From a4b7ed7a42c716ab9f05e351f003d589124fd55d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:58 +0200 Subject: Adding upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/ui/abi/abi-sysv64-arg-passing.rs | 448 + tests/ui/abi/abi-sysv64-register-usage.rs | 107 + tests/ui/abi/abi-typo-unstable.rs | 6 + tests/ui/abi/abi-typo-unstable.stderr | 11 + tests/ui/abi/anon-extern-mod.rs | 18 + tests/ui/abi/c-stack-as-value.rs | 18 + tests/ui/abi/c-stack-returning-int64.rs | 36 + tests/ui/abi/cabi-int-widening.rs | 15 + .../cross-crate/anon-extern-mod-cross-crate-2.rs | 14 + .../auxiliary/anon-extern-mod-cross-crate-1.rs | 9 + .../ui/abi/cross-crate/duplicated-external-mods.rs | 9 + .../extern/auxiliary/extern-crosscrate-source.rs | 28 + tests/ui/abi/extern/extern-call-deep.rs | 36 + tests/ui/abi/extern/extern-call-deep2.rs | 41 + tests/ui/abi/extern/extern-call-direct.rs | 10 + tests/ui/abi/extern/extern-call-indirect.rs | 35 + tests/ui/abi/extern/extern-call-scrub.rs | 45 + tests/ui/abi/extern/extern-crosscrate.rs | 21 + tests/ui/abi/extern/extern-pass-TwoU16s.rs | 26 + tests/ui/abi/extern/extern-pass-TwoU32s.rs | 26 + tests/ui/abi/extern/extern-pass-TwoU64s.rs | 26 + tests/ui/abi/extern/extern-pass-TwoU8s.rs | 26 + tests/ui/abi/extern/extern-pass-char.rs | 15 + tests/ui/abi/extern/extern-pass-double.rs | 13 + tests/ui/abi/extern/extern-pass-empty.rs | 55 + tests/ui/abi/extern/extern-pass-u32.rs | 15 + tests/ui/abi/extern/extern-pass-u64.rs | 15 + tests/ui/abi/extern/extern-return-TwoU16s.rs | 22 + tests/ui/abi/extern/extern-return-TwoU32s.rs | 22 + tests/ui/abi/extern/extern-return-TwoU64s.rs | 22 + tests/ui/abi/extern/extern-return-TwoU8s.rs | 22 + tests/ui/abi/foreign/auxiliary/foreign_lib.rs | 37 + tests/ui/abi/foreign/foreign-call-no-runtime.rs | 60 + tests/ui/abi/foreign/foreign-dupe.rs | 17 + tests/ui/abi/foreign/foreign-fn-with-byval.rs | 30 + tests/ui/abi/foreign/foreign-no-abi.rs | 22 + tests/ui/abi/foreign/invoke-external-foreign.rs | 17 + .../abi/homogenous-floats-target-feature-mixup.rs | 192 + tests/ui/abi/issue-28676.rs | 40 + tests/ui/abi/issues/issue-22565-rust-call.rs | 31 + tests/ui/abi/issues/issue-22565-rust-call.stderr | 33 + .../abi/issues/issue-62350-sysv-neg-reg-counts.rs | 46 + .../issue-97463-broken-abi-leaked-uninit-data.rs | 39 + tests/ui/abi/lib-defaults.rs | 17 + tests/ui/abi/mir/mir_codegen_calls_variadic.rs | 19 + tests/ui/abi/nullable-pointer-ffi-compat.rs | 28 + tests/ui/abi/numbers-arithmetic/i128-ffi.rs | 31 + tests/ui/abi/rustcall-generic.rs | 12 + tests/ui/abi/segfault-no-out-of-stack.rs | 48 + tests/ui/abi/stack-probes-lto.rs | 17 + tests/ui/abi/stack-probes.rs | 85 + tests/ui/abi/stack-protector.rs | 99 + tests/ui/abi/statics/static-mut-foreign.rs | 41 + tests/ui/abi/struct-enums/struct-return.rs | 122 + tests/ui/abi/union/union-c-interop.rs | 37 + tests/ui/abi/unsupported.aarch64.stderr | 61 + tests/ui/abi/unsupported.arm.stderr | 55 + tests/ui/abi/unsupported.i686.stderr | 39 + tests/ui/abi/unsupported.rs | 53 + tests/ui/abi/unsupported.x64.stderr | 55 + tests/ui/abi/variadic-ffi.rs | 84 + tests/ui/abi/x86stdcall.rs | 22 + tests/ui/abi/x86stdcall2.rs | 27 + tests/ui/alias-uninit-value.rs | 20 + .../alloc-error-handler-bad-signature-1.rs | 18 + .../alloc-error-handler-bad-signature-1.stderr | 44 + .../alloc-error-handler-bad-signature-2.rs | 17 + .../alloc-error-handler-bad-signature-2.stderr | 50 + .../alloc-error-handler-bad-signature-3.rs | 15 + .../alloc-error-handler-bad-signature-3.stderr | 25 + tests/ui/alloc-error/default-alloc-error-hook.rs | 28 + tests/ui/allocator/allocator-args.rs | 13 + tests/ui/allocator/allocator-args.stderr | 8 + tests/ui/allocator/auxiliary/custom-as-global.rs | 16 + tests/ui/allocator/auxiliary/custom.rs | 21 + tests/ui/allocator/auxiliary/helper.rs | 11 + tests/ui/allocator/auxiliary/system-allocator.rs | 8 + tests/ui/allocator/auxiliary/system-allocator2.rs | 8 + tests/ui/allocator/custom-in-block.rs | 22 + tests/ui/allocator/custom-in-submodule.rs | 26 + tests/ui/allocator/custom.rs | 59 + tests/ui/allocator/function-allocator.rs | 4 + tests/ui/allocator/function-allocator.stderr | 8 + tests/ui/allocator/hygiene.rs | 31 + .../allocator/no_std-alloc-error-handler-custom.rs | 84 + .../no_std-alloc-error-handler-default.rs | 71 + tests/ui/allocator/not-an-allocator.rs | 8 + tests/ui/allocator/not-an-allocator.stderr | 47 + tests/ui/allocator/object-safe.rs | 13 + tests/ui/allocator/two-allocators.rs | 9 + tests/ui/allocator/two-allocators.stderr | 14 + tests/ui/allocator/two-allocators2.rs | 12 + tests/ui/allocator/two-allocators2.stderr | 4 + tests/ui/allocator/two-allocators3.rs | 10 + tests/ui/allocator/two-allocators3.stderr | 4 + tests/ui/allocator/xcrate-use.rs | 36 + tests/ui/allocator/xcrate-use2.rs | 47 + tests/ui/annotate-snippet/auxiliary/multispan.rs | 37 + tests/ui/annotate-snippet/missing-type.rs | 5 + tests/ui/annotate-snippet/missing-type.stderr | 6 + tests/ui/annotate-snippet/multispan.rs | 28 + tests/ui/annotate-snippet/multispan.stderr | 42 + tests/ui/anon-params/anon-params-denied-2018.rs | 32 + .../ui/anon-params/anon-params-denied-2018.stderr | 142 + tests/ui/anon-params/anon-params-deprecated.fixed | 19 + tests/ui/anon-params/anon-params-deprecated.rs | 19 + tests/ui/anon-params/anon-params-deprecated.stderr | 34 + .../ui/anon-params/anon-params-edition-hygiene.rs | 13 + .../auxiliary/anon-params-edition-hygiene.rs | 12 + tests/ui/anonymous-higher-ranked-lifetime.rs | 30 + tests/ui/anonymous-higher-ranked-lifetime.stderr | 223 + tests/ui/argument-suggestions/basic.rs | 28 + tests/ui/argument-suggestions/basic.stderr | 103 + tests/ui/argument-suggestions/complex.rs | 16 + tests/ui/argument-suggestions/complex.stderr | 19 + .../argument-suggestions/display-is-suggestable.rs | 8 + .../display-is-suggestable.stderr | 19 + tests/ui/argument-suggestions/exotic-calls.rs | 26 + tests/ui/argument-suggestions/exotic-calls.stderr | 67 + .../ui/argument-suggestions/extern-fn-arg-names.rs | 9 + .../extern-fn-arg-names.stderr | 26 + tests/ui/argument-suggestions/extra_arguments.rs | 35 + .../ui/argument-suggestions/extra_arguments.stderr | 239 + .../formal-and-expected-differ.rs | 25 + .../formal-and-expected-differ.stderr | 30 + tests/ui/argument-suggestions/invalid_arguments.rs | 43 + .../argument-suggestions/invalid_arguments.stderr | 299 + tests/ui/argument-suggestions/issue-100154.rs | 7 + tests/ui/argument-suggestions/issue-100154.stderr | 35 + tests/ui/argument-suggestions/issue-100478.rs | 52 + tests/ui/argument-suggestions/issue-100478.stderr | 81 + tests/ui/argument-suggestions/issue-101097.rs | 21 + tests/ui/argument-suggestions/issue-101097.stderr | 160 + tests/ui/argument-suggestions/issue-96638.rs | 9 + tests/ui/argument-suggestions/issue-96638.stderr | 21 + tests/ui/argument-suggestions/issue-97197.rs | 6 + tests/ui/argument-suggestions/issue-97197.stderr | 19 + tests/ui/argument-suggestions/issue-97484.rs | 14 + tests/ui/argument-suggestions/issue-97484.stderr | 27 + tests/ui/argument-suggestions/issue-98894.rs | 4 + tests/ui/argument-suggestions/issue-98894.stderr | 19 + tests/ui/argument-suggestions/issue-98897.rs | 4 + tests/ui/argument-suggestions/issue-98897.stderr | 19 + tests/ui/argument-suggestions/issue-99482.rs | 5 + tests/ui/argument-suggestions/issue-99482.stderr | 19 + tests/ui/argument-suggestions/missing_arguments.rs | 40 + .../argument-suggestions/missing_arguments.stderr | 310 + tests/ui/argument-suggestions/mixed_cases.rs | 24 + tests/ui/argument-suggestions/mixed_cases.stderr | 117 + .../ui/argument-suggestions/permuted_arguments.rs | 13 + .../argument-suggestions/permuted_arguments.stderr | 43 + tests/ui/argument-suggestions/swapped_arguments.rs | 14 + .../argument-suggestions/swapped_arguments.stderr | 95 + tests/ui/argument-suggestions/too-long.rs | 41 + tests/ui/argument-suggestions/too-long.stderr | 24 + .../ui/argument-suggestions/two-mismatch-notes.rs | 11 + .../argument-suggestions/two-mismatch-notes.stderr | 29 + tests/ui/array-slice-vec/array-break-length.rs | 9 + tests/ui/array-slice-vec/array-break-length.stderr | 15 + tests/ui/array-slice-vec/array-not-vector.rs | 12 + tests/ui/array-slice-vec/array-not-vector.stderr | 22 + tests/ui/array-slice-vec/array_const_index-0.rs | 8 + .../ui/array-slice-vec/array_const_index-0.stderr | 9 + tests/ui/array-slice-vec/array_const_index-1.rs | 8 + .../ui/array-slice-vec/array_const_index-1.stderr | 9 + tests/ui/array-slice-vec/array_const_index-2.rs | 12 + .../ui/array-slice-vec/bounds-check-no-overflow.rs | 10 + tests/ui/array-slice-vec/box-of-array-of-drop-1.rs | 53 + tests/ui/array-slice-vec/box-of-array-of-drop-2.rs | 53 + tests/ui/array-slice-vec/byte-literals.rs | 67 + tests/ui/array-slice-vec/cast-in-array-size.rs | 14 + .../ui/array-slice-vec/check-static-mut-slices.rs | 15 + tests/ui/array-slice-vec/check-static-slice.rs | 36 + tests/ui/array-slice-vec/copy-out-of-array-1.rs | 19 + tests/ui/array-slice-vec/destructure-array-1.rs | 27 + tests/ui/array-slice-vec/dst-raw-slice.rs | 13 + tests/ui/array-slice-vec/empty-mutable-vec.rs | 8 + tests/ui/array-slice-vec/estr-slice.rs | 50 + tests/ui/array-slice-vec/evec-slice.rs | 47 + tests/ui/array-slice-vec/fixed_length_copy.rs | 9 + tests/ui/array-slice-vec/huge-largest-array.rs | 14 + tests/ui/array-slice-vec/infer_array_len.rs | 21 + tests/ui/array-slice-vec/infer_array_len.stderr | 14 + tests/ui/array-slice-vec/issue-15730.rs | 9 + tests/ui/array-slice-vec/issue-18425.rs | 9 + .../issue-69103-extra-binding-subslice.rs | 18 + .../issue-69103-extra-binding-subslice.stderr | 26 + tests/ui/array-slice-vec/ivec-pass-by-value.rs | 4 + tests/ui/array-slice-vec/match_arr_unknown_len.rs | 8 + .../array-slice-vec/match_arr_unknown_len.stderr | 12 + tests/ui/array-slice-vec/mut-vstore-expr.rs | 6 + ...mutability-inherits-through-fixed-length-vec.rs | 19 + tests/ui/array-slice-vec/mutable-alias-vec.rs | 15 + tests/ui/array-slice-vec/nested-vec-1.rs | 8 + tests/ui/array-slice-vec/nested-vec-2.rs | 15 + tests/ui/array-slice-vec/nested-vec-3.rs | 60 + .../array-slice-vec/new-style-fixed-length-vec.rs | 7 + tests/ui/array-slice-vec/rcvr-borrowed-to-slice.rs | 33 + tests/ui/array-slice-vec/repeat_empty_ok.rs | 15 + tests/ui/array-slice-vec/repeat_empty_ok.stderr | 27 + tests/ui/array-slice-vec/repeated-vector-syntax.rs | 13 + tests/ui/array-slice-vec/show-boxed-slice.rs | 8 + tests/ui/array-slice-vec/slice-2.rs | 11 + tests/ui/array-slice-vec/slice-2.stderr | 27 + tests/ui/array-slice-vec/slice-mut-2.rs | 8 + tests/ui/array-slice-vec/slice-mut-2.stderr | 14 + tests/ui/array-slice-vec/slice-mut.rs | 12 + tests/ui/array-slice-vec/slice-mut.stderr | 14 + .../array-slice-vec/slice-of-zero-size-elements.rs | 53 + tests/ui/array-slice-vec/slice-panic-1.rs | 27 + tests/ui/array-slice-vec/slice-panic-2.rs | 31 + .../array-slice-vec/slice-pat-type-mismatches.rs | 36 + .../slice-pat-type-mismatches.stderr | 34 + .../ui/array-slice-vec/slice-to-vec-comparison.rs | 6 + .../array-slice-vec/slice-to-vec-comparison.stderr | 12 + tests/ui/array-slice-vec/slice.rs | 81 + tests/ui/array-slice-vec/slice_binary_search.rs | 22 + .../array-slice-vec/slice_is_sorted_by_borrow.rs | 20 + .../subslice-only-once-semantic-restriction.rs | 11 + .../subslice-only-once-semantic-restriction.stderr | 24 + .../subslice-patterns-const-eval-match.rs | 96 + .../subslice-patterns-const-eval.rs | 95 + .../ui/array-slice-vec/suggest-array-length.fixed | 26 + tests/ui/array-slice-vec/suggest-array-length.rs | 26 + .../ui/array-slice-vec/suggest-array-length.stderr | 108 + tests/ui/array-slice-vec/variance-vec-covariant.rs | 20 + tests/ui/array-slice-vec/vec-dst.rs | 24 + tests/ui/array-slice-vec/vec-fixed-length.rs | 24 + tests/ui/array-slice-vec/vec-late-init.rs | 9 + tests/ui/array-slice-vec/vec-macro-no-std.rs | 27 + tests/ui/array-slice-vec/vec-macro-rvalue-scope.rs | 11 + .../ui/array-slice-vec/vec-macro-with-brackets.rs | 16 + .../array-slice-vec/vec-macro-with-comma-only.rs | 3 + .../vec-macro-with-comma-only.stderr | 10 + .../vec-macro-with-trailing-comma.rs | 8 + tests/ui/array-slice-vec/vec-matching-autoslice.rs | 23 + tests/ui/array-slice-vec/vec-matching-fixed.rs | 30 + tests/ui/array-slice-vec/vec-matching-fold.rs | 46 + .../vec-matching-legal-tail-element-borrow.rs | 15 + tests/ui/array-slice-vec/vec-matching.rs | 142 + tests/ui/array-slice-vec/vec-mut-iter-borrow.rs | 7 + .../ui/array-slice-vec/vec-mut-iter-borrow.stderr | 14 + tests/ui/array-slice-vec/vec-overrun.rs | 12 + tests/ui/array-slice-vec/vec-repeat-with-cast.rs | 5 + tests/ui/array-slice-vec/vec-res-add.rs | 19 + tests/ui/array-slice-vec/vec-res-add.stderr | 11 + tests/ui/array-slice-vec/vec-tail-matching.rs | 34 + tests/ui/array-slice-vec/vector-cast-weirdness.rs | 34 + .../array-slice-vec/vector-cast-weirdness.stderr | 21 + tests/ui/array-slice-vec/vector-no-ann-2.rs | 7 + tests/ui/array-slice-vec/vector-no-ann.rs | 4 + tests/ui/array-slice-vec/vector-no-ann.stderr | 14 + tests/ui/artificial-block.rs | 5 + tests/ui/as-precedence.rs | 10 + tests/ui/asm/aarch64/bad-options.rs | 39 + tests/ui/asm/aarch64/bad-options.stderr | 84 + tests/ui/asm/aarch64/bad-reg.rs | 61 + tests/ui/asm/aarch64/bad-reg.stderr | 162 + tests/ui/asm/aarch64/const.rs | 44 + tests/ui/asm/aarch64/duplicate-options.fixed | 27 + tests/ui/asm/aarch64/duplicate-options.rs | 27 + tests/ui/asm/aarch64/duplicate-options.stderr | 56 + tests/ui/asm/aarch64/interpolated-idents.rs | 24 + tests/ui/asm/aarch64/interpolated-idents.stderr | 46 + tests/ui/asm/aarch64/llvm-58384.rs | 16 + tests/ui/asm/aarch64/may_unwind.rs | 37 + tests/ui/asm/aarch64/parse-error.rs | 133 + tests/ui/asm/aarch64/parse-error.stderr | 446 + tests/ui/asm/aarch64/srcloc.rs | 129 + tests/ui/asm/aarch64/srcloc.stderr | 290 + tests/ui/asm/aarch64/sym.rs | 84 + tests/ui/asm/aarch64/type-check-2-2.rs | 35 + tests/ui/asm/aarch64/type-check-2-2.stderr | 46 + tests/ui/asm/aarch64/type-check-2.rs | 76 + tests/ui/asm/aarch64/type-check-2.stderr | 75 + tests/ui/asm/aarch64/type-check-3.rs | 97 + tests/ui/asm/aarch64/type-check-3.stderr | 147 + tests/ui/asm/aarch64/type-check-4.rs | 32 + tests/ui/asm/aarch64/type-check-4.stderr | 27 + tests/ui/asm/bad-arch.mirunsafeck.stderr | 17 + tests/ui/asm/bad-arch.rs | 28 + tests/ui/asm/bad-arch.thirunsafeck.stderr | 17 + .../ui/asm/bad-template.aarch64_mirunsafeck.stderr | 197 + .../asm/bad-template.aarch64_thirunsafeck.stderr | 197 + tests/ui/asm/bad-template.rs | 75 + .../ui/asm/bad-template.x86_64_mirunsafeck.stderr | 197 + .../ui/asm/bad-template.x86_64_thirunsafeck.stderr | 197 + tests/ui/asm/generic-const.rs | 30 + tests/ui/asm/inline-syntax.arm.stderr | 88 + tests/ui/asm/inline-syntax.rs | 60 + tests/ui/asm/inline-syntax.x86_64.stderr | 46 + tests/ui/asm/issue-72570.rs | 12 + tests/ui/asm/issue-72570.stderr | 8 + tests/ui/asm/issue-85247.rs | 26 + tests/ui/asm/issue-85247.rwpi.stderr | 8 + tests/ui/asm/issue-87802.rs | 20 + tests/ui/asm/issue-87802.stderr | 10 + tests/ui/asm/issue-89305.rs | 16 + tests/ui/asm/issue-89305.stderr | 15 + tests/ui/asm/issue-92378.rs | 31 + tests/ui/asm/issue-97490.rs | 12 + tests/ui/asm/issue-99071.rs | 21 + tests/ui/asm/issue-99071.stderr | 8 + tests/ui/asm/issue-99122-2.rs | 21 + tests/ui/asm/issue-99122.rs | 13 + tests/ui/asm/issue-99122.stderr | 11 + tests/ui/asm/may_unwind.rs | 10 + tests/ui/asm/naked-functions-ffi.rs | 15 + tests/ui/asm/naked-functions-ffi.stderr | 20 + tests/ui/asm/naked-functions-unused.aarch64.stderr | 69 + tests/ui/asm/naked-functions-unused.rs | 87 + tests/ui/asm/naked-functions-unused.x86_64.stderr | 69 + tests/ui/asm/naked-functions.rs | 218 + tests/ui/asm/naked-functions.stderr | 290 + tests/ui/asm/naked-invalid-attr.rs | 52 + tests/ui/asm/naked-invalid-attr.stderr | 42 + tests/ui/asm/named-asm-labels.rs | 196 + tests/ui/asm/named-asm-labels.s | 5 + tests/ui/asm/named-asm-labels.stderr | 334 + tests/ui/asm/noreturn.rs | 19 + tests/ui/asm/reg-conflict.rs | 20 + tests/ui/asm/reg-conflict.stderr | 10 + tests/ui/asm/type-check-1.rs | 79 + tests/ui/asm/type-check-1.stderr | 144 + tests/ui/asm/type-check-4.rs | 26 + tests/ui/asm/type-check-4.stderr | 26 + tests/ui/asm/unpretty-expanded.rs | 4 + tests/ui/asm/unpretty-expanded.stdout | 10 + tests/ui/asm/x86_64/bad-clobber-abi.rs | 32 + tests/ui/asm/x86_64/bad-clobber-abi.stderr | 88 + tests/ui/asm/x86_64/bad-options.rs | 42 + tests/ui/asm/x86_64/bad-options.stderr | 101 + tests/ui/asm/x86_64/bad-reg.rs | 72 + tests/ui/asm/x86_64/bad-reg.stderr | 218 + tests/ui/asm/x86_64/const.rs | 44 + tests/ui/asm/x86_64/duplicate-options.fixed | 29 + tests/ui/asm/x86_64/duplicate-options.rs | 29 + tests/ui/asm/x86_64/duplicate-options.stderr | 62 + tests/ui/asm/x86_64/interpolated-idents.rs | 24 + tests/ui/asm/x86_64/interpolated-idents.stderr | 46 + tests/ui/asm/x86_64/issue-82869.rs | 25 + tests/ui/asm/x86_64/issue-82869.stderr | 24 + tests/ui/asm/x86_64/issue-89875.rs | 17 + tests/ui/asm/x86_64/issue-96797.rs | 24 + tests/ui/asm/x86_64/may_unwind.rs | 38 + tests/ui/asm/x86_64/multiple-clobber-abi.rs | 33 + tests/ui/asm/x86_64/parse-error.rs | 137 + tests/ui/asm/x86_64/parse-error.stderr | 458 + tests/ui/asm/x86_64/srcloc.rs | 131 + tests/ui/asm/x86_64/srcloc.stderr | 302 + tests/ui/asm/x86_64/sym.rs | 84 + tests/ui/asm/x86_64/target-feature-attr.rs | 42 + tests/ui/asm/x86_64/target-feature-attr.stderr | 26 + tests/ui/asm/x86_64/type-check-2.rs | 87 + tests/ui/asm/x86_64/type-check-2.stderr | 83 + tests/ui/asm/x86_64/type-check-3.rs | 73 + tests/ui/asm/x86_64/type-check-3.stderr | 118 + tests/ui/asm/x86_64/type-check-4.rs | 28 + tests/ui/asm/x86_64/type-check-4.stderr | 27 + tests/ui/asm/x86_64/type-check-5.rs | 62 + tests/ui/asm/x86_64/type-check-5.stderr | 46 + tests/ui/assign-assign.rs | 30 + tests/ui/assign-imm-local-twice.rs | 13 + tests/ui/assign-imm-local-twice.stderr | 15 + tests/ui/assoc-lang-items.rs | 21 + tests/ui/assoc-lang-items.stderr | 27 + tests/ui/assoc-oddities-3.rs | 13 + .../ui/associated-consts/assoc-const-eq-missing.rs | 26 + .../assoc-const-eq-missing.stderr | 21 + .../associated-consts/assoc-const-ty-mismatch.rs | 31 + .../assoc-const-ty-mismatch.stderr | 26 + tests/ui/associated-consts/assoc-const.rs | 22 + .../associated-const-ambiguity-report.rs | 21 + .../associated-const-ambiguity-report.stderr | 28 + .../associated-const-array-len.rs | 10 + .../associated-const-array-len.stderr | 9 + .../associated-const-const-eval.rs | 20 + .../associated-const-cross-crate-const-eval.rs | 28 + .../associated-const-cross-crate-defaults.rs | 22 + .../associated-const-cross-crate.rs | 17 + .../associated-const-dead-code.rs | 12 + .../associated-const-dead-code.stderr | 14 + .../associated-const-generic-obligations.rs | 18 + .../associated-const-generic-obligations.stderr | 17 + .../associated-const-impl-wrong-lifetime.rs | 11 + .../associated-const-impl-wrong-lifetime.stderr | 18 + .../associated-const-impl-wrong-type.rs | 12 + .../associated-const-impl-wrong-type.stderr | 15 + .../associated-const-in-global-const.rs | 13 + .../associated-consts/associated-const-in-trait.rs | 12 + .../associated-const-in-trait.stderr | 18 + .../associated-const-inherent-impl.rs | 11 + .../associated-const-marks-live-code.rs | 15 + .../associated-const-match-patterns.rs | 68 + .../associated-consts/associated-const-no-item.rs | 10 + .../associated-const-no-item.stderr | 16 + .../associated-const-outer-ty-refs.rs | 10 + .../associated-const-overwrite-default.rs | 13 + .../associated-const-private-impl.rs | 15 + .../associated-const-private-impl.stderr | 12 + .../associated-const-public-impl.rs | 16 + .../associated-const-range-match-patterns.rs | 40 + .../associated-const-resolution-order.rs | 25 + .../associated-const-self-type.rs | 13 + .../associated-const-trait-bound.rs | 21 + .../associated-const-type-parameter-arms.rs | 29 + .../associated-const-type-parameter-arms.stderr | 15 + .../associated-const-type-parameter-arrays-2.rs | 21 + ...associated-const-type-parameter-arrays-2.stderr | 10 + .../associated-const-type-parameter-arrays.rs | 20 + .../associated-const-type-parameter-arrays.stderr | 11 + .../associated-const-type-parameters.rs | 44 + .../associated-const-ufcs-infer-trait.rs | 13 + .../associated-const-use-default.rs | 11 + .../associated-const-use-impl-of-same-trait.rs | 25 + tests/ui/associated-consts/associated-const.rs | 13 + .../auxiliary/associated-const-cc-lib.rs | 34 + .../ui/associated-consts/auxiliary/empty-struct.rs | 9 + tests/ui/associated-consts/defaults-cyclic-fail.rs | 17 + .../associated-consts/defaults-cyclic-fail.stderr | 21 + tests/ui/associated-consts/defaults-cyclic-pass.rs | 36 + .../associated-consts/defaults-not-assumed-fail.rs | 44 + .../defaults-not-assumed-fail.stderr | 39 + .../associated-consts/defaults-not-assumed-pass.rs | 42 + tests/ui/associated-consts/issue-102335-const.rs | 12 + .../ui/associated-consts/issue-102335-const.stderr | 9 + tests/ui/associated-consts/issue-105330.rs | 21 + tests/ui/associated-consts/issue-105330.stderr | 113 + ...ssue-24949-assoc-const-static-recursion-impl.rs | 15 + ...-24949-assoc-const-static-recursion-impl.stderr | 32 + ...9-assoc-const-static-recursion-trait-default.rs | 17 + ...soc-const-static-recursion-trait-default.stderr | 32 + ...sue-24949-assoc-const-static-recursion-trait.rs | 15 + ...24949-assoc-const-static-recursion-trait.stderr | 32 + tests/ui/associated-consts/issue-47814.rs | 14 + tests/ui/associated-consts/issue-47814.stderr | 14 + tests/ui/associated-consts/issue-58022.rs | 19 + tests/ui/associated-consts/issue-58022.stderr | 19 + tests/ui/associated-consts/issue-63496.rs | 9 + tests/ui/associated-consts/issue-63496.stderr | 21 + ...e-69020-assoc-const-arith-overflow.noopt.stderr | 54 + ...sue-69020-assoc-const-arith-overflow.opt.stderr | 54 + ...-arith-overflow.opt_with_overflow_checks.stderr | 54 + .../issue-69020-assoc-const-arith-overflow.rs | 46 + tests/ui/associated-consts/issue-88599-ref-self.rs | 24 + tests/ui/associated-consts/issue-93775.rs | 29 + tests/ui/associated-consts/issue-93835.rs | 12 + tests/ui/associated-consts/issue-93835.stderr | 40 + tests/ui/associated-consts/mismatched_impl_ty_1.rs | 18 + tests/ui/associated-consts/mismatched_impl_ty_2.rs | 11 + tests/ui/associated-consts/mismatched_impl_ty_3.rs | 11 + tests/ui/associated-consts/shadowed-const.rs | 23 + tests/ui/associated-consts/shadowed-const.stderr | 8 + .../assoc-inherent-no-body.rs | 10 + .../assoc-inherent-no-body.stderr | 10 + .../assoc-inherent-private.rs | 23 + .../assoc-inherent-private.stderr | 21 + .../assoc-inherent-unstable.rs | 6 + .../assoc-inherent-unstable.stderr | 11 + .../assoc-inherent-use.rs | 14 + .../auxiliary/assoc-inherent-unstable.rs | 11 + tests/ui/associated-inherent-types/issue-104260.rs | 14 + .../normalize-projection-0.rs | 22 + .../normalize-projection-1.rs | 22 + .../associated-inherent-types/struct-generics.rs | 15 + tests/ui/associated-inherent-types/style.rs | 12 + tests/ui/associated-inherent-types/style.stderr | 14 + .../ambiguous-associated-type-with-generics.fixed | 14 + .../ambiguous-associated-type-with-generics.rs | 14 + .../ambiguous-associated-type-with-generics.stderr | 9 + .../associated-item-duplicate-bounds.rs | 11 + .../associated-item-duplicate-bounds.stderr | 11 + .../associated-item-duplicate-names-2.rs | 8 + .../associated-item-duplicate-names-2.stderr | 11 + .../associated-item-duplicate-names-3.rs | 20 + .../associated-item-duplicate-names-3.stderr | 21 + .../associated-item-duplicate-names.rs | 19 + .../associated-item-duplicate-names.stderr | 25 + tests/ui/associated-item/associated-item-enum.rs | 20 + .../ui/associated-item/associated-item-enum.stderr | 39 + .../associated-item/associated-item-two-bounds.rs | 16 + tests/ui/associated-item/impl-duplicate-methods.rs | 9 + .../associated-item/impl-duplicate-methods.stderr | 11 + tests/ui/associated-item/issue-105449.rs | 59 + tests/ui/associated-item/issue-48027.rs | 8 + tests/ui/associated-item/issue-48027.stderr | 27 + tests/ui/associated-item/issue-87638.fixed | 22 + tests/ui/associated-item/issue-87638.rs | 22 + tests/ui/associated-item/issue-87638.stderr | 27 + tests/ui/associated-path-shl.rs | 9 + tests/ui/associated-path-shl.stderr | 33 + .../ambiguous-associated-type.rs | 12 + .../ambiguous-associated-type2.rs | 10 + .../ambiguous-associated-type2.stderr | 16 + .../assoc-type-bound-through-where-clause.rs | 16 + .../assoc-type-eq-with-dyn-atb-fail.rs | 36 + .../assoc-type-eq-with-dyn-atb-fail.stderr | 9 + .../associated-item-through-where-clause.rs | 21 + .../ui/associated-type-bounds/auxiliary/fn-aux.rs | 177 + .../associated-type-bounds/auxiliary/fn-dyn-aux.rs | 182 + .../bad-bounds-on-assoc-in-trait.rs | 67 + .../bad-bounds-on-assoc-in-trait.stderr | 39 + tests/ui/associated-type-bounds/binder-on-bound.rs | 9 + .../associated-type-bounds/binder-on-bound.stderr | 8 + .../bounds-on-assoc-in-trait.rs | 54 + .../bounds-on-assoc-in-trait.stderr | 26 + .../const-projection-err.gce.stderr | 24 + .../associated-type-bounds/const-projection-err.rs | 18 + .../const-projection-err.stock.stderr | 17 + tests/ui/associated-type-bounds/duplicate.rs | 259 + tests/ui/associated-type-bounds/duplicate.stderr | 507 + .../associated-type-bounds/dyn-impl-trait-type.rs | 66 + .../ui/associated-type-bounds/dyn-rpit-and-let.rs | 73 + tests/ui/associated-type-bounds/elision.rs | 9 + tests/ui/associated-type-bounds/elision.stderr | 28 + .../entails-sized-object-safety.rs | 26 + tests/ui/associated-type-bounds/enum-bounds.rs | 123 + tests/ui/associated-type-bounds/fn-apit.rs | 59 + tests/ui/associated-type-bounds/fn-aux.rs | 12 + tests/ui/associated-type-bounds/fn-dyn-apit.rs | 61 + tests/ui/associated-type-bounds/fn-inline.rs | 63 + tests/ui/associated-type-bounds/fn-where.rs | 79 + tests/ui/associated-type-bounds/fn-wrap-apit.rs | 65 + ...handle-predicates-that-can-define-assoc-type.rs | 10 + tests/ui/associated-type-bounds/hrtb.rs | 65 + .../implied-region-constraints.rs | 45 + .../implied-region-constraints.stderr | 28 + tests/ui/associated-type-bounds/inside-adt.rs | 30 + tests/ui/associated-type-bounds/inside-adt.stderr | 131 + tests/ui/associated-type-bounds/issue-102335-ty.rs | 12 + .../associated-type-bounds/issue-102335-ty.stderr | 9 + tests/ui/associated-type-bounds/issue-61752.rs | 24 + tests/ui/associated-type-bounds/issue-70292.rs | 21 + tests/ui/associated-type-bounds/issue-71443-1.rs | 9 + .../ui/associated-type-bounds/issue-71443-1.stderr | 11 + tests/ui/associated-type-bounds/issue-71443-2.rs | 11 + tests/ui/associated-type-bounds/issue-73818.rs | 25 + tests/ui/associated-type-bounds/issue-79949.rs | 25 + tests/ui/associated-type-bounds/issue-81193.rs | 15 + tests/ui/associated-type-bounds/issue-83017.rs | 39 + tests/ui/associated-type-bounds/issue-99828.rs | 11 + tests/ui/associated-type-bounds/issue-99828.stderr | 21 + .../missing-trait-bound-for-assoc-fails.rs | 10 + .../missing-trait-bound-for-assoc-fails.stderr | 16 + .../order-dependent-bounds-issue-54121.rs | 47 + tests/ui/associated-type-bounds/rpit.rs | 64 + tests/ui/associated-type-bounds/struct-bounds.rs | 116 + .../supertrait-referencing-self.rs | 12 + .../supertrait-referencing.rs | 19 + .../supertrait-where-referencing-self.rs | 27 + .../trait-alias-impl-trait.rs | 96 + tests/ui/associated-type-bounds/trait-params.rs | 116 + .../traits-assoc-anonymized.rs | 33 + .../traits-assoc-type-macros.rs | 43 + tests/ui/associated-type-bounds/type-alias.rs | 19 + tests/ui/associated-type-bounds/type-alias.stderr | 147 + tests/ui/associated-type-bounds/union-bounds.rs | 123 + .../associate-type-bound-normalization.rs | 25 + .../associated-types/associated-item-long-paths.rs | 47 + .../associated-type-destructuring-assignment.rs | 10 + tests/ui/associated-types/associated-type-macro.rs | 4 + .../associated-types/associated-type-macro.stderr | 8 + ...jection-ambig-between-bound-and-where-clause.rs | 42 + ...ion-ambig-between-bound-and-where-clause.stderr | 129 + ...ed-type-projection-from-multiple-supertraits.rs | 43 + ...ype-projection-from-multiple-supertraits.stderr | 100 + .../associated-type-projection-from-supertrait.rs | 36 + ...sociated-type-projection-from-supertrait.stderr | 59 + .../associated-type-struct-construction.rs | 24 + .../associated-type-tuple-struct-construction.rs | 24 + ...ssociated-type-tuple-struct-construction.stderr | 19 + ...ociated-types-ICE-when-projecting-out-of-err.rs | 25 + ...ted-types-ICE-when-projecting-out-of-err.stderr | 9 + .../ui/associated-types/associated-types-basic.rs | 14 + .../associated-types-binding-in-trait.rs | 36 + .../associated-types-binding-in-where-clause.rs | 38 + ...-types-binding-to-type-defined-in-supertrait.rs | 35 + ...es-binding-to-type-defined-in-supertrait.stderr | 41 + .../associated-types-bound-ambiguity.rs | 23 + .../associated-types-bound-failure.fixed | 29 + .../associated-types-bound-failure.rs | 29 + .../associated-types-bound-failure.stderr | 16 + .../ui/associated-types/associated-types-bound.rs | 43 + tests/ui/associated-types/associated-types-cc.rs | 18 + .../associated-types-coherence-failure.rs | 49 + .../associated-types-coherence-failure.stderr | 21 + .../associated-types-conditional-dispatch.rs | 66 + .../associated-types-constant-type.rs | 31 + .../associated-types-doubleendediterator-object.rs | 19 + ...sociated-types-duplicate-binding-in-env-hrtb.rs | 17 + .../associated-types-duplicate-binding-in-env.rs | 21 + .../associated-types-enum-field-named.rs | 35 + .../associated-types-enum-field-numbered.rs | 35 + tests/ui/associated-types/associated-types-eq-1.rs | 13 + .../associated-types/associated-types-eq-1.stderr | 20 + tests/ui/associated-types/associated-types-eq-2.rs | 19 + .../associated-types/associated-types-eq-2.stderr | 9 + tests/ui/associated-types/associated-types-eq-3.rs | 42 + .../associated-types/associated-types-eq-3.stderr | 51 + .../associated-types-eq-expr-path.rs | 16 + .../associated-types-eq-expr-path.stderr | 9 + .../ui/associated-types/associated-types-eq-hr.rs | 111 + .../associated-types/associated-types-eq-hr.stderr | 47 + .../ui/associated-types/associated-types-eq-obj.rs | 25 + .../associated-types-for-unimpl-trait.fixed | 15 + .../associated-types-for-unimpl-trait.rs | 15 + .../associated-types-for-unimpl-trait.stderr | 14 + .../associated-types-from-supertrait.rs | 8 + .../associated-types-impl-redirect.rs | 51 + .../associated-types-in-ambiguous-context.rs | 29 + .../associated-types-in-ambiguous-context.stderr | 48 + .../associated-types-in-bound-type-arg.rs | 17 + .../associated-types-in-default-method.rs | 27 + .../ui/associated-types/associated-types-in-fn.rs | 28 + .../associated-types-in-impl-generics.rs | 36 + .../associated-types-in-inherent-method.rs | 30 + .../associated-types-incomplete-object.rs | 31 + .../associated-types-incomplete-object.stderr | 32 + ...sociated-types-invalid-trait-ref-issue-18865.rs | 14 + ...ated-types-invalid-trait-ref-issue-18865.stderr | 14 + .../associated-types-issue-17359.rs | 10 + .../associated-types-issue-17359.stderr | 12 + .../associated-types-issue-20220.rs | 28 + .../associated-types-issue-20346.rs | 35 + .../associated-types-issue-20346.stderr | 27 + .../associated-types-issue-20371.rs | 9 + .../associated-types-issue-21212.rs | 22 + .../associated-types-iterator-binding.rs | 19 + .../ui/associated-types/associated-types-method.rs | 28 + .../associated-types-multiple-types-one-trait.rs | 46 + ...ssociated-types-multiple-types-one-trait.stderr | 43 + .../associated-types-nested-projections.rs | 44 + .../associated-types-no-suitable-bound.rs | 16 + .../associated-types-no-suitable-bound.stderr | 14 + .../associated-types-no-suitable-supertrait-2.rs | 21 + ...ssociated-types-no-suitable-supertrait-2.stderr | 14 + .../associated-types-no-suitable-supertrait.rs | 26 + .../associated-types-no-suitable-supertrait.stderr | 20 + ...associated-types-normalize-in-bounds-binding.rs | 38 + .../associated-types-normalize-in-bounds-ufcs.rs | 35 + .../associated-types-normalize-in-bounds.rs | 35 + .../associated-types-normalize-unifield-struct.rs | 24 + .../associated-types/associated-types-outlives.rs | 28 + .../associated-types-outlives.stderr | 13 + .../associated-types-overridden-binding-2.rs | 8 + .../associated-types-overridden-binding-2.stderr | 11 + .../associated-types-overridden-binding.rs | 11 + .../associated-types-overridden-binding.stderr | 27 + .../associated-types-overridden-default.rs | 22 + .../ui/associated-types/associated-types-path-1.rs | 13 + .../associated-types-path-1.stderr | 31 + .../ui/associated-types/associated-types-path-2.rs | 48 + .../associated-types-path-2.stderr | 97 + ...ssociated-types-project-from-hrtb-in-fn-body.rs | 27 + ...iated-types-project-from-hrtb-in-fn-body.stderr | 30 + .../associated-types-project-from-hrtb-in-fn.fixed | 37 + .../associated-types-project-from-hrtb-in-fn.rs | 37 + ...associated-types-project-from-hrtb-in-fn.stderr | 14 + ...associated-types-project-from-hrtb-in-struct.rs | 39 + ...ciated-types-project-from-hrtb-in-struct.stderr | 54 + ...d-types-project-from-hrtb-in-trait-method.fixed | 38 + ...ated-types-project-from-hrtb-in-trait-method.rs | 38 + ...-types-project-from-hrtb-in-trait-method.stderr | 25 + ...s-project-from-type-param-via-bound-in-where.rs | 98 + .../associated-types-projection-bound-ambiguity.rs | 16 + ...ciated-types-projection-bound-in-supertraits.rs | 23 + ...ted-types-projection-from-known-type-in-impl.rs | 38 + .../associated-types-projection-in-object-type.rs | 40 + .../associated-types-projection-in-supertrait.rs | 45 + .../associated-types-projection-in-where-clause.rs | 31 + ...unrelated-trait-in-method-without-default.fixed | 30 + ...to-unrelated-trait-in-method-without-default.rs | 30 + ...nrelated-trait-in-method-without-default.stderr | 14 + ...sociated-types-projection-to-unrelated-trait.rs | 35 + ...alified-path-with-trait-with-type-parameters.rs | 9 + .../associated-types-ref-from-struct.rs | 51 + .../associated-types-ref-in-struct-literal.rs | 23 + .../associated-types-region-erasure-issue-20582.rs | 21 + .../associated-types-resolve-lifetime.rs | 15 + .../ui/associated-types/associated-types-return.rs | 46 + .../ui/associated-types/associated-types-simple.rs | 24 + .../ui/associated-types/associated-types-stream.rs | 38 + .../associated-types-struct-field-named.rs | 35 + .../associated-types-struct-field-numbered.rs | 32 + .../associated-types-subtyping-1.rs | 49 + .../associated-types-subtyping-1.stderr | 28 + .../associated-types-sugar-path.rs | 41 + .../associated-types-unconstrained.rs | 16 + .../associated-types-unconstrained.stderr | 17 + .../associated-types-unsized.fixed | 14 + .../associated-types/associated-types-unsized.rs | 14 + .../associated-types-unsized.stderr | 17 + ...associated-types-where-clause-impl-ambiguity.rs | 46 + .../auxiliary/associated-types-cc-lib.rs | 16 + .../bound-lifetime-constrained.clause.stderr | 15 + .../bound-lifetime-constrained.func.stderr | 15 + .../bound-lifetime-constrained.object.stderr | 15 + .../associated-types/bound-lifetime-constrained.rs | 48 + .../bound-lifetime-in-binding-only.angle.stderr | 27 + .../bound-lifetime-in-binding-only.elision.stderr | 15 + .../bound-lifetime-in-binding-only.ok.stderr | 8 + .../bound-lifetime-in-binding-only.paren.stderr | 27 + .../bound-lifetime-in-binding-only.rs | 71 + .../bound-lifetime-in-return-only.elision.stderr | 15 + .../bound-lifetime-in-return-only.local.stderr | 9 + .../bound-lifetime-in-return-only.ok.stderr | 8 + .../bound-lifetime-in-return-only.rs | 49 + .../bound-lifetime-in-return-only.sig.stderr | 15 + .../bound-lifetime-in-return-only.structure.stderr | 9 + tests/ui/associated-types/cache/chrono-scan.rs | 30 + tests/ui/associated-types/cache/elision.rs | 23 + .../project-fn-ret-contravariant.krisskross.stderr | 30 + .../cache/project-fn-ret-contravariant.rs | 50 + .../project-fn-ret-contravariant.transmute.stderr | 10 + .../project-fn-ret-invariant.krisskross.stderr | 36 + .../cache/project-fn-ret-invariant.oneuse.stderr | 36 + .../cache/project-fn-ret-invariant.rs | 64 + .../project-fn-ret-invariant.transmute.stderr | 15 + .../associated-types/default-associated-types.rs | 23 + .../ui/associated-types/defaults-cyclic-fail-1.rs | 40 + .../associated-types/defaults-cyclic-fail-1.stderr | 15 + .../ui/associated-types/defaults-cyclic-fail-2.rs | 41 + .../associated-types/defaults-cyclic-fail-2.stderr | 15 + .../ui/associated-types/defaults-cyclic-pass-1.rs | 56 + .../ui/associated-types/defaults-cyclic-pass-2.rs | 56 + .../defaults-in-other-trait-items-pass.rs | 37 + .../defaults-in-other-trait-items.rs | 47 + .../defaults-in-other-trait-items.stderr | 29 + tests/ui/associated-types/defaults-mixed.rs | 34 + tests/ui/associated-types/defaults-mixed.stderr | 21 + .../ui/associated-types/defaults-specialization.rs | 96 + .../defaults-specialization.stderr | 156 + tests/ui/associated-types/defaults-suitability.rs | 101 + .../associated-types/defaults-suitability.stderr | 135 + .../associated-types/defaults-unsound-62211-1.rs | 54 + .../defaults-unsound-62211-1.stderr | 68 + .../associated-types/defaults-unsound-62211-2.rs | 54 + .../defaults-unsound-62211-2.stderr | 68 + tests/ui/associated-types/defaults-wf.rs | 11 + tests/ui/associated-types/defaults-wf.stderr | 13 + .../higher-ranked-projection.bad.stderr | 17 + .../associated-types/higher-ranked-projection.rs | 25 + .../associated-types/hr-associated-type-bound-1.rs | 18 + .../hr-associated-type-bound-1.stderr | 19 + .../associated-types/hr-associated-type-bound-2.rs | 20 + .../hr-associated-type-bound-2.stderr | 21 + .../hr-associated-type-bound-object.rs | 14 + .../hr-associated-type-bound-object.stderr | 18 + .../hr-associated-type-bound-param-1.rs | 20 + .../hr-associated-type-bound-param-1.stderr | 19 + .../hr-associated-type-bound-param-2.rs | 21 + .../hr-associated-type-bound-param-2.stderr | 51 + .../hr-associated-type-bound-param-3.rs | 19 + .../hr-associated-type-bound-param-3.stderr | 19 + .../hr-associated-type-bound-param-4.rs | 19 + .../hr-associated-type-bound-param-4.stderr | 19 + .../hr-associated-type-bound-param-5.rs | 37 + .../hr-associated-type-bound-param-5.stderr | 35 + .../hr-associated-type-bound-param-6.rs | 19 + .../hr-associated-type-bound-param-6.stderr | 14 + .../hr-associated-type-projection-1.rs | 20 + .../hr-associated-type-projection-1.stderr | 24 + .../impl-trait-return-missing-constraint.rs | 32 + .../impl-trait-return-missing-constraint.stderr | 24 + tests/ui/associated-types/impl-wf-cycle-1.rs | 27 + tests/ui/associated-types/impl-wf-cycle-1.stderr | 20 + tests/ui/associated-types/impl-wf-cycle-2.rs | 15 + tests/ui/associated-types/impl-wf-cycle-2.stderr | 18 + tests/ui/associated-types/issue-18655.rs | 22 + tests/ui/associated-types/issue-19081.rs | 14 + tests/ui/associated-types/issue-19883.rs | 16 + tests/ui/associated-types/issue-19883.stderr | 15 + tests/ui/associated-types/issue-20005.rs | 15 + tests/ui/associated-types/issue-20005.stderr | 23 + tests/ui/associated-types/issue-20825-2.rs | 10 + tests/ui/associated-types/issue-20825.rs | 10 + tests/ui/associated-types/issue-20825.stderr | 16 + tests/ui/associated-types/issue-21363.rs | 15 + tests/ui/associated-types/issue-21726.rs | 38 + tests/ui/associated-types/issue-22037.rs | 17 + tests/ui/associated-types/issue-22037.stderr | 14 + tests/ui/associated-types/issue-22066.rs | 12 + tests/ui/associated-types/issue-22560.rs | 15 + tests/ui/associated-types/issue-22560.stderr | 56 + tests/ui/associated-types/issue-22828.rs | 23 + tests/ui/associated-types/issue-23208.rs | 26 + tests/ui/associated-types/issue-23595-1.rs | 14 + tests/ui/associated-types/issue-23595-1.stderr | 13 + tests/ui/associated-types/issue-23595-2.rs | 10 + tests/ui/associated-types/issue-23595-2.stderr | 9 + tests/ui/associated-types/issue-24159.rs | 37 + tests/ui/associated-types/issue-24204.rs | 25 + tests/ui/associated-types/issue-24338.rs | 21 + tests/ui/associated-types/issue-25339.rs | 31 + tests/ui/associated-types/issue-25700-1.rs | 13 + tests/ui/associated-types/issue-25700-2.rs | 23 + tests/ui/associated-types/issue-25700.rs | 14 + tests/ui/associated-types/issue-25700.stderr | 13 + tests/ui/associated-types/issue-26681.rs | 20 + tests/ui/associated-types/issue-26681.stderr | 14 + .../issue-27675-unchecked-bounds.rs | 19 + .../issue-27675-unchecked-bounds.stderr | 19 + tests/ui/associated-types/issue-28871.rs | 24 + tests/ui/associated-types/issue-31597.rs | 29 + tests/ui/associated-types/issue-32350.rs | 29 + tests/ui/associated-types/issue-36499.rs | 5 + tests/ui/associated-types/issue-36499.stderr | 14 + tests/ui/associated-types/issue-37808.rs | 19 + tests/ui/associated-types/issue-37883.rs | 25 + tests/ui/associated-types/issue-38917.rs | 25 + tests/ui/associated-types/issue-39532.rs | 14 + tests/ui/associated-types/issue-40093.rs | 14 + tests/ui/associated-types/issue-41868.rs | 23 + tests/ui/associated-types/issue-43475.rs | 10 + .../issue-43784-associated-type.rs | 17 + .../issue-43784-associated-type.stderr | 24 + tests/ui/associated-types/issue-43924.rs | 16 + tests/ui/associated-types/issue-43924.stderr | 22 + tests/ui/associated-types/issue-44153.rs | 19 + tests/ui/associated-types/issue-44153.stderr | 22 + tests/ui/associated-types/issue-47139-1.rs | 78 + tests/ui/associated-types/issue-47139-2.rs | 66 + tests/ui/associated-types/issue-47385.rs | 16 + tests/ui/associated-types/issue-47814.rs | 13 + tests/ui/associated-types/issue-47814.stderr | 14 + tests/ui/associated-types/issue-48010.rs | 23 + tests/ui/associated-types/issue-48551.rs | 34 + tests/ui/associated-types/issue-50301.rs | 31 + tests/ui/associated-types/issue-54108.rs | 41 + tests/ui/associated-types/issue-54108.stderr | 20 + tests/ui/associated-types/issue-54182-1.rs | 92 + tests/ui/associated-types/issue-54182-2.rs | 19 + tests/ui/associated-types/issue-54467.rs | 46 + tests/ui/associated-types/issue-55846.rs | 39 + tests/ui/associated-types/issue-59324.rs | 26 + tests/ui/associated-types/issue-59324.stderr | 65 + tests/ui/associated-types/issue-62200.rs | 16 + tests/ui/associated-types/issue-62200.stderr | 12 + tests/ui/associated-types/issue-63591.rs | 24 + tests/ui/associated-types/issue-63593.rs | 13 + tests/ui/associated-types/issue-63593.stderr | 19 + tests/ui/associated-types/issue-64848.rs | 29 + tests/ui/associated-types/issue-64855-2.rs | 5 + tests/ui/associated-types/issue-64855.rs | 8 + tests/ui/associated-types/issue-64855.stderr | 9 + tests/ui/associated-types/issue-65774-1.rs | 58 + tests/ui/associated-types/issue-65774-1.stderr | 32 + tests/ui/associated-types/issue-65774-2.rs | 58 + tests/ui/associated-types/issue-65774-2.stderr | 25 + tests/ui/associated-types/issue-65934.rs | 17 + tests/ui/associated-types/issue-67684.rs | 62 + tests/ui/associated-types/issue-69398.rs | 21 + tests/ui/associated-types/issue-71113.rs | 16 + tests/ui/associated-types/issue-72806.rs | 21 + tests/ui/associated-types/issue-72806.stderr | 20 + tests/ui/associated-types/issue-76179.rs | 19 + tests/ui/associated-types/issue-82079.rs | 124 + tests/ui/associated-types/issue-85103.rs | 9 + tests/ui/associated-types/issue-85103.stderr | 8 + tests/ui/associated-types/issue-87261.rs | 99 + tests/ui/associated-types/issue-87261.stderr | 294 + tests/ui/associated-types/issue-88856.rs | 32 + tests/ui/associated-types/issue-91069.rs | 24 + tests/ui/associated-types/issue-91231.rs | 17 + tests/ui/associated-types/issue-91234.rs | 13 + .../associated-types/missing-associated-types.rs | 27 + .../missing-associated-types.stderr | 129 + .../associated-types/normalization-debruijn-1.rs | 36 + .../associated-types/normalization-debruijn-2.rs | 31 + .../associated-types/normalization-debruijn-3.rs | 41 + .../associated-types/normalization-generality-2.rs | 30 + .../associated-types/normalization-generality.rs | 36 + .../associated-types/normalization-probe-cycle.rs | 25 + .../normalize-cycle-in-eval-no-region.rs | 20 + .../ui/associated-types/normalize-cycle-in-eval.rs | 43 + .../ui/associated-types/object-method-numbering.rs | 28 + tests/ui/associated-types/object-normalization.rs | 26 + .../associated-types/param-env-normalize-cycle.rs | 39 + .../point-at-type-on-obligation-failure-2.rs | 33 + .../point-at-type-on-obligation-failure-2.stderr | 45 + .../point-at-type-on-obligation-failure.rs | 21 + .../point-at-type-on-obligation-failure.stderr | 20 + .../associated-types/project-defer-unification.rs | 104 + .../project-recursion-limit-non-fatal.rs | 58 + .../ui/associated-types/substs-ppaux.normal.stderr | 91 + tests/ui/associated-types/substs-ppaux.rs | 52 + .../associated-types/substs-ppaux.verbose.stderr | 91 + .../trait-with-supertraits-needing-sized-self.rs | 11 + ...rait-with-supertraits-needing-sized-self.stderr | 16 + tests/ui/associated-types/wf-cycle-2.rs | 18 + tests/ui/associated-types/wf-cycle.rs | 13 + tests/ui/async-await/argument-patterns.rs | 28 + .../async-await/async-assoc-fn-anon-lifetimes.rs | 23 + .../async-await-let-else.drop-tracking.stderr | 106 + .../async-await-let-else.no-drop-tracking.stderr | 90 + tests/ui/async-await/async-await-let-else.rs | 56 + tests/ui/async-await/async-await.rs | 219 + .../async-block-control-flow-static-semantics.rs | 65 + ...sync-block-control-flow-static-semantics.stderr | 81 + .../async-borrowck-escaping-block-error.fixed | 18 + .../async-borrowck-escaping-block-error.rs | 18 + .../async-borrowck-escaping-block-error.stderr | 41 + .../async-borrowck-escaping-closure-error.rs | 10 + .../async-borrowck-escaping-closure-error.stderr | 21 + tests/ui/async-await/async-closure-matches-expr.rs | 12 + tests/ui/async-await/async-closure.rs | 100 + tests/ui/async-await/async-error-span.rs | 17 + tests/ui/async-await/async-error-span.stderr | 25 + .../async-fn-elided-impl-lifetime-parameter.rs | 15 + tests/ui/async-await/async-fn-nonsend.rs | 74 + tests/ui/async-await/async-fn-nonsend.stderr | 49 + tests/ui/async-await/async-fn-path-elision.rs | 13 + tests/ui/async-await/async-fn-path-elision.stderr | 15 + tests/ui/async-await/async-fn-send-uses-nonsend.rs | 57 + tests/ui/async-await/async-fn-size-moved-locals.rs | 118 + .../ui/async-await/async-fn-size-uninit-locals.rs | 102 + tests/ui/async-await/async-fn-size.rs | 105 + tests/ui/async-await/async-is-unwindsafe.rs | 30 + tests/ui/async-await/async-is-unwindsafe.stderr | 38 + tests/ui/async-await/async-matches-expr.rs | 10 + tests/ui/async-await/async-trait-fn.rs | 11 + tests/ui/async-await/async-trait-fn.stderr | 42 + .../async-unsafe-fn-call-in-safe.mir.stderr | 35 + .../ui/async-await/async-unsafe-fn-call-in-safe.rs | 25 + .../async-unsafe-fn-call-in-safe.thir.stderr | 19 + tests/ui/async-await/async-with-closure.rs | 24 + tests/ui/async-await/auxiliary/arc_wake.rs | 64 + tests/ui/async-await/auxiliary/issue-107036.rs | 12 + tests/ui/async-await/auxiliary/issue-72470-lib.rs | 175 + tests/ui/async-await/await-into-future.rs | 28 + .../2015-edition-error-various-positions.rs | 38 + .../2015-edition-error-various-positions.stderr | 97 + .../await-keyword/2015-edition-warning.fixed | 27 + .../await-keyword/2015-edition-warning.rs | 27 + .../await-keyword/2015-edition-warning.stderr | 61 + .../2018-edition-error-in-non-macro-position.rs | 24 + ...2018-edition-error-in-non-macro-position.stderr | 81 + .../await-keyword/2018-edition-error.rs | 16 + .../await-keyword/2018-edition-error.stderr | 63 + .../await-keyword/incorrect-syntax-suggestions.rs | 132 + .../incorrect-syntax-suggestions.stderr | 230 + .../await-keyword/post_expansion_error.rs | 10 + .../await-keyword/post_expansion_error.stderr | 8 + tests/ui/async-await/await-sequence.rs | 21 + tests/ui/async-await/await-unsize.rs | 14 + tests/ui/async-await/bound-normalization.rs | 14 + .../conditional-and-guaranteed-initialization.rs | 16 + tests/ui/async-await/default-struct-update.rs | 22 + tests/ui/async-await/dont-print-desugared-async.rs | 8 + .../async-await/dont-print-desugared-async.stderr | 9 + ...dont-suggest-await-on-method-return-mismatch.rs | 24 + ...-suggest-await-on-method-return-mismatch.stderr | 9 + tests/ui/async-await/dont-suggest-missing-await.rs | 19 + .../async-await/dont-suggest-missing-await.stderr | 28 + tests/ui/async-await/drop-and-assign.rs | 19 + .../async-await/drop-order/auxiliary/arc_wake.rs | 64 + ...order-for-async-fn-parameters-by-ref-binding.rs | 270 + .../drop-order-for-async-fn-parameters.rs | 265 + .../drop-order-for-locals-when-cancelled.rs | 176 + ...drop-order-for-temporary-in-tail-return-expr.rs | 98 + .../drop-order/drop-order-locals-are-hidden.rs | 13 + .../drop-order/drop-order-locals-are-hidden.stderr | 27 + .../drop-order/drop-order-when-cancelled.rs | 309 + .../ui/async-await/drop-track-bad-field-in-fru.rs | 10 + .../async-await/drop-track-bad-field-in-fru.stderr | 23 + .../async-await/drop-track-field-assign-nonsend.rs | 45 + .../drop-track-field-assign-nonsend.stderr | 25 + tests/ui/async-await/drop-track-field-assign.rs | 44 + .../drop-tracking-unresolved-typeck-results.rs | 106 + .../drop-tracking-unresolved-typeck-results.stderr | 62 + .../ui/async-await/edition-deny-async-fns-2015.rs | 38 + .../async-await/edition-deny-async-fns-2015.stderr | 98 + tests/ui/async-await/expansion-in-attrs.rs | 13 + tests/ui/async-await/feature-async-closure.rs | 8 + tests/ui/async-await/feature-async-closure.stderr | 13 + .../async-await/feature-gate-async_fn_in_trait.rs | 25 + .../feature-gate-async_fn_in_trait.stderr | 42 + tests/ui/async-await/feature-self-return-type.rs | 28 + .../ui/async-await/feature-self-return-type.stderr | 15 + tests/ui/async-await/futures-api.rs | 61 + tests/ui/async-await/generator-desc.rs | 16 + tests/ui/async-await/generator-desc.stderr | 63 + tests/ui/async-await/generator-not-future.rs | 45 + tests/ui/async-await/generator-not-future.stderr | 81 + tests/ui/async-await/generics-and-bounds.rs | 88 + .../async-await/in-trait/async-associated-types.rs | 24 + .../in-trait/async-associated-types2.rs | 30 + .../async-example-desugared-boxed-in-trait.rs | 21 + .../async-example-desugared-boxed-in-trait.stderr | 17 + .../in-trait/async-example-desugared-boxed.rs | 21 + .../in-trait/async-example-desugared-boxed.stderr | 11 + .../in-trait/async-example-desugared-extra.rs | 37 + .../in-trait/async-example-desugared-in-trait.rs | 21 + .../in-trait/async-example-desugared-manual.rs | 29 + .../in-trait/async-example-desugared-manual.stderr | 11 + .../in-trait/async-example-desugared.rs | 20 + tests/ui/async-await/in-trait/async-example.rs | 32 + .../in-trait/async-generics-and-bounds.rs | 21 + .../in-trait/async-generics-and-bounds.stderr | 37 + tests/ui/async-await/in-trait/async-generics.rs | 18 + .../ui/async-await/in-trait/async-generics.stderr | 37 + .../in-trait/async-lifetimes-and-bounds.rs | 19 + tests/ui/async-await/in-trait/async-lifetimes.rs | 17 + .../in-trait/async-recursive-generic.rs | 21 + .../in-trait/async-recursive-generic.stderr | 12 + tests/ui/async-await/in-trait/async-recursive.rs | 21 + .../ui/async-await/in-trait/async-recursive.stderr | 12 + tests/ui/async-await/in-trait/bad-signatures.rs | 16 + .../ui/async-await/in-trait/bad-signatures.stderr | 26 + tests/ui/async-await/in-trait/early-bound-1.rs | 17 + tests/ui/async-await/in-trait/early-bound-2.rs | 15 + tests/ui/async-await/in-trait/fn-not-async-err.rs | 17 + .../async-await/in-trait/fn-not-async-err.stderr | 11 + tests/ui/async-await/in-trait/fn-not-async-err2.rs | 19 + .../async-await/in-trait/fn-not-async-err2.stderr | 12 + tests/ui/async-await/in-trait/implied-bounds.rs | 13 + tests/ui/async-await/in-trait/issue-102138.rs | 46 + tests/ui/async-await/in-trait/issue-102219.rs | 10 + tests/ui/async-await/in-trait/issue-102310.rs | 15 + tests/ui/async-await/in-trait/issue-104678.rs | 31 + tests/ui/async-await/in-trait/lifetime-mismatch.rs | 20 + .../async-await/in-trait/lifetime-mismatch.stderr | 21 + .../ui/async-await/in-trait/missing-send-bound.rs | 21 + .../async-await/in-trait/missing-send-bound.stderr | 29 + tests/ui/async-await/in-trait/nested-rpit.rs | 19 + tests/ui/async-await/in-trait/object-safety.rs | 13 + tests/ui/async-await/in-trait/object-safety.stderr | 27 + .../async-await/in-trait/return-type-suggestion.rs | 14 + .../in-trait/return-type-suggestion.stderr | 23 + .../incorrect-move-async-order-issue-79694.fixed | 8 + .../incorrect-move-async-order-issue-79694.rs | 8 + .../incorrect-move-async-order-issue-79694.stderr | 13 + .../interior-with-const-generic-expr.rs | 26 + tests/ui/async-await/issue-101715.rs | 17 + tests/ui/async-await/issue-101715.stderr | 16 + tests/ui/async-await/issue-105501.rs | 165 + tests/ui/async-await/issue-107036.rs | 14 + .../issue-54239-private-type-triggers-lint.rs | 17 + tests/ui/async-await/issue-60709.rs | 28 + tests/ui/async-await/issue-61076.rs | 97 + tests/ui/async-await/issue-61076.stderr | 82 + tests/ui/async-await/issue-61452.rs | 13 + tests/ui/async-await/issue-61452.stderr | 26 + tests/ui/async-await/issue-61793.rs | 16 + .../ui/async-await/issue-61949-self-return-type.rs | 28 + .../issue-61949-self-return-type.stderr | 25 + tests/ui/async-await/issue-62658.rs | 27 + ...issue-63832-await-short-temporary-lifetime-1.rs | 19 + .../issue-63832-await-short-temporary-lifetime.rs | 12 + tests/ui/async-await/issue-64130-1-sync.rs | 23 + tests/ui/async-await/issue-64130-1-sync.stderr | 24 + tests/ui/async-await/issue-64130-2-send.rs | 23 + tests/ui/async-await/issue-64130-2-send.stderr | 24 + tests/ui/async-await/issue-64130-3-other.rs | 26 + tests/ui/async-await/issue-64130-3-other.stderr | 27 + .../issue-64130-4-async-move.drop-tracking.stderr | 26 + ...ssue-64130-4-async-move.no_drop_tracking.stderr | 26 + tests/ui/async-await/issue-64130-4-async-move.rs | 32 + .../issue-64130-non-send-future-diags.rs | 25 + .../issue-64130-non-send-future-diags.stderr | 24 + tests/ui/async-await/issue-64391.rs | 14 + tests/ui/async-await/issue-66312.rs | 14 + tests/ui/async-await/issue-66312.stderr | 12 + .../ui/async-await/issue-66387-if-without-else.rs | 10 + .../async-await/issue-66387-if-without-else.stderr | 14 + tests/ui/async-await/issue-67252-unnamed-future.rs | 24 + .../async-await/issue-67252-unnamed-future.stderr | 28 + tests/ui/async-await/issue-67651.rs | 20 + tests/ui/async-await/issue-67651.stderr | 12 + .../ui/async-await/issue-67765-async-diagnostic.rs | 16 + .../issue-67765-async-diagnostic.stderr | 12 + .../async-await/issue-68112.drop_tracking.stderr | 79 + .../issue-68112.no_drop_tracking.stderr | 79 + tests/ui/async-await/issue-68112.rs | 69 + tests/ui/async-await/issue-68523-start.rs | 9 + tests/ui/async-await/issue-68523-start.stderr | 9 + tests/ui/async-await/issue-68523.rs | 6 + tests/ui/async-await/issue-68523.stderr | 9 + tests/ui/async-await/issue-69446-fnmut-capture.rs | 22 + .../async-await/issue-69446-fnmut-capture.stderr | 19 + tests/ui/async-await/issue-70594.rs | 11 + tests/ui/async-await/issue-70594.stderr | 37 + tests/ui/async-await/issue-70818.rs | 9 + tests/ui/async-await/issue-70818.stderr | 18 + .../issue-70935-complex-spans.drop_tracking.stderr | 34 + ...sue-70935-complex-spans.no_drop_tracking.stderr | 21 + tests/ui/async-await/issue-70935-complex-spans.rs | 29 + tests/ui/async-await/issue-71137.rs | 23 + tests/ui/async-await/issue-71137.stderr | 25 + tests/ui/async-await/issue-72442.rs | 26 + tests/ui/async-await/issue-72442.stderr | 14 + tests/ui/async-await/issue-72470-llvm-dominate.rs | 66 + .../ui/async-await/issue-72590-type-error-sized.rs | 22 + .../issue-72590-type-error-sized.stderr | 34 + tests/ui/async-await/issue-73050.rs | 12 + tests/ui/async-await/issue-73137.rs | 44 + tests/ui/async-await/issue-73541-1.rs | 12 + tests/ui/async-await/issue-73541-1.stderr | 14 + tests/ui/async-await/issue-73541-2.rs | 20 + tests/ui/async-await/issue-73541-2.stderr | 18 + tests/ui/async-await/issue-73541-3.rs | 9 + tests/ui/async-await/issue-73541-3.stderr | 12 + tests/ui/async-await/issue-73541.rs | 9 + tests/ui/async-await/issue-73541.stderr | 14 + .../issue-73741-type-err-drop-tracking.rs | 14 + .../issue-73741-type-err-drop-tracking.stderr | 11 + tests/ui/async-await/issue-73741-type-err.rs | 14 + tests/ui/async-await/issue-73741-type-err.stderr | 11 + tests/ui/async-await/issue-74047.rs | 17 + tests/ui/async-await/issue-74047.stderr | 12 + .../issue-74072-lifetime-name-annotations.rs | 37 + .../issue-74072-lifetime-name-annotations.stderr | 51 + .../async-await/issue-74497-lifetime-in-opaque.rs | 19 + .../issue-74497-lifetime-in-opaque.stderr | 11 + .../issue-75785-confusing-named-region.rs | 13 + .../issue-75785-confusing-named-region.stderr | 15 + tests/ui/async-await/issue-76547.rs | 38 + tests/ui/async-await/issue-76547.stderr | 32 + tests/ui/async-await/issue-77993-2.rs | 9 + tests/ui/async-await/issue-77993-2.stderr | 8 + tests/ui/async-await/issue-84841.rs | 16 + tests/ui/async-await/issue-84841.stderr | 26 + tests/ui/async-await/issue-86507.rs | 25 + tests/ui/async-await/issue-86507.stderr | 23 + tests/ui/async-await/issue-93197.rs | 16 + tests/ui/async-await/issue-93648.rs | 12 + tests/ui/async-await/issue-98634.rs | 50 + tests/ui/async-await/issue-98634.stderr | 60 + .../ui/async-await/issues/auxiliary/issue-60674.rs | 12 + .../ui/async-await/issues/auxiliary/issue_67893.rs | 10 + tests/ui/async-await/issues/issue-102206.rs | 8 + tests/ui/async-await/issues/issue-102206.stderr | 23 + tests/ui/async-await/issues/issue-51719.rs | 12 + tests/ui/async-await/issues/issue-51719.stderr | 11 + tests/ui/async-await/issues/issue-51751.rs | 11 + tests/ui/async-await/issues/issue-51751.stderr | 12 + tests/ui/async-await/issues/issue-53249.rs | 47 + .../async-await/issues/issue-54752-async-block.rs | 7 + .../issues/issue-54752-async-block.stderr | 15 + tests/ui/async-await/issues/issue-54974.rs | 14 + tests/ui/async-await/issues/issue-55324.rs | 11 + tests/ui/async-await/issues/issue-55809.rs | 28 + tests/ui/async-await/issues/issue-58885.rs | 19 + tests/ui/async-await/issues/issue-59001.rs | 14 + tests/ui/async-await/issues/issue-59972.rs | 34 + tests/ui/async-await/issues/issue-60518.rs | 10 + .../issues/issue-60655-latebound-regions.rs | 30 + tests/ui/async-await/issues/issue-60674.rs | 19 + tests/ui/async-await/issues/issue-60674.stdout | 3 + tests/ui/async-await/issues/issue-61187.rs | 7 + tests/ui/async-await/issues/issue-61187.stderr | 14 + tests/ui/async-await/issues/issue-61986.rs | 19 + tests/ui/async-await/issues/issue-62009-1.rs | 15 + tests/ui/async-await/issues/issue-62009-1.stderr | 43 + tests/ui/async-await/issues/issue-62009-2.rs | 10 + tests/ui/async-await/issues/issue-62009-2.stderr | 11 + tests/ui/async-await/issues/issue-62097.rs | 21 + tests/ui/async-await/issues/issue-62097.stderr | 36 + tests/ui/async-await/issues/issue-62517-1.rs | 21 + tests/ui/async-await/issues/issue-62517-2.rs | 16 + tests/ui/async-await/issues/issue-63388-1.rs | 19 + tests/ui/async-await/issues/issue-63388-1.stderr | 15 + tests/ui/async-await/issues/issue-63388-2.rs | 19 + tests/ui/async-await/issues/issue-63388-2.stderr | 30 + tests/ui/async-await/issues/issue-63388-3.rs | 17 + tests/ui/async-await/issues/issue-63388-4.rs | 10 + tests/ui/async-await/issues/issue-64391-2.rs | 20 + tests/ui/async-await/issues/issue-64433.rs | 30 + tests/ui/async-await/issues/issue-64477-2.rs | 22 + tests/ui/async-await/issues/issue-64477.rs | 20 + tests/ui/async-await/issues/issue-64964.rs | 23 + tests/ui/async-await/issues/issue-65159.rs | 11 + tests/ui/async-await/issues/issue-65159.stderr | 16 + ...issue-65419-async-fn-resume-after-completion.rs | 46 + .../issue-65419-async-fn-resume-after-panic.rs | 52 + ...ssue-65419-generator-resume-after-completion.rs | 25 + ...-65436-raw-ptr-not-send.no_drop_tracking.stderr | 32 + .../issues/issue-65436-raw-ptr-not-send.rs | 20 + .../async-await/issues/issue-66695-static-refs.rs | 24 + .../issue-66958-non-copy-infered-type-arg.rs | 15 + .../issue-66958-non-copy-infered-type-arg.stderr | 13 + .../issues/issue-67611-static-mut-refs.rs | 33 + tests/ui/async-await/issues/issue-67893.rs | 11 + tests/ui/async-await/issues/issue-67893.stderr | 23 + tests/ui/async-await/issues/issue-69307-nested.rs | 30 + tests/ui/async-await/issues/issue-69307.rs | 23 + tests/ui/async-await/issues/issue-72312.rs | 21 + tests/ui/async-await/issues/issue-72312.stderr | 23 + tests/ui/async-await/issues/issue-78600.rs | 12 + tests/ui/async-await/issues/issue-78600.stderr | 14 + .../ui/async-await/issues/issue-78654.full.stderr | 19 + tests/ui/async-await/issues/issue-78654.min.stderr | 19 + tests/ui/async-await/issues/issue-78654.rs | 15 + .../async-await/issues/issue-78938-async-block.rs | 33 + .../issues/issue-78938-async-block.stderr | 19 + tests/ui/async-await/issues/issue-95307.rs | 13 + tests/ui/async-await/issues/issue-95307.stderr | 32 + .../async-await/issues/non-async-enclosing-span.rs | 11 + .../issues/non-async-enclosing-span.stderr | 12 + tests/ui/async-await/large_moves.attribute.stderr | 45 + tests/ui/async-await/large_moves.option.stderr | 45 + tests/ui/async-await/large_moves.rs | 27 + .../move-part-await-return-rest-struct.rs | 18 + .../move-part-await-return-rest-tuple.rs | 12 + tests/ui/async-await/multiple-lifetimes/elided.rs | 10 + tests/ui/async-await/multiple-lifetimes/fn-ptr.rs | 12 + tests/ui/async-await/multiple-lifetimes/hrtb.rs | 14 + tests/ui/async-await/multiple-lifetimes/named.rs | 10 + .../multiple-lifetimes/partial-relation.rs | 13 + .../multiple-lifetimes/ret-impl-trait-fg.rs | 17 + .../multiple-lifetimes/ret-impl-trait-one.rs | 31 + .../multiple-lifetimes/ret-impl-trait-one.stderr | 35 + tests/ui/async-await/multiple-lifetimes/ret-ref.rs | 44 + .../async-await/multiple-lifetimes/ret-ref.stderr | 37 + .../ui/async-await/multiple-lifetimes/variance.rs | 15 + .../mutually-recursive-async-impl-trait-type.rs | 13 + ...mutually-recursive-async-impl-trait-type.stderr | 21 + tests/ui/async-await/nested-in-impl.rs | 15 + tests/ui/async-await/no-async-const.rs | 5 + tests/ui/async-await/no-async-const.stderr | 13 + tests/ui/async-await/no-const-async.rs | 6 + tests/ui/async-await/no-const-async.stderr | 42 + .../ui/async-await/no-move-across-await-struct.rs | 16 + .../async-await/no-move-across-await-struct.stderr | 13 + tests/ui/async-await/no-move-across-await-tuple.rs | 12 + .../async-await/no-move-across-await-tuple.stderr | 14 + .../no-non-guaranteed-initialization.rs | 12 + .../no-non-guaranteed-initialization.stderr | 16 + .../no-params-non-move-async-closure.rs | 8 + .../no-params-non-move-async-closure.stderr | 11 + tests/ui/async-await/no-std.rs | 13 + tests/ui/async-await/no-unsafe-async.rs | 11 + tests/ui/async-await/no-unsafe-async.stderr | 29 + tests/ui/async-await/non-trivial-drop.rs | 36 + ...artial-drop-partial-reinit.drop_tracking.stderr | 35 + ...ial-drop-partial-reinit.no_drop_tracking.stderr | 35 + .../ui/async-await/partial-drop-partial-reinit.rs | 40 + .../partial-initialization-across-await.rs | 39 + .../partial-initialization-across-await.stderr | 33 + tests/ui/async-await/pin-needed-to-poll-2.rs | 48 + tests/ui/async-await/pin-needed-to-poll-2.stderr | 20 + tests/ui/async-await/pin-needed-to-poll.rs | 47 + tests/ui/async-await/pin-needed-to-poll.stderr | 20 + .../async-await/proper-span-for-type-error.fixed | 12 + tests/ui/async-await/proper-span-for-type-error.rs | 11 + .../async-await/proper-span-for-type-error.stderr | 17 + .../async-await/recursive-async-impl-trait-type.rs | 10 + .../recursive-async-impl-trait-type.stderr | 12 + .../async-await/repeat_count_const_in_async_fn.rs | 10 + tests/ui/async-await/return-ty-raw-ptr-coercion.rs | 25 + tests/ui/async-await/return-ty-unsize-coercion.rs | 45 + .../suggest-missing-await-closure.fixed | 23 + .../async-await/suggest-missing-await-closure.rs | 23 + .../suggest-missing-await-closure.stderr | 28 + tests/ui/async-await/suggest-missing-await.rs | 74 + tests/ui/async-await/suggest-missing-await.stderr | 167 + .../suggest-switching-edition-on-await-cargo.rs | 47 + ...suggest-switching-edition-on-await-cargo.stderr | 43 + .../suggest-switching-edition-on-await.rs | 45 + .../suggest-switching-edition-on-await.stderr | 43 + tests/ui/async-await/track-caller/async-block.rs | 9 + .../ui/async-await/track-caller/async-block.stderr | 12 + .../async-await/track-caller/async-closure-gate.rs | 9 + .../track-caller/async-closure-gate.stderr | 12 + tests/ui/async-await/track-caller/issue-105134.rs | 11 + .../track-caller/panic-track-caller.nofeat.stderr | 29 + .../async-await/track-caller/panic-track-caller.rs | 113 + tests/ui/async-await/try-on-option-in-async.rs | 28 + tests/ui/async-await/try-on-option-in-async.stderr | 44 + tests/ui/async-await/type-parameter-send.rs | 18 + tests/ui/async-await/unnecessary-await.rs | 14 + tests/ui/async-await/unnecessary-await.stderr | 24 + tests/ui/async-await/unreachable-lint-1.rs | 12 + tests/ui/async-await/unreachable-lint-1.stderr | 16 + tests/ui/async-await/unreachable-lint.rs | 13 + tests/ui/async-await/unresolved_type_param.rs | 24 + tests/ui/async-await/unresolved_type_param.stderr | 39 + tests/ui/async-await/unused-lifetime.rs | 39 + tests/ui/async-await/unused-lifetime.stderr | 48 + tests/ui/atomic-from-mut-not-available.rs | 7 + tests/ui/atomic-from-mut-not-available.stderr | 9 + tests/ui/attempted-access-non-fatal.rs | 10 + tests/ui/attempted-access-non-fatal.stderr | 59 + tests/ui/attr-bad-crate-attr.rc | 4 + tests/ui/attr-shebang.rs | 5 + tests/ui/attr-start.rs | 9 + tests/ui/attr-usage-inline.rs | 25 + tests/ui/attr-usage-inline.stderr | 17 + tests/ui/attributes/attr-before-view-item.rs | 10 + tests/ui/attributes/attr-before-view-item2.rs | 12 + tests/ui/attributes/attr-eq-token-tree.rs | 2 + tests/ui/attributes/attr-eq-token-tree.stderr | 8 + tests/ui/attributes/attr-mix-new.rs | 11 + tests/ui/attributes/attrs-on-params.rs | 8 + tests/ui/attributes/attrs-on-params.stderr | 17 + .../attrs-with-no-formal-in-generics-1.rs | 13 + .../attrs-with-no-formal-in-generics-1.stderr | 8 + .../attrs-with-no-formal-in-generics-2.rs | 12 + .../attrs-with-no-formal-in-generics-2.stderr | 8 + .../attrs-with-no-formal-in-generics-3.rs | 12 + .../attrs-with-no-formal-in-generics-3.stderr | 8 + .../ui/attributes/auxiliary/key-value-expansion.rs | 12 + tests/ui/attributes/class-attributes-1.rs | 19 + tests/ui/attributes/class-attributes-2.rs | 31 + tests/ui/attributes/collapse-debuginfo-invalid.rs | 110 + .../attributes/collapse-debuginfo-invalid.stderr | 222 + tests/ui/attributes/const-stability-on-macro.rs | 16 + .../ui/attributes/const-stability-on-macro.stderr | 20 + tests/ui/attributes/doc-attr.rs | 25 + tests/ui/attributes/doc-attr.stderr | 71 + tests/ui/attributes/duplicated-attributes.rs | 41 + tests/ui/attributes/duplicated-attributes.stderr | 22 + .../attributes/extented-attribute-macro-error.rs | 7 + .../extented-attribute-macro-error.stderr | 10 + .../attributes/field-attributes-vis-unresolved.rs | 25 + .../field-attributes-vis-unresolved.stderr | 19 + tests/ui/attributes/invalid-doc-attr.rs | 32 + tests/ui/attributes/invalid-doc-attr.stderr | 78 + tests/ui/attributes/issue-100631.rs | 8 + tests/ui/attributes/issue-100631.stderr | 12 + .../issue-105594-invalid-attr-validation.rs | 13 + .../issue-105594-invalid-attr-validation.stderr | 26 + tests/ui/attributes/issue-40962.rs | 11 + tests/ui/attributes/issue-90873.rs | 9 + tests/ui/attributes/issue-90873.stderr | 44 + tests/ui/attributes/item-attributes.rs | 174 + tests/ui/attributes/key-value-expansion-on-mac.rs | 14 + .../attributes/key-value-expansion-on-mac.stderr | 8 + tests/ui/attributes/key-value-expansion.rs | 55 + tests/ui/attributes/key-value-expansion.stderr | 35 + tests/ui/attributes/key-value-non-ascii.rs | 4 + tests/ui/attributes/key-value-non-ascii.stderr | 13 + tests/ui/attributes/log-backtrace.rs | 9 + tests/ui/attributes/main-removed-1.rs | 2 + tests/ui/attributes/main-removed-1.stderr | 10 + .../attributes/main-removed-2/auxiliary/tokyo.rs | 12 + tests/ui/attributes/main-removed-2/main.rs | 11 + tests/ui/attributes/method-attributes.rs | 28 + tests/ui/attributes/multiple-invalid.rs | 10 + tests/ui/attributes/multiple-invalid.stderr | 21 + tests/ui/attributes/nonterminal-expansion.rs | 18 + tests/ui/attributes/nonterminal-expansion.stderr | 25 + tests/ui/attributes/obsolete-attr.rs | 9 + tests/ui/attributes/obsolete-attr.stderr | 14 + tests/ui/attributes/suffixed-literal-meta.rs | 15 + tests/ui/attributes/suffixed-literal-meta.stderr | 98 + tests/ui/attributes/tool_attributes.rs | 13 + .../unix_sigpipe/auxiliary/sigpipe-utils.rs | 33 + .../attributes/unix_sigpipe/unix_sigpipe-crate.rs | 4 + .../unix_sigpipe/unix_sigpipe-crate.stderr | 13 + .../unix_sigpipe/unix_sigpipe-duplicates.rs | 5 + .../unix_sigpipe/unix_sigpipe-duplicates.stderr | 14 + .../attributes/unix_sigpipe/unix_sigpipe-error.rs | 13 + .../unix_sigpipe/unix_sigpipe-inherit.rs | 14 + .../attributes/unix_sigpipe/unix_sigpipe-list.rs | 4 + .../unix_sigpipe/unix_sigpipe-list.stderr | 15 + .../unix_sigpipe/unix_sigpipe-non-main-fn.rs | 6 + .../unix_sigpipe/unix_sigpipe-non-main-fn.stderr | 8 + .../unix_sigpipe/unix_sigpipe-non-root-main.rs | 8 + .../unix_sigpipe/unix_sigpipe-non-root-main.stderr | 8 + .../unix_sigpipe/unix_sigpipe-not-used.rs | 9 + .../unix_sigpipe/unix_sigpipe-only-feature.rs | 13 + .../unix_sigpipe/unix_sigpipe-rustc_main.rs | 15 + .../unix_sigpipe/unix_sigpipe-sig_dfl.rs | 13 + .../attributes/unix_sigpipe/unix_sigpipe-start.rs | 6 + .../unix_sigpipe/unix_sigpipe-start.stderr | 8 + .../attributes/unix_sigpipe/unix_sigpipe-struct.rs | 6 + .../unix_sigpipe/unix_sigpipe-struct.stderr | 8 + .../attributes/unix_sigpipe/unix_sigpipe-wrong.rs | 4 + .../unix_sigpipe/unix_sigpipe-wrong.stderr | 8 + tests/ui/attributes/unix_sigpipe/unix_sigpipe.rs | 4 + .../ui/attributes/unix_sigpipe/unix_sigpipe.stderr | 8 + tests/ui/attributes/unknown-attr.rs | 12 + tests/ui/attributes/unknown-attr.stderr | 20 + .../ui/attributes/unnamed-field-attributes-dup.rs | 11 + .../ui/attributes/unnamed-field-attributes-vis.rs | 11 + tests/ui/attributes/unnamed-field-attributes.rs | 9 + .../ui/attributes/unrestricted-attribute-tokens.rs | 8 + tests/ui/attributes/unused-item-in-attr.rs | 6 + tests/ui/attributes/unused-item-in-attr.stderr | 16 + tests/ui/attributes/used_with_arg.rs | 19 + tests/ui/attributes/used_with_arg.stderr | 18 + tests/ui/attributes/used_with_arg_no_mangle.rs | 9 + tests/ui/attributes/used_with_multi_args.rs | 6 + tests/ui/attributes/used_with_multi_args.stderr | 8 + tests/ui/attributes/variant-attributes.rs | 37 + tests/ui/attributes/z-crate-attr.rs | 12 + tests/ui/attrs-resolution-errors.rs | 40 + tests/ui/attrs-resolution-errors.stderr | 32 + tests/ui/attrs-resolution.rs | 37 + .../ui/augmented-assignments-feature-gate-cross.rs | 11 + tests/ui/augmented-assignments-rpass.rs | 172 + tests/ui/augmented-assignments.rs | 27 + tests/ui/augmented-assignments.stderr | 24 + tests/ui/auto-instantiate.rs | 13 + tests/ui/auto-ref-slice-plus-ref.rs | 27 + tests/ui/auto-ref-slice-plus-ref.stderr | 55 + tests/ui/auto-traits/auto-is-contextual.rs | 18 + .../auto-traits/auto-trait-projection-recursion.rs | 34 + tests/ui/auto-traits/auto-trait-validation.fixed | 13 + tests/ui/auto-traits/auto-trait-validation.rs | 13 + tests/ui/auto-traits/auto-trait-validation.stderr | 37 + tests/ui/auto-traits/auto-traits.rs | 32 + tests/ui/auto-traits/bad-generics-on-dyn.rs | 11 + tests/ui/auto-traits/bad-generics-on-dyn.stderr | 11 + tests/ui/auto-traits/issue-23080-2.rs | 13 + tests/ui/auto-traits/issue-23080-2.stderr | 11 + tests/ui/auto-traits/issue-23080.rs | 17 + tests/ui/auto-traits/issue-23080.stderr | 14 + tests/ui/auto-traits/issue-84075.rs | 16 + tests/ui/auto-traits/issue-84075.stderr | 11 + tests/ui/auto-traits/suspicious-impls-lint.rs | 50 + tests/ui/auto-traits/suspicious-impls-lint.stderr | 82 + .../typeck-auto-trait-no-supertraits-2.rs | 16 + .../typeck-auto-trait-no-supertraits-2.stderr | 19 + .../typeck-auto-trait-no-supertraits.rs | 39 + .../typeck-auto-trait-no-supertraits.stderr | 11 + ...ypeck-default-trait-impl-constituent-types-2.rs | 19 + ...k-default-trait-impl-constituent-types-2.stderr | 16 + .../typeck-default-trait-impl-constituent-types.rs | 23 + ...eck-default-trait-impl-constituent-types.stderr | 15 + .../typeck-default-trait-impl-negation.rs | 29 + .../typeck-default-trait-impl-negation.stderr | 27 + .../typeck-default-trait-impl-precedence.rs | 21 + .../typeck-default-trait-impl-precedence.stderr | 27 + tests/ui/autoderef-full-lval.rs | 25 + tests/ui/autoderef-full-lval.stderr | 19 + .../autoref-autoderef/auto-ref-bounded-ty-param.rs | 29 + tests/ui/autoref-autoderef/auto-ref-sliceable.rs | 19 + tests/ui/autoref-autoderef/auto-ref.rs | 19 + .../autoderef-and-borrow-method-receiver.rs | 18 + .../autoref-autoderef/autoderef-method-on-trait.rs | 15 + .../autoref-autoderef/autoderef-method-priority.rs | 19 + .../autoderef-method-twice-but-not-thrice.rs | 15 + .../ui/autoref-autoderef/autoderef-method-twice.rs | 15 + tests/ui/autoref-autoderef/autoderef-method.rs | 15 + tests/ui/autoref-autoderef/autoderef-privacy.rs | 51 + .../autoref-intermediate-types-issue-3585.rs | 22 + tests/ui/autoref-autoderef/deref-into-array.rs | 17 + tests/ui/autoref-autoderef/issue-38940.rs | 52 + tests/ui/autoref-autoderef/issue-38940.stderr | 23 + tests/ui/auxiliary/augmented_assignments.rs | 8 + .../check_static_recursion_foreign_helper.rs | 11 + .../auxiliary/crate-method-reexport-grrrrrrr2.rs | 31 + .../default-ty-param-cross-crate-crate.rs | 9 + tests/ui/auxiliary/edition-kw-macro-2015.rs | 26 + tests/ui/auxiliary/edition-kw-macro-2018.rs | 26 + tests/ui/auxiliary/fancy-panic.rs | 9 + tests/ui/auxiliary/hello_macro.rs | 21 + tests/ui/auxiliary/impl_privacy_xc_1.rs | 9 + tests/ui/auxiliary/inner_static.rs | 51 + tests/ui/auxiliary/issue-76387.rs | 29 + tests/ui/auxiliary/kinds_in_metadata.rs | 8 + tests/ui/auxiliary/msvc-data-only-lib.rs | 5 + tests/ui/auxiliary/noexporttypelib.rs | 2 + tests/ui/auxiliary/orphan-check-diagnostics.rs | 1 + tests/ui/auxiliary/pub-and-stability.rs | 133 + tests/ui/auxiliary/removing-extern-crate.rs | 1 + tests/ui/auxiliary/rustc-rust-log-aux.rs | 1 + tests/ui/auxiliary/svh-a-base.rs | 25 + tests/ui/auxiliary/svh-b.rs | 13 + tests/ui/auxiliary/typeid-intrinsic-aux1.rs | 29 + tests/ui/auxiliary/typeid-intrinsic-aux2.rs | 29 + .../ui/auxiliary/using-target-feature-unstable.rs | 5 + tests/ui/auxiliary/xc-private-method-lib.rs | 33 + tests/ui/backtrace-apple-no-dsymutil.rs | 29 + tests/ui/backtrace.rs | 130 + tests/ui/bare-fn-implements-fn-mut.rs | 27 + tests/ui/bare-static-string.rs | 6 + tests/ui/bench/issue-32062.rs | 50 + tests/ui/big-literals.rs | 17 + tests/ui/bind-by-move.rs | 13 + tests/ui/binding/ambiguity-item.rs | 19 + tests/ui/binding/ambiguity-item.stderr | 43 + .../ui/binding/bind-field-short-with-modifiers.rs | 26 + tests/ui/binding/borrowed-ptr-pattern-2.rs | 13 + tests/ui/binding/borrowed-ptr-pattern-3.rs | 13 + .../ui/binding/borrowed-ptr-pattern-infallible.rs | 8 + tests/ui/binding/borrowed-ptr-pattern-option.rs | 15 + tests/ui/binding/borrowed-ptr-pattern.rs | 12 + tests/ui/binding/const-param.rs | 10 + tests/ui/binding/const-param.stderr | 9 + tests/ui/binding/empty-types-in-patterns.rs | 59 + tests/ui/binding/exhaustive-bool-match-sanity.rs | 22 + tests/ui/binding/expr-match-generic-unique1.rs | 18 + tests/ui/binding/expr-match-generic-unique2.rs | 16 + tests/ui/binding/expr-match-generic.rs | 29 + tests/ui/binding/expr-match-panic-all.rs | 14 + tests/ui/binding/expr-match-panic.rs | 14 + tests/ui/binding/expr-match-unique.rs | 9 + tests/ui/binding/expr-match.rs | 45 + tests/ui/binding/fat-arrow-match.rs | 17 + .../fn-arg-incomplete-pattern-drop-order.rs | 69 + tests/ui/binding/fn-pattern-expected-type-2.rs | 8 + tests/ui/binding/fn-pattern-expected-type.rs | 9 + tests/ui/binding/func-arg-incomplete-pattern.rs | 22 + tests/ui/binding/func-arg-ref-pattern.rs | 26 + tests/ui/binding/func-arg-wild-pattern.rs | 12 + tests/ui/binding/if-let.rs | 60 + tests/ui/binding/inconsistent-lifetime-mismatch.rs | 15 + .../ui/binding/inferred-suffix-in-pattern-range.rs | 24 + tests/ui/binding/irrefutable-slice-patterns.rs | 14 + tests/ui/binding/issue-53114-borrow-checks.rs | 84 + tests/ui/binding/issue-53114-borrow-checks.stderr | 81 + tests/ui/binding/issue-53114-safety-checks.rs | 51 + tests/ui/binding/issue-53114-safety-checks.stderr | 156 + tests/ui/binding/let-assignability.rs | 11 + tests/ui/binding/let-destruct-ref.rs | 7 + tests/ui/binding/let-var-hygiene.rs | 11 + tests/ui/binding/match-arm-statics.rs | 165 + tests/ui/binding/match-beginning-vert.rs | 19 + tests/ui/binding/match-borrowed_str.rs | 48 + tests/ui/binding/match-bot-2.rs | 6 + tests/ui/binding/match-bot.rs | 7 + tests/ui/binding/match-byte-array-patterns.rs | 44 + tests/ui/binding/match-enum-struct-0.rs | 17 + tests/ui/binding/match-enum-struct-1.rs | 19 + tests/ui/binding/match-implicit-copy-unique.rs | 16 + tests/ui/binding/match-in-macro.rs | 17 + tests/ui/binding/match-join.rs | 20 + tests/ui/binding/match-larger-const.rs | 12 + tests/ui/binding/match-naked-record-expr.rs | 12 + tests/ui/binding/match-naked-record.rs | 13 + tests/ui/binding/match-path.rs | 14 + tests/ui/binding/match-pattern-bindings.rs | 21 + tests/ui/binding/match-pattern-lit.rs | 15 + tests/ui/binding/match-pattern-no-type-params.rs | 14 + tests/ui/binding/match-pattern-simple.rs | 9 + tests/ui/binding/match-phi.rs | 19 + tests/ui/binding/match-pipe-binding.rs | 60 + tests/ui/binding/match-range-infer.rs | 17 + tests/ui/binding/match-range-static.rs | 13 + tests/ui/binding/match-range.rs | 51 + tests/ui/binding/match-reassign.rs | 21 + .../ui/binding/match-ref-binding-in-guard-3256.rs | 13 + tests/ui/binding/match-ref-binding-mut-option.rs | 10 + tests/ui/binding/match-ref-binding-mut.rs | 18 + tests/ui/binding/match-ref-binding.rs | 12 + tests/ui/binding/match-ref-unsized.rs | 11 + tests/ui/binding/match-str.rs | 25 + tests/ui/binding/match-struct-0.rs | 21 + tests/ui/binding/match-tag.rs | 30 + tests/ui/binding/match-unique-bind.rs | 11 + tests/ui/binding/match-unsized.rs | 9 + .../binding/match-value-binding-in-guard-3291.rs | 17 + tests/ui/binding/match-var-hygiene.rs | 11 + tests/ui/binding/match-vec-alternatives.rs | 80 + tests/ui/binding/match-vec-rvalue.rs | 15 + tests/ui/binding/match-with-ret-arm.rs | 12 + tests/ui/binding/multi-let.rs | 7 + tests/ui/binding/mut-in-ident-patterns.rs | 76 + tests/ui/binding/nested-matchs.rs | 16 + tests/ui/binding/nested-pattern.rs | 16 + tests/ui/binding/nil-pattern.rs | 4 + tests/ui/binding/nullary-or-pattern.rs | 13 + tests/ui/binding/optional_comma_in_match_arm.rs | 40 + tests/ui/binding/or-pattern.rs | 14 + tests/ui/binding/order-drop-with-match.rs | 57 + tests/ui/binding/pat-ranges.rs | 20 + tests/ui/binding/pat-tuple-1.rs | 93 + tests/ui/binding/pat-tuple-2.rs | 23 + tests/ui/binding/pat-tuple-3.rs | 29 + tests/ui/binding/pat-tuple-4.rs | 57 + tests/ui/binding/pat-tuple-5.rs | 29 + tests/ui/binding/pat-tuple-6.rs | 45 + tests/ui/binding/pat-tuple-7.rs | 8 + tests/ui/binding/pattern-bound-var-in-for-each.rs | 20 + tests/ui/binding/pattern-in-closure.rs | 14 + .../binding/range-inclusive-pattern-precedence.rs | 23 + tests/ui/binding/shadow.rs | 24 + tests/ui/binding/simple-generic-match.rs | 8 + tests/ui/binding/use-uninit-match.rs | 17 + tests/ui/binding/use-uninit-match2.rs | 18 + tests/ui/binding/zero_sized_subslice_match.rs | 11 + tests/ui/binop/binary-minus-without-space.rs | 8 + tests/ui/binop/binary-op-on-double-ref.fixed | 9 + tests/ui/binop/binary-op-on-double-ref.rs | 9 + tests/ui/binop/binary-op-on-double-ref.stderr | 16 + tests/ui/binop/binary-op-on-fn-ptr-eq.rs | 9 + tests/ui/binop/binop-bitxor-str.rs | 3 + tests/ui/binop/binop-bitxor-str.stderr | 11 + tests/ui/binop/binop-consume-args.rs | 65 + tests/ui/binop/binop-consume-args.stderr | 333 + tests/ui/binop/binop-fail-3.rs | 11 + tests/ui/binop/binop-logic-float.rs | 3 + tests/ui/binop/binop-logic-float.stderr | 15 + tests/ui/binop/binop-logic-int.rs | 3 + tests/ui/binop/binop-logic-int.stderr | 15 + tests/ui/binop/binop-move-semantics.rs | 68 + tests/ui/binop/binop-move-semantics.stderr | 118 + tests/ui/binop/binop-mul-bool.rs | 3 + tests/ui/binop/binop-mul-bool.stderr | 11 + tests/ui/binop/binop-mul-i32-f32.rs | 5 + tests/ui/binop/binop-mul-i32-f32.stderr | 16 + tests/ui/binop/binop-panic.rs | 12 + tests/ui/binop/binop-typeck.rs | 8 + tests/ui/binop/binop-typeck.stderr | 11 + tests/ui/binop/binops-issue-22743.rs | 24 + tests/ui/binop/binops.rs | 89 + tests/ui/binop/issue-25916.rs | 28 + tests/ui/binop/issue-28837.rs | 35 + tests/ui/binop/issue-28837.stderr | 255 + tests/ui/binop/issue-3820.rs | 15 + tests/ui/binop/issue-3820.stderr | 19 + tests/ui/binop/issue-77910-1.rs | 11 + tests/ui/binop/issue-77910-1.stderr | 28 + tests/ui/binop/issue-77910-2.rs | 9 + tests/ui/binop/issue-77910-2.stderr | 16 + tests/ui/binop/issue-93927.rs | 20 + tests/ui/binop/issue-93927.stderr | 16 + tests/ui/binop/operator-multidispatch.rs | 36 + tests/ui/binop/operator-overloading.rs | 81 + tests/ui/binop/placement-syntax.rs | 6 + tests/ui/binop/placement-syntax.stderr | 13 + tests/ui/binop/shift-various-bad-types.rs | 31 + tests/ui/binop/shift-various-bad-types.stderr | 71 + tests/ui/binop/structured-compare.rs | 30 + tests/ui/bitwise.rs | 34 + tests/ui/blind/blind-item-block-item-shadow.rs | 9 + tests/ui/blind/blind-item-block-item-shadow.stderr | 17 + tests/ui/blind/blind-item-block-middle.rs | 9 + tests/ui/blind/blind-item-block-middle.stderr | 16 + tests/ui/blind/blind-item-item-shadow.rs | 7 + tests/ui/blind/blind-item-item-shadow.stderr | 18 + .../block-result/block-must-not-have-result-do.rs | 5 + .../block-must-not-have-result-do.stderr | 9 + .../block-result/block-must-not-have-result-res.rs | 10 + .../block-must-not-have-result-res.stderr | 11 + .../block-must-not-have-result-while.rs | 6 + .../block-must-not-have-result-while.stderr | 21 + .../block-result/consider-removing-last-semi.fixed | 20 + .../ui/block-result/consider-removing-last-semi.rs | 20 + .../consider-removing-last-semi.stderr | 36 + tests/ui/block-result/issue-11714.rs | 7 + tests/ui/block-result/issue-11714.stderr | 14 + tests/ui/block-result/issue-13428.rs | 16 + tests/ui/block-result/issue-13428.stderr | 22 + tests/ui/block-result/issue-13624.rs | 29 + tests/ui/block-result/issue-13624.stderr | 19 + tests/ui/block-result/issue-20862.rs | 9 + tests/ui/block-result/issue-20862.stderr | 26 + tests/ui/block-result/issue-22645.rs | 17 + tests/ui/block-result/issue-22645.stderr | 28 + tests/ui/block-result/issue-3563.rs | 7 + tests/ui/block-result/issue-3563.stderr | 9 + tests/ui/block-result/issue-5500.rs | 7 + tests/ui/block-result/issue-5500.stderr | 19 + tests/ui/block-result/unexpected-return-on-unit.rs | 14 + .../block-result/unexpected-return-on-unit.stderr | 18 + tests/ui/bogus-tag.rs | 10 + tests/ui/bogus-tag.stderr | 12 + tests/ui/borrow-by-val-method-receiver.rs | 14 + tests/ui/borrowck/access-mode-in-closures.rs | 10 + tests/ui/borrowck/access-mode-in-closures.stderr | 18 + tests/ui/borrowck/anonymous-region-in-apit.rs | 12 + tests/ui/borrowck/anonymous-region-in-apit.stderr | 16 + tests/ui/borrowck/assign-never-type.rs | 14 + tests/ui/borrowck/assign_mutable_fields.rs | 22 + tests/ui/borrowck/assign_mutable_fields.stderr | 23 + tests/ui/borrowck/async-reference-generality.rs | 35 + .../ui/borrowck/async-reference-generality.stderr | 27 + ...r-at-or-patterns-slice-patterns-box-patterns.rs | 220 + ...-or-patterns-slice-patterns-box-patterns.stderr | 217 + .../borrow-immutable-upvar-mutation-impl-trait.rs | 14 + ...rrow-immutable-upvar-mutation-impl-trait.stderr | 14 + .../ui/borrowck/borrow-immutable-upvar-mutation.rs | 56 + .../borrow-immutable-upvar-mutation.stderr | 87 + .../ui/borrowck/borrow-raw-address-of-borrowed.rs | 22 + .../borrowck/borrow-raw-address-of-borrowed.stderr | 40 + .../borrow-raw-address-of-deref-mutability-ok.rs | 23 + .../borrow-raw-address-of-deref-mutability.rs | 17 + .../borrow-raw-address-of-deref-mutability.stderr | 25 + .../borrow-raw-address-of-mutability-ok.rs | 44 + .../borrowck/borrow-raw-address-of-mutability.rs | 42 + .../borrow-raw-address-of-mutability.stderr | 63 + tests/ui/borrowck/borrow-tuple-fields.rs | 43 + tests/ui/borrowck/borrow-tuple-fields.stderr | 65 + tests/ui/borrowck/borrowck-access-permissions.rs | 50 + .../ui/borrowck/borrowck-access-permissions.stderr | 64 + tests/ui/borrowck/borrowck-and-init.rs | 6 + tests/ui/borrowck/borrowck-and-init.stderr | 16 + tests/ui/borrowck/borrowck-anon-fields-struct.rs | 37 + .../ui/borrowck/borrowck-anon-fields-struct.stderr | 15 + tests/ui/borrowck/borrowck-anon-fields-tuple.rs | 35 + .../ui/borrowck/borrowck-anon-fields-tuple.stderr | 15 + tests/ui/borrowck/borrowck-anon-fields-variant.rs | 46 + .../borrowck/borrowck-anon-fields-variant.stderr | 40 + tests/ui/borrowck/borrowck-argument.rs | 34 + tests/ui/borrowck/borrowck-argument.stderr | 47 + tests/ui/borrowck/borrowck-assign-comp-idx.rs | 39 + tests/ui/borrowck/borrowck-assign-comp-idx.stderr | 27 + tests/ui/borrowck/borrowck-assign-comp.rs | 36 + tests/ui/borrowck/borrowck-assign-comp.stderr | 35 + .../borrowck-assign-to-andmut-in-aliasable-loc.rs | 20 + ...rrowck-assign-to-andmut-in-aliasable-loc.stderr | 25 + .../borrowck-assign-to-andmut-in-borrowed-loc.rs | 23 + ...orrowck-assign-to-andmut-in-borrowed-loc.stderr | 26 + tests/ui/borrowck/borrowck-assign-to-constants.rs | 6 + .../borrowck/borrowck-assign-to-constants.stderr | 9 + tests/ui/borrowck/borrowck-assign-to-subfield.rs | 23 + .../borrowck/borrowck-assignment-to-static-mut.rs | 11 + .../borrowck/borrowck-auto-mut-ref-to-immut-var.rs | 16 + .../borrowck-auto-mut-ref-to-immut-var.stderr | 14 + tests/ui/borrowck/borrowck-autoref-3261.rs | 24 + tests/ui/borrowck/borrowck-autoref-3261.stderr | 16 + .../ui/borrowck/borrowck-bad-nested-calls-free.rs | 35 + .../borrowck/borrowck-bad-nested-calls-free.stderr | 23 + .../ui/borrowck/borrowck-bad-nested-calls-move.rs | 35 + .../borrowck/borrowck-bad-nested-calls-move.stderr | 23 + tests/ui/borrowck/borrowck-binding-mutbl.rs | 16 + tests/ui/borrowck/borrowck-block-unint.rs | 7 + tests/ui/borrowck/borrowck-block-unint.stderr | 18 + .../ui/borrowck/borrowck-borrow-from-expr-block.rs | 17 + .../ui/borrowck/borrowck-borrow-from-owned-ptr.rs | 134 + .../borrowck/borrowck-borrow-from-owned-ptr.stderr | 119 + .../borrowck-borrow-from-stack-variable.rs | 131 + .../borrowck-borrow-from-stack-variable.stderr | 119 + .../ui/borrowck/borrowck-borrow-from-temporary.rs | 14 + .../borrowck/borrowck-borrow-from-temporary.stderr | 11 + .../borrowck-borrow-immut-deref-of-box-as-mut.rs | 14 + ...orrowck-borrow-immut-deref-of-box-as-mut.stderr | 14 + ...orrowck-borrow-mut-base-ptr-in-aliasable-loc.rs | 24 + ...wck-borrow-mut-base-ptr-in-aliasable-loc.stderr | 34 + .../borrowck/borrowck-borrow-mut-object-twice.rs | 20 + .../borrowck-borrow-mut-object-twice.stderr | 13 + .../borrowck-borrow-of-mut-base-ptr-safe.rs | 21 + .../borrowck-borrow-overloaded-auto-deref.rs | 103 + .../borrowck-borrow-overloaded-auto-deref.stderr | 116 + .../borrowck/borrowck-borrow-overloaded-deref.rs | 43 + .../borrowck-borrow-overloaded-deref.stderr | 60 + .../ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs | 22 + .../borrowck-borrowed-uniq-rvalue-2.stderr | 16 + .../borrowck/borrowck-borrowed-uniq-rvalue.fixed | 14 + tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs | 13 + .../borrowck/borrowck-borrowed-uniq-rvalue.stderr | 20 + tests/ui/borrowck/borrowck-box-sensitivity.rs | 148 + tests/ui/borrowck/borrowck-break-uninit-2.rs | 14 + tests/ui/borrowck/borrowck-break-uninit-2.stderr | 18 + tests/ui/borrowck/borrowck-break-uninit.rs | 14 + tests/ui/borrowck/borrowck-break-uninit.stderr | 18 + tests/ui/borrowck/borrowck-closures-mut-and-imm.rs | 87 + .../borrowck/borrowck-closures-mut-and-imm.stderr | 116 + tests/ui/borrowck/borrowck-closures-mut-of-imm.rs | 18 + .../borrowck/borrowck-closures-mut-of-imm.stderr | 32 + tests/ui/borrowck/borrowck-closures-mut-of-mut.rs | 20 + .../borrowck/borrowck-closures-mut-of-mut.stderr | 18 + .../borrowck-closures-slice-patterns-ok.rs | 117 + .../borrowck/borrowck-closures-slice-patterns.rs | 82 + .../borrowck-closures-slice-patterns.stderr | 114 + tests/ui/borrowck/borrowck-closures-two-imm.rs | 41 + .../ui/borrowck/borrowck-closures-two-mut-fail.rs | 59 + .../borrowck/borrowck-closures-two-mut-fail.stderr | 75 + tests/ui/borrowck/borrowck-closures-two-mut.rs | 55 + tests/ui/borrowck/borrowck-closures-two-mut.stderr | 75 + tests/ui/borrowck/borrowck-closures-unique-imm.rs | 18 + .../borrowck/borrowck-closures-unique-imm.stderr | 13 + tests/ui/borrowck/borrowck-closures-unique.rs | 54 + tests/ui/borrowck/borrowck-closures-unique.stderr | 54 + .../borrowck/borrowck-closures-use-after-free.rs | 23 + .../borrowck-closures-use-after-free.stderr | 16 + tests/ui/borrowck/borrowck-consume-unsize-vec.rs | 12 + .../ui/borrowck/borrowck-consume-unsize-vec.stderr | 25 + tests/ui/borrowck/borrowck-consume-upcast-box.rs | 14 + .../ui/borrowck/borrowck-consume-upcast-box.stderr | 21 + tests/ui/borrowck/borrowck-describe-lvalue.rs | 279 + tests/ui/borrowck/borrowck-describe-lvalue.stderr | 372 + tests/ui/borrowck/borrowck-drop-from-guard.rs | 20 + tests/ui/borrowck/borrowck-drop-from-guard.stderr | 37 + .../borrowck/borrowck-escaping-closure-error-1.rs | 15 + .../borrowck-escaping-closure-error-1.stderr | 21 + .../borrowck/borrowck-escaping-closure-error-2.rs | 15 + .../borrowck-escaping-closure-error-2.stderr | 21 + .../borrowck/borrowck-field-sensitivity-rpass.rs | 264 + tests/ui/borrowck/borrowck-field-sensitivity.rs | 116 + .../ui/borrowck/borrowck-field-sensitivity.stderr | 144 + tests/ui/borrowck/borrowck-fixed-length-vecs.rs | 7 + tests/ui/borrowck/borrowck-fn-in-const-a.rs | 12 + tests/ui/borrowck/borrowck-fn-in-const-a.stderr | 9 + tests/ui/borrowck/borrowck-fn-in-const-c.rs | 23 + tests/ui/borrowck/borrowck-fn-in-const-c.stderr | 11 + .../borrowck-for-loop-correct-cmt-for-pattern.rs | 24 + ...orrowck-for-loop-correct-cmt-for-pattern.stderr | 48 + .../ui/borrowck/borrowck-for-loop-head-linkage.rs | 10 + .../borrowck/borrowck-for-loop-head-linkage.stderr | 27 + .../borrowck-for-loop-uninitialized-binding.rs | 7 + .../borrowck-for-loop-uninitialized-binding.stderr | 13 + tests/ui/borrowck/borrowck-freeze-frozen-mut.rs | 28 + tests/ui/borrowck/borrowck-if-no-else.rs | 6 + tests/ui/borrowck/borrowck-if-no-else.stderr | 14 + tests/ui/borrowck/borrowck-if-with-else.rs | 11 + tests/ui/borrowck/borrowck-if-with-else.stderr | 14 + ...rrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs | 10 + ...ck-imm-ref-to-mut-rec-field-issue-3162-c.stderr | 15 + tests/ui/borrowck/borrowck-in-static.rs | 12 + tests/ui/borrowck/borrowck-in-static.stderr | 13 + .../ui/borrowck/borrowck-init-in-called-fn-expr.rs | 7 + .../borrowck-init-in-called-fn-expr.stderr | 16 + tests/ui/borrowck/borrowck-init-in-fn-expr.rs | 7 + tests/ui/borrowck/borrowck-init-in-fn-expr.stderr | 16 + tests/ui/borrowck/borrowck-init-in-fru.rs | 12 + tests/ui/borrowck/borrowck-init-in-fru.stderr | 16 + tests/ui/borrowck/borrowck-init-op-equal.rs | 8 + tests/ui/borrowck/borrowck-init-op-equal.stderr | 16 + tests/ui/borrowck/borrowck-init-plus-equal.rs | 8 + tests/ui/borrowck/borrowck-init-plus-equal.stderr | 16 + tests/ui/borrowck/borrowck-insert-during-each.rs | 26 + .../ui/borrowck/borrowck-insert-during-each.stderr | 34 + tests/ui/borrowck/borrowck-issue-14498.rs | 110 + tests/ui/borrowck/borrowck-issue-14498.stderr | 103 + tests/ui/borrowck/borrowck-issue-2657-1.rs | 14 + tests/ui/borrowck/borrowck-issue-2657-1.stderr | 13 + tests/ui/borrowck/borrowck-issue-2657-2.fixed | 12 + tests/ui/borrowck/borrowck-issue-2657-2.rs | 12 + tests/ui/borrowck/borrowck-issue-2657-2.stderr | 15 + tests/ui/borrowck/borrowck-issue-48962.rs | 26 + tests/ui/borrowck/borrowck-issue-48962.stderr | 23 + tests/ui/borrowck/borrowck-lend-args.rs | 21 + tests/ui/borrowck/borrowck-lend-flow-if.rs | 51 + tests/ui/borrowck/borrowck-lend-flow-if.stderr | 14 + tests/ui/borrowck/borrowck-lend-flow-loop.rs | 132 + tests/ui/borrowck/borrowck-lend-flow-loop.stderr | 26 + tests/ui/borrowck/borrowck-lend-flow-match.rs | 18 + tests/ui/borrowck/borrowck-lend-flow-match.stderr | 13 + tests/ui/borrowck/borrowck-lend-flow.rs | 39 + tests/ui/borrowck/borrowck-lend-flow.stderr | 13 + tests/ui/borrowck/borrowck-loan-blocks-move-cc.rs | 35 + .../borrowck/borrowck-loan-blocks-move-cc.stderr | 31 + tests/ui/borrowck/borrowck-loan-blocks-move.rs | 19 + tests/ui/borrowck/borrowck-loan-blocks-move.stderr | 13 + tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs | 18 + .../borrowck/borrowck-loan-blocks-mut-uniq.stderr | 15 + .../ui/borrowck/borrowck-loan-in-overloaded-op.rs | 23 + .../borrowck/borrowck-loan-in-overloaded-op.stderr | 18 + .../borrowck-loan-of-static-data-issue-27616.rs | 24 + ...borrowck-loan-of-static-data-issue-27616.stderr | 14 + .../borrowck/borrowck-loan-rcvr-overloaded-op.rs | 46 + .../borrowck-loan-rcvr-overloaded-op.stderr | 28 + tests/ui/borrowck/borrowck-loan-rcvr.rs | 40 + tests/ui/borrowck/borrowck-loan-rcvr.stderr | 27 + tests/ui/borrowck/borrowck-loan-vec-content.rs | 24 + tests/ui/borrowck/borrowck-loan-vec-content.stderr | 15 + .../borrowck/borrowck-local-borrow-outlives-fn.rs | 6 + .../borrowck-local-borrow-outlives-fn.stderr | 9 + ...borrowck-local-borrow-with-panic-outlives-fn.rs | 10 + ...owck-local-borrow-with-panic-outlives-fn.stderr | 15 + tests/ui/borrowck/borrowck-local-borrow.rs | 9 + .../borrowck-macro-interaction-issue-6304.rs | 36 + .../ui/borrowck/borrowck-match-already-borrowed.rs | 26 + .../borrowck-match-already-borrowed.stderr | 50 + .../borrowck-match-binding-is-assignment.rs | 41 + .../borrowck-match-binding-is-assignment.stderr | 58 + tests/ui/borrowck/borrowck-move-by-capture-ok.rs | 7 + tests/ui/borrowck/borrowck-move-by-capture.rs | 11 + tests/ui/borrowck/borrowck-move-by-capture.stderr | 17 + .../borrowck/borrowck-move-error-with-note.fixed | 56 + tests/ui/borrowck/borrowck-move-error-with-note.rs | 56 + .../borrowck/borrowck-move-error-with-note.stderr | 60 + .../borrowck-move-from-subpath-of-borrowed-path.rs | 17 + ...rowck-move-from-subpath-of-borrowed-path.stderr | 14 + tests/ui/borrowck/borrowck-move-from-unsafe-ptr.rs | 7 + .../borrowck/borrowck-move-from-unsafe-ptr.stderr | 15 + tests/ui/borrowck/borrowck-move-in-irrefut-pat.rs | 16 + .../borrowck/borrowck-move-in-irrefut-pat.stderr | 48 + .../borrowck-move-moved-value-into-closure.rs | 12 + .../borrowck-move-moved-value-into-closure.stderr | 18 + tests/ui/borrowck/borrowck-move-mut-base-ptr.rs | 19 + .../ui/borrowck/borrowck-move-mut-base-ptr.stderr | 14 + .../borrowck/borrowck-move-out-from-array-match.rs | 116 + .../borrowck-move-out-from-array-match.stderr | 153 + ...orrowck-move-out-from-array-no-overlap-match.rs | 115 + ...wck-move-out-from-array-no-overlap-match.stderr | 138 + .../borrowck-move-out-from-array-no-overlap.rs | 67 + .../borrowck-move-out-from-array-use-match.rs | 150 + .../borrowck-move-out-from-array-use-match.stderr | 213 + ...wck-move-out-from-array-use-no-overlap-match.rs | 115 + ...move-out-from-array-use-no-overlap-match.stderr | 138 + .../borrowck-move-out-from-array-use-no-overlap.rs | 67 + .../borrowck/borrowck-move-out-from-array-use.rs | 97 + .../borrowck-move-out-from-array-use.stderr | 199 + tests/ui/borrowck/borrowck-move-out-from-array.rs | 71 + .../borrowck/borrowck-move-out-from-array.stderr | 143 + .../borrowck-move-out-of-overloaded-auto-deref.rs | 6 + ...rrowck-move-out-of-overloaded-auto-deref.stderr | 19 + .../borrowck-move-out-of-overloaded-deref.rs | 6 + .../borrowck-move-out-of-overloaded-deref.stderr | 15 + .../borrowck/borrowck-move-out-of-static-item.rs | 16 + .../borrowck-move-out-of-static-item.stderr | 9 + .../borrowck-move-out-of-struct-with-dtor.fixed | 24 + .../borrowck-move-out-of-struct-with-dtor.rs | 24 + .../borrowck-move-out-of-struct-with-dtor.stderr | 49 + ...rrowck-move-out-of-tuple-struct-with-dtor.fixed | 24 + .../borrowck-move-out-of-tuple-struct-with-dtor.rs | 24 + ...rowck-move-out-of-tuple-struct-with-dtor.stderr | 49 + tests/ui/borrowck/borrowck-move-out-of-vec-tail.rs | 33 + .../borrowck/borrowck-move-out-of-vec-tail.stderr | 21 + tests/ui/borrowck/borrowck-move-subcomponent.rs | 17 + .../ui/borrowck/borrowck-move-subcomponent.stderr | 13 + .../borrowck-multiple-borrows-interior-boxes.rs | 20 + tests/ui/borrowck/borrowck-multiple-captures.rs | 61 + .../ui/borrowck/borrowck-multiple-captures.stderr | 122 + tests/ui/borrowck/borrowck-mut-addr-of-imm-var.rs | 6 + .../borrowck/borrowck-mut-addr-of-imm-var.stderr | 14 + .../borrowck/borrowck-mut-borrow-linear-errors.rs | 15 + .../borrowck-mut-borrow-linear-errors.stderr | 35 + .../borrowck-mut-borrow-of-mut-base-ptr.rs | 28 + .../borrowck-mut-borrow-of-mut-base-ptr.stderr | 26 + tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs | 8 + .../borrowck/borrowck-mut-slice-of-imm-vec.stderr | 14 + tests/ui/borrowck/borrowck-mut-uniq.rs | 32 + tests/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs | 16 + tests/ui/borrowck/borrowck-mutate-in-guard.rs | 34 + tests/ui/borrowck/borrowck-mutate-in-guard.stderr | 37 + .../borrowck/borrowck-no-cycle-in-exchange-heap.rs | 20 + .../borrowck-no-cycle-in-exchange-heap.stderr | 13 + tests/ui/borrowck/borrowck-object-lifetime.rs | 40 + tests/ui/borrowck/borrowck-object-lifetime.stderr | 23 + tests/ui/borrowck/borrowck-or-init.rs | 6 + tests/ui/borrowck/borrowck-or-init.stderr | 16 + tests/ui/borrowck/borrowck-overloaded-call.rs | 80 + tests/ui/borrowck/borrowck-overloaded-call.stderr | 36 + ...rrowck-overloaded-index-and-overloaded-deref.rs | 36 + ...ck-overloaded-index-and-overloaded-deref.stderr | 14 + .../borrowck-overloaded-index-autoderef.rs | 97 + .../borrowck-overloaded-index-autoderef.stderr | 84 + .../borrowck-overloaded-index-move-from-vec.rs | 22 + .../borrowck-overloaded-index-move-from-vec.stderr | 14 + .../borrowck-overloaded-index-move-index.rs | 68 + .../borrowck-overloaded-index-move-index.stderr | 45 + .../borrowck-overloaded-index-ref-index.rs | 59 + .../borrowck-overloaded-index-ref-index.stderr | 35 + tests/ui/borrowck/borrowck-partial-reinit-1.rs | 39 + tests/ui/borrowck/borrowck-partial-reinit-1.stderr | 25 + tests/ui/borrowck/borrowck-partial-reinit-2.rs | 23 + tests/ui/borrowck/borrowck-partial-reinit-2.stderr | 13 + tests/ui/borrowck/borrowck-partial-reinit-3.rs | 13 + tests/ui/borrowck/borrowck-partial-reinit-3.stderr | 13 + tests/ui/borrowck/borrowck-partial-reinit-4.rs | 22 + tests/ui/borrowck/borrowck-partial-reinit-4.stderr | 13 + tests/ui/borrowck/borrowck-pat-enum.rs | 39 + tests/ui/borrowck/borrowck-pat-reassign-binding.rs | 15 + .../borrowck/borrowck-pat-reassign-binding.stderr | 14 + .../borrowck/borrowck-pat-reassign-no-binding.rs | 14 + tests/ui/borrowck/borrowck-reborrow-from-mut.rs | 99 + .../ui/borrowck/borrowck-reborrow-from-mut.stderr | 119 + .../borrowck-reborrow-from-shorter-lived-andmut.rs | 22 + ...rowck-reborrow-from-shorter-lived-andmut.stderr | 14 + tests/ui/borrowck/borrowck-ref-mut-of-imm.rs | 10 + tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr | 14 + tests/ui/borrowck/borrowck-reinit.rs | 7 + tests/ui/borrowck/borrowck-reinit.stderr | 19 + .../borrowck-report-with-custom-diagnostic.rs | 44 + .../borrowck-report-with-custom-diagnostic.stderr | 40 + .../borrowck-return-variable-on-stack-via-clone.rs | 10 + ...rowck-return-variable-on-stack-via-clone.stderr | 12 + tests/ui/borrowck/borrowck-return.rs | 6 + tests/ui/borrowck/borrowck-return.stderr | 16 + tests/ui/borrowck/borrowck-rvalues-mutable.rs | 34 + .../borrowck/borrowck-scope-of-deref-issue-4666.rs | 42 + ...-slice-pattern-element-loan-array-no-overlap.rs | 64 + .../borrowck-slice-pattern-element-loan-array.rs | 58 + ...orrowck-slice-pattern-element-loan-array.stderr | 86 + .../borrowck-slice-pattern-element-loan-rpass.rs | 21 + ...-slice-pattern-element-loan-slice-no-overlap.rs | 59 + .../borrowck-slice-pattern-element-loan-slice.rs | 79 + ...orrowck-slice-pattern-element-loan-slice.stderr | 117 + tests/ui/borrowck/borrowck-static-item-in-fn.rs | 9 + tests/ui/borrowck/borrowck-storage-dead.rs | 24 + tests/ui/borrowck/borrowck-storage-dead.stderr | 16 + .../borrowck/borrowck-struct-update-with-dtor.rs | 21 + .../borrowck-struct-update-with-dtor.stderr | 21 + tests/ui/borrowck/borrowck-swap-mut-base-ptr.rs | 22 + .../ui/borrowck/borrowck-swap-mut-base-ptr.stderr | 14 + ...rowck-thread-local-static-borrow-outlives-fn.rs | 9 + ...k-thread-local-static-borrow-outlives-fn.stderr | 11 + tests/ui/borrowck/borrowck-trait-lifetime.rs | 18 + tests/ui/borrowck/borrowck-unary-move.rs | 11 + tests/ui/borrowck/borrowck-unary-move.stderr | 13 + tests/ui/borrowck/borrowck-unboxed-closures.rs | 17 + tests/ui/borrowck/borrowck-unboxed-closures.stderr | 45 + tests/ui/borrowck/borrowck-uninit-after-item.rs | 5 + .../ui/borrowck/borrowck-uninit-after-item.stderr | 17 + tests/ui/borrowck/borrowck-uninit-field-access.rs | 30 + .../borrowck/borrowck-uninit-field-access.stderr | 37 + tests/ui/borrowck/borrowck-uninit-in-assignop.rs | 34 + .../ui/borrowck/borrowck-uninit-in-assignop.stderr | 133 + tests/ui/borrowck/borrowck-uninit-ref-chain.rs | 33 + tests/ui/borrowck/borrowck-uninit-ref-chain.stderr | 82 + tests/ui/borrowck/borrowck-uninit.rs | 6 + tests/ui/borrowck/borrowck-uninit.stderr | 16 + tests/ui/borrowck/borrowck-union-borrow-nested.rs | 31 + .../borrowck/borrowck-union-borrow-nested.stderr | 13 + tests/ui/borrowck/borrowck-union-borrow.rs | 96 + tests/ui/borrowck/borrowck-union-borrow.stderr | 131 + tests/ui/borrowck/borrowck-union-move-assign.rs | 32 + .../ui/borrowck/borrowck-union-move-assign.stderr | 13 + tests/ui/borrowck/borrowck-union-move.rs | 86 + tests/ui/borrowck/borrowck-union-move.stderr | 63 + tests/ui/borrowck/borrowck-union-uninitialized.rs | 18 + .../borrowck/borrowck-union-uninitialized.stderr | 25 + tests/ui/borrowck/borrowck-uniq-via-lend.rs | 61 + tests/ui/borrowck/borrowck-uniq-via-lend.stderr | 23 + tests/ui/borrowck/borrowck-uniq-via-ref.rs | 49 + tests/ui/borrowck/borrowck-univariant-enum.rs | 25 + .../borrowck-unsafe-static-mutable-borrows.rs | 20 + tests/ui/borrowck/borrowck-unused-mut-locals.rs | 47 + tests/ui/borrowck/borrowck-use-in-index-lvalue.rs | 9 + .../borrowck/borrowck-use-in-index-lvalue.stderr | 29 + tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs | 49 + tests/ui/borrowck/borrowck-use-mut-borrow.rs | 86 + tests/ui/borrowck/borrowck-use-mut-borrow.stderr | 95 + .../borrowck-use-uninitialized-in-cast-trait.rs | 10 + ...borrowck-use-uninitialized-in-cast-trait.stderr | 16 + .../borrowck/borrowck-use-uninitialized-in-cast.rs | 8 + .../borrowck-use-uninitialized-in-cast.stderr | 16 + .../borrowck/borrowck-vec-pattern-element-loan.rs | 31 + .../borrowck-vec-pattern-element-loan.stderr | 30 + .../borrowck/borrowck-vec-pattern-loan-from-mut.rs | 12 + .../borrowck-vec-pattern-loan-from-mut.stderr | 15 + .../ui/borrowck/borrowck-vec-pattern-move-tail.rs | 11 + .../borrowck/borrowck-vec-pattern-move-tail.stderr | 14 + tests/ui/borrowck/borrowck-vec-pattern-nesting.rs | 94 + .../borrowck/borrowck-vec-pattern-nesting.stderr | 125 + .../borrowck-vec-pattern-tail-element-loan.rs | 14 + .../borrowck-vec-pattern-tail-element-loan.stderr | 12 + tests/ui/borrowck/borrowck-while-break.rs | 12 + tests/ui/borrowck/borrowck-while-break.stderr | 16 + tests/ui/borrowck/borrowck-while-cond.rs | 4 + tests/ui/borrowck/borrowck-while-cond.stderr | 16 + tests/ui/borrowck/borrowck-while.rs | 7 + tests/ui/borrowck/borrowck-while.stderr | 13 + tests/ui/borrowck/copy-suggestion-region-vid.rs | 17 + .../ui/borrowck/copy-suggestion-region-vid.stderr | 14 + .../ui/borrowck/disallow-possibly-uninitialized.rs | 22 + .../disallow-possibly-uninitialized.stderr | 43 + ...-move-when-closure-is-already-marked-as-move.rs | 8 + ...e-when-closure-is-already-marked-as-move.stderr | 18 + tests/ui/borrowck/fsu-moves-and-copies.rs | 95 + tests/ui/borrowck/immut-function-arguments.rs | 9 + tests/ui/borrowck/immut-function-arguments.stderr | 25 + tests/ui/borrowck/immutable-arg.rs | 6 + tests/ui/borrowck/immutable-arg.stderr | 11 + tests/ui/borrowck/index-mut-help-with-impl.rs | 10 + tests/ui/borrowck/index-mut-help-with-impl.stderr | 9 + tests/ui/borrowck/index-mut-help.rs | 13 + tests/ui/borrowck/index-mut-help.stderr | 41 + tests/ui/borrowck/issue-101119.rs | 16 + tests/ui/borrowck/issue-101119.stderr | 15 + tests/ui/borrowck/issue-102209.rs | 28 + tests/ui/borrowck/issue-102209.stderr | 22 + tests/ui/borrowck/issue-103095.rs | 30 + tests/ui/borrowck/issue-103250.rs | 37 + tests/ui/borrowck/issue-103250.stderr | 17 + tests/ui/borrowck/issue-103624.rs | 31 + tests/ui/borrowck/issue-103624.stderr | 35 + tests/ui/borrowck/issue-104639-lifetime-order.rs | 10 + tests/ui/borrowck/issue-10876.rs | 17 + tests/ui/borrowck/issue-11493.fixed | 9 + tests/ui/borrowck/issue-11493.rs | 8 + tests/ui/borrowck/issue-11493.stderr | 19 + tests/ui/borrowck/issue-17263.rs | 23 + tests/ui/borrowck/issue-17545.rs | 10 + tests/ui/borrowck/issue-17545.stderr | 16 + tests/ui/borrowck/issue-17718-static-move.rs | 7 + tests/ui/borrowck/issue-17718-static-move.stderr | 14 + tests/ui/borrowck/issue-20801.rs | 37 + tests/ui/borrowck/issue-20801.stderr | 51 + .../issue-23338-params-outlive-temps-of-body.rs | 30 + tests/ui/borrowck/issue-24267-flow-exit.rs | 19 + tests/ui/borrowck/issue-24267-flow-exit.stderr | 33 + tests/ui/borrowck/issue-25793.rs | 26 + tests/ui/borrowck/issue-25793.stderr | 18 + tests/ui/borrowck/issue-28934.rs | 25 + tests/ui/borrowck/issue-29166.rs | 21 + tests/ui/borrowck/issue-31287-drop-in-guard.rs | 15 + tests/ui/borrowck/issue-31287-drop-in-guard.stderr | 35 + tests/ui/borrowck/issue-33819.rs | 9 + tests/ui/borrowck/issue-33819.stderr | 12 + tests/ui/borrowck/issue-36082.fixed | 17 + tests/ui/borrowck/issue-36082.rs | 16 + tests/ui/borrowck/issue-36082.stderr | 20 + tests/ui/borrowck/issue-41962.rs | 9 + tests/ui/borrowck/issue-41962.stderr | 15 + tests/ui/borrowck/issue-42344.rs | 8 + tests/ui/borrowck/issue-42344.stderr | 9 + tests/ui/borrowck/issue-45199.rs | 24 + tests/ui/borrowck/issue-45199.stderr | 35 + tests/ui/borrowck/issue-45983.rs | 12 + tests/ui/borrowck/issue-45983.stderr | 13 + tests/ui/borrowck/issue-46095.rs | 30 + tests/ui/borrowck/issue-46471.rs | 7 + tests/ui/borrowck/issue-46471.stderr | 9 + .../ui/borrowck/issue-47215-ice-from-drop-elab.rs | 20 + .../borrowck/issue-47215-ice-from-drop-elab.stderr | 14 + tests/ui/borrowck/issue-51117.rs | 15 + tests/ui/borrowck/issue-51117.stderr | 13 + tests/ui/borrowck/issue-51301.rs | 35 + tests/ui/borrowck/issue-51301.stderr | 17 + .../borrowck/issue-51348-multi-ref-mut-in-guard.rs | 21 + tests/ui/borrowck/issue-51415.fixed | 12 + tests/ui/borrowck/issue-51415.rs | 12 + tests/ui/borrowck/issue-51415.stderr | 17 + tests/ui/borrowck/issue-52713-bug.rs | 17 + tests/ui/borrowck/issue-52713-bug.stderr | 14 + ...e-52967-edition-2018-needs-two-phase-borrows.rs | 21 + ...53432-nested-closure-outlives-borrowed-value.rs | 7 + ...2-nested-closure-outlives-borrowed-value.stderr | 19 + ...issue-54499-field-mutation-marks-mut-as-used.rs | 33 + ...e-54499-field-mutation-marks-mut-as-used.stderr | 33 + ...e-54499-field-mutation-of-moved-out-with-mut.rs | 36 + ...499-field-mutation-of-moved-out-with-mut.stderr | 33 + .../issue-54499-field-mutation-of-moved-out.rs | 42 + .../issue-54499-field-mutation-of-moved-out.stderr | 100 + .../issue-54499-field-mutation-of-never-init.rs | 33 + ...issue-54499-field-mutation-of-never-init.stderr | 33 + ...ssue-54597-reject-move-out-of-borrow-via-pat.rs | 20 + ...-54597-reject-move-out-of-borrow-via-pat.stderr | 15 + .../issue-55492-borrowck-migrate-scans-parents.rs | 55 + ...sue-55492-borrowck-migrate-scans-parents.stderr | 54 + ...55552-ascribe-wildcard-to-structured-pattern.rs | 31 + .../issue-58776-borrowck-scans-children.rs | 11 + .../issue-58776-borrowck-scans-children.stderr | 32 + tests/ui/borrowck/issue-62007-assign-box.rs | 27 + tests/ui/borrowck/issue-62007-assign-field.rs | 26 + tests/ui/borrowck/issue-62107-match-arm-scopes.rs | 12 + .../borrowck/issue-62107-match-arm-scopes.stderr | 16 + tests/ui/borrowck/issue-64453.rs | 23 + tests/ui/borrowck/issue-64453.stderr | 29 + .../issue-69789-iterator-mut-suggestion.rs | 11 + .../issue-69789-iterator-mut-suggestion.stderr | 12 + tests/ui/borrowck/issue-71546.rs | 17 + tests/ui/borrowck/issue-7573.rs | 41 + tests/ui/borrowck/issue-7573.stderr | 15 + tests/ui/borrowck/issue-80772.rs | 21 + tests/ui/borrowck/issue-81365-1.rs | 26 + tests/ui/borrowck/issue-81365-1.stderr | 20 + tests/ui/borrowck/issue-81365-10.rs | 26 + tests/ui/borrowck/issue-81365-10.stderr | 13 + tests/ui/borrowck/issue-81365-11.rs | 32 + tests/ui/borrowck/issue-81365-11.stderr | 13 + tests/ui/borrowck/issue-81365-2.rs | 30 + tests/ui/borrowck/issue-81365-2.stderr | 20 + tests/ui/borrowck/issue-81365-3.rs | 37 + tests/ui/borrowck/issue-81365-3.stderr | 20 + tests/ui/borrowck/issue-81365-4.rs | 38 + tests/ui/borrowck/issue-81365-4.stderr | 20 + tests/ui/borrowck/issue-81365-5.rs | 33 + tests/ui/borrowck/issue-81365-5.stderr | 20 + tests/ui/borrowck/issue-81365-6.rs | 23 + tests/ui/borrowck/issue-81365-6.stderr | 20 + tests/ui/borrowck/issue-81365-7.rs | 24 + tests/ui/borrowck/issue-81365-7.stderr | 20 + tests/ui/borrowck/issue-81365-8.rs | 26 + tests/ui/borrowck/issue-81365-8.stderr | 20 + tests/ui/borrowck/issue-81365-9.rs | 26 + tests/ui/borrowck/issue-81365-9.stderr | 13 + tests/ui/borrowck/issue-81899.rs | 15 + tests/ui/borrowck/issue-81899.stderr | 27 + tests/ui/borrowck/issue-82032.rs | 16 + tests/ui/borrowck/issue-82032.stderr | 14 + .../issue-82126-mismatched-subst-and-hir.rs | 24 + .../issue-82126-mismatched-subst-and-hir.stderr | 33 + tests/ui/borrowck/issue-82462.rs | 21 + tests/ui/borrowck/issue-82462.stderr | 22 + .../borrowck/issue-83309-ice-immut-in-for-loop.rs | 32 + .../issue-83309-ice-immut-in-for-loop.stderr | 12 + tests/ui/borrowck/issue-83760.rs | 40 + tests/ui/borrowck/issue-83760.stderr | 60 + tests/ui/borrowck/issue-85581.rs | 15 + tests/ui/borrowck/issue-85581.stderr | 17 + tests/ui/borrowck/issue-85765.rs | 29 + tests/ui/borrowck/issue-85765.stderr | 42 + tests/ui/borrowck/issue-87456-point-to-closure.rs | 14 + .../borrowck/issue-87456-point-to-closure.stderr | 20 + tests/ui/borrowck/issue-88434-minimal-example.rs | 14 + .../ui/borrowck/issue-88434-minimal-example.stderr | 27 + .../issue-88434-removal-index-should-be-less.rs | 14 + ...issue-88434-removal-index-should-be-less.stderr | 27 + tests/ui/borrowck/issue-91206.rs | 16 + tests/ui/borrowck/issue-91206.stderr | 12 + tests/ui/borrowck/issue-92015.rs | 7 + tests/ui/borrowck/issue-92015.stderr | 11 + tests/ui/borrowck/issue-92157.rs | 40 + tests/ui/borrowck/issue-92157.stderr | 11 + tests/ui/borrowck/issue-93078.rs | 15 + tests/ui/borrowck/issue-93078.stderr | 12 + tests/ui/borrowck/issue-93093.rs | 14 + tests/ui/borrowck/issue-93093.stderr | 14 + .../issue-95079-missing-move-in-nested-closure.rs | 14 + ...sue-95079-missing-move-in-nested-closure.stderr | 37 + .../borrowck/kindck-implicit-close-over-mut-var.rs | 49 + tests/ui/borrowck/lazy-init.rs | 8 + tests/ui/borrowck/many-mutable-borrows.rs | 18 + tests/ui/borrowck/many-mutable-borrows.stderr | 33 + tests/ui/borrowck/move-error-in-promoted-2.rs | 10 + tests/ui/borrowck/move-error-in-promoted-2.stderr | 12 + tests/ui/borrowck/move-error-in-promoted.rs | 17 + tests/ui/borrowck/move-error-in-promoted.stderr | 12 + tests/ui/borrowck/move-error-snippets-ext.rs | 7 + tests/ui/borrowck/move-error-snippets.rs | 23 + tests/ui/borrowck/move-error-snippets.stderr | 20 + .../borrowck/move-from-union-field-issue-66500.rs | 28 + .../move-from-union-field-issue-66500.stderr | 27 + tests/ui/borrowck/move-in-pattern-mut-in-loop.rs | 10 + .../ui/borrowck/move-in-pattern-mut-in-loop.stderr | 15 + tests/ui/borrowck/move-in-pattern-mut.rs | 23 + tests/ui/borrowck/move-in-pattern-mut.stderr | 33 + tests/ui/borrowck/move-in-pattern.fixed | 24 + tests/ui/borrowck/move-in-pattern.rs | 24 + tests/ui/borrowck/move-in-pattern.stderr | 33 + .../move-in-static-initializer-issue-38520.rs | 16 + .../move-in-static-initializer-issue-38520.stderr | 15 + tests/ui/borrowck/mut-borrow-in-loop-2.fixed | 35 + tests/ui/borrowck/mut-borrow-in-loop-2.rs | 35 + tests/ui/borrowck/mut-borrow-in-loop-2.stderr | 25 + tests/ui/borrowck/mut-borrow-in-loop.rs | 29 + tests/ui/borrowck/mut-borrow-in-loop.stderr | 47 + tests/ui/borrowck/mut-borrow-of-mut-ref.rs | 36 + tests/ui/borrowck/mut-borrow-of-mut-ref.stderr | 59 + tests/ui/borrowck/mut-borrow-outside-loop.rs | 22 + tests/ui/borrowck/mut-borrow-outside-loop.stderr | 24 + tests/ui/borrowck/mutability-errors.rs | 82 + tests/ui/borrowck/mutability-errors.stderr | 361 + tests/ui/borrowck/or-patterns.rs | 62 + tests/ui/borrowck/or-patterns.stderr | 157 + .../borrowck/promote-ref-mut-in-let-issue-46557.rs | 31 + .../promote-ref-mut-in-let-issue-46557.stderr | 50 + tests/ui/borrowck/reassignment_immutable_fields.rs | 20 + .../borrowck/reassignment_immutable_fields.stderr | 23 + .../reassignment_immutable_fields_overlapping.rs | 16 + ...eassignment_immutable_fields_overlapping.stderr | 25 + .../reassignment_immutable_fields_twice.rs | 17 + .../reassignment_immutable_fields_twice.stderr | 25 + .../ui/borrowck/reborrow-sugg-move-then-borrow.rs | 26 + .../borrowck/reborrow-sugg-move-then-borrow.stderr | 21 + .../regions-bound-missing-bound-in-impl.rs | 54 + .../regions-bound-missing-bound-in-impl.stderr | 78 + tests/ui/borrowck/regions-escape-bound-fn-2.rs | 13 + tests/ui/borrowck/regions-escape-bound-fn-2.stderr | 13 + tests/ui/borrowck/regions-escape-bound-fn.rs | 13 + tests/ui/borrowck/regions-escape-bound-fn.stderr | 13 + .../ui/borrowck/regions-escape-unboxed-closure.rs | 7 + .../borrowck/regions-escape-unboxed-closure.stderr | 13 + .../return-local-binding-from-desugaring.rs | 33 + .../return-local-binding-from-desugaring.stderr | 12 + .../slice-index-bounds-check-invalidation.rs | 82 + .../slice-index-bounds-check-invalidation.stderr | 35 + tests/ui/borrowck/suggest-as-ref-on-mut-closure.rs | 16 + .../borrowck/suggest-as-ref-on-mut-closure.stderr | 25 + tests/ui/borrowck/suggest-assign-rvalue.rs | 57 + tests/ui/borrowck/suggest-assign-rvalue.stderr | 138 + tests/ui/borrowck/suggest-local-var-double-mut.rs | 27 + .../borrowck/suggest-local-var-double-mut.stderr | 44 + tests/ui/borrowck/suggest-local-var-for-vector.rs | 4 + .../borrowck/suggest-local-var-for-vector.stderr | 24 + tests/ui/borrowck/suggest-local-var-imm-and-mut.rs | 27 + .../borrowck/suggest-local-var-imm-and-mut.stderr | 22 + .../suggest-storing-local-var-for-vector.rs | 4 + .../suggest-storing-local-var-for-vector.stderr | 24 + tests/ui/borrowck/two-phase-across-loop.rs | 22 + tests/ui/borrowck/two-phase-across-loop.stderr | 12 + ...tivation-sharing-interference.nll_target.stderr | 47 + .../two-phase-activation-sharing-interference.rs | 65 + ...low-access-during-reservation.nll_target.stderr | 27 + .../two-phase-allow-access-during-reservation.rs | 37 + tests/ui/borrowck/two-phase-baseline.rs | 9 + tests/ui/borrowck/two-phase-bin-ops.rs | 35 + .../two-phase-cannot-nest-mut-self-calls.rs | 19 + .../two-phase-cannot-nest-mut-self-calls.stderr | 19 + ...o-phase-control-flow-split-before-activation.rs | 15 + tests/ui/borrowck/two-phase-method-receivers.rs | 15 + tests/ui/borrowck/two-phase-multi-mut.rs | 14 + tests/ui/borrowck/two-phase-multi-mut.stderr | 23 + .../ui/borrowck/two-phase-multiple-activations.rs | 21 + .../borrowck/two-phase-nonrecv-autoref.base.stderr | 93 + tests/ui/borrowck/two-phase-nonrecv-autoref.rs | 166 + ...two-phase-reservation-sharing-interference-2.rs | 29 + ...phase-reservation-sharing-interference-2.stderr | 25 + ...ervation-sharing-interference.nll_target.stderr | 15 + .../two-phase-reservation-sharing-interference.rs | 45 + tests/ui/borrowck/two-phase-sneaky.rs | 15 + tests/ui/borrowck/two-phase-sneaky.stderr | 14 + .../ui/borrowck/two-phase-surprise-no-conflict.rs | 167 + .../borrowck/two-phase-surprise-no-conflict.stderr | 161 + ...ures-move-upvar-from-non-once-ref-closure.fixed | 15 + ...losures-move-upvar-from-non-once-ref-closure.rs | 15 + ...res-move-upvar-from-non-once-ref-closure.stderr | 22 + tests/ui/bounds-lifetime.rs | 7 + tests/ui/bounds-lifetime.stderr | 32 + tests/ui/box/alloc-unstable-fail.rs | 6 + tests/ui/box/alloc-unstable-fail.stderr | 12 + tests/ui/box/alloc-unstable.rs | 8 + tests/ui/box/into-boxed-slice-fail.rs | 14 + tests/ui/box/into-boxed-slice-fail.stderr | 45 + tests/ui/box/into-boxed-slice.rs | 11 + tests/ui/box/issue-82446.rs | 15 + tests/ui/box/issue-82446.stderr | 12 + tests/ui/box/issue-95036.rs | 22 + tests/ui/box/large-allocator-ice.rs | 29 + tests/ui/box/leak-alloc.rs | 29 + tests/ui/box/leak-alloc.stderr | 15 + tests/ui/box/new-box-syntax.rs | 27 + tests/ui/box/new-box.rs | 30 + tests/ui/box/new.rs | 6 + tests/ui/box/thin_align.rs | 26 + tests/ui/box/thin_drop.rs | 37 + tests/ui/box/thin_new.rs | 30 + tests/ui/box/thin_zst.rs | 34 + tests/ui/break-diverging-value.rs | 37 + tests/ui/break-diverging-value.stderr | 19 + tests/ui/btreemap/btreemap-index-mut.rs | 6 + tests/ui/btreemap/btreemap-index-mut.stderr | 19 + tests/ui/btreemap/btreemap_dropck.rs | 16 + tests/ui/btreemap/btreemap_dropck.stderr | 13 + .../ui/btreemap/btreemap_into_iterator_lifetime.rs | 23 + tests/ui/builtin-clone-unwind.rs | 61 + .../auxiliary/trait_superkinds_in_metadata.rs | 8 + .../builtin-superkinds-capabilities-transitive.rs | 25 + .../builtin-superkinds-capabilities-xc.rs | 27 + .../builtin-superkinds-capabilities.rs | 21 + .../builtin-superkinds-double-superkind.rs | 14 + .../builtin-superkinds-double-superkind.stderr | 37 + .../builtin-superkinds-in-metadata.rs | 16 + .../builtin-superkinds-in-metadata.stderr | 24 + .../builtin-superkinds-in-metadata2.rs | 23 + .../builtin-superkinds-phantom-typaram.rs | 18 + .../builtin-superkinds-self-type.rs | 17 + .../builtin-superkinds-self-type.stderr | 19 + .../builtin-superkinds-simple.rs | 9 + .../builtin-superkinds-simple.stderr | 16 + .../builtin-superkinds-simple2.rs | 10 + .../builtin-superkinds-typaram-not-send.rs | 8 + .../builtin-superkinds-typaram-not-send.stderr | 19 + .../builtin-superkinds-typaram.rs | 11 + tests/ui/by-move-pattern-binding.rs | 29 + tests/ui/by-move-pattern-binding.stderr | 51 + .../feature-gate-extended_varargs_abi_support.rs | 17 + ...eature-gate-extended_varargs_abi_support.stderr | 49 + tests/ui/c-variadic/issue-32201.rs | 13 + tests/ui/c-variadic/issue-32201.stderr | 9 + tests/ui/c-variadic/issue-86053-1.rs | 12 + tests/ui/c-variadic/issue-86053-1.stderr | 81 + tests/ui/c-variadic/issue-86053-2.rs | 11 + tests/ui/c-variadic/issue-86053-2.stderr | 16 + tests/ui/c-variadic/variadic-ffi-1.rs | 35 + tests/ui/c-variadic/variadic-ffi-1.stderr | 100 + tests/ui/c-variadic/variadic-ffi-2.rs | 20 + tests/ui/c-variadic/variadic-ffi-2.stderr | 9 + tests/ui/c-variadic/variadic-ffi-4.rs | 38 + tests/ui/c-variadic/variadic-ffi-4.stderr | 150 + tests/ui/c-variadic/variadic-ffi-6.rs | 13 + tests/ui/c-variadic/variadic-ffi-6.stderr | 15 + tests/ui/c-variadic/variadic-ffi-no-fixed-args.rs | 6 + .../c-variadic/variadic-ffi-no-fixed-args.stderr | 8 + .../c-variadic/variadic-unreachable-arg-error.rs | 14 + tests/ui/can-copy-pod.rs | 16 + tests/ui/cancel-clean-via-immediate-rvalue-ref.rs | 10 + tests/ui/cannot-mutate-captured-non-mut-var.rs | 15 + tests/ui/cannot-mutate-captured-non-mut-var.stderr | 20 + tests/ui/capture1.rs | 6 + tests/ui/capture1.stderr | 11 + tests/ui/cast/cast-as-bool.rs | 13 + tests/ui/cast/cast-as-bool.stderr | 27 + tests/ui/cast/cast-char.rs | 10 + tests/ui/cast/cast-char.stderr | 20 + tests/ui/cast/cast-does-fallback.rs | 12 + tests/ui/cast/cast-errors-issue-43825.rs | 7 + tests/ui/cast/cast-errors-issue-43825.stderr | 9 + tests/ui/cast/cast-from-nil.rs | 2 + tests/ui/cast/cast-from-nil.stderr | 9 + tests/ui/cast/cast-int-to-char.rs | 9 + tests/ui/cast/cast-int-to-char.stderr | 89 + tests/ui/cast/cast-macro-lhs.rs | 12 + tests/ui/cast/cast-macro-lhs.stderr | 11 + tests/ui/cast/cast-pointee-projection.rs | 17 + tests/ui/cast/cast-region-to-uint.rs | 6 + tests/ui/cast/cast-rfc0401-2.rs | 8 + tests/ui/cast/cast-rfc0401-2.stderr | 9 + tests/ui/cast/cast-rfc0401-vtable-kinds.rs | 62 + tests/ui/cast/cast-rfc0401.rs | 169 + tests/ui/cast/cast-to-bare-fn.rs | 10 + tests/ui/cast/cast-to-bare-fn.stderr | 15 + tests/ui/cast/cast-to-infer-ty.rs | 8 + tests/ui/cast/cast-to-nil.rs | 2 + tests/ui/cast/cast-to-nil.stderr | 9 + .../cast-to-unsized-trait-object-suggestion.rs | 4 + .../cast-to-unsized-trait-object-suggestion.stderr | 19 + tests/ui/cast/cast.rs | 21 + tests/ui/cast/casts-differing-anon.rs | 22 + tests/ui/cast/casts-differing-anon.stderr | 11 + tests/ui/cast/casts-issue-46365.rs | 8 + tests/ui/cast/casts-issue-46365.stderr | 9 + tests/ui/cast/codegen-object-shim.rs | 6 + tests/ui/cast/fat-ptr-cast-rpass.rs | 34 + tests/ui/cast/fat-ptr-cast.rs | 33 + tests/ui/cast/fat-ptr-cast.stderr | 88 + tests/ui/cast/issue-106883-is-empty.rs | 27 + tests/ui/cast/issue-106883-is-empty.stderr | 58 + tests/ui/cast/issue-10991.rs | 4 + tests/ui/cast/issue-10991.stderr | 9 + tests/ui/cast/issue-17444.rs | 8 + tests/ui/cast/issue-17444.stderr | 9 + tests/ui/cast/issue-84213.fixed | 16 + tests/ui/cast/issue-84213.rs | 16 + tests/ui/cast/issue-84213.stderr | 25 + tests/ui/cast/issue-85586.rs | 10 + tests/ui/cast/issue-85586.stderr | 9 + tests/ui/cast/issue-88621.rs | 11 + tests/ui/cast/issue-88621.stderr | 9 + tests/ui/cast/issue-89497.fixed | 10 + tests/ui/cast/issue-89497.rs | 10 + tests/ui/cast/issue-89497.stderr | 15 + tests/ui/cast/supported-cast.rs | 206 + tests/ui/cast/unsupported-cast.rs | 5 + tests/ui/cast/unsupported-cast.stderr | 9 + tests/ui/catch-unwind-bang.rs | 10 + tests/ui/cenum_impl_drop_cast.rs | 18 + tests/ui/cenum_impl_drop_cast.stderr | 31 + .../assume-incomplete-release/assume-incomplete.rs | 38 + .../auxiliary/ver-cfg-rel.rs | 56 + tests/ui/cfg/auxiliary/cfg_inner_static.rs | 7 + tests/ui/cfg/cfg-attr-cfg.rs | 8 + tests/ui/cfg/cfg-attr-crate.rs | 8 + tests/ui/cfg/cfg-family.rs | 12 + tests/ui/cfg/cfg-in-crate-1.rs | 5 + tests/ui/cfg/cfg-macros-foo.rs | 26 + tests/ui/cfg/cfg-macros-notfoo.rs | 26 + tests/ui/cfg/cfg-match-arm.rs | 20 + tests/ui/cfg/cfg-method-receiver-ok.rs | 14 + tests/ui/cfg/cfg-method-receiver.rs | 11 + tests/ui/cfg/cfg-method-receiver.stderr | 24 + tests/ui/cfg/cfg-panic-abort.rs | 16 + tests/ui/cfg/cfg-panic.rs | 16 + tests/ui/cfg/cfg-path-error.rs | 19 + tests/ui/cfg/cfg-path-error.stderr | 26 + tests/ui/cfg/cfg-target-abi.rs | 10 + tests/ui/cfg/cfg-target-compact-errors.rs | 17 + tests/ui/cfg/cfg-target-compact-errors.stderr | 22 + tests/ui/cfg/cfg-target-compact.rs | 10 + tests/ui/cfg/cfg-target-family.rs | 13 + tests/ui/cfg/cfg-target-vendor.rs | 8 + tests/ui/cfg/cfg_attr.rs | 50 + tests/ui/cfg/cfg_inner_static.rs | 10 + tests/ui/cfg/cfg_stmt_expr.rs | 92 + tests/ui/cfg/cfgs-on-items.rs | 29 + tests/ui/cfg/conditional-compile-arch.rs | 41 + tests/ui/cfg/conditional-compile.rs | 155 + tests/ui/cfg/crt-static-off-works.rs | 10 + tests/ui/cfg/crt-static-on-works.rs | 6 + tests/ui/cfg/expanded-cfg.rs | 21 + ...uture-compat-crate-attributes-using-cfg_attr.rs | 15 + ...e-compat-crate-attributes-using-cfg_attr.stderr | 39 + tests/ui/cfguard-run.rs | 6 + tests/ui/chalkify/arithmetic.rs | 20 + tests/ui/chalkify/assert.rs | 6 + tests/ui/chalkify/basic.rs | 12 + tests/ui/chalkify/bugs/async.rs | 25 + tests/ui/chalkify/bugs/async.stderr | 58 + tests/ui/chalkify/builtin-copy-clone.rs | 45 + tests/ui/chalkify/chalk_initial_program.rs | 16 + tests/ui/chalkify/chalk_initial_program.stderr | 18 + tests/ui/chalkify/closure.rs | 38 + tests/ui/chalkify/closure.stderr | 22 + tests/ui/chalkify/generic_impls.rs | 18 + tests/ui/chalkify/generic_impls.stderr | 29 + tests/ui/chalkify/impl_wf.rs | 26 + tests/ui/chalkify/impl_wf.stderr | 29 + tests/ui/chalkify/impl_wf_2.rs | 33 + tests/ui/chalkify/impl_wf_2.stderr | 16 + tests/ui/chalkify/inherent_impl.rs | 42 + tests/ui/chalkify/inherent_impl_min.rs | 27 + tests/ui/chalkify/lower_env1.rs | 14 + tests/ui/chalkify/lower_env2.rs | 16 + tests/ui/chalkify/lower_env3.rs | 16 + tests/ui/chalkify/lower_impl.rs | 17 + tests/ui/chalkify/lower_struct.rs | 8 + tests/ui/chalkify/lower_trait.rs | 11 + tests/ui/chalkify/lower_trait_higher_rank.rs | 9 + tests/ui/chalkify/lower_trait_where_clause.rs | 16 + tests/ui/chalkify/println.rs | 6 + tests/ui/chalkify/projection.rs | 25 + .../ui/chalkify/recursive_where_clause_on_type.rs | 30 + .../chalkify/recursive_where_clause_on_type.stderr | 14 + tests/ui/chalkify/super_trait.rs | 19 + tests/ui/chalkify/trait-objects.rs | 12 + tests/ui/chalkify/trait_implied_bound.rs | 18 + tests/ui/chalkify/type_implied_bound.rs | 29 + tests/ui/chalkify/type_inference.rs | 28 + tests/ui/chalkify/type_inference.stderr | 20 + tests/ui/chalkify/type_wf.rs | 25 + tests/ui/chalkify/type_wf.stderr | 16 + tests/ui/char.rs | 13 + tests/ui/check-cfg/allow-at-crate-level.rs | 8 + tests/ui/check-cfg/allow-macro-cfg.rs | 14 + tests/ui/check-cfg/allow-same-level.rs | 11 + tests/ui/check-cfg/allow-same-level.stderr | 10 + tests/ui/check-cfg/allow-top-level.rs | 15 + tests/ui/check-cfg/allow-upper-level.rs | 12 + tests/ui/check-cfg/compact-names.rs | 15 + tests/ui/check-cfg/compact-names.stderr | 10 + tests/ui/check-cfg/compact-values.rs | 15 + tests/ui/check-cfg/compact-values.stderr | 11 + tests/ui/check-cfg/empty-names.rs | 10 + tests/ui/check-cfg/empty-names.stderr | 10 + tests/ui/check-cfg/empty-values.rs | 10 + tests/ui/check-cfg/empty-values.stderr | 13 + .../invalid-arguments.anything_else.stderr | 2 + .../invalid-arguments.names_simple_ident.stderr | 2 + tests/ui/check-cfg/invalid-arguments.rs | 10 + .../invalid-arguments.values_simple_ident.stderr | 2 + ...invalid-arguments.values_string_literals.stderr | 2 + tests/ui/check-cfg/invalid-cfg-name.rs | 14 + tests/ui/check-cfg/invalid-cfg-name.stderr | 10 + tests/ui/check-cfg/invalid-cfg-value.rs | 18 + tests/ui/check-cfg/invalid-cfg-value.stderr | 23 + tests/ui/check-cfg/mix.rs | 74 + tests/ui/check-cfg/mix.stderr | 182 + tests/ui/check-cfg/no-values.rs | 14 + tests/ui/check-cfg/no-values.stderr | 21 + tests/ui/check-cfg/stmt-no-ice.rs | 10 + tests/ui/check-cfg/stmt-no-ice.stderr | 10 + tests/ui/check-cfg/well-known-names.rs | 33 + tests/ui/check-cfg/well-known-names.stderr | 26 + tests/ui/check-cfg/well-known-values.rs | 42 + tests/ui/check-cfg/well-known-values.stderr | 53 + tests/ui/check-static-immutable-mut-slices.rs | 6 + tests/ui/check-static-immutable-mut-slices.stderr | 9 + tests/ui/check-static-recursion-foreign.rs | 23 + tests/ui/check-static-values-constraints.rs | 113 + tests/ui/check-static-values-constraints.stderr | 78 + tests/ui/class-cast-to-trait.rs | 54 + tests/ui/class-cast-to-trait.stderr | 9 + tests/ui/class-method-missing.rs | 21 + tests/ui/class-method-missing.stderr | 12 + tests/ui/cleanup-rvalue-for-scope.rs | 63 + tests/ui/cleanup-rvalue-scopes-cf.rs | 35 + tests/ui/cleanup-rvalue-scopes-cf.stderr | 122 + tests/ui/cleanup-rvalue-scopes.rs | 130 + .../cleanup-rvalue-temp-during-incomplete-alloc.rs | 47 + tests/ui/cleanup-shortcircuit.rs | 24 + tests/ui/close-over-big-then-small-data.rs | 39 + .../expect-fn-supply-fn-multiple.rs | 38 + .../closure-expected-type/expect-fn-supply-fn.rs | 60 + .../expect-fn-supply-fn.stderr | 51 + .../expect-infer-var-appearing-twice.rs | 25 + .../expect-infer-var-appearing-twice.stderr | 21 + ...expect-infer-var-supply-ty-with-bound-region.rs | 19 + .../expect-infer-var-supply-ty-with-free-region.rs | 19 + ...t-two-infer-vars-supply-ty-with-bound-region.rs | 19 + ...o-infer-vars-supply-ty-with-bound-region.stderr | 14 + tests/ui/closure-expected-type/issue-24421.rs | 10 + tests/ui/closure_context/issue-26046-fn-mut.rs | 11 + tests/ui/closure_context/issue-26046-fn-mut.stderr | 16 + tests/ui/closure_context/issue-26046-fn-once.rs | 11 + .../ui/closure_context/issue-26046-fn-once.stderr | 16 + tests/ui/closure_context/issue-42065.rs | 13 + tests/ui/closure_context/issue-42065.stderr | 22 + .../arrays-completely-captured.rs | 22 + .../arrays-completely-captured.stderr | 53 + .../ui/closures/2229_closure_analysis/by_value.rs | 37 + .../closures/2229_closure_analysis/by_value.stderr | 58 + .../2229_closure_analysis/capture-analysis-1.rs | 33 + .../capture-analysis-1.stderr | 68 + .../2229_closure_analysis/capture-analysis-2.rs | 28 + .../capture-analysis-2.stderr | 56 + .../2229_closure_analysis/capture-analysis-3.rs | 33 + .../capture-analysis-3.stderr | 56 + .../2229_closure_analysis/capture-analysis-4.rs | 31 + .../capture-analysis-4.stderr | 53 + .../capture-disjoint-field-struct.rs | 29 + .../capture-disjoint-field-struct.stderr | 48 + .../capture-disjoint-field-tuple.rs | 24 + .../capture-disjoint-field-tuple.stderr | 48 + .../2229_closure_analysis/capture-enum-field.rs | 27 + .../2229_closure_analysis/capture-enums.rs | 62 + .../2229_closure_analysis/capture-enums.stderr | 113 + .../deep-multilevel-struct.rs | 50 + .../deep-multilevel-struct.stderr | 61 + .../2229_closure_analysis/deep-multilevel-tuple.rs | 24 + .../deep-multilevel-tuple.stderr | 61 + .../2229_closure_analysis/destructure_patterns.rs | 77 + .../destructure_patterns.stderr | 178 + .../2229_closure_analysis/diagnostics/arrays.rs | 85 + .../diagnostics/arrays.stderr | 104 + .../diagnostics/borrowck/borrowck-1.rs | 19 + .../diagnostics/borrowck/borrowck-1.stderr | 19 + .../diagnostics/borrowck/borrowck-2.rs | 19 + .../diagnostics/borrowck/borrowck-2.stderr | 19 + .../diagnostics/borrowck/borrowck-3.rs | 17 + .../diagnostics/borrowck/borrowck-3.stderr | 22 + .../diagnostics/borrowck/borrowck-4.rs | 20 + .../diagnostics/borrowck/borrowck-4.stderr | 22 + .../borrowck/borrowck-closures-mut-and-imm.rs | 26 + .../borrowck/borrowck-closures-mut-and-imm.stderr | 21 + .../2229_closure_analysis/diagnostics/box.rs | 64 + .../2229_closure_analysis/diagnostics/box.stderr | 48 + .../diagnostics/cant-mutate-imm-borrow.rs | 19 + .../diagnostics/cant-mutate-imm-borrow.stderr | 12 + .../diagnostics/cant-mutate-imm.rs | 34 + .../diagnostics/cant-mutate-imm.stderr | 21 + .../closure-origin-array-diagnostics.rs | 13 + .../closure-origin-array-diagnostics.stderr | 22 + .../closure-origin-multi-variant-diagnostics.rs | 27 + ...closure-origin-multi-variant-diagnostics.stderr | 21 + .../closure-origin-single-variant-diagnostics.rs | 18 + ...losure-origin-single-variant-diagnostics.stderr | 21 + .../closure-origin-struct-diagnostics.rs | 22 + .../closure-origin-struct-diagnostics.stderr | 21 + .../closure-origin-tuple-diagnostics-1.rs | 13 + .../closure-origin-tuple-diagnostics-1.stderr | 21 + .../closure-origin-tuple-diagnostics.rs | 13 + .../closure-origin-tuple-diagnostics.stderr | 22 + .../2229_closure_analysis/diagnostics/liveness.rs | 92 + .../diagnostics/liveness.stderr | 65 + .../diagnostics/liveness_unintentional_copy.rs | 43 + .../diagnostics/liveness_unintentional_copy.stderr | 33 + .../diagnostics/multilevel-path.rs | 28 + .../diagnostics/multilevel-path.stderr | 17 + .../2229_closure_analysis/diagnostics/mut_ref.rs | 37 + .../diagnostics/mut_ref.stderr | 26 + .../diagnostics/repr_packed.rs | 32 + .../diagnostics/repr_packed.stderr | 29 + .../diagnostics/simple-struct-min-capture.rs | 25 + .../diagnostics/simple-struct-min-capture.stderr | 21 + .../2229_closure_analysis/diagnostics/union.rs | 25 + .../2229_closure_analysis/diagnostics/union.stderr | 18 + .../feature-gate-capture_disjoint_fields.rs | 18 + .../feature-gate-capture_disjoint_fields.stderr | 48 + .../filter-on-struct-member.rs | 41 + .../filter-on-struct-member.stderr | 26 + .../closures/2229_closure_analysis/issue-87378.rs | 26 + .../2229_closure_analysis/issue-87378.stderr | 48 + .../closures/2229_closure_analysis/issue-87987.rs | 27 + .../2229_closure_analysis/issue-87987.stderr | 14 + .../2229_closure_analysis/issue-88118-2.rs | 24 + .../2229_closure_analysis/issue-88118-2.stderr | 12 + .../closures/2229_closure_analysis/issue-88476.rs | 62 + .../2229_closure_analysis/issue-88476.stderr | 97 + .../closures/2229_closure_analysis/issue-89606.rs | 40 + .../2229_closure_analysis/issue-90465.fixed | 35 + .../closures/2229_closure_analysis/issue-90465.rs | 34 + .../2229_closure_analysis/issue-90465.stderr | 26 + .../issue-92724-needsdrop-query-cycle.rs | 14 + .../closures/2229_closure_analysis/issue_88118.rs | 15 + .../match/auxiliary/match_non_exhaustive_lib.rs | 10 + .../2229_closure_analysis/match/issue-87097.rs | 35 + .../2229_closure_analysis/match/issue-87097.stderr | 36 + .../2229_closure_analysis/match/issue-87426.rs | 14 + .../2229_closure_analysis/match/issue-87988.rs | 19 + .../2229_closure_analysis/match/issue-88331.rs | 33 + .../2229_closure_analysis/match/issue-88331.stderr | 39 + .../match/match-edge-cases_1.rs | 44 + .../match/match-edge-cases_2.rs | 37 + .../match/match-edge-cases_2.stderr | 17 + .../match/non-exhaustive-match.rs | 54 + .../match/non-exhaustive-match.stderr | 70 + .../match/pattern-matching-should-fail.rs | 79 + .../match/pattern-matching-should-fail.stderr | 88 + .../match/patterns-capture-analysis.rs | 137 + .../match/patterns-capture-analysis.stderr | 203 + .../migrations/auto_traits.fixed | 88 + .../migrations/auto_traits.rs | 87 + .../migrations/auto_traits.stderr | 67 + .../migrations/closure-body-macro-fragment.fixed | 33 + .../migrations/closure-body-macro-fragment.rs | 32 + .../migrations/closure-body-macro-fragment.stderr | 33 + .../migrations/insignificant_drop.fixed | 38 + .../migrations/insignificant_drop.rs | 38 + .../insignificant_drop_attr_migrations.fixed | 76 + .../insignificant_drop_attr_migrations.rs | 74 + .../insignificant_drop_attr_migrations.stderr | 45 + .../insignificant_drop_attr_no_migrations.rs | 45 + .../migrations/issue-78720.rs | 10 + .../migrations/issue-78720.stderr | 12 + .../migrations/issue-86753.rs | 34 + .../migrations/issue-90024-adt-correct-subst.rs | 37 + .../2229_closure_analysis/migrations/macro.fixed | 25 + .../2229_closure_analysis/migrations/macro.rs | 25 + .../2229_closure_analysis/migrations/macro.stderr | 22 + .../migrations/migrations_rustfix.fixed | 47 + .../migrations/migrations_rustfix.rs | 46 + .../migrations/migrations_rustfix.stderr | 41 + .../migrations/mir_calls_to_shims.fixed | 50 + .../migrations/mir_calls_to_shims.rs | 49 + .../migrations/mir_calls_to_shims.stderr | 26 + .../migrations/multi_diagnostics.fixed | 157 + .../migrations/multi_diagnostics.rs | 153 + .../migrations/multi_diagnostics.stderr | 118 + .../migrations/no_migrations.rs | 81 + .../2229_closure_analysis/migrations/old_name.rs | 9 + .../migrations/old_name.stderr | 10 + .../2229_closure_analysis/migrations/precise.fixed | 69 + .../2229_closure_analysis/migrations/precise.rs | 67 + .../migrations/precise.stderr | 55 + .../migrations/precise_no_migrations.rs | 104 + .../migrations/significant_drop.fixed | 229 + .../migrations/significant_drop.rs | 220 + .../migrations/significant_drop.stderr | 214 + .../migrations/unpin_no_migration.rs | 13 + .../closures/2229_closure_analysis/move_closure.rs | 222 + .../2229_closure_analysis/move_closure.stderr | 462 + .../2229_closure_analysis/multilevel-path-1.rs | 39 + .../2229_closure_analysis/multilevel-path-1.stderr | 48 + .../2229_closure_analysis/multilevel-path-2.rs | 33 + .../2229_closure_analysis/multilevel-path-2.stderr | 48 + .../2229_closure_analysis/nested-closure.rs | 53 + .../2229_closure_analysis/nested-closure.stderr | 106 + .../optimization/edge_case.rs | 34 + .../optimization/edge_case.stderr | 36 + .../optimization/edge_case_run_pass.rs | 27 + .../path-with-array-access.rs | 33 + .../path-with-array-access.stderr | 48 + .../preserve_field_drop_order.rs | 101 + .../preserve_field_drop_order.stderr | 228 + .../preserve_field_drop_order2.rs | 58 + ...ve_field_drop_order2.twenty_eighteen.run.stdout | 13 + ...e_field_drop_order2.twenty_twentyone.run.stdout | 13 + .../closures/2229_closure_analysis/repr_packed.rs | 101 + .../2229_closure_analysis/repr_packed.stderr | 161 + .../closures/2229_closure_analysis/run_pass/box.rs | 92 + .../2229_closure_analysis/run_pass/by_value.rs | 26 + .../run_pass/capture-disjoint-field-struct.rs | 24 + .../run_pass/capture-disjoint-field-tuple-mut.rs | 20 + .../run_pass/capture-disjoint-field-tuple.rs | 21 + .../run_pass/capture_with_wildcard_match.rs | 27 + .../destructure-pattern-closure-within-closure.rs | 21 + ...structure-pattern-closure-within-closure.stderr | 21 + .../run_pass/destructure_patterns.rs | 119 + .../run_pass/destructure_patterns.stderr | 39 + .../run_pass/disjoint-capture-in-same-closure.rs | 23 + .../run_pass/drop_then_use_fake_reads.rs | 11 + .../2229_closure_analysis/run_pass/edition.rs | 23 + .../run_pass/filter-on-struct-member.rs | 37 + .../2229_closure_analysis/run_pass/fru_syntax.rs | 42 + .../2229_closure_analysis/run_pass/issue-87378.rs | 16 + .../2229_closure_analysis/run_pass/issue-88372.rs | 19 + .../2229_closure_analysis/run_pass/issue-88431.rs | 59 + .../2229_closure_analysis/run_pass/issue-88476.rs | 47 + .../run_pass/lit-pattern-matching-with-methods.rs | 30 + .../2229_closure_analysis/run_pass/move_closure.rs | 93 + .../run_pass/multilevel-path-1.rs | 33 + .../run_pass/multilevel-path-2.rs | 31 + .../run_pass/multilevel-path-3.rs | 28 + .../2229_closure_analysis/run_pass/mut_ref.rs | 54 + .../run_pass/mut_ref_struct_mem.rs | 43 + .../run_pass/nested-closure.rs | 36 + .../struct-pattern-matching-with-methods.rs | 49 + .../tuple-struct-pattern-matching-with-methods.rs | 43 + .../2229_closure_analysis/run_pass/unsafe_ptr.rs | 47 + .../use_of_mutable_borrow_and_fake_reads.rs | 11 + .../simple-struct-min-capture.rs | 39 + .../simple-struct-min-capture.stderr | 56 + .../closures/2229_closure_analysis/unsafe_ptr.rs | 62 + .../2229_closure_analysis/unsafe_ptr.stderr | 93 + .../2229_closure_analysis/wild_patterns.rs | 73 + .../2229_closure_analysis/wild_patterns.stderr | 138 + .../ui/closures/add_semicolon_non_block_closure.rs | 11 + .../add_semicolon_non_block_closure.stderr | 16 + .../closures/binder/async-closure-with-binder.rs | 8 + .../binder/async-closure-with-binder.stderr | 16 + tests/ui/closures/binder/disallow-const.rs | 6 + tests/ui/closures/binder/disallow-const.stderr | 8 + tests/ui/closures/binder/disallow-ty.rs | 6 + tests/ui/closures/binder/disallow-ty.stderr | 8 + tests/ui/closures/binder/implicit-return.rs | 6 + tests/ui/closures/binder/implicit-return.stderr | 10 + tests/ui/closures/binder/implicit-stuff.rs | 27 + tests/ui/closures/binder/implicit-stuff.stderr | 107 + tests/ui/closures/binder/late-bound-in-body.rs | 9 + .../ui/closures/binder/nested-closures-regions.rs | 9 + .../closures/binder/nested-closures-regions.stderr | 38 + tests/ui/closures/binder/nested-closures.rs | 7 + ...gestion-for-introducing-lifetime-into-binder.rs | 7 + ...ion-for-introducing-lifetime-into-binder.stderr | 33 + tests/ui/closures/closure-array-break-length.rs | 7 + .../ui/closures/closure-array-break-length.stderr | 21 + ...sure-bounds-cant-promote-superkind-in-struct.rs | 11 + ...-bounds-cant-promote-superkind-in-struct.stderr | 19 + .../closure-bounds-static-cant-capture-borrowed.rs | 13 + ...sure-bounds-static-cant-capture-borrowed.stderr | 44 + tests/ui/closures/closure-bounds-subtype.rs | 16 + tests/ui/closures/closure-bounds-subtype.stderr | 25 + .../expect-region-supply-region-2.polonius.stderr | 37 + .../expect-region-supply-region-2.rs | 24 + .../expect-region-supply-region-2.stderr | 22 + .../expect-region-supply-region.rs | 57 + .../expect-region-supply-region.stderr | 23 + tests/ui/closures/closure-expected.rs | 5 + tests/ui/closures/closure-expected.stderr | 16 + .../closure-immutable-outer-variable.fixed | 13 + .../closures/closure-immutable-outer-variable.rs | 13 + .../closure-immutable-outer-variable.rs.fixed | 10 + .../closure-immutable-outer-variable.stderr | 11 + tests/ui/closures/closure-move-sync.rs | 22 + tests/ui/closures/closure-move-sync.stderr | 43 + tests/ui/closures/closure-no-fn-1.rs | 8 + tests/ui/closures/closure-no-fn-1.stderr | 19 + tests/ui/closures/closure-no-fn-2.rs | 8 + tests/ui/closures/closure-no-fn-2.stderr | 19 + tests/ui/closures/closure-no-fn-3.rs | 8 + tests/ui/closures/closure-no-fn-3.stderr | 9 + tests/ui/closures/closure-no-fn-4.rs | 8 + tests/ui/closures/closure-no-fn-4.stderr | 24 + tests/ui/closures/closure-no-fn-5.rs | 12 + tests/ui/closures/closure-no-fn-5.stderr | 23 + .../closure-referencing-itself-issue-25954.rs | 18 + .../closure-referencing-itself-issue-25954.stderr | 9 + tests/ui/closures/closure-reform-bad.rs | 12 + tests/ui/closures/closure-reform-bad.stderr | 26 + tests/ui/closures/closure-return-type-mismatch.rs | 17 + .../closures/closure-return-type-mismatch.stderr | 21 + .../closures/closure-return-type-must-be-sized.rs | 74 + .../closure-return-type-must-be-sized.stderr | 99 + tests/ui/closures/closure-wrong-kind.rs | 12 + tests/ui/closures/closure-wrong-kind.stderr | 21 + tests/ui/closures/closure_cap_coerce_many_fail.rs | 39 + .../closures/closure_cap_coerce_many_fail.stderr | 82 + .../closure_no_cap_coerce_many_check_pass.rs | 166 + .../closure_no_cap_coerce_many_run_pass.rs | 59 + .../closure_no_cap_coerce_many_unsafe_0.mir.stderr | 19 + .../closure_no_cap_coerce_many_unsafe_0.rs | 25 + ...closure_no_cap_coerce_many_unsafe_0.thir.stderr | 19 + .../closure_no_cap_coerce_many_unsafe_1.rs | 23 + tests/ui/closures/closure_promotion.rs | 5 + ...erce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr | 11 + .../coerce-unsafe-closure-to-unsafe-fn-ptr.rs | 8 + ...rce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr | 11 + tests/ui/closures/coerce-unsafe-to-closure.rs | 4 + tests/ui/closures/coerce-unsafe-to-closure.stderr | 16 + tests/ui/closures/deeply-nested_closures.rs | 23 + tests/ui/closures/diverging-closure.rs | 10 + tests/ui/closures/issue-101696.rs | 36 + .../closures/issue-102089-multiple-opaque-cast.rs | 17 + tests/ui/closures/issue-10398.rs | 9 + tests/ui/closures/issue-10398.stderr | 13 + .../issue-23012-supertrait-signature-inference.rs | 29 + tests/ui/closures/issue-41366.rs | 13 + tests/ui/closures/issue-42463.rs | 32 + tests/ui/closures/issue-46742.rs | 9 + tests/ui/closures/issue-48109.rs | 14 + tests/ui/closures/issue-52437.rs | 5 + tests/ui/closures/issue-52437.stderr | 20 + tests/ui/closures/issue-67123.rs | 5 + tests/ui/closures/issue-67123.stderr | 17 + tests/ui/closures/issue-6801.rs | 21 + tests/ui/closures/issue-6801.stderr | 16 + tests/ui/closures/issue-68025.rs | 12 + .../issue-72408-nested-closures-exponential.rs | 59 + tests/ui/closures/issue-78720.rs | 19 + tests/ui/closures/issue-78720.stderr | 53 + .../issue-80313-mutable-borrow-in-closure.rs | 7 + .../issue-80313-mutable-borrow-in-closure.stderr | 17 + .../issue-80313-mutable-borrow-in-move-closure.rs | 7 + ...sue-80313-mutable-borrow-in-move-closure.stderr | 17 + .../ui/closures/issue-80313-mutation-in-closure.rs | 7 + .../issue-80313-mutation-in-closure.stderr | 17 + .../issue-80313-mutation-in-move-closure.rs | 7 + .../issue-80313-mutation-in-move-closure.stderr | 17 + tests/ui/closures/issue-81700-mut-borrow.rs | 5 + tests/ui/closures/issue-81700-mut-borrow.stderr | 16 + tests/ui/closures/issue-82438-mut-without-upvar.rs | 28 + .../closures/issue-82438-mut-without-upvar.stderr | 14 + tests/ui/closures/issue-84044-drop-non-mut.rs | 6 + tests/ui/closures/issue-84044-drop-non-mut.stderr | 14 + tests/ui/closures/issue-84128.rs | 16 + tests/ui/closures/issue-84128.stderr | 24 + tests/ui/closures/issue-87461.rs | 29 + tests/ui/closures/issue-87461.stderr | 57 + tests/ui/closures/issue-87814-1.rs | 8 + tests/ui/closures/issue-87814-2.rs | 10 + tests/ui/closures/issue-90871.rs | 7 + tests/ui/closures/issue-90871.stderr | 26 + tests/ui/closures/issue-97607.rs | 12 + tests/ui/closures/issue-99565.rs | 7 + tests/ui/closures/issue-99565.stderr | 14 + tests/ui/closures/local-type-mix.rs | 17 + tests/ui/closures/local-type-mix.stderr | 51 + tests/ui/closures/multiple-fn-bounds.rs | 15 + tests/ui/closures/multiple-fn-bounds.stderr | 28 + tests/ui/closures/old-closure-arg-call-as.rs | 12 + tests/ui/closures/old-closure-arg.rs | 11 + tests/ui/closures/old-closure-explicit-types.rs | 6 + tests/ui/closures/old-closure-expr-precedence.rs | 62 + .../ui/closures/old-closure-expr-precedence.stderr | 10 + .../old-closure-expression-remove-semicolon.fixed | 12 + .../old-closure-expression-remove-semicolon.rs | 12 + .../old-closure-expression-remove-semicolon.stderr | 14 + tests/ui/closures/old-closure-fn-coerce.rs | 11 + tests/ui/closures/old-closure-iter-1.rs | 15 + tests/ui/closures/old-closure-iter-2.rs | 15 + tests/ui/closures/once-move-out-on-heap.rs | 18 + tests/ui/closures/print/closure-print-generic-1.rs | 23 + .../closures/print/closure-print-generic-1.stderr | 20 + tests/ui/closures/print/closure-print-generic-2.rs | 13 + .../closures/print/closure-print-generic-2.stderr | 20 + .../closure-print-generic-trim-off-verbose-2.rs | 16 + ...closure-print-generic-trim-off-verbose-2.stderr | 20 + .../print/closure-print-generic-verbose-1.rs | 24 + .../print/closure-print-generic-verbose-1.stderr | 20 + .../print/closure-print-generic-verbose-2.rs | 16 + .../print/closure-print-generic-verbose-2.stderr | 20 + tests/ui/closures/print/closure-print-verbose.rs | 12 + .../ui/closures/print/closure-print-verbose.stderr | 19 + tests/ui/closures/semistatement-in-lambda.rs | 12 + tests/ui/closures/supertrait-hint-cycle-2.rs | 18 + tests/ui/closures/supertrait-hint-cycle-3.rs | 16 + tests/ui/closures/supertrait-hint-cycle.rs | 65 + .../supertrait-hint-references-assoc-ty.rs | 17 + tests/ui/closures/thir-unsafeck-issue-85871.rs | 20 + .../cmse-nonsecure-call/gate_test.rs | 11 + .../cmse-nonsecure-call/gate_test.stderr | 12 + .../cmse-nonsecure-call/params-on-registers.rs | 24 + .../cmse-nonsecure-call/params-on-stack.rs | 27 + .../cmse-nonsecure-call/params-on-stack.stderr | 4 + .../cmse-nonsecure-call/wrong-abi-location-1.rs | 8 + .../wrong-abi-location-1.stderr | 9 + .../cmse-nonsecure-call/wrong-abi-location-2.rs | 10 + .../wrong-abi-location-2.stderr | 11 + .../cmse-nonsecure-entry/gate_test.rs | 11 + .../cmse-nonsecure-entry/gate_test.stderr | 19 + .../cmse-nonsecure-entry/issue-83475.rs | 9 + .../cmse-nonsecure-entry/issue-83475.stderr | 11 + .../cmse-nonsecure-entry/params-on-registers.rs | 16 + .../cmse-nonsecure-entry/params-on-stack.rs | 16 + .../cmse-nonsecure-entry/params-on-stack.stderr | 4 + .../cmse-nonsecure-entry/trustzone-only.rs | 10 + .../cmse-nonsecure-entry/trustzone-only.stderr | 9 + .../cmse-nonsecure-entry/wrong-abi.rs | 13 + .../cmse-nonsecure-entry/wrong-abi.stderr | 9 + tests/ui/codegen/auxiliary/issue-97708-aux.rs | 41 + tests/ui/codegen/auxiliary/llvm_pr32379.rs | 5 + tests/ui/codegen/init-large-type.rs | 23 + tests/ui/codegen/issue-101585-128bit-repeat.rs | 14 + tests/ui/codegen/issue-16602-1.rs | 6 + tests/ui/codegen/issue-16602-2.rs | 12 + tests/ui/codegen/issue-16602-3.rs | 28 + tests/ui/codegen/issue-28950.rs | 22 + tests/ui/codegen/issue-55976.rs | 13 + tests/ui/codegen/issue-63787.rs | 36 + tests/ui/codegen/issue-64401.rs | 51 + tests/ui/codegen/issue-82859-slice-miscompile.rs | 19 + .../issue-88043-bb-does-not-have-terminator.rs | 35 + tests/ui/codegen/issue-97708.rs | 9 + tests/ui/codegen/issue-99551.rs | 20 + tests/ui/codegen/llvm-pr32379.rs | 14 + tests/ui/codemap_tests/bad-format-args.rs | 5 + tests/ui/codemap_tests/bad-format-args.stderr | 22 + .../coherence-overlapping-inherent-impl-trait.rs | 6 + ...oherence-overlapping-inherent-impl-trait.stderr | 11 + tests/ui/codemap_tests/empty_span.rs | 8 + tests/ui/codemap_tests/empty_span.stderr | 9 + tests/ui/codemap_tests/huge_multispan_highlight.rs | 91 + .../codemap_tests/huge_multispan_highlight.stderr | 14 + tests/ui/codemap_tests/issue-11715.rs | 11 + tests/ui/codemap_tests/issue-11715.stderr | 14 + tests/ui/codemap_tests/issue-28308.rs | 4 + tests/ui/codemap_tests/issue-28308.stderr | 11 + tests/ui/codemap_tests/one_line.rs | 4 + tests/ui/codemap_tests/one_line.stderr | 24 + .../ui/codemap_tests/overlapping_inherent_impls.rs | 36 + .../overlapping_inherent_impls.stderr | 32 + tests/ui/codemap_tests/tab.rs | 9 + tests/ui/codemap_tests/tab.stderr | 18 + tests/ui/codemap_tests/tab_2.rs | 5 + tests/ui/codemap_tests/tab_2.stderr | 11 + tests/ui/codemap_tests/tab_3.rs | 9 + tests/ui/codemap_tests/tab_3.stderr | 22 + tests/ui/codemap_tests/two_files.rs | 7 + tests/ui/codemap_tests/two_files.stderr | 15 + tests/ui/codemap_tests/two_files_data.rs | 5 + tests/ui/codemap_tests/unicode.expanded.stdout | 13 + tests/ui/codemap_tests/unicode.normal.stderr | 11 + tests/ui/codemap_tests/unicode.rs | 7 + tests/ui/codemap_tests/unicode_2.rs | 5 + tests/ui/codemap_tests/unicode_2.stderr | 25 + tests/ui/codemap_tests/unicode_3.rs | 6 + tests/ui/codemap_tests/unicode_3.stderr | 10 + tests/ui/coercion/auxiliary/issue-39823.rs | 7 + tests/ui/coercion/coerce-block-tail-26978.rs | 11 + tests/ui/coercion/coerce-block-tail-26978.stderr | 16 + tests/ui/coercion/coerce-block-tail-57749.rs | 35 + tests/ui/coercion/coerce-block-tail-57749.stderr | 14 + tests/ui/coercion/coerce-block-tail-83783.rs | 13 + tests/ui/coercion/coerce-block-tail-83783.stderr | 12 + tests/ui/coercion/coerce-block-tail-83850.rs | 7 + tests/ui/coercion/coerce-block-tail-83850.stderr | 19 + tests/ui/coercion/coerce-block-tail.rs | 6 + tests/ui/coercion/coerce-block-tail.stderr | 16 + .../ui/coercion/coerce-expect-unsized-ascribed.rs | 32 + .../coercion/coerce-expect-unsized-ascribed.stderr | 129 + tests/ui/coercion/coerce-expect-unsized.rs | 43 + ...issue-49593-box-never-windows.nofallback.stderr | 19 + .../coerce-issue-49593-box-never-windows.rs | 58 + .../coerce-issue-49593-box-never.nofallback.stderr | 19 + tests/ui/coercion/coerce-issue-49593-box-never.rs | 58 + tests/ui/coercion/coerce-mut.rs | 10 + tests/ui/coercion/coerce-mut.stderr | 19 + .../coercion/coerce-overloaded-autoderef-fail.rs | 32 + .../coerce-overloaded-autoderef-fail.stderr | 46 + tests/ui/coercion/coerce-overloaded-autoderef.rs | 68 + tests/ui/coercion/coerce-reborrow-imm-ptr-arg.rs | 17 + tests/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs | 18 + tests/ui/coercion/coerce-reborrow-imm-vec-arg.rs | 19 + tests/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs | 16 + .../ui/coercion/coerce-reborrow-multi-arg-fail.rs | 6 + .../coercion/coerce-reborrow-multi-arg-fail.stderr | 19 + tests/ui/coercion/coerce-reborrow-multi-arg.rs | 9 + tests/ui/coercion/coerce-reborrow-mut-ptr-arg.rs | 25 + tests/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs | 27 + tests/ui/coercion/coerce-reborrow-mut-vec-arg.rs | 18 + tests/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs | 14 + tests/ui/coercion/coerce-to-bang-cast.rs | 12 + tests/ui/coercion/coerce-to-bang-cast.stderr | 15 + tests/ui/coercion/coerce-to-bang.rs | 79 + tests/ui/coercion/coerce-to-bang.stderr | 130 + tests/ui/coercion/coerce-unify-return.rs | 19 + tests/ui/coercion/coerce-unify.rs | 68 + tests/ui/coercion/coerce-unsize-subtype.rs | 40 + .../coercion-missing-tail-expected-type.fixed | 16 + .../coercion-missing-tail-expected-type.rs | 16 + .../coercion-missing-tail-expected-type.stderr | 26 + tests/ui/coercion/coercion-slice.rs | 7 + tests/ui/coercion/coercion-slice.stderr | 13 + tests/ui/coercion/issue-101066.rs | 16 + tests/ui/coercion/issue-14589.rs | 24 + tests/ui/coercion/issue-36007.rs | 20 + tests/ui/coercion/issue-37655.rs | 37 + tests/ui/coercion/issue-39823.rs | 25 + tests/ui/coercion/issue-53475.rs | 13 + tests/ui/coercion/issue-53475.stderr | 14 + tests/ui/coercion/issue-73886.rs | 6 + tests/ui/coercion/issue-73886.stderr | 17 + tests/ui/coercion/issue-88097.rs | 31 + tests/ui/coercion/retslot-cast.rs | 22 + tests/ui/coercion/retslot-cast.stderr | 15 + tests/ui/coercion/unsafe-coercion.rs | 17 + .../coherence/auxiliary/coherence_copy_like_lib.rs | 10 + .../auxiliary/coherence_fundamental_trait_lib.rs | 7 + .../auxiliary/coherence_inherent_cc_lib.rs | 11 + tests/ui/coherence/auxiliary/coherence_lib.rs | 15 + .../ui/coherence/auxiliary/coherence_orphan_lib.rs | 3 + tests/ui/coherence/auxiliary/error_lib.rs | 6 + tests/ui/coherence/auxiliary/go_trait.rs | 43 + tests/ui/coherence/auxiliary/option_future.rs | 8 + .../auxiliary/re_rebalance_coherence_lib-rpass.rs | 31 + .../auxiliary/re_rebalance_coherence_lib.rs | 22 + .../coherence/auxiliary/trait-with-const-param.rs | 1 + .../ui/coherence/auxiliary/trait_impl_conflict.rs | 6 + tests/ui/coherence/coherence-all-remote.rs | 9 + tests/ui/coherence/coherence-all-remote.stderr | 12 + tests/ui/coherence/coherence-bigint-int.rs | 13 + tests/ui/coherence/coherence-bigint-param.rs | 11 + tests/ui/coherence/coherence-bigint-param.stderr | 12 + tests/ui/coherence/coherence-bigint-vecint.rs | 13 + ...e-blanket-conflicts-with-blanket-implemented.rs | 30 + ...anket-conflicts-with-blanket-implemented.stderr | 12 + ...blanket-conflicts-with-blanket-unimplemented.rs | 25 + ...ket-conflicts-with-blanket-unimplemented.stderr | 12 + ...-blanket-conflicts-with-specific-cross-crate.rs | 20 + ...nket-conflicts-with-specific-cross-crate.stderr | 13 + ...lanket-conflicts-with-specific-multidispatch.rs | 27 + ...et-conflicts-with-specific-multidispatch.stderr | 12 + ...erence-blanket-conflicts-with-specific-trait.rs | 29 + ...ce-blanket-conflicts-with-specific-trait.stderr | 12 + .../coherence-blanket-conflicts-with-specific.rs | 24 + ...oherence-blanket-conflicts-with-specific.stderr | 12 + tests/ui/coherence/coherence-blanket.rs | 16 + .../coherence-conflicting-negative-trait-impl.rs | 17 + ...oherence-conflicting-negative-trait-impl.stderr | 22 + .../coherence/coherence-covered-type-parameter.rs | 14 + tests/ui/coherence/coherence-cow.re_a.stderr | 14 + tests/ui/coherence/coherence-cow.re_b.stderr | 14 + tests/ui/coherence/coherence-cow.re_c.stderr | 14 + tests/ui/coherence/coherence-cow.rs | 29 + .../ui/coherence/coherence-cross-crate-conflict.rs | 13 + .../coherence-cross-crate-conflict.stderr | 12 + tests/ui/coherence/coherence-default-trait-impl.rs | 16 + .../coherence/coherence-default-trait-impl.stderr | 28 + tests/ui/coherence/coherence-error-suppression.rs | 16 + .../coherence/coherence-error-suppression.stderr | 9 + .../coherence-fn-covariant-bound-vs-static.rs | 26 + .../coherence-fn-covariant-bound-vs-static.stderr | 13 + tests/ui/coherence/coherence-fn-implied-bounds.rs | 26 + .../coherence/coherence-fn-implied-bounds.stderr | 20 + tests/ui/coherence/coherence-fn-inputs.rs | 25 + tests/ui/coherence/coherence-fn-inputs.stderr | 13 + .../ui/coherence/coherence-free-vs-bound-region.rs | 21 + .../coherence-free-vs-bound-region.stderr | 20 + .../coherence-fundamental-trait-objects.rs | 15 + .../coherence-fundamental-trait-objects.stderr | 14 + tests/ui/coherence/coherence-impl-in-fn.rs | 14 + ...herence-impl-trait-for-marker-trait-negative.rs | 30 + ...nce-impl-trait-for-marker-trait-negative.stderr | 39 + ...herence-impl-trait-for-marker-trait-positive.rs | 30 + ...nce-impl-trait-for-marker-trait-positive.stderr | 39 + .../coherence-impl-trait-for-trait-object-safe.rs | 10 + ...herence-impl-trait-for-trait-object-safe.stderr | 18 + .../ui/coherence/coherence-impl-trait-for-trait.rs | 20 + .../coherence-impl-trait-for-trait.stderr | 21 + tests/ui/coherence/coherence-impls-copy.rs | 36 + tests/ui/coherence/coherence-impls-copy.stderr | 76 + tests/ui/coherence/coherence-impls-send.rs | 28 + tests/ui/coherence/coherence-impls-send.stderr | 43 + tests/ui/coherence/coherence-impls-sized.rs | 36 + tests/ui/coherence/coherence-impls-sized.stderr | 73 + .../coherence-inherited-assoc-ty-cycle-err.rs | 24 + .../coherence-inherited-assoc-ty-cycle-err.stderr | 26 + .../coherence-inherited-subtyping.old.stderr | 14 + .../coherence-inherited-subtyping.re.stderr | 14 + .../ui/coherence/coherence-inherited-subtyping.rs | 21 + .../coherence/coherence-iterator-vec-any-elem.rs | 14 + tests/ui/coherence/coherence-iterator-vec.rs | 14 + .../ui/coherence/coherence-lone-type-parameter.rs | 10 + .../coherence/coherence-lone-type-parameter.stderr | 12 + .../ui/coherence/coherence-multidispatch-tuple.rs | 24 + .../coherence/coherence-negative-impls-copy-bad.rs | 11 + .../coherence-negative-impls-copy-bad.stderr | 36 + .../ui/coherence/coherence-negative-impls-copy.rs | 29 + .../coherence-negative-impls-safe-rpass.rs | 13 + .../ui/coherence/coherence-negative-impls-safe.rs | 10 + .../coherence/coherence-negative-impls-safe.stderr | 12 + .../coherence-negative-inherent-where-bounds.rs | 25 + tests/ui/coherence/coherence-negative-inherent.rs | 22 + .../coherence-negative-outlives-lifetimes.rs | 17 + ...erence-negative-outlives-lifetimes.stock.stderr | 11 + .../coherence-no-direct-lifetime-dispatch.rs | 9 + .../coherence-no-direct-lifetime-dispatch.stderr | 11 + tests/ui/coherence/coherence-orphan.rs | 20 + tests/ui/coherence/coherence-orphan.stderr | 26 + .../coherence/coherence-overlap-all-t-and-tuple.rs | 20 + .../coherence-overlap-all-t-and-tuple.stderr | 12 + .../coherence/coherence-overlap-double-negative.rs | 12 + .../coherence-overlap-downstream-inherent.rs | 17 + .../coherence-overlap-downstream-inherent.stderr | 23 + tests/ui/coherence/coherence-overlap-downstream.rs | 17 + .../coherence/coherence-overlap-downstream.stderr | 21 + .../coherence-overlap-issue-23516-inherent.rs | 13 + .../coherence-overlap-issue-23516-inherent.stderr | 14 + .../ui/coherence/coherence-overlap-issue-23516.rs | 11 + .../coherence/coherence-overlap-issue-23516.stderr | 13 + tests/ui/coherence/coherence-overlap-messages.rs | 28 + .../ui/coherence/coherence-overlap-messages.stderr | 44 + .../coherence-overlap-negate-alias-strict.rs | 19 + ...oherence-overlap-negate-not-use-feature-gate.rs | 8 + ...ence-overlap-negate-not-use-feature-gate.stderr | 11 + .../coherence/coherence-overlap-negate-strict.rs | 18 + .../coherence-overlap-negate-use-feature-gate.rs | 11 + .../coherence/coherence-overlap-negative-trait.rs | 16 + .../coherence/coherence-overlap-negative-trait2.rs | 17 + .../coherence/coherence-overlap-super-negative.rs | 18 + .../ui/coherence/coherence-overlap-trait-alias.rs | 20 + .../coherence/coherence-overlap-trait-alias.stderr | 17 + .../coherence-overlap-upstream-inherent.rs | 16 + .../coherence-overlap-upstream-inherent.stderr | 14 + tests/ui/coherence/coherence-overlap-upstream.rs | 16 + .../ui/coherence/coherence-overlap-upstream.stderr | 13 + .../ui/coherence/coherence-overlap-with-regions.rs | 16 + tests/ui/coherence/coherence-overlapping-pairs.rs | 11 + .../coherence/coherence-overlapping-pairs.stderr | 14 + .../coherence-pair-covered-uncovered-1.rs | 15 + .../coherence-pair-covered-uncovered-1.stderr | 15 + .../coherence/coherence-pair-covered-uncovered.rs | 11 + .../coherence-pair-covered-uncovered.stderr | 14 + .../coherence-projection-conflict-orphan.rs | 19 + .../coherence-projection-conflict-orphan.stderr | 14 + .../coherence-projection-conflict-ty-param.rs | 13 + .../coherence-projection-conflict-ty-param.stderr | 12 + .../ui/coherence/coherence-projection-conflict.rs | 18 + .../coherence/coherence-projection-conflict.stderr | 12 + .../ui/coherence/coherence-projection-ok-orphan.rs | 17 + tests/ui/coherence/coherence-projection-ok.rs | 17 + tests/ui/coherence/coherence-rfc447-constrained.rs | 22 + tests/ui/coherence/coherence-subtyping.rs | 20 + tests/ui/coherence/coherence-subtyping.stderr | 16 + tests/ui/coherence/coherence-tuple-conflict.rs | 20 + tests/ui/coherence/coherence-tuple-conflict.stderr | 12 + .../coherence-unsafe-trait-object-impl.rs | 18 + .../coherence-unsafe-trait-object-impl.stderr | 17 + tests/ui/coherence/coherence-vec-local-2.rs | 14 + tests/ui/coherence/coherence-vec-local-2.stderr | 14 + tests/ui/coherence/coherence-vec-local.rs | 14 + tests/ui/coherence/coherence-vec-local.stderr | 14 + tests/ui/coherence/coherence-wasm-bindgen.rs | 37 + tests/ui/coherence/coherence-wasm-bindgen.stderr | 21 + tests/ui/coherence/coherence-where-clause.rs | 38 + tests/ui/coherence/coherence-with-closure.rs | 14 + tests/ui/coherence/coherence-with-closure.stderr | 11 + tests/ui/coherence/coherence-with-generator.rs | 24 + .../coherence-with-generator.stock.stderr | 11 + tests/ui/coherence/coherence_copy_like.rs | 19 + .../coherence_copy_like_err_fundamental_struct.rs | 24 + ...herence_copy_like_err_fundamental_struct_ref.rs | 21 + ...rence_copy_like_err_fundamental_struct_tuple.rs | 20 + ...e_copy_like_err_fundamental_struct_tuple.stderr | 14 + .../ui/coherence/coherence_copy_like_err_struct.rs | 22 + .../coherence_copy_like_err_struct.stderr | 14 + .../ui/coherence/coherence_copy_like_err_tuple.rs | 21 + .../coherence/coherence_copy_like_err_tuple.stderr | 14 + tests/ui/coherence/coherence_inherent.rs | 36 + tests/ui/coherence/coherence_inherent.stderr | 15 + tests/ui/coherence/coherence_inherent_cc.rs | 28 + tests/ui/coherence/coherence_inherent_cc.stderr | 15 + tests/ui/coherence/coherence_local.rs | 20 + tests/ui/coherence/coherence_local_err_struct.rs | 18 + .../ui/coherence/coherence_local_err_struct.stderr | 14 + tests/ui/coherence/coherence_local_err_tuple.rs | 18 + .../ui/coherence/coherence_local_err_tuple.stderr | 14 + tests/ui/coherence/coherence_local_ref.rs | 14 + tests/ui/coherence/conflicting-impl-with-err.rs | 16 + .../ui/coherence/conflicting-impl-with-err.stderr | 15 + .../ui/coherence/const-generics-orphan-check-ok.rs | 28 + tests/ui/coherence/deep-bad-copy-reason.rs | 40 + tests/ui/coherence/deep-bad-copy-reason.stderr | 18 + tests/ui/coherence/impl-foreign-for-foreign.rs | 15 + tests/ui/coherence/impl-foreign-for-foreign.stderr | 14 + .../coherence/impl-foreign-for-foreign[foreign].rs | 23 + .../impl-foreign-for-foreign[foreign].stderr | 39 + .../coherence/impl-foreign-for-foreign[local].rs | 14 + .../impl-foreign-for-fundamental[foreign].rs | 19 + .../impl-foreign-for-fundamental[foreign].stderr | 27 + .../impl-foreign-for-fundamental[local].rs | 15 + tests/ui/coherence/impl-foreign-for-local.rs | 13 + ...impl-foreign-for-locally-defined-fundamental.rs | 15 + ...ign-for-locally-defined-fundamental[foreign].rs | 15 + .../coherence/impl-foreign[foreign]-for-foreign.rs | 15 + .../impl-foreign[foreign]-for-foreign.stderr | 15 + .../coherence/impl-foreign[foreign]-for-local.rs | 14 + ...pl-foreign[fundemental[foreign]]-for-foreign.rs | 24 + ...oreign[fundemental[foreign]]-for-foreign.stderr | 42 + ...impl-foreign[fundemental[local]]-for-foreign.rs | 16 + .../ui/coherence/impl[t]-foreign-for-foreign[t].rs | 21 + .../impl[t]-foreign-for-foreign[t].stderr | 25 + .../impl[t]-foreign-for-fundamental[t].rs | 15 + .../impl[t]-foreign-for-fundamental[t].stderr | 12 + ...mpl[t]-foreign[foreign[t]_local]-for-foreign.rs | 12 + .../impl[t]-foreign[foreign]-for-fundamental[t].rs | 18 + ...l[t]-foreign[foreign]-for-fundamental[t].stderr | 21 + .../ui/coherence/impl[t]-foreign[foreign]-for-t.rs | 14 + .../impl[t]-foreign[foreign]-for-t.stderr | 12 + .../impl[t]-foreign[fundamental[t]]-for-foreign.rs | 18 + ...l[t]-foreign[fundamental[t]]-for-foreign.stderr | 21 + ...]-foreign[fundamental[t]]-for-fundamental[t].rs | 17 + ...reign[fundamental[t]]-for-fundamental[t].stderr | 21 + .../impl[t]-foreign[fundamental[t]]-for-local.rs | 15 + .../impl[t]-foreign[fundamental[t]]-for-t.rs | 17 + .../impl[t]-foreign[fundamental[t]]-for-t.stderr | 21 + ...t]-foreign[fundamental[t]_local]-for-foreign.rs | 18 + ...oreign[fundamental[t]_local]-for-foreign.stderr | 21 + ...]-foreign[fundemental[local]]-for-foreign[t].rs | 15 + .../impl[t]-foreign[local]-for-foreign.rs | 14 + .../impl[t]-foreign[local]-for-foreign[t].rs | 15 + ...]-foreign[local]-for-fundamental[foreign[t]].rs | 17 + .../impl[t]-foreign[local]-for-fundamental[t].rs | 18 + ...mpl[t]-foreign[local]-for-fundamental[t].stderr | 21 + .../coherence/impl[t]-foreign[local]-for-local.rs | 13 + tests/ui/coherence/impl[t]-foreign[local]-for-t.rs | 14 + .../coherence/impl[t]-foreign[local]-for-t.stderr | 12 + ...t]-foreign[local_fundamental[t]]-for-foreign.rs | 17 + .../ui/coherence/impl[t]-foreign[t]-for-foreign.rs | 14 + .../impl[t]-foreign[t]-for-foreign.stderr | 12 + .../impl[t]-foreign[t]-for-fundamental.rs | 18 + .../impl[t]-foreign[t]-for-fundamental.stderr | 21 + tests/ui/coherence/impl[t]-foreign[t]-for-local.rs | 13 + tests/ui/coherence/impl[t]-foreign[t]-for-t.rs | 14 + tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr | 12 + .../inter-crate-ambiguity-causes-notes.rs | 19 + .../inter-crate-ambiguity-causes-notes.stderr | 14 + tests/ui/coherence/issue-85026.rs | 10 + tests/ui/coherence/issue-85026.stderr | 19 + tests/ui/coherence/issue-99663-2.rs | 22 + tests/ui/coherence/issue-99663.rs | 22 + ...ce-coherence-default-generic-associated-type.rs | 26 + tests/ui/coherence/re-rebalance-coherence.rs | 11 + .../strict-coherence-needs-negative-coherence.rs | 7 + ...trict-coherence-needs-negative-coherence.stderr | 10 + tests/ui/command-line-diagnostics.rs | 7 + tests/ui/command-line-diagnostics.stderr | 14 + tests/ui/command/command-argv0.rs | 30 + tests/ui/command/command-create-pidfd.rs | 56 + tests/ui/command/command-current-dir.rs | 50 + tests/ui/command/command-exec.rs | 104 + tests/ui/command/command-pre-exec.rs | 106 + tests/ui/command/command-setgroups.rs | 26 + tests/ui/command/command-uid-gid.rs | 32 + tests/ui/command/issue-10626.rs | 26 + tests/ui/commandline-argfile-badutf8.args | 2 + tests/ui/commandline-argfile-badutf8.rs | 12 + tests/ui/commandline-argfile-badutf8.stderr | 2 + tests/ui/commandline-argfile-missing.rs | 14 + tests/ui/commandline-argfile-missing.stderr | 2 + tests/ui/commandline-argfile.args | 2 + tests/ui/commandline-argfile.rs | 13 + tests/ui/compare-method/bad-self-type.rs | 26 + tests/ui/compare-method/bad-self-type.stderr | 50 + tests/ui/compare-method/issue-90444.rs | 17 + tests/ui/compare-method/issue-90444.stderr | 27 + tests/ui/compare-method/proj-outlives-region.rs | 14 + .../ui/compare-method/proj-outlives-region.stderr | 12 + tests/ui/compare-method/region-extra-2.rs | 15 + tests/ui/compare-method/region-extra-2.stderr | 17 + tests/ui/compare-method/region-extra.rs | 14 + tests/ui/compare-method/region-extra.stderr | 18 + tests/ui/compare-method/region-unrelated.rs | 15 + tests/ui/compare-method/region-unrelated.stderr | 12 + tests/ui/compare-method/reordered-type-param.rs | 19 + .../ui/compare-method/reordered-type-param.stderr | 24 + .../trait-bound-on-type-parameter.rs | 18 + .../trait-bound-on-type-parameter.stderr | 12 + tests/ui/compare-method/traits-misc-mismatch-1.rs | 71 + .../compare-method/traits-misc-mismatch-1.stderr | 66 + tests/ui/compare-method/traits-misc-mismatch-2.rs | 23 + .../compare-method/traits-misc-mismatch-2.stderr | 12 + tests/ui/compile_error_macro.rs | 3 + tests/ui/compile_error_macro.stderr | 8 + .../ui/compiletest-self-test/compile-flags-last.rs | 7 + .../compile-flags-last.stderr | 2 + .../ui/compiletest-self-test/ui-testing-optout.rs | 94 + .../compiletest-self-test/ui-testing-optout.stderr | 27 + tests/ui/complex.rs | 38 + .../auxiliary/namespaced_enums.rs | 10 + .../conditional-compilation/cfg-arg-invalid-1.rs | 3 + .../cfg-arg-invalid-1.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-2.rs | 3 + .../cfg-arg-invalid-2.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-3.rs | 3 + .../cfg-arg-invalid-3.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-4.rs | 3 + .../cfg-arg-invalid-4.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-5.rs | 3 + .../cfg-arg-invalid-5.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-6.rs | 3 + .../cfg-arg-invalid-6.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-7.rs | 5 + .../cfg-arg-invalid-7.stderr | 4 + .../conditional-compilation/cfg-arg-invalid-8.rs | 3 + .../cfg-arg-invalid-8.stderr | 2 + .../conditional-compilation/cfg-arg-invalid-9.rs | 4 + .../cfg-arg-invalid-9.stderr | 2 + tests/ui/conditional-compilation/cfg-attr-cfg-2.rs | 9 + .../conditional-compilation/cfg-attr-cfg-2.stderr | 9 + .../ui/conditional-compilation/cfg-attr-crate-2.rs | 8 + .../cfg-attr-crate-2.stderr | 12 + .../cfg-attr-empty-is-unused.rs | 13 + .../cfg-attr-empty-is-unused.stderr | 21 + .../cfg-attr-invalid-predicate.rs | 4 + .../cfg-attr-invalid-predicate.stderr | 9 + .../cfg-attr-multi-false.rs | 19 + .../cfg-attr-multi-invalid-1.rs | 7 + .../cfg-attr-multi-invalid-1.stderr | 12 + .../cfg-attr-multi-invalid-2.rs | 7 + .../cfg-attr-multi-invalid-2.stderr | 12 + .../conditional-compilation/cfg-attr-multi-true.rs | 21 + .../cfg-attr-multi-true.stderr | 40 + tests/ui/conditional-compilation/cfg-attr-parse.rs | 55 + .../conditional-compilation/cfg-attr-parse.stderr | 86 + .../cfg-attr-syntax-validation.rs | 39 + .../cfg-attr-syntax-validation.stderr | 82 + .../cfg-attr-unknown-attribute-macro-expansion.rs | 11 + ...g-attr-unknown-attribute-macro-expansion.stderr | 13 + .../conditional-compilation/cfg-empty-codemap.rs | 8 + .../cfg-empty-codemap.stderr | 2 + .../conditional-compilation/cfg-generic-params.rs | 40 + .../cfg-generic-params.stderr | 50 + tests/ui/conditional-compilation/cfg-in-crate-1.rs | 3 + .../conditional-compilation/cfg-in-crate-1.stderr | 9 + .../ui/conditional-compilation/cfg-non-opt-expr.rs | 11 + .../cfg-non-opt-expr.stderr | 20 + .../conditional-compilation/cfg_accessible-bugs.rs | 18 + .../cfg_accessible-bugs.stderr | 16 + .../cfg_accessible-input-validation.rs | 24 + .../cfg_accessible-input-validation.stderr | 44 + .../cfg_accessible-not_sure.edition2015.stderr | 122 + .../cfg_accessible-not_sure.edition2021.stderr | 122 + .../cfg_accessible-not_sure.rs | 89 + .../cfg_accessible-private.rs | 21 + .../cfg_accessible-stuck.rs | 9 + .../cfg_accessible-stuck.stderr | 8 + .../cfg_accessible-unstable.rs | 2 + .../cfg_accessible-unstable.stderr | 12 + tests/ui/conditional-compilation/cfg_accessible.rs | 55 + .../conditional-compilation/cfg_accessible.stderr | 27 + tests/ui/conditional-compilation/cfg_attr_path.rs | 13 + .../inner-cfg-non-inline-mod.rs | 7 + tests/ui/conditional-compilation/issue-34028.rs | 10 + .../ui/conditional-compilation/module_with_cfg.rs | 3 + tests/ui/conditional-compilation/test-cfg.rs | 8 + tests/ui/conditional-compilation/test-cfg.stderr | 9 + tests/ui/conflicting-repr-hints.rs | 80 + tests/ui/conflicting-repr-hints.stderr | 83 + tests/ui/confuse-field-and-method/issue-18343.rs | 9 + .../ui/confuse-field-and-method/issue-18343.stderr | 17 + tests/ui/confuse-field-and-method/issue-2392.rs | 69 + .../ui/confuse-field-and-method/issue-2392.stderr | 151 + tests/ui/confuse-field-and-method/issue-32128.rs | 15 + .../ui/confuse-field-and-method/issue-32128.stderr | 17 + tests/ui/confuse-field-and-method/issue-33784.rs | 33 + .../ui/confuse-field-and-method/issue-33784.stderr | 36 + tests/ui/confuse-field-and-method/private-field.rs | 19 + .../confuse-field-and-method/private-field.stderr | 12 + tests/ui/conservative_impl_trait.rs | 7 + tests/ui/conservative_impl_trait.stderr | 11 + tests/ui/const-generics/apit-with-const-param.rs | 7 + tests/ui/const-generics/arg-in-pat-1.rs | 23 + tests/ui/const-generics/arg-in-pat-2.rs | 10 + tests/ui/const-generics/arg-in-pat-3.rs | 43 + tests/ui/const-generics/argument_order.rs | 15 + tests/ui/const-generics/argument_order.stderr | 18 + .../array-impls/alloc-traits-impls-length-32.rs | 48 + .../array-impls/alloc-traits-impls-length-33.rs | 40 + .../array-impls/alloc-types-impls-length-33.rs | 25 + .../array-impls/core-traits-impls-length-32.rs | 66 + .../array-impls/core-traits-impls-length-33.rs | 66 + .../array-impls/into-iter-impls-length-32.rs | 40 + .../array-impls/into-iter-impls-length-33.rs | 40 + .../ui/const-generics/array-wrapper-struct-ctor.rs | 14 + .../ui/const-generics/assoc_const_eq_diagnostic.rs | 18 + .../assoc_const_eq_diagnostic.stderr | 33 + .../const-generics/associated-type-bound-fail.rs | 12 + .../associated-type-bound-fail.stderr | 16 + tests/ui/const-generics/associated-type-bound.rs | 19 + .../const-generics/auxiliary/const_generic_lib.rs | 7 + tests/ui/const-generics/auxiliary/crayte.rs | 16 + .../const-generics/auxiliary/generics_of_parent.rs | 23 + .../auxiliary/generics_of_parent_impl_trait.rs | 8 + .../auxiliary/legacy-const-generics.rs | 6 + .../backcompat/trait-resolution-breakage.rs | 18 + .../backcompat/unevaluated-consts.rs | 18 + tests/ui/const-generics/bad-const-generic-exprs.rs | 22 + .../const-generics/bad-const-generic-exprs.stderr | 59 + tests/ui/const-generics/broken-mir-1.rs | 13 + tests/ui/const-generics/broken-mir-2.rs | 10 + .../cannot-infer-type-for-const-param.rs | 10 + tests/ui/const-generics/coerce_unsized_array.rs | 8 + .../ui/const-generics/concrete-const-as-fn-arg.rs | 11 + .../const-generics/concrete-const-impl-method.rs | 21 + .../const-generics/condition-in-trait-const-arg.rs | 14 + .../const-arg-in-const-arg.full.stderr | 162 + .../const-arg-in-const-arg.min.stderr | 359 + tests/ui/const-generics/const-arg-in-const-arg.rs | 60 + tests/ui/const-generics/const-arg-in-fn.rs | 9 + .../const-arg-type-arg-misordered.rs | 8 + .../const-arg-type-arg-misordered.stderr | 9 + .../const-argument-cross-crate-mismatch.rs | 10 + .../const-argument-cross-crate-mismatch.stderr | 31 + .../const-generics/const-argument-cross-crate.rs | 13 + .../const-argument-if-length.full.stderr | 35 + .../const-argument-if-length.min.stderr | 36 + .../ui/const-generics/const-argument-if-length.rs | 22 + .../const-argument-non-static-lifetime.min.stderr | 12 + .../const-argument-non-static-lifetime.rs | 21 + .../ui/const-generics/const-fn-with-const-param.rs | 10 + .../const-generic-default-wont-borrowck.rs | 5 + .../const-generic-default-wont-borrowck.stderr | 16 + tests/ui/const-generics/const-generic-function.rs | 21 + .../const-generics/const-generic-function.stderr | 54 + tests/ui/const-generics/const-generic-type_name.rs | 8 + .../const-param-after-const-literal-arg.rs | 7 + .../const-param-before-other-params.rs | 7 + .../const-param-before-other-params.stderr | 8 + .../const-param-elided-lifetime.full.stderr | 33 + .../const-param-elided-lifetime.min.stderr | 78 + .../const-generics/const-param-elided-lifetime.rs | 30 + tests/ui/const-generics/const-param-in-async.rs | 31 + ...t-param-type-depends-on-const-param.full.stderr | 15 + ...st-param-type-depends-on-const-param.min.stderr | 33 + .../const-param-type-depends-on-const-param.rs | 19 + ...nst-param-type-depends-on-type-param-ungated.rs | 9 + ...param-type-depends-on-type-param-ungated.stderr | 9 + ...st-param-type-depends-on-type-param.full.stderr | 19 + ...nst-param-type-depends-on-type-param.min.stderr | 19 + .../const-param-type-depends-on-type-param.rs | 15 + .../const-parameter-uppercase-lint.rs | 7 + .../const-parameter-uppercase-lint.stderr | 14 + .../const-generics/const_trait_fn-issue-88433.rs | 27 + tests/ui/const-generics/core-types.rs | 50 + tests/ui/const-generics/cross_crate_complex.rs | 23 + .../defaults/auxiliary/const_defaulty.rs | 11 + .../auxiliary/trait_object_lt_defaults_lib.rs | 1 + .../complex-generic-default-expr.min.stderr | 20 + .../defaults/complex-generic-default-expr.rs | 12 + .../const-generics/defaults/complex-unord-param.rs | 17 + tests/ui/const-generics/defaults/const-default.rs | 24 + .../defaults/const-param-as-default-value.rs | 21 + .../defaults/const-param-in-ty-defaults.rs | 12 + .../const-generics/defaults/default-annotation.rs | 17 + .../default-const-param-cannot-reference-self.rs | 14 + ...efault-const-param-cannot-reference-self.stderr | 21 + .../ui/const-generics/defaults/default-on-impl.rs | 6 + .../const-generics/defaults/default-on-impl.stderr | 8 + .../defaults/default-param-wf-concrete.rs | 3 + .../defaults/default-param-wf-concrete.stderr | 9 + tests/ui/const-generics/defaults/doesnt_infer.rs | 13 + .../ui/const-generics/defaults/doesnt_infer.stderr | 14 + tests/ui/const-generics/defaults/external.rs | 24 + .../ui/const-generics/defaults/forward-declared.rs | 13 + .../defaults/forward-declared.stderr | 27 + .../defaults/generic-expr-default-concrete.rs | 14 + .../defaults/generic-expr-default-concrete.stderr | 12 + .../generic-expr-default-mismatched-types.rs | 16 + .../generic-expr-default-mismatched-types.stderr | 12 + .../defaults/generic-expr-default.rs | 24 + .../defaults/generic-expr-default.stderr | 18 + .../const-generics/defaults/intermixed-lifetime.rs | 9 + .../defaults/intermixed-lifetime.stderr | 14 + tests/ui/const-generics/defaults/mismatch.rs | 22 + tests/ui/const-generics/defaults/mismatch.stderr | 58 + .../defaults/mismatched_ty_const_in_trait_impl.rs | 41 + .../mismatched_ty_const_in_trait_impl.stderr | 68 + .../param-order-err-pretty-prints-default.rs | 4 + .../param-order-err-pretty-prints-default.stderr | 8 + .../const-generics/defaults/pretty-printing-ast.rs | 11 + .../defaults/pretty-printing-ast.stdout | 18 + .../const-generics/defaults/repr-c-issue-82792.rs | 11 + tests/ui/const-generics/defaults/rp_impl_trait.rs | 29 + .../const-generics/defaults/rp_impl_trait_fail.rs | 30 + .../defaults/rp_impl_trait_fail.stderr | 36 + .../ui/const-generics/defaults/self-referential.rs | 4 + .../defaults/self-referential.stderr | 11 + .../ui/const-generics/defaults/simple-defaults.rs | 13 + .../defaults/trait_object_lt_defaults.rs | 24 + tests/ui/const-generics/defaults/trait_objects.rs | 43 + .../const-generics/defaults/trait_objects_fail.rs | 30 + .../defaults/trait_objects_fail.stderr | 21 + .../defaults/type-default-const-param-name.rs | 14 + tests/ui/const-generics/defaults/wfness.rs | 23 + tests/ui/const-generics/defaults/wfness.stderr | 34 + tests/ui/const-generics/defaults/wrong-order.rs | 9 + .../ui/const-generics/defaults/wrong-order.stderr | 14 + .../ui/const-generics/deref-into-array-generic.rs | 27 + .../different_generic_args.full.stderr | 12 + .../different_generic_args.min.stderr | 12 + tests/ui/const-generics/different_generic_args.rs | 13 + .../const-generics/different_generic_args_array.rs | 11 + .../different_generic_args_array.stderr | 12 + .../dont-evaluate-array-len-on-err-1.rs | 22 + .../dont-evaluate-array-len-on-err-1.stderr | 9 + tests/ui/const-generics/dyn-supertraits.rs | 80 + .../ui/const-generics/early/closing-args-token.rs | 26 + .../const-generics/early/closing-args-token.stderr | 52 + .../early/const-expression-parameter.rs | 19 + .../early/const-expression-parameter.stderr | 13 + .../early/const-param-from-outer-fn.rs | 7 + .../early/const-param-from-outer-fn.stderr | 13 + .../ui/const-generics/early/const-param-hygiene.rs | 17 + .../const-generics/early/const-param-shadowing.rs | 7 + .../early/const-param-shadowing.stderr | 14 + .../early/invalid-const-arguments.rs | 16 + .../early/invalid-const-arguments.stderr | 73 + .../ui/const-generics/early/macro_rules-braces.rs | 73 + .../const-generics/early/macro_rules-braces.stderr | 60 + tests/ui/const-generics/ensure_is_evaluatable.rs | 20 + .../ui/const-generics/ensure_is_evaluatable.stderr | 18 + tests/ui/const-generics/enum-variants.rs | 24 + tests/ui/const-generics/exhaustive-value.rs | 267 + tests/ui/const-generics/exhaustive-value.stderr | 20 + .../expose-default-substs-param-env.rs | 9 + .../float-generic.adt_const_params.stderr | 11 + tests/ui/const-generics/float-generic.rs | 12 + .../ui/const-generics/float-generic.simple.stderr | 11 + .../const-generics/fn-const-param-call.full.stderr | 15 + .../const-generics/fn-const-param-call.min.stderr | 14 + tests/ui/const-generics/fn-const-param-call.rs | 22 + .../fn-const-param-infer.full.stderr | 9 + .../const-generics/fn-const-param-infer.min.stderr | 8 + tests/ui/const-generics/fn-const-param-infer.rs | 29 + .../ui/const-generics/fn_with_two_const_inputs.rs | 23 + .../const-generics/fn_with_two_const_inputs.stderr | 18 + .../fn_with_two_same_const_inputs.rs | 22 + .../forbid-non-structural_match-types.rs | 13 + .../forbid-non-structural_match-types.stderr | 9 + .../const-generics/foreign-item-const-parameter.rs | 7 + .../foreign-item-const-parameter.stderr | 19 + tests/ui/const-generics/generic-param-mismatch.rs | 5 + .../const-generics/generic-param-mismatch.stderr | 14 + .../generic_arg_infer/array-repeat-expr.rs | 13 + .../generic_arg_infer/dont-use-defaults.rs | 15 + .../generic_arg_infer/in-signature.rs | 61 + .../generic_arg_infer/in-signature.stderr | 119 + .../generic_arg_infer/infer-arg-test.rs | 22 + .../generic_arg_infer/infer-arg-test.stderr | 24 + .../generic_arg_infer/infer_arg_and_const_arg.rs | 12 + .../generic_arg_infer/issue-91614.rs | 8 + .../generic_arg_infer/issue-91614.stderr | 23 + .../abstract-const-as-cast-1.rs | 18 + .../abstract-const-as-cast-2.rs | 20 + .../abstract-const-as-cast-2.stderr | 26 + .../abstract-const-as-cast-3.rs | 47 + .../abstract-const-as-cast-3.stderr | 187 + .../abstract-const-as-cast-4.rs | 29 + .../abstract-consts-as-cast-5.rs | 11 + .../abstract-consts-as-cast-5.stderr | 10 + .../array-size-in-generic-struct-param.full.stderr | 19 + .../array-size-in-generic-struct-param.min.stderr | 29 + .../array-size-in-generic-struct-param.rs | 29 + .../const_equate_assoc_consts.rs | 27 + .../doesnt_unify_evaluatable.rs | 15 + .../doesnt_unify_evaluatable.stderr | 10 + .../dropck_unifies_assoc_consts.rs | 20 + .../assoc_const_unification/unifies_evaluatable.rs | 18 + .../generic_const_exprs/associated-const.rs | 11 + .../generic_const_exprs/associated-consts.rs | 31 + .../auxiliary/anon_const_non_local.rs | 8 + .../auxiliary/const_evaluatable_lib.rs | 9 + .../auxiliary/issue-94287-aux.rs | 21 + .../const-generics/generic_const_exprs/closures.rs | 6 + .../generic_const_exprs/closures.stderr | 26 + .../generic_const_exprs/const-block-is-poly.rs | 11 + .../generic_const_exprs/const-block-is-poly.stderr | 20 + .../const_eval_resolve_canonical.rs | 28 + .../const_kind_expr/wf_obligation.rs | 22 + .../const_kind_expr/wf_obligation.stderr | 20 + .../generic_const_exprs/cross_crate.rs | 15 + .../generic_const_exprs/cross_crate_predicate.rs | 14 + .../cross_crate_predicate.stderr | 54 + .../dependence_lint.full.stderr | 39 + .../generic_const_exprs/dependence_lint.gce.stderr | 34 + .../generic_const_exprs/dependence_lint.rs | 26 + .../generic_const_exprs/different-fn.rs | 17 + .../generic_const_exprs/different-fn.stderr | 20 + .../const-generics/generic_const_exprs/division.rs | 11 + .../dont-eagerly-error-in-is-const-evaluatable.rs | 16 + .../generic_const_exprs/drop_impl.rs | 16 + .../generic_const_exprs/elaborate-trait-pred.rs | 24 + .../generic_const_exprs/eval-privacy.rs | 26 + .../generic_const_exprs/eval-privacy.stderr | 12 + .../generic_const_exprs/eval-try-unify.rs | 26 + .../generic_const_exprs/eval-try-unify.stderr | 11 + .../generic_const_exprs/evaluated-to-ambig.rs | 22 + .../feature-gate-generic_const_exprs.rs | 11 + .../feature-gate-generic_const_exprs.stderr | 11 + .../const-generics/generic_const_exprs/fn_call.rs | 30 + .../generic_const_exprs/from-sig-fail.rs | 11 + .../generic_const_exprs/from-sig-fail.stderr | 9 + .../const-generics/generic_const_exprs/from-sig.rs | 14 + .../generic_const_exprs/function-call.rs | 20 + .../generic_const_exprs/function-call.stderr | 12 + .../generic_const_exprs/impl-bounds.rs | 25 + .../generic_const_exprs/infer-too-generic.rs | 24 + .../generic_const_exprs/issue-100217.rs | 42 + .../generic_const_exprs/issue-100360.rs | 13 + .../generic_const_exprs/issue-102074.rs | 23 + .../generic_const_exprs/issue-102768.rs | 14 + .../generic_const_exprs/issue-102768.stderr | 33 + .../generic_const_exprs/issue-105257.rs | 9 + .../generic_const_exprs/issue-105257.stderr | 14 + .../generic_const_exprs/issue-105608.rs | 15 + .../generic_const_exprs/issue-105608.stderr | 14 + .../generic_const_exprs/issue-62504.full.stderr | 20 + .../generic_const_exprs/issue-62504.min.stderr | 27 + .../generic_const_exprs/issue-62504.rs | 27 + .../generic_const_exprs/issue-69654.rs | 19 + .../generic_const_exprs/issue-69654.stderr | 30 + .../generic_const_exprs/issue-72787.min.stderr | 38 + .../generic_const_exprs/issue-72787.rs | 33 + .../issue-72819-generic-in-const-eval.full.stderr | 35 + .../issue-72819-generic-in-const-eval.min.stderr | 11 + .../issue-72819-generic-in-const-eval.rs | 23 + .../generic_const_exprs/issue-73298.rs | 23 + .../generic_const_exprs/issue-73899.rs | 20 + .../generic_const_exprs/issue-74634.rs | 28 + .../generic_const_exprs/issue-74713.rs | 8 + .../generic_const_exprs/issue-74713.stderr | 22 + .../generic_const_exprs/issue-76595.rs | 17 + .../generic_const_exprs/issue-76595.stderr | 21 + ...sue-79518-default_trait_method_normalization.rs | 21 + ...79518-default_trait_method_normalization.stderr | 16 + .../issue-80561-incorrect-param-env.rs | 24 + .../generic_const_exprs/issue-80742.rs | 32 + .../generic_const_exprs/issue-80742.stderr | 71 + .../generic_const_exprs/issue-82268.rs | 73 + .../generic_const_exprs/issue-83765.rs | 38 + .../generic_const_exprs/issue-83765.stderr | 34 + .../generic_const_exprs/issue-83972.rs | 38 + .../generic_const_exprs/issue-84408.rs | 38 + .../generic_const_exprs/issue-84669.rs | 30 + .../generic_const_exprs/issue-85848.rs | 32 + .../generic_const_exprs/issue-85848.stderr | 65 + .../generic_const_exprs/issue-86710.rs | 73 + .../generic_const_exprs/issue-89851.rs | 12 + .../generic_const_exprs/issue-90847.rs | 9 + .../generic_const_exprs/issue-94287.rs | 10 + .../generic_const_exprs/issue-94287.stderr | 15 + .../generic_const_exprs/issue-94293.rs | 31 + .../generic_const_exprs/issue-97047-ice-1.rs | 25 + .../generic_const_exprs/issue-97047-ice-1.stderr | 19 + .../generic_const_exprs/issue-97047-ice-2.rs | 23 + .../generic_const_exprs/issue-97047-ice-2.stderr | 19 + .../generic_const_exprs/issue-99647.rs | 15 + .../generic_const_exprs/issue-99705.rs | 33 + .../generic_const_exprs/less_than.rs | 14 + .../generic_const_exprs/let-bindings.rs | 15 + .../generic_const_exprs/let-bindings.stderr | 20 + .../generic_const_exprs/needs_where_clause.rs | 14 + .../generic_const_exprs/needs_where_clause.stderr | 10 + .../nested-abstract-consts-1.rs | 24 + .../nested-abstract-consts-2.rs | 35 + .../nested_uneval_unification-1.rs | 34 + .../nested_uneval_unification-2.rs | 29 + .../generic_const_exprs/no_dependence.rs | 13 + .../generic_const_exprs/no_where_clause.rs | 29 + .../generic_const_exprs/no_where_clause.stderr | 10 + .../non_local_anon_const_diagnostics.rs | 16 + .../non_local_anon_const_diagnostics.stderr | 12 + .../normed_to_param_is_evaluatable.rs | 12 + .../generic_const_exprs/object-safety-err-ret.rs | 21 + .../object-safety-err-ret.stderr | 18 + .../object-safety-err-where-bounds.rs | 22 + .../object-safety-err-where-bounds.stderr | 24 + .../object-safety-ok-infer-err.rs | 21 + .../object-safety-ok-infer-err.stderr | 19 + .../generic_const_exprs/object-safety-ok.rs | 21 + .../generic_const_exprs/obligation-cause.rs | 24 + .../generic_const_exprs/obligation-cause.stderr | 20 + .../generic_const_exprs/simple_fail.rs | 17 + .../generic_const_exprs/simple_fail.stderr | 15 + .../subexprs_are_const_evalutable.rs | 17 + .../generic_const_exprs/ty-alias-substitution.rs | 14 + .../generic_const_exprs/unify-op-with-fn-call.rs | 35 + .../unify-op-with-fn-call.stderr | 10 + .../ui/const-generics/generic_const_exprs/unop.rs | 14 + .../unused-complex-default-expr.rs | 6 + .../generic_const_exprs/unused_expr.rs | 25 + .../generic_const_exprs/unused_expr.stderr | 29 + tests/ui/const-generics/ice-68875.rs | 11 + tests/ui/const-generics/ice-68875.stderr | 8 + .../ice-const-generic-function-return-ty.rs | 5 + .../ice-const-generic-function-return-ty.stderr | 8 + .../ui/const-generics/impl-const-generic-struct.rs | 12 + .../incorrect-number-of-const-args.rs | 11 + .../incorrect-number-of-const-args.stderr | 35 + .../infer/cannot-infer-const-args.rs | 7 + .../infer/cannot-infer-const-args.stderr | 14 + tests/ui/const-generics/infer/issue-77092.rs | 14 + tests/ui/const-generics/infer/issue-77092.stderr | 14 + tests/ui/const-generics/infer/method-chain.rs | 16 + tests/ui/const-generics/infer/method-chain.stderr | 14 + .../const-generics/infer/one-param-uninferred.rs | 11 + .../infer/one-param-uninferred.stderr | 14 + tests/ui/const-generics/infer/uninferred-consts.rs | 11 + .../const-generics/infer/uninferred-consts.stderr | 14 + tests/ui/const-generics/infer_arg_from_pat.rs | 25 + tests/ui/const-generics/infer_arr_len_from_pat.rs | 11 + .../ui/const-generics/inhabited-assoc-ty-ice-1.rs | 28 + .../ui/const-generics/inhabited-assoc-ty-ice-2.rs | 21 + .../integer-literal-generic-arg-in-where-clause.rs | 18 + ...trinsics-type_name-as-const-argument.min.stderr | 20 + .../intrinsics-type_name-as-const-argument.rs | 21 + .../invalid-const-arg-for-type-param.rs | 14 + .../invalid-const-arg-for-type-param.stderr | 43 + .../ui/const-generics/invalid-constant-in-args.rs | 6 + .../const-generics/invalid-constant-in-args.stderr | 11 + tests/ui/const-generics/invalid-enum.rs | 35 + tests/ui/const-generics/invalid-enum.stderr | 75 + tests/ui/const-generics/invariant.rs | 34 + tests/ui/const-generics/invariant.stderr | 26 + tests/ui/const-generics/issue-102124.rs | 20 + tests/ui/const-generics/issue-105689.rs | 14 + ...sue-106419-struct-with-multiple-const-params.rs | 12 + tests/ui/const-generics/issue-46511.rs | 8 + tests/ui/const-generics/issue-46511.stderr | 21 + tests/ui/const-generics/issue-66451.rs | 28 + tests/ui/const-generics/issue-66451.stderr | 20 + tests/ui/const-generics/issue-70408.rs | 13 + tests/ui/const-generics/issue-80471.rs | 13 + tests/ui/const-generics/issue-80471.stderr | 18 + tests/ui/const-generics/issue-93647.rs | 6 + tests/ui/const-generics/issue-93647.stderr | 13 + tests/ui/const-generics/issue-97007.rs | 88 + .../issues/auxiliary/const_generic_issues_lib.rs | 15 + .../const-generics/issues/auxiliary/impl-const.rs | 9 + tests/ui/const-generics/issues/issue-100313.rs | 21 + tests/ui/const-generics/issues/issue-100313.stderr | 20 + tests/ui/const-generics/issues/issue-105037.rs | 35 + .../issues/issue-56445-1.full.stderr | 11 + .../const-generics/issues/issue-56445-1.min.stderr | 20 + tests/ui/const-generics/issues/issue-56445-1.rs | 13 + tests/ui/const-generics/issues/issue-56445-2.rs | 11 + .../ui/const-generics/issues/issue-56445-2.stderr | 14 + tests/ui/const-generics/issues/issue-56445-3.rs | 12 + .../ui/const-generics/issues/issue-56445-3.stderr | 8 + .../issues/issue-60818-struct-constructors.rs | 7 + tests/ui/const-generics/issues/issue-61336-1.rs | 9 + tests/ui/const-generics/issues/issue-61336-2.rs | 13 + .../ui/const-generics/issues/issue-61336-2.stderr | 15 + tests/ui/const-generics/issues/issue-61336.rs | 13 + tests/ui/const-generics/issues/issue-61336.stderr | 15 + tests/ui/const-generics/issues/issue-61422.rs | 24 + tests/ui/const-generics/issues/issue-61432.rs | 9 + .../issue-62187-encountered-polymorphic-const.rs | 12 + .../const-generics/issues/issue-62878.full.stderr | 9 + .../const-generics/issues/issue-62878.min.stderr | 18 + tests/ui/const-generics/issues/issue-62878.rs | 11 + .../issues/issue-63322-forbid-dyn.full.stderr | 9 + .../issues/issue-63322-forbid-dyn.min.stderr | 11 + .../issues/issue-63322-forbid-dyn.rs | 17 + tests/ui/const-generics/issues/issue-64519.rs | 17 + .../issue-66596-impl-trait-for-str-const-arg.rs | 16 + tests/ui/const-generics/issues/issue-66906.rs | 9 + tests/ui/const-generics/issues/issue-67185-1.rs | 29 + tests/ui/const-generics/issues/issue-67185-2.rs | 31 + .../ui/const-generics/issues/issue-67185-2.stderr | 99 + .../const-generics/issues/issue-67375.full.stderr | 12 + .../const-generics/issues/issue-67375.min.stderr | 21 + tests/ui/const-generics/issues/issue-67375.rs | 12 + .../const-generics/issues/issue-67739.full.stderr | 10 + .../const-generics/issues/issue-67739.min.stderr | 10 + tests/ui/const-generics/issues/issue-67739.rs | 18 + .../issues/issue-67945-1.full.stderr | 17 + .../const-generics/issues/issue-67945-1.min.stderr | 30 + tests/ui/const-generics/issues/issue-67945-1.rs | 19 + .../issues/issue-67945-2.full.stderr | 17 + .../const-generics/issues/issue-67945-2.min.stderr | 8 + tests/ui/const-generics/issues/issue-67945-2.rs | 16 + .../issues/issue-67945-3.full.stderr | 16 + .../const-generics/issues/issue-67945-3.min.stderr | 21 + tests/ui/const-generics/issues/issue-67945-3.rs | 17 + .../issues/issue-67945-4.full.stderr | 16 + .../const-generics/issues/issue-67945-4.min.stderr | 21 + tests/ui/const-generics/issues/issue-67945-4.rs | 16 + .../issues/issue-68104-print-stack-overflow.rs | 13 + .../const-generics/issues/issue-68366.full.stderr | 21 + .../const-generics/issues/issue-68366.min.stderr | 30 + tests/ui/const-generics/issues/issue-68366.rs | 20 + tests/ui/const-generics/issues/issue-68596.rs | 15 + .../issues/issue-68615-adt.min.stderr | 11 + tests/ui/const-generics/issues/issue-68615-adt.rs | 13 + .../issues/issue-68615-array.min.stderr | 11 + .../ui/const-generics/issues/issue-68615-array.rs | 13 + .../const-generics/issues/issue-69654-run-pass.rs | 15 + tests/ui/const-generics/issues/issue-70125-1.rs | 17 + tests/ui/const-generics/issues/issue-70125-2.rs | 12 + tests/ui/const-generics/issues/issue-70167.rs | 6 + .../issues/issue-70180-1-stalled_on.rs | 33 + .../issues/issue-70180-2-stalled_on.rs | 33 + tests/ui/const-generics/issues/issue-70225.rs | 19 + .../const-generics/issues/issue-70273-assoc-fn.rs | 14 + .../const-generics/issues/issue-71169.full.stderr | 9 + .../const-generics/issues/issue-71169.min.stderr | 18 + tests/ui/const-generics/issues/issue-71169.rs | 11 + tests/ui/const-generics/issues/issue-71202.rs | 31 + tests/ui/const-generics/issues/issue-71202.stderr | 33 + .../const-generics/issues/issue-71381.full.stderr | 28 + .../const-generics/issues/issue-71381.min.stderr | 27 + tests/ui/const-generics/issues/issue-71381.rs | 36 + .../const-generics/issues/issue-71382.full.stderr | 9 + .../const-generics/issues/issue-71382.min.stderr | 8 + tests/ui/const-generics/issues/issue-71382.rs | 25 + tests/ui/const-generics/issues/issue-71547.rs | 18 + .../const-generics/issues/issue-71611.full.stderr | 16 + .../const-generics/issues/issue-71611.min.stderr | 15 + tests/ui/const-generics/issues/issue-71611.rs | 11 + tests/ui/const-generics/issues/issue-71986.rs | 6 + .../const-generics/issues/issue-72352.full.stderr | 9 + .../const-generics/issues/issue-72352.min.stderr | 8 + tests/ui/const-generics/issues/issue-72352.rs | 22 + tests/ui/const-generics/issues/issue-72845.rs | 49 + tests/ui/const-generics/issues/issue-72845.stderr | 12 + tests/ui/const-generics/issues/issue-73120.rs | 10 + tests/ui/const-generics/issues/issue-73260.rs | 19 + tests/ui/const-generics/issues/issue-73260.stderr | 37 + .../const-generics/issues/issue-73491.min.stderr | 11 + tests/ui/const-generics/issues/issue-73491.rs | 11 + ...7-static-reference-array-const-param.min.stderr | 11 + ...sue-73727-static-reference-array-const-param.rs | 14 + .../const-generics/issues/issue-74101.min.stderr | 20 + tests/ui/const-generics/issues/issue-74101.rs | 12 + .../const-generics/issues/issue-74255.min.stderr | 11 + tests/ui/const-generics/issues/issue-74255.rs | 20 + tests/ui/const-generics/issues/issue-74906.rs | 22 + .../const-generics/issues/issue-74950.min.stderr | 47 + tests/ui/const-generics/issues/issue-74950.rs | 24 + .../const-generics/issues/issue-75047.min.stderr | 11 + tests/ui/const-generics/issues/issue-75047.rs | 17 + tests/ui/const-generics/issues/issue-75299.rs | 8 + .../issues/issue-76701-ty-param-in-const.rs | 11 + .../issues/issue-76701-ty-param-in-const.stderr | 20 + tests/ui/const-generics/issues/issue-77357.rs | 11 + tests/ui/const-generics/issues/issue-77357.stderr | 11 + tests/ui/const-generics/issues/issue-79674.rs | 28 + tests/ui/const-generics/issues/issue-79674.stderr | 20 + tests/ui/const-generics/issues/issue-80062.rs | 10 + tests/ui/const-generics/issues/issue-80062.stderr | 11 + tests/ui/const-generics/issues/issue-80375.rs | 4 + tests/ui/const-generics/issues/issue-80375.stderr | 11 + tests/ui/const-generics/issues/issue-82956.rs | 33 + tests/ui/const-generics/issues/issue-82956.stderr | 21 + tests/ui/const-generics/issues/issue-83249.rs | 23 + tests/ui/const-generics/issues/issue-83249.stderr | 14 + tests/ui/const-generics/issues/issue-83288.rs | 69 + tests/ui/const-generics/issues/issue-83466.rs | 17 + tests/ui/const-generics/issues/issue-83466.stderr | 22 + tests/ui/const-generics/issues/issue-83765.rs | 116 + tests/ui/const-generics/issues/issue-83765.stderr | 21 + tests/ui/const-generics/issues/issue-83993.rs | 14 + tests/ui/const-generics/issues/issue-84659.rs | 12 + tests/ui/const-generics/issues/issue-84659.stderr | 10 + tests/ui/const-generics/issues/issue-85031-2.rs | 17 + .../ui/const-generics/issues/issue-85031-2.stderr | 13 + tests/ui/const-generics/issues/issue-86033.rs | 20 + tests/ui/const-generics/issues/issue-86530.rs | 20 + tests/ui/const-generics/issues/issue-86530.stderr | 20 + tests/ui/const-generics/issues/issue-86535-2.rs | 19 + tests/ui/const-generics/issues/issue-86535.rs | 20 + tests/ui/const-generics/issues/issue-86820.rs | 24 + tests/ui/const-generics/issues/issue-86820.stderr | 16 + tests/ui/const-generics/issues/issue-87076.rs | 20 + tests/ui/const-generics/issues/issue-87470.rs | 24 + tests/ui/const-generics/issues/issue-87493.rs | 14 + tests/ui/const-generics/issues/issue-87493.stderr | 30 + tests/ui/const-generics/issues/issue-87964.rs | 29 + tests/ui/const-generics/issues/issue-88119.rs | 36 + tests/ui/const-generics/issues/issue-88468.rs | 13 + tests/ui/const-generics/issues/issue-88997.rs | 14 + tests/ui/const-generics/issues/issue-88997.stderr | 15 + tests/ui/const-generics/issues/issue-89146.rs | 26 + tests/ui/const-generics/issues/issue-89304.rs | 20 + tests/ui/const-generics/issues/issue-89320.rs | 19 + tests/ui/const-generics/issues/issue-89334.rs | 16 + tests/ui/const-generics/issues/issue-90318.rs | 30 + tests/ui/const-generics/issues/issue-90318.stderr | 24 + tests/ui/const-generics/issues/issue-90364.rs | 9 + tests/ui/const-generics/issues/issue-90364.stderr | 9 + tests/ui/const-generics/issues/issue-90455.rs | 12 + tests/ui/const-generics/issues/issue-90455.stderr | 10 + tests/ui/const-generics/issues/issue-92186.rs | 12 + tests/ui/const-generics/issues/issue-96654.rs | 15 + tests/ui/const-generics/issues/issue-97278.rs | 14 + tests/ui/const-generics/issues/issue-97278.stderr | 9 + tests/ui/const-generics/issues/issue-97634.rs | 10 + tests/ui/const-generics/issues/issue-98629.rs | 16 + tests/ui/const-generics/issues/issue-98629.stderr | 12 + tests/ui/const-generics/issues/issue-99641.rs | 18 + tests/ui/const-generics/issues/issue-99641.stderr | 15 + .../const-generics/late-bound-vars/in_closure.rs | 18 + tests/ui/const-generics/late-bound-vars/simple.rs | 16 + .../ui/const-generics/legacy-const-generics-bad.rs | 16 + .../legacy-const-generics-bad.stderr | 20 + tests/ui/const-generics/legacy-const-generics.rs | 18 + .../min_const_generics/assoc_const.rs | 16 + .../min_const_generics/complex-expression.rs | 48 + .../min_const_generics/complex-expression.stderr | 75 + .../min_const_generics/complex-types.rs | 27 + .../min_const_generics/complex-types.stderr | 65 + .../const-evaluatable-unchecked.rs | 35 + .../const-evaluatable-unchecked.stderr | 30 + ...ion-suggest-missing-braces-without-turbofish.rs | 47 + ...suggest-missing-braces-without-turbofish.stderr | 140 + .../const-expression-suggest-missing-braces.rs | 51 + .../const-expression-suggest-missing-braces.stderr | 143 + .../min_const_generics/const_default_first.rs | 7 + .../min_const_generics/const_default_first.stderr | 8 + .../min_const_generics/const_fn_in_generics.rs | 15 + .../min_const_generics/default_function_param.rs | 4 + .../default_function_param.stderr | 8 + .../min_const_generics/default_trait_param.rs | 4 + .../forbid-non-static-lifetimes.rs | 25 + .../forbid-non-static-lifetimes.stderr | 21 + .../min_const_generics/forbid-self-no-normalize.rs | 15 + .../forbid-self-no-normalize.stderr | 14 + .../min_const_generics/inferred_const.rs | 9 + .../invalid-patterns.32bit.stderr | 62 + .../invalid-patterns.64bit.stderr | 62 + .../min_const_generics/invalid-patterns.rs | 47 + .../min_const_generics/macro-fail.rs | 39 + .../min_const_generics/macro-fail.stderr | 71 + .../ui/const-generics/min_const_generics/macro.rs | 55 + .../min_const_generics/self-ty-in-const-1.rs | 25 + .../min_const_generics/self-ty-in-const-1.stderr | 23 + .../min_const_generics/self-ty-in-const-2.rs | 19 + .../min_const_generics/self-ty-in-const-2.stderr | 14 + .../min_const_generics/type_and_const_defaults.rs | 25 + tests/ui/const-generics/nested-type.full.stderr | 11 + tests/ui/const-generics/nested-type.min.stderr | 28 + tests/ui/const-generics/nested-type.rs | 19 + tests/ui/const-generics/occurs-check/bind-param.rs | 17 + .../const-generics/occurs-check/unify-fixpoint.rs | 12 + .../occurs-check/unify-fixpoint.stderr | 11 + .../occurs-check/unify-n-nplusone.rs | 16 + .../occurs-check/unify-n-nplusone.stderr | 9 + .../const-generics/occurs-check/unused-substs-1.rs | 13 + .../occurs-check/unused-substs-1.stderr | 19 + .../const-generics/occurs-check/unused-substs-2.rs | 28 + .../occurs-check/unused-substs-2.stderr | 9 + .../const-generics/occurs-check/unused-substs-3.rs | 19 + .../occurs-check/unused-substs-3.stderr | 11 + .../const-generics/occurs-check/unused-substs-4.rs | 11 + .../occurs-check/unused-substs-4.stderr | 9 + .../const-generics/occurs-check/unused-substs-5.rs | 20 + .../occurs-check/unused-substs-5.stderr | 11 + .../outer-lifetime-in-const-generic-default.rs | 10 + .../outer-lifetime-in-const-generic-default.stderr | 11 + tests/ui/const-generics/overlapping_impls.rs | 36 + .../params-in-ct-in-ty-param-lazy-norm.full.stderr | 15 + .../params-in-ct-in-ty-param-lazy-norm.min.stderr | 24 + .../params-in-ct-in-ty-param-lazy-norm.rs | 12 + .../const-generics/parent_generics_of_encoding.rs | 25 + .../parent_generics_of_encoding_impl_trait.rs | 11 + .../parent_generics_of_encoding_impl_trait.stderr | 15 + .../parser-error-recovery/issue-89013-no-assoc.rs | 16 + .../issue-89013-no-assoc.stderr | 14 + .../parser-error-recovery/issue-89013-no-kw.rs | 18 + .../parser-error-recovery/issue-89013-no-kw.stderr | 35 + .../parser-error-recovery/issue-89013-type.rs | 16 + .../parser-error-recovery/issue-89013-type.stderr | 8 + .../parser-error-recovery/issue-89013.rs | 19 + .../parser-error-recovery/issue-89013.stderr | 47 + tests/ui/const-generics/projection-as-arg-const.rs | 20 + .../const-generics/projection-as-arg-const.stderr | 11 + tests/ui/const-generics/promotion.rs | 9 + .../raw-ptr-const-param-deref.full.stderr | 15 + .../raw-ptr-const-param-deref.min.stderr | 14 + .../ui/const-generics/raw-ptr-const-param-deref.rs | 21 + .../const-generics/raw-ptr-const-param.full.stderr | 9 + .../const-generics/raw-ptr-const-param.min.stderr | 8 + tests/ui/const-generics/raw-ptr-const-param.rs | 11 + .../slice-const-param-mismatch.full.stderr | 36 + .../slice-const-param-mismatch.min.stderr | 20 + .../const-generics/slice-const-param-mismatch.rs | 19 + tests/ui/const-generics/slice-const-param.rs | 19 + .../ui/const-generics/sneaky-array-repeat-expr.rs | 32 + .../const-generics/sneaky-array-repeat-expr.stderr | 18 + .../std/const-generics-range.min.stderr | 56 + .../ui/const-generics/std/const-generics-range.rs | 37 + .../struct-with-invalid-const-param.rs | 5 + .../struct-with-invalid-const-param.stderr | 9 + tests/ui/const-generics/suggest_const_for_array.rs | 10 + .../const-generics/suggest_const_for_array.stderr | 15 + tests/ui/const-generics/trait-const-args.rs | 27 + ...ansmute-const-param-static-reference.min.stderr | 11 + .../transmute-const-param-static-reference.rs | 16 + .../transparent-maybeunit-array-wrapper.rs | 12 + .../const-generics/try_unify_ignore_lifetimes.rs | 33 + tests/ui/const-generics/two_matching_preds.rs | 19 + tests/ui/const-generics/type-after-const-ok.rs | 6 + .../type-dependent/auxiliary/type_dependent_lib.rs | 33 + .../type-dependent/const-arg-in-const-arg.rs | 26 + .../const-generics/type-dependent/issue-61936.rs | 47 + .../const-generics/type-dependent/issue-63695.rs | 15 + .../const-generics/type-dependent/issue-67144-1.rs | 25 + .../const-generics/type-dependent/issue-67144-2.rs | 19 + .../const-generics/type-dependent/issue-69816.rs | 17 + .../const-generics/type-dependent/issue-70217.rs | 14 + .../const-generics/type-dependent/issue-70507.rs | 45 + .../const-generics/type-dependent/issue-70586.rs | 30 + .../type-dependent/issue-71348.min.stderr | 20 + .../const-generics/type-dependent/issue-71348.rs | 38 + .../const-generics/type-dependent/issue-71382.rs | 21 + .../type-dependent/issue-71382.stderr | 8 + .../const-generics/type-dependent/issue-71805.rs | 38 + .../const-generics/type-dependent/issue-73730.rs | 14 + .../ui/const-generics/type-dependent/non-local.rs | 21 + tests/ui/const-generics/type-dependent/qpath.rs | 9 + tests/ui/const-generics/type-dependent/simple.rs | 9 + .../type-dependent/type-mismatch.full.stderr | 14 + .../type-dependent/type-mismatch.min.stderr | 14 + .../const-generics/type-dependent/type-mismatch.rs | 10 + tests/ui/const-generics/type_mismatch.rs | 9 + tests/ui/const-generics/type_mismatch.stderr | 23 + tests/ui/const-generics/type_not_in_scope.rs | 11 + tests/ui/const-generics/type_not_in_scope.stderr | 24 + tests/ui/const-generics/type_of_anon_const.rs | 17 + .../types-mismatch-const-args.full.stderr | 34 + .../types-mismatch-const-args.min.stderr | 36 + .../ui/const-generics/types-mismatch-const-args.rs | 22 + tests/ui/const-generics/unify_with_nested_expr.rs | 18 + .../const-generics/unify_with_nested_expr.stderr | 22 + .../uninferred-consts-during-codegen-1.rs | 15 + .../uninferred-consts-during-codegen-2.rs | 15 + tests/ui/const-generics/unknown_adt.rs | 4 + tests/ui/const-generics/unknown_adt.stderr | 9 + tests/ui/const-generics/unused-const-param.rs | 5 + .../const-generics/unused-type-param-suggestion.rs | 4 + .../unused-type-param-suggestion.stderr | 12 + tests/ui/const-generics/unused_braces.fixed | 18 + tests/ui/const-generics/unused_braces.full.fixed | 16 + tests/ui/const-generics/unused_braces.min.fixed | 16 + tests/ui/const-generics/unused_braces.rs | 18 + tests/ui/const-generics/unused_braces.stderr | 19 + tests/ui/const-generics/where-clauses.rs | 30 + tests/ui/const-ptr/allowed_slices.rs | 105 + tests/ui/const-ptr/forbidden_slices.rs | 98 + tests/ui/const-ptr/forbidden_slices.stderr | 240 + tests/ui/const-ptr/out_of_bounds_read.rs | 15 + tests/ui/const-ptr/out_of_bounds_read.stderr | 46 + tests/ui/const_prop/ice-assert-fail-div-by-zero.rs | 14 + .../const_prop/ice-assert-fail-div-by-zero.stderr | 14 + tests/ui/const_prop/inline_spans.rs | 15 + tests/ui/const_prop/inline_spans_lint_attribute.rs | 15 + tests/ui/const_prop/issue-102553.rs | 24 + tests/ui/constructor-lifetime-args.rs | 26 + tests/ui/constructor-lifetime-args.stderr | 67 + tests/ui/consts/array-literal-index-oob.rs | 9 + tests/ui/consts/array-literal-index-oob.stderr | 14 + tests/ui/consts/array-to-slice-cast.rs | 13 + tests/ui/consts/assert-type-intrinsics.rs | 23 + tests/ui/consts/assert-type-intrinsics.stderr | 21 + tests/ui/consts/assoc-const.rs | 21 + tests/ui/consts/assoc_const_generic_impl.rs | 19 + tests/ui/consts/assoc_const_generic_impl.stderr | 15 + tests/ui/consts/associated_const_generic.rs | 25 + tests/ui/consts/async-block.rs | 19 + tests/ui/consts/async-block.with_feature.stderr | 8 + tests/ui/consts/async-block.without_feature.stderr | 21 + tests/ui/consts/auxiliary/cci_const_block.rs | 6 + .../consts/auxiliary/closure-in-foreign-crate.rs | 8 + tests/ui/consts/auxiliary/const_fn_lib.rs | 22 + tests/ui/consts/auxiliary/external_macro.rs | 14 + tests/ui/consts/auxiliary/issue-17718-aux.rs | 10 + tests/ui/consts/auxiliary/issue-63226.rs | 14 + .../ui/consts/auxiliary/promotable_const_fn_lib.rs | 23 + tests/ui/consts/bswap-const.rs | 15 + tests/ui/consts/cast-discriminant-zst-enum.rs | 45 + tests/ui/consts/chained-constants-stackoverflow.rs | 356 + tests/ui/consts/check_const-feature-gated.rs | 7 + tests/ui/consts/closure-in-foreign-crate.rs | 8 + .../consts/closure-structural-match-issue-90013.rs | 7 + tests/ui/consts/const-address-of-interior-mut.rs | 16 + .../ui/consts/const-address-of-interior-mut.stderr | 39 + tests/ui/consts/const-address-of-mut.rs | 14 + tests/ui/consts/const-address-of-mut.stderr | 39 + tests/ui/consts/const-address-of.rs | 19 + tests/ui/consts/const-adt-align-mismatch.rs | 22 + tests/ui/consts/const-array-oob-arith.rs | 14 + tests/ui/consts/const-array-oob-arith.stderr | 15 + tests/ui/consts/const-array-oob.rs | 10 + tests/ui/consts/const-array-oob.stderr | 9 + tests/ui/consts/const-as-fn.rs | 5 + tests/ui/consts/const-as-fn.stderr | 14 + tests/ui/consts/const-autoderef.rs | 11 + tests/ui/consts/const-big-enum.rs | 30 + tests/ui/consts/const-binops.rs | 126 + tests/ui/consts/const-bitshift-rhs-inference.rs | 24 + tests/ui/consts/const-block-const-bound.rs | 25 + tests/ui/consts/const-block-const-bound.stderr | 45 + tests/ui/consts/const-block-cross-crate-fn.rs | 9 + tests/ui/consts/const-block-item-macro-codegen.rs | 40 + tests/ui/consts/const-block-item.rs | 41 + .../ui/consts/const-block-non-item-statement-3.rs | 8 + .../consts/const-block-non-item-statement-rpass.rs | 11 + tests/ui/consts/const-block-non-item-statement.rs | 23 + tests/ui/consts/const-block.rs | 45 + tests/ui/consts/const-blocks/const-repeat.rs | 27 + tests/ui/consts/const-blocks/fn-call-in-const.rs | 23 + .../ui/consts/const-blocks/fn-call-in-non-const.rs | 16 + .../const-blocks/fn-call-in-non-const.stderr | 18 + tests/ui/consts/const-blocks/migrate-fail.rs | 22 + tests/ui/consts/const-blocks/migrate-fail.stderr | 29 + tests/ui/consts/const-blocks/migrate-pass.rs | 125 + tests/ui/consts/const-blocks/nll-fail.rs | 22 + tests/ui/consts/const-blocks/nll-fail.stderr | 29 + tests/ui/consts/const-blocks/nll-pass.rs | 125 + tests/ui/consts/const-blocks/run-pass.rs | 11 + tests/ui/consts/const-blocks/trait-error.rs | 7 + tests/ui/consts/const-blocks/trait-error.stderr | 19 + tests/ui/consts/const-bound.rs | 20 + tests/ui/consts/const-byte-str-cast.rs | 9 + tests/ui/consts/const-call.rs | 8 + tests/ui/consts/const-call.stderr | 11 + tests/ui/consts/const-cast-different-types.rs | 6 + tests/ui/consts/const-cast-different-types.stderr | 15 + tests/ui/consts/const-cast-ptr-int.rs | 16 + tests/ui/consts/const-cast-wrong-type.rs | 5 + tests/ui/consts/const-cast-wrong-type.stderr | 9 + tests/ui/consts/const-cast.rs | 16 + tests/ui/consts/const-const.rs | 9 + tests/ui/consts/const-contents.rs | 19 + tests/ui/consts/const-deref-ptr.rs | 7 + tests/ui/consts/const-deref-ptr.stderr | 9 + tests/ui/consts/const-deref.rs | 8 + tests/ui/consts/const-endianess.rs | 21 + tests/ui/consts/const-enum-byref-self.rs | 18 + tests/ui/consts/const-enum-byref.rs | 16 + tests/ui/consts/const-enum-cast.rs | 41 + tests/ui/consts/const-enum-ptr.rs | 12 + tests/ui/consts/const-enum-struct.rs | 12 + tests/ui/consts/const-enum-struct2.rs | 12 + tests/ui/consts/const-enum-structlike.rs | 16 + tests/ui/consts/const-enum-tuple.rs | 11 + tests/ui/consts/const-enum-tuple2.rs | 11 + tests/ui/consts/const-enum-tuplestruct.rs | 12 + tests/ui/consts/const-enum-tuplestruct2.rs | 12 + tests/ui/consts/const-enum-vec-index.rs | 30 + tests/ui/consts/const-enum-vec-ptr.rs | 15 + tests/ui/consts/const-enum-vector.rs | 15 + tests/ui/consts/const-err-early.rs | 14 + tests/ui/consts/const-err-early.stderr | 33 + tests/ui/consts/const-err-late.rs | 20 + tests/ui/consts/const-err-late.stderr | 51 + tests/ui/consts/const-err-multi.rs | 12 + tests/ui/consts/const-err-multi.stderr | 27 + tests/ui/consts/const-err-rpass.rs | 18 + tests/ui/consts/const-err2.noopt.stderr | 48 + tests/ui/consts/const-err2.opt.stderr | 48 + .../const-err2.opt_with_overflow_checks.stderr | 48 + tests/ui/consts/const-err2.rs | 39 + tests/ui/consts/const-err4.32bit.stderr | 9 + tests/ui/consts/const-err4.64bit.stderr | 9 + tests/ui/consts/const-err4.rs | 16 + .../assign-to-static-within-other-static.rs | 12 + .../assign-to-static-within-other-static.stderr | 9 + .../auxiliary/post_monomorphization_error.rs | 20 + tests/ui/consts/const-eval/auxiliary/stability.rs | 10 + .../const-eval/conditional_array_execution.rs | 8 + .../const-eval/conditional_array_execution.stderr | 9 + .../const-eval/const-eval-intrinsic-promotion.rs | 6 + .../const-eval-intrinsic-promotion.stderr | 13 + .../ui/consts/const-eval/const-eval-overflow-2.rs | 20 + .../consts/const-eval/const-eval-overflow-2.stderr | 21 + .../ui/consts/const-eval/const-eval-overflow-3.rs | 27 + .../consts/const-eval/const-eval-overflow-3.stderr | 9 + .../ui/consts/const-eval/const-eval-overflow-3b.rs | 26 + .../const-eval/const-eval-overflow-3b.stderr | 23 + .../ui/consts/const-eval/const-eval-overflow-4.rs | 21 + .../consts/const-eval/const-eval-overflow-4.stderr | 9 + .../ui/consts/const-eval/const-eval-overflow-4b.rs | 26 + .../const-eval/const-eval-overflow-4b.stderr | 35 + tests/ui/consts/const-eval/const-eval-overflow2.rs | 69 + .../consts/const-eval/const-eval-overflow2.stderr | 51 + .../ui/consts/const-eval/const-eval-overflow2b.rs | 69 + .../consts/const-eval/const-eval-overflow2b.stderr | 51 + .../ui/consts/const-eval/const-eval-overflow2c.rs | 69 + .../consts/const-eval/const-eval-overflow2c.stderr | 51 + .../ui/consts/const-eval/const-eval-query-stack.rs | 22 + .../const-eval/const-eval-query-stack.stderr | 13 + tests/ui/consts/const-eval/const-eval-span.rs | 14 + tests/ui/consts/const-eval/const-eval-span.stderr | 9 + ...st-pointer-values-in-various-types.64bit.stderr | 258 + .../const-pointer-values-in-various-types.rs | 114 + tests/ui/consts/const-eval/const_fn_ptr.rs | 36 + tests/ui/consts/const-eval/const_fn_ptr.stderr | 20 + tests/ui/consts/const-eval/const_fn_ptr_fail.rs | 12 + .../ui/consts/const-eval/const_fn_ptr_fail.stderr | 10 + tests/ui/consts/const-eval/const_fn_ptr_fail2.rs | 20 + .../ui/consts/const-eval/const_fn_ptr_fail2.stderr | 45 + tests/ui/consts/const-eval/const_let.rs | 29 + tests/ui/consts/const-eval/const_let.stderr | 35 + tests/ui/consts/const-eval/const_panic.rs | 40 + tests/ui/consts/const-eval/const_panic.stderr | 99 + tests/ui/consts/const-eval/const_panic_2021.rs | 34 + tests/ui/consts/const-eval/const_panic_2021.stderr | 83 + .../consts/const-eval/const_panic_libcore_bin.rs | 25 + .../const-eval/const_panic_libcore_bin.stderr | 27 + .../const-eval/const_panic_stability.e2018.stderr | 16 + .../const-eval/const_panic_stability.e2021.stderr | 13 + .../ui/consts/const-eval/const_panic_stability.rs | 17 + .../consts/const-eval/const_panic_track_caller.rs | 22 + .../const-eval/const_panic_track_caller.stderr | 20 + tests/ui/consts/const-eval/const_prop_errors.rs | 14 + tests/ui/consts/const-eval/const_raw_ptr_ops.rs | 6 + .../ui/consts/const-eval/const_raw_ptr_ops.stderr | 29 + tests/ui/consts/const-eval/const_raw_ptr_ops2.rs | 10 + .../ui/consts/const-eval/const_raw_ptr_ops2.stderr | 15 + tests/ui/consts/const-eval/const_signed_pat.rs | 9 + tests/ui/consts/const-eval/dangling.rs | 10 + tests/ui/consts/const-eval/dangling.stderr | 9 + .../const-eval/dont_promote_unstable_const_fn.rs | 24 + .../dont_promote_unstable_const_fn.stderr | 43 + .../dont_promote_unstable_const_fn_cross_crate.rs | 10 + ...nt_promote_unstable_const_fn_cross_crate.stderr | 24 + tests/ui/consts/const-eval/double_check.rs | 25 + tests/ui/consts/const-eval/double_check2.rs | 32 + tests/ui/consts/const-eval/duration_conversion.rs | 16 + tests/ui/consts/const-eval/enum_discr.rs | 25 + tests/ui/consts/const-eval/erroneous-const.rs | 21 + tests/ui/consts/const-eval/erroneous-const.stderr | 15 + tests/ui/consts/const-eval/erroneous-const2.rs | 19 + tests/ui/consts/const-eval/erroneous-const2.stderr | 15 + tests/ui/consts/const-eval/extern_fat_pointer.rs | 13 + tests/ui/consts/const-eval/format.rs | 13 + tests/ui/consts/const-eval/format.stderr | 95 + tests/ui/consts/const-eval/generic-slice.rs | 31 + tests/ui/consts/const-eval/generic-slice.stderr | 30 + .../const-eval/heap/alloc_intrinsic_errors.rs | 15 + .../const-eval/heap/alloc_intrinsic_errors.stderr | 20 + .../heap/alloc_intrinsic_nontransient.rs | 19 + .../heap/alloc_intrinsic_nontransient_fail.rs | 18 + .../heap/alloc_intrinsic_nontransient_fail.stderr | 8 + .../const-eval/heap/alloc_intrinsic_transient.rs | 19 + .../heap/alloc_intrinsic_uninit.32bit.stderr | 14 + .../heap/alloc_intrinsic_uninit.64bit.stderr | 14 + .../const-eval/heap/alloc_intrinsic_uninit.rs | 10 + .../const-eval/heap/alloc_intrinsic_untyped.rs | 9 + .../const-eval/heap/alloc_intrinsic_untyped.stderr | 8 + .../const-eval/heap/alloc_intrinsic_zero_sized.rs | 16 + .../ui/consts/const-eval/heap/dealloc_intrinsic.rs | 36 + .../const-eval/heap/dealloc_intrinsic_dangling.rs | 22 + .../heap/dealloc_intrinsic_dangling.stderr | 15 + .../const-eval/heap/dealloc_intrinsic_duplicate.rs | 13 + .../heap/dealloc_intrinsic_duplicate.stderr | 9 + .../heap/dealloc_intrinsic_incorrect_layout.rs | 29 + .../heap/dealloc_intrinsic_incorrect_layout.stderr | 27 + .../heap/dealloc_intrinsic_zero_sized.rs | 17 + .../consts/const-eval/ice-generic-assoc-const.rs | 16 + tests/ui/consts/const-eval/ice-packed.rs | 21 + .../const-eval/index-out-of-bounds-never-type.rs | 21 + .../index-out-of-bounds-never-type.stderr | 15 + tests/ui/consts/const-eval/index_out_of_bounds.rs | 4 + .../consts/const-eval/index_out_of_bounds.stderr | 9 + .../const-eval/index_out_of_bounds_propagated.rs | 6 + .../index_out_of_bounds_propagated.stderr | 10 + tests/ui/consts/const-eval/infinite_loop.rs | 12 + tests/ui/consts/const-eval/infinite_loop.stderr | 9 + tests/ui/consts/const-eval/issue-100878.rs | 8 + tests/ui/consts/const-eval/issue-104390.rs | 10 + tests/ui/consts/const-eval/issue-104390.stderr | 65 + tests/ui/consts/const-eval/issue-43197.rs | 11 + tests/ui/consts/const-eval/issue-43197.stderr | 15 + tests/ui/consts/const-eval/issue-44578.rs | 27 + tests/ui/consts/const-eval/issue-44578.stderr | 39 + tests/ui/consts/const-eval/issue-47971.rs | 9 + tests/ui/consts/const-eval/issue-49296.rs | 14 + tests/ui/consts/const-eval/issue-49296.stderr | 9 + tests/ui/consts/const-eval/issue-50706.rs | 37 + tests/ui/consts/const-eval/issue-50814-2.rs | 34 + tests/ui/consts/const-eval/issue-50814-2.stderr | 21 + tests/ui/consts/const-eval/issue-50814.rs | 26 + tests/ui/consts/const-eval/issue-50814.stderr | 21 + tests/ui/consts/const-eval/issue-51300.rs | 31 + tests/ui/consts/const-eval/issue-52475.rs | 11 + tests/ui/consts/const-eval/issue-52475.stderr | 9 + tests/ui/consts/const-eval/issue-53157.rs | 13 + tests/ui/consts/const-eval/issue-53401.rs | 11 + tests/ui/consts/const-eval/issue-55541.rs | 27 + tests/ui/consts/const-eval/issue-64908.rs | 20 + tests/ui/consts/const-eval/issue-64970.rs | 15 + tests/ui/consts/const-eval/issue-65394.rs | 13 + tests/ui/consts/const-eval/issue-65394.stderr | 22 + tests/ui/consts/const-eval/issue-70723.rs | 3 + tests/ui/consts/const-eval/issue-70723.stderr | 9 + .../consts/const-eval/issue-70804-fn-subtyping.rs | 9 + .../const-eval/issue-84957-const-str-as-bytes.rs | 28 + tests/ui/consts/const-eval/issue-85155.rs | 21 + tests/ui/consts/const-eval/issue-85155.stderr | 15 + tests/ui/consts/const-eval/issue-85907.rs | 7 + tests/ui/consts/const-eval/issue-85907.stderr | 10 + .../consts/const-eval/issue-91827-extern-types.rs | 56 + tests/ui/consts/const-eval/livedrop.rs | 17 + tests/ui/consts/const-eval/livedrop.stderr | 12 + tests/ui/consts/const-eval/match-test-ptr-null.rs | 12 + .../consts/const-eval/match-test-ptr-null.stderr | 11 + .../consts/const-eval/mod-static-with-const-fn.rs | 22 + .../const-eval/mod-static-with-const-fn.stderr | 9 + .../no_lint_for_statically_known_error.rs | 18 + tests/ui/consts/const-eval/nrvo.rs | 26 + .../ui/consts/const-eval/panic-assoc-never-type.rs | 15 + .../const-eval/panic-assoc-never-type.stderr | 23 + tests/ui/consts/const-eval/panic-never-type.rs | 9 + tests/ui/consts/const-eval/panic-never-type.stderr | 11 + .../ui/consts/const-eval/partial_ptr_overwrite.rs | 14 + .../consts/const-eval/partial_ptr_overwrite.stderr | 12 + tests/ui/consts/const-eval/promote-static.rs | 14 + .../const-eval/promote_mutable_zst_mir_borrowck.rs | 5 + .../ui/consts/const-eval/promoted_const_fn_fail.rs | 20 + .../const-eval/promoted_const_fn_fail.stderr | 14 + .../promoted_const_fn_fail_deny_const_err.rs | 22 + .../promoted_const_fn_fail_deny_const_err.stderr | 14 + .../consts/const-eval/promoted_errors.noopt.stderr | 44 + .../consts/const-eval/promoted_errors.opt.stderr | 44 + ...promoted_errors.opt_with_overflow_checks.stderr | 44 + tests/ui/consts/const-eval/promoted_errors.rs | 52 + tests/ui/consts/const-eval/promoted_raw_ptr_ops.rs | 10 + .../consts/const-eval/promoted_raw_ptr_ops.stderr | 47 + tests/ui/consts/const-eval/raw-bytes.32bit.stderr | 596 ++ tests/ui/consts/const-eval/raw-bytes.64bit.stderr | 596 ++ tests/ui/consts/const-eval/raw-bytes.rs | 263 + .../const-eval/ref_to_int_match.32bit.stderr | 24 + .../const-eval/ref_to_int_match.64bit.stderr | 24 + tests/ui/consts/const-eval/ref_to_int_match.rs | 26 + tests/ui/consts/const-eval/shift_overflow.rs | 9 + tests/ui/consts/const-eval/shift_overflow.stderr | 9 + tests/ui/consts/const-eval/simd/insert_extract.rs | 70 + tests/ui/consts/const-eval/simple_with_undef.rs | 6 + tests/ui/consts/const-eval/size-of-t.rs | 13 + tests/ui/consts/const-eval/size-of-t.stderr | 11 + tests/ui/consts/const-eval/strlen.rs | 31 + .../consts/const-eval/transmute-const-promotion.rs | 6 + .../const-eval/transmute-const-promotion.stderr | 14 + .../consts/const-eval/transmute-const.32bit.stderr | 14 + .../consts/const-eval/transmute-const.64bit.stderr | 14 + tests/ui/consts/const-eval/transmute-const.rs | 7 + tests/ui/consts/const-eval/ub-enum-overwrite.rs | 18 + .../ui/consts/const-eval/ub-enum-overwrite.stderr | 9 + tests/ui/consts/const-eval/ub-enum.32bit.stderr | 121 + tests/ui/consts/const-eval/ub-enum.64bit.stderr | 121 + tests/ui/consts/const-eval/ub-enum.rs | 102 + .../const-eval/ub-incorrect-vtable.32bit.stderr | 59 + .../const-eval/ub-incorrect-vtable.64bit.stderr | 59 + tests/ui/consts/const-eval/ub-incorrect-vtable.rs | 96 + .../ui/consts/const-eval/ub-int-array.32bit.stderr | 21 + .../ui/consts/const-eval/ub-int-array.64bit.stderr | 21 + tests/ui/consts/const-eval/ub-int-array.rs | 63 + .../const-eval/ub-nonnull.chalk.64bit.stderr | 9 + tests/ui/consts/const-eval/ub-nonnull.rs | 59 + tests/ui/consts/const-eval/ub-nonnull.stderr | 81 + tests/ui/consts/const-eval/ub-ref-ptr.rs | 71 + tests/ui/consts/const-eval/ub-ref-ptr.stderr | 186 + tests/ui/consts/const-eval/ub-uninhabit.rs | 25 + tests/ui/consts/const-eval/ub-uninhabit.stderr | 32 + tests/ui/consts/const-eval/ub-upvars.32bit.stderr | 14 + tests/ui/consts/const-eval/ub-upvars.64bit.stderr | 14 + tests/ui/consts/const-eval/ub-upvars.rs | 12 + .../const-eval/ub-wide-ptr.chalk.64bit.stderr | 9 + tests/ui/consts/const-eval/ub-wide-ptr.rs | 159 + tests/ui/consts/const-eval/ub-wide-ptr.stderr | 297 + .../ui/consts/const-eval/union-const-eval-field.rs | 38 + .../const-eval/union-const-eval-field.stderr | 21 + tests/ui/consts/const-eval/union-ice.rs | 48 + tests/ui/consts/const-eval/union-ice.stderr | 21 + tests/ui/consts/const-eval/union-ub.32bit.stderr | 20 + tests/ui/consts/const-eval/union-ub.64bit.stderr | 20 + tests/ui/consts/const-eval/union-ub.rs | 43 + tests/ui/consts/const-eval/union_promotion.rs | 11 + tests/ui/consts/const-eval/union_promotion.stderr | 16 + tests/ui/consts/const-eval/unused-broken-const.rs | 8 + .../consts/const-eval/unused-broken-const.stderr | 9 + tests/ui/consts/const-eval/unwind-abort.rs | 12 + tests/ui/consts/const-eval/unwind-abort.stderr | 21 + tests/ui/consts/const-eval/valid-const.rs | 17 + .../validate_uninhabited_zsts.32bit.stderr | 61 + .../validate_uninhabited_zsts.64bit.stderr | 61 + .../consts/const-eval/validate_uninhabited_zsts.rs | 28 + .../write-to-uninhabited-enum-variant.rs | 28 + tests/ui/consts/const-eval/zst_operand_eval.rs | 5 + tests/ui/consts/const-expr-addr-operator.rs | 11 + tests/ui/consts/const-expr-in-fixed-length-vec.rs | 12 + tests/ui/consts/const-expr-in-vec-repeat.rs | 11 + .../const-extern-fn-call-extern-fn.rs | 23 + .../const-extern-fn-call-extern-fn.stderr | 19 + .../const-extern-fn-min-const-fn.rs | 11 + .../const-extern-fn-min-const-fn.stderr | 21 + .../const-extern-fn-requires-unsafe.mir.stderr | 19 + .../const-extern-fn-requires-unsafe.rs | 14 + .../const-extern-fn-requires-unsafe.thir.stderr | 11 + tests/ui/consts/const-extern-fn/const-extern-fn.rs | 35 + .../feature-gate-const_extern_fn.rs | 13 + .../feature-gate-const_extern_fn.stderr | 21 + ...62-const-extern-fns-dont-need-fn-specifier-2.rs | 7 + ...onst-extern-fns-dont-need-fn-specifier-2.stderr | 8 + ...8062-const-extern-fns-dont-need-fn-specifier.rs | 7 + ...-const-extern-fns-dont-need-fn-specifier.stderr | 8 + tests/ui/consts/const-extern-function.rs | 16 + tests/ui/consts/const-external-macro-const-err.rs | 13 + .../consts/const-external-macro-const-err.stderr | 11 + tests/ui/consts/const-fields-and-indexing.rs | 28 + tests/ui/consts/const-float-bits-conv.rs | 63 + tests/ui/consts/const-float-bits-reject-conv.rs | 68 + .../ui/consts/const-float-bits-reject-conv.stderr | 115 + tests/ui/consts/const-float-classify.rs | 78 + tests/ui/consts/const-fn-const-eval.rs | 10 + tests/ui/consts/const-fn-destructuring-arg.rs | 7 + tests/ui/consts/const-fn-error.rs | 18 + tests/ui/consts/const-fn-error.stderr | 48 + tests/ui/consts/const-fn-in-vec.rs | 7 + tests/ui/consts/const-fn-in-vec.stderr | 13 + tests/ui/consts/const-fn-method.rs | 16 + tests/ui/consts/const-fn-mismatch.rs | 17 + tests/ui/consts/const-fn-mismatch.stderr | 9 + tests/ui/consts/const-fn-nested.rs | 12 + tests/ui/consts/const-fn-not-in-trait.rs | 13 + tests/ui/consts/const-fn-not-in-trait.stderr | 15 + tests/ui/consts/const-fn-not-safe-for-const.rs | 35 + tests/ui/consts/const-fn-not-safe-for-const.stderr | 28 + tests/ui/consts/const-fn-ptr.rs | 16 + tests/ui/consts/const-fn-ptr.stderr | 20 + tests/ui/consts/const-fn-stability-calls-3.rs | 12 + tests/ui/consts/const-fn-stability-calls.rs | 27 + tests/ui/consts/const-fn-type-name-any.rs | 28 + tests/ui/consts/const-fn-type-name.rs | 37 + tests/ui/consts/const-fn-val.rs | 15 + tests/ui/consts/const-fn-zst-args.rs | 14 + tests/ui/consts/const-fn.rs | 42 + tests/ui/consts/const-for-feature-gate.rs | 8 + tests/ui/consts/const-for-feature-gate.stderr | 12 + tests/ui/consts/const-for.rs | 10 + tests/ui/consts/const-for.stderr | 23 + tests/ui/consts/const-index-feature-gate.rs | 7 + tests/ui/consts/const-int-arithmetic-overflow.rs | 25 + tests/ui/consts/const-int-arithmetic.rs | 138 + tests/ui/consts/const-int-conversion-rpass.rs | 19 + tests/ui/consts/const-int-conversion.rs | 16 + tests/ui/consts/const-int-conversion.stderr | 80 + tests/ui/consts/const-int-overflowing-rpass.rs | 47 + tests/ui/consts/const-int-overflowing.rs | 8 + tests/ui/consts/const-int-overflowing.stderr | 36 + tests/ui/consts/const-int-pow-rpass.rs | 47 + tests/ui/consts/const-int-rotate-rpass.rs | 43 + tests/ui/consts/const-int-rotate.rs | 6 + tests/ui/consts/const-int-rotate.stderr | 25 + tests/ui/consts/const-int-saturating-arith.rs | 33 + tests/ui/consts/const-int-sign-rpass.rs | 27 + tests/ui/consts/const-int-sign.rs | 6 + tests/ui/consts/const-int-sign.stderr | 25 + tests/ui/consts/const-int-unchecked.rs | 149 + tests/ui/consts/const-int-unchecked.stderr | 297 + tests/ui/consts/const-int-wrapping-rpass.rs | 47 + tests/ui/consts/const-int-wrapping.rs | 12 + tests/ui/consts/const-int-wrapping.stderr | 58 + tests/ui/consts/const-integer-bool-ops.rs | 85 + tests/ui/consts/const-integer-bool-ops.stderr | 171 + tests/ui/consts/const-labeled-break.rs | 11 + .../consts/const-len-underflow-separate-spans.rs | 13 + .../const-len-underflow-separate-spans.stderr | 15 + tests/ui/consts/const-len-underflow-subspans.rs | 11 + .../ui/consts/const-len-underflow-subspans.stderr | 9 + tests/ui/consts/const-match-check.eval1.stderr | 21 + tests/ui/consts/const-match-check.eval2.stderr | 21 + tests/ui/consts/const-match-check.matchck.stderr | 75 + tests/ui/consts/const-match-check.rs | 33 + tests/ui/consts/const-match-pattern-arm.rs | 15 + tests/ui/consts/const-meth-pattern.rs | 18 + tests/ui/consts/const-multi-ref.rs | 24 + tests/ui/consts/const-multi-ref.stderr | 21 + .../consts/const-mut-refs/const_mut_address_of.rs | 28 + tests/ui/consts/const-mut-refs/const_mut_refs.rs | 35 + .../const-mut-refs/feature-gate-const_mut_refs.rs | 8 + .../feature-gate-const_mut_refs.stderr | 12 + .../consts/const-mut-refs/issue-76510.32bit.stderr | 31 + .../consts/const-mut-refs/issue-76510.64bit.stderr | 31 + tests/ui/consts/const-mut-refs/issue-76510.rs | 18 + tests/ui/consts/const-mut-refs/mut_ref_in_final.rs | 55 + .../consts/const-mut-refs/mut_ref_in_final.stderr | 60 + .../mut_ref_in_final_dynamic_check.rs | 27 + .../mut_ref_in_final_dynamic_check.stderr | 26 + tests/ui/consts/const-needs_drop-monomorphic.rs | 17 + .../ui/consts/const-needs_drop-monomorphic.stderr | 20 + tests/ui/consts/const-needs_drop.rs | 31 + tests/ui/consts/const-negation.rs | 33 + tests/ui/consts/const-negative.rs | 9 + tests/ui/consts/const-nullary-enum.rs | 23 + tests/ui/consts/const-nullary-univariant-enum.rs | 15 + tests/ui/consts/const-pattern-irrefutable.rs | 28 + tests/ui/consts/const-pattern-irrefutable.stderr | 48 + .../ui/consts/const-pattern-not-const-evaluable.rs | 30 + tests/ui/consts/const-pattern-variant.rs | 29 + .../ui/consts/const-points-to-static.32bit.stderr | 22 + .../ui/consts/const-points-to-static.64bit.stderr | 22 + tests/ui/consts/const-points-to-static.rs | 13 + tests/ui/consts/const-prop-ice.rs | 5 + tests/ui/consts/const-prop-ice.stderr | 10 + tests/ui/consts/const-prop-ice2.rs | 7 + tests/ui/consts/const-prop-ice2.stderr | 10 + tests/ui/consts/const-prop-ice3.rs | 7 + tests/ui/consts/const-prop-overflowing-casts.rs | 15 + tests/ui/consts/const-prop-read-static-in-const.rs | 10 + .../consts/const-prop-read-static-in-const.stderr | 17 + tests/ui/consts/const-ptr-nonnull-rpass.rs | 17 + tests/ui/consts/const-ptr-nonnull.rs | 11 + tests/ui/consts/const-ptr-nonnull.stderr | 25 + tests/ui/consts/const-ptr-unique-rpass.rs | 16 + tests/ui/consts/const-ptr-unique.rs | 10 + tests/ui/consts/const-ptr-unique.stderr | 14 + tests/ui/consts/const-rec-and-tup.rs | 20 + tests/ui/consts/const-region-ptrs-noncopy.rs | 12 + tests/ui/consts/const-region-ptrs.rs | 15 + tests/ui/consts/const-repeated-values.rs | 10 + tests/ui/consts/const-size_of-align_of.rs | 51 + tests/ui/consts/const-size_of-cycle.rs | 7 + tests/ui/consts/const-size_of-cycle.stderr | 29 + .../const-size_of_val-align_of_val-extern-type.rs | 14 + ...nst-size_of_val-align_of_val-extern-type.stderr | 15 + tests/ui/consts/const-size_of_val-align_of_val.rs | 55 + tests/ui/consts/const-slice-oob.rs | 8 + tests/ui/consts/const-slice-oob.stderr | 9 + tests/ui/consts/const-struct-offsets.rs | 18 + tests/ui/consts/const-struct.rs | 32 + tests/ui/consts/const-suggest-feature.rs | 7 + tests/ui/consts/const-suggest-feature.stderr | 12 + tests/ui/consts/const-trait-to-trait.rs | 24 + tests/ui/consts/const-try-feature-gate.rs | 9 + tests/ui/consts/const-try-feature-gate.stderr | 12 + tests/ui/consts/const-try.rs | 39 + tests/ui/consts/const-tup-index-span.rs | 10 + tests/ui/consts/const-tup-index-span.stderr | 22 + tests/ui/consts/const-tuple-struct.rs | 14 + tests/ui/consts/const-type-mismatch.rs | 11 + tests/ui/consts/const-type-mismatch.stderr | 15 + tests/ui/consts/const-typeid-of-rpass.rs | 34 + tests/ui/consts/const-unit-struct.rs | 12 + tests/ui/consts/const-unsafe-fn.rs | 21 + tests/ui/consts/const-unsized.rs | 17 + tests/ui/consts/const-unsized.stderr | 35 + tests/ui/consts/const-unwrap.rs | 13 + tests/ui/consts/const-unwrap.stderr | 9 + tests/ui/consts/const-validation-fail-55455.rs | 9 + tests/ui/consts/const-variant-count.rs | 47 + tests/ui/consts/const-vec-of-fns.rs | 25 + tests/ui/consts/const-vec-syntax.rs | 9 + tests/ui/consts/const-vecs-and-slices.rs | 23 + tests/ui/consts/const.rs | 6 + tests/ui/consts/const_cmp_type_id.rs | 12 + .../const_constructor/const-construct-call.rs | 110 + .../const_constructor/const_constructor_qpath.rs | 37 + tests/ui/consts/const_discriminant.rs | 42 + ...const_fn_floating_point_arithmetic.gated.stderr | 8 + .../consts/const_fn_floating_point_arithmetic.rs | 20 + ...const_fn_floating_point_arithmetic.stock.stderr | 48 + tests/ui/consts/const_fn_return_nested_fn_ptr.rs | 10 + tests/ui/consts/const_fn_unsize.rs | 21 + tests/ui/consts/const_forget.rs | 20 + .../consts/const_in_pattern/accept_structural.rs | 66 + .../ui/consts/const_in_pattern/auxiliary/consts.rs | 16 + .../ui/consts/const_in_pattern/cross-crate-fail.rs | 25 + .../const_in_pattern/cross-crate-fail.stderr | 14 + .../ui/consts/const_in_pattern/cross-crate-pass.rs | 23 + .../const_in_pattern/custom-eq-branch-pass.rs | 32 + .../const_in_pattern/custom-eq-branch-warn.rs | 36 + .../const_in_pattern/custom-eq-branch-warn.stderr | 12 + .../ui/consts/const_in_pattern/incomplete-slice.rs | 15 + .../const_in_pattern/incomplete-slice.stderr | 26 + tests/ui/consts/const_in_pattern/issue-44333.rs | 25 + .../ui/consts/const_in_pattern/issue-44333.stderr | 25 + tests/ui/consts/const_in_pattern/issue-53708.rs | 11 + tests/ui/consts/const_in_pattern/issue-62614.rs | 24 + tests/ui/consts/const_in_pattern/issue-65466.rs | 21 + tests/ui/consts/const_in_pattern/issue-73431.rs | 29 + .../ui/consts/const_in_pattern/issue-73431.stderr | 1 + tests/ui/consts/const_in_pattern/issue-78057.rs | 17 + .../ui/consts/const_in_pattern/issue-78057.stderr | 23 + .../consts/const_in_pattern/no-eq-branch-fail.rs | 25 + .../const_in_pattern/no-eq-branch-fail.stderr | 8 + .../const_in_pattern/reject_non_partial_eq.rs | 32 + .../const_in_pattern/reject_non_partial_eq.stderr | 8 + .../const_in_pattern/reject_non_structural.rs | 83 + .../const_in_pattern/reject_non_structural.stderr | 76 + .../consts/const_in_pattern/warn_corner_cases.rs | 41 + .../const_in_pattern/warn_corner_cases.stderr | 30 + tests/ui/consts/const_let_assign.rs | 10 + tests/ui/consts/const_let_assign2.rs | 22 + tests/ui/consts/const_let_assign3.rs | 27 + tests/ui/consts/const_let_assign3.stderr | 30 + tests/ui/consts/const_let_eq.rs | 469 + tests/ui/consts/const_let_eq_float.rs | 280 + tests/ui/consts/const_let_irrefutable.rs | 11 + tests/ui/consts/const_let_promote.rs | 17 + tests/ui/consts/const_let_refutable.rs | 6 + tests/ui/consts/const_let_refutable.stderr | 11 + .../const_limit/const_eval_limit_not_reached.rs | 20 + .../const_limit/const_eval_limit_overflow.rs | 15 + .../const_limit/const_eval_limit_overflow.stderr | 10 + .../consts/const_limit/const_eval_limit_reached.rs | 16 + .../const_limit/const_eval_limit_reached.stderr | 9 + .../const_limit/feature-gate-const_eval_limit.rs | 14 + .../feature-gate-const_eval_limit.stderr | 12 + tests/ui/consts/const_prop_slice_pat_ice.rs | 8 + tests/ui/consts/const_short_circuit.rs | 14 + tests/ui/consts/const_unsafe_unreachable.rs | 14 + tests/ui/consts/const_unsafe_unreachable_ub.rs | 14 + tests/ui/consts/const_unsafe_unreachable_ub.stderr | 21 + .../consts/constifconst-call-in-const-position.rs | 22 + .../constifconst-call-in-const-position.stderr | 18 + tests/ui/consts/consts-in-patterns.rs | 28 + tests/ui/consts/control-flow/assert.rs | 8 + tests/ui/consts/control-flow/assert.stderr | 11 + tests/ui/consts/control-flow/basics.rs | 82 + .../consts/control-flow/drop-fail.precise.stderr | 15 + tests/ui/consts/control-flow/drop-fail.rs | 62 + .../ui/consts/control-flow/drop-fail.stock.stderr | 39 + tests/ui/consts/control-flow/drop-pass.rs | 46 + tests/ui/consts/control-flow/drop-precise.rs | 18 + .../control-flow/exhaustive-c-like-enum-match.rs | 29 + .../control-flow/feature-gate-const-if-match.rs | 96 + .../ui/consts/control-flow/interior-mutability.rs | 43 + .../consts/control-flow/interior-mutability.stderr | 35 + tests/ui/consts/control-flow/issue-46843.rs | 16 + tests/ui/consts/control-flow/issue-46843.stderr | 11 + tests/ui/consts/control-flow/issue-50577.rs | 6 + tests/ui/consts/control-flow/issue-50577.stderr | 13 + tests/ui/consts/control-flow/loop.rs | 89 + tests/ui/consts/control-flow/loop.stderr | 25 + tests/ui/consts/control-flow/short-circuit-let.rs | 36 + tests/ui/consts/control-flow/short-circuit.rs | 12 + .../control-flow/single_variant_match_ice.rs | 25 + tests/ui/consts/control-flow/try.rs | 10 + tests/ui/consts/control-flow/try.stderr | 12 + tests/ui/consts/copy-intrinsic.rs | 52 + tests/ui/consts/copy-intrinsic.stderr | 27 + .../ui/consts/ct-var-in-collect_all_mismatches.rs | 20 + .../consts/ct-var-in-collect_all_mismatches.stderr | 22 + tests/ui/consts/dangling-alloc-id-ice.rs | 14 + tests/ui/consts/dangling-alloc-id-ice.stderr | 8 + tests/ui/consts/dangling_raw_ptr.rs | 8 + tests/ui/consts/dangling_raw_ptr.stderr | 8 + tests/ui/consts/deref_in_pattern.rs | 12 + tests/ui/consts/drop_box.rs | 4 + tests/ui/consts/drop_box.stderr | 11 + tests/ui/consts/drop_none.rs | 13 + tests/ui/consts/drop_zst.rs | 17 + tests/ui/consts/drop_zst.stderr | 9 + tests/ui/consts/enum-discr-type-err.rs | 30 + tests/ui/consts/enum-discr-type-err.stderr | 31 + tests/ui/consts/eval-enum.rs | 10 + tests/ui/consts/eval-enum.stderr | 15 + tests/ui/consts/extra-const-ub/detect-extra-ub.rs | 31 + .../detect-extra-ub.with_flag.stderr | 33 + tests/ui/consts/extra-const-ub/issue-100771.rs | 20 + tests/ui/consts/extra-const-ub/issue-101034.rs | 17 + tests/ui/consts/fn_trait_refs.rs | 77 + tests/ui/consts/huge-values.rs | 17 + tests/ui/consts/ice-48279.rs | 26 + tests/ui/consts/ice-zst-static-access.rs | 32 + tests/ui/consts/inline_asm.rs | 8 + tests/ui/consts/inline_asm.stderr | 9 + tests/ui/consts/int_ptr_for_zst_slices.rs | 5 + tests/ui/consts/intrinsic_without_const_stab.rs | 17 + .../ui/consts/intrinsic_without_const_stab.stderr | 11 + .../ui/consts/intrinsic_without_const_stab_fail.rs | 15 + .../intrinsic_without_const_stab_fail.stderr | 11 + tests/ui/consts/invalid-const-in-body.rs | 6 + tests/ui/consts/invalid-const-in-body.stderr | 8 + .../ui/consts/invalid-inline-const-in-match-arm.rs | 9 + .../invalid-inline-const-in-match-arm.stderr | 13 + tests/ui/consts/invalid-union.32bit.stderr | 26 + tests/ui/consts/invalid-union.64bit.stderr | 26 + tests/ui/consts/invalid-union.rs | 44 + tests/ui/consts/invalid_promotion.rs | 18 + tests/ui/consts/issue-102117.rs | 30 + tests/ui/consts/issue-102117.stderr | 25 + tests/ui/consts/issue-103790.rs | 10 + tests/ui/consts/issue-103790.stderr | 65 + tests/ui/consts/issue-104155.rs | 5 + tests/ui/consts/issue-104396.rs | 36 + tests/ui/consts/issue-104396.stderr | 11 + tests/ui/consts/issue-104609.rs | 10 + tests/ui/consts/issue-104609.stderr | 9 + tests/ui/consts/issue-104768.rs | 4 + tests/ui/consts/issue-104768.stderr | 12 + tests/ui/consts/issue-13837.rs | 13 + tests/ui/consts/issue-13902.rs | 16 + tests/ui/consts/issue-17074.rs | 15 + tests/ui/consts/issue-17458.rs | 6 + tests/ui/consts/issue-17458.stderr | 11 + tests/ui/consts/issue-17718-borrow-interior.rs | 19 + tests/ui/consts/issue-17718-const-bad-values.rs | 9 + .../ui/consts/issue-17718-const-bad-values.stderr | 26 + tests/ui/consts/issue-17718-const-borrow.rs | 14 + tests/ui/consts/issue-17718-const-borrow.stderr | 21 + .../ui/consts/issue-17718-constants-not-static.rs | 9 + .../consts/issue-17718-constants-not-static.stderr | 12 + tests/ui/consts/issue-17718-references.rs | 24 + tests/ui/consts/issue-17718-references.stderr | 27 + tests/ui/consts/issue-17718.rs | 75 + tests/ui/consts/issue-17756.rs | 8 + tests/ui/consts/issue-18294.rs | 5 + tests/ui/consts/issue-18294.stderr | 11 + tests/ui/consts/issue-19244.rs | 34 + tests/ui/consts/issue-21562.rs | 19 + tests/ui/consts/issue-21721.rs | 9 + tests/ui/consts/issue-23833.rs | 15 + tests/ui/consts/issue-23968-const-not-overflow.rs | 12 + tests/ui/consts/issue-25826.rs | 6 + tests/ui/consts/issue-25826.stderr | 16 + tests/ui/consts/issue-27890.rs | 7 + tests/ui/consts/issue-28113.rs | 8 + tests/ui/consts/issue-28113.stderr | 13 + tests/ui/consts/issue-29914-2.rs | 6 + tests/ui/consts/issue-29914-3.rs | 7 + tests/ui/consts/issue-29914.rs | 10 + tests/ui/consts/issue-29927-1.rs | 11 + tests/ui/consts/issue-29927.rs | 11 + tests/ui/consts/issue-32829-2.rs | 71 + tests/ui/consts/issue-32829-2.stderr | 29 + tests/ui/consts/issue-32829.rs | 6 + tests/ui/consts/issue-32829.stderr | 11 + tests/ui/consts/issue-33537.rs | 14 + tests/ui/consts/issue-34784.rs | 21 + tests/ui/consts/issue-3521.fixed | 13 + tests/ui/consts/issue-3521.rs | 13 + tests/ui/consts/issue-3521.stderr | 12 + tests/ui/consts/issue-36163.rs | 7 + tests/ui/consts/issue-36163.stderr | 21 + tests/ui/consts/issue-37222.rs | 17 + tests/ui/consts/issue-37550-1.rs | 8 + tests/ui/consts/issue-37550.rs | 10 + tests/ui/consts/issue-37991.rs | 17 + tests/ui/consts/issue-39161-bogus-error.rs | 13 + tests/ui/consts/issue-39974.rs | 11 + tests/ui/consts/issue-39974.stderr | 9 + tests/ui/consts/issue-43105.rs | 13 + tests/ui/consts/issue-43105.stderr | 23 + tests/ui/consts/issue-44415.rs | 11 + tests/ui/consts/issue-44415.stderr | 29 + tests/ui/consts/issue-46553.rs | 21 + tests/ui/consts/issue-47789.rs | 10 + tests/ui/consts/issue-50439.rs | 29 + tests/ui/consts/issue-50439.stderr | 10 + .../consts/issue-52023-array-size-pointer-cast.rs | 3 + .../issue-52023-array-size-pointer-cast.stderr | 11 + tests/ui/consts/issue-52060.rs | 7 + tests/ui/consts/issue-52060.stderr | 11 + tests/ui/consts/issue-54224.rs | 12 + tests/ui/consts/issue-54224.stderr | 23 + tests/ui/consts/issue-54348.rs | 7 + tests/ui/consts/issue-54348.stderr | 16 + tests/ui/consts/issue-54387.rs | 12 + tests/ui/consts/issue-54954.rs | 19 + tests/ui/consts/issue-54954.stderr | 34 + tests/ui/consts/issue-56164.rs | 10 + tests/ui/consts/issue-56164.stderr | 31 + .../ui/consts/issue-58435-ice-with-assoc-const.rs | 18 + tests/ui/consts/issue-62045.rs | 5 + tests/ui/consts/issue-63226.rs | 12 + tests/ui/consts/issue-63952.32bit.stderr | 14 + tests/ui/consts/issue-63952.64bit.stderr | 14 + tests/ui/consts/issue-63952.rs | 27 + tests/ui/consts/issue-64059.rs | 10 + tests/ui/consts/issue-64506.rs | 20 + tests/ui/consts/issue-64662.rs | 10 + tests/ui/consts/issue-64662.stderr | 25 + tests/ui/consts/issue-65348.rs | 23 + tests/ui/consts/issue-66342.rs | 12 + tests/ui/consts/issue-66345.rs | 24 + tests/ui/consts/issue-66397.rs | 8 + tests/ui/consts/issue-66693-panic-in-array-len.rs | 15 + .../consts/issue-66693-panic-in-array-len.stderr | 19 + tests/ui/consts/issue-66693.rs | 23 + tests/ui/consts/issue-66693.stderr | 38 + tests/ui/consts/issue-66787.rs | 39 + tests/ui/consts/issue-67529.rs | 11 + tests/ui/consts/issue-67640.rs | 24 + tests/ui/consts/issue-67641.rs | 24 + tests/ui/consts/issue-67696-const-prop-ice.rs | 20 + tests/ui/consts/issue-67862.rs | 18 + tests/ui/consts/issue-68264-overflow.rs | 43 + .../ui/consts/issue-68542-closure-in-array-len.rs | 9 + .../consts/issue-68542-closure-in-array-len.stderr | 13 + tests/ui/consts/issue-68684.rs | 15 + .../issue-69191-ice-on-uninhabited-enum-field.rs | 91 + .../consts/issue-69310-array-size-lit-wrong-ty.rs | 11 + .../issue-69310-array-size-lit-wrong-ty.stderr | 15 + tests/ui/consts/issue-69312.rs | 10 + tests/ui/consts/issue-69488.rs | 34 + tests/ui/consts/issue-69532.rs | 23 + tests/ui/consts/issue-6991.rs | 8 + tests/ui/consts/issue-70773-mir-typeck-lt-norm.rs | 16 + .../consts/issue-70942-trait-vs-impl-mismatch.rs | 14 + .../issue-70942-trait-vs-impl-mismatch.stderr | 15 + tests/ui/consts/issue-73976-monomorphic.rs | 37 + tests/ui/consts/issue-73976-polymorphic.rs | 40 + tests/ui/consts/issue-73976-polymorphic.stderr | 26 + tests/ui/consts/issue-76064.rs | 3 + tests/ui/consts/issue-76064.stderr | 11 + tests/ui/consts/issue-77062-large-zst-array.rs | 5 + tests/ui/consts/issue-78655.rs | 10 + tests/ui/consts/issue-78655.stderr | 28 + tests/ui/consts/issue-79137-monomorphic.rs | 19 + tests/ui/consts/issue-79137-toogeneric.rs | 19 + tests/ui/consts/issue-79137-toogeneric.stderr | 14 + tests/ui/consts/issue-79152-const-array-index.rs | 11 + tests/ui/consts/issue-79690.64bit.stderr | 14 + tests/ui/consts/issue-79690.rs | 33 + tests/ui/consts/issue-83182.rs | 9 + tests/ui/consts/issue-83182.stderr | 15 + tests/ui/consts/issue-87046.rs | 33 + tests/ui/consts/issue-87046.stderr | 8 + tests/ui/consts/issue-88071.rs | 18 + tests/ui/consts/issue-88649.rs | 18 + tests/ui/consts/issue-89088.rs | 22 + tests/ui/consts/issue-90762.rs | 31 + tests/ui/consts/issue-90870.fixed | 37 + tests/ui/consts/issue-90870.rs | 37 + tests/ui/consts/issue-90870.stderr | 42 + tests/ui/consts/issue-90878-2.rs | 10 + tests/ui/consts/issue-90878-2.stderr | 14 + tests/ui/consts/issue-90878-3.rs | 6 + tests/ui/consts/issue-90878-3.stderr | 11 + tests/ui/consts/issue-90878.rs | 4 + tests/ui/consts/issue-90878.stderr | 11 + tests/ui/consts/issue-91434.rs | 5 + tests/ui/consts/issue-91434.stderr | 15 + tests/ui/consts/issue-91560.fixed | 21 + tests/ui/consts/issue-91560.rs | 21 + tests/ui/consts/issue-91560.stderr | 21 + tests/ui/consts/issue-94371.rs | 16 + tests/ui/consts/issue-94675.rs | 15 + tests/ui/consts/issue-94675.stderr | 29 + tests/ui/consts/issue-96169.rs | 18 + tests/ui/consts/issue-broken-mir.rs | 10 + tests/ui/consts/issue-miri-1910.rs | 12 + tests/ui/consts/issue-miri-1910.stderr | 20 + tests/ui/consts/large_const_alloc.rs | 18 + tests/ui/consts/large_const_alloc.stderr | 15 + tests/ui/consts/locals-in-const-fn.rs | 35 + tests/ui/consts/match-const-fn-structs.rs | 22 + tests/ui/consts/match_ice.rs | 18 + tests/ui/consts/match_ice.stderr | 8 + tests/ui/consts/min_const_fn/address_of.rs | 17 + tests/ui/consts/min_const_fn/address_of.stderr | 21 + tests/ui/consts/min_const_fn/address_of_const.rs | 19 + .../min_const_fn/allow_const_fn_ptr_run_pass.rs | 19 + .../allow_raw_ptr_dereference_const_fn.rs | 9 + .../consts/min_const_fn/bad_const_fn_body_ice.rs | 7 + .../min_const_fn/bad_const_fn_body_ice.stderr | 21 + tests/ui/consts/min_const_fn/cast_fn.rs | 11 + tests/ui/consts/min_const_fn/cmp_fn_pointers.rs | 6 + .../ui/consts/min_const_fn/cmp_fn_pointers.stderr | 16 + tests/ui/consts/min_const_fn/min_const_fn.rs | 134 + tests/ui/consts/min_const_fn/min_const_fn.stderr | 213 + tests/ui/consts/min_const_fn/min_const_fn_dyn.rs | 15 + .../ui/consts/min_const_fn/min_const_fn_libstd.rs | 26 + .../min_const_fn/min_const_fn_libstd_stability.rs | 41 + .../min_const_fn_libstd_stability.stderr | 41 + .../consts/min_const_fn/min_const_fn_unsafe_bad.rs | 10 + .../min_const_fn/min_const_fn_unsafe_bad.stderr | 30 + .../consts/min_const_fn/min_const_fn_unsafe_ok.rs | 44 + .../min_const_unsafe_fn_libstd_stability.rs | 42 + .../min_const_unsafe_fn_libstd_stability.stderr | 41 + .../min_const_unsafe_fn_libstd_stability2.rs | 35 + .../min_const_unsafe_fn_libstd_stability2.stderr | 26 + tests/ui/consts/min_const_fn/mutable_borrow.rs | 17 + tests/ui/consts/min_const_fn/mutable_borrow.stderr | 21 + tests/ui/consts/min_const_fn/promotion.rs | 17 + tests/ui/consts/min_const_fn/promotion.stderr | 68 + tests/ui/consts/mir_check_nonconst.rs | 11 + tests/ui/consts/mir_check_nonconst.stderr | 12 + tests/ui/consts/miri_unleashed/abi-mismatch.rs | 18 + tests/ui/consts/miri_unleashed/abi-mismatch.stderr | 28 + tests/ui/consts/miri_unleashed/assoc_const.rs | 30 + tests/ui/consts/miri_unleashed/assoc_const.stderr | 44 + tests/ui/consts/miri_unleashed/assoc_const_2.rs | 28 + .../ui/consts/miri_unleashed/assoc_const_2.stderr | 27 + .../miri_unleashed/auxiliary/static_cross_crate.rs | 3 + tests/ui/consts/miri_unleashed/box.rs | 12 + tests/ui/consts/miri_unleashed/box.stderr | 32 + .../const_refers_to_static.32bit.stderr | 81 + .../const_refers_to_static.64bit.stderr | 81 + .../miri_unleashed/const_refers_to_static.rs | 33 + ...const_refers_to_static_cross_crate.32bit.stderr | 138 + ...const_refers_to_static_cross_crate.64bit.stderr | 138 + .../const_refers_to_static_cross_crate.rs | 76 + tests/ui/consts/miri_unleashed/drop.rs | 17 + tests/ui/consts/miri_unleashed/drop.stderr | 24 + .../feature-gate-unleash_the_miri_inside_of_you.rs | 26 + ...ture-gate-unleash_the_miri_inside_of_you.stderr | 11 + tests/ui/consts/miri_unleashed/inline_asm.rs | 13 + tests/ui/consts/miri_unleashed/inline_asm.stderr | 17 + .../ui/consts/miri_unleashed/mutable_references.rs | 36 + .../miri_unleashed/mutable_references.stderr | 37 + .../mutable_references_err.32bit.stderr | 54 + .../mutable_references_err.64bit.stderr | 54 + .../miri_unleashed/mutable_references_err.rs | 36 + tests/ui/consts/miri_unleashed/mutating_global.rs | 15 + .../consts/miri_unleashed/mutating_global.stderr | 9 + tests/ui/consts/miri_unleashed/non_const_fn.rs | 11 + tests/ui/consts/miri_unleashed/non_const_fn.stderr | 17 + tests/ui/consts/miri_unleashed/ptr_arith.rs | 24 + tests/ui/consts/miri_unleashed/ptr_arith.stderr | 26 + .../ui/consts/miri_unleashed/raw_mutable_const.rs | 8 + .../consts/miri_unleashed/raw_mutable_const.stderr | 16 + tests/ui/consts/miri_unleashed/slice_eq.rs | 13 + tests/ui/consts/miri_unleashed/tls.rs | 23 + tests/ui/consts/miri_unleashed/tls.stderr | 28 + tests/ui/consts/missing_span_in_backtrace.rs | 27 + tests/ui/consts/missing_span_in_backtrace.stderr | 28 + tests/ui/consts/mozjs-error.rs | 31 + tests/ui/consts/nested_erroneous_ctfe.rs | 4 + tests/ui/consts/nested_erroneous_ctfe.stderr | 12 + tests/ui/consts/non-const-value-in-const.rs | 7 + tests/ui/consts/non-const-value-in-const.stderr | 20 + tests/ui/consts/non-scalar-cast.rs | 9 + tests/ui/consts/offset.rs | 112 + tests/ui/consts/offset_from.rs | 59 + tests/ui/consts/offset_from_ub.rs | 125 + tests/ui/consts/offset_from_ub.stderr | 114 + tests/ui/consts/offset_ub.rs | 26 + tests/ui/consts/offset_ub.stderr | 159 + tests/ui/consts/packed_pattern.rs | 19 + tests/ui/consts/packed_pattern.stderr | 10 + tests/ui/consts/packed_pattern2.rs | 27 + tests/ui/consts/packed_pattern2.stderr | 10 + tests/ui/consts/partial_qualif.rs | 9 + tests/ui/consts/partial_qualif.stderr | 9 + tests/ui/consts/precise-drop-with-coverage.rs | 16 + tests/ui/consts/precise-drop-with-promoted.rs | 9 + tests/ui/consts/promote-not.rs | 68 + tests/ui/consts/promote-not.stderr | 215 + tests/ui/consts/promote_borrowed_field.rs | 12 + tests/ui/consts/promote_const_let.rs | 10 + tests/ui/consts/promote_const_let.stderr | 29 + .../ui/consts/promote_evaluation_unused_result.rs | 6 + tests/ui/consts/promote_fn_calls.rs | 11 + tests/ui/consts/promote_fn_calls_std.rs | 29 + tests/ui/consts/promoted-const-drop.rs | 15 + tests/ui/consts/promoted-const-drop.stderr | 24 + tests/ui/consts/promoted-storage.rs | 20 + tests/ui/consts/promoted-validation-55454.rs | 9 + tests/ui/consts/promoted_const_call.rs | 19 + tests/ui/consts/promoted_const_call.stderr | 65 + tests/ui/consts/promoted_const_call2.rs | 14 + tests/ui/consts/promoted_const_call2.stderr | 50 + tests/ui/consts/promoted_const_call3.rs | 26 + tests/ui/consts/promoted_const_call3.stderr | 105 + tests/ui/consts/promoted_const_call4.rs | 18 + tests/ui/consts/promoted_const_call5.rs | 42 + tests/ui/consts/promoted_const_call5.stderr | 74 + tests/ui/consts/promoted_regression.rs | 9 + tests/ui/consts/promotion-mutable-ref.rs | 17 + tests/ui/consts/promotion.rs | 45 + tests/ui/consts/ptr_comparisons.rs | 63 + tests/ui/consts/ptr_comparisons.stderr | 40 + tests/ui/consts/ptr_is_null.rs | 16 + tests/ui/consts/qualif-indirect-mutation-fail.rs | 64 + .../ui/consts/qualif-indirect-mutation-fail.stderr | 57 + tests/ui/consts/qualif-indirect-mutation-pass.rs | 24 + tests/ui/consts/qualif-union.rs | 33 + tests/ui/consts/qualif-union.stderr | 57 + tests/ui/consts/qualif_overwrite.rs | 13 + tests/ui/consts/qualif_overwrite.stderr | 9 + tests/ui/consts/qualif_overwrite_2.rs | 11 + tests/ui/consts/qualif_overwrite_2.stderr | 9 + tests/ui/consts/raw-ptr-const.rs | 8 + tests/ui/consts/raw-ptr-const.stderr | 8 + tests/ui/consts/raw_pointer_promoted.rs | 5 + .../ui/consts/recursive-zst-static.default.stderr | 25 + tests/ui/consts/recursive-zst-static.rs | 14 + .../ui/consts/recursive-zst-static.unleash.stderr | 25 + tests/ui/consts/recursive.rs | 10 + tests/ui/consts/recursive.stderr | 36 + tests/ui/consts/references.rs | 27 + tests/ui/consts/refs_check_const_eq-issue-88384.rs | 25 + .../consts/refs_check_const_eq-issue-88384.stderr | 24 + .../refs_check_const_value_eq-issue-88876.rs | 12 + tests/ui/consts/repeat_match.rs | 12 + tests/ui/consts/return-in-const-fn.rs | 10 + .../consts/rustc-const-stability-require-const.rs | 47 + .../rustc-const-stability-require-const.stderr | 86 + tests/ui/consts/rustc-impl-const-stability.rs | 19 + tests/ui/consts/rvalue-static-promotion.rs | 19 + tests/ui/consts/self_normalization.rs | 16 + tests/ui/consts/self_normalization2.rs | 21 + tests/ui/consts/signed_enum_discr.rs | 19 + .../consts/stable-precise-live-drops-in-libcore.rs | 22 + .../stable-precise-live-drops-in-libcore.stderr | 12 + tests/ui/consts/static-cycle-error.rs | 11 + tests/ui/consts/static-raw-pointer-interning.rs | 15 + tests/ui/consts/static-raw-pointer-interning2.rs | 15 + tests/ui/consts/static_mut_containing_mut_ref.rs | 7 + .../static_mut_containing_mut_ref2.mut_refs.stderr | 9 + tests/ui/consts/static_mut_containing_mut_ref2.rs | 11 + .../static_mut_containing_mut_ref2.stock.stderr | 12 + tests/ui/consts/static_mut_containing_mut_ref3.rs | 6 + .../consts/static_mut_containing_mut_ref3.stderr | 9 + tests/ui/consts/std/alloc.32bit.stderr | 25 + tests/ui/consts/std/alloc.64bit.stderr | 25 + tests/ui/consts/std/alloc.rs | 19 + tests/ui/consts/std/cell.rs | 46 + tests/ui/consts/std/cell.stderr | 26 + tests/ui/consts/std/iter.rs | 9 + tests/ui/consts/std/slice.rs | 10 + tests/ui/consts/too_generic_eval_ice.rs | 14 + tests/ui/consts/too_generic_eval_ice.stderr | 37 + tests/ui/consts/trait_specialization.rs | 65 + tests/ui/consts/trait_specialization.stderr | 12 + tests/ui/consts/transmute-const.rs | 12 + .../transmute-size-mismatch-before-typeck.rs | 13 + .../transmute-size-mismatch-before-typeck.stderr | 12 + tests/ui/consts/try-operator.rs | 23 + tests/ui/consts/tuple-struct-constructors.rs | 10 + tests/ui/consts/underscore_const_names.rs | 31 + tests/ui/consts/uninhabited-const-issue-61744.rs | 19 + .../ui/consts/uninhabited-const-issue-61744.stderr | 668 ++ tests/ui/consts/union_constant.rs | 11 + tests/ui/consts/unnormalized-param-env.rs | 31 + tests/ui/consts/unstable-const-fn-in-libcore.rs | 27 + .../ui/consts/unstable-const-fn-in-libcore.stderr | 21 + .../unstable-precise-live-drops-in-libcore.rs | 23 + tests/ui/consts/unwind-abort.rs | 16 + tests/ui/consts/validate_never_arrays.rs | 12 + tests/ui/consts/validate_never_arrays.stderr | 36 + tests/ui/consts/write-to-static-mut-in-static.rs | 10 + .../ui/consts/write-to-static-mut-in-static.stderr | 34 + tests/ui/consts/write_to_mut_ref_dest.rs | 17 + tests/ui/consts/write_to_mut_ref_dest.stock.stderr | 21 + tests/ui/consts/write_to_static_via_mut_ref.rs | 7 + tests/ui/consts/write_to_static_via_mut_ref.stderr | 16 + tests/ui/consts/zst_no_llvm_alloc.rs | 21 + tests/ui/copy-a-resource.rs | 21 + tests/ui/copy-a-resource.stderr | 16 + tests/ui/crate-leading-sep.rs | 7 + .../ui/crate-loading/auxiliary/crateresolve1-1.rs | 6 + .../ui/crate-loading/auxiliary/crateresolve1-2.rs | 6 + .../ui/crate-loading/auxiliary/crateresolve1-3.rs | 6 + .../ui/crate-loading/auxiliary/crateresolve2-1.rs | 5 + .../ui/crate-loading/auxiliary/crateresolve2-2.rs | 5 + .../ui/crate-loading/auxiliary/crateresolve2-3.rs | 5 + tests/ui/crate-loading/auxiliary/libfoo.rlib | 0 tests/ui/crate-loading/auxiliary/proc-macro.rs | 12 + tests/ui/crate-loading/crateresolve1.rs | 14 + tests/ui/crate-loading/crateresolve1.stderr | 13 + tests/ui/crate-loading/crateresolve2.rs | 13 + tests/ui/crate-loading/crateresolve2.stderr | 13 + .../ui/crate-loading/cross-compiled-proc-macro.rs | 8 + tests/ui/crate-loading/invalid-rlib.rs | 10 + tests/ui/crate-loading/invalid-rlib.stderr | 19 + tests/ui/crate-loading/missing-std.rs | 12 + tests/ui/crate-loading/missing-std.stderr | 15 + tests/ui/crate-method-reexport-grrrrrrr.rs | 19 + tests/ui/crate-name-attr-used.rs | 8 + tests/ui/crate-name-mismatch.rs | 6 + tests/ui/crate-name-mismatch.stderr | 8 + tests/ui/cross-crate/auxiliary/cci_borrow_lib.rs | 3 + .../ui/cross-crate/auxiliary/cci_capture_clause.rs | 10 + tests/ui/cross-crate/auxiliary/cci_const.rs | 6 + tests/ui/cross-crate/auxiliary/cci_impl_lib.rs | 16 + tests/ui/cross-crate/auxiliary/cci_iter_lib.rs | 11 + tests/ui/cross-crate/auxiliary/cci_nested_lib.rs | 50 + .../ui/cross-crate/auxiliary/cci_no_inline_lib.rs | 12 + .../auxiliary/moves_based_on_type_lib.rs | 17 + tests/ui/cross-crate/auxiliary/pub_static_array.rs | 1 + .../auxiliary/reexported_static_methods.rs | 43 + tests/ui/cross-crate/auxiliary/static_init_aux.rs | 10 + .../auxiliary/xcrate-trait-lifetime-param.rs | 3 + .../auxiliary/xcrate_address_insignificant.rs | 8 + .../auxiliary/xcrate_associated_type_defaults.rs | 12 + .../auxiliary/xcrate_generic_fn_nested_return.rs | 16 + .../auxiliary/xcrate_static_addresses.rs | 17 + tests/ui/cross-crate/cci_borrow.rs | 12 + tests/ui/cross-crate/cci_capture_clause.rs | 14 + tests/ui/cross-crate/cci_impl_exe.rs | 18 + tests/ui/cross-crate/cci_iter_exe.rs | 13 + tests/ui/cross-crate/cci_nested_exe.rs | 20 + tests/ui/cross-crate/cci_no_inline_exe.rs | 23 + tests/ui/cross-crate/const-cross-crate-const.rs | 16 + tests/ui/cross-crate/const-cross-crate-extern.rs | 11 + tests/ui/cross-crate/cross-crate-const-pat.rs | 14 + .../cross-crate/issue-64872/auxiliary/a_def_obj.rs | 16 + .../issue-64872/auxiliary/b_reexport_obj.rs | 7 + .../auxiliary/c_another_vtable_for_obj.rs | 12 + .../auxiliary/d_chain_of_rlibs_and_dylibs.rs | 9 + tests/ui/cross-crate/issue-64872/issue-64872.rs | 17 + .../cross-crate/moves-based-on-type-cross-crate.rs | 11 + .../reexported-static-methods-cross-crate.rs | 16 + tests/ui/cross-crate/static-array-across-crate.rs | 13 + tests/ui/cross-crate/static-init.rs | 15 + .../ui/cross-crate/xcrate-address-insignificant.rs | 9 + .../cross-crate/xcrate-associated-type-defaults.rs | 29 + tests/ui/cross-crate/xcrate-static-addresses.rs | 13 + .../ui/cross-crate/xcrate-trait-lifetime-param.rs | 19 + .../cross-crate/xcrate_generic_fn_nested_return.rs | 8 + tests/ui/cross/cross-borrow-trait.rs | 13 + tests/ui/cross/cross-borrow-trait.stderr | 14 + .../auxiliary/extern_macro_crate.rs | 13 + tests/ui/cross/cross-crate-macro-backtrace/main.rs | 8 + .../cross/cross-crate-macro-backtrace/main.stderr | 10 + tests/ui/cross/cross-file-errors/main.rs | 7 + tests/ui/cross/cross-file-errors/main.stderr | 15 + tests/ui/cross/cross-file-errors/underscore.rs | 10 + tests/ui/cross/cross-fn-cache-hole.rs | 31 + tests/ui/cross/cross-fn-cache-hole.stderr | 12 + tests/ui/custom-attribute-multisegment.rs | 6 + tests/ui/custom-attribute-multisegment.stderr | 9 + tests/ui/custom-test-frameworks-simple.rs | 22 + tests/ui/custom_attribute.rs | 9 + tests/ui/custom_attribute.stderr | 20 + .../auxiliary/dynamic_runner.rs | 35 + .../auxiliary/example_runner.rs | 10 + tests/ui/custom_test_frameworks/dynamic.rs | 35 + tests/ui/custom_test_frameworks/full.rs | 28 + tests/ui/custom_test_frameworks/mismatch.rs | 10 + tests/ui/custom_test_frameworks/mismatch.stderr | 14 + .../cycle-trait/cycle-trait-default-type-trait.rs | 8 + .../cycle-trait-default-type-trait.stderr | 20 + .../cycle-trait/cycle-trait-supertrait-direct.rs | 7 + .../cycle-trait-supertrait-direct.stderr | 23 + .../cycle-trait/cycle-trait-supertrait-indirect.rs | 13 + .../cycle-trait-supertrait-indirect.stderr | 31 + .../debuginfo-box-with-large-allocator.rs | 23 + .../debuginfo-emit-llvm-ir-and-split-debuginfo.rs | 8 + .../debuginfo-type-name-layout-ice-94961-1.rs | 16 + .../debuginfo-type-name-layout-ice-94961-1.stderr | 4 + .../debuginfo-type-name-layout-ice-94961-2.rs | 20 + .../debuginfo-type-name-layout-ice-94961-2.stderr | 4 + ...buginfo_with_uninhabitable_field_and_unsized.rs | 29 + tests/ui/debuginfo/issue-105386-debuginfo-ub.rs | 20 + tests/ui/debuginfo/late-bound-projection.rs | 7 + .../ui/deduplicate-diagnostics.deduplicate.stderr | 15 + tests/ui/deduplicate-diagnostics.duplicate.stderr | 27 + tests/ui/deduplicate-diagnostics.rs | 10 + tests/ui/deep.rs | 8 + tests/ui/default-method-parsing.rs | 8 + tests/ui/default-method-simple.rs | 26 + tests/ui/defaults-well-formedness.rs | 27 + .../auxiliary/field-method-macro.rs | 23 + .../auxiliary/nested-fn-macro.rs | 11 + .../auxiliary/private-use-macro.rs | 11 + tests/ui/definition-reachable/field-method.rs | 11 + tests/ui/definition-reachable/nested-fn.rs | 11 + tests/ui/definition-reachable/private-non-types.rs | 21 + tests/ui/definition-reachable/private-types.rs | 19 + tests/ui/definition-reachable/private-use.rs | 10 + tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs | 38 + .../dep-graph/dep-graph-assoc-type-codegen.stderr | 8 + tests/ui/dep-graph/dep-graph-caller-callee.rs | 36 + tests/ui/dep-graph/dep-graph-caller-callee.stderr | 14 + tests/ui/dep-graph/dep-graph-check-attr.rs | 20 + tests/ui/dep-graph/dep-graph-check-attr.stderr | 26 + tests/ui/dep-graph/dep-graph-dump.rs | 6 + tests/ui/dep-graph/dep-graph-dump.stderr | 2 + tests/ui/dep-graph/dep-graph-struct-signature.rs | 87 + .../ui/dep-graph/dep-graph-struct-signature.stderr | 134 + .../dep-graph-trait-impl-two-traits-same-method.rs | 46 + ...-graph-trait-impl-two-traits-same-method.stderr | 14 + .../dep-graph/dep-graph-trait-impl-two-traits.rs | 45 + .../dep-graph-trait-impl-two-traits.stderr | 14 + tests/ui/dep-graph/dep-graph-trait-impl.rs | 61 + tests/ui/dep-graph/dep-graph-trait-impl.stderr | 32 + tests/ui/dep-graph/dep-graph-type-alias.rs | 56 + tests/ui/dep-graph/dep-graph-type-alias.stderr | 74 + tests/ui/dep-graph/dep-graph-variance-alias.rs | 22 + tests/ui/dep-graph/dep-graph-variance-alias.stderr | 8 + tests/ui/deprecation-in-force-unstable.rs | 5 + tests/ui/deprecation/atomic_initializers.fixed | 11 + tests/ui/deprecation/atomic_initializers.rs | 11 + tests/ui/deprecation/atomic_initializers.stderr | 14 + tests/ui/deprecation/auxiliary/deprecation-lint.rs | 98 + .../deprecation/deprecated-macro_escape-inner.rs | 8 + .../deprecated-macro_escape-inner.stderr | 10 + tests/ui/deprecation/deprecated-macro_escape.rs | 6 + .../ui/deprecation/deprecated-macro_escape.stderr | 8 + tests/ui/deprecation/deprecated_no_stack_check.rs | 6 + .../deprecation/deprecated_no_stack_check.stderr | 9 + tests/ui/deprecation/deprecation-in-future.rs | 13 + tests/ui/deprecation/deprecation-in-future.stderr | 10 + tests/ui/deprecation/deprecation-lint-2.rs | 13 + tests/ui/deprecation/deprecation-lint-2.stderr | 15 + tests/ui/deprecation/deprecation-lint-3.rs | 14 + tests/ui/deprecation/deprecation-lint-3.stderr | 14 + tests/ui/deprecation/deprecation-lint-nested.rs | 71 + .../ui/deprecation/deprecation-lint-nested.stderr | 44 + tests/ui/deprecation/deprecation-lint.rs | 454 + tests/ui/deprecation/deprecation-lint.stderr | 747 ++ tests/ui/deprecation/deprecation-sanity.rs | 42 + tests/ui/deprecation/deprecation-sanity.stderr | 74 + tests/ui/deprecation/derive_on_deprecated.rs | 15 + .../deprecation/derive_on_deprecated_forbidden.rs | 9 + .../feature-gate-deprecated_suggestion.rs | 6 + .../feature-gate-deprecated_suggestion.stderr | 11 + tests/ui/deprecation/invalid-literal.rs | 4 + tests/ui/deprecation/invalid-literal.stderr | 17 + ...issue-66340-deprecated-attr-non-meta-grammar.rs | 11 + ...e-66340-deprecated-attr-non-meta-grammar.stderr | 8 + ...ssue-84637-deprecated-associated-function.fixed | 9 + .../issue-84637-deprecated-associated-function.rs | 9 + ...sue-84637-deprecated-associated-function.stderr | 29 + .../ui/deprecation/staged-deprecation-in-future.rs | 18 + .../staged-deprecation-in-future.stderr | 20 + tests/ui/deprecation/suggestion.fixed | 43 + tests/ui/deprecation/suggestion.rs | 43 + tests/ui/deprecation/suggestion.stderr | 29 + tests/ui/deprecation/try-macro-suggestion.rs | 9 + tests/ui/deprecation/try-macro-suggestion.stderr | 31 + tests/ui/deref-non-pointer.rs | 5 + tests/ui/deref-non-pointer.stderr | 9 + tests/ui/deref-patterns/basic.rs | 17 + tests/ui/deref-patterns/basic.run.stdout | 3 + tests/ui/deref-patterns/default-infer.rs | 9 + tests/ui/deref-patterns/gate.rs | 7 + tests/ui/deref-patterns/gate.stderr | 11 + tests/ui/deref-patterns/refs.rs | 18 + tests/ui/deref-rc.rs | 8 + tests/ui/deref.rs | 7 + tests/ui/derive-uninhabited-enum-38885.rs | 19 + tests/ui/derive-uninhabited-enum-38885.stderr | 14 + tests/ui/derived-errors/issue-30580.rs | 17 + tests/ui/derived-errors/issue-30580.stderr | 9 + tests/ui/derived-errors/issue-31997-1.rs | 56 + tests/ui/derived-errors/issue-31997-1.stderr | 14 + tests/ui/derived-errors/issue-31997.rs | 18 + tests/ui/derived-errors/issue-31997.stderr | 9 + tests/ui/derives/auxiliary/derive-marker-tricky.rs | 15 + .../clone-debug-dead-code-in-the-same-struct.rs | 12 + ...clone-debug-dead-code-in-the-same-struct.stderr | 24 + tests/ui/derives/clone-debug-dead-code.rs | 45 + tests/ui/derives/clone-debug-dead-code.stderr | 54 + tests/ui/derives/derive-Debug-use-ufcs-struct.rs | 40 + tests/ui/derives/derive-Debug-use-ufcs-tuple.rs | 32 + tests/ui/derives/derive-assoc-type-not-impl.rs | 19 + tests/ui/derives/derive-assoc-type-not-impl.stderr | 31 + tests/ui/derives/derive-deadlock.rs | 6 + tests/ui/derives/derive-deadlock.stderr | 10 + tests/ui/derives/derive-hygiene.rs | 121 + tests/ui/derives/derive-macro-const-default.rs | 11 + tests/ui/derives/derive-marker-tricky.rs | 16 + tests/ui/derives/derive-multiple-with-packed.rs | 10 + .../derives/derive-on-trait-item-or-impl-item.rs | 15 + .../derive-on-trait-item-or-impl-item.stderr | 21 + tests/ui/derives/derive-partial-ord.rs | 60 + tests/ui/derives/derive-renamed.rs | 11 + .../derives-span-Clone-enum-struct-variant.rs | 13 + .../derives-span-Clone-enum-struct-variant.stderr | 18 + tests/ui/derives/derives-span-Clone-enum.rs | 13 + tests/ui/derives/derives-span-Clone-enum.stderr | 18 + tests/ui/derives/derives-span-Clone-struct.rs | 11 + tests/ui/derives/derives-span-Clone-struct.stderr | 18 + .../ui/derives/derives-span-Clone-tuple-struct.rs | 11 + .../derives/derives-span-Clone-tuple-struct.stderr | 18 + .../derives-span-Debug-enum-struct-variant.rs | 13 + .../derives-span-Debug-enum-struct-variant.stderr | 20 + tests/ui/derives/derives-span-Debug-enum.rs | 13 + tests/ui/derives/derives-span-Debug-enum.stderr | 20 + tests/ui/derives/derives-span-Debug-struct.rs | 11 + tests/ui/derives/derives-span-Debug-struct.stderr | 20 + .../ui/derives/derives-span-Debug-tuple-struct.rs | 11 + .../derives/derives-span-Debug-tuple-struct.stderr | 20 + tests/ui/derives/derives-span-Default-struct.rs | 11 + .../ui/derives/derives-span-Default-struct.stderr | 18 + .../derives/derives-span-Default-tuple-struct.rs | 11 + .../derives-span-Default-tuple-struct.stderr | 18 + .../derives/derives-span-Eq-enum-struct-variant.rs | 13 + .../derives-span-Eq-enum-struct-variant.stderr | 20 + tests/ui/derives/derives-span-Eq-enum.rs | 13 + tests/ui/derives/derives-span-Eq-enum.stderr | 20 + tests/ui/derives/derives-span-Eq-struct.rs | 11 + tests/ui/derives/derives-span-Eq-struct.stderr | 20 + tests/ui/derives/derives-span-Eq-tuple-struct.rs | 11 + .../ui/derives/derives-span-Eq-tuple-struct.stderr | 20 + .../derives-span-Hash-enum-struct-variant.rs | 13 + .../derives-span-Hash-enum-struct-variant.stderr | 18 + tests/ui/derives/derives-span-Hash-enum.rs | 12 + tests/ui/derives/derives-span-Hash-enum.stderr | 18 + tests/ui/derives/derives-span-Hash-struct.rs | 11 + tests/ui/derives/derives-span-Hash-struct.stderr | 18 + tests/ui/derives/derives-span-Hash-tuple-struct.rs | 11 + .../derives/derives-span-Hash-tuple-struct.stderr | 18 + .../derives-span-Ord-enum-struct-variant.rs | 13 + .../derives-span-Ord-enum-struct-variant.stderr | 18 + tests/ui/derives/derives-span-Ord-enum.rs | 13 + tests/ui/derives/derives-span-Ord-enum.stderr | 18 + tests/ui/derives/derives-span-Ord-struct.rs | 11 + tests/ui/derives/derives-span-Ord-struct.stderr | 18 + tests/ui/derives/derives-span-Ord-tuple-struct.rs | 11 + .../derives/derives-span-Ord-tuple-struct.stderr | 18 + .../derives-span-PartialEq-enum-struct-variant.rs | 13 + ...rives-span-PartialEq-enum-struct-variant.stderr | 23 + tests/ui/derives/derives-span-PartialEq-enum.rs | 13 + .../ui/derives/derives-span-PartialEq-enum.stderr | 23 + tests/ui/derives/derives-span-PartialEq-struct.rs | 11 + .../derives/derives-span-PartialEq-struct.stderr | 23 + .../derives/derives-span-PartialEq-tuple-struct.rs | 11 + .../derives-span-PartialEq-tuple-struct.stderr | 23 + .../derives-span-PartialOrd-enum-struct-variant.rs | 13 + ...ives-span-PartialOrd-enum-struct-variant.stderr | 19 + tests/ui/derives/derives-span-PartialOrd-enum.rs | 13 + .../ui/derives/derives-span-PartialOrd-enum.stderr | 19 + tests/ui/derives/derives-span-PartialOrd-struct.rs | 11 + .../derives/derives-span-PartialOrd-struct.stderr | 19 + .../derives-span-PartialOrd-tuple-struct.rs | 11 + .../derives-span-PartialOrd-tuple-struct.stderr | 19 + tests/ui/derives/deriving-bounds.rs | 11 + tests/ui/derives/deriving-bounds.stderr | 50 + tests/ui/derives/deriving-copyclone.rs | 37 + tests/ui/derives/deriving-copyclone.stderr | 75 + tests/ui/derives/deriving-meta-empty-trait-list.rs | 8 + tests/ui/derives/deriving-meta-unknown-trait.rs | 6 + .../ui/derives/deriving-meta-unknown-trait.stderr | 20 + .../deriving-no-inner-impl-error-message.rs | 14 + .../deriving-no-inner-impl-error-message.stderr | 39 + tests/ui/derives/deriving-non-type.rs | 30 + tests/ui/derives/deriving-non-type.stderr | 75 + tests/ui/derives/deriving-primitive.rs | 5 + tests/ui/derives/deriving-primitive.stderr | 14 + tests/ui/derives/deriving-with-repr-packed.rs | 45 + tests/ui/derives/deriving-with-repr-packed.stderr | 111 + tests/ui/derives/issue-36617.rs | 16 + tests/ui/derives/issue-36617.stderr | 97 + tests/ui/derives/issue-43023.rs | 20 + tests/ui/derives/issue-43023.stderr | 29 + tests/ui/derives/issue-91492.rs | 25 + tests/ui/derives/issue-91492.stderr | 59 + tests/ui/derives/issue-91550.rs | 29 + tests/ui/derives/issue-91550.stderr | 131 + tests/ui/derives/issue-97343.rs | 8 + tests/ui/derives/issue-97343.stderr | 21 + tests/ui/deriving/auxiliary/derive-no-std.rs | 29 + tests/ui/deriving/derive-no-std.rs | 12 + tests/ui/deriving/derive-partialord-correctness.rs | 9 + tests/ui/deriving/deriving-all-codegen.rs | 106 + tests/ui/deriving/deriving-all-codegen.stdout | 1074 ++ tests/ui/deriving/deriving-associated-types.rs | 199 + tests/ui/deriving/deriving-bounds.rs | 5 + tests/ui/deriving/deriving-clone-array.rs | 10 + tests/ui/deriving/deriving-clone-enum.rs | 14 + tests/ui/deriving/deriving-clone-generic-enum.rs | 14 + tests/ui/deriving/deriving-clone-generic-struct.rs | 15 + .../deriving-clone-generic-tuple-struct.rs | 10 + tests/ui/deriving/deriving-clone-struct.rs | 28 + tests/ui/deriving/deriving-clone-tuple-struct.rs | 9 + tests/ui/deriving/deriving-cmp-generic-enum.rs | 44 + .../deriving/deriving-cmp-generic-struct-enum.rs | 48 + tests/ui/deriving/deriving-cmp-generic-struct.rs | 40 + .../deriving/deriving-cmp-generic-tuple-struct.rs | 38 + tests/ui/deriving/deriving-cmp-shortcircuit.rs | 37 + tests/ui/deriving/deriving-copyclone.rs | 38 + tests/ui/deriving/deriving-default-box.rs | 13 + tests/ui/deriving/deriving-default-enum.rs | 27 + tests/ui/deriving/deriving-enum-single-variant.rs | 12 + tests/ui/deriving/deriving-eq-ord-boxed-slice.rs | 15 + tests/ui/deriving/deriving-hash.rs | 96 + tests/ui/deriving/deriving-in-fn.rs | 13 + tests/ui/deriving/deriving-in-macro.rs | 16 + tests/ui/deriving/deriving-meta-multiple.rs | 26 + tests/ui/deriving/deriving-meta.rs | 23 + .../deriving-self-lifetime-totalord-totaleq.rs | 16 + tests/ui/deriving/deriving-show-2.rs | 54 + tests/ui/deriving/deriving-show.rs | 35 + tests/ui/deriving/deriving-via-extension-c-enum.rs | 17 + tests/ui/deriving/deriving-via-extension-enum.rs | 16 + .../deriving/deriving-via-extension-hash-enum.rs | 17 + .../deriving/deriving-via-extension-hash-struct.rs | 12 + .../deriving-via-extension-struct-empty.rs | 8 + ...iving-via-extension-struct-like-enum-variant.rs | 13 + .../deriving-via-extension-struct-tuple.rs | 17 + tests/ui/deriving/deriving-via-extension-struct.rs | 16 + .../deriving/deriving-via-extension-type-params.rs | 16 + tests/ui/deriving/deriving-with-helper.rs | 36 + tests/ui/deriving/deriving-with-repr-packed.rs | 36 + tests/ui/deriving/issue-103157.rs | 12 + tests/ui/deriving/issue-103157.stderr | 27 + tests/ui/deriving/issue-105101.rs | 9 + tests/ui/deriving/issue-105101.stderr | 29 + tests/ui/deriving/issue-19358.rs | 23 + tests/ui/deriving/issue-3935.rs | 13 + tests/ui/deriving/issue-58319.rs | 622 ++ tests/ui/deriving/issue-6341.rs | 11 + tests/ui/deriving/issue-89188-gat-hrtb.rs | 37 + tests/ui/dest-prop/skeptic-miscompile.rs | 24 + tests/ui/destructure-trait-ref.rs | 44 + tests/ui/destructure-trait-ref.stderr | 65 + tests/ui/destructuring-assignment/bad-expr-lhs.rs | 9 + .../destructuring-assignment/bad-expr-lhs.stderr | 44 + .../default-match-bindings-forbidden.rs | 5 + .../default-match-bindings-forbidden.stderr | 14 + tests/ui/destructuring-assignment/drop-order.rs | 43 + .../destructuring-assignment/nested_destructure.rs | 18 + .../destructuring-assignment/note-unsupported.rs | 22 + .../note-unsupported.stderr | 66 + .../destructuring-assignment/slice_destructure.rs | 15 + .../slice_destructure_fail.rs | 6 + .../slice_destructure_fail.stderr | 23 + .../struct-or-enum-variant-path.rs | 34 + .../destructuring-assignment/struct_destructure.rs | 20 + .../struct_destructure_fail.rs | 16 + .../struct_destructure_fail.stderr | 45 + .../destructuring-assignment/tuple_destructure.rs | 37 + .../tuple_destructure_fail.rs | 9 + .../tuple_destructure_fail.stderr | 42 + .../tuple_struct_destructure.rs | 34 + .../tuple_struct_destructure_fail.rs | 44 + .../tuple_struct_destructure_fail.stderr | 98 + .../warn-unused-duplication.rs | 21 + .../warn-unused-duplication.stderr | 15 + tests/ui/diagnostic-width/E0271.rs | 33 + tests/ui/diagnostic-width/E0271.stderr | 23 + tests/ui/diagnostic-width/flag-human.rs | 9 + tests/ui/diagnostic-width/flag-human.stderr | 11 + tests/ui/diagnostic-width/flag-json.rs | 9 + tests/ui/diagnostic-width/flag-json.stderr | 40 + tests/ui/diagnostic-width/long-E0308.rs | 97 + tests/ui/diagnostic-width/long-E0308.stderr | 80 + .../non-1-width-unicode-multiline-label.rs | 7 + .../non-1-width-unicode-multiline-label.stderr | 18 + .../diagnostic-width/non-whitespace-trimming-2.rs | 6 + .../non-whitespace-trimming-2.stderr | 11 + .../non-whitespace-trimming-unicode.rs | 6 + .../non-whitespace-trimming-unicode.stderr | 11 + .../ui/diagnostic-width/non-whitespace-trimming.rs | 6 + .../non-whitespace-trimming.stderr | 11 + tests/ui/diagnostic-width/tabs-trimming.rs | 13 + tests/ui/diagnostic-width/tabs-trimming.stderr | 12 + tests/ui/diagnostic-width/whitespace-trimming-2.rs | 8 + .../diagnostic-width/whitespace-trimming-2.stderr | 11 + tests/ui/diagnostic-width/whitespace-trimming.rs | 6 + .../ui/diagnostic-width/whitespace-trimming.stderr | 11 + tests/ui/did_you_mean/E0178.rs | 13 + tests/ui/did_you_mean/E0178.stderr | 27 + tests/ui/did_you_mean/bad-assoc-expr.rs | 36 + tests/ui/did_you_mean/bad-assoc-expr.stderr | 61 + tests/ui/did_you_mean/bad-assoc-pat.rs | 36 + tests/ui/did_you_mean/bad-assoc-pat.stderr | 85 + tests/ui/did_you_mean/bad-assoc-ty.rs | 85 + tests/ui/did_you_mean/bad-assoc-ty.stderr | 282 + .../brackets-to-braces-single-element.rs | 10 + .../brackets-to-braces-single-element.stderr | 38 + .../ui/did_you_mean/compatible-variants-in-pat.rs | 41 + .../did_you_mean/compatible-variants-in-pat.stderr | 68 + tests/ui/did_you_mean/compatible-variants.rs | 89 + tests/ui/did_you_mean/compatible-variants.stderr | 221 + tests/ui/did_you_mean/issue-103909.rs | 9 + tests/ui/did_you_mean/issue-103909.stderr | 26 + .../issue-21659-show-relevant-trait-impls-1.rs | 26 + .../issue-21659-show-relevant-trait-impls-1.stderr | 15 + .../issue-21659-show-relevant-trait-impls-2.rs | 30 + .../issue-21659-show-relevant-trait-impls-2.stderr | 19 + tests/ui/did_you_mean/issue-31424.rs | 21 + tests/ui/did_you_mean/issue-31424.stderr | 49 + tests/ui/did_you_mean/issue-34126.rs | 15 + tests/ui/did_you_mean/issue-34126.stderr | 31 + tests/ui/did_you_mean/issue-34337.rs | 8 + tests/ui/did_you_mean/issue-34337.stderr | 12 + tests/ui/did_you_mean/issue-35937.rs | 21 + tests/ui/did_you_mean/issue-35937.stderr | 37 + tests/ui/did_you_mean/issue-36798.rs | 8 + tests/ui/did_you_mean/issue-36798.stderr | 9 + tests/ui/did_you_mean/issue-36798_unknown_field.rs | 8 + .../did_you_mean/issue-36798_unknown_field.stderr | 11 + tests/ui/did_you_mean/issue-37139.rs | 16 + tests/ui/did_you_mean/issue-37139.stderr | 12 + .../issue-38054-do-not-show-unresolved-names.rs | 5 + ...issue-38054-do-not-show-unresolved-names.stderr | 15 + tests/ui/did_you_mean/issue-38147-1.rs | 21 + tests/ui/did_you_mean/issue-38147-1.stderr | 14 + tests/ui/did_you_mean/issue-38147-2.rs | 17 + tests/ui/did_you_mean/issue-38147-2.stderr | 25 + tests/ui/did_you_mean/issue-38147-3.rs | 12 + tests/ui/did_you_mean/issue-38147-3.stderr | 14 + tests/ui/did_you_mean/issue-38147-4.rs | 9 + tests/ui/did_you_mean/issue-38147-4.stderr | 14 + tests/ui/did_you_mean/issue-39544.rs | 50 + tests/ui/did_you_mean/issue-39544.stderr | 131 + .../did_you_mean/issue-39802-show-5-trait-impls.rs | 27 + .../issue-39802-show-5-trait-impls.stderr | 48 + tests/ui/did_you_mean/issue-40006.rs | 39 + tests/ui/did_you_mean/issue-40006.stderr | 98 + tests/ui/did_you_mean/issue-40396.rs | 29 + tests/ui/did_you_mean/issue-40396.stderr | 112 + tests/ui/did_you_mean/issue-40823.rs | 4 + tests/ui/did_you_mean/issue-40823.stderr | 14 + ...ssue-41679-tilde-bitwise-negation-attempt.fixed | 10 + .../issue-41679-tilde-bitwise-negation-attempt.rs | 10 + ...sue-41679-tilde-bitwise-negation-attempt.stderr | 40 + .../issue-42599_available_fields_note.rs | 37 + .../issue-42599_available_fields_note.stderr | 32 + tests/ui/did_you_mean/issue-42764.rs | 30 + tests/ui/did_you_mean/issue-42764.stderr | 36 + .../issue-43871-enum-instead-of-variant.rs | 36 + .../issue-43871-enum-instead-of-variant.stderr | 66 + .../issue-46718-struct-pattern-dotdotdot.rs | 17 + .../issue-46718-struct-pattern-dotdotdot.stderr | 8 + ...sue-46836-identifier-not-instead-of-negation.rs | 34 + ...46836-identifier-not-instead-of-negation.stderr | 56 + ...issue-48492-tuple-destructure-missing-parens.rs | 87 + ...e-48492-tuple-destructure-missing-parens.stderr | 74 + ...746-unicode-confusable-in-float-literal-expt.rs | 6 + ...unicode-confusable-in-float-literal-expt.stderr | 38 + ...e-53280-expected-float-found-integer-literal.rs | 19 + ...280-expected-float-found-integer-literal.stderr | 49 + .../issue-54109-and_instead_of_ampersands.rs | 57 + .../issue-54109-and_instead_of_ampersands.stderr | 75 + .../did_you_mean/issue-54109-without-witness.fixed | 61 + .../ui/did_you_mean/issue-54109-without-witness.rs | 61 + .../issue-54109-without-witness.stderr | 66 + .../issue-56028-there-is-an-enum-variant.rs | 15 + .../issue-56028-there-is-an-enum-variant.stderr | 40 + .../issue-87830-try-brackets-for-arrays.rs | 18 + .../issue-87830-try-brackets-for-arrays.stderr | 48 + .../did_you_mean/issue-93210-ignore-doc-hidden.rs | 24 + .../issue-93210-ignore-doc-hidden.stderr | 19 + tests/ui/did_you_mean/pub-macro-rules.rs | 16 + tests/ui/did_you_mean/pub-macro-rules.stderr | 8 + tests/ui/did_you_mean/recursion_limit.rs | 35 + tests/ui/did_you_mean/recursion_limit.stderr | 66 + tests/ui/did_you_mean/recursion_limit_deref.rs | 53 + tests/ui/did_you_mean/recursion_limit_deref.stderr | 23 + tests/ui/did_you_mean/recursion_limit_macro.rs | 15 + tests/ui/did_you_mean/recursion_limit_macro.stderr | 14 + .../replace-impl-infer-ty-from-trait.fixed | 15 + .../replace-impl-infer-ty-from-trait.rs | 15 + .../replace-impl-infer-ty-from-trait.stderr | 18 + ...t-object-reference-without-parens-suggestion.rs | 7 + ...ject-reference-without-parens-suggestion.stderr | 25 + tests/ui/did_you_mean/use_instead_of_import.fixed | 23 + tests/ui/did_you_mean/use_instead_of_import.rs | 23 + tests/ui/did_you_mean/use_instead_of_import.stderr | 26 + .../directory_ownership/foo/compiletest-ignore-dir | 0 .../foo/mod_file_not_owning/aux2.rs | 1 + .../foo/mod_file_not_owning_aux2.rs | 1 + tests/ui/directory_ownership/macro-expanded-mod.rs | 15 + .../directory_ownership/macro-expanded-mod.stderr | 13 + .../macro_expanded_mod_helper/foo/bar.rs | 1 + .../macro_expanded_mod_helper/foo/mod.rs | 3 + .../mod_file_not_owning_aux1.rs | 6 + .../compiletest-ignore-dir | 0 .../mod_file_not_owning_aux2.rs | 1 + .../mod_file_not_owning_aux2.rs | 1 + .../mod_file_not_owning_aux3.rs | 3 + .../non-inline-mod-restriction.rs | 5 + .../non-inline-mod-restriction.stderr | 8 + ...wed-deconstructing-destructing-struct-let.fixed | 21 + ...llowed-deconstructing-destructing-struct-let.rs | 21 + ...ed-deconstructing-destructing-struct-let.stderr | 17 + ...d-deconstructing-destructing-struct-match.fixed | 19 + ...owed-deconstructing-destructing-struct-match.rs | 19 + ...-deconstructing-destructing-struct-match.stderr | 20 + tests/ui/disambiguate-identical-names.rs | 15 + tests/ui/disambiguate-identical-names.stderr | 19 + tests/ui/discrim/discrim-ill-typed.rs | 114 + tests/ui/discrim/discrim-ill-typed.stderr | 91 + tests/ui/discrim/discrim-overflow-2.rs | 80 + tests/ui/discrim/discrim-overflow-2.stderr | 67 + tests/ui/discrim/discrim-overflow.rs | 99 + tests/ui/discrim/discrim-overflow.stderr | 67 + tests/ui/diverging-fallback-method-chain.rs | 20 + tests/ui/diverging-fallback-option.rs | 14 + tests/ui/diverging-fn-tail-35849.rs | 8 + tests/ui/diverging-fn-tail-35849.stderr | 15 + tests/ui/does-nothing.rs | 2 + tests/ui/does-nothing.stderr | 9 + tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs | 13 + .../dollar-crate/dollar-crate-is-keyword-2.stderr | 37 + tests/ui/dollar-crate/dollar-crate-is-keyword.rs | 17 + .../ui/dollar-crate/dollar-crate-is-keyword.stderr | 46 + tests/ui/dont-suggest-private-trait-method.rs | 6 + tests/ui/dont-suggest-private-trait-method.stderr | 12 + tests/ui/double-ref.rs | 36 + tests/ui/double-type-import.rs | 13 + tests/ui/double-type-import.stderr | 13 + tests/ui/drop-bounds/drop-bounds-impl-drop.rs | 14 + tests/ui/drop-bounds/drop-bounds.rs | 19 + tests/ui/drop-bounds/drop-bounds.stderr | 50 + .../drop/auxiliary/dropck_eyepatch_extern_crate.rs | 50 + tests/ui/drop/auxiliary/inline_dtor.rs | 8 + tests/ui/drop/auxiliary/issue-10028.rs | 9 + tests/ui/drop/drop-foreign-fundamental.rs | 23 + tests/ui/drop/drop-foreign-fundamental.stderr | 9 + tests/ui/drop/drop-if-let-binding.rs | 7 + tests/ui/drop/drop-on-empty-block-exit.rs | 10 + tests/ui/drop/drop-on-ret.rs | 15 + tests/ui/drop/drop-struct-as-object.rs | 36 + tests/ui/drop/drop-trait-enum.rs | 94 + tests/ui/drop/drop-trait-generic.rs | 15 + tests/ui/drop/drop-trait.rs | 15 + tests/ui/drop/drop-uninhabited-enum.rs | 14 + tests/ui/drop/drop-with-type-ascription-1.rs | 8 + tests/ui/drop/drop-with-type-ascription-2.rs | 8 + tests/ui/drop/drop_order.rs | 292 + tests/ui/drop/dropck-eyepatch-extern-crate.rs | 39 + tests/ui/drop/dropck-eyepatch-reorder.rs | 79 + tests/ui/drop/dropck-eyepatch.rs | 102 + tests/ui/drop/dropck_legal_cycles.rs | 1183 +++ tests/ui/drop/dynamic-drop-async.rs | 332 + tests/ui/drop/dynamic-drop.rs | 520 + tests/ui/drop/issue-100276.rs | 12 + tests/ui/drop/issue-10028.rs | 21 + tests/ui/drop/issue-103107.rs | 37 + tests/ui/drop/issue-17718-const-destructors.rs | 10 + tests/ui/drop/issue-21486.rs | 77 + .../ui/drop/issue-23338-ensure-param-drop-order.rs | 162 + tests/ui/drop/issue-2734.rs | 22 + tests/ui/drop/issue-30018-nopanic.rs | 103 + tests/ui/drop/issue-35546.rs | 20 + tests/ui/drop/issue-48962.rs | 34 + tests/ui/drop/issue-90752-raw-ptr-shenanigans.rs | 41 + tests/ui/drop/issue-90752.rs | 32 + tests/ui/drop/no-drop-flag-size.rs | 15 + tests/ui/drop/nondrop-cycle.rs | 31 + tests/ui/drop/repeat-drop-2.rs | 15 + tests/ui/drop/repeat-drop-2.stderr | 41 + tests/ui/drop/repeat-drop.rs | 118 + tests/ui/drop/terminate-in-initializer.rs | 34 + tests/ui/drop/use_inline_dtor.rs | 10 + .../auxiliary/dropck_eyepatch_extern_crate.rs | 37 + tests/ui/dropck/cleanup-arm-conditional.rs | 39 + tests/ui/dropck/drop-on-non-struct.rs | 14 + tests/ui/dropck/drop-on-non-struct.stderr | 27 + tests/ui/dropck/drop-with-active-borrows-1.rs | 8 + tests/ui/dropck/drop-with-active-borrows-1.stderr | 13 + tests/ui/dropck/drop-with-active-borrows-2.rs | 9 + tests/ui/dropck/drop-with-active-borrows-2.stderr | 12 + tests/ui/dropck/dropck-eyepatch-extern-crate.rs | 82 + .../ui/dropck/dropck-eyepatch-extern-crate.stderr | 31 + .../dropck/dropck-eyepatch-implies-unsafe-impl.rs | 35 + .../dropck-eyepatch-implies-unsafe-impl.stderr | 27 + tests/ui/dropck/dropck-eyepatch-reorder.rs | 100 + tests/ui/dropck/dropck-eyepatch-reorder.stderr | 31 + tests/ui/dropck/dropck-eyepatch.rs | 123 + tests/ui/dropck/dropck-eyepatch.stderr | 31 + tests/ui/dropck/dropck-union.rs | 38 + tests/ui/dropck/dropck-union.stderr | 14 + tests/ui/dropck/dropck_fn_type.rs | 20 + .../ui/dropck/dropck_no_diverge_on_nonregular_1.rs | 26 + .../dropck_no_diverge_on_nonregular_1.stderr | 11 + .../ui/dropck/dropck_no_diverge_on_nonregular_2.rs | 25 + .../dropck_no_diverge_on_nonregular_2.stderr | 11 + .../ui/dropck/dropck_no_diverge_on_nonregular_3.rs | 35 + .../dropck_no_diverge_on_nonregular_3.stderr | 19 + tests/ui/dropck/dropck_trait_cycle_checked.rs | 121 + tests/ui/dropck/dropck_trait_cycle_checked.stderr | 73 + tests/ui/dropck/dropck_traits.rs | 68 + tests/ui/dropck/issue-24805-dropck-itemless.rs | 77 + .../dropck/issue-28498-ugeh-with-lifetime-param.rs | 38 + .../dropck/issue-28498-ugeh-with-passed-to-fn.rs | 46 + .../ui/dropck/issue-28498-ugeh-with-trait-bound.rs | 41 + tests/ui/dropck/issue-29844.rs | 24 + tests/ui/dropck/issue-34053.rs | 30 + tests/ui/dropck/issue-38868.rs | 13 + tests/ui/dropck/issue-38868.stderr | 16 + tests/ui/dropck/issue-54943-1.rs | 13 + tests/ui/dropck/issue-54943-2.rs | 16 + tests/ui/dropck/reject-specialized-drops-8142.rs | 75 + .../ui/dropck/reject-specialized-drops-8142.stderr | 166 + .../ui/dropck/relate_lt_in_type_outlives_bound.rs | 13 + .../dropck/relate_lt_in_type_outlives_bound.stderr | 15 + tests/ui/dst/dst-bad-assign-2.rs | 38 + tests/ui/dst/dst-bad-assign-2.stderr | 12 + tests/ui/dst/dst-bad-assign-3.rs | 39 + tests/ui/dst/dst-bad-assign-3.stderr | 24 + tests/ui/dst/dst-bad-assign.rs | 41 + tests/ui/dst/dst-bad-assign.stderr | 24 + tests/ui/dst/dst-bad-coerce1.rs | 36 + tests/ui/dst/dst-bad-coerce1.stderr | 42 + tests/ui/dst/dst-bad-coerce2.rs | 31 + tests/ui/dst/dst-bad-coerce2.stderr | 47 + tests/ui/dst/dst-bad-coerce3.rs | 37 + tests/ui/dst/dst-bad-coerce3.stderr | 58 + tests/ui/dst/dst-bad-coerce4.rs | 25 + tests/ui/dst/dst-bad-coerce4.stderr | 25 + tests/ui/dst/dst-bad-coercions.rs | 26 + tests/ui/dst/dst-bad-coercions.stderr | 80 + tests/ui/dst/dst-bad-deep-2.rs | 13 + tests/ui/dst/dst-bad-deep-2.stderr | 14 + tests/ui/dst/dst-bad-deep.rs | 15 + tests/ui/dst/dst-bad-deep.stderr | 17 + tests/ui/dst/dst-index.rs | 37 + tests/ui/dst/dst-index.stderr | 28 + tests/ui/dst/dst-object-from-unsized-type.rs | 27 + tests/ui/dst/dst-object-from-unsized-type.stderr | 51 + tests/ui/dst/dst-rvalue.rs | 10 + tests/ui/dst/dst-rvalue.stderr | 27 + tests/ui/dst/dst-sized-trait-param.rs | 13 + tests/ui/dst/dst-sized-trait-param.stderr | 33 + tests/ui/dupe-first-attr.rc | 24 + tests/ui/duplicate/dupe-symbols-1.rs | 14 + tests/ui/duplicate/dupe-symbols-1.stderr | 8 + tests/ui/duplicate/dupe-symbols-2.rs | 18 + tests/ui/duplicate/dupe-symbols-2.stderr | 8 + tests/ui/duplicate/dupe-symbols-3.rs | 14 + tests/ui/duplicate/dupe-symbols-3.stderr | 8 + tests/ui/duplicate/dupe-symbols-4.rs | 24 + tests/ui/duplicate/dupe-symbols-4.stderr | 8 + tests/ui/duplicate/dupe-symbols-5.rs | 13 + tests/ui/duplicate/dupe-symbols-5.stderr | 8 + tests/ui/duplicate/dupe-symbols-6.rs | 11 + tests/ui/duplicate/dupe-symbols-6.stderr | 8 + tests/ui/duplicate/dupe-symbols-7.rs | 12 + tests/ui/duplicate/dupe-symbols-7.stderr | 10 + tests/ui/duplicate/dupe-symbols-8.rs | 12 + tests/ui/duplicate/dupe-symbols-8.stderr | 10 + .../ui/duplicate/duplicate-check-macro-exports.rs | 6 + .../duplicate/duplicate-check-macro-exports.stderr | 18 + tests/ui/duplicate/duplicate-parameter.rs | 5 + tests/ui/duplicate/duplicate-parameter.stderr | 9 + tests/ui/duplicate/duplicate-type-parameter.rs | 29 + tests/ui/duplicate/duplicate-type-parameter.stderr | 66 + tests/ui/duplicate_entry_error.rs | 16 + tests/ui/duplicate_entry_error.stderr | 13 + tests/ui/dyn-drop/dyn-drop.rs | 16 + tests/ui/dyn-drop/dyn-drop.stderr | 38 + .../dyn-2015-edition-keyword-ident-lint.fixed | 82 + .../dyn-2015-edition-keyword-ident-lint.rs | 82 + .../dyn-2015-edition-keyword-ident-lint.stderr | 133 + .../dyn-2015-idents-in-decl-macros-unlinted.rs | 52 + .../dyn-2015-idents-in-macros-unlinted.rs | 57 + .../dyn-2015-no-warnings-without-lints.rs | 28 + tests/ui/dyn-keyword/dyn-2018-edition-lint.rs | 24 + tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr | 98 + tests/ui/dyn-keyword/dyn-2021-edition-error.rs | 11 + tests/ui/dyn-keyword/dyn-2021-edition-error.stderr | 25 + tests/ui/dyn-keyword/dyn-angle-brackets.fixed | 21 + tests/ui/dyn-keyword/dyn-angle-brackets.rs | 21 + tests/ui/dyn-keyword/dyn-angle-brackets.stderr | 20 + .../issue-56327-dyn-trait-in-macro-is-okay.rs | 27 + tests/ui/dyn-star/align.normal.stderr | 11 + tests/ui/dyn-star/align.over_aligned.stderr | 20 + tests/ui/dyn-star/align.rs | 17 + tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs | 10 + tests/ui/dyn-star/box.rs | 17 + .../dyn-star/check-size-at-cast-polymorphic-bad.rs | 15 + .../check-size-at-cast-polymorphic-bad.stderr | 15 + .../ui/dyn-star/check-size-at-cast-polymorphic.rs | 16 + tests/ui/dyn-star/check-size-at-cast.rs | 10 + tests/ui/dyn-star/check-size-at-cast.stderr | 11 + tests/ui/dyn-star/const.rs | 14 + tests/ui/dyn-star/dispatch-on-pin-mut.rs | 52 + tests/ui/dyn-star/dispatch-on-pin-mut.run.stdout | 1 + tests/ui/dyn-star/dispatch-on-pin-mut.stderr | 11 + tests/ui/dyn-star/dont-unsize-coerce-dyn-star.rs | 27 + .../dont-unsize-coerce-dyn-star.run.stdout | 2 + .../ui/dyn-star/dont-unsize-coerce-dyn-star.stderr | 11 + tests/ui/dyn-star/drop.rs | 23 + tests/ui/dyn-star/drop.run.stdout | 1 + tests/ui/dyn-star/dyn-async-trait.rs | 36 + tests/ui/dyn-star/dyn-star-to-dyn.rs | 9 + tests/ui/dyn-star/dyn-star-to-dyn.stderr | 11 + tests/ui/dyn-star/dyn-to-rigid.rs | 11 + tests/ui/dyn-star/dyn-to-rigid.stderr | 9 + tests/ui/dyn-star/error.rs | 13 + tests/ui/dyn-star/error.stderr | 9 + tests/ui/dyn-star/feature-gate-dyn_star.rs | 9 + tests/ui/dyn-star/feature-gate-dyn_star.stderr | 12 + tests/ui/dyn-star/issue-102430.rs | 32 + tests/ui/dyn-star/make-dyn-star.rs | 18 + tests/ui/dyn-star/method.rs | 27 + tests/ui/dyn-star/no-explicit-dyn-star-cast.rs | 13 + tests/ui/dyn-star/no-explicit-dyn-star-cast.stderr | 28 + tests/ui/dyn-star/no-explicit-dyn-star.rs | 8 + tests/ui/dyn-star/no-explicit-dyn-star.stderr | 9 + tests/ui/dyn-star/no-implicit-dyn-star.rs | 8 + tests/ui/dyn-star/no-implicit-dyn-star.stderr | 19 + tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs | 13 + .../ui/dyn-star/no-unsize-coerce-dyn-trait.stderr | 23 + tests/ui/dyn-star/return.rs | 10 + tests/ui/dyn-star/return.stderr | 11 + tests/ui/dyn-star/syntax.rs | 11 + tests/ui/dyn-star/unsize-into-ref-dyn-star.rs | 9 + tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr | 9 + tests/ui/dyn-star/upcast.rs | 32 + tests/ui/dyn-star/upcast.stderr | 20 + .../dynamically-sized-types/dst-coerce-custom.rs | 43 + tests/ui/dynamically-sized-types/dst-coerce-rc.rs | 42 + tests/ui/dynamically-sized-types/dst-coercions.rs | 28 + tests/ui/dynamically-sized-types/dst-deref-mut.rs | 35 + tests/ui/dynamically-sized-types/dst-deref.rs | 30 + .../ui/dynamically-sized-types/dst-field-align.rs | 67 + tests/ui/dynamically-sized-types/dst-index.rs | 34 + .../dst-irrefutable-bind.rs | 27 + tests/ui/dynamically-sized-types/dst-raw.rs | 138 + .../ui/dynamically-sized-types/dst-struct-sole.rs | 76 + tests/ui/dynamically-sized-types/dst-struct.rs | 121 + .../ui/dynamically-sized-types/dst-trait-tuple.rs | 102 + tests/ui/dynamically-sized-types/dst-trait.rs | 104 + .../dst-tuple-no-reorder.rs | 26 + tests/ui/dynamically-sized-types/dst-tuple-sole.rs | 79 + .../dst-tuple-zst-offsets.rs | 22 + tests/ui/dynamically-sized-types/dst-tuple.rs | 119 + tests/ui/early-ret-binop-add.rs | 11 + tests/ui/editions/async-block-2015.rs | 30 + tests/ui/editions/async-block-2015.stderr | 41 + tests/ui/editions/auxiliary/absolute.rs | 1 + .../auxiliary/edition-extern-crate-allowed.rs | 1 + .../ui/editions/auxiliary/edition-imports-2015.rs | 31 + .../ui/editions/auxiliary/edition-imports-2018.rs | 17 + .../ui/editions/auxiliary/edition-kw-macro-2015.rs | 28 + .../ui/editions/auxiliary/edition-kw-macro-2018.rs | 28 + tests/ui/editions/dyn-trait-sugg-2021.rs | 12 + tests/ui/editions/dyn-trait-sugg-2021.stderr | 14 + tests/ui/editions/edition-extern-crate-allowed.rs | 10 + .../editions/edition-extern-crate-allowed.stderr | 15 + tests/ui/editions/edition-feature-ok.rs | 5 + tests/ui/editions/edition-feature-redundant.rs | 7 + tests/ui/editions/edition-feature-redundant.stderr | 9 + tests/ui/editions/edition-imports-2015.rs | 26 + tests/ui/editions/edition-imports-2015.stderr | 10 + tests/ui/editions/edition-imports-2018.rs | 27 + tests/ui/editions/edition-imports-2018.stderr | 10 + .../edition-imports-virtual-2015-ambiguity.rs | 20 + .../editions/edition-imports-virtual-2015-gated.rs | 11 + .../edition-imports-virtual-2015-gated.stderr | 11 + .../edition-keywords-2015-2015-expansion.rs | 17 + .../editions/edition-keywords-2015-2015-parsing.rs | 26 + .../edition-keywords-2015-2015-parsing.stderr | 26 + tests/ui/editions/edition-keywords-2015-2015.rs | 36 + .../edition-keywords-2015-2018-expansion.rs | 14 + .../edition-keywords-2015-2018-expansion.stderr | 15 + .../editions/edition-keywords-2015-2018-parsing.rs | 26 + .../edition-keywords-2015-2018-parsing.stderr | 26 + tests/ui/editions/edition-keywords-2015-2018.rs | 36 + .../edition-keywords-2018-2015-expansion.rs | 17 + .../editions/edition-keywords-2018-2015-parsing.rs | 30 + .../edition-keywords-2018-2015-parsing.stderr | 68 + tests/ui/editions/edition-keywords-2018-2015.rs | 34 + .../edition-keywords-2018-2018-expansion.rs | 14 + .../edition-keywords-2018-2018-expansion.stderr | 15 + .../editions/edition-keywords-2018-2018-parsing.rs | 30 + .../edition-keywords-2018-2018-parsing.stderr | 68 + tests/ui/editions/edition-keywords-2018-2018.rs | 34 + .../ui/editions/edition-raw-pointer-method-2015.rs | 12 + .../edition-raw-pointer-method-2015.stderr | 17 + .../ui/editions/edition-raw-pointer-method-2018.rs | 11 + .../edition-raw-pointer-method-2018.stderr | 9 + tests/ui/editions/epoch-gate-feature.rs | 15 + tests/ui/elide-errors-on-mismatched-tuple.rs | 18 + tests/ui/elide-errors-on-mismatched-tuple.stderr | 14 + tests/ui/elided-test.rs | 7 + tests/ui/elided-test.stderr | 9 + tests/ui/else-if.rs | 20 + tests/ui/empty-allocation-non-null.rs | 14 + tests/ui/empty-allocation-rvalue-non-null.rs | 8 + tests/ui/empty-type-parameter-list.rs | 24 + tests/ui/empty/auxiliary/empty-struct.rs | 9 + tests/ui/empty/auxiliary/two_macros.rs | 5 + tests/ui/empty/empty-attributes.rs | 17 + tests/ui/empty/empty-attributes.stderr | 71 + tests/ui/empty/empty-comment.rs | 11 + tests/ui/empty/empty-comment.stderr | 17 + tests/ui/empty/empty-linkname.rs | 4 + tests/ui/empty/empty-linkname.stderr | 9 + tests/ui/empty/empty-macro-use.rs | 9 + tests/ui/empty/empty-macro-use.stderr | 11 + tests/ui/empty/empty-never-array.rs | 18 + tests/ui/empty/empty-never-array.stderr | 24 + tests/ui/empty/empty-struct-braces-expr.rs | 29 + tests/ui/empty/empty-struct-braces-expr.stderr | 130 + tests/ui/empty/empty-struct-braces-pat-1.rs | 34 + tests/ui/empty/empty-struct-braces-pat-1.stderr | 15 + tests/ui/empty/empty-struct-braces-pat-2.rs | 26 + tests/ui/empty/empty-struct-braces-pat-2.stderr | 95 + tests/ui/empty/empty-struct-braces-pat-3.rs | 32 + tests/ui/empty/empty-struct-braces-pat-3.stderr | 27 + tests/ui/empty/empty-struct-tuple-pat.rs | 37 + tests/ui/empty/empty-struct-tuple-pat.stderr | 59 + tests/ui/empty/empty-struct-unit-expr.rs | 21 + tests/ui/empty/empty-struct-unit-expr.stderr | 65 + tests/ui/empty/empty-struct-unit-pat.rs | 54 + tests/ui/empty/empty-struct-unit-pat.stderr | 155 + tests/ui/empty/issue-37026.rs | 8 + tests/ui/empty/issue-37026.stderr | 19 + tests/ui/empty/no-link.rs | 9 + tests/ui/empty_global_asm.rs | 8 + tests/ui/entry-point/auxiliary/main_functions.rs | 1 + tests/ui/entry-point/imported_main_conflict.rs | 7 + tests/ui/entry-point/imported_main_conflict.stderr | 19 + .../imported_main_const_fn_item_type_forbidden.rs | 11 + ...ported_main_const_fn_item_type_forbidden.stderr | 11 + .../entry-point/imported_main_const_forbidden.rs | 6 + .../imported_main_const_forbidden.stderr | 11 + .../entry-point/imported_main_from_extern_crate.rs | 7 + .../ui/entry-point/imported_main_from_inner_mod.rs | 9 + ...mported_main_unused_not_trigger_feature_gate.rs | 11 + .../actually_not_an_enum-discriminant.rs | 49 + .../arbitrary_enum_discriminant-no-repr.rs | 8 + .../arbitrary_enum_discriminant-no-repr.stderr | 9 + .../arbitrary_enum_discriminant.rs | 43 + tests/ui/enum-discriminant/discriminant_size.rs | 54 + .../ui/enum-discriminant/discriminant_size.stderr | 11 + .../discriminant_value-wrapper.rs | 20 + tests/ui/enum-discriminant/discriminant_value.rs | 82 + .../forbidden-discriminant-kind-impl.rs | 14 + .../forbidden-discriminant-kind-impl.stderr | 9 + tests/ui/enum-discriminant/get_discr.rs | 114 + tests/ui/enum-discriminant/issue-104519.rs | 36 + tests/ui/enum-discriminant/issue-43398.rs | 14 + tests/ui/enum-discriminant/issue-43398.stderr | 11 + tests/ui/enum-discriminant/issue-46519.rs | 30 + tests/ui/enum-discriminant/issue-51582.rs | 18 + .../issue-70453-generics-in-discr-ice-2.rs | 16 + .../issue-70453-generics-in-discr-ice-2.stderr | 11 + .../issue-70453-generics-in-discr-ice.rs | 17 + .../issue-70453-generics-in-discr-ice.stderr | 21 + .../issue-70453-polymorphic-ctfe.rs | 16 + .../issue-70453-polymorphic-ctfe.stderr | 11 + .../ui/enum-discriminant/issue-70509-partial_eq.rs | 18 + .../issue-70509-partial_eq.stderr | 11 + tests/ui/enum-discriminant/issue-72554.rs | 22 + tests/ui/enum-discriminant/issue-72554.stderr | 17 + tests/ui/enum-discriminant/issue-90038.rs | 21 + tests/ui/enum-discriminant/niche-prefer-zero.rs | 14 + tests/ui/enum-discriminant/niche.rs | 109 + tests/ui/enum-discriminant/repr128.rs | 45 + tests/ui/enum-discriminant/repr128.stderr | 11 + tests/ui/enum/enum-and-module-in-same-scope.rs | 10 + tests/ui/enum/enum-and-module-in-same-scope.stderr | 14 + tests/ui/enum/enum-discrim-autosizing.rs | 14 + tests/ui/enum/enum-discrim-autosizing.stderr | 15 + tests/ui/enum/enum-discrim-too-small.rs | 38 + tests/ui/enum/enum-discrim-too-small.stderr | 35 + tests/ui/enum/enum-discrim-too-small2.rs | 37 + tests/ui/enum/enum-discrim-too-small2.stderr | 43 + tests/ui/enum/enum-in-scope.rs | 7 + tests/ui/enum/enum-in-scope.stderr | 12 + tests/ui/enum/enum-size-variance.rs | 35 + tests/ui/enum/enum-size-variance.stderr | 14 + tests/ui/enum/enum-to-float-cast-2.rs | 18 + tests/ui/enum/enum-to-float-cast-2.stderr | 19 + tests/ui/enum/enum-to-float-cast.rs | 21 + tests/ui/enum/enum-to-float-cast.stderr | 19 + tests/ui/enum/enum-variant-type-2.rs | 9 + tests/ui/enum/enum-variant-type-2.stderr | 12 + tests/ui/enum/issue-42747.rs | 46 + tests/ui/enum/issue-67945-1.rs | 8 + tests/ui/enum/issue-67945-1.stderr | 21 + tests/ui/enum/issue-67945-2.rs | 8 + tests/ui/enum/issue-67945-2.stderr | 21 + tests/ui/enum/nested-enum.rs | 8 + tests/ui/enum/nested-enum.stderr | 26 + tests/ui/enum/suggest-default-attribute.rs | 8 + tests/ui/enum/suggest-default-attribute.stderr | 14 + tests/ui/enum/union-in-enum.rs | 13 + tests/ui/env-args-reverse-iterator.rs | 38 + tests/ui/env-funky-keys.rs | 43 + tests/ui/env-null-vars.rs | 23 + tests/ui/env-vars.rs | 20 + tests/ui/error-codes/E0001.rs | 10 + tests/ui/error-codes/E0001.stderr | 14 + tests/ui/error-codes/E0004-2.rs | 5 + tests/ui/error-codes/E0004-2.stderr | 25 + tests/ui/error-codes/E0004.rs | 12 + tests/ui/error-codes/E0004.stderr | 23 + tests/ui/error-codes/E0005.rs | 4 + tests/ui/error-codes/E0005.stderr | 17 + tests/ui/error-codes/E0010-teach.rs | 8 + tests/ui/error-codes/E0010-teach.stderr | 11 + tests/ui/error-codes/E0010.rs | 6 + tests/ui/error-codes/E0010.stderr | 9 + tests/ui/error-codes/E0013.rs | 4 + tests/ui/error-codes/E0013.stderr | 11 + tests/ui/error-codes/E0015.rs | 8 + tests/ui/error-codes/E0015.stderr | 11 + tests/ui/error-codes/E0017.rs | 14 + tests/ui/error-codes/E0017.stderr | 72 + tests/ui/error-codes/E0023.rs | 17 + tests/ui/error-codes/E0023.stderr | 63 + tests/ui/error-codes/E0025.rs | 10 + tests/ui/error-codes/E0025.stderr | 11 + tests/ui/error-codes/E0026-teach.rs | 14 + tests/ui/error-codes/E0026-teach.stderr | 13 + tests/ui/error-codes/E0026.rs | 12 + tests/ui/error-codes/E0026.stderr | 9 + tests/ui/error-codes/E0027.rs | 24 + tests/ui/error-codes/E0027.stderr | 63 + tests/ui/error-codes/E0029-teach.rs | 11 + tests/ui/error-codes/E0029-teach.stderr | 14 + tests/ui/error-codes/E0029.rs | 9 + tests/ui/error-codes/E0029.stderr | 12 + tests/ui/error-codes/E0030-teach.rs | 9 + tests/ui/error-codes/E0030-teach.stderr | 17 + tests/ui/error-codes/E0030.rs | 7 + tests/ui/error-codes/E0030.stderr | 15 + tests/ui/error-codes/E0033-teach.rs | 14 + tests/ui/error-codes/E0033-teach.stderr | 13 + tests/ui/error-codes/E0033.rs | 13 + tests/ui/error-codes/E0033.stderr | 9 + tests/ui/error-codes/E0034.rs | 21 + tests/ui/error-codes/E0034.stderr | 28 + tests/ui/error-codes/E0038.rs | 11 + tests/ui/error-codes/E0038.stderr | 18 + tests/ui/error-codes/E0040.fixed | 18 + tests/ui/error-codes/E0040.rs | 18 + tests/ui/error-codes/E0040.stderr | 12 + tests/ui/error-codes/E0044.rs | 8 + tests/ui/error-codes/E0044.stderr | 11 + tests/ui/error-codes/E0045.rs | 4 + tests/ui/error-codes/E0045.stderr | 9 + tests/ui/error-codes/E0049.rs | 22 + tests/ui/error-codes/E0049.stderr | 23 + tests/ui/error-codes/E0050.rs | 16 + tests/ui/error-codes/E0050.stderr | 30 + tests/ui/error-codes/E0054.rs | 4 + tests/ui/error-codes/E0054.stderr | 9 + tests/ui/error-codes/E0055.rs | 13 + tests/ui/error-codes/E0055.stderr | 11 + tests/ui/error-codes/E0057.rs | 6 + tests/ui/error-codes/E0057.stderr | 35 + tests/ui/error-codes/E0059.rs | 6 + tests/ui/error-codes/E0059.stderr | 12 + tests/ui/error-codes/E0060.rs | 8 + tests/ui/error-codes/E0060.stderr | 19 + tests/ui/error-codes/E0061.rs | 11 + tests/ui/error-codes/E0061.stderr | 35 + tests/ui/error-codes/E0062.rs | 11 + tests/ui/error-codes/E0062.stderr | 11 + tests/ui/error-codes/E0063.rs | 38 + tests/ui/error-codes/E0063.stderr | 27 + tests/ui/error-codes/E0067.rs | 6 + tests/ui/error-codes/E0067.stderr | 20 + tests/ui/error-codes/E0069.rs | 7 + tests/ui/error-codes/E0069.stderr | 11 + tests/ui/error-codes/E0070.rs | 12 + tests/ui/error-codes/E0070.stderr | 27 + tests/ui/error-codes/E0071.rs | 7 + tests/ui/error-codes/E0071.stderr | 9 + tests/ui/error-codes/E0075.rs | 7 + tests/ui/error-codes/E0075.stderr | 9 + tests/ui/error-codes/E0076.rs | 8 + tests/ui/error-codes/E0076.stderr | 9 + tests/ui/error-codes/E0077.rs | 7 + tests/ui/error-codes/E0077.stderr | 9 + tests/ui/error-codes/E0080.rs | 8 + tests/ui/error-codes/E0080.stderr | 15 + tests/ui/error-codes/E0081.rs | 54 + tests/ui/error-codes/E0081.stderr | 78 + tests/ui/error-codes/E0084.rs | 5 + tests/ui/error-codes/E0084.stderr | 11 + tests/ui/error-codes/E0091.rs | 5 + tests/ui/error-codes/E0091.stderr | 15 + tests/ui/error-codes/E0092.rs | 7 + tests/ui/error-codes/E0092.stderr | 9 + tests/ui/error-codes/E0093.rs | 8 + tests/ui/error-codes/E0093.stderr | 9 + tests/ui/error-codes/E0094.rs | 9 + tests/ui/error-codes/E0094.stderr | 9 + tests/ui/error-codes/E0106.rs | 26 + tests/ui/error-codes/E0106.stderr | 66 + tests/ui/error-codes/E0107.rs | 60 + tests/ui/error-codes/E0107.stderr | 149 + tests/ui/error-codes/E0109.rs | 4 + tests/ui/error-codes/E0109.stderr | 17 + tests/ui/error-codes/E0110.rs | 3 + tests/ui/error-codes/E0110.stderr | 17 + tests/ui/error-codes/E0116.rs | 5 + tests/ui/error-codes/E0116.stderr | 11 + tests/ui/error-codes/E0117.rs | 4 + tests/ui/error-codes/E0117.stderr | 21 + tests/ui/error-codes/E0118.rs | 7 + tests/ui/error-codes/E0118.stderr | 11 + tests/ui/error-codes/E0119.rs | 18 + tests/ui/error-codes/E0119.stderr | 12 + tests/ui/error-codes/E0120.rs | 8 + tests/ui/error-codes/E0120.stderr | 9 + tests/ui/error-codes/E0121.rs | 5 + tests/ui/error-codes/E0121.stderr | 21 + tests/ui/error-codes/E0124.rs | 8 + tests/ui/error-codes/E0124.stderr | 11 + tests/ui/error-codes/E0128.rs | 7 + tests/ui/error-codes/E0128.stderr | 9 + tests/ui/error-codes/E0130.rs | 6 + tests/ui/error-codes/E0130.stderr | 9 + tests/ui/error-codes/E0131.rs | 3 + tests/ui/error-codes/E0131.stderr | 9 + tests/ui/error-codes/E0132.rs | 7 + tests/ui/error-codes/E0132.stderr | 9 + tests/ui/error-codes/E0133.mir.stderr | 11 + tests/ui/error-codes/E0133.rs | 9 + tests/ui/error-codes/E0133.thir.stderr | 11 + tests/ui/error-codes/E0138.rs | 8 + tests/ui/error-codes/E0138.stderr | 12 + tests/ui/error-codes/E0152.rs | 8 + tests/ui/error-codes/E0152.stderr | 13 + tests/ui/error-codes/E0161.base.stderr | 9 + tests/ui/error-codes/E0161.rs | 20 + tests/ui/error-codes/E0164.rs | 14 + tests/ui/error-codes/E0164.stderr | 9 + tests/ui/error-codes/E0184.rs | 10 + tests/ui/error-codes/E0184.stderr | 11 + tests/ui/error-codes/E0185.rs | 15 + tests/ui/error-codes/E0185.stderr | 12 + tests/ui/error-codes/E0186.rs | 13 + tests/ui/error-codes/E0186.stderr | 12 + tests/ui/error-codes/E0191.rs | 7 + tests/ui/error-codes/E0191.stderr | 12 + tests/ui/error-codes/E0194.rs | 8 + tests/ui/error-codes/E0194.stderr | 12 + tests/ui/error-codes/E0195.rs | 15 + tests/ui/error-codes/E0195.stderr | 12 + tests/ui/error-codes/E0197.rs | 6 + tests/ui/error-codes/E0197.stderr | 11 + tests/ui/error-codes/E0198.rs | 8 + tests/ui/error-codes/E0198.stderr | 12 + tests/ui/error-codes/E0199.rs | 9 + tests/ui/error-codes/E0199.stderr | 15 + tests/ui/error-codes/E0200.rs | 8 + tests/ui/error-codes/E0200.stderr | 15 + tests/ui/error-codes/E0201.rs | 22 + tests/ui/error-codes/E0201.stderr | 35 + tests/ui/error-codes/E0206.rs | 8 + tests/ui/error-codes/E0206.stderr | 9 + tests/ui/error-codes/E0207.rs | 10 + tests/ui/error-codes/E0207.stderr | 9 + tests/ui/error-codes/E0208.rs | 8 + tests/ui/error-codes/E0208.stderr | 8 + tests/ui/error-codes/E0214.rs | 4 + tests/ui/error-codes/E0214.stderr | 14 + tests/ui/error-codes/E0220.rs | 8 + tests/ui/error-codes/E0220.stderr | 19 + tests/ui/error-codes/E0221.rs | 27 + tests/ui/error-codes/E0221.stderr | 39 + tests/ui/error-codes/E0223.rs | 10 + tests/ui/error-codes/E0223.stderr | 9 + tests/ui/error-codes/E0225.rs | 10 + tests/ui/error-codes/E0225.stderr | 31 + tests/ui/error-codes/E0227.rs | 12 + tests/ui/error-codes/E0227.stderr | 9 + tests/ui/error-codes/E0229.rs | 17 + tests/ui/error-codes/E0229.stderr | 9 + tests/ui/error-codes/E0252.rs | 15 + tests/ui/error-codes/E0252.stderr | 17 + tests/ui/error-codes/E0253.rs | 10 + tests/ui/error-codes/E0253.stderr | 9 + tests/ui/error-codes/E0254.rs | 14 + tests/ui/error-codes/E0254.stderr | 18 + tests/ui/error-codes/E0255.rs | 9 + tests/ui/error-codes/E0255.stderr | 18 + tests/ui/error-codes/E0259.rs | 8 + tests/ui/error-codes/E0259.stderr | 18 + tests/ui/error-codes/E0260.rs | 10 + tests/ui/error-codes/E0260.stderr | 18 + tests/ui/error-codes/E0261.rs | 9 + tests/ui/error-codes/E0261.stderr | 19 + tests/ui/error-codes/E0262.rs | 4 + tests/ui/error-codes/E0262.stderr | 9 + tests/ui/error-codes/E0263.rs | 5 + tests/ui/error-codes/E0263.stderr | 11 + tests/ui/error-codes/E0264.rs | 8 + tests/ui/error-codes/E0264.stderr | 9 + tests/ui/error-codes/E0267.rs | 3 + tests/ui/error-codes/E0267.stderr | 11 + tests/ui/error-codes/E0268.rs | 3 + tests/ui/error-codes/E0268.stderr | 9 + tests/ui/error-codes/E0271.rs | 11 + tests/ui/error-codes/E0271.stderr | 22 + tests/ui/error-codes/E0275.rs | 9 + tests/ui/error-codes/E0275.stderr | 19 + tests/ui/error-codes/E0276.rs | 10 + tests/ui/error-codes/E0276.stderr | 12 + tests/ui/error-codes/E0277-2.rs | 18 + tests/ui/error-codes/E0277-2.stderr | 31 + tests/ui/error-codes/E0277-3.rs | 8 + tests/ui/error-codes/E0277-3.stderr | 22 + tests/ui/error-codes/E0277.rs | 17 + tests/ui/error-codes/E0277.stderr | 31 + tests/ui/error-codes/E0282.rs | 4 + tests/ui/error-codes/E0282.stderr | 14 + tests/ui/error-codes/E0283.rs | 37 + tests/ui/error-codes/E0283.stderr | 37 + tests/ui/error-codes/E0297.rs | 6 + tests/ui/error-codes/E0297.stderr | 11 + tests/ui/error-codes/E0308-2.rs | 12 + tests/ui/error-codes/E0308-2.stderr | 18 + tests/ui/error-codes/E0308-4.rs | 7 + tests/ui/error-codes/E0308-4.stderr | 13 + tests/ui/error-codes/E0308.rs | 10 + tests/ui/error-codes/E0308.stderr | 12 + tests/ui/error-codes/E0311.fixed | 13 + tests/ui/error-codes/E0311.rs | 13 + tests/ui/error-codes/E0311.stderr | 24 + tests/ui/error-codes/E0328.rs | 10 + tests/ui/error-codes/E0328.stderr | 9 + tests/ui/error-codes/E0365.rs | 8 + tests/ui/error-codes/E0365.stderr | 11 + tests/ui/error-codes/E0370.rs | 10 + tests/ui/error-codes/E0370.stderr | 11 + tests/ui/error-codes/E0374.rs | 11 + tests/ui/error-codes/E0374.stderr | 9 + tests/ui/error-codes/E0375.rs | 13 + tests/ui/error-codes/E0375.stderr | 12 + tests/ui/error-codes/E0376.rs | 10 + tests/ui/error-codes/E0376.stderr | 9 + tests/ui/error-codes/E0377.rs | 14 + tests/ui/error-codes/E0377.stderr | 9 + tests/ui/error-codes/E0388.rs | 13 + tests/ui/error-codes/E0388.stderr | 66 + tests/ui/error-codes/E0389.rs | 10 + tests/ui/error-codes/E0389.stderr | 14 + tests/ui/error-codes/E0390.rs | 10 + tests/ui/error-codes/E0390.stderr | 19 + tests/ui/error-codes/E0392.rs | 4 + tests/ui/error-codes/E0392.stderr | 12 + tests/ui/error-codes/E0393.rs | 7 + tests/ui/error-codes/E0393.stderr | 14 + tests/ui/error-codes/E0396-fixed.rs | 9 + tests/ui/error-codes/E0396-fixed.stderr | 9 + tests/ui/error-codes/E0396.rs | 18 + tests/ui/error-codes/E0396.stderr | 30 + tests/ui/error-codes/E0401.rs | 32 + tests/ui/error-codes/E0401.stderr | 70 + tests/ui/error-codes/E0403.rs | 4 + tests/ui/error-codes/E0403.stderr | 11 + tests/ui/error-codes/E0404.rs | 8 + tests/ui/error-codes/E0404.stderr | 15 + tests/ui/error-codes/E0405.rs | 6 + tests/ui/error-codes/E0405.stderr | 9 + tests/ui/error-codes/E0407.rs | 14 + tests/ui/error-codes/E0407.stderr | 12 + tests/ui/error-codes/E0408.rs | 8 + tests/ui/error-codes/E0408.stderr | 11 + tests/ui/error-codes/E0411.rs | 3 + tests/ui/error-codes/E0411.stderr | 11 + tests/ui/error-codes/E0412.rs | 4 + tests/ui/error-codes/E0412.stderr | 9 + tests/ui/error-codes/E0415.rs | 4 + tests/ui/error-codes/E0415.stderr | 9 + tests/ui/error-codes/E0416.rs | 5 + tests/ui/error-codes/E0416.stderr | 9 + tests/ui/error-codes/E0423.rs | 22 + tests/ui/error-codes/E0423.stderr | 63 + tests/ui/error-codes/E0424.rs | 21 + tests/ui/error-codes/E0424.stderr | 50 + tests/ui/error-codes/E0425.rs | 8 + tests/ui/error-codes/E0425.stderr | 9 + tests/ui/error-codes/E0426.rs | 6 + tests/ui/error-codes/E0426.stderr | 9 + tests/ui/error-codes/E0428.rs | 5 + tests/ui/error-codes/E0428.stderr | 13 + tests/ui/error-codes/E0429.rs | 4 + tests/ui/error-codes/E0429.stderr | 19 + tests/ui/error-codes/E0430.rs | 5 + tests/ui/error-codes/E0430.stderr | 22 + tests/ui/error-codes/E0431.rs | 4 + tests/ui/error-codes/E0431.stderr | 9 + tests/ui/error-codes/E0432.rs | 4 + tests/ui/error-codes/E0432.stderr | 11 + tests/ui/error-codes/E0433.rs | 3 + tests/ui/error-codes/E0433.stderr | 9 + tests/ui/error-codes/E0434.rs | 9 + tests/ui/error-codes/E0434.stderr | 11 + tests/ui/error-codes/E0435.fixed | 6 + tests/ui/error-codes/E0435.rs | 6 + tests/ui/error-codes/E0435.stderr | 11 + tests/ui/error-codes/E0437.rs | 8 + tests/ui/error-codes/E0437.stderr | 9 + tests/ui/error-codes/E0438.rs | 8 + tests/ui/error-codes/E0438.stderr | 9 + tests/ui/error-codes/E0445.rs | 12 + tests/ui/error-codes/E0445.stderr | 30 + tests/ui/error-codes/E0446.rs | 9 + tests/ui/error-codes/E0446.stderr | 12 + tests/ui/error-codes/E0449.rs | 14 + tests/ui/error-codes/E0449.stderr | 23 + tests/ui/error-codes/E0451.rs | 19 + tests/ui/error-codes/E0451.stderr | 15 + tests/ui/error-codes/E0452.rs | 6 + tests/ui/error-codes/E0452.stderr | 27 + tests/ui/error-codes/E0453.rs | 7 + tests/ui/error-codes/E0453.stderr | 21 + tests/ui/error-codes/E0454.rs | 5 + tests/ui/error-codes/E0454.stderr | 9 + tests/ui/error-codes/E0458.rs | 5 + tests/ui/error-codes/E0458.stderr | 16 + tests/ui/error-codes/E0459.rs | 4 + tests/ui/error-codes/E0459.stderr | 9 + tests/ui/error-codes/E0462.rs | 11 + tests/ui/error-codes/E0462.stderr | 13 + tests/ui/error-codes/E0463.rs | 7 + tests/ui/error-codes/E0463.stderr | 9 + tests/ui/error-codes/E0464.rs | 14 + tests/ui/error-codes/E0464.stderr | 13 + tests/ui/error-codes/E0478.rs | 8 + tests/ui/error-codes/E0478.stderr | 20 + tests/ui/error-codes/E0492.rs | 10 + tests/ui/error-codes/E0492.stderr | 17 + tests/ui/error-codes/E0496.rs | 11 + tests/ui/error-codes/E0496.stderr | 11 + tests/ui/error-codes/E0499.rs | 10 + tests/ui/error-codes/E0499.stderr | 14 + tests/ui/error-codes/E0501.rs | 24 + tests/ui/error-codes/E0501.stderr | 31 + tests/ui/error-codes/E0502.rs | 12 + tests/ui/error-codes/E0502.stderr | 13 + tests/ui/error-codes/E0503.rs | 9 + tests/ui/error-codes/E0503.stderr | 13 + tests/ui/error-codes/E0504.rs | 15 + tests/ui/error-codes/E0504.stderr | 17 + tests/ui/error-codes/E0505.rs | 15 + tests/ui/error-codes/E0505.stderr | 13 + tests/ui/error-codes/E0506.rs | 11 + tests/ui/error-codes/E0506.stderr | 14 + tests/ui/error-codes/E0507.rs | 13 + tests/ui/error-codes/E0507.stderr | 18 + tests/ui/error-codes/E0508-fail.rs | 6 + tests/ui/error-codes/E0508-fail.stderr | 17 + tests/ui/error-codes/E0508.rs | 6 + tests/ui/error-codes/E0508.stderr | 17 + tests/ui/error-codes/E0509.rs | 18 + tests/ui/error-codes/E0509.stderr | 17 + tests/ui/error-codes/E0511.rs | 11 + tests/ui/error-codes/E0511.stderr | 9 + tests/ui/error-codes/E0512.rs | 5 + tests/ui/error-codes/E0512.stderr | 12 + tests/ui/error-codes/E0516.rs | 4 + tests/ui/error-codes/E0516.stderr | 14 + tests/ui/error-codes/E0517.rs | 15 + tests/ui/error-codes/E0517.stderr | 36 + tests/ui/error-codes/E0518.rs | 9 + tests/ui/error-codes/E0518.stderr | 20 + tests/ui/error-codes/E0519.rs | 8 + tests/ui/error-codes/E0519.stderr | 9 + tests/ui/error-codes/E0520.rs | 22 + tests/ui/error-codes/E0520.stderr | 24 + tests/ui/error-codes/E0522.rs | 9 + tests/ui/error-codes/E0522.stderr | 9 + tests/ui/error-codes/E0527.rs | 9 + tests/ui/error-codes/E0527.stderr | 9 + tests/ui/error-codes/E0528.rs | 8 + tests/ui/error-codes/E0528.stderr | 9 + tests/ui/error-codes/E0529.rs | 8 + tests/ui/error-codes/E0529.stderr | 9 + tests/ui/error-codes/E0530.rs | 8 + tests/ui/error-codes/E0530.stderr | 12 + tests/ui/error-codes/E0532.rs | 14 + tests/ui/error-codes/E0532.stderr | 9 + tests/ui/error-codes/E0534.rs | 6 + tests/ui/error-codes/E0534.stderr | 9 + tests/ui/error-codes/E0559.rs | 8 + tests/ui/error-codes/E0559.stderr | 11 + tests/ui/error-codes/E0560.rs | 8 + tests/ui/error-codes/E0560.stderr | 11 + tests/ui/error-codes/E0565-1.rs | 5 + tests/ui/error-codes/E0565-1.stderr | 9 + tests/ui/error-codes/E0565-2.rs | 5 + tests/ui/error-codes/E0565-2.stderr | 11 + tests/ui/error-codes/E0565.rs | 5 + tests/ui/error-codes/E0565.stderr | 9 + tests/ui/error-codes/E0572.rs | 3 + tests/ui/error-codes/E0572.stderr | 9 + tests/ui/error-codes/E0582.rs | 42 + tests/ui/error-codes/E0582.stderr | 15 + tests/ui/error-codes/E0583.rs | 4 + tests/ui/error-codes/E0583.stderr | 11 + tests/ui/error-codes/E0585.rs | 4 + tests/ui/error-codes/E0585.stderr | 11 + tests/ui/error-codes/E0586.rs | 4 + tests/ui/error-codes/E0586.stderr | 11 + tests/ui/error-codes/E0594.rs | 5 + tests/ui/error-codes/E0594.stderr | 9 + tests/ui/error-codes/E0596.rs | 4 + tests/ui/error-codes/E0596.stderr | 14 + tests/ui/error-codes/E0597.rs | 12 + tests/ui/error-codes/E0597.stderr | 17 + tests/ui/error-codes/E0599.rs | 5 + tests/ui/error-codes/E0599.stderr | 12 + tests/ui/error-codes/E0600.rs | 3 + tests/ui/error-codes/E0600.stderr | 9 + tests/ui/error-codes/E0601.rs | 1 + tests/ui/error-codes/E0601.stderr | 9 + tests/ui/error-codes/E0602.rs | 6 + tests/ui/error-codes/E0602.stderr | 11 + tests/ui/error-codes/E0603.rs | 7 + tests/ui/error-codes/E0603.stderr | 15 + tests/ui/error-codes/E0604.rs | 3 + tests/ui/error-codes/E0604.stderr | 12 + tests/ui/error-codes/E0605.rs | 7 + tests/ui/error-codes/E0605.stderr | 21 + tests/ui/error-codes/E0606.rs | 4 + tests/ui/error-codes/E0606.stderr | 26 + tests/ui/error-codes/E0607.rs | 4 + tests/ui/error-codes/E0607.stderr | 9 + tests/ui/error-codes/E0608.rs | 3 + tests/ui/error-codes/E0608.stderr | 9 + tests/ui/error-codes/E0609.rs | 12 + tests/ui/error-codes/E0609.stderr | 17 + tests/ui/error-codes/E0610.rs | 4 + tests/ui/error-codes/E0610.stderr | 9 + tests/ui/error-codes/E0614.rs | 4 + tests/ui/error-codes/E0614.stderr | 9 + tests/ui/error-codes/E0615.rs | 12 + tests/ui/error-codes/E0615.stderr | 14 + tests/ui/error-codes/E0616.rs | 14 + tests/ui/error-codes/E0616.stderr | 9 + tests/ui/error-codes/E0617.rs | 26 + tests/ui/error-codes/E0617.stderr | 44 + tests/ui/error-codes/E0618.rs | 11 + tests/ui/error-codes/E0618.stderr | 30 + tests/ui/error-codes/E0620.rs | 3 + tests/ui/error-codes/E0620.stderr | 15 + .../E0621-does-not-trigger-for-closures.rs | 16 + .../E0621-does-not-trigger-for-closures.stderr | 11 + tests/ui/error-codes/E0622.rs | 6 + tests/ui/error-codes/E0622.stderr | 9 + tests/ui/error-codes/E0624.rs | 12 + tests/ui/error-codes/E0624.stderr | 12 + tests/ui/error-codes/E0637.rs | 17 + tests/ui/error-codes/E0637.stderr | 34 + tests/ui/error-codes/E0642.fixed | 20 + tests/ui/error-codes/E0642.rs | 20 + tests/ui/error-codes/E0642.stderr | 36 + tests/ui/error-codes/E0646.rs | 1 + tests/ui/error-codes/E0646.stderr | 9 + tests/ui/error-codes/E0647.rs | 9 + tests/ui/error-codes/E0647.stderr | 9 + tests/ui/error-codes/E0648.rs | 4 + tests/ui/error-codes/E0648.stderr | 9 + tests/ui/error-codes/E0657.rs | 26 + tests/ui/error-codes/E0657.stderr | 15 + tests/ui/error-codes/E0658.rs | 6 + tests/ui/error-codes/E0658.stderr | 12 + tests/ui/error-codes/E0659.rs | 16 + tests/ui/error-codes/E0659.stderr | 23 + tests/ui/error-codes/E0705.rs | 10 + tests/ui/error-codes/E0705.stderr | 9 + tests/ui/error-codes/E0711.rs | 18 + tests/ui/error-codes/E0711.stderr | 15 + tests/ui/error-codes/E0718.rs | 7 + tests/ui/error-codes/E0718.stderr | 9 + tests/ui/error-codes/E0719.rs | 14 + tests/ui/error-codes/E0719.stderr | 19 + tests/ui/error-codes/E0730.rs | 8 + tests/ui/error-codes/E0730.stderr | 9 + tests/ui/error-codes/E0746.fixed | 18 + tests/ui/error-codes/E0746.rs | 18 + tests/ui/error-codes/E0746.stderr | 27 + tests/ui/error-codes/E0767.rs | 8 + tests/ui/error-codes/E0767.stderr | 27 + tests/ui/error-codes/E0771.rs | 8 + tests/ui/error-codes/E0771.stderr | 20 + tests/ui/error-codes/E0777.rs | 7 + tests/ui/error-codes/E0777.stderr | 21 + tests/ui/error-codes/E0778.rs | 4 + tests/ui/error-codes/E0778.stderr | 9 + tests/ui/error-codes/E0779.rs | 2 + tests/ui/error-codes/E0779.stderr | 9 + tests/ui/error-codes/E0790.rs | 53 + tests/ui/error-codes/E0790.stderr | 73 + tests/ui/error-codes/auxiliary/crateresolve1-1.rs | 6 + tests/ui/error-codes/auxiliary/crateresolve1-2.rs | 6 + tests/ui/error-codes/auxiliary/crateresolve1-3.rs | 6 + tests/ui/error-codes/auxiliary/found-staticlib.rs | 4 + .../e0119/auxiliary/complex_impl_support.rs | 22 + .../error-codes/e0119/auxiliary/issue-23563-a.rs | 25 + tests/ui/error-codes/e0119/complex-impl.rs | 11 + tests/ui/error-codes/e0119/complex-impl.stderr | 14 + tests/ui/error-codes/e0119/conflict-with-std.rs | 26 + .../ui/error-codes/e0119/conflict-with-std.stderr | 32 + tests/ui/error-codes/e0119/issue-23563.rs | 29 + tests/ui/error-codes/e0119/issue-23563.stderr | 13 + tests/ui/error-codes/e0119/issue-27403.rs | 11 + tests/ui/error-codes/e0119/issue-27403.stderr | 13 + tests/ui/error-codes/e0119/issue-28981.rs | 7 + tests/ui/error-codes/e0119/issue-28981.stderr | 12 + tests/ui/error-codes/e0119/so-37347311.rs | 17 + tests/ui/error-codes/e0119/so-37347311.stderr | 12 + tests/ui/error-codes/ex-E0611.rs | 12 + tests/ui/error-codes/ex-E0611.stderr | 9 + tests/ui/error-codes/ex-E0612.rs | 6 + tests/ui/error-codes/ex-E0612.stderr | 9 + tests/ui/error-festival.rs | 43 + tests/ui/error-festival.stderr | 88 + tests/ui/error-should-say-copy-not-pod.rs | 7 + tests/ui/error-should-say-copy-not-pod.stderr | 17 + tests/ui/errors/auxiliary/remapped_dep.rs | 4 + tests/ui/errors/issue-104621-extern-bad-file.rs | 8 + .../ui/errors/issue-104621-extern-bad-file.stderr | 21 + tests/ui/errors/issue-104621-extern-not-file.rs | 4 + .../ui/errors/issue-104621-extern-not-file.stderr | 8 + .../issue-89280-emitter-overflow-splice-lines.rs | 10 + ...ssue-89280-emitter-overflow-splice-lines.stderr | 23 + .../ui/errors/issue-99572-impl-trait-on-pointer.rs | 25 + .../issue-99572-impl-trait-on-pointer.stderr | 31 + .../remap-path-prefix-reverse.local-self.stderr | 14 + .../remap-path-prefix-reverse.remapped-self.stderr | 14 + tests/ui/errors/remap-path-prefix-reverse.rs | 17 + tests/ui/errors/remap-path-prefix.rs | 17 + tests/ui/errors/remap-path-prefix.stderr | 9 + tests/ui/exclusive-drop-and-copy.rs | 17 + tests/ui/exclusive-drop-and-copy.stderr | 19 + tests/ui/exec-env.rs | 10 + tests/ui/explain.rs | 2 + tests/ui/explain.stdout | 71 + tests/ui/explicit-i-suffix.rs | 14 + tests/ui/explicit/explicit-call-to-dtor.fixed | 16 + tests/ui/explicit/explicit-call-to-dtor.rs | 16 + tests/ui/explicit/explicit-call-to-dtor.stderr | 12 + .../explicit-call-to-supertrait-dtor.fixed | 26 + .../explicit/explicit-call-to-supertrait-dtor.rs | 26 + .../explicit-call-to-supertrait-dtor.stderr | 12 + .../ui/explicit/explicit-self-lifetime-mismatch.rs | 20 + .../explicit-self-lifetime-mismatch.stderr | 41 + tests/ui/explore-issue-38412.rs | 64 + tests/ui/explore-issue-38412.stderr | 169 + tests/ui/expr-block-fn.rs | 9 + tests/ui/expr-block-generic-unique1.rs | 18 + tests/ui/expr-block-generic-unique2.rs | 14 + tests/ui/expr-block-generic.rs | 27 + tests/ui/expr-block.rs | 18 + tests/ui/expr-copy.rs | 18 + tests/ui/expr-if-generic.rs | 29 + tests/ui/expr-if-panic-all.rs | 11 + tests/ui/expr-if-unique.rs | 9 + tests/ui/expr-scope.rs | 7 + tests/ui/expr/compound-assignment/eval-order.rs | 76 + tests/ui/expr/if-bot.rs | 6 + tests/ui/expr/if/attrs/bad-cfg.rs | 5 + tests/ui/expr/if/attrs/bad-cfg.stderr | 8 + tests/ui/expr/if/attrs/builtin-if-attr.rs | 12 + tests/ui/expr/if/attrs/cfg-false-if-attr.rs | 43 + tests/ui/expr/if/attrs/else-attrs.rs | 25 + tests/ui/expr/if/attrs/else-attrs.stderr | 26 + tests/ui/expr/if/attrs/gate-whole-expr.rs | 15 + tests/ui/expr/if/attrs/let-chains-attr.rs | 13 + tests/ui/expr/if/attrs/stmt-expr-gated.rs | 6 + tests/ui/expr/if/attrs/stmt-expr-gated.stderr | 12 + tests/ui/expr/if/bad-if-let-suggestion.rs | 24 + tests/ui/expr/if/bad-if-let-suggestion.stderr | 74 + tests/ui/expr/if/expr-if-panic-fn.rs | 20 + tests/ui/expr/if/expr-if-panic-pass.rs | 18 + tests/ui/expr/if/expr-if-panic.rs | 13 + tests/ui/expr/if/expr-if.rs | 52 + tests/ui/expr/if/if-branch-types.rs | 5 + tests/ui/expr/if/if-branch-types.stderr | 16 + tests/ui/expr/if/if-check-panic.rs | 25 + tests/ui/expr/if/if-check.rs | 17 + tests/ui/expr/if/if-cond-bot.rs | 13 + tests/ui/expr/if/if-else-type-mismatch.rs | 46 + tests/ui/expr/if/if-else-type-mismatch.stderr | 116 + tests/ui/expr/if/if-let-arm-types.rs | 11 + tests/ui/expr/if/if-let-arm-types.stderr | 17 + tests/ui/expr/if/if-let.rs | 49 + tests/ui/expr/if/if-let.stderr | 69 + tests/ui/expr/if/if-loop.rs | 8 + tests/ui/expr/if/if-no-match-bindings.rs | 28 + tests/ui/expr/if/if-no-match-bindings.stderr | 95 + tests/ui/expr/if/if-ret.rs | 8 + tests/ui/expr/if/if-ret.stderr | 12 + tests/ui/expr/if/if-typeck.rs | 10 + tests/ui/expr/if/if-typeck.stderr | 12 + tests/ui/expr/if/if-without-block.rs | 7 + tests/ui/expr/if/if-without-block.stderr | 14 + tests/ui/expr/if/if-without-else-as-fn-expr.rs | 49 + tests/ui/expr/if/if-without-else-as-fn-expr.stderr | 83 + tests/ui/expr/if/if-without-else-result.rs | 6 + tests/ui/expr/if/if-without-else-result.stderr | 15 + tests/ui/expr/if/issue-4201.rs | 9 + tests/ui/expr/if/issue-4201.stderr | 18 + .../missing_braces_around_block.fixed | 19 + .../missing_braces_around_block.rs | 19 + .../missing_braces_around_block.stderr | 38 + .../expr/malformed_closure/ruby_style_closure.rs | 15 + .../malformed_closure/ruby_style_closure.stderr | 9 + tests/ui/ext-expand-inner-exprs.rs | 7 + tests/ui/ext-nonexistent.rs | 2 + tests/ui/ext-nonexistent.stderr | 8 + tests/ui/extenv/extenv-arg-2-not-string-literal.rs | 1 + .../extenv/extenv-arg-2-not-string-literal.stderr | 8 + tests/ui/extenv/extenv-no-args.rs | 1 + tests/ui/extenv/extenv-no-args.stderr | 8 + tests/ui/extenv/extenv-not-defined-custom.rs | 1 + tests/ui/extenv/extenv-not-defined-custom.stderr | 10 + tests/ui/extenv/extenv-not-defined-default.rs | 4 + tests/ui/extenv/extenv-not-defined-default.stderr | 10 + tests/ui/extenv/extenv-not-string-literal.rs | 1 + tests/ui/extenv/extenv-not-string-literal.stderr | 8 + tests/ui/extenv/extenv-too-many-args.rs | 1 + tests/ui/extenv/extenv-too-many-args.stderr | 8 + tests/ui/extenv/issue-55897.rs | 20 + tests/ui/extenv/issue-55897.stderr | 45 + tests/ui/extern-flag/auxiliary/somedep.rs | 3 + tests/ui/extern-flag/empty-extern-arg.rs | 6 + tests/ui/extern-flag/empty-extern-arg.stderr | 11 + tests/ui/extern-flag/multiple-opts.rs | 20 + tests/ui/extern-flag/multiple-opts.stderr | 9 + tests/ui/extern-flag/no-nounused.rs | 6 + tests/ui/extern-flag/no-nounused.stderr | 10 + tests/ui/extern-flag/noprelude-and-prelude.rs | 10 + tests/ui/extern-flag/noprelude-resolves.rs | 11 + tests/ui/extern-flag/noprelude.rs | 7 + tests/ui/extern-flag/noprelude.stderr | 9 + tests/ui/extern-flag/nounused.rs | 7 + tests/ui/extern-flag/public-and-private.rs | 13 + tests/ui/extern-flag/public-and-private.stderr | 14 + tests/ui/extern/auxiliary/extern-take-value.rs | 5 + .../extern/auxiliary/extern-types-inherent-impl.rs | 9 + .../extern/auxiliary/extern_calling_convention.rs | 26 + .../ui/extern/auxiliary/extern_mod_ordering_lib.rs | 5 + tests/ui/extern/auxiliary/fat_drop.rs | 13 + tests/ui/extern/auxiliary/invalid-utf8.txt | 1 + tests/ui/extern/auxiliary/issue-80074-macro.rs | 4 + tests/ui/extern/auxiliary/m1.rs | 1 + tests/ui/extern/auxiliary/m2.rs | 1 + .../ui/extern/auxiliary/no-mangle-associated-fn.rs | 21 + .../extern/auxiliary/reexport-should-still-link.rs | 5 + tests/ui/extern/extern-1.rs | 9 + tests/ui/extern/extern-calling-convention-test.rs | 12 + tests/ui/extern/extern-compare-with-return-type.rs | 27 + tests/ui/extern/extern-const.fixed | 26 + tests/ui/extern/extern-const.rs | 26 + tests/ui/extern/extern-const.stderr | 12 + tests/ui/extern/extern-crate-multiple-missing.rs | 10 + .../ui/extern/extern-crate-multiple-missing.stderr | 15 + tests/ui/extern/extern-crate-rename.rs | 8 + tests/ui/extern/extern-crate-rename.stderr | 17 + tests/ui/extern/extern-crate-visibility.rs | 24 + tests/ui/extern/extern-crate-visibility.stderr | 27 + tests/ui/extern/extern-ffi-fn-with-body.rs | 11 + tests/ui/extern/extern-ffi-fn-with-body.stderr | 18 + tests/ui/extern/extern-foreign-crate.rs | 6 + tests/ui/extern/extern-macro.rs | 6 + tests/ui/extern/extern-macro.stderr | 9 + tests/ui/extern/extern-main-fn.rs | 1 + tests/ui/extern/extern-main-fn.stderr | 12 + tests/ui/extern/extern-main-issue-86110.rs | 7 + tests/ui/extern/extern-main-issue-86110.stderr | 8 + tests/ui/extern/extern-methods.rs | 29 + tests/ui/extern/extern-mod-abi.rs | 9 + tests/ui/extern/extern-mod-ordering-exe.rs | 12 + tests/ui/extern/extern-no-mangle.rs | 30 + tests/ui/extern/extern-no-mangle.stderr | 42 + tests/ui/extern/extern-prelude-core.rs | 18 + tests/ui/extern/extern-prelude-no-speculative.rs | 13 + tests/ui/extern/extern-prelude-std.rs | 12 + tests/ui/extern/extern-pub.rs | 8 + tests/ui/extern/extern-rust.rs | 12 + tests/ui/extern/extern-static-size-overflow.rs | 43 + tests/ui/extern/extern-static-size-overflow.stderr | 20 + tests/ui/extern/extern-take-value.rs | 13 + tests/ui/extern/extern-thiscall.rs | 25 + tests/ui/extern/extern-type-diag-not-similar.rs | 22 + .../ui/extern/extern-type-diag-not-similar.stderr | 16 + tests/ui/extern/extern-types-distinct-types.rs | 12 + tests/ui/extern/extern-types-distinct-types.stderr | 19 + tests/ui/extern/extern-types-inherent-impl.rs | 26 + tests/ui/extern/extern-types-manual-sync-send.rs | 19 + tests/ui/extern/extern-types-not-sync-send.rs | 18 + tests/ui/extern/extern-types-not-sync-send.stderr | 29 + tests/ui/extern/extern-types-pointer-cast.rs | 31 + tests/ui/extern/extern-types-size_of_val.rs | 15 + tests/ui/extern/extern-types-thin-pointer.rs | 42 + tests/ui/extern/extern-types-trait-impl.rs | 26 + tests/ui/extern/extern-types-unsized.rs | 33 + tests/ui/extern/extern-types-unsized.stderr | 86 + tests/ui/extern/extern-vectorcall.rs | 27 + tests/ui/extern/extern-with-type-bounds.rs | 22 + tests/ui/extern/extern-with-type-bounds.stderr | 9 + tests/ui/extern/extern-wrong-value-type.rs | 11 + tests/ui/extern/extern-wrong-value-type.stderr | 19 + tests/ui/extern/extern_fat_drop.rs | 13 + tests/ui/extern/issue-10025.rs | 11 + tests/ui/extern/issue-10763.rs | 7 + tests/ui/extern/issue-10764-rpass.rs | 4 + tests/ui/extern/issue-13655.rs | 32 + tests/ui/extern/issue-28324.mir.stderr | 11 + tests/ui/extern/issue-28324.rs | 11 + tests/ui/extern/issue-28324.thir.stderr | 11 + .../extern/issue-36122-accessing-externed-dst.rs | 6 + .../issue-36122-accessing-externed-dst.stderr | 11 + ...655-allow-unwind-when-calling-panic-directly.rs | 64 + .../issue-64655-extern-rust-must-allow-unwind.rs | 83 + tests/ui/extern/issue-80074.rs | 10 + tests/ui/extern/issue-95829.rs | 10 + tests/ui/extern/issue-95829.stderr | 32 + tests/ui/extern/no-mangle-associated-fn.rs | 37 + tests/ui/extern/not-in-block.rs | 6 + tests/ui/extern/not-in-block.stderr | 32 + tests/ui/extoption_env-no-args.rs | 1 + tests/ui/extoption_env-no-args.stderr | 8 + tests/ui/extoption_env-not-defined.rs | 5 + tests/ui/extoption_env-not-string-literal.rs | 1 + tests/ui/extoption_env-not-string-literal.stderr | 8 + tests/ui/extoption_env-too-many-args.rs | 1 + tests/ui/extoption_env-too-many-args.stderr | 8 + tests/ui/fact.rs | 26 + tests/ui/fail-simple.rs | 3 + tests/ui/fail-simple.stderr | 10 + tests/ui/feature-gates/allow-features-empty.rs | 8 + tests/ui/feature-gates/allow-features-empty.stderr | 15 + tests/ui/feature-gates/allow-features.rs | 8 + tests/ui/feature-gates/allow-features.stderr | 9 + .../auxiliary/cfg-target-thread-local.rs | 7 + .../auxiliary/debugger-visualizer.natvis | 3 + tests/ui/feature-gates/auxiliary/pub_dep.rs | 1 + .../auxiliary/re_rebalance_coherence_lib.rs | 22 + tests/ui/feature-gates/bench.rs | 9 + tests/ui/feature-gates/bench.stderr | 21 + tests/ui/feature-gates/duplicate-features.rs | 9 + tests/ui/feature-gates/duplicate-features.stderr | 15 + .../feature-gate-abi-avr-interrupt.rs | 51 + .../feature-gate-abi-avr-interrupt.stderr | 129 + .../feature-gate-abi-msp430-interrupt.rs | 34 + .../feature-gate-abi-msp430-interrupt.stderr | 66 + .../feature-gate-abi-x86-interrupt.rs | 28 + .../feature-gate-abi-x86-interrupt.stderr | 66 + tests/ui/feature-gates/feature-gate-abi.rs | 60 + tests/ui/feature-gates/feature-gate-abi.stderr | 216 + .../feature-gate-abi_amdgpu_kernel.rs | 30 + .../feature-gate-abi_amdgpu_kernel.stderr | 97 + tests/ui/feature-gates/feature-gate-abi_ptx.rs | 26 + tests/ui/feature-gates/feature-gate-abi_ptx.stderr | 66 + .../feature-gates/feature-gate-abi_unadjusted.rs | 7 + .../feature-gate-abi_unadjusted.stderr | 11 + .../feature-gates/feature-gate-adt_const_params.rs | 2 + .../feature-gate-adt_const_params.stderr | 11 + .../feature-gate-alloc-error-handler.rs | 16 + .../feature-gate-alloc-error-handler.stderr | 12 + .../feature-gate-allocator_internals.rs | 3 + .../feature-gate-allocator_internals.stderr | 11 + ...ture-gate-allow-internal-unsafe-nested-macro.rs | 17 + ...-gate-allow-internal-unsafe-nested-macro.stderr | 15 + ...re-gate-allow-internal-unstable-nested-macro.rs | 17 + ...ate-allow-internal-unstable-nested-macro.stderr | 15 + .../feature-gate-allow-internal-unstable-struct.rs | 8 + ...ture-gate-allow-internal-unstable-struct.stderr | 20 + .../feature-gate-allow-internal-unstable.rs | 8 + .../feature-gate-allow-internal-unstable.stderr | 11 + .../feature-gate-arbitrary-self-types.rs | 29 + .../feature-gate-arbitrary-self-types.stderr | 33 + ...eature-gate-arbitrary_self_types-raw-pointer.rs | 18 + ...re-gate-arbitrary_self_types-raw-pointer.stderr | 33 + tests/ui/feature-gates/feature-gate-asm_const.rs | 16 + .../ui/feature-gates/feature-gate-asm_const.stderr | 21 + .../feature-gate-asm_experimental_arch.rs | 21 + .../feature-gate-asm_experimental_arch.stderr | 12 + tests/ui/feature-gates/feature-gate-asm_unwind.rs | 10 + .../feature-gates/feature-gate-asm_unwind.stderr | 12 + .../feature-gate-assoc-type-defaults.rs | 7 + .../feature-gate-assoc-type-defaults.stderr | 12 + .../feature-gate-associated_const_equality.rs | 15 + .../feature-gate-associated_const_equality.stderr | 12 + .../feature-gate-associated_type_bounds.rs | 76 + .../feature-gate-associated_type_bounds.stderr | 150 + tests/ui/feature-gates/feature-gate-auto-traits.rs | 12 + .../feature-gates/feature-gate-auto-traits.stderr | 21 + tests/ui/feature-gates/feature-gate-box-expr.rs | 14 + .../ui/feature-gates/feature-gate-box-expr.stderr | 12 + .../ui/feature-gates/feature-gate-box_patterns.rs | 4 + .../feature-gates/feature-gate-box_patterns.stderr | 12 + tests/ui/feature-gates/feature-gate-box_syntax.rs | 6 + .../feature-gates/feature-gate-box_syntax.stderr | 12 + tests/ui/feature-gates/feature-gate-c_variadic.rs | 4 + .../feature-gates/feature-gate-c_variadic.stderr | 12 + .../feature-gates/feature-gate-cfg-target-abi.rs | 13 + .../feature-gate-cfg-target-abi.stderr | 39 + .../feature-gate-cfg-target-compact.rs | 13 + .../feature-gate-cfg-target-compact.stderr | 39 + ...e-gate-cfg-target-has-atomic-equal-alignment.rs | 14 + ...te-cfg-target-has-atomic-equal-alignment.stderr | 57 + .../feature-gate-cfg-target-has-atomic.rs | 14 + .../feature-gate-cfg-target-has-atomic.stderr | 57 + .../feature-gate-cfg-target-thread-local.rs | 16 + .../feature-gate-cfg-target-thread-local.stderr | 12 + tests/ui/feature-gates/feature-gate-cfg-version.rs | 49 + .../feature-gates/feature-gate-cfg-version.stderr | 204 + .../ui/feature-gates/feature-gate-cfg_sanitize.rs | 3 + .../feature-gates/feature-gate-cfg_sanitize.stderr | 12 + tests/ui/feature-gates/feature-gate-check-cfg.rs | 3 + .../ui/feature-gates/feature-gate-check-cfg.stderr | 2 + .../feature-gate-closure_lifetime_binder.rs | 8 + .../feature-gate-closure_lifetime_binder.stderr | 33 + .../feature-gate-closure_track_caller.rs | 7 + .../feature-gate-closure_track_caller.stderr | 21 + .../feature-gate-collapse_debuginfo.rs | 7 + .../feature-gate-collapse_debuginfo.stderr | 12 + .../feature-gate-compiler-builtins.rs | 3 + .../feature-gate-compiler-builtins.stderr | 11 + .../ui/feature-gates/feature-gate-concat_bytes.rs | 4 + .../feature-gates/feature-gate-concat_bytes.stderr | 12 + .../ui/feature-gates/feature-gate-concat_idents.rs | 9 + .../feature-gate-concat_idents.stderr | 21 + .../feature-gates/feature-gate-concat_idents2.rs | 4 + .../feature-gate-concat_idents2.stderr | 21 + .../feature-gates/feature-gate-concat_idents3.rs | 7 + .../feature-gate-concat_idents3.stderr | 21 + .../feature-gates/feature-gate-const-indexing.rs | 8 + .../feature-gate-const_refs_to_cell.rs | 12 + .../feature-gates/feature-gate-custom_attribute.rs | 18 + .../feature-gate-custom_attribute.stderr | 80 + .../feature-gate-custom_attribute2.rs | 58 + .../feature-gate-custom_attribute2.stderr | 104 + tests/ui/feature-gates/feature-gate-custom_mir.rs | 12 + .../feature-gates/feature-gate-custom_mir.stderr | 11 + .../feature-gate-custom_test_frameworks.rs | 6 + .../feature-gate-custom_test_frameworks.stderr | 21 + .../feature-gate-debugger-visualizer.rs | 3 + .../feature-gate-debugger-visualizer.stderr | 12 + tests/ui/feature-gates/feature-gate-decl_macro.rs | 5 + .../feature-gates/feature-gate-decl_macro.stderr | 12 + ...feature-gate-default_type_parameter_fallback.rs | 12 + ...ure-gate-default_type_parameter_fallback.stderr | 21 + .../feature-gates/feature-gate-deprecated_safe.rs | 7 + .../feature-gate-deprecated_safe.stderr | 21 + tests/ui/feature-gates/feature-gate-doc_cfg.rs | 2 + tests/ui/feature-gates/feature-gate-doc_cfg.stderr | 12 + tests/ui/feature-gates/feature-gate-doc_masked.rs | 4 + .../feature-gates/feature-gate-doc_masked.stderr | 12 + .../feature-gate-doc_notable_trait.rs | 4 + .../feature-gate-doc_notable_trait.stderr | 12 + .../feature-gate-exclusive-range-pattern.rs | 6 + .../feature-gate-exclusive-range-pattern.stderr | 12 + .../feature-gate-exhaustive-patterns.rs | 9 + .../feature-gate-exhaustive-patterns.stderr | 17 + .../feature-gate-extern_absolute_paths.rs | 5 + .../feature-gate-extern_absolute_paths.stderr | 20 + .../feature-gates/feature-gate-extern_prelude.rs | 1 + .../feature-gate-extern_prelude.stderr | 8 + .../ui/feature-gates/feature-gate-extern_types.rs | 5 + .../feature-gates/feature-gate-extern_types.stderr | 12 + .../ui/feature-gates/feature-gate-feature-gate.rs | 4 + .../feature-gates/feature-gate-feature-gate.stderr | 14 + tests/ui/feature-gates/feature-gate-ffi_const.rs | 6 + .../ui/feature-gates/feature-gate-ffi_const.stderr | 12 + tests/ui/feature-gates/feature-gate-ffi_pure.rs | 6 + .../ui/feature-gates/feature-gate-ffi_pure.stderr | 12 + .../feature-gate-ffi_returns_twice.rs | 6 + .../feature-gate-ffi_returns_twice.stderr | 12 + tests/ui/feature-gates/feature-gate-fn_align.rs | 4 + .../ui/feature-gates/feature-gate-fn_align.stderr | 12 + .../feature-gates/feature-gate-format_args_nl.rs | 3 + .../feature-gate-format_args_nl.stderr | 11 + tests/ui/feature-gates/feature-gate-fundamental.rs | 4 + .../feature-gates/feature-gate-fundamental.stderr | 12 + tests/ui/feature-gates/feature-gate-generators.rs | 10 + .../feature-gates/feature-gate-generators.stderr | 37 + .../feature-gate-generic_arg_infer.normal.stderr | 43 + .../feature-gate-generic_arg_infer.rs | 23 + ...ature-gate-generic_associated_types_extended.rs | 4 + ...e-gate-generic_associated_types_extended.stderr | 11 + .../feature-gate-impl_trait_in_fn_trait_return.rs | 6 + ...ature-gate-impl_trait_in_fn_trait_return.stderr | 21 + .../ui/feature-gates/feature-gate-imported_main.rs | 6 + .../feature-gate-imported_main.stderr | 12 + .../feature-gate-inherent_associated_types.rs | 10 + .../feature-gate-inherent_associated_types.stderr | 12 + .../ui/feature-gates/feature-gate-inline_const.rs | 6 + .../feature-gates/feature-gate-inline_const.stderr | 12 + .../feature-gates/feature-gate-inline_const_pat.rs | 4 + .../feature-gate-inline_const_pat.stderr | 12 + tests/ui/feature-gates/feature-gate-intrinsics.rs | 8 + .../feature-gates/feature-gate-intrinsics.stderr | 32 + tests/ui/feature-gates/feature-gate-is_sorted.rs | 13 + .../ui/feature-gates/feature-gate-is_sorted.stderr | 39 + tests/ui/feature-gates/feature-gate-lang-items.rs | 5 + .../feature-gates/feature-gate-lang-items.stderr | 18 + .../feature-gate-large-assignments.rs | 5 + .../feature-gate-large-assignments.stderr | 12 + tests/ui/feature-gates/feature-gate-link_cfg.rs | 5 + .../ui/feature-gates/feature-gate-link_cfg.stderr | 12 + .../feature-gate-link_llvm_intrinsics.rs | 7 + .../feature-gate-link_llvm_intrinsics.stderr | 12 + tests/ui/feature-gates/feature-gate-linkage.rs | 6 + tests/ui/feature-gates/feature-gate-linkage.stderr | 12 + .../ui/feature-gates/feature-gate-lint-reasons.rs | 5 + .../feature-gates/feature-gate-lint-reasons.stderr | 21 + tests/ui/feature-gates/feature-gate-log_syntax.rs | 3 + .../feature-gates/feature-gate-log_syntax.stderr | 12 + .../feature-gates/feature-gate-log_syntax.stdout | 1 + tests/ui/feature-gates/feature-gate-log_syntax2.rs | 3 + .../feature-gates/feature-gate-log_syntax2.stderr | 12 + .../feature-gates/feature-gate-log_syntax2.stdout | 1 + .../feature-gate-marker_trait_attr.rs | 9 + .../feature-gate-marker_trait_attr.stderr | 12 + tests/ui/feature-gates/feature-gate-may-dangle.rs | 11 + .../feature-gates/feature-gate-may-dangle.stderr | 12 + .../ui/feature-gates/feature-gate-min_const_fn.rs | 35 + .../feature-gates/feature-gate-min_const_fn.stderr | 21 + .../feature-gate-more-qualified-paths.rs | 27 + .../feature-gate-more-qualified-paths.stderr | 30 + .../feature-gates/feature-gate-naked_functions.rs | 17 + .../feature-gate-naked_functions.stderr | 21 + ...feature-gate-native_link_modifiers_as_needed.rs | 5 + ...ure-gate-native_link_modifiers_as_needed.stderr | 12 + .../feature-gates/feature-gate-needs-allocator.rs | 3 + .../feature-gate-needs-allocator.stderr | 11 + .../feature-gates/feature-gate-negate-unsigned.rs | 18 + .../feature-gate-negate-unsigned.stderr | 22 + tests/ui/feature-gates/feature-gate-never_type.rs | 17 + .../feature-gates/feature-gate-never_type.stderr | 48 + tests/ui/feature-gates/feature-gate-no_core.rs | 5 + tests/ui/feature-gates/feature-gate-no_core.stderr | 12 + tests/ui/feature-gates/feature-gate-no_coverage.rs | 13 + .../feature-gates/feature-gate-no_coverage.stderr | 12 + tests/ui/feature-gates/feature-gate-no_sanitize.rs | 4 + .../feature-gates/feature-gate-no_sanitize.stderr | 12 + ...re-gate-non_exhaustive_omitted_patterns_lint.rs | 34 + ...ate-non_exhaustive_omitted_patterns_lint.stderr | 124 + .../feature-gate-object_safe_for_dispatch.rs | 41 + .../feature-gate-object_safe_for_dispatch.stderr | 83 + ...feature-gate-omit-gdb-pretty-printer-section.rs | 2 + ...ure-gate-omit-gdb-pretty-printer-section.stderr | 11 + .../feature-gate-optimize_attribute.rs | 18 + .../feature-gate-optimize_attribute.stderr | 55 + .../feature-gate-overlapping_marker_traits.rs | 9 + .../feature-gate-overlapping_marker_traits.stderr | 11 + .../feature-gate-precise_pointer_size_matching.rs | 17 + ...ature-gate-precise_pointer_size_matching.stderr | 33 + .../feature-gates/feature-gate-prelude_import.rs | 4 + .../feature-gate-prelude_import.stderr | 11 + .../feature-gates/feature-gate-profiler-runtime.rs | 3 + .../feature-gate-profiler-runtime.stderr | 11 + .../feature-gate-public_private_dependencies.rs | 20 + tests/ui/feature-gates/feature-gate-raw-dylib-2.rs | 12 + .../feature-gates/feature-gate-raw-dylib-2.stderr | 21 + .../feature-gate-raw-dylib-import-name-type.rs | 8 + .../feature-gate-raw-dylib-import-name-type.stderr | 21 + tests/ui/feature-gates/feature-gate-raw-dylib.rs | 7 + .../ui/feature-gates/feature-gate-raw-dylib.stderr | 12 + .../ui/feature-gates/feature-gate-register_tool.rs | 3 + .../feature-gate-register_tool.stderr | 12 + tests/ui/feature-gates/feature-gate-repr-simd.rs | 9 + .../ui/feature-gates/feature-gate-repr-simd.stderr | 35 + tests/ui/feature-gates/feature-gate-repr128.rs | 6 + tests/ui/feature-gates/feature-gate-repr128.stderr | 12 + ...ure-gate-return_position_impl_trait_in_trait.rs | 18 + ...gate-return_position_impl_trait_in_trait.stderr | 30 + .../ui/feature-gates/feature-gate-rust_cold_cc.rs | 21 + .../feature-gates/feature-gate-rust_cold_cc.stderr | 66 + .../feature-gate-rustc-allow-const-fn-unstable.rs | 6 + ...ature-gate-rustc-allow-const-fn-unstable.stderr | 12 + .../ui/feature-gates/feature-gate-rustc-attrs-1.rs | 7 + .../feature-gate-rustc-attrs-1.stderr | 27 + tests/ui/feature-gates/feature-gate-rustc-attrs.rs | 23 + .../feature-gates/feature-gate-rustc-attrs.stderr | 47 + .../feature-gate-rustc_const_unstable.rs | 7 + .../feature-gate-rustc_const_unstable.stderr | 9 + .../feature-gate-rustdoc_internals.rs | 10 + .../feature-gate-rustdoc_internals.stderr | 21 + tests/ui/feature-gates/feature-gate-simd-ffi.rs | 13 + .../ui/feature-gates/feature-gate-simd-ffi.stderr | 18 + tests/ui/feature-gates/feature-gate-simd.rs | 11 + tests/ui/feature-gates/feature-gate-simd.stderr | 12 + tests/ui/feature-gates/feature-gate-staged_api.rs | 14 + .../feature-gates/feature-gate-staged_api.stderr | 15 + tests/ui/feature-gates/feature-gate-start.rs | 3 + tests/ui/feature-gates/feature-gate-start.stderr | 12 + .../feature-gate-stmt_expr_attributes.rs | 4 + .../feature-gate-stmt_expr_attributes.stderr | 12 + .../feature-gate-strict_provenance.rs | 19 + .../feature-gate-strict_provenance.stderr | 63 + .../feature-gate-test_unstable_lint.rs | 9 + .../feature-gate-test_unstable_lint.stderr | 30 + .../ui/feature-gates/feature-gate-thread_local.rs | 11 + .../feature-gates/feature-gate-thread_local.stderr | 12 + .../ui/feature-gates/feature-gate-trace_macros.rs | 3 + .../feature-gates/feature-gate-trace_macros.stderr | 12 + tests/ui/feature-gates/feature-gate-trait-alias.rs | 4 + .../feature-gates/feature-gate-trait-alias.stderr | 12 + .../feature-gates/feature-gate-trait_upcasting.rs | 13 + .../feature-gate-trait_upcasting.stderr | 13 + .../feature-gate-transparent_unions.rs | 7 + .../feature-gate-transparent_unions.stderr | 12 + .../feature-gate-trivial_bounds-lint.rs | 8 + .../feature-gates/feature-gate-trivial_bounds.rs | 69 + .../feature-gate-trivial_bounds.stderr | 118 + tests/ui/feature-gates/feature-gate-try_blocks.rs | 9 + .../feature-gates/feature-gate-try_blocks.stderr | 16 + .../feature-gate-type_alias_impl_trait.rs | 34 + .../feature-gates/feature-gate-type_ascription.rs | 5 + .../feature-gate-type_ascription.stderr | 12 + .../feature-gate-unboxed-closures-manual-impls.rs | 37 + ...ature-gate-unboxed-closures-manual-impls.stderr | 105 + .../feature-gate-unboxed-closures-method-calls.rs | 9 + ...ature-gate-unboxed-closures-method-calls.stderr | 30 + .../feature-gate-unboxed-closures-ufcs-calls.rs | 9 + ...feature-gate-unboxed-closures-ufcs-calls.stderr | 30 + .../feature-gates/feature-gate-unboxed-closures.rs | 18 + .../feature-gate-unboxed-closures.stderr | 30 + .../ui/feature-gates/feature-gate-unix_sigpipe.rs | 4 + .../feature-gates/feature-gate-unix_sigpipe.stderr | 12 + .../feature-gate-unsafe_pin_internals.rs | 17 + .../feature-gate-unsafe_pin_internals.stderr | 14 + .../feature-gate-unsized_fn_params.rs | 30 + .../feature-gate-unsized_fn_params.stderr | 60 + .../feature-gates/feature-gate-unsized_locals.rs | 5 + .../feature-gate-unsized_locals.stderr | 20 + .../feature-gate-unsized_tuple_coercion.rs | 4 + .../feature-gate-unsized_tuple_coercion.stderr | 12 + .../ui/feature-gates/feature-gate-used_with_arg.rs | 7 + .../feature-gate-used_with_arg.stderr | 21 + tests/ui/feature-gates/feature-gate-vectorcall.rs | 31 + .../feature-gates/feature-gate-vectorcall.stderr | 59 + tests/ui/feature-gates/feature-gate-wasm_abi.rs | 26 + .../ui/feature-gates/feature-gate-wasm_abi.stderr | 66 + .../feature-gate-with_negative_coherence.rs | 8 + .../feature-gate-with_negative_coherence.stderr | 12 + .../feature-gates/feature-gate-yeet_expr-in-cfg.rs | 19 + .../feature-gate-yeet_expr-in-cfg.stderr | 21 + tests/ui/feature-gates/feature-gate-yeet_expr.rs | 9 + .../ui/feature-gates/feature-gate-yeet_expr.stderr | 21 + .../feature-gated-feature-in-macro-arg.rs | 14 + .../feature-gated-feature-in-macro-arg.stderr | 11 + tests/ui/feature-gates/gated-bad-feature.rs | 10 + tests/ui/feature-gates/gated-bad-feature.stderr | 46 + .../feature-gates/issue-43106-gating-of-bench.rs | 10 + .../issue-43106-gating-of-bench.stderr | 21 + .../issue-43106-gating-of-builtin-attrs-error.rs | 160 + ...ssue-43106-gating-of-builtin-attrs-error.stderr | 310 + .../issue-43106-gating-of-builtin-attrs.rs | 772 ++ .../issue-43106-gating-of-builtin-attrs.stderr | 1181 +++ .../issue-43106-gating-of-deprecated.rs | 12 + .../issue-43106-gating-of-derive-2.rs | 20 + .../issue-43106-gating-of-derive-2.stderr | 38 + .../feature-gates/issue-43106-gating-of-derive.rs | 33 + .../issue-43106-gating-of-derive.stderr | 64 + .../issue-43106-gating-of-macro_escape.rs | 11 + .../issue-43106-gating-of-macro_escape.stderr | 10 + .../issue-43106-gating-of-macro_use.rs | 25 + .../issue-43106-gating-of-macro_use.stderr | 33 + .../issue-43106-gating-of-proc_macro_derive.rs | 34 + .../issue-43106-gating-of-proc_macro_derive.stderr | 38 + .../feature-gates/issue-43106-gating-of-stable.rs | 35 + .../issue-43106-gating-of-stable.stderr | 45 + .../ui/feature-gates/issue-43106-gating-of-test.rs | 7 + .../issue-43106-gating-of-test.stderr | 21 + .../issue-43106-gating-of-unstable.rs | 35 + .../issue-43106-gating-of-unstable.stderr | 45 + tests/ui/feature-gates/issue-49983-see-issue-0.rs | 6 + .../feature-gates/issue-49983-see-issue-0.stderr | 11 + tests/ui/feature-gates/rustc-private.rs | 5 + tests/ui/feature-gates/rustc-private.stderr | 12 + .../feature-gates/soft-syntax-gates-with-errors.rs | 30 + .../soft-syntax-gates-with-errors.stderr | 21 + .../soft-syntax-gates-without-errors.rs | 26 + .../soft-syntax-gates-without-errors.stderr | 24 + .../stability-attribute-consistency.rs | 16 + .../stability-attribute-consistency.stderr | 15 + tests/ui/feature-gates/stable-features.rs | 14 + tests/ui/feature-gates/stable-features.stderr | 20 + tests/ui/feature-gates/trace_macros-gate.rs | 14 + tests/ui/feature-gates/trace_macros-gate.stderr | 49 + tests/ui/feature-gates/unknown-feature.rs | 3 + tests/ui/feature-gates/unknown-feature.stderr | 9 + .../unstable-attribute-allow-issue-0.rs | 13 + .../unstable-attribute-allow-issue-0.stderr | 19 + tests/ui/ffi_const.rs | 5 + tests/ui/ffi_const.stderr | 9 + tests/ui/ffi_const2.rs | 11 + tests/ui/ffi_const2.stderr | 9 + tests/ui/ffi_pure.rs | 5 + tests/ui/ffi_pure.stderr | 9 + tests/ui/ffi_returns_twice.rs | 5 + tests/ui/ffi_returns_twice.stderr | 9 + tests/ui/filter-block-view-items.rs | 8 + tests/ui/fmt/auxiliary/format-string-proc-macro.rs | 52 + tests/ui/fmt/format-args-capture-issue-102057.rs | 19 + .../ui/fmt/format-args-capture-issue-102057.stderr | 45 + tests/ui/fmt/format-args-capture-issue-93378.rs | 11 + .../ui/fmt/format-args-capture-issue-93378.stderr | 17 + tests/ui/fmt/format-args-capture-issue-94010.rs | 7 + .../ui/fmt/format-args-capture-issue-94010.stderr | 20 + tests/ui/fmt/format-args-capture-macro-hygiene.rs | 22 + .../fmt/format-args-capture-macro-hygiene.stderr | 53 + .../fmt/format-args-capture-missing-variables.rs | 20 + .../format-args-capture-missing-variables.stderr | 47 + tests/ui/fmt/format-args-capture.rs | 89 + tests/ui/fmt/format-expanded-string.rs | 24 + tests/ui/fmt/format-expanded-string.stderr | 19 + tests/ui/fmt/format-raw-string-error.rs | 3 + tests/ui/fmt/format-raw-string-error.stderr | 10 + tests/ui/fmt/format-string-error-2.rs | 86 + tests/ui/fmt/format-string-error-2.stderr | 175 + tests/ui/fmt/format-string-error.rs | 55 + tests/ui/fmt/format-string-error.stderr | 125 + tests/ui/fmt/format-with-yield-point.rs | 33 + tests/ui/fmt/ifmt-bad-arg.rs | 99 + tests/ui/fmt/ifmt-bad-arg.stderr | 332 + tests/ui/fmt/ifmt-bad-format-args.rs | 4 + tests/ui/fmt/ifmt-bad-format-args.stderr | 21 + tests/ui/fmt/ifmt-unimpl.rs | 4 + tests/ui/fmt/ifmt-unimpl.stderr | 24 + tests/ui/fmt/ifmt-unknown-trait.rs | 4 + tests/ui/fmt/ifmt-unknown-trait.stderr | 19 + tests/ui/fmt/incorrect-separator.rs | 29 + tests/ui/fmt/incorrect-separator.stderr | 44 + tests/ui/fmt/indoc-issue-106408.rs | 9 + tests/ui/fmt/issue-103826.rs | 8 + tests/ui/fmt/issue-103826.stderr | 20 + tests/ui/fmt/issue-104142.rs | 6 + tests/ui/fmt/issue-104142.stderr | 10 + tests/ui/fmt/issue-86085.rs | 6 + tests/ui/fmt/issue-86085.stderr | 11 + tests/ui/fmt/issue-89173.rs | 14 + tests/ui/fmt/issue-89173.stderr | 18 + tests/ui/fmt/issue-91556.rs | 8 + tests/ui/fmt/issue-91556.stderr | 11 + tests/ui/fmt/respanned-literal-issue-106191.rs | 15 + tests/ui/fmt/respanned-literal-issue-106191.stderr | 2 + tests/ui/fmt/send-sync.rs | 10 + tests/ui/fmt/send-sync.stderr | 43 + .../ui/fmt/struct-field-as-captured-argument.fixed | 18 + tests/ui/fmt/struct-field-as-captured-argument.rs | 18 + .../fmt/struct-field-as-captured-argument.stderr | 79 + tests/ui/fmt/unicode-escape-spans.rs | 19 + tests/ui/fmt/unicode-escape-spans.stderr | 63 + tests/ui/fn-in-pat.rs | 16 + tests/ui/fn-in-pat.stderr | 11 + tests/ui/fn/bad-main.rs | 1 + tests/ui/fn/bad-main.stderr | 12 + tests/ui/fn/dyn-fn-alignment.rs | 23 + tests/ui/fn/expr-fn-panic.rs | 11 + tests/ui/fn/expr-fn.rs | 62 + tests/ui/fn/fn-bad-block-type.rs | 5 + tests/ui/fn/fn-bad-block-type.stderr | 11 + tests/ui/fn/fn-closure-mutable-capture.rs | 12 + tests/ui/fn/fn-closure-mutable-capture.stderr | 15 + tests/ui/fn/fn-compare-mismatch.rs | 7 + tests/ui/fn/fn-compare-mismatch.stderr | 26 + tests/ui/fn/fn-item-type.rs | 53 + tests/ui/fn/fn-item-type.stderr | 97 + tests/ui/fn/fn-recover-return-sign.fixed | 28 + tests/ui/fn/fn-recover-return-sign.rs | 28 + tests/ui/fn/fn-recover-return-sign.stderr | 26 + tests/ui/fn/fn-recover-return-sign2.rs | 8 + tests/ui/fn/fn-recover-return-sign2.stderr | 14 + tests/ui/fn/fn-trait-formatting.rs | 21 + tests/ui/fn/fn-trait-formatting.stderr | 60 + tests/ui/fn/fun-call-variants.rs | 12 + .../fn/implied-bounds-unnorm-associated-type-2.rs | 23 + .../implied-bounds-unnorm-associated-type-2.stderr | 17 + .../fn/implied-bounds-unnorm-associated-type-3.rs | 22 + .../fn/implied-bounds-unnorm-associated-type-4.rs | 24 + .../implied-bounds-unnorm-associated-type-4.stderr | 14 + .../fn/implied-bounds-unnorm-associated-type-5.rs | 23 + .../implied-bounds-unnorm-associated-type-5.stderr | 19 + .../ui/fn/implied-bounds-unnorm-associated-type.rs | 23 + .../implied-bounds-unnorm-associated-type.stderr | 14 + tests/ui/fn/issue-3044.rs | 6 + tests/ui/fn/issue-3044.stderr | 21 + tests/ui/fn/issue-3904.rs | 25 + tests/ui/fn/issue-80179.rs | 27 + tests/ui/fn/issue-80179.stderr | 23 + tests/ui/fn/keyword-order.rs | 6 + tests/ui/fn/keyword-order.stderr | 16 + tests/ui/fn/nested-function-names-issue-8587.rs | 42 + .../fn/signature-error-reporting-under-verbose.rs | 15 + .../signature-error-reporting-under-verbose.stderr | 19 + tests/ui/fn/suggest-return-closure.rs | 34 + tests/ui/fn/suggest-return-closure.stderr | 36 + tests/ui/fn/suggest-return-future.rs | 23 + tests/ui/fn/suggest-return-future.stderr | 21 + tests/ui/for-loop-while/auto-loop.rs | 10 + tests/ui/for-loop-while/break-outside-loop.rs | 35 + tests/ui/for-loop-while/break-outside-loop.stderr | 58 + tests/ui/for-loop-while/break-value.rs | 7 + tests/ui/for-loop-while/break-while-condition.rs | 29 + .../ui/for-loop-while/break-while-condition.stderr | 45 + tests/ui/for-loop-while/break.rs | 25 + .../cleanup-rvalue-during-if-and-while.rs | 41 + tests/ui/for-loop-while/for-destruct.rs | 9 + tests/ui/for-loop-while/for-loop-goofiness.rs | 16 + tests/ui/for-loop-while/for-loop-has-unit-body.rs | 13 + tests/ui/for-loop-while/for-loop-into-iterator.rs | 19 + .../for-loop-lifetime-of-unbound-values.rs | 34 + tests/ui/for-loop-while/for-loop-macro.rs | 11 + .../ui/for-loop-while/for-loop-mut-ref-element.rs | 6 + tests/ui/for-loop-while/for-loop-no-std.rs | 14 + tests/ui/for-loop-while/for-loop-panic.rs | 4 + ...loop-unconstrained-element-type-i32-fallback.rs | 11 + .../foreach-external-iterators-break.rs | 13 + ...ach-external-iterators-hashmap-break-restart.rs | 33 + .../foreach-external-iterators-hashmap.rs | 19 + .../foreach-external-iterators-loop.rs | 13 + .../foreach-external-iterators-nested.rs | 15 + .../for-loop-while/foreach-external-iterators.rs | 10 + tests/ui/for-loop-while/foreach-nested.rs | 16 + tests/ui/for-loop-while/foreach-put-structured.rs | 22 + .../ui/for-loop-while/foreach-simple-outer-slot.rs | 16 + tests/ui/for-loop-while/issue-2216.rs | 24 + tests/ui/for-loop-while/issue-51345.rs | 8 + tests/ui/for-loop-while/issue-69841.rs | 31 + tests/ui/for-loop-while/label_break_value.rs | 166 + .../ui/for-loop-while/label_break_value_invalid.rs | 35 + .../label_break_value_invalid.stderr | 32 + tests/ui/for-loop-while/labeled-break.rs | 22 + tests/ui/for-loop-while/linear-for-loop.rs | 23 + .../liveness-assign-imm-local-after-loop.rs | 18 + tests/ui/for-loop-while/liveness-loop-break.rs | 13 + tests/ui/for-loop-while/liveness-move-in-loop.rs | 20 + tests/ui/for-loop-while/long-while.rs | 12 + tests/ui/for-loop-while/loop-break-cont-1.rs | 9 + tests/ui/for-loop-while/loop-break-cont.rs | 39 + tests/ui/for-loop-while/loop-break-value.rs | 139 + tests/ui/for-loop-while/loop-diverges.rs | 14 + tests/ui/for-loop-while/loop-label-shadowing.rs | 12 + .../ui/for-loop-while/loop-labeled-break-value.rs | 11 + .../loop-no-reinit-needed-post-bot.rs | 34 + tests/ui/for-loop-while/loop-scope.rs | 8 + tests/ui/for-loop-while/while-cont.rs | 11 + tests/ui/for-loop-while/while-flow-graph.rs | 6 + tests/ui/for-loop-while/while-label.rs | 15 + tests/ui/for-loop-while/while-let-2.rs | 31 + tests/ui/for-loop-while/while-let-2.stderr | 42 + tests/ui/for-loop-while/while-let.rs | 46 + .../ui/for-loop-while/while-loop-constraints-2.rs | 15 + tests/ui/for-loop-while/while-prelude-drop.rs | 24 + tests/ui/for-loop-while/while-with-break.rs | 17 + tests/ui/for-loop-while/while.rs | 13 + tests/ui/for/for-c-in-str.rs | 14 + tests/ui/for/for-c-in-str.stderr | 12 + tests/ui/for/for-expn.rs | 9 + tests/ui/for/for-expn.stderr | 9 + tests/ui/for/for-loop-bogosity.rs | 21 + tests/ui/for/for-loop-bogosity.stderr | 12 + .../for-loop-refutable-pattern-error-message.rs | 3 + ...for-loop-refutable-pattern-error-message.stderr | 11 + tests/ui/for/for-loop-type-error.rs | 6 + tests/ui/for/for-loop-type-error.stderr | 11 + .../ui/for/for-loop-unconstrained-element-type.rs | 9 + .../for/for-loop-unconstrained-element-type.stderr | 14 + tests/ui/foreign-fn-return-lifetime.fixed | 8 + tests/ui/foreign-fn-return-lifetime.rs | 8 + tests/ui/foreign-fn-return-lifetime.stderr | 15 + tests/ui/foreign-unsafe-fn-called.mir.stderr | 11 + tests/ui/foreign-unsafe-fn-called.rs | 14 + tests/ui/foreign-unsafe-fn-called.thir.stderr | 11 + tests/ui/foreign/auxiliary/fn-abi.rs | 2 + tests/ui/foreign/foreign-fn-linkname.rs | 28 + tests/ui/foreign/foreign-int-types.rs | 12 + .../foreign/foreign-mod-src/compiletest-ignore-dir | 0 tests/ui/foreign/foreign-mod-src/inner.rs | 14 + tests/ui/foreign/foreign-mod-unused-const.rs | 11 + tests/ui/foreign/foreign-pub-super.rs | 12 + .../ui/foreign/foreign-src/compiletest-ignore-dir | 0 tests/ui/foreign/foreign-src/foreign.rs | 9 + tests/ui/foreign/foreign-truncated-arguments.rs | 20 + tests/ui/foreign/foreign2.rs | 29 + .../issue-74120-lowering-of-ffi-block-bodies.rs | 11 + ...issue-74120-lowering-of-ffi-block-bodies.stderr | 19 + .../foreign/issue-91370-foreign-fn-block-impl.rs | 12 + .../issue-91370-foreign-fn-block-impl.stderr | 21 + .../ui/foreign/issue-99276-same-type-lifetimes.rs | 24 + tests/ui/foreign/nil-decl-in-foreign.rs | 14 + tests/ui/format-no-std.rs | 28 + .../fully-qualified-type-name1.rs | 10 + .../fully-qualified-type-name1.stderr | 20 + .../fully-qualified-type-name2.rs | 18 + .../fully-qualified-type-name2.stderr | 23 + .../fully-qualified-type-name4.rs | 14 + .../fully-qualified-type-name4.stderr | 18 + tests/ui/fun-indirect-call.rs | 9 + .../function-pointer-comparison-issue-54685.rs | 30 + tests/ui/function-pointer/issue-102289.rs | 54 + tests/ui/function-pointer/sized-ret-with-binder.rs | 15 + tests/ui/function-pointer/unsized-ret.rs | 15 + tests/ui/function-pointer/unsized-ret.stderr | 35 + .../functional-struct-update-noncopyable.rs | 14 + .../functional-struct-update-noncopyable.stderr | 12 + .../functional-struct-update-respects-privacy.rs | 32 + ...unctional-struct-update-respects-privacy.stderr | 9 + tests/ui/functions-closures/auxiliary/fn-abi.rs | 2 + .../call-closure-from-overloaded-op.rs | 9 + .../capture-clauses-boxed-closures.rs | 14 + .../capture-clauses-unboxed-closures.rs | 13 + tests/ui/functions-closures/clone-closure.rs | 18 + .../closure-bounds-can-capture-chan.rs | 16 + .../closure-expected-type/README.md | 8 + .../expect-infer-supply-two-infers.rs | 19 + .../closure-expected-type/issue-38714.rs | 19 + .../supply-just-return-type.rs | 26 + .../closure-expected-type/supply-nothing.rs | 11 + tests/ui/functions-closures/closure-immediate.rs | 13 + tests/ui/functions-closures/closure-inference.rs | 11 + tests/ui/functions-closures/closure-inference2.rs | 9 + tests/ui/functions-closures/closure-reform.rs | 56 + .../closure-returning-closure.rs | 5 + .../functions-closures/closure-to-fn-coercion.rs | 35 + .../closure_to_fn_coercion-expected-types.rs | 9 + tests/ui/functions-closures/copy-closure.rs | 16 + tests/ui/functions-closures/fn-abi.rs | 18 + tests/ui/functions-closures/fn-bare-assign.rs | 17 + .../functions-closures/fn-bare-coerce-to-block.rs | 10 + tests/ui/functions-closures/fn-bare-item.rs | 8 + tests/ui/functions-closures/fn-bare-size.rs | 8 + tests/ui/functions-closures/fn-bare-spawn.rs | 15 + tests/ui/functions-closures/fn-coerce-field.rs | 13 + .../fn-help-with-err-generic-is-not-function.rs | 14 + ...fn-help-with-err-generic-is-not-function.stderr | 20 + tests/ui/functions-closures/fn-help-with-err.rs | 24 + .../ui/functions-closures/fn-help-with-err.stderr | 27 + tests/ui/functions-closures/fn-item-type-cast.rs | 22 + tests/ui/functions-closures/fn-item-type-coerce.rs | 17 + .../functions-closures/fn-item-type-zero-sized.rs | 13 + tests/ui/functions-closures/fn-lval.rs | 11 + tests/ui/functions-closures/fn-type-infer.rs | 11 + .../implied-bounds-closure-arg-outlives.rs | 35 + .../nullable-pointer-opt-closures.rs | 34 + .../parallel-codegen-closures.rs | 28 + tests/ui/functions-closures/return-from-closure.rs | 33 + tests/ui/future-incompatible-lint-group.rs | 18 + tests/ui/future-incompatible-lint-group.stderr | 28 + tests/ui/generator/addassign-yield.rs | 35 + tests/ui/generator/async-generator-issue-67158.rs | 6 + .../generator/async-generator-issue-67158.stderr | 9 + tests/ui/generator/auto-trait-regions.rs | 53 + tests/ui/generator/auto-trait-regions.stderr | 47 + .../auxiliary/metadata-sufficient-for-layout.rs | 11 + tests/ui/generator/auxiliary/xcrate-reachable.rs | 14 + tests/ui/generator/auxiliary/xcrate.rs | 18 + tests/ui/generator/borrow-in-tail-expr.rs | 11 + tests/ui/generator/borrowing.rs | 20 + tests/ui/generator/borrowing.stderr | 31 + tests/ui/generator/clone-impl-async.rs | 70 + tests/ui/generator/clone-impl-async.stderr | 171 + tests/ui/generator/clone-impl-static.rs | 17 + tests/ui/generator/clone-impl-static.stderr | 31 + tests/ui/generator/clone-impl.rs | 73 + tests/ui/generator/clone-impl.stderr | 142 + tests/ui/generator/conditional-drop.rs | 61 + tests/ui/generator/control-flow.rs | 53 + tests/ui/generator/derived-drop-parent-expr.rs | 17 + tests/ui/generator/discriminant.rs | 137 + tests/ui/generator/drop-and-replace.rs | 45 + tests/ui/generator/drop-control-flow.rs | 139 + tests/ui/generator/drop-env.rs | 66 + tests/ui/generator/drop-track-addassign-yield.rs | 41 + .../generator/drop-tracking-parent-expression.rs | 69 + .../drop-tracking-parent-expression.stderr | 128 + .../drop-tracking-yielding-in-match-guards.rs | 12 + tests/ui/generator/drop-yield-twice.rs | 15 + tests/ui/generator/drop-yield-twice.stderr | 31 + tests/ui/generator/dropck-resume.rs | 33 + tests/ui/generator/dropck-resume.stderr | 15 + tests/ui/generator/dropck.rs | 20 + tests/ui/generator/dropck.stderr | 34 + .../generator-region-requirements.migrate.stderr | 12 + .../ui/generator/generator-region-requirements.rs | 19 + .../generator/generator-region-requirements.stderr | 11 + tests/ui/generator/generator-resume-after-panic.rs | 25 + tests/ui/generator/generator-with-nll.rs | 12 + tests/ui/generator/generator-with-nll.stderr | 12 + .../generator-yielding-or-returning-itself.rs | 35 + .../generator-yielding-or-returning-itself.stderr | 53 + tests/ui/generator/issue-102645.rs | 23 + tests/ui/generator/issue-102645.stderr | 16 + tests/ui/generator/issue-44197.rs | 36 + .../issue-45729-unsafe-in-generator.mir.stderr | 11 + .../generator/issue-45729-unsafe-in-generator.rs | 12 + .../issue-45729-unsafe-in-generator.thir.stderr | 11 + tests/ui/generator/issue-48048.rs | 13 + tests/ui/generator/issue-48048.stderr | 11 + tests/ui/generator/issue-52304.rs | 11 + tests/ui/generator/issue-52398.rs | 28 + tests/ui/generator/issue-52398.stderr | 24 + tests/ui/generator/issue-53548-1.rs | 20 + tests/ui/generator/issue-53548.rs | 38 + tests/ui/generator/issue-57017.rs | 55 + tests/ui/generator/issue-57084.rs | 28 + tests/ui/generator/issue-57084.stderr | 16 + tests/ui/generator/issue-57478.rs | 17 + tests/ui/generator/issue-58888.rs | 28 + .../generator/issue-61442-stmt-expr-with-drop.rs | 32 + tests/ui/generator/issue-62506-two_awaits.rs | 17 + .../generator/issue-64620-yield-array-element.rs | 9 + .../issue-64620-yield-array-element.stderr | 9 + tests/ui/generator/issue-68112.rs | 71 + tests/ui/generator/issue-68112.stderr | 64 + tests/ui/generator/issue-69017.rs | 18 + tests/ui/generator/issue-69039.rs | 34 + tests/ui/generator/issue-87142.rs | 32 + tests/ui/generator/issue-88653.rs | 22 + tests/ui/generator/issue-88653.stderr | 15 + tests/ui/generator/issue-91477.rs | 7 + tests/ui/generator/issue-91477.stderr | 9 + tests/ui/generator/issue-93161.rs | 94 + tests/ui/generator/iterator-count.rs | 44 + tests/ui/generator/layout-error.rs | 28 + tests/ui/generator/layout-error.stderr | 9 + tests/ui/generator/live-upvar-across-yield.rs | 14 + tests/ui/generator/match-bindings.rs | 23 + tests/ui/generator/match-bindings.stderr | 17 + .../ui/generator/metadata-sufficient-for-layout.rs | 25 + .../metadata-sufficient-for-layout.stderr | 8 + tests/ui/generator/nested_generators.rs | 21 + tests/ui/generator/niche-in-generator.rs | 19 + tests/ui/generator/non-static-is-unpin.rs | 18 + tests/ui/generator/not-send-sync.rs | 21 + tests/ui/generator/not-send-sync.stderr | 56 + tests/ui/generator/overlap-locals.rs | 29 + tests/ui/generator/panic-drops-resume.rs | 36 + tests/ui/generator/panic-drops.rs | 57 + tests/ui/generator/panic-safe.rs | 30 + tests/ui/generator/partial-drop.rs | 42 + tests/ui/generator/partial-drop.stderr | 92 + .../partial-initialization-across-yield.rs | 43 + .../partial-initialization-across-yield.stderr | 33 + tests/ui/generator/pattern-borrow.rs | 17 + tests/ui/generator/pattern-borrow.stderr | 11 + tests/ui/generator/pin-box-generator.rs | 13 + .../generator/print/generator-print-verbose-1.rs | 60 + .../print/generator-print-verbose-1.stderr | 62 + .../generator/print/generator-print-verbose-2.rs | 24 + .../print/generator-print-verbose-2.stderr | 56 + .../generator/print/generator-print-verbose-3.rs | 12 + .../print/generator-print-verbose-3.stderr | 19 + tests/ui/generator/reborrow-mut-upvar.rs | 16 + tests/ui/generator/reborrow-mut-upvar.stderr | 17 + .../ui/generator/ref-escapes-but-not-over-yield.rs | 16 + .../ref-escapes-but-not-over-yield.stderr | 15 + tests/ui/generator/ref-upvar-not-send.rs | 31 + tests/ui/generator/ref-upvar-not-send.stderr | 50 + tests/ui/generator/reinit-in-match-guard.rs | 25 + tests/ui/generator/resume-after-return.rs | 28 + tests/ui/generator/resume-arg-late-bound.rs | 17 + tests/ui/generator/resume-arg-late-bound.stderr | 17 + tests/ui/generator/resume-arg-size.rs | 28 + tests/ui/generator/resume-live-across-yield.rs | 45 + tests/ui/generator/retain-resume-ref.rs | 25 + tests/ui/generator/retain-resume-ref.stderr | 13 + tests/ui/generator/size-moved-locals.rs | 78 + tests/ui/generator/sized-yield.rs | 14 + tests/ui/generator/sized-yield.stderr | 26 + tests/ui/generator/smoke-resume-args.rs | 100 + tests/ui/generator/smoke.rs | 177 + tests/ui/generator/static-generators.rs | 20 + .../generator/static-mut-reference-across-yield.rs | 32 + tests/ui/generator/static-not-unpin.rs | 15 + tests/ui/generator/static-not-unpin.stderr | 18 + .../ui/generator/static-reference-across-yield.rs | 16 + .../generator/too-live-local-in-immovable-gen.rs | 21 + .../too-live-local-in-immovable-gen.stderr | 17 + tests/ui/generator/too-many-parameters.rs | 8 + tests/ui/generator/too-many-parameters.stderr | 9 + tests/ui/generator/type-mismatch-error.rs | 22 + tests/ui/generator/type-mismatch-error.stderr | 19 + .../generator/type-mismatch-signature-deduction.rs | 18 + .../type-mismatch-signature-deduction.stderr | 33 + .../generator/unresolved-ct-var-drop-tracking.rs | 15 + .../unresolved-ct-var-drop-tracking.stderr | 78 + tests/ui/generator/unresolved-ct-var.rs | 14 + tests/ui/generator/unresolved-ct-var.stderr | 78 + tests/ui/generator/xcrate-reachable.rs | 14 + tests/ui/generator/xcrate.rs | 30 + tests/ui/generator/yield-in-args-rev.rs | 19 + tests/ui/generator/yield-in-args-rev.stderr | 14 + tests/ui/generator/yield-in-args.rs | 10 + tests/ui/generator/yield-in-args.stderr | 9 + tests/ui/generator/yield-in-box.rs | 24 + tests/ui/generator/yield-in-box.stderr | 17 + tests/ui/generator/yield-in-const.rs | 6 + tests/ui/generator/yield-in-const.stderr | 9 + tests/ui/generator/yield-in-function.rs | 4 + tests/ui/generator/yield-in-function.stderr | 9 + tests/ui/generator/yield-in-initializer.rs | 17 + tests/ui/generator/yield-in-initializer.stderr | 17 + tests/ui/generator/yield-in-static.rs | 6 + tests/ui/generator/yield-in-static.stderr | 9 + .../yield-outside-generator-issue-78653.rs | 7 + .../yield-outside-generator-issue-78653.stderr | 20 + tests/ui/generator/yield-subtype.rs | 17 + tests/ui/generator/yield-subtype.stderr | 14 + tests/ui/generator/yield-while-iterating.rs | 75 + tests/ui/generator/yield-while-iterating.stderr | 25 + tests/ui/generator/yield-while-local-borrowed.rs | 49 + .../ui/generator/yield-while-local-borrowed.stderr | 21 + tests/ui/generator/yield-while-ref-reborrowed.rs | 40 + .../ui/generator/yield-while-ref-reborrowed.stderr | 18 + tests/ui/generator/yielding-in-match-guards.rs | 53 + .../anonymize-bound-vars.rs | 13 + .../generic-associated-types/auxiliary/foo_defn.rs | 6 + .../bugs/hrtb-implied-1.rs | 34 + .../bugs/hrtb-implied-1.stderr | 20 + .../bugs/hrtb-implied-2.rs | 39 + .../bugs/hrtb-implied-2.stderr | 22 + .../bugs/hrtb-implied-3.rs | 23 + .../bugs/hrtb-implied-3.stderr | 22 + .../generic-associated-types/bugs/issue-100013.rs | 35 + .../bugs/issue-100013.stderr | 78 + .../generic-associated-types/bugs/issue-80626.rs | 12 + .../generic-associated-types/bugs/issue-87735.rs | 44 + .../bugs/issue-87735.stderr | 9 + .../generic-associated-types/bugs/issue-87755.rs | 19 + .../bugs/issue-87755.stderr | 9 + .../generic-associated-types/bugs/issue-87803.rs | 25 + .../bugs/issue-87803.stderr | 12 + .../generic-associated-types/bugs/issue-88382.rs | 29 + .../bugs/issue-88382.stderr | 22 + .../generic-associated-types/bugs/issue-88460.rs | 29 + .../bugs/issue-88460.stderr | 21 + .../generic-associated-types/bugs/issue-88526.rs | 33 + .../bugs/issue-88526.stderr | 9 + .../generic-associated-types/bugs/issue-91762.rs | 28 + .../bugs/issue-91762.stderr | 14 + .../collections-project-default.rs | 70 + .../collections-project-default.stderr | 15 + tests/ui/generic-associated-types/collections.rs | 69 + .../collectivity-regression.rs | 22 + .../collectivity-regression.stderr | 24 + .../const-generics-gat-in-trait-return-type-1.rs | 20 + .../const-generics-gat-in-trait-return-type-2.rs | 20 + .../const-generics-gat-in-trait-return-type-3.rs | 25 + .../const_params_have_right_type.rs | 10 + .../const_params_have_right_type.stderr | 16 + .../constraint-assoc-type-suggestion.rs | 14 + .../constraint-assoc-type-suggestion.stderr | 18 + .../construct_with_other_type.rs | 22 + .../generic-associated-types/cross-crate-bounds.rs | 32 + .../cross-crate-bounds.stderr | 15 + .../elided-in-expr-position.rs | 37 + .../elided-in-expr-position.stderr | 35 + .../ui/generic-associated-types/empty_generics.rs | 6 + .../generic-associated-types/empty_generics.stderr | 13 + .../ui/generic-associated-types/equality-bound.rs | 15 + .../generic-associated-types/equality-bound.stderr | 43 + .../extended/lending_iterator.base.stderr | 12 + .../extended/lending_iterator.rs | 38 + .../extended/lending_iterator_2.base.stderr | 12 + .../extended/lending_iterator_2.rs | 30 + .../gat-in-trait-path-undeclared-lifetime.rs | 9 + .../gat-in-trait-path-undeclared-lifetime.stderr | 26 + .../gat-in-trait-path.base.stderr | 18 + .../generic-associated-types/gat-in-trait-path.rs | 33 + .../gat-trait-path-generic-type-arg.rs | 14 + .../gat-trait-path-generic-type-arg.stderr | 25 + .../gat-trait-path-missing-lifetime.rs | 15 + .../gat-trait-path-missing-lifetime.stderr | 35 + .../gat-trait-path-parenthesised-args.rs | 16 + .../gat-trait-path-parenthesised-args.stderr | 74 + .../generic-associated-type-bounds.rs | 32 + .../generic-associated-types-where.rs | 26 + .../generic-associated-types-where.stderr | 25 + ...generic_associated_type_undeclared_lifetimes.rs | 13 + ...ric_associated_type_undeclared_lifetimes.stderr | 38 + tests/ui/generic-associated-types/impl_bounds.rs | 24 + .../ui/generic-associated-types/impl_bounds.stderr | 77 + .../ui/generic-associated-types/impl_bounds_ok.rs | 29 + tests/ui/generic-associated-types/issue-101020.rs | 35 + .../generic-associated-types/issue-101020.stderr | 23 + tests/ui/generic-associated-types/issue-102114.rs | 16 + .../generic-associated-types/issue-102114.stderr | 12 + tests/ui/generic-associated-types/issue-102333.rs | 15 + .../generic-associated-types/issue-102335-gat.rs | 12 + .../issue-102335-gat.stderr | 9 + .../issue-47206-where-clause.rs | 14 + .../issue-47206-where-clause.stderr | 12 + .../issue-58694-parameter-out-of-range.rs | 7 + .../issue-62326-parameter-out-of-range.rs | 11 + tests/ui/generic-associated-types/issue-67424.rs | 12 + .../issue-67510-pass.base.stderr | 18 + .../generic-associated-types/issue-67510-pass.rs | 15 + tests/ui/generic-associated-types/issue-67510.rs | 10 + .../ui/generic-associated-types/issue-67510.stderr | 50 + .../issue-68641-check-gat-bounds.rs | 29 + .../issue-68641-check-gat-bounds.stderr | 19 + .../issue-68642-broken-llvm-ir.rs | 18 + .../issue-68642-broken-llvm-ir.stderr | 20 + .../issue-68643-broken-mir.rs | 18 + .../issue-68643-broken-mir.stderr | 20 + .../issue-68644-codegen-selection.rs | 18 + .../issue-68644-codegen-selection.stderr | 20 + .../issue-68645-codegen-fulfillment.rs | 18 + .../issue-68645-codegen-fulfillment.stderr | 20 + tests/ui/generic-associated-types/issue-68648-1.rs | 22 + tests/ui/generic-associated-types/issue-68648-2.rs | 21 + .../generic-associated-types/issue-68648-2.stderr | 21 + .../generic-associated-types/issue-68649-pass.rs | 22 + tests/ui/generic-associated-types/issue-68653.rs | 13 + .../issue-68656-unsized-values.rs | 19 + .../issue-68656-unsized-values.stderr | 23 + tests/ui/generic-associated-types/issue-70303.rs | 57 + tests/ui/generic-associated-types/issue-70304.rs | 55 + .../ui/generic-associated-types/issue-70304.stderr | 33 + tests/ui/generic-associated-types/issue-71176.rs | 18 + .../ui/generic-associated-types/issue-71176.stderr | 19 + tests/ui/generic-associated-types/issue-74684-1.rs | 23 + .../generic-associated-types/issue-74684-1.stderr | 18 + tests/ui/generic-associated-types/issue-74684-2.rs | 23 + .../generic-associated-types/issue-74684-2.stderr | 22 + tests/ui/generic-associated-types/issue-74816.rs | 21 + .../ui/generic-associated-types/issue-74816.stderr | 35 + tests/ui/generic-associated-types/issue-74824.rs | 25 + .../ui/generic-associated-types/issue-74824.stderr | 33 + tests/ui/generic-associated-types/issue-76407.rs | 25 + .../issue-76535.base.stderr | 52 + .../issue-76535.extended.stderr | 19 + tests/ui/generic-associated-types/issue-76535.rs | 43 + tests/ui/generic-associated-types/issue-76826.rs | 42 + .../issue-78113-lifetime-mismatch-dyn-trait-box.rs | 38 + ...ue-78113-lifetime-mismatch-dyn-trait-box.stderr | 87 + .../issue-78671.base.stderr | 35 + .../issue-78671.extended.stderr | 19 + tests/ui/generic-associated-types/issue-78671.rs | 17 + .../issue-79422.base.stderr | 52 + .../issue-79422.extended.stderr | 35 + tests/ui/generic-associated-types/issue-79422.rs | 50 + tests/ui/generic-associated-types/issue-79636-1.rs | 21 + .../generic-associated-types/issue-79636-1.stderr | 19 + tests/ui/generic-associated-types/issue-79636-2.rs | 15 + .../generic-associated-types/issue-79636-2.stderr | 19 + .../issue-80433-reduced.rs | 21 + tests/ui/generic-associated-types/issue-80433.rs | 32 + .../ui/generic-associated-types/issue-80433.stderr | 19 + tests/ui/generic-associated-types/issue-81487.rs | 17 + .../issue-81712-cyclic-traits.rs | 18 + .../issue-81712-cyclic-traits.stderr | 19 + tests/ui/generic-associated-types/issue-81862.rs | 10 + .../ui/generic-associated-types/issue-81862.stderr | 19 + tests/ui/generic-associated-types/issue-84931.rs | 21 + .../ui/generic-associated-types/issue-84931.stderr | 11 + tests/ui/generic-associated-types/issue-85921.rs | 17 + tests/ui/generic-associated-types/issue-86218-2.rs | 23 + tests/ui/generic-associated-types/issue-86218.rs | 24 + tests/ui/generic-associated-types/issue-86483.rs | 14 + tests/ui/generic-associated-types/issue-86787.rs | 37 + .../ui/generic-associated-types/issue-86787.stderr | 13 + tests/ui/generic-associated-types/issue-87258_a.rs | 24 + .../generic-associated-types/issue-87258_a.stderr | 10 + tests/ui/generic-associated-types/issue-87258_b.rs | 26 + .../generic-associated-types/issue-87258_b.stderr | 10 + tests/ui/generic-associated-types/issue-87429-2.rs | 18 + .../issue-87429-associated-type-default.rs | 17 + .../issue-87429-associated-type-default.stderr | 20 + .../issue-87429-specialization.rs | 24 + .../issue-87429-specialization.stderr | 30 + tests/ui/generic-associated-types/issue-87429.rs | 13 + tests/ui/generic-associated-types/issue-87748.rs | 21 + tests/ui/generic-associated-types/issue-87750.rs | 24 + tests/ui/generic-associated-types/issue-88287.rs | 39 + .../ui/generic-associated-types/issue-88287.stderr | 27 + tests/ui/generic-associated-types/issue-88360.rs | 18 + .../ui/generic-associated-types/issue-88360.stderr | 20 + tests/ui/generic-associated-types/issue-88405.rs | 14 + tests/ui/generic-associated-types/issue-88459.rs | 17 + tests/ui/generic-associated-types/issue-88595.rs | 21 + .../ui/generic-associated-types/issue-88595.stderr | 16 + tests/ui/generic-associated-types/issue-89008.rs | 37 + tests/ui/generic-associated-types/issue-89352.rs | 30 + tests/ui/generic-associated-types/issue-90014.rs | 21 + .../ui/generic-associated-types/issue-90014.stderr | 22 + tests/ui/generic-associated-types/issue-90729.rs | 36 + .../issue-91139.migrate.stderr | 8 + tests/ui/generic-associated-types/issue-91139.rs | 27 + .../ui/generic-associated-types/issue-91139.stderr | 14 + tests/ui/generic-associated-types/issue-91883.rs | 40 + .../ui/generic-associated-types/issue-91883.stderr | 27 + tests/ui/generic-associated-types/issue-92033.rs | 37 + .../ui/generic-associated-types/issue-92033.stderr | 22 + .../issue-92096.migrate.stderr | 24 + tests/ui/generic-associated-types/issue-92096.rs | 28 + .../ui/generic-associated-types/issue-92096.stderr | 8 + tests/ui/generic-associated-types/issue-92280.rs | 24 + tests/ui/generic-associated-types/issue-92954.rs | 8 + tests/ui/generic-associated-types/issue-93141.rs | 23 + tests/ui/generic-associated-types/issue-93262.rs | 19 + tests/ui/generic-associated-types/issue-93340.rs | 18 + tests/ui/generic-associated-types/issue-93341.rs | 54 + tests/ui/generic-associated-types/issue-93342.rs | 55 + tests/ui/generic-associated-types/issue-93874.rs | 33 + tests/ui/generic-associated-types/issue-95305.rs | 19 + .../ui/generic-associated-types/issue-95305.stderr | 9 + tests/ui/generic-associated-types/iterable.rs | 44 + .../method-unsatified-assoc-type-predicate.rs | 33 + .../method-unsatified-assoc-type-predicate.stderr | 24 + .../mismatched-where-clause-regions.rs | 12 + .../mismatched-where-clause-regions.stderr | 17 + .../generic-associated-types/missing-bounds.fixed | 46 + .../ui/generic-associated-types/missing-bounds.rs | 46 + .../generic-associated-types/missing-bounds.stderr | 105 + .../missing-where-clause-on-trait.rs | 11 + .../missing-where-clause-on-trait.stderr | 18 + .../missing_lifetime_args.rs | 20 + .../missing_lifetime_args.stderr | 55 + .../missing_lifetime_const.rs | 10 + .../missing_lifetime_const.stderr | 19 + .../ui/generic-associated-types/own-bound-span.rs | 17 + .../generic-associated-types/own-bound-span.stderr | 15 + .../parameter_number_and_kind.rs | 18 + .../parameter_number_and_kind.stderr | 47 + .../parameter_number_and_kind_impl.rs | 33 + .../parameter_number_and_kind_impl.stderr | 62 + .../parse/in-trait-impl.rs | 8 + .../ui/generic-associated-types/parse/in-trait.rs | 22 + .../parse/trait-path-expected-token.rs | 8 + .../parse/trait-path-expected-token.stderr | 10 + .../parse/trait-path-expressions.rs | 20 + .../parse/trait-path-expressions.stderr | 23 + .../parse/trait-path-missing-gen_arg.rs | 18 + .../parse/trait-path-missing-gen_arg.stderr | 43 + .../parse/trait-path-segments.rs | 32 + .../parse/trait-path-segments.stderr | 41 + .../trait-path-type-error-once-implemented.rs | 11 + .../trait-path-type-error-once-implemented.stderr | 33 + .../parse/trait-path-types.rs | 20 + .../parse/trait-path-types.stderr | 41 + .../ui/generic-associated-types/pointer_family.rs | 34 + .../projection-bound-cycle-generic.rs | 59 + .../projection-bound-cycle-generic.stderr | 9 + .../projection-bound-cycle.rs | 62 + .../projection-bound-cycle.stderr | 9 + .../projection-type-lifetime-mismatch.rs | 33 + .../projection-type-lifetime-mismatch.stderr | 26 + .../generic-associated-types/self-outlives-lint.rs | 224 + .../self-outlives-lint.stderr | 178 + tests/ui/generic-associated-types/shadowing.rs | 29 + tests/ui/generic-associated-types/shadowing.stderr | 36 + .../generic-associated-types/streaming_iterator.rs | 74 + .../trait-objects.base.stderr | 18 + .../trait-objects.extended.stderr | 19 + tests/ui/generic-associated-types/trait-objects.rs | 19 + .../type-param-defaults.rs | 34 + .../type-param-defaults.stderr | 20 + .../unsatified-item-lifetime-bound.rs | 25 + .../unsatified-item-lifetime-bound.stderr | 50 + .../unsatisfied-outlives-bound.rs | 19 + .../unsatisfied-outlives-bound.stderr | 27 + .../variance_constraints.rs | 22 + tests/ui/generics/autobind.rs | 12 + .../generics/auxiliary/default_type_params_xc.rs | 5 + tests/ui/generics/bad-mid-path-type-params.rs | 44 + tests/ui/generics/bad-mid-path-type-params.stderr | 73 + tests/ui/generics/generic-alias-unique.rs | 10 + tests/ui/generics/generic-arg-mismatch-recover.rs | 12 + .../generics/generic-arg-mismatch-recover.stderr | 45 + .../generic-default-type-params-cross-crate.rs | 17 + tests/ui/generics/generic-default-type-params.rs | 53 + tests/ui/generics/generic-derived-type.rs | 21 + tests/ui/generics/generic-exterior-unique.rs | 11 + tests/ui/generics/generic-extern-lifetime.rs | 15 + tests/ui/generics/generic-extern-lifetime.stderr | 42 + tests/ui/generics/generic-extern-mangle.rs | 9 + tests/ui/generics/generic-extern.rs | 7 + tests/ui/generics/generic-extern.stderr | 11 + tests/ui/generics/generic-fn-infer.rs | 10 + tests/ui/generics/generic-fn-twice.rs | 11 + tests/ui/generics/generic-fn-unique.rs | 8 + tests/ui/generics/generic-fn.rs | 28 + .../generics/generic-function-item-where-type.rs | 6 + .../generic-function-item-where-type.stderr | 12 + .../generic-impl-less-params-with-defaults.rs | 13 + .../generic-impl-less-params-with-defaults.stderr | 21 + .../generic-impl-more-params-with-defaults.rs | 15 + .../generic-impl-more-params-with-defaults.stderr | 17 + tests/ui/generics/generic-ivec-leak.rs | 5 + tests/ui/generics/generic-lifetime-trait-impl.rs | 23 + .../ui/generics/generic-lifetime-trait-impl.stderr | 12 + tests/ui/generics/generic-newtype-struct.rs | 8 + tests/ui/generics/generic-no-mangle.fixed | 159 + tests/ui/generics/generic-no-mangle.rs | 159 + tests/ui/generics/generic-no-mangle.stderr | 144 + tests/ui/generics/generic-non-trailing-defaults.rs | 10 + .../generics/generic-non-trailing-defaults.stderr | 21 + tests/ui/generics/generic-object.rs | 21 + tests/ui/generics/generic-param-attrs.rs | 38 + tests/ui/generics/generic-recursive-tag.rs | 12 + tests/ui/generics/generic-static-methods.rs | 21 + tests/ui/generics/generic-tag-corruption.rs | 10 + tests/ui/generics/generic-tag-local.rs | 8 + tests/ui/generics/generic-tag-match.rs | 13 + tests/ui/generics/generic-tag-values.rs | 20 + tests/ui/generics/generic-tag.rs | 14 + tests/ui/generics/generic-temporary.rs | 16 + tests/ui/generics/generic-tup.rs | 8 + .../generic-type-less-params-with-defaults.rs | 11 + .../generic-type-less-params-with-defaults.stderr | 19 + .../generic-type-more-params-with-defaults.rs | 11 + .../generic-type-more-params-with-defaults.stderr | 17 + .../generic-type-params-forward-mention.rs | 6 + .../generic-type-params-forward-mention.stderr | 9 + tests/ui/generics/generic-type-params-name-repr.rs | 51 + .../generics/generic-type-params-name-repr.stderr | 69 + tests/ui/generics/generic-type-synonym.rs | 15 + tests/ui/generics/generic-type.rs | 11 + tests/ui/generics/generic-unique.rs | 11 + tests/ui/generics/issue-106694.rs | 24 + tests/ui/generics/issue-106694.stderr | 93 + tests/ui/generics/issue-1112.rs | 37 + tests/ui/generics/issue-2936.rs | 31 + tests/ui/generics/issue-32498.rs | 16 + tests/ui/generics/issue-333.rs | 7 + tests/ui/generics/issue-59508-1.rs | 16 + tests/ui/generics/issue-59508-1.stderr | 8 + tests/ui/generics/issue-59508.fixed | 16 + tests/ui/generics/issue-59508.rs | 16 + tests/ui/generics/issue-59508.stderr | 8 + ...fault-type-param-can-reference-self-in-trait.rs | 20 + ...t-type-param-can-reference-self-in-trait.stderr | 16 + ...631-default-type-param-cannot-reference-self.rs | 45 + ...default-type-param-cannot-reference-self.stderr | 39 + ...5285-incorrect-explicit-lifetime-name-needed.rs | 15 + ...-incorrect-explicit-lifetime-name-needed.stderr | 57 + .../issue-80512-param-reordering-with-defaults.rs | 4 + ...sue-80512-param-reordering-with-defaults.stderr | 8 + tests/ui/generics/issue-94432-garbage-ice.rs | 10 + tests/ui/generics/issue-94923.rs | 49 + tests/ui/generics/issue-95208-ignore-qself.fixed | 11 + tests/ui/generics/issue-95208-ignore-qself.rs | 11 + tests/ui/generics/issue-95208-ignore-qself.stderr | 10 + tests/ui/generics/issue-95208.fixed | 11 + tests/ui/generics/issue-95208.rs | 11 + tests/ui/generics/issue-95208.stderr | 10 + tests/ui/generics/issue-98432.rs | 9 + tests/ui/generics/issue-98432.stderr | 14 + tests/ui/generics/lifetime-before-type-params.rs | 11 + .../ui/generics/lifetime-before-type-params.stderr | 26 + tests/ui/generics/mid-path-type-params.rs | 37 + .../ui/generics/param-in-ct-in-ty-param-default.rs | 4 + .../param-in-ct-in-ty-param-default.stderr | 11 + .../post_monomorphization_error_backtrace.rs | 33 + .../post_monomorphization_error_backtrace.stderr | 31 + .../single-colon-path-not-const-generics.rs | 13 + .../single-colon-path-not-const-generics.stderr | 11 + tests/ui/generics/type-params-in-for-each.rs | 23 + tests/ui/generics/wrong-number-of-args.rs | 358 + tests/ui/generics/wrong-number-of-args.stderr | 1013 ++ tests/ui/global-scope.rs | 13 + .../exclusive_range_pattern_syntax_collision.rs | 10 + ...exclusive_range_pattern_syntax_collision.stderr | 14 + .../exclusive_range_pattern_syntax_collision2.rs | 11 + ...xclusive_range_pattern_syntax_collision2.stderr | 21 + .../exclusive_range_pattern_syntax_collision3.rs | 11 + ...xclusive_range_pattern_syntax_collision3.stderr | 40 + ...ture-gate-half-open-range-patterns-in-slices.rs | 7 + ...-gate-half-open-range-patterns-in-slices.stderr | 12 + .../half-open-range-pats-bad-types.rs | 7 + .../half-open-range-pats-bad-types.stderr | 21 + .../half-open-range-pats-exhaustive-fail.rs | 167 + .../half-open-range-pats-exhaustive-fail.stderr | 819 ++ .../half-open-range-pats-exhaustive-pass.rs | 48 + ...en-range-pats-inclusive-dotdotdot-bad-syntax.rs | 30 + ...ange-pats-inclusive-dotdotdot-bad-syntax.stderr | 37 + .../half-open-range-pats-inclusive-no-end.rs | 24 + .../half-open-range-pats-inclusive-no-end.stderr | 59 + .../half-open-range-pats-ref-ambiguous-interp.rs | 24 + ...alf-open-range-pats-ref-ambiguous-interp.stderr | 55 + .../half-open-range-pats-semantics.rs | 159 + .../half-open-range-pats-syntactic-pass.rs | 29 + .../half-open-range-pats-thir-lower-empty.rs | 53 + .../half-open-range-pats-thir-lower-empty.stderr | 159 + tests/ui/half-open-range-patterns/pat-tuple-4.rs | 12 + tests/ui/half-open-range-patterns/pat-tuple-5.rs | 9 + .../ui/half-open-range-patterns/pat-tuple-5.stderr | 14 + .../range_pat_interactions0.rs | 31 + .../range_pat_interactions1.rs | 29 + .../range_pat_interactions1.stderr | 36 + .../range_pat_interactions2.rs | 21 + .../range_pat_interactions2.stderr | 17 + .../range_pat_interactions3.rs | 23 + .../range_pat_interactions3.stderr | 48 + .../slice_pattern_syntax_problem0.rs | 16 + .../slice_pattern_syntax_problem0.stderr | 9 + .../slice_pattern_syntax_problem1.rs | 8 + .../slice_pattern_syntax_problem1.stderr | 30 + .../slice_pattern_syntax_problem2.rs | 10 + tests/ui/hashmap/hashmap-capacity-overflow.rs | 12 + tests/ui/hashmap/hashmap-index-mut.rs | 6 + tests/ui/hashmap/hashmap-index-mut.stderr | 19 + tests/ui/hashmap/hashmap-iter-value-lifetime.rs | 10 + .../ui/hashmap/hashmap-iter-value-lifetime.stderr | 15 + tests/ui/hashmap/hashmap-lifetimes.rs | 8 + tests/ui/hashmap/hashmap-lifetimes.stderr | 13 + tests/ui/hashmap/hashmap-memory.rs | 94 + tests/ui/hello.rs | 12 + tests/ui/hello_world/main.rs | 7 + tests/ui/higher-lifetime-bounds.rs | 69 + tests/ui/higher-lifetime-bounds.stderr | 68 + tests/ui/higher-rank-trait-bounds/complex.rs | 28 + .../due-to-where-clause.rs | 13 + .../due-to-where-clause.stderr | 11 + .../hang-on-deeply-nested-dyn.rs | 16 + .../hang-on-deeply-nested-dyn.stderr | 22 + .../hrtb-binder-levels-in-object-types.rs | 29 + .../hrtb-cache-issue-54302.rs | 24 + .../hrtb-cache-issue-54302.stderr | 11 + .../hrtb-conflate-regions.rs | 31 + .../hrtb-conflate-regions.stderr | 20 + .../hrtb-debruijn-in-receiver.rs | 18 + .../hrtb-debruijn-in-receiver.stderr | 14 + .../hrtb-debruijn-object-types-in-closures.rs | 16 + .../hrtb-exists-forall-fn.rs | 18 + .../hrtb-exists-forall-fn.stderr | 12 + .../hrtb-exists-forall-trait-contravariant.rs | 36 + .../hrtb-exists-forall-trait-contravariant.stderr | 11 + .../hrtb-exists-forall-trait-covariant.rs | 37 + .../hrtb-exists-forall-trait-invariant.rs | 29 + .../hrtb-exists-forall-trait-invariant.stderr | 11 + .../hrtb-fn-like-trait-object.rs | 27 + .../higher-rank-trait-bounds/hrtb-fn-like-trait.rs | 27 + .../hrtb-higher-ranker-supertraits-transitive.rs | 50 + ...rtb-higher-ranker-supertraits-transitive.stderr | 23 + .../hrtb-higher-ranker-supertraits.rs | 48 + .../hrtb-higher-ranker-supertraits.stderr | 43 + .../hrtb-identity-fn-borrows.rs | 26 + .../hrtb-identity-fn-borrows.stderr | 14 + .../hrtb-just-for-static.rs | 35 + .../hrtb-just-for-static.stderr | 34 + .../hrtb-malformed-lifetime-generics.rs | 20 + .../hrtb-malformed-lifetime-generics.stderr | 62 + .../higher-rank-trait-bounds/hrtb-opt-in-copy.rs | 28 + tests/ui/higher-rank-trait-bounds/hrtb-parse.rs | 36 + .../hrtb-perfect-forwarding.polonius.stderr | 71 + .../hrtb-perfect-forwarding.rs | 56 + .../hrtb-perfect-forwarding.stderr | 79 + .../hrtb-precedence-of-plus-where-clause.rs | 25 + .../hrtb-precedence-of-plus.rs | 13 + .../hrtb-resolve-lifetime.rs | 14 + .../hrtb-trait-object-paren-notation.rs | 26 + .../hrtb-trait-object-passed-to-closure.rs | 25 + .../higher-rank-trait-bounds/hrtb-type-outlives.rs | 46 + .../hrtb-unboxed-closure-trait.rs | 11 + .../ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs | 7 + .../hrtb-wrong-kind.stderr | 14 + tests/ui/higher-rank-trait-bounds/issue-100689.rs | 29 + tests/ui/higher-rank-trait-bounds/issue-102899.rs | 32 + tests/ui/higher-rank-trait-bounds/issue-30786.rs | 134 + .../ui/higher-rank-trait-bounds/issue-30786.stderr | 45 + .../issue-36139-normalize-closure-sig.rs | 19 + tests/ui/higher-rank-trait-bounds/issue-42114.rs | 20 + tests/ui/higher-rank-trait-bounds/issue-43623.rs | 21 + tests/ui/higher-rank-trait-bounds/issue-46989.rs | 40 + .../ui/higher-rank-trait-bounds/issue-46989.stderr | 11 + tests/ui/higher-rank-trait-bounds/issue-57639.rs | 29 + tests/ui/higher-rank-trait-bounds/issue-58451.rs | 13 + .../ui/higher-rank-trait-bounds/issue-58451.stderr | 19 + tests/ui/higher-rank-trait-bounds/issue-59311.rs | 22 + .../ui/higher-rank-trait-bounds/issue-59311.stderr | 18 + tests/ui/higher-rank-trait-bounds/issue-60283.rs | 20 + .../issue-62203-hrtb-ice.rs | 54 + .../issue-62203-hrtb-ice.stderr | 66 + tests/ui/higher-rank-trait-bounds/issue-88446.rs | 35 + .../issue-88586-hr-self-outlives-in-trait-def.rs | 13 + tests/ui/higher-rank-trait-bounds/issue-90177.rs | 32 + tests/ui/higher-rank-trait-bounds/issue-95034.rs | 80 + tests/ui/higher-rank-trait-bounds/issue-95230.rs | 7 + .../normalize-under-binder/issue-44005.rs | 31 + .../normalize-under-binder/issue-56556.rs | 30 + .../normalize-under-binder/issue-62529-1.rs | 88 + .../normalize-under-binder/issue-62529-2.rs | 33 + .../normalize-under-binder/issue-62529-3.rs | 32 + .../normalize-under-binder/issue-62529-3.stderr | 19 + .../normalize-under-binder/issue-62529-4.rs | 39 + .../normalize-under-binder/issue-62529-5.rs | 27 + .../normalize-under-binder/issue-62529-6.rs | 77 + .../normalize-under-binder/issue-70120.rs | 31 + .../issue-71955.migrate.stderr | 79 + .../normalize-under-binder/issue-71955.rs | 51 + .../normalize-under-binder/issue-71955.stderr | 79 + .../normalize-under-binder/issue-74261.rs | 30 + .../normalize-under-binder/issue-76956.rs | 15 + .../normalize-under-binder/issue-80706.rs | 71 + .../normalize-under-binder/issue-80956.rs | 21 + .../normalize-under-binder/issue-81809.rs | 21 + .../normalize-under-binder/issue-85455.rs | 19 + .../normalize-under-binder/issue-85455.stderr | 25 + .../normalize-under-binder/issue-89118.rs | 32 + .../normalize-under-binder/issue-89118.stderr | 69 + .../normalize-under-binder/issue-89436.rs | 44 + .../normalize-under-binder/issue-90612.rs | 41 + .../normalize-under-binder/issue-90638.rs | 35 + .../normalize-under-binder/issue-90875.rs | 31 + .../normalize-under-binder/issue-90950.rs | 53 + .../normalize-under-binder/issue-90950.stderr | 21 + .../norm-before-method-resolution.rs | 23 + .../norm-before-method-resolution.stderr | 18 + ...subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 17 + .../hr-subtype/hr-subtype.bound_a_vs_free_x.stderr | 17 + .../hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr | 31 + .../hr-subtype.free_inv_x_vs_free_inv_y.stderr | 42 + .../hr-subtype/hr-subtype.free_x_vs_free_y.stderr | 19 + tests/ui/hr-subtype/hr-subtype.rs | 111 + tests/ui/hr-subtype/placeholder-pattern-fail.rs | 25 + .../ui/hr-subtype/placeholder-pattern-fail.stderr | 12 + tests/ui/hr-subtype/placeholder-pattern.rs | 18 + tests/ui/hr-subtype/return-static.rs | 13 + tests/ui/hygiene/arguments.rs | 17 + tests/ui/hygiene/arguments.stderr | 9 + tests/ui/hygiene/assoc_item_ctxt.rs | 42 + tests/ui/hygiene/assoc_item_ctxt.stderr | 32 + tests/ui/hygiene/assoc_ty_bindings.rs | 38 + tests/ui/hygiene/auxiliary/codegen-attrs.rs | 10 + tests/ui/hygiene/auxiliary/def-site-async-await.rs | 7 + tests/ui/hygiene/auxiliary/fields.rs | 73 + tests/ui/hygiene/auxiliary/intercrate.rs | 46 + tests/ui/hygiene/auxiliary/legacy_interaction.rs | 9 + tests/ui/hygiene/auxiliary/local_inner_macros.rs | 19 + tests/ui/hygiene/auxiliary/methods.rs | 160 + tests/ui/hygiene/auxiliary/my_crate.rs | 1 + tests/ui/hygiene/auxiliary/needs_hygiene.rs | 5 + tests/ui/hygiene/auxiliary/nested-dollar-crate.rs | 14 + tests/ui/hygiene/auxiliary/not-libstd.rs | 1 + tests/ui/hygiene/auxiliary/opaque-hygiene.rs | 21 + tests/ui/hygiene/auxiliary/pub_hygiene.rs | 7 + tests/ui/hygiene/auxiliary/stdlib-prelude.rs | 3 + tests/ui/hygiene/auxiliary/transparent-basic.rs | 6 + tests/ui/hygiene/auxiliary/unhygienic_example.rs | 27 + tests/ui/hygiene/auxiliary/use_by_macro.rs | 15 + tests/ui/hygiene/auxiliary/variants.rs | 36 + tests/ui/hygiene/auxiliary/xcrate.rs | 28 + tests/ui/hygiene/cross-crate-codegen-attrs.rs | 12 + tests/ui/hygiene/cross-crate-define-and-use.rs | 19 + tests/ui/hygiene/cross-crate-fields.rs | 24 + tests/ui/hygiene/cross-crate-glob-hygiene.rs | 23 + tests/ui/hygiene/cross-crate-glob-hygiene.stderr | 11 + tests/ui/hygiene/cross-crate-methods.rs | 33 + tests/ui/hygiene/cross-crate-name-collision.rs | 12 + tests/ui/hygiene/cross-crate-name-hiding-2.rs | 15 + tests/ui/hygiene/cross-crate-name-hiding-2.stderr | 9 + tests/ui/hygiene/cross-crate-name-hiding.rs | 13 + tests/ui/hygiene/cross-crate-name-hiding.stderr | 9 + tests/ui/hygiene/cross-crate-redefine.rs | 14 + tests/ui/hygiene/cross-crate-redefine.stderr | 15 + tests/ui/hygiene/cross-crate-variants.rs | 18 + tests/ui/hygiene/dollar-crate-modern.rs | 25 + tests/ui/hygiene/duplicate_lifetimes.rs | 19 + tests/ui/hygiene/duplicate_lifetimes.stderr | 31 + tests/ui/hygiene/eager-from-opaque-2.rs | 22 + tests/ui/hygiene/eager-from-opaque.rs | 20 + tests/ui/hygiene/expansion-info-reset.rs | 4 + tests/ui/hygiene/expansion-info-reset.stderr | 13 + .../ui/hygiene/extern-prelude-from-opaque-fail.rs | 28 + .../hygiene/extern-prelude-from-opaque-fail.stderr | 38 + tests/ui/hygiene/fields-definition.rs | 22 + tests/ui/hygiene/fields-definition.stderr | 16 + tests/ui/hygiene/fields-move.rs | 30 + tests/ui/hygiene/fields-move.stderr | 39 + tests/ui/hygiene/fields-numeric-borrowck.rs | 13 + tests/ui/hygiene/fields-numeric-borrowck.stderr | 14 + tests/ui/hygiene/fields.rs | 30 + tests/ui/hygiene/fields.stderr | 46 + tests/ui/hygiene/for-loop.rs | 8 + tests/ui/hygiene/for-loop.stderr | 9 + tests/ui/hygiene/format-args.rs | 12 + tests/ui/hygiene/generate-mod.rs | 49 + tests/ui/hygiene/generate-mod.stderr | 59 + tests/ui/hygiene/generic_params.rs | 104 + tests/ui/hygiene/globs.rs | 72 + tests/ui/hygiene/globs.stderr | 73 + tests/ui/hygiene/hir-res-hygiene.rs | 18 + tests/ui/hygiene/hygiene-dodging-1.rs | 14 + tests/ui/hygiene/hygiene.rs | 114 + tests/ui/hygiene/hygienic-label-1.rs | 7 + tests/ui/hygiene/hygienic-label-1.stderr | 14 + tests/ui/hygiene/hygienic-label-2.rs | 7 + tests/ui/hygiene/hygienic-label-2.stderr | 9 + tests/ui/hygiene/hygienic-label-3.rs | 9 + tests/ui/hygiene/hygienic-label-3.stderr | 14 + tests/ui/hygiene/hygienic-label-4.rs | 7 + tests/ui/hygiene/hygienic-label-4.stderr | 9 + tests/ui/hygiene/hygienic-labels-in-let.rs | 82 + tests/ui/hygiene/hygienic-labels.rs | 60 + tests/ui/hygiene/impl_items-2.rs | 26 + tests/ui/hygiene/impl_items-2.stderr | 15 + tests/ui/hygiene/impl_items.rs | 34 + tests/ui/hygiene/impl_items.stderr | 13 + tests/ui/hygiene/intercrate.rs | 12 + tests/ui/hygiene/intercrate.stderr | 10 + tests/ui/hygiene/issue-15221.rs | 16 + tests/ui/hygiene/issue-32922.rs | 29 + tests/ui/hygiene/issue-40847.rs | 17 + tests/ui/hygiene/issue-44128.rs | 17 + tests/ui/hygiene/issue-47311.rs | 17 + tests/ui/hygiene/issue-47312.rs | 21 + tests/ui/hygiene/issue-61574-const-parameters.rs | 30 + .../ui/hygiene/issue-77523-def-site-async-await.rs | 19 + tests/ui/hygiene/items.rs | 27 + tests/ui/hygiene/lambda-var-hygiene.rs | 12 + tests/ui/hygiene/legacy_interaction.rs | 42 + tests/ui/hygiene/lexical.rs | 24 + tests/ui/hygiene/local_inner_macros.rs | 19 + tests/ui/hygiene/macro-metavars-legacy.rs | 29 + tests/ui/hygiene/macro-metavars-transparent.rs | 24 + tests/ui/hygiene/missing-self-diag.rs | 23 + tests/ui/hygiene/missing-self-diag.stderr | 17 + tests/ui/hygiene/nested-dollar-crate.rs | 9 + tests/ui/hygiene/nested_macro_privacy.rs | 17 + tests/ui/hygiene/nested_macro_privacy.stderr | 9 + tests/ui/hygiene/no_implicit_prelude-2018.rs | 11 + tests/ui/hygiene/no_implicit_prelude-2018.stderr | 11 + tests/ui/hygiene/no_implicit_prelude-2021.rs | 9 + tests/ui/hygiene/no_implicit_prelude.rs | 20 + tests/ui/hygiene/no_implicit_prelude.stderr | 35 + tests/ui/hygiene/panic-location.rs | 10 + tests/ui/hygiene/panic-location.run.stderr | 2 + tests/ui/hygiene/pattern-macro.rs | 6 + tests/ui/hygiene/pattern-macro.stderr | 9 + tests/ui/hygiene/prelude-import-hygiene.rs | 29 + tests/ui/hygiene/privacy-early.rs | 17 + tests/ui/hygiene/privacy-early.stderr | 22 + tests/ui/hygiene/privacy.rs | 18 + tests/ui/hygiene/privacy.stderr | 15 + tests/ui/hygiene/rustc-macro-transparency.rs | 31 + tests/ui/hygiene/rustc-macro-transparency.stderr | 28 + tests/ui/hygiene/specialization.rs | 25 + .../ui/hygiene/stdlib-prelude-from-opaque-early.rs | 21 + .../ui/hygiene/stdlib-prelude-from-opaque-late.rs | 16 + tests/ui/hygiene/thread-local-not-in-prelude.rs | 9 + tests/ui/hygiene/trait_items-2.rs | 20 + tests/ui/hygiene/trait_items.rs | 21 + tests/ui/hygiene/trait_items.stderr | 22 + tests/ui/hygiene/traits-in-scope.rs | 53 + tests/ui/hygiene/transparent-basic.rs | 43 + tests/ui/hygiene/unpretty-debug.rs | 20 + tests/ui/hygiene/unpretty-debug.stdout | 28 + tests/ui/hygiene/wrap_unhygienic_example.rs | 34 + tests/ui/hygiene/xcrate.rs | 12 + .../mutability-mismatch-arg.fixed | 9 + .../illegal-sized-bound/mutability-mismatch-arg.rs | 9 + .../mutability-mismatch-arg.stderr | 13 + .../ui/illegal-sized-bound/mutability-mismatch.rs | 32 + .../illegal-sized-bound/mutability-mismatch.stderr | 18 + tests/ui/illegal-sized-bound/regular.rs | 32 + tests/ui/illegal-sized-bound/regular.stderr | 20 + tests/ui/illegal-ufcs-drop.fixed | 10 + tests/ui/illegal-ufcs-drop.rs | 10 + tests/ui/illegal-ufcs-drop.stderr | 12 + .../ui/impl-header-lifetime-elision/assoc-type.rs | 25 + .../impl-header-lifetime-elision/assoc-type.stderr | 15 + .../constant-used-as-arraylen.rs | 24 + tests/ui/impl-header-lifetime-elision/dyn-trait.rs | 36 + .../impl-header-lifetime-elision/dyn-trait.stderr | 16 + .../explicit-and-elided-same-header.rs | 13 + .../impl-header-lifetime-elision/inherent-impl.rs | 9 + .../ui/impl-header-lifetime-elision/path-elided.rs | 11 + .../path-elided.stderr | 15 + .../path-underscore.rs | 34 + .../impl-header-lifetime-elision/ref-underscore.rs | 30 + .../impl-header-lifetime-elision/trait-elided.rs | 8 + .../trait-elided.stderr | 15 + .../trait-underscore.rs | 35 + tests/ui/impl-inherent-non-conflict.rs | 23 + tests/ui/impl-not-adjacent-to-type.rs | 16 + tests/ui/impl-privacy-xc-1.rs | 11 + .../associated-impl-trait-type-generic-trait.rs | 30 + .../associated-impl-trait-type-trivial.rs | 20 + tests/ui/impl-trait/associated-impl-trait-type.rs | 24 + tests/ui/impl-trait/async_scope_creep.rs | 28 + tests/ui/impl-trait/auto-trait-leak-rpass.rs | 21 + tests/ui/impl-trait/auto-trait-leak.rs | 23 + tests/ui/impl-trait/auto-trait-leak.stderr | 99 + tests/ui/impl-trait/auto-trait-leak2.rs | 39 + tests/ui/impl-trait/auto-trait-leak2.stderr | 59 + tests/ui/impl-trait/auto-trait.rs | 25 + tests/ui/impl-trait/auto-trait.stderr | 12 + tests/ui/impl-trait/autoderef.rs | 19 + tests/ui/impl-trait/auxiliary/extra-item.rs | 1 + .../auxiliary/no_method_suggested_traits.rs | 36 + tests/ui/impl-trait/auxiliary/xcrate.rs | 23 + tests/ui/impl-trait/bound-normalization-fail.rs | 48 + .../ui/impl-trait/bound-normalization-fail.stderr | 55 + tests/ui/impl-trait/bound-normalization-pass.rs | 87 + tests/ui/impl-trait/bounds_regression.rs | 24 + .../impl-trait/can-return-unconstrained-closure.rs | 23 + tests/ui/impl-trait/closure-calling-parent-fn.rs | 12 + tests/ui/impl-trait/closure-in-impl-trait-arg.rs | 7 + tests/ui/impl-trait/closure-in-impl-trait.rs | 14 + tests/ui/impl-trait/cross-return-site-inference.rs | 48 + .../impl-trait/cross-return-site-inference.stderr | 36 + .../impl-trait/deduce-signature-from-supertrait.rs | 15 + tests/ui/impl-trait/deprecated_annotation.rs | 19 + .../diagnostics/fully-qualified-path-impl-trait.rs | 15 + .../fully-qualified-path-impl-trait.stderr | 9 + tests/ui/impl-trait/divergence.rs | 13 + tests/ui/impl-trait/does-not-live-long-enough.rs | 11 + .../ui/impl-trait/does-not-live-long-enough.stderr | 21 + .../dyn-trait-elided-two-inputs-assoc.rs | 16 + .../dyn-trait-elided-two-inputs-param.rs | 11 + .../dyn-trait-elided-two-inputs-ref-assoc.rs | 27 + .../dyn-trait-elided-two-inputs-ref-param.rs | 23 + .../dyn-trait-return-should-be-impl-trait.rs | 74 + .../dyn-trait-return-should-be-impl-trait.stderr | 303 + tests/ui/impl-trait/equal-hidden-lifetimes.rs | 49 + tests/ui/impl-trait/equal-hidden-lifetimes.stderr | 10 + tests/ui/impl-trait/equality-rpass.rs | 48 + tests/ui/impl-trait/equality-rpass.stderr | 12 + tests/ui/impl-trait/equality.rs | 43 + tests/ui/impl-trait/equality.stderr | 41 + tests/ui/impl-trait/equality2.rs | 44 + tests/ui/impl-trait/equality2.stderr | 75 + tests/ui/impl-trait/example-calendar.rs | 840 ++ tests/ui/impl-trait/example-st.rs | 30 + .../const-args.rs | 21 + .../explicit-generic-args-for-impl.rs | 5 + .../explicit-generic-args-for-impl.stderr | 18 + .../explicit-generic-args.rs | 7 + .../issue-87718.rs | 7 + .../not-enough-args.rs | 6 + .../not-enough-args.stderr | 21 + tests/ui/impl-trait/extra-item.rs | 10 + tests/ui/impl-trait/extra-item.stderr | 9 + tests/ui/impl-trait/fallback.rs | 9 + tests/ui/impl-trait/fallback_inference.rs | 7 + tests/ui/impl-trait/fallback_inference.stderr | 14 + tests/ui/impl-trait/feature-self-return-type.rs | 102 + .../ui/impl-trait/feature-self-return-type.stderr | 39 + ...th-implicit-hrtb-without-dyn.edition2015.stderr | 9 + ...th-implicit-hrtb-without-dyn.edition2021.stderr | 14 + .../generic-with-implicit-hrtb-without-dyn.rs | 12 + tests/ui/impl-trait/hidden-lifetimes.rs | 63 + tests/ui/impl-trait/hidden-lifetimes.stderr | 29 + tests/ui/impl-trait/hidden-type-is-opaque-2.rs | 45 + tests/ui/impl-trait/hidden-type-is-opaque-2.stderr | 15 + tests/ui/impl-trait/hidden-type-is-opaque.rs | 42 + tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs | 8 + tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr | 11 + tests/ui/impl-trait/impl-fn-hrtb-bounds.rs | 24 + tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr | 51 + tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs | 15 + .../impl-trait/impl-fn-parsing-ambiguities.stderr | 26 + .../ui/impl-trait/impl-fn-predefined-lifetimes.rs | 15 + .../impl-trait/impl-fn-predefined-lifetimes.stderr | 21 + tests/ui/impl-trait/impl-generic-mismatch-ab.rs | 12 + .../ui/impl-trait/impl-generic-mismatch-ab.stderr | 23 + tests/ui/impl-trait/impl-generic-mismatch.rs | 41 + tests/ui/impl-trait/impl-generic-mismatch.stderr | 55 + tests/ui/impl-trait/impl-trait-in-macro.rs | 20 + tests/ui/impl-trait/impl-trait-in-macro.stderr | 22 + tests/ui/impl-trait/impl-trait-plus-priority.rs | 49 + .../ui/impl-trait/impl-trait-plus-priority.stderr | 69 + tests/ui/impl-trait/impl_fn_associativity.rs | 26 + tests/ui/impl-trait/impl_trait_projections.rs | 39 + tests/ui/impl-trait/impl_trait_projections.stderr | 33 + tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs | 11 + .../in-trait/box-coerce-span-in-default.rs | 49 + .../in-trait/box-coerce-span-in-default.stderr | 11 + tests/ui/impl-trait/in-trait/deep-match-works.rs | 16 + tests/ui/impl-trait/in-trait/deep-match.rs | 15 + tests/ui/impl-trait/in-trait/deep-match.stderr | 15 + .../impl-trait/in-trait/default-body-type-err-2.rs | 13 + .../in-trait/default-body-type-err-2.stderr | 11 + .../impl-trait/in-trait/default-body-type-err.rs | 13 + .../in-trait/default-body-type-err.stderr | 12 + .../impl-trait/in-trait/default-body-with-rpit.rs | 21 + tests/ui/impl-trait/in-trait/default-body.rs | 21 + tests/ui/impl-trait/in-trait/doesnt-satisfy.rs | 13 + tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr | 17 + tests/ui/impl-trait/in-trait/early.rs | 23 + tests/ui/impl-trait/in-trait/encode.rs | 9 + tests/ui/impl-trait/in-trait/foreign.rs | 9 + tests/ui/impl-trait/in-trait/generics-mismatch.rs | 17 + .../impl-trait/in-trait/generics-mismatch.stderr | 12 + tests/ui/impl-trait/in-trait/issue-102140.rs | 30 + tests/ui/impl-trait/in-trait/issue-102140.stderr | 33 + tests/ui/impl-trait/in-trait/issue-102301.rs | 18 + tests/ui/impl-trait/in-trait/issue-102571.rs | 24 + tests/ui/impl-trait/in-trait/issue-102571.stderr | 14 + .../in-trait/method-signature-matches.rs | 51 + .../in-trait/method-signature-matches.stderr | 84 + tests/ui/impl-trait/in-trait/nested-rpitit.rs | 32 + tests/ui/impl-trait/in-trait/object-safety.rs | 22 + tests/ui/impl-trait/in-trait/object-safety.stderr | 50 + .../in-trait/opaque-in-impl-is-opaque.rs | 19 + .../in-trait/opaque-in-impl-is-opaque.stderr | 17 + tests/ui/impl-trait/in-trait/opaque-in-impl.rs | 48 + tests/ui/impl-trait/in-trait/reveal.rs | 18 + tests/ui/impl-trait/in-trait/signature-mismatch.rs | 21 + .../impl-trait/in-trait/signature-mismatch.stderr | 16 + .../impl-trait/in-trait/specialization-broken.rs | 26 + .../in-trait/specialization-broken.stderr | 23 + .../in-trait/specialization-substs-remap.rs | 24 + tests/ui/impl-trait/in-trait/success.rs | 40 + .../in-trait/trait-more-generics-than-impl.rs | 17 + .../in-trait/trait-more-generics-than-impl.stderr | 12 + tests/ui/impl-trait/in-trait/wf-bounds.rs | 16 + tests/ui/impl-trait/in-trait/wf-bounds.stderr | 30 + tests/ui/impl-trait/in-trait/where-clause.rs | 24 + tests/ui/impl-trait/issue-100075-2.rs | 8 + tests/ui/impl-trait/issue-100075-2.stderr | 24 + tests/ui/impl-trait/issue-100075.rs | 21 + tests/ui/impl-trait/issue-100075.stderr | 12 + tests/ui/impl-trait/issue-100187.rs | 12 + tests/ui/impl-trait/issue-102605.rs | 15 + tests/ui/impl-trait/issue-102605.stderr | 41 + tests/ui/impl-trait/issue-103181-1.rs | 85 + tests/ui/impl-trait/issue-103181-1.stderr | 12 + tests/ui/impl-trait/issue-103181-2.rs | 29 + tests/ui/impl-trait/issue-103181-2.stderr | 9 + tests/ui/impl-trait/issue-103599.rs | 10 + tests/ui/impl-trait/issue-103599.stderr | 14 + tests/ui/impl-trait/issue-35668.rs | 12 + tests/ui/impl-trait/issue-35668.stderr | 16 + tests/ui/impl-trait/issue-46959.rs | 9 + tests/ui/impl-trait/issue-49556.rs | 13 + tests/ui/impl-trait/issue-49579.rs | 14 + tests/ui/impl-trait/issue-49685.rs | 13 + tests/ui/impl-trait/issue-51185.rs | 8 + tests/ui/impl-trait/issue-54966.rs | 6 + tests/ui/impl-trait/issue-54966.stderr | 9 + tests/ui/impl-trait/issue-55872-1.rs | 20 + tests/ui/impl-trait/issue-55872-1.stderr | 37 + tests/ui/impl-trait/issue-55872-2.rs | 19 + tests/ui/impl-trait/issue-55872-2.stderr | 8 + tests/ui/impl-trait/issue-55872-3.rs | 20 + tests/ui/impl-trait/issue-55872-3.stderr | 9 + tests/ui/impl-trait/issue-55872.rs | 18 + tests/ui/impl-trait/issue-55872.stderr | 8 + tests/ui/impl-trait/issue-56445.rs | 25 + tests/ui/impl-trait/issue-68532.rs | 13 + tests/ui/impl-trait/issue-72911.rs | 21 + tests/ui/impl-trait/issue-72911.stderr | 15 + tests/ui/impl-trait/issue-86465.rs | 14 + tests/ui/impl-trait/issue-86465.stderr | 11 + tests/ui/impl-trait/issue-87450.rs | 16 + tests/ui/impl-trait/issue-87450.stderr | 27 + tests/ui/impl-trait/issue-99073-2.rs | 17 + tests/ui/impl-trait/issue-99073-2.stderr | 14 + tests/ui/impl-trait/issue-99073.rs | 8 + tests/ui/impl-trait/issue-99073.stderr | 14 + tests/ui/impl-trait/issue-99642-2.rs | 8 + tests/ui/impl-trait/issue-99642.rs | 7 + tests/ui/impl-trait/issue-99914.rs | 13 + tests/ui/impl-trait/issue-99914.stderr | 21 + .../issues/infinite-impl-trait-issue-38064.rs | 25 + .../issues/infinite-impl-trait-issue-38064.stderr | 27 + tests/ui/impl-trait/issues/issue-104815.rs | 66 + tests/ui/impl-trait/issues/issue-105826.rs | 39 + .../issue-21659-show-relevant-trait-impls-3.rs | 22 + .../issue-21659-show-relevant-trait-impls-3.stderr | 19 + tests/ui/impl-trait/issues/issue-42479.rs | 17 + tests/ui/impl-trait/issues/issue-49376.rs | 23 + tests/ui/impl-trait/issues/issue-52128.rs | 25 + tests/ui/impl-trait/issues/issue-53457.rs | 14 + tests/ui/impl-trait/issues/issue-54600.rs | 7 + tests/ui/impl-trait/issues/issue-54600.stderr | 9 + tests/ui/impl-trait/issues/issue-54840.rs | 7 + tests/ui/impl-trait/issues/issue-54840.stderr | 9 + tests/ui/impl-trait/issues/issue-54895.rs | 22 + tests/ui/impl-trait/issues/issue-54895.stderr | 14 + .../issues/issue-55608-captures-empty-region.rs | 22 + .../issues/issue-57464-unexpected-regions.rs | 29 + ...57979-deeply-nested-impl-trait-in-assoc-proj.rs | 17 + ...9-deeply-nested-impl-trait-in-assoc-proj.stderr | 12 + .../issues/issue-57979-impl-trait-in-path.rs | 12 + .../issues/issue-57979-impl-trait-in-path.stderr | 9 + .../issue-57979-nested-impl-trait-in-assoc-proj.rs | 12 + ...ue-57979-nested-impl-trait-in-assoc-proj.stderr | 12 + tests/ui/impl-trait/issues/issue-58504.rs | 12 + tests/ui/impl-trait/issues/issue-58504.stderr | 9 + tests/ui/impl-trait/issues/issue-58956.rs | 14 + tests/ui/impl-trait/issues/issue-58956.stderr | 15 + tests/ui/impl-trait/issues/issue-62742.rs | 32 + tests/ui/impl-trait/issues/issue-62742.stderr | 55 + tests/ui/impl-trait/issues/issue-65581.rs | 34 + tests/ui/impl-trait/issues/issue-67830.rs | 26 + tests/ui/impl-trait/issues/issue-67830.stderr | 14 + tests/ui/impl-trait/issues/issue-70877.rs | 36 + tests/ui/impl-trait/issues/issue-70877.stderr | 19 + tests/ui/impl-trait/issues/issue-70971.rs | 4 + tests/ui/impl-trait/issues/issue-70971.stderr | 9 + tests/ui/impl-trait/issues/issue-74282.rs | 11 + tests/ui/impl-trait/issues/issue-74282.stderr | 40 + tests/ui/impl-trait/issues/issue-77987.rs | 21 + tests/ui/impl-trait/issues/issue-78722.rs | 20 + tests/ui/impl-trait/issues/issue-78722.stderr | 28 + tests/ui/impl-trait/issues/issue-79099.rs | 10 + tests/ui/impl-trait/issues/issue-79099.stderr | 20 + tests/ui/impl-trait/issues/issue-82139.rs | 19 + tests/ui/impl-trait/issues/issue-82139.stderr | 9 + tests/ui/impl-trait/issues/issue-83919.rs | 32 + tests/ui/impl-trait/issues/issue-83919.stderr | 12 + .../issue-83929-impl-trait-in-generic-default.rs | 12 + ...ssue-83929-impl-trait-in-generic-default.stderr | 15 + tests/ui/impl-trait/issues/issue-84073.rs | 33 + tests/ui/impl-trait/issues/issue-84073.stderr | 14 + tests/ui/impl-trait/issues/issue-84919.rs | 9 + tests/ui/impl-trait/issues/issue-84919.stderr | 9 + tests/ui/impl-trait/issues/issue-86201.rs | 13 + tests/ui/impl-trait/issues/issue-86642.rs | 8 + tests/ui/impl-trait/issues/issue-86642.stderr | 9 + tests/ui/impl-trait/issues/issue-86719.rs | 12 + tests/ui/impl-trait/issues/issue-86719.stderr | 29 + tests/ui/impl-trait/issues/issue-86800.rs | 55 + tests/ui/impl-trait/issues/issue-86800.stderr | 26 + tests/ui/impl-trait/issues/issue-87295.rs | 18 + tests/ui/impl-trait/issues/issue-87295.stderr | 9 + tests/ui/impl-trait/issues/issue-87340.rs | 14 + tests/ui/impl-trait/issues/issue-87340.stderr | 9 + tests/ui/impl-trait/issues/issue-88236-2.rs | 28 + tests/ui/impl-trait/issues/issue-88236-2.stderr | 38 + tests/ui/impl-trait/issues/issue-88236.rs | 18 + tests/ui/impl-trait/issues/issue-88236.stderr | 14 + tests/ui/impl-trait/issues/issue-89312.rs | 24 + tests/ui/impl-trait/issues/issue-92305.rs | 14 + tests/ui/impl-trait/issues/issue-92305.stderr | 14 + tests/ui/impl-trait/issues/issue-93788.rs | 27 + .../issues/issue-99348-impl-compatibility.rs | 26 + .../issues/issue-99348-impl-compatibility.stderr | 25 + tests/ui/impl-trait/lifetimes.rs | 123 + tests/ui/impl-trait/lifetimes2.rs | 10 + .../impl-trait/method-suggestion-no-duplication.rs | 9 + .../method-suggestion-no-duplication.stderr | 16 + tests/ui/impl-trait/multiple-lifetimes.rs | 12 + .../multiple-lifetimes/error-handling-2.rs | 26 + .../multiple-lifetimes/error-handling-2.stderr | 12 + .../error-handling.polonius.stderr | 15 + .../multiple-lifetimes/error-handling.rs | 26 + .../multiple-lifetimes/error-handling.stderr | 15 + .../multiple-lifetimes/inverse-bounds.rs | 50 + .../ordinary-bounds-pick-original-elided.rs | 25 + ...y-bounds-pick-original-type-alias-impl-trait.rs | 28 + .../ordinary-bounds-pick-original.rs | 25 + .../ordinary-bounds-pick-other.rs | 42 + .../ordinary-bounds-unrelated.rs | 36 + .../ordinary-bounds-unrelated.stderr | 17 + .../multiple-lifetimes/ordinary-bounds-unsuited.rs | 39 + .../ordinary-bounds-unsuited.stderr | 17 + .../must_outlive_least_region_or_bound.rs | 47 + .../must_outlive_least_region_or_bound.stderr | 126 + tests/ui/impl-trait/needs_least_region_or_bound.rs | 21 + tests/ui/impl-trait/negative-reasoning.rs | 23 + tests/ui/impl-trait/negative-reasoning.stderr | 14 + tests/ui/impl-trait/nested-return-type.rs | 16 + tests/ui/impl-trait/nested-return-type2-tait.rs | 34 + .../ui/impl-trait/nested-return-type2-tait.stderr | 17 + tests/ui/impl-trait/nested-return-type2-tait2.rs | 32 + .../ui/impl-trait/nested-return-type2-tait2.stderr | 18 + tests/ui/impl-trait/nested-return-type2-tait3.rs | 31 + .../ui/impl-trait/nested-return-type2-tait3.stderr | 18 + tests/ui/impl-trait/nested-return-type2.rs | 31 + tests/ui/impl-trait/nested-return-type2.stderr | 17 + tests/ui/impl-trait/nested-return-type3-tait.rs | 25 + .../ui/impl-trait/nested-return-type3-tait.stderr | 17 + tests/ui/impl-trait/nested-return-type3-tait2.rs | 26 + .../ui/impl-trait/nested-return-type3-tait2.stderr | 17 + tests/ui/impl-trait/nested-return-type3-tait3.rs | 25 + .../ui/impl-trait/nested-return-type3-tait3.stderr | 17 + tests/ui/impl-trait/nested-return-type3.rs | 21 + tests/ui/impl-trait/nested-return-type3.stderr | 17 + tests/ui/impl-trait/nested-return-type4.rs | 8 + tests/ui/impl-trait/nested-return-type4.stderr | 20 + tests/ui/impl-trait/nested-rpit-hrtb.rs | 64 + tests/ui/impl-trait/nested-rpit-hrtb.stderr | 82 + .../nested-rpit-with-anonymous-lifetimes.rs | 23 + tests/ui/impl-trait/nested_impl_trait.rs | 32 + tests/ui/impl-trait/nested_impl_trait.stderr | 64 + tests/ui/impl-trait/nesting.rs | 15 + tests/ui/impl-trait/no-method-suggested-traits.rs | 77 + .../impl-trait/no-method-suggested-traits.stderr | 284 + tests/ui/impl-trait/no-trait.rs | 3 + tests/ui/impl-trait/no-trait.stderr | 8 + tests/ui/impl-trait/normalize-tait-in-const.rs | 39 + tests/ui/impl-trait/normalize-tait-in-const.stderr | 8 + ...ct-unsafe-trait-in-return-position-dyn-trait.rs | 35 + ...nsafe-trait-in-return-position-dyn-trait.stderr | 47 + ...t-unsafe-trait-in-return-position-impl-trait.rs | 46 + ...safe-trait-in-return-position-impl-trait.stderr | 21 + ...point-to-type-err-cause-on-impl-trait-return.rs | 101 + ...t-to-type-err-cause-on-impl-trait-return.stderr | 278 + tests/ui/impl-trait/printing-binder.rs | 14 + tests/ui/impl-trait/printing-binder.stderr | 31 + tests/ui/impl-trait/private_unused.rs | 13 + .../projection-mismatch-in-impl-where-clause.rs | 20 + ...projection-mismatch-in-impl-where-clause.stderr | 20 + tests/ui/impl-trait/projection.rs | 29 + tests/ui/impl-trait/question_mark.rs | 30 + tests/ui/impl-trait/recursive-generator.rs | 23 + tests/ui/impl-trait/recursive-generator.stderr | 19 + .../impl-trait/recursive-impl-trait-type-direct.rs | 9 + .../recursive-impl-trait-type-indirect.rs | 96 + .../recursive-impl-trait-type-indirect.stderr | 152 + ...ursive-impl-trait-type-through-non-recursive.rs | 25 + ...ve-impl-trait-type-through-non-recursive.stderr | 47 + ...pe-alias-impl-trait-declaration-too-subtle-2.rs | 18 + ...lias-impl-trait-declaration-too-subtle-2.stderr | 15 + ...type-alias-impl-trait-declaration-too-subtle.rs | 31 + ...-alias-impl-trait-declaration-too-subtle.stderr | 49 + .../recursive-type-alias-impl-trait-declaration.rs | 19 + ...egion-escape-via-bound-contravariant-closure.rs | 18 + .../region-escape-via-bound-contravariant.rs | 22 + tests/ui/impl-trait/region-escape-via-bound.rs | 21 + tests/ui/impl-trait/region-escape-via-bound.stderr | 17 + .../return-position-impl-trait-minimal.rs | 5 + .../ui/impl-trait/rpit-assoc-pair-with-lifetime.rs | 7 + tests/ui/impl-trait/rpit-not-sized.rs | 6 + tests/ui/impl-trait/rpit-not-sized.stderr | 12 + .../impl-trait/static-return-lifetime-infered.rs | 16 + .../static-return-lifetime-infered.stderr | 29 + .../ui/impl-trait/suggest-calling-rpit-closure.rs | 12 + .../impl-trait/suggest-calling-rpit-closure.stderr | 21 + tests/ui/impl-trait/trait_resolution.rs | 30 + tests/ui/impl-trait/trait_type.rs | 24 + tests/ui/impl-trait/trait_type.stderr | 40 + .../ui/impl-trait/two_tait_defining_each_other.rs | 19 + .../impl-trait/two_tait_defining_each_other.stderr | 19 + .../ui/impl-trait/two_tait_defining_each_other2.rs | 16 + .../two_tait_defining_each_other2.stderr | 27 + .../ui/impl-trait/two_tait_defining_each_other3.rs | 19 + .../two_tait_defining_each_other3.stderr | 19 + tests/ui/impl-trait/type-alias-generic-param.rs | 23 + .../impl-trait/type-alias-impl-trait-in-fn-body.rs | 12 + .../type-arg-mismatch-due-to-impl-trait.rs | 16 + .../type-arg-mismatch-due-to-impl-trait.stderr | 15 + tests/ui/impl-trait/type_parameters_captured.rs | 12 + .../ui/impl-trait/type_parameters_captured.stderr | 14 + tests/ui/impl-trait/unactionable_diagnostic.fixed | 25 + tests/ui/impl-trait/unactionable_diagnostic.rs | 25 + tests/ui/impl-trait/unactionable_diagnostic.stderr | 14 + tests/ui/impl-trait/universal-mismatched-type.rs | 7 + .../ui/impl-trait/universal-mismatched-type.stderr | 16 + tests/ui/impl-trait/universal-two-impl-traits.rs | 16 + .../ui/impl-trait/universal-two-impl-traits.stderr | 20 + tests/ui/impl-trait/universal_hrtb_anon.rs | 10 + tests/ui/impl-trait/universal_hrtb_named.rs | 10 + .../impl-trait/universal_in_adt_in_parameters.rs | 22 + .../universal_in_impl_trait_in_parameters.rs | 30 + .../universal_in_trait_defn_parameters.rs | 18 + tests/ui/impl-trait/universal_multiple_bounds.rs | 13 + tests/ui/impl-trait/universal_wrong_bounds.rs | 13 + tests/ui/impl-trait/universal_wrong_bounds.stderr | 25 + tests/ui/impl-trait/universal_wrong_hrtb.rs | 8 + tests/ui/impl-trait/universal_wrong_hrtb.stderr | 14 + tests/ui/impl-trait/unsafety-checking-cycle.rs | 32 + tests/ui/impl-trait/wf-eval-order.rs | 39 + tests/ui/impl-trait/where-allowed-2.rs | 6 + tests/ui/impl-trait/where-allowed-2.stderr | 9 + tests/ui/impl-trait/where-allowed.rs | 250 + tests/ui/impl-trait/where-allowed.stderr | 316 + tests/ui/impl-trait/xcrate.rs | 11 + tests/ui/impl-trait/xcrate_simple.rs | 9 + tests/ui/impl-unused-rps-in-assoc-type.rs | 18 + tests/ui/impl-unused-rps-in-assoc-type.stderr | 9 + tests/ui/impl-unused-tps-inherent.rs | 25 + tests/ui/impl-unused-tps-inherent.stderr | 15 + tests/ui/impl-unused-tps.rs | 62 + tests/ui/impl-unused-tps.stderr | 33 + tests/ui/implicit-method-bind.rs | 3 + tests/ui/implicit-method-bind.stderr | 14 + .../assoc-ty-wf-used-to-get-assoc-ty.rs | 27 + .../assoc-ty-wf-used-to-get-assoc-ty.stderr | 15 + .../hrlt-implied-trait-bounds-guard.rs | 61 + .../hrlt-implied-trait-bounds-guard.stderr | 30 + .../hrlt-implied-trait-bounds-roundtrip.rs | 35 + .../impl-header-unnormalized-types.rs | 28 + .../impl-header-unnormalized-types.stderr | 20 + ...pl-implied-bounds-compatibility-unnormalized.rs | 22 + ...mplied-bounds-compatibility-unnormalized.stderr | 31 + .../impl-implied-bounds-compatibility.rs | 21 + .../impl-implied-bounds-compatibility.stderr | 31 + tests/ui/implied-bounds/issue-100690.rs | 45 + tests/ui/implied-bounds/issue-100690.stderr | 22 + tests/ui/implied-bounds/issue-101951.rs | 50 + .../imports/absolute-paths-in-nested-use-groups.rs | 11 + .../absolute-paths-in-nested-use-groups.stderr | 21 + tests/ui/imports/auxiliary/gensymed.rs | 3 + tests/ui/imports/auxiliary/glob-conflict.rs | 13 + tests/ui/imports/auxiliary/import_crate_var.rs | 7 + tests/ui/imports/auxiliary/issue-36881-aux.rs | 1 + tests/ui/imports/auxiliary/issue-52891.rs | 33 + tests/ui/imports/auxiliary/issue-55811.rs | 5 + tests/ui/imports/auxiliary/issue-56125.rs | 11 + tests/ui/imports/auxiliary/issue-59764.rs | 18 + .../auxiliary/overlapping_pub_trait_source.rs | 13 + tests/ui/imports/auxiliary/two_macros.rs | 5 + .../imports/auxiliary/unnamed_pub_trait_source.rs | 13 + tests/ui/imports/bad-import-in-nested.rs | 27 + tests/ui/imports/bad-import-in-nested.stderr | 30 + tests/ui/imports/bad-import-with-rename.rs | 16 + tests/ui/imports/bad-import-with-rename.stderr | 25 + tests/ui/imports/double-import.rs | 15 + tests/ui/imports/double-import.stderr | 17 + tests/ui/imports/duplicate.rs | 51 + tests/ui/imports/duplicate.stderr | 74 + tests/ui/imports/export-glob-imports-target.rs | 22 + tests/ui/imports/export-multi.rs | 12 + .../extern-crate-self/extern-crate-self-fail.rs | 6 + .../extern-crate-self-fail.stderr | 19 + .../extern-crate-self-macro-alias.rs | 16 + .../extern-crate-self-macro-item.rs | 12 + .../extern-crate-self-macro-self.rs | 16 + .../extern-crate-self/extern-crate-self-pass.rs | 13 + tests/ui/imports/extern-crate-used.rs | 32 + tests/ui/imports/extern-crate-used.stderr | 14 + ...xtern-prelude-extern-crate-absolute-expanded.rs | 16 + .../ui/imports/extern-prelude-extern-crate-cfg.rs | 16 + .../ui/imports/extern-prelude-extern-crate-fail.rs | 22 + .../extern-prelude-extern-crate-fail.stderr | 20 + .../ui/imports/extern-prelude-extern-crate-pass.rs | 12 + ...rn-prelude-extern-crate-restricted-shadowing.rs | 26 + ...relude-extern-crate-restricted-shadowing.stderr | 33 + .../extern-prelude-extern-crate-shadowing.rs | 12 + tests/ui/imports/gensymed.rs | 9 + tests/ui/imports/glob-conflict-cross-crate.rs | 8 + tests/ui/imports/glob-conflict-cross-crate.stderr | 15 + tests/ui/imports/glob-cycles.rs | 18 + tests/ui/imports/glob-resolve1.rs | 39 + tests/ui/imports/glob-resolve1.stderr | 114 + tests/ui/imports/glob-shadowing.rs | 34 + tests/ui/imports/glob-shadowing.stderr | 54 + tests/ui/imports/glob-use-std.rs | 11 + tests/ui/imports/import-crate-var.rs | 8 + tests/ui/imports/import-crate-var.stderr | 10 + .../auxiliary/crate_with_invalid_spans.rs | 20 + .../auxiliary/crate_with_invalid_spans_macros.rs | 7 + .../import-crate-with-invalid-spans/main.rs | 13 + tests/ui/imports/import-from-missing.rs | 12 + tests/ui/imports/import-from-missing.stderr | 9 + tests/ui/imports/import-from.rs | 11 + tests/ui/imports/import-glob-0-rpass.rs | 29 + tests/ui/imports/import-glob-0.rs | 16 + tests/ui/imports/import-glob-0.stderr | 9 + tests/ui/imports/import-glob-1.rs | 27 + tests/ui/imports/import-glob-circular.rs | 19 + tests/ui/imports/import-glob-circular.stderr | 9 + tests/ui/imports/import-glob-crate.rs | 19 + tests/ui/imports/import-in-block.rs | 13 + tests/ui/imports/import-loop-2.rs | 13 + tests/ui/imports/import-loop-2.stderr | 9 + tests/ui/imports/import-loop.rs | 9 + tests/ui/imports/import-loop.stderr | 9 + tests/ui/imports/import-prefix-macro-1.rs | 16 + tests/ui/imports/import-prefix-macro-1.stderr | 13 + tests/ui/imports/import-prefix-macro-2.rs | 16 + tests/ui/imports/import-prefix-macro-2.stderr | 13 + tests/ui/imports/import-prefix-macro.rs | 27 + tests/ui/imports/import-rename.rs | 13 + tests/ui/imports/import-rpass.rs | 12 + tests/ui/imports/import-trailing-comma.rs | 13 + tests/ui/imports/import-trait-method.rs | 7 + tests/ui/imports/import-trait-method.stderr | 9 + tests/ui/imports/import.rs | 17 + tests/ui/imports/import.stderr | 31 + tests/ui/imports/import2-rpass.rs | 9 + tests/ui/imports/import2.rs | 10 + tests/ui/imports/import2.stderr | 9 + tests/ui/imports/import3-rpass.rs | 13 + tests/ui/imports/import3.rs | 4 + tests/ui/imports/import3.stderr | 11 + tests/ui/imports/import4-rpass.rs | 9 + tests/ui/imports/import4.rs | 7 + tests/ui/imports/import4.stderr | 9 + tests/ui/imports/import5.rs | 10 + tests/ui/imports/import6.rs | 15 + tests/ui/imports/import7.rs | 18 + tests/ui/imports/import8.rs | 10 + tests/ui/imports/imports.rs | 66 + tests/ui/imports/inaccessible_type_aliases.rs | 14 + tests/ui/imports/inaccessible_type_aliases.stderr | 30 + tests/ui/imports/issue-13404.rs | 10 + tests/ui/imports/issue-13404.stderr | 9 + tests/ui/imports/issue-1697.rs | 6 + tests/ui/imports/issue-1697.stderr | 11 + tests/ui/imports/issue-18083.rs | 25 + tests/ui/imports/issue-19498.rs | 13 + tests/ui/imports/issue-19498.stderr | 47 + tests/ui/imports/issue-24081.rs | 18 + tests/ui/imports/issue-24081.stderr | 78 + tests/ui/imports/issue-24883.rs | 17 + tests/ui/imports/issue-25396.rs | 29 + tests/ui/imports/issue-25396.stderr | 59 + tests/ui/imports/issue-26873-multifile/A/B.rs | 4 + tests/ui/imports/issue-26873-multifile/A/C.rs | 6 + tests/ui/imports/issue-26873-multifile/A/mod.rs | 5 + .../issue-26873-multifile/compiletest-ignore-dir | 0 .../issue-26873-multifile/issue-26873-multifile.rs | 11 + .../issue-26873-multifile/issue-26873-onefile.rs | 25 + tests/ui/imports/issue-26873-multifile/mod.rs | 4 + tests/ui/imports/issue-26886.rs | 8 + tests/ui/imports/issue-26886.stderr | 24 + tests/ui/imports/issue-26930.rs | 8 + tests/ui/imports/issue-28134.rs | 5 + tests/ui/imports/issue-28134.stderr | 21 + tests/ui/imports/issue-28388-1.rs | 5 + tests/ui/imports/issue-28388-1.stderr | 9 + tests/ui/imports/issue-28388-2.rs | 10 + tests/ui/imports/issue-28388-2.stderr | 15 + tests/ui/imports/issue-2937.rs | 6 + tests/ui/imports/issue-2937.stderr | 9 + tests/ui/imports/issue-30560.rs | 9 + tests/ui/imports/issue-30560.stderr | 21 + tests/ui/imports/issue-31212.rs | 10 + tests/ui/imports/issue-31212.stderr | 16 + tests/ui/imports/issue-32119.rs | 17 + tests/ui/imports/issue-32222.rs | 22 + .../issue-32354-suggest-import-rename.fixed | 16 + .../imports/issue-32354-suggest-import-rename.rs | 16 + .../issue-32354-suggest-import-rename.stderr | 17 + tests/ui/imports/issue-32833.rs | 7 + tests/ui/imports/issue-32833.stderr | 9 + tests/ui/imports/issue-33464.rs | 10 + tests/ui/imports/issue-33464.stderr | 27 + tests/ui/imports/issue-36881.rs | 6 + tests/ui/imports/issue-36881.stderr | 11 + tests/ui/imports/issue-37887.rs | 4 + tests/ui/imports/issue-37887.stderr | 21 + tests/ui/imports/issue-38293.rs | 16 + tests/ui/imports/issue-38293.stderr | 21 + tests/ui/imports/issue-4366-2.rs | 26 + tests/ui/imports/issue-4366-2.stderr | 27 + tests/ui/imports/issue-4366.rs | 26 + tests/ui/imports/issue-4366.stderr | 14 + ...extern-crate-rename-suggestion-formatting.fixed | 5 + ...ad-extern-crate-rename-suggestion-formatting.rs | 5 + ...xtern-crate-rename-suggestion-formatting.stderr | 15 + .../imports/issue-45829/auxiliary/issue-45829-a.rs | 1 + .../imports/issue-45829/auxiliary/issue-45829-b.rs | 1 + tests/ui/imports/issue-45829/import-self.rs | 19 + tests/ui/imports/issue-45829/import-self.stderr | 70 + tests/ui/imports/issue-45829/import-twice.rs | 9 + tests/ui/imports/issue-45829/import-twice.stderr | 13 + tests/ui/imports/issue-45829/issue-45829.rs | 9 + tests/ui/imports/issue-45829/issue-45829.stderr | 17 + .../ui/imports/issue-45829/rename-extern-vs-use.rs | 11 + .../issue-45829/rename-extern-vs-use.stderr | 17 + .../imports/issue-45829/rename-extern-with-tab.rs | 8 + .../issue-45829/rename-extern-with-tab.stderr | 17 + tests/ui/imports/issue-45829/rename-extern.rs | 8 + tests/ui/imports/issue-45829/rename-extern.stderr | 17 + .../ui/imports/issue-45829/rename-use-vs-extern.rs | 7 + .../issue-45829/rename-use-vs-extern.stderr | 17 + .../ui/imports/issue-45829/rename-use-with-tabs.rs | 12 + .../issue-45829/rename-use-with-tabs.stderr | 17 + tests/ui/imports/issue-45829/rename-with-path.rs | 4 + .../ui/imports/issue-45829/rename-with-path.stderr | 17 + tests/ui/imports/issue-45829/rename.rs | 7 + tests/ui/imports/issue-45829/rename.stderr | 17 + tests/ui/imports/issue-47623.rs | 3 + tests/ui/imports/issue-47623.stderr | 9 + tests/ui/imports/issue-4865-1.rs | 33 + tests/ui/imports/issue-4865-2.rs | 24 + tests/ui/imports/issue-4865-3.rs | 17 + tests/ui/imports/issue-52891.fixed | 37 + tests/ui/imports/issue-52891.rs | 38 + tests/ui/imports/issue-52891.stderr | 131 + tests/ui/imports/issue-53140.rs | 11 + tests/ui/imports/issue-53269.rs | 11 + tests/ui/imports/issue-53269.stderr | 31 + tests/ui/imports/issue-53512.rs | 8 + tests/ui/imports/issue-53512.stderr | 9 + tests/ui/imports/issue-53565.rs | 7 + tests/ui/imports/issue-53565.stderr | 20 + tests/ui/imports/issue-55457.rs | 10 + tests/ui/imports/issue-55457.stderr | 52 + tests/ui/imports/issue-55811.rs | 6 + tests/ui/imports/issue-55884-1.rs | 21 + tests/ui/imports/issue-55884-1.stderr | 23 + tests/ui/imports/issue-55884-2.rs | 14 + tests/ui/imports/issue-55884-2.stderr | 30 + tests/ui/imports/issue-56125.rs | 21 + tests/ui/imports/issue-56125.stderr | 70 + tests/ui/imports/issue-56263.rs | 8 + tests/ui/imports/issue-57015.rs | 13 + tests/ui/imports/issue-57015.stderr | 14 + tests/ui/imports/issue-57539.rs | 8 + tests/ui/imports/issue-57539.stderr | 19 + tests/ui/imports/issue-59764.rs | 136 + tests/ui/imports/issue-59764.stderr | 246 + tests/ui/imports/issue-62767.rs | 30 + tests/ui/imports/issue-68103.rs | 6 + tests/ui/imports/issue-8208.rs | 17 + tests/ui/imports/issue-8208.stderr | 21 + tests/ui/imports/issue-8640.rs | 10 + tests/ui/imports/issue-8640.stderr | 17 + tests/ui/imports/issue-99695-b.fixed | 20 + tests/ui/imports/issue-99695-b.rs | 19 + tests/ui/imports/issue-99695-b.stderr | 16 + tests/ui/imports/issue-99695.fixed | 17 + tests/ui/imports/issue-99695.rs | 16 + tests/ui/imports/issue-99695.stderr | 16 + .../ui/imports/local-modularized-tricky-fail-1.rs | 46 + .../imports/local-modularized-tricky-fail-1.stderr | 70 + .../ui/imports/local-modularized-tricky-fail-2.rs | 22 + .../imports/local-modularized-tricky-fail-2.stderr | 43 + .../ui/imports/local-modularized-tricky-pass-1.rs | 19 + .../ui/imports/local-modularized-tricky-pass-2.rs | 50 + tests/ui/imports/local-modularized.rs | 35 + tests/ui/imports/macro-paths.rs | 28 + tests/ui/imports/macro-paths.stderr | 43 + tests/ui/imports/macros.rs | 41 + tests/ui/imports/macros.stderr | 41 + tests/ui/imports/no-std-inject.rs | 6 + tests/ui/imports/no-std-inject.stderr | 15 + tests/ui/imports/overlapping_pub_trait.rs | 15 + tests/ui/imports/overlapping_pub_trait.stderr | 20 + tests/ui/imports/reexport-star.rs | 16 + tests/ui/imports/reexports.rs | 37 + tests/ui/imports/reexports.stderr | 62 + tests/ui/imports/resolve_self_super_hint.rs | 27 + tests/ui/imports/resolve_self_super_hint.stderr | 33 + tests/ui/imports/rfc-1560-warning-cycle.rs | 13 + tests/ui/imports/rfc-1560-warning-cycle.stderr | 23 + tests/ui/imports/shadow_builtin_macros.rs | 52 + tests/ui/imports/shadow_builtin_macros.stderr | 72 + tests/ui/imports/tool-mod-child.rs | 7 + tests/ui/imports/tool-mod-child.stderr | 36 + tests/ui/imports/unnamed_pub_trait.rs | 16 + tests/ui/imports/unnamed_pub_trait.stderr | 20 + tests/ui/imports/unresolved-imports-used.rs | 18 + tests/ui/imports/unresolved-imports-used.stderr | 72 + tests/ui/imports/unused-import-issue-87973.fixed | 8 + tests/ui/imports/unused-import-issue-87973.rs | 11 + tests/ui/imports/unused-import-issue-87973.stderr | 14 + tests/ui/imports/unused-imports-in-test-mode.rs | 102 + .../ui/imports/unused-imports-in-test-mode.stderr | 68 + tests/ui/imports/unused-imports-in-test-module.rs | 89 + .../imports/unused-imports-in-test-module.stderr | 92 + tests/ui/imports/unused-macro-use.rs | 11 + tests/ui/imports/unused-macro-use.stderr | 21 + tests/ui/imports/unused.rs | 27 + tests/ui/imports/unused.stderr | 15 + tests/ui/imports/use-mod.rs | 33 + tests/ui/impossible_range.fixed | 20 + tests/ui/impossible_range.rs | 20 + tests/ui/impossible_range.stderr | 19 + tests/ui/inc-range-pat.rs | 12 + .../auxiliary/same-file-in-two-crates-aux.rs | 4 + tests/ui/include-macros/data.bin | 2 + tests/ui/include-macros/file.txt | 0 tests/ui/include-macros/mismatched-types.rs | 4 + tests/ui/include-macros/mismatched-types.stderr | 27 + tests/ui/include-macros/normalization.rs | 12 + tests/ui/include-macros/same-file-in-two-crates.rs | 21 + .../auxiliary/extern-crate.rs | 9 + .../needs-has-incoherent-impls.rs | 40 + .../needs-has-incoherent-impls.stderr | 115 + .../no-attr-empty-impl.rs | 18 + .../no-attr-empty-impl.stderr | 44 + tests/ui/index-bot.rs | 3 + tests/ui/index-bot.stderr | 9 + tests/ui/index-help.rs | 4 + tests/ui/index-help.stderr | 13 + tests/ui/index_message.rs | 4 + tests/ui/index_message.stderr | 9 + tests/ui/indexing-requires-a-uint.rs | 14 + tests/ui/indexing-requires-a-uint.stderr | 32 + tests/ui/infer-fn-tail-expr.rs | 11 + tests/ui/inference/ambiguous_type_parameter.rs | 17 + tests/ui/inference/ambiguous_type_parameter.stderr | 14 + .../auxiliary/inference_unstable_iterator.rs | 35 + .../auxiliary/inference_unstable_itertools.rs | 25 + tests/ui/inference/cannot-infer-async.rs | 16 + tests/ui/inference/cannot-infer-async.stderr | 14 + .../ui/inference/cannot-infer-closure-circular.rs | 13 + .../inference/cannot-infer-closure-circular.stderr | 14 + tests/ui/inference/cannot-infer-closure.rs | 7 + tests/ui/inference/cannot-infer-closure.stderr | 14 + .../inference/cannot-infer-partial-try-return.rs | 23 + .../cannot-infer-partial-try-return.stderr | 14 + tests/ui/inference/char-as-str-multi.rs | 7 + tests/ui/inference/char-as-str-multi.stderr | 19 + tests/ui/inference/char-as-str-single.fixed | 12 + tests/ui/inference/char-as-str-single.rs | 12 + tests/ui/inference/char-as-str-single.stderr | 42 + tests/ui/inference/deref-suggestion.rs | 75 + tests/ui/inference/deref-suggestion.stderr | 180 + tests/ui/inference/erase-type-params-in-label.rs | 27 + .../ui/inference/erase-type-params-in-label.stderr | 37 + .../infer-binary-operand-behind-reference.rs | 30 + .../inference-variable-behind-raw-pointer.rs | 11 + .../inference-variable-behind-raw-pointer.stderr | 12 + tests/ui/inference/inference_unstable.rs | 31 + tests/ui/inference/inference_unstable.stderr | 57 + tests/ui/inference/inference_unstable_featured.rs | 17 + .../inference/inference_unstable_featured.stderr | 20 + tests/ui/inference/inference_unstable_forced.rs | 12 + .../ui/inference/inference_unstable_forced.stderr | 12 + tests/ui/inference/issue-103587.rs | 12 + tests/ui/inference/issue-103587.stderr | 40 + tests/ui/inference/issue-104649.rs | 32 + tests/ui/inference/issue-104649.stderr | 14 + tests/ui/inference/issue-28935.rs | 9 + tests/ui/inference/issue-36053.rs | 22 + tests/ui/inference/issue-70703.rs | 26 + tests/ui/inference/issue-71309.rs | 7 + tests/ui/inference/issue-71309.stderr | 15 + tests/ui/inference/issue-71732.rs | 24 + tests/ui/inference/issue-71732.stderr | 22 + tests/ui/inference/issue-72616.rs | 32 + tests/ui/inference/issue-72616.stderr | 37 + tests/ui/inference/issue-72690.rs | 70 + tests/ui/inference/issue-72690.stderr | 229 + tests/ui/inference/issue-80816.rs | 55 + tests/ui/inference/issue-80816.stderr | 29 + tests/ui/inference/issue-81522.rs | 31 + tests/ui/inference/issue-83606.rs | 10 + tests/ui/inference/issue-83606.stderr | 14 + tests/ui/inference/issue-86162-1.rs | 9 + tests/ui/inference/issue-86162-1.stderr | 22 + tests/ui/inference/issue-86162-2.rs | 14 + tests/ui/inference/issue-86162-2.stderr | 22 + .../ui/inference/lub-glb-with-unbound-infer-var.rs | 15 + tests/ui/inference/need_type_info/channel.rs | 19 + tests/ui/inference/need_type_info/channel.stderr | 25 + tests/ui/inference/need_type_info/concrete-impl.rs | 16 + .../inference/need_type_info/concrete-impl.stderr | 24 + ...-not-suggest-generic-arguments-for-turbofish.rs | 11 + ...-suggest-generic-arguments-for-turbofish.stderr | 9 + .../expr-struct-type-relative-enum.rs | 21 + .../expr-struct-type-relative-enum.stderr | 14 + .../expr-struct-type-relative-gat.rs | 19 + .../expr-struct-type-relative-gat.stderr | 9 + .../need_type_info/expr-struct-type-relative.rs | 21 + .../expr-struct-type-relative.stderr | 14 + tests/ui/inference/need_type_info/issue-103053.rs | 18 + .../inference/need_type_info/issue-103053.stderr | 14 + .../ui/inference/need_type_info/self-ty-in-path.rs | 13 + .../need_type_info/self-ty-in-path.stderr | 14 + .../need_type_info/type-alias-indirect.rs | 18 + .../need_type_info/type-alias-indirect.stderr | 9 + tests/ui/inference/need_type_info/type-alias.rs | 36 + .../ui/inference/need_type_info/type-alias.stderr | 15 + tests/ui/inference/newlambdas-ret-infer.rs | 12 + tests/ui/inference/newlambdas-ret-infer2.rs | 12 + tests/ui/inference/question-mark-type-infer.rs | 16 + tests/ui/inference/question-mark-type-infer.stderr | 14 + tests/ui/inference/range-type-infer.rs | 22 + tests/ui/inference/simple-infer.rs | 6 + tests/ui/inference/str-as-char.fixed | 10 + tests/ui/inference/str-as-char.rs | 10 + tests/ui/inference/str-as-char.stderr | 38 + .../ui/inference/tutorial-suffix-inference-test.rs | 24 + .../tutorial-suffix-inference-test.stderr | 57 + tests/ui/inference/type-infer-generalize-ty-var.rs | 56 + tests/ui/infinite/infinite-autoderef.rs | 26 + tests/ui/infinite/infinite-autoderef.stderr | 54 + .../infinite-instantiation.polonius.stderr | 15 + tests/ui/infinite/infinite-instantiation.rs | 29 + tests/ui/infinite/infinite-instantiation.stderr | 15 + tests/ui/infinite/infinite-macro-expansion.rs | 7 + tests/ui/infinite/infinite-macro-expansion.stderr | 14 + tests/ui/infinite/infinite-recursion-const-fn.rs | 11 + .../ui/infinite/infinite-recursion-const-fn.stderr | 650 ++ tests/ui/infinite/infinite-struct.rs | 16 + tests/ui/infinite/infinite-struct.stderr | 27 + tests/ui/infinite/infinite-tag-type-recursion.rs | 4 + .../ui/infinite/infinite-tag-type-recursion.stderr | 14 + .../ui/infinite/infinite-trait-alias-recursion.rs | 10 + .../infinite/infinite-trait-alias-recursion.stderr | 42 + .../infinite-type-alias-mutual-recursion.rs | 6 + .../infinite-type-alias-mutual-recursion.stderr | 34 + tests/ui/infinite/infinite-vec-type-recursion.rs | 4 + .../ui/infinite/infinite-vec-type-recursion.stderr | 22 + .../infinite/issue-41731-infinite-macro-print.rs | 15 + .../issue-41731-infinite-macro-print.stderr | 38 + .../infinite/issue-41731-infinite-macro-println.rs | 15 + .../issue-41731-infinite-macro-println.stderr | 38 + .../auxiliary/repeat.rs | 54 + .../ui/inherent-impls-overlap-check/no-overlap.rs | 53 + tests/ui/inherent-impls-overlap-check/overlap.rs | 71 + .../ui/inherent-impls-overlap-check/overlap.stderr | 47 + tests/ui/inherit-env.rs | 26 + tests/ui/inline-const/const-expr-array-init.rs | 9 + tests/ui/inline-const/const-expr-basic.rs | 14 + tests/ui/inline-const/const-expr-generic-err.rs | 15 + .../ui/inline-const/const-expr-generic-err.stderr | 29 + tests/ui/inline-const/const-expr-generic-err2.rs | 10 + .../ui/inline-const/const-expr-generic-err2.stderr | 10 + tests/ui/inline-const/const-expr-generic.rs | 15 + tests/ui/inline-const/const-expr-inference.rs | 11 + tests/ui/inline-const/const-expr-lifetime-err.rs | 29 + .../ui/inline-const/const-expr-lifetime-err.stderr | 18 + tests/ui/inline-const/const-expr-lifetime.rs | 35 + tests/ui/inline-const/const-expr-macro.rs | 12 + tests/ui/inline-const/const-expr-reference.rs | 14 + tests/ui/inline-const/const-match-pat-generic.rs | 31 + .../ui/inline-const/const-match-pat-generic.stderr | 26 + tests/ui/inline-const/const-match-pat-inference.rs | 12 + .../inline-const/const-match-pat-lifetime-err.rs | 34 + tests/ui/inline-const/const-match-pat-lifetime.rs | 37 + tests/ui/inline-const/const-match-pat-range.rs | 39 + tests/ui/inline-const/const-match-pat.rs | 21 + tests/ui/inline-const/expr-unsafe-err.mir.stderr | 11 + tests/ui/inline-const/expr-unsafe-err.rs | 11 + tests/ui/inline-const/expr-unsafe-err.thir.stderr | 11 + tests/ui/inline-const/expr-unsafe.mir.stderr | 14 + tests/ui/inline-const/expr-unsafe.rs | 16 + tests/ui/inline-const/expr-unsafe.thir.stderr | 17 + tests/ui/inline-const/expr-with-block-err.rs | 6 + tests/ui/inline-const/expr-with-block-err.stderr | 9 + tests/ui/inline-const/expr-with-block.rs | 10 + tests/ui/inline-const/macro-with-const.rs | 20 + tests/ui/inline-const/pat-unsafe-err.rs | 17 + tests/ui/inline-const/pat-unsafe.rs | 22 + tests/ui/inline-disallow-on-variant.rs | 7 + tests/ui/inline-disallow-on-variant.stderr | 12 + tests/ui/inlined-main.rs | 4 + tests/ui/inner-attrs-on-impl.rs | 24 + tests/ui/inner-module.rs | 10 + tests/ui/inner-static-type-parameter.rs | 11 + tests/ui/inner-static-type-parameter.stderr | 21 + tests/ui/inner-static.rs | 14 + tests/ui/integral-indexing.rs | 16 + tests/ui/integral-indexing.stderr | 83 + tests/ui/integral-variable-unification-error.rs | 8 + .../ui/integral-variable-unification-error.stderr | 14 + .../ui/interior-mutability/interior-mutability.rs | 7 + .../interior-mutability/interior-mutability.stderr | 22 + tests/ui/internal/auxiliary/internal_unstable.rs | 101 + tests/ui/internal/internal-unstable-const.rs | 13 + tests/ui/internal/internal-unstable-const.stderr | 17 + tests/ui/internal/internal-unstable-noallow.rs | 23 + tests/ui/internal/internal-unstable-noallow.stderr | 39 + .../ui/internal/internal-unstable-thread-local.rs | 11 + .../internal/internal-unstable-thread-local.stderr | 11 + tests/ui/internal/internal-unstable.rs | 56 + tests/ui/internal/internal-unstable.stderr | 47 + tests/ui/intrinsics-always-extern.rs | 16 + tests/ui/intrinsics-always-extern.stderr | 24 + tests/ui/intrinsics/auxiliary/cci_intrinsic.rs | 14 + .../intrinsics/bad-intrinsic-monomorphization.rs | 32 + .../bad-intrinsic-monomorphization.stderr | 21 + .../intrinsics/const-eval-select-backtrace-std.rs | 7 + .../const-eval-select-backtrace-std.run.stderr | 2 + tests/ui/intrinsics/const-eval-select-backtrace.rs | 19 + .../const-eval-select-backtrace.run.stderr | 2 + tests/ui/intrinsics/const-eval-select-bad.rs | 46 + tests/ui/intrinsics/const-eval-select-bad.stderr | 101 + tests/ui/intrinsics/const-eval-select-stability.rs | 21 + .../intrinsics/const-eval-select-stability.stderr | 10 + tests/ui/intrinsics/const-eval-select-x86_64.rs | 40 + tests/ui/intrinsics/const-eval-select.rs | 27 + tests/ui/intrinsics/intrinsic-alignment.rs | 67 + tests/ui/intrinsics/intrinsic-assume.rs | 17 + tests/ui/intrinsics/intrinsic-atomics-cc.rs | 12 + tests/ui/intrinsics/intrinsic-atomics.rs | 102 + tests/ui/intrinsics/intrinsic-nearby.rs | 11 + .../intrinsics/intrinsic-raw_eq-const-padding.rs | 10 + .../intrinsic-raw_eq-const-padding.stderr | 9 + tests/ui/intrinsics/intrinsic-raw_eq-const.rs | 26 + tests/ui/intrinsics/intrinsic-unreachable.rs | 17 + tests/ui/intrinsics/intrinsic-volatile.rs | 44 + tests/ui/intrinsics/intrinsics-integer.rs | 177 + tests/ui/intrinsics/intrinsics-math.rs | 60 + tests/ui/intrinsics/issue-28575.mir.stderr | 11 + tests/ui/intrinsics/issue-28575.rs | 12 + tests/ui/intrinsics/issue-28575.thir.stderr | 11 + tests/ui/intrinsics/issue-84297-reifying-copy.rs | 9 + tests/ui/intrinsics/non-integer-atomic.rs | 92 + tests/ui/intrinsics/non-integer-atomic.stderr | 99 + tests/ui/intrinsics/panic-uninitialized-zeroed.rs | 397 + tests/ui/intrinsics/safe-intrinsic-mismatch.rs | 11 + tests/ui/intrinsics/safe-intrinsic-mismatch.stderr | 14 + .../ui/intrinsics/unchecked_math_unsafe.mir.stderr | 27 + tests/ui/intrinsics/unchecked_math_unsafe.rs | 11 + .../intrinsics/unchecked_math_unsafe.thir.stderr | 27 + tests/ui/intrinsics/unchecked_math_unstable.rs | 8 + tests/ui/intrinsics/unchecked_math_unstable.stderr | 27 + ...anch-protection-missing-pac-ret.BADFLAGS.stderr | 2 + ...nch-protection-missing-pac-ret.BADTARGET.stderr | 4 + .../branch-protection-missing-pac-ret.rs | 14 + .../codegen-option-without-group.rs | 1 + .../codegen-option-without-group.stderr | 2 + .../debug-option-without-group.rs | 1 + .../debug-option-without-group.stderr | 2 + .../auxiliary/foo/bar.rs | 1 + .../auxiliary/foo/mod.rs | 1 + .../invalid-module-declaration.rs | 5 + .../invalid-module-declaration.stderr | 11 + tests/ui/invalid-self-argument/bare-fn-start.rs | 6 + .../ui/invalid-self-argument/bare-fn-start.stderr | 10 + tests/ui/invalid-self-argument/bare-fn.rs | 5 + tests/ui/invalid-self-argument/bare-fn.stderr | 8 + tests/ui/invalid-self-argument/trait-fn.rs | 11 + tests/ui/invalid-self-argument/trait-fn.stderr | 8 + tests/ui/invalid/invalid-crate-type-macro.rs | 7 + tests/ui/invalid/invalid-crate-type-macro.stderr | 8 + tests/ui/invalid/invalid-crate-type.rs | 48 + tests/ui/invalid/invalid-crate-type.stderr | 58 + .../invalid/invalid-debugger-visualizer-option.rs | 7 + .../invalid-debugger-visualizer-option.stderr | 18 + .../invalid/invalid-debugger-visualizer-target.rs | 4 + .../invalid-debugger-visualizer-target.stderr | 8 + tests/ui/invalid/invalid-inline.rs | 14 + tests/ui/invalid/invalid-inline.stderr | 15 + tests/ui/invalid/invalid-llvm-passes.rs | 4 + tests/ui/invalid/invalid-llvm-passes.stderr | 4 + tests/ui/invalid/invalid-macro-matcher.rs | 8 + tests/ui/invalid/invalid-macro-matcher.stderr | 8 + tests/ui/invalid/invalid-no-sanitize.rs | 5 + tests/ui/invalid/invalid-no-sanitize.stderr | 10 + tests/ui/invalid/invalid-path-in-const.rs | 4 + tests/ui/invalid/invalid-path-in-const.stderr | 9 + tests/ui/invalid/invalid-plugin-attr.rs | 7 + tests/ui/invalid/invalid-plugin-attr.stderr | 22 + ...nvalid-rustc_legacy_const_generics-arguments.rs | 43 + ...id-rustc_legacy_const_generics-arguments.stderr | 95 + .../invalid_rustc_layout_scalar_valid_range.rs | 30 + .../invalid_rustc_layout_scalar_valid_range.stderr | 37 + tests/ui/invalid_crate_type_syntax.rs | 6 + tests/ui/invalid_crate_type_syntax.stderr | 8 + tests/ui/invalid_dispatch_from_dyn_impls.rs | 51 + tests/ui/invalid_dispatch_from_dyn_impls.stderr | 40 + tests/ui/issue-76387-llvm-miscompile.rs | 22 + tests/ui/issue-94866.rs | 14 + tests/ui/issue-94866.stderr | 21 + tests/ui/issues-71798.rs | 8 + tests/ui/issues-71798.stderr | 22 + tests/ui/issues/auxiliary/cgu_test.rs | 6 + tests/ui/issues/auxiliary/cgu_test_a.rs | 15 + tests/ui/issues/auxiliary/cgu_test_b.rs | 15 + tests/ui/issues/auxiliary/i8.rs | 3 + tests/ui/issues/auxiliary/iss.rs | 12 + tests/ui/issues/auxiliary/issue-11224.rs | 16 + tests/ui/issues/auxiliary/issue-11508.rs | 10 + tests/ui/issues/auxiliary/issue-11529.rs | 1 + tests/ui/issues/auxiliary/issue-11680.rs | 9 + tests/ui/issues/auxiliary/issue-12133-dylib.rs | 1 + tests/ui/issues/auxiliary/issue-12133-dylib2.rs | 6 + tests/ui/issues/auxiliary/issue-12133-rlib.rs | 3 + tests/ui/issues/auxiliary/issue-12612-1.rs | 3 + tests/ui/issues/auxiliary/issue-12612-2.rs | 1 + tests/ui/issues/auxiliary/issue-12660-aux.rs | 11 + tests/ui/issues/auxiliary/issue-13507.rs | 87 + tests/ui/issues/auxiliary/issue-13620-1.rs | 9 + tests/ui/issues/auxiliary/issue-13620-2.rs | 3 + tests/ui/issues/auxiliary/issue-13872-1.rs | 1 + tests/ui/issues/auxiliary/issue-13872-2.rs | 3 + tests/ui/issues/auxiliary/issue-13872-3.rs | 9 + tests/ui/issues/auxiliary/issue-14344-1.rs | 5 + tests/ui/issues/auxiliary/issue-14344-2.rs | 3 + tests/ui/issues/auxiliary/issue-14421.rs | 25 + tests/ui/issues/auxiliary/issue-14422.rs | 25 + tests/ui/issues/auxiliary/issue-15562.rs | 5 + tests/ui/issues/auxiliary/issue-16643.rs | 19 + tests/ui/issues/auxiliary/issue-16725.rs | 3 + tests/ui/issues/auxiliary/issue-17662.rs | 12 + tests/ui/issues/auxiliary/issue-18501.rs | 17 + tests/ui/issues/auxiliary/issue-18514.rs | 17 + tests/ui/issues/auxiliary/issue-18711.rs | 5 + tests/ui/issues/auxiliary/issue-18913-1.rs | 6 + tests/ui/issues/auxiliary/issue-18913-2.rs | 6 + tests/ui/issues/auxiliary/issue-1920.rs | 4 + tests/ui/issues/auxiliary/issue-19293.rs | 4 + tests/ui/issues/auxiliary/issue-19340-1.rs | 3 + tests/ui/issues/auxiliary/issue-20389.rs | 4 + tests/ui/issues/auxiliary/issue-21202.rs | 6 + tests/ui/issues/auxiliary/issue-2170-lib.rs | 18 + tests/ui/issues/auxiliary/issue-2316-a.rs | 3 + tests/ui/issues/auxiliary/issue-2316-b.rs | 11 + tests/ui/issues/auxiliary/issue-2380.rs | 13 + tests/ui/issues/auxiliary/issue-2414-a.rs | 12 + tests/ui/issues/auxiliary/issue-2414-b.rs | 4 + tests/ui/issues/auxiliary/issue-2472-b.rs | 13 + tests/ui/issues/auxiliary/issue-25185-1.rs | 8 + tests/ui/issues/auxiliary/issue-25185-2.rs | 3 + tests/ui/issues/auxiliary/issue-2526.rs | 44 + tests/ui/issues/auxiliary/issue-25467.rs | 10 + tests/ui/issues/auxiliary/issue-2631-a.rs | 14 + tests/ui/issues/auxiliary/issue-2723-a.rs | 3 + tests/ui/issues/auxiliary/issue-29181.rs | 5 + tests/ui/issues/auxiliary/issue-29265.rs | 9 + tests/ui/issues/auxiliary/issue-29485.rs | 16 + tests/ui/issues/auxiliary/issue-3012-1.rs | 20 + tests/ui/issues/auxiliary/issue-30123-aux.rs | 23 + tests/ui/issues/auxiliary/issue-3136-a.rc | 4 + tests/ui/issues/auxiliary/issue-3136-a.rs | 14 + tests/ui/issues/auxiliary/issue-31702-1.rs | 16 + tests/ui/issues/auxiliary/issue-31702-2.rs | 20 + tests/ui/issues/auxiliary/issue-34796-aux.rs | 20 + tests/ui/issues/auxiliary/issue-36954.rs | 7 + tests/ui/issues/auxiliary/issue-38190.rs | 2 + tests/ui/issues/auxiliary/issue-38226-aux.rs | 23 + tests/ui/issues/auxiliary/issue-3979-traits.rs | 15 + tests/ui/issues/auxiliary/issue-41053.rs | 1 + tests/ui/issues/auxiliary/issue-41394.rs | 16 + tests/ui/issues/auxiliary/issue-41549.rs | 3 + tests/ui/issues/auxiliary/issue-42007-s.rs | 4 + tests/ui/issues/auxiliary/issue-4208-cc.rs | 10 + tests/ui/issues/auxiliary/issue-4545.rs | 2 + tests/ui/issues/auxiliary/issue-48984-aux.rs | 6 + tests/ui/issues/auxiliary/issue-49544.rs | 7 + tests/ui/issues/auxiliary/issue-51798.rs | 3 + tests/ui/issues/auxiliary/issue-52489.rs | 3 + tests/ui/issues/auxiliary/issue-5518.rs | 4 + tests/ui/issues/auxiliary/issue-5521.rs | 3 + tests/ui/issues/auxiliary/issue-56943.rs | 3 + tests/ui/issues/auxiliary/issue-57271-lib.rs | 11 + tests/ui/issues/auxiliary/issue-5844-aux.rs | 3 + tests/ui/issues/auxiliary/issue-7178.rs | 7 + tests/ui/issues/auxiliary/issue-73112.rs | 10 + tests/ui/issues/auxiliary/issue-7899.rs | 1 + tests/ui/issues/auxiliary/issue-8044.rs | 15 + tests/ui/issues/auxiliary/issue-8259.rs | 4 + tests/ui/issues/auxiliary/issue-8401.rs | 16 + tests/ui/issues/auxiliary/issue-9123.rs | 9 + tests/ui/issues/auxiliary/issue-9155.rs | 7 + tests/ui/issues/auxiliary/issue-9188.rs | 13 + tests/ui/issues/auxiliary/issue-9906.rs | 15 + tests/ui/issues/auxiliary/issue-9968.rs | 22 + tests/ui/issues/auxiliary/private-trait-xc.rs | 1 + tests/ui/issues/auxiliary/reexported-trait.rs | 17 + tests/ui/issues/issue-100605.rs | 9 + tests/ui/issues/issue-100605.stderr | 46 + tests/ui/issues/issue-10228.rs | 20 + tests/ui/issues/issue-10291.rs | 8 + tests/ui/issues/issue-10291.stderr | 11 + tests/ui/issues/issue-102964.rs | 10 + tests/ui/issues/issue-102964.stderr | 19 + tests/ui/issues/issue-10396.rs | 14 + tests/ui/issues/issue-10412.rs | 27 + tests/ui/issues/issue-10412.stderr | 75 + tests/ui/issues/issue-10436.rs | 11 + tests/ui/issues/issue-10456.rs | 25 + tests/ui/issues/issue-10465.rs | 23 + tests/ui/issues/issue-10465.stderr | 15 + tests/ui/issues/issue-10545.rs | 9 + tests/ui/issues/issue-10545.stderr | 15 + tests/ui/issues/issue-10638.rs | 11 + tests/ui/issues/issue-10656.rs | 3 + tests/ui/issues/issue-10656.stderr | 15 + tests/ui/issues/issue-10682.rs | 13 + tests/ui/issues/issue-10683.rs | 11 + tests/ui/issues/issue-10718.rs | 11 + tests/ui/issues/issue-10734.rs | 36 + tests/ui/issues/issue-10764.rs | 5 + tests/ui/issues/issue-10764.stderr | 19 + tests/ui/issues/issue-10767.rs | 8 + tests/ui/issues/issue-10802.rs | 45 + tests/ui/issues/issue-10806.rs | 38 + tests/ui/issues/issue-10853.rs | 15 + tests/ui/issues/issue-10877.rs | 16 + tests/ui/issues/issue-10877.stderr | 27 + tests/ui/issues/issue-10902.rs | 21 + tests/ui/issues/issue-11004.rs | 27 + tests/ui/issues/issue-11004.stderr | 19 + tests/ui/issues/issue-11047.rs | 26 + tests/ui/issues/issue-11085.rs | 46 + tests/ui/issues/issue-11192.rs | 22 + tests/ui/issues/issue-11192.stderr | 17 + tests/ui/issues/issue-11205.rs | 85 + tests/ui/issues/issue-11224.rs | 8 + tests/ui/issues/issue-11267.rs | 19 + tests/ui/issues/issue-11374.rs | 27 + tests/ui/issues/issue-11374.stderr | 21 + tests/ui/issues/issue-11382.rs | 4 + tests/ui/issues/issue-11384.rs | 10 + tests/ui/issues/issue-11508.rs | 11 + tests/ui/issues/issue-11515.rs | 10 + tests/ui/issues/issue-11515.stderr | 13 + tests/ui/issues/issue-11529.rs | 11 + tests/ui/issues/issue-11552.rs | 24 + tests/ui/issues/issue-11592.rs | 11 + tests/ui/issues/issue-11593.rs | 10 + tests/ui/issues/issue-11593.stderr | 15 + tests/ui/issues/issue-11677.rs | 23 + tests/ui/issues/issue-11680.rs | 11 + tests/ui/issues/issue-11680.stderr | 27 + tests/ui/issues/issue-11681.rs | 19 + tests/ui/issues/issue-11681.stderr | 11 + tests/ui/issues/issue-11692-1.rs | 3 + tests/ui/issues/issue-11692-1.stderr | 8 + tests/ui/issues/issue-11692-2.rs | 3 + tests/ui/issues/issue-11692-2.stderr | 10 + tests/ui/issues/issue-11709.rs | 38 + tests/ui/issues/issue-11740.rs | 28 + tests/ui/issues/issue-11771.rs | 11 + tests/ui/issues/issue-11771.stderr | 39 + tests/ui/issues/issue-11820.rs | 12 + tests/ui/issues/issue-11844.rs | 8 + tests/ui/issues/issue-11844.stderr | 14 + tests/ui/issues/issue-11869.rs | 17 + tests/ui/issues/issue-11873.rs | 7 + tests/ui/issues/issue-11873.stderr | 16 + tests/ui/issues/issue-11958.rs | 11 + tests/ui/issues/issue-11958.stderr | 20 + tests/ui/issues/issue-12028.rs | 38 + tests/ui/issues/issue-12028.stderr | 15 + tests/ui/issues/issue-12033.rs | 7 + tests/ui/issues/issue-12041.rs | 13 + tests/ui/issues/issue-12041.stderr | 11 + tests/ui/issues/issue-12127.rs | 14 + tests/ui/issues/issue-12127.stderr | 18 + tests/ui/issues/issue-12133-1.rs | 10 + tests/ui/issues/issue-12133-2.rs | 11 + tests/ui/issues/issue-12133-3.rs | 13 + tests/ui/issues/issue-12187-1.rs | 8 + tests/ui/issues/issue-12187-1.stderr | 14 + tests/ui/issues/issue-12187-2.rs | 8 + tests/ui/issues/issue-12187-2.stderr | 14 + tests/ui/issues/issue-12285.rs | 14 + tests/ui/issues/issue-1251.rs | 16 + tests/ui/issues/issue-12511.rs | 8 + tests/ui/issues/issue-12511.stderr | 33 + tests/ui/issues/issue-12567.rs | 13 + tests/ui/issues/issue-12567.stderr | 47 + tests/ui/issues/issue-1257.rs | 11 + tests/ui/issues/issue-12612.rs | 15 + tests/ui/issues/issue-12660.rs | 14 + tests/ui/issues/issue-12677.rs | 9 + tests/ui/issues/issue-12699.rs | 10 + tests/ui/issues/issue-12729.rs | 14 + tests/ui/issues/issue-12744.rs | 5 + tests/ui/issues/issue-12860.rs | 49 + tests/ui/issues/issue-12863.rs | 8 + tests/ui/issues/issue-12863.stderr | 9 + tests/ui/issues/issue-12909.rs | 20 + tests/ui/issues/issue-12920.rs | 8 + tests/ui/issues/issue-12997-1.rs | 11 + tests/ui/issues/issue-12997-1.stderr | 14 + tests/ui/issues/issue-12997-2.rs | 9 + tests/ui/issues/issue-12997-2.stderr | 21 + tests/ui/issues/issue-13027.rs | 178 + tests/ui/issues/issue-13033.rs | 14 + tests/ui/issues/issue-13033.stderr | 20 + tests/ui/issues/issue-13058.rs | 27 + tests/ui/issues/issue-13058.stderr | 12 + tests/ui/issues/issue-13105.rs | 9 + tests/ui/issues/issue-13167.rs | 22 + tests/ui/issues/issue-13202.rs | 7 + tests/ui/issues/issue-13204.rs | 25 + tests/ui/issues/issue-13214.rs | 23 + tests/ui/issues/issue-13259-windows-tcb-trash.rs | 42 + tests/ui/issues/issue-13264.rs | 74 + tests/ui/issues/issue-13323.rs | 58 + tests/ui/issues/issue-13359.rs | 13 + tests/ui/issues/issue-13359.stderr | 39 + tests/ui/issues/issue-13405.rs | 20 + tests/ui/issues/issue-13407.rs | 9 + tests/ui/issues/issue-13407.stderr | 24 + tests/ui/issues/issue-13434.rs | 21 + tests/ui/issues/issue-13446.rs | 6 + tests/ui/issues/issue-13446.stderr | 13 + tests/ui/issues/issue-13466.rs | 20 + tests/ui/issues/issue-13466.stderr | 26 + tests/ui/issues/issue-13482-2.rs | 9 + tests/ui/issues/issue-13482-2.stderr | 9 + tests/ui/issues/issue-13482.rs | 7 + tests/ui/issues/issue-13482.stderr | 9 + tests/ui/issues/issue-13497-2.rs | 7 + tests/ui/issues/issue-13497-2.stderr | 12 + tests/ui/issues/issue-13497.rs | 8 + tests/ui/issues/issue-13497.stderr | 15 + tests/ui/issues/issue-13507-2.rs | 36 + tests/ui/issues/issue-1362.rs | 8 + tests/ui/issues/issue-1362.stderr | 16 + tests/ui/issues/issue-13620.rs | 11 + tests/ui/issues/issue-13665.rs | 15 + tests/ui/issues/issue-13703.rs | 6 + tests/ui/issues/issue-13763.rs | 15 + tests/ui/issues/issue-13775.rs | 9 + tests/ui/issues/issue-13808.rs | 18 + tests/ui/issues/issue-13847.rs | 3 + tests/ui/issues/issue-13847.stderr | 9 + tests/ui/issues/issue-13867.rs | 48 + tests/ui/issues/issue-13872.rs | 12 + tests/ui/issues/issue-14082.rs | 20 + tests/ui/issues/issue-14091-2.rs | 17 + tests/ui/issues/issue-14091-2.stderr | 18 + tests/ui/issues/issue-14091.rs | 4 + tests/ui/issues/issue-14091.stderr | 9 + tests/ui/issues/issue-14092.rs | 4 + tests/ui/issues/issue-14092.stderr | 14 + tests/ui/issues/issue-14229.rs | 21 + tests/ui/issues/issue-14254.rs | 93 + tests/ui/issues/issue-14285.rs | 17 + tests/ui/issues/issue-14285.stderr | 11 + tests/ui/issues/issue-14308.rs | 15 + tests/ui/issues/issue-14330.rs | 7 + tests/ui/issues/issue-14344.rs | 11 + tests/ui/issues/issue-14366.rs | 4 + tests/ui/issues/issue-14366.stderr | 16 + tests/ui/issues/issue-14382.rs | 15 + tests/ui/issues/issue-14393.rs | 10 + tests/ui/issues/issue-14399.rs | 18 + tests/ui/issues/issue-14421.rs | 16 + tests/ui/issues/issue-14422.rs | 16 + tests/ui/issues/issue-1448-2.rs | 7 + tests/ui/issues/issue-1448-2.stderr | 21 + tests/ui/issues/issue-1451.rs | 27 + tests/ui/issues/issue-14541.rs | 10 + tests/ui/issues/issue-14541.stderr | 11 + tests/ui/issues/issue-1460.rs | 7 + tests/ui/issues/issue-1460.stderr | 11 + tests/ui/issues/issue-14721.rs | 4 + tests/ui/issues/issue-14721.stderr | 9 + tests/ui/issues/issue-1476.rs | 3 + tests/ui/issues/issue-1476.stderr | 9 + tests/ui/issues/issue-14821.rs | 21 + tests/ui/issues/issue-14845.rs | 11 + tests/ui/issues/issue-14845.stderr | 15 + tests/ui/issues/issue-14853.rs | 20 + tests/ui/issues/issue-14853.stderr | 12 + tests/ui/issues/issue-14865.rs | 23 + tests/ui/issues/issue-14875.rs | 35 + tests/ui/issues/issue-14901.rs | 18 + tests/ui/issues/issue-14915.rs | 6 + tests/ui/issues/issue-14915.stderr | 11 + tests/ui/issues/issue-14919.rs | 55 + tests/ui/issues/issue-14959.rs | 55 + tests/ui/issues/issue-15034.rs | 22 + tests/ui/issues/issue-15034.stderr | 11 + tests/ui/issues/issue-15043.rs | 14 + tests/ui/issues/issue-15063.rs | 12 + tests/ui/issues/issue-15094.rs | 26 + tests/ui/issues/issue-15094.stderr | 12 + tests/ui/issues/issue-15104.rs | 13 + tests/ui/issues/issue-15129-rpass.rs | 25 + tests/ui/issues/issue-15155.rs | 21 + tests/ui/issues/issue-15167.rs | 26 + tests/ui/issues/issue-15167.stderr | 47 + tests/ui/issues/issue-15189.rs | 10 + tests/ui/issues/issue-15207.rs | 6 + tests/ui/issues/issue-15207.stderr | 9 + tests/ui/issues/issue-15260.rs | 25 + tests/ui/issues/issue-15260.stderr | 36 + tests/ui/issues/issue-15381.rs | 9 + tests/ui/issues/issue-15381.stderr | 11 + tests/ui/issues/issue-15444.rs | 23 + tests/ui/issues/issue-15523-big.rs | 39 + tests/ui/issues/issue-15523.rs | 42 + tests/ui/issues/issue-15562.rs | 19 + tests/ui/issues/issue-15571.rs | 57 + tests/ui/issues/issue-15673.rs | 9 + tests/ui/issues/issue-15689-1.rs | 10 + tests/ui/issues/issue-15689-2.rs | 10 + tests/ui/issues/issue-15734.rs | 58 + tests/ui/issues/issue-15735.rs | 17 + tests/ui/issues/issue-15756.rs | 14 + tests/ui/issues/issue-15756.stderr | 13 + tests/ui/issues/issue-15763.rs | 88 + tests/ui/issues/issue-15774.rs | 25 + tests/ui/issues/issue-15783.rs | 14 + tests/ui/issues/issue-15783.stderr | 19 + tests/ui/issues/issue-15793.rs | 27 + tests/ui/issues/issue-15858.rs | 33 + tests/ui/issues/issue-15896.rs | 15 + tests/ui/issues/issue-15896.stderr | 12 + tests/ui/issues/issue-15965.rs | 7 + tests/ui/issues/issue-15965.stderr | 11 + tests/ui/issues/issue-16048.rs | 30 + tests/ui/issues/issue-16048.stderr | 21 + tests/ui/issues/issue-16149.rs | 11 + tests/ui/issues/issue-16149.stderr | 12 + tests/ui/issues/issue-16151.rs | 29 + tests/ui/issues/issue-16250.rs | 9 + tests/ui/issues/issue-16250.stderr | 22 + tests/ui/issues/issue-16256.rs | 7 + tests/ui/issues/issue-16256.stderr | 11 + tests/ui/issues/issue-16278.rs | 10 + tests/ui/issues/issue-16338.rs | 10 + tests/ui/issues/issue-16338.stderr | 14 + tests/ui/issues/issue-16401.rs | 15 + tests/ui/issues/issue-16401.stderr | 14 + tests/ui/issues/issue-16441.rs | 12 + tests/ui/issues/issue-16452.rs | 10 + tests/ui/issues/issue-16492.rs | 67 + tests/ui/issues/issue-16530.rs | 15 + tests/ui/issues/issue-16538.mir.stderr | 29 + tests/ui/issues/issue-16538.rs | 19 + tests/ui/issues/issue-16538.thir.stderr | 29 + tests/ui/issues/issue-16560.rs | 18 + tests/ui/issues/issue-16562.rs | 17 + tests/ui/issues/issue-16562.stderr | 9 + tests/ui/issues/issue-16596.rs | 22 + tests/ui/issues/issue-1660.rs | 8 + tests/ui/issues/issue-16643.rs | 10 + tests/ui/issues/issue-16648.rs | 11 + tests/ui/issues/issue-16668.rs | 20 + tests/ui/issues/issue-16671.rs | 12 + tests/ui/issues/issue-16683.rs | 9 + tests/ui/issues/issue-16683.stderr | 13 + tests/ui/issues/issue-16725.rs | 8 + tests/ui/issues/issue-16725.stderr | 15 + tests/ui/issues/issue-16739.rs | 45 + tests/ui/issues/issue-16745.rs | 11 + tests/ui/issues/issue-16774.rs | 45 + tests/ui/issues/issue-16783.rs | 8 + tests/ui/issues/issue-16819.rs | 12 + tests/ui/issues/issue-16922-rpass.rs | 11 + tests/ui/issues/issue-16922.rs | 10 + tests/ui/issues/issue-16922.stderr | 15 + tests/ui/issues/issue-16939.rs | 8 + tests/ui/issues/issue-16939.stderr | 19 + tests/ui/issues/issue-1696.rs | 8 + tests/ui/issues/issue-16966.rs | 4 + tests/ui/issues/issue-16966.stderr | 11 + tests/ui/issues/issue-16994.rs | 9 + tests/ui/issues/issue-17001.rs | 5 + tests/ui/issues/issue-17001.stderr | 9 + tests/ui/issues/issue-17033.rs | 6 + tests/ui/issues/issue-17033.stderr | 13 + tests/ui/issues/issue-17068.rs | 12 + tests/ui/issues/issue-17121.rs | 31 + tests/ui/issues/issue-17216.rs | 21 + tests/ui/issues/issue-17252.rs | 10 + tests/ui/issues/issue-17252.stderr | 16 + tests/ui/issues/issue-17302.rs | 26 + tests/ui/issues/issue-17322.rs | 13 + tests/ui/issues/issue-17336.rs | 9 + tests/ui/issues/issue-17337.rs | 17 + tests/ui/issues/issue-17337.stderr | 14 + tests/ui/issues/issue-17351.rs | 10 + tests/ui/issues/issue-17361.rs | 9 + tests/ui/issues/issue-17373.rs | 4 + tests/ui/issues/issue-17373.stderr | 9 + tests/ui/issues/issue-17385.rs | 29 + tests/ui/issues/issue-17385.stderr | 23 + tests/ui/issues/issue-17405.rs | 9 + tests/ui/issues/issue-17405.stderr | 9 + tests/ui/issues/issue-17431-1.rs | 6 + tests/ui/issues/issue-17431-1.stderr | 14 + tests/ui/issues/issue-17431-2.rs | 8 + tests/ui/issues/issue-17431-2.stderr | 20 + tests/ui/issues/issue-17431-3.rs | 8 + tests/ui/issues/issue-17431-3.stderr | 14 + tests/ui/issues/issue-17431-4.rs | 8 + tests/ui/issues/issue-17431-4.stderr | 14 + tests/ui/issues/issue-17431-5.rs | 11 + tests/ui/issues/issue-17431-5.stderr | 14 + tests/ui/issues/issue-17431-6.rs | 8 + tests/ui/issues/issue-17431-6.stderr | 14 + tests/ui/issues/issue-17431-7.rs | 6 + tests/ui/issues/issue-17431-7.stderr | 14 + tests/ui/issues/issue-17441.rs | 13 + tests/ui/issues/issue-17441.stderr | 47 + tests/ui/issues/issue-17450.rs | 7 + tests/ui/issues/issue-17503.rs | 10 + tests/ui/issues/issue-17546.rs | 42 + tests/ui/issues/issue-17546.stderr | 73 + tests/ui/issues/issue-17551.rs | 8 + tests/ui/issues/issue-17551.stderr | 14 + tests/ui/issues/issue-17651.rs | 7 + tests/ui/issues/issue-17651.stderr | 15 + tests/ui/issues/issue-17662.rs | 17 + tests/ui/issues/issue-17732.rs | 13 + tests/ui/issues/issue-17734.rs | 15 + tests/ui/issues/issue-17740.rs | 18 + tests/ui/issues/issue-17740.stderr | 41 + tests/ui/issues/issue-17746.rs | 25 + tests/ui/issues/issue-17758.rs | 12 + tests/ui/issues/issue-17758.stderr | 13 + tests/ui/issues/issue-17771.rs | 21 + tests/ui/issues/issue-17800.rs | 12 + tests/ui/issues/issue-17800.stderr | 14 + tests/ui/issues/issue-17816.rs | 10 + tests/ui/issues/issue-17877.rs | 13 + tests/ui/issues/issue-17897.rs | 8 + tests/ui/issues/issue-17904-2.rs | 6 + tests/ui/issues/issue-17904-2.stderr | 11 + tests/ui/issues/issue-17904.rs | 14 + tests/ui/issues/issue-17905-2.rs | 18 + tests/ui/issues/issue-17905-2.stderr | 41 + tests/ui/issues/issue-17905.rs | 19 + tests/ui/issues/issue-17933.rs | 9 + tests/ui/issues/issue-17933.stderr | 9 + tests/ui/issues/issue-17954.rs | 15 + tests/ui/issues/issue-17954.stderr | 12 + tests/ui/issues/issue-17959.rs | 21 + tests/ui/issues/issue-17959.stderr | 15 + tests/ui/issues/issue-17994.rs | 3 + tests/ui/issues/issue-17994.stderr | 9 + tests/ui/issues/issue-17999.rs | 10 + tests/ui/issues/issue-17999.stderr | 20 + tests/ui/issues/issue-18058.rs | 4 + tests/ui/issues/issue-18058.stderr | 9 + tests/ui/issues/issue-18088.rs | 8 + tests/ui/issues/issue-18107.rs | 13 + tests/ui/issues/issue-18107.stderr | 18 + tests/ui/issues/issue-18110.rs | 7 + tests/ui/issues/issue-18119.rs | 12 + tests/ui/issues/issue-18119.stderr | 21 + tests/ui/issues/issue-18159.rs | 3 + tests/ui/issues/issue-18159.stderr | 14 + tests/ui/issues/issue-18173.rs | 12 + tests/ui/issues/issue-18183.rs | 3 + tests/ui/issues/issue-18183.stderr | 9 + tests/ui/issues/issue-18188.rs | 22 + tests/ui/issues/issue-1821.rs | 13 + tests/ui/issues/issue-18232.rs | 22 + tests/ui/issues/issue-18352.rs | 14 + tests/ui/issues/issue-18353.rs | 15 + tests/ui/issues/issue-18389.rs | 18 + tests/ui/issues/issue-18389.stderr | 16 + tests/ui/issues/issue-18423.rs | 8 + tests/ui/issues/issue-18423.stderr | 11 + tests/ui/issues/issue-18446-2.rs | 13 + tests/ui/issues/issue-18446.rs | 19 + tests/ui/issues/issue-18446.stderr | 24 + tests/ui/issues/issue-18464.rs | 12 + tests/ui/issues/issue-18501.rs | 13 + tests/ui/issues/issue-18514.rs | 16 + tests/ui/issues/issue-18532.rs | 7 + tests/ui/issues/issue-18532.stderr | 11 + tests/ui/issues/issue-18539.rs | 16 + tests/ui/issues/issue-18566.rs | 25 + tests/ui/issues/issue-18566.stderr | 12 + tests/ui/issues/issue-18576.rs | 16 + tests/ui/issues/issue-18611.rs | 9 + tests/ui/issues/issue-18611.stderr | 9 + tests/ui/issues/issue-18685.rs | 21 + tests/ui/issues/issue-1871.rs | 12 + tests/ui/issues/issue-1871.stderr | 9 + tests/ui/issues/issue-18711.rs | 12 + tests/ui/issues/issue-18738.rs | 17 + tests/ui/issues/issue-18767.rs | 10 + tests/ui/issues/issue-18783.rs | 28 + tests/ui/issues/issue-18783.stderr | 33 + tests/ui/issues/issue-18804/auxiliary/lib.rs | 10 + tests/ui/issues/issue-18804/main.rs | 19 + tests/ui/issues/issue-18809.rs | 12 + tests/ui/issues/issue-18819.rs | 18 + tests/ui/issues/issue-18819.stderr | 30 + tests/ui/issues/issue-18845.rs | 16 + tests/ui/issues/issue-18859.rs | 16 + tests/ui/issues/issue-18906.rs | 30 + tests/ui/issues/issue-18913.rs | 9 + tests/ui/issues/issue-18919.rs | 12 + tests/ui/issues/issue-18919.stderr | 23 + tests/ui/issues/issue-18952.rs | 56 + tests/ui/issues/issue-18959.rs | 20 + tests/ui/issues/issue-18959.stderr | 18 + tests/ui/issues/issue-18988.rs | 11 + tests/ui/issues/issue-1900.rs | 2 + tests/ui/issues/issue-1900.stderr | 9 + tests/ui/issues/issue-19001.rs | 11 + tests/ui/issues/issue-19037.rs | 20 + tests/ui/issues/issue-19086.rs | 13 + tests/ui/issues/issue-19086.stderr | 12 + tests/ui/issues/issue-19097.rs | 14 + tests/ui/issues/issue-19098.rs | 12 + tests/ui/issues/issue-19100.fixed | 29 + tests/ui/issues/issue-19100.rs | 29 + tests/ui/issues/issue-19100.stderr | 17 + tests/ui/issues/issue-19102.rs | 12 + tests/ui/issues/issue-19127.rs | 10 + tests/ui/issues/issue-19129-1.rs | 16 + tests/ui/issues/issue-19129-2.rs | 11 + tests/ui/issues/issue-19135.rs | 13 + tests/ui/issues/issue-1920-1.rs | 14 + tests/ui/issues/issue-1920-1.stderr | 15 + tests/ui/issues/issue-1920-2.rs | 12 + tests/ui/issues/issue-1920-2.stderr | 15 + tests/ui/issues/issue-1920-3.rs | 16 + tests/ui/issues/issue-1920-3.stderr | 15 + tests/ui/issues/issue-19244-1.rs | 6 + tests/ui/issues/issue-19244-1.stderr | 9 + tests/ui/issues/issue-19244-2.rs | 7 + tests/ui/issues/issue-19244-2.stderr | 11 + tests/ui/issues/issue-19293.rs | 10 + tests/ui/issues/issue-19340-1.rs | 17 + tests/ui/issues/issue-19340-2.rs | 24 + tests/ui/issues/issue-19367.rs | 32 + tests/ui/issues/issue-19380.rs | 18 + tests/ui/issues/issue-19380.stderr | 25 + tests/ui/issues/issue-19398.rs | 12 + tests/ui/issues/issue-19404.rs | 37 + tests/ui/issues/issue-19479.rs | 19 + tests/ui/issues/issue-19482.rs | 13 + tests/ui/issues/issue-19482.stderr | 12 + tests/ui/issues/issue-19499.rs | 15 + tests/ui/issues/issue-19521.rs | 3 + tests/ui/issues/issue-19521.stderr | 9 + tests/ui/issues/issue-19601.rs | 6 + tests/ui/issues/issue-1962.fixed | 10 + tests/ui/issues/issue-1962.rs | 10 + tests/ui/issues/issue-1962.stderr | 10 + tests/ui/issues/issue-19631.rs | 16 + tests/ui/issues/issue-19632.rs | 14 + tests/ui/issues/issue-19692.rs | 8 + tests/ui/issues/issue-19692.stderr | 12 + tests/ui/issues/issue-19707.rs | 7 + tests/ui/issues/issue-19707.stderr | 36 + tests/ui/issues/issue-19734.rs | 8 + tests/ui/issues/issue-19734.stderr | 8 + tests/ui/issues/issue-1974.rs | 11 + tests/ui/issues/issue-19811-escape-unicode.rs | 9 + tests/ui/issues/issue-19850.rs | 22 + tests/ui/issues/issue-19922.rs | 8 + tests/ui/issues/issue-19922.stderr | 11 + tests/ui/issues/issue-19982.rs | 22 + tests/ui/issues/issue-19991.rs | 9 + tests/ui/issues/issue-19991.stderr | 16 + tests/ui/issues/issue-20009.rs | 13 + tests/ui/issues/issue-20055-box-trait.rs | 41 + tests/ui/issues/issue-20055-box-unsized-array.rs | 29 + tests/ui/issues/issue-20162.rs | 7 + tests/ui/issues/issue-20162.stderr | 16 + tests/ui/issues/issue-20174.rs | 7 + tests/ui/issues/issue-20186.rs | 16 + tests/ui/issues/issue-20225.rs | 22 + tests/ui/issues/issue-20225.stderr | 46 + tests/ui/issues/issue-20261.rs | 7 + tests/ui/issues/issue-20261.stderr | 9 + tests/ui/issues/issue-20313-rpass.rs | 11 + tests/ui/issues/issue-20313.rs | 6 + tests/ui/issues/issue-20313.stderr | 12 + tests/ui/issues/issue-20389.rs | 15 + tests/ui/issues/issue-20396.rs | 16 + tests/ui/issues/issue-20413.rs | 42 + tests/ui/issues/issue-20413.stderr | 73 + tests/ui/issues/issue-20414.rs | 21 + tests/ui/issues/issue-20427.rs | 88 + tests/ui/issues/issue-20433.rs | 8 + tests/ui/issues/issue-20433.stderr | 13 + tests/ui/issues/issue-20454.rs | 13 + tests/ui/issues/issue-20544.rs | 18 + tests/ui/issues/issue-20575.rs | 10 + tests/ui/issues/issue-20605.rs | 6 + tests/ui/issues/issue-20605.stderr | 16 + tests/ui/issues/issue-20616.rs | 44 + tests/ui/issues/issue-2063-resource.rs | 14 + tests/ui/issues/issue-2063.rs | 22 + tests/ui/issues/issue-20644.rs | 32 + tests/ui/issues/issue-20676.rs | 12 + tests/ui/issues/issue-20714.rs | 5 + tests/ui/issues/issue-20714.stderr | 20 + tests/ui/issues/issue-2074.rs | 16 + tests/ui/issues/issue-20763-1.rs | 29 + tests/ui/issues/issue-20763-2.rs | 24 + tests/ui/issues/issue-20772.rs | 5 + tests/ui/issues/issue-20772.stderr | 16 + tests/ui/issues/issue-20797.rs | 93 + tests/ui/issues/issue-20803.rs | 10 + tests/ui/issues/issue-20831-debruijn.rs | 39 + tests/ui/issues/issue-20831-debruijn.stderr | 27 + tests/ui/issues/issue-20847.rs | 12 + tests/ui/issues/issue-20939.rs | 6 + tests/ui/issues/issue-20939.stderr | 9 + tests/ui/issues/issue-20953.rs | 12 + tests/ui/issues/issue-20971.rs | 23 + tests/ui/issues/issue-21033.rs | 48 + tests/ui/issues/issue-21140.rs | 6 + tests/ui/issues/issue-21160.rs | 11 + tests/ui/issues/issue-21160.stderr | 17 + tests/ui/issues/issue-21174-2.rs | 13 + tests/ui/issues/issue-21174.rs | 11 + tests/ui/issues/issue-21174.stderr | 12 + tests/ui/issues/issue-21177.rs | 9 + tests/ui/issues/issue-21177.stderr | 16 + tests/ui/issues/issue-21202.rs | 15 + tests/ui/issues/issue-21202.stderr | 14 + tests/ui/issues/issue-21245.rs | 56 + tests/ui/issues/issue-21291.rs | 10 + tests/ui/issues/issue-21306.rs | 9 + tests/ui/issues/issue-21332.rs | 10 + tests/ui/issues/issue-21332.stderr | 15 + tests/ui/issues/issue-21361.rs | 11 + tests/ui/issues/issue-21384.rs | 21 + tests/ui/issues/issue-21400.rs | 56 + tests/ui/issues/issue-21402.rs | 12 + tests/ui/issues/issue-21449.rs | 6 + tests/ui/issues/issue-21449.stderr | 9 + tests/ui/issues/issue-2150.rs | 12 + tests/ui/issues/issue-2150.stderr | 16 + tests/ui/issues/issue-2151.rs | 4 + tests/ui/issues/issue-2151.stderr | 16 + tests/ui/issues/issue-21546.rs | 49 + tests/ui/issues/issue-21546.stderr | 69 + tests/ui/issues/issue-21554.rs | 6 + tests/ui/issues/issue-21554.stderr | 9 + tests/ui/issues/issue-21596.rs | 5 + tests/ui/issues/issue-21596.stderr | 15 + tests/ui/issues/issue-21600.rs | 18 + tests/ui/issues/issue-21600.stderr | 31 + tests/ui/issues/issue-21622.rs | 21 + tests/ui/issues/issue-21634.rs | 20 + tests/ui/issues/issue-21655.rs | 12 + tests/ui/issues/issue-2170-exe.rs | 9 + tests/ui/issues/issue-21701.rs | 15 + tests/ui/issues/issue-21701.stderr | 30 + tests/ui/issues/issue-21763.rs | 11 + tests/ui/issues/issue-21763.stderr | 20 + tests/ui/issues/issue-21837.rs | 10 + tests/ui/issues/issue-21837.stderr | 19 + tests/ui/issues/issue-21891.rs | 12 + tests/ui/issues/issue-2190-1.rs | 26 + tests/ui/issues/issue-21909.rs | 15 + tests/ui/issues/issue-21922.rs | 17 + tests/ui/issues/issue-21946.rs | 12 + tests/ui/issues/issue-21946.stderr | 9 + tests/ui/issues/issue-21950.rs | 13 + tests/ui/issues/issue-21950.stderr | 24 + tests/ui/issues/issue-21974.rs | 18 + tests/ui/issues/issue-21974.stderr | 17 + tests/ui/issues/issue-22008.rs | 9 + tests/ui/issues/issue-22034.rs | 11 + tests/ui/issues/issue-22034.stderr | 13 + tests/ui/issues/issue-22036.rs | 25 + tests/ui/issues/issue-2214.rs | 41 + tests/ui/issues/issue-22258.rs | 10 + tests/ui/issues/issue-22289.rs | 3 + tests/ui/issues/issue-22289.stderr | 14 + tests/ui/issues/issue-22312.rs | 17 + tests/ui/issues/issue-22312.stderr | 14 + tests/ui/issues/issue-22346.rs | 11 + tests/ui/issues/issue-22356.rs | 34 + tests/ui/issues/issue-22370.rs | 6 + tests/ui/issues/issue-22370.stderr | 14 + tests/ui/issues/issue-22384.rs | 8 + tests/ui/issues/issue-22384.stderr | 9 + tests/ui/issues/issue-22403.rs | 6 + tests/ui/issues/issue-22426.rs | 9 + tests/ui/issues/issue-22434.rs | 8 + tests/ui/issues/issue-22434.stderr | 12 + tests/ui/issues/issue-22468.rs | 9 + tests/ui/issues/issue-22468.stderr | 13 + tests/ui/issues/issue-22471.rs | 7 + tests/ui/issues/issue-22536-copy-mustnt-zero.rs | 28 + tests/ui/issues/issue-22577.rs | 26 + tests/ui/issues/issue-22599.rs | 10 + tests/ui/issues/issue-22599.stderr | 14 + tests/ui/issues/issue-22603.rs | 15 + tests/ui/issues/issue-22629.rs | 14 + tests/ui/issues/issue-22638.polonius.stderr | 15 + tests/ui/issues/issue-22638.rs | 63 + tests/ui/issues/issue-22638.stderr | 14 + tests/ui/issues/issue-22644.rs | 35 + tests/ui/issues/issue-22644.stderr | 123 + tests/ui/issues/issue-22673.rs | 7 + tests/ui/issues/issue-22684.rs | 18 + tests/ui/issues/issue-22684.stderr | 11 + tests/ui/issues/issue-22706.rs | 3 + tests/ui/issues/issue-22706.stderr | 11 + tests/ui/issues/issue-22777.rs | 48 + tests/ui/issues/issue-22781.rs | 15 + tests/ui/issues/issue-22789.rs | 8 + tests/ui/issues/issue-2281-part1.rs | 1 + tests/ui/issues/issue-2281-part1.stderr | 9 + tests/ui/issues/issue-22814.rs | 13 + tests/ui/issues/issue-2284.rs | 14 + tests/ui/issues/issue-22864-1.rs | 7 + tests/ui/issues/issue-22864-2.rs | 7 + tests/ui/issues/issue-22872.rs | 24 + tests/ui/issues/issue-22872.stderr | 24 + tests/ui/issues/issue-22874.rs | 10 + tests/ui/issues/issue-22874.stderr | 12 + tests/ui/issues/issue-2288.rs | 33 + tests/ui/issues/issue-22886.rs | 21 + tests/ui/issues/issue-22886.stderr | 9 + tests/ui/issues/issue-22894.rs | 4 + tests/ui/issues/issue-22933-1.rs | 23 + tests/ui/issues/issue-22933-2.rs | 8 + tests/ui/issues/issue-22933-2.stderr | 15 + tests/ui/issues/issue-22992-2.rs | 18 + tests/ui/issues/issue-22992.rs | 75 + tests/ui/issues/issue-23024.rs | 12 + tests/ui/issues/issue-23024.stderr | 30 + tests/ui/issues/issue-23036.rs | 10 + tests/ui/issues/issue-23041.rs | 7 + tests/ui/issues/issue-23041.stderr | 14 + tests/ui/issues/issue-23046.rs | 20 + tests/ui/issues/issue-23046.stderr | 14 + tests/ui/issues/issue-23073.rs | 9 + tests/ui/issues/issue-23073.stderr | 14 + tests/ui/issues/issue-2311-2.rs | 26 + tests/ui/issues/issue-2311.rs | 11 + tests/ui/issues/issue-2312.rs | 16 + tests/ui/issues/issue-23122-1.rs | 14 + tests/ui/issues/issue-23122-1.stderr | 9 + tests/ui/issues/issue-23122-2.rs | 15 + tests/ui/issues/issue-23122-2.stderr | 19 + tests/ui/issues/issue-2316-c.rs | 12 + tests/ui/issues/issue-23173.rs | 13 + tests/ui/issues/issue-23173.stderr | 39 + tests/ui/issues/issue-23189.rs | 5 + tests/ui/issues/issue-23189.stderr | 9 + tests/ui/issues/issue-23217.rs | 5 + tests/ui/issues/issue-23217.stderr | 14 + tests/ui/issues/issue-23253.rs | 6 + tests/ui/issues/issue-23253.stderr | 9 + tests/ui/issues/issue-23261.rs | 61 + tests/ui/issues/issue-23281.rs | 12 + tests/ui/issues/issue-23281.stderr | 23 + tests/ui/issues/issue-23302-1.rs | 7 + tests/ui/issues/issue-23302-1.stderr | 16 + tests/ui/issues/issue-23302-2.rs | 8 + tests/ui/issues/issue-23302-2.stderr | 16 + tests/ui/issues/issue-23302-3.rs | 5 + tests/ui/issues/issue-23302-3.stderr | 21 + tests/ui/issues/issue-23304-1.rs | 25 + tests/ui/issues/issue-23304-2.rs | 13 + tests/ui/issues/issue-23311.rs | 11 + tests/ui/issues/issue-23336.rs | 11 + tests/ui/issues/issue-23354-2.rs | 9 + tests/ui/issues/issue-23354.rs | 8 + tests/ui/issues/issue-23406.rs | 15 + tests/ui/issues/issue-23433.rs | 13 + tests/ui/issues/issue-23442.rs | 23 + tests/ui/issues/issue-23477.rs | 16 + tests/ui/issues/issue-23485.rs | 50 + tests/ui/issues/issue-23491.rs | 8 + tests/ui/issues/issue-23543.rs | 11 + tests/ui/issues/issue-23543.stderr | 9 + tests/ui/issues/issue-23544.rs | 9 + tests/ui/issues/issue-23544.stderr | 9 + tests/ui/issues/issue-23550.rs | 22 + tests/ui/issues/issue-23589.rs | 5 + tests/ui/issues/issue-23589.stderr | 26 + tests/ui/issues/issue-23611-enum-swap-in-drop.rs | 259 + tests/ui/issues/issue-23649-1.rs | 12 + tests/ui/issues/issue-23649-2.rs | 10 + tests/ui/issues/issue-23649-3.rs | 5 + tests/ui/issues/issue-23699.rs | 14 + tests/ui/issues/issue-23781.rs | 29 + tests/ui/issues/issue-2380-b.rs | 10 + tests/ui/issues/issue-23808.rs | 59 + tests/ui/issues/issue-2383.rs | 9 + tests/ui/issues/issue-23891.rs | 11 + tests/ui/issues/issue-23898.rs | 11 + tests/ui/issues/issue-23958.rs | 13 + tests/ui/issues/issue-23966.rs | 4 + tests/ui/issues/issue-23966.stderr | 15 + tests/ui/issues/issue-23992.rs | 19 + tests/ui/issues/issue-24013.rs | 7 + tests/ui/issues/issue-24013.stderr | 9 + tests/ui/issues/issue-24036.rs | 16 + tests/ui/issues/issue-24036.stderr | 28 + tests/ui/issues/issue-24086.rs | 23 + tests/ui/issues/issue-2414-c.rs | 9 + tests/ui/issues/issue-24161.rs | 11 + tests/ui/issues/issue-24227.rs | 18 + tests/ui/issues/issue-2428.rs | 14 + tests/ui/issues/issue-24308.rs | 17 + tests/ui/issues/issue-24322.rs | 9 + tests/ui/issues/issue-24322.stderr | 14 + tests/ui/issues/issue-24352.rs | 4 + tests/ui/issues/issue-24352.stderr | 20 + tests/ui/issues/issue-24353.rs | 8 + tests/ui/issues/issue-24357.rs | 11 + tests/ui/issues/issue-24357.stderr | 17 + tests/ui/issues/issue-24363.rs | 6 + tests/ui/issues/issue-24363.stderr | 18 + tests/ui/issues/issue-24365.rs | 19 + tests/ui/issues/issue-24365.stderr | 21 + tests/ui/issues/issue-24389.rs | 11 + tests/ui/issues/issue-24424.rs | 7 + tests/ui/issues/issue-24424.stderr | 15 + tests/ui/issues/issue-24434.rs | 7 + tests/ui/issues/issue-24446.rs | 7 + tests/ui/issues/issue-24446.stderr | 20 + tests/ui/issues/issue-2445-b.rs | 31 + tests/ui/issues/issue-2445.rs | 29 + tests/ui/issues/issue-24533.rs | 24 + tests/ui/issues/issue-24589.rs | 17 + tests/ui/issues/issue-2463.rs | 25 + tests/ui/issues/issue-24682.rs | 21 + tests/ui/issues/issue-24682.stderr | 22 + .../auxiliary/issue-24687-lib.rs | 10 + .../auxiliary/issue-24687-mbcs-in-comments.rs | 27 + .../ui/issues/issue-24687-embed-debuginfo/main.rs | 14 + .../ui/issues/issue-2470-bounds-check-overflow.rs | 27 + tests/ui/issues/issue-2472.rs | 14 + tests/ui/issues/issue-24779.rs | 4 + tests/ui/issues/issue-24819.rs | 11 + tests/ui/issues/issue-24819.stderr | 19 + tests/ui/issues/issue-2487-a.rs | 32 + tests/ui/issues/issue-24945-repeat-dash-opts.rs | 10 + tests/ui/issues/issue-24947.rs | 25 + tests/ui/issues/issue-24954.rs | 13 + tests/ui/issues/issue-2502.rs | 24 + tests/ui/issues/issue-25076.rs | 11 + tests/ui/issues/issue-25076.stderr | 17 + tests/ui/issues/issue-25089.rs | 34 + tests/ui/issues/issue-25145.rs | 13 + tests/ui/issues/issue-25180.rs | 7 + tests/ui/issues/issue-25185.rs | 13 + tests/ui/issues/issue-2526-a.rs | 11 + tests/ui/issues/issue-25279.rs | 16 + tests/ui/issues/issue-25343.rs | 22 + tests/ui/issues/issue-25368.rs | 14 + tests/ui/issues/issue-25368.stderr | 14 + tests/ui/issues/issue-25386.rs | 27 + tests/ui/issues/issue-25386.stderr | 14 + tests/ui/issues/issue-25394.rs | 6 + tests/ui/issues/issue-25439.rs | 9 + tests/ui/issues/issue-25439.stderr | 19 + tests/ui/issues/issue-25467.rs | 12 + tests/ui/issues/issue-25497.rs | 19 + tests/ui/issues/issue-2550.rs | 22 + tests/ui/issues/issue-25515.rs | 20 + tests/ui/issues/issue-25549-multiple-drop.rs | 33 + tests/ui/issues/issue-25579.rs | 20 + tests/ui/issues/issue-25679.rs | 20 + tests/ui/issues/issue-25693.rs | 22 + tests/ui/issues/issue-25746-bool-transmute.rs | 11 + tests/ui/issues/issue-25757.rs | 18 + tests/ui/issues/issue-25810.rs | 28 + tests/ui/issues/issue-2590.rs | 15 + tests/ui/issues/issue-2590.stderr | 9 + tests/ui/issues/issue-25901.rs | 14 + tests/ui/issues/issue-25901.stderr | 15 + tests/ui/issues/issue-26056.rs | 22 + tests/ui/issues/issue-26056.stderr | 17 + tests/ui/issues/issue-26093.rs | 12 + tests/ui/issues/issue-26093.stderr | 32 + tests/ui/issues/issue-26094.rs | 13 + tests/ui/issues/issue-26094.stderr | 22 + tests/ui/issues/issue-26095.rs | 23 + tests/ui/issues/issue-2611-3.rs | 19 + tests/ui/issues/issue-26127.rs | 12 + tests/ui/issues/issue-26186.rs | 62 + tests/ui/issues/issue-26205.rs | 31 + tests/ui/issues/issue-26217.rs | 10 + tests/ui/issues/issue-26217.stderr | 16 + tests/ui/issues/issue-26237.rs | 12 + tests/ui/issues/issue-26237.stderr | 15 + tests/ui/issues/issue-26262.rs | 22 + tests/ui/issues/issue-26262.stderr | 15 + tests/ui/issues/issue-2631-b.rs | 17 + tests/ui/issues/issue-2642.rs | 10 + tests/ui/issues/issue-26468.rs | 29 + tests/ui/issues/issue-26472.rs | 13 + tests/ui/issues/issue-26472.stderr | 20 + tests/ui/issues/issue-26484.rs | 12 + tests/ui/issues/issue-26614.rs | 14 + tests/ui/issues/issue-26619.rs | 22 + tests/ui/issues/issue-26619.stderr | 11 + tests/ui/issues/issue-26641.rs | 6 + tests/ui/issues/issue-26646.rs | 12 + tests/ui/issues/issue-26655.rs | 26 + tests/ui/issues/issue-26709.rs | 17 + tests/ui/issues/issue-26802.rs | 14 + tests/ui/issues/issue-26805.rs | 6 + tests/ui/issues/issue-26812.rs | 6 + tests/ui/issues/issue-26812.stderr | 9 + tests/ui/issues/issue-26905-rpass.rs | 21 + tests/ui/issues/issue-26905.rs | 23 + tests/ui/issues/issue-26905.stderr | 12 + tests/ui/issues/issue-26948.rs | 6 + tests/ui/issues/issue-26948.stderr | 9 + tests/ui/issues/issue-26997.rs | 15 + tests/ui/issues/issue-27008.rs | 7 + tests/ui/issues/issue-27008.stderr | 9 + tests/ui/issues/issue-27033.rs | 12 + tests/ui/issues/issue-27033.stderr | 21 + tests/ui/issues/issue-27042.rs | 17 + tests/ui/issues/issue-27042.stderr | 48 + .../ui/issues/issue-27054-primitive-binary-ops.rs | 5 + tests/ui/issues/issue-27078.rs | 9 + tests/ui/issues/issue-27078.stderr | 19 + tests/ui/issues/issue-2708.rs | 30 + tests/ui/issues/issue-27105.rs | 15 + tests/ui/issues/issue-2723-b.rs | 11 + tests/ui/issues/issue-27240.rs | 27 + tests/ui/issues/issue-27268.rs | 4 + tests/ui/issues/issue-27281.rs | 17 + tests/ui/issues/issue-27340.rs | 6 + tests/ui/issues/issue-27340.stderr | 14 + tests/ui/issues/issue-2735-2.rs | 27 + tests/ui/issues/issue-2735-3.rs | 27 + tests/ui/issues/issue-2735.rs | 22 + tests/ui/issues/issue-27401-dropflag-reinit.rs | 26 + tests/ui/issues/issue-27433.fixed | 7 + tests/ui/issues/issue-27433.rs | 7 + tests/ui/issues/issue-27433.stderr | 11 + tests/ui/issues/issue-2748-a.rs | 17 + tests/ui/issues/issue-27583.rs | 47 + tests/ui/issues/issue-27592.rs | 19 + tests/ui/issues/issue-27592.stderr | 22 + tests/ui/issues/issue-2761.rs | 7 + tests/ui/issues/issue-27639.rs | 11 + tests/ui/issues/issue-27697.rs | 21 + tests/ui/issues/issue-27815.rs | 12 + tests/ui/issues/issue-27815.stderr | 27 + tests/ui/issues/issue-27842.rs | 11 + tests/ui/issues/issue-27842.stderr | 17 + tests/ui/issues/issue-27859.rs | 20 + tests/ui/issues/issue-27889.rs | 23 + tests/ui/issues/issue-27901.rs | 11 + tests/ui/issues/issue-27942.rs | 14 + tests/ui/issues/issue-27942.stderr | 41 + tests/ui/issues/issue-27949.rs | 41 + tests/ui/issues/issue-27997.rs | 37 + tests/ui/issues/issue-2804-2.rs | 12 + tests/ui/issues/issue-28105.rs | 8 + tests/ui/issues/issue-28105.stderr | 15 + tests/ui/issues/issue-28109.rs | 12 + tests/ui/issues/issue-28109.stderr | 15 + tests/ui/issues/issue-28181.rs | 6 + tests/ui/issues/issue-2823.rs | 14 + tests/ui/issues/issue-2823.stderr | 16 + tests/ui/issues/issue-28279.rs | 21 + tests/ui/issues/issue-28344.rs | 15 + tests/ui/issues/issue-28344.stderr | 61 + tests/ui/issues/issue-28433.rs | 12 + tests/ui/issues/issue-28433.stderr | 15 + tests/ui/issues/issue-28472.rs | 14 + tests/ui/issues/issue-28472.stderr | 27 + tests/ui/issues/issue-2848.rs | 17 + tests/ui/issues/issue-2848.stderr | 11 + tests/ui/issues/issue-2849.rs | 8 + tests/ui/issues/issue-2849.stderr | 11 + tests/ui/issues/issue-28498-must-work-ex1.rs | 18 + tests/ui/issues/issue-28498-must-work-ex2.rs | 20 + tests/ui/issues/issue-28498-ugeh-ex1.rs | 27 + tests/ui/issues/issue-28550.rs | 16 + tests/ui/issues/issue-28561.rs | 73 + tests/ui/issues/issue-28568.rs | 12 + tests/ui/issues/issue-28568.stderr | 12 + tests/ui/issues/issue-28586.rs | 7 + tests/ui/issues/issue-28586.stderr | 9 + tests/ui/issues/issue-28600.rs | 15 + tests/ui/issues/issue-28625.rs | 22 + tests/ui/issues/issue-28625.stderr | 12 + tests/ui/issues/issue-28776.mir.stderr | 11 + tests/ui/issues/issue-28776.rs | 9 + tests/ui/issues/issue-28776.thir.stderr | 11 + tests/ui/issues/issue-28777.rs | 22 + tests/ui/issues/issue-28822.rs | 7 + tests/ui/issues/issue-28828.rs | 18 + tests/ui/issues/issue-28839.rs | 15 + tests/ui/issues/issue-28936.rs | 27 + tests/ui/issues/issue-2895.rs | 28 + tests/ui/issues/issue-28971.rs | 16 + tests/ui/issues/issue-28971.stderr | 15 + tests/ui/issues/issue-28983.rs | 22 + tests/ui/issues/issue-28992-empty.rs | 16 + tests/ui/issues/issue-28992-empty.stderr | 16 + tests/ui/issues/issue-28999.rs | 11 + tests/ui/issues/issue-29030.rs | 9 + tests/ui/issues/issue-29037.rs | 24 + tests/ui/issues/issue-2904.rs | 79 + tests/ui/issues/issue-29048.rs | 12 + tests/ui/issues/issue-29053.rs | 12 + tests/ui/issues/issue-29071-2.rs | 32 + tests/ui/issues/issue-29071.rs | 16 + tests/ui/issues/issue-29092.rs | 26 + tests/ui/issues/issue-29147-rpass.rs | 28 + tests/ui/issues/issue-29147.rs | 23 + tests/ui/issues/issue-29147.stderr | 17 + tests/ui/issues/issue-29181.rs | 9 + tests/ui/issues/issue-29181.stderr | 21 + tests/ui/issues/issue-29265.rs | 10 + tests/ui/issues/issue-29276.rs | 5 + tests/ui/issues/issue-2935.rs | 28 + tests/ui/issues/issue-29466.rs | 3603 +++++++ tests/ui/issues/issue-29485.rs | 19 + tests/ui/issues/issue-2951.rs | 11 + tests/ui/issues/issue-2951.stderr | 20 + tests/ui/issues/issue-29516.rs | 20 + tests/ui/issues/issue-29522.rs | 17 + tests/ui/issues/issue-29540.rs | 492 + tests/ui/issues/issue-29663.rs | 56 + tests/ui/issues/issue-29668.rs | 16 + tests/ui/issues/issue-29710.rs | 11 + tests/ui/issues/issue-29723.rs | 22 + tests/ui/issues/issue-29723.stderr | 36 + tests/ui/issues/issue-29740.rs | 317 + tests/ui/issues/issue-29743.rs | 7 + tests/ui/issues/issue-29746.rs | 36 + tests/ui/issues/issue-29798.rs | 11 + tests/ui/issues/issue-29821.rs | 19 + tests/ui/issues/issue-29857.rs | 19 + tests/ui/issues/issue-29861.rs | 20 + tests/ui/issues/issue-29861.stderr | 9 + tests/ui/issues/issue-2989.rs | 36 + tests/ui/issues/issue-29948.rs | 40 + tests/ui/issues/issue-2995.rs | 5 + tests/ui/issues/issue-2995.stderr | 15 + tests/ui/issues/issue-30007.rs | 7 + tests/ui/issues/issue-30007.stderr | 13 + tests/ui/issues/issue-30018-panic.rs | 26 + tests/ui/issues/issue-3008-1.rs | 12 + tests/ui/issues/issue-3008-1.stderr | 17 + tests/ui/issues/issue-3008-2.rs | 6 + tests/ui/issues/issue-3008-2.stderr | 14 + tests/ui/issues/issue-3008-3.rs | 10 + tests/ui/issues/issue-3008-3.stderr | 14 + tests/ui/issues/issue-30081.rs | 15 + tests/ui/issues/issue-3012-2.rs | 13 + tests/ui/issues/issue-30123.rs | 9 + tests/ui/issues/issue-30123.stderr | 12 + tests/ui/issues/issue-3021-b.rs | 14 + tests/ui/issues/issue-3021-b.stderr | 11 + tests/ui/issues/issue-3021-d.rs | 28 + tests/ui/issues/issue-3021-d.stderr | 19 + tests/ui/issues/issue-30236.rs | 7 + tests/ui/issues/issue-30236.stderr | 9 + tests/ui/issues/issue-30255.rs | 24 + tests/ui/issues/issue-30255.stderr | 39 + tests/ui/issues/issue-3026.rs | 11 + tests/ui/issues/issue-3029.rs | 14 + tests/ui/issues/issue-3037.rs | 16 + tests/ui/issues/issue-30371.rs | 10 + tests/ui/issues/issue-3038.rs | 26 + tests/ui/issues/issue-3038.stderr | 21 + tests/ui/issues/issue-30380.rs | 36 + tests/ui/issues/issue-30438-a.rs | 23 + tests/ui/issues/issue-30438-a.stderr | 12 + tests/ui/issues/issue-30438-b.rs | 24 + tests/ui/issues/issue-30438-b.stderr | 12 + tests/ui/issues/issue-30438-c.rs | 21 + tests/ui/issues/issue-30438-c.stderr | 17 + tests/ui/issues/issue-30490.rs | 102 + tests/ui/issues/issue-3052.rs | 13 + tests/ui/issues/issue-30530.rs | 28 + tests/ui/issues/issue-30589.rs | 9 + tests/ui/issues/issue-30589.stderr | 9 + tests/ui/issues/issue-30615.rs | 5 + tests/ui/issues/issue-30756.rs | 7 + tests/ui/issues/issue-30891.rs | 10 + tests/ui/issues/issue-3091.rs | 7 + tests/ui/issues/issue-3099-a.rs | 5 + tests/ui/issues/issue-3099-a.stderr | 14 + tests/ui/issues/issue-3099-b.rs | 5 + tests/ui/issues/issue-3099-b.stderr | 14 + tests/ui/issues/issue-3099.rs | 11 + tests/ui/issues/issue-3099.stderr | 14 + tests/ui/issues/issue-31011.rs | 29 + tests/ui/issues/issue-31011.stderr | 17 + tests/ui/issues/issue-3109.rs | 4 + tests/ui/issues/issue-3121.rs | 24 + tests/ui/issues/issue-31260.rs | 15 + tests/ui/issues/issue-31267-additional.rs | 20 + tests/ui/issues/issue-31267.rs | 14 + tests/ui/issues/issue-31299.rs | 35 + tests/ui/issues/issue-3136-b.rs | 8 + tests/ui/issues/issue-3149.rs | 26 + tests/ui/issues/issue-31511.rs | 6 + tests/ui/issues/issue-31511.stderr | 9 + tests/ui/issues/issue-3154.rs | 11 + tests/ui/issues/issue-3154.stderr | 11 + tests/ui/issues/issue-31702.rs | 10 + tests/ui/issues/issue-31769.rs | 4 + tests/ui/issues/issue-31769.stderr | 16 + tests/ui/issues/issue-31776.rs | 55 + tests/ui/issues/issue-31910.rs | 11 + tests/ui/issues/issue-31910.stderr | 9 + tests/ui/issues/issue-32004.rs | 19 + tests/ui/issues/issue-32004.stderr | 32 + tests/ui/issues/issue-32008.rs | 28 + tests/ui/issues/issue-32086.rs | 7 + tests/ui/issues/issue-32086.stderr | 21 + tests/ui/issues/issue-32122-1.fixed | 17 + tests/ui/issues/issue-32122-1.rs | 17 + tests/ui/issues/issue-32122-1.stderr | 18 + tests/ui/issues/issue-32122-2.fixed | 28 + tests/ui/issues/issue-32122-2.rs | 28 + tests/ui/issues/issue-32122-2.stderr | 18 + tests/ui/issues/issue-3214.rs | 11 + tests/ui/issues/issue-3214.stderr | 28 + tests/ui/issues/issue-3220.rs | 25 + tests/ui/issues/issue-32292.rs | 9 + tests/ui/issues/issue-32323.rs | 8 + tests/ui/issues/issue-32323.stderr | 18 + tests/ui/issues/issue-32324.rs | 24 + tests/ui/issues/issue-32326.rs | 10 + tests/ui/issues/issue-32326.stderr | 16 + tests/ui/issues/issue-32377.rs | 19 + tests/ui/issues/issue-32377.stderr | 12 + tests/ui/issues/issue-32389.rs | 11 + tests/ui/issues/issue-32518.rs | 13 + tests/ui/issues/issue-32655.rs | 19 + tests/ui/issues/issue-32655.stderr | 25 + tests/ui/issues/issue-32709.rs | 8 + tests/ui/issues/issue-32709.stderr | 17 + tests/ui/issues/issue-32782.rs | 13 + tests/ui/issues/issue-32782.stderr | 15 + tests/ui/issues/issue-32797.rs | 13 + tests/ui/issues/issue-32805.rs | 10 + tests/ui/issues/issue-3290.rs | 8 + tests/ui/issues/issue-32950.rs | 9 + tests/ui/issues/issue-32950.stderr | 17 + tests/ui/issues/issue-32995-2.rs | 13 + tests/ui/issues/issue-32995-2.stderr | 21 + tests/ui/issues/issue-32995.rs | 24 + tests/ui/issues/issue-32995.stderr | 45 + tests/ui/issues/issue-33096.rs | 19 + tests/ui/issues/issue-33187.rs | 23 + tests/ui/issues/issue-33202.rs | 9 + tests/ui/issues/issue-33241.rs | 12 + tests/ui/issues/issue-33287.rs | 10 + tests/ui/issues/issue-33293.rs | 6 + tests/ui/issues/issue-33293.stderr | 9 + tests/ui/issues/issue-33387.rs | 32 + tests/ui/issues/issue-3344.rs | 7 + tests/ui/issues/issue-3344.stderr | 11 + tests/ui/issues/issue-33461.rs | 28 + tests/ui/issues/issue-33504.rs | 9 + tests/ui/issues/issue-33504.stderr | 16 + tests/ui/issues/issue-33525.rs | 5 + tests/ui/issues/issue-33525.stderr | 22 + tests/ui/issues/issue-33571.rs | 7 + tests/ui/issues/issue-33571.stderr | 26 + tests/ui/issues/issue-33687.rs | 17 + tests/ui/issues/issue-33770.rs | 94 + tests/ui/issues/issue-3389.rs | 26 + tests/ui/issues/issue-33903.rs | 10 + tests/ui/issues/issue-33941.rs | 9 + tests/ui/issues/issue-33941.stderr | 42 + tests/ui/issues/issue-33992.rs | 32 + tests/ui/issues/issue-34047.rs | 8 + tests/ui/issues/issue-34047.stderr | 12 + tests/ui/issues/issue-34074.rs | 10 + tests/ui/issues/issue-34209.rs | 11 + tests/ui/issues/issue-34209.stderr | 12 + tests/ui/issues/issue-34229.rs | 5 + tests/ui/issues/issue-34229.stderr | 18 + tests/ui/issues/issue-3424.rs | 20 + tests/ui/issues/issue-3429.rs | 8 + tests/ui/issues/issue-34334.rs | 8 + tests/ui/issues/issue-34334.stderr | 38 + tests/ui/issues/issue-34349.rs | 22 + tests/ui/issues/issue-34349.stderr | 22 + tests/ui/issues/issue-34373.rs | 11 + tests/ui/issues/issue-34373.stderr | 27 + tests/ui/issues/issue-34418.rs | 19 + tests/ui/issues/issue-34427.rs | 17 + tests/ui/issues/issue-3447.rs | 32 + tests/ui/issues/issue-34503.rs | 11 + tests/ui/issues/issue-34569.rs | 18 + tests/ui/issues/issue-34571.rs | 11 + tests/ui/issues/issue-34721.fixed | 34 + tests/ui/issues/issue-34721.rs | 34 + tests/ui/issues/issue-34721.stderr | 28 + tests/ui/issues/issue-34751.rs | 11 + tests/ui/issues/issue-3477.rs | 5 + tests/ui/issues/issue-3477.stderr | 11 + tests/ui/issues/issue-34780.rs | 11 + tests/ui/issues/issue-34796.rs | 28 + tests/ui/issues/issue-34839.rs | 19 + tests/ui/issues/issue-34932.rs | 11 + tests/ui/issues/issue-3500.rs | 10 + tests/ui/issues/issue-35139.rs | 26 + tests/ui/issues/issue-35139.stderr | 9 + tests/ui/issues/issue-3521-2.fixed | 9 + tests/ui/issues/issue-3521-2.rs | 9 + tests/ui/issues/issue-3521-2.stderr | 11 + tests/ui/issues/issue-35241.rs | 5 + tests/ui/issues/issue-35241.stderr | 21 + tests/ui/issues/issue-35423.rs | 9 + tests/ui/issues/issue-3556.rs | 36 + tests/ui/issues/issue-35570.rs | 29 + tests/ui/issues/issue-35570.stderr | 19 + tests/ui/issues/issue-3559.rs | 18 + tests/ui/issues/issue-35600.rs | 18 + tests/ui/issues/issue-3563-3.rs | 180 + tests/ui/issues/issue-3574.rs | 14 + tests/ui/issues/issue-35815.rs | 15 + tests/ui/issues/issue-35976.rs | 24 + tests/ui/issues/issue-35976.unimported.stderr | 16 + tests/ui/issues/issue-35988.rs | 6 + tests/ui/issues/issue-35988.stderr | 21 + tests/ui/issues/issue-36023.rs | 24 + .../issues/issue-36036-associated-type-layout.rs | 27 + tests/ui/issues/issue-36075.rs | 14 + tests/ui/issues/issue-3609.rs | 30 + tests/ui/issues/issue-36116.rs | 25 + tests/ui/issues/issue-36260.rs | 13 + tests/ui/issues/issue-36278-prefix-nesting.rs | 20 + tests/ui/issues/issue-36299.rs | 5 + tests/ui/issues/issue-36299.stderr | 20 + tests/ui/issues/issue-36379.rs | 5 + tests/ui/issues/issue-36400.rs | 6 + tests/ui/issues/issue-36400.stderr | 14 + tests/ui/issues/issue-36401.rs | 16 + tests/ui/issues/issue-36474.rs | 31 + tests/ui/issues/issue-3656.rs | 27 + tests/ui/issues/issue-3668-2.fixed | 8 + tests/ui/issues/issue-3668-2.rs | 8 + tests/ui/issues/issue-3668-2.stderr | 11 + tests/ui/issues/issue-3668.rs | 14 + tests/ui/issues/issue-3668.stderr | 11 + .../issues/issue-36744-bitcast-args-if-needed.rs | 23 + tests/ui/issues/issue-36744-without-calls.rs | 13 + tests/ui/issues/issue-36786-resolve-call.rs | 8 + tests/ui/issues/issue-36792.rs | 7 + tests/ui/issues/issue-3680.rs | 9 + tests/ui/issues/issue-3680.stderr | 18 + tests/ui/issues/issue-36816.rs | 7 + tests/ui/issues/issue-36836.rs | 15 + tests/ui/issues/issue-36836.stderr | 9 + tests/ui/issues/issue-36839.rs | 21 + tests/ui/issues/issue-36856.rs | 16 + tests/ui/issues/issue-36936.rs | 26 + tests/ui/issues/issue-36954.rs | 8 + tests/ui/issues/issue-3702-2.rs | 20 + tests/ui/issues/issue-3702-2.stderr | 28 + tests/ui/issues/issue-3702.rs | 13 + tests/ui/issues/issue-37051.rs | 18 + tests/ui/issues/issue-3707.rs | 18 + tests/ui/issues/issue-3707.stderr | 19 + tests/ui/issues/issue-37109.rs | 16 + tests/ui/issues/issue-37131.rs | 9 + tests/ui/issues/issue-37131.stderr | 11 + tests/ui/issues/issue-37291/auxiliary/lib.rs | 42 + tests/ui/issues/issue-37291/main.rs | 21 + .../issue-37311.polonius.stderr | 15 + .../issue-37311-type-length-limit/issue-37311.rs | 23 + .../issue-37311.stderr | 15 + tests/ui/issues/issue-3743.rs | 55 + tests/ui/issues/issue-37510.rs | 14 + tests/ui/issues/issue-3753.rs | 32 + tests/ui/issues/issue-37534.rs | 6 + tests/ui/issues/issue-37534.stderr | 29 + tests/ui/issues/issue-37576.rs | 45 + tests/ui/issues/issue-37576.stderr | 51 + tests/ui/issues/issue-37598.rs | 11 + tests/ui/issues/issue-3763.rs | 29 + tests/ui/issues/issue-3763.stderr | 40 + tests/ui/issues/issue-37665.rs | 10 + tests/ui/issues/issue-37665.stderr | 11 + tests/ui/issues/issue-37686.rs | 7 + tests/ui/issues/issue-37725.rs | 12 + tests/ui/issues/issue-37733.rs | 7 + tests/ui/issues/issue-3779.rs | 8 + tests/ui/issues/issue-3779.stderr | 17 + tests/ui/issues/issue-37884.rs | 14 + tests/ui/issues/issue-37884.stderr | 22 + tests/ui/issues/issue-3794.rs | 32 + tests/ui/issues/issue-38160.rs | 19 + tests/ui/issues/issue-38190.rs | 15 + tests/ui/issues/issue-38226.rs | 15 + tests/ui/issues/issue-38381.rs | 7 + tests/ui/issues/issue-38412.rs | 10 + tests/ui/issues/issue-38412.stderr | 9 + tests/ui/issues/issue-38437.rs | 46 + tests/ui/issues/issue-38458.rs | 5 + tests/ui/issues/issue-38458.stderr | 9 + tests/ui/issues/issue-3847.rs | 13 + tests/ui/issues/issue-38556.rs | 13 + tests/ui/issues/issue-38727.rs | 13 + tests/ui/issues/issue-3874.rs | 12 + tests/ui/issues/issue-38763.rs | 13 + tests/ui/issues/issue-3878.rs | 9 + tests/ui/issues/issue-38821.rs | 33 + tests/ui/issues/issue-38821.stderr | 22 + tests/ui/issues/issue-38857.rs | 5 + tests/ui/issues/issue-38857.stderr | 19 + .../issues/issue-38875/auxiliary/issue-38875-b.rs | 1 + tests/ui/issues/issue-38875/issue-38875.rs | 8 + tests/ui/issues/issue-3888-2.rs | 9 + tests/ui/issues/issue-38919.rs | 5 + tests/ui/issues/issue-38919.stderr | 11 + tests/ui/issues/issue-38942.rs | 17 + tests/ui/issues/issue-3895.rs | 11 + tests/ui/issues/issue-38954.rs | 4 + tests/ui/issues/issue-38954.stderr | 16 + tests/ui/issues/issue-38987.rs | 4 + tests/ui/issues/issue-39089.rs | 5 + tests/ui/issues/issue-39175.rs | 16 + tests/ui/issues/issue-39175.stderr | 15 + tests/ui/issues/issue-39211.rs | 13 + tests/ui/issues/issue-39211.stderr | 10 + tests/ui/issues/issue-39292.rs | 17 + tests/ui/issues/issue-39367.rs | 42 + tests/ui/issues/issue-39467.rs | 11 + tests/ui/issues/issue-39548.rs | 6 + tests/ui/issues/issue-39687.rs | 6 + tests/ui/issues/issue-39687.stderr | 9 + tests/ui/issues/issue-39709.rs | 5 + tests/ui/issues/issue-3979-2.rs | 18 + tests/ui/issues/issue-3979-generics.rs | 36 + tests/ui/issues/issue-3979-xcrate.rs | 25 + tests/ui/issues/issue-3979.rs | 34 + tests/ui/issues/issue-39808.rs | 17 + tests/ui/issues/issue-39827.rs | 34 + tests/ui/issues/issue-39848.rs | 9 + tests/ui/issues/issue-39848.stderr | 25 + tests/ui/issues/issue-3991.rs | 16 + tests/ui/issues/issue-3993.rs | 10 + tests/ui/issues/issue-3993.stderr | 15 + tests/ui/issues/issue-39970.rs | 21 + tests/ui/issues/issue-39970.stderr | 23 + tests/ui/issues/issue-39984.rs | 14 + tests/ui/issues/issue-40000.rs | 9 + tests/ui/issues/issue-40000.stderr | 21 + tests/ui/issues/issue-40003.rs | 178 + tests/ui/issues/issue-40085.rs | 13 + tests/ui/issues/issue-40136.rs | 15 + tests/ui/issues/issue-40235.rs | 8 + tests/ui/issues/issue-4025.rs | 25 + tests/ui/issues/issue-40288-2.rs | 31 + tests/ui/issues/issue-40288-2.stderr | 21 + tests/ui/issues/issue-40288.rs | 20 + tests/ui/issues/issue-40288.stderr | 15 + tests/ui/issues/issue-40350.rs | 10 + .../issues/issue-40402-ref-hints/issue-40402-1.rs | 10 + .../issue-40402-ref-hints/issue-40402-1.stderr | 14 + .../issues/issue-40402-ref-hints/issue-40402-2.rs | 6 + .../issue-40402-ref-hints/issue-40402-2.stderr | 18 + tests/ui/issues/issue-40408.rs | 7 + tests/ui/issues/issue-40510-1.migrate.stderr | 13 + tests/ui/issues/issue-40510-1.rs | 12 + tests/ui/issues/issue-40510-1.stderr | 19 + tests/ui/issues/issue-40510-2.rs | 13 + tests/ui/issues/issue-40510-3.migrate.stderr | 15 + tests/ui/issues/issue-40510-3.rs | 14 + tests/ui/issues/issue-40510-3.stderr | 23 + tests/ui/issues/issue-40510-4.rs | 15 + tests/ui/issues/issue-40610.rs | 6 + tests/ui/issues/issue-40610.stderr | 11 + tests/ui/issues/issue-40749.rs | 6 + tests/ui/issues/issue-40749.stderr | 12 + tests/ui/issues/issue-40782.fixed | 8 + tests/ui/issues/issue-40782.rs | 8 + tests/ui/issues/issue-40782.stderr | 14 + tests/ui/issues/issue-40827.rs | 17 + tests/ui/issues/issue-40827.stderr | 55 + tests/ui/issues/issue-40845.rs | 6 + tests/ui/issues/issue-40845.stderr | 14 + tests/ui/issues/issue-40861.rs | 6 + tests/ui/issues/issue-40861.stderr | 11 + tests/ui/issues/issue-40883.rs | 94 + tests/ui/issues/issue-40951.rs | 12 + tests/ui/issues/issue-41053.rs | 21 + tests/ui/issues/issue-41139.rs | 12 + tests/ui/issues/issue-41139.stderr | 12 + tests/ui/issues/issue-41213.rs | 24 + tests/ui/issues/issue-41229-ref-str.rs | 4 + tests/ui/issues/issue-41229-ref-str.stderr | 16 + tests/ui/issues/issue-41272.rs | 21 + tests/ui/issues/issue-41298.rs | 8 + tests/ui/issues/issue-41394-rpass.rs | 8 + tests/ui/issues/issue-41394.rs | 11 + tests/ui/issues/issue-41394.stderr | 17 + tests/ui/issues/issue-41479.rs | 9 + tests/ui/issues/issue-41498.rs | 17 + tests/ui/issues/issue-41549.rs | 12 + tests/ui/issues/issue-41549.stderr | 9 + tests/ui/issues/issue-41604.rs | 11 + tests/ui/issues/issue-41628.rs | 7 + .../issues/issue-41652/auxiliary/issue-41652-b.rs | 6 + tests/ui/issues/issue-41652/issue-41652.rs | 14 + tests/ui/issues/issue-41652/issue-41652.stderr | 14 + tests/ui/issues/issue-41677.rs | 28 + tests/ui/issues/issue-41696.rs | 54 + tests/ui/issues/issue-41726.rs | 7 + tests/ui/issues/issue-41726.stderr | 15 + tests/ui/issues/issue-41742.rs | 25 + tests/ui/issues/issue-41742.stderr | 9 + tests/ui/issues/issue-41744.rs | 7 + tests/ui/issues/issue-41849-variance-req.rs | 35 + tests/ui/issues/issue-41880.rs | 29 + tests/ui/issues/issue-41880.stderr | 12 + tests/ui/issues/issue-41888.rs | 34 + .../issue-41936-variance-coerce-unsized-cycle.rs | 30 + tests/ui/issues/issue-41974.rs | 14 + tests/ui/issues/issue-41974.stderr | 19 + tests/ui/issues/issue-41998.rs | 10 + tests/ui/issues/issue-42007.rs | 11 + tests/ui/issues/issue-4208.rs | 12 + tests/ui/issues/issue-42106.rs | 10 + tests/ui/issues/issue-42106.stderr | 13 + tests/ui/issues/issue-42148.rs | 6 + tests/ui/issues/issue-42210.rs | 21 + tests/ui/issues/issue-4228.rs | 16 + tests/ui/issues/issue-42312.rs | 11 + tests/ui/issues/issue-42312.stderr | 37 + tests/ui/issues/issue-42453.rs | 10 + tests/ui/issues/issue-42467.rs | 24 + tests/ui/issues/issue-4252.rs | 33 + tests/ui/issues/issue-42552.rs | 31 + tests/ui/issues/issue-4265.rs | 14 + tests/ui/issues/issue-4265.stderr | 12 + tests/ui/issues/issue-42755.rs | 7 + tests/ui/issues/issue-42755.stderr | 8 + tests/ui/issues/issue-42796.rs | 19 + tests/ui/issues/issue-42796.stderr | 20 + tests/ui/issues/issue-42880.rs | 8 + tests/ui/issues/issue-42880.stderr | 9 + tests/ui/issues/issue-42956.rs | 26 + tests/ui/issues/issue-43057.rs | 14 + tests/ui/issues/issue-43162.rs | 8 + tests/ui/issues/issue-43162.stderr | 24 + tests/ui/issues/issue-43205.rs | 5 + tests/ui/issues/issue-43250.rs | 13 + tests/ui/issues/issue-43250.stderr | 14 + tests/ui/issues/issue-43291.rs | 9 + tests/ui/issues/issue-4333.rs | 10 + tests/ui/issues/issue-4335.rs | 13 + tests/ui/issues/issue-4335.stderr | 13 + tests/ui/issues/issue-43355.rs | 19 + tests/ui/issues/issue-43355.stderr | 14 + tests/ui/issues/issue-43357.rs | 11 + tests/ui/issues/issue-43420-no-over-suggest.rs | 9 + tests/ui/issues/issue-43420-no-over-suggest.stderr | 19 + tests/ui/issues/issue-43424.rs | 12 + tests/ui/issues/issue-43424.stderr | 8 + tests/ui/issues/issue-43431.rs | 14 + tests/ui/issues/issue-43431.stderr | 9 + tests/ui/issues/issue-43483.rs | 16 + tests/ui/issues/issue-43692.rs | 5 + tests/ui/issues/issue-43806.rs | 23 + tests/ui/issues/issue-43853.rs | 17 + tests/ui/issues/issue-4387.rs | 6 + tests/ui/issues/issue-43910.rs | 7 + tests/ui/issues/issue-43923.rs | 12 + tests/ui/issues/issue-43925.rs | 4 + tests/ui/issues/issue-43925.stderr | 8 + tests/ui/issues/issue-43926.rs | 4 + tests/ui/issues/issue-43926.stderr | 8 + tests/ui/issues/issue-43988.rs | 36 + tests/ui/issues/issue-43988.stderr | 56 + tests/ui/issues/issue-44023.rs | 4 + tests/ui/issues/issue-44023.stderr | 11 + tests/ui/issues/issue-44056.rs | 6 + tests/ui/issues/issue-44078.rs | 3 + tests/ui/issues/issue-44078.stderr | 11 + tests/ui/issues/issue-44216-add-instant.rs | 10 + tests/ui/issues/issue-44216-add-system-time.rs | 10 + tests/ui/issues/issue-44216-sub-instant.rs | 10 + tests/ui/issues/issue-44216-sub-system-time.rs | 10 + tests/ui/issues/issue-44239.fixed | 11 + tests/ui/issues/issue-44239.rs | 11 + tests/ui/issues/issue-44239.stderr | 12 + tests/ui/issues/issue-44247.rs | 19 + tests/ui/issues/issue-44255.rs | 29 + tests/ui/issues/issue-44405.rs | 22 + tests/ui/issues/issue-44405.stderr | 11 + tests/ui/issues/issue-4464.rs | 7 + tests/ui/issues/issue-44730.rs | 15 + tests/ui/issues/issue-44851.rs | 15 + tests/ui/issues/issue-4517.rs | 8 + tests/ui/issues/issue-4517.stderr | 17 + tests/ui/issues/issue-4541.rs | 22 + tests/ui/issues/issue-4542.rs | 12 + tests/ui/issues/issue-45425.rs | 12 + tests/ui/issues/issue-4545.rs | 7 + tests/ui/issues/issue-45510.rs | 32 + tests/ui/issues/issue-45562.fixed | 6 + tests/ui/issues/issue-45562.rs | 6 + tests/ui/issues/issue-45562.stderr | 12 + tests/ui/issues/issue-45697-1.rs | 25 + tests/ui/issues/issue-45697-1.stderr | 26 + tests/ui/issues/issue-45697.rs | 25 + tests/ui/issues/issue-45697.stderr | 26 + tests/ui/issues/issue-45730.rs | 9 + tests/ui/issues/issue-45730.stderr | 27 + tests/ui/issues/issue-45731.rs | 27 + tests/ui/issues/issue-45801.rs | 25 + tests/ui/issues/issue-45801.stderr | 11 + tests/ui/issues/issue-45965.rs | 4 + tests/ui/issues/issue-45965.stderr | 11 + tests/ui/issues/issue-46069.rs | 23 + tests/ui/issues/issue-46101.rs | 6 + tests/ui/issues/issue-46101.stderr | 15 + tests/ui/issues/issue-46302.rs | 9 + tests/ui/issues/issue-46302.stderr | 12 + tests/ui/issues/issue-46311.rs | 4 + tests/ui/issues/issue-46311.stderr | 8 + tests/ui/issues/issue-46332.rs | 11 + tests/ui/issues/issue-46332.stderr | 12 + tests/ui/issues/issue-46438.rs | 13 + tests/ui/issues/issue-46438.stderr | 8 + tests/ui/issues/issue-46471-1.rs | 8 + tests/ui/issues/issue-46471-1.stderr | 14 + tests/ui/issues/issue-46472.rs | 6 + tests/ui/issues/issue-46472.stderr | 12 + tests/ui/issues/issue-46604.rs | 7 + tests/ui/issues/issue-46604.stderr | 16 + ...-46756-consider-borrowing-cast-or-binexpr.fixed | 16 + ...sue-46756-consider-borrowing-cast-or-binexpr.rs | 16 + ...46756-consider-borrowing-cast-or-binexpr.stderr | 35 + tests/ui/issues/issue-46771.rs | 4 + tests/ui/issues/issue-46771.stderr | 13 + tests/ui/issues/issue-46855.rs | 24 + tests/ui/issues/issue-46964.rs | 19 + tests/ui/issues/issue-46983.rs | 6 + tests/ui/issues/issue-46983.stderr | 10 + ...issue-47073-zero-padded-tuple-struct-indices.rs | 12 + ...e-47073-zero-padded-tuple-struct-indices.stderr | 17 + tests/ui/issues/issue-47094.rs | 16 + tests/ui/issues/issue-47094.stderr | 25 + tests/ui/issues/issue-47184.rs | 4 + tests/ui/issues/issue-47184.stderr | 12 + tests/ui/issues/issue-47309.rs | 21 + tests/ui/issues/issue-4734.rs | 37 + tests/ui/issues/issue-4735.rs | 19 + tests/ui/issues/issue-4736.rs | 5 + tests/ui/issues/issue-4736.stderr | 17 + tests/ui/issues/issue-47364.rs | 59 + tests/ui/issues/issue-47377.rs | 6 + tests/ui/issues/issue-47377.stderr | 18 + tests/ui/issues/issue-47380.rs | 5 + tests/ui/issues/issue-47380.stderr | 18 + tests/ui/issues/issue-47486.rs | 4 + tests/ui/issues/issue-47486.stderr | 18 + tests/ui/issues/issue-4759-1.rs | 4 + tests/ui/issues/issue-4759.rs | 18 + tests/ui/issues/issue-47638.rs | 10 + tests/ui/issues/issue-47646.rs | 13 + tests/ui/issues/issue-47646.stderr | 20 + tests/ui/issues/issue-47673.rs | 6 + tests/ui/issues/issue-47703-1.rs | 23 + tests/ui/issues/issue-47703-tuple.rs | 11 + tests/ui/issues/issue-47703.rs | 18 + tests/ui/issues/issue-47715.rs | 28 + tests/ui/issues/issue-47715.stderr | 27 + tests/ui/issues/issue-47722.rs | 17 + tests/ui/issues/issue-47725.rs | 28 + tests/ui/issues/issue-47725.stderr | 60 + tests/ui/issues/issue-48006.rs | 15 + tests/ui/issues/issue-48131.mir.stderr | 20 + tests/ui/issues/issue-48131.rs | 33 + tests/ui/issues/issue-48131.thir.stderr | 20 + tests/ui/issues/issue-48132.rs | 31 + tests/ui/issues/issue-48159.rs | 27 + tests/ui/issues/issue-48179.rs | 38 + tests/ui/issues/issue-48276.rs | 33 + tests/ui/issues/issue-48276.stderr | 28 + tests/ui/issues/issue-4830.rs | 11 + tests/ui/issues/issue-48364.rs | 6 + tests/ui/issues/issue-48364.stderr | 17 + tests/ui/issues/issue-48728.rs | 13 + tests/ui/issues/issue-48728.stderr | 15 + tests/ui/issues/issue-4875.rs | 15 + tests/ui/issues/issue-48838.rs | 5 + tests/ui/issues/issue-48838.stderr | 12 + tests/ui/issues/issue-48984.rs | 9 + tests/ui/issues/issue-49298.rs | 42 + tests/ui/issues/issue-4935.rs | 6 + tests/ui/issues/issue-4935.stderr | 19 + tests/ui/issues/issue-49544.rs | 9 + ...on-shorthand-field-patterns-in-pattern-macro.rs | 16 + tests/ui/issues/issue-49632.rs | 8 + tests/ui/issues/issue-4968.rs | 10 + tests/ui/issues/issue-4968.stderr | 20 + tests/ui/issues/issue-4972.rs | 17 + tests/ui/issues/issue-4972.stderr | 9 + tests/ui/issues/issue-49824.rs | 9 + tests/ui/issues/issue-49824.stderr | 23 + .../issues/issue-49851/compiler-builtins-error.rs | 13 + .../issue-49851/compiler-builtins-error.stderr | 19 + tests/ui/issues/issue-49854.rs | 9 + tests/ui/issues/issue-49919.rs | 7 + tests/ui/issues/issue-49919.stderr | 9 + tests/ui/issues/issue-49934-errors.rs | 8 + tests/ui/issues/issue-49934-errors.stderr | 14 + tests/ui/issues/issue-49934.rs | 30 + tests/ui/issues/issue-49934.stderr | 43 + tests/ui/issues/issue-49955.rs | 20 + tests/ui/issues/issue-49973.rs | 11 + .../issue-5008-borrowed-traitobject-method-call.rs | 34 + tests/ui/issues/issue-50187.rs | 39 + .../option-as_deref.rs | 4 + .../option-as_deref.stderr | 12 + .../option-as_deref_mut.rs | 4 + .../option-as_deref_mut.stderr | 12 + .../result-as_deref.rs | 4 + .../result-as_deref.stderr | 12 + .../result-as_deref_mut.rs | 4 + .../result-as_deref_mut.stderr | 12 + tests/ui/issues/issue-50403.rs | 5 + tests/ui/issues/issue-50403.stderr | 8 + tests/ui/issues/issue-50411.rs | 11 + tests/ui/issues/issue-50415.rs | 16 + tests/ui/issues/issue-50442.rs | 13 + tests/ui/issues/issue-50471.rs | 9 + tests/ui/issues/issue-50518.rs | 40 + tests/ui/issues/issue-50571.fixed | 8 + tests/ui/issues/issue-50571.rs | 8 + tests/ui/issues/issue-50571.stderr | 14 + tests/ui/issues/issue-50576.rs | 6 + tests/ui/issues/issue-50576.stderr | 22 + tests/ui/issues/issue-50581.rs | 3 + tests/ui/issues/issue-50581.stderr | 9 + tests/ui/issues/issue-50582.rs | 5 + tests/ui/issues/issue-50582.stderr | 31 + tests/ui/issues/issue-50585.rs | 5 + tests/ui/issues/issue-50585.stderr | 19 + tests/ui/issues/issue-50600.rs | 5 + tests/ui/issues/issue-50600.stderr | 12 + tests/ui/issues/issue-50618.rs | 19 + tests/ui/issues/issue-50618.stderr | 11 + tests/ui/issues/issue-5062.rs | 2 + tests/ui/issues/issue-5062.stderr | 14 + tests/ui/issues/issue-5067.rs | 75 + tests/ui/issues/issue-5067.stderr | 110 + tests/ui/issues/issue-50688.rs | 3 + tests/ui/issues/issue-50688.stderr | 12 + tests/ui/issues/issue-50689.rs | 9 + tests/ui/issues/issue-50714-1.rs | 11 + tests/ui/issues/issue-50714-1.stderr | 9 + tests/ui/issues/issue-50714.rs | 3 + tests/ui/issues/issue-50714.stderr | 9 + tests/ui/issues/issue-50761.rs | 23 + tests/ui/issues/issue-50781.rs | 19 + tests/ui/issues/issue-50781.stderr | 24 + tests/ui/issues/issue-50802.rs | 8 + tests/ui/issues/issue-50802.stderr | 9 + tests/ui/issues/issue-50811.rs | 55 + tests/ui/issues/issue-50825-1.rs | 22 + tests/ui/issues/issue-50825.rs | 15 + .../auxiliary/lib.rs | 18 + .../issues/issue-50865-private-impl-trait/main.rs | 16 + tests/ui/issues/issue-5100.rs | 57 + tests/ui/issues/issue-5100.stderr | 76 + tests/ui/issues/issue-51022.rs | 2 + tests/ui/issues/issue-51022.stderr | 9 + tests/ui/issues/issue-51044.rs | 30 + tests/ui/issues/issue-51102.rs | 38 + tests/ui/issues/issue-51102.stderr | 27 + tests/ui/issues/issue-51116.rs | 12 + tests/ui/issues/issue-51116.stderr | 9 + tests/ui/issues/issue-51154.rs | 6 + tests/ui/issues/issue-51154.stderr | 19 + tests/ui/issues/issue-51515.rs | 10 + tests/ui/issues/issue-51515.stderr | 22 + tests/ui/issues/issue-5153.rs | 12 + tests/ui/issues/issue-5153.stderr | 12 + .../issue-51632-try-desugar-incompatible-types.rs | 12 + ...sue-51632-try-desugar-incompatible-types.stderr | 22 + tests/ui/issues/issue-51655.rs | 14 + tests/ui/issues/issue-51714.rs | 21 + tests/ui/issues/issue-51714.stderr | 63 + tests/ui/issues/issue-51798.rs | 14 + tests/ui/issues/issue-51874.rs | 3 + tests/ui/issues/issue-51874.stderr | 14 + tests/ui/issues/issue-51907.rs | 19 + tests/ui/issues/issue-5192.rs | 39 + tests/ui/issues/issue-51947.rs | 17 + tests/ui/issues/issue-52049.rs | 8 + tests/ui/issues/issue-52049.stderr | 14 + .../ui/issues/issue-52126-assign-op-invariance.rs | 49 + .../issues/issue-52126-assign-op-invariance.stderr | 15 + .../ui/issues/issue-52140/auxiliary/some_crate.rs | 5 + tests/ui/issues/issue-52140/main.rs | 13 + .../ui/issues/issue-52141/auxiliary/some_crate.rs | 5 + tests/ui/issues/issue-52141/main.rs | 16 + tests/ui/issues/issue-52262.rs | 24 + tests/ui/issues/issue-52262.stderr | 9 + tests/ui/issues/issue-5239-1.rs | 6 + tests/ui/issues/issue-5239-1.stderr | 11 + tests/ui/issues/issue-5239-2.rs | 9 + tests/ui/issues/issue-52489.rs | 8 + tests/ui/issues/issue-52489.stderr | 11 + tests/ui/issues/issue-52533.rs | 7 + tests/ui/issues/issue-52533.stderr | 11 + tests/ui/issues/issue-52705/auxiliary/png2.rs | 3 + tests/ui/issues/issue-52705/main.rs | 15 + tests/ui/issues/issue-52717.rs | 13 + tests/ui/issues/issue-52717.stderr | 12 + tests/ui/issues/issue-5280.rs | 18 + tests/ui/issues/issue-5315.rs | 9 + .../issues/issue-5321-immediates-with-bare-self.rs | 15 + tests/ui/issues/issue-53251.rs | 21 + tests/ui/issues/issue-53251.stderr | 39 + tests/ui/issues/issue-53275.rs | 9 + tests/ui/issues/issue-53300.rs | 12 + tests/ui/issues/issue-53300.stderr | 9 + tests/ui/issues/issue-53333.rs | 9 + tests/ui/issues/issue-53348.rs | 15 + tests/ui/issues/issue-53348.stderr | 12 + tests/ui/issues/issue-53419.rs | 8 + tests/ui/issues/issue-53498.rs | 17 + tests/ui/issues/issue-53498.stderr | 12 + tests/ui/issues/issue-53568.rs | 47 + tests/ui/issues/issue-5358-1.rs | 13 + tests/ui/issues/issue-5358-1.stderr | 22 + tests/ui/issues/issue-53712.rs | 9 + tests/ui/issues/issue-53712.stderr | 11 + tests/ui/issues/issue-53728.rs | 19 + tests/ui/issues/issue-53843.rs | 26 + tests/ui/issues/issue-54044.rs | 13 + tests/ui/issues/issue-54044.stderr | 29 + tests/ui/issues/issue-54062.rs | 12 + tests/ui/issues/issue-54062.stderr | 9 + tests/ui/issues/issue-54094.rs | 14 + tests/ui/issues/issue-54302-cases.rs | 85 + tests/ui/issues/issue-54302-cases.stderr | 38 + tests/ui/issues/issue-54302.rs | 19 + tests/ui/issues/issue-54302.stderr | 11 + tests/ui/issues/issue-5439.rs | 19 + tests/ui/issues/issue-5439.stderr | 11 + tests/ui/issues/issue-54410.rs | 8 + tests/ui/issues/issue-54410.stderr | 11 + .../issue-54462-mutable-noalias-correctness.rs | 25 + tests/ui/issues/issue-54477-reduced-2.rs | 26 + tests/ui/issues/issue-54582.rs | 16 + tests/ui/issues/issue-54696.rs | 8 + tests/ui/issues/issue-5518.rs | 8 + tests/ui/issues/issue-5521.rs | 17 + tests/ui/issues/issue-55376.rs | 16 + tests/ui/issues/issue-55380.rs | 28 + tests/ui/issues/issue-55380.stderr | 12 + tests/ui/issues/issue-5550.rs | 9 + tests/ui/issues/issue-5554.rs | 29 + tests/ui/issues/issue-55587.rs | 5 + tests/ui/issues/issue-55587.stderr | 11 + tests/ui/issues/issue-5572.rs | 7 + tests/ui/issues/issue-55731.rs | 52 + tests/ui/issues/issue-55731.stderr | 14 + tests/ui/issues/issue-56128.rs | 15 + tests/ui/issues/issue-56175.rs | 9 + tests/ui/issues/issue-56175.stderr | 37 + tests/ui/issues/issue-56199.rs | 22 + tests/ui/issues/issue-56199.stderr | 30 + tests/ui/issues/issue-56229.rs | 35 + tests/ui/issues/issue-56237.rs | 13 + tests/ui/issues/issue-5666.rs | 26 + tests/ui/issues/issue-56806.rs | 6 + tests/ui/issues/issue-56806.stderr | 12 + tests/ui/issues/issue-56835.rs | 9 + tests/ui/issues/issue-56835.stderr | 15 + tests/ui/issues/issue-56870.rs | 38 + tests/ui/issues/issue-5688.rs | 20 + tests/ui/issues/issue-56943.rs | 8 + tests/ui/issues/issue-56943.stderr | 11 + tests/ui/issues/issue-5708.rs | 55 + tests/ui/issues/issue-57156.rs | 23 + tests/ui/issues/issue-57162.rs | 7 + tests/ui/issues/issue-5718.rs | 24 + tests/ui/issues/issue-57198-pass.rs | 9 + tests/ui/issues/issue-57271.rs | 24 + tests/ui/issues/issue-57271.stderr | 27 + tests/ui/issues/issue-57362-1.rs | 23 + tests/ui/issues/issue-57362-1.stderr | 16 + tests/ui/issues/issue-57362-2.rs | 25 + tests/ui/issues/issue-57362-2.stderr | 18 + .../issues/issue-57399-self-return-impl-trait.rs | 22 + tests/ui/issues/issue-5741.rs | 9 + tests/ui/issues/issue-5754.rs | 16 + tests/ui/issues/issue-57741-1.rs | 18 + tests/ui/issues/issue-57741-1.stderr | 25 + tests/ui/issues/issue-57741.fixed | 31 + tests/ui/issues/issue-57741.rs | 31 + tests/ui/issues/issue-57741.stderr | 59 + tests/ui/issues/issue-57781.rs | 20 + tests/ui/issues/issue-57924.rs | 10 + tests/ui/issues/issue-57924.stderr | 11 + tests/ui/issues/issue-58212.rs | 15 + tests/ui/issues/issue-58344.rs | 50 + .../issue-58375-monomorphize-default-impls.rs | 24 + tests/ui/issues/issue-5844.mir.stderr | 11 + tests/ui/issues/issue-5844.rs | 9 + tests/ui/issues/issue-5844.thir.stderr | 11 + tests/ui/issues/issue-58463.rs | 10 + tests/ui/issues/issue-58712.rs | 14 + tests/ui/issues/issue-58712.stderr | 20 + tests/ui/issues/issue-58734.rs | 24 + tests/ui/issues/issue-58734.stderr | 23 + tests/ui/issues/issue-5883.rs | 13 + tests/ui/issues/issue-5883.stderr | 36 + tests/ui/issues/issue-5884.rs | 18 + tests/ui/issues/issue-58857.rs | 7 + tests/ui/issues/issue-58857.stderr | 8 + tests/ui/issues/issue-5900.rs | 15 + tests/ui/issues/issue-59020.rs | 27 + tests/ui/issues/issue-5917.rs | 9 + tests/ui/issues/issue-59326.rs | 26 + tests/ui/issues/issue-59488.rs | 34 + tests/ui/issues/issue-59488.stderr | 127 + tests/ui/issues/issue-59494.rs | 23 + tests/ui/issues/issue-59494.stderr | 18 + tests/ui/issues/issue-5950.rs | 9 + tests/ui/issues/issue-59756.fixed | 17 + tests/ui/issues/issue-59756.rs | 21 + tests/ui/issues/issue-59756.stderr | 20 + tests/ui/issues/issue-5988.rs | 24 + tests/ui/issues/issue-5997-enum.rs | 10 + tests/ui/issues/issue-5997-enum.stderr | 13 + tests/ui/issues/issue-5997-struct.rs | 10 + tests/ui/issues/issue-5997-struct.stderr | 13 + tests/ui/issues/issue-5997.rs | 15 + tests/ui/issues/issue-60218.rs | 19 + tests/ui/issues/issue-60218.stderr | 20 + tests/ui/issues/issue-60622.rs | 16 + tests/ui/issues/issue-60622.stderr | 35 + tests/ui/issues/issue-60989.rs | 18 + tests/ui/issues/issue-60989.stderr | 19 + tests/ui/issues/issue-61106.rs | 6 + tests/ui/issues/issue-61106.stderr | 19 + tests/ui/issues/issue-61108.rs | 7 + tests/ui/issues/issue-61108.stderr | 21 + tests/ui/issues/issue-6117.rs | 12 + tests/ui/issues/issue-6130.rs | 10 + tests/ui/issues/issue-61475.rs | 15 + tests/ui/issues/issue-6153.rs | 13 + tests/ui/issues/issue-61623.rs | 10 + tests/ui/issues/issue-61623.stderr | 14 + tests/ui/issues/issue-61696.rs | 66 + tests/ui/issues/issue-61894.rs | 21 + tests/ui/issues/issue-62375.rs | 9 + tests/ui/issues/issue-62375.stderr | 21 + tests/ui/issues/issue-62480.rs | 10 + tests/ui/issues/issue-62480.stderr | 22 + tests/ui/issues/issue-6318.rs | 20 + tests/ui/issues/issue-6344-let.rs | 15 + tests/ui/issues/issue-6344-match.rs | 18 + tests/ui/issues/issue-63983.rs | 15 + tests/ui/issues/issue-63983.stderr | 19 + tests/ui/issues/issue-64430.rs | 14 + tests/ui/issues/issue-64430.stderr | 12 + tests/ui/issues/issue-64559.rs | 6 + tests/ui/issues/issue-64559.stderr | 22 + tests/ui/issues/issue-6458-1.rs | 8 + tests/ui/issues/issue-6458-2.rs | 5 + tests/ui/issues/issue-6458-2.stderr | 14 + tests/ui/issues/issue-6458-3.rs | 6 + tests/ui/issues/issue-6458-3.stderr | 14 + tests/ui/issues/issue-6458-4.rs | 7 + tests/ui/issues/issue-6458-4.stderr | 16 + tests/ui/issues/issue-6458.rs | 14 + tests/ui/issues/issue-6458.stderr | 14 + tests/ui/issues/issue-64593.rs | 12 + tests/ui/issues/issue-64792-bad-unicode-ctor.rs | 5 + .../ui/issues/issue-64792-bad-unicode-ctor.stderr | 12 + tests/ui/issues/issue-65131.rs | 18 + tests/ui/issues/issue-65131.stderr | 12 + tests/ui/issues/issue-65230.rs | 11 + tests/ui/issues/issue-65230.stderr | 18 + tests/ui/issues/issue-65462.rs | 15 + tests/ui/issues/issue-6557.rs | 9 + ...e-65634-raw-ident-suggestion.edition2015.stderr | 28 + ...e-65634-raw-ident-suggestion.edition2018.stderr | 28 + .../ui/issues/issue-65634-raw-ident-suggestion.rs | 25 + tests/ui/issues/issue-6596-2.rs | 11 + tests/ui/issues/issue-6596-2.stderr | 13 + tests/ui/issues/issue-66308.rs | 8 + tests/ui/issues/issue-66353.rs | 15 + tests/ui/issues/issue-66353.stderr | 17 + tests/ui/issues/issue-6642.rs | 9 + tests/ui/issues/issue-6642.stderr | 11 + tests/ui/issues/issue-66667-function-cmp-cycle.rs | 16 + .../issues/issue-66667-function-cmp-cycle.stderr | 55 + .../issues/issue-66702-break-outside-loop-val.rs | 9 + .../issue-66702-break-outside-loop-val.stderr | 22 + tests/ui/issues/issue-66706.rs | 22 + tests/ui/issues/issue-66706.stderr | 37 + tests/ui/issues/issue-66768.rs | 205 + .../issue-66923-show-error-for-correct-call.rs | 15 + .../issue-66923-show-error-for-correct-call.stderr | 40 + .../ui/issues/issue-67039-unsound-pin-partialeq.rs | 27 + .../issue-67039-unsound-pin-partialeq.stderr | 13 + tests/ui/issues/issue-6738.rs | 10 + tests/ui/issues/issue-6738.stderr | 16 + tests/ui/issues/issue-67535.rs | 22 + tests/ui/issues/issue-67535.stderr | 39 + tests/ui/issues/issue-67552.polonius.stderr | 17 + tests/ui/issues/issue-67552.rs | 32 + tests/ui/issues/issue-67552.stderr | 17 + tests/ui/issues/issue-68010-large-zst-consts.rs | 5 + tests/ui/issues/issue-68696-catch-during-unwind.rs | 25 + tests/ui/issues/issue-6892.rs | 58 + tests/ui/issues/issue-68951.rs | 9 + tests/ui/issues/issue-6898.rs | 33 + tests/ui/issues/issue-69130.rs | 7 + tests/ui/issues/issue-69130.stderr | 21 + tests/ui/issues/issue-6919.rs | 11 + .../ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs | 33 + .../issue-69225-layout-repeated-checked-add.rs | 31 + tests/ui/issues/issue-69306.rs | 45 + tests/ui/issues/issue-69306.stderr | 138 + tests/ui/issues/issue-6936.rs | 34 + tests/ui/issues/issue-6936.stderr | 43 + .../issues/issue-69396-const-no-type-in-macro.rs | 17 + .../issue-69396-const-no-type-in-macro.stderr | 50 + tests/ui/issues/issue-69455.rs | 31 + tests/ui/issues/issue-69455.stderr | 39 + .../issue-69602-type-err-during-codegen-ice.rs | 23 + .../issue-69602-type-err-during-codegen-ice.stderr | 25 + tests/ui/issues/issue-69683.rs | 33 + tests/ui/issues/issue-69683.stderr | 43 + tests/ui/issues/issue-70093.rs | 10 + tests/ui/issues/issue-7012.rs | 22 + tests/ui/issues/issue-70381.rs | 6 + tests/ui/issues/issue-70381.stderr | 8 + tests/ui/issues/issue-7044.rs | 4 + tests/ui/issues/issue-7044.stderr | 13 + tests/ui/issues/issue-7061.rs | 10 + tests/ui/issues/issue-7061.stderr | 14 + tests/ui/issues/issue-70673.rs | 12 + .../issue-70724-add_type_neq_err_label-unwrap.rs | 10 + ...ssue-70724-add_type_neq_err_label-unwrap.stderr | 38 + tests/ui/issues/issue-70746.rs | 29 + tests/ui/issues/issue-7092.rs | 15 + tests/ui/issues/issue-7092.stderr | 14 + tests/ui/issues/issue-71406.rs | 6 + tests/ui/issues/issue-71406.stderr | 9 + tests/ui/issues/issue-71584.rs | 6 + tests/ui/issues/issue-71584.stderr | 17 + tests/ui/issues/issue-71676-1.fixed | 53 + tests/ui/issues/issue-71676-1.rs | 53 + tests/ui/issues/issue-71676-1.stderr | 63 + tests/ui/issues/issue-71676-2.rs | 42 + tests/ui/issues/issue-71676-2.stderr | 18 + tests/ui/issues/issue-7178.rs | 10 + tests/ui/issues/issue-72002.rs | 29 + tests/ui/issues/issue-72076.rs | 6 + tests/ui/issues/issue-72076.stderr | 14 + tests/ui/issues/issue-72278.rs | 19 + tests/ui/issues/issue-72278.stderr | 15 + tests/ui/issues/issue-7246.rs | 11 + tests/ui/issues/issue-7246.stderr | 24 + tests/ui/issues/issue-7268.rs | 10 + tests/ui/issues/issue-72839-error-overflow.rs | 19 + tests/ui/issues/issue-72839-error-overflow.stderr | 9 + .../ui/issues/issue-72933-match-stack-overflow.rs | 5208 +++++++++ tests/ui/issues/issue-73112.rs | 13 + tests/ui/issues/issue-73112.stderr | 15 + tests/ui/issues/issue-73229.rs | 33 + tests/ui/issues/issue-7344.rs | 22 + tests/ui/issues/issue-7364.rs | 7 + tests/ui/issues/issue-7364.stderr | 14 + tests/ui/issues/issue-74082.rs | 9 + tests/ui/issues/issue-74082.stderr | 19 + tests/ui/issues/issue-74236/auxiliary/dep.rs | 8 + tests/ui/issues/issue-74236/main.rs | 9 + tests/ui/issues/issue-74236/main.stderr | 11 + .../issues/issue-74564-if-expr-stack-overflow.rs | 10419 +++++++++++++++++++ tests/ui/issues/issue-7519-match-unit-in-arg.rs | 12 + tests/ui/issues/issue-75283.rs | 6 + tests/ui/issues/issue-75283.stderr | 18 + tests/ui/issues/issue-75307.rs | 3 + tests/ui/issues/issue-75307.stderr | 8 + tests/ui/issues/issue-7563.rs | 28 + tests/ui/issues/issue-75704.rs | 7 + tests/ui/issues/issue-7575.rs | 17 + tests/ui/issues/issue-75777.rs | 15 + tests/ui/issues/issue-75777.stderr | 11 + tests/ui/issues/issue-76042.rs | 16 + tests/ui/issues/issue-7607-1.rs | 9 + tests/ui/issues/issue-7607-1.stderr | 12 + tests/ui/issues/issue-7607-2.rs | 16 + tests/ui/issues/issue-76077-1.fixed | 18 + tests/ui/issues/issue-76077-1.rs | 18 + tests/ui/issues/issue-76077-1.stderr | 24 + tests/ui/issues/issue-76077.rs | 10 + tests/ui/issues/issue-76077.stderr | 10 + tests/ui/issues/issue-76191.rs | 19 + tests/ui/issues/issue-76191.stderr | 43 + tests/ui/issues/issue-7660.rs | 18 + tests/ui/issues/issue-7663.rs | 32 + ...ssue-7673-cast-generically-implemented-trait.rs | 20 + tests/ui/issues/issue-77218/issue-77218-2.fixed | 6 + tests/ui/issues/issue-77218/issue-77218-2.rs | 6 + tests/ui/issues/issue-77218/issue-77218-2.stderr | 16 + tests/ui/issues/issue-77218/issue-77218.fixed | 5 + tests/ui/issues/issue-77218/issue-77218.rs | 5 + tests/ui/issues/issue-77218/issue-77218.stderr | 16 + tests/ui/issues/issue-7784.rs | 30 + tests/ui/issues/issue-77919.rs | 13 + tests/ui/issues/issue-77919.stderr | 35 + tests/ui/issues/issue-78115.rs | 19 + tests/ui/issues/issue-7813.rs | 4 + tests/ui/issues/issue-7813.stderr | 14 + tests/ui/issues/issue-78192.rs | 17 + tests/ui/issues/issue-78622.rs | 7 + tests/ui/issues/issue-78622.stderr | 14 + tests/ui/issues/issue-7867.rs | 14 + tests/ui/issues/issue-7867.stderr | 17 + tests/ui/issues/issue-78957.rs | 29 + tests/ui/issues/issue-78957.stderr | 69 + tests/ui/issues/issue-7899.rs | 11 + tests/ui/issues/issue-7911.rs | 37 + tests/ui/issues/issue-7950.rs | 8 + tests/ui/issues/issue-7950.stderr | 12 + tests/ui/issues/issue-7970a.rs | 8 + tests/ui/issues/issue-7970a.stderr | 17 + tests/ui/issues/issue-8044.rs | 11 + tests/ui/issues/issue-80607.rs | 10 + tests/ui/issues/issue-80607.stderr | 17 + tests/ui/issues/issue-81584.fixed | 8 + tests/ui/issues/issue-81584.rs | 8 + tests/ui/issues/issue-81584.stderr | 14 + ...71-default-method-self-inherit-builtin-trait.rs | 19 + tests/ui/issues/issue-81918.rs | 11 + tests/ui/issues/issue-8248.rs | 15 + tests/ui/issues/issue-8249.rs | 20 + tests/ui/issues/issue-8259.rs | 12 + tests/ui/issues/issue-82833-slice-miscompile.rs | 16 + tests/ui/issues/issue-83048.rs | 5 + tests/ui/issues/issue-83048.stderr | 9 + tests/ui/issues/issue-83190.rs | 49 + tests/ui/issues/issue-8391.rs | 9 + tests/ui/issues/issue-83924.fixed | 20 + tests/ui/issues/issue-83924.rs | 20 + tests/ui/issues/issue-83924.stderr | 22 + tests/ui/issues/issue-8398.rs | 13 + tests/ui/issues/issue-8401.rs | 8 + tests/ui/issues/issue-8498.rs | 27 + tests/ui/issues/issue-8506.rs | 14 + tests/ui/issues/issue-8521.rs | 25 + tests/ui/issues/issue-85461.rs | 27 + tests/ui/issues/issue-8578.rs | 20 + tests/ui/issues/issue-86756.rs | 12 + tests/ui/issues/issue-86756.stderr | 48 + tests/ui/issues/issue-868.rs | 18 + tests/ui/issues/issue-87199.rs | 20 + tests/ui/issues/issue-87199.stderr | 40 + tests/ui/issues/issue-8727.polonius.stderr | 26 + tests/ui/issues/issue-8727.rs | 16 + tests/ui/issues/issue-8727.stderr | 26 + tests/ui/issues/issue-87490.rs | 10 + tests/ui/issues/issue-87490.stderr | 14 + tests/ui/issues/issue-8761.rs | 10 + tests/ui/issues/issue-8761.stderr | 25 + tests/ui/issues/issue-8767.rs | 5 + tests/ui/issues/issue-8767.stderr | 9 + tests/ui/issues/issue-87707.rs | 17 + tests/ui/issues/issue-87707.run.stderr | 3 + tests/ui/issues/issue-8783.rs | 24 + tests/ui/issues/issue-88150.rs | 21 + tests/ui/issues/issue-8860.rs | 49 + tests/ui/issues/issue-8898.rs | 18 + tests/ui/issues/issue-9047.rs | 14 + tests/ui/issues/issue-9110.rs | 17 + tests/ui/issues/issue-9123.rs | 8 + tests/ui/issues/issue-9129.rs | 32 + tests/ui/issues/issue-91489.rs | 40 + tests/ui/issues/issue-9155.rs | 12 + tests/ui/issues/issue-9188.rs | 11 + tests/ui/issues/issue-9243.rs | 16 + tests/ui/issues/issue-9249.rs | 6 + tests/ui/issues/issue-9259.rs | 16 + tests/ui/issues/issue-9382.rs | 40 + tests/ui/issues/issue-9446.rs | 30 + tests/ui/issues/issue-948.rs | 15 + tests/ui/issues/issue-9575.rs | 7 + tests/ui/issues/issue-9575.stderr | 12 + tests/ui/issues/issue-9719.rs | 41 + tests/ui/issues/issue-9725.rs | 7 + tests/ui/issues/issue-9725.stderr | 18 + tests/ui/issues/issue-9737.rs | 10 + tests/ui/issues/issue-979.rs | 29 + tests/ui/issues/issue-9814.rs | 8 + tests/ui/issues/issue-9814.stderr | 9 + tests/ui/issues/issue-98299.rs | 18 + tests/ui/issues/issue-98299.stderr | 14 + tests/ui/issues/issue-9837.rs | 11 + tests/ui/issues/issue-9906.rs | 11 + tests/ui/issues/issue-9918.rs | 5 + tests/ui/issues/issue-9942.rs | 6 + tests/ui/issues/issue-9951.rs | 21 + tests/ui/issues/issue-9968.rs | 13 + tests/ui/issues/issue-99838.rs | 40 + tests/ui/issues/issue-pr29383.rs | 14 + tests/ui/issues/issue-pr29383.stderr | 21 + tests/ui/item-name-overload.rs | 17 + tests/ui/iterators/array-of-ranges.rs | 16 + tests/ui/iterators/array.rs | 8 + tests/ui/iterators/bound.rs | 4 + tests/ui/iterators/bound.stderr | 17 + tests/ui/iterators/collect-into-array.rs | 6 + tests/ui/iterators/collect-into-array.stderr | 13 + tests/ui/iterators/collect-into-slice.rs | 17 + tests/ui/iterators/collect-into-slice.stderr | 33 + tests/ui/iterators/float_iterator_hint.rs | 15 + tests/ui/iterators/float_iterator_hint.stderr | 13 + tests/ui/iterators/integral.rs | 26 + tests/ui/iterators/integral.stderr | 123 + tests/ui/iterators/into-iter-on-arrays-2018.rs | 46 + tests/ui/iterators/into-iter-on-arrays-2018.stderr | 65 + tests/ui/iterators/into-iter-on-arrays-2021.rs | 32 + tests/ui/iterators/into-iter-on-arrays-lint.fixed | 63 + tests/ui/iterators/into-iter-on-arrays-lint.rs | 63 + tests/ui/iterators/into-iter-on-arrays-lint.stderr | 143 + .../into-iterator-type-inference-shift.rs | 36 + .../invalid-iterator-chain-with-int-infer.rs | 4 + .../invalid-iterator-chain-with-int-infer.stderr | 24 + tests/ui/iterators/invalid-iterator-chain.rs | 53 + tests/ui/iterators/invalid-iterator-chain.stderr | 176 + tests/ui/iterators/issue-28098.rs | 31 + tests/ui/iterators/issue-28098.stderr | 109 + .../ui/iterators/issue-58952-filter-type-length.rs | 32 + tests/ui/iterators/iter-cloned-type-inference.rs | 16 + tests/ui/iterators/iter-count-overflow-debug.rs | 15 + tests/ui/iterators/iter-count-overflow-ndebug.rs | 8 + tests/ui/iterators/iter-map-fold-type-length.rs | 38 + tests/ui/iterators/iter-position-overflow-debug.rs | 21 + .../ui/iterators/iter-position-overflow-ndebug.rs | 10 + tests/ui/iterators/iter-range.rs | 14 + tests/ui/iterators/iter-step-overflow-debug.rs | 21 + tests/ui/iterators/iter-step-overflow-ndebug.rs | 12 + tests/ui/iterators/iter-sum-overflow-debug.rs | 27 + tests/ui/iterators/iter-sum-overflow-ndebug.rs | 14 + .../iterators/iter-sum-overflow-overflow-checks.rs | 27 + tests/ui/iterators/ranges.rs | 9 + tests/ui/iterators/ranges.stderr | 23 + tests/ui/iterators/rsplit-clone.rs | 11 + tests/ui/iterators/skip-count-overflow.rs | 8 + tests/ui/iterators/string.rs | 6 + tests/ui/iterators/string.stderr | 21 + tests/ui/iterators/vec-on-unimplemented.rs | 4 + tests/ui/iterators/vec-on-unimplemented.stderr | 18 + tests/ui/json/json-and-color.rs | 3 + tests/ui/json/json-and-color.stderr | 2 + tests/ui/json/json-and-error-format.rs | 3 + tests/ui/json/json-and-error-format.stderr | 2 + tests/ui/json/json-bom-plus-crlf-multifile-aux.rs | 27 + tests/ui/json/json-bom-plus-crlf-multifile.rs | 11 + tests/ui/json/json-bom-plus-crlf-multifile.stderr | 114 + tests/ui/json/json-bom-plus-crlf.rs | 26 + tests/ui/json/json-bom-plus-crlf.stderr | 114 + tests/ui/json/json-invalid.rs | 3 + tests/ui/json/json-invalid.stderr | 2 + tests/ui/json/json-multiple.polonius.stderr | 1 + tests/ui/json/json-multiple.rs | 5 + tests/ui/json/json-multiple.stderr | 1 + tests/ui/json/json-options.polonius.stderr | 1 + tests/ui/json/json-options.rs | 5 + tests/ui/json/json-options.stderr | 1 + tests/ui/json/json-short.rs | 1 + tests/ui/json/json-short.stderr | 19 + .../extern/keyword-extern-as-identifier-expr.rs | 3 + .../keyword-extern-as-identifier-expr.stderr | 8 + .../extern/keyword-extern-as-identifier-pat.rs | 3 + .../extern/keyword-extern-as-identifier-pat.stderr | 13 + .../extern/keyword-extern-as-identifier-type.rs | 3 + .../keyword-extern-as-identifier-type.stderr | 8 + .../extern/keyword-extern-as-identifier-use.rs | 4 + .../extern/keyword-extern-as-identifier-use.stderr | 22 + tests/ui/keyword/keyword-false-as-identifier.rs | 3 + .../ui/keyword/keyword-false-as-identifier.stderr | 11 + tests/ui/keyword/keyword-self-as-identifier.rs | 3 + tests/ui/keyword/keyword-self-as-identifier.stderr | 9 + tests/ui/keyword/keyword-self-as-type-param.rs | 10 + tests/ui/keyword/keyword-self-as-type-param.stderr | 30 + tests/ui/keyword/keyword-super-as-identifier.rs | 3 + .../ui/keyword/keyword-super-as-identifier.stderr | 9 + tests/ui/keyword/keyword-super.rs | 3 + tests/ui/keyword/keyword-super.stderr | 9 + tests/ui/keyword/keyword-true-as-identifier.rs | 3 + tests/ui/keyword/keyword-true-as-identifier.stderr | 11 + tests/ui/kindck/kindck-copy.rs | 71 + tests/ui/kindck/kindck-copy.stderr | 145 + tests/ui/kindck/kindck-impl-type-params-2.rs | 15 + tests/ui/kindck/kindck-impl-type-params-2.stderr | 24 + tests/ui/kindck/kindck-impl-type-params.rs | 47 + tests/ui/kindck/kindck-impl-type-params.stderr | 115 + .../kindck/kindck-inherited-copy-bound.curr.stderr | 55 + ...ited-copy-bound.object_safe_for_dispatch.stderr | 41 + tests/ui/kindck/kindck-inherited-copy-bound.rs | 34 + tests/ui/kindck/kindck-nonsendable-1.rs | 11 + tests/ui/kindck/kindck-nonsendable-1.stderr | 25 + tests/ui/kindck/kindck-send-object.rs | 26 + tests/ui/kindck/kindck-send-object.stderr | 32 + tests/ui/kindck/kindck-send-object1.rs | 32 + tests/ui/kindck/kindck-send-object1.stderr | 32 + tests/ui/kindck/kindck-send-object2.rs | 24 + tests/ui/kindck/kindck-send-object2.stderr | 32 + tests/ui/kindck/kindck-send-owned.rs | 16 + tests/ui/kindck/kindck-send-owned.stderr | 18 + tests/ui/kindck/kindck-send-unsafe.rs | 11 + .../kindck/kindck-send-unsafe.rs~rust-lang_master | 12 + tests/ui/kindck/kindck-send-unsafe.stderr | 16 + tests/ui/kinds-in-metadata.rs | 17 + tests/ui/kinds-of-primitive-impl.rs | 26 + tests/ui/kinds-of-primitive-impl.stderr | 36 + tests/ui/label/label-beginning-with-underscore.rs | 10 + tests/ui/label/label-static.rs | 5 + tests/ui/label/label-static.stderr | 14 + tests/ui/label/label-underscore.rs | 5 + tests/ui/label/label-underscore.stderr | 14 + tests/ui/label/label_break_value_continue.rs | 26 + tests/ui/label/label_break_value_continue.stderr | 25 + .../ui/label/label_break_value_desugared_break.rs | 19 + .../ui/label/label_break_value_illegal_uses.fixed | 29 + tests/ui/label/label_break_value_illegal_uses.rs | 29 + .../ui/label/label_break_value_illegal_uses.stderr | 26 + .../ui/label/label_break_value_unlabeled_break.rs | 19 + .../label/label_break_value_unlabeled_break.stderr | 15 + tests/ui/label/label_misspelled.rs | 62 + tests/ui/label/label_misspelled.stderr | 206 + tests/ui/label/label_misspelled_2.rs | 16 + tests/ui/label/label_misspelled_2.stderr | 37 + tests/ui/lambda-infer-unresolved.rs | 15 + tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs | 27 + .../ui/lang-items/fn-fn_mut-call-ill-formed.stderr | 14 + tests/ui/lang-items/issue-19660.rs | 15 + tests/ui/lang-items/issue-19660.stderr | 4 + tests/ui/lang-items/issue-31076.rs | 17 + tests/ui/lang-items/issue-31076.stderr | 19 + tests/ui/lang-items/issue-83471.rs | 23 + tests/ui/lang-items/issue-83471.stderr | 51 + tests/ui/lang-items/issue-86238.rs | 16 + tests/ui/lang-items/issue-86238.stderr | 10 + tests/ui/lang-items/issue-87573.rs | 28 + tests/ui/lang-items/issue-87573.stderr | 21 + .../lang-items/lang-item-generic-requirements.rs | 59 + .../lang-item-generic-requirements.stderr | 55 + tests/ui/lang-items/lang-item-missing-generator.rs | 21 + .../lang-items/lang-item-missing-generator.stderr | 15 + tests/ui/lang-items/lang-item-missing.rs | 12 + tests/ui/lang-items/lang-item-missing.stderr | 4 + .../ui/lang-items/missing-clone-for-suggestion.rs | 20 + .../lang-items/missing-clone-for-suggestion.stderr | 21 + tests/ui/lang-items/no_owned_box_lang_item.rs | 16 + tests/ui/lang-items/no_owned_box_lang_item.stderr | 4 + tests/ui/lang-items/required-lang-item.rs | 11 + tests/ui/lang-items/required-lang-item.stderr | 4 + .../ui/lang-items/start_lang_item_args.argc.stderr | 8 + .../ui/lang-items/start_lang_item_args.argv.stderr | 8 + .../start_lang_item_args.argv_inner_ptr.stderr | 13 + .../start_lang_item_args.main_args.stderr | 13 + .../start_lang_item_args.main_ret.stderr | 13 + .../lang-items/start_lang_item_args.main_ty.stderr | 8 + .../start_lang_item_args.missing_all_args.stderr | 11 + .../start_lang_item_args.missing_ret.stderr | 8 + ...start_lang_item_args.missing_sigpipe_arg.stderr | 11 + tests/ui/lang-items/start_lang_item_args.rs | 101 + .../lang-items/start_lang_item_args.sigpipe.stderr | 8 + .../start_lang_item_args.start_ret.stderr | 8 + .../start_lang_item_args.too_many_args.stderr | 17 + tests/ui/last-use-in-block.rs | 21 + tests/ui/last-use-in-cap-clause.rs | 17 + tests/ui/last-use-is-capture.rs | 13 + .../auxiliary/upstream_alias.rs | 5 + tests/ui/late-bound-lifetimes/cross_crate_alias.rs | 10 + .../downgraded_to_early_through_alias.rs | 24 + tests/ui/late-bound-lifetimes/issue-36381.rs | 25 + tests/ui/late-bound-lifetimes/issue-47511.rs | 21 + .../late_bound_through_alias.rs | 16 + .../late-bound-lifetimes/mismatched_arg_count.rs | 12 + .../mismatched_arg_count.stderr | 17 + tests/ui/layout/big-type-no-err.rs | 13 + tests/ui/layout/debug.rs | 22 + tests/ui/layout/debug.stderr | 311 + tests/ui/layout/hexagon-enum.rs | 34 + tests/ui/layout/hexagon-enum.stderr | 352 + .../layout/homogeneous-aggr-zero-sized-c-struct.rs | 36 + .../homogeneous-aggr-zero-sized-c-struct.stderr | 14 + .../homogeneous-aggr-zero-sized-repr-rust.rs | 72 + .../homogeneous-aggr-zero-sized-repr-rust.stderr | 32 + .../issue-60431-unsized-tail-behind-projection.rs | 35 + tests/ui/layout/issue-84108.rs | 14 + tests/ui/layout/issue-84108.stderr | 44 + ...sue-96158-scalarpair-payload-might-be-uninit.rs | 54 + ...96158-scalarpair-payload-might-be-uninit.stderr | 655 ++ tests/ui/layout/issue-96185-overaligned-enum.rs | 19 + .../ui/layout/issue-96185-overaligned-enum.stderr | 172 + tests/ui/layout/thin-meta-implies-thin-ptr.rs | 11 + tests/ui/layout/thumb-enum.rs | 34 + tests/ui/layout/thumb-enum.stderr | 352 + tests/ui/layout/unsafe-cell-hides-niche.rs | 82 + tests/ui/layout/valid_range_oob.rs | 15 + tests/ui/layout/valid_range_oob.stderr | 6 + tests/ui/layout/zero-sized-array-enum-niche.rs | 45 + tests/ui/layout/zero-sized-array-enum-niche.stderr | 424 + tests/ui/layout/zero-sized-array-union.rs | 95 + tests/ui/layout/zero-sized-array-union.stderr | 26 + tests/ui/lazy-and-or.rs | 12 + tests/ui/lazy-type-alias-impl-trait/branches.rs | 25 + .../ui/lazy-type-alias-impl-trait/branches.stderr | 13 + tests/ui/lazy-type-alias-impl-trait/branches2.rs | 28 + tests/ui/lazy-type-alias-impl-trait/branches3.rs | 36 + .../ui/lazy-type-alias-impl-trait/branches3.stderr | 47 + .../ui/lazy-type-alias-impl-trait/freeze_cycle.rs | 46 + .../infer_cross_function.rs | 27 + .../lifetime_inference.rs | 7 + tests/ui/lazy-type-alias-impl-trait/nested.rs | 23 + .../lazy-type-alias-impl-trait/opaque_vs_opaque.rs | 10 + tests/ui/lazy-type-alias-impl-trait/recursion.rs | 23 + tests/ui/lazy-type-alias-impl-trait/recursion2.rs | 23 + tests/ui/lazy-type-alias-impl-trait/recursion3.rs | 21 + .../lazy-type-alias-impl-trait/recursion3.stderr | 19 + tests/ui/lazy-type-alias-impl-trait/recursion4.rs | 23 + .../lazy-type-alias-impl-trait/recursion4.stderr | 23 + .../unsized_sized_opaque.rs | 16 + tests/ui/let-else/const-fn.rs | 18 + tests/ui/let-else/issue-100103.rs | 15 + tests/ui/let-else/issue-102317.rs | 20 + tests/ui/let-else/issue-94176.rs | 10 + tests/ui/let-else/issue-94176.stderr | 19 + tests/ui/let-else/issue-99975.rs | 20 + tests/ui/let-else/let-else-allow-in-expr.rs | 28 + tests/ui/let-else/let-else-allow-in-expr.stderr | 20 + tests/ui/let-else/let-else-allow-unused.rs | 15 + tests/ui/let-else/let-else-allow-unused.stderr | 14 + .../let-else-binding-explicit-mut-annotated.rs | 16 + .../let-else-binding-explicit-mut-annotated.stderr | 25 + .../let-else-binding-explicit-mut-borrow.rs | 13 + .../let-else-binding-explicit-mut-borrow.stderr | 9 + .../let-else/let-else-binding-explicit-mut-pass.rs | 13 + tests/ui/let-else/let-else-binding-explicit-mut.rs | 20 + .../let-else/let-else-binding-explicit-mut.stderr | 21 + tests/ui/let-else/let-else-binding-immutable.rs | 10 + .../ui/let-else/let-else-binding-immutable.stderr | 9 + tests/ui/let-else/let-else-bindings.rs | 75 + tests/ui/let-else/let-else-bool-binop-init.fixed | 8 + tests/ui/let-else/let-else-bool-binop-init.rs | 8 + tests/ui/let-else/let-else-bool-binop-init.stderr | 24 + tests/ui/let-else/let-else-brace-before-else.fixed | 26 + tests/ui/let-else/let-else-brace-before-else.rs | 26 + .../ui/let-else/let-else-brace-before-else.stderr | 46 + tests/ui/let-else/let-else-check.rs | 17 + tests/ui/let-else/let-else-check.stderr | 20 + .../let-else/let-else-deref-coercion-annotated.rs | 77 + tests/ui/let-else/let-else-deref-coercion.rs | 75 + tests/ui/let-else/let-else-deref-coercion.stderr | 19 + tests/ui/let-else/let-else-destructuring.rs | 17 + tests/ui/let-else/let-else-destructuring.stderr | 17 + tests/ui/let-else/let-else-drop-order.rs | 270 + tests/ui/let-else/let-else-drop-order.run.stdout | 51 + tests/ui/let-else/let-else-if.rs | 8 + tests/ui/let-else/let-else-if.stderr | 17 + tests/ui/let-else/let-else-irrefutable.rs | 11 + tests/ui/let-else/let-else-irrefutable.stderr | 21 + tests/ui/let-else/let-else-missing-semicolon.rs | 9 + .../ui/let-else/let-else-missing-semicolon.stderr | 18 + tests/ui/let-else/let-else-no-double-error.rs | 12 + tests/ui/let-else/let-else-no-double-error.stderr | 9 + tests/ui/let-else/let-else-non-copy.rs | 45 + tests/ui/let-else/let-else-non-diverging.rs | 22 + tests/ui/let-else/let-else-non-diverging.stderr | 55 + tests/ui/let-else/let-else-ref-bindings-pass.rs | 71 + tests/ui/let-else/let-else-ref-bindings.rs | 62 + tests/ui/let-else/let-else-ref-bindings.stderr | 83 + tests/ui/let-else/let-else-run-pass.rs | 35 + tests/ui/let-else/let-else-scope.rs | 5 + tests/ui/let-else/let-else-scope.stderr | 9 + tests/ui/let-else/let-else-slicing-error.rs | 9 + tests/ui/let-else/let-else-slicing-error.stderr | 11 + .../let-else/let-else-source-expr-nomove-pass.rs | 17 + tests/ui/let-else/let-else-temp-borrowck.rs | 26 + tests/ui/let-else/let-else-temporary-lifetime.rs | 99 + tests/ui/let-else/let-else-then-diverge.rs | 17 + tests/ui/let-else/let-else-then-diverge.stderr | 14 + tests/ui/let-else/let-else.rs | 8 + tests/ui/lexer/error-stage.rs | 80 + tests/ui/lexer/error-stage.stderr | 56 + tests/ui/lexer/lex-bad-binary-literal.rs | 11 + tests/ui/lexer/lex-bad-binary-literal.stderr | 56 + tests/ui/lexer/lex-bad-char-literals-1.rs | 17 + tests/ui/lexer/lex-bad-char-literals-1.stderr | 38 + tests/ui/lexer/lex-bad-char-literals-2.rs | 6 + tests/ui/lexer/lex-bad-char-literals-2.stderr | 13 + tests/ui/lexer/lex-bad-char-literals-3.rs | 7 + tests/ui/lexer/lex-bad-char-literals-3.stderr | 24 + tests/ui/lexer/lex-bad-char-literals-4.rs | 5 + tests/ui/lexer/lex-bad-char-literals-4.stderr | 9 + tests/ui/lexer/lex-bad-char-literals-5.rs | 7 + tests/ui/lexer/lex-bad-char-literals-5.stderr | 24 + tests/ui/lexer/lex-bad-char-literals-6.rs | 15 + tests/ui/lexer/lex-bad-char-literals-6.stderr | 44 + tests/ui/lexer/lex-bad-char-literals-7.rs | 13 + tests/ui/lexer/lex-bad-char-literals-7.stderr | 21 + tests/ui/lexer/lex-bad-numeric-literals.rs | 35 + tests/ui/lexer/lex-bad-numeric-literals.stderr | 169 + tests/ui/lexer/lex-bad-octal-literal.rs | 4 + tests/ui/lexer/lex-bad-octal-literal.stderr | 14 + tests/ui/lexer/lex-bad-token.rs | 3 + tests/ui/lexer/lex-bad-token.stderr | 8 + tests/ui/lexer/lex-bare-cr-nondoc-comment.rs | 9 + .../lex-bare-cr-string-literal-doc-comment.rs | 26 + .../lex-bare-cr-string-literal-doc-comment.stderr | 46 + tests/ui/lexer/lex-emoji-identifiers.rs | 17 + tests/ui/lexer/lex-emoji-identifiers.stderr | 52 + tests/ui/lexer/lex-stray-backslash.rs | 3 + tests/ui/lexer/lex-stray-backslash.stderr | 8 + ...crlf-line-endings-string-literal-doc-comment.rs | 38 + tests/ui/lexical-scopes.rs | 13 + tests/ui/lexical-scopes.stderr | 22 + tests/ui/lexical-scoping.rs | 19 + tests/ui/lifetimes/auxiliary/issue-91763-aux.rs | 47 + .../lifetime_bound_will_change_warning_lib.rs | 11 + tests/ui/lifetimes/bare-trait-object-borrowck.rs | 24 + tests/ui/lifetimes/bare-trait-object.rs | 25 + tests/ui/lifetimes/borrowck-let-suggestion.rs | 12 + tests/ui/lifetimes/borrowck-let-suggestion.stderr | 17 + tests/ui/lifetimes/conflicting-bounds.rs | 11 + tests/ui/lifetimes/conflicting-bounds.stderr | 14 + tests/ui/lifetimes/copy_modulo_regions.rs | 17 + tests/ui/lifetimes/copy_modulo_regions.stderr | 14 + tests/ui/lifetimes/elided-lifetime-in-param-pat.rs | 11 + .../elided-lifetime-in-path-in-impl-Fn.rs | 19 + .../ui/lifetimes/elided-lifetime-in-path-in-pat.rs | 13 + ...lifetime-in-path-in-type-relative-expression.rs | 17 + tests/ui/lifetimes/fullwidth-ampersand.rs | 7 + tests/ui/lifetimes/fullwidth-ampersand.stderr | 26 + tests/ui/lifetimes/issue-105227.fixed | 26 + tests/ui/lifetimes/issue-105227.rs | 26 + tests/ui/lifetimes/issue-105227.stderr | 47 + tests/ui/lifetimes/issue-105507.fixed | 43 + tests/ui/lifetimes/issue-105507.rs | 43 + tests/ui/lifetimes/issue-105507.stderr | 34 + tests/ui/lifetimes/issue-17728.rs | 122 + tests/ui/lifetimes/issue-17728.stderr | 21 + tests/ui/lifetimes/issue-26638.rs | 13 + tests/ui/lifetimes/issue-26638.stderr | 73 + tests/ui/lifetimes/issue-34979.rs | 9 + tests/ui/lifetimes/issue-34979.stderr | 20 + tests/ui/lifetimes/issue-54378.rs | 26 + tests/ui/lifetimes/issue-55796.rs | 26 + tests/ui/lifetimes/issue-55796.stderr | 20 + tests/ui/lifetimes/issue-64173-unused-lifetimes.rs | 19 + .../lifetimes/issue-64173-unused-lifetimes.stderr | 35 + tests/ui/lifetimes/issue-67498.rs | 21 + .../lifetimes/issue-70917-lifetimes-in-fn-def.rs | 13 + tests/ui/lifetimes/issue-76168-hr-outlives-2.rs | 22 + tests/ui/lifetimes/issue-76168-hr-outlives.rs | 19 + tests/ui/lifetimes/issue-77175.rs | 19 + tests/ui/lifetimes/issue-79187-2.rs | 29 + tests/ui/lifetimes/issue-79187-2.stderr | 77 + tests/ui/lifetimes/issue-79187.rs | 8 + tests/ui/lifetimes/issue-79187.stderr | 31 + .../lifetimes/issue-83737-binders-across-types.rs | 14 + .../ui/lifetimes/issue-83737-erasing-bound-vars.rs | 14 + ...3753-invalid-associated-type-supertrait-hrtb.rs | 8 + ...-invalid-associated-type-supertrait-hrtb.stderr | 9 + .../lifetimes/issue-83907-invalid-fn-like-path.rs | 7 + .../issue-83907-invalid-fn-like-path.stderr | 17 + tests/ui/lifetimes/issue-84398.rs | 20 + tests/ui/lifetimes/issue-84604.rs | 9 + .../lifetimes/issue-90170-elision-mismatch.fixed | 9 + tests/ui/lifetimes/issue-90170-elision-mismatch.rs | 9 + .../lifetimes/issue-90170-elision-mismatch.stderr | 44 + .../issue-90600-expected-return-static-indirect.rs | 15 + ...ue-90600-expected-return-static-indirect.stderr | 24 + tests/ui/lifetimes/issue-91763.rs | 11 + tests/ui/lifetimes/issue-91763.stderr | 18 + tests/ui/lifetimes/issue-95023.rs | 11 + tests/ui/lifetimes/issue-95023.stderr | 38 + tests/ui/lifetimes/issue-97193.rs | 9 + tests/ui/lifetimes/issue-97193.stderr | 28 + tests/ui/lifetimes/issue-97194.rs | 10 + tests/ui/lifetimes/issue-97194.stderr | 36 + .../lifetime-bound-will-change-warning.rs | 56 + .../lifetime-bound-will-change-warning.stderr | 31 + .../lifetimes/lifetime-doesnt-live-long-enough.rs | 49 + .../lifetime-doesnt-live-long-enough.stderr | 68 + ...ision-return-type-requires-explicit-lifetime.rs | 51 + ...n-return-type-requires-explicit-lifetime.stderr | 87 + .../lifetime-elision-return-type-trait.rs | 13 + .../lifetime-elision-return-type-trait.stderr | 9 + .../42701_one_named_and_one_anonymous.rs | 14 + .../42701_one_named_and_one_anonymous.stderr | 12 + ...turn-one-existing-name-early-bound-in-struct.rs | 20 + ...-one-existing-name-early-bound-in-struct.stderr | 12 + .../ex1-return-one-existing-name-if-else-2.rs | 5 + .../ex1-return-one-existing-name-if-else-2.stderr | 11 + .../ex1-return-one-existing-name-if-else-3.rs | 5 + .../ex1-return-one-existing-name-if-else-3.stderr | 11 + ...eturn-one-existing-name-if-else-using-impl-2.rs | 8 + ...n-one-existing-name-if-else-using-impl-2.stderr | 11 + ...eturn-one-existing-name-if-else-using-impl-3.rs | 14 + ...n-one-existing-name-if-else-using-impl-3.stderr | 12 + ...-return-one-existing-name-if-else-using-impl.rs | 18 + ...urn-one-existing-name-if-else-using-impl.stderr | 13 + .../ex1-return-one-existing-name-if-else.rs | 5 + .../ex1-return-one-existing-name-if-else.stderr | 11 + ...return-one-existing-name-return-type-is-anon.rs | 15 + ...rn-one-existing-name-return-type-is-anon.stderr | 13 + .../ex1-return-one-existing-name-self-is-anon.rs | 14 + ...x1-return-one-existing-name-self-is-anon.stderr | 13 + .../ex1b-return-no-names-if-else.rs | 5 + .../ex1b-return-no-names-if-else.stderr | 15 + .../ex2a-push-one-existing-name-2.rs | 9 + .../ex2a-push-one-existing-name-2.stderr | 11 + .../ex2a-push-one-existing-name-early-bound.rs | 11 + .../ex2a-push-one-existing-name-early-bound.stderr | 12 + .../lifetime-errors/ex2a-push-one-existing-name.rs | 9 + .../ex2a-push-one-existing-name.stderr | 11 + .../lifetime-errors/ex2b-push-no-existing-names.rs | 10 + .../ex2b-push-no-existing-names.stderr | 12 + .../ex2c-push-inference-variable.rs | 11 + .../ex2c-push-inference-variable.stderr | 15 + .../ex2d-push-inference-variable-2.rs | 12 + .../ex2d-push-inference-variable-2.stderr | 15 + .../ex2e-push-inference-variable-3.rs | 12 + .../ex2e-push-inference-variable-3.stderr | 15 + .../lifetime-errors/ex3-both-anon-regions-2.rs | 6 + .../lifetime-errors/ex3-both-anon-regions-2.stderr | 17 + .../lifetime-errors/ex3-both-anon-regions-3.rs | 7 + .../lifetime-errors/ex3-both-anon-regions-3.stderr | 32 + .../ex3-both-anon-regions-both-are-structs-2.rs | 11 + ...ex3-both-anon-regions-both-are-structs-2.stderr | 12 + .../ex3-both-anon-regions-both-are-structs-3.rs | 11 + ...ex3-both-anon-regions-both-are-structs-3.stderr | 13 + ...-regions-both-are-structs-earlybound-regions.rs | 13 + ...ions-both-are-structs-earlybound-regions.stderr | 15 + ...n-regions-both-are-structs-latebound-regions.rs | 10 + ...gions-both-are-structs-latebound-regions.stderr | 14 + .../ex3-both-anon-regions-both-are-structs.rs | 10 + .../ex3-both-anon-regions-both-are-structs.stderr | 12 + .../ex3-both-anon-regions-latebound-regions.rs | 6 + .../ex3-both-anon-regions-latebound-regions.stderr | 14 + .../ex3-both-anon-regions-one-is-struct-2.rs | 9 + .../ex3-both-anon-regions-one-is-struct-2.stderr | 21 + .../ex3-both-anon-regions-one-is-struct-3.rs | 8 + .../ex3-both-anon-regions-one-is-struct-3.stderr | 12 + .../ex3-both-anon-regions-one-is-struct-4.rs | 8 + .../ex3-both-anon-regions-one-is-struct-4.stderr | 12 + .../ex3-both-anon-regions-one-is-struct.rs | 11 + .../ex3-both-anon-regions-one-is-struct.stderr | 12 + .../ex3-both-anon-regions-return-type-is-anon.rs | 12 + ...x3-both-anon-regions-return-type-is-anon.stderr | 17 + .../ex3-both-anon-regions-self-is-anon.rs | 12 + .../ex3-both-anon-regions-self-is-anon.stderr | 17 + .../ex3-both-anon-regions-using-fn-items.rs | 7 + .../ex3-both-anon-regions-using-fn-items.stderr | 29 + .../ex3-both-anon-regions-using-impl-items.rs | 10 + .../ex3-both-anon-regions-using-impl-items.stderr | 17 + .../ex3-both-anon-regions-using-trait-objects.rs | 7 + ...x3-both-anon-regions-using-trait-objects.stderr | 29 + .../lifetime-errors/ex3-both-anon-regions.rs | 6 + .../lifetime-errors/ex3-both-anon-regions.stderr | 17 + tests/ui/lifetimes/lifetime-errors/issue_74400.rs | 16 + .../lifetimes/lifetime-errors/issue_74400.stderr | 38 + .../liveness-assign-imm-local-notes.rs | 37 + .../liveness-assign-imm-local-notes.stderr | 46 + .../lifetime-mismatch-between-trait-and-impl.rs | 12 + ...lifetime-mismatch-between-trait-and-impl.stderr | 16 + tests/ui/lifetimes/lifetime-no-keyword.rs | 7 + tests/ui/lifetimes/lifetime-no-keyword.stderr | 26 + tests/ui/lifetimes/missing-lifetime-in-alias.rs | 31 + .../ui/lifetimes/missing-lifetime-in-alias.stderr | 47 + tests/ui/lifetimes/nested-binder-print.rs | 10 + tests/ui/lifetimes/nested-binder-print.stderr | 14 + tests/ui/lifetimes/nested.rs | 7 + tests/ui/lifetimes/re-empty-in-error.rs | 10 + tests/ui/lifetimes/re-empty-in-error.stderr | 10 + tests/ui/lifetimes/shadow.rs | 8 + tests/ui/lifetimes/shadow.stderr | 20 + ...t-introducing-and-adding-missing-lifetime.fixed | 13 + ...gest-introducing-and-adding-missing-lifetime.rs | 13 + ...-introducing-and-adding-missing-lifetime.stderr | 24 + ...red-lifetime-used-in-debug-macro-issue-70152.rs | 16 + ...lifetime-used-in-debug-macro-issue-70152.stderr | 36 + ...-closure-doesnt-life-long-enough-issue-67634.rs | 3 + ...sure-doesnt-life-long-enough-issue-67634.stderr | 21 + tests/ui/lifetimes/unusual-rib-combinations.rs | 28 + tests/ui/lifetimes/unusual-rib-combinations.stderr | 61 + tests/ui/limits/huge-array-simple-32.rs | 12 + tests/ui/limits/huge-array-simple-32.stderr | 8 + tests/ui/limits/huge-array-simple-64.rs | 12 + tests/ui/limits/huge-array-simple-64.stderr | 8 + tests/ui/limits/huge-array.rs | 15 + tests/ui/limits/huge-array.stderr | 8 + tests/ui/limits/huge-enum.rs | 18 + tests/ui/limits/huge-enum.stderr | 8 + tests/ui/limits/huge-struct.rs | 53 + tests/ui/limits/huge-struct.stderr | 8 + tests/ui/limits/issue-15919-32.rs | 13 + tests/ui/limits/issue-15919-32.stderr | 8 + tests/ui/limits/issue-15919-64.rs | 13 + tests/ui/limits/issue-15919-64.stderr | 8 + tests/ui/limits/issue-17913.rs | 21 + tests/ui/limits/issue-17913.stderr | 4 + tests/ui/limits/issue-55878.rs | 8 + tests/ui/limits/issue-55878.stderr | 38 + tests/ui/limits/issue-56762.rs | 24 + tests/ui/limits/issue-56762.stderr | 15 + .../limits/issue-69485-var-size-diffs-too-large.rs | 11 + .../issue-69485-var-size-diffs-too-large.stderr | 8 + tests/ui/limits/issue-75158-64.rs | 16 + tests/ui/limits/issue-75158-64.stderr | 4 + tests/ui/link-section.rs | 37 + .../auxiliary/def_colliding_external.rs | 7 + tests/ui/linkage-attr/auxiliary/def_external.rs | 5 + .../auxiliary/link-cfg-works-transitive-dylib.rs | 4 + .../auxiliary/link-cfg-works-transitive-rlib.rs | 7 + tests/ui/linkage-attr/auxiliary/linkage1.rs | 4 + tests/ui/linkage-attr/issue-10755.rs | 10 + .../ui/linkage-attr/link-attr-validation-early.rs | 8 + .../linkage-attr/link-attr-validation-early.stderr | 21 + tests/ui/linkage-attr/link-attr-validation-late.rs | 39 + .../linkage-attr/link-attr-validation-late.stderr | 147 + tests/ui/linkage-attr/link-cfg-works.rs | 13 + ...nkage-detect-extern-generated-name-collision.rs | 24 + ...e-detect-extern-generated-name-collision.stderr | 8 + ...inkage-detect-local-generated-name-collision.rs | 26 + ...ge-detect-local-generated-name-collision.stderr | 8 + tests/ui/linkage-attr/linkage-import.rs | 8 + tests/ui/linkage-attr/linkage1.rs | 32 + tests/ui/linkage-attr/linkage2.rs | 13 + tests/ui/linkage-attr/linkage2.stderr | 9 + tests/ui/linkage-attr/linkage3.rs | 17 + tests/ui/linkage-attr/linkage3.stderr | 8 + tests/ui/linkage-attr/linkage4.rs | 5 + tests/ui/linkage-attr/linkage4.stderr | 12 + tests/ui/lint-unknown-lints-at-crate-level.rs | 7 + tests/ui/lint/auxiliary/add-impl.rs | 22 + tests/ui/lint/auxiliary/external_extern_fn.rs | 3 + tests/ui/lint/auxiliary/inherited_stability.rs | 47 + tests/ui/lint/auxiliary/lint_output_format.rs | 20 + tests/ui/lint/auxiliary/lint_stability.rs | 188 + tests/ui/lint/auxiliary/lint_stability_fields.rs | 66 + tests/ui/lint/auxiliary/lints-in-foreign-macros.rs | 14 + tests/ui/lint/auxiliary/stability-cfg2.rs | 5 + tests/ui/lint/auxiliary/stability_cfg1.rs | 3 + tests/ui/lint/auxiliary/stability_cfg2.rs | 5 + tests/ui/lint/auxiliary/trivial-cast-ice.rs | 7 + .../unaligned_references_external_crate.rs | 28 + tests/ui/lint/bad-lint-cap.rs | 4 + tests/ui/lint/bad-lint-cap.stderr | 2 + tests/ui/lint/bad-lint-cap2.rs | 8 + tests/ui/lint/bad-lint-cap2.stderr | 15 + tests/ui/lint/bad-lint-cap3.rs | 9 + tests/ui/lint/bad-lint-cap3.stderr | 15 + tests/ui/lint/bare-trait-objects-path.rs | 26 + tests/ui/lint/bare-trait-objects-path.stderr | 62 + tests/ui/lint/clashing-extern-fn-recursion.rs | 119 + tests/ui/lint/clashing-extern-fn-wasm.rs | 21 + tests/ui/lint/clashing-extern-fn.rs | 417 + tests/ui/lint/clashing-extern-fn.stderr | 236 + tests/ui/lint/cli-lint-override.forbid_warn.stderr | 11 + .../lint/cli-lint-override.force_warn_deny.stderr | 11 + tests/ui/lint/cli-lint-override.rs | 17 + tests/ui/lint/cli-lint-override.warn_deny.stderr | 11 + tests/ui/lint/cli-unknown-force-warn.rs | 7 + tests/ui/lint/cli-unknown-force-warn.stderr | 11 + tests/ui/lint/command-line-lint-group-allow.rs | 6 + tests/ui/lint/command-line-lint-group-deny.rs | 5 + tests/ui/lint/command-line-lint-group-deny.stderr | 10 + tests/ui/lint/command-line-lint-group-forbid.rs | 5 + .../ui/lint/command-line-lint-group-forbid.stderr | 10 + tests/ui/lint/command-line-lint-group-warn.rs | 7 + tests/ui/lint/command-line-lint-group-warn.stderr | 10 + tests/ui/lint/command-line-register-lint-tool.rs | 7 + .../command-line-register-unknown-lint-tool.rs | 4 + .../command-line-register-unknown-lint-tool.stderr | 11 + tests/ui/lint/crate_level_only_lint.rs | 22 + tests/ui/lint/crate_level_only_lint.stderr | 62 + tests/ui/lint/dead-code/alias-in-pat.rs | 10 + tests/ui/lint/dead-code/anon-const-in-pat.rs | 45 + tests/ui/lint/dead-code/associated-type.rs | 19 + tests/ui/lint/dead-code/basic.rs | 15 + tests/ui/lint/dead-code/basic.stderr | 14 + tests/ui/lint/dead-code/closure-bang.rs | 9 + tests/ui/lint/dead-code/const-and-self.rs | 54 + tests/ui/lint/dead-code/const-and-self.stderr | 19 + tests/ui/lint/dead-code/empty-unused-enum.rs | 5 + tests/ui/lint/dead-code/empty-unused-enum.stderr | 15 + .../ui/lint/dead-code/empty-unused-public-enum.rs | 6 + tests/ui/lint/dead-code/enum-variants.rs | 14 + tests/ui/lint/dead-code/impl-trait.rs | 18 + tests/ui/lint/dead-code/impl-trait.stderr | 14 + .../lint/dead-code/issue-68408-false-positive.rs | 22 + tests/ui/lint/dead-code/issue-85071-2.rs | 22 + tests/ui/lint/dead-code/issue-85071-2.stderr | 34 + tests/ui/lint/dead-code/issue-85071.rs | 19 + tests/ui/lint/dead-code/issue-85071.stderr | 34 + tests/ui/lint/dead-code/issue-85255.rs | 50 + tests/ui/lint/dead-code/issue-85255.stderr | 74 + tests/ui/lint/dead-code/leading-underscore.rs | 31 + tests/ui/lint/dead-code/lint-dead-code-1.rs | 110 + tests/ui/lint/dead-code/lint-dead-code-1.stderr | 71 + tests/ui/lint/dead-code/lint-dead-code-2.rs | 41 + tests/ui/lint/dead-code/lint-dead-code-2.stderr | 26 + tests/ui/lint/dead-code/lint-dead-code-3.rs | 90 + tests/ui/lint/dead-code/lint-dead-code-3.stderr | 50 + tests/ui/lint/dead-code/lint-dead-code-4.rs | 83 + tests/ui/lint/dead-code/lint-dead-code-4.stderr | 66 + tests/ui/lint/dead-code/lint-dead-code-5.rs | 50 + tests/ui/lint/dead-code/lint-dead-code-5.stderr | 34 + tests/ui/lint/dead-code/lint-dead-code-6.rs | 20 + tests/ui/lint/dead-code/lint-dead-code-6.stderr | 32 + .../multiple-dead-codes-in-the-same-struct.rs | 29 + .../multiple-dead-codes-in-the-same-struct.stderr | 55 + tests/ui/lint/dead-code/newline-span.rs | 19 + tests/ui/lint/dead-code/newline-span.stderr | 26 + tests/ui/lint/dead-code/self-assign.rs | 52 + tests/ui/lint/dead-code/self-assign.stderr | 44 + tests/ui/lint/dead-code/trait-impl.rs | 19 + tests/ui/lint/dead-code/tuple-struct-field.rs | 37 + tests/ui/lint/dead-code/tuple-struct-field.stderr | 33 + tests/ui/lint/dead-code/type-alias.rs | 10 + tests/ui/lint/dead-code/type-alias.stderr | 14 + tests/ui/lint/dead-code/type-in-foreign.rs | 19 + tests/ui/lint/dead-code/unused-enum.rs | 12 + tests/ui/lint/dead-code/unused-enum.stderr | 27 + tests/ui/lint/dead-code/unused-struct-variant.rs | 13 + .../ui/lint/dead-code/unused-struct-variant.stderr | 18 + tests/ui/lint/dead-code/unused-variant-pub.rs | 14 + tests/ui/lint/dead-code/unused-variant.rs | 12 + tests/ui/lint/dead-code/unused-variant.stderr | 17 + tests/ui/lint/dead-code/with-core-crate.rs | 18 + tests/ui/lint/dead-code/with-core-crate.stderr | 14 + tests/ui/lint/dead-code/with-impl.rs | 17 + tests/ui/lint/deny-overflowing-literals.rs | 7 + tests/ui/lint/deny-overflowing-literals.stderr | 17 + tests/ui/lint/empty-lint-attributes.rs | 17 + tests/ui/lint/enable-unstable-lib-feature.rs | 13 + tests/ui/lint/enable-unstable-lib-feature.stderr | 14 + tests/ui/lint/expansion-time-include.rs | 4 + tests/ui/lint/expansion-time.rs | 33 + tests/ui/lint/expansion-time.stderr | 56 + tests/ui/lint/expr_attr_paren_order.rs | 22 + tests/ui/lint/expr_attr_paren_order.stderr | 14 + tests/ui/lint/fn_must_use.rs | 76 + tests/ui/lint/fn_must_use.stderr | 69 + tests/ui/lint/for_loop_over_fallibles.rs | 43 + tests/ui/lint/for_loop_over_fallibles.stderr | 101 + tests/ui/lint/forbid-error-capped.rs | 15 + tests/ui/lint/forbid-group-group-1.rs | 13 + tests/ui/lint/forbid-group-group-1.stderr | 15 + tests/ui/lint/forbid-group-group-2.rs | 26 + tests/ui/lint/forbid-group-group-2.stderr | 115 + tests/ui/lint/forbid-group-member.rs | 17 + tests/ui/lint/forbid-group-member.stderr | 39 + tests/ui/lint/forbid-member-group.rs | 11 + tests/ui/lint/forbid-member-group.stderr | 21 + tests/ui/lint/force-warn/allow-warnings.rs | 11 + tests/ui/lint/force-warn/allow-warnings.stderr | 10 + .../ui/lint/force-warn/allowed-by-default-lint.rs | 12 + .../lint/force-warn/allowed-by-default-lint.stderr | 14 + .../force-warn/allowed-cli-deny-by-default-lint.rs | 10 + .../allowed-cli-deny-by-default-lint.stderr | 10 + .../force-warn/allowed-deny-by-default-lint.rs | 11 + .../force-warn/allowed-deny-by-default-lint.stderr | 10 + .../allowed-group-warn-by-default-lint.rs | 18 + .../allowed-group-warn-by-default-lint.stderr | 42 + .../force-warn/allowed-warn-by-default-lint.rs | 11 + .../force-warn/allowed-warn-by-default-lint.stderr | 10 + tests/ui/lint/force-warn/cap-lints-allow.rs | 16 + tests/ui/lint/force-warn/cap-lints-allow.stderr | 42 + .../cap-lints-warn-allowed-warn-by-default-lint.rs | 17 + ...-lints-warn-allowed-warn-by-default-lint.stderr | 12 + tests/ui/lint/force-warn/deny-by-default-lint.rs | 9 + .../ui/lint/force-warn/deny-by-default-lint.stderr | 10 + .../lint/force-warn/lint-group-allow-warnings.rs | 12 + .../force-warn/lint-group-allow-warnings.stderr | 10 + .../lint-group-allowed-cli-warn-by-default-lint.rs | 16 + ...t-group-allowed-cli-warn-by-default-lint.stderr | 42 + .../force-warn/lint-group-allowed-lint-group.rs | 18 + .../lint-group-allowed-lint-group.stderr | 42 + .../lint-group-allowed-warn-by-default-lint.rs | 18 + .../lint-group-allowed-warn-by-default-lint.stderr | 42 + .../force-warn/warn-by-default-lint-two-modules.rs | 18 + .../warn-by-default-lint-two-modules.stderr | 16 + tests/ui/lint/force-warn/warnings-lint-group.rs | 5 + .../ui/lint/force-warn/warnings-lint-group.stderr | 7 + tests/ui/lint/function-item-references.rs | 169 + tests/ui/lint/function-item-references.stderr | 206 + tests/ui/lint/future-incompat-test.rs | 10 + tests/ui/lint/future-incompat-test.stderr | 9 + tests/ui/lint/inclusive-range-pattern-syntax.fixed | 21 + tests/ui/lint/inclusive-range-pattern-syntax.rs | 21 + .../ui/lint/inclusive-range-pattern-syntax.stderr | 25 + tests/ui/lint/inert-attr-macro.rs | 20 + tests/ui/lint/inert-attr-macro.stderr | 44 + tests/ui/lint/inline-trait-and-foreign-items.rs | 37 + .../ui/lint/inline-trait-and-foreign-items.stderr | 74 + tests/ui/lint/invalid_value.rs | 169 + tests/ui/lint/invalid_value.stderr | 676 ++ tests/ui/lint/issue-101284.rs | 15 + tests/ui/lint/issue-102705.rs | 22 + tests/ui/lint/issue-103317.fixed | 14 + tests/ui/lint/issue-103317.rs | 14 + tests/ui/lint/issue-103317.stderr | 17 + tests/ui/lint/issue-103435-extra-parentheses.fixed | 18 + tests/ui/lint/issue-103435-extra-parentheses.rs | 18 + .../ui/lint/issue-103435-extra-parentheses.stderr | 61 + tests/ui/lint/issue-104392.rs | 11 + tests/ui/lint/issue-104392.stderr | 27 + tests/ui/lint/issue-104897.rs | 6 + tests/ui/lint/issue-104897.stderr | 43 + tests/ui/lint/issue-108155.rs | 15 + tests/ui/lint/issue-14309.rs | 39 + tests/ui/lint/issue-14309.stderr | 77 + tests/ui/lint/issue-14837.rs | 11 + tests/ui/lint/issue-17718-const-naming.rs | 8 + tests/ui/lint/issue-17718-const-naming.stderr | 23 + tests/ui/lint/issue-1866.rs | 29 + tests/ui/lint/issue-1866.stderr | 19 + tests/ui/lint/issue-20343.rs | 32 + tests/ui/lint/issue-30302.rs | 20 + tests/ui/lint/issue-30302.stderr | 26 + tests/ui/lint/issue-31924-non-snake-ffi.rs | 15 + tests/ui/lint/issue-34798.rs | 25 + tests/ui/lint/issue-35075.rs | 9 + tests/ui/lint/issue-35075.stderr | 25 + ...ue-47775-nested-macro-unnecessary-parens-arg.rs | 27 + .../issue-54099-camel-case-underscore-types.rs | 14 + tests/ui/lint/issue-57410-1.rs | 18 + tests/ui/lint/issue-57410.rs | 17 + tests/ui/lint/issue-63364.rs | 10 + tests/ui/lint/issue-63364.stderr | 11 + ...e-66362-no-snake-case-warning-for-field-puns.rs | 29 + ...362-no-snake-case-warning-for-field-puns.stderr | 32 + ...sue-70819-dont-override-forbid-in-same-scope.rs | 50 + ...70819-dont-override-forbid-in-same-scope.stderr | 18 + tests/ui/lint/issue-79546-fuel-ice.rs | 8 + tests/ui/lint/issue-79744.rs | 13 + tests/ui/lint/issue-79744.stderr | 12 + tests/ui/lint/issue-80988.rs | 14 + tests/ui/lint/issue-80988.stderr | 39 + tests/ui/lint/issue-81218.rs | 14 + tests/ui/lint/issue-83477.rs | 16 + tests/ui/lint/issue-83477.stderr | 30 + tests/ui/lint/issue-86600-lint-twice.rs | 15 + tests/ui/lint/issue-86600-lint-twice.stderr | 12 + tests/ui/lint/issue-87274-paren-parent.rs | 9 + tests/ui/lint/issue-87274-paren-parent.stderr | 10 + tests/ui/lint/issue-89469.rs | 20 + ...low-text-direction-codepoint-in-comment-lint.rs | 9 + tests/ui/lint/issue-97094.rs | 50 + tests/ui/lint/issue-97094.stderr | 53 + tests/ui/lint/issue-99387.rs | 24 + tests/ui/lint/known-tool-in-submodule/root.rs | 10 + tests/ui/lint/known-tool-in-submodule/submodule.rs | 4 + .../ui/lint/let_underscore/let_underscore_drop.rs | 14 + .../lint/let_underscore/let_underscore_drop.stderr | 22 + .../ui/lint/let_underscore/let_underscore_lock.rs | 7 + .../lint/let_underscore/let_underscore_lock.stderr | 20 + tests/ui/lint/lint-attr-everywhere-early.rs | 176 + tests/ui/lint/lint-attr-everywhere-early.stderr | 486 + tests/ui/lint/lint-attr-everywhere-late.rs | 197 + tests/ui/lint/lint-attr-everywhere-late.stderr | 428 + tests/ui/lint/lint-attr-non-item-node.rs | 9 + tests/ui/lint/lint-attr-non-item-node.stderr | 16 + tests/ui/lint/lint-cap.rs | 8 + tests/ui/lint/lint-change-warnings.rs | 21 + tests/ui/lint/lint-change-warnings.stderr | 36 + tests/ui/lint/lint-const-item-mutation.rs | 66 + tests/ui/lint/lint-const-item-mutation.stderr | 118 + tests/ui/lint/lint-ctypes-66202.rs | 17 + tests/ui/lint/lint-ctypes-73249-1.rs | 21 + tests/ui/lint/lint-ctypes-73249-2.rs | 29 + tests/ui/lint/lint-ctypes-73249-2.stderr | 15 + tests/ui/lint/lint-ctypes-73249-3.rs | 23 + tests/ui/lint/lint-ctypes-73249-3.stderr | 15 + tests/ui/lint/lint-ctypes-73249-4.rs | 24 + tests/ui/lint/lint-ctypes-73249-5.rs | 23 + tests/ui/lint/lint-ctypes-73249-5.stderr | 15 + tests/ui/lint/lint-ctypes-73249.rs | 21 + tests/ui/lint/lint-ctypes-73251-1.rs | 26 + tests/ui/lint/lint-ctypes-73251-1.stderr | 15 + tests/ui/lint/lint-ctypes-73251-2.rs | 39 + tests/ui/lint/lint-ctypes-73251-2.stderr | 15 + tests/ui/lint/lint-ctypes-73251.rs | 22 + tests/ui/lint/lint-ctypes-73747.rs | 14 + tests/ui/lint/lint-ctypes-enum.rs | 92 + tests/ui/lint/lint-ctypes-enum.stderr | 92 + tests/ui/lint/lint-ctypes-fn.rs | 196 + tests/ui/lint/lint-ctypes-fn.stderr | 188 + tests/ui/lint/lint-ctypes.rs | 118 + tests/ui/lint/lint-ctypes.stderr | 262 + tests/ui/lint/lint-deref-nullptr.rs | 38 + tests/ui/lint/lint-deref-nullptr.stderr | 68 + .../lint-directives-on-use-items-issue-10534.rs | 24 + ...lint-directives-on-use-items-issue-10534.stderr | 26 + tests/ui/lint/lint-enum-intrinsics-non-enums.rs | 67 + .../ui/lint/lint-enum-intrinsics-non-enums.stderr | 95 + .../ui/lint/lint-exceeding-bitshifts.noopt.stderr | 152 + tests/ui/lint/lint-exceeding-bitshifts.opt.stderr | 152 + ...eding-bitshifts.opt_with_overflow_checks.stderr | 152 + tests/ui/lint/lint-exceeding-bitshifts.rs | 79 + .../lint/lint-expr-stmt-attrs-for-early-lints.rs | 14 + tests/ui/lint/lint-ffi-safety-all-phantom.rs | 22 + tests/ui/lint/lint-forbid-attr.rs | 7 + tests/ui/lint/lint-forbid-attr.stderr | 21 + tests/ui/lint/lint-forbid-cmdline.rs | 6 + tests/ui/lint/lint-forbid-cmdline.stderr | 19 + tests/ui/lint/lint-forbid-internal-unsafe.rs | 17 + tests/ui/lint/lint-forbid-internal-unsafe.stderr | 22 + tests/ui/lint/lint-group-nonstandard-style.rs | 26 + tests/ui/lint/lint-group-nonstandard-style.stderr | 57 + tests/ui/lint/lint-impl-fn.rs | 33 + tests/ui/lint/lint-impl-fn.stderr | 38 + .../ui/lint/lint-incoherent-auto-trait-objects.rs | 19 + .../lint/lint-incoherent-auto-trait-objects.stderr | 81 + tests/ui/lint/lint-invalid-atomic-ordering-bool.rs | 28 + .../lint/lint-invalid-atomic-ordering-bool.stderr | 35 + .../lint-invalid-atomic-ordering-exchange-weak.rs | 50 + ...nt-invalid-atomic-ordering-exchange-weak.stderr | 83 + .../lint/lint-invalid-atomic-ordering-exchange.rs | 48 + .../lint-invalid-atomic-ordering-exchange.stderr | 83 + .../lint-invalid-atomic-ordering-false-positive.rs | 18 + .../ui/lint/lint-invalid-atomic-ordering-fence.rs | 21 + .../lint/lint-invalid-atomic-ordering-fence.stderr | 19 + .../lint-invalid-atomic-ordering-fetch-update.rs | 49 + ...int-invalid-atomic-ordering-fetch-update.stderr | 83 + tests/ui/lint/lint-invalid-atomic-ordering-int.rs | 130 + .../lint/lint-invalid-atomic-ordering-int.stderr | 163 + tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs | 30 + .../lint/lint-invalid-atomic-ordering-ptr.stderr | 35 + tests/ui/lint/lint-invalid-atomic-ordering-uint.rs | 129 + .../lint/lint-invalid-atomic-ordering-uint.stderr | 163 + tests/ui/lint/lint-level-macro-def-mod.rs | 17 + tests/ui/lint/lint-level-macro-def.rs | 17 + .../lint-lowercase-static-const-pattern-rename.rs | 63 + .../ui/lint/lint-lowercase-static-const-pattern.rs | 51 + .../lint-lowercase-static-const-pattern.stderr | 26 + tests/ui/lint/lint-malformed.rs | 6 + tests/ui/lint/lint-malformed.stderr | 33 + tests/ui/lint/lint-match-arms.rs | 18 + tests/ui/lint/lint-match-arms.stderr | 14 + tests/ui/lint/lint-misplaced-attr.rs | 10 + tests/ui/lint/lint-misplaced-attr.stderr | 20 + .../lint-missing-copy-implementations-allow.rs | 35 + tests/ui/lint/lint-missing-copy-implementations.rs | 15 + .../lint/lint-missing-copy-implementations.stderr | 16 + tests/ui/lint/lint-missing-doc.rs | 203 + tests/ui/lint/lint-missing-doc.stderr | 140 + tests/ui/lint/lint-non-camel-case-types.rs | 37 + tests/ui/lint/lint-non-camel-case-types.stderr | 62 + tests/ui/lint/lint-non-camel-case-variant.rs | 10 + ...int-non-camel-case-with-trailing-underscores.rs | 11 + tests/ui/lint/lint-non-snake-case-crate-2.rs | 6 + tests/ui/lint/lint-non-snake-case-crate-2.stderr | 11 + tests/ui/lint/lint-non-snake-case-crate.rs | 5 + tests/ui/lint/lint-non-snake-case-crate.stderr | 14 + tests/ui/lint/lint-non-snake-case-functions.rs | 44 + tests/ui/lint/lint-non-snake-case-functions.stderr | 62 + ...n-snake-case-identifiers-suggestion-reserved.rs | 19 + ...ake-case-identifiers-suggestion-reserved.stderr | 67 + tests/ui/lint/lint-non-snake-case-lifetimes.rs | 8 + tests/ui/lint/lint-non-snake-case-lifetimes.stderr | 14 + tests/ui/lint/lint-non-snake-case-modules.rs | 10 + tests/ui/lint/lint-non-snake-case-modules.stderr | 14 + .../lint-non-snake-case-no-lowercase-equivalent.rs | 11 + .../ui/lint/lint-non-uppercase-associated-const.rs | 11 + .../lint-non-uppercase-associated-const.stderr | 14 + tests/ui/lint/lint-non-uppercase-statics.rs | 11 + tests/ui/lint/lint-non-uppercase-statics.stderr | 20 + tests/ui/lint/lint-nonstandard-style-unicode-1.rs | 49 + .../lint/lint-nonstandard-style-unicode-1.stderr | 50 + tests/ui/lint/lint-nonstandard-style-unicode-2.rs | 29 + .../lint/lint-nonstandard-style-unicode-2.stderr | 20 + tests/ui/lint/lint-nonstandard-style-unicode-3.rs | 24 + .../lint/lint-nonstandard-style-unicode-3.stderr | 14 + tests/ui/lint/lint-output-format-2.rs | 15 + tests/ui/lint/lint-output-format-2.stderr | 16 + tests/ui/lint/lint-output-format.rs | 13 + tests/ui/lint/lint-output-format.stderr | 35 + tests/ui/lint/lint-owned-heap-memory.rs | 12 + tests/ui/lint/lint-owned-heap-memory.stderr | 20 + tests/ui/lint/lint-pre-expansion-extern-module.rs | 7 + .../lint/lint-pre-expansion-extern-module.stderr | 12 + .../lint/lint-pub-unreachable-for-nested-glob.rs | 28 + tests/ui/lint/lint-qualification.rs | 20 + tests/ui/lint/lint-qualification.stderr | 14 + tests/ui/lint/lint-range-endpoint-overflow.rs | 17 + tests/ui/lint/lint-range-endpoint-overflow.stderr | 50 + tests/ui/lint/lint-removed-allow.rs | 8 + tests/ui/lint/lint-removed-allow.stderr | 14 + tests/ui/lint/lint-removed-cmdline.rs | 12 + tests/ui/lint/lint-removed-cmdline.stderr | 27 + tests/ui/lint/lint-removed.rs | 8 + tests/ui/lint/lint-removed.stderr | 22 + tests/ui/lint/lint-renamed-allow.rs | 8 + tests/ui/lint/lint-renamed-allow.stderr | 15 + tests/ui/lint/lint-renamed-cmdline.rs | 8 + tests/ui/lint/lint-renamed-cmdline.stderr | 27 + tests/ui/lint/lint-renamed.rs | 4 + tests/ui/lint/lint-renamed.stderr | 23 + tests/ui/lint/lint-shorthand-field.fixed | 70 + tests/ui/lint/lint-shorthand-field.rs | 70 + tests/ui/lint/lint-shorthand-field.stderr | 38 + tests/ui/lint/lint-stability-2.rs | 413 + tests/ui/lint/lint-stability-2.stderr | 259 + tests/ui/lint/lint-stability-deprecated.rs | 464 + tests/ui/lint/lint-stability-deprecated.stderr | 656 ++ tests/ui/lint/lint-stability-fields-deprecated.rs | 344 + .../lint/lint-stability-fields-deprecated.stderr | 380 + tests/ui/lint/lint-stability-fields.rs | 293 + tests/ui/lint/lint-stability-fields.stderr | 347 + tests/ui/lint/lint-stability.rs | 454 + tests/ui/lint/lint-stability.stderr | 347 + tests/ui/lint/lint-stability2.rs | 13 + tests/ui/lint/lint-stability2.stderr | 15 + tests/ui/lint/lint-stability3.rs | 14 + tests/ui/lint/lint-stability3.stderr | 14 + .../ui/lint/lint-strict-provenance-fuzzy-casts.rs | 7 + .../lint/lint-strict-provenance-fuzzy-casts.stderr | 19 + .../ui/lint/lint-strict-provenance-lossy-casts.rs | 18 + .../lint/lint-strict-provenance-lossy-casts.stderr | 51 + tests/ui/lint/lint-temporary-cstring-as-param.rs | 11 + .../ui/lint/lint-temporary-cstring-as-param.stderr | 18 + tests/ui/lint/lint-temporary-cstring-as-ptr.rs | 9 + tests/ui/lint/lint-temporary-cstring-as-ptr.stderr | 18 + tests/ui/lint/lint-type-limits.rs | 27 + tests/ui/lint/lint-type-limits.stderr | 58 + tests/ui/lint/lint-type-limits2.rs | 15 + tests/ui/lint/lint-type-limits2.stderr | 24 + tests/ui/lint/lint-type-limits3.rs | 13 + tests/ui/lint/lint-type-limits3.stderr | 24 + tests/ui/lint/lint-type-overflow.rs | 45 + tests/ui/lint/lint-type-overflow.stderr | 167 + tests/ui/lint/lint-type-overflow2.rs | 12 + tests/ui/lint/lint-type-overflow2.stderr | 48 + tests/ui/lint/lint-unconditional-recursion.rs | 194 + tests/ui/lint/lint-unconditional-recursion.stderr | 201 + tests/ui/lint/lint-unexported-no-mangle.rs | 29 + tests/ui/lint/lint-unexported-no-mangle.stderr | 44 + tests/ui/lint/lint-unknown-feature-default.rs | 9 + tests/ui/lint/lint-unknown-feature.rs | 9 + tests/ui/lint/lint-unknown-lint-cmdline.rs | 9 + tests/ui/lint/lint-unknown-lint-cmdline.stderr | 21 + tests/ui/lint/lint-unknown-lint.rs | 13 + tests/ui/lint/lint-unknown-lint.stderr | 26 + tests/ui/lint/lint-unnecessary-import-braces.rs | 11 + .../ui/lint/lint-unnecessary-import-braces.stderr | 14 + tests/ui/lint/lint-unnecessary-parens.fixed | 81 + tests/ui/lint/lint-unnecessary-parens.rs | 81 + tests/ui/lint/lint-unnecessary-parens.stderr | 211 + tests/ui/lint/lint-unsafe-code.rs | 130 + tests/ui/lint/lint-unsafe-code.stderr | 224 + tests/ui/lint/lint-uppercase-variables.rs | 41 + tests/ui/lint/lint-uppercase-variables.stderr | 90 + .../lint/lint_pre_expansion_extern_module_aux.rs | 3 + tests/ui/lint/lints-in-foreign-macros.rs | 21 + tests/ui/lint/lints-in-foreign-macros.stderr | 60 + tests/ui/lint/missing-doc-private-macro.rs | 43 + tests/ui/lint/missing-doc-private-macro.stderr | 20 + tests/ui/lint/must_not_suspend/boxed.rs | 25 + tests/ui/lint/must_not_suspend/boxed.stderr | 26 + tests/ui/lint/must_not_suspend/dedup.rs | 20 + tests/ui/lint/must_not_suspend/dedup.stderr | 19 + .../feature-gate-must_not_suspend.rs | 9 + .../feature-gate-must_not_suspend.stderr | 12 + tests/ui/lint/must_not_suspend/gated.rs | 17 + tests/ui/lint/must_not_suspend/gated.stderr | 33 + tests/ui/lint/must_not_suspend/generic.rs | 20 + tests/ui/lint/must_not_suspend/handled.rs | 28 + tests/ui/lint/must_not_suspend/issue-89562.rs | 19 + tests/ui/lint/must_not_suspend/mutex.rs | 13 + tests/ui/lint/must_not_suspend/mutex.stderr | 26 + tests/ui/lint/must_not_suspend/other_items.rs | 8 + tests/ui/lint/must_not_suspend/other_items.stderr | 10 + .../ui/lint/must_not_suspend/ref-drop-tracking.rs | 30 + .../lint/must_not_suspend/ref-drop-tracking.stderr | 27 + .../lint/must_not_suspend/ref.drop_tracking.stderr | 27 + .../must_not_suspend/ref.no_drop_tracking.stderr | 27 + tests/ui/lint/must_not_suspend/ref.rs | 29 + tests/ui/lint/must_not_suspend/return.rs | 9 + tests/ui/lint/must_not_suspend/return.stderr | 12 + tests/ui/lint/must_not_suspend/trait.rs | 28 + tests/ui/lint/must_not_suspend/trait.stderr | 37 + tests/ui/lint/must_not_suspend/tuple-mismatch.rs | 9 + .../ui/lint/must_not_suspend/tuple-mismatch.stderr | 12 + tests/ui/lint/must_not_suspend/unit.rs | 25 + tests/ui/lint/must_not_suspend/unit.stderr | 26 + tests/ui/lint/must_not_suspend/warn.rs | 26 + tests/ui/lint/must_not_suspend/warn.stderr | 26 + tests/ui/lint/no-coverage.rs | 55 + tests/ui/lint/no-coverage.stderr | 101 + tests/ui/lint/noop-method-call.rs | 55 + tests/ui/lint/noop-method-call.stderr | 47 + tests/ui/lint/not_found.rs | 21 + tests/ui/lint/not_found.stderr | 22 + tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs | 41 + .../lint/opaque-ty-ffi-normalization-cycle.stderr | 15 + tests/ui/lint/opaque-ty-ffi-unsafe.rs | 15 + tests/ui/lint/opaque-ty-ffi-unsafe.stderr | 15 + tests/ui/lint/outer-forbid.rs | 32 + tests/ui/lint/outer-forbid.stderr | 41 + tests/ui/lint/reasons-erroneous.rs | 54 + tests/ui/lint/reasons-erroneous.stderr | 131 + tests/ui/lint/reasons-forbidden.rs | 34 + tests/ui/lint/reasons-forbidden.stderr | 31 + tests/ui/lint/reasons.rs | 35 + tests/ui/lint/reasons.stderr | 36 + tests/ui/lint/recommend-literal.rs | 42 + tests/ui/lint/recommend-literal.stderr | 96 + .../auxiliary/redundant-semi-proc-macro-def.rs | 12 + .../ui/lint/redundant-semicolon/item-stmt-semi.rs | 6 + .../lint/redundant-semicolon/item-stmt-semi.stderr | 20 + .../redundant-semi-proc-macro.rs | 19 + .../redundant-semi-proc-macro.stderr | 21 + tests/ui/lint/register-tool-lint.rs | 9 + tests/ui/lint/register-tool-lint.stderr | 19 + tests/ui/lint/renamed-lints-still-apply.rs | 9 + tests/ui/lint/renamed-lints-still-apply.stderr | 29 + .../avoid_delayed_good_path_ice.rs | 8 + .../catch_multiple_lint_triggers.rs | 45 + .../rfc-2383-lint-reason/crate_level_expect.rs | 15 + .../rfc-2383-lint-reason/crate_level_expect.stderr | 10 + .../rfc-2383-lint-reason/expect_inside_macro.rs | 16 + .../rfc-2383-lint-reason/expect_lint_from_macro.rs | 42 + .../expect_lint_from_macro.stderr | 29 + .../expect_missing_feature_gate.rs | 9 + .../expect_missing_feature_gate.stderr | 12 + .../rfc-2383-lint-reason/expect_multiple_lints.rs | 58 + .../expect_multiple_lints.stderr | 52 + .../expect_nested_lint_levels.rs | 53 + .../expect_nested_lint_levels.stderr | 52 + .../rfc-2383-lint-reason/expect_on_fn_params.rs | 15 + .../expect_on_fn_params.stderr | 10 + .../expect_tool_lint_rfc_2383.rs | 155 + .../expect_tool_lint_rfc_2383.stderr | 16 + .../expect_unfulfilled_expectation.rs | 39 + .../expect_unfulfilled_expectation.stderr | 38 + .../rfc-2383-lint-reason/expect_with_forbid.rs | 34 + .../rfc-2383-lint-reason/expect_with_forbid.stderr | 51 + .../rfc-2383-lint-reason/expect_with_reason.rs | 11 + .../rfc-2383-lint-reason/expect_with_reason.stderr | 11 + .../force_warn_expected_lints_fulfilled.rs | 48 + .../force_warn_expected_lints_fulfilled.stderr | 40 + .../force_warn_expected_lints_unfulfilled.rs | 49 + .../force_warn_expected_lints_unfulfilled.stderr | 38 + .../fulfilled_expectation_early_lints.rs | 23 + .../fulfilled_expectation_late_lints.rs | 43 + .../lint-attribute-only-with-reason.rs | 14 + .../lint-attribute-only-with-reason.stderr | 47 + .../rfc-2383-lint-reason/multiple_expect_attrs.rs | 14 + .../multiple_expect_attrs.stderr | 10 + .../no_ice_for_partial_compiler_runs.rs | 16 + .../no_ice_for_partial_compiler_runs.stdout | 20 + .../lint-confusable-idents.rs | 16 + .../lint-confusable-idents.stderr | 26 + .../lint-mixed-script-confusables-2.rs | 19 + .../lint-mixed-script-confusables.rs | 14 + .../lint-mixed-script-confusables.stderr | 34 + .../lint-non-ascii-idents.rs | 12 + .../lint-non-ascii-idents.stderr | 26 + .../lint-uncommon-codepoints.rs | 13 + .../lint-uncommon-codepoints.stderr | 34 + tests/ui/lint/rustdoc-group.rs | 5 + tests/ui/lint/rustdoc-group.stderr | 10 + tests/ui/lint/rustdoc-renamed.rs | 15 + tests/ui/lint/rustdoc-renamed.stderr | 14 + .../auxiliary/foreign-crate.rs | 4 + .../foreign-crate.rs | 9 + .../semicolon-in-expressions-from-macros.rs | 51 + .../semicolon-in-expressions-from-macros.stderr | 185 + .../warn-semicolon-in-expressions-from-macros.rs | 16 + ...arn-semicolon-in-expressions-from-macros.stderr | 31 + tests/ui/lint/special-upper-lower-cases.rs | 23 + tests/ui/lint/special-upper-lower-cases.stderr | 32 + tests/ui/lint/suggestions.fixed | 66 + tests/ui/lint/suggestions.rs | 67 + tests/ui/lint/suggestions.stderr | 114 + .../test-allow-dead-extern-static-no-warning.rs | 11 + tests/ui/lint/test-inner-fn.rs | 19 + tests/ui/lint/test-inner-fn.stderr | 19 + tests/ui/lint/trivial-cast-ice.rs | 12 + .../trivial-casts-featuring-type-ascription.rs | 10 + .../trivial-casts-featuring-type-ascription.stderr | 28 + tests/ui/lint/trivial-casts.rs | 9 + tests/ui/lint/trivial-casts.stderr | 28 + tests/ui/lint/trivial_casts.rs | 85 + tests/ui/lint/trivial_casts.stderr | 164 + tests/ui/lint/type-overflow.rs | 22 + tests/ui/lint/type-overflow.stderr | 67 + tests/ui/lint/unaligned_references.rs | 103 + tests/ui/lint/unaligned_references.stderr | 259 + .../ui/lint/unaligned_references_external_macro.rs | 13 + .../unaligned_references_external_macro.stderr | 61 + tests/ui/lint/unnecessary-extern-crate.rs | 71 + tests/ui/lint/unnecessary-extern-crate.stderr | 44 + tests/ui/lint/unreachable-async-fn.rs | 9 + tests/ui/lint/unreachable_pub.rs | 66 + tests/ui/lint/unreachable_pub.stderr | 148 + .../unsafe_code/auxiliary/forge_unsafe_block.rs | 16 + tests/ui/lint/unsafe_code/forge_unsafe_block.rs | 16 + tests/ui/lint/unused-borrows.rs | 33 + tests/ui/lint/unused-borrows.stderr | 73 + .../unused-braces-while-let-with-mutable-value.rs | 12 + .../unused-qualification-in-derive-expansion.rs | 16 + .../unused/auxiliary/lint_unused_extern_crate.rs | 1 + .../unused/auxiliary/lint_unused_extern_crate2.rs | 1 + .../unused/auxiliary/lint_unused_extern_crate3.rs | 1 + .../unused/auxiliary/lint_unused_extern_crate4.rs | 1 + .../unused/auxiliary/lint_unused_extern_crate5.rs | 1 + tests/ui/lint/unused/issue-104397.rs | 18 + tests/ui/lint/unused/issue-105061-array-lint.rs | 11 + .../ui/lint/unused/issue-105061-array-lint.stderr | 56 + tests/ui/lint/unused/issue-105061-should-lint.rs | 23 + .../ui/lint/unused/issue-105061-should-lint.stderr | 32 + tests/ui/lint/unused/issue-105061.rs | 17 + tests/ui/lint/unused/issue-105061.stderr | 20 + tests/ui/lint/unused/issue-30730.rs | 5 + tests/ui/lint/unused/issue-30730.stderr | 15 + tests/ui/lint/unused/issue-46576.rs | 21 + tests/ui/lint/unused/issue-46576.stderr | 14 + ...ssue-47390-unused-variable-in-struct-pattern.rs | 88 + ...-47390-unused-variable-in-struct-pattern.stderr | 116 + .../lint/unused/issue-54180-unused-ref-field.fixed | 34 + .../ui/lint/unused/issue-54180-unused-ref-field.rs | 34 + .../unused/issue-54180-unused-ref-field.stderr | 33 + .../unused/issue-54538-unused-parens-lint.fixed | 113 + .../lint/unused/issue-54538-unused-parens-lint.rs | 113 + .../unused/issue-54538-unused-parens-lint.stderr | 295 + tests/ui/lint/unused/issue-59896.rs | 9 + tests/ui/lint/unused/issue-59896.stderr | 17 + .../issue-67691-unused-field-in-or-pattern.rs | 85 + .../issue-67691-unused-field-in-or-pattern.stderr | 74 + tests/ui/lint/unused/issue-70041.rs | 13 + tests/ui/lint/unused/issue-70041.stderr | 18 + .../lint/unused/issue-71290-unused-paren-binop.rs | 23 + .../unused/issue-74883-unused-paren-baren-yield.rs | 26 + .../issue-74883-unused-paren-baren-yield.stderr | 84 + .../unused/issue-81314-unused-span-ident.fixed | 12 + .../lint/unused/issue-81314-unused-span-ident.rs | 12 + .../unused/issue-81314-unused-span-ident.stderr | 21 + tests/ui/lint/unused/issue-85913.rs | 13 + tests/ui/lint/unused/issue-85913.stderr | 18 + tests/ui/lint/unused/issue-88519-unused-paren.rs | 85 + .../lint/unused/issue-90807-unused-paren-error.rs | 9 + .../unused/issue-90807-unused-paren-error.stderr | 31 + tests/ui/lint/unused/issue-90807-unused-paren.rs | 8 + tests/ui/lint/unused/issue-92751.rs | 9 + tests/ui/lint/unused/issue-92751.stderr | 32 + tests/ui/lint/unused/lint-unused-extern-crate.rs | 35 + .../ui/lint/unused/lint-unused-extern-crate.stderr | 20 + tests/ui/lint/unused/lint-unused-imports.rs | 90 + tests/ui/lint/unused/lint-unused-imports.stderr | 78 + tests/ui/lint/unused/lint-unused-mut-self.fixed | 14 + tests/ui/lint/unused/lint-unused-mut-self.rs | 14 + tests/ui/lint/unused/lint-unused-mut-self.stderr | 24 + tests/ui/lint/unused/lint-unused-mut-variables.rs | 207 + .../lint/unused/lint-unused-mut-variables.stderr | 222 + tests/ui/lint/unused/lint-unused-variables.rs | 79 + tests/ui/lint/unused/lint-unused-variables.stderr | 74 + tests/ui/lint/unused/must-use-box-from-raw.rs | 11 + tests/ui/lint/unused/must-use-box-from-raw.stderr | 15 + tests/ui/lint/unused/must-use-ops.rs | 51 + tests/ui/lint/unused/must-use-ops.stderr | 238 + tests/ui/lint/unused/must_use-array.rs | 54 + tests/ui/lint/unused/must_use-array.stderr | 50 + tests/ui/lint/unused/must_use-in-stdlib-traits.rs | 47 + .../lint/unused/must_use-in-stdlib-traits.stderr | 47 + tests/ui/lint/unused/must_use-trait.rs | 39 + tests/ui/lint/unused/must_use-trait.stderr | 38 + tests/ui/lint/unused/must_use-tuple.rs | 17 + tests/ui/lint/unused/must_use-tuple.stderr | 47 + tests/ui/lint/unused/must_use-unit.rs | 16 + tests/ui/lint/unused/must_use-unit.stderr | 20 + .../lint/unused/no-unused-parens-return-block.rs | 9 + tests/ui/lint/unused/unused-async.rs | 62 + tests/ui/lint/unused/unused-async.stderr | 55 + tests/ui/lint/unused/unused-attr-duplicate.rs | 105 + tests/ui/lint/unused/unused-attr-duplicate.stderr | 293 + tests/ui/lint/unused/unused-attr-macro-rules.rs | 33 + .../ui/lint/unused/unused-attr-macro-rules.stderr | 26 + tests/ui/lint/unused/unused-closure.rs | 35 + tests/ui/lint/unused/unused-closure.stderr | 65 + .../lint/unused/unused-doc-comments-edge-cases.rs | 46 + .../unused/unused-doc-comments-edge-cases.stderr | 95 + .../lint/unused/unused-doc-comments-for-macros.rs | 17 + .../unused/unused-doc-comments-for-macros.stderr | 31 + .../unused/unused-macro-rules-compile-error.rs | 27 + .../unused/unused-macro-rules-compile-error.stderr | 26 + tests/ui/lint/unused/unused-macro-rules-decl.rs | 49 + .../ui/lint/unused/unused-macro-rules-decl.stderr | 26 + .../unused/unused-macro-rules-malformed-rule.rs | 11 + .../unused-macro-rules-malformed-rule.stderr | 8 + tests/ui/lint/unused/unused-macro-rules.rs | 47 + tests/ui/lint/unused/unused-macro-rules.stderr | 26 + .../lint/unused/unused-macro-with-bad-frag-spec.rs | 9 + .../unused/unused-macro-with-bad-frag-spec.stderr | 10 + .../unused/unused-macro-with-follow-violation.rs | 7 + .../unused-macro-with-follow-violation.stderr | 10 + tests/ui/lint/unused/unused-macros-decl.rs | 28 + tests/ui/lint/unused/unused-macros-decl.stderr | 32 + .../ui/lint/unused/unused-macros-malformed-rule.rs | 15 + .../unused/unused-macros-malformed-rule.stderr | 26 + tests/ui/lint/unused/unused-macros.rs | 31 + tests/ui/lint/unused/unused-macros.stderr | 32 + .../unused/unused-mut-warning-captured-var.fixed | 9 + .../lint/unused/unused-mut-warning-captured-var.rs | 9 + .../unused/unused-mut-warning-captured-var.stderr | 16 + tests/ui/lint/unused/unused-result.rs | 42 + tests/ui/lint/unused/unused-result.stderr | 48 + tests/ui/lint/unused/unused-supertrait.rs | 11 + tests/ui/lint/unused/unused-supertrait.stderr | 15 + tests/ui/lint/unused/unused_attributes-must_use.rs | 131 + .../lint/unused/unused_attributes-must_use.stderr | 187 + tests/ui/lint/unused/useless-comment.rs | 45 + tests/ui/lint/unused/useless-comment.stderr | 110 + tests/ui/lint/unused_braces.fixed | 57 + tests/ui/lint/unused_braces.rs | 57 + tests/ui/lint/unused_braces.stderr | 84 + tests/ui/lint/unused_braces_borrow.fixed | 26 + tests/ui/lint/unused_braces_borrow.rs | 26 + tests/ui/lint/unused_braces_borrow.stderr | 19 + tests/ui/lint/unused_braces_macro.rs | 6 + tests/ui/lint/unused_import_warning_issue_45268.rs | 49 + .../lint/unused_import_warning_issue_45268.stderr | 14 + tests/ui/lint/unused_labels.rs | 85 + tests/ui/lint/unused_labels.stderr | 65 + tests/ui/lint/unused_parens_json_suggestion.fixed | 26 + tests/ui/lint/unused_parens_json_suggestion.rs | 26 + tests/ui/lint/unused_parens_json_suggestion.stderr | 21 + tests/ui/lint/unused_parens_multibyte_recovery.rs | 11 + .../lint/unused_parens_multibyte_recovery.stderr | 43 + .../unused_parens_remove_json_suggestion.fixed | 61 + .../lint/unused_parens_remove_json_suggestion.rs | 61 + .../unused_parens_remove_json_suggestion.stderr | 125 + tests/ui/lint/unused_variables-issue-82488.fixed | 16 + tests/ui/lint/unused_variables-issue-82488.rs | 16 + tests/ui/lint/unused_variables-issue-82488.stderr | 14 + tests/ui/lint/use-redundant.rs | 27 + tests/ui/lint/use-redundant.stderr | 29 + tests/ui/lint/use_suggestion_json.rs | 13 + tests/ui/lint/use_suggestion_json.stderr | 3 + tests/ui/lint/warn-ctypes-inhibit.rs | 15 + tests/ui/lint/warn-path-statement.rs | 17 + tests/ui/lint/warn-path-statement.stderr | 22 + .../ui/lint/warn-unused-inline-on-fn-prototypes.rs | 13 + .../warn-unused-inline-on-fn-prototypes.stderr | 20 + tests/ui/list.rs | 10 + tests/ui/liveness/liveness-asm.rs | 45 + tests/ui/liveness/liveness-asm.stderr | 23 + .../liveness-assign-imm-local-after-ret.rs | 16 + .../liveness-assign-imm-local-in-loop.rs | 12 + .../liveness-assign-imm-local-in-loop.stderr | 12 + .../liveness-assign-imm-local-in-op-eq.rs | 12 + .../liveness-assign-imm-local-in-op-eq.stderr | 14 + .../liveness-assign-imm-local-with-drop.rs | 12 + .../liveness-assign-imm-local-with-drop.stderr | 15 + .../liveness-assign-imm-local-with-init.rs | 12 + .../liveness-assign-imm-local-with-init.stderr | 15 + tests/ui/liveness/liveness-closure-require-ret.rs | 2 + .../liveness/liveness-closure-require-ret.stderr | 9 + tests/ui/liveness/liveness-consts.rs | 63 + tests/ui/liveness/liveness-consts.stderr | 63 + tests/ui/liveness/liveness-dead.rs | 39 + tests/ui/liveness/liveness-dead.stderr | 39 + tests/ui/liveness/liveness-derive.rs | 38 + tests/ui/liveness/liveness-derive.stderr | 21 + tests/ui/liveness/liveness-forgot-ret.rs | 6 + tests/ui/liveness/liveness-forgot-ret.stderr | 16 + tests/ui/liveness/liveness-issue-2163.rs | 8 + tests/ui/liveness/liveness-issue-2163.stderr | 12 + tests/ui/liveness/liveness-missing-ret2.rs | 7 + tests/ui/liveness/liveness-missing-ret2.stderr | 11 + tests/ui/liveness/liveness-move-call-arg.rs | 11 + tests/ui/liveness/liveness-move-call-arg.stderr | 26 + tests/ui/liveness/liveness-move-in-loop.rs | 17 + tests/ui/liveness/liveness-move-in-loop.stderr | 26 + tests/ui/liveness/liveness-move-in-while.rs | 13 + tests/ui/liveness/liveness-move-in-while.stderr | 46 + .../ui/liveness/liveness-return-last-stmt-semi.rs | 18 + .../liveness/liveness-return-last-stmt-semi.stderr | 42 + tests/ui/liveness/liveness-unused.rs | 141 + tests/ui/liveness/liveness-unused.stderr | 116 + tests/ui/liveness/liveness-upvars.rs | 144 + tests/ui/liveness/liveness-upvars.stderr | 185 + tests/ui/liveness/liveness-use-after-move.rs | 8 + tests/ui/liveness/liveness-use-after-move.stderr | 20 + tests/ui/liveness/liveness-use-after-send.rs | 19 + tests/ui/liveness/liveness-use-after-send.stderr | 24 + tests/ui/log-err-phi.rs | 7 + tests/ui/log-knows-the-names-of-variants.rs | 21 + tests/ui/log-poly.rs | 13 + tests/ui/logging-only-prints-once.rs | 30 + tests/ui/loops/for-each-loop-panic.rs | 9 + tests/ui/loops/issue-82916.rs | 10 + tests/ui/loops/issue-82916.stderr | 21 + tests/ui/loops/loop-break-unsize.rs | 8 + tests/ui/loops/loop-break-value-no-repeat.rs | 14 + tests/ui/loops/loop-break-value-no-repeat.stderr | 16 + tests/ui/loops/loop-break-value.rs | 98 + tests/ui/loops/loop-break-value.stderr | 193 + tests/ui/loops/loop-labeled-break-value.rs | 11 + tests/ui/loops/loop-labeled-break-value.stderr | 30 + tests/ui/loops/loop-no-implicit-break.rs | 31 + tests/ui/loops/loop-no-implicit-break.stderr | 47 + tests/ui/loops/loop-proper-liveness.rs | 32 + tests/ui/loops/loop-proper-liveness.stderr | 18 + tests/ui/loops/loop-properly-diverging-2.rs | 6 + tests/ui/loops/loop-properly-diverging-2.stderr | 12 + tests/ui/loud_ui.rs | 6 + tests/ui/lowering/issue-96847.rs | 14 + tests/ui/lto/all-crates.rs | 8 + tests/ui/lto/auxiliary/debuginfo-lto-aux.rs | 29 + tests/ui/lto/auxiliary/dylib.rs | 6 + tests/ui/lto/auxiliary/lto-duplicate-symbols1.rs | 6 + tests/ui/lto/auxiliary/lto-duplicate-symbols2.rs | 6 + .../lto/auxiliary/lto-rustc-loads-linker-plugin.rs | 6 + tests/ui/lto/auxiliary/msvc-imp-present.rs | 11 + tests/ui/lto/auxiliary/thin-lto-inlines-aux.rs | 7 + tests/ui/lto/auxiliary/thinlto-dylib.rs | 23 + tests/ui/lto/debuginfo-lto.rs | 25 + tests/ui/lto/dylib-works.rs | 9 + tests/ui/lto/fat-lto.rs | 7 + tests/ui/lto/issue-100772.rs | 11 + tests/ui/lto/issue-105637.rs | 28 + tests/ui/lto/issue-105637.run.stderr | 1 + tests/ui/lto/issue-11154.rs | 6 + tests/ui/lto/issue-11154.stderr | 6 + tests/ui/lto/lto-and-no-bitcode-in-rlib.rs | 3 + tests/ui/lto/lto-and-no-bitcode-in-rlib.stderr | 2 + tests/ui/lto/lto-duplicate-symbols.rs | 11 + tests/ui/lto/lto-duplicate-symbols.stderr | 6 + tests/ui/lto/lto-many-codegen-units.rs | 6 + tests/ui/lto/lto-opt-level-s.rs | 7 + tests/ui/lto/lto-opt-level-z.rs | 7 + tests/ui/lto/lto-rustc-loads-linker-plugin.rs | 17 + tests/ui/lto/lto-still-runs-thread-dtors.rs | 34 + tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs | 13 + tests/ui/lto/msvc-imp-present.rs | 22 + tests/ui/lto/thin-lto-global-allocator.rs | 7 + tests/ui/lto/thin-lto-inlines.rs | 30 + tests/ui/lto/thin-lto-inlines2.rs | 28 + tests/ui/lto/weak-works.rs | 28 + tests/ui/lub-glb/empty-binder-future-compat.rs | 22 + tests/ui/lub-glb/empty-binders-err.rs | 55 + tests/ui/lub-glb/empty-binders-err.stderr | 59 + tests/ui/lub-glb/empty-binders.rs | 45 + tests/ui/lub-glb/old-lub-glb-hr-eq.rs | 27 + .../lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr | 21 + .../old-lub-glb-hr-noteq1.basenoleak.stderr | 12 + tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr | 20 + .../ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr | 12 + tests/ui/lub-glb/old-lub-glb-hr-noteq1.rs | 29 + tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr | 19 + tests/ui/lub-glb/old-lub-glb-hr-noteq2.rs | 39 + tests/ui/lub-glb/old-lub-glb-object.rs | 23 + tests/ui/lub-glb/old-lub-glb-object.stderr | 21 + tests/ui/macro-quote-test.rs | 10 + tests/ui/macro_backtrace/auxiliary/ping.rs | 30 + .../macro_backtrace/main.-Zmacro-backtrace.stderr | 72 + tests/ui/macro_backtrace/main.default.stderr | 35 + tests/ui/macro_backtrace/main.rs | 23 + tests/ui/macros/ambiguity-legacy-vs-modern.rs | 46 + tests/ui/macros/ambiguity-legacy-vs-modern.stderr | 39 + tests/ui/macros/assert-as-macro.rs | 7 + tests/ui/macros/assert-eq-macro-msg.rs | 9 + tests/ui/macros/assert-eq-macro-panic.rs | 9 + tests/ui/macros/assert-eq-macro-success.rs | 13 + tests/ui/macros/assert-eq-macro-unsized.rs | 4 + tests/ui/macros/assert-format-lazy.rs | 12 + tests/ui/macros/assert-macro-explicit.rs | 7 + tests/ui/macros/assert-macro-fmt.rs | 7 + tests/ui/macros/assert-macro-owned.rs | 9 + tests/ui/macros/assert-macro-static.rs | 7 + tests/ui/macros/assert-matches-macro-msg.rs | 13 + tests/ui/macros/assert-ne-macro-msg.rs | 9 + tests/ui/macros/assert-ne-macro-panic.rs | 9 + tests/ui/macros/assert-ne-macro-success.rs | 13 + tests/ui/macros/assert-ne-macro-unsized.rs | 4 + tests/ui/macros/assert-trailing-junk.rs | 27 + .../assert-trailing-junk.with-generic-asset.stderr | 58 + ...sert-trailing-junk.without-generic-asset.stderr | 58 + tests/ui/macros/assert.rs | 9 + tests/ui/macros/assert.with-generic-asset.stderr | 28 + .../ui/macros/assert.without-generic-asset.stderr | 28 + tests/ui/macros/attr-empty-expr.rs | 11 + tests/ui/macros/attr-empty-expr.stderr | 20 + tests/ui/macros/attr-from-macro.rs | 20 + tests/ui/macros/auxiliary/attr-from-macro.rs | 15 + tests/ui/macros/auxiliary/define-macro.rs | 6 + tests/ui/macros/auxiliary/deprecated-macros.rs | 3 + .../auxiliary/dollar-crate-nested-encoding.rs | 10 + .../ui/macros/auxiliary/foreign-crate-macro-pat.rs | 11 + tests/ui/macros/auxiliary/issue-100199.rs | 18 + tests/ui/macros/auxiliary/issue-19163.rs | 6 + tests/ui/macros/auxiliary/issue-40469.rs | 1 + tests/ui/macros/auxiliary/issue-75982.rs | 12 + tests/ui/macros/auxiliary/macro-comma-support.rs | 1 + tests/ui/macros/auxiliary/macro-def-site-super.rs | 13 + tests/ui/macros/auxiliary/macro-in-other-crate.rs | 14 + .../macros/auxiliary/macro-include-items-expr.rs | 3 + .../macros/auxiliary/macro-include-items-item.rs | 3 + tests/ui/macros/auxiliary/macro_crate_def_only.rs | 4 + .../ui/macros/auxiliary/macro_crate_nonterminal.rs | 12 + .../macros/auxiliary/macro_export_inner_module.rs | 6 + tests/ui/macros/auxiliary/macro_with_super_1.rs | 16 + tests/ui/macros/auxiliary/or-pattern.rs | 6 + tests/ui/macros/auxiliary/proc_macro_def.rs | 35 + tests/ui/macros/auxiliary/proc_macro_sequence.rs | 27 + tests/ui/macros/auxiliary/two_macros-rpass.rs | 5 + tests/ui/macros/auxiliary/two_macros.rs | 5 + tests/ui/macros/auxiliary/unstable-macros.rs | 16 + tests/ui/macros/auxiliary/use-macro-self.rs | 6 + tests/ui/macros/bad-concat.rs | 8 + tests/ui/macros/bad-concat.stderr | 10 + tests/ui/macros/bad_hello.rs | 6 + tests/ui/macros/bad_hello.stderr | 24 + tests/ui/macros/bang-after-name.fixed | 8 + tests/ui/macros/bang-after-name.rs | 8 + tests/ui/macros/bang-after-name.stderr | 8 + tests/ui/macros/best-failure.rs | 11 + tests/ui/macros/best-failure.stderr | 21 + tests/ui/macros/builtin-prelude-no-accidents.rs | 8 + .../ui/macros/builtin-prelude-no-accidents.stderr | 21 + tests/ui/macros/builtin-std-paths-fail.rs | 25 + tests/ui/macros/builtin-std-paths-fail.stderr | 99 + tests/ui/macros/builtin-std-paths.rs | 32 + tests/ui/macros/cfg.rs | 6 + tests/ui/macros/cfg.stderr | 31 + tests/ui/macros/colorful-write-macros.rs | 34 + tests/ui/macros/concat-bytes-error.rs | 50 + tests/ui/macros/concat-bytes-error.stderr | 181 + tests/ui/macros/concat-bytes.rs | 17 + tests/ui/macros/concat-rpass.rs | 18 + tests/ui/macros/concat.rs | 6 + tests/ui/macros/concat.stderr | 30 + tests/ui/macros/conditional-debug-macro-on.rs | 8 + tests/ui/macros/cross-crate-pat-span.rs | 12 + tests/ui/macros/derive-in-eager-expansion-hang.rs | 14 + .../macros/derive-in-eager-expansion-hang.stderr | 22 + tests/ui/macros/die-macro-2.rs | 7 + tests/ui/macros/die-macro-expr.rs | 7 + tests/ui/macros/die-macro-pure.rs | 11 + tests/ui/macros/die-macro.rs | 16 + tests/ui/macros/doc-comment.rs | 25 + tests/ui/macros/dollar-crate-nested-encoding.rs | 8 + tests/ui/macros/duplicate-builtin.rs | 17 + tests/ui/macros/duplicate-builtin.stderr | 21 + tests/ui/macros/edition-macro-pats.rs | 12 + tests/ui/macros/empty-trailing-stmt.rs | 10 + tests/ui/macros/empty-trailing-stmt.stderr | 22 + tests/ui/macros/format-args-temporaries-async.rs | 37 + .../ui/macros/format-args-temporaries-in-write.rs | 50 + .../macros/format-args-temporaries-in-write.stderr | 33 + tests/ui/macros/format-args-temporaries.rs | 54 + tests/ui/macros/format-foreign.rs | 17 + tests/ui/macros/format-foreign.stderr | 82 + tests/ui/macros/format-parse-errors.rs | 17 + tests/ui/macros/format-parse-errors.stderr | 53 + tests/ui/macros/format-unused-lables.rs | 18 + tests/ui/macros/format-unused-lables.stderr | 50 + tests/ui/macros/global-asm.rs | 7 + tests/ui/macros/global-asm.stderr | 20 + tests/ui/macros/html-literals.rs | 95 + tests/ui/macros/include-single-expr-helper-1.rs | 5 + tests/ui/macros/include-single-expr-helper.rs | 5 + tests/ui/macros/include-single-expr.rs | 6 + tests/ui/macros/include-single-expr.stderr | 10 + tests/ui/macros/issue-100199.rs | 16 + tests/ui/macros/issue-100199.stderr | 15 + tests/ui/macros/issue-102878.rs | 10 + tests/ui/macros/issue-102878.stderr | 60 + tests/ui/macros/issue-103529.rs | 13 + tests/ui/macros/issue-103529.stderr | 39 + .../issue-104769-concat_bytes-invalid-literal.rs | 8 + ...ssue-104769-concat_bytes-invalid-literal.stderr | 18 + tests/ui/macros/issue-105011.rs | 3 + tests/ui/macros/issue-105011.stderr | 8 + tests/ui/macros/issue-10536.rs | 19 + tests/ui/macros/issue-10536.stderr | 14 + tests/ui/macros/issue-16098.rs | 16 + tests/ui/macros/issue-16098.stderr | 14 + tests/ui/macros/issue-19163.rs | 11 + tests/ui/macros/issue-19163.stderr | 11 + tests/ui/macros/issue-21356.rs | 6 + tests/ui/macros/issue-21356.stderr | 10 + tests/ui/macros/issue-22463.rs | 20 + tests/ui/macros/issue-25274.rs | 18 + tests/ui/macros/issue-25385.rs | 12 + tests/ui/macros/issue-25385.stderr | 20 + tests/ui/macros/issue-26322.rs | 30 + tests/ui/macros/issue-29084.rs | 13 + tests/ui/macros/issue-29084.stderr | 24 + tests/ui/macros/issue-30143.rs | 11 + tests/ui/macros/issue-30143.stderr | 35 + tests/ui/macros/issue-33185.rs | 17 + tests/ui/macros/issue-34171.rs | 10 + .../issue-34421-mac-expr-bad-stmt-good-add-semi.rs | 15 + ...ue-34421-mac-expr-bad-stmt-good-add-semi.stderr | 34 + tests/ui/macros/issue-35450.rs | 5 + tests/ui/macros/issue-35450.stderr | 8 + tests/ui/macros/issue-37175.rs | 5 + tests/ui/macros/issue-38715.rs | 17 + tests/ui/macros/issue-38715.stderr | 25 + tests/ui/macros/issue-39388.rs | 9 + tests/ui/macros/issue-39388.stderr | 8 + tests/ui/macros/issue-39404.rs | 7 + tests/ui/macros/issue-39404.stderr | 12 + tests/ui/macros/issue-40469.rs | 9 + tests/ui/macros/issue-40770.rs | 11 + tests/ui/macros/issue-41776.rs | 3 + tests/ui/macros/issue-41776.stderr | 8 + tests/ui/macros/issue-41803.rs | 23 + tests/ui/macros/issue-42954.fixed | 14 + tests/ui/macros/issue-42954.rs | 14 + tests/ui/macros/issue-42954.stderr | 19 + tests/ui/macros/issue-44127.rs | 17 + tests/ui/macros/issue-5060.rs | 16 + tests/ui/macros/issue-51848.rs | 20 + tests/ui/macros/issue-51848.stderr | 24 + tests/ui/macros/issue-52169.rs | 15 + tests/ui/macros/issue-54441.rs | 11 + tests/ui/macros/issue-54441.stderr | 13 + tests/ui/macros/issue-57597.rs | 80 + tests/ui/macros/issue-57597.stderr | 74 + tests/ui/macros/issue-58490.rs | 26 + tests/ui/macros/issue-58490.stderr | 14 + tests/ui/macros/issue-61033-1.rs | 10 + tests/ui/macros/issue-61033-1.stderr | 17 + tests/ui/macros/issue-61033-2.rs | 25 + tests/ui/macros/issue-61033-2.stderr | 24 + tests/ui/macros/issue-61053-different-kleene.rs | 30 + .../ui/macros/issue-61053-different-kleene.stderr | 45 + tests/ui/macros/issue-61053-duplicate-binder.rs | 14 + .../ui/macros/issue-61053-duplicate-binder.stderr | 16 + tests/ui/macros/issue-61053-missing-repetition.rs | 28 + .../macros/issue-61053-missing-repetition.stderr | 33 + tests/ui/macros/issue-61053-unbound.rs | 28 + tests/ui/macros/issue-61053-unbound.stderr | 26 + tests/ui/macros/issue-63102.rs | 8 + tests/ui/macros/issue-6596-1.rs | 10 + tests/ui/macros/issue-6596-1.stderr | 13 + tests/ui/macros/issue-68058.rs | 14 + tests/ui/macros/issue-68060.rs | 15 + tests/ui/macros/issue-68060.stderr | 27 + tests/ui/macros/issue-69838-dir/bar.rs | 3 + tests/ui/macros/issue-69838-dir/included.rs | 3 + .../issue-69838-mods-relative-to-included-path.rs | 7 + tests/ui/macros/issue-70446.rs | 13 + .../macros/issue-75982-foreign-macro-weird-mod.rs | 13 + tests/ui/macros/issue-77475.rs | 10 + .../macros/issue-78325-inconsistent-resolution.rs | 12 + .../issue-78325-inconsistent-resolution.stderr | 13 + tests/ui/macros/issue-78333.rs | 13 + .../issue-78892-substitution-in-statement-attr.rs | 14 + tests/ui/macros/issue-81006.rs | 10 + tests/ui/macros/issue-81006.stderr | 14 + tests/ui/macros/issue-83340.rs | 8 + tests/ui/macros/issue-83340.stderr | 8 + tests/ui/macros/issue-83344.rs | 6 + tests/ui/macros/issue-83344.stderr | 8 + tests/ui/macros/issue-84195-lint-anon-const.rs | 14 + tests/ui/macros/issue-84195-lint-anon-const.stderr | 39 + tests/ui/macros/issue-84429-matches-edition.rs | 9 + .../issue-84632-eager-expansion-recursion-limit.rs | 16 + ...ue-84632-eager-expansion-recursion-limit.stderr | 14 + .../macros/issue-86082-option-env-invalid-char.rs | 10 + tests/ui/macros/issue-86865.rs | 11 + tests/ui/macros/issue-86865.stderr | 18 + tests/ui/macros/issue-8709.rs | 14 + tests/ui/macros/issue-87877.rs | 25 + tests/ui/macros/issue-88206.rs | 66 + tests/ui/macros/issue-88206.stderr | 114 + tests/ui/macros/issue-88228.rs | 23 + tests/ui/macros/issue-88228.stderr | 28 + tests/ui/macros/issue-8851.rs | 30 + tests/ui/macros/issue-92267.rs | 3 + tests/ui/macros/issue-92267.stderr | 16 + tests/ui/macros/issue-95267.rs | 14 + tests/ui/macros/issue-95533.rs | 8 + tests/ui/macros/issue-98466-allow.rs | 16 + tests/ui/macros/issue-98466.fixed | 51 + tests/ui/macros/issue-98466.rs | 51 + tests/ui/macros/issue-98466.stderr | 81 + tests/ui/macros/issue-99261.rs | 17 + tests/ui/macros/issue-99265.fixed | 139 + tests/ui/macros/issue-99265.rs | 139 + tests/ui/macros/issue-99265.stderr | 562 + tests/ui/macros/issue-99907.fixed | 24 + tests/ui/macros/issue-99907.rs | 24 + tests/ui/macros/issue-99907.stderr | 68 + tests/ui/macros/lint-trailing-macro-call.rs | 16 + tests/ui/macros/lint-trailing-macro-call.stderr | 35 + .../local-ambiguity-multiple-parsing-options.rs | 8 + ...local-ambiguity-multiple-parsing-options.stderr | 14 + .../log_syntax-trace_macros-macro-locations.rs | 22 + .../log_syntax-trace_macros-macro-locations.stdout | 3 + tests/ui/macros/macro-2.rs | 12 + tests/ui/macros/macro-as-fn-body.rs | 33 + .../ui/macros/macro-at-most-once-rep-2015-rpass.rs | 50 + tests/ui/macros/macro-at-most-once-rep-2015.rs | 42 + tests/ui/macros/macro-at-most-once-rep-2015.stderr | 161 + .../ui/macros/macro-at-most-once-rep-2018-rpass.rs | 50 + tests/ui/macros/macro-at-most-once-rep-2018.rs | 42 + tests/ui/macros/macro-at-most-once-rep-2018.stderr | 161 + tests/ui/macros/macro-attribute-expansion.rs | 16 + tests/ui/macros/macro-attribute.rs | 2 + tests/ui/macros/macro-attribute.stderr | 8 + tests/ui/macros/macro-attributes.rs | 23 + .../ui/macros/macro-backtrace-invalid-internals.rs | 61 + .../macro-backtrace-invalid-internals.stderr | 100 + tests/ui/macros/macro-backtrace-nested.rs | 20 + tests/ui/macros/macro-backtrace-nested.stderr | 25 + tests/ui/macros/macro-backtrace-println.rs | 19 + tests/ui/macros/macro-backtrace-println.stderr | 13 + tests/ui/macros/macro-block-nonterminal.rs | 11 + tests/ui/macros/macro-comma-behavior-rpass.rs | 98 + tests/ui/macros/macro-comma-behavior.core.stderr | 50 + tests/ui/macros/macro-comma-behavior.rs | 89 + tests/ui/macros/macro-comma-behavior.std.stderr | 80 + tests/ui/macros/macro-comma-support-rpass.rs | 355 + tests/ui/macros/macro-comma-support.rs | 10 + tests/ui/macros/macro-comma-support.stderr | 14 + tests/ui/macros/macro-context.rs | 21 + tests/ui/macros/macro-context.stderr | 99 + tests/ui/macros/macro-crate-def-only.rs | 10 + .../ui/macros/macro-crate-nonterminal-non-root.rs | 9 + .../macros/macro-crate-nonterminal-non-root.stderr | 9 + tests/ui/macros/macro-crate-nonterminal-renamed.rs | 10 + tests/ui/macros/macro-crate-nonterminal.rs | 10 + tests/ui/macros/macro-crate-use.rs | 17 + tests/ui/macros/macro-deep_expansion.rs | 17 + tests/ui/macros/macro-def-site-super.rs | 10 + tests/ui/macros/macro-delimiter-significance.rs | 4 + tests/ui/macros/macro-deprecation.rs | 13 + tests/ui/macros/macro-deprecation.stderr | 16 + tests/ui/macros/macro-doc-comments.rs | 26 + tests/ui/macros/macro-doc-escapes.rs | 16 + tests/ui/macros/macro-doc-raw-str-hashes.rs | 30 + tests/ui/macros/macro-error.rs | 9 + tests/ui/macros/macro-error.stderr | 14 + tests/ui/macros/macro-expanded-include/file.txt | 0 tests/ui/macros/macro-expanded-include/foo/mod.rs | 9 + tests/ui/macros/macro-expanded-include/test.rs | 13 + tests/ui/macros/macro-expansion-tests.rs | 40 + tests/ui/macros/macro-expansion-tests.stderr | 18 + tests/ui/macros/macro-export-inner-module.rs | 9 + tests/ui/macros/macro-first-set.rs | 272 + tests/ui/macros/macro-follow-rpass.rs | 183 + tests/ui/macros/macro-follow.rs | 114 + tests/ui/macros/macro-follow.stderr | 682 ++ tests/ui/macros/macro-followed-by-seq-bad.rs | 11 + tests/ui/macros/macro-followed-by-seq-bad.stderr | 18 + tests/ui/macros/macro-followed-by-seq.rs | 14 + tests/ui/macros/macro-in-expression-context-2.rs | 8 + .../ui/macros/macro-in-expression-context-2.stderr | 17 + tests/ui/macros/macro-in-expression-context.fixed | 27 + tests/ui/macros/macro-in-expression-context.rs | 27 + tests/ui/macros/macro-in-expression-context.stderr | 50 + tests/ui/macros/macro-in-fn.rs | 8 + tests/ui/macros/macro-include-items.rs | 13 + tests/ui/macros/macro-inner-attributes.rs | 20 + tests/ui/macros/macro-inner-attributes.stderr | 14 + tests/ui/macros/macro-input-future-proofing.rs | 23 + tests/ui/macros/macro-input-future-proofing.stderr | 74 + tests/ui/macros/macro-interpolation.rs | 33 + tests/ui/macros/macro-invalid-fragment-spec.rs | 8 + tests/ui/macros/macro-invalid-fragment-spec.stderr | 10 + ...ro-invocation-in-count-expr-fixed-array-type.rs | 10 + tests/ui/macros/macro-lifetime-used-with-bound.rs | 15 + tests/ui/macros/macro-lifetime-used-with-labels.rs | 36 + tests/ui/macros/macro-lifetime-used-with-static.rs | 14 + tests/ui/macros/macro-lifetime.rs | 14 + tests/ui/macros/macro-literal.rs | 134 + tests/ui/macros/macro-local-data-key-priv.rs | 10 + tests/ui/macros/macro-local-data-key-priv.stderr | 16 + tests/ui/macros/macro-match-nonterminal.rs | 14 + tests/ui/macros/macro-match-nonterminal.stderr | 27 + tests/ui/macros/macro-meta-items-modern.rs | 11 + tests/ui/macros/macro-meta-items.rs | 31 + tests/ui/macros/macro-method-issue-4621.rs | 10 + tests/ui/macros/macro-missing-delimiters.rs | 7 + tests/ui/macros/macro-missing-delimiters.stderr | 8 + .../macros/macro-missing-fragment-deduplication.rs | 15 + .../macro-missing-fragment-deduplication.stderr | 18 + tests/ui/macros/macro-missing-fragment.rs | 26 + tests/ui/macros/macro-missing-fragment.stderr | 40 + tests/ui/macros/macro-multiple-items.rs | 16 + tests/ui/macros/macro-multiple-matcher-bindings.rs | 21 + .../macros/macro-multiple-matcher-bindings.stderr | 34 + tests/ui/macros/macro-name-typo.rs | 3 + tests/ui/macros/macro-name-typo.stderr | 11 + tests/ui/macros/macro-named-default.rs | 18 + .../macros/macro-nested_definition_issue-31946.rs | 9 + tests/ui/macros/macro-nested_expr.rs | 22 + tests/ui/macros/macro-nested_stmt_macros.rs | 23 + tests/ui/macros/macro-non-lifetime.rs | 8 + tests/ui/macros/macro-non-lifetime.stderr | 17 + tests/ui/macros/macro-nt-list.rs | 21 + tests/ui/macros/macro-of-higher-order.rs | 22 + .../ui/macros/macro-or-patterns-back-compat.fixed | 39 + tests/ui/macros/macro-or-patterns-back-compat.rs | 39 + .../ui/macros/macro-or-patterns-back-compat.stderr | 43 + tests/ui/macros/macro-outer-attributes.rs | 20 + tests/ui/macros/macro-outer-attributes.stderr | 19 + tests/ui/macros/macro-parameter-span.rs | 13 + tests/ui/macros/macro-parameter-span.stderr | 9 + tests/ui/macros/macro-pat-follow-2018.rs | 15 + tests/ui/macros/macro-pat-follow.rs | 21 + tests/ui/macros/macro-pat-neg-lit.rs | 25 + .../macro-pat-pattern-followed-by-or-in-2021.rs | 20 + ...macro-pat-pattern-followed-by-or-in-2021.stderr | 32 + .../ui/macros/macro-pat-pattern-followed-by-or.rs | 20 + tests/ui/macros/macro-pat.rs | 65 + .../macros/macro-pat2021-pattern-followed-by-or.rs | 22 + .../macro-pat2021-pattern-followed-by-or.stderr | 32 + tests/ui/macros/macro-path-prelude-fail-1.rs | 8 + tests/ui/macros/macro-path-prelude-fail-1.stderr | 15 + tests/ui/macros/macro-path-prelude-fail-2.rs | 7 + tests/ui/macros/macro-path-prelude-fail-2.stderr | 9 + tests/ui/macros/macro-path-prelude-fail-3.rs | 3 + tests/ui/macros/macro-path-prelude-fail-3.stderr | 13 + tests/ui/macros/macro-path-prelude-fail-4.rs | 4 + tests/ui/macros/macro-path-prelude-fail-4.stderr | 8 + tests/ui/macros/macro-path-prelude-pass.rs | 9 + tests/ui/macros/macro-path-prelude-shadowing.rs | 33 + .../ui/macros/macro-path-prelude-shadowing.stderr | 19 + tests/ui/macros/macro-path.rs | 18 + tests/ui/macros/macro-pub-matcher.rs | 117 + tests/ui/macros/macro-reexport-removed.rs | 8 + tests/ui/macros/macro-reexport-removed.stderr | 17 + tests/ui/macros/macro-seq-followed-by-seq.rs | 17 + tests/ui/macros/macro-shadowing-relaxed.rs | 25 + tests/ui/macros/macro-shadowing.rs | 26 + tests/ui/macros/macro-shadowing.stderr | 37 + tests/ui/macros/macro-stability-rpass.rs | 15 + tests/ui/macros/macro-stability.rs | 31 + tests/ui/macros/macro-stability.stderr | 41 + tests/ui/macros/macro-stmt-matchers.rs | 7 + tests/ui/macros/macro-stmt.rs | 31 + tests/ui/macros/macro-stmt_macro_in_expr_macro.rs | 21 + tests/ui/macros/macro-tt-followed-by-seq.rs | 28 + tests/ui/macros/macro-tt-matchers.rs | 11 + tests/ui/macros/macro-use-all-and-none.rs | 13 + tests/ui/macros/macro-use-all-and-none.stderr | 15 + tests/ui/macros/macro-use-all.rs | 10 + tests/ui/macros/macro-use-bad-args-1.rs | 6 + tests/ui/macros/macro-use-bad-args-1.stderr | 9 + tests/ui/macros/macro-use-bad-args-2.rs | 6 + tests/ui/macros/macro-use-bad-args-2.stderr | 9 + tests/ui/macros/macro-use-both.rs | 10 + tests/ui/macros/macro-use-one.rs | 9 + tests/ui/macros/macro-use-scope.rs | 22 + tests/ui/macros/macro-use-undef.rs | 8 + tests/ui/macros/macro-use-undef.stderr | 9 + tests/ui/macros/macro-use-wrong-name.rs | 9 + tests/ui/macros/macro-use-wrong-name.stderr | 16 + tests/ui/macros/macro-with-attrs1.rs | 13 + tests/ui/macros/macro-with-attrs2.rs | 11 + .../macros/macro-with-braces-in-expr-position.rs | 22 + tests/ui/macros/macro_path_as_generic_bound.rs | 9 + tests/ui/macros/macro_path_as_generic_bound.stderr | 9 + .../ui/macros/macro_rules-unmatchable-literals.rs | 14 + .../macros/macro_rules-unmatchable-literals.stderr | 14 + tests/ui/macros/macro_undefined.rs | 13 + tests/ui/macros/macro_undefined.stderr | 11 + tests/ui/macros/macro_with_super_2.rs | 13 + tests/ui/macros/macros-in-extern.rs | 51 + tests/ui/macros/macros-nonfatal-errors.rs | 139 + tests/ui/macros/macros-nonfatal-errors.stderr | 235 + tests/ui/macros/malformed_macro_lhs.rs | 7 + tests/ui/macros/malformed_macro_lhs.stderr | 8 + tests/ui/macros/meta-item-absolute-path.rs | 5 + tests/ui/macros/meta-item-absolute-path.stderr | 15 + .../macros/meta-variable-depth-outside-repeat.rs | 12 + .../meta-variable-depth-outside-repeat.stderr | 8 + tests/ui/macros/meta-variable-misuse.rs | 34 + tests/ui/macros/missing-bang-in-decl.fixed | 16 + tests/ui/macros/missing-bang-in-decl.rs | 16 + tests/ui/macros/missing-bang-in-decl.stderr | 20 + tests/ui/macros/missing-comma.rs | 34 + tests/ui/macros/missing-comma.stderr | 104 + tests/ui/macros/must-use-in-macro-55516.rs | 10 + tests/ui/macros/must-use-in-macro-55516.stderr | 12 + tests/ui/macros/no-std-macros.rs | 13 + tests/ui/macros/none-delim-lookahead.rs | 15 + tests/ui/macros/nonterminal-matching.rs | 26 + tests/ui/macros/nonterminal-matching.stderr | 24 + tests/ui/macros/not-utf8.bin | Bin 0 -> 3036 bytes tests/ui/macros/not-utf8.rs | 5 + tests/ui/macros/not-utf8.stderr | 10 + tests/ui/macros/out-of-order-shadowing.rs | 10 + tests/ui/macros/out-of-order-shadowing.stderr | 22 + tests/ui/macros/parse-complex-macro-invoc-op.rs | 42 + tests/ui/macros/paths-in-macro-invocations.rs | 36 + tests/ui/macros/proc_macro.rs | 37 + tests/ui/macros/pub-item-inside-macro.rs | 18 + tests/ui/macros/pub-method-inside-macro.rs | 22 + tests/ui/macros/recovery-allowed.rs | 8 + tests/ui/macros/recovery-allowed.stderr | 10 + tests/ui/macros/recovery-forbidden.rs | 13 + tests/ui/macros/restricted-shadowing-legacy.rs | 289 + tests/ui/macros/restricted-shadowing-legacy.stderr | 227 + tests/ui/macros/restricted-shadowing-modern.rs | 241 + tests/ui/macros/restricted-shadowing-modern.stderr | 171 + .../all-expr-kinds.rs | 186 + .../all-not-available-cases.rs | 44 + ...stom-errors-does-not-create-unnecessary-code.rs | 13 + ...ut-captures-does-not-create-unnecessary-code.rs | 15 + .../auxiliary/common.rs | 25 + .../feature-gate-generic_assert.rs | 26 + ...non-consuming-methods-have-optimized-codegen.rs | 32 + ...consuming-methods-have-optimized-codegen.stdout | 147 + .../count-and-length-are-distinct.rs | 271 + .../dollar-dollar-has-correct-behavior.rs | 28 + .../feature-gate-macro_metavar_expr.rs | 148 + .../rfc-3086-metavar-expr/macro-expansion.rs | 102 + .../out-of-bounds-arguments.rs | 43 + .../out-of-bounds-arguments.stderr | 20 + .../rfc-3086-metavar-expr/required-feature.rs | 44 + .../rfc-3086-metavar-expr/required-feature.stderr | 93 + .../macros/rfc-3086-metavar-expr/syntax-errors.rs | 165 + .../rfc-3086-metavar-expr/syntax-errors.stderr | 385 + tests/ui/macros/same-sequence-span.rs | 22 + tests/ui/macros/same-sequence-span.stderr | 43 + tests/ui/macros/semi-after-macro-ty.rs | 8 + tests/ui/macros/span-covering-argument-1.rs | 13 + tests/ui/macros/span-covering-argument-1.stderr | 18 + tests/ui/macros/stmt_expr_attr_macro_parse.rs | 25 + tests/ui/macros/stringify.rs | 889 ++ tests/ui/macros/syntax-error-recovery.rs | 18 + tests/ui/macros/syntax-error-recovery.stderr | 31 + tests/ui/macros/syntax-extension-cfg.rs | 24 + .../includeme.fragment | 7 + tests/ui/macros/syntax-extension-source-utils.rs | 37 + tests/ui/macros/trace-macro.rs | 6 + tests/ui/macros/trace-macro.stderr | 9 + tests/ui/macros/trace_faulty_macros.rs | 43 + tests/ui/macros/trace_faulty_macros.stderr | 85 + tests/ui/macros/trace_macros-format.rs | 18 + tests/ui/macros/trace_macros-format.stderr | 38 + tests/ui/macros/try-macro.rs | 49 + tests/ui/macros/two-macro-use.rs | 11 + tests/ui/macros/type-macros-hlist.rs | 80 + tests/ui/macros/type-macros-simple.rs | 30 + .../macros/typeck-macro-interaction-issue-8852.rs | 30 + tests/ui/macros/unimplemented-macro-panic.rs | 7 + tests/ui/macros/unknown-builtin.rs | 14 + tests/ui/macros/unknown-builtin.stderr | 18 + .../ui/macros/unreachable-arg.edition_2021.stderr | 13 + tests/ui/macros/unreachable-arg.rs | 16 + tests/ui/macros/unreachable-fmt-msg.rs | 7 + tests/ui/macros/unreachable-format-arg.rs | 15 + .../unreachable-format-args.edition_2015.stderr | 12 + tests/ui/macros/unreachable-format-args.rs | 14 + tests/ui/macros/unreachable-macro-panic.rs | 7 + tests/ui/macros/unreachable-static-msg.rs | 7 + tests/ui/macros/unreachable.rs | 7 + tests/ui/macros/use-macro-self.rs | 12 + tests/ui/macros/vec-macro-in-pattern.rs | 10 + tests/ui/macros/vec-macro-in-pattern.stderr | 10 + tests/ui/main-wrong-location.rs | 5 + tests/ui/main-wrong-location.stderr | 17 + tests/ui/main-wrong-type.rs | 8 + tests/ui/main-wrong-type.stderr | 12 + .../issue-69341-malformed-derive-inert.rs | 6 + .../issue-69341-malformed-derive-inert.stderr | 8 + tests/ui/malformed/malformed-derive-entry.rs | 14 + tests/ui/malformed/malformed-derive-entry.stderr | 49 + tests/ui/malformed/malformed-interpolated.rs | 16 + tests/ui/malformed/malformed-interpolated.stderr | 22 + tests/ui/malformed/malformed-meta-delim.rs | 11 + tests/ui/malformed/malformed-meta-delim.stderr | 24 + tests/ui/malformed/malformed-plugin-1.rs | 5 + tests/ui/malformed/malformed-plugin-1.stderr | 16 + tests/ui/malformed/malformed-plugin-2.rs | 5 + tests/ui/malformed/malformed-plugin-2.stderr | 16 + tests/ui/malformed/malformed-plugin-3.rs | 5 + tests/ui/malformed/malformed-plugin-3.stderr | 17 + tests/ui/malformed/malformed-regressions.rs | 12 + tests/ui/malformed/malformed-regressions.stderr | 48 + tests/ui/malformed/malformed-special-attrs.rs | 13 + tests/ui/malformed/malformed-special-attrs.stderr | 30 + tests/ui/manual/manual-link-bad-form.rs | 5 + tests/ui/manual/manual-link-bad-form.stderr | 2 + tests/ui/manual/manual-link-bad-kind.rs | 5 + tests/ui/manual/manual-link-bad-kind.stderr | 2 + tests/ui/manual/manual-link-bad-search-path.rs | 5 + tests/ui/manual/manual-link-bad-search-path.stderr | 2 + tests/ui/manual/manual-link-framework.rs | 7 + tests/ui/manual/manual-link-framework.stderr | 4 + tests/ui/manual/manual-link-unsupported-kind.rs | 5 + .../ui/manual/manual-link-unsupported-kind.stderr | 2 + .../marker_trait_attr/issue-61651-type-mismatch.rs | 17 + .../marker-attribute-on-non-trait.rs | 23 + .../marker-attribute-on-non-trait.stderr | 52 + .../marker-attribute-with-values.rs | 12 + .../marker-attribute-with-values.stderr | 20 + .../marker-trait-with-associated-items.rs | 40 + .../marker-trait-with-associated-items.stderr | 39 + .../overlap-doesnt-conflict-with-specialization.rs | 20 + ...rlap-doesnt-conflict-with-specialization.stderr | 12 + .../overlap-marker-trait-with-static-lifetime.rs | 10 + ...verlap-marker-trait-with-underscore-lifetime.rs | 9 + ...ap-marker-trait-with-underscore-lifetime.stderr | 31 + tests/ui/marker_trait_attr/overlap-marker-trait.rs | 29 + .../marker_trait_attr/overlap-marker-trait.stderr | 15 + ...verlap-permitted-for-annotated-marker-traits.rs | 27 + .../overlapping-impl-1-modulo-regions.rs | 9 + .../override-item-on-marker-trait.rs | 23 + .../override-item-on-marker-trait.stderr | 15 + tests/ui/marker_trait_attr/region-overlap.rs | 8 + tests/ui/marker_trait_attr/region-overlap.stderr | 31 + tests/ui/marker_trait_attr/unsound-overlap.rs | 25 + tests/ui/marker_trait_attr/unsound-overlap.stderr | 12 + .../ui/match/auxiliary/match_non_exhaustive_lib.rs | 5 + tests/ui/match/const_non_normal_zst_ref_pattern.rs | 9 + tests/ui/match/expr-match-panic-fn.rs | 19 + tests/ui/match/expr-match-panic.rs | 10 + tests/ui/match/expr_before_ident_pat.rs | 13 + tests/ui/match/expr_before_ident_pat.stderr | 15 + tests/ui/match/guards.rs | 20 + tests/ui/match/issue-11319.rs | 13 + tests/ui/match/issue-11319.stderr | 21 + tests/ui/match/issue-11940.rs | 11 + tests/ui/match/issue-12552.rs | 11 + tests/ui/match/issue-12552.stderr | 34 + tests/ui/match/issue-18060.rs | 8 + tests/ui/match/issue-26251.rs | 15 + tests/ui/match/issue-26996.rs | 24 + tests/ui/match/issue-27021.rs | 28 + tests/ui/match/issue-33498.rs | 11 + tests/ui/match/issue-41255.rs | 50 + tests/ui/match/issue-41255.stderr | 115 + tests/ui/match/issue-42679.rs | 21 + tests/ui/match/issue-46920-byte-array-patterns.rs | 28 + tests/ui/match/issue-5530.rs | 40 + tests/ui/match/issue-56685.rs | 44 + tests/ui/match/issue-56685.stderr | 63 + tests/ui/match/issue-70972-dyn-trait.rs | 10 + tests/ui/match/issue-70972-dyn-trait.stderr | 8 + tests/ui/match/issue-72680.rs | 63 + tests/ui/match/issue-72896.rs | 23 + tests/ui/match/issue-74050-end-span.rs | 13 + tests/ui/match/issue-74050-end-span.stderr | 15 + tests/ui/match/issue-82392.rs | 9 + tests/ui/match/issue-82392.stdout | 16 + tests/ui/match/issue-82866.rs | 7 + tests/ui/match/issue-82866.stderr | 16 + tests/ui/match/issue-84434.rs | 18 + tests/ui/match/issue-91058.rs | 11 + tests/ui/match/issue-91058.stderr | 11 + tests/ui/match/issue-92100.rs | 7 + tests/ui/match/issue-92100.stderr | 9 + tests/ui/match/match-arm-resolving-to-never.rs | 19 + tests/ui/match/match-arm-resolving-to-never.stderr | 18 + tests/ui/match/match-bot-panic.rs | 16 + tests/ui/match/match-disc-bot.rs | 16 + tests/ui/match/match-fn-call.rs | 12 + tests/ui/match/match-fn-call.stderr | 19 + tests/ui/match/match-ill-type2.rs | 7 + tests/ui/match/match-ill-type2.stderr | 12 + tests/ui/match/match-incompat-type-semi.rs | 52 + tests/ui/match/match-incompat-type-semi.stderr | 88 + tests/ui/match/match-join.rs | 11 + tests/ui/match/match-join.stderr | 9 + tests/ui/match/match-no-arms-unreachable-after.rs | 12 + .../match/match-no-arms-unreachable-after.stderr | 16 + tests/ui/match/match-on-negative-integer-ranges.rs | 7 + tests/ui/match/match-pattern-field-mismatch-2.rs | 16 + .../ui/match/match-pattern-field-mismatch-2.stderr | 12 + tests/ui/match/match-pattern-field-mismatch.rs | 16 + tests/ui/match/match-pattern-field-mismatch.stderr | 21 + tests/ui/match/match-range-fail-2.rs | 24 + tests/ui/match/match-range-fail-2.stderr | 40 + tests/ui/match/match-range-fail.rs | 22 + tests/ui/match/match-range-fail.stderr | 40 + tests/ui/match/match-ref-mut-invariance.rs | 15 + tests/ui/match/match-ref-mut-invariance.stderr | 17 + tests/ui/match/match-ref-mut-let-invariance.rs | 16 + tests/ui/match/match-ref-mut-let-invariance.stderr | 18 + tests/ui/match/match-ref-mut-stability.rs | 37 + tests/ui/match/match-struct.rs | 11 + tests/ui/match/match-struct.stderr | 11 + tests/ui/match/match-tag-nullary.rs | 4 + tests/ui/match/match-tag-nullary.stderr | 14 + tests/ui/match/match-tag-unary.rs | 4 + tests/ui/match/match-tag-unary.stderr | 11 + tests/ui/match/match-type-err-first-arm.rs | 50 + tests/ui/match/match-type-err-first-arm.stderr | 65 + tests/ui/match/match-unresolved-one-arm.rs | 7 + tests/ui/match/match-unresolved-one-arm.stderr | 14 + tests/ui/match/match-vec-mismatch-2.rs | 6 + tests/ui/match/match-vec-mismatch-2.stderr | 9 + tests/ui/match/match-wildcards.rs | 21 + tests/ui/match/match_non_exhaustive.rs | 32 + tests/ui/match/match_non_exhaustive.stderr | 56 + tests/ui/match/pattern-deref-miscompile.rs | 46 + tests/ui/match/single-line.rs | 3 + tests/ui/match/single-line.stderr | 12 + tests/ui/max-min-classes.rs | 32 + tests/ui/maximal_mir_to_hir_coverage.rs | 10 + tests/ui/maybe-bounds.rs | 9 + tests/ui/maybe-bounds.stderr | 22 + tests/ui/meta/auxiliary/env.rs | 9 + tests/ui/meta/expected-error-correct-rev.a.stderr | 16 + tests/ui/meta/expected-error-correct-rev.rs | 10 + .../ui/meta/meta-expected-error-wrong-rev.a.stderr | 16 + tests/ui/meta/meta-expected-error-wrong-rev.rs | 16 + tests/ui/meta/revision-bad.rs | 22 + tests/ui/meta/revision-ok.rs | 21 + tests/ui/meta/rustc-env.rs | 18 + tests/ui/methods/assign-to-method.rs | 24 + tests/ui/methods/assign-to-method.stderr | 19 + tests/ui/methods/auxiliary/ambig_impl_2_lib.rs | 4 + tests/ui/methods/auxiliary/macro-in-other-crate.rs | 9 + tests/ui/methods/auxiliary/method_self_arg1.rs | 35 + tests/ui/methods/auxiliary/method_self_arg2.rs | 52 + .../field-method-suggestion-using-return-ty.rs | 18 + .../field-method-suggestion-using-return-ty.stderr | 27 + tests/ui/methods/issues/issue-105732.rs | 14 + tests/ui/methods/issues/issue-105732.stderr | 18 + tests/ui/methods/issues/issue-61525.rs | 20 + tests/ui/methods/issues/issue-61525.stderr | 39 + tests/ui/methods/issues/issue-84495.rs | 4 + tests/ui/methods/issues/issue-84495.stderr | 13 + tests/ui/methods/issues/issue-90315.rs | 75 + tests/ui/methods/issues/issue-90315.stderr | 190 + tests/ui/methods/issues/issue-94581.rs | 7 + tests/ui/methods/issues/issue-94581.stderr | 15 + .../method-ambig-one-trait-unknown-int-type.rs | 36 + .../method-ambig-one-trait-unknown-int-type.stderr | 47 + .../methods/method-ambig-two-traits-cross-crate.rs | 11 + .../method-ambig-two-traits-cross-crate.stderr | 24 + .../methods/method-ambig-two-traits-from-bounds.rs | 8 + .../method-ambig-two-traits-from-bounds.stderr | 28 + .../methods/method-ambig-two-traits-from-impls.rs | 16 + .../method-ambig-two-traits-from-impls.stderr | 28 + .../methods/method-ambig-two-traits-from-impls2.rs | 16 + .../method-ambig-two-traits-from-impls2.stderr | 28 + .../method-ambig-two-traits-with-default-method.rs | 13 + ...hod-ambig-two-traits-with-default-method.stderr | 28 + .../method-argument-inference-associated-type.rs | 28 + tests/ui/methods/method-call-err-msg.rs | 22 + tests/ui/methods/method-call-err-msg.stderr | 89 + tests/ui/methods/method-call-lifetime-args-fail.rs | 72 + .../methods/method-call-lifetime-args-fail.stderr | 235 + .../methods/method-call-lifetime-args-lint-fail.rs | 87 + .../method-call-lifetime-args-lint-fail.stderr | 187 + tests/ui/methods/method-call-lifetime-args-lint.rs | 21 + .../methods/method-call-lifetime-args-lint.stderr | 31 + .../method-call-lifetime-args-subst-index.rs | 15 + .../method-call-lifetime-args-unresolved.rs | 6 + .../method-call-lifetime-args-unresolved.stderr | 24 + tests/ui/methods/method-call-lifetime-args.rs | 15 + tests/ui/methods/method-call-lifetime-args.stderr | 26 + tests/ui/methods/method-call-type-binding.rs | 3 + tests/ui/methods/method-call-type-binding.stderr | 9 + ...ef-to-same-trait-object-with-separate-params.rs | 179 + ...o-same-trait-object-with-separate-params.stderr | 87 + .../method-early-bound-lifetimes-on-self.rs | 31 + tests/ui/methods/method-lookup-order.rs | 190 + tests/ui/methods/method-macro-backtrace.rs | 25 + tests/ui/methods/method-macro-backtrace.stderr | 11 + tests/ui/methods/method-missing-call.rs | 30 + tests/ui/methods/method-missing-call.stderr | 25 + .../method-mut-self-modifies-mut-slice-lvalue.rs | 44 + .../methods/method-normalize-bounds-issue-20604.rs | 61 + .../method-not-found-generic-arg-elision.rs | 106 + .../method-not-found-generic-arg-elision.stderr | 104 + .../ui/methods/method-on-ambiguous-numeric-type.rs | 32 + .../method-on-ambiguous-numeric-type.stderr | 56 + tests/ui/methods/method-path-in-pattern.rs | 32 + tests/ui/methods/method-path-in-pattern.stderr | 39 + .../methods/method-probe-no-guessing-dyn-trait.rs | 60 + tests/ui/methods/method-projection.rs | 61 + tests/ui/methods/method-recursive-blanket-impl.rs | 41 + .../methods/method-resolvable-path-in-pattern.rs | 14 + .../method-resolvable-path-in-pattern.stderr | 9 + tests/ui/methods/method-self-arg-1.rs | 17 + tests/ui/methods/method-self-arg-1.stderr | 35 + tests/ui/methods/method-self-arg-2.rs | 25 + tests/ui/methods/method-self-arg-2.stderr | 24 + tests/ui/methods/method-self-arg-aux1.rs | 18 + tests/ui/methods/method-self-arg-aux2.rs | 22 + tests/ui/methods/method-self-arg-trait.rs | 67 + tests/ui/methods/method-self-arg.rs | 46 + tests/ui/methods/method-trait-object-with-hrtb.rs | 41 + .../methods/method-two-trait-defer-resolution-1.rs | 37 + .../methods/method-two-trait-defer-resolution-2.rs | 46 + ...od-two-traits-distinguished-via-where-clause.rs | 27 + tests/ui/methods/method-where-clause.rs | 34 + tests/ui/minus-string.rs | 3 + tests/ui/minus-string.stderr | 9 + tests/ui/mir-dataflow/README.md | 53 + tests/ui/mir-dataflow/def-inits-1.rs | 51 + tests/ui/mir-dataflow/def-inits-1.stderr | 28 + tests/ui/mir-dataflow/inits-1.rs | 53 + tests/ui/mir-dataflow/inits-1.stderr | 22 + tests/ui/mir-dataflow/liveness-enum.rs | 22 + tests/ui/mir-dataflow/liveness-enum.stderr | 10 + tests/ui/mir-dataflow/liveness-projection.rs | 32 + tests/ui/mir-dataflow/liveness-projection.stderr | 16 + tests/ui/mir-dataflow/liveness-ptr.rs | 28 + tests/ui/mir-dataflow/liveness-ptr.stderr | 10 + tests/ui/mir-dataflow/uninits-1.rs | 51 + tests/ui/mir-dataflow/uninits-1.stderr | 34 + tests/ui/mir-dataflow/uninits-2.rs | 24 + tests/ui/mir-dataflow/uninits-2.stderr | 10 + tests/ui/mir-unpretty.rs | 5 + tests/ui/mir-unpretty.stderr | 11 + tests/ui/mir/auxiliary/issue_76375_aux.rs | 20 + tests/ui/mir/auxiliary/mir_external_refs.rs | 17 + .../mir/drop-elaboration-after-borrowck-error.rs | 25 + .../drop-elaboration-after-borrowck-error.stderr | 65 + tests/ui/mir/important-higher-ranked-regions.rs | 26 + tests/ui/mir/issue-101844.rs | 73 + tests/ui/mir/issue-102389.rs | 8 + tests/ui/mir/issue-102389.stderr | 9 + tests/ui/mir/issue-105809.rs | 36 + tests/ui/mir/issue-106062.rs | 26 + tests/ui/mir/issue-106062.stderr | 16 + tests/ui/mir/issue-29227.rs | 142 + tests/ui/mir/issue-46845.rs | 32 + tests/ui/mir/issue-60390.rs | 8 + tests/ui/mir/issue-66851.rs | 20 + tests/ui/mir/issue-66930.rs | 11 + tests/ui/mir/issue-67639-normalization-ice.rs | 34 + tests/ui/mir/issue-67710-inline-projection.rs | 17 + tests/ui/mir/issue-67947.rs | 7 + tests/ui/mir/issue-67947.stderr | 16 + tests/ui/mir/issue-68841.rs | 15 + tests/ui/mir/issue-71793-inline-args-storage.rs | 16 + tests/ui/mir/issue-73914.rs | 30 + tests/ui/mir/issue-74739.rs | 14 + tests/ui/mir/issue-75053.rs | 49 + tests/ui/mir/issue-75053.stderr | 8 + tests/ui/mir/issue-75419-validation-impl-trait.rs | 13 + tests/ui/mir/issue-76248.rs | 29 + tests/ui/mir/issue-76375.rs | 27 + tests/ui/mir/issue-76740-copy-propagation.rs | 30 + tests/ui/mir/issue-76803-branches-not-same.rs | 19 + tests/ui/mir/issue-77002.rs | 16 + tests/ui/mir/issue-77359-simplify-arm-identity.rs | 35 + tests/ui/mir/issue-77911.rs | 15 + tests/ui/mir/issue-78496.rs | 16 + tests/ui/mir/issue-80949.rs | 34 + .../mir/issue-83499-input-output-iteration-ice.rs | 10 + .../issue-83499-input-output-iteration-ice.stderr | 21 + tests/ui/mir/issue-89485.rs | 18 + tests/ui/mir/issue-91745.rs | 21 + tests/ui/mir/issue-92893.rs | 8 + tests/ui/mir/issue-92893.stderr | 26 + tests/ui/mir/issue-99852.rs | 24 + tests/ui/mir/issue-99866.rs | 25 + tests/ui/mir/issue66339.rs | 13 + .../mir-inlining/array-clone-with-generic-size.rs | 11 + .../ice-issue-100550-unnormalized-projection.rs | 30 + tests/ui/mir/mir-inlining/ice-issue-45493.rs | 17 + tests/ui/mir/mir-inlining/ice-issue-45885.rs | 29 + tests/ui/mir/mir-inlining/ice-issue-68347.rs | 28 + tests/ui/mir/mir-inlining/ice-issue-77306-1.rs | 17 + tests/ui/mir/mir-inlining/ice-issue-77306-2.rs | 32 + tests/ui/mir/mir-inlining/ice-issue-77564.rs | 38 + .../mir-inlining/no-trait-method-issue-40473.rs | 16 + .../mir/mir-inlining/var-debuginfo-issue-67586.rs | 11 + tests/ui/mir/mir-typeck-normalize-fn-sig.rs | 30 + tests/ui/mir/mir_adt_construction.rs | 92 + tests/ui/mir/mir_ascription_coercion.rs | 10 + tests/ui/mir/mir_assign_eval_order.rs | 67 + tests/ui/mir/mir_augmented_assignments.rs | 160 + tests/ui/mir/mir_autoderef.rs | 28 + tests/ui/mir/mir_boxing.rs | 10 + tests/ui/mir/mir_build_match_comparisons.rs | 59 + tests/ui/mir/mir_call_with_associated_type.rs | 16 + tests/ui/mir/mir_calls_to_shims.rs | 49 + tests/ui/mir/mir_cast_fn_ret.rs | 23 + tests/ui/mir/mir_codegen_array.rs | 11 + tests/ui/mir/mir_codegen_array_2.rs | 9 + tests/ui/mir/mir_codegen_call_converging.rs | 17 + tests/ui/mir/mir_codegen_calls.rs | 192 + tests/ui/mir/mir_codegen_calls_converging_drops.rs | 26 + .../ui/mir/mir_codegen_calls_converging_drops_2.rs | 30 + tests/ui/mir/mir_codegen_calls_diverging.rs | 15 + tests/ui/mir/mir_codegen_calls_diverging_drops.rs | 24 + tests/ui/mir/mir_codegen_critical_edge.rs | 44 + tests/ui/mir/mir_codegen_spike1.rs | 12 + tests/ui/mir/mir_codegen_switch.rs | 35 + tests/ui/mir/mir_codegen_switchint.rs | 12 + tests/ui/mir/mir_coercion_casts.rs | 10 + tests/ui/mir/mir_coercions.rs | 71 + tests/ui/mir/mir_const_prop_identity.rs | 12 + tests/ui/mir/mir_const_prop_tuple_field_reorder.rs | 27 + tests/ui/mir/mir_constval_adts.rs | 34 + tests/ui/mir/mir_detects_invalid_ops.rs | 24 + tests/ui/mir/mir_detects_invalid_ops.stderr | 16 + tests/ui/mir/mir_drop_order.rs | 48 + tests/ui/mir/mir_drop_panics.rs | 24 + tests/ui/mir/mir_dynamic_drops_1.rs | 31 + tests/ui/mir/mir_dynamic_drops_2.rs | 29 + tests/ui/mir/mir_dynamic_drops_3.rs | 35 + tests/ui/mir/mir_early_return_scope.rs | 29 + tests/ui/mir/mir_fat_ptr.rs | 52 + tests/ui/mir/mir_fat_ptr_drop.rs | 32 + tests/ui/mir/mir_heavy_promoted.rs | 11 + tests/ui/mir/mir_indexing_oob_1.rs | 14 + tests/ui/mir/mir_indexing_oob_2.rs | 14 + tests/ui/mir/mir_indexing_oob_3.rs | 14 + tests/ui/mir/mir_let_chains_drop_order.rs | 93 + tests/ui/mir/mir_match_arm_guard.rs | 16 + tests/ui/mir/mir_match_test.rs | 83 + tests/ui/mir/mir_misc_casts.rs | 320 + tests/ui/mir/mir_overflow_off.rs | 17 + tests/ui/mir/mir_raw_fat_ptr.rs | 216 + tests/ui/mir/mir_refs_correct.rs | 209 + tests/ui/mir/mir_small_agg_arg.rs | 8 + tests/ui/mir/mir_static_subtype.rs | 9 + tests/ui/mir/mir_struct_with_assoc_ty.rs | 29 + tests/ui/mir/mir_temp_promotions.rs | 10 + tests/ui/mir/mir_void_return.rs | 12 + tests/ui/mir/mir_void_return_2.rs | 10 + tests/ui/mir/remove-zsts-query-cycle.rs | 16 + tests/ui/mir/simplify-branch-same.rs | 21 + tests/ui/mir/ssa-analysis-regression-50041.rs | 36 + tests/ui/mir/thir-constparam-temp.rs | 20 + tests/ui/mir/thir-constparam-temp.stderr | 22 + .../issue-95978-validator-lifetime-comparison.rs | 10 + tests/ui/mir/validate/needs-reveal-all.rs | 52 + tests/ui/mismatched_types/E0053.rs | 16 + tests/ui/mismatched_types/E0053.stderr | 37 + tests/ui/mismatched_types/E0409.rs | 9 + tests/ui/mismatched_types/E0409.stderr | 28 + tests/ui/mismatched_types/E0631.rs | 11 + tests/ui/mismatched_types/E0631.stderr | 73 + tests/ui/mismatched_types/abridged.rs | 62 + tests/ui/mismatched_types/abridged.stderr | 105 + .../assignment-operator-unimplemented.rs | 7 + .../assignment-operator-unimplemented.stderr | 19 + tests/ui/mismatched_types/binops.rs | 8 + tests/ui/mismatched_types/binops.stderr | 106 + tests/ui/mismatched_types/cast-rfc0401.rs | 72 + tests/ui/mismatched_types/cast-rfc0401.stderr | 256 + ...osure-arg-count-expected-type-issue-47244.fixed | 20 + .../closure-arg-count-expected-type-issue-47244.rs | 20 + ...sure-arg-count-expected-type-issue-47244.stderr | 16 + tests/ui/mismatched_types/closure-arg-count.rs | 43 + tests/ui/mismatched_types/closure-arg-count.stderr | 189 + .../closure-arg-type-mismatch-issue-45727.fixed | 5 + .../closure-arg-type-mismatch-issue-45727.rs | 5 + .../closure-arg-type-mismatch-issue-45727.stderr | 38 + .../mismatched_types/closure-arg-type-mismatch.rs | 11 + .../closure-arg-type-mismatch.stderr | 46 + tests/ui/mismatched_types/closure-mismatch.rs | 11 + tests/ui/mismatched_types/closure-mismatch.stderr | 31 + tests/ui/mismatched_types/const-fn-in-trait.rs | 11 + tests/ui/mismatched_types/const-fn-in-trait.stderr | 15 + ...st-boxed-trait-objects-instead-of-impl-trait.rs | 23 + ...oxed-trait-objects-instead-of-impl-trait.stderr | 26 + .../mismatched_types/dont-point-return-on-E0308.rs | 18 + .../dont-point-return-on-E0308.stderr | 19 + .../float-literal-inference-restrictions.rs | 4 + .../float-literal-inference-restrictions.stderr | 26 + tests/ui/mismatched_types/fn-variance-1.rs | 17 + tests/ui/mismatched_types/fn-variance-1.stderr | 41 + .../ui/mismatched_types/for-loop-has-unit-body.rs | 5 + .../mismatched_types/for-loop-has-unit-body.stderr | 9 + tests/ui/mismatched_types/issue-106182.fixed | 14 + tests/ui/mismatched_types/issue-106182.rs | 14 + tests/ui/mismatched_types/issue-106182.stderr | 18 + tests/ui/mismatched_types/issue-19109.rs | 8 + tests/ui/mismatched_types/issue-19109.stderr | 14 + tests/ui/mismatched_types/issue-26480.rs | 29 + tests/ui/mismatched_types/issue-26480.stderr | 37 + tests/ui/mismatched_types/issue-35030.rs | 15 + tests/ui/mismatched_types/issue-35030.stderr | 26 + tests/ui/mismatched_types/issue-36053-2.rs | 10 + tests/ui/mismatched_types/issue-36053-2.stderr | 41 + tests/ui/mismatched_types/issue-38371-unfixable.rs | 5 + .../mismatched_types/issue-38371-unfixable.stderr | 21 + tests/ui/mismatched_types/issue-38371.fixed | 18 + tests/ui/mismatched_types/issue-38371.rs | 18 + tests/ui/mismatched_types/issue-38371.stderr | 35 + tests/ui/mismatched_types/issue-47706-trait.rs | 8 + tests/ui/mismatched_types/issue-47706-trait.stderr | 16 + tests/ui/mismatched_types/issue-47706.rs | 29 + tests/ui/mismatched_types/issue-47706.stderr | 37 + .../issue-74918-missing-lifetime.rs | 29 + .../issue-74918-missing-lifetime.stderr | 28 + .../issue-75361-mismatched-impl.rs | 24 + .../issue-75361-mismatched-impl.stderr | 19 + tests/ui/mismatched_types/issue-84976.rs | 25 + tests/ui/mismatched_types/issue-84976.stderr | 38 + tests/ui/mismatched_types/main.rs | 4 + tests/ui/mismatched_types/main.stderr | 13 + .../method-help-unsatisfied-bound.rs | 7 + .../method-help-unsatisfied-bound.stderr | 18 + .../non_zero_assigned_something.rs | 9 + .../non_zero_assigned_something.stderr | 31 + tests/ui/mismatched_types/normalize-fn-sig.rs | 16 + tests/ui/mismatched_types/normalize-fn-sig.stderr | 19 + tests/ui/mismatched_types/numeric-literal-cast.rs | 12 + .../mismatched_types/numeric-literal-cast.stderr | 57 + tests/ui/mismatched_types/overloaded-calls-bad.rs | 42 + .../mismatched_types/overloaded-calls-bad.stderr | 66 + tests/ui/mismatched_types/recovered-block.rs | 21 + tests/ui/mismatched_types/recovered-block.stderr | 19 + .../ui/mismatched_types/ref-pat-suggestions.fixed | 37 + tests/ui/mismatched_types/ref-pat-suggestions.rs | 37 + .../ui/mismatched_types/ref-pat-suggestions.stderr | 386 + tests/ui/mismatched_types/show_module.rs | 18 + tests/ui/mismatched_types/show_module.stderr | 23 + tests/ui/mismatched_types/similar_paths.rs | 11 + tests/ui/mismatched_types/similar_paths.stderr | 20 + .../ui/mismatched_types/similar_paths_primitive.rs | 10 + .../similar_paths_primitive.stderr | 24 + ...dding-or-removing-ref-for-binding-pattern.fixed | 21 + ...t-adding-or-removing-ref-for-binding-pattern.rs | 21 + ...ding-or-removing-ref-for-binding-pattern.stderr | 49 + ...boxed-trait-objects-instead-of-impl-trait.fixed | 28 + ...st-boxed-trait-objects-instead-of-impl-trait.rs | 28 + ...oxed-trait-objects-instead-of-impl-trait.stderr | 47 + .../suggest-removing-tuple-struct-field.fixed | 17 + .../suggest-removing-tuple-struct-field.rs | 17 + .../suggest-removing-tuple-struct-field.stderr | 41 + .../mismatched_types/trait-bounds-cant-coerce.rs | 16 + .../trait-bounds-cant-coerce.stderr | 19 + .../trait-impl-fn-incompatibility.rs | 14 + .../trait-impl-fn-incompatibility.stderr | 37 + .../unboxed-closures-vtable-mismatch.rs | 22 + .../unboxed-closures-vtable-mismatch.stderr | 22 + .../ui/mismatched_types/wrap-suggestion-privacy.rs | 24 + .../wrap-suggestion-privacy.stderr | 59 + .../missing-trait-bounds/auxiliary/issue-69725.rs | 8 + tests/ui/missing-trait-bounds/issue-35677.fixed | 11 + tests/ui/missing-trait-bounds/issue-35677.rs | 11 + tests/ui/missing-trait-bounds/issue-35677.stderr | 19 + tests/ui/missing-trait-bounds/issue-69725.fixed | 13 + tests/ui/missing-trait-bounds/issue-69725.rs | 13 + tests/ui/missing-trait-bounds/issue-69725.stderr | 22 + .../missing-trait-bound-for-op.fixed | 7 + .../missing-trait-bound-for-op.rs | 7 + .../missing-trait-bound-for-op.stderr | 16 + .../missing-trait-bounds-for-method-call.rs | 31 + .../missing-trait-bounds-for-method-call.stderr | 48 + tests/ui/missing/auxiliary/two_macros.rs | 5 + tests/ui/missing/missing-allocator.rs | 18 + tests/ui/missing/missing-allocator.stderr | 4 + tests/ui/missing/missing-block-hint.rs | 9 + tests/ui/missing/missing-block-hint.stderr | 30 + tests/ui/missing/missing-comma-in-match.fixed | 11 + tests/ui/missing/missing-comma-in-match.rs | 11 + tests/ui/missing/missing-comma-in-match.stderr | 10 + tests/ui/missing/missing-derivable-attr.rs | 16 + tests/ui/missing/missing-derivable-attr.stderr | 12 + .../ui/missing/missing-fields-in-struct-pattern.rs | 8 + .../missing-fields-in-struct-pattern.stderr | 14 + tests/ui/missing/missing-items/auxiliary/m1.rs | 9 + tests/ui/missing/missing-items/m2.rs | 12 + tests/ui/missing/missing-items/m2.stderr | 17 + .../missing-items/missing-type-parameter.rs | 5 + .../missing-items/missing-type-parameter.stderr | 14 + .../missing-items/missing-type-parameter2.rs | 19 + .../missing-items/missing-type-parameter2.stderr | 121 + tests/ui/missing/missing-macro-use.rs | 8 + tests/ui/missing/missing-macro-use.stderr | 11 + tests/ui/missing/missing-main.rs | 2 + tests/ui/missing/missing-main.stderr | 9 + tests/ui/missing/missing-return.rs | 5 + tests/ui/missing/missing-return.stderr | 11 + tests/ui/missing/missing-stability.rs | 24 + tests/ui/missing/missing-stability.stderr | 17 + tests/ui/missing_debug_impls.rs | 38 + tests/ui/missing_debug_impls.stderr | 20 + tests/ui/missing_non_modrs_mod/foo.rs | 4 + tests/ui/missing_non_modrs_mod/foo_inline.rs | 5 + .../missing_non_modrs_mod/missing_non_modrs_mod.rs | 2 + .../missing_non_modrs_mod.stderr | 11 + .../missing_non_modrs_mod_inline.rs | 2 + .../missing_non_modrs_mod_inline.stderr | 11 + tests/ui/mod-subitem-as-enum-variant.rs | 9 + tests/ui/mod-subitem-as-enum-variant.stderr | 11 + tests/ui/module-macro_use-arguments.rs | 6 + tests/ui/module-macro_use-arguments.stderr | 8 + tests/ui/modules/auxiliary/dummy_lib.rs | 2 + tests/ui/modules/auxiliary/two_macros_2.rs | 3 + tests/ui/modules/issue-56411-aux.rs | 5 + tests/ui/modules/issue-56411.rs | 18 + tests/ui/modules/issue-56411.stderr | 33 + tests/ui/modules/mod-inside-fn.rs | 13 + tests/ui/modules/mod-view-items.rs | 14 + tests/ui/modules/mod_dir_implicit.rs | 8 + .../mod_dir_implicit_aux/compiletest-ignore-dir | 0 tests/ui/modules/mod_dir_implicit_aux/mod.rs | 2 + tests/ui/modules/mod_dir_path.rs | 23 + tests/ui/modules/mod_dir_path2.rs | 12 + tests/ui/modules/mod_dir_path3.rs | 11 + tests/ui/modules/mod_dir_path_multi.rs | 17 + tests/ui/modules/mod_dir_recursive.rs | 14 + tests/ui/modules/mod_dir_simple.rs | 10 + .../modules/mod_dir_simple/compiletest-ignore-dir | 0 .../ui/modules/mod_dir_simple/load_another_mod.rs | 3 + tests/ui/modules/mod_dir_simple/test.rs | 2 + tests/ui/modules/mod_file.rs | 10 + tests/ui/modules/mod_file_aux.rs | 4 + tests/ui/modules/mod_file_with_path_attr.rs | 11 + .../compiletest-ignore-dir | 0 .../float-template/inst_f32.rs | 3 + .../float-template/inst_f64.rs | 3 + .../float-template/inst_float.rs | 3 + tests/ui/modules/path-invalid-form.rs | 4 + tests/ui/modules/path-invalid-form.stderr | 8 + tests/ui/modules/path-macro.rs | 8 + tests/ui/modules/path-macro.stderr | 8 + tests/ui/modules/path-no-file-name.rs | 7 + tests/ui/modules/path-no-file-name.stderr | 8 + tests/ui/modules/special_module_name.rs | 8 + tests/ui/modules/special_module_name.stderr | 37 + tests/ui/modules/special_module_name_ignore.rs | 9 + .../modules_and_files_visibility/mod_file_aux.rs | 3 + .../mod_file_correct_spans.rs | 8 + .../mod_file_correct_spans.stderr | 9 + .../mod_file_disambig.rs | 6 + .../mod_file_disambig.stderr | 18 + .../mod_file_disambig_aux.rs | 1 + .../mod_file_disambig_aux/mod.rs | 1 + tests/ui/monomorphize-abi-alignment.rs | 35 + tests/ui/moves/borrow-closures-instead-of-move.rs | 36 + .../moves/borrow-closures-instead-of-move.stderr | 68 + tests/ui/moves/issue-46099-move-in-macro.rs | 15 + tests/ui/moves/issue-46099-move-in-macro.stderr | 16 + tests/ui/moves/issue-72649-uninit-in-loop.rs | 74 + tests/ui/moves/issue-72649-uninit-in-loop.stderr | 79 + tests/ui/moves/issue-75904-move-closure-loop.rs | 15 + .../ui/moves/issue-75904-move-closure-loop.stderr | 15 + tests/ui/moves/issue-99470-move-out-of-some.rs | 9 + tests/ui/moves/issue-99470-move-out-of-some.stderr | 21 + tests/ui/moves/move-1-unique.rs | 25 + tests/ui/moves/move-2-unique.rs | 10 + tests/ui/moves/move-2.rs | 6 + tests/ui/moves/move-3-unique.rs | 25 + tests/ui/moves/move-4-unique.rs | 18 + tests/ui/moves/move-4.rs | 18 + tests/ui/moves/move-arg-2-unique.rs | 12 + tests/ui/moves/move-arg-2.rs | 12 + tests/ui/moves/move-arg.rs | 5 + tests/ui/moves/move-deref-coercion.rs | 33 + tests/ui/moves/move-deref-coercion.stderr | 35 + tests/ui/moves/move-fn-self-receiver.rs | 79 + tests/ui/moves/move-fn-self-receiver.stderr | 177 + tests/ui/moves/move-guard-same-consts.rs | 25 + tests/ui/moves/move-guard-same-consts.stderr | 26 + tests/ui/moves/move-in-guard-1.rs | 15 + tests/ui/moves/move-in-guard-1.stderr | 26 + tests/ui/moves/move-in-guard-2.rs | 13 + tests/ui/moves/move-in-guard-2.stderr | 24 + tests/ui/moves/move-into-dead-array-1.rs | 15 + tests/ui/moves/move-into-dead-array-1.stderr | 16 + tests/ui/moves/move-into-dead-array-2.rs | 15 + tests/ui/moves/move-into-dead-array-2.stderr | 13 + tests/ui/moves/move-nullary-fn.rs | 13 + tests/ui/moves/move-of-addr-of-mut.rs | 12 + tests/ui/moves/move-of-addr-of-mut.stderr | 17 + tests/ui/moves/move-out-of-array-1.rs | 18 + tests/ui/moves/move-out-of-array-1.stderr | 12 + tests/ui/moves/move-out-of-array-ref.rs | 34 + tests/ui/moves/move-out-of-array-ref.stderr | 63 + tests/ui/moves/move-out-of-field.rs | 27 + tests/ui/moves/move-out-of-slice-1.rs | 11 + tests/ui/moves/move-out-of-slice-1.stderr | 19 + tests/ui/moves/move-out-of-slice-2.rs | 36 + tests/ui/moves/move-out-of-slice-2.stderr | 80 + tests/ui/moves/move-out-of-tuple-field.rs | 13 + tests/ui/moves/move-out-of-tuple-field.stderr | 23 + tests/ui/moves/move-scalar.rs | 10 + .../moves/moves-based-on-type-access-to-field.rs | 14 + .../moves-based-on-type-access-to-field.stderr | 20 + tests/ui/moves/moves-based-on-type-block-bad.rs | 29 + .../ui/moves/moves-based-on-type-block-bad.stderr | 20 + .../moves-based-on-type-capture-clause-bad.rs | 9 + .../moves-based-on-type-capture-clause-bad.stderr | 18 + .../ui/moves/moves-based-on-type-capture-clause.rs | 12 + .../moves-based-on-type-cyclic-types-issue-4821.rs | 20 + ...es-based-on-type-cyclic-types-issue-4821.stderr | 18 + ...ves-based-on-type-distribute-copy-over-paren.rs | 49 + ...based-on-type-distribute-copy-over-paren.stderr | 37 + tests/ui/moves/moves-based-on-type-exprs.rs | 93 + tests/ui/moves/moves-based-on-type-exprs.stderr | 189 + .../ui/moves/moves-based-on-type-match-bindings.rs | 21 + .../moves-based-on-type-match-bindings.stderr | 18 + ...d-on-type-move-out-of-closure-env-issue-1965.rs | 10 + ...-type-move-out-of-closure-env-issue-1965.stderr | 13 + ...ves-based-on-type-no-recursive-stack-closure.rs | 35 + ...based-on-type-no-recursive-stack-closure.stderr | 28 + tests/ui/moves/moves-based-on-type-tuple.rs | 10 + tests/ui/moves/moves-based-on-type-tuple.stderr | 19 + tests/ui/moves/moves-sru-moved-field.rs | 23 + tests/ui/moves/moves-sru-moved-field.stderr | 13 + tests/ui/moves/pin-mut-reborrow.fixed | 15 + tests/ui/moves/pin-mut-reborrow.rs | 15 + tests/ui/moves/pin-mut-reborrow.stderr | 23 + tests/ui/moves/suggest-clone.fixed | 11 + tests/ui/moves/suggest-clone.rs | 11 + tests/ui/moves/suggest-clone.stderr | 22 + .../moves/use_of_moved_value_clone_suggestions.rs | 6 + .../use_of_moved_value_clone_suggestions.stderr | 18 + .../use_of_moved_value_copy_suggestions.fixed | 86 + .../moves/use_of_moved_value_copy_suggestions.rs | 86 + .../use_of_moved_value_copy_suggestions.stderr | 179 + tests/ui/msvc-data-only.rs | 8 + tests/ui/multibyte.rs | 7 + tests/ui/multiline-comment.rs | 7 + tests/ui/mut-function-arguments.rs | 19 + tests/ui/mut/mut-cant-alias.rs | 14 + tests/ui/mut/mut-cant-alias.stderr | 13 + tests/ui/mut/mut-cross-borrowing.rs | 8 + tests/ui/mut/mut-cross-borrowing.stderr | 21 + tests/ui/mut/mut-pattern-internal-mutability.rs | 15 + .../ui/mut/mut-pattern-internal-mutability.stderr | 25 + tests/ui/mut/mut-pattern-mismatched.rs | 20 + tests/ui/mut/mut-pattern-mismatched.stderr | 27 + tests/ui/mut/mut-ref.rs | 4 + tests/ui/mut/mut-ref.stderr | 8 + tests/ui/mut/mut-suggestion.rs | 22 + tests/ui/mut/mut-suggestion.stderr | 25 + tests/ui/mut/mutable-class-fields-2.rs | 24 + tests/ui/mut/mutable-class-fields-2.stderr | 14 + tests/ui/mut/mutable-class-fields.rs | 16 + tests/ui/mut/mutable-class-fields.stderr | 14 + tests/ui/mut/mutable-enum-indirect.rs | 19 + tests/ui/mut/mutable-enum-indirect.stderr | 24 + tests/ui/mut/no-mut-lint-for-desugared-mut.rs | 8 + tests/ui/mutexguard-sync.rs | 13 + tests/ui/mutexguard-sync.stderr | 19 + tests/ui/mutual-recursion-group.rs | 16 + tests/ui/namespace/auxiliary/namespace-mix.rs | 66 + tests/ui/namespace/auxiliary/namespaced_enums.rs | 10 + tests/ui/namespace/namespace-mix.rs | 155 + tests/ui/namespace/namespace-mix.stderr | 728 ++ .../namespaced-enum-glob-import-no-impls-xcrate.rs | 15 + ...espaced-enum-glob-import-no-impls-xcrate.stderr | 27 + .../namespaced-enum-glob-import-no-impls.rs | 25 + .../namespaced-enum-glob-import-no-impls.stderr | 27 + tests/ui/native-library-link-flags/empty-kind-1.rs | 6 + .../native-library-link-flags/empty-kind-1.stderr | 2 + tests/ui/native-library-link-flags/empty-kind-2.rs | 6 + .../native-library-link-flags/empty-kind-2.stderr | 2 + .../ui/native-library-link-flags/link-arg-error.rs | 4 + .../link-arg-error.stderr | 2 + .../native-library-link-flags/link-arg-from-rs.rs | 8 + .../link-arg-from-rs.stderr | 16 + .../mix-bundle-and-whole-archive-link-attr.rs | 8 + .../mix-bundle-and-whole-archive-link-attr.stderr | 6 + .../mix-bundle-and-whole-archive.rs | 7 + .../mix-bundle-and-whole-archive.stderr | 6 + .../modifiers-override-2.rs | 3 + .../modifiers-override-2.stderr | 2 + .../modifiers-override-3.rs | 7 + .../modifiers-override-3.stderr | 4 + .../modifiers-override.rs | 16 + .../modifiers-override.stderr | 26 + .../suggest-libname-only-1.rs | 9 + .../suggest-libname-only-1.stderr | 6 + .../suggest-libname-only-2.rs | 9 + .../suggest-libname-only-2.stderr | 6 + tests/ui/nested-block-comment.rs | 12 + tests/ui/nested-cfg-attrs.rs | 4 + tests/ui/nested-cfg-attrs.stderr | 9 + tests/ui/nested-class.rs | 25 + tests/ui/nested-ty-params.rs | 8 + tests/ui/nested-ty-params.stderr | 23 + tests/ui/never_type/adjust_never.rs | 10 + tests/ui/never_type/auto-traits.rs | 18 + .../ui/never_type/call-fn-never-arg-wrong-type.rs | 11 + .../never_type/call-fn-never-arg-wrong-type.stderr | 19 + tests/ui/never_type/call-fn-never-arg.rs | 14 + tests/ui/never_type/cast-never.rs | 10 + .../defaulted-never-note.fallback.stderr | 20 + tests/ui/never_type/defaulted-never-note.rs | 41 + tests/ui/never_type/dispatch_from_dyn_zst.rs | 51 + .../never_type/diverging-fallback-control-flow.rs | 100 + .../diverging-fallback-no-leak.fallback.stderr | 22 + tests/ui/never_type/diverging-fallback-no-leak.rs | 19 + .../diverging-fallback-unconstrained-return.rs | 37 + tests/ui/never_type/diverging-tuple-parts-39485.rs | 15 + .../never_type/diverging-tuple-parts-39485.stderr | 32 + tests/ui/never_type/exhaustive_patterns.rs | 21 + tests/ui/never_type/exhaustive_patterns.stderr | 25 + tests/ui/never_type/expr-empty-ret.rs | 15 + tests/ui/never_type/fallback-closure-ret.rs | 23 + .../fallback-closure-wrap.fallback.stderr | 17 + tests/ui/never_type/fallback-closure-wrap.rs | 30 + .../never_type/feature-gate-never_type_fallback.rs | 13 + .../feature-gate-never_type_fallback.stderr | 19 + tests/ui/never_type/impl-for-never.rs | 27 + tests/ui/never_type/impl_trait_fallback.rs | 10 + tests/ui/never_type/impl_trait_fallback2.rs | 22 + tests/ui/never_type/impl_trait_fallback2.stderr | 19 + tests/ui/never_type/impl_trait_fallback3.rs | 15 + tests/ui/never_type/impl_trait_fallback3.stderr | 9 + tests/ui/never_type/impl_trait_fallback4.rs | 24 + tests/ui/never_type/impl_trait_fallback4.stderr | 9 + tests/ui/never_type/issue-10176.rs | 9 + tests/ui/never_type/issue-10176.stderr | 14 + tests/ui/never_type/issue-13352.rs | 9 + tests/ui/never_type/issue-13352.stderr | 16 + tests/ui/never_type/issue-2149.rs | 15 + tests/ui/never_type/issue-2149.stderr | 25 + tests/ui/never_type/issue-44402.rs | 33 + tests/ui/never_type/issue-51506.rs | 41 + tests/ui/never_type/issue-51506.stderr | 16 + tests/ui/never_type/issue-52443.rs | 14 + tests/ui/never_type/issue-52443.stderr | 73 + tests/ui/never_type/issue-5500-1.rs | 15 + tests/ui/never_type/issue-96335.rs | 5 + tests/ui/never_type/issue-96335.stderr | 32 + tests/ui/never_type/never-assign-dead-code.rs | 12 + tests/ui/never_type/never-assign-dead-code.stderr | 33 + tests/ui/never_type/never-assign-wrong-type.rs | 8 + tests/ui/never_type/never-assign-wrong-type.stderr | 14 + tests/ui/never_type/never-associated-type.rs | 23 + tests/ui/never_type/never-from-impl-is-reserved.rs | 12 + .../never_type/never-from-impl-is-reserved.stderr | 14 + tests/ui/never_type/never-result.rs | 21 + tests/ui/never_type/never-type-arg.rs | 17 + tests/ui/never_type/never-type-rvalues.rs | 38 + ...er-value-fallback-issue-66757.nofallback.stderr | 13 + .../never_type/never-value-fallback-issue-66757.rs | 31 + tests/ui/never_type/never_coercions.rs | 12 + tests/ui/never_type/never_transmute_never.rs | 23 + tests/ui/never_type/return-never-coerce.rs | 18 + tests/ui/never_type/try_from.rs | 37 + tests/ui/new-impl-syntax.rs | 29 + tests/ui/new-import-syntax.rs | 5 + tests/ui/new-style-constants.rs | 7 + tests/ui/new-unicode-escapes.rs | 14 + tests/ui/new-unsafe-pointers.rs | 7 + tests/ui/newlambdas.rs | 14 + tests/ui/newtype-polymorphic.rs | 27 + tests/ui/newtype.rs | 23 + tests/ui/nll/assign-while-to-immutable.rs | 11 + tests/ui/nll/borrow-use-issue-46875.rs | 18 + ...k-thread-local-static-mut-borrow-outlives-fn.rs | 25 + tests/ui/nll/borrowed-local-error.rs | 12 + tests/ui/nll/borrowed-local-error.stderr | 15 + tests/ui/nll/borrowed-match-issue-45045.rs | 18 + tests/ui/nll/borrowed-match-issue-45045.stderr | 15 + tests/ui/nll/borrowed-referent-issue-38899.rs | 17 + tests/ui/nll/borrowed-referent-issue-38899.stderr | 15 + tests/ui/nll/borrowed-temporary-error.rs | 12 + tests/ui/nll/borrowed-temporary-error.stderr | 16 + tests/ui/nll/borrowed-universal-error-2.rs | 7 + tests/ui/nll/borrowed-universal-error-2.stderr | 9 + tests/ui/nll/borrowed-universal-error.rs | 11 + tests/ui/nll/borrowed-universal-error.stderr | 12 + tests/ui/nll/cannot-move-block-spans.rs | 22 + tests/ui/nll/cannot-move-block-spans.stderr | 118 + tests/ui/nll/capture-mut-ref.fixed | 16 + tests/ui/nll/capture-mut-ref.rs | 16 + tests/ui/nll/capture-mut-ref.stderr | 16 + tests/ui/nll/capture-ref-in-struct.rs | 36 + tests/ui/nll/capture-ref-in-struct.stderr | 15 + tests/ui/nll/closure-access-spans.rs | 56 + tests/ui/nll/closure-access-spans.stderr | 120 + tests/ui/nll/closure-borrow-spans.rs | 100 + tests/ui/nll/closure-borrow-spans.stderr | 172 + tests/ui/nll/closure-captures.rs | 55 + tests/ui/nll/closure-captures.stderr | 148 + ...sure-malformed-projection-input-issue-102800.rs | 21 + ...-malformed-projection-input-issue-102800.stderr | 20 + tests/ui/nll/closure-move-spans.rs | 21 + tests/ui/nll/closure-move-spans.stderr | 39 + .../closure-requirements/escape-argument-callee.rs | 42 + .../escape-argument-callee.stderr | 31 + .../ui/nll/closure-requirements/escape-argument.rs | 42 + .../closure-requirements/escape-argument.stderr | 35 + .../closure-requirements/escape-upvar-nested.rs | 33 + .../escape-upvar-nested.stderr | 53 + .../nll/closure-requirements/escape-upvar-ref.rs | 33 + .../closure-requirements/escape-upvar-ref.stderr | 39 + .../issue-58127-mutliple-requirements.rs | 36 + .../propagate-approximated-fail-no-postdom.rs | 51 + .../propagate-approximated-fail-no-postdom.stderr | 36 + .../propagate-approximated-ref.rs | 50 + .../propagate-approximated-ref.stderr | 39 + ...ted-shorter-to-static-comparing-against-free.rs | 40 + ...shorter-to-static-comparing-against-free.stderr | 69 + ...gate-approximated-shorter-to-static-no-bound.rs | 40 + ...-approximated-shorter-to-static-no-bound.stderr | 49 + ...e-approximated-shorter-to-static-wrong-bound.rs | 43 + ...proximated-shorter-to-static-wrong-bound.stderr | 49 + .../propagate-approximated-val.rs | 43 + .../propagate-approximated-val.stderr | 39 + .../propagate-despite-same-free-region.rs | 50 + .../propagate-despite-same-free-region.stderr | 23 + ...opagate-fail-to-approximate-longer-no-bounds.rs | 42 + ...ate-fail-to-approximate-longer-no-bounds.stderr | 35 + ...gate-fail-to-approximate-longer-wrong-bounds.rs | 46 + ...-fail-to-approximate-longer-wrong-bounds.stderr | 35 + .../propagate-from-trait-match.rs | 48 + .../propagate-from-trait-match.stderr | 38 + .../propagate-multiple-requirements.rs | 23 + .../propagate-multiple-requirements.stderr | 17 + .../region-lbr-anon-does-not-outlive-static.rs | 13 + .../region-lbr-anon-does-not-outlive-static.stderr | 10 + .../region-lbr-named-does-not-outlive-static.rs | 13 + ...region-lbr-named-does-not-outlive-static.stderr | 10 + .../region-lbr1-does-not-outlive-ebr2.rs | 13 + .../region-lbr1-does-not-outlive-ebr2.stderr | 14 + ...lbr1-does-outlive-lbr2-because-implied-bound.rs | 11 + .../return-wrong-bound-region.rs | 23 + .../return-wrong-bound-region.stderr | 31 + tests/ui/nll/closure-use-spans.rs | 21 + tests/ui/nll/closure-use-spans.stderr | 33 + tests/ui/nll/closures-in-loops.rs | 24 + tests/ui/nll/closures-in-loops.stderr | 35 + tests/ui/nll/constant-thread-locals-issue-47053.rs | 10 + .../nll/constant-thread-locals-issue-47053.stderr | 9 + tests/ui/nll/constant.rs | 10 + tests/ui/nll/continue-after-missing-main.rs | 29 + tests/ui/nll/continue-after-missing-main.stderr | 9 + tests/ui/nll/decl-macro-illegal-copy.rs | 28 + tests/ui/nll/decl-macro-illegal-copy.stderr | 14 + .../do-not-ignore-lifetime-bounds-in-copy-proj.rs | 12 + ...-not-ignore-lifetime-bounds-in-copy-proj.stderr | 14 + .../nll/do-not-ignore-lifetime-bounds-in-copy.rs | 11 + .../do-not-ignore-lifetime-bounds-in-copy.stderr | 14 + tests/ui/nll/dont-print-desugared.rs | 21 + tests/ui/nll/dont-print-desugared.stderr | 24 + tests/ui/nll/drop-may-dangle.rs | 34 + tests/ui/nll/drop-no-may-dangle.rs | 30 + tests/ui/nll/drop-no-may-dangle.stderr | 26 + tests/ui/nll/empty-type-predicate-2.rs | 18 + tests/ui/nll/empty-type-predicate.rs | 11 + tests/ui/nll/enum-drop-access.rs | 49 + tests/ui/nll/enum-drop-access.stderr | 31 + tests/ui/nll/extra-unused-mut.rs | 66 + tests/ui/nll/generator-distinct-lifetime.rs | 25 + tests/ui/nll/generator-upvar-mutability.rs | 14 + tests/ui/nll/generator-upvar-mutability.stderr | 12 + tests/ui/nll/get_default.polonius.stderr | 18 + tests/ui/nll/get_default.rs | 44 + tests/ui/nll/get_default.stderr | 48 + tests/ui/nll/guarantor-issue-46974.rs | 19 + tests/ui/nll/guarantor-issue-46974.stderr | 23 + tests/ui/nll/issue-16223.rs | 52 + tests/ui/nll/issue-21114-ebfull.rs | 18 + tests/ui/nll/issue-21114-kixunil.rs | 17 + .../issue-21232-partial-init-and-erroneous-use.rs | 60 + ...sue-21232-partial-init-and-erroneous-use.stderr | 64 + tests/ui/nll/issue-21232-partial-init-and-use.rs | 297 + .../ui/nll/issue-21232-partial-init-and-use.stderr | 260 + tests/ui/nll/issue-22323-temp-destruction.rs | 30 + ...ue-24535-allow-mutable-borrow-in-match-guard.rs | 63 + .../nll/issue-27282-move-match-input-into-guard.rs | 34 + .../issue-27282-move-match-input-into-guard.stderr | 29 + .../ui/nll/issue-27282-move-ref-mut-into-guard.rs | 23 + .../nll/issue-27282-move-ref-mut-into-guard.stderr | 23 + .../issue-27282-mutate-before-diverging-arm-1.rs | 31 + ...ssue-27282-mutate-before-diverging-arm-1.stderr | 14 + .../issue-27282-mutate-before-diverging-arm-2.rs | 40 + ...ssue-27282-mutate-before-diverging-arm-2.stderr | 14 + .../issue-27282-mutate-before-diverging-arm-3.rs | 30 + ...ssue-27282-mutate-before-diverging-arm-3.stderr | 14 + tests/ui/nll/issue-27282-mutation-in-guard.rs | 26 + tests/ui/nll/issue-27282-mutation-in-guard.stderr | 23 + .../nll/issue-27282-reborrow-ref-mut-in-guard.rs | 30 + .../issue-27282-reborrow-ref-mut-in-guard.stderr | 23 + tests/ui/nll/issue-27868.rs | 28 + tests/ui/nll/issue-27868.stderr | 18 + tests/ui/nll/issue-30104.rs | 40 + tests/ui/nll/issue-31567.rs | 25 + tests/ui/nll/issue-31567.stderr | 16 + .../issue-32382-index-assoc-type-with-lifetime.rs | 41 + .../issue-42574-diagnostic-in-nested-closure.rs | 11 + ...issue-42574-diagnostic-in-nested-closure.stderr | 26 + tests/ui/nll/issue-43058.rs | 26 + tests/ui/nll/issue-45157.rs | 31 + tests/ui/nll/issue-45157.stderr | 17 + .../nll/issue-45696-long-live-borrows-in-boxes.rs | 114 + tests/ui/nll/issue-45696-no-variant-box-recur.rs | 47 + .../ui/nll/issue-45696-scribble-on-boxed-borrow.rs | 67 + .../issue-45696-scribble-on-boxed-borrow.stderr | 33 + tests/ui/nll/issue-46023.rs | 8 + tests/ui/nll/issue-46023.stderr | 12 + tests/ui/nll/issue-46036.rs | 12 + tests/ui/nll/issue-46036.stderr | 15 + tests/ui/nll/issue-46589.rs | 31 + tests/ui/nll/issue-46589.stderr | 15 + tests/ui/nll/issue-47022.rs | 33 + tests/ui/nll/issue-47153-generic-const.rs | 18 + tests/ui/nll/issue-47388.rs | 10 + tests/ui/nll/issue-47388.stderr | 14 + tests/ui/nll/issue-47470.rs | 22 + tests/ui/nll/issue-47470.stderr | 9 + tests/ui/nll/issue-47589.rs | 23 + tests/ui/nll/issue-48070.rs | 22 + tests/ui/nll/issue-48238.rs | 10 + tests/ui/nll/issue-48238.stderr | 13 + tests/ui/nll/issue-48623-closure.rs | 16 + tests/ui/nll/issue-48623-generator.rs | 18 + tests/ui/nll/issue-48623-generator.stderr | 11 + tests/ui/nll/issue-48697.rs | 10 + tests/ui/nll/issue-48697.stderr | 11 + tests/ui/nll/issue-48803.rs | 13 + tests/ui/nll/issue-48803.stderr | 15 + tests/ui/nll/issue-50343.rs | 8 + tests/ui/nll/issue-50461-used-mut-from-moves.rs | 17 + tests/ui/nll/issue-50716-1.rs | 10 + tests/ui/nll/issue-50716.rs | 17 + tests/ui/nll/issue-50716.stderr | 11 + tests/ui/nll/issue-51191.rs | 34 + tests/ui/nll/issue-51191.stderr | 72 + tests/ui/nll/issue-51244.rs | 5 + tests/ui/nll/issue-51244.stderr | 14 + tests/ui/nll/issue-51268.rs | 21 + tests/ui/nll/issue-51268.stderr | 17 + tests/ui/nll/issue-51345-2.rs | 8 + tests/ui/nll/issue-51351.rs | 21 + tests/ui/nll/issue-51512.rs | 6 + tests/ui/nll/issue-51512.stderr | 18 + tests/ui/nll/issue-51770.rs | 19 + tests/ui/nll/issue-52057.rs | 22 + ...e-52059-report-when-borrow-and-drop-conflict.rs | 30 + ...059-report-when-borrow-and-drop-conflict.stderr | 48 + tests/ui/nll/issue-52078.rs | 24 + tests/ui/nll/issue-52086.rs | 14 + tests/ui/nll/issue-52086.stderr | 15 + tests/ui/nll/issue-52113.rs | 35 + tests/ui/nll/issue-52113.stderr | 15 + tests/ui/nll/issue-52213.rs | 15 + tests/ui/nll/issue-52213.stderr | 15 + tests/ui/nll/issue-52533-1.rs | 11 + tests/ui/nll/issue-52533-1.stderr | 11 + tests/ui/nll/issue-52534-1.rs | 48 + tests/ui/nll/issue-52534-1.stderr | 57 + tests/ui/nll/issue-52534-2.rs | 14 + tests/ui/nll/issue-52534-2.stderr | 15 + tests/ui/nll/issue-52534.rs | 19 + tests/ui/nll/issue-52534.stderr | 31 + .../nll/issue-52663-span-decl-captured-variable.rs | 11 + .../issue-52663-span-decl-captured-variable.stderr | 13 + tests/ui/nll/issue-52663-trait-object.rs | 16 + tests/ui/nll/issue-52663-trait-object.stderr | 13 + tests/ui/nll/issue-52669.rs | 17 + tests/ui/nll/issue-52669.stderr | 14 + tests/ui/nll/issue-52742.rs | 17 + tests/ui/nll/issue-52742.stderr | 12 + tests/ui/nll/issue-52992.rs | 25 + tests/ui/nll/issue-53040.rs | 5 + tests/ui/nll/issue-53040.stderr | 17 + tests/ui/nll/issue-53119.rs | 23 + tests/ui/nll/issue-53123-raw-pointer-cast.rs | 26 + tests/ui/nll/issue-53570.rs | 32 + tests/ui/nll/issue-53773.rs | 47 + tests/ui/nll/issue-53773.stderr | 14 + tests/ui/nll/issue-53807.rs | 8 + tests/ui/nll/issue-53807.stderr | 15 + tests/ui/nll/issue-54189.rs | 6 + tests/ui/nll/issue-54189.stderr | 9 + .../nll/issue-54382-use-span-of-tail-of-block.rs | 29 + .../issue-54382-use-span-of-tail-of-block.stderr | 23 + tests/ui/nll/issue-54556-niconii.rs | 31 + tests/ui/nll/issue-54556-niconii.stderr | 23 + tests/ui/nll/issue-54556-stephaneyfx.rs | 35 + tests/ui/nll/issue-54556-stephaneyfx.stderr | 24 + .../ui/nll/issue-54556-temps-in-tail-diagnostic.rs | 23 + .../issue-54556-temps-in-tail-diagnostic.stderr | 22 + tests/ui/nll/issue-54556-used-vs-unused-tails.rs | 56 + .../ui/nll/issue-54556-used-vs-unused-tails.stderr | 146 + tests/ui/nll/issue-54556-wrap-it-up.rs | 28 + tests/ui/nll/issue-54556-wrap-it-up.stderr | 14 + tests/ui/nll/issue-54779-anon-static-lifetime.rs | 49 + .../ui/nll/issue-54779-anon-static-lifetime.stderr | 11 + tests/ui/nll/issue-54943-3.rs | 19 + tests/ui/nll/issue-54943.rs | 10 + tests/ui/nll/issue-54943.stderr | 11 + tests/ui/nll/issue-55288.rs | 9 + tests/ui/nll/issue-55344.rs | 14 + tests/ui/nll/issue-55394.rs | 13 + tests/ui/nll/issue-55394.stderr | 12 + tests/ui/nll/issue-55401.rs | 6 + tests/ui/nll/issue-55401.stderr | 11 + tests/ui/nll/issue-55511.rs | 19 + tests/ui/nll/issue-55511.stderr | 15 + tests/ui/nll/issue-55651.rs | 28 + tests/ui/nll/issue-55825-const-fn.rs | 8 + tests/ui/nll/issue-55850.rs | 35 + tests/ui/nll/issue-55850.stderr | 19 + tests/ui/nll/issue-57100.rs | 67 + tests/ui/nll/issue-57100.stderr | 31 + tests/ui/nll/issue-57265-return-type-wf-check.rs | 24 + .../ui/nll/issue-57265-return-type-wf-check.stderr | 12 + tests/ui/nll/issue-57280-1-flipped.rs | 23 + tests/ui/nll/issue-57280-1-flipped.stderr | 11 + tests/ui/nll/issue-57280-1.rs | 19 + tests/ui/nll/issue-57280.rs | 20 + tests/ui/nll/issue-57642-higher-ranked-subtype.rs | 38 + .../nll/issue-57642-higher-ranked-subtype.stderr | 31 + tests/ui/nll/issue-57843.rs | 26 + tests/ui/nll/issue-57843.stderr | 11 + tests/ui/nll/issue-57960.rs | 38 + tests/ui/nll/issue-57989.rs | 10 + tests/ui/nll/issue-57989.stderr | 26 + tests/ui/nll/issue-58053.rs | 11 + tests/ui/nll/issue-58053.stderr | 20 + tests/ui/nll/issue-58299.rs | 27 + tests/ui/nll/issue-58299.stderr | 20 + tests/ui/nll/issue-61311-normalize.rs | 34 + tests/ui/nll/issue-61320-normalize.rs | 160 + tests/ui/nll/issue-61424.fixed | 9 + tests/ui/nll/issue-61424.rs | 9 + tests/ui/nll/issue-61424.stderr | 16 + tests/ui/nll/issue-62007-assign-const-index.rs | 32 + tests/ui/nll/issue-62007-assign-const-index.stderr | 27 + .../ui/nll/issue-62007-assign-differing-fields.rs | 25 + .../nll/issue-62007-assign-differing-fields.stderr | 27 + tests/ui/nll/issue-63154-normalize.rs | 34 + tests/ui/nll/issue-67007-escaping-data.rs | 24 + tests/ui/nll/issue-67007-escaping-data.stderr | 14 + tests/ui/nll/issue-68550.rs | 15 + tests/ui/nll/issue-68550.stderr | 16 + tests/ui/nll/issue-69114-static-mut-ty.rs | 30 + tests/ui/nll/issue-69114-static-mut-ty.stderr | 27 + tests/ui/nll/issue-69114-static-ty.rs | 9 + tests/ui/nll/issue-69114-static-ty.stderr | 15 + tests/ui/nll/issue-73159-rpit-static.rs | 13 + tests/ui/nll/issue-73159-rpit-static.stderr | 12 + tests/ui/nll/issue-78561.rs | 23 + tests/ui/nll/issue-95272.rs | 15 + tests/ui/nll/issue-95272.stderr | 17 + tests/ui/nll/issue-97997.rs | 16 + tests/ui/nll/issue-97997.stderr | 20 + tests/ui/nll/issue-98170.rs | 25 + tests/ui/nll/issue-98170.stderr | 44 + .../issue-98589-closures-relate-named-regions.rs | 36 + ...ssue-98589-closures-relate-named-regions.stderr | 61 + tests/ui/nll/issue-98693.rs | 21 + tests/ui/nll/issue-98693.stderr | 14 + tests/ui/nll/lint-no-err.rs | 21 + tests/ui/nll/loan_ends_mid_block_pair.rs | 29 + tests/ui/nll/loan_ends_mid_block_pair.stderr | 15 + tests/ui/nll/loan_ends_mid_block_vec.rs | 30 + tests/ui/nll/loan_ends_mid_block_vec.stderr | 39 + tests/ui/nll/local-outlives-static-via-hrtb.rs | 26 + tests/ui/nll/local-outlives-static-via-hrtb.stderr | 38 + tests/ui/nll/lub-if.rs | 44 + tests/ui/nll/lub-if.stderr | 20 + tests/ui/nll/lub-match.rs | 47 + tests/ui/nll/lub-match.stderr | 20 + tests/ui/nll/match-cfg-fake-edges.rs | 70 + tests/ui/nll/match-cfg-fake-edges.stderr | 72 + tests/ui/nll/match-cfg-fake-edges2.rs | 18 + tests/ui/nll/match-cfg-fake-edges2.stderr | 15 + tests/ui/nll/match-guards-always-borrow.rs | 64 + tests/ui/nll/match-guards-always-borrow.stderr | 23 + tests/ui/nll/match-guards-partially-borrow.rs | 332 + tests/ui/nll/match-guards-partially-borrow.stderr | 170 + tests/ui/nll/match-on-borrowed.rs | 96 + tests/ui/nll/match-on-borrowed.stderr | 52 + ...aybe-initialized-drop-implicit-fragment-drop.rs | 19 + ...-initialized-drop-implicit-fragment-drop.stderr | 15 + .../ui/nll/maybe-initialized-drop-uninitialized.rs | 18 + .../ui/nll/maybe-initialized-drop-with-fragment.rs | 20 + .../maybe-initialized-drop-with-fragment.stderr | 14 + ...nitialized-drop-with-uninitialized-fragments.rs | 22 + ...alized-drop-with-uninitialized-fragments.stderr | 15 + tests/ui/nll/maybe-initialized-drop.rs | 15 + tests/ui/nll/maybe-initialized-drop.stderr | 13 + tests/ui/nll/mir_check_cast_closure.rs | 9 + tests/ui/nll/mir_check_cast_closure.stderr | 15 + tests/ui/nll/mir_check_cast_reify.rs | 39 + tests/ui/nll/mir_check_cast_reify.stderr | 11 + tests/ui/nll/mir_check_cast_unsafe_fn.rs | 11 + tests/ui/nll/mir_check_cast_unsafe_fn.stderr | 11 + tests/ui/nll/mir_check_cast_unsize.rs | 10 + tests/ui/nll/mir_check_cast_unsize.stderr | 15 + tests/ui/nll/move-errors.rs | 117 + tests/ui/nll/move-errors.stderr | 210 + tests/ui/nll/move-subpaths-moves-root.rs | 5 + tests/ui/nll/move-subpaths-moves-root.stderr | 13 + tests/ui/nll/mutating_references.rs | 24 + tests/ui/nll/normalization-bounds-error.rs | 15 + tests/ui/nll/normalization-bounds-error.stderr | 27 + tests/ui/nll/normalization-bounds.rs | 15 + tests/ui/nll/outlives-suggestion-more.rs | 26 + tests/ui/nll/outlives-suggestion-more.stderr | 96 + .../nll/outlives-suggestion-simple.polonius.stderr | 124 + tests/ui/nll/outlives-suggestion-simple.rs | 75 + tests/ui/nll/outlives-suggestion-simple.stderr | 104 + tests/ui/nll/polonius/assignment-kills-loans.rs | 87 + .../nll/polonius/assignment-to-differing-field.rs | 49 + .../polonius/assignment-to-differing-field.stderr | 51 + tests/ui/nll/polonius/call-kills-loans.rs | 23 + tests/ui/nll/polonius/issue-46589.rs | 31 + tests/ui/nll/polonius/polonius-smoke-test.rs | 46 + tests/ui/nll/polonius/polonius-smoke-test.stderr | 43 + tests/ui/nll/polonius/storagedead-kills-loans.rs | 28 + tests/ui/nll/polonius/subset-relations.rs | 29 + tests/ui/nll/polonius/subset-relations.stderr | 14 + tests/ui/nll/process_or_insert_default.rs | 27 + tests/ui/nll/projection-return.rs | 17 + .../nll/promotable-mutable-zst-doesnt-conflict.rs | 11 + tests/ui/nll/promoted-bounds.rs | 25 + tests/ui/nll/promoted-bounds.stderr | 15 + tests/ui/nll/promoted-closure-pair.rs | 10 + tests/ui/nll/promoted-closure-pair.stderr | 12 + tests/ui/nll/promoted-liveness.rs | 8 + tests/ui/nll/rc-loop.rs | 28 + tests/ui/nll/ref-suggestion.rs | 17 + tests/ui/nll/ref-suggestion.stderr | 48 + .../nll/reference-carried-through-struct-field.rs | 10 + .../reference-carried-through-struct-field.stderr | 13 + tests/ui/nll/region-ends-after-if-condition.rs | 32 + tests/ui/nll/region-ends-after-if-condition.stderr | 15 + tests/ui/nll/relate_tys/fn-subtype.rs | 8 + tests/ui/nll/relate_tys/fn-subtype.stderr | 12 + tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs | 24 + tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr | 21 + tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs | 23 + tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs | 15 + .../relate_tys/impl-fn-ignore-binder-via-bottom.rs | 34 + .../impl-fn-ignore-binder-via-bottom.stderr | 29 + tests/ui/nll/relate_tys/issue-48071.rs | 24 + tests/ui/nll/relate_tys/opaque-hrtb.rs | 14 + tests/ui/nll/relate_tys/opaque-hrtb.stderr | 11 + tests/ui/nll/relate_tys/trait-hrtb.rs | 14 + tests/ui/nll/relate_tys/trait-hrtb.stderr | 12 + tests/ui/nll/relate_tys/universe-violation.rs | 15 + tests/ui/nll/relate_tys/universe-violation.stderr | 12 + tests/ui/nll/relate_tys/var-appears-twice.rs | 25 + tests/ui/nll/relate_tys/var-appears-twice.stderr | 14 + tests/ui/nll/return-ref-mut-issue-46557.rs | 8 + tests/ui/nll/return-ref-mut-issue-46557.stderr | 11 + tests/ui/nll/return_from_loop.rs | 35 + tests/ui/nll/return_from_loop.stderr | 15 + tests/ui/nll/self-assign-ref-mut.rs | 20 + tests/ui/nll/snocat-regression.rs | 16 + tests/ui/nll/snocat-regression.stderr | 14 + tests/ui/nll/trait-associated-constant.rs | 31 + tests/ui/nll/trait-associated-constant.stderr | 22 + tests/ui/nll/ty-outlives/impl-trait-captures.rs | 15 + .../ui/nll/ty-outlives/impl-trait-captures.stderr | 16 + tests/ui/nll/ty-outlives/impl-trait-outlives.rs | 38 + .../ui/nll/ty-outlives/impl-trait-outlives.stderr | 25 + tests/ui/nll/ty-outlives/issue-53789-1.rs | 87 + tests/ui/nll/ty-outlives/issue-53789-2.rs | 249 + tests/ui/nll/ty-outlives/issue-55756.rs | 37 + tests/ui/nll/ty-outlives/projection-body.rs | 27 + .../nll/ty-outlives/projection-implied-bounds.rs | 40 + .../ty-outlives/projection-implied-bounds.stderr | 14 + .../ty-outlives/projection-no-regions-closure.rs | 55 + .../projection-no-regions-closure.stderr | 118 + .../ui/nll/ty-outlives/projection-no-regions-fn.rs | 40 + .../ty-outlives/projection-no-regions-fn.stderr | 21 + .../ty-outlives/projection-one-region-closure.rs | 83 + .../projection-one-region-closure.stderr | 155 + .../projection-one-region-trait-bound-closure.rs | 84 + ...rojection-one-region-trait-bound-closure.stderr | 152 + ...ection-one-region-trait-bound-static-closure.rs | 88 + ...on-one-region-trait-bound-static-closure.stderr | 114 + .../projection-two-region-trait-bound-closure.rs | 112 + ...rojection-two-region-trait-bound-closure.stderr | 236 + .../projection-where-clause-env-wrong-bound.rs | 34 + .../projection-where-clause-env-wrong-bound.stderr | 12 + .../projection-where-clause-env-wrong-lifetime.rs | 25 + ...ojection-where-clause-env-wrong-lifetime.stderr | 12 + .../nll/ty-outlives/projection-where-clause-env.rs | 28 + .../ty-outlives/projection-where-clause-none.rs | 24 + .../projection-where-clause-none.stderr | 14 + .../ty-outlives/projection-where-clause-trait.rs | 25 + .../ty-param-closure-approximate-lower-bound.rs | 39 + ...ty-param-closure-approximate-lower-bound.stderr | 59 + .../ty-param-closure-outlives-from-return-type.rs | 53 + ...-param-closure-outlives-from-return-type.stderr | 49 + .../ty-param-closure-outlives-from-where-clause.rs | 82 + ...param-closure-outlives-from-where-clause.stderr | 122 + tests/ui/nll/ty-outlives/ty-param-fn-body.rs | 27 + tests/ui/nll/ty-outlives/ty-param-fn-body.stderr | 14 + tests/ui/nll/ty-outlives/ty-param-fn.rs | 36 + tests/ui/nll/ty-outlives/ty-param-fn.stderr | 25 + .../ui/nll/ty-outlives/ty-param-implied-bounds.rs | 28 + tests/ui/nll/ty-outlives/wf-unreachable.rs | 52 + tests/ui/nll/ty-outlives/wf-unreachable.stderr | 73 + tests/ui/nll/type-alias-free-regions.rs | 31 + tests/ui/nll/type-alias-free-regions.stderr | 22 + tests/ui/nll/type-check-pointer-coercions.rs | 37 + tests/ui/nll/type-check-pointer-coercions.stderr | 111 + tests/ui/nll/type-check-pointer-comparisons.rs | 31 + tests/ui/nll/type-check-pointer-comparisons.stderr | 98 + tests/ui/nll/type-test-universe.rs | 21 + tests/ui/nll/type-test-universe.stderr | 22 + tests/ui/nll/unused-mut-issue-50343.fixed | 9 + tests/ui/nll/unused-mut-issue-50343.rs | 9 + tests/ui/nll/unused-mut-issue-50343.stderr | 16 + tests/ui/nll/user-annotations/adt-brace-enums.rs | 50 + .../ui/nll/user-annotations/adt-brace-enums.stderr | 42 + tests/ui/nll/user-annotations/adt-brace-structs.rs | 48 + .../nll/user-annotations/adt-brace-structs.stderr | 42 + tests/ui/nll/user-annotations/adt-nullary-enums.rs | 69 + .../nll/user-annotations/adt-nullary-enums.stderr | 45 + tests/ui/nll/user-annotations/adt-tuple-enums.rs | 53 + .../ui/nll/user-annotations/adt-tuple-enums.stderr | 42 + .../nll/user-annotations/adt-tuple-struct-calls.rs | 71 + .../user-annotations/adt-tuple-struct-calls.stderr | 56 + tests/ui/nll/user-annotations/adt-tuple-struct.rs | 48 + .../nll/user-annotations/adt-tuple-struct.stderr | 42 + tests/ui/nll/user-annotations/ascribed-type-wf.rs | 17 + .../nll/user-annotations/ascribed-type-wf.stderr | 10 + .../nll/user-annotations/cast_static_lifetime.rs | 6 + .../user-annotations/cast_static_lifetime.stderr | 14 + tests/ui/nll/user-annotations/closure-sig.rs | 15 + .../closure-substs.polonius.stderr | 61 + tests/ui/nll/user-annotations/closure-substs.rs | 31 + .../ui/nll/user-annotations/closure-substs.stderr | 42 + .../constant-in-expr-inherent-1.rs | 12 + .../constant-in-expr-inherent-1.stderr | 10 + .../constant-in-expr-inherent-2.rs | 27 + .../constant-in-expr-inherent-2.stderr | 50 + .../user-annotations/constant-in-expr-normalize.rs | 22 + .../constant-in-expr-normalize.stderr | 10 + .../constant-in-expr-trait-item-1.rs | 14 + .../constant-in-expr-trait-item-1.stderr | 10 + .../constant-in-expr-trait-item-2.rs | 14 + .../constant-in-expr-trait-item-2.stderr | 10 + .../constant-in-expr-trait-item-3.rs | 14 + .../constant-in-expr-trait-item-3.stderr | 10 + tests/ui/nll/user-annotations/downcast-infer.rs | 11 + .../nll/user-annotations/dump-adt-brace-struct.rs | 20 + .../user-annotations/dump-adt-brace-struct.stderr | 8 + tests/ui/nll/user-annotations/dump-fn-method.rs | 57 + .../ui/nll/user-annotations/dump-fn-method.stderr | 26 + tests/ui/nll/user-annotations/fns.rs | 48 + tests/ui/nll/user-annotations/fns.stderr | 42 + .../inherent-associated-constants.rs | 15 + .../inherent-associated-constants.stderr | 10 + tests/ui/nll/user-annotations/issue-54124.rs | 8 + tests/ui/nll/user-annotations/issue-54124.stderr | 20 + .../user-annotations/issue-54570-bootstrapping.rs | 30 + tests/ui/nll/user-annotations/issue-55219.rs | 18 + tests/ui/nll/user-annotations/issue-55241.rs | 26 + .../issue-55748-pat-types-constrain-bindings.rs | 68 + ...issue-55748-pat-types-constrain-bindings.stderr | 29 + .../issue-57731-ascibed-coupled-types.rs | 40 + .../issue-57731-ascibed-coupled-types.stderr | 38 + tests/ui/nll/user-annotations/method-call.rs | 69 + tests/ui/nll/user-annotations/method-call.stderr | 42 + tests/ui/nll/user-annotations/method-ufcs-1.rs | 63 + tests/ui/nll/user-annotations/method-ufcs-1.stderr | 46 + tests/ui/nll/user-annotations/method-ufcs-2.rs | 63 + tests/ui/nll/user-annotations/method-ufcs-2.stderr | 46 + tests/ui/nll/user-annotations/method-ufcs-3.rs | 69 + tests/ui/nll/user-annotations/method-ufcs-3.stderr | 42 + .../nll/user-annotations/method-ufcs-inherent-1.rs | 18 + .../user-annotations/method-ufcs-inherent-1.stderr | 18 + .../nll/user-annotations/method-ufcs-inherent-2.rs | 19 + .../user-annotations/method-ufcs-inherent-2.stderr | 33 + .../nll/user-annotations/method-ufcs-inherent-3.rs | 18 + .../user-annotations/method-ufcs-inherent-3.stderr | 18 + .../nll/user-annotations/method-ufcs-inherent-4.rs | 20 + .../user-annotations/method-ufcs-inherent-4.stderr | 33 + tests/ui/nll/user-annotations/normalization-2.rs | 152 + .../ui/nll/user-annotations/normalization-2.stderr | 296 + .../nll/user-annotations/normalization-default.rs | 22 + .../user-annotations/normalization-default.stderr | 36 + .../ui/nll/user-annotations/normalization-infer.rs | 40 + .../user-annotations/normalization-infer.stderr | 101 + .../ui/nll/user-annotations/normalization-self.rs | 26 + .../nll/user-annotations/normalization-self.stderr | 36 + tests/ui/nll/user-annotations/normalization.rs | 17 + tests/ui/nll/user-annotations/normalization.stderr | 25 + tests/ui/nll/user-annotations/normalize-self-ty.rs | 23 + .../pattern_substs_on_brace_enum_variant.rs | 22 + .../pattern_substs_on_brace_enum_variant.stderr | 26 + .../pattern_substs_on_brace_struct.rs | 20 + .../pattern_substs_on_brace_struct.stderr | 26 + .../pattern_substs_on_tuple_enum_variant.rs | 22 + .../pattern_substs_on_tuple_enum_variant.stderr | 26 + .../pattern_substs_on_tuple_struct.rs | 20 + .../pattern_substs_on_tuple_struct.stderr | 26 + tests/ui/nll/user-annotations/patterns.rs | 136 + tests/ui/nll/user-annotations/patterns.stderr | 189 + .../ui/nll/user-annotations/promoted-annotation.rs | 10 + .../user-annotations/promoted-annotation.stderr | 17 + .../user-annotations/type-annotation-with-hrtb.rs | 33 + .../type_ascription_static_lifetime.rs | 7 + .../type_ascription_static_lifetime.stderr | 14 + tests/ui/nll/user-annotations/wf-self-type.rs | 13 + tests/ui/nll/user-annotations/wf-self-type.stderr | 14 + tests/ui/nll/vimwiki-core-regression.rs | 37 + tests/ui/nll/where_clauses_in_functions.rs | 15 + tests/ui/nll/where_clauses_in_functions.stderr | 14 + tests/ui/nll/where_clauses_in_structs.rs | 15 + tests/ui/nll/where_clauses_in_structs.stderr | 17 + tests/ui/no-capture-arc.rs | 17 + tests/ui/no-capture-arc.stderr | 19 + tests/ui/no-core-1.rs | 15 + tests/ui/no-core-2.rs | 20 + tests/ui/no-link-unknown-crate.rs | 4 + tests/ui/no-link-unknown-crate.stderr | 9 + tests/ui/no-patterns-in-args-2.rs | 13 + tests/ui/no-patterns-in-args-2.stderr | 23 + tests/ui/no-patterns-in-args-macro.rs | 26 + tests/ui/no-patterns-in-args-macro.stderr | 22 + tests/ui/no-patterns-in-args.rs | 16 + tests/ui/no-patterns-in-args.stderr | 34 + tests/ui/no-reuse-move-arc.rs | 15 + tests/ui/no-reuse-move-arc.stderr | 19 + tests/ui/no-send-res-ports.rs | 30 + tests/ui/no-send-res-ports.stderr | 37 + tests/ui/no-warn-on-field-replace-issue-34101.rs | 46 + tests/ui/no_crate_type.rs | 6 + tests/ui/no_crate_type.stderr | 8 + tests/ui/no_send-enum.rs | 18 + tests/ui/no_send-enum.stderr | 23 + tests/ui/no_send-rc.rs | 9 + tests/ui/no_send-rc.stderr | 18 + tests/ui/no_share-enum.rs | 16 + tests/ui/no_share-enum.stderr | 23 + tests/ui/no_share-struct.rs | 14 + tests/ui/no_share-struct.stderr | 18 + tests/ui/noexporttypeexe.rs | 15 + tests/ui/noexporttypeexe.stderr | 14 + tests/ui/non-constant-expr-for-arr-len.rs | 8 + tests/ui/non-constant-expr-for-arr-len.stderr | 11 + tests/ui/non-copyable-void.rs | 14 + tests/ui/non-copyable-void.stderr | 9 + tests/ui/non-fmt-panic.fixed | 89 + tests/ui/non-fmt-panic.rs | 89 + tests/ui/non-fmt-panic.stderr | 491 + tests/ui/non-ice-error-on-worker-io-fail.rs | 40 + tests/ui/non-ice-error-on-worker-io-fail.stderr | 6 + tests/ui/non_modrs_mods/foors_mod.rs | 10 + .../foors_mod/compiletest-ignore-dir | 0 .../ui/non_modrs_mods/foors_mod/inline/somename.rs | 3 + .../ui/non_modrs_mods/foors_mod/inner_foors_mod.rs | 3 + .../foors_mod/inner_foors_mod/innest.rs | 3 + .../foors_mod/inner_modrs_mod/innest.rs | 3 + .../foors_mod/inner_modrs_mod/mod.rs | 3 + .../modrs_mod/compiletest-ignore-dir | 0 .../ui/non_modrs_mods/modrs_mod/inline/somename.rs | 3 + .../ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs | 3 + .../modrs_mod/inner_foors_mod/innest.rs | 3 + .../modrs_mod/inner_modrs_mod/innest.rs | 3 + .../modrs_mod/inner_modrs_mod/mod.rs | 3 + tests/ui/non_modrs_mods/modrs_mod/mod.rs | 8 + tests/ui/non_modrs_mods/non_modrs_mods.rs | 16 + .../some_crazy_attr_mod_dir/arbitrary_name.rs | 3 + .../some_crazy_attr_mod_dir/compiletest-ignore-dir | 0 .../inner_modrs_mod/innest.rs | 3 + .../some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs | 3 + .../non_modrs_mods_and_inline_mods.rs | 5 + tests/ui/non_modrs_mods_and_inline_mods/x.rs | 5 + .../ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs | 1 + tests/ui/noncopyable-class.rs | 36 + tests/ui/noncopyable-class.stderr | 16 + tests/ui/nonscalar-cast.fixed | 16 + tests/ui/nonscalar-cast.rs | 16 + tests/ui/nonscalar-cast.stderr | 11 + tests/ui/not-clone-closure.rs | 12 + tests/ui/not-clone-closure.stderr | 22 + tests/ui/not-copy-closure.rs | 11 + tests/ui/not-copy-closure.stderr | 21 + tests/ui/not-enough-arguments.rs | 31 + tests/ui/not-enough-arguments.stderr | 47 + tests/ui/not-panic/not-panic-safe-2.rs | 13 + tests/ui/not-panic/not-panic-safe-2.stderr | 34 + tests/ui/not-panic/not-panic-safe-3.rs | 13 + tests/ui/not-panic/not-panic-safe-3.stderr | 34 + tests/ui/not-panic/not-panic-safe-4.rs | 12 + tests/ui/not-panic/not-panic-safe-4.stderr | 44 + tests/ui/not-panic/not-panic-safe-5.rs | 10 + tests/ui/not-panic/not-panic-safe-5.stderr | 17 + tests/ui/not-panic/not-panic-safe-6.rs | 12 + tests/ui/not-panic/not-panic-safe-6.stderr | 34 + tests/ui/not-panic/not-panic-safe.rs | 10 + tests/ui/not-panic/not-panic-safe.stderr | 22 + tests/ui/nul-characters.rs | 36 + tests/ui/nullable-pointer-iotareduction.rs | 71 + tests/ui/nullable-pointer-size.rs | 35 + tests/ui/numbers-arithmetic/arith-unsigned.rs | 26 + tests/ui/numbers-arithmetic/div-mod.rs | 19 + tests/ui/numbers-arithmetic/divide-by-zero.rs | 9 + .../float-int-invalid-const-cast.rs | 48 + .../numbers-arithmetic/float-literal-inference.rs | 13 + tests/ui/numbers-arithmetic/float-nan.rs | 82 + tests/ui/numbers-arithmetic/float-signature.rs | 9 + tests/ui/numbers-arithmetic/float.rs | 9 + tests/ui/numbers-arithmetic/float2.rs | 26 + tests/ui/numbers-arithmetic/float_math.rs | 21 + tests/ui/numbers-arithmetic/floatlits.rs | 12 + tests/ui/numbers-arithmetic/i128.rs | 107 + tests/ui/numbers-arithmetic/i32-sub.rs | 6 + tests/ui/numbers-arithmetic/i8-incr.rs | 12 + tests/ui/numbers-arithmetic/int-abs-overflow.rs | 14 + tests/ui/numbers-arithmetic/int.rs | 7 + .../ui/numbers-arithmetic/integer-literal-radix.rs | 19 + .../integer-literal-suffix-inference-2.rs | 9 + .../integer-literal-suffix-inference-3.rs | 4 + .../integer-literal-suffix-inference.rs | 60 + .../issue-8460-const.noopt.stderr | 148 + .../numbers-arithmetic/issue-8460-const.opt.stderr | 148 + ...ssue-8460-const.opt_with_overflow_checks.stderr | 148 + tests/ui/numbers-arithmetic/issue-8460-const.rs | 59 + tests/ui/numbers-arithmetic/issue-8460.rs | 52 + tests/ui/numbers-arithmetic/mod-zero.rs | 9 + .../next-power-of-two-overflow-debug.rs | 27 + .../next-power-of-two-overflow-ndebug.rs | 14 + .../not-suggest-float-literal.rs | 53 + .../not-suggest-float-literal.stderr | 160 + tests/ui/numbers-arithmetic/num-wrapping.rs | 448 + .../numeric-method-autoexport.rs | 25 + tests/ui/numbers-arithmetic/overflowing-add.rs | 10 + tests/ui/numbers-arithmetic/overflowing-lsh-1.rs | 9 + .../ui/numbers-arithmetic/overflowing-lsh-1.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-lsh-2.rs | 9 + .../ui/numbers-arithmetic/overflowing-lsh-2.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-lsh-3.rs | 9 + .../ui/numbers-arithmetic/overflowing-lsh-3.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-lsh-4.rs | 24 + .../ui/numbers-arithmetic/overflowing-lsh-4.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-mul.rs | 10 + tests/ui/numbers-arithmetic/overflowing-neg.rs | 10 + .../numbers-arithmetic/overflowing-pow-signed.rs | 8 + .../numbers-arithmetic/overflowing-pow-unsigned.rs | 8 + tests/ui/numbers-arithmetic/overflowing-rsh-1.rs | 9 + .../ui/numbers-arithmetic/overflowing-rsh-1.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-rsh-2.rs | 9 + .../ui/numbers-arithmetic/overflowing-rsh-2.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-rsh-3.rs | 9 + .../ui/numbers-arithmetic/overflowing-rsh-3.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-rsh-4.rs | 24 + .../ui/numbers-arithmetic/overflowing-rsh-4.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-rsh-5.rs | 9 + .../ui/numbers-arithmetic/overflowing-rsh-5.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-rsh-6.rs | 9 + .../ui/numbers-arithmetic/overflowing-rsh-6.stderr | 14 + tests/ui/numbers-arithmetic/overflowing-sub.rs | 10 + tests/ui/numbers-arithmetic/promoted_overflow.rs | 13 + .../ui/numbers-arithmetic/promoted_overflow_opt.rs | 8 + .../saturating-float-casts-impl.rs | 503 + .../saturating-float-casts-wasm.rs | 13 + .../numbers-arithmetic/saturating-float-casts.rs | 12 + tests/ui/numbers-arithmetic/shift-near-oflo.rs | 100 + tests/ui/numbers-arithmetic/shift-various-types.rs | 48 + tests/ui/numbers-arithmetic/shift.rs | 76 + .../numbers-arithmetic/signed-shift-const-eval.rs | 8 + .../numbers-arithmetic/suggest-float-literal.fixed | 37 + .../ui/numbers-arithmetic/suggest-float-literal.rs | 37 + .../suggest-float-literal.stderr | 139 + tests/ui/numbers-arithmetic/u128-as-f32.rs | 46 + tests/ui/numbers-arithmetic/u128.rs | 119 + tests/ui/numbers-arithmetic/u32-decr.rs | 10 + tests/ui/numbers-arithmetic/u8-incr-decr.rs | 19 + tests/ui/numbers-arithmetic/u8-incr.rs | 15 + tests/ui/numbers-arithmetic/uint.rs | 7 + .../unary-minus-suffix-inference.rs | 23 + tests/ui/numeric/const-scope.rs | 12 + tests/ui/numeric/const-scope.stderr | 67 + .../ui/numeric/integer-literal-suffix-inference.rs | 220 + .../integer-literal-suffix-inference.stderr | 939 ++ tests/ui/numeric/len.rs | 8 + tests/ui/numeric/len.stderr | 21 + tests/ui/numeric/numeric-cast-2.rs | 11 + tests/ui/numeric/numeric-cast-2.stderr | 42 + tests/ui/numeric/numeric-cast-binop.fixed | 320 + tests/ui/numeric/numeric-cast-binop.rs | 320 + tests/ui/numeric/numeric-cast-binop.stderr | 1719 +++ tests/ui/numeric/numeric-cast-no-fix.rs | 87 + tests/ui/numeric/numeric-cast-no-fix.stderr | 396 + .../ui/numeric/numeric-cast-without-suggestion.rs | 38 + .../numeric/numeric-cast-without-suggestion.stderr | 297 + tests/ui/numeric/numeric-cast.fixed | 293 + tests/ui/numeric/numeric-cast.rs | 293 + tests/ui/numeric/numeric-cast.stderr | 2037 ++++ tests/ui/numeric/numeric-fields.rs | 10 + tests/ui/numeric/numeric-fields.stderr | 27 + .../numeric-suffix/numeric-suffix-i32.fixed | 73 + .../numeric/numeric-suffix/numeric-suffix-i32.rs | 73 + .../numeric-suffix/numeric-suffix-i32.stderr | 201 + .../numeric-suffix/numeric-suffix-i64.fixed | 73 + .../numeric/numeric-suffix/numeric-suffix-i64.rs | 73 + .../numeric-suffix/numeric-suffix-i64.stderr | 201 + .../numeric-suffix/numeric-suffix-isize.fixed | 73 + .../numeric/numeric-suffix/numeric-suffix-isize.rs | 73 + .../numeric-suffix/numeric-suffix-isize.stderr | 201 + .../numeric-suffix/numeric-suffix-u32.fixed | 73 + .../numeric/numeric-suffix/numeric-suffix-u32.rs | 73 + .../numeric-suffix/numeric-suffix-u32.stderr | 201 + .../numeric-suffix/numeric-suffix-u64.fixed | 73 + .../numeric/numeric-suffix/numeric-suffix-u64.rs | 73 + .../numeric-suffix/numeric-suffix-u64.stderr | 201 + .../numeric-suffix/numeric-suffix-usize.fixed | 73 + .../numeric/numeric-suffix/numeric-suffix-usize.rs | 73 + .../numeric-suffix/numeric-suffix-usize.stderr | 201 + .../ui/numeric/numeric-suffix/numeric-suffix.fixed | 427 + tests/ui/numeric/numeric-suffix/numeric-suffix.rs | 427 + .../numeric/numeric-suffix/numeric-suffix.stderr | 1227 +++ .../uppercase-base-prefix-invalid-no-fix.rs | 34 + .../uppercase-base-prefix-invalid-no-fix.stderr | 50 + tests/ui/numeric/uppercase-base-prefix.fixed | 77 + tests/ui/numeric/uppercase-base-prefix.rs | 77 + tests/ui/numeric/uppercase-base-prefix.stderr | 98 + .../object-lifetime-default-ambiguous.rs | 48 + .../object-lifetime-default-ambiguous.stderr | 21 + .../object-lifetime-default-default-to-static.rs | 35 + ...ject-lifetime-default-dyn-binding-nonstatic1.rs | 27 + ...-lifetime-default-dyn-binding-nonstatic1.stderr | 9 + ...ject-lifetime-default-dyn-binding-nonstatic2.rs | 30 + ...-lifetime-default-dyn-binding-nonstatic2.stderr | 9 + ...ject-lifetime-default-dyn-binding-nonstatic3.rs | 23 + ...-lifetime-default-dyn-binding-nonstatic3.stderr | 9 + .../object-lifetime-default-dyn-binding-static.rs | 28 + .../object-lifetime-default-elision.rs | 76 + .../object-lifetime-default-elision.stderr | 15 + .../object-lifetime-default-from-box-error.rs | 37 + .../object-lifetime-default-from-box-error.stderr | 33 + .../object-lifetime-default-from-ref-struct.rs | 58 + .../object-lifetime-default-from-rptr-box-error.rs | 20 + ...ect-lifetime-default-from-rptr-box-error.stderr | 10 + .../object-lifetime-default-from-rptr-box.rs | 33 + .../object-lifetime-default-from-rptr-mut.rs | 36 + ...ject-lifetime-default-from-rptr-struct-error.rs | 25 + ...-lifetime-default-from-rptr-struct-error.stderr | 10 + .../object-lifetime-default-from-rptr-struct.rs | 37 + .../object-lifetime-default-from-rptr.rs | 42 + .../object-lifetime-default-inferred.rs | 35 + .../object-lifetime-default-mybox.rs | 37 + .../object-lifetime-default-mybox.stderr | 29 + .../ui/object-lifetime/object-lifetime-default.rs | 50 + .../object-lifetime/object-lifetime-default.stderr | 56 + tests/ui/object-pointer-types.rs | 30 + tests/ui/object-pointer-types.stderr | 27 + tests/ui/object-safety/issue-102762.rs | 26 + tests/ui/object-safety/issue-102762.stderr | 20 + tests/ui/object-safety/issue-102933.rs | 25 + tests/ui/object-safety/issue-106247.rs | 9 + tests/ui/object-safety/issue-19538.rs | 20 + tests/ui/object-safety/issue-19538.stderr | 37 + .../object-safety-associated-consts.curr.stderr | 18 + ...sociated-consts.object_safe_for_dispatch.stderr | 20 + .../object-safety-associated-consts.rs | 19 + tests/ui/object-safety/object-safety-bounds.rs | 12 + tests/ui/object-safety/object-safety-bounds.stderr | 17 + .../object-safety-by-value-self-use.rs | 18 + .../object-safety-by-value-self-use.stderr | 9 + .../object-safety/object-safety-by-value-self.rs | 46 + .../object-safety-generics.curr.stderr | 33 + ...safety-generics.object_safe_for_dispatch.stderr | 37 + tests/ui/object-safety/object-safety-generics.rs | 39 + .../ui/object-safety/object-safety-issue-22040.rs | 42 + .../object-safety/object-safety-issue-22040.stderr | 17 + .../object-safety-mentions-Self.curr.stderr | 33 + ...y-mentions-Self.object_safe_for_dispatch.stderr | 37 + .../object-safety/object-safety-mentions-Self.rs | 42 + .../object-safety-no-static.curr.stderr | 25 + ...afety-no-static.object_safe_for_dispatch.stderr | 27 + tests/ui/object-safety/object-safety-no-static.rs | 24 + tests/ui/object-safety/object-safety-phantom-fn.rs | 22 + .../object-safety-sized-2.curr.stderr | 17 + ...-safety-sized-2.object_safe_for_dispatch.stderr | 19 + tests/ui/object-safety/object-safety-sized-2.rs | 21 + .../object-safety/object-safety-sized.curr.stderr | 17 + ...ct-safety-sized.object_safe_for_dispatch.stderr | 19 + tests/ui/object-safety/object-safety-sized.rs | 19 + .../object-safety-supertrait-mentions-GAT.rs | 15 + .../object-safety-supertrait-mentions-GAT.stderr | 43 + .../object-safety-supertrait-mentions-Self.rs | 21 + .../object-safety-supertrait-mentions-Self.stderr | 17 + tests/ui/objects-coerce-freeze-borrored.rs | 40 + tests/ui/obsolete-in-place/bad.rs | 11 + tests/ui/obsolete-in-place/bad.stderr | 19 + tests/ui/occurs-check-2.rs | 10 + tests/ui/occurs-check-2.stderr | 14 + tests/ui/occurs-check-3.rs | 5 + tests/ui/occurs-check-3.stderr | 9 + tests/ui/occurs-check.rs | 8 + tests/ui/occurs-check.stderr | 14 + tests/ui/on-unimplemented/auxiliary/no_debug.rs | 3 + tests/ui/on-unimplemented/bad-annotation.rs | 64 + tests/ui/on-unimplemented/bad-annotation.stderr | 83 + .../on-unimplemented/expected-comma-found-token.rs | 13 + .../expected-comma-found-token.stderr | 10 + .../feature-gate-on-unimplemented.rs | 8 + .../feature-gate-on-unimplemented.stderr | 11 + tests/ui/on-unimplemented/impl-substs.rs | 15 + tests/ui/on-unimplemented/impl-substs.stderr | 14 + tests/ui/on-unimplemented/issue-104140.rs | 8 + tests/ui/on-unimplemented/issue-104140.stderr | 15 + tests/ui/on-unimplemented/multiple-impls.rs | 45 + tests/ui/on-unimplemented/multiple-impls.stderr | 108 + tests/ui/on-unimplemented/no-debug.rs | 16 + tests/ui/on-unimplemented/no-debug.stderr | 46 + tests/ui/on-unimplemented/on-impl.rs | 26 + tests/ui/on-unimplemented/on-impl.stderr | 32 + tests/ui/on-unimplemented/on-trait.rs | 32 + tests/ui/on-unimplemented/on-trait.stderr | 29 + tests/ui/on-unimplemented/parent-label.rs | 27 + tests/ui/on-unimplemented/parent-label.stderr | 69 + tests/ui/on-unimplemented/slice-index.rs | 10 + tests/ui/on-unimplemented/slice-index.stderr | 25 + tests/ui/on-unimplemented/sum.rs | 9 + tests/ui/on-unimplemented/sum.stderr | 43 + tests/ui/once-cant-call-twice-on-heap.rs | 17 + tests/ui/once-cant-call-twice-on-heap.stderr | 23 + tests/ui/oom_unwind.rs | 21 + tests/ui/op-assign-builtins-by-ref.rs | 76 + tests/ui/opeq.rs | 17 + .../ui/operator-recovery/less-than-greater-than.rs | 4 + .../less-than-greater-than.stderr | 8 + tests/ui/operator-recovery/spaceship.rs | 4 + tests/ui/operator-recovery/spaceship.stderr | 8 + tests/ui/opt-in-copy.rs | 22 + tests/ui/opt-in-copy.stderr | 21 + tests/ui/optimization-fuel-0.rs | 17 + tests/ui/optimization-fuel-0.stderr | 4 + tests/ui/optimization-fuel-1.rs | 18 + tests/ui/optimization-fuel-1.stderr | 4 + tests/ui/optimization-remark.rs | 28 + tests/ui/or-patterns/already-bound-name.rs | 43 + tests/ui/or-patterns/already-bound-name.stderr | 101 + tests/ui/or-patterns/basic-switch.rs | 31 + tests/ui/or-patterns/basic-switchint.rs | 52 + tests/ui/or-patterns/bindings-runpass-1.rs | 23 + tests/ui/or-patterns/bindings-runpass-2.rs | 30 + tests/ui/or-patterns/box-patterns.rs | 36 + tests/ui/or-patterns/consistent-bindings.rs | 39 + tests/ui/or-patterns/const-fn.rs | 29 + .../or-patterns/exhaustiveness-non-exhaustive.rs | 17 + .../exhaustiveness-non-exhaustive.stderr | 42 + tests/ui/or-patterns/exhaustiveness-pass.rs | 38 + .../exhaustiveness-unreachable-pattern.rs | 152 + .../exhaustiveness-unreachable-pattern.stderr | 170 + tests/ui/or-patterns/fn-param-wrap-parens.fixed | 13 + tests/ui/or-patterns/fn-param-wrap-parens.rs | 13 + tests/ui/or-patterns/fn-param-wrap-parens.stderr | 8 + tests/ui/or-patterns/for-loop.rs | 16 + tests/ui/or-patterns/if-let-while-let.rs | 20 + tests/ui/or-patterns/inconsistent-modes.rs | 25 + tests/ui/or-patterns/inconsistent-modes.stderr | 80 + tests/ui/or-patterns/inner-or-pat.or3.stderr | 11 + tests/ui/or-patterns/inner-or-pat.or4.stderr | 11 + tests/ui/or-patterns/inner-or-pat.rs | 73 + .../issue-64879-trailing-before-guard.rs | 15 + .../issue-64879-trailing-before-guard.stderr | 19 + .../or-patterns/issue-67514-irrefutable-param.rs | 9 + .../issue-68785-irrefutable-param-with-at.rs | 12 + ...ld-have-been-expanded-earlier-non-exhaustive.rs | 7 + ...ave-been-expanded-earlier-non-exhaustive.stderr | 31 + ...ssue-69875-should-have-been-expanded-earlier.rs | 7 + .../issue-70413-no-unreachable-pat-and-guard.rs | 21 + tests/ui/or-patterns/let-pattern.rs | 17 + tests/ui/or-patterns/macro-pat.rs | 41 + .../ui/or-patterns/mismatched-bindings-async-fn.rs | 14 + .../mismatched-bindings-async-fn.stderr | 35 + tests/ui/or-patterns/missing-bindings.rs | 81 + tests/ui/or-patterns/missing-bindings.stderr | 242 + tests/ui/or-patterns/mix-with-wild.rs | 18 + tests/ui/or-patterns/multiple-pattern-typo.rs | 44 + tests/ui/or-patterns/multiple-pattern-typo.stderr | 56 + .../or-patterns/nested-undelimited-precedence.rs | 44 + .../nested-undelimited-precedence.stderr | 86 + .../or-patterns-binding-type-mismatch.rs | 66 + .../or-patterns-binding-type-mismatch.stderr | 257 + .../or-patterns-default-binding-modes.rs | 131 + .../or-patterns/or-patterns-syntactic-fail-2018.rs | 13 + .../or-patterns-syntactic-fail-2018.stderr | 32 + tests/ui/or-patterns/or-patterns-syntactic-fail.rs | 30 + .../or-patterns/or-patterns-syntactic-fail.stderr | 43 + .../or-patterns/or-patterns-syntactic-pass-2021.rs | 12 + tests/ui/or-patterns/or-patterns-syntactic-pass.rs | 78 + .../or-patterns/or-patterns-syntactic-pass.stderr | 13 + tests/ui/or-patterns/remove-leading-vert.fixed | 48 + tests/ui/or-patterns/remove-leading-vert.rs | 48 + tests/ui/or-patterns/remove-leading-vert.stderr | 162 + tests/ui/or-patterns/search-via-bindings.rs | 63 + tests/ui/or-patterns/slice-patterns.rs | 51 + tests/ui/or-patterns/struct-like.rs | 40 + .../or-patterns/while-parsing-this-or-pattern.rs | 9 + .../while-parsing-this-or-pattern.stderr | 10 + tests/ui/order-dependent-cast-inference.rs | 8 + tests/ui/order-dependent-cast-inference.stderr | 11 + tests/ui/orphan-check-diagnostics.rs | 14 + tests/ui/orphan-check-diagnostics.stderr | 12 + tests/ui/osx-frameworks.rs | 7 + tests/ui/osx-frameworks.stderr | 9 + tests/ui/out-pointer-aliasing.rs | 23 + tests/ui/output-slot-variants.rs | 69 + tests/ui/output-type-mismatch.rs | 5 + tests/ui/output-type-mismatch.stderr | 11 + tests/ui/over-constrained-vregs.rs | 12 + .../auxiliary/overloaded_autoderef_xc.rs | 30 + tests/ui/overloaded/fixup-deref-mut.rs | 50 + tests/ui/overloaded/issue-14958.rs | 31 + tests/ui/overloaded/overloaded-autoderef-count.rs | 74 + .../ui/overloaded/overloaded-autoderef-indexing.rs | 20 + tests/ui/overloaded/overloaded-autoderef-order.rs | 73 + tests/ui/overloaded/overloaded-autoderef-vtable.rs | 39 + tests/ui/overloaded/overloaded-autoderef-xcrate.rs | 9 + tests/ui/overloaded/overloaded-autoderef.rs | 43 + tests/ui/overloaded/overloaded-calls-nontuple.rs | 30 + .../ui/overloaded/overloaded-calls-nontuple.stderr | 34 + .../overloaded/overloaded-calls-object-one-arg.rs | 13 + .../overloaded/overloaded-calls-object-two-args.rs | 13 + .../overloaded-calls-object-zero-args.rs | 13 + .../overloaded/overloaded-calls-param-vtables.rs | 32 + tests/ui/overloaded/overloaded-calls-simple.rs | 78 + tests/ui/overloaded/overloaded-calls-zero-args.rs | 30 + tests/ui/overloaded/overloaded-deref-count.rs | 78 + tests/ui/overloaded/overloaded-deref.rs | 43 + tests/ui/overloaded/overloaded-index-assoc-list.rs | 48 + tests/ui/overloaded/overloaded-index-autoderef.rs | 75 + tests/ui/overloaded/overloaded-index-in-field.rs | 46 + tests/ui/overloaded/overloaded-index.rs | 64 + .../overloaded_deref_with_ref_pattern.rs | 95 + ...overloaded_deref_with_ref_pattern_issue15609.rs | 37 + .../packed-struct-generic-transmute.rs | 27 + .../packed-struct-generic-transmute.stderr | 12 + tests/ui/packed-struct/packed-struct-transmute.rs | 29 + .../packed-struct/packed-struct-transmute.stderr | 12 + tests/ui/packed/auxiliary/packed.rs | 19 + tests/ui/packed/issue-27060-2.rs | 6 + tests/ui/packed/issue-27060-2.stderr | 27 + tests/ui/packed/issue-27060-rpass.rs | 23 + tests/ui/packed/issue-27060-rpass.stderr | 68 + tests/ui/packed/issue-27060.rs | 27 + tests/ui/packed/issue-27060.stderr | 99 + tests/ui/packed/issue-46152.rs | 24 + .../ui/packed/packed-struct-address-of-element.rs | 36 + .../packed/packed-struct-borrow-element-64bit.rs | 18 + .../packed-struct-borrow-element-64bit.stderr | 35 + tests/ui/packed/packed-struct-borrow-element.rs | 34 + .../ui/packed/packed-struct-borrow-element.stderr | 63 + tests/ui/packed/packed-struct-drop-aligned.rs | 57 + tests/ui/packed/packed-struct-generic-layout.rs | 32 + tests/ui/packed/packed-struct-generic-size.rs | 44 + tests/ui/packed/packed-struct-layout.rs | 28 + tests/ui/packed/packed-struct-match.rs | 45 + tests/ui/packed/packed-struct-optimized-enum.rs | 36 + tests/ui/packed/packed-struct-size-xc.rs | 20 + tests/ui/packed/packed-struct-size.rs | 157 + tests/ui/packed/packed-struct-vec.rs | 120 + tests/ui/packed/packed-tuple-struct-layout.rs | 23 + tests/ui/packed/packed-tuple-struct-size.rs | 79 + .../packed-with-inference-vars-issue-61402.rs | 22 + .../ui/panic-handler/auxiliary/some-panic-impl.rs | 11 + .../ui/panic-handler/auxiliary/weak-lang-items.rs | 22 + .../panic-handler/panic-handler-bad-signature-1.rs | 13 + .../panic-handler-bad-signature-1.stderr | 14 + .../panic-handler/panic-handler-bad-signature-2.rs | 14 + .../panic-handler-bad-signature-2.stderr | 8 + .../panic-handler/panic-handler-bad-signature-3.rs | 11 + .../panic-handler-bad-signature-3.stderr | 8 + .../panic-handler/panic-handler-bad-signature-4.rs | 12 + .../panic-handler-bad-signature-4.stderr | 8 + tests/ui/panic-handler/panic-handler-duplicate.rs | 17 + .../panic-handler/panic-handler-duplicate.stderr | 15 + tests/ui/panic-handler/panic-handler-missing.rs | 9 + .../panic-handler-requires-panic-info.rs | 15 + .../panic-handler-requires-panic-info.stderr | 4 + tests/ui/panic-handler/panic-handler-std.rs | 12 + tests/ui/panic-handler/panic-handler-std.stderr | 13 + tests/ui/panic-handler/panic-handler-twice.rs | 19 + .../panic-handler/panic-handler-wrong-location.rs | 8 + .../panic-handler-wrong-location.stderr | 11 + tests/ui/panic-handler/weak-lang-item-2.rs | 15 + tests/ui/panic-handler/weak-lang-item.rs | 12 + tests/ui/panic-handler/weak-lang-item.stderr | 22 + .../ui/panic-runtime/abort-link-to-unwind-dylib.rs | 18 + .../abort-link-to-unwind-dylib.stderr | 4 + .../abort-link-to-unwinding-crates.rs | 40 + tests/ui/panic-runtime/abort.rs | 43 + tests/ui/panic-runtime/auxiliary/depends.rs | 8 + .../auxiliary/exit-success-if-unwind.rs | 16 + tests/ui/panic-runtime/auxiliary/needs-abort.rs | 5 + .../panic-runtime/auxiliary/needs-panic-runtime.rs | 6 + tests/ui/panic-runtime/auxiliary/needs-unwind.rs | 13 + .../panic-runtime/auxiliary/panic-runtime-abort.rs | 17 + .../auxiliary/panic-runtime-lang-items.rs | 15 + .../auxiliary/panic-runtime-unwind.rs | 17 + .../auxiliary/panic-runtime-unwind2.rs | 17 + .../auxiliary/wants-panic-runtime-abort.rs | 7 + .../auxiliary/wants-panic-runtime-unwind.rs | 6 + tests/ui/panic-runtime/bad-panic-flag1.rs | 4 + tests/ui/panic-runtime/bad-panic-flag1.stderr | 2 + tests/ui/panic-runtime/bad-panic-flag2.rs | 4 + tests/ui/panic-runtime/bad-panic-flag2.stderr | 2 + tests/ui/panic-runtime/incompatible-type.rs | 24 + tests/ui/panic-runtime/link-to-abort.rs | 11 + tests/ui/panic-runtime/link-to-unwind.rs | 10 + tests/ui/panic-runtime/lto-abort.rs | 33 + tests/ui/panic-runtime/lto-unwind.rs | 37 + tests/ui/panic-runtime/need-abort-got-unwind.rs | 8 + .../ui/panic-runtime/need-abort-got-unwind.stderr | 4 + tests/ui/panic-runtime/need-unwind-got-abort.rs | 9 + .../ui/panic-runtime/need-unwind-got-abort.stderr | 4 + tests/ui/panic-runtime/needs-gate.rs | 7 + tests/ui/panic-runtime/needs-gate.stderr | 21 + .../runtime-depend-on-needs-runtime.rs | 8 + tests/ui/panic-runtime/transitive-link-a-bunch.rs | 15 + .../panic-runtime/transitive-link-a-bunch.stderr | 8 + tests/ui/panic-runtime/two-panic-runtimes.rs | 15 + tests/ui/panic-runtime/unwind-interleaved.rs | 16 + tests/ui/panic-runtime/unwind-rec.rs | 15 + tests/ui/panic-runtime/unwind-rec2.rs | 23 + .../panic-runtime/unwind-tables-target-required.rs | 10 + tests/ui/panic-runtime/unwind-unique.rs | 12 + tests/ui/panic-runtime/want-abort-got-unwind.rs | 9 + tests/ui/panic-runtime/want-abort-got-unwind2.rs | 10 + tests/ui/panic-runtime/want-unwind-got-abort.rs | 11 + .../ui/panic-runtime/want-unwind-got-abort.stderr | 4 + tests/ui/panic-runtime/want-unwind-got-abort2.rs | 12 + .../ui/panic-runtime/want-unwind-got-abort2.stderr | 6 + tests/ui/panic-while-printing.rs | 25 + tests/ui/panic_implementation-closures.rs | 10 + tests/ui/panics/abort-on-panic.rs | 98 + tests/ui/panics/args-panic.rs | 11 + tests/ui/panics/default-backtrace-ice.rs | 9 + tests/ui/panics/default-backtrace-ice.stderr | 18 + tests/ui/panics/doublepanic.rs | 10 + tests/ui/panics/explicit-panic-msg.rs | 15 + tests/ui/panics/explicit-panic.rs | 7 + tests/ui/panics/fmt-panic.rs | 8 + .../issue-47429-short-backtraces.legacy.run.stderr | 5 + tests/ui/panics/issue-47429-short-backtraces.rs | 24 + .../issue-47429-short-backtraces.v0.run.stderr | 5 + tests/ui/panics/location-detail-panic-no-column.rs | 8 + .../location-detail-panic-no-column.run.stderr | 2 + tests/ui/panics/location-detail-panic-no-file.rs | 8 + .../location-detail-panic-no-file.run.stderr | 2 + tests/ui/panics/location-detail-panic-no-line.rs | 8 + .../location-detail-panic-no-line.run.stderr | 2 + .../location-detail-panic-no-location-info.rs | 8 + ...cation-detail-panic-no-location-info.run.stderr | 2 + tests/ui/panics/location-detail-unwrap-no-file.rs | 9 + .../location-detail-unwrap-no-file.run.stderr | 2 + tests/ui/panics/main-panic.rs | 7 + tests/ui/panics/panic-2021.rs | 9 + tests/ui/panics/panic-2021.stderr | 42 + tests/ui/panics/panic-arg.rs | 11 + tests/ui/panics/panic-handler-chain-update-hook.rs | 36 + tests/ui/panics/panic-handler-chain.rs | 30 + tests/ui/panics/panic-handler-flail-wildly.rs | 56 + tests/ui/panics/panic-handler-set-twice.rs | 25 + tests/ui/panics/panic-in-dtor-drops-fields.rs | 38 + tests/ui/panics/panic-macro-any-wrapped.rs | 9 + tests/ui/panics/panic-macro-any.rs | 9 + tests/ui/panics/panic-macro-explicit.rs | 7 + tests/ui/panics/panic-macro-fmt.rs | 7 + tests/ui/panics/panic-macro-owned.rs | 7 + tests/ui/panics/panic-macro-static.rs | 7 + tests/ui/panics/panic-main.rs | 7 + tests/ui/panics/panic-parens.rs | 20 + tests/ui/panics/panic-recover-propagate.rs | 27 + tests/ui/panics/panic-set-handler.rs | 12 + tests/ui/panics/panic-set-unset-handler.rs | 13 + .../panics/panic-short-backtrace-windows-x86_64.rs | 53 + ...panic-short-backtrace-windows-x86_64.run.stderr | 9 + tests/ui/panics/panic-take-handler-nop.rs | 10 + tests/ui/panics/panic-task-name-none.rs | 13 + tests/ui/panics/panic-task-name-owned.rs | 18 + tests/ui/panics/panic.rs | 7 + tests/ui/panics/result-get-panic.rs | 9 + tests/ui/panics/runtime-switch.legacy.run.stderr | 5 + tests/ui/panics/runtime-switch.rs | 27 + tests/ui/panics/runtime-switch.v0.run.stderr | 5 + tests/ui/panics/test-panic.rs | 9 + tests/ui/panics/test-should-fail-bad-message.rs | 10 + tests/ui/panics/test-should-panic-bad-message.rs | 10 + tests/ui/panics/test-should-panic-no-message.rs | 10 + tests/ui/panics/unique-panic.rs | 10 + tests/ui/panics/while-body-panics.rs | 14 + tests/ui/panics/while-panic.rs | 14 + tests/ui/paren-span.rs | 21 + tests/ui/paren-span.stderr | 9 + tests/ui/parser/ascii-only-character-escape.rs | 6 + tests/ui/parser/ascii-only-character-escape.stderr | 20 + .../parser/assoc-const-underscore-semantic-fail.rs | 17 + .../assoc-const-underscore-semantic-fail.stderr | 27 + .../assoc-const-underscore-syntactic-pass.rs | 18 + tests/ui/parser/assoc-oddities-1.rs | 11 + tests/ui/parser/assoc-oddities-1.stderr | 8 + tests/ui/parser/assoc-oddities-2.rs | 6 + tests/ui/parser/assoc-oddities-2.stderr | 8 + tests/ui/parser/assoc-static-semantic-fail.rs | 52 + tests/ui/parser/assoc-static-semantic-fail.stderr | 177 + tests/ui/parser/assoc-static-syntactic-fail.rs | 33 + tests/ui/parser/assoc-static-syntactic-fail.stderr | 122 + tests/ui/parser/assoc-type-in-type-arg.rs | 11 + tests/ui/parser/assoc-type-in-type-arg.stderr | 8 + .../associated-types-project-from-hrtb-explicit.rs | 16 + ...ociated-types-project-from-hrtb-explicit.stderr | 14 + tests/ui/parser/attr-bad-meta-2.rs | 2 + tests/ui/parser/attr-bad-meta-2.stderr | 8 + tests/ui/parser/attr-bad-meta-3.rs | 2 + tests/ui/parser/attr-bad-meta-3.stderr | 8 + tests/ui/parser/attr-bad-meta.rs | 2 + tests/ui/parser/attr-bad-meta.stderr | 8 + tests/ui/parser/attr-before-eof.rs | 3 + tests/ui/parser/attr-before-eof.stderr | 8 + tests/ui/parser/attr-dangling-in-fn.rs | 8 + tests/ui/parser/attr-dangling-in-fn.stderr | 8 + tests/ui/parser/attr-dangling-in-mod.rs | 6 + tests/ui/parser/attr-dangling-in-mod.stderr | 8 + tests/ui/parser/attr-stmt-expr-attr-bad.rs | 109 + tests/ui/parser/attr-stmt-expr-attr-bad.stderr | 445 + tests/ui/parser/attr-with-a-semicolon.rs | 4 + tests/ui/parser/attr-with-a-semicolon.stderr | 14 + tests/ui/parser/attr.rs | 6 + tests/ui/parser/attr.stderr | 17 + ...attribute-with-no-generics-in-parameter-list.rs | 3 + ...ibute-with-no-generics-in-parameter-list.stderr | 8 + tests/ui/parser/attrs-after-extern-mod.rs | 7 + tests/ui/parser/attrs-after-extern-mod.stderr | 12 + tests/ui/parser/bad-char-literals.rs | 20 + tests/ui/parser/bad-char-literals.stderr | 28 + tests/ui/parser/bad-crate-name.rs | 5 + tests/ui/parser/bad-crate-name.stderr | 20 + tests/ui/parser/bad-escape-suggest-raw-string.rs | 7 + .../ui/parser/bad-escape-suggest-raw-string.stderr | 14 + tests/ui/parser/bad-fn-ptr-qualifier.fixed | 26 + tests/ui/parser/bad-fn-ptr-qualifier.rs | 26 + tests/ui/parser/bad-fn-ptr-qualifier.stderr | 146 + tests/ui/parser/bad-if-statements.rs | 38 + tests/ui/parser/bad-if-statements.stderr | 86 + tests/ui/parser/bad-interpolated-block.rs | 13 + tests/ui/parser/bad-interpolated-block.stderr | 39 + tests/ui/parser/bad-let-as-field.rs | 6 + tests/ui/parser/bad-let-as-field.stderr | 15 + tests/ui/parser/bad-lit-suffixes.rs | 44 + tests/ui/parser/bad-lit-suffixes.stderr | 140 + tests/ui/parser/bad-match.rs | 4 + tests/ui/parser/bad-match.stderr | 8 + tests/ui/parser/bad-name.rs | 5 + tests/ui/parser/bad-name.stderr | 8 + tests/ui/parser/bad-pointer-type.rs | 5 + tests/ui/parser/bad-pointer-type.stderr | 15 + tests/ui/parser/bad-recover-kw-after-impl.rs | 15 + tests/ui/parser/bad-recover-ty-after-impl.rs | 17 + tests/ui/parser/bad-struct-following-where.rs | 2 + tests/ui/parser/bad-struct-following-where.stderr | 8 + tests/ui/parser/bad-value-ident-false.rs | 2 + tests/ui/parser/bad-value-ident-false.stderr | 13 + tests/ui/parser/bad-value-ident-true.rs | 2 + tests/ui/parser/bad-value-ident-true.stderr | 13 + tests/ui/parser/bare-struct-body.rs | 15 + tests/ui/parser/bare-struct-body.stderr | 43 + tests/ui/parser/bastion-of-the-turbofish.rs | 43 + tests/ui/parser/better-expected.rs | 3 + tests/ui/parser/better-expected.stderr | 10 + tests/ui/parser/bind-struct-early-modifiers.rs | 7 + tests/ui/parser/bind-struct-early-modifiers.stderr | 10 + tests/ui/parser/block-no-opening-brace.rs | 31 + tests/ui/parser/block-no-opening-brace.stderr | 55 + tests/ui/parser/bound-single-question-mark.rs | 1 + tests/ui/parser/bound-single-question-mark.stderr | 8 + tests/ui/parser/bounds-lifetime-1.rs | 3 + tests/ui/parser/bounds-lifetime-1.stderr | 8 + tests/ui/parser/bounds-lifetime-2.rs | 3 + tests/ui/parser/bounds-lifetime-2.stderr | 8 + tests/ui/parser/bounds-lifetime-where-1.rs | 3 + tests/ui/parser/bounds-lifetime-where-1.stderr | 8 + tests/ui/parser/bounds-lifetime-where.rs | 10 + tests/ui/parser/bounds-lifetime-where.stderr | 8 + tests/ui/parser/bounds-lifetime.rs | 11 + tests/ui/parser/bounds-lifetime.stderr | 8 + tests/ui/parser/bounds-obj-parens.rs | 7 + tests/ui/parser/bounds-type-where.rs | 11 + tests/ui/parser/bounds-type-where.stderr | 8 + tests/ui/parser/bounds-type.rs | 18 + tests/ui/parser/bounds-type.stderr | 14 + tests/ui/parser/byte-literals.rs | 12 + tests/ui/parser/byte-literals.stderr | 54 + tests/ui/parser/byte-string-literals.rs | 9 + tests/ui/parser/byte-string-literals.stderr | 50 + tests/ui/parser/can-begin-expr-check.rs | 20 + tests/ui/parser/can-begin-expr-check.stderr | 8 + tests/ui/parser/chained-comparison-suggestion.rs | 53 + .../ui/parser/chained-comparison-suggestion.stderr | 172 + .../ui/parser/char/whitespace-character-literal.rs | 10 + .../char/whitespace-character-literal.stderr | 16 + tests/ui/parser/circular_modules_hello.rs | 8 + tests/ui/parser/circular_modules_main.rs | 12 + tests/ui/parser/circular_modules_main.stderr | 25 + tests/ui/parser/class-implements-bad-trait.rs | 9 + tests/ui/parser/class-implements-bad-trait.stderr | 8 + tests/ui/parser/closure-return-syntax.rs | 7 + tests/ui/parser/closure-return-syntax.stderr | 13 + tests/ui/parser/column-offset-1-based.rs | 1 + tests/ui/parser/column-offset-1-based.stderr | 8 + .../const-param-decl-on-type-instead-of-impl.rs | 15 + ...const-param-decl-on-type-instead-of-impl.stderr | 47 + ...nstraints-before-generic-args-syntactic-pass.rs | 13 + ...aints-before-generic-args-syntactic-pass.stderr | 24 + tests/ui/parser/default-on-wrong-item-kind.rs | 140 + tests/ui/parser/default-on-wrong-item-kind.stderr | 760 ++ tests/ui/parser/default-unmatched-assoc.rs | 16 + tests/ui/parser/default-unmatched-assoc.stderr | 54 + tests/ui/parser/default-unmatched-extern.rs | 8 + tests/ui/parser/default-unmatched-extern.stderr | 28 + tests/ui/parser/default-unmatched.rs | 6 + tests/ui/parser/default-unmatched.stderr | 16 + tests/ui/parser/default.rs | 28 + tests/ui/parser/default.stderr | 48 + tests/ui/parser/diff-markers/enum-2.rs | 11 + tests/ui/parser/diff-markers/enum-2.stderr | 21 + tests/ui/parser/diff-markers/enum.rs | 7 + tests/ui/parser/diff-markers/enum.stderr | 18 + tests/ui/parser/diff-markers/fn-arg.rs | 16 + tests/ui/parser/diff-markers/fn-arg.stderr | 18 + tests/ui/parser/diff-markers/item-with-attr.rs | 10 + tests/ui/parser/diff-markers/item-with-attr.stderr | 18 + tests/ui/parser/diff-markers/item.rs | 9 + tests/ui/parser/diff-markers/item.stderr | 18 + tests/ui/parser/diff-markers/statement.rs | 15 + tests/ui/parser/diff-markers/statement.stderr | 18 + tests/ui/parser/diff-markers/struct-expr.rs | 12 + tests/ui/parser/diff-markers/struct-expr.stderr | 18 + tests/ui/parser/diff-markers/struct.rs | 7 + tests/ui/parser/diff-markers/struct.stderr | 18 + tests/ui/parser/diff-markers/trait-item.rs | 14 + tests/ui/parser/diff-markers/trait-item.stderr | 18 + tests/ui/parser/diff-markers/tuple-struct.rs | 7 + tests/ui/parser/diff-markers/tuple-struct.stderr | 18 + tests/ui/parser/diff-markers/use-statement.rs | 9 + tests/ui/parser/diff-markers/use-statement.stderr | 18 + tests/ui/parser/do-catch-suggests-try.rs | 10 + tests/ui/parser/do-catch-suggests-try.stderr | 19 + .../do-not-suggest-semicolon-before-array.rs | 8 + .../do-not-suggest-semicolon-before-array.stderr | 10 + ...een-macro-without-exclamation-mark-and-array.rs | 3 + ...macro-without-exclamation-mark-and-array.stderr | 8 + tests/ui/parser/doc-after-struct-field.rs | 16 + tests/ui/parser/doc-after-struct-field.stderr | 19 + tests/ui/parser/doc-before-attr.rs | 4 + tests/ui/parser/doc-before-attr.stderr | 10 + tests/ui/parser/doc-before-eof.rs | 3 + tests/ui/parser/doc-before-eof.stderr | 8 + tests/ui/parser/doc-before-extern-rbrace.rs | 6 + tests/ui/parser/doc-before-extern-rbrace.stderr | 11 + tests/ui/parser/doc-before-fn-rbrace.rs | 5 + tests/ui/parser/doc-before-fn-rbrace.stderr | 11 + tests/ui/parser/doc-before-identifier.rs | 7 + tests/ui/parser/doc-before-identifier.stderr | 8 + tests/ui/parser/doc-before-mod-rbrace.rs | 6 + tests/ui/parser/doc-before-mod-rbrace.stderr | 8 + tests/ui/parser/doc-before-rbrace.rs | 5 + tests/ui/parser/doc-before-rbrace.stderr | 11 + tests/ui/parser/doc-before-semi.rs | 6 + tests/ui/parser/doc-before-semi.stderr | 11 + tests/ui/parser/doc-before-struct-rbrace-1.rs | 10 + tests/ui/parser/doc-before-struct-rbrace-1.stderr | 14 + tests/ui/parser/doc-before-struct-rbrace-2.rs | 9 + tests/ui/parser/doc-before-struct-rbrace-2.stderr | 11 + tests/ui/parser/doc-comment-in-if-statement.rs | 5 + tests/ui/parser/doc-comment-in-if-statement.stderr | 25 + tests/ui/parser/doc-comment-in-stmt.rs | 20 + tests/ui/parser/doc-comment-in-stmt.stderr | 50 + tests/ui/parser/doc-inside-trait-item.rs | 6 + tests/ui/parser/doc-inside-trait-item.stderr | 11 + tests/ui/parser/dotdotdot-expr.rs | 4 + tests/ui/parser/dotdotdot-expr.stderr | 17 + tests/ui/parser/double-pointer.rs | 7 + tests/ui/parser/double-pointer.stderr | 15 + tests/ui/parser/duplicate-visibility.rs | 9 + tests/ui/parser/duplicate-visibility.stderr | 22 + tests/ui/parser/duplicate-where-clauses.rs | 19 + tests/ui/parser/duplicate-where-clauses.stderr | 80 + tests/ui/parser/dyn-trait-compatibility.rs | 14 + tests/ui/parser/dyn-trait-compatibility.stderr | 52 + tests/ui/parser/else-no-if.rs | 32 + tests/ui/parser/else-no-if.stderr | 50 + tests/ui/parser/emoji-identifiers.rs | 19 + tests/ui/parser/emoji-identifiers.stderr | 91 + tests/ui/parser/empty-impl-semicolon.rs | 4 + tests/ui/parser/empty-impl-semicolon.stderr | 10 + tests/ui/parser/expr-as-stmt-2.rs | 10 + tests/ui/parser/expr-as-stmt-2.stderr | 46 + tests/ui/parser/expr-as-stmt.fixed | 79 + tests/ui/parser/expr-as-stmt.rs | 79 + tests/ui/parser/expr-as-stmt.stderr | 248 + .../ui/parser/extern-abi-from-mac-literal-frag.rs | 47 + tests/ui/parser/extern-abi-raw-strings.rs | 13 + tests/ui/parser/extern-abi-string-escaping.rs | 13 + tests/ui/parser/extern-abi-syntactic.rs | 17 + tests/ui/parser/extern-crate-async.rs | 12 + tests/ui/parser/extern-crate-unexpected-token.rs | 1 + .../ui/parser/extern-crate-unexpected-token.stderr | 8 + tests/ui/parser/extern-expected-fn-or-brace.rs | 3 + tests/ui/parser/extern-expected-fn-or-brace.stderr | 8 + tests/ui/parser/extern-foreign-crate.rs | 4 + tests/ui/parser/extern-foreign-crate.stderr | 8 + tests/ui/parser/extern-no-fn.rs | 6 + tests/ui/parser/extern-no-fn.stderr | 12 + tests/ui/parser/float-field-interpolated.rs | 17 + tests/ui/parser/float-field-interpolated.stderr | 46 + tests/ui/parser/float-field.rs | 62 + tests/ui/parser/float-field.stderr | 349 + tests/ui/parser/float-literals.rs | 9 + tests/ui/parser/fn-arg-doc-comment.rs | 30 + tests/ui/parser/fn-arg-doc-comment.stderr | 61 + tests/ui/parser/fn-body-eq-expr-semi.rs | 23 + tests/ui/parser/fn-body-eq-expr-semi.stderr | 117 + tests/ui/parser/fn-body-optional-semantic-fail.rs | 27 + .../parser/fn-body-optional-semantic-fail.stderr | 40 + tests/ui/parser/fn-body-optional-syntactic-pass.rs | 31 + tests/ui/parser/fn-colon-return-type.rs | 6 + tests/ui/parser/fn-colon-return-type.stderr | 8 + tests/ui/parser/fn-defined-using-def.rs | 10 + tests/ui/parser/fn-defined-using-def.stderr | 10 + tests/ui/parser/fn-defined-using-fun.rs | 10 + tests/ui/parser/fn-defined-using-fun.stderr | 10 + tests/ui/parser/fn-defined-using-func.rs | 10 + tests/ui/parser/fn-defined-using-func.stderr | 10 + tests/ui/parser/fn-defined-using-function.rs | 10 + tests/ui/parser/fn-defined-using-function.stderr | 10 + tests/ui/parser/fn-field-parse-error-ice.rs | 10 + tests/ui/parser/fn-field-parse-error-ice.stderr | 28 + tests/ui/parser/fn-header-semantic-fail.rs | 58 + tests/ui/parser/fn-header-semantic-fail.stderr | 302 + tests/ui/parser/fn-header-syntactic-pass.rs | 47 + tests/ui/parser/fn-returns-fn-pointer.rs | 6 + tests/ui/parser/foreign-const-semantic-fail.rs | 9 + tests/ui/parser/foreign-const-semantic-fail.stderr | 35 + tests/ui/parser/foreign-const-syntactic-fail.rs | 9 + .../ui/parser/foreign-const-syntactic-fail.stderr | 22 + tests/ui/parser/foreign-static-semantic-fail.rs | 8 + .../ui/parser/foreign-static-semantic-fail.stderr | 27 + tests/ui/parser/foreign-static-syntactic-pass.rs | 11 + tests/ui/parser/foreign-ty-semantic-fail.rs | 18 + tests/ui/parser/foreign-ty-semantic-fail.stderr | 65 + tests/ui/parser/foreign-ty-syntactic-pass.rs | 12 + tests/ui/parser/if-block-unreachable-expr.rs | 8 + tests/ui/parser/if-in-in.fixed | 7 + tests/ui/parser/if-in-in.rs | 7 + tests/ui/parser/if-in-in.stderr | 10 + tests/ui/parser/impl-item-const-pass.rs | 8 + tests/ui/parser/impl-item-const-semantic-fail.rs | 7 + .../ui/parser/impl-item-const-semantic-fail.stderr | 10 + tests/ui/parser/impl-item-fn-no-body-pass.rs | 8 + .../parser/impl-item-fn-no-body-semantic-fail.rs | 7 + .../impl-item-fn-no-body-semantic-fail.stderr | 10 + tests/ui/parser/impl-item-type-no-body-pass.rs | 11 + .../parser/impl-item-type-no-body-semantic-fail.rs | 20 + .../impl-item-type-no-body-semantic-fail.stderr | 83 + tests/ui/parser/impl-parsing.rs | 10 + tests/ui/parser/impl-parsing.stderr | 40 + tests/ui/parser/impl-qpath.rs | 7 + tests/ui/parser/import-from-path.rs | 2 + tests/ui/parser/import-from-path.stderr | 10 + tests/ui/parser/import-from-rename.rs | 10 + tests/ui/parser/import-from-rename.stderr | 10 + tests/ui/parser/import-glob-path.rs | 2 + tests/ui/parser/import-glob-path.stderr | 10 + tests/ui/parser/import-glob-rename.rs | 10 + tests/ui/parser/import-glob-rename.stderr | 10 + tests/ui/parser/increment-autofix-2.fixed | 63 + tests/ui/parser/increment-autofix-2.rs | 63 + tests/ui/parser/increment-autofix-2.stderr | 84 + tests/ui/parser/increment-autofix.fixed | 31 + tests/ui/parser/increment-autofix.rs | 31 + tests/ui/parser/increment-autofix.stderr | 52 + tests/ui/parser/inner-attr-after-doc-comment.rs | 8 + .../ui/parser/inner-attr-after-doc-comment.stderr | 23 + tests/ui/parser/inner-attr-in-trait-def.rs | 9 + tests/ui/parser/inner-attr.rs | 4 + tests/ui/parser/inner-attr.stderr | 20 + tests/ui/parser/int-literal-too-large-span.rs | 7 + tests/ui/parser/int-literal-too-large-span.stderr | 10 + tests/ui/parser/intersection-patterns-1.fixed | 35 + tests/ui/parser/intersection-patterns-1.rs | 35 + tests/ui/parser/intersection-patterns-1.stderr | 22 + tests/ui/parser/intersection-patterns-2.rs | 20 + tests/ui/parser/intersection-patterns-2.stderr | 13 + tests/ui/parser/inverted-parameters.rs | 32 + tests/ui/parser/inverted-parameters.stderr | 61 + tests/ui/parser/issue-100197-mut-let.fixed | 6 + tests/ui/parser/issue-100197-mut-let.rs | 6 + tests/ui/parser/issue-100197-mut-let.stderr | 8 + tests/ui/parser/issue-101477-enum.fixed | 10 + tests/ui/parser/issue-101477-enum.rs | 10 + tests/ui/parser/issue-101477-enum.stderr | 16 + tests/ui/parser/issue-101477-let.fixed | 6 + tests/ui/parser/issue-101477-let.rs | 6 + tests/ui/parser/issue-101477-let.stderr | 8 + tests/ui/parser/issue-102806.rs | 25 + tests/ui/parser/issue-102806.stderr | 45 + tests/ui/parser/issue-103143.rs | 5 + tests/ui/parser/issue-103143.stderr | 20 + tests/ui/parser/issue-103381.fixed | 59 + tests/ui/parser/issue-103381.rs | 59 + tests/ui/parser/issue-103381.stderr | 50 + tests/ui/parser/issue-103425.rs | 15 + tests/ui/parser/issue-103425.stderr | 29 + tests/ui/parser/issue-103451.rs | 5 + tests/ui/parser/issue-103451.stderr | 32 + tests/ui/parser/issue-103748-ICE-wrong-braces.rs | 8 + .../ui/parser/issue-103748-ICE-wrong-braces.stderr | 51 + tests/ui/parser/issue-103869.rs | 9 + tests/ui/parser/issue-103869.stderr | 16 + tests/ui/parser/issue-104620.rs | 4 + tests/ui/parser/issue-104620.stderr | 8 + tests/ui/parser/issue-104867-inc-dec-2.rs | 52 + tests/ui/parser/issue-104867-inc-dec-2.stderr | 107 + tests/ui/parser/issue-104867-inc-dec.rs | 45 + tests/ui/parser/issue-104867-inc-dec.stderr | 81 + tests/ui/parser/issue-105366.fixed | 12 + tests/ui/parser/issue-105366.rs | 12 + tests/ui/parser/issue-105366.stderr | 13 + tests/ui/parser/issue-105634.rs | 8 + tests/ui/parser/issue-17718-parse-const.rs | 7 + tests/ui/parser/issue-39616.rs | 3 + tests/ui/parser/issue-39616.stderr | 8 + tests/ui/parser/issue-49257.rs | 14 + tests/ui/parser/issue-49257.stderr | 42 + tests/ui/parser/issue-61858.rs | 3 + tests/ui/parser/issue-61858.stderr | 14 + .../parser/issue-68091-unicode-ident-after-if.rs | 10 + .../issue-68091-unicode-ident-after-if.stderr | 10 + ...ue-68092-unicode-ident-after-incomplete-expr.rs | 9 + ...8092-unicode-ident-after-incomplete-expr.stderr | 8 + tests/ui/parser/issue-81804.rs | 9 + tests/ui/parser/issue-81804.stderr | 41 + tests/ui/parser/issue-81827.rs | 11 + tests/ui/parser/issue-81827.stderr | 35 + tests/ui/parser/issue-87694-duplicated-pub.rs | 5 + tests/ui/parser/issue-87694-duplicated-pub.stderr | 17 + tests/ui/parser/issue-87694-misplaced-pub.rs | 5 + tests/ui/parser/issue-87694-misplaced-pub.stderr | 11 + tests/ui/parser/issue-90728.rs | 6 + tests/ui/parser/issue-90728.stderr | 20 + tests/ui/parser/issue-91421.rs | 9 + tests/ui/parser/issue-91421.stderr | 14 + ...ssue-99625-enum-struct-mutually-exclusive.fixed | 13 + .../issue-99625-enum-struct-mutually-exclusive.rs | 13 + ...sue-99625-enum-struct-mutually-exclusive.stderr | 8 + .../issue-99910-const-let-mutually-exclusive.fixed | 8 + .../issue-99910-const-let-mutually-exclusive.rs | 8 + ...issue-99910-const-let-mutually-exclusive.stderr | 14 + .../ui/parser/issues/auxiliary/issue-21146-inc.rs | 3 + ...ue-89971-outer-attr-following-inner-attr-ice.rs | 13 + .../ui/parser/issues/auxiliary/issue-94340-inc.rs | 3 + tests/ui/parser/issues/issue-101540.rs | 7 + tests/ui/parser/issues/issue-101540.stderr | 12 + .../issues/issue-102182-impl-trait-recover.rs | 3 + .../issues/issue-102182-impl-trait-recover.stderr | 14 + tests/ui/parser/issues/issue-10392-2.fixed | 9 + tests/ui/parser/issues/issue-10392-2.rs | 9 + tests/ui/parser/issues/issue-10392-2.stderr | 12 + tests/ui/parser/issues/issue-10392.rs | 7 + tests/ui/parser/issues/issue-10392.stderr | 10 + tests/ui/parser/issues/issue-104088.rs | 26 + tests/ui/parser/issues/issue-104088.stderr | 29 + tests/ui/parser/issues/issue-10636-1.rs | 8 + tests/ui/parser/issues/issue-10636-1.stderr | 11 + tests/ui/parser/issues/issue-10636-2.rs | 11 + tests/ui/parser/issues/issue-10636-2.stderr | 16 + tests/ui/parser/issues/issue-13483.rs | 17 + tests/ui/parser/issues/issue-13483.stderr | 18 + .../parser/issues/issue-14303-fncall.full.stderr | 9 + .../issues/issue-14303-fncall.generic_arg.stderr | 9 + tests/ui/parser/issues/issue-14303-fncall.rs | 20 + tests/ui/parser/issues/issue-14303.rs | 33 + tests/ui/parser/issues/issue-14303.stderr | 39 + tests/ui/parser/issues/issue-15914.rs | 4 + tests/ui/parser/issues/issue-15914.stderr | 8 + tests/ui/parser/issues/issue-15980.rs | 17 + tests/ui/parser/issues/issue-15980.stderr | 25 + tests/ui/parser/issues/issue-1655.rs | 10 + tests/ui/parser/issues/issue-1655.stderr | 8 + tests/ui/parser/issues/issue-17718-const-mut.rs | 7 + .../ui/parser/issues/issue-17718-const-mut.stderr | 10 + tests/ui/parser/issues/issue-17904-2.rs | 3 + tests/ui/parser/issues/issue-17904-2.stderr | 8 + tests/ui/parser/issues/issue-17904.rs | 8 + tests/ui/parser/issues/issue-17904.stderr | 17 + tests/ui/parser/issues/issue-1802-1.rs | 7 + tests/ui/parser/issues/issue-1802-1.stderr | 9 + tests/ui/parser/issues/issue-1802-2.rs | 7 + tests/ui/parser/issues/issue-1802-2.stderr | 9 + tests/ui/parser/issues/issue-19096.rs | 10 + tests/ui/parser/issues/issue-19096.stderr | 14 + tests/ui/parser/issues/issue-19398.rs | 6 + tests/ui/parser/issues/issue-19398.stderr | 13 + tests/ui/parser/issues/issue-20616-1.rs | 36 + tests/ui/parser/issues/issue-20616-1.stderr | 8 + tests/ui/parser/issues/issue-20616-2.rs | 36 + tests/ui/parser/issues/issue-20616-2.stderr | 13 + tests/ui/parser/issues/issue-20616-3.rs | 35 + tests/ui/parser/issues/issue-20616-3.stderr | 13 + tests/ui/parser/issues/issue-20616-4.rs | 35 + tests/ui/parser/issues/issue-20616-4.stderr | 13 + tests/ui/parser/issues/issue-20616-5.rs | 35 + tests/ui/parser/issues/issue-20616-5.stderr | 13 + tests/ui/parser/issues/issue-20616-6.rs | 35 + tests/ui/parser/issues/issue-20616-6.stderr | 13 + tests/ui/parser/issues/issue-20616-7.rs | 35 + tests/ui/parser/issues/issue-20616-7.stderr | 13 + tests/ui/parser/issues/issue-20616-8.rs | 35 + tests/ui/parser/issues/issue-20616-8.stderr | 8 + tests/ui/parser/issues/issue-20616-9.rs | 35 + tests/ui/parser/issues/issue-20616-9.stderr | 8 + tests/ui/parser/issues/issue-20711-2.rs | 10 + tests/ui/parser/issues/issue-20711-2.stderr | 14 + tests/ui/parser/issues/issue-20711.rs | 8 + tests/ui/parser/issues/issue-20711.stderr | 13 + tests/ui/parser/issues/issue-21146.rs | 3 + tests/ui/parser/issues/issue-21146.stderr | 8 + tests/ui/parser/issues/issue-21153.rs | 6 + tests/ui/parser/issues/issue-21153.stderr | 13 + tests/ui/parser/issues/issue-21475.rs | 19 + tests/ui/parser/issues/issue-22647.rs | 15 + tests/ui/parser/issues/issue-22647.stderr | 8 + tests/ui/parser/issues/issue-22712.rs | 9 + tests/ui/parser/issues/issue-22712.stderr | 8 + tests/ui/parser/issues/issue-2354-1.rs | 1 + tests/ui/parser/issues/issue-2354-1.stderr | 8 + tests/ui/parser/issues/issue-2354.rs | 15 + tests/ui/parser/issues/issue-2354.stderr | 16 + .../parser/issues/issue-23620-invalid-escapes.rs | 34 + .../issues/issue-23620-invalid-escapes.stderr | 94 + tests/ui/parser/issues/issue-24197.rs | 3 + tests/ui/parser/issues/issue-24197.stderr | 8 + tests/ui/parser/issues/issue-24375.rs | 9 + tests/ui/parser/issues/issue-24375.stderr | 8 + tests/ui/parser/issues/issue-24780.rs | 9 + tests/ui/parser/issues/issue-24780.stderr | 8 + tests/ui/parser/issues/issue-27255.rs | 10 + tests/ui/parser/issues/issue-27255.stderr | 22 + tests/ui/parser/issues/issue-30318.fixed | 27 + tests/ui/parser/issues/issue-30318.rs | 27 + tests/ui/parser/issues/issue-30318.stderr | 81 + tests/ui/parser/issues/issue-3036.fixed | 7 + tests/ui/parser/issues/issue-3036.rs | 7 + tests/ui/parser/issues/issue-3036.stderr | 10 + tests/ui/parser/issues/issue-31804.rs | 6 + tests/ui/parser/issues/issue-31804.stderr | 8 + tests/ui/parser/issues/issue-32214.rs | 6 + tests/ui/parser/issues/issue-32214.stderr | 15 + tests/ui/parser/issues/issue-32446.rs | 4 + tests/ui/parser/issues/issue-32446.stderr | 11 + tests/ui/parser/issues/issue-32501.rs | 9 + tests/ui/parser/issues/issue-32501.stderr | 10 + tests/ui/parser/issues/issue-32505.rs | 5 + tests/ui/parser/issues/issue-32505.stderr | 8 + tests/ui/parser/issues/issue-33262.rs | 6 + tests/ui/parser/issues/issue-33262.stderr | 8 + tests/ui/parser/issues/issue-33413.rs | 9 + tests/ui/parser/issues/issue-33413.stderr | 22 + tests/ui/parser/issues/issue-33418.fixed | 19 + tests/ui/parser/issues/issue-33418.rs | 21 + tests/ui/parser/issues/issue-33418.stderr | 36 + tests/ui/parser/issues/issue-33455.rs | 1 + tests/ui/parser/issues/issue-33455.stderr | 8 + tests/ui/parser/issues/issue-34222-1.rs | 3 + tests/ui/parser/issues/issue-34222-1.stderr | 11 + tests/ui/parser/issues/issue-34255-1.rs | 10 + tests/ui/parser/issues/issue-34255-1.stderr | 18 + .../issues/issue-35813-postfix-after-cast.rs | 171 + .../issues/issue-35813-postfix-after-cast.stderr | 472 + tests/ui/parser/issues/issue-41155.rs | 7 + tests/ui/parser/issues/issue-41155.stderr | 22 + tests/ui/parser/issues/issue-43196.rs | 6 + tests/ui/parser/issues/issue-43196.stderr | 16 + tests/ui/parser/issues/issue-43692.rs | 3 + tests/ui/parser/issues/issue-43692.stderr | 8 + tests/ui/parser/issues/issue-44021.rs | 6 + tests/ui/parser/issues/issue-44021.stderr | 8 + tests/ui/parser/issues/issue-44406.rs | 10 + tests/ui/parser/issues/issue-44406.stderr | 33 + tests/ui/parser/issues/issue-45296.rs | 6 + tests/ui/parser/issues/issue-45296.stderr | 17 + tests/ui/parser/issues/issue-46186.fixed | 8 + tests/ui/parser/issues/issue-46186.rs | 8 + tests/ui/parser/issues/issue-46186.stderr | 10 + ...s-cannot-interpolate-impl-items-bad-variants.rs | 44 + ...nnot-interpolate-impl-items-bad-variants.stderr | 62 + ...e-48137-macros-cannot-interpolate-impl-items.rs | 34 + tests/ui/parser/issues/issue-48508-aux.rs | 7 + tests/ui/parser/issues/issue-48508.rs | 20 + tests/ui/parser/issues/issue-48636.fixed | 12 + tests/ui/parser/issues/issue-48636.rs | 12 + tests/ui/parser/issues/issue-48636.stderr | 15 + tests/ui/parser/issues/issue-49040.rs | 3 + tests/ui/parser/issues/issue-49040.stderr | 15 + tests/ui/parser/issues/issue-51602.rs | 6 + tests/ui/parser/issues/issue-51602.stderr | 14 + tests/ui/parser/issues/issue-52496.rs | 12 + tests/ui/parser/issues/issue-52496.stderr | 38 + tests/ui/parser/issues/issue-54521-1.rs | 16 + tests/ui/parser/issues/issue-54521-2.fixed | 22 + tests/ui/parser/issues/issue-54521-2.rs | 22 + tests/ui/parser/issues/issue-54521-2.stderr | 26 + tests/ui/parser/issues/issue-54521-3.fixed | 22 + tests/ui/parser/issues/issue-54521-3.rs | 22 + tests/ui/parser/issues/issue-54521-3.stderr | 26 + tests/ui/parser/issues/issue-5544-a.rs | 4 + tests/ui/parser/issues/issue-5544-a.stderr | 10 + tests/ui/parser/issues/issue-5544-b.rs | 4 + tests/ui/parser/issues/issue-5544-b.stderr | 10 + tests/ui/parser/issues/issue-56031.rs | 6 + tests/ui/parser/issues/issue-56031.stderr | 18 + tests/ui/parser/issues/issue-57198.rs | 8 + tests/ui/parser/issues/issue-57198.stderr | 13 + tests/ui/parser/issues/issue-57684.fixed | 37 + tests/ui/parser/issues/issue-57684.rs | 37 + tests/ui/parser/issues/issue-57684.stderr | 18 + tests/ui/parser/issues/issue-57819.fixed | 47 + tests/ui/parser/issues/issue-57819.rs | 47 + tests/ui/parser/issues/issue-57819.stderr | 44 + tests/ui/parser/issues/issue-5806.rs | 7 + tests/ui/parser/issues/issue-5806.stderr | 8 + .../issue-58094-missing-right-square-bracket.rs | 4 + ...issue-58094-missing-right-square-bracket.stderr | 16 + tests/ui/parser/issues/issue-58856-1.rs | 8 + tests/ui/parser/issues/issue-58856-1.stderr | 29 + tests/ui/parser/issues/issue-58856-2.rs | 14 + tests/ui/parser/issues/issue-58856-2.stderr | 34 + tests/ui/parser/issues/issue-59418.rs | 18 + tests/ui/parser/issues/issue-59418.stderr | 26 + tests/ui/parser/issues/issue-60075.rs | 11 + tests/ui/parser/issues/issue-60075.stderr | 29 + tests/ui/parser/issues/issue-62524.rs | 6 + tests/ui/parser/issues/issue-62524.stderr | 33 + tests/ui/parser/issues/issue-62546.rs | 3 + tests/ui/parser/issues/issue-62546.stderr | 17 + tests/ui/parser/issues/issue-62554.rs | 6 + tests/ui/parser/issues/issue-62554.stderr | 73 + tests/ui/parser/issues/issue-62660.rs | 11 + tests/ui/parser/issues/issue-62660.stderr | 13 + tests/ui/parser/issues/issue-62881.rs | 6 + tests/ui/parser/issues/issue-62881.stderr | 26 + tests/ui/parser/issues/issue-62894.rs | 7 + tests/ui/parser/issues/issue-62894.stderr | 50 + tests/ui/parser/issues/issue-62895.rs | 11 + tests/ui/parser/issues/issue-62895.stderr | 47 + tests/ui/parser/issues/issue-62913.rs | 4 + tests/ui/parser/issues/issue-62913.stderr | 22 + tests/ui/parser/issues/issue-62973.rs | 8 + tests/ui/parser/issues/issue-62973.stderr | 83 + .../issues/issue-63115-range-pat-interpolated.rs | 21 + tests/ui/parser/issues/issue-63116.rs | 3 + tests/ui/parser/issues/issue-63116.stderr | 24 + tests/ui/parser/issues/issue-63135.rs | 3 + tests/ui/parser/issues/issue-63135.stderr | 43 + tests/ui/parser/issues/issue-64732.rs | 9 + tests/ui/parser/issues/issue-64732.stderr | 24 + .../issue-65041-empty-vis-matcher-in-enum.rs | 28 + .../issue-65041-empty-vis-matcher-in-trait.rs | 28 + .../issue-65122-mac-invoc-in-mut-patterns.rs | 26 + .../issue-65122-mac-invoc-in-mut-patterns.stderr | 49 + .../issue-65257-invalid-var-decl-recovery.rs | 21 + .../issue-65257-invalid-var-decl-recovery.stderr | 67 + .../issue-65846-rollback-gating-failing-matcher.rs | 15 + tests/ui/parser/issues/issue-6610.rs | 3 + tests/ui/parser/issues/issue-6610.stderr | 10 + .../issues/issue-66357-unexpected-unreachable.rs | 14 + .../issue-66357-unexpected-unreachable.stderr | 16 + tests/ui/parser/issues/issue-66473.rs | Bin 0 -> 127 bytes tests/ui/parser/issues/issue-66473.stderr | Bin 0 -> 1061 bytes ...46-negative-outlives-bound-syntactic-fail.fixed | 14 + ...67146-negative-outlives-bound-syntactic-fail.rs | 14 + ...6-negative-outlives-bound-syntactic-fail.stderr | 20 + ...ue-67377-invalid-syntax-in-enum-discriminant.rs | 35 + ...7377-invalid-syntax-in-enum-discriminant.stderr | 128 + ...ssue-68000-unicode-ident-after-missing-comma.rs | 6 + ...-68000-unicode-ident-after-missing-comma.stderr | 19 + tests/ui/parser/issues/issue-68629.rs | Bin 0 -> 336 bytes tests/ui/parser/issues/issue-68629.stderr | Bin 0 -> 1637 bytes tests/ui/parser/issues/issue-68730.rs | Bin 0 -> 175 bytes tests/ui/parser/issues/issue-68730.stderr | Bin 0 -> 1266 bytes .../issue-68788-in-trait-item-propagation.rs | 21 + tests/ui/parser/issues/issue-68890-2.rs | 5 + tests/ui/parser/issues/issue-68890-2.stderr | 15 + tests/ui/parser/issues/issue-68890.rs | 4 + tests/ui/parser/issues/issue-68890.stderr | 20 + .../issue-70050-ntliteral-accepts-negated-lit.rs | 16 + .../issue-70388-recover-dotdotdot-rest-pat.rs | 7 + .../issue-70388-recover-dotdotdot-rest-pat.stderr | 29 + .../issues/issue-70388-without-witness.fixed | 9 + .../parser/issues/issue-70388-without-witness.rs | 9 + .../issues/issue-70388-without-witness.stderr | 20 + ...ssue-70549-resolve-after-recovered-self-ctor.rs | 18 + ...-70549-resolve-after-recovered-self-ctor.stderr | 56 + .../issue-70552-ascription-in-parens-after-call.rs | 3 + ...ue-70552-ascription-in-parens-after-call.stderr | 8 + .../parser/issues/issue-70583-block-is-empty-1.rs | 20 + .../issues/issue-70583-block-is-empty-1.stderr | 13 + .../parser/issues/issue-70583-block-is-empty-2.rs | 14 + .../issues/issue-70583-block-is-empty-2.stderr | 11 + tests/ui/parser/issues/issue-7222.rs | 12 + tests/ui/parser/issues/issue-72253.rs | 6 + tests/ui/parser/issues/issue-72253.stderr | 10 + tests/ui/parser/issues/issue-72373.rs | 9 + tests/ui/parser/issues/issue-72373.stderr | 13 + .../issues/issue-73568-lifetime-after-mut.rs | 19 + .../issues/issue-73568-lifetime-after-mut.stderr | 39 + tests/ui/parser/issues/issue-75599.rs | 24 + tests/ui/parser/issues/issue-76437-async.rs | 7 + tests/ui/parser/issues/issue-76437-async.stderr | 11 + .../issues/issue-76437-const-async-unsafe.rs | 7 + .../issues/issue-76437-const-async-unsafe.stderr | 11 + tests/ui/parser/issues/issue-76437-const-async.rs | 7 + .../parser/issues/issue-76437-const-async.stderr | 11 + tests/ui/parser/issues/issue-76437-const.rs | 7 + tests/ui/parser/issues/issue-76437-const.stderr | 11 + .../parser/issues/issue-76437-pub-crate-unsafe.rs | 7 + .../issues/issue-76437-pub-crate-unsafe.stderr | 11 + tests/ui/parser/issues/issue-76437-unsafe.rs | 7 + tests/ui/parser/issues/issue-76437-unsafe.stderr | 11 + tests/ui/parser/issues/issue-76597.fixed | 11 + tests/ui/parser/issues/issue-76597.rs | 11 + tests/ui/parser/issues/issue-76597.stderr | 13 + tests/ui/parser/issues/issue-7970b.rs | 4 + tests/ui/parser/issues/issue-7970b.stderr | 8 + tests/ui/parser/issues/issue-81806.rs | 5 + tests/ui/parser/issues/issue-81806.stderr | 17 + tests/ui/parser/issues/issue-83639.rs | 6 + tests/ui/parser/issues/issue-83639.stderr | 8 + tests/ui/parser/issues/issue-84104.rs | 3 + tests/ui/parser/issues/issue-84104.stderr | 16 + tests/ui/parser/issues/issue-84117.rs | 9 + tests/ui/parser/issues/issue-84117.stderr | 72 + tests/ui/parser/issues/issue-84148-1.rs | 3 + tests/ui/parser/issues/issue-84148-1.stderr | 19 + tests/ui/parser/issues/issue-84148-2.rs | 3 + tests/ui/parser/issues/issue-84148-2.stderr | 27 + tests/ui/parser/issues/issue-8537.rs | 5 + tests/ui/parser/issues/issue-8537.stderr | 11 + tests/ui/parser/issues/issue-86895.rs | 3 + tests/ui/parser/issues/issue-86895.stderr | 8 + .../ui/parser/issues/issue-87086-colon-path-sep.rs | 79 + .../issues/issue-87086-colon-path-sep.stderr | 90 + .../issues/issue-87197-missing-semicolon.fixed | 10 + .../parser/issues/issue-87197-missing-semicolon.rs | 10 + .../issues/issue-87197-missing-semicolon.stderr | 26 + .../issue-87217-keyword-order/const-async-const.rs | 9 + .../const-async-const.stderr | 17 + .../issue-87217-keyword-order/several-kw-jump.rs | 14 + .../several-kw-jump.stderr | 13 + .../issue-87217-keyword-order/wrong-async.rs | 14 + .../issue-87217-keyword-order/wrong-async.stderr | 13 + .../issue-87217-keyword-order/wrong-const.rs | 14 + .../issue-87217-keyword-order/wrong-const.stderr | 13 + .../issue-87217-keyword-order/wrong-unsafe.rs | 14 + .../issue-87217-keyword-order/wrong-unsafe.stderr | 13 + tests/ui/parser/issues/issue-87635.rs | 9 + tests/ui/parser/issues/issue-87635.stderr | 19 + tests/ui/parser/issues/issue-87812-path.rs | 11 + tests/ui/parser/issues/issue-87812-path.stderr | 16 + tests/ui/parser/issues/issue-87812.rs | 13 + tests/ui/parser/issues/issue-87812.stderr | 22 + .../ui/parser/issues/issue-88276-unary-plus.fixed | 8 + tests/ui/parser/issues/issue-88276-unary-plus.rs | 8 + .../ui/parser/issues/issue-88276-unary-plus.stderr | 50 + .../ui/parser/issues/issue-88583-union-as-ident.rs | 15 + tests/ui/parser/issues/issue-88770.rs | 11 + tests/ui/parser/issues/issue-88770.stderr | 60 + tests/ui/parser/issues/issue-88818.rs | 10 + tests/ui/parser/issues/issue-88818.stderr | 18 + tests/ui/parser/issues/issue-89388.rs | 7 + tests/ui/parser/issues/issue-89388.stderr | 8 + tests/ui/parser/issues/issue-89396.fixed | 16 + tests/ui/parser/issues/issue-89396.rs | 16 + tests/ui/parser/issues/issue-89396.stderr | 20 + tests/ui/parser/issues/issue-89574.rs | 4 + tests/ui/parser/issues/issue-89574.stderr | 8 + ...ue-89971-outer-attr-following-inner-attr-ice.rs | 15 + ...9971-outer-attr-following-inner-attr-ice.stderr | 18 + tests/ui/parser/issues/issue-90993.rs | 6 + tests/ui/parser/issues/issue-90993.stderr | 31 + tests/ui/parser/issues/issue-91461.rs | 6 + tests/ui/parser/issues/issue-91461.stderr | 31 + tests/ui/parser/issues/issue-93282.rs | 16 + tests/ui/parser/issues/issue-93282.stderr | 50 + tests/ui/parser/issues/issue-93867.rs | 10 + tests/ui/parser/issues/issue-93867.stderr | 13 + tests/ui/parser/issues/issue-94340.rs | 8 + tests/ui/parser/issues/issue-94340.stderr | 20 + .../item-free-const-no-body-semantic-fail.rs | 7 + .../item-free-const-no-body-semantic-fail.stderr | 24 + .../item-free-const-no-body-syntactic-pass.rs | 8 + .../item-free-static-no-body-semantic-fail.rs | 11 + .../item-free-static-no-body-semantic-fail.stderr | 46 + .../item-free-static-no-body-syntactic-pass.rs | 8 + .../parser/item-free-type-bounds-semantic-fail.rs | 20 + .../item-free-type-bounds-semantic-fail.stderr | 67 + .../parser/item-free-type-bounds-syntactic-pass.rs | 13 + tests/ui/parser/item-kw-case-mismatch.fixed | 34 + tests/ui/parser/item-kw-case-mismatch.rs | 34 + tests/ui/parser/item-kw-case-mismatch.stderr | 86 + tests/ui/parser/item-needs-block.rs | 10 + tests/ui/parser/item-needs-block.stderr | 26 + tests/ui/parser/keyword-abstract.rs | 3 + tests/ui/parser/keyword-abstract.stderr | 13 + tests/ui/parser/keyword-as-as-identifier.rs | 5 + tests/ui/parser/keyword-as-as-identifier.stderr | 13 + tests/ui/parser/keyword-box-as-identifier.rs | 10 + tests/ui/parser/keyword-box-as-identifier.stderr | 66 + tests/ui/parser/keyword-break-as-identifier.rs | 5 + tests/ui/parser/keyword-break-as-identifier.stderr | 13 + tests/ui/parser/keyword-const-as-identifier.rs | 5 + tests/ui/parser/keyword-const-as-identifier.stderr | 13 + tests/ui/parser/keyword-continue-as-identifier.rs | 5 + .../parser/keyword-continue-as-identifier.stderr | 13 + tests/ui/parser/keyword-else-as-identifier.rs | 5 + tests/ui/parser/keyword-else-as-identifier.stderr | 13 + tests/ui/parser/keyword-enum-as-identifier.rs | 5 + tests/ui/parser/keyword-enum-as-identifier.stderr | 13 + tests/ui/parser/keyword-final.rs | 3 + tests/ui/parser/keyword-final.stderr | 13 + tests/ui/parser/keyword-fn-as-identifier.rs | 5 + tests/ui/parser/keyword-fn-as-identifier.stderr | 13 + tests/ui/parser/keyword-for-as-identifier.rs | 5 + tests/ui/parser/keyword-for-as-identifier.stderr | 13 + tests/ui/parser/keyword-if-as-identifier.rs | 5 + tests/ui/parser/keyword-if-as-identifier.stderr | 13 + tests/ui/parser/keyword-impl-as-identifier.rs | 5 + tests/ui/parser/keyword-impl-as-identifier.stderr | 13 + tests/ui/parser/keyword-in-as-identifier.rs | 5 + tests/ui/parser/keyword-in-as-identifier.stderr | 8 + tests/ui/parser/keyword-let-as-identifier.rs | 5 + tests/ui/parser/keyword-let-as-identifier.stderr | 13 + tests/ui/parser/keyword-loop-as-identifier.rs | 5 + tests/ui/parser/keyword-loop-as-identifier.stderr | 13 + tests/ui/parser/keyword-match-as-identifier.rs | 5 + tests/ui/parser/keyword-match-as-identifier.stderr | 13 + tests/ui/parser/keyword-mod-as-identifier.rs | 5 + tests/ui/parser/keyword-mod-as-identifier.stderr | 13 + tests/ui/parser/keyword-move-as-identifier.rs | 5 + tests/ui/parser/keyword-move-as-identifier.stderr | 13 + tests/ui/parser/keyword-mut-as-identifier.rs | 3 + tests/ui/parser/keyword-mut-as-identifier.stderr | 8 + tests/ui/parser/keyword-override.rs | 3 + tests/ui/parser/keyword-override.stderr | 13 + tests/ui/parser/keyword-pub-as-identifier.rs | 5 + tests/ui/parser/keyword-pub-as-identifier.stderr | 13 + tests/ui/parser/keyword-ref-as-identifier.rs | 3 + tests/ui/parser/keyword-ref-as-identifier.stderr | 8 + tests/ui/parser/keyword-return-as-identifier.rs | 5 + .../ui/parser/keyword-return-as-identifier.stderr | 13 + tests/ui/parser/keyword-static-as-identifier.rs | 5 + .../ui/parser/keyword-static-as-identifier.stderr | 13 + tests/ui/parser/keyword-struct-as-identifier.rs | 5 + .../ui/parser/keyword-struct-as-identifier.stderr | 13 + tests/ui/parser/keyword-trait-as-identifier.rs | 5 + tests/ui/parser/keyword-trait-as-identifier.stderr | 13 + .../keyword-try-as-identifier-edition2018.rs | 5 + .../keyword-try-as-identifier-edition2018.stderr | 13 + tests/ui/parser/keyword-type-as-identifier.rs | 5 + tests/ui/parser/keyword-type-as-identifier.stderr | 13 + tests/ui/parser/keyword-typeof.rs | 3 + tests/ui/parser/keyword-typeof.stderr | 13 + tests/ui/parser/keyword-unsafe-as-identifier.rs | 5 + .../ui/parser/keyword-unsafe-as-identifier.stderr | 13 + tests/ui/parser/keyword-use-as-identifier.rs | 5 + tests/ui/parser/keyword-use-as-identifier.stderr | 13 + tests/ui/parser/keyword-where-as-identifier.rs | 5 + tests/ui/parser/keyword-where-as-identifier.stderr | 13 + tests/ui/parser/keyword-while-as-identifier.rs | 5 + tests/ui/parser/keyword-while-as-identifier.stderr | 13 + tests/ui/parser/keyword.rs | 5 + tests/ui/parser/keyword.stderr | 13 + .../ui/parser/keywords-followed-by-double-colon.rs | 8 + .../keywords-followed-by-double-colon.stderr | 14 + tests/ui/parser/kw-in-trait-bounds.rs | 39 + tests/ui/parser/kw-in-trait-bounds.stderr | 127 + tests/ui/parser/label-after-block-like.rs | 43 + tests/ui/parser/label-after-block-like.stderr | 176 + tests/ui/parser/label-is-actually-char.rs | 16 + tests/ui/parser/label-is-actually-char.stderr | 46 + tests/ui/parser/labeled-no-colon-expr.rs | 15 + tests/ui/parser/labeled-no-colon-expr.stderr | 95 + tests/ui/parser/let-binop.fixed | 10 + tests/ui/parser/let-binop.rs | 10 + tests/ui/parser/let-binop.stderr | 26 + tests/ui/parser/lifetime-in-pattern-recover.rs | 6 + tests/ui/parser/lifetime-in-pattern-recover.stderr | 23 + tests/ui/parser/lifetime-in-pattern.rs | 7 + tests/ui/parser/lifetime-in-pattern.stderr | 28 + tests/ui/parser/lifetime-semicolon.fixed | 10 + tests/ui/parser/lifetime-semicolon.rs | 10 + tests/ui/parser/lifetime-semicolon.stderr | 13 + tests/ui/parser/lifetime_starts_expressions.rs | 39 + tests/ui/parser/lifetime_starts_expressions.stderr | 47 + tests/ui/parser/macro-bad-delimiter-ident.rs | 3 + tests/ui/parser/macro-bad-delimiter-ident.stderr | 8 + tests/ui/parser/macro-braces-dot-question.rs | 11 + tests/ui/parser/macro-keyword.rs | 5 + tests/ui/parser/macro-keyword.stderr | 13 + .../parser/macro-mismatched-delim-brace-paren.rs | 7 + .../macro-mismatched-delim-brace-paren.stderr | 11 + .../parser/macro-mismatched-delim-paren-brace.rs | 5 + .../macro-mismatched-delim-paren-brace.stderr | 22 + tests/ui/parser/macro/bad-macro-argument.rs | 4 + tests/ui/parser/macro/bad-macro-argument.stderr | 8 + tests/ui/parser/macro/issue-33569.rs | 12 + tests/ui/parser/macro/issue-33569.stderr | 30 + tests/ui/parser/macro/issue-37113.rs | 11 + tests/ui/parser/macro/issue-37113.stderr | 16 + tests/ui/parser/macro/issue-37234.rs | 9 + tests/ui/parser/macro/issue-37234.stderr | 13 + .../literals-are-validated-before-expansion.rs | 10 + .../literals-are-validated-before-expansion.stderr | 18 + tests/ui/parser/macro/macro-doc-comments-1.rs | 9 + tests/ui/parser/macro/macro-doc-comments-1.stderr | 20 + tests/ui/parser/macro/macro-doc-comments-2.rs | 9 + tests/ui/parser/macro/macro-doc-comments-2.stderr | 20 + tests/ui/parser/macro/macro-incomplete-parse.rs | 27 + .../ui/parser/macro/macro-incomplete-parse.stderr | 35 + tests/ui/parser/macro/macro-repeat.rs | 12 + tests/ui/parser/macro/macro-repeat.stderr | 14 + tests/ui/parser/macro/pub-item-macro.rs | 21 + tests/ui/parser/macro/pub-item-macro.stderr | 31 + tests/ui/parser/macro/trait-non-item-macros.rs | 13 + tests/ui/parser/macro/trait-non-item-macros.stderr | 22 + .../ui/parser/macro/trait-object-macro-matcher.rs | 14 + .../parser/macro/trait-object-macro-matcher.stderr | 15 + tests/ui/parser/macros-no-semicolon-items.rs | 15 + tests/ui/parser/macros-no-semicolon-items.stderr | 47 + tests/ui/parser/macros-no-semicolon.rs | 5 + tests/ui/parser/macros-no-semicolon.stderr | 18 + tests/ui/parser/match-arm-without-braces.rs | 87 + tests/ui/parser/match-arm-without-braces.stderr | 131 + tests/ui/parser/match-arrows-block-then-binop.rs | 7 + .../ui/parser/match-arrows-block-then-binop.stderr | 15 + tests/ui/parser/match-refactor-to-expr.fixed | 12 + tests/ui/parser/match-refactor-to-expr.rs | 12 + tests/ui/parser/match-refactor-to-expr.stderr | 16 + tests/ui/parser/mbe_missing_right_paren.rs | 3 + tests/ui/parser/mbe_missing_right_paren.stderr | 31 + ...ethod-call-on-struct-literal-in-if-condition.rs | 13 + ...d-call-on-struct-literal-in-if-condition.stderr | 13 + .../missing-close-brace-in-impl-trait.rs | 13 + .../missing-close-brace-in-impl-trait.stderr | 34 + .../missing-close-brace-in-struct.rs | 13 + .../missing-close-brace-in-struct.stderr | 20 + .../missing-close-brace-in-trait.rs | 12 + .../missing-close-brace-in-trait.stderr | 27 + .../parser/mismatched-delim-brace-empty-block.rs | 5 + .../mismatched-delim-brace-empty-block.stderr | 14 + .../missing-closing-angle-bracket-eq-constraint.rs | 23 + ...sing-closing-angle-bracket-eq-constraint.stderr | 66 + ...issing-closing-angle-bracket-struct-field-ty.rs | 11 + ...ng-closing-angle-bracket-struct-field-ty.stderr | 18 + tests/ui/parser/missing-semicolon.rs | 8 + tests/ui/parser/missing-semicolon.stderr | 13 + tests/ui/parser/missing_right_paren.rs | 3 + tests/ui/parser/missing_right_paren.stderr | 32 + tests/ui/parser/misspelled-macro-rules.fixed | 13 + tests/ui/parser/misspelled-macro-rules.rs | 13 + tests/ui/parser/misspelled-macro-rules.stderr | 10 + tests/ui/parser/mod_file_not_exist.rs | 9 + tests/ui/parser/mod_file_not_exist.stderr | 18 + tests/ui/parser/mod_file_not_exist_windows.rs | 9 + tests/ui/parser/mod_file_not_exist_windows.stderr | 18 + tests/ui/parser/mod_file_with_path_attr.rs | 8 + tests/ui/parser/mod_file_with_path_attr.stderr | 8 + .../multibyte-char-use-seperator-issue-80134.rs | 10 + ...multibyte-char-use-seperator-issue-80134.stderr | 33 + tests/ui/parser/multiline-comment-line-tracking.rs | 9 + .../parser/multiline-comment-line-tracking.stderr | 8 + tests/ui/parser/multitrait.rs | 9 + tests/ui/parser/multitrait.stderr | 8 + tests/ui/parser/mut-patterns.rs | 48 + tests/ui/parser/mut-patterns.stderr | 114 + tests/ui/parser/nested-bad-turbofish.rs | 3 + tests/ui/parser/nested-bad-turbofish.stderr | 11 + .../parser/nested-missing-closing-angle-bracket.rs | 4 + .../nested-missing-closing-angle-bracket.stderr | 8 + tests/ui/parser/new-unicode-escapes-1.rs | 3 + tests/ui/parser/new-unicode-escapes-1.stderr | 13 + tests/ui/parser/new-unicode-escapes-2.rs | 3 + tests/ui/parser/new-unicode-escapes-2.stderr | 8 + tests/ui/parser/new-unicode-escapes-3.rs | 4 + tests/ui/parser/new-unicode-escapes-3.stderr | 18 + tests/ui/parser/new-unicode-escapes-4.rs | 4 + tests/ui/parser/new-unicode-escapes-4.stderr | 8 + tests/ui/parser/no-binary-float-literal.rs | 8 + tests/ui/parser/no-binary-float-literal.stderr | 22 + tests/ui/parser/no-const-fn-in-extern-block.rs | 8 + tests/ui/parser/no-const-fn-in-extern-block.stderr | 29 + tests/ui/parser/no-hex-float-literal.rs | 9 + tests/ui/parser/no-hex-float-literal.stderr | 29 + tests/ui/parser/no-unsafe-self.rs | 14 + tests/ui/parser/no-unsafe-self.stderr | 38 + tests/ui/parser/not-a-pred.rs | 15 + tests/ui/parser/not-a-pred.stderr | 34 + tests/ui/parser/nt-parsing-has-recovery.rs | 10 + tests/ui/parser/nt-parsing-has-recovery.stderr | 29 + tests/ui/parser/numeric-lifetime.rs | 8 + tests/ui/parser/numeric-lifetime.stderr | 23 + tests/ui/parser/obsolete-syntax-impl-for-dotdot.rs | 9 + .../parser/obsolete-syntax-impl-for-dotdot.stderr | 10 + .../ui/parser/old-suffixes-are-really-forbidden.rs | 4 + .../old-suffixes-are-really-forbidden.stderr | 18 + tests/ui/parser/omitted-arg-in-item-fn.rs | 4 + tests/ui/parser/omitted-arg-in-item-fn.stderr | 22 + tests/ui/parser/operator-associativity.rs | 4 + tests/ui/parser/paamayim-nekudotayim.rs | 5 + tests/ui/parser/paamayim-nekudotayim.stderr | 8 + tests/ui/parser/parse-assoc-type-lt.rs | 9 + tests/ui/parser/parse-error-correct.rs | 10 + tests/ui/parser/parse-error-correct.stderr | 33 + tests/ui/parser/parse-panic.rs | 8 + tests/ui/parser/parser-recovery-1.rs | 13 + tests/ui/parser/parser-recovery-1.stderr | 35 + tests/ui/parser/parser-recovery-2.rs | 12 + tests/ui/parser/parser-recovery-2.stderr | 30 + tests/ui/parser/parser-unicode-whitespace.rs | 12 + tests/ui/parser/pat-lt-bracket-1.rs | 7 + tests/ui/parser/pat-lt-bracket-1.stderr | 8 + tests/ui/parser/pat-lt-bracket-2.rs | 4 + tests/ui/parser/pat-lt-bracket-2.stderr | 18 + tests/ui/parser/pat-lt-bracket-3.rs | 14 + tests/ui/parser/pat-lt-bracket-3.stderr | 8 + tests/ui/parser/pat-lt-bracket-4.rs | 11 + tests/ui/parser/pat-lt-bracket-4.stderr | 8 + tests/ui/parser/pat-lt-bracket-5.rs | 3 + tests/ui/parser/pat-lt-bracket-5.stderr | 8 + tests/ui/parser/pat-lt-bracket-6.rs | 9 + tests/ui/parser/pat-lt-bracket-6.stderr | 18 + tests/ui/parser/pat-lt-bracket-7.rs | 9 + tests/ui/parser/pat-lt-bracket-7.stderr | 18 + tests/ui/parser/pat-ranges-1.rs | 5 + tests/ui/parser/pat-ranges-1.stderr | 8 + tests/ui/parser/pat-ranges-2.rs | 5 + tests/ui/parser/pat-ranges-2.stderr | 8 + tests/ui/parser/pat-ranges-3.rs | 5 + tests/ui/parser/pat-ranges-3.stderr | 8 + tests/ui/parser/pat-ranges-4.rs | 6 + tests/ui/parser/pat-ranges-4.stderr | 8 + tests/ui/parser/pat-ref-enum.rs | 8 + tests/ui/parser/pat-ref-enum.stderr | 8 + tests/ui/parser/pat-tuple-1.rs | 5 + tests/ui/parser/pat-tuple-1.stderr | 8 + tests/ui/parser/pat-tuple-2.rs | 7 + tests/ui/parser/pat-tuple-3.rs | 6 + tests/ui/parser/pat-tuple-3.stderr | 10 + tests/ui/parser/pub-method-macro.rs | 23 + tests/ui/parser/pub-method-macro.stderr | 10 + tests/ui/parser/public-instead-of-pub-1.fixed | 11 + tests/ui/parser/public-instead-of-pub-1.rs | 11 + tests/ui/parser/public-instead-of-pub-1.stderr | 13 + tests/ui/parser/public-instead-of-pub-2.rs | 7 + tests/ui/parser/public-instead-of-pub-2.stderr | 8 + tests/ui/parser/public-instead-of-pub-3.fixed | 9 + tests/ui/parser/public-instead-of-pub-3.rs | 9 + tests/ui/parser/public-instead-of-pub-3.stderr | 13 + tests/ui/parser/public-instead-of-pub.fixed | 8 + tests/ui/parser/public-instead-of-pub.rs | 8 + tests/ui/parser/public-instead-of-pub.stderr | 13 + tests/ui/parser/qualified-path-in-turbofish.fixed | 19 + tests/ui/parser/qualified-path-in-turbofish.rs | 19 + tests/ui/parser/qualified-path-in-turbofish.stderr | 8 + tests/ui/parser/range-3.rs | 6 + tests/ui/parser/range-3.stderr | 8 + tests/ui/parser/range-4.rs | 6 + tests/ui/parser/range-4.stderr | 8 + tests/ui/parser/range-inclusive-extra-equals.rs | 10 + .../ui/parser/range-inclusive-extra-equals.stderr | 10 + tests/ui/parser/range_inclusive.fixed | 7 + tests/ui/parser/range_inclusive.rs | 7 + tests/ui/parser/range_inclusive.stderr | 11 + tests/ui/parser/range_inclusive_dotdotdot.rs | 23 + tests/ui/parser/range_inclusive_dotdotdot.stderr | 62 + tests/ui/parser/ranges-precedence.rs | 52 + ...e-70677-panic-on-unterminated-raw-str-at-eof.rs | 5 + ...677-panic-on-unterminated-raw-str-at-eof.stderr | 9 + tests/ui/parser/raw/raw-byte-string-eof.rs | 3 + tests/ui/parser/raw/raw-byte-string-eof.stderr | 13 + tests/ui/parser/raw/raw-byte-string-literals.rs | 7 + .../ui/parser/raw/raw-byte-string-literals.stderr | 20 + tests/ui/parser/raw/raw-literal-keywords.rs | 25 + tests/ui/parser/raw/raw-literal-keywords.stderr | 39 + tests/ui/parser/raw/raw-literal-self.rs | 4 + tests/ui/parser/raw/raw-literal-self.stderr | 8 + tests/ui/parser/raw/raw-literal-underscore.rs | 4 + tests/ui/parser/raw/raw-literal-underscore.stderr | 8 + tests/ui/parser/raw/raw-str-delim.rs | 3 + tests/ui/parser/raw/raw-str-delim.stderr | 8 + tests/ui/parser/raw/raw-str-in-macro-call.rs | 14 + tests/ui/parser/raw/raw-str-unbalanced.rs | 22 + tests/ui/parser/raw/raw-str-unbalanced.stderr | 36 + tests/ui/parser/raw/raw-str-unterminated.rs | 4 + tests/ui/parser/raw/raw-str-unterminated.stderr | 11 + tests/ui/parser/raw/raw-string-2.rs | 4 + tests/ui/parser/raw/raw-string-2.stderr | 11 + tests/ui/parser/raw/raw-string.rs | 4 + tests/ui/parser/raw/raw-string.stderr | 13 + tests/ui/parser/recover-assoc-const-constraint.rs | 9 + .../parser/recover-assoc-const-constraint.stderr | 21 + tests/ui/parser/recover-assoc-eq-missing-term.rs | 6 + .../ui/parser/recover-assoc-eq-missing-term.stderr | 18 + .../ui/parser/recover-assoc-lifetime-constraint.rs | 6 + .../recover-assoc-lifetime-constraint.stderr | 12 + tests/ui/parser/recover-const-async-fn-ptr.rs | 25 + tests/ui/parser/recover-const-async-fn-ptr.stderr | 155 + tests/ui/parser/recover-enum.rs | 11 + tests/ui/parser/recover-enum.stderr | 37 + tests/ui/parser/recover-enum2.rs | 28 + tests/ui/parser/recover-enum2.stderr | 16 + ...-extra-angle-brackets-in-struct-with-a-field.rs | 6 + ...ra-angle-brackets-in-struct-with-a-field.stderr | 11 + .../parser/recover-field-extra-angle-brackets.rs | 14 + .../recover-field-extra-angle-brackets.stderr | 8 + tests/ui/parser/recover-field-semi.rs | 16 + tests/ui/parser/recover-field-semi.stderr | 35 + tests/ui/parser/recover-fn-ptr-with-generics.rs | 31 + .../ui/parser/recover-fn-ptr-with-generics.stderr | 111 + tests/ui/parser/recover-fn-trait-from-fn-kw.rs | 12 + tests/ui/parser/recover-fn-trait-from-fn-kw.stderr | 48 + .../parser/recover-for-loop-parens-around-head.rs | 15 + .../recover-for-loop-parens-around-head.stderr | 27 + tests/ui/parser/recover-from-bad-variant.rs | 15 + tests/ui/parser/recover-from-bad-variant.stderr | 37 + tests/ui/parser/recover-from-homoglyph.rs | 4 + tests/ui/parser/recover-from-homoglyph.stderr | 22 + .../ui/parser/recover-labeled-non-block-expr.fixed | 26 + tests/ui/parser/recover-labeled-non-block-expr.rs | 26 + .../parser/recover-labeled-non-block-expr.stderr | 74 + .../parser/recover-missing-semi-before-item.fixed | 61 + .../ui/parser/recover-missing-semi-before-item.rs | 61 + .../parser/recover-missing-semi-before-item.stderr | 83 + tests/ui/parser/recover-missing-semi.rs | 13 + tests/ui/parser/recover-missing-semi.stderr | 37 + tests/ui/parser/recover-quantified-closure.rs | 12 + tests/ui/parser/recover-quantified-closure.stderr | 37 + tests/ui/parser/recover-range-pats.rs | 159 + tests/ui/parser/recover-range-pats.stderr | 484 + tests/ui/parser/recover-ref-dyn-mut.rs | 9 + tests/ui/parser/recover-ref-dyn-mut.stderr | 15 + tests/ui/parser/recover-struct.rs | 7 + tests/ui/parser/recover-struct.stderr | 12 + tests/ui/parser/recover-tuple-pat.rs | 12 + tests/ui/parser/recover-tuple-pat.stderr | 8 + tests/ui/parser/recover-tuple.rs | 11 + tests/ui/parser/recover-tuple.stderr | 17 + tests/ui/parser/recover-unticked-labels.fixed | 7 + tests/ui/parser/recover-unticked-labels.rs | 7 + tests/ui/parser/recover-unticked-labels.stderr | 25 + ...r-where-clause-before-tuple-struct-body-0.fixed | 15 + ...over-where-clause-before-tuple-struct-body-0.rs | 17 + ...-where-clause-before-tuple-struct-body-0.stderr | 40 + ...over-where-clause-before-tuple-struct-body-1.rs | 7 + ...-where-clause-before-tuple-struct-body-1.stderr | 23 + tests/ui/parser/recovered-struct-variant.rs | 13 + tests/ui/parser/recovered-struct-variant.stderr | 10 + tests/ui/parser/regions-out-of-scope-slice.rs | 11 + tests/ui/parser/regions-out-of-scope-slice.stderr | 11 + tests/ui/parser/removed-syntax-closure-lifetime.rs | 2 + .../parser/removed-syntax-closure-lifetime.stderr | 13 + tests/ui/parser/removed-syntax-enum-newtype.rs | 1 + tests/ui/parser/removed-syntax-enum-newtype.stderr | 10 + tests/ui/parser/removed-syntax-field-let-2.rs | 12 + tests/ui/parser/removed-syntax-field-let-2.stderr | 33 + tests/ui/parser/removed-syntax-field-let.rs | 6 + tests/ui/parser/removed-syntax-field-let.stderr | 14 + tests/ui/parser/removed-syntax-field-semicolon.rs | 6 + .../parser/removed-syntax-field-semicolon.stderr | 10 + tests/ui/parser/removed-syntax-fixed-vec.rs | 1 + tests/ui/parser/removed-syntax-fixed-vec.stderr | 8 + tests/ui/parser/removed-syntax-fn-sigil.rs | 3 + tests/ui/parser/removed-syntax-fn-sigil.stderr | 10 + tests/ui/parser/removed-syntax-mode.rs | 4 + tests/ui/parser/removed-syntax-mode.stderr | 8 + tests/ui/parser/removed-syntax-mut-vec-expr.rs | 3 + tests/ui/parser/removed-syntax-mut-vec-expr.stderr | 8 + tests/ui/parser/removed-syntax-mut-vec-ty.rs | 1 + tests/ui/parser/removed-syntax-mut-vec-ty.stderr | 8 + tests/ui/parser/removed-syntax-ptr-lifetime.rs | 1 + tests/ui/parser/removed-syntax-ptr-lifetime.stderr | 8 + tests/ui/parser/removed-syntax-record.rs | 1 + tests/ui/parser/removed-syntax-record.stderr | 8 + tests/ui/parser/removed-syntax-static-fn.rs | 10 + tests/ui/parser/removed-syntax-static-fn.stderr | 25 + tests/ui/parser/removed-syntax-uniq-mut-expr.rs | 3 + .../ui/parser/removed-syntax-uniq-mut-expr.stderr | 8 + tests/ui/parser/removed-syntax-uniq-mut-ty.rs | 2 + tests/ui/parser/removed-syntax-uniq-mut-ty.stderr | 8 + tests/ui/parser/removed-syntax-with-1.rs | 10 + tests/ui/parser/removed-syntax-with-1.stderr | 11 + tests/ui/parser/removed-syntax-with-2.rs | 11 + tests/ui/parser/removed-syntax-with-2.stderr | 17 + .../require-parens-for-chained-comparison.rs | 38 + .../require-parens-for-chained-comparison.stderr | 110 + tests/ui/parser/self-in-function-arg.rs | 3 + tests/ui/parser/self-in-function-arg.stderr | 8 + tests/ui/parser/self-param-semantic-fail.rs | 64 + tests/ui/parser/self-param-semantic-fail.stderr | 220 + tests/ui/parser/self-param-syntactic-pass.rs | 66 + tests/ui/parser/semi-after-closure-in-macro.rs | 14 + .../several-carriage-returns-in-doc-comment.rs | 10 + .../several-carriage-returns-in-doc-comment.stderr | 20 + tests/ui/parser/shebang/issue-71471-ignore-tidy.rs | 2 + .../parser/shebang/issue-71471-ignore-tidy.stderr | 8 + tests/ui/parser/shebang/multiline-attrib.rs | 7 + tests/ui/parser/shebang/regular-attrib.rs | 5 + tests/ui/parser/shebang/shebang-and-attrib.rs | 9 + tests/ui/parser/shebang/shebang-comment.rs | 6 + tests/ui/parser/shebang/shebang-doc-comment.rs | 3 + tests/ui/parser/shebang/shebang-doc-comment.stderr | 8 + tests/ui/parser/shebang/shebang-empty.rs | 4 + tests/ui/parser/shebang/shebang-must-start-file.rs | 6 + .../parser/shebang/shebang-must-start-file.stderr | 8 + tests/ui/parser/shebang/shebang-space.rs | 5 + tests/ui/parser/shebang/sneaky-attrib.rs | 16 + tests/ui/parser/shebang/valid-shebang.rs | 6 + tests/ui/parser/similar-tokens.rs | 11 + tests/ui/parser/similar-tokens.stderr | 11 + tests/ui/parser/slowparse-bstring.rs | 6 + tests/ui/parser/slowparse-string.rs | 6 + tests/ui/parser/stmt_expr_attrs_placement.rs | 38 + tests/ui/parser/stmt_expr_attrs_placement.stderr | 65 + .../ui/parser/stripped-nested-outline-mod-pass.rs | 13 + ...efault-values-and-missing-field-separator.fixed | 35 + ...t-default-values-and-missing-field-separator.rs | 35 + ...fault-values-and-missing-field-separator.stderr | 92 + tests/ui/parser/struct-field-numeric-shorthand.rs | 9 + .../parser/struct-field-numeric-shorthand.stderr | 33 + tests/ui/parser/struct-filed-with-attr.fixed | 18 + tests/ui/parser/struct-filed-with-attr.rs | 18 + tests/ui/parser/struct-filed-with-attr.stderr | 8 + tests/ui/parser/struct-literal-in-for.rs | 17 + tests/ui/parser/struct-literal-in-for.stderr | 31 + tests/ui/parser/struct-literal-in-if.rs | 17 + tests/ui/parser/struct-literal-in-if.stderr | 18 + .../parser/struct-literal-in-match-discriminant.rs | 13 + .../struct-literal-in-match-discriminant.stderr | 18 + tests/ui/parser/struct-literal-in-match-guard.rs | 18 + tests/ui/parser/struct-literal-in-while.rs | 17 + tests/ui/parser/struct-literal-in-while.stderr | 18 + .../parser/struct-literal-restrictions-in-lamda.rs | 17 + .../struct-literal-restrictions-in-lamda.stderr | 37 + tests/ui/parser/struct-literal-variant-in-if.rs | 25 + .../ui/parser/struct-literal-variant-in-if.stderr | 71 + tests/ui/parser/suggest-assoc-const.fixed | 10 + tests/ui/parser/suggest-assoc-const.rs | 10 + tests/ui/parser/suggest-assoc-const.stderr | 8 + tests/ui/parser/suggest-const-for-global-var.rs | 6 + .../ui/parser/suggest-const-for-global-var.stderr | 8 + ...removing-semicolon-after-impl-trait-items.fixed | 7 + ...st-removing-semicolon-after-impl-trait-items.rs | 7 + ...emoving-semicolon-after-impl-trait-items.stderr | 15 + tests/ui/parser/suggest-semi-in-array.rs | 5 + tests/ui/parser/suggest-semi-in-array.stderr | 10 + .../ui/parser/suggest-semicolon-before-array.fixed | 11 + tests/ui/parser/suggest-semicolon-before-array.rs | 11 + .../parser/suggest-semicolon-before-array.stderr | 13 + .../parser/trailing-carriage-return-in-string.rs | 14 + .../trailing-carriage-return-in-string.stderr | 10 + tests/ui/parser/trailing-plus-in-bounds.rs | 9 + tests/ui/parser/trailing-question-in-macro-type.rs | 14 + .../parser/trailing-question-in-macro-type.stderr | 9 + tests/ui/parser/trailing-question-in-type.fixed | 10 + tests/ui/parser/trailing-question-in-type.rs | 10 + tests/ui/parser/trailing-question-in-type.stderr | 24 + tests/ui/parser/trait-bounds-not-on-impl.rs | 7 + tests/ui/parser/trait-bounds-not-on-impl.stderr | 8 + .../trait-item-with-defaultness-fail-semantic.rs | 12 + ...rait-item-with-defaultness-fail-semantic.stderr | 60 + .../ui/parser/trait-item-with-defaultness-pass.rs | 13 + tests/ui/parser/trait-object-bad-parens.rs | 16 + tests/ui/parser/trait-object-bad-parens.stderr | 27 + tests/ui/parser/trait-object-delimiters.rs | 17 + tests/ui/parser/trait-object-delimiters.stderr | 78 + tests/ui/parser/trait-object-lifetime-parens.rs | 13 + .../ui/parser/trait-object-lifetime-parens.stderr | 20 + tests/ui/parser/trait-object-polytrait-priority.rs | 10 + .../parser/trait-object-polytrait-priority.stderr | 9 + tests/ui/parser/trait-object-trait-parens.rs | 23 + tests/ui/parser/trait-object-trait-parens.stderr | 94 + tests/ui/parser/trait-plusequal-splitting.rs | 8 + tests/ui/parser/trait-pub-assoc-const.rs | 6 + tests/ui/parser/trait-pub-assoc-const.stderr | 9 + tests/ui/parser/trait-pub-assoc-ty.rs | 6 + tests/ui/parser/trait-pub-assoc-ty.stderr | 9 + tests/ui/parser/trait-pub-method.rs | 6 + tests/ui/parser/trait-pub-method.stderr | 9 + tests/ui/parser/type-alias-where-fixable.fixed | 28 + tests/ui/parser/type-alias-where-fixable.rs | 28 + tests/ui/parser/type-alias-where-fixable.stderr | 42 + tests/ui/parser/type-alias-where.rs | 11 + tests/ui/parser/type-alias-where.stderr | 18 + tests/ui/parser/type-parameters-in-field-exprs.rs | 17 + .../parser/type-parameters-in-field-exprs.stderr | 20 + tests/ui/parser/unbalanced-doublequote.rs | 6 + tests/ui/parser/unbalanced-doublequote.stderr | 10 + tests/ui/parser/unclosed-braces.rs | 22 + tests/ui/parser/unclosed-braces.stderr | 17 + tests/ui/parser/unclosed-delimiter-in-dep.rs | 6 + tests/ui/parser/unclosed-delimiter-in-dep.stderr | 25 + tests/ui/parser/unclosed_delim_mod.rs | 8 + tests/ui/parser/unclosed_delim_mod.stderr | 13 + tests/ui/parser/underscore-suffix-for-float.rs | 4 + tests/ui/parser/underscore-suffix-for-float.stderr | 15 + tests/ui/parser/underscore-suffix-for-string.rs | 17 + .../ui/parser/underscore-suffix-for-string.stderr | 14 + tests/ui/parser/underscore_item_not_const.rs | 16 + tests/ui/parser/underscore_item_not_const.stderr | 74 + tests/ui/parser/unicode-character-literal.fixed | 21 + tests/ui/parser/unicode-character-literal.rs | 21 + tests/ui/parser/unicode-character-literal.stderr | 48 + tests/ui/parser/unicode-chars.rs | 12 + tests/ui/parser/unicode-chars.stderr | 36 + tests/ui/parser/unicode-control-codepoints.rs | 39 + tests/ui/parser/unicode-control-codepoints.stderr | 192 + tests/ui/parser/unicode-quote-chars.rs | 8 + tests/ui/parser/unicode-quote-chars.stderr | 30 + .../parser/unmatched-delimiter-at-end-of-file.rs | 11 + .../unmatched-delimiter-at-end-of-file.stderr | 8 + tests/ui/parser/unmatched-langle-1.rs | 9 + tests/ui/parser/unmatched-langle-1.stderr | 22 + tests/ui/parser/unmatched-langle-2.rs | 15 + tests/ui/parser/unmatched-langle-2.stderr | 8 + tests/ui/parser/unnecessary-let.rs | 11 + tests/ui/parser/unnecessary-let.stderr | 20 + tests/ui/parser/unsafe-foreign-mod-2.rs | 8 + tests/ui/parser/unsafe-foreign-mod-2.stderr | 28 + tests/ui/parser/unsafe-foreign-mod.rs | 5 + tests/ui/parser/unsafe-foreign-mod.stderr | 8 + tests/ui/parser/unsafe-mod.rs | 9 + tests/ui/parser/unsafe-mod.stderr | 23 + tests/ui/parser/unsized.rs | 7 + tests/ui/parser/unsized.stderr | 8 + tests/ui/parser/unsized2.rs | 7 + tests/ui/parser/unsized2.stderr | 8 + .../parser/use-as-where-use-ends-with-mod-sep.rs | 2 + .../use-as-where-use-ends-with-mod-sep.stderr | 14 + tests/ui/parser/use-colon-as-mod-sep.rs | 11 + tests/ui/parser/use-colon-as-mod-sep.stderr | 28 + tests/ui/parser/use-ends-with-mod-sep.rs | 1 + tests/ui/parser/use-ends-with-mod-sep.stderr | 8 + tests/ui/parser/use-unclosed-brace.rs | 12 + tests/ui/parser/use-unclosed-brace.stderr | 27 + tests/ui/parser/utf16-be-without-bom.rs | Bin 0 -> 125 bytes tests/ui/parser/utf16-be-without-bom.stderr | Bin 0 -> 3537 bytes tests/ui/parser/utf16-le-without-bom.rs | Bin 0 -> 126 bytes tests/ui/parser/utf16-le-without-bom.stderr | Bin 0 -> 3500 bytes tests/ui/parser/utf8_idents-rpass.rs | 39 + .../parser/variadic-ffi-nested-syntactic-fail.rs | 9 + .../variadic-ffi-nested-syntactic-fail.stderr | 24 + .../parser/variadic-ffi-semantic-restrictions.rs | 77 + .../variadic-ffi-semantic-restrictions.stderr | 206 + tests/ui/parser/variadic-ffi-syntactic-pass.rs | 53 + tests/ui/parser/virtual-structs.rs | 10 + tests/ui/parser/virtual-structs.stderr | 8 + .../where-clauses-no-bounds-or-predicates.rs | 15 + .../where-clauses-no-bounds-or-predicates.stderr | 8 + tests/ui/parser/where_with_bound.rs | 5 + tests/ui/parser/where_with_bound.stderr | 15 + tests/ui/parser/while-if-let-without-body.rs | 13 + tests/ui/parser/while-if-let-without-body.stderr | 18 + tests/ui/parser/wrong-escape-of-curly-braces.rs | 8 + .../ui/parser/wrong-escape-of-curly-braces.stderr | 18 + tests/ui/partialeq_help.rs | 12 + tests/ui/partialeq_help.stderr | 27 + tests/ui/path-lookahead.fixed | 17 + tests/ui/path-lookahead.rs | 17 + tests/ui/path-lookahead.stderr | 19 + tests/ui/path.rs | 8 + tests/ui/paths-containing-nul.rs | 49 + .../declarations-for-tuple-field-count-errors.rs | 20 + tests/ui/pattern/bindings-after-at/bind-by-copy.rs | 47 + ...-neither-can-live-while-the-other-survives-1.rs | 37 + ...ther-can-live-while-the-other-survives-1.stderr | 79 + .../bind-by-move-no-subbindings-fun-param.rs | 11 + .../bind-by-move-no-subbindings-fun-param.stderr | 13 + .../bindings-after-at/borrowck-move-and-move.rs | 31 + .../borrowck-move-and-move.stderr | 112 + .../borrowck-pat-at-and-box-pass.rs | 84 + .../bindings-after-at/borrowck-pat-at-and-box.rs | 69 + .../borrowck-pat-at-and-box.stderr | 145 + .../borrowck-pat-by-copy-bindings-in-at.rs | 49 + ...rrowck-pat-by-move-and-ref-inverse-promotion.rs | 7 + ...ck-pat-by-move-and-ref-inverse-promotion.stderr | 17 + .../borrowck-pat-by-move-and-ref-inverse.rs | 80 + .../borrowck-pat-by-move-and-ref-inverse.stderr | 487 + .../borrowck-pat-by-move-and-ref.rs | 82 + .../borrowck-pat-by-move-and-ref.stderr | 375 + .../borrowck-pat-ref-both-sides.rs | 45 + .../borrowck-pat-ref-mut-and-ref.rs | 136 + .../borrowck-pat-ref-mut-and-ref.stderr | 445 + .../borrowck-pat-ref-mut-twice.rs | 109 + .../borrowck-pat-ref-mut-twice.stderr | 359 + tests/ui/pattern/bindings-after-at/box-patterns.rs | 35 + .../bindings-after-at/copy-and-move-mixed.rs | 14 + .../bindings-after-at/copy-and-move-mixed.stderr | 17 + ...default-binding-modes-both-sides-independent.rs | 48 + ...ult-binding-modes-both-sides-independent.stderr | 68 + .../bindings-after-at/nested-binding-mode-lint.rs | 12 + .../bindings-after-at/nested-binding-modes-mut.rs | 11 + .../nested-binding-modes-mut.stderr | 25 + .../bindings-after-at/nested-binding-modes-ref.rs | 11 + .../nested-binding-modes-ref.stderr | 15 + .../pattern/bindings-after-at/nested-patterns.rs | 14 + ...nested-type-ascription-syntactically-invalid.rs | 33 + ...ed-type-ascription-syntactically-invalid.stderr | 26 + .../bindings-after-at/or-patterns-box-patterns.rs | 43 + .../or-patterns-slice-patterns.rs | 54 + tests/ui/pattern/bindings-after-at/or-patterns.rs | 38 + .../bindings-after-at/pat-at-same-name-both.rs | 29 + .../bindings-after-at/pat-at-same-name-both.stderr | 64 + .../ui/pattern/bindings-after-at/slice-patterns.rs | 39 + .../wild-before-at-syntactically-rejected.rs | 16 + .../wild-before-at-syntactically-rejected.stderr | 43 + tests/ui/pattern/for-loop-bad-item.rs | 20 + tests/ui/pattern/for-loop-bad-item.stderr | 32 + tests/ui/pattern/ignore-all-the-things.rs | 44 + tests/ui/pattern/integer-range-binding.rs | 8 + tests/ui/pattern/issue-10392.rs | 30 + tests/ui/pattern/issue-106552.rs | 7 + tests/ui/pattern/issue-106552.stderr | 35 + tests/ui/pattern/issue-11577.rs | 18 + tests/ui/pattern/issue-12582.rs | 21 + tests/ui/pattern/issue-14221.rs | 21 + tests/ui/pattern/issue-14221.stderr | 32 + tests/ui/pattern/issue-15080.rs | 22 + tests/ui/pattern/issue-17718-patterns.rs | 12 + tests/ui/pattern/issue-17718-patterns.stderr | 21 + tests/ui/pattern/issue-22546.rs | 52 + tests/ui/pattern/issue-27320.rs | 15 + tests/ui/pattern/issue-52240.rs | 16 + tests/ui/pattern/issue-52240.stderr | 9 + tests/ui/pattern/issue-6449.rs | 44 + .../issue-66270-pat-struct-parser-recovery.rs | 14 + .../issue-66270-pat-struct-parser-recovery.stderr | 10 + ...ssue-67037-pat-tup-scrut-ty-diff-less-fields.rs | 21 + ...-67037-pat-tup-scrut-ty-diff-less-fields.stderr | 33 + ...ssue-67776-match-same-name-enum-variant-refs.rs | 40 + ...-67776-match-same-name-enum-variant-refs.stderr | 41 + .../pattern/issue-68393-let-pat-assoc-constant.rs | 26 + .../issue-68393-let-pat-assoc-constant.stderr | 15 + tests/ui/pattern/issue-72565.rs | 8 + tests/ui/pattern/issue-72565.stderr | 8 + tests/ui/pattern/issue-72574-1.rs | 10 + tests/ui/pattern/issue-72574-1.stderr | 34 + tests/ui/pattern/issue-72574-2.rs | 12 + tests/ui/pattern/issue-72574-2.stderr | 37 + tests/ui/pattern/issue-74539.rs | 15 + tests/ui/pattern/issue-74539.stderr | 37 + tests/ui/pattern/issue-74702.rs | 7 + tests/ui/pattern/issue-74702.stderr | 34 + tests/ui/pattern/issue-74954.rs | 7 + .../issue-80186-mut-binding-help-suggestion.rs | 9 + .../issue-80186-mut-binding-help-suggestion.stderr | 10 + tests/ui/pattern/issue-8351-1.rs | 16 + tests/ui/pattern/issue-8351-2.rs | 16 + .../issue-88074-pat-range-type-inference-err.rs | 28 + ...issue-88074-pat-range-type-inference-err.stderr | 19 + .../issue-88074-pat-range-type-inference.rs | 16 + tests/ui/pattern/issue-92074-macro-ice.rs | 36 + tests/ui/pattern/issue-92074-macro-ice.stderr | 35 + tests/ui/pattern/issue-95878.rs | 12 + tests/ui/pattern/issue-95878.stderr | 8 + .../borrowck-move-ref-pattern-pass.rs | 29 + .../move-ref-patterns/borrowck-move-ref-pattern.rs | 48 + .../borrowck-move-ref-pattern.stderr | 216 + .../by-move-sub-pat-unreachable.rs | 12 + tests/ui/pattern/move-ref-patterns/issue-53840.rs | 20 + .../move-ref-patterns-closure-captures-inside.rs | 120 + ...ove-ref-patterns-closure-captures-inside.stderr | 404 + .../move-ref-patterns-closure-captures-pass.rs | 28 + .../move-ref-patterns-closure-captures.rs | 32 + .../move-ref-patterns-closure-captures.stderr | 63 + ...ef-patterns-default-binding-modes-fixable.fixed | 12 + ...e-ref-patterns-default-binding-modes-fixable.rs | 12 + ...f-patterns-default-binding-modes-fixable.stderr | 17 + .../move-ref-patterns-default-binding-modes.rs | 10 + .../move-ref-patterns-default-binding-modes.stderr | 17 + .../move-ref-patterns-dynamic-semantics.rs | 79 + tests/ui/pattern/non-constant-in-const-path.rs | 18 + tests/ui/pattern/non-constant-in-const-path.stderr | 28 + tests/ui/pattern/non-structural-match-types.rs | 14 + tests/ui/pattern/non-structural-match-types.stderr | 14 + tests/ui/pattern/pat-shadow-in-nested-binding.rs | 6 + .../ui/pattern/pat-shadow-in-nested-binding.stderr | 12 + tests/ui/pattern/pat-struct-field-expr-has-type.rs | 9 + .../pattern/pat-struct-field-expr-has-type.stderr | 14 + tests/ui/pattern/pat-tuple-bad-type.rs | 15 + tests/ui/pattern/pat-tuple-bad-type.stderr | 26 + tests/ui/pattern/pat-tuple-field-count-cross.rs | 57 + .../ui/pattern/pat-tuple-field-count-cross.stderr | 531 + tests/ui/pattern/pat-tuple-overfield.rs | 74 + tests/ui/pattern/pat-tuple-overfield.stderr | 312 + tests/ui/pattern/pat-tuple-underfield.rs | 67 + tests/ui/pattern/pat-tuple-underfield.stderr | 167 + tests/ui/pattern/pat-type-err-formal-param.rs | 8 + tests/ui/pattern/pat-type-err-formal-param.stderr | 11 + tests/ui/pattern/pat-type-err-let-stmt.rs | 16 + tests/ui/pattern/pat-type-err-let-stmt.stderr | 51 + tests/ui/pattern/patkind-litrange-no-expr.rs | 24 + tests/ui/pattern/patkind-litrange-no-expr.stderr | 14 + tests/ui/pattern/pattern-binding-disambiguation.rs | 57 + .../pattern/pattern-binding-disambiguation.stderr | 63 + tests/ui/pattern/pattern-error-continue.rs | 35 + tests/ui/pattern/pattern-error-continue.stderr | 62 + tests/ui/pattern/pattern-ident-path-generics.rs | 6 + .../ui/pattern/pattern-ident-path-generics.stderr | 14 + tests/ui/pattern/pattern-tyvar-2.rs | 6 + tests/ui/pattern/pattern-tyvar-2.stderr | 11 + tests/ui/pattern/pattern-tyvar.rs | 12 + tests/ui/pattern/pattern-tyvar.stderr | 14 + tests/ui/pattern/rest-pat-semantic-disallowed.rs | 83 + .../ui/pattern/rest-pat-semantic-disallowed.stderr | 201 + tests/ui/pattern/rest-pat-syntactic.rs | 73 + tests/ui/pattern/rest-pat-syntactic.stderr | 24 + tests/ui/pattern/size-and-align.rs | 20 + ...priate-missing-pattern-excluding-comments.fixed | 10 + ...propriate-missing-pattern-excluding-comments.rs | 9 + ...riate-missing-pattern-excluding-comments.stderr | 21 + .../usefulness/always-inhabited-union-ref.rs | 32 + .../usefulness/always-inhabited-union-ref.stderr | 37 + tests/ui/pattern/usefulness/auxiliary/empty.rs | 10 + tests/ui/pattern/usefulness/auxiliary/hidden.rs | 14 + tests/ui/pattern/usefulness/auxiliary/unstable.rs | 23 + .../usefulness/const-partial_eq-fallback-ice.rs | 18 + .../const-partial_eq-fallback-ice.stderr | 8 + tests/ui/pattern/usefulness/const-pat-ice.rs | 11 + .../ui/pattern/usefulness/const-private-fields.rs | 30 + tests/ui/pattern/usefulness/consts-opaque.rs | 145 + tests/ui/pattern/usefulness/consts-opaque.stderr | 202 + .../usefulness/deny-irrefutable-let-patterns.rs | 16 + .../deny-irrefutable-let-patterns.stderr | 34 + tests/ui/pattern/usefulness/doc-hidden-fields.rs | 26 + .../ui/pattern/usefulness/doc-hidden-fields.stderr | 59 + .../usefulness/doc-hidden-non-exhaustive.rs | 43 + .../usefulness/doc-hidden-non-exhaustive.stderr | 102 + .../empty-match.exhaustive_patterns.stderr | 303 + .../pattern/usefulness/empty-match.normal.stderr | 303 + tests/ui/pattern/usefulness/empty-match.rs | 95 + tests/ui/pattern/usefulness/floats.rs | 19 + tests/ui/pattern/usefulness/floats.stderr | 28 + tests/ui/pattern/usefulness/guards.rs | 22 + tests/ui/pattern/usefulness/guards.stderr | 16 + .../usefulness/integer-ranges/exhaustiveness.rs | 101 + .../integer-ranges/exhaustiveness.stderr | 149 + .../integer-ranges/overlapping_range_endpoints.rs | 59 + .../overlapping_range_endpoints.stderr | 89 + .../integer-ranges/pointer-sized-int.allow.stderr | 17 + .../integer-ranges/pointer-sized-int.deny.stderr | 170 + .../usefulness/integer-ranges/pointer-sized-int.rs | 50 + .../precise_pointer_matching-message.rs | 18 + .../precise_pointer_matching-message.stderr | 33 + .../usefulness/integer-ranges/reachability.rs | 113 + .../usefulness/integer-ranges/reachability.stderr | 154 + .../pattern/usefulness/irrefutable-let-patterns.rs | 11 + tests/ui/pattern/usefulness/irrefutable-unit.rs | 6 + tests/ui/pattern/usefulness/issue-12116.rs | 21 + tests/ui/pattern/usefulness/issue-12116.stderr | 14 + tests/ui/pattern/usefulness/issue-12369.rs | 11 + tests/ui/pattern/usefulness/issue-12369.stderr | 14 + tests/ui/pattern/usefulness/issue-13727.rs | 15 + tests/ui/pattern/usefulness/issue-13727.stderr | 14 + tests/ui/pattern/usefulness/issue-15129.rs | 17 + tests/ui/pattern/usefulness/issue-15129.stderr | 16 + tests/ui/pattern/usefulness/issue-2111.rs | 11 + tests/ui/pattern/usefulness/issue-2111.stderr | 16 + tests/ui/pattern/usefulness/issue-30240-b.rs | 15 + tests/ui/pattern/usefulness/issue-30240-b.stderr | 14 + tests/ui/pattern/usefulness/issue-30240-rpass.rs | 14 + tests/ui/pattern/usefulness/issue-30240.rs | 10 + tests/ui/pattern/usefulness/issue-30240.stderr | 29 + tests/ui/pattern/usefulness/issue-3096-1.rs | 3 + tests/ui/pattern/usefulness/issue-3096-1.stderr | 17 + tests/ui/pattern/usefulness/issue-3096-2.rs | 6 + tests/ui/pattern/usefulness/issue-3096-2.stderr | 17 + tests/ui/pattern/usefulness/issue-31221.rs | 34 + tests/ui/pattern/usefulness/issue-31221.stderr | 32 + tests/ui/pattern/usefulness/issue-31561.rs | 11 + tests/ui/pattern/usefulness/issue-31561.stderr | 27 + tests/ui/pattern/usefulness/issue-35609.rs | 43 + tests/ui/pattern/usefulness/issue-35609.stderr | 119 + tests/ui/pattern/usefulness/issue-3601.rs | 34 + tests/ui/pattern/usefulness/issue-3601.stderr | 18 + tests/ui/pattern/usefulness/issue-39362.rs | 18 + tests/ui/pattern/usefulness/issue-39362.stderr | 23 + tests/ui/pattern/usefulness/issue-40221.rs | 16 + tests/ui/pattern/usefulness/issue-40221.stderr | 23 + tests/ui/pattern/usefulness/issue-4321.rs | 8 + tests/ui/pattern/usefulness/issue-4321.stderr | 16 + tests/ui/pattern/usefulness/issue-50900.rs | 19 + tests/ui/pattern/usefulness/issue-50900.stderr | 21 + .../issue-53820-slice-pattern-large-array.rs | 11 + tests/ui/pattern/usefulness/issue-56379.rs | 14 + tests/ui/pattern/usefulness/issue-56379.stderr | 27 + tests/ui/pattern/usefulness/issue-57472.rs | 35 + tests/ui/pattern/usefulness/issue-57472.stderr | 20 + ...ue-65413-constants-and-slices-exhaustiveness.rs | 15 + tests/ui/pattern/usefulness/issue-66501.rs | 12 + .../issue-71930-type-of-match-scrutinee.rs | 22 + tests/ui/pattern/usefulness/issue-72377.rs | 17 + tests/ui/pattern/usefulness/issue-72377.stderr | 16 + .../issue-72476-and-89393-associated-type.rs | 56 + .../issue-78123-non-exhaustive-reference.rs | 12 + .../issue-78123-non-exhaustive-reference.stderr | 23 + .../usefulness/issue-78549-ref-pat-and-str.rs | 25 + .../usefulness/issue-80501-or-pat-and-macro.rs | 27 + .../usefulness/issue-82772-match-box-as-struct.rs | 6 + .../issue-82772-match-box-as-struct.stderr | 9 + tests/ui/pattern/usefulness/issue-88747.rs | 14 + tests/ui/pattern/usefulness/match-arm-statics-2.rs | 62 + .../pattern/usefulness/match-arm-statics-2.stderr | 54 + tests/ui/pattern/usefulness/match-arm-statics.rs | 69 + .../ui/pattern/usefulness/match-arm-statics.stderr | 26 + .../usefulness/match-byte-array-patterns-2.rs | 13 + .../usefulness/match-byte-array-patterns-2.stderr | 29 + .../usefulness/match-byte-array-patterns.rs | 55 + .../usefulness/match-byte-array-patterns.stderr | 56 + .../ui/pattern/usefulness/match-non-exhaustive.rs | 4 + .../pattern/usefulness/match-non-exhaustive.stderr | 27 + .../ui/pattern/usefulness/match-privately-empty.rs | 21 + .../usefulness/match-privately-empty.stderr | 21 + tests/ui/pattern/usefulness/match-ref-ice.rs | 16 + tests/ui/pattern/usefulness/match-ref-ice.stderr | 14 + .../ui/pattern/usefulness/match-slice-patterns.rs | 12 + .../pattern/usefulness/match-slice-patterns.stderr | 16 + tests/ui/pattern/usefulness/match-vec-fixed.rs | 18 + tests/ui/pattern/usefulness/match-vec-fixed.stderr | 20 + .../ui/pattern/usefulness/match-vec-unreachable.rs | 29 + .../usefulness/match-vec-unreachable.stderr | 26 + .../pattern/usefulness/nested-exhaustive-match.rs | 14 + .../usefulness/non-exhaustive-defined-here.rs | 107 + .../usefulness/non-exhaustive-defined-here.stderr | 194 + .../usefulness/non-exhaustive-match-nested.rs | 19 + .../usefulness/non-exhaustive-match-nested.stderr | 34 + .../ui/pattern/usefulness/non-exhaustive-match.rs | 63 + .../pattern/usefulness/non-exhaustive-match.stderr | 121 + .../usefulness/non-exhaustive-pattern-witness.rs | 89 + .../non-exhaustive-pattern-witness.stderr | 129 + .../pattern/usefulness/refutable-pattern-errors.rs | 9 + .../usefulness/refutable-pattern-errors.stderr | 25 + .../usefulness/refutable-pattern-in-fn-arg.rs | 6 + .../usefulness/refutable-pattern-in-fn-arg.stderr | 11 + .../ui/pattern/usefulness/slice-pattern-const-2.rs | 31 + .../usefulness/slice-pattern-const-2.stderr | 32 + .../ui/pattern/usefulness/slice-pattern-const-3.rs | 31 + .../usefulness/slice-pattern-const-3.stderr | 32 + tests/ui/pattern/usefulness/slice-pattern-const.rs | 54 + .../pattern/usefulness/slice-pattern-const.stderr | 62 + .../usefulness/slice-patterns-exhaustiveness.rs | 129 + .../slice-patterns-exhaustiveness.stderr | 263 + .../usefulness/slice-patterns-irrefutable.rs | 26 + .../usefulness/slice-patterns-reachability.rs | 25 + .../usefulness/slice-patterns-reachability.stderr | 44 + tests/ui/pattern/usefulness/stable-gated-fields.rs | 16 + .../pattern/usefulness/stable-gated-fields.stderr | 29 + .../ui/pattern/usefulness/stable-gated-patterns.rs | 18 + .../usefulness/stable-gated-patterns.stderr | 42 + .../usefulness/struct-like-enum-nonexhaustive.rs | 12 + .../struct-like-enum-nonexhaustive.stderr | 23 + .../usefulness/struct-pattern-match-useless.rs | 15 + .../usefulness/struct-pattern-match-useless.stderr | 16 + .../ui/pattern/usefulness/top-level-alternation.rs | 57 + .../usefulness/top-level-alternation.stderr | 74 + .../usefulness/tuple-struct-nonexhaustive.rs | 9 + .../usefulness/tuple-struct-nonexhaustive.stderr | 21 + .../type_polymorphic_byte_str_literals.rs | 36 + .../type_polymorphic_byte_str_literals.stderr | 29 + tests/ui/pattern/usefulness/uninhabited.rs | 143 + .../ui/pattern/usefulness/unstable-gated-fields.rs | 18 + .../usefulness/unstable-gated-fields.stderr | 33 + .../pattern/usefulness/unstable-gated-patterns.rs | 22 + .../usefulness/unstable-gated-patterns.stderr | 24 + tests/ui/phantom-auto-trait.rs | 30 + tests/ui/phantom-auto-trait.stderr | 66 + tests/ui/pin-macro/cant_access_internals.rs | 12 + tests/ui/pin-macro/cant_access_internals.stderr | 11 + .../lifetime_errors_on_promotion_misusage.rs | 28 + .../lifetime_errors_on_promotion_misusage.stderr | 31 + ...int-to-type-err-cause-on-impl-trait-return-2.rs | 17 + ...to-type-err-cause-on-impl-trait-return-2.stderr | 12 + tests/ui/polymorphization/closure_in_upvar/fn.rs | 29 + .../ui/polymorphization/closure_in_upvar/fnmut.rs | 34 + .../ui/polymorphization/closure_in_upvar/fnonce.rs | 34 + .../ui/polymorphization/closure_in_upvar/other.rs | 38 + .../polymorphization/const_parameters/closures.rs | 67 + .../const_parameters/closures.stderr | 44 + .../polymorphization/const_parameters/functions.rs | 37 + .../const_parameters/functions.stderr | 17 + tests/ui/polymorphization/drop_shims/simple.rs | 22 + tests/ui/polymorphization/drop_shims/transitive.rs | 27 + tests/ui/polymorphization/generators.rs | 92 + tests/ui/polymorphization/generators.stderr | 39 + tests/ui/polymorphization/issue-74614.rs | 18 + tests/ui/polymorphization/issue-74636.rs | 16 + tests/ui/polymorphization/lifetimes.rs | 25 + tests/ui/polymorphization/lifetimes.stderr | 17 + tests/ui/polymorphization/normalized_sig_types.rs | 26 + tests/ui/polymorphization/predicates.rs | 95 + tests/ui/polymorphization/predicates.stderr | 51 + tests/ui/polymorphization/promoted-function-1.rs | 12 + .../ui/polymorphization/promoted-function-1.stderr | 8 + tests/ui/polymorphization/promoted-function-2.rs | 16 + .../ui/polymorphization/promoted-function-2.stderr | 17 + tests/ui/polymorphization/promoted-function-3.rs | 14 + tests/ui/polymorphization/promoted-function.rs | 15 + tests/ui/polymorphization/symbol-ambiguity.rs | 22 + .../ui/polymorphization/too-many-generic-params.rs | 85 + .../polymorphization/type_parameters/closures.rs | 161 + .../type_parameters/closures.stderr | 80 + .../polymorphization/type_parameters/functions.rs | 96 + .../type_parameters/functions.stderr | 35 + tests/ui/polymorphization/unsized_cast.rs | 30 + tests/ui/polymorphization/unsized_cast.stderr | 38 + tests/ui/pptypedef.rs | 11 + tests/ui/pptypedef.stderr | 29 + tests/ui/primitive-binop-lhs-mut.rs | 6 + tests/ui/print-fuel/print-fuel.rs | 13 + tests/ui/print-fuel/print-fuel.stderr | 1 + tests/ui/print-stdout-eprint-stderr.rs | 32 + tests/ui/print_type_sizes/anonymous.rs | 23 + tests/ui/print_type_sizes/async.rs | 11 + tests/ui/print_type_sizes/async.stdout | 34 + tests/ui/print_type_sizes/generator.rs | 18 + tests/ui/print_type_sizes/generator.stdout | 10 + .../print_type_sizes/generator_discr_placement.rs | 23 + .../generator_discr_placement.stdout | 11 + tests/ui/print_type_sizes/generics.rs | 51 + tests/ui/print_type_sizes/generics.stdout | 14 + tests/ui/print_type_sizes/multiple_types.rs | 13 + tests/ui/print_type_sizes/multiple_types.stdout | 10 + tests/ui/print_type_sizes/niche-filling.rs | 97 + tests/ui/print_type_sizes/niche-filling.stdout | 112 + tests/ui/print_type_sizes/no_duplicates.rs | 19 + tests/ui/print_type_sizes/no_duplicates.stdout | 2 + tests/ui/print_type_sizes/packed.rs | 59 + tests/ui/print_type_sizes/packed.stdout | 31 + tests/ui/print_type_sizes/padding.rs | 28 + tests/ui/print_type_sizes/padding.stdout | 23 + tests/ui/print_type_sizes/repr-align.rs | 32 + tests/ui/print_type_sizes/repr-align.stdout | 16 + tests/ui/print_type_sizes/repr_int_c.rs | 19 + tests/ui/print_type_sizes/repr_int_c.stdout | 12 + tests/ui/print_type_sizes/uninhabited.rs | 13 + tests/ui/print_type_sizes/uninhabited.stdout | 6 + tests/ui/print_type_sizes/variants.rs | 18 + tests/ui/print_type_sizes/variants.stdout | 10 + tests/ui/print_type_sizes/zero-sized-fields.rs | 43 + tests/ui/print_type_sizes/zero-sized-fields.stdout | 16 + .../ui/privacy/associated-item-privacy-inherent.rs | 112 + .../associated-item-privacy-inherent.stderr | 233 + tests/ui/privacy/associated-item-privacy-trait.rs | 134 + .../privacy/associated-item-privacy-trait.stderr | 332 + .../associated-item-privacy-type-binding.rs | 64 + .../associated-item-privacy-type-binding.stderr | 178 + tests/ui/privacy/auxiliary/cci_class.rs | 14 + tests/ui/privacy/auxiliary/cci_class_5.rs | 17 + tests/ui/privacy/auxiliary/ctor_aux.rs | 25 + tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs | 13 + .../privacy/auxiliary/issue-17718-const-privacy.rs | 8 + tests/ui/privacy/auxiliary/issue-57264-1.rs | 9 + tests/ui/privacy/auxiliary/issue-57264-2.rs | 10 + tests/ui/privacy/auxiliary/issue-75907.rs | 17 + tests/ui/privacy/auxiliary/issue-92755.rs | 17 + tests/ui/privacy/auxiliary/priv-impl-prim-ty.rs | 9 + tests/ui/privacy/auxiliary/privacy_reexport.rs | 6 + tests/ui/privacy/auxiliary/privacy_tuple_struct.rs | 4 + .../ui/privacy/auxiliary/private-inferred-type.rs | 36 + tests/ui/privacy/auxiliary/pub_use_mods_xcrate.rs | 10 + tests/ui/privacy/auxiliary/pub_use_xcrate1.rs | 3 + tests/ui/privacy/auxiliary/pub_use_xcrate2.rs | 3 + .../auxiliary/reachable-unnameable-items.rs | 106 + tests/ui/privacy/crate-private-reexport.rs | 66 + tests/ui/privacy/crate-private-reexport.stderr | 220 + tests/ui/privacy/ctor.rs | 16 + tests/ui/privacy/decl-macro.rs | 9 + tests/ui/privacy/decl-macro.stderr | 15 + tests/ui/privacy/effective_visibilities.rs | 76 + tests/ui/privacy/effective_visibilities.stderr | 140 + tests/ui/privacy/effective_visibilities_glob.rs | 21 + .../ui/privacy/effective_visibilities_glob.stderr | 26 + .../privacy/effective_visibilities_invariants.rs | 12 + .../effective_visibilities_invariants.stderr | 32 + tests/ui/privacy/export-tag-variant.rs | 7 + tests/ui/privacy/export-tag-variant.stderr | 15 + tests/ui/privacy/impl-privacy-xc-2.rs | 10 + tests/ui/privacy/issue-13641.rs | 13 + tests/ui/privacy/issue-13641.stderr | 27 + tests/ui/privacy/issue-17718-const-privacy.rs | 16 + tests/ui/privacy/issue-17718-const-privacy.stderr | 27 + tests/ui/privacy/issue-29161.rs | 15 + tests/ui/privacy/issue-29161.stderr | 22 + tests/ui/privacy/issue-30079.rs | 39 + tests/ui/privacy/issue-30079.stderr | 31 + .../issue-46209-private-enum-variant-reexport.rs | 40 + ...ssue-46209-private-enum-variant-reexport.stderr | 51 + tests/ui/privacy/issue-57264-1.rs | 8 + tests/ui/privacy/issue-57264-2.rs | 10 + .../privacy/issue-75062-fieldless-tuple-struct.rs | 10 + .../issue-75062-fieldless-tuple-struct.stderr | 15 + tests/ui/privacy/issue-75906.rs | 13 + tests/ui/privacy/issue-75906.stderr | 19 + tests/ui/privacy/issue-75907.rs | 18 + tests/ui/privacy/issue-75907.stderr | 37 + tests/ui/privacy/issue-75907_b.rs | 14 + tests/ui/privacy/issue-75907_b.stderr | 31 + tests/ui/privacy/issue-79593.rs | 29 + tests/ui/privacy/issue-79593.stderr | 35 + tests/ui/privacy/issue-92755.rs | 10 + tests/ui/privacy/legacy-ctor-visibility.rs | 15 + tests/ui/privacy/legacy-ctor-visibility.stderr | 9 + tests/ui/privacy/macro-private-reexport.rs | 17 + tests/ui/privacy/macro-private-reexport.stderr | 29 + tests/ui/privacy/priv-impl-prim-ty.rs | 11 + tests/ui/privacy/priv-in-bad-locations.rs | 17 + tests/ui/privacy/priv-in-bad-locations.stderr | 31 + tests/ui/privacy/privacy-in-paths.rs | 30 + tests/ui/privacy/privacy-in-paths.stderr | 39 + tests/ui/privacy/privacy-ns.rs | 114 + tests/ui/privacy/privacy-ns1.rs | 56 + tests/ui/privacy/privacy-ns1.stderr | 67 + tests/ui/privacy/privacy-ns2.rs | 79 + tests/ui/privacy/privacy-ns2.stderr | 102 + tests/ui/privacy/privacy-reexport.rs | 13 + tests/ui/privacy/privacy-sanity.rs | 82 + tests/ui/privacy/privacy-sanity.stderr | 123 + tests/ui/privacy/privacy-ufcs.rs | 13 + tests/ui/privacy/privacy-ufcs.stderr | 15 + tests/ui/privacy/privacy1-rpass.rs | 23 + tests/ui/privacy/privacy1.rs | 176 + tests/ui/privacy/privacy1.stderr | 205 + tests/ui/privacy/privacy2.rs | 27 + tests/ui/privacy/privacy2.stderr | 35 + tests/ui/privacy/privacy3.rs | 27 + tests/ui/privacy/privacy3.stderr | 17 + tests/ui/privacy/privacy4.rs | 25 + tests/ui/privacy/privacy4.stderr | 15 + tests/ui/privacy/privacy5.rs | 128 + tests/ui/privacy/privacy5.stderr | 867 ++ tests/ui/privacy/private-class-field.rs | 26 + tests/ui/privacy/private-field-ty-err.rs | 20 + tests/ui/privacy/private-field-ty-err.stderr | 9 + tests/ui/privacy/private-impl-method.rs | 21 + tests/ui/privacy/private-impl-method.stderr | 12 + tests/ui/privacy/private-in-public-assoc-ty.rs | 52 + tests/ui/privacy/private-in-public-assoc-ty.stderr | 68 + tests/ui/privacy/private-in-public-expr-pat.rs | 13 + tests/ui/privacy/private-in-public-ill-formed.rs | 37 + .../ui/privacy/private-in-public-ill-formed.stderr | 19 + tests/ui/privacy/private-in-public-lint.rs | 19 + tests/ui/privacy/private-in-public-lint.stderr | 21 + .../privacy/private-in-public-non-principal-2.rs | 14 + .../private-in-public-non-principal-2.stderr | 8 + .../ui/privacy/private-in-public-non-principal.rs | 21 + .../privacy/private-in-public-non-principal.stderr | 24 + .../private-in-public-type-alias-impl-trait.rs | 27 + tests/ui/privacy/private-in-public-warn.rs | 280 + tests/ui/privacy/private-in-public-warn.stderr | 339 + tests/ui/privacy/private-in-public.rs | 148 + tests/ui/privacy/private-in-public.stderr | 292 + tests/ui/privacy/private-inferred-type-1.rs | 18 + tests/ui/privacy/private-inferred-type-1.stderr | 14 + tests/ui/privacy/private-inferred-type-2.rs | 19 + tests/ui/privacy/private-inferred-type-2.stderr | 20 + tests/ui/privacy/private-inferred-type-3.rs | 17 + tests/ui/privacy/private-inferred-type-3.stderr | 58 + tests/ui/privacy/private-inferred-type.rs | 133 + tests/ui/privacy/private-inferred-type.stderr | 237 + tests/ui/privacy/private-item-simple.rs | 7 + tests/ui/privacy/private-item-simple.stderr | 15 + tests/ui/privacy/private-method-cross-crate.rs | 8 + tests/ui/privacy/private-method-cross-crate.stderr | 14 + tests/ui/privacy/private-method-inherited.rs | 14 + tests/ui/privacy/private-method-inherited.stderr | 12 + tests/ui/privacy/private-method-rpass.rs | 34 + tests/ui/privacy/private-method.rs | 23 + tests/ui/privacy/private-method.stderr | 12 + .../ui/privacy/private-struct-field-cross-crate.rs | 9 + .../private-struct-field-cross-crate.stderr | 9 + tests/ui/privacy/private-struct-field-ctor.rs | 9 + tests/ui/privacy/private-struct-field-ctor.stderr | 9 + tests/ui/privacy/private-struct-field-pattern.rs | 17 + .../ui/privacy/private-struct-field-pattern.stderr | 9 + tests/ui/privacy/private-struct-field.rs | 14 + tests/ui/privacy/private-struct-field.stderr | 9 + tests/ui/privacy/private-type-in-interface.rs | 30 + tests/ui/privacy/private-type-in-interface.stderr | 56 + tests/ui/privacy/private-variant-reexport.rs | 20 + tests/ui/privacy/private-variant-reexport.stderr | 48 + tests/ui/privacy/pub-extern-privacy.rs | 18 + .../ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs | 2 + tests/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs | 1 + tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 44 + tests/ui/privacy/pub-priv-dep/pub-priv1.stderr | 26 + tests/ui/privacy/pub-priv-dep/std-pub.rs | 12 + tests/ui/privacy/pub-use-xcrate.rs | 15 + tests/ui/privacy/pub_use_mods_xcrate_exe.rs | 11 + tests/ui/privacy/reachable-unnameable-items.rs | 31 + .../privacy/restricted/auxiliary/pub_restricted.rs | 14 + .../privacy/restricted/lookup-ignores-private.rs | 34 + tests/ui/privacy/restricted/private-in-public.rs | 11 + .../ui/privacy/restricted/private-in-public.stderr | 21 + tests/ui/privacy/restricted/relative-2018.rs | 13 + tests/ui/privacy/restricted/relative-2018.stderr | 17 + .../ui/privacy/restricted/struct-literal-field.rs | 19 + .../privacy/restricted/struct-literal-field.stderr | 9 + tests/ui/privacy/restricted/test.rs | 52 + tests/ui/privacy/restricted/test.stderr | 112 + tests/ui/privacy/suggest-making-field-public.fixed | 15 + tests/ui/privacy/suggest-making-field-public.rs | 15 + .../ui/privacy/suggest-making-field-public.stderr | 39 + tests/ui/privacy/union-field-privacy-1.rs | 17 + tests/ui/privacy/union-field-privacy-1.stderr | 15 + tests/ui/privacy/union-field-privacy-2.rs | 15 + tests/ui/privacy/union-field-privacy-2.stderr | 9 + tests/ui/privacy/useless-pub.rs | 16 + tests/ui/privacy/useless-pub.stderr | 21 + tests/ui/privacy/where-priv-type.rs | 90 + tests/ui/privacy/where-priv-type.stderr | 66 + .../ui/privacy/where-pub-type-impls-priv-trait.rs | 56 + .../privacy/where-pub-type-impls-priv-trait.stderr | 54 + tests/ui/proc-macro/add-impl.rs | 14 + tests/ui/proc-macro/allowed-attr-stmt-expr.rs | 78 + tests/ui/proc-macro/allowed-attr-stmt-expr.stdout | 321 + .../ui/proc-macro/ambiguous-builtin-attrs-test.rs | 20 + .../proc-macro/ambiguous-builtin-attrs-test.stderr | 9 + tests/ui/proc-macro/ambiguous-builtin-attrs.rs | 39 + tests/ui/proc-macro/ambiguous-builtin-attrs.stderr | 115 + tests/ui/proc-macro/amputate-span.fixed | 69 + tests/ui/proc-macro/amputate-span.rs | 65 + tests/ui/proc-macro/amputate-span.stderr | 25 + tests/ui/proc-macro/append-impl.rs | 22 + tests/ui/proc-macro/attr-args.rs | 13 + tests/ui/proc-macro/attr-cfg.rs | 27 + tests/ui/proc-macro/attr-complex-fn.rs | 26 + tests/ui/proc-macro/attr-complex-fn.stdout | 171 + tests/ui/proc-macro/attr-invalid-exprs.rs | 28 + tests/ui/proc-macro/attr-invalid-exprs.stderr | 32 + tests/ui/proc-macro/attr-on-trait.rs | 19 + tests/ui/proc-macro/attr-stmt-expr-rpass.rs | 36 + tests/ui/proc-macro/attr-stmt-expr.rs | 66 + tests/ui/proc-macro/attr-stmt-expr.stderr | 21 + tests/ui/proc-macro/attr-stmt-expr.stdout | 274 + tests/ui/proc-macro/attribute-after-derive.rs | 28 + tests/ui/proc-macro/attribute-after-derive.stdout | 192 + tests/ui/proc-macro/attribute-spans-preserved.rs | 10 + .../ui/proc-macro/attribute-spans-preserved.stderr | 19 + .../ui/proc-macro/attribute-spans-preserved.stdout | 1 + tests/ui/proc-macro/attribute-with-error.rs | 42 + tests/ui/proc-macro/attribute-with-error.stderr | 35 + tests/ui/proc-macro/attribute.rs | 73 + tests/ui/proc-macro/attribute.stderr | 104 + tests/ui/proc-macro/attributes-included.rs | 22 + tests/ui/proc-macro/attributes-included.stderr | 15 + tests/ui/proc-macro/attributes-on-definitions.rs | 12 + .../ui/proc-macro/attributes-on-definitions.stderr | 10 + tests/ui/proc-macro/attributes-on-modules-fail.rs | 46 + .../proc-macro/attributes-on-modules-fail.stderr | 70 + tests/ui/proc-macro/attributes-on-modules.rs | 19 + tests/ui/proc-macro/auxiliary/add-impl.rs | 21 + tests/ui/proc-macro/auxiliary/amputate-span.rs | 14 + tests/ui/proc-macro/auxiliary/api/cmp.rs | 21 + tests/ui/proc-macro/auxiliary/api/mod.rs | 24 + tests/ui/proc-macro/auxiliary/api/parse.rs | 55 + tests/ui/proc-macro/auxiliary/append-impl.rs | 16 + tests/ui/proc-macro/auxiliary/assert-span-pos.rs | 37 + tests/ui/proc-macro/auxiliary/attr-args.rs | 28 + tests/ui/proc-macro/auxiliary/attr-cfg.rs | 21 + tests/ui/proc-macro/auxiliary/attr-on-trait.rs | 15 + .../proc-macro/auxiliary/attr-stmt-expr-rpass.rs | 51 + tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs | 49 + .../auxiliary/attribute-spans-preserved.rs | 35 + .../ui/proc-macro/auxiliary/attributes-included.rs | 150 + .../auxiliary/attributes-on-definitions.rs | 23 + tests/ui/proc-macro/auxiliary/bang-macro.rs | 17 + tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs | 13 + tests/ui/proc-macro/auxiliary/builtin-attrs.rs | 27 + tests/ui/proc-macro/auxiliary/call-deprecated.rs | 19 + tests/ui/proc-macro/auxiliary/call-site.rs | 27 + tests/ui/proc-macro/auxiliary/cond_plugin.rs | 38 + .../ui/proc-macro/auxiliary/count_compound_ops.rs | 32 + .../auxiliary/custom-attr-only-one-derive.rs | 18 + tests/ui/proc-macro/auxiliary/custom-quote.rs | 32 + tests/ui/proc-macro/auxiliary/derive-a.rs | 15 + tests/ui/proc-macro/auxiliary/derive-atob.rs | 15 + tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs | 14 + tests/ui/proc-macro/auxiliary/derive-b-rpass.rs | 17 + tests/ui/proc-macro/auxiliary/derive-b.rs | 13 + tests/ui/proc-macro/auxiliary/derive-bad.rs | 13 + tests/ui/proc-macro/auxiliary/derive-clona.rs | 13 + tests/ui/proc-macro/auxiliary/derive-ctod.rs | 15 + tests/ui/proc-macro/auxiliary/derive-foo.rs | 13 + .../auxiliary/derive-helper-shadowed-2.rs | 2 + .../auxiliary/derive-helper-shadowing-2.rs | 12 + .../auxiliary/derive-helper-shadowing.rs | 15 + tests/ui/proc-macro/auxiliary/derive-nothing.rs | 13 + .../ui/proc-macro/auxiliary/derive-same-struct.rs | 21 + tests/ui/proc-macro/auxiliary/derive-two-attrs.rs | 13 + tests/ui/proc-macro/auxiliary/derive-union.rs | 18 + tests/ui/proc-macro/auxiliary/derive-unstable-2.rs | 17 + tests/ui/proc-macro/auxiliary/derive-unstable.rs | 14 + .../proc-macro/auxiliary/dollar-crate-external.rs | 22 + tests/ui/proc-macro/auxiliary/double.rs | 16 + tests/ui/proc-macro/auxiliary/duplicate.rs | 32 + .../proc-macro/auxiliary/edition-imports-2015.rs | 20 + tests/ui/proc-macro/auxiliary/empty-crate.rs | 5 + tests/ui/proc-macro/auxiliary/expand-expr.rs | 166 + .../ui/proc-macro/auxiliary/expand-with-a-macro.rs | 22 + .../ui/proc-macro/auxiliary/external-crate-var.rs | 40 + tests/ui/proc-macro/auxiliary/first-second.rs | 20 + .../ui/proc-macro/auxiliary/gen-lifetime-token.rs | 25 + .../auxiliary/gen-macro-rules-hygiene.rs | 23 + tests/ui/proc-macro/auxiliary/gen-macro-rules.rs | 12 + .../proc-macro/auxiliary/generate-dollar-ident.rs | 16 + tests/ui/proc-macro/auxiliary/generate-mod.rs | 58 + tests/ui/proc-macro/auxiliary/hygiene_example.rs | 7 + .../auxiliary/hygiene_example_codegen.rs | 27 + tests/ui/proc-macro/auxiliary/included-file.txt | 1 + .../ui/proc-macro/auxiliary/invalid-punct-ident.rs | 28 + tests/ui/proc-macro/auxiliary/is-available.rs | 13 + tests/ui/proc-macro/auxiliary/issue-104884.rs | 23 + tests/ui/proc-macro/auxiliary/issue-38586.rs | 11 + tests/ui/proc-macro/auxiliary/issue-39889.rs | 17 + tests/ui/proc-macro/auxiliary/issue-42708.rs | 18 + tests/ui/proc-macro/auxiliary/issue-50061.rs | 12 + tests/ui/proc-macro/auxiliary/issue-50493.rs | 21 + tests/ui/proc-macro/auxiliary/issue-59191.rs | 16 + tests/ui/proc-macro/auxiliary/issue-66286.rs | 14 + tests/ui/proc-macro/auxiliary/issue-75801.rs | 13 + tests/ui/proc-macro/auxiliary/issue-79242.rs | 16 + tests/ui/proc-macro/auxiliary/issue-79825.rs | 14 + tests/ui/proc-macro/auxiliary/issue-83510.rs | 19 + tests/ui/proc-macro/auxiliary/issue-91800-macro.rs | 26 + tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs | 26 + tests/ui/proc-macro/auxiliary/lifetimes.rs | 20 + tests/ui/proc-macro/auxiliary/macro-only-syntax.rs | 89 + tests/ui/proc-macro/auxiliary/make-macro.rs | 18 + tests/ui/proc-macro/auxiliary/meta-delim.rs | 12 + tests/ui/proc-macro/auxiliary/meta-macro.rs | 15 + tests/ui/proc-macro/auxiliary/mixed-site-span.rs | 40 + tests/ui/proc-macro/auxiliary/modify-ast.rs | 47 + tests/ui/proc-macro/auxiliary/multiple-derives.rs | 22 + tests/ui/proc-macro/auxiliary/multispan.rs | 37 + tests/ui/proc-macro/auxiliary/negative-token.rs | 18 + .../ui/proc-macro/auxiliary/nested-macro-rules.rs | 16 + .../auxiliary/nonterminal-recollect-attr.rs | 25 + tests/ui/proc-macro/auxiliary/not-joint.rs | 30 + .../ui/proc-macro/auxiliary/parent-source-spans.rs | 43 + tests/ui/proc-macro/auxiliary/proc-macro-panic.rs | 13 + tests/ui/proc-macro/auxiliary/raw-ident.rs | 35 + tests/ui/proc-macro/auxiliary/re-export.rs | 19 + tests/ui/proc-macro/auxiliary/recollect.rs | 12 + .../ui/proc-macro/auxiliary/resolved-located-at.rs | 31 + tests/ui/proc-macro/auxiliary/span-api-tests.rs | 45 + .../proc-macro/auxiliary/span-from-proc-macro.rs | 49 + tests/ui/proc-macro/auxiliary/span-test-macros.rs | 9 + tests/ui/proc-macro/auxiliary/subspan.rs | 38 + tests/ui/proc-macro/auxiliary/test-macros.rs | 180 + tests/ui/proc-macro/auxiliary/three-equals.rs | 49 + tests/ui/proc-macro/auxiliary/weird-hygiene.rs | 48 + tests/ui/proc-macro/bang-macro.rs | 9 + tests/ui/proc-macro/break-token-spans.rs | 16 + tests/ui/proc-macro/break-token-spans.stderr | 21 + tests/ui/proc-macro/call-deprecated.rs | 34 + tests/ui/proc-macro/call-deprecated.stderr | 16 + tests/ui/proc-macro/call-site.rs | 10 + tests/ui/proc-macro/capture-macro-rules-invoke.rs | 57 + .../proc-macro/capture-macro-rules-invoke.stdout | 324 + tests/ui/proc-macro/capture-unglued-token.rs | 20 + tests/ui/proc-macro/capture-unglued-token.stdout | 28 + tests/ui/proc-macro/cfg-eval-fail.rs | 7 + tests/ui/proc-macro/cfg-eval-fail.stderr | 8 + tests/ui/proc-macro/cfg-eval-inner.rs | 39 + tests/ui/proc-macro/cfg-eval-inner.stdout | 247 + tests/ui/proc-macro/cfg-eval.rs | 37 + tests/ui/proc-macro/cfg-eval.stdout | 150 + tests/ui/proc-macro/count_compound_ops.rs | 9 + tests/ui/proc-macro/crate-attrs-multiple.rs | 14 + tests/ui/proc-macro/crate-var.rs | 61 + tests/ui/proc-macro/crt-static.rs | 24 + tests/ui/proc-macro/custom-attr-only-one-derive.rs | 16 + .../proc-macro/debug/auxiliary/macro-dump-debug.rs | 15 + tests/ui/proc-macro/debug/dump-debug-span-debug.rs | 46 + .../proc-macro/debug/dump-debug-span-debug.stderr | 231 + tests/ui/proc-macro/debug/dump-debug.rs | 40 + tests/ui/proc-macro/debug/dump-debug.stderr | 166 + tests/ui/proc-macro/define-two.rs | 18 + tests/ui/proc-macro/define-two.stderr | 14 + tests/ui/proc-macro/derive-attr-cfg.rs | 17 + tests/ui/proc-macro/derive-b.rs | 19 + tests/ui/proc-macro/derive-bad.rs | 11 + tests/ui/proc-macro/derive-bad.stderr | 31 + tests/ui/proc-macro/derive-expand-order.rs | 14 + tests/ui/proc-macro/derive-expand-order.stdout | 5 + tests/ui/proc-macro/derive-helper-configured.rs | 18 + tests/ui/proc-macro/derive-helper-legacy-limits.rs | 21 + .../proc-macro/derive-helper-legacy-limits.stderr | 8 + .../ui/proc-macro/derive-helper-legacy-spurious.rs | 12 + .../derive-helper-legacy-spurious.stderr | 22 + tests/ui/proc-macro/derive-helper-shadowed.rs | 16 + tests/ui/proc-macro/derive-helper-shadowing-2.rs | 16 + tests/ui/proc-macro/derive-helper-shadowing.rs | 56 + tests/ui/proc-macro/derive-helper-shadowing.stderr | 89 + tests/ui/proc-macro/derive-helper-vs-legacy.rs | 12 + tests/ui/proc-macro/derive-in-mod.rs | 13 + tests/ui/proc-macro/derive-multiple-with-packed.rs | 11 + tests/ui/proc-macro/derive-same-struct.rs | 15 + tests/ui/proc-macro/derive-same-struct.stdout | 1 + tests/ui/proc-macro/derive-still-gated.rs | 9 + tests/ui/proc-macro/derive-still-gated.stderr | 8 + tests/ui/proc-macro/derive-test.rs | 22 + tests/ui/proc-macro/derive-two-attrs.rs | 15 + tests/ui/proc-macro/derive-union.rs | 17 + tests/ui/proc-macro/disappearing-resolution.rs | 22 + tests/ui/proc-macro/disappearing-resolution.stderr | 26 + tests/ui/proc-macro/doc-comment-preserved.rs | 24 + tests/ui/proc-macro/doc-comment-preserved.stdout | 54 + tests/ui/proc-macro/dollar-crate-issue-101211.rs | 29 + tests/ui/proc-macro/dollar-crate-issue-57089.rs | 27 + .../ui/proc-macro/dollar-crate-issue-57089.stdout | 80 + tests/ui/proc-macro/dollar-crate-issue-62325.rs | 26 + .../ui/proc-macro/dollar-crate-issue-62325.stdout | 110 + tests/ui/proc-macro/dollar-crate.rs | 40 + tests/ui/proc-macro/dollar-crate.stdout | 240 + tests/ui/proc-macro/edition-imports-2018.rs | 24 + tests/ui/proc-macro/empty-crate.rs | 9 + tests/ui/proc-macro/empty-where-clause.rs | 18 + tests/ui/proc-macro/empty-where-clause.stderr | 21 + tests/ui/proc-macro/expand-expr.rs | 134 + tests/ui/proc-macro/expand-expr.stderr | 59 + tests/ui/proc-macro/expand-to-derive.rs | 34 + tests/ui/proc-macro/expand-to-derive.stdout | 104 + tests/ui/proc-macro/expand-to-unstable.rs | 14 + tests/ui/proc-macro/expand-to-unstable.stderr | 12 + tests/ui/proc-macro/expand-with-a-macro.rs | 20 + tests/ui/proc-macro/export-macro.rs | 11 + tests/ui/proc-macro/export-macro.stderr | 8 + tests/ui/proc-macro/exports.rs | 15 + tests/ui/proc-macro/exports.stderr | 26 + .../ui/proc-macro/expr-stmt-nonterminal-tokens.rs | 37 + .../proc-macro/expr-stmt-nonterminal-tokens.stdout | 540 + .../extern-prelude-extern-crate-proc-macro.rs | 7 + tests/ui/proc-macro/gen-lifetime-token.rs | 11 + tests/ui/proc-macro/gen-macro-rules-hygiene.rs | 23 + tests/ui/proc-macro/gen-macro-rules-hygiene.stderr | 32 + tests/ui/proc-macro/gen-macro-rules.rs | 13 + tests/ui/proc-macro/generate-dollar-ident.rs | 18 + tests/ui/proc-macro/generate-mod.rs | 33 + tests/ui/proc-macro/generate-mod.stderr | 164 + .../helper-attr-blocked-by-import-ambig.rs | 13 + .../helper-attr-blocked-by-import-ambig.stderr | 35 + .../ui/proc-macro/helper-attr-blocked-by-import.rs | 28 + tests/ui/proc-macro/hygiene_example.rs | 16 + .../ui/proc-macro/illegal-proc-macro-derive-use.rs | 15 + .../illegal-proc-macro-derive-use.stderr | 14 + tests/ui/proc-macro/import.rs | 8 + tests/ui/proc-macro/import.stderr | 9 + tests/ui/proc-macro/inert-attribute-order.rs | 23 + tests/ui/proc-macro/inert-attribute-order.stdout | 7 + tests/ui/proc-macro/inner-attr-non-inline-mod.rs | 18 + .../ui/proc-macro/inner-attr-non-inline-mod.stderr | 40 + .../ui/proc-macro/inner-attr-non-inline-mod.stdout | 76 + tests/ui/proc-macro/inner-attrs.rs | 87 + tests/ui/proc-macro/inner-attrs.stderr | 26 + tests/ui/proc-macro/inner-attrs.stdout | 956 ++ tests/ui/proc-macro/input-interpolated.rs | 29 + tests/ui/proc-macro/input-interpolated.stdout | 59 + tests/ui/proc-macro/invalid-attributes.rs | 26 + tests/ui/proc-macro/invalid-attributes.stderr | 38 + tests/ui/proc-macro/invalid-punct-ident-1.rs | 9 + tests/ui/proc-macro/invalid-punct-ident-1.stderr | 10 + tests/ui/proc-macro/invalid-punct-ident-2.rs | 9 + tests/ui/proc-macro/invalid-punct-ident-2.stderr | 10 + tests/ui/proc-macro/invalid-punct-ident-3.rs | 9 + tests/ui/proc-macro/invalid-punct-ident-3.stderr | 10 + tests/ui/proc-macro/invalid-punct-ident-4.rs | 13 + tests/ui/proc-macro/invalid-punct-ident-4.stderr | 25 + tests/ui/proc-macro/is-available.rs | 15 + .../proc-macro/issue-104884-trait-impl-sugg-err.rs | 20 + .../issue-104884-trait-impl-sugg-err.stderr | 39 + tests/ui/proc-macro/issue-36935.rs | 14 + tests/ui/proc-macro/issue-36935.stderr | 22 + tests/ui/proc-macro/issue-37788.rs | 9 + tests/ui/proc-macro/issue-37788.stderr | 17 + tests/ui/proc-macro/issue-38586.rs | 9 + tests/ui/proc-macro/issue-38586.stderr | 11 + tests/ui/proc-macro/issue-39889.rs | 12 + tests/ui/proc-macro/issue-42708.rs | 26 + tests/ui/proc-macro/issue-50061.rs | 23 + tests/ui/proc-macro/issue-50493.rs | 13 + tests/ui/proc-macro/issue-50493.stderr | 9 + tests/ui/proc-macro/issue-53481.rs | 22 + .../proc-macro/issue-59191-replace-root-with-fn.rs | 10 + .../issue-59191-replace-root-with-fn.stderr | 4 + tests/ui/proc-macro/issue-66286.rs | 13 + tests/ui/proc-macro/issue-66286.stderr | 14 + .../issue-73933-procedural-masquerade.rs | 12 + .../issue-73933-procedural-masquerade.stdout | 21 + tests/ui/proc-macro/issue-75734-pp-paren.rs | 26 + tests/ui/proc-macro/issue-75734-pp-paren.stdout | 134 + tests/ui/proc-macro/issue-75801.rs | 19 + tests/ui/proc-macro/issue-75801.stderr | 12 + tests/ui/proc-macro/issue-75930-derive-cfg.rs | 74 + tests/ui/proc-macro/issue-75930-derive-cfg.stderr | 27 + tests/ui/proc-macro/issue-75930-derive-cfg.stdout | 1904 ++++ .../ui/proc-macro/issue-76182-leading-vert-pat.rs | 16 + .../proc-macro/issue-76182-leading-vert-pat.stdout | 62 + .../issue-76270-panic-in-libproc-macro.rs | 13 + .../issue-76270-panic-in-libproc-macro.stderr | 10 + .../proc-macro/issue-78675-captured-inner-attrs.rs | 32 + .../issue-78675-captured-inner-attrs.stdout | 87 + tests/ui/proc-macro/issue-79148.rs | 10 + tests/ui/proc-macro/issue-79148.stderr | 16 + .../issue-79242-slow-retokenize-check.rs | 34 + tests/ui/proc-macro/issue-79825.rs | 10 + tests/ui/proc-macro/issue-80760-empty-stmt.rs | 26 + tests/ui/proc-macro/issue-80760-empty-stmt.stdout | 14 + tests/ui/proc-macro/issue-81007-item-attrs.rs | 31 + tests/ui/proc-macro/issue-81007-item-attrs.stdout | 99 + tests/ui/proc-macro/issue-81543-item-parse-err.rs | 14 + .../proc-macro/issue-81543-item-parse-err.stderr | 8 + tests/ui/proc-macro/issue-81555.rs | 15 + .../issue-83469-global-alloc-invalid-stmt.rs | 10 + .../issue-83469-global-alloc-invalid-stmt.stderr | 8 + tests/ui/proc-macro/issue-83510.rs | 11 + tests/ui/proc-macro/issue-83510.stderr | 38 + .../ui/proc-macro/issue-86781-bad-inner-doc.fixed | 12 + tests/ui/proc-macro/issue-86781-bad-inner-doc.rs | 12 + .../ui/proc-macro/issue-86781-bad-inner-doc.stderr | 17 + tests/ui/proc-macro/issue-91800.rs | 16 + tests/ui/proc-macro/issue-91800.stderr | 56 + tests/ui/proc-macro/item-error.rs | 15 + tests/ui/proc-macro/item-error.stderr | 15 + tests/ui/proc-macro/keep-expr-tokens.rs | 24 + tests/ui/proc-macro/keep-expr-tokens.stderr | 15 + tests/ui/proc-macro/keep-expr-tokens.stdout | 46 + tests/ui/proc-macro/lifetimes-rpass.rs | 26 + tests/ui/proc-macro/lifetimes.rs | 9 + tests/ui/proc-macro/lifetimes.stderr | 13 + tests/ui/proc-macro/lints_in_proc_macros.rs | 14 + tests/ui/proc-macro/lints_in_proc_macros.stderr | 11 + tests/ui/proc-macro/load-panic-backtrace.rs | 15 + tests/ui/proc-macro/load-panic-backtrace.stderr | 11 + tests/ui/proc-macro/load-panic.rs | 11 + tests/ui/proc-macro/load-panic.stderr | 10 + tests/ui/proc-macro/load-two.rs | 23 + tests/ui/proc-macro/macro-brackets.rs | 14 + tests/ui/proc-macro/macro-brackets.stderr | 14 + tests/ui/proc-macro/macro-crate-multi-decorator.rs | 41 + tests/ui/proc-macro/macro-namespace-reserved-2.rs | 57 + .../proc-macro/macro-namespace-reserved-2.stderr | 132 + tests/ui/proc-macro/macro-namespace-reserved.rs | 38 + .../ui/proc-macro/macro-namespace-reserved.stderr | 47 + tests/ui/proc-macro/macro-quote-cond.rs | 46 + tests/ui/proc-macro/macro-rules-derive-cfg.rs | 31 + tests/ui/proc-macro/macro-rules-derive-cfg.stdout | 171 + tests/ui/proc-macro/macro-rules-derive.rs | 19 + tests/ui/proc-macro/macro-rules-derive.stderr | 14 + tests/ui/proc-macro/macro-use-attr.rs | 12 + tests/ui/proc-macro/macro-use-bang.rs | 9 + tests/ui/proc-macro/macros-in-extern-derive.rs | 6 + tests/ui/proc-macro/macros-in-extern-derive.stderr | 11 + tests/ui/proc-macro/macros-in-extern.rs | 24 + tests/ui/proc-macro/macros-in-type.rs | 11 + tests/ui/proc-macro/meta-delim.rs | 12 + tests/ui/proc-macro/meta-macro-hygiene.rs | 30 + tests/ui/proc-macro/meta-macro-hygiene.stdout | 69 + tests/ui/proc-macro/meta-macro.rs | 14 + tests/ui/proc-macro/meta-macro.stdout | 3 + tests/ui/proc-macro/mixed-site-span.rs | 24 + tests/ui/proc-macro/mixed-site-span.stderr | 34 + tests/ui/proc-macro/modify-ast.rs | 26 + tests/ui/proc-macro/module.rs | 1 + tests/ui/proc-macro/module_with_attrs.rs | 4 + tests/ui/proc-macro/multispan.rs | 25 + tests/ui/proc-macro/multispan.stderr | 93 + tests/ui/proc-macro/negative-token.rs | 11 + tests/ui/proc-macro/nested-derive-cfg.rs | 23 + tests/ui/proc-macro/nested-derive-cfg.stdout | 81 + tests/ui/proc-macro/nested-item-spans.rs | 23 + tests/ui/proc-macro/nested-item-spans.stderr | 19 + tests/ui/proc-macro/nested-macro-rules.rs | 23 + tests/ui/proc-macro/nested-macro-rules.stdout | 46 + tests/ui/proc-macro/nested-nonterminal-tokens.rs | 26 + .../ui/proc-macro/nested-nonterminal-tokens.stdout | 60 + tests/ui/proc-macro/no-macro-use-attr.rs | 10 + tests/ui/proc-macro/no-macro-use-attr.stderr | 20 + tests/ui/proc-macro/no-missing-docs.rs | 16 + tests/ui/proc-macro/nodelim-groups.rs | 22 + tests/ui/proc-macro/nodelim-groups.stdout | 167 + tests/ui/proc-macro/non-root.rs | 15 + tests/ui/proc-macro/non-root.stderr | 8 + tests/ui/proc-macro/nonterminal-expansion.rs | 37 + tests/ui/proc-macro/nonterminal-expansion.stdout | 42 + tests/ui/proc-macro/nonterminal-recollect-attr.rs | 21 + .../proc-macro/nonterminal-recollect-attr.stdout | 66 + tests/ui/proc-macro/nonterminal-token-hygiene.rs | 34 + .../ui/proc-macro/nonterminal-token-hygiene.stdout | 92 + tests/ui/proc-macro/not-joint.rs | 24 + tests/ui/proc-macro/out-of-line-mod.rs | 13 + tests/ui/proc-macro/outer/inner.rs | 1 + tests/ui/proc-macro/panic-abort.rs | 4 + tests/ui/proc-macro/panic-abort.stderr | 4 + tests/ui/proc-macro/parent-source-spans.rs | 53 + tests/ui/proc-macro/parent-source-spans.stderr | 183 + tests/ui/proc-macro/pretty-print-hack-hide.rs | 12 + tests/ui/proc-macro/pretty-print-hack-hide.stdout | 21 + .../proc-macro/pretty-print-hack-show.local.stderr | 179 + .../proc-macro/pretty-print-hack-show.local.stdout | 44 + .../pretty-print-hack-show.remapped.stderr | 179 + .../pretty-print-hack-show.remapped.stdout | 44 + tests/ui/proc-macro/pretty-print-hack-show.rs | 20 + .../allsorts-rental-0.5.6/src/lib.rs | 14 + .../pretty-print-hack/rental-0.5.5/src/lib.rs | 14 + .../pretty-print-hack/rental-0.5.6/src/lib.rs | 14 + tests/ui/proc-macro/pretty-print-tts.rs | 20 + tests/ui/proc-macro/pretty-print-tts.stdout | 102 + tests/ui/proc-macro/proc-macro-attributes.rs | 22 + tests/ui/proc-macro/proc-macro-attributes.stderr | 130 + tests/ui/proc-macro/proc-macro-deprecated-attr.rs | 16 + tests/ui/proc-macro/proc-macro-gates.rs | 53 + tests/ui/proc-macro/proc-macro-gates.stderr | 91 + tests/ui/proc-macro/proc-macro-gates2.rs | 24 + tests/ui/proc-macro/proc-macro-gates2.stderr | 14 + tests/ui/proc-macro/pub-at-crate-root.rs | 22 + tests/ui/proc-macro/pub-at-crate-root.stderr | 20 + tests/ui/proc-macro/quote-debug.rs | 18 + tests/ui/proc-macro/quote-debug.stdout | 48 + tests/ui/proc-macro/raw-ident.rs | 16 + tests/ui/proc-macro/raw-ident.stderr | 10 + tests/ui/proc-macro/reserved-macro-names.rs | 19 + tests/ui/proc-macro/reserved-macro-names.stderr | 14 + tests/ui/proc-macro/resolve-error.rs | 62 + tests/ui/proc-macro/resolve-error.stderr | 128 + tests/ui/proc-macro/resolved-located-at.rs | 10 + tests/ui/proc-macro/resolved-located-at.stderr | 21 + tests/ui/proc-macro/shadow.rs | 8 + tests/ui/proc-macro/shadow.stderr | 14 + tests/ui/proc-macro/signature.rs | 13 + tests/ui/proc-macro/signature.stderr | 20 + tests/ui/proc-macro/smoke.rs | 20 + tests/ui/proc-macro/span-absolute-posititions.rs | 24 + .../ui/proc-macro/span-absolute-posititions.stderr | 14 + tests/ui/proc-macro/span-api-tests.rs | 62 + tests/ui/proc-macro/span-from-proc-macro.rs | 17 + tests/ui/proc-macro/span-from-proc-macro.stderr | 62 + tests/ui/proc-macro/span-preservation.rs | 57 + tests/ui/proc-macro/span-preservation.stderr | 72 + tests/ui/proc-macro/struct-field-macro.rs | 18 + tests/ui/proc-macro/subspan.rs | 26 + tests/ui/proc-macro/subspan.stderr | 106 + tests/ui/proc-macro/test.rs | 12 + tests/ui/proc-macro/three-equals.rs | 25 + tests/ui/proc-macro/three-equals.stderr | 49 + tests/ui/proc-macro/trailing-plus.rs | 14 + tests/ui/proc-macro/trailing-plus.stdout | 57 + tests/ui/proc-macro/trait-fn-args-2015.rs | 16 + tests/ui/proc-macro/two-crate-types-1.rs | 7 + tests/ui/proc-macro/two-crate-types-1.stderr | 4 + tests/ui/proc-macro/two-crate-types-2.rs | 3 + tests/ui/proc-macro/two-crate-types-2.stderr | 4 + tests/ui/proc-macro/unsafe-foreign-mod.rs | 14 + tests/ui/proc-macro/unsafe-mod.rs | 13 + tests/ui/proc-macro/visibility-path.rs | 25 + tests/ui/proc-macro/visibility-path.stderr | 14 + tests/ui/proc-macro/weird-braces.rs | 23 + tests/ui/proc-macro/weird-braces.stdout | 524 + tests/ui/proc-macro/weird-hygiene.rs | 46 + tests/ui/proc-macro/weird-hygiene.stderr | 25 + .../process-termination-blocking-io.rs | 19 + .../process-termination-simple.rs | 13 + tests/ui/process/core-run-destroy.rs | 88 + tests/ui/process/fds-are-cloexec.rs | 82 + tests/ui/process/issue-13304.rs | 39 + tests/ui/process/issue-14456.rs | 37 + tests/ui/process/issue-14940.rs | 19 + tests/ui/process/issue-16272.rs | 23 + tests/ui/process/issue-20091.rs | 24 + tests/ui/process/multi-panic.rs | 38 + tests/ui/process/no-stdio.rs | 139 + tests/ui/process/nofile-limit.rs | 46 + tests/ui/process/process-envs.rs | 54 + tests/ui/process/process-exit.rs | 26 + tests/ui/process/process-panic-after-fork.rs | 197 + tests/ui/process/process-remove-from-env.rs | 48 + tests/ui/process/process-sigpipe.rs | 37 + tests/ui/process/process-spawn-nonexistent.rs | 17 + .../process/process-spawn-with-unicode-params.rs | 77 + tests/ui/process/process-status-inherits-stdin.rs | 35 + tests/ui/process/signal-exit-status.rs | 19 + tests/ui/process/sigpipe-should-be-ignored.rs | 33 + tests/ui/process/tls-exit-status.rs | 11 + tests/ui/process/try-wait.rs | 60 + tests/ui/project-cache-issue-31849.rs | 65 + tests/ui/ptr-coercion-rpass.rs | 30 + tests/ui/ptr-coercion.rs | 23 + tests/ui/ptr-coercion.stderr | 36 + tests/ui/ptr_ops/issue-80309-safe.rs | 16 + tests/ui/ptr_ops/issue-80309.rs | 13 + ...ue-33174-restricted-type-in-public-interface.rs | 28 + ...3174-restricted-type-in-public-interface.stderr | 30 + tests/ui/pub/pub-ident-fn-2.fixed | 10 + tests/ui/pub/pub-ident-fn-2.rs | 10 + tests/ui/pub/pub-ident-fn-2.stderr | 13 + tests/ui/pub/pub-ident-fn-3.rs | 8 + tests/ui/pub/pub-ident-fn-3.stderr | 8 + tests/ui/pub/pub-ident-fn-or-struct-2.rs | 4 + tests/ui/pub/pub-ident-fn-or-struct-2.stderr | 8 + tests/ui/pub/pub-ident-fn-or-struct.rs | 4 + tests/ui/pub/pub-ident-fn-or-struct.stderr | 8 + tests/ui/pub/pub-ident-fn-with-lifetime-2.rs | 6 + tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr | 13 + tests/ui/pub/pub-ident-fn-with-lifetime.fixed | 8 + tests/ui/pub/pub-ident-fn-with-lifetime.rs | 8 + tests/ui/pub/pub-ident-fn-with-lifetime.stderr | 13 + tests/ui/pub/pub-ident-fn.fixed | 8 + tests/ui/pub/pub-ident-fn.rs | 8 + tests/ui/pub/pub-ident-fn.stderr | 13 + tests/ui/pub/pub-ident-struct-with-lifetime.rs | 4 + tests/ui/pub/pub-ident-struct-with-lifetime.stderr | 13 + tests/ui/pub/pub-ident-struct.fixed | 6 + tests/ui/pub/pub-ident-struct.rs | 6 + tests/ui/pub/pub-ident-struct.stderr | 13 + tests/ui/pub/pub-ident-with-lifetime-incomplete.rs | 5 + .../pub/pub-ident-with-lifetime-incomplete.stderr | 8 + tests/ui/pub/pub-reexport-priv-extern-crate.rs | 20 + tests/ui/pub/pub-reexport-priv-extern-crate.stderr | 37 + tests/ui/pub/pub-restricted-error-fn.rs | 2 + tests/ui/pub/pub-restricted-error-fn.stderr | 16 + tests/ui/pub/pub-restricted-error.rs | 7 + tests/ui/pub/pub-restricted-error.stderr | 10 + tests/ui/pub/pub-restricted-non-path.rs | 5 + tests/ui/pub/pub-restricted-non-path.stderr | 8 + tests/ui/pub/pub-restricted.rs | 31 + tests/ui/pub/pub-restricted.stderr | 65 + tests/ui/qualified/qualified-path-params-2.rs | 21 + tests/ui/qualified/qualified-path-params-2.stderr | 14 + tests/ui/qualified/qualified-path-params.rs | 25 + tests/ui/qualified/qualified-path-params.stderr | 18 + tests/ui/query-system/fn-sig-cycle-arity.rs | 8 + tests/ui/query-system/fn-sig-cycle-arity.stderr | 9 + tests/ui/query-system/issue-83479.rs | 16 + tests/ui/query-system/issue-83479.stderr | 44 + tests/ui/query-system/query_depth.rs | 31 + tests/ui/query-system/query_depth.stderr | 11 + tests/ui/query-visibility.rs | 9 + tests/ui/range/exclusive-range-patterns-2021.rs | 14 + .../ui/range/exclusive-range-patterns-2021.stderr | 27 + tests/ui/range/issue-54505-no-literals.fixed | 75 + tests/ui/range/issue-54505-no-literals.rs | 75 + tests/ui/range/issue-54505-no-literals.stderr | 219 + tests/ui/range/issue-54505-no-std.rs | 58 + tests/ui/range/issue-54505-no-std.stderr | 123 + tests/ui/range/issue-54505.fixed | 43 + tests/ui/range/issue-54505.rs | 43 + tests/ui/range/issue-54505.stderr | 111 + .../range/issue-73553-misinterp-range-literal.rs | 16 + .../issue-73553-misinterp-range-literal.stderr | 39 + tests/ui/range/range-1.rs | 16 + tests/ui/range/range-1.stderr | 39 + .../range/range-inclusive-pattern-precedence.fixed | 21 + .../ui/range/range-inclusive-pattern-precedence.rs | 21 + .../range-inclusive-pattern-precedence.stderr | 22 + .../range/range-inclusive-pattern-precedence2.rs | 20 + .../range-inclusive-pattern-precedence2.stderr | 22 + .../range-pattern-out-of-bounds-issue-68972.rs | 13 + .../range-pattern-out-of-bounds-issue-68972.stderr | 26 + tests/ui/range/range_traits-1.rs | 25 + tests/ui/range/range_traits-1.stderr | 141 + tests/ui/range/range_traits-2.rs | 6 + tests/ui/range/range_traits-2.stderr | 13 + tests/ui/range/range_traits-3.rs | 6 + tests/ui/range/range_traits-3.stderr | 13 + tests/ui/range/range_traits-4.rs | 9 + tests/ui/range/range_traits-5.rs | 9 + tests/ui/range/range_traits-6.rs | 6 + tests/ui/range/range_traits-6.stderr | 13 + tests/ui/range/range_traits-7.rs | 9 + tests/ui/range_inclusive.rs | 121 + tests/ui/raw-ref-op/feature-raw-ref-op.rs | 21 + tests/ui/raw-ref-op/feature-raw-ref-op.stderr | 57 + tests/ui/raw-ref-op/raw-ref-op.rs | 13 + tests/ui/raw-ref-op/raw-ref-temp-deref.rs | 24 + tests/ui/raw-ref-op/raw-ref-temp.rs | 31 + tests/ui/raw-ref-op/raw-ref-temp.stderr | 99 + tests/ui/raw-ref-op/unusual_locations.rs | 22 + tests/ui/raw-str.rs | Bin 0 -> 847 bytes tests/ui/reachable-unnameable-type-alias.rs | 16 + tests/ui/reachable/README.md | 7 + tests/ui/reachable/auxiliary/issue-11225-1.rs | 18 + tests/ui/reachable/auxiliary/issue-11225-2.rs | 28 + tests/ui/reachable/auxiliary/issue-11225-3.rs | 28 + .../ui/reachable/auxiliary/unreachable_variant.rs | 5 + tests/ui/reachable/expr_add.rs | 18 + tests/ui/reachable/expr_add.stderr | 17 + tests/ui/reachable/expr_again.rs | 11 + tests/ui/reachable/expr_again.stderr | 17 + tests/ui/reachable/expr_andand.rs | 13 + tests/ui/reachable/expr_array.rs | 17 + tests/ui/reachable/expr_array.stderr | 25 + tests/ui/reachable/expr_assign.rs | 29 + tests/ui/reachable/expr_assign.stderr | 33 + tests/ui/reachable/expr_block.rs | 31 + tests/ui/reachable/expr_block.stderr | 26 + tests/ui/reachable/expr_box.rs | 8 + tests/ui/reachable/expr_box.stderr | 17 + tests/ui/reachable/expr_call.rs | 21 + tests/ui/reachable/expr_call.stderr | 24 + tests/ui/reachable/expr_cast.rs | 13 + tests/ui/reachable/expr_cast.stderr | 24 + tests/ui/reachable/expr_if.rs | 31 + tests/ui/reachable/expr_if.stderr | 30 + tests/ui/reachable/expr_loop.rs | 36 + tests/ui/reachable/expr_loop.stderr | 37 + tests/ui/reachable/expr_match.rs | 39 + tests/ui/reachable/expr_match.stderr | 27 + tests/ui/reachable/expr_method.rs | 24 + tests/ui/reachable/expr_method.stderr | 24 + tests/ui/reachable/expr_oror.rs | 12 + tests/ui/reachable/expr_repeat.rs | 12 + tests/ui/reachable/expr_repeat.stderr | 17 + tests/ui/reachable/expr_return.rs | 13 + tests/ui/reachable/expr_return.stderr | 17 + tests/ui/reachable/expr_return_in_macro.rs | 15 + tests/ui/reachable/expr_return_in_macro.stderr | 17 + tests/ui/reachable/expr_struct.rs | 32 + tests/ui/reachable/expr_struct.stderr | 42 + tests/ui/reachable/expr_tup.rs | 17 + tests/ui/reachable/expr_tup.stderr | 25 + tests/ui/reachable/expr_type.rs | 12 + tests/ui/reachable/expr_type.stderr | 17 + tests/ui/reachable/expr_unary.rs | 12 + tests/ui/reachable/expr_unary.stderr | 24 + tests/ui/reachable/expr_while.rs | 29 + tests/ui/reachable/expr_while.stderr | 32 + tests/ui/reachable/issue-11225-1.rs | 11 + tests/ui/reachable/issue-11225-2.rs | 11 + tests/ui/reachable/issue-11225-3.rs | 11 + tests/ui/reachable/unreachable-arm.rs | 14 + tests/ui/reachable/unreachable-arm.stderr | 14 + tests/ui/reachable/unreachable-code-ret.rs | 8 + tests/ui/reachable/unreachable-code-ret.stderr | 17 + tests/ui/reachable/unreachable-code.rs | 8 + tests/ui/reachable/unreachable-code.stderr | 17 + tests/ui/reachable/unreachable-in-call.rs | 22 + tests/ui/reachable/unreachable-in-call.stderr | 25 + tests/ui/reachable/unreachable-loop-patterns.rs | 20 + .../ui/reachable/unreachable-loop-patterns.stderr | 14 + tests/ui/reachable/unreachable-try-pattern.rs | 41 + tests/ui/reachable/unreachable-try-pattern.stderr | 35 + tests/ui/reachable/unreachable-variant.rs | 7 + tests/ui/reachable/unreachable-variant.stderr | 15 + tests/ui/reachable/unwarned-match-on-never.rs | 24 + tests/ui/reachable/unwarned-match-on-never.stderr | 35 + tests/ui/realloc-16687.rs | 188 + tests/ui/reassign-ref-mut.rs | 16 + tests/ui/reassign-ref-mut.stderr | 20 + .../ui/recursion/auxiliary/recursive_reexports.rs | 3 + tests/ui/recursion/instantiable.rs | 17 + .../issue-26548-recursion-via-normalize.rs | 17 + .../issue-26548-recursion-via-normalize.stderr | 10 + ...91-non-regular-dropck-recursion.polonius.stderr | 15 + .../issue-38591-non-regular-dropck-recursion.rs | 16 + ...issue-38591-non-regular-dropck-recursion.stderr | 11 + tests/ui/recursion/issue-83150.rs | 13 + tests/ui/recursion/issue-83150.stderr | 20 + tests/ui/recursion/issue-86784.rs | 2597 +++++ tests/ui/recursion/issue-95134.rs | 30 + tests/ui/recursion/recursion.polonius.stderr | 15 + tests/ui/recursion/recursion.rs | 25 + tests/ui/recursion/recursion.stderr | 15 + tests/ui/recursion/recursive-enum.rs | 4 + tests/ui/recursion/recursive-enum.stderr | 14 + tests/ui/recursion/recursive-reexports.rs | 7 + tests/ui/recursion/recursive-reexports.stderr | 9 + tests/ui/recursion/recursive-requirements.rs | 19 + tests/ui/recursion/recursive-requirements.stderr | 45 + tests/ui/recursion/recursive-static-definition.rs | 4 + .../recursion/recursive-static-definition.stderr | 24 + .../recursive-types-are-not-uninhabited.rs | 13 + .../recursive-types-are-not-uninhabited.stderr | 17 + tests/ui/recursion_limit/empty.rs | 8 + tests/ui/recursion_limit/empty.stderr | 18 + tests/ui/recursion_limit/invalid_digit.rs | 7 + tests/ui/recursion_limit/invalid_digit.stderr | 18 + tests/ui/recursion_limit/invalid_digit_type.rs | 3 + tests/ui/recursion_limit/invalid_digit_type.stderr | 8 + tests/ui/recursion_limit/invalid_macro.rs | 7 + tests/ui/recursion_limit/invalid_macro.stderr | 8 + tests/ui/recursion_limit/no-value.rs | 6 + tests/ui/recursion_limit/no-value.stderr | 8 + tests/ui/recursion_limit/overflow.rs | 9 + tests/ui/recursion_limit/overflow.stderr | 18 + tests/ui/recursion_limit/zero-overflow.rs | 7 + tests/ui/recursion_limit/zero-overflow.stderr | 7 + tests/ui/recursion_limit/zero.rs | 12 + tests/ui/recursion_limit/zero.stderr | 10 + tests/ui/reexport-test-harness-main.rs | 11 + .../ui/regions/auxiliary/rbmtp_cross_crate_lib.rs | 32 + .../regions/closure-in-projection-issue-97405.rs | 32 + .../closure-in-projection-issue-97405.stderr | 30 + .../do-not-suggest-adding-bound-to-opaque-type.rs | 12 + ...-not-suggest-adding-bound-to-opaque-type.stderr | 14 + tests/ui/regions/forall-wf-ref-reflexive.rs | 18 + tests/ui/regions/forall-wf-ref-reflexive.stderr | 8 + tests/ui/regions/forall-wf-reflexive.rs | 15 + tests/ui/regions/init-res-into-things.rs | 81 + tests/ui/regions/issue-101280.rs | 10 + tests/ui/regions/issue-101280.stderr | 14 + tests/ui/regions/issue-102374.rs | 21 + tests/ui/regions/issue-102374.stderr | 15 + tests/ui/regions/issue-102392.rs | 6 + tests/ui/regions/issue-102392.stderr | 14 + tests/ui/regions/issue-11612.rs | 24 + tests/ui/regions/issue-12470.rs | 34 + tests/ui/regions/issue-12470.stderr | 11 + tests/ui/regions/issue-21520.rs | 22 + tests/ui/regions/issue-24085.rs | 19 + tests/ui/regions/issue-26448-1.rs | 13 + tests/ui/regions/issue-26448-2.rs | 21 + tests/ui/regions/issue-26448-3.rs | 25 + tests/ui/regions/issue-2718.rs | 327 + tests/ui/regions/issue-28848.rs | 14 + tests/ui/regions/issue-28848.stderr | 14 + tests/ui/regions/issue-5243.rs | 17 + ...sue-56537-closure-uses-region-from-container.rs | 67 + tests/ui/regions/issue-6157.rs | 23 + tests/ui/regions/issue-72051-member-region-hang.rs | 7 + tests/ui/regions/issue-78262.base.stderr | 14 + tests/ui/regions/issue-78262.polonius.stderr | 14 + tests/ui/regions/issue-78262.rs | 15 + tests/ui/regions/outlives-with-missing.rs | 16 + tests/ui/regions/outlives-with-missing.stderr | 12 + tests/ui/regions/owned-implies-static.rs | 8 + tests/ui/regions/rcvr-borrowed-to-region.rs | 28 + .../region-borrow-params-issue-29793-big.rs | 74 + .../region-borrow-params-issue-29793-big.stderr | 39 + .../region-borrow-params-issue-29793-small.rs | 212 + .../region-borrow-params-issue-29793-small.stderr | 363 + .../region-bound-extra-bound-in-inherent-impl.rs | 16 + .../region-bound-on-closure-outlives-call.rs | 6 + .../region-bound-on-closure-outlives-call.stderr | 24 + .../region-bound-same-bounds-in-trait-and-impl.rs | 17 + ...region-bounds-on-objects-and-type-parameters.rs | 36 + ...on-bounds-on-objects-and-type-parameters.stderr | 35 + .../region-invariant-static-error-reporting.rs | 21 + .../region-invariant-static-error-reporting.stderr | 21 + .../region-lifetime-bounds-on-fns-where-clause.rs | 30 + ...gion-lifetime-bounds-on-fns-where-clause.stderr | 12 + ...multiple-lifetime-bounds-on-fns-where-clause.rs | 32 + ...iple-lifetime-bounds-on-fns-where-clause.stderr | 12 + tests/ui/regions/region-object-lifetime-1.rs | 18 + tests/ui/regions/region-object-lifetime-2.rs | 14 + tests/ui/regions/region-object-lifetime-2.stderr | 14 + tests/ui/regions/region-object-lifetime-3.rs | 18 + tests/ui/regions/region-object-lifetime-4.rs | 16 + tests/ui/regions/region-object-lifetime-4.stderr | 14 + tests/ui/regions/region-object-lifetime-5.rs | 14 + tests/ui/regions/region-object-lifetime-5.stderr | 9 + .../regions/region-object-lifetime-in-coercion.rs | 34 + .../region-object-lifetime-in-coercion.stderr | 62 + tests/ui/regions/regions-addr-of-arg.rs | 17 + tests/ui/regions/regions-addr-of-arg.stderr | 20 + .../regions-addr-of-interior-of-unique-box.rs | 23 + tests/ui/regions/regions-addr-of-ret.rs | 9 + tests/ui/regions/regions-addr-of-self.rs | 28 + tests/ui/regions/regions-addr-of-self.stderr | 10 + tests/ui/regions/regions-addr-of-upvar-self.rs | 18 + tests/ui/regions/regions-addr-of-upvar-self.stderr | 35 + tests/ui/regions/regions-adjusted-lvalue-op.rs | 16 + tests/ui/regions/regions-adjusted-lvalue-op.stderr | 21 + ...-assoc-type-in-supertrait-outlives-container.rs | 41 + ...oc-type-in-supertrait-outlives-container.stderr | 15 + ...ons-assoc-type-region-bound-in-trait-not-met.rs | 24 + ...assoc-type-region-bound-in-trait-not-met.stderr | 27 + .../ui/regions/regions-assoc-type-region-bound.rs | 22 + ...ons-assoc-type-static-bound-in-trait-not-met.rs | 19 + ...assoc-type-static-bound-in-trait-not-met.stderr | 15 + .../ui/regions/regions-assoc-type-static-bound.rs | 19 + tests/ui/regions/regions-borrow-at.rs | 12 + tests/ui/regions/regions-borrow-evec-fixed.rs | 10 + tests/ui/regions/regions-borrow-evec-uniq.rs | 16 + tests/ui/regions/regions-borrow-uniq.rs | 11 + tests/ui/regions/regions-bot.rs | 11 + .../regions/regions-bound-lists-feature-gate-2.rs | 14 + .../ui/regions/regions-bound-lists-feature-gate.rs | 18 + .../regions-bounded-by-trait-requiring-static.rs | 69 + ...egions-bounded-by-trait-requiring-static.stderr | 50 + ...s-bounded-method-type-parameters-cross-crate.rs | 24 + ...unded-method-type-parameters-cross-crate.stderr | 18 + ...s-bounded-method-type-parameters-trait-bound.rs | 29 + ...unded-method-type-parameters-trait-bound.stderr | 18 + .../regions-bounded-method-type-parameters.rs | 16 + .../regions-bounded-method-type-parameters.stderr | 10 + tests/ui/regions/regions-bounds.rs | 18 + tests/ui/regions/regions-bounds.stderr | 26 + .../regions-close-associated-type-into-object.rs | 71 + ...egions-close-associated-type-into-object.stderr | 40 + .../regions/regions-close-object-into-object-1.rs | 15 + .../regions-close-object-into-object-1.stderr | 12 + .../regions/regions-close-object-into-object-2.rs | 14 + .../regions-close-object-into-object-2.stderr | 29 + .../regions/regions-close-object-into-object-3.rs | 14 + .../regions-close-object-into-object-3.stderr | 12 + .../regions/regions-close-object-into-object-4.rs | 19 + .../regions-close-object-into-object-4.stderr | 74 + .../regions/regions-close-object-into-object-5.rs | 25 + .../regions-close-object-into-object-5.stderr | 57 + .../regions/regions-close-over-type-parameter-1.rs | 24 + .../regions-close-over-type-parameter-1.stderr | 26 + .../regions-close-over-type-parameter-multiple.rs | 24 + ...gions-close-over-type-parameter-multiple.stderr | 15 + ...gions-close-over-type-parameter-successfully.rs | 21 + .../ui/regions/regions-close-param-into-object.rs | 27 + .../regions/regions-close-param-into-object.stderr | 48 + tests/ui/regions/regions-copy-closure.rs | 21 + tests/ui/regions/regions-creating-enums.rs | 33 + tests/ui/regions/regions-creating-enums.stderr | 21 + tests/ui/regions/regions-creating-enums2.rs | 17 + tests/ui/regions/regions-creating-enums3.rs | 12 + tests/ui/regions/regions-creating-enums3.stderr | 14 + tests/ui/regions/regions-creating-enums4.rs | 12 + tests/ui/regions/regions-creating-enums4.stderr | 14 + tests/ui/regions/regions-creating-enums5.rs | 17 + tests/ui/regions/regions-debruijn-of-object.rs | 22 + tests/ui/regions/regions-dependent-addr-of.rs | 112 + tests/ui/regions/regions-dependent-autofn.rs | 15 + tests/ui/regions/regions-dependent-autoslice.rs | 14 + tests/ui/regions/regions-dependent-let-ref.rs | 12 + .../ui/regions/regions-early-bound-error-method.rs | 26 + .../regions-early-bound-error-method.stderr | 14 + tests/ui/regions/regions-early-bound-error.rs | 24 + tests/ui/regions/regions-early-bound-error.stderr | 14 + .../regions-early-bound-lifetime-in-assoc-fn.rs | 35 + .../ui/regions/regions-early-bound-trait-param.rs | 132 + .../regions-early-bound-used-in-bound-method.rs | 30 + .../regions/regions-early-bound-used-in-bound.rs | 28 + .../regions-early-bound-used-in-type-param.rs | 28 + tests/ui/regions/regions-escape-into-other-fn.rs | 8 + tests/ui/regions/regions-escape-method.rs | 16 + tests/ui/regions/regions-escape-method.stderr | 11 + .../ui/regions/regions-escape-via-trait-or-not.rs | 22 + .../regions/regions-escape-via-trait-or-not.stderr | 11 + tests/ui/regions/regions-expl-self.rs | 15 + tests/ui/regions/regions-fn-subtyping-2.rs | 20 + .../regions-fn-subtyping-return-static-fail.rs | 51 + .../regions-fn-subtyping-return-static-fail.stderr | 19 + .../regions/regions-fn-subtyping-return-static.rs | 48 + tests/ui/regions/regions-fn-subtyping.rs | 30 + .../regions-free-region-ordering-callee-4.rs | 11 + .../regions-free-region-ordering-callee-4.stderr | 20 + .../regions/regions-free-region-ordering-callee.rs | 30 + .../regions-free-region-ordering-callee.stderr | 28 + .../regions/regions-free-region-ordering-caller.rs | 23 + .../regions-free-region-ordering-caller.stderr | 39 + .../regions-free-region-ordering-caller1.rs | 14 + .../regions-free-region-ordering-caller1.stderr | 32 + .../regions-free-region-ordering-incorrect.rs | 22 + .../regions-free-region-ordering-incorrect.stderr | 17 + ...-region-outlives-static-outlives-free-region.rs | 17 + ...ion-outlives-static-outlives-free-region.stderr | 10 + tests/ui/regions/regions-glb-free-free.rs | 29 + tests/ui/regions/regions-glb-free-free.stderr | 16 + .../regions-implied-bounds-projection-gap-1.rs | 30 + .../regions-implied-bounds-projection-gap-1.stderr | 14 + .../regions-implied-bounds-projection-gap-2.rs | 23 + .../regions-implied-bounds-projection-gap-3.rs | 23 + .../regions-implied-bounds-projection-gap-4.rs | 23 + .../regions-implied-bounds-projection-gap-hr-1.rs | 27 + ...gions-implied-bounds-projection-gap-hr-1.stderr | 29 + tests/ui/regions/regions-in-enums-anon.rs | 7 + tests/ui/regions/regions-in-enums-anon.stderr | 15 + tests/ui/regions/regions-in-enums.rs | 20 + tests/ui/regions/regions-in-enums.stderr | 19 + tests/ui/regions/regions-in-structs-anon.rs | 7 + tests/ui/regions/regions-in-structs-anon.stderr | 15 + tests/ui/regions/regions-in-structs.rs | 15 + tests/ui/regions/regions-in-structs.stderr | 20 + tests/ui/regions/regions-infer-at-fn-not-param.rs | 19 + .../regions/regions-infer-at-fn-not-param.stderr | 11 + .../regions/regions-infer-borrow-scope-addr-of.rs | 23 + .../regions/regions-infer-borrow-scope-too-big.rs | 16 + .../regions-infer-borrow-scope-too-big.stderr | 12 + .../ui/regions/regions-infer-borrow-scope-view.rs | 11 + .../regions-infer-borrow-scope-within-loop-ok.rs | 12 + tests/ui/regions/regions-infer-borrow-scope.rs | 14 + .../regions/regions-infer-bound-from-trait-self.rs | 51 + .../regions-infer-bound-from-trait-self.stderr | 12 + tests/ui/regions/regions-infer-bound-from-trait.rs | 40 + .../regions/regions-infer-bound-from-trait.stderr | 25 + tests/ui/regions/regions-infer-call-2.rs | 15 + tests/ui/regions/regions-infer-call-3.rs | 14 + tests/ui/regions/regions-infer-call-3.stderr | 11 + tests/ui/regions/regions-infer-call.rs | 11 + .../regions-infer-contravariance-due-to-decl.rs | 29 + ...regions-infer-contravariance-due-to-decl.stderr | 15 + .../regions-infer-contravariance-due-to-ret.rs | 22 + .../regions-infer-covariance-due-to-decl.rs | 26 + .../regions-infer-covariance-due-to-decl.stderr | 15 + .../regions-infer-invariance-due-to-decl.rs | 17 + .../regions-infer-invariance-due-to-decl.stderr | 14 + ...regions-infer-invariance-due-to-mutability-3.rs | 15 + ...ons-infer-invariance-due-to-mutability-3.stderr | 14 + ...regions-infer-invariance-due-to-mutability-4.rs | 15 + ...ons-infer-invariance-due-to-mutability-4.stderr | 14 + tests/ui/regions/regions-infer-not-param.rs | 24 + tests/ui/regions/regions-infer-not-param.stderr | 40 + tests/ui/regions/regions-infer-paramd-indirect.rs | 27 + .../regions/regions-infer-paramd-indirect.stderr | 13 + .../ui/regions/regions-infer-proc-static-upvar.rs | 24 + .../regions/regions-infer-proc-static-upvar.stderr | 15 + .../regions-infer-reborrow-ref-mut-recurse.rs | 18 + .../regions-infer-region-in-fn-but-not-type.rs | 19 + tests/ui/regions/regions-infer-static-from-proc.rs | 18 + tests/ui/regions/regions-issue-21422.rs | 18 + tests/ui/regions/regions-issue-22246.rs | 29 + tests/ui/regions/regions-lifetime-bounds-on-fns.rs | 30 + .../regions/regions-lifetime-bounds-on-fns.stderr | 12 + .../regions/regions-lifetime-nonfree-late-bound.rs | 33 + .../regions-lifetime-of-struct-or-enum-variant.rs | 26 + ...gions-lifetime-of-struct-or-enum-variant.stderr | 19 + ...gions-lifetime-static-items-enclosing-scopes.rs | 20 + tests/ui/regions/regions-link-fn-args.rs | 15 + tests/ui/regions/regions-lub-ref-ref-rc.rs | 28 + tests/ui/regions/regions-mock-codegen.rs | 54 + tests/ui/regions/regions-name-duplicated.rs | 6 + tests/ui/regions/regions-name-duplicated.stderr | 11 + tests/ui/regions/regions-name-static.rs | 6 + tests/ui/regions/regions-name-static.stderr | 9 + tests/ui/regions/regions-name-undeclared.rs | 58 + tests/ui/regions/regions-name-undeclared.stderr | 156 + tests/ui/regions/regions-nested-fns-2.rs | 12 + tests/ui/regions/regions-nested-fns-2.stderr | 17 + tests/ui/regions/regions-nested-fns.rs | 24 + tests/ui/regions/regions-nested-fns.stderr | 52 + .../regions-no-bound-in-argument-cleanup.rs | 24 + .../regions-no-variance-from-fn-generics.rs | 44 + .../regions-normalize-in-where-clause-list.rs | 31 + .../regions-normalize-in-where-clause-list.stderr | 27 + tests/ui/regions/regions-nullary-variant.rs | 15 + ...egions-outlives-nominal-type-enum-region-rev.rs | 20 + .../regions-outlives-nominal-type-enum-region.rs | 20 + .../regions-outlives-nominal-type-enum-type-rev.rs | 20 + .../regions-outlives-nominal-type-enum-type.rs | 20 + ...ions-outlives-nominal-type-struct-region-rev.rs | 20 + .../regions-outlives-nominal-type-struct-region.rs | 20 + ...egions-outlives-nominal-type-struct-type-rev.rs | 20 + .../regions-outlives-nominal-type-struct-type.rs | 20 + .../regions-outlives-projection-container-hrtb.rs | 52 + ...gions-outlives-projection-container-hrtb.stderr | 28 + .../regions-outlives-projection-container-wc.rs | 35 + ...regions-outlives-projection-container-wc.stderr | 15 + .../regions-outlives-projection-container.rs | 77 + .../regions-outlives-projection-container.stderr | 54 + .../regions/regions-outlives-projection-hrtype.rs | 26 + .../regions-outlives-projection-trait-def.rs | 21 + tests/ui/regions/regions-outlives-scalar.rs | 13 + tests/ui/regions/regions-params.rs | 19 + .../regions/regions-pattern-typing-issue-19552.rs | 8 + .../regions-pattern-typing-issue-19552.stderr | 14 + .../regions/regions-pattern-typing-issue-19997.rs | 11 + .../regions-pattern-typing-issue-19997.stderr | 14 + tests/ui/regions/regions-proc-bound-capture.rs | 13 + tests/ui/regions/regions-proc-bound-capture.stderr | 20 + .../regions/regions-reassign-let-bound-pointer.rs | 18 + .../regions-reassign-match-bound-pointer.rs | 21 + ...egions-reborrow-from-shorter-mut-ref-mut-ref.rs | 9 + ...ns-reborrow-from-shorter-mut-ref-mut-ref.stderr | 14 + .../regions-reborrow-from-shorter-mut-ref.rs | 16 + .../regions-reborrow-from-shorter-mut-ref.stderr | 14 + tests/ui/regions/regions-ref-in-fn-arg.rs | 14 + tests/ui/regions/regions-ref-in-fn-arg.stderr | 19 + tests/ui/regions/regions-refcell.rs | 45 + ...d-regions-on-closures-to-inference-variables.rs | 57 + tests/ui/regions/regions-ret-borrowed-1.rs | 17 + tests/ui/regions/regions-ret-borrowed-1.stderr | 11 + tests/ui/regions/regions-ret-borrowed.rs | 20 + tests/ui/regions/regions-ret-borrowed.stderr | 11 + tests/ui/regions/regions-ret.rs | 8 + tests/ui/regions/regions-ret.stderr | 12 + .../regions/regions-return-interior-of-option.rs | 24 + .../regions-return-ref-to-upvar-issue-17403.rs | 11 + .../regions-return-ref-to-upvar-issue-17403.stderr | 17 + .../regions/regions-return-stack-allocated-vec.rs | 10 + .../regions-return-stack-allocated-vec.stderr | 12 + tests/ui/regions/regions-scope-chain-example.rs | 43 + tests/ui/regions/regions-self-impls.rs | 20 + tests/ui/regions/regions-self-in-enums.rs | 17 + tests/ui/regions/regions-simple.rs | 7 + tests/ui/regions/regions-static-bound-rpass.rs | 26 + tests/ui/regions/regions-static-bound-rpass.stderr | 26 + tests/ui/regions/regions-static-bound.rs | 21 + tests/ui/regions/regions-static-bound.stderr | 54 + tests/ui/regions/regions-static-closure.rs | 19 + tests/ui/regions/regions-steal-closure.rs | 17 + tests/ui/regions/regions-steal-closure.stderr | 16 + tests/ui/regions/regions-trait-1.rs | 33 + tests/ui/regions/regions-trait-object-1.rs | 35 + tests/ui/regions/regions-trait-object-subtyping.rs | 26 + .../regions/regions-trait-object-subtyping.stderr | 34 + tests/ui/regions/regions-trait-variance.rs | 44 + tests/ui/regions/regions-trait-variance.stderr | 11 + tests/ui/regions/regions-undeclared.rs | 13 + tests/ui/regions/regions-undeclared.stderr | 42 + tests/ui/regions/regions-var-type-out-of-scope.rs | 14 + .../regions/regions-var-type-out-of-scope.stderr | 15 + ...ons-variance-contravariant-use-contravariant.rs | 27 + ...ntravariant-use-covariant-in-second-position.rs | 29 + ...variant-use-covariant-in-second-position.stderr | 15 + ...regions-variance-contravariant-use-covariant.rs | 27 + ...ons-variance-contravariant-use-covariant.stderr | 15 + ...regions-variance-covariant-use-contravariant.rs | 27 + ...ons-variance-covariant-use-contravariant.stderr | 15 + .../regions-variance-covariant-use-covariant.rs | 23 + ...regions-variance-invariant-use-contravariant.rs | 24 + ...ons-variance-invariant-use-contravariant.stderr | 18 + .../regions-variance-invariant-use-covariant.rs | 21 + ...regions-variance-invariant-use-covariant.stderr | 15 + tests/ui/regions/regions-wf-trait-object.rs | 10 + tests/ui/regions/regions-wf-trait-object.stderr | 20 + .../type-param-outlives-reempty-issue-74429-2.rs | 66 + .../type-param-outlives-reempty-issue-74429.rs | 35 + tests/ui/regions/wf-bound-region-in-object-type.rs | 22 + tests/ui/reify-intrinsic.rs | 23 + tests/ui/reify-intrinsic.stderr | 33 + tests/ui/removing-extern-crate.fixed | 16 + tests/ui/removing-extern-crate.rs | 16 + tests/ui/removing-extern-crate.stderr | 33 + tests/ui/repeat-expr/infer.rs | 16 + tests/ui/repeat-expr/repeat-expr-in-static.rs | 8 + tests/ui/repeat-expr/repeat-to-run-dtor-twice.rs | 19 + .../ui/repeat-expr/repeat-to-run-dtor-twice.stderr | 15 + tests/ui/repeat-expr/repeat_count.rs | 34 + tests/ui/repeat-expr/repeat_count.stderr | 69 + tests/ui/repr/align-with-extern-c-fn.rs | 18 + tests/ui/repr/aligned_enum_cast.rs | 25 + tests/ui/repr/attr-usage-repr.rs | 33 + tests/ui/repr/attr-usage-repr.stderr | 35 + .../auxiliary/repr-transparent-non-exhaustive.rs | 18 + tests/ui/repr/invalid_repr_list_help.rs | 17 + tests/ui/repr/invalid_repr_list_help.stderr | 35 + tests/ui/repr/issue-83505-repr-simd.rs | 10 + tests/ui/repr/issue-83505-repr-simd.stderr | 30 + tests/ui/repr/issue-83921-ice.rs | 34 + tests/ui/repr/issue-83921-ice.stderr | 46 + tests/ui/repr/repr-align-assign.fixed | 13 + tests/ui/repr/repr-align-assign.rs | 13 + tests/ui/repr/repr-align-assign.stderr | 27 + tests/ui/repr/repr-align.rs | 33 + tests/ui/repr/repr-align.stderr | 75 + tests/ui/repr/repr-disallow-on-variant.rs | 9 + tests/ui/repr/repr-disallow-on-variant.stderr | 12 + tests/ui/repr/repr-packed-contains-align.rs | 53 + tests/ui/repr/repr-packed-contains-align.stderr | 139 + tests/ui/repr/repr-transparent-issue-87496.rs | 12 + tests/ui/repr/repr-transparent-issue-87496.stderr | 16 + tests/ui/repr/repr-transparent-non-exhaustive.rs | 96 + .../ui/repr/repr-transparent-non-exhaustive.stderr | 127 + tests/ui/repr/repr-transparent-other-items.rs | 9 + tests/ui/repr/repr-transparent-other-items.stderr | 19 + tests/ui/repr/repr-transparent-other-reprs.rs | 18 + tests/ui/repr/repr-transparent-other-reprs.stderr | 29 + tests/ui/repr/repr-transparent.rs | 90 + tests/ui/repr/repr-transparent.stderr | 90 + tests/ui/repr/repr.rs | 13 + tests/ui/repr/repr.stderr | 20 + tests/ui/repr/repr_c_int_align.rs | 46 + .../ui/repr/transparent-enum-too-many-variants.rs | 10 + .../repr/transparent-enum-too-many-variants.stderr | 11 + tests/ui/reserved/reserved-attr-on-macro.rs | 11 + tests/ui/reserved/reserved-attr-on-macro.stderr | 22 + tests/ui/reserved/reserved-become.rs | 4 + tests/ui/reserved/reserved-become.stderr | 13 + tests/ui/resolve/associated-fn-called-as-fn.rs | 32 + tests/ui/resolve/associated-fn-called-as-fn.stderr | 15 + .../blind-item-mixed-crate-use-item-foo.rs | 3 + .../blind-item-mixed-crate-use-item-foo2.rs | 3 + tests/ui/resolve/auxiliary/extern-prelude-vec.rs | 3 + tests/ui/resolve/auxiliary/extern-prelude.rs | 5 + tests/ui/resolve/auxiliary/issue-19452-aux.rs | 3 + tests/ui/resolve/auxiliary/issue-21221-3.rs | 19 + tests/ui/resolve/auxiliary/issue-21221-4.rs | 12 + tests/ui/resolve/auxiliary/issue-30535.rs | 5 + tests/ui/resolve/auxiliary/issue-3907.rs | 3 + tests/ui/resolve/auxiliary/issue-80079.rs | 18 + tests/ui/resolve/auxiliary/namespaced_enums.rs | 10 + tests/ui/resolve/auxiliary/privacy-struct-ctor.rs | 9 + tests/ui/resolve/bad-env-capture.rs | 6 + tests/ui/resolve/bad-env-capture.stderr | 24 + tests/ui/resolve/bad-env-capture2.rs | 5 + tests/ui/resolve/bad-env-capture2.stderr | 24 + tests/ui/resolve/bad-env-capture3.rs | 8 + tests/ui/resolve/bad-env-capture3.stderr | 24 + tests/ui/resolve/bad-expr-path.rs | 8 + tests/ui/resolve/bad-expr-path.stderr | 31 + tests/ui/resolve/bad-expr-path2.rs | 10 + tests/ui/resolve/bad-expr-path2.stderr | 31 + tests/ui/resolve/bad-module.rs | 7 + tests/ui/resolve/bad-module.stderr | 15 + tests/ui/resolve/bad-type-env-capture.rs | 4 + tests/ui/resolve/bad-type-env-capture.stderr | 13 + tests/ui/resolve/blind-item-local-shadow.rs | 13 + .../ui/resolve/blind-item-mixed-crate-use-item.rs | 26 + tests/ui/resolve/blind-item-mixed-use-item.rs | 20 + tests/ui/resolve/block-with-trait-parent.rs | 14 + tests/ui/resolve/crate-called-as-function.rs | 3 + tests/ui/resolve/crate-called-as-function.stderr | 9 + tests/ui/resolve/crate-in-paths.rs | 10 + tests/ui/resolve/crate-in-paths.stderr | 14 + tests/ui/resolve/editions-crate-root-2015.rs | 21 + tests/ui/resolve/editions-crate-root-2015.stderr | 32 + tests/ui/resolve/editions-crate-root-2018.rs | 21 + tests/ui/resolve/editions-crate-root-2018.stderr | 28 + tests/ui/resolve/enums-are-namespaced-xc.rs | 11 + tests/ui/resolve/enums-are-namespaced-xc.stderr | 52 + tests/ui/resolve/enums-pats-not-idents.rs | 3 + tests/ui/resolve/enums-pats-not-idents.stderr | 9 + tests/ui/resolve/export-fully-qualified.rs | 11 + tests/ui/resolve/export-fully-qualified.stderr | 9 + tests/ui/resolve/extern-prelude-fail.rs | 9 + tests/ui/resolve/extern-prelude-fail.stderr | 20 + tests/ui/resolve/extern-prelude.rs | 31 + tests/ui/resolve/filter-intrinsics.rs | 10 + tests/ui/resolve/filter-intrinsics.stderr | 25 + tests/ui/resolve/impl-items-vis-unresolved.rs | 26 + tests/ui/resolve/impl-items-vis-unresolved.stderr | 9 + tests/ui/resolve/issue-100365.rs | 50 + tests/ui/resolve/issue-100365.stderr | 54 + tests/ui/resolve/issue-101749-2.rs | 16 + tests/ui/resolve/issue-101749-2.stderr | 9 + tests/ui/resolve/issue-101749.fixed | 19 + tests/ui/resolve/issue-101749.rs | 19 + tests/ui/resolve/issue-101749.stderr | 14 + tests/ui/resolve/issue-10200.rs | 9 + tests/ui/resolve/issue-10200.stderr | 12 + tests/ui/resolve/issue-102946.rs | 7 + tests/ui/resolve/issue-102946.stderr | 26 + tests/ui/resolve/issue-103202.rs | 7 + tests/ui/resolve/issue-103202.stderr | 14 + tests/ui/resolve/issue-103474.rs | 28 + tests/ui/resolve/issue-103474.stderr | 35 + tests/ui/resolve/issue-104700-inner_scope.rs | 11 + tests/ui/resolve/issue-104700-inner_scope.stderr | 21 + tests/ui/resolve/issue-105069.rs | 11 + tests/ui/resolve/issue-105069.stderr | 21 + tests/ui/resolve/issue-12796.rs | 9 + tests/ui/resolve/issue-12796.stderr | 12 + tests/ui/resolve/issue-14254.rs | 105 + tests/ui/resolve/issue-14254.stderr | 182 + tests/ui/resolve/issue-16058.rs | 18 + tests/ui/resolve/issue-16058.stderr | 18 + tests/ui/resolve/issue-17518.rs | 7 + tests/ui/resolve/issue-17518.stderr | 14 + tests/ui/resolve/issue-18252.rs | 8 + tests/ui/resolve/issue-18252.stderr | 9 + tests/ui/resolve/issue-19452.rs | 15 + tests/ui/resolve/issue-19452.stderr | 15 + tests/ui/resolve/issue-21221-1.rs | 75 + tests/ui/resolve/issue-21221-1.stderr | 51 + tests/ui/resolve/issue-21221-2.rs | 21 + tests/ui/resolve/issue-21221-2.stderr | 16 + tests/ui/resolve/issue-21221-3.rs | 19 + tests/ui/resolve/issue-21221-3.stderr | 14 + tests/ui/resolve/issue-21221-4.rs | 15 + tests/ui/resolve/issue-21221-4.stderr | 14 + tests/ui/resolve/issue-22692.rs | 60 + tests/ui/resolve/issue-22692.stderr | 88 + tests/ui/resolve/issue-2330.rs | 13 + tests/ui/resolve/issue-2330.stderr | 9 + tests/ui/resolve/issue-23305.rs | 8 + tests/ui/resolve/issue-23305.stderr | 10 + tests/ui/resolve/issue-2356.rs | 94 + tests/ui/resolve/issue-2356.stderr | 134 + tests/ui/resolve/issue-23716.rs | 17 + tests/ui/resolve/issue-23716.stderr | 21 + tests/ui/resolve/issue-24968.rs | 30 + tests/ui/resolve/issue-24968.stderr | 57 + tests/ui/resolve/issue-26545.rs | 12 + tests/ui/resolve/issue-26545.stderr | 14 + tests/ui/resolve/issue-3021-c.rs | 9 + tests/ui/resolve/issue-3021-c.stderr | 25 + tests/ui/resolve/issue-3021.rs | 18 + tests/ui/resolve/issue-3021.stderr | 11 + tests/ui/resolve/issue-30535.rs | 9 + tests/ui/resolve/issue-30535.stderr | 12 + tests/ui/resolve/issue-31845.rs | 12 + tests/ui/resolve/issue-31845.stderr | 9 + tests/ui/resolve/issue-33876.rs | 12 + tests/ui/resolve/issue-33876.stderr | 9 + tests/ui/resolve/issue-35675.rs | 42 + tests/ui/resolve/issue-35675.stderr | 75 + tests/ui/resolve/issue-3907-2.rs | 14 + tests/ui/resolve/issue-3907-2.stderr | 15 + tests/ui/resolve/issue-3907.rs | 20 + tests/ui/resolve/issue-3907.stderr | 18 + tests/ui/resolve/issue-39226.rs | 14 + tests/ui/resolve/issue-39226.stderr | 21 + tests/ui/resolve/issue-39559-2.rs | 18 + tests/ui/resolve/issue-39559-2.stderr | 21 + tests/ui/resolve/issue-39559.rs | 19 + tests/ui/resolve/issue-39559.stderr | 11 + tests/ui/resolve/issue-42944.rs | 21 + tests/ui/resolve/issue-42944.stderr | 32 + tests/ui/resolve/issue-49074.rs | 13 + tests/ui/resolve/issue-49074.stderr | 16 + tests/ui/resolve/issue-5035-2.rs | 7 + tests/ui/resolve/issue-5035-2.stderr | 20 + tests/ui/resolve/issue-5035.rs | 9 + tests/ui/resolve/issue-5035.stderr | 28 + tests/ui/resolve/issue-50599.rs | 6 + tests/ui/resolve/issue-50599.stderr | 27 + tests/ui/resolve/issue-5099.rs | 13 + tests/ui/resolve/issue-5099.stderr | 48 + tests/ui/resolve/issue-54379.rs | 14 + tests/ui/resolve/issue-54379.stderr | 19 + tests/ui/resolve/issue-55673.rs | 12 + tests/ui/resolve/issue-55673.stderr | 9 + tests/ui/resolve/issue-57523.rs | 21 + tests/ui/resolve/issue-5927.rs | 7 + tests/ui/resolve/issue-5927.stderr | 16 + tests/ui/resolve/issue-60057.rs | 19 + tests/ui/resolve/issue-60057.stderr | 15 + .../issue-65025-extern-static-parent-generics.rs | 10 + ...ssue-65025-extern-static-parent-generics.stderr | 12 + .../issue-65035-static-with-parent-generics.rs | 26 + .../issue-65035-static-with-parent-generics.stderr | 45 + tests/ui/resolve/issue-6702.rs | 9 + tests/ui/resolve/issue-6702.stderr | 14 + .../issue-69401-trait-fn-no-body-ty-local.rs | 6 + .../issue-69401-trait-fn-no-body-ty-local.stderr | 9 + .../issue-70736-async-fn-no-body-def-collector.rs | 19 + ...sue-70736-async-fn-no-body-def-collector.stderr | 53 + tests/ui/resolve/issue-73427.rs | 50 + tests/ui/resolve/issue-73427.stderr | 168 + tests/ui/resolve/issue-80079.rs | 12 + tests/ui/resolve/issue-80079.stderr | 9 + tests/ui/resolve/issue-81508.rs | 22 + tests/ui/resolve/issue-81508.stderr | 21 + tests/ui/resolve/issue-82156.rs | 3 + tests/ui/resolve/issue-82156.stderr | 9 + tests/ui/resolve/issue-82865.rs | 13 + tests/ui/resolve/issue-82865.stderr | 23 + tests/ui/resolve/issue-85348.rs | 12 + tests/ui/resolve/issue-85348.stderr | 30 + tests/ui/resolve/issue-85671.rs | 37 + tests/ui/resolve/issue-88472.rs | 38 + tests/ui/resolve/issue-88472.stderr | 42 + tests/ui/resolve/issue-90113.rs | 21 + tests/ui/resolve/issue-90113.stderr | 14 + tests/ui/resolve/levenshtein.rs | 31 + tests/ui/resolve/levenshtein.stderr | 70 + tests/ui/resolve/macro-determinacy-non-module.rs | 7 + tests/ui/resolve/missing-in-namespace.rs | 4 + tests/ui/resolve/missing-in-namespace.stderr | 19 + tests/ui/resolve/name-clash-nullary.rs | 3 + tests/ui/resolve/name-clash-nullary.stderr | 14 + tests/ui/resolve/name-collision-in-trait-fn-sig.rs | 11 + tests/ui/resolve/no-implicit-prelude-nested.rs | 54 + tests/ui/resolve/no-implicit-prelude-nested.stderr | 187 + tests/ui/resolve/no-implicit-prelude.rs | 18 + tests/ui/resolve/no-implicit-prelude.stderr | 65 + tests/ui/resolve/no-std-1.rs | 10 + tests/ui/resolve/no-std-2.rs | 10 + tests/ui/resolve/no-std-3.rs | 17 + tests/ui/resolve/pathless-extern-ok.rs | 9 + ...int-at-type-parameter-shadowing-another-type.rs | 21 + ...at-type-parameter-shadowing-another-type.stderr | 15 + tests/ui/resolve/privacy-enum-ctor.rs | 71 + tests/ui/resolve/privacy-enum-ctor.stderr | 395 + tests/ui/resolve/privacy-struct-ctor.rs | 47 + tests/ui/resolve/privacy-struct-ctor.stderr | 155 + tests/ui/resolve/raw-ident-in-path.rs | 5 + tests/ui/resolve/raw-ident-in-path.stderr | 9 + tests/ui/resolve/resolve-assoc-suggestions.rs | 39 + tests/ui/resolve/resolve-assoc-suggestions.stderr | 58 + tests/ui/resolve/resolve-bad-import-prefix.rs | 14 + tests/ui/resolve/resolve-bad-import-prefix.stderr | 9 + tests/ui/resolve/resolve-bad-visibility.rs | 15 + tests/ui/resolve/resolve-bad-visibility.stderr | 38 + ...esolve-conflict-extern-crate-vs-extern-crate.rs | 4 + ...ve-conflict-extern-crate-vs-extern-crate.stderr | 11 + .../resolve-conflict-import-vs-extern-crate.rs | 4 + .../resolve-conflict-import-vs-extern-crate.stderr | 15 + .../resolve-conflict-import-vs-import.fixed | 9 + .../resolve/resolve-conflict-import-vs-import.rs | 9 + .../resolve-conflict-import-vs-import.stderr | 13 + .../resolve-conflict-item-vs-extern-crate.rs | 5 + .../resolve-conflict-item-vs-extern-crate.stderr | 11 + .../ui/resolve/resolve-conflict-item-vs-import.rs | 8 + .../resolve/resolve-conflict-item-vs-import.stderr | 18 + .../ui/resolve/resolve-conflict-type-vs-import.rs | 7 + .../resolve/resolve-conflict-type-vs-import.stderr | 18 + tests/ui/resolve/resolve-hint-macro.fixed | 11 + tests/ui/resolve/resolve-hint-macro.rs | 11 + tests/ui/resolve/resolve-hint-macro.stderr | 53 + .../resolve/resolve-inconsistent-binding-mode.rs | 41 + .../resolve-inconsistent-binding-mode.stderr | 72 + tests/ui/resolve/resolve-inconsistent-names.rs | 36 + tests/ui/resolve/resolve-inconsistent-names.stderr | 104 + tests/ui/resolve/resolve-issue-2428.rs | 8 + tests/ui/resolve/resolve-label.rs | 13 + tests/ui/resolve/resolve-label.stderr | 14 + tests/ui/resolve/resolve-primitive-fallback.rs | 10 + tests/ui/resolve/resolve-primitive-fallback.stderr | 39 + tests/ui/resolve/resolve-pseudo-shadowing.rs | 11 + tests/ui/resolve/resolve-self-in-impl-2.rs | 7 + tests/ui/resolve/resolve-self-in-impl-2.stderr | 16 + tests/ui/resolve/resolve-self-in-impl.rs | 21 + tests/ui/resolve/resolve-self-in-impl.stderr | 62 + tests/ui/resolve/resolve-speculative-adjustment.rs | 30 + .../resolve/resolve-speculative-adjustment.stderr | 27 + .../resolve/resolve-type-param-in-item-in-trait.rs | 35 + .../resolve-type-param-in-item-in-trait.stderr | 47 + tests/ui/resolve/resolve-unknown-trait.rs | 10 + tests/ui/resolve/resolve-unknown-trait.stderr | 21 + tests/ui/resolve/resolve-variant-assoc-item.rs | 7 + tests/ui/resolve/resolve-variant-assoc-item.stderr | 15 + tests/ui/resolve/shadow-const-param.rs | 20 + tests/ui/resolve/shadow-const-param.stderr | 20 + tests/ui/resolve/suggest-path-for-tuple-struct.rs | 26 + .../resolve/suggest-path-for-tuple-struct.stderr | 15 + .../suggest-path-instead-of-mod-dot-item.rs | 111 + .../suggest-path-instead-of-mod-dot-item.stderr | 140 + tests/ui/resolve/token-error-correct-2.rs | 7 + tests/ui/resolve/token-error-correct-2.stderr | 18 + tests/ui/resolve/token-error-correct-3.rs | 25 + tests/ui/resolve/token-error-correct-3.stderr | 25 + tests/ui/resolve/token-error-correct-4.fixed | 10 + tests/ui/resolve/token-error-correct-4.rs | 10 + tests/ui/resolve/token-error-correct-4.stderr | 16 + tests/ui/resolve/token-error-correct.rs | 9 + tests/ui/resolve/token-error-correct.stderr | 20 + tests/ui/resolve/tuple-struct-alias.rs | 9 + tests/ui/resolve/tuple-struct-alias.stderr | 26 + ...r-variable-with-name-similar-to-struct-field.rs | 46 + ...riable-with-name-similar-to-struct-field.stderr | 109 + .../ui/resolve/typo-suggestion-mistyped-in-path.rs | 42 + .../typo-suggestion-mistyped-in-path.stderr | 54 + .../ui/resolve/typo-suggestion-named-underscore.rs | 14 + .../typo-suggestion-named-underscore.stderr | 16 + .../unboxed-closure-sugar-nonexistent-trait.rs | 9 + .../unboxed-closure-sugar-nonexistent-trait.stderr | 21 + tests/ui/resolve/unresolved_static_type_field.rs | 14 + .../ui/resolve/unresolved_static_type_field.stderr | 9 + tests/ui/resolve/use-self-in-inner-fn.rs | 14 + tests/ui/resolve/use-self-in-inner-fn.stderr | 15 + tests/ui/resolve/use_suggestion.rs | 7 + tests/ui/resolve/use_suggestion.stderr | 38 + tests/ui/resolve/use_suggestion_placement.fixed | 35 + tests/ui/resolve/use_suggestion_placement.rs | 29 + tests/ui/resolve/use_suggestion_placement.stderr | 37 + tests/ui/resolve/visibility-indeterminate.rs | 7 + tests/ui/resolve/visibility-indeterminate.stderr | 15 + tests/ui/resource-assign-is-not-copy.rs | 33 + tests/ui/resource-destruct.rs | 31 + tests/ui/ret-bang.rs | 13 + tests/ui/ret-non-nil.rs | 7 + tests/ui/ret-non-nil.stderr | 11 + tests/ui/return-disjoint-regions.rs | 7 + tests/ui/return-disjoint-regions.stderr | 11 + tests/ui/return-nil.rs | 6 + tests/ui/return/issue-64620.rs | 5 + tests/ui/return/issue-64620.stderr | 9 + .../return/issue-82612-return-mutable-reference.rs | 24 + .../issue-82612-return-mutable-reference.stderr | 28 + .../ui/return/issue-86188-return-not-in-fn-body.rs | 41 + .../issue-86188-return-not-in-fn-body.stderr | 52 + tests/ui/return/return-from-diverging.rs | 8 + tests/ui/return/return-from-diverging.stderr | 14 + tests/ui/return/return-impl-trait-bad.rs | 31 + tests/ui/return/return-impl-trait-bad.stderr | 59 + tests/ui/return/return-impl-trait.fixed | 30 + tests/ui/return/return-impl-trait.rs | 30 + tests/ui/return/return-impl-trait.stderr | 34 + tests/ui/return/return-match-array-const.rs | 19 + tests/ui/return/return-match-array-const.stderr | 56 + tests/ui/return/return-type.rs | 14 + tests/ui/return/return-type.stderr | 20 + tests/ui/return/return-unit-from-diverging.rs | 9 + tests/ui/return/return-unit-from-diverging.stderr | 11 + tests/ui/return/tail-expr-as-potential-return.rs | 47 + .../ui/return/tail-expr-as-potential-return.stderr | 52 + .../bind-by-move-no-guards.rs | 19 + .../former-E0008-now-pass.rs | 11 + .../rfc-basic-examples.rs | 43 + .../rfc-reject-double-move-across-arms.rs | 24 + .../rfc-reject-double-move-across-arms.stderr | 19 + .../rfc-reject-double-move-in-first-arm.rs | 26 + .../rfc-reject-double-move-in-first-arm.stderr | 19 + ...allow-hide-behind-direct-unsafe-ptr-embedded.rs | 26 + .../allow-hide-behind-direct-unsafe-ptr-param.rs | 26 + ...low-hide-behind-indirect-unsafe-ptr-embedded.rs | 26 + .../allow-hide-behind-indirect-unsafe-ptr-param.rs | 26 + .../allow-use-behind-cousin-variant.rs | 59 + .../cant-hide-behind-direct-struct-embedded.rs | 26 + .../cant-hide-behind-direct-struct-embedded.stderr | 8 + .../cant-hide-behind-direct-struct-param.rs | 26 + .../cant-hide-behind-direct-struct-param.stderr | 8 + .../cant-hide-behind-doubly-indirect-embedded.rs | 29 + ...ant-hide-behind-doubly-indirect-embedded.stderr | 16 + .../cant-hide-behind-doubly-indirect-param.rs | 29 + .../cant-hide-behind-doubly-indirect-param.stderr | 16 + .../cant-hide-behind-indirect-struct-embedded.rs | 29 + ...ant-hide-behind-indirect-struct-embedded.stderr | 16 + .../cant-hide-behind-indirect-struct-param.rs | 29 + .../cant-hide-behind-indirect-struct-param.stderr | 16 + .../feature-gate.no_gate.stderr | 21 + .../feature-gate.rs | 39 + .../feature-gate.with_gate.stderr | 8 + .../fn-ptr-is-structurally-matchable.rs | 135 + ...issue-61188-match-slice-forbidden-without-eq.rs | 19 + ...e-61188-match-slice-forbidden-without-eq.stderr | 8 + ...sue-62307-match-ref-ref-forbidden-without-eq.rs | 43 + ...62307-match-ref-ref-forbidden-without-eq.stderr | 25 + .../issue-63479-match-fnptr.rs | 40 + .../issue-63479-match-fnptr.stderr | 16 + .../issue-6804.rs | 21 + .../issue-6804.stderr | 25 + ...h-empty-array-allowed-without-eq-issue-62336.rs | 17 + .../match-forbidden-without-eq.rs | 23 + .../match-forbidden-without-eq.stderr | 18 + .../match-nonempty-array-forbidden-without-eq.rs | 19 + ...atch-nonempty-array-forbidden-without-eq.stderr | 8 + .../match-requires-both-partialeq-and-eq.rs | 21 + .../match-requires-both-partialeq-and-eq.stderr | 8 + .../phantom-data-is-structurally-matchable.rs | 53 + tests/ui/rfc-1717-dllimport/missing-link-attr.rs | 4 + .../ui/rfc-1717-dllimport/missing-link-attr.stderr | 4 + tests/ui/rfc-1717-dllimport/multiple-renames.rs | 7 + .../ui/rfc-1717-dllimport/multiple-renames.stderr | 4 + tests/ui/rfc-1717-dllimport/rename-modifiers.rs | 9 + .../ui/rfc-1717-dllimport/rename-modifiers.stderr | 8 + tests/ui/rfc-1717-dllimport/rename-to-empty.rs | 7 + tests/ui/rfc-1717-dllimport/rename-to-empty.stderr | 4 + .../rfc-1937-termination-trait/issue-103052-1.rs | 11 + .../issue-103052-1.stderr | 17 + .../rfc-1937-termination-trait/issue-103052-2.rs | 18 + .../issue-103052-2.stderr | 15 + .../termination-trait-for-box-dyn-error.rs | 11 + .../termination-trait-for-never.rs | 7 + .../termination-trait-for-result-box-error_err.rs | 10 + .../termination-trait-for-str.rs | 8 + .../termination-trait-impl-trait.rs | 3 + .../termination-trait-impl-trait.stderr | 11 + .../termination-trait-in-test-should-panic.rs | 15 + .../termination-trait-in-test-should-panic.stderr | 12 + .../termination-trait-in-test.rs | 28 + .../termination-trait-main-i32.rs | 6 + .../termination-trait-main-i32.stderr | 11 + .../termination-trait-main-wrong-type.rs | 3 + .../termination-trait-main-wrong-type.stderr | 11 + .../termination-trait-not-satisfied.rs | 5 + .../termination-trait-not-satisfied.stderr | 11 + .../termination-trait-test-wrong-type.rs | 8 + .../termination-trait-test-wrong-type.stderr | 16 + .../borrowck-issue-49631.rs | 24 + .../borrowck-issue-49631.stderr | 14 + tests/ui/rfc-2005-default-binding-mode/const.rs | 17 + .../ui/rfc-2005-default-binding-mode/const.stderr | 18 + tests/ui/rfc-2005-default-binding-mode/enum.rs | 22 + tests/ui/rfc-2005-default-binding-mode/enum.stderr | 21 + .../rfc-2005-default-binding-mode/explicit-mut.rs | 28 + .../explicit-mut.stderr | 21 + tests/ui/rfc-2005-default-binding-mode/for.rs | 9 + tests/ui/rfc-2005-default-binding-mode/for.stderr | 17 + .../issue-44912-or.rs | 10 + .../issue-44912-or.stderr | 9 + tests/ui/rfc-2005-default-binding-mode/lit.rs | 24 + tests/ui/rfc-2005-default-binding-mode/lit.stderr | 25 + .../no-double-error.rs | 11 + .../no-double-error.stderr | 9 + tests/ui/rfc-2005-default-binding-mode/slice.rs | 7 + .../ui/rfc-2005-default-binding-mode/slice.stderr | 16 + .../ui/rfc-2008-non-exhaustive/auxiliary/enums.rs | 44 + .../auxiliary/monovariants.rs | 8 + .../rfc-2008-non-exhaustive/auxiliary/structs.rs | 41 + .../rfc-2008-non-exhaustive/auxiliary/unstable.rs | 60 + .../rfc-2008-non-exhaustive/auxiliary/variants.rs | 7 + .../rfc-2008-non-exhaustive/borrowck-exhaustive.rs | 42 + .../borrowck-non-exhaustive.rs | 18 + .../borrowck-non-exhaustive.stderr | 14 + tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs | 11 + .../ui/rfc-2008-non-exhaustive/enum-as-cast.stderr | 11 + tests/ui/rfc-2008-non-exhaustive/enum.rs | 69 + tests/ui/rfc-2008-non-exhaustive/enum.stderr | 59 + .../ui/rfc-2008-non-exhaustive/enum_same_crate.rs | 18 + .../enum_same_crate_empty_match.rs | 37 + .../enum_same_crate_empty_match.stderr | 69 + .../improper_ctypes/auxiliary/types.rs | 29 + .../improper_ctypes/extern_crate_improper.rs | 24 + .../improper_ctypes/extern_crate_improper.stderr | 47 + .../improper_ctypes/same_crate_proper.rs | 48 + .../rfc-2008-non-exhaustive/invalid-attribute.rs | 16 + .../invalid-attribute.stderr | 30 + .../ui/rfc-2008-non-exhaustive/omitted-patterns.rs | 187 + .../omitted-patterns.stderr | 188 + .../stable-omitted-patterns.rs | 45 + .../stable-omitted-patterns.stderr | 30 + tests/ui/rfc-2008-non-exhaustive/struct.rs | 49 + tests/ui/rfc-2008-non-exhaustive/struct.stderr | 96 + .../rfc-2008-non-exhaustive/structs_same_crate.rs | 32 + .../uninhabited/auxiliary/uninhabited.rs | 32 + .../uninhabited/coercions.rs | 38 + .../uninhabited/coercions.stderr | 35 + .../uninhabited/coercions_same_crate.rs | 45 + .../uninhabited/coercions_same_crate.stderr | 35 + .../uninhabited/indirect_match.rs | 36 + .../uninhabited/indirect_match.stderr | 79 + .../uninhabited/indirect_match_same_crate.rs | 51 + .../uninhabited/indirect_match_same_crate.stderr | 79 + .../indirect_match_with_exhaustive_patterns.rs | 40 + .../indirect_match_with_exhaustive_patterns.stderr | 79 + ...ct_match_with_exhaustive_patterns_same_crate.rs | 57 + .../uninhabited/issue-65157-repeated-match-arm.rs | 21 + .../issue-65157-repeated-match-arm.stderr | 14 + .../rfc-2008-non-exhaustive/uninhabited/match.rs | 34 + .../uninhabited/match.stderr | 83 + .../uninhabited/match_same_crate.rs | 41 + .../uninhabited/match_same_crate.stderr | 64 + .../uninhabited/match_with_exhaustive_patterns.rs | 37 + .../match_with_exhaustive_patterns.stderr | 83 + .../match_with_exhaustive_patterns_same_crate.rs | 47 + .../uninhabited/patterns.rs | 59 + .../uninhabited/patterns_same_crate.rs | 70 + .../uninhabited/patterns_same_crate.stderr | 38 + tests/ui/rfc-2008-non-exhaustive/variant.rs | 33 + tests/ui/rfc-2008-non-exhaustive/variant.stderr | 92 + .../variants_fictive_visibility.rs | 12 + .../rfc-2008-non-exhaustive/variants_same_crate.rs | 18 + .../downcast-unsafe-trait-objects.rs | 23 + .../manual-self-impl-for-unsafe-obj.rs | 66 + .../static-dispatch-unsafe-object.rs | 37 + tests/ui/rfc-2091-track-caller/call-chain.rs | 30 + .../caller-location-fnptr-rt-ctfe-equiv.rs | 32 + .../caller-location-fnptr-rt-ctfe-equiv.stderr | 10 + .../caller-location-intrinsic.rs | 27 + .../rfc-2091-track-caller/const-caller-location.rs | 43 + .../diverging-caller-location.rs | 17 + tests/ui/rfc-2091-track-caller/error-odd-syntax.rs | 5 + .../rfc-2091-track-caller/error-odd-syntax.stderr | 8 + .../error-with-invalid-abi.rs | 11 + .../error-with-invalid-abi.stderr | 15 + tests/ui/rfc-2091-track-caller/error-with-main.rs | 4 + .../rfc-2091-track-caller/error-with-main.stderr | 10 + tests/ui/rfc-2091-track-caller/error-with-naked.rs | 24 + .../rfc-2091-track-caller/error-with-naked.stderr | 28 + tests/ui/rfc-2091-track-caller/error-with-start.rs | 7 + .../rfc-2091-track-caller/error-with-start.stderr | 10 + .../ui/rfc-2091-track-caller/intrinsic-wrapper.rs | 21 + .../ui/rfc-2091-track-caller/macro-declaration.rs | 10 + tests/ui/rfc-2091-track-caller/only-for-fns.rs | 5 + tests/ui/rfc-2091-track-caller/only-for-fns.stderr | 11 + tests/ui/rfc-2091-track-caller/pass.rs | 10 + .../rfc-2091-track-caller/std-panic-locations.rs | 64 + .../track-caller-attribute.rs | 40 + tests/ui/rfc-2091-track-caller/track-caller-ffi.rs | 48 + tests/ui/rfc-2091-track-caller/tracked-closure.rs | 154 + .../tracked-fn-ptr-with-arg.rs | 62 + tests/ui/rfc-2091-track-caller/tracked-fn-ptr.rs | 62 + .../rfc-2091-track-caller/tracked-trait-impls.rs | 77 + .../ui/rfc-2091-track-caller/tracked-trait-obj.rs | 61 + tests/ui/rfc-2093-infer-outlives/cross-crate.rs | 8 + .../ui/rfc-2093-infer-outlives/cross-crate.stderr | 10 + .../rfc-2093-infer-outlives/dont-infer-static.rs | 12 + .../dont-infer-static.stderr | 19 + tests/ui/rfc-2093-infer-outlives/enum.rs | 27 + tests/ui/rfc-2093-infer-outlives/enum.stderr | 26 + tests/ui/rfc-2093-infer-outlives/explicit-dyn.rs | 12 + .../ui/rfc-2093-infer-outlives/explicit-dyn.stderr | 10 + tests/ui/rfc-2093-infer-outlives/explicit-enum.rs | 13 + .../rfc-2093-infer-outlives/explicit-enum.stderr | 10 + .../rfc-2093-infer-outlives/explicit-projection.rs | 13 + .../explicit-projection.stderr | 10 + .../ui/rfc-2093-infer-outlives/explicit-struct.rs | 13 + .../rfc-2093-infer-outlives/explicit-struct.stderr | 10 + tests/ui/rfc-2093-infer-outlives/explicit-union.rs | 14 + .../rfc-2093-infer-outlives/explicit-union.stderr | 10 + tests/ui/rfc-2093-infer-outlives/issue-54467.rs | 17 + tests/ui/rfc-2093-infer-outlives/nested-enum.rs | 13 + .../ui/rfc-2093-infer-outlives/nested-enum.stderr | 10 + tests/ui/rfc-2093-infer-outlives/nested-regions.rs | 8 + .../rfc-2093-infer-outlives/nested-regions.stderr | 12 + tests/ui/rfc-2093-infer-outlives/nested-structs.rs | 12 + .../rfc-2093-infer-outlives/nested-structs.stderr | 10 + tests/ui/rfc-2093-infer-outlives/nested-union.rs | 14 + .../ui/rfc-2093-infer-outlives/nested-union.stderr | 10 + tests/ui/rfc-2093-infer-outlives/privacy.rs | 20 + tests/ui/rfc-2093-infer-outlives/projection.rs | 8 + tests/ui/rfc-2093-infer-outlives/projection.stderr | 10 + tests/ui/rfc-2093-infer-outlives/reference.rs | 8 + tests/ui/rfc-2093-infer-outlives/reference.stderr | 10 + .../rfc-2093-infer-outlives/regions-enum-not-wf.rs | 39 + .../regions-enum-not-wf.stderr | 36 + .../regions-outlives-nominal-type-region-rev.rs | 22 + ...regions-outlives-nominal-type-region-rev.stderr | 20 + .../regions-outlives-nominal-type-region.rs | 22 + .../regions-outlives-nominal-type-region.stderr | 20 + .../regions-outlives-nominal-type-type-rev.rs | 22 + .../regions-outlives-nominal-type-type-rev.stderr | 20 + .../regions-outlives-nominal-type-type.rs | 22 + .../regions-outlives-nominal-type-type.stderr | 20 + .../regions-struct-not-wf.rs | 28 + .../regions-struct-not-wf.stderr | 48 + tests/ui/rfc-2093-infer-outlives/self-dyn.rs | 13 + tests/ui/rfc-2093-infer-outlives/self-dyn.stderr | 10 + tests/ui/rfc-2093-infer-outlives/self-structs.rs | 13 + .../ui/rfc-2093-infer-outlives/self-structs.stderr | 10 + .../crate-path-non-absolute.rs | 11 + .../crate-path-non-absolute.stderr | 15 + .../keyword-crate-as-identifier.rs | 4 + .../keyword-crate-as-identifier.stderr | 9 + .../auxiliary/xcrate.rs | 5 + .../non-existent-1.rs | 5 + .../non-existent-1.stderr | 9 + .../non-existent-2.rs | 6 + .../non-existent-2.stderr | 9 + .../non-existent-3.rs | 5 + .../non-existent-3.stderr | 9 + .../rfc-2126-extern-absolute-paths/not-allowed.rs | 9 + .../not-allowed.stderr | 16 + .../single-segment.rs | 11 + .../single-segment.stderr | 21 + tests/ui/rfc-2294-if-let-guard/bindings.rs | 9 + tests/ui/rfc-2294-if-let-guard/bindings.stderr | 15 + tests/ui/rfc-2294-if-let-guard/feature-gate.rs | 84 + tests/ui/rfc-2294-if-let-guard/feature-gate.stderr | 288 + tests/ui/rfc-2294-if-let-guard/run-pass.rs | 40 + tests/ui/rfc-2294-if-let-guard/typeck.rs | 15 + tests/ui/rfc-2294-if-let-guard/typeck.stderr | 25 + tests/ui/rfc-2294-if-let-guard/warns.rs | 21 + tests/ui/rfc-2294-if-let-guard/warns.stderr | 28 + tests/ui/rfc-2306/convert-id-const-with-gate.rs | 7 + .../dbg-macro-expected-behavior.rs | 67 + .../dbg-macro-expected-behavior.run.stderr | 28 + .../rfc-2361-dbg-macro/dbg-macro-move-semantics.rs | 10 + .../dbg-macro-move-semantics.stderr | 14 + .../rfc-2361-dbg-macro/dbg-macro-requires-debug.rs | 7 + .../dbg-macro-requires-debug.stderr | 17 + .../feature-gate-do_not_recommend.rs | 21 + .../feature-gate-do_not_recommend.stderr | 25 + .../incorrect-locations.rs | 45 + .../incorrect-locations.stderr | 50 + .../rfc-2397-do-not-recommend/unstable-feature.rs | 10 + .../unstable-feature.stderr | 12 + .../mod_file_nonascii_with_path_allowed-aux.rs | 1 + .../ui/rfc-2457/crate_name_nonascii_forbidden-1.rs | 3 + .../crate_name_nonascii_forbidden-1.stderr | 8 + .../ui/rfc-2457/crate_name_nonascii_forbidden-2.rs | 6 + .../crate_name_nonascii_forbidden-2.stderr | 8 + .../ui/rfc-2457/extern_block_nonascii_forbidden.rs | 9 + .../extern_block_nonascii_forbidden.stderr | 34 + tests/ui/rfc-2457/idents-normalized.rs | 7 + tests/ui/rfc-2457/mod_file_nonascii_forbidden.rs | 4 + .../ui/rfc-2457/mod_file_nonascii_forbidden.stderr | 20 + .../mod_file_nonascii_with_path_allowed.rs | 6 + tests/ui/rfc-2457/mod_inline_nonascii_allowed.rs | 7 + tests/ui/rfc-2457/no_mangle_nonascii_forbidden.rs | 20 + .../rfc-2457/no_mangle_nonascii_forbidden.stderr | 21 + .../ast-lowering-does-not-wrap-let-chains.rs | 16 + .../ui/rfc-2497-if-let-chains/ast-pretty-check.rs | 6 + .../rfc-2497-if-let-chains/ast-pretty-check.stdout | 10 + .../rfc-2497-if-let-chains/chains-without-let.rs | 20 + .../chains-without-let.stderr | 33 + .../rfc-2497-if-let-chains/disallowed-positions.rs | 480 + .../disallowed-positions.stderr | 1911 ++++ ...t-let-else-does-not-interact-with-let-chains.rs | 55 + ...t-else-does-not-interact-with-let-chains.stderr | 142 + tests/ui/rfc-2497-if-let-chains/feature-gate.rs | 62 + .../ui/rfc-2497-if-let-chains/feature-gate.stderr | 120 + .../invalid-let-in-a-valid-let-context.rs | 45 + .../invalid-let-in-a-valid-let-context.stderr | 38 + .../irrefutable-lets.disallowed.stderr | 115 + .../ui/rfc-2497-if-let-chains/irrefutable-lets.rs | 78 + tests/ui/rfc-2497-if-let-chains/issue-88498.rs | 16 + tests/ui/rfc-2497-if-let-chains/issue-90722.rs | 11 + tests/ui/rfc-2497-if-let-chains/issue-92145.rs | 11 + tests/ui/rfc-2497-if-let-chains/issue-93150.rs | 8 + tests/ui/rfc-2497-if-let-chains/issue-93150.stderr | 22 + tests/ui/rfc-2497-if-let-chains/issue-99938.rs | 31 + .../rfc-2497-if-let-chains/no-double-assigments.rs | 9 + .../rfc-2497-if-let-chains/protect-precedences.rs | 17 + .../protect-precedences.stderr | 12 + .../ui/rfc-2497-if-let-chains/then-else-blocks.rs | 49 + .../ui/rfc-2565-param-attrs/attr-without-param.rs | 16 + .../rfc-2565-param-attrs/attr-without-param.stderr | 20 + .../ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs | 11 + .../rfc-2565-param-attrs/auxiliary/param-attrs.rs | 43 + ...issue-64682-dropping-first-attrs-in-impl-fns.rs | 21 + tests/ui/rfc-2565-param-attrs/param-attrs-2018.rs | 6 + .../rfc-2565-param-attrs/param-attrs-2018.stderr | 22 + .../ui/rfc-2565-param-attrs/param-attrs-allowed.rs | 101 + .../param-attrs-builtin-attrs.rs | 174 + .../param-attrs-builtin-attrs.stderr | 386 + tests/ui/rfc-2565-param-attrs/param-attrs-cfg.rs | 121 + .../ui/rfc-2565-param-attrs/param-attrs-cfg.stderr | 122 + .../ui/rfc-2565-param-attrs/param-attrs-pretty.rs | 61 + .../proc-macro-cannot-be-used.rs | 66 + .../proc-macro-cannot-be-used.stderr | 176 + .../import-name-type-invalid-format.rs | 9 + .../import-name-type-invalid-format.stderr | 8 + .../import-name-type-multiple.rs | 10 + .../import-name-type-multiple.stderr | 8 + .../import-name-type-unknown-value.rs | 9 + .../import-name-type-unknown-value.stderr | 8 + .../import-name-type-unsupported-link-kind.rs | 17 + .../import-name-type-unsupported-link-kind.stderr | 14 + .../import-name-type-x86-only.rs | 7 + .../import-name-type-x86-only.stderr | 8 + .../ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs | 15 + .../link-ordinal-and-name.stderr | 14 + .../link-ordinal-invalid-format.rs | 13 + .../link-ordinal-invalid-format.stderr | 18 + .../link-ordinal-missing-argument.rs | 13 + .../link-ordinal-missing-argument.stderr | 18 + .../ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs | 14 + .../link-ordinal-multiple.stderr | 26 + .../link-ordinal-not-foreign-fn.rs | 24 + .../link-ordinal-not-foreign-fn.stderr | 20 + .../rfc-2627-raw-dylib/link-ordinal-too-large.rs | 13 + .../link-ordinal-too-large.stderr | 18 + .../link-ordinal-too-many-arguments.rs | 13 + .../link-ordinal-too-many-arguments.stderr | 18 + .../link-ordinal-unsupported-link-kind.rs | 17 + .../link-ordinal-unsupported-link-kind.stderr | 14 + .../ui/rfc-2627-raw-dylib/multiple-declarations.rs | 19 + .../multiple-declarations.stderr | 8 + .../rfc-2627-raw-dylib/raw-dylib-windows-only.rs | 6 + .../raw-dylib-windows-only.stderr | 9 + tests/ui/rfc-2627-raw-dylib/unsupported-abi.rs | 12 + tests/ui/rfc-2627-raw-dylib/unsupported-abi.stderr | 8 + .../assoc-type-const-bound-usage.rs | 14 + tests/ui/rfc-2632-const-trait-impl/assoc-type.rs | 32 + .../ui/rfc-2632-const-trait-impl/assoc-type.stderr | 21 + tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs | 10 + .../rfc-2632-const-trait-impl/attr-misuse.stderr | 14 + .../auxiliary/cross-crate.rs | 23 + .../auxiliary/staged-api.rs | 19 + .../call-const-trait-method-fail.rs | 29 + .../call-const-trait-method-fail.stderr | 15 + .../call-const-trait-method-pass.rs | 43 + .../call-generic-in-impl.rs | 15 + .../call-generic-method-chain.rs | 28 + .../call-generic-method-dup-bound.rs | 31 + .../call-generic-method-fail.rs | 8 + .../call-generic-method-fail.stderr | 15 + .../call-generic-method-nonconst-bound.rs | 17 + .../call-generic-method-nonconst.rs | 26 + .../call-generic-method-nonconst.stderr | 22 + .../call-generic-method-pass.rs | 24 + tests/ui/rfc-2632-const-trait-impl/call.rs | 10 + .../const-and-non-const-impl.rs | 31 + .../const-and-non-const-impl.stderr | 25 + .../const-check-fns-in-const-impl.rs | 16 + .../const-check-fns-in-const-impl.stderr | 11 + .../const-closure-trait-method-fail.rs | 19 + .../const-closure-trait-method-fail.stderr | 23 + .../const-closure-trait-method.rs | 19 + .../ui/rfc-2632-const-trait-impl/const-closures.rs | 30 + .../const-default-method-bodies.rs | 29 + .../const-default-method-bodies.stderr | 15 + .../rfc-2632-const-trait-impl/const-drop-bound.rs | 25 + .../const-drop-fail.precise.stderr | 99 + .../rfc-2632-const-trait-impl/const-drop-fail.rs | 62 + .../const-drop-fail.stock.stderr | 99 + tests/ui/rfc-2632-const-trait-impl/const-drop.rs | 113 + .../const-impl-norecover.rs | 12 + .../const-impl-norecover.stderr | 8 + .../const-impl-recovery.rs | 17 + .../const-impl-recovery.stderr | 26 + .../const-impl-requires-const-trait.rs | 9 + .../const-impl-requires-const-trait.stderr | 14 + .../rfc-2632-const-trait-impl/const-impl-trait.rs | 55 + .../const_derives/derive-const-gate.rs | 4 + .../const_derives/derive-const-gate.stderr | 11 + .../const_derives/derive-const-non-const-type.rs | 13 + .../derive-const-non-const-type.stderr | 15 + .../const_derives/derive-const-use.rs | 19 + .../cross-crate-default-method-body-is-const.rs | 18 + .../cross-crate.gatednc.stderr | 15 + tests/ui/rfc-2632-const-trait-impl/cross-crate.rs | 24 + .../cross-crate.stock.stderr | 12 + .../cross-crate.stocknc.stderr | 15 + .../default-method-body-is-const-body-checking.rs | 17 + ...fault-method-body-is-const-body-checking.stderr | 20 + .../default-method-body-is-const-same-trait-ck.rs | 15 + ...fault-method-body-is-const-same-trait-ck.stderr | 15 + ...default-method-body-is-const-with-staged-api.rs | 17 + .../feature-gate.gated.stderr | 8 + tests/ui/rfc-2632-const-trait-impl/feature-gate.rs | 14 + .../feature-gate.stock.stderr | 21 + tests/ui/rfc-2632-const-trait-impl/gate.rs | 5 + tests/ui/rfc-2632-const-trait-impl/gate.stderr | 12 + .../ui/rfc-2632-const-trait-impl/generic-bound.rs | 30 + .../rfc-2632-const-trait-impl/hir-const-check.rs | 17 + .../hir-const-check.stderr | 12 + .../impl-tilde-const-trait.rs | 9 + .../impl-tilde-const-trait.stderr | 8 + .../impl-with-default-fn-fail.rs | 17 + .../impl-with-default-fn-fail.stderr | 12 + .../impl-with-default-fn-pass.rs | 26 + .../inherent-impl-const-bounds.rs | 22 + .../ui/rfc-2632-const-trait-impl/inherent-impl.rs | 13 + .../rfc-2632-const-trait-impl/inherent-impl.stderr | 22 + tests/ui/rfc-2632-const-trait-impl/issue-100222.rs | 39 + tests/ui/rfc-2632-const-trait-impl/issue-102156.rs | 15 + .../rfc-2632-const-trait-impl/issue-102156.stderr | 19 + tests/ui/rfc-2632-const-trait-impl/issue-102985.rs | 12 + .../rfc-2632-const-trait-impl/issue-102985.stderr | 41 + tests/ui/rfc-2632-const-trait-impl/issue-103677.rs | 5 + tests/ui/rfc-2632-const-trait-impl/issue-79450.rs | 20 + .../rfc-2632-const-trait-impl/issue-79450.stderr | 12 + tests/ui/rfc-2632-const-trait-impl/issue-88155.rs | 13 + .../rfc-2632-const-trait-impl/issue-88155.stderr | 24 + tests/ui/rfc-2632-const-trait-impl/issue-90052.rs | 9 + .../rfc-2632-const-trait-impl/issue-90052.stderr | 14 + tests/ui/rfc-2632-const-trait-impl/issue-92111.rs | 23 + .../issue-92230-wf-super-trait-env.rs | 15 + .../ui/rfc-2632-const-trait-impl/nested-closure.rs | 12 + .../non-const-op-const-closure-non-const-outer.rs | 15 + ...n-const-op-const-closure-non-const-outer.stderr | 11 + .../non-const-op-in-closure-in-const.rs | 18 + ...st-default-bound-non-const-specialized-bound.rs | 46 + ...efault-bound-non-const-specialized-bound.stderr | 18 + .../const-default-const-specialized.rs | 39 + ...onst-default-impl-non-const-specialized-impl.rs | 26 + ...-default-impl-non-const-specialized-impl.stderr | 8 + .../specialization/default-keyword.rs | 15 + .../issue-95186-specialize-on-tilde-const.rs | 37 + ...e-95187-same-trait-bound-different-constness.rs | 45 + .../non-const-default-const-specialized.rs | 39 + .../specializing-constness-2.rs | 31 + .../specializing-constness-2.stderr | 21 + .../specializing-constness.rs | 28 + .../specializing-constness.stderr | 14 + .../staged-api-user-crate.rs | 16 + .../staged-api-user-crate.stderr | 12 + tests/ui/rfc-2632-const-trait-impl/staged-api.rs | 63 + .../staged-api.stable.stderr | 25 + .../staged-api.unstable.stderr | 42 + .../static-const-trait-bound.rs | 18 + .../ui/rfc-2632-const-trait-impl/std-impl-gate.rs | 21 + .../std-impl-gate.stock.stderr | 12 + .../super-traits-fail-2.nn.stderr | 8 + .../super-traits-fail-2.ny.stderr | 8 + .../super-traits-fail-2.rs | 19 + .../super-traits-fail-2.yn.stderr | 19 + .../super-traits-fail-2.yy.stderr | 19 + .../super-traits-fail-3.nn.stderr | 14 + .../super-traits-fail-3.ny.stderr | 8 + .../super-traits-fail-3.rs | 20 + .../super-traits-fail-3.yn.stderr | 8 + .../rfc-2632-const-trait-impl/super-traits-fail.rs | 18 + .../super-traits-fail.stderr | 20 + tests/ui/rfc-2632-const-trait-impl/super-traits.rs | 25 + tests/ui/rfc-2632-const-trait-impl/syntax.rs | 8 + .../tilde-const-and-const-params.rs | 34 + .../tilde-const-and-const-params.stderr | 14 + .../tilde-const-invalid-places.rs | 7 + .../tilde-const-invalid-places.stderr | 8 + .../tilde-const-syntax.rs | 9 + tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs | 6 + .../rfc-2632-const-trait-impl/tilde-twice.stderr | 8 + .../tilde_const_on_impl_bound.rs | 17 + .../trait-default-body-stability.rs | 50 + .../trait-where-clause-const.rs | 31 + .../trait-where-clause-const.stderr | 35 + .../trait-where-clause-run.rs | 41 + .../trait-where-clause-self-referential.rs | 24 + .../trait-where-clause.rs | 26 + .../trait-where-clause.stderr | 35 + .../ui/rfc-2632-const-trait-impl/without-tilde.rs | 6 + .../rfc-2632-const-trait-impl/without-tilde.stderr | 10 + tests/ui/rfcs/rfc-1014-2.rs | 31 + tests/ui/rfcs/rfc-1014.rs | 34 + tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs | 20 + .../termination-trait-for-box-dyn-error.rs | 6 + .../termination-trait-for-empty.rs | 2 + .../termination-trait-for-exitcode.rs | 7 + .../termination-trait-for-impl-termination.rs | 3 + .../termination-trait-for-result-box-error_ok.rs | 6 + .../termination-trait-for-result.rs | 6 + .../termination-trait-for-str.rs | 4 + tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs | 18 + .../rfcs/rfc-2005-default-binding-mode/constref.rs | 40 + .../ui/rfcs/rfc-2005-default-binding-mode/enum.rs | 45 + tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs | 20 + .../rfcs/rfc-2005-default-binding-mode/general.rs | 249 + tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs | 34 + .../ui/rfcs/rfc-2005-default-binding-mode/range.rs | 9 + .../rfc-2005-default-binding-mode/ref-region.rs | 16 + .../rfc-2005-default-binding-mode/reset-mode.rs | 14 + .../ui/rfcs/rfc-2005-default-binding-mode/slice.rs | 25 + .../rfcs/rfc-2005-default-binding-mode/struct.rs | 22 + .../rfc-2005-default-binding-mode/tuple-struct.rs | 19 + .../ui/rfcs/rfc-2005-default-binding-mode/tuple.rs | 12 + tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs | 15 + tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs | 20 + tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs | 32 + tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs | 38 + tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs | 33 + tests/ui/rfcs/rfc-2302-self-struct-ctor.rs | 127 + .../rfcs/rfc-2396-target_feature-11/check-pass.rs | 52 + .../closures-inherit-target_feature.rs | 20 + .../feature-gate-target_feature_11.rs | 6 + .../feature-gate-target_feature_11.stderr | 14 + .../rfc-2396-target_feature-11/fn-ptr.mir.stderr | 18 + tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs | 12 + .../rfc-2396-target_feature-11/fn-ptr.thir.stderr | 18 + .../rfcs/rfc-2396-target_feature-11/fn-traits.rs | 34 + .../rfc-2396-target_feature-11/fn-traits.stderr | 105 + .../rfcs/rfc-2396-target_feature-11/issue-99876.rs | 9 + .../safe-calls.mir.stderr | 83 + .../rfcs/rfc-2396-target_feature-11/safe-calls.rs | 69 + .../safe-calls.thir.stderr | 83 + .../rfcs/rfc-2396-target_feature-11/trait-impl.rs | 21 + .../rfc-2396-target_feature-11/trait-impl.stderr | 11 + ...-2421-unreserve-pure-offsetof-sizeof-alignof.rs | 15 + .../coerce-in-base-expr.rs | 28 + .../feature-gate.rs | 29 + .../feature-gate.stderr | 22 + .../issue-92010-trait-bound-not-satisfied.rs | 12 + .../issue-92010-trait-bound-not-satisfied.stderr | 12 + .../issue-96878.rs | 31 + .../lifetime-update.rs | 43 + .../lifetime-update.stderr | 15 + .../type-generic-update.rs | 56 + .../type-generic-update.stderr | 21 + .../rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs | 23 + tests/ui/rfcs/rfc1445/eq-allows-match.rs | 17 + tests/ui/rfcs/rfc1623-2.rs | 99 + tests/ui/rfcs/rfc1623-2.stderr | 39 + tests/ui/rfcs/rfc1623-3.rs | 14 + tests/ui/rfcs/rfc1623-3.stderr | 35 + tests/ui/rfcs/rfc1623.rs | 75 + tests/ui/rfcs/rfc1717/library-override.rs | 14 + tests/ui/rfcs/rfc1857-drop-order.rs | 224 + tests/ui/rmeta/auxiliary/rmeta-meta.rs | 8 + tests/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs | 8 + tests/ui/rmeta/auxiliary/rmeta-rlib.rs | 5 + tests/ui/rmeta/auxiliary/rmeta-rmeta.rs | 9 + .../emit-artifact-notifications.polonius.stderr | 1 + tests/ui/rmeta/emit-artifact-notifications.rs | 8 + tests/ui/rmeta/emit-artifact-notifications.stderr | 1 + tests/ui/rmeta/emit-metadata-obj.rs | 7 + tests/ui/rmeta/rmeta-lib-pass.rs | 14 + tests/ui/rmeta/rmeta-pass.rs | 15 + tests/ui/rmeta/rmeta-priv-warn.rs | 11 + tests/ui/rmeta/rmeta-rpass.rs | 18 + tests/ui/rmeta/rmeta.rs | 8 + tests/ui/rmeta/rmeta.stderr | 9 + tests/ui/rmeta/rmeta_lib.rs | 14 + tests/ui/rmeta/rmeta_lib.stderr | 4 + tests/ui/rmeta/rmeta_meta_main.rs | 14 + tests/ui/rmeta/rmeta_meta_main.stderr | 9 + tests/ui/runtime/atomic-print.rs | 45 + tests/ui/runtime/backtrace-debuginfo-aux.rs | 14 + tests/ui/runtime/backtrace-debuginfo.rs | 190 + tests/ui/runtime/native-print-no-runtime.rs | 9 + tests/ui/runtime/out-of-stack.rs | 88 + tests/ui/runtime/rt-explody-panic-payloads.rs | 33 + tests/ui/runtime/running-with-no-runtime.rs | 52 + tests/ui/runtime/signal-alternate-stack-cleanup.rs | 37 + tests/ui/runtime/stdout-during-shutdown.rs | 19 + tests/ui/runtime/stdout-during-shutdown.run.stdout | 1 + tests/ui/rust-2018/async-ident-allowed.rs | 11 + tests/ui/rust-2018/async-ident-allowed.stderr | 17 + tests/ui/rust-2018/async-ident.fixed | 79 + tests/ui/rust-2018/async-ident.rs | 79 + tests/ui/rust-2018/async-ident.stderr | 142 + tests/ui/rust-2018/auxiliary/baz.rs | 5 + .../auxiliary/edition-lint-infer-outlives-macro.rs | 6 + tests/ui/rust-2018/auxiliary/edition-lint-paths.rs | 12 + .../auxiliary/macro-use-warned-against.rs | 2 + .../auxiliary/macro-use-warned-against2.rs | 1 + .../ui/rust-2018/auxiliary/remove-extern-crate.rs | 9 + .../auxiliary/suggestions-not-always-applicable.rs | 13 + .../auxiliary/trait-import-suggestions.rs | 5 + tests/ui/rust-2018/dyn-keyword.fixed | 10 + tests/ui/rust-2018/dyn-keyword.rs | 10 + tests/ui/rust-2018/dyn-keyword.stderr | 16 + tests/ui/rust-2018/dyn-trait-compatibility.rs | 8 + tests/ui/rust-2018/dyn-trait-compatibility.stderr | 19 + .../edition-lint-fully-qualified-paths.fixed | 26 + .../edition-lint-fully-qualified-paths.rs | 26 + .../edition-lint-fully-qualified-paths.stderr | 25 + .../edition-lint-infer-outlives-macro.fixed | 137 + .../rust-2018/edition-lint-infer-outlives-macro.rs | 137 + .../edition-lint-infer-outlives-macro.stderr | 110 + .../edition-lint-infer-outlives-multispan.rs | 368 + .../edition-lint-infer-outlives-multispan.stderr | 823 ++ .../ui/rust-2018/edition-lint-infer-outlives.fixed | 795 ++ tests/ui/rust-2018/edition-lint-infer-outlives.rs | 795 ++ .../rust-2018/edition-lint-infer-outlives.stderr | 920 ++ .../edition-lint-nested-empty-paths.fixed | 34 + .../rust-2018/edition-lint-nested-empty-paths.rs | 34 + .../edition-lint-nested-empty-paths.stderr | 52 + tests/ui/rust-2018/edition-lint-nested-paths.fixed | 31 + tests/ui/rust-2018/edition-lint-nested-paths.rs | 31 + .../ui/rust-2018/edition-lint-nested-paths.stderr | 43 + tests/ui/rust-2018/edition-lint-paths-2018.rs | 10 + tests/ui/rust-2018/edition-lint-paths.fixed | 77 + tests/ui/rust-2018/edition-lint-paths.rs | 77 + tests/ui/rust-2018/edition-lint-paths.stderr | 88 + .../rust-2018/edition-lint-uninferable-outlives.rs | 30 + .../rust-2018/extern-crate-idiomatic-in-2018.fixed | 28 + .../ui/rust-2018/extern-crate-idiomatic-in-2018.rs | 28 + .../extern-crate-idiomatic-in-2018.stderr | 15 + tests/ui/rust-2018/extern-crate-idiomatic.fixed | 18 + tests/ui/rust-2018/extern-crate-idiomatic.rs | 18 + .../extern-crate-referenced-by-self-path.fixed | 17 + .../extern-crate-referenced-by-self-path.rs | 17 + tests/ui/rust-2018/extern-crate-rename.fixed | 18 + tests/ui/rust-2018/extern-crate-rename.rs | 18 + tests/ui/rust-2018/extern-crate-rename.stderr | 16 + tests/ui/rust-2018/extern-crate-submod.fixed | 25 + tests/ui/rust-2018/extern-crate-submod.rs | 25 + tests/ui/rust-2018/extern-crate-submod.stderr | 16 + tests/ui/rust-2018/future-proofing-locals.rs | 50 + tests/ui/rust-2018/future-proofing-locals.stderr | 56 + tests/ui/rust-2018/issue-51008-1.rs | 15 + tests/ui/rust-2018/issue-51008.rs | 15 + tests/ui/rust-2018/issue-52202-use-suggestions.rs | 13 + .../rust-2018/issue-52202-use-suggestions.stderr | 21 + tests/ui/rust-2018/issue-54006.rs | 13 + tests/ui/rust-2018/issue-54006.stderr | 17 + ...issue-54400-unused-extern-crate-attr-span.fixed | 14 + .../issue-54400-unused-extern-crate-attr-span.rs | 15 + ...ssue-54400-unused-extern-crate-attr-span.stderr | 18 + tests/ui/rust-2018/local-path-suggestions-2015.rs | 26 + .../rust-2018/local-path-suggestions-2015.stderr | 12 + tests/ui/rust-2018/local-path-suggestions-2018.rs | 21 + .../rust-2018/local-path-suggestions-2018.stderr | 17 + tests/ui/rust-2018/macro-use-warned-against.rs | 14 + tests/ui/rust-2018/macro-use-warned-against.stderr | 27 + tests/ui/rust-2018/proc-macro-crate-in-paths.rs | 16 + tests/ui/rust-2018/remove-extern-crate.fixed | 39 + tests/ui/rust-2018/remove-extern-crate.rs | 39 + tests/ui/rust-2018/remove-extern-crate.stderr | 21 + .../suggestions-not-always-applicable.fixed | 23 + .../rust-2018/suggestions-not-always-applicable.rs | 23 + tests/ui/rust-2018/trait-import-suggestions.rs | 31 + tests/ui/rust-2018/trait-import-suggestions.stderr | 55 + tests/ui/rust-2018/try-ident.fixed | 15 + tests/ui/rust-2018/try-ident.rs | 15 + tests/ui/rust-2018/try-ident.stderr | 26 + tests/ui/rust-2018/try-macro.fixed | 18 + tests/ui/rust-2018/try-macro.rs | 18 + tests/ui/rust-2018/try-macro.stderr | 17 + .../uniform-paths/ambiguity-macros-nested.rs | 21 + .../uniform-paths/ambiguity-macros-nested.stderr | 25 + .../ui/rust-2018/uniform-paths/ambiguity-macros.rs | 19 + .../uniform-paths/ambiguity-macros.stderr | 25 + .../ui/rust-2018/uniform-paths/ambiguity-nested.rs | 16 + .../uniform-paths/ambiguity-nested.stderr | 21 + tests/ui/rust-2018/uniform-paths/ambiguity.rs | 12 + tests/ui/rust-2018/uniform-paths/ambiguity.stderr | 21 + .../uniform-paths/auxiliary/cross-crate.rs | 5 + .../auxiliary/issue-55779-extern-trait.rs | 1 + .../uniform-paths/auxiliary/issue-56596-2.rs | 1 + .../uniform-paths/auxiliary/issue-56596.rs | 1 + .../uniform-paths/auxiliary/issue-87932-a.rs | 3 + .../uniform-paths/block-scoped-shadow-nested.rs | 20 + .../block-scoped-shadow-nested.stderr | 24 + .../rust-2018/uniform-paths/block-scoped-shadow.rs | 21 + .../uniform-paths/block-scoped-shadow.stderr | 60 + tests/ui/rust-2018/uniform-paths/cross-crate.rs | 12 + .../ui/rust-2018/uniform-paths/cross-crate.stderr | 38 + tests/ui/rust-2018/uniform-paths/deadlock.rs | 8 + tests/ui/rust-2018/uniform-paths/deadlock.stderr | 24 + tests/ui/rust-2018/uniform-paths/fn-local-enum.rs | 13 + .../ui/rust-2018/uniform-paths/from-decl-macro.rs | 12 + tests/ui/rust-2018/uniform-paths/issue-54253.rs | 17 + .../ui/rust-2018/uniform-paths/issue-54253.stderr | 9 + tests/ui/rust-2018/uniform-paths/issue-55779.rs | 29 + tests/ui/rust-2018/uniform-paths/issue-56596-2.rs | 11 + tests/ui/rust-2018/uniform-paths/issue-56596.rs | 12 + .../ui/rust-2018/uniform-paths/issue-56596.stderr | 19 + tests/ui/rust-2018/uniform-paths/issue-87932.rs | 15 + .../ui/rust-2018/uniform-paths/issue-87932.stderr | 18 + tests/ui/rust-2018/uniform-paths/macro-rules.rs | 43 + .../ui/rust-2018/uniform-paths/macro-rules.stderr | 35 + tests/ui/rust-2018/uniform-paths/prelude-fail-2.rs | 21 + .../rust-2018/uniform-paths/prelude-fail-2.stderr | 68 + tests/ui/rust-2018/uniform-paths/prelude-fail.rs | 6 + .../ui/rust-2018/uniform-paths/prelude-fail.stderr | 9 + tests/ui/rust-2018/uniform-paths/prelude.rs | 22 + tests/ui/rust-2018/uniform-paths/redundant.rs | 20 + tests/ui/rust-2018/unresolved-asterisk-imports.rs | 6 + .../rust-2018/unresolved-asterisk-imports.stderr | 9 + tests/ui/rust-2021/array-into-iter-ambiguous.fixed | 27 + tests/ui/rust-2021/array-into-iter-ambiguous.rs | 27 + .../ui/rust-2021/array-into-iter-ambiguous.stderr | 16 + .../auxiliary/reserved-prefixes-macro-2018.rs | 25 + .../auxiliary/reserved-prefixes-macro-2021.rs | 25 + .../future-prelude-collision-generic-trait.fixed | 30 + .../future-prelude-collision-generic-trait.rs | 30 + .../future-prelude-collision-generic-trait.stderr | 16 + .../future-prelude-collision-generic.fixed | 37 + .../rust-2021/future-prelude-collision-generic.rs | 37 + .../future-prelude-collision-generic.stderr | 34 + .../future-prelude-collision-imported.fixed | 70 + .../rust-2021/future-prelude-collision-imported.rs | 70 + .../future-prelude-collision-imported.stderr | 43 + .../future-prelude-collision-macros.fixed | 45 + .../rust-2021/future-prelude-collision-macros.rs | 45 + .../future-prelude-collision-macros.stderr | 25 + .../rust-2021/future-prelude-collision-shadow.rs | 32 + .../future-prelude-collision-shadow.stderr | 18 + .../future-prelude-collision-turbofish.fixed | 28 + .../future-prelude-collision-turbofish.rs | 28 + .../future-prelude-collision-turbofish.stderr | 25 + .../rust-2021/future-prelude-collision-unneeded.rs | 60 + tests/ui/rust-2021/future-prelude-collision.fixed | 98 + tests/ui/rust-2021/future-prelude-collision.rs | 98 + tests/ui/rust-2021/future-prelude-collision.stderr | 79 + tests/ui/rust-2021/generic-type-collision.fixed | 18 + tests/ui/rust-2021/generic-type-collision.rs | 18 + tests/ui/rust-2021/generic-type-collision.stderr | 16 + tests/ui/rust-2021/inherent-dyn-collision.fixed | 53 + tests/ui/rust-2021/inherent-dyn-collision.rs | 53 + tests/ui/rust-2021/inherent-dyn-collision.stderr | 16 + tests/ui/rust-2021/inherent-method-collision.rs | 15 + tests/ui/rust-2021/panic.rs | 24 + tests/ui/rust-2021/panic.stderr | 101 + tests/ui/rust-2021/prelude2021.rs | 6 + .../ui/rust-2021/reserved-prefixes-migration.fixed | 38 + tests/ui/rust-2021/reserved-prefixes-migration.rs | 38 + .../rust-2021/reserved-prefixes-migration.stderr | 72 + .../ui/rust-2021/reserved-prefixes-via-macro-2.rs | 21 + .../rust-2021/reserved-prefixes-via-macro-2.stderr | 29 + tests/ui/rust-2021/reserved-prefixes-via-macro.rs | 12 + tests/ui/rust-2021/reserved-prefixes.rs | 36 + tests/ui/rust-2021/reserved-prefixes.stderr | 110 + tests/ui/rustc-error.rs | 6 + tests/ui/rustc-error.stderr | 8 + tests/ui/rustc-rust-log.rs | 11 + tests/ui/rustdoc/README.md | 3 + tests/ui/rustdoc/cfg-rustdoc.rs | 6 + tests/ui/rustdoc/cfg-rustdoc.stderr | 9 + tests/ui/rustdoc/check-doc-alias-attr-location.rs | 32 + .../rustdoc/check-doc-alias-attr-location.stderr | 50 + tests/ui/rustdoc/check-doc-alias-attr.rs | 28 + tests/ui/rustdoc/check-doc-alias-attr.stderr | 108 + tests/ui/rustdoc/deny-invalid-doc-attrs.rs | 7 + tests/ui/rustdoc/deny-invalid-doc-attrs.stderr | 16 + tests/ui/rustdoc/doc-alias-crate-level.rs | 8 + tests/ui/rustdoc/doc-alias-crate-level.stderr | 14 + tests/ui/rustdoc/doc-alias-same-name.rs | 4 + tests/ui/rustdoc/doc-alias-same-name.stderr | 8 + tests/ui/rustdoc/doc-inline-extern-crate.rs | 9 + tests/ui/rustdoc/doc-inline-extern-crate.stderr | 13 + tests/ui/rustdoc/doc-test-attr-pass.rs | 9 + tests/ui/rustdoc/doc-test-attr.rs | 14 + tests/ui/rustdoc/doc-test-attr.stderr | 34 + tests/ui/rustdoc/doc_keyword.rs | 20 + tests/ui/rustdoc/doc_keyword.stderr | 26 + tests/ui/rustdoc/duplicate_doc_alias.rs | 9 + tests/ui/rustdoc/duplicate_doc_alias.stderr | 24 + tests/ui/rustdoc/feature-gate-doc_primitive.rs | 8 + tests/ui/rustdoc/feature-gate-doc_primitive.stderr | 12 + tests/ui/rustdoc/hidden-doc-associated-item.rs | 15 + .../rustdoc/renamed-features-rustdoc_internals.rs | 5 + .../renamed-features-rustdoc_internals.stderr | 19 + tests/ui/rustdoc/unterminated-doc-comment.rs | 1 + tests/ui/rustdoc/unterminated-doc-comment.stderr | 9 + tests/ui/sanitize/address.rs | 18 + tests/ui/sanitize/badfree.rs | 19 + tests/ui/sanitize/cfg.rs | 28 + tests/ui/sanitize/crt-static.rs | 6 + tests/ui/sanitize/crt-static.stderr | 4 + tests/ui/sanitize/hwaddress.rs | 21 + tests/ui/sanitize/incompatible.rs | 7 + tests/ui/sanitize/incompatible.stderr | 4 + tests/ui/sanitize/inline-always.rs | 15 + tests/ui/sanitize/inline-always.stderr | 15 + tests/ui/sanitize/issue-72154-lifetime-markers.rs | 31 + tests/ui/sanitize/leak.rs | 19 + tests/ui/sanitize/memory-eager.rs | 37 + tests/ui/sanitize/memory-passing.rs | 32 + tests/ui/sanitize/memory.rs | 46 + .../ui/sanitize/new-llvm-pass-manager-thin-lto.rs | 26 + tests/ui/sanitize/thread.rs | 57 + tests/ui/sanitize/unsupported-target.rs | 6 + tests/ui/sanitize/unsupported-target.stderr | 4 + tests/ui/sanitize/use-after-scope.rs | 18 + .../emit-notifications.polonius.stderr | 2 + tests/ui/save-analysis/emit-notifications.rs | 7 + tests/ui/save-analysis/emit-notifications.stderr | 2 + tests/ui/save-analysis/issue-26459.rs | 8 + tests/ui/save-analysis/issue-26459.stderr | 9 + tests/ui/save-analysis/issue-37323.rs | 20 + tests/ui/save-analysis/issue-59134-0.rs | 12 + tests/ui/save-analysis/issue-59134-0.stderr | 9 + tests/ui/save-analysis/issue-59134-1.rs | 12 + tests/ui/save-analysis/issue-59134-1.stderr | 9 + tests/ui/save-analysis/issue-63663.rs | 28 + tests/ui/save-analysis/issue-64659.rs | 10 + tests/ui/save-analysis/issue-65411.rs | 15 + tests/ui/save-analysis/issue-65590.rs | 21 + tests/ui/save-analysis/issue-68621.rs | 17 + tests/ui/save-analysis/issue-68621.stderr | 10 + tests/ui/save-analysis/issue-72267.rs | 7 + tests/ui/save-analysis/issue-72267.stderr | 15 + tests/ui/save-analysis/issue-73020.rs | 5 + tests/ui/save-analysis/issue-73020.stderr | 9 + tests/ui/save-analysis/issue-73022.rs | 13 + tests/ui/save-analysis/issue-89066.rs | 28 + tests/ui/save-analysis/issue-89066.stderr | 39 + ...rbitrary-self-types-not-object-safe.curr.stderr | 39 + ...not-object-safe.object_safe_for_dispatch.stderr | 22 + .../self/arbitrary-self-types-not-object-safe.rs | 44 + tests/ui/self/arbitrary_self_types_nested.rs | 36 + .../arbitrary_self_types_pin_lifetime-async.rs | 35 + tests/ui/self/arbitrary_self_types_pin_lifetime.rs | 60 + ...ary_self_types_pin_lifetime_impl_trait-async.rs | 14 + ...self_types_pin_lifetime_impl_trait-async.stderr | 16 + ...arbitrary_self_types_pin_lifetime_impl_trait.rs | 12 + ...trary_self_types_pin_lifetime_impl_trait.stderr | 16 + ...trary_self_types_pin_lifetime_mismatch-async.rs | 21 + ...y_self_types_pin_lifetime_mismatch-async.stderr | 39 + .../arbitrary_self_types_pin_lifetime_mismatch.rs | 19 + ...bitrary_self_types_pin_lifetime_mismatch.stderr | 38 + .../arbitrary_self_types_pointers_and_wrappers.rs | 68 + .../arbitrary_self_types_raw_pointer_struct.rs | 28 + .../self/arbitrary_self_types_raw_pointer_trait.rs | 61 + tests/ui/self/arbitrary_self_types_silly.rs | 21 + .../self/arbitrary_self_types_stdlib_pointers.rs | 54 + tests/ui/self/arbitrary_self_types_struct.rs | 24 + tests/ui/self/arbitrary_self_types_trait.rs | 19 + .../ui/self/arbitrary_self_types_unsized_struct.rs | 16 + tests/ui/self/auxiliary/explicit_self_xcrate.rs | 15 + tests/ui/self/builtin-superkinds-self-type.rs | 20 + tests/ui/self/by-value-self-in-mut-slot.rs | 22 + tests/ui/self/class-missing-self.rs | 16 + tests/ui/self/class-missing-self.stderr | 24 + tests/ui/self/elision/README.md | 75 + tests/ui/self/elision/alias-async.rs | 36 + tests/ui/self/elision/alias.rs | 35 + tests/ui/self/elision/assoc-async.rs | 40 + tests/ui/self/elision/assoc.rs | 39 + tests/ui/self/elision/lt-alias-async.rs | 38 + tests/ui/self/elision/lt-alias.rs | 37 + tests/ui/self/elision/lt-assoc-async.rs | 50 + tests/ui/self/elision/lt-assoc.rs | 43 + tests/ui/self/elision/lt-ref-self-async.rs | 45 + tests/ui/self/elision/lt-ref-self-async.stderr | 92 + tests/ui/self/elision/lt-ref-self.rs | 43 + tests/ui/self/elision/lt-ref-self.stderr | 92 + tests/ui/self/elision/lt-self-async.rs | 49 + tests/ui/self/elision/lt-self.rs | 48 + tests/ui/self/elision/lt-struct-async.rs | 36 + tests/ui/self/elision/lt-struct.rs | 35 + tests/ui/self/elision/multiple-ref-self-async.rs | 44 + tests/ui/self/elision/multiple-ref-self.rs | 43 + tests/ui/self/elision/ref-alias-async.rs | 39 + tests/ui/self/elision/ref-alias.rs | 38 + tests/ui/self/elision/ref-assoc-async.rs | 40 + tests/ui/self/elision/ref-assoc.rs | 39 + tests/ui/self/elision/ref-mut-alias-async.rs | 36 + tests/ui/self/elision/ref-mut-alias.rs | 35 + tests/ui/self/elision/ref-mut-self-async.rs | 45 + tests/ui/self/elision/ref-mut-self-async.stderr | 92 + tests/ui/self/elision/ref-mut-self.rs | 43 + tests/ui/self/elision/ref-mut-self.stderr | 92 + tests/ui/self/elision/ref-mut-struct-async.rs | 38 + tests/ui/self/elision/ref-mut-struct-async.stderr | 77 + tests/ui/self/elision/ref-mut-struct.rs | 36 + tests/ui/self/elision/ref-mut-struct.stderr | 77 + tests/ui/self/elision/ref-self-async.rs | 60 + tests/ui/self/elision/ref-self-async.stderr | 107 + tests/ui/self/elision/ref-self.rs | 58 + tests/ui/self/elision/ref-self.stderr | 107 + tests/ui/self/elision/ref-struct-async.rs | 38 + tests/ui/self/elision/ref-struct-async.stderr | 77 + tests/ui/self/elision/ref-struct.rs | 36 + tests/ui/self/elision/ref-struct.stderr | 77 + tests/ui/self/elision/self-async.rs | 36 + tests/ui/self/elision/self.rs | 35 + tests/ui/self/elision/struct-async.rs | 32 + tests/ui/self/elision/struct.rs | 31 + tests/ui/self/explicit-self-closures.rs | 17 + tests/ui/self/explicit-self-generic.rs | 28 + tests/ui/self/explicit-self-objects-uniq.rs | 21 + tests/ui/self/explicit-self.rs | 71 + tests/ui/self/explicit_self_xcrate_exe.rs | 12 + tests/ui/self/issue-61882-2.rs | 11 + tests/ui/self/issue-61882-2.stderr | 15 + tests/ui/self/issue-61882.rs | 9 + tests/ui/self/issue-61882.stderr | 26 + tests/ui/self/move-self.rs | 19 + .../self/object-safety-sized-self-by-value-self.rs | 39 + .../object-safety-sized-self-generic-method.rs | 39 + .../self/object-safety-sized-self-return-Self.rs | 39 + tests/ui/self/objects-owned-object-owned-method.rs | 23 + .../ui/self/point-at-arbitrary-self-type-method.rs | 9 + .../point-at-arbitrary-self-type-method.stderr | 20 + .../point-at-arbitrary-self-type-trait-method.rs | 10 + ...oint-at-arbitrary-self-type-trait-method.stderr | 21 + tests/ui/self/self-impl-2.rs | 68 + tests/ui/self/self-impl.rs | 30 + tests/ui/self/self-impl.stderr | 15 + tests/ui/self/self-in-mut-slot-default-method.rs | 35 + tests/ui/self/self-in-mut-slot-immediate-value.rs | 23 + tests/ui/self/self-in-typedefs.rs | 38 + tests/ui/self/self-infer.rs | 8 + tests/ui/self/self-infer.stderr | 25 + tests/ui/self/self-re-assign.rs | 17 + tests/ui/self/self-shadowing-import.rs | 16 + tests/ui/self/self-type-param.rs | 19 + tests/ui/self/self-vs-path-ambiguity.rs | 12 + tests/ui/self/self-vs-path-ambiguity.stderr | 8 + tests/ui/self/self_lifetime-async.rs | 14 + tests/ui/self/self_lifetime.rs | 15 + tests/ui/self/self_type_keyword-2.rs | 13 + tests/ui/self/self_type_keyword-2.stderr | 28 + tests/ui/self/self_type_keyword.rs | 41 + tests/ui/self/self_type_keyword.stderr | 86 + tests/ui/self/string-self-append.rs | 14 + tests/ui/self/suggest-self-2.rs | 25 + tests/ui/self/suggest-self-2.stderr | 40 + tests/ui/self/suggest-self.rs | 41 + tests/ui/self/suggest-self.stderr | 30 + tests/ui/self/ufcs-explicit-self.rs | 49 + tests/ui/self/uniq-self-in-mut-slot.rs | 22 + tests/ui/self/where-for-self.rs | 51 + tests/ui/sepcomp/auxiliary/sepcomp-extern-lib.rs | 4 + tests/ui/sepcomp/auxiliary/sepcomp_cci_lib.rs | 6 + tests/ui/sepcomp/auxiliary/sepcomp_lib.rs | 21 + tests/ui/sepcomp/sepcomp-cci.rs | 33 + tests/ui/sepcomp/sepcomp-extern.rs | 33 + tests/ui/sepcomp/sepcomp-fns-backwards.rs | 33 + tests/ui/sepcomp/sepcomp-fns.rs | 30 + tests/ui/sepcomp/sepcomp-lib-lto.rs | 19 + tests/ui/sepcomp/sepcomp-lib.rs | 16 + tests/ui/sepcomp/sepcomp-statics.rs | 31 + tests/ui/sepcomp/sepcomp-unwind.rs | 35 + tests/ui/seq-args.rs | 13 + tests/ui/seq-args.stderr | 31 + tests/ui/shadow-bool.rs | 18 + tests/ui/shadowed-use-visibility.rs | 13 + tests/ui/shadowed/shadowed-lifetime.rs | 24 + tests/ui/shadowed/shadowed-lifetime.stderr | 19 + tests/ui/shadowed/shadowed-trait-methods.rs | 14 + tests/ui/shadowed/shadowed-trait-methods.stderr | 18 + tests/ui/shadowed/shadowed-type-parameter.rs | 30 + tests/ui/shadowed/shadowed-type-parameter.stderr | 29 + tests/ui/shadowed/shadowed-use-visibility.rs | 16 + tests/ui/shadowed/shadowed-use-visibility.stderr | 37 + tests/ui/shadowed/shadowing-in-the-same-pattern.rs | 7 + .../shadowed/shadowing-in-the-same-pattern.stderr | 16 + tests/ui/short-error-format.rs | 9 + tests/ui/short-error-format.stderr | 3 + tests/ui/simd/array-trait.rs | 41 + tests/ui/simd/array-trait.stderr | 10 + tests/ui/simd/array-type.rs | 42 + tests/ui/simd/generics.rs | 85 + tests/ui/simd/intrinsic/float-math-pass.rs | 114 + tests/ui/simd/intrinsic/float-minmax-pass.rs | 52 + tests/ui/simd/intrinsic/generic-arithmetic-2.rs | 103 + .../ui/simd/intrinsic/generic-arithmetic-2.stderr | 93 + tests/ui/simd/intrinsic/generic-arithmetic-pass.rs | 136 + .../intrinsic/generic-arithmetic-saturating-2.rs | 38 + .../generic-arithmetic-saturating-2.stderr | 15 + .../generic-arithmetic-saturating-pass.rs | 91 + tests/ui/simd/intrinsic/generic-as.rs | 48 + tests/ui/simd/intrinsic/generic-bitmask-pass.rs | 62 + tests/ui/simd/intrinsic/generic-bitmask.rs | 69 + tests/ui/simd/intrinsic/generic-bitmask.stderr | 33 + tests/ui/simd/intrinsic/generic-cast-pass.rs | 121 + .../simd/intrinsic/generic-cast-pointer-width.rs | 21 + tests/ui/simd/intrinsic/generic-cast.rs | 43 + tests/ui/simd/intrinsic/generic-cast.stderr | 27 + tests/ui/simd/intrinsic/generic-comparison-pass.rs | 106 + tests/ui/simd/intrinsic/generic-comparison.rs | 67 + tests/ui/simd/intrinsic/generic-comparison.stderr | 111 + tests/ui/simd/intrinsic/generic-elements-pass.rs | 102 + tests/ui/simd/intrinsic/generic-elements.rs | 77 + tests/ui/simd/intrinsic/generic-elements.stderr | 75 + tests/ui/simd/intrinsic/generic-gather-pass.rs | 141 + tests/ui/simd/intrinsic/generic-reduction-pass.rs | 155 + tests/ui/simd/intrinsic/generic-reduction.rs | 58 + tests/ui/simd/intrinsic/generic-reduction.stderr | 63 + tests/ui/simd/intrinsic/generic-select-pass.rs | 195 + tests/ui/simd/intrinsic/generic-select.rs | 63 + tests/ui/simd/intrinsic/generic-select.stderr | 51 + tests/ui/simd/intrinsic/generic-shuffle.rs | 33 + tests/ui/simd/intrinsic/generic-shuffle.stderr | 21 + tests/ui/simd/intrinsic/inlining-issue67557-ice.rs | 26 + tests/ui/simd/intrinsic/inlining-issue67557.rs | 42 + tests/ui/simd/intrinsic/issue-85855.rs | 19 + tests/ui/simd/intrinsic/issue-85855.stderr | 21 + tests/ui/simd/intrinsic/ptr-cast.rs | 33 + tests/ui/simd/issue-17170.rs | 11 + tests/ui/simd/issue-32947.rs | 24 + tests/ui/simd/issue-39720.rs | 22 + tests/ui/simd/issue-85915-simd-ptrs.rs | 67 + tests/ui/simd/issue-89193.rs | 51 + tests/ui/simd/libm_no_std_cant_float.rs | 22 + tests/ui/simd/libm_no_std_cant_float.stderr | 39 + tests/ui/simd/libm_std_can_float.rs | 23 + tests/ui/simd/monomorphize-shuffle-index.rs | 40 + tests/ui/simd/portable-intrinsics-arent-exposed.rs | 9 + .../simd/portable-intrinsics-arent-exposed.stderr | 23 + tests/ui/simd/shuffle-not-out-of-bounds.rs | 87 + tests/ui/simd/shuffle-not-out-of-bounds.stderr | 75 + tests/ui/simd/shuffle.rs | 24 + tests/ui/simd/simd-bitmask.rs | 52 + tests/ui/simd/size-align.rs | 53 + tests/ui/simd/target-feature-mixup.rs | 186 + .../ui/simd/type-generic-monomorphisation-empty.rs | 12 + .../type-generic-monomorphisation-empty.stderr | 4 + ...-generic-monomorphisation-extern-nonnull-ptr.rs | 23 + .../type-generic-monomorphisation-non-primitive.rs | 14 + ...e-generic-monomorphisation-non-primitive.stderr | 4 + .../type-generic-monomorphisation-oversized.rs | 12 + .../type-generic-monomorphisation-oversized.stderr | 4 + .../type-generic-monomorphisation-power-of-two.rs | 10 + .../simd/type-generic-monomorphisation-wide-ptr.rs | 12 + .../type-generic-monomorphisation-wide-ptr.stderr | 4 + tests/ui/simd/type-generic-monomorphisation.rs | 14 + tests/ui/simd/type-generic-monomorphisation.stderr | 4 + tests/ui/simd/type-len.rs | 39 + tests/ui/simd/type-len.stderr | 40 + tests/ui/simd/type-wide-ptr.rs | 12 + tests/ui/simd/type-wide-ptr.stderr | 4 + tests/ui/simd/wasm-simd-indirect.rs | 31 + tests/ui/simple_global_asm.rs | 29 + tests/ui/single-use-lifetime/derive-eq.rs | 11 + tests/ui/single-use-lifetime/fn-types.rs | 16 + tests/ui/single-use-lifetime/fn-types.stderr | 28 + tests/ui/single-use-lifetime/issue-104440.rs | 100 + tests/ui/single-use-lifetime/issue-104440.stderr | 28 + .../single-use-lifetime/one-use-in-fn-argument.rs | 33 + .../one-use-in-fn-argument.stderr | 59 + .../ui/single-use-lifetime/one-use-in-fn-return.rs | 23 + .../one-use-in-inherent-impl-header.rs | 22 + .../one-use-in-inherent-impl-header.stderr | 21 + .../one-use-in-inherent-method-argument.rs | 18 + .../one-use-in-inherent-method-argument.stderr | 35 + .../one-use-in-inherent-method-return.rs | 18 + .../one-use-in-inherent-method-return.stderr | 21 + tests/ui/single-use-lifetime/one-use-in-struct.rs | 28 + .../one-use-in-trait-method-argument.rs | 26 + .../one-use-in-trait-method-argument.stderr | 21 + .../two-uses-in-fn-argument-and-return.rs | 15 + .../two-uses-in-fn-arguments.rs | 16 + .../two-uses-in-inherent-impl-header.rs | 17 + ...-uses-in-inherent-method-argument-and-return.rs | 18 + ...s-in-inherent-method-argument-and-return.stderr | 21 + .../single-use-lifetime/two-uses-in-trait-impl.rs | 22 + tests/ui/single-use-lifetime/zero-uses-in-fn.fixed | 24 + tests/ui/single-use-lifetime/zero-uses-in-fn.rs | 24 + .../ui/single-use-lifetime/zero-uses-in-fn.stderr | 30 + tests/ui/single-use-lifetime/zero-uses-in-impl.rs | 10 + .../single-use-lifetime/zero-uses-in-impl.stderr | 14 + tests/ui/sized-borrowed-pointer.rs | 10 + tests/ui/sized-cycle-note.rs | 7 + tests/ui/sized-cycle-note.stderr | 19 + tests/ui/sized-owned-pointer.rs | 11 + tests/ui/sized/coinductive-1-gat.rs | 14 + tests/ui/sized/coinductive-1.rs | 14 + tests/ui/sized/coinductive-2.rs | 28 + tests/ui/sized/recursive-type-1.rs | 10 + tests/ui/sized/recursive-type-2.rs | 13 + tests/ui/sized/recursive-type-2.stderr | 13 + tests/ui/slightly-nice-generic-literal-messages.rs | 14 + .../slightly-nice-generic-literal-messages.stderr | 14 + tests/ui/span/E0046.rs | 11 + tests/ui/span/E0046.stderr | 12 + tests/ui/span/E0072.rs | 7 + tests/ui/span/E0072.stderr | 17 + tests/ui/span/E0204.rs | 26 + tests/ui/span/E0204.stderr | 43 + tests/ui/span/E0493.rs | 21 + tests/ui/span/E0493.stderr | 11 + tests/ui/span/E0535.rs | 6 + tests/ui/span/E0535.stderr | 11 + tests/ui/span/E0536.rs | 4 + tests/ui/span/E0536.stderr | 9 + tests/ui/span/E0537.rs | 4 + tests/ui/span/E0537.stderr | 9 + tests/ui/span/auxiliary/transitive_dep_three.rs | 9 + tests/ui/span/auxiliary/transitive_dep_two.rs | 3 + .../borrowck-borrow-overloaded-auto-deref-mut.rs | 142 + ...orrowck-borrow-overloaded-auto-deref-mut.stderr | 112 + .../span/borrowck-borrow-overloaded-deref-mut.rs | 60 + .../borrowck-borrow-overloaded-deref-mut.stderr | 47 + .../ui/span/borrowck-call-is-borrow-issue-12224.rs | 62 + .../borrowck-call-is-borrow-issue-12224.stderr | 61 + .../borrowck-call-method-from-mut-aliasable.rs | 21 + .../borrowck-call-method-from-mut-aliasable.stderr | 14 + tests/ui/span/borrowck-fn-in-const-b.rs | 14 + tests/ui/span/borrowck-fn-in-const-b.stderr | 14 + tests/ui/span/borrowck-let-suggestion-suffixes.rs | 59 + .../span/borrowck-let-suggestion-suffixes.stderr | 63 + tests/ui/span/borrowck-object-mutability.rs | 26 + tests/ui/span/borrowck-object-mutability.stderr | 25 + tests/ui/span/borrowck-ref-into-rvalue.fixed | 13 + tests/ui/span/borrowck-ref-into-rvalue.rs | 12 + tests/ui/span/borrowck-ref-into-rvalue.stderr | 20 + tests/ui/span/coerce-suggestions.rs | 23 + tests/ui/span/coerce-suggestions.stderr | 72 + tests/ui/span/destructor-restrictions.rs | 11 + tests/ui/span/destructor-restrictions.stderr | 23 + ...ust-2021-incompatible-closure-captures-93117.rs | 18 + ...2021-incompatible-closure-captures-93117.stderr | 95 + ...ust-2021-incompatible-closure-captures-96258.rs | 15 + ...2021-incompatible-closure-captures-96258.stderr | 24 + tests/ui/span/dropck-object-cycle.rs | 47 + tests/ui/span/dropck-object-cycle.stderr | 15 + tests/ui/span/dropck_arr_cycle_checked.rs | 106 + tests/ui/span/dropck_arr_cycle_checked.stderr | 43 + tests/ui/span/dropck_direct_cycle_with_drop.rs | 44 + tests/ui/span/dropck_direct_cycle_with_drop.stderr | 29 + tests/ui/span/dropck_misc_variants.rs | 37 + tests/ui/span/dropck_misc_variants.stderr | 30 + tests/ui/span/dropck_vec_cycle_checked.rs | 111 + tests/ui/span/dropck_vec_cycle_checked.stderr | 43 + tests/ui/span/gated-features-attr-spans.rs | 7 + tests/ui/span/gated-features-attr-spans.stderr | 12 + tests/ui/span/impl-wrong-item-for-trait.rs | 38 + tests/ui/span/impl-wrong-item-for-trait.stderr | 66 + tests/ui/span/import-ty-params.rs | 23 + tests/ui/span/import-ty-params.stderr | 20 + tests/ui/span/issue-11925.rs | 13 + tests/ui/span/issue-11925.stderr | 9 + tests/ui/span/issue-15480.fixed | 14 + tests/ui/span/issue-15480.rs | 13 + tests/ui/span/issue-15480.stderr | 21 + .../issue-23338-locals-die-before-temps-of-body.rs | 28 + ...ue-23338-locals-die-before-temps-of-body.stderr | 44 + tests/ui/span/issue-23729.rs | 33 + tests/ui/span/issue-23729.stderr | 11 + tests/ui/span/issue-23827.rs | 33 + tests/ui/span/issue-23827.stderr | 11 + tests/ui/span/issue-24356.rs | 27 + tests/ui/span/issue-24356.stderr | 11 + tests/ui/span/issue-24690.rs | 16 + tests/ui/span/issue-24690.stderr | 29 + ...ssue-24805-dropck-child-has-items-via-parent.rs | 37 + ...-24805-dropck-child-has-items-via-parent.stderr | 17 + .../ui/span/issue-24805-dropck-trait-has-items.rs | 57 + .../span/issue-24805-dropck-trait-has-items.stderr | 42 + tests/ui/span/issue-24895-copy-clone-dropck.rs | 29 + tests/ui/span/issue-24895-copy-clone-dropck.stderr | 16 + tests/ui/span/issue-25199.rs | 74 + tests/ui/span/issue-25199.stderr | 15 + tests/ui/span/issue-26656.rs | 42 + tests/ui/span/issue-26656.stderr | 16 + tests/ui/span/issue-27522.rs | 9 + tests/ui/span/issue-27522.stderr | 12 + tests/ui/span/issue-29106.rs | 26 + tests/ui/span/issue-29106.stderr | 29 + tests/ui/span/issue-29595.rs | 7 + tests/ui/span/issue-29595.stderr | 9 + tests/ui/span/issue-33884.rs | 18 + tests/ui/span/issue-33884.stderr | 11 + tests/ui/span/issue-34264.rs | 11 + tests/ui/span/issue-34264.stderr | 102 + tests/ui/span/issue-35987.rs | 14 + tests/ui/span/issue-35987.stderr | 19 + tests/ui/span/issue-36537.rs | 14 + tests/ui/span/issue-36537.stderr | 14 + tests/ui/span/issue-37767.rs | 41 + tests/ui/span/issue-37767.stderr | 78 + tests/ui/span/issue-39018.rs | 38 + tests/ui/span/issue-39018.stderr | 194 + tests/ui/span/issue-39698.rs | 16 + tests/ui/span/issue-39698.stderr | 43 + tests/ui/span/issue-40157.rs | 4 + tests/ui/span/issue-40157.stderr | 13 + .../issue-42234-unknown-receiver-type.full.stderr | 27 + ...-42234-unknown-receiver-type.generic_arg.stderr | 27 + tests/ui/span/issue-42234-unknown-receiver-type.rs | 19 + tests/ui/span/issue-43927-non-ADT-derive.rs | 6 + tests/ui/span/issue-43927-non-ADT-derive.stderr | 21 + tests/ui/span/issue-71363.rs | 19 + tests/ui/span/issue-71363.stderr | 29 + tests/ui/span/issue-81800.rs | 2 + tests/ui/span/issue-81800.stderr | 19 + tests/ui/span/issue28498-reject-ex1.rs | 37 + tests/ui/span/issue28498-reject-ex1.stderr | 17 + tests/ui/span/issue28498-reject-lifetime-param.rs | 36 + .../span/issue28498-reject-lifetime-param.stderr | 17 + tests/ui/span/issue28498-reject-passed-to-fn.rs | 38 + .../ui/span/issue28498-reject-passed-to-fn.stderr | 17 + tests/ui/span/issue28498-reject-trait-bound.rs | 38 + tests/ui/span/issue28498-reject-trait-bound.stderr | 17 + tests/ui/span/lint-unused-unsafe-thir.rs | 61 + tests/ui/span/lint-unused-unsafe-thir.stderr | 50 + tests/ui/span/lint-unused-unsafe.mir.stderr | 1402 +++ tests/ui/span/lint-unused-unsafe.rs | 1100 ++ tests/ui/span/macro-span-replacement.rs | 13 + tests/ui/span/macro-span-replacement.stderr | 19 + tests/ui/span/macro-ty-params.rs | 15 + tests/ui/span/macro-ty-params.stderr | 26 + tests/ui/span/method-and-field-eager-resolution.rs | 15 + .../span/method-and-field-eager-resolution.stderr | 31 + tests/ui/span/missing-unit-argument.rs | 17 + tests/ui/span/missing-unit-argument.stderr | 96 + tests/ui/span/move-closure.rs | 6 + tests/ui/span/move-closure.stderr | 18 + tests/ui/span/multiline-span-E0072.rs | 10 + tests/ui/span/multiline-span-E0072.stderr | 18 + tests/ui/span/multiline-span-simple.rs | 20 + tests/ui/span/multiline-span-simple.stderr | 16 + tests/ui/span/multispan-import-lint.rs | 10 + tests/ui/span/multispan-import-lint.stderr | 15 + tests/ui/span/mut-arg-hint.rs | 22 + tests/ui/span/mut-arg-hint.stderr | 36 + tests/ui/span/mut-ptr-cant-outlive-ref.rs | 15 + tests/ui/span/mut-ptr-cant-outlive-ref.stderr | 14 + tests/ui/span/non-existing-module-import.rs | 3 + tests/ui/span/non-existing-module-import.stderr | 9 + tests/ui/span/pub-struct-field.rs | 10 + tests/ui/span/pub-struct-field.stderr | 20 + tests/ui/span/range-2.rs | 15 + tests/ui/span/range-2.stderr | 25 + tests/ui/span/recursive-type-field.rs | 18 + tests/ui/span/recursive-type-field.stderr | 27 + .../ui/span/regionck-unboxed-closure-lifetimes.rs | 16 + .../span/regionck-unboxed-closure-lifetimes.stderr | 14 + .../span/regions-close-over-borrowed-ref-in-obj.rs | 16 + .../regions-close-over-borrowed-ref-in-obj.stderr | 16 + .../ui/span/regions-close-over-type-parameter-2.rs | 27 + .../regions-close-over-type-parameter-2.stderr | 13 + tests/ui/span/regions-escape-loop-via-variable.rs | 14 + .../span/regions-escape-loop-via-variable.stderr | 13 + tests/ui/span/regions-escape-loop-via-vec.rs | 13 + tests/ui/span/regions-escape-loop-via-vec.stderr | 50 + .../span/regions-infer-borrow-scope-within-loop.rs | 22 + .../regions-infer-borrow-scope-within-loop.stderr | 14 + .../ui/span/send-is-not-static-ensures-scoping.rs | 26 + .../span/send-is-not-static-ensures-scoping.stderr | 29 + tests/ui/span/send-is-not-static-std-sync-2.rs | 39 + tests/ui/span/send-is-not-static-std-sync-2.stderr | 37 + tests/ui/span/send-is-not-static-std-sync.rs | 55 + tests/ui/span/send-is-not-static-std-sync.stderr | 72 + tests/ui/span/slice-borrow.rs | 14 + tests/ui/span/slice-borrow.stderr | 17 + tests/ui/span/suggestion-non-ascii.rs | 4 + tests/ui/span/suggestion-non-ascii.stderr | 9 + tests/ui/span/transitive-dep-span.rs | 15 + tests/ui/span/transitive-dep-span.stderr | 18 + tests/ui/span/type-annotations-needed-expr.rs | 3 + tests/ui/span/type-annotations-needed-expr.stderr | 14 + tests/ui/span/type-binding.rs | 9 + tests/ui/span/type-binding.stderr | 9 + tests/ui/span/typo-suggestion.rs | 9 + tests/ui/span/typo-suggestion.stderr | 15 + .../ui/span/unused-warning-point-at-identifier.rs | 30 + .../span/unused-warning-point-at-identifier.stderr | 33 + .../ui/span/vec-must-not-hide-type-from-dropck.rs | 125 + .../span/vec-must-not-hide-type-from-dropck.stderr | 29 + tests/ui/span/vec_refs_data_with_early_death.rs | 33 + .../ui/span/vec_refs_data_with_early_death.stderr | 31 + tests/ui/span/visibility-ty-params.rs | 13 + tests/ui/span/visibility-ty-params.stderr | 21 + tests/ui/span/wf-method-late-bound-regions.rs | 24 + tests/ui/span/wf-method-late-bound-regions.stderr | 14 + tests/ui/specialization/README-rpass.md | 37 + tests/ui/specialization/README.md | 21 + tests/ui/specialization/assoc-ty-graph-cycle.rs | 25 + .../ui/specialization/assoc-ty-graph-cycle.stderr | 12 + .../auxiliary/cross_crates_defaults.rs | 40 + tests/ui/specialization/auxiliary/go_trait.rs | 43 + .../auxiliary/specialization_cross_crate.rs | 72 + tests/ui/specialization/const_trait_impl.rs | 55 + tests/ui/specialization/cross-crate-defaults.rs | 41 + .../ui/specialization/cross-crate-defaults.stderr | 12 + .../default-associated-type-bound-1.rs | 24 + .../default-associated-type-bound-1.stderr | 26 + .../default-associated-type-bound-2.rs | 22 + .../default-associated-type-bound-2.stderr | 30 + .../default-generic-associated-type-bound.rs | 25 + .../default-generic-associated-type-bound.stderr | 30 + .../defaultimpl/allowed-cross-crate.rs | 26 + .../defaultimpl/allowed-cross-crate.stderr | 12 + .../defaultimpl/auxiliary/go_trait.rs | 43 + .../ui/specialization/defaultimpl/out-of-order.rs | 19 + .../specialization/defaultimpl/out-of-order.stderr | 12 + .../defaultimpl/overlap-projection.rs | 25 + .../defaultimpl/overlap-projection.stderr | 12 + tests/ui/specialization/defaultimpl/projection.rs | 42 + .../specialization/defaultimpl/projection.stderr | 12 + .../specialization-feature-gate-default.rs | 11 + .../specialization-feature-gate-default.stderr | 14 + .../defaultimpl/specialization-no-default.rs | 77 + .../defaultimpl/specialization-no-default.stderr | 68 + ...cialization-trait-item-not-implemented-rpass.rs | 34 + ...ization-trait-item-not-implemented-rpass.stderr | 12 + .../specialization-trait-item-not-implemented.rs | 23 + ...pecialization-trait-item-not-implemented.stderr | 22 + .../specialization-trait-not-implemented.rs | 24 + .../specialization-trait-not-implemented.stderr | 44 + .../defaultimpl/specialization-wfcheck.rs | 10 + .../defaultimpl/specialization-wfcheck.stderr | 29 + tests/ui/specialization/defaultimpl/validation.rs | 16 + .../specialization/defaultimpl/validation.stderr | 51 + tests/ui/specialization/issue-33017.rs | 45 + tests/ui/specialization/issue-33017.stderr | 19 + tests/ui/specialization/issue-35376.rs | 43 + tests/ui/specialization/issue-35376.stderr | 12 + tests/ui/specialization/issue-36804.rs | 35 + tests/ui/specialization/issue-36804.stderr | 12 + tests/ui/specialization/issue-38091-2.rs | 28 + tests/ui/specialization/issue-38091-2.stderr | 24 + tests/ui/specialization/issue-38091.rs | 24 + tests/ui/specialization/issue-38091.stderr | 25 + tests/ui/specialization/issue-39448.rs | 50 + tests/ui/specialization/issue-39448.stderr | 35 + tests/ui/specialization/issue-39618.rs | 27 + tests/ui/specialization/issue-39618.stderr | 12 + tests/ui/specialization/issue-43037.current.stderr | 12 + .../ui/specialization/issue-43037.negative.stderr | 12 + tests/ui/specialization/issue-43037.rs | 22 + tests/ui/specialization/issue-44861.rs | 40 + tests/ui/specialization/issue-44861.stderr | 15 + tests/ui/specialization/issue-45814.current.stderr | 14 + .../ui/specialization/issue-45814.negative.stderr | 14 + tests/ui/specialization/issue-45814.rs | 13 + tests/ui/specialization/issue-50452-fail.rs | 21 + tests/ui/specialization/issue-50452-fail.stderr | 24 + tests/ui/specialization/issue-50452.rs | 19 + tests/ui/specialization/issue-50452.stderr | 12 + tests/ui/specialization/issue-51892.rs | 18 + tests/ui/specialization/issue-51892.stderr | 10 + tests/ui/specialization/issue-52050.rs | 32 + tests/ui/specialization/issue-52050.stderr | 24 + tests/ui/specialization/issue-59435.rs | 17 + tests/ui/specialization/issue-59435.stderr | 19 + tests/ui/specialization/issue-63716-parse-async.rs | 14 + .../specialization/issue-63716-parse-async.stderr | 12 + .../issue-68830-spurious-diagnostics.rs | 23 + .../issue-68830-spurious-diagnostics.stderr | 9 + tests/ui/specialization/issue-70442.rs | 23 + tests/ui/specialization/issue-70442.stderr | 12 + .../auxiliary/specialization-trait.rs | 6 + .../min_specialization/dyn-trait-assoc-types.rs | 32 + .../dyn-trait-assoc-types.stderr | 14 + .../min_specialization/impl-on-nonexisting.rs | 7 + .../min_specialization/impl-on-nonexisting.stderr | 9 + .../impl_specialization_trait.rs | 16 + .../impl_specialization_trait.stderr | 10 + .../implcit-well-formed-bounds.rs | 30 + .../min_specialization/issue-79224.rs | 26 + .../min_specialization/issue-79224.stderr | 27 + .../min_specialization/repeated_projection_type.rs | 24 + .../repeated_projection_type.stderr | 8 + .../min_specialization/repeating_lifetimes.rs | 19 + .../min_specialization/repeating_lifetimes.stderr | 8 + .../min_specialization/repeating_param.rs | 17 + .../min_specialization/repeating_param.stderr | 8 + .../specialization/min_specialization/spec-iter.rs | 20 + .../min_specialization/spec-marker-supertraits.rs | 29 + .../spec-marker-supertraits.stderr | 8 + .../min_specialization/spec-reference.rs | 19 + .../min_specialization/specialization_marker.rs | 17 + .../specialization_marker.stderr | 15 + .../specialization_super_trait.rs | 18 + .../specialization_super_trait.stderr | 8 + .../min_specialization/specialization_trait.rs | 26 + .../min_specialization/specialization_trait.stderr | 20 + .../min_specialization/specialize_on_marker.rs | 24 + .../min_specialization/specialize_on_spec_trait.rs | 27 + .../min_specialization/specialize_on_static.rs | 18 + .../min_specialization/specialize_on_static.stderr | 8 + .../min_specialization/specialize_on_trait.rs | 20 + .../min_specialization/specialize_on_trait.stderr | 8 + tests/ui/specialization/non-defaulted-item-fail.rs | 54 + .../specialization/non-defaulted-item-fail.stderr | 79 + .../soundness/partial_eq_range_inclusive.rs | 35 + .../specialization/soundness/partial_ord_slice.rs | 42 + .../specialization-allowed-cross-crate.rs | 26 + .../specialization-allowed-cross-crate.stderr | 12 + .../ui/specialization/specialization-assoc-fns.rs | 29 + .../specialization/specialization-assoc-fns.stderr | 12 + tests/ui/specialization/specialization-basics.rs | 98 + .../ui/specialization/specialization-basics.stderr | 12 + .../specialization-cross-crate-no-gate.rs | 21 + .../specialization/specialization-cross-crate.rs | 50 + .../specialization-cross-crate.stderr | 12 + .../specialization-default-methods.rs | 87 + .../specialization-default-methods.stderr | 12 + .../specialization-default-projection.rs | 36 + .../specialization-default-projection.stderr | 43 + .../specialization/specialization-default-types.rs | 35 + .../specialization-default-types.stderr | 39 + .../specialization-feature-gate-default.rs | 13 + .../specialization-feature-gate-default.stderr | 12 + .../specialization-feature-gate-overlap.rs | 17 + .../specialization-feature-gate-overlap.stderr | 12 + .../ui/specialization/specialization-no-default.rs | 77 + .../specialization-no-default.stderr | 68 + .../specialization/specialization-on-projection.rs | 24 + .../specialization-on-projection.stderr | 12 + .../specialization/specialization-out-of-order.rs | 19 + .../specialization-out-of-order.stderr | 12 + .../specialization-overlap-hygiene.rs | 23 + .../specialization-overlap-hygiene.stderr | 12 + .../specialization-overlap-negative.rs | 11 + .../specialization-overlap-negative.stderr | 21 + .../specialization-overlap-projection.rs | 25 + .../specialization-overlap-projection.stderr | 12 + tests/ui/specialization/specialization-overlap.rs | 19 + .../specialization/specialization-overlap.stderr | 45 + tests/ui/specialization/specialization-polarity.rs | 17 + .../specialization/specialization-polarity.stderr | 29 + .../specialization-projection-alias.rs | 26 + .../specialization-projection-alias.stderr | 12 + .../ui/specialization/specialization-projection.rs | 42 + .../specialization-projection.stderr | 12 + .../specialization/specialization-supertraits.rs | 17 + .../specialization-supertraits.stderr | 12 + ...ization-translate-projections-with-lifetimes.rs | 33 + ...ion-translate-projections-with-lifetimes.stderr | 12 + ...ialization-translate-projections-with-params.rs | 32 + ...zation-translate-projections-with-params.stderr | 12 + .../specialization-translate-projections.rs | 33 + .../specialization-translate-projections.stderr | 12 + .../ui/specialization/transmute-specialization.rs | 15 + .../specialization/transmute-specialization.stderr | 12 + tests/ui/sse2.rs | 25 + .../accidental-stable-in-unstable.rs | 10 + .../accidental-stable-in-unstable.stderr | 11 + .../stability-attribute/allow-unstable-reexport.rs | 30 + .../allow-unstable-reexport.stderr | 27 + .../allowed-through-unstable.rs | 9 + .../allowed-through-unstable.stderr | 12 + .../auxiliary/allowed-through-unstable-core.rs | 14 + .../auxiliary/ctor-stability.rs | 8 + .../stability-attribute/auxiliary/default_body.rs | 29 + .../auxiliary/lint-stability-reexport.rs | 9 + .../auxiliary/lint-stability.rs | 188 + .../auxiliary/stability-attribute-implies.rs | 8 + .../auxiliary/stability_attribute_issue.rs | 9 + .../auxiliary/stable-in-unstable-core.rs | 8 + .../auxiliary/stable-in-unstable-std.rs | 11 + .../auxiliary/unstable_generic_param.rs | 229 + tests/ui/stability-attribute/ctor-stability.rs | 8 + .../default-body-stability-err.rs | 19 + .../default-body-stability-err.stderr | 38 + .../default-body-stability-ok-enables.rs | 18 + .../default-body-stability-ok-impls.rs | 21 + .../generics-default-stability-trait.rs | 33 + .../generics-default-stability-trait.stderr | 27 + .../generics-default-stability-where.rs | 11 + .../generics-default-stability-where.stderr | 11 + .../generics-default-stability.rs | 251 + .../generics-default-stability.stderr | 469 + tests/ui/stability-attribute/issue-106589.rs | 10 + tests/ui/stability-attribute/issue-106589.stderr | 15 + tests/ui/stability-attribute/issue-28075.rs | 13 + tests/ui/stability-attribute/issue-28075.stderr | 11 + tests/ui/stability-attribute/issue-28388-3.rs | 11 + tests/ui/stability-attribute/issue-28388-3.stderr | 11 + .../issue-99286-stable-intrinsics.rs | 17 + .../stability-attribute/missing-const-stability.rs | 33 + .../missing-const-stability.stderr | 23 + .../missing-stability-attr-at-top-level.rs | 4 + .../missing-stability-attr-at-top-level.stderr | 11 + .../stability-attribute-implies-missing.rs | 10 + .../stability-attribute-implies-missing.stderr | 8 + .../stability-attribute-implies-no-feature.rs | 13 + .../stability-attribute-implies-no-feature.stderr | 21 + .../stability-attribute-implies-using-stable.rs | 15 + ...stability-attribute-implies-using-stable.stderr | 22 + .../stability-attribute-implies-using-unstable.rs | 17 + ...ability-attribute-implies-using-unstable.stderr | 22 + .../stability-attribute-issue-43027.rs | 15 + .../stability-attribute-issue.rs | 12 + .../stability-attribute-issue.stderr | 21 + ...tability-attribute-non-staged-force-unstable.rs | 5 + ...lity-attribute-non-staged-force-unstable.stderr | 15 + .../stability-attribute-non-staged.rs | 3 + .../stability-attribute-non-staged.stderr | 15 + .../stability-attribute-sanity-2.rs | 17 + .../stability-attribute-sanity-2.stderr | 24 + .../stability-attribute-sanity-3.rs | 12 + .../stability-attribute-sanity-3.stderr | 10 + .../stability-attribute-sanity-4.rs | 29 + .../stability-attribute-sanity-4.stderr | 39 + .../stability-attribute-sanity.rs | 76 + .../stability-attribute-sanity.stderr | 136 + .../stability-attribute-trait-impl.rs | 43 + .../stability-attribute-trait-impl.stderr | 31 + .../stability-in-private-module.rs | 4 + .../stability-in-private-module.stderr | 12 + tests/ui/stability-attribute/stable-in-unstable.rs | 54 + .../stability-attribute/stable-in-unstable.stderr | 57 + .../suggest-vec-allocator-api.rs | 9 + .../suggest-vec-allocator-api.stderr | 49 + tests/ui/stable-addr-of.rs | 8 + .../warn-stack-protector-unsupported.all.stderr | 4 + .../warn-stack-protector-unsupported.basic.stderr | 4 + .../warn-stack-protector-unsupported.rs | 19 + .../warn-stack-protector-unsupported.strong.stderr | 4 + tests/ui/static/auxiliary/extern-statics.rs | 4 + tests/ui/static/auxiliary/issue_24843.rs | 1 + tests/ui/static/auxiliary/nested_item.rs | 30 + .../ui/static/auxiliary/static-priv-by-default.rs | 27 + .../ui/static/auxiliary/static_priv_by_default.rs | 51 + tests/ui/static/bad-const-type.rs | 4 + tests/ui/static/bad-const-type.stderr | 11 + tests/ui/static/issue-18118-2.rs | 6 + tests/ui/static/issue-18118-2.stderr | 11 + tests/ui/static/issue-18118.rs | 6 + tests/ui/static/issue-18118.stderr | 14 + tests/ui/static/issue-24843.rs | 8 + tests/ui/static/issue-34194.rs | 11 + tests/ui/static/issue-5216.rs | 10 + tests/ui/static/issue-5216.stderr | 28 + tests/ui/static/nested_item_main.rs | 10 + tests/ui/static/refer-to-other-statics-by-value.rs | 8 + tests/ui/static/safe-extern-statics-mut.mir.stderr | 35 + tests/ui/static/safe-extern-statics-mut.rs | 17 + .../ui/static/safe-extern-statics-mut.thir.stderr | 35 + tests/ui/static/safe-extern-statics.mir.stderr | 35 + tests/ui/static/safe-extern-statics.rs | 17 + tests/ui/static/safe-extern-statics.thir.stderr | 35 + tests/ui/static/static-closures.rs | 4 + tests/ui/static/static-closures.stderr | 9 + tests/ui/static/static-drop-scope.rs | 37 + tests/ui/static/static-drop-scope.stderr | 89 + tests/ui/static/static-extern-type.rs | 27 + tests/ui/static/static-items-cant-move.rs | 19 + tests/ui/static/static-items-cant-move.stderr | 9 + tests/ui/static/static-lifetime-bound.rs | 6 + tests/ui/static/static-lifetime-bound.stderr | 22 + tests/ui/static/static-lifetime.rs | 6 + tests/ui/static/static-lifetime.stderr | 16 + tests/ui/static/static-method-privacy.rs | 10 + tests/ui/static/static-method-privacy.stderr | 12 + tests/ui/static/static-mut-bad-types.rs | 7 + tests/ui/static/static-mut-bad-types.stderr | 12 + .../static-mut-foreign-requires-unsafe.mir.stderr | 27 + .../static/static-mut-foreign-requires-unsafe.rs | 12 + .../static-mut-foreign-requires-unsafe.thir.stderr | 27 + tests/ui/static/static-mut-not-constant.rs | 6 + tests/ui/static/static-mut-not-constant.stderr | 9 + tests/ui/static/static-mut-not-pat.rs | 43 + tests/ui/static/static-mut-not-pat.stderr | 21 + .../static/static-mut-requires-unsafe.mir.stderr | 27 + tests/ui/static/static-mut-requires-unsafe.rs | 10 + .../static/static-mut-requires-unsafe.thir.stderr | 27 + tests/ui/static/static-priv-by-default2.rs | 30 + tests/ui/static/static-priv-by-default2.stderr | 27 + tests/ui/static/static-reference-to-fn-1.rs | 24 + tests/ui/static/static-reference-to-fn-1.stderr | 12 + tests/ui/static/static-reference-to-fn-2.rs | 54 + tests/ui/static/static-reference-to-fn-2.stderr | 49 + tests/ui/static/static-region-bound.rs | 12 + tests/ui/static/static-region-bound.stderr | 13 + tests/ui/static/static-vec-repeat-not-constant.rs | 6 + .../static/static-vec-repeat-not-constant.stderr | 12 + tests/ui/static/static_sized_requirement.rs | 12 + tests/ui/static/thread-local-in-ctfe.rs | 23 + tests/ui/static/thread-local-in-ctfe.stderr | 33 + .../auxiliary/static-function-pointer-aux.rs | 4 + tests/ui/statics/auxiliary/static-methods-crate.rs | 29 + .../statics/auxiliary/static_fn_inline_xc_aux.rs | 12 + .../ui/statics/auxiliary/static_fn_trait_xc_aux.rs | 11 + tests/ui/statics/auxiliary/static_mut_xc.rs | 1 + tests/ui/statics/issue-14227.mir.stderr | 11 + tests/ui/statics/issue-14227.rs | 10 + tests/ui/statics/issue-14227.thir.stderr | 11 + tests/ui/statics/issue-15261.rs | 11 + tests/ui/statics/issue-17233.rs | 17 + tests/ui/statics/issue-17718-static-sync.rs | 12 + tests/ui/statics/issue-17718-static-sync.stderr | 12 + .../statics/issue-17718-static-unsafe-interior.rs | 52 + tests/ui/statics/issue-44373-2.rs | 11 + tests/ui/statics/issue-44373.rs | 5 + tests/ui/statics/issue-44373.stderr | 13 + tests/ui/statics/issue-91050-1.rs | 34 + tests/ui/statics/issue-91050-2.rs | 24 + tests/ui/statics/static-fn-inline-xc.rs | 12 + tests/ui/statics/static-fn-trait-xc.rs | 12 + tests/ui/statics/static-function-pointer-xc.rs | 17 + tests/ui/statics/static-function-pointer.rs | 16 + tests/ui/statics/static-impl.rs | 66 + .../static-method-in-trait-with-tps-intracrate.rs | 28 + tests/ui/statics/static-method-xcrate.rs | 13 + tests/ui/statics/static-methods-in-traits.rs | 26 + tests/ui/statics/static-methods-in-traits2.rs | 22 + tests/ui/statics/static-mut-xc.rs | 39 + tests/ui/statics/static-promotion.rs | 34 + tests/ui/statics/static-recursive.rs | 36 + tests/ui/statics/uninhabited-static.rs | 21 + tests/ui/statics/uninhabited-static.stderr | 91 + tests/ui/stats/hir-stats.rs | 42 + tests/ui/stats/hir-stats.stderr | 178 + tests/ui/std-backtrace.rs | 74 + tests/ui/std-uncopyable-atomics.rs | 16 + tests/ui/std-uncopyable-atomics.stderr | 51 + tests/ui/stdio-is-blocking.rs | 84 + tests/ui/stdlib-unit-tests/builtin-clone.rs | 45 + tests/ui/stdlib-unit-tests/eq-multidispatch.rs | 30 + tests/ui/stdlib-unit-tests/issue-21058.rs | 64 + tests/ui/stdlib-unit-tests/istr.rs | 53 + .../log-knows-the-names-of-variants-in-std.rs | 27 + tests/ui/stdlib-unit-tests/matches2021.rs | 13 + .../minmax-stability-issue-23687.rs | 64 + tests/ui/stdlib-unit-tests/not-sync.rs | 22 + tests/ui/stdlib-unit-tests/not-sync.stderr | 81 + tests/ui/stdlib-unit-tests/raw-fat-ptr.rs | 119 + tests/ui/stdlib-unit-tests/seq-compare.rs | 16 + tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs | 15 + tests/ui/stmt_expr_attrs_no_feature.rs | 141 + tests/ui/stmt_expr_attrs_no_feature.stderr | 84 + tests/ui/str/str-array-assignment.rs | 11 + tests/ui/str/str-array-assignment.stderr | 45 + tests/ui/str/str-as-char.fixed | 5 + tests/ui/str/str-as-char.rs | 5 + tests/ui/str/str-as-char.stderr | 13 + tests/ui/str/str-concat-on-double-ref.rs | 7 + tests/ui/str/str-concat-on-double-ref.stderr | 18 + tests/ui/str/str-escape.rs | 11 + tests/ui/str/str-escape.stderr | 21 + tests/ui/str/str-idx.rs | 7 + tests/ui/str/str-idx.stderr | 54 + tests/ui/str/str-lit-type-mismatch.rs | 5 + tests/ui/str/str-lit-type-mismatch.stderr | 49 + tests/ui/str/str-mut-idx.rs | 17 + tests/ui/str/str-mut-idx.stderr | 78 + tests/ui/str/str-overrun.rs | 10 + tests/ui/string-box-error.rs | 12 + tests/ui/struct-ctor-mangling.rs | 14 + tests/ui/structs-enums/align-enum.rs | 54 + tests/ui/structs-enums/align-struct.rs | 244 + tests/ui/structs-enums/auxiliary/cci_class.rs | 14 + tests/ui/structs-enums/auxiliary/cci_class_2.rs | 19 + tests/ui/structs-enums/auxiliary/cci_class_3.rs | 19 + tests/ui/structs-enums/auxiliary/cci_class_4.rs | 41 + tests/ui/structs-enums/auxiliary/cci_class_6.rs | 25 + tests/ui/structs-enums/auxiliary/cci_class_cast.rs | 50 + .../ui/structs-enums/auxiliary/cci_class_trait.rs | 5 + tests/ui/structs-enums/auxiliary/empty-struct.rs | 9 + .../auxiliary/namespaced_enum_emulate_flat.rs | 25 + .../ui/structs-enums/auxiliary/namespaced_enums.rs | 10 + .../structs-enums/auxiliary/newtype_struct_xc.rs | 3 + .../auxiliary/struct_destructuring_cross_crate.rs | 6 + .../auxiliary/struct_variant_xc_aux.rs | 8 + .../auxiliary/xcrate_struct_aliases.rs | 6 + tests/ui/structs-enums/borrow-tuple-fields.rs | 38 + .../class-cast-to-trait-cross-crate-2.rs | 18 + .../class-cast-to-trait-multiple-types.rs | 94 + tests/ui/structs-enums/class-cast-to-trait.rs | 60 + tests/ui/structs-enums/class-dtor.rs | 25 + tests/ui/structs-enums/class-exports.rs | 31 + .../class-impl-very-parameterized-trait.rs | 107 + .../class-implement-trait-cross-crate.rs | 59 + tests/ui/structs-enums/class-implement-traits.rs | 64 + tests/ui/structs-enums/class-method-cross-crate.rs | 13 + .../ui/structs-enums/class-methods-cross-crate.rs | 14 + tests/ui/structs-enums/class-methods.rs | 30 + .../class-poly-methods-cross-crate.rs | 16 + tests/ui/structs-enums/class-poly-methods.rs | 37 + tests/ui/structs-enums/class-separate-impl.rs | 63 + tests/ui/structs-enums/class-str-field.rs | 21 + tests/ui/structs-enums/class-typarams.rs | 32 + tests/ui/structs-enums/classes-cross-crate.rs | 13 + tests/ui/structs-enums/classes-self-referential.rs | 20 + .../ui/structs-enums/classes-simple-cross-crate.rs | 12 + tests/ui/structs-enums/classes-simple-method.rs | 28 + tests/ui/structs-enums/classes-simple.rs | 23 + tests/ui/structs-enums/classes.rs | 51 + .../ui/structs-enums/codegen-tag-static-padding.rs | 59 + tests/ui/structs-enums/compare-generic-enums.rs | 16 + .../cross-crate-newtype-struct-pat.rs | 12 + tests/ui/structs-enums/discrim-explicit-23030.rs | 145 + tests/ui/structs-enums/empty-struct-braces.rs | 213 + tests/ui/structs-enums/empty-tag.rs | 22 + tests/ui/structs-enums/enum-alignment.rs | 24 + tests/ui/structs-enums/enum-clike-ffi-as-int.rs | 33 + tests/ui/structs-enums/enum-discr.rs | 23 + tests/ui/structs-enums/enum-discrim-autosizing.rs | 53 + .../ui/structs-enums/enum-discrim-manual-sizing.rs | 111 + .../structs-enums/enum-discrim-range-overflow.rs | 26 + tests/ui/structs-enums/enum-discrim-width-stuff.rs | 44 + tests/ui/structs-enums/enum-disr-val-pretty.rs | 17 + tests/ui/structs-enums/enum-export-inheritance.rs | 15 + tests/ui/structs-enums/enum-layout-optimization.rs | 50 + .../enum-non-c-like-repr-c-and-int.rs | 173 + tests/ui/structs-enums/enum-non-c-like-repr-c.rs | 174 + tests/ui/structs-enums/enum-non-c-like-repr-int.rs | 169 + tests/ui/structs-enums/enum-null-pointer-opt.rs | 74 + .../enum-nullable-const-null-with-fields.rs | 13 + .../enum-nullable-simplifycfg-misopt.rs | 16 + tests/ui/structs-enums/enum-univariant-repr.rs | 51 + tests/ui/structs-enums/enum-variants.rs | 18 + tests/ui/structs-enums/enum-vec-initializer.rs | 17 + tests/ui/structs-enums/export-abstract-tag.rs | 15 + tests/ui/structs-enums/export-tag-variant.rs | 9 + tests/ui/structs-enums/expr-if-struct.rs | 32 + tests/ui/structs-enums/expr-match-struct.rs | 31 + tests/ui/structs-enums/field-destruction-order.rs | 47 + tests/ui/structs-enums/foreign-struct.rs | 19 + tests/ui/structs-enums/functional-struct-upd.rs | 15 + tests/ui/structs-enums/issue-1701.rs | 26 + tests/ui/structs-enums/issue-2718-a.rs | 12 + tests/ui/structs-enums/issue-2718-a.stderr | 14 + tests/ui/structs-enums/issue-38002.rs | 35 + tests/ui/structs-enums/issue-50731.rs | 6 + tests/ui/structs-enums/ivec-tag.rs | 22 + .../module-qualified-struct-destructure.rs | 14 + tests/ui/structs-enums/multiple-reprs.rs | 82 + .../namespaced-enum-emulate-flat-xc.rs | 25 + .../structs-enums/namespaced-enum-emulate-flat.rs | 44 + .../namespaced-enum-glob-import-xcrate.rs | 26 + .../structs-enums/namespaced-enum-glob-import.rs | 35 + tests/ui/structs-enums/namespaced-enums-xcrate.rs | 16 + tests/ui/structs-enums/namespaced-enums.rs | 17 + tests/ui/structs-enums/nested-enum-same-names.rs | 27 + tests/ui/structs-enums/newtype-struct-drop-run.rs | 21 + tests/ui/structs-enums/newtype-struct-with-dtor.rs | 20 + tests/ui/structs-enums/newtype-struct-xc-2.rs | 15 + tests/ui/structs-enums/newtype-struct-xc.rs | 10 + tests/ui/structs-enums/nonzero-enum.rs | 30 + tests/ui/structs-enums/numeric-fields.rs | 12 + tests/ui/structs-enums/rec-align-u32.rs | 57 + tests/ui/structs-enums/rec-align-u64.rs | 97 + tests/ui/structs-enums/rec-auto.rs | 14 + tests/ui/structs-enums/rec-extend.rs | 18 + tests/ui/structs-enums/rec-tup.rs | 31 + tests/ui/structs-enums/rec.rs | 24 + tests/ui/structs-enums/record-pat.rs | 19 + tests/ui/structs-enums/resource-in-struct.rs | 37 + tests/ui/structs-enums/simple-generic-tag.rs | 11 + tests/ui/structs-enums/simple-match-generic-tag.rs | 13 + tests/ui/structs-enums/small-enum-range-edge.rs | 27 + tests/ui/structs-enums/small-enums-with-fields.rs | 33 + tests/ui/structs-enums/struct-aliases-xcrate.rs | 25 + tests/ui/structs-enums/struct-aliases.rs | 64 + .../struct-destructuring-cross-crate.rs | 12 + .../struct-enum-ignoring-field-with-underscore.rs | 12 + ...ruct-enum-ignoring-field-with-underscore.stderr | 24 + tests/ui/structs-enums/struct-field-shorthand.rs | 26 + .../structs-enums/struct-like-variant-construct.rs | 18 + .../ui/structs-enums/struct-like-variant-match.rs | 33 + .../struct-lit-functional-no-fields.rs | 26 + tests/ui/structs-enums/struct-literal-dtor.rs | 18 + tests/ui/structs-enums/struct-new-as-field-name.rs | 10 + tests/ui/structs-enums/struct-order-of-eval-1.rs | 16 + tests/ui/structs-enums/struct-order-of-eval-2.rs | 16 + tests/ui/structs-enums/struct-order-of-eval-3.rs | 37 + tests/ui/structs-enums/struct-order-of-eval-4.rs | 34 + tests/ui/structs-enums/struct-partial-move-1.rs | 21 + tests/ui/structs-enums/struct-partial-move-2.rs | 28 + .../structs-enums/struct-path-associated-type.rs | 27 + tests/ui/structs-enums/struct-path-self.rs | 45 + tests/ui/structs-enums/struct-pattern-matching.rs | 18 + tests/ui/structs-enums/struct-rec/issue-74224.rs | 11 + .../ui/structs-enums/struct-rec/issue-74224.stderr | 17 + tests/ui/structs-enums/struct-rec/issue-84611.rs | 11 + .../ui/structs-enums/struct-rec/issue-84611.stderr | 17 + .../struct-rec/mutual-struct-recursion.rs | 21 + .../struct-rec/mutual-struct-recursion.stderr | 49 + .../struct-variant-field-visibility.rs | 17 + tests/ui/structs-enums/struct_variant_xc.rs | 11 + tests/ui/structs-enums/struct_variant_xc_match.rs | 14 + tests/ui/structs-enums/tag-align-dyn-u64.rs | 29 + tests/ui/structs-enums/tag-align-dyn-variants.rs | 67 + tests/ui/structs-enums/tag-align-shape.rs | 21 + tests/ui/structs-enums/tag-align-u64.rs | 29 + tests/ui/structs-enums/tag-disr-val-shape.rs | 20 + tests/ui/structs-enums/tag-exports.rs | 21 + tests/ui/structs-enums/tag-in-block.rs | 15 + .../tag-variant-disr-type-mismatch.rs | 12 + tests/ui/structs-enums/tag-variant-disr-val.rs | 66 + tests/ui/structs-enums/tag.rs | 30 + tests/ui/structs-enums/tuple-struct-construct.rs | 9 + .../tuple-struct-constructor-pointer.rs | 12 + .../ui/structs-enums/tuple-struct-destructuring.rs | 10 + tests/ui/structs-enums/tuple-struct-matching.rs | 13 + tests/ui/structs-enums/tuple-struct-trivial.rs | 8 + tests/ui/structs-enums/type-sizes.rs | 273 + tests/ui/structs-enums/uninstantiable-struct.rs | 4 + .../ui/structs-enums/unit-like-struct-drop-run.rs | 24 + tests/ui/structs-enums/unit-like-struct.rs | 9 + tests/ui/structs-enums/variant-structs-trivial.rs | 10 + tests/ui/structs/auxiliary/struct_field_privacy.rs | 9 + .../ui/structs/auxiliary/struct_variant_privacy.rs | 3 + .../structs/incomplete-fn-in-struct-definition.rs | 5 + .../incomplete-fn-in-struct-definition.stderr | 15 + tests/ui/structs/issue-80853.rs | 7 + tests/ui/structs/issue-80853.stderr | 13 + tests/ui/structs/large-records.rs | 38 + tests/ui/structs/multi-line-fru-suggestion.rs | 22 + tests/ui/structs/multi-line-fru-suggestion.stderr | 25 + tests/ui/structs/rhs-type.rs | 18 + tests/ui/structs/struct-base-wrong-type.rs | 14 + tests/ui/structs/struct-base-wrong-type.stderr | 27 + tests/ui/structs/struct-duplicate-comma.fixed | 15 + tests/ui/structs/struct-duplicate-comma.rs | 15 + tests/ui/structs/struct-duplicate-comma.stderr | 13 + tests/ui/structs/struct-field-cfg.rs | 18 + tests/ui/structs/struct-field-cfg.stderr | 39 + tests/ui/structs/struct-field-init-syntax.rs | 20 + tests/ui/structs/struct-field-init-syntax.stderr | 18 + tests/ui/structs/struct-field-privacy.rs | 38 + tests/ui/structs/struct-field-privacy.stderr | 33 + tests/ui/structs/struct-fields-decl-dupe.rs | 8 + tests/ui/structs/struct-fields-decl-dupe.stderr | 11 + tests/ui/structs/struct-fields-dupe.rs | 10 + tests/ui/structs/struct-fields-dupe.stderr | 11 + tests/ui/structs/struct-fields-hints-no-dupe.rs | 14 + .../ui/structs/struct-fields-hints-no-dupe.stderr | 9 + tests/ui/structs/struct-fields-hints.rs | 13 + tests/ui/structs/struct-fields-hints.stderr | 9 + tests/ui/structs/struct-fields-missing.rs | 10 + tests/ui/structs/struct-fields-missing.stderr | 9 + .../structs/struct-fields-shorthand-unresolved.rs | 12 + .../struct-fields-shorthand-unresolved.stderr | 9 + tests/ui/structs/struct-fields-shorthand.rs | 11 + tests/ui/structs/struct-fields-shorthand.stderr | 11 + tests/ui/structs/struct-fields-too-many.rs | 11 + tests/ui/structs/struct-fields-too-many.stderr | 11 + tests/ui/structs/struct-fields-typo.rs | 15 + tests/ui/structs/struct-fields-typo.stderr | 9 + tests/ui/structs/struct-fn-in-definition.rs | 34 + tests/ui/structs/struct-fn-in-definition.stderr | 39 + tests/ui/structs/struct-missing-comma.fixed | 12 + tests/ui/structs/struct-missing-comma.rs | 12 + tests/ui/structs/struct-missing-comma.stderr | 8 + tests/ui/structs/struct-pat-derived-error.rs | 14 + tests/ui/structs/struct-pat-derived-error.stderr | 31 + tests/ui/structs/struct-path-alias-bounds.rs | 11 + tests/ui/structs/struct-path-alias-bounds.stderr | 19 + tests/ui/structs/struct-path-associated-type.rs | 37 + .../ui/structs/struct-path-associated-type.stderr | 68 + tests/ui/structs/struct-path-self-type-mismatch.rs | 21 + .../structs/struct-path-self-type-mismatch.stderr | 46 + tests/ui/structs/struct-path-self.rs | 37 + tests/ui/structs/struct-path-self.stderr | 80 + tests/ui/structs/struct-record-suggestion.fixed | 33 + tests/ui/structs/struct-record-suggestion.rs | 33 + tests/ui/structs/struct-record-suggestion.stderr | 38 + tests/ui/structs/struct-tuple-field-names.rs | 15 + tests/ui/structs/struct-tuple-field-names.stderr | 25 + tests/ui/structs/struct-variant-privacy-xc.rs | 11 + tests/ui/structs/struct-variant-privacy-xc.stderr | 27 + tests/ui/structs/struct-variant-privacy.rs | 14 + tests/ui/structs/struct-variant-privacy.stderr | 27 + .../structs/structure-constructor-type-mismatch.rs | 73 + .../structure-constructor-type-mismatch.stderr | 137 + tests/ui/structs/suggest-private-fields.rs | 27 + tests/ui/structs/suggest-private-fields.stderr | 29 + ...st-replacing-field-when-specifying-same-type.rs | 28 + ...eplacing-field-when-specifying-same-type.stderr | 94 + tests/ui/structs/unresolved-struct-with-fru.rs | 12 + tests/ui/structs/unresolved-struct-with-fru.stderr | 9 + tests/ui/suggestions/abi-typo.fixed | 6 + tests/ui/suggestions/abi-typo.rs | 6 + tests/ui/suggestions/abi-typo.stderr | 14 + .../adt-param-with-implicit-sized-bound.rs | 28 + .../adt-param-with-implicit-sized-bound.stderr | 112 + .../ui/suggestions/args-instead-of-tuple-errors.rs | 22 + .../args-instead-of-tuple-errors.stderr | 107 + tests/ui/suggestions/args-instead-of-tuple.fixed | 33 + tests/ui/suggestions/args-instead-of-tuple.rs | 33 + tests/ui/suggestions/args-instead-of-tuple.stderr | 125 + tests/ui/suggestions/as-ref-2.rs | 11 + tests/ui/suggestions/as-ref-2.stderr | 18 + tests/ui/suggestions/as-ref.rs | 27 + tests/ui/suggestions/as-ref.stderr | 162 + tests/ui/suggestions/assoc-const-as-field.rs | 13 + tests/ui/suggestions/assoc-const-as-field.stderr | 9 + tests/ui/suggestions/assoc-const-as-fn.rs | 18 + tests/ui/suggestions/assoc-const-as-fn.stderr | 16 + tests/ui/suggestions/assoc-ct-for-assoc-method.rs | 25 + .../suggestions/assoc-ct-for-assoc-method.stderr | 47 + .../ui/suggestions/assoc-type-in-method-return.rs | 7 + .../suggestions/assoc-type-in-method-return.stderr | 9 + tests/ui/suggestions/assoc_fn_without_self.rs | 20 + tests/ui/suggestions/assoc_fn_without_self.stderr | 42 + ...ssed-as-arg-where-it-should-have-been-called.rs | 13 + ...-as-arg-where-it-should-have-been-called.stderr | 43 + tests/ui/suggestions/attribute-typos.rs | 11 + tests/ui/suggestions/attribute-typos.stderr | 29 + tests/ui/suggestions/auxiliary/foo.rs | 3 + tests/ui/suggestions/auxiliary/issue-61963-1.rs | 40 + tests/ui/suggestions/auxiliary/issue-61963.rs | 41 + tests/ui/suggestions/auxiliary/issue-81839.rs | 9 + tests/ui/suggestions/auxiliary/meow.rs | 11 + tests/ui/suggestions/auxiliary/not-object-safe.rs | 6 + .../suggestions/auxiliary/proc-macro-type-error.rs | 18 + tests/ui/suggestions/bad-hex-float-lit.rs | 13 + tests/ui/suggestions/bad-hex-float-lit.stderr | 48 + tests/ui/suggestions/bool_typo_err_suggest.rs | 12 + tests/ui/suggestions/bool_typo_err_suggest.stderr | 25 + tests/ui/suggestions/borrow-for-loop-head.rs | 10 + tests/ui/suggestions/borrow-for-loop-head.stderr | 29 + tests/ui/suggestions/bound-suggestions.fixed | 68 + tests/ui/suggestions/bound-suggestions.rs | 68 + tests/ui/suggestions/bound-suggestions.stderr | 140 + tests/ui/suggestions/box-future-wrong-output.rs | 22 + .../ui/suggestions/box-future-wrong-output.stderr | 14 + tests/ui/suggestions/boxed-variant-field.rs | 15 + tests/ui/suggestions/boxed-variant-field.stderr | 23 + tests/ui/suggestions/call-boxed.rs | 7 + tests/ui/suggestions/call-boxed.stderr | 20 + tests/ui/suggestions/call-on-missing.rs | 39 + tests/ui/suggestions/call-on-missing.stderr | 75 + tests/ui/suggestions/call-on-unimplemented-ctor.rs | 17 + .../suggestions/call-on-unimplemented-ctor.stderr | 21 + .../ui/suggestions/call-on-unimplemented-fn-ptr.rs | 15 + .../call-on-unimplemented-fn-ptr.stderr | 21 + .../call-on-unimplemented-with-autoderef.rs | 13 + .../call-on-unimplemented-with-autoderef.stderr | 21 + .../chain-method-call-mutation-in-place.rs | 4 + .../chain-method-call-mutation-in-place.stderr | 20 + ...lone-on-unconstrained-borrowed-type-param.fixed | 16 + .../clone-on-unconstrained-borrowed-type-param.rs | 15 + ...one-on-unconstrained-borrowed-type-param.stderr | 43 + tests/ui/suggestions/const-in-struct-pat.rs | 11 + tests/ui/suggestions/const-in-struct-pat.stderr | 20 + tests/ui/suggestions/const-no-type.rs | 51 + tests/ui/suggestions/const-no-type.stderr | 44 + .../const-pat-non-exaustive-let-new-var.rs | 11 + .../const-pat-non-exaustive-let-new-var.stderr | 18 + tests/ui/suggestions/constrain-suggest-ice.rs | 11 + tests/ui/suggestions/constrain-suggest-ice.stderr | 72 + tests/ui/suggestions/constrain-trait.fixed | 47 + tests/ui/suggestions/constrain-trait.rs | 47 + tests/ui/suggestions/constrain-trait.stderr | 27 + tests/ui/suggestions/copied-and-cloned.fixed | 23 + tests/ui/suggestions/copied-and-cloned.rs | 23 + tests/ui/suggestions/copied-and-cloned.stderr | 83 + .../core-std-import-order-issue-83564.rs | 10 + .../core-std-import-order-issue-83564.stderr | 16 + tests/ui/suggestions/count2len.rs | 8 + tests/ui/suggestions/count2len.stderr | 36 + tests/ui/suggestions/crate-or-module-typo.rs | 17 + tests/ui/suggestions/crate-or-module-typo.stderr | 43 + tests/ui/suggestions/deref-path-method.rs | 6 + tests/ui/suggestions/deref-path-method.stderr | 14 + tests/ui/suggestions/derive-clone-for-eq.fixed | 18 + tests/ui/suggestions/derive-clone-for-eq.rs | 18 + tests/ui/suggestions/derive-clone-for-eq.stderr | 24 + .../ui/suggestions/derive-macro-missing-bounds.rs | 89 + .../suggestions/derive-macro-missing-bounds.stderr | 113 + .../ui/suggestions/derive-trait-for-method-call.rs | 44 + .../derive-trait-for-method-call.stderr | 105 + ...t-attempt-to-add-suggestions-with-no-changes.rs | 5 + ...tempt-to-add-suggestions-with-no-changes.stderr | 18 + .../dont-suggest-deref-inside-macro-issue-58298.rs | 14 + ...t-suggest-deref-inside-macro-issue-58298.stderr | 13 + .../auxiliary/hidden-child.rs | 8 + .../auxiliary/hidden-parent.rs | 8 + .../hidden-child.rs | 10 + .../hidden-child.stderr | 18 + .../hidden-parent.rs | 7 + .../hidden-parent.stderr | 18 + .../suggestions/dont-suggest-pin-array-dot-set.rs | 15 + .../dont-suggest-pin-array-dot-set.stderr | 9 + .../dont-suggest-ref/duplicate-suggestions.rs | 131 + .../dont-suggest-ref/duplicate-suggestions.stderr | 309 + .../dont-suggest-ref/move-into-closure.rs | 138 + .../dont-suggest-ref/move-into-closure.stderr | 448 + tests/ui/suggestions/dont-suggest-ref/simple.rs | 336 + .../ui/suggestions/dont-suggest-ref/simple.stderr | 985 ++ .../suggestions/dont-suggest-try_into-in-macros.rs | 3 + .../dont-suggest-try_into-in-macros.stderr | 14 + .../ui/suggestions/dont-suggest-ufcs-for-const.rs | 4 + .../suggestions/dont-suggest-ufcs-for-const.stderr | 9 + .../ui/suggestions/dont-try-removing-the-field.rs | 17 + .../suggestions/dont-try-removing-the-field.stderr | 10 + .../suggestions/dont-wrap-ambiguous-receivers.rs | 21 + .../dont-wrap-ambiguous-receivers.stderr | 20 + tests/ui/suggestions/enum-method-probe.fixed | 59 + tests/ui/suggestions/enum-method-probe.rs | 59 + tests/ui/suggestions/enum-method-probe.stderr | 99 + tests/ui/suggestions/enum-variant-arg-mismatch.rs | 10 + .../suggestions/enum-variant-arg-mismatch.stderr | 22 + .../expected-boxed-future-isnt-pinned.rs | 33 + .../expected-boxed-future-isnt-pinned.stderr | 94 + .../field-access-considering-privacy.rs | 35 + .../field-access-considering-privacy.stderr | 14 + tests/ui/suggestions/field-access.fixed | 35 + tests/ui/suggestions/field-access.rs | 35 + tests/ui/suggestions/field-access.stderr | 67 + tests/ui/suggestions/field-has-method.rs | 23 + tests/ui/suggestions/field-has-method.stderr | 17 + ...ssed-as-arg-where-it-should-have-been-called.rs | 20 + ...-as-arg-where-it-should-have-been-called.stderr | 39 + .../ui/suggestions/fn-missing-lifetime-in-item.rs | 8 + .../suggestions/fn-missing-lifetime-in-item.stderr | 48 + .../fn-needing-specified-return-type-param.rs | 7 + .../fn-needing-specified-return-type-param.stderr | 14 + .../fn-or-tuple-struct-with-underscore-args.rs | 19 + .../fn-or-tuple-struct-with-underscore-args.stderr | 38 + .../suggestions/fn-or-tuple-struct-without-args.rs | 47 + .../fn-or-tuple-struct-without-args.stderr | 283 + tests/ui/suggestions/fn-to-method-deeply-nested.rs | 13 + .../suggestions/fn-to-method-deeply-nested.stderr | 39 + tests/ui/suggestions/fn-to-method.rs | 19 + tests/ui/suggestions/fn-to-method.stderr | 38 + tests/ui/suggestions/fn-trait-notation.fixed | 19 + tests/ui/suggestions/fn-trait-notation.rs | 19 + tests/ui/suggestions/fn-trait-notation.stderr | 30 + tests/ui/suggestions/for-i-in-vec.fixed | 27 + tests/ui/suggestions/for-i-in-vec.rs | 27 + tests/ui/suggestions/for-i-in-vec.stderr | 49 + tests/ui/suggestions/format-borrow.rs | 10 + tests/ui/suggestions/format-borrow.stderr | 75 + tests/ui/suggestions/if-let-typo.rs | 11 + tests/ui/suggestions/if-let-typo.stderr | 73 + tests/ui/suggestions/if-then-neeing-semi.rs | 70 + tests/ui/suggestions/if-then-neeing-semi.stderr | 130 + .../suggestions/ignore-nested-field-binding.fixed | 20 + .../ui/suggestions/ignore-nested-field-binding.rs | 20 + .../suggestions/ignore-nested-field-binding.stderr | 20 + .../imm-ref-trait-object-literal-bound-regions.rs | 18 + ...m-ref-trait-object-literal-bound-regions.stderr | 22 + .../ui/suggestions/imm-ref-trait-object-literal.rs | 14 + .../imm-ref-trait-object-literal.stderr | 40 + tests/ui/suggestions/imm-ref-trait-object.rs | 8 + tests/ui/suggestions/imm-ref-trait-object.stderr | 13 + ...plicit-static-bound-needing-more-suggestions.rs | 113 + ...it-static-bound-needing-more-suggestions.stderr | 21 + ...impl-on-dyn-trait-with-implicit-static-bound.rs | 114 + ...-on-dyn-trait-with-implicit-static-bound.stderr | 105 + .../impl-trait-missing-lifetime-gated.rs | 68 + .../impl-trait-missing-lifetime-gated.stderr | 172 + .../ui/suggestions/impl-trait-missing-lifetime.rs | 20 + .../suggestions/impl-trait-missing-lifetime.stderr | 35 + .../impl-trait-return-trailing-semicolon.rs | 21 + .../impl-trait-return-trailing-semicolon.stderr | 24 + .../suggestions/impl-trait-with-missing-bounds.rs | 52 + .../impl-trait-with-missing-bounds.stderr | 117 + ...pl-trait-with-missing-trait-bounds-in-arg.fixed | 20 + .../impl-trait-with-missing-trait-bounds-in-arg.rs | 20 + ...l-trait-with-missing-trait-bounds-in-arg.stderr | 17 + .../ui/suggestions/import-trait-for-method-call.rs | 16 + .../import-trait-for-method-call.stderr | 34 + tests/ui/suggestions/inner_type.fixed | 40 + tests/ui/suggestions/inner_type.rs | 40 + tests/ui/suggestions/inner_type.stderr | 83 + tests/ui/suggestions/inner_type2.rs | 26 + tests/ui/suggestions/inner_type2.stderr | 29 + tests/ui/suggestions/into-convert.rs | 26 + tests/ui/suggestions/into-convert.stderr | 44 + tests/ui/suggestions/into-str.rs | 6 + tests/ui/suggestions/into-str.stderr | 26 + tests/ui/suggestions/invalid-bin-op.rs | 7 + tests/ui/suggestions/invalid-bin-op.stderr | 25 + tests/ui/suggestions/issue-101065.fixed | 14 + tests/ui/suggestions/issue-101065.rs | 14 + tests/ui/suggestions/issue-101065.stderr | 23 + tests/ui/suggestions/issue-101421.rs | 12 + tests/ui/suggestions/issue-101421.stderr | 17 + tests/ui/suggestions/issue-101465.rs | 25 + tests/ui/suggestions/issue-101465.stderr | 25 + tests/ui/suggestions/issue-101623.rs | 25 + tests/ui/suggestions/issue-101623.stderr | 14 + tests/ui/suggestions/issue-101984.rs | 27 + tests/ui/suggestions/issue-101984.stderr | 14 + tests/ui/suggestions/issue-102354.rs | 10 + tests/ui/suggestions/issue-102354.stderr | 19 + tests/ui/suggestions/issue-102892.rs | 25 + tests/ui/suggestions/issue-102892.stderr | 57 + tests/ui/suggestions/issue-103112.rs | 4 + tests/ui/suggestions/issue-103112.stderr | 15 + tests/ui/suggestions/issue-104086-suggest-let.rs | 30 + .../ui/suggestions/issue-104086-suggest-let.stderr | 135 + tests/ui/suggestions/issue-104287.rs | 13 + tests/ui/suggestions/issue-104287.stderr | 30 + tests/ui/suggestions/issue-104327.rs | 12 + tests/ui/suggestions/issue-104327.stderr | 17 + tests/ui/suggestions/issue-104328.rs | 12 + tests/ui/suggestions/issue-104328.stderr | 17 + tests/ui/suggestions/issue-105226.rs | 22 + tests/ui/suggestions/issue-105226.stderr | 31 + tests/ui/suggestions/issue-105494.rs | 22 + tests/ui/suggestions/issue-105494.stderr | 54 + tests/ui/suggestions/issue-105645.rs | 8 + tests/ui/suggestions/issue-105645.stderr | 18 + .../issue-105761-suggest-self-for-closure.fixed | 28 + .../issue-105761-suggest-self-for-closure.rs | 28 + .../issue-105761-suggest-self-for-closure.stderr | 49 + .../suggestions/issue-106443-sugg-clone-for-arg.rs | 23 + .../issue-106443-sugg-clone-for-arg.stderr | 35 + .../issue-106443-sugg-clone-for-bound.rs | 20 + .../issue-106443-sugg-clone-for-bound.stderr | 29 + tests/ui/suggestions/issue-21673.rs | 13 + tests/ui/suggestions/issue-21673.stderr | 29 + ...055-missing-semicolon-between-call-and-tuple.rs | 8 + ...missing-semicolon-between-call-and-tuple.stderr | 16 + tests/ui/suggestions/issue-52820.fixed | 15 + tests/ui/suggestions/issue-52820.rs | 15 + tests/ui/suggestions/issue-52820.stderr | 23 + tests/ui/suggestions/issue-53692.fixed | 20 + tests/ui/suggestions/issue-53692.rs | 20 + tests/ui/suggestions/issue-53692.stderr | 26 + tests/ui/suggestions/issue-57672.rs | 14 + tests/ui/suggestions/issue-59819.fixed | 35 + tests/ui/suggestions/issue-59819.rs | 35 + tests/ui/suggestions/issue-59819.stderr | 38 + tests/ui/suggestions/issue-61226.fixed | 6 + tests/ui/suggestions/issue-61226.rs | 6 + tests/ui/suggestions/issue-61226.stderr | 12 + tests/ui/suggestions/issue-61963.rs | 37 + tests/ui/suggestions/issue-61963.stderr | 98 + tests/ui/suggestions/issue-62843.rs | 5 + tests/ui/suggestions/issue-62843.stderr | 20 + tests/ui/suggestions/issue-64252-self-type.rs | 14 + tests/ui/suggestions/issue-64252-self-type.stderr | 34 + .../issue-66968-suggest-sorted-words.rs | 4 + .../issue-66968-suggest-sorted-words.stderr | 9 + tests/ui/suggestions/issue-68049-1.rs | 16 + tests/ui/suggestions/issue-68049-1.stderr | 9 + tests/ui/suggestions/issue-68049-2.rs | 21 + tests/ui/suggestions/issue-68049-2.stderr | 25 + tests/ui/suggestions/issue-71394-no-from-impl.rs | 5 + .../ui/suggestions/issue-71394-no-from-impl.stderr | 14 + tests/ui/suggestions/issue-72766.rs | 20 + tests/ui/suggestions/issue-72766.stderr | 15 + ...3-impl-trait-with-missing-bounds-on-async-fn.rs | 32 + ...pl-trait-with-missing-bounds-on-async-fn.stderr | 41 + tests/ui/suggestions/issue-81098.rs | 13 + tests/ui/suggestions/issue-81098.stderr | 25 + tests/ui/suggestions/issue-81839.rs | 17 + tests/ui/suggestions/issue-81839.stderr | 27 + tests/ui/suggestions/issue-82361.fixed | 24 + tests/ui/suggestions/issue-82361.rs | 24 + tests/ui/suggestions/issue-82361.stderr | 56 + tests/ui/suggestions/issue-82566-1.rs | 21 + tests/ui/suggestions/issue-82566-1.stderr | 35 + tests/ui/suggestions/issue-82566-2.rs | 31 + tests/ui/suggestions/issue-82566-2.stderr | 35 + tests/ui/suggestions/issue-83892.fixed | 11 + tests/ui/suggestions/issue-83892.rs | 11 + tests/ui/suggestions/issue-83892.stderr | 14 + tests/ui/suggestions/issue-83943.fixed | 9 + tests/ui/suggestions/issue-83943.rs | 9 + tests/ui/suggestions/issue-83943.stderr | 17 + tests/ui/suggestions/issue-84592.rs | 17 + tests/ui/suggestions/issue-84592.stderr | 17 + tests/ui/suggestions/issue-84700.rs | 26 + tests/ui/suggestions/issue-84700.stderr | 19 + tests/ui/suggestions/issue-84973-2.rs | 13 + tests/ui/suggestions/issue-84973-2.stderr | 21 + tests/ui/suggestions/issue-84973-blacklist.rs | 28 + tests/ui/suggestions/issue-84973-blacklist.stderr | 80 + tests/ui/suggestions/issue-84973-negative.rs | 12 + tests/ui/suggestions/issue-84973-negative.stderr | 36 + tests/ui/suggestions/issue-84973.rs | 33 + tests/ui/suggestions/issue-84973.stderr | 24 + tests/ui/suggestions/issue-85347.rs | 9 + tests/ui/suggestions/issue-85347.stderr | 26 + ...-suggest-unsized-indirection-in-where-clause.rs | 9 + ...gest-unsized-indirection-in-where-clause.stderr | 23 + ...check-where-clause-before-suggesting-unsized.rs | 8 + ...k-where-clause-before-suggesting-unsized.stderr | 18 + .../suggestions/issue-86100-tuple-paren-comma.rs | 25 + .../issue-86100-tuple-paren-comma.stderr | 62 + tests/ui/suggestions/issue-86667.rs | 17 + tests/ui/suggestions/issue-86667.stderr | 36 + tests/ui/suggestions/issue-88730.rs | 15 + tests/ui/suggestions/issue-88730.stderr | 17 + tests/ui/suggestions/issue-89064.rs | 35 + tests/ui/suggestions/issue-89064.stderr | 77 + tests/ui/suggestions/issue-89333.rs | 11 + tests/ui/suggestions/issue-89333.stderr | 15 + .../issue-90213-expected-boxfuture-self-ice.rs | 13 + .../issue-90213-expected-boxfuture-self-ice.stderr | 24 + tests/ui/suggestions/issue-90974.rs | 3 + tests/ui/suggestions/issue-90974.stderr | 14 + tests/ui/suggestions/issue-96223.rs | 52 + tests/ui/suggestions/issue-96223.stderr | 31 + tests/ui/suggestions/issue-96555.rs | 19 + tests/ui/suggestions/issue-96555.stderr | 66 + tests/ui/suggestions/issue-97677.fixed | 8 + tests/ui/suggestions/issue-97677.rs | 8 + tests/ui/suggestions/issue-97677.stderr | 16 + tests/ui/suggestions/issue-97704.fixed | 19 + tests/ui/suggestions/issue-97704.rs | 19 + tests/ui/suggestions/issue-97704.stderr | 15 + tests/ui/suggestions/issue-97760.rs | 9 + tests/ui/suggestions/issue-97760.stderr | 18 + tests/ui/suggestions/issue-98500.rs | 14 + tests/ui/suggestions/issue-98500.stderr | 24 + tests/ui/suggestions/issue-99080.rs | 16 + tests/ui/suggestions/issue-99080.stderr | 20 + tests/ui/suggestions/issue-99240-2.rs | 10 + tests/ui/suggestions/issue-99240-2.stderr | 21 + tests/ui/suggestions/issue-99240.rs | 6 + tests/ui/suggestions/issue-99240.stderr | 11 + .../js-style-comparison-op-separate-eq-token.rs | 5 + ...js-style-comparison-op-separate-eq-token.stderr | 8 + tests/ui/suggestions/js-style-comparison-op.fixed | 8 + tests/ui/suggestions/js-style-comparison-op.rs | 8 + tests/ui/suggestions/js-style-comparison-op.stderr | 14 + .../ui/suggestions/let-binding-init-expr-as-ty.rs | 11 + .../suggestions/let-binding-init-expr-as-ty.stderr | 34 + tests/ui/suggestions/lifetimes/issue-105544.fixed | 45 + tests/ui/suggestions/lifetimes/issue-105544.rs | 45 + tests/ui/suggestions/lifetimes/issue-105544.stderr | 110 + .../missing-lifetimes-in-signature-2.fixed | 29 + .../lifetimes/missing-lifetimes-in-signature-2.rs | 29 + .../missing-lifetimes-in-signature-2.stderr | 30 + ...ssing-lifetimes-in-signature-before-const.fixed | 10 + .../missing-lifetimes-in-signature-before-const.rs | 10 + ...sing-lifetimes-in-signature-before-const.stderr | 15 + .../lifetimes/missing-lifetimes-in-signature.rs | 111 + .../missing-lifetimes-in-signature.stderr | 168 + .../lifetimes/trait-object-nested-in-impl-trait.rs | 72 + .../trait-object-nested-in-impl-trait.stderr | 78 + tests/ui/suggestions/many-type-ascription.rs | 4 + tests/ui/suggestions/many-type-ascription.stderr | 12 + tests/ui/suggestions/match-ergonomics.rs | 41 + tests/ui/suggestions/match-ergonomics.stderr | 68 + tests/ui/suggestions/match-needing-semi.rs | 21 + tests/ui/suggestions/match-needing-semi.stderr | 37 + .../ui/suggestions/match-prev-arm-needing-semi.rs | 66 + .../suggestions/match-prev-arm-needing-semi.stderr | 127 + ...-different-arm-types-as-stmt-instead-of-expr.rs | 30 + ...ferent-arm-types-as-stmt-instead-of-expr.stderr | 51 + .../method-access-to-range-literal-typo.fixed | 34 + .../method-access-to-range-literal-typo.rs | 34 + .../method-access-to-range-literal-typo.stderr | 48 + tests/ui/suggestions/method-missing-parentheses.rs | 5 + .../suggestions/method-missing-parentheses.stderr | 20 + .../suggestions/mismatched-types-numeric-from.rs | 3 + .../mismatched-types-numeric-from.stderr | 11 + .../missing-assoc-fn-applicable-suggestions.fixed | 21 + .../missing-assoc-fn-applicable-suggestions.rs | 18 + .../missing-assoc-fn-applicable-suggestions.stderr | 16 + tests/ui/suggestions/missing-assoc-fn.rs | 22 + tests/ui/suggestions/missing-assoc-fn.stderr | 36 + .../missing-assoc-type-bound-restriction.rs | 21 + .../missing-bound-in-derive-copy-impl-2.fixed | 16 + .../missing-bound-in-derive-copy-impl-2.rs | 16 + .../missing-bound-in-derive-copy-impl-2.stderr | 19 + .../missing-bound-in-derive-copy-impl-3.fixed | 16 + .../missing-bound-in-derive-copy-impl-3.rs | 16 + .../missing-bound-in-derive-copy-impl-3.stderr | 27 + .../missing-bound-in-derive-copy-impl.rs | 15 + .../missing-bound-in-derive-copy-impl.stderr | 27 + .../missing-bound-in-manual-copy-impl-2.fixed | 19 + .../missing-bound-in-manual-copy-impl-2.rs | 19 + .../missing-bound-in-manual-copy-impl-2.stderr | 22 + .../missing-bound-in-manual-copy-impl.fixed | 9 + .../missing-bound-in-manual-copy-impl.rs | 9 + .../missing-bound-in-manual-copy-impl.stderr | 17 + .../missing-lifetime-in-assoc-const-type.rs | 16 + .../missing-lifetime-in-assoc-const-type.stderr | 57 + tests/ui/suggestions/missing-lifetime-specifier.rs | 57 + .../suggestions/missing-lifetime-specifier.stderr | 319 + tests/ui/suggestions/missing-lt-for-hrtb.rs | 13 + tests/ui/suggestions/missing-lt-for-hrtb.stderr | 36 + tests/ui/suggestions/missing-trait-item.fixed | 20 + tests/ui/suggestions/missing-trait-item.rs | 16 + tests/ui/suggestions/missing-trait-item.stderr | 25 + .../missing-type-param-used-in-param.fixed | 8 + .../missing-type-param-used-in-param.rs | 8 + .../missing-type-param-used-in-param.stderr | 21 + .../move-generic-to-trait-in-method-with-params.rs | 18 + ...e-generic-to-trait-in-method-with-params.stderr | 24 + tests/ui/suggestions/multibyte-escapes.rs | 18 + tests/ui/suggestions/multibyte-escapes.stderr | 33 + tests/ui/suggestions/mut-borrow-needed-by-trait.rs | 22 + .../suggestions/mut-borrow-needed-by-trait.stderr | 40 + tests/ui/suggestions/mut-ref-reassignment.rs | 17 + tests/ui/suggestions/mut-ref-reassignment.stderr | 55 + tests/ui/suggestions/negative-literal-index.fixed | 22 + tests/ui/suggestions/negative-literal-index.rs | 22 + tests/ui/suggestions/negative-literal-index.stderr | 35 + .../suggestions/nested-non-tuple-tuple-struct.rs | 18 + .../nested-non-tuple-tuple-struct.stderr | 116 + tests/ui/suggestions/no-extern-crate-in-type.rs | 7 + .../ui/suggestions/no-extern-crate-in-type.stderr | 14 + ...nt-field-present-in-subfield-recursion-limit.rs | 43 + ...ield-present-in-subfield-recursion-limit.stderr | 11 + .../non-existent-field-present-in-subfield.fixed | 42 + .../non-existent-field-present-in-subfield.rs | 42 + .../non-existent-field-present-in-subfield.stderr | 27 + .../object-unsafe-trait-references-self.rs | 12 + .../object-unsafe-trait-references-self.stderr | 35 + .../object-unsafe-trait-should-use-self.rs | 16 + .../object-unsafe-trait-should-use-self.stderr | 65 + ...bject-unsafe-trait-should-use-where-sized.fixed | 13 + .../object-unsafe-trait-should-use-where-sized.rs | 13 + ...ject-unsafe-trait-should-use-where-sized.stderr | 41 + tests/ui/suggestions/opaque-type-error.rs | 24 + tests/ui/suggestions/opaque-type-error.stderr | 31 + .../option-content-move-from-tuple-match.rs | 9 + .../option-content-move-from-tuple-match.stderr | 20 + tests/ui/suggestions/option-content-move.rs | 37 + tests/ui/suggestions/option-content-move.stderr | 35 + tests/ui/suggestions/option-content-move2.rs | 16 + tests/ui/suggestions/option-content-move2.stderr | 20 + tests/ui/suggestions/option-to-bool.rs | 9 + tests/ui/suggestions/option-to-bool.stderr | 18 + .../suggestions/parenthesized-deref-suggestion.rs | 11 + .../parenthesized-deref-suggestion.stderr | 22 + tests/ui/suggestions/path-by-value.rs | 6 + tests/ui/suggestions/path-by-value.stderr | 17 + tests/ui/suggestions/path-display.rs | 11 + tests/ui/suggestions/path-display.stderr | 23 + tests/ui/suggestions/pattern-slice-vec.fixed | 31 + tests/ui/suggestions/pattern-slice-vec.rs | 31 + tests/ui/suggestions/pattern-slice-vec.stderr | 44 + .../pattern-struct-with-slice-vec-field.rs | 35 + .../pattern-struct-with-slice-vec-field.stderr | 15 + tests/ui/suggestions/private-field.rs | 19 + tests/ui/suggestions/private-field.stderr | 11 + tests/ui/suggestions/raw-byte-string-prefix.rs | 10 + tests/ui/suggestions/raw-byte-string-prefix.stderr | 20 + tests/ui/suggestions/raw-name-use-suggestion.rs | 9 + .../ui/suggestions/raw-name-use-suggestion.stderr | 36 + .../recover-from-semicolon-trailing-item.rs | 16 + .../recover-from-semicolon-trailing-item.stderr | 53 + tests/ui/suggestions/recover-invalid-float.fixed | 10 + tests/ui/suggestions/recover-invalid-float.rs | 10 + tests/ui/suggestions/recover-invalid-float.stderr | 20 + ...r-missing-turbofish-surrounding-angle-braket.rs | 10 + ...ssing-turbofish-surrounding-angle-braket.stderr | 46 + tests/ui/suggestions/ref-pattern-binding.fixed | 19 + tests/ui/suggestions/ref-pattern-binding.rs | 19 + tests/ui/suggestions/ref-pattern-binding.stderr | 107 + ...val-of-multiline-trait-bound-in-where-clause.rs | 30 + ...of-multiline-trait-bound-in-where-clause.stderr | 83 + tests/ui/suggestions/remove-as_str.rs | 21 + tests/ui/suggestions/remove-as_str.stderr | 27 + tests/ui/suggestions/restrict-type-argument.rs | 31 + tests/ui/suggestions/restrict-type-argument.stderr | 111 + tests/ui/suggestions/restrict-type-not-param.rs | 12 + .../ui/suggestions/restrict-type-not-param.stderr | 23 + tests/ui/suggestions/return-bindings-multi.rs | 9 + tests/ui/suggestions/return-bindings-multi.stderr | 34 + tests/ui/suggestions/return-bindings.rs | 51 + tests/ui/suggestions/return-bindings.stderr | 110 + tests/ui/suggestions/return-closures.rs | 13 + tests/ui/suggestions/return-closures.stderr | 27 + tests/ui/suggestions/return-cycle-2.rs | 14 + tests/ui/suggestions/return-cycle-2.stderr | 12 + tests/ui/suggestions/return-cycle.rs | 14 + tests/ui/suggestions/return-cycle.stderr | 12 + tests/ui/suggestions/return-elided-lifetime.rs | 32 + tests/ui/suggestions/return-elided-lifetime.stderr | 143 + tests/ui/suggestions/return-without-lifetime.rs | 10 + .../ui/suggestions/return-without-lifetime.stderr | 38 + tests/ui/suggestions/shadowed-lplace-method-2.rs | 23 + .../ui/suggestions/shadowed-lplace-method-2.stderr | 25 + tests/ui/suggestions/shadowed-lplace-method.fixed | 10 + tests/ui/suggestions/shadowed-lplace-method.rs | 10 + tests/ui/suggestions/shadowed-lplace-method.stderr | 26 + tests/ui/suggestions/slice-issue-87994.rs | 16 + tests/ui/suggestions/slice-issue-87994.stderr | 63 + .../struct-field-type-including-single-colon.rs | 20 + ...struct-field-type-including-single-colon.stderr | 40 + .../ui/suggestions/struct-initializer-comma.fixed | 15 + tests/ui/suggestions/struct-initializer-comma.rs | 15 + .../ui/suggestions/struct-initializer-comma.stderr | 23 + tests/ui/suggestions/sugg-else-for-closure.fixed | 8 + tests/ui/suggestions/sugg-else-for-closure.rs | 8 + tests/ui/suggestions/sugg-else-for-closure.stderr | 27 + .../sugg_with_positional_args_and_debug_fmt.rs | 10 + .../sugg_with_positional_args_and_debug_fmt.stderr | 21 + tests/ui/suggestions/suggest-add-self.rs | 15 + tests/ui/suggestions/suggest-add-self.stderr | 29 + ...gest-adding-reference-to-trait-assoc-item.fixed | 15 + ...suggest-adding-reference-to-trait-assoc-item.rs | 15 + ...est-adding-reference-to-trait-assoc-item.stderr | 25 + .../suggestions/suggest-assoc-fn-call-deref.fixed | 15 + .../ui/suggestions/suggest-assoc-fn-call-deref.rs | 15 + .../suggestions/suggest-assoc-fn-call-deref.stderr | 19 + ...est-assoc-fn-call-with-turbofish-placeholder.rs | 11 + ...assoc-fn-call-with-turbofish-placeholder.stderr | 22 + ...t-assoc-fn-call-with-turbofish-through-deref.rs | 13 + ...soc-fn-call-with-turbofish-through-deref.stderr | 19 + .../suggest-assoc-fn-call-with-turbofish.fixed | 26 + .../suggest-assoc-fn-call-with-turbofish.rs | 26 + .../suggest-assoc-fn-call-with-turbofish.stderr | 98 + .../suggest-blanket-impl-local-trait.rs | 58 + .../suggest-blanket-impl-local-trait.stderr | 100 + .../ui/suggestions/suggest-borrow-to-dyn-object.rs | 16 + .../suggest-borrow-to-dyn-object.stderr | 17 + tests/ui/suggestions/suggest-box.fixed | 8 + tests/ui/suggestions/suggest-box.rs | 8 + tests/ui/suggestions/suggest-box.stderr | 26 + tests/ui/suggestions/suggest-change-mut.rs | 21 + tests/ui/suggestions/suggest-change-mut.stderr | 41 + .../suggestions/suggest-closure-return-type-1.rs | 7 + .../suggest-closure-return-type-1.stderr | 14 + .../suggestions/suggest-closure-return-type-2.rs | 7 + .../suggest-closure-return-type-2.stderr | 14 + .../suggestions/suggest-closure-return-type-3.rs | 7 + .../suggest-closure-return-type-3.stderr | 14 + .../suggestions/suggest-dereferencing-index.fixed | 7 + .../ui/suggestions/suggest-dereferencing-index.rs | 7 + .../suggestions/suggest-dereferencing-index.stderr | 17 + .../suggest-full-enum-variant-for-local-module.rs | 10 + ...ggest-full-enum-variant-for-local-module.stderr | 18 + .../suggest-imm-mut-trait-implementations.rs | 23 + .../suggest-imm-mut-trait-implementations.stderr | 59 + .../suggestions/suggest-impl-trait-lifetime.fixed | 18 + .../ui/suggestions/suggest-impl-trait-lifetime.rs | 18 + .../suggestions/suggest-impl-trait-lifetime.stderr | 14 + tests/ui/suggestions/suggest-labels.rs | 16 + tests/ui/suggestions/suggest-labels.stderr | 36 + .../suggestions/suggest-let-for-assignment.fixed | 17 + tests/ui/suggestions/suggest-let-for-assignment.rs | 17 + .../suggestions/suggest-let-for-assignment.stderr | 60 + tests/ui/suggestions/suggest-methods.rs | 30 + tests/ui/suggestions/suggest-methods.stderr | 30 + tests/ui/suggestions/suggest-move-lifetimes.rs | 21 + tests/ui/suggestions/suggest-move-lifetimes.stderr | 26 + tests/ui/suggestions/suggest-move-types.rs | 91 + tests/ui/suggestions/suggest-move-types.stderr | 137 + .../suggest-mut-method-for-loop-hashmap.fixed | 21 + .../suggest-mut-method-for-loop-hashmap.rs | 21 + .../suggest-mut-method-for-loop-hashmap.stderr | 15 + .../ui/suggestions/suggest-mut-method-for-loop.rs | 17 + .../suggestions/suggest-mut-method-for-loop.stderr | 15 + .../ui/suggestions/suggest-on-bare-closure-call.rs | 11 + .../suggest-on-bare-closure-call.stderr | 29 + tests/ui/suggestions/suggest-ref-macro.rs | 29 + tests/ui/suggestions/suggest-ref-macro.stderr | 57 + tests/ui/suggestions/suggest-ref-mut.rs | 30 + tests/ui/suggestions/suggest-ref-mut.stderr | 47 + tests/ui/suggestions/suggest-remove-refs-1.fixed | 10 + tests/ui/suggestions/suggest-remove-refs-1.rs | 10 + tests/ui/suggestions/suggest-remove-refs-1.stderr | 17 + tests/ui/suggestions/suggest-remove-refs-2.fixed | 10 + tests/ui/suggestions/suggest-remove-refs-2.rs | 10 + tests/ui/suggestions/suggest-remove-refs-2.stderr | 17 + tests/ui/suggestions/suggest-remove-refs-3.fixed | 12 + tests/ui/suggestions/suggest-remove-refs-3.rs | 13 + tests/ui/suggestions/suggest-remove-refs-3.stderr | 21 + tests/ui/suggestions/suggest-remove-refs-4.fixed | 5 + tests/ui/suggestions/suggest-remove-refs-4.rs | 5 + tests/ui/suggestions/suggest-remove-refs-4.stderr | 17 + tests/ui/suggestions/suggest-remove-refs-5.fixed | 8 + tests/ui/suggestions/suggest-remove-refs-5.rs | 8 + tests/ui/suggestions/suggest-remove-refs-5.stderr | 37 + .../suggest-semicolon-for-fn-in-extern-block.fixed | 9 + .../suggest-semicolon-for-fn-in-extern-block.rs | 9 + ...suggest-semicolon-for-fn-in-extern-block.stderr | 10 + tests/ui/suggestions/suggest-split-at-mut.rs | 8 + tests/ui/suggestions/suggest-split-at-mut.stderr | 15 + .../suggestions/suggest-std-when-using-type.fixed | 8 + .../ui/suggestions/suggest-std-when-using-type.rs | 8 + .../suggestions/suggest-std-when-using-type.stderr | 26 + ...gest-swapping-self-ty-and-trait-edition-2021.rs | 22 + ...-swapping-self-ty-and-trait-edition-2021.stderr | 48 + .../suggest-swapping-self-ty-and-trait.rs | 21 + .../suggest-swapping-self-ty-and-trait.stderr | 50 + tests/ui/suggestions/suggest-trait-items.rs | 48 + tests/ui/suggestions/suggest-trait-items.stderr | 74 + .../suggestions/suggest-tryinto-edition-change.rs | 32 + .../suggest-tryinto-edition-change.stderr | 69 + tests/ui/suggestions/suggest-using-chars.rs | 7 + tests/ui/suggestions/suggest-using-chars.stderr | 48 + tests/ui/suggestions/suggest-variants.rs | 18 + tests/ui/suggestions/suggest-variants.stderr | 63 + tests/ui/suggestions/suggest_print_over_printf.rs | 8 + .../suggestions/suggest_print_over_printf.stderr | 14 + tests/ui/suggestions/too-many-field-suggestions.rs | 29 + .../suggestions/too-many-field-suggestions.stderr | 44 + ...ssing-associated-type-restriction-fixable.fixed | 43 + ...-missing-associated-type-restriction-fixable.rs | 43 + ...sing-associated-type-restriction-fixable.stderr | 143 + ...ait-with-missing-associated-type-restriction.rs | 44 + ...with-missing-associated-type-restriction.stderr | 177 + .../try-operator-dont-suggest-semicolon.rs | 27 + .../try-operator-dont-suggest-semicolon.stderr | 33 + tests/ui/suggestions/try-removing-the-field.rs | 32 + tests/ui/suggestions/try-removing-the-field.stderr | 26 + .../suggestions/type-ascription-and-other-error.rs | 6 + .../type-ascription-and-other-error.stderr | 8 + .../suggestions/type-ascription-instead-of-let.rs | 10 + .../type-ascription-instead-of-let.stderr | 18 + .../type-ascription-instead-of-method.fixed | 5 + .../type-ascription-instead-of-method.rs | 5 + .../type-ascription-instead-of-method.stderr | 12 + .../type-ascription-instead-of-path-2.fixed | 6 + .../type-ascription-instead-of-path-2.rs | 6 + .../type-ascription-instead-of-path-2.stderr | 12 + .../type-ascription-instead-of-path-in-type.rs | 14 + .../type-ascription-instead-of-path-in-type.stderr | 41 + .../suggestions/type-ascription-instead-of-path.rs | 5 + .../type-ascription-instead-of-path.stderr | 18 + .../type-ascription-instead-of-variant.fixed | 5 + .../type-ascription-instead-of-variant.rs | 5 + .../type-ascription-instead-of-variant.stderr | 12 + tests/ui/suggestions/type-mismatch-byte-literal.rs | 18 + .../suggestions/type-mismatch-byte-literal.stderr | 42 + .../type-mismatch-struct-field-shorthand-2.rs | 9 + .../type-mismatch-struct-field-shorthand-2.stderr | 32 + .../type-mismatch-struct-field-shorthand.fixed | 12 + .../type-mismatch-struct-field-shorthand.rs | 12 + .../type-mismatch-struct-field-shorthand.stderr | 36 + .../ui/suggestions/type-not-found-in-adt-field.rs | 9 + .../suggestions/type-not-found-in-adt-field.stderr | 20 + tests/ui/suggestions/undeclared-module-alloc.rs | 5 + .../ui/suggestions/undeclared-module-alloc.stderr | 11 + tests/ui/suggestions/unnamable-types.rs | 39 + tests/ui/suggestions/unnamable-types.stderr | 66 + .../unnecessary_dot_for_floating_point_literal.rs | 6 + ...necessary_dot_for_floating_point_literal.stderr | 59 + .../suggestions/unsized-function-parameter.fixed | 23 + tests/ui/suggestions/unsized-function-parameter.rs | 23 + .../suggestions/unsized-function-parameter.stderr | 42 + tests/ui/suggestions/unused-closure-argument.rs | 20 + .../ui/suggestions/unused-closure-argument.stderr | 20 + tests/ui/suggestions/use-placement-resolve.fixed | 13 + tests/ui/suggestions/use-placement-resolve.rs | 11 + tests/ui/suggestions/use-placement-resolve.stderr | 14 + tests/ui/suggestions/use-placement-typeck.fixed | 21 + tests/ui/suggestions/use-placement-typeck.rs | 20 + tests/ui/suggestions/use-placement-typeck.stderr | 21 + .../use-type-argument-instead-of-assoc-type.rs | 13 + .../use-type-argument-instead-of-assoc-type.stderr | 32 + tests/ui/suggestions/while-let-typo.rs | 9 + tests/ui/suggestions/while-let-typo.stderr | 45 + tests/ui/super-at-top-level.rs | 4 + tests/ui/super-at-top-level.stderr | 9 + tests/ui/super-fast-paren-parsing.rs | 25 + tests/ui/super.rs | 16 + tests/ui/suppressed-error.rs | 8 + tests/ui/suppressed-error.stderr | 14 + tests/ui/svh-add-nothing.rs | 14 + tests/ui/svh/auxiliary/changing-crates-a1.rs | 3 + tests/ui/svh/auxiliary/changing-crates-a2.rs | 3 + tests/ui/svh/auxiliary/changing-crates-b.rs | 5 + tests/ui/svh/auxiliary/svh-a-base.rs | 25 + tests/ui/svh/auxiliary/svh-a-change-lit.rs | 25 + .../svh/auxiliary/svh-a-change-significant-cfg.rs | 27 + tests/ui/svh/auxiliary/svh-a-change-trait-bound.rs | 25 + tests/ui/svh/auxiliary/svh-a-change-type-arg.rs | 25 + tests/ui/svh/auxiliary/svh-a-change-type-ret.rs | 25 + tests/ui/svh/auxiliary/svh-a-change-type-static.rs | 25 + tests/ui/svh/auxiliary/svh-b.rs | 13 + tests/ui/svh/auxiliary/svh-uta-base.rs | 22 + tests/ui/svh/auxiliary/svh-uta-change-use-trait.rs | 22 + tests/ui/svh/auxiliary/svh-utb.rs | 12 + tests/ui/svh/changing-crates.rs | 10 + tests/ui/svh/changing-crates.stderr | 14 + tests/ui/svh/svh-change-lit.rs | 12 + tests/ui/svh/svh-change-lit.stderr | 14 + tests/ui/svh/svh-change-significant-cfg.rs | 12 + tests/ui/svh/svh-change-significant-cfg.stderr | 14 + tests/ui/svh/svh-change-trait-bound.rs | 12 + tests/ui/svh/svh-change-trait-bound.stderr | 14 + tests/ui/svh/svh-change-type-arg.rs | 12 + tests/ui/svh/svh-change-type-arg.stderr | 14 + tests/ui/svh/svh-change-type-ret.rs | 12 + tests/ui/svh/svh-change-type-ret.stderr | 14 + tests/ui/svh/svh-change-type-static.rs | 12 + tests/ui/svh/svh-change-type-static.stderr | 14 + tests/ui/svh/svh-use-trait.rs | 17 + tests/ui/svh/svh-use-trait.stderr | 14 + tests/ui/swap-1.rs | 10 + tests/ui/swap-overlapping.rs | 44 + tests/ui/switched-expectations.rs | 4 + tests/ui/switched-expectations.stderr | 9 + tests/ui/symbol-names/basic.legacy.stderr | 26 + tests/ui/symbol-names/basic.rs | 19 + tests/ui/symbol-names/basic.v0.stderr | 26 + .../const-generics-demangling.legacy.stderr | 74 + tests/ui/symbol-names/const-generics-demangling.rs | 62 + .../const-generics-demangling.v0.stderr | 74 + .../symbol-names/const-generics-str-demangling.rs | 45 + .../const-generics-str-demangling.stderr | 110 + .../const-generics-structural-demangling.rs | 96 + .../const-generics-structural-demangling.stderr | 161 + tests/ui/symbol-names/const-generics.rs | 85 + tests/ui/symbol-names/foreign-types.rs | 19 + tests/ui/symbol-names/foreign-types.stderr | 20 + tests/ui/symbol-names/impl1.legacy.stderr | 74 + tests/ui/symbol-names/impl1.rs | 75 + tests/ui/symbol-names/impl1.v0.stderr | 74 + tests/ui/symbol-names/impl2.rs | 15 + tests/ui/symbol-names/impl2.stderr | 8 + tests/ui/symbol-names/issue-53912.rs | 37 + tests/ui/symbol-names/issue-60925.legacy.stderr | 20 + tests/ui/symbol-names/issue-60925.rs | 49 + tests/ui/symbol-names/issue-60925.v0.stderr | 20 + tests/ui/symbol-names/issue-75326.legacy.stderr | 20 + tests/ui/symbol-names/issue-75326.rs | 56 + tests/ui/symbol-names/issue-75326.v0.stderr | 20 + tests/ui/symbol-names/issue-76365.rs | 17 + tests/ui/symbol-names/trait-objects.rs | 47 + tests/ui/symbol-names/trait-objects.v0.stderr | 56 + tests/ui/symbol-names/types.legacy.stderr | 470 + tests/ui/symbol-names/types.rs | 170 + tests/ui/symbol-names/types.verbose-legacy.stderr | 470 + tests/ui/symbol-names/verbose.rs | 15 + tests/ui/symbol-names/x86-stdcall.rs | 13 + tests/ui/syntax-extension-minor.rs | 14 + tests/ui/tag-that-dare-not-speak-its-name.rs | 16 + tests/ui/tag-that-dare-not-speak-its-name.stderr | 14 + tests/ui/tag-type-args.rs | 5 + tests/ui/tag-type-args.stderr | 19 + tests/ui/tag-variant-cast-non-nullary.fixed | 20 + tests/ui/tag-variant-cast-non-nullary.rs | 20 + tests/ui/tag-variant-cast-non-nullary.stderr | 11 + tests/ui/tail-call-arg-leak.rs | 9 + tests/ui/tail-cps.rs | 17 + tests/ui/tail-typeck.rs | 7 + tests/ui/tail-typeck.stderr | 16 + tests/ui/target-feature/aarch64-neon-works.rs | 23 + tests/ui/target-feature/feature-hierarchy.rs | 58 + tests/ui/target-feature/gate.rs | 36 + tests/ui/target-feature/gate.stderr | 12 + tests/ui/target-feature/invalid-attribute.rs | 97 + tests/ui/target-feature/invalid-attribute.stderr | 136 + tests/ui/target-feature/missing-plusminus-2.rs | 6 + tests/ui/target-feature/missing-plusminus-2.stderr | 6 + tests/ui/target-feature/missing-plusminus.rs | 2 + tests/ui/target-feature/missing-plusminus.stderr | 6 + tests/ui/target-feature/no-llvm-leaks.rs | 64 + .../rust-specific-name-no-warnings.rs | 5 + .../target-feature/similar-feature-suggestion.rs | 6 + .../similar-feature-suggestion.stderr | 7 + .../ui/target-feature/tied-features-cli.one.stderr | 4 + tests/ui/target-feature/tied-features-cli.rs | 20 + .../target-feature/tied-features-cli.three.stderr | 4 + .../ui/target-feature/tied-features-cli.two.stderr | 4 + tests/ui/target-feature/tied-features.rs | 34 + tests/ui/target-feature/tied-features.stderr | 18 + tests/ui/target-feature/wasm-safe.rs | 44 + tests/ui/terr-in-field.rs | 17 + tests/ui/terr-in-field.stderr | 17 + tests/ui/terr-sorts.rs | 15 + tests/ui/terr-sorts.stderr | 23 + tests/ui/test-attrs/auxiliary/test_macro.rs | 4 + tests/ui/test-attrs/decl-macro-test.rs | 22 + tests/ui/test-attrs/inaccessible-test-modules.rs | 9 + .../ui/test-attrs/inaccessible-test-modules.stderr | 20 + tests/ui/test-attrs/issue-16597-empty.rs | 5 + tests/ui/test-attrs/issue-16597.rs | 10 + tests/ui/test-attrs/issue-20823.rs | 5 + tests/ui/test-attrs/issue-36768.rs | 9 + tests/ui/test-attrs/issue-52557.rs | 30 + .../test-attrs/issue-53675-a-test-called-panic.rs | 36 + tests/ui/test-attrs/run-unexported-tests.rs | 12 + .../test-attr-non-associated-functions.rs | 25 + .../test-attr-non-associated-functions.stderr | 20 + tests/ui/test-attrs/test-cant-be-shadowed.rs | 13 + tests/ui/test-attrs/test-filter-multiple.rs | 17 + .../ui/test-attrs/test-filter-multiple.run.stdout | 7 + ...nature-verification-for-explicit-return-type.rs | 13 + tests/ui/test-attrs/test-main-not-dead-attr.rs | 9 + tests/ui/test-attrs/test-main-not-dead.rs | 6 + tests/ui/test-attrs/test-on-not-fn.rs | 80 + tests/ui/test-attrs/test-on-not-fn.stderr | 173 + tests/ui/test-attrs/test-panic-abort-disabled.rs | 20 + .../ui/test-attrs/test-panic-abort-disabled.stderr | 4 + tests/ui/test-attrs/test-panic-abort-nocapture.rs | 41 + .../test-panic-abort-nocapture.run.stderr | 9 + .../test-panic-abort-nocapture.run.stdout | 23 + tests/ui/test-attrs/test-panic-abort.rs | 50 + tests/ui/test-attrs/test-panic-abort.run.stdout | 30 + tests/ui/test-attrs/test-panic-while-printing.rs | 24 + tests/ui/test-attrs/test-passed-wasm.rs | 20 + tests/ui/test-attrs/test-passed-wasm.run.stdout | 7 + tests/ui/test-attrs/test-passed.rs | 21 + tests/ui/test-attrs/test-passed.run.stdout | 7 + .../ui/test-attrs/test-runner-hides-buried-main.rs | 15 + tests/ui/test-attrs/test-runner-hides-main.rs | 5 + tests/ui/test-attrs/test-runner-hides-start.rs | 7 + .../ui/test-attrs/test-should-fail-good-message.rs | 14 + tests/ui/test-attrs/test-should-panic-attr.rs | 36 + tests/ui/test-attrs/test-should-panic-attr.stderr | 34 + tests/ui/test-attrs/test-thread-capture.rs | 33 + tests/ui/test-attrs/test-thread-capture.run.stdout | 21 + tests/ui/test-attrs/test-thread-nocapture.rs | 33 + .../ui/test-attrs/test-thread-nocapture.run.stderr | 2 + .../ui/test-attrs/test-thread-nocapture.run.stdout | 20 + tests/ui/test-attrs/test-type.rs | 27 + tests/ui/test-attrs/test-type.run.stdout | 8 + tests/ui/test-attrs/test-vs-cfg-test.rs | 9 + tests/ui/test-attrs/test-warns-dead-code.rs | 7 + tests/ui/test-attrs/test-warns-dead-code.stderr | 14 + tests/ui/thir-tree.rs | 4 + tests/ui/thir-tree.stdout | 56 + tests/ui/thread-local-mutation.rs | 18 + tests/ui/thread-local-mutation.stderr | 9 + tests/ui/thread-local-static.rs | 16 + tests/ui/thread-local-static.stderr | 44 + tests/ui/thread-local/name-collision.rs | 15 + tests/ui/thread-local/non-static.rs | 30 + tests/ui/thread-local/non-static.stderr | 38 + tests/ui/thread-local/thread-local-issue-37508.rs | 36 + tests/ui/thread-local/tls.rs | 14 + .../auxiliary/thread-local-extern-static.rs | 10 + tests/ui/threads-sendsync/child-outlives-parent.rs | 13 + tests/ui/threads-sendsync/clone-with-exterior.rs | 20 + tests/ui/threads-sendsync/comm.rs | 22 + tests/ui/threads-sendsync/eprint-on-tls-drop.rs | 49 + tests/ui/threads-sendsync/issue-24313.rs | 32 + tests/ui/threads-sendsync/issue-29488.rs | 23 + tests/ui/threads-sendsync/issue-43733-2.rs | 30 + tests/ui/threads-sendsync/issue-43733.mir.stderr | 19 + tests/ui/threads-sendsync/issue-43733.rs | 38 + tests/ui/threads-sendsync/issue-43733.thir.stderr | 19 + tests/ui/threads-sendsync/issue-4446.rs | 15 + tests/ui/threads-sendsync/issue-4448.rs | 16 + tests/ui/threads-sendsync/issue-8827.rs | 53 + tests/ui/threads-sendsync/issue-9396.rs | 23 + tests/ui/threads-sendsync/mpsc_stress.rs | 200 + .../threads-sendsync/send-is-not-static-par-for.rs | 34 + tests/ui/threads-sendsync/send-resource.rs | 39 + tests/ui/threads-sendsync/send-type-inference.rs | 19 + tests/ui/threads-sendsync/send_str_hashmap.rs | 53 + tests/ui/threads-sendsync/send_str_treemap.rs | 58 + tests/ui/threads-sendsync/sendable-class.rs | 28 + tests/ui/threads-sendsync/sendfn-is-a-block.rs | 11 + .../threads-sendsync/sendfn-spawn-with-fn-arg.rs | 21 + tests/ui/threads-sendsync/spawn-fn.rs | 25 + tests/ui/threads-sendsync/spawn-types.rs | 25 + tests/ui/threads-sendsync/spawn.rs | 10 + tests/ui/threads-sendsync/spawn2.rs | 31 + tests/ui/threads-sendsync/spawning-with-debug.rs | 15 + .../threads-sendsync/std-sync-right-kind-impls.rs | 16 + tests/ui/threads-sendsync/sync-send-atomics.rs | 14 + tests/ui/threads-sendsync/sync-send-in-std.rs | 25 + .../sync-send-iterators-in-libcollections.rs | 71 + .../sync-send-iterators-in-libcore.rs | 105 + tests/ui/threads-sendsync/task-comm-0.rs | 30 + tests/ui/threads-sendsync/task-comm-1.rs | 14 + tests/ui/threads-sendsync/task-comm-10.rs | 33 + tests/ui/threads-sendsync/task-comm-11.rs | 21 + tests/ui/threads-sendsync/task-comm-12.rs | 29 + tests/ui/threads-sendsync/task-comm-13.rs | 18 + tests/ui/threads-sendsync/task-comm-14.rs | 36 + tests/ui/threads-sendsync/task-comm-15.rs | 28 + tests/ui/threads-sendsync/task-comm-16.rs | 111 + tests/ui/threads-sendsync/task-comm-17.rs | 17 + tests/ui/threads-sendsync/task-comm-3.rs | 63 + tests/ui/threads-sendsync/task-comm-4.rs | 45 + tests/ui/threads-sendsync/task-comm-5.rs | 17 + tests/ui/threads-sendsync/task-comm-6.rs | 42 + tests/ui/threads-sendsync/task-comm-7.rs | 59 + tests/ui/threads-sendsync/task-comm-9.rs | 35 + tests/ui/threads-sendsync/task-comm-chan-nil.rs | 13 + tests/ui/threads-sendsync/task-life-0.rs | 14 + tests/ui/threads-sendsync/task-spawn-barefn.rs | 18 + .../threads-sendsync/task-spawn-move-and-copy.rs | 23 + tests/ui/threads-sendsync/task-stderr.rs | 26 + tests/ui/threads-sendsync/tcp-stress.rs | 64 + .../threads-sendsync/test-tasks-invalid-value.rs | 11 + .../threads-sendsync/thread-local-extern-static.rs | 27 + tests/ui/threads-sendsync/thread-local-syntax.rs | 22 + tests/ui/threads-sendsync/threads.rs | 16 + .../tls-dtors-are-run-in-a-static-binary.rs | 22 + tests/ui/threads-sendsync/tls-init-on-init.rs | 44 + tests/ui/threads-sendsync/tls-try-with.rs | 30 + tests/ui/threads-sendsync/trivial-message.rs | 16 + tests/ui/threads-sendsync/unwind-resource.rs | 40 + tests/ui/threads-sendsync/yield.rs | 21 + tests/ui/threads-sendsync/yield1.rs | 16 + tests/ui/threads-sendsync/yield2.rs | 8 + tests/ui/tool-attributes/diagnostic_item.rs | 3 + tests/ui/tool-attributes/diagnostic_item.stderr | 11 + tests/ui/tool-attributes/diagnostic_item2.rs | 6 + tests/ui/tool-attributes/diagnostic_item3.rs | 7 + .../tool-attributes/tool-attributes-misplaced-1.rs | 18 + .../tool-attributes-misplaced-1.stderr | 52 + .../tool-attributes/tool-attributes-misplaced-2.rs | 6 + .../tool-attributes-misplaced-2.stderr | 14 + .../tool-attributes/tool-attributes-shadowing.rs | 4 + .../tool-attributes-shadowing.stderr | 9 + tests/ui/tool_lints-fail.rs | 8 + tests/ui/tool_lints-fail.stderr | 14 + tests/ui/tool_lints-rpass.rs | 6 + tests/ui/tool_lints.rs | 4 + tests/ui/tool_lints.stderr | 19 + tests/ui/tool_lints_2018_preview.rs | 7 + tests/ui/track-diagnostics/track.rs | 11 + tests/ui/track-diagnostics/track.stderr | 26 + tests/ui/track-diagnostics/track2.rs | 10 + tests/ui/track-diagnostics/track2.stderr | 18 + tests/ui/track-diagnostics/track3.rs | 10 + tests/ui/track-diagnostics/track3.stderr | 18 + tests/ui/track-diagnostics/track4.rs | 13 + tests/ui/track-diagnostics/track4.stderr | 14 + tests/ui/track-diagnostics/track5.rs | 8 + tests/ui/track-diagnostics/track5.stderr | 9 + tests/ui/track-diagnostics/track6.rs | 14 + tests/ui/track-diagnostics/track6.stderr | 13 + tests/ui/trailing-comma.rs | 35 + .../impl-bound-with-references-error.rs | 20 + .../impl-bound-with-references-error.stderr | 24 + .../impl-derived-implicit-sized-bound-2.rs | 33 + .../impl-derived-implicit-sized-bound-2.stderr | 31 + .../impl-derived-implicit-sized-bound.rs | 36 + .../impl-derived-implicit-sized-bound.stderr | 31 + ...pl-missing-where-clause-lifetimes-from-trait.rs | 38 + ...issing-where-clause-lifetimes-from-trait.stderr | 36 + tests/ui/trait-bounds/issue-75961.rs | 7 + tests/ui/trait-bounds/issue-93008.rs | 15 + tests/ui/trait-bounds/issue-94680.rs | 14 + tests/ui/trait-bounds/issue-94999.rs | 34 + tests/ui/trait-bounds/issue-95640.rs | 31 + tests/ui/trait-bounds/mismatch-fn-trait.rs | 28 + tests/ui/trait-bounds/mismatch-fn-trait.stderr | 81 + .../shadowed-path-in-trait-bound-suggestion.fixed | 16 + .../shadowed-path-in-trait-bound-suggestion.rs | 14 + .../shadowed-path-in-trait-bound-suggestion.stderr | 19 + tests/ui/trait-bounds/unsized-bound.rs | 32 + tests/ui/trait-bounds/unsized-bound.stderr | 273 + tests/ui/trait-impl-bound-suggestions.fixed | 20 + tests/ui/trait-impl-bound-suggestions.rs | 20 + tests/ui/trait-impl-bound-suggestions.stderr | 19 + tests/ui/trait-method-number-parameters.rs | 13 + tests/ui/trait-method-number-parameters.stderr | 13 + tests/ui/traits/alias/ambiguous.rs | 24 + tests/ui/traits/alias/ambiguous.stderr | 28 + tests/ui/traits/alias/auxiliary/greeter.rs | 13 + tests/ui/traits/alias/auxiliary/send_sync.rs | 3 + tests/ui/traits/alias/basic.rs | 8 + tests/ui/traits/alias/bounds.rs | 57 + tests/ui/traits/alias/cross-crate.rs | 17 + tests/ui/traits/alias/cross-crate.stderr | 31 + tests/ui/traits/alias/generic-default-in-dyn.rs | 10 + .../ui/traits/alias/generic-default-in-dyn.stderr | 35 + tests/ui/traits/alias/impl.rs | 7 + tests/ui/traits/alias/impl.stderr | 9 + tests/ui/traits/alias/import-cross-crate.rs | 14 + tests/ui/traits/alias/import.rs | 40 + .../alias/issue-60021-assoc-method-resolve.rs | 19 + .../alias/issue-72415-assoc-const-resolve.rs | 14 + tests/ui/traits/alias/issue-75983.rs | 17 + tests/ui/traits/alias/issue-83613.rs | 12 + tests/ui/traits/alias/issue-83613.stderr | 11 + tests/ui/traits/alias/maybe-bound.rs | 29 + tests/ui/traits/alias/no-duplicates.rs | 126 + tests/ui/traits/alias/no-duplicates.stderr | 527 + tests/ui/traits/alias/no-extra-traits.rs | 121 + tests/ui/traits/alias/no-extra-traits.stderr | 579 ++ tests/ui/traits/alias/object-fail.rs | 11 + tests/ui/traits/alias/object-fail.stderr | 21 + tests/ui/traits/alias/object-wf.rs | 85 + tests/ui/traits/alias/object.rs | 18 + tests/ui/traits/alias/only-maybe-bound.rs | 22 + tests/ui/traits/alias/only-maybe-bound.stderr | 21 + tests/ui/traits/alias/self-in-const-generics.rs | 12 + .../ui/traits/alias/self-in-const-generics.stderr | 11 + tests/ui/traits/alias/self-in-generics.rs | 15 + tests/ui/traits/alias/self-in-generics.stderr | 11 + tests/ui/traits/alias/style_lint.rs | 8 + tests/ui/traits/alias/style_lint.stderr | 10 + .../suggest-trait-alias-instead-of-type.fixed | 13 + .../alias/suggest-trait-alias-instead-of-type.rs | 13 + .../suggest-trait-alias-instead-of-type.stderr | 14 + tests/ui/traits/alias/syntax-fail.rs | 10 + tests/ui/traits/alias/syntax-fail.stderr | 26 + tests/ui/traits/alias/syntax.rs | 24 + tests/ui/traits/alias/wf.rs | 7 + tests/ui/traits/alias/wf.stderr | 19 + tests/ui/traits/alignment-gep-tup-like-1.rs | 37 + tests/ui/traits/anon-static-method.rs | 15 + tests/ui/traits/anon_trait_static_method_exe.rs | 12 + tests/ui/traits/as-struct-constructor.rs | 6 + tests/ui/traits/as-struct-constructor.stderr | 9 + tests/ui/traits/assignability-trait.rs | 47 + tests/ui/traits/assoc-type-in-superbad.rs | 16 + tests/ui/traits/assoc-type-in-superbad.stderr | 15 + tests/ui/traits/assoc-type-in-supertrait.rs | 23 + .../assoc_type_bound_with_struct.rs | 23 + .../assoc_type_bound_with_struct.stderr | 91 + .../check-trait-object-bounds-1.rs | 14 + .../check-trait-object-bounds-1.stderr | 16 + .../check-trait-object-bounds-2-ok.rs | 15 + .../check-trait-object-bounds-2.rs | 15 + .../check-trait-object-bounds-2.stderr | 16 + .../check-trait-object-bounds-3.rs | 20 + .../check-trait-object-bounds-3.stderr | 15 + .../check-trait-object-bounds-4.rs | 17 + .../check-trait-object-bounds-4.stderr | 16 + .../check-trait-object-bounds-5.rs | 27 + .../check-trait-object-bounds-5.stderr | 22 + .../check-trait-object-bounds-6.rs | 24 + .../check-trait-object-bounds-6.stderr | 22 + .../ui/traits/associated_type_bound/issue-51446.rs | 34 + tests/ui/traits/astconv-cycle-between-and-type.rs | 29 + tests/ui/traits/augmented-assignments-trait.rs | 12 + .../auxiliary/anon_trait_static_method_lib.rs | 9 + tests/ui/traits/auxiliary/go_trait.rs | 43 + .../auxiliary/issue_89119_intercrate_caching.rs | 60 + tests/ui/traits/auxiliary/trait_safety_lib.rs | 9 + tests/ui/traits/auxiliary/traitimpl.rs | 7 + tests/ui/traits/bad-method-typaram-kind.rs | 14 + tests/ui/traits/bad-method-typaram-kind.stderr | 19 + tests/ui/traits/bad-sized.rs | 9 + tests/ui/traits/bad-sized.stderr | 45 + .../traits/bound/assoc-fn-bound-root-obligation.rs | 11 + .../bound/assoc-fn-bound-root-obligation.stderr | 20 + tests/ui/traits/bound/auxiliary/crate_a1.rs | 9 + tests/ui/traits/bound/auxiliary/crate_a2.rs | 13 + .../bound/auxiliary/on_structs_and_enums_xc.rs | 13 + tests/ui/traits/bound/basic.rs | 25 + tests/ui/traits/bound/generic_trait.rs | 30 + .../ui/traits/bound/impl-comparison-duplicates.rs | 16 + tests/ui/traits/bound/in-arc.rs | 108 + tests/ui/traits/bound/multiple.rs | 9 + tests/ui/traits/bound/not-on-bare-trait.rs | 13 + tests/ui/traits/bound/not-on-bare-trait.stderr | 34 + tests/ui/traits/bound/not-on-struct.rs | 38 + tests/ui/traits/bound/not-on-struct.stderr | 175 + .../ui/traits/bound/on-structs-and-enums-in-fns.rs | 20 + .../bound/on-structs-and-enums-in-fns.stderr | 27 + .../traits/bound/on-structs-and-enums-in-impls.rs | 25 + .../bound/on-structs-and-enums-in-impls.stderr | 15 + .../ui/traits/bound/on-structs-and-enums-locals.rs | 17 + .../bound/on-structs-and-enums-locals.stderr | 27 + .../ui/traits/bound/on-structs-and-enums-rpass.rs | 21 + .../ui/traits/bound/on-structs-and-enums-static.rs | 15 + .../bound/on-structs-and-enums-static.stderr | 15 + tests/ui/traits/bound/on-structs-and-enums-xc.rs | 14 + .../ui/traits/bound/on-structs-and-enums-xc.stderr | 27 + tests/ui/traits/bound/on-structs-and-enums-xc1.rs | 15 + .../traits/bound/on-structs-and-enums-xc1.stderr | 27 + tests/ui/traits/bound/on-structs-and-enums.rs | 43 + tests/ui/traits/bound/on-structs-and-enums.stderr | 99 + tests/ui/traits/bound/recursion.rs | 20 + tests/ui/traits/bound/same-crate-name.rs | 55 + tests/ui/traits/bound/same-crate-name.stderr | 75 + tests/ui/traits/bound/sugar.rs | 19 + tests/ui/traits/bound/sugar.stderr | 19 + tests/ui/traits/bug-7183-generics.rs | 36 + tests/ui/traits/bug-7295.rs | 14 + tests/ui/traits/cache-issue-18209.rs | 20 + tests/ui/traits/cache-reached-depth-ice.rs | 45 + tests/ui/traits/cache-reached-depth-ice.stderr | 11 + tests/ui/traits/coercion-generic-bad.rs | 19 + tests/ui/traits/coercion-generic-bad.stderr | 12 + tests/ui/traits/coercion-generic-regions.rs | 19 + tests/ui/traits/coercion-generic-regions.stderr | 15 + tests/ui/traits/coercion-generic.rs | 25 + tests/ui/traits/coercion.rs | 35 + tests/ui/traits/composition-trivial.rs | 12 + tests/ui/traits/conditional-dispatch.rs | 34 + tests/ui/traits/conditional-model-fn.rs | 53 + tests/ui/traits/conservative_impl_trait.rs | 8 + tests/ui/traits/copy-guessing.rs | 38 + tests/ui/traits/copy-impl-cannot-normalize.rs | 25 + tests/ui/traits/copy-impl-cannot-normalize.stderr | 24 + .../copy-is-not-modulo-regions.not_static.stderr | 22 + tests/ui/traits/copy-is-not-modulo-regions.rs | 19 + tests/ui/traits/copy-requires-self-wf.rs | 14 + tests/ui/traits/cycle-cache-err-60010.rs | 74 + tests/ui/traits/cycle-cache-err-60010.stderr | 39 + tests/ui/traits/cycle-generic-bound.rs | 11 + tests/ui/traits/cycle-type-trait.rs | 25 + tests/ui/traits/default-method/auxiliary/xc.rs | 40 + tests/ui/traits/default-method/auxiliary/xc_2.rs | 17 + tests/ui/traits/default-method/bound-subst.rs | 18 + tests/ui/traits/default-method/bound-subst2.rs | 16 + tests/ui/traits/default-method/bound-subst3.rs | 17 + tests/ui/traits/default-method/bound-subst4.rs | 19 + tests/ui/traits/default-method/bound.rs | 16 + tests/ui/traits/default-method/macro.rs | 20 + tests/ui/traits/default-method/mut.rs | 11 + .../default-method/rustc_must_implement_one_of.rs | 44 + .../rustc_must_implement_one_of.stderr | 15 + .../rustc_must_implement_one_of_duplicates.rs | 19 + .../rustc_must_implement_one_of_duplicates.stderr | 34 + .../rustc_must_implement_one_of_gated.rs | 13 + .../rustc_must_implement_one_of_gated.stderr | 11 + .../rustc_must_implement_one_of_misuse.rs | 46 + .../rustc_must_implement_one_of_misuse.stderr | 100 + tests/ui/traits/default-method/self.rs | 18 + tests/ui/traits/default-method/supervtable.rs | 28 + tests/ui/traits/default-method/trivial.rs | 21 + tests/ui/traits/default-method/xc-2.rs | 26 + tests/ui/traits/default-method/xc.rs | 81 + ...ype-params-by-name-in-suggestion-issue-96292.rs | 20 + ...params-by-name-in-suggestion-issue-96292.stderr | 34 + tests/ui/traits/duplicate-methods.rs | 6 + tests/ui/traits/duplicate-methods.stderr | 13 + tests/ui/traits/dyn-trait.rs | 17 + tests/ui/traits/early-vtbl-resolution.rs | 19 + tests/ui/traits/elaborate-type-region.rs | 49 + .../false-ambiguity-where-clause-builtin-bound.rs | 16 + tests/ui/traits/fmt-pointer-trait.rs | 24 + tests/ui/traits/fn-trait-cast-diagnostic.rs | 26 + tests/ui/traits/fn-trait-cast-diagnostic.stderr | 43 + tests/ui/traits/generic.rs | 45 + tests/ui/traits/ignore-err-impls.rs | 9 + tests/ui/traits/ignore-err-impls.stderr | 14 + tests/ui/traits/impl-1.rs | 16 + tests/ui/traits/impl-1.stderr | 9 + tests/ui/traits/impl-2.rs | 19 + tests/ui/traits/impl-bounds-checking.rs | 14 + tests/ui/traits/impl-bounds-checking.stderr | 15 + .../traits/impl-can-not-have-untraitful-items.rs | 9 + .../impl-can-not-have-untraitful-items.stderr | 22 + tests/ui/traits/impl-different-num-params.rs | 12 + tests/ui/traits/impl-different-num-params.stderr | 12 + tests/ui/traits/impl-evaluation-order.rs | 39 + tests/ui/traits/impl-for-module.rs | 11 + tests/ui/traits/impl-for-module.stderr | 12 + tests/ui/traits/impl-implicit-trait.rs | 26 + tests/ui/traits/impl-inherent-prefer-over-trait.rs | 30 + tests/ui/traits/impl-method-mismatch.rs | 13 + tests/ui/traits/impl-method-mismatch.stderr | 17 + tests/ui/traits/impl-object-overlap-issue-23853.rs | 18 + ...-of-supertrait-has-wrong-lifetime-parameters.rs | 31 + ...supertrait-has-wrong-lifetime-parameters.stderr | 27 + tests/ui/traits/impl.rs | 41 + .../traits/impl_trait_as_trait_return_position.rs | 17 + tests/ui/traits/inductive-overflow/lifetime.rs | 33 + tests/ui/traits/inductive-overflow/lifetime.stderr | 24 + tests/ui/traits/inductive-overflow/simultaneous.rs | 20 + .../traits/inductive-overflow/simultaneous.stderr | 22 + .../inductive-overflow/supertrait-auto-trait.rs | 18 + .../supertrait-auto-trait.stderr | 35 + tests/ui/traits/inductive-overflow/supertrait.rs | 15 + .../ui/traits/inductive-overflow/supertrait.stderr | 22 + tests/ui/traits/inductive-overflow/two-traits.rs | 22 + .../ui/traits/inductive-overflow/two-traits.stderr | 32 + tests/ui/traits/infer-from-object-issue-26952.rs | 26 + tests/ui/traits/inherent-method-order.rs | 25 + tests/ui/traits/inheritance/auto-xc-2.rs | 23 + tests/ui/traits/inheritance/auto-xc.rs | 25 + tests/ui/traits/inheritance/auto.rs | 29 + tests/ui/traits/inheritance/auxiliary/auto_xc.rs | 7 + tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs | 9 + .../traits/inheritance/auxiliary/overloading_xc.rs | 38 + tests/ui/traits/inheritance/auxiliary/xc_call.rs | 11 + tests/ui/traits/inheritance/basic.rs | 26 + .../ui/traits/inheritance/call-bound-inherited.rs | 20 + .../ui/traits/inheritance/call-bound-inherited2.rs | 23 + .../inheritance/cast-without-call-to-supertrait.rs | 33 + tests/ui/traits/inheritance/cast.rs | 33 + tests/ui/traits/inheritance/cross-trait-call-xc.rs | 20 + tests/ui/traits/inheritance/cross-trait-call.rs | 19 + tests/ui/traits/inheritance/diamond.rs | 28 + tests/ui/traits/inheritance/multiple-inheritors.rs | 23 + tests/ui/traits/inheritance/multiple-params.rs | 26 + tests/ui/traits/inheritance/num.rs | 13 + tests/ui/traits/inheritance/num0.rs | 24 + tests/ui/traits/inheritance/num1.rs | 15 + tests/ui/traits/inheritance/num2.rs | 86 + tests/ui/traits/inheritance/num3.rs | 19 + tests/ui/traits/inheritance/num5.rs | 26 + tests/ui/traits/inheritance/overloading-simple.rs | 27 + tests/ui/traits/inheritance/overloading-xc-exe.rs | 20 + tests/ui/traits/inheritance/overloading.rs | 47 + .../inheritance/repeated-supertrait-ambig.rs | 43 + .../inheritance/repeated-supertrait-ambig.stderr | 65 + tests/ui/traits/inheritance/repeated-supertrait.rs | 48 + tests/ui/traits/inheritance/self-in-supertype.rs | 62 + tests/ui/traits/inheritance/self.rs | 29 + tests/ui/traits/inheritance/simple.rs | 24 + tests/ui/traits/inheritance/static.rs | 26 + tests/ui/traits/inheritance/static2.rs | 29 + tests/ui/traits/inheritance/subst.rs | 27 + tests/ui/traits/inheritance/subst2.rs | 37 + tests/ui/traits/inheritance/visibility.rs | 20 + tests/ui/traits/invalid_operator_trait.rs | 23 + tests/ui/traits/invalid_operator_trait.stderr | 8 + tests/ui/traits/issue-102989.rs | 14 + tests/ui/traits/issue-102989.stderr | 34 + tests/ui/traits/issue-104322.rs | 80 + tests/ui/traits/issue-106072.rs | 5 + tests/ui/traits/issue-106072.stderr | 30 + tests/ui/traits/issue-18400.rs | 26 + tests/ui/traits/issue-18400.stderr | 20 + tests/ui/traits/issue-18412.rs | 26 + tests/ui/traits/issue-20692.rs | 11 + tests/ui/traits/issue-20692.stderr | 35 + tests/ui/traits/issue-22019.rs | 34 + tests/ui/traits/issue-22110.rs | 27 + tests/ui/traits/issue-22655.rs | 23 + tests/ui/traits/issue-23003-overflow.rs | 29 + tests/ui/traits/issue-23003.rs | 32 + tests/ui/traits/issue-23825.rs | 21 + tests/ui/traits/issue-24010.rs | 14 + tests/ui/traits/issue-26339.rs | 31 + tests/ui/traits/issue-28576.rs | 12 + tests/ui/traits/issue-28576.stderr | 20 + tests/ui/traits/issue-32963.rs | 11 + tests/ui/traits/issue-32963.stderr | 27 + tests/ui/traits/issue-33140-hack-boundaries.rs | 70 + tests/ui/traits/issue-33140-hack-boundaries.stderr | 85 + tests/ui/traits/issue-33140.rs | 47 + tests/ui/traits/issue-33140.stderr | 31 + tests/ui/traits/issue-35869.rs | 21 + tests/ui/traits/issue-35869.stderr | 71 + tests/ui/traits/issue-3683.rs | 18 + tests/ui/traits/issue-38033.rs | 79 + tests/ui/traits/issue-38404.rs | 6 + tests/ui/traits/issue-38404.stderr | 17 + tests/ui/traits/issue-38604.rs | 16 + tests/ui/traits/issue-38604.stderr | 33 + tests/ui/traits/issue-3973.rs | 25 + tests/ui/traits/issue-3973.stderr | 22 + tests/ui/traits/issue-4107.rs | 26 + tests/ui/traits/issue-43132.rs | 65 + tests/ui/traits/issue-43784-supertrait.rs | 10 + tests/ui/traits/issue-43784-supertrait.stderr | 24 + tests/ui/traits/issue-50480.rs | 15 + tests/ui/traits/issue-50480.stderr | 92 + tests/ui/traits/issue-52893.rs | 57 + tests/ui/traits/issue-52893.stderr | 29 + tests/ui/traits/issue-56202.rs | 17 + tests/ui/traits/issue-56488.rs | 13 + tests/ui/traits/issue-59029-1.rs | 9 + tests/ui/traits/issue-59029-1.stderr | 15 + tests/ui/traits/issue-59029-2.rs | 8 + tests/ui/traits/issue-6128.rs | 22 + tests/ui/traits/issue-6334.rs | 46 + .../issue-65284-suggest-generic-trait-bound.rs | 11 + .../issue-65284-suggest-generic-trait-bound.stderr | 17 + tests/ui/traits/issue-65673.rs | 12 + tests/ui/traits/issue-65673.stderr | 12 + tests/ui/traits/issue-68295.rs | 47 + tests/ui/traits/issue-68295.stderr | 17 + tests/ui/traits/issue-7013.rs | 26 + tests/ui/traits/issue-7013.stderr | 18 + tests/ui/traits/issue-70944.rs | 23 + tests/ui/traits/issue-71036.rs | 17 + tests/ui/traits/issue-71036.stderr | 12 + tests/ui/traits/issue-71136.rs | 8 + tests/ui/traits/issue-71136.stderr | 19 + tests/ui/traits/issue-72410.rs | 18 + tests/ui/traits/issue-72410.stderr | 25 + tests/ui/traits/issue-72455.rs | 27 + tests/ui/traits/issue-75627.rs | 6 + tests/ui/traits/issue-75627.stderr | 14 + tests/ui/traits/issue-77982.rs | 41 + tests/ui/traits/issue-77982.stderr | 98 + tests/ui/traits/issue-78372.rs | 13 + tests/ui/traits/issue-78372.stderr | 65 + tests/ui/traits/issue-78632.rs | 59 + tests/ui/traits/issue-79458.rs | 10 + tests/ui/traits/issue-79458.stderr | 16 + tests/ui/traits/issue-8153.rs | 16 + tests/ui/traits/issue-8153.stderr | 14 + tests/ui/traits/issue-82830.rs | 18 + .../issue-83538-tainted-cache-after-cycle.rs | 66 + .../issue-83538-tainted-cache-after-cycle.stderr | 38 + tests/ui/traits/issue-84399-bad-fresh-caching.rs | 55 + tests/ui/traits/issue-85360-eval-obligation-ice.rs | 143 + .../traits/issue-85360-eval-obligation-ice.stderr | 38 + tests/ui/traits/issue-85735.rs | 13 + tests/ui/traits/issue-85735.stderr | 18 + tests/ui/traits/issue-87558.rs | 9 + tests/ui/traits/issue-87558.stderr | 24 + tests/ui/traits/issue-89119.rs | 11 + tests/ui/traits/issue-90195-2.rs | 20 + tests/ui/traits/issue-90195.rs | 21 + tests/ui/traits/issue-90662-projection-caching.rs | 34 + tests/ui/traits/issue-91594.rs | 17 + tests/ui/traits/issue-91594.stderr | 18 + tests/ui/traits/issue-91949-hangs-on-recursion.rs | 32 + .../traits/issue-91949-hangs-on-recursion.stderr | 25 + tests/ui/traits/issue-92292.rs | 32 + tests/ui/traits/issue-9394-inherited-calls.rs | 62 + tests/ui/traits/issue-95311.rs | 19 + tests/ui/traits/issue-95898.rs | 9 + tests/ui/traits/issue-95898.stderr | 17 + tests/ui/traits/issue-96664.rs | 16 + tests/ui/traits/issue-96665.rs | 16 + tests/ui/traits/issue-97576.rs | 13 + tests/ui/traits/issue-97576.stderr | 11 + .../ui/traits/issue-97695-double-trivial-bound.rs | 24 + tests/ui/traits/issue-99875.rs | 16 + tests/ui/traits/issue-99875.stderr | 36 + tests/ui/traits/item-inside-macro.rs | 30 + tests/ui/traits/item-privacy.rs | 134 + tests/ui/traits/item-privacy.stderr | 188 + tests/ui/traits/kindck-owned-contains-1.rs | 21 + tests/ui/traits/map-types.rs | 19 + tests/ui/traits/map-types.stderr | 12 + tests/ui/traits/matching-lifetimes.rs | 20 + tests/ui/traits/matching-lifetimes.stderr | 41 + tests/ui/traits/method-private.rs | 20 + tests/ui/traits/method-private.stderr | 18 + tests/ui/traits/monad.rs | 48 + .../monomorphized-callees-with-ty-params-3314.rs | 32 + tests/ui/traits/multidispatch-bad.rs | 22 + tests/ui/traits/multidispatch-bad.stderr | 21 + ...ultidispatch-conditional-impl-not-considered.rs | 24 + .../ui/traits/multidispatch-convert-ambig-dest.rs | 31 + .../traits/multidispatch-convert-ambig-dest.stderr | 43 + .../traits/multidispatch-infer-convert-target.rs | 36 + tests/ui/traits/multidispatch1.rs | 33 + tests/ui/traits/multidispatch2.rs | 39 + tests/ui/traits/mutual-recursion-issue-75860.rs | 15 + .../ui/traits/mutual-recursion-issue-75860.stderr | 13 + .../negative-impls/auxiliary/foreign_trait.rs | 7 + tests/ui/traits/negative-impls/eager-mono.rs | 12 + .../explicitly-unimplemented-error-message.rs | 53 + .../explicitly-unimplemented-error-message.stderr | 52 + .../negative-impls/feature-gate-negative_impls.rs | 3 + .../feature-gate-negative_impls.stderr | 12 + .../negative-impls/negated-auto-traits-error.rs | 68 + .../negated-auto-traits-error.stderr | 127 + .../negative-impls/negated-auto-traits-rpass.rs | 21 + .../negative-impls/negative-default-impls.rs | 11 + .../negative-impls/negative-default-impls.stderr | 19 + .../traits/negative-impls/negative-impls-basic.rs | 17 + .../negative-specializes-negative.rs | 13 + .../negative-specializes-negative.stderr | 12 + .../negative-specializes-positive-item.rs | 13 + .../negative-specializes-positive-item.stderr | 22 + .../negative-specializes-positive.rs | 14 + .../negative-specializes-positive.stderr | 21 + tests/ui/traits/negative-impls/no-items.rs | 11 + tests/ui/traits/negative-impls/no-items.stderr | 9 + .../pin-unsound-issue-66544-clone.rs | 26 + .../pin-unsound-issue-66544-clone.stderr | 11 + .../pin-unsound-issue-66544-derefmut.rs | 33 + .../pin-unsound-issue-66544-derefmut.stderr | 11 + .../positive-specializes-negative.rs | 9 + .../positive-specializes-negative.stderr | 21 + .../rely-on-negative-impl-in-coherence.rs | 24 + tests/ui/traits/new-solver/fn-trait-closure.rs | 15 + tests/ui/traits/new-solver/fn-trait.rs | 13 + tests/ui/traits/new-solver/pointer-sized.rs | 12 + tests/ui/traits/new-solver/pointer-sized.stderr | 24 + tests/ui/traits/no-fallback-multiple-impls.rs | 16 + tests/ui/traits/no-fallback-multiple-impls.stderr | 9 + tests/ui/traits/no_send-struct.rs | 17 + tests/ui/traits/no_send-struct.stderr | 18 + tests/ui/traits/normalize-supertrait.rs | 37 + ...ot-suggest-non-existing-fully-qualified-path.rs | 24 + ...uggest-non-existing-fully-qualified-path.stderr | 41 + tests/ui/traits/object-does-not-impl-trait.rs | 8 + tests/ui/traits/object-does-not-impl-trait.stderr | 17 + tests/ui/traits/object-one-type-two-traits.rs | 31 + tests/ui/traits/object/auto-dedup-in-impl.rs | 19 + tests/ui/traits/object/auto-dedup-in-impl.stderr | 12 + tests/ui/traits/object/auto-dedup.rs | 46 + tests/ui/traits/object/bounds-cycle-1.rs | 24 + tests/ui/traits/object/bounds-cycle-2.rs | 28 + tests/ui/traits/object/bounds-cycle-3.rs | 25 + tests/ui/traits/object/bounds-cycle-4.rs | 25 + .../traits/object/enforce-supertrait-projection.rs | 24 + .../object/enforce-supertrait-projection.stderr | 26 + tests/ui/traits/object/exclusion.rs | 19 + tests/ui/traits/object/generics.rs | 41 + .../traits/object/issue-33140-traitobject-crate.rs | 108 + .../object/issue-33140-traitobject-crate.stderr | 95 + tests/ui/traits/object/issue-44454-1.rs | 22 + tests/ui/traits/object/issue-44454-1.stderr | 10 + tests/ui/traits/object/issue-44454-2.rs | 22 + tests/ui/traits/object/issue-44454-2.stderr | 17 + tests/ui/traits/object/issue-44454-3.rs | 33 + tests/ui/traits/object/issue-44454-3.stderr | 11 + tests/ui/traits/object/lifetime-first.rs | 13 + tests/ui/traits/object/macro-matcher.rs | 12 + tests/ui/traits/object/macro-matcher.stderr | 19 + tests/ui/traits/object/safety.rs | 17 + tests/ui/traits/object/safety.stderr | 49 + .../ui/traits/object/supertrait-lifetime-bound.rs | 14 + .../traits/object/supertrait-lifetime-bound.stderr | 11 + tests/ui/traits/object/vs-lifetime-2.rs | 11 + tests/ui/traits/object/vs-lifetime-2.stderr | 9 + tests/ui/traits/object/vs-lifetime.rs | 17 + tests/ui/traits/object/vs-lifetime.stderr | 52 + tests/ui/traits/object/with-lifetime-bound.rs | 34 + .../object/with-self-in-projection-output-bad.rs | 50 + .../with-self-in-projection-output-bad.stderr | 21 + .../object/with-self-in-projection-output-good.rs | 28 + ...elf-in-projection-output-repeated-supertrait.rs | 51 + ...ects-owned-object-borrowed-method-headerless.rs | 30 + .../ui/traits/operator-overloading-issue-52025.rs | 57 + .../overlap-not-permitted-for-builtin-trait.rs | 10 + .../overlap-not-permitted-for-builtin-trait.stderr | 11 + .../traits/overlap-permitted-for-marker-traits.rs | 28 + .../ui/traits/param-without-lifetime-constraint.rs | 20 + .../param-without-lifetime-constraint.stderr | 19 + tests/ui/traits/parameterized-with-bounds.rs | 21 + tests/ui/traits/pointee-deduction.rs | 22 + tests/ui/traits/pointee-tail-is-generic-errors.rs | 22 + .../traits/pointee-tail-is-generic-errors.stderr | 40 + tests/ui/traits/pointee-tail-is-generic.rs | 29 + tests/ui/traits/principal-less-objects.rs | 42 + tests/ui/traits/privacy.rs | 24 + tests/ui/traits/project-modulo-regions.rs | 55 + .../project-modulo-regions.with_clause.stderr | 11 + .../project-modulo-regions.without_clause.stderr | 11 + tests/ui/traits/region-pointer-simple.rs | 21 + .../traits/reservation-impl/coherence-conflict.rs | 14 + .../reservation-impl/coherence-conflict.stderr | 13 + tests/ui/traits/reservation-impl/no-use.rs | 12 + tests/ui/traits/reservation-impl/no-use.stderr | 13 + tests/ui/traits/reservation-impl/non-lattice-ok.rs | 59 + tests/ui/traits/reservation-impl/ok.rs | 28 + tests/ui/traits/resolution-in-overloaded-op.rs | 11 + tests/ui/traits/resolution-in-overloaded-op.stderr | 16 + tests/ui/traits/safety-fn-body.mir.stderr | 11 + tests/ui/traits/safety-fn-body.rs | 19 + tests/ui/traits/safety-fn-body.thir.stderr | 11 + tests/ui/traits/safety-inherent-impl.rs | 9 + tests/ui/traits/safety-inherent-impl.stderr | 11 + tests/ui/traits/safety-ok-cc.rs | 24 + tests/ui/traits/safety-ok.rs | 18 + tests/ui/traits/safety-trait-impl-cc.rs | 15 + tests/ui/traits/safety-trait-impl-cc.stderr | 15 + tests/ui/traits/safety-trait-impl.rs | 18 + tests/ui/traits/safety-trait-impl.stderr | 28 + .../ui/traits/self-without-lifetime-constraint.rs | 53 + .../traits/self-without-lifetime-constraint.stderr | 19 + .../solver-cycles/inductive-canonical-cycle.rs | 69 + tests/ui/traits/static-method-generic-inference.rs | 28 + .../traits/static-method-generic-inference.stderr | 17 + tests/ui/traits/static-method-overwriting.rs | 34 + tests/ui/traits/static-outlives-a-where-clause.rs | 23 + tests/ui/traits/staticness-mismatch.rs | 11 + tests/ui/traits/staticness-mismatch.stderr | 12 + .../ui/traits/suggest-deferences/issue-39029.fixed | 18 + tests/ui/traits/suggest-deferences/issue-39029.rs | 18 + .../traits/suggest-deferences/issue-39029.stderr | 19 + .../ui/traits/suggest-deferences/issue-62530.fixed | 15 + tests/ui/traits/suggest-deferences/issue-62530.rs | 15 + .../traits/suggest-deferences/issue-62530.stderr | 21 + .../ui/traits/suggest-deferences/multiple-0.fixed | 36 + tests/ui/traits/suggest-deferences/multiple-0.rs | 36 + .../ui/traits/suggest-deferences/multiple-0.stderr | 21 + tests/ui/traits/suggest-deferences/multiple-1.rs | 54 + .../ui/traits/suggest-deferences/multiple-1.stderr | 18 + .../suggest-deferences/root-obligation.fixed | 13 + .../traits/suggest-deferences/root-obligation.rs | 13 + .../suggest-deferences/root-obligation.stderr | 21 + .../suggest-dereferencing-receiver-argument.fixed | 14 + .../suggest-dereferencing-receiver-argument.rs | 14 + .../suggest-dereferencing-receiver-argument.stderr | 15 + tests/ui/traits/suggest-fully-qualified-closure.rs | 24 + .../traits/suggest-fully-qualified-closure.stderr | 34 + ...suggest-fully-qualified-path-with-adjustment.rs | 60 + ...est-fully-qualified-path-with-adjustment.stderr | 186 + ...gest-fully-qualified-path-without-adjustment.rs | 64 + ...-fully-qualified-path-without-adjustment.stderr | 224 + tests/ui/traits/suggest-where-clause.rs | 36 + tests/ui/traits/suggest-where-clause.stderr | 90 + tests/ui/traits/superdefault-generics.rs | 39 + tests/ui/traits/syntax-polarity.rs | 21 + tests/ui/traits/syntax-trait-polarity.rs | 25 + tests/ui/traits/syntax-trait-polarity.stderr | 37 + tests/ui/traits/test-2.rs | 17 + tests/ui/traits/test-2.stderr | 85 + tests/ui/traits/test.rs | 6 + tests/ui/traits/test.stderr | 9 + tests/ui/traits/to-str.rs | 36 + tests/ui/traits/track-obligations.rs | 88 + tests/ui/traits/track-obligations.stderr | 76 + tests/ui/traits/trait-or-new-type-instead.rs | 6 + tests/ui/traits/trait-or-new-type-instead.stderr | 14 + tests/ui/traits/trait-upcasting/basic.rs | 86 + .../correct-supertrait-substitution.rs | 38 + .../trait-upcasting/cyclic-trait-resolution.rs | 13 + .../trait-upcasting/cyclic-trait-resolution.stderr | 21 + tests/ui/traits/trait-upcasting/diamond.rs | 114 + tests/ui/traits/trait-upcasting/invalid-upcast.rs | 86 + .../traits/trait-upcasting/invalid-upcast.stderr | 168 + .../issue-11515-upcast-fn_mut-fn.rs | 12 + tests/ui/traits/trait-upcasting/lifetime.rs | 94 + .../ui/traits/trait-upcasting/migrate-lint-deny.rs | 27 + .../trait-upcasting/migrate-lint-deny.stderr | 19 + .../multiple-occurrence-ambiguousity.rs | 21 + .../multiple-occurrence-ambiguousity.stderr | 14 + tests/ui/traits/trait-upcasting/replace-vptr.rs | 48 + tests/ui/traits/trait-upcasting/struct.rs | 173 + tests/ui/traits/trait-upcasting/subtrait-method.rs | 69 + .../traits/trait-upcasting/subtrait-method.stderr | 68 + .../traits/trait-upcasting/type-checking-test-1.rs | 26 + .../trait-upcasting/type-checking-test-1.stderr | 23 + .../traits/trait-upcasting/type-checking-test-2.rs | 31 + .../trait-upcasting/type-checking-test-2.stderr | 42 + .../type-checking-test-3.polonius.stderr | 18 + .../traits/trait-upcasting/type-checking-test-3.rs | 20 + .../trait-upcasting/type-checking-test-3.stderr | 18 + .../type-checking-test-4.polonius.stderr | 52 + .../traits/trait-upcasting/type-checking-test-4.rs | 48 + .../trait-upcasting/type-checking-test-4.stderr | 52 + tests/ui/traits/typeclasses-eq-example-static.rs | 68 + tests/ui/traits/typeclasses-eq-example.rs | 64 + tests/ui/traits/ufcs-object.rs | 17 + tests/ui/traits/unspecified-self-in-trait-ref.rs | 30 + .../ui/traits/unspecified-self-in-trait-ref.stderr | 105 + tests/ui/traits/use-before-def.rs | 10 + tests/ui/traits/vtable-res-trait-param.rs | 23 + tests/ui/traits/vtable-res-trait-param.stderr | 17 + tests/ui/traits/vtable/issue-91807.rs | 17 + tests/ui/traits/vtable/issue-97381.rs | 30 + tests/ui/traits/vtable/issue-97381.stderr | 15 + tests/ui/traits/vtable/vtable-diamond.rs | 44 + tests/ui/traits/vtable/vtable-diamond.stderr | 29 + tests/ui/traits/vtable/vtable-multi-level.rs | 143 + tests/ui/traits/vtable/vtable-multi-level.stderr | 203 + tests/ui/traits/vtable/vtable-multiple.rs | 33 + tests/ui/traits/vtable/vtable-multiple.stderr | 27 + tests/ui/traits/vtable/vtable-non-object-safe.rs | 18 + .../ui/traits/vtable/vtable-non-object-safe.stderr | 16 + tests/ui/traits/vtable/vtable-vacant.rs | 31 + tests/ui/traits/vtable/vtable-vacant.stderr | 16 + tests/ui/traits/wf-object/maybe-bound.rs | 18 + tests/ui/traits/wf-object/maybe-bound.stderr | 32 + tests/ui/traits/wf-object/no-duplicates.rs | 33 + tests/ui/traits/wf-object/no-duplicates.stderr | 58 + tests/ui/traits/wf-object/only-maybe-bound.rs | 7 + tests/ui/traits/wf-object/only-maybe-bound.stderr | 15 + tests/ui/traits/wf-object/reverse-order.rs | 15 + tests/ui/traits/where-clause-vs-impl.rs | 45 + tests/ui/traits/with-bounds-default.rs | 32 + tests/ui/traits/with-dst.rs | 22 + .../abstraction/abstracted_assume.rs | 72 + .../abstraction/const_generic_fn.rs | 41 + .../arrays/issue-103783-array-length.rs | 24 + .../arrays/issue-103783-array-length.stderr | 9 + .../arrays/should_have_correct_length.rs | 44 + .../arrays/should_inherit_alignment.rs | 60 + .../arrays/should_require_well_defined_layout.rs | 66 + .../should_require_well_defined_layout.stderr | 135 + .../primitive_reprs_should_have_correct_length.rs | 156 + ...imitive_reprs_should_have_correct_length.stderr | 463 + .../repr/should_require_well_defined_layout.rs | 124 + .../repr/should_require_well_defined_layout.stderr | 141 + .../enums/should_order_correctly.rs | 36 + .../transmutability/enums/should_pad_variants.rs | 45 + .../enums/should_pad_variants.stderr | 25 + .../enums/should_respect_endianness.rs | 37 + .../enums/should_respect_endianness.stderr | 25 + tests/ui/transmutability/issue-101739-1.rs | 21 + tests/ui/transmutability/issue-101739-1.stderr | 16 + tests/ui/transmutability/issue-101739-2.rs | 37 + tests/ui/transmutability/issue-101739-2.stderr | 14 + .../feature-missing.rs | 9 + .../feature-missing.stderr | 21 + .../malformed-program-gracefulness/unknown_dst.rs | 21 + .../unknown_dst.stderr | 14 + .../malformed-program-gracefulness/unknown_src.rs | 21 + .../unknown_src.stderr | 14 + .../unknown_src_field.rs | 22 + .../unknown_src_field.stderr | 9 + .../wrong-type-assume.rs | 53 + .../wrong-type-assume.stderr | 27 + tests/ui/transmutability/primitives/bool.rs | 25 + tests/ui/transmutability/primitives/bool.stderr | 19 + tests/ui/transmutability/primitives/numbers.rs | 128 + tests/ui/transmutability/primitives/numbers.stderr | 915 ++ tests/ui/transmutability/primitives/unit.rs | 29 + tests/ui/transmutability/primitives/unit.stderr | 25 + tests/ui/transmutability/references.rs | 27 + tests/ui/transmutability/references.stderr | 26 + .../structs/repr/should_handle_align.rs | 43 + .../structs/repr/should_handle_packed.rs | 42 + .../repr/should_require_well_defined_layout.rs | 83 + .../repr/should_require_well_defined_layout.stderr | 279 + .../structs/should_order_fields_correctly.rs | 36 + tests/ui/transmutability/unions/boolish.rs | 31 + .../unions/repr/should_handle_align.rs | 47 + .../unions/repr/should_handle_packed.rs | 48 + .../repr/should_require_well_defined_layout.rs | 44 + .../repr/should_require_well_defined_layout.stderr | 49 + .../transmutability/unions/should_pad_variants.rs | 45 + .../unions/should_pad_variants.stderr | 25 + ...d_permit_intersecting_if_validity_is_assumed.rs | 38 + .../unions/should_reject_contraction.rs | 36 + .../unions/should_reject_contraction.stderr | 19 + .../unions/should_reject_disjoint.rs | 35 + .../unions/should_reject_disjoint.stderr | 35 + .../unions/should_reject_intersecting.rs | 38 + .../unions/should_reject_intersecting.stderr | 35 + .../should_accept_if_dst_has_private_field.rs | 38 + .../should_accept_if_dst_has_private_variant.rs | 39 + ...d_accept_if_dst_has_tricky_unreachable_field.rs | 46 + .../should_accept_if_dst_has_unreachable_field.rs | 39 + ...ould_accept_if_dst_has_unreachable_field.stderr | 12 + .../should_accept_if_dst_has_unreachable_ty.rs | 40 + .../should_accept_if_dst_has_unreachable_ty.stderr | 15 + .../should_accept_if_src_has_private_field.rs | 37 + .../should_accept_if_src_has_private_variant.rs | 38 + .../should_accept_if_src_has_unreachable_field.rs | 37 + ...ould_accept_if_src_has_unreachable_field.stderr | 12 + .../should_accept_if_src_has_unreachable_ty.rs | 38 + .../should_accept_if_src_has_unreachable_ty.stderr | 15 + .../should_reject_if_dst_has_private_field.rs | 36 + .../should_reject_if_dst_has_private_field.stderr | 19 + .../should_reject_if_dst_has_private_variant.rs | 37 + ...should_reject_if_dst_has_private_variant.stderr | 19 + ...d_reject_if_dst_has_tricky_unreachable_field.rs | 51 + .../should_reject_if_dst_has_unreachable_field.rs | 38 + ...ould_reject_if_dst_has_unreachable_field.stderr | 19 + .../should_reject_if_dst_has_unreachable_ty.rs | 41 + .../should_reject_if_dst_has_unreachable_ty.stderr | 32 + tests/ui/transmute-equal-assoc-types.rs | 11 + tests/ui/transmute-non-immediate-to-immediate.rs | 11 + tests/ui/transmute/lifetimes.rs | 23 + tests/ui/transmute/main.rs | 29 + tests/ui/transmute/main.stderr | 30 + tests/ui/transmute/transmute-different-sizes.rs | 31 + .../ui/transmute/transmute-different-sizes.stderr | 30 + tests/ui/transmute/transmute-fat-pointers.rs | 33 + tests/ui/transmute/transmute-fat-pointers.stderr | 39 + .../transmute-from-fn-item-types-error.rs | 60 + .../transmute-from-fn-item-types-error.stderr | 92 + tests/ui/transmute/transmute-impl.rs | 25 + tests/ui/transmute/transmute-impl.stderr | 12 + tests/ui/transmute/transmute-imut-to-mut.rs | 8 + tests/ui/transmute/transmute-imut-to-mut.stderr | 10 + tests/ui/transmute/transmute-padding-ice.rs | 29 + tests/ui/transmute/transmute-padding-ice.stderr | 24 + tests/ui/transmute/transmute-type-parameters.rs | 44 + .../ui/transmute/transmute-type-parameters.stderr | 57 + tests/ui/treat-err-as-bug/delay_span_bug.rs | 12 + tests/ui/treat-err-as-bug/delay_span_bug.stderr | 11 + tests/ui/treat-err-as-bug/err.rs | 12 + tests/ui/treat-err-as-bug/err.stderr | 12 + .../issue-73021-impossible-inline.inline.stderr | 46 + .../issue-73021-impossible-inline.no-opt.stderr | 46 + .../issue-73021-impossible-inline.rs | 71 + ...ial-bounds-inconsistent-associated-functions.rs | 23 + .../trivial-bounds-inconsistent-copy-reborrow.rs | 13 + ...rivial-bounds-inconsistent-copy-reborrow.stderr | 25 + .../trivial-bounds-inconsistent-copy.rs | 33 + .../trivial-bounds-inconsistent-copy.stderr | 28 + ...trivial-bounds-inconsistent-projection-error.rs | 23 + ...ial-bounds-inconsistent-projection-error.stderr | 17 + .../trivial-bounds-inconsistent-projection.rs | 58 + .../trivial-bounds-inconsistent-projection.stderr | 46 + .../trivial-bounds-inconsistent-sized.rs | 27 + .../trivial-bounds-inconsistent-sized.stderr | 22 + .../trivial-bounds-inconsistent-well-formed.rs | 14 + .../trivial-bounds-inconsistent-well-formed.stderr | 16 + .../trivial-bounds/trivial-bounds-inconsistent.rs | 74 + .../trivial-bounds-inconsistent.stderr | 95 + .../ui/trivial-bounds/trivial-bounds-leak-copy.rs | 12 + .../trivial-bounds/trivial-bounds-leak-copy.stderr | 9 + tests/ui/trivial-bounds/trivial-bounds-leak.rs | 31 + tests/ui/trivial-bounds/trivial-bounds-leak.stderr | 48 + tests/ui/trivial-bounds/trivial-bounds-lint.rs | 40 + tests/ui/trivial-bounds/trivial-bounds-lint.stderr | 50 + tests/ui/trivial-bounds/trivial-bounds-object.rs | 18 + tests/ui/trivial_casts-rpass.rs | 62 + tests/ui/try-block/issue-45124.rs | 18 + tests/ui/try-block/try-block-bad-lifetime.rs | 37 + tests/ui/try-block/try-block-bad-lifetime.stderr | 52 + tests/ui/try-block/try-block-bad-type.rs | 21 + tests/ui/try-block/try-block-bad-type.stderr | 42 + tests/ui/try-block/try-block-catch.rs | 10 + tests/ui/try-block/try-block-catch.stderr | 10 + tests/ui/try-block/try-block-in-edition2015.rs | 10 + tests/ui/try-block/try-block-in-edition2015.stderr | 24 + tests/ui/try-block/try-block-in-match.rs | 11 + tests/ui/try-block/try-block-in-return.rs | 12 + tests/ui/try-block/try-block-in-while.rs | 8 + tests/ui/try-block/try-block-in-while.stderr | 11 + tests/ui/try-block/try-block-maybe-bad-lifetime.rs | 44 + .../try-block/try-block-maybe-bad-lifetime.stderr | 46 + tests/ui/try-block/try-block-opt-init.rs | 16 + tests/ui/try-block/try-block-opt-init.stderr | 17 + tests/ui/try-block/try-block-type-error.rs | 18 + tests/ui/try-block/try-block-type-error.stderr | 18 + .../try-block/try-block-unreachable-code-lint.rs | 76 + .../try-block-unreachable-code-lint.stderr | 40 + tests/ui/try-block/try-block-unused-delims.fixed | 29 + tests/ui/try-block/try-block-unused-delims.rs | 29 + tests/ui/try-block/try-block-unused-delims.stderr | 72 + tests/ui/try-block/try-block.rs | 75 + .../ui/try-block/try-is-identifier-edition2015.rs | 11 + tests/ui/try-from-int-error-partial-eq.rs | 12 + tests/ui/try-operator-hygiene.rs | 26 + tests/ui/try-operator.rs | 192 + tests/ui/try-trait/bad-interconversion.rs | 48 + tests/ui/try-trait/bad-interconversion.stderr | 103 + tests/ui/try-trait/option-to-result.rs | 13 + tests/ui/try-trait/option-to-result.stderr | 31 + tests/ui/try-trait/try-as-monad.rs | 24 + tests/ui/try-trait/try-on-option-diagnostics.rs | 47 + .../ui/try-trait/try-on-option-diagnostics.stderr | 47 + tests/ui/try-trait/try-on-option.rs | 13 + tests/ui/try-trait/try-on-option.stderr | 28 + tests/ui/try-trait/try-operator-custom.rs | 91 + tests/ui/try-trait/try-operator-on-main.rs | 22 + tests/ui/try-trait/try-operator-on-main.stderr | 53 + tests/ui/try-trait/try-poll.rs | 50 + tests/ui/try-trait/yeet-for-option.rs | 11 + tests/ui/try-trait/yeet-for-result.rs | 11 + tests/ui/tuple-index.rs | 32 + tests/ui/tuple/add-tuple-within-arguments.rs | 10 + tests/ui/tuple/add-tuple-within-arguments.stderr | 40 + tests/ui/tuple/array-diagnostics.rs | 7 + tests/ui/tuple/array-diagnostics.stderr | 9 + tests/ui/tuple/builtin-fail.rs | 19 + tests/ui/tuple/builtin-fail.stderr | 55 + tests/ui/tuple/builtin.rs | 20 + tests/ui/tuple/index-float.rs | 10 + tests/ui/tuple/index-invalid.rs | 7 + tests/ui/tuple/index-invalid.stderr | 21 + tests/ui/tuple/indexing-in-macro.rs | 9 + tests/ui/tuple/nested-index.rs | 12 + tests/ui/tuple/one-tuple.rs | 15 + tests/ui/tuple/tup.rs | 21 + tests/ui/tuple/tuple-arity-mismatch.rs | 17 + tests/ui/tuple/tuple-arity-mismatch.stderr | 35 + tests/ui/tuple/tuple-index-fat-types.rs | 13 + tests/ui/tuple/tuple-index-not-tuple.rs | 10 + tests/ui/tuple/tuple-index-not-tuple.stderr | 15 + tests/ui/tuple/tuple-index-out-of-bounds.rs | 14 + tests/ui/tuple/tuple-index-out-of-bounds.stderr | 15 + tests/ui/tuple/tuple-struct-fields/test.rs | 9 + tests/ui/tuple/tuple-struct-fields/test.stderr | 17 + tests/ui/tuple/tuple-struct-fields/test2.rs | 15 + tests/ui/tuple/tuple-struct-fields/test2.stderr | 28 + tests/ui/tuple/tuple-struct-fields/test3.rs | 15 + tests/ui/tuple/tuple-struct-fields/test3.stderr | 28 + tests/ui/tuple/wrong_argument_ice-2.rs | 17 + tests/ui/tuple/wrong_argument_ice-2.stderr | 19 + tests/ui/tuple/wrong_argument_ice-3.rs | 17 + tests/ui/tuple/wrong_argument_ice-3.stderr | 23 + tests/ui/tuple/wrong_argument_ice-4.rs | 6 + tests/ui/tuple/wrong_argument_ice-4.stderr | 23 + tests/ui/tuple/wrong_argument_ice.rs | 17 + tests/ui/tuple/wrong_argument_ice.stderr | 16 + tests/ui/tydesc-name.rs | 14 + .../enum-variant-generic-args-pass.rs | 59 + .../enum-variant-generic-args.rs | 105 + .../enum-variant-generic-args.stderr | 512 + ...-variant-priority-higher-than-other-inherent.rs | 23 + ...iant-priority-higher-than-other-inherent.stderr | 28 + ...ant-priority-lint-ambiguous_associated_items.rs | 41 + ...priority-lint-ambiguous_associated_items.stderr | 41 + ...orrect-variant-form-through-Self-issue-58006.rs | 14 + ...ct-variant-form-through-Self-issue-58006.stderr | 9 + .../incorrect-variant-form-through-alias-caught.rs | 19 + ...orrect-variant-form-through-alias-caught.stderr | 45 + tests/ui/type-alias-enum-variants/issue-57866.rs | 24 + .../issue-61801-path-pattern-can-infer.rs | 28 + ...ssue-63151-dead-code-lint-fields-in-patterns.rs | 26 + .../no-type-application-on-aliased-enum-variant.rs | 14 + ...type-application-on-aliased-enum-variant.stderr | 11 + ...-to-enum-variant-in-type-namespace-and-error.rs | 11 + ...enum-variant-in-type-namespace-and-error.stderr | 8 + .../self-in-enum-definition.rs | 8 + .../self-in-enum-definition.stderr | 73 + .../type-alias-enum-variants-pass.rs | 69 + tests/ui/type-alias-impl-trait/argument-types.rs | 26 + .../type-alias-impl-trait/assoc-projection-ice.rs | 24 + tests/ui/type-alias-impl-trait/assoc-type-const.rs | 32 + .../assoc-type-lifetime-unconstrained.rs | 26 + .../assoc-type-lifetime-unconstrained.stderr | 9 + .../type-alias-impl-trait/assoc-type-lifetime.rs | 26 + .../associated-type-alias-impl-trait.rs | 26 + .../associated-type-impl-trait-lifetime.rs | 20 + .../ui/type-alias-impl-trait/auto-trait-leakage.rs | 18 + .../type-alias-impl-trait/auto-trait-leakage2.rs | 25 + .../auto-trait-leakage2.stderr | 26 + .../type-alias-impl-trait/auto-trait-leakage3.rs | 21 + .../auto-trait-leakage3.stderr | 22 + .../auxiliary/coherence_cross_crate_trait_decl.rs | 9 + .../auxiliary/collect_hidden_types.rs | 21 + .../auxiliary/cross_crate_ice.rs | 10 + .../auxiliary/cross_crate_ice2.rs | 20 + .../auxiliary/foreign-crate.rs | 2 + tests/ui/type-alias-impl-trait/bound_reduction.rs | 19 + tests/ui/type-alias-impl-trait/bound_reduction2.rs | 18 + .../type-alias-impl-trait/bound_reduction2.stderr | 12 + .../type-alias-impl-trait/bounds-are-checked-2.rs | 19 + .../bounds-are-checked-2.stderr | 14 + .../ui/type-alias-impl-trait/bounds-are-checked.rs | 24 + .../bounds-are-checked.stderr | 19 + tests/ui/type-alias-impl-trait/closure_args.rs | 16 + tests/ui/type-alias-impl-trait/closure_args2.rs | 23 + .../type-alias-impl-trait/closure_parent_substs.rs | 65 + .../type-alias-impl-trait/closure_wf_outlives.rs | 65 + .../closure_wf_outlives.stderr | 64 + .../type-alias-impl-trait/closures_in_branches.rs | 31 + .../closures_in_branches.stderr | 25 + tests/ui/type-alias-impl-trait/coherence.rs | 17 + tests/ui/type-alias-impl-trait/coherence.stderr | 14 + .../type-alias-impl-trait/coherence_cross_crate.rs | 24 + .../coherence_cross_crate.stderr | 13 + .../coherence_generalization.rs | 13 + .../type-alias-impl-trait/collect_hidden_types.rs | 22 + tests/ui/type-alias-impl-trait/constrain_inputs.rs | 33 + .../type-alias-impl-trait/constrain_inputs.stderr | 58 + .../constrain_inputs_unsound.rs | 31 + .../constrain_inputs_unsound.stderr | 9 + tests/ui/type-alias-impl-trait/cross_crate_ice.rs | 16 + tests/ui/type-alias-impl-trait/cross_crate_ice2.rs | 11 + tests/ui/type-alias-impl-trait/cross_inference.rs | 10 + .../cross_inference_pattern_bug.rs | 9 + .../cross_inference_pattern_bug_no_type.rs | 13 + .../type-alias-impl-trait/cross_inference_rpit.rs | 14 + .../declared_but_never_defined.rs | 6 + .../declared_but_never_defined.stderr | 10 + .../declared_but_not_defined_in_scope.rs | 13 + .../declared_but_not_defined_in_scope.stderr | 25 + .../defining-use-submodule.rs | 23 + tests/ui/type-alias-impl-trait/destructuring.rs | 10 + .../different_defining_uses.rs | 15 + .../different_defining_uses.stderr | 14 + .../different_defining_uses_never_type.rs | 18 + .../different_defining_uses_never_type.stderr | 14 + .../different_defining_uses_never_type2.rs | 44 + .../different_defining_uses_never_type3.rs | 12 + .../different_defining_uses_never_type3.stderr | 14 + .../different_lifetimes_defining_uses.rs | 19 + .../different_lifetimes_defining_uses.stderr | 14 + tests/ui/type-alias-impl-trait/fallback.rs | 28 + tests/ui/type-alias-impl-trait/fallback.stderr | 17 + tests/ui/type-alias-impl-trait/field-types.rs | 18 + tests/ui/type-alias-impl-trait/future.rs | 22 + tests/ui/type-alias-impl-trait/future.stderr | 19 + .../generic_different_defining_uses.rs | 14 + .../generic_different_defining_uses.stderr | 14 + .../generic_duplicate_lifetime_param.rs | 14 + .../generic_duplicate_lifetime_param.stderr | 14 + .../generic_duplicate_param_use.rs | 33 + .../generic_duplicate_param_use.stderr | 38 + .../generic_duplicate_param_use10.rs | 12 + .../generic_duplicate_param_use2.rs | 13 + .../generic_duplicate_param_use2.stderr | 14 + .../generic_duplicate_param_use3.rs | 18 + .../generic_duplicate_param_use3.stderr | 25 + .../generic_duplicate_param_use4.rs | 13 + .../generic_duplicate_param_use4.stderr | 14 + .../generic_duplicate_param_use5.rs | 20 + .../generic_duplicate_param_use5.stderr | 51 + .../generic_duplicate_param_use6.rs | 19 + .../generic_duplicate_param_use6.stderr | 39 + .../generic_duplicate_param_use7.rs | 24 + .../generic_duplicate_param_use8.rs | 17 + .../generic_duplicate_param_use8.stderr | 27 + .../generic_duplicate_param_use9.rs | 25 + .../generic_duplicate_param_use9.stderr | 62 + .../generic_lifetime_param.rs | 12 + .../generic_nondefining_use.rs | 28 + .../generic_nondefining_use.stderr | 30 + tests/ui/type-alias-impl-trait/generic_not_used.rs | 11 + .../type-alias-impl-trait/generic_not_used.stderr | 14 + .../generic_type_does_not_live_long_enough.rs | 16 + .../generic_type_does_not_live_long_enough.stderr | 30 + .../generic_underconstrained.rs | 12 + .../generic_underconstrained.stderr | 19 + .../generic_underconstrained2.rs | 19 + .../generic_underconstrained2.stderr | 35 + .../impl-with-unconstrained-param.rs | 17 + .../impl-with-unconstrained-param.stderr | 9 + .../impl_trait_for_generic_tait.rs | 23 + .../impl_trait_for_same_tait.rs | 33 + .../impl_trait_for_same_tait.stderr | 30 + .../type-alias-impl-trait/impl_trait_for_tait.rs | 21 + .../impl_trait_for_tait_bound.rs | 19 + .../impl_trait_for_tait_bound.stderr | 16 + .../impl_trait_for_tait_bound2.rs | 16 + .../impl_trait_for_tait_bound2.stderr | 16 + tests/ui/type-alias-impl-trait/implied_bounds.rs | 51 + .../ui/type-alias-impl-trait/implied_bounds.stderr | 16 + tests/ui/type-alias-impl-trait/implied_bounds2.rs | 10 + tests/ui/type-alias-impl-trait/implied_bounds3.rs | 18 + .../implied_bounds_closure.rs | 31 + .../implied_bounds_closure.stderr | 11 + .../implied_bounds_from_types.rs | 51 + .../implied_bounds_from_types.stderr | 16 + .../implied_lifetime_wf_check.rs | 27 + .../implied_lifetime_wf_check3.rs | 43 + .../implied_lifetime_wf_check3.stderr | 58 + .../implied_lifetime_wf_check4_static.rs | 11 + .../implied_lifetime_wf_check4_static.stderr | 14 + .../imply_bounds_from_bounds.rs | 25 + .../imply_bounds_from_bounds_param.rs | 38 + .../imply_bounds_from_bounds_param.stderr | 16 + .../incoherent-assoc-imp-trait.rs | 15 + .../incoherent-assoc-imp-trait.stderr | 12 + .../type-alias-impl-trait/incomplete-inference.rs | 14 + .../incomplete-inference.stderr | 14 + tests/ui/type-alias-impl-trait/inference-cycle.rs | 25 + .../type-alias-impl-trait/inference-cycle.stderr | 22 + tests/ui/type-alias-impl-trait/issue-101750.rs | 37 + tests/ui/type-alias-impl-trait/issue-104817.rs | 19 + .../issue-104817.stock.stderr | 11 + .../issue-52843-closure-constrain.rs | 13 + .../issue-52843-closure-constrain.stderr | 14 + tests/ui/type-alias-impl-trait/issue-52843.rs | 15 + tests/ui/type-alias-impl-trait/issue-52843.stderr | 14 + tests/ui/type-alias-impl-trait/issue-53092-2.rs | 14 + .../ui/type-alias-impl-trait/issue-53092-2.stderr | 46 + tests/ui/type-alias-impl-trait/issue-53092.rs | 19 + tests/ui/type-alias-impl-trait/issue-53092.stderr | 19 + tests/ui/type-alias-impl-trait/issue-53096.rs | 11 + tests/ui/type-alias-impl-trait/issue-53096.stderr | 8 + .../issue-53398-cyclic-types.rs | 10 + .../issue-53398-cyclic-types.stderr | 12 + tests/ui/type-alias-impl-trait/issue-53598.rs | 27 + tests/ui/type-alias-impl-trait/issue-53598.stderr | 8 + .../issue-53678-generator-and-const-fn.rs | 19 + .../issue-53678-generator-and-const-fn.stderr | 8 + .../issue-55099-lifetime-inference.rs | 26 + .../issue-57188-associate-impl-capture.rs | 24 + .../issue-57611-trait-alias.rs | 26 + tests/ui/type-alias-impl-trait/issue-57700.rs | 21 + tests/ui/type-alias-impl-trait/issue-57700.stderr | 8 + .../issue-57807-associated-type.rs | 31 + tests/ui/type-alias-impl-trait/issue-57961.rs | 18 + tests/ui/type-alias-impl-trait/issue-57961.stderr | 20 + .../issue-58662-generator-with-lifetime.rs | 39 + .../issue-58662-simplified.rs | 20 + tests/ui/type-alias-impl-trait/issue-58887.rs | 22 + tests/ui/type-alias-impl-trait/issue-58951-2.rs | 18 + tests/ui/type-alias-impl-trait/issue-58951.rs | 15 + tests/ui/type-alias-impl-trait/issue-60371.rs | 14 + tests/ui/type-alias-impl-trait/issue-60371.stderr | 21 + tests/ui/type-alias-impl-trait/issue-60407.rs | 15 + tests/ui/type-alias-impl-trait/issue-60407.stderr | 8 + .../type-alias-impl-trait/issue-60564-working.rs | 24 + tests/ui/type-alias-impl-trait/issue-60564.rs | 25 + tests/ui/type-alias-impl-trait/issue-60564.stderr | 12 + tests/ui/type-alias-impl-trait/issue-60662.rs | 10 + tests/ui/type-alias-impl-trait/issue-60662.stdout | 14 + .../issue-62000-associate-impl-trait-lifetimes.rs | 38 + .../issue-63263-closure-return.rs | 13 + tests/ui/type-alias-impl-trait/issue-63279.rs | 15 + tests/ui/type-alias-impl-trait/issue-63279.stderr | 48 + tests/ui/type-alias-impl-trait/issue-63355.rs | 46 + .../issue-63677-type-alias-coherence.rs | 21 + tests/ui/type-alias-impl-trait/issue-65384.rs | 15 + tests/ui/type-alias-impl-trait/issue-65384.stderr | 12 + .../issue-65679-inst-opaque-ty-from-val-twice.rs | 18 + tests/ui/type-alias-impl-trait/issue-65918.rs | 51 + .../issue-66580-closure-coherence.rs | 21 + .../issue-67844-nested-opaque.rs | 33 + .../issue-68368-non-defining-use-2.rs | 14 + .../issue-68368-non-defining-use-2.stderr | 12 + .../issue-68368-non-defining-use.rs | 14 + .../issue-68368-non-defining-use.stderr | 12 + .../issue-69136-inner-lifetime-resolve-error.rs | 23 + ...issue-69136-inner-lifetime-resolve-error.stderr | 29 + .../issue-69136-inner-lifetime-resolve-ok.rs | 23 + tests/ui/type-alias-impl-trait/issue-69323.rs | 16 + tests/ui/type-alias-impl-trait/issue-70121.rs | 23 + tests/ui/type-alias-impl-trait/issue-72793.rs | 25 + tests/ui/type-alias-impl-trait/issue-74244.rs | 20 + tests/ui/type-alias-impl-trait/issue-74244.stderr | 9 + tests/ui/type-alias-impl-trait/issue-74280.rs | 12 + tests/ui/type-alias-impl-trait/issue-74280.stderr | 12 + tests/ui/type-alias-impl-trait/issue-74761-2.rs | 15 + .../ui/type-alias-impl-trait/issue-74761-2.stderr | 15 + tests/ui/type-alias-impl-trait/issue-74761.rs | 15 + tests/ui/type-alias-impl-trait/issue-74761.stderr | 15 + .../issue-76202-trait-impl-for-tait.rs | 31 + tests/ui/type-alias-impl-trait/issue-77179.rs | 14 + tests/ui/type-alias-impl-trait/issue-77179.stderr | 12 + tests/ui/type-alias-impl-trait/issue-78450.rs | 25 + .../issue-84660-trait-impl-for-tait.rs | 25 + .../issue-84660-unsoundness.rs | 41 + .../issue-84660-unsoundness.stderr | 12 + .../issue-87455-static-lifetime-ice.rs | 73 + tests/ui/type-alias-impl-trait/issue-89686.rs | 23 + tests/ui/type-alias-impl-trait/issue-89686.stderr | 14 + tests/ui/type-alias-impl-trait/issue-89952.rs | 31 + tests/ui/type-alias-impl-trait/issue-90400-1.rs | 29 + .../ui/type-alias-impl-trait/issue-90400-1.stderr | 19 + tests/ui/type-alias-impl-trait/issue-90400-2.rs | 37 + .../ui/type-alias-impl-trait/issue-90400-2.stderr | 21 + tests/ui/type-alias-impl-trait/issue-93411.rs | 19 + tests/ui/type-alias-impl-trait/issue-94429.rs | 23 + tests/ui/type-alias-impl-trait/issue-94429.stderr | 9 + .../issue-96572-unconstrained-mismatch.rs | 10 + .../issue-96572-unconstrained-mismatch.stderr | 15 + .../issue-96572-unconstrained.rs | 92 + tests/ui/type-alias-impl-trait/issue-98604.rs | 11 + tests/ui/type-alias-impl-trait/issue-98604.stderr | 18 + tests/ui/type-alias-impl-trait/issue-98608.rs | 11 + tests/ui/type-alias-impl-trait/issue-98608.stderr | 16 + .../missing_lifetime_bound.rs | 7 + .../missing_lifetime_bound.stderr | 11 + .../multiple-def-uses-in-one-fn-infer.rs | 13 + .../multiple-def-uses-in-one-fn-infer.stderr | 11 + .../multiple-def-uses-in-one-fn-lifetimes.rs | 13 + .../multiple-def-uses-in-one-fn-lifetimes.stderr | 11 + .../multiple-def-uses-in-one-fn-pass.rs | 25 + .../multiple-def-uses-in-one-fn.rs | 16 + .../multiple-def-uses-in-one-fn.stderr | 15 + .../multiple-def-uses-in-one-fn2.rs | 16 + .../multiple-def-uses-in-one-fn2.stderr | 11 + .../multiple-def-uses-in-one-fn3.rs | 18 + .../multiple-def-uses-in-one-fn3.stderr | 18 + .../type-alias-impl-trait/multiple_definitions.rs | 30 + .../type-alias-impl-trait/nested-tait-inference.rs | 18 + .../nested-tait-inference.stderr | 14 + .../nested-tait-inference2.rs | 18 + .../nested-tait-inference2.stderr | 16 + .../nested-tait-inference3.rs | 17 + .../nested-tait-inference3.stderr | 10 + tests/ui/type-alias-impl-trait/nested.rs | 17 + tests/ui/type-alias-impl-trait/nested.stderr | 12 + .../nested_type_alias_impl_trait.rs | 20 + .../nested_type_alias_impl_trait.stderr | 19 + .../never_reveal_concrete_type.rs | 14 + .../no_inferrable_concrete_type.rs | 18 + .../no_inferrable_concrete_type.stderr | 10 + .../no_revealing_outside_defining_module.rs | 24 + .../no_revealing_outside_defining_module.stderr | 31 + .../ui/type-alias-impl-trait/not_a_defining_use.rs | 36 + .../not_a_defining_use.stderr | 38 + tests/ui/type-alias-impl-trait/not_well_formed.rs | 17 + .../type-alias-impl-trait/not_well_formed.stderr | 9 + .../ui/type-alias-impl-trait/outlives-bound-var.rs | 18 + tests/ui/type-alias-impl-trait/reveal_local.rs | 25 + tests/ui/type-alias-impl-trait/reveal_local.stderr | 28 + .../ui/type-alias-impl-trait/self-referential-2.rs | 10 + .../self-referential-2.stderr | 14 + .../ui/type-alias-impl-trait/self-referential-3.rs | 14 + .../ui/type-alias-impl-trait/self-referential-4.rs | 25 + .../self-referential-4.stderr | 36 + tests/ui/type-alias-impl-trait/self-referential.rs | 28 + .../type-alias-impl-trait/self-referential.stderr | 39 + tests/ui/type-alias-impl-trait/self_implication.rs | 38 + .../ui/type-alias-impl-trait/static-const-types.rs | 13 + .../structural-match-no-leak.rs | 20 + .../structural-match-no-leak.stderr | 8 + tests/ui/type-alias-impl-trait/structural-match.rs | 21 + .../type-alias-impl-trait/structural-match.stderr | 8 + .../type-alias-impl-trait-assoc-dyn.rs | 12 + .../type-alias-impl-trait-assoc-impl-trait.rs | 19 + .../type-alias-impl-trait-const.rs | 11 + .../type-alias-impl-trait-fn-type.rs | 13 + .../type-alias-impl-trait-fn-type.stderr | 9 + .../type-alias-impl-trait-fns.rs | 26 + .../type-alias-impl-trait-sized.rs | 25 + .../type-alias-impl-trait-struct.rs | 12 + .../type-alias-impl-trait-tuple.rs | 30 + ...type-alias-impl-trait-unconstrained-lifetime.rs | 18 + ...-alias-impl-trait-unconstrained-lifetime.stderr | 9 + .../type-alias-impl-trait-with-cycle-error.rs | 12 + .../type-alias-impl-trait-with-cycle-error.stderr | 10 + .../type-alias-impl-trait-with-cycle-error2.rs | 14 + .../type-alias-impl-trait-with-cycle-error2.stderr | 10 + .../type-alias-impl-trait-with-no-traits.rs | 14 + .../type-alias-impl-trait-with-no-traits.stderr | 14 + .../type-alias-impl-trait/type-alias-impl-trait.rs | 79 + .../type-alias-impl-trait2.rs | 84 + .../type-alias-nested-impl-trait.rs | 14 + tests/ui/type-alias-impl-trait/type_of_a_let.rs | 22 + .../ui/type-alias-impl-trait/type_of_a_let.stderr | 23 + .../type-alias-impl-trait/unbounded_opaque_type.rs | 14 + .../underconstrained_generic.rs | 28 + .../underconstrained_generic.stderr | 21 + .../underconstrained_lifetime.rs | 34 + .../underconstrained_lifetime.stderr | 20 + tests/ui/type-alias-impl-trait/unnameable_type.rs | 24 + .../type-alias-impl-trait/unnameable_type.stderr | 31 + .../type-alias-impl-trait/unused_generic_param.rs | 22 + .../ui/type-alias-impl-trait/weird-return-types.rs | 16 + tests/ui/type-alias-impl-trait/wf-check-fn-def.rs | 18 + .../type-alias-impl-trait/wf-check-fn-def.stderr | 19 + tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs | 23 + .../ui/type-alias-impl-trait/wf_check_closures.rs | 17 + .../type-alias-impl-trait/wf_check_closures.stderr | 19 + tests/ui/type-alias/issue-14933.rs | 6 + tests/ui/type-alias/issue-37515.rs | 8 + tests/ui/type-alias/issue-37515.stderr | 15 + tests/ui/type-alias/issue-62263-self-in-atb.rs | 8 + tests/ui/type-alias/issue-62263-self-in-atb.stderr | 9 + tests/ui/type-alias/issue-62305-self-assoc-ty.rs | 4 + .../ui/type-alias/issue-62305-self-assoc-ty.stderr | 9 + tests/ui/type-alias/issue-62364-self-ty-arg.rs | 8 + tests/ui/type-alias/issue-62364-self-ty-arg.stderr | 11 + tests/ui/type-id-higher-rank-2.rs | 31 + tests/ui/type-inference/issue-30225.rs | 38 + tests/ui/type-inference/issue-30225.stderr | 9 + .../type-inference/or_else-multiple-type-params.rs | 10 + .../or_else-multiple-type-params.stderr | 14 + tests/ui/type-inference/sort_by_key.rs | 5 + tests/ui/type-inference/sort_by_key.stderr | 14 + .../ui/type-inference/unbounded-associated-type.rs | 16 + .../unbounded-associated-type.stderr | 14 + .../unbounded-type-param-in-fn-with-assoc-type.rs | 9 + ...bounded-type-param-in-fn-with-assoc-type.stderr | 14 + .../type-inference/unbounded-type-param-in-fn.rs | 7 + .../unbounded-type-param-in-fn.stderr | 14 + tests/ui/type-namespace.rs | 7 + tests/ui/type-param-constraints.rs | 37 + tests/ui/type-param.rs | 11 + tests/ui/type-ptr.rs | 10 + tests/ui/type-use-i1-versus-i8.rs | 12 + tests/ui/type/ascription/issue-34255-1.rs | 15 + tests/ui/type/ascription/issue-34255-1.stderr | 36 + tests/ui/type/ascription/issue-47666.fixed | 4 + tests/ui/type/ascription/issue-47666.rs | 4 + tests/ui/type/ascription/issue-47666.stderr | 16 + tests/ui/type/ascription/issue-54516.fixed | 7 + tests/ui/type/ascription/issue-54516.rs | 7 + tests/ui/type/ascription/issue-54516.stderr | 12 + tests/ui/type/ascription/issue-60933.fixed | 5 + tests/ui/type/ascription/issue-60933.rs | 5 + tests/ui/type/ascription/issue-60933.stderr | 12 + tests/ui/type/auxiliary/crate_a1.rs | 11 + tests/ui/type/auxiliary/crate_a2.rs | 7 + ...nding-assigned-block-without-tail-expression.rs | 22 + ...g-assigned-block-without-tail-expression.stderr | 109 + tests/ui/type/closure-with-wrong-borrows.rs | 10 + tests/ui/type/closure-with-wrong-borrows.stderr | 19 + tests/ui/type/issue-100584.rs | 15 + tests/ui/type/issue-100584.stderr | 44 + tests/ui/type/issue-101866.rs | 15 + tests/ui/type/issue-101866.stderr | 18 + tests/ui/type/issue-102598.rs | 8 + tests/ui/type/issue-102598.stderr | 43 + tests/ui/type/issue-103271.rs | 18 + tests/ui/type/issue-103271.stderr | 25 + tests/ui/type/issue-58355.rs | 7 + tests/ui/type/issue-58355.stderr | 13 + ...ssue-67690-type-alias-bound-diagnostic-crash.rs | 8 + ...-67690-type-alias-bound-diagnostic-crash.stderr | 15 + tests/ui/type/issue-91268.rs | 9 + tests/ui/type/issue-91268.stderr | 63 + tests/ui/type/issue-94187-verbose-type-name.rs | 16 + tests/ui/type/missing-let-in-binding.fixed | 5 + tests/ui/type/missing-let-in-binding.rs | 5 + tests/ui/type/missing-let-in-binding.stderr | 16 + tests/ui/type/type-alias-bounds.rs | 59 + tests/ui/type/type-alias-bounds.stderr | 121 + tests/ui/type/type-annotation-needed.rs | 10 + tests/ui/type/type-annotation-needed.stderr | 20 + tests/ui/type/type-arg-out-of-scope.rs | 5 + tests/ui/type/type-arg-out-of-scope.stderr | 23 + .../type/type-ascription-instead-of-initializer.rs | 4 + .../type-ascription-instead-of-initializer.stderr | 25 + .../type-ascription-instead-of-statement-end.rs | 10 + ...type-ascription-instead-of-statement-end.stderr | 24 + tests/ui/type/type-ascription-precedence.rs | 54 + tests/ui/type/type-ascription-precedence.stderr | 63 + tests/ui/type/type-ascription-soundness.rs | 13 + tests/ui/type/type-ascription-soundness.stderr | 39 + tests/ui/type/type-ascription-with-fn-call.fixed | 9 + tests/ui/type/type-ascription-with-fn-call.rs | 9 + tests/ui/type/type-ascription-with-fn-call.stderr | 11 + tests/ui/type/type-ascription.rs | 39 + tests/ui/type/type-check-defaults.rs | 27 + tests/ui/type/type-check-defaults.stderr | 76 + .../ui/type/type-check/assignment-expected-bool.rs | 34 + .../type-check/assignment-expected-bool.stderr | 141 + tests/ui/type/type-check/assignment-in-if.rs | 62 + tests/ui/type/type-check/assignment-in-if.stderr | 130 + .../type/type-check/cannot_infer_local_or_array.rs | 3 + .../type-check/cannot_infer_local_or_array.stderr | 14 + .../type/type-check/cannot_infer_local_or_vec.rs | 4 + .../type-check/cannot_infer_local_or_vec.stderr | 14 + .../cannot_infer_local_or_vec_in_tuples.rs | 4 + .../cannot_infer_local_or_vec_in_tuples.stderr | 14 + tests/ui/type/type-check/issue-22897.rs | 5 + tests/ui/type/type-check/issue-22897.stderr | 9 + tests/ui/type/type-check/issue-40294.rs | 13 + tests/ui/type/type-check/issue-40294.stderr | 17 + tests/ui/type/type-check/issue-41314.rs | 10 + tests/ui/type/type-check/issue-41314.stderr | 14 + ...ssignment-match-prior-arm-bool-expected-unit.rs | 27 + ...nment-match-prior-arm-bool-expected-unit.stderr | 22 + ...8577-check-fn-with-more-than-65535-arguments.rs | 12 + ...-check-fn-with-more-than-65535-arguments.stderr | 13 + tests/ui/type/type-check/missing_trait_impl.rs | 16 + tests/ui/type/type-check/missing_trait_impl.stderr | 58 + tests/ui/type/type-check/point-at-inference-2.rs | 13 + .../ui/type/type-check/point-at-inference-2.stderr | 51 + .../ui/type/type-check/point-at-inference-3.fixed | 11 + tests/ui/type/type-check/point-at-inference-3.rs | 11 + .../ui/type/type-check/point-at-inference-3.stderr | 18 + tests/ui/type/type-check/point-at-inference.rs | 12 + tests/ui/type/type-check/point-at-inference.stderr | 19 + .../ui/type/type-check/unknown_type_for_closure.rs | 17 + .../type-check/unknown_type_for_closure.stderr | 37 + tests/ui/type/type-dependent-def-issue-49241.rs | 6 + .../ui/type/type-dependent-def-issue-49241.stderr | 17 + tests/ui/type/type-error-break-tail.rs | 8 + tests/ui/type/type-error-break-tail.stderr | 15 + tests/ui/type/type-mismatch-multiple.rs | 7 + tests/ui/type/type-mismatch-multiple.stderr | 19 + tests/ui/type/type-mismatch-same-crate-name.rs | 27 + tests/ui/type/type-mismatch-same-crate-name.stderr | 46 + tests/ui/type/type-mismatch.rs | 78 + tests/ui/type/type-mismatch.stderr | 751 ++ ...pe-parameter-defaults-referencing-Self-ppaux.rs | 17 + ...arameter-defaults-referencing-Self-ppaux.stderr | 31 + .../type-parameter-defaults-referencing-Self.rs | 11 + ...type-parameter-defaults-referencing-Self.stderr | 14 + tests/ui/type/type-parameter-names.rs | 12 + tests/ui/type/type-parameter-names.stderr | 19 + tests/ui/type/type-params-in-different-spaces-1.rs | 18 + .../type/type-params-in-different-spaces-1.stderr | 20 + tests/ui/type/type-params-in-different-spaces-2.rs | 21 + .../type/type-params-in-different-spaces-2.stderr | 29 + tests/ui/type/type-params-in-different-spaces-3.rs | 7 + .../type/type-params-in-different-spaces-3.stderr | 20 + tests/ui/type/type-path-err-node-types.rs | 26 + tests/ui/type/type-path-err-node-types.stderr | 39 + tests/ui/type/type-recursive-box-shadowed.rs | 12 + tests/ui/type/type-recursive-box-shadowed.stderr | 17 + tests/ui/type/type-recursive.rs | 30 + tests/ui/type/type-recursive.stderr | 93 + tests/ui/type/type-shadow.rs | 8 + tests/ui/type/type-shadow.stderr | 11 + tests/ui/type/type-unsatisfiable.rs | 59 + tests/ui/type/type-unsatisfiable.usage.stderr | 11 + .../wrong-call-return-type-due-to-generic-arg.rs | 28 + ...rong-call-return-type-due-to-generic-arg.stderr | 131 + tests/ui/type_length_limit.polonius.stderr | 11 + tests/ui/type_length_limit.rs | 34 + tests/ui/type_length_limit.stderr | 8 + tests/ui/typeck/assign-non-lval-derefmut.fixed | 15 + tests/ui/typeck/assign-non-lval-derefmut.rs | 15 + tests/ui/typeck/assign-non-lval-derefmut.stderr | 58 + tests/ui/typeck/assign-non-lval-mut-ref.fixed | 15 + tests/ui/typeck/assign-non-lval-mut-ref.rs | 15 + tests/ui/typeck/assign-non-lval-mut-ref.stderr | 56 + tests/ui/typeck/assign-non-lval-needs-deref.rs | 19 + tests/ui/typeck/assign-non-lval-needs-deref.stderr | 16 + tests/ui/typeck/autoderef-with-param-env-error.rs | 9 + .../typeck/autoderef-with-param-env-error.stderr | 14 + tests/ui/typeck/auxiliary/issue-36708.rs | 5 + tests/ui/typeck/auxiliary/issue-81943-lib.rs | 7 + tests/ui/typeck/auxiliary/tdticc_coherence_lib.rs | 6 + tests/ui/typeck/auxiliary/xcrate-issue-43189-a.rs | 7 + tests/ui/typeck/auxiliary/xcrate-issue-43189-b.rs | 3 + .../auxiliary/xcrate-issue-46112-rexport-core.rs | 3 + tests/ui/typeck/auxiliary/xcrate-issue-61711-b.rs | 5 + tests/ui/typeck/call-block.rs | 3 + tests/ui/typeck/call-block.stderr | 11 + tests/ui/typeck/check-args-on-fn-err-2.rs | 5 + tests/ui/typeck/check-args-on-fn-err-2.stderr | 23 + tests/ui/typeck/check-args-on-fn-err.rs | 6 + tests/ui/typeck/check-args-on-fn-err.stderr | 9 + tests/ui/typeck/conversion-methods.rs | 13 + tests/ui/typeck/conversion-methods.stderr | 45 + tests/ui/typeck/deref-multi.rs | 26 + tests/ui/typeck/deref-multi.stderr | 72 + ...adding-missing-zero-to-floating-point-number.rs | 21 + ...ng-missing-zero-to-floating-point-number.stderr | 51 + ...est-placeholder-to-const-static-without-type.rs | 8 + ...placeholder-to-const-static-without-type.stderr | 20 + tests/ui/typeck/explain_clone_autoref.rs | 13 + tests/ui/typeck/explain_clone_autoref.stderr | 22 + tests/ui/typeck/issue-100164.fixed | 9 + tests/ui/typeck/issue-100164.rs | 9 + tests/ui/typeck/issue-100164.stderr | 14 + tests/ui/typeck/issue-100246.rs | 30 + tests/ui/typeck/issue-100246.stderr | 13 + tests/ui/typeck/issue-100285.rs | 22 + tests/ui/typeck/issue-100285.stderr | 34 + tests/ui/typeck/issue-103899.rs | 30 + tests/ui/typeck/issue-10401.rs | 5 + tests/ui/typeck/issue-10401.stderr | 11 + tests/ui/typeck/issue-104510-ice.rs | 16 + tests/ui/typeck/issue-104510-ice.stderr | 9 + tests/ui/typeck/issue-104513-ice.rs | 6 + tests/ui/typeck/issue-104513-ice.stderr | 16 + tests/ui/typeck/issue-104582.rs | 5 + tests/ui/typeck/issue-104582.stderr | 25 + tests/ui/typeck/issue-105946.rs | 12 + tests/ui/typeck/issue-105946.stderr | 49 + tests/ui/typeck/issue-10969.rs | 7 + tests/ui/typeck/issue-10969.stderr | 23 + tests/ui/typeck/issue-13853-2.rs | 6 + tests/ui/typeck/issue-13853-2.stderr | 14 + tests/ui/typeck/issue-13853-5.rs | 13 + tests/ui/typeck/issue-13853-5.stderr | 9 + tests/ui/typeck/issue-13853.rs | 38 + tests/ui/typeck/issue-13853.stderr | 40 + tests/ui/typeck/issue-18937-1.rs | 21 + tests/ui/typeck/issue-18937.rs | 40 + tests/ui/typeck/issue-18937.stderr | 14 + tests/ui/typeck/issue-22375.rs | 4 + tests/ui/typeck/issue-29124.rs | 19 + tests/ui/typeck/issue-29124.stderr | 15 + tests/ui/typeck/issue-31173.rs | 15 + tests/ui/typeck/issue-31173.stderr | 45 + tests/ui/typeck/issue-33575.rs | 4 + tests/ui/typeck/issue-33575.stderr | 9 + tests/ui/typeck/issue-36708.rs | 12 + tests/ui/typeck/issue-36708.stderr | 9 + tests/ui/typeck/issue-43189.rs | 12 + tests/ui/typeck/issue-43189.stderr | 20 + tests/ui/typeck/issue-46112.rs | 10 + tests/ui/typeck/issue-46112.stderr | 27 + tests/ui/typeck/issue-50687-ice-on-borrow.rs | 41 + tests/ui/typeck/issue-50687-ice-on-borrow.stderr | 18 + ...issue-52082-type-param-shadows-existing-type.rs | 54 + ...e-52082-type-param-shadows-existing-type.stderr | 75 + ...e-55810-must-typeck-match-pats-before-guards.rs | 23 + tests/ui/typeck/issue-57404.rs | 7 + tests/ui/typeck/issue-57404.stderr | 19 + .../issue-57673-ice-on-deref-of-boxed-trait.rs | 7 + .../issue-57673-ice-on-deref-of-boxed-trait.stderr | 14 + .../issue-61711-once-caused-rustc-inf-loop.rs | 11 + tests/ui/typeck/issue-65611.rs | 63 + tests/ui/typeck/issue-65611.stderr | 16 + tests/ui/typeck/issue-67971.rs | 9 + tests/ui/typeck/issue-67971.stderr | 18 + .../issue-68590-reborrow-through-derefmut.rs | 25 + ...9378-ice-on-invalid-type-node-after-recovery.rs | 9 + ...-ice-on-invalid-type-node-after-recovery.stderr | 10 + .../issue-72225-call-fnmut-through-derefmut.rs | 21 + .../issue-73592-borrow_mut-through-deref.fixed | 59 + .../typeck/issue-73592-borrow_mut-through-deref.rs | 59 + .../issue-73592-borrow_mut-through-deref.stderr | 24 + tests/ui/typeck/issue-74086.rs | 5 + tests/ui/typeck/issue-74086.stderr | 15 + tests/ui/typeck/issue-74933.rs | 38 + tests/ui/typeck/issue-75883.rs | 22 + tests/ui/typeck/issue-75883.stderr | 42 + tests/ui/typeck/issue-75889.rs | 6 + tests/ui/typeck/issue-75889.stderr | 15 + tests/ui/typeck/issue-79040.rs | 5 + tests/ui/typeck/issue-79040.stderr | 17 + tests/ui/typeck/issue-80207-unsized-return.rs | 20 + tests/ui/typeck/issue-80779.rs | 13 + tests/ui/typeck/issue-80779.stderr | 21 + tests/ui/typeck/issue-81293.rs | 9 + tests/ui/typeck/issue-81293.stderr | 32 + tests/ui/typeck/issue-81885.rs | 9 + tests/ui/typeck/issue-81885.stderr | 27 + tests/ui/typeck/issue-81943.rs | 13 + tests/ui/typeck/issue-81943.stderr | 51 + tests/ui/typeck/issue-82772.rs | 13 + tests/ui/typeck/issue-82772.stderr | 21 + .../issue-83621-placeholder-static-in-extern.rs | 7 + ...issue-83621-placeholder-static-in-extern.stderr | 9 + tests/ui/typeck/issue-83693.rs | 19 + tests/ui/typeck/issue-83693.stderr | 37 + tests/ui/typeck/issue-84160.rs | 9 + tests/ui/typeck/issue-84160.stderr | 15 + tests/ui/typeck/issue-84768.rs | 10 + tests/ui/typeck/issue-84768.stderr | 30 + tests/ui/typeck/issue-84831.rs | 9 + tests/ui/typeck/issue-84831.stderr | 26 + .../typeck/issue-86721-return-expr-ice.rev1.stderr | 9 + .../typeck/issue-86721-return-expr-ice.rev2.stderr | 9 + tests/ui/typeck/issue-86721-return-expr-ice.rs | 17 + tests/ui/typeck/issue-87181/empty-tuple-method.rs | 14 + .../typeck/issue-87181/empty-tuple-method.stderr | 14 + tests/ui/typeck/issue-87181/enum-variant.rs | 16 + tests/ui/typeck/issue-87181/enum-variant.stderr | 14 + tests/ui/typeck/issue-87181/tuple-field.rs | 14 + tests/ui/typeck/issue-87181/tuple-field.stderr | 14 + tests/ui/typeck/issue-87181/tuple-method.rs | 14 + tests/ui/typeck/issue-87181/tuple-method.stderr | 9 + .../issue-87771-ice-assign-assign-to-bool.rs | 4 + .../issue-87771-ice-assign-assign-to-bool.stderr | 11 + ...sue-87872-missing-inaccessible-field-literal.rs | 11 + ...87872-missing-inaccessible-field-literal.stderr | 10 + ...sue-87872-missing-inaccessible-field-pattern.rs | 11 + ...87872-missing-inaccessible-field-pattern.stderr | 18 + tests/ui/typeck/issue-87935-unsized-box-expr.rs | 10 + .../ui/typeck/issue-87935-unsized-box-expr.stderr | 12 + tests/ui/typeck/issue-88609.rs | 19 + tests/ui/typeck/issue-88643.rs | 19 + tests/ui/typeck/issue-88643.stderr | 21 + tests/ui/typeck/issue-88803-call-expr-method.fixed | 9 + tests/ui/typeck/issue-88803-call-expr-method.rs | 9 + .../ui/typeck/issue-88803-call-expr-method.stderr | 15 + tests/ui/typeck/issue-88844.rs | 14 + tests/ui/typeck/issue-88844.stderr | 12 + .../typeck/issue-89044-wrapped-expr-method.fixed | 9 + tests/ui/typeck/issue-89044-wrapped-expr-method.rs | 9 + .../typeck/issue-89044-wrapped-expr-method.stderr | 14 + tests/ui/typeck/issue-89275.rs | 29 + tests/ui/typeck/issue-89275.stderr | 14 + tests/ui/typeck/issue-89806.rs | 3 + tests/ui/typeck/issue-89806.stderr | 9 + tests/ui/typeck/issue-89856.rs | 8 + tests/ui/typeck/issue-89856.stderr | 23 + tests/ui/typeck/issue-89935.rs | 18 + tests/ui/typeck/issue-90101.rs | 8 + tests/ui/typeck/issue-90101.stderr | 24 + tests/ui/typeck/issue-90164.rs | 9 + tests/ui/typeck/issue-90164.stderr | 22 + tests/ui/typeck/issue-90319.rs | 17 + tests/ui/typeck/issue-90319.stderr | 9 + .../issue-90483-inaccessible-field-adjustment.rs | 14 + ...ssue-90483-inaccessible-field-adjustment.stderr | 14 + .../issue-90804-incorrect-reference-suggestion.rs | 11 + ...sue-90804-incorrect-reference-suggestion.stderr | 17 + tests/ui/typeck/issue-91210-ptr-method.fixed | 15 + tests/ui/typeck/issue-91210-ptr-method.rs | 15 + tests/ui/typeck/issue-91210-ptr-method.stderr | 14 + tests/ui/typeck/issue-91267.rs | 8 + tests/ui/typeck/issue-91267.stderr | 24 + tests/ui/typeck/issue-91328.fixed | 47 + tests/ui/typeck/issue-91328.rs | 47 + tests/ui/typeck/issue-91328.stderr | 39 + tests/ui/typeck/issue-91334.rs | 10 + tests/ui/typeck/issue-91334.stderr | 50 + tests/ui/typeck/issue-91450-inner-ty-error.rs | 7 + tests/ui/typeck/issue-91450-inner-ty-error.stderr | 21 + tests/ui/typeck/issue-91633.rs | 8 + tests/ui/typeck/issue-92481.rs | 14 + tests/ui/typeck/issue-92481.stderr | 60 + tests/ui/typeck/issue-93486.rs | 6 + tests/ui/typeck/issue-93486.stderr | 16 + tests/ui/typeck/issue-96530.rs | 20 + tests/ui/typeck/issue-96530.stderr | 9 + tests/ui/typeck/issue-96738.rs | 4 + tests/ui/typeck/issue-96738.stderr | 16 + tests/ui/typeck/issue-98260.rs | 9 + tests/ui/typeck/issue-98260.stderr | 12 + tests/ui/typeck/issue-98982.rs | 9 + tests/ui/typeck/issue-98982.stderr | 24 + .../missing-private-fields-in-struct-literal.rs | 18 + ...missing-private-fields-in-struct-literal.stderr | 15 + tests/ui/typeck/no-type-for-node-ice.rs | 5 + tests/ui/typeck/no-type-for-node-ice.stderr | 9 + tests/ui/typeck/nonexistent-field-not-ambiguous.rs | 8 + .../typeck/nonexistent-field-not-ambiguous.stderr | 9 + .../typeck/path-to-method-sugg-unresolved-expr.rs | 4 + .../path-to-method-sugg-unresolved-expr.stderr | 9 + .../ui/typeck/point-at-type-param-in-path-expr.rs | 6 + .../typeck/point-at-type-param-in-path-expr.stderr | 17 + .../typeck/point-at-type-parameter-definition.rs | 17 + .../point-at-type-parameter-definition.stderr | 12 + tests/ui/typeck/prim-with-args.fixed | 28 + tests/ui/typeck/prim-with-args.rs | 28 + tests/ui/typeck/prim-with-args.stderr | 311 + tests/ui/typeck/project-cache-issue-37154.rs | 21 + tests/ui/typeck/quiet-type-err-let-binding.rs | 17 + tests/ui/typeck/quiet-type-err-let-binding.stderr | 9 + tests/ui/typeck/remove-extra-argument.fixed | 9 + tests/ui/typeck/remove-extra-argument.rs | 9 + tests/ui/typeck/remove-extra-argument.stderr | 19 + tests/ui/typeck/return_type_containing_closure.rs | 10 + .../typeck/return_type_containing_closure.stderr | 20 + tests/ui/typeck/slow-lhs-suggestion.rs | 26 + tests/ui/typeck/slow-lhs-suggestion.stderr | 187 + tests/ui/typeck/struct-enum-wrong-args.rs | 14 + tests/ui/typeck/struct-enum-wrong-args.stderr | 124 + ...ing-missing-zero-to-floating-point-number.fixed | 11 + ...adding-missing-zero-to-floating-point-number.rs | 11 + ...ng-missing-zero-to-floating-point-number.stderr | 80 + tests/ui/typeck/type-placeholder-fn-in-const.rs | 14 + .../ui/typeck/type-placeholder-fn-in-const.stderr | 21 + .../typeck/typeck-builtin-bound-type-parameters.rs | 17 + .../typeck-builtin-bound-type-parameters.stderr | 51 + tests/ui/typeck/typeck-cast-pointer-to-float.rs | 5 + .../ui/typeck/typeck-cast-pointer-to-float.stderr | 9 + tests/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs | 9 + .../typeck-default-trait-impl-assoc-type.fixed | 17 + .../typeck/typeck-default-trait-impl-assoc-type.rs | 17 + .../typeck-default-trait-impl-assoc-type.stderr | 20 + ...eck-default-trait-impl-cross-crate-coherence.rs | 25 + ...default-trait-impl-cross-crate-coherence.stderr | 43 + .../typeck-default-trait-impl-negation-send.rs | 21 + .../typeck-default-trait-impl-negation-send.stderr | 16 + .../typeck-default-trait-impl-negation-sync.rs | 41 + .../typeck-default-trait-impl-negation-sync.stderr | 52 + .../typeck/typeck-default-trait-impl-send-param.rs | 11 + .../typeck-default-trait-impl-send-param.stderr | 19 + tests/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs | 12 + tests/ui/typeck/typeck-unsafe-always-share.rs | 32 + tests/ui/typeck/typeck-unsafe-always-share.stderr | 68 + tests/ui/typeck/typeck_type_placeholder_1.rs | 32 + tests/ui/typeck/typeck_type_placeholder_item.rs | 230 + .../ui/typeck/typeck_type_placeholder_item.stderr | 663 ++ .../ui/typeck/typeck_type_placeholder_item_help.rs | 33 + .../typeck_type_placeholder_item_help.stderr | 60 + .../typeck/typeck_type_placeholder_lifetime_1.rs | 11 + .../typeck_type_placeholder_lifetime_1.stderr | 17 + .../typeck/typeck_type_placeholder_lifetime_2.rs | 11 + .../typeck_type_placeholder_lifetime_2.stderr | 17 + .../ui/typeck/typeck_type_placeholder_mismatch.rs | 27 + .../typeck/typeck_type_placeholder_mismatch.stderr | 25 + tests/ui/typeck/ufcs-type-params.rs | 15 + tests/ui/typeck/unify-return-ty.rs | 16 + tests/ui/typeck/while-loop-block-cond.rs | 4 + tests/ui/typeck/while-loop-block-cond.stderr | 9 + tests/ui/typeid-intrinsic.rs | 97 + tests/ui/typeof/issue-100183.rs | 6 + tests/ui/typeof/issue-100183.stderr | 14 + tests/ui/typeof/issue-29184.rs | 3 + tests/ui/typeof/issue-29184.stderr | 14 + tests/ui/typeof/issue-42060.rs | 11 + tests/ui/typeof/issue-42060.stderr | 32 + tests/ui/typeof/type_mismatch.rs | 9 + tests/ui/typeof/type_mismatch.stderr | 28 + tests/ui/typestate-multi-decl.rs | 7 + tests/ui/ufcs-polymorphic-paths.rs | 154 + tests/ui/ufcs/ufcs-explicit-self-bad.rs | 59 + tests/ui/ufcs/ufcs-explicit-self-bad.stderr | 107 + tests/ui/ufcs/ufcs-partially-resolved.rs | 56 + tests/ui/ufcs/ufcs-partially-resolved.stderr | 230 + tests/ui/ufcs/ufcs-qpath-missing-params.rs | 20 + tests/ui/ufcs/ufcs-qpath-missing-params.stderr | 49 + tests/ui/ufcs/ufcs-qpath-self-mismatch.rs | 11 + tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr | 76 + .../auxiliary/unboxed-closures-cross-crate.rs | 16 + tests/ui/unboxed-closures/issue-18652.rs | 10 + tests/ui/unboxed-closures/issue-18661.rs | 19 + tests/ui/unboxed-closures/issue-30906.rs | 22 + tests/ui/unboxed-closures/issue-30906.stderr | 11 + tests/ui/unboxed-closures/issue-53448.rs | 16 + .../ui/unboxed-closures/non-tupled-arg-mismatch.rs | 8 + .../non-tupled-arg-mismatch.stderr | 12 + tests/ui/unboxed-closures/non-tupled-call.rs | 17 + tests/ui/unboxed-closures/non-tupled-call.stderr | 9 + tests/ui/unboxed-closures/type-id-higher-rank.rs | 72 + .../unboxed-closure-feature-gate.rs | 20 + .../unboxed-closure-feature-gate.stderr | 12 + .../unboxed-closure-illegal-move.rs | 38 + .../unboxed-closure-illegal-move.stderr | 43 + .../unboxed-closure-immutable-capture.rs | 17 + .../unboxed-closure-immutable-capture.stderr | 75 + .../unboxed-closure-no-cyclic-sig.rs | 9 + .../unboxed-closure-no-cyclic-sig.stderr | 19 + .../ui/unboxed-closures/unboxed-closure-region.rs | 11 + .../unboxed-closures/unboxed-closure-region.stderr | 21 + .../unboxed-closure-sugar-default.rs | 28 + .../unboxed-closure-sugar-default.stderr | 15 + .../unboxed-closure-sugar-equiv.rs | 48 + .../unboxed-closure-sugar-equiv.stderr | 15 + .../unboxed-closure-sugar-lifetime-elision.rs | 27 + .../unboxed-closure-sugar-lifetime-elision.stderr | 24 + .../unboxed-closure-sugar-not-used-on-fn.rs | 11 + .../unboxed-closure-sugar-not-used-on-fn.stderr | 21 + .../unboxed-closure-sugar-region.rs | 36 + .../unboxed-closure-sugar-region.stderr | 15 + .../unboxed-closure-sugar-used-on-struct-1.rs | 13 + .../unboxed-closure-sugar-used-on-struct-1.stderr | 26 + .../unboxed-closure-sugar-used-on-struct-3.rs | 18 + .../unboxed-closure-sugar-used-on-struct-3.stderr | 14 + .../unboxed-closure-sugar-used-on-struct.rs | 12 + .../unboxed-closure-sugar-used-on-struct.stderr | 26 + ...-sugar-wrong-number-number-type-parameters-1.rs | 8 + ...ar-wrong-number-number-type-parameters-1.stderr | 9 + ...-sugar-wrong-number-number-type-parameters-3.rs | 10 + ...ar-wrong-number-number-type-parameters-3.stderr | 24 + ...re-sugar-wrong-number-number-type-parameters.rs | 28 + ...ugar-wrong-number-number-type-parameters.stderr | 92 + .../unboxed-closure-sugar-wrong-trait.rs | 9 + .../unboxed-closure-sugar-wrong-trait.stderr | 24 + .../unboxed-closures-all-traits.rs | 21 + .../unboxed-closures-blanket-fn-mut.rs | 27 + .../unboxed-closures-blanket-fn.rs | 27 + .../unboxed-closures-borrow-conflict.rs | 11 + .../unboxed-closures-borrow-conflict.stderr | 15 + .../ui/unboxed-closures/unboxed-closures-boxed.rs | 15 + .../ui/unboxed-closures/unboxed-closures-by-ref.rs | 24 + .../unboxed-closures-call-fn-autoderef.rs | 18 + .../unboxed-closures-call-sugar-autoderef.rs | 15 + ...unboxed-closures-call-sugar-object-autoderef.rs | 15 + .../unboxed-closures-call-sugar-object.rs | 13 + .../unboxed-closures-counter-not-moved.rs | 28 + .../unboxed-closures-counter-not-moved.stderr | 27 + .../unboxed-closures-cross-crate.rs | 14 + .../unboxed-closures-direct-sugary-call.rs | 8 + tests/ui/unboxed-closures/unboxed-closures-drop.rs | 117 + .../unboxed-closures-extern-fn-hr.rs | 31 + .../unboxed-closures/unboxed-closures-extern-fn.rs | 27 + .../unboxed-closures-failed-recursive-fn-1.rs | 37 + .../unboxed-closures-failed-recursive-fn-1.stderr | 60 + .../unboxed-closures-failed-recursive-fn-2.rs | 29 + .../unboxed-closures-failed-recursive-fn-2.stderr | 17 + .../unboxed-closures-fn-as-fnmut-and-fnonce.rs | 44 + .../unboxed-closures-fnmut-as-fn.rs | 29 + .../unboxed-closures-fnmut-as-fn.stderr | 19 + .../unboxed-closures-fnmut-as-fnonce.rs | 33 + .../unboxed-closures/unboxed-closures-generic.rs | 13 + ...closures-infer-arg-types-from-expected-bound.rs | 23 + ...es-infer-arg-types-from-expected-object-type.rs | 19 + ...r-arg-types-w-bound-regs-from-expected-bound.rs | 23 + ...res-infer-argument-types-two-region-pointers.rs | 20 + ...infer-argument-types-two-region-pointers.stderr | 12 + .../unboxed-closures-infer-explicit-call-early.rs | 8 + ...-closures-infer-fn-once-move-from-projection.rs | 16 + ...sures-infer-fn-once-move-from-projection.stderr | 23 + ...ed-closures-infer-fnmut-calling-fnmut-no-mut.rs | 20 + ...losures-infer-fnmut-calling-fnmut-no-mut.stderr | 28 + .../unboxed-closures-infer-fnmut-calling-fnmut.rs | 19 + .../unboxed-closures-infer-fnmut-missing-mut.rs | 8 + ...unboxed-closures-infer-fnmut-missing-mut.stderr | 16 + ...nboxed-closures-infer-fnmut-move-missing-mut.rs | 8 + ...ed-closures-infer-fnmut-move-missing-mut.stderr | 16 + .../unboxed-closures-infer-fnmut-move.rs | 16 + .../unboxed-closures-infer-fnmut.rs | 15 + .../unboxed-closures-infer-fnonce-call-twice.rs | 11 + ...unboxed-closures-infer-fnonce-call-twice.stderr | 22 + ...nboxed-closures-infer-fnonce-move-call-twice.rs | 11 + ...ed-closures-infer-fnonce-move-call-twice.stderr | 22 + .../unboxed-closures-infer-fnonce-move.rs | 25 + .../unboxed-closures-infer-fnonce.rs | 25 + .../unboxed-closures-infer-kind.rs | 27 + .../unboxed-closures-infer-recursive-fn.rs | 45 + .../unboxed-closures-infer-upvar.rs | 13 + .../unboxed-closures-manual-impl.rs | 31 + .../unboxed-closures-monomorphization.rs | 26 + ...ed-closures-move-from-projection-issue-30046.rs | 26 + .../unboxed-closures-move-mutable.rs | 31 + .../unboxed-closures-move-mutable.stderr | 19 + ...-closures-move-some-upvars-in-by-ref-closure.rs | 23 + .../unboxed-closures-mutate-upvar.rs | 57 + .../unboxed-closures-mutate-upvar.stderr | 43 + ...boxed-closures-mutated-upvar-from-fn-closure.rs | 14 + ...d-closures-mutated-upvar-from-fn-closure.stderr | 16 + .../unboxed-closures/unboxed-closures-prelude.rs | 18 + .../unboxed-closures-recursive-fn-using-fn-mut.rs | 43 + ...boxed-closures-recursive-fn-using-fn-mut.stderr | 12 + .../ui/unboxed-closures/unboxed-closures-simple.rs | 10 + .../unboxed-closures-single-word-env.rs | 22 + .../unboxed-closures-static-call-fn-once.rs | 7 + .../unboxed-closures-static-call-wrong-trait.rs | 8 + ...unboxed-closures-static-call-wrong-trait.stderr | 9 + .../unboxed-closures-sugar-object.rs | 25 + .../unboxed-closures-type-mismatch.rs | 7 + .../unboxed-closures-type-mismatch.stderr | 21 + .../unboxed-closures-unique-type-id.rs | 26 + .../unboxed-closures-unsafe-extern-fn.rs | 34 + .../unboxed-closures-unsafe-extern-fn.stderr | 51 + .../unboxed-closures/unboxed-closures-wrong-abi.rs | 34 + .../unboxed-closures-wrong-abi.stderr | 48 + .../unboxed-closures-wrong-arg-type-extern-fn.rs | 35 + ...nboxed-closures-wrong-arg-type-extern-fn.stderr | 51 + .../unboxed-closures/unboxed-closures-zero-args.rs | 8 + tests/ui/unconstrained-none.rs | 5 + tests/ui/unconstrained-none.stderr | 14 + tests/ui/unconstrained-ref.rs | 7 + tests/ui/unconstrained-ref.stderr | 14 + tests/ui/underscore-ident-matcher.rs | 9 + tests/ui/underscore-ident-matcher.stderr | 17 + tests/ui/underscore-imports/auxiliary/duplicate.rs | 14 + .../auxiliary/underscore-imports.rs | 20 + tests/ui/underscore-imports/basic.rs | 62 + tests/ui/underscore-imports/basic.stderr | 20 + tests/ui/underscore-imports/cycle.rs | 18 + tests/ui/underscore-imports/duplicate.rs | 15 + tests/ui/underscore-imports/hygiene-2.rs | 34 + tests/ui/underscore-imports/hygiene.rs | 40 + tests/ui/underscore-imports/intercrate.rs | 11 + tests/ui/underscore-imports/macro-expanded.rs | 45 + tests/ui/underscore-imports/shadow.rs | 23 + tests/ui/underscore-imports/shadow.stderr | 15 + tests/ui/underscore-imports/unused-2018.rs | 17 + tests/ui/underscore-imports/unused-2018.stderr | 20 + .../dyn-trait-underscore-in-struct.rs | 12 + .../dyn-trait-underscore-in-struct.stderr | 15 + .../ui/underscore-lifetime/dyn-trait-underscore.rs | 20 + .../dyn-trait-underscore.stderr | 16 + tests/ui/underscore-lifetime/in-binder.rs | 35 + tests/ui/underscore-lifetime/in-binder.stderr | 39 + .../ui/underscore-lifetime/in-fn-return-illegal.rs | 7 + .../in-fn-return-illegal.stderr | 15 + tests/ui/underscore-lifetime/in-struct.rs | 13 + tests/ui/underscore-lifetime/in-struct.stderr | 27 + .../underscore-lifetime-binders.rs | 22 + .../underscore-lifetime-binders.stderr | 51 + .../underscore-lifetime-elison-mismatch.rs | 4 + .../underscore-lifetime-elison-mismatch.stderr | 16 + .../underscore-outlives-bounds.rs | 8 + .../underscore-outlives-bounds.stderr | 9 + .../where-clause-inherent-impl-ampersand.rs | 18 + ...-clause-inherent-impl-ampersand.rust2015.stderr | 15 + ...-clause-inherent-impl-ampersand.rust2018.stderr | 15 + .../where-clause-inherent-impl-underscore.rs | 17 + ...clause-inherent-impl-underscore.rust2015.stderr | 9 + ...clause-inherent-impl-underscore.rust2018.stderr | 9 + .../where-clause-trait-impl-region.rs | 15 + .../where-clause-trait-impl-region.rust2015.stderr | 15 + .../where-clause-trait-impl-region.rust2018.stderr | 15 + .../where-clause-trait-impl-underscore.rs | 15 + ...re-clause-trait-impl-underscore.rust2015.stderr | 9 + ...re-clause-trait-impl-underscore.rust2018.stderr | 9 + tests/ui/underscore-lifetime/where-clauses.rs | 7 + tests/ui/underscore-lifetime/where-clauses.stderr | 15 + tests/ui/underscore-lifetimes.rs | 38 + tests/ui/underscore-method-after-integer.rs | 11 + tests/ui/unevaluated_fixed_size_array_len.rs | 13 + tests/ui/unevaluated_fixed_size_array_len.stderr | 11 + tests/ui/uniform-paths/auxiliary/issue-53691.rs | 7 + tests/ui/uniform-paths/basic-nested.rs | 61 + tests/ui/uniform-paths/basic.rs | 33 + tests/ui/uniform-paths/issue-53691.rs | 9 + tests/ui/uniform-paths/macros-nested.rs | 53 + tests/ui/uniform-paths/macros.rs | 36 + tests/ui/uniform-paths/same-crate.rs | 98 + .../exhaustive-wo-nevertype-issue-51221.rs | 9 + .../uninhabited/privately-uninhabited-dead-code.rs | 20 + .../uninhabited/privately-uninhabited-mir-call.rs | 29 + .../privately-uninhabited-mir-call.stderr | 17 + tests/ui/uninhabited/uninhabited-enum-cast.rs | 9 + tests/ui/uninhabited/uninhabited-irrefutable.rs | 30 + .../ui/uninhabited/uninhabited-irrefutable.stderr | 24 + .../uninhabited-matches-feature-gated.rs | 39 + .../uninhabited-matches-feature-gated.stderr | 115 + tests/ui/uninhabited/uninhabited-patterns.rs | 47 + tests/ui/uninhabited/uninhabited-patterns.stderr | 38 + tests/ui/uninit-empty-types.rs | 19 + tests/ui/union/auxiliary/union.rs | 4 + tests/ui/union/field_checks.rs | 65 + tests/ui/union/field_checks.stderr | 63 + tests/ui/union/issue-41073.rs | 22 + tests/ui/union/issue-41073.stderr | 15 + tests/ui/union/issue-81199.rs | 21 + tests/ui/union/issue-81199.stderr | 19 + tests/ui/union/issue-99375.rs | 21 + tests/ui/union/union-align.rs | 65 + tests/ui/union/union-backcomp.rs | 28 + tests/ui/union/union-basic.rs | 62 + ...n-borrow-move-parent-sibling.mirunsafeck.stderr | 84 + tests/ui/union/union-borrow-move-parent-sibling.rs | 96 + ...-borrow-move-parent-sibling.thirunsafeck.stderr | 84 + tests/ui/union/union-const-codegen.rs | 19 + tests/ui/union/union-const-eval-field.rs | 45 + tests/ui/union/union-const-eval.rs | 15 + tests/ui/union/union-const-pat.rs | 13 + tests/ui/union/union-const-pat.stderr | 8 + tests/ui/union/union-copy.rs | 14 + tests/ui/union/union-copy.stderr | 18 + tests/ui/union/union-deref.mirunsafeck.stderr | 56 + tests/ui/union/union-deref.rs | 29 + tests/ui/union/union-deref.thirunsafeck.stderr | 56 + .../ui/union/union-derive-clone.mirunsafeck.stderr | 43 + tests/ui/union/union-derive-clone.rs | 39 + .../union/union-derive-clone.thirunsafeck.stderr | 43 + tests/ui/union/union-derive-eq.mirunsafeck.stderr | 20 + tests/ui/union/union-derive-eq.rs | 21 + tests/ui/union/union-derive-eq.thirunsafeck.stderr | 20 + tests/ui/union/union-derive-rpass.rs | 42 + tests/ui/union/union-derive.rs | 16 + tests/ui/union/union-derive.stderr | 38 + tests/ui/union/union-drop-assign.rs | 37 + tests/ui/union/union-drop.rs | 60 + tests/ui/union/union-empty.rs | 3 + tests/ui/union/union-empty.stderr | 8 + tests/ui/union/union-fields-1.mirunsafeck.stderr | 42 + tests/ui/union/union-fields-1.rs | 35 + tests/ui/union/union-fields-1.thirunsafeck.stderr | 42 + tests/ui/union/union-fields-2.mirunsafeck.stderr | 84 + tests/ui/union/union-fields-2.rs | 26 + tests/ui/union/union-fields-2.thirunsafeck.stderr | 84 + tests/ui/union/union-generic-rpass.rs | 34 + tests/ui/union/union-generic.mirunsafeck.stderr | 27 + tests/ui/union/union-generic.rs | 15 + tests/ui/union/union-generic.thirunsafeck.stderr | 27 + tests/ui/union/union-inherent-method.rs | 16 + .../union/union-lint-dead-code.mirunsafeck.stderr | 17 + tests/ui/union/union-lint-dead-code.rs | 18 + .../union/union-lint-dead-code.thirunsafeck.stderr | 17 + tests/ui/union/union-macro.rs | 27 + tests/ui/union/union-manuallydrop-rpass.rs | 44 + tests/ui/union/union-move.mirunsafeck.stderr | 51 + tests/ui/union/union-move.rs | 56 + tests/ui/union/union-move.thirunsafeck.stderr | 51 + tests/ui/union/union-nodrop.rs | 62 + tests/ui/union/union-nonrepresentable.rs | 6 + tests/ui/union/union-nonrepresentable.stderr | 17 + tests/ui/union/union-nonzero.rs | 54 + tests/ui/union/union-overwrite.rs | 80 + tests/ui/union/union-packed.rs | 173 + tests/ui/union/union-pat-refutability.rs | 57 + tests/ui/union/union-repr-c.rs | 18 + tests/ui/union/union-repr-c.stderr | 21 + tests/ui/union/union-sized-field.rs | 19 + tests/ui/union/union-sized-field.stderr | 78 + .../union/union-suggest-field.mirunsafeck.stderr | 27 + tests/ui/union/union-suggest-field.rs | 24 + .../union/union-suggest-field.thirunsafeck.stderr | 27 + tests/ui/union/union-trait-impl.rs | 19 + tests/ui/union/union-transmute.rs | 27 + tests/ui/union/union-unsafe.mir.stderr | 75 + tests/ui/union/union-unsafe.rs | 78 + tests/ui/union/union-unsafe.thir.stderr | 75 + tests/ui/union/union-unsized.mirunsafeck.stderr | 39 + tests/ui/union/union-unsized.rs | 17 + tests/ui/union/union-unsized.thirunsafeck.stderr | 39 + .../union-with-drop-fields.mirunsafeck.stderr | 39 + tests/ui/union/union-with-drop-fields.rs | 31 + .../union-with-drop-fields.thirunsafeck.stderr | 39 + tests/ui/unique-object-noncopyable.rs | 25 + tests/ui/unique-object-noncopyable.stderr | 25 + tests/ui/unique-pinned-nocopy.rs | 14 + tests/ui/unique-pinned-nocopy.stderr | 27 + tests/ui/unique/unique-assign-copy.rs | 12 + tests/ui/unique/unique-assign-drop.rs | 10 + tests/ui/unique/unique-assign-generic.rs | 11 + tests/ui/unique/unique-assign.rs | 8 + tests/ui/unique/unique-autoderef-field.rs | 10 + tests/ui/unique/unique-autoderef-index.rs | 6 + tests/ui/unique/unique-cmp.rs | 11 + tests/ui/unique/unique-containing-tag.rs | 25 + tests/ui/unique/unique-create.rs | 11 + tests/ui/unique/unique-decl-init-copy.rs | 11 + tests/ui/unique/unique-decl-init.rs | 7 + tests/ui/unique/unique-decl-move.rs | 7 + tests/ui/unique/unique-decl.rs | 11 + tests/ui/unique/unique-deref.rs | 6 + tests/ui/unique/unique-destructure.rs | 9 + tests/ui/unique/unique-drop-complex.rs | 6 + tests/ui/unique/unique-ffi-symbols.rs | 16 + tests/ui/unique/unique-fn-arg-move.rs | 10 + tests/ui/unique/unique-fn-arg-mut.rs | 11 + tests/ui/unique/unique-fn-arg.rs | 11 + tests/ui/unique/unique-fn-ret.rs | 9 + tests/ui/unique/unique-generic-assign.rs | 11 + tests/ui/unique/unique-in-tag.rs | 20 + tests/ui/unique/unique-in-vec-copy.rs | 15 + tests/ui/unique/unique-in-vec.rs | 6 + tests/ui/unique/unique-init.rs | 6 + tests/ui/unique/unique-kinds.rs | 64 + tests/ui/unique/unique-log.rs | 6 + tests/ui/unique/unique-match-discrim.rs | 12 + tests/ui/unique/unique-move-drop.rs | 10 + tests/ui/unique/unique-move-temp.rs | 8 + tests/ui/unique/unique-move.rs | 9 + tests/ui/unique/unique-mutable.rs | 7 + tests/ui/unique/unique-object-move.rs | 18 + tests/ui/unique/unique-pat-2.rs | 18 + tests/ui/unique/unique-pat-3.rs | 16 + tests/ui/unique/unique-pat.rs | 14 + tests/ui/unique/unique-rec.rs | 9 + tests/ui/unique/unique-send-2.rs | 33 + tests/ui/unique/unique-send.rs | 10 + tests/ui/unique/unique-swap.rs | 11 + tests/ui/unit.rs | 17 + tests/ui/unknown-language-item.rs | 10 + tests/ui/unknown-language-item.stderr | 9 + tests/ui/unknown-lint-tool-name.rs | 6 + tests/ui/unknown-lint-tool-name.stderr | 35 + tests/ui/unknown-llvm-arg.rs | 22 + tests/ui/unknown-llvm-arg.stderr | 1 + tests/ui/unknown-tool-name.rs | 2 + tests/ui/unknown-tool-name.stderr | 9 + .../allow-unknown-unstable-lint-command-line.rs | 4 + .../allow-unknown-unstable-lint-inline.rs | 5 + .../deny-unstable-lint-command-line.rs | 6 + .../deny-unstable-lint-command-line.stderr | 18 + .../deny-unstable-lint-inline.rs | 9 + .../deny-unstable-lint-inline.stderr | 34 + .../warn-unknown-unstable-lint-command-line.rs | 6 + .../warn-unknown-unstable-lint-command-line.stderr | 18 + .../warn-unknown-unstable-lint-inline.rs | 9 + .../warn-unknown-unstable-lint-inline.stderr | 34 + tests/ui/unnamed_argument_mode.rs | 14 + tests/ui/unop-move-semantics.rs | 32 + tests/ui/unop-move-semantics.stderr | 70 + tests/ui/unop-neg-bool.rs | 3 + tests/ui/unop-neg-bool.stderr | 9 + tests/ui/unpretty-expr-fn-arg.rs | 13 + tests/ui/unpretty-expr-fn-arg.stdout | 17 + tests/ui/unpretty/avoid-crash.rs | 4 + tests/ui/unpretty/avoid-crash.stderr | 4 + tests/ui/unpretty/bad-literal.rs | 8 + tests/ui/unpretty/bad-literal.stderr | 10 + tests/ui/unpretty/bad-literal.stdout | 11 + tests/ui/unpretty/pretty-let-else.rs | 10 + tests/ui/unpretty/pretty-let-else.stdout | 18 + tests/ui/unreachable-code-1.rs | 19 + tests/ui/unreachable-code.rs | 28 + tests/ui/unresolved/unresolved-asterisk-imports.rs | 4 + .../unresolved/unresolved-asterisk-imports.stderr | 11 + tests/ui/unresolved/unresolved-candidates.rs | 13 + tests/ui/unresolved/unresolved-candidates.stderr | 26 + .../unresolved/unresolved-extern-mod-suggestion.rs | 5 + .../unresolved-extern-mod-suggestion.stderr | 13 + tests/ui/unresolved/unresolved-import-recovery.rs | 17 + .../unresolved/unresolved-import-recovery.stderr | 9 + tests/ui/unresolved/unresolved-import.rs | 56 + tests/ui/unresolved/unresolved-import.stderr | 50 + tests/ui/unsafe-fn-called-from-unsafe-blk.rs | 18 + tests/ui/unsafe-fn-called-from-unsafe-fn.rs | 17 + tests/ui/unsafe-pointer-assignability.rs | 11 + tests/ui/unsafe/access_union_field.mir.stderr | 19 + tests/ui/unsafe/access_union_field.rs | 15 + tests/ui/unsafe/access_union_field.thir.stderr | 19 + tests/ui/unsafe/auxiliary/issue-106126.rs | 9 + tests/ui/unsafe/inline_asm.mir.stderr | 11 + tests/ui/unsafe/inline_asm.rs | 9 + tests/ui/unsafe/inline_asm.thir.stderr | 11 + tests/ui/unsafe/issue-106126-good-path-bug.rs | 12 + tests/ui/unsafe/issue-3080.mir.stderr | 11 + tests/ui/unsafe/issue-3080.rs | 11 + tests/ui/unsafe/issue-3080.thir.stderr | 11 + .../issue-45087-unreachable-unsafe.mir.stderr | 27 + tests/ui/unsafe/issue-45087-unreachable-unsafe.rs | 31 + .../issue-45087-unreachable-unsafe.thir.stderr | 27 + ...-45107-unnecessary-unsafe-in-closure.mir.stderr | 35 + .../issue-45107-unnecessary-unsafe-in-closure.rs | 28 + ...45107-unnecessary-unsafe-in-closure.thir.stderr | 35 + tests/ui/unsafe/issue-47412.mir.stderr | 19 + tests/ui/unsafe/issue-47412.rs | 24 + tests/ui/unsafe/issue-47412.thir.stderr | 19 + ...-unsafe-op-in-let-under-unsafe-under-closure.rs | 27 + tests/ui/unsafe/issue-87414-query-cycle.rs | 15 + tests/ui/unsafe/ranged_ints.mir.stderr | 11 + tests/ui/unsafe/ranged_ints.rs | 11 + tests/ui/unsafe/ranged_ints.thir.stderr | 11 + tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr | 11 + tests/ui/unsafe/ranged_ints2.rs | 12 + tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr | 11 + .../unsafe/ranged_ints2_const.mirunsafeck.stderr | 39 + tests/ui/unsafe/ranged_ints2_const.rs | 29 + .../unsafe/ranged_ints2_const.thirunsafeck.stderr | 39 + tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr | 11 + tests/ui/unsafe/ranged_ints3.rs | 14 + tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr | 11 + .../unsafe/ranged_ints3_const.mirunsafeck.stderr | 30 + tests/ui/unsafe/ranged_ints3_const.rs | 24 + .../unsafe/ranged_ints3_const.thirunsafeck.stderr | 30 + .../unsafe/ranged_ints3_match.mirunsafeck.stderr | 19 + tests/ui/unsafe/ranged_ints3_match.rs | 22 + .../unsafe/ranged_ints3_match.thirunsafeck.stderr | 19 + tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr | 11 + tests/ui/unsafe/ranged_ints4.rs | 12 + tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr | 11 + .../unsafe/ranged_ints4_const.mirunsafeck.stderr | 11 + tests/ui/unsafe/ranged_ints4_const.rs | 22 + .../unsafe/ranged_ints4_const.thirunsafeck.stderr | 11 + tests/ui/unsafe/ranged_ints_const.mir.stderr | 11 + tests/ui/unsafe/ranged_ints_const.rs | 14 + tests/ui/unsafe/ranged_ints_const.thir.stderr | 11 + tests/ui/unsafe/ranged_ints_macro.rs | 19 + .../rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr | 102 + tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs | 85 + .../rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr | 104 + tests/ui/unsafe/union-assignop.mirunsafeck.stderr | 51 + tests/ui/unsafe/union-assignop.rs | 29 + tests/ui/unsafe/union-assignop.thirunsafeck.stderr | 51 + tests/ui/unsafe/union-modification.rs | 37 + tests/ui/unsafe/union.mir.stderr | 19 + tests/ui/unsafe/union.rs | 53 + tests/ui/unsafe/union.thir.stderr | 38 + tests/ui/unsafe/union_access_through_block.rs | 18 + tests/ui/unsafe/union_destructure.mir.stderr | 16 + tests/ui/unsafe/union_destructure.rs | 51 + tests/ui/unsafe/union_wild_or_wild.rs | 12 + ...afe-around-compiler-generated-unsafe.mir.stderr | 20 + .../unsafe-around-compiler-generated-unsafe.rs | 14 + ...fe-around-compiler-generated-unsafe.thir.stderr | 20 + tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr | 11 + tests/ui/unsafe/unsafe-assign.rs | 25 + tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr | 11 + tests/ui/unsafe/unsafe-block-without-braces.rs | 6 + tests/ui/unsafe/unsafe-block-without-braces.stderr | 15 + tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr | 27 + tests/ui/unsafe/unsafe-borrow.rs | 56 + tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr | 27 + tests/ui/unsafe/unsafe-const-fn.mir.stderr | 11 + tests/ui/unsafe/unsafe-const-fn.rs | 15 + tests/ui/unsafe/unsafe-const-fn.thir.stderr | 11 + .../unsafe/unsafe-fn-assign-deref-ptr.mir.stderr | 11 + tests/ui/unsafe/unsafe-fn-assign-deref-ptr.rs | 10 + .../unsafe/unsafe-fn-assign-deref-ptr.thir.stderr | 11 + tests/ui/unsafe/unsafe-fn-autoderef.rs | 23 + tests/ui/unsafe/unsafe-fn-autoderef.stderr | 11 + .../unsafe/unsafe-fn-called-from-safe.mir.stderr | 11 + tests/ui/unsafe/unsafe-fn-called-from-safe.rs | 10 + .../unsafe/unsafe-fn-called-from-safe.thir.stderr | 11 + tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr | 11 + tests/ui/unsafe/unsafe-fn-deref-ptr.rs | 9 + tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr | 11 + tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr | 11 + tests/ui/unsafe/unsafe-fn-used-as-value.rs | 11 + .../ui/unsafe/unsafe-fn-used-as-value.thir.stderr | 11 + tests/ui/unsafe/unsafe-not-inherited.rs | 26 + tests/ui/unsafe/unsafe-not-inherited.stderr | 24 + tests/ui/unsafe/unsafe-subtyping.rs | 11 + tests/ui/unsafe/unsafe-subtyping.stderr | 14 + tests/ui/unsafe/unsafe-trait-impl.rs | 14 + tests/ui/unsafe/unsafe-trait-impl.stderr | 17 + .../ui/unsafe/unsafe-unstable-const-fn.mir.stderr | 11 + tests/ui/unsafe/unsafe-unstable-const-fn.rs | 14 + .../ui/unsafe/unsafe-unstable-const-fn.thir.stderr | 11 + tests/ui/unsigned-literal-negation.rs | 5 + tests/ui/unsigned-literal-negation.stderr | 36 + tests/ui/unsized-locals/autoderef.rs | 49 + tests/ui/unsized-locals/auxiliary/ufuncs.rs | 3 + tests/ui/unsized-locals/borrow-after-move.rs | 43 + tests/ui/unsized-locals/borrow-after-move.stderr | 85 + tests/ui/unsized-locals/box-fnonce.rs | 10 + .../by-value-trait-object-safety-rpass.rs | 25 + .../by-value-trait-object-safety-withdefault.rs | 23 + .../unsized-locals/by-value-trait-object-safety.rs | 22 + .../by-value-trait-object-safety.stderr | 20 + tests/ui/unsized-locals/double-move.rs | 54 + tests/ui/unsized-locals/double-move.stderr | 86 + .../unsized-locals/issue-30276-feature-flagged.rs | 8 + .../issue-30276-feature-flagged.stderr | 22 + tests/ui/unsized-locals/issue-30276.rs | 5 + tests/ui/unsized-locals/issue-30276.stderr | 13 + .../ui/unsized-locals/issue-50940-with-feature.rs | 8 + .../unsized-locals/issue-50940-with-feature.stderr | 26 + tests/ui/unsized-locals/issue-50940.rs | 5 + tests/ui/unsized-locals/issue-50940.stderr | 13 + .../ui/unsized-locals/reference-unsized-locals.rs | 10 + tests/ui/unsized-locals/simple-unsized-locals.rs | 9 + tests/ui/unsized-locals/suggest-borrow.rs | 7 + tests/ui/unsized-locals/suggest-borrow.stderr | 60 + tests/ui/unsized-locals/unsized-exprs-rpass.rs | 33 + tests/ui/unsized-locals/unsized-exprs.rs | 28 + tests/ui/unsized-locals/unsized-exprs.stderr | 41 + tests/ui/unsized-locals/unsized-exprs2.rs | 24 + tests/ui/unsized-locals/unsized-exprs2.stderr | 12 + tests/ui/unsized-locals/unsized-exprs3.rs | 10 + tests/ui/unsized-locals/unsized-exprs3.stderr | 13 + tests/ui/unsized-locals/unsized-index.rs | 27 + .../unsized-locals-using-unsized-fn-params.rs | 15 + .../unsized-locals-using-unsized-fn-params.stderr | 37 + tests/ui/unsized-locals/unsized-parameters.rs | 13 + tests/ui/unsized/box-instead-of-dyn-fn.rs | 15 + tests/ui/unsized/box-instead-of-dyn-fn.stderr | 42 + tests/ui/unsized/issue-30355.rs | 9 + tests/ui/unsized/issue-30355.stderr | 13 + tests/ui/unsized/issue-40231-1.rs | 54 + tests/ui/unsized/issue-40231-2.rs | 54 + tests/ui/unsized/issue-71659.rs | 32 + tests/ui/unsized/issue-71659.stderr | 18 + tests/ui/unsized/issue-75707.rs | 17 + tests/ui/unsized/issue-75707.stderr | 15 + tests/ui/unsized/issue-75899-but-gats.rs | 21 + tests/ui/unsized/issue-75899.rs | 18 + tests/ui/unsized/issue-91801.rs | 19 + tests/ui/unsized/issue-91801.stderr | 15 + tests/ui/unsized/issue-91803.rs | 8 + tests/ui/unsized/issue-91803.stderr | 15 + tests/ui/unsized/issue-97732.rs | 28 + tests/ui/unsized/maybe-bounds-where-cpass.rs | 9 + tests/ui/unsized/maybe-bounds-where.rs | 28 + tests/ui/unsized/maybe-bounds-where.stderr | 51 + .../unsized/param-mentioned-by-different-field.rs | 10 + .../param-mentioned-by-different-field.stderr | 14 + .../ui/unsized/return-unsized-from-trait-method.rs | 14 + .../return-unsized-from-trait-method.stderr | 9 + tests/ui/unsized/unchanged-param.rs | 11 + tests/ui/unsized/unsized-bare-typaram.rs | 4 + tests/ui/unsized/unsized-bare-typaram.stderr | 22 + tests/ui/unsized/unsized-enum.rs | 11 + tests/ui/unsized/unsized-enum.stderr | 29 + tests/ui/unsized/unsized-enum2.rs | 74 + tests/ui/unsized/unsized-enum2.stderr | 411 + tests/ui/unsized/unsized-fn-arg.fixed | 6 + tests/ui/unsized/unsized-fn-arg.rs | 6 + tests/ui/unsized/unsized-fn-arg.stderr | 22 + tests/ui/unsized/unsized-fn-param.rs | 20 + tests/ui/unsized/unsized-fn-param.stderr | 55 + .../ui/unsized/unsized-inherent-impl-self-type.rs | 11 + .../unsized/unsized-inherent-impl-self-type.stderr | 29 + tests/ui/unsized/unsized-struct.rs | 18 + tests/ui/unsized/unsized-struct.stderr | 53 + tests/ui/unsized/unsized-trait-impl-self-type.rs | 14 + .../ui/unsized/unsized-trait-impl-self-type.stderr | 29 + tests/ui/unsized/unsized-trait-impl-trait-arg.rs | 12 + .../ui/unsized/unsized-trait-impl-trait-arg.stderr | 26 + tests/ui/unsized/unsized-tuple-impls.rs | 21 + tests/ui/unsized/unsized.rs | 25 + tests/ui/unsized/unsized2.rs | 96 + tests/ui/unsized/unsized3-rpass.rs | 93 + tests/ui/unsized/unsized3.rs | 50 + tests/ui/unsized/unsized3.stderr | 155 + tests/ui/unsized/unsized5.rs | 34 + tests/ui/unsized/unsized5.stderr | 136 + tests/ui/unsized/unsized6.rs | 44 + tests/ui/unsized/unsized6.stderr | 238 + tests/ui/unsized/unsized7.rs | 16 + tests/ui/unsized/unsized7.stderr | 26 + tests/ui/unterminated-comment.rs | 1 + tests/ui/unterminated-comment.stderr | 9 + tests/ui/unterminated-nested-comment.rs | 4 + tests/ui/unterminated-nested-comment.stderr | 21 + tests/ui/unused-crate-deps/auxiliary/bar.rs | 1 + tests/ui/unused-crate-deps/auxiliary/foo.rs | 5 + tests/ui/unused-crate-deps/deny-attr.rs | 9 + tests/ui/unused-crate-deps/deny-attr.stderr | 14 + .../unused-crate-deps/deny-cmdline-json-silent.rs | 8 + .../deny-cmdline-json-silent.stderr | 1 + tests/ui/unused-crate-deps/deny-cmdline-json.rs | 7 + .../ui/unused-crate-deps/deny-cmdline-json.stderr | 1 + tests/ui/unused-crate-deps/deny-cmdline.rs | 8 + tests/ui/unused-crate-deps/deny-cmdline.stderr | 10 + .../ui/unused-crate-deps/ignore-pathless-extern.rs | 12 + tests/ui/unused-crate-deps/libfib.rs | 21 + tests/ui/unused-crate-deps/libfib.stderr | 10 + tests/ui/unused-crate-deps/lint-group.rs | 9 + tests/ui/unused-crate-deps/suppress.rs | 11 + tests/ui/unused-crate-deps/test-use-ok.rs | 15 + tests/ui/unused-crate-deps/test.mk | 7 + tests/ui/unused-crate-deps/unused-aliases.rs | 13 + tests/ui/unused-crate-deps/unused-aliases.stderr | 14 + .../ui/unused-crate-deps/use_extern_crate_2015.rs | 13 + tests/ui/unused-crate-deps/warn-attr.rs | 10 + tests/ui/unused-crate-deps/warn-attr.stderr | 14 + tests/ui/unused-crate-deps/warn-cmdline-json.rs | 8 + .../ui/unused-crate-deps/warn-cmdline-json.stderr | 1 + tests/ui/unused-crate-deps/warn-cmdline-static.rs | 10 + .../unused-crate-deps/warn-cmdline-static.stderr | 10 + tests/ui/unused-crate-deps/warn-cmdline.rs | 9 + tests/ui/unused-crate-deps/warn-cmdline.stderr | 10 + tests/ui/unused-move-capture.rs | 8 + tests/ui/unused-move.rs | 13 + .../unwind-abis/feature-gate-c-unwind-enabled.rs | 12 + tests/ui/unwind-abis/feature-gate-c-unwind.rs | 13 + tests/ui/unwind-abis/feature-gate-c-unwind.stderr | 33 + .../ui/unwind-abis/feature-gate-stdcall-unwind.rs | 30 + .../unwind-abis/feature-gate-stdcall-unwind.stderr | 66 + tests/ui/unwind-abis/feature-gate-system-unwind.rs | 9 + .../unwind-abis/feature-gate-system-unwind.stderr | 12 + .../ui/unwind-abis/feature-gate-thiscall-unwind.rs | 39 + .../feature-gate-thiscall-unwind.stderr | 122 + tests/ui/unwind-abis/ffi-unwind-calls-lint.rs | 26 + tests/ui/unwind-abis/ffi-unwind-calls-lint.stderr | 20 + tests/ui/unwind-no-uwtable.rs | 34 + tests/ui/unwind-unique.rs | 15 + tests/ui/use-import-export.rs | 12 + tests/ui/use-keyword-2.rs | 23 + tests/ui/use-module-level-int-consts.rs | 12 + tests/ui/use-nested-groups.rs | 32 + tests/ui/use.rs | 23 + .../use/auxiliary/extern-use-primitive-type-lib.rs | 3 + tests/ui/use/auxiliary/use-from-trait-xc.rs | 29 + tests/ui/use/issue-18986.rs | 10 + tests/ui/use/issue-18986.stderr | 9 + .../use/issue-60976-extern-use-primitive-type.rs | 7 + tests/ui/use/use-after-move-based-on-type.rs | 5 + tests/ui/use/use-after-move-based-on-type.stderr | 19 + .../use/use-after-move-implicity-coerced-object.rs | 30 + .../use-after-move-implicity-coerced-object.stderr | 23 + tests/ui/use/use-after-move-self-based-on-type.rs | 21 + .../use/use-after-move-self-based-on-type.stderr | 19 + tests/ui/use/use-after-move-self.rs | 19 + tests/ui/use/use-after-move-self.stderr | 19 + tests/ui/use/use-associated-const.rs | 13 + tests/ui/use/use-associated-const.stderr | 9 + tests/ui/use/use-crate-self.rs | 4 + tests/ui/use/use-crate-self.stderr | 8 + tests/ui/use/use-from-trait-xc.rs | 26 + tests/ui/use/use-from-trait-xc.stderr | 70 + tests/ui/use/use-from-trait.rs | 22 + tests/ui/use/use-from-trait.stderr | 34 + tests/ui/use/use-keyword.rs | 17 + tests/ui/use/use-keyword.stderr | 22 + tests/ui/use/use-meta-mismatch.rs | 5 + tests/ui/use/use-meta-mismatch.stderr | 9 + tests/ui/use/use-mod.rs | 19 + tests/ui/use/use-mod.stderr | 33 + tests/ui/use/use-mod/use-mod-2.rs | 11 + tests/ui/use/use-mod/use-mod-2.stderr | 15 + tests/ui/use/use-mod/use-mod-3.rs | 12 + tests/ui/use/use-mod/use-mod-3.stderr | 27 + tests/ui/use/use-mod/use-mod-4.rs | 7 + tests/ui/use/use-mod/use-mod-4.stderr | 42 + tests/ui/use/use-mod/use-mod-5.rs | 13 + tests/ui/use/use-mod/use-mod-5.stderr | 19 + tests/ui/use/use-mod/use-mod-6.rs | 13 + tests/ui/use/use-mod/use-mod-6.stderr | 19 + tests/ui/use/use-nested-groups-error.rs | 15 + tests/ui/use/use-nested-groups-error.stderr | 12 + tests/ui/use/use-nested-groups-unused-imports.rs | 24 + .../ui/use/use-nested-groups-unused-imports.stderr | 26 + tests/ui/use/use-paths-as-items.rs | 9 + tests/ui/use/use-paths-as-items.stderr | 13 + tests/ui/use/use-self-type.rs | 11 + tests/ui/use/use-self-type.stderr | 16 + tests/ui/use/use-super-global-path.rs | 16 + tests/ui/use/use-super-global-path.stderr | 21 + tests/ui/used.rs | 16 + tests/ui/used.stderr | 26 + tests/ui/user-defined-macro-rules.rs | 9 + tests/ui/using-target-feature-unstable.rs | 11 + tests/ui/usize-generic-argument-parent.rs | 5 + tests/ui/usize-generic-argument-parent.stderr | 17 + tests/ui/utf8-bom.rs | 6 + tests/ui/utf8_idents.rs | 16 + .../ui/variance-intersection-of-ref-and-opt-ref.rs | 25 + tests/ui/variance-iterators-in-libcore.rs | 10 + tests/ui/variance/variance-associated-consts.rs | 17 + .../ui/variance/variance-associated-consts.stderr | 8 + tests/ui/variance/variance-associated-types.rs | 22 + tests/ui/variance/variance-associated-types.stderr | 14 + tests/ui/variance/variance-associated-types2.rs | 17 + .../ui/variance/variance-associated-types2.stderr | 10 + .../ui/variance/variance-btree-invariant-types.rs | 80 + .../variance/variance-btree-invariant-types.stderr | 202 + tests/ui/variance/variance-cell-is-invariant.rs | 19 + .../ui/variance/variance-cell-is-invariant.stderr | 18 + .../variance/variance-contravariant-arg-object.rs | 27 + .../variance-contravariant-arg-object.stderr | 28 + .../variance-contravariant-arg-trait-match.rs | 28 + .../variance-contravariant-arg-trait-match.stderr | 28 + .../variance-contravariant-self-trait-match.rs | 29 + .../variance-contravariant-self-trait-match.stderr | 28 + tests/ui/variance/variance-covariant-arg-object.rs | 27 + .../variance/variance-covariant-arg-object.stderr | 28 + .../variance/variance-covariant-arg-trait-match.rs | 27 + .../variance-covariant-arg-trait-match.stderr | 28 + .../variance-covariant-self-trait-match.rs | 27 + .../variance-covariant-self-trait-match.stderr | 28 + tests/ui/variance/variance-invariant-arg-object.rs | 23 + .../variance/variance-invariant-arg-object.stderr | 28 + .../variance/variance-invariant-arg-trait-match.rs | 23 + .../variance-invariant-arg-trait-match.stderr | 28 + .../variance-invariant-self-trait-match.rs | 23 + .../variance-invariant-self-trait-match.stderr | 28 + tests/ui/variance/variance-issue-20533.rs | 43 + tests/ui/variance/variance-issue-20533.stderr | 33 + tests/ui/variance/variance-object-types.rs | 12 + tests/ui/variance/variance-object-types.stderr | 8 + tests/ui/variance/variance-regions-direct.rs | 65 + tests/ui/variance/variance-regions-direct.stderr | 44 + tests/ui/variance/variance-regions-indirect.rs | 34 + tests/ui/variance/variance-regions-indirect.stderr | 32 + .../ui/variance/variance-regions-unused-direct.rs | 15 + .../variance/variance-regions-unused-direct.stderr | 19 + .../variance/variance-regions-unused-indirect.rs | 12 + .../variance-regions-unused-indirect.stderr | 43 + tests/ui/variance/variance-trait-bounds.rs | 35 + tests/ui/variance/variance-trait-bounds.stderr | 26 + tests/ui/variance/variance-trait-matching.rs | 38 + tests/ui/variance/variance-trait-matching.stderr | 12 + tests/ui/variance/variance-trait-object-bound.rs | 18 + .../ui/variance/variance-trait-object-bound.stderr | 8 + tests/ui/variance/variance-types-bounds.rs | 43 + tests/ui/variance/variance-types-bounds.stderr | 32 + tests/ui/variance/variance-types.rs | 41 + tests/ui/variance/variance-types.stderr | 38 + tests/ui/variance/variance-unused-region-param.rs | 7 + .../variance/variance-unused-region-param.stderr | 19 + tests/ui/variance/variance-unused-type-param.rs | 28 + .../ui/variance/variance-unused-type-param.stderr | 54 + .../variance-use-contravariant-struct-1.rs | 15 + .../variance-use-contravariant-struct-1.stderr | 15 + .../variance-use-contravariant-struct-2.rs | 17 + .../ui/variance/variance-use-covariant-struct-1.rs | 14 + .../variance-use-covariant-struct-1.stderr | 15 + .../ui/variance/variance-use-covariant-struct-2.rs | 16 + .../ui/variance/variance-use-invariant-struct-1.rs | 23 + .../variance-use-invariant-struct-1.stderr | 34 + tests/ui/variants/auxiliary/variant-namespacing.rs | 5 + tests/ui/variants/variant-namespacing.rs | 33 + tests/ui/variants/variant-namespacing.stderr | 93 + tests/ui/variants/variant-size-differences.rs | 8 + tests/ui/variants/variant-size-differences.stderr | 14 + tests/ui/variants/variant-used-as-type.rs | 20 + tests/ui/variants/variant-used-as-type.stderr | 29 + tests/ui/wait-forked-but-failed-child.rs | 63 + tests/ui/walk-struct-literal-with.rs | 17 + tests/ui/walk-struct-literal-with.stderr | 20 + tests/ui/wasm-custom-section-relocations.rs | 15 + tests/ui/wasm-custom-section-relocations.stderr | 14 + tests/ui/wasm/simd-to-array-80108.rs | 15 + tests/ui/wasm/wasm-hang-issue-76281.rs | 12 + tests/ui/wasm/wasm-import-module.rs | 21 + tests/ui/wasm/wasm-import-module.stderr | 38 + tests/ui/weak-new-uninhabited-issue-48493.rs | 7 + tests/ui/weird-exit-code.rs | 28 + tests/ui/weird-exprs.rs | 230 + tests/ui/wf/hir-wf-canonicalized.rs | 18 + tests/ui/wf/hir-wf-canonicalized.stderr | 32 + tests/ui/wf/hir-wf-check-erase-regions.rs | 14 + tests/ui/wf/hir-wf-check-erase-regions.stderr | 27 + tests/ui/wf/issue-103573.rs | 22 + tests/ui/wf/issue-103573.stderr | 14 + tests/ui/wf/issue-48638.rs | 21 + tests/ui/wf/issue-87495.rs | 8 + tests/ui/wf/issue-87495.stderr | 18 + tests/ui/wf/issue-95665.rs | 18 + tests/ui/wf/issue-95665.stderr | 15 + tests/ui/wf/issue-96810.rs | 12 + tests/ui/wf/issue-96810.stderr | 19 + tests/ui/wf/wf-array-elem-sized.rs | 11 + tests/ui/wf/wf-array-elem-sized.stderr | 12 + tests/ui/wf/wf-complex-assoc-type.rs | 12 + tests/ui/wf/wf-complex-assoc-type.stderr | 15 + tests/ui/wf/wf-const-type.rs | 14 + tests/ui/wf/wf-const-type.stderr | 20 + tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs | 18 + tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr | 51 + tests/ui/wf/wf-convert-unsafe-trait-obj.rs | 18 + tests/ui/wf/wf-convert-unsafe-trait-obj.stderr | 51 + tests/ui/wf/wf-enum-bound.rs | 16 + tests/ui/wf/wf-enum-bound.stderr | 19 + tests/ui/wf/wf-enum-fields-struct-variant.rs | 18 + tests/ui/wf/wf-enum-fields-struct-variant.stderr | 19 + tests/ui/wf/wf-enum-fields.rs | 16 + tests/ui/wf/wf-enum-fields.stderr | 19 + tests/ui/wf/wf-fn-where-clause.rs | 20 + tests/ui/wf/wf-fn-where-clause.stderr | 49 + tests/ui/wf/wf-foreign-fn-decl-ret.rs | 18 + tests/ui/wf/wf-foreign-fn-decl-ret.stderr | 21 + tests/ui/wf/wf-impl-associated-type-region.rs | 14 + tests/ui/wf/wf-impl-associated-type-region.stderr | 14 + tests/ui/wf/wf-impl-associated-type-trait.rs | 22 + tests/ui/wf/wf-impl-associated-type-trait.stderr | 19 + tests/ui/wf/wf-impl-self-type.rs | 7 + tests/ui/wf/wf-impl-self-type.stderr | 13 + tests/ui/wf/wf-in-fn-arg.rs | 14 + tests/ui/wf/wf-in-fn-arg.stderr | 19 + tests/ui/wf/wf-in-fn-ret.rs | 14 + tests/ui/wf/wf-in-fn-ret.stderr | 19 + tests/ui/wf/wf-in-fn-type-arg.rs | 12 + tests/ui/wf/wf-in-fn-type-arg.stderr | 19 + tests/ui/wf/wf-in-fn-type-ret.rs | 12 + tests/ui/wf/wf-in-fn-type-ret.stderr | 19 + tests/ui/wf/wf-in-fn-type-static.rs | 22 + tests/ui/wf/wf-in-fn-type-static.stderr | 25 + tests/ui/wf/wf-in-fn-where-clause.rs | 15 + tests/ui/wf/wf-in-fn-where-clause.stderr | 19 + tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs | 17 + .../wf/wf-in-foreign-fn-decls-issue-80468.stderr | 37 + tests/ui/wf/wf-in-obj-type-static.rs | 18 + tests/ui/wf/wf-in-obj-type-static.stderr | 14 + tests/ui/wf/wf-in-obj-type-trait.rs | 14 + tests/ui/wf/wf-in-obj-type-trait.stderr | 19 + .../ui/wf/wf-inherent-impl-method-where-clause.rs | 17 + .../wf/wf-inherent-impl-method-where-clause.stderr | 19 + tests/ui/wf/wf-inherent-impl-where-clause.rs | 16 + tests/ui/wf/wf-inherent-impl-where-clause.stderr | 19 + tests/ui/wf/wf-misc-methods-issue-28609.rs | 74 + tests/ui/wf/wf-misc-methods-issue-28609.stderr | 55 + tests/ui/wf/wf-object-safe.rs | 10 + tests/ui/wf/wf-object-safe.stderr | 18 + tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs | 22 + tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr | 25 + .../wf-packed-on-proj-of-type-as-unimpl-trait.rs | 31 + ...f-packed-on-proj-of-type-as-unimpl-trait.stderr | 9 + tests/ui/wf/wf-static-method.rs | 59 + tests/ui/wf/wf-static-method.stderr | 77 + tests/ui/wf/wf-static-type.rs | 14 + tests/ui/wf/wf-static-type.stderr | 20 + tests/ui/wf/wf-struct-bound.rs | 16 + tests/ui/wf/wf-struct-bound.stderr | 19 + tests/ui/wf/wf-struct-field.rs | 16 + tests/ui/wf/wf-struct-field.stderr | 19 + tests/ui/wf/wf-trait-associated-type-bound.rs | 14 + tests/ui/wf/wf-trait-associated-type-bound.stderr | 19 + tests/ui/wf/wf-trait-associated-type-region.rs | 14 + tests/ui/wf/wf-trait-associated-type-region.stderr | 12 + tests/ui/wf/wf-trait-associated-type-trait.rs | 16 + tests/ui/wf/wf-trait-associated-type-trait.stderr | 19 + tests/ui/wf/wf-trait-bound.rs | 15 + tests/ui/wf/wf-trait-bound.stderr | 19 + tests/ui/wf/wf-trait-default-fn-arg.rs | 19 + tests/ui/wf/wf-trait-default-fn-arg.stderr | 19 + tests/ui/wf/wf-trait-default-fn-ret.rs | 19 + tests/ui/wf/wf-trait-default-fn-ret.stderr | 19 + tests/ui/wf/wf-trait-default-fn-where-clause.rs | 19 + .../ui/wf/wf-trait-default-fn-where-clause.stderr | 19 + tests/ui/wf/wf-trait-fn-arg.rs | 16 + tests/ui/wf/wf-trait-fn-arg.stderr | 19 + tests/ui/wf/wf-trait-fn-ret.rs | 16 + tests/ui/wf/wf-trait-fn-ret.stderr | 19 + tests/ui/wf/wf-trait-fn-where-clause.rs | 17 + tests/ui/wf/wf-trait-fn-where-clause.stderr | 19 + tests/ui/wf/wf-trait-superbound.rs | 12 + tests/ui/wf/wf-trait-superbound.stderr | 19 + tests/ui/wf/wf-unsafe-trait-obj-match.rs | 29 + tests/ui/wf/wf-unsafe-trait-obj-match.stderr | 54 + .../ui/where-clauses/auxiliary/where_clauses_xc.rs | 19 + .../higher-ranked-fn-type.quiet.stderr | 18 + tests/ui/where-clauses/higher-ranked-fn-type.rs | 25 + .../higher-ranked-fn-type.verbose.stderr | 18 + tests/ui/where-clauses/ignore-err-clauses.rs | 14 + tests/ui/where-clauses/ignore-err-clauses.stderr | 9 + .../where-clause-bounds-inconsistency.rs | 23 + ...ause-constraints-are-local-for-inherent-impl.rs | 18 + ...-constraints-are-local-for-inherent-impl.stderr | 21 + ...-clause-constraints-are-local-for-trait-impl.rs | 23 + ...use-constraints-are-local-for-trait-impl.stderr | 21 + .../where-clause-early-bound-lifetimes.rs | 18 + .../where-clause-method-substituion-rpass.rs | 23 + .../where-clause-method-substituion.rs | 22 + .../where-clause-method-substituion.stderr | 15 + .../where-clauses/where-clause-region-outlives.rs | 12 + .../ui/where-clauses/where-clauses-cross-crate.rs | 13 + tests/ui/where-clauses/where-clauses-lifetimes.rs | 10 + .../where-clauses-method-unsatisfied.rs | 20 + .../where-clauses-method-unsatisfied.stderr | 19 + tests/ui/where-clauses/where-clauses-method.rs | 20 + .../where-clauses-unboxed-closures.rs | 17 + .../ui/where-clauses/where-clauses-unsatisfied.rs | 8 + .../where-clauses/where-clauses-unsatisfied.stderr | 19 + tests/ui/where-clauses/where-clauses.rs | 27 + .../ui/where-clauses/where-equality-constraints.rs | 6 + .../where-equality-constraints.stderr | 18 + tests/ui/where-clauses/where-for-self-2.rs | 24 + tests/ui/where-clauses/where-for-self-2.stderr | 11 + tests/ui/where-clauses/where-for-self.rs | 19 + tests/ui/where-clauses/where-for-self.stderr | 9 + .../ui/where-clauses/where-lifetime-resolution.rs | 12 + .../where-clauses/where-lifetime-resolution.stderr | 42 + tests/ui/while-type-error.rs | 3 + tests/ui/while-type-error.stderr | 12 + tests/ui/windows-subsystem-invalid.rs | 5 + tests/ui/windows-subsystem-invalid.stderr | 4 + tests/ui/write-fmt-errors.rs | 48 + tests/ui/writing-to-immutable-vec.rs | 4 + tests/ui/writing-to-immutable-vec.stderr | 14 + tests/ui/wrong-hashset-issue-42918.rs | 31 + tests/ui/wrong-mul-method-signature.rs | 68 + tests/ui/wrong-mul-method-signature.stderr | 56 + tests/ui/wrong-ret-type.rs | 3 + tests/ui/wrong-ret-type.stderr | 16 + tests/ui/xc-private-method.rs | 11 + tests/ui/xc-private-method.stderr | 25 + tests/ui/xc-private-method2.rs | 11 + tests/ui/xc-private-method2.stderr | 25 + .../ui/xcrate/auxiliary/static_priv_by_default.rs | 51 + tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs | 28 + tests/ui/xcrate/xcrate-private-by-default.rs | 45 + tests/ui/xcrate/xcrate-private-by-default.stderr | 123 + tests/ui/xcrate/xcrate-unit-struct-2.rs | 30 + tests/ui/xcrate/xcrate-unit-struct.rs | 12 + tests/ui/xcrate/xcrate-unit-struct.stderr | 14 + tests/ui/zero-sized/zero-size-type-destructors.rs | 21 + tests/ui/zero-sized/zero-sized-binary-heap-push.rs | 20 + tests/ui/zero-sized/zero-sized-btreemap-insert.rs | 25 + tests/ui/zero-sized/zero-sized-linkedlist-push.rs | 29 + tests/ui/zero-sized/zero-sized-tuple-struct.rs | 13 + 23539 files changed, 709199 insertions(+) create mode 100644 tests/ui/abi/abi-sysv64-arg-passing.rs create mode 100644 tests/ui/abi/abi-sysv64-register-usage.rs create mode 100644 tests/ui/abi/abi-typo-unstable.rs create mode 100644 tests/ui/abi/abi-typo-unstable.stderr create mode 100644 tests/ui/abi/anon-extern-mod.rs create mode 100644 tests/ui/abi/c-stack-as-value.rs create mode 100644 tests/ui/abi/c-stack-returning-int64.rs create mode 100644 tests/ui/abi/cabi-int-widening.rs create mode 100644 tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs create mode 100644 tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs create mode 100644 tests/ui/abi/cross-crate/duplicated-external-mods.rs create mode 100644 tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs create mode 100644 tests/ui/abi/extern/extern-call-deep.rs create mode 100644 tests/ui/abi/extern/extern-call-deep2.rs create mode 100644 tests/ui/abi/extern/extern-call-direct.rs create mode 100644 tests/ui/abi/extern/extern-call-indirect.rs create mode 100644 tests/ui/abi/extern/extern-call-scrub.rs create mode 100644 tests/ui/abi/extern/extern-crosscrate.rs create mode 100644 tests/ui/abi/extern/extern-pass-TwoU16s.rs create mode 100644 tests/ui/abi/extern/extern-pass-TwoU32s.rs create mode 100644 tests/ui/abi/extern/extern-pass-TwoU64s.rs create mode 100644 tests/ui/abi/extern/extern-pass-TwoU8s.rs create mode 100644 tests/ui/abi/extern/extern-pass-char.rs create mode 100644 tests/ui/abi/extern/extern-pass-double.rs create mode 100644 tests/ui/abi/extern/extern-pass-empty.rs create mode 100644 tests/ui/abi/extern/extern-pass-u32.rs create mode 100644 tests/ui/abi/extern/extern-pass-u64.rs create mode 100644 tests/ui/abi/extern/extern-return-TwoU16s.rs create mode 100644 tests/ui/abi/extern/extern-return-TwoU32s.rs create mode 100644 tests/ui/abi/extern/extern-return-TwoU64s.rs create mode 100644 tests/ui/abi/extern/extern-return-TwoU8s.rs create mode 100644 tests/ui/abi/foreign/auxiliary/foreign_lib.rs create mode 100644 tests/ui/abi/foreign/foreign-call-no-runtime.rs create mode 100644 tests/ui/abi/foreign/foreign-dupe.rs create mode 100644 tests/ui/abi/foreign/foreign-fn-with-byval.rs create mode 100644 tests/ui/abi/foreign/foreign-no-abi.rs create mode 100644 tests/ui/abi/foreign/invoke-external-foreign.rs create mode 100644 tests/ui/abi/homogenous-floats-target-feature-mixup.rs create mode 100644 tests/ui/abi/issue-28676.rs create mode 100644 tests/ui/abi/issues/issue-22565-rust-call.rs create mode 100644 tests/ui/abi/issues/issue-22565-rust-call.stderr create mode 100644 tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs create mode 100644 tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs create mode 100644 tests/ui/abi/lib-defaults.rs create mode 100644 tests/ui/abi/mir/mir_codegen_calls_variadic.rs create mode 100644 tests/ui/abi/nullable-pointer-ffi-compat.rs create mode 100644 tests/ui/abi/numbers-arithmetic/i128-ffi.rs create mode 100644 tests/ui/abi/rustcall-generic.rs create mode 100644 tests/ui/abi/segfault-no-out-of-stack.rs create mode 100644 tests/ui/abi/stack-probes-lto.rs create mode 100644 tests/ui/abi/stack-probes.rs create mode 100644 tests/ui/abi/stack-protector.rs create mode 100644 tests/ui/abi/statics/static-mut-foreign.rs create mode 100644 tests/ui/abi/struct-enums/struct-return.rs create mode 100644 tests/ui/abi/union/union-c-interop.rs create mode 100644 tests/ui/abi/unsupported.aarch64.stderr create mode 100644 tests/ui/abi/unsupported.arm.stderr create mode 100644 tests/ui/abi/unsupported.i686.stderr create mode 100644 tests/ui/abi/unsupported.rs create mode 100644 tests/ui/abi/unsupported.x64.stderr create mode 100644 tests/ui/abi/variadic-ffi.rs create mode 100644 tests/ui/abi/x86stdcall.rs create mode 100644 tests/ui/abi/x86stdcall2.rs create mode 100644 tests/ui/alias-uninit-value.rs create mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs create mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr create mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs create mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr create mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs create mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr create mode 100644 tests/ui/alloc-error/default-alloc-error-hook.rs create mode 100644 tests/ui/allocator/allocator-args.rs create mode 100644 tests/ui/allocator/allocator-args.stderr create mode 100644 tests/ui/allocator/auxiliary/custom-as-global.rs create mode 100644 tests/ui/allocator/auxiliary/custom.rs create mode 100644 tests/ui/allocator/auxiliary/helper.rs create mode 100644 tests/ui/allocator/auxiliary/system-allocator.rs create mode 100644 tests/ui/allocator/auxiliary/system-allocator2.rs create mode 100644 tests/ui/allocator/custom-in-block.rs create mode 100644 tests/ui/allocator/custom-in-submodule.rs create mode 100644 tests/ui/allocator/custom.rs create mode 100644 tests/ui/allocator/function-allocator.rs create mode 100644 tests/ui/allocator/function-allocator.stderr create mode 100644 tests/ui/allocator/hygiene.rs create mode 100644 tests/ui/allocator/no_std-alloc-error-handler-custom.rs create mode 100644 tests/ui/allocator/no_std-alloc-error-handler-default.rs create mode 100644 tests/ui/allocator/not-an-allocator.rs create mode 100644 tests/ui/allocator/not-an-allocator.stderr create mode 100644 tests/ui/allocator/object-safe.rs create mode 100644 tests/ui/allocator/two-allocators.rs create mode 100644 tests/ui/allocator/two-allocators.stderr create mode 100644 tests/ui/allocator/two-allocators2.rs create mode 100644 tests/ui/allocator/two-allocators2.stderr create mode 100644 tests/ui/allocator/two-allocators3.rs create mode 100644 tests/ui/allocator/two-allocators3.stderr create mode 100644 tests/ui/allocator/xcrate-use.rs create mode 100644 tests/ui/allocator/xcrate-use2.rs create mode 100644 tests/ui/annotate-snippet/auxiliary/multispan.rs create mode 100644 tests/ui/annotate-snippet/missing-type.rs create mode 100644 tests/ui/annotate-snippet/missing-type.stderr create mode 100644 tests/ui/annotate-snippet/multispan.rs create mode 100644 tests/ui/annotate-snippet/multispan.stderr create mode 100644 tests/ui/anon-params/anon-params-denied-2018.rs create mode 100644 tests/ui/anon-params/anon-params-denied-2018.stderr create mode 100644 tests/ui/anon-params/anon-params-deprecated.fixed create mode 100644 tests/ui/anon-params/anon-params-deprecated.rs create mode 100644 tests/ui/anon-params/anon-params-deprecated.stderr create mode 100644 tests/ui/anon-params/anon-params-edition-hygiene.rs create mode 100644 tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs create mode 100644 tests/ui/anonymous-higher-ranked-lifetime.rs create mode 100644 tests/ui/anonymous-higher-ranked-lifetime.stderr create mode 100644 tests/ui/argument-suggestions/basic.rs create mode 100644 tests/ui/argument-suggestions/basic.stderr create mode 100644 tests/ui/argument-suggestions/complex.rs create mode 100644 tests/ui/argument-suggestions/complex.stderr create mode 100644 tests/ui/argument-suggestions/display-is-suggestable.rs create mode 100644 tests/ui/argument-suggestions/display-is-suggestable.stderr create mode 100644 tests/ui/argument-suggestions/exotic-calls.rs create mode 100644 tests/ui/argument-suggestions/exotic-calls.stderr create mode 100644 tests/ui/argument-suggestions/extern-fn-arg-names.rs create mode 100644 tests/ui/argument-suggestions/extern-fn-arg-names.stderr create mode 100644 tests/ui/argument-suggestions/extra_arguments.rs create mode 100644 tests/ui/argument-suggestions/extra_arguments.stderr create mode 100644 tests/ui/argument-suggestions/formal-and-expected-differ.rs create mode 100644 tests/ui/argument-suggestions/formal-and-expected-differ.stderr create mode 100644 tests/ui/argument-suggestions/invalid_arguments.rs create mode 100644 tests/ui/argument-suggestions/invalid_arguments.stderr create mode 100644 tests/ui/argument-suggestions/issue-100154.rs create mode 100644 tests/ui/argument-suggestions/issue-100154.stderr create mode 100644 tests/ui/argument-suggestions/issue-100478.rs create mode 100644 tests/ui/argument-suggestions/issue-100478.stderr create mode 100644 tests/ui/argument-suggestions/issue-101097.rs create mode 100644 tests/ui/argument-suggestions/issue-101097.stderr create mode 100644 tests/ui/argument-suggestions/issue-96638.rs create mode 100644 tests/ui/argument-suggestions/issue-96638.stderr create mode 100644 tests/ui/argument-suggestions/issue-97197.rs create mode 100644 tests/ui/argument-suggestions/issue-97197.stderr create mode 100644 tests/ui/argument-suggestions/issue-97484.rs create mode 100644 tests/ui/argument-suggestions/issue-97484.stderr create mode 100644 tests/ui/argument-suggestions/issue-98894.rs create mode 100644 tests/ui/argument-suggestions/issue-98894.stderr create mode 100644 tests/ui/argument-suggestions/issue-98897.rs create mode 100644 tests/ui/argument-suggestions/issue-98897.stderr create mode 100644 tests/ui/argument-suggestions/issue-99482.rs create mode 100644 tests/ui/argument-suggestions/issue-99482.stderr create mode 100644 tests/ui/argument-suggestions/missing_arguments.rs create mode 100644 tests/ui/argument-suggestions/missing_arguments.stderr create mode 100644 tests/ui/argument-suggestions/mixed_cases.rs create mode 100644 tests/ui/argument-suggestions/mixed_cases.stderr create mode 100644 tests/ui/argument-suggestions/permuted_arguments.rs create mode 100644 tests/ui/argument-suggestions/permuted_arguments.stderr create mode 100644 tests/ui/argument-suggestions/swapped_arguments.rs create mode 100644 tests/ui/argument-suggestions/swapped_arguments.stderr create mode 100644 tests/ui/argument-suggestions/too-long.rs create mode 100644 tests/ui/argument-suggestions/too-long.stderr create mode 100644 tests/ui/argument-suggestions/two-mismatch-notes.rs create mode 100644 tests/ui/argument-suggestions/two-mismatch-notes.stderr create mode 100644 tests/ui/array-slice-vec/array-break-length.rs create mode 100644 tests/ui/array-slice-vec/array-break-length.stderr create mode 100644 tests/ui/array-slice-vec/array-not-vector.rs create mode 100644 tests/ui/array-slice-vec/array-not-vector.stderr create mode 100644 tests/ui/array-slice-vec/array_const_index-0.rs create mode 100644 tests/ui/array-slice-vec/array_const_index-0.stderr create mode 100644 tests/ui/array-slice-vec/array_const_index-1.rs create mode 100644 tests/ui/array-slice-vec/array_const_index-1.stderr create mode 100644 tests/ui/array-slice-vec/array_const_index-2.rs create mode 100644 tests/ui/array-slice-vec/bounds-check-no-overflow.rs create mode 100644 tests/ui/array-slice-vec/box-of-array-of-drop-1.rs create mode 100644 tests/ui/array-slice-vec/box-of-array-of-drop-2.rs create mode 100644 tests/ui/array-slice-vec/byte-literals.rs create mode 100644 tests/ui/array-slice-vec/cast-in-array-size.rs create mode 100644 tests/ui/array-slice-vec/check-static-mut-slices.rs create mode 100644 tests/ui/array-slice-vec/check-static-slice.rs create mode 100644 tests/ui/array-slice-vec/copy-out-of-array-1.rs create mode 100644 tests/ui/array-slice-vec/destructure-array-1.rs create mode 100644 tests/ui/array-slice-vec/dst-raw-slice.rs create mode 100644 tests/ui/array-slice-vec/empty-mutable-vec.rs create mode 100644 tests/ui/array-slice-vec/estr-slice.rs create mode 100644 tests/ui/array-slice-vec/evec-slice.rs create mode 100644 tests/ui/array-slice-vec/fixed_length_copy.rs create mode 100644 tests/ui/array-slice-vec/huge-largest-array.rs create mode 100644 tests/ui/array-slice-vec/infer_array_len.rs create mode 100644 tests/ui/array-slice-vec/infer_array_len.stderr create mode 100644 tests/ui/array-slice-vec/issue-15730.rs create mode 100644 tests/ui/array-slice-vec/issue-18425.rs create mode 100644 tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs create mode 100644 tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr create mode 100644 tests/ui/array-slice-vec/ivec-pass-by-value.rs create mode 100644 tests/ui/array-slice-vec/match_arr_unknown_len.rs create mode 100644 tests/ui/array-slice-vec/match_arr_unknown_len.stderr create mode 100644 tests/ui/array-slice-vec/mut-vstore-expr.rs create mode 100644 tests/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs create mode 100644 tests/ui/array-slice-vec/mutable-alias-vec.rs create mode 100644 tests/ui/array-slice-vec/nested-vec-1.rs create mode 100644 tests/ui/array-slice-vec/nested-vec-2.rs create mode 100644 tests/ui/array-slice-vec/nested-vec-3.rs create mode 100644 tests/ui/array-slice-vec/new-style-fixed-length-vec.rs create mode 100644 tests/ui/array-slice-vec/rcvr-borrowed-to-slice.rs create mode 100644 tests/ui/array-slice-vec/repeat_empty_ok.rs create mode 100644 tests/ui/array-slice-vec/repeat_empty_ok.stderr create mode 100644 tests/ui/array-slice-vec/repeated-vector-syntax.rs create mode 100644 tests/ui/array-slice-vec/show-boxed-slice.rs create mode 100644 tests/ui/array-slice-vec/slice-2.rs create mode 100644 tests/ui/array-slice-vec/slice-2.stderr create mode 100644 tests/ui/array-slice-vec/slice-mut-2.rs create mode 100644 tests/ui/array-slice-vec/slice-mut-2.stderr create mode 100644 tests/ui/array-slice-vec/slice-mut.rs create mode 100644 tests/ui/array-slice-vec/slice-mut.stderr create mode 100644 tests/ui/array-slice-vec/slice-of-zero-size-elements.rs create mode 100644 tests/ui/array-slice-vec/slice-panic-1.rs create mode 100644 tests/ui/array-slice-vec/slice-panic-2.rs create mode 100644 tests/ui/array-slice-vec/slice-pat-type-mismatches.rs create mode 100644 tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr create mode 100644 tests/ui/array-slice-vec/slice-to-vec-comparison.rs create mode 100644 tests/ui/array-slice-vec/slice-to-vec-comparison.stderr create mode 100644 tests/ui/array-slice-vec/slice.rs create mode 100644 tests/ui/array-slice-vec/slice_binary_search.rs create mode 100644 tests/ui/array-slice-vec/slice_is_sorted_by_borrow.rs create mode 100644 tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs create mode 100644 tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr create mode 100644 tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs create mode 100644 tests/ui/array-slice-vec/subslice-patterns-const-eval.rs create mode 100644 tests/ui/array-slice-vec/suggest-array-length.fixed create mode 100644 tests/ui/array-slice-vec/suggest-array-length.rs create mode 100644 tests/ui/array-slice-vec/suggest-array-length.stderr create mode 100644 tests/ui/array-slice-vec/variance-vec-covariant.rs create mode 100644 tests/ui/array-slice-vec/vec-dst.rs create mode 100644 tests/ui/array-slice-vec/vec-fixed-length.rs create mode 100644 tests/ui/array-slice-vec/vec-late-init.rs create mode 100644 tests/ui/array-slice-vec/vec-macro-no-std.rs create mode 100644 tests/ui/array-slice-vec/vec-macro-rvalue-scope.rs create mode 100644 tests/ui/array-slice-vec/vec-macro-with-brackets.rs create mode 100644 tests/ui/array-slice-vec/vec-macro-with-comma-only.rs create mode 100644 tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr create mode 100644 tests/ui/array-slice-vec/vec-macro-with-trailing-comma.rs create mode 100644 tests/ui/array-slice-vec/vec-matching-autoslice.rs create mode 100644 tests/ui/array-slice-vec/vec-matching-fixed.rs create mode 100644 tests/ui/array-slice-vec/vec-matching-fold.rs create mode 100644 tests/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs create mode 100644 tests/ui/array-slice-vec/vec-matching.rs create mode 100644 tests/ui/array-slice-vec/vec-mut-iter-borrow.rs create mode 100644 tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr create mode 100644 tests/ui/array-slice-vec/vec-overrun.rs create mode 100644 tests/ui/array-slice-vec/vec-repeat-with-cast.rs create mode 100644 tests/ui/array-slice-vec/vec-res-add.rs create mode 100644 tests/ui/array-slice-vec/vec-res-add.stderr create mode 100644 tests/ui/array-slice-vec/vec-tail-matching.rs create mode 100644 tests/ui/array-slice-vec/vector-cast-weirdness.rs create mode 100644 tests/ui/array-slice-vec/vector-cast-weirdness.stderr create mode 100644 tests/ui/array-slice-vec/vector-no-ann-2.rs create mode 100644 tests/ui/array-slice-vec/vector-no-ann.rs create mode 100644 tests/ui/array-slice-vec/vector-no-ann.stderr create mode 100644 tests/ui/artificial-block.rs create mode 100644 tests/ui/as-precedence.rs create mode 100644 tests/ui/asm/aarch64/bad-options.rs create mode 100644 tests/ui/asm/aarch64/bad-options.stderr create mode 100644 tests/ui/asm/aarch64/bad-reg.rs create mode 100644 tests/ui/asm/aarch64/bad-reg.stderr create mode 100644 tests/ui/asm/aarch64/const.rs create mode 100644 tests/ui/asm/aarch64/duplicate-options.fixed create mode 100644 tests/ui/asm/aarch64/duplicate-options.rs create mode 100644 tests/ui/asm/aarch64/duplicate-options.stderr create mode 100644 tests/ui/asm/aarch64/interpolated-idents.rs create mode 100644 tests/ui/asm/aarch64/interpolated-idents.stderr create mode 100644 tests/ui/asm/aarch64/llvm-58384.rs create mode 100644 tests/ui/asm/aarch64/may_unwind.rs create mode 100644 tests/ui/asm/aarch64/parse-error.rs create mode 100644 tests/ui/asm/aarch64/parse-error.stderr create mode 100644 tests/ui/asm/aarch64/srcloc.rs create mode 100644 tests/ui/asm/aarch64/srcloc.stderr create mode 100644 tests/ui/asm/aarch64/sym.rs create mode 100644 tests/ui/asm/aarch64/type-check-2-2.rs create mode 100644 tests/ui/asm/aarch64/type-check-2-2.stderr create mode 100644 tests/ui/asm/aarch64/type-check-2.rs create mode 100644 tests/ui/asm/aarch64/type-check-2.stderr create mode 100644 tests/ui/asm/aarch64/type-check-3.rs create mode 100644 tests/ui/asm/aarch64/type-check-3.stderr create mode 100644 tests/ui/asm/aarch64/type-check-4.rs create mode 100644 tests/ui/asm/aarch64/type-check-4.stderr create mode 100644 tests/ui/asm/bad-arch.mirunsafeck.stderr create mode 100644 tests/ui/asm/bad-arch.rs create mode 100644 tests/ui/asm/bad-arch.thirunsafeck.stderr create mode 100644 tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr create mode 100644 tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr create mode 100644 tests/ui/asm/bad-template.rs create mode 100644 tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr create mode 100644 tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr create mode 100644 tests/ui/asm/generic-const.rs create mode 100644 tests/ui/asm/inline-syntax.arm.stderr create mode 100644 tests/ui/asm/inline-syntax.rs create mode 100644 tests/ui/asm/inline-syntax.x86_64.stderr create mode 100644 tests/ui/asm/issue-72570.rs create mode 100644 tests/ui/asm/issue-72570.stderr create mode 100644 tests/ui/asm/issue-85247.rs create mode 100644 tests/ui/asm/issue-85247.rwpi.stderr create mode 100644 tests/ui/asm/issue-87802.rs create mode 100644 tests/ui/asm/issue-87802.stderr create mode 100644 tests/ui/asm/issue-89305.rs create mode 100644 tests/ui/asm/issue-89305.stderr create mode 100644 tests/ui/asm/issue-92378.rs create mode 100644 tests/ui/asm/issue-97490.rs create mode 100644 tests/ui/asm/issue-99071.rs create mode 100644 tests/ui/asm/issue-99071.stderr create mode 100644 tests/ui/asm/issue-99122-2.rs create mode 100644 tests/ui/asm/issue-99122.rs create mode 100644 tests/ui/asm/issue-99122.stderr create mode 100644 tests/ui/asm/may_unwind.rs create mode 100644 tests/ui/asm/naked-functions-ffi.rs create mode 100644 tests/ui/asm/naked-functions-ffi.stderr create mode 100644 tests/ui/asm/naked-functions-unused.aarch64.stderr create mode 100644 tests/ui/asm/naked-functions-unused.rs create mode 100644 tests/ui/asm/naked-functions-unused.x86_64.stderr create mode 100644 tests/ui/asm/naked-functions.rs create mode 100644 tests/ui/asm/naked-functions.stderr create mode 100644 tests/ui/asm/naked-invalid-attr.rs create mode 100644 tests/ui/asm/naked-invalid-attr.stderr create mode 100644 tests/ui/asm/named-asm-labels.rs create mode 100644 tests/ui/asm/named-asm-labels.s create mode 100644 tests/ui/asm/named-asm-labels.stderr create mode 100644 tests/ui/asm/noreturn.rs create mode 100644 tests/ui/asm/reg-conflict.rs create mode 100644 tests/ui/asm/reg-conflict.stderr create mode 100644 tests/ui/asm/type-check-1.rs create mode 100644 tests/ui/asm/type-check-1.stderr create mode 100644 tests/ui/asm/type-check-4.rs create mode 100644 tests/ui/asm/type-check-4.stderr create mode 100644 tests/ui/asm/unpretty-expanded.rs create mode 100644 tests/ui/asm/unpretty-expanded.stdout create mode 100644 tests/ui/asm/x86_64/bad-clobber-abi.rs create mode 100644 tests/ui/asm/x86_64/bad-clobber-abi.stderr create mode 100644 tests/ui/asm/x86_64/bad-options.rs create mode 100644 tests/ui/asm/x86_64/bad-options.stderr create mode 100644 tests/ui/asm/x86_64/bad-reg.rs create mode 100644 tests/ui/asm/x86_64/bad-reg.stderr create mode 100644 tests/ui/asm/x86_64/const.rs create mode 100644 tests/ui/asm/x86_64/duplicate-options.fixed create mode 100644 tests/ui/asm/x86_64/duplicate-options.rs create mode 100644 tests/ui/asm/x86_64/duplicate-options.stderr create mode 100644 tests/ui/asm/x86_64/interpolated-idents.rs create mode 100644 tests/ui/asm/x86_64/interpolated-idents.stderr create mode 100644 tests/ui/asm/x86_64/issue-82869.rs create mode 100644 tests/ui/asm/x86_64/issue-82869.stderr create mode 100644 tests/ui/asm/x86_64/issue-89875.rs create mode 100644 tests/ui/asm/x86_64/issue-96797.rs create mode 100644 tests/ui/asm/x86_64/may_unwind.rs create mode 100644 tests/ui/asm/x86_64/multiple-clobber-abi.rs create mode 100644 tests/ui/asm/x86_64/parse-error.rs create mode 100644 tests/ui/asm/x86_64/parse-error.stderr create mode 100644 tests/ui/asm/x86_64/srcloc.rs create mode 100644 tests/ui/asm/x86_64/srcloc.stderr create mode 100644 tests/ui/asm/x86_64/sym.rs create mode 100644 tests/ui/asm/x86_64/target-feature-attr.rs create mode 100644 tests/ui/asm/x86_64/target-feature-attr.stderr create mode 100644 tests/ui/asm/x86_64/type-check-2.rs create mode 100644 tests/ui/asm/x86_64/type-check-2.stderr create mode 100644 tests/ui/asm/x86_64/type-check-3.rs create mode 100644 tests/ui/asm/x86_64/type-check-3.stderr create mode 100644 tests/ui/asm/x86_64/type-check-4.rs create mode 100644 tests/ui/asm/x86_64/type-check-4.stderr create mode 100644 tests/ui/asm/x86_64/type-check-5.rs create mode 100644 tests/ui/asm/x86_64/type-check-5.stderr create mode 100644 tests/ui/assign-assign.rs create mode 100644 tests/ui/assign-imm-local-twice.rs create mode 100644 tests/ui/assign-imm-local-twice.stderr create mode 100644 tests/ui/assoc-lang-items.rs create mode 100644 tests/ui/assoc-lang-items.stderr create mode 100644 tests/ui/assoc-oddities-3.rs create mode 100644 tests/ui/associated-consts/assoc-const-eq-missing.rs create mode 100644 tests/ui/associated-consts/assoc-const-eq-missing.stderr create mode 100644 tests/ui/associated-consts/assoc-const-ty-mismatch.rs create mode 100644 tests/ui/associated-consts/assoc-const-ty-mismatch.stderr create mode 100644 tests/ui/associated-consts/assoc-const.rs create mode 100644 tests/ui/associated-consts/associated-const-ambiguity-report.rs create mode 100644 tests/ui/associated-consts/associated-const-ambiguity-report.stderr create mode 100644 tests/ui/associated-consts/associated-const-array-len.rs create mode 100644 tests/ui/associated-consts/associated-const-array-len.stderr create mode 100644 tests/ui/associated-consts/associated-const-const-eval.rs create mode 100644 tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs create mode 100644 tests/ui/associated-consts/associated-const-cross-crate-defaults.rs create mode 100644 tests/ui/associated-consts/associated-const-cross-crate.rs create mode 100644 tests/ui/associated-consts/associated-const-dead-code.rs create mode 100644 tests/ui/associated-consts/associated-const-dead-code.stderr create mode 100644 tests/ui/associated-consts/associated-const-generic-obligations.rs create mode 100644 tests/ui/associated-consts/associated-const-generic-obligations.stderr create mode 100644 tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs create mode 100644 tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr create mode 100644 tests/ui/associated-consts/associated-const-impl-wrong-type.rs create mode 100644 tests/ui/associated-consts/associated-const-impl-wrong-type.stderr create mode 100644 tests/ui/associated-consts/associated-const-in-global-const.rs create mode 100644 tests/ui/associated-consts/associated-const-in-trait.rs create mode 100644 tests/ui/associated-consts/associated-const-in-trait.stderr create mode 100644 tests/ui/associated-consts/associated-const-inherent-impl.rs create mode 100644 tests/ui/associated-consts/associated-const-marks-live-code.rs create mode 100644 tests/ui/associated-consts/associated-const-match-patterns.rs create mode 100644 tests/ui/associated-consts/associated-const-no-item.rs create mode 100644 tests/ui/associated-consts/associated-const-no-item.stderr create mode 100644 tests/ui/associated-consts/associated-const-outer-ty-refs.rs create mode 100644 tests/ui/associated-consts/associated-const-overwrite-default.rs create mode 100644 tests/ui/associated-consts/associated-const-private-impl.rs create mode 100644 tests/ui/associated-consts/associated-const-private-impl.stderr create mode 100644 tests/ui/associated-consts/associated-const-public-impl.rs create mode 100644 tests/ui/associated-consts/associated-const-range-match-patterns.rs create mode 100644 tests/ui/associated-consts/associated-const-resolution-order.rs create mode 100644 tests/ui/associated-consts/associated-const-self-type.rs create mode 100644 tests/ui/associated-consts/associated-const-trait-bound.rs create mode 100644 tests/ui/associated-consts/associated-const-type-parameter-arms.rs create mode 100644 tests/ui/associated-consts/associated-const-type-parameter-arms.stderr create mode 100644 tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs create mode 100644 tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr create mode 100644 tests/ui/associated-consts/associated-const-type-parameter-arrays.rs create mode 100644 tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr create mode 100644 tests/ui/associated-consts/associated-const-type-parameters.rs create mode 100644 tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs create mode 100644 tests/ui/associated-consts/associated-const-use-default.rs create mode 100644 tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs create mode 100644 tests/ui/associated-consts/associated-const.rs create mode 100644 tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs create mode 100644 tests/ui/associated-consts/auxiliary/empty-struct.rs create mode 100644 tests/ui/associated-consts/defaults-cyclic-fail.rs create mode 100644 tests/ui/associated-consts/defaults-cyclic-fail.stderr create mode 100644 tests/ui/associated-consts/defaults-cyclic-pass.rs create mode 100644 tests/ui/associated-consts/defaults-not-assumed-fail.rs create mode 100644 tests/ui/associated-consts/defaults-not-assumed-fail.stderr create mode 100644 tests/ui/associated-consts/defaults-not-assumed-pass.rs create mode 100644 tests/ui/associated-consts/issue-102335-const.rs create mode 100644 tests/ui/associated-consts/issue-102335-const.stderr create mode 100644 tests/ui/associated-consts/issue-105330.rs create mode 100644 tests/ui/associated-consts/issue-105330.stderr create mode 100644 tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs create mode 100644 tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr create mode 100644 tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs create mode 100644 tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr create mode 100644 tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs create mode 100644 tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr create mode 100644 tests/ui/associated-consts/issue-47814.rs create mode 100644 tests/ui/associated-consts/issue-47814.stderr create mode 100644 tests/ui/associated-consts/issue-58022.rs create mode 100644 tests/ui/associated-consts/issue-58022.stderr create mode 100644 tests/ui/associated-consts/issue-63496.rs create mode 100644 tests/ui/associated-consts/issue-63496.stderr create mode 100644 tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr create mode 100644 tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr create mode 100644 tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr create mode 100644 tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs create mode 100644 tests/ui/associated-consts/issue-88599-ref-self.rs create mode 100644 tests/ui/associated-consts/issue-93775.rs create mode 100644 tests/ui/associated-consts/issue-93835.rs create mode 100644 tests/ui/associated-consts/issue-93835.stderr create mode 100644 tests/ui/associated-consts/mismatched_impl_ty_1.rs create mode 100644 tests/ui/associated-consts/mismatched_impl_ty_2.rs create mode 100644 tests/ui/associated-consts/mismatched_impl_ty_3.rs create mode 100644 tests/ui/associated-consts/shadowed-const.rs create mode 100644 tests/ui/associated-consts/shadowed-const.stderr create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-no-body.rs create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-private.rs create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-private.stderr create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-unstable.rs create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr create mode 100644 tests/ui/associated-inherent-types/assoc-inherent-use.rs create mode 100644 tests/ui/associated-inherent-types/auxiliary/assoc-inherent-unstable.rs create mode 100644 tests/ui/associated-inherent-types/issue-104260.rs create mode 100644 tests/ui/associated-inherent-types/normalize-projection-0.rs create mode 100644 tests/ui/associated-inherent-types/normalize-projection-1.rs create mode 100644 tests/ui/associated-inherent-types/struct-generics.rs create mode 100644 tests/ui/associated-inherent-types/style.rs create mode 100644 tests/ui/associated-inherent-types/style.stderr create mode 100644 tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed create mode 100644 tests/ui/associated-item/ambiguous-associated-type-with-generics.rs create mode 100644 tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr create mode 100644 tests/ui/associated-item/associated-item-duplicate-bounds.rs create mode 100644 tests/ui/associated-item/associated-item-duplicate-bounds.stderr create mode 100644 tests/ui/associated-item/associated-item-duplicate-names-2.rs create mode 100644 tests/ui/associated-item/associated-item-duplicate-names-2.stderr create mode 100644 tests/ui/associated-item/associated-item-duplicate-names-3.rs create mode 100644 tests/ui/associated-item/associated-item-duplicate-names-3.stderr create mode 100644 tests/ui/associated-item/associated-item-duplicate-names.rs create mode 100644 tests/ui/associated-item/associated-item-duplicate-names.stderr create mode 100644 tests/ui/associated-item/associated-item-enum.rs create mode 100644 tests/ui/associated-item/associated-item-enum.stderr create mode 100644 tests/ui/associated-item/associated-item-two-bounds.rs create mode 100644 tests/ui/associated-item/impl-duplicate-methods.rs create mode 100644 tests/ui/associated-item/impl-duplicate-methods.stderr create mode 100644 tests/ui/associated-item/issue-105449.rs create mode 100644 tests/ui/associated-item/issue-48027.rs create mode 100644 tests/ui/associated-item/issue-48027.stderr create mode 100644 tests/ui/associated-item/issue-87638.fixed create mode 100644 tests/ui/associated-item/issue-87638.rs create mode 100644 tests/ui/associated-item/issue-87638.stderr create mode 100644 tests/ui/associated-path-shl.rs create mode 100644 tests/ui/associated-path-shl.stderr create mode 100644 tests/ui/associated-type-bounds/ambiguous-associated-type.rs create mode 100644 tests/ui/associated-type-bounds/ambiguous-associated-type2.rs create mode 100644 tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr create mode 100644 tests/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs create mode 100644 tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs create mode 100644 tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr create mode 100644 tests/ui/associated-type-bounds/associated-item-through-where-clause.rs create mode 100644 tests/ui/associated-type-bounds/auxiliary/fn-aux.rs create mode 100644 tests/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs create mode 100644 tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs create mode 100644 tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr create mode 100644 tests/ui/associated-type-bounds/binder-on-bound.rs create mode 100644 tests/ui/associated-type-bounds/binder-on-bound.stderr create mode 100644 tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs create mode 100644 tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr create mode 100644 tests/ui/associated-type-bounds/const-projection-err.gce.stderr create mode 100644 tests/ui/associated-type-bounds/const-projection-err.rs create mode 100644 tests/ui/associated-type-bounds/const-projection-err.stock.stderr create mode 100644 tests/ui/associated-type-bounds/duplicate.rs create mode 100644 tests/ui/associated-type-bounds/duplicate.stderr create mode 100644 tests/ui/associated-type-bounds/dyn-impl-trait-type.rs create mode 100644 tests/ui/associated-type-bounds/dyn-rpit-and-let.rs create mode 100644 tests/ui/associated-type-bounds/elision.rs create mode 100644 tests/ui/associated-type-bounds/elision.stderr create mode 100644 tests/ui/associated-type-bounds/entails-sized-object-safety.rs create mode 100644 tests/ui/associated-type-bounds/enum-bounds.rs create mode 100644 tests/ui/associated-type-bounds/fn-apit.rs create mode 100644 tests/ui/associated-type-bounds/fn-aux.rs create mode 100644 tests/ui/associated-type-bounds/fn-dyn-apit.rs create mode 100644 tests/ui/associated-type-bounds/fn-inline.rs create mode 100644 tests/ui/associated-type-bounds/fn-where.rs create mode 100644 tests/ui/associated-type-bounds/fn-wrap-apit.rs create mode 100644 tests/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs create mode 100644 tests/ui/associated-type-bounds/hrtb.rs create mode 100644 tests/ui/associated-type-bounds/implied-region-constraints.rs create mode 100644 tests/ui/associated-type-bounds/implied-region-constraints.stderr create mode 100644 tests/ui/associated-type-bounds/inside-adt.rs create mode 100644 tests/ui/associated-type-bounds/inside-adt.stderr create mode 100644 tests/ui/associated-type-bounds/issue-102335-ty.rs create mode 100644 tests/ui/associated-type-bounds/issue-102335-ty.stderr create mode 100644 tests/ui/associated-type-bounds/issue-61752.rs create mode 100644 tests/ui/associated-type-bounds/issue-70292.rs create mode 100644 tests/ui/associated-type-bounds/issue-71443-1.rs create mode 100644 tests/ui/associated-type-bounds/issue-71443-1.stderr create mode 100644 tests/ui/associated-type-bounds/issue-71443-2.rs create mode 100644 tests/ui/associated-type-bounds/issue-73818.rs create mode 100644 tests/ui/associated-type-bounds/issue-79949.rs create mode 100644 tests/ui/associated-type-bounds/issue-81193.rs create mode 100644 tests/ui/associated-type-bounds/issue-83017.rs create mode 100644 tests/ui/associated-type-bounds/issue-99828.rs create mode 100644 tests/ui/associated-type-bounds/issue-99828.stderr create mode 100644 tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs create mode 100644 tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr create mode 100644 tests/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs create mode 100644 tests/ui/associated-type-bounds/rpit.rs create mode 100644 tests/ui/associated-type-bounds/struct-bounds.rs create mode 100644 tests/ui/associated-type-bounds/supertrait-referencing-self.rs create mode 100644 tests/ui/associated-type-bounds/supertrait-referencing.rs create mode 100644 tests/ui/associated-type-bounds/supertrait-where-referencing-self.rs create mode 100644 tests/ui/associated-type-bounds/trait-alias-impl-trait.rs create mode 100644 tests/ui/associated-type-bounds/trait-params.rs create mode 100644 tests/ui/associated-type-bounds/traits-assoc-anonymized.rs create mode 100644 tests/ui/associated-type-bounds/traits-assoc-type-macros.rs create mode 100644 tests/ui/associated-type-bounds/type-alias.rs create mode 100644 tests/ui/associated-type-bounds/type-alias.stderr create mode 100644 tests/ui/associated-type-bounds/union-bounds.rs create mode 100644 tests/ui/associated-types/associate-type-bound-normalization.rs create mode 100644 tests/ui/associated-types/associated-item-long-paths.rs create mode 100644 tests/ui/associated-types/associated-type-destructuring-assignment.rs create mode 100644 tests/ui/associated-types/associated-type-macro.rs create mode 100644 tests/ui/associated-types/associated-type-macro.stderr create mode 100644 tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.rs create mode 100644 tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr create mode 100644 tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs create mode 100644 tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr create mode 100644 tests/ui/associated-types/associated-type-projection-from-supertrait.rs create mode 100644 tests/ui/associated-types/associated-type-projection-from-supertrait.stderr create mode 100644 tests/ui/associated-types/associated-type-struct-construction.rs create mode 100644 tests/ui/associated-types/associated-type-tuple-struct-construction.rs create mode 100644 tests/ui/associated-types/associated-type-tuple-struct-construction.stderr create mode 100644 tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs create mode 100644 tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr create mode 100644 tests/ui/associated-types/associated-types-basic.rs create mode 100644 tests/ui/associated-types/associated-types-binding-in-trait.rs create mode 100644 tests/ui/associated-types/associated-types-binding-in-where-clause.rs create mode 100644 tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs create mode 100644 tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr create mode 100644 tests/ui/associated-types/associated-types-bound-ambiguity.rs create mode 100644 tests/ui/associated-types/associated-types-bound-failure.fixed create mode 100644 tests/ui/associated-types/associated-types-bound-failure.rs create mode 100644 tests/ui/associated-types/associated-types-bound-failure.stderr create mode 100644 tests/ui/associated-types/associated-types-bound.rs create mode 100644 tests/ui/associated-types/associated-types-cc.rs create mode 100644 tests/ui/associated-types/associated-types-coherence-failure.rs create mode 100644 tests/ui/associated-types/associated-types-coherence-failure.stderr create mode 100644 tests/ui/associated-types/associated-types-conditional-dispatch.rs create mode 100644 tests/ui/associated-types/associated-types-constant-type.rs create mode 100644 tests/ui/associated-types/associated-types-doubleendediterator-object.rs create mode 100644 tests/ui/associated-types/associated-types-duplicate-binding-in-env-hrtb.rs create mode 100644 tests/ui/associated-types/associated-types-duplicate-binding-in-env.rs create mode 100644 tests/ui/associated-types/associated-types-enum-field-named.rs create mode 100644 tests/ui/associated-types/associated-types-enum-field-numbered.rs create mode 100644 tests/ui/associated-types/associated-types-eq-1.rs create mode 100644 tests/ui/associated-types/associated-types-eq-1.stderr create mode 100644 tests/ui/associated-types/associated-types-eq-2.rs create mode 100644 tests/ui/associated-types/associated-types-eq-2.stderr create mode 100644 tests/ui/associated-types/associated-types-eq-3.rs create mode 100644 tests/ui/associated-types/associated-types-eq-3.stderr create mode 100644 tests/ui/associated-types/associated-types-eq-expr-path.rs create mode 100644 tests/ui/associated-types/associated-types-eq-expr-path.stderr create mode 100644 tests/ui/associated-types/associated-types-eq-hr.rs create mode 100644 tests/ui/associated-types/associated-types-eq-hr.stderr create mode 100644 tests/ui/associated-types/associated-types-eq-obj.rs create mode 100644 tests/ui/associated-types/associated-types-for-unimpl-trait.fixed create mode 100644 tests/ui/associated-types/associated-types-for-unimpl-trait.rs create mode 100644 tests/ui/associated-types/associated-types-for-unimpl-trait.stderr create mode 100644 tests/ui/associated-types/associated-types-from-supertrait.rs create mode 100644 tests/ui/associated-types/associated-types-impl-redirect.rs create mode 100644 tests/ui/associated-types/associated-types-in-ambiguous-context.rs create mode 100644 tests/ui/associated-types/associated-types-in-ambiguous-context.stderr create mode 100644 tests/ui/associated-types/associated-types-in-bound-type-arg.rs create mode 100644 tests/ui/associated-types/associated-types-in-default-method.rs create mode 100644 tests/ui/associated-types/associated-types-in-fn.rs create mode 100644 tests/ui/associated-types/associated-types-in-impl-generics.rs create mode 100644 tests/ui/associated-types/associated-types-in-inherent-method.rs create mode 100644 tests/ui/associated-types/associated-types-incomplete-object.rs create mode 100644 tests/ui/associated-types/associated-types-incomplete-object.stderr create mode 100644 tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs create mode 100644 tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr create mode 100644 tests/ui/associated-types/associated-types-issue-17359.rs create mode 100644 tests/ui/associated-types/associated-types-issue-17359.stderr create mode 100644 tests/ui/associated-types/associated-types-issue-20220.rs create mode 100644 tests/ui/associated-types/associated-types-issue-20346.rs create mode 100644 tests/ui/associated-types/associated-types-issue-20346.stderr create mode 100644 tests/ui/associated-types/associated-types-issue-20371.rs create mode 100644 tests/ui/associated-types/associated-types-issue-21212.rs create mode 100644 tests/ui/associated-types/associated-types-iterator-binding.rs create mode 100644 tests/ui/associated-types/associated-types-method.rs create mode 100644 tests/ui/associated-types/associated-types-multiple-types-one-trait.rs create mode 100644 tests/ui/associated-types/associated-types-multiple-types-one-trait.stderr create mode 100644 tests/ui/associated-types/associated-types-nested-projections.rs create mode 100644 tests/ui/associated-types/associated-types-no-suitable-bound.rs create mode 100644 tests/ui/associated-types/associated-types-no-suitable-bound.stderr create mode 100644 tests/ui/associated-types/associated-types-no-suitable-supertrait-2.rs create mode 100644 tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr create mode 100644 tests/ui/associated-types/associated-types-no-suitable-supertrait.rs create mode 100644 tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr create mode 100644 tests/ui/associated-types/associated-types-normalize-in-bounds-binding.rs create mode 100644 tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs create mode 100644 tests/ui/associated-types/associated-types-normalize-in-bounds.rs create mode 100644 tests/ui/associated-types/associated-types-normalize-unifield-struct.rs create mode 100644 tests/ui/associated-types/associated-types-outlives.rs create mode 100644 tests/ui/associated-types/associated-types-outlives.stderr create mode 100644 tests/ui/associated-types/associated-types-overridden-binding-2.rs create mode 100644 tests/ui/associated-types/associated-types-overridden-binding-2.stderr create mode 100644 tests/ui/associated-types/associated-types-overridden-binding.rs create mode 100644 tests/ui/associated-types/associated-types-overridden-binding.stderr create mode 100644 tests/ui/associated-types/associated-types-overridden-default.rs create mode 100644 tests/ui/associated-types/associated-types-path-1.rs create mode 100644 tests/ui/associated-types/associated-types-path-1.stderr create mode 100644 tests/ui/associated-types/associated-types-path-2.rs create mode 100644 tests/ui/associated-types/associated-types-path-2.stderr create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.fixed create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.fixed create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs create mode 100644 tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr create mode 100644 tests/ui/associated-types/associated-types-project-from-type-param-via-bound-in-where.rs create mode 100644 tests/ui/associated-types/associated-types-projection-bound-ambiguity.rs create mode 100644 tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs create mode 100644 tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs create mode 100644 tests/ui/associated-types/associated-types-projection-in-object-type.rs create mode 100644 tests/ui/associated-types/associated-types-projection-in-supertrait.rs create mode 100644 tests/ui/associated-types/associated-types-projection-in-where-clause.rs create mode 100644 tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed create mode 100644 tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs create mode 100644 tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr create mode 100644 tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs create mode 100644 tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs create mode 100644 tests/ui/associated-types/associated-types-ref-from-struct.rs create mode 100644 tests/ui/associated-types/associated-types-ref-in-struct-literal.rs create mode 100644 tests/ui/associated-types/associated-types-region-erasure-issue-20582.rs create mode 100644 tests/ui/associated-types/associated-types-resolve-lifetime.rs create mode 100644 tests/ui/associated-types/associated-types-return.rs create mode 100644 tests/ui/associated-types/associated-types-simple.rs create mode 100644 tests/ui/associated-types/associated-types-stream.rs create mode 100644 tests/ui/associated-types/associated-types-struct-field-named.rs create mode 100644 tests/ui/associated-types/associated-types-struct-field-numbered.rs create mode 100644 tests/ui/associated-types/associated-types-subtyping-1.rs create mode 100644 tests/ui/associated-types/associated-types-subtyping-1.stderr create mode 100644 tests/ui/associated-types/associated-types-sugar-path.rs create mode 100644 tests/ui/associated-types/associated-types-unconstrained.rs create mode 100644 tests/ui/associated-types/associated-types-unconstrained.stderr create mode 100644 tests/ui/associated-types/associated-types-unsized.fixed create mode 100644 tests/ui/associated-types/associated-types-unsized.rs create mode 100644 tests/ui/associated-types/associated-types-unsized.stderr create mode 100644 tests/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs create mode 100644 tests/ui/associated-types/auxiliary/associated-types-cc-lib.rs create mode 100644 tests/ui/associated-types/bound-lifetime-constrained.clause.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-constrained.func.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-constrained.object.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-constrained.rs create mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-binding-only.rs create mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.rs create mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.sig.stderr create mode 100644 tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr create mode 100644 tests/ui/associated-types/cache/chrono-scan.rs create mode 100644 tests/ui/associated-types/cache/elision.rs create mode 100644 tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr create mode 100644 tests/ui/associated-types/cache/project-fn-ret-contravariant.rs create mode 100644 tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr create mode 100644 tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr create mode 100644 tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr create mode 100644 tests/ui/associated-types/cache/project-fn-ret-invariant.rs create mode 100644 tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr create mode 100644 tests/ui/associated-types/default-associated-types.rs create mode 100644 tests/ui/associated-types/defaults-cyclic-fail-1.rs create mode 100644 tests/ui/associated-types/defaults-cyclic-fail-1.stderr create mode 100644 tests/ui/associated-types/defaults-cyclic-fail-2.rs create mode 100644 tests/ui/associated-types/defaults-cyclic-fail-2.stderr create mode 100644 tests/ui/associated-types/defaults-cyclic-pass-1.rs create mode 100644 tests/ui/associated-types/defaults-cyclic-pass-2.rs create mode 100644 tests/ui/associated-types/defaults-in-other-trait-items-pass.rs create mode 100644 tests/ui/associated-types/defaults-in-other-trait-items.rs create mode 100644 tests/ui/associated-types/defaults-in-other-trait-items.stderr create mode 100644 tests/ui/associated-types/defaults-mixed.rs create mode 100644 tests/ui/associated-types/defaults-mixed.stderr create mode 100644 tests/ui/associated-types/defaults-specialization.rs create mode 100644 tests/ui/associated-types/defaults-specialization.stderr create mode 100644 tests/ui/associated-types/defaults-suitability.rs create mode 100644 tests/ui/associated-types/defaults-suitability.stderr create mode 100644 tests/ui/associated-types/defaults-unsound-62211-1.rs create mode 100644 tests/ui/associated-types/defaults-unsound-62211-1.stderr create mode 100644 tests/ui/associated-types/defaults-unsound-62211-2.rs create mode 100644 tests/ui/associated-types/defaults-unsound-62211-2.stderr create mode 100644 tests/ui/associated-types/defaults-wf.rs create mode 100644 tests/ui/associated-types/defaults-wf.stderr create mode 100644 tests/ui/associated-types/higher-ranked-projection.bad.stderr create mode 100644 tests/ui/associated-types/higher-ranked-projection.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-1.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-1.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-2.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-2.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-object.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-object.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-1.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-1.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-2.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-2.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-3.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-3.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-4.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-4.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-5.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-5.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-6.rs create mode 100644 tests/ui/associated-types/hr-associated-type-bound-param-6.stderr create mode 100644 tests/ui/associated-types/hr-associated-type-projection-1.rs create mode 100644 tests/ui/associated-types/hr-associated-type-projection-1.stderr create mode 100644 tests/ui/associated-types/impl-trait-return-missing-constraint.rs create mode 100644 tests/ui/associated-types/impl-trait-return-missing-constraint.stderr create mode 100644 tests/ui/associated-types/impl-wf-cycle-1.rs create mode 100644 tests/ui/associated-types/impl-wf-cycle-1.stderr create mode 100644 tests/ui/associated-types/impl-wf-cycle-2.rs create mode 100644 tests/ui/associated-types/impl-wf-cycle-2.stderr create mode 100644 tests/ui/associated-types/issue-18655.rs create mode 100644 tests/ui/associated-types/issue-19081.rs create mode 100644 tests/ui/associated-types/issue-19883.rs create mode 100644 tests/ui/associated-types/issue-19883.stderr create mode 100644 tests/ui/associated-types/issue-20005.rs create mode 100644 tests/ui/associated-types/issue-20005.stderr create mode 100644 tests/ui/associated-types/issue-20825-2.rs create mode 100644 tests/ui/associated-types/issue-20825.rs create mode 100644 tests/ui/associated-types/issue-20825.stderr create mode 100644 tests/ui/associated-types/issue-21363.rs create mode 100644 tests/ui/associated-types/issue-21726.rs create mode 100644 tests/ui/associated-types/issue-22037.rs create mode 100644 tests/ui/associated-types/issue-22037.stderr create mode 100644 tests/ui/associated-types/issue-22066.rs create mode 100644 tests/ui/associated-types/issue-22560.rs create mode 100644 tests/ui/associated-types/issue-22560.stderr create mode 100644 tests/ui/associated-types/issue-22828.rs create mode 100644 tests/ui/associated-types/issue-23208.rs create mode 100644 tests/ui/associated-types/issue-23595-1.rs create mode 100644 tests/ui/associated-types/issue-23595-1.stderr create mode 100644 tests/ui/associated-types/issue-23595-2.rs create mode 100644 tests/ui/associated-types/issue-23595-2.stderr create mode 100644 tests/ui/associated-types/issue-24159.rs create mode 100644 tests/ui/associated-types/issue-24204.rs create mode 100644 tests/ui/associated-types/issue-24338.rs create mode 100644 tests/ui/associated-types/issue-25339.rs create mode 100644 tests/ui/associated-types/issue-25700-1.rs create mode 100644 tests/ui/associated-types/issue-25700-2.rs create mode 100644 tests/ui/associated-types/issue-25700.rs create mode 100644 tests/ui/associated-types/issue-25700.stderr create mode 100644 tests/ui/associated-types/issue-26681.rs create mode 100644 tests/ui/associated-types/issue-26681.stderr create mode 100644 tests/ui/associated-types/issue-27675-unchecked-bounds.rs create mode 100644 tests/ui/associated-types/issue-27675-unchecked-bounds.stderr create mode 100644 tests/ui/associated-types/issue-28871.rs create mode 100644 tests/ui/associated-types/issue-31597.rs create mode 100644 tests/ui/associated-types/issue-32350.rs create mode 100644 tests/ui/associated-types/issue-36499.rs create mode 100644 tests/ui/associated-types/issue-36499.stderr create mode 100644 tests/ui/associated-types/issue-37808.rs create mode 100644 tests/ui/associated-types/issue-37883.rs create mode 100644 tests/ui/associated-types/issue-38917.rs create mode 100644 tests/ui/associated-types/issue-39532.rs create mode 100644 tests/ui/associated-types/issue-40093.rs create mode 100644 tests/ui/associated-types/issue-41868.rs create mode 100644 tests/ui/associated-types/issue-43475.rs create mode 100644 tests/ui/associated-types/issue-43784-associated-type.rs create mode 100644 tests/ui/associated-types/issue-43784-associated-type.stderr create mode 100644 tests/ui/associated-types/issue-43924.rs create mode 100644 tests/ui/associated-types/issue-43924.stderr create mode 100644 tests/ui/associated-types/issue-44153.rs create mode 100644 tests/ui/associated-types/issue-44153.stderr create mode 100644 tests/ui/associated-types/issue-47139-1.rs create mode 100644 tests/ui/associated-types/issue-47139-2.rs create mode 100644 tests/ui/associated-types/issue-47385.rs create mode 100644 tests/ui/associated-types/issue-47814.rs create mode 100644 tests/ui/associated-types/issue-47814.stderr create mode 100644 tests/ui/associated-types/issue-48010.rs create mode 100644 tests/ui/associated-types/issue-48551.rs create mode 100644 tests/ui/associated-types/issue-50301.rs create mode 100644 tests/ui/associated-types/issue-54108.rs create mode 100644 tests/ui/associated-types/issue-54108.stderr create mode 100644 tests/ui/associated-types/issue-54182-1.rs create mode 100644 tests/ui/associated-types/issue-54182-2.rs create mode 100644 tests/ui/associated-types/issue-54467.rs create mode 100644 tests/ui/associated-types/issue-55846.rs create mode 100644 tests/ui/associated-types/issue-59324.rs create mode 100644 tests/ui/associated-types/issue-59324.stderr create mode 100644 tests/ui/associated-types/issue-62200.rs create mode 100644 tests/ui/associated-types/issue-62200.stderr create mode 100644 tests/ui/associated-types/issue-63591.rs create mode 100644 tests/ui/associated-types/issue-63593.rs create mode 100644 tests/ui/associated-types/issue-63593.stderr create mode 100644 tests/ui/associated-types/issue-64848.rs create mode 100644 tests/ui/associated-types/issue-64855-2.rs create mode 100644 tests/ui/associated-types/issue-64855.rs create mode 100644 tests/ui/associated-types/issue-64855.stderr create mode 100644 tests/ui/associated-types/issue-65774-1.rs create mode 100644 tests/ui/associated-types/issue-65774-1.stderr create mode 100644 tests/ui/associated-types/issue-65774-2.rs create mode 100644 tests/ui/associated-types/issue-65774-2.stderr create mode 100644 tests/ui/associated-types/issue-65934.rs create mode 100644 tests/ui/associated-types/issue-67684.rs create mode 100644 tests/ui/associated-types/issue-69398.rs create mode 100644 tests/ui/associated-types/issue-71113.rs create mode 100644 tests/ui/associated-types/issue-72806.rs create mode 100644 tests/ui/associated-types/issue-72806.stderr create mode 100644 tests/ui/associated-types/issue-76179.rs create mode 100644 tests/ui/associated-types/issue-82079.rs create mode 100644 tests/ui/associated-types/issue-85103.rs create mode 100644 tests/ui/associated-types/issue-85103.stderr create mode 100644 tests/ui/associated-types/issue-87261.rs create mode 100644 tests/ui/associated-types/issue-87261.stderr create mode 100644 tests/ui/associated-types/issue-88856.rs create mode 100644 tests/ui/associated-types/issue-91069.rs create mode 100644 tests/ui/associated-types/issue-91231.rs create mode 100644 tests/ui/associated-types/issue-91234.rs create mode 100644 tests/ui/associated-types/missing-associated-types.rs create mode 100644 tests/ui/associated-types/missing-associated-types.stderr create mode 100644 tests/ui/associated-types/normalization-debruijn-1.rs create mode 100644 tests/ui/associated-types/normalization-debruijn-2.rs create mode 100644 tests/ui/associated-types/normalization-debruijn-3.rs create mode 100644 tests/ui/associated-types/normalization-generality-2.rs create mode 100644 tests/ui/associated-types/normalization-generality.rs create mode 100644 tests/ui/associated-types/normalization-probe-cycle.rs create mode 100644 tests/ui/associated-types/normalize-cycle-in-eval-no-region.rs create mode 100644 tests/ui/associated-types/normalize-cycle-in-eval.rs create mode 100644 tests/ui/associated-types/object-method-numbering.rs create mode 100644 tests/ui/associated-types/object-normalization.rs create mode 100644 tests/ui/associated-types/param-env-normalize-cycle.rs create mode 100644 tests/ui/associated-types/point-at-type-on-obligation-failure-2.rs create mode 100644 tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr create mode 100644 tests/ui/associated-types/point-at-type-on-obligation-failure.rs create mode 100644 tests/ui/associated-types/point-at-type-on-obligation-failure.stderr create mode 100644 tests/ui/associated-types/project-defer-unification.rs create mode 100644 tests/ui/associated-types/project-recursion-limit-non-fatal.rs create mode 100644 tests/ui/associated-types/substs-ppaux.normal.stderr create mode 100644 tests/ui/associated-types/substs-ppaux.rs create mode 100644 tests/ui/associated-types/substs-ppaux.verbose.stderr create mode 100644 tests/ui/associated-types/trait-with-supertraits-needing-sized-self.rs create mode 100644 tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr create mode 100644 tests/ui/associated-types/wf-cycle-2.rs create mode 100644 tests/ui/associated-types/wf-cycle.rs create mode 100644 tests/ui/async-await/argument-patterns.rs create mode 100644 tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs create mode 100644 tests/ui/async-await/async-await-let-else.drop-tracking.stderr create mode 100644 tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr create mode 100644 tests/ui/async-await/async-await-let-else.rs create mode 100644 tests/ui/async-await/async-await.rs create mode 100644 tests/ui/async-await/async-block-control-flow-static-semantics.rs create mode 100644 tests/ui/async-await/async-block-control-flow-static-semantics.stderr create mode 100644 tests/ui/async-await/async-borrowck-escaping-block-error.fixed create mode 100644 tests/ui/async-await/async-borrowck-escaping-block-error.rs create mode 100644 tests/ui/async-await/async-borrowck-escaping-block-error.stderr create mode 100644 tests/ui/async-await/async-borrowck-escaping-closure-error.rs create mode 100644 tests/ui/async-await/async-borrowck-escaping-closure-error.stderr create mode 100644 tests/ui/async-await/async-closure-matches-expr.rs create mode 100644 tests/ui/async-await/async-closure.rs create mode 100644 tests/ui/async-await/async-error-span.rs create mode 100644 tests/ui/async-await/async-error-span.stderr create mode 100644 tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs create mode 100644 tests/ui/async-await/async-fn-nonsend.rs create mode 100644 tests/ui/async-await/async-fn-nonsend.stderr create mode 100644 tests/ui/async-await/async-fn-path-elision.rs create mode 100644 tests/ui/async-await/async-fn-path-elision.stderr create mode 100644 tests/ui/async-await/async-fn-send-uses-nonsend.rs create mode 100644 tests/ui/async-await/async-fn-size-moved-locals.rs create mode 100644 tests/ui/async-await/async-fn-size-uninit-locals.rs create mode 100644 tests/ui/async-await/async-fn-size.rs create mode 100644 tests/ui/async-await/async-is-unwindsafe.rs create mode 100644 tests/ui/async-await/async-is-unwindsafe.stderr create mode 100644 tests/ui/async-await/async-matches-expr.rs create mode 100644 tests/ui/async-await/async-trait-fn.rs create mode 100644 tests/ui/async-await/async-trait-fn.stderr create mode 100644 tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr create mode 100644 tests/ui/async-await/async-unsafe-fn-call-in-safe.rs create mode 100644 tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr create mode 100644 tests/ui/async-await/async-with-closure.rs create mode 100644 tests/ui/async-await/auxiliary/arc_wake.rs create mode 100644 tests/ui/async-await/auxiliary/issue-107036.rs create mode 100644 tests/ui/async-await/auxiliary/issue-72470-lib.rs create mode 100644 tests/ui/async-await/await-into-future.rs create mode 100644 tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs create mode 100644 tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr create mode 100644 tests/ui/async-await/await-keyword/2015-edition-warning.fixed create mode 100644 tests/ui/async-await/await-keyword/2015-edition-warning.rs create mode 100644 tests/ui/async-await/await-keyword/2015-edition-warning.stderr create mode 100644 tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs create mode 100644 tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr create mode 100644 tests/ui/async-await/await-keyword/2018-edition-error.rs create mode 100644 tests/ui/async-await/await-keyword/2018-edition-error.stderr create mode 100644 tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs create mode 100644 tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr create mode 100644 tests/ui/async-await/await-keyword/post_expansion_error.rs create mode 100644 tests/ui/async-await/await-keyword/post_expansion_error.stderr create mode 100644 tests/ui/async-await/await-sequence.rs create mode 100644 tests/ui/async-await/await-unsize.rs create mode 100644 tests/ui/async-await/bound-normalization.rs create mode 100644 tests/ui/async-await/conditional-and-guaranteed-initialization.rs create mode 100644 tests/ui/async-await/default-struct-update.rs create mode 100644 tests/ui/async-await/dont-print-desugared-async.rs create mode 100644 tests/ui/async-await/dont-print-desugared-async.stderr create mode 100644 tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs create mode 100644 tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr create mode 100644 tests/ui/async-await/dont-suggest-missing-await.rs create mode 100644 tests/ui/async-await/dont-suggest-missing-await.stderr create mode 100644 tests/ui/async-await/drop-and-assign.rs create mode 100644 tests/ui/async-await/drop-order/auxiliary/arc_wake.rs create mode 100644 tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs create mode 100644 tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs create mode 100644 tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs create mode 100644 tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs create mode 100644 tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs create mode 100644 tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr create mode 100644 tests/ui/async-await/drop-order/drop-order-when-cancelled.rs create mode 100644 tests/ui/async-await/drop-track-bad-field-in-fru.rs create mode 100644 tests/ui/async-await/drop-track-bad-field-in-fru.stderr create mode 100644 tests/ui/async-await/drop-track-field-assign-nonsend.rs create mode 100644 tests/ui/async-await/drop-track-field-assign-nonsend.stderr create mode 100644 tests/ui/async-await/drop-track-field-assign.rs create mode 100644 tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs create mode 100644 tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr create mode 100644 tests/ui/async-await/edition-deny-async-fns-2015.rs create mode 100644 tests/ui/async-await/edition-deny-async-fns-2015.stderr create mode 100644 tests/ui/async-await/expansion-in-attrs.rs create mode 100644 tests/ui/async-await/feature-async-closure.rs create mode 100644 tests/ui/async-await/feature-async-closure.stderr create mode 100644 tests/ui/async-await/feature-gate-async_fn_in_trait.rs create mode 100644 tests/ui/async-await/feature-gate-async_fn_in_trait.stderr create mode 100644 tests/ui/async-await/feature-self-return-type.rs create mode 100644 tests/ui/async-await/feature-self-return-type.stderr create mode 100644 tests/ui/async-await/futures-api.rs create mode 100644 tests/ui/async-await/generator-desc.rs create mode 100644 tests/ui/async-await/generator-desc.stderr create mode 100644 tests/ui/async-await/generator-not-future.rs create mode 100644 tests/ui/async-await/generator-not-future.stderr create mode 100644 tests/ui/async-await/generics-and-bounds.rs create mode 100644 tests/ui/async-await/in-trait/async-associated-types.rs create mode 100644 tests/ui/async-await/in-trait/async-associated-types2.rs create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed.rs create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-extra.rs create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-manual.rs create mode 100644 tests/ui/async-await/in-trait/async-example-desugared-manual.stderr create mode 100644 tests/ui/async-await/in-trait/async-example-desugared.rs create mode 100644 tests/ui/async-await/in-trait/async-example.rs create mode 100644 tests/ui/async-await/in-trait/async-generics-and-bounds.rs create mode 100644 tests/ui/async-await/in-trait/async-generics-and-bounds.stderr create mode 100644 tests/ui/async-await/in-trait/async-generics.rs create mode 100644 tests/ui/async-await/in-trait/async-generics.stderr create mode 100644 tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs create mode 100644 tests/ui/async-await/in-trait/async-lifetimes.rs create mode 100644 tests/ui/async-await/in-trait/async-recursive-generic.rs create mode 100644 tests/ui/async-await/in-trait/async-recursive-generic.stderr create mode 100644 tests/ui/async-await/in-trait/async-recursive.rs create mode 100644 tests/ui/async-await/in-trait/async-recursive.stderr create mode 100644 tests/ui/async-await/in-trait/bad-signatures.rs create mode 100644 tests/ui/async-await/in-trait/bad-signatures.stderr create mode 100644 tests/ui/async-await/in-trait/early-bound-1.rs create mode 100644 tests/ui/async-await/in-trait/early-bound-2.rs create mode 100644 tests/ui/async-await/in-trait/fn-not-async-err.rs create mode 100644 tests/ui/async-await/in-trait/fn-not-async-err.stderr create mode 100644 tests/ui/async-await/in-trait/fn-not-async-err2.rs create mode 100644 tests/ui/async-await/in-trait/fn-not-async-err2.stderr create mode 100644 tests/ui/async-await/in-trait/implied-bounds.rs create mode 100644 tests/ui/async-await/in-trait/issue-102138.rs create mode 100644 tests/ui/async-await/in-trait/issue-102219.rs create mode 100644 tests/ui/async-await/in-trait/issue-102310.rs create mode 100644 tests/ui/async-await/in-trait/issue-104678.rs create mode 100644 tests/ui/async-await/in-trait/lifetime-mismatch.rs create mode 100644 tests/ui/async-await/in-trait/lifetime-mismatch.stderr create mode 100644 tests/ui/async-await/in-trait/missing-send-bound.rs create mode 100644 tests/ui/async-await/in-trait/missing-send-bound.stderr create mode 100644 tests/ui/async-await/in-trait/nested-rpit.rs create mode 100644 tests/ui/async-await/in-trait/object-safety.rs create mode 100644 tests/ui/async-await/in-trait/object-safety.stderr create mode 100644 tests/ui/async-await/in-trait/return-type-suggestion.rs create mode 100644 tests/ui/async-await/in-trait/return-type-suggestion.stderr create mode 100644 tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed create mode 100644 tests/ui/async-await/incorrect-move-async-order-issue-79694.rs create mode 100644 tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr create mode 100644 tests/ui/async-await/interior-with-const-generic-expr.rs create mode 100644 tests/ui/async-await/issue-101715.rs create mode 100644 tests/ui/async-await/issue-101715.stderr create mode 100644 tests/ui/async-await/issue-105501.rs create mode 100644 tests/ui/async-await/issue-107036.rs create mode 100644 tests/ui/async-await/issue-54239-private-type-triggers-lint.rs create mode 100644 tests/ui/async-await/issue-60709.rs create mode 100644 tests/ui/async-await/issue-61076.rs create mode 100644 tests/ui/async-await/issue-61076.stderr create mode 100644 tests/ui/async-await/issue-61452.rs create mode 100644 tests/ui/async-await/issue-61452.stderr create mode 100644 tests/ui/async-await/issue-61793.rs create mode 100644 tests/ui/async-await/issue-61949-self-return-type.rs create mode 100644 tests/ui/async-await/issue-61949-self-return-type.stderr create mode 100644 tests/ui/async-await/issue-62658.rs create mode 100644 tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs create mode 100644 tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs create mode 100644 tests/ui/async-await/issue-64130-1-sync.rs create mode 100644 tests/ui/async-await/issue-64130-1-sync.stderr create mode 100644 tests/ui/async-await/issue-64130-2-send.rs create mode 100644 tests/ui/async-await/issue-64130-2-send.stderr create mode 100644 tests/ui/async-await/issue-64130-3-other.rs create mode 100644 tests/ui/async-await/issue-64130-3-other.stderr create mode 100644 tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr create mode 100644 tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr create mode 100644 tests/ui/async-await/issue-64130-4-async-move.rs create mode 100644 tests/ui/async-await/issue-64130-non-send-future-diags.rs create mode 100644 tests/ui/async-await/issue-64130-non-send-future-diags.stderr create mode 100644 tests/ui/async-await/issue-64391.rs create mode 100644 tests/ui/async-await/issue-66312.rs create mode 100644 tests/ui/async-await/issue-66312.stderr create mode 100644 tests/ui/async-await/issue-66387-if-without-else.rs create mode 100644 tests/ui/async-await/issue-66387-if-without-else.stderr create mode 100644 tests/ui/async-await/issue-67252-unnamed-future.rs create mode 100644 tests/ui/async-await/issue-67252-unnamed-future.stderr create mode 100644 tests/ui/async-await/issue-67651.rs create mode 100644 tests/ui/async-await/issue-67651.stderr create mode 100644 tests/ui/async-await/issue-67765-async-diagnostic.rs create mode 100644 tests/ui/async-await/issue-67765-async-diagnostic.stderr create mode 100644 tests/ui/async-await/issue-68112.drop_tracking.stderr create mode 100644 tests/ui/async-await/issue-68112.no_drop_tracking.stderr create mode 100644 tests/ui/async-await/issue-68112.rs create mode 100644 tests/ui/async-await/issue-68523-start.rs create mode 100644 tests/ui/async-await/issue-68523-start.stderr create mode 100644 tests/ui/async-await/issue-68523.rs create mode 100644 tests/ui/async-await/issue-68523.stderr create mode 100644 tests/ui/async-await/issue-69446-fnmut-capture.rs create mode 100644 tests/ui/async-await/issue-69446-fnmut-capture.stderr create mode 100644 tests/ui/async-await/issue-70594.rs create mode 100644 tests/ui/async-await/issue-70594.stderr create mode 100644 tests/ui/async-await/issue-70818.rs create mode 100644 tests/ui/async-await/issue-70818.stderr create mode 100644 tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr create mode 100644 tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr create mode 100644 tests/ui/async-await/issue-70935-complex-spans.rs create mode 100644 tests/ui/async-await/issue-71137.rs create mode 100644 tests/ui/async-await/issue-71137.stderr create mode 100644 tests/ui/async-await/issue-72442.rs create mode 100644 tests/ui/async-await/issue-72442.stderr create mode 100644 tests/ui/async-await/issue-72470-llvm-dominate.rs create mode 100644 tests/ui/async-await/issue-72590-type-error-sized.rs create mode 100644 tests/ui/async-await/issue-72590-type-error-sized.stderr create mode 100644 tests/ui/async-await/issue-73050.rs create mode 100644 tests/ui/async-await/issue-73137.rs create mode 100644 tests/ui/async-await/issue-73541-1.rs create mode 100644 tests/ui/async-await/issue-73541-1.stderr create mode 100644 tests/ui/async-await/issue-73541-2.rs create mode 100644 tests/ui/async-await/issue-73541-2.stderr create mode 100644 tests/ui/async-await/issue-73541-3.rs create mode 100644 tests/ui/async-await/issue-73541-3.stderr create mode 100644 tests/ui/async-await/issue-73541.rs create mode 100644 tests/ui/async-await/issue-73541.stderr create mode 100644 tests/ui/async-await/issue-73741-type-err-drop-tracking.rs create mode 100644 tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr create mode 100644 tests/ui/async-await/issue-73741-type-err.rs create mode 100644 tests/ui/async-await/issue-73741-type-err.stderr create mode 100644 tests/ui/async-await/issue-74047.rs create mode 100644 tests/ui/async-await/issue-74047.stderr create mode 100644 tests/ui/async-await/issue-74072-lifetime-name-annotations.rs create mode 100644 tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr create mode 100644 tests/ui/async-await/issue-74497-lifetime-in-opaque.rs create mode 100644 tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr create mode 100644 tests/ui/async-await/issue-75785-confusing-named-region.rs create mode 100644 tests/ui/async-await/issue-75785-confusing-named-region.stderr create mode 100644 tests/ui/async-await/issue-76547.rs create mode 100644 tests/ui/async-await/issue-76547.stderr create mode 100644 tests/ui/async-await/issue-77993-2.rs create mode 100644 tests/ui/async-await/issue-77993-2.stderr create mode 100644 tests/ui/async-await/issue-84841.rs create mode 100644 tests/ui/async-await/issue-84841.stderr create mode 100644 tests/ui/async-await/issue-86507.rs create mode 100644 tests/ui/async-await/issue-86507.stderr create mode 100644 tests/ui/async-await/issue-93197.rs create mode 100644 tests/ui/async-await/issue-93648.rs create mode 100644 tests/ui/async-await/issue-98634.rs create mode 100644 tests/ui/async-await/issue-98634.stderr create mode 100644 tests/ui/async-await/issues/auxiliary/issue-60674.rs create mode 100644 tests/ui/async-await/issues/auxiliary/issue_67893.rs create mode 100644 tests/ui/async-await/issues/issue-102206.rs create mode 100644 tests/ui/async-await/issues/issue-102206.stderr create mode 100644 tests/ui/async-await/issues/issue-51719.rs create mode 100644 tests/ui/async-await/issues/issue-51719.stderr create mode 100644 tests/ui/async-await/issues/issue-51751.rs create mode 100644 tests/ui/async-await/issues/issue-51751.stderr create mode 100644 tests/ui/async-await/issues/issue-53249.rs create mode 100644 tests/ui/async-await/issues/issue-54752-async-block.rs create mode 100644 tests/ui/async-await/issues/issue-54752-async-block.stderr create mode 100644 tests/ui/async-await/issues/issue-54974.rs create mode 100644 tests/ui/async-await/issues/issue-55324.rs create mode 100644 tests/ui/async-await/issues/issue-55809.rs create mode 100644 tests/ui/async-await/issues/issue-58885.rs create mode 100644 tests/ui/async-await/issues/issue-59001.rs create mode 100644 tests/ui/async-await/issues/issue-59972.rs create mode 100644 tests/ui/async-await/issues/issue-60518.rs create mode 100644 tests/ui/async-await/issues/issue-60655-latebound-regions.rs create mode 100644 tests/ui/async-await/issues/issue-60674.rs create mode 100644 tests/ui/async-await/issues/issue-60674.stdout create mode 100644 tests/ui/async-await/issues/issue-61187.rs create mode 100644 tests/ui/async-await/issues/issue-61187.stderr create mode 100644 tests/ui/async-await/issues/issue-61986.rs create mode 100644 tests/ui/async-await/issues/issue-62009-1.rs create mode 100644 tests/ui/async-await/issues/issue-62009-1.stderr create mode 100644 tests/ui/async-await/issues/issue-62009-2.rs create mode 100644 tests/ui/async-await/issues/issue-62009-2.stderr create mode 100644 tests/ui/async-await/issues/issue-62097.rs create mode 100644 tests/ui/async-await/issues/issue-62097.stderr create mode 100644 tests/ui/async-await/issues/issue-62517-1.rs create mode 100644 tests/ui/async-await/issues/issue-62517-2.rs create mode 100644 tests/ui/async-await/issues/issue-63388-1.rs create mode 100644 tests/ui/async-await/issues/issue-63388-1.stderr create mode 100644 tests/ui/async-await/issues/issue-63388-2.rs create mode 100644 tests/ui/async-await/issues/issue-63388-2.stderr create mode 100644 tests/ui/async-await/issues/issue-63388-3.rs create mode 100644 tests/ui/async-await/issues/issue-63388-4.rs create mode 100644 tests/ui/async-await/issues/issue-64391-2.rs create mode 100644 tests/ui/async-await/issues/issue-64433.rs create mode 100644 tests/ui/async-await/issues/issue-64477-2.rs create mode 100644 tests/ui/async-await/issues/issue-64477.rs create mode 100644 tests/ui/async-await/issues/issue-64964.rs create mode 100644 tests/ui/async-await/issues/issue-65159.rs create mode 100644 tests/ui/async-await/issues/issue-65159.stderr create mode 100644 tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs create mode 100644 tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs create mode 100644 tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs create mode 100644 tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr create mode 100644 tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs create mode 100644 tests/ui/async-await/issues/issue-66695-static-refs.rs create mode 100644 tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs create mode 100644 tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr create mode 100644 tests/ui/async-await/issues/issue-67611-static-mut-refs.rs create mode 100644 tests/ui/async-await/issues/issue-67893.rs create mode 100644 tests/ui/async-await/issues/issue-67893.stderr create mode 100644 tests/ui/async-await/issues/issue-69307-nested.rs create mode 100644 tests/ui/async-await/issues/issue-69307.rs create mode 100644 tests/ui/async-await/issues/issue-72312.rs create mode 100644 tests/ui/async-await/issues/issue-72312.stderr create mode 100644 tests/ui/async-await/issues/issue-78600.rs create mode 100644 tests/ui/async-await/issues/issue-78600.stderr create mode 100644 tests/ui/async-await/issues/issue-78654.full.stderr create mode 100644 tests/ui/async-await/issues/issue-78654.min.stderr create mode 100644 tests/ui/async-await/issues/issue-78654.rs create mode 100644 tests/ui/async-await/issues/issue-78938-async-block.rs create mode 100644 tests/ui/async-await/issues/issue-78938-async-block.stderr create mode 100644 tests/ui/async-await/issues/issue-95307.rs create mode 100644 tests/ui/async-await/issues/issue-95307.stderr create mode 100644 tests/ui/async-await/issues/non-async-enclosing-span.rs create mode 100644 tests/ui/async-await/issues/non-async-enclosing-span.stderr create mode 100644 tests/ui/async-await/large_moves.attribute.stderr create mode 100644 tests/ui/async-await/large_moves.option.stderr create mode 100644 tests/ui/async-await/large_moves.rs create mode 100644 tests/ui/async-await/move-part-await-return-rest-struct.rs create mode 100644 tests/ui/async-await/move-part-await-return-rest-tuple.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/elided.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/fn-ptr.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/hrtb.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/named.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/partial-relation.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr create mode 100644 tests/ui/async-await/multiple-lifetimes/ret-ref.rs create mode 100644 tests/ui/async-await/multiple-lifetimes/ret-ref.stderr create mode 100644 tests/ui/async-await/multiple-lifetimes/variance.rs create mode 100644 tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs create mode 100644 tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr create mode 100644 tests/ui/async-await/nested-in-impl.rs create mode 100644 tests/ui/async-await/no-async-const.rs create mode 100644 tests/ui/async-await/no-async-const.stderr create mode 100644 tests/ui/async-await/no-const-async.rs create mode 100644 tests/ui/async-await/no-const-async.stderr create mode 100644 tests/ui/async-await/no-move-across-await-struct.rs create mode 100644 tests/ui/async-await/no-move-across-await-struct.stderr create mode 100644 tests/ui/async-await/no-move-across-await-tuple.rs create mode 100644 tests/ui/async-await/no-move-across-await-tuple.stderr create mode 100644 tests/ui/async-await/no-non-guaranteed-initialization.rs create mode 100644 tests/ui/async-await/no-non-guaranteed-initialization.stderr create mode 100644 tests/ui/async-await/no-params-non-move-async-closure.rs create mode 100644 tests/ui/async-await/no-params-non-move-async-closure.stderr create mode 100644 tests/ui/async-await/no-std.rs create mode 100644 tests/ui/async-await/no-unsafe-async.rs create mode 100644 tests/ui/async-await/no-unsafe-async.stderr create mode 100644 tests/ui/async-await/non-trivial-drop.rs create mode 100644 tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr create mode 100644 tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr create mode 100644 tests/ui/async-await/partial-drop-partial-reinit.rs create mode 100644 tests/ui/async-await/partial-initialization-across-await.rs create mode 100644 tests/ui/async-await/partial-initialization-across-await.stderr create mode 100644 tests/ui/async-await/pin-needed-to-poll-2.rs create mode 100644 tests/ui/async-await/pin-needed-to-poll-2.stderr create mode 100644 tests/ui/async-await/pin-needed-to-poll.rs create mode 100644 tests/ui/async-await/pin-needed-to-poll.stderr create mode 100644 tests/ui/async-await/proper-span-for-type-error.fixed create mode 100644 tests/ui/async-await/proper-span-for-type-error.rs create mode 100644 tests/ui/async-await/proper-span-for-type-error.stderr create mode 100644 tests/ui/async-await/recursive-async-impl-trait-type.rs create mode 100644 tests/ui/async-await/recursive-async-impl-trait-type.stderr create mode 100644 tests/ui/async-await/repeat_count_const_in_async_fn.rs create mode 100644 tests/ui/async-await/return-ty-raw-ptr-coercion.rs create mode 100644 tests/ui/async-await/return-ty-unsize-coercion.rs create mode 100644 tests/ui/async-await/suggest-missing-await-closure.fixed create mode 100644 tests/ui/async-await/suggest-missing-await-closure.rs create mode 100644 tests/ui/async-await/suggest-missing-await-closure.stderr create mode 100644 tests/ui/async-await/suggest-missing-await.rs create mode 100644 tests/ui/async-await/suggest-missing-await.stderr create mode 100644 tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs create mode 100644 tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr create mode 100644 tests/ui/async-await/suggest-switching-edition-on-await.rs create mode 100644 tests/ui/async-await/suggest-switching-edition-on-await.stderr create mode 100644 tests/ui/async-await/track-caller/async-block.rs create mode 100644 tests/ui/async-await/track-caller/async-block.stderr create mode 100644 tests/ui/async-await/track-caller/async-closure-gate.rs create mode 100644 tests/ui/async-await/track-caller/async-closure-gate.stderr create mode 100644 tests/ui/async-await/track-caller/issue-105134.rs create mode 100644 tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr create mode 100644 tests/ui/async-await/track-caller/panic-track-caller.rs create mode 100644 tests/ui/async-await/try-on-option-in-async.rs create mode 100644 tests/ui/async-await/try-on-option-in-async.stderr create mode 100644 tests/ui/async-await/type-parameter-send.rs create mode 100644 tests/ui/async-await/unnecessary-await.rs create mode 100644 tests/ui/async-await/unnecessary-await.stderr create mode 100644 tests/ui/async-await/unreachable-lint-1.rs create mode 100644 tests/ui/async-await/unreachable-lint-1.stderr create mode 100644 tests/ui/async-await/unreachable-lint.rs create mode 100644 tests/ui/async-await/unresolved_type_param.rs create mode 100644 tests/ui/async-await/unresolved_type_param.stderr create mode 100644 tests/ui/async-await/unused-lifetime.rs create mode 100644 tests/ui/async-await/unused-lifetime.stderr create mode 100644 tests/ui/atomic-from-mut-not-available.rs create mode 100644 tests/ui/atomic-from-mut-not-available.stderr create mode 100644 tests/ui/attempted-access-non-fatal.rs create mode 100644 tests/ui/attempted-access-non-fatal.stderr create mode 100644 tests/ui/attr-bad-crate-attr.rc create mode 100644 tests/ui/attr-shebang.rs create mode 100644 tests/ui/attr-start.rs create mode 100644 tests/ui/attr-usage-inline.rs create mode 100644 tests/ui/attr-usage-inline.stderr create mode 100644 tests/ui/attributes/attr-before-view-item.rs create mode 100644 tests/ui/attributes/attr-before-view-item2.rs create mode 100644 tests/ui/attributes/attr-eq-token-tree.rs create mode 100644 tests/ui/attributes/attr-eq-token-tree.stderr create mode 100644 tests/ui/attributes/attr-mix-new.rs create mode 100644 tests/ui/attributes/attrs-on-params.rs create mode 100644 tests/ui/attributes/attrs-on-params.stderr create mode 100644 tests/ui/attributes/attrs-with-no-formal-in-generics-1.rs create mode 100644 tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr create mode 100644 tests/ui/attributes/attrs-with-no-formal-in-generics-2.rs create mode 100644 tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr create mode 100644 tests/ui/attributes/attrs-with-no-formal-in-generics-3.rs create mode 100644 tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr create mode 100644 tests/ui/attributes/auxiliary/key-value-expansion.rs create mode 100644 tests/ui/attributes/class-attributes-1.rs create mode 100644 tests/ui/attributes/class-attributes-2.rs create mode 100644 tests/ui/attributes/collapse-debuginfo-invalid.rs create mode 100644 tests/ui/attributes/collapse-debuginfo-invalid.stderr create mode 100644 tests/ui/attributes/const-stability-on-macro.rs create mode 100644 tests/ui/attributes/const-stability-on-macro.stderr create mode 100644 tests/ui/attributes/doc-attr.rs create mode 100644 tests/ui/attributes/doc-attr.stderr create mode 100644 tests/ui/attributes/duplicated-attributes.rs create mode 100644 tests/ui/attributes/duplicated-attributes.stderr create mode 100644 tests/ui/attributes/extented-attribute-macro-error.rs create mode 100644 tests/ui/attributes/extented-attribute-macro-error.stderr create mode 100644 tests/ui/attributes/field-attributes-vis-unresolved.rs create mode 100644 tests/ui/attributes/field-attributes-vis-unresolved.stderr create mode 100644 tests/ui/attributes/invalid-doc-attr.rs create mode 100644 tests/ui/attributes/invalid-doc-attr.stderr create mode 100644 tests/ui/attributes/issue-100631.rs create mode 100644 tests/ui/attributes/issue-100631.stderr create mode 100644 tests/ui/attributes/issue-105594-invalid-attr-validation.rs create mode 100644 tests/ui/attributes/issue-105594-invalid-attr-validation.stderr create mode 100644 tests/ui/attributes/issue-40962.rs create mode 100644 tests/ui/attributes/issue-90873.rs create mode 100644 tests/ui/attributes/issue-90873.stderr create mode 100644 tests/ui/attributes/item-attributes.rs create mode 100644 tests/ui/attributes/key-value-expansion-on-mac.rs create mode 100644 tests/ui/attributes/key-value-expansion-on-mac.stderr create mode 100644 tests/ui/attributes/key-value-expansion.rs create mode 100644 tests/ui/attributes/key-value-expansion.stderr create mode 100644 tests/ui/attributes/key-value-non-ascii.rs create mode 100644 tests/ui/attributes/key-value-non-ascii.stderr create mode 100644 tests/ui/attributes/log-backtrace.rs create mode 100644 tests/ui/attributes/main-removed-1.rs create mode 100644 tests/ui/attributes/main-removed-1.stderr create mode 100644 tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs create mode 100644 tests/ui/attributes/main-removed-2/main.rs create mode 100644 tests/ui/attributes/method-attributes.rs create mode 100644 tests/ui/attributes/multiple-invalid.rs create mode 100644 tests/ui/attributes/multiple-invalid.stderr create mode 100644 tests/ui/attributes/nonterminal-expansion.rs create mode 100644 tests/ui/attributes/nonterminal-expansion.stderr create mode 100644 tests/ui/attributes/obsolete-attr.rs create mode 100644 tests/ui/attributes/obsolete-attr.stderr create mode 100644 tests/ui/attributes/suffixed-literal-meta.rs create mode 100644 tests/ui/attributes/suffixed-literal-meta.stderr create mode 100644 tests/ui/attributes/tool_attributes.rs create mode 100644 tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe.rs create mode 100644 tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr create mode 100644 tests/ui/attributes/unknown-attr.rs create mode 100644 tests/ui/attributes/unknown-attr.stderr create mode 100644 tests/ui/attributes/unnamed-field-attributes-dup.rs create mode 100644 tests/ui/attributes/unnamed-field-attributes-vis.rs create mode 100644 tests/ui/attributes/unnamed-field-attributes.rs create mode 100644 tests/ui/attributes/unrestricted-attribute-tokens.rs create mode 100644 tests/ui/attributes/unused-item-in-attr.rs create mode 100644 tests/ui/attributes/unused-item-in-attr.stderr create mode 100644 tests/ui/attributes/used_with_arg.rs create mode 100644 tests/ui/attributes/used_with_arg.stderr create mode 100644 tests/ui/attributes/used_with_arg_no_mangle.rs create mode 100644 tests/ui/attributes/used_with_multi_args.rs create mode 100644 tests/ui/attributes/used_with_multi_args.stderr create mode 100644 tests/ui/attributes/variant-attributes.rs create mode 100644 tests/ui/attributes/z-crate-attr.rs create mode 100644 tests/ui/attrs-resolution-errors.rs create mode 100644 tests/ui/attrs-resolution-errors.stderr create mode 100644 tests/ui/attrs-resolution.rs create mode 100644 tests/ui/augmented-assignments-feature-gate-cross.rs create mode 100644 tests/ui/augmented-assignments-rpass.rs create mode 100644 tests/ui/augmented-assignments.rs create mode 100644 tests/ui/augmented-assignments.stderr create mode 100644 tests/ui/auto-instantiate.rs create mode 100644 tests/ui/auto-ref-slice-plus-ref.rs create mode 100644 tests/ui/auto-ref-slice-plus-ref.stderr create mode 100644 tests/ui/auto-traits/auto-is-contextual.rs create mode 100644 tests/ui/auto-traits/auto-trait-projection-recursion.rs create mode 100644 tests/ui/auto-traits/auto-trait-validation.fixed create mode 100644 tests/ui/auto-traits/auto-trait-validation.rs create mode 100644 tests/ui/auto-traits/auto-trait-validation.stderr create mode 100644 tests/ui/auto-traits/auto-traits.rs create mode 100644 tests/ui/auto-traits/bad-generics-on-dyn.rs create mode 100644 tests/ui/auto-traits/bad-generics-on-dyn.stderr create mode 100644 tests/ui/auto-traits/issue-23080-2.rs create mode 100644 tests/ui/auto-traits/issue-23080-2.stderr create mode 100644 tests/ui/auto-traits/issue-23080.rs create mode 100644 tests/ui/auto-traits/issue-23080.stderr create mode 100644 tests/ui/auto-traits/issue-84075.rs create mode 100644 tests/ui/auto-traits/issue-84075.stderr create mode 100644 tests/ui/auto-traits/suspicious-impls-lint.rs create mode 100644 tests/ui/auto-traits/suspicious-impls-lint.stderr create mode 100644 tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs create mode 100644 tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr create mode 100644 tests/ui/auto-traits/typeck-auto-trait-no-supertraits.rs create mode 100644 tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-negation.rs create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-negation.stderr create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs create mode 100644 tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr create mode 100644 tests/ui/autoderef-full-lval.rs create mode 100644 tests/ui/autoderef-full-lval.stderr create mode 100644 tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs create mode 100644 tests/ui/autoref-autoderef/auto-ref-sliceable.rs create mode 100644 tests/ui/autoref-autoderef/auto-ref.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-method-on-trait.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-method-priority.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-method-twice.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-method.rs create mode 100644 tests/ui/autoref-autoderef/autoderef-privacy.rs create mode 100644 tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs create mode 100644 tests/ui/autoref-autoderef/deref-into-array.rs create mode 100644 tests/ui/autoref-autoderef/issue-38940.rs create mode 100644 tests/ui/autoref-autoderef/issue-38940.stderr create mode 100644 tests/ui/auxiliary/augmented_assignments.rs create mode 100644 tests/ui/auxiliary/check_static_recursion_foreign_helper.rs create mode 100644 tests/ui/auxiliary/crate-method-reexport-grrrrrrr2.rs create mode 100644 tests/ui/auxiliary/default-ty-param-cross-crate-crate.rs create mode 100644 tests/ui/auxiliary/edition-kw-macro-2015.rs create mode 100644 tests/ui/auxiliary/edition-kw-macro-2018.rs create mode 100644 tests/ui/auxiliary/fancy-panic.rs create mode 100644 tests/ui/auxiliary/hello_macro.rs create mode 100644 tests/ui/auxiliary/impl_privacy_xc_1.rs create mode 100644 tests/ui/auxiliary/inner_static.rs create mode 100644 tests/ui/auxiliary/issue-76387.rs create mode 100644 tests/ui/auxiliary/kinds_in_metadata.rs create mode 100644 tests/ui/auxiliary/msvc-data-only-lib.rs create mode 100644 tests/ui/auxiliary/noexporttypelib.rs create mode 100644 tests/ui/auxiliary/orphan-check-diagnostics.rs create mode 100644 tests/ui/auxiliary/pub-and-stability.rs create mode 100644 tests/ui/auxiliary/removing-extern-crate.rs create mode 100644 tests/ui/auxiliary/rustc-rust-log-aux.rs create mode 100644 tests/ui/auxiliary/svh-a-base.rs create mode 100644 tests/ui/auxiliary/svh-b.rs create mode 100644 tests/ui/auxiliary/typeid-intrinsic-aux1.rs create mode 100644 tests/ui/auxiliary/typeid-intrinsic-aux2.rs create mode 100644 tests/ui/auxiliary/using-target-feature-unstable.rs create mode 100644 tests/ui/auxiliary/xc-private-method-lib.rs create mode 100644 tests/ui/backtrace-apple-no-dsymutil.rs create mode 100644 tests/ui/backtrace.rs create mode 100644 tests/ui/bare-fn-implements-fn-mut.rs create mode 100644 tests/ui/bare-static-string.rs create mode 100644 tests/ui/bench/issue-32062.rs create mode 100644 tests/ui/big-literals.rs create mode 100644 tests/ui/bind-by-move.rs create mode 100644 tests/ui/binding/ambiguity-item.rs create mode 100644 tests/ui/binding/ambiguity-item.stderr create mode 100644 tests/ui/binding/bind-field-short-with-modifiers.rs create mode 100644 tests/ui/binding/borrowed-ptr-pattern-2.rs create mode 100644 tests/ui/binding/borrowed-ptr-pattern-3.rs create mode 100644 tests/ui/binding/borrowed-ptr-pattern-infallible.rs create mode 100644 tests/ui/binding/borrowed-ptr-pattern-option.rs create mode 100644 tests/ui/binding/borrowed-ptr-pattern.rs create mode 100644 tests/ui/binding/const-param.rs create mode 100644 tests/ui/binding/const-param.stderr create mode 100644 tests/ui/binding/empty-types-in-patterns.rs create mode 100644 tests/ui/binding/exhaustive-bool-match-sanity.rs create mode 100644 tests/ui/binding/expr-match-generic-unique1.rs create mode 100644 tests/ui/binding/expr-match-generic-unique2.rs create mode 100644 tests/ui/binding/expr-match-generic.rs create mode 100644 tests/ui/binding/expr-match-panic-all.rs create mode 100644 tests/ui/binding/expr-match-panic.rs create mode 100644 tests/ui/binding/expr-match-unique.rs create mode 100644 tests/ui/binding/expr-match.rs create mode 100644 tests/ui/binding/fat-arrow-match.rs create mode 100644 tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs create mode 100644 tests/ui/binding/fn-pattern-expected-type-2.rs create mode 100644 tests/ui/binding/fn-pattern-expected-type.rs create mode 100644 tests/ui/binding/func-arg-incomplete-pattern.rs create mode 100644 tests/ui/binding/func-arg-ref-pattern.rs create mode 100644 tests/ui/binding/func-arg-wild-pattern.rs create mode 100644 tests/ui/binding/if-let.rs create mode 100644 tests/ui/binding/inconsistent-lifetime-mismatch.rs create mode 100644 tests/ui/binding/inferred-suffix-in-pattern-range.rs create mode 100644 tests/ui/binding/irrefutable-slice-patterns.rs create mode 100644 tests/ui/binding/issue-53114-borrow-checks.rs create mode 100644 tests/ui/binding/issue-53114-borrow-checks.stderr create mode 100644 tests/ui/binding/issue-53114-safety-checks.rs create mode 100644 tests/ui/binding/issue-53114-safety-checks.stderr create mode 100644 tests/ui/binding/let-assignability.rs create mode 100644 tests/ui/binding/let-destruct-ref.rs create mode 100644 tests/ui/binding/let-var-hygiene.rs create mode 100644 tests/ui/binding/match-arm-statics.rs create mode 100644 tests/ui/binding/match-beginning-vert.rs create mode 100644 tests/ui/binding/match-borrowed_str.rs create mode 100644 tests/ui/binding/match-bot-2.rs create mode 100644 tests/ui/binding/match-bot.rs create mode 100644 tests/ui/binding/match-byte-array-patterns.rs create mode 100644 tests/ui/binding/match-enum-struct-0.rs create mode 100644 tests/ui/binding/match-enum-struct-1.rs create mode 100644 tests/ui/binding/match-implicit-copy-unique.rs create mode 100644 tests/ui/binding/match-in-macro.rs create mode 100644 tests/ui/binding/match-join.rs create mode 100644 tests/ui/binding/match-larger-const.rs create mode 100644 tests/ui/binding/match-naked-record-expr.rs create mode 100644 tests/ui/binding/match-naked-record.rs create mode 100644 tests/ui/binding/match-path.rs create mode 100644 tests/ui/binding/match-pattern-bindings.rs create mode 100644 tests/ui/binding/match-pattern-lit.rs create mode 100644 tests/ui/binding/match-pattern-no-type-params.rs create mode 100644 tests/ui/binding/match-pattern-simple.rs create mode 100644 tests/ui/binding/match-phi.rs create mode 100644 tests/ui/binding/match-pipe-binding.rs create mode 100644 tests/ui/binding/match-range-infer.rs create mode 100644 tests/ui/binding/match-range-static.rs create mode 100644 tests/ui/binding/match-range.rs create mode 100644 tests/ui/binding/match-reassign.rs create mode 100644 tests/ui/binding/match-ref-binding-in-guard-3256.rs create mode 100644 tests/ui/binding/match-ref-binding-mut-option.rs create mode 100644 tests/ui/binding/match-ref-binding-mut.rs create mode 100644 tests/ui/binding/match-ref-binding.rs create mode 100644 tests/ui/binding/match-ref-unsized.rs create mode 100644 tests/ui/binding/match-str.rs create mode 100644 tests/ui/binding/match-struct-0.rs create mode 100644 tests/ui/binding/match-tag.rs create mode 100644 tests/ui/binding/match-unique-bind.rs create mode 100644 tests/ui/binding/match-unsized.rs create mode 100644 tests/ui/binding/match-value-binding-in-guard-3291.rs create mode 100644 tests/ui/binding/match-var-hygiene.rs create mode 100644 tests/ui/binding/match-vec-alternatives.rs create mode 100644 tests/ui/binding/match-vec-rvalue.rs create mode 100644 tests/ui/binding/match-with-ret-arm.rs create mode 100644 tests/ui/binding/multi-let.rs create mode 100644 tests/ui/binding/mut-in-ident-patterns.rs create mode 100644 tests/ui/binding/nested-matchs.rs create mode 100644 tests/ui/binding/nested-pattern.rs create mode 100644 tests/ui/binding/nil-pattern.rs create mode 100644 tests/ui/binding/nullary-or-pattern.rs create mode 100644 tests/ui/binding/optional_comma_in_match_arm.rs create mode 100644 tests/ui/binding/or-pattern.rs create mode 100644 tests/ui/binding/order-drop-with-match.rs create mode 100644 tests/ui/binding/pat-ranges.rs create mode 100644 tests/ui/binding/pat-tuple-1.rs create mode 100644 tests/ui/binding/pat-tuple-2.rs create mode 100644 tests/ui/binding/pat-tuple-3.rs create mode 100644 tests/ui/binding/pat-tuple-4.rs create mode 100644 tests/ui/binding/pat-tuple-5.rs create mode 100644 tests/ui/binding/pat-tuple-6.rs create mode 100644 tests/ui/binding/pat-tuple-7.rs create mode 100644 tests/ui/binding/pattern-bound-var-in-for-each.rs create mode 100644 tests/ui/binding/pattern-in-closure.rs create mode 100644 tests/ui/binding/range-inclusive-pattern-precedence.rs create mode 100644 tests/ui/binding/shadow.rs create mode 100644 tests/ui/binding/simple-generic-match.rs create mode 100644 tests/ui/binding/use-uninit-match.rs create mode 100644 tests/ui/binding/use-uninit-match2.rs create mode 100644 tests/ui/binding/zero_sized_subslice_match.rs create mode 100644 tests/ui/binop/binary-minus-without-space.rs create mode 100644 tests/ui/binop/binary-op-on-double-ref.fixed create mode 100644 tests/ui/binop/binary-op-on-double-ref.rs create mode 100644 tests/ui/binop/binary-op-on-double-ref.stderr create mode 100644 tests/ui/binop/binary-op-on-fn-ptr-eq.rs create mode 100644 tests/ui/binop/binop-bitxor-str.rs create mode 100644 tests/ui/binop/binop-bitxor-str.stderr create mode 100644 tests/ui/binop/binop-consume-args.rs create mode 100644 tests/ui/binop/binop-consume-args.stderr create mode 100644 tests/ui/binop/binop-fail-3.rs create mode 100644 tests/ui/binop/binop-logic-float.rs create mode 100644 tests/ui/binop/binop-logic-float.stderr create mode 100644 tests/ui/binop/binop-logic-int.rs create mode 100644 tests/ui/binop/binop-logic-int.stderr create mode 100644 tests/ui/binop/binop-move-semantics.rs create mode 100644 tests/ui/binop/binop-move-semantics.stderr create mode 100644 tests/ui/binop/binop-mul-bool.rs create mode 100644 tests/ui/binop/binop-mul-bool.stderr create mode 100644 tests/ui/binop/binop-mul-i32-f32.rs create mode 100644 tests/ui/binop/binop-mul-i32-f32.stderr create mode 100644 tests/ui/binop/binop-panic.rs create mode 100644 tests/ui/binop/binop-typeck.rs create mode 100644 tests/ui/binop/binop-typeck.stderr create mode 100644 tests/ui/binop/binops-issue-22743.rs create mode 100644 tests/ui/binop/binops.rs create mode 100644 tests/ui/binop/issue-25916.rs create mode 100644 tests/ui/binop/issue-28837.rs create mode 100644 tests/ui/binop/issue-28837.stderr create mode 100644 tests/ui/binop/issue-3820.rs create mode 100644 tests/ui/binop/issue-3820.stderr create mode 100644 tests/ui/binop/issue-77910-1.rs create mode 100644 tests/ui/binop/issue-77910-1.stderr create mode 100644 tests/ui/binop/issue-77910-2.rs create mode 100644 tests/ui/binop/issue-77910-2.stderr create mode 100644 tests/ui/binop/issue-93927.rs create mode 100644 tests/ui/binop/issue-93927.stderr create mode 100644 tests/ui/binop/operator-multidispatch.rs create mode 100644 tests/ui/binop/operator-overloading.rs create mode 100644 tests/ui/binop/placement-syntax.rs create mode 100644 tests/ui/binop/placement-syntax.stderr create mode 100644 tests/ui/binop/shift-various-bad-types.rs create mode 100644 tests/ui/binop/shift-various-bad-types.stderr create mode 100644 tests/ui/binop/structured-compare.rs create mode 100644 tests/ui/bitwise.rs create mode 100644 tests/ui/blind/blind-item-block-item-shadow.rs create mode 100644 tests/ui/blind/blind-item-block-item-shadow.stderr create mode 100644 tests/ui/blind/blind-item-block-middle.rs create mode 100644 tests/ui/blind/blind-item-block-middle.stderr create mode 100644 tests/ui/blind/blind-item-item-shadow.rs create mode 100644 tests/ui/blind/blind-item-item-shadow.stderr create mode 100644 tests/ui/block-result/block-must-not-have-result-do.rs create mode 100644 tests/ui/block-result/block-must-not-have-result-do.stderr create mode 100644 tests/ui/block-result/block-must-not-have-result-res.rs create mode 100644 tests/ui/block-result/block-must-not-have-result-res.stderr create mode 100644 tests/ui/block-result/block-must-not-have-result-while.rs create mode 100644 tests/ui/block-result/block-must-not-have-result-while.stderr create mode 100644 tests/ui/block-result/consider-removing-last-semi.fixed create mode 100644 tests/ui/block-result/consider-removing-last-semi.rs create mode 100644 tests/ui/block-result/consider-removing-last-semi.stderr create mode 100644 tests/ui/block-result/issue-11714.rs create mode 100644 tests/ui/block-result/issue-11714.stderr create mode 100644 tests/ui/block-result/issue-13428.rs create mode 100644 tests/ui/block-result/issue-13428.stderr create mode 100644 tests/ui/block-result/issue-13624.rs create mode 100644 tests/ui/block-result/issue-13624.stderr create mode 100644 tests/ui/block-result/issue-20862.rs create mode 100644 tests/ui/block-result/issue-20862.stderr create mode 100644 tests/ui/block-result/issue-22645.rs create mode 100644 tests/ui/block-result/issue-22645.stderr create mode 100644 tests/ui/block-result/issue-3563.rs create mode 100644 tests/ui/block-result/issue-3563.stderr create mode 100644 tests/ui/block-result/issue-5500.rs create mode 100644 tests/ui/block-result/issue-5500.stderr create mode 100644 tests/ui/block-result/unexpected-return-on-unit.rs create mode 100644 tests/ui/block-result/unexpected-return-on-unit.stderr create mode 100644 tests/ui/bogus-tag.rs create mode 100644 tests/ui/bogus-tag.stderr create mode 100644 tests/ui/borrow-by-val-method-receiver.rs create mode 100644 tests/ui/borrowck/access-mode-in-closures.rs create mode 100644 tests/ui/borrowck/access-mode-in-closures.stderr create mode 100644 tests/ui/borrowck/anonymous-region-in-apit.rs create mode 100644 tests/ui/borrowck/anonymous-region-in-apit.stderr create mode 100644 tests/ui/borrowck/assign-never-type.rs create mode 100644 tests/ui/borrowck/assign_mutable_fields.rs create mode 100644 tests/ui/borrowck/assign_mutable_fields.stderr create mode 100644 tests/ui/borrowck/async-reference-generality.rs create mode 100644 tests/ui/borrowck/async-reference-generality.stderr create mode 100644 tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs create mode 100644 tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr create mode 100644 tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs create mode 100644 tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr create mode 100644 tests/ui/borrowck/borrow-immutable-upvar-mutation.rs create mode 100644 tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr create mode 100644 tests/ui/borrowck/borrow-raw-address-of-borrowed.rs create mode 100644 tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr create mode 100644 tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs create mode 100644 tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs create mode 100644 tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr create mode 100644 tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs create mode 100644 tests/ui/borrowck/borrow-raw-address-of-mutability.rs create mode 100644 tests/ui/borrowck/borrow-raw-address-of-mutability.stderr create mode 100644 tests/ui/borrowck/borrow-tuple-fields.rs create mode 100644 tests/ui/borrowck/borrow-tuple-fields.stderr create mode 100644 tests/ui/borrowck/borrowck-access-permissions.rs create mode 100644 tests/ui/borrowck/borrowck-access-permissions.stderr create mode 100644 tests/ui/borrowck/borrowck-and-init.rs create mode 100644 tests/ui/borrowck/borrowck-and-init.stderr create mode 100644 tests/ui/borrowck/borrowck-anon-fields-struct.rs create mode 100644 tests/ui/borrowck/borrowck-anon-fields-struct.stderr create mode 100644 tests/ui/borrowck/borrowck-anon-fields-tuple.rs create mode 100644 tests/ui/borrowck/borrowck-anon-fields-tuple.stderr create mode 100644 tests/ui/borrowck/borrowck-anon-fields-variant.rs create mode 100644 tests/ui/borrowck/borrowck-anon-fields-variant.stderr create mode 100644 tests/ui/borrowck/borrowck-argument.rs create mode 100644 tests/ui/borrowck/borrowck-argument.stderr create mode 100644 tests/ui/borrowck/borrowck-assign-comp-idx.rs create mode 100644 tests/ui/borrowck/borrowck-assign-comp-idx.stderr create mode 100644 tests/ui/borrowck/borrowck-assign-comp.rs create mode 100644 tests/ui/borrowck/borrowck-assign-comp.stderr create mode 100644 tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs create mode 100644 tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr create mode 100644 tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs create mode 100644 tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr create mode 100644 tests/ui/borrowck/borrowck-assign-to-constants.rs create mode 100644 tests/ui/borrowck/borrowck-assign-to-constants.stderr create mode 100644 tests/ui/borrowck/borrowck-assign-to-subfield.rs create mode 100644 tests/ui/borrowck/borrowck-assignment-to-static-mut.rs create mode 100644 tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs create mode 100644 tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr create mode 100644 tests/ui/borrowck/borrowck-autoref-3261.rs create mode 100644 tests/ui/borrowck/borrowck-autoref-3261.stderr create mode 100644 tests/ui/borrowck/borrowck-bad-nested-calls-free.rs create mode 100644 tests/ui/borrowck/borrowck-bad-nested-calls-free.stderr create mode 100644 tests/ui/borrowck/borrowck-bad-nested-calls-move.rs create mode 100644 tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr create mode 100644 tests/ui/borrowck/borrowck-binding-mutbl.rs create mode 100644 tests/ui/borrowck/borrowck-block-unint.rs create mode 100644 tests/ui/borrowck/borrowck-block-unint.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-from-expr-block.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-from-owned-ptr.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-from-stack-variable.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-from-stack-variable.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-from-temporary.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-from-temporary.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-mut-object-twice.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr create mode 100644 tests/ui/borrowck/borrowck-borrow-overloaded-deref.rs create mode 100644 tests/ui/borrowck/borrowck-borrow-overloaded-deref.stderr create mode 100644 tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs create mode 100644 tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr create mode 100644 tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.fixed create mode 100644 tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs create mode 100644 tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr create mode 100644 tests/ui/borrowck/borrowck-box-sensitivity.rs create mode 100644 tests/ui/borrowck/borrowck-break-uninit-2.rs create mode 100644 tests/ui/borrowck/borrowck-break-uninit-2.stderr create mode 100644 tests/ui/borrowck/borrowck-break-uninit.rs create mode 100644 tests/ui/borrowck/borrowck-break-uninit.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-mut-and-imm.rs create mode 100644 tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-mut-of-imm.rs create mode 100644 tests/ui/borrowck/borrowck-closures-mut-of-imm.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-mut-of-mut.rs create mode 100644 tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs create mode 100644 tests/ui/borrowck/borrowck-closures-slice-patterns.rs create mode 100644 tests/ui/borrowck/borrowck-closures-slice-patterns.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-two-imm.rs create mode 100644 tests/ui/borrowck/borrowck-closures-two-mut-fail.rs create mode 100644 tests/ui/borrowck/borrowck-closures-two-mut-fail.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-two-mut.rs create mode 100644 tests/ui/borrowck/borrowck-closures-two-mut.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-unique-imm.rs create mode 100644 tests/ui/borrowck/borrowck-closures-unique-imm.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-unique.rs create mode 100644 tests/ui/borrowck/borrowck-closures-unique.stderr create mode 100644 tests/ui/borrowck/borrowck-closures-use-after-free.rs create mode 100644 tests/ui/borrowck/borrowck-closures-use-after-free.stderr create mode 100644 tests/ui/borrowck/borrowck-consume-unsize-vec.rs create mode 100644 tests/ui/borrowck/borrowck-consume-unsize-vec.stderr create mode 100644 tests/ui/borrowck/borrowck-consume-upcast-box.rs create mode 100644 tests/ui/borrowck/borrowck-consume-upcast-box.stderr create mode 100644 tests/ui/borrowck/borrowck-describe-lvalue.rs create mode 100644 tests/ui/borrowck/borrowck-describe-lvalue.stderr create mode 100644 tests/ui/borrowck/borrowck-drop-from-guard.rs create mode 100644 tests/ui/borrowck/borrowck-drop-from-guard.stderr create mode 100644 tests/ui/borrowck/borrowck-escaping-closure-error-1.rs create mode 100644 tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr create mode 100644 tests/ui/borrowck/borrowck-escaping-closure-error-2.rs create mode 100644 tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr create mode 100644 tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs create mode 100644 tests/ui/borrowck/borrowck-field-sensitivity.rs create mode 100644 tests/ui/borrowck/borrowck-field-sensitivity.stderr create mode 100644 tests/ui/borrowck/borrowck-fixed-length-vecs.rs create mode 100644 tests/ui/borrowck/borrowck-fn-in-const-a.rs create mode 100644 tests/ui/borrowck/borrowck-fn-in-const-a.stderr create mode 100644 tests/ui/borrowck/borrowck-fn-in-const-c.rs create mode 100644 tests/ui/borrowck/borrowck-fn-in-const-c.stderr create mode 100644 tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs create mode 100644 tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr create mode 100644 tests/ui/borrowck/borrowck-for-loop-head-linkage.rs create mode 100644 tests/ui/borrowck/borrowck-for-loop-head-linkage.stderr create mode 100644 tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs create mode 100644 tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr create mode 100644 tests/ui/borrowck/borrowck-freeze-frozen-mut.rs create mode 100644 tests/ui/borrowck/borrowck-if-no-else.rs create mode 100644 tests/ui/borrowck/borrowck-if-no-else.stderr create mode 100644 tests/ui/borrowck/borrowck-if-with-else.rs create mode 100644 tests/ui/borrowck/borrowck-if-with-else.stderr create mode 100644 tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs create mode 100644 tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr create mode 100644 tests/ui/borrowck/borrowck-in-static.rs create mode 100644 tests/ui/borrowck/borrowck-in-static.stderr create mode 100644 tests/ui/borrowck/borrowck-init-in-called-fn-expr.rs create mode 100644 tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr create mode 100644 tests/ui/borrowck/borrowck-init-in-fn-expr.rs create mode 100644 tests/ui/borrowck/borrowck-init-in-fn-expr.stderr create mode 100644 tests/ui/borrowck/borrowck-init-in-fru.rs create mode 100644 tests/ui/borrowck/borrowck-init-in-fru.stderr create mode 100644 tests/ui/borrowck/borrowck-init-op-equal.rs create mode 100644 tests/ui/borrowck/borrowck-init-op-equal.stderr create mode 100644 tests/ui/borrowck/borrowck-init-plus-equal.rs create mode 100644 tests/ui/borrowck/borrowck-init-plus-equal.stderr create mode 100644 tests/ui/borrowck/borrowck-insert-during-each.rs create mode 100644 tests/ui/borrowck/borrowck-insert-during-each.stderr create mode 100644 tests/ui/borrowck/borrowck-issue-14498.rs create mode 100644 tests/ui/borrowck/borrowck-issue-14498.stderr create mode 100644 tests/ui/borrowck/borrowck-issue-2657-1.rs create mode 100644 tests/ui/borrowck/borrowck-issue-2657-1.stderr create mode 100644 tests/ui/borrowck/borrowck-issue-2657-2.fixed create mode 100644 tests/ui/borrowck/borrowck-issue-2657-2.rs create mode 100644 tests/ui/borrowck/borrowck-issue-2657-2.stderr create mode 100644 tests/ui/borrowck/borrowck-issue-48962.rs create mode 100644 tests/ui/borrowck/borrowck-issue-48962.stderr create mode 100644 tests/ui/borrowck/borrowck-lend-args.rs create mode 100644 tests/ui/borrowck/borrowck-lend-flow-if.rs create mode 100644 tests/ui/borrowck/borrowck-lend-flow-if.stderr create mode 100644 tests/ui/borrowck/borrowck-lend-flow-loop.rs create mode 100644 tests/ui/borrowck/borrowck-lend-flow-loop.stderr create mode 100644 tests/ui/borrowck/borrowck-lend-flow-match.rs create mode 100644 tests/ui/borrowck/borrowck-lend-flow-match.stderr create mode 100644 tests/ui/borrowck/borrowck-lend-flow.rs create mode 100644 tests/ui/borrowck/borrowck-lend-flow.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-blocks-move-cc.rs create mode 100644 tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-blocks-move.rs create mode 100644 tests/ui/borrowck/borrowck-loan-blocks-move.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs create mode 100644 tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-in-overloaded-op.rs create mode 100644 tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs create mode 100644 tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs create mode 100644 tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-rcvr.rs create mode 100644 tests/ui/borrowck/borrowck-loan-rcvr.stderr create mode 100644 tests/ui/borrowck/borrowck-loan-vec-content.rs create mode 100644 tests/ui/borrowck/borrowck-loan-vec-content.stderr create mode 100644 tests/ui/borrowck/borrowck-local-borrow-outlives-fn.rs create mode 100644 tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr create mode 100644 tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs create mode 100644 tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr create mode 100644 tests/ui/borrowck/borrowck-local-borrow.rs create mode 100644 tests/ui/borrowck/borrowck-macro-interaction-issue-6304.rs create mode 100644 tests/ui/borrowck/borrowck-match-already-borrowed.rs create mode 100644 tests/ui/borrowck/borrowck-match-already-borrowed.stderr create mode 100644 tests/ui/borrowck/borrowck-match-binding-is-assignment.rs create mode 100644 tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr create mode 100644 tests/ui/borrowck/borrowck-move-by-capture-ok.rs create mode 100644 tests/ui/borrowck/borrowck-move-by-capture.rs create mode 100644 tests/ui/borrowck/borrowck-move-by-capture.stderr create mode 100644 tests/ui/borrowck/borrowck-move-error-with-note.fixed create mode 100644 tests/ui/borrowck/borrowck-move-error-with-note.rs create mode 100644 tests/ui/borrowck/borrowck-move-error-with-note.stderr create mode 100644 tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs create mode 100644 tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr create mode 100644 tests/ui/borrowck/borrowck-move-from-unsafe-ptr.rs create mode 100644 tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr create mode 100644 tests/ui/borrowck/borrowck-move-in-irrefut-pat.rs create mode 100644 tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr create mode 100644 tests/ui/borrowck/borrowck-move-moved-value-into-closure.rs create mode 100644 tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr create mode 100644 tests/ui/borrowck/borrowck-move-mut-base-ptr.rs create mode 100644 tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-match.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-match.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use-match.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use-match.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array-use.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-from-array.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-of-static-item.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-of-static-item.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed create mode 100644 tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed create mode 100644 tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr create mode 100644 tests/ui/borrowck/borrowck-move-out-of-vec-tail.rs create mode 100644 tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr create mode 100644 tests/ui/borrowck/borrowck-move-subcomponent.rs create mode 100644 tests/ui/borrowck/borrowck-move-subcomponent.stderr create mode 100644 tests/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs create mode 100644 tests/ui/borrowck/borrowck-multiple-captures.rs create mode 100644 tests/ui/borrowck/borrowck-multiple-captures.stderr create mode 100644 tests/ui/borrowck/borrowck-mut-addr-of-imm-var.rs create mode 100644 tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr create mode 100644 tests/ui/borrowck/borrowck-mut-borrow-linear-errors.rs create mode 100644 tests/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr create mode 100644 tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs create mode 100644 tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr create mode 100644 tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs create mode 100644 tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr create mode 100644 tests/ui/borrowck/borrowck-mut-uniq.rs create mode 100644 tests/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs create mode 100644 tests/ui/borrowck/borrowck-mutate-in-guard.rs create mode 100644 tests/ui/borrowck/borrowck-mutate-in-guard.stderr create mode 100644 tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs create mode 100644 tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr create mode 100644 tests/ui/borrowck/borrowck-object-lifetime.rs create mode 100644 tests/ui/borrowck/borrowck-object-lifetime.stderr create mode 100644 tests/ui/borrowck/borrowck-or-init.rs create mode 100644 tests/ui/borrowck/borrowck-or-init.stderr create mode 100644 tests/ui/borrowck/borrowck-overloaded-call.rs create mode 100644 tests/ui/borrowck/borrowck-overloaded-call.stderr create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-autoderef.rs create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-move-index.rs create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-ref-index.rs create mode 100644 tests/ui/borrowck/borrowck-overloaded-index-ref-index.stderr create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-1.rs create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-1.stderr create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-2.rs create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-2.stderr create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-3.rs create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-3.stderr create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-4.rs create mode 100644 tests/ui/borrowck/borrowck-partial-reinit-4.stderr create mode 100644 tests/ui/borrowck/borrowck-pat-enum.rs create mode 100644 tests/ui/borrowck/borrowck-pat-reassign-binding.rs create mode 100644 tests/ui/borrowck/borrowck-pat-reassign-binding.stderr create mode 100644 tests/ui/borrowck/borrowck-pat-reassign-no-binding.rs create mode 100644 tests/ui/borrowck/borrowck-reborrow-from-mut.rs create mode 100644 tests/ui/borrowck/borrowck-reborrow-from-mut.stderr create mode 100644 tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs create mode 100644 tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr create mode 100644 tests/ui/borrowck/borrowck-ref-mut-of-imm.rs create mode 100644 tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr create mode 100644 tests/ui/borrowck/borrowck-reinit.rs create mode 100644 tests/ui/borrowck/borrowck-reinit.stderr create mode 100644 tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs create mode 100644 tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr create mode 100644 tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs create mode 100644 tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr create mode 100644 tests/ui/borrowck/borrowck-return.rs create mode 100644 tests/ui/borrowck/borrowck-return.stderr create mode 100644 tests/ui/borrowck/borrowck-rvalues-mutable.rs create mode 100644 tests/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs create mode 100644 tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr create mode 100644 tests/ui/borrowck/borrowck-static-item-in-fn.rs create mode 100644 tests/ui/borrowck/borrowck-storage-dead.rs create mode 100644 tests/ui/borrowck/borrowck-storage-dead.stderr create mode 100644 tests/ui/borrowck/borrowck-struct-update-with-dtor.rs create mode 100644 tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr create mode 100644 tests/ui/borrowck/borrowck-swap-mut-base-ptr.rs create mode 100644 tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr create mode 100644 tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs create mode 100644 tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr create mode 100644 tests/ui/borrowck/borrowck-trait-lifetime.rs create mode 100644 tests/ui/borrowck/borrowck-unary-move.rs create mode 100644 tests/ui/borrowck/borrowck-unary-move.stderr create mode 100644 tests/ui/borrowck/borrowck-unboxed-closures.rs create mode 100644 tests/ui/borrowck/borrowck-unboxed-closures.stderr create mode 100644 tests/ui/borrowck/borrowck-uninit-after-item.rs create mode 100644 tests/ui/borrowck/borrowck-uninit-after-item.stderr create mode 100644 tests/ui/borrowck/borrowck-uninit-field-access.rs create mode 100644 tests/ui/borrowck/borrowck-uninit-field-access.stderr create mode 100644 tests/ui/borrowck/borrowck-uninit-in-assignop.rs create mode 100644 tests/ui/borrowck/borrowck-uninit-in-assignop.stderr create mode 100644 tests/ui/borrowck/borrowck-uninit-ref-chain.rs create mode 100644 tests/ui/borrowck/borrowck-uninit-ref-chain.stderr create mode 100644 tests/ui/borrowck/borrowck-uninit.rs create mode 100644 tests/ui/borrowck/borrowck-uninit.stderr create mode 100644 tests/ui/borrowck/borrowck-union-borrow-nested.rs create mode 100644 tests/ui/borrowck/borrowck-union-borrow-nested.stderr create mode 100644 tests/ui/borrowck/borrowck-union-borrow.rs create mode 100644 tests/ui/borrowck/borrowck-union-borrow.stderr create mode 100644 tests/ui/borrowck/borrowck-union-move-assign.rs create mode 100644 tests/ui/borrowck/borrowck-union-move-assign.stderr create mode 100644 tests/ui/borrowck/borrowck-union-move.rs create mode 100644 tests/ui/borrowck/borrowck-union-move.stderr create mode 100644 tests/ui/borrowck/borrowck-union-uninitialized.rs create mode 100644 tests/ui/borrowck/borrowck-union-uninitialized.stderr create mode 100644 tests/ui/borrowck/borrowck-uniq-via-lend.rs create mode 100644 tests/ui/borrowck/borrowck-uniq-via-lend.stderr create mode 100644 tests/ui/borrowck/borrowck-uniq-via-ref.rs create mode 100644 tests/ui/borrowck/borrowck-univariant-enum.rs create mode 100644 tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs create mode 100644 tests/ui/borrowck/borrowck-unused-mut-locals.rs create mode 100644 tests/ui/borrowck/borrowck-use-in-index-lvalue.rs create mode 100644 tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr create mode 100644 tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs create mode 100644 tests/ui/borrowck/borrowck-use-mut-borrow.rs create mode 100644 tests/ui/borrowck/borrowck-use-mut-borrow.stderr create mode 100644 tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs create mode 100644 tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr create mode 100644 tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs create mode 100644 tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-element-loan.rs create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-element-loan.stderr create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-move-tail.rs create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-nesting.rs create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs create mode 100644 tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr create mode 100644 tests/ui/borrowck/borrowck-while-break.rs create mode 100644 tests/ui/borrowck/borrowck-while-break.stderr create mode 100644 tests/ui/borrowck/borrowck-while-cond.rs create mode 100644 tests/ui/borrowck/borrowck-while-cond.stderr create mode 100644 tests/ui/borrowck/borrowck-while.rs create mode 100644 tests/ui/borrowck/borrowck-while.stderr create mode 100644 tests/ui/borrowck/copy-suggestion-region-vid.rs create mode 100644 tests/ui/borrowck/copy-suggestion-region-vid.stderr create mode 100644 tests/ui/borrowck/disallow-possibly-uninitialized.rs create mode 100644 tests/ui/borrowck/disallow-possibly-uninitialized.stderr create mode 100644 tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs create mode 100644 tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr create mode 100644 tests/ui/borrowck/fsu-moves-and-copies.rs create mode 100644 tests/ui/borrowck/immut-function-arguments.rs create mode 100644 tests/ui/borrowck/immut-function-arguments.stderr create mode 100644 tests/ui/borrowck/immutable-arg.rs create mode 100644 tests/ui/borrowck/immutable-arg.stderr create mode 100644 tests/ui/borrowck/index-mut-help-with-impl.rs create mode 100644 tests/ui/borrowck/index-mut-help-with-impl.stderr create mode 100644 tests/ui/borrowck/index-mut-help.rs create mode 100644 tests/ui/borrowck/index-mut-help.stderr create mode 100644 tests/ui/borrowck/issue-101119.rs create mode 100644 tests/ui/borrowck/issue-101119.stderr create mode 100644 tests/ui/borrowck/issue-102209.rs create mode 100644 tests/ui/borrowck/issue-102209.stderr create mode 100644 tests/ui/borrowck/issue-103095.rs create mode 100644 tests/ui/borrowck/issue-103250.rs create mode 100644 tests/ui/borrowck/issue-103250.stderr create mode 100644 tests/ui/borrowck/issue-103624.rs create mode 100644 tests/ui/borrowck/issue-103624.stderr create mode 100644 tests/ui/borrowck/issue-104639-lifetime-order.rs create mode 100644 tests/ui/borrowck/issue-10876.rs create mode 100644 tests/ui/borrowck/issue-11493.fixed create mode 100644 tests/ui/borrowck/issue-11493.rs create mode 100644 tests/ui/borrowck/issue-11493.stderr create mode 100644 tests/ui/borrowck/issue-17263.rs create mode 100644 tests/ui/borrowck/issue-17545.rs create mode 100644 tests/ui/borrowck/issue-17545.stderr create mode 100644 tests/ui/borrowck/issue-17718-static-move.rs create mode 100644 tests/ui/borrowck/issue-17718-static-move.stderr create mode 100644 tests/ui/borrowck/issue-20801.rs create mode 100644 tests/ui/borrowck/issue-20801.stderr create mode 100644 tests/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs create mode 100644 tests/ui/borrowck/issue-24267-flow-exit.rs create mode 100644 tests/ui/borrowck/issue-24267-flow-exit.stderr create mode 100644 tests/ui/borrowck/issue-25793.rs create mode 100644 tests/ui/borrowck/issue-25793.stderr create mode 100644 tests/ui/borrowck/issue-28934.rs create mode 100644 tests/ui/borrowck/issue-29166.rs create mode 100644 tests/ui/borrowck/issue-31287-drop-in-guard.rs create mode 100644 tests/ui/borrowck/issue-31287-drop-in-guard.stderr create mode 100644 tests/ui/borrowck/issue-33819.rs create mode 100644 tests/ui/borrowck/issue-33819.stderr create mode 100644 tests/ui/borrowck/issue-36082.fixed create mode 100644 tests/ui/borrowck/issue-36082.rs create mode 100644 tests/ui/borrowck/issue-36082.stderr create mode 100644 tests/ui/borrowck/issue-41962.rs create mode 100644 tests/ui/borrowck/issue-41962.stderr create mode 100644 tests/ui/borrowck/issue-42344.rs create mode 100644 tests/ui/borrowck/issue-42344.stderr create mode 100644 tests/ui/borrowck/issue-45199.rs create mode 100644 tests/ui/borrowck/issue-45199.stderr create mode 100644 tests/ui/borrowck/issue-45983.rs create mode 100644 tests/ui/borrowck/issue-45983.stderr create mode 100644 tests/ui/borrowck/issue-46095.rs create mode 100644 tests/ui/borrowck/issue-46471.rs create mode 100644 tests/ui/borrowck/issue-46471.stderr create mode 100644 tests/ui/borrowck/issue-47215-ice-from-drop-elab.rs create mode 100644 tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr create mode 100644 tests/ui/borrowck/issue-51117.rs create mode 100644 tests/ui/borrowck/issue-51117.stderr create mode 100644 tests/ui/borrowck/issue-51301.rs create mode 100644 tests/ui/borrowck/issue-51301.stderr create mode 100644 tests/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs create mode 100644 tests/ui/borrowck/issue-51415.fixed create mode 100644 tests/ui/borrowck/issue-51415.rs create mode 100644 tests/ui/borrowck/issue-51415.stderr create mode 100644 tests/ui/borrowck/issue-52713-bug.rs create mode 100644 tests/ui/borrowck/issue-52713-bug.stderr create mode 100644 tests/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs create mode 100644 tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs create mode 100644 tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.stderr create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-of-never-init.rs create mode 100644 tests/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr create mode 100644 tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs create mode 100644 tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr create mode 100644 tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs create mode 100644 tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr create mode 100644 tests/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs create mode 100644 tests/ui/borrowck/issue-58776-borrowck-scans-children.rs create mode 100644 tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr create mode 100644 tests/ui/borrowck/issue-62007-assign-box.rs create mode 100644 tests/ui/borrowck/issue-62007-assign-field.rs create mode 100644 tests/ui/borrowck/issue-62107-match-arm-scopes.rs create mode 100644 tests/ui/borrowck/issue-62107-match-arm-scopes.stderr create mode 100644 tests/ui/borrowck/issue-64453.rs create mode 100644 tests/ui/borrowck/issue-64453.stderr create mode 100644 tests/ui/borrowck/issue-69789-iterator-mut-suggestion.rs create mode 100644 tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr create mode 100644 tests/ui/borrowck/issue-71546.rs create mode 100644 tests/ui/borrowck/issue-7573.rs create mode 100644 tests/ui/borrowck/issue-7573.stderr create mode 100644 tests/ui/borrowck/issue-80772.rs create mode 100644 tests/ui/borrowck/issue-81365-1.rs create mode 100644 tests/ui/borrowck/issue-81365-1.stderr create mode 100644 tests/ui/borrowck/issue-81365-10.rs create mode 100644 tests/ui/borrowck/issue-81365-10.stderr create mode 100644 tests/ui/borrowck/issue-81365-11.rs create mode 100644 tests/ui/borrowck/issue-81365-11.stderr create mode 100644 tests/ui/borrowck/issue-81365-2.rs create mode 100644 tests/ui/borrowck/issue-81365-2.stderr create mode 100644 tests/ui/borrowck/issue-81365-3.rs create mode 100644 tests/ui/borrowck/issue-81365-3.stderr create mode 100644 tests/ui/borrowck/issue-81365-4.rs create mode 100644 tests/ui/borrowck/issue-81365-4.stderr create mode 100644 tests/ui/borrowck/issue-81365-5.rs create mode 100644 tests/ui/borrowck/issue-81365-5.stderr create mode 100644 tests/ui/borrowck/issue-81365-6.rs create mode 100644 tests/ui/borrowck/issue-81365-6.stderr create mode 100644 tests/ui/borrowck/issue-81365-7.rs create mode 100644 tests/ui/borrowck/issue-81365-7.stderr create mode 100644 tests/ui/borrowck/issue-81365-8.rs create mode 100644 tests/ui/borrowck/issue-81365-8.stderr create mode 100644 tests/ui/borrowck/issue-81365-9.rs create mode 100644 tests/ui/borrowck/issue-81365-9.stderr create mode 100644 tests/ui/borrowck/issue-81899.rs create mode 100644 tests/ui/borrowck/issue-81899.stderr create mode 100644 tests/ui/borrowck/issue-82032.rs create mode 100644 tests/ui/borrowck/issue-82032.stderr create mode 100644 tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs create mode 100644 tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr create mode 100644 tests/ui/borrowck/issue-82462.rs create mode 100644 tests/ui/borrowck/issue-82462.stderr create mode 100644 tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs create mode 100644 tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr create mode 100644 tests/ui/borrowck/issue-83760.rs create mode 100644 tests/ui/borrowck/issue-83760.stderr create mode 100644 tests/ui/borrowck/issue-85581.rs create mode 100644 tests/ui/borrowck/issue-85581.stderr create mode 100644 tests/ui/borrowck/issue-85765.rs create mode 100644 tests/ui/borrowck/issue-85765.stderr create mode 100644 tests/ui/borrowck/issue-87456-point-to-closure.rs create mode 100644 tests/ui/borrowck/issue-87456-point-to-closure.stderr create mode 100644 tests/ui/borrowck/issue-88434-minimal-example.rs create mode 100644 tests/ui/borrowck/issue-88434-minimal-example.stderr create mode 100644 tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs create mode 100644 tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr create mode 100644 tests/ui/borrowck/issue-91206.rs create mode 100644 tests/ui/borrowck/issue-91206.stderr create mode 100644 tests/ui/borrowck/issue-92015.rs create mode 100644 tests/ui/borrowck/issue-92015.stderr create mode 100644 tests/ui/borrowck/issue-92157.rs create mode 100644 tests/ui/borrowck/issue-92157.stderr create mode 100644 tests/ui/borrowck/issue-93078.rs create mode 100644 tests/ui/borrowck/issue-93078.stderr create mode 100644 tests/ui/borrowck/issue-93093.rs create mode 100644 tests/ui/borrowck/issue-93093.stderr create mode 100644 tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs create mode 100644 tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr create mode 100644 tests/ui/borrowck/kindck-implicit-close-over-mut-var.rs create mode 100644 tests/ui/borrowck/lazy-init.rs create mode 100644 tests/ui/borrowck/many-mutable-borrows.rs create mode 100644 tests/ui/borrowck/many-mutable-borrows.stderr create mode 100644 tests/ui/borrowck/move-error-in-promoted-2.rs create mode 100644 tests/ui/borrowck/move-error-in-promoted-2.stderr create mode 100644 tests/ui/borrowck/move-error-in-promoted.rs create mode 100644 tests/ui/borrowck/move-error-in-promoted.stderr create mode 100644 tests/ui/borrowck/move-error-snippets-ext.rs create mode 100644 tests/ui/borrowck/move-error-snippets.rs create mode 100644 tests/ui/borrowck/move-error-snippets.stderr create mode 100644 tests/ui/borrowck/move-from-union-field-issue-66500.rs create mode 100644 tests/ui/borrowck/move-from-union-field-issue-66500.stderr create mode 100644 tests/ui/borrowck/move-in-pattern-mut-in-loop.rs create mode 100644 tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr create mode 100644 tests/ui/borrowck/move-in-pattern-mut.rs create mode 100644 tests/ui/borrowck/move-in-pattern-mut.stderr create mode 100644 tests/ui/borrowck/move-in-pattern.fixed create mode 100644 tests/ui/borrowck/move-in-pattern.rs create mode 100644 tests/ui/borrowck/move-in-pattern.stderr create mode 100644 tests/ui/borrowck/move-in-static-initializer-issue-38520.rs create mode 100644 tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr create mode 100644 tests/ui/borrowck/mut-borrow-in-loop-2.fixed create mode 100644 tests/ui/borrowck/mut-borrow-in-loop-2.rs create mode 100644 tests/ui/borrowck/mut-borrow-in-loop-2.stderr create mode 100644 tests/ui/borrowck/mut-borrow-in-loop.rs create mode 100644 tests/ui/borrowck/mut-borrow-in-loop.stderr create mode 100644 tests/ui/borrowck/mut-borrow-of-mut-ref.rs create mode 100644 tests/ui/borrowck/mut-borrow-of-mut-ref.stderr create mode 100644 tests/ui/borrowck/mut-borrow-outside-loop.rs create mode 100644 tests/ui/borrowck/mut-borrow-outside-loop.stderr create mode 100644 tests/ui/borrowck/mutability-errors.rs create mode 100644 tests/ui/borrowck/mutability-errors.stderr create mode 100644 tests/ui/borrowck/or-patterns.rs create mode 100644 tests/ui/borrowck/or-patterns.stderr create mode 100644 tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs create mode 100644 tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr create mode 100644 tests/ui/borrowck/reassignment_immutable_fields.rs create mode 100644 tests/ui/borrowck/reassignment_immutable_fields.stderr create mode 100644 tests/ui/borrowck/reassignment_immutable_fields_overlapping.rs create mode 100644 tests/ui/borrowck/reassignment_immutable_fields_overlapping.stderr create mode 100644 tests/ui/borrowck/reassignment_immutable_fields_twice.rs create mode 100644 tests/ui/borrowck/reassignment_immutable_fields_twice.stderr create mode 100644 tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs create mode 100644 tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr create mode 100644 tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs create mode 100644 tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr create mode 100644 tests/ui/borrowck/regions-escape-bound-fn-2.rs create mode 100644 tests/ui/borrowck/regions-escape-bound-fn-2.stderr create mode 100644 tests/ui/borrowck/regions-escape-bound-fn.rs create mode 100644 tests/ui/borrowck/regions-escape-bound-fn.stderr create mode 100644 tests/ui/borrowck/regions-escape-unboxed-closure.rs create mode 100644 tests/ui/borrowck/regions-escape-unboxed-closure.stderr create mode 100644 tests/ui/borrowck/return-local-binding-from-desugaring.rs create mode 100644 tests/ui/borrowck/return-local-binding-from-desugaring.stderr create mode 100644 tests/ui/borrowck/slice-index-bounds-check-invalidation.rs create mode 100644 tests/ui/borrowck/slice-index-bounds-check-invalidation.stderr create mode 100644 tests/ui/borrowck/suggest-as-ref-on-mut-closure.rs create mode 100644 tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr create mode 100644 tests/ui/borrowck/suggest-assign-rvalue.rs create mode 100644 tests/ui/borrowck/suggest-assign-rvalue.stderr create mode 100644 tests/ui/borrowck/suggest-local-var-double-mut.rs create mode 100644 tests/ui/borrowck/suggest-local-var-double-mut.stderr create mode 100644 tests/ui/borrowck/suggest-local-var-for-vector.rs create mode 100644 tests/ui/borrowck/suggest-local-var-for-vector.stderr create mode 100644 tests/ui/borrowck/suggest-local-var-imm-and-mut.rs create mode 100644 tests/ui/borrowck/suggest-local-var-imm-and-mut.stderr create mode 100644 tests/ui/borrowck/suggest-storing-local-var-for-vector.rs create mode 100644 tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr create mode 100644 tests/ui/borrowck/two-phase-across-loop.rs create mode 100644 tests/ui/borrowck/two-phase-across-loop.stderr create mode 100644 tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr create mode 100644 tests/ui/borrowck/two-phase-activation-sharing-interference.rs create mode 100644 tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr create mode 100644 tests/ui/borrowck/two-phase-allow-access-during-reservation.rs create mode 100644 tests/ui/borrowck/two-phase-baseline.rs create mode 100644 tests/ui/borrowck/two-phase-bin-ops.rs create mode 100644 tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs create mode 100644 tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr create mode 100644 tests/ui/borrowck/two-phase-control-flow-split-before-activation.rs create mode 100644 tests/ui/borrowck/two-phase-method-receivers.rs create mode 100644 tests/ui/borrowck/two-phase-multi-mut.rs create mode 100644 tests/ui/borrowck/two-phase-multi-mut.stderr create mode 100644 tests/ui/borrowck/two-phase-multiple-activations.rs create mode 100644 tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr create mode 100644 tests/ui/borrowck/two-phase-nonrecv-autoref.rs create mode 100644 tests/ui/borrowck/two-phase-reservation-sharing-interference-2.rs create mode 100644 tests/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr create mode 100644 tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr create mode 100644 tests/ui/borrowck/two-phase-reservation-sharing-interference.rs create mode 100644 tests/ui/borrowck/two-phase-sneaky.rs create mode 100644 tests/ui/borrowck/two-phase-sneaky.stderr create mode 100644 tests/ui/borrowck/two-phase-surprise-no-conflict.rs create mode 100644 tests/ui/borrowck/two-phase-surprise-no-conflict.stderr create mode 100644 tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed create mode 100644 tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs create mode 100644 tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr create mode 100644 tests/ui/bounds-lifetime.rs create mode 100644 tests/ui/bounds-lifetime.stderr create mode 100644 tests/ui/box/alloc-unstable-fail.rs create mode 100644 tests/ui/box/alloc-unstable-fail.stderr create mode 100644 tests/ui/box/alloc-unstable.rs create mode 100644 tests/ui/box/into-boxed-slice-fail.rs create mode 100644 tests/ui/box/into-boxed-slice-fail.stderr create mode 100644 tests/ui/box/into-boxed-slice.rs create mode 100644 tests/ui/box/issue-82446.rs create mode 100644 tests/ui/box/issue-82446.stderr create mode 100644 tests/ui/box/issue-95036.rs create mode 100644 tests/ui/box/large-allocator-ice.rs create mode 100644 tests/ui/box/leak-alloc.rs create mode 100644 tests/ui/box/leak-alloc.stderr create mode 100644 tests/ui/box/new-box-syntax.rs create mode 100644 tests/ui/box/new-box.rs create mode 100644 tests/ui/box/new.rs create mode 100644 tests/ui/box/thin_align.rs create mode 100644 tests/ui/box/thin_drop.rs create mode 100644 tests/ui/box/thin_new.rs create mode 100644 tests/ui/box/thin_zst.rs create mode 100644 tests/ui/break-diverging-value.rs create mode 100644 tests/ui/break-diverging-value.stderr create mode 100644 tests/ui/btreemap/btreemap-index-mut.rs create mode 100644 tests/ui/btreemap/btreemap-index-mut.stderr create mode 100644 tests/ui/btreemap/btreemap_dropck.rs create mode 100644 tests/ui/btreemap/btreemap_dropck.stderr create mode 100644 tests/ui/btreemap/btreemap_into_iterator_lifetime.rs create mode 100644 tests/ui/builtin-clone-unwind.rs create mode 100644 tests/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-capabilities-transitive.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-capabilities-xc.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-capabilities.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-phantom-typaram.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-self-type.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-simple.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr create mode 100644 tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs create mode 100644 tests/ui/by-move-pattern-binding.rs create mode 100644 tests/ui/by-move-pattern-binding.stderr create mode 100644 tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs create mode 100644 tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr create mode 100644 tests/ui/c-variadic/issue-32201.rs create mode 100644 tests/ui/c-variadic/issue-32201.stderr create mode 100644 tests/ui/c-variadic/issue-86053-1.rs create mode 100644 tests/ui/c-variadic/issue-86053-1.stderr create mode 100644 tests/ui/c-variadic/issue-86053-2.rs create mode 100644 tests/ui/c-variadic/issue-86053-2.stderr create mode 100644 tests/ui/c-variadic/variadic-ffi-1.rs create mode 100644 tests/ui/c-variadic/variadic-ffi-1.stderr create mode 100644 tests/ui/c-variadic/variadic-ffi-2.rs create mode 100644 tests/ui/c-variadic/variadic-ffi-2.stderr create mode 100644 tests/ui/c-variadic/variadic-ffi-4.rs create mode 100644 tests/ui/c-variadic/variadic-ffi-4.stderr create mode 100644 tests/ui/c-variadic/variadic-ffi-6.rs create mode 100644 tests/ui/c-variadic/variadic-ffi-6.stderr create mode 100644 tests/ui/c-variadic/variadic-ffi-no-fixed-args.rs create mode 100644 tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr create mode 100644 tests/ui/c-variadic/variadic-unreachable-arg-error.rs create mode 100644 tests/ui/can-copy-pod.rs create mode 100644 tests/ui/cancel-clean-via-immediate-rvalue-ref.rs create mode 100644 tests/ui/cannot-mutate-captured-non-mut-var.rs create mode 100644 tests/ui/cannot-mutate-captured-non-mut-var.stderr create mode 100644 tests/ui/capture1.rs create mode 100644 tests/ui/capture1.stderr create mode 100644 tests/ui/cast/cast-as-bool.rs create mode 100644 tests/ui/cast/cast-as-bool.stderr create mode 100644 tests/ui/cast/cast-char.rs create mode 100644 tests/ui/cast/cast-char.stderr create mode 100644 tests/ui/cast/cast-does-fallback.rs create mode 100644 tests/ui/cast/cast-errors-issue-43825.rs create mode 100644 tests/ui/cast/cast-errors-issue-43825.stderr create mode 100644 tests/ui/cast/cast-from-nil.rs create mode 100644 tests/ui/cast/cast-from-nil.stderr create mode 100644 tests/ui/cast/cast-int-to-char.rs create mode 100644 tests/ui/cast/cast-int-to-char.stderr create mode 100644 tests/ui/cast/cast-macro-lhs.rs create mode 100644 tests/ui/cast/cast-macro-lhs.stderr create mode 100644 tests/ui/cast/cast-pointee-projection.rs create mode 100644 tests/ui/cast/cast-region-to-uint.rs create mode 100644 tests/ui/cast/cast-rfc0401-2.rs create mode 100644 tests/ui/cast/cast-rfc0401-2.stderr create mode 100644 tests/ui/cast/cast-rfc0401-vtable-kinds.rs create mode 100644 tests/ui/cast/cast-rfc0401.rs create mode 100644 tests/ui/cast/cast-to-bare-fn.rs create mode 100644 tests/ui/cast/cast-to-bare-fn.stderr create mode 100644 tests/ui/cast/cast-to-infer-ty.rs create mode 100644 tests/ui/cast/cast-to-nil.rs create mode 100644 tests/ui/cast/cast-to-nil.stderr create mode 100644 tests/ui/cast/cast-to-unsized-trait-object-suggestion.rs create mode 100644 tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr create mode 100644 tests/ui/cast/cast.rs create mode 100644 tests/ui/cast/casts-differing-anon.rs create mode 100644 tests/ui/cast/casts-differing-anon.stderr create mode 100644 tests/ui/cast/casts-issue-46365.rs create mode 100644 tests/ui/cast/casts-issue-46365.stderr create mode 100644 tests/ui/cast/codegen-object-shim.rs create mode 100644 tests/ui/cast/fat-ptr-cast-rpass.rs create mode 100644 tests/ui/cast/fat-ptr-cast.rs create mode 100644 tests/ui/cast/fat-ptr-cast.stderr create mode 100644 tests/ui/cast/issue-106883-is-empty.rs create mode 100644 tests/ui/cast/issue-106883-is-empty.stderr create mode 100644 tests/ui/cast/issue-10991.rs create mode 100644 tests/ui/cast/issue-10991.stderr create mode 100644 tests/ui/cast/issue-17444.rs create mode 100644 tests/ui/cast/issue-17444.stderr create mode 100644 tests/ui/cast/issue-84213.fixed create mode 100644 tests/ui/cast/issue-84213.rs create mode 100644 tests/ui/cast/issue-84213.stderr create mode 100644 tests/ui/cast/issue-85586.rs create mode 100644 tests/ui/cast/issue-85586.stderr create mode 100644 tests/ui/cast/issue-88621.rs create mode 100644 tests/ui/cast/issue-88621.stderr create mode 100644 tests/ui/cast/issue-89497.fixed create mode 100644 tests/ui/cast/issue-89497.rs create mode 100644 tests/ui/cast/issue-89497.stderr create mode 100644 tests/ui/cast/supported-cast.rs create mode 100644 tests/ui/cast/unsupported-cast.rs create mode 100644 tests/ui/cast/unsupported-cast.stderr create mode 100644 tests/ui/catch-unwind-bang.rs create mode 100644 tests/ui/cenum_impl_drop_cast.rs create mode 100644 tests/ui/cenum_impl_drop_cast.stderr create mode 100644 tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs create mode 100644 tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs create mode 100644 tests/ui/cfg/auxiliary/cfg_inner_static.rs create mode 100644 tests/ui/cfg/cfg-attr-cfg.rs create mode 100644 tests/ui/cfg/cfg-attr-crate.rs create mode 100644 tests/ui/cfg/cfg-family.rs create mode 100644 tests/ui/cfg/cfg-in-crate-1.rs create mode 100644 tests/ui/cfg/cfg-macros-foo.rs create mode 100644 tests/ui/cfg/cfg-macros-notfoo.rs create mode 100644 tests/ui/cfg/cfg-match-arm.rs create mode 100644 tests/ui/cfg/cfg-method-receiver-ok.rs create mode 100644 tests/ui/cfg/cfg-method-receiver.rs create mode 100644 tests/ui/cfg/cfg-method-receiver.stderr create mode 100644 tests/ui/cfg/cfg-panic-abort.rs create mode 100644 tests/ui/cfg/cfg-panic.rs create mode 100644 tests/ui/cfg/cfg-path-error.rs create mode 100644 tests/ui/cfg/cfg-path-error.stderr create mode 100644 tests/ui/cfg/cfg-target-abi.rs create mode 100644 tests/ui/cfg/cfg-target-compact-errors.rs create mode 100644 tests/ui/cfg/cfg-target-compact-errors.stderr create mode 100644 tests/ui/cfg/cfg-target-compact.rs create mode 100644 tests/ui/cfg/cfg-target-family.rs create mode 100644 tests/ui/cfg/cfg-target-vendor.rs create mode 100644 tests/ui/cfg/cfg_attr.rs create mode 100644 tests/ui/cfg/cfg_inner_static.rs create mode 100644 tests/ui/cfg/cfg_stmt_expr.rs create mode 100644 tests/ui/cfg/cfgs-on-items.rs create mode 100644 tests/ui/cfg/conditional-compile-arch.rs create mode 100644 tests/ui/cfg/conditional-compile.rs create mode 100644 tests/ui/cfg/crt-static-off-works.rs create mode 100644 tests/ui/cfg/crt-static-on-works.rs create mode 100644 tests/ui/cfg/expanded-cfg.rs create mode 100644 tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs create mode 100644 tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr create mode 100644 tests/ui/cfguard-run.rs create mode 100644 tests/ui/chalkify/arithmetic.rs create mode 100644 tests/ui/chalkify/assert.rs create mode 100644 tests/ui/chalkify/basic.rs create mode 100644 tests/ui/chalkify/bugs/async.rs create mode 100644 tests/ui/chalkify/bugs/async.stderr create mode 100644 tests/ui/chalkify/builtin-copy-clone.rs create mode 100644 tests/ui/chalkify/chalk_initial_program.rs create mode 100644 tests/ui/chalkify/chalk_initial_program.stderr create mode 100644 tests/ui/chalkify/closure.rs create mode 100644 tests/ui/chalkify/closure.stderr create mode 100644 tests/ui/chalkify/generic_impls.rs create mode 100644 tests/ui/chalkify/generic_impls.stderr create mode 100644 tests/ui/chalkify/impl_wf.rs create mode 100644 tests/ui/chalkify/impl_wf.stderr create mode 100644 tests/ui/chalkify/impl_wf_2.rs create mode 100644 tests/ui/chalkify/impl_wf_2.stderr create mode 100644 tests/ui/chalkify/inherent_impl.rs create mode 100644 tests/ui/chalkify/inherent_impl_min.rs create mode 100644 tests/ui/chalkify/lower_env1.rs create mode 100644 tests/ui/chalkify/lower_env2.rs create mode 100644 tests/ui/chalkify/lower_env3.rs create mode 100644 tests/ui/chalkify/lower_impl.rs create mode 100644 tests/ui/chalkify/lower_struct.rs create mode 100644 tests/ui/chalkify/lower_trait.rs create mode 100644 tests/ui/chalkify/lower_trait_higher_rank.rs create mode 100644 tests/ui/chalkify/lower_trait_where_clause.rs create mode 100644 tests/ui/chalkify/println.rs create mode 100644 tests/ui/chalkify/projection.rs create mode 100644 tests/ui/chalkify/recursive_where_clause_on_type.rs create mode 100644 tests/ui/chalkify/recursive_where_clause_on_type.stderr create mode 100644 tests/ui/chalkify/super_trait.rs create mode 100644 tests/ui/chalkify/trait-objects.rs create mode 100644 tests/ui/chalkify/trait_implied_bound.rs create mode 100644 tests/ui/chalkify/type_implied_bound.rs create mode 100644 tests/ui/chalkify/type_inference.rs create mode 100644 tests/ui/chalkify/type_inference.stderr create mode 100644 tests/ui/chalkify/type_wf.rs create mode 100644 tests/ui/chalkify/type_wf.stderr create mode 100644 tests/ui/char.rs create mode 100644 tests/ui/check-cfg/allow-at-crate-level.rs create mode 100644 tests/ui/check-cfg/allow-macro-cfg.rs create mode 100644 tests/ui/check-cfg/allow-same-level.rs create mode 100644 tests/ui/check-cfg/allow-same-level.stderr create mode 100644 tests/ui/check-cfg/allow-top-level.rs create mode 100644 tests/ui/check-cfg/allow-upper-level.rs create mode 100644 tests/ui/check-cfg/compact-names.rs create mode 100644 tests/ui/check-cfg/compact-names.stderr create mode 100644 tests/ui/check-cfg/compact-values.rs create mode 100644 tests/ui/check-cfg/compact-values.stderr create mode 100644 tests/ui/check-cfg/empty-names.rs create mode 100644 tests/ui/check-cfg/empty-names.stderr create mode 100644 tests/ui/check-cfg/empty-values.rs create mode 100644 tests/ui/check-cfg/empty-values.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.anything_else.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.rs create mode 100644 tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr create mode 100644 tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr create mode 100644 tests/ui/check-cfg/invalid-cfg-name.rs create mode 100644 tests/ui/check-cfg/invalid-cfg-name.stderr create mode 100644 tests/ui/check-cfg/invalid-cfg-value.rs create mode 100644 tests/ui/check-cfg/invalid-cfg-value.stderr create mode 100644 tests/ui/check-cfg/mix.rs create mode 100644 tests/ui/check-cfg/mix.stderr create mode 100644 tests/ui/check-cfg/no-values.rs create mode 100644 tests/ui/check-cfg/no-values.stderr create mode 100644 tests/ui/check-cfg/stmt-no-ice.rs create mode 100644 tests/ui/check-cfg/stmt-no-ice.stderr create mode 100644 tests/ui/check-cfg/well-known-names.rs create mode 100644 tests/ui/check-cfg/well-known-names.stderr create mode 100644 tests/ui/check-cfg/well-known-values.rs create mode 100644 tests/ui/check-cfg/well-known-values.stderr create mode 100644 tests/ui/check-static-immutable-mut-slices.rs create mode 100644 tests/ui/check-static-immutable-mut-slices.stderr create mode 100644 tests/ui/check-static-recursion-foreign.rs create mode 100644 tests/ui/check-static-values-constraints.rs create mode 100644 tests/ui/check-static-values-constraints.stderr create mode 100644 tests/ui/class-cast-to-trait.rs create mode 100644 tests/ui/class-cast-to-trait.stderr create mode 100644 tests/ui/class-method-missing.rs create mode 100644 tests/ui/class-method-missing.stderr create mode 100644 tests/ui/cleanup-rvalue-for-scope.rs create mode 100644 tests/ui/cleanup-rvalue-scopes-cf.rs create mode 100644 tests/ui/cleanup-rvalue-scopes-cf.stderr create mode 100644 tests/ui/cleanup-rvalue-scopes.rs create mode 100644 tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs create mode 100644 tests/ui/cleanup-shortcircuit.rs create mode 100644 tests/ui/close-over-big-then-small-data.rs create mode 100644 tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs create mode 100644 tests/ui/closure-expected-type/expect-fn-supply-fn.rs create mode 100644 tests/ui/closure-expected-type/expect-fn-supply-fn.stderr create mode 100644 tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs create mode 100644 tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr create mode 100644 tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs create mode 100644 tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs create mode 100644 tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs create mode 100644 tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr create mode 100644 tests/ui/closure-expected-type/issue-24421.rs create mode 100644 tests/ui/closure_context/issue-26046-fn-mut.rs create mode 100644 tests/ui/closure_context/issue-26046-fn-mut.stderr create mode 100644 tests/ui/closure_context/issue-26046-fn-once.rs create mode 100644 tests/ui/closure_context/issue-26046-fn-once.stderr create mode 100644 tests/ui/closure_context/issue-42065.rs create mode 100644 tests/ui/closure_context/issue-42065.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs create mode 100644 tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/by_value.rs create mode 100644 tests/ui/closures/2229_closure_analysis/by_value.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/capture-enum-field.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-enums.rs create mode 100644 tests/ui/closures/2229_closure_analysis/capture-enums.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs create mode 100644 tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs create mode 100644 tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/destructure_patterns.rs create mode 100644 tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/box.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/union.rs create mode 100644 tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs create mode 100644 tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs create mode 100644 tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/issue-87378.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue-87378.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/issue-87987.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue-87987.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/issue-88118-2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue-88118-2.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/issue-88476.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue-88476.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/issue-89606.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue-90465.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/issue-90465.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue-90465.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs create mode 100644 tests/ui/closures/2229_closure_analysis/issue_88118.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/issue-87097.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/issue-87097.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/issue-87426.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/issue-87988.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/issue-88331.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/issue-88331.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/issue-86753.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/macro.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/macro.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/macro.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/no_migrations.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/old_name.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/old_name.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/precise.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/precise.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/precise.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/significant_drop.rs create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs create mode 100644 tests/ui/closures/2229_closure_analysis/move_closure.rs create mode 100644 tests/ui/closures/2229_closure_analysis/move_closure.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/nested-closure.rs create mode 100644 tests/ui/closures/2229_closure_analysis/nested-closure.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs create mode 100644 tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs create mode 100644 tests/ui/closures/2229_closure_analysis/path-with-array-access.rs create mode 100644 tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs create mode 100644 tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_eighteen.run.stdout create mode 100644 tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_twentyone.run.stdout create mode 100644 tests/ui/closures/2229_closure_analysis/repr_packed.rs create mode 100644 tests/ui/closures/2229_closure_analysis/repr_packed.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/box.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/by_value.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/edition.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/move_closure.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs create mode 100644 tests/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs create mode 100644 tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs create mode 100644 tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs create mode 100644 tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr create mode 100644 tests/ui/closures/2229_closure_analysis/wild_patterns.rs create mode 100644 tests/ui/closures/2229_closure_analysis/wild_patterns.stderr create mode 100644 tests/ui/closures/add_semicolon_non_block_closure.rs create mode 100644 tests/ui/closures/add_semicolon_non_block_closure.stderr create mode 100644 tests/ui/closures/binder/async-closure-with-binder.rs create mode 100644 tests/ui/closures/binder/async-closure-with-binder.stderr create mode 100644 tests/ui/closures/binder/disallow-const.rs create mode 100644 tests/ui/closures/binder/disallow-const.stderr create mode 100644 tests/ui/closures/binder/disallow-ty.rs create mode 100644 tests/ui/closures/binder/disallow-ty.stderr create mode 100644 tests/ui/closures/binder/implicit-return.rs create mode 100644 tests/ui/closures/binder/implicit-return.stderr create mode 100644 tests/ui/closures/binder/implicit-stuff.rs create mode 100644 tests/ui/closures/binder/implicit-stuff.stderr create mode 100644 tests/ui/closures/binder/late-bound-in-body.rs create mode 100644 tests/ui/closures/binder/nested-closures-regions.rs create mode 100644 tests/ui/closures/binder/nested-closures-regions.stderr create mode 100644 tests/ui/closures/binder/nested-closures.rs create mode 100644 tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.rs create mode 100644 tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.stderr create mode 100644 tests/ui/closures/closure-array-break-length.rs create mode 100644 tests/ui/closures/closure-array-break-length.stderr create mode 100644 tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs create mode 100644 tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr create mode 100644 tests/ui/closures/closure-bounds-static-cant-capture-borrowed.rs create mode 100644 tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr create mode 100644 tests/ui/closures/closure-bounds-subtype.rs create mode 100644 tests/ui/closures/closure-bounds-subtype.stderr create mode 100644 tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr create mode 100644 tests/ui/closures/closure-expected-type/expect-region-supply-region-2.rs create mode 100644 tests/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr create mode 100644 tests/ui/closures/closure-expected-type/expect-region-supply-region.rs create mode 100644 tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr create mode 100644 tests/ui/closures/closure-expected.rs create mode 100644 tests/ui/closures/closure-expected.stderr create mode 100644 tests/ui/closures/closure-immutable-outer-variable.fixed create mode 100644 tests/ui/closures/closure-immutable-outer-variable.rs create mode 100644 tests/ui/closures/closure-immutable-outer-variable.rs.fixed create mode 100644 tests/ui/closures/closure-immutable-outer-variable.stderr create mode 100644 tests/ui/closures/closure-move-sync.rs create mode 100644 tests/ui/closures/closure-move-sync.stderr create mode 100644 tests/ui/closures/closure-no-fn-1.rs create mode 100644 tests/ui/closures/closure-no-fn-1.stderr create mode 100644 tests/ui/closures/closure-no-fn-2.rs create mode 100644 tests/ui/closures/closure-no-fn-2.stderr create mode 100644 tests/ui/closures/closure-no-fn-3.rs create mode 100644 tests/ui/closures/closure-no-fn-3.stderr create mode 100644 tests/ui/closures/closure-no-fn-4.rs create mode 100644 tests/ui/closures/closure-no-fn-4.stderr create mode 100644 tests/ui/closures/closure-no-fn-5.rs create mode 100644 tests/ui/closures/closure-no-fn-5.stderr create mode 100644 tests/ui/closures/closure-referencing-itself-issue-25954.rs create mode 100644 tests/ui/closures/closure-referencing-itself-issue-25954.stderr create mode 100644 tests/ui/closures/closure-reform-bad.rs create mode 100644 tests/ui/closures/closure-reform-bad.stderr create mode 100644 tests/ui/closures/closure-return-type-mismatch.rs create mode 100644 tests/ui/closures/closure-return-type-mismatch.stderr create mode 100644 tests/ui/closures/closure-return-type-must-be-sized.rs create mode 100644 tests/ui/closures/closure-return-type-must-be-sized.stderr create mode 100644 tests/ui/closures/closure-wrong-kind.rs create mode 100644 tests/ui/closures/closure-wrong-kind.stderr create mode 100644 tests/ui/closures/closure_cap_coerce_many_fail.rs create mode 100644 tests/ui/closures/closure_cap_coerce_many_fail.stderr create mode 100644 tests/ui/closures/closure_no_cap_coerce_many_check_pass.rs create mode 100644 tests/ui/closures/closure_no_cap_coerce_many_run_pass.rs create mode 100644 tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.mir.stderr create mode 100644 tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs create mode 100644 tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.thir.stderr create mode 100644 tests/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs create mode 100644 tests/ui/closures/closure_promotion.rs create mode 100644 tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr create mode 100644 tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs create mode 100644 tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr create mode 100644 tests/ui/closures/coerce-unsafe-to-closure.rs create mode 100644 tests/ui/closures/coerce-unsafe-to-closure.stderr create mode 100644 tests/ui/closures/deeply-nested_closures.rs create mode 100644 tests/ui/closures/diverging-closure.rs create mode 100644 tests/ui/closures/issue-101696.rs create mode 100644 tests/ui/closures/issue-102089-multiple-opaque-cast.rs create mode 100644 tests/ui/closures/issue-10398.rs create mode 100644 tests/ui/closures/issue-10398.stderr create mode 100644 tests/ui/closures/issue-23012-supertrait-signature-inference.rs create mode 100644 tests/ui/closures/issue-41366.rs create mode 100644 tests/ui/closures/issue-42463.rs create mode 100644 tests/ui/closures/issue-46742.rs create mode 100644 tests/ui/closures/issue-48109.rs create mode 100644 tests/ui/closures/issue-52437.rs create mode 100644 tests/ui/closures/issue-52437.stderr create mode 100644 tests/ui/closures/issue-67123.rs create mode 100644 tests/ui/closures/issue-67123.stderr create mode 100644 tests/ui/closures/issue-6801.rs create mode 100644 tests/ui/closures/issue-6801.stderr create mode 100644 tests/ui/closures/issue-68025.rs create mode 100644 tests/ui/closures/issue-72408-nested-closures-exponential.rs create mode 100644 tests/ui/closures/issue-78720.rs create mode 100644 tests/ui/closures/issue-78720.stderr create mode 100644 tests/ui/closures/issue-80313-mutable-borrow-in-closure.rs create mode 100644 tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr create mode 100644 tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs create mode 100644 tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr create mode 100644 tests/ui/closures/issue-80313-mutation-in-closure.rs create mode 100644 tests/ui/closures/issue-80313-mutation-in-closure.stderr create mode 100644 tests/ui/closures/issue-80313-mutation-in-move-closure.rs create mode 100644 tests/ui/closures/issue-80313-mutation-in-move-closure.stderr create mode 100644 tests/ui/closures/issue-81700-mut-borrow.rs create mode 100644 tests/ui/closures/issue-81700-mut-borrow.stderr create mode 100644 tests/ui/closures/issue-82438-mut-without-upvar.rs create mode 100644 tests/ui/closures/issue-82438-mut-without-upvar.stderr create mode 100644 tests/ui/closures/issue-84044-drop-non-mut.rs create mode 100644 tests/ui/closures/issue-84044-drop-non-mut.stderr create mode 100644 tests/ui/closures/issue-84128.rs create mode 100644 tests/ui/closures/issue-84128.stderr create mode 100644 tests/ui/closures/issue-87461.rs create mode 100644 tests/ui/closures/issue-87461.stderr create mode 100644 tests/ui/closures/issue-87814-1.rs create mode 100644 tests/ui/closures/issue-87814-2.rs create mode 100644 tests/ui/closures/issue-90871.rs create mode 100644 tests/ui/closures/issue-90871.stderr create mode 100644 tests/ui/closures/issue-97607.rs create mode 100644 tests/ui/closures/issue-99565.rs create mode 100644 tests/ui/closures/issue-99565.stderr create mode 100644 tests/ui/closures/local-type-mix.rs create mode 100644 tests/ui/closures/local-type-mix.stderr create mode 100644 tests/ui/closures/multiple-fn-bounds.rs create mode 100644 tests/ui/closures/multiple-fn-bounds.stderr create mode 100644 tests/ui/closures/old-closure-arg-call-as.rs create mode 100644 tests/ui/closures/old-closure-arg.rs create mode 100644 tests/ui/closures/old-closure-explicit-types.rs create mode 100644 tests/ui/closures/old-closure-expr-precedence.rs create mode 100644 tests/ui/closures/old-closure-expr-precedence.stderr create mode 100644 tests/ui/closures/old-closure-expression-remove-semicolon.fixed create mode 100644 tests/ui/closures/old-closure-expression-remove-semicolon.rs create mode 100644 tests/ui/closures/old-closure-expression-remove-semicolon.stderr create mode 100644 tests/ui/closures/old-closure-fn-coerce.rs create mode 100644 tests/ui/closures/old-closure-iter-1.rs create mode 100644 tests/ui/closures/old-closure-iter-2.rs create mode 100644 tests/ui/closures/once-move-out-on-heap.rs create mode 100644 tests/ui/closures/print/closure-print-generic-1.rs create mode 100644 tests/ui/closures/print/closure-print-generic-1.stderr create mode 100644 tests/ui/closures/print/closure-print-generic-2.rs create mode 100644 tests/ui/closures/print/closure-print-generic-2.stderr create mode 100644 tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.rs create mode 100644 tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr create mode 100644 tests/ui/closures/print/closure-print-generic-verbose-1.rs create mode 100644 tests/ui/closures/print/closure-print-generic-verbose-1.stderr create mode 100644 tests/ui/closures/print/closure-print-generic-verbose-2.rs create mode 100644 tests/ui/closures/print/closure-print-generic-verbose-2.stderr create mode 100644 tests/ui/closures/print/closure-print-verbose.rs create mode 100644 tests/ui/closures/print/closure-print-verbose.stderr create mode 100644 tests/ui/closures/semistatement-in-lambda.rs create mode 100644 tests/ui/closures/supertrait-hint-cycle-2.rs create mode 100644 tests/ui/closures/supertrait-hint-cycle-3.rs create mode 100644 tests/ui/closures/supertrait-hint-cycle.rs create mode 100644 tests/ui/closures/supertrait-hint-references-assoc-ty.rs create mode 100644 tests/ui/closures/thir-unsafeck-issue-85871.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs create mode 100644 tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr create mode 100644 tests/ui/codegen/auxiliary/issue-97708-aux.rs create mode 100644 tests/ui/codegen/auxiliary/llvm_pr32379.rs create mode 100644 tests/ui/codegen/init-large-type.rs create mode 100644 tests/ui/codegen/issue-101585-128bit-repeat.rs create mode 100644 tests/ui/codegen/issue-16602-1.rs create mode 100644 tests/ui/codegen/issue-16602-2.rs create mode 100644 tests/ui/codegen/issue-16602-3.rs create mode 100644 tests/ui/codegen/issue-28950.rs create mode 100644 tests/ui/codegen/issue-55976.rs create mode 100644 tests/ui/codegen/issue-63787.rs create mode 100644 tests/ui/codegen/issue-64401.rs create mode 100644 tests/ui/codegen/issue-82859-slice-miscompile.rs create mode 100644 tests/ui/codegen/issue-88043-bb-does-not-have-terminator.rs create mode 100644 tests/ui/codegen/issue-97708.rs create mode 100644 tests/ui/codegen/issue-99551.rs create mode 100644 tests/ui/codegen/llvm-pr32379.rs create mode 100644 tests/ui/codemap_tests/bad-format-args.rs create mode 100644 tests/ui/codemap_tests/bad-format-args.stderr create mode 100644 tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs create mode 100644 tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr create mode 100644 tests/ui/codemap_tests/empty_span.rs create mode 100644 tests/ui/codemap_tests/empty_span.stderr create mode 100644 tests/ui/codemap_tests/huge_multispan_highlight.rs create mode 100644 tests/ui/codemap_tests/huge_multispan_highlight.stderr create mode 100644 tests/ui/codemap_tests/issue-11715.rs create mode 100644 tests/ui/codemap_tests/issue-11715.stderr create mode 100644 tests/ui/codemap_tests/issue-28308.rs create mode 100644 tests/ui/codemap_tests/issue-28308.stderr create mode 100644 tests/ui/codemap_tests/one_line.rs create mode 100644 tests/ui/codemap_tests/one_line.stderr create mode 100644 tests/ui/codemap_tests/overlapping_inherent_impls.rs create mode 100644 tests/ui/codemap_tests/overlapping_inherent_impls.stderr create mode 100644 tests/ui/codemap_tests/tab.rs create mode 100644 tests/ui/codemap_tests/tab.stderr create mode 100644 tests/ui/codemap_tests/tab_2.rs create mode 100644 tests/ui/codemap_tests/tab_2.stderr create mode 100644 tests/ui/codemap_tests/tab_3.rs create mode 100644 tests/ui/codemap_tests/tab_3.stderr create mode 100644 tests/ui/codemap_tests/two_files.rs create mode 100644 tests/ui/codemap_tests/two_files.stderr create mode 100644 tests/ui/codemap_tests/two_files_data.rs create mode 100644 tests/ui/codemap_tests/unicode.expanded.stdout create mode 100644 tests/ui/codemap_tests/unicode.normal.stderr create mode 100644 tests/ui/codemap_tests/unicode.rs create mode 100644 tests/ui/codemap_tests/unicode_2.rs create mode 100644 tests/ui/codemap_tests/unicode_2.stderr create mode 100644 tests/ui/codemap_tests/unicode_3.rs create mode 100644 tests/ui/codemap_tests/unicode_3.stderr create mode 100644 tests/ui/coercion/auxiliary/issue-39823.rs create mode 100644 tests/ui/coercion/coerce-block-tail-26978.rs create mode 100644 tests/ui/coercion/coerce-block-tail-26978.stderr create mode 100644 tests/ui/coercion/coerce-block-tail-57749.rs create mode 100644 tests/ui/coercion/coerce-block-tail-57749.stderr create mode 100644 tests/ui/coercion/coerce-block-tail-83783.rs create mode 100644 tests/ui/coercion/coerce-block-tail-83783.stderr create mode 100644 tests/ui/coercion/coerce-block-tail-83850.rs create mode 100644 tests/ui/coercion/coerce-block-tail-83850.stderr create mode 100644 tests/ui/coercion/coerce-block-tail.rs create mode 100644 tests/ui/coercion/coerce-block-tail.stderr create mode 100644 tests/ui/coercion/coerce-expect-unsized-ascribed.rs create mode 100644 tests/ui/coercion/coerce-expect-unsized-ascribed.stderr create mode 100644 tests/ui/coercion/coerce-expect-unsized.rs create mode 100644 tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr create mode 100644 tests/ui/coercion/coerce-issue-49593-box-never-windows.rs create mode 100644 tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr create mode 100644 tests/ui/coercion/coerce-issue-49593-box-never.rs create mode 100644 tests/ui/coercion/coerce-mut.rs create mode 100644 tests/ui/coercion/coerce-mut.stderr create mode 100644 tests/ui/coercion/coerce-overloaded-autoderef-fail.rs create mode 100644 tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr create mode 100644 tests/ui/coercion/coerce-overloaded-autoderef.rs create mode 100644 tests/ui/coercion/coerce-reborrow-imm-ptr-arg.rs create mode 100644 tests/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs create mode 100644 tests/ui/coercion/coerce-reborrow-imm-vec-arg.rs create mode 100644 tests/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs create mode 100644 tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs create mode 100644 tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr create mode 100644 tests/ui/coercion/coerce-reborrow-multi-arg.rs create mode 100644 tests/ui/coercion/coerce-reborrow-mut-ptr-arg.rs create mode 100644 tests/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs create mode 100644 tests/ui/coercion/coerce-reborrow-mut-vec-arg.rs create mode 100644 tests/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs create mode 100644 tests/ui/coercion/coerce-to-bang-cast.rs create mode 100644 tests/ui/coercion/coerce-to-bang-cast.stderr create mode 100644 tests/ui/coercion/coerce-to-bang.rs create mode 100644 tests/ui/coercion/coerce-to-bang.stderr create mode 100644 tests/ui/coercion/coerce-unify-return.rs create mode 100644 tests/ui/coercion/coerce-unify.rs create mode 100644 tests/ui/coercion/coerce-unsize-subtype.rs create mode 100644 tests/ui/coercion/coercion-missing-tail-expected-type.fixed create mode 100644 tests/ui/coercion/coercion-missing-tail-expected-type.rs create mode 100644 tests/ui/coercion/coercion-missing-tail-expected-type.stderr create mode 100644 tests/ui/coercion/coercion-slice.rs create mode 100644 tests/ui/coercion/coercion-slice.stderr create mode 100644 tests/ui/coercion/issue-101066.rs create mode 100644 tests/ui/coercion/issue-14589.rs create mode 100644 tests/ui/coercion/issue-36007.rs create mode 100644 tests/ui/coercion/issue-37655.rs create mode 100644 tests/ui/coercion/issue-39823.rs create mode 100644 tests/ui/coercion/issue-53475.rs create mode 100644 tests/ui/coercion/issue-53475.stderr create mode 100644 tests/ui/coercion/issue-73886.rs create mode 100644 tests/ui/coercion/issue-73886.stderr create mode 100644 tests/ui/coercion/issue-88097.rs create mode 100644 tests/ui/coercion/retslot-cast.rs create mode 100644 tests/ui/coercion/retslot-cast.stderr create mode 100644 tests/ui/coercion/unsafe-coercion.rs create mode 100644 tests/ui/coherence/auxiliary/coherence_copy_like_lib.rs create mode 100644 tests/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs create mode 100644 tests/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs create mode 100644 tests/ui/coherence/auxiliary/coherence_lib.rs create mode 100644 tests/ui/coherence/auxiliary/coherence_orphan_lib.rs create mode 100644 tests/ui/coherence/auxiliary/error_lib.rs create mode 100644 tests/ui/coherence/auxiliary/go_trait.rs create mode 100644 tests/ui/coherence/auxiliary/option_future.rs create mode 100644 tests/ui/coherence/auxiliary/re_rebalance_coherence_lib-rpass.rs create mode 100644 tests/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs create mode 100644 tests/ui/coherence/auxiliary/trait-with-const-param.rs create mode 100644 tests/ui/coherence/auxiliary/trait_impl_conflict.rs create mode 100644 tests/ui/coherence/coherence-all-remote.rs create mode 100644 tests/ui/coherence/coherence-all-remote.stderr create mode 100644 tests/ui/coherence/coherence-bigint-int.rs create mode 100644 tests/ui/coherence/coherence-bigint-param.rs create mode 100644 tests/ui/coherence/coherence-bigint-param.stderr create mode 100644 tests/ui/coherence/coherence-bigint-vecint.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific.rs create mode 100644 tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr create mode 100644 tests/ui/coherence/coherence-blanket.rs create mode 100644 tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs create mode 100644 tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr create mode 100644 tests/ui/coherence/coherence-covered-type-parameter.rs create mode 100644 tests/ui/coherence/coherence-cow.re_a.stderr create mode 100644 tests/ui/coherence/coherence-cow.re_b.stderr create mode 100644 tests/ui/coherence/coherence-cow.re_c.stderr create mode 100644 tests/ui/coherence/coherence-cow.rs create mode 100644 tests/ui/coherence/coherence-cross-crate-conflict.rs create mode 100644 tests/ui/coherence/coherence-cross-crate-conflict.stderr create mode 100644 tests/ui/coherence/coherence-default-trait-impl.rs create mode 100644 tests/ui/coherence/coherence-default-trait-impl.stderr create mode 100644 tests/ui/coherence/coherence-error-suppression.rs create mode 100644 tests/ui/coherence/coherence-error-suppression.stderr create mode 100644 tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs create mode 100644 tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr create mode 100644 tests/ui/coherence/coherence-fn-implied-bounds.rs create mode 100644 tests/ui/coherence/coherence-fn-implied-bounds.stderr create mode 100644 tests/ui/coherence/coherence-fn-inputs.rs create mode 100644 tests/ui/coherence/coherence-fn-inputs.stderr create mode 100644 tests/ui/coherence/coherence-free-vs-bound-region.rs create mode 100644 tests/ui/coherence/coherence-free-vs-bound-region.stderr create mode 100644 tests/ui/coherence/coherence-fundamental-trait-objects.rs create mode 100644 tests/ui/coherence/coherence-fundamental-trait-objects.stderr create mode 100644 tests/ui/coherence/coherence-impl-in-fn.rs create mode 100644 tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs create mode 100644 tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr create mode 100644 tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs create mode 100644 tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr create mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs create mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr create mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait.rs create mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait.stderr create mode 100644 tests/ui/coherence/coherence-impls-copy.rs create mode 100644 tests/ui/coherence/coherence-impls-copy.stderr create mode 100644 tests/ui/coherence/coherence-impls-send.rs create mode 100644 tests/ui/coherence/coherence-impls-send.stderr create mode 100644 tests/ui/coherence/coherence-impls-sized.rs create mode 100644 tests/ui/coherence/coherence-impls-sized.stderr create mode 100644 tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs create mode 100644 tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr create mode 100644 tests/ui/coherence/coherence-inherited-subtyping.old.stderr create mode 100644 tests/ui/coherence/coherence-inherited-subtyping.re.stderr create mode 100644 tests/ui/coherence/coherence-inherited-subtyping.rs create mode 100644 tests/ui/coherence/coherence-iterator-vec-any-elem.rs create mode 100644 tests/ui/coherence/coherence-iterator-vec.rs create mode 100644 tests/ui/coherence/coherence-lone-type-parameter.rs create mode 100644 tests/ui/coherence/coherence-lone-type-parameter.stderr create mode 100644 tests/ui/coherence/coherence-multidispatch-tuple.rs create mode 100644 tests/ui/coherence/coherence-negative-impls-copy-bad.rs create mode 100644 tests/ui/coherence/coherence-negative-impls-copy-bad.stderr create mode 100644 tests/ui/coherence/coherence-negative-impls-copy.rs create mode 100644 tests/ui/coherence/coherence-negative-impls-safe-rpass.rs create mode 100644 tests/ui/coherence/coherence-negative-impls-safe.rs create mode 100644 tests/ui/coherence/coherence-negative-impls-safe.stderr create mode 100644 tests/ui/coherence/coherence-negative-inherent-where-bounds.rs create mode 100644 tests/ui/coherence/coherence-negative-inherent.rs create mode 100644 tests/ui/coherence/coherence-negative-outlives-lifetimes.rs create mode 100644 tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr create mode 100644 tests/ui/coherence/coherence-no-direct-lifetime-dispatch.rs create mode 100644 tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr create mode 100644 tests/ui/coherence/coherence-orphan.rs create mode 100644 tests/ui/coherence/coherence-orphan.stderr create mode 100644 tests/ui/coherence/coherence-overlap-all-t-and-tuple.rs create mode 100644 tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr create mode 100644 tests/ui/coherence/coherence-overlap-double-negative.rs create mode 100644 tests/ui/coherence/coherence-overlap-downstream-inherent.rs create mode 100644 tests/ui/coherence/coherence-overlap-downstream-inherent.stderr create mode 100644 tests/ui/coherence/coherence-overlap-downstream.rs create mode 100644 tests/ui/coherence/coherence-overlap-downstream.stderr create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516.rs create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516.stderr create mode 100644 tests/ui/coherence/coherence-overlap-messages.rs create mode 100644 tests/ui/coherence/coherence-overlap-messages.stderr create mode 100644 tests/ui/coherence/coherence-overlap-negate-alias-strict.rs create mode 100644 tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs create mode 100644 tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr create mode 100644 tests/ui/coherence/coherence-overlap-negate-strict.rs create mode 100644 tests/ui/coherence/coherence-overlap-negate-use-feature-gate.rs create mode 100644 tests/ui/coherence/coherence-overlap-negative-trait.rs create mode 100644 tests/ui/coherence/coherence-overlap-negative-trait2.rs create mode 100644 tests/ui/coherence/coherence-overlap-super-negative.rs create mode 100644 tests/ui/coherence/coherence-overlap-trait-alias.rs create mode 100644 tests/ui/coherence/coherence-overlap-trait-alias.stderr create mode 100644 tests/ui/coherence/coherence-overlap-upstream-inherent.rs create mode 100644 tests/ui/coherence/coherence-overlap-upstream-inherent.stderr create mode 100644 tests/ui/coherence/coherence-overlap-upstream.rs create mode 100644 tests/ui/coherence/coherence-overlap-upstream.stderr create mode 100644 tests/ui/coherence/coherence-overlap-with-regions.rs create mode 100644 tests/ui/coherence/coherence-overlapping-pairs.rs create mode 100644 tests/ui/coherence/coherence-overlapping-pairs.stderr create mode 100644 tests/ui/coherence/coherence-pair-covered-uncovered-1.rs create mode 100644 tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr create mode 100644 tests/ui/coherence/coherence-pair-covered-uncovered.rs create mode 100644 tests/ui/coherence/coherence-pair-covered-uncovered.stderr create mode 100644 tests/ui/coherence/coherence-projection-conflict-orphan.rs create mode 100644 tests/ui/coherence/coherence-projection-conflict-orphan.stderr create mode 100644 tests/ui/coherence/coherence-projection-conflict-ty-param.rs create mode 100644 tests/ui/coherence/coherence-projection-conflict-ty-param.stderr create mode 100644 tests/ui/coherence/coherence-projection-conflict.rs create mode 100644 tests/ui/coherence/coherence-projection-conflict.stderr create mode 100644 tests/ui/coherence/coherence-projection-ok-orphan.rs create mode 100644 tests/ui/coherence/coherence-projection-ok.rs create mode 100644 tests/ui/coherence/coherence-rfc447-constrained.rs create mode 100644 tests/ui/coherence/coherence-subtyping.rs create mode 100644 tests/ui/coherence/coherence-subtyping.stderr create mode 100644 tests/ui/coherence/coherence-tuple-conflict.rs create mode 100644 tests/ui/coherence/coherence-tuple-conflict.stderr create mode 100644 tests/ui/coherence/coherence-unsafe-trait-object-impl.rs create mode 100644 tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr create mode 100644 tests/ui/coherence/coherence-vec-local-2.rs create mode 100644 tests/ui/coherence/coherence-vec-local-2.stderr create mode 100644 tests/ui/coherence/coherence-vec-local.rs create mode 100644 tests/ui/coherence/coherence-vec-local.stderr create mode 100644 tests/ui/coherence/coherence-wasm-bindgen.rs create mode 100644 tests/ui/coherence/coherence-wasm-bindgen.stderr create mode 100644 tests/ui/coherence/coherence-where-clause.rs create mode 100644 tests/ui/coherence/coherence-with-closure.rs create mode 100644 tests/ui/coherence/coherence-with-closure.stderr create mode 100644 tests/ui/coherence/coherence-with-generator.rs create mode 100644 tests/ui/coherence/coherence-with-generator.stock.stderr create mode 100644 tests/ui/coherence/coherence_copy_like.rs create mode 100644 tests/ui/coherence/coherence_copy_like_err_fundamental_struct.rs create mode 100644 tests/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs create mode 100644 tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs create mode 100644 tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr create mode 100644 tests/ui/coherence/coherence_copy_like_err_struct.rs create mode 100644 tests/ui/coherence/coherence_copy_like_err_struct.stderr create mode 100644 tests/ui/coherence/coherence_copy_like_err_tuple.rs create mode 100644 tests/ui/coherence/coherence_copy_like_err_tuple.stderr create mode 100644 tests/ui/coherence/coherence_inherent.rs create mode 100644 tests/ui/coherence/coherence_inherent.stderr create mode 100644 tests/ui/coherence/coherence_inherent_cc.rs create mode 100644 tests/ui/coherence/coherence_inherent_cc.stderr create mode 100644 tests/ui/coherence/coherence_local.rs create mode 100644 tests/ui/coherence/coherence_local_err_struct.rs create mode 100644 tests/ui/coherence/coherence_local_err_struct.stderr create mode 100644 tests/ui/coherence/coherence_local_err_tuple.rs create mode 100644 tests/ui/coherence/coherence_local_err_tuple.stderr create mode 100644 tests/ui/coherence/coherence_local_ref.rs create mode 100644 tests/ui/coherence/conflicting-impl-with-err.rs create mode 100644 tests/ui/coherence/conflicting-impl-with-err.stderr create mode 100644 tests/ui/coherence/const-generics-orphan-check-ok.rs create mode 100644 tests/ui/coherence/deep-bad-copy-reason.rs create mode 100644 tests/ui/coherence/deep-bad-copy-reason.stderr create mode 100644 tests/ui/coherence/impl-foreign-for-foreign.rs create mode 100644 tests/ui/coherence/impl-foreign-for-foreign.stderr create mode 100644 tests/ui/coherence/impl-foreign-for-foreign[foreign].rs create mode 100644 tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr create mode 100644 tests/ui/coherence/impl-foreign-for-foreign[local].rs create mode 100644 tests/ui/coherence/impl-foreign-for-fundamental[foreign].rs create mode 100644 tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr create mode 100644 tests/ui/coherence/impl-foreign-for-fundamental[local].rs create mode 100644 tests/ui/coherence/impl-foreign-for-local.rs create mode 100644 tests/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs create mode 100644 tests/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs create mode 100644 tests/ui/coherence/impl-foreign[foreign]-for-foreign.rs create mode 100644 tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr create mode 100644 tests/ui/coherence/impl-foreign[foreign]-for-local.rs create mode 100644 tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs create mode 100644 tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr create mode 100644 tests/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign-for-foreign[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr create mode 100644 tests/ui/coherence/impl[t]-foreign-for-fundamental[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[foreign]-for-t.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-local.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-t.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-foreign.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-local.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-t.rs create mode 100644 tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr create mode 100644 tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs create mode 100644 tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr create mode 100644 tests/ui/coherence/issue-85026.rs create mode 100644 tests/ui/coherence/issue-85026.stderr create mode 100644 tests/ui/coherence/issue-99663-2.rs create mode 100644 tests/ui/coherence/issue-99663.rs create mode 100644 tests/ui/coherence/re-rebalance-coherence-default-generic-associated-type.rs create mode 100644 tests/ui/coherence/re-rebalance-coherence.rs create mode 100644 tests/ui/coherence/strict-coherence-needs-negative-coherence.rs create mode 100644 tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr create mode 100644 tests/ui/command-line-diagnostics.rs create mode 100644 tests/ui/command-line-diagnostics.stderr create mode 100644 tests/ui/command/command-argv0.rs create mode 100644 tests/ui/command/command-create-pidfd.rs create mode 100644 tests/ui/command/command-current-dir.rs create mode 100644 tests/ui/command/command-exec.rs create mode 100644 tests/ui/command/command-pre-exec.rs create mode 100644 tests/ui/command/command-setgroups.rs create mode 100644 tests/ui/command/command-uid-gid.rs create mode 100644 tests/ui/command/issue-10626.rs create mode 100644 tests/ui/commandline-argfile-badutf8.args create mode 100644 tests/ui/commandline-argfile-badutf8.rs create mode 100644 tests/ui/commandline-argfile-badutf8.stderr create mode 100644 tests/ui/commandline-argfile-missing.rs create mode 100644 tests/ui/commandline-argfile-missing.stderr create mode 100644 tests/ui/commandline-argfile.args create mode 100644 tests/ui/commandline-argfile.rs create mode 100644 tests/ui/compare-method/bad-self-type.rs create mode 100644 tests/ui/compare-method/bad-self-type.stderr create mode 100644 tests/ui/compare-method/issue-90444.rs create mode 100644 tests/ui/compare-method/issue-90444.stderr create mode 100644 tests/ui/compare-method/proj-outlives-region.rs create mode 100644 tests/ui/compare-method/proj-outlives-region.stderr create mode 100644 tests/ui/compare-method/region-extra-2.rs create mode 100644 tests/ui/compare-method/region-extra-2.stderr create mode 100644 tests/ui/compare-method/region-extra.rs create mode 100644 tests/ui/compare-method/region-extra.stderr create mode 100644 tests/ui/compare-method/region-unrelated.rs create mode 100644 tests/ui/compare-method/region-unrelated.stderr create mode 100644 tests/ui/compare-method/reordered-type-param.rs create mode 100644 tests/ui/compare-method/reordered-type-param.stderr create mode 100644 tests/ui/compare-method/trait-bound-on-type-parameter.rs create mode 100644 tests/ui/compare-method/trait-bound-on-type-parameter.stderr create mode 100644 tests/ui/compare-method/traits-misc-mismatch-1.rs create mode 100644 tests/ui/compare-method/traits-misc-mismatch-1.stderr create mode 100644 tests/ui/compare-method/traits-misc-mismatch-2.rs create mode 100644 tests/ui/compare-method/traits-misc-mismatch-2.stderr create mode 100644 tests/ui/compile_error_macro.rs create mode 100644 tests/ui/compile_error_macro.stderr create mode 100644 tests/ui/compiletest-self-test/compile-flags-last.rs create mode 100644 tests/ui/compiletest-self-test/compile-flags-last.stderr create mode 100644 tests/ui/compiletest-self-test/ui-testing-optout.rs create mode 100644 tests/ui/compiletest-self-test/ui-testing-optout.stderr create mode 100644 tests/ui/complex.rs create mode 100644 tests/ui/conditional-compilation/auxiliary/namespaced_enums.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-1.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-1.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-2.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-2.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-3.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-3.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-4.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-4.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-5.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-5.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-6.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-6.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-7.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-7.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-8.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-8.stderr create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-9.rs create mode 100644 tests/ui/conditional-compilation/cfg-arg-invalid-9.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-cfg-2.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-crate-2.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-crate-2.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-empty-is-unused.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-false.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-true.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-multi-true.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-parse.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-parse.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr create mode 100644 tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr create mode 100644 tests/ui/conditional-compilation/cfg-empty-codemap.rs create mode 100644 tests/ui/conditional-compilation/cfg-empty-codemap.stderr create mode 100644 tests/ui/conditional-compilation/cfg-generic-params.rs create mode 100644 tests/ui/conditional-compilation/cfg-generic-params.stderr create mode 100644 tests/ui/conditional-compilation/cfg-in-crate-1.rs create mode 100644 tests/ui/conditional-compilation/cfg-in-crate-1.stderr create mode 100644 tests/ui/conditional-compilation/cfg-non-opt-expr.rs create mode 100644 tests/ui/conditional-compilation/cfg-non-opt-expr.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible-bugs.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible-bugs.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible-input-validation.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible-input-validation.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2015.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2021.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible-not_sure.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible-private.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible-stuck.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible-stuck.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible-unstable.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible-unstable.stderr create mode 100644 tests/ui/conditional-compilation/cfg_accessible.rs create mode 100644 tests/ui/conditional-compilation/cfg_accessible.stderr create mode 100644 tests/ui/conditional-compilation/cfg_attr_path.rs create mode 100644 tests/ui/conditional-compilation/inner-cfg-non-inline-mod.rs create mode 100644 tests/ui/conditional-compilation/issue-34028.rs create mode 100644 tests/ui/conditional-compilation/module_with_cfg.rs create mode 100644 tests/ui/conditional-compilation/test-cfg.rs create mode 100644 tests/ui/conditional-compilation/test-cfg.stderr create mode 100644 tests/ui/conflicting-repr-hints.rs create mode 100644 tests/ui/conflicting-repr-hints.stderr create mode 100644 tests/ui/confuse-field-and-method/issue-18343.rs create mode 100644 tests/ui/confuse-field-and-method/issue-18343.stderr create mode 100644 tests/ui/confuse-field-and-method/issue-2392.rs create mode 100644 tests/ui/confuse-field-and-method/issue-2392.stderr create mode 100644 tests/ui/confuse-field-and-method/issue-32128.rs create mode 100644 tests/ui/confuse-field-and-method/issue-32128.stderr create mode 100644 tests/ui/confuse-field-and-method/issue-33784.rs create mode 100644 tests/ui/confuse-field-and-method/issue-33784.stderr create mode 100644 tests/ui/confuse-field-and-method/private-field.rs create mode 100644 tests/ui/confuse-field-and-method/private-field.stderr create mode 100644 tests/ui/conservative_impl_trait.rs create mode 100644 tests/ui/conservative_impl_trait.stderr create mode 100644 tests/ui/const-generics/apit-with-const-param.rs create mode 100644 tests/ui/const-generics/arg-in-pat-1.rs create mode 100644 tests/ui/const-generics/arg-in-pat-2.rs create mode 100644 tests/ui/const-generics/arg-in-pat-3.rs create mode 100644 tests/ui/const-generics/argument_order.rs create mode 100644 tests/ui/const-generics/argument_order.stderr create mode 100644 tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs create mode 100644 tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs create mode 100644 tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs create mode 100644 tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs create mode 100644 tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs create mode 100644 tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs create mode 100644 tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs create mode 100644 tests/ui/const-generics/array-wrapper-struct-ctor.rs create mode 100644 tests/ui/const-generics/assoc_const_eq_diagnostic.rs create mode 100644 tests/ui/const-generics/assoc_const_eq_diagnostic.stderr create mode 100644 tests/ui/const-generics/associated-type-bound-fail.rs create mode 100644 tests/ui/const-generics/associated-type-bound-fail.stderr create mode 100644 tests/ui/const-generics/associated-type-bound.rs create mode 100644 tests/ui/const-generics/auxiliary/const_generic_lib.rs create mode 100644 tests/ui/const-generics/auxiliary/crayte.rs create mode 100644 tests/ui/const-generics/auxiliary/generics_of_parent.rs create mode 100644 tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs create mode 100644 tests/ui/const-generics/auxiliary/legacy-const-generics.rs create mode 100644 tests/ui/const-generics/backcompat/trait-resolution-breakage.rs create mode 100644 tests/ui/const-generics/backcompat/unevaluated-consts.rs create mode 100644 tests/ui/const-generics/bad-const-generic-exprs.rs create mode 100644 tests/ui/const-generics/bad-const-generic-exprs.stderr create mode 100644 tests/ui/const-generics/broken-mir-1.rs create mode 100644 tests/ui/const-generics/broken-mir-2.rs create mode 100644 tests/ui/const-generics/cannot-infer-type-for-const-param.rs create mode 100644 tests/ui/const-generics/coerce_unsized_array.rs create mode 100644 tests/ui/const-generics/concrete-const-as-fn-arg.rs create mode 100644 tests/ui/const-generics/concrete-const-impl-method.rs create mode 100644 tests/ui/const-generics/condition-in-trait-const-arg.rs create mode 100644 tests/ui/const-generics/const-arg-in-const-arg.full.stderr create mode 100644 tests/ui/const-generics/const-arg-in-const-arg.min.stderr create mode 100644 tests/ui/const-generics/const-arg-in-const-arg.rs create mode 100644 tests/ui/const-generics/const-arg-in-fn.rs create mode 100644 tests/ui/const-generics/const-arg-type-arg-misordered.rs create mode 100644 tests/ui/const-generics/const-arg-type-arg-misordered.stderr create mode 100644 tests/ui/const-generics/const-argument-cross-crate-mismatch.rs create mode 100644 tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr create mode 100644 tests/ui/const-generics/const-argument-cross-crate.rs create mode 100644 tests/ui/const-generics/const-argument-if-length.full.stderr create mode 100644 tests/ui/const-generics/const-argument-if-length.min.stderr create mode 100644 tests/ui/const-generics/const-argument-if-length.rs create mode 100644 tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr create mode 100644 tests/ui/const-generics/const-argument-non-static-lifetime.rs create mode 100644 tests/ui/const-generics/const-fn-with-const-param.rs create mode 100644 tests/ui/const-generics/const-generic-default-wont-borrowck.rs create mode 100644 tests/ui/const-generics/const-generic-default-wont-borrowck.stderr create mode 100644 tests/ui/const-generics/const-generic-function.rs create mode 100644 tests/ui/const-generics/const-generic-function.stderr create mode 100644 tests/ui/const-generics/const-generic-type_name.rs create mode 100644 tests/ui/const-generics/const-param-after-const-literal-arg.rs create mode 100644 tests/ui/const-generics/const-param-before-other-params.rs create mode 100644 tests/ui/const-generics/const-param-before-other-params.stderr create mode 100644 tests/ui/const-generics/const-param-elided-lifetime.full.stderr create mode 100644 tests/ui/const-generics/const-param-elided-lifetime.min.stderr create mode 100644 tests/ui/const-generics/const-param-elided-lifetime.rs create mode 100644 tests/ui/const-generics/const-param-in-async.rs create mode 100644 tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr create mode 100644 tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr create mode 100644 tests/ui/const-generics/const-param-type-depends-on-const-param.rs create mode 100644 tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs create mode 100644 tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr create mode 100644 tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr create mode 100644 tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr create mode 100644 tests/ui/const-generics/const-param-type-depends-on-type-param.rs create mode 100644 tests/ui/const-generics/const-parameter-uppercase-lint.rs create mode 100644 tests/ui/const-generics/const-parameter-uppercase-lint.stderr create mode 100644 tests/ui/const-generics/const_trait_fn-issue-88433.rs create mode 100644 tests/ui/const-generics/core-types.rs create mode 100644 tests/ui/const-generics/cross_crate_complex.rs create mode 100644 tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs create mode 100644 tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs create mode 100644 tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr create mode 100644 tests/ui/const-generics/defaults/complex-generic-default-expr.rs create mode 100644 tests/ui/const-generics/defaults/complex-unord-param.rs create mode 100644 tests/ui/const-generics/defaults/const-default.rs create mode 100644 tests/ui/const-generics/defaults/const-param-as-default-value.rs create mode 100644 tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs create mode 100644 tests/ui/const-generics/defaults/default-annotation.rs create mode 100644 tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs create mode 100644 tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr create mode 100644 tests/ui/const-generics/defaults/default-on-impl.rs create mode 100644 tests/ui/const-generics/defaults/default-on-impl.stderr create mode 100644 tests/ui/const-generics/defaults/default-param-wf-concrete.rs create mode 100644 tests/ui/const-generics/defaults/default-param-wf-concrete.stderr create mode 100644 tests/ui/const-generics/defaults/doesnt_infer.rs create mode 100644 tests/ui/const-generics/defaults/doesnt_infer.stderr create mode 100644 tests/ui/const-generics/defaults/external.rs create mode 100644 tests/ui/const-generics/defaults/forward-declared.rs create mode 100644 tests/ui/const-generics/defaults/forward-declared.stderr create mode 100644 tests/ui/const-generics/defaults/generic-expr-default-concrete.rs create mode 100644 tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr create mode 100644 tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs create mode 100644 tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr create mode 100644 tests/ui/const-generics/defaults/generic-expr-default.rs create mode 100644 tests/ui/const-generics/defaults/generic-expr-default.stderr create mode 100644 tests/ui/const-generics/defaults/intermixed-lifetime.rs create mode 100644 tests/ui/const-generics/defaults/intermixed-lifetime.stderr create mode 100644 tests/ui/const-generics/defaults/mismatch.rs create mode 100644 tests/ui/const-generics/defaults/mismatch.stderr create mode 100644 tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs create mode 100644 tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr create mode 100644 tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs create mode 100644 tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr create mode 100644 tests/ui/const-generics/defaults/pretty-printing-ast.rs create mode 100644 tests/ui/const-generics/defaults/pretty-printing-ast.stdout create mode 100644 tests/ui/const-generics/defaults/repr-c-issue-82792.rs create mode 100644 tests/ui/const-generics/defaults/rp_impl_trait.rs create mode 100644 tests/ui/const-generics/defaults/rp_impl_trait_fail.rs create mode 100644 tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr create mode 100644 tests/ui/const-generics/defaults/self-referential.rs create mode 100644 tests/ui/const-generics/defaults/self-referential.stderr create mode 100644 tests/ui/const-generics/defaults/simple-defaults.rs create mode 100644 tests/ui/const-generics/defaults/trait_object_lt_defaults.rs create mode 100644 tests/ui/const-generics/defaults/trait_objects.rs create mode 100644 tests/ui/const-generics/defaults/trait_objects_fail.rs create mode 100644 tests/ui/const-generics/defaults/trait_objects_fail.stderr create mode 100644 tests/ui/const-generics/defaults/type-default-const-param-name.rs create mode 100644 tests/ui/const-generics/defaults/wfness.rs create mode 100644 tests/ui/const-generics/defaults/wfness.stderr create mode 100644 tests/ui/const-generics/defaults/wrong-order.rs create mode 100644 tests/ui/const-generics/defaults/wrong-order.stderr create mode 100644 tests/ui/const-generics/deref-into-array-generic.rs create mode 100644 tests/ui/const-generics/different_generic_args.full.stderr create mode 100644 tests/ui/const-generics/different_generic_args.min.stderr create mode 100644 tests/ui/const-generics/different_generic_args.rs create mode 100644 tests/ui/const-generics/different_generic_args_array.rs create mode 100644 tests/ui/const-generics/different_generic_args_array.stderr create mode 100644 tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs create mode 100644 tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr create mode 100644 tests/ui/const-generics/dyn-supertraits.rs create mode 100644 tests/ui/const-generics/early/closing-args-token.rs create mode 100644 tests/ui/const-generics/early/closing-args-token.stderr create mode 100644 tests/ui/const-generics/early/const-expression-parameter.rs create mode 100644 tests/ui/const-generics/early/const-expression-parameter.stderr create mode 100644 tests/ui/const-generics/early/const-param-from-outer-fn.rs create mode 100644 tests/ui/const-generics/early/const-param-from-outer-fn.stderr create mode 100644 tests/ui/const-generics/early/const-param-hygiene.rs create mode 100644 tests/ui/const-generics/early/const-param-shadowing.rs create mode 100644 tests/ui/const-generics/early/const-param-shadowing.stderr create mode 100644 tests/ui/const-generics/early/invalid-const-arguments.rs create mode 100644 tests/ui/const-generics/early/invalid-const-arguments.stderr create mode 100644 tests/ui/const-generics/early/macro_rules-braces.rs create mode 100644 tests/ui/const-generics/early/macro_rules-braces.stderr create mode 100644 tests/ui/const-generics/ensure_is_evaluatable.rs create mode 100644 tests/ui/const-generics/ensure_is_evaluatable.stderr create mode 100644 tests/ui/const-generics/enum-variants.rs create mode 100644 tests/ui/const-generics/exhaustive-value.rs create mode 100644 tests/ui/const-generics/exhaustive-value.stderr create mode 100644 tests/ui/const-generics/expose-default-substs-param-env.rs create mode 100644 tests/ui/const-generics/float-generic.adt_const_params.stderr create mode 100644 tests/ui/const-generics/float-generic.rs create mode 100644 tests/ui/const-generics/float-generic.simple.stderr create mode 100644 tests/ui/const-generics/fn-const-param-call.full.stderr create mode 100644 tests/ui/const-generics/fn-const-param-call.min.stderr create mode 100644 tests/ui/const-generics/fn-const-param-call.rs create mode 100644 tests/ui/const-generics/fn-const-param-infer.full.stderr create mode 100644 tests/ui/const-generics/fn-const-param-infer.min.stderr create mode 100644 tests/ui/const-generics/fn-const-param-infer.rs create mode 100644 tests/ui/const-generics/fn_with_two_const_inputs.rs create mode 100644 tests/ui/const-generics/fn_with_two_const_inputs.stderr create mode 100644 tests/ui/const-generics/fn_with_two_same_const_inputs.rs create mode 100644 tests/ui/const-generics/forbid-non-structural_match-types.rs create mode 100644 tests/ui/const-generics/forbid-non-structural_match-types.stderr create mode 100644 tests/ui/const-generics/foreign-item-const-parameter.rs create mode 100644 tests/ui/const-generics/foreign-item-const-parameter.stderr create mode 100644 tests/ui/const-generics/generic-param-mismatch.rs create mode 100644 tests/ui/const-generics/generic-param-mismatch.stderr create mode 100644 tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs create mode 100644 tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs create mode 100644 tests/ui/const-generics/generic_arg_infer/in-signature.rs create mode 100644 tests/ui/const-generics/generic_arg_infer/in-signature.stderr create mode 100644 tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs create mode 100644 tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr create mode 100644 tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs create mode 100644 tests/ui/const-generics/generic_arg_infer/issue-91614.rs create mode 100644 tests/ui/const-generics/generic_arg_infer/issue-91614.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/associated-const.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/associated-consts.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/closures.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/closures.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/cross_crate.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/dependence_lint.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/different-fn.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/different-fn.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/division.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/drop_impl.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/eval-privacy.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/fn_call.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/from-sig.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/function-call.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/function-call.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/impl-bounds.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-100217.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-100360.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-102074.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-102768.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-102768.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-105257.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-105257.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-105608.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-105608.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-62504.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-69654.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-69654.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-72787.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-73298.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-73899.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-74634.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-74713.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-74713.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-76595.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-76595.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-80742.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-80742.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-82268.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-83765.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-83765.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-83972.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-84408.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-84669.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-85848.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-85848.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-86710.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-89851.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-90847.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-94287.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-94287.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-94293.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-99647.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/issue-99705.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/less_than.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/let-bindings.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/let-bindings.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/no_dependence.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/no_where_clause.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/obligation-cause.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/simple_fail.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/simple_fail.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/unop.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/unused_expr.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/unused_expr.stderr create mode 100644 tests/ui/const-generics/ice-68875.rs create mode 100644 tests/ui/const-generics/ice-68875.stderr create mode 100644 tests/ui/const-generics/ice-const-generic-function-return-ty.rs create mode 100644 tests/ui/const-generics/ice-const-generic-function-return-ty.stderr create mode 100644 tests/ui/const-generics/impl-const-generic-struct.rs create mode 100644 tests/ui/const-generics/incorrect-number-of-const-args.rs create mode 100644 tests/ui/const-generics/incorrect-number-of-const-args.stderr create mode 100644 tests/ui/const-generics/infer/cannot-infer-const-args.rs create mode 100644 tests/ui/const-generics/infer/cannot-infer-const-args.stderr create mode 100644 tests/ui/const-generics/infer/issue-77092.rs create mode 100644 tests/ui/const-generics/infer/issue-77092.stderr create mode 100644 tests/ui/const-generics/infer/method-chain.rs create mode 100644 tests/ui/const-generics/infer/method-chain.stderr create mode 100644 tests/ui/const-generics/infer/one-param-uninferred.rs create mode 100644 tests/ui/const-generics/infer/one-param-uninferred.stderr create mode 100644 tests/ui/const-generics/infer/uninferred-consts.rs create mode 100644 tests/ui/const-generics/infer/uninferred-consts.stderr create mode 100644 tests/ui/const-generics/infer_arg_from_pat.rs create mode 100644 tests/ui/const-generics/infer_arr_len_from_pat.rs create mode 100644 tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs create mode 100644 tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs create mode 100644 tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs create mode 100644 tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr create mode 100644 tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs create mode 100644 tests/ui/const-generics/invalid-const-arg-for-type-param.rs create mode 100644 tests/ui/const-generics/invalid-const-arg-for-type-param.stderr create mode 100644 tests/ui/const-generics/invalid-constant-in-args.rs create mode 100644 tests/ui/const-generics/invalid-constant-in-args.stderr create mode 100644 tests/ui/const-generics/invalid-enum.rs create mode 100644 tests/ui/const-generics/invalid-enum.stderr create mode 100644 tests/ui/const-generics/invariant.rs create mode 100644 tests/ui/const-generics/invariant.stderr create mode 100644 tests/ui/const-generics/issue-102124.rs create mode 100644 tests/ui/const-generics/issue-105689.rs create mode 100644 tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs create mode 100644 tests/ui/const-generics/issue-46511.rs create mode 100644 tests/ui/const-generics/issue-46511.stderr create mode 100644 tests/ui/const-generics/issue-66451.rs create mode 100644 tests/ui/const-generics/issue-66451.stderr create mode 100644 tests/ui/const-generics/issue-70408.rs create mode 100644 tests/ui/const-generics/issue-80471.rs create mode 100644 tests/ui/const-generics/issue-80471.stderr create mode 100644 tests/ui/const-generics/issue-93647.rs create mode 100644 tests/ui/const-generics/issue-93647.stderr create mode 100644 tests/ui/const-generics/issue-97007.rs create mode 100644 tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs create mode 100644 tests/ui/const-generics/issues/auxiliary/impl-const.rs create mode 100644 tests/ui/const-generics/issues/issue-100313.rs create mode 100644 tests/ui/const-generics/issues/issue-100313.stderr create mode 100644 tests/ui/const-generics/issues/issue-105037.rs create mode 100644 tests/ui/const-generics/issues/issue-56445-1.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-56445-1.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-56445-1.rs create mode 100644 tests/ui/const-generics/issues/issue-56445-2.rs create mode 100644 tests/ui/const-generics/issues/issue-56445-2.stderr create mode 100644 tests/ui/const-generics/issues/issue-56445-3.rs create mode 100644 tests/ui/const-generics/issues/issue-56445-3.stderr create mode 100644 tests/ui/const-generics/issues/issue-60818-struct-constructors.rs create mode 100644 tests/ui/const-generics/issues/issue-61336-1.rs create mode 100644 tests/ui/const-generics/issues/issue-61336-2.rs create mode 100644 tests/ui/const-generics/issues/issue-61336-2.stderr create mode 100644 tests/ui/const-generics/issues/issue-61336.rs create mode 100644 tests/ui/const-generics/issues/issue-61336.stderr create mode 100644 tests/ui/const-generics/issues/issue-61422.rs create mode 100644 tests/ui/const-generics/issues/issue-61432.rs create mode 100644 tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs create mode 100644 tests/ui/const-generics/issues/issue-62878.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-62878.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-62878.rs create mode 100644 tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs create mode 100644 tests/ui/const-generics/issues/issue-64519.rs create mode 100644 tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs create mode 100644 tests/ui/const-generics/issues/issue-66906.rs create mode 100644 tests/ui/const-generics/issues/issue-67185-1.rs create mode 100644 tests/ui/const-generics/issues/issue-67185-2.rs create mode 100644 tests/ui/const-generics/issues/issue-67185-2.stderr create mode 100644 tests/ui/const-generics/issues/issue-67375.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-67375.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-67375.rs create mode 100644 tests/ui/const-generics/issues/issue-67739.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-67739.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-67739.rs create mode 100644 tests/ui/const-generics/issues/issue-67945-1.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-1.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-1.rs create mode 100644 tests/ui/const-generics/issues/issue-67945-2.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-2.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-2.rs create mode 100644 tests/ui/const-generics/issues/issue-67945-3.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-3.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-3.rs create mode 100644 tests/ui/const-generics/issues/issue-67945-4.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-4.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-67945-4.rs create mode 100644 tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs create mode 100644 tests/ui/const-generics/issues/issue-68366.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-68366.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-68366.rs create mode 100644 tests/ui/const-generics/issues/issue-68596.rs create mode 100644 tests/ui/const-generics/issues/issue-68615-adt.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-68615-adt.rs create mode 100644 tests/ui/const-generics/issues/issue-68615-array.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-68615-array.rs create mode 100644 tests/ui/const-generics/issues/issue-69654-run-pass.rs create mode 100644 tests/ui/const-generics/issues/issue-70125-1.rs create mode 100644 tests/ui/const-generics/issues/issue-70125-2.rs create mode 100644 tests/ui/const-generics/issues/issue-70167.rs create mode 100644 tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs create mode 100644 tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs create mode 100644 tests/ui/const-generics/issues/issue-70225.rs create mode 100644 tests/ui/const-generics/issues/issue-70273-assoc-fn.rs create mode 100644 tests/ui/const-generics/issues/issue-71169.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-71169.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-71169.rs create mode 100644 tests/ui/const-generics/issues/issue-71202.rs create mode 100644 tests/ui/const-generics/issues/issue-71202.stderr create mode 100644 tests/ui/const-generics/issues/issue-71381.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-71381.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-71381.rs create mode 100644 tests/ui/const-generics/issues/issue-71382.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-71382.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-71382.rs create mode 100644 tests/ui/const-generics/issues/issue-71547.rs create mode 100644 tests/ui/const-generics/issues/issue-71611.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-71611.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-71611.rs create mode 100644 tests/ui/const-generics/issues/issue-71986.rs create mode 100644 tests/ui/const-generics/issues/issue-72352.full.stderr create mode 100644 tests/ui/const-generics/issues/issue-72352.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-72352.rs create mode 100644 tests/ui/const-generics/issues/issue-72845.rs create mode 100644 tests/ui/const-generics/issues/issue-72845.stderr create mode 100644 tests/ui/const-generics/issues/issue-73120.rs create mode 100644 tests/ui/const-generics/issues/issue-73260.rs create mode 100644 tests/ui/const-generics/issues/issue-73260.stderr create mode 100644 tests/ui/const-generics/issues/issue-73491.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-73491.rs create mode 100644 tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs create mode 100644 tests/ui/const-generics/issues/issue-74101.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-74101.rs create mode 100644 tests/ui/const-generics/issues/issue-74255.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-74255.rs create mode 100644 tests/ui/const-generics/issues/issue-74906.rs create mode 100644 tests/ui/const-generics/issues/issue-74950.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-74950.rs create mode 100644 tests/ui/const-generics/issues/issue-75047.min.stderr create mode 100644 tests/ui/const-generics/issues/issue-75047.rs create mode 100644 tests/ui/const-generics/issues/issue-75299.rs create mode 100644 tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs create mode 100644 tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr create mode 100644 tests/ui/const-generics/issues/issue-77357.rs create mode 100644 tests/ui/const-generics/issues/issue-77357.stderr create mode 100644 tests/ui/const-generics/issues/issue-79674.rs create mode 100644 tests/ui/const-generics/issues/issue-79674.stderr create mode 100644 tests/ui/const-generics/issues/issue-80062.rs create mode 100644 tests/ui/const-generics/issues/issue-80062.stderr create mode 100644 tests/ui/const-generics/issues/issue-80375.rs create mode 100644 tests/ui/const-generics/issues/issue-80375.stderr create mode 100644 tests/ui/const-generics/issues/issue-82956.rs create mode 100644 tests/ui/const-generics/issues/issue-82956.stderr create mode 100644 tests/ui/const-generics/issues/issue-83249.rs create mode 100644 tests/ui/const-generics/issues/issue-83249.stderr create mode 100644 tests/ui/const-generics/issues/issue-83288.rs create mode 100644 tests/ui/const-generics/issues/issue-83466.rs create mode 100644 tests/ui/const-generics/issues/issue-83466.stderr create mode 100644 tests/ui/const-generics/issues/issue-83765.rs create mode 100644 tests/ui/const-generics/issues/issue-83765.stderr create mode 100644 tests/ui/const-generics/issues/issue-83993.rs create mode 100644 tests/ui/const-generics/issues/issue-84659.rs create mode 100644 tests/ui/const-generics/issues/issue-84659.stderr create mode 100644 tests/ui/const-generics/issues/issue-85031-2.rs create mode 100644 tests/ui/const-generics/issues/issue-85031-2.stderr create mode 100644 tests/ui/const-generics/issues/issue-86033.rs create mode 100644 tests/ui/const-generics/issues/issue-86530.rs create mode 100644 tests/ui/const-generics/issues/issue-86530.stderr create mode 100644 tests/ui/const-generics/issues/issue-86535-2.rs create mode 100644 tests/ui/const-generics/issues/issue-86535.rs create mode 100644 tests/ui/const-generics/issues/issue-86820.rs create mode 100644 tests/ui/const-generics/issues/issue-86820.stderr create mode 100644 tests/ui/const-generics/issues/issue-87076.rs create mode 100644 tests/ui/const-generics/issues/issue-87470.rs create mode 100644 tests/ui/const-generics/issues/issue-87493.rs create mode 100644 tests/ui/const-generics/issues/issue-87493.stderr create mode 100644 tests/ui/const-generics/issues/issue-87964.rs create mode 100644 tests/ui/const-generics/issues/issue-88119.rs create mode 100644 tests/ui/const-generics/issues/issue-88468.rs create mode 100644 tests/ui/const-generics/issues/issue-88997.rs create mode 100644 tests/ui/const-generics/issues/issue-88997.stderr create mode 100644 tests/ui/const-generics/issues/issue-89146.rs create mode 100644 tests/ui/const-generics/issues/issue-89304.rs create mode 100644 tests/ui/const-generics/issues/issue-89320.rs create mode 100644 tests/ui/const-generics/issues/issue-89334.rs create mode 100644 tests/ui/const-generics/issues/issue-90318.rs create mode 100644 tests/ui/const-generics/issues/issue-90318.stderr create mode 100644 tests/ui/const-generics/issues/issue-90364.rs create mode 100644 tests/ui/const-generics/issues/issue-90364.stderr create mode 100644 tests/ui/const-generics/issues/issue-90455.rs create mode 100644 tests/ui/const-generics/issues/issue-90455.stderr create mode 100644 tests/ui/const-generics/issues/issue-92186.rs create mode 100644 tests/ui/const-generics/issues/issue-96654.rs create mode 100644 tests/ui/const-generics/issues/issue-97278.rs create mode 100644 tests/ui/const-generics/issues/issue-97278.stderr create mode 100644 tests/ui/const-generics/issues/issue-97634.rs create mode 100644 tests/ui/const-generics/issues/issue-98629.rs create mode 100644 tests/ui/const-generics/issues/issue-98629.stderr create mode 100644 tests/ui/const-generics/issues/issue-99641.rs create mode 100644 tests/ui/const-generics/issues/issue-99641.stderr create mode 100644 tests/ui/const-generics/late-bound-vars/in_closure.rs create mode 100644 tests/ui/const-generics/late-bound-vars/simple.rs create mode 100644 tests/ui/const-generics/legacy-const-generics-bad.rs create mode 100644 tests/ui/const-generics/legacy-const-generics-bad.stderr create mode 100644 tests/ui/const-generics/legacy-const-generics.rs create mode 100644 tests/ui/const-generics/min_const_generics/assoc_const.rs create mode 100644 tests/ui/const-generics/min_const_generics/complex-expression.rs create mode 100644 tests/ui/const-generics/min_const_generics/complex-expression.stderr create mode 100644 tests/ui/const-generics/min_const_generics/complex-types.rs create mode 100644 tests/ui/const-generics/min_const_generics/complex-types.stderr create mode 100644 tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs create mode 100644 tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr create mode 100644 tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs create mode 100644 tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr create mode 100644 tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs create mode 100644 tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr create mode 100644 tests/ui/const-generics/min_const_generics/const_default_first.rs create mode 100644 tests/ui/const-generics/min_const_generics/const_default_first.stderr create mode 100644 tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs create mode 100644 tests/ui/const-generics/min_const_generics/default_function_param.rs create mode 100644 tests/ui/const-generics/min_const_generics/default_function_param.stderr create mode 100644 tests/ui/const-generics/min_const_generics/default_trait_param.rs create mode 100644 tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs create mode 100644 tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr create mode 100644 tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs create mode 100644 tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr create mode 100644 tests/ui/const-generics/min_const_generics/inferred_const.rs create mode 100644 tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr create mode 100644 tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr create mode 100644 tests/ui/const-generics/min_const_generics/invalid-patterns.rs create mode 100644 tests/ui/const-generics/min_const_generics/macro-fail.rs create mode 100644 tests/ui/const-generics/min_const_generics/macro-fail.stderr create mode 100644 tests/ui/const-generics/min_const_generics/macro.rs create mode 100644 tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs create mode 100644 tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr create mode 100644 tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs create mode 100644 tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr create mode 100644 tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs create mode 100644 tests/ui/const-generics/nested-type.full.stderr create mode 100644 tests/ui/const-generics/nested-type.min.stderr create mode 100644 tests/ui/const-generics/nested-type.rs create mode 100644 tests/ui/const-generics/occurs-check/bind-param.rs create mode 100644 tests/ui/const-generics/occurs-check/unify-fixpoint.rs create mode 100644 tests/ui/const-generics/occurs-check/unify-fixpoint.stderr create mode 100644 tests/ui/const-generics/occurs-check/unify-n-nplusone.rs create mode 100644 tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-1.rs create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-1.stderr create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-2.rs create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-2.stderr create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-3.rs create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-3.stderr create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-4.rs create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-4.stderr create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-5.rs create mode 100644 tests/ui/const-generics/occurs-check/unused-substs-5.stderr create mode 100644 tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs create mode 100644 tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr create mode 100644 tests/ui/const-generics/overlapping_impls.rs create mode 100644 tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr create mode 100644 tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr create mode 100644 tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs create mode 100644 tests/ui/const-generics/parent_generics_of_encoding.rs create mode 100644 tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs create mode 100644 tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013.rs create mode 100644 tests/ui/const-generics/parser-error-recovery/issue-89013.stderr create mode 100644 tests/ui/const-generics/projection-as-arg-const.rs create mode 100644 tests/ui/const-generics/projection-as-arg-const.stderr create mode 100644 tests/ui/const-generics/promotion.rs create mode 100644 tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr create mode 100644 tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr create mode 100644 tests/ui/const-generics/raw-ptr-const-param-deref.rs create mode 100644 tests/ui/const-generics/raw-ptr-const-param.full.stderr create mode 100644 tests/ui/const-generics/raw-ptr-const-param.min.stderr create mode 100644 tests/ui/const-generics/raw-ptr-const-param.rs create mode 100644 tests/ui/const-generics/slice-const-param-mismatch.full.stderr create mode 100644 tests/ui/const-generics/slice-const-param-mismatch.min.stderr create mode 100644 tests/ui/const-generics/slice-const-param-mismatch.rs create mode 100644 tests/ui/const-generics/slice-const-param.rs create mode 100644 tests/ui/const-generics/sneaky-array-repeat-expr.rs create mode 100644 tests/ui/const-generics/sneaky-array-repeat-expr.stderr create mode 100644 tests/ui/const-generics/std/const-generics-range.min.stderr create mode 100644 tests/ui/const-generics/std/const-generics-range.rs create mode 100644 tests/ui/const-generics/struct-with-invalid-const-param.rs create mode 100644 tests/ui/const-generics/struct-with-invalid-const-param.stderr create mode 100644 tests/ui/const-generics/suggest_const_for_array.rs create mode 100644 tests/ui/const-generics/suggest_const_for_array.stderr create mode 100644 tests/ui/const-generics/trait-const-args.rs create mode 100644 tests/ui/const-generics/transmute-const-param-static-reference.min.stderr create mode 100644 tests/ui/const-generics/transmute-const-param-static-reference.rs create mode 100644 tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs create mode 100644 tests/ui/const-generics/try_unify_ignore_lifetimes.rs create mode 100644 tests/ui/const-generics/two_matching_preds.rs create mode 100644 tests/ui/const-generics/type-after-const-ok.rs create mode 100644 tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs create mode 100644 tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-61936.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-63695.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-67144-1.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-67144-2.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-69816.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-70217.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-70507.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-70586.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-71348.min.stderr create mode 100644 tests/ui/const-generics/type-dependent/issue-71348.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-71382.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-71382.stderr create mode 100644 tests/ui/const-generics/type-dependent/issue-71805.rs create mode 100644 tests/ui/const-generics/type-dependent/issue-73730.rs create mode 100644 tests/ui/const-generics/type-dependent/non-local.rs create mode 100644 tests/ui/const-generics/type-dependent/qpath.rs create mode 100644 tests/ui/const-generics/type-dependent/simple.rs create mode 100644 tests/ui/const-generics/type-dependent/type-mismatch.full.stderr create mode 100644 tests/ui/const-generics/type-dependent/type-mismatch.min.stderr create mode 100644 tests/ui/const-generics/type-dependent/type-mismatch.rs create mode 100644 tests/ui/const-generics/type_mismatch.rs create mode 100644 tests/ui/const-generics/type_mismatch.stderr create mode 100644 tests/ui/const-generics/type_not_in_scope.rs create mode 100644 tests/ui/const-generics/type_not_in_scope.stderr create mode 100644 tests/ui/const-generics/type_of_anon_const.rs create mode 100644 tests/ui/const-generics/types-mismatch-const-args.full.stderr create mode 100644 tests/ui/const-generics/types-mismatch-const-args.min.stderr create mode 100644 tests/ui/const-generics/types-mismatch-const-args.rs create mode 100644 tests/ui/const-generics/unify_with_nested_expr.rs create mode 100644 tests/ui/const-generics/unify_with_nested_expr.stderr create mode 100644 tests/ui/const-generics/uninferred-consts-during-codegen-1.rs create mode 100644 tests/ui/const-generics/uninferred-consts-during-codegen-2.rs create mode 100644 tests/ui/const-generics/unknown_adt.rs create mode 100644 tests/ui/const-generics/unknown_adt.stderr create mode 100644 tests/ui/const-generics/unused-const-param.rs create mode 100644 tests/ui/const-generics/unused-type-param-suggestion.rs create mode 100644 tests/ui/const-generics/unused-type-param-suggestion.stderr create mode 100644 tests/ui/const-generics/unused_braces.fixed create mode 100644 tests/ui/const-generics/unused_braces.full.fixed create mode 100644 tests/ui/const-generics/unused_braces.min.fixed create mode 100644 tests/ui/const-generics/unused_braces.rs create mode 100644 tests/ui/const-generics/unused_braces.stderr create mode 100644 tests/ui/const-generics/where-clauses.rs create mode 100644 tests/ui/const-ptr/allowed_slices.rs create mode 100644 tests/ui/const-ptr/forbidden_slices.rs create mode 100644 tests/ui/const-ptr/forbidden_slices.stderr create mode 100644 tests/ui/const-ptr/out_of_bounds_read.rs create mode 100644 tests/ui/const-ptr/out_of_bounds_read.stderr create mode 100644 tests/ui/const_prop/ice-assert-fail-div-by-zero.rs create mode 100644 tests/ui/const_prop/ice-assert-fail-div-by-zero.stderr create mode 100644 tests/ui/const_prop/inline_spans.rs create mode 100644 tests/ui/const_prop/inline_spans_lint_attribute.rs create mode 100644 tests/ui/const_prop/issue-102553.rs create mode 100644 tests/ui/constructor-lifetime-args.rs create mode 100644 tests/ui/constructor-lifetime-args.stderr create mode 100644 tests/ui/consts/array-literal-index-oob.rs create mode 100644 tests/ui/consts/array-literal-index-oob.stderr create mode 100644 tests/ui/consts/array-to-slice-cast.rs create mode 100644 tests/ui/consts/assert-type-intrinsics.rs create mode 100644 tests/ui/consts/assert-type-intrinsics.stderr create mode 100644 tests/ui/consts/assoc-const.rs create mode 100644 tests/ui/consts/assoc_const_generic_impl.rs create mode 100644 tests/ui/consts/assoc_const_generic_impl.stderr create mode 100644 tests/ui/consts/associated_const_generic.rs create mode 100644 tests/ui/consts/async-block.rs create mode 100644 tests/ui/consts/async-block.with_feature.stderr create mode 100644 tests/ui/consts/async-block.without_feature.stderr create mode 100644 tests/ui/consts/auxiliary/cci_const_block.rs create mode 100644 tests/ui/consts/auxiliary/closure-in-foreign-crate.rs create mode 100644 tests/ui/consts/auxiliary/const_fn_lib.rs create mode 100644 tests/ui/consts/auxiliary/external_macro.rs create mode 100644 tests/ui/consts/auxiliary/issue-17718-aux.rs create mode 100644 tests/ui/consts/auxiliary/issue-63226.rs create mode 100644 tests/ui/consts/auxiliary/promotable_const_fn_lib.rs create mode 100644 tests/ui/consts/bswap-const.rs create mode 100644 tests/ui/consts/cast-discriminant-zst-enum.rs create mode 100644 tests/ui/consts/chained-constants-stackoverflow.rs create mode 100644 tests/ui/consts/check_const-feature-gated.rs create mode 100644 tests/ui/consts/closure-in-foreign-crate.rs create mode 100644 tests/ui/consts/closure-structural-match-issue-90013.rs create mode 100644 tests/ui/consts/const-address-of-interior-mut.rs create mode 100644 tests/ui/consts/const-address-of-interior-mut.stderr create mode 100644 tests/ui/consts/const-address-of-mut.rs create mode 100644 tests/ui/consts/const-address-of-mut.stderr create mode 100644 tests/ui/consts/const-address-of.rs create mode 100644 tests/ui/consts/const-adt-align-mismatch.rs create mode 100644 tests/ui/consts/const-array-oob-arith.rs create mode 100644 tests/ui/consts/const-array-oob-arith.stderr create mode 100644 tests/ui/consts/const-array-oob.rs create mode 100644 tests/ui/consts/const-array-oob.stderr create mode 100644 tests/ui/consts/const-as-fn.rs create mode 100644 tests/ui/consts/const-as-fn.stderr create mode 100644 tests/ui/consts/const-autoderef.rs create mode 100644 tests/ui/consts/const-big-enum.rs create mode 100644 tests/ui/consts/const-binops.rs create mode 100644 tests/ui/consts/const-bitshift-rhs-inference.rs create mode 100644 tests/ui/consts/const-block-const-bound.rs create mode 100644 tests/ui/consts/const-block-const-bound.stderr create mode 100644 tests/ui/consts/const-block-cross-crate-fn.rs create mode 100644 tests/ui/consts/const-block-item-macro-codegen.rs create mode 100644 tests/ui/consts/const-block-item.rs create mode 100644 tests/ui/consts/const-block-non-item-statement-3.rs create mode 100644 tests/ui/consts/const-block-non-item-statement-rpass.rs create mode 100644 tests/ui/consts/const-block-non-item-statement.rs create mode 100644 tests/ui/consts/const-block.rs create mode 100644 tests/ui/consts/const-blocks/const-repeat.rs create mode 100644 tests/ui/consts/const-blocks/fn-call-in-const.rs create mode 100644 tests/ui/consts/const-blocks/fn-call-in-non-const.rs create mode 100644 tests/ui/consts/const-blocks/fn-call-in-non-const.stderr create mode 100644 tests/ui/consts/const-blocks/migrate-fail.rs create mode 100644 tests/ui/consts/const-blocks/migrate-fail.stderr create mode 100644 tests/ui/consts/const-blocks/migrate-pass.rs create mode 100644 tests/ui/consts/const-blocks/nll-fail.rs create mode 100644 tests/ui/consts/const-blocks/nll-fail.stderr create mode 100644 tests/ui/consts/const-blocks/nll-pass.rs create mode 100644 tests/ui/consts/const-blocks/run-pass.rs create mode 100644 tests/ui/consts/const-blocks/trait-error.rs create mode 100644 tests/ui/consts/const-blocks/trait-error.stderr create mode 100644 tests/ui/consts/const-bound.rs create mode 100644 tests/ui/consts/const-byte-str-cast.rs create mode 100644 tests/ui/consts/const-call.rs create mode 100644 tests/ui/consts/const-call.stderr create mode 100644 tests/ui/consts/const-cast-different-types.rs create mode 100644 tests/ui/consts/const-cast-different-types.stderr create mode 100644 tests/ui/consts/const-cast-ptr-int.rs create mode 100644 tests/ui/consts/const-cast-wrong-type.rs create mode 100644 tests/ui/consts/const-cast-wrong-type.stderr create mode 100644 tests/ui/consts/const-cast.rs create mode 100644 tests/ui/consts/const-const.rs create mode 100644 tests/ui/consts/const-contents.rs create mode 100644 tests/ui/consts/const-deref-ptr.rs create mode 100644 tests/ui/consts/const-deref-ptr.stderr create mode 100644 tests/ui/consts/const-deref.rs create mode 100644 tests/ui/consts/const-endianess.rs create mode 100644 tests/ui/consts/const-enum-byref-self.rs create mode 100644 tests/ui/consts/const-enum-byref.rs create mode 100644 tests/ui/consts/const-enum-cast.rs create mode 100644 tests/ui/consts/const-enum-ptr.rs create mode 100644 tests/ui/consts/const-enum-struct.rs create mode 100644 tests/ui/consts/const-enum-struct2.rs create mode 100644 tests/ui/consts/const-enum-structlike.rs create mode 100644 tests/ui/consts/const-enum-tuple.rs create mode 100644 tests/ui/consts/const-enum-tuple2.rs create mode 100644 tests/ui/consts/const-enum-tuplestruct.rs create mode 100644 tests/ui/consts/const-enum-tuplestruct2.rs create mode 100644 tests/ui/consts/const-enum-vec-index.rs create mode 100644 tests/ui/consts/const-enum-vec-ptr.rs create mode 100644 tests/ui/consts/const-enum-vector.rs create mode 100644 tests/ui/consts/const-err-early.rs create mode 100644 tests/ui/consts/const-err-early.stderr create mode 100644 tests/ui/consts/const-err-late.rs create mode 100644 tests/ui/consts/const-err-late.stderr create mode 100644 tests/ui/consts/const-err-multi.rs create mode 100644 tests/ui/consts/const-err-multi.stderr create mode 100644 tests/ui/consts/const-err-rpass.rs create mode 100644 tests/ui/consts/const-err2.noopt.stderr create mode 100644 tests/ui/consts/const-err2.opt.stderr create mode 100644 tests/ui/consts/const-err2.opt_with_overflow_checks.stderr create mode 100644 tests/ui/consts/const-err2.rs create mode 100644 tests/ui/consts/const-err4.32bit.stderr create mode 100644 tests/ui/consts/const-err4.64bit.stderr create mode 100644 tests/ui/consts/const-err4.rs create mode 100644 tests/ui/consts/const-eval/assign-to-static-within-other-static.rs create mode 100644 tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr create mode 100644 tests/ui/consts/const-eval/auxiliary/post_monomorphization_error.rs create mode 100644 tests/ui/consts/const-eval/auxiliary/stability.rs create mode 100644 tests/ui/consts/const-eval/conditional_array_execution.rs create mode 100644 tests/ui/consts/const-eval/conditional_array_execution.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-intrinsic-promotion.rs create mode 100644 tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-2.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-2.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-3.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-3.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-3b.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-3b.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-4.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-4.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-4b.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow-4b.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow2.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow2.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow2b.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow2b.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-overflow2c.rs create mode 100644 tests/ui/consts/const-eval/const-eval-overflow2c.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-query-stack.rs create mode 100644 tests/ui/consts/const-eval/const-eval-query-stack.stderr create mode 100644 tests/ui/consts/const-eval/const-eval-span.rs create mode 100644 tests/ui/consts/const-eval/const-eval-span.stderr create mode 100644 tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr create mode 100644 tests/ui/consts/const-eval/const-pointer-values-in-various-types.rs create mode 100644 tests/ui/consts/const-eval/const_fn_ptr.rs create mode 100644 tests/ui/consts/const-eval/const_fn_ptr.stderr create mode 100644 tests/ui/consts/const-eval/const_fn_ptr_fail.rs create mode 100644 tests/ui/consts/const-eval/const_fn_ptr_fail.stderr create mode 100644 tests/ui/consts/const-eval/const_fn_ptr_fail2.rs create mode 100644 tests/ui/consts/const-eval/const_fn_ptr_fail2.stderr create mode 100644 tests/ui/consts/const-eval/const_let.rs create mode 100644 tests/ui/consts/const-eval/const_let.stderr create mode 100644 tests/ui/consts/const-eval/const_panic.rs create mode 100644 tests/ui/consts/const-eval/const_panic.stderr create mode 100644 tests/ui/consts/const-eval/const_panic_2021.rs create mode 100644 tests/ui/consts/const-eval/const_panic_2021.stderr create mode 100644 tests/ui/consts/const-eval/const_panic_libcore_bin.rs create mode 100644 tests/ui/consts/const-eval/const_panic_libcore_bin.stderr create mode 100644 tests/ui/consts/const-eval/const_panic_stability.e2018.stderr create mode 100644 tests/ui/consts/const-eval/const_panic_stability.e2021.stderr create mode 100644 tests/ui/consts/const-eval/const_panic_stability.rs create mode 100644 tests/ui/consts/const-eval/const_panic_track_caller.rs create mode 100644 tests/ui/consts/const-eval/const_panic_track_caller.stderr create mode 100644 tests/ui/consts/const-eval/const_prop_errors.rs create mode 100644 tests/ui/consts/const-eval/const_raw_ptr_ops.rs create mode 100644 tests/ui/consts/const-eval/const_raw_ptr_ops.stderr create mode 100644 tests/ui/consts/const-eval/const_raw_ptr_ops2.rs create mode 100644 tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr create mode 100644 tests/ui/consts/const-eval/const_signed_pat.rs create mode 100644 tests/ui/consts/const-eval/dangling.rs create mode 100644 tests/ui/consts/const-eval/dangling.stderr create mode 100644 tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs create mode 100644 tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr create mode 100644 tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs create mode 100644 tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr create mode 100644 tests/ui/consts/const-eval/double_check.rs create mode 100644 tests/ui/consts/const-eval/double_check2.rs create mode 100644 tests/ui/consts/const-eval/duration_conversion.rs create mode 100644 tests/ui/consts/const-eval/enum_discr.rs create mode 100644 tests/ui/consts/const-eval/erroneous-const.rs create mode 100644 tests/ui/consts/const-eval/erroneous-const.stderr create mode 100644 tests/ui/consts/const-eval/erroneous-const2.rs create mode 100644 tests/ui/consts/const-eval/erroneous-const2.stderr create mode 100644 tests/ui/consts/const-eval/extern_fat_pointer.rs create mode 100644 tests/ui/consts/const-eval/format.rs create mode 100644 tests/ui/consts/const-eval/format.stderr create mode 100644 tests/ui/consts/const-eval/generic-slice.rs create mode 100644 tests/ui/consts/const-eval/generic-slice.stderr create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr create mode 100644 tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.rs create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.rs create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr create mode 100644 tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs create mode 100644 tests/ui/consts/const-eval/ice-generic-assoc-const.rs create mode 100644 tests/ui/consts/const-eval/ice-packed.rs create mode 100644 tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs create mode 100644 tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr create mode 100644 tests/ui/consts/const-eval/index_out_of_bounds.rs create mode 100644 tests/ui/consts/const-eval/index_out_of_bounds.stderr create mode 100644 tests/ui/consts/const-eval/index_out_of_bounds_propagated.rs create mode 100644 tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr create mode 100644 tests/ui/consts/const-eval/infinite_loop.rs create mode 100644 tests/ui/consts/const-eval/infinite_loop.stderr create mode 100644 tests/ui/consts/const-eval/issue-100878.rs create mode 100644 tests/ui/consts/const-eval/issue-104390.rs create mode 100644 tests/ui/consts/const-eval/issue-104390.stderr create mode 100644 tests/ui/consts/const-eval/issue-43197.rs create mode 100644 tests/ui/consts/const-eval/issue-43197.stderr create mode 100644 tests/ui/consts/const-eval/issue-44578.rs create mode 100644 tests/ui/consts/const-eval/issue-44578.stderr create mode 100644 tests/ui/consts/const-eval/issue-47971.rs create mode 100644 tests/ui/consts/const-eval/issue-49296.rs create mode 100644 tests/ui/consts/const-eval/issue-49296.stderr create mode 100644 tests/ui/consts/const-eval/issue-50706.rs create mode 100644 tests/ui/consts/const-eval/issue-50814-2.rs create mode 100644 tests/ui/consts/const-eval/issue-50814-2.stderr create mode 100644 tests/ui/consts/const-eval/issue-50814.rs create mode 100644 tests/ui/consts/const-eval/issue-50814.stderr create mode 100644 tests/ui/consts/const-eval/issue-51300.rs create mode 100644 tests/ui/consts/const-eval/issue-52475.rs create mode 100644 tests/ui/consts/const-eval/issue-52475.stderr create mode 100644 tests/ui/consts/const-eval/issue-53157.rs create mode 100644 tests/ui/consts/const-eval/issue-53401.rs create mode 100644 tests/ui/consts/const-eval/issue-55541.rs create mode 100644 tests/ui/consts/const-eval/issue-64908.rs create mode 100644 tests/ui/consts/const-eval/issue-64970.rs create mode 100644 tests/ui/consts/const-eval/issue-65394.rs create mode 100644 tests/ui/consts/const-eval/issue-65394.stderr create mode 100644 tests/ui/consts/const-eval/issue-70723.rs create mode 100644 tests/ui/consts/const-eval/issue-70723.stderr create mode 100644 tests/ui/consts/const-eval/issue-70804-fn-subtyping.rs create mode 100644 tests/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs create mode 100644 tests/ui/consts/const-eval/issue-85155.rs create mode 100644 tests/ui/consts/const-eval/issue-85155.stderr create mode 100644 tests/ui/consts/const-eval/issue-85907.rs create mode 100644 tests/ui/consts/const-eval/issue-85907.stderr create mode 100644 tests/ui/consts/const-eval/issue-91827-extern-types.rs create mode 100644 tests/ui/consts/const-eval/livedrop.rs create mode 100644 tests/ui/consts/const-eval/livedrop.stderr create mode 100644 tests/ui/consts/const-eval/match-test-ptr-null.rs create mode 100644 tests/ui/consts/const-eval/match-test-ptr-null.stderr create mode 100644 tests/ui/consts/const-eval/mod-static-with-const-fn.rs create mode 100644 tests/ui/consts/const-eval/mod-static-with-const-fn.stderr create mode 100644 tests/ui/consts/const-eval/no_lint_for_statically_known_error.rs create mode 100644 tests/ui/consts/const-eval/nrvo.rs create mode 100644 tests/ui/consts/const-eval/panic-assoc-never-type.rs create mode 100644 tests/ui/consts/const-eval/panic-assoc-never-type.stderr create mode 100644 tests/ui/consts/const-eval/panic-never-type.rs create mode 100644 tests/ui/consts/const-eval/panic-never-type.stderr create mode 100644 tests/ui/consts/const-eval/partial_ptr_overwrite.rs create mode 100644 tests/ui/consts/const-eval/partial_ptr_overwrite.stderr create mode 100644 tests/ui/consts/const-eval/promote-static.rs create mode 100644 tests/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs create mode 100644 tests/ui/consts/const-eval/promoted_const_fn_fail.rs create mode 100644 tests/ui/consts/const-eval/promoted_const_fn_fail.stderr create mode 100644 tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs create mode 100644 tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr create mode 100644 tests/ui/consts/const-eval/promoted_errors.noopt.stderr create mode 100644 tests/ui/consts/const-eval/promoted_errors.opt.stderr create mode 100644 tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr create mode 100644 tests/ui/consts/const-eval/promoted_errors.rs create mode 100644 tests/ui/consts/const-eval/promoted_raw_ptr_ops.rs create mode 100644 tests/ui/consts/const-eval/promoted_raw_ptr_ops.stderr create mode 100644 tests/ui/consts/const-eval/raw-bytes.32bit.stderr create mode 100644 tests/ui/consts/const-eval/raw-bytes.64bit.stderr create mode 100644 tests/ui/consts/const-eval/raw-bytes.rs create mode 100644 tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr create mode 100644 tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ref_to_int_match.rs create mode 100644 tests/ui/consts/const-eval/shift_overflow.rs create mode 100644 tests/ui/consts/const-eval/shift_overflow.stderr create mode 100644 tests/ui/consts/const-eval/simd/insert_extract.rs create mode 100644 tests/ui/consts/const-eval/simple_with_undef.rs create mode 100644 tests/ui/consts/const-eval/size-of-t.rs create mode 100644 tests/ui/consts/const-eval/size-of-t.stderr create mode 100644 tests/ui/consts/const-eval/strlen.rs create mode 100644 tests/ui/consts/const-eval/transmute-const-promotion.rs create mode 100644 tests/ui/consts/const-eval/transmute-const-promotion.stderr create mode 100644 tests/ui/consts/const-eval/transmute-const.32bit.stderr create mode 100644 tests/ui/consts/const-eval/transmute-const.64bit.stderr create mode 100644 tests/ui/consts/const-eval/transmute-const.rs create mode 100644 tests/ui/consts/const-eval/ub-enum-overwrite.rs create mode 100644 tests/ui/consts/const-eval/ub-enum-overwrite.stderr create mode 100644 tests/ui/consts/const-eval/ub-enum.32bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-enum.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-enum.rs create mode 100644 tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-incorrect-vtable.rs create mode 100644 tests/ui/consts/const-eval/ub-int-array.32bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-int-array.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-int-array.rs create mode 100644 tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-nonnull.rs create mode 100644 tests/ui/consts/const-eval/ub-nonnull.stderr create mode 100644 tests/ui/consts/const-eval/ub-ref-ptr.rs create mode 100644 tests/ui/consts/const-eval/ub-ref-ptr.stderr create mode 100644 tests/ui/consts/const-eval/ub-uninhabit.rs create mode 100644 tests/ui/consts/const-eval/ub-uninhabit.stderr create mode 100644 tests/ui/consts/const-eval/ub-upvars.32bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-upvars.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-upvars.rs create mode 100644 tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr create mode 100644 tests/ui/consts/const-eval/ub-wide-ptr.rs create mode 100644 tests/ui/consts/const-eval/ub-wide-ptr.stderr create mode 100644 tests/ui/consts/const-eval/union-const-eval-field.rs create mode 100644 tests/ui/consts/const-eval/union-const-eval-field.stderr create mode 100644 tests/ui/consts/const-eval/union-ice.rs create mode 100644 tests/ui/consts/const-eval/union-ice.stderr create mode 100644 tests/ui/consts/const-eval/union-ub.32bit.stderr create mode 100644 tests/ui/consts/const-eval/union-ub.64bit.stderr create mode 100644 tests/ui/consts/const-eval/union-ub.rs create mode 100644 tests/ui/consts/const-eval/union_promotion.rs create mode 100644 tests/ui/consts/const-eval/union_promotion.stderr create mode 100644 tests/ui/consts/const-eval/unused-broken-const.rs create mode 100644 tests/ui/consts/const-eval/unused-broken-const.stderr create mode 100644 tests/ui/consts/const-eval/unwind-abort.rs create mode 100644 tests/ui/consts/const-eval/unwind-abort.stderr create mode 100644 tests/ui/consts/const-eval/valid-const.rs create mode 100644 tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr create mode 100644 tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr create mode 100644 tests/ui/consts/const-eval/validate_uninhabited_zsts.rs create mode 100644 tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs create mode 100644 tests/ui/consts/const-eval/zst_operand_eval.rs create mode 100644 tests/ui/consts/const-expr-addr-operator.rs create mode 100644 tests/ui/consts/const-expr-in-fixed-length-vec.rs create mode 100644 tests/ui/consts/const-expr-in-vec-repeat.rs create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr create mode 100644 tests/ui/consts/const-extern-fn/const-extern-fn.rs create mode 100644 tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs create mode 100644 tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr create mode 100644 tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs create mode 100644 tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr create mode 100644 tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs create mode 100644 tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr create mode 100644 tests/ui/consts/const-extern-function.rs create mode 100644 tests/ui/consts/const-external-macro-const-err.rs create mode 100644 tests/ui/consts/const-external-macro-const-err.stderr create mode 100644 tests/ui/consts/const-fields-and-indexing.rs create mode 100644 tests/ui/consts/const-float-bits-conv.rs create mode 100644 tests/ui/consts/const-float-bits-reject-conv.rs create mode 100644 tests/ui/consts/const-float-bits-reject-conv.stderr create mode 100644 tests/ui/consts/const-float-classify.rs create mode 100644 tests/ui/consts/const-fn-const-eval.rs create mode 100644 tests/ui/consts/const-fn-destructuring-arg.rs create mode 100644 tests/ui/consts/const-fn-error.rs create mode 100644 tests/ui/consts/const-fn-error.stderr create mode 100644 tests/ui/consts/const-fn-in-vec.rs create mode 100644 tests/ui/consts/const-fn-in-vec.stderr create mode 100644 tests/ui/consts/const-fn-method.rs create mode 100644 tests/ui/consts/const-fn-mismatch.rs create mode 100644 tests/ui/consts/const-fn-mismatch.stderr create mode 100644 tests/ui/consts/const-fn-nested.rs create mode 100644 tests/ui/consts/const-fn-not-in-trait.rs create mode 100644 tests/ui/consts/const-fn-not-in-trait.stderr create mode 100644 tests/ui/consts/const-fn-not-safe-for-const.rs create mode 100644 tests/ui/consts/const-fn-not-safe-for-const.stderr create mode 100644 tests/ui/consts/const-fn-ptr.rs create mode 100644 tests/ui/consts/const-fn-ptr.stderr create mode 100644 tests/ui/consts/const-fn-stability-calls-3.rs create mode 100644 tests/ui/consts/const-fn-stability-calls.rs create mode 100644 tests/ui/consts/const-fn-type-name-any.rs create mode 100644 tests/ui/consts/const-fn-type-name.rs create mode 100644 tests/ui/consts/const-fn-val.rs create mode 100644 tests/ui/consts/const-fn-zst-args.rs create mode 100644 tests/ui/consts/const-fn.rs create mode 100644 tests/ui/consts/const-for-feature-gate.rs create mode 100644 tests/ui/consts/const-for-feature-gate.stderr create mode 100644 tests/ui/consts/const-for.rs create mode 100644 tests/ui/consts/const-for.stderr create mode 100644 tests/ui/consts/const-index-feature-gate.rs create mode 100644 tests/ui/consts/const-int-arithmetic-overflow.rs create mode 100644 tests/ui/consts/const-int-arithmetic.rs create mode 100644 tests/ui/consts/const-int-conversion-rpass.rs create mode 100644 tests/ui/consts/const-int-conversion.rs create mode 100644 tests/ui/consts/const-int-conversion.stderr create mode 100644 tests/ui/consts/const-int-overflowing-rpass.rs create mode 100644 tests/ui/consts/const-int-overflowing.rs create mode 100644 tests/ui/consts/const-int-overflowing.stderr create mode 100644 tests/ui/consts/const-int-pow-rpass.rs create mode 100644 tests/ui/consts/const-int-rotate-rpass.rs create mode 100644 tests/ui/consts/const-int-rotate.rs create mode 100644 tests/ui/consts/const-int-rotate.stderr create mode 100644 tests/ui/consts/const-int-saturating-arith.rs create mode 100644 tests/ui/consts/const-int-sign-rpass.rs create mode 100644 tests/ui/consts/const-int-sign.rs create mode 100644 tests/ui/consts/const-int-sign.stderr create mode 100644 tests/ui/consts/const-int-unchecked.rs create mode 100644 tests/ui/consts/const-int-unchecked.stderr create mode 100644 tests/ui/consts/const-int-wrapping-rpass.rs create mode 100644 tests/ui/consts/const-int-wrapping.rs create mode 100644 tests/ui/consts/const-int-wrapping.stderr create mode 100644 tests/ui/consts/const-integer-bool-ops.rs create mode 100644 tests/ui/consts/const-integer-bool-ops.stderr create mode 100644 tests/ui/consts/const-labeled-break.rs create mode 100644 tests/ui/consts/const-len-underflow-separate-spans.rs create mode 100644 tests/ui/consts/const-len-underflow-separate-spans.stderr create mode 100644 tests/ui/consts/const-len-underflow-subspans.rs create mode 100644 tests/ui/consts/const-len-underflow-subspans.stderr create mode 100644 tests/ui/consts/const-match-check.eval1.stderr create mode 100644 tests/ui/consts/const-match-check.eval2.stderr create mode 100644 tests/ui/consts/const-match-check.matchck.stderr create mode 100644 tests/ui/consts/const-match-check.rs create mode 100644 tests/ui/consts/const-match-pattern-arm.rs create mode 100644 tests/ui/consts/const-meth-pattern.rs create mode 100644 tests/ui/consts/const-multi-ref.rs create mode 100644 tests/ui/consts/const-multi-ref.stderr create mode 100644 tests/ui/consts/const-mut-refs/const_mut_address_of.rs create mode 100644 tests/ui/consts/const-mut-refs/const_mut_refs.rs create mode 100644 tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs create mode 100644 tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr create mode 100644 tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr create mode 100644 tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr create mode 100644 tests/ui/consts/const-mut-refs/issue-76510.rs create mode 100644 tests/ui/consts/const-mut-refs/mut_ref_in_final.rs create mode 100644 tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr create mode 100644 tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs create mode 100644 tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr create mode 100644 tests/ui/consts/const-needs_drop-monomorphic.rs create mode 100644 tests/ui/consts/const-needs_drop-monomorphic.stderr create mode 100644 tests/ui/consts/const-needs_drop.rs create mode 100644 tests/ui/consts/const-negation.rs create mode 100644 tests/ui/consts/const-negative.rs create mode 100644 tests/ui/consts/const-nullary-enum.rs create mode 100644 tests/ui/consts/const-nullary-univariant-enum.rs create mode 100644 tests/ui/consts/const-pattern-irrefutable.rs create mode 100644 tests/ui/consts/const-pattern-irrefutable.stderr create mode 100644 tests/ui/consts/const-pattern-not-const-evaluable.rs create mode 100644 tests/ui/consts/const-pattern-variant.rs create mode 100644 tests/ui/consts/const-points-to-static.32bit.stderr create mode 100644 tests/ui/consts/const-points-to-static.64bit.stderr create mode 100644 tests/ui/consts/const-points-to-static.rs create mode 100644 tests/ui/consts/const-prop-ice.rs create mode 100644 tests/ui/consts/const-prop-ice.stderr create mode 100644 tests/ui/consts/const-prop-ice2.rs create mode 100644 tests/ui/consts/const-prop-ice2.stderr create mode 100644 tests/ui/consts/const-prop-ice3.rs create mode 100644 tests/ui/consts/const-prop-overflowing-casts.rs create mode 100644 tests/ui/consts/const-prop-read-static-in-const.rs create mode 100644 tests/ui/consts/const-prop-read-static-in-const.stderr create mode 100644 tests/ui/consts/const-ptr-nonnull-rpass.rs create mode 100644 tests/ui/consts/const-ptr-nonnull.rs create mode 100644 tests/ui/consts/const-ptr-nonnull.stderr create mode 100644 tests/ui/consts/const-ptr-unique-rpass.rs create mode 100644 tests/ui/consts/const-ptr-unique.rs create mode 100644 tests/ui/consts/const-ptr-unique.stderr create mode 100644 tests/ui/consts/const-rec-and-tup.rs create mode 100644 tests/ui/consts/const-region-ptrs-noncopy.rs create mode 100644 tests/ui/consts/const-region-ptrs.rs create mode 100644 tests/ui/consts/const-repeated-values.rs create mode 100644 tests/ui/consts/const-size_of-align_of.rs create mode 100644 tests/ui/consts/const-size_of-cycle.rs create mode 100644 tests/ui/consts/const-size_of-cycle.stderr create mode 100644 tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs create mode 100644 tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr create mode 100644 tests/ui/consts/const-size_of_val-align_of_val.rs create mode 100644 tests/ui/consts/const-slice-oob.rs create mode 100644 tests/ui/consts/const-slice-oob.stderr create mode 100644 tests/ui/consts/const-struct-offsets.rs create mode 100644 tests/ui/consts/const-struct.rs create mode 100644 tests/ui/consts/const-suggest-feature.rs create mode 100644 tests/ui/consts/const-suggest-feature.stderr create mode 100644 tests/ui/consts/const-trait-to-trait.rs create mode 100644 tests/ui/consts/const-try-feature-gate.rs create mode 100644 tests/ui/consts/const-try-feature-gate.stderr create mode 100644 tests/ui/consts/const-try.rs create mode 100644 tests/ui/consts/const-tup-index-span.rs create mode 100644 tests/ui/consts/const-tup-index-span.stderr create mode 100644 tests/ui/consts/const-tuple-struct.rs create mode 100644 tests/ui/consts/const-type-mismatch.rs create mode 100644 tests/ui/consts/const-type-mismatch.stderr create mode 100644 tests/ui/consts/const-typeid-of-rpass.rs create mode 100644 tests/ui/consts/const-unit-struct.rs create mode 100644 tests/ui/consts/const-unsafe-fn.rs create mode 100644 tests/ui/consts/const-unsized.rs create mode 100644 tests/ui/consts/const-unsized.stderr create mode 100644 tests/ui/consts/const-unwrap.rs create mode 100644 tests/ui/consts/const-unwrap.stderr create mode 100644 tests/ui/consts/const-validation-fail-55455.rs create mode 100644 tests/ui/consts/const-variant-count.rs create mode 100644 tests/ui/consts/const-vec-of-fns.rs create mode 100644 tests/ui/consts/const-vec-syntax.rs create mode 100644 tests/ui/consts/const-vecs-and-slices.rs create mode 100644 tests/ui/consts/const.rs create mode 100644 tests/ui/consts/const_cmp_type_id.rs create mode 100644 tests/ui/consts/const_constructor/const-construct-call.rs create mode 100644 tests/ui/consts/const_constructor/const_constructor_qpath.rs create mode 100644 tests/ui/consts/const_discriminant.rs create mode 100644 tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr create mode 100644 tests/ui/consts/const_fn_floating_point_arithmetic.rs create mode 100644 tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr create mode 100644 tests/ui/consts/const_fn_return_nested_fn_ptr.rs create mode 100644 tests/ui/consts/const_fn_unsize.rs create mode 100644 tests/ui/consts/const_forget.rs create mode 100644 tests/ui/consts/const_in_pattern/accept_structural.rs create mode 100644 tests/ui/consts/const_in_pattern/auxiliary/consts.rs create mode 100644 tests/ui/consts/const_in_pattern/cross-crate-fail.rs create mode 100644 tests/ui/consts/const_in_pattern/cross-crate-fail.stderr create mode 100644 tests/ui/consts/const_in_pattern/cross-crate-pass.rs create mode 100644 tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs create mode 100644 tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs create mode 100644 tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr create mode 100644 tests/ui/consts/const_in_pattern/incomplete-slice.rs create mode 100644 tests/ui/consts/const_in_pattern/incomplete-slice.stderr create mode 100644 tests/ui/consts/const_in_pattern/issue-44333.rs create mode 100644 tests/ui/consts/const_in_pattern/issue-44333.stderr create mode 100644 tests/ui/consts/const_in_pattern/issue-53708.rs create mode 100644 tests/ui/consts/const_in_pattern/issue-62614.rs create mode 100644 tests/ui/consts/const_in_pattern/issue-65466.rs create mode 100644 tests/ui/consts/const_in_pattern/issue-73431.rs create mode 100644 tests/ui/consts/const_in_pattern/issue-73431.stderr create mode 100644 tests/ui/consts/const_in_pattern/issue-78057.rs create mode 100644 tests/ui/consts/const_in_pattern/issue-78057.stderr create mode 100644 tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs create mode 100644 tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr create mode 100644 tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs create mode 100644 tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr create mode 100644 tests/ui/consts/const_in_pattern/reject_non_structural.rs create mode 100644 tests/ui/consts/const_in_pattern/reject_non_structural.stderr create mode 100644 tests/ui/consts/const_in_pattern/warn_corner_cases.rs create mode 100644 tests/ui/consts/const_in_pattern/warn_corner_cases.stderr create mode 100644 tests/ui/consts/const_let_assign.rs create mode 100644 tests/ui/consts/const_let_assign2.rs create mode 100644 tests/ui/consts/const_let_assign3.rs create mode 100644 tests/ui/consts/const_let_assign3.stderr create mode 100644 tests/ui/consts/const_let_eq.rs create mode 100644 tests/ui/consts/const_let_eq_float.rs create mode 100644 tests/ui/consts/const_let_irrefutable.rs create mode 100644 tests/ui/consts/const_let_promote.rs create mode 100644 tests/ui/consts/const_let_refutable.rs create mode 100644 tests/ui/consts/const_let_refutable.stderr create mode 100644 tests/ui/consts/const_limit/const_eval_limit_not_reached.rs create mode 100644 tests/ui/consts/const_limit/const_eval_limit_overflow.rs create mode 100644 tests/ui/consts/const_limit/const_eval_limit_overflow.stderr create mode 100644 tests/ui/consts/const_limit/const_eval_limit_reached.rs create mode 100644 tests/ui/consts/const_limit/const_eval_limit_reached.stderr create mode 100644 tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs create mode 100644 tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr create mode 100644 tests/ui/consts/const_prop_slice_pat_ice.rs create mode 100644 tests/ui/consts/const_short_circuit.rs create mode 100644 tests/ui/consts/const_unsafe_unreachable.rs create mode 100644 tests/ui/consts/const_unsafe_unreachable_ub.rs create mode 100644 tests/ui/consts/const_unsafe_unreachable_ub.stderr create mode 100644 tests/ui/consts/constifconst-call-in-const-position.rs create mode 100644 tests/ui/consts/constifconst-call-in-const-position.stderr create mode 100644 tests/ui/consts/consts-in-patterns.rs create mode 100644 tests/ui/consts/control-flow/assert.rs create mode 100644 tests/ui/consts/control-flow/assert.stderr create mode 100644 tests/ui/consts/control-flow/basics.rs create mode 100644 tests/ui/consts/control-flow/drop-fail.precise.stderr create mode 100644 tests/ui/consts/control-flow/drop-fail.rs create mode 100644 tests/ui/consts/control-flow/drop-fail.stock.stderr create mode 100644 tests/ui/consts/control-flow/drop-pass.rs create mode 100644 tests/ui/consts/control-flow/drop-precise.rs create mode 100644 tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs create mode 100644 tests/ui/consts/control-flow/feature-gate-const-if-match.rs create mode 100644 tests/ui/consts/control-flow/interior-mutability.rs create mode 100644 tests/ui/consts/control-flow/interior-mutability.stderr create mode 100644 tests/ui/consts/control-flow/issue-46843.rs create mode 100644 tests/ui/consts/control-flow/issue-46843.stderr create mode 100644 tests/ui/consts/control-flow/issue-50577.rs create mode 100644 tests/ui/consts/control-flow/issue-50577.stderr create mode 100644 tests/ui/consts/control-flow/loop.rs create mode 100644 tests/ui/consts/control-flow/loop.stderr create mode 100644 tests/ui/consts/control-flow/short-circuit-let.rs create mode 100644 tests/ui/consts/control-flow/short-circuit.rs create mode 100644 tests/ui/consts/control-flow/single_variant_match_ice.rs create mode 100644 tests/ui/consts/control-flow/try.rs create mode 100644 tests/ui/consts/control-flow/try.stderr create mode 100644 tests/ui/consts/copy-intrinsic.rs create mode 100644 tests/ui/consts/copy-intrinsic.stderr create mode 100644 tests/ui/consts/ct-var-in-collect_all_mismatches.rs create mode 100644 tests/ui/consts/ct-var-in-collect_all_mismatches.stderr create mode 100644 tests/ui/consts/dangling-alloc-id-ice.rs create mode 100644 tests/ui/consts/dangling-alloc-id-ice.stderr create mode 100644 tests/ui/consts/dangling_raw_ptr.rs create mode 100644 tests/ui/consts/dangling_raw_ptr.stderr create mode 100644 tests/ui/consts/deref_in_pattern.rs create mode 100644 tests/ui/consts/drop_box.rs create mode 100644 tests/ui/consts/drop_box.stderr create mode 100644 tests/ui/consts/drop_none.rs create mode 100644 tests/ui/consts/drop_zst.rs create mode 100644 tests/ui/consts/drop_zst.stderr create mode 100644 tests/ui/consts/enum-discr-type-err.rs create mode 100644 tests/ui/consts/enum-discr-type-err.stderr create mode 100644 tests/ui/consts/eval-enum.rs create mode 100644 tests/ui/consts/eval-enum.stderr create mode 100644 tests/ui/consts/extra-const-ub/detect-extra-ub.rs create mode 100644 tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr create mode 100644 tests/ui/consts/extra-const-ub/issue-100771.rs create mode 100644 tests/ui/consts/extra-const-ub/issue-101034.rs create mode 100644 tests/ui/consts/fn_trait_refs.rs create mode 100644 tests/ui/consts/huge-values.rs create mode 100644 tests/ui/consts/ice-48279.rs create mode 100644 tests/ui/consts/ice-zst-static-access.rs create mode 100644 tests/ui/consts/inline_asm.rs create mode 100644 tests/ui/consts/inline_asm.stderr create mode 100644 tests/ui/consts/int_ptr_for_zst_slices.rs create mode 100644 tests/ui/consts/intrinsic_without_const_stab.rs create mode 100644 tests/ui/consts/intrinsic_without_const_stab.stderr create mode 100644 tests/ui/consts/intrinsic_without_const_stab_fail.rs create mode 100644 tests/ui/consts/intrinsic_without_const_stab_fail.stderr create mode 100644 tests/ui/consts/invalid-const-in-body.rs create mode 100644 tests/ui/consts/invalid-const-in-body.stderr create mode 100644 tests/ui/consts/invalid-inline-const-in-match-arm.rs create mode 100644 tests/ui/consts/invalid-inline-const-in-match-arm.stderr create mode 100644 tests/ui/consts/invalid-union.32bit.stderr create mode 100644 tests/ui/consts/invalid-union.64bit.stderr create mode 100644 tests/ui/consts/invalid-union.rs create mode 100644 tests/ui/consts/invalid_promotion.rs create mode 100644 tests/ui/consts/issue-102117.rs create mode 100644 tests/ui/consts/issue-102117.stderr create mode 100644 tests/ui/consts/issue-103790.rs create mode 100644 tests/ui/consts/issue-103790.stderr create mode 100644 tests/ui/consts/issue-104155.rs create mode 100644 tests/ui/consts/issue-104396.rs create mode 100644 tests/ui/consts/issue-104396.stderr create mode 100644 tests/ui/consts/issue-104609.rs create mode 100644 tests/ui/consts/issue-104609.stderr create mode 100644 tests/ui/consts/issue-104768.rs create mode 100644 tests/ui/consts/issue-104768.stderr create mode 100644 tests/ui/consts/issue-13837.rs create mode 100644 tests/ui/consts/issue-13902.rs create mode 100644 tests/ui/consts/issue-17074.rs create mode 100644 tests/ui/consts/issue-17458.rs create mode 100644 tests/ui/consts/issue-17458.stderr create mode 100644 tests/ui/consts/issue-17718-borrow-interior.rs create mode 100644 tests/ui/consts/issue-17718-const-bad-values.rs create mode 100644 tests/ui/consts/issue-17718-const-bad-values.stderr create mode 100644 tests/ui/consts/issue-17718-const-borrow.rs create mode 100644 tests/ui/consts/issue-17718-const-borrow.stderr create mode 100644 tests/ui/consts/issue-17718-constants-not-static.rs create mode 100644 tests/ui/consts/issue-17718-constants-not-static.stderr create mode 100644 tests/ui/consts/issue-17718-references.rs create mode 100644 tests/ui/consts/issue-17718-references.stderr create mode 100644 tests/ui/consts/issue-17718.rs create mode 100644 tests/ui/consts/issue-17756.rs create mode 100644 tests/ui/consts/issue-18294.rs create mode 100644 tests/ui/consts/issue-18294.stderr create mode 100644 tests/ui/consts/issue-19244.rs create mode 100644 tests/ui/consts/issue-21562.rs create mode 100644 tests/ui/consts/issue-21721.rs create mode 100644 tests/ui/consts/issue-23833.rs create mode 100644 tests/ui/consts/issue-23968-const-not-overflow.rs create mode 100644 tests/ui/consts/issue-25826.rs create mode 100644 tests/ui/consts/issue-25826.stderr create mode 100644 tests/ui/consts/issue-27890.rs create mode 100644 tests/ui/consts/issue-28113.rs create mode 100644 tests/ui/consts/issue-28113.stderr create mode 100644 tests/ui/consts/issue-29914-2.rs create mode 100644 tests/ui/consts/issue-29914-3.rs create mode 100644 tests/ui/consts/issue-29914.rs create mode 100644 tests/ui/consts/issue-29927-1.rs create mode 100644 tests/ui/consts/issue-29927.rs create mode 100644 tests/ui/consts/issue-32829-2.rs create mode 100644 tests/ui/consts/issue-32829-2.stderr create mode 100644 tests/ui/consts/issue-32829.rs create mode 100644 tests/ui/consts/issue-32829.stderr create mode 100644 tests/ui/consts/issue-33537.rs create mode 100644 tests/ui/consts/issue-34784.rs create mode 100644 tests/ui/consts/issue-3521.fixed create mode 100644 tests/ui/consts/issue-3521.rs create mode 100644 tests/ui/consts/issue-3521.stderr create mode 100644 tests/ui/consts/issue-36163.rs create mode 100644 tests/ui/consts/issue-36163.stderr create mode 100644 tests/ui/consts/issue-37222.rs create mode 100644 tests/ui/consts/issue-37550-1.rs create mode 100644 tests/ui/consts/issue-37550.rs create mode 100644 tests/ui/consts/issue-37991.rs create mode 100644 tests/ui/consts/issue-39161-bogus-error.rs create mode 100644 tests/ui/consts/issue-39974.rs create mode 100644 tests/ui/consts/issue-39974.stderr create mode 100644 tests/ui/consts/issue-43105.rs create mode 100644 tests/ui/consts/issue-43105.stderr create mode 100644 tests/ui/consts/issue-44415.rs create mode 100644 tests/ui/consts/issue-44415.stderr create mode 100644 tests/ui/consts/issue-46553.rs create mode 100644 tests/ui/consts/issue-47789.rs create mode 100644 tests/ui/consts/issue-50439.rs create mode 100644 tests/ui/consts/issue-50439.stderr create mode 100644 tests/ui/consts/issue-52023-array-size-pointer-cast.rs create mode 100644 tests/ui/consts/issue-52023-array-size-pointer-cast.stderr create mode 100644 tests/ui/consts/issue-52060.rs create mode 100644 tests/ui/consts/issue-52060.stderr create mode 100644 tests/ui/consts/issue-54224.rs create mode 100644 tests/ui/consts/issue-54224.stderr create mode 100644 tests/ui/consts/issue-54348.rs create mode 100644 tests/ui/consts/issue-54348.stderr create mode 100644 tests/ui/consts/issue-54387.rs create mode 100644 tests/ui/consts/issue-54954.rs create mode 100644 tests/ui/consts/issue-54954.stderr create mode 100644 tests/ui/consts/issue-56164.rs create mode 100644 tests/ui/consts/issue-56164.stderr create mode 100644 tests/ui/consts/issue-58435-ice-with-assoc-const.rs create mode 100644 tests/ui/consts/issue-62045.rs create mode 100644 tests/ui/consts/issue-63226.rs create mode 100644 tests/ui/consts/issue-63952.32bit.stderr create mode 100644 tests/ui/consts/issue-63952.64bit.stderr create mode 100644 tests/ui/consts/issue-63952.rs create mode 100644 tests/ui/consts/issue-64059.rs create mode 100644 tests/ui/consts/issue-64506.rs create mode 100644 tests/ui/consts/issue-64662.rs create mode 100644 tests/ui/consts/issue-64662.stderr create mode 100644 tests/ui/consts/issue-65348.rs create mode 100644 tests/ui/consts/issue-66342.rs create mode 100644 tests/ui/consts/issue-66345.rs create mode 100644 tests/ui/consts/issue-66397.rs create mode 100644 tests/ui/consts/issue-66693-panic-in-array-len.rs create mode 100644 tests/ui/consts/issue-66693-panic-in-array-len.stderr create mode 100644 tests/ui/consts/issue-66693.rs create mode 100644 tests/ui/consts/issue-66693.stderr create mode 100644 tests/ui/consts/issue-66787.rs create mode 100644 tests/ui/consts/issue-67529.rs create mode 100644 tests/ui/consts/issue-67640.rs create mode 100644 tests/ui/consts/issue-67641.rs create mode 100644 tests/ui/consts/issue-67696-const-prop-ice.rs create mode 100644 tests/ui/consts/issue-67862.rs create mode 100644 tests/ui/consts/issue-68264-overflow.rs create mode 100644 tests/ui/consts/issue-68542-closure-in-array-len.rs create mode 100644 tests/ui/consts/issue-68542-closure-in-array-len.stderr create mode 100644 tests/ui/consts/issue-68684.rs create mode 100644 tests/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs create mode 100644 tests/ui/consts/issue-69310-array-size-lit-wrong-ty.rs create mode 100644 tests/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr create mode 100644 tests/ui/consts/issue-69312.rs create mode 100644 tests/ui/consts/issue-69488.rs create mode 100644 tests/ui/consts/issue-69532.rs create mode 100644 tests/ui/consts/issue-6991.rs create mode 100644 tests/ui/consts/issue-70773-mir-typeck-lt-norm.rs create mode 100644 tests/ui/consts/issue-70942-trait-vs-impl-mismatch.rs create mode 100644 tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr create mode 100644 tests/ui/consts/issue-73976-monomorphic.rs create mode 100644 tests/ui/consts/issue-73976-polymorphic.rs create mode 100644 tests/ui/consts/issue-73976-polymorphic.stderr create mode 100644 tests/ui/consts/issue-76064.rs create mode 100644 tests/ui/consts/issue-76064.stderr create mode 100644 tests/ui/consts/issue-77062-large-zst-array.rs create mode 100644 tests/ui/consts/issue-78655.rs create mode 100644 tests/ui/consts/issue-78655.stderr create mode 100644 tests/ui/consts/issue-79137-monomorphic.rs create mode 100644 tests/ui/consts/issue-79137-toogeneric.rs create mode 100644 tests/ui/consts/issue-79137-toogeneric.stderr create mode 100644 tests/ui/consts/issue-79152-const-array-index.rs create mode 100644 tests/ui/consts/issue-79690.64bit.stderr create mode 100644 tests/ui/consts/issue-79690.rs create mode 100644 tests/ui/consts/issue-83182.rs create mode 100644 tests/ui/consts/issue-83182.stderr create mode 100644 tests/ui/consts/issue-87046.rs create mode 100644 tests/ui/consts/issue-87046.stderr create mode 100644 tests/ui/consts/issue-88071.rs create mode 100644 tests/ui/consts/issue-88649.rs create mode 100644 tests/ui/consts/issue-89088.rs create mode 100644 tests/ui/consts/issue-90762.rs create mode 100644 tests/ui/consts/issue-90870.fixed create mode 100644 tests/ui/consts/issue-90870.rs create mode 100644 tests/ui/consts/issue-90870.stderr create mode 100644 tests/ui/consts/issue-90878-2.rs create mode 100644 tests/ui/consts/issue-90878-2.stderr create mode 100644 tests/ui/consts/issue-90878-3.rs create mode 100644 tests/ui/consts/issue-90878-3.stderr create mode 100644 tests/ui/consts/issue-90878.rs create mode 100644 tests/ui/consts/issue-90878.stderr create mode 100644 tests/ui/consts/issue-91434.rs create mode 100644 tests/ui/consts/issue-91434.stderr create mode 100644 tests/ui/consts/issue-91560.fixed create mode 100644 tests/ui/consts/issue-91560.rs create mode 100644 tests/ui/consts/issue-91560.stderr create mode 100644 tests/ui/consts/issue-94371.rs create mode 100644 tests/ui/consts/issue-94675.rs create mode 100644 tests/ui/consts/issue-94675.stderr create mode 100644 tests/ui/consts/issue-96169.rs create mode 100644 tests/ui/consts/issue-broken-mir.rs create mode 100644 tests/ui/consts/issue-miri-1910.rs create mode 100644 tests/ui/consts/issue-miri-1910.stderr create mode 100644 tests/ui/consts/large_const_alloc.rs create mode 100644 tests/ui/consts/large_const_alloc.stderr create mode 100644 tests/ui/consts/locals-in-const-fn.rs create mode 100644 tests/ui/consts/match-const-fn-structs.rs create mode 100644 tests/ui/consts/match_ice.rs create mode 100644 tests/ui/consts/match_ice.stderr create mode 100644 tests/ui/consts/min_const_fn/address_of.rs create mode 100644 tests/ui/consts/min_const_fn/address_of.stderr create mode 100644 tests/ui/consts/min_const_fn/address_of_const.rs create mode 100644 tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs create mode 100644 tests/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs create mode 100644 tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs create mode 100644 tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr create mode 100644 tests/ui/consts/min_const_fn/cast_fn.rs create mode 100644 tests/ui/consts/min_const_fn/cmp_fn_pointers.rs create mode 100644 tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr create mode 100644 tests/ui/consts/min_const_fn/min_const_fn.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_fn.stderr create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_dyn.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_libstd.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr create mode 100644 tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr create mode 100644 tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs create mode 100644 tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr create mode 100644 tests/ui/consts/min_const_fn/mutable_borrow.rs create mode 100644 tests/ui/consts/min_const_fn/mutable_borrow.stderr create mode 100644 tests/ui/consts/min_const_fn/promotion.rs create mode 100644 tests/ui/consts/min_const_fn/promotion.stderr create mode 100644 tests/ui/consts/mir_check_nonconst.rs create mode 100644 tests/ui/consts/mir_check_nonconst.stderr create mode 100644 tests/ui/consts/miri_unleashed/abi-mismatch.rs create mode 100644 tests/ui/consts/miri_unleashed/abi-mismatch.stderr create mode 100644 tests/ui/consts/miri_unleashed/assoc_const.rs create mode 100644 tests/ui/consts/miri_unleashed/assoc_const.stderr create mode 100644 tests/ui/consts/miri_unleashed/assoc_const_2.rs create mode 100644 tests/ui/consts/miri_unleashed/assoc_const_2.stderr create mode 100644 tests/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs create mode 100644 tests/ui/consts/miri_unleashed/box.rs create mode 100644 tests/ui/consts/miri_unleashed/box.stderr create mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr create mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr create mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static.rs create mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr create mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr create mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs create mode 100644 tests/ui/consts/miri_unleashed/drop.rs create mode 100644 tests/ui/consts/miri_unleashed/drop.stderr create mode 100644 tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs create mode 100644 tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr create mode 100644 tests/ui/consts/miri_unleashed/inline_asm.rs create mode 100644 tests/ui/consts/miri_unleashed/inline_asm.stderr create mode 100644 tests/ui/consts/miri_unleashed/mutable_references.rs create mode 100644 tests/ui/consts/miri_unleashed/mutable_references.stderr create mode 100644 tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr create mode 100644 tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr create mode 100644 tests/ui/consts/miri_unleashed/mutable_references_err.rs create mode 100644 tests/ui/consts/miri_unleashed/mutating_global.rs create mode 100644 tests/ui/consts/miri_unleashed/mutating_global.stderr create mode 100644 tests/ui/consts/miri_unleashed/non_const_fn.rs create mode 100644 tests/ui/consts/miri_unleashed/non_const_fn.stderr create mode 100644 tests/ui/consts/miri_unleashed/ptr_arith.rs create mode 100644 tests/ui/consts/miri_unleashed/ptr_arith.stderr create mode 100644 tests/ui/consts/miri_unleashed/raw_mutable_const.rs create mode 100644 tests/ui/consts/miri_unleashed/raw_mutable_const.stderr create mode 100644 tests/ui/consts/miri_unleashed/slice_eq.rs create mode 100644 tests/ui/consts/miri_unleashed/tls.rs create mode 100644 tests/ui/consts/miri_unleashed/tls.stderr create mode 100644 tests/ui/consts/missing_span_in_backtrace.rs create mode 100644 tests/ui/consts/missing_span_in_backtrace.stderr create mode 100644 tests/ui/consts/mozjs-error.rs create mode 100644 tests/ui/consts/nested_erroneous_ctfe.rs create mode 100644 tests/ui/consts/nested_erroneous_ctfe.stderr create mode 100644 tests/ui/consts/non-const-value-in-const.rs create mode 100644 tests/ui/consts/non-const-value-in-const.stderr create mode 100644 tests/ui/consts/non-scalar-cast.rs create mode 100644 tests/ui/consts/offset.rs create mode 100644 tests/ui/consts/offset_from.rs create mode 100644 tests/ui/consts/offset_from_ub.rs create mode 100644 tests/ui/consts/offset_from_ub.stderr create mode 100644 tests/ui/consts/offset_ub.rs create mode 100644 tests/ui/consts/offset_ub.stderr create mode 100644 tests/ui/consts/packed_pattern.rs create mode 100644 tests/ui/consts/packed_pattern.stderr create mode 100644 tests/ui/consts/packed_pattern2.rs create mode 100644 tests/ui/consts/packed_pattern2.stderr create mode 100644 tests/ui/consts/partial_qualif.rs create mode 100644 tests/ui/consts/partial_qualif.stderr create mode 100644 tests/ui/consts/precise-drop-with-coverage.rs create mode 100644 tests/ui/consts/precise-drop-with-promoted.rs create mode 100644 tests/ui/consts/promote-not.rs create mode 100644 tests/ui/consts/promote-not.stderr create mode 100644 tests/ui/consts/promote_borrowed_field.rs create mode 100644 tests/ui/consts/promote_const_let.rs create mode 100644 tests/ui/consts/promote_const_let.stderr create mode 100644 tests/ui/consts/promote_evaluation_unused_result.rs create mode 100644 tests/ui/consts/promote_fn_calls.rs create mode 100644 tests/ui/consts/promote_fn_calls_std.rs create mode 100644 tests/ui/consts/promoted-const-drop.rs create mode 100644 tests/ui/consts/promoted-const-drop.stderr create mode 100644 tests/ui/consts/promoted-storage.rs create mode 100644 tests/ui/consts/promoted-validation-55454.rs create mode 100644 tests/ui/consts/promoted_const_call.rs create mode 100644 tests/ui/consts/promoted_const_call.stderr create mode 100644 tests/ui/consts/promoted_const_call2.rs create mode 100644 tests/ui/consts/promoted_const_call2.stderr create mode 100644 tests/ui/consts/promoted_const_call3.rs create mode 100644 tests/ui/consts/promoted_const_call3.stderr create mode 100644 tests/ui/consts/promoted_const_call4.rs create mode 100644 tests/ui/consts/promoted_const_call5.rs create mode 100644 tests/ui/consts/promoted_const_call5.stderr create mode 100644 tests/ui/consts/promoted_regression.rs create mode 100644 tests/ui/consts/promotion-mutable-ref.rs create mode 100644 tests/ui/consts/promotion.rs create mode 100644 tests/ui/consts/ptr_comparisons.rs create mode 100644 tests/ui/consts/ptr_comparisons.stderr create mode 100644 tests/ui/consts/ptr_is_null.rs create mode 100644 tests/ui/consts/qualif-indirect-mutation-fail.rs create mode 100644 tests/ui/consts/qualif-indirect-mutation-fail.stderr create mode 100644 tests/ui/consts/qualif-indirect-mutation-pass.rs create mode 100644 tests/ui/consts/qualif-union.rs create mode 100644 tests/ui/consts/qualif-union.stderr create mode 100644 tests/ui/consts/qualif_overwrite.rs create mode 100644 tests/ui/consts/qualif_overwrite.stderr create mode 100644 tests/ui/consts/qualif_overwrite_2.rs create mode 100644 tests/ui/consts/qualif_overwrite_2.stderr create mode 100644 tests/ui/consts/raw-ptr-const.rs create mode 100644 tests/ui/consts/raw-ptr-const.stderr create mode 100644 tests/ui/consts/raw_pointer_promoted.rs create mode 100644 tests/ui/consts/recursive-zst-static.default.stderr create mode 100644 tests/ui/consts/recursive-zst-static.rs create mode 100644 tests/ui/consts/recursive-zst-static.unleash.stderr create mode 100644 tests/ui/consts/recursive.rs create mode 100644 tests/ui/consts/recursive.stderr create mode 100644 tests/ui/consts/references.rs create mode 100644 tests/ui/consts/refs_check_const_eq-issue-88384.rs create mode 100644 tests/ui/consts/refs_check_const_eq-issue-88384.stderr create mode 100644 tests/ui/consts/refs_check_const_value_eq-issue-88876.rs create mode 100644 tests/ui/consts/repeat_match.rs create mode 100644 tests/ui/consts/return-in-const-fn.rs create mode 100644 tests/ui/consts/rustc-const-stability-require-const.rs create mode 100644 tests/ui/consts/rustc-const-stability-require-const.stderr create mode 100644 tests/ui/consts/rustc-impl-const-stability.rs create mode 100644 tests/ui/consts/rvalue-static-promotion.rs create mode 100644 tests/ui/consts/self_normalization.rs create mode 100644 tests/ui/consts/self_normalization2.rs create mode 100644 tests/ui/consts/signed_enum_discr.rs create mode 100644 tests/ui/consts/stable-precise-live-drops-in-libcore.rs create mode 100644 tests/ui/consts/stable-precise-live-drops-in-libcore.stderr create mode 100644 tests/ui/consts/static-cycle-error.rs create mode 100644 tests/ui/consts/static-raw-pointer-interning.rs create mode 100644 tests/ui/consts/static-raw-pointer-interning2.rs create mode 100644 tests/ui/consts/static_mut_containing_mut_ref.rs create mode 100644 tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr create mode 100644 tests/ui/consts/static_mut_containing_mut_ref2.rs create mode 100644 tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr create mode 100644 tests/ui/consts/static_mut_containing_mut_ref3.rs create mode 100644 tests/ui/consts/static_mut_containing_mut_ref3.stderr create mode 100644 tests/ui/consts/std/alloc.32bit.stderr create mode 100644 tests/ui/consts/std/alloc.64bit.stderr create mode 100644 tests/ui/consts/std/alloc.rs create mode 100644 tests/ui/consts/std/cell.rs create mode 100644 tests/ui/consts/std/cell.stderr create mode 100644 tests/ui/consts/std/iter.rs create mode 100644 tests/ui/consts/std/slice.rs create mode 100644 tests/ui/consts/too_generic_eval_ice.rs create mode 100644 tests/ui/consts/too_generic_eval_ice.stderr create mode 100644 tests/ui/consts/trait_specialization.rs create mode 100644 tests/ui/consts/trait_specialization.stderr create mode 100644 tests/ui/consts/transmute-const.rs create mode 100644 tests/ui/consts/transmute-size-mismatch-before-typeck.rs create mode 100644 tests/ui/consts/transmute-size-mismatch-before-typeck.stderr create mode 100644 tests/ui/consts/try-operator.rs create mode 100644 tests/ui/consts/tuple-struct-constructors.rs create mode 100644 tests/ui/consts/underscore_const_names.rs create mode 100644 tests/ui/consts/uninhabited-const-issue-61744.rs create mode 100644 tests/ui/consts/uninhabited-const-issue-61744.stderr create mode 100644 tests/ui/consts/union_constant.rs create mode 100644 tests/ui/consts/unnormalized-param-env.rs create mode 100644 tests/ui/consts/unstable-const-fn-in-libcore.rs create mode 100644 tests/ui/consts/unstable-const-fn-in-libcore.stderr create mode 100644 tests/ui/consts/unstable-precise-live-drops-in-libcore.rs create mode 100644 tests/ui/consts/unwind-abort.rs create mode 100644 tests/ui/consts/validate_never_arrays.rs create mode 100644 tests/ui/consts/validate_never_arrays.stderr create mode 100644 tests/ui/consts/write-to-static-mut-in-static.rs create mode 100644 tests/ui/consts/write-to-static-mut-in-static.stderr create mode 100644 tests/ui/consts/write_to_mut_ref_dest.rs create mode 100644 tests/ui/consts/write_to_mut_ref_dest.stock.stderr create mode 100644 tests/ui/consts/write_to_static_via_mut_ref.rs create mode 100644 tests/ui/consts/write_to_static_via_mut_ref.stderr create mode 100644 tests/ui/consts/zst_no_llvm_alloc.rs create mode 100644 tests/ui/copy-a-resource.rs create mode 100644 tests/ui/copy-a-resource.stderr create mode 100644 tests/ui/crate-leading-sep.rs create mode 100644 tests/ui/crate-loading/auxiliary/crateresolve1-1.rs create mode 100644 tests/ui/crate-loading/auxiliary/crateresolve1-2.rs create mode 100644 tests/ui/crate-loading/auxiliary/crateresolve1-3.rs create mode 100644 tests/ui/crate-loading/auxiliary/crateresolve2-1.rs create mode 100644 tests/ui/crate-loading/auxiliary/crateresolve2-2.rs create mode 100644 tests/ui/crate-loading/auxiliary/crateresolve2-3.rs create mode 100644 tests/ui/crate-loading/auxiliary/libfoo.rlib create mode 100644 tests/ui/crate-loading/auxiliary/proc-macro.rs create mode 100644 tests/ui/crate-loading/crateresolve1.rs create mode 100644 tests/ui/crate-loading/crateresolve1.stderr create mode 100644 tests/ui/crate-loading/crateresolve2.rs create mode 100644 tests/ui/crate-loading/crateresolve2.stderr create mode 100644 tests/ui/crate-loading/cross-compiled-proc-macro.rs create mode 100644 tests/ui/crate-loading/invalid-rlib.rs create mode 100644 tests/ui/crate-loading/invalid-rlib.stderr create mode 100644 tests/ui/crate-loading/missing-std.rs create mode 100644 tests/ui/crate-loading/missing-std.stderr create mode 100644 tests/ui/crate-method-reexport-grrrrrrr.rs create mode 100644 tests/ui/crate-name-attr-used.rs create mode 100644 tests/ui/crate-name-mismatch.rs create mode 100644 tests/ui/crate-name-mismatch.stderr create mode 100644 tests/ui/cross-crate/auxiliary/cci_borrow_lib.rs create mode 100644 tests/ui/cross-crate/auxiliary/cci_capture_clause.rs create mode 100644 tests/ui/cross-crate/auxiliary/cci_const.rs create mode 100644 tests/ui/cross-crate/auxiliary/cci_impl_lib.rs create mode 100644 tests/ui/cross-crate/auxiliary/cci_iter_lib.rs create mode 100644 tests/ui/cross-crate/auxiliary/cci_nested_lib.rs create mode 100644 tests/ui/cross-crate/auxiliary/cci_no_inline_lib.rs create mode 100644 tests/ui/cross-crate/auxiliary/moves_based_on_type_lib.rs create mode 100644 tests/ui/cross-crate/auxiliary/pub_static_array.rs create mode 100644 tests/ui/cross-crate/auxiliary/reexported_static_methods.rs create mode 100644 tests/ui/cross-crate/auxiliary/static_init_aux.rs create mode 100644 tests/ui/cross-crate/auxiliary/xcrate-trait-lifetime-param.rs create mode 100644 tests/ui/cross-crate/auxiliary/xcrate_address_insignificant.rs create mode 100644 tests/ui/cross-crate/auxiliary/xcrate_associated_type_defaults.rs create mode 100644 tests/ui/cross-crate/auxiliary/xcrate_generic_fn_nested_return.rs create mode 100644 tests/ui/cross-crate/auxiliary/xcrate_static_addresses.rs create mode 100644 tests/ui/cross-crate/cci_borrow.rs create mode 100644 tests/ui/cross-crate/cci_capture_clause.rs create mode 100644 tests/ui/cross-crate/cci_impl_exe.rs create mode 100644 tests/ui/cross-crate/cci_iter_exe.rs create mode 100644 tests/ui/cross-crate/cci_nested_exe.rs create mode 100644 tests/ui/cross-crate/cci_no_inline_exe.rs create mode 100644 tests/ui/cross-crate/const-cross-crate-const.rs create mode 100644 tests/ui/cross-crate/const-cross-crate-extern.rs create mode 100644 tests/ui/cross-crate/cross-crate-const-pat.rs create mode 100644 tests/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs create mode 100644 tests/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs create mode 100644 tests/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs create mode 100644 tests/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs create mode 100644 tests/ui/cross-crate/issue-64872/issue-64872.rs create mode 100644 tests/ui/cross-crate/moves-based-on-type-cross-crate.rs create mode 100644 tests/ui/cross-crate/reexported-static-methods-cross-crate.rs create mode 100644 tests/ui/cross-crate/static-array-across-crate.rs create mode 100644 tests/ui/cross-crate/static-init.rs create mode 100644 tests/ui/cross-crate/xcrate-address-insignificant.rs create mode 100644 tests/ui/cross-crate/xcrate-associated-type-defaults.rs create mode 100644 tests/ui/cross-crate/xcrate-static-addresses.rs create mode 100644 tests/ui/cross-crate/xcrate-trait-lifetime-param.rs create mode 100644 tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs create mode 100644 tests/ui/cross/cross-borrow-trait.rs create mode 100644 tests/ui/cross/cross-borrow-trait.stderr create mode 100644 tests/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs create mode 100644 tests/ui/cross/cross-crate-macro-backtrace/main.rs create mode 100644 tests/ui/cross/cross-crate-macro-backtrace/main.stderr create mode 100644 tests/ui/cross/cross-file-errors/main.rs create mode 100644 tests/ui/cross/cross-file-errors/main.stderr create mode 100644 tests/ui/cross/cross-file-errors/underscore.rs create mode 100644 tests/ui/cross/cross-fn-cache-hole.rs create mode 100644 tests/ui/cross/cross-fn-cache-hole.stderr create mode 100644 tests/ui/custom-attribute-multisegment.rs create mode 100644 tests/ui/custom-attribute-multisegment.stderr create mode 100644 tests/ui/custom-test-frameworks-simple.rs create mode 100644 tests/ui/custom_attribute.rs create mode 100644 tests/ui/custom_attribute.stderr create mode 100644 tests/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs create mode 100644 tests/ui/custom_test_frameworks/auxiliary/example_runner.rs create mode 100644 tests/ui/custom_test_frameworks/dynamic.rs create mode 100644 tests/ui/custom_test_frameworks/full.rs create mode 100644 tests/ui/custom_test_frameworks/mismatch.rs create mode 100644 tests/ui/custom_test_frameworks/mismatch.stderr create mode 100644 tests/ui/cycle-trait/cycle-trait-default-type-trait.rs create mode 100644 tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr create mode 100644 tests/ui/cycle-trait/cycle-trait-supertrait-direct.rs create mode 100644 tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr create mode 100644 tests/ui/cycle-trait/cycle-trait-supertrait-indirect.rs create mode 100644 tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr create mode 100644 tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs create mode 100644 tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs create mode 100644 tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs create mode 100644 tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr create mode 100644 tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs create mode 100644 tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr create mode 100644 tests/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs create mode 100644 tests/ui/debuginfo/issue-105386-debuginfo-ub.rs create mode 100644 tests/ui/debuginfo/late-bound-projection.rs create mode 100644 tests/ui/deduplicate-diagnostics.deduplicate.stderr create mode 100644 tests/ui/deduplicate-diagnostics.duplicate.stderr create mode 100644 tests/ui/deduplicate-diagnostics.rs create mode 100644 tests/ui/deep.rs create mode 100644 tests/ui/default-method-parsing.rs create mode 100644 tests/ui/default-method-simple.rs create mode 100644 tests/ui/defaults-well-formedness.rs create mode 100644 tests/ui/definition-reachable/auxiliary/field-method-macro.rs create mode 100644 tests/ui/definition-reachable/auxiliary/nested-fn-macro.rs create mode 100644 tests/ui/definition-reachable/auxiliary/private-use-macro.rs create mode 100644 tests/ui/definition-reachable/field-method.rs create mode 100644 tests/ui/definition-reachable/nested-fn.rs create mode 100644 tests/ui/definition-reachable/private-non-types.rs create mode 100644 tests/ui/definition-reachable/private-types.rs create mode 100644 tests/ui/definition-reachable/private-use.rs create mode 100644 tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs create mode 100644 tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr create mode 100644 tests/ui/dep-graph/dep-graph-caller-callee.rs create mode 100644 tests/ui/dep-graph/dep-graph-caller-callee.stderr create mode 100644 tests/ui/dep-graph/dep-graph-check-attr.rs create mode 100644 tests/ui/dep-graph/dep-graph-check-attr.stderr create mode 100644 tests/ui/dep-graph/dep-graph-dump.rs create mode 100644 tests/ui/dep-graph/dep-graph-dump.stderr create mode 100644 tests/ui/dep-graph/dep-graph-struct-signature.rs create mode 100644 tests/ui/dep-graph/dep-graph-struct-signature.stderr create mode 100644 tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs create mode 100644 tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr create mode 100644 tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs create mode 100644 tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr create mode 100644 tests/ui/dep-graph/dep-graph-trait-impl.rs create mode 100644 tests/ui/dep-graph/dep-graph-trait-impl.stderr create mode 100644 tests/ui/dep-graph/dep-graph-type-alias.rs create mode 100644 tests/ui/dep-graph/dep-graph-type-alias.stderr create mode 100644 tests/ui/dep-graph/dep-graph-variance-alias.rs create mode 100644 tests/ui/dep-graph/dep-graph-variance-alias.stderr create mode 100644 tests/ui/deprecation-in-force-unstable.rs create mode 100644 tests/ui/deprecation/atomic_initializers.fixed create mode 100644 tests/ui/deprecation/atomic_initializers.rs create mode 100644 tests/ui/deprecation/atomic_initializers.stderr create mode 100644 tests/ui/deprecation/auxiliary/deprecation-lint.rs create mode 100644 tests/ui/deprecation/deprecated-macro_escape-inner.rs create mode 100644 tests/ui/deprecation/deprecated-macro_escape-inner.stderr create mode 100644 tests/ui/deprecation/deprecated-macro_escape.rs create mode 100644 tests/ui/deprecation/deprecated-macro_escape.stderr create mode 100644 tests/ui/deprecation/deprecated_no_stack_check.rs create mode 100644 tests/ui/deprecation/deprecated_no_stack_check.stderr create mode 100644 tests/ui/deprecation/deprecation-in-future.rs create mode 100644 tests/ui/deprecation/deprecation-in-future.stderr create mode 100644 tests/ui/deprecation/deprecation-lint-2.rs create mode 100644 tests/ui/deprecation/deprecation-lint-2.stderr create mode 100644 tests/ui/deprecation/deprecation-lint-3.rs create mode 100644 tests/ui/deprecation/deprecation-lint-3.stderr create mode 100644 tests/ui/deprecation/deprecation-lint-nested.rs create mode 100644 tests/ui/deprecation/deprecation-lint-nested.stderr create mode 100644 tests/ui/deprecation/deprecation-lint.rs create mode 100644 tests/ui/deprecation/deprecation-lint.stderr create mode 100644 tests/ui/deprecation/deprecation-sanity.rs create mode 100644 tests/ui/deprecation/deprecation-sanity.stderr create mode 100644 tests/ui/deprecation/derive_on_deprecated.rs create mode 100644 tests/ui/deprecation/derive_on_deprecated_forbidden.rs create mode 100644 tests/ui/deprecation/feature-gate-deprecated_suggestion.rs create mode 100644 tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr create mode 100644 tests/ui/deprecation/invalid-literal.rs create mode 100644 tests/ui/deprecation/invalid-literal.stderr create mode 100644 tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs create mode 100644 tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr create mode 100644 tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed create mode 100644 tests/ui/deprecation/issue-84637-deprecated-associated-function.rs create mode 100644 tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr create mode 100644 tests/ui/deprecation/staged-deprecation-in-future.rs create mode 100644 tests/ui/deprecation/staged-deprecation-in-future.stderr create mode 100644 tests/ui/deprecation/suggestion.fixed create mode 100644 tests/ui/deprecation/suggestion.rs create mode 100644 tests/ui/deprecation/suggestion.stderr create mode 100644 tests/ui/deprecation/try-macro-suggestion.rs create mode 100644 tests/ui/deprecation/try-macro-suggestion.stderr create mode 100644 tests/ui/deref-non-pointer.rs create mode 100644 tests/ui/deref-non-pointer.stderr create mode 100644 tests/ui/deref-patterns/basic.rs create mode 100644 tests/ui/deref-patterns/basic.run.stdout create mode 100644 tests/ui/deref-patterns/default-infer.rs create mode 100644 tests/ui/deref-patterns/gate.rs create mode 100644 tests/ui/deref-patterns/gate.stderr create mode 100644 tests/ui/deref-patterns/refs.rs create mode 100644 tests/ui/deref-rc.rs create mode 100644 tests/ui/deref.rs create mode 100644 tests/ui/derive-uninhabited-enum-38885.rs create mode 100644 tests/ui/derive-uninhabited-enum-38885.stderr create mode 100644 tests/ui/derived-errors/issue-30580.rs create mode 100644 tests/ui/derived-errors/issue-30580.stderr create mode 100644 tests/ui/derived-errors/issue-31997-1.rs create mode 100644 tests/ui/derived-errors/issue-31997-1.stderr create mode 100644 tests/ui/derived-errors/issue-31997.rs create mode 100644 tests/ui/derived-errors/issue-31997.stderr create mode 100644 tests/ui/derives/auxiliary/derive-marker-tricky.rs create mode 100644 tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs create mode 100644 tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr create mode 100644 tests/ui/derives/clone-debug-dead-code.rs create mode 100644 tests/ui/derives/clone-debug-dead-code.stderr create mode 100644 tests/ui/derives/derive-Debug-use-ufcs-struct.rs create mode 100644 tests/ui/derives/derive-Debug-use-ufcs-tuple.rs create mode 100644 tests/ui/derives/derive-assoc-type-not-impl.rs create mode 100644 tests/ui/derives/derive-assoc-type-not-impl.stderr create mode 100644 tests/ui/derives/derive-deadlock.rs create mode 100644 tests/ui/derives/derive-deadlock.stderr create mode 100644 tests/ui/derives/derive-hygiene.rs create mode 100644 tests/ui/derives/derive-macro-const-default.rs create mode 100644 tests/ui/derives/derive-marker-tricky.rs create mode 100644 tests/ui/derives/derive-multiple-with-packed.rs create mode 100644 tests/ui/derives/derive-on-trait-item-or-impl-item.rs create mode 100644 tests/ui/derives/derive-on-trait-item-or-impl-item.stderr create mode 100644 tests/ui/derives/derive-partial-ord.rs create mode 100644 tests/ui/derives/derive-renamed.rs create mode 100644 tests/ui/derives/derives-span-Clone-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-Clone-enum.rs create mode 100644 tests/ui/derives/derives-span-Clone-enum.stderr create mode 100644 tests/ui/derives/derives-span-Clone-struct.rs create mode 100644 tests/ui/derives/derives-span-Clone-struct.stderr create mode 100644 tests/ui/derives/derives-span-Clone-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-Clone-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-Debug-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-Debug-enum.rs create mode 100644 tests/ui/derives/derives-span-Debug-enum.stderr create mode 100644 tests/ui/derives/derives-span-Debug-struct.rs create mode 100644 tests/ui/derives/derives-span-Debug-struct.stderr create mode 100644 tests/ui/derives/derives-span-Debug-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-Debug-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-Default-struct.rs create mode 100644 tests/ui/derives/derives-span-Default-struct.stderr create mode 100644 tests/ui/derives/derives-span-Default-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-Default-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-Eq-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-Eq-enum.rs create mode 100644 tests/ui/derives/derives-span-Eq-enum.stderr create mode 100644 tests/ui/derives/derives-span-Eq-struct.rs create mode 100644 tests/ui/derives/derives-span-Eq-struct.stderr create mode 100644 tests/ui/derives/derives-span-Eq-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-Eq-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-Hash-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-Hash-enum.rs create mode 100644 tests/ui/derives/derives-span-Hash-enum.stderr create mode 100644 tests/ui/derives/derives-span-Hash-struct.rs create mode 100644 tests/ui/derives/derives-span-Hash-struct.stderr create mode 100644 tests/ui/derives/derives-span-Hash-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-Hash-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-Ord-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-Ord-enum.rs create mode 100644 tests/ui/derives/derives-span-Ord-enum.stderr create mode 100644 tests/ui/derives/derives-span-Ord-struct.rs create mode 100644 tests/ui/derives/derives-span-Ord-struct.stderr create mode 100644 tests/ui/derives/derives-span-Ord-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-Ord-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-PartialEq-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-PartialEq-enum.rs create mode 100644 tests/ui/derives/derives-span-PartialEq-enum.stderr create mode 100644 tests/ui/derives/derives-span-PartialEq-struct.rs create mode 100644 tests/ui/derives/derives-span-PartialEq-struct.stderr create mode 100644 tests/ui/derives/derives-span-PartialEq-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr create mode 100644 tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs create mode 100644 tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr create mode 100644 tests/ui/derives/derives-span-PartialOrd-enum.rs create mode 100644 tests/ui/derives/derives-span-PartialOrd-enum.stderr create mode 100644 tests/ui/derives/derives-span-PartialOrd-struct.rs create mode 100644 tests/ui/derives/derives-span-PartialOrd-struct.stderr create mode 100644 tests/ui/derives/derives-span-PartialOrd-tuple-struct.rs create mode 100644 tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr create mode 100644 tests/ui/derives/deriving-bounds.rs create mode 100644 tests/ui/derives/deriving-bounds.stderr create mode 100644 tests/ui/derives/deriving-copyclone.rs create mode 100644 tests/ui/derives/deriving-copyclone.stderr create mode 100644 tests/ui/derives/deriving-meta-empty-trait-list.rs create mode 100644 tests/ui/derives/deriving-meta-unknown-trait.rs create mode 100644 tests/ui/derives/deriving-meta-unknown-trait.stderr create mode 100644 tests/ui/derives/deriving-no-inner-impl-error-message.rs create mode 100644 tests/ui/derives/deriving-no-inner-impl-error-message.stderr create mode 100644 tests/ui/derives/deriving-non-type.rs create mode 100644 tests/ui/derives/deriving-non-type.stderr create mode 100644 tests/ui/derives/deriving-primitive.rs create mode 100644 tests/ui/derives/deriving-primitive.stderr create mode 100644 tests/ui/derives/deriving-with-repr-packed.rs create mode 100644 tests/ui/derives/deriving-with-repr-packed.stderr create mode 100644 tests/ui/derives/issue-36617.rs create mode 100644 tests/ui/derives/issue-36617.stderr create mode 100644 tests/ui/derives/issue-43023.rs create mode 100644 tests/ui/derives/issue-43023.stderr create mode 100644 tests/ui/derives/issue-91492.rs create mode 100644 tests/ui/derives/issue-91492.stderr create mode 100644 tests/ui/derives/issue-91550.rs create mode 100644 tests/ui/derives/issue-91550.stderr create mode 100644 tests/ui/derives/issue-97343.rs create mode 100644 tests/ui/derives/issue-97343.stderr create mode 100644 tests/ui/deriving/auxiliary/derive-no-std.rs create mode 100644 tests/ui/deriving/derive-no-std.rs create mode 100644 tests/ui/deriving/derive-partialord-correctness.rs create mode 100644 tests/ui/deriving/deriving-all-codegen.rs create mode 100644 tests/ui/deriving/deriving-all-codegen.stdout create mode 100644 tests/ui/deriving/deriving-associated-types.rs create mode 100644 tests/ui/deriving/deriving-bounds.rs create mode 100644 tests/ui/deriving/deriving-clone-array.rs create mode 100644 tests/ui/deriving/deriving-clone-enum.rs create mode 100644 tests/ui/deriving/deriving-clone-generic-enum.rs create mode 100644 tests/ui/deriving/deriving-clone-generic-struct.rs create mode 100644 tests/ui/deriving/deriving-clone-generic-tuple-struct.rs create mode 100644 tests/ui/deriving/deriving-clone-struct.rs create mode 100644 tests/ui/deriving/deriving-clone-tuple-struct.rs create mode 100644 tests/ui/deriving/deriving-cmp-generic-enum.rs create mode 100644 tests/ui/deriving/deriving-cmp-generic-struct-enum.rs create mode 100644 tests/ui/deriving/deriving-cmp-generic-struct.rs create mode 100644 tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs create mode 100644 tests/ui/deriving/deriving-cmp-shortcircuit.rs create mode 100644 tests/ui/deriving/deriving-copyclone.rs create mode 100644 tests/ui/deriving/deriving-default-box.rs create mode 100644 tests/ui/deriving/deriving-default-enum.rs create mode 100644 tests/ui/deriving/deriving-enum-single-variant.rs create mode 100644 tests/ui/deriving/deriving-eq-ord-boxed-slice.rs create mode 100644 tests/ui/deriving/deriving-hash.rs create mode 100644 tests/ui/deriving/deriving-in-fn.rs create mode 100644 tests/ui/deriving/deriving-in-macro.rs create mode 100644 tests/ui/deriving/deriving-meta-multiple.rs create mode 100644 tests/ui/deriving/deriving-meta.rs create mode 100644 tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs create mode 100644 tests/ui/deriving/deriving-show-2.rs create mode 100644 tests/ui/deriving/deriving-show.rs create mode 100644 tests/ui/deriving/deriving-via-extension-c-enum.rs create mode 100644 tests/ui/deriving/deriving-via-extension-enum.rs create mode 100644 tests/ui/deriving/deriving-via-extension-hash-enum.rs create mode 100644 tests/ui/deriving/deriving-via-extension-hash-struct.rs create mode 100644 tests/ui/deriving/deriving-via-extension-struct-empty.rs create mode 100644 tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs create mode 100644 tests/ui/deriving/deriving-via-extension-struct-tuple.rs create mode 100644 tests/ui/deriving/deriving-via-extension-struct.rs create mode 100644 tests/ui/deriving/deriving-via-extension-type-params.rs create mode 100644 tests/ui/deriving/deriving-with-helper.rs create mode 100644 tests/ui/deriving/deriving-with-repr-packed.rs create mode 100644 tests/ui/deriving/issue-103157.rs create mode 100644 tests/ui/deriving/issue-103157.stderr create mode 100644 tests/ui/deriving/issue-105101.rs create mode 100644 tests/ui/deriving/issue-105101.stderr create mode 100644 tests/ui/deriving/issue-19358.rs create mode 100644 tests/ui/deriving/issue-3935.rs create mode 100644 tests/ui/deriving/issue-58319.rs create mode 100644 tests/ui/deriving/issue-6341.rs create mode 100644 tests/ui/deriving/issue-89188-gat-hrtb.rs create mode 100644 tests/ui/dest-prop/skeptic-miscompile.rs create mode 100644 tests/ui/destructure-trait-ref.rs create mode 100644 tests/ui/destructure-trait-ref.stderr create mode 100644 tests/ui/destructuring-assignment/bad-expr-lhs.rs create mode 100644 tests/ui/destructuring-assignment/bad-expr-lhs.stderr create mode 100644 tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs create mode 100644 tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr create mode 100644 tests/ui/destructuring-assignment/drop-order.rs create mode 100644 tests/ui/destructuring-assignment/nested_destructure.rs create mode 100644 tests/ui/destructuring-assignment/note-unsupported.rs create mode 100644 tests/ui/destructuring-assignment/note-unsupported.stderr create mode 100644 tests/ui/destructuring-assignment/slice_destructure.rs create mode 100644 tests/ui/destructuring-assignment/slice_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/slice_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs create mode 100644 tests/ui/destructuring-assignment/struct_destructure.rs create mode 100644 tests/ui/destructuring-assignment/struct_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/struct_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/tuple_destructure.rs create mode 100644 tests/ui/destructuring-assignment/tuple_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/tuple_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/tuple_struct_destructure.rs create mode 100644 tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs create mode 100644 tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr create mode 100644 tests/ui/destructuring-assignment/warn-unused-duplication.rs create mode 100644 tests/ui/destructuring-assignment/warn-unused-duplication.stderr create mode 100644 tests/ui/diagnostic-width/E0271.rs create mode 100644 tests/ui/diagnostic-width/E0271.stderr create mode 100644 tests/ui/diagnostic-width/flag-human.rs create mode 100644 tests/ui/diagnostic-width/flag-human.stderr create mode 100644 tests/ui/diagnostic-width/flag-json.rs create mode 100644 tests/ui/diagnostic-width/flag-json.stderr create mode 100644 tests/ui/diagnostic-width/long-E0308.rs create mode 100644 tests/ui/diagnostic-width/long-E0308.stderr create mode 100644 tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs create mode 100644 tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr create mode 100644 tests/ui/diagnostic-width/non-whitespace-trimming-2.rs create mode 100644 tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr create mode 100644 tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs create mode 100644 tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr create mode 100644 tests/ui/diagnostic-width/non-whitespace-trimming.rs create mode 100644 tests/ui/diagnostic-width/non-whitespace-trimming.stderr create mode 100644 tests/ui/diagnostic-width/tabs-trimming.rs create mode 100644 tests/ui/diagnostic-width/tabs-trimming.stderr create mode 100644 tests/ui/diagnostic-width/whitespace-trimming-2.rs create mode 100644 tests/ui/diagnostic-width/whitespace-trimming-2.stderr create mode 100644 tests/ui/diagnostic-width/whitespace-trimming.rs create mode 100644 tests/ui/diagnostic-width/whitespace-trimming.stderr create mode 100644 tests/ui/did_you_mean/E0178.rs create mode 100644 tests/ui/did_you_mean/E0178.stderr create mode 100644 tests/ui/did_you_mean/bad-assoc-expr.rs create mode 100644 tests/ui/did_you_mean/bad-assoc-expr.stderr create mode 100644 tests/ui/did_you_mean/bad-assoc-pat.rs create mode 100644 tests/ui/did_you_mean/bad-assoc-pat.stderr create mode 100644 tests/ui/did_you_mean/bad-assoc-ty.rs create mode 100644 tests/ui/did_you_mean/bad-assoc-ty.stderr create mode 100644 tests/ui/did_you_mean/brackets-to-braces-single-element.rs create mode 100644 tests/ui/did_you_mean/brackets-to-braces-single-element.stderr create mode 100644 tests/ui/did_you_mean/compatible-variants-in-pat.rs create mode 100644 tests/ui/did_you_mean/compatible-variants-in-pat.stderr create mode 100644 tests/ui/did_you_mean/compatible-variants.rs create mode 100644 tests/ui/did_you_mean/compatible-variants.stderr create mode 100644 tests/ui/did_you_mean/issue-103909.rs create mode 100644 tests/ui/did_you_mean/issue-103909.stderr create mode 100644 tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs create mode 100644 tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr create mode 100644 tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs create mode 100644 tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr create mode 100644 tests/ui/did_you_mean/issue-31424.rs create mode 100644 tests/ui/did_you_mean/issue-31424.stderr create mode 100644 tests/ui/did_you_mean/issue-34126.rs create mode 100644 tests/ui/did_you_mean/issue-34126.stderr create mode 100644 tests/ui/did_you_mean/issue-34337.rs create mode 100644 tests/ui/did_you_mean/issue-34337.stderr create mode 100644 tests/ui/did_you_mean/issue-35937.rs create mode 100644 tests/ui/did_you_mean/issue-35937.stderr create mode 100644 tests/ui/did_you_mean/issue-36798.rs create mode 100644 tests/ui/did_you_mean/issue-36798.stderr create mode 100644 tests/ui/did_you_mean/issue-36798_unknown_field.rs create mode 100644 tests/ui/did_you_mean/issue-36798_unknown_field.stderr create mode 100644 tests/ui/did_you_mean/issue-37139.rs create mode 100644 tests/ui/did_you_mean/issue-37139.stderr create mode 100644 tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs create mode 100644 tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr create mode 100644 tests/ui/did_you_mean/issue-38147-1.rs create mode 100644 tests/ui/did_you_mean/issue-38147-1.stderr create mode 100644 tests/ui/did_you_mean/issue-38147-2.rs create mode 100644 tests/ui/did_you_mean/issue-38147-2.stderr create mode 100644 tests/ui/did_you_mean/issue-38147-3.rs create mode 100644 tests/ui/did_you_mean/issue-38147-3.stderr create mode 100644 tests/ui/did_you_mean/issue-38147-4.rs create mode 100644 tests/ui/did_you_mean/issue-38147-4.stderr create mode 100644 tests/ui/did_you_mean/issue-39544.rs create mode 100644 tests/ui/did_you_mean/issue-39544.stderr create mode 100644 tests/ui/did_you_mean/issue-39802-show-5-trait-impls.rs create mode 100644 tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr create mode 100644 tests/ui/did_you_mean/issue-40006.rs create mode 100644 tests/ui/did_you_mean/issue-40006.stderr create mode 100644 tests/ui/did_you_mean/issue-40396.rs create mode 100644 tests/ui/did_you_mean/issue-40396.stderr create mode 100644 tests/ui/did_you_mean/issue-40823.rs create mode 100644 tests/ui/did_you_mean/issue-40823.stderr create mode 100644 tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed create mode 100644 tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs create mode 100644 tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr create mode 100644 tests/ui/did_you_mean/issue-42599_available_fields_note.rs create mode 100644 tests/ui/did_you_mean/issue-42599_available_fields_note.stderr create mode 100644 tests/ui/did_you_mean/issue-42764.rs create mode 100644 tests/ui/did_you_mean/issue-42764.stderr create mode 100644 tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs create mode 100644 tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr create mode 100644 tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs create mode 100644 tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr create mode 100644 tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs create mode 100644 tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr create mode 100644 tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs create mode 100644 tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr create mode 100644 tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs create mode 100644 tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr create mode 100644 tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs create mode 100644 tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr create mode 100644 tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs create mode 100644 tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr create mode 100644 tests/ui/did_you_mean/issue-54109-without-witness.fixed create mode 100644 tests/ui/did_you_mean/issue-54109-without-witness.rs create mode 100644 tests/ui/did_you_mean/issue-54109-without-witness.stderr create mode 100644 tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs create mode 100644 tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr create mode 100644 tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs create mode 100644 tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr create mode 100644 tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs create mode 100644 tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr create mode 100644 tests/ui/did_you_mean/pub-macro-rules.rs create mode 100644 tests/ui/did_you_mean/pub-macro-rules.stderr create mode 100644 tests/ui/did_you_mean/recursion_limit.rs create mode 100644 tests/ui/did_you_mean/recursion_limit.stderr create mode 100644 tests/ui/did_you_mean/recursion_limit_deref.rs create mode 100644 tests/ui/did_you_mean/recursion_limit_deref.stderr create mode 100644 tests/ui/did_you_mean/recursion_limit_macro.rs create mode 100644 tests/ui/did_you_mean/recursion_limit_macro.stderr create mode 100644 tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed create mode 100644 tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs create mode 100644 tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr create mode 100644 tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs create mode 100644 tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr create mode 100644 tests/ui/did_you_mean/use_instead_of_import.fixed create mode 100644 tests/ui/did_you_mean/use_instead_of_import.rs create mode 100644 tests/ui/did_you_mean/use_instead_of_import.stderr create mode 100644 tests/ui/directory_ownership/foo/compiletest-ignore-dir create mode 100644 tests/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs create mode 100644 tests/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs create mode 100644 tests/ui/directory_ownership/macro-expanded-mod.rs create mode 100644 tests/ui/directory_ownership/macro-expanded-mod.stderr create mode 100644 tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs create mode 100644 tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs create mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux1.rs create mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir create mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs create mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux2.rs create mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux3.rs create mode 100644 tests/ui/directory_ownership/non-inline-mod-restriction.rs create mode 100644 tests/ui/directory_ownership/non-inline-mod-restriction.stderr create mode 100644 tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed create mode 100644 tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs create mode 100644 tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr create mode 100644 tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed create mode 100644 tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs create mode 100644 tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr create mode 100644 tests/ui/disambiguate-identical-names.rs create mode 100644 tests/ui/disambiguate-identical-names.stderr create mode 100644 tests/ui/discrim/discrim-ill-typed.rs create mode 100644 tests/ui/discrim/discrim-ill-typed.stderr create mode 100644 tests/ui/discrim/discrim-overflow-2.rs create mode 100644 tests/ui/discrim/discrim-overflow-2.stderr create mode 100644 tests/ui/discrim/discrim-overflow.rs create mode 100644 tests/ui/discrim/discrim-overflow.stderr create mode 100644 tests/ui/diverging-fallback-method-chain.rs create mode 100644 tests/ui/diverging-fallback-option.rs create mode 100644 tests/ui/diverging-fn-tail-35849.rs create mode 100644 tests/ui/diverging-fn-tail-35849.stderr create mode 100644 tests/ui/does-nothing.rs create mode 100644 tests/ui/does-nothing.stderr create mode 100644 tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs create mode 100644 tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr create mode 100644 tests/ui/dollar-crate/dollar-crate-is-keyword.rs create mode 100644 tests/ui/dollar-crate/dollar-crate-is-keyword.stderr create mode 100644 tests/ui/dont-suggest-private-trait-method.rs create mode 100644 tests/ui/dont-suggest-private-trait-method.stderr create mode 100644 tests/ui/double-ref.rs create mode 100644 tests/ui/double-type-import.rs create mode 100644 tests/ui/double-type-import.stderr create mode 100644 tests/ui/drop-bounds/drop-bounds-impl-drop.rs create mode 100644 tests/ui/drop-bounds/drop-bounds.rs create mode 100644 tests/ui/drop-bounds/drop-bounds.stderr create mode 100644 tests/ui/drop/auxiliary/dropck_eyepatch_extern_crate.rs create mode 100644 tests/ui/drop/auxiliary/inline_dtor.rs create mode 100644 tests/ui/drop/auxiliary/issue-10028.rs create mode 100644 tests/ui/drop/drop-foreign-fundamental.rs create mode 100644 tests/ui/drop/drop-foreign-fundamental.stderr create mode 100644 tests/ui/drop/drop-if-let-binding.rs create mode 100644 tests/ui/drop/drop-on-empty-block-exit.rs create mode 100644 tests/ui/drop/drop-on-ret.rs create mode 100644 tests/ui/drop/drop-struct-as-object.rs create mode 100644 tests/ui/drop/drop-trait-enum.rs create mode 100644 tests/ui/drop/drop-trait-generic.rs create mode 100644 tests/ui/drop/drop-trait.rs create mode 100644 tests/ui/drop/drop-uninhabited-enum.rs create mode 100644 tests/ui/drop/drop-with-type-ascription-1.rs create mode 100644 tests/ui/drop/drop-with-type-ascription-2.rs create mode 100644 tests/ui/drop/drop_order.rs create mode 100644 tests/ui/drop/dropck-eyepatch-extern-crate.rs create mode 100644 tests/ui/drop/dropck-eyepatch-reorder.rs create mode 100644 tests/ui/drop/dropck-eyepatch.rs create mode 100644 tests/ui/drop/dropck_legal_cycles.rs create mode 100644 tests/ui/drop/dynamic-drop-async.rs create mode 100644 tests/ui/drop/dynamic-drop.rs create mode 100644 tests/ui/drop/issue-100276.rs create mode 100644 tests/ui/drop/issue-10028.rs create mode 100644 tests/ui/drop/issue-103107.rs create mode 100644 tests/ui/drop/issue-17718-const-destructors.rs create mode 100644 tests/ui/drop/issue-21486.rs create mode 100644 tests/ui/drop/issue-23338-ensure-param-drop-order.rs create mode 100644 tests/ui/drop/issue-2734.rs create mode 100644 tests/ui/drop/issue-30018-nopanic.rs create mode 100644 tests/ui/drop/issue-35546.rs create mode 100644 tests/ui/drop/issue-48962.rs create mode 100644 tests/ui/drop/issue-90752-raw-ptr-shenanigans.rs create mode 100644 tests/ui/drop/issue-90752.rs create mode 100644 tests/ui/drop/no-drop-flag-size.rs create mode 100644 tests/ui/drop/nondrop-cycle.rs create mode 100644 tests/ui/drop/repeat-drop-2.rs create mode 100644 tests/ui/drop/repeat-drop-2.stderr create mode 100644 tests/ui/drop/repeat-drop.rs create mode 100644 tests/ui/drop/terminate-in-initializer.rs create mode 100644 tests/ui/drop/use_inline_dtor.rs create mode 100644 tests/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs create mode 100644 tests/ui/dropck/cleanup-arm-conditional.rs create mode 100644 tests/ui/dropck/drop-on-non-struct.rs create mode 100644 tests/ui/dropck/drop-on-non-struct.stderr create mode 100644 tests/ui/dropck/drop-with-active-borrows-1.rs create mode 100644 tests/ui/dropck/drop-with-active-borrows-1.stderr create mode 100644 tests/ui/dropck/drop-with-active-borrows-2.rs create mode 100644 tests/ui/dropck/drop-with-active-borrows-2.stderr create mode 100644 tests/ui/dropck/dropck-eyepatch-extern-crate.rs create mode 100644 tests/ui/dropck/dropck-eyepatch-extern-crate.stderr create mode 100644 tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs create mode 100644 tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr create mode 100644 tests/ui/dropck/dropck-eyepatch-reorder.rs create mode 100644 tests/ui/dropck/dropck-eyepatch-reorder.stderr create mode 100644 tests/ui/dropck/dropck-eyepatch.rs create mode 100644 tests/ui/dropck/dropck-eyepatch.stderr create mode 100644 tests/ui/dropck/dropck-union.rs create mode 100644 tests/ui/dropck/dropck-union.stderr create mode 100644 tests/ui/dropck/dropck_fn_type.rs create mode 100644 tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs create mode 100644 tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr create mode 100644 tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs create mode 100644 tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr create mode 100644 tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs create mode 100644 tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr create mode 100644 tests/ui/dropck/dropck_trait_cycle_checked.rs create mode 100644 tests/ui/dropck/dropck_trait_cycle_checked.stderr create mode 100644 tests/ui/dropck/dropck_traits.rs create mode 100644 tests/ui/dropck/issue-24805-dropck-itemless.rs create mode 100644 tests/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs create mode 100644 tests/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs create mode 100644 tests/ui/dropck/issue-28498-ugeh-with-trait-bound.rs create mode 100644 tests/ui/dropck/issue-29844.rs create mode 100644 tests/ui/dropck/issue-34053.rs create mode 100644 tests/ui/dropck/issue-38868.rs create mode 100644 tests/ui/dropck/issue-38868.stderr create mode 100644 tests/ui/dropck/issue-54943-1.rs create mode 100644 tests/ui/dropck/issue-54943-2.rs create mode 100644 tests/ui/dropck/reject-specialized-drops-8142.rs create mode 100644 tests/ui/dropck/reject-specialized-drops-8142.stderr create mode 100644 tests/ui/dropck/relate_lt_in_type_outlives_bound.rs create mode 100644 tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr create mode 100644 tests/ui/dst/dst-bad-assign-2.rs create mode 100644 tests/ui/dst/dst-bad-assign-2.stderr create mode 100644 tests/ui/dst/dst-bad-assign-3.rs create mode 100644 tests/ui/dst/dst-bad-assign-3.stderr create mode 100644 tests/ui/dst/dst-bad-assign.rs create mode 100644 tests/ui/dst/dst-bad-assign.stderr create mode 100644 tests/ui/dst/dst-bad-coerce1.rs create mode 100644 tests/ui/dst/dst-bad-coerce1.stderr create mode 100644 tests/ui/dst/dst-bad-coerce2.rs create mode 100644 tests/ui/dst/dst-bad-coerce2.stderr create mode 100644 tests/ui/dst/dst-bad-coerce3.rs create mode 100644 tests/ui/dst/dst-bad-coerce3.stderr create mode 100644 tests/ui/dst/dst-bad-coerce4.rs create mode 100644 tests/ui/dst/dst-bad-coerce4.stderr create mode 100644 tests/ui/dst/dst-bad-coercions.rs create mode 100644 tests/ui/dst/dst-bad-coercions.stderr create mode 100644 tests/ui/dst/dst-bad-deep-2.rs create mode 100644 tests/ui/dst/dst-bad-deep-2.stderr create mode 100644 tests/ui/dst/dst-bad-deep.rs create mode 100644 tests/ui/dst/dst-bad-deep.stderr create mode 100644 tests/ui/dst/dst-index.rs create mode 100644 tests/ui/dst/dst-index.stderr create mode 100644 tests/ui/dst/dst-object-from-unsized-type.rs create mode 100644 tests/ui/dst/dst-object-from-unsized-type.stderr create mode 100644 tests/ui/dst/dst-rvalue.rs create mode 100644 tests/ui/dst/dst-rvalue.stderr create mode 100644 tests/ui/dst/dst-sized-trait-param.rs create mode 100644 tests/ui/dst/dst-sized-trait-param.stderr create mode 100644 tests/ui/dupe-first-attr.rc create mode 100644 tests/ui/duplicate/dupe-symbols-1.rs create mode 100644 tests/ui/duplicate/dupe-symbols-1.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-2.rs create mode 100644 tests/ui/duplicate/dupe-symbols-2.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-3.rs create mode 100644 tests/ui/duplicate/dupe-symbols-3.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-4.rs create mode 100644 tests/ui/duplicate/dupe-symbols-4.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-5.rs create mode 100644 tests/ui/duplicate/dupe-symbols-5.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-6.rs create mode 100644 tests/ui/duplicate/dupe-symbols-6.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-7.rs create mode 100644 tests/ui/duplicate/dupe-symbols-7.stderr create mode 100644 tests/ui/duplicate/dupe-symbols-8.rs create mode 100644 tests/ui/duplicate/dupe-symbols-8.stderr create mode 100644 tests/ui/duplicate/duplicate-check-macro-exports.rs create mode 100644 tests/ui/duplicate/duplicate-check-macro-exports.stderr create mode 100644 tests/ui/duplicate/duplicate-parameter.rs create mode 100644 tests/ui/duplicate/duplicate-parameter.stderr create mode 100644 tests/ui/duplicate/duplicate-type-parameter.rs create mode 100644 tests/ui/duplicate/duplicate-type-parameter.stderr create mode 100644 tests/ui/duplicate_entry_error.rs create mode 100644 tests/ui/duplicate_entry_error.stderr create mode 100644 tests/ui/dyn-drop/dyn-drop.rs create mode 100644 tests/ui/dyn-drop/dyn-drop.stderr create mode 100644 tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed create mode 100644 tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs create mode 100644 tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr create mode 100644 tests/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs create mode 100644 tests/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs create mode 100644 tests/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs create mode 100644 tests/ui/dyn-keyword/dyn-2018-edition-lint.rs create mode 100644 tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr create mode 100644 tests/ui/dyn-keyword/dyn-2021-edition-error.rs create mode 100644 tests/ui/dyn-keyword/dyn-2021-edition-error.stderr create mode 100644 tests/ui/dyn-keyword/dyn-angle-brackets.fixed create mode 100644 tests/ui/dyn-keyword/dyn-angle-brackets.rs create mode 100644 tests/ui/dyn-keyword/dyn-angle-brackets.stderr create mode 100644 tests/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs create mode 100644 tests/ui/dyn-star/align.normal.stderr create mode 100644 tests/ui/dyn-star/align.over_aligned.stderr create mode 100644 tests/ui/dyn-star/align.rs create mode 100644 tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs create mode 100644 tests/ui/dyn-star/box.rs create mode 100644 tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs create mode 100644 tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr create mode 100644 tests/ui/dyn-star/check-size-at-cast-polymorphic.rs create mode 100644 tests/ui/dyn-star/check-size-at-cast.rs create mode 100644 tests/ui/dyn-star/check-size-at-cast.stderr create mode 100644 tests/ui/dyn-star/const.rs create mode 100644 tests/ui/dyn-star/dispatch-on-pin-mut.rs create mode 100644 tests/ui/dyn-star/dispatch-on-pin-mut.run.stdout create mode 100644 tests/ui/dyn-star/dispatch-on-pin-mut.stderr create mode 100644 tests/ui/dyn-star/dont-unsize-coerce-dyn-star.rs create mode 100644 tests/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout create mode 100644 tests/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr create mode 100644 tests/ui/dyn-star/drop.rs create mode 100644 tests/ui/dyn-star/drop.run.stdout create mode 100644 tests/ui/dyn-star/dyn-async-trait.rs create mode 100644 tests/ui/dyn-star/dyn-star-to-dyn.rs create mode 100644 tests/ui/dyn-star/dyn-star-to-dyn.stderr create mode 100644 tests/ui/dyn-star/dyn-to-rigid.rs create mode 100644 tests/ui/dyn-star/dyn-to-rigid.stderr create mode 100644 tests/ui/dyn-star/error.rs create mode 100644 tests/ui/dyn-star/error.stderr create mode 100644 tests/ui/dyn-star/feature-gate-dyn_star.rs create mode 100644 tests/ui/dyn-star/feature-gate-dyn_star.stderr create mode 100644 tests/ui/dyn-star/issue-102430.rs create mode 100644 tests/ui/dyn-star/make-dyn-star.rs create mode 100644 tests/ui/dyn-star/method.rs create mode 100644 tests/ui/dyn-star/no-explicit-dyn-star-cast.rs create mode 100644 tests/ui/dyn-star/no-explicit-dyn-star-cast.stderr create mode 100644 tests/ui/dyn-star/no-explicit-dyn-star.rs create mode 100644 tests/ui/dyn-star/no-explicit-dyn-star.stderr create mode 100644 tests/ui/dyn-star/no-implicit-dyn-star.rs create mode 100644 tests/ui/dyn-star/no-implicit-dyn-star.stderr create mode 100644 tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs create mode 100644 tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr create mode 100644 tests/ui/dyn-star/return.rs create mode 100644 tests/ui/dyn-star/return.stderr create mode 100644 tests/ui/dyn-star/syntax.rs create mode 100644 tests/ui/dyn-star/unsize-into-ref-dyn-star.rs create mode 100644 tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr create mode 100644 tests/ui/dyn-star/upcast.rs create mode 100644 tests/ui/dyn-star/upcast.stderr create mode 100644 tests/ui/dynamically-sized-types/dst-coerce-custom.rs create mode 100644 tests/ui/dynamically-sized-types/dst-coerce-rc.rs create mode 100644 tests/ui/dynamically-sized-types/dst-coercions.rs create mode 100644 tests/ui/dynamically-sized-types/dst-deref-mut.rs create mode 100644 tests/ui/dynamically-sized-types/dst-deref.rs create mode 100644 tests/ui/dynamically-sized-types/dst-field-align.rs create mode 100644 tests/ui/dynamically-sized-types/dst-index.rs create mode 100644 tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs create mode 100644 tests/ui/dynamically-sized-types/dst-raw.rs create mode 100644 tests/ui/dynamically-sized-types/dst-struct-sole.rs create mode 100644 tests/ui/dynamically-sized-types/dst-struct.rs create mode 100644 tests/ui/dynamically-sized-types/dst-trait-tuple.rs create mode 100644 tests/ui/dynamically-sized-types/dst-trait.rs create mode 100644 tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs create mode 100644 tests/ui/dynamically-sized-types/dst-tuple-sole.rs create mode 100644 tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs create mode 100644 tests/ui/dynamically-sized-types/dst-tuple.rs create mode 100644 tests/ui/early-ret-binop-add.rs create mode 100644 tests/ui/editions/async-block-2015.rs create mode 100644 tests/ui/editions/async-block-2015.stderr create mode 100644 tests/ui/editions/auxiliary/absolute.rs create mode 100644 tests/ui/editions/auxiliary/edition-extern-crate-allowed.rs create mode 100644 tests/ui/editions/auxiliary/edition-imports-2015.rs create mode 100644 tests/ui/editions/auxiliary/edition-imports-2018.rs create mode 100644 tests/ui/editions/auxiliary/edition-kw-macro-2015.rs create mode 100644 tests/ui/editions/auxiliary/edition-kw-macro-2018.rs create mode 100644 tests/ui/editions/dyn-trait-sugg-2021.rs create mode 100644 tests/ui/editions/dyn-trait-sugg-2021.stderr create mode 100644 tests/ui/editions/edition-extern-crate-allowed.rs create mode 100644 tests/ui/editions/edition-extern-crate-allowed.stderr create mode 100644 tests/ui/editions/edition-feature-ok.rs create mode 100644 tests/ui/editions/edition-feature-redundant.rs create mode 100644 tests/ui/editions/edition-feature-redundant.stderr create mode 100644 tests/ui/editions/edition-imports-2015.rs create mode 100644 tests/ui/editions/edition-imports-2015.stderr create mode 100644 tests/ui/editions/edition-imports-2018.rs create mode 100644 tests/ui/editions/edition-imports-2018.stderr create mode 100644 tests/ui/editions/edition-imports-virtual-2015-ambiguity.rs create mode 100644 tests/ui/editions/edition-imports-virtual-2015-gated.rs create mode 100644 tests/ui/editions/edition-imports-virtual-2015-gated.stderr create mode 100644 tests/ui/editions/edition-keywords-2015-2015-expansion.rs create mode 100644 tests/ui/editions/edition-keywords-2015-2015-parsing.rs create mode 100644 tests/ui/editions/edition-keywords-2015-2015-parsing.stderr create mode 100644 tests/ui/editions/edition-keywords-2015-2015.rs create mode 100644 tests/ui/editions/edition-keywords-2015-2018-expansion.rs create mode 100644 tests/ui/editions/edition-keywords-2015-2018-expansion.stderr create mode 100644 tests/ui/editions/edition-keywords-2015-2018-parsing.rs create mode 100644 tests/ui/editions/edition-keywords-2015-2018-parsing.stderr create mode 100644 tests/ui/editions/edition-keywords-2015-2018.rs create mode 100644 tests/ui/editions/edition-keywords-2018-2015-expansion.rs create mode 100644 tests/ui/editions/edition-keywords-2018-2015-parsing.rs create mode 100644 tests/ui/editions/edition-keywords-2018-2015-parsing.stderr create mode 100644 tests/ui/editions/edition-keywords-2018-2015.rs create mode 100644 tests/ui/editions/edition-keywords-2018-2018-expansion.rs create mode 100644 tests/ui/editions/edition-keywords-2018-2018-expansion.stderr create mode 100644 tests/ui/editions/edition-keywords-2018-2018-parsing.rs create mode 100644 tests/ui/editions/edition-keywords-2018-2018-parsing.stderr create mode 100644 tests/ui/editions/edition-keywords-2018-2018.rs create mode 100644 tests/ui/editions/edition-raw-pointer-method-2015.rs create mode 100644 tests/ui/editions/edition-raw-pointer-method-2015.stderr create mode 100644 tests/ui/editions/edition-raw-pointer-method-2018.rs create mode 100644 tests/ui/editions/edition-raw-pointer-method-2018.stderr create mode 100644 tests/ui/editions/epoch-gate-feature.rs create mode 100644 tests/ui/elide-errors-on-mismatched-tuple.rs create mode 100644 tests/ui/elide-errors-on-mismatched-tuple.stderr create mode 100644 tests/ui/elided-test.rs create mode 100644 tests/ui/elided-test.stderr create mode 100644 tests/ui/else-if.rs create mode 100644 tests/ui/empty-allocation-non-null.rs create mode 100644 tests/ui/empty-allocation-rvalue-non-null.rs create mode 100644 tests/ui/empty-type-parameter-list.rs create mode 100644 tests/ui/empty/auxiliary/empty-struct.rs create mode 100644 tests/ui/empty/auxiliary/two_macros.rs create mode 100644 tests/ui/empty/empty-attributes.rs create mode 100644 tests/ui/empty/empty-attributes.stderr create mode 100644 tests/ui/empty/empty-comment.rs create mode 100644 tests/ui/empty/empty-comment.stderr create mode 100644 tests/ui/empty/empty-linkname.rs create mode 100644 tests/ui/empty/empty-linkname.stderr create mode 100644 tests/ui/empty/empty-macro-use.rs create mode 100644 tests/ui/empty/empty-macro-use.stderr create mode 100644 tests/ui/empty/empty-never-array.rs create mode 100644 tests/ui/empty/empty-never-array.stderr create mode 100644 tests/ui/empty/empty-struct-braces-expr.rs create mode 100644 tests/ui/empty/empty-struct-braces-expr.stderr create mode 100644 tests/ui/empty/empty-struct-braces-pat-1.rs create mode 100644 tests/ui/empty/empty-struct-braces-pat-1.stderr create mode 100644 tests/ui/empty/empty-struct-braces-pat-2.rs create mode 100644 tests/ui/empty/empty-struct-braces-pat-2.stderr create mode 100644 tests/ui/empty/empty-struct-braces-pat-3.rs create mode 100644 tests/ui/empty/empty-struct-braces-pat-3.stderr create mode 100644 tests/ui/empty/empty-struct-tuple-pat.rs create mode 100644 tests/ui/empty/empty-struct-tuple-pat.stderr create mode 100644 tests/ui/empty/empty-struct-unit-expr.rs create mode 100644 tests/ui/empty/empty-struct-unit-expr.stderr create mode 100644 tests/ui/empty/empty-struct-unit-pat.rs create mode 100644 tests/ui/empty/empty-struct-unit-pat.stderr create mode 100644 tests/ui/empty/issue-37026.rs create mode 100644 tests/ui/empty/issue-37026.stderr create mode 100644 tests/ui/empty/no-link.rs create mode 100644 tests/ui/empty_global_asm.rs create mode 100644 tests/ui/entry-point/auxiliary/main_functions.rs create mode 100644 tests/ui/entry-point/imported_main_conflict.rs create mode 100644 tests/ui/entry-point/imported_main_conflict.stderr create mode 100644 tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs create mode 100644 tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr create mode 100644 tests/ui/entry-point/imported_main_const_forbidden.rs create mode 100644 tests/ui/entry-point/imported_main_const_forbidden.stderr create mode 100644 tests/ui/entry-point/imported_main_from_extern_crate.rs create mode 100644 tests/ui/entry-point/imported_main_from_inner_mod.rs create mode 100644 tests/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs create mode 100644 tests/ui/enum-discriminant/actually_not_an_enum-discriminant.rs create mode 100644 tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs create mode 100644 tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr create mode 100644 tests/ui/enum-discriminant/arbitrary_enum_discriminant.rs create mode 100644 tests/ui/enum-discriminant/discriminant_size.rs create mode 100644 tests/ui/enum-discriminant/discriminant_size.stderr create mode 100644 tests/ui/enum-discriminant/discriminant_value-wrapper.rs create mode 100644 tests/ui/enum-discriminant/discriminant_value.rs create mode 100644 tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.rs create mode 100644 tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr create mode 100644 tests/ui/enum-discriminant/get_discr.rs create mode 100644 tests/ui/enum-discriminant/issue-104519.rs create mode 100644 tests/ui/enum-discriminant/issue-43398.rs create mode 100644 tests/ui/enum-discriminant/issue-43398.stderr create mode 100644 tests/ui/enum-discriminant/issue-46519.rs create mode 100644 tests/ui/enum-discriminant/issue-51582.rs create mode 100644 tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs create mode 100644 tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr create mode 100644 tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs create mode 100644 tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr create mode 100644 tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs create mode 100644 tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr create mode 100644 tests/ui/enum-discriminant/issue-70509-partial_eq.rs create mode 100644 tests/ui/enum-discriminant/issue-70509-partial_eq.stderr create mode 100644 tests/ui/enum-discriminant/issue-72554.rs create mode 100644 tests/ui/enum-discriminant/issue-72554.stderr create mode 100644 tests/ui/enum-discriminant/issue-90038.rs create mode 100644 tests/ui/enum-discriminant/niche-prefer-zero.rs create mode 100644 tests/ui/enum-discriminant/niche.rs create mode 100644 tests/ui/enum-discriminant/repr128.rs create mode 100644 tests/ui/enum-discriminant/repr128.stderr create mode 100644 tests/ui/enum/enum-and-module-in-same-scope.rs create mode 100644 tests/ui/enum/enum-and-module-in-same-scope.stderr create mode 100644 tests/ui/enum/enum-discrim-autosizing.rs create mode 100644 tests/ui/enum/enum-discrim-autosizing.stderr create mode 100644 tests/ui/enum/enum-discrim-too-small.rs create mode 100644 tests/ui/enum/enum-discrim-too-small.stderr create mode 100644 tests/ui/enum/enum-discrim-too-small2.rs create mode 100644 tests/ui/enum/enum-discrim-too-small2.stderr create mode 100644 tests/ui/enum/enum-in-scope.rs create mode 100644 tests/ui/enum/enum-in-scope.stderr create mode 100644 tests/ui/enum/enum-size-variance.rs create mode 100644 tests/ui/enum/enum-size-variance.stderr create mode 100644 tests/ui/enum/enum-to-float-cast-2.rs create mode 100644 tests/ui/enum/enum-to-float-cast-2.stderr create mode 100644 tests/ui/enum/enum-to-float-cast.rs create mode 100644 tests/ui/enum/enum-to-float-cast.stderr create mode 100644 tests/ui/enum/enum-variant-type-2.rs create mode 100644 tests/ui/enum/enum-variant-type-2.stderr create mode 100644 tests/ui/enum/issue-42747.rs create mode 100644 tests/ui/enum/issue-67945-1.rs create mode 100644 tests/ui/enum/issue-67945-1.stderr create mode 100644 tests/ui/enum/issue-67945-2.rs create mode 100644 tests/ui/enum/issue-67945-2.stderr create mode 100644 tests/ui/enum/nested-enum.rs create mode 100644 tests/ui/enum/nested-enum.stderr create mode 100644 tests/ui/enum/suggest-default-attribute.rs create mode 100644 tests/ui/enum/suggest-default-attribute.stderr create mode 100644 tests/ui/enum/union-in-enum.rs create mode 100644 tests/ui/env-args-reverse-iterator.rs create mode 100644 tests/ui/env-funky-keys.rs create mode 100644 tests/ui/env-null-vars.rs create mode 100644 tests/ui/env-vars.rs create mode 100644 tests/ui/error-codes/E0001.rs create mode 100644 tests/ui/error-codes/E0001.stderr create mode 100644 tests/ui/error-codes/E0004-2.rs create mode 100644 tests/ui/error-codes/E0004-2.stderr create mode 100644 tests/ui/error-codes/E0004.rs create mode 100644 tests/ui/error-codes/E0004.stderr create mode 100644 tests/ui/error-codes/E0005.rs create mode 100644 tests/ui/error-codes/E0005.stderr create mode 100644 tests/ui/error-codes/E0010-teach.rs create mode 100644 tests/ui/error-codes/E0010-teach.stderr create mode 100644 tests/ui/error-codes/E0010.rs create mode 100644 tests/ui/error-codes/E0010.stderr create mode 100644 tests/ui/error-codes/E0013.rs create mode 100644 tests/ui/error-codes/E0013.stderr create mode 100644 tests/ui/error-codes/E0015.rs create mode 100644 tests/ui/error-codes/E0015.stderr create mode 100644 tests/ui/error-codes/E0017.rs create mode 100644 tests/ui/error-codes/E0017.stderr create mode 100644 tests/ui/error-codes/E0023.rs create mode 100644 tests/ui/error-codes/E0023.stderr create mode 100644 tests/ui/error-codes/E0025.rs create mode 100644 tests/ui/error-codes/E0025.stderr create mode 100644 tests/ui/error-codes/E0026-teach.rs create mode 100644 tests/ui/error-codes/E0026-teach.stderr create mode 100644 tests/ui/error-codes/E0026.rs create mode 100644 tests/ui/error-codes/E0026.stderr create mode 100644 tests/ui/error-codes/E0027.rs create mode 100644 tests/ui/error-codes/E0027.stderr create mode 100644 tests/ui/error-codes/E0029-teach.rs create mode 100644 tests/ui/error-codes/E0029-teach.stderr create mode 100644 tests/ui/error-codes/E0029.rs create mode 100644 tests/ui/error-codes/E0029.stderr create mode 100644 tests/ui/error-codes/E0030-teach.rs create mode 100644 tests/ui/error-codes/E0030-teach.stderr create mode 100644 tests/ui/error-codes/E0030.rs create mode 100644 tests/ui/error-codes/E0030.stderr create mode 100644 tests/ui/error-codes/E0033-teach.rs create mode 100644 tests/ui/error-codes/E0033-teach.stderr create mode 100644 tests/ui/error-codes/E0033.rs create mode 100644 tests/ui/error-codes/E0033.stderr create mode 100644 tests/ui/error-codes/E0034.rs create mode 100644 tests/ui/error-codes/E0034.stderr create mode 100644 tests/ui/error-codes/E0038.rs create mode 100644 tests/ui/error-codes/E0038.stderr create mode 100644 tests/ui/error-codes/E0040.fixed create mode 100644 tests/ui/error-codes/E0040.rs create mode 100644 tests/ui/error-codes/E0040.stderr create mode 100644 tests/ui/error-codes/E0044.rs create mode 100644 tests/ui/error-codes/E0044.stderr create mode 100644 tests/ui/error-codes/E0045.rs create mode 100644 tests/ui/error-codes/E0045.stderr create mode 100644 tests/ui/error-codes/E0049.rs create mode 100644 tests/ui/error-codes/E0049.stderr create mode 100644 tests/ui/error-codes/E0050.rs create mode 100644 tests/ui/error-codes/E0050.stderr create mode 100644 tests/ui/error-codes/E0054.rs create mode 100644 tests/ui/error-codes/E0054.stderr create mode 100644 tests/ui/error-codes/E0055.rs create mode 100644 tests/ui/error-codes/E0055.stderr create mode 100644 tests/ui/error-codes/E0057.rs create mode 100644 tests/ui/error-codes/E0057.stderr create mode 100644 tests/ui/error-codes/E0059.rs create mode 100644 tests/ui/error-codes/E0059.stderr create mode 100644 tests/ui/error-codes/E0060.rs create mode 100644 tests/ui/error-codes/E0060.stderr create mode 100644 tests/ui/error-codes/E0061.rs create mode 100644 tests/ui/error-codes/E0061.stderr create mode 100644 tests/ui/error-codes/E0062.rs create mode 100644 tests/ui/error-codes/E0062.stderr create mode 100644 tests/ui/error-codes/E0063.rs create mode 100644 tests/ui/error-codes/E0063.stderr create mode 100644 tests/ui/error-codes/E0067.rs create mode 100644 tests/ui/error-codes/E0067.stderr create mode 100644 tests/ui/error-codes/E0069.rs create mode 100644 tests/ui/error-codes/E0069.stderr create mode 100644 tests/ui/error-codes/E0070.rs create mode 100644 tests/ui/error-codes/E0070.stderr create mode 100644 tests/ui/error-codes/E0071.rs create mode 100644 tests/ui/error-codes/E0071.stderr create mode 100644 tests/ui/error-codes/E0075.rs create mode 100644 tests/ui/error-codes/E0075.stderr create mode 100644 tests/ui/error-codes/E0076.rs create mode 100644 tests/ui/error-codes/E0076.stderr create mode 100644 tests/ui/error-codes/E0077.rs create mode 100644 tests/ui/error-codes/E0077.stderr create mode 100644 tests/ui/error-codes/E0080.rs create mode 100644 tests/ui/error-codes/E0080.stderr create mode 100644 tests/ui/error-codes/E0081.rs create mode 100644 tests/ui/error-codes/E0081.stderr create mode 100644 tests/ui/error-codes/E0084.rs create mode 100644 tests/ui/error-codes/E0084.stderr create mode 100644 tests/ui/error-codes/E0091.rs create mode 100644 tests/ui/error-codes/E0091.stderr create mode 100644 tests/ui/error-codes/E0092.rs create mode 100644 tests/ui/error-codes/E0092.stderr create mode 100644 tests/ui/error-codes/E0093.rs create mode 100644 tests/ui/error-codes/E0093.stderr create mode 100644 tests/ui/error-codes/E0094.rs create mode 100644 tests/ui/error-codes/E0094.stderr create mode 100644 tests/ui/error-codes/E0106.rs create mode 100644 tests/ui/error-codes/E0106.stderr create mode 100644 tests/ui/error-codes/E0107.rs create mode 100644 tests/ui/error-codes/E0107.stderr create mode 100644 tests/ui/error-codes/E0109.rs create mode 100644 tests/ui/error-codes/E0109.stderr create mode 100644 tests/ui/error-codes/E0110.rs create mode 100644 tests/ui/error-codes/E0110.stderr create mode 100644 tests/ui/error-codes/E0116.rs create mode 100644 tests/ui/error-codes/E0116.stderr create mode 100644 tests/ui/error-codes/E0117.rs create mode 100644 tests/ui/error-codes/E0117.stderr create mode 100644 tests/ui/error-codes/E0118.rs create mode 100644 tests/ui/error-codes/E0118.stderr create mode 100644 tests/ui/error-codes/E0119.rs create mode 100644 tests/ui/error-codes/E0119.stderr create mode 100644 tests/ui/error-codes/E0120.rs create mode 100644 tests/ui/error-codes/E0120.stderr create mode 100644 tests/ui/error-codes/E0121.rs create mode 100644 tests/ui/error-codes/E0121.stderr create mode 100644 tests/ui/error-codes/E0124.rs create mode 100644 tests/ui/error-codes/E0124.stderr create mode 100644 tests/ui/error-codes/E0128.rs create mode 100644 tests/ui/error-codes/E0128.stderr create mode 100644 tests/ui/error-codes/E0130.rs create mode 100644 tests/ui/error-codes/E0130.stderr create mode 100644 tests/ui/error-codes/E0131.rs create mode 100644 tests/ui/error-codes/E0131.stderr create mode 100644 tests/ui/error-codes/E0132.rs create mode 100644 tests/ui/error-codes/E0132.stderr create mode 100644 tests/ui/error-codes/E0133.mir.stderr create mode 100644 tests/ui/error-codes/E0133.rs create mode 100644 tests/ui/error-codes/E0133.thir.stderr create mode 100644 tests/ui/error-codes/E0138.rs create mode 100644 tests/ui/error-codes/E0138.stderr create mode 100644 tests/ui/error-codes/E0152.rs create mode 100644 tests/ui/error-codes/E0152.stderr create mode 100644 tests/ui/error-codes/E0161.base.stderr create mode 100644 tests/ui/error-codes/E0161.rs create mode 100644 tests/ui/error-codes/E0164.rs create mode 100644 tests/ui/error-codes/E0164.stderr create mode 100644 tests/ui/error-codes/E0184.rs create mode 100644 tests/ui/error-codes/E0184.stderr create mode 100644 tests/ui/error-codes/E0185.rs create mode 100644 tests/ui/error-codes/E0185.stderr create mode 100644 tests/ui/error-codes/E0186.rs create mode 100644 tests/ui/error-codes/E0186.stderr create mode 100644 tests/ui/error-codes/E0191.rs create mode 100644 tests/ui/error-codes/E0191.stderr create mode 100644 tests/ui/error-codes/E0194.rs create mode 100644 tests/ui/error-codes/E0194.stderr create mode 100644 tests/ui/error-codes/E0195.rs create mode 100644 tests/ui/error-codes/E0195.stderr create mode 100644 tests/ui/error-codes/E0197.rs create mode 100644 tests/ui/error-codes/E0197.stderr create mode 100644 tests/ui/error-codes/E0198.rs create mode 100644 tests/ui/error-codes/E0198.stderr create mode 100644 tests/ui/error-codes/E0199.rs create mode 100644 tests/ui/error-codes/E0199.stderr create mode 100644 tests/ui/error-codes/E0200.rs create mode 100644 tests/ui/error-codes/E0200.stderr create mode 100644 tests/ui/error-codes/E0201.rs create mode 100644 tests/ui/error-codes/E0201.stderr create mode 100644 tests/ui/error-codes/E0206.rs create mode 100644 tests/ui/error-codes/E0206.stderr create mode 100644 tests/ui/error-codes/E0207.rs create mode 100644 tests/ui/error-codes/E0207.stderr create mode 100644 tests/ui/error-codes/E0208.rs create mode 100644 tests/ui/error-codes/E0208.stderr create mode 100644 tests/ui/error-codes/E0214.rs create mode 100644 tests/ui/error-codes/E0214.stderr create mode 100644 tests/ui/error-codes/E0220.rs create mode 100644 tests/ui/error-codes/E0220.stderr create mode 100644 tests/ui/error-codes/E0221.rs create mode 100644 tests/ui/error-codes/E0221.stderr create mode 100644 tests/ui/error-codes/E0223.rs create mode 100644 tests/ui/error-codes/E0223.stderr create mode 100644 tests/ui/error-codes/E0225.rs create mode 100644 tests/ui/error-codes/E0225.stderr create mode 100644 tests/ui/error-codes/E0227.rs create mode 100644 tests/ui/error-codes/E0227.stderr create mode 100644 tests/ui/error-codes/E0229.rs create mode 100644 tests/ui/error-codes/E0229.stderr create mode 100644 tests/ui/error-codes/E0252.rs create mode 100644 tests/ui/error-codes/E0252.stderr create mode 100644 tests/ui/error-codes/E0253.rs create mode 100644 tests/ui/error-codes/E0253.stderr create mode 100644 tests/ui/error-codes/E0254.rs create mode 100644 tests/ui/error-codes/E0254.stderr create mode 100644 tests/ui/error-codes/E0255.rs create mode 100644 tests/ui/error-codes/E0255.stderr create mode 100644 tests/ui/error-codes/E0259.rs create mode 100644 tests/ui/error-codes/E0259.stderr create mode 100644 tests/ui/error-codes/E0260.rs create mode 100644 tests/ui/error-codes/E0260.stderr create mode 100644 tests/ui/error-codes/E0261.rs create mode 100644 tests/ui/error-codes/E0261.stderr create mode 100644 tests/ui/error-codes/E0262.rs create mode 100644 tests/ui/error-codes/E0262.stderr create mode 100644 tests/ui/error-codes/E0263.rs create mode 100644 tests/ui/error-codes/E0263.stderr create mode 100644 tests/ui/error-codes/E0264.rs create mode 100644 tests/ui/error-codes/E0264.stderr create mode 100644 tests/ui/error-codes/E0267.rs create mode 100644 tests/ui/error-codes/E0267.stderr create mode 100644 tests/ui/error-codes/E0268.rs create mode 100644 tests/ui/error-codes/E0268.stderr create mode 100644 tests/ui/error-codes/E0271.rs create mode 100644 tests/ui/error-codes/E0271.stderr create mode 100644 tests/ui/error-codes/E0275.rs create mode 100644 tests/ui/error-codes/E0275.stderr create mode 100644 tests/ui/error-codes/E0276.rs create mode 100644 tests/ui/error-codes/E0276.stderr create mode 100644 tests/ui/error-codes/E0277-2.rs create mode 100644 tests/ui/error-codes/E0277-2.stderr create mode 100644 tests/ui/error-codes/E0277-3.rs create mode 100644 tests/ui/error-codes/E0277-3.stderr create mode 100644 tests/ui/error-codes/E0277.rs create mode 100644 tests/ui/error-codes/E0277.stderr create mode 100644 tests/ui/error-codes/E0282.rs create mode 100644 tests/ui/error-codes/E0282.stderr create mode 100644 tests/ui/error-codes/E0283.rs create mode 100644 tests/ui/error-codes/E0283.stderr create mode 100644 tests/ui/error-codes/E0297.rs create mode 100644 tests/ui/error-codes/E0297.stderr create mode 100644 tests/ui/error-codes/E0308-2.rs create mode 100644 tests/ui/error-codes/E0308-2.stderr create mode 100644 tests/ui/error-codes/E0308-4.rs create mode 100644 tests/ui/error-codes/E0308-4.stderr create mode 100644 tests/ui/error-codes/E0308.rs create mode 100644 tests/ui/error-codes/E0308.stderr create mode 100644 tests/ui/error-codes/E0311.fixed create mode 100644 tests/ui/error-codes/E0311.rs create mode 100644 tests/ui/error-codes/E0311.stderr create mode 100644 tests/ui/error-codes/E0328.rs create mode 100644 tests/ui/error-codes/E0328.stderr create mode 100644 tests/ui/error-codes/E0365.rs create mode 100644 tests/ui/error-codes/E0365.stderr create mode 100644 tests/ui/error-codes/E0370.rs create mode 100644 tests/ui/error-codes/E0370.stderr create mode 100644 tests/ui/error-codes/E0374.rs create mode 100644 tests/ui/error-codes/E0374.stderr create mode 100644 tests/ui/error-codes/E0375.rs create mode 100644 tests/ui/error-codes/E0375.stderr create mode 100644 tests/ui/error-codes/E0376.rs create mode 100644 tests/ui/error-codes/E0376.stderr create mode 100644 tests/ui/error-codes/E0377.rs create mode 100644 tests/ui/error-codes/E0377.stderr create mode 100644 tests/ui/error-codes/E0388.rs create mode 100644 tests/ui/error-codes/E0388.stderr create mode 100644 tests/ui/error-codes/E0389.rs create mode 100644 tests/ui/error-codes/E0389.stderr create mode 100644 tests/ui/error-codes/E0390.rs create mode 100644 tests/ui/error-codes/E0390.stderr create mode 100644 tests/ui/error-codes/E0392.rs create mode 100644 tests/ui/error-codes/E0392.stderr create mode 100644 tests/ui/error-codes/E0393.rs create mode 100644 tests/ui/error-codes/E0393.stderr create mode 100644 tests/ui/error-codes/E0396-fixed.rs create mode 100644 tests/ui/error-codes/E0396-fixed.stderr create mode 100644 tests/ui/error-codes/E0396.rs create mode 100644 tests/ui/error-codes/E0396.stderr create mode 100644 tests/ui/error-codes/E0401.rs create mode 100644 tests/ui/error-codes/E0401.stderr create mode 100644 tests/ui/error-codes/E0403.rs create mode 100644 tests/ui/error-codes/E0403.stderr create mode 100644 tests/ui/error-codes/E0404.rs create mode 100644 tests/ui/error-codes/E0404.stderr create mode 100644 tests/ui/error-codes/E0405.rs create mode 100644 tests/ui/error-codes/E0405.stderr create mode 100644 tests/ui/error-codes/E0407.rs create mode 100644 tests/ui/error-codes/E0407.stderr create mode 100644 tests/ui/error-codes/E0408.rs create mode 100644 tests/ui/error-codes/E0408.stderr create mode 100644 tests/ui/error-codes/E0411.rs create mode 100644 tests/ui/error-codes/E0411.stderr create mode 100644 tests/ui/error-codes/E0412.rs create mode 100644 tests/ui/error-codes/E0412.stderr create mode 100644 tests/ui/error-codes/E0415.rs create mode 100644 tests/ui/error-codes/E0415.stderr create mode 100644 tests/ui/error-codes/E0416.rs create mode 100644 tests/ui/error-codes/E0416.stderr create mode 100644 tests/ui/error-codes/E0423.rs create mode 100644 tests/ui/error-codes/E0423.stderr create mode 100644 tests/ui/error-codes/E0424.rs create mode 100644 tests/ui/error-codes/E0424.stderr create mode 100644 tests/ui/error-codes/E0425.rs create mode 100644 tests/ui/error-codes/E0425.stderr create mode 100644 tests/ui/error-codes/E0426.rs create mode 100644 tests/ui/error-codes/E0426.stderr create mode 100644 tests/ui/error-codes/E0428.rs create mode 100644 tests/ui/error-codes/E0428.stderr create mode 100644 tests/ui/error-codes/E0429.rs create mode 100644 tests/ui/error-codes/E0429.stderr create mode 100644 tests/ui/error-codes/E0430.rs create mode 100644 tests/ui/error-codes/E0430.stderr create mode 100644 tests/ui/error-codes/E0431.rs create mode 100644 tests/ui/error-codes/E0431.stderr create mode 100644 tests/ui/error-codes/E0432.rs create mode 100644 tests/ui/error-codes/E0432.stderr create mode 100644 tests/ui/error-codes/E0433.rs create mode 100644 tests/ui/error-codes/E0433.stderr create mode 100644 tests/ui/error-codes/E0434.rs create mode 100644 tests/ui/error-codes/E0434.stderr create mode 100644 tests/ui/error-codes/E0435.fixed create mode 100644 tests/ui/error-codes/E0435.rs create mode 100644 tests/ui/error-codes/E0435.stderr create mode 100644 tests/ui/error-codes/E0437.rs create mode 100644 tests/ui/error-codes/E0437.stderr create mode 100644 tests/ui/error-codes/E0438.rs create mode 100644 tests/ui/error-codes/E0438.stderr create mode 100644 tests/ui/error-codes/E0445.rs create mode 100644 tests/ui/error-codes/E0445.stderr create mode 100644 tests/ui/error-codes/E0446.rs create mode 100644 tests/ui/error-codes/E0446.stderr create mode 100644 tests/ui/error-codes/E0449.rs create mode 100644 tests/ui/error-codes/E0449.stderr create mode 100644 tests/ui/error-codes/E0451.rs create mode 100644 tests/ui/error-codes/E0451.stderr create mode 100644 tests/ui/error-codes/E0452.rs create mode 100644 tests/ui/error-codes/E0452.stderr create mode 100644 tests/ui/error-codes/E0453.rs create mode 100644 tests/ui/error-codes/E0453.stderr create mode 100644 tests/ui/error-codes/E0454.rs create mode 100644 tests/ui/error-codes/E0454.stderr create mode 100644 tests/ui/error-codes/E0458.rs create mode 100644 tests/ui/error-codes/E0458.stderr create mode 100644 tests/ui/error-codes/E0459.rs create mode 100644 tests/ui/error-codes/E0459.stderr create mode 100644 tests/ui/error-codes/E0462.rs create mode 100644 tests/ui/error-codes/E0462.stderr create mode 100644 tests/ui/error-codes/E0463.rs create mode 100644 tests/ui/error-codes/E0463.stderr create mode 100644 tests/ui/error-codes/E0464.rs create mode 100644 tests/ui/error-codes/E0464.stderr create mode 100644 tests/ui/error-codes/E0478.rs create mode 100644 tests/ui/error-codes/E0478.stderr create mode 100644 tests/ui/error-codes/E0492.rs create mode 100644 tests/ui/error-codes/E0492.stderr create mode 100644 tests/ui/error-codes/E0496.rs create mode 100644 tests/ui/error-codes/E0496.stderr create mode 100644 tests/ui/error-codes/E0499.rs create mode 100644 tests/ui/error-codes/E0499.stderr create mode 100644 tests/ui/error-codes/E0501.rs create mode 100644 tests/ui/error-codes/E0501.stderr create mode 100644 tests/ui/error-codes/E0502.rs create mode 100644 tests/ui/error-codes/E0502.stderr create mode 100644 tests/ui/error-codes/E0503.rs create mode 100644 tests/ui/error-codes/E0503.stderr create mode 100644 tests/ui/error-codes/E0504.rs create mode 100644 tests/ui/error-codes/E0504.stderr create mode 100644 tests/ui/error-codes/E0505.rs create mode 100644 tests/ui/error-codes/E0505.stderr create mode 100644 tests/ui/error-codes/E0506.rs create mode 100644 tests/ui/error-codes/E0506.stderr create mode 100644 tests/ui/error-codes/E0507.rs create mode 100644 tests/ui/error-codes/E0507.stderr create mode 100644 tests/ui/error-codes/E0508-fail.rs create mode 100644 tests/ui/error-codes/E0508-fail.stderr create mode 100644 tests/ui/error-codes/E0508.rs create mode 100644 tests/ui/error-codes/E0508.stderr create mode 100644 tests/ui/error-codes/E0509.rs create mode 100644 tests/ui/error-codes/E0509.stderr create mode 100644 tests/ui/error-codes/E0511.rs create mode 100644 tests/ui/error-codes/E0511.stderr create mode 100644 tests/ui/error-codes/E0512.rs create mode 100644 tests/ui/error-codes/E0512.stderr create mode 100644 tests/ui/error-codes/E0516.rs create mode 100644 tests/ui/error-codes/E0516.stderr create mode 100644 tests/ui/error-codes/E0517.rs create mode 100644 tests/ui/error-codes/E0517.stderr create mode 100644 tests/ui/error-codes/E0518.rs create mode 100644 tests/ui/error-codes/E0518.stderr create mode 100644 tests/ui/error-codes/E0519.rs create mode 100644 tests/ui/error-codes/E0519.stderr create mode 100644 tests/ui/error-codes/E0520.rs create mode 100644 tests/ui/error-codes/E0520.stderr create mode 100644 tests/ui/error-codes/E0522.rs create mode 100644 tests/ui/error-codes/E0522.stderr create mode 100644 tests/ui/error-codes/E0527.rs create mode 100644 tests/ui/error-codes/E0527.stderr create mode 100644 tests/ui/error-codes/E0528.rs create mode 100644 tests/ui/error-codes/E0528.stderr create mode 100644 tests/ui/error-codes/E0529.rs create mode 100644 tests/ui/error-codes/E0529.stderr create mode 100644 tests/ui/error-codes/E0530.rs create mode 100644 tests/ui/error-codes/E0530.stderr create mode 100644 tests/ui/error-codes/E0532.rs create mode 100644 tests/ui/error-codes/E0532.stderr create mode 100644 tests/ui/error-codes/E0534.rs create mode 100644 tests/ui/error-codes/E0534.stderr create mode 100644 tests/ui/error-codes/E0559.rs create mode 100644 tests/ui/error-codes/E0559.stderr create mode 100644 tests/ui/error-codes/E0560.rs create mode 100644 tests/ui/error-codes/E0560.stderr create mode 100644 tests/ui/error-codes/E0565-1.rs create mode 100644 tests/ui/error-codes/E0565-1.stderr create mode 100644 tests/ui/error-codes/E0565-2.rs create mode 100644 tests/ui/error-codes/E0565-2.stderr create mode 100644 tests/ui/error-codes/E0565.rs create mode 100644 tests/ui/error-codes/E0565.stderr create mode 100644 tests/ui/error-codes/E0572.rs create mode 100644 tests/ui/error-codes/E0572.stderr create mode 100644 tests/ui/error-codes/E0582.rs create mode 100644 tests/ui/error-codes/E0582.stderr create mode 100644 tests/ui/error-codes/E0583.rs create mode 100644 tests/ui/error-codes/E0583.stderr create mode 100644 tests/ui/error-codes/E0585.rs create mode 100644 tests/ui/error-codes/E0585.stderr create mode 100644 tests/ui/error-codes/E0586.rs create mode 100644 tests/ui/error-codes/E0586.stderr create mode 100644 tests/ui/error-codes/E0594.rs create mode 100644 tests/ui/error-codes/E0594.stderr create mode 100644 tests/ui/error-codes/E0596.rs create mode 100644 tests/ui/error-codes/E0596.stderr create mode 100644 tests/ui/error-codes/E0597.rs create mode 100644 tests/ui/error-codes/E0597.stderr create mode 100644 tests/ui/error-codes/E0599.rs create mode 100644 tests/ui/error-codes/E0599.stderr create mode 100644 tests/ui/error-codes/E0600.rs create mode 100644 tests/ui/error-codes/E0600.stderr create mode 100644 tests/ui/error-codes/E0601.rs create mode 100644 tests/ui/error-codes/E0601.stderr create mode 100644 tests/ui/error-codes/E0602.rs create mode 100644 tests/ui/error-codes/E0602.stderr create mode 100644 tests/ui/error-codes/E0603.rs create mode 100644 tests/ui/error-codes/E0603.stderr create mode 100644 tests/ui/error-codes/E0604.rs create mode 100644 tests/ui/error-codes/E0604.stderr create mode 100644 tests/ui/error-codes/E0605.rs create mode 100644 tests/ui/error-codes/E0605.stderr create mode 100644 tests/ui/error-codes/E0606.rs create mode 100644 tests/ui/error-codes/E0606.stderr create mode 100644 tests/ui/error-codes/E0607.rs create mode 100644 tests/ui/error-codes/E0607.stderr create mode 100644 tests/ui/error-codes/E0608.rs create mode 100644 tests/ui/error-codes/E0608.stderr create mode 100644 tests/ui/error-codes/E0609.rs create mode 100644 tests/ui/error-codes/E0609.stderr create mode 100644 tests/ui/error-codes/E0610.rs create mode 100644 tests/ui/error-codes/E0610.stderr create mode 100644 tests/ui/error-codes/E0614.rs create mode 100644 tests/ui/error-codes/E0614.stderr create mode 100644 tests/ui/error-codes/E0615.rs create mode 100644 tests/ui/error-codes/E0615.stderr create mode 100644 tests/ui/error-codes/E0616.rs create mode 100644 tests/ui/error-codes/E0616.stderr create mode 100644 tests/ui/error-codes/E0617.rs create mode 100644 tests/ui/error-codes/E0617.stderr create mode 100644 tests/ui/error-codes/E0618.rs create mode 100644 tests/ui/error-codes/E0618.stderr create mode 100644 tests/ui/error-codes/E0620.rs create mode 100644 tests/ui/error-codes/E0620.stderr create mode 100644 tests/ui/error-codes/E0621-does-not-trigger-for-closures.rs create mode 100644 tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr create mode 100644 tests/ui/error-codes/E0622.rs create mode 100644 tests/ui/error-codes/E0622.stderr create mode 100644 tests/ui/error-codes/E0624.rs create mode 100644 tests/ui/error-codes/E0624.stderr create mode 100644 tests/ui/error-codes/E0637.rs create mode 100644 tests/ui/error-codes/E0637.stderr create mode 100644 tests/ui/error-codes/E0642.fixed create mode 100644 tests/ui/error-codes/E0642.rs create mode 100644 tests/ui/error-codes/E0642.stderr create mode 100644 tests/ui/error-codes/E0646.rs create mode 100644 tests/ui/error-codes/E0646.stderr create mode 100644 tests/ui/error-codes/E0647.rs create mode 100644 tests/ui/error-codes/E0647.stderr create mode 100644 tests/ui/error-codes/E0648.rs create mode 100644 tests/ui/error-codes/E0648.stderr create mode 100644 tests/ui/error-codes/E0657.rs create mode 100644 tests/ui/error-codes/E0657.stderr create mode 100644 tests/ui/error-codes/E0658.rs create mode 100644 tests/ui/error-codes/E0658.stderr create mode 100644 tests/ui/error-codes/E0659.rs create mode 100644 tests/ui/error-codes/E0659.stderr create mode 100644 tests/ui/error-codes/E0705.rs create mode 100644 tests/ui/error-codes/E0705.stderr create mode 100644 tests/ui/error-codes/E0711.rs create mode 100644 tests/ui/error-codes/E0711.stderr create mode 100644 tests/ui/error-codes/E0718.rs create mode 100644 tests/ui/error-codes/E0718.stderr create mode 100644 tests/ui/error-codes/E0719.rs create mode 100644 tests/ui/error-codes/E0719.stderr create mode 100644 tests/ui/error-codes/E0730.rs create mode 100644 tests/ui/error-codes/E0730.stderr create mode 100644 tests/ui/error-codes/E0746.fixed create mode 100644 tests/ui/error-codes/E0746.rs create mode 100644 tests/ui/error-codes/E0746.stderr create mode 100644 tests/ui/error-codes/E0767.rs create mode 100644 tests/ui/error-codes/E0767.stderr create mode 100644 tests/ui/error-codes/E0771.rs create mode 100644 tests/ui/error-codes/E0771.stderr create mode 100644 tests/ui/error-codes/E0777.rs create mode 100644 tests/ui/error-codes/E0777.stderr create mode 100644 tests/ui/error-codes/E0778.rs create mode 100644 tests/ui/error-codes/E0778.stderr create mode 100644 tests/ui/error-codes/E0779.rs create mode 100644 tests/ui/error-codes/E0779.stderr create mode 100644 tests/ui/error-codes/E0790.rs create mode 100644 tests/ui/error-codes/E0790.stderr create mode 100644 tests/ui/error-codes/auxiliary/crateresolve1-1.rs create mode 100644 tests/ui/error-codes/auxiliary/crateresolve1-2.rs create mode 100644 tests/ui/error-codes/auxiliary/crateresolve1-3.rs create mode 100644 tests/ui/error-codes/auxiliary/found-staticlib.rs create mode 100644 tests/ui/error-codes/e0119/auxiliary/complex_impl_support.rs create mode 100644 tests/ui/error-codes/e0119/auxiliary/issue-23563-a.rs create mode 100644 tests/ui/error-codes/e0119/complex-impl.rs create mode 100644 tests/ui/error-codes/e0119/complex-impl.stderr create mode 100644 tests/ui/error-codes/e0119/conflict-with-std.rs create mode 100644 tests/ui/error-codes/e0119/conflict-with-std.stderr create mode 100644 tests/ui/error-codes/e0119/issue-23563.rs create mode 100644 tests/ui/error-codes/e0119/issue-23563.stderr create mode 100644 tests/ui/error-codes/e0119/issue-27403.rs create mode 100644 tests/ui/error-codes/e0119/issue-27403.stderr create mode 100644 tests/ui/error-codes/e0119/issue-28981.rs create mode 100644 tests/ui/error-codes/e0119/issue-28981.stderr create mode 100644 tests/ui/error-codes/e0119/so-37347311.rs create mode 100644 tests/ui/error-codes/e0119/so-37347311.stderr create mode 100644 tests/ui/error-codes/ex-E0611.rs create mode 100644 tests/ui/error-codes/ex-E0611.stderr create mode 100644 tests/ui/error-codes/ex-E0612.rs create mode 100644 tests/ui/error-codes/ex-E0612.stderr create mode 100644 tests/ui/error-festival.rs create mode 100644 tests/ui/error-festival.stderr create mode 100644 tests/ui/error-should-say-copy-not-pod.rs create mode 100644 tests/ui/error-should-say-copy-not-pod.stderr create mode 100644 tests/ui/errors/auxiliary/remapped_dep.rs create mode 100644 tests/ui/errors/issue-104621-extern-bad-file.rs create mode 100644 tests/ui/errors/issue-104621-extern-bad-file.stderr create mode 100644 tests/ui/errors/issue-104621-extern-not-file.rs create mode 100644 tests/ui/errors/issue-104621-extern-not-file.stderr create mode 100644 tests/ui/errors/issue-89280-emitter-overflow-splice-lines.rs create mode 100644 tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr create mode 100644 tests/ui/errors/issue-99572-impl-trait-on-pointer.rs create mode 100644 tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr create mode 100644 tests/ui/errors/remap-path-prefix-reverse.local-self.stderr create mode 100644 tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr create mode 100644 tests/ui/errors/remap-path-prefix-reverse.rs create mode 100644 tests/ui/errors/remap-path-prefix.rs create mode 100644 tests/ui/errors/remap-path-prefix.stderr create mode 100644 tests/ui/exclusive-drop-and-copy.rs create mode 100644 tests/ui/exclusive-drop-and-copy.stderr create mode 100644 tests/ui/exec-env.rs create mode 100644 tests/ui/explain.rs create mode 100644 tests/ui/explain.stdout create mode 100644 tests/ui/explicit-i-suffix.rs create mode 100644 tests/ui/explicit/explicit-call-to-dtor.fixed create mode 100644 tests/ui/explicit/explicit-call-to-dtor.rs create mode 100644 tests/ui/explicit/explicit-call-to-dtor.stderr create mode 100644 tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed create mode 100644 tests/ui/explicit/explicit-call-to-supertrait-dtor.rs create mode 100644 tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr create mode 100644 tests/ui/explicit/explicit-self-lifetime-mismatch.rs create mode 100644 tests/ui/explicit/explicit-self-lifetime-mismatch.stderr create mode 100644 tests/ui/explore-issue-38412.rs create mode 100644 tests/ui/explore-issue-38412.stderr create mode 100644 tests/ui/expr-block-fn.rs create mode 100644 tests/ui/expr-block-generic-unique1.rs create mode 100644 tests/ui/expr-block-generic-unique2.rs create mode 100644 tests/ui/expr-block-generic.rs create mode 100644 tests/ui/expr-block.rs create mode 100644 tests/ui/expr-copy.rs create mode 100644 tests/ui/expr-if-generic.rs create mode 100644 tests/ui/expr-if-panic-all.rs create mode 100644 tests/ui/expr-if-unique.rs create mode 100644 tests/ui/expr-scope.rs create mode 100644 tests/ui/expr/compound-assignment/eval-order.rs create mode 100644 tests/ui/expr/if-bot.rs create mode 100644 tests/ui/expr/if/attrs/bad-cfg.rs create mode 100644 tests/ui/expr/if/attrs/bad-cfg.stderr create mode 100644 tests/ui/expr/if/attrs/builtin-if-attr.rs create mode 100644 tests/ui/expr/if/attrs/cfg-false-if-attr.rs create mode 100644 tests/ui/expr/if/attrs/else-attrs.rs create mode 100644 tests/ui/expr/if/attrs/else-attrs.stderr create mode 100644 tests/ui/expr/if/attrs/gate-whole-expr.rs create mode 100644 tests/ui/expr/if/attrs/let-chains-attr.rs create mode 100644 tests/ui/expr/if/attrs/stmt-expr-gated.rs create mode 100644 tests/ui/expr/if/attrs/stmt-expr-gated.stderr create mode 100644 tests/ui/expr/if/bad-if-let-suggestion.rs create mode 100644 tests/ui/expr/if/bad-if-let-suggestion.stderr create mode 100644 tests/ui/expr/if/expr-if-panic-fn.rs create mode 100644 tests/ui/expr/if/expr-if-panic-pass.rs create mode 100644 tests/ui/expr/if/expr-if-panic.rs create mode 100644 tests/ui/expr/if/expr-if.rs create mode 100644 tests/ui/expr/if/if-branch-types.rs create mode 100644 tests/ui/expr/if/if-branch-types.stderr create mode 100644 tests/ui/expr/if/if-check-panic.rs create mode 100644 tests/ui/expr/if/if-check.rs create mode 100644 tests/ui/expr/if/if-cond-bot.rs create mode 100644 tests/ui/expr/if/if-else-type-mismatch.rs create mode 100644 tests/ui/expr/if/if-else-type-mismatch.stderr create mode 100644 tests/ui/expr/if/if-let-arm-types.rs create mode 100644 tests/ui/expr/if/if-let-arm-types.stderr create mode 100644 tests/ui/expr/if/if-let.rs create mode 100644 tests/ui/expr/if/if-let.stderr create mode 100644 tests/ui/expr/if/if-loop.rs create mode 100644 tests/ui/expr/if/if-no-match-bindings.rs create mode 100644 tests/ui/expr/if/if-no-match-bindings.stderr create mode 100644 tests/ui/expr/if/if-ret.rs create mode 100644 tests/ui/expr/if/if-ret.stderr create mode 100644 tests/ui/expr/if/if-typeck.rs create mode 100644 tests/ui/expr/if/if-typeck.stderr create mode 100644 tests/ui/expr/if/if-without-block.rs create mode 100644 tests/ui/expr/if/if-without-block.stderr create mode 100644 tests/ui/expr/if/if-without-else-as-fn-expr.rs create mode 100644 tests/ui/expr/if/if-without-else-as-fn-expr.stderr create mode 100644 tests/ui/expr/if/if-without-else-result.rs create mode 100644 tests/ui/expr/if/if-without-else-result.stderr create mode 100644 tests/ui/expr/if/issue-4201.rs create mode 100644 tests/ui/expr/if/issue-4201.stderr create mode 100644 tests/ui/expr/malformed_closure/missing_braces_around_block.fixed create mode 100644 tests/ui/expr/malformed_closure/missing_braces_around_block.rs create mode 100644 tests/ui/expr/malformed_closure/missing_braces_around_block.stderr create mode 100644 tests/ui/expr/malformed_closure/ruby_style_closure.rs create mode 100644 tests/ui/expr/malformed_closure/ruby_style_closure.stderr create mode 100644 tests/ui/ext-expand-inner-exprs.rs create mode 100644 tests/ui/ext-nonexistent.rs create mode 100644 tests/ui/ext-nonexistent.stderr create mode 100644 tests/ui/extenv/extenv-arg-2-not-string-literal.rs create mode 100644 tests/ui/extenv/extenv-arg-2-not-string-literal.stderr create mode 100644 tests/ui/extenv/extenv-no-args.rs create mode 100644 tests/ui/extenv/extenv-no-args.stderr create mode 100644 tests/ui/extenv/extenv-not-defined-custom.rs create mode 100644 tests/ui/extenv/extenv-not-defined-custom.stderr create mode 100644 tests/ui/extenv/extenv-not-defined-default.rs create mode 100644 tests/ui/extenv/extenv-not-defined-default.stderr create mode 100644 tests/ui/extenv/extenv-not-string-literal.rs create mode 100644 tests/ui/extenv/extenv-not-string-literal.stderr create mode 100644 tests/ui/extenv/extenv-too-many-args.rs create mode 100644 tests/ui/extenv/extenv-too-many-args.stderr create mode 100644 tests/ui/extenv/issue-55897.rs create mode 100644 tests/ui/extenv/issue-55897.stderr create mode 100644 tests/ui/extern-flag/auxiliary/somedep.rs create mode 100644 tests/ui/extern-flag/empty-extern-arg.rs create mode 100644 tests/ui/extern-flag/empty-extern-arg.stderr create mode 100644 tests/ui/extern-flag/multiple-opts.rs create mode 100644 tests/ui/extern-flag/multiple-opts.stderr create mode 100644 tests/ui/extern-flag/no-nounused.rs create mode 100644 tests/ui/extern-flag/no-nounused.stderr create mode 100644 tests/ui/extern-flag/noprelude-and-prelude.rs create mode 100644 tests/ui/extern-flag/noprelude-resolves.rs create mode 100644 tests/ui/extern-flag/noprelude.rs create mode 100644 tests/ui/extern-flag/noprelude.stderr create mode 100644 tests/ui/extern-flag/nounused.rs create mode 100644 tests/ui/extern-flag/public-and-private.rs create mode 100644 tests/ui/extern-flag/public-and-private.stderr create mode 100644 tests/ui/extern/auxiliary/extern-take-value.rs create mode 100644 tests/ui/extern/auxiliary/extern-types-inherent-impl.rs create mode 100644 tests/ui/extern/auxiliary/extern_calling_convention.rs create mode 100644 tests/ui/extern/auxiliary/extern_mod_ordering_lib.rs create mode 100644 tests/ui/extern/auxiliary/fat_drop.rs create mode 100644 tests/ui/extern/auxiliary/invalid-utf8.txt create mode 100644 tests/ui/extern/auxiliary/issue-80074-macro.rs create mode 100644 tests/ui/extern/auxiliary/m1.rs create mode 100644 tests/ui/extern/auxiliary/m2.rs create mode 100644 tests/ui/extern/auxiliary/no-mangle-associated-fn.rs create mode 100644 tests/ui/extern/auxiliary/reexport-should-still-link.rs create mode 100644 tests/ui/extern/extern-1.rs create mode 100644 tests/ui/extern/extern-calling-convention-test.rs create mode 100644 tests/ui/extern/extern-compare-with-return-type.rs create mode 100644 tests/ui/extern/extern-const.fixed create mode 100644 tests/ui/extern/extern-const.rs create mode 100644 tests/ui/extern/extern-const.stderr create mode 100644 tests/ui/extern/extern-crate-multiple-missing.rs create mode 100644 tests/ui/extern/extern-crate-multiple-missing.stderr create mode 100644 tests/ui/extern/extern-crate-rename.rs create mode 100644 tests/ui/extern/extern-crate-rename.stderr create mode 100644 tests/ui/extern/extern-crate-visibility.rs create mode 100644 tests/ui/extern/extern-crate-visibility.stderr create mode 100644 tests/ui/extern/extern-ffi-fn-with-body.rs create mode 100644 tests/ui/extern/extern-ffi-fn-with-body.stderr create mode 100644 tests/ui/extern/extern-foreign-crate.rs create mode 100644 tests/ui/extern/extern-macro.rs create mode 100644 tests/ui/extern/extern-macro.stderr create mode 100644 tests/ui/extern/extern-main-fn.rs create mode 100644 tests/ui/extern/extern-main-fn.stderr create mode 100644 tests/ui/extern/extern-main-issue-86110.rs create mode 100644 tests/ui/extern/extern-main-issue-86110.stderr create mode 100644 tests/ui/extern/extern-methods.rs create mode 100644 tests/ui/extern/extern-mod-abi.rs create mode 100644 tests/ui/extern/extern-mod-ordering-exe.rs create mode 100644 tests/ui/extern/extern-no-mangle.rs create mode 100644 tests/ui/extern/extern-no-mangle.stderr create mode 100644 tests/ui/extern/extern-prelude-core.rs create mode 100644 tests/ui/extern/extern-prelude-no-speculative.rs create mode 100644 tests/ui/extern/extern-prelude-std.rs create mode 100644 tests/ui/extern/extern-pub.rs create mode 100644 tests/ui/extern/extern-rust.rs create mode 100644 tests/ui/extern/extern-static-size-overflow.rs create mode 100644 tests/ui/extern/extern-static-size-overflow.stderr create mode 100644 tests/ui/extern/extern-take-value.rs create mode 100644 tests/ui/extern/extern-thiscall.rs create mode 100644 tests/ui/extern/extern-type-diag-not-similar.rs create mode 100644 tests/ui/extern/extern-type-diag-not-similar.stderr create mode 100644 tests/ui/extern/extern-types-distinct-types.rs create mode 100644 tests/ui/extern/extern-types-distinct-types.stderr create mode 100644 tests/ui/extern/extern-types-inherent-impl.rs create mode 100644 tests/ui/extern/extern-types-manual-sync-send.rs create mode 100644 tests/ui/extern/extern-types-not-sync-send.rs create mode 100644 tests/ui/extern/extern-types-not-sync-send.stderr create mode 100644 tests/ui/extern/extern-types-pointer-cast.rs create mode 100644 tests/ui/extern/extern-types-size_of_val.rs create mode 100644 tests/ui/extern/extern-types-thin-pointer.rs create mode 100644 tests/ui/extern/extern-types-trait-impl.rs create mode 100644 tests/ui/extern/extern-types-unsized.rs create mode 100644 tests/ui/extern/extern-types-unsized.stderr create mode 100644 tests/ui/extern/extern-vectorcall.rs create mode 100644 tests/ui/extern/extern-with-type-bounds.rs create mode 100644 tests/ui/extern/extern-with-type-bounds.stderr create mode 100644 tests/ui/extern/extern-wrong-value-type.rs create mode 100644 tests/ui/extern/extern-wrong-value-type.stderr create mode 100644 tests/ui/extern/extern_fat_drop.rs create mode 100644 tests/ui/extern/issue-10025.rs create mode 100644 tests/ui/extern/issue-10763.rs create mode 100644 tests/ui/extern/issue-10764-rpass.rs create mode 100644 tests/ui/extern/issue-13655.rs create mode 100644 tests/ui/extern/issue-28324.mir.stderr create mode 100644 tests/ui/extern/issue-28324.rs create mode 100644 tests/ui/extern/issue-28324.thir.stderr create mode 100644 tests/ui/extern/issue-36122-accessing-externed-dst.rs create mode 100644 tests/ui/extern/issue-36122-accessing-externed-dst.stderr create mode 100644 tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs create mode 100644 tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs create mode 100644 tests/ui/extern/issue-80074.rs create mode 100644 tests/ui/extern/issue-95829.rs create mode 100644 tests/ui/extern/issue-95829.stderr create mode 100644 tests/ui/extern/no-mangle-associated-fn.rs create mode 100644 tests/ui/extern/not-in-block.rs create mode 100644 tests/ui/extern/not-in-block.stderr create mode 100644 tests/ui/extoption_env-no-args.rs create mode 100644 tests/ui/extoption_env-no-args.stderr create mode 100644 tests/ui/extoption_env-not-defined.rs create mode 100644 tests/ui/extoption_env-not-string-literal.rs create mode 100644 tests/ui/extoption_env-not-string-literal.stderr create mode 100644 tests/ui/extoption_env-too-many-args.rs create mode 100644 tests/ui/extoption_env-too-many-args.stderr create mode 100644 tests/ui/fact.rs create mode 100644 tests/ui/fail-simple.rs create mode 100644 tests/ui/fail-simple.stderr create mode 100644 tests/ui/feature-gates/allow-features-empty.rs create mode 100644 tests/ui/feature-gates/allow-features-empty.stderr create mode 100644 tests/ui/feature-gates/allow-features.rs create mode 100644 tests/ui/feature-gates/allow-features.stderr create mode 100644 tests/ui/feature-gates/auxiliary/cfg-target-thread-local.rs create mode 100644 tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis create mode 100644 tests/ui/feature-gates/auxiliary/pub_dep.rs create mode 100644 tests/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs create mode 100644 tests/ui/feature-gates/bench.rs create mode 100644 tests/ui/feature-gates/bench.stderr create mode 100644 tests/ui/feature-gates/duplicate-features.rs create mode 100644 tests/ui/feature-gates/duplicate-features.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi_ptx.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi_ptx.stderr create mode 100644 tests/ui/feature-gates/feature-gate-abi_unadjusted.rs create mode 100644 tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr create mode 100644 tests/ui/feature-gates/feature-gate-adt_const_params.rs create mode 100644 tests/ui/feature-gates/feature-gate-adt_const_params.stderr create mode 100644 tests/ui/feature-gates/feature-gate-alloc-error-handler.rs create mode 100644 tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr create mode 100644 tests/ui/feature-gates/feature-gate-allocator_internals.rs create mode 100644 tests/ui/feature-gates/feature-gate-allocator_internals.stderr create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unstable.rs create mode 100644 tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr create mode 100644 tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs create mode 100644 tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr create mode 100644 tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs create mode 100644 tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr create mode 100644 tests/ui/feature-gates/feature-gate-asm_const.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_const.stderr create mode 100644 tests/ui/feature-gates/feature-gate-asm_experimental_arch.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr create mode 100644 tests/ui/feature-gates/feature-gate-asm_unwind.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_unwind.stderr create mode 100644 tests/ui/feature-gates/feature-gate-assoc-type-defaults.rs create mode 100644 tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr create mode 100644 tests/ui/feature-gates/feature-gate-associated_const_equality.rs create mode 100644 tests/ui/feature-gates/feature-gate-associated_const_equality.stderr create mode 100644 tests/ui/feature-gates/feature-gate-associated_type_bounds.rs create mode 100644 tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr create mode 100644 tests/ui/feature-gates/feature-gate-auto-traits.rs create mode 100644 tests/ui/feature-gates/feature-gate-auto-traits.stderr create mode 100644 tests/ui/feature-gates/feature-gate-box-expr.rs create mode 100644 tests/ui/feature-gates/feature-gate-box-expr.stderr create mode 100644 tests/ui/feature-gates/feature-gate-box_patterns.rs create mode 100644 tests/ui/feature-gates/feature-gate-box_patterns.stderr create mode 100644 tests/ui/feature-gates/feature-gate-box_syntax.rs create mode 100644 tests/ui/feature-gates/feature-gate-box_syntax.stderr create mode 100644 tests/ui/feature-gates/feature-gate-c_variadic.rs create mode 100644 tests/ui/feature-gates/feature-gate-c_variadic.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-abi.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-abi.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-compact.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-version.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-version.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg_sanitize.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr create mode 100644 tests/ui/feature-gates/feature-gate-check-cfg.rs create mode 100644 tests/ui/feature-gates/feature-gate-check-cfg.stderr create mode 100644 tests/ui/feature-gates/feature-gate-closure_lifetime_binder.rs create mode 100644 tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr create mode 100644 tests/ui/feature-gates/feature-gate-closure_track_caller.rs create mode 100644 tests/ui/feature-gates/feature-gate-closure_track_caller.stderr create mode 100644 tests/ui/feature-gates/feature-gate-collapse_debuginfo.rs create mode 100644 tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr create mode 100644 tests/ui/feature-gates/feature-gate-compiler-builtins.rs create mode 100644 tests/ui/feature-gates/feature-gate-compiler-builtins.stderr create mode 100644 tests/ui/feature-gates/feature-gate-concat_bytes.rs create mode 100644 tests/ui/feature-gates/feature-gate-concat_bytes.stderr create mode 100644 tests/ui/feature-gates/feature-gate-concat_idents.rs create mode 100644 tests/ui/feature-gates/feature-gate-concat_idents.stderr create mode 100644 tests/ui/feature-gates/feature-gate-concat_idents2.rs create mode 100644 tests/ui/feature-gates/feature-gate-concat_idents2.stderr create mode 100644 tests/ui/feature-gates/feature-gate-concat_idents3.rs create mode 100644 tests/ui/feature-gates/feature-gate-concat_idents3.stderr create mode 100644 tests/ui/feature-gates/feature-gate-const-indexing.rs create mode 100644 tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs create mode 100644 tests/ui/feature-gates/feature-gate-custom_attribute.rs create mode 100644 tests/ui/feature-gates/feature-gate-custom_attribute.stderr create mode 100644 tests/ui/feature-gates/feature-gate-custom_attribute2.rs create mode 100644 tests/ui/feature-gates/feature-gate-custom_attribute2.stderr create mode 100644 tests/ui/feature-gates/feature-gate-custom_mir.rs create mode 100644 tests/ui/feature-gates/feature-gate-custom_mir.stderr create mode 100644 tests/ui/feature-gates/feature-gate-custom_test_frameworks.rs create mode 100644 tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr create mode 100644 tests/ui/feature-gates/feature-gate-debugger-visualizer.rs create mode 100644 tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr create mode 100644 tests/ui/feature-gates/feature-gate-decl_macro.rs create mode 100644 tests/ui/feature-gates/feature-gate-decl_macro.stderr create mode 100644 tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs create mode 100644 tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr create mode 100644 tests/ui/feature-gates/feature-gate-deprecated_safe.rs create mode 100644 tests/ui/feature-gates/feature-gate-deprecated_safe.stderr create mode 100644 tests/ui/feature-gates/feature-gate-doc_cfg.rs create mode 100644 tests/ui/feature-gates/feature-gate-doc_cfg.stderr create mode 100644 tests/ui/feature-gates/feature-gate-doc_masked.rs create mode 100644 tests/ui/feature-gates/feature-gate-doc_masked.stderr create mode 100644 tests/ui/feature-gates/feature-gate-doc_notable_trait.rs create mode 100644 tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr create mode 100644 tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs create mode 100644 tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr create mode 100644 tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs create mode 100644 tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr create mode 100644 tests/ui/feature-gates/feature-gate-extern_absolute_paths.rs create mode 100644 tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr create mode 100644 tests/ui/feature-gates/feature-gate-extern_prelude.rs create mode 100644 tests/ui/feature-gates/feature-gate-extern_prelude.stderr create mode 100644 tests/ui/feature-gates/feature-gate-extern_types.rs create mode 100644 tests/ui/feature-gates/feature-gate-extern_types.stderr create mode 100644 tests/ui/feature-gates/feature-gate-feature-gate.rs create mode 100644 tests/ui/feature-gates/feature-gate-feature-gate.stderr create mode 100644 tests/ui/feature-gates/feature-gate-ffi_const.rs create mode 100644 tests/ui/feature-gates/feature-gate-ffi_const.stderr create mode 100644 tests/ui/feature-gates/feature-gate-ffi_pure.rs create mode 100644 tests/ui/feature-gates/feature-gate-ffi_pure.stderr create mode 100644 tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs create mode 100644 tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr create mode 100644 tests/ui/feature-gates/feature-gate-fn_align.rs create mode 100644 tests/ui/feature-gates/feature-gate-fn_align.stderr create mode 100644 tests/ui/feature-gates/feature-gate-format_args_nl.rs create mode 100644 tests/ui/feature-gates/feature-gate-format_args_nl.stderr create mode 100644 tests/ui/feature-gates/feature-gate-fundamental.rs create mode 100644 tests/ui/feature-gates/feature-gate-fundamental.stderr create mode 100644 tests/ui/feature-gates/feature-gate-generators.rs create mode 100644 tests/ui/feature-gates/feature-gate-generators.stderr create mode 100644 tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr create mode 100644 tests/ui/feature-gates/feature-gate-generic_arg_infer.rs create mode 100644 tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs create mode 100644 tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr create mode 100644 tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs create mode 100644 tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr create mode 100644 tests/ui/feature-gates/feature-gate-imported_main.rs create mode 100644 tests/ui/feature-gates/feature-gate-imported_main.stderr create mode 100644 tests/ui/feature-gates/feature-gate-inherent_associated_types.rs create mode 100644 tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr create mode 100644 tests/ui/feature-gates/feature-gate-inline_const.rs create mode 100644 tests/ui/feature-gates/feature-gate-inline_const.stderr create mode 100644 tests/ui/feature-gates/feature-gate-inline_const_pat.rs create mode 100644 tests/ui/feature-gates/feature-gate-inline_const_pat.stderr create mode 100644 tests/ui/feature-gates/feature-gate-intrinsics.rs create mode 100644 tests/ui/feature-gates/feature-gate-intrinsics.stderr create mode 100644 tests/ui/feature-gates/feature-gate-is_sorted.rs create mode 100644 tests/ui/feature-gates/feature-gate-is_sorted.stderr create mode 100644 tests/ui/feature-gates/feature-gate-lang-items.rs create mode 100644 tests/ui/feature-gates/feature-gate-lang-items.stderr create mode 100644 tests/ui/feature-gates/feature-gate-large-assignments.rs create mode 100644 tests/ui/feature-gates/feature-gate-large-assignments.stderr create mode 100644 tests/ui/feature-gates/feature-gate-link_cfg.rs create mode 100644 tests/ui/feature-gates/feature-gate-link_cfg.stderr create mode 100644 tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs create mode 100644 tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr create mode 100644 tests/ui/feature-gates/feature-gate-linkage.rs create mode 100644 tests/ui/feature-gates/feature-gate-linkage.stderr create mode 100644 tests/ui/feature-gates/feature-gate-lint-reasons.rs create mode 100644 tests/ui/feature-gates/feature-gate-lint-reasons.stderr create mode 100644 tests/ui/feature-gates/feature-gate-log_syntax.rs create mode 100644 tests/ui/feature-gates/feature-gate-log_syntax.stderr create mode 100644 tests/ui/feature-gates/feature-gate-log_syntax.stdout create mode 100644 tests/ui/feature-gates/feature-gate-log_syntax2.rs create mode 100644 tests/ui/feature-gates/feature-gate-log_syntax2.stderr create mode 100644 tests/ui/feature-gates/feature-gate-log_syntax2.stdout create mode 100644 tests/ui/feature-gates/feature-gate-marker_trait_attr.rs create mode 100644 tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr create mode 100644 tests/ui/feature-gates/feature-gate-may-dangle.rs create mode 100644 tests/ui/feature-gates/feature-gate-may-dangle.stderr create mode 100644 tests/ui/feature-gates/feature-gate-min_const_fn.rs create mode 100644 tests/ui/feature-gates/feature-gate-min_const_fn.stderr create mode 100644 tests/ui/feature-gates/feature-gate-more-qualified-paths.rs create mode 100644 tests/ui/feature-gates/feature-gate-more-qualified-paths.stderr create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions.stderr create mode 100644 tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs create mode 100644 tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr create mode 100644 tests/ui/feature-gates/feature-gate-needs-allocator.rs create mode 100644 tests/ui/feature-gates/feature-gate-needs-allocator.stderr create mode 100644 tests/ui/feature-gates/feature-gate-negate-unsigned.rs create mode 100644 tests/ui/feature-gates/feature-gate-negate-unsigned.stderr create mode 100644 tests/ui/feature-gates/feature-gate-never_type.rs create mode 100644 tests/ui/feature-gates/feature-gate-never_type.stderr create mode 100644 tests/ui/feature-gates/feature-gate-no_core.rs create mode 100644 tests/ui/feature-gates/feature-gate-no_core.stderr create mode 100644 tests/ui/feature-gates/feature-gate-no_coverage.rs create mode 100644 tests/ui/feature-gates/feature-gate-no_coverage.stderr create mode 100644 tests/ui/feature-gates/feature-gate-no_sanitize.rs create mode 100644 tests/ui/feature-gates/feature-gate-no_sanitize.stderr create mode 100644 tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs create mode 100644 tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr create mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs create mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr create mode 100644 tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs create mode 100644 tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr create mode 100644 tests/ui/feature-gates/feature-gate-optimize_attribute.rs create mode 100644 tests/ui/feature-gates/feature-gate-optimize_attribute.stderr create mode 100644 tests/ui/feature-gates/feature-gate-overlapping_marker_traits.rs create mode 100644 tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr create mode 100644 tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs create mode 100644 tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr create mode 100644 tests/ui/feature-gates/feature-gate-prelude_import.rs create mode 100644 tests/ui/feature-gates/feature-gate-prelude_import.stderr create mode 100644 tests/ui/feature-gates/feature-gate-profiler-runtime.rs create mode 100644 tests/ui/feature-gates/feature-gate-profiler-runtime.stderr create mode 100644 tests/ui/feature-gates/feature-gate-public_private_dependencies.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-2.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib.stderr create mode 100644 tests/ui/feature-gates/feature-gate-register_tool.rs create mode 100644 tests/ui/feature-gates/feature-gate-register_tool.stderr create mode 100644 tests/ui/feature-gates/feature-gate-repr-simd.rs create mode 100644 tests/ui/feature-gates/feature-gate-repr-simd.stderr create mode 100644 tests/ui/feature-gates/feature-gate-repr128.rs create mode 100644 tests/ui/feature-gates/feature-gate-repr128.stderr create mode 100644 tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs create mode 100644 tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr create mode 100644 tests/ui/feature-gates/feature-gate-rust_cold_cc.rs create mode 100644 tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr create mode 100644 tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs create mode 100644 tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr create mode 100644 tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs create mode 100644 tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr create mode 100644 tests/ui/feature-gates/feature-gate-rustc-attrs.rs create mode 100644 tests/ui/feature-gates/feature-gate-rustc-attrs.stderr create mode 100644 tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs create mode 100644 tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr create mode 100644 tests/ui/feature-gates/feature-gate-rustdoc_internals.rs create mode 100644 tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr create mode 100644 tests/ui/feature-gates/feature-gate-simd-ffi.rs create mode 100644 tests/ui/feature-gates/feature-gate-simd-ffi.stderr create mode 100644 tests/ui/feature-gates/feature-gate-simd.rs create mode 100644 tests/ui/feature-gates/feature-gate-simd.stderr create mode 100644 tests/ui/feature-gates/feature-gate-staged_api.rs create mode 100644 tests/ui/feature-gates/feature-gate-staged_api.stderr create mode 100644 tests/ui/feature-gates/feature-gate-start.rs create mode 100644 tests/ui/feature-gates/feature-gate-start.stderr create mode 100644 tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs create mode 100644 tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr create mode 100644 tests/ui/feature-gates/feature-gate-strict_provenance.rs create mode 100644 tests/ui/feature-gates/feature-gate-strict_provenance.stderr create mode 100644 tests/ui/feature-gates/feature-gate-test_unstable_lint.rs create mode 100644 tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr create mode 100644 tests/ui/feature-gates/feature-gate-thread_local.rs create mode 100644 tests/ui/feature-gates/feature-gate-thread_local.stderr create mode 100644 tests/ui/feature-gates/feature-gate-trace_macros.rs create mode 100644 tests/ui/feature-gates/feature-gate-trace_macros.stderr create mode 100644 tests/ui/feature-gates/feature-gate-trait-alias.rs create mode 100644 tests/ui/feature-gates/feature-gate-trait-alias.stderr create mode 100644 tests/ui/feature-gates/feature-gate-trait_upcasting.rs create mode 100644 tests/ui/feature-gates/feature-gate-trait_upcasting.stderr create mode 100644 tests/ui/feature-gates/feature-gate-transparent_unions.rs create mode 100644 tests/ui/feature-gates/feature-gate-transparent_unions.stderr create mode 100644 tests/ui/feature-gates/feature-gate-trivial_bounds-lint.rs create mode 100644 tests/ui/feature-gates/feature-gate-trivial_bounds.rs create mode 100644 tests/ui/feature-gates/feature-gate-trivial_bounds.stderr create mode 100644 tests/ui/feature-gates/feature-gate-try_blocks.rs create mode 100644 tests/ui/feature-gates/feature-gate-try_blocks.stderr create mode 100644 tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs create mode 100644 tests/ui/feature-gates/feature-gate-type_ascription.rs create mode 100644 tests/ui/feature-gates/feature-gate-type_ascription.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures.rs create mode 100644 tests/ui/feature-gates/feature-gate-unboxed-closures.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unix_sigpipe.rs create mode 100644 tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs create mode 100644 tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unsized_fn_params.rs create mode 100644 tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unsized_locals.rs create mode 100644 tests/ui/feature-gates/feature-gate-unsized_locals.stderr create mode 100644 tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs create mode 100644 tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr create mode 100644 tests/ui/feature-gates/feature-gate-used_with_arg.rs create mode 100644 tests/ui/feature-gates/feature-gate-used_with_arg.stderr create mode 100644 tests/ui/feature-gates/feature-gate-vectorcall.rs create mode 100644 tests/ui/feature-gates/feature-gate-vectorcall.stderr create mode 100644 tests/ui/feature-gates/feature-gate-wasm_abi.rs create mode 100644 tests/ui/feature-gates/feature-gate-wasm_abi.stderr create mode 100644 tests/ui/feature-gates/feature-gate-with_negative_coherence.rs create mode 100644 tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr create mode 100644 tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs create mode 100644 tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr create mode 100644 tests/ui/feature-gates/feature-gate-yeet_expr.rs create mode 100644 tests/ui/feature-gates/feature-gate-yeet_expr.stderr create mode 100644 tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs create mode 100644 tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr create mode 100644 tests/ui/feature-gates/gated-bad-feature.rs create mode 100644 tests/ui/feature-gates/gated-bad-feature.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-bench.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-bench.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-deprecated.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-derive-2.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-derive.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-derive.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-macro_escape.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-macro_escape.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-stable.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-stable.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-test.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-test.stderr create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-unstable.rs create mode 100644 tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr create mode 100644 tests/ui/feature-gates/issue-49983-see-issue-0.rs create mode 100644 tests/ui/feature-gates/issue-49983-see-issue-0.stderr create mode 100644 tests/ui/feature-gates/rustc-private.rs create mode 100644 tests/ui/feature-gates/rustc-private.stderr create mode 100644 tests/ui/feature-gates/soft-syntax-gates-with-errors.rs create mode 100644 tests/ui/feature-gates/soft-syntax-gates-with-errors.stderr create mode 100644 tests/ui/feature-gates/soft-syntax-gates-without-errors.rs create mode 100644 tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr create mode 100644 tests/ui/feature-gates/stability-attribute-consistency.rs create mode 100644 tests/ui/feature-gates/stability-attribute-consistency.stderr create mode 100644 tests/ui/feature-gates/stable-features.rs create mode 100644 tests/ui/feature-gates/stable-features.stderr create mode 100644 tests/ui/feature-gates/trace_macros-gate.rs create mode 100644 tests/ui/feature-gates/trace_macros-gate.stderr create mode 100644 tests/ui/feature-gates/unknown-feature.rs create mode 100644 tests/ui/feature-gates/unknown-feature.stderr create mode 100644 tests/ui/feature-gates/unstable-attribute-allow-issue-0.rs create mode 100644 tests/ui/feature-gates/unstable-attribute-allow-issue-0.stderr create mode 100644 tests/ui/ffi_const.rs create mode 100644 tests/ui/ffi_const.stderr create mode 100644 tests/ui/ffi_const2.rs create mode 100644 tests/ui/ffi_const2.stderr create mode 100644 tests/ui/ffi_pure.rs create mode 100644 tests/ui/ffi_pure.stderr create mode 100644 tests/ui/ffi_returns_twice.rs create mode 100644 tests/ui/ffi_returns_twice.stderr create mode 100644 tests/ui/filter-block-view-items.rs create mode 100644 tests/ui/fmt/auxiliary/format-string-proc-macro.rs create mode 100644 tests/ui/fmt/format-args-capture-issue-102057.rs create mode 100644 tests/ui/fmt/format-args-capture-issue-102057.stderr create mode 100644 tests/ui/fmt/format-args-capture-issue-93378.rs create mode 100644 tests/ui/fmt/format-args-capture-issue-93378.stderr create mode 100644 tests/ui/fmt/format-args-capture-issue-94010.rs create mode 100644 tests/ui/fmt/format-args-capture-issue-94010.stderr create mode 100644 tests/ui/fmt/format-args-capture-macro-hygiene.rs create mode 100644 tests/ui/fmt/format-args-capture-macro-hygiene.stderr create mode 100644 tests/ui/fmt/format-args-capture-missing-variables.rs create mode 100644 tests/ui/fmt/format-args-capture-missing-variables.stderr create mode 100644 tests/ui/fmt/format-args-capture.rs create mode 100644 tests/ui/fmt/format-expanded-string.rs create mode 100644 tests/ui/fmt/format-expanded-string.stderr create mode 100644 tests/ui/fmt/format-raw-string-error.rs create mode 100644 tests/ui/fmt/format-raw-string-error.stderr create mode 100644 tests/ui/fmt/format-string-error-2.rs create mode 100644 tests/ui/fmt/format-string-error-2.stderr create mode 100644 tests/ui/fmt/format-string-error.rs create mode 100644 tests/ui/fmt/format-string-error.stderr create mode 100644 tests/ui/fmt/format-with-yield-point.rs create mode 100644 tests/ui/fmt/ifmt-bad-arg.rs create mode 100644 tests/ui/fmt/ifmt-bad-arg.stderr create mode 100644 tests/ui/fmt/ifmt-bad-format-args.rs create mode 100644 tests/ui/fmt/ifmt-bad-format-args.stderr create mode 100644 tests/ui/fmt/ifmt-unimpl.rs create mode 100644 tests/ui/fmt/ifmt-unimpl.stderr create mode 100644 tests/ui/fmt/ifmt-unknown-trait.rs create mode 100644 tests/ui/fmt/ifmt-unknown-trait.stderr create mode 100644 tests/ui/fmt/incorrect-separator.rs create mode 100644 tests/ui/fmt/incorrect-separator.stderr create mode 100644 tests/ui/fmt/indoc-issue-106408.rs create mode 100644 tests/ui/fmt/issue-103826.rs create mode 100644 tests/ui/fmt/issue-103826.stderr create mode 100644 tests/ui/fmt/issue-104142.rs create mode 100644 tests/ui/fmt/issue-104142.stderr create mode 100644 tests/ui/fmt/issue-86085.rs create mode 100644 tests/ui/fmt/issue-86085.stderr create mode 100644 tests/ui/fmt/issue-89173.rs create mode 100644 tests/ui/fmt/issue-89173.stderr create mode 100644 tests/ui/fmt/issue-91556.rs create mode 100644 tests/ui/fmt/issue-91556.stderr create mode 100644 tests/ui/fmt/respanned-literal-issue-106191.rs create mode 100644 tests/ui/fmt/respanned-literal-issue-106191.stderr create mode 100644 tests/ui/fmt/send-sync.rs create mode 100644 tests/ui/fmt/send-sync.stderr create mode 100644 tests/ui/fmt/struct-field-as-captured-argument.fixed create mode 100644 tests/ui/fmt/struct-field-as-captured-argument.rs create mode 100644 tests/ui/fmt/struct-field-as-captured-argument.stderr create mode 100644 tests/ui/fmt/unicode-escape-spans.rs create mode 100644 tests/ui/fmt/unicode-escape-spans.stderr create mode 100644 tests/ui/fn-in-pat.rs create mode 100644 tests/ui/fn-in-pat.stderr create mode 100644 tests/ui/fn/bad-main.rs create mode 100644 tests/ui/fn/bad-main.stderr create mode 100644 tests/ui/fn/dyn-fn-alignment.rs create mode 100644 tests/ui/fn/expr-fn-panic.rs create mode 100644 tests/ui/fn/expr-fn.rs create mode 100644 tests/ui/fn/fn-bad-block-type.rs create mode 100644 tests/ui/fn/fn-bad-block-type.stderr create mode 100644 tests/ui/fn/fn-closure-mutable-capture.rs create mode 100644 tests/ui/fn/fn-closure-mutable-capture.stderr create mode 100644 tests/ui/fn/fn-compare-mismatch.rs create mode 100644 tests/ui/fn/fn-compare-mismatch.stderr create mode 100644 tests/ui/fn/fn-item-type.rs create mode 100644 tests/ui/fn/fn-item-type.stderr create mode 100644 tests/ui/fn/fn-recover-return-sign.fixed create mode 100644 tests/ui/fn/fn-recover-return-sign.rs create mode 100644 tests/ui/fn/fn-recover-return-sign.stderr create mode 100644 tests/ui/fn/fn-recover-return-sign2.rs create mode 100644 tests/ui/fn/fn-recover-return-sign2.stderr create mode 100644 tests/ui/fn/fn-trait-formatting.rs create mode 100644 tests/ui/fn/fn-trait-formatting.stderr create mode 100644 tests/ui/fn/fun-call-variants.rs create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type.rs create mode 100644 tests/ui/fn/implied-bounds-unnorm-associated-type.stderr create mode 100644 tests/ui/fn/issue-3044.rs create mode 100644 tests/ui/fn/issue-3044.stderr create mode 100644 tests/ui/fn/issue-3904.rs create mode 100644 tests/ui/fn/issue-80179.rs create mode 100644 tests/ui/fn/issue-80179.stderr create mode 100644 tests/ui/fn/keyword-order.rs create mode 100644 tests/ui/fn/keyword-order.stderr create mode 100644 tests/ui/fn/nested-function-names-issue-8587.rs create mode 100644 tests/ui/fn/signature-error-reporting-under-verbose.rs create mode 100644 tests/ui/fn/signature-error-reporting-under-verbose.stderr create mode 100644 tests/ui/fn/suggest-return-closure.rs create mode 100644 tests/ui/fn/suggest-return-closure.stderr create mode 100644 tests/ui/fn/suggest-return-future.rs create mode 100644 tests/ui/fn/suggest-return-future.stderr create mode 100644 tests/ui/for-loop-while/auto-loop.rs create mode 100644 tests/ui/for-loop-while/break-outside-loop.rs create mode 100644 tests/ui/for-loop-while/break-outside-loop.stderr create mode 100644 tests/ui/for-loop-while/break-value.rs create mode 100644 tests/ui/for-loop-while/break-while-condition.rs create mode 100644 tests/ui/for-loop-while/break-while-condition.stderr create mode 100644 tests/ui/for-loop-while/break.rs create mode 100644 tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs create mode 100644 tests/ui/for-loop-while/for-destruct.rs create mode 100644 tests/ui/for-loop-while/for-loop-goofiness.rs create mode 100644 tests/ui/for-loop-while/for-loop-has-unit-body.rs create mode 100644 tests/ui/for-loop-while/for-loop-into-iterator.rs create mode 100644 tests/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs create mode 100644 tests/ui/for-loop-while/for-loop-macro.rs create mode 100644 tests/ui/for-loop-while/for-loop-mut-ref-element.rs create mode 100644 tests/ui/for-loop-while/for-loop-no-std.rs create mode 100644 tests/ui/for-loop-while/for-loop-panic.rs create mode 100644 tests/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs create mode 100644 tests/ui/for-loop-while/foreach-external-iterators-break.rs create mode 100644 tests/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs create mode 100644 tests/ui/for-loop-while/foreach-external-iterators-hashmap.rs create mode 100644 tests/ui/for-loop-while/foreach-external-iterators-loop.rs create mode 100644 tests/ui/for-loop-while/foreach-external-iterators-nested.rs create mode 100644 tests/ui/for-loop-while/foreach-external-iterators.rs create mode 100644 tests/ui/for-loop-while/foreach-nested.rs create mode 100644 tests/ui/for-loop-while/foreach-put-structured.rs create mode 100644 tests/ui/for-loop-while/foreach-simple-outer-slot.rs create mode 100644 tests/ui/for-loop-while/issue-2216.rs create mode 100644 tests/ui/for-loop-while/issue-51345.rs create mode 100644 tests/ui/for-loop-while/issue-69841.rs create mode 100644 tests/ui/for-loop-while/label_break_value.rs create mode 100644 tests/ui/for-loop-while/label_break_value_invalid.rs create mode 100644 tests/ui/for-loop-while/label_break_value_invalid.stderr create mode 100644 tests/ui/for-loop-while/labeled-break.rs create mode 100644 tests/ui/for-loop-while/linear-for-loop.rs create mode 100644 tests/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs create mode 100644 tests/ui/for-loop-while/liveness-loop-break.rs create mode 100644 tests/ui/for-loop-while/liveness-move-in-loop.rs create mode 100644 tests/ui/for-loop-while/long-while.rs create mode 100644 tests/ui/for-loop-while/loop-break-cont-1.rs create mode 100644 tests/ui/for-loop-while/loop-break-cont.rs create mode 100644 tests/ui/for-loop-while/loop-break-value.rs create mode 100644 tests/ui/for-loop-while/loop-diverges.rs create mode 100644 tests/ui/for-loop-while/loop-label-shadowing.rs create mode 100644 tests/ui/for-loop-while/loop-labeled-break-value.rs create mode 100644 tests/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs create mode 100644 tests/ui/for-loop-while/loop-scope.rs create mode 100644 tests/ui/for-loop-while/while-cont.rs create mode 100644 tests/ui/for-loop-while/while-flow-graph.rs create mode 100644 tests/ui/for-loop-while/while-label.rs create mode 100644 tests/ui/for-loop-while/while-let-2.rs create mode 100644 tests/ui/for-loop-while/while-let-2.stderr create mode 100644 tests/ui/for-loop-while/while-let.rs create mode 100644 tests/ui/for-loop-while/while-loop-constraints-2.rs create mode 100644 tests/ui/for-loop-while/while-prelude-drop.rs create mode 100644 tests/ui/for-loop-while/while-with-break.rs create mode 100644 tests/ui/for-loop-while/while.rs create mode 100644 tests/ui/for/for-c-in-str.rs create mode 100644 tests/ui/for/for-c-in-str.stderr create mode 100644 tests/ui/for/for-expn.rs create mode 100644 tests/ui/for/for-expn.stderr create mode 100644 tests/ui/for/for-loop-bogosity.rs create mode 100644 tests/ui/for/for-loop-bogosity.stderr create mode 100644 tests/ui/for/for-loop-refutable-pattern-error-message.rs create mode 100644 tests/ui/for/for-loop-refutable-pattern-error-message.stderr create mode 100644 tests/ui/for/for-loop-type-error.rs create mode 100644 tests/ui/for/for-loop-type-error.stderr create mode 100644 tests/ui/for/for-loop-unconstrained-element-type.rs create mode 100644 tests/ui/for/for-loop-unconstrained-element-type.stderr create mode 100644 tests/ui/foreign-fn-return-lifetime.fixed create mode 100644 tests/ui/foreign-fn-return-lifetime.rs create mode 100644 tests/ui/foreign-fn-return-lifetime.stderr create mode 100644 tests/ui/foreign-unsafe-fn-called.mir.stderr create mode 100644 tests/ui/foreign-unsafe-fn-called.rs create mode 100644 tests/ui/foreign-unsafe-fn-called.thir.stderr create mode 100644 tests/ui/foreign/auxiliary/fn-abi.rs create mode 100644 tests/ui/foreign/foreign-fn-linkname.rs create mode 100644 tests/ui/foreign/foreign-int-types.rs create mode 100644 tests/ui/foreign/foreign-mod-src/compiletest-ignore-dir create mode 100644 tests/ui/foreign/foreign-mod-src/inner.rs create mode 100644 tests/ui/foreign/foreign-mod-unused-const.rs create mode 100644 tests/ui/foreign/foreign-pub-super.rs create mode 100644 tests/ui/foreign/foreign-src/compiletest-ignore-dir create mode 100644 tests/ui/foreign/foreign-src/foreign.rs create mode 100644 tests/ui/foreign/foreign-truncated-arguments.rs create mode 100644 tests/ui/foreign/foreign2.rs create mode 100644 tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs create mode 100644 tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr create mode 100644 tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs create mode 100644 tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr create mode 100644 tests/ui/foreign/issue-99276-same-type-lifetimes.rs create mode 100644 tests/ui/foreign/nil-decl-in-foreign.rs create mode 100644 tests/ui/format-no-std.rs create mode 100644 tests/ui/fully-qualified-type/fully-qualified-type-name1.rs create mode 100644 tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr create mode 100644 tests/ui/fully-qualified-type/fully-qualified-type-name2.rs create mode 100644 tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr create mode 100644 tests/ui/fully-qualified-type/fully-qualified-type-name4.rs create mode 100644 tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr create mode 100644 tests/ui/fun-indirect-call.rs create mode 100644 tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs create mode 100644 tests/ui/function-pointer/issue-102289.rs create mode 100644 tests/ui/function-pointer/sized-ret-with-binder.rs create mode 100644 tests/ui/function-pointer/unsized-ret.rs create mode 100644 tests/ui/function-pointer/unsized-ret.stderr create mode 100644 tests/ui/functional-struct-update/functional-struct-update-noncopyable.rs create mode 100644 tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr create mode 100644 tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs create mode 100644 tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr create mode 100644 tests/ui/functions-closures/auxiliary/fn-abi.rs create mode 100644 tests/ui/functions-closures/call-closure-from-overloaded-op.rs create mode 100644 tests/ui/functions-closures/capture-clauses-boxed-closures.rs create mode 100644 tests/ui/functions-closures/capture-clauses-unboxed-closures.rs create mode 100644 tests/ui/functions-closures/clone-closure.rs create mode 100644 tests/ui/functions-closures/closure-bounds-can-capture-chan.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/README.md create mode 100644 tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/issue-38714.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs create mode 100644 tests/ui/functions-closures/closure-expected-type/supply-nothing.rs create mode 100644 tests/ui/functions-closures/closure-immediate.rs create mode 100644 tests/ui/functions-closures/closure-inference.rs create mode 100644 tests/ui/functions-closures/closure-inference2.rs create mode 100644 tests/ui/functions-closures/closure-reform.rs create mode 100644 tests/ui/functions-closures/closure-returning-closure.rs create mode 100644 tests/ui/functions-closures/closure-to-fn-coercion.rs create mode 100644 tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs create mode 100644 tests/ui/functions-closures/copy-closure.rs create mode 100644 tests/ui/functions-closures/fn-abi.rs create mode 100644 tests/ui/functions-closures/fn-bare-assign.rs create mode 100644 tests/ui/functions-closures/fn-bare-coerce-to-block.rs create mode 100644 tests/ui/functions-closures/fn-bare-item.rs create mode 100644 tests/ui/functions-closures/fn-bare-size.rs create mode 100644 tests/ui/functions-closures/fn-bare-spawn.rs create mode 100644 tests/ui/functions-closures/fn-coerce-field.rs create mode 100644 tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs create mode 100644 tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr create mode 100644 tests/ui/functions-closures/fn-help-with-err.rs create mode 100644 tests/ui/functions-closures/fn-help-with-err.stderr create mode 100644 tests/ui/functions-closures/fn-item-type-cast.rs create mode 100644 tests/ui/functions-closures/fn-item-type-coerce.rs create mode 100644 tests/ui/functions-closures/fn-item-type-zero-sized.rs create mode 100644 tests/ui/functions-closures/fn-lval.rs create mode 100644 tests/ui/functions-closures/fn-type-infer.rs create mode 100644 tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs create mode 100644 tests/ui/functions-closures/nullable-pointer-opt-closures.rs create mode 100644 tests/ui/functions-closures/parallel-codegen-closures.rs create mode 100644 tests/ui/functions-closures/return-from-closure.rs create mode 100644 tests/ui/future-incompatible-lint-group.rs create mode 100644 tests/ui/future-incompatible-lint-group.stderr create mode 100644 tests/ui/generator/addassign-yield.rs create mode 100644 tests/ui/generator/async-generator-issue-67158.rs create mode 100644 tests/ui/generator/async-generator-issue-67158.stderr create mode 100644 tests/ui/generator/auto-trait-regions.rs create mode 100644 tests/ui/generator/auto-trait-regions.stderr create mode 100644 tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs create mode 100644 tests/ui/generator/auxiliary/xcrate-reachable.rs create mode 100644 tests/ui/generator/auxiliary/xcrate.rs create mode 100644 tests/ui/generator/borrow-in-tail-expr.rs create mode 100644 tests/ui/generator/borrowing.rs create mode 100644 tests/ui/generator/borrowing.stderr create mode 100644 tests/ui/generator/clone-impl-async.rs create mode 100644 tests/ui/generator/clone-impl-async.stderr create mode 100644 tests/ui/generator/clone-impl-static.rs create mode 100644 tests/ui/generator/clone-impl-static.stderr create mode 100644 tests/ui/generator/clone-impl.rs create mode 100644 tests/ui/generator/clone-impl.stderr create mode 100644 tests/ui/generator/conditional-drop.rs create mode 100644 tests/ui/generator/control-flow.rs create mode 100644 tests/ui/generator/derived-drop-parent-expr.rs create mode 100644 tests/ui/generator/discriminant.rs create mode 100644 tests/ui/generator/drop-and-replace.rs create mode 100644 tests/ui/generator/drop-control-flow.rs create mode 100644 tests/ui/generator/drop-env.rs create mode 100644 tests/ui/generator/drop-track-addassign-yield.rs create mode 100644 tests/ui/generator/drop-tracking-parent-expression.rs create mode 100644 tests/ui/generator/drop-tracking-parent-expression.stderr create mode 100644 tests/ui/generator/drop-tracking-yielding-in-match-guards.rs create mode 100644 tests/ui/generator/drop-yield-twice.rs create mode 100644 tests/ui/generator/drop-yield-twice.stderr create mode 100644 tests/ui/generator/dropck-resume.rs create mode 100644 tests/ui/generator/dropck-resume.stderr create mode 100644 tests/ui/generator/dropck.rs create mode 100644 tests/ui/generator/dropck.stderr create mode 100644 tests/ui/generator/generator-region-requirements.migrate.stderr create mode 100644 tests/ui/generator/generator-region-requirements.rs create mode 100644 tests/ui/generator/generator-region-requirements.stderr create mode 100644 tests/ui/generator/generator-resume-after-panic.rs create mode 100644 tests/ui/generator/generator-with-nll.rs create mode 100644 tests/ui/generator/generator-with-nll.stderr create mode 100644 tests/ui/generator/generator-yielding-or-returning-itself.rs create mode 100644 tests/ui/generator/generator-yielding-or-returning-itself.stderr create mode 100644 tests/ui/generator/issue-102645.rs create mode 100644 tests/ui/generator/issue-102645.stderr create mode 100644 tests/ui/generator/issue-44197.rs create mode 100644 tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr create mode 100644 tests/ui/generator/issue-45729-unsafe-in-generator.rs create mode 100644 tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr create mode 100644 tests/ui/generator/issue-48048.rs create mode 100644 tests/ui/generator/issue-48048.stderr create mode 100644 tests/ui/generator/issue-52304.rs create mode 100644 tests/ui/generator/issue-52398.rs create mode 100644 tests/ui/generator/issue-52398.stderr create mode 100644 tests/ui/generator/issue-53548-1.rs create mode 100644 tests/ui/generator/issue-53548.rs create mode 100644 tests/ui/generator/issue-57017.rs create mode 100644 tests/ui/generator/issue-57084.rs create mode 100644 tests/ui/generator/issue-57084.stderr create mode 100644 tests/ui/generator/issue-57478.rs create mode 100644 tests/ui/generator/issue-58888.rs create mode 100644 tests/ui/generator/issue-61442-stmt-expr-with-drop.rs create mode 100644 tests/ui/generator/issue-62506-two_awaits.rs create mode 100644 tests/ui/generator/issue-64620-yield-array-element.rs create mode 100644 tests/ui/generator/issue-64620-yield-array-element.stderr create mode 100644 tests/ui/generator/issue-68112.rs create mode 100644 tests/ui/generator/issue-68112.stderr create mode 100644 tests/ui/generator/issue-69017.rs create mode 100644 tests/ui/generator/issue-69039.rs create mode 100644 tests/ui/generator/issue-87142.rs create mode 100644 tests/ui/generator/issue-88653.rs create mode 100644 tests/ui/generator/issue-88653.stderr create mode 100644 tests/ui/generator/issue-91477.rs create mode 100644 tests/ui/generator/issue-91477.stderr create mode 100644 tests/ui/generator/issue-93161.rs create mode 100644 tests/ui/generator/iterator-count.rs create mode 100644 tests/ui/generator/layout-error.rs create mode 100644 tests/ui/generator/layout-error.stderr create mode 100644 tests/ui/generator/live-upvar-across-yield.rs create mode 100644 tests/ui/generator/match-bindings.rs create mode 100644 tests/ui/generator/match-bindings.stderr create mode 100644 tests/ui/generator/metadata-sufficient-for-layout.rs create mode 100644 tests/ui/generator/metadata-sufficient-for-layout.stderr create mode 100644 tests/ui/generator/nested_generators.rs create mode 100644 tests/ui/generator/niche-in-generator.rs create mode 100644 tests/ui/generator/non-static-is-unpin.rs create mode 100644 tests/ui/generator/not-send-sync.rs create mode 100644 tests/ui/generator/not-send-sync.stderr create mode 100644 tests/ui/generator/overlap-locals.rs create mode 100644 tests/ui/generator/panic-drops-resume.rs create mode 100644 tests/ui/generator/panic-drops.rs create mode 100644 tests/ui/generator/panic-safe.rs create mode 100644 tests/ui/generator/partial-drop.rs create mode 100644 tests/ui/generator/partial-drop.stderr create mode 100644 tests/ui/generator/partial-initialization-across-yield.rs create mode 100644 tests/ui/generator/partial-initialization-across-yield.stderr create mode 100644 tests/ui/generator/pattern-borrow.rs create mode 100644 tests/ui/generator/pattern-borrow.stderr create mode 100644 tests/ui/generator/pin-box-generator.rs create mode 100644 tests/ui/generator/print/generator-print-verbose-1.rs create mode 100644 tests/ui/generator/print/generator-print-verbose-1.stderr create mode 100644 tests/ui/generator/print/generator-print-verbose-2.rs create mode 100644 tests/ui/generator/print/generator-print-verbose-2.stderr create mode 100644 tests/ui/generator/print/generator-print-verbose-3.rs create mode 100644 tests/ui/generator/print/generator-print-verbose-3.stderr create mode 100644 tests/ui/generator/reborrow-mut-upvar.rs create mode 100644 tests/ui/generator/reborrow-mut-upvar.stderr create mode 100644 tests/ui/generator/ref-escapes-but-not-over-yield.rs create mode 100644 tests/ui/generator/ref-escapes-but-not-over-yield.stderr create mode 100644 tests/ui/generator/ref-upvar-not-send.rs create mode 100644 tests/ui/generator/ref-upvar-not-send.stderr create mode 100644 tests/ui/generator/reinit-in-match-guard.rs create mode 100644 tests/ui/generator/resume-after-return.rs create mode 100644 tests/ui/generator/resume-arg-late-bound.rs create mode 100644 tests/ui/generator/resume-arg-late-bound.stderr create mode 100644 tests/ui/generator/resume-arg-size.rs create mode 100644 tests/ui/generator/resume-live-across-yield.rs create mode 100644 tests/ui/generator/retain-resume-ref.rs create mode 100644 tests/ui/generator/retain-resume-ref.stderr create mode 100644 tests/ui/generator/size-moved-locals.rs create mode 100644 tests/ui/generator/sized-yield.rs create mode 100644 tests/ui/generator/sized-yield.stderr create mode 100644 tests/ui/generator/smoke-resume-args.rs create mode 100644 tests/ui/generator/smoke.rs create mode 100644 tests/ui/generator/static-generators.rs create mode 100644 tests/ui/generator/static-mut-reference-across-yield.rs create mode 100644 tests/ui/generator/static-not-unpin.rs create mode 100644 tests/ui/generator/static-not-unpin.stderr create mode 100644 tests/ui/generator/static-reference-across-yield.rs create mode 100644 tests/ui/generator/too-live-local-in-immovable-gen.rs create mode 100644 tests/ui/generator/too-live-local-in-immovable-gen.stderr create mode 100644 tests/ui/generator/too-many-parameters.rs create mode 100644 tests/ui/generator/too-many-parameters.stderr create mode 100644 tests/ui/generator/type-mismatch-error.rs create mode 100644 tests/ui/generator/type-mismatch-error.stderr create mode 100644 tests/ui/generator/type-mismatch-signature-deduction.rs create mode 100644 tests/ui/generator/type-mismatch-signature-deduction.stderr create mode 100644 tests/ui/generator/unresolved-ct-var-drop-tracking.rs create mode 100644 tests/ui/generator/unresolved-ct-var-drop-tracking.stderr create mode 100644 tests/ui/generator/unresolved-ct-var.rs create mode 100644 tests/ui/generator/unresolved-ct-var.stderr create mode 100644 tests/ui/generator/xcrate-reachable.rs create mode 100644 tests/ui/generator/xcrate.rs create mode 100644 tests/ui/generator/yield-in-args-rev.rs create mode 100644 tests/ui/generator/yield-in-args-rev.stderr create mode 100644 tests/ui/generator/yield-in-args.rs create mode 100644 tests/ui/generator/yield-in-args.stderr create mode 100644 tests/ui/generator/yield-in-box.rs create mode 100644 tests/ui/generator/yield-in-box.stderr create mode 100644 tests/ui/generator/yield-in-const.rs create mode 100644 tests/ui/generator/yield-in-const.stderr create mode 100644 tests/ui/generator/yield-in-function.rs create mode 100644 tests/ui/generator/yield-in-function.stderr create mode 100644 tests/ui/generator/yield-in-initializer.rs create mode 100644 tests/ui/generator/yield-in-initializer.stderr create mode 100644 tests/ui/generator/yield-in-static.rs create mode 100644 tests/ui/generator/yield-in-static.stderr create mode 100644 tests/ui/generator/yield-outside-generator-issue-78653.rs create mode 100644 tests/ui/generator/yield-outside-generator-issue-78653.stderr create mode 100644 tests/ui/generator/yield-subtype.rs create mode 100644 tests/ui/generator/yield-subtype.stderr create mode 100644 tests/ui/generator/yield-while-iterating.rs create mode 100644 tests/ui/generator/yield-while-iterating.stderr create mode 100644 tests/ui/generator/yield-while-local-borrowed.rs create mode 100644 tests/ui/generator/yield-while-local-borrowed.stderr create mode 100644 tests/ui/generator/yield-while-ref-reborrowed.rs create mode 100644 tests/ui/generator/yield-while-ref-reborrowed.stderr create mode 100644 tests/ui/generator/yielding-in-match-guards.rs create mode 100644 tests/ui/generic-associated-types/anonymize-bound-vars.rs create mode 100644 tests/ui/generic-associated-types/auxiliary/foo_defn.rs create mode 100644 tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs create mode 100644 tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr create mode 100644 tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs create mode 100644 tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr create mode 100644 tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs create mode 100644 tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-100013.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-100013.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-80626.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-87735.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-87735.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-87755.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-87755.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-87803.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-87803.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-88382.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-88382.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-88460.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-88460.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-88526.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-88526.stderr create mode 100644 tests/ui/generic-associated-types/bugs/issue-91762.rs create mode 100644 tests/ui/generic-associated-types/bugs/issue-91762.stderr create mode 100644 tests/ui/generic-associated-types/collections-project-default.rs create mode 100644 tests/ui/generic-associated-types/collections-project-default.stderr create mode 100644 tests/ui/generic-associated-types/collections.rs create mode 100644 tests/ui/generic-associated-types/collectivity-regression.rs create mode 100644 tests/ui/generic-associated-types/collectivity-regression.stderr create mode 100644 tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs create mode 100644 tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs create mode 100644 tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs create mode 100644 tests/ui/generic-associated-types/const_params_have_right_type.rs create mode 100644 tests/ui/generic-associated-types/const_params_have_right_type.stderr create mode 100644 tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs create mode 100644 tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr create mode 100644 tests/ui/generic-associated-types/construct_with_other_type.rs create mode 100644 tests/ui/generic-associated-types/cross-crate-bounds.rs create mode 100644 tests/ui/generic-associated-types/cross-crate-bounds.stderr create mode 100644 tests/ui/generic-associated-types/elided-in-expr-position.rs create mode 100644 tests/ui/generic-associated-types/elided-in-expr-position.stderr create mode 100644 tests/ui/generic-associated-types/empty_generics.rs create mode 100644 tests/ui/generic-associated-types/empty_generics.stderr create mode 100644 tests/ui/generic-associated-types/equality-bound.rs create mode 100644 tests/ui/generic-associated-types/equality-bound.stderr create mode 100644 tests/ui/generic-associated-types/extended/lending_iterator.base.stderr create mode 100644 tests/ui/generic-associated-types/extended/lending_iterator.rs create mode 100644 tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr create mode 100644 tests/ui/generic-associated-types/extended/lending_iterator_2.rs create mode 100644 tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs create mode 100644 tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr create mode 100644 tests/ui/generic-associated-types/gat-in-trait-path.base.stderr create mode 100644 tests/ui/generic-associated-types/gat-in-trait-path.rs create mode 100644 tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs create mode 100644 tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr create mode 100644 tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs create mode 100644 tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr create mode 100644 tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs create mode 100644 tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr create mode 100644 tests/ui/generic-associated-types/generic-associated-type-bounds.rs create mode 100644 tests/ui/generic-associated-types/generic-associated-types-where.rs create mode 100644 tests/ui/generic-associated-types/generic-associated-types-where.stderr create mode 100644 tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs create mode 100644 tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr create mode 100644 tests/ui/generic-associated-types/impl_bounds.rs create mode 100644 tests/ui/generic-associated-types/impl_bounds.stderr create mode 100644 tests/ui/generic-associated-types/impl_bounds_ok.rs create mode 100644 tests/ui/generic-associated-types/issue-101020.rs create mode 100644 tests/ui/generic-associated-types/issue-101020.stderr create mode 100644 tests/ui/generic-associated-types/issue-102114.rs create mode 100644 tests/ui/generic-associated-types/issue-102114.stderr create mode 100644 tests/ui/generic-associated-types/issue-102333.rs create mode 100644 tests/ui/generic-associated-types/issue-102335-gat.rs create mode 100644 tests/ui/generic-associated-types/issue-102335-gat.stderr create mode 100644 tests/ui/generic-associated-types/issue-47206-where-clause.rs create mode 100644 tests/ui/generic-associated-types/issue-47206-where-clause.stderr create mode 100644 tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs create mode 100644 tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs create mode 100644 tests/ui/generic-associated-types/issue-67424.rs create mode 100644 tests/ui/generic-associated-types/issue-67510-pass.base.stderr create mode 100644 tests/ui/generic-associated-types/issue-67510-pass.rs create mode 100644 tests/ui/generic-associated-types/issue-67510.rs create mode 100644 tests/ui/generic-associated-types/issue-67510.stderr create mode 100644 tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs create mode 100644 tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr create mode 100644 tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs create mode 100644 tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr create mode 100644 tests/ui/generic-associated-types/issue-68643-broken-mir.rs create mode 100644 tests/ui/generic-associated-types/issue-68643-broken-mir.stderr create mode 100644 tests/ui/generic-associated-types/issue-68644-codegen-selection.rs create mode 100644 tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr create mode 100644 tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs create mode 100644 tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr create mode 100644 tests/ui/generic-associated-types/issue-68648-1.rs create mode 100644 tests/ui/generic-associated-types/issue-68648-2.rs create mode 100644 tests/ui/generic-associated-types/issue-68648-2.stderr create mode 100644 tests/ui/generic-associated-types/issue-68649-pass.rs create mode 100644 tests/ui/generic-associated-types/issue-68653.rs create mode 100644 tests/ui/generic-associated-types/issue-68656-unsized-values.rs create mode 100644 tests/ui/generic-associated-types/issue-68656-unsized-values.stderr create mode 100644 tests/ui/generic-associated-types/issue-70303.rs create mode 100644 tests/ui/generic-associated-types/issue-70304.rs create mode 100644 tests/ui/generic-associated-types/issue-70304.stderr create mode 100644 tests/ui/generic-associated-types/issue-71176.rs create mode 100644 tests/ui/generic-associated-types/issue-71176.stderr create mode 100644 tests/ui/generic-associated-types/issue-74684-1.rs create mode 100644 tests/ui/generic-associated-types/issue-74684-1.stderr create mode 100644 tests/ui/generic-associated-types/issue-74684-2.rs create mode 100644 tests/ui/generic-associated-types/issue-74684-2.stderr create mode 100644 tests/ui/generic-associated-types/issue-74816.rs create mode 100644 tests/ui/generic-associated-types/issue-74816.stderr create mode 100644 tests/ui/generic-associated-types/issue-74824.rs create mode 100644 tests/ui/generic-associated-types/issue-74824.stderr create mode 100644 tests/ui/generic-associated-types/issue-76407.rs create mode 100644 tests/ui/generic-associated-types/issue-76535.base.stderr create mode 100644 tests/ui/generic-associated-types/issue-76535.extended.stderr create mode 100644 tests/ui/generic-associated-types/issue-76535.rs create mode 100644 tests/ui/generic-associated-types/issue-76826.rs create mode 100644 tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs create mode 100644 tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr create mode 100644 tests/ui/generic-associated-types/issue-78671.base.stderr create mode 100644 tests/ui/generic-associated-types/issue-78671.extended.stderr create mode 100644 tests/ui/generic-associated-types/issue-78671.rs create mode 100644 tests/ui/generic-associated-types/issue-79422.base.stderr create mode 100644 tests/ui/generic-associated-types/issue-79422.extended.stderr create mode 100644 tests/ui/generic-associated-types/issue-79422.rs create mode 100644 tests/ui/generic-associated-types/issue-79636-1.rs create mode 100644 tests/ui/generic-associated-types/issue-79636-1.stderr create mode 100644 tests/ui/generic-associated-types/issue-79636-2.rs create mode 100644 tests/ui/generic-associated-types/issue-79636-2.stderr create mode 100644 tests/ui/generic-associated-types/issue-80433-reduced.rs create mode 100644 tests/ui/generic-associated-types/issue-80433.rs create mode 100644 tests/ui/generic-associated-types/issue-80433.stderr create mode 100644 tests/ui/generic-associated-types/issue-81487.rs create mode 100644 tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs create mode 100644 tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr create mode 100644 tests/ui/generic-associated-types/issue-81862.rs create mode 100644 tests/ui/generic-associated-types/issue-81862.stderr create mode 100644 tests/ui/generic-associated-types/issue-84931.rs create mode 100644 tests/ui/generic-associated-types/issue-84931.stderr create mode 100644 tests/ui/generic-associated-types/issue-85921.rs create mode 100644 tests/ui/generic-associated-types/issue-86218-2.rs create mode 100644 tests/ui/generic-associated-types/issue-86218.rs create mode 100644 tests/ui/generic-associated-types/issue-86483.rs create mode 100644 tests/ui/generic-associated-types/issue-86787.rs create mode 100644 tests/ui/generic-associated-types/issue-86787.stderr create mode 100644 tests/ui/generic-associated-types/issue-87258_a.rs create mode 100644 tests/ui/generic-associated-types/issue-87258_a.stderr create mode 100644 tests/ui/generic-associated-types/issue-87258_b.rs create mode 100644 tests/ui/generic-associated-types/issue-87258_b.stderr create mode 100644 tests/ui/generic-associated-types/issue-87429-2.rs create mode 100644 tests/ui/generic-associated-types/issue-87429-associated-type-default.rs create mode 100644 tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr create mode 100644 tests/ui/generic-associated-types/issue-87429-specialization.rs create mode 100644 tests/ui/generic-associated-types/issue-87429-specialization.stderr create mode 100644 tests/ui/generic-associated-types/issue-87429.rs create mode 100644 tests/ui/generic-associated-types/issue-87748.rs create mode 100644 tests/ui/generic-associated-types/issue-87750.rs create mode 100644 tests/ui/generic-associated-types/issue-88287.rs create mode 100644 tests/ui/generic-associated-types/issue-88287.stderr create mode 100644 tests/ui/generic-associated-types/issue-88360.rs create mode 100644 tests/ui/generic-associated-types/issue-88360.stderr create mode 100644 tests/ui/generic-associated-types/issue-88405.rs create mode 100644 tests/ui/generic-associated-types/issue-88459.rs create mode 100644 tests/ui/generic-associated-types/issue-88595.rs create mode 100644 tests/ui/generic-associated-types/issue-88595.stderr create mode 100644 tests/ui/generic-associated-types/issue-89008.rs create mode 100644 tests/ui/generic-associated-types/issue-89352.rs create mode 100644 tests/ui/generic-associated-types/issue-90014.rs create mode 100644 tests/ui/generic-associated-types/issue-90014.stderr create mode 100644 tests/ui/generic-associated-types/issue-90729.rs create mode 100644 tests/ui/generic-associated-types/issue-91139.migrate.stderr create mode 100644 tests/ui/generic-associated-types/issue-91139.rs create mode 100644 tests/ui/generic-associated-types/issue-91139.stderr create mode 100644 tests/ui/generic-associated-types/issue-91883.rs create mode 100644 tests/ui/generic-associated-types/issue-91883.stderr create mode 100644 tests/ui/generic-associated-types/issue-92033.rs create mode 100644 tests/ui/generic-associated-types/issue-92033.stderr create mode 100644 tests/ui/generic-associated-types/issue-92096.migrate.stderr create mode 100644 tests/ui/generic-associated-types/issue-92096.rs create mode 100644 tests/ui/generic-associated-types/issue-92096.stderr create mode 100644 tests/ui/generic-associated-types/issue-92280.rs create mode 100644 tests/ui/generic-associated-types/issue-92954.rs create mode 100644 tests/ui/generic-associated-types/issue-93141.rs create mode 100644 tests/ui/generic-associated-types/issue-93262.rs create mode 100644 tests/ui/generic-associated-types/issue-93340.rs create mode 100644 tests/ui/generic-associated-types/issue-93341.rs create mode 100644 tests/ui/generic-associated-types/issue-93342.rs create mode 100644 tests/ui/generic-associated-types/issue-93874.rs create mode 100644 tests/ui/generic-associated-types/issue-95305.rs create mode 100644 tests/ui/generic-associated-types/issue-95305.stderr create mode 100644 tests/ui/generic-associated-types/iterable.rs create mode 100644 tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs create mode 100644 tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr create mode 100644 tests/ui/generic-associated-types/mismatched-where-clause-regions.rs create mode 100644 tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr create mode 100644 tests/ui/generic-associated-types/missing-bounds.fixed create mode 100644 tests/ui/generic-associated-types/missing-bounds.rs create mode 100644 tests/ui/generic-associated-types/missing-bounds.stderr create mode 100644 tests/ui/generic-associated-types/missing-where-clause-on-trait.rs create mode 100644 tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr create mode 100644 tests/ui/generic-associated-types/missing_lifetime_args.rs create mode 100644 tests/ui/generic-associated-types/missing_lifetime_args.stderr create mode 100644 tests/ui/generic-associated-types/missing_lifetime_const.rs create mode 100644 tests/ui/generic-associated-types/missing_lifetime_const.stderr create mode 100644 tests/ui/generic-associated-types/own-bound-span.rs create mode 100644 tests/ui/generic-associated-types/own-bound-span.stderr create mode 100644 tests/ui/generic-associated-types/parameter_number_and_kind.rs create mode 100644 tests/ui/generic-associated-types/parameter_number_and_kind.stderr create mode 100644 tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs create mode 100644 tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr create mode 100644 tests/ui/generic-associated-types/parse/in-trait-impl.rs create mode 100644 tests/ui/generic-associated-types/parse/in-trait.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-expected-token.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr create mode 100644 tests/ui/generic-associated-types/parse/trait-path-expressions.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-expressions.stderr create mode 100644 tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr create mode 100644 tests/ui/generic-associated-types/parse/trait-path-segments.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-segments.stderr create mode 100644 tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr create mode 100644 tests/ui/generic-associated-types/parse/trait-path-types.rs create mode 100644 tests/ui/generic-associated-types/parse/trait-path-types.stderr create mode 100644 tests/ui/generic-associated-types/pointer_family.rs create mode 100644 tests/ui/generic-associated-types/projection-bound-cycle-generic.rs create mode 100644 tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr create mode 100644 tests/ui/generic-associated-types/projection-bound-cycle.rs create mode 100644 tests/ui/generic-associated-types/projection-bound-cycle.stderr create mode 100644 tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs create mode 100644 tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr create mode 100644 tests/ui/generic-associated-types/self-outlives-lint.rs create mode 100644 tests/ui/generic-associated-types/self-outlives-lint.stderr create mode 100644 tests/ui/generic-associated-types/shadowing.rs create mode 100644 tests/ui/generic-associated-types/shadowing.stderr create mode 100644 tests/ui/generic-associated-types/streaming_iterator.rs create mode 100644 tests/ui/generic-associated-types/trait-objects.base.stderr create mode 100644 tests/ui/generic-associated-types/trait-objects.extended.stderr create mode 100644 tests/ui/generic-associated-types/trait-objects.rs create mode 100644 tests/ui/generic-associated-types/type-param-defaults.rs create mode 100644 tests/ui/generic-associated-types/type-param-defaults.stderr create mode 100644 tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs create mode 100644 tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr create mode 100644 tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs create mode 100644 tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr create mode 100644 tests/ui/generic-associated-types/variance_constraints.rs create mode 100644 tests/ui/generics/autobind.rs create mode 100644 tests/ui/generics/auxiliary/default_type_params_xc.rs create mode 100644 tests/ui/generics/bad-mid-path-type-params.rs create mode 100644 tests/ui/generics/bad-mid-path-type-params.stderr create mode 100644 tests/ui/generics/generic-alias-unique.rs create mode 100644 tests/ui/generics/generic-arg-mismatch-recover.rs create mode 100644 tests/ui/generics/generic-arg-mismatch-recover.stderr create mode 100644 tests/ui/generics/generic-default-type-params-cross-crate.rs create mode 100644 tests/ui/generics/generic-default-type-params.rs create mode 100644 tests/ui/generics/generic-derived-type.rs create mode 100644 tests/ui/generics/generic-exterior-unique.rs create mode 100644 tests/ui/generics/generic-extern-lifetime.rs create mode 100644 tests/ui/generics/generic-extern-lifetime.stderr create mode 100644 tests/ui/generics/generic-extern-mangle.rs create mode 100644 tests/ui/generics/generic-extern.rs create mode 100644 tests/ui/generics/generic-extern.stderr create mode 100644 tests/ui/generics/generic-fn-infer.rs create mode 100644 tests/ui/generics/generic-fn-twice.rs create mode 100644 tests/ui/generics/generic-fn-unique.rs create mode 100644 tests/ui/generics/generic-fn.rs create mode 100644 tests/ui/generics/generic-function-item-where-type.rs create mode 100644 tests/ui/generics/generic-function-item-where-type.stderr create mode 100644 tests/ui/generics/generic-impl-less-params-with-defaults.rs create mode 100644 tests/ui/generics/generic-impl-less-params-with-defaults.stderr create mode 100644 tests/ui/generics/generic-impl-more-params-with-defaults.rs create mode 100644 tests/ui/generics/generic-impl-more-params-with-defaults.stderr create mode 100644 tests/ui/generics/generic-ivec-leak.rs create mode 100644 tests/ui/generics/generic-lifetime-trait-impl.rs create mode 100644 tests/ui/generics/generic-lifetime-trait-impl.stderr create mode 100644 tests/ui/generics/generic-newtype-struct.rs create mode 100644 tests/ui/generics/generic-no-mangle.fixed create mode 100644 tests/ui/generics/generic-no-mangle.rs create mode 100644 tests/ui/generics/generic-no-mangle.stderr create mode 100644 tests/ui/generics/generic-non-trailing-defaults.rs create mode 100644 tests/ui/generics/generic-non-trailing-defaults.stderr create mode 100644 tests/ui/generics/generic-object.rs create mode 100644 tests/ui/generics/generic-param-attrs.rs create mode 100644 tests/ui/generics/generic-recursive-tag.rs create mode 100644 tests/ui/generics/generic-static-methods.rs create mode 100644 tests/ui/generics/generic-tag-corruption.rs create mode 100644 tests/ui/generics/generic-tag-local.rs create mode 100644 tests/ui/generics/generic-tag-match.rs create mode 100644 tests/ui/generics/generic-tag-values.rs create mode 100644 tests/ui/generics/generic-tag.rs create mode 100644 tests/ui/generics/generic-temporary.rs create mode 100644 tests/ui/generics/generic-tup.rs create mode 100644 tests/ui/generics/generic-type-less-params-with-defaults.rs create mode 100644 tests/ui/generics/generic-type-less-params-with-defaults.stderr create mode 100644 tests/ui/generics/generic-type-more-params-with-defaults.rs create mode 100644 tests/ui/generics/generic-type-more-params-with-defaults.stderr create mode 100644 tests/ui/generics/generic-type-params-forward-mention.rs create mode 100644 tests/ui/generics/generic-type-params-forward-mention.stderr create mode 100644 tests/ui/generics/generic-type-params-name-repr.rs create mode 100644 tests/ui/generics/generic-type-params-name-repr.stderr create mode 100644 tests/ui/generics/generic-type-synonym.rs create mode 100644 tests/ui/generics/generic-type.rs create mode 100644 tests/ui/generics/generic-unique.rs create mode 100644 tests/ui/generics/issue-106694.rs create mode 100644 tests/ui/generics/issue-106694.stderr create mode 100644 tests/ui/generics/issue-1112.rs create mode 100644 tests/ui/generics/issue-2936.rs create mode 100644 tests/ui/generics/issue-32498.rs create mode 100644 tests/ui/generics/issue-333.rs create mode 100644 tests/ui/generics/issue-59508-1.rs create mode 100644 tests/ui/generics/issue-59508-1.stderr create mode 100644 tests/ui/generics/issue-59508.fixed create mode 100644 tests/ui/generics/issue-59508.rs create mode 100644 tests/ui/generics/issue-59508.stderr create mode 100644 tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs create mode 100644 tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr create mode 100644 tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs create mode 100644 tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr create mode 100644 tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs create mode 100644 tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr create mode 100644 tests/ui/generics/issue-80512-param-reordering-with-defaults.rs create mode 100644 tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr create mode 100644 tests/ui/generics/issue-94432-garbage-ice.rs create mode 100644 tests/ui/generics/issue-94923.rs create mode 100644 tests/ui/generics/issue-95208-ignore-qself.fixed create mode 100644 tests/ui/generics/issue-95208-ignore-qself.rs create mode 100644 tests/ui/generics/issue-95208-ignore-qself.stderr create mode 100644 tests/ui/generics/issue-95208.fixed create mode 100644 tests/ui/generics/issue-95208.rs create mode 100644 tests/ui/generics/issue-95208.stderr create mode 100644 tests/ui/generics/issue-98432.rs create mode 100644 tests/ui/generics/issue-98432.stderr create mode 100644 tests/ui/generics/lifetime-before-type-params.rs create mode 100644 tests/ui/generics/lifetime-before-type-params.stderr create mode 100644 tests/ui/generics/mid-path-type-params.rs create mode 100644 tests/ui/generics/param-in-ct-in-ty-param-default.rs create mode 100644 tests/ui/generics/param-in-ct-in-ty-param-default.stderr create mode 100644 tests/ui/generics/post_monomorphization_error_backtrace.rs create mode 100644 tests/ui/generics/post_monomorphization_error_backtrace.stderr create mode 100644 tests/ui/generics/single-colon-path-not-const-generics.rs create mode 100644 tests/ui/generics/single-colon-path-not-const-generics.stderr create mode 100644 tests/ui/generics/type-params-in-for-each.rs create mode 100644 tests/ui/generics/wrong-number-of-args.rs create mode 100644 tests/ui/generics/wrong-number-of-args.stderr create mode 100644 tests/ui/global-scope.rs create mode 100644 tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs create mode 100644 tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr create mode 100644 tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs create mode 100644 tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr create mode 100644 tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs create mode 100644 tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr create mode 100644 tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs create mode 100644 tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs create mode 100644 tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr create mode 100644 tests/ui/half-open-range-patterns/pat-tuple-4.rs create mode 100644 tests/ui/half-open-range-patterns/pat-tuple-5.rs create mode 100644 tests/ui/half-open-range-patterns/pat-tuple-5.stderr create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions0.rs create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions1.rs create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions1.stderr create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions2.rs create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions2.stderr create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions3.rs create mode 100644 tests/ui/half-open-range-patterns/range_pat_interactions3.stderr create mode 100644 tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs create mode 100644 tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr create mode 100644 tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs create mode 100644 tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr create mode 100644 tests/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs create mode 100644 tests/ui/hashmap/hashmap-capacity-overflow.rs create mode 100644 tests/ui/hashmap/hashmap-index-mut.rs create mode 100644 tests/ui/hashmap/hashmap-index-mut.stderr create mode 100644 tests/ui/hashmap/hashmap-iter-value-lifetime.rs create mode 100644 tests/ui/hashmap/hashmap-iter-value-lifetime.stderr create mode 100644 tests/ui/hashmap/hashmap-lifetimes.rs create mode 100644 tests/ui/hashmap/hashmap-lifetimes.stderr create mode 100644 tests/ui/hashmap/hashmap-memory.rs create mode 100644 tests/ui/hello.rs create mode 100644 tests/ui/hello_world/main.rs create mode 100644 tests/ui/higher-lifetime-bounds.rs create mode 100644 tests/ui/higher-lifetime-bounds.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/complex.rs create mode 100644 tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs create mode 100644 tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-parse.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs create mode 100644 tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/issue-100689.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-102899.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-30786.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-30786.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-42114.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-43623.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-46989.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-46989.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/issue-57639.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-58451.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-58451.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/issue-59311.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-59311.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/issue-60283.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/issue-88446.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-90177.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-95034.rs create mode 100644 tests/ui/higher-rank-trait-bounds/issue-95230.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs create mode 100644 tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr create mode 100644 tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr create mode 100644 tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr create mode 100644 tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr create mode 100644 tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr create mode 100644 tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr create mode 100644 tests/ui/hr-subtype/hr-subtype.rs create mode 100644 tests/ui/hr-subtype/placeholder-pattern-fail.rs create mode 100644 tests/ui/hr-subtype/placeholder-pattern-fail.stderr create mode 100644 tests/ui/hr-subtype/placeholder-pattern.rs create mode 100644 tests/ui/hr-subtype/return-static.rs create mode 100644 tests/ui/hygiene/arguments.rs create mode 100644 tests/ui/hygiene/arguments.stderr create mode 100644 tests/ui/hygiene/assoc_item_ctxt.rs create mode 100644 tests/ui/hygiene/assoc_item_ctxt.stderr create mode 100644 tests/ui/hygiene/assoc_ty_bindings.rs create mode 100644 tests/ui/hygiene/auxiliary/codegen-attrs.rs create mode 100644 tests/ui/hygiene/auxiliary/def-site-async-await.rs create mode 100644 tests/ui/hygiene/auxiliary/fields.rs create mode 100644 tests/ui/hygiene/auxiliary/intercrate.rs create mode 100644 tests/ui/hygiene/auxiliary/legacy_interaction.rs create mode 100644 tests/ui/hygiene/auxiliary/local_inner_macros.rs create mode 100644 tests/ui/hygiene/auxiliary/methods.rs create mode 100644 tests/ui/hygiene/auxiliary/my_crate.rs create mode 100644 tests/ui/hygiene/auxiliary/needs_hygiene.rs create mode 100644 tests/ui/hygiene/auxiliary/nested-dollar-crate.rs create mode 100644 tests/ui/hygiene/auxiliary/not-libstd.rs create mode 100644 tests/ui/hygiene/auxiliary/opaque-hygiene.rs create mode 100644 tests/ui/hygiene/auxiliary/pub_hygiene.rs create mode 100644 tests/ui/hygiene/auxiliary/stdlib-prelude.rs create mode 100644 tests/ui/hygiene/auxiliary/transparent-basic.rs create mode 100644 tests/ui/hygiene/auxiliary/unhygienic_example.rs create mode 100644 tests/ui/hygiene/auxiliary/use_by_macro.rs create mode 100644 tests/ui/hygiene/auxiliary/variants.rs create mode 100644 tests/ui/hygiene/auxiliary/xcrate.rs create mode 100644 tests/ui/hygiene/cross-crate-codegen-attrs.rs create mode 100644 tests/ui/hygiene/cross-crate-define-and-use.rs create mode 100644 tests/ui/hygiene/cross-crate-fields.rs create mode 100644 tests/ui/hygiene/cross-crate-glob-hygiene.rs create mode 100644 tests/ui/hygiene/cross-crate-glob-hygiene.stderr create mode 100644 tests/ui/hygiene/cross-crate-methods.rs create mode 100644 tests/ui/hygiene/cross-crate-name-collision.rs create mode 100644 tests/ui/hygiene/cross-crate-name-hiding-2.rs create mode 100644 tests/ui/hygiene/cross-crate-name-hiding-2.stderr create mode 100644 tests/ui/hygiene/cross-crate-name-hiding.rs create mode 100644 tests/ui/hygiene/cross-crate-name-hiding.stderr create mode 100644 tests/ui/hygiene/cross-crate-redefine.rs create mode 100644 tests/ui/hygiene/cross-crate-redefine.stderr create mode 100644 tests/ui/hygiene/cross-crate-variants.rs create mode 100644 tests/ui/hygiene/dollar-crate-modern.rs create mode 100644 tests/ui/hygiene/duplicate_lifetimes.rs create mode 100644 tests/ui/hygiene/duplicate_lifetimes.stderr create mode 100644 tests/ui/hygiene/eager-from-opaque-2.rs create mode 100644 tests/ui/hygiene/eager-from-opaque.rs create mode 100644 tests/ui/hygiene/expansion-info-reset.rs create mode 100644 tests/ui/hygiene/expansion-info-reset.stderr create mode 100644 tests/ui/hygiene/extern-prelude-from-opaque-fail.rs create mode 100644 tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr create mode 100644 tests/ui/hygiene/fields-definition.rs create mode 100644 tests/ui/hygiene/fields-definition.stderr create mode 100644 tests/ui/hygiene/fields-move.rs create mode 100644 tests/ui/hygiene/fields-move.stderr create mode 100644 tests/ui/hygiene/fields-numeric-borrowck.rs create mode 100644 tests/ui/hygiene/fields-numeric-borrowck.stderr create mode 100644 tests/ui/hygiene/fields.rs create mode 100644 tests/ui/hygiene/fields.stderr create mode 100644 tests/ui/hygiene/for-loop.rs create mode 100644 tests/ui/hygiene/for-loop.stderr create mode 100644 tests/ui/hygiene/format-args.rs create mode 100644 tests/ui/hygiene/generate-mod.rs create mode 100644 tests/ui/hygiene/generate-mod.stderr create mode 100644 tests/ui/hygiene/generic_params.rs create mode 100644 tests/ui/hygiene/globs.rs create mode 100644 tests/ui/hygiene/globs.stderr create mode 100644 tests/ui/hygiene/hir-res-hygiene.rs create mode 100644 tests/ui/hygiene/hygiene-dodging-1.rs create mode 100644 tests/ui/hygiene/hygiene.rs create mode 100644 tests/ui/hygiene/hygienic-label-1.rs create mode 100644 tests/ui/hygiene/hygienic-label-1.stderr create mode 100644 tests/ui/hygiene/hygienic-label-2.rs create mode 100644 tests/ui/hygiene/hygienic-label-2.stderr create mode 100644 tests/ui/hygiene/hygienic-label-3.rs create mode 100644 tests/ui/hygiene/hygienic-label-3.stderr create mode 100644 tests/ui/hygiene/hygienic-label-4.rs create mode 100644 tests/ui/hygiene/hygienic-label-4.stderr create mode 100644 tests/ui/hygiene/hygienic-labels-in-let.rs create mode 100644 tests/ui/hygiene/hygienic-labels.rs create mode 100644 tests/ui/hygiene/impl_items-2.rs create mode 100644 tests/ui/hygiene/impl_items-2.stderr create mode 100644 tests/ui/hygiene/impl_items.rs create mode 100644 tests/ui/hygiene/impl_items.stderr create mode 100644 tests/ui/hygiene/intercrate.rs create mode 100644 tests/ui/hygiene/intercrate.stderr create mode 100644 tests/ui/hygiene/issue-15221.rs create mode 100644 tests/ui/hygiene/issue-32922.rs create mode 100644 tests/ui/hygiene/issue-40847.rs create mode 100644 tests/ui/hygiene/issue-44128.rs create mode 100644 tests/ui/hygiene/issue-47311.rs create mode 100644 tests/ui/hygiene/issue-47312.rs create mode 100644 tests/ui/hygiene/issue-61574-const-parameters.rs create mode 100644 tests/ui/hygiene/issue-77523-def-site-async-await.rs create mode 100644 tests/ui/hygiene/items.rs create mode 100644 tests/ui/hygiene/lambda-var-hygiene.rs create mode 100644 tests/ui/hygiene/legacy_interaction.rs create mode 100644 tests/ui/hygiene/lexical.rs create mode 100644 tests/ui/hygiene/local_inner_macros.rs create mode 100644 tests/ui/hygiene/macro-metavars-legacy.rs create mode 100644 tests/ui/hygiene/macro-metavars-transparent.rs create mode 100644 tests/ui/hygiene/missing-self-diag.rs create mode 100644 tests/ui/hygiene/missing-self-diag.stderr create mode 100644 tests/ui/hygiene/nested-dollar-crate.rs create mode 100644 tests/ui/hygiene/nested_macro_privacy.rs create mode 100644 tests/ui/hygiene/nested_macro_privacy.stderr create mode 100644 tests/ui/hygiene/no_implicit_prelude-2018.rs create mode 100644 tests/ui/hygiene/no_implicit_prelude-2018.stderr create mode 100644 tests/ui/hygiene/no_implicit_prelude-2021.rs create mode 100644 tests/ui/hygiene/no_implicit_prelude.rs create mode 100644 tests/ui/hygiene/no_implicit_prelude.stderr create mode 100644 tests/ui/hygiene/panic-location.rs create mode 100644 tests/ui/hygiene/panic-location.run.stderr create mode 100644 tests/ui/hygiene/pattern-macro.rs create mode 100644 tests/ui/hygiene/pattern-macro.stderr create mode 100644 tests/ui/hygiene/prelude-import-hygiene.rs create mode 100644 tests/ui/hygiene/privacy-early.rs create mode 100644 tests/ui/hygiene/privacy-early.stderr create mode 100644 tests/ui/hygiene/privacy.rs create mode 100644 tests/ui/hygiene/privacy.stderr create mode 100644 tests/ui/hygiene/rustc-macro-transparency.rs create mode 100644 tests/ui/hygiene/rustc-macro-transparency.stderr create mode 100644 tests/ui/hygiene/specialization.rs create mode 100644 tests/ui/hygiene/stdlib-prelude-from-opaque-early.rs create mode 100644 tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs create mode 100644 tests/ui/hygiene/thread-local-not-in-prelude.rs create mode 100644 tests/ui/hygiene/trait_items-2.rs create mode 100644 tests/ui/hygiene/trait_items.rs create mode 100644 tests/ui/hygiene/trait_items.stderr create mode 100644 tests/ui/hygiene/traits-in-scope.rs create mode 100644 tests/ui/hygiene/transparent-basic.rs create mode 100644 tests/ui/hygiene/unpretty-debug.rs create mode 100644 tests/ui/hygiene/unpretty-debug.stdout create mode 100644 tests/ui/hygiene/wrap_unhygienic_example.rs create mode 100644 tests/ui/hygiene/xcrate.rs create mode 100644 tests/ui/illegal-sized-bound/mutability-mismatch-arg.fixed create mode 100644 tests/ui/illegal-sized-bound/mutability-mismatch-arg.rs create mode 100644 tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr create mode 100644 tests/ui/illegal-sized-bound/mutability-mismatch.rs create mode 100644 tests/ui/illegal-sized-bound/mutability-mismatch.stderr create mode 100644 tests/ui/illegal-sized-bound/regular.rs create mode 100644 tests/ui/illegal-sized-bound/regular.stderr create mode 100644 tests/ui/illegal-ufcs-drop.fixed create mode 100644 tests/ui/illegal-ufcs-drop.rs create mode 100644 tests/ui/illegal-ufcs-drop.stderr create mode 100644 tests/ui/impl-header-lifetime-elision/assoc-type.rs create mode 100644 tests/ui/impl-header-lifetime-elision/assoc-type.stderr create mode 100644 tests/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs create mode 100644 tests/ui/impl-header-lifetime-elision/dyn-trait.rs create mode 100644 tests/ui/impl-header-lifetime-elision/dyn-trait.stderr create mode 100644 tests/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs create mode 100644 tests/ui/impl-header-lifetime-elision/inherent-impl.rs create mode 100644 tests/ui/impl-header-lifetime-elision/path-elided.rs create mode 100644 tests/ui/impl-header-lifetime-elision/path-elided.stderr create mode 100644 tests/ui/impl-header-lifetime-elision/path-underscore.rs create mode 100644 tests/ui/impl-header-lifetime-elision/ref-underscore.rs create mode 100644 tests/ui/impl-header-lifetime-elision/trait-elided.rs create mode 100644 tests/ui/impl-header-lifetime-elision/trait-elided.stderr create mode 100644 tests/ui/impl-header-lifetime-elision/trait-underscore.rs create mode 100644 tests/ui/impl-inherent-non-conflict.rs create mode 100644 tests/ui/impl-not-adjacent-to-type.rs create mode 100644 tests/ui/impl-privacy-xc-1.rs create mode 100644 tests/ui/impl-trait/associated-impl-trait-type-generic-trait.rs create mode 100644 tests/ui/impl-trait/associated-impl-trait-type-trivial.rs create mode 100644 tests/ui/impl-trait/associated-impl-trait-type.rs create mode 100644 tests/ui/impl-trait/async_scope_creep.rs create mode 100644 tests/ui/impl-trait/auto-trait-leak-rpass.rs create mode 100644 tests/ui/impl-trait/auto-trait-leak.rs create mode 100644 tests/ui/impl-trait/auto-trait-leak.stderr create mode 100644 tests/ui/impl-trait/auto-trait-leak2.rs create mode 100644 tests/ui/impl-trait/auto-trait-leak2.stderr create mode 100644 tests/ui/impl-trait/auto-trait.rs create mode 100644 tests/ui/impl-trait/auto-trait.stderr create mode 100644 tests/ui/impl-trait/autoderef.rs create mode 100644 tests/ui/impl-trait/auxiliary/extra-item.rs create mode 100644 tests/ui/impl-trait/auxiliary/no_method_suggested_traits.rs create mode 100644 tests/ui/impl-trait/auxiliary/xcrate.rs create mode 100644 tests/ui/impl-trait/bound-normalization-fail.rs create mode 100644 tests/ui/impl-trait/bound-normalization-fail.stderr create mode 100644 tests/ui/impl-trait/bound-normalization-pass.rs create mode 100644 tests/ui/impl-trait/bounds_regression.rs create mode 100644 tests/ui/impl-trait/can-return-unconstrained-closure.rs create mode 100644 tests/ui/impl-trait/closure-calling-parent-fn.rs create mode 100644 tests/ui/impl-trait/closure-in-impl-trait-arg.rs create mode 100644 tests/ui/impl-trait/closure-in-impl-trait.rs create mode 100644 tests/ui/impl-trait/cross-return-site-inference.rs create mode 100644 tests/ui/impl-trait/cross-return-site-inference.stderr create mode 100644 tests/ui/impl-trait/deduce-signature-from-supertrait.rs create mode 100644 tests/ui/impl-trait/deprecated_annotation.rs create mode 100644 tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs create mode 100644 tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr create mode 100644 tests/ui/impl-trait/divergence.rs create mode 100644 tests/ui/impl-trait/does-not-live-long-enough.rs create mode 100644 tests/ui/impl-trait/does-not-live-long-enough.stderr create mode 100644 tests/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs create mode 100644 tests/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs create mode 100644 tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs create mode 100644 tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs create mode 100644 tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs create mode 100644 tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr create mode 100644 tests/ui/impl-trait/equal-hidden-lifetimes.rs create mode 100644 tests/ui/impl-trait/equal-hidden-lifetimes.stderr create mode 100644 tests/ui/impl-trait/equality-rpass.rs create mode 100644 tests/ui/impl-trait/equality-rpass.stderr create mode 100644 tests/ui/impl-trait/equality.rs create mode 100644 tests/ui/impl-trait/equality.stderr create mode 100644 tests/ui/impl-trait/equality2.rs create mode 100644 tests/ui/impl-trait/equality2.stderr create mode 100644 tests/ui/impl-trait/example-calendar.rs create mode 100644 tests/ui/impl-trait/example-st.rs create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs create mode 100644 tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr create mode 100644 tests/ui/impl-trait/extra-item.rs create mode 100644 tests/ui/impl-trait/extra-item.stderr create mode 100644 tests/ui/impl-trait/fallback.rs create mode 100644 tests/ui/impl-trait/fallback_inference.rs create mode 100644 tests/ui/impl-trait/fallback_inference.stderr create mode 100644 tests/ui/impl-trait/feature-self-return-type.rs create mode 100644 tests/ui/impl-trait/feature-self-return-type.stderr create mode 100644 tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr create mode 100644 tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr create mode 100644 tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs create mode 100644 tests/ui/impl-trait/hidden-lifetimes.rs create mode 100644 tests/ui/impl-trait/hidden-lifetimes.stderr create mode 100644 tests/ui/impl-trait/hidden-type-is-opaque-2.rs create mode 100644 tests/ui/impl-trait/hidden-type-is-opaque-2.stderr create mode 100644 tests/ui/impl-trait/hidden-type-is-opaque.rs create mode 100644 tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs create mode 100644 tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr create mode 100644 tests/ui/impl-trait/impl-fn-hrtb-bounds.rs create mode 100644 tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr create mode 100644 tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs create mode 100644 tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr create mode 100644 tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs create mode 100644 tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr create mode 100644 tests/ui/impl-trait/impl-generic-mismatch-ab.rs create mode 100644 tests/ui/impl-trait/impl-generic-mismatch-ab.stderr create mode 100644 tests/ui/impl-trait/impl-generic-mismatch.rs create mode 100644 tests/ui/impl-trait/impl-generic-mismatch.stderr create mode 100644 tests/ui/impl-trait/impl-trait-in-macro.rs create mode 100644 tests/ui/impl-trait/impl-trait-in-macro.stderr create mode 100644 tests/ui/impl-trait/impl-trait-plus-priority.rs create mode 100644 tests/ui/impl-trait/impl-trait-plus-priority.stderr create mode 100644 tests/ui/impl-trait/impl_fn_associativity.rs create mode 100644 tests/ui/impl-trait/impl_trait_projections.rs create mode 100644 tests/ui/impl-trait/impl_trait_projections.stderr create mode 100644 tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs create mode 100644 tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs create mode 100644 tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr create mode 100644 tests/ui/impl-trait/in-trait/deep-match-works.rs create mode 100644 tests/ui/impl-trait/in-trait/deep-match.rs create mode 100644 tests/ui/impl-trait/in-trait/deep-match.stderr create mode 100644 tests/ui/impl-trait/in-trait/default-body-type-err-2.rs create mode 100644 tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr create mode 100644 tests/ui/impl-trait/in-trait/default-body-type-err.rs create mode 100644 tests/ui/impl-trait/in-trait/default-body-type-err.stderr create mode 100644 tests/ui/impl-trait/in-trait/default-body-with-rpit.rs create mode 100644 tests/ui/impl-trait/in-trait/default-body.rs create mode 100644 tests/ui/impl-trait/in-trait/doesnt-satisfy.rs create mode 100644 tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr create mode 100644 tests/ui/impl-trait/in-trait/early.rs create mode 100644 tests/ui/impl-trait/in-trait/encode.rs create mode 100644 tests/ui/impl-trait/in-trait/foreign.rs create mode 100644 tests/ui/impl-trait/in-trait/generics-mismatch.rs create mode 100644 tests/ui/impl-trait/in-trait/generics-mismatch.stderr create mode 100644 tests/ui/impl-trait/in-trait/issue-102140.rs create mode 100644 tests/ui/impl-trait/in-trait/issue-102140.stderr create mode 100644 tests/ui/impl-trait/in-trait/issue-102301.rs create mode 100644 tests/ui/impl-trait/in-trait/issue-102571.rs create mode 100644 tests/ui/impl-trait/in-trait/issue-102571.stderr create mode 100644 tests/ui/impl-trait/in-trait/method-signature-matches.rs create mode 100644 tests/ui/impl-trait/in-trait/method-signature-matches.stderr create mode 100644 tests/ui/impl-trait/in-trait/nested-rpitit.rs create mode 100644 tests/ui/impl-trait/in-trait/object-safety.rs create mode 100644 tests/ui/impl-trait/in-trait/object-safety.stderr create mode 100644 tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs create mode 100644 tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr create mode 100644 tests/ui/impl-trait/in-trait/opaque-in-impl.rs create mode 100644 tests/ui/impl-trait/in-trait/reveal.rs create mode 100644 tests/ui/impl-trait/in-trait/signature-mismatch.rs create mode 100644 tests/ui/impl-trait/in-trait/signature-mismatch.stderr create mode 100644 tests/ui/impl-trait/in-trait/specialization-broken.rs create mode 100644 tests/ui/impl-trait/in-trait/specialization-broken.stderr create mode 100644 tests/ui/impl-trait/in-trait/specialization-substs-remap.rs create mode 100644 tests/ui/impl-trait/in-trait/success.rs create mode 100644 tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs create mode 100644 tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr create mode 100644 tests/ui/impl-trait/in-trait/wf-bounds.rs create mode 100644 tests/ui/impl-trait/in-trait/wf-bounds.stderr create mode 100644 tests/ui/impl-trait/in-trait/where-clause.rs create mode 100644 tests/ui/impl-trait/issue-100075-2.rs create mode 100644 tests/ui/impl-trait/issue-100075-2.stderr create mode 100644 tests/ui/impl-trait/issue-100075.rs create mode 100644 tests/ui/impl-trait/issue-100075.stderr create mode 100644 tests/ui/impl-trait/issue-100187.rs create mode 100644 tests/ui/impl-trait/issue-102605.rs create mode 100644 tests/ui/impl-trait/issue-102605.stderr create mode 100644 tests/ui/impl-trait/issue-103181-1.rs create mode 100644 tests/ui/impl-trait/issue-103181-1.stderr create mode 100644 tests/ui/impl-trait/issue-103181-2.rs create mode 100644 tests/ui/impl-trait/issue-103181-2.stderr create mode 100644 tests/ui/impl-trait/issue-103599.rs create mode 100644 tests/ui/impl-trait/issue-103599.stderr create mode 100644 tests/ui/impl-trait/issue-35668.rs create mode 100644 tests/ui/impl-trait/issue-35668.stderr create mode 100644 tests/ui/impl-trait/issue-46959.rs create mode 100644 tests/ui/impl-trait/issue-49556.rs create mode 100644 tests/ui/impl-trait/issue-49579.rs create mode 100644 tests/ui/impl-trait/issue-49685.rs create mode 100644 tests/ui/impl-trait/issue-51185.rs create mode 100644 tests/ui/impl-trait/issue-54966.rs create mode 100644 tests/ui/impl-trait/issue-54966.stderr create mode 100644 tests/ui/impl-trait/issue-55872-1.rs create mode 100644 tests/ui/impl-trait/issue-55872-1.stderr create mode 100644 tests/ui/impl-trait/issue-55872-2.rs create mode 100644 tests/ui/impl-trait/issue-55872-2.stderr create mode 100644 tests/ui/impl-trait/issue-55872-3.rs create mode 100644 tests/ui/impl-trait/issue-55872-3.stderr create mode 100644 tests/ui/impl-trait/issue-55872.rs create mode 100644 tests/ui/impl-trait/issue-55872.stderr create mode 100644 tests/ui/impl-trait/issue-56445.rs create mode 100644 tests/ui/impl-trait/issue-68532.rs create mode 100644 tests/ui/impl-trait/issue-72911.rs create mode 100644 tests/ui/impl-trait/issue-72911.stderr create mode 100644 tests/ui/impl-trait/issue-86465.rs create mode 100644 tests/ui/impl-trait/issue-86465.stderr create mode 100644 tests/ui/impl-trait/issue-87450.rs create mode 100644 tests/ui/impl-trait/issue-87450.stderr create mode 100644 tests/ui/impl-trait/issue-99073-2.rs create mode 100644 tests/ui/impl-trait/issue-99073-2.stderr create mode 100644 tests/ui/impl-trait/issue-99073.rs create mode 100644 tests/ui/impl-trait/issue-99073.stderr create mode 100644 tests/ui/impl-trait/issue-99642-2.rs create mode 100644 tests/ui/impl-trait/issue-99642.rs create mode 100644 tests/ui/impl-trait/issue-99914.rs create mode 100644 tests/ui/impl-trait/issue-99914.stderr create mode 100644 tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs create mode 100644 tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr create mode 100644 tests/ui/impl-trait/issues/issue-104815.rs create mode 100644 tests/ui/impl-trait/issues/issue-105826.rs create mode 100644 tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs create mode 100644 tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr create mode 100644 tests/ui/impl-trait/issues/issue-42479.rs create mode 100644 tests/ui/impl-trait/issues/issue-49376.rs create mode 100644 tests/ui/impl-trait/issues/issue-52128.rs create mode 100644 tests/ui/impl-trait/issues/issue-53457.rs create mode 100644 tests/ui/impl-trait/issues/issue-54600.rs create mode 100644 tests/ui/impl-trait/issues/issue-54600.stderr create mode 100644 tests/ui/impl-trait/issues/issue-54840.rs create mode 100644 tests/ui/impl-trait/issues/issue-54840.stderr create mode 100644 tests/ui/impl-trait/issues/issue-54895.rs create mode 100644 tests/ui/impl-trait/issues/issue-54895.stderr create mode 100644 tests/ui/impl-trait/issues/issue-55608-captures-empty-region.rs create mode 100644 tests/ui/impl-trait/issues/issue-57464-unexpected-regions.rs create mode 100644 tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs create mode 100644 tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr create mode 100644 tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs create mode 100644 tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr create mode 100644 tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs create mode 100644 tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr create mode 100644 tests/ui/impl-trait/issues/issue-58504.rs create mode 100644 tests/ui/impl-trait/issues/issue-58504.stderr create mode 100644 tests/ui/impl-trait/issues/issue-58956.rs create mode 100644 tests/ui/impl-trait/issues/issue-58956.stderr create mode 100644 tests/ui/impl-trait/issues/issue-62742.rs create mode 100644 tests/ui/impl-trait/issues/issue-62742.stderr create mode 100644 tests/ui/impl-trait/issues/issue-65581.rs create mode 100644 tests/ui/impl-trait/issues/issue-67830.rs create mode 100644 tests/ui/impl-trait/issues/issue-67830.stderr create mode 100644 tests/ui/impl-trait/issues/issue-70877.rs create mode 100644 tests/ui/impl-trait/issues/issue-70877.stderr create mode 100644 tests/ui/impl-trait/issues/issue-70971.rs create mode 100644 tests/ui/impl-trait/issues/issue-70971.stderr create mode 100644 tests/ui/impl-trait/issues/issue-74282.rs create mode 100644 tests/ui/impl-trait/issues/issue-74282.stderr create mode 100644 tests/ui/impl-trait/issues/issue-77987.rs create mode 100644 tests/ui/impl-trait/issues/issue-78722.rs create mode 100644 tests/ui/impl-trait/issues/issue-78722.stderr create mode 100644 tests/ui/impl-trait/issues/issue-79099.rs create mode 100644 tests/ui/impl-trait/issues/issue-79099.stderr create mode 100644 tests/ui/impl-trait/issues/issue-82139.rs create mode 100644 tests/ui/impl-trait/issues/issue-82139.stderr create mode 100644 tests/ui/impl-trait/issues/issue-83919.rs create mode 100644 tests/ui/impl-trait/issues/issue-83919.stderr create mode 100644 tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs create mode 100644 tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr create mode 100644 tests/ui/impl-trait/issues/issue-84073.rs create mode 100644 tests/ui/impl-trait/issues/issue-84073.stderr create mode 100644 tests/ui/impl-trait/issues/issue-84919.rs create mode 100644 tests/ui/impl-trait/issues/issue-84919.stderr create mode 100644 tests/ui/impl-trait/issues/issue-86201.rs create mode 100644 tests/ui/impl-trait/issues/issue-86642.rs create mode 100644 tests/ui/impl-trait/issues/issue-86642.stderr create mode 100644 tests/ui/impl-trait/issues/issue-86719.rs create mode 100644 tests/ui/impl-trait/issues/issue-86719.stderr create mode 100644 tests/ui/impl-trait/issues/issue-86800.rs create mode 100644 tests/ui/impl-trait/issues/issue-86800.stderr create mode 100644 tests/ui/impl-trait/issues/issue-87295.rs create mode 100644 tests/ui/impl-trait/issues/issue-87295.stderr create mode 100644 tests/ui/impl-trait/issues/issue-87340.rs create mode 100644 tests/ui/impl-trait/issues/issue-87340.stderr create mode 100644 tests/ui/impl-trait/issues/issue-88236-2.rs create mode 100644 tests/ui/impl-trait/issues/issue-88236-2.stderr create mode 100644 tests/ui/impl-trait/issues/issue-88236.rs create mode 100644 tests/ui/impl-trait/issues/issue-88236.stderr create mode 100644 tests/ui/impl-trait/issues/issue-89312.rs create mode 100644 tests/ui/impl-trait/issues/issue-92305.rs create mode 100644 tests/ui/impl-trait/issues/issue-92305.stderr create mode 100644 tests/ui/impl-trait/issues/issue-93788.rs create mode 100644 tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs create mode 100644 tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr create mode 100644 tests/ui/impl-trait/lifetimes.rs create mode 100644 tests/ui/impl-trait/lifetimes2.rs create mode 100644 tests/ui/impl-trait/method-suggestion-no-duplication.rs create mode 100644 tests/ui/impl-trait/method-suggestion-no-duplication.stderr create mode 100644 tests/ui/impl-trait/multiple-lifetimes.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr create mode 100644 tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr create mode 100644 tests/ui/impl-trait/multiple-lifetimes/error-handling.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr create mode 100644 tests/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs create mode 100644 tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr create mode 100644 tests/ui/impl-trait/must_outlive_least_region_or_bound.rs create mode 100644 tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr create mode 100644 tests/ui/impl-trait/needs_least_region_or_bound.rs create mode 100644 tests/ui/impl-trait/negative-reasoning.rs create mode 100644 tests/ui/impl-trait/negative-reasoning.stderr create mode 100644 tests/ui/impl-trait/nested-return-type.rs create mode 100644 tests/ui/impl-trait/nested-return-type2-tait.rs create mode 100644 tests/ui/impl-trait/nested-return-type2-tait.stderr create mode 100644 tests/ui/impl-trait/nested-return-type2-tait2.rs create mode 100644 tests/ui/impl-trait/nested-return-type2-tait2.stderr create mode 100644 tests/ui/impl-trait/nested-return-type2-tait3.rs create mode 100644 tests/ui/impl-trait/nested-return-type2-tait3.stderr create mode 100644 tests/ui/impl-trait/nested-return-type2.rs create mode 100644 tests/ui/impl-trait/nested-return-type2.stderr create mode 100644 tests/ui/impl-trait/nested-return-type3-tait.rs create mode 100644 tests/ui/impl-trait/nested-return-type3-tait.stderr create mode 100644 tests/ui/impl-trait/nested-return-type3-tait2.rs create mode 100644 tests/ui/impl-trait/nested-return-type3-tait2.stderr create mode 100644 tests/ui/impl-trait/nested-return-type3-tait3.rs create mode 100644 tests/ui/impl-trait/nested-return-type3-tait3.stderr create mode 100644 tests/ui/impl-trait/nested-return-type3.rs create mode 100644 tests/ui/impl-trait/nested-return-type3.stderr create mode 100644 tests/ui/impl-trait/nested-return-type4.rs create mode 100644 tests/ui/impl-trait/nested-return-type4.stderr create mode 100644 tests/ui/impl-trait/nested-rpit-hrtb.rs create mode 100644 tests/ui/impl-trait/nested-rpit-hrtb.stderr create mode 100644 tests/ui/impl-trait/nested-rpit-with-anonymous-lifetimes.rs create mode 100644 tests/ui/impl-trait/nested_impl_trait.rs create mode 100644 tests/ui/impl-trait/nested_impl_trait.stderr create mode 100644 tests/ui/impl-trait/nesting.rs create mode 100644 tests/ui/impl-trait/no-method-suggested-traits.rs create mode 100644 tests/ui/impl-trait/no-method-suggested-traits.stderr create mode 100644 tests/ui/impl-trait/no-trait.rs create mode 100644 tests/ui/impl-trait/no-trait.stderr create mode 100644 tests/ui/impl-trait/normalize-tait-in-const.rs create mode 100644 tests/ui/impl-trait/normalize-tait-in-const.stderr create mode 100644 tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs create mode 100644 tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr create mode 100644 tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs create mode 100644 tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr create mode 100644 tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs create mode 100644 tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr create mode 100644 tests/ui/impl-trait/printing-binder.rs create mode 100644 tests/ui/impl-trait/printing-binder.stderr create mode 100644 tests/ui/impl-trait/private_unused.rs create mode 100644 tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs create mode 100644 tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr create mode 100644 tests/ui/impl-trait/projection.rs create mode 100644 tests/ui/impl-trait/question_mark.rs create mode 100644 tests/ui/impl-trait/recursive-generator.rs create mode 100644 tests/ui/impl-trait/recursive-generator.stderr create mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-direct.rs create mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs create mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr create mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs create mode 100644 tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr create mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs create mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr create mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs create mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr create mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs create mode 100644 tests/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs create mode 100644 tests/ui/impl-trait/region-escape-via-bound-contravariant.rs create mode 100644 tests/ui/impl-trait/region-escape-via-bound.rs create mode 100644 tests/ui/impl-trait/region-escape-via-bound.stderr create mode 100644 tests/ui/impl-trait/return-position-impl-trait-minimal.rs create mode 100644 tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs create mode 100644 tests/ui/impl-trait/rpit-not-sized.rs create mode 100644 tests/ui/impl-trait/rpit-not-sized.stderr create mode 100644 tests/ui/impl-trait/static-return-lifetime-infered.rs create mode 100644 tests/ui/impl-trait/static-return-lifetime-infered.stderr create mode 100644 tests/ui/impl-trait/suggest-calling-rpit-closure.rs create mode 100644 tests/ui/impl-trait/suggest-calling-rpit-closure.stderr create mode 100644 tests/ui/impl-trait/trait_resolution.rs create mode 100644 tests/ui/impl-trait/trait_type.rs create mode 100644 tests/ui/impl-trait/trait_type.stderr create mode 100644 tests/ui/impl-trait/two_tait_defining_each_other.rs create mode 100644 tests/ui/impl-trait/two_tait_defining_each_other.stderr create mode 100644 tests/ui/impl-trait/two_tait_defining_each_other2.rs create mode 100644 tests/ui/impl-trait/two_tait_defining_each_other2.stderr create mode 100644 tests/ui/impl-trait/two_tait_defining_each_other3.rs create mode 100644 tests/ui/impl-trait/two_tait_defining_each_other3.stderr create mode 100644 tests/ui/impl-trait/type-alias-generic-param.rs create mode 100644 tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs create mode 100644 tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs create mode 100644 tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr create mode 100644 tests/ui/impl-trait/type_parameters_captured.rs create mode 100644 tests/ui/impl-trait/type_parameters_captured.stderr create mode 100644 tests/ui/impl-trait/unactionable_diagnostic.fixed create mode 100644 tests/ui/impl-trait/unactionable_diagnostic.rs create mode 100644 tests/ui/impl-trait/unactionable_diagnostic.stderr create mode 100644 tests/ui/impl-trait/universal-mismatched-type.rs create mode 100644 tests/ui/impl-trait/universal-mismatched-type.stderr create mode 100644 tests/ui/impl-trait/universal-two-impl-traits.rs create mode 100644 tests/ui/impl-trait/universal-two-impl-traits.stderr create mode 100644 tests/ui/impl-trait/universal_hrtb_anon.rs create mode 100644 tests/ui/impl-trait/universal_hrtb_named.rs create mode 100644 tests/ui/impl-trait/universal_in_adt_in_parameters.rs create mode 100644 tests/ui/impl-trait/universal_in_impl_trait_in_parameters.rs create mode 100644 tests/ui/impl-trait/universal_in_trait_defn_parameters.rs create mode 100644 tests/ui/impl-trait/universal_multiple_bounds.rs create mode 100644 tests/ui/impl-trait/universal_wrong_bounds.rs create mode 100644 tests/ui/impl-trait/universal_wrong_bounds.stderr create mode 100644 tests/ui/impl-trait/universal_wrong_hrtb.rs create mode 100644 tests/ui/impl-trait/universal_wrong_hrtb.stderr create mode 100644 tests/ui/impl-trait/unsafety-checking-cycle.rs create mode 100644 tests/ui/impl-trait/wf-eval-order.rs create mode 100644 tests/ui/impl-trait/where-allowed-2.rs create mode 100644 tests/ui/impl-trait/where-allowed-2.stderr create mode 100644 tests/ui/impl-trait/where-allowed.rs create mode 100644 tests/ui/impl-trait/where-allowed.stderr create mode 100644 tests/ui/impl-trait/xcrate.rs create mode 100644 tests/ui/impl-trait/xcrate_simple.rs create mode 100644 tests/ui/impl-unused-rps-in-assoc-type.rs create mode 100644 tests/ui/impl-unused-rps-in-assoc-type.stderr create mode 100644 tests/ui/impl-unused-tps-inherent.rs create mode 100644 tests/ui/impl-unused-tps-inherent.stderr create mode 100644 tests/ui/impl-unused-tps.rs create mode 100644 tests/ui/impl-unused-tps.stderr create mode 100644 tests/ui/implicit-method-bind.rs create mode 100644 tests/ui/implicit-method-bind.stderr create mode 100644 tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs create mode 100644 tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr create mode 100644 tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs create mode 100644 tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr create mode 100644 tests/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs create mode 100644 tests/ui/implied-bounds/impl-header-unnormalized-types.rs create mode 100644 tests/ui/implied-bounds/impl-header-unnormalized-types.stderr create mode 100644 tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs create mode 100644 tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr create mode 100644 tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs create mode 100644 tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr create mode 100644 tests/ui/implied-bounds/issue-100690.rs create mode 100644 tests/ui/implied-bounds/issue-100690.stderr create mode 100644 tests/ui/implied-bounds/issue-101951.rs create mode 100644 tests/ui/imports/absolute-paths-in-nested-use-groups.rs create mode 100644 tests/ui/imports/absolute-paths-in-nested-use-groups.stderr create mode 100644 tests/ui/imports/auxiliary/gensymed.rs create mode 100644 tests/ui/imports/auxiliary/glob-conflict.rs create mode 100644 tests/ui/imports/auxiliary/import_crate_var.rs create mode 100644 tests/ui/imports/auxiliary/issue-36881-aux.rs create mode 100644 tests/ui/imports/auxiliary/issue-52891.rs create mode 100644 tests/ui/imports/auxiliary/issue-55811.rs create mode 100644 tests/ui/imports/auxiliary/issue-56125.rs create mode 100644 tests/ui/imports/auxiliary/issue-59764.rs create mode 100644 tests/ui/imports/auxiliary/overlapping_pub_trait_source.rs create mode 100644 tests/ui/imports/auxiliary/two_macros.rs create mode 100644 tests/ui/imports/auxiliary/unnamed_pub_trait_source.rs create mode 100644 tests/ui/imports/bad-import-in-nested.rs create mode 100644 tests/ui/imports/bad-import-in-nested.stderr create mode 100644 tests/ui/imports/bad-import-with-rename.rs create mode 100644 tests/ui/imports/bad-import-with-rename.stderr create mode 100644 tests/ui/imports/double-import.rs create mode 100644 tests/ui/imports/double-import.stderr create mode 100644 tests/ui/imports/duplicate.rs create mode 100644 tests/ui/imports/duplicate.stderr create mode 100644 tests/ui/imports/export-glob-imports-target.rs create mode 100644 tests/ui/imports/export-multi.rs create mode 100644 tests/ui/imports/extern-crate-self/extern-crate-self-fail.rs create mode 100644 tests/ui/imports/extern-crate-self/extern-crate-self-fail.stderr create mode 100644 tests/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs create mode 100644 tests/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs create mode 100644 tests/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs create mode 100644 tests/ui/imports/extern-crate-self/extern-crate-self-pass.rs create mode 100644 tests/ui/imports/extern-crate-used.rs create mode 100644 tests/ui/imports/extern-crate-used.stderr create mode 100644 tests/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs create mode 100644 tests/ui/imports/extern-prelude-extern-crate-cfg.rs create mode 100644 tests/ui/imports/extern-prelude-extern-crate-fail.rs create mode 100644 tests/ui/imports/extern-prelude-extern-crate-fail.stderr create mode 100644 tests/ui/imports/extern-prelude-extern-crate-pass.rs create mode 100644 tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs create mode 100644 tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr create mode 100644 tests/ui/imports/extern-prelude-extern-crate-shadowing.rs create mode 100644 tests/ui/imports/gensymed.rs create mode 100644 tests/ui/imports/glob-conflict-cross-crate.rs create mode 100644 tests/ui/imports/glob-conflict-cross-crate.stderr create mode 100644 tests/ui/imports/glob-cycles.rs create mode 100644 tests/ui/imports/glob-resolve1.rs create mode 100644 tests/ui/imports/glob-resolve1.stderr create mode 100644 tests/ui/imports/glob-shadowing.rs create mode 100644 tests/ui/imports/glob-shadowing.stderr create mode 100644 tests/ui/imports/glob-use-std.rs create mode 100644 tests/ui/imports/import-crate-var.rs create mode 100644 tests/ui/imports/import-crate-var.stderr create mode 100644 tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans.rs create mode 100644 tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans_macros.rs create mode 100644 tests/ui/imports/import-crate-with-invalid-spans/main.rs create mode 100644 tests/ui/imports/import-from-missing.rs create mode 100644 tests/ui/imports/import-from-missing.stderr create mode 100644 tests/ui/imports/import-from.rs create mode 100644 tests/ui/imports/import-glob-0-rpass.rs create mode 100644 tests/ui/imports/import-glob-0.rs create mode 100644 tests/ui/imports/import-glob-0.stderr create mode 100644 tests/ui/imports/import-glob-1.rs create mode 100644 tests/ui/imports/import-glob-circular.rs create mode 100644 tests/ui/imports/import-glob-circular.stderr create mode 100644 tests/ui/imports/import-glob-crate.rs create mode 100644 tests/ui/imports/import-in-block.rs create mode 100644 tests/ui/imports/import-loop-2.rs create mode 100644 tests/ui/imports/import-loop-2.stderr create mode 100644 tests/ui/imports/import-loop.rs create mode 100644 tests/ui/imports/import-loop.stderr create mode 100644 tests/ui/imports/import-prefix-macro-1.rs create mode 100644 tests/ui/imports/import-prefix-macro-1.stderr create mode 100644 tests/ui/imports/import-prefix-macro-2.rs create mode 100644 tests/ui/imports/import-prefix-macro-2.stderr create mode 100644 tests/ui/imports/import-prefix-macro.rs create mode 100644 tests/ui/imports/import-rename.rs create mode 100644 tests/ui/imports/import-rpass.rs create mode 100644 tests/ui/imports/import-trailing-comma.rs create mode 100644 tests/ui/imports/import-trait-method.rs create mode 100644 tests/ui/imports/import-trait-method.stderr create mode 100644 tests/ui/imports/import.rs create mode 100644 tests/ui/imports/import.stderr create mode 100644 tests/ui/imports/import2-rpass.rs create mode 100644 tests/ui/imports/import2.rs create mode 100644 tests/ui/imports/import2.stderr create mode 100644 tests/ui/imports/import3-rpass.rs create mode 100644 tests/ui/imports/import3.rs create mode 100644 tests/ui/imports/import3.stderr create mode 100644 tests/ui/imports/import4-rpass.rs create mode 100644 tests/ui/imports/import4.rs create mode 100644 tests/ui/imports/import4.stderr create mode 100644 tests/ui/imports/import5.rs create mode 100644 tests/ui/imports/import6.rs create mode 100644 tests/ui/imports/import7.rs create mode 100644 tests/ui/imports/import8.rs create mode 100644 tests/ui/imports/imports.rs create mode 100644 tests/ui/imports/inaccessible_type_aliases.rs create mode 100644 tests/ui/imports/inaccessible_type_aliases.stderr create mode 100644 tests/ui/imports/issue-13404.rs create mode 100644 tests/ui/imports/issue-13404.stderr create mode 100644 tests/ui/imports/issue-1697.rs create mode 100644 tests/ui/imports/issue-1697.stderr create mode 100644 tests/ui/imports/issue-18083.rs create mode 100644 tests/ui/imports/issue-19498.rs create mode 100644 tests/ui/imports/issue-19498.stderr create mode 100644 tests/ui/imports/issue-24081.rs create mode 100644 tests/ui/imports/issue-24081.stderr create mode 100644 tests/ui/imports/issue-24883.rs create mode 100644 tests/ui/imports/issue-25396.rs create mode 100644 tests/ui/imports/issue-25396.stderr create mode 100644 tests/ui/imports/issue-26873-multifile/A/B.rs create mode 100644 tests/ui/imports/issue-26873-multifile/A/C.rs create mode 100644 tests/ui/imports/issue-26873-multifile/A/mod.rs create mode 100644 tests/ui/imports/issue-26873-multifile/compiletest-ignore-dir create mode 100644 tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs create mode 100644 tests/ui/imports/issue-26873-multifile/issue-26873-onefile.rs create mode 100644 tests/ui/imports/issue-26873-multifile/mod.rs create mode 100644 tests/ui/imports/issue-26886.rs create mode 100644 tests/ui/imports/issue-26886.stderr create mode 100644 tests/ui/imports/issue-26930.rs create mode 100644 tests/ui/imports/issue-28134.rs create mode 100644 tests/ui/imports/issue-28134.stderr create mode 100644 tests/ui/imports/issue-28388-1.rs create mode 100644 tests/ui/imports/issue-28388-1.stderr create mode 100644 tests/ui/imports/issue-28388-2.rs create mode 100644 tests/ui/imports/issue-28388-2.stderr create mode 100644 tests/ui/imports/issue-2937.rs create mode 100644 tests/ui/imports/issue-2937.stderr create mode 100644 tests/ui/imports/issue-30560.rs create mode 100644 tests/ui/imports/issue-30560.stderr create mode 100644 tests/ui/imports/issue-31212.rs create mode 100644 tests/ui/imports/issue-31212.stderr create mode 100644 tests/ui/imports/issue-32119.rs create mode 100644 tests/ui/imports/issue-32222.rs create mode 100644 tests/ui/imports/issue-32354-suggest-import-rename.fixed create mode 100644 tests/ui/imports/issue-32354-suggest-import-rename.rs create mode 100644 tests/ui/imports/issue-32354-suggest-import-rename.stderr create mode 100644 tests/ui/imports/issue-32833.rs create mode 100644 tests/ui/imports/issue-32833.stderr create mode 100644 tests/ui/imports/issue-33464.rs create mode 100644 tests/ui/imports/issue-33464.stderr create mode 100644 tests/ui/imports/issue-36881.rs create mode 100644 tests/ui/imports/issue-36881.stderr create mode 100644 tests/ui/imports/issue-37887.rs create mode 100644 tests/ui/imports/issue-37887.stderr create mode 100644 tests/ui/imports/issue-38293.rs create mode 100644 tests/ui/imports/issue-38293.stderr create mode 100644 tests/ui/imports/issue-4366-2.rs create mode 100644 tests/ui/imports/issue-4366-2.stderr create mode 100644 tests/ui/imports/issue-4366.rs create mode 100644 tests/ui/imports/issue-4366.stderr create mode 100644 tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed create mode 100644 tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs create mode 100644 tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr create mode 100644 tests/ui/imports/issue-45829/auxiliary/issue-45829-a.rs create mode 100644 tests/ui/imports/issue-45829/auxiliary/issue-45829-b.rs create mode 100644 tests/ui/imports/issue-45829/import-self.rs create mode 100644 tests/ui/imports/issue-45829/import-self.stderr create mode 100644 tests/ui/imports/issue-45829/import-twice.rs create mode 100644 tests/ui/imports/issue-45829/import-twice.stderr create mode 100644 tests/ui/imports/issue-45829/issue-45829.rs create mode 100644 tests/ui/imports/issue-45829/issue-45829.stderr create mode 100644 tests/ui/imports/issue-45829/rename-extern-vs-use.rs create mode 100644 tests/ui/imports/issue-45829/rename-extern-vs-use.stderr create mode 100644 tests/ui/imports/issue-45829/rename-extern-with-tab.rs create mode 100644 tests/ui/imports/issue-45829/rename-extern-with-tab.stderr create mode 100644 tests/ui/imports/issue-45829/rename-extern.rs create mode 100644 tests/ui/imports/issue-45829/rename-extern.stderr create mode 100644 tests/ui/imports/issue-45829/rename-use-vs-extern.rs create mode 100644 tests/ui/imports/issue-45829/rename-use-vs-extern.stderr create mode 100644 tests/ui/imports/issue-45829/rename-use-with-tabs.rs create mode 100644 tests/ui/imports/issue-45829/rename-use-with-tabs.stderr create mode 100644 tests/ui/imports/issue-45829/rename-with-path.rs create mode 100644 tests/ui/imports/issue-45829/rename-with-path.stderr create mode 100644 tests/ui/imports/issue-45829/rename.rs create mode 100644 tests/ui/imports/issue-45829/rename.stderr create mode 100644 tests/ui/imports/issue-47623.rs create mode 100644 tests/ui/imports/issue-47623.stderr create mode 100644 tests/ui/imports/issue-4865-1.rs create mode 100644 tests/ui/imports/issue-4865-2.rs create mode 100644 tests/ui/imports/issue-4865-3.rs create mode 100644 tests/ui/imports/issue-52891.fixed create mode 100644 tests/ui/imports/issue-52891.rs create mode 100644 tests/ui/imports/issue-52891.stderr create mode 100644 tests/ui/imports/issue-53140.rs create mode 100644 tests/ui/imports/issue-53269.rs create mode 100644 tests/ui/imports/issue-53269.stderr create mode 100644 tests/ui/imports/issue-53512.rs create mode 100644 tests/ui/imports/issue-53512.stderr create mode 100644 tests/ui/imports/issue-53565.rs create mode 100644 tests/ui/imports/issue-53565.stderr create mode 100644 tests/ui/imports/issue-55457.rs create mode 100644 tests/ui/imports/issue-55457.stderr create mode 100644 tests/ui/imports/issue-55811.rs create mode 100644 tests/ui/imports/issue-55884-1.rs create mode 100644 tests/ui/imports/issue-55884-1.stderr create mode 100644 tests/ui/imports/issue-55884-2.rs create mode 100644 tests/ui/imports/issue-55884-2.stderr create mode 100644 tests/ui/imports/issue-56125.rs create mode 100644 tests/ui/imports/issue-56125.stderr create mode 100644 tests/ui/imports/issue-56263.rs create mode 100644 tests/ui/imports/issue-57015.rs create mode 100644 tests/ui/imports/issue-57015.stderr create mode 100644 tests/ui/imports/issue-57539.rs create mode 100644 tests/ui/imports/issue-57539.stderr create mode 100644 tests/ui/imports/issue-59764.rs create mode 100644 tests/ui/imports/issue-59764.stderr create mode 100644 tests/ui/imports/issue-62767.rs create mode 100644 tests/ui/imports/issue-68103.rs create mode 100644 tests/ui/imports/issue-8208.rs create mode 100644 tests/ui/imports/issue-8208.stderr create mode 100644 tests/ui/imports/issue-8640.rs create mode 100644 tests/ui/imports/issue-8640.stderr create mode 100644 tests/ui/imports/issue-99695-b.fixed create mode 100644 tests/ui/imports/issue-99695-b.rs create mode 100644 tests/ui/imports/issue-99695-b.stderr create mode 100644 tests/ui/imports/issue-99695.fixed create mode 100644 tests/ui/imports/issue-99695.rs create mode 100644 tests/ui/imports/issue-99695.stderr create mode 100644 tests/ui/imports/local-modularized-tricky-fail-1.rs create mode 100644 tests/ui/imports/local-modularized-tricky-fail-1.stderr create mode 100644 tests/ui/imports/local-modularized-tricky-fail-2.rs create mode 100644 tests/ui/imports/local-modularized-tricky-fail-2.stderr create mode 100644 tests/ui/imports/local-modularized-tricky-pass-1.rs create mode 100644 tests/ui/imports/local-modularized-tricky-pass-2.rs create mode 100644 tests/ui/imports/local-modularized.rs create mode 100644 tests/ui/imports/macro-paths.rs create mode 100644 tests/ui/imports/macro-paths.stderr create mode 100644 tests/ui/imports/macros.rs create mode 100644 tests/ui/imports/macros.stderr create mode 100644 tests/ui/imports/no-std-inject.rs create mode 100644 tests/ui/imports/no-std-inject.stderr create mode 100644 tests/ui/imports/overlapping_pub_trait.rs create mode 100644 tests/ui/imports/overlapping_pub_trait.stderr create mode 100644 tests/ui/imports/reexport-star.rs create mode 100644 tests/ui/imports/reexports.rs create mode 100644 tests/ui/imports/reexports.stderr create mode 100644 tests/ui/imports/resolve_self_super_hint.rs create mode 100644 tests/ui/imports/resolve_self_super_hint.stderr create mode 100644 tests/ui/imports/rfc-1560-warning-cycle.rs create mode 100644 tests/ui/imports/rfc-1560-warning-cycle.stderr create mode 100644 tests/ui/imports/shadow_builtin_macros.rs create mode 100644 tests/ui/imports/shadow_builtin_macros.stderr create mode 100644 tests/ui/imports/tool-mod-child.rs create mode 100644 tests/ui/imports/tool-mod-child.stderr create mode 100644 tests/ui/imports/unnamed_pub_trait.rs create mode 100644 tests/ui/imports/unnamed_pub_trait.stderr create mode 100644 tests/ui/imports/unresolved-imports-used.rs create mode 100644 tests/ui/imports/unresolved-imports-used.stderr create mode 100644 tests/ui/imports/unused-import-issue-87973.fixed create mode 100644 tests/ui/imports/unused-import-issue-87973.rs create mode 100644 tests/ui/imports/unused-import-issue-87973.stderr create mode 100644 tests/ui/imports/unused-imports-in-test-mode.rs create mode 100644 tests/ui/imports/unused-imports-in-test-mode.stderr create mode 100644 tests/ui/imports/unused-imports-in-test-module.rs create mode 100644 tests/ui/imports/unused-imports-in-test-module.stderr create mode 100644 tests/ui/imports/unused-macro-use.rs create mode 100644 tests/ui/imports/unused-macro-use.stderr create mode 100644 tests/ui/imports/unused.rs create mode 100644 tests/ui/imports/unused.stderr create mode 100644 tests/ui/imports/use-mod.rs create mode 100644 tests/ui/impossible_range.fixed create mode 100644 tests/ui/impossible_range.rs create mode 100644 tests/ui/impossible_range.stderr create mode 100644 tests/ui/inc-range-pat.rs create mode 100644 tests/ui/include-macros/auxiliary/same-file-in-two-crates-aux.rs create mode 100644 tests/ui/include-macros/data.bin create mode 100644 tests/ui/include-macros/file.txt create mode 100644 tests/ui/include-macros/mismatched-types.rs create mode 100644 tests/ui/include-macros/mismatched-types.stderr create mode 100644 tests/ui/include-macros/normalization.rs create mode 100644 tests/ui/include-macros/same-file-in-two-crates.rs create mode 100644 tests/ui/incoherent-inherent-impls/auxiliary/extern-crate.rs create mode 100644 tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.rs create mode 100644 tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr create mode 100644 tests/ui/incoherent-inherent-impls/no-attr-empty-impl.rs create mode 100644 tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr create mode 100644 tests/ui/index-bot.rs create mode 100644 tests/ui/index-bot.stderr create mode 100644 tests/ui/index-help.rs create mode 100644 tests/ui/index-help.stderr create mode 100644 tests/ui/index_message.rs create mode 100644 tests/ui/index_message.stderr create mode 100644 tests/ui/indexing-requires-a-uint.rs create mode 100644 tests/ui/indexing-requires-a-uint.stderr create mode 100644 tests/ui/infer-fn-tail-expr.rs create mode 100644 tests/ui/inference/ambiguous_type_parameter.rs create mode 100644 tests/ui/inference/ambiguous_type_parameter.stderr create mode 100644 tests/ui/inference/auxiliary/inference_unstable_iterator.rs create mode 100644 tests/ui/inference/auxiliary/inference_unstable_itertools.rs create mode 100644 tests/ui/inference/cannot-infer-async.rs create mode 100644 tests/ui/inference/cannot-infer-async.stderr create mode 100644 tests/ui/inference/cannot-infer-closure-circular.rs create mode 100644 tests/ui/inference/cannot-infer-closure-circular.stderr create mode 100644 tests/ui/inference/cannot-infer-closure.rs create mode 100644 tests/ui/inference/cannot-infer-closure.stderr create mode 100644 tests/ui/inference/cannot-infer-partial-try-return.rs create mode 100644 tests/ui/inference/cannot-infer-partial-try-return.stderr create mode 100644 tests/ui/inference/char-as-str-multi.rs create mode 100644 tests/ui/inference/char-as-str-multi.stderr create mode 100644 tests/ui/inference/char-as-str-single.fixed create mode 100644 tests/ui/inference/char-as-str-single.rs create mode 100644 tests/ui/inference/char-as-str-single.stderr create mode 100644 tests/ui/inference/deref-suggestion.rs create mode 100644 tests/ui/inference/deref-suggestion.stderr create mode 100644 tests/ui/inference/erase-type-params-in-label.rs create mode 100644 tests/ui/inference/erase-type-params-in-label.stderr create mode 100644 tests/ui/inference/infer-binary-operand-behind-reference.rs create mode 100644 tests/ui/inference/inference-variable-behind-raw-pointer.rs create mode 100644 tests/ui/inference/inference-variable-behind-raw-pointer.stderr create mode 100644 tests/ui/inference/inference_unstable.rs create mode 100644 tests/ui/inference/inference_unstable.stderr create mode 100644 tests/ui/inference/inference_unstable_featured.rs create mode 100644 tests/ui/inference/inference_unstable_featured.stderr create mode 100644 tests/ui/inference/inference_unstable_forced.rs create mode 100644 tests/ui/inference/inference_unstable_forced.stderr create mode 100644 tests/ui/inference/issue-103587.rs create mode 100644 tests/ui/inference/issue-103587.stderr create mode 100644 tests/ui/inference/issue-104649.rs create mode 100644 tests/ui/inference/issue-104649.stderr create mode 100644 tests/ui/inference/issue-28935.rs create mode 100644 tests/ui/inference/issue-36053.rs create mode 100644 tests/ui/inference/issue-70703.rs create mode 100644 tests/ui/inference/issue-71309.rs create mode 100644 tests/ui/inference/issue-71309.stderr create mode 100644 tests/ui/inference/issue-71732.rs create mode 100644 tests/ui/inference/issue-71732.stderr create mode 100644 tests/ui/inference/issue-72616.rs create mode 100644 tests/ui/inference/issue-72616.stderr create mode 100644 tests/ui/inference/issue-72690.rs create mode 100644 tests/ui/inference/issue-72690.stderr create mode 100644 tests/ui/inference/issue-80816.rs create mode 100644 tests/ui/inference/issue-80816.stderr create mode 100644 tests/ui/inference/issue-81522.rs create mode 100644 tests/ui/inference/issue-83606.rs create mode 100644 tests/ui/inference/issue-83606.stderr create mode 100644 tests/ui/inference/issue-86162-1.rs create mode 100644 tests/ui/inference/issue-86162-1.stderr create mode 100644 tests/ui/inference/issue-86162-2.rs create mode 100644 tests/ui/inference/issue-86162-2.stderr create mode 100644 tests/ui/inference/lub-glb-with-unbound-infer-var.rs create mode 100644 tests/ui/inference/need_type_info/channel.rs create mode 100644 tests/ui/inference/need_type_info/channel.stderr create mode 100644 tests/ui/inference/need_type_info/concrete-impl.rs create mode 100644 tests/ui/inference/need_type_info/concrete-impl.stderr create mode 100644 tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs create mode 100644 tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr create mode 100644 tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs create mode 100644 tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr create mode 100644 tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs create mode 100644 tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr create mode 100644 tests/ui/inference/need_type_info/expr-struct-type-relative.rs create mode 100644 tests/ui/inference/need_type_info/expr-struct-type-relative.stderr create mode 100644 tests/ui/inference/need_type_info/issue-103053.rs create mode 100644 tests/ui/inference/need_type_info/issue-103053.stderr create mode 100644 tests/ui/inference/need_type_info/self-ty-in-path.rs create mode 100644 tests/ui/inference/need_type_info/self-ty-in-path.stderr create mode 100644 tests/ui/inference/need_type_info/type-alias-indirect.rs create mode 100644 tests/ui/inference/need_type_info/type-alias-indirect.stderr create mode 100644 tests/ui/inference/need_type_info/type-alias.rs create mode 100644 tests/ui/inference/need_type_info/type-alias.stderr create mode 100644 tests/ui/inference/newlambdas-ret-infer.rs create mode 100644 tests/ui/inference/newlambdas-ret-infer2.rs create mode 100644 tests/ui/inference/question-mark-type-infer.rs create mode 100644 tests/ui/inference/question-mark-type-infer.stderr create mode 100644 tests/ui/inference/range-type-infer.rs create mode 100644 tests/ui/inference/simple-infer.rs create mode 100644 tests/ui/inference/str-as-char.fixed create mode 100644 tests/ui/inference/str-as-char.rs create mode 100644 tests/ui/inference/str-as-char.stderr create mode 100644 tests/ui/inference/tutorial-suffix-inference-test.rs create mode 100644 tests/ui/inference/tutorial-suffix-inference-test.stderr create mode 100644 tests/ui/inference/type-infer-generalize-ty-var.rs create mode 100644 tests/ui/infinite/infinite-autoderef.rs create mode 100644 tests/ui/infinite/infinite-autoderef.stderr create mode 100644 tests/ui/infinite/infinite-instantiation.polonius.stderr create mode 100644 tests/ui/infinite/infinite-instantiation.rs create mode 100644 tests/ui/infinite/infinite-instantiation.stderr create mode 100644 tests/ui/infinite/infinite-macro-expansion.rs create mode 100644 tests/ui/infinite/infinite-macro-expansion.stderr create mode 100644 tests/ui/infinite/infinite-recursion-const-fn.rs create mode 100644 tests/ui/infinite/infinite-recursion-const-fn.stderr create mode 100644 tests/ui/infinite/infinite-struct.rs create mode 100644 tests/ui/infinite/infinite-struct.stderr create mode 100644 tests/ui/infinite/infinite-tag-type-recursion.rs create mode 100644 tests/ui/infinite/infinite-tag-type-recursion.stderr create mode 100644 tests/ui/infinite/infinite-trait-alias-recursion.rs create mode 100644 tests/ui/infinite/infinite-trait-alias-recursion.stderr create mode 100644 tests/ui/infinite/infinite-type-alias-mutual-recursion.rs create mode 100644 tests/ui/infinite/infinite-type-alias-mutual-recursion.stderr create mode 100644 tests/ui/infinite/infinite-vec-type-recursion.rs create mode 100644 tests/ui/infinite/infinite-vec-type-recursion.stderr create mode 100644 tests/ui/infinite/issue-41731-infinite-macro-print.rs create mode 100644 tests/ui/infinite/issue-41731-infinite-macro-print.stderr create mode 100644 tests/ui/infinite/issue-41731-infinite-macro-println.rs create mode 100644 tests/ui/infinite/issue-41731-infinite-macro-println.stderr create mode 100644 tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs create mode 100644 tests/ui/inherent-impls-overlap-check/no-overlap.rs create mode 100644 tests/ui/inherent-impls-overlap-check/overlap.rs create mode 100644 tests/ui/inherent-impls-overlap-check/overlap.stderr create mode 100644 tests/ui/inherit-env.rs create mode 100644 tests/ui/inline-const/const-expr-array-init.rs create mode 100644 tests/ui/inline-const/const-expr-basic.rs create mode 100644 tests/ui/inline-const/const-expr-generic-err.rs create mode 100644 tests/ui/inline-const/const-expr-generic-err.stderr create mode 100644 tests/ui/inline-const/const-expr-generic-err2.rs create mode 100644 tests/ui/inline-const/const-expr-generic-err2.stderr create mode 100644 tests/ui/inline-const/const-expr-generic.rs create mode 100644 tests/ui/inline-const/const-expr-inference.rs create mode 100644 tests/ui/inline-const/const-expr-lifetime-err.rs create mode 100644 tests/ui/inline-const/const-expr-lifetime-err.stderr create mode 100644 tests/ui/inline-const/const-expr-lifetime.rs create mode 100644 tests/ui/inline-const/const-expr-macro.rs create mode 100644 tests/ui/inline-const/const-expr-reference.rs create mode 100644 tests/ui/inline-const/const-match-pat-generic.rs create mode 100644 tests/ui/inline-const/const-match-pat-generic.stderr create mode 100644 tests/ui/inline-const/const-match-pat-inference.rs create mode 100644 tests/ui/inline-const/const-match-pat-lifetime-err.rs create mode 100644 tests/ui/inline-const/const-match-pat-lifetime.rs create mode 100644 tests/ui/inline-const/const-match-pat-range.rs create mode 100644 tests/ui/inline-const/const-match-pat.rs create mode 100644 tests/ui/inline-const/expr-unsafe-err.mir.stderr create mode 100644 tests/ui/inline-const/expr-unsafe-err.rs create mode 100644 tests/ui/inline-const/expr-unsafe-err.thir.stderr create mode 100644 tests/ui/inline-const/expr-unsafe.mir.stderr create mode 100644 tests/ui/inline-const/expr-unsafe.rs create mode 100644 tests/ui/inline-const/expr-unsafe.thir.stderr create mode 100644 tests/ui/inline-const/expr-with-block-err.rs create mode 100644 tests/ui/inline-const/expr-with-block-err.stderr create mode 100644 tests/ui/inline-const/expr-with-block.rs create mode 100644 tests/ui/inline-const/macro-with-const.rs create mode 100644 tests/ui/inline-const/pat-unsafe-err.rs create mode 100644 tests/ui/inline-const/pat-unsafe.rs create mode 100644 tests/ui/inline-disallow-on-variant.rs create mode 100644 tests/ui/inline-disallow-on-variant.stderr create mode 100644 tests/ui/inlined-main.rs create mode 100644 tests/ui/inner-attrs-on-impl.rs create mode 100644 tests/ui/inner-module.rs create mode 100644 tests/ui/inner-static-type-parameter.rs create mode 100644 tests/ui/inner-static-type-parameter.stderr create mode 100644 tests/ui/inner-static.rs create mode 100644 tests/ui/integral-indexing.rs create mode 100644 tests/ui/integral-indexing.stderr create mode 100644 tests/ui/integral-variable-unification-error.rs create mode 100644 tests/ui/integral-variable-unification-error.stderr create mode 100644 tests/ui/interior-mutability/interior-mutability.rs create mode 100644 tests/ui/interior-mutability/interior-mutability.stderr create mode 100644 tests/ui/internal/auxiliary/internal_unstable.rs create mode 100644 tests/ui/internal/internal-unstable-const.rs create mode 100644 tests/ui/internal/internal-unstable-const.stderr create mode 100644 tests/ui/internal/internal-unstable-noallow.rs create mode 100644 tests/ui/internal/internal-unstable-noallow.stderr create mode 100644 tests/ui/internal/internal-unstable-thread-local.rs create mode 100644 tests/ui/internal/internal-unstable-thread-local.stderr create mode 100644 tests/ui/internal/internal-unstable.rs create mode 100644 tests/ui/internal/internal-unstable.stderr create mode 100644 tests/ui/intrinsics-always-extern.rs create mode 100644 tests/ui/intrinsics-always-extern.stderr create mode 100644 tests/ui/intrinsics/auxiliary/cci_intrinsic.rs create mode 100644 tests/ui/intrinsics/bad-intrinsic-monomorphization.rs create mode 100644 tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr create mode 100644 tests/ui/intrinsics/const-eval-select-backtrace-std.rs create mode 100644 tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr create mode 100644 tests/ui/intrinsics/const-eval-select-backtrace.rs create mode 100644 tests/ui/intrinsics/const-eval-select-backtrace.run.stderr create mode 100644 tests/ui/intrinsics/const-eval-select-bad.rs create mode 100644 tests/ui/intrinsics/const-eval-select-bad.stderr create mode 100644 tests/ui/intrinsics/const-eval-select-stability.rs create mode 100644 tests/ui/intrinsics/const-eval-select-stability.stderr create mode 100644 tests/ui/intrinsics/const-eval-select-x86_64.rs create mode 100644 tests/ui/intrinsics/const-eval-select.rs create mode 100644 tests/ui/intrinsics/intrinsic-alignment.rs create mode 100644 tests/ui/intrinsics/intrinsic-assume.rs create mode 100644 tests/ui/intrinsics/intrinsic-atomics-cc.rs create mode 100644 tests/ui/intrinsics/intrinsic-atomics.rs create mode 100644 tests/ui/intrinsics/intrinsic-nearby.rs create mode 100644 tests/ui/intrinsics/intrinsic-raw_eq-const-padding.rs create mode 100644 tests/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr create mode 100644 tests/ui/intrinsics/intrinsic-raw_eq-const.rs create mode 100644 tests/ui/intrinsics/intrinsic-unreachable.rs create mode 100644 tests/ui/intrinsics/intrinsic-volatile.rs create mode 100644 tests/ui/intrinsics/intrinsics-integer.rs create mode 100644 tests/ui/intrinsics/intrinsics-math.rs create mode 100644 tests/ui/intrinsics/issue-28575.mir.stderr create mode 100644 tests/ui/intrinsics/issue-28575.rs create mode 100644 tests/ui/intrinsics/issue-28575.thir.stderr create mode 100644 tests/ui/intrinsics/issue-84297-reifying-copy.rs create mode 100644 tests/ui/intrinsics/non-integer-atomic.rs create mode 100644 tests/ui/intrinsics/non-integer-atomic.stderr create mode 100644 tests/ui/intrinsics/panic-uninitialized-zeroed.rs create mode 100644 tests/ui/intrinsics/safe-intrinsic-mismatch.rs create mode 100644 tests/ui/intrinsics/safe-intrinsic-mismatch.stderr create mode 100644 tests/ui/intrinsics/unchecked_math_unsafe.mir.stderr create mode 100644 tests/ui/intrinsics/unchecked_math_unsafe.rs create mode 100644 tests/ui/intrinsics/unchecked_math_unsafe.thir.stderr create mode 100644 tests/ui/intrinsics/unchecked_math_unstable.rs create mode 100644 tests/ui/intrinsics/unchecked_math_unstable.stderr create mode 100644 tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr create mode 100644 tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr create mode 100644 tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs create mode 100644 tests/ui/invalid-compile-flags/codegen-option-without-group.rs create mode 100644 tests/ui/invalid-compile-flags/codegen-option-without-group.stderr create mode 100644 tests/ui/invalid-compile-flags/debug-option-without-group.rs create mode 100644 tests/ui/invalid-compile-flags/debug-option-without-group.stderr create mode 100644 tests/ui/invalid-module-declaration/auxiliary/foo/bar.rs create mode 100644 tests/ui/invalid-module-declaration/auxiliary/foo/mod.rs create mode 100644 tests/ui/invalid-module-declaration/invalid-module-declaration.rs create mode 100644 tests/ui/invalid-module-declaration/invalid-module-declaration.stderr create mode 100644 tests/ui/invalid-self-argument/bare-fn-start.rs create mode 100644 tests/ui/invalid-self-argument/bare-fn-start.stderr create mode 100644 tests/ui/invalid-self-argument/bare-fn.rs create mode 100644 tests/ui/invalid-self-argument/bare-fn.stderr create mode 100644 tests/ui/invalid-self-argument/trait-fn.rs create mode 100644 tests/ui/invalid-self-argument/trait-fn.stderr create mode 100644 tests/ui/invalid/invalid-crate-type-macro.rs create mode 100644 tests/ui/invalid/invalid-crate-type-macro.stderr create mode 100644 tests/ui/invalid/invalid-crate-type.rs create mode 100644 tests/ui/invalid/invalid-crate-type.stderr create mode 100644 tests/ui/invalid/invalid-debugger-visualizer-option.rs create mode 100644 tests/ui/invalid/invalid-debugger-visualizer-option.stderr create mode 100644 tests/ui/invalid/invalid-debugger-visualizer-target.rs create mode 100644 tests/ui/invalid/invalid-debugger-visualizer-target.stderr create mode 100644 tests/ui/invalid/invalid-inline.rs create mode 100644 tests/ui/invalid/invalid-inline.stderr create mode 100644 tests/ui/invalid/invalid-llvm-passes.rs create mode 100644 tests/ui/invalid/invalid-llvm-passes.stderr create mode 100644 tests/ui/invalid/invalid-macro-matcher.rs create mode 100644 tests/ui/invalid/invalid-macro-matcher.stderr create mode 100644 tests/ui/invalid/invalid-no-sanitize.rs create mode 100644 tests/ui/invalid/invalid-no-sanitize.stderr create mode 100644 tests/ui/invalid/invalid-path-in-const.rs create mode 100644 tests/ui/invalid/invalid-path-in-const.stderr create mode 100644 tests/ui/invalid/invalid-plugin-attr.rs create mode 100644 tests/ui/invalid/invalid-plugin-attr.stderr create mode 100644 tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs create mode 100644 tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr create mode 100644 tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs create mode 100644 tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr create mode 100644 tests/ui/invalid_crate_type_syntax.rs create mode 100644 tests/ui/invalid_crate_type_syntax.stderr create mode 100644 tests/ui/invalid_dispatch_from_dyn_impls.rs create mode 100644 tests/ui/invalid_dispatch_from_dyn_impls.stderr create mode 100644 tests/ui/issue-76387-llvm-miscompile.rs create mode 100644 tests/ui/issue-94866.rs create mode 100644 tests/ui/issue-94866.stderr create mode 100644 tests/ui/issues-71798.rs create mode 100644 tests/ui/issues-71798.stderr create mode 100644 tests/ui/issues/auxiliary/cgu_test.rs create mode 100644 tests/ui/issues/auxiliary/cgu_test_a.rs create mode 100644 tests/ui/issues/auxiliary/cgu_test_b.rs create mode 100644 tests/ui/issues/auxiliary/i8.rs create mode 100644 tests/ui/issues/auxiliary/iss.rs create mode 100644 tests/ui/issues/auxiliary/issue-11224.rs create mode 100644 tests/ui/issues/auxiliary/issue-11508.rs create mode 100644 tests/ui/issues/auxiliary/issue-11529.rs create mode 100644 tests/ui/issues/auxiliary/issue-11680.rs create mode 100644 tests/ui/issues/auxiliary/issue-12133-dylib.rs create mode 100644 tests/ui/issues/auxiliary/issue-12133-dylib2.rs create mode 100644 tests/ui/issues/auxiliary/issue-12133-rlib.rs create mode 100644 tests/ui/issues/auxiliary/issue-12612-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-12612-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-12660-aux.rs create mode 100644 tests/ui/issues/auxiliary/issue-13507.rs create mode 100644 tests/ui/issues/auxiliary/issue-13620-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-13620-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-13872-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-13872-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-13872-3.rs create mode 100644 tests/ui/issues/auxiliary/issue-14344-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-14344-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-14421.rs create mode 100644 tests/ui/issues/auxiliary/issue-14422.rs create mode 100644 tests/ui/issues/auxiliary/issue-15562.rs create mode 100644 tests/ui/issues/auxiliary/issue-16643.rs create mode 100644 tests/ui/issues/auxiliary/issue-16725.rs create mode 100644 tests/ui/issues/auxiliary/issue-17662.rs create mode 100644 tests/ui/issues/auxiliary/issue-18501.rs create mode 100644 tests/ui/issues/auxiliary/issue-18514.rs create mode 100644 tests/ui/issues/auxiliary/issue-18711.rs create mode 100644 tests/ui/issues/auxiliary/issue-18913-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-18913-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-1920.rs create mode 100644 tests/ui/issues/auxiliary/issue-19293.rs create mode 100644 tests/ui/issues/auxiliary/issue-19340-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-20389.rs create mode 100644 tests/ui/issues/auxiliary/issue-21202.rs create mode 100644 tests/ui/issues/auxiliary/issue-2170-lib.rs create mode 100644 tests/ui/issues/auxiliary/issue-2316-a.rs create mode 100644 tests/ui/issues/auxiliary/issue-2316-b.rs create mode 100644 tests/ui/issues/auxiliary/issue-2380.rs create mode 100644 tests/ui/issues/auxiliary/issue-2414-a.rs create mode 100644 tests/ui/issues/auxiliary/issue-2414-b.rs create mode 100644 tests/ui/issues/auxiliary/issue-2472-b.rs create mode 100644 tests/ui/issues/auxiliary/issue-25185-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-25185-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-2526.rs create mode 100644 tests/ui/issues/auxiliary/issue-25467.rs create mode 100644 tests/ui/issues/auxiliary/issue-2631-a.rs create mode 100644 tests/ui/issues/auxiliary/issue-2723-a.rs create mode 100644 tests/ui/issues/auxiliary/issue-29181.rs create mode 100644 tests/ui/issues/auxiliary/issue-29265.rs create mode 100644 tests/ui/issues/auxiliary/issue-29485.rs create mode 100644 tests/ui/issues/auxiliary/issue-3012-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-30123-aux.rs create mode 100644 tests/ui/issues/auxiliary/issue-3136-a.rc create mode 100644 tests/ui/issues/auxiliary/issue-3136-a.rs create mode 100644 tests/ui/issues/auxiliary/issue-31702-1.rs create mode 100644 tests/ui/issues/auxiliary/issue-31702-2.rs create mode 100644 tests/ui/issues/auxiliary/issue-34796-aux.rs create mode 100644 tests/ui/issues/auxiliary/issue-36954.rs create mode 100644 tests/ui/issues/auxiliary/issue-38190.rs create mode 100644 tests/ui/issues/auxiliary/issue-38226-aux.rs create mode 100644 tests/ui/issues/auxiliary/issue-3979-traits.rs create mode 100644 tests/ui/issues/auxiliary/issue-41053.rs create mode 100644 tests/ui/issues/auxiliary/issue-41394.rs create mode 100644 tests/ui/issues/auxiliary/issue-41549.rs create mode 100644 tests/ui/issues/auxiliary/issue-42007-s.rs create mode 100644 tests/ui/issues/auxiliary/issue-4208-cc.rs create mode 100644 tests/ui/issues/auxiliary/issue-4545.rs create mode 100644 tests/ui/issues/auxiliary/issue-48984-aux.rs create mode 100644 tests/ui/issues/auxiliary/issue-49544.rs create mode 100644 tests/ui/issues/auxiliary/issue-51798.rs create mode 100644 tests/ui/issues/auxiliary/issue-52489.rs create mode 100644 tests/ui/issues/auxiliary/issue-5518.rs create mode 100644 tests/ui/issues/auxiliary/issue-5521.rs create mode 100644 tests/ui/issues/auxiliary/issue-56943.rs create mode 100644 tests/ui/issues/auxiliary/issue-57271-lib.rs create mode 100644 tests/ui/issues/auxiliary/issue-5844-aux.rs create mode 100644 tests/ui/issues/auxiliary/issue-7178.rs create mode 100644 tests/ui/issues/auxiliary/issue-73112.rs create mode 100644 tests/ui/issues/auxiliary/issue-7899.rs create mode 100644 tests/ui/issues/auxiliary/issue-8044.rs create mode 100644 tests/ui/issues/auxiliary/issue-8259.rs create mode 100644 tests/ui/issues/auxiliary/issue-8401.rs create mode 100644 tests/ui/issues/auxiliary/issue-9123.rs create mode 100644 tests/ui/issues/auxiliary/issue-9155.rs create mode 100644 tests/ui/issues/auxiliary/issue-9188.rs create mode 100644 tests/ui/issues/auxiliary/issue-9906.rs create mode 100644 tests/ui/issues/auxiliary/issue-9968.rs create mode 100644 tests/ui/issues/auxiliary/private-trait-xc.rs create mode 100644 tests/ui/issues/auxiliary/reexported-trait.rs create mode 100644 tests/ui/issues/issue-100605.rs create mode 100644 tests/ui/issues/issue-100605.stderr create mode 100644 tests/ui/issues/issue-10228.rs create mode 100644 tests/ui/issues/issue-10291.rs create mode 100644 tests/ui/issues/issue-10291.stderr create mode 100644 tests/ui/issues/issue-102964.rs create mode 100644 tests/ui/issues/issue-102964.stderr create mode 100644 tests/ui/issues/issue-10396.rs create mode 100644 tests/ui/issues/issue-10412.rs create mode 100644 tests/ui/issues/issue-10412.stderr create mode 100644 tests/ui/issues/issue-10436.rs create mode 100644 tests/ui/issues/issue-10456.rs create mode 100644 tests/ui/issues/issue-10465.rs create mode 100644 tests/ui/issues/issue-10465.stderr create mode 100644 tests/ui/issues/issue-10545.rs create mode 100644 tests/ui/issues/issue-10545.stderr create mode 100644 tests/ui/issues/issue-10638.rs create mode 100644 tests/ui/issues/issue-10656.rs create mode 100644 tests/ui/issues/issue-10656.stderr create mode 100644 tests/ui/issues/issue-10682.rs create mode 100644 tests/ui/issues/issue-10683.rs create mode 100644 tests/ui/issues/issue-10718.rs create mode 100644 tests/ui/issues/issue-10734.rs create mode 100644 tests/ui/issues/issue-10764.rs create mode 100644 tests/ui/issues/issue-10764.stderr create mode 100644 tests/ui/issues/issue-10767.rs create mode 100644 tests/ui/issues/issue-10802.rs create mode 100644 tests/ui/issues/issue-10806.rs create mode 100644 tests/ui/issues/issue-10853.rs create mode 100644 tests/ui/issues/issue-10877.rs create mode 100644 tests/ui/issues/issue-10877.stderr create mode 100644 tests/ui/issues/issue-10902.rs create mode 100644 tests/ui/issues/issue-11004.rs create mode 100644 tests/ui/issues/issue-11004.stderr create mode 100644 tests/ui/issues/issue-11047.rs create mode 100644 tests/ui/issues/issue-11085.rs create mode 100644 tests/ui/issues/issue-11192.rs create mode 100644 tests/ui/issues/issue-11192.stderr create mode 100644 tests/ui/issues/issue-11205.rs create mode 100644 tests/ui/issues/issue-11224.rs create mode 100644 tests/ui/issues/issue-11267.rs create mode 100644 tests/ui/issues/issue-11374.rs create mode 100644 tests/ui/issues/issue-11374.stderr create mode 100644 tests/ui/issues/issue-11382.rs create mode 100644 tests/ui/issues/issue-11384.rs create mode 100644 tests/ui/issues/issue-11508.rs create mode 100644 tests/ui/issues/issue-11515.rs create mode 100644 tests/ui/issues/issue-11515.stderr create mode 100644 tests/ui/issues/issue-11529.rs create mode 100644 tests/ui/issues/issue-11552.rs create mode 100644 tests/ui/issues/issue-11592.rs create mode 100644 tests/ui/issues/issue-11593.rs create mode 100644 tests/ui/issues/issue-11593.stderr create mode 100644 tests/ui/issues/issue-11677.rs create mode 100644 tests/ui/issues/issue-11680.rs create mode 100644 tests/ui/issues/issue-11680.stderr create mode 100644 tests/ui/issues/issue-11681.rs create mode 100644 tests/ui/issues/issue-11681.stderr create mode 100644 tests/ui/issues/issue-11692-1.rs create mode 100644 tests/ui/issues/issue-11692-1.stderr create mode 100644 tests/ui/issues/issue-11692-2.rs create mode 100644 tests/ui/issues/issue-11692-2.stderr create mode 100644 tests/ui/issues/issue-11709.rs create mode 100644 tests/ui/issues/issue-11740.rs create mode 100644 tests/ui/issues/issue-11771.rs create mode 100644 tests/ui/issues/issue-11771.stderr create mode 100644 tests/ui/issues/issue-11820.rs create mode 100644 tests/ui/issues/issue-11844.rs create mode 100644 tests/ui/issues/issue-11844.stderr create mode 100644 tests/ui/issues/issue-11869.rs create mode 100644 tests/ui/issues/issue-11873.rs create mode 100644 tests/ui/issues/issue-11873.stderr create mode 100644 tests/ui/issues/issue-11958.rs create mode 100644 tests/ui/issues/issue-11958.stderr create mode 100644 tests/ui/issues/issue-12028.rs create mode 100644 tests/ui/issues/issue-12028.stderr create mode 100644 tests/ui/issues/issue-12033.rs create mode 100644 tests/ui/issues/issue-12041.rs create mode 100644 tests/ui/issues/issue-12041.stderr create mode 100644 tests/ui/issues/issue-12127.rs create mode 100644 tests/ui/issues/issue-12127.stderr create mode 100644 tests/ui/issues/issue-12133-1.rs create mode 100644 tests/ui/issues/issue-12133-2.rs create mode 100644 tests/ui/issues/issue-12133-3.rs create mode 100644 tests/ui/issues/issue-12187-1.rs create mode 100644 tests/ui/issues/issue-12187-1.stderr create mode 100644 tests/ui/issues/issue-12187-2.rs create mode 100644 tests/ui/issues/issue-12187-2.stderr create mode 100644 tests/ui/issues/issue-12285.rs create mode 100644 tests/ui/issues/issue-1251.rs create mode 100644 tests/ui/issues/issue-12511.rs create mode 100644 tests/ui/issues/issue-12511.stderr create mode 100644 tests/ui/issues/issue-12567.rs create mode 100644 tests/ui/issues/issue-12567.stderr create mode 100644 tests/ui/issues/issue-1257.rs create mode 100644 tests/ui/issues/issue-12612.rs create mode 100644 tests/ui/issues/issue-12660.rs create mode 100644 tests/ui/issues/issue-12677.rs create mode 100644 tests/ui/issues/issue-12699.rs create mode 100644 tests/ui/issues/issue-12729.rs create mode 100644 tests/ui/issues/issue-12744.rs create mode 100644 tests/ui/issues/issue-12860.rs create mode 100644 tests/ui/issues/issue-12863.rs create mode 100644 tests/ui/issues/issue-12863.stderr create mode 100644 tests/ui/issues/issue-12909.rs create mode 100644 tests/ui/issues/issue-12920.rs create mode 100644 tests/ui/issues/issue-12997-1.rs create mode 100644 tests/ui/issues/issue-12997-1.stderr create mode 100644 tests/ui/issues/issue-12997-2.rs create mode 100644 tests/ui/issues/issue-12997-2.stderr create mode 100644 tests/ui/issues/issue-13027.rs create mode 100644 tests/ui/issues/issue-13033.rs create mode 100644 tests/ui/issues/issue-13033.stderr create mode 100644 tests/ui/issues/issue-13058.rs create mode 100644 tests/ui/issues/issue-13058.stderr create mode 100644 tests/ui/issues/issue-13105.rs create mode 100644 tests/ui/issues/issue-13167.rs create mode 100644 tests/ui/issues/issue-13202.rs create mode 100644 tests/ui/issues/issue-13204.rs create mode 100644 tests/ui/issues/issue-13214.rs create mode 100644 tests/ui/issues/issue-13259-windows-tcb-trash.rs create mode 100644 tests/ui/issues/issue-13264.rs create mode 100644 tests/ui/issues/issue-13323.rs create mode 100644 tests/ui/issues/issue-13359.rs create mode 100644 tests/ui/issues/issue-13359.stderr create mode 100644 tests/ui/issues/issue-13405.rs create mode 100644 tests/ui/issues/issue-13407.rs create mode 100644 tests/ui/issues/issue-13407.stderr create mode 100644 tests/ui/issues/issue-13434.rs create mode 100644 tests/ui/issues/issue-13446.rs create mode 100644 tests/ui/issues/issue-13446.stderr create mode 100644 tests/ui/issues/issue-13466.rs create mode 100644 tests/ui/issues/issue-13466.stderr create mode 100644 tests/ui/issues/issue-13482-2.rs create mode 100644 tests/ui/issues/issue-13482-2.stderr create mode 100644 tests/ui/issues/issue-13482.rs create mode 100644 tests/ui/issues/issue-13482.stderr create mode 100644 tests/ui/issues/issue-13497-2.rs create mode 100644 tests/ui/issues/issue-13497-2.stderr create mode 100644 tests/ui/issues/issue-13497.rs create mode 100644 tests/ui/issues/issue-13497.stderr create mode 100644 tests/ui/issues/issue-13507-2.rs create mode 100644 tests/ui/issues/issue-1362.rs create mode 100644 tests/ui/issues/issue-1362.stderr create mode 100644 tests/ui/issues/issue-13620.rs create mode 100644 tests/ui/issues/issue-13665.rs create mode 100644 tests/ui/issues/issue-13703.rs create mode 100644 tests/ui/issues/issue-13763.rs create mode 100644 tests/ui/issues/issue-13775.rs create mode 100644 tests/ui/issues/issue-13808.rs create mode 100644 tests/ui/issues/issue-13847.rs create mode 100644 tests/ui/issues/issue-13847.stderr create mode 100644 tests/ui/issues/issue-13867.rs create mode 100644 tests/ui/issues/issue-13872.rs create mode 100644 tests/ui/issues/issue-14082.rs create mode 100644 tests/ui/issues/issue-14091-2.rs create mode 100644 tests/ui/issues/issue-14091-2.stderr create mode 100644 tests/ui/issues/issue-14091.rs create mode 100644 tests/ui/issues/issue-14091.stderr create mode 100644 tests/ui/issues/issue-14092.rs create mode 100644 tests/ui/issues/issue-14092.stderr create mode 100644 tests/ui/issues/issue-14229.rs create mode 100644 tests/ui/issues/issue-14254.rs create mode 100644 tests/ui/issues/issue-14285.rs create mode 100644 tests/ui/issues/issue-14285.stderr create mode 100644 tests/ui/issues/issue-14308.rs create mode 100644 tests/ui/issues/issue-14330.rs create mode 100644 tests/ui/issues/issue-14344.rs create mode 100644 tests/ui/issues/issue-14366.rs create mode 100644 tests/ui/issues/issue-14366.stderr create mode 100644 tests/ui/issues/issue-14382.rs create mode 100644 tests/ui/issues/issue-14393.rs create mode 100644 tests/ui/issues/issue-14399.rs create mode 100644 tests/ui/issues/issue-14421.rs create mode 100644 tests/ui/issues/issue-14422.rs create mode 100644 tests/ui/issues/issue-1448-2.rs create mode 100644 tests/ui/issues/issue-1448-2.stderr create mode 100644 tests/ui/issues/issue-1451.rs create mode 100644 tests/ui/issues/issue-14541.rs create mode 100644 tests/ui/issues/issue-14541.stderr create mode 100644 tests/ui/issues/issue-1460.rs create mode 100644 tests/ui/issues/issue-1460.stderr create mode 100644 tests/ui/issues/issue-14721.rs create mode 100644 tests/ui/issues/issue-14721.stderr create mode 100644 tests/ui/issues/issue-1476.rs create mode 100644 tests/ui/issues/issue-1476.stderr create mode 100644 tests/ui/issues/issue-14821.rs create mode 100644 tests/ui/issues/issue-14845.rs create mode 100644 tests/ui/issues/issue-14845.stderr create mode 100644 tests/ui/issues/issue-14853.rs create mode 100644 tests/ui/issues/issue-14853.stderr create mode 100644 tests/ui/issues/issue-14865.rs create mode 100644 tests/ui/issues/issue-14875.rs create mode 100644 tests/ui/issues/issue-14901.rs create mode 100644 tests/ui/issues/issue-14915.rs create mode 100644 tests/ui/issues/issue-14915.stderr create mode 100644 tests/ui/issues/issue-14919.rs create mode 100644 tests/ui/issues/issue-14959.rs create mode 100644 tests/ui/issues/issue-15034.rs create mode 100644 tests/ui/issues/issue-15034.stderr create mode 100644 tests/ui/issues/issue-15043.rs create mode 100644 tests/ui/issues/issue-15063.rs create mode 100644 tests/ui/issues/issue-15094.rs create mode 100644 tests/ui/issues/issue-15094.stderr create mode 100644 tests/ui/issues/issue-15104.rs create mode 100644 tests/ui/issues/issue-15129-rpass.rs create mode 100644 tests/ui/issues/issue-15155.rs create mode 100644 tests/ui/issues/issue-15167.rs create mode 100644 tests/ui/issues/issue-15167.stderr create mode 100644 tests/ui/issues/issue-15189.rs create mode 100644 tests/ui/issues/issue-15207.rs create mode 100644 tests/ui/issues/issue-15207.stderr create mode 100644 tests/ui/issues/issue-15260.rs create mode 100644 tests/ui/issues/issue-15260.stderr create mode 100644 tests/ui/issues/issue-15381.rs create mode 100644 tests/ui/issues/issue-15381.stderr create mode 100644 tests/ui/issues/issue-15444.rs create mode 100644 tests/ui/issues/issue-15523-big.rs create mode 100644 tests/ui/issues/issue-15523.rs create mode 100644 tests/ui/issues/issue-15562.rs create mode 100644 tests/ui/issues/issue-15571.rs create mode 100644 tests/ui/issues/issue-15673.rs create mode 100644 tests/ui/issues/issue-15689-1.rs create mode 100644 tests/ui/issues/issue-15689-2.rs create mode 100644 tests/ui/issues/issue-15734.rs create mode 100644 tests/ui/issues/issue-15735.rs create mode 100644 tests/ui/issues/issue-15756.rs create mode 100644 tests/ui/issues/issue-15756.stderr create mode 100644 tests/ui/issues/issue-15763.rs create mode 100644 tests/ui/issues/issue-15774.rs create mode 100644 tests/ui/issues/issue-15783.rs create mode 100644 tests/ui/issues/issue-15783.stderr create mode 100644 tests/ui/issues/issue-15793.rs create mode 100644 tests/ui/issues/issue-15858.rs create mode 100644 tests/ui/issues/issue-15896.rs create mode 100644 tests/ui/issues/issue-15896.stderr create mode 100644 tests/ui/issues/issue-15965.rs create mode 100644 tests/ui/issues/issue-15965.stderr create mode 100644 tests/ui/issues/issue-16048.rs create mode 100644 tests/ui/issues/issue-16048.stderr create mode 100644 tests/ui/issues/issue-16149.rs create mode 100644 tests/ui/issues/issue-16149.stderr create mode 100644 tests/ui/issues/issue-16151.rs create mode 100644 tests/ui/issues/issue-16250.rs create mode 100644 tests/ui/issues/issue-16250.stderr create mode 100644 tests/ui/issues/issue-16256.rs create mode 100644 tests/ui/issues/issue-16256.stderr create mode 100644 tests/ui/issues/issue-16278.rs create mode 100644 tests/ui/issues/issue-16338.rs create mode 100644 tests/ui/issues/issue-16338.stderr create mode 100644 tests/ui/issues/issue-16401.rs create mode 100644 tests/ui/issues/issue-16401.stderr create mode 100644 tests/ui/issues/issue-16441.rs create mode 100644 tests/ui/issues/issue-16452.rs create mode 100644 tests/ui/issues/issue-16492.rs create mode 100644 tests/ui/issues/issue-16530.rs create mode 100644 tests/ui/issues/issue-16538.mir.stderr create mode 100644 tests/ui/issues/issue-16538.rs create mode 100644 tests/ui/issues/issue-16538.thir.stderr create mode 100644 tests/ui/issues/issue-16560.rs create mode 100644 tests/ui/issues/issue-16562.rs create mode 100644 tests/ui/issues/issue-16562.stderr create mode 100644 tests/ui/issues/issue-16596.rs create mode 100644 tests/ui/issues/issue-1660.rs create mode 100644 tests/ui/issues/issue-16643.rs create mode 100644 tests/ui/issues/issue-16648.rs create mode 100644 tests/ui/issues/issue-16668.rs create mode 100644 tests/ui/issues/issue-16671.rs create mode 100644 tests/ui/issues/issue-16683.rs create mode 100644 tests/ui/issues/issue-16683.stderr create mode 100644 tests/ui/issues/issue-16725.rs create mode 100644 tests/ui/issues/issue-16725.stderr create mode 100644 tests/ui/issues/issue-16739.rs create mode 100644 tests/ui/issues/issue-16745.rs create mode 100644 tests/ui/issues/issue-16774.rs create mode 100644 tests/ui/issues/issue-16783.rs create mode 100644 tests/ui/issues/issue-16819.rs create mode 100644 tests/ui/issues/issue-16922-rpass.rs create mode 100644 tests/ui/issues/issue-16922.rs create mode 100644 tests/ui/issues/issue-16922.stderr create mode 100644 tests/ui/issues/issue-16939.rs create mode 100644 tests/ui/issues/issue-16939.stderr create mode 100644 tests/ui/issues/issue-1696.rs create mode 100644 tests/ui/issues/issue-16966.rs create mode 100644 tests/ui/issues/issue-16966.stderr create mode 100644 tests/ui/issues/issue-16994.rs create mode 100644 tests/ui/issues/issue-17001.rs create mode 100644 tests/ui/issues/issue-17001.stderr create mode 100644 tests/ui/issues/issue-17033.rs create mode 100644 tests/ui/issues/issue-17033.stderr create mode 100644 tests/ui/issues/issue-17068.rs create mode 100644 tests/ui/issues/issue-17121.rs create mode 100644 tests/ui/issues/issue-17216.rs create mode 100644 tests/ui/issues/issue-17252.rs create mode 100644 tests/ui/issues/issue-17252.stderr create mode 100644 tests/ui/issues/issue-17302.rs create mode 100644 tests/ui/issues/issue-17322.rs create mode 100644 tests/ui/issues/issue-17336.rs create mode 100644 tests/ui/issues/issue-17337.rs create mode 100644 tests/ui/issues/issue-17337.stderr create mode 100644 tests/ui/issues/issue-17351.rs create mode 100644 tests/ui/issues/issue-17361.rs create mode 100644 tests/ui/issues/issue-17373.rs create mode 100644 tests/ui/issues/issue-17373.stderr create mode 100644 tests/ui/issues/issue-17385.rs create mode 100644 tests/ui/issues/issue-17385.stderr create mode 100644 tests/ui/issues/issue-17405.rs create mode 100644 tests/ui/issues/issue-17405.stderr create mode 100644 tests/ui/issues/issue-17431-1.rs create mode 100644 tests/ui/issues/issue-17431-1.stderr create mode 100644 tests/ui/issues/issue-17431-2.rs create mode 100644 tests/ui/issues/issue-17431-2.stderr create mode 100644 tests/ui/issues/issue-17431-3.rs create mode 100644 tests/ui/issues/issue-17431-3.stderr create mode 100644 tests/ui/issues/issue-17431-4.rs create mode 100644 tests/ui/issues/issue-17431-4.stderr create mode 100644 tests/ui/issues/issue-17431-5.rs create mode 100644 tests/ui/issues/issue-17431-5.stderr create mode 100644 tests/ui/issues/issue-17431-6.rs create mode 100644 tests/ui/issues/issue-17431-6.stderr create mode 100644 tests/ui/issues/issue-17431-7.rs create mode 100644 tests/ui/issues/issue-17431-7.stderr create mode 100644 tests/ui/issues/issue-17441.rs create mode 100644 tests/ui/issues/issue-17441.stderr create mode 100644 tests/ui/issues/issue-17450.rs create mode 100644 tests/ui/issues/issue-17503.rs create mode 100644 tests/ui/issues/issue-17546.rs create mode 100644 tests/ui/issues/issue-17546.stderr create mode 100644 tests/ui/issues/issue-17551.rs create mode 100644 tests/ui/issues/issue-17551.stderr create mode 100644 tests/ui/issues/issue-17651.rs create mode 100644 tests/ui/issues/issue-17651.stderr create mode 100644 tests/ui/issues/issue-17662.rs create mode 100644 tests/ui/issues/issue-17732.rs create mode 100644 tests/ui/issues/issue-17734.rs create mode 100644 tests/ui/issues/issue-17740.rs create mode 100644 tests/ui/issues/issue-17740.stderr create mode 100644 tests/ui/issues/issue-17746.rs create mode 100644 tests/ui/issues/issue-17758.rs create mode 100644 tests/ui/issues/issue-17758.stderr create mode 100644 tests/ui/issues/issue-17771.rs create mode 100644 tests/ui/issues/issue-17800.rs create mode 100644 tests/ui/issues/issue-17800.stderr create mode 100644 tests/ui/issues/issue-17816.rs create mode 100644 tests/ui/issues/issue-17877.rs create mode 100644 tests/ui/issues/issue-17897.rs create mode 100644 tests/ui/issues/issue-17904-2.rs create mode 100644 tests/ui/issues/issue-17904-2.stderr create mode 100644 tests/ui/issues/issue-17904.rs create mode 100644 tests/ui/issues/issue-17905-2.rs create mode 100644 tests/ui/issues/issue-17905-2.stderr create mode 100644 tests/ui/issues/issue-17905.rs create mode 100644 tests/ui/issues/issue-17933.rs create mode 100644 tests/ui/issues/issue-17933.stderr create mode 100644 tests/ui/issues/issue-17954.rs create mode 100644 tests/ui/issues/issue-17954.stderr create mode 100644 tests/ui/issues/issue-17959.rs create mode 100644 tests/ui/issues/issue-17959.stderr create mode 100644 tests/ui/issues/issue-17994.rs create mode 100644 tests/ui/issues/issue-17994.stderr create mode 100644 tests/ui/issues/issue-17999.rs create mode 100644 tests/ui/issues/issue-17999.stderr create mode 100644 tests/ui/issues/issue-18058.rs create mode 100644 tests/ui/issues/issue-18058.stderr create mode 100644 tests/ui/issues/issue-18088.rs create mode 100644 tests/ui/issues/issue-18107.rs create mode 100644 tests/ui/issues/issue-18107.stderr create mode 100644 tests/ui/issues/issue-18110.rs create mode 100644 tests/ui/issues/issue-18119.rs create mode 100644 tests/ui/issues/issue-18119.stderr create mode 100644 tests/ui/issues/issue-18159.rs create mode 100644 tests/ui/issues/issue-18159.stderr create mode 100644 tests/ui/issues/issue-18173.rs create mode 100644 tests/ui/issues/issue-18183.rs create mode 100644 tests/ui/issues/issue-18183.stderr create mode 100644 tests/ui/issues/issue-18188.rs create mode 100644 tests/ui/issues/issue-1821.rs create mode 100644 tests/ui/issues/issue-18232.rs create mode 100644 tests/ui/issues/issue-18352.rs create mode 100644 tests/ui/issues/issue-18353.rs create mode 100644 tests/ui/issues/issue-18389.rs create mode 100644 tests/ui/issues/issue-18389.stderr create mode 100644 tests/ui/issues/issue-18423.rs create mode 100644 tests/ui/issues/issue-18423.stderr create mode 100644 tests/ui/issues/issue-18446-2.rs create mode 100644 tests/ui/issues/issue-18446.rs create mode 100644 tests/ui/issues/issue-18446.stderr create mode 100644 tests/ui/issues/issue-18464.rs create mode 100644 tests/ui/issues/issue-18501.rs create mode 100644 tests/ui/issues/issue-18514.rs create mode 100644 tests/ui/issues/issue-18532.rs create mode 100644 tests/ui/issues/issue-18532.stderr create mode 100644 tests/ui/issues/issue-18539.rs create mode 100644 tests/ui/issues/issue-18566.rs create mode 100644 tests/ui/issues/issue-18566.stderr create mode 100644 tests/ui/issues/issue-18576.rs create mode 100644 tests/ui/issues/issue-18611.rs create mode 100644 tests/ui/issues/issue-18611.stderr create mode 100644 tests/ui/issues/issue-18685.rs create mode 100644 tests/ui/issues/issue-1871.rs create mode 100644 tests/ui/issues/issue-1871.stderr create mode 100644 tests/ui/issues/issue-18711.rs create mode 100644 tests/ui/issues/issue-18738.rs create mode 100644 tests/ui/issues/issue-18767.rs create mode 100644 tests/ui/issues/issue-18783.rs create mode 100644 tests/ui/issues/issue-18783.stderr create mode 100644 tests/ui/issues/issue-18804/auxiliary/lib.rs create mode 100644 tests/ui/issues/issue-18804/main.rs create mode 100644 tests/ui/issues/issue-18809.rs create mode 100644 tests/ui/issues/issue-18819.rs create mode 100644 tests/ui/issues/issue-18819.stderr create mode 100644 tests/ui/issues/issue-18845.rs create mode 100644 tests/ui/issues/issue-18859.rs create mode 100644 tests/ui/issues/issue-18906.rs create mode 100644 tests/ui/issues/issue-18913.rs create mode 100644 tests/ui/issues/issue-18919.rs create mode 100644 tests/ui/issues/issue-18919.stderr create mode 100644 tests/ui/issues/issue-18952.rs create mode 100644 tests/ui/issues/issue-18959.rs create mode 100644 tests/ui/issues/issue-18959.stderr create mode 100644 tests/ui/issues/issue-18988.rs create mode 100644 tests/ui/issues/issue-1900.rs create mode 100644 tests/ui/issues/issue-1900.stderr create mode 100644 tests/ui/issues/issue-19001.rs create mode 100644 tests/ui/issues/issue-19037.rs create mode 100644 tests/ui/issues/issue-19086.rs create mode 100644 tests/ui/issues/issue-19086.stderr create mode 100644 tests/ui/issues/issue-19097.rs create mode 100644 tests/ui/issues/issue-19098.rs create mode 100644 tests/ui/issues/issue-19100.fixed create mode 100644 tests/ui/issues/issue-19100.rs create mode 100644 tests/ui/issues/issue-19100.stderr create mode 100644 tests/ui/issues/issue-19102.rs create mode 100644 tests/ui/issues/issue-19127.rs create mode 100644 tests/ui/issues/issue-19129-1.rs create mode 100644 tests/ui/issues/issue-19129-2.rs create mode 100644 tests/ui/issues/issue-19135.rs create mode 100644 tests/ui/issues/issue-1920-1.rs create mode 100644 tests/ui/issues/issue-1920-1.stderr create mode 100644 tests/ui/issues/issue-1920-2.rs create mode 100644 tests/ui/issues/issue-1920-2.stderr create mode 100644 tests/ui/issues/issue-1920-3.rs create mode 100644 tests/ui/issues/issue-1920-3.stderr create mode 100644 tests/ui/issues/issue-19244-1.rs create mode 100644 tests/ui/issues/issue-19244-1.stderr create mode 100644 tests/ui/issues/issue-19244-2.rs create mode 100644 tests/ui/issues/issue-19244-2.stderr create mode 100644 tests/ui/issues/issue-19293.rs create mode 100644 tests/ui/issues/issue-19340-1.rs create mode 100644 tests/ui/issues/issue-19340-2.rs create mode 100644 tests/ui/issues/issue-19367.rs create mode 100644 tests/ui/issues/issue-19380.rs create mode 100644 tests/ui/issues/issue-19380.stderr create mode 100644 tests/ui/issues/issue-19398.rs create mode 100644 tests/ui/issues/issue-19404.rs create mode 100644 tests/ui/issues/issue-19479.rs create mode 100644 tests/ui/issues/issue-19482.rs create mode 100644 tests/ui/issues/issue-19482.stderr create mode 100644 tests/ui/issues/issue-19499.rs create mode 100644 tests/ui/issues/issue-19521.rs create mode 100644 tests/ui/issues/issue-19521.stderr create mode 100644 tests/ui/issues/issue-19601.rs create mode 100644 tests/ui/issues/issue-1962.fixed create mode 100644 tests/ui/issues/issue-1962.rs create mode 100644 tests/ui/issues/issue-1962.stderr create mode 100644 tests/ui/issues/issue-19631.rs create mode 100644 tests/ui/issues/issue-19632.rs create mode 100644 tests/ui/issues/issue-19692.rs create mode 100644 tests/ui/issues/issue-19692.stderr create mode 100644 tests/ui/issues/issue-19707.rs create mode 100644 tests/ui/issues/issue-19707.stderr create mode 100644 tests/ui/issues/issue-19734.rs create mode 100644 tests/ui/issues/issue-19734.stderr create mode 100644 tests/ui/issues/issue-1974.rs create mode 100644 tests/ui/issues/issue-19811-escape-unicode.rs create mode 100644 tests/ui/issues/issue-19850.rs create mode 100644 tests/ui/issues/issue-19922.rs create mode 100644 tests/ui/issues/issue-19922.stderr create mode 100644 tests/ui/issues/issue-19982.rs create mode 100644 tests/ui/issues/issue-19991.rs create mode 100644 tests/ui/issues/issue-19991.stderr create mode 100644 tests/ui/issues/issue-20009.rs create mode 100644 tests/ui/issues/issue-20055-box-trait.rs create mode 100644 tests/ui/issues/issue-20055-box-unsized-array.rs create mode 100644 tests/ui/issues/issue-20162.rs create mode 100644 tests/ui/issues/issue-20162.stderr create mode 100644 tests/ui/issues/issue-20174.rs create mode 100644 tests/ui/issues/issue-20186.rs create mode 100644 tests/ui/issues/issue-20225.rs create mode 100644 tests/ui/issues/issue-20225.stderr create mode 100644 tests/ui/issues/issue-20261.rs create mode 100644 tests/ui/issues/issue-20261.stderr create mode 100644 tests/ui/issues/issue-20313-rpass.rs create mode 100644 tests/ui/issues/issue-20313.rs create mode 100644 tests/ui/issues/issue-20313.stderr create mode 100644 tests/ui/issues/issue-20389.rs create mode 100644 tests/ui/issues/issue-20396.rs create mode 100644 tests/ui/issues/issue-20413.rs create mode 100644 tests/ui/issues/issue-20413.stderr create mode 100644 tests/ui/issues/issue-20414.rs create mode 100644 tests/ui/issues/issue-20427.rs create mode 100644 tests/ui/issues/issue-20433.rs create mode 100644 tests/ui/issues/issue-20433.stderr create mode 100644 tests/ui/issues/issue-20454.rs create mode 100644 tests/ui/issues/issue-20544.rs create mode 100644 tests/ui/issues/issue-20575.rs create mode 100644 tests/ui/issues/issue-20605.rs create mode 100644 tests/ui/issues/issue-20605.stderr create mode 100644 tests/ui/issues/issue-20616.rs create mode 100644 tests/ui/issues/issue-2063-resource.rs create mode 100644 tests/ui/issues/issue-2063.rs create mode 100644 tests/ui/issues/issue-20644.rs create mode 100644 tests/ui/issues/issue-20676.rs create mode 100644 tests/ui/issues/issue-20714.rs create mode 100644 tests/ui/issues/issue-20714.stderr create mode 100644 tests/ui/issues/issue-2074.rs create mode 100644 tests/ui/issues/issue-20763-1.rs create mode 100644 tests/ui/issues/issue-20763-2.rs create mode 100644 tests/ui/issues/issue-20772.rs create mode 100644 tests/ui/issues/issue-20772.stderr create mode 100644 tests/ui/issues/issue-20797.rs create mode 100644 tests/ui/issues/issue-20803.rs create mode 100644 tests/ui/issues/issue-20831-debruijn.rs create mode 100644 tests/ui/issues/issue-20831-debruijn.stderr create mode 100644 tests/ui/issues/issue-20847.rs create mode 100644 tests/ui/issues/issue-20939.rs create mode 100644 tests/ui/issues/issue-20939.stderr create mode 100644 tests/ui/issues/issue-20953.rs create mode 100644 tests/ui/issues/issue-20971.rs create mode 100644 tests/ui/issues/issue-21033.rs create mode 100644 tests/ui/issues/issue-21140.rs create mode 100644 tests/ui/issues/issue-21160.rs create mode 100644 tests/ui/issues/issue-21160.stderr create mode 100644 tests/ui/issues/issue-21174-2.rs create mode 100644 tests/ui/issues/issue-21174.rs create mode 100644 tests/ui/issues/issue-21174.stderr create mode 100644 tests/ui/issues/issue-21177.rs create mode 100644 tests/ui/issues/issue-21177.stderr create mode 100644 tests/ui/issues/issue-21202.rs create mode 100644 tests/ui/issues/issue-21202.stderr create mode 100644 tests/ui/issues/issue-21245.rs create mode 100644 tests/ui/issues/issue-21291.rs create mode 100644 tests/ui/issues/issue-21306.rs create mode 100644 tests/ui/issues/issue-21332.rs create mode 100644 tests/ui/issues/issue-21332.stderr create mode 100644 tests/ui/issues/issue-21361.rs create mode 100644 tests/ui/issues/issue-21384.rs create mode 100644 tests/ui/issues/issue-21400.rs create mode 100644 tests/ui/issues/issue-21402.rs create mode 100644 tests/ui/issues/issue-21449.rs create mode 100644 tests/ui/issues/issue-21449.stderr create mode 100644 tests/ui/issues/issue-2150.rs create mode 100644 tests/ui/issues/issue-2150.stderr create mode 100644 tests/ui/issues/issue-2151.rs create mode 100644 tests/ui/issues/issue-2151.stderr create mode 100644 tests/ui/issues/issue-21546.rs create mode 100644 tests/ui/issues/issue-21546.stderr create mode 100644 tests/ui/issues/issue-21554.rs create mode 100644 tests/ui/issues/issue-21554.stderr create mode 100644 tests/ui/issues/issue-21596.rs create mode 100644 tests/ui/issues/issue-21596.stderr create mode 100644 tests/ui/issues/issue-21600.rs create mode 100644 tests/ui/issues/issue-21600.stderr create mode 100644 tests/ui/issues/issue-21622.rs create mode 100644 tests/ui/issues/issue-21634.rs create mode 100644 tests/ui/issues/issue-21655.rs create mode 100644 tests/ui/issues/issue-2170-exe.rs create mode 100644 tests/ui/issues/issue-21701.rs create mode 100644 tests/ui/issues/issue-21701.stderr create mode 100644 tests/ui/issues/issue-21763.rs create mode 100644 tests/ui/issues/issue-21763.stderr create mode 100644 tests/ui/issues/issue-21837.rs create mode 100644 tests/ui/issues/issue-21837.stderr create mode 100644 tests/ui/issues/issue-21891.rs create mode 100644 tests/ui/issues/issue-2190-1.rs create mode 100644 tests/ui/issues/issue-21909.rs create mode 100644 tests/ui/issues/issue-21922.rs create mode 100644 tests/ui/issues/issue-21946.rs create mode 100644 tests/ui/issues/issue-21946.stderr create mode 100644 tests/ui/issues/issue-21950.rs create mode 100644 tests/ui/issues/issue-21950.stderr create mode 100644 tests/ui/issues/issue-21974.rs create mode 100644 tests/ui/issues/issue-21974.stderr create mode 100644 tests/ui/issues/issue-22008.rs create mode 100644 tests/ui/issues/issue-22034.rs create mode 100644 tests/ui/issues/issue-22034.stderr create mode 100644 tests/ui/issues/issue-22036.rs create mode 100644 tests/ui/issues/issue-2214.rs create mode 100644 tests/ui/issues/issue-22258.rs create mode 100644 tests/ui/issues/issue-22289.rs create mode 100644 tests/ui/issues/issue-22289.stderr create mode 100644 tests/ui/issues/issue-22312.rs create mode 100644 tests/ui/issues/issue-22312.stderr create mode 100644 tests/ui/issues/issue-22346.rs create mode 100644 tests/ui/issues/issue-22356.rs create mode 100644 tests/ui/issues/issue-22370.rs create mode 100644 tests/ui/issues/issue-22370.stderr create mode 100644 tests/ui/issues/issue-22384.rs create mode 100644 tests/ui/issues/issue-22384.stderr create mode 100644 tests/ui/issues/issue-22403.rs create mode 100644 tests/ui/issues/issue-22426.rs create mode 100644 tests/ui/issues/issue-22434.rs create mode 100644 tests/ui/issues/issue-22434.stderr create mode 100644 tests/ui/issues/issue-22468.rs create mode 100644 tests/ui/issues/issue-22468.stderr create mode 100644 tests/ui/issues/issue-22471.rs create mode 100644 tests/ui/issues/issue-22536-copy-mustnt-zero.rs create mode 100644 tests/ui/issues/issue-22577.rs create mode 100644 tests/ui/issues/issue-22599.rs create mode 100644 tests/ui/issues/issue-22599.stderr create mode 100644 tests/ui/issues/issue-22603.rs create mode 100644 tests/ui/issues/issue-22629.rs create mode 100644 tests/ui/issues/issue-22638.polonius.stderr create mode 100644 tests/ui/issues/issue-22638.rs create mode 100644 tests/ui/issues/issue-22638.stderr create mode 100644 tests/ui/issues/issue-22644.rs create mode 100644 tests/ui/issues/issue-22644.stderr create mode 100644 tests/ui/issues/issue-22673.rs create mode 100644 tests/ui/issues/issue-22684.rs create mode 100644 tests/ui/issues/issue-22684.stderr create mode 100644 tests/ui/issues/issue-22706.rs create mode 100644 tests/ui/issues/issue-22706.stderr create mode 100644 tests/ui/issues/issue-22777.rs create mode 100644 tests/ui/issues/issue-22781.rs create mode 100644 tests/ui/issues/issue-22789.rs create mode 100644 tests/ui/issues/issue-2281-part1.rs create mode 100644 tests/ui/issues/issue-2281-part1.stderr create mode 100644 tests/ui/issues/issue-22814.rs create mode 100644 tests/ui/issues/issue-2284.rs create mode 100644 tests/ui/issues/issue-22864-1.rs create mode 100644 tests/ui/issues/issue-22864-2.rs create mode 100644 tests/ui/issues/issue-22872.rs create mode 100644 tests/ui/issues/issue-22872.stderr create mode 100644 tests/ui/issues/issue-22874.rs create mode 100644 tests/ui/issues/issue-22874.stderr create mode 100644 tests/ui/issues/issue-2288.rs create mode 100644 tests/ui/issues/issue-22886.rs create mode 100644 tests/ui/issues/issue-22886.stderr create mode 100644 tests/ui/issues/issue-22894.rs create mode 100644 tests/ui/issues/issue-22933-1.rs create mode 100644 tests/ui/issues/issue-22933-2.rs create mode 100644 tests/ui/issues/issue-22933-2.stderr create mode 100644 tests/ui/issues/issue-22992-2.rs create mode 100644 tests/ui/issues/issue-22992.rs create mode 100644 tests/ui/issues/issue-23024.rs create mode 100644 tests/ui/issues/issue-23024.stderr create mode 100644 tests/ui/issues/issue-23036.rs create mode 100644 tests/ui/issues/issue-23041.rs create mode 100644 tests/ui/issues/issue-23041.stderr create mode 100644 tests/ui/issues/issue-23046.rs create mode 100644 tests/ui/issues/issue-23046.stderr create mode 100644 tests/ui/issues/issue-23073.rs create mode 100644 tests/ui/issues/issue-23073.stderr create mode 100644 tests/ui/issues/issue-2311-2.rs create mode 100644 tests/ui/issues/issue-2311.rs create mode 100644 tests/ui/issues/issue-2312.rs create mode 100644 tests/ui/issues/issue-23122-1.rs create mode 100644 tests/ui/issues/issue-23122-1.stderr create mode 100644 tests/ui/issues/issue-23122-2.rs create mode 100644 tests/ui/issues/issue-23122-2.stderr create mode 100644 tests/ui/issues/issue-2316-c.rs create mode 100644 tests/ui/issues/issue-23173.rs create mode 100644 tests/ui/issues/issue-23173.stderr create mode 100644 tests/ui/issues/issue-23189.rs create mode 100644 tests/ui/issues/issue-23189.stderr create mode 100644 tests/ui/issues/issue-23217.rs create mode 100644 tests/ui/issues/issue-23217.stderr create mode 100644 tests/ui/issues/issue-23253.rs create mode 100644 tests/ui/issues/issue-23253.stderr create mode 100644 tests/ui/issues/issue-23261.rs create mode 100644 tests/ui/issues/issue-23281.rs create mode 100644 tests/ui/issues/issue-23281.stderr create mode 100644 tests/ui/issues/issue-23302-1.rs create mode 100644 tests/ui/issues/issue-23302-1.stderr create mode 100644 tests/ui/issues/issue-23302-2.rs create mode 100644 tests/ui/issues/issue-23302-2.stderr create mode 100644 tests/ui/issues/issue-23302-3.rs create mode 100644 tests/ui/issues/issue-23302-3.stderr create mode 100644 tests/ui/issues/issue-23304-1.rs create mode 100644 tests/ui/issues/issue-23304-2.rs create mode 100644 tests/ui/issues/issue-23311.rs create mode 100644 tests/ui/issues/issue-23336.rs create mode 100644 tests/ui/issues/issue-23354-2.rs create mode 100644 tests/ui/issues/issue-23354.rs create mode 100644 tests/ui/issues/issue-23406.rs create mode 100644 tests/ui/issues/issue-23433.rs create mode 100644 tests/ui/issues/issue-23442.rs create mode 100644 tests/ui/issues/issue-23477.rs create mode 100644 tests/ui/issues/issue-23485.rs create mode 100644 tests/ui/issues/issue-23491.rs create mode 100644 tests/ui/issues/issue-23543.rs create mode 100644 tests/ui/issues/issue-23543.stderr create mode 100644 tests/ui/issues/issue-23544.rs create mode 100644 tests/ui/issues/issue-23544.stderr create mode 100644 tests/ui/issues/issue-23550.rs create mode 100644 tests/ui/issues/issue-23589.rs create mode 100644 tests/ui/issues/issue-23589.stderr create mode 100644 tests/ui/issues/issue-23611-enum-swap-in-drop.rs create mode 100644 tests/ui/issues/issue-23649-1.rs create mode 100644 tests/ui/issues/issue-23649-2.rs create mode 100644 tests/ui/issues/issue-23649-3.rs create mode 100644 tests/ui/issues/issue-23699.rs create mode 100644 tests/ui/issues/issue-23781.rs create mode 100644 tests/ui/issues/issue-2380-b.rs create mode 100644 tests/ui/issues/issue-23808.rs create mode 100644 tests/ui/issues/issue-2383.rs create mode 100644 tests/ui/issues/issue-23891.rs create mode 100644 tests/ui/issues/issue-23898.rs create mode 100644 tests/ui/issues/issue-23958.rs create mode 100644 tests/ui/issues/issue-23966.rs create mode 100644 tests/ui/issues/issue-23966.stderr create mode 100644 tests/ui/issues/issue-23992.rs create mode 100644 tests/ui/issues/issue-24013.rs create mode 100644 tests/ui/issues/issue-24013.stderr create mode 100644 tests/ui/issues/issue-24036.rs create mode 100644 tests/ui/issues/issue-24036.stderr create mode 100644 tests/ui/issues/issue-24086.rs create mode 100644 tests/ui/issues/issue-2414-c.rs create mode 100644 tests/ui/issues/issue-24161.rs create mode 100644 tests/ui/issues/issue-24227.rs create mode 100644 tests/ui/issues/issue-2428.rs create mode 100644 tests/ui/issues/issue-24308.rs create mode 100644 tests/ui/issues/issue-24322.rs create mode 100644 tests/ui/issues/issue-24322.stderr create mode 100644 tests/ui/issues/issue-24352.rs create mode 100644 tests/ui/issues/issue-24352.stderr create mode 100644 tests/ui/issues/issue-24353.rs create mode 100644 tests/ui/issues/issue-24357.rs create mode 100644 tests/ui/issues/issue-24357.stderr create mode 100644 tests/ui/issues/issue-24363.rs create mode 100644 tests/ui/issues/issue-24363.stderr create mode 100644 tests/ui/issues/issue-24365.rs create mode 100644 tests/ui/issues/issue-24365.stderr create mode 100644 tests/ui/issues/issue-24389.rs create mode 100644 tests/ui/issues/issue-24424.rs create mode 100644 tests/ui/issues/issue-24424.stderr create mode 100644 tests/ui/issues/issue-24434.rs create mode 100644 tests/ui/issues/issue-24446.rs create mode 100644 tests/ui/issues/issue-24446.stderr create mode 100644 tests/ui/issues/issue-2445-b.rs create mode 100644 tests/ui/issues/issue-2445.rs create mode 100644 tests/ui/issues/issue-24533.rs create mode 100644 tests/ui/issues/issue-24589.rs create mode 100644 tests/ui/issues/issue-2463.rs create mode 100644 tests/ui/issues/issue-24682.rs create mode 100644 tests/ui/issues/issue-24682.stderr create mode 100644 tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs create mode 100644 tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs create mode 100644 tests/ui/issues/issue-24687-embed-debuginfo/main.rs create mode 100644 tests/ui/issues/issue-2470-bounds-check-overflow.rs create mode 100644 tests/ui/issues/issue-2472.rs create mode 100644 tests/ui/issues/issue-24779.rs create mode 100644 tests/ui/issues/issue-24819.rs create mode 100644 tests/ui/issues/issue-24819.stderr create mode 100644 tests/ui/issues/issue-2487-a.rs create mode 100644 tests/ui/issues/issue-24945-repeat-dash-opts.rs create mode 100644 tests/ui/issues/issue-24947.rs create mode 100644 tests/ui/issues/issue-24954.rs create mode 100644 tests/ui/issues/issue-2502.rs create mode 100644 tests/ui/issues/issue-25076.rs create mode 100644 tests/ui/issues/issue-25076.stderr create mode 100644 tests/ui/issues/issue-25089.rs create mode 100644 tests/ui/issues/issue-25145.rs create mode 100644 tests/ui/issues/issue-25180.rs create mode 100644 tests/ui/issues/issue-25185.rs create mode 100644 tests/ui/issues/issue-2526-a.rs create mode 100644 tests/ui/issues/issue-25279.rs create mode 100644 tests/ui/issues/issue-25343.rs create mode 100644 tests/ui/issues/issue-25368.rs create mode 100644 tests/ui/issues/issue-25368.stderr create mode 100644 tests/ui/issues/issue-25386.rs create mode 100644 tests/ui/issues/issue-25386.stderr create mode 100644 tests/ui/issues/issue-25394.rs create mode 100644 tests/ui/issues/issue-25439.rs create mode 100644 tests/ui/issues/issue-25439.stderr create mode 100644 tests/ui/issues/issue-25467.rs create mode 100644 tests/ui/issues/issue-25497.rs create mode 100644 tests/ui/issues/issue-2550.rs create mode 100644 tests/ui/issues/issue-25515.rs create mode 100644 tests/ui/issues/issue-25549-multiple-drop.rs create mode 100644 tests/ui/issues/issue-25579.rs create mode 100644 tests/ui/issues/issue-25679.rs create mode 100644 tests/ui/issues/issue-25693.rs create mode 100644 tests/ui/issues/issue-25746-bool-transmute.rs create mode 100644 tests/ui/issues/issue-25757.rs create mode 100644 tests/ui/issues/issue-25810.rs create mode 100644 tests/ui/issues/issue-2590.rs create mode 100644 tests/ui/issues/issue-2590.stderr create mode 100644 tests/ui/issues/issue-25901.rs create mode 100644 tests/ui/issues/issue-25901.stderr create mode 100644 tests/ui/issues/issue-26056.rs create mode 100644 tests/ui/issues/issue-26056.stderr create mode 100644 tests/ui/issues/issue-26093.rs create mode 100644 tests/ui/issues/issue-26093.stderr create mode 100644 tests/ui/issues/issue-26094.rs create mode 100644 tests/ui/issues/issue-26094.stderr create mode 100644 tests/ui/issues/issue-26095.rs create mode 100644 tests/ui/issues/issue-2611-3.rs create mode 100644 tests/ui/issues/issue-26127.rs create mode 100644 tests/ui/issues/issue-26186.rs create mode 100644 tests/ui/issues/issue-26205.rs create mode 100644 tests/ui/issues/issue-26217.rs create mode 100644 tests/ui/issues/issue-26217.stderr create mode 100644 tests/ui/issues/issue-26237.rs create mode 100644 tests/ui/issues/issue-26237.stderr create mode 100644 tests/ui/issues/issue-26262.rs create mode 100644 tests/ui/issues/issue-26262.stderr create mode 100644 tests/ui/issues/issue-2631-b.rs create mode 100644 tests/ui/issues/issue-2642.rs create mode 100644 tests/ui/issues/issue-26468.rs create mode 100644 tests/ui/issues/issue-26472.rs create mode 100644 tests/ui/issues/issue-26472.stderr create mode 100644 tests/ui/issues/issue-26484.rs create mode 100644 tests/ui/issues/issue-26614.rs create mode 100644 tests/ui/issues/issue-26619.rs create mode 100644 tests/ui/issues/issue-26619.stderr create mode 100644 tests/ui/issues/issue-26641.rs create mode 100644 tests/ui/issues/issue-26646.rs create mode 100644 tests/ui/issues/issue-26655.rs create mode 100644 tests/ui/issues/issue-26709.rs create mode 100644 tests/ui/issues/issue-26802.rs create mode 100644 tests/ui/issues/issue-26805.rs create mode 100644 tests/ui/issues/issue-26812.rs create mode 100644 tests/ui/issues/issue-26812.stderr create mode 100644 tests/ui/issues/issue-26905-rpass.rs create mode 100644 tests/ui/issues/issue-26905.rs create mode 100644 tests/ui/issues/issue-26905.stderr create mode 100644 tests/ui/issues/issue-26948.rs create mode 100644 tests/ui/issues/issue-26948.stderr create mode 100644 tests/ui/issues/issue-26997.rs create mode 100644 tests/ui/issues/issue-27008.rs create mode 100644 tests/ui/issues/issue-27008.stderr create mode 100644 tests/ui/issues/issue-27033.rs create mode 100644 tests/ui/issues/issue-27033.stderr create mode 100644 tests/ui/issues/issue-27042.rs create mode 100644 tests/ui/issues/issue-27042.stderr create mode 100644 tests/ui/issues/issue-27054-primitive-binary-ops.rs create mode 100644 tests/ui/issues/issue-27078.rs create mode 100644 tests/ui/issues/issue-27078.stderr create mode 100644 tests/ui/issues/issue-2708.rs create mode 100644 tests/ui/issues/issue-27105.rs create mode 100644 tests/ui/issues/issue-2723-b.rs create mode 100644 tests/ui/issues/issue-27240.rs create mode 100644 tests/ui/issues/issue-27268.rs create mode 100644 tests/ui/issues/issue-27281.rs create mode 100644 tests/ui/issues/issue-27340.rs create mode 100644 tests/ui/issues/issue-27340.stderr create mode 100644 tests/ui/issues/issue-2735-2.rs create mode 100644 tests/ui/issues/issue-2735-3.rs create mode 100644 tests/ui/issues/issue-2735.rs create mode 100644 tests/ui/issues/issue-27401-dropflag-reinit.rs create mode 100644 tests/ui/issues/issue-27433.fixed create mode 100644 tests/ui/issues/issue-27433.rs create mode 100644 tests/ui/issues/issue-27433.stderr create mode 100644 tests/ui/issues/issue-2748-a.rs create mode 100644 tests/ui/issues/issue-27583.rs create mode 100644 tests/ui/issues/issue-27592.rs create mode 100644 tests/ui/issues/issue-27592.stderr create mode 100644 tests/ui/issues/issue-2761.rs create mode 100644 tests/ui/issues/issue-27639.rs create mode 100644 tests/ui/issues/issue-27697.rs create mode 100644 tests/ui/issues/issue-27815.rs create mode 100644 tests/ui/issues/issue-27815.stderr create mode 100644 tests/ui/issues/issue-27842.rs create mode 100644 tests/ui/issues/issue-27842.stderr create mode 100644 tests/ui/issues/issue-27859.rs create mode 100644 tests/ui/issues/issue-27889.rs create mode 100644 tests/ui/issues/issue-27901.rs create mode 100644 tests/ui/issues/issue-27942.rs create mode 100644 tests/ui/issues/issue-27942.stderr create mode 100644 tests/ui/issues/issue-27949.rs create mode 100644 tests/ui/issues/issue-27997.rs create mode 100644 tests/ui/issues/issue-2804-2.rs create mode 100644 tests/ui/issues/issue-28105.rs create mode 100644 tests/ui/issues/issue-28105.stderr create mode 100644 tests/ui/issues/issue-28109.rs create mode 100644 tests/ui/issues/issue-28109.stderr create mode 100644 tests/ui/issues/issue-28181.rs create mode 100644 tests/ui/issues/issue-2823.rs create mode 100644 tests/ui/issues/issue-2823.stderr create mode 100644 tests/ui/issues/issue-28279.rs create mode 100644 tests/ui/issues/issue-28344.rs create mode 100644 tests/ui/issues/issue-28344.stderr create mode 100644 tests/ui/issues/issue-28433.rs create mode 100644 tests/ui/issues/issue-28433.stderr create mode 100644 tests/ui/issues/issue-28472.rs create mode 100644 tests/ui/issues/issue-28472.stderr create mode 100644 tests/ui/issues/issue-2848.rs create mode 100644 tests/ui/issues/issue-2848.stderr create mode 100644 tests/ui/issues/issue-2849.rs create mode 100644 tests/ui/issues/issue-2849.stderr create mode 100644 tests/ui/issues/issue-28498-must-work-ex1.rs create mode 100644 tests/ui/issues/issue-28498-must-work-ex2.rs create mode 100644 tests/ui/issues/issue-28498-ugeh-ex1.rs create mode 100644 tests/ui/issues/issue-28550.rs create mode 100644 tests/ui/issues/issue-28561.rs create mode 100644 tests/ui/issues/issue-28568.rs create mode 100644 tests/ui/issues/issue-28568.stderr create mode 100644 tests/ui/issues/issue-28586.rs create mode 100644 tests/ui/issues/issue-28586.stderr create mode 100644 tests/ui/issues/issue-28600.rs create mode 100644 tests/ui/issues/issue-28625.rs create mode 100644 tests/ui/issues/issue-28625.stderr create mode 100644 tests/ui/issues/issue-28776.mir.stderr create mode 100644 tests/ui/issues/issue-28776.rs create mode 100644 tests/ui/issues/issue-28776.thir.stderr create mode 100644 tests/ui/issues/issue-28777.rs create mode 100644 tests/ui/issues/issue-28822.rs create mode 100644 tests/ui/issues/issue-28828.rs create mode 100644 tests/ui/issues/issue-28839.rs create mode 100644 tests/ui/issues/issue-28936.rs create mode 100644 tests/ui/issues/issue-2895.rs create mode 100644 tests/ui/issues/issue-28971.rs create mode 100644 tests/ui/issues/issue-28971.stderr create mode 100644 tests/ui/issues/issue-28983.rs create mode 100644 tests/ui/issues/issue-28992-empty.rs create mode 100644 tests/ui/issues/issue-28992-empty.stderr create mode 100644 tests/ui/issues/issue-28999.rs create mode 100644 tests/ui/issues/issue-29030.rs create mode 100644 tests/ui/issues/issue-29037.rs create mode 100644 tests/ui/issues/issue-2904.rs create mode 100644 tests/ui/issues/issue-29048.rs create mode 100644 tests/ui/issues/issue-29053.rs create mode 100644 tests/ui/issues/issue-29071-2.rs create mode 100644 tests/ui/issues/issue-29071.rs create mode 100644 tests/ui/issues/issue-29092.rs create mode 100644 tests/ui/issues/issue-29147-rpass.rs create mode 100644 tests/ui/issues/issue-29147.rs create mode 100644 tests/ui/issues/issue-29147.stderr create mode 100644 tests/ui/issues/issue-29181.rs create mode 100644 tests/ui/issues/issue-29181.stderr create mode 100644 tests/ui/issues/issue-29265.rs create mode 100644 tests/ui/issues/issue-29276.rs create mode 100644 tests/ui/issues/issue-2935.rs create mode 100644 tests/ui/issues/issue-29466.rs create mode 100644 tests/ui/issues/issue-29485.rs create mode 100644 tests/ui/issues/issue-2951.rs create mode 100644 tests/ui/issues/issue-2951.stderr create mode 100644 tests/ui/issues/issue-29516.rs create mode 100644 tests/ui/issues/issue-29522.rs create mode 100644 tests/ui/issues/issue-29540.rs create mode 100644 tests/ui/issues/issue-29663.rs create mode 100644 tests/ui/issues/issue-29668.rs create mode 100644 tests/ui/issues/issue-29710.rs create mode 100644 tests/ui/issues/issue-29723.rs create mode 100644 tests/ui/issues/issue-29723.stderr create mode 100644 tests/ui/issues/issue-29740.rs create mode 100644 tests/ui/issues/issue-29743.rs create mode 100644 tests/ui/issues/issue-29746.rs create mode 100644 tests/ui/issues/issue-29798.rs create mode 100644 tests/ui/issues/issue-29821.rs create mode 100644 tests/ui/issues/issue-29857.rs create mode 100644 tests/ui/issues/issue-29861.rs create mode 100644 tests/ui/issues/issue-29861.stderr create mode 100644 tests/ui/issues/issue-2989.rs create mode 100644 tests/ui/issues/issue-29948.rs create mode 100644 tests/ui/issues/issue-2995.rs create mode 100644 tests/ui/issues/issue-2995.stderr create mode 100644 tests/ui/issues/issue-30007.rs create mode 100644 tests/ui/issues/issue-30007.stderr create mode 100644 tests/ui/issues/issue-30018-panic.rs create mode 100644 tests/ui/issues/issue-3008-1.rs create mode 100644 tests/ui/issues/issue-3008-1.stderr create mode 100644 tests/ui/issues/issue-3008-2.rs create mode 100644 tests/ui/issues/issue-3008-2.stderr create mode 100644 tests/ui/issues/issue-3008-3.rs create mode 100644 tests/ui/issues/issue-3008-3.stderr create mode 100644 tests/ui/issues/issue-30081.rs create mode 100644 tests/ui/issues/issue-3012-2.rs create mode 100644 tests/ui/issues/issue-30123.rs create mode 100644 tests/ui/issues/issue-30123.stderr create mode 100644 tests/ui/issues/issue-3021-b.rs create mode 100644 tests/ui/issues/issue-3021-b.stderr create mode 100644 tests/ui/issues/issue-3021-d.rs create mode 100644 tests/ui/issues/issue-3021-d.stderr create mode 100644 tests/ui/issues/issue-30236.rs create mode 100644 tests/ui/issues/issue-30236.stderr create mode 100644 tests/ui/issues/issue-30255.rs create mode 100644 tests/ui/issues/issue-30255.stderr create mode 100644 tests/ui/issues/issue-3026.rs create mode 100644 tests/ui/issues/issue-3029.rs create mode 100644 tests/ui/issues/issue-3037.rs create mode 100644 tests/ui/issues/issue-30371.rs create mode 100644 tests/ui/issues/issue-3038.rs create mode 100644 tests/ui/issues/issue-3038.stderr create mode 100644 tests/ui/issues/issue-30380.rs create mode 100644 tests/ui/issues/issue-30438-a.rs create mode 100644 tests/ui/issues/issue-30438-a.stderr create mode 100644 tests/ui/issues/issue-30438-b.rs create mode 100644 tests/ui/issues/issue-30438-b.stderr create mode 100644 tests/ui/issues/issue-30438-c.rs create mode 100644 tests/ui/issues/issue-30438-c.stderr create mode 100644 tests/ui/issues/issue-30490.rs create mode 100644 tests/ui/issues/issue-3052.rs create mode 100644 tests/ui/issues/issue-30530.rs create mode 100644 tests/ui/issues/issue-30589.rs create mode 100644 tests/ui/issues/issue-30589.stderr create mode 100644 tests/ui/issues/issue-30615.rs create mode 100644 tests/ui/issues/issue-30756.rs create mode 100644 tests/ui/issues/issue-30891.rs create mode 100644 tests/ui/issues/issue-3091.rs create mode 100644 tests/ui/issues/issue-3099-a.rs create mode 100644 tests/ui/issues/issue-3099-a.stderr create mode 100644 tests/ui/issues/issue-3099-b.rs create mode 100644 tests/ui/issues/issue-3099-b.stderr create mode 100644 tests/ui/issues/issue-3099.rs create mode 100644 tests/ui/issues/issue-3099.stderr create mode 100644 tests/ui/issues/issue-31011.rs create mode 100644 tests/ui/issues/issue-31011.stderr create mode 100644 tests/ui/issues/issue-3109.rs create mode 100644 tests/ui/issues/issue-3121.rs create mode 100644 tests/ui/issues/issue-31260.rs create mode 100644 tests/ui/issues/issue-31267-additional.rs create mode 100644 tests/ui/issues/issue-31267.rs create mode 100644 tests/ui/issues/issue-31299.rs create mode 100644 tests/ui/issues/issue-3136-b.rs create mode 100644 tests/ui/issues/issue-3149.rs create mode 100644 tests/ui/issues/issue-31511.rs create mode 100644 tests/ui/issues/issue-31511.stderr create mode 100644 tests/ui/issues/issue-3154.rs create mode 100644 tests/ui/issues/issue-3154.stderr create mode 100644 tests/ui/issues/issue-31702.rs create mode 100644 tests/ui/issues/issue-31769.rs create mode 100644 tests/ui/issues/issue-31769.stderr create mode 100644 tests/ui/issues/issue-31776.rs create mode 100644 tests/ui/issues/issue-31910.rs create mode 100644 tests/ui/issues/issue-31910.stderr create mode 100644 tests/ui/issues/issue-32004.rs create mode 100644 tests/ui/issues/issue-32004.stderr create mode 100644 tests/ui/issues/issue-32008.rs create mode 100644 tests/ui/issues/issue-32086.rs create mode 100644 tests/ui/issues/issue-32086.stderr create mode 100644 tests/ui/issues/issue-32122-1.fixed create mode 100644 tests/ui/issues/issue-32122-1.rs create mode 100644 tests/ui/issues/issue-32122-1.stderr create mode 100644 tests/ui/issues/issue-32122-2.fixed create mode 100644 tests/ui/issues/issue-32122-2.rs create mode 100644 tests/ui/issues/issue-32122-2.stderr create mode 100644 tests/ui/issues/issue-3214.rs create mode 100644 tests/ui/issues/issue-3214.stderr create mode 100644 tests/ui/issues/issue-3220.rs create mode 100644 tests/ui/issues/issue-32292.rs create mode 100644 tests/ui/issues/issue-32323.rs create mode 100644 tests/ui/issues/issue-32323.stderr create mode 100644 tests/ui/issues/issue-32324.rs create mode 100644 tests/ui/issues/issue-32326.rs create mode 100644 tests/ui/issues/issue-32326.stderr create mode 100644 tests/ui/issues/issue-32377.rs create mode 100644 tests/ui/issues/issue-32377.stderr create mode 100644 tests/ui/issues/issue-32389.rs create mode 100644 tests/ui/issues/issue-32518.rs create mode 100644 tests/ui/issues/issue-32655.rs create mode 100644 tests/ui/issues/issue-32655.stderr create mode 100644 tests/ui/issues/issue-32709.rs create mode 100644 tests/ui/issues/issue-32709.stderr create mode 100644 tests/ui/issues/issue-32782.rs create mode 100644 tests/ui/issues/issue-32782.stderr create mode 100644 tests/ui/issues/issue-32797.rs create mode 100644 tests/ui/issues/issue-32805.rs create mode 100644 tests/ui/issues/issue-3290.rs create mode 100644 tests/ui/issues/issue-32950.rs create mode 100644 tests/ui/issues/issue-32950.stderr create mode 100644 tests/ui/issues/issue-32995-2.rs create mode 100644 tests/ui/issues/issue-32995-2.stderr create mode 100644 tests/ui/issues/issue-32995.rs create mode 100644 tests/ui/issues/issue-32995.stderr create mode 100644 tests/ui/issues/issue-33096.rs create mode 100644 tests/ui/issues/issue-33187.rs create mode 100644 tests/ui/issues/issue-33202.rs create mode 100644 tests/ui/issues/issue-33241.rs create mode 100644 tests/ui/issues/issue-33287.rs create mode 100644 tests/ui/issues/issue-33293.rs create mode 100644 tests/ui/issues/issue-33293.stderr create mode 100644 tests/ui/issues/issue-33387.rs create mode 100644 tests/ui/issues/issue-3344.rs create mode 100644 tests/ui/issues/issue-3344.stderr create mode 100644 tests/ui/issues/issue-33461.rs create mode 100644 tests/ui/issues/issue-33504.rs create mode 100644 tests/ui/issues/issue-33504.stderr create mode 100644 tests/ui/issues/issue-33525.rs create mode 100644 tests/ui/issues/issue-33525.stderr create mode 100644 tests/ui/issues/issue-33571.rs create mode 100644 tests/ui/issues/issue-33571.stderr create mode 100644 tests/ui/issues/issue-33687.rs create mode 100644 tests/ui/issues/issue-33770.rs create mode 100644 tests/ui/issues/issue-3389.rs create mode 100644 tests/ui/issues/issue-33903.rs create mode 100644 tests/ui/issues/issue-33941.rs create mode 100644 tests/ui/issues/issue-33941.stderr create mode 100644 tests/ui/issues/issue-33992.rs create mode 100644 tests/ui/issues/issue-34047.rs create mode 100644 tests/ui/issues/issue-34047.stderr create mode 100644 tests/ui/issues/issue-34074.rs create mode 100644 tests/ui/issues/issue-34209.rs create mode 100644 tests/ui/issues/issue-34209.stderr create mode 100644 tests/ui/issues/issue-34229.rs create mode 100644 tests/ui/issues/issue-34229.stderr create mode 100644 tests/ui/issues/issue-3424.rs create mode 100644 tests/ui/issues/issue-3429.rs create mode 100644 tests/ui/issues/issue-34334.rs create mode 100644 tests/ui/issues/issue-34334.stderr create mode 100644 tests/ui/issues/issue-34349.rs create mode 100644 tests/ui/issues/issue-34349.stderr create mode 100644 tests/ui/issues/issue-34373.rs create mode 100644 tests/ui/issues/issue-34373.stderr create mode 100644 tests/ui/issues/issue-34418.rs create mode 100644 tests/ui/issues/issue-34427.rs create mode 100644 tests/ui/issues/issue-3447.rs create mode 100644 tests/ui/issues/issue-34503.rs create mode 100644 tests/ui/issues/issue-34569.rs create mode 100644 tests/ui/issues/issue-34571.rs create mode 100644 tests/ui/issues/issue-34721.fixed create mode 100644 tests/ui/issues/issue-34721.rs create mode 100644 tests/ui/issues/issue-34721.stderr create mode 100644 tests/ui/issues/issue-34751.rs create mode 100644 tests/ui/issues/issue-3477.rs create mode 100644 tests/ui/issues/issue-3477.stderr create mode 100644 tests/ui/issues/issue-34780.rs create mode 100644 tests/ui/issues/issue-34796.rs create mode 100644 tests/ui/issues/issue-34839.rs create mode 100644 tests/ui/issues/issue-34932.rs create mode 100644 tests/ui/issues/issue-3500.rs create mode 100644 tests/ui/issues/issue-35139.rs create mode 100644 tests/ui/issues/issue-35139.stderr create mode 100644 tests/ui/issues/issue-3521-2.fixed create mode 100644 tests/ui/issues/issue-3521-2.rs create mode 100644 tests/ui/issues/issue-3521-2.stderr create mode 100644 tests/ui/issues/issue-35241.rs create mode 100644 tests/ui/issues/issue-35241.stderr create mode 100644 tests/ui/issues/issue-35423.rs create mode 100644 tests/ui/issues/issue-3556.rs create mode 100644 tests/ui/issues/issue-35570.rs create mode 100644 tests/ui/issues/issue-35570.stderr create mode 100644 tests/ui/issues/issue-3559.rs create mode 100644 tests/ui/issues/issue-35600.rs create mode 100644 tests/ui/issues/issue-3563-3.rs create mode 100644 tests/ui/issues/issue-3574.rs create mode 100644 tests/ui/issues/issue-35815.rs create mode 100644 tests/ui/issues/issue-35976.rs create mode 100644 tests/ui/issues/issue-35976.unimported.stderr create mode 100644 tests/ui/issues/issue-35988.rs create mode 100644 tests/ui/issues/issue-35988.stderr create mode 100644 tests/ui/issues/issue-36023.rs create mode 100644 tests/ui/issues/issue-36036-associated-type-layout.rs create mode 100644 tests/ui/issues/issue-36075.rs create mode 100644 tests/ui/issues/issue-3609.rs create mode 100644 tests/ui/issues/issue-36116.rs create mode 100644 tests/ui/issues/issue-36260.rs create mode 100644 tests/ui/issues/issue-36278-prefix-nesting.rs create mode 100644 tests/ui/issues/issue-36299.rs create mode 100644 tests/ui/issues/issue-36299.stderr create mode 100644 tests/ui/issues/issue-36379.rs create mode 100644 tests/ui/issues/issue-36400.rs create mode 100644 tests/ui/issues/issue-36400.stderr create mode 100644 tests/ui/issues/issue-36401.rs create mode 100644 tests/ui/issues/issue-36474.rs create mode 100644 tests/ui/issues/issue-3656.rs create mode 100644 tests/ui/issues/issue-3668-2.fixed create mode 100644 tests/ui/issues/issue-3668-2.rs create mode 100644 tests/ui/issues/issue-3668-2.stderr create mode 100644 tests/ui/issues/issue-3668.rs create mode 100644 tests/ui/issues/issue-3668.stderr create mode 100644 tests/ui/issues/issue-36744-bitcast-args-if-needed.rs create mode 100644 tests/ui/issues/issue-36744-without-calls.rs create mode 100644 tests/ui/issues/issue-36786-resolve-call.rs create mode 100644 tests/ui/issues/issue-36792.rs create mode 100644 tests/ui/issues/issue-3680.rs create mode 100644 tests/ui/issues/issue-3680.stderr create mode 100644 tests/ui/issues/issue-36816.rs create mode 100644 tests/ui/issues/issue-36836.rs create mode 100644 tests/ui/issues/issue-36836.stderr create mode 100644 tests/ui/issues/issue-36839.rs create mode 100644 tests/ui/issues/issue-36856.rs create mode 100644 tests/ui/issues/issue-36936.rs create mode 100644 tests/ui/issues/issue-36954.rs create mode 100644 tests/ui/issues/issue-3702-2.rs create mode 100644 tests/ui/issues/issue-3702-2.stderr create mode 100644 tests/ui/issues/issue-3702.rs create mode 100644 tests/ui/issues/issue-37051.rs create mode 100644 tests/ui/issues/issue-3707.rs create mode 100644 tests/ui/issues/issue-3707.stderr create mode 100644 tests/ui/issues/issue-37109.rs create mode 100644 tests/ui/issues/issue-37131.rs create mode 100644 tests/ui/issues/issue-37131.stderr create mode 100644 tests/ui/issues/issue-37291/auxiliary/lib.rs create mode 100644 tests/ui/issues/issue-37291/main.rs create mode 100644 tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr create mode 100644 tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs create mode 100644 tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr create mode 100644 tests/ui/issues/issue-3743.rs create mode 100644 tests/ui/issues/issue-37510.rs create mode 100644 tests/ui/issues/issue-3753.rs create mode 100644 tests/ui/issues/issue-37534.rs create mode 100644 tests/ui/issues/issue-37534.stderr create mode 100644 tests/ui/issues/issue-37576.rs create mode 100644 tests/ui/issues/issue-37576.stderr create mode 100644 tests/ui/issues/issue-37598.rs create mode 100644 tests/ui/issues/issue-3763.rs create mode 100644 tests/ui/issues/issue-3763.stderr create mode 100644 tests/ui/issues/issue-37665.rs create mode 100644 tests/ui/issues/issue-37665.stderr create mode 100644 tests/ui/issues/issue-37686.rs create mode 100644 tests/ui/issues/issue-37725.rs create mode 100644 tests/ui/issues/issue-37733.rs create mode 100644 tests/ui/issues/issue-3779.rs create mode 100644 tests/ui/issues/issue-3779.stderr create mode 100644 tests/ui/issues/issue-37884.rs create mode 100644 tests/ui/issues/issue-37884.stderr create mode 100644 tests/ui/issues/issue-3794.rs create mode 100644 tests/ui/issues/issue-38160.rs create mode 100644 tests/ui/issues/issue-38190.rs create mode 100644 tests/ui/issues/issue-38226.rs create mode 100644 tests/ui/issues/issue-38381.rs create mode 100644 tests/ui/issues/issue-38412.rs create mode 100644 tests/ui/issues/issue-38412.stderr create mode 100644 tests/ui/issues/issue-38437.rs create mode 100644 tests/ui/issues/issue-38458.rs create mode 100644 tests/ui/issues/issue-38458.stderr create mode 100644 tests/ui/issues/issue-3847.rs create mode 100644 tests/ui/issues/issue-38556.rs create mode 100644 tests/ui/issues/issue-38727.rs create mode 100644 tests/ui/issues/issue-3874.rs create mode 100644 tests/ui/issues/issue-38763.rs create mode 100644 tests/ui/issues/issue-3878.rs create mode 100644 tests/ui/issues/issue-38821.rs create mode 100644 tests/ui/issues/issue-38821.stderr create mode 100644 tests/ui/issues/issue-38857.rs create mode 100644 tests/ui/issues/issue-38857.stderr create mode 100644 tests/ui/issues/issue-38875/auxiliary/issue-38875-b.rs create mode 100644 tests/ui/issues/issue-38875/issue-38875.rs create mode 100644 tests/ui/issues/issue-3888-2.rs create mode 100644 tests/ui/issues/issue-38919.rs create mode 100644 tests/ui/issues/issue-38919.stderr create mode 100644 tests/ui/issues/issue-38942.rs create mode 100644 tests/ui/issues/issue-3895.rs create mode 100644 tests/ui/issues/issue-38954.rs create mode 100644 tests/ui/issues/issue-38954.stderr create mode 100644 tests/ui/issues/issue-38987.rs create mode 100644 tests/ui/issues/issue-39089.rs create mode 100644 tests/ui/issues/issue-39175.rs create mode 100644 tests/ui/issues/issue-39175.stderr create mode 100644 tests/ui/issues/issue-39211.rs create mode 100644 tests/ui/issues/issue-39211.stderr create mode 100644 tests/ui/issues/issue-39292.rs create mode 100644 tests/ui/issues/issue-39367.rs create mode 100644 tests/ui/issues/issue-39467.rs create mode 100644 tests/ui/issues/issue-39548.rs create mode 100644 tests/ui/issues/issue-39687.rs create mode 100644 tests/ui/issues/issue-39687.stderr create mode 100644 tests/ui/issues/issue-39709.rs create mode 100644 tests/ui/issues/issue-3979-2.rs create mode 100644 tests/ui/issues/issue-3979-generics.rs create mode 100644 tests/ui/issues/issue-3979-xcrate.rs create mode 100644 tests/ui/issues/issue-3979.rs create mode 100644 tests/ui/issues/issue-39808.rs create mode 100644 tests/ui/issues/issue-39827.rs create mode 100644 tests/ui/issues/issue-39848.rs create mode 100644 tests/ui/issues/issue-39848.stderr create mode 100644 tests/ui/issues/issue-3991.rs create mode 100644 tests/ui/issues/issue-3993.rs create mode 100644 tests/ui/issues/issue-3993.stderr create mode 100644 tests/ui/issues/issue-39970.rs create mode 100644 tests/ui/issues/issue-39970.stderr create mode 100644 tests/ui/issues/issue-39984.rs create mode 100644 tests/ui/issues/issue-40000.rs create mode 100644 tests/ui/issues/issue-40000.stderr create mode 100644 tests/ui/issues/issue-40003.rs create mode 100644 tests/ui/issues/issue-40085.rs create mode 100644 tests/ui/issues/issue-40136.rs create mode 100644 tests/ui/issues/issue-40235.rs create mode 100644 tests/ui/issues/issue-4025.rs create mode 100644 tests/ui/issues/issue-40288-2.rs create mode 100644 tests/ui/issues/issue-40288-2.stderr create mode 100644 tests/ui/issues/issue-40288.rs create mode 100644 tests/ui/issues/issue-40288.stderr create mode 100644 tests/ui/issues/issue-40350.rs create mode 100644 tests/ui/issues/issue-40402-ref-hints/issue-40402-1.rs create mode 100644 tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr create mode 100644 tests/ui/issues/issue-40402-ref-hints/issue-40402-2.rs create mode 100644 tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr create mode 100644 tests/ui/issues/issue-40408.rs create mode 100644 tests/ui/issues/issue-40510-1.migrate.stderr create mode 100644 tests/ui/issues/issue-40510-1.rs create mode 100644 tests/ui/issues/issue-40510-1.stderr create mode 100644 tests/ui/issues/issue-40510-2.rs create mode 100644 tests/ui/issues/issue-40510-3.migrate.stderr create mode 100644 tests/ui/issues/issue-40510-3.rs create mode 100644 tests/ui/issues/issue-40510-3.stderr create mode 100644 tests/ui/issues/issue-40510-4.rs create mode 100644 tests/ui/issues/issue-40610.rs create mode 100644 tests/ui/issues/issue-40610.stderr create mode 100644 tests/ui/issues/issue-40749.rs create mode 100644 tests/ui/issues/issue-40749.stderr create mode 100644 tests/ui/issues/issue-40782.fixed create mode 100644 tests/ui/issues/issue-40782.rs create mode 100644 tests/ui/issues/issue-40782.stderr create mode 100644 tests/ui/issues/issue-40827.rs create mode 100644 tests/ui/issues/issue-40827.stderr create mode 100644 tests/ui/issues/issue-40845.rs create mode 100644 tests/ui/issues/issue-40845.stderr create mode 100644 tests/ui/issues/issue-40861.rs create mode 100644 tests/ui/issues/issue-40861.stderr create mode 100644 tests/ui/issues/issue-40883.rs create mode 100644 tests/ui/issues/issue-40951.rs create mode 100644 tests/ui/issues/issue-41053.rs create mode 100644 tests/ui/issues/issue-41139.rs create mode 100644 tests/ui/issues/issue-41139.stderr create mode 100644 tests/ui/issues/issue-41213.rs create mode 100644 tests/ui/issues/issue-41229-ref-str.rs create mode 100644 tests/ui/issues/issue-41229-ref-str.stderr create mode 100644 tests/ui/issues/issue-41272.rs create mode 100644 tests/ui/issues/issue-41298.rs create mode 100644 tests/ui/issues/issue-41394-rpass.rs create mode 100644 tests/ui/issues/issue-41394.rs create mode 100644 tests/ui/issues/issue-41394.stderr create mode 100644 tests/ui/issues/issue-41479.rs create mode 100644 tests/ui/issues/issue-41498.rs create mode 100644 tests/ui/issues/issue-41549.rs create mode 100644 tests/ui/issues/issue-41549.stderr create mode 100644 tests/ui/issues/issue-41604.rs create mode 100644 tests/ui/issues/issue-41628.rs create mode 100644 tests/ui/issues/issue-41652/auxiliary/issue-41652-b.rs create mode 100644 tests/ui/issues/issue-41652/issue-41652.rs create mode 100644 tests/ui/issues/issue-41652/issue-41652.stderr create mode 100644 tests/ui/issues/issue-41677.rs create mode 100644 tests/ui/issues/issue-41696.rs create mode 100644 tests/ui/issues/issue-41726.rs create mode 100644 tests/ui/issues/issue-41726.stderr create mode 100644 tests/ui/issues/issue-41742.rs create mode 100644 tests/ui/issues/issue-41742.stderr create mode 100644 tests/ui/issues/issue-41744.rs create mode 100644 tests/ui/issues/issue-41849-variance-req.rs create mode 100644 tests/ui/issues/issue-41880.rs create mode 100644 tests/ui/issues/issue-41880.stderr create mode 100644 tests/ui/issues/issue-41888.rs create mode 100644 tests/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs create mode 100644 tests/ui/issues/issue-41974.rs create mode 100644 tests/ui/issues/issue-41974.stderr create mode 100644 tests/ui/issues/issue-41998.rs create mode 100644 tests/ui/issues/issue-42007.rs create mode 100644 tests/ui/issues/issue-4208.rs create mode 100644 tests/ui/issues/issue-42106.rs create mode 100644 tests/ui/issues/issue-42106.stderr create mode 100644 tests/ui/issues/issue-42148.rs create mode 100644 tests/ui/issues/issue-42210.rs create mode 100644 tests/ui/issues/issue-4228.rs create mode 100644 tests/ui/issues/issue-42312.rs create mode 100644 tests/ui/issues/issue-42312.stderr create mode 100644 tests/ui/issues/issue-42453.rs create mode 100644 tests/ui/issues/issue-42467.rs create mode 100644 tests/ui/issues/issue-4252.rs create mode 100644 tests/ui/issues/issue-42552.rs create mode 100644 tests/ui/issues/issue-4265.rs create mode 100644 tests/ui/issues/issue-4265.stderr create mode 100644 tests/ui/issues/issue-42755.rs create mode 100644 tests/ui/issues/issue-42755.stderr create mode 100644 tests/ui/issues/issue-42796.rs create mode 100644 tests/ui/issues/issue-42796.stderr create mode 100644 tests/ui/issues/issue-42880.rs create mode 100644 tests/ui/issues/issue-42880.stderr create mode 100644 tests/ui/issues/issue-42956.rs create mode 100644 tests/ui/issues/issue-43057.rs create mode 100644 tests/ui/issues/issue-43162.rs create mode 100644 tests/ui/issues/issue-43162.stderr create mode 100644 tests/ui/issues/issue-43205.rs create mode 100644 tests/ui/issues/issue-43250.rs create mode 100644 tests/ui/issues/issue-43250.stderr create mode 100644 tests/ui/issues/issue-43291.rs create mode 100644 tests/ui/issues/issue-4333.rs create mode 100644 tests/ui/issues/issue-4335.rs create mode 100644 tests/ui/issues/issue-4335.stderr create mode 100644 tests/ui/issues/issue-43355.rs create mode 100644 tests/ui/issues/issue-43355.stderr create mode 100644 tests/ui/issues/issue-43357.rs create mode 100644 tests/ui/issues/issue-43420-no-over-suggest.rs create mode 100644 tests/ui/issues/issue-43420-no-over-suggest.stderr create mode 100644 tests/ui/issues/issue-43424.rs create mode 100644 tests/ui/issues/issue-43424.stderr create mode 100644 tests/ui/issues/issue-43431.rs create mode 100644 tests/ui/issues/issue-43431.stderr create mode 100644 tests/ui/issues/issue-43483.rs create mode 100644 tests/ui/issues/issue-43692.rs create mode 100644 tests/ui/issues/issue-43806.rs create mode 100644 tests/ui/issues/issue-43853.rs create mode 100644 tests/ui/issues/issue-4387.rs create mode 100644 tests/ui/issues/issue-43910.rs create mode 100644 tests/ui/issues/issue-43923.rs create mode 100644 tests/ui/issues/issue-43925.rs create mode 100644 tests/ui/issues/issue-43925.stderr create mode 100644 tests/ui/issues/issue-43926.rs create mode 100644 tests/ui/issues/issue-43926.stderr create mode 100644 tests/ui/issues/issue-43988.rs create mode 100644 tests/ui/issues/issue-43988.stderr create mode 100644 tests/ui/issues/issue-44023.rs create mode 100644 tests/ui/issues/issue-44023.stderr create mode 100644 tests/ui/issues/issue-44056.rs create mode 100644 tests/ui/issues/issue-44078.rs create mode 100644 tests/ui/issues/issue-44078.stderr create mode 100644 tests/ui/issues/issue-44216-add-instant.rs create mode 100644 tests/ui/issues/issue-44216-add-system-time.rs create mode 100644 tests/ui/issues/issue-44216-sub-instant.rs create mode 100644 tests/ui/issues/issue-44216-sub-system-time.rs create mode 100644 tests/ui/issues/issue-44239.fixed create mode 100644 tests/ui/issues/issue-44239.rs create mode 100644 tests/ui/issues/issue-44239.stderr create mode 100644 tests/ui/issues/issue-44247.rs create mode 100644 tests/ui/issues/issue-44255.rs create mode 100644 tests/ui/issues/issue-44405.rs create mode 100644 tests/ui/issues/issue-44405.stderr create mode 100644 tests/ui/issues/issue-4464.rs create mode 100644 tests/ui/issues/issue-44730.rs create mode 100644 tests/ui/issues/issue-44851.rs create mode 100644 tests/ui/issues/issue-4517.rs create mode 100644 tests/ui/issues/issue-4517.stderr create mode 100644 tests/ui/issues/issue-4541.rs create mode 100644 tests/ui/issues/issue-4542.rs create mode 100644 tests/ui/issues/issue-45425.rs create mode 100644 tests/ui/issues/issue-4545.rs create mode 100644 tests/ui/issues/issue-45510.rs create mode 100644 tests/ui/issues/issue-45562.fixed create mode 100644 tests/ui/issues/issue-45562.rs create mode 100644 tests/ui/issues/issue-45562.stderr create mode 100644 tests/ui/issues/issue-45697-1.rs create mode 100644 tests/ui/issues/issue-45697-1.stderr create mode 100644 tests/ui/issues/issue-45697.rs create mode 100644 tests/ui/issues/issue-45697.stderr create mode 100644 tests/ui/issues/issue-45730.rs create mode 100644 tests/ui/issues/issue-45730.stderr create mode 100644 tests/ui/issues/issue-45731.rs create mode 100644 tests/ui/issues/issue-45801.rs create mode 100644 tests/ui/issues/issue-45801.stderr create mode 100644 tests/ui/issues/issue-45965.rs create mode 100644 tests/ui/issues/issue-45965.stderr create mode 100644 tests/ui/issues/issue-46069.rs create mode 100644 tests/ui/issues/issue-46101.rs create mode 100644 tests/ui/issues/issue-46101.stderr create mode 100644 tests/ui/issues/issue-46302.rs create mode 100644 tests/ui/issues/issue-46302.stderr create mode 100644 tests/ui/issues/issue-46311.rs create mode 100644 tests/ui/issues/issue-46311.stderr create mode 100644 tests/ui/issues/issue-46332.rs create mode 100644 tests/ui/issues/issue-46332.stderr create mode 100644 tests/ui/issues/issue-46438.rs create mode 100644 tests/ui/issues/issue-46438.stderr create mode 100644 tests/ui/issues/issue-46471-1.rs create mode 100644 tests/ui/issues/issue-46471-1.stderr create mode 100644 tests/ui/issues/issue-46472.rs create mode 100644 tests/ui/issues/issue-46472.stderr create mode 100644 tests/ui/issues/issue-46604.rs create mode 100644 tests/ui/issues/issue-46604.stderr create mode 100644 tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed create mode 100644 tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs create mode 100644 tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr create mode 100644 tests/ui/issues/issue-46771.rs create mode 100644 tests/ui/issues/issue-46771.stderr create mode 100644 tests/ui/issues/issue-46855.rs create mode 100644 tests/ui/issues/issue-46964.rs create mode 100644 tests/ui/issues/issue-46983.rs create mode 100644 tests/ui/issues/issue-46983.stderr create mode 100644 tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs create mode 100644 tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr create mode 100644 tests/ui/issues/issue-47094.rs create mode 100644 tests/ui/issues/issue-47094.stderr create mode 100644 tests/ui/issues/issue-47184.rs create mode 100644 tests/ui/issues/issue-47184.stderr create mode 100644 tests/ui/issues/issue-47309.rs create mode 100644 tests/ui/issues/issue-4734.rs create mode 100644 tests/ui/issues/issue-4735.rs create mode 100644 tests/ui/issues/issue-4736.rs create mode 100644 tests/ui/issues/issue-4736.stderr create mode 100644 tests/ui/issues/issue-47364.rs create mode 100644 tests/ui/issues/issue-47377.rs create mode 100644 tests/ui/issues/issue-47377.stderr create mode 100644 tests/ui/issues/issue-47380.rs create mode 100644 tests/ui/issues/issue-47380.stderr create mode 100644 tests/ui/issues/issue-47486.rs create mode 100644 tests/ui/issues/issue-47486.stderr create mode 100644 tests/ui/issues/issue-4759-1.rs create mode 100644 tests/ui/issues/issue-4759.rs create mode 100644 tests/ui/issues/issue-47638.rs create mode 100644 tests/ui/issues/issue-47646.rs create mode 100644 tests/ui/issues/issue-47646.stderr create mode 100644 tests/ui/issues/issue-47673.rs create mode 100644 tests/ui/issues/issue-47703-1.rs create mode 100644 tests/ui/issues/issue-47703-tuple.rs create mode 100644 tests/ui/issues/issue-47703.rs create mode 100644 tests/ui/issues/issue-47715.rs create mode 100644 tests/ui/issues/issue-47715.stderr create mode 100644 tests/ui/issues/issue-47722.rs create mode 100644 tests/ui/issues/issue-47725.rs create mode 100644 tests/ui/issues/issue-47725.stderr create mode 100644 tests/ui/issues/issue-48006.rs create mode 100644 tests/ui/issues/issue-48131.mir.stderr create mode 100644 tests/ui/issues/issue-48131.rs create mode 100644 tests/ui/issues/issue-48131.thir.stderr create mode 100644 tests/ui/issues/issue-48132.rs create mode 100644 tests/ui/issues/issue-48159.rs create mode 100644 tests/ui/issues/issue-48179.rs create mode 100644 tests/ui/issues/issue-48276.rs create mode 100644 tests/ui/issues/issue-48276.stderr create mode 100644 tests/ui/issues/issue-4830.rs create mode 100644 tests/ui/issues/issue-48364.rs create mode 100644 tests/ui/issues/issue-48364.stderr create mode 100644 tests/ui/issues/issue-48728.rs create mode 100644 tests/ui/issues/issue-48728.stderr create mode 100644 tests/ui/issues/issue-4875.rs create mode 100644 tests/ui/issues/issue-48838.rs create mode 100644 tests/ui/issues/issue-48838.stderr create mode 100644 tests/ui/issues/issue-48984.rs create mode 100644 tests/ui/issues/issue-49298.rs create mode 100644 tests/ui/issues/issue-4935.rs create mode 100644 tests/ui/issues/issue-4935.stderr create mode 100644 tests/ui/issues/issue-49544.rs create mode 100644 tests/ui/issues/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs create mode 100644 tests/ui/issues/issue-49632.rs create mode 100644 tests/ui/issues/issue-4968.rs create mode 100644 tests/ui/issues/issue-4968.stderr create mode 100644 tests/ui/issues/issue-4972.rs create mode 100644 tests/ui/issues/issue-4972.stderr create mode 100644 tests/ui/issues/issue-49824.rs create mode 100644 tests/ui/issues/issue-49824.stderr create mode 100644 tests/ui/issues/issue-49851/compiler-builtins-error.rs create mode 100644 tests/ui/issues/issue-49851/compiler-builtins-error.stderr create mode 100644 tests/ui/issues/issue-49854.rs create mode 100644 tests/ui/issues/issue-49919.rs create mode 100644 tests/ui/issues/issue-49919.stderr create mode 100644 tests/ui/issues/issue-49934-errors.rs create mode 100644 tests/ui/issues/issue-49934-errors.stderr create mode 100644 tests/ui/issues/issue-49934.rs create mode 100644 tests/ui/issues/issue-49934.stderr create mode 100644 tests/ui/issues/issue-49955.rs create mode 100644 tests/ui/issues/issue-49973.rs create mode 100644 tests/ui/issues/issue-5008-borrowed-traitobject-method-call.rs create mode 100644 tests/ui/issues/issue-50187.rs create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs create mode 100644 tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr create mode 100644 tests/ui/issues/issue-50403.rs create mode 100644 tests/ui/issues/issue-50403.stderr create mode 100644 tests/ui/issues/issue-50411.rs create mode 100644 tests/ui/issues/issue-50415.rs create mode 100644 tests/ui/issues/issue-50442.rs create mode 100644 tests/ui/issues/issue-50471.rs create mode 100644 tests/ui/issues/issue-50518.rs create mode 100644 tests/ui/issues/issue-50571.fixed create mode 100644 tests/ui/issues/issue-50571.rs create mode 100644 tests/ui/issues/issue-50571.stderr create mode 100644 tests/ui/issues/issue-50576.rs create mode 100644 tests/ui/issues/issue-50576.stderr create mode 100644 tests/ui/issues/issue-50581.rs create mode 100644 tests/ui/issues/issue-50581.stderr create mode 100644 tests/ui/issues/issue-50582.rs create mode 100644 tests/ui/issues/issue-50582.stderr create mode 100644 tests/ui/issues/issue-50585.rs create mode 100644 tests/ui/issues/issue-50585.stderr create mode 100644 tests/ui/issues/issue-50600.rs create mode 100644 tests/ui/issues/issue-50600.stderr create mode 100644 tests/ui/issues/issue-50618.rs create mode 100644 tests/ui/issues/issue-50618.stderr create mode 100644 tests/ui/issues/issue-5062.rs create mode 100644 tests/ui/issues/issue-5062.stderr create mode 100644 tests/ui/issues/issue-5067.rs create mode 100644 tests/ui/issues/issue-5067.stderr create mode 100644 tests/ui/issues/issue-50688.rs create mode 100644 tests/ui/issues/issue-50688.stderr create mode 100644 tests/ui/issues/issue-50689.rs create mode 100644 tests/ui/issues/issue-50714-1.rs create mode 100644 tests/ui/issues/issue-50714-1.stderr create mode 100644 tests/ui/issues/issue-50714.rs create mode 100644 tests/ui/issues/issue-50714.stderr create mode 100644 tests/ui/issues/issue-50761.rs create mode 100644 tests/ui/issues/issue-50781.rs create mode 100644 tests/ui/issues/issue-50781.stderr create mode 100644 tests/ui/issues/issue-50802.rs create mode 100644 tests/ui/issues/issue-50802.stderr create mode 100644 tests/ui/issues/issue-50811.rs create mode 100644 tests/ui/issues/issue-50825-1.rs create mode 100644 tests/ui/issues/issue-50825.rs create mode 100644 tests/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs create mode 100644 tests/ui/issues/issue-50865-private-impl-trait/main.rs create mode 100644 tests/ui/issues/issue-5100.rs create mode 100644 tests/ui/issues/issue-5100.stderr create mode 100644 tests/ui/issues/issue-51022.rs create mode 100644 tests/ui/issues/issue-51022.stderr create mode 100644 tests/ui/issues/issue-51044.rs create mode 100644 tests/ui/issues/issue-51102.rs create mode 100644 tests/ui/issues/issue-51102.stderr create mode 100644 tests/ui/issues/issue-51116.rs create mode 100644 tests/ui/issues/issue-51116.stderr create mode 100644 tests/ui/issues/issue-51154.rs create mode 100644 tests/ui/issues/issue-51154.stderr create mode 100644 tests/ui/issues/issue-51515.rs create mode 100644 tests/ui/issues/issue-51515.stderr create mode 100644 tests/ui/issues/issue-5153.rs create mode 100644 tests/ui/issues/issue-5153.stderr create mode 100644 tests/ui/issues/issue-51632-try-desugar-incompatible-types.rs create mode 100644 tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr create mode 100644 tests/ui/issues/issue-51655.rs create mode 100644 tests/ui/issues/issue-51714.rs create mode 100644 tests/ui/issues/issue-51714.stderr create mode 100644 tests/ui/issues/issue-51798.rs create mode 100644 tests/ui/issues/issue-51874.rs create mode 100644 tests/ui/issues/issue-51874.stderr create mode 100644 tests/ui/issues/issue-51907.rs create mode 100644 tests/ui/issues/issue-5192.rs create mode 100644 tests/ui/issues/issue-51947.rs create mode 100644 tests/ui/issues/issue-52049.rs create mode 100644 tests/ui/issues/issue-52049.stderr create mode 100644 tests/ui/issues/issue-52126-assign-op-invariance.rs create mode 100644 tests/ui/issues/issue-52126-assign-op-invariance.stderr create mode 100644 tests/ui/issues/issue-52140/auxiliary/some_crate.rs create mode 100644 tests/ui/issues/issue-52140/main.rs create mode 100644 tests/ui/issues/issue-52141/auxiliary/some_crate.rs create mode 100644 tests/ui/issues/issue-52141/main.rs create mode 100644 tests/ui/issues/issue-52262.rs create mode 100644 tests/ui/issues/issue-52262.stderr create mode 100644 tests/ui/issues/issue-5239-1.rs create mode 100644 tests/ui/issues/issue-5239-1.stderr create mode 100644 tests/ui/issues/issue-5239-2.rs create mode 100644 tests/ui/issues/issue-52489.rs create mode 100644 tests/ui/issues/issue-52489.stderr create mode 100644 tests/ui/issues/issue-52533.rs create mode 100644 tests/ui/issues/issue-52533.stderr create mode 100644 tests/ui/issues/issue-52705/auxiliary/png2.rs create mode 100644 tests/ui/issues/issue-52705/main.rs create mode 100644 tests/ui/issues/issue-52717.rs create mode 100644 tests/ui/issues/issue-52717.stderr create mode 100644 tests/ui/issues/issue-5280.rs create mode 100644 tests/ui/issues/issue-5315.rs create mode 100644 tests/ui/issues/issue-5321-immediates-with-bare-self.rs create mode 100644 tests/ui/issues/issue-53251.rs create mode 100644 tests/ui/issues/issue-53251.stderr create mode 100644 tests/ui/issues/issue-53275.rs create mode 100644 tests/ui/issues/issue-53300.rs create mode 100644 tests/ui/issues/issue-53300.stderr create mode 100644 tests/ui/issues/issue-53333.rs create mode 100644 tests/ui/issues/issue-53348.rs create mode 100644 tests/ui/issues/issue-53348.stderr create mode 100644 tests/ui/issues/issue-53419.rs create mode 100644 tests/ui/issues/issue-53498.rs create mode 100644 tests/ui/issues/issue-53498.stderr create mode 100644 tests/ui/issues/issue-53568.rs create mode 100644 tests/ui/issues/issue-5358-1.rs create mode 100644 tests/ui/issues/issue-5358-1.stderr create mode 100644 tests/ui/issues/issue-53712.rs create mode 100644 tests/ui/issues/issue-53712.stderr create mode 100644 tests/ui/issues/issue-53728.rs create mode 100644 tests/ui/issues/issue-53843.rs create mode 100644 tests/ui/issues/issue-54044.rs create mode 100644 tests/ui/issues/issue-54044.stderr create mode 100644 tests/ui/issues/issue-54062.rs create mode 100644 tests/ui/issues/issue-54062.stderr create mode 100644 tests/ui/issues/issue-54094.rs create mode 100644 tests/ui/issues/issue-54302-cases.rs create mode 100644 tests/ui/issues/issue-54302-cases.stderr create mode 100644 tests/ui/issues/issue-54302.rs create mode 100644 tests/ui/issues/issue-54302.stderr create mode 100644 tests/ui/issues/issue-5439.rs create mode 100644 tests/ui/issues/issue-5439.stderr create mode 100644 tests/ui/issues/issue-54410.rs create mode 100644 tests/ui/issues/issue-54410.stderr create mode 100644 tests/ui/issues/issue-54462-mutable-noalias-correctness.rs create mode 100644 tests/ui/issues/issue-54477-reduced-2.rs create mode 100644 tests/ui/issues/issue-54582.rs create mode 100644 tests/ui/issues/issue-54696.rs create mode 100644 tests/ui/issues/issue-5518.rs create mode 100644 tests/ui/issues/issue-5521.rs create mode 100644 tests/ui/issues/issue-55376.rs create mode 100644 tests/ui/issues/issue-55380.rs create mode 100644 tests/ui/issues/issue-55380.stderr create mode 100644 tests/ui/issues/issue-5550.rs create mode 100644 tests/ui/issues/issue-5554.rs create mode 100644 tests/ui/issues/issue-55587.rs create mode 100644 tests/ui/issues/issue-55587.stderr create mode 100644 tests/ui/issues/issue-5572.rs create mode 100644 tests/ui/issues/issue-55731.rs create mode 100644 tests/ui/issues/issue-55731.stderr create mode 100644 tests/ui/issues/issue-56128.rs create mode 100644 tests/ui/issues/issue-56175.rs create mode 100644 tests/ui/issues/issue-56175.stderr create mode 100644 tests/ui/issues/issue-56199.rs create mode 100644 tests/ui/issues/issue-56199.stderr create mode 100644 tests/ui/issues/issue-56229.rs create mode 100644 tests/ui/issues/issue-56237.rs create mode 100644 tests/ui/issues/issue-5666.rs create mode 100644 tests/ui/issues/issue-56806.rs create mode 100644 tests/ui/issues/issue-56806.stderr create mode 100644 tests/ui/issues/issue-56835.rs create mode 100644 tests/ui/issues/issue-56835.stderr create mode 100644 tests/ui/issues/issue-56870.rs create mode 100644 tests/ui/issues/issue-5688.rs create mode 100644 tests/ui/issues/issue-56943.rs create mode 100644 tests/ui/issues/issue-56943.stderr create mode 100644 tests/ui/issues/issue-5708.rs create mode 100644 tests/ui/issues/issue-57156.rs create mode 100644 tests/ui/issues/issue-57162.rs create mode 100644 tests/ui/issues/issue-5718.rs create mode 100644 tests/ui/issues/issue-57198-pass.rs create mode 100644 tests/ui/issues/issue-57271.rs create mode 100644 tests/ui/issues/issue-57271.stderr create mode 100644 tests/ui/issues/issue-57362-1.rs create mode 100644 tests/ui/issues/issue-57362-1.stderr create mode 100644 tests/ui/issues/issue-57362-2.rs create mode 100644 tests/ui/issues/issue-57362-2.stderr create mode 100644 tests/ui/issues/issue-57399-self-return-impl-trait.rs create mode 100644 tests/ui/issues/issue-5741.rs create mode 100644 tests/ui/issues/issue-5754.rs create mode 100644 tests/ui/issues/issue-57741-1.rs create mode 100644 tests/ui/issues/issue-57741-1.stderr create mode 100644 tests/ui/issues/issue-57741.fixed create mode 100644 tests/ui/issues/issue-57741.rs create mode 100644 tests/ui/issues/issue-57741.stderr create mode 100644 tests/ui/issues/issue-57781.rs create mode 100644 tests/ui/issues/issue-57924.rs create mode 100644 tests/ui/issues/issue-57924.stderr create mode 100644 tests/ui/issues/issue-58212.rs create mode 100644 tests/ui/issues/issue-58344.rs create mode 100644 tests/ui/issues/issue-58375-monomorphize-default-impls.rs create mode 100644 tests/ui/issues/issue-5844.mir.stderr create mode 100644 tests/ui/issues/issue-5844.rs create mode 100644 tests/ui/issues/issue-5844.thir.stderr create mode 100644 tests/ui/issues/issue-58463.rs create mode 100644 tests/ui/issues/issue-58712.rs create mode 100644 tests/ui/issues/issue-58712.stderr create mode 100644 tests/ui/issues/issue-58734.rs create mode 100644 tests/ui/issues/issue-58734.stderr create mode 100644 tests/ui/issues/issue-5883.rs create mode 100644 tests/ui/issues/issue-5883.stderr create mode 100644 tests/ui/issues/issue-5884.rs create mode 100644 tests/ui/issues/issue-58857.rs create mode 100644 tests/ui/issues/issue-58857.stderr create mode 100644 tests/ui/issues/issue-5900.rs create mode 100644 tests/ui/issues/issue-59020.rs create mode 100644 tests/ui/issues/issue-5917.rs create mode 100644 tests/ui/issues/issue-59326.rs create mode 100644 tests/ui/issues/issue-59488.rs create mode 100644 tests/ui/issues/issue-59488.stderr create mode 100644 tests/ui/issues/issue-59494.rs create mode 100644 tests/ui/issues/issue-59494.stderr create mode 100644 tests/ui/issues/issue-5950.rs create mode 100644 tests/ui/issues/issue-59756.fixed create mode 100644 tests/ui/issues/issue-59756.rs create mode 100644 tests/ui/issues/issue-59756.stderr create mode 100644 tests/ui/issues/issue-5988.rs create mode 100644 tests/ui/issues/issue-5997-enum.rs create mode 100644 tests/ui/issues/issue-5997-enum.stderr create mode 100644 tests/ui/issues/issue-5997-struct.rs create mode 100644 tests/ui/issues/issue-5997-struct.stderr create mode 100644 tests/ui/issues/issue-5997.rs create mode 100644 tests/ui/issues/issue-60218.rs create mode 100644 tests/ui/issues/issue-60218.stderr create mode 100644 tests/ui/issues/issue-60622.rs create mode 100644 tests/ui/issues/issue-60622.stderr create mode 100644 tests/ui/issues/issue-60989.rs create mode 100644 tests/ui/issues/issue-60989.stderr create mode 100644 tests/ui/issues/issue-61106.rs create mode 100644 tests/ui/issues/issue-61106.stderr create mode 100644 tests/ui/issues/issue-61108.rs create mode 100644 tests/ui/issues/issue-61108.stderr create mode 100644 tests/ui/issues/issue-6117.rs create mode 100644 tests/ui/issues/issue-6130.rs create mode 100644 tests/ui/issues/issue-61475.rs create mode 100644 tests/ui/issues/issue-6153.rs create mode 100644 tests/ui/issues/issue-61623.rs create mode 100644 tests/ui/issues/issue-61623.stderr create mode 100644 tests/ui/issues/issue-61696.rs create mode 100644 tests/ui/issues/issue-61894.rs create mode 100644 tests/ui/issues/issue-62375.rs create mode 100644 tests/ui/issues/issue-62375.stderr create mode 100644 tests/ui/issues/issue-62480.rs create mode 100644 tests/ui/issues/issue-62480.stderr create mode 100644 tests/ui/issues/issue-6318.rs create mode 100644 tests/ui/issues/issue-6344-let.rs create mode 100644 tests/ui/issues/issue-6344-match.rs create mode 100644 tests/ui/issues/issue-63983.rs create mode 100644 tests/ui/issues/issue-63983.stderr create mode 100644 tests/ui/issues/issue-64430.rs create mode 100644 tests/ui/issues/issue-64430.stderr create mode 100644 tests/ui/issues/issue-64559.rs create mode 100644 tests/ui/issues/issue-64559.stderr create mode 100644 tests/ui/issues/issue-6458-1.rs create mode 100644 tests/ui/issues/issue-6458-2.rs create mode 100644 tests/ui/issues/issue-6458-2.stderr create mode 100644 tests/ui/issues/issue-6458-3.rs create mode 100644 tests/ui/issues/issue-6458-3.stderr create mode 100644 tests/ui/issues/issue-6458-4.rs create mode 100644 tests/ui/issues/issue-6458-4.stderr create mode 100644 tests/ui/issues/issue-6458.rs create mode 100644 tests/ui/issues/issue-6458.stderr create mode 100644 tests/ui/issues/issue-64593.rs create mode 100644 tests/ui/issues/issue-64792-bad-unicode-ctor.rs create mode 100644 tests/ui/issues/issue-64792-bad-unicode-ctor.stderr create mode 100644 tests/ui/issues/issue-65131.rs create mode 100644 tests/ui/issues/issue-65131.stderr create mode 100644 tests/ui/issues/issue-65230.rs create mode 100644 tests/ui/issues/issue-65230.stderr create mode 100644 tests/ui/issues/issue-65462.rs create mode 100644 tests/ui/issues/issue-6557.rs create mode 100644 tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr create mode 100644 tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr create mode 100644 tests/ui/issues/issue-65634-raw-ident-suggestion.rs create mode 100644 tests/ui/issues/issue-6596-2.rs create mode 100644 tests/ui/issues/issue-6596-2.stderr create mode 100644 tests/ui/issues/issue-66308.rs create mode 100644 tests/ui/issues/issue-66353.rs create mode 100644 tests/ui/issues/issue-66353.stderr create mode 100644 tests/ui/issues/issue-6642.rs create mode 100644 tests/ui/issues/issue-6642.stderr create mode 100644 tests/ui/issues/issue-66667-function-cmp-cycle.rs create mode 100644 tests/ui/issues/issue-66667-function-cmp-cycle.stderr create mode 100644 tests/ui/issues/issue-66702-break-outside-loop-val.rs create mode 100644 tests/ui/issues/issue-66702-break-outside-loop-val.stderr create mode 100644 tests/ui/issues/issue-66706.rs create mode 100644 tests/ui/issues/issue-66706.stderr create mode 100644 tests/ui/issues/issue-66768.rs create mode 100644 tests/ui/issues/issue-66923-show-error-for-correct-call.rs create mode 100644 tests/ui/issues/issue-66923-show-error-for-correct-call.stderr create mode 100644 tests/ui/issues/issue-67039-unsound-pin-partialeq.rs create mode 100644 tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr create mode 100644 tests/ui/issues/issue-6738.rs create mode 100644 tests/ui/issues/issue-6738.stderr create mode 100644 tests/ui/issues/issue-67535.rs create mode 100644 tests/ui/issues/issue-67535.stderr create mode 100644 tests/ui/issues/issue-67552.polonius.stderr create mode 100644 tests/ui/issues/issue-67552.rs create mode 100644 tests/ui/issues/issue-67552.stderr create mode 100644 tests/ui/issues/issue-68010-large-zst-consts.rs create mode 100644 tests/ui/issues/issue-68696-catch-during-unwind.rs create mode 100644 tests/ui/issues/issue-6892.rs create mode 100644 tests/ui/issues/issue-68951.rs create mode 100644 tests/ui/issues/issue-6898.rs create mode 100644 tests/ui/issues/issue-69130.rs create mode 100644 tests/ui/issues/issue-69130.stderr create mode 100644 tests/ui/issues/issue-6919.rs create mode 100644 tests/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs create mode 100644 tests/ui/issues/issue-69225-layout-repeated-checked-add.rs create mode 100644 tests/ui/issues/issue-69306.rs create mode 100644 tests/ui/issues/issue-69306.stderr create mode 100644 tests/ui/issues/issue-6936.rs create mode 100644 tests/ui/issues/issue-6936.stderr create mode 100644 tests/ui/issues/issue-69396-const-no-type-in-macro.rs create mode 100644 tests/ui/issues/issue-69396-const-no-type-in-macro.stderr create mode 100644 tests/ui/issues/issue-69455.rs create mode 100644 tests/ui/issues/issue-69455.stderr create mode 100644 tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs create mode 100644 tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr create mode 100644 tests/ui/issues/issue-69683.rs create mode 100644 tests/ui/issues/issue-69683.stderr create mode 100644 tests/ui/issues/issue-70093.rs create mode 100644 tests/ui/issues/issue-7012.rs create mode 100644 tests/ui/issues/issue-70381.rs create mode 100644 tests/ui/issues/issue-70381.stderr create mode 100644 tests/ui/issues/issue-7044.rs create mode 100644 tests/ui/issues/issue-7044.stderr create mode 100644 tests/ui/issues/issue-7061.rs create mode 100644 tests/ui/issues/issue-7061.stderr create mode 100644 tests/ui/issues/issue-70673.rs create mode 100644 tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs create mode 100644 tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr create mode 100644 tests/ui/issues/issue-70746.rs create mode 100644 tests/ui/issues/issue-7092.rs create mode 100644 tests/ui/issues/issue-7092.stderr create mode 100644 tests/ui/issues/issue-71406.rs create mode 100644 tests/ui/issues/issue-71406.stderr create mode 100644 tests/ui/issues/issue-71584.rs create mode 100644 tests/ui/issues/issue-71584.stderr create mode 100644 tests/ui/issues/issue-71676-1.fixed create mode 100644 tests/ui/issues/issue-71676-1.rs create mode 100644 tests/ui/issues/issue-71676-1.stderr create mode 100644 tests/ui/issues/issue-71676-2.rs create mode 100644 tests/ui/issues/issue-71676-2.stderr create mode 100644 tests/ui/issues/issue-7178.rs create mode 100644 tests/ui/issues/issue-72002.rs create mode 100644 tests/ui/issues/issue-72076.rs create mode 100644 tests/ui/issues/issue-72076.stderr create mode 100644 tests/ui/issues/issue-72278.rs create mode 100644 tests/ui/issues/issue-72278.stderr create mode 100644 tests/ui/issues/issue-7246.rs create mode 100644 tests/ui/issues/issue-7246.stderr create mode 100644 tests/ui/issues/issue-7268.rs create mode 100644 tests/ui/issues/issue-72839-error-overflow.rs create mode 100644 tests/ui/issues/issue-72839-error-overflow.stderr create mode 100644 tests/ui/issues/issue-72933-match-stack-overflow.rs create mode 100644 tests/ui/issues/issue-73112.rs create mode 100644 tests/ui/issues/issue-73112.stderr create mode 100644 tests/ui/issues/issue-73229.rs create mode 100644 tests/ui/issues/issue-7344.rs create mode 100644 tests/ui/issues/issue-7364.rs create mode 100644 tests/ui/issues/issue-7364.stderr create mode 100644 tests/ui/issues/issue-74082.rs create mode 100644 tests/ui/issues/issue-74082.stderr create mode 100644 tests/ui/issues/issue-74236/auxiliary/dep.rs create mode 100644 tests/ui/issues/issue-74236/main.rs create mode 100644 tests/ui/issues/issue-74236/main.stderr create mode 100644 tests/ui/issues/issue-74564-if-expr-stack-overflow.rs create mode 100644 tests/ui/issues/issue-7519-match-unit-in-arg.rs create mode 100644 tests/ui/issues/issue-75283.rs create mode 100644 tests/ui/issues/issue-75283.stderr create mode 100644 tests/ui/issues/issue-75307.rs create mode 100644 tests/ui/issues/issue-75307.stderr create mode 100644 tests/ui/issues/issue-7563.rs create mode 100644 tests/ui/issues/issue-75704.rs create mode 100644 tests/ui/issues/issue-7575.rs create mode 100644 tests/ui/issues/issue-75777.rs create mode 100644 tests/ui/issues/issue-75777.stderr create mode 100644 tests/ui/issues/issue-76042.rs create mode 100644 tests/ui/issues/issue-7607-1.rs create mode 100644 tests/ui/issues/issue-7607-1.stderr create mode 100644 tests/ui/issues/issue-7607-2.rs create mode 100644 tests/ui/issues/issue-76077-1.fixed create mode 100644 tests/ui/issues/issue-76077-1.rs create mode 100644 tests/ui/issues/issue-76077-1.stderr create mode 100644 tests/ui/issues/issue-76077.rs create mode 100644 tests/ui/issues/issue-76077.stderr create mode 100644 tests/ui/issues/issue-76191.rs create mode 100644 tests/ui/issues/issue-76191.stderr create mode 100644 tests/ui/issues/issue-7660.rs create mode 100644 tests/ui/issues/issue-7663.rs create mode 100644 tests/ui/issues/issue-7673-cast-generically-implemented-trait.rs create mode 100644 tests/ui/issues/issue-77218/issue-77218-2.fixed create mode 100644 tests/ui/issues/issue-77218/issue-77218-2.rs create mode 100644 tests/ui/issues/issue-77218/issue-77218-2.stderr create mode 100644 tests/ui/issues/issue-77218/issue-77218.fixed create mode 100644 tests/ui/issues/issue-77218/issue-77218.rs create mode 100644 tests/ui/issues/issue-77218/issue-77218.stderr create mode 100644 tests/ui/issues/issue-7784.rs create mode 100644 tests/ui/issues/issue-77919.rs create mode 100644 tests/ui/issues/issue-77919.stderr create mode 100644 tests/ui/issues/issue-78115.rs create mode 100644 tests/ui/issues/issue-7813.rs create mode 100644 tests/ui/issues/issue-7813.stderr create mode 100644 tests/ui/issues/issue-78192.rs create mode 100644 tests/ui/issues/issue-78622.rs create mode 100644 tests/ui/issues/issue-78622.stderr create mode 100644 tests/ui/issues/issue-7867.rs create mode 100644 tests/ui/issues/issue-7867.stderr create mode 100644 tests/ui/issues/issue-78957.rs create mode 100644 tests/ui/issues/issue-78957.stderr create mode 100644 tests/ui/issues/issue-7899.rs create mode 100644 tests/ui/issues/issue-7911.rs create mode 100644 tests/ui/issues/issue-7950.rs create mode 100644 tests/ui/issues/issue-7950.stderr create mode 100644 tests/ui/issues/issue-7970a.rs create mode 100644 tests/ui/issues/issue-7970a.stderr create mode 100644 tests/ui/issues/issue-8044.rs create mode 100644 tests/ui/issues/issue-80607.rs create mode 100644 tests/ui/issues/issue-80607.stderr create mode 100644 tests/ui/issues/issue-81584.fixed create mode 100644 tests/ui/issues/issue-81584.rs create mode 100644 tests/ui/issues/issue-81584.stderr create mode 100644 tests/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs create mode 100644 tests/ui/issues/issue-81918.rs create mode 100644 tests/ui/issues/issue-8248.rs create mode 100644 tests/ui/issues/issue-8249.rs create mode 100644 tests/ui/issues/issue-8259.rs create mode 100644 tests/ui/issues/issue-82833-slice-miscompile.rs create mode 100644 tests/ui/issues/issue-83048.rs create mode 100644 tests/ui/issues/issue-83048.stderr create mode 100644 tests/ui/issues/issue-83190.rs create mode 100644 tests/ui/issues/issue-8391.rs create mode 100644 tests/ui/issues/issue-83924.fixed create mode 100644 tests/ui/issues/issue-83924.rs create mode 100644 tests/ui/issues/issue-83924.stderr create mode 100644 tests/ui/issues/issue-8398.rs create mode 100644 tests/ui/issues/issue-8401.rs create mode 100644 tests/ui/issues/issue-8498.rs create mode 100644 tests/ui/issues/issue-8506.rs create mode 100644 tests/ui/issues/issue-8521.rs create mode 100644 tests/ui/issues/issue-85461.rs create mode 100644 tests/ui/issues/issue-8578.rs create mode 100644 tests/ui/issues/issue-86756.rs create mode 100644 tests/ui/issues/issue-86756.stderr create mode 100644 tests/ui/issues/issue-868.rs create mode 100644 tests/ui/issues/issue-87199.rs create mode 100644 tests/ui/issues/issue-87199.stderr create mode 100644 tests/ui/issues/issue-8727.polonius.stderr create mode 100644 tests/ui/issues/issue-8727.rs create mode 100644 tests/ui/issues/issue-8727.stderr create mode 100644 tests/ui/issues/issue-87490.rs create mode 100644 tests/ui/issues/issue-87490.stderr create mode 100644 tests/ui/issues/issue-8761.rs create mode 100644 tests/ui/issues/issue-8761.stderr create mode 100644 tests/ui/issues/issue-8767.rs create mode 100644 tests/ui/issues/issue-8767.stderr create mode 100644 tests/ui/issues/issue-87707.rs create mode 100644 tests/ui/issues/issue-87707.run.stderr create mode 100644 tests/ui/issues/issue-8783.rs create mode 100644 tests/ui/issues/issue-88150.rs create mode 100644 tests/ui/issues/issue-8860.rs create mode 100644 tests/ui/issues/issue-8898.rs create mode 100644 tests/ui/issues/issue-9047.rs create mode 100644 tests/ui/issues/issue-9110.rs create mode 100644 tests/ui/issues/issue-9123.rs create mode 100644 tests/ui/issues/issue-9129.rs create mode 100644 tests/ui/issues/issue-91489.rs create mode 100644 tests/ui/issues/issue-9155.rs create mode 100644 tests/ui/issues/issue-9188.rs create mode 100644 tests/ui/issues/issue-9243.rs create mode 100644 tests/ui/issues/issue-9249.rs create mode 100644 tests/ui/issues/issue-9259.rs create mode 100644 tests/ui/issues/issue-9382.rs create mode 100644 tests/ui/issues/issue-9446.rs create mode 100644 tests/ui/issues/issue-948.rs create mode 100644 tests/ui/issues/issue-9575.rs create mode 100644 tests/ui/issues/issue-9575.stderr create mode 100644 tests/ui/issues/issue-9719.rs create mode 100644 tests/ui/issues/issue-9725.rs create mode 100644 tests/ui/issues/issue-9725.stderr create mode 100644 tests/ui/issues/issue-9737.rs create mode 100644 tests/ui/issues/issue-979.rs create mode 100644 tests/ui/issues/issue-9814.rs create mode 100644 tests/ui/issues/issue-9814.stderr create mode 100644 tests/ui/issues/issue-98299.rs create mode 100644 tests/ui/issues/issue-98299.stderr create mode 100644 tests/ui/issues/issue-9837.rs create mode 100644 tests/ui/issues/issue-9906.rs create mode 100644 tests/ui/issues/issue-9918.rs create mode 100644 tests/ui/issues/issue-9942.rs create mode 100644 tests/ui/issues/issue-9951.rs create mode 100644 tests/ui/issues/issue-9968.rs create mode 100644 tests/ui/issues/issue-99838.rs create mode 100644 tests/ui/issues/issue-pr29383.rs create mode 100644 tests/ui/issues/issue-pr29383.stderr create mode 100644 tests/ui/item-name-overload.rs create mode 100644 tests/ui/iterators/array-of-ranges.rs create mode 100644 tests/ui/iterators/array.rs create mode 100644 tests/ui/iterators/bound.rs create mode 100644 tests/ui/iterators/bound.stderr create mode 100644 tests/ui/iterators/collect-into-array.rs create mode 100644 tests/ui/iterators/collect-into-array.stderr create mode 100644 tests/ui/iterators/collect-into-slice.rs create mode 100644 tests/ui/iterators/collect-into-slice.stderr create mode 100644 tests/ui/iterators/float_iterator_hint.rs create mode 100644 tests/ui/iterators/float_iterator_hint.stderr create mode 100644 tests/ui/iterators/integral.rs create mode 100644 tests/ui/iterators/integral.stderr create mode 100644 tests/ui/iterators/into-iter-on-arrays-2018.rs create mode 100644 tests/ui/iterators/into-iter-on-arrays-2018.stderr create mode 100644 tests/ui/iterators/into-iter-on-arrays-2021.rs create mode 100644 tests/ui/iterators/into-iter-on-arrays-lint.fixed create mode 100644 tests/ui/iterators/into-iter-on-arrays-lint.rs create mode 100644 tests/ui/iterators/into-iter-on-arrays-lint.stderr create mode 100644 tests/ui/iterators/into-iterator-type-inference-shift.rs create mode 100644 tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs create mode 100644 tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr create mode 100644 tests/ui/iterators/invalid-iterator-chain.rs create mode 100644 tests/ui/iterators/invalid-iterator-chain.stderr create mode 100644 tests/ui/iterators/issue-28098.rs create mode 100644 tests/ui/iterators/issue-28098.stderr create mode 100644 tests/ui/iterators/issue-58952-filter-type-length.rs create mode 100644 tests/ui/iterators/iter-cloned-type-inference.rs create mode 100644 tests/ui/iterators/iter-count-overflow-debug.rs create mode 100644 tests/ui/iterators/iter-count-overflow-ndebug.rs create mode 100644 tests/ui/iterators/iter-map-fold-type-length.rs create mode 100644 tests/ui/iterators/iter-position-overflow-debug.rs create mode 100644 tests/ui/iterators/iter-position-overflow-ndebug.rs create mode 100644 tests/ui/iterators/iter-range.rs create mode 100644 tests/ui/iterators/iter-step-overflow-debug.rs create mode 100644 tests/ui/iterators/iter-step-overflow-ndebug.rs create mode 100644 tests/ui/iterators/iter-sum-overflow-debug.rs create mode 100644 tests/ui/iterators/iter-sum-overflow-ndebug.rs create mode 100644 tests/ui/iterators/iter-sum-overflow-overflow-checks.rs create mode 100644 tests/ui/iterators/ranges.rs create mode 100644 tests/ui/iterators/ranges.stderr create mode 100644 tests/ui/iterators/rsplit-clone.rs create mode 100644 tests/ui/iterators/skip-count-overflow.rs create mode 100644 tests/ui/iterators/string.rs create mode 100644 tests/ui/iterators/string.stderr create mode 100644 tests/ui/iterators/vec-on-unimplemented.rs create mode 100644 tests/ui/iterators/vec-on-unimplemented.stderr create mode 100644 tests/ui/json/json-and-color.rs create mode 100644 tests/ui/json/json-and-color.stderr create mode 100644 tests/ui/json/json-and-error-format.rs create mode 100644 tests/ui/json/json-and-error-format.stderr create mode 100644 tests/ui/json/json-bom-plus-crlf-multifile-aux.rs create mode 100644 tests/ui/json/json-bom-plus-crlf-multifile.rs create mode 100644 tests/ui/json/json-bom-plus-crlf-multifile.stderr create mode 100644 tests/ui/json/json-bom-plus-crlf.rs create mode 100644 tests/ui/json/json-bom-plus-crlf.stderr create mode 100644 tests/ui/json/json-invalid.rs create mode 100644 tests/ui/json/json-invalid.stderr create mode 100644 tests/ui/json/json-multiple.polonius.stderr create mode 100644 tests/ui/json/json-multiple.rs create mode 100644 tests/ui/json/json-multiple.stderr create mode 100644 tests/ui/json/json-options.polonius.stderr create mode 100644 tests/ui/json/json-options.rs create mode 100644 tests/ui/json/json-options.stderr create mode 100644 tests/ui/json/json-short.rs create mode 100644 tests/ui/json/json-short.stderr create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-expr.rs create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-pat.rs create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-type.rs create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-use.rs create mode 100644 tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr create mode 100644 tests/ui/keyword/keyword-false-as-identifier.rs create mode 100644 tests/ui/keyword/keyword-false-as-identifier.stderr create mode 100644 tests/ui/keyword/keyword-self-as-identifier.rs create mode 100644 tests/ui/keyword/keyword-self-as-identifier.stderr create mode 100644 tests/ui/keyword/keyword-self-as-type-param.rs create mode 100644 tests/ui/keyword/keyword-self-as-type-param.stderr create mode 100644 tests/ui/keyword/keyword-super-as-identifier.rs create mode 100644 tests/ui/keyword/keyword-super-as-identifier.stderr create mode 100644 tests/ui/keyword/keyword-super.rs create mode 100644 tests/ui/keyword/keyword-super.stderr create mode 100644 tests/ui/keyword/keyword-true-as-identifier.rs create mode 100644 tests/ui/keyword/keyword-true-as-identifier.stderr create mode 100644 tests/ui/kindck/kindck-copy.rs create mode 100644 tests/ui/kindck/kindck-copy.stderr create mode 100644 tests/ui/kindck/kindck-impl-type-params-2.rs create mode 100644 tests/ui/kindck/kindck-impl-type-params-2.stderr create mode 100644 tests/ui/kindck/kindck-impl-type-params.rs create mode 100644 tests/ui/kindck/kindck-impl-type-params.stderr create mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr create mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr create mode 100644 tests/ui/kindck/kindck-inherited-copy-bound.rs create mode 100644 tests/ui/kindck/kindck-nonsendable-1.rs create mode 100644 tests/ui/kindck/kindck-nonsendable-1.stderr create mode 100644 tests/ui/kindck/kindck-send-object.rs create mode 100644 tests/ui/kindck/kindck-send-object.stderr create mode 100644 tests/ui/kindck/kindck-send-object1.rs create mode 100644 tests/ui/kindck/kindck-send-object1.stderr create mode 100644 tests/ui/kindck/kindck-send-object2.rs create mode 100644 tests/ui/kindck/kindck-send-object2.stderr create mode 100644 tests/ui/kindck/kindck-send-owned.rs create mode 100644 tests/ui/kindck/kindck-send-owned.stderr create mode 100644 tests/ui/kindck/kindck-send-unsafe.rs create mode 100644 tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master create mode 100644 tests/ui/kindck/kindck-send-unsafe.stderr create mode 100644 tests/ui/kinds-in-metadata.rs create mode 100644 tests/ui/kinds-of-primitive-impl.rs create mode 100644 tests/ui/kinds-of-primitive-impl.stderr create mode 100644 tests/ui/label/label-beginning-with-underscore.rs create mode 100644 tests/ui/label/label-static.rs create mode 100644 tests/ui/label/label-static.stderr create mode 100644 tests/ui/label/label-underscore.rs create mode 100644 tests/ui/label/label-underscore.stderr create mode 100644 tests/ui/label/label_break_value_continue.rs create mode 100644 tests/ui/label/label_break_value_continue.stderr create mode 100644 tests/ui/label/label_break_value_desugared_break.rs create mode 100644 tests/ui/label/label_break_value_illegal_uses.fixed create mode 100644 tests/ui/label/label_break_value_illegal_uses.rs create mode 100644 tests/ui/label/label_break_value_illegal_uses.stderr create mode 100644 tests/ui/label/label_break_value_unlabeled_break.rs create mode 100644 tests/ui/label/label_break_value_unlabeled_break.stderr create mode 100644 tests/ui/label/label_misspelled.rs create mode 100644 tests/ui/label/label_misspelled.stderr create mode 100644 tests/ui/label/label_misspelled_2.rs create mode 100644 tests/ui/label/label_misspelled_2.stderr create mode 100644 tests/ui/lambda-infer-unresolved.rs create mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs create mode 100644 tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr create mode 100644 tests/ui/lang-items/issue-19660.rs create mode 100644 tests/ui/lang-items/issue-19660.stderr create mode 100644 tests/ui/lang-items/issue-31076.rs create mode 100644 tests/ui/lang-items/issue-31076.stderr create mode 100644 tests/ui/lang-items/issue-83471.rs create mode 100644 tests/ui/lang-items/issue-83471.stderr create mode 100644 tests/ui/lang-items/issue-86238.rs create mode 100644 tests/ui/lang-items/issue-86238.stderr create mode 100644 tests/ui/lang-items/issue-87573.rs create mode 100644 tests/ui/lang-items/issue-87573.stderr create mode 100644 tests/ui/lang-items/lang-item-generic-requirements.rs create mode 100644 tests/ui/lang-items/lang-item-generic-requirements.stderr create mode 100644 tests/ui/lang-items/lang-item-missing-generator.rs create mode 100644 tests/ui/lang-items/lang-item-missing-generator.stderr create mode 100644 tests/ui/lang-items/lang-item-missing.rs create mode 100644 tests/ui/lang-items/lang-item-missing.stderr create mode 100644 tests/ui/lang-items/missing-clone-for-suggestion.rs create mode 100644 tests/ui/lang-items/missing-clone-for-suggestion.stderr create mode 100644 tests/ui/lang-items/no_owned_box_lang_item.rs create mode 100644 tests/ui/lang-items/no_owned_box_lang_item.stderr create mode 100644 tests/ui/lang-items/required-lang-item.rs create mode 100644 tests/ui/lang-items/required-lang-item.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.argc.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.argv.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.main_args.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.main_ret.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.main_ty.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.missing_ret.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.rs create mode 100644 tests/ui/lang-items/start_lang_item_args.sigpipe.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.start_ret.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.too_many_args.stderr create mode 100644 tests/ui/last-use-in-block.rs create mode 100644 tests/ui/last-use-in-cap-clause.rs create mode 100644 tests/ui/last-use-is-capture.rs create mode 100644 tests/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs create mode 100644 tests/ui/late-bound-lifetimes/cross_crate_alias.rs create mode 100644 tests/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs create mode 100644 tests/ui/late-bound-lifetimes/issue-36381.rs create mode 100644 tests/ui/late-bound-lifetimes/issue-47511.rs create mode 100644 tests/ui/late-bound-lifetimes/late_bound_through_alias.rs create mode 100644 tests/ui/late-bound-lifetimes/mismatched_arg_count.rs create mode 100644 tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr create mode 100644 tests/ui/layout/big-type-no-err.rs create mode 100644 tests/ui/layout/debug.rs create mode 100644 tests/ui/layout/debug.stderr create mode 100644 tests/ui/layout/hexagon-enum.rs create mode 100644 tests/ui/layout/hexagon-enum.stderr create mode 100644 tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs create mode 100644 tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr create mode 100644 tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs create mode 100644 tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr create mode 100644 tests/ui/layout/issue-60431-unsized-tail-behind-projection.rs create mode 100644 tests/ui/layout/issue-84108.rs create mode 100644 tests/ui/layout/issue-84108.stderr create mode 100644 tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs create mode 100644 tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr create mode 100644 tests/ui/layout/issue-96185-overaligned-enum.rs create mode 100644 tests/ui/layout/issue-96185-overaligned-enum.stderr create mode 100644 tests/ui/layout/thin-meta-implies-thin-ptr.rs create mode 100644 tests/ui/layout/thumb-enum.rs create mode 100644 tests/ui/layout/thumb-enum.stderr create mode 100644 tests/ui/layout/unsafe-cell-hides-niche.rs create mode 100644 tests/ui/layout/valid_range_oob.rs create mode 100644 tests/ui/layout/valid_range_oob.stderr create mode 100644 tests/ui/layout/zero-sized-array-enum-niche.rs create mode 100644 tests/ui/layout/zero-sized-array-enum-niche.stderr create mode 100644 tests/ui/layout/zero-sized-array-union.rs create mode 100644 tests/ui/layout/zero-sized-array-union.stderr create mode 100644 tests/ui/lazy-and-or.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/branches.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/branches.stderr create mode 100644 tests/ui/lazy-type-alias-impl-trait/branches2.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/branches3.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/branches3.stderr create mode 100644 tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/infer_cross_function.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/lifetime_inference.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/nested.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/recursion.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/recursion2.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/recursion3.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/recursion3.stderr create mode 100644 tests/ui/lazy-type-alias-impl-trait/recursion4.rs create mode 100644 tests/ui/lazy-type-alias-impl-trait/recursion4.stderr create mode 100644 tests/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs create mode 100644 tests/ui/let-else/const-fn.rs create mode 100644 tests/ui/let-else/issue-100103.rs create mode 100644 tests/ui/let-else/issue-102317.rs create mode 100644 tests/ui/let-else/issue-94176.rs create mode 100644 tests/ui/let-else/issue-94176.stderr create mode 100644 tests/ui/let-else/issue-99975.rs create mode 100644 tests/ui/let-else/let-else-allow-in-expr.rs create mode 100644 tests/ui/let-else/let-else-allow-in-expr.stderr create mode 100644 tests/ui/let-else/let-else-allow-unused.rs create mode 100644 tests/ui/let-else/let-else-allow-unused.stderr create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut-annotated.rs create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut-borrow.rs create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut-pass.rs create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut.rs create mode 100644 tests/ui/let-else/let-else-binding-explicit-mut.stderr create mode 100644 tests/ui/let-else/let-else-binding-immutable.rs create mode 100644 tests/ui/let-else/let-else-binding-immutable.stderr create mode 100644 tests/ui/let-else/let-else-bindings.rs create mode 100644 tests/ui/let-else/let-else-bool-binop-init.fixed create mode 100644 tests/ui/let-else/let-else-bool-binop-init.rs create mode 100644 tests/ui/let-else/let-else-bool-binop-init.stderr create mode 100644 tests/ui/let-else/let-else-brace-before-else.fixed create mode 100644 tests/ui/let-else/let-else-brace-before-else.rs create mode 100644 tests/ui/let-else/let-else-brace-before-else.stderr create mode 100644 tests/ui/let-else/let-else-check.rs create mode 100644 tests/ui/let-else/let-else-check.stderr create mode 100644 tests/ui/let-else/let-else-deref-coercion-annotated.rs create mode 100644 tests/ui/let-else/let-else-deref-coercion.rs create mode 100644 tests/ui/let-else/let-else-deref-coercion.stderr create mode 100644 tests/ui/let-else/let-else-destructuring.rs create mode 100644 tests/ui/let-else/let-else-destructuring.stderr create mode 100644 tests/ui/let-else/let-else-drop-order.rs create mode 100644 tests/ui/let-else/let-else-drop-order.run.stdout create mode 100644 tests/ui/let-else/let-else-if.rs create mode 100644 tests/ui/let-else/let-else-if.stderr create mode 100644 tests/ui/let-else/let-else-irrefutable.rs create mode 100644 tests/ui/let-else/let-else-irrefutable.stderr create mode 100644 tests/ui/let-else/let-else-missing-semicolon.rs create mode 100644 tests/ui/let-else/let-else-missing-semicolon.stderr create mode 100644 tests/ui/let-else/let-else-no-double-error.rs create mode 100644 tests/ui/let-else/let-else-no-double-error.stderr create mode 100644 tests/ui/let-else/let-else-non-copy.rs create mode 100644 tests/ui/let-else/let-else-non-diverging.rs create mode 100644 tests/ui/let-else/let-else-non-diverging.stderr create mode 100644 tests/ui/let-else/let-else-ref-bindings-pass.rs create mode 100644 tests/ui/let-else/let-else-ref-bindings.rs create mode 100644 tests/ui/let-else/let-else-ref-bindings.stderr create mode 100644 tests/ui/let-else/let-else-run-pass.rs create mode 100644 tests/ui/let-else/let-else-scope.rs create mode 100644 tests/ui/let-else/let-else-scope.stderr create mode 100644 tests/ui/let-else/let-else-slicing-error.rs create mode 100644 tests/ui/let-else/let-else-slicing-error.stderr create mode 100644 tests/ui/let-else/let-else-source-expr-nomove-pass.rs create mode 100644 tests/ui/let-else/let-else-temp-borrowck.rs create mode 100644 tests/ui/let-else/let-else-temporary-lifetime.rs create mode 100644 tests/ui/let-else/let-else-then-diverge.rs create mode 100644 tests/ui/let-else/let-else-then-diverge.stderr create mode 100644 tests/ui/let-else/let-else.rs create mode 100644 tests/ui/lexer/error-stage.rs create mode 100644 tests/ui/lexer/error-stage.stderr create mode 100644 tests/ui/lexer/lex-bad-binary-literal.rs create mode 100644 tests/ui/lexer/lex-bad-binary-literal.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-1.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-1.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-2.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-2.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-3.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-3.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-4.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-4.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-5.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-5.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-6.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-6.stderr create mode 100644 tests/ui/lexer/lex-bad-char-literals-7.rs create mode 100644 tests/ui/lexer/lex-bad-char-literals-7.stderr create mode 100644 tests/ui/lexer/lex-bad-numeric-literals.rs create mode 100644 tests/ui/lexer/lex-bad-numeric-literals.stderr create mode 100644 tests/ui/lexer/lex-bad-octal-literal.rs create mode 100644 tests/ui/lexer/lex-bad-octal-literal.stderr create mode 100644 tests/ui/lexer/lex-bad-token.rs create mode 100644 tests/ui/lexer/lex-bad-token.stderr create mode 100644 tests/ui/lexer/lex-bare-cr-nondoc-comment.rs create mode 100644 tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs create mode 100644 tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr create mode 100644 tests/ui/lexer/lex-emoji-identifiers.rs create mode 100644 tests/ui/lexer/lex-emoji-identifiers.stderr create mode 100644 tests/ui/lexer/lex-stray-backslash.rs create mode 100644 tests/ui/lexer/lex-stray-backslash.stderr create mode 100644 tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs create mode 100644 tests/ui/lexical-scopes.rs create mode 100644 tests/ui/lexical-scopes.stderr create mode 100644 tests/ui/lexical-scoping.rs create mode 100644 tests/ui/lifetimes/auxiliary/issue-91763-aux.rs create mode 100644 tests/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs create mode 100644 tests/ui/lifetimes/bare-trait-object-borrowck.rs create mode 100644 tests/ui/lifetimes/bare-trait-object.rs create mode 100644 tests/ui/lifetimes/borrowck-let-suggestion.rs create mode 100644 tests/ui/lifetimes/borrowck-let-suggestion.stderr create mode 100644 tests/ui/lifetimes/conflicting-bounds.rs create mode 100644 tests/ui/lifetimes/conflicting-bounds.stderr create mode 100644 tests/ui/lifetimes/copy_modulo_regions.rs create mode 100644 tests/ui/lifetimes/copy_modulo_regions.stderr create mode 100644 tests/ui/lifetimes/elided-lifetime-in-param-pat.rs create mode 100644 tests/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs create mode 100644 tests/ui/lifetimes/elided-lifetime-in-path-in-pat.rs create mode 100644 tests/ui/lifetimes/elided-lifetime-in-path-in-type-relative-expression.rs create mode 100644 tests/ui/lifetimes/fullwidth-ampersand.rs create mode 100644 tests/ui/lifetimes/fullwidth-ampersand.stderr create mode 100644 tests/ui/lifetimes/issue-105227.fixed create mode 100644 tests/ui/lifetimes/issue-105227.rs create mode 100644 tests/ui/lifetimes/issue-105227.stderr create mode 100644 tests/ui/lifetimes/issue-105507.fixed create mode 100644 tests/ui/lifetimes/issue-105507.rs create mode 100644 tests/ui/lifetimes/issue-105507.stderr create mode 100644 tests/ui/lifetimes/issue-17728.rs create mode 100644 tests/ui/lifetimes/issue-17728.stderr create mode 100644 tests/ui/lifetimes/issue-26638.rs create mode 100644 tests/ui/lifetimes/issue-26638.stderr create mode 100644 tests/ui/lifetimes/issue-34979.rs create mode 100644 tests/ui/lifetimes/issue-34979.stderr create mode 100644 tests/ui/lifetimes/issue-54378.rs create mode 100644 tests/ui/lifetimes/issue-55796.rs create mode 100644 tests/ui/lifetimes/issue-55796.stderr create mode 100644 tests/ui/lifetimes/issue-64173-unused-lifetimes.rs create mode 100644 tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr create mode 100644 tests/ui/lifetimes/issue-67498.rs create mode 100644 tests/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs create mode 100644 tests/ui/lifetimes/issue-76168-hr-outlives-2.rs create mode 100644 tests/ui/lifetimes/issue-76168-hr-outlives.rs create mode 100644 tests/ui/lifetimes/issue-77175.rs create mode 100644 tests/ui/lifetimes/issue-79187-2.rs create mode 100644 tests/ui/lifetimes/issue-79187-2.stderr create mode 100644 tests/ui/lifetimes/issue-79187.rs create mode 100644 tests/ui/lifetimes/issue-79187.stderr create mode 100644 tests/ui/lifetimes/issue-83737-binders-across-types.rs create mode 100644 tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs create mode 100644 tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs create mode 100644 tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr create mode 100644 tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs create mode 100644 tests/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr create mode 100644 tests/ui/lifetimes/issue-84398.rs create mode 100644 tests/ui/lifetimes/issue-84604.rs create mode 100644 tests/ui/lifetimes/issue-90170-elision-mismatch.fixed create mode 100644 tests/ui/lifetimes/issue-90170-elision-mismatch.rs create mode 100644 tests/ui/lifetimes/issue-90170-elision-mismatch.stderr create mode 100644 tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs create mode 100644 tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr create mode 100644 tests/ui/lifetimes/issue-91763.rs create mode 100644 tests/ui/lifetimes/issue-91763.stderr create mode 100644 tests/ui/lifetimes/issue-95023.rs create mode 100644 tests/ui/lifetimes/issue-95023.stderr create mode 100644 tests/ui/lifetimes/issue-97193.rs create mode 100644 tests/ui/lifetimes/issue-97193.stderr create mode 100644 tests/ui/lifetimes/issue-97194.rs create mode 100644 tests/ui/lifetimes/issue-97194.stderr create mode 100644 tests/ui/lifetimes/lifetime-bound-will-change-warning.rs create mode 100644 tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr create mode 100644 tests/ui/lifetimes/lifetime-doesnt-live-long-enough.rs create mode 100644 tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr create mode 100644 tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs create mode 100644 tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr create mode 100644 tests/ui/lifetimes/lifetime-elision-return-type-trait.rs create mode 100644 tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/issue_74400.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/issue_74400.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr create mode 100644 tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs create mode 100644 tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr create mode 100644 tests/ui/lifetimes/lifetime-no-keyword.rs create mode 100644 tests/ui/lifetimes/lifetime-no-keyword.stderr create mode 100644 tests/ui/lifetimes/missing-lifetime-in-alias.rs create mode 100644 tests/ui/lifetimes/missing-lifetime-in-alias.stderr create mode 100644 tests/ui/lifetimes/nested-binder-print.rs create mode 100644 tests/ui/lifetimes/nested-binder-print.stderr create mode 100644 tests/ui/lifetimes/nested.rs create mode 100644 tests/ui/lifetimes/re-empty-in-error.rs create mode 100644 tests/ui/lifetimes/re-empty-in-error.stderr create mode 100644 tests/ui/lifetimes/shadow.rs create mode 100644 tests/ui/lifetimes/shadow.stderr create mode 100644 tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed create mode 100644 tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs create mode 100644 tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr create mode 100644 tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.rs create mode 100644 tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr create mode 100644 tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs create mode 100644 tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr create mode 100644 tests/ui/lifetimes/unusual-rib-combinations.rs create mode 100644 tests/ui/lifetimes/unusual-rib-combinations.stderr create mode 100644 tests/ui/limits/huge-array-simple-32.rs create mode 100644 tests/ui/limits/huge-array-simple-32.stderr create mode 100644 tests/ui/limits/huge-array-simple-64.rs create mode 100644 tests/ui/limits/huge-array-simple-64.stderr create mode 100644 tests/ui/limits/huge-array.rs create mode 100644 tests/ui/limits/huge-array.stderr create mode 100644 tests/ui/limits/huge-enum.rs create mode 100644 tests/ui/limits/huge-enum.stderr create mode 100644 tests/ui/limits/huge-struct.rs create mode 100644 tests/ui/limits/huge-struct.stderr create mode 100644 tests/ui/limits/issue-15919-32.rs create mode 100644 tests/ui/limits/issue-15919-32.stderr create mode 100644 tests/ui/limits/issue-15919-64.rs create mode 100644 tests/ui/limits/issue-15919-64.stderr create mode 100644 tests/ui/limits/issue-17913.rs create mode 100644 tests/ui/limits/issue-17913.stderr create mode 100644 tests/ui/limits/issue-55878.rs create mode 100644 tests/ui/limits/issue-55878.stderr create mode 100644 tests/ui/limits/issue-56762.rs create mode 100644 tests/ui/limits/issue-56762.stderr create mode 100644 tests/ui/limits/issue-69485-var-size-diffs-too-large.rs create mode 100644 tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr create mode 100644 tests/ui/limits/issue-75158-64.rs create mode 100644 tests/ui/limits/issue-75158-64.stderr create mode 100644 tests/ui/link-section.rs create mode 100644 tests/ui/linkage-attr/auxiliary/def_colliding_external.rs create mode 100644 tests/ui/linkage-attr/auxiliary/def_external.rs create mode 100644 tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-dylib.rs create mode 100644 tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-rlib.rs create mode 100644 tests/ui/linkage-attr/auxiliary/linkage1.rs create mode 100644 tests/ui/linkage-attr/issue-10755.rs create mode 100644 tests/ui/linkage-attr/link-attr-validation-early.rs create mode 100644 tests/ui/linkage-attr/link-attr-validation-early.stderr create mode 100644 tests/ui/linkage-attr/link-attr-validation-late.rs create mode 100644 tests/ui/linkage-attr/link-attr-validation-late.stderr create mode 100644 tests/ui/linkage-attr/link-cfg-works.rs create mode 100644 tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs create mode 100644 tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr create mode 100644 tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs create mode 100644 tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr create mode 100644 tests/ui/linkage-attr/linkage-import.rs create mode 100644 tests/ui/linkage-attr/linkage1.rs create mode 100644 tests/ui/linkage-attr/linkage2.rs create mode 100644 tests/ui/linkage-attr/linkage2.stderr create mode 100644 tests/ui/linkage-attr/linkage3.rs create mode 100644 tests/ui/linkage-attr/linkage3.stderr create mode 100644 tests/ui/linkage-attr/linkage4.rs create mode 100644 tests/ui/linkage-attr/linkage4.stderr create mode 100644 tests/ui/lint-unknown-lints-at-crate-level.rs create mode 100644 tests/ui/lint/auxiliary/add-impl.rs create mode 100644 tests/ui/lint/auxiliary/external_extern_fn.rs create mode 100644 tests/ui/lint/auxiliary/inherited_stability.rs create mode 100644 tests/ui/lint/auxiliary/lint_output_format.rs create mode 100644 tests/ui/lint/auxiliary/lint_stability.rs create mode 100644 tests/ui/lint/auxiliary/lint_stability_fields.rs create mode 100644 tests/ui/lint/auxiliary/lints-in-foreign-macros.rs create mode 100644 tests/ui/lint/auxiliary/stability-cfg2.rs create mode 100644 tests/ui/lint/auxiliary/stability_cfg1.rs create mode 100644 tests/ui/lint/auxiliary/stability_cfg2.rs create mode 100644 tests/ui/lint/auxiliary/trivial-cast-ice.rs create mode 100644 tests/ui/lint/auxiliary/unaligned_references_external_crate.rs create mode 100644 tests/ui/lint/bad-lint-cap.rs create mode 100644 tests/ui/lint/bad-lint-cap.stderr create mode 100644 tests/ui/lint/bad-lint-cap2.rs create mode 100644 tests/ui/lint/bad-lint-cap2.stderr create mode 100644 tests/ui/lint/bad-lint-cap3.rs create mode 100644 tests/ui/lint/bad-lint-cap3.stderr create mode 100644 tests/ui/lint/bare-trait-objects-path.rs create mode 100644 tests/ui/lint/bare-trait-objects-path.stderr create mode 100644 tests/ui/lint/clashing-extern-fn-recursion.rs create mode 100644 tests/ui/lint/clashing-extern-fn-wasm.rs create mode 100644 tests/ui/lint/clashing-extern-fn.rs create mode 100644 tests/ui/lint/clashing-extern-fn.stderr create mode 100644 tests/ui/lint/cli-lint-override.forbid_warn.stderr create mode 100644 tests/ui/lint/cli-lint-override.force_warn_deny.stderr create mode 100644 tests/ui/lint/cli-lint-override.rs create mode 100644 tests/ui/lint/cli-lint-override.warn_deny.stderr create mode 100644 tests/ui/lint/cli-unknown-force-warn.rs create mode 100644 tests/ui/lint/cli-unknown-force-warn.stderr create mode 100644 tests/ui/lint/command-line-lint-group-allow.rs create mode 100644 tests/ui/lint/command-line-lint-group-deny.rs create mode 100644 tests/ui/lint/command-line-lint-group-deny.stderr create mode 100644 tests/ui/lint/command-line-lint-group-forbid.rs create mode 100644 tests/ui/lint/command-line-lint-group-forbid.stderr create mode 100644 tests/ui/lint/command-line-lint-group-warn.rs create mode 100644 tests/ui/lint/command-line-lint-group-warn.stderr create mode 100644 tests/ui/lint/command-line-register-lint-tool.rs create mode 100644 tests/ui/lint/command-line-register-unknown-lint-tool.rs create mode 100644 tests/ui/lint/command-line-register-unknown-lint-tool.stderr create mode 100644 tests/ui/lint/crate_level_only_lint.rs create mode 100644 tests/ui/lint/crate_level_only_lint.stderr create mode 100644 tests/ui/lint/dead-code/alias-in-pat.rs create mode 100644 tests/ui/lint/dead-code/anon-const-in-pat.rs create mode 100644 tests/ui/lint/dead-code/associated-type.rs create mode 100644 tests/ui/lint/dead-code/basic.rs create mode 100644 tests/ui/lint/dead-code/basic.stderr create mode 100644 tests/ui/lint/dead-code/closure-bang.rs create mode 100644 tests/ui/lint/dead-code/const-and-self.rs create mode 100644 tests/ui/lint/dead-code/const-and-self.stderr create mode 100644 tests/ui/lint/dead-code/empty-unused-enum.rs create mode 100644 tests/ui/lint/dead-code/empty-unused-enum.stderr create mode 100644 tests/ui/lint/dead-code/empty-unused-public-enum.rs create mode 100644 tests/ui/lint/dead-code/enum-variants.rs create mode 100644 tests/ui/lint/dead-code/impl-trait.rs create mode 100644 tests/ui/lint/dead-code/impl-trait.stderr create mode 100644 tests/ui/lint/dead-code/issue-68408-false-positive.rs create mode 100644 tests/ui/lint/dead-code/issue-85071-2.rs create mode 100644 tests/ui/lint/dead-code/issue-85071-2.stderr create mode 100644 tests/ui/lint/dead-code/issue-85071.rs create mode 100644 tests/ui/lint/dead-code/issue-85071.stderr create mode 100644 tests/ui/lint/dead-code/issue-85255.rs create mode 100644 tests/ui/lint/dead-code/issue-85255.stderr create mode 100644 tests/ui/lint/dead-code/leading-underscore.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-1.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-1.stderr create mode 100644 tests/ui/lint/dead-code/lint-dead-code-2.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-2.stderr create mode 100644 tests/ui/lint/dead-code/lint-dead-code-3.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-3.stderr create mode 100644 tests/ui/lint/dead-code/lint-dead-code-4.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-4.stderr create mode 100644 tests/ui/lint/dead-code/lint-dead-code-5.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-5.stderr create mode 100644 tests/ui/lint/dead-code/lint-dead-code-6.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-6.stderr create mode 100644 tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs create mode 100644 tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr create mode 100644 tests/ui/lint/dead-code/newline-span.rs create mode 100644 tests/ui/lint/dead-code/newline-span.stderr create mode 100644 tests/ui/lint/dead-code/self-assign.rs create mode 100644 tests/ui/lint/dead-code/self-assign.stderr create mode 100644 tests/ui/lint/dead-code/trait-impl.rs create mode 100644 tests/ui/lint/dead-code/tuple-struct-field.rs create mode 100644 tests/ui/lint/dead-code/tuple-struct-field.stderr create mode 100644 tests/ui/lint/dead-code/type-alias.rs create mode 100644 tests/ui/lint/dead-code/type-alias.stderr create mode 100644 tests/ui/lint/dead-code/type-in-foreign.rs create mode 100644 tests/ui/lint/dead-code/unused-enum.rs create mode 100644 tests/ui/lint/dead-code/unused-enum.stderr create mode 100644 tests/ui/lint/dead-code/unused-struct-variant.rs create mode 100644 tests/ui/lint/dead-code/unused-struct-variant.stderr create mode 100644 tests/ui/lint/dead-code/unused-variant-pub.rs create mode 100644 tests/ui/lint/dead-code/unused-variant.rs create mode 100644 tests/ui/lint/dead-code/unused-variant.stderr create mode 100644 tests/ui/lint/dead-code/with-core-crate.rs create mode 100644 tests/ui/lint/dead-code/with-core-crate.stderr create mode 100644 tests/ui/lint/dead-code/with-impl.rs create mode 100644 tests/ui/lint/deny-overflowing-literals.rs create mode 100644 tests/ui/lint/deny-overflowing-literals.stderr create mode 100644 tests/ui/lint/empty-lint-attributes.rs create mode 100644 tests/ui/lint/enable-unstable-lib-feature.rs create mode 100644 tests/ui/lint/enable-unstable-lib-feature.stderr create mode 100644 tests/ui/lint/expansion-time-include.rs create mode 100644 tests/ui/lint/expansion-time.rs create mode 100644 tests/ui/lint/expansion-time.stderr create mode 100644 tests/ui/lint/expr_attr_paren_order.rs create mode 100644 tests/ui/lint/expr_attr_paren_order.stderr create mode 100644 tests/ui/lint/fn_must_use.rs create mode 100644 tests/ui/lint/fn_must_use.stderr create mode 100644 tests/ui/lint/for_loop_over_fallibles.rs create mode 100644 tests/ui/lint/for_loop_over_fallibles.stderr create mode 100644 tests/ui/lint/forbid-error-capped.rs create mode 100644 tests/ui/lint/forbid-group-group-1.rs create mode 100644 tests/ui/lint/forbid-group-group-1.stderr create mode 100644 tests/ui/lint/forbid-group-group-2.rs create mode 100644 tests/ui/lint/forbid-group-group-2.stderr create mode 100644 tests/ui/lint/forbid-group-member.rs create mode 100644 tests/ui/lint/forbid-group-member.stderr create mode 100644 tests/ui/lint/forbid-member-group.rs create mode 100644 tests/ui/lint/forbid-member-group.stderr create mode 100644 tests/ui/lint/force-warn/allow-warnings.rs create mode 100644 tests/ui/lint/force-warn/allow-warnings.stderr create mode 100644 tests/ui/lint/force-warn/allowed-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/allowed-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/cap-lints-allow.rs create mode 100644 tests/ui/lint/force-warn/cap-lints-allow.stderr create mode 100644 tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/deny-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/deny-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/lint-group-allow-warnings.rs create mode 100644 tests/ui/lint/force-warn/lint-group-allow-warnings.stderr create mode 100644 tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs create mode 100644 tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr create mode 100644 tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs create mode 100644 tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr create mode 100644 tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs create mode 100644 tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr create mode 100644 tests/ui/lint/force-warn/warnings-lint-group.rs create mode 100644 tests/ui/lint/force-warn/warnings-lint-group.stderr create mode 100644 tests/ui/lint/function-item-references.rs create mode 100644 tests/ui/lint/function-item-references.stderr create mode 100644 tests/ui/lint/future-incompat-test.rs create mode 100644 tests/ui/lint/future-incompat-test.stderr create mode 100644 tests/ui/lint/inclusive-range-pattern-syntax.fixed create mode 100644 tests/ui/lint/inclusive-range-pattern-syntax.rs create mode 100644 tests/ui/lint/inclusive-range-pattern-syntax.stderr create mode 100644 tests/ui/lint/inert-attr-macro.rs create mode 100644 tests/ui/lint/inert-attr-macro.stderr create mode 100644 tests/ui/lint/inline-trait-and-foreign-items.rs create mode 100644 tests/ui/lint/inline-trait-and-foreign-items.stderr create mode 100644 tests/ui/lint/invalid_value.rs create mode 100644 tests/ui/lint/invalid_value.stderr create mode 100644 tests/ui/lint/issue-101284.rs create mode 100644 tests/ui/lint/issue-102705.rs create mode 100644 tests/ui/lint/issue-103317.fixed create mode 100644 tests/ui/lint/issue-103317.rs create mode 100644 tests/ui/lint/issue-103317.stderr create mode 100644 tests/ui/lint/issue-103435-extra-parentheses.fixed create mode 100644 tests/ui/lint/issue-103435-extra-parentheses.rs create mode 100644 tests/ui/lint/issue-103435-extra-parentheses.stderr create mode 100644 tests/ui/lint/issue-104392.rs create mode 100644 tests/ui/lint/issue-104392.stderr create mode 100644 tests/ui/lint/issue-104897.rs create mode 100644 tests/ui/lint/issue-104897.stderr create mode 100644 tests/ui/lint/issue-108155.rs create mode 100644 tests/ui/lint/issue-14309.rs create mode 100644 tests/ui/lint/issue-14309.stderr create mode 100644 tests/ui/lint/issue-14837.rs create mode 100644 tests/ui/lint/issue-17718-const-naming.rs create mode 100644 tests/ui/lint/issue-17718-const-naming.stderr create mode 100644 tests/ui/lint/issue-1866.rs create mode 100644 tests/ui/lint/issue-1866.stderr create mode 100644 tests/ui/lint/issue-20343.rs create mode 100644 tests/ui/lint/issue-30302.rs create mode 100644 tests/ui/lint/issue-30302.stderr create mode 100644 tests/ui/lint/issue-31924-non-snake-ffi.rs create mode 100644 tests/ui/lint/issue-34798.rs create mode 100644 tests/ui/lint/issue-35075.rs create mode 100644 tests/ui/lint/issue-35075.stderr create mode 100644 tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs create mode 100644 tests/ui/lint/issue-54099-camel-case-underscore-types.rs create mode 100644 tests/ui/lint/issue-57410-1.rs create mode 100644 tests/ui/lint/issue-57410.rs create mode 100644 tests/ui/lint/issue-63364.rs create mode 100644 tests/ui/lint/issue-63364.stderr create mode 100644 tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs create mode 100644 tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr create mode 100644 tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs create mode 100644 tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr create mode 100644 tests/ui/lint/issue-79546-fuel-ice.rs create mode 100644 tests/ui/lint/issue-79744.rs create mode 100644 tests/ui/lint/issue-79744.stderr create mode 100644 tests/ui/lint/issue-80988.rs create mode 100644 tests/ui/lint/issue-80988.stderr create mode 100644 tests/ui/lint/issue-81218.rs create mode 100644 tests/ui/lint/issue-83477.rs create mode 100644 tests/ui/lint/issue-83477.stderr create mode 100644 tests/ui/lint/issue-86600-lint-twice.rs create mode 100644 tests/ui/lint/issue-86600-lint-twice.stderr create mode 100644 tests/ui/lint/issue-87274-paren-parent.rs create mode 100644 tests/ui/lint/issue-87274-paren-parent.stderr create mode 100644 tests/ui/lint/issue-89469.rs create mode 100644 tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs create mode 100644 tests/ui/lint/issue-97094.rs create mode 100644 tests/ui/lint/issue-97094.stderr create mode 100644 tests/ui/lint/issue-99387.rs create mode 100644 tests/ui/lint/known-tool-in-submodule/root.rs create mode 100644 tests/ui/lint/known-tool-in-submodule/submodule.rs create mode 100644 tests/ui/lint/let_underscore/let_underscore_drop.rs create mode 100644 tests/ui/lint/let_underscore/let_underscore_drop.stderr create mode 100644 tests/ui/lint/let_underscore/let_underscore_lock.rs create mode 100644 tests/ui/lint/let_underscore/let_underscore_lock.stderr create mode 100644 tests/ui/lint/lint-attr-everywhere-early.rs create mode 100644 tests/ui/lint/lint-attr-everywhere-early.stderr create mode 100644 tests/ui/lint/lint-attr-everywhere-late.rs create mode 100644 tests/ui/lint/lint-attr-everywhere-late.stderr create mode 100644 tests/ui/lint/lint-attr-non-item-node.rs create mode 100644 tests/ui/lint/lint-attr-non-item-node.stderr create mode 100644 tests/ui/lint/lint-cap.rs create mode 100644 tests/ui/lint/lint-change-warnings.rs create mode 100644 tests/ui/lint/lint-change-warnings.stderr create mode 100644 tests/ui/lint/lint-const-item-mutation.rs create mode 100644 tests/ui/lint/lint-const-item-mutation.stderr create mode 100644 tests/ui/lint/lint-ctypes-66202.rs create mode 100644 tests/ui/lint/lint-ctypes-73249-1.rs create mode 100644 tests/ui/lint/lint-ctypes-73249-2.rs create mode 100644 tests/ui/lint/lint-ctypes-73249-2.stderr create mode 100644 tests/ui/lint/lint-ctypes-73249-3.rs create mode 100644 tests/ui/lint/lint-ctypes-73249-3.stderr create mode 100644 tests/ui/lint/lint-ctypes-73249-4.rs create mode 100644 tests/ui/lint/lint-ctypes-73249-5.rs create mode 100644 tests/ui/lint/lint-ctypes-73249-5.stderr create mode 100644 tests/ui/lint/lint-ctypes-73249.rs create mode 100644 tests/ui/lint/lint-ctypes-73251-1.rs create mode 100644 tests/ui/lint/lint-ctypes-73251-1.stderr create mode 100644 tests/ui/lint/lint-ctypes-73251-2.rs create mode 100644 tests/ui/lint/lint-ctypes-73251-2.stderr create mode 100644 tests/ui/lint/lint-ctypes-73251.rs create mode 100644 tests/ui/lint/lint-ctypes-73747.rs create mode 100644 tests/ui/lint/lint-ctypes-enum.rs create mode 100644 tests/ui/lint/lint-ctypes-enum.stderr create mode 100644 tests/ui/lint/lint-ctypes-fn.rs create mode 100644 tests/ui/lint/lint-ctypes-fn.stderr create mode 100644 tests/ui/lint/lint-ctypes.rs create mode 100644 tests/ui/lint/lint-ctypes.stderr create mode 100644 tests/ui/lint/lint-deref-nullptr.rs create mode 100644 tests/ui/lint/lint-deref-nullptr.stderr create mode 100644 tests/ui/lint/lint-directives-on-use-items-issue-10534.rs create mode 100644 tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr create mode 100644 tests/ui/lint/lint-enum-intrinsics-non-enums.rs create mode 100644 tests/ui/lint/lint-enum-intrinsics-non-enums.stderr create mode 100644 tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr create mode 100644 tests/ui/lint/lint-exceeding-bitshifts.opt.stderr create mode 100644 tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr create mode 100644 tests/ui/lint/lint-exceeding-bitshifts.rs create mode 100644 tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs create mode 100644 tests/ui/lint/lint-ffi-safety-all-phantom.rs create mode 100644 tests/ui/lint/lint-forbid-attr.rs create mode 100644 tests/ui/lint/lint-forbid-attr.stderr create mode 100644 tests/ui/lint/lint-forbid-cmdline.rs create mode 100644 tests/ui/lint/lint-forbid-cmdline.stderr create mode 100644 tests/ui/lint/lint-forbid-internal-unsafe.rs create mode 100644 tests/ui/lint/lint-forbid-internal-unsafe.stderr create mode 100644 tests/ui/lint/lint-group-nonstandard-style.rs create mode 100644 tests/ui/lint/lint-group-nonstandard-style.stderr create mode 100644 tests/ui/lint/lint-impl-fn.rs create mode 100644 tests/ui/lint/lint-impl-fn.stderr create mode 100644 tests/ui/lint/lint-incoherent-auto-trait-objects.rs create mode 100644 tests/ui/lint/lint-incoherent-auto-trait-objects.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-bool.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-fence.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-int.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-int.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-uint.rs create mode 100644 tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr create mode 100644 tests/ui/lint/lint-level-macro-def-mod.rs create mode 100644 tests/ui/lint/lint-level-macro-def.rs create mode 100644 tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs create mode 100644 tests/ui/lint/lint-lowercase-static-const-pattern.rs create mode 100644 tests/ui/lint/lint-lowercase-static-const-pattern.stderr create mode 100644 tests/ui/lint/lint-malformed.rs create mode 100644 tests/ui/lint/lint-malformed.stderr create mode 100644 tests/ui/lint/lint-match-arms.rs create mode 100644 tests/ui/lint/lint-match-arms.stderr create mode 100644 tests/ui/lint/lint-misplaced-attr.rs create mode 100644 tests/ui/lint/lint-misplaced-attr.stderr create mode 100644 tests/ui/lint/lint-missing-copy-implementations-allow.rs create mode 100644 tests/ui/lint/lint-missing-copy-implementations.rs create mode 100644 tests/ui/lint/lint-missing-copy-implementations.stderr create mode 100644 tests/ui/lint/lint-missing-doc.rs create mode 100644 tests/ui/lint/lint-missing-doc.stderr create mode 100644 tests/ui/lint/lint-non-camel-case-types.rs create mode 100644 tests/ui/lint/lint-non-camel-case-types.stderr create mode 100644 tests/ui/lint/lint-non-camel-case-variant.rs create mode 100644 tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs create mode 100644 tests/ui/lint/lint-non-snake-case-crate-2.rs create mode 100644 tests/ui/lint/lint-non-snake-case-crate-2.stderr create mode 100644 tests/ui/lint/lint-non-snake-case-crate.rs create mode 100644 tests/ui/lint/lint-non-snake-case-crate.stderr create mode 100644 tests/ui/lint/lint-non-snake-case-functions.rs create mode 100644 tests/ui/lint/lint-non-snake-case-functions.stderr create mode 100644 tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs create mode 100644 tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr create mode 100644 tests/ui/lint/lint-non-snake-case-lifetimes.rs create mode 100644 tests/ui/lint/lint-non-snake-case-lifetimes.stderr create mode 100644 tests/ui/lint/lint-non-snake-case-modules.rs create mode 100644 tests/ui/lint/lint-non-snake-case-modules.stderr create mode 100644 tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs create mode 100644 tests/ui/lint/lint-non-uppercase-associated-const.rs create mode 100644 tests/ui/lint/lint-non-uppercase-associated-const.stderr create mode 100644 tests/ui/lint/lint-non-uppercase-statics.rs create mode 100644 tests/ui/lint/lint-non-uppercase-statics.stderr create mode 100644 tests/ui/lint/lint-nonstandard-style-unicode-1.rs create mode 100644 tests/ui/lint/lint-nonstandard-style-unicode-1.stderr create mode 100644 tests/ui/lint/lint-nonstandard-style-unicode-2.rs create mode 100644 tests/ui/lint/lint-nonstandard-style-unicode-2.stderr create mode 100644 tests/ui/lint/lint-nonstandard-style-unicode-3.rs create mode 100644 tests/ui/lint/lint-nonstandard-style-unicode-3.stderr create mode 100644 tests/ui/lint/lint-output-format-2.rs create mode 100644 tests/ui/lint/lint-output-format-2.stderr create mode 100644 tests/ui/lint/lint-output-format.rs create mode 100644 tests/ui/lint/lint-output-format.stderr create mode 100644 tests/ui/lint/lint-owned-heap-memory.rs create mode 100644 tests/ui/lint/lint-owned-heap-memory.stderr create mode 100644 tests/ui/lint/lint-pre-expansion-extern-module.rs create mode 100644 tests/ui/lint/lint-pre-expansion-extern-module.stderr create mode 100644 tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs create mode 100644 tests/ui/lint/lint-qualification.rs create mode 100644 tests/ui/lint/lint-qualification.stderr create mode 100644 tests/ui/lint/lint-range-endpoint-overflow.rs create mode 100644 tests/ui/lint/lint-range-endpoint-overflow.stderr create mode 100644 tests/ui/lint/lint-removed-allow.rs create mode 100644 tests/ui/lint/lint-removed-allow.stderr create mode 100644 tests/ui/lint/lint-removed-cmdline.rs create mode 100644 tests/ui/lint/lint-removed-cmdline.stderr create mode 100644 tests/ui/lint/lint-removed.rs create mode 100644 tests/ui/lint/lint-removed.stderr create mode 100644 tests/ui/lint/lint-renamed-allow.rs create mode 100644 tests/ui/lint/lint-renamed-allow.stderr create mode 100644 tests/ui/lint/lint-renamed-cmdline.rs create mode 100644 tests/ui/lint/lint-renamed-cmdline.stderr create mode 100644 tests/ui/lint/lint-renamed.rs create mode 100644 tests/ui/lint/lint-renamed.stderr create mode 100644 tests/ui/lint/lint-shorthand-field.fixed create mode 100644 tests/ui/lint/lint-shorthand-field.rs create mode 100644 tests/ui/lint/lint-shorthand-field.stderr create mode 100644 tests/ui/lint/lint-stability-2.rs create mode 100644 tests/ui/lint/lint-stability-2.stderr create mode 100644 tests/ui/lint/lint-stability-deprecated.rs create mode 100644 tests/ui/lint/lint-stability-deprecated.stderr create mode 100644 tests/ui/lint/lint-stability-fields-deprecated.rs create mode 100644 tests/ui/lint/lint-stability-fields-deprecated.stderr create mode 100644 tests/ui/lint/lint-stability-fields.rs create mode 100644 tests/ui/lint/lint-stability-fields.stderr create mode 100644 tests/ui/lint/lint-stability.rs create mode 100644 tests/ui/lint/lint-stability.stderr create mode 100644 tests/ui/lint/lint-stability2.rs create mode 100644 tests/ui/lint/lint-stability2.stderr create mode 100644 tests/ui/lint/lint-stability3.rs create mode 100644 tests/ui/lint/lint-stability3.stderr create mode 100644 tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs create mode 100644 tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr create mode 100644 tests/ui/lint/lint-strict-provenance-lossy-casts.rs create mode 100644 tests/ui/lint/lint-strict-provenance-lossy-casts.stderr create mode 100644 tests/ui/lint/lint-temporary-cstring-as-param.rs create mode 100644 tests/ui/lint/lint-temporary-cstring-as-param.stderr create mode 100644 tests/ui/lint/lint-temporary-cstring-as-ptr.rs create mode 100644 tests/ui/lint/lint-temporary-cstring-as-ptr.stderr create mode 100644 tests/ui/lint/lint-type-limits.rs create mode 100644 tests/ui/lint/lint-type-limits.stderr create mode 100644 tests/ui/lint/lint-type-limits2.rs create mode 100644 tests/ui/lint/lint-type-limits2.stderr create mode 100644 tests/ui/lint/lint-type-limits3.rs create mode 100644 tests/ui/lint/lint-type-limits3.stderr create mode 100644 tests/ui/lint/lint-type-overflow.rs create mode 100644 tests/ui/lint/lint-type-overflow.stderr create mode 100644 tests/ui/lint/lint-type-overflow2.rs create mode 100644 tests/ui/lint/lint-type-overflow2.stderr create mode 100644 tests/ui/lint/lint-unconditional-recursion.rs create mode 100644 tests/ui/lint/lint-unconditional-recursion.stderr create mode 100644 tests/ui/lint/lint-unexported-no-mangle.rs create mode 100644 tests/ui/lint/lint-unexported-no-mangle.stderr create mode 100644 tests/ui/lint/lint-unknown-feature-default.rs create mode 100644 tests/ui/lint/lint-unknown-feature.rs create mode 100644 tests/ui/lint/lint-unknown-lint-cmdline.rs create mode 100644 tests/ui/lint/lint-unknown-lint-cmdline.stderr create mode 100644 tests/ui/lint/lint-unknown-lint.rs create mode 100644 tests/ui/lint/lint-unknown-lint.stderr create mode 100644 tests/ui/lint/lint-unnecessary-import-braces.rs create mode 100644 tests/ui/lint/lint-unnecessary-import-braces.stderr create mode 100644 tests/ui/lint/lint-unnecessary-parens.fixed create mode 100644 tests/ui/lint/lint-unnecessary-parens.rs create mode 100644 tests/ui/lint/lint-unnecessary-parens.stderr create mode 100644 tests/ui/lint/lint-unsafe-code.rs create mode 100644 tests/ui/lint/lint-unsafe-code.stderr create mode 100644 tests/ui/lint/lint-uppercase-variables.rs create mode 100644 tests/ui/lint/lint-uppercase-variables.stderr create mode 100644 tests/ui/lint/lint_pre_expansion_extern_module_aux.rs create mode 100644 tests/ui/lint/lints-in-foreign-macros.rs create mode 100644 tests/ui/lint/lints-in-foreign-macros.stderr create mode 100644 tests/ui/lint/missing-doc-private-macro.rs create mode 100644 tests/ui/lint/missing-doc-private-macro.stderr create mode 100644 tests/ui/lint/must_not_suspend/boxed.rs create mode 100644 tests/ui/lint/must_not_suspend/boxed.stderr create mode 100644 tests/ui/lint/must_not_suspend/dedup.rs create mode 100644 tests/ui/lint/must_not_suspend/dedup.stderr create mode 100644 tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs create mode 100644 tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr create mode 100644 tests/ui/lint/must_not_suspend/gated.rs create mode 100644 tests/ui/lint/must_not_suspend/gated.stderr create mode 100644 tests/ui/lint/must_not_suspend/generic.rs create mode 100644 tests/ui/lint/must_not_suspend/handled.rs create mode 100644 tests/ui/lint/must_not_suspend/issue-89562.rs create mode 100644 tests/ui/lint/must_not_suspend/mutex.rs create mode 100644 tests/ui/lint/must_not_suspend/mutex.stderr create mode 100644 tests/ui/lint/must_not_suspend/other_items.rs create mode 100644 tests/ui/lint/must_not_suspend/other_items.stderr create mode 100644 tests/ui/lint/must_not_suspend/ref-drop-tracking.rs create mode 100644 tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr create mode 100644 tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr create mode 100644 tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr create mode 100644 tests/ui/lint/must_not_suspend/ref.rs create mode 100644 tests/ui/lint/must_not_suspend/return.rs create mode 100644 tests/ui/lint/must_not_suspend/return.stderr create mode 100644 tests/ui/lint/must_not_suspend/trait.rs create mode 100644 tests/ui/lint/must_not_suspend/trait.stderr create mode 100644 tests/ui/lint/must_not_suspend/tuple-mismatch.rs create mode 100644 tests/ui/lint/must_not_suspend/tuple-mismatch.stderr create mode 100644 tests/ui/lint/must_not_suspend/unit.rs create mode 100644 tests/ui/lint/must_not_suspend/unit.stderr create mode 100644 tests/ui/lint/must_not_suspend/warn.rs create mode 100644 tests/ui/lint/must_not_suspend/warn.stderr create mode 100644 tests/ui/lint/no-coverage.rs create mode 100644 tests/ui/lint/no-coverage.stderr create mode 100644 tests/ui/lint/noop-method-call.rs create mode 100644 tests/ui/lint/noop-method-call.stderr create mode 100644 tests/ui/lint/not_found.rs create mode 100644 tests/ui/lint/not_found.stderr create mode 100644 tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs create mode 100644 tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr create mode 100644 tests/ui/lint/opaque-ty-ffi-unsafe.rs create mode 100644 tests/ui/lint/opaque-ty-ffi-unsafe.stderr create mode 100644 tests/ui/lint/outer-forbid.rs create mode 100644 tests/ui/lint/outer-forbid.stderr create mode 100644 tests/ui/lint/reasons-erroneous.rs create mode 100644 tests/ui/lint/reasons-erroneous.stderr create mode 100644 tests/ui/lint/reasons-forbidden.rs create mode 100644 tests/ui/lint/reasons-forbidden.stderr create mode 100644 tests/ui/lint/reasons.rs create mode 100644 tests/ui/lint/reasons.stderr create mode 100644 tests/ui/lint/recommend-literal.rs create mode 100644 tests/ui/lint/recommend-literal.stderr create mode 100644 tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs create mode 100644 tests/ui/lint/redundant-semicolon/item-stmt-semi.rs create mode 100644 tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr create mode 100644 tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs create mode 100644 tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr create mode 100644 tests/ui/lint/register-tool-lint.rs create mode 100644 tests/ui/lint/register-tool-lint.stderr create mode 100644 tests/ui/lint/renamed-lints-still-apply.rs create mode 100644 tests/ui/lint/renamed-lints-still-apply.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs create mode 100644 tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr create mode 100644 tests/ui/lint/rustdoc-group.rs create mode 100644 tests/ui/lint/rustdoc-group.stderr create mode 100644 tests/ui/lint/rustdoc-renamed.rs create mode 100644 tests/ui/lint/rustdoc-renamed.stderr create mode 100644 tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs create mode 100644 tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs create mode 100644 tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs create mode 100644 tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr create mode 100644 tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs create mode 100644 tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr create mode 100644 tests/ui/lint/special-upper-lower-cases.rs create mode 100644 tests/ui/lint/special-upper-lower-cases.stderr create mode 100644 tests/ui/lint/suggestions.fixed create mode 100644 tests/ui/lint/suggestions.rs create mode 100644 tests/ui/lint/suggestions.stderr create mode 100644 tests/ui/lint/test-allow-dead-extern-static-no-warning.rs create mode 100644 tests/ui/lint/test-inner-fn.rs create mode 100644 tests/ui/lint/test-inner-fn.stderr create mode 100644 tests/ui/lint/trivial-cast-ice.rs create mode 100644 tests/ui/lint/trivial-casts-featuring-type-ascription.rs create mode 100644 tests/ui/lint/trivial-casts-featuring-type-ascription.stderr create mode 100644 tests/ui/lint/trivial-casts.rs create mode 100644 tests/ui/lint/trivial-casts.stderr create mode 100644 tests/ui/lint/trivial_casts.rs create mode 100644 tests/ui/lint/trivial_casts.stderr create mode 100644 tests/ui/lint/type-overflow.rs create mode 100644 tests/ui/lint/type-overflow.stderr create mode 100644 tests/ui/lint/unaligned_references.rs create mode 100644 tests/ui/lint/unaligned_references.stderr create mode 100644 tests/ui/lint/unaligned_references_external_macro.rs create mode 100644 tests/ui/lint/unaligned_references_external_macro.stderr create mode 100644 tests/ui/lint/unnecessary-extern-crate.rs create mode 100644 tests/ui/lint/unnecessary-extern-crate.stderr create mode 100644 tests/ui/lint/unreachable-async-fn.rs create mode 100644 tests/ui/lint/unreachable_pub.rs create mode 100644 tests/ui/lint/unreachable_pub.stderr create mode 100644 tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs create mode 100644 tests/ui/lint/unsafe_code/forge_unsafe_block.rs create mode 100644 tests/ui/lint/unused-borrows.rs create mode 100644 tests/ui/lint/unused-borrows.stderr create mode 100644 tests/ui/lint/unused-braces-while-let-with-mutable-value.rs create mode 100644 tests/ui/lint/unused-qualification-in-derive-expansion.rs create mode 100644 tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs create mode 100644 tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs create mode 100644 tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs create mode 100644 tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs create mode 100644 tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs create mode 100644 tests/ui/lint/unused/issue-104397.rs create mode 100644 tests/ui/lint/unused/issue-105061-array-lint.rs create mode 100644 tests/ui/lint/unused/issue-105061-array-lint.stderr create mode 100644 tests/ui/lint/unused/issue-105061-should-lint.rs create mode 100644 tests/ui/lint/unused/issue-105061-should-lint.stderr create mode 100644 tests/ui/lint/unused/issue-105061.rs create mode 100644 tests/ui/lint/unused/issue-105061.stderr create mode 100644 tests/ui/lint/unused/issue-30730.rs create mode 100644 tests/ui/lint/unused/issue-30730.stderr create mode 100644 tests/ui/lint/unused/issue-46576.rs create mode 100644 tests/ui/lint/unused/issue-46576.stderr create mode 100644 tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs create mode 100644 tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr create mode 100644 tests/ui/lint/unused/issue-54180-unused-ref-field.fixed create mode 100644 tests/ui/lint/unused/issue-54180-unused-ref-field.rs create mode 100644 tests/ui/lint/unused/issue-54180-unused-ref-field.stderr create mode 100644 tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed create mode 100644 tests/ui/lint/unused/issue-54538-unused-parens-lint.rs create mode 100644 tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr create mode 100644 tests/ui/lint/unused/issue-59896.rs create mode 100644 tests/ui/lint/unused/issue-59896.stderr create mode 100644 tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs create mode 100644 tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr create mode 100644 tests/ui/lint/unused/issue-70041.rs create mode 100644 tests/ui/lint/unused/issue-70041.stderr create mode 100644 tests/ui/lint/unused/issue-71290-unused-paren-binop.rs create mode 100644 tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs create mode 100644 tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr create mode 100644 tests/ui/lint/unused/issue-81314-unused-span-ident.fixed create mode 100644 tests/ui/lint/unused/issue-81314-unused-span-ident.rs create mode 100644 tests/ui/lint/unused/issue-81314-unused-span-ident.stderr create mode 100644 tests/ui/lint/unused/issue-85913.rs create mode 100644 tests/ui/lint/unused/issue-85913.stderr create mode 100644 tests/ui/lint/unused/issue-88519-unused-paren.rs create mode 100644 tests/ui/lint/unused/issue-90807-unused-paren-error.rs create mode 100644 tests/ui/lint/unused/issue-90807-unused-paren-error.stderr create mode 100644 tests/ui/lint/unused/issue-90807-unused-paren.rs create mode 100644 tests/ui/lint/unused/issue-92751.rs create mode 100644 tests/ui/lint/unused/issue-92751.stderr create mode 100644 tests/ui/lint/unused/lint-unused-extern-crate.rs create mode 100644 tests/ui/lint/unused/lint-unused-extern-crate.stderr create mode 100644 tests/ui/lint/unused/lint-unused-imports.rs create mode 100644 tests/ui/lint/unused/lint-unused-imports.stderr create mode 100644 tests/ui/lint/unused/lint-unused-mut-self.fixed create mode 100644 tests/ui/lint/unused/lint-unused-mut-self.rs create mode 100644 tests/ui/lint/unused/lint-unused-mut-self.stderr create mode 100644 tests/ui/lint/unused/lint-unused-mut-variables.rs create mode 100644 tests/ui/lint/unused/lint-unused-mut-variables.stderr create mode 100644 tests/ui/lint/unused/lint-unused-variables.rs create mode 100644 tests/ui/lint/unused/lint-unused-variables.stderr create mode 100644 tests/ui/lint/unused/must-use-box-from-raw.rs create mode 100644 tests/ui/lint/unused/must-use-box-from-raw.stderr create mode 100644 tests/ui/lint/unused/must-use-ops.rs create mode 100644 tests/ui/lint/unused/must-use-ops.stderr create mode 100644 tests/ui/lint/unused/must_use-array.rs create mode 100644 tests/ui/lint/unused/must_use-array.stderr create mode 100644 tests/ui/lint/unused/must_use-in-stdlib-traits.rs create mode 100644 tests/ui/lint/unused/must_use-in-stdlib-traits.stderr create mode 100644 tests/ui/lint/unused/must_use-trait.rs create mode 100644 tests/ui/lint/unused/must_use-trait.stderr create mode 100644 tests/ui/lint/unused/must_use-tuple.rs create mode 100644 tests/ui/lint/unused/must_use-tuple.stderr create mode 100644 tests/ui/lint/unused/must_use-unit.rs create mode 100644 tests/ui/lint/unused/must_use-unit.stderr create mode 100644 tests/ui/lint/unused/no-unused-parens-return-block.rs create mode 100644 tests/ui/lint/unused/unused-async.rs create mode 100644 tests/ui/lint/unused/unused-async.stderr create mode 100644 tests/ui/lint/unused/unused-attr-duplicate.rs create mode 100644 tests/ui/lint/unused/unused-attr-duplicate.stderr create mode 100644 tests/ui/lint/unused/unused-attr-macro-rules.rs create mode 100644 tests/ui/lint/unused/unused-attr-macro-rules.stderr create mode 100644 tests/ui/lint/unused/unused-closure.rs create mode 100644 tests/ui/lint/unused/unused-closure.stderr create mode 100644 tests/ui/lint/unused/unused-doc-comments-edge-cases.rs create mode 100644 tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr create mode 100644 tests/ui/lint/unused/unused-doc-comments-for-macros.rs create mode 100644 tests/ui/lint/unused/unused-doc-comments-for-macros.stderr create mode 100644 tests/ui/lint/unused/unused-macro-rules-compile-error.rs create mode 100644 tests/ui/lint/unused/unused-macro-rules-compile-error.stderr create mode 100644 tests/ui/lint/unused/unused-macro-rules-decl.rs create mode 100644 tests/ui/lint/unused/unused-macro-rules-decl.stderr create mode 100644 tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs create mode 100644 tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr create mode 100644 tests/ui/lint/unused/unused-macro-rules.rs create mode 100644 tests/ui/lint/unused/unused-macro-rules.stderr create mode 100644 tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs create mode 100644 tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr create mode 100644 tests/ui/lint/unused/unused-macro-with-follow-violation.rs create mode 100644 tests/ui/lint/unused/unused-macro-with-follow-violation.stderr create mode 100644 tests/ui/lint/unused/unused-macros-decl.rs create mode 100644 tests/ui/lint/unused/unused-macros-decl.stderr create mode 100644 tests/ui/lint/unused/unused-macros-malformed-rule.rs create mode 100644 tests/ui/lint/unused/unused-macros-malformed-rule.stderr create mode 100644 tests/ui/lint/unused/unused-macros.rs create mode 100644 tests/ui/lint/unused/unused-macros.stderr create mode 100644 tests/ui/lint/unused/unused-mut-warning-captured-var.fixed create mode 100644 tests/ui/lint/unused/unused-mut-warning-captured-var.rs create mode 100644 tests/ui/lint/unused/unused-mut-warning-captured-var.stderr create mode 100644 tests/ui/lint/unused/unused-result.rs create mode 100644 tests/ui/lint/unused/unused-result.stderr create mode 100644 tests/ui/lint/unused/unused-supertrait.rs create mode 100644 tests/ui/lint/unused/unused-supertrait.stderr create mode 100644 tests/ui/lint/unused/unused_attributes-must_use.rs create mode 100644 tests/ui/lint/unused/unused_attributes-must_use.stderr create mode 100644 tests/ui/lint/unused/useless-comment.rs create mode 100644 tests/ui/lint/unused/useless-comment.stderr create mode 100644 tests/ui/lint/unused_braces.fixed create mode 100644 tests/ui/lint/unused_braces.rs create mode 100644 tests/ui/lint/unused_braces.stderr create mode 100644 tests/ui/lint/unused_braces_borrow.fixed create mode 100644 tests/ui/lint/unused_braces_borrow.rs create mode 100644 tests/ui/lint/unused_braces_borrow.stderr create mode 100644 tests/ui/lint/unused_braces_macro.rs create mode 100644 tests/ui/lint/unused_import_warning_issue_45268.rs create mode 100644 tests/ui/lint/unused_import_warning_issue_45268.stderr create mode 100644 tests/ui/lint/unused_labels.rs create mode 100644 tests/ui/lint/unused_labels.stderr create mode 100644 tests/ui/lint/unused_parens_json_suggestion.fixed create mode 100644 tests/ui/lint/unused_parens_json_suggestion.rs create mode 100644 tests/ui/lint/unused_parens_json_suggestion.stderr create mode 100644 tests/ui/lint/unused_parens_multibyte_recovery.rs create mode 100644 tests/ui/lint/unused_parens_multibyte_recovery.stderr create mode 100644 tests/ui/lint/unused_parens_remove_json_suggestion.fixed create mode 100644 tests/ui/lint/unused_parens_remove_json_suggestion.rs create mode 100644 tests/ui/lint/unused_parens_remove_json_suggestion.stderr create mode 100644 tests/ui/lint/unused_variables-issue-82488.fixed create mode 100644 tests/ui/lint/unused_variables-issue-82488.rs create mode 100644 tests/ui/lint/unused_variables-issue-82488.stderr create mode 100644 tests/ui/lint/use-redundant.rs create mode 100644 tests/ui/lint/use-redundant.stderr create mode 100644 tests/ui/lint/use_suggestion_json.rs create mode 100644 tests/ui/lint/use_suggestion_json.stderr create mode 100644 tests/ui/lint/warn-ctypes-inhibit.rs create mode 100644 tests/ui/lint/warn-path-statement.rs create mode 100644 tests/ui/lint/warn-path-statement.stderr create mode 100644 tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs create mode 100644 tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr create mode 100644 tests/ui/list.rs create mode 100644 tests/ui/liveness/liveness-asm.rs create mode 100644 tests/ui/liveness/liveness-asm.stderr create mode 100644 tests/ui/liveness/liveness-assign-imm-local-after-ret.rs create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs create mode 100644 tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr create mode 100644 tests/ui/liveness/liveness-closure-require-ret.rs create mode 100644 tests/ui/liveness/liveness-closure-require-ret.stderr create mode 100644 tests/ui/liveness/liveness-consts.rs create mode 100644 tests/ui/liveness/liveness-consts.stderr create mode 100644 tests/ui/liveness/liveness-dead.rs create mode 100644 tests/ui/liveness/liveness-dead.stderr create mode 100644 tests/ui/liveness/liveness-derive.rs create mode 100644 tests/ui/liveness/liveness-derive.stderr create mode 100644 tests/ui/liveness/liveness-forgot-ret.rs create mode 100644 tests/ui/liveness/liveness-forgot-ret.stderr create mode 100644 tests/ui/liveness/liveness-issue-2163.rs create mode 100644 tests/ui/liveness/liveness-issue-2163.stderr create mode 100644 tests/ui/liveness/liveness-missing-ret2.rs create mode 100644 tests/ui/liveness/liveness-missing-ret2.stderr create mode 100644 tests/ui/liveness/liveness-move-call-arg.rs create mode 100644 tests/ui/liveness/liveness-move-call-arg.stderr create mode 100644 tests/ui/liveness/liveness-move-in-loop.rs create mode 100644 tests/ui/liveness/liveness-move-in-loop.stderr create mode 100644 tests/ui/liveness/liveness-move-in-while.rs create mode 100644 tests/ui/liveness/liveness-move-in-while.stderr create mode 100644 tests/ui/liveness/liveness-return-last-stmt-semi.rs create mode 100644 tests/ui/liveness/liveness-return-last-stmt-semi.stderr create mode 100644 tests/ui/liveness/liveness-unused.rs create mode 100644 tests/ui/liveness/liveness-unused.stderr create mode 100644 tests/ui/liveness/liveness-upvars.rs create mode 100644 tests/ui/liveness/liveness-upvars.stderr create mode 100644 tests/ui/liveness/liveness-use-after-move.rs create mode 100644 tests/ui/liveness/liveness-use-after-move.stderr create mode 100644 tests/ui/liveness/liveness-use-after-send.rs create mode 100644 tests/ui/liveness/liveness-use-after-send.stderr create mode 100644 tests/ui/log-err-phi.rs create mode 100644 tests/ui/log-knows-the-names-of-variants.rs create mode 100644 tests/ui/log-poly.rs create mode 100644 tests/ui/logging-only-prints-once.rs create mode 100644 tests/ui/loops/for-each-loop-panic.rs create mode 100644 tests/ui/loops/issue-82916.rs create mode 100644 tests/ui/loops/issue-82916.stderr create mode 100644 tests/ui/loops/loop-break-unsize.rs create mode 100644 tests/ui/loops/loop-break-value-no-repeat.rs create mode 100644 tests/ui/loops/loop-break-value-no-repeat.stderr create mode 100644 tests/ui/loops/loop-break-value.rs create mode 100644 tests/ui/loops/loop-break-value.stderr create mode 100644 tests/ui/loops/loop-labeled-break-value.rs create mode 100644 tests/ui/loops/loop-labeled-break-value.stderr create mode 100644 tests/ui/loops/loop-no-implicit-break.rs create mode 100644 tests/ui/loops/loop-no-implicit-break.stderr create mode 100644 tests/ui/loops/loop-proper-liveness.rs create mode 100644 tests/ui/loops/loop-proper-liveness.stderr create mode 100644 tests/ui/loops/loop-properly-diverging-2.rs create mode 100644 tests/ui/loops/loop-properly-diverging-2.stderr create mode 100644 tests/ui/loud_ui.rs create mode 100644 tests/ui/lowering/issue-96847.rs create mode 100644 tests/ui/lto/all-crates.rs create mode 100644 tests/ui/lto/auxiliary/debuginfo-lto-aux.rs create mode 100644 tests/ui/lto/auxiliary/dylib.rs create mode 100644 tests/ui/lto/auxiliary/lto-duplicate-symbols1.rs create mode 100644 tests/ui/lto/auxiliary/lto-duplicate-symbols2.rs create mode 100644 tests/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs create mode 100644 tests/ui/lto/auxiliary/msvc-imp-present.rs create mode 100644 tests/ui/lto/auxiliary/thin-lto-inlines-aux.rs create mode 100644 tests/ui/lto/auxiliary/thinlto-dylib.rs create mode 100644 tests/ui/lto/debuginfo-lto.rs create mode 100644 tests/ui/lto/dylib-works.rs create mode 100644 tests/ui/lto/fat-lto.rs create mode 100644 tests/ui/lto/issue-100772.rs create mode 100644 tests/ui/lto/issue-105637.rs create mode 100644 tests/ui/lto/issue-105637.run.stderr create mode 100644 tests/ui/lto/issue-11154.rs create mode 100644 tests/ui/lto/issue-11154.stderr create mode 100644 tests/ui/lto/lto-and-no-bitcode-in-rlib.rs create mode 100644 tests/ui/lto/lto-and-no-bitcode-in-rlib.stderr create mode 100644 tests/ui/lto/lto-duplicate-symbols.rs create mode 100644 tests/ui/lto/lto-duplicate-symbols.stderr create mode 100644 tests/ui/lto/lto-many-codegen-units.rs create mode 100644 tests/ui/lto/lto-opt-level-s.rs create mode 100644 tests/ui/lto/lto-opt-level-z.rs create mode 100644 tests/ui/lto/lto-rustc-loads-linker-plugin.rs create mode 100644 tests/ui/lto/lto-still-runs-thread-dtors.rs create mode 100644 tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs create mode 100644 tests/ui/lto/msvc-imp-present.rs create mode 100644 tests/ui/lto/thin-lto-global-allocator.rs create mode 100644 tests/ui/lto/thin-lto-inlines.rs create mode 100644 tests/ui/lto/thin-lto-inlines2.rs create mode 100644 tests/ui/lto/weak-works.rs create mode 100644 tests/ui/lub-glb/empty-binder-future-compat.rs create mode 100644 tests/ui/lub-glb/empty-binders-err.rs create mode 100644 tests/ui/lub-glb/empty-binders-err.stderr create mode 100644 tests/ui/lub-glb/empty-binders.rs create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-eq.rs create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq1.rs create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr create mode 100644 tests/ui/lub-glb/old-lub-glb-hr-noteq2.rs create mode 100644 tests/ui/lub-glb/old-lub-glb-object.rs create mode 100644 tests/ui/lub-glb/old-lub-glb-object.stderr create mode 100644 tests/ui/macro-quote-test.rs create mode 100644 tests/ui/macro_backtrace/auxiliary/ping.rs create mode 100644 tests/ui/macro_backtrace/main.-Zmacro-backtrace.stderr create mode 100644 tests/ui/macro_backtrace/main.default.stderr create mode 100644 tests/ui/macro_backtrace/main.rs create mode 100644 tests/ui/macros/ambiguity-legacy-vs-modern.rs create mode 100644 tests/ui/macros/ambiguity-legacy-vs-modern.stderr create mode 100644 tests/ui/macros/assert-as-macro.rs create mode 100644 tests/ui/macros/assert-eq-macro-msg.rs create mode 100644 tests/ui/macros/assert-eq-macro-panic.rs create mode 100644 tests/ui/macros/assert-eq-macro-success.rs create mode 100644 tests/ui/macros/assert-eq-macro-unsized.rs create mode 100644 tests/ui/macros/assert-format-lazy.rs create mode 100644 tests/ui/macros/assert-macro-explicit.rs create mode 100644 tests/ui/macros/assert-macro-fmt.rs create mode 100644 tests/ui/macros/assert-macro-owned.rs create mode 100644 tests/ui/macros/assert-macro-static.rs create mode 100644 tests/ui/macros/assert-matches-macro-msg.rs create mode 100644 tests/ui/macros/assert-ne-macro-msg.rs create mode 100644 tests/ui/macros/assert-ne-macro-panic.rs create mode 100644 tests/ui/macros/assert-ne-macro-success.rs create mode 100644 tests/ui/macros/assert-ne-macro-unsized.rs create mode 100644 tests/ui/macros/assert-trailing-junk.rs create mode 100644 tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr create mode 100644 tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr create mode 100644 tests/ui/macros/assert.rs create mode 100644 tests/ui/macros/assert.with-generic-asset.stderr create mode 100644 tests/ui/macros/assert.without-generic-asset.stderr create mode 100644 tests/ui/macros/attr-empty-expr.rs create mode 100644 tests/ui/macros/attr-empty-expr.stderr create mode 100644 tests/ui/macros/attr-from-macro.rs create mode 100644 tests/ui/macros/auxiliary/attr-from-macro.rs create mode 100644 tests/ui/macros/auxiliary/define-macro.rs create mode 100644 tests/ui/macros/auxiliary/deprecated-macros.rs create mode 100644 tests/ui/macros/auxiliary/dollar-crate-nested-encoding.rs create mode 100644 tests/ui/macros/auxiliary/foreign-crate-macro-pat.rs create mode 100644 tests/ui/macros/auxiliary/issue-100199.rs create mode 100644 tests/ui/macros/auxiliary/issue-19163.rs create mode 100644 tests/ui/macros/auxiliary/issue-40469.rs create mode 100644 tests/ui/macros/auxiliary/issue-75982.rs create mode 100644 tests/ui/macros/auxiliary/macro-comma-support.rs create mode 100644 tests/ui/macros/auxiliary/macro-def-site-super.rs create mode 100644 tests/ui/macros/auxiliary/macro-in-other-crate.rs create mode 100644 tests/ui/macros/auxiliary/macro-include-items-expr.rs create mode 100644 tests/ui/macros/auxiliary/macro-include-items-item.rs create mode 100644 tests/ui/macros/auxiliary/macro_crate_def_only.rs create mode 100644 tests/ui/macros/auxiliary/macro_crate_nonterminal.rs create mode 100644 tests/ui/macros/auxiliary/macro_export_inner_module.rs create mode 100644 tests/ui/macros/auxiliary/macro_with_super_1.rs create mode 100644 tests/ui/macros/auxiliary/or-pattern.rs create mode 100644 tests/ui/macros/auxiliary/proc_macro_def.rs create mode 100644 tests/ui/macros/auxiliary/proc_macro_sequence.rs create mode 100644 tests/ui/macros/auxiliary/two_macros-rpass.rs create mode 100644 tests/ui/macros/auxiliary/two_macros.rs create mode 100644 tests/ui/macros/auxiliary/unstable-macros.rs create mode 100644 tests/ui/macros/auxiliary/use-macro-self.rs create mode 100644 tests/ui/macros/bad-concat.rs create mode 100644 tests/ui/macros/bad-concat.stderr create mode 100644 tests/ui/macros/bad_hello.rs create mode 100644 tests/ui/macros/bad_hello.stderr create mode 100644 tests/ui/macros/bang-after-name.fixed create mode 100644 tests/ui/macros/bang-after-name.rs create mode 100644 tests/ui/macros/bang-after-name.stderr create mode 100644 tests/ui/macros/best-failure.rs create mode 100644 tests/ui/macros/best-failure.stderr create mode 100644 tests/ui/macros/builtin-prelude-no-accidents.rs create mode 100644 tests/ui/macros/builtin-prelude-no-accidents.stderr create mode 100644 tests/ui/macros/builtin-std-paths-fail.rs create mode 100644 tests/ui/macros/builtin-std-paths-fail.stderr create mode 100644 tests/ui/macros/builtin-std-paths.rs create mode 100644 tests/ui/macros/cfg.rs create mode 100644 tests/ui/macros/cfg.stderr create mode 100644 tests/ui/macros/colorful-write-macros.rs create mode 100644 tests/ui/macros/concat-bytes-error.rs create mode 100644 tests/ui/macros/concat-bytes-error.stderr create mode 100644 tests/ui/macros/concat-bytes.rs create mode 100644 tests/ui/macros/concat-rpass.rs create mode 100644 tests/ui/macros/concat.rs create mode 100644 tests/ui/macros/concat.stderr create mode 100644 tests/ui/macros/conditional-debug-macro-on.rs create mode 100644 tests/ui/macros/cross-crate-pat-span.rs create mode 100644 tests/ui/macros/derive-in-eager-expansion-hang.rs create mode 100644 tests/ui/macros/derive-in-eager-expansion-hang.stderr create mode 100644 tests/ui/macros/die-macro-2.rs create mode 100644 tests/ui/macros/die-macro-expr.rs create mode 100644 tests/ui/macros/die-macro-pure.rs create mode 100644 tests/ui/macros/die-macro.rs create mode 100644 tests/ui/macros/doc-comment.rs create mode 100644 tests/ui/macros/dollar-crate-nested-encoding.rs create mode 100644 tests/ui/macros/duplicate-builtin.rs create mode 100644 tests/ui/macros/duplicate-builtin.stderr create mode 100644 tests/ui/macros/edition-macro-pats.rs create mode 100644 tests/ui/macros/empty-trailing-stmt.rs create mode 100644 tests/ui/macros/empty-trailing-stmt.stderr create mode 100644 tests/ui/macros/format-args-temporaries-async.rs create mode 100644 tests/ui/macros/format-args-temporaries-in-write.rs create mode 100644 tests/ui/macros/format-args-temporaries-in-write.stderr create mode 100644 tests/ui/macros/format-args-temporaries.rs create mode 100644 tests/ui/macros/format-foreign.rs create mode 100644 tests/ui/macros/format-foreign.stderr create mode 100644 tests/ui/macros/format-parse-errors.rs create mode 100644 tests/ui/macros/format-parse-errors.stderr create mode 100644 tests/ui/macros/format-unused-lables.rs create mode 100644 tests/ui/macros/format-unused-lables.stderr create mode 100644 tests/ui/macros/global-asm.rs create mode 100644 tests/ui/macros/global-asm.stderr create mode 100644 tests/ui/macros/html-literals.rs create mode 100644 tests/ui/macros/include-single-expr-helper-1.rs create mode 100644 tests/ui/macros/include-single-expr-helper.rs create mode 100644 tests/ui/macros/include-single-expr.rs create mode 100644 tests/ui/macros/include-single-expr.stderr create mode 100644 tests/ui/macros/issue-100199.rs create mode 100644 tests/ui/macros/issue-100199.stderr create mode 100644 tests/ui/macros/issue-102878.rs create mode 100644 tests/ui/macros/issue-102878.stderr create mode 100644 tests/ui/macros/issue-103529.rs create mode 100644 tests/ui/macros/issue-103529.stderr create mode 100644 tests/ui/macros/issue-104769-concat_bytes-invalid-literal.rs create mode 100644 tests/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr create mode 100644 tests/ui/macros/issue-105011.rs create mode 100644 tests/ui/macros/issue-105011.stderr create mode 100644 tests/ui/macros/issue-10536.rs create mode 100644 tests/ui/macros/issue-10536.stderr create mode 100644 tests/ui/macros/issue-16098.rs create mode 100644 tests/ui/macros/issue-16098.stderr create mode 100644 tests/ui/macros/issue-19163.rs create mode 100644 tests/ui/macros/issue-19163.stderr create mode 100644 tests/ui/macros/issue-21356.rs create mode 100644 tests/ui/macros/issue-21356.stderr create mode 100644 tests/ui/macros/issue-22463.rs create mode 100644 tests/ui/macros/issue-25274.rs create mode 100644 tests/ui/macros/issue-25385.rs create mode 100644 tests/ui/macros/issue-25385.stderr create mode 100644 tests/ui/macros/issue-26322.rs create mode 100644 tests/ui/macros/issue-29084.rs create mode 100644 tests/ui/macros/issue-29084.stderr create mode 100644 tests/ui/macros/issue-30143.rs create mode 100644 tests/ui/macros/issue-30143.stderr create mode 100644 tests/ui/macros/issue-33185.rs create mode 100644 tests/ui/macros/issue-34171.rs create mode 100644 tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs create mode 100644 tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr create mode 100644 tests/ui/macros/issue-35450.rs create mode 100644 tests/ui/macros/issue-35450.stderr create mode 100644 tests/ui/macros/issue-37175.rs create mode 100644 tests/ui/macros/issue-38715.rs create mode 100644 tests/ui/macros/issue-38715.stderr create mode 100644 tests/ui/macros/issue-39388.rs create mode 100644 tests/ui/macros/issue-39388.stderr create mode 100644 tests/ui/macros/issue-39404.rs create mode 100644 tests/ui/macros/issue-39404.stderr create mode 100644 tests/ui/macros/issue-40469.rs create mode 100644 tests/ui/macros/issue-40770.rs create mode 100644 tests/ui/macros/issue-41776.rs create mode 100644 tests/ui/macros/issue-41776.stderr create mode 100644 tests/ui/macros/issue-41803.rs create mode 100644 tests/ui/macros/issue-42954.fixed create mode 100644 tests/ui/macros/issue-42954.rs create mode 100644 tests/ui/macros/issue-42954.stderr create mode 100644 tests/ui/macros/issue-44127.rs create mode 100644 tests/ui/macros/issue-5060.rs create mode 100644 tests/ui/macros/issue-51848.rs create mode 100644 tests/ui/macros/issue-51848.stderr create mode 100644 tests/ui/macros/issue-52169.rs create mode 100644 tests/ui/macros/issue-54441.rs create mode 100644 tests/ui/macros/issue-54441.stderr create mode 100644 tests/ui/macros/issue-57597.rs create mode 100644 tests/ui/macros/issue-57597.stderr create mode 100644 tests/ui/macros/issue-58490.rs create mode 100644 tests/ui/macros/issue-58490.stderr create mode 100644 tests/ui/macros/issue-61033-1.rs create mode 100644 tests/ui/macros/issue-61033-1.stderr create mode 100644 tests/ui/macros/issue-61033-2.rs create mode 100644 tests/ui/macros/issue-61033-2.stderr create mode 100644 tests/ui/macros/issue-61053-different-kleene.rs create mode 100644 tests/ui/macros/issue-61053-different-kleene.stderr create mode 100644 tests/ui/macros/issue-61053-duplicate-binder.rs create mode 100644 tests/ui/macros/issue-61053-duplicate-binder.stderr create mode 100644 tests/ui/macros/issue-61053-missing-repetition.rs create mode 100644 tests/ui/macros/issue-61053-missing-repetition.stderr create mode 100644 tests/ui/macros/issue-61053-unbound.rs create mode 100644 tests/ui/macros/issue-61053-unbound.stderr create mode 100644 tests/ui/macros/issue-63102.rs create mode 100644 tests/ui/macros/issue-6596-1.rs create mode 100644 tests/ui/macros/issue-6596-1.stderr create mode 100644 tests/ui/macros/issue-68058.rs create mode 100644 tests/ui/macros/issue-68060.rs create mode 100644 tests/ui/macros/issue-68060.stderr create mode 100644 tests/ui/macros/issue-69838-dir/bar.rs create mode 100644 tests/ui/macros/issue-69838-dir/included.rs create mode 100644 tests/ui/macros/issue-69838-mods-relative-to-included-path.rs create mode 100644 tests/ui/macros/issue-70446.rs create mode 100644 tests/ui/macros/issue-75982-foreign-macro-weird-mod.rs create mode 100644 tests/ui/macros/issue-77475.rs create mode 100644 tests/ui/macros/issue-78325-inconsistent-resolution.rs create mode 100644 tests/ui/macros/issue-78325-inconsistent-resolution.stderr create mode 100644 tests/ui/macros/issue-78333.rs create mode 100644 tests/ui/macros/issue-78892-substitution-in-statement-attr.rs create mode 100644 tests/ui/macros/issue-81006.rs create mode 100644 tests/ui/macros/issue-81006.stderr create mode 100644 tests/ui/macros/issue-83340.rs create mode 100644 tests/ui/macros/issue-83340.stderr create mode 100644 tests/ui/macros/issue-83344.rs create mode 100644 tests/ui/macros/issue-83344.stderr create mode 100644 tests/ui/macros/issue-84195-lint-anon-const.rs create mode 100644 tests/ui/macros/issue-84195-lint-anon-const.stderr create mode 100644 tests/ui/macros/issue-84429-matches-edition.rs create mode 100644 tests/ui/macros/issue-84632-eager-expansion-recursion-limit.rs create mode 100644 tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr create mode 100644 tests/ui/macros/issue-86082-option-env-invalid-char.rs create mode 100644 tests/ui/macros/issue-86865.rs create mode 100644 tests/ui/macros/issue-86865.stderr create mode 100644 tests/ui/macros/issue-8709.rs create mode 100644 tests/ui/macros/issue-87877.rs create mode 100644 tests/ui/macros/issue-88206.rs create mode 100644 tests/ui/macros/issue-88206.stderr create mode 100644 tests/ui/macros/issue-88228.rs create mode 100644 tests/ui/macros/issue-88228.stderr create mode 100644 tests/ui/macros/issue-8851.rs create mode 100644 tests/ui/macros/issue-92267.rs create mode 100644 tests/ui/macros/issue-92267.stderr create mode 100644 tests/ui/macros/issue-95267.rs create mode 100644 tests/ui/macros/issue-95533.rs create mode 100644 tests/ui/macros/issue-98466-allow.rs create mode 100644 tests/ui/macros/issue-98466.fixed create mode 100644 tests/ui/macros/issue-98466.rs create mode 100644 tests/ui/macros/issue-98466.stderr create mode 100644 tests/ui/macros/issue-99261.rs create mode 100644 tests/ui/macros/issue-99265.fixed create mode 100644 tests/ui/macros/issue-99265.rs create mode 100644 tests/ui/macros/issue-99265.stderr create mode 100644 tests/ui/macros/issue-99907.fixed create mode 100644 tests/ui/macros/issue-99907.rs create mode 100644 tests/ui/macros/issue-99907.stderr create mode 100644 tests/ui/macros/lint-trailing-macro-call.rs create mode 100644 tests/ui/macros/lint-trailing-macro-call.stderr create mode 100644 tests/ui/macros/local-ambiguity-multiple-parsing-options.rs create mode 100644 tests/ui/macros/local-ambiguity-multiple-parsing-options.stderr create mode 100644 tests/ui/macros/log_syntax-trace_macros-macro-locations.rs create mode 100644 tests/ui/macros/log_syntax-trace_macros-macro-locations.stdout create mode 100644 tests/ui/macros/macro-2.rs create mode 100644 tests/ui/macros/macro-as-fn-body.rs create mode 100644 tests/ui/macros/macro-at-most-once-rep-2015-rpass.rs create mode 100644 tests/ui/macros/macro-at-most-once-rep-2015.rs create mode 100644 tests/ui/macros/macro-at-most-once-rep-2015.stderr create mode 100644 tests/ui/macros/macro-at-most-once-rep-2018-rpass.rs create mode 100644 tests/ui/macros/macro-at-most-once-rep-2018.rs create mode 100644 tests/ui/macros/macro-at-most-once-rep-2018.stderr create mode 100644 tests/ui/macros/macro-attribute-expansion.rs create mode 100644 tests/ui/macros/macro-attribute.rs create mode 100644 tests/ui/macros/macro-attribute.stderr create mode 100644 tests/ui/macros/macro-attributes.rs create mode 100644 tests/ui/macros/macro-backtrace-invalid-internals.rs create mode 100644 tests/ui/macros/macro-backtrace-invalid-internals.stderr create mode 100644 tests/ui/macros/macro-backtrace-nested.rs create mode 100644 tests/ui/macros/macro-backtrace-nested.stderr create mode 100644 tests/ui/macros/macro-backtrace-println.rs create mode 100644 tests/ui/macros/macro-backtrace-println.stderr create mode 100644 tests/ui/macros/macro-block-nonterminal.rs create mode 100644 tests/ui/macros/macro-comma-behavior-rpass.rs create mode 100644 tests/ui/macros/macro-comma-behavior.core.stderr create mode 100644 tests/ui/macros/macro-comma-behavior.rs create mode 100644 tests/ui/macros/macro-comma-behavior.std.stderr create mode 100644 tests/ui/macros/macro-comma-support-rpass.rs create mode 100644 tests/ui/macros/macro-comma-support.rs create mode 100644 tests/ui/macros/macro-comma-support.stderr create mode 100644 tests/ui/macros/macro-context.rs create mode 100644 tests/ui/macros/macro-context.stderr create mode 100644 tests/ui/macros/macro-crate-def-only.rs create mode 100644 tests/ui/macros/macro-crate-nonterminal-non-root.rs create mode 100644 tests/ui/macros/macro-crate-nonterminal-non-root.stderr create mode 100644 tests/ui/macros/macro-crate-nonterminal-renamed.rs create mode 100644 tests/ui/macros/macro-crate-nonterminal.rs create mode 100644 tests/ui/macros/macro-crate-use.rs create mode 100644 tests/ui/macros/macro-deep_expansion.rs create mode 100644 tests/ui/macros/macro-def-site-super.rs create mode 100644 tests/ui/macros/macro-delimiter-significance.rs create mode 100644 tests/ui/macros/macro-deprecation.rs create mode 100644 tests/ui/macros/macro-deprecation.stderr create mode 100644 tests/ui/macros/macro-doc-comments.rs create mode 100644 tests/ui/macros/macro-doc-escapes.rs create mode 100644 tests/ui/macros/macro-doc-raw-str-hashes.rs create mode 100644 tests/ui/macros/macro-error.rs create mode 100644 tests/ui/macros/macro-error.stderr create mode 100644 tests/ui/macros/macro-expanded-include/file.txt create mode 100644 tests/ui/macros/macro-expanded-include/foo/mod.rs create mode 100644 tests/ui/macros/macro-expanded-include/test.rs create mode 100644 tests/ui/macros/macro-expansion-tests.rs create mode 100644 tests/ui/macros/macro-expansion-tests.stderr create mode 100644 tests/ui/macros/macro-export-inner-module.rs create mode 100644 tests/ui/macros/macro-first-set.rs create mode 100644 tests/ui/macros/macro-follow-rpass.rs create mode 100644 tests/ui/macros/macro-follow.rs create mode 100644 tests/ui/macros/macro-follow.stderr create mode 100644 tests/ui/macros/macro-followed-by-seq-bad.rs create mode 100644 tests/ui/macros/macro-followed-by-seq-bad.stderr create mode 100644 tests/ui/macros/macro-followed-by-seq.rs create mode 100644 tests/ui/macros/macro-in-expression-context-2.rs create mode 100644 tests/ui/macros/macro-in-expression-context-2.stderr create mode 100644 tests/ui/macros/macro-in-expression-context.fixed create mode 100644 tests/ui/macros/macro-in-expression-context.rs create mode 100644 tests/ui/macros/macro-in-expression-context.stderr create mode 100644 tests/ui/macros/macro-in-fn.rs create mode 100644 tests/ui/macros/macro-include-items.rs create mode 100644 tests/ui/macros/macro-inner-attributes.rs create mode 100644 tests/ui/macros/macro-inner-attributes.stderr create mode 100644 tests/ui/macros/macro-input-future-proofing.rs create mode 100644 tests/ui/macros/macro-input-future-proofing.stderr create mode 100644 tests/ui/macros/macro-interpolation.rs create mode 100644 tests/ui/macros/macro-invalid-fragment-spec.rs create mode 100644 tests/ui/macros/macro-invalid-fragment-spec.stderr create mode 100644 tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs create mode 100644 tests/ui/macros/macro-lifetime-used-with-bound.rs create mode 100644 tests/ui/macros/macro-lifetime-used-with-labels.rs create mode 100644 tests/ui/macros/macro-lifetime-used-with-static.rs create mode 100644 tests/ui/macros/macro-lifetime.rs create mode 100644 tests/ui/macros/macro-literal.rs create mode 100644 tests/ui/macros/macro-local-data-key-priv.rs create mode 100644 tests/ui/macros/macro-local-data-key-priv.stderr create mode 100644 tests/ui/macros/macro-match-nonterminal.rs create mode 100644 tests/ui/macros/macro-match-nonterminal.stderr create mode 100644 tests/ui/macros/macro-meta-items-modern.rs create mode 100644 tests/ui/macros/macro-meta-items.rs create mode 100644 tests/ui/macros/macro-method-issue-4621.rs create mode 100644 tests/ui/macros/macro-missing-delimiters.rs create mode 100644 tests/ui/macros/macro-missing-delimiters.stderr create mode 100644 tests/ui/macros/macro-missing-fragment-deduplication.rs create mode 100644 tests/ui/macros/macro-missing-fragment-deduplication.stderr create mode 100644 tests/ui/macros/macro-missing-fragment.rs create mode 100644 tests/ui/macros/macro-missing-fragment.stderr create mode 100644 tests/ui/macros/macro-multiple-items.rs create mode 100644 tests/ui/macros/macro-multiple-matcher-bindings.rs create mode 100644 tests/ui/macros/macro-multiple-matcher-bindings.stderr create mode 100644 tests/ui/macros/macro-name-typo.rs create mode 100644 tests/ui/macros/macro-name-typo.stderr create mode 100644 tests/ui/macros/macro-named-default.rs create mode 100644 tests/ui/macros/macro-nested_definition_issue-31946.rs create mode 100644 tests/ui/macros/macro-nested_expr.rs create mode 100644 tests/ui/macros/macro-nested_stmt_macros.rs create mode 100644 tests/ui/macros/macro-non-lifetime.rs create mode 100644 tests/ui/macros/macro-non-lifetime.stderr create mode 100644 tests/ui/macros/macro-nt-list.rs create mode 100644 tests/ui/macros/macro-of-higher-order.rs create mode 100644 tests/ui/macros/macro-or-patterns-back-compat.fixed create mode 100644 tests/ui/macros/macro-or-patterns-back-compat.rs create mode 100644 tests/ui/macros/macro-or-patterns-back-compat.stderr create mode 100644 tests/ui/macros/macro-outer-attributes.rs create mode 100644 tests/ui/macros/macro-outer-attributes.stderr create mode 100644 tests/ui/macros/macro-parameter-span.rs create mode 100644 tests/ui/macros/macro-parameter-span.stderr create mode 100644 tests/ui/macros/macro-pat-follow-2018.rs create mode 100644 tests/ui/macros/macro-pat-follow.rs create mode 100644 tests/ui/macros/macro-pat-neg-lit.rs create mode 100644 tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs create mode 100644 tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr create mode 100644 tests/ui/macros/macro-pat-pattern-followed-by-or.rs create mode 100644 tests/ui/macros/macro-pat.rs create mode 100644 tests/ui/macros/macro-pat2021-pattern-followed-by-or.rs create mode 100644 tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr create mode 100644 tests/ui/macros/macro-path-prelude-fail-1.rs create mode 100644 tests/ui/macros/macro-path-prelude-fail-1.stderr create mode 100644 tests/ui/macros/macro-path-prelude-fail-2.rs create mode 100644 tests/ui/macros/macro-path-prelude-fail-2.stderr create mode 100644 tests/ui/macros/macro-path-prelude-fail-3.rs create mode 100644 tests/ui/macros/macro-path-prelude-fail-3.stderr create mode 100644 tests/ui/macros/macro-path-prelude-fail-4.rs create mode 100644 tests/ui/macros/macro-path-prelude-fail-4.stderr create mode 100644 tests/ui/macros/macro-path-prelude-pass.rs create mode 100644 tests/ui/macros/macro-path-prelude-shadowing.rs create mode 100644 tests/ui/macros/macro-path-prelude-shadowing.stderr create mode 100644 tests/ui/macros/macro-path.rs create mode 100644 tests/ui/macros/macro-pub-matcher.rs create mode 100644 tests/ui/macros/macro-reexport-removed.rs create mode 100644 tests/ui/macros/macro-reexport-removed.stderr create mode 100644 tests/ui/macros/macro-seq-followed-by-seq.rs create mode 100644 tests/ui/macros/macro-shadowing-relaxed.rs create mode 100644 tests/ui/macros/macro-shadowing.rs create mode 100644 tests/ui/macros/macro-shadowing.stderr create mode 100644 tests/ui/macros/macro-stability-rpass.rs create mode 100644 tests/ui/macros/macro-stability.rs create mode 100644 tests/ui/macros/macro-stability.stderr create mode 100644 tests/ui/macros/macro-stmt-matchers.rs create mode 100644 tests/ui/macros/macro-stmt.rs create mode 100644 tests/ui/macros/macro-stmt_macro_in_expr_macro.rs create mode 100644 tests/ui/macros/macro-tt-followed-by-seq.rs create mode 100644 tests/ui/macros/macro-tt-matchers.rs create mode 100644 tests/ui/macros/macro-use-all-and-none.rs create mode 100644 tests/ui/macros/macro-use-all-and-none.stderr create mode 100644 tests/ui/macros/macro-use-all.rs create mode 100644 tests/ui/macros/macro-use-bad-args-1.rs create mode 100644 tests/ui/macros/macro-use-bad-args-1.stderr create mode 100644 tests/ui/macros/macro-use-bad-args-2.rs create mode 100644 tests/ui/macros/macro-use-bad-args-2.stderr create mode 100644 tests/ui/macros/macro-use-both.rs create mode 100644 tests/ui/macros/macro-use-one.rs create mode 100644 tests/ui/macros/macro-use-scope.rs create mode 100644 tests/ui/macros/macro-use-undef.rs create mode 100644 tests/ui/macros/macro-use-undef.stderr create mode 100644 tests/ui/macros/macro-use-wrong-name.rs create mode 100644 tests/ui/macros/macro-use-wrong-name.stderr create mode 100644 tests/ui/macros/macro-with-attrs1.rs create mode 100644 tests/ui/macros/macro-with-attrs2.rs create mode 100644 tests/ui/macros/macro-with-braces-in-expr-position.rs create mode 100644 tests/ui/macros/macro_path_as_generic_bound.rs create mode 100644 tests/ui/macros/macro_path_as_generic_bound.stderr create mode 100644 tests/ui/macros/macro_rules-unmatchable-literals.rs create mode 100644 tests/ui/macros/macro_rules-unmatchable-literals.stderr create mode 100644 tests/ui/macros/macro_undefined.rs create mode 100644 tests/ui/macros/macro_undefined.stderr create mode 100644 tests/ui/macros/macro_with_super_2.rs create mode 100644 tests/ui/macros/macros-in-extern.rs create mode 100644 tests/ui/macros/macros-nonfatal-errors.rs create mode 100644 tests/ui/macros/macros-nonfatal-errors.stderr create mode 100644 tests/ui/macros/malformed_macro_lhs.rs create mode 100644 tests/ui/macros/malformed_macro_lhs.stderr create mode 100644 tests/ui/macros/meta-item-absolute-path.rs create mode 100644 tests/ui/macros/meta-item-absolute-path.stderr create mode 100644 tests/ui/macros/meta-variable-depth-outside-repeat.rs create mode 100644 tests/ui/macros/meta-variable-depth-outside-repeat.stderr create mode 100644 tests/ui/macros/meta-variable-misuse.rs create mode 100644 tests/ui/macros/missing-bang-in-decl.fixed create mode 100644 tests/ui/macros/missing-bang-in-decl.rs create mode 100644 tests/ui/macros/missing-bang-in-decl.stderr create mode 100644 tests/ui/macros/missing-comma.rs create mode 100644 tests/ui/macros/missing-comma.stderr create mode 100644 tests/ui/macros/must-use-in-macro-55516.rs create mode 100644 tests/ui/macros/must-use-in-macro-55516.stderr create mode 100644 tests/ui/macros/no-std-macros.rs create mode 100644 tests/ui/macros/none-delim-lookahead.rs create mode 100644 tests/ui/macros/nonterminal-matching.rs create mode 100644 tests/ui/macros/nonterminal-matching.stderr create mode 100644 tests/ui/macros/not-utf8.bin create mode 100644 tests/ui/macros/not-utf8.rs create mode 100644 tests/ui/macros/not-utf8.stderr create mode 100644 tests/ui/macros/out-of-order-shadowing.rs create mode 100644 tests/ui/macros/out-of-order-shadowing.stderr create mode 100644 tests/ui/macros/parse-complex-macro-invoc-op.rs create mode 100644 tests/ui/macros/paths-in-macro-invocations.rs create mode 100644 tests/ui/macros/proc_macro.rs create mode 100644 tests/ui/macros/pub-item-inside-macro.rs create mode 100644 tests/ui/macros/pub-method-inside-macro.rs create mode 100644 tests/ui/macros/recovery-allowed.rs create mode 100644 tests/ui/macros/recovery-allowed.stderr create mode 100644 tests/ui/macros/recovery-forbidden.rs create mode 100644 tests/ui/macros/restricted-shadowing-legacy.rs create mode 100644 tests/ui/macros/restricted-shadowing-legacy.stderr create mode 100644 tests/ui/macros/restricted-shadowing-modern.rs create mode 100644 tests/ui/macros/restricted-shadowing-modern.stderr create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs create mode 100644 tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs create mode 100644 tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr create mode 100644 tests/ui/macros/same-sequence-span.rs create mode 100644 tests/ui/macros/same-sequence-span.stderr create mode 100644 tests/ui/macros/semi-after-macro-ty.rs create mode 100644 tests/ui/macros/span-covering-argument-1.rs create mode 100644 tests/ui/macros/span-covering-argument-1.stderr create mode 100644 tests/ui/macros/stmt_expr_attr_macro_parse.rs create mode 100644 tests/ui/macros/stringify.rs create mode 100644 tests/ui/macros/syntax-error-recovery.rs create mode 100644 tests/ui/macros/syntax-error-recovery.stderr create mode 100644 tests/ui/macros/syntax-extension-cfg.rs create mode 100644 tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment create mode 100644 tests/ui/macros/syntax-extension-source-utils.rs create mode 100644 tests/ui/macros/trace-macro.rs create mode 100644 tests/ui/macros/trace-macro.stderr create mode 100644 tests/ui/macros/trace_faulty_macros.rs create mode 100644 tests/ui/macros/trace_faulty_macros.stderr create mode 100644 tests/ui/macros/trace_macros-format.rs create mode 100644 tests/ui/macros/trace_macros-format.stderr create mode 100644 tests/ui/macros/try-macro.rs create mode 100644 tests/ui/macros/two-macro-use.rs create mode 100644 tests/ui/macros/type-macros-hlist.rs create mode 100644 tests/ui/macros/type-macros-simple.rs create mode 100644 tests/ui/macros/typeck-macro-interaction-issue-8852.rs create mode 100644 tests/ui/macros/unimplemented-macro-panic.rs create mode 100644 tests/ui/macros/unknown-builtin.rs create mode 100644 tests/ui/macros/unknown-builtin.stderr create mode 100644 tests/ui/macros/unreachable-arg.edition_2021.stderr create mode 100644 tests/ui/macros/unreachable-arg.rs create mode 100644 tests/ui/macros/unreachable-fmt-msg.rs create mode 100644 tests/ui/macros/unreachable-format-arg.rs create mode 100644 tests/ui/macros/unreachable-format-args.edition_2015.stderr create mode 100644 tests/ui/macros/unreachable-format-args.rs create mode 100644 tests/ui/macros/unreachable-macro-panic.rs create mode 100644 tests/ui/macros/unreachable-static-msg.rs create mode 100644 tests/ui/macros/unreachable.rs create mode 100644 tests/ui/macros/use-macro-self.rs create mode 100644 tests/ui/macros/vec-macro-in-pattern.rs create mode 100644 tests/ui/macros/vec-macro-in-pattern.stderr create mode 100644 tests/ui/main-wrong-location.rs create mode 100644 tests/ui/main-wrong-location.stderr create mode 100644 tests/ui/main-wrong-type.rs create mode 100644 tests/ui/main-wrong-type.stderr create mode 100644 tests/ui/malformed/issue-69341-malformed-derive-inert.rs create mode 100644 tests/ui/malformed/issue-69341-malformed-derive-inert.stderr create mode 100644 tests/ui/malformed/malformed-derive-entry.rs create mode 100644 tests/ui/malformed/malformed-derive-entry.stderr create mode 100644 tests/ui/malformed/malformed-interpolated.rs create mode 100644 tests/ui/malformed/malformed-interpolated.stderr create mode 100644 tests/ui/malformed/malformed-meta-delim.rs create mode 100644 tests/ui/malformed/malformed-meta-delim.stderr create mode 100644 tests/ui/malformed/malformed-plugin-1.rs create mode 100644 tests/ui/malformed/malformed-plugin-1.stderr create mode 100644 tests/ui/malformed/malformed-plugin-2.rs create mode 100644 tests/ui/malformed/malformed-plugin-2.stderr create mode 100644 tests/ui/malformed/malformed-plugin-3.rs create mode 100644 tests/ui/malformed/malformed-plugin-3.stderr create mode 100644 tests/ui/malformed/malformed-regressions.rs create mode 100644 tests/ui/malformed/malformed-regressions.stderr create mode 100644 tests/ui/malformed/malformed-special-attrs.rs create mode 100644 tests/ui/malformed/malformed-special-attrs.stderr create mode 100644 tests/ui/manual/manual-link-bad-form.rs create mode 100644 tests/ui/manual/manual-link-bad-form.stderr create mode 100644 tests/ui/manual/manual-link-bad-kind.rs create mode 100644 tests/ui/manual/manual-link-bad-kind.stderr create mode 100644 tests/ui/manual/manual-link-bad-search-path.rs create mode 100644 tests/ui/manual/manual-link-bad-search-path.stderr create mode 100644 tests/ui/manual/manual-link-framework.rs create mode 100644 tests/ui/manual/manual-link-framework.stderr create mode 100644 tests/ui/manual/manual-link-unsupported-kind.rs create mode 100644 tests/ui/manual/manual-link-unsupported-kind.stderr create mode 100644 tests/ui/marker_trait_attr/issue-61651-type-mismatch.rs create mode 100644 tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs create mode 100644 tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr create mode 100644 tests/ui/marker_trait_attr/marker-attribute-with-values.rs create mode 100644 tests/ui/marker_trait_attr/marker-attribute-with-values.stderr create mode 100644 tests/ui/marker_trait_attr/marker-trait-with-associated-items.rs create mode 100644 tests/ui/marker_trait_attr/marker-trait-with-associated-items.stderr create mode 100644 tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs create mode 100644 tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr create mode 100644 tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs create mode 100644 tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs create mode 100644 tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr create mode 100644 tests/ui/marker_trait_attr/overlap-marker-trait.rs create mode 100644 tests/ui/marker_trait_attr/overlap-marker-trait.stderr create mode 100644 tests/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs create mode 100644 tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs create mode 100644 tests/ui/marker_trait_attr/override-item-on-marker-trait.rs create mode 100644 tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr create mode 100644 tests/ui/marker_trait_attr/region-overlap.rs create mode 100644 tests/ui/marker_trait_attr/region-overlap.stderr create mode 100644 tests/ui/marker_trait_attr/unsound-overlap.rs create mode 100644 tests/ui/marker_trait_attr/unsound-overlap.stderr create mode 100644 tests/ui/match/auxiliary/match_non_exhaustive_lib.rs create mode 100644 tests/ui/match/const_non_normal_zst_ref_pattern.rs create mode 100644 tests/ui/match/expr-match-panic-fn.rs create mode 100644 tests/ui/match/expr-match-panic.rs create mode 100644 tests/ui/match/expr_before_ident_pat.rs create mode 100644 tests/ui/match/expr_before_ident_pat.stderr create mode 100644 tests/ui/match/guards.rs create mode 100644 tests/ui/match/issue-11319.rs create mode 100644 tests/ui/match/issue-11319.stderr create mode 100644 tests/ui/match/issue-11940.rs create mode 100644 tests/ui/match/issue-12552.rs create mode 100644 tests/ui/match/issue-12552.stderr create mode 100644 tests/ui/match/issue-18060.rs create mode 100644 tests/ui/match/issue-26251.rs create mode 100644 tests/ui/match/issue-26996.rs create mode 100644 tests/ui/match/issue-27021.rs create mode 100644 tests/ui/match/issue-33498.rs create mode 100644 tests/ui/match/issue-41255.rs create mode 100644 tests/ui/match/issue-41255.stderr create mode 100644 tests/ui/match/issue-42679.rs create mode 100644 tests/ui/match/issue-46920-byte-array-patterns.rs create mode 100644 tests/ui/match/issue-5530.rs create mode 100644 tests/ui/match/issue-56685.rs create mode 100644 tests/ui/match/issue-56685.stderr create mode 100644 tests/ui/match/issue-70972-dyn-trait.rs create mode 100644 tests/ui/match/issue-70972-dyn-trait.stderr create mode 100644 tests/ui/match/issue-72680.rs create mode 100644 tests/ui/match/issue-72896.rs create mode 100644 tests/ui/match/issue-74050-end-span.rs create mode 100644 tests/ui/match/issue-74050-end-span.stderr create mode 100644 tests/ui/match/issue-82392.rs create mode 100644 tests/ui/match/issue-82392.stdout create mode 100644 tests/ui/match/issue-82866.rs create mode 100644 tests/ui/match/issue-82866.stderr create mode 100644 tests/ui/match/issue-84434.rs create mode 100644 tests/ui/match/issue-91058.rs create mode 100644 tests/ui/match/issue-91058.stderr create mode 100644 tests/ui/match/issue-92100.rs create mode 100644 tests/ui/match/issue-92100.stderr create mode 100644 tests/ui/match/match-arm-resolving-to-never.rs create mode 100644 tests/ui/match/match-arm-resolving-to-never.stderr create mode 100644 tests/ui/match/match-bot-panic.rs create mode 100644 tests/ui/match/match-disc-bot.rs create mode 100644 tests/ui/match/match-fn-call.rs create mode 100644 tests/ui/match/match-fn-call.stderr create mode 100644 tests/ui/match/match-ill-type2.rs create mode 100644 tests/ui/match/match-ill-type2.stderr create mode 100644 tests/ui/match/match-incompat-type-semi.rs create mode 100644 tests/ui/match/match-incompat-type-semi.stderr create mode 100644 tests/ui/match/match-join.rs create mode 100644 tests/ui/match/match-join.stderr create mode 100644 tests/ui/match/match-no-arms-unreachable-after.rs create mode 100644 tests/ui/match/match-no-arms-unreachable-after.stderr create mode 100644 tests/ui/match/match-on-negative-integer-ranges.rs create mode 100644 tests/ui/match/match-pattern-field-mismatch-2.rs create mode 100644 tests/ui/match/match-pattern-field-mismatch-2.stderr create mode 100644 tests/ui/match/match-pattern-field-mismatch.rs create mode 100644 tests/ui/match/match-pattern-field-mismatch.stderr create mode 100644 tests/ui/match/match-range-fail-2.rs create mode 100644 tests/ui/match/match-range-fail-2.stderr create mode 100644 tests/ui/match/match-range-fail.rs create mode 100644 tests/ui/match/match-range-fail.stderr create mode 100644 tests/ui/match/match-ref-mut-invariance.rs create mode 100644 tests/ui/match/match-ref-mut-invariance.stderr create mode 100644 tests/ui/match/match-ref-mut-let-invariance.rs create mode 100644 tests/ui/match/match-ref-mut-let-invariance.stderr create mode 100644 tests/ui/match/match-ref-mut-stability.rs create mode 100644 tests/ui/match/match-struct.rs create mode 100644 tests/ui/match/match-struct.stderr create mode 100644 tests/ui/match/match-tag-nullary.rs create mode 100644 tests/ui/match/match-tag-nullary.stderr create mode 100644 tests/ui/match/match-tag-unary.rs create mode 100644 tests/ui/match/match-tag-unary.stderr create mode 100644 tests/ui/match/match-type-err-first-arm.rs create mode 100644 tests/ui/match/match-type-err-first-arm.stderr create mode 100644 tests/ui/match/match-unresolved-one-arm.rs create mode 100644 tests/ui/match/match-unresolved-one-arm.stderr create mode 100644 tests/ui/match/match-vec-mismatch-2.rs create mode 100644 tests/ui/match/match-vec-mismatch-2.stderr create mode 100644 tests/ui/match/match-wildcards.rs create mode 100644 tests/ui/match/match_non_exhaustive.rs create mode 100644 tests/ui/match/match_non_exhaustive.stderr create mode 100644 tests/ui/match/pattern-deref-miscompile.rs create mode 100644 tests/ui/match/single-line.rs create mode 100644 tests/ui/match/single-line.stderr create mode 100644 tests/ui/max-min-classes.rs create mode 100644 tests/ui/maximal_mir_to_hir_coverage.rs create mode 100644 tests/ui/maybe-bounds.rs create mode 100644 tests/ui/maybe-bounds.stderr create mode 100644 tests/ui/meta/auxiliary/env.rs create mode 100644 tests/ui/meta/expected-error-correct-rev.a.stderr create mode 100644 tests/ui/meta/expected-error-correct-rev.rs create mode 100644 tests/ui/meta/meta-expected-error-wrong-rev.a.stderr create mode 100644 tests/ui/meta/meta-expected-error-wrong-rev.rs create mode 100644 tests/ui/meta/revision-bad.rs create mode 100644 tests/ui/meta/revision-ok.rs create mode 100644 tests/ui/meta/rustc-env.rs create mode 100644 tests/ui/methods/assign-to-method.rs create mode 100644 tests/ui/methods/assign-to-method.stderr create mode 100644 tests/ui/methods/auxiliary/ambig_impl_2_lib.rs create mode 100644 tests/ui/methods/auxiliary/macro-in-other-crate.rs create mode 100644 tests/ui/methods/auxiliary/method_self_arg1.rs create mode 100644 tests/ui/methods/auxiliary/method_self_arg2.rs create mode 100644 tests/ui/methods/field-method-suggestion-using-return-ty.rs create mode 100644 tests/ui/methods/field-method-suggestion-using-return-ty.stderr create mode 100644 tests/ui/methods/issues/issue-105732.rs create mode 100644 tests/ui/methods/issues/issue-105732.stderr create mode 100644 tests/ui/methods/issues/issue-61525.rs create mode 100644 tests/ui/methods/issues/issue-61525.stderr create mode 100644 tests/ui/methods/issues/issue-84495.rs create mode 100644 tests/ui/methods/issues/issue-84495.stderr create mode 100644 tests/ui/methods/issues/issue-90315.rs create mode 100644 tests/ui/methods/issues/issue-90315.stderr create mode 100644 tests/ui/methods/issues/issue-94581.rs create mode 100644 tests/ui/methods/issues/issue-94581.stderr create mode 100644 tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs create mode 100644 tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr create mode 100644 tests/ui/methods/method-ambig-two-traits-cross-crate.rs create mode 100644 tests/ui/methods/method-ambig-two-traits-cross-crate.stderr create mode 100644 tests/ui/methods/method-ambig-two-traits-from-bounds.rs create mode 100644 tests/ui/methods/method-ambig-two-traits-from-bounds.stderr create mode 100644 tests/ui/methods/method-ambig-two-traits-from-impls.rs create mode 100644 tests/ui/methods/method-ambig-two-traits-from-impls.stderr create mode 100644 tests/ui/methods/method-ambig-two-traits-from-impls2.rs create mode 100644 tests/ui/methods/method-ambig-two-traits-from-impls2.stderr create mode 100644 tests/ui/methods/method-ambig-two-traits-with-default-method.rs create mode 100644 tests/ui/methods/method-ambig-two-traits-with-default-method.stderr create mode 100644 tests/ui/methods/method-argument-inference-associated-type.rs create mode 100644 tests/ui/methods/method-call-err-msg.rs create mode 100644 tests/ui/methods/method-call-err-msg.stderr create mode 100644 tests/ui/methods/method-call-lifetime-args-fail.rs create mode 100644 tests/ui/methods/method-call-lifetime-args-fail.stderr create mode 100644 tests/ui/methods/method-call-lifetime-args-lint-fail.rs create mode 100644 tests/ui/methods/method-call-lifetime-args-lint-fail.stderr create mode 100644 tests/ui/methods/method-call-lifetime-args-lint.rs create mode 100644 tests/ui/methods/method-call-lifetime-args-lint.stderr create mode 100644 tests/ui/methods/method-call-lifetime-args-subst-index.rs create mode 100644 tests/ui/methods/method-call-lifetime-args-unresolved.rs create mode 100644 tests/ui/methods/method-call-lifetime-args-unresolved.stderr create mode 100644 tests/ui/methods/method-call-lifetime-args.rs create mode 100644 tests/ui/methods/method-call-lifetime-args.stderr create mode 100644 tests/ui/methods/method-call-type-binding.rs create mode 100644 tests/ui/methods/method-call-type-binding.stderr create mode 100644 tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs create mode 100644 tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr create mode 100644 tests/ui/methods/method-early-bound-lifetimes-on-self.rs create mode 100644 tests/ui/methods/method-lookup-order.rs create mode 100644 tests/ui/methods/method-macro-backtrace.rs create mode 100644 tests/ui/methods/method-macro-backtrace.stderr create mode 100644 tests/ui/methods/method-missing-call.rs create mode 100644 tests/ui/methods/method-missing-call.stderr create mode 100644 tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs create mode 100644 tests/ui/methods/method-normalize-bounds-issue-20604.rs create mode 100644 tests/ui/methods/method-not-found-generic-arg-elision.rs create mode 100644 tests/ui/methods/method-not-found-generic-arg-elision.stderr create mode 100644 tests/ui/methods/method-on-ambiguous-numeric-type.rs create mode 100644 tests/ui/methods/method-on-ambiguous-numeric-type.stderr create mode 100644 tests/ui/methods/method-path-in-pattern.rs create mode 100644 tests/ui/methods/method-path-in-pattern.stderr create mode 100644 tests/ui/methods/method-probe-no-guessing-dyn-trait.rs create mode 100644 tests/ui/methods/method-projection.rs create mode 100644 tests/ui/methods/method-recursive-blanket-impl.rs create mode 100644 tests/ui/methods/method-resolvable-path-in-pattern.rs create mode 100644 tests/ui/methods/method-resolvable-path-in-pattern.stderr create mode 100644 tests/ui/methods/method-self-arg-1.rs create mode 100644 tests/ui/methods/method-self-arg-1.stderr create mode 100644 tests/ui/methods/method-self-arg-2.rs create mode 100644 tests/ui/methods/method-self-arg-2.stderr create mode 100644 tests/ui/methods/method-self-arg-aux1.rs create mode 100644 tests/ui/methods/method-self-arg-aux2.rs create mode 100644 tests/ui/methods/method-self-arg-trait.rs create mode 100644 tests/ui/methods/method-self-arg.rs create mode 100644 tests/ui/methods/method-trait-object-with-hrtb.rs create mode 100644 tests/ui/methods/method-two-trait-defer-resolution-1.rs create mode 100644 tests/ui/methods/method-two-trait-defer-resolution-2.rs create mode 100644 tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs create mode 100644 tests/ui/methods/method-where-clause.rs create mode 100644 tests/ui/minus-string.rs create mode 100644 tests/ui/minus-string.stderr create mode 100644 tests/ui/mir-dataflow/README.md create mode 100644 tests/ui/mir-dataflow/def-inits-1.rs create mode 100644 tests/ui/mir-dataflow/def-inits-1.stderr create mode 100644 tests/ui/mir-dataflow/inits-1.rs create mode 100644 tests/ui/mir-dataflow/inits-1.stderr create mode 100644 tests/ui/mir-dataflow/liveness-enum.rs create mode 100644 tests/ui/mir-dataflow/liveness-enum.stderr create mode 100644 tests/ui/mir-dataflow/liveness-projection.rs create mode 100644 tests/ui/mir-dataflow/liveness-projection.stderr create mode 100644 tests/ui/mir-dataflow/liveness-ptr.rs create mode 100644 tests/ui/mir-dataflow/liveness-ptr.stderr create mode 100644 tests/ui/mir-dataflow/uninits-1.rs create mode 100644 tests/ui/mir-dataflow/uninits-1.stderr create mode 100644 tests/ui/mir-dataflow/uninits-2.rs create mode 100644 tests/ui/mir-dataflow/uninits-2.stderr create mode 100644 tests/ui/mir-unpretty.rs create mode 100644 tests/ui/mir-unpretty.stderr create mode 100644 tests/ui/mir/auxiliary/issue_76375_aux.rs create mode 100644 tests/ui/mir/auxiliary/mir_external_refs.rs create mode 100644 tests/ui/mir/drop-elaboration-after-borrowck-error.rs create mode 100644 tests/ui/mir/drop-elaboration-after-borrowck-error.stderr create mode 100644 tests/ui/mir/important-higher-ranked-regions.rs create mode 100644 tests/ui/mir/issue-101844.rs create mode 100644 tests/ui/mir/issue-102389.rs create mode 100644 tests/ui/mir/issue-102389.stderr create mode 100644 tests/ui/mir/issue-105809.rs create mode 100644 tests/ui/mir/issue-106062.rs create mode 100644 tests/ui/mir/issue-106062.stderr create mode 100644 tests/ui/mir/issue-29227.rs create mode 100644 tests/ui/mir/issue-46845.rs create mode 100644 tests/ui/mir/issue-60390.rs create mode 100644 tests/ui/mir/issue-66851.rs create mode 100644 tests/ui/mir/issue-66930.rs create mode 100644 tests/ui/mir/issue-67639-normalization-ice.rs create mode 100644 tests/ui/mir/issue-67710-inline-projection.rs create mode 100644 tests/ui/mir/issue-67947.rs create mode 100644 tests/ui/mir/issue-67947.stderr create mode 100644 tests/ui/mir/issue-68841.rs create mode 100644 tests/ui/mir/issue-71793-inline-args-storage.rs create mode 100644 tests/ui/mir/issue-73914.rs create mode 100644 tests/ui/mir/issue-74739.rs create mode 100644 tests/ui/mir/issue-75053.rs create mode 100644 tests/ui/mir/issue-75053.stderr create mode 100644 tests/ui/mir/issue-75419-validation-impl-trait.rs create mode 100644 tests/ui/mir/issue-76248.rs create mode 100644 tests/ui/mir/issue-76375.rs create mode 100644 tests/ui/mir/issue-76740-copy-propagation.rs create mode 100644 tests/ui/mir/issue-76803-branches-not-same.rs create mode 100644 tests/ui/mir/issue-77002.rs create mode 100644 tests/ui/mir/issue-77359-simplify-arm-identity.rs create mode 100644 tests/ui/mir/issue-77911.rs create mode 100644 tests/ui/mir/issue-78496.rs create mode 100644 tests/ui/mir/issue-80949.rs create mode 100644 tests/ui/mir/issue-83499-input-output-iteration-ice.rs create mode 100644 tests/ui/mir/issue-83499-input-output-iteration-ice.stderr create mode 100644 tests/ui/mir/issue-89485.rs create mode 100644 tests/ui/mir/issue-91745.rs create mode 100644 tests/ui/mir/issue-92893.rs create mode 100644 tests/ui/mir/issue-92893.stderr create mode 100644 tests/ui/mir/issue-99852.rs create mode 100644 tests/ui/mir/issue-99866.rs create mode 100644 tests/ui/mir/issue66339.rs create mode 100644 tests/ui/mir/mir-inlining/array-clone-with-generic-size.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-100550-unnormalized-projection.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-45493.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-45885.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-68347.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-77306-1.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-77306-2.rs create mode 100644 tests/ui/mir/mir-inlining/ice-issue-77564.rs create mode 100644 tests/ui/mir/mir-inlining/no-trait-method-issue-40473.rs create mode 100644 tests/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs create mode 100644 tests/ui/mir/mir-typeck-normalize-fn-sig.rs create mode 100644 tests/ui/mir/mir_adt_construction.rs create mode 100644 tests/ui/mir/mir_ascription_coercion.rs create mode 100644 tests/ui/mir/mir_assign_eval_order.rs create mode 100644 tests/ui/mir/mir_augmented_assignments.rs create mode 100644 tests/ui/mir/mir_autoderef.rs create mode 100644 tests/ui/mir/mir_boxing.rs create mode 100644 tests/ui/mir/mir_build_match_comparisons.rs create mode 100644 tests/ui/mir/mir_call_with_associated_type.rs create mode 100644 tests/ui/mir/mir_calls_to_shims.rs create mode 100644 tests/ui/mir/mir_cast_fn_ret.rs create mode 100644 tests/ui/mir/mir_codegen_array.rs create mode 100644 tests/ui/mir/mir_codegen_array_2.rs create mode 100644 tests/ui/mir/mir_codegen_call_converging.rs create mode 100644 tests/ui/mir/mir_codegen_calls.rs create mode 100644 tests/ui/mir/mir_codegen_calls_converging_drops.rs create mode 100644 tests/ui/mir/mir_codegen_calls_converging_drops_2.rs create mode 100644 tests/ui/mir/mir_codegen_calls_diverging.rs create mode 100644 tests/ui/mir/mir_codegen_calls_diverging_drops.rs create mode 100644 tests/ui/mir/mir_codegen_critical_edge.rs create mode 100644 tests/ui/mir/mir_codegen_spike1.rs create mode 100644 tests/ui/mir/mir_codegen_switch.rs create mode 100644 tests/ui/mir/mir_codegen_switchint.rs create mode 100644 tests/ui/mir/mir_coercion_casts.rs create mode 100644 tests/ui/mir/mir_coercions.rs create mode 100644 tests/ui/mir/mir_const_prop_identity.rs create mode 100644 tests/ui/mir/mir_const_prop_tuple_field_reorder.rs create mode 100644 tests/ui/mir/mir_constval_adts.rs create mode 100644 tests/ui/mir/mir_detects_invalid_ops.rs create mode 100644 tests/ui/mir/mir_detects_invalid_ops.stderr create mode 100644 tests/ui/mir/mir_drop_order.rs create mode 100644 tests/ui/mir/mir_drop_panics.rs create mode 100644 tests/ui/mir/mir_dynamic_drops_1.rs create mode 100644 tests/ui/mir/mir_dynamic_drops_2.rs create mode 100644 tests/ui/mir/mir_dynamic_drops_3.rs create mode 100644 tests/ui/mir/mir_early_return_scope.rs create mode 100644 tests/ui/mir/mir_fat_ptr.rs create mode 100644 tests/ui/mir/mir_fat_ptr_drop.rs create mode 100644 tests/ui/mir/mir_heavy_promoted.rs create mode 100644 tests/ui/mir/mir_indexing_oob_1.rs create mode 100644 tests/ui/mir/mir_indexing_oob_2.rs create mode 100644 tests/ui/mir/mir_indexing_oob_3.rs create mode 100644 tests/ui/mir/mir_let_chains_drop_order.rs create mode 100644 tests/ui/mir/mir_match_arm_guard.rs create mode 100644 tests/ui/mir/mir_match_test.rs create mode 100644 tests/ui/mir/mir_misc_casts.rs create mode 100644 tests/ui/mir/mir_overflow_off.rs create mode 100644 tests/ui/mir/mir_raw_fat_ptr.rs create mode 100644 tests/ui/mir/mir_refs_correct.rs create mode 100644 tests/ui/mir/mir_small_agg_arg.rs create mode 100644 tests/ui/mir/mir_static_subtype.rs create mode 100644 tests/ui/mir/mir_struct_with_assoc_ty.rs create mode 100644 tests/ui/mir/mir_temp_promotions.rs create mode 100644 tests/ui/mir/mir_void_return.rs create mode 100644 tests/ui/mir/mir_void_return_2.rs create mode 100644 tests/ui/mir/remove-zsts-query-cycle.rs create mode 100644 tests/ui/mir/simplify-branch-same.rs create mode 100644 tests/ui/mir/ssa-analysis-regression-50041.rs create mode 100644 tests/ui/mir/thir-constparam-temp.rs create mode 100644 tests/ui/mir/thir-constparam-temp.stderr create mode 100644 tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs create mode 100644 tests/ui/mir/validate/needs-reveal-all.rs create mode 100644 tests/ui/mismatched_types/E0053.rs create mode 100644 tests/ui/mismatched_types/E0053.stderr create mode 100644 tests/ui/mismatched_types/E0409.rs create mode 100644 tests/ui/mismatched_types/E0409.stderr create mode 100644 tests/ui/mismatched_types/E0631.rs create mode 100644 tests/ui/mismatched_types/E0631.stderr create mode 100644 tests/ui/mismatched_types/abridged.rs create mode 100644 tests/ui/mismatched_types/abridged.stderr create mode 100644 tests/ui/mismatched_types/assignment-operator-unimplemented.rs create mode 100644 tests/ui/mismatched_types/assignment-operator-unimplemented.stderr create mode 100644 tests/ui/mismatched_types/binops.rs create mode 100644 tests/ui/mismatched_types/binops.stderr create mode 100644 tests/ui/mismatched_types/cast-rfc0401.rs create mode 100644 tests/ui/mismatched_types/cast-rfc0401.stderr create mode 100644 tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed create mode 100644 tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs create mode 100644 tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr create mode 100644 tests/ui/mismatched_types/closure-arg-count.rs create mode 100644 tests/ui/mismatched_types/closure-arg-count.stderr create mode 100644 tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed create mode 100644 tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs create mode 100644 tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr create mode 100644 tests/ui/mismatched_types/closure-arg-type-mismatch.rs create mode 100644 tests/ui/mismatched_types/closure-arg-type-mismatch.stderr create mode 100644 tests/ui/mismatched_types/closure-mismatch.rs create mode 100644 tests/ui/mismatched_types/closure-mismatch.stderr create mode 100644 tests/ui/mismatched_types/const-fn-in-trait.rs create mode 100644 tests/ui/mismatched_types/const-fn-in-trait.stderr create mode 100644 tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.rs create mode 100644 tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr create mode 100644 tests/ui/mismatched_types/dont-point-return-on-E0308.rs create mode 100644 tests/ui/mismatched_types/dont-point-return-on-E0308.stderr create mode 100644 tests/ui/mismatched_types/float-literal-inference-restrictions.rs create mode 100644 tests/ui/mismatched_types/float-literal-inference-restrictions.stderr create mode 100644 tests/ui/mismatched_types/fn-variance-1.rs create mode 100644 tests/ui/mismatched_types/fn-variance-1.stderr create mode 100644 tests/ui/mismatched_types/for-loop-has-unit-body.rs create mode 100644 tests/ui/mismatched_types/for-loop-has-unit-body.stderr create mode 100644 tests/ui/mismatched_types/issue-106182.fixed create mode 100644 tests/ui/mismatched_types/issue-106182.rs create mode 100644 tests/ui/mismatched_types/issue-106182.stderr create mode 100644 tests/ui/mismatched_types/issue-19109.rs create mode 100644 tests/ui/mismatched_types/issue-19109.stderr create mode 100644 tests/ui/mismatched_types/issue-26480.rs create mode 100644 tests/ui/mismatched_types/issue-26480.stderr create mode 100644 tests/ui/mismatched_types/issue-35030.rs create mode 100644 tests/ui/mismatched_types/issue-35030.stderr create mode 100644 tests/ui/mismatched_types/issue-36053-2.rs create mode 100644 tests/ui/mismatched_types/issue-36053-2.stderr create mode 100644 tests/ui/mismatched_types/issue-38371-unfixable.rs create mode 100644 tests/ui/mismatched_types/issue-38371-unfixable.stderr create mode 100644 tests/ui/mismatched_types/issue-38371.fixed create mode 100644 tests/ui/mismatched_types/issue-38371.rs create mode 100644 tests/ui/mismatched_types/issue-38371.stderr create mode 100644 tests/ui/mismatched_types/issue-47706-trait.rs create mode 100644 tests/ui/mismatched_types/issue-47706-trait.stderr create mode 100644 tests/ui/mismatched_types/issue-47706.rs create mode 100644 tests/ui/mismatched_types/issue-47706.stderr create mode 100644 tests/ui/mismatched_types/issue-74918-missing-lifetime.rs create mode 100644 tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr create mode 100644 tests/ui/mismatched_types/issue-75361-mismatched-impl.rs create mode 100644 tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr create mode 100644 tests/ui/mismatched_types/issue-84976.rs create mode 100644 tests/ui/mismatched_types/issue-84976.stderr create mode 100644 tests/ui/mismatched_types/main.rs create mode 100644 tests/ui/mismatched_types/main.stderr create mode 100644 tests/ui/mismatched_types/method-help-unsatisfied-bound.rs create mode 100644 tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr create mode 100644 tests/ui/mismatched_types/non_zero_assigned_something.rs create mode 100644 tests/ui/mismatched_types/non_zero_assigned_something.stderr create mode 100644 tests/ui/mismatched_types/normalize-fn-sig.rs create mode 100644 tests/ui/mismatched_types/normalize-fn-sig.stderr create mode 100644 tests/ui/mismatched_types/numeric-literal-cast.rs create mode 100644 tests/ui/mismatched_types/numeric-literal-cast.stderr create mode 100644 tests/ui/mismatched_types/overloaded-calls-bad.rs create mode 100644 tests/ui/mismatched_types/overloaded-calls-bad.stderr create mode 100644 tests/ui/mismatched_types/recovered-block.rs create mode 100644 tests/ui/mismatched_types/recovered-block.stderr create mode 100644 tests/ui/mismatched_types/ref-pat-suggestions.fixed create mode 100644 tests/ui/mismatched_types/ref-pat-suggestions.rs create mode 100644 tests/ui/mismatched_types/ref-pat-suggestions.stderr create mode 100644 tests/ui/mismatched_types/show_module.rs create mode 100644 tests/ui/mismatched_types/show_module.stderr create mode 100644 tests/ui/mismatched_types/similar_paths.rs create mode 100644 tests/ui/mismatched_types/similar_paths.stderr create mode 100644 tests/ui/mismatched_types/similar_paths_primitive.rs create mode 100644 tests/ui/mismatched_types/similar_paths_primitive.stderr create mode 100644 tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed create mode 100644 tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs create mode 100644 tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.stderr create mode 100644 tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed create mode 100644 tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs create mode 100644 tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr create mode 100644 tests/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed create mode 100644 tests/ui/mismatched_types/suggest-removing-tuple-struct-field.rs create mode 100644 tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr create mode 100644 tests/ui/mismatched_types/trait-bounds-cant-coerce.rs create mode 100644 tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr create mode 100644 tests/ui/mismatched_types/trait-impl-fn-incompatibility.rs create mode 100644 tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr create mode 100644 tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs create mode 100644 tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr create mode 100644 tests/ui/mismatched_types/wrap-suggestion-privacy.rs create mode 100644 tests/ui/mismatched_types/wrap-suggestion-privacy.stderr create mode 100644 tests/ui/missing-trait-bounds/auxiliary/issue-69725.rs create mode 100644 tests/ui/missing-trait-bounds/issue-35677.fixed create mode 100644 tests/ui/missing-trait-bounds/issue-35677.rs create mode 100644 tests/ui/missing-trait-bounds/issue-35677.stderr create mode 100644 tests/ui/missing-trait-bounds/issue-69725.fixed create mode 100644 tests/ui/missing-trait-bounds/issue-69725.rs create mode 100644 tests/ui/missing-trait-bounds/issue-69725.stderr create mode 100644 tests/ui/missing-trait-bounds/missing-trait-bound-for-op.fixed create mode 100644 tests/ui/missing-trait-bounds/missing-trait-bound-for-op.rs create mode 100644 tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr create mode 100644 tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.rs create mode 100644 tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr create mode 100644 tests/ui/missing/auxiliary/two_macros.rs create mode 100644 tests/ui/missing/missing-allocator.rs create mode 100644 tests/ui/missing/missing-allocator.stderr create mode 100644 tests/ui/missing/missing-block-hint.rs create mode 100644 tests/ui/missing/missing-block-hint.stderr create mode 100644 tests/ui/missing/missing-comma-in-match.fixed create mode 100644 tests/ui/missing/missing-comma-in-match.rs create mode 100644 tests/ui/missing/missing-comma-in-match.stderr create mode 100644 tests/ui/missing/missing-derivable-attr.rs create mode 100644 tests/ui/missing/missing-derivable-attr.stderr create mode 100644 tests/ui/missing/missing-fields-in-struct-pattern.rs create mode 100644 tests/ui/missing/missing-fields-in-struct-pattern.stderr create mode 100644 tests/ui/missing/missing-items/auxiliary/m1.rs create mode 100644 tests/ui/missing/missing-items/m2.rs create mode 100644 tests/ui/missing/missing-items/m2.stderr create mode 100644 tests/ui/missing/missing-items/missing-type-parameter.rs create mode 100644 tests/ui/missing/missing-items/missing-type-parameter.stderr create mode 100644 tests/ui/missing/missing-items/missing-type-parameter2.rs create mode 100644 tests/ui/missing/missing-items/missing-type-parameter2.stderr create mode 100644 tests/ui/missing/missing-macro-use.rs create mode 100644 tests/ui/missing/missing-macro-use.stderr create mode 100644 tests/ui/missing/missing-main.rs create mode 100644 tests/ui/missing/missing-main.stderr create mode 100644 tests/ui/missing/missing-return.rs create mode 100644 tests/ui/missing/missing-return.stderr create mode 100644 tests/ui/missing/missing-stability.rs create mode 100644 tests/ui/missing/missing-stability.stderr create mode 100644 tests/ui/missing_debug_impls.rs create mode 100644 tests/ui/missing_debug_impls.stderr create mode 100644 tests/ui/missing_non_modrs_mod/foo.rs create mode 100644 tests/ui/missing_non_modrs_mod/foo_inline.rs create mode 100644 tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs create mode 100644 tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr create mode 100644 tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs create mode 100644 tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr create mode 100644 tests/ui/mod-subitem-as-enum-variant.rs create mode 100644 tests/ui/mod-subitem-as-enum-variant.stderr create mode 100644 tests/ui/module-macro_use-arguments.rs create mode 100644 tests/ui/module-macro_use-arguments.stderr create mode 100644 tests/ui/modules/auxiliary/dummy_lib.rs create mode 100644 tests/ui/modules/auxiliary/two_macros_2.rs create mode 100644 tests/ui/modules/issue-56411-aux.rs create mode 100644 tests/ui/modules/issue-56411.rs create mode 100644 tests/ui/modules/issue-56411.stderr create mode 100644 tests/ui/modules/mod-inside-fn.rs create mode 100644 tests/ui/modules/mod-view-items.rs create mode 100644 tests/ui/modules/mod_dir_implicit.rs create mode 100644 tests/ui/modules/mod_dir_implicit_aux/compiletest-ignore-dir create mode 100644 tests/ui/modules/mod_dir_implicit_aux/mod.rs create mode 100644 tests/ui/modules/mod_dir_path.rs create mode 100644 tests/ui/modules/mod_dir_path2.rs create mode 100644 tests/ui/modules/mod_dir_path3.rs create mode 100644 tests/ui/modules/mod_dir_path_multi.rs create mode 100644 tests/ui/modules/mod_dir_recursive.rs create mode 100644 tests/ui/modules/mod_dir_simple.rs create mode 100644 tests/ui/modules/mod_dir_simple/compiletest-ignore-dir create mode 100644 tests/ui/modules/mod_dir_simple/load_another_mod.rs create mode 100644 tests/ui/modules/mod_dir_simple/test.rs create mode 100644 tests/ui/modules/mod_file.rs create mode 100644 tests/ui/modules/mod_file_aux.rs create mode 100644 tests/ui/modules/mod_file_with_path_attr.rs create mode 100644 tests/ui/modules/module-polymorphism3-files/compiletest-ignore-dir create mode 100644 tests/ui/modules/module-polymorphism3-files/float-template/inst_f32.rs create mode 100644 tests/ui/modules/module-polymorphism3-files/float-template/inst_f64.rs create mode 100644 tests/ui/modules/module-polymorphism3-files/float-template/inst_float.rs create mode 100644 tests/ui/modules/path-invalid-form.rs create mode 100644 tests/ui/modules/path-invalid-form.stderr create mode 100644 tests/ui/modules/path-macro.rs create mode 100644 tests/ui/modules/path-macro.stderr create mode 100644 tests/ui/modules/path-no-file-name.rs create mode 100644 tests/ui/modules/path-no-file-name.stderr create mode 100644 tests/ui/modules/special_module_name.rs create mode 100644 tests/ui/modules/special_module_name.stderr create mode 100644 tests/ui/modules/special_module_name_ignore.rs create mode 100644 tests/ui/modules_and_files_visibility/mod_file_aux.rs create mode 100644 tests/ui/modules_and_files_visibility/mod_file_correct_spans.rs create mode 100644 tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr create mode 100644 tests/ui/modules_and_files_visibility/mod_file_disambig.rs create mode 100644 tests/ui/modules_and_files_visibility/mod_file_disambig.stderr create mode 100644 tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs create mode 100644 tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs create mode 100644 tests/ui/monomorphize-abi-alignment.rs create mode 100644 tests/ui/moves/borrow-closures-instead-of-move.rs create mode 100644 tests/ui/moves/borrow-closures-instead-of-move.stderr create mode 100644 tests/ui/moves/issue-46099-move-in-macro.rs create mode 100644 tests/ui/moves/issue-46099-move-in-macro.stderr create mode 100644 tests/ui/moves/issue-72649-uninit-in-loop.rs create mode 100644 tests/ui/moves/issue-72649-uninit-in-loop.stderr create mode 100644 tests/ui/moves/issue-75904-move-closure-loop.rs create mode 100644 tests/ui/moves/issue-75904-move-closure-loop.stderr create mode 100644 tests/ui/moves/issue-99470-move-out-of-some.rs create mode 100644 tests/ui/moves/issue-99470-move-out-of-some.stderr create mode 100644 tests/ui/moves/move-1-unique.rs create mode 100644 tests/ui/moves/move-2-unique.rs create mode 100644 tests/ui/moves/move-2.rs create mode 100644 tests/ui/moves/move-3-unique.rs create mode 100644 tests/ui/moves/move-4-unique.rs create mode 100644 tests/ui/moves/move-4.rs create mode 100644 tests/ui/moves/move-arg-2-unique.rs create mode 100644 tests/ui/moves/move-arg-2.rs create mode 100644 tests/ui/moves/move-arg.rs create mode 100644 tests/ui/moves/move-deref-coercion.rs create mode 100644 tests/ui/moves/move-deref-coercion.stderr create mode 100644 tests/ui/moves/move-fn-self-receiver.rs create mode 100644 tests/ui/moves/move-fn-self-receiver.stderr create mode 100644 tests/ui/moves/move-guard-same-consts.rs create mode 100644 tests/ui/moves/move-guard-same-consts.stderr create mode 100644 tests/ui/moves/move-in-guard-1.rs create mode 100644 tests/ui/moves/move-in-guard-1.stderr create mode 100644 tests/ui/moves/move-in-guard-2.rs create mode 100644 tests/ui/moves/move-in-guard-2.stderr create mode 100644 tests/ui/moves/move-into-dead-array-1.rs create mode 100644 tests/ui/moves/move-into-dead-array-1.stderr create mode 100644 tests/ui/moves/move-into-dead-array-2.rs create mode 100644 tests/ui/moves/move-into-dead-array-2.stderr create mode 100644 tests/ui/moves/move-nullary-fn.rs create mode 100644 tests/ui/moves/move-of-addr-of-mut.rs create mode 100644 tests/ui/moves/move-of-addr-of-mut.stderr create mode 100644 tests/ui/moves/move-out-of-array-1.rs create mode 100644 tests/ui/moves/move-out-of-array-1.stderr create mode 100644 tests/ui/moves/move-out-of-array-ref.rs create mode 100644 tests/ui/moves/move-out-of-array-ref.stderr create mode 100644 tests/ui/moves/move-out-of-field.rs create mode 100644 tests/ui/moves/move-out-of-slice-1.rs create mode 100644 tests/ui/moves/move-out-of-slice-1.stderr create mode 100644 tests/ui/moves/move-out-of-slice-2.rs create mode 100644 tests/ui/moves/move-out-of-slice-2.stderr create mode 100644 tests/ui/moves/move-out-of-tuple-field.rs create mode 100644 tests/ui/moves/move-out-of-tuple-field.stderr create mode 100644 tests/ui/moves/move-scalar.rs create mode 100644 tests/ui/moves/moves-based-on-type-access-to-field.rs create mode 100644 tests/ui/moves/moves-based-on-type-access-to-field.stderr create mode 100644 tests/ui/moves/moves-based-on-type-block-bad.rs create mode 100644 tests/ui/moves/moves-based-on-type-block-bad.stderr create mode 100644 tests/ui/moves/moves-based-on-type-capture-clause-bad.rs create mode 100644 tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr create mode 100644 tests/ui/moves/moves-based-on-type-capture-clause.rs create mode 100644 tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs create mode 100644 tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr create mode 100644 tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs create mode 100644 tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr create mode 100644 tests/ui/moves/moves-based-on-type-exprs.rs create mode 100644 tests/ui/moves/moves-based-on-type-exprs.stderr create mode 100644 tests/ui/moves/moves-based-on-type-match-bindings.rs create mode 100644 tests/ui/moves/moves-based-on-type-match-bindings.stderr create mode 100644 tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs create mode 100644 tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr create mode 100644 tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs create mode 100644 tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr create mode 100644 tests/ui/moves/moves-based-on-type-tuple.rs create mode 100644 tests/ui/moves/moves-based-on-type-tuple.stderr create mode 100644 tests/ui/moves/moves-sru-moved-field.rs create mode 100644 tests/ui/moves/moves-sru-moved-field.stderr create mode 100644 tests/ui/moves/pin-mut-reborrow.fixed create mode 100644 tests/ui/moves/pin-mut-reborrow.rs create mode 100644 tests/ui/moves/pin-mut-reborrow.stderr create mode 100644 tests/ui/moves/suggest-clone.fixed create mode 100644 tests/ui/moves/suggest-clone.rs create mode 100644 tests/ui/moves/suggest-clone.stderr create mode 100644 tests/ui/moves/use_of_moved_value_clone_suggestions.rs create mode 100644 tests/ui/moves/use_of_moved_value_clone_suggestions.stderr create mode 100644 tests/ui/moves/use_of_moved_value_copy_suggestions.fixed create mode 100644 tests/ui/moves/use_of_moved_value_copy_suggestions.rs create mode 100644 tests/ui/moves/use_of_moved_value_copy_suggestions.stderr create mode 100644 tests/ui/msvc-data-only.rs create mode 100644 tests/ui/multibyte.rs create mode 100644 tests/ui/multiline-comment.rs create mode 100644 tests/ui/mut-function-arguments.rs create mode 100644 tests/ui/mut/mut-cant-alias.rs create mode 100644 tests/ui/mut/mut-cant-alias.stderr create mode 100644 tests/ui/mut/mut-cross-borrowing.rs create mode 100644 tests/ui/mut/mut-cross-borrowing.stderr create mode 100644 tests/ui/mut/mut-pattern-internal-mutability.rs create mode 100644 tests/ui/mut/mut-pattern-internal-mutability.stderr create mode 100644 tests/ui/mut/mut-pattern-mismatched.rs create mode 100644 tests/ui/mut/mut-pattern-mismatched.stderr create mode 100644 tests/ui/mut/mut-ref.rs create mode 100644 tests/ui/mut/mut-ref.stderr create mode 100644 tests/ui/mut/mut-suggestion.rs create mode 100644 tests/ui/mut/mut-suggestion.stderr create mode 100644 tests/ui/mut/mutable-class-fields-2.rs create mode 100644 tests/ui/mut/mutable-class-fields-2.stderr create mode 100644 tests/ui/mut/mutable-class-fields.rs create mode 100644 tests/ui/mut/mutable-class-fields.stderr create mode 100644 tests/ui/mut/mutable-enum-indirect.rs create mode 100644 tests/ui/mut/mutable-enum-indirect.stderr create mode 100644 tests/ui/mut/no-mut-lint-for-desugared-mut.rs create mode 100644 tests/ui/mutexguard-sync.rs create mode 100644 tests/ui/mutexguard-sync.stderr create mode 100644 tests/ui/mutual-recursion-group.rs create mode 100644 tests/ui/namespace/auxiliary/namespace-mix.rs create mode 100644 tests/ui/namespace/auxiliary/namespaced_enums.rs create mode 100644 tests/ui/namespace/namespace-mix.rs create mode 100644 tests/ui/namespace/namespace-mix.stderr create mode 100644 tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs create mode 100644 tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr create mode 100644 tests/ui/namespace/namespaced-enum-glob-import-no-impls.rs create mode 100644 tests/ui/namespace/namespaced-enum-glob-import-no-impls.stderr create mode 100644 tests/ui/native-library-link-flags/empty-kind-1.rs create mode 100644 tests/ui/native-library-link-flags/empty-kind-1.stderr create mode 100644 tests/ui/native-library-link-flags/empty-kind-2.rs create mode 100644 tests/ui/native-library-link-flags/empty-kind-2.stderr create mode 100644 tests/ui/native-library-link-flags/link-arg-error.rs create mode 100644 tests/ui/native-library-link-flags/link-arg-error.stderr create mode 100644 tests/ui/native-library-link-flags/link-arg-from-rs.rs create mode 100644 tests/ui/native-library-link-flags/link-arg-from-rs.stderr create mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs create mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr create mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs create mode 100644 tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr create mode 100644 tests/ui/native-library-link-flags/modifiers-override-2.rs create mode 100644 tests/ui/native-library-link-flags/modifiers-override-2.stderr create mode 100644 tests/ui/native-library-link-flags/modifiers-override-3.rs create mode 100644 tests/ui/native-library-link-flags/modifiers-override-3.stderr create mode 100644 tests/ui/native-library-link-flags/modifiers-override.rs create mode 100644 tests/ui/native-library-link-flags/modifiers-override.stderr create mode 100644 tests/ui/native-library-link-flags/suggest-libname-only-1.rs create mode 100644 tests/ui/native-library-link-flags/suggest-libname-only-1.stderr create mode 100644 tests/ui/native-library-link-flags/suggest-libname-only-2.rs create mode 100644 tests/ui/native-library-link-flags/suggest-libname-only-2.stderr create mode 100644 tests/ui/nested-block-comment.rs create mode 100644 tests/ui/nested-cfg-attrs.rs create mode 100644 tests/ui/nested-cfg-attrs.stderr create mode 100644 tests/ui/nested-class.rs create mode 100644 tests/ui/nested-ty-params.rs create mode 100644 tests/ui/nested-ty-params.stderr create mode 100644 tests/ui/never_type/adjust_never.rs create mode 100644 tests/ui/never_type/auto-traits.rs create mode 100644 tests/ui/never_type/call-fn-never-arg-wrong-type.rs create mode 100644 tests/ui/never_type/call-fn-never-arg-wrong-type.stderr create mode 100644 tests/ui/never_type/call-fn-never-arg.rs create mode 100644 tests/ui/never_type/cast-never.rs create mode 100644 tests/ui/never_type/defaulted-never-note.fallback.stderr create mode 100644 tests/ui/never_type/defaulted-never-note.rs create mode 100644 tests/ui/never_type/dispatch_from_dyn_zst.rs create mode 100644 tests/ui/never_type/diverging-fallback-control-flow.rs create mode 100644 tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr create mode 100644 tests/ui/never_type/diverging-fallback-no-leak.rs create mode 100644 tests/ui/never_type/diverging-fallback-unconstrained-return.rs create mode 100644 tests/ui/never_type/diverging-tuple-parts-39485.rs create mode 100644 tests/ui/never_type/diverging-tuple-parts-39485.stderr create mode 100644 tests/ui/never_type/exhaustive_patterns.rs create mode 100644 tests/ui/never_type/exhaustive_patterns.stderr create mode 100644 tests/ui/never_type/expr-empty-ret.rs create mode 100644 tests/ui/never_type/fallback-closure-ret.rs create mode 100644 tests/ui/never_type/fallback-closure-wrap.fallback.stderr create mode 100644 tests/ui/never_type/fallback-closure-wrap.rs create mode 100644 tests/ui/never_type/feature-gate-never_type_fallback.rs create mode 100644 tests/ui/never_type/feature-gate-never_type_fallback.stderr create mode 100644 tests/ui/never_type/impl-for-never.rs create mode 100644 tests/ui/never_type/impl_trait_fallback.rs create mode 100644 tests/ui/never_type/impl_trait_fallback2.rs create mode 100644 tests/ui/never_type/impl_trait_fallback2.stderr create mode 100644 tests/ui/never_type/impl_trait_fallback3.rs create mode 100644 tests/ui/never_type/impl_trait_fallback3.stderr create mode 100644 tests/ui/never_type/impl_trait_fallback4.rs create mode 100644 tests/ui/never_type/impl_trait_fallback4.stderr create mode 100644 tests/ui/never_type/issue-10176.rs create mode 100644 tests/ui/never_type/issue-10176.stderr create mode 100644 tests/ui/never_type/issue-13352.rs create mode 100644 tests/ui/never_type/issue-13352.stderr create mode 100644 tests/ui/never_type/issue-2149.rs create mode 100644 tests/ui/never_type/issue-2149.stderr create mode 100644 tests/ui/never_type/issue-44402.rs create mode 100644 tests/ui/never_type/issue-51506.rs create mode 100644 tests/ui/never_type/issue-51506.stderr create mode 100644 tests/ui/never_type/issue-52443.rs create mode 100644 tests/ui/never_type/issue-52443.stderr create mode 100644 tests/ui/never_type/issue-5500-1.rs create mode 100644 tests/ui/never_type/issue-96335.rs create mode 100644 tests/ui/never_type/issue-96335.stderr create mode 100644 tests/ui/never_type/never-assign-dead-code.rs create mode 100644 tests/ui/never_type/never-assign-dead-code.stderr create mode 100644 tests/ui/never_type/never-assign-wrong-type.rs create mode 100644 tests/ui/never_type/never-assign-wrong-type.stderr create mode 100644 tests/ui/never_type/never-associated-type.rs create mode 100644 tests/ui/never_type/never-from-impl-is-reserved.rs create mode 100644 tests/ui/never_type/never-from-impl-is-reserved.stderr create mode 100644 tests/ui/never_type/never-result.rs create mode 100644 tests/ui/never_type/never-type-arg.rs create mode 100644 tests/ui/never_type/never-type-rvalues.rs create mode 100644 tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr create mode 100644 tests/ui/never_type/never-value-fallback-issue-66757.rs create mode 100644 tests/ui/never_type/never_coercions.rs create mode 100644 tests/ui/never_type/never_transmute_never.rs create mode 100644 tests/ui/never_type/return-never-coerce.rs create mode 100644 tests/ui/never_type/try_from.rs create mode 100644 tests/ui/new-impl-syntax.rs create mode 100644 tests/ui/new-import-syntax.rs create mode 100644 tests/ui/new-style-constants.rs create mode 100644 tests/ui/new-unicode-escapes.rs create mode 100644 tests/ui/new-unsafe-pointers.rs create mode 100644 tests/ui/newlambdas.rs create mode 100644 tests/ui/newtype-polymorphic.rs create mode 100644 tests/ui/newtype.rs create mode 100644 tests/ui/nll/assign-while-to-immutable.rs create mode 100644 tests/ui/nll/borrow-use-issue-46875.rs create mode 100644 tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs create mode 100644 tests/ui/nll/borrowed-local-error.rs create mode 100644 tests/ui/nll/borrowed-local-error.stderr create mode 100644 tests/ui/nll/borrowed-match-issue-45045.rs create mode 100644 tests/ui/nll/borrowed-match-issue-45045.stderr create mode 100644 tests/ui/nll/borrowed-referent-issue-38899.rs create mode 100644 tests/ui/nll/borrowed-referent-issue-38899.stderr create mode 100644 tests/ui/nll/borrowed-temporary-error.rs create mode 100644 tests/ui/nll/borrowed-temporary-error.stderr create mode 100644 tests/ui/nll/borrowed-universal-error-2.rs create mode 100644 tests/ui/nll/borrowed-universal-error-2.stderr create mode 100644 tests/ui/nll/borrowed-universal-error.rs create mode 100644 tests/ui/nll/borrowed-universal-error.stderr create mode 100644 tests/ui/nll/cannot-move-block-spans.rs create mode 100644 tests/ui/nll/cannot-move-block-spans.stderr create mode 100644 tests/ui/nll/capture-mut-ref.fixed create mode 100644 tests/ui/nll/capture-mut-ref.rs create mode 100644 tests/ui/nll/capture-mut-ref.stderr create mode 100644 tests/ui/nll/capture-ref-in-struct.rs create mode 100644 tests/ui/nll/capture-ref-in-struct.stderr create mode 100644 tests/ui/nll/closure-access-spans.rs create mode 100644 tests/ui/nll/closure-access-spans.stderr create mode 100644 tests/ui/nll/closure-borrow-spans.rs create mode 100644 tests/ui/nll/closure-borrow-spans.stderr create mode 100644 tests/ui/nll/closure-captures.rs create mode 100644 tests/ui/nll/closure-captures.stderr create mode 100644 tests/ui/nll/closure-malformed-projection-input-issue-102800.rs create mode 100644 tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr create mode 100644 tests/ui/nll/closure-move-spans.rs create mode 100644 tests/ui/nll/closure-move-spans.stderr create mode 100644 tests/ui/nll/closure-requirements/escape-argument-callee.rs create mode 100644 tests/ui/nll/closure-requirements/escape-argument-callee.stderr create mode 100644 tests/ui/nll/closure-requirements/escape-argument.rs create mode 100644 tests/ui/nll/closure-requirements/escape-argument.stderr create mode 100644 tests/ui/nll/closure-requirements/escape-upvar-nested.rs create mode 100644 tests/ui/nll/closure-requirements/escape-upvar-nested.stderr create mode 100644 tests/ui/nll/closure-requirements/escape-upvar-ref.rs create mode 100644 tests/ui/nll/closure-requirements/escape-upvar-ref.stderr create mode 100644 tests/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-ref.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-val.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-approximated-val.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-despite-same-free-region.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-from-trait-match.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr create mode 100644 tests/ui/nll/closure-requirements/propagate-multiple-requirements.rs create mode 100644 tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr create mode 100644 tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs create mode 100644 tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr create mode 100644 tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs create mode 100644 tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr create mode 100644 tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs create mode 100644 tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr create mode 100644 tests/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs create mode 100644 tests/ui/nll/closure-requirements/return-wrong-bound-region.rs create mode 100644 tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr create mode 100644 tests/ui/nll/closure-use-spans.rs create mode 100644 tests/ui/nll/closure-use-spans.stderr create mode 100644 tests/ui/nll/closures-in-loops.rs create mode 100644 tests/ui/nll/closures-in-loops.stderr create mode 100644 tests/ui/nll/constant-thread-locals-issue-47053.rs create mode 100644 tests/ui/nll/constant-thread-locals-issue-47053.stderr create mode 100644 tests/ui/nll/constant.rs create mode 100644 tests/ui/nll/continue-after-missing-main.rs create mode 100644 tests/ui/nll/continue-after-missing-main.stderr create mode 100644 tests/ui/nll/decl-macro-illegal-copy.rs create mode 100644 tests/ui/nll/decl-macro-illegal-copy.stderr create mode 100644 tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs create mode 100644 tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr create mode 100644 tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs create mode 100644 tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr create mode 100644 tests/ui/nll/dont-print-desugared.rs create mode 100644 tests/ui/nll/dont-print-desugared.stderr create mode 100644 tests/ui/nll/drop-may-dangle.rs create mode 100644 tests/ui/nll/drop-no-may-dangle.rs create mode 100644 tests/ui/nll/drop-no-may-dangle.stderr create mode 100644 tests/ui/nll/empty-type-predicate-2.rs create mode 100644 tests/ui/nll/empty-type-predicate.rs create mode 100644 tests/ui/nll/enum-drop-access.rs create mode 100644 tests/ui/nll/enum-drop-access.stderr create mode 100644 tests/ui/nll/extra-unused-mut.rs create mode 100644 tests/ui/nll/generator-distinct-lifetime.rs create mode 100644 tests/ui/nll/generator-upvar-mutability.rs create mode 100644 tests/ui/nll/generator-upvar-mutability.stderr create mode 100644 tests/ui/nll/get_default.polonius.stderr create mode 100644 tests/ui/nll/get_default.rs create mode 100644 tests/ui/nll/get_default.stderr create mode 100644 tests/ui/nll/guarantor-issue-46974.rs create mode 100644 tests/ui/nll/guarantor-issue-46974.stderr create mode 100644 tests/ui/nll/issue-16223.rs create mode 100644 tests/ui/nll/issue-21114-ebfull.rs create mode 100644 tests/ui/nll/issue-21114-kixunil.rs create mode 100644 tests/ui/nll/issue-21232-partial-init-and-erroneous-use.rs create mode 100644 tests/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr create mode 100644 tests/ui/nll/issue-21232-partial-init-and-use.rs create mode 100644 tests/ui/nll/issue-21232-partial-init-and-use.stderr create mode 100644 tests/ui/nll/issue-22323-temp-destruction.rs create mode 100644 tests/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs create mode 100644 tests/ui/nll/issue-27282-move-match-input-into-guard.rs create mode 100644 tests/ui/nll/issue-27282-move-match-input-into-guard.stderr create mode 100644 tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs create mode 100644 tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr create mode 100644 tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.rs create mode 100644 tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr create mode 100644 tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.rs create mode 100644 tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr create mode 100644 tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.rs create mode 100644 tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr create mode 100644 tests/ui/nll/issue-27282-mutation-in-guard.rs create mode 100644 tests/ui/nll/issue-27282-mutation-in-guard.stderr create mode 100644 tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs create mode 100644 tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr create mode 100644 tests/ui/nll/issue-27868.rs create mode 100644 tests/ui/nll/issue-27868.stderr create mode 100644 tests/ui/nll/issue-30104.rs create mode 100644 tests/ui/nll/issue-31567.rs create mode 100644 tests/ui/nll/issue-31567.stderr create mode 100644 tests/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs create mode 100644 tests/ui/nll/issue-42574-diagnostic-in-nested-closure.rs create mode 100644 tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr create mode 100644 tests/ui/nll/issue-43058.rs create mode 100644 tests/ui/nll/issue-45157.rs create mode 100644 tests/ui/nll/issue-45157.stderr create mode 100644 tests/ui/nll/issue-45696-long-live-borrows-in-boxes.rs create mode 100644 tests/ui/nll/issue-45696-no-variant-box-recur.rs create mode 100644 tests/ui/nll/issue-45696-scribble-on-boxed-borrow.rs create mode 100644 tests/ui/nll/issue-45696-scribble-on-boxed-borrow.stderr create mode 100644 tests/ui/nll/issue-46023.rs create mode 100644 tests/ui/nll/issue-46023.stderr create mode 100644 tests/ui/nll/issue-46036.rs create mode 100644 tests/ui/nll/issue-46036.stderr create mode 100644 tests/ui/nll/issue-46589.rs create mode 100644 tests/ui/nll/issue-46589.stderr create mode 100644 tests/ui/nll/issue-47022.rs create mode 100644 tests/ui/nll/issue-47153-generic-const.rs create mode 100644 tests/ui/nll/issue-47388.rs create mode 100644 tests/ui/nll/issue-47388.stderr create mode 100644 tests/ui/nll/issue-47470.rs create mode 100644 tests/ui/nll/issue-47470.stderr create mode 100644 tests/ui/nll/issue-47589.rs create mode 100644 tests/ui/nll/issue-48070.rs create mode 100644 tests/ui/nll/issue-48238.rs create mode 100644 tests/ui/nll/issue-48238.stderr create mode 100644 tests/ui/nll/issue-48623-closure.rs create mode 100644 tests/ui/nll/issue-48623-generator.rs create mode 100644 tests/ui/nll/issue-48623-generator.stderr create mode 100644 tests/ui/nll/issue-48697.rs create mode 100644 tests/ui/nll/issue-48697.stderr create mode 100644 tests/ui/nll/issue-48803.rs create mode 100644 tests/ui/nll/issue-48803.stderr create mode 100644 tests/ui/nll/issue-50343.rs create mode 100644 tests/ui/nll/issue-50461-used-mut-from-moves.rs create mode 100644 tests/ui/nll/issue-50716-1.rs create mode 100644 tests/ui/nll/issue-50716.rs create mode 100644 tests/ui/nll/issue-50716.stderr create mode 100644 tests/ui/nll/issue-51191.rs create mode 100644 tests/ui/nll/issue-51191.stderr create mode 100644 tests/ui/nll/issue-51244.rs create mode 100644 tests/ui/nll/issue-51244.stderr create mode 100644 tests/ui/nll/issue-51268.rs create mode 100644 tests/ui/nll/issue-51268.stderr create mode 100644 tests/ui/nll/issue-51345-2.rs create mode 100644 tests/ui/nll/issue-51351.rs create mode 100644 tests/ui/nll/issue-51512.rs create mode 100644 tests/ui/nll/issue-51512.stderr create mode 100644 tests/ui/nll/issue-51770.rs create mode 100644 tests/ui/nll/issue-52057.rs create mode 100644 tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs create mode 100644 tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr create mode 100644 tests/ui/nll/issue-52078.rs create mode 100644 tests/ui/nll/issue-52086.rs create mode 100644 tests/ui/nll/issue-52086.stderr create mode 100644 tests/ui/nll/issue-52113.rs create mode 100644 tests/ui/nll/issue-52113.stderr create mode 100644 tests/ui/nll/issue-52213.rs create mode 100644 tests/ui/nll/issue-52213.stderr create mode 100644 tests/ui/nll/issue-52533-1.rs create mode 100644 tests/ui/nll/issue-52533-1.stderr create mode 100644 tests/ui/nll/issue-52534-1.rs create mode 100644 tests/ui/nll/issue-52534-1.stderr create mode 100644 tests/ui/nll/issue-52534-2.rs create mode 100644 tests/ui/nll/issue-52534-2.stderr create mode 100644 tests/ui/nll/issue-52534.rs create mode 100644 tests/ui/nll/issue-52534.stderr create mode 100644 tests/ui/nll/issue-52663-span-decl-captured-variable.rs create mode 100644 tests/ui/nll/issue-52663-span-decl-captured-variable.stderr create mode 100644 tests/ui/nll/issue-52663-trait-object.rs create mode 100644 tests/ui/nll/issue-52663-trait-object.stderr create mode 100644 tests/ui/nll/issue-52669.rs create mode 100644 tests/ui/nll/issue-52669.stderr create mode 100644 tests/ui/nll/issue-52742.rs create mode 100644 tests/ui/nll/issue-52742.stderr create mode 100644 tests/ui/nll/issue-52992.rs create mode 100644 tests/ui/nll/issue-53040.rs create mode 100644 tests/ui/nll/issue-53040.stderr create mode 100644 tests/ui/nll/issue-53119.rs create mode 100644 tests/ui/nll/issue-53123-raw-pointer-cast.rs create mode 100644 tests/ui/nll/issue-53570.rs create mode 100644 tests/ui/nll/issue-53773.rs create mode 100644 tests/ui/nll/issue-53773.stderr create mode 100644 tests/ui/nll/issue-53807.rs create mode 100644 tests/ui/nll/issue-53807.stderr create mode 100644 tests/ui/nll/issue-54189.rs create mode 100644 tests/ui/nll/issue-54189.stderr create mode 100644 tests/ui/nll/issue-54382-use-span-of-tail-of-block.rs create mode 100644 tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr create mode 100644 tests/ui/nll/issue-54556-niconii.rs create mode 100644 tests/ui/nll/issue-54556-niconii.stderr create mode 100644 tests/ui/nll/issue-54556-stephaneyfx.rs create mode 100644 tests/ui/nll/issue-54556-stephaneyfx.stderr create mode 100644 tests/ui/nll/issue-54556-temps-in-tail-diagnostic.rs create mode 100644 tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr create mode 100644 tests/ui/nll/issue-54556-used-vs-unused-tails.rs create mode 100644 tests/ui/nll/issue-54556-used-vs-unused-tails.stderr create mode 100644 tests/ui/nll/issue-54556-wrap-it-up.rs create mode 100644 tests/ui/nll/issue-54556-wrap-it-up.stderr create mode 100644 tests/ui/nll/issue-54779-anon-static-lifetime.rs create mode 100644 tests/ui/nll/issue-54779-anon-static-lifetime.stderr create mode 100644 tests/ui/nll/issue-54943-3.rs create mode 100644 tests/ui/nll/issue-54943.rs create mode 100644 tests/ui/nll/issue-54943.stderr create mode 100644 tests/ui/nll/issue-55288.rs create mode 100644 tests/ui/nll/issue-55344.rs create mode 100644 tests/ui/nll/issue-55394.rs create mode 100644 tests/ui/nll/issue-55394.stderr create mode 100644 tests/ui/nll/issue-55401.rs create mode 100644 tests/ui/nll/issue-55401.stderr create mode 100644 tests/ui/nll/issue-55511.rs create mode 100644 tests/ui/nll/issue-55511.stderr create mode 100644 tests/ui/nll/issue-55651.rs create mode 100644 tests/ui/nll/issue-55825-const-fn.rs create mode 100644 tests/ui/nll/issue-55850.rs create mode 100644 tests/ui/nll/issue-55850.stderr create mode 100644 tests/ui/nll/issue-57100.rs create mode 100644 tests/ui/nll/issue-57100.stderr create mode 100644 tests/ui/nll/issue-57265-return-type-wf-check.rs create mode 100644 tests/ui/nll/issue-57265-return-type-wf-check.stderr create mode 100644 tests/ui/nll/issue-57280-1-flipped.rs create mode 100644 tests/ui/nll/issue-57280-1-flipped.stderr create mode 100644 tests/ui/nll/issue-57280-1.rs create mode 100644 tests/ui/nll/issue-57280.rs create mode 100644 tests/ui/nll/issue-57642-higher-ranked-subtype.rs create mode 100644 tests/ui/nll/issue-57642-higher-ranked-subtype.stderr create mode 100644 tests/ui/nll/issue-57843.rs create mode 100644 tests/ui/nll/issue-57843.stderr create mode 100644 tests/ui/nll/issue-57960.rs create mode 100644 tests/ui/nll/issue-57989.rs create mode 100644 tests/ui/nll/issue-57989.stderr create mode 100644 tests/ui/nll/issue-58053.rs create mode 100644 tests/ui/nll/issue-58053.stderr create mode 100644 tests/ui/nll/issue-58299.rs create mode 100644 tests/ui/nll/issue-58299.stderr create mode 100644 tests/ui/nll/issue-61311-normalize.rs create mode 100644 tests/ui/nll/issue-61320-normalize.rs create mode 100644 tests/ui/nll/issue-61424.fixed create mode 100644 tests/ui/nll/issue-61424.rs create mode 100644 tests/ui/nll/issue-61424.stderr create mode 100644 tests/ui/nll/issue-62007-assign-const-index.rs create mode 100644 tests/ui/nll/issue-62007-assign-const-index.stderr create mode 100644 tests/ui/nll/issue-62007-assign-differing-fields.rs create mode 100644 tests/ui/nll/issue-62007-assign-differing-fields.stderr create mode 100644 tests/ui/nll/issue-63154-normalize.rs create mode 100644 tests/ui/nll/issue-67007-escaping-data.rs create mode 100644 tests/ui/nll/issue-67007-escaping-data.stderr create mode 100644 tests/ui/nll/issue-68550.rs create mode 100644 tests/ui/nll/issue-68550.stderr create mode 100644 tests/ui/nll/issue-69114-static-mut-ty.rs create mode 100644 tests/ui/nll/issue-69114-static-mut-ty.stderr create mode 100644 tests/ui/nll/issue-69114-static-ty.rs create mode 100644 tests/ui/nll/issue-69114-static-ty.stderr create mode 100644 tests/ui/nll/issue-73159-rpit-static.rs create mode 100644 tests/ui/nll/issue-73159-rpit-static.stderr create mode 100644 tests/ui/nll/issue-78561.rs create mode 100644 tests/ui/nll/issue-95272.rs create mode 100644 tests/ui/nll/issue-95272.stderr create mode 100644 tests/ui/nll/issue-97997.rs create mode 100644 tests/ui/nll/issue-97997.stderr create mode 100644 tests/ui/nll/issue-98170.rs create mode 100644 tests/ui/nll/issue-98170.stderr create mode 100644 tests/ui/nll/issue-98589-closures-relate-named-regions.rs create mode 100644 tests/ui/nll/issue-98589-closures-relate-named-regions.stderr create mode 100644 tests/ui/nll/issue-98693.rs create mode 100644 tests/ui/nll/issue-98693.stderr create mode 100644 tests/ui/nll/lint-no-err.rs create mode 100644 tests/ui/nll/loan_ends_mid_block_pair.rs create mode 100644 tests/ui/nll/loan_ends_mid_block_pair.stderr create mode 100644 tests/ui/nll/loan_ends_mid_block_vec.rs create mode 100644 tests/ui/nll/loan_ends_mid_block_vec.stderr create mode 100644 tests/ui/nll/local-outlives-static-via-hrtb.rs create mode 100644 tests/ui/nll/local-outlives-static-via-hrtb.stderr create mode 100644 tests/ui/nll/lub-if.rs create mode 100644 tests/ui/nll/lub-if.stderr create mode 100644 tests/ui/nll/lub-match.rs create mode 100644 tests/ui/nll/lub-match.stderr create mode 100644 tests/ui/nll/match-cfg-fake-edges.rs create mode 100644 tests/ui/nll/match-cfg-fake-edges.stderr create mode 100644 tests/ui/nll/match-cfg-fake-edges2.rs create mode 100644 tests/ui/nll/match-cfg-fake-edges2.stderr create mode 100644 tests/ui/nll/match-guards-always-borrow.rs create mode 100644 tests/ui/nll/match-guards-always-borrow.stderr create mode 100644 tests/ui/nll/match-guards-partially-borrow.rs create mode 100644 tests/ui/nll/match-guards-partially-borrow.stderr create mode 100644 tests/ui/nll/match-on-borrowed.rs create mode 100644 tests/ui/nll/match-on-borrowed.stderr create mode 100644 tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs create mode 100644 tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr create mode 100644 tests/ui/nll/maybe-initialized-drop-uninitialized.rs create mode 100644 tests/ui/nll/maybe-initialized-drop-with-fragment.rs create mode 100644 tests/ui/nll/maybe-initialized-drop-with-fragment.stderr create mode 100644 tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs create mode 100644 tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr create mode 100644 tests/ui/nll/maybe-initialized-drop.rs create mode 100644 tests/ui/nll/maybe-initialized-drop.stderr create mode 100644 tests/ui/nll/mir_check_cast_closure.rs create mode 100644 tests/ui/nll/mir_check_cast_closure.stderr create mode 100644 tests/ui/nll/mir_check_cast_reify.rs create mode 100644 tests/ui/nll/mir_check_cast_reify.stderr create mode 100644 tests/ui/nll/mir_check_cast_unsafe_fn.rs create mode 100644 tests/ui/nll/mir_check_cast_unsafe_fn.stderr create mode 100644 tests/ui/nll/mir_check_cast_unsize.rs create mode 100644 tests/ui/nll/mir_check_cast_unsize.stderr create mode 100644 tests/ui/nll/move-errors.rs create mode 100644 tests/ui/nll/move-errors.stderr create mode 100644 tests/ui/nll/move-subpaths-moves-root.rs create mode 100644 tests/ui/nll/move-subpaths-moves-root.stderr create mode 100644 tests/ui/nll/mutating_references.rs create mode 100644 tests/ui/nll/normalization-bounds-error.rs create mode 100644 tests/ui/nll/normalization-bounds-error.stderr create mode 100644 tests/ui/nll/normalization-bounds.rs create mode 100644 tests/ui/nll/outlives-suggestion-more.rs create mode 100644 tests/ui/nll/outlives-suggestion-more.stderr create mode 100644 tests/ui/nll/outlives-suggestion-simple.polonius.stderr create mode 100644 tests/ui/nll/outlives-suggestion-simple.rs create mode 100644 tests/ui/nll/outlives-suggestion-simple.stderr create mode 100644 tests/ui/nll/polonius/assignment-kills-loans.rs create mode 100644 tests/ui/nll/polonius/assignment-to-differing-field.rs create mode 100644 tests/ui/nll/polonius/assignment-to-differing-field.stderr create mode 100644 tests/ui/nll/polonius/call-kills-loans.rs create mode 100644 tests/ui/nll/polonius/issue-46589.rs create mode 100644 tests/ui/nll/polonius/polonius-smoke-test.rs create mode 100644 tests/ui/nll/polonius/polonius-smoke-test.stderr create mode 100644 tests/ui/nll/polonius/storagedead-kills-loans.rs create mode 100644 tests/ui/nll/polonius/subset-relations.rs create mode 100644 tests/ui/nll/polonius/subset-relations.stderr create mode 100644 tests/ui/nll/process_or_insert_default.rs create mode 100644 tests/ui/nll/projection-return.rs create mode 100644 tests/ui/nll/promotable-mutable-zst-doesnt-conflict.rs create mode 100644 tests/ui/nll/promoted-bounds.rs create mode 100644 tests/ui/nll/promoted-bounds.stderr create mode 100644 tests/ui/nll/promoted-closure-pair.rs create mode 100644 tests/ui/nll/promoted-closure-pair.stderr create mode 100644 tests/ui/nll/promoted-liveness.rs create mode 100644 tests/ui/nll/rc-loop.rs create mode 100644 tests/ui/nll/ref-suggestion.rs create mode 100644 tests/ui/nll/ref-suggestion.stderr create mode 100644 tests/ui/nll/reference-carried-through-struct-field.rs create mode 100644 tests/ui/nll/reference-carried-through-struct-field.stderr create mode 100644 tests/ui/nll/region-ends-after-if-condition.rs create mode 100644 tests/ui/nll/region-ends-after-if-condition.stderr create mode 100644 tests/ui/nll/relate_tys/fn-subtype.rs create mode 100644 tests/ui/nll/relate_tys/fn-subtype.stderr create mode 100644 tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs create mode 100644 tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr create mode 100644 tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs create mode 100644 tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs create mode 100644 tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs create mode 100644 tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr create mode 100644 tests/ui/nll/relate_tys/issue-48071.rs create mode 100644 tests/ui/nll/relate_tys/opaque-hrtb.rs create mode 100644 tests/ui/nll/relate_tys/opaque-hrtb.stderr create mode 100644 tests/ui/nll/relate_tys/trait-hrtb.rs create mode 100644 tests/ui/nll/relate_tys/trait-hrtb.stderr create mode 100644 tests/ui/nll/relate_tys/universe-violation.rs create mode 100644 tests/ui/nll/relate_tys/universe-violation.stderr create mode 100644 tests/ui/nll/relate_tys/var-appears-twice.rs create mode 100644 tests/ui/nll/relate_tys/var-appears-twice.stderr create mode 100644 tests/ui/nll/return-ref-mut-issue-46557.rs create mode 100644 tests/ui/nll/return-ref-mut-issue-46557.stderr create mode 100644 tests/ui/nll/return_from_loop.rs create mode 100644 tests/ui/nll/return_from_loop.stderr create mode 100644 tests/ui/nll/self-assign-ref-mut.rs create mode 100644 tests/ui/nll/snocat-regression.rs create mode 100644 tests/ui/nll/snocat-regression.stderr create mode 100644 tests/ui/nll/trait-associated-constant.rs create mode 100644 tests/ui/nll/trait-associated-constant.stderr create mode 100644 tests/ui/nll/ty-outlives/impl-trait-captures.rs create mode 100644 tests/ui/nll/ty-outlives/impl-trait-captures.stderr create mode 100644 tests/ui/nll/ty-outlives/impl-trait-outlives.rs create mode 100644 tests/ui/nll/ty-outlives/impl-trait-outlives.stderr create mode 100644 tests/ui/nll/ty-outlives/issue-53789-1.rs create mode 100644 tests/ui/nll/ty-outlives/issue-53789-2.rs create mode 100644 tests/ui/nll/ty-outlives/issue-55756.rs create mode 100644 tests/ui/nll/ty-outlives/projection-body.rs create mode 100644 tests/ui/nll/ty-outlives/projection-implied-bounds.rs create mode 100644 tests/ui/nll/ty-outlives/projection-implied-bounds.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-no-regions-closure.rs create mode 100644 tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-no-regions-fn.rs create mode 100644 tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-one-region-closure.rs create mode 100644 tests/ui/nll/ty-outlives/projection-one-region-closure.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs create mode 100644 tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs create mode 100644 tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs create mode 100644 tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-env.rs create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-none.rs create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-none.stderr create mode 100644 tests/ui/nll/ty-outlives/projection-where-clause-trait.rs create mode 100644 tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs create mode 100644 tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr create mode 100644 tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs create mode 100644 tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr create mode 100644 tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs create mode 100644 tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr create mode 100644 tests/ui/nll/ty-outlives/ty-param-fn-body.rs create mode 100644 tests/ui/nll/ty-outlives/ty-param-fn-body.stderr create mode 100644 tests/ui/nll/ty-outlives/ty-param-fn.rs create mode 100644 tests/ui/nll/ty-outlives/ty-param-fn.stderr create mode 100644 tests/ui/nll/ty-outlives/ty-param-implied-bounds.rs create mode 100644 tests/ui/nll/ty-outlives/wf-unreachable.rs create mode 100644 tests/ui/nll/ty-outlives/wf-unreachable.stderr create mode 100644 tests/ui/nll/type-alias-free-regions.rs create mode 100644 tests/ui/nll/type-alias-free-regions.stderr create mode 100644 tests/ui/nll/type-check-pointer-coercions.rs create mode 100644 tests/ui/nll/type-check-pointer-coercions.stderr create mode 100644 tests/ui/nll/type-check-pointer-comparisons.rs create mode 100644 tests/ui/nll/type-check-pointer-comparisons.stderr create mode 100644 tests/ui/nll/type-test-universe.rs create mode 100644 tests/ui/nll/type-test-universe.stderr create mode 100644 tests/ui/nll/unused-mut-issue-50343.fixed create mode 100644 tests/ui/nll/unused-mut-issue-50343.rs create mode 100644 tests/ui/nll/unused-mut-issue-50343.stderr create mode 100644 tests/ui/nll/user-annotations/adt-brace-enums.rs create mode 100644 tests/ui/nll/user-annotations/adt-brace-enums.stderr create mode 100644 tests/ui/nll/user-annotations/adt-brace-structs.rs create mode 100644 tests/ui/nll/user-annotations/adt-brace-structs.stderr create mode 100644 tests/ui/nll/user-annotations/adt-nullary-enums.rs create mode 100644 tests/ui/nll/user-annotations/adt-nullary-enums.stderr create mode 100644 tests/ui/nll/user-annotations/adt-tuple-enums.rs create mode 100644 tests/ui/nll/user-annotations/adt-tuple-enums.stderr create mode 100644 tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs create mode 100644 tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr create mode 100644 tests/ui/nll/user-annotations/adt-tuple-struct.rs create mode 100644 tests/ui/nll/user-annotations/adt-tuple-struct.stderr create mode 100644 tests/ui/nll/user-annotations/ascribed-type-wf.rs create mode 100644 tests/ui/nll/user-annotations/ascribed-type-wf.stderr create mode 100644 tests/ui/nll/user-annotations/cast_static_lifetime.rs create mode 100644 tests/ui/nll/user-annotations/cast_static_lifetime.stderr create mode 100644 tests/ui/nll/user-annotations/closure-sig.rs create mode 100644 tests/ui/nll/user-annotations/closure-substs.polonius.stderr create mode 100644 tests/ui/nll/user-annotations/closure-substs.rs create mode 100644 tests/ui/nll/user-annotations/closure-substs.stderr create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-normalize.rs create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs create mode 100644 tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr create mode 100644 tests/ui/nll/user-annotations/downcast-infer.rs create mode 100644 tests/ui/nll/user-annotations/dump-adt-brace-struct.rs create mode 100644 tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr create mode 100644 tests/ui/nll/user-annotations/dump-fn-method.rs create mode 100644 tests/ui/nll/user-annotations/dump-fn-method.stderr create mode 100644 tests/ui/nll/user-annotations/fns.rs create mode 100644 tests/ui/nll/user-annotations/fns.stderr create mode 100644 tests/ui/nll/user-annotations/inherent-associated-constants.rs create mode 100644 tests/ui/nll/user-annotations/inherent-associated-constants.stderr create mode 100644 tests/ui/nll/user-annotations/issue-54124.rs create mode 100644 tests/ui/nll/user-annotations/issue-54124.stderr create mode 100644 tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs create mode 100644 tests/ui/nll/user-annotations/issue-55219.rs create mode 100644 tests/ui/nll/user-annotations/issue-55241.rs create mode 100644 tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs create mode 100644 tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr create mode 100644 tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs create mode 100644 tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr create mode 100644 tests/ui/nll/user-annotations/method-call.rs create mode 100644 tests/ui/nll/user-annotations/method-call.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-1.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-1.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-2.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-2.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-3.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-3.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs create mode 100644 tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr create mode 100644 tests/ui/nll/user-annotations/normalization-2.rs create mode 100644 tests/ui/nll/user-annotations/normalization-2.stderr create mode 100644 tests/ui/nll/user-annotations/normalization-default.rs create mode 100644 tests/ui/nll/user-annotations/normalization-default.stderr create mode 100644 tests/ui/nll/user-annotations/normalization-infer.rs create mode 100644 tests/ui/nll/user-annotations/normalization-infer.stderr create mode 100644 tests/ui/nll/user-annotations/normalization-self.rs create mode 100644 tests/ui/nll/user-annotations/normalization-self.stderr create mode 100644 tests/ui/nll/user-annotations/normalization.rs create mode 100644 tests/ui/nll/user-annotations/normalization.stderr create mode 100644 tests/ui/nll/user-annotations/normalize-self-ty.rs create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs create mode 100644 tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr create mode 100644 tests/ui/nll/user-annotations/patterns.rs create mode 100644 tests/ui/nll/user-annotations/patterns.stderr create mode 100644 tests/ui/nll/user-annotations/promoted-annotation.rs create mode 100644 tests/ui/nll/user-annotations/promoted-annotation.stderr create mode 100644 tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs create mode 100644 tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs create mode 100644 tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr create mode 100644 tests/ui/nll/user-annotations/wf-self-type.rs create mode 100644 tests/ui/nll/user-annotations/wf-self-type.stderr create mode 100644 tests/ui/nll/vimwiki-core-regression.rs create mode 100644 tests/ui/nll/where_clauses_in_functions.rs create mode 100644 tests/ui/nll/where_clauses_in_functions.stderr create mode 100644 tests/ui/nll/where_clauses_in_structs.rs create mode 100644 tests/ui/nll/where_clauses_in_structs.stderr create mode 100644 tests/ui/no-capture-arc.rs create mode 100644 tests/ui/no-capture-arc.stderr create mode 100644 tests/ui/no-core-1.rs create mode 100644 tests/ui/no-core-2.rs create mode 100644 tests/ui/no-link-unknown-crate.rs create mode 100644 tests/ui/no-link-unknown-crate.stderr create mode 100644 tests/ui/no-patterns-in-args-2.rs create mode 100644 tests/ui/no-patterns-in-args-2.stderr create mode 100644 tests/ui/no-patterns-in-args-macro.rs create mode 100644 tests/ui/no-patterns-in-args-macro.stderr create mode 100644 tests/ui/no-patterns-in-args.rs create mode 100644 tests/ui/no-patterns-in-args.stderr create mode 100644 tests/ui/no-reuse-move-arc.rs create mode 100644 tests/ui/no-reuse-move-arc.stderr create mode 100644 tests/ui/no-send-res-ports.rs create mode 100644 tests/ui/no-send-res-ports.stderr create mode 100644 tests/ui/no-warn-on-field-replace-issue-34101.rs create mode 100644 tests/ui/no_crate_type.rs create mode 100644 tests/ui/no_crate_type.stderr create mode 100644 tests/ui/no_send-enum.rs create mode 100644 tests/ui/no_send-enum.stderr create mode 100644 tests/ui/no_send-rc.rs create mode 100644 tests/ui/no_send-rc.stderr create mode 100644 tests/ui/no_share-enum.rs create mode 100644 tests/ui/no_share-enum.stderr create mode 100644 tests/ui/no_share-struct.rs create mode 100644 tests/ui/no_share-struct.stderr create mode 100644 tests/ui/noexporttypeexe.rs create mode 100644 tests/ui/noexporttypeexe.stderr create mode 100644 tests/ui/non-constant-expr-for-arr-len.rs create mode 100644 tests/ui/non-constant-expr-for-arr-len.stderr create mode 100644 tests/ui/non-copyable-void.rs create mode 100644 tests/ui/non-copyable-void.stderr create mode 100644 tests/ui/non-fmt-panic.fixed create mode 100644 tests/ui/non-fmt-panic.rs create mode 100644 tests/ui/non-fmt-panic.stderr create mode 100644 tests/ui/non-ice-error-on-worker-io-fail.rs create mode 100644 tests/ui/non-ice-error-on-worker-io-fail.stderr create mode 100644 tests/ui/non_modrs_mods/foors_mod.rs create mode 100644 tests/ui/non_modrs_mods/foors_mod/compiletest-ignore-dir create mode 100644 tests/ui/non_modrs_mods/foors_mod/inline/somename.rs create mode 100644 tests/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs create mode 100644 tests/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs create mode 100644 tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs create mode 100644 tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs create mode 100644 tests/ui/non_modrs_mods/modrs_mod/compiletest-ignore-dir create mode 100644 tests/ui/non_modrs_mods/modrs_mod/inline/somename.rs create mode 100644 tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs create mode 100644 tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs create mode 100644 tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs create mode 100644 tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs create mode 100644 tests/ui/non_modrs_mods/modrs_mod/mod.rs create mode 100644 tests/ui/non_modrs_mods/non_modrs_mods.rs create mode 100644 tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs create mode 100644 tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/compiletest-ignore-dir create mode 100644 tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs create mode 100644 tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs create mode 100644 tests/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs create mode 100644 tests/ui/non_modrs_mods_and_inline_mods/x.rs create mode 100644 tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs create mode 100644 tests/ui/noncopyable-class.rs create mode 100644 tests/ui/noncopyable-class.stderr create mode 100644 tests/ui/nonscalar-cast.fixed create mode 100644 tests/ui/nonscalar-cast.rs create mode 100644 tests/ui/nonscalar-cast.stderr create mode 100644 tests/ui/not-clone-closure.rs create mode 100644 tests/ui/not-clone-closure.stderr create mode 100644 tests/ui/not-copy-closure.rs create mode 100644 tests/ui/not-copy-closure.stderr create mode 100644 tests/ui/not-enough-arguments.rs create mode 100644 tests/ui/not-enough-arguments.stderr create mode 100644 tests/ui/not-panic/not-panic-safe-2.rs create mode 100644 tests/ui/not-panic/not-panic-safe-2.stderr create mode 100644 tests/ui/not-panic/not-panic-safe-3.rs create mode 100644 tests/ui/not-panic/not-panic-safe-3.stderr create mode 100644 tests/ui/not-panic/not-panic-safe-4.rs create mode 100644 tests/ui/not-panic/not-panic-safe-4.stderr create mode 100644 tests/ui/not-panic/not-panic-safe-5.rs create mode 100644 tests/ui/not-panic/not-panic-safe-5.stderr create mode 100644 tests/ui/not-panic/not-panic-safe-6.rs create mode 100644 tests/ui/not-panic/not-panic-safe-6.stderr create mode 100644 tests/ui/not-panic/not-panic-safe.rs create mode 100644 tests/ui/not-panic/not-panic-safe.stderr create mode 100644 tests/ui/nul-characters.rs create mode 100644 tests/ui/nullable-pointer-iotareduction.rs create mode 100644 tests/ui/nullable-pointer-size.rs create mode 100644 tests/ui/numbers-arithmetic/arith-unsigned.rs create mode 100644 tests/ui/numbers-arithmetic/div-mod.rs create mode 100644 tests/ui/numbers-arithmetic/divide-by-zero.rs create mode 100644 tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs create mode 100644 tests/ui/numbers-arithmetic/float-literal-inference.rs create mode 100644 tests/ui/numbers-arithmetic/float-nan.rs create mode 100644 tests/ui/numbers-arithmetic/float-signature.rs create mode 100644 tests/ui/numbers-arithmetic/float.rs create mode 100644 tests/ui/numbers-arithmetic/float2.rs create mode 100644 tests/ui/numbers-arithmetic/float_math.rs create mode 100644 tests/ui/numbers-arithmetic/floatlits.rs create mode 100644 tests/ui/numbers-arithmetic/i128.rs create mode 100644 tests/ui/numbers-arithmetic/i32-sub.rs create mode 100644 tests/ui/numbers-arithmetic/i8-incr.rs create mode 100644 tests/ui/numbers-arithmetic/int-abs-overflow.rs create mode 100644 tests/ui/numbers-arithmetic/int.rs create mode 100644 tests/ui/numbers-arithmetic/integer-literal-radix.rs create mode 100644 tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs create mode 100644 tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs create mode 100644 tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs create mode 100644 tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr create mode 100644 tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr create mode 100644 tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr create mode 100644 tests/ui/numbers-arithmetic/issue-8460-const.rs create mode 100644 tests/ui/numbers-arithmetic/issue-8460.rs create mode 100644 tests/ui/numbers-arithmetic/mod-zero.rs create mode 100644 tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs create mode 100644 tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs create mode 100644 tests/ui/numbers-arithmetic/not-suggest-float-literal.rs create mode 100644 tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr create mode 100644 tests/ui/numbers-arithmetic/num-wrapping.rs create mode 100644 tests/ui/numbers-arithmetic/numeric-method-autoexport.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-add.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-1.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-2.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-3.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-4.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-mul.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-neg.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-pow-signed.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-1.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-2.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-3.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-4.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-5.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-6.rs create mode 100644 tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr create mode 100644 tests/ui/numbers-arithmetic/overflowing-sub.rs create mode 100644 tests/ui/numbers-arithmetic/promoted_overflow.rs create mode 100644 tests/ui/numbers-arithmetic/promoted_overflow_opt.rs create mode 100644 tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs create mode 100644 tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs create mode 100644 tests/ui/numbers-arithmetic/saturating-float-casts.rs create mode 100644 tests/ui/numbers-arithmetic/shift-near-oflo.rs create mode 100644 tests/ui/numbers-arithmetic/shift-various-types.rs create mode 100644 tests/ui/numbers-arithmetic/shift.rs create mode 100644 tests/ui/numbers-arithmetic/signed-shift-const-eval.rs create mode 100644 tests/ui/numbers-arithmetic/suggest-float-literal.fixed create mode 100644 tests/ui/numbers-arithmetic/suggest-float-literal.rs create mode 100644 tests/ui/numbers-arithmetic/suggest-float-literal.stderr create mode 100644 tests/ui/numbers-arithmetic/u128-as-f32.rs create mode 100644 tests/ui/numbers-arithmetic/u128.rs create mode 100644 tests/ui/numbers-arithmetic/u32-decr.rs create mode 100644 tests/ui/numbers-arithmetic/u8-incr-decr.rs create mode 100644 tests/ui/numbers-arithmetic/u8-incr.rs create mode 100644 tests/ui/numbers-arithmetic/uint.rs create mode 100644 tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs create mode 100644 tests/ui/numeric/const-scope.rs create mode 100644 tests/ui/numeric/const-scope.stderr create mode 100644 tests/ui/numeric/integer-literal-suffix-inference.rs create mode 100644 tests/ui/numeric/integer-literal-suffix-inference.stderr create mode 100644 tests/ui/numeric/len.rs create mode 100644 tests/ui/numeric/len.stderr create mode 100644 tests/ui/numeric/numeric-cast-2.rs create mode 100644 tests/ui/numeric/numeric-cast-2.stderr create mode 100644 tests/ui/numeric/numeric-cast-binop.fixed create mode 100644 tests/ui/numeric/numeric-cast-binop.rs create mode 100644 tests/ui/numeric/numeric-cast-binop.stderr create mode 100644 tests/ui/numeric/numeric-cast-no-fix.rs create mode 100644 tests/ui/numeric/numeric-cast-no-fix.stderr create mode 100644 tests/ui/numeric/numeric-cast-without-suggestion.rs create mode 100644 tests/ui/numeric/numeric-cast-without-suggestion.stderr create mode 100644 tests/ui/numeric/numeric-cast.fixed create mode 100644 tests/ui/numeric/numeric-cast.rs create mode 100644 tests/ui/numeric/numeric-cast.stderr create mode 100644 tests/ui/numeric/numeric-fields.rs create mode 100644 tests/ui/numeric/numeric-fields.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix.fixed create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix.rs create mode 100644 tests/ui/numeric/numeric-suffix/numeric-suffix.stderr create mode 100644 tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs create mode 100644 tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr create mode 100644 tests/ui/numeric/uppercase-base-prefix.fixed create mode 100644 tests/ui/numeric/uppercase-base-prefix.rs create mode 100644 tests/ui/numeric/uppercase-base-prefix.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-elision.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-elision.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-inferred.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-mybox.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default-mybox.stderr create mode 100644 tests/ui/object-lifetime/object-lifetime-default.rs create mode 100644 tests/ui/object-lifetime/object-lifetime-default.stderr create mode 100644 tests/ui/object-pointer-types.rs create mode 100644 tests/ui/object-pointer-types.stderr create mode 100644 tests/ui/object-safety/issue-102762.rs create mode 100644 tests/ui/object-safety/issue-102762.stderr create mode 100644 tests/ui/object-safety/issue-102933.rs create mode 100644 tests/ui/object-safety/issue-106247.rs create mode 100644 tests/ui/object-safety/issue-19538.rs create mode 100644 tests/ui/object-safety/issue-19538.stderr create mode 100644 tests/ui/object-safety/object-safety-associated-consts.curr.stderr create mode 100644 tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-associated-consts.rs create mode 100644 tests/ui/object-safety/object-safety-bounds.rs create mode 100644 tests/ui/object-safety/object-safety-bounds.stderr create mode 100644 tests/ui/object-safety/object-safety-by-value-self-use.rs create mode 100644 tests/ui/object-safety/object-safety-by-value-self-use.stderr create mode 100644 tests/ui/object-safety/object-safety-by-value-self.rs create mode 100644 tests/ui/object-safety/object-safety-generics.curr.stderr create mode 100644 tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-generics.rs create mode 100644 tests/ui/object-safety/object-safety-issue-22040.rs create mode 100644 tests/ui/object-safety/object-safety-issue-22040.stderr create mode 100644 tests/ui/object-safety/object-safety-mentions-Self.curr.stderr create mode 100644 tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-mentions-Self.rs create mode 100644 tests/ui/object-safety/object-safety-no-static.curr.stderr create mode 100644 tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-no-static.rs create mode 100644 tests/ui/object-safety/object-safety-phantom-fn.rs create mode 100644 tests/ui/object-safety/object-safety-sized-2.curr.stderr create mode 100644 tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-sized-2.rs create mode 100644 tests/ui/object-safety/object-safety-sized.curr.stderr create mode 100644 tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr create mode 100644 tests/ui/object-safety/object-safety-sized.rs create mode 100644 tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs create mode 100644 tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr create mode 100644 tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs create mode 100644 tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr create mode 100644 tests/ui/objects-coerce-freeze-borrored.rs create mode 100644 tests/ui/obsolete-in-place/bad.rs create mode 100644 tests/ui/obsolete-in-place/bad.stderr create mode 100644 tests/ui/occurs-check-2.rs create mode 100644 tests/ui/occurs-check-2.stderr create mode 100644 tests/ui/occurs-check-3.rs create mode 100644 tests/ui/occurs-check-3.stderr create mode 100644 tests/ui/occurs-check.rs create mode 100644 tests/ui/occurs-check.stderr create mode 100644 tests/ui/on-unimplemented/auxiliary/no_debug.rs create mode 100644 tests/ui/on-unimplemented/bad-annotation.rs create mode 100644 tests/ui/on-unimplemented/bad-annotation.stderr create mode 100644 tests/ui/on-unimplemented/expected-comma-found-token.rs create mode 100644 tests/ui/on-unimplemented/expected-comma-found-token.stderr create mode 100644 tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs create mode 100644 tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr create mode 100644 tests/ui/on-unimplemented/impl-substs.rs create mode 100644 tests/ui/on-unimplemented/impl-substs.stderr create mode 100644 tests/ui/on-unimplemented/issue-104140.rs create mode 100644 tests/ui/on-unimplemented/issue-104140.stderr create mode 100644 tests/ui/on-unimplemented/multiple-impls.rs create mode 100644 tests/ui/on-unimplemented/multiple-impls.stderr create mode 100644 tests/ui/on-unimplemented/no-debug.rs create mode 100644 tests/ui/on-unimplemented/no-debug.stderr create mode 100644 tests/ui/on-unimplemented/on-impl.rs create mode 100644 tests/ui/on-unimplemented/on-impl.stderr create mode 100644 tests/ui/on-unimplemented/on-trait.rs create mode 100644 tests/ui/on-unimplemented/on-trait.stderr create mode 100644 tests/ui/on-unimplemented/parent-label.rs create mode 100644 tests/ui/on-unimplemented/parent-label.stderr create mode 100644 tests/ui/on-unimplemented/slice-index.rs create mode 100644 tests/ui/on-unimplemented/slice-index.stderr create mode 100644 tests/ui/on-unimplemented/sum.rs create mode 100644 tests/ui/on-unimplemented/sum.stderr create mode 100644 tests/ui/once-cant-call-twice-on-heap.rs create mode 100644 tests/ui/once-cant-call-twice-on-heap.stderr create mode 100644 tests/ui/oom_unwind.rs create mode 100644 tests/ui/op-assign-builtins-by-ref.rs create mode 100644 tests/ui/opeq.rs create mode 100644 tests/ui/operator-recovery/less-than-greater-than.rs create mode 100644 tests/ui/operator-recovery/less-than-greater-than.stderr create mode 100644 tests/ui/operator-recovery/spaceship.rs create mode 100644 tests/ui/operator-recovery/spaceship.stderr create mode 100644 tests/ui/opt-in-copy.rs create mode 100644 tests/ui/opt-in-copy.stderr create mode 100644 tests/ui/optimization-fuel-0.rs create mode 100644 tests/ui/optimization-fuel-0.stderr create mode 100644 tests/ui/optimization-fuel-1.rs create mode 100644 tests/ui/optimization-fuel-1.stderr create mode 100644 tests/ui/optimization-remark.rs create mode 100644 tests/ui/or-patterns/already-bound-name.rs create mode 100644 tests/ui/or-patterns/already-bound-name.stderr create mode 100644 tests/ui/or-patterns/basic-switch.rs create mode 100644 tests/ui/or-patterns/basic-switchint.rs create mode 100644 tests/ui/or-patterns/bindings-runpass-1.rs create mode 100644 tests/ui/or-patterns/bindings-runpass-2.rs create mode 100644 tests/ui/or-patterns/box-patterns.rs create mode 100644 tests/ui/or-patterns/consistent-bindings.rs create mode 100644 tests/ui/or-patterns/const-fn.rs create mode 100644 tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs create mode 100644 tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr create mode 100644 tests/ui/or-patterns/exhaustiveness-pass.rs create mode 100644 tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs create mode 100644 tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr create mode 100644 tests/ui/or-patterns/fn-param-wrap-parens.fixed create mode 100644 tests/ui/or-patterns/fn-param-wrap-parens.rs create mode 100644 tests/ui/or-patterns/fn-param-wrap-parens.stderr create mode 100644 tests/ui/or-patterns/for-loop.rs create mode 100644 tests/ui/or-patterns/if-let-while-let.rs create mode 100644 tests/ui/or-patterns/inconsistent-modes.rs create mode 100644 tests/ui/or-patterns/inconsistent-modes.stderr create mode 100644 tests/ui/or-patterns/inner-or-pat.or3.stderr create mode 100644 tests/ui/or-patterns/inner-or-pat.or4.stderr create mode 100644 tests/ui/or-patterns/inner-or-pat.rs create mode 100644 tests/ui/or-patterns/issue-64879-trailing-before-guard.rs create mode 100644 tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr create mode 100644 tests/ui/or-patterns/issue-67514-irrefutable-param.rs create mode 100644 tests/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs create mode 100644 tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs create mode 100644 tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr create mode 100644 tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs create mode 100644 tests/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs create mode 100644 tests/ui/or-patterns/let-pattern.rs create mode 100644 tests/ui/or-patterns/macro-pat.rs create mode 100644 tests/ui/or-patterns/mismatched-bindings-async-fn.rs create mode 100644 tests/ui/or-patterns/mismatched-bindings-async-fn.stderr create mode 100644 tests/ui/or-patterns/missing-bindings.rs create mode 100644 tests/ui/or-patterns/missing-bindings.stderr create mode 100644 tests/ui/or-patterns/mix-with-wild.rs create mode 100644 tests/ui/or-patterns/multiple-pattern-typo.rs create mode 100644 tests/ui/or-patterns/multiple-pattern-typo.stderr create mode 100644 tests/ui/or-patterns/nested-undelimited-precedence.rs create mode 100644 tests/ui/or-patterns/nested-undelimited-precedence.stderr create mode 100644 tests/ui/or-patterns/or-patterns-binding-type-mismatch.rs create mode 100644 tests/ui/or-patterns/or-patterns-binding-type-mismatch.stderr create mode 100644 tests/ui/or-patterns/or-patterns-default-binding-modes.rs create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-fail.rs create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-fail.stderr create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-pass-2021.rs create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-pass.rs create mode 100644 tests/ui/or-patterns/or-patterns-syntactic-pass.stderr create mode 100644 tests/ui/or-patterns/remove-leading-vert.fixed create mode 100644 tests/ui/or-patterns/remove-leading-vert.rs create mode 100644 tests/ui/or-patterns/remove-leading-vert.stderr create mode 100644 tests/ui/or-patterns/search-via-bindings.rs create mode 100644 tests/ui/or-patterns/slice-patterns.rs create mode 100644 tests/ui/or-patterns/struct-like.rs create mode 100644 tests/ui/or-patterns/while-parsing-this-or-pattern.rs create mode 100644 tests/ui/or-patterns/while-parsing-this-or-pattern.stderr create mode 100644 tests/ui/order-dependent-cast-inference.rs create mode 100644 tests/ui/order-dependent-cast-inference.stderr create mode 100644 tests/ui/orphan-check-diagnostics.rs create mode 100644 tests/ui/orphan-check-diagnostics.stderr create mode 100644 tests/ui/osx-frameworks.rs create mode 100644 tests/ui/osx-frameworks.stderr create mode 100644 tests/ui/out-pointer-aliasing.rs create mode 100644 tests/ui/output-slot-variants.rs create mode 100644 tests/ui/output-type-mismatch.rs create mode 100644 tests/ui/output-type-mismatch.stderr create mode 100644 tests/ui/over-constrained-vregs.rs create mode 100644 tests/ui/overloaded/auxiliary/overloaded_autoderef_xc.rs create mode 100644 tests/ui/overloaded/fixup-deref-mut.rs create mode 100644 tests/ui/overloaded/issue-14958.rs create mode 100644 tests/ui/overloaded/overloaded-autoderef-count.rs create mode 100644 tests/ui/overloaded/overloaded-autoderef-indexing.rs create mode 100644 tests/ui/overloaded/overloaded-autoderef-order.rs create mode 100644 tests/ui/overloaded/overloaded-autoderef-vtable.rs create mode 100644 tests/ui/overloaded/overloaded-autoderef-xcrate.rs create mode 100644 tests/ui/overloaded/overloaded-autoderef.rs create mode 100644 tests/ui/overloaded/overloaded-calls-nontuple.rs create mode 100644 tests/ui/overloaded/overloaded-calls-nontuple.stderr create mode 100644 tests/ui/overloaded/overloaded-calls-object-one-arg.rs create mode 100644 tests/ui/overloaded/overloaded-calls-object-two-args.rs create mode 100644 tests/ui/overloaded/overloaded-calls-object-zero-args.rs create mode 100644 tests/ui/overloaded/overloaded-calls-param-vtables.rs create mode 100644 tests/ui/overloaded/overloaded-calls-simple.rs create mode 100644 tests/ui/overloaded/overloaded-calls-zero-args.rs create mode 100644 tests/ui/overloaded/overloaded-deref-count.rs create mode 100644 tests/ui/overloaded/overloaded-deref.rs create mode 100644 tests/ui/overloaded/overloaded-index-assoc-list.rs create mode 100644 tests/ui/overloaded/overloaded-index-autoderef.rs create mode 100644 tests/ui/overloaded/overloaded-index-in-field.rs create mode 100644 tests/ui/overloaded/overloaded-index.rs create mode 100644 tests/ui/overloaded/overloaded_deref_with_ref_pattern.rs create mode 100644 tests/ui/overloaded/overloaded_deref_with_ref_pattern_issue15609.rs create mode 100644 tests/ui/packed-struct/packed-struct-generic-transmute.rs create mode 100644 tests/ui/packed-struct/packed-struct-generic-transmute.stderr create mode 100644 tests/ui/packed-struct/packed-struct-transmute.rs create mode 100644 tests/ui/packed-struct/packed-struct-transmute.stderr create mode 100644 tests/ui/packed/auxiliary/packed.rs create mode 100644 tests/ui/packed/issue-27060-2.rs create mode 100644 tests/ui/packed/issue-27060-2.stderr create mode 100644 tests/ui/packed/issue-27060-rpass.rs create mode 100644 tests/ui/packed/issue-27060-rpass.stderr create mode 100644 tests/ui/packed/issue-27060.rs create mode 100644 tests/ui/packed/issue-27060.stderr create mode 100644 tests/ui/packed/issue-46152.rs create mode 100644 tests/ui/packed/packed-struct-address-of-element.rs create mode 100644 tests/ui/packed/packed-struct-borrow-element-64bit.rs create mode 100644 tests/ui/packed/packed-struct-borrow-element-64bit.stderr create mode 100644 tests/ui/packed/packed-struct-borrow-element.rs create mode 100644 tests/ui/packed/packed-struct-borrow-element.stderr create mode 100644 tests/ui/packed/packed-struct-drop-aligned.rs create mode 100644 tests/ui/packed/packed-struct-generic-layout.rs create mode 100644 tests/ui/packed/packed-struct-generic-size.rs create mode 100644 tests/ui/packed/packed-struct-layout.rs create mode 100644 tests/ui/packed/packed-struct-match.rs create mode 100644 tests/ui/packed/packed-struct-optimized-enum.rs create mode 100644 tests/ui/packed/packed-struct-size-xc.rs create mode 100644 tests/ui/packed/packed-struct-size.rs create mode 100644 tests/ui/packed/packed-struct-vec.rs create mode 100644 tests/ui/packed/packed-tuple-struct-layout.rs create mode 100644 tests/ui/packed/packed-tuple-struct-size.rs create mode 100644 tests/ui/packed/packed-with-inference-vars-issue-61402.rs create mode 100644 tests/ui/panic-handler/auxiliary/some-panic-impl.rs create mode 100644 tests/ui/panic-handler/auxiliary/weak-lang-items.rs create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-1.rs create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-1.stderr create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-2.rs create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-2.stderr create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-3.rs create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-3.stderr create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-4.rs create mode 100644 tests/ui/panic-handler/panic-handler-bad-signature-4.stderr create mode 100644 tests/ui/panic-handler/panic-handler-duplicate.rs create mode 100644 tests/ui/panic-handler/panic-handler-duplicate.stderr create mode 100644 tests/ui/panic-handler/panic-handler-missing.rs create mode 100644 tests/ui/panic-handler/panic-handler-requires-panic-info.rs create mode 100644 tests/ui/panic-handler/panic-handler-requires-panic-info.stderr create mode 100644 tests/ui/panic-handler/panic-handler-std.rs create mode 100644 tests/ui/panic-handler/panic-handler-std.stderr create mode 100644 tests/ui/panic-handler/panic-handler-twice.rs create mode 100644 tests/ui/panic-handler/panic-handler-wrong-location.rs create mode 100644 tests/ui/panic-handler/panic-handler-wrong-location.stderr create mode 100644 tests/ui/panic-handler/weak-lang-item-2.rs create mode 100644 tests/ui/panic-handler/weak-lang-item.rs create mode 100644 tests/ui/panic-handler/weak-lang-item.stderr create mode 100644 tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs create mode 100644 tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr create mode 100644 tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs create mode 100644 tests/ui/panic-runtime/abort.rs create mode 100644 tests/ui/panic-runtime/auxiliary/depends.rs create mode 100644 tests/ui/panic-runtime/auxiliary/exit-success-if-unwind.rs create mode 100644 tests/ui/panic-runtime/auxiliary/needs-abort.rs create mode 100644 tests/ui/panic-runtime/auxiliary/needs-panic-runtime.rs create mode 100644 tests/ui/panic-runtime/auxiliary/needs-unwind.rs create mode 100644 tests/ui/panic-runtime/auxiliary/panic-runtime-abort.rs create mode 100644 tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs create mode 100644 tests/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs create mode 100644 tests/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs create mode 100644 tests/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs create mode 100644 tests/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs create mode 100644 tests/ui/panic-runtime/bad-panic-flag1.rs create mode 100644 tests/ui/panic-runtime/bad-panic-flag1.stderr create mode 100644 tests/ui/panic-runtime/bad-panic-flag2.rs create mode 100644 tests/ui/panic-runtime/bad-panic-flag2.stderr create mode 100644 tests/ui/panic-runtime/incompatible-type.rs create mode 100644 tests/ui/panic-runtime/link-to-abort.rs create mode 100644 tests/ui/panic-runtime/link-to-unwind.rs create mode 100644 tests/ui/panic-runtime/lto-abort.rs create mode 100644 tests/ui/panic-runtime/lto-unwind.rs create mode 100644 tests/ui/panic-runtime/need-abort-got-unwind.rs create mode 100644 tests/ui/panic-runtime/need-abort-got-unwind.stderr create mode 100644 tests/ui/panic-runtime/need-unwind-got-abort.rs create mode 100644 tests/ui/panic-runtime/need-unwind-got-abort.stderr create mode 100644 tests/ui/panic-runtime/needs-gate.rs create mode 100644 tests/ui/panic-runtime/needs-gate.stderr create mode 100644 tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs create mode 100644 tests/ui/panic-runtime/transitive-link-a-bunch.rs create mode 100644 tests/ui/panic-runtime/transitive-link-a-bunch.stderr create mode 100644 tests/ui/panic-runtime/two-panic-runtimes.rs create mode 100644 tests/ui/panic-runtime/unwind-interleaved.rs create mode 100644 tests/ui/panic-runtime/unwind-rec.rs create mode 100644 tests/ui/panic-runtime/unwind-rec2.rs create mode 100644 tests/ui/panic-runtime/unwind-tables-target-required.rs create mode 100644 tests/ui/panic-runtime/unwind-unique.rs create mode 100644 tests/ui/panic-runtime/want-abort-got-unwind.rs create mode 100644 tests/ui/panic-runtime/want-abort-got-unwind2.rs create mode 100644 tests/ui/panic-runtime/want-unwind-got-abort.rs create mode 100644 tests/ui/panic-runtime/want-unwind-got-abort.stderr create mode 100644 tests/ui/panic-runtime/want-unwind-got-abort2.rs create mode 100644 tests/ui/panic-runtime/want-unwind-got-abort2.stderr create mode 100644 tests/ui/panic-while-printing.rs create mode 100644 tests/ui/panic_implementation-closures.rs create mode 100644 tests/ui/panics/abort-on-panic.rs create mode 100644 tests/ui/panics/args-panic.rs create mode 100644 tests/ui/panics/default-backtrace-ice.rs create mode 100644 tests/ui/panics/default-backtrace-ice.stderr create mode 100644 tests/ui/panics/doublepanic.rs create mode 100644 tests/ui/panics/explicit-panic-msg.rs create mode 100644 tests/ui/panics/explicit-panic.rs create mode 100644 tests/ui/panics/fmt-panic.rs create mode 100644 tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr create mode 100644 tests/ui/panics/issue-47429-short-backtraces.rs create mode 100644 tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr create mode 100644 tests/ui/panics/location-detail-panic-no-column.rs create mode 100644 tests/ui/panics/location-detail-panic-no-column.run.stderr create mode 100644 tests/ui/panics/location-detail-panic-no-file.rs create mode 100644 tests/ui/panics/location-detail-panic-no-file.run.stderr create mode 100644 tests/ui/panics/location-detail-panic-no-line.rs create mode 100644 tests/ui/panics/location-detail-panic-no-line.run.stderr create mode 100644 tests/ui/panics/location-detail-panic-no-location-info.rs create mode 100644 tests/ui/panics/location-detail-panic-no-location-info.run.stderr create mode 100644 tests/ui/panics/location-detail-unwrap-no-file.rs create mode 100644 tests/ui/panics/location-detail-unwrap-no-file.run.stderr create mode 100644 tests/ui/panics/main-panic.rs create mode 100644 tests/ui/panics/panic-2021.rs create mode 100644 tests/ui/panics/panic-2021.stderr create mode 100644 tests/ui/panics/panic-arg.rs create mode 100644 tests/ui/panics/panic-handler-chain-update-hook.rs create mode 100644 tests/ui/panics/panic-handler-chain.rs create mode 100644 tests/ui/panics/panic-handler-flail-wildly.rs create mode 100644 tests/ui/panics/panic-handler-set-twice.rs create mode 100644 tests/ui/panics/panic-in-dtor-drops-fields.rs create mode 100644 tests/ui/panics/panic-macro-any-wrapped.rs create mode 100644 tests/ui/panics/panic-macro-any.rs create mode 100644 tests/ui/panics/panic-macro-explicit.rs create mode 100644 tests/ui/panics/panic-macro-fmt.rs create mode 100644 tests/ui/panics/panic-macro-owned.rs create mode 100644 tests/ui/panics/panic-macro-static.rs create mode 100644 tests/ui/panics/panic-main.rs create mode 100644 tests/ui/panics/panic-parens.rs create mode 100644 tests/ui/panics/panic-recover-propagate.rs create mode 100644 tests/ui/panics/panic-set-handler.rs create mode 100644 tests/ui/panics/panic-set-unset-handler.rs create mode 100644 tests/ui/panics/panic-short-backtrace-windows-x86_64.rs create mode 100644 tests/ui/panics/panic-short-backtrace-windows-x86_64.run.stderr create mode 100644 tests/ui/panics/panic-take-handler-nop.rs create mode 100644 tests/ui/panics/panic-task-name-none.rs create mode 100644 tests/ui/panics/panic-task-name-owned.rs create mode 100644 tests/ui/panics/panic.rs create mode 100644 tests/ui/panics/result-get-panic.rs create mode 100644 tests/ui/panics/runtime-switch.legacy.run.stderr create mode 100644 tests/ui/panics/runtime-switch.rs create mode 100644 tests/ui/panics/runtime-switch.v0.run.stderr create mode 100644 tests/ui/panics/test-panic.rs create mode 100644 tests/ui/panics/test-should-fail-bad-message.rs create mode 100644 tests/ui/panics/test-should-panic-bad-message.rs create mode 100644 tests/ui/panics/test-should-panic-no-message.rs create mode 100644 tests/ui/panics/unique-panic.rs create mode 100644 tests/ui/panics/while-body-panics.rs create mode 100644 tests/ui/panics/while-panic.rs create mode 100644 tests/ui/paren-span.rs create mode 100644 tests/ui/paren-span.stderr create mode 100644 tests/ui/parser/ascii-only-character-escape.rs create mode 100644 tests/ui/parser/ascii-only-character-escape.stderr create mode 100644 tests/ui/parser/assoc-const-underscore-semantic-fail.rs create mode 100644 tests/ui/parser/assoc-const-underscore-semantic-fail.stderr create mode 100644 tests/ui/parser/assoc-const-underscore-syntactic-pass.rs create mode 100644 tests/ui/parser/assoc-oddities-1.rs create mode 100644 tests/ui/parser/assoc-oddities-1.stderr create mode 100644 tests/ui/parser/assoc-oddities-2.rs create mode 100644 tests/ui/parser/assoc-oddities-2.stderr create mode 100644 tests/ui/parser/assoc-static-semantic-fail.rs create mode 100644 tests/ui/parser/assoc-static-semantic-fail.stderr create mode 100644 tests/ui/parser/assoc-static-syntactic-fail.rs create mode 100644 tests/ui/parser/assoc-static-syntactic-fail.stderr create mode 100644 tests/ui/parser/assoc-type-in-type-arg.rs create mode 100644 tests/ui/parser/assoc-type-in-type-arg.stderr create mode 100644 tests/ui/parser/associated-types-project-from-hrtb-explicit.rs create mode 100644 tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr create mode 100644 tests/ui/parser/attr-bad-meta-2.rs create mode 100644 tests/ui/parser/attr-bad-meta-2.stderr create mode 100644 tests/ui/parser/attr-bad-meta-3.rs create mode 100644 tests/ui/parser/attr-bad-meta-3.stderr create mode 100644 tests/ui/parser/attr-bad-meta.rs create mode 100644 tests/ui/parser/attr-bad-meta.stderr create mode 100644 tests/ui/parser/attr-before-eof.rs create mode 100644 tests/ui/parser/attr-before-eof.stderr create mode 100644 tests/ui/parser/attr-dangling-in-fn.rs create mode 100644 tests/ui/parser/attr-dangling-in-fn.stderr create mode 100644 tests/ui/parser/attr-dangling-in-mod.rs create mode 100644 tests/ui/parser/attr-dangling-in-mod.stderr create mode 100644 tests/ui/parser/attr-stmt-expr-attr-bad.rs create mode 100644 tests/ui/parser/attr-stmt-expr-attr-bad.stderr create mode 100644 tests/ui/parser/attr-with-a-semicolon.rs create mode 100644 tests/ui/parser/attr-with-a-semicolon.stderr create mode 100644 tests/ui/parser/attr.rs create mode 100644 tests/ui/parser/attr.stderr create mode 100644 tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs create mode 100644 tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr create mode 100644 tests/ui/parser/attrs-after-extern-mod.rs create mode 100644 tests/ui/parser/attrs-after-extern-mod.stderr create mode 100644 tests/ui/parser/bad-char-literals.rs create mode 100644 tests/ui/parser/bad-char-literals.stderr create mode 100644 tests/ui/parser/bad-crate-name.rs create mode 100644 tests/ui/parser/bad-crate-name.stderr create mode 100644 tests/ui/parser/bad-escape-suggest-raw-string.rs create mode 100644 tests/ui/parser/bad-escape-suggest-raw-string.stderr create mode 100644 tests/ui/parser/bad-fn-ptr-qualifier.fixed create mode 100644 tests/ui/parser/bad-fn-ptr-qualifier.rs create mode 100644 tests/ui/parser/bad-fn-ptr-qualifier.stderr create mode 100644 tests/ui/parser/bad-if-statements.rs create mode 100644 tests/ui/parser/bad-if-statements.stderr create mode 100644 tests/ui/parser/bad-interpolated-block.rs create mode 100644 tests/ui/parser/bad-interpolated-block.stderr create mode 100644 tests/ui/parser/bad-let-as-field.rs create mode 100644 tests/ui/parser/bad-let-as-field.stderr create mode 100644 tests/ui/parser/bad-lit-suffixes.rs create mode 100644 tests/ui/parser/bad-lit-suffixes.stderr create mode 100644 tests/ui/parser/bad-match.rs create mode 100644 tests/ui/parser/bad-match.stderr create mode 100644 tests/ui/parser/bad-name.rs create mode 100644 tests/ui/parser/bad-name.stderr create mode 100644 tests/ui/parser/bad-pointer-type.rs create mode 100644 tests/ui/parser/bad-pointer-type.stderr create mode 100644 tests/ui/parser/bad-recover-kw-after-impl.rs create mode 100644 tests/ui/parser/bad-recover-ty-after-impl.rs create mode 100644 tests/ui/parser/bad-struct-following-where.rs create mode 100644 tests/ui/parser/bad-struct-following-where.stderr create mode 100644 tests/ui/parser/bad-value-ident-false.rs create mode 100644 tests/ui/parser/bad-value-ident-false.stderr create mode 100644 tests/ui/parser/bad-value-ident-true.rs create mode 100644 tests/ui/parser/bad-value-ident-true.stderr create mode 100644 tests/ui/parser/bare-struct-body.rs create mode 100644 tests/ui/parser/bare-struct-body.stderr create mode 100644 tests/ui/parser/bastion-of-the-turbofish.rs create mode 100644 tests/ui/parser/better-expected.rs create mode 100644 tests/ui/parser/better-expected.stderr create mode 100644 tests/ui/parser/bind-struct-early-modifiers.rs create mode 100644 tests/ui/parser/bind-struct-early-modifiers.stderr create mode 100644 tests/ui/parser/block-no-opening-brace.rs create mode 100644 tests/ui/parser/block-no-opening-brace.stderr create mode 100644 tests/ui/parser/bound-single-question-mark.rs create mode 100644 tests/ui/parser/bound-single-question-mark.stderr create mode 100644 tests/ui/parser/bounds-lifetime-1.rs create mode 100644 tests/ui/parser/bounds-lifetime-1.stderr create mode 100644 tests/ui/parser/bounds-lifetime-2.rs create mode 100644 tests/ui/parser/bounds-lifetime-2.stderr create mode 100644 tests/ui/parser/bounds-lifetime-where-1.rs create mode 100644 tests/ui/parser/bounds-lifetime-where-1.stderr create mode 100644 tests/ui/parser/bounds-lifetime-where.rs create mode 100644 tests/ui/parser/bounds-lifetime-where.stderr create mode 100644 tests/ui/parser/bounds-lifetime.rs create mode 100644 tests/ui/parser/bounds-lifetime.stderr create mode 100644 tests/ui/parser/bounds-obj-parens.rs create mode 100644 tests/ui/parser/bounds-type-where.rs create mode 100644 tests/ui/parser/bounds-type-where.stderr create mode 100644 tests/ui/parser/bounds-type.rs create mode 100644 tests/ui/parser/bounds-type.stderr create mode 100644 tests/ui/parser/byte-literals.rs create mode 100644 tests/ui/parser/byte-literals.stderr create mode 100644 tests/ui/parser/byte-string-literals.rs create mode 100644 tests/ui/parser/byte-string-literals.stderr create mode 100644 tests/ui/parser/can-begin-expr-check.rs create mode 100644 tests/ui/parser/can-begin-expr-check.stderr create mode 100644 tests/ui/parser/chained-comparison-suggestion.rs create mode 100644 tests/ui/parser/chained-comparison-suggestion.stderr create mode 100644 tests/ui/parser/char/whitespace-character-literal.rs create mode 100644 tests/ui/parser/char/whitespace-character-literal.stderr create mode 100644 tests/ui/parser/circular_modules_hello.rs create mode 100644 tests/ui/parser/circular_modules_main.rs create mode 100644 tests/ui/parser/circular_modules_main.stderr create mode 100644 tests/ui/parser/class-implements-bad-trait.rs create mode 100644 tests/ui/parser/class-implements-bad-trait.stderr create mode 100644 tests/ui/parser/closure-return-syntax.rs create mode 100644 tests/ui/parser/closure-return-syntax.stderr create mode 100644 tests/ui/parser/column-offset-1-based.rs create mode 100644 tests/ui/parser/column-offset-1-based.stderr create mode 100644 tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs create mode 100644 tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr create mode 100644 tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs create mode 100644 tests/ui/parser/constraints-before-generic-args-syntactic-pass.stderr create mode 100644 tests/ui/parser/default-on-wrong-item-kind.rs create mode 100644 tests/ui/parser/default-on-wrong-item-kind.stderr create mode 100644 tests/ui/parser/default-unmatched-assoc.rs create mode 100644 tests/ui/parser/default-unmatched-assoc.stderr create mode 100644 tests/ui/parser/default-unmatched-extern.rs create mode 100644 tests/ui/parser/default-unmatched-extern.stderr create mode 100644 tests/ui/parser/default-unmatched.rs create mode 100644 tests/ui/parser/default-unmatched.stderr create mode 100644 tests/ui/parser/default.rs create mode 100644 tests/ui/parser/default.stderr create mode 100644 tests/ui/parser/diff-markers/enum-2.rs create mode 100644 tests/ui/parser/diff-markers/enum-2.stderr create mode 100644 tests/ui/parser/diff-markers/enum.rs create mode 100644 tests/ui/parser/diff-markers/enum.stderr create mode 100644 tests/ui/parser/diff-markers/fn-arg.rs create mode 100644 tests/ui/parser/diff-markers/fn-arg.stderr create mode 100644 tests/ui/parser/diff-markers/item-with-attr.rs create mode 100644 tests/ui/parser/diff-markers/item-with-attr.stderr create mode 100644 tests/ui/parser/diff-markers/item.rs create mode 100644 tests/ui/parser/diff-markers/item.stderr create mode 100644 tests/ui/parser/diff-markers/statement.rs create mode 100644 tests/ui/parser/diff-markers/statement.stderr create mode 100644 tests/ui/parser/diff-markers/struct-expr.rs create mode 100644 tests/ui/parser/diff-markers/struct-expr.stderr create mode 100644 tests/ui/parser/diff-markers/struct.rs create mode 100644 tests/ui/parser/diff-markers/struct.stderr create mode 100644 tests/ui/parser/diff-markers/trait-item.rs create mode 100644 tests/ui/parser/diff-markers/trait-item.stderr create mode 100644 tests/ui/parser/diff-markers/tuple-struct.rs create mode 100644 tests/ui/parser/diff-markers/tuple-struct.stderr create mode 100644 tests/ui/parser/diff-markers/use-statement.rs create mode 100644 tests/ui/parser/diff-markers/use-statement.stderr create mode 100644 tests/ui/parser/do-catch-suggests-try.rs create mode 100644 tests/ui/parser/do-catch-suggests-try.stderr create mode 100644 tests/ui/parser/do-not-suggest-semicolon-before-array.rs create mode 100644 tests/ui/parser/do-not-suggest-semicolon-before-array.stderr create mode 100644 tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs create mode 100644 tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr create mode 100644 tests/ui/parser/doc-after-struct-field.rs create mode 100644 tests/ui/parser/doc-after-struct-field.stderr create mode 100644 tests/ui/parser/doc-before-attr.rs create mode 100644 tests/ui/parser/doc-before-attr.stderr create mode 100644 tests/ui/parser/doc-before-eof.rs create mode 100644 tests/ui/parser/doc-before-eof.stderr create mode 100644 tests/ui/parser/doc-before-extern-rbrace.rs create mode 100644 tests/ui/parser/doc-before-extern-rbrace.stderr create mode 100644 tests/ui/parser/doc-before-fn-rbrace.rs create mode 100644 tests/ui/parser/doc-before-fn-rbrace.stderr create mode 100644 tests/ui/parser/doc-before-identifier.rs create mode 100644 tests/ui/parser/doc-before-identifier.stderr create mode 100644 tests/ui/parser/doc-before-mod-rbrace.rs create mode 100644 tests/ui/parser/doc-before-mod-rbrace.stderr create mode 100644 tests/ui/parser/doc-before-rbrace.rs create mode 100644 tests/ui/parser/doc-before-rbrace.stderr create mode 100644 tests/ui/parser/doc-before-semi.rs create mode 100644 tests/ui/parser/doc-before-semi.stderr create mode 100644 tests/ui/parser/doc-before-struct-rbrace-1.rs create mode 100644 tests/ui/parser/doc-before-struct-rbrace-1.stderr create mode 100644 tests/ui/parser/doc-before-struct-rbrace-2.rs create mode 100644 tests/ui/parser/doc-before-struct-rbrace-2.stderr create mode 100644 tests/ui/parser/doc-comment-in-if-statement.rs create mode 100644 tests/ui/parser/doc-comment-in-if-statement.stderr create mode 100644 tests/ui/parser/doc-comment-in-stmt.rs create mode 100644 tests/ui/parser/doc-comment-in-stmt.stderr create mode 100644 tests/ui/parser/doc-inside-trait-item.rs create mode 100644 tests/ui/parser/doc-inside-trait-item.stderr create mode 100644 tests/ui/parser/dotdotdot-expr.rs create mode 100644 tests/ui/parser/dotdotdot-expr.stderr create mode 100644 tests/ui/parser/double-pointer.rs create mode 100644 tests/ui/parser/double-pointer.stderr create mode 100644 tests/ui/parser/duplicate-visibility.rs create mode 100644 tests/ui/parser/duplicate-visibility.stderr create mode 100644 tests/ui/parser/duplicate-where-clauses.rs create mode 100644 tests/ui/parser/duplicate-where-clauses.stderr create mode 100644 tests/ui/parser/dyn-trait-compatibility.rs create mode 100644 tests/ui/parser/dyn-trait-compatibility.stderr create mode 100644 tests/ui/parser/else-no-if.rs create mode 100644 tests/ui/parser/else-no-if.stderr create mode 100644 tests/ui/parser/emoji-identifiers.rs create mode 100644 tests/ui/parser/emoji-identifiers.stderr create mode 100644 tests/ui/parser/empty-impl-semicolon.rs create mode 100644 tests/ui/parser/empty-impl-semicolon.stderr create mode 100644 tests/ui/parser/expr-as-stmt-2.rs create mode 100644 tests/ui/parser/expr-as-stmt-2.stderr create mode 100644 tests/ui/parser/expr-as-stmt.fixed create mode 100644 tests/ui/parser/expr-as-stmt.rs create mode 100644 tests/ui/parser/expr-as-stmt.stderr create mode 100644 tests/ui/parser/extern-abi-from-mac-literal-frag.rs create mode 100644 tests/ui/parser/extern-abi-raw-strings.rs create mode 100644 tests/ui/parser/extern-abi-string-escaping.rs create mode 100644 tests/ui/parser/extern-abi-syntactic.rs create mode 100644 tests/ui/parser/extern-crate-async.rs create mode 100644 tests/ui/parser/extern-crate-unexpected-token.rs create mode 100644 tests/ui/parser/extern-crate-unexpected-token.stderr create mode 100644 tests/ui/parser/extern-expected-fn-or-brace.rs create mode 100644 tests/ui/parser/extern-expected-fn-or-brace.stderr create mode 100644 tests/ui/parser/extern-foreign-crate.rs create mode 100644 tests/ui/parser/extern-foreign-crate.stderr create mode 100644 tests/ui/parser/extern-no-fn.rs create mode 100644 tests/ui/parser/extern-no-fn.stderr create mode 100644 tests/ui/parser/float-field-interpolated.rs create mode 100644 tests/ui/parser/float-field-interpolated.stderr create mode 100644 tests/ui/parser/float-field.rs create mode 100644 tests/ui/parser/float-field.stderr create mode 100644 tests/ui/parser/float-literals.rs create mode 100644 tests/ui/parser/fn-arg-doc-comment.rs create mode 100644 tests/ui/parser/fn-arg-doc-comment.stderr create mode 100644 tests/ui/parser/fn-body-eq-expr-semi.rs create mode 100644 tests/ui/parser/fn-body-eq-expr-semi.stderr create mode 100644 tests/ui/parser/fn-body-optional-semantic-fail.rs create mode 100644 tests/ui/parser/fn-body-optional-semantic-fail.stderr create mode 100644 tests/ui/parser/fn-body-optional-syntactic-pass.rs create mode 100644 tests/ui/parser/fn-colon-return-type.rs create mode 100644 tests/ui/parser/fn-colon-return-type.stderr create mode 100644 tests/ui/parser/fn-defined-using-def.rs create mode 100644 tests/ui/parser/fn-defined-using-def.stderr create mode 100644 tests/ui/parser/fn-defined-using-fun.rs create mode 100644 tests/ui/parser/fn-defined-using-fun.stderr create mode 100644 tests/ui/parser/fn-defined-using-func.rs create mode 100644 tests/ui/parser/fn-defined-using-func.stderr create mode 100644 tests/ui/parser/fn-defined-using-function.rs create mode 100644 tests/ui/parser/fn-defined-using-function.stderr create mode 100644 tests/ui/parser/fn-field-parse-error-ice.rs create mode 100644 tests/ui/parser/fn-field-parse-error-ice.stderr create mode 100644 tests/ui/parser/fn-header-semantic-fail.rs create mode 100644 tests/ui/parser/fn-header-semantic-fail.stderr create mode 100644 tests/ui/parser/fn-header-syntactic-pass.rs create mode 100644 tests/ui/parser/fn-returns-fn-pointer.rs create mode 100644 tests/ui/parser/foreign-const-semantic-fail.rs create mode 100644 tests/ui/parser/foreign-const-semantic-fail.stderr create mode 100644 tests/ui/parser/foreign-const-syntactic-fail.rs create mode 100644 tests/ui/parser/foreign-const-syntactic-fail.stderr create mode 100644 tests/ui/parser/foreign-static-semantic-fail.rs create mode 100644 tests/ui/parser/foreign-static-semantic-fail.stderr create mode 100644 tests/ui/parser/foreign-static-syntactic-pass.rs create mode 100644 tests/ui/parser/foreign-ty-semantic-fail.rs create mode 100644 tests/ui/parser/foreign-ty-semantic-fail.stderr create mode 100644 tests/ui/parser/foreign-ty-syntactic-pass.rs create mode 100644 tests/ui/parser/if-block-unreachable-expr.rs create mode 100644 tests/ui/parser/if-in-in.fixed create mode 100644 tests/ui/parser/if-in-in.rs create mode 100644 tests/ui/parser/if-in-in.stderr create mode 100644 tests/ui/parser/impl-item-const-pass.rs create mode 100644 tests/ui/parser/impl-item-const-semantic-fail.rs create mode 100644 tests/ui/parser/impl-item-const-semantic-fail.stderr create mode 100644 tests/ui/parser/impl-item-fn-no-body-pass.rs create mode 100644 tests/ui/parser/impl-item-fn-no-body-semantic-fail.rs create mode 100644 tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr create mode 100644 tests/ui/parser/impl-item-type-no-body-pass.rs create mode 100644 tests/ui/parser/impl-item-type-no-body-semantic-fail.rs create mode 100644 tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr create mode 100644 tests/ui/parser/impl-parsing.rs create mode 100644 tests/ui/parser/impl-parsing.stderr create mode 100644 tests/ui/parser/impl-qpath.rs create mode 100644 tests/ui/parser/import-from-path.rs create mode 100644 tests/ui/parser/import-from-path.stderr create mode 100644 tests/ui/parser/import-from-rename.rs create mode 100644 tests/ui/parser/import-from-rename.stderr create mode 100644 tests/ui/parser/import-glob-path.rs create mode 100644 tests/ui/parser/import-glob-path.stderr create mode 100644 tests/ui/parser/import-glob-rename.rs create mode 100644 tests/ui/parser/import-glob-rename.stderr create mode 100644 tests/ui/parser/increment-autofix-2.fixed create mode 100644 tests/ui/parser/increment-autofix-2.rs create mode 100644 tests/ui/parser/increment-autofix-2.stderr create mode 100644 tests/ui/parser/increment-autofix.fixed create mode 100644 tests/ui/parser/increment-autofix.rs create mode 100644 tests/ui/parser/increment-autofix.stderr create mode 100644 tests/ui/parser/inner-attr-after-doc-comment.rs create mode 100644 tests/ui/parser/inner-attr-after-doc-comment.stderr create mode 100644 tests/ui/parser/inner-attr-in-trait-def.rs create mode 100644 tests/ui/parser/inner-attr.rs create mode 100644 tests/ui/parser/inner-attr.stderr create mode 100644 tests/ui/parser/int-literal-too-large-span.rs create mode 100644 tests/ui/parser/int-literal-too-large-span.stderr create mode 100644 tests/ui/parser/intersection-patterns-1.fixed create mode 100644 tests/ui/parser/intersection-patterns-1.rs create mode 100644 tests/ui/parser/intersection-patterns-1.stderr create mode 100644 tests/ui/parser/intersection-patterns-2.rs create mode 100644 tests/ui/parser/intersection-patterns-2.stderr create mode 100644 tests/ui/parser/inverted-parameters.rs create mode 100644 tests/ui/parser/inverted-parameters.stderr create mode 100644 tests/ui/parser/issue-100197-mut-let.fixed create mode 100644 tests/ui/parser/issue-100197-mut-let.rs create mode 100644 tests/ui/parser/issue-100197-mut-let.stderr create mode 100644 tests/ui/parser/issue-101477-enum.fixed create mode 100644 tests/ui/parser/issue-101477-enum.rs create mode 100644 tests/ui/parser/issue-101477-enum.stderr create mode 100644 tests/ui/parser/issue-101477-let.fixed create mode 100644 tests/ui/parser/issue-101477-let.rs create mode 100644 tests/ui/parser/issue-101477-let.stderr create mode 100644 tests/ui/parser/issue-102806.rs create mode 100644 tests/ui/parser/issue-102806.stderr create mode 100644 tests/ui/parser/issue-103143.rs create mode 100644 tests/ui/parser/issue-103143.stderr create mode 100644 tests/ui/parser/issue-103381.fixed create mode 100644 tests/ui/parser/issue-103381.rs create mode 100644 tests/ui/parser/issue-103381.stderr create mode 100644 tests/ui/parser/issue-103425.rs create mode 100644 tests/ui/parser/issue-103425.stderr create mode 100644 tests/ui/parser/issue-103451.rs create mode 100644 tests/ui/parser/issue-103451.stderr create mode 100644 tests/ui/parser/issue-103748-ICE-wrong-braces.rs create mode 100644 tests/ui/parser/issue-103748-ICE-wrong-braces.stderr create mode 100644 tests/ui/parser/issue-103869.rs create mode 100644 tests/ui/parser/issue-103869.stderr create mode 100644 tests/ui/parser/issue-104620.rs create mode 100644 tests/ui/parser/issue-104620.stderr create mode 100644 tests/ui/parser/issue-104867-inc-dec-2.rs create mode 100644 tests/ui/parser/issue-104867-inc-dec-2.stderr create mode 100644 tests/ui/parser/issue-104867-inc-dec.rs create mode 100644 tests/ui/parser/issue-104867-inc-dec.stderr create mode 100644 tests/ui/parser/issue-105366.fixed create mode 100644 tests/ui/parser/issue-105366.rs create mode 100644 tests/ui/parser/issue-105366.stderr create mode 100644 tests/ui/parser/issue-105634.rs create mode 100644 tests/ui/parser/issue-17718-parse-const.rs create mode 100644 tests/ui/parser/issue-39616.rs create mode 100644 tests/ui/parser/issue-39616.stderr create mode 100644 tests/ui/parser/issue-49257.rs create mode 100644 tests/ui/parser/issue-49257.stderr create mode 100644 tests/ui/parser/issue-61858.rs create mode 100644 tests/ui/parser/issue-61858.stderr create mode 100644 tests/ui/parser/issue-68091-unicode-ident-after-if.rs create mode 100644 tests/ui/parser/issue-68091-unicode-ident-after-if.stderr create mode 100644 tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.rs create mode 100644 tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.stderr create mode 100644 tests/ui/parser/issue-81804.rs create mode 100644 tests/ui/parser/issue-81804.stderr create mode 100644 tests/ui/parser/issue-81827.rs create mode 100644 tests/ui/parser/issue-81827.stderr create mode 100644 tests/ui/parser/issue-87694-duplicated-pub.rs create mode 100644 tests/ui/parser/issue-87694-duplicated-pub.stderr create mode 100644 tests/ui/parser/issue-87694-misplaced-pub.rs create mode 100644 tests/ui/parser/issue-87694-misplaced-pub.stderr create mode 100644 tests/ui/parser/issue-90728.rs create mode 100644 tests/ui/parser/issue-90728.stderr create mode 100644 tests/ui/parser/issue-91421.rs create mode 100644 tests/ui/parser/issue-91421.stderr create mode 100644 tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.fixed create mode 100644 tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.rs create mode 100644 tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.stderr create mode 100644 tests/ui/parser/issue-99910-const-let-mutually-exclusive.fixed create mode 100644 tests/ui/parser/issue-99910-const-let-mutually-exclusive.rs create mode 100644 tests/ui/parser/issue-99910-const-let-mutually-exclusive.stderr create mode 100644 tests/ui/parser/issues/auxiliary/issue-21146-inc.rs create mode 100644 tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs create mode 100644 tests/ui/parser/issues/auxiliary/issue-94340-inc.rs create mode 100644 tests/ui/parser/issues/issue-101540.rs create mode 100644 tests/ui/parser/issues/issue-101540.stderr create mode 100644 tests/ui/parser/issues/issue-102182-impl-trait-recover.rs create mode 100644 tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr create mode 100644 tests/ui/parser/issues/issue-10392-2.fixed create mode 100644 tests/ui/parser/issues/issue-10392-2.rs create mode 100644 tests/ui/parser/issues/issue-10392-2.stderr create mode 100644 tests/ui/parser/issues/issue-10392.rs create mode 100644 tests/ui/parser/issues/issue-10392.stderr create mode 100644 tests/ui/parser/issues/issue-104088.rs create mode 100644 tests/ui/parser/issues/issue-104088.stderr create mode 100644 tests/ui/parser/issues/issue-10636-1.rs create mode 100644 tests/ui/parser/issues/issue-10636-1.stderr create mode 100644 tests/ui/parser/issues/issue-10636-2.rs create mode 100644 tests/ui/parser/issues/issue-10636-2.stderr create mode 100644 tests/ui/parser/issues/issue-13483.rs create mode 100644 tests/ui/parser/issues/issue-13483.stderr create mode 100644 tests/ui/parser/issues/issue-14303-fncall.full.stderr create mode 100644 tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr create mode 100644 tests/ui/parser/issues/issue-14303-fncall.rs create mode 100644 tests/ui/parser/issues/issue-14303.rs create mode 100644 tests/ui/parser/issues/issue-14303.stderr create mode 100644 tests/ui/parser/issues/issue-15914.rs create mode 100644 tests/ui/parser/issues/issue-15914.stderr create mode 100644 tests/ui/parser/issues/issue-15980.rs create mode 100644 tests/ui/parser/issues/issue-15980.stderr create mode 100644 tests/ui/parser/issues/issue-1655.rs create mode 100644 tests/ui/parser/issues/issue-1655.stderr create mode 100644 tests/ui/parser/issues/issue-17718-const-mut.rs create mode 100644 tests/ui/parser/issues/issue-17718-const-mut.stderr create mode 100644 tests/ui/parser/issues/issue-17904-2.rs create mode 100644 tests/ui/parser/issues/issue-17904-2.stderr create mode 100644 tests/ui/parser/issues/issue-17904.rs create mode 100644 tests/ui/parser/issues/issue-17904.stderr create mode 100644 tests/ui/parser/issues/issue-1802-1.rs create mode 100644 tests/ui/parser/issues/issue-1802-1.stderr create mode 100644 tests/ui/parser/issues/issue-1802-2.rs create mode 100644 tests/ui/parser/issues/issue-1802-2.stderr create mode 100644 tests/ui/parser/issues/issue-19096.rs create mode 100644 tests/ui/parser/issues/issue-19096.stderr create mode 100644 tests/ui/parser/issues/issue-19398.rs create mode 100644 tests/ui/parser/issues/issue-19398.stderr create mode 100644 tests/ui/parser/issues/issue-20616-1.rs create mode 100644 tests/ui/parser/issues/issue-20616-1.stderr create mode 100644 tests/ui/parser/issues/issue-20616-2.rs create mode 100644 tests/ui/parser/issues/issue-20616-2.stderr create mode 100644 tests/ui/parser/issues/issue-20616-3.rs create mode 100644 tests/ui/parser/issues/issue-20616-3.stderr create mode 100644 tests/ui/parser/issues/issue-20616-4.rs create mode 100644 tests/ui/parser/issues/issue-20616-4.stderr create mode 100644 tests/ui/parser/issues/issue-20616-5.rs create mode 100644 tests/ui/parser/issues/issue-20616-5.stderr create mode 100644 tests/ui/parser/issues/issue-20616-6.rs create mode 100644 tests/ui/parser/issues/issue-20616-6.stderr create mode 100644 tests/ui/parser/issues/issue-20616-7.rs create mode 100644 tests/ui/parser/issues/issue-20616-7.stderr create mode 100644 tests/ui/parser/issues/issue-20616-8.rs create mode 100644 tests/ui/parser/issues/issue-20616-8.stderr create mode 100644 tests/ui/parser/issues/issue-20616-9.rs create mode 100644 tests/ui/parser/issues/issue-20616-9.stderr create mode 100644 tests/ui/parser/issues/issue-20711-2.rs create mode 100644 tests/ui/parser/issues/issue-20711-2.stderr create mode 100644 tests/ui/parser/issues/issue-20711.rs create mode 100644 tests/ui/parser/issues/issue-20711.stderr create mode 100644 tests/ui/parser/issues/issue-21146.rs create mode 100644 tests/ui/parser/issues/issue-21146.stderr create mode 100644 tests/ui/parser/issues/issue-21153.rs create mode 100644 tests/ui/parser/issues/issue-21153.stderr create mode 100644 tests/ui/parser/issues/issue-21475.rs create mode 100644 tests/ui/parser/issues/issue-22647.rs create mode 100644 tests/ui/parser/issues/issue-22647.stderr create mode 100644 tests/ui/parser/issues/issue-22712.rs create mode 100644 tests/ui/parser/issues/issue-22712.stderr create mode 100644 tests/ui/parser/issues/issue-2354-1.rs create mode 100644 tests/ui/parser/issues/issue-2354-1.stderr create mode 100644 tests/ui/parser/issues/issue-2354.rs create mode 100644 tests/ui/parser/issues/issue-2354.stderr create mode 100644 tests/ui/parser/issues/issue-23620-invalid-escapes.rs create mode 100644 tests/ui/parser/issues/issue-23620-invalid-escapes.stderr create mode 100644 tests/ui/parser/issues/issue-24197.rs create mode 100644 tests/ui/parser/issues/issue-24197.stderr create mode 100644 tests/ui/parser/issues/issue-24375.rs create mode 100644 tests/ui/parser/issues/issue-24375.stderr create mode 100644 tests/ui/parser/issues/issue-24780.rs create mode 100644 tests/ui/parser/issues/issue-24780.stderr create mode 100644 tests/ui/parser/issues/issue-27255.rs create mode 100644 tests/ui/parser/issues/issue-27255.stderr create mode 100644 tests/ui/parser/issues/issue-30318.fixed create mode 100644 tests/ui/parser/issues/issue-30318.rs create mode 100644 tests/ui/parser/issues/issue-30318.stderr create mode 100644 tests/ui/parser/issues/issue-3036.fixed create mode 100644 tests/ui/parser/issues/issue-3036.rs create mode 100644 tests/ui/parser/issues/issue-3036.stderr create mode 100644 tests/ui/parser/issues/issue-31804.rs create mode 100644 tests/ui/parser/issues/issue-31804.stderr create mode 100644 tests/ui/parser/issues/issue-32214.rs create mode 100644 tests/ui/parser/issues/issue-32214.stderr create mode 100644 tests/ui/parser/issues/issue-32446.rs create mode 100644 tests/ui/parser/issues/issue-32446.stderr create mode 100644 tests/ui/parser/issues/issue-32501.rs create mode 100644 tests/ui/parser/issues/issue-32501.stderr create mode 100644 tests/ui/parser/issues/issue-32505.rs create mode 100644 tests/ui/parser/issues/issue-32505.stderr create mode 100644 tests/ui/parser/issues/issue-33262.rs create mode 100644 tests/ui/parser/issues/issue-33262.stderr create mode 100644 tests/ui/parser/issues/issue-33413.rs create mode 100644 tests/ui/parser/issues/issue-33413.stderr create mode 100644 tests/ui/parser/issues/issue-33418.fixed create mode 100644 tests/ui/parser/issues/issue-33418.rs create mode 100644 tests/ui/parser/issues/issue-33418.stderr create mode 100644 tests/ui/parser/issues/issue-33455.rs create mode 100644 tests/ui/parser/issues/issue-33455.stderr create mode 100644 tests/ui/parser/issues/issue-34222-1.rs create mode 100644 tests/ui/parser/issues/issue-34222-1.stderr create mode 100644 tests/ui/parser/issues/issue-34255-1.rs create mode 100644 tests/ui/parser/issues/issue-34255-1.stderr create mode 100644 tests/ui/parser/issues/issue-35813-postfix-after-cast.rs create mode 100644 tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr create mode 100644 tests/ui/parser/issues/issue-41155.rs create mode 100644 tests/ui/parser/issues/issue-41155.stderr create mode 100644 tests/ui/parser/issues/issue-43196.rs create mode 100644 tests/ui/parser/issues/issue-43196.stderr create mode 100644 tests/ui/parser/issues/issue-43692.rs create mode 100644 tests/ui/parser/issues/issue-43692.stderr create mode 100644 tests/ui/parser/issues/issue-44021.rs create mode 100644 tests/ui/parser/issues/issue-44021.stderr create mode 100644 tests/ui/parser/issues/issue-44406.rs create mode 100644 tests/ui/parser/issues/issue-44406.stderr create mode 100644 tests/ui/parser/issues/issue-45296.rs create mode 100644 tests/ui/parser/issues/issue-45296.stderr create mode 100644 tests/ui/parser/issues/issue-46186.fixed create mode 100644 tests/ui/parser/issues/issue-46186.rs create mode 100644 tests/ui/parser/issues/issue-46186.stderr create mode 100644 tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs create mode 100644 tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr create mode 100644 tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs create mode 100644 tests/ui/parser/issues/issue-48508-aux.rs create mode 100644 tests/ui/parser/issues/issue-48508.rs create mode 100644 tests/ui/parser/issues/issue-48636.fixed create mode 100644 tests/ui/parser/issues/issue-48636.rs create mode 100644 tests/ui/parser/issues/issue-48636.stderr create mode 100644 tests/ui/parser/issues/issue-49040.rs create mode 100644 tests/ui/parser/issues/issue-49040.stderr create mode 100644 tests/ui/parser/issues/issue-51602.rs create mode 100644 tests/ui/parser/issues/issue-51602.stderr create mode 100644 tests/ui/parser/issues/issue-52496.rs create mode 100644 tests/ui/parser/issues/issue-52496.stderr create mode 100644 tests/ui/parser/issues/issue-54521-1.rs create mode 100644 tests/ui/parser/issues/issue-54521-2.fixed create mode 100644 tests/ui/parser/issues/issue-54521-2.rs create mode 100644 tests/ui/parser/issues/issue-54521-2.stderr create mode 100644 tests/ui/parser/issues/issue-54521-3.fixed create mode 100644 tests/ui/parser/issues/issue-54521-3.rs create mode 100644 tests/ui/parser/issues/issue-54521-3.stderr create mode 100644 tests/ui/parser/issues/issue-5544-a.rs create mode 100644 tests/ui/parser/issues/issue-5544-a.stderr create mode 100644 tests/ui/parser/issues/issue-5544-b.rs create mode 100644 tests/ui/parser/issues/issue-5544-b.stderr create mode 100644 tests/ui/parser/issues/issue-56031.rs create mode 100644 tests/ui/parser/issues/issue-56031.stderr create mode 100644 tests/ui/parser/issues/issue-57198.rs create mode 100644 tests/ui/parser/issues/issue-57198.stderr create mode 100644 tests/ui/parser/issues/issue-57684.fixed create mode 100644 tests/ui/parser/issues/issue-57684.rs create mode 100644 tests/ui/parser/issues/issue-57684.stderr create mode 100644 tests/ui/parser/issues/issue-57819.fixed create mode 100644 tests/ui/parser/issues/issue-57819.rs create mode 100644 tests/ui/parser/issues/issue-57819.stderr create mode 100644 tests/ui/parser/issues/issue-5806.rs create mode 100644 tests/ui/parser/issues/issue-5806.stderr create mode 100644 tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs create mode 100644 tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr create mode 100644 tests/ui/parser/issues/issue-58856-1.rs create mode 100644 tests/ui/parser/issues/issue-58856-1.stderr create mode 100644 tests/ui/parser/issues/issue-58856-2.rs create mode 100644 tests/ui/parser/issues/issue-58856-2.stderr create mode 100644 tests/ui/parser/issues/issue-59418.rs create mode 100644 tests/ui/parser/issues/issue-59418.stderr create mode 100644 tests/ui/parser/issues/issue-60075.rs create mode 100644 tests/ui/parser/issues/issue-60075.stderr create mode 100644 tests/ui/parser/issues/issue-62524.rs create mode 100644 tests/ui/parser/issues/issue-62524.stderr create mode 100644 tests/ui/parser/issues/issue-62546.rs create mode 100644 tests/ui/parser/issues/issue-62546.stderr create mode 100644 tests/ui/parser/issues/issue-62554.rs create mode 100644 tests/ui/parser/issues/issue-62554.stderr create mode 100644 tests/ui/parser/issues/issue-62660.rs create mode 100644 tests/ui/parser/issues/issue-62660.stderr create mode 100644 tests/ui/parser/issues/issue-62881.rs create mode 100644 tests/ui/parser/issues/issue-62881.stderr create mode 100644 tests/ui/parser/issues/issue-62894.rs create mode 100644 tests/ui/parser/issues/issue-62894.stderr create mode 100644 tests/ui/parser/issues/issue-62895.rs create mode 100644 tests/ui/parser/issues/issue-62895.stderr create mode 100644 tests/ui/parser/issues/issue-62913.rs create mode 100644 tests/ui/parser/issues/issue-62913.stderr create mode 100644 tests/ui/parser/issues/issue-62973.rs create mode 100644 tests/ui/parser/issues/issue-62973.stderr create mode 100644 tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs create mode 100644 tests/ui/parser/issues/issue-63116.rs create mode 100644 tests/ui/parser/issues/issue-63116.stderr create mode 100644 tests/ui/parser/issues/issue-63135.rs create mode 100644 tests/ui/parser/issues/issue-63135.stderr create mode 100644 tests/ui/parser/issues/issue-64732.rs create mode 100644 tests/ui/parser/issues/issue-64732.stderr create mode 100644 tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs create mode 100644 tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs create mode 100644 tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs create mode 100644 tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr create mode 100644 tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs create mode 100644 tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.stderr create mode 100644 tests/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs create mode 100644 tests/ui/parser/issues/issue-6610.rs create mode 100644 tests/ui/parser/issues/issue-6610.stderr create mode 100644 tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs create mode 100644 tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr create mode 100644 tests/ui/parser/issues/issue-66473.rs create mode 100644 tests/ui/parser/issues/issue-66473.stderr create mode 100644 tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.fixed create mode 100644 tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs create mode 100644 tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.stderr create mode 100644 tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs create mode 100644 tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr create mode 100644 tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs create mode 100644 tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr create mode 100644 tests/ui/parser/issues/issue-68629.rs create mode 100644 tests/ui/parser/issues/issue-68629.stderr create mode 100644 tests/ui/parser/issues/issue-68730.rs create mode 100644 tests/ui/parser/issues/issue-68730.stderr create mode 100644 tests/ui/parser/issues/issue-68788-in-trait-item-propagation.rs create mode 100644 tests/ui/parser/issues/issue-68890-2.rs create mode 100644 tests/ui/parser/issues/issue-68890-2.stderr create mode 100644 tests/ui/parser/issues/issue-68890.rs create mode 100644 tests/ui/parser/issues/issue-68890.stderr create mode 100644 tests/ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs create mode 100644 tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs create mode 100644 tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.stderr create mode 100644 tests/ui/parser/issues/issue-70388-without-witness.fixed create mode 100644 tests/ui/parser/issues/issue-70388-without-witness.rs create mode 100644 tests/ui/parser/issues/issue-70388-without-witness.stderr create mode 100644 tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs create mode 100644 tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr create mode 100644 tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs create mode 100644 tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr create mode 100644 tests/ui/parser/issues/issue-70583-block-is-empty-1.rs create mode 100644 tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr create mode 100644 tests/ui/parser/issues/issue-70583-block-is-empty-2.rs create mode 100644 tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr create mode 100644 tests/ui/parser/issues/issue-7222.rs create mode 100644 tests/ui/parser/issues/issue-72253.rs create mode 100644 tests/ui/parser/issues/issue-72253.stderr create mode 100644 tests/ui/parser/issues/issue-72373.rs create mode 100644 tests/ui/parser/issues/issue-72373.stderr create mode 100644 tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs create mode 100644 tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr create mode 100644 tests/ui/parser/issues/issue-75599.rs create mode 100644 tests/ui/parser/issues/issue-76437-async.rs create mode 100644 tests/ui/parser/issues/issue-76437-async.stderr create mode 100644 tests/ui/parser/issues/issue-76437-const-async-unsafe.rs create mode 100644 tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr create mode 100644 tests/ui/parser/issues/issue-76437-const-async.rs create mode 100644 tests/ui/parser/issues/issue-76437-const-async.stderr create mode 100644 tests/ui/parser/issues/issue-76437-const.rs create mode 100644 tests/ui/parser/issues/issue-76437-const.stderr create mode 100644 tests/ui/parser/issues/issue-76437-pub-crate-unsafe.rs create mode 100644 tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr create mode 100644 tests/ui/parser/issues/issue-76437-unsafe.rs create mode 100644 tests/ui/parser/issues/issue-76437-unsafe.stderr create mode 100644 tests/ui/parser/issues/issue-76597.fixed create mode 100644 tests/ui/parser/issues/issue-76597.rs create mode 100644 tests/ui/parser/issues/issue-76597.stderr create mode 100644 tests/ui/parser/issues/issue-7970b.rs create mode 100644 tests/ui/parser/issues/issue-7970b.stderr create mode 100644 tests/ui/parser/issues/issue-81806.rs create mode 100644 tests/ui/parser/issues/issue-81806.stderr create mode 100644 tests/ui/parser/issues/issue-83639.rs create mode 100644 tests/ui/parser/issues/issue-83639.stderr create mode 100644 tests/ui/parser/issues/issue-84104.rs create mode 100644 tests/ui/parser/issues/issue-84104.stderr create mode 100644 tests/ui/parser/issues/issue-84117.rs create mode 100644 tests/ui/parser/issues/issue-84117.stderr create mode 100644 tests/ui/parser/issues/issue-84148-1.rs create mode 100644 tests/ui/parser/issues/issue-84148-1.stderr create mode 100644 tests/ui/parser/issues/issue-84148-2.rs create mode 100644 tests/ui/parser/issues/issue-84148-2.stderr create mode 100644 tests/ui/parser/issues/issue-8537.rs create mode 100644 tests/ui/parser/issues/issue-8537.stderr create mode 100644 tests/ui/parser/issues/issue-86895.rs create mode 100644 tests/ui/parser/issues/issue-86895.stderr create mode 100644 tests/ui/parser/issues/issue-87086-colon-path-sep.rs create mode 100644 tests/ui/parser/issues/issue-87086-colon-path-sep.stderr create mode 100644 tests/ui/parser/issues/issue-87197-missing-semicolon.fixed create mode 100644 tests/ui/parser/issues/issue-87197-missing-semicolon.rs create mode 100644 tests/ui/parser/issues/issue-87197-missing-semicolon.stderr create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs create mode 100644 tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr create mode 100644 tests/ui/parser/issues/issue-87635.rs create mode 100644 tests/ui/parser/issues/issue-87635.stderr create mode 100644 tests/ui/parser/issues/issue-87812-path.rs create mode 100644 tests/ui/parser/issues/issue-87812-path.stderr create mode 100644 tests/ui/parser/issues/issue-87812.rs create mode 100644 tests/ui/parser/issues/issue-87812.stderr create mode 100644 tests/ui/parser/issues/issue-88276-unary-plus.fixed create mode 100644 tests/ui/parser/issues/issue-88276-unary-plus.rs create mode 100644 tests/ui/parser/issues/issue-88276-unary-plus.stderr create mode 100644 tests/ui/parser/issues/issue-88583-union-as-ident.rs create mode 100644 tests/ui/parser/issues/issue-88770.rs create mode 100644 tests/ui/parser/issues/issue-88770.stderr create mode 100644 tests/ui/parser/issues/issue-88818.rs create mode 100644 tests/ui/parser/issues/issue-88818.stderr create mode 100644 tests/ui/parser/issues/issue-89388.rs create mode 100644 tests/ui/parser/issues/issue-89388.stderr create mode 100644 tests/ui/parser/issues/issue-89396.fixed create mode 100644 tests/ui/parser/issues/issue-89396.rs create mode 100644 tests/ui/parser/issues/issue-89396.stderr create mode 100644 tests/ui/parser/issues/issue-89574.rs create mode 100644 tests/ui/parser/issues/issue-89574.stderr create mode 100644 tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs create mode 100644 tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr create mode 100644 tests/ui/parser/issues/issue-90993.rs create mode 100644 tests/ui/parser/issues/issue-90993.stderr create mode 100644 tests/ui/parser/issues/issue-91461.rs create mode 100644 tests/ui/parser/issues/issue-91461.stderr create mode 100644 tests/ui/parser/issues/issue-93282.rs create mode 100644 tests/ui/parser/issues/issue-93282.stderr create mode 100644 tests/ui/parser/issues/issue-93867.rs create mode 100644 tests/ui/parser/issues/issue-93867.stderr create mode 100644 tests/ui/parser/issues/issue-94340.rs create mode 100644 tests/ui/parser/issues/issue-94340.stderr create mode 100644 tests/ui/parser/item-free-const-no-body-semantic-fail.rs create mode 100644 tests/ui/parser/item-free-const-no-body-semantic-fail.stderr create mode 100644 tests/ui/parser/item-free-const-no-body-syntactic-pass.rs create mode 100644 tests/ui/parser/item-free-static-no-body-semantic-fail.rs create mode 100644 tests/ui/parser/item-free-static-no-body-semantic-fail.stderr create mode 100644 tests/ui/parser/item-free-static-no-body-syntactic-pass.rs create mode 100644 tests/ui/parser/item-free-type-bounds-semantic-fail.rs create mode 100644 tests/ui/parser/item-free-type-bounds-semantic-fail.stderr create mode 100644 tests/ui/parser/item-free-type-bounds-syntactic-pass.rs create mode 100644 tests/ui/parser/item-kw-case-mismatch.fixed create mode 100644 tests/ui/parser/item-kw-case-mismatch.rs create mode 100644 tests/ui/parser/item-kw-case-mismatch.stderr create mode 100644 tests/ui/parser/item-needs-block.rs create mode 100644 tests/ui/parser/item-needs-block.stderr create mode 100644 tests/ui/parser/keyword-abstract.rs create mode 100644 tests/ui/parser/keyword-abstract.stderr create mode 100644 tests/ui/parser/keyword-as-as-identifier.rs create mode 100644 tests/ui/parser/keyword-as-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-box-as-identifier.rs create mode 100644 tests/ui/parser/keyword-box-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-break-as-identifier.rs create mode 100644 tests/ui/parser/keyword-break-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-const-as-identifier.rs create mode 100644 tests/ui/parser/keyword-const-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-continue-as-identifier.rs create mode 100644 tests/ui/parser/keyword-continue-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-else-as-identifier.rs create mode 100644 tests/ui/parser/keyword-else-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-enum-as-identifier.rs create mode 100644 tests/ui/parser/keyword-enum-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-final.rs create mode 100644 tests/ui/parser/keyword-final.stderr create mode 100644 tests/ui/parser/keyword-fn-as-identifier.rs create mode 100644 tests/ui/parser/keyword-fn-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-for-as-identifier.rs create mode 100644 tests/ui/parser/keyword-for-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-if-as-identifier.rs create mode 100644 tests/ui/parser/keyword-if-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-impl-as-identifier.rs create mode 100644 tests/ui/parser/keyword-impl-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-in-as-identifier.rs create mode 100644 tests/ui/parser/keyword-in-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-let-as-identifier.rs create mode 100644 tests/ui/parser/keyword-let-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-loop-as-identifier.rs create mode 100644 tests/ui/parser/keyword-loop-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-match-as-identifier.rs create mode 100644 tests/ui/parser/keyword-match-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-mod-as-identifier.rs create mode 100644 tests/ui/parser/keyword-mod-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-move-as-identifier.rs create mode 100644 tests/ui/parser/keyword-move-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-mut-as-identifier.rs create mode 100644 tests/ui/parser/keyword-mut-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-override.rs create mode 100644 tests/ui/parser/keyword-override.stderr create mode 100644 tests/ui/parser/keyword-pub-as-identifier.rs create mode 100644 tests/ui/parser/keyword-pub-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-ref-as-identifier.rs create mode 100644 tests/ui/parser/keyword-ref-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-return-as-identifier.rs create mode 100644 tests/ui/parser/keyword-return-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-static-as-identifier.rs create mode 100644 tests/ui/parser/keyword-static-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-struct-as-identifier.rs create mode 100644 tests/ui/parser/keyword-struct-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-trait-as-identifier.rs create mode 100644 tests/ui/parser/keyword-trait-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-try-as-identifier-edition2018.rs create mode 100644 tests/ui/parser/keyword-try-as-identifier-edition2018.stderr create mode 100644 tests/ui/parser/keyword-type-as-identifier.rs create mode 100644 tests/ui/parser/keyword-type-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-typeof.rs create mode 100644 tests/ui/parser/keyword-typeof.stderr create mode 100644 tests/ui/parser/keyword-unsafe-as-identifier.rs create mode 100644 tests/ui/parser/keyword-unsafe-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-use-as-identifier.rs create mode 100644 tests/ui/parser/keyword-use-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-where-as-identifier.rs create mode 100644 tests/ui/parser/keyword-where-as-identifier.stderr create mode 100644 tests/ui/parser/keyword-while-as-identifier.rs create mode 100644 tests/ui/parser/keyword-while-as-identifier.stderr create mode 100644 tests/ui/parser/keyword.rs create mode 100644 tests/ui/parser/keyword.stderr create mode 100644 tests/ui/parser/keywords-followed-by-double-colon.rs create mode 100644 tests/ui/parser/keywords-followed-by-double-colon.stderr create mode 100644 tests/ui/parser/kw-in-trait-bounds.rs create mode 100644 tests/ui/parser/kw-in-trait-bounds.stderr create mode 100644 tests/ui/parser/label-after-block-like.rs create mode 100644 tests/ui/parser/label-after-block-like.stderr create mode 100644 tests/ui/parser/label-is-actually-char.rs create mode 100644 tests/ui/parser/label-is-actually-char.stderr create mode 100644 tests/ui/parser/labeled-no-colon-expr.rs create mode 100644 tests/ui/parser/labeled-no-colon-expr.stderr create mode 100644 tests/ui/parser/let-binop.fixed create mode 100644 tests/ui/parser/let-binop.rs create mode 100644 tests/ui/parser/let-binop.stderr create mode 100644 tests/ui/parser/lifetime-in-pattern-recover.rs create mode 100644 tests/ui/parser/lifetime-in-pattern-recover.stderr create mode 100644 tests/ui/parser/lifetime-in-pattern.rs create mode 100644 tests/ui/parser/lifetime-in-pattern.stderr create mode 100644 tests/ui/parser/lifetime-semicolon.fixed create mode 100644 tests/ui/parser/lifetime-semicolon.rs create mode 100644 tests/ui/parser/lifetime-semicolon.stderr create mode 100644 tests/ui/parser/lifetime_starts_expressions.rs create mode 100644 tests/ui/parser/lifetime_starts_expressions.stderr create mode 100644 tests/ui/parser/macro-bad-delimiter-ident.rs create mode 100644 tests/ui/parser/macro-bad-delimiter-ident.stderr create mode 100644 tests/ui/parser/macro-braces-dot-question.rs create mode 100644 tests/ui/parser/macro-keyword.rs create mode 100644 tests/ui/parser/macro-keyword.stderr create mode 100644 tests/ui/parser/macro-mismatched-delim-brace-paren.rs create mode 100644 tests/ui/parser/macro-mismatched-delim-brace-paren.stderr create mode 100644 tests/ui/parser/macro-mismatched-delim-paren-brace.rs create mode 100644 tests/ui/parser/macro-mismatched-delim-paren-brace.stderr create mode 100644 tests/ui/parser/macro/bad-macro-argument.rs create mode 100644 tests/ui/parser/macro/bad-macro-argument.stderr create mode 100644 tests/ui/parser/macro/issue-33569.rs create mode 100644 tests/ui/parser/macro/issue-33569.stderr create mode 100644 tests/ui/parser/macro/issue-37113.rs create mode 100644 tests/ui/parser/macro/issue-37113.stderr create mode 100644 tests/ui/parser/macro/issue-37234.rs create mode 100644 tests/ui/parser/macro/issue-37234.stderr create mode 100644 tests/ui/parser/macro/literals-are-validated-before-expansion.rs create mode 100644 tests/ui/parser/macro/literals-are-validated-before-expansion.stderr create mode 100644 tests/ui/parser/macro/macro-doc-comments-1.rs create mode 100644 tests/ui/parser/macro/macro-doc-comments-1.stderr create mode 100644 tests/ui/parser/macro/macro-doc-comments-2.rs create mode 100644 tests/ui/parser/macro/macro-doc-comments-2.stderr create mode 100644 tests/ui/parser/macro/macro-incomplete-parse.rs create mode 100644 tests/ui/parser/macro/macro-incomplete-parse.stderr create mode 100644 tests/ui/parser/macro/macro-repeat.rs create mode 100644 tests/ui/parser/macro/macro-repeat.stderr create mode 100644 tests/ui/parser/macro/pub-item-macro.rs create mode 100644 tests/ui/parser/macro/pub-item-macro.stderr create mode 100644 tests/ui/parser/macro/trait-non-item-macros.rs create mode 100644 tests/ui/parser/macro/trait-non-item-macros.stderr create mode 100644 tests/ui/parser/macro/trait-object-macro-matcher.rs create mode 100644 tests/ui/parser/macro/trait-object-macro-matcher.stderr create mode 100644 tests/ui/parser/macros-no-semicolon-items.rs create mode 100644 tests/ui/parser/macros-no-semicolon-items.stderr create mode 100644 tests/ui/parser/macros-no-semicolon.rs create mode 100644 tests/ui/parser/macros-no-semicolon.stderr create mode 100644 tests/ui/parser/match-arm-without-braces.rs create mode 100644 tests/ui/parser/match-arm-without-braces.stderr create mode 100644 tests/ui/parser/match-arrows-block-then-binop.rs create mode 100644 tests/ui/parser/match-arrows-block-then-binop.stderr create mode 100644 tests/ui/parser/match-refactor-to-expr.fixed create mode 100644 tests/ui/parser/match-refactor-to-expr.rs create mode 100644 tests/ui/parser/match-refactor-to-expr.stderr create mode 100644 tests/ui/parser/mbe_missing_right_paren.rs create mode 100644 tests/ui/parser/mbe_missing_right_paren.stderr create mode 100644 tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs create mode 100644 tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr create mode 100644 tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs create mode 100644 tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr create mode 100644 tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs create mode 100644 tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr create mode 100644 tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs create mode 100644 tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr create mode 100644 tests/ui/parser/mismatched-delim-brace-empty-block.rs create mode 100644 tests/ui/parser/mismatched-delim-brace-empty-block.stderr create mode 100644 tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs create mode 100644 tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr create mode 100644 tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs create mode 100644 tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr create mode 100644 tests/ui/parser/missing-semicolon.rs create mode 100644 tests/ui/parser/missing-semicolon.stderr create mode 100644 tests/ui/parser/missing_right_paren.rs create mode 100644 tests/ui/parser/missing_right_paren.stderr create mode 100644 tests/ui/parser/misspelled-macro-rules.fixed create mode 100644 tests/ui/parser/misspelled-macro-rules.rs create mode 100644 tests/ui/parser/misspelled-macro-rules.stderr create mode 100644 tests/ui/parser/mod_file_not_exist.rs create mode 100644 tests/ui/parser/mod_file_not_exist.stderr create mode 100644 tests/ui/parser/mod_file_not_exist_windows.rs create mode 100644 tests/ui/parser/mod_file_not_exist_windows.stderr create mode 100644 tests/ui/parser/mod_file_with_path_attr.rs create mode 100644 tests/ui/parser/mod_file_with_path_attr.stderr create mode 100644 tests/ui/parser/multibyte-char-use-seperator-issue-80134.rs create mode 100644 tests/ui/parser/multibyte-char-use-seperator-issue-80134.stderr create mode 100644 tests/ui/parser/multiline-comment-line-tracking.rs create mode 100644 tests/ui/parser/multiline-comment-line-tracking.stderr create mode 100644 tests/ui/parser/multitrait.rs create mode 100644 tests/ui/parser/multitrait.stderr create mode 100644 tests/ui/parser/mut-patterns.rs create mode 100644 tests/ui/parser/mut-patterns.stderr create mode 100644 tests/ui/parser/nested-bad-turbofish.rs create mode 100644 tests/ui/parser/nested-bad-turbofish.stderr create mode 100644 tests/ui/parser/nested-missing-closing-angle-bracket.rs create mode 100644 tests/ui/parser/nested-missing-closing-angle-bracket.stderr create mode 100644 tests/ui/parser/new-unicode-escapes-1.rs create mode 100644 tests/ui/parser/new-unicode-escapes-1.stderr create mode 100644 tests/ui/parser/new-unicode-escapes-2.rs create mode 100644 tests/ui/parser/new-unicode-escapes-2.stderr create mode 100644 tests/ui/parser/new-unicode-escapes-3.rs create mode 100644 tests/ui/parser/new-unicode-escapes-3.stderr create mode 100644 tests/ui/parser/new-unicode-escapes-4.rs create mode 100644 tests/ui/parser/new-unicode-escapes-4.stderr create mode 100644 tests/ui/parser/no-binary-float-literal.rs create mode 100644 tests/ui/parser/no-binary-float-literal.stderr create mode 100644 tests/ui/parser/no-const-fn-in-extern-block.rs create mode 100644 tests/ui/parser/no-const-fn-in-extern-block.stderr create mode 100644 tests/ui/parser/no-hex-float-literal.rs create mode 100644 tests/ui/parser/no-hex-float-literal.stderr create mode 100644 tests/ui/parser/no-unsafe-self.rs create mode 100644 tests/ui/parser/no-unsafe-self.stderr create mode 100644 tests/ui/parser/not-a-pred.rs create mode 100644 tests/ui/parser/not-a-pred.stderr create mode 100644 tests/ui/parser/nt-parsing-has-recovery.rs create mode 100644 tests/ui/parser/nt-parsing-has-recovery.stderr create mode 100644 tests/ui/parser/numeric-lifetime.rs create mode 100644 tests/ui/parser/numeric-lifetime.stderr create mode 100644 tests/ui/parser/obsolete-syntax-impl-for-dotdot.rs create mode 100644 tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr create mode 100644 tests/ui/parser/old-suffixes-are-really-forbidden.rs create mode 100644 tests/ui/parser/old-suffixes-are-really-forbidden.stderr create mode 100644 tests/ui/parser/omitted-arg-in-item-fn.rs create mode 100644 tests/ui/parser/omitted-arg-in-item-fn.stderr create mode 100644 tests/ui/parser/operator-associativity.rs create mode 100644 tests/ui/parser/paamayim-nekudotayim.rs create mode 100644 tests/ui/parser/paamayim-nekudotayim.stderr create mode 100644 tests/ui/parser/parse-assoc-type-lt.rs create mode 100644 tests/ui/parser/parse-error-correct.rs create mode 100644 tests/ui/parser/parse-error-correct.stderr create mode 100644 tests/ui/parser/parse-panic.rs create mode 100644 tests/ui/parser/parser-recovery-1.rs create mode 100644 tests/ui/parser/parser-recovery-1.stderr create mode 100644 tests/ui/parser/parser-recovery-2.rs create mode 100644 tests/ui/parser/parser-recovery-2.stderr create mode 100644 tests/ui/parser/parser-unicode-whitespace.rs create mode 100644 tests/ui/parser/pat-lt-bracket-1.rs create mode 100644 tests/ui/parser/pat-lt-bracket-1.stderr create mode 100644 tests/ui/parser/pat-lt-bracket-2.rs create mode 100644 tests/ui/parser/pat-lt-bracket-2.stderr create mode 100644 tests/ui/parser/pat-lt-bracket-3.rs create mode 100644 tests/ui/parser/pat-lt-bracket-3.stderr create mode 100644 tests/ui/parser/pat-lt-bracket-4.rs create mode 100644 tests/ui/parser/pat-lt-bracket-4.stderr create mode 100644 tests/ui/parser/pat-lt-bracket-5.rs create mode 100644 tests/ui/parser/pat-lt-bracket-5.stderr create mode 100644 tests/ui/parser/pat-lt-bracket-6.rs create mode 100644 tests/ui/parser/pat-lt-bracket-6.stderr create mode 100644 tests/ui/parser/pat-lt-bracket-7.rs create mode 100644 tests/ui/parser/pat-lt-bracket-7.stderr create mode 100644 tests/ui/parser/pat-ranges-1.rs create mode 100644 tests/ui/parser/pat-ranges-1.stderr create mode 100644 tests/ui/parser/pat-ranges-2.rs create mode 100644 tests/ui/parser/pat-ranges-2.stderr create mode 100644 tests/ui/parser/pat-ranges-3.rs create mode 100644 tests/ui/parser/pat-ranges-3.stderr create mode 100644 tests/ui/parser/pat-ranges-4.rs create mode 100644 tests/ui/parser/pat-ranges-4.stderr create mode 100644 tests/ui/parser/pat-ref-enum.rs create mode 100644 tests/ui/parser/pat-ref-enum.stderr create mode 100644 tests/ui/parser/pat-tuple-1.rs create mode 100644 tests/ui/parser/pat-tuple-1.stderr create mode 100644 tests/ui/parser/pat-tuple-2.rs create mode 100644 tests/ui/parser/pat-tuple-3.rs create mode 100644 tests/ui/parser/pat-tuple-3.stderr create mode 100644 tests/ui/parser/pub-method-macro.rs create mode 100644 tests/ui/parser/pub-method-macro.stderr create mode 100644 tests/ui/parser/public-instead-of-pub-1.fixed create mode 100644 tests/ui/parser/public-instead-of-pub-1.rs create mode 100644 tests/ui/parser/public-instead-of-pub-1.stderr create mode 100644 tests/ui/parser/public-instead-of-pub-2.rs create mode 100644 tests/ui/parser/public-instead-of-pub-2.stderr create mode 100644 tests/ui/parser/public-instead-of-pub-3.fixed create mode 100644 tests/ui/parser/public-instead-of-pub-3.rs create mode 100644 tests/ui/parser/public-instead-of-pub-3.stderr create mode 100644 tests/ui/parser/public-instead-of-pub.fixed create mode 100644 tests/ui/parser/public-instead-of-pub.rs create mode 100644 tests/ui/parser/public-instead-of-pub.stderr create mode 100644 tests/ui/parser/qualified-path-in-turbofish.fixed create mode 100644 tests/ui/parser/qualified-path-in-turbofish.rs create mode 100644 tests/ui/parser/qualified-path-in-turbofish.stderr create mode 100644 tests/ui/parser/range-3.rs create mode 100644 tests/ui/parser/range-3.stderr create mode 100644 tests/ui/parser/range-4.rs create mode 100644 tests/ui/parser/range-4.stderr create mode 100644 tests/ui/parser/range-inclusive-extra-equals.rs create mode 100644 tests/ui/parser/range-inclusive-extra-equals.stderr create mode 100644 tests/ui/parser/range_inclusive.fixed create mode 100644 tests/ui/parser/range_inclusive.rs create mode 100644 tests/ui/parser/range_inclusive.stderr create mode 100644 tests/ui/parser/range_inclusive_dotdotdot.rs create mode 100644 tests/ui/parser/range_inclusive_dotdotdot.stderr create mode 100644 tests/ui/parser/ranges-precedence.rs create mode 100644 tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs create mode 100644 tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr create mode 100644 tests/ui/parser/raw/raw-byte-string-eof.rs create mode 100644 tests/ui/parser/raw/raw-byte-string-eof.stderr create mode 100644 tests/ui/parser/raw/raw-byte-string-literals.rs create mode 100644 tests/ui/parser/raw/raw-byte-string-literals.stderr create mode 100644 tests/ui/parser/raw/raw-literal-keywords.rs create mode 100644 tests/ui/parser/raw/raw-literal-keywords.stderr create mode 100644 tests/ui/parser/raw/raw-literal-self.rs create mode 100644 tests/ui/parser/raw/raw-literal-self.stderr create mode 100644 tests/ui/parser/raw/raw-literal-underscore.rs create mode 100644 tests/ui/parser/raw/raw-literal-underscore.stderr create mode 100644 tests/ui/parser/raw/raw-str-delim.rs create mode 100644 tests/ui/parser/raw/raw-str-delim.stderr create mode 100644 tests/ui/parser/raw/raw-str-in-macro-call.rs create mode 100644 tests/ui/parser/raw/raw-str-unbalanced.rs create mode 100644 tests/ui/parser/raw/raw-str-unbalanced.stderr create mode 100644 tests/ui/parser/raw/raw-str-unterminated.rs create mode 100644 tests/ui/parser/raw/raw-str-unterminated.stderr create mode 100644 tests/ui/parser/raw/raw-string-2.rs create mode 100644 tests/ui/parser/raw/raw-string-2.stderr create mode 100644 tests/ui/parser/raw/raw-string.rs create mode 100644 tests/ui/parser/raw/raw-string.stderr create mode 100644 tests/ui/parser/recover-assoc-const-constraint.rs create mode 100644 tests/ui/parser/recover-assoc-const-constraint.stderr create mode 100644 tests/ui/parser/recover-assoc-eq-missing-term.rs create mode 100644 tests/ui/parser/recover-assoc-eq-missing-term.stderr create mode 100644 tests/ui/parser/recover-assoc-lifetime-constraint.rs create mode 100644 tests/ui/parser/recover-assoc-lifetime-constraint.stderr create mode 100644 tests/ui/parser/recover-const-async-fn-ptr.rs create mode 100644 tests/ui/parser/recover-const-async-fn-ptr.stderr create mode 100644 tests/ui/parser/recover-enum.rs create mode 100644 tests/ui/parser/recover-enum.stderr create mode 100644 tests/ui/parser/recover-enum2.rs create mode 100644 tests/ui/parser/recover-enum2.stderr create mode 100644 tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs create mode 100644 tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr create mode 100644 tests/ui/parser/recover-field-extra-angle-brackets.rs create mode 100644 tests/ui/parser/recover-field-extra-angle-brackets.stderr create mode 100644 tests/ui/parser/recover-field-semi.rs create mode 100644 tests/ui/parser/recover-field-semi.stderr create mode 100644 tests/ui/parser/recover-fn-ptr-with-generics.rs create mode 100644 tests/ui/parser/recover-fn-ptr-with-generics.stderr create mode 100644 tests/ui/parser/recover-fn-trait-from-fn-kw.rs create mode 100644 tests/ui/parser/recover-fn-trait-from-fn-kw.stderr create mode 100644 tests/ui/parser/recover-for-loop-parens-around-head.rs create mode 100644 tests/ui/parser/recover-for-loop-parens-around-head.stderr create mode 100644 tests/ui/parser/recover-from-bad-variant.rs create mode 100644 tests/ui/parser/recover-from-bad-variant.stderr create mode 100644 tests/ui/parser/recover-from-homoglyph.rs create mode 100644 tests/ui/parser/recover-from-homoglyph.stderr create mode 100644 tests/ui/parser/recover-labeled-non-block-expr.fixed create mode 100644 tests/ui/parser/recover-labeled-non-block-expr.rs create mode 100644 tests/ui/parser/recover-labeled-non-block-expr.stderr create mode 100644 tests/ui/parser/recover-missing-semi-before-item.fixed create mode 100644 tests/ui/parser/recover-missing-semi-before-item.rs create mode 100644 tests/ui/parser/recover-missing-semi-before-item.stderr create mode 100644 tests/ui/parser/recover-missing-semi.rs create mode 100644 tests/ui/parser/recover-missing-semi.stderr create mode 100644 tests/ui/parser/recover-quantified-closure.rs create mode 100644 tests/ui/parser/recover-quantified-closure.stderr create mode 100644 tests/ui/parser/recover-range-pats.rs create mode 100644 tests/ui/parser/recover-range-pats.stderr create mode 100644 tests/ui/parser/recover-ref-dyn-mut.rs create mode 100644 tests/ui/parser/recover-ref-dyn-mut.stderr create mode 100644 tests/ui/parser/recover-struct.rs create mode 100644 tests/ui/parser/recover-struct.stderr create mode 100644 tests/ui/parser/recover-tuple-pat.rs create mode 100644 tests/ui/parser/recover-tuple-pat.stderr create mode 100644 tests/ui/parser/recover-tuple.rs create mode 100644 tests/ui/parser/recover-tuple.stderr create mode 100644 tests/ui/parser/recover-unticked-labels.fixed create mode 100644 tests/ui/parser/recover-unticked-labels.rs create mode 100644 tests/ui/parser/recover-unticked-labels.stderr create mode 100644 tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed create mode 100644 tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs create mode 100644 tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr create mode 100644 tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs create mode 100644 tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr create mode 100644 tests/ui/parser/recovered-struct-variant.rs create mode 100644 tests/ui/parser/recovered-struct-variant.stderr create mode 100644 tests/ui/parser/regions-out-of-scope-slice.rs create mode 100644 tests/ui/parser/regions-out-of-scope-slice.stderr create mode 100644 tests/ui/parser/removed-syntax-closure-lifetime.rs create mode 100644 tests/ui/parser/removed-syntax-closure-lifetime.stderr create mode 100644 tests/ui/parser/removed-syntax-enum-newtype.rs create mode 100644 tests/ui/parser/removed-syntax-enum-newtype.stderr create mode 100644 tests/ui/parser/removed-syntax-field-let-2.rs create mode 100644 tests/ui/parser/removed-syntax-field-let-2.stderr create mode 100644 tests/ui/parser/removed-syntax-field-let.rs create mode 100644 tests/ui/parser/removed-syntax-field-let.stderr create mode 100644 tests/ui/parser/removed-syntax-field-semicolon.rs create mode 100644 tests/ui/parser/removed-syntax-field-semicolon.stderr create mode 100644 tests/ui/parser/removed-syntax-fixed-vec.rs create mode 100644 tests/ui/parser/removed-syntax-fixed-vec.stderr create mode 100644 tests/ui/parser/removed-syntax-fn-sigil.rs create mode 100644 tests/ui/parser/removed-syntax-fn-sigil.stderr create mode 100644 tests/ui/parser/removed-syntax-mode.rs create mode 100644 tests/ui/parser/removed-syntax-mode.stderr create mode 100644 tests/ui/parser/removed-syntax-mut-vec-expr.rs create mode 100644 tests/ui/parser/removed-syntax-mut-vec-expr.stderr create mode 100644 tests/ui/parser/removed-syntax-mut-vec-ty.rs create mode 100644 tests/ui/parser/removed-syntax-mut-vec-ty.stderr create mode 100644 tests/ui/parser/removed-syntax-ptr-lifetime.rs create mode 100644 tests/ui/parser/removed-syntax-ptr-lifetime.stderr create mode 100644 tests/ui/parser/removed-syntax-record.rs create mode 100644 tests/ui/parser/removed-syntax-record.stderr create mode 100644 tests/ui/parser/removed-syntax-static-fn.rs create mode 100644 tests/ui/parser/removed-syntax-static-fn.stderr create mode 100644 tests/ui/parser/removed-syntax-uniq-mut-expr.rs create mode 100644 tests/ui/parser/removed-syntax-uniq-mut-expr.stderr create mode 100644 tests/ui/parser/removed-syntax-uniq-mut-ty.rs create mode 100644 tests/ui/parser/removed-syntax-uniq-mut-ty.stderr create mode 100644 tests/ui/parser/removed-syntax-with-1.rs create mode 100644 tests/ui/parser/removed-syntax-with-1.stderr create mode 100644 tests/ui/parser/removed-syntax-with-2.rs create mode 100644 tests/ui/parser/removed-syntax-with-2.stderr create mode 100644 tests/ui/parser/require-parens-for-chained-comparison.rs create mode 100644 tests/ui/parser/require-parens-for-chained-comparison.stderr create mode 100644 tests/ui/parser/self-in-function-arg.rs create mode 100644 tests/ui/parser/self-in-function-arg.stderr create mode 100644 tests/ui/parser/self-param-semantic-fail.rs create mode 100644 tests/ui/parser/self-param-semantic-fail.stderr create mode 100644 tests/ui/parser/self-param-syntactic-pass.rs create mode 100644 tests/ui/parser/semi-after-closure-in-macro.rs create mode 100644 tests/ui/parser/several-carriage-returns-in-doc-comment.rs create mode 100644 tests/ui/parser/several-carriage-returns-in-doc-comment.stderr create mode 100644 tests/ui/parser/shebang/issue-71471-ignore-tidy.rs create mode 100644 tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr create mode 100644 tests/ui/parser/shebang/multiline-attrib.rs create mode 100644 tests/ui/parser/shebang/regular-attrib.rs create mode 100644 tests/ui/parser/shebang/shebang-and-attrib.rs create mode 100644 tests/ui/parser/shebang/shebang-comment.rs create mode 100644 tests/ui/parser/shebang/shebang-doc-comment.rs create mode 100644 tests/ui/parser/shebang/shebang-doc-comment.stderr create mode 100644 tests/ui/parser/shebang/shebang-empty.rs create mode 100644 tests/ui/parser/shebang/shebang-must-start-file.rs create mode 100644 tests/ui/parser/shebang/shebang-must-start-file.stderr create mode 100644 tests/ui/parser/shebang/shebang-space.rs create mode 100644 tests/ui/parser/shebang/sneaky-attrib.rs create mode 100644 tests/ui/parser/shebang/valid-shebang.rs create mode 100644 tests/ui/parser/similar-tokens.rs create mode 100644 tests/ui/parser/similar-tokens.stderr create mode 100644 tests/ui/parser/slowparse-bstring.rs create mode 100644 tests/ui/parser/slowparse-string.rs create mode 100644 tests/ui/parser/stmt_expr_attrs_placement.rs create mode 100644 tests/ui/parser/stmt_expr_attrs_placement.stderr create mode 100644 tests/ui/parser/stripped-nested-outline-mod-pass.rs create mode 100644 tests/ui/parser/struct-default-values-and-missing-field-separator.fixed create mode 100644 tests/ui/parser/struct-default-values-and-missing-field-separator.rs create mode 100644 tests/ui/parser/struct-default-values-and-missing-field-separator.stderr create mode 100644 tests/ui/parser/struct-field-numeric-shorthand.rs create mode 100644 tests/ui/parser/struct-field-numeric-shorthand.stderr create mode 100644 tests/ui/parser/struct-filed-with-attr.fixed create mode 100644 tests/ui/parser/struct-filed-with-attr.rs create mode 100644 tests/ui/parser/struct-filed-with-attr.stderr create mode 100644 tests/ui/parser/struct-literal-in-for.rs create mode 100644 tests/ui/parser/struct-literal-in-for.stderr create mode 100644 tests/ui/parser/struct-literal-in-if.rs create mode 100644 tests/ui/parser/struct-literal-in-if.stderr create mode 100644 tests/ui/parser/struct-literal-in-match-discriminant.rs create mode 100644 tests/ui/parser/struct-literal-in-match-discriminant.stderr create mode 100644 tests/ui/parser/struct-literal-in-match-guard.rs create mode 100644 tests/ui/parser/struct-literal-in-while.rs create mode 100644 tests/ui/parser/struct-literal-in-while.stderr create mode 100644 tests/ui/parser/struct-literal-restrictions-in-lamda.rs create mode 100644 tests/ui/parser/struct-literal-restrictions-in-lamda.stderr create mode 100644 tests/ui/parser/struct-literal-variant-in-if.rs create mode 100644 tests/ui/parser/struct-literal-variant-in-if.stderr create mode 100644 tests/ui/parser/suggest-assoc-const.fixed create mode 100644 tests/ui/parser/suggest-assoc-const.rs create mode 100644 tests/ui/parser/suggest-assoc-const.stderr create mode 100644 tests/ui/parser/suggest-const-for-global-var.rs create mode 100644 tests/ui/parser/suggest-const-for-global-var.stderr create mode 100644 tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed create mode 100644 tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs create mode 100644 tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr create mode 100644 tests/ui/parser/suggest-semi-in-array.rs create mode 100644 tests/ui/parser/suggest-semi-in-array.stderr create mode 100644 tests/ui/parser/suggest-semicolon-before-array.fixed create mode 100644 tests/ui/parser/suggest-semicolon-before-array.rs create mode 100644 tests/ui/parser/suggest-semicolon-before-array.stderr create mode 100644 tests/ui/parser/trailing-carriage-return-in-string.rs create mode 100644 tests/ui/parser/trailing-carriage-return-in-string.stderr create mode 100644 tests/ui/parser/trailing-plus-in-bounds.rs create mode 100644 tests/ui/parser/trailing-question-in-macro-type.rs create mode 100644 tests/ui/parser/trailing-question-in-macro-type.stderr create mode 100644 tests/ui/parser/trailing-question-in-type.fixed create mode 100644 tests/ui/parser/trailing-question-in-type.rs create mode 100644 tests/ui/parser/trailing-question-in-type.stderr create mode 100644 tests/ui/parser/trait-bounds-not-on-impl.rs create mode 100644 tests/ui/parser/trait-bounds-not-on-impl.stderr create mode 100644 tests/ui/parser/trait-item-with-defaultness-fail-semantic.rs create mode 100644 tests/ui/parser/trait-item-with-defaultness-fail-semantic.stderr create mode 100644 tests/ui/parser/trait-item-with-defaultness-pass.rs create mode 100644 tests/ui/parser/trait-object-bad-parens.rs create mode 100644 tests/ui/parser/trait-object-bad-parens.stderr create mode 100644 tests/ui/parser/trait-object-delimiters.rs create mode 100644 tests/ui/parser/trait-object-delimiters.stderr create mode 100644 tests/ui/parser/trait-object-lifetime-parens.rs create mode 100644 tests/ui/parser/trait-object-lifetime-parens.stderr create mode 100644 tests/ui/parser/trait-object-polytrait-priority.rs create mode 100644 tests/ui/parser/trait-object-polytrait-priority.stderr create mode 100644 tests/ui/parser/trait-object-trait-parens.rs create mode 100644 tests/ui/parser/trait-object-trait-parens.stderr create mode 100644 tests/ui/parser/trait-plusequal-splitting.rs create mode 100644 tests/ui/parser/trait-pub-assoc-const.rs create mode 100644 tests/ui/parser/trait-pub-assoc-const.stderr create mode 100644 tests/ui/parser/trait-pub-assoc-ty.rs create mode 100644 tests/ui/parser/trait-pub-assoc-ty.stderr create mode 100644 tests/ui/parser/trait-pub-method.rs create mode 100644 tests/ui/parser/trait-pub-method.stderr create mode 100644 tests/ui/parser/type-alias-where-fixable.fixed create mode 100644 tests/ui/parser/type-alias-where-fixable.rs create mode 100644 tests/ui/parser/type-alias-where-fixable.stderr create mode 100644 tests/ui/parser/type-alias-where.rs create mode 100644 tests/ui/parser/type-alias-where.stderr create mode 100644 tests/ui/parser/type-parameters-in-field-exprs.rs create mode 100644 tests/ui/parser/type-parameters-in-field-exprs.stderr create mode 100644 tests/ui/parser/unbalanced-doublequote.rs create mode 100644 tests/ui/parser/unbalanced-doublequote.stderr create mode 100644 tests/ui/parser/unclosed-braces.rs create mode 100644 tests/ui/parser/unclosed-braces.stderr create mode 100644 tests/ui/parser/unclosed-delimiter-in-dep.rs create mode 100644 tests/ui/parser/unclosed-delimiter-in-dep.stderr create mode 100644 tests/ui/parser/unclosed_delim_mod.rs create mode 100644 tests/ui/parser/unclosed_delim_mod.stderr create mode 100644 tests/ui/parser/underscore-suffix-for-float.rs create mode 100644 tests/ui/parser/underscore-suffix-for-float.stderr create mode 100644 tests/ui/parser/underscore-suffix-for-string.rs create mode 100644 tests/ui/parser/underscore-suffix-for-string.stderr create mode 100644 tests/ui/parser/underscore_item_not_const.rs create mode 100644 tests/ui/parser/underscore_item_not_const.stderr create mode 100644 tests/ui/parser/unicode-character-literal.fixed create mode 100644 tests/ui/parser/unicode-character-literal.rs create mode 100644 tests/ui/parser/unicode-character-literal.stderr create mode 100644 tests/ui/parser/unicode-chars.rs create mode 100644 tests/ui/parser/unicode-chars.stderr create mode 100644 tests/ui/parser/unicode-control-codepoints.rs create mode 100644 tests/ui/parser/unicode-control-codepoints.stderr create mode 100644 tests/ui/parser/unicode-quote-chars.rs create mode 100644 tests/ui/parser/unicode-quote-chars.stderr create mode 100644 tests/ui/parser/unmatched-delimiter-at-end-of-file.rs create mode 100644 tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr create mode 100644 tests/ui/parser/unmatched-langle-1.rs create mode 100644 tests/ui/parser/unmatched-langle-1.stderr create mode 100644 tests/ui/parser/unmatched-langle-2.rs create mode 100644 tests/ui/parser/unmatched-langle-2.stderr create mode 100644 tests/ui/parser/unnecessary-let.rs create mode 100644 tests/ui/parser/unnecessary-let.stderr create mode 100644 tests/ui/parser/unsafe-foreign-mod-2.rs create mode 100644 tests/ui/parser/unsafe-foreign-mod-2.stderr create mode 100644 tests/ui/parser/unsafe-foreign-mod.rs create mode 100644 tests/ui/parser/unsafe-foreign-mod.stderr create mode 100644 tests/ui/parser/unsafe-mod.rs create mode 100644 tests/ui/parser/unsafe-mod.stderr create mode 100644 tests/ui/parser/unsized.rs create mode 100644 tests/ui/parser/unsized.stderr create mode 100644 tests/ui/parser/unsized2.rs create mode 100644 tests/ui/parser/unsized2.stderr create mode 100644 tests/ui/parser/use-as-where-use-ends-with-mod-sep.rs create mode 100644 tests/ui/parser/use-as-where-use-ends-with-mod-sep.stderr create mode 100644 tests/ui/parser/use-colon-as-mod-sep.rs create mode 100644 tests/ui/parser/use-colon-as-mod-sep.stderr create mode 100644 tests/ui/parser/use-ends-with-mod-sep.rs create mode 100644 tests/ui/parser/use-ends-with-mod-sep.stderr create mode 100644 tests/ui/parser/use-unclosed-brace.rs create mode 100644 tests/ui/parser/use-unclosed-brace.stderr create mode 100644 tests/ui/parser/utf16-be-without-bom.rs create mode 100644 tests/ui/parser/utf16-be-without-bom.stderr create mode 100644 tests/ui/parser/utf16-le-without-bom.rs create mode 100644 tests/ui/parser/utf16-le-without-bom.stderr create mode 100644 tests/ui/parser/utf8_idents-rpass.rs create mode 100644 tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs create mode 100644 tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr create mode 100644 tests/ui/parser/variadic-ffi-semantic-restrictions.rs create mode 100644 tests/ui/parser/variadic-ffi-semantic-restrictions.stderr create mode 100644 tests/ui/parser/variadic-ffi-syntactic-pass.rs create mode 100644 tests/ui/parser/virtual-structs.rs create mode 100644 tests/ui/parser/virtual-structs.stderr create mode 100644 tests/ui/parser/where-clauses-no-bounds-or-predicates.rs create mode 100644 tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr create mode 100644 tests/ui/parser/where_with_bound.rs create mode 100644 tests/ui/parser/where_with_bound.stderr create mode 100644 tests/ui/parser/while-if-let-without-body.rs create mode 100644 tests/ui/parser/while-if-let-without-body.stderr create mode 100644 tests/ui/parser/wrong-escape-of-curly-braces.rs create mode 100644 tests/ui/parser/wrong-escape-of-curly-braces.stderr create mode 100644 tests/ui/partialeq_help.rs create mode 100644 tests/ui/partialeq_help.stderr create mode 100644 tests/ui/path-lookahead.fixed create mode 100644 tests/ui/path-lookahead.rs create mode 100644 tests/ui/path-lookahead.stderr create mode 100644 tests/ui/path.rs create mode 100644 tests/ui/paths-containing-nul.rs create mode 100644 tests/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs create mode 100644 tests/ui/pattern/bindings-after-at/bind-by-copy.rs create mode 100644 tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs create mode 100644 tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr create mode 100644 tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs create mode 100644 tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs create mode 100644 tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr create mode 100644 tests/ui/pattern/bindings-after-at/box-patterns.rs create mode 100644 tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs create mode 100644 tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr create mode 100644 tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs create mode 100644 tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr create mode 100644 tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs create mode 100644 tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs create mode 100644 tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr create mode 100644 tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs create mode 100644 tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr create mode 100644 tests/ui/pattern/bindings-after-at/nested-patterns.rs create mode 100644 tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs create mode 100644 tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr create mode 100644 tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs create mode 100644 tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs create mode 100644 tests/ui/pattern/bindings-after-at/or-patterns.rs create mode 100644 tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs create mode 100644 tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr create mode 100644 tests/ui/pattern/bindings-after-at/slice-patterns.rs create mode 100644 tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs create mode 100644 tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr create mode 100644 tests/ui/pattern/for-loop-bad-item.rs create mode 100644 tests/ui/pattern/for-loop-bad-item.stderr create mode 100644 tests/ui/pattern/ignore-all-the-things.rs create mode 100644 tests/ui/pattern/integer-range-binding.rs create mode 100644 tests/ui/pattern/issue-10392.rs create mode 100644 tests/ui/pattern/issue-106552.rs create mode 100644 tests/ui/pattern/issue-106552.stderr create mode 100644 tests/ui/pattern/issue-11577.rs create mode 100644 tests/ui/pattern/issue-12582.rs create mode 100644 tests/ui/pattern/issue-14221.rs create mode 100644 tests/ui/pattern/issue-14221.stderr create mode 100644 tests/ui/pattern/issue-15080.rs create mode 100644 tests/ui/pattern/issue-17718-patterns.rs create mode 100644 tests/ui/pattern/issue-17718-patterns.stderr create mode 100644 tests/ui/pattern/issue-22546.rs create mode 100644 tests/ui/pattern/issue-27320.rs create mode 100644 tests/ui/pattern/issue-52240.rs create mode 100644 tests/ui/pattern/issue-52240.stderr create mode 100644 tests/ui/pattern/issue-6449.rs create mode 100644 tests/ui/pattern/issue-66270-pat-struct-parser-recovery.rs create mode 100644 tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr create mode 100644 tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs create mode 100644 tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr create mode 100644 tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs create mode 100644 tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr create mode 100644 tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs create mode 100644 tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr create mode 100644 tests/ui/pattern/issue-72565.rs create mode 100644 tests/ui/pattern/issue-72565.stderr create mode 100644 tests/ui/pattern/issue-72574-1.rs create mode 100644 tests/ui/pattern/issue-72574-1.stderr create mode 100644 tests/ui/pattern/issue-72574-2.rs create mode 100644 tests/ui/pattern/issue-72574-2.stderr create mode 100644 tests/ui/pattern/issue-74539.rs create mode 100644 tests/ui/pattern/issue-74539.stderr create mode 100644 tests/ui/pattern/issue-74702.rs create mode 100644 tests/ui/pattern/issue-74702.stderr create mode 100644 tests/ui/pattern/issue-74954.rs create mode 100644 tests/ui/pattern/issue-80186-mut-binding-help-suggestion.rs create mode 100644 tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr create mode 100644 tests/ui/pattern/issue-8351-1.rs create mode 100644 tests/ui/pattern/issue-8351-2.rs create mode 100644 tests/ui/pattern/issue-88074-pat-range-type-inference-err.rs create mode 100644 tests/ui/pattern/issue-88074-pat-range-type-inference-err.stderr create mode 100644 tests/ui/pattern/issue-88074-pat-range-type-inference.rs create mode 100644 tests/ui/pattern/issue-92074-macro-ice.rs create mode 100644 tests/ui/pattern/issue-92074-macro-ice.stderr create mode 100644 tests/ui/pattern/issue-95878.rs create mode 100644 tests/ui/pattern/issue-95878.stderr create mode 100644 tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs create mode 100644 tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs create mode 100644 tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr create mode 100644 tests/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs create mode 100644 tests/ui/pattern/move-ref-patterns/issue-53840.rs create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr create mode 100644 tests/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs create mode 100644 tests/ui/pattern/non-constant-in-const-path.rs create mode 100644 tests/ui/pattern/non-constant-in-const-path.stderr create mode 100644 tests/ui/pattern/non-structural-match-types.rs create mode 100644 tests/ui/pattern/non-structural-match-types.stderr create mode 100644 tests/ui/pattern/pat-shadow-in-nested-binding.rs create mode 100644 tests/ui/pattern/pat-shadow-in-nested-binding.stderr create mode 100644 tests/ui/pattern/pat-struct-field-expr-has-type.rs create mode 100644 tests/ui/pattern/pat-struct-field-expr-has-type.stderr create mode 100644 tests/ui/pattern/pat-tuple-bad-type.rs create mode 100644 tests/ui/pattern/pat-tuple-bad-type.stderr create mode 100644 tests/ui/pattern/pat-tuple-field-count-cross.rs create mode 100644 tests/ui/pattern/pat-tuple-field-count-cross.stderr create mode 100644 tests/ui/pattern/pat-tuple-overfield.rs create mode 100644 tests/ui/pattern/pat-tuple-overfield.stderr create mode 100644 tests/ui/pattern/pat-tuple-underfield.rs create mode 100644 tests/ui/pattern/pat-tuple-underfield.stderr create mode 100644 tests/ui/pattern/pat-type-err-formal-param.rs create mode 100644 tests/ui/pattern/pat-type-err-formal-param.stderr create mode 100644 tests/ui/pattern/pat-type-err-let-stmt.rs create mode 100644 tests/ui/pattern/pat-type-err-let-stmt.stderr create mode 100644 tests/ui/pattern/patkind-litrange-no-expr.rs create mode 100644 tests/ui/pattern/patkind-litrange-no-expr.stderr create mode 100644 tests/ui/pattern/pattern-binding-disambiguation.rs create mode 100644 tests/ui/pattern/pattern-binding-disambiguation.stderr create mode 100644 tests/ui/pattern/pattern-error-continue.rs create mode 100644 tests/ui/pattern/pattern-error-continue.stderr create mode 100644 tests/ui/pattern/pattern-ident-path-generics.rs create mode 100644 tests/ui/pattern/pattern-ident-path-generics.stderr create mode 100644 tests/ui/pattern/pattern-tyvar-2.rs create mode 100644 tests/ui/pattern/pattern-tyvar-2.stderr create mode 100644 tests/ui/pattern/pattern-tyvar.rs create mode 100644 tests/ui/pattern/pattern-tyvar.stderr create mode 100644 tests/ui/pattern/rest-pat-semantic-disallowed.rs create mode 100644 tests/ui/pattern/rest-pat-semantic-disallowed.stderr create mode 100644 tests/ui/pattern/rest-pat-syntactic.rs create mode 100644 tests/ui/pattern/rest-pat-syntactic.stderr create mode 100644 tests/ui/pattern/size-and-align.rs create mode 100644 tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed create mode 100644 tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.rs create mode 100644 tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr create mode 100644 tests/ui/pattern/usefulness/always-inhabited-union-ref.rs create mode 100644 tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr create mode 100644 tests/ui/pattern/usefulness/auxiliary/empty.rs create mode 100644 tests/ui/pattern/usefulness/auxiliary/hidden.rs create mode 100644 tests/ui/pattern/usefulness/auxiliary/unstable.rs create mode 100644 tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs create mode 100644 tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr create mode 100644 tests/ui/pattern/usefulness/const-pat-ice.rs create mode 100644 tests/ui/pattern/usefulness/const-private-fields.rs create mode 100644 tests/ui/pattern/usefulness/consts-opaque.rs create mode 100644 tests/ui/pattern/usefulness/consts-opaque.stderr create mode 100644 tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs create mode 100644 tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr create mode 100644 tests/ui/pattern/usefulness/doc-hidden-fields.rs create mode 100644 tests/ui/pattern/usefulness/doc-hidden-fields.stderr create mode 100644 tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs create mode 100644 tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr create mode 100644 tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr create mode 100644 tests/ui/pattern/usefulness/empty-match.normal.stderr create mode 100644 tests/ui/pattern/usefulness/empty-match.rs create mode 100644 tests/ui/pattern/usefulness/floats.rs create mode 100644 tests/ui/pattern/usefulness/floats.stderr create mode 100644 tests/ui/pattern/usefulness/guards.rs create mode 100644 tests/ui/pattern/usefulness/guards.stderr create mode 100644 tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs create mode 100644 tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr create mode 100644 tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs create mode 100644 tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr create mode 100644 tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr create mode 100644 tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr create mode 100644 tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs create mode 100644 tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs create mode 100644 tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr create mode 100644 tests/ui/pattern/usefulness/integer-ranges/reachability.rs create mode 100644 tests/ui/pattern/usefulness/integer-ranges/reachability.stderr create mode 100644 tests/ui/pattern/usefulness/irrefutable-let-patterns.rs create mode 100644 tests/ui/pattern/usefulness/irrefutable-unit.rs create mode 100644 tests/ui/pattern/usefulness/issue-12116.rs create mode 100644 tests/ui/pattern/usefulness/issue-12116.stderr create mode 100644 tests/ui/pattern/usefulness/issue-12369.rs create mode 100644 tests/ui/pattern/usefulness/issue-12369.stderr create mode 100644 tests/ui/pattern/usefulness/issue-13727.rs create mode 100644 tests/ui/pattern/usefulness/issue-13727.stderr create mode 100644 tests/ui/pattern/usefulness/issue-15129.rs create mode 100644 tests/ui/pattern/usefulness/issue-15129.stderr create mode 100644 tests/ui/pattern/usefulness/issue-2111.rs create mode 100644 tests/ui/pattern/usefulness/issue-2111.stderr create mode 100644 tests/ui/pattern/usefulness/issue-30240-b.rs create mode 100644 tests/ui/pattern/usefulness/issue-30240-b.stderr create mode 100644 tests/ui/pattern/usefulness/issue-30240-rpass.rs create mode 100644 tests/ui/pattern/usefulness/issue-30240.rs create mode 100644 tests/ui/pattern/usefulness/issue-30240.stderr create mode 100644 tests/ui/pattern/usefulness/issue-3096-1.rs create mode 100644 tests/ui/pattern/usefulness/issue-3096-1.stderr create mode 100644 tests/ui/pattern/usefulness/issue-3096-2.rs create mode 100644 tests/ui/pattern/usefulness/issue-3096-2.stderr create mode 100644 tests/ui/pattern/usefulness/issue-31221.rs create mode 100644 tests/ui/pattern/usefulness/issue-31221.stderr create mode 100644 tests/ui/pattern/usefulness/issue-31561.rs create mode 100644 tests/ui/pattern/usefulness/issue-31561.stderr create mode 100644 tests/ui/pattern/usefulness/issue-35609.rs create mode 100644 tests/ui/pattern/usefulness/issue-35609.stderr create mode 100644 tests/ui/pattern/usefulness/issue-3601.rs create mode 100644 tests/ui/pattern/usefulness/issue-3601.stderr create mode 100644 tests/ui/pattern/usefulness/issue-39362.rs create mode 100644 tests/ui/pattern/usefulness/issue-39362.stderr create mode 100644 tests/ui/pattern/usefulness/issue-40221.rs create mode 100644 tests/ui/pattern/usefulness/issue-40221.stderr create mode 100644 tests/ui/pattern/usefulness/issue-4321.rs create mode 100644 tests/ui/pattern/usefulness/issue-4321.stderr create mode 100644 tests/ui/pattern/usefulness/issue-50900.rs create mode 100644 tests/ui/pattern/usefulness/issue-50900.stderr create mode 100644 tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs create mode 100644 tests/ui/pattern/usefulness/issue-56379.rs create mode 100644 tests/ui/pattern/usefulness/issue-56379.stderr create mode 100644 tests/ui/pattern/usefulness/issue-57472.rs create mode 100644 tests/ui/pattern/usefulness/issue-57472.stderr create mode 100644 tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs create mode 100644 tests/ui/pattern/usefulness/issue-66501.rs create mode 100644 tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs create mode 100644 tests/ui/pattern/usefulness/issue-72377.rs create mode 100644 tests/ui/pattern/usefulness/issue-72377.stderr create mode 100644 tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs create mode 100644 tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs create mode 100644 tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr create mode 100644 tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs create mode 100644 tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs create mode 100644 tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs create mode 100644 tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr create mode 100644 tests/ui/pattern/usefulness/issue-88747.rs create mode 100644 tests/ui/pattern/usefulness/match-arm-statics-2.rs create mode 100644 tests/ui/pattern/usefulness/match-arm-statics-2.stderr create mode 100644 tests/ui/pattern/usefulness/match-arm-statics.rs create mode 100644 tests/ui/pattern/usefulness/match-arm-statics.stderr create mode 100644 tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs create mode 100644 tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr create mode 100644 tests/ui/pattern/usefulness/match-byte-array-patterns.rs create mode 100644 tests/ui/pattern/usefulness/match-byte-array-patterns.stderr create mode 100644 tests/ui/pattern/usefulness/match-non-exhaustive.rs create mode 100644 tests/ui/pattern/usefulness/match-non-exhaustive.stderr create mode 100644 tests/ui/pattern/usefulness/match-privately-empty.rs create mode 100644 tests/ui/pattern/usefulness/match-privately-empty.stderr create mode 100644 tests/ui/pattern/usefulness/match-ref-ice.rs create mode 100644 tests/ui/pattern/usefulness/match-ref-ice.stderr create mode 100644 tests/ui/pattern/usefulness/match-slice-patterns.rs create mode 100644 tests/ui/pattern/usefulness/match-slice-patterns.stderr create mode 100644 tests/ui/pattern/usefulness/match-vec-fixed.rs create mode 100644 tests/ui/pattern/usefulness/match-vec-fixed.stderr create mode 100644 tests/ui/pattern/usefulness/match-vec-unreachable.rs create mode 100644 tests/ui/pattern/usefulness/match-vec-unreachable.stderr create mode 100644 tests/ui/pattern/usefulness/nested-exhaustive-match.rs create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-match.rs create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-match.stderr create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs create mode 100644 tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr create mode 100644 tests/ui/pattern/usefulness/refutable-pattern-errors.rs create mode 100644 tests/ui/pattern/usefulness/refutable-pattern-errors.stderr create mode 100644 tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs create mode 100644 tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr create mode 100644 tests/ui/pattern/usefulness/slice-pattern-const-2.rs create mode 100644 tests/ui/pattern/usefulness/slice-pattern-const-2.stderr create mode 100644 tests/ui/pattern/usefulness/slice-pattern-const-3.rs create mode 100644 tests/ui/pattern/usefulness/slice-pattern-const-3.stderr create mode 100644 tests/ui/pattern/usefulness/slice-pattern-const.rs create mode 100644 tests/ui/pattern/usefulness/slice-pattern-const.stderr create mode 100644 tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs create mode 100644 tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr create mode 100644 tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs create mode 100644 tests/ui/pattern/usefulness/slice-patterns-reachability.rs create mode 100644 tests/ui/pattern/usefulness/slice-patterns-reachability.stderr create mode 100644 tests/ui/pattern/usefulness/stable-gated-fields.rs create mode 100644 tests/ui/pattern/usefulness/stable-gated-fields.stderr create mode 100644 tests/ui/pattern/usefulness/stable-gated-patterns.rs create mode 100644 tests/ui/pattern/usefulness/stable-gated-patterns.stderr create mode 100644 tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs create mode 100644 tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr create mode 100644 tests/ui/pattern/usefulness/struct-pattern-match-useless.rs create mode 100644 tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr create mode 100644 tests/ui/pattern/usefulness/top-level-alternation.rs create mode 100644 tests/ui/pattern/usefulness/top-level-alternation.stderr create mode 100644 tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs create mode 100644 tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr create mode 100644 tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs create mode 100644 tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr create mode 100644 tests/ui/pattern/usefulness/uninhabited.rs create mode 100644 tests/ui/pattern/usefulness/unstable-gated-fields.rs create mode 100644 tests/ui/pattern/usefulness/unstable-gated-fields.stderr create mode 100644 tests/ui/pattern/usefulness/unstable-gated-patterns.rs create mode 100644 tests/ui/pattern/usefulness/unstable-gated-patterns.stderr create mode 100644 tests/ui/phantom-auto-trait.rs create mode 100644 tests/ui/phantom-auto-trait.stderr create mode 100644 tests/ui/pin-macro/cant_access_internals.rs create mode 100644 tests/ui/pin-macro/cant_access_internals.stderr create mode 100644 tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs create mode 100644 tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr create mode 100644 tests/ui/point-to-type-err-cause-on-impl-trait-return-2.rs create mode 100644 tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr create mode 100644 tests/ui/polymorphization/closure_in_upvar/fn.rs create mode 100644 tests/ui/polymorphization/closure_in_upvar/fnmut.rs create mode 100644 tests/ui/polymorphization/closure_in_upvar/fnonce.rs create mode 100644 tests/ui/polymorphization/closure_in_upvar/other.rs create mode 100644 tests/ui/polymorphization/const_parameters/closures.rs create mode 100644 tests/ui/polymorphization/const_parameters/closures.stderr create mode 100644 tests/ui/polymorphization/const_parameters/functions.rs create mode 100644 tests/ui/polymorphization/const_parameters/functions.stderr create mode 100644 tests/ui/polymorphization/drop_shims/simple.rs create mode 100644 tests/ui/polymorphization/drop_shims/transitive.rs create mode 100644 tests/ui/polymorphization/generators.rs create mode 100644 tests/ui/polymorphization/generators.stderr create mode 100644 tests/ui/polymorphization/issue-74614.rs create mode 100644 tests/ui/polymorphization/issue-74636.rs create mode 100644 tests/ui/polymorphization/lifetimes.rs create mode 100644 tests/ui/polymorphization/lifetimes.stderr create mode 100644 tests/ui/polymorphization/normalized_sig_types.rs create mode 100644 tests/ui/polymorphization/predicates.rs create mode 100644 tests/ui/polymorphization/predicates.stderr create mode 100644 tests/ui/polymorphization/promoted-function-1.rs create mode 100644 tests/ui/polymorphization/promoted-function-1.stderr create mode 100644 tests/ui/polymorphization/promoted-function-2.rs create mode 100644 tests/ui/polymorphization/promoted-function-2.stderr create mode 100644 tests/ui/polymorphization/promoted-function-3.rs create mode 100644 tests/ui/polymorphization/promoted-function.rs create mode 100644 tests/ui/polymorphization/symbol-ambiguity.rs create mode 100644 tests/ui/polymorphization/too-many-generic-params.rs create mode 100644 tests/ui/polymorphization/type_parameters/closures.rs create mode 100644 tests/ui/polymorphization/type_parameters/closures.stderr create mode 100644 tests/ui/polymorphization/type_parameters/functions.rs create mode 100644 tests/ui/polymorphization/type_parameters/functions.stderr create mode 100644 tests/ui/polymorphization/unsized_cast.rs create mode 100644 tests/ui/polymorphization/unsized_cast.stderr create mode 100644 tests/ui/pptypedef.rs create mode 100644 tests/ui/pptypedef.stderr create mode 100644 tests/ui/primitive-binop-lhs-mut.rs create mode 100644 tests/ui/print-fuel/print-fuel.rs create mode 100644 tests/ui/print-fuel/print-fuel.stderr create mode 100644 tests/ui/print-stdout-eprint-stderr.rs create mode 100644 tests/ui/print_type_sizes/anonymous.rs create mode 100644 tests/ui/print_type_sizes/async.rs create mode 100644 tests/ui/print_type_sizes/async.stdout create mode 100644 tests/ui/print_type_sizes/generator.rs create mode 100644 tests/ui/print_type_sizes/generator.stdout create mode 100644 tests/ui/print_type_sizes/generator_discr_placement.rs create mode 100644 tests/ui/print_type_sizes/generator_discr_placement.stdout create mode 100644 tests/ui/print_type_sizes/generics.rs create mode 100644 tests/ui/print_type_sizes/generics.stdout create mode 100644 tests/ui/print_type_sizes/multiple_types.rs create mode 100644 tests/ui/print_type_sizes/multiple_types.stdout create mode 100644 tests/ui/print_type_sizes/niche-filling.rs create mode 100644 tests/ui/print_type_sizes/niche-filling.stdout create mode 100644 tests/ui/print_type_sizes/no_duplicates.rs create mode 100644 tests/ui/print_type_sizes/no_duplicates.stdout create mode 100644 tests/ui/print_type_sizes/packed.rs create mode 100644 tests/ui/print_type_sizes/packed.stdout create mode 100644 tests/ui/print_type_sizes/padding.rs create mode 100644 tests/ui/print_type_sizes/padding.stdout create mode 100644 tests/ui/print_type_sizes/repr-align.rs create mode 100644 tests/ui/print_type_sizes/repr-align.stdout create mode 100644 tests/ui/print_type_sizes/repr_int_c.rs create mode 100644 tests/ui/print_type_sizes/repr_int_c.stdout create mode 100644 tests/ui/print_type_sizes/uninhabited.rs create mode 100644 tests/ui/print_type_sizes/uninhabited.stdout create mode 100644 tests/ui/print_type_sizes/variants.rs create mode 100644 tests/ui/print_type_sizes/variants.stdout create mode 100644 tests/ui/print_type_sizes/zero-sized-fields.rs create mode 100644 tests/ui/print_type_sizes/zero-sized-fields.stdout create mode 100644 tests/ui/privacy/associated-item-privacy-inherent.rs create mode 100644 tests/ui/privacy/associated-item-privacy-inherent.stderr create mode 100644 tests/ui/privacy/associated-item-privacy-trait.rs create mode 100644 tests/ui/privacy/associated-item-privacy-trait.stderr create mode 100644 tests/ui/privacy/associated-item-privacy-type-binding.rs create mode 100644 tests/ui/privacy/associated-item-privacy-type-binding.stderr create mode 100644 tests/ui/privacy/auxiliary/cci_class.rs create mode 100644 tests/ui/privacy/auxiliary/cci_class_5.rs create mode 100644 tests/ui/privacy/auxiliary/ctor_aux.rs create mode 100644 tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs create mode 100644 tests/ui/privacy/auxiliary/issue-17718-const-privacy.rs create mode 100644 tests/ui/privacy/auxiliary/issue-57264-1.rs create mode 100644 tests/ui/privacy/auxiliary/issue-57264-2.rs create mode 100644 tests/ui/privacy/auxiliary/issue-75907.rs create mode 100644 tests/ui/privacy/auxiliary/issue-92755.rs create mode 100644 tests/ui/privacy/auxiliary/priv-impl-prim-ty.rs create mode 100644 tests/ui/privacy/auxiliary/privacy_reexport.rs create mode 100644 tests/ui/privacy/auxiliary/privacy_tuple_struct.rs create mode 100644 tests/ui/privacy/auxiliary/private-inferred-type.rs create mode 100644 tests/ui/privacy/auxiliary/pub_use_mods_xcrate.rs create mode 100644 tests/ui/privacy/auxiliary/pub_use_xcrate1.rs create mode 100644 tests/ui/privacy/auxiliary/pub_use_xcrate2.rs create mode 100644 tests/ui/privacy/auxiliary/reachable-unnameable-items.rs create mode 100644 tests/ui/privacy/crate-private-reexport.rs create mode 100644 tests/ui/privacy/crate-private-reexport.stderr create mode 100644 tests/ui/privacy/ctor.rs create mode 100644 tests/ui/privacy/decl-macro.rs create mode 100644 tests/ui/privacy/decl-macro.stderr create mode 100644 tests/ui/privacy/effective_visibilities.rs create mode 100644 tests/ui/privacy/effective_visibilities.stderr create mode 100644 tests/ui/privacy/effective_visibilities_glob.rs create mode 100644 tests/ui/privacy/effective_visibilities_glob.stderr create mode 100644 tests/ui/privacy/effective_visibilities_invariants.rs create mode 100644 tests/ui/privacy/effective_visibilities_invariants.stderr create mode 100644 tests/ui/privacy/export-tag-variant.rs create mode 100644 tests/ui/privacy/export-tag-variant.stderr create mode 100644 tests/ui/privacy/impl-privacy-xc-2.rs create mode 100644 tests/ui/privacy/issue-13641.rs create mode 100644 tests/ui/privacy/issue-13641.stderr create mode 100644 tests/ui/privacy/issue-17718-const-privacy.rs create mode 100644 tests/ui/privacy/issue-17718-const-privacy.stderr create mode 100644 tests/ui/privacy/issue-29161.rs create mode 100644 tests/ui/privacy/issue-29161.stderr create mode 100644 tests/ui/privacy/issue-30079.rs create mode 100644 tests/ui/privacy/issue-30079.stderr create mode 100644 tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs create mode 100644 tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr create mode 100644 tests/ui/privacy/issue-57264-1.rs create mode 100644 tests/ui/privacy/issue-57264-2.rs create mode 100644 tests/ui/privacy/issue-75062-fieldless-tuple-struct.rs create mode 100644 tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr create mode 100644 tests/ui/privacy/issue-75906.rs create mode 100644 tests/ui/privacy/issue-75906.stderr create mode 100644 tests/ui/privacy/issue-75907.rs create mode 100644 tests/ui/privacy/issue-75907.stderr create mode 100644 tests/ui/privacy/issue-75907_b.rs create mode 100644 tests/ui/privacy/issue-75907_b.stderr create mode 100644 tests/ui/privacy/issue-79593.rs create mode 100644 tests/ui/privacy/issue-79593.stderr create mode 100644 tests/ui/privacy/issue-92755.rs create mode 100644 tests/ui/privacy/legacy-ctor-visibility.rs create mode 100644 tests/ui/privacy/legacy-ctor-visibility.stderr create mode 100644 tests/ui/privacy/macro-private-reexport.rs create mode 100644 tests/ui/privacy/macro-private-reexport.stderr create mode 100644 tests/ui/privacy/priv-impl-prim-ty.rs create mode 100644 tests/ui/privacy/priv-in-bad-locations.rs create mode 100644 tests/ui/privacy/priv-in-bad-locations.stderr create mode 100644 tests/ui/privacy/privacy-in-paths.rs create mode 100644 tests/ui/privacy/privacy-in-paths.stderr create mode 100644 tests/ui/privacy/privacy-ns.rs create mode 100644 tests/ui/privacy/privacy-ns1.rs create mode 100644 tests/ui/privacy/privacy-ns1.stderr create mode 100644 tests/ui/privacy/privacy-ns2.rs create mode 100644 tests/ui/privacy/privacy-ns2.stderr create mode 100644 tests/ui/privacy/privacy-reexport.rs create mode 100644 tests/ui/privacy/privacy-sanity.rs create mode 100644 tests/ui/privacy/privacy-sanity.stderr create mode 100644 tests/ui/privacy/privacy-ufcs.rs create mode 100644 tests/ui/privacy/privacy-ufcs.stderr create mode 100644 tests/ui/privacy/privacy1-rpass.rs create mode 100644 tests/ui/privacy/privacy1.rs create mode 100644 tests/ui/privacy/privacy1.stderr create mode 100644 tests/ui/privacy/privacy2.rs create mode 100644 tests/ui/privacy/privacy2.stderr create mode 100644 tests/ui/privacy/privacy3.rs create mode 100644 tests/ui/privacy/privacy3.stderr create mode 100644 tests/ui/privacy/privacy4.rs create mode 100644 tests/ui/privacy/privacy4.stderr create mode 100644 tests/ui/privacy/privacy5.rs create mode 100644 tests/ui/privacy/privacy5.stderr create mode 100644 tests/ui/privacy/private-class-field.rs create mode 100644 tests/ui/privacy/private-field-ty-err.rs create mode 100644 tests/ui/privacy/private-field-ty-err.stderr create mode 100644 tests/ui/privacy/private-impl-method.rs create mode 100644 tests/ui/privacy/private-impl-method.stderr create mode 100644 tests/ui/privacy/private-in-public-assoc-ty.rs create mode 100644 tests/ui/privacy/private-in-public-assoc-ty.stderr create mode 100644 tests/ui/privacy/private-in-public-expr-pat.rs create mode 100644 tests/ui/privacy/private-in-public-ill-formed.rs create mode 100644 tests/ui/privacy/private-in-public-ill-formed.stderr create mode 100644 tests/ui/privacy/private-in-public-lint.rs create mode 100644 tests/ui/privacy/private-in-public-lint.stderr create mode 100644 tests/ui/privacy/private-in-public-non-principal-2.rs create mode 100644 tests/ui/privacy/private-in-public-non-principal-2.stderr create mode 100644 tests/ui/privacy/private-in-public-non-principal.rs create mode 100644 tests/ui/privacy/private-in-public-non-principal.stderr create mode 100644 tests/ui/privacy/private-in-public-type-alias-impl-trait.rs create mode 100644 tests/ui/privacy/private-in-public-warn.rs create mode 100644 tests/ui/privacy/private-in-public-warn.stderr create mode 100644 tests/ui/privacy/private-in-public.rs create mode 100644 tests/ui/privacy/private-in-public.stderr create mode 100644 tests/ui/privacy/private-inferred-type-1.rs create mode 100644 tests/ui/privacy/private-inferred-type-1.stderr create mode 100644 tests/ui/privacy/private-inferred-type-2.rs create mode 100644 tests/ui/privacy/private-inferred-type-2.stderr create mode 100644 tests/ui/privacy/private-inferred-type-3.rs create mode 100644 tests/ui/privacy/private-inferred-type-3.stderr create mode 100644 tests/ui/privacy/private-inferred-type.rs create mode 100644 tests/ui/privacy/private-inferred-type.stderr create mode 100644 tests/ui/privacy/private-item-simple.rs create mode 100644 tests/ui/privacy/private-item-simple.stderr create mode 100644 tests/ui/privacy/private-method-cross-crate.rs create mode 100644 tests/ui/privacy/private-method-cross-crate.stderr create mode 100644 tests/ui/privacy/private-method-inherited.rs create mode 100644 tests/ui/privacy/private-method-inherited.stderr create mode 100644 tests/ui/privacy/private-method-rpass.rs create mode 100644 tests/ui/privacy/private-method.rs create mode 100644 tests/ui/privacy/private-method.stderr create mode 100644 tests/ui/privacy/private-struct-field-cross-crate.rs create mode 100644 tests/ui/privacy/private-struct-field-cross-crate.stderr create mode 100644 tests/ui/privacy/private-struct-field-ctor.rs create mode 100644 tests/ui/privacy/private-struct-field-ctor.stderr create mode 100644 tests/ui/privacy/private-struct-field-pattern.rs create mode 100644 tests/ui/privacy/private-struct-field-pattern.stderr create mode 100644 tests/ui/privacy/private-struct-field.rs create mode 100644 tests/ui/privacy/private-struct-field.stderr create mode 100644 tests/ui/privacy/private-type-in-interface.rs create mode 100644 tests/ui/privacy/private-type-in-interface.stderr create mode 100644 tests/ui/privacy/private-variant-reexport.rs create mode 100644 tests/ui/privacy/private-variant-reexport.stderr create mode 100644 tests/ui/privacy/pub-extern-privacy.rs create mode 100644 tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs create mode 100644 tests/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs create mode 100644 tests/ui/privacy/pub-priv-dep/pub-priv1.rs create mode 100644 tests/ui/privacy/pub-priv-dep/pub-priv1.stderr create mode 100644 tests/ui/privacy/pub-priv-dep/std-pub.rs create mode 100644 tests/ui/privacy/pub-use-xcrate.rs create mode 100644 tests/ui/privacy/pub_use_mods_xcrate_exe.rs create mode 100644 tests/ui/privacy/reachable-unnameable-items.rs create mode 100644 tests/ui/privacy/restricted/auxiliary/pub_restricted.rs create mode 100644 tests/ui/privacy/restricted/lookup-ignores-private.rs create mode 100644 tests/ui/privacy/restricted/private-in-public.rs create mode 100644 tests/ui/privacy/restricted/private-in-public.stderr create mode 100644 tests/ui/privacy/restricted/relative-2018.rs create mode 100644 tests/ui/privacy/restricted/relative-2018.stderr create mode 100644 tests/ui/privacy/restricted/struct-literal-field.rs create mode 100644 tests/ui/privacy/restricted/struct-literal-field.stderr create mode 100644 tests/ui/privacy/restricted/test.rs create mode 100644 tests/ui/privacy/restricted/test.stderr create mode 100644 tests/ui/privacy/suggest-making-field-public.fixed create mode 100644 tests/ui/privacy/suggest-making-field-public.rs create mode 100644 tests/ui/privacy/suggest-making-field-public.stderr create mode 100644 tests/ui/privacy/union-field-privacy-1.rs create mode 100644 tests/ui/privacy/union-field-privacy-1.stderr create mode 100644 tests/ui/privacy/union-field-privacy-2.rs create mode 100644 tests/ui/privacy/union-field-privacy-2.stderr create mode 100644 tests/ui/privacy/useless-pub.rs create mode 100644 tests/ui/privacy/useless-pub.stderr create mode 100644 tests/ui/privacy/where-priv-type.rs create mode 100644 tests/ui/privacy/where-priv-type.stderr create mode 100644 tests/ui/privacy/where-pub-type-impls-priv-trait.rs create mode 100644 tests/ui/privacy/where-pub-type-impls-priv-trait.stderr create mode 100644 tests/ui/proc-macro/add-impl.rs create mode 100644 tests/ui/proc-macro/allowed-attr-stmt-expr.rs create mode 100644 tests/ui/proc-macro/allowed-attr-stmt-expr.stdout create mode 100644 tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs create mode 100644 tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr create mode 100644 tests/ui/proc-macro/ambiguous-builtin-attrs.rs create mode 100644 tests/ui/proc-macro/ambiguous-builtin-attrs.stderr create mode 100644 tests/ui/proc-macro/amputate-span.fixed create mode 100644 tests/ui/proc-macro/amputate-span.rs create mode 100644 tests/ui/proc-macro/amputate-span.stderr create mode 100644 tests/ui/proc-macro/append-impl.rs create mode 100644 tests/ui/proc-macro/attr-args.rs create mode 100644 tests/ui/proc-macro/attr-cfg.rs create mode 100644 tests/ui/proc-macro/attr-complex-fn.rs create mode 100644 tests/ui/proc-macro/attr-complex-fn.stdout create mode 100644 tests/ui/proc-macro/attr-invalid-exprs.rs create mode 100644 tests/ui/proc-macro/attr-invalid-exprs.stderr create mode 100644 tests/ui/proc-macro/attr-on-trait.rs create mode 100644 tests/ui/proc-macro/attr-stmt-expr-rpass.rs create mode 100644 tests/ui/proc-macro/attr-stmt-expr.rs create mode 100644 tests/ui/proc-macro/attr-stmt-expr.stderr create mode 100644 tests/ui/proc-macro/attr-stmt-expr.stdout create mode 100644 tests/ui/proc-macro/attribute-after-derive.rs create mode 100644 tests/ui/proc-macro/attribute-after-derive.stdout create mode 100644 tests/ui/proc-macro/attribute-spans-preserved.rs create mode 100644 tests/ui/proc-macro/attribute-spans-preserved.stderr create mode 100644 tests/ui/proc-macro/attribute-spans-preserved.stdout create mode 100644 tests/ui/proc-macro/attribute-with-error.rs create mode 100644 tests/ui/proc-macro/attribute-with-error.stderr create mode 100644 tests/ui/proc-macro/attribute.rs create mode 100644 tests/ui/proc-macro/attribute.stderr create mode 100644 tests/ui/proc-macro/attributes-included.rs create mode 100644 tests/ui/proc-macro/attributes-included.stderr create mode 100644 tests/ui/proc-macro/attributes-on-definitions.rs create mode 100644 tests/ui/proc-macro/attributes-on-definitions.stderr create mode 100644 tests/ui/proc-macro/attributes-on-modules-fail.rs create mode 100644 tests/ui/proc-macro/attributes-on-modules-fail.stderr create mode 100644 tests/ui/proc-macro/attributes-on-modules.rs create mode 100644 tests/ui/proc-macro/auxiliary/add-impl.rs create mode 100644 tests/ui/proc-macro/auxiliary/amputate-span.rs create mode 100644 tests/ui/proc-macro/auxiliary/api/cmp.rs create mode 100644 tests/ui/proc-macro/auxiliary/api/mod.rs create mode 100644 tests/ui/proc-macro/auxiliary/api/parse.rs create mode 100644 tests/ui/proc-macro/auxiliary/append-impl.rs create mode 100644 tests/ui/proc-macro/auxiliary/assert-span-pos.rs create mode 100644 tests/ui/proc-macro/auxiliary/attr-args.rs create mode 100644 tests/ui/proc-macro/auxiliary/attr-cfg.rs create mode 100644 tests/ui/proc-macro/auxiliary/attr-on-trait.rs create mode 100644 tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs create mode 100644 tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs create mode 100644 tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs create mode 100644 tests/ui/proc-macro/auxiliary/attributes-included.rs create mode 100644 tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs create mode 100644 tests/ui/proc-macro/auxiliary/bang-macro.rs create mode 100644 tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs create mode 100644 tests/ui/proc-macro/auxiliary/builtin-attrs.rs create mode 100644 tests/ui/proc-macro/auxiliary/call-deprecated.rs create mode 100644 tests/ui/proc-macro/auxiliary/call-site.rs create mode 100644 tests/ui/proc-macro/auxiliary/cond_plugin.rs create mode 100644 tests/ui/proc-macro/auxiliary/count_compound_ops.rs create mode 100644 tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs create mode 100644 tests/ui/proc-macro/auxiliary/custom-quote.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-a.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-atob.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-b-rpass.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-b.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-bad.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-clona.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-ctod.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-foo.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-nothing.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-same-struct.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-two-attrs.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-union.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-unstable-2.rs create mode 100644 tests/ui/proc-macro/auxiliary/derive-unstable.rs create mode 100644 tests/ui/proc-macro/auxiliary/dollar-crate-external.rs create mode 100644 tests/ui/proc-macro/auxiliary/double.rs create mode 100644 tests/ui/proc-macro/auxiliary/duplicate.rs create mode 100644 tests/ui/proc-macro/auxiliary/edition-imports-2015.rs create mode 100644 tests/ui/proc-macro/auxiliary/empty-crate.rs create mode 100644 tests/ui/proc-macro/auxiliary/expand-expr.rs create mode 100644 tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs create mode 100644 tests/ui/proc-macro/auxiliary/external-crate-var.rs create mode 100644 tests/ui/proc-macro/auxiliary/first-second.rs create mode 100644 tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs create mode 100644 tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs create mode 100644 tests/ui/proc-macro/auxiliary/gen-macro-rules.rs create mode 100644 tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs create mode 100644 tests/ui/proc-macro/auxiliary/generate-mod.rs create mode 100644 tests/ui/proc-macro/auxiliary/hygiene_example.rs create mode 100644 tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs create mode 100644 tests/ui/proc-macro/auxiliary/included-file.txt create mode 100644 tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs create mode 100644 tests/ui/proc-macro/auxiliary/is-available.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-104884.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-38586.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-39889.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-42708.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-50061.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-50493.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-59191.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-66286.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-75801.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-79242.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-79825.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-83510.rs create mode 100644 tests/ui/proc-macro/auxiliary/issue-91800-macro.rs create mode 100644 tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs create mode 100644 tests/ui/proc-macro/auxiliary/lifetimes.rs create mode 100644 tests/ui/proc-macro/auxiliary/macro-only-syntax.rs create mode 100644 tests/ui/proc-macro/auxiliary/make-macro.rs create mode 100644 tests/ui/proc-macro/auxiliary/meta-delim.rs create mode 100644 tests/ui/proc-macro/auxiliary/meta-macro.rs create mode 100644 tests/ui/proc-macro/auxiliary/mixed-site-span.rs create mode 100644 tests/ui/proc-macro/auxiliary/modify-ast.rs create mode 100644 tests/ui/proc-macro/auxiliary/multiple-derives.rs create mode 100644 tests/ui/proc-macro/auxiliary/multispan.rs create mode 100644 tests/ui/proc-macro/auxiliary/negative-token.rs create mode 100644 tests/ui/proc-macro/auxiliary/nested-macro-rules.rs create mode 100644 tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs create mode 100644 tests/ui/proc-macro/auxiliary/not-joint.rs create mode 100644 tests/ui/proc-macro/auxiliary/parent-source-spans.rs create mode 100644 tests/ui/proc-macro/auxiliary/proc-macro-panic.rs create mode 100644 tests/ui/proc-macro/auxiliary/raw-ident.rs create mode 100644 tests/ui/proc-macro/auxiliary/re-export.rs create mode 100644 tests/ui/proc-macro/auxiliary/recollect.rs create mode 100644 tests/ui/proc-macro/auxiliary/resolved-located-at.rs create mode 100644 tests/ui/proc-macro/auxiliary/span-api-tests.rs create mode 100644 tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs create mode 100644 tests/ui/proc-macro/auxiliary/span-test-macros.rs create mode 100644 tests/ui/proc-macro/auxiliary/subspan.rs create mode 100644 tests/ui/proc-macro/auxiliary/test-macros.rs create mode 100644 tests/ui/proc-macro/auxiliary/three-equals.rs create mode 100644 tests/ui/proc-macro/auxiliary/weird-hygiene.rs create mode 100644 tests/ui/proc-macro/bang-macro.rs create mode 100644 tests/ui/proc-macro/break-token-spans.rs create mode 100644 tests/ui/proc-macro/break-token-spans.stderr create mode 100644 tests/ui/proc-macro/call-deprecated.rs create mode 100644 tests/ui/proc-macro/call-deprecated.stderr create mode 100644 tests/ui/proc-macro/call-site.rs create mode 100644 tests/ui/proc-macro/capture-macro-rules-invoke.rs create mode 100644 tests/ui/proc-macro/capture-macro-rules-invoke.stdout create mode 100644 tests/ui/proc-macro/capture-unglued-token.rs create mode 100644 tests/ui/proc-macro/capture-unglued-token.stdout create mode 100644 tests/ui/proc-macro/cfg-eval-fail.rs create mode 100644 tests/ui/proc-macro/cfg-eval-fail.stderr create mode 100644 tests/ui/proc-macro/cfg-eval-inner.rs create mode 100644 tests/ui/proc-macro/cfg-eval-inner.stdout create mode 100644 tests/ui/proc-macro/cfg-eval.rs create mode 100644 tests/ui/proc-macro/cfg-eval.stdout create mode 100644 tests/ui/proc-macro/count_compound_ops.rs create mode 100644 tests/ui/proc-macro/crate-attrs-multiple.rs create mode 100644 tests/ui/proc-macro/crate-var.rs create mode 100644 tests/ui/proc-macro/crt-static.rs create mode 100644 tests/ui/proc-macro/custom-attr-only-one-derive.rs create mode 100644 tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs create mode 100644 tests/ui/proc-macro/debug/dump-debug-span-debug.rs create mode 100644 tests/ui/proc-macro/debug/dump-debug-span-debug.stderr create mode 100644 tests/ui/proc-macro/debug/dump-debug.rs create mode 100644 tests/ui/proc-macro/debug/dump-debug.stderr create mode 100644 tests/ui/proc-macro/define-two.rs create mode 100644 tests/ui/proc-macro/define-two.stderr create mode 100644 tests/ui/proc-macro/derive-attr-cfg.rs create mode 100644 tests/ui/proc-macro/derive-b.rs create mode 100644 tests/ui/proc-macro/derive-bad.rs create mode 100644 tests/ui/proc-macro/derive-bad.stderr create mode 100644 tests/ui/proc-macro/derive-expand-order.rs create mode 100644 tests/ui/proc-macro/derive-expand-order.stdout create mode 100644 tests/ui/proc-macro/derive-helper-configured.rs create mode 100644 tests/ui/proc-macro/derive-helper-legacy-limits.rs create mode 100644 tests/ui/proc-macro/derive-helper-legacy-limits.stderr create mode 100644 tests/ui/proc-macro/derive-helper-legacy-spurious.rs create mode 100644 tests/ui/proc-macro/derive-helper-legacy-spurious.stderr create mode 100644 tests/ui/proc-macro/derive-helper-shadowed.rs create mode 100644 tests/ui/proc-macro/derive-helper-shadowing-2.rs create mode 100644 tests/ui/proc-macro/derive-helper-shadowing.rs create mode 100644 tests/ui/proc-macro/derive-helper-shadowing.stderr create mode 100644 tests/ui/proc-macro/derive-helper-vs-legacy.rs create mode 100644 tests/ui/proc-macro/derive-in-mod.rs create mode 100644 tests/ui/proc-macro/derive-multiple-with-packed.rs create mode 100644 tests/ui/proc-macro/derive-same-struct.rs create mode 100644 tests/ui/proc-macro/derive-same-struct.stdout create mode 100644 tests/ui/proc-macro/derive-still-gated.rs create mode 100644 tests/ui/proc-macro/derive-still-gated.stderr create mode 100644 tests/ui/proc-macro/derive-test.rs create mode 100644 tests/ui/proc-macro/derive-two-attrs.rs create mode 100644 tests/ui/proc-macro/derive-union.rs create mode 100644 tests/ui/proc-macro/disappearing-resolution.rs create mode 100644 tests/ui/proc-macro/disappearing-resolution.stderr create mode 100644 tests/ui/proc-macro/doc-comment-preserved.rs create mode 100644 tests/ui/proc-macro/doc-comment-preserved.stdout create mode 100644 tests/ui/proc-macro/dollar-crate-issue-101211.rs create mode 100644 tests/ui/proc-macro/dollar-crate-issue-57089.rs create mode 100644 tests/ui/proc-macro/dollar-crate-issue-57089.stdout create mode 100644 tests/ui/proc-macro/dollar-crate-issue-62325.rs create mode 100644 tests/ui/proc-macro/dollar-crate-issue-62325.stdout create mode 100644 tests/ui/proc-macro/dollar-crate.rs create mode 100644 tests/ui/proc-macro/dollar-crate.stdout create mode 100644 tests/ui/proc-macro/edition-imports-2018.rs create mode 100644 tests/ui/proc-macro/empty-crate.rs create mode 100644 tests/ui/proc-macro/empty-where-clause.rs create mode 100644 tests/ui/proc-macro/empty-where-clause.stderr create mode 100644 tests/ui/proc-macro/expand-expr.rs create mode 100644 tests/ui/proc-macro/expand-expr.stderr create mode 100644 tests/ui/proc-macro/expand-to-derive.rs create mode 100644 tests/ui/proc-macro/expand-to-derive.stdout create mode 100644 tests/ui/proc-macro/expand-to-unstable.rs create mode 100644 tests/ui/proc-macro/expand-to-unstable.stderr create mode 100644 tests/ui/proc-macro/expand-with-a-macro.rs create mode 100644 tests/ui/proc-macro/export-macro.rs create mode 100644 tests/ui/proc-macro/export-macro.stderr create mode 100644 tests/ui/proc-macro/exports.rs create mode 100644 tests/ui/proc-macro/exports.stderr create mode 100644 tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs create mode 100644 tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout create mode 100644 tests/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs create mode 100644 tests/ui/proc-macro/gen-lifetime-token.rs create mode 100644 tests/ui/proc-macro/gen-macro-rules-hygiene.rs create mode 100644 tests/ui/proc-macro/gen-macro-rules-hygiene.stderr create mode 100644 tests/ui/proc-macro/gen-macro-rules.rs create mode 100644 tests/ui/proc-macro/generate-dollar-ident.rs create mode 100644 tests/ui/proc-macro/generate-mod.rs create mode 100644 tests/ui/proc-macro/generate-mod.stderr create mode 100644 tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs create mode 100644 tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr create mode 100644 tests/ui/proc-macro/helper-attr-blocked-by-import.rs create mode 100644 tests/ui/proc-macro/hygiene_example.rs create mode 100644 tests/ui/proc-macro/illegal-proc-macro-derive-use.rs create mode 100644 tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr create mode 100644 tests/ui/proc-macro/import.rs create mode 100644 tests/ui/proc-macro/import.stderr create mode 100644 tests/ui/proc-macro/inert-attribute-order.rs create mode 100644 tests/ui/proc-macro/inert-attribute-order.stdout create mode 100644 tests/ui/proc-macro/inner-attr-non-inline-mod.rs create mode 100644 tests/ui/proc-macro/inner-attr-non-inline-mod.stderr create mode 100644 tests/ui/proc-macro/inner-attr-non-inline-mod.stdout create mode 100644 tests/ui/proc-macro/inner-attrs.rs create mode 100644 tests/ui/proc-macro/inner-attrs.stderr create mode 100644 tests/ui/proc-macro/inner-attrs.stdout create mode 100644 tests/ui/proc-macro/input-interpolated.rs create mode 100644 tests/ui/proc-macro/input-interpolated.stdout create mode 100644 tests/ui/proc-macro/invalid-attributes.rs create mode 100644 tests/ui/proc-macro/invalid-attributes.stderr create mode 100644 tests/ui/proc-macro/invalid-punct-ident-1.rs create mode 100644 tests/ui/proc-macro/invalid-punct-ident-1.stderr create mode 100644 tests/ui/proc-macro/invalid-punct-ident-2.rs create mode 100644 tests/ui/proc-macro/invalid-punct-ident-2.stderr create mode 100644 tests/ui/proc-macro/invalid-punct-ident-3.rs create mode 100644 tests/ui/proc-macro/invalid-punct-ident-3.stderr create mode 100644 tests/ui/proc-macro/invalid-punct-ident-4.rs create mode 100644 tests/ui/proc-macro/invalid-punct-ident-4.stderr create mode 100644 tests/ui/proc-macro/is-available.rs create mode 100644 tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs create mode 100644 tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr create mode 100644 tests/ui/proc-macro/issue-36935.rs create mode 100644 tests/ui/proc-macro/issue-36935.stderr create mode 100644 tests/ui/proc-macro/issue-37788.rs create mode 100644 tests/ui/proc-macro/issue-37788.stderr create mode 100644 tests/ui/proc-macro/issue-38586.rs create mode 100644 tests/ui/proc-macro/issue-38586.stderr create mode 100644 tests/ui/proc-macro/issue-39889.rs create mode 100644 tests/ui/proc-macro/issue-42708.rs create mode 100644 tests/ui/proc-macro/issue-50061.rs create mode 100644 tests/ui/proc-macro/issue-50493.rs create mode 100644 tests/ui/proc-macro/issue-50493.stderr create mode 100644 tests/ui/proc-macro/issue-53481.rs create mode 100644 tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs create mode 100644 tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr create mode 100644 tests/ui/proc-macro/issue-66286.rs create mode 100644 tests/ui/proc-macro/issue-66286.stderr create mode 100644 tests/ui/proc-macro/issue-73933-procedural-masquerade.rs create mode 100644 tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout create mode 100644 tests/ui/proc-macro/issue-75734-pp-paren.rs create mode 100644 tests/ui/proc-macro/issue-75734-pp-paren.stdout create mode 100644 tests/ui/proc-macro/issue-75801.rs create mode 100644 tests/ui/proc-macro/issue-75801.stderr create mode 100644 tests/ui/proc-macro/issue-75930-derive-cfg.rs create mode 100644 tests/ui/proc-macro/issue-75930-derive-cfg.stderr create mode 100644 tests/ui/proc-macro/issue-75930-derive-cfg.stdout create mode 100644 tests/ui/proc-macro/issue-76182-leading-vert-pat.rs create mode 100644 tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout create mode 100644 tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs create mode 100644 tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr create mode 100644 tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs create mode 100644 tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout create mode 100644 tests/ui/proc-macro/issue-79148.rs create mode 100644 tests/ui/proc-macro/issue-79148.stderr create mode 100644 tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs create mode 100644 tests/ui/proc-macro/issue-79825.rs create mode 100644 tests/ui/proc-macro/issue-80760-empty-stmt.rs create mode 100644 tests/ui/proc-macro/issue-80760-empty-stmt.stdout create mode 100644 tests/ui/proc-macro/issue-81007-item-attrs.rs create mode 100644 tests/ui/proc-macro/issue-81007-item-attrs.stdout create mode 100644 tests/ui/proc-macro/issue-81543-item-parse-err.rs create mode 100644 tests/ui/proc-macro/issue-81543-item-parse-err.stderr create mode 100644 tests/ui/proc-macro/issue-81555.rs create mode 100644 tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs create mode 100644 tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr create mode 100644 tests/ui/proc-macro/issue-83510.rs create mode 100644 tests/ui/proc-macro/issue-83510.stderr create mode 100644 tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed create mode 100644 tests/ui/proc-macro/issue-86781-bad-inner-doc.rs create mode 100644 tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr create mode 100644 tests/ui/proc-macro/issue-91800.rs create mode 100644 tests/ui/proc-macro/issue-91800.stderr create mode 100644 tests/ui/proc-macro/item-error.rs create mode 100644 tests/ui/proc-macro/item-error.stderr create mode 100644 tests/ui/proc-macro/keep-expr-tokens.rs create mode 100644 tests/ui/proc-macro/keep-expr-tokens.stderr create mode 100644 tests/ui/proc-macro/keep-expr-tokens.stdout create mode 100644 tests/ui/proc-macro/lifetimes-rpass.rs create mode 100644 tests/ui/proc-macro/lifetimes.rs create mode 100644 tests/ui/proc-macro/lifetimes.stderr create mode 100644 tests/ui/proc-macro/lints_in_proc_macros.rs create mode 100644 tests/ui/proc-macro/lints_in_proc_macros.stderr create mode 100644 tests/ui/proc-macro/load-panic-backtrace.rs create mode 100644 tests/ui/proc-macro/load-panic-backtrace.stderr create mode 100644 tests/ui/proc-macro/load-panic.rs create mode 100644 tests/ui/proc-macro/load-panic.stderr create mode 100644 tests/ui/proc-macro/load-two.rs create mode 100644 tests/ui/proc-macro/macro-brackets.rs create mode 100644 tests/ui/proc-macro/macro-brackets.stderr create mode 100644 tests/ui/proc-macro/macro-crate-multi-decorator.rs create mode 100644 tests/ui/proc-macro/macro-namespace-reserved-2.rs create mode 100644 tests/ui/proc-macro/macro-namespace-reserved-2.stderr create mode 100644 tests/ui/proc-macro/macro-namespace-reserved.rs create mode 100644 tests/ui/proc-macro/macro-namespace-reserved.stderr create mode 100644 tests/ui/proc-macro/macro-quote-cond.rs create mode 100644 tests/ui/proc-macro/macro-rules-derive-cfg.rs create mode 100644 tests/ui/proc-macro/macro-rules-derive-cfg.stdout create mode 100644 tests/ui/proc-macro/macro-rules-derive.rs create mode 100644 tests/ui/proc-macro/macro-rules-derive.stderr create mode 100644 tests/ui/proc-macro/macro-use-attr.rs create mode 100644 tests/ui/proc-macro/macro-use-bang.rs create mode 100644 tests/ui/proc-macro/macros-in-extern-derive.rs create mode 100644 tests/ui/proc-macro/macros-in-extern-derive.stderr create mode 100644 tests/ui/proc-macro/macros-in-extern.rs create mode 100644 tests/ui/proc-macro/macros-in-type.rs create mode 100644 tests/ui/proc-macro/meta-delim.rs create mode 100644 tests/ui/proc-macro/meta-macro-hygiene.rs create mode 100644 tests/ui/proc-macro/meta-macro-hygiene.stdout create mode 100644 tests/ui/proc-macro/meta-macro.rs create mode 100644 tests/ui/proc-macro/meta-macro.stdout create mode 100644 tests/ui/proc-macro/mixed-site-span.rs create mode 100644 tests/ui/proc-macro/mixed-site-span.stderr create mode 100644 tests/ui/proc-macro/modify-ast.rs create mode 100644 tests/ui/proc-macro/module.rs create mode 100644 tests/ui/proc-macro/module_with_attrs.rs create mode 100644 tests/ui/proc-macro/multispan.rs create mode 100644 tests/ui/proc-macro/multispan.stderr create mode 100644 tests/ui/proc-macro/negative-token.rs create mode 100644 tests/ui/proc-macro/nested-derive-cfg.rs create mode 100644 tests/ui/proc-macro/nested-derive-cfg.stdout create mode 100644 tests/ui/proc-macro/nested-item-spans.rs create mode 100644 tests/ui/proc-macro/nested-item-spans.stderr create mode 100644 tests/ui/proc-macro/nested-macro-rules.rs create mode 100644 tests/ui/proc-macro/nested-macro-rules.stdout create mode 100644 tests/ui/proc-macro/nested-nonterminal-tokens.rs create mode 100644 tests/ui/proc-macro/nested-nonterminal-tokens.stdout create mode 100644 tests/ui/proc-macro/no-macro-use-attr.rs create mode 100644 tests/ui/proc-macro/no-macro-use-attr.stderr create mode 100644 tests/ui/proc-macro/no-missing-docs.rs create mode 100644 tests/ui/proc-macro/nodelim-groups.rs create mode 100644 tests/ui/proc-macro/nodelim-groups.stdout create mode 100644 tests/ui/proc-macro/non-root.rs create mode 100644 tests/ui/proc-macro/non-root.stderr create mode 100644 tests/ui/proc-macro/nonterminal-expansion.rs create mode 100644 tests/ui/proc-macro/nonterminal-expansion.stdout create mode 100644 tests/ui/proc-macro/nonterminal-recollect-attr.rs create mode 100644 tests/ui/proc-macro/nonterminal-recollect-attr.stdout create mode 100644 tests/ui/proc-macro/nonterminal-token-hygiene.rs create mode 100644 tests/ui/proc-macro/nonterminal-token-hygiene.stdout create mode 100644 tests/ui/proc-macro/not-joint.rs create mode 100644 tests/ui/proc-macro/out-of-line-mod.rs create mode 100644 tests/ui/proc-macro/outer/inner.rs create mode 100644 tests/ui/proc-macro/panic-abort.rs create mode 100644 tests/ui/proc-macro/panic-abort.stderr create mode 100644 tests/ui/proc-macro/parent-source-spans.rs create mode 100644 tests/ui/proc-macro/parent-source-spans.stderr create mode 100644 tests/ui/proc-macro/pretty-print-hack-hide.rs create mode 100644 tests/ui/proc-macro/pretty-print-hack-hide.stdout create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.local.stderr create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.local.stdout create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.rs create mode 100644 tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs create mode 100644 tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs create mode 100644 tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs create mode 100644 tests/ui/proc-macro/pretty-print-tts.rs create mode 100644 tests/ui/proc-macro/pretty-print-tts.stdout create mode 100644 tests/ui/proc-macro/proc-macro-attributes.rs create mode 100644 tests/ui/proc-macro/proc-macro-attributes.stderr create mode 100644 tests/ui/proc-macro/proc-macro-deprecated-attr.rs create mode 100644 tests/ui/proc-macro/proc-macro-gates.rs create mode 100644 tests/ui/proc-macro/proc-macro-gates.stderr create mode 100644 tests/ui/proc-macro/proc-macro-gates2.rs create mode 100644 tests/ui/proc-macro/proc-macro-gates2.stderr create mode 100644 tests/ui/proc-macro/pub-at-crate-root.rs create mode 100644 tests/ui/proc-macro/pub-at-crate-root.stderr create mode 100644 tests/ui/proc-macro/quote-debug.rs create mode 100644 tests/ui/proc-macro/quote-debug.stdout create mode 100644 tests/ui/proc-macro/raw-ident.rs create mode 100644 tests/ui/proc-macro/raw-ident.stderr create mode 100644 tests/ui/proc-macro/reserved-macro-names.rs create mode 100644 tests/ui/proc-macro/reserved-macro-names.stderr create mode 100644 tests/ui/proc-macro/resolve-error.rs create mode 100644 tests/ui/proc-macro/resolve-error.stderr create mode 100644 tests/ui/proc-macro/resolved-located-at.rs create mode 100644 tests/ui/proc-macro/resolved-located-at.stderr create mode 100644 tests/ui/proc-macro/shadow.rs create mode 100644 tests/ui/proc-macro/shadow.stderr create mode 100644 tests/ui/proc-macro/signature.rs create mode 100644 tests/ui/proc-macro/signature.stderr create mode 100644 tests/ui/proc-macro/smoke.rs create mode 100644 tests/ui/proc-macro/span-absolute-posititions.rs create mode 100644 tests/ui/proc-macro/span-absolute-posititions.stderr create mode 100644 tests/ui/proc-macro/span-api-tests.rs create mode 100644 tests/ui/proc-macro/span-from-proc-macro.rs create mode 100644 tests/ui/proc-macro/span-from-proc-macro.stderr create mode 100644 tests/ui/proc-macro/span-preservation.rs create mode 100644 tests/ui/proc-macro/span-preservation.stderr create mode 100644 tests/ui/proc-macro/struct-field-macro.rs create mode 100644 tests/ui/proc-macro/subspan.rs create mode 100644 tests/ui/proc-macro/subspan.stderr create mode 100644 tests/ui/proc-macro/test.rs create mode 100644 tests/ui/proc-macro/three-equals.rs create mode 100644 tests/ui/proc-macro/three-equals.stderr create mode 100644 tests/ui/proc-macro/trailing-plus.rs create mode 100644 tests/ui/proc-macro/trailing-plus.stdout create mode 100644 tests/ui/proc-macro/trait-fn-args-2015.rs create mode 100644 tests/ui/proc-macro/two-crate-types-1.rs create mode 100644 tests/ui/proc-macro/two-crate-types-1.stderr create mode 100644 tests/ui/proc-macro/two-crate-types-2.rs create mode 100644 tests/ui/proc-macro/two-crate-types-2.stderr create mode 100644 tests/ui/proc-macro/unsafe-foreign-mod.rs create mode 100644 tests/ui/proc-macro/unsafe-mod.rs create mode 100644 tests/ui/proc-macro/visibility-path.rs create mode 100644 tests/ui/proc-macro/visibility-path.stderr create mode 100644 tests/ui/proc-macro/weird-braces.rs create mode 100644 tests/ui/proc-macro/weird-braces.stdout create mode 100644 tests/ui/proc-macro/weird-hygiene.rs create mode 100644 tests/ui/proc-macro/weird-hygiene.stderr create mode 100644 tests/ui/process-termination/process-termination-blocking-io.rs create mode 100644 tests/ui/process-termination/process-termination-simple.rs create mode 100644 tests/ui/process/core-run-destroy.rs create mode 100644 tests/ui/process/fds-are-cloexec.rs create mode 100644 tests/ui/process/issue-13304.rs create mode 100644 tests/ui/process/issue-14456.rs create mode 100644 tests/ui/process/issue-14940.rs create mode 100644 tests/ui/process/issue-16272.rs create mode 100644 tests/ui/process/issue-20091.rs create mode 100644 tests/ui/process/multi-panic.rs create mode 100644 tests/ui/process/no-stdio.rs create mode 100644 tests/ui/process/nofile-limit.rs create mode 100644 tests/ui/process/process-envs.rs create mode 100644 tests/ui/process/process-exit.rs create mode 100644 tests/ui/process/process-panic-after-fork.rs create mode 100644 tests/ui/process/process-remove-from-env.rs create mode 100644 tests/ui/process/process-sigpipe.rs create mode 100644 tests/ui/process/process-spawn-nonexistent.rs create mode 100644 tests/ui/process/process-spawn-with-unicode-params.rs create mode 100644 tests/ui/process/process-status-inherits-stdin.rs create mode 100644 tests/ui/process/signal-exit-status.rs create mode 100644 tests/ui/process/sigpipe-should-be-ignored.rs create mode 100644 tests/ui/process/tls-exit-status.rs create mode 100644 tests/ui/process/try-wait.rs create mode 100644 tests/ui/project-cache-issue-31849.rs create mode 100644 tests/ui/ptr-coercion-rpass.rs create mode 100644 tests/ui/ptr-coercion.rs create mode 100644 tests/ui/ptr-coercion.stderr create mode 100644 tests/ui/ptr_ops/issue-80309-safe.rs create mode 100644 tests/ui/ptr_ops/issue-80309.rs create mode 100644 tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs create mode 100644 tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr create mode 100644 tests/ui/pub/pub-ident-fn-2.fixed create mode 100644 tests/ui/pub/pub-ident-fn-2.rs create mode 100644 tests/ui/pub/pub-ident-fn-2.stderr create mode 100644 tests/ui/pub/pub-ident-fn-3.rs create mode 100644 tests/ui/pub/pub-ident-fn-3.stderr create mode 100644 tests/ui/pub/pub-ident-fn-or-struct-2.rs create mode 100644 tests/ui/pub/pub-ident-fn-or-struct-2.stderr create mode 100644 tests/ui/pub/pub-ident-fn-or-struct.rs create mode 100644 tests/ui/pub/pub-ident-fn-or-struct.stderr create mode 100644 tests/ui/pub/pub-ident-fn-with-lifetime-2.rs create mode 100644 tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr create mode 100644 tests/ui/pub/pub-ident-fn-with-lifetime.fixed create mode 100644 tests/ui/pub/pub-ident-fn-with-lifetime.rs create mode 100644 tests/ui/pub/pub-ident-fn-with-lifetime.stderr create mode 100644 tests/ui/pub/pub-ident-fn.fixed create mode 100644 tests/ui/pub/pub-ident-fn.rs create mode 100644 tests/ui/pub/pub-ident-fn.stderr create mode 100644 tests/ui/pub/pub-ident-struct-with-lifetime.rs create mode 100644 tests/ui/pub/pub-ident-struct-with-lifetime.stderr create mode 100644 tests/ui/pub/pub-ident-struct.fixed create mode 100644 tests/ui/pub/pub-ident-struct.rs create mode 100644 tests/ui/pub/pub-ident-struct.stderr create mode 100644 tests/ui/pub/pub-ident-with-lifetime-incomplete.rs create mode 100644 tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr create mode 100644 tests/ui/pub/pub-reexport-priv-extern-crate.rs create mode 100644 tests/ui/pub/pub-reexport-priv-extern-crate.stderr create mode 100644 tests/ui/pub/pub-restricted-error-fn.rs create mode 100644 tests/ui/pub/pub-restricted-error-fn.stderr create mode 100644 tests/ui/pub/pub-restricted-error.rs create mode 100644 tests/ui/pub/pub-restricted-error.stderr create mode 100644 tests/ui/pub/pub-restricted-non-path.rs create mode 100644 tests/ui/pub/pub-restricted-non-path.stderr create mode 100644 tests/ui/pub/pub-restricted.rs create mode 100644 tests/ui/pub/pub-restricted.stderr create mode 100644 tests/ui/qualified/qualified-path-params-2.rs create mode 100644 tests/ui/qualified/qualified-path-params-2.stderr create mode 100644 tests/ui/qualified/qualified-path-params.rs create mode 100644 tests/ui/qualified/qualified-path-params.stderr create mode 100644 tests/ui/query-system/fn-sig-cycle-arity.rs create mode 100644 tests/ui/query-system/fn-sig-cycle-arity.stderr create mode 100644 tests/ui/query-system/issue-83479.rs create mode 100644 tests/ui/query-system/issue-83479.stderr create mode 100644 tests/ui/query-system/query_depth.rs create mode 100644 tests/ui/query-system/query_depth.stderr create mode 100644 tests/ui/query-visibility.rs create mode 100644 tests/ui/range/exclusive-range-patterns-2021.rs create mode 100644 tests/ui/range/exclusive-range-patterns-2021.stderr create mode 100644 tests/ui/range/issue-54505-no-literals.fixed create mode 100644 tests/ui/range/issue-54505-no-literals.rs create mode 100644 tests/ui/range/issue-54505-no-literals.stderr create mode 100644 tests/ui/range/issue-54505-no-std.rs create mode 100644 tests/ui/range/issue-54505-no-std.stderr create mode 100644 tests/ui/range/issue-54505.fixed create mode 100644 tests/ui/range/issue-54505.rs create mode 100644 tests/ui/range/issue-54505.stderr create mode 100644 tests/ui/range/issue-73553-misinterp-range-literal.rs create mode 100644 tests/ui/range/issue-73553-misinterp-range-literal.stderr create mode 100644 tests/ui/range/range-1.rs create mode 100644 tests/ui/range/range-1.stderr create mode 100644 tests/ui/range/range-inclusive-pattern-precedence.fixed create mode 100644 tests/ui/range/range-inclusive-pattern-precedence.rs create mode 100644 tests/ui/range/range-inclusive-pattern-precedence.stderr create mode 100644 tests/ui/range/range-inclusive-pattern-precedence2.rs create mode 100644 tests/ui/range/range-inclusive-pattern-precedence2.stderr create mode 100644 tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs create mode 100644 tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr create mode 100644 tests/ui/range/range_traits-1.rs create mode 100644 tests/ui/range/range_traits-1.stderr create mode 100644 tests/ui/range/range_traits-2.rs create mode 100644 tests/ui/range/range_traits-2.stderr create mode 100644 tests/ui/range/range_traits-3.rs create mode 100644 tests/ui/range/range_traits-3.stderr create mode 100644 tests/ui/range/range_traits-4.rs create mode 100644 tests/ui/range/range_traits-5.rs create mode 100644 tests/ui/range/range_traits-6.rs create mode 100644 tests/ui/range/range_traits-6.stderr create mode 100644 tests/ui/range/range_traits-7.rs create mode 100644 tests/ui/range_inclusive.rs create mode 100644 tests/ui/raw-ref-op/feature-raw-ref-op.rs create mode 100644 tests/ui/raw-ref-op/feature-raw-ref-op.stderr create mode 100644 tests/ui/raw-ref-op/raw-ref-op.rs create mode 100644 tests/ui/raw-ref-op/raw-ref-temp-deref.rs create mode 100644 tests/ui/raw-ref-op/raw-ref-temp.rs create mode 100644 tests/ui/raw-ref-op/raw-ref-temp.stderr create mode 100644 tests/ui/raw-ref-op/unusual_locations.rs create mode 100644 tests/ui/raw-str.rs create mode 100644 tests/ui/reachable-unnameable-type-alias.rs create mode 100644 tests/ui/reachable/README.md create mode 100644 tests/ui/reachable/auxiliary/issue-11225-1.rs create mode 100644 tests/ui/reachable/auxiliary/issue-11225-2.rs create mode 100644 tests/ui/reachable/auxiliary/issue-11225-3.rs create mode 100644 tests/ui/reachable/auxiliary/unreachable_variant.rs create mode 100644 tests/ui/reachable/expr_add.rs create mode 100644 tests/ui/reachable/expr_add.stderr create mode 100644 tests/ui/reachable/expr_again.rs create mode 100644 tests/ui/reachable/expr_again.stderr create mode 100644 tests/ui/reachable/expr_andand.rs create mode 100644 tests/ui/reachable/expr_array.rs create mode 100644 tests/ui/reachable/expr_array.stderr create mode 100644 tests/ui/reachable/expr_assign.rs create mode 100644 tests/ui/reachable/expr_assign.stderr create mode 100644 tests/ui/reachable/expr_block.rs create mode 100644 tests/ui/reachable/expr_block.stderr create mode 100644 tests/ui/reachable/expr_box.rs create mode 100644 tests/ui/reachable/expr_box.stderr create mode 100644 tests/ui/reachable/expr_call.rs create mode 100644 tests/ui/reachable/expr_call.stderr create mode 100644 tests/ui/reachable/expr_cast.rs create mode 100644 tests/ui/reachable/expr_cast.stderr create mode 100644 tests/ui/reachable/expr_if.rs create mode 100644 tests/ui/reachable/expr_if.stderr create mode 100644 tests/ui/reachable/expr_loop.rs create mode 100644 tests/ui/reachable/expr_loop.stderr create mode 100644 tests/ui/reachable/expr_match.rs create mode 100644 tests/ui/reachable/expr_match.stderr create mode 100644 tests/ui/reachable/expr_method.rs create mode 100644 tests/ui/reachable/expr_method.stderr create mode 100644 tests/ui/reachable/expr_oror.rs create mode 100644 tests/ui/reachable/expr_repeat.rs create mode 100644 tests/ui/reachable/expr_repeat.stderr create mode 100644 tests/ui/reachable/expr_return.rs create mode 100644 tests/ui/reachable/expr_return.stderr create mode 100644 tests/ui/reachable/expr_return_in_macro.rs create mode 100644 tests/ui/reachable/expr_return_in_macro.stderr create mode 100644 tests/ui/reachable/expr_struct.rs create mode 100644 tests/ui/reachable/expr_struct.stderr create mode 100644 tests/ui/reachable/expr_tup.rs create mode 100644 tests/ui/reachable/expr_tup.stderr create mode 100644 tests/ui/reachable/expr_type.rs create mode 100644 tests/ui/reachable/expr_type.stderr create mode 100644 tests/ui/reachable/expr_unary.rs create mode 100644 tests/ui/reachable/expr_unary.stderr create mode 100644 tests/ui/reachable/expr_while.rs create mode 100644 tests/ui/reachable/expr_while.stderr create mode 100644 tests/ui/reachable/issue-11225-1.rs create mode 100644 tests/ui/reachable/issue-11225-2.rs create mode 100644 tests/ui/reachable/issue-11225-3.rs create mode 100644 tests/ui/reachable/unreachable-arm.rs create mode 100644 tests/ui/reachable/unreachable-arm.stderr create mode 100644 tests/ui/reachable/unreachable-code-ret.rs create mode 100644 tests/ui/reachable/unreachable-code-ret.stderr create mode 100644 tests/ui/reachable/unreachable-code.rs create mode 100644 tests/ui/reachable/unreachable-code.stderr create mode 100644 tests/ui/reachable/unreachable-in-call.rs create mode 100644 tests/ui/reachable/unreachable-in-call.stderr create mode 100644 tests/ui/reachable/unreachable-loop-patterns.rs create mode 100644 tests/ui/reachable/unreachable-loop-patterns.stderr create mode 100644 tests/ui/reachable/unreachable-try-pattern.rs create mode 100644 tests/ui/reachable/unreachable-try-pattern.stderr create mode 100644 tests/ui/reachable/unreachable-variant.rs create mode 100644 tests/ui/reachable/unreachable-variant.stderr create mode 100644 tests/ui/reachable/unwarned-match-on-never.rs create mode 100644 tests/ui/reachable/unwarned-match-on-never.stderr create mode 100644 tests/ui/realloc-16687.rs create mode 100644 tests/ui/reassign-ref-mut.rs create mode 100644 tests/ui/reassign-ref-mut.stderr create mode 100644 tests/ui/recursion/auxiliary/recursive_reexports.rs create mode 100644 tests/ui/recursion/instantiable.rs create mode 100644 tests/ui/recursion/issue-26548-recursion-via-normalize.rs create mode 100644 tests/ui/recursion/issue-26548-recursion-via-normalize.stderr create mode 100644 tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr create mode 100644 tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs create mode 100644 tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr create mode 100644 tests/ui/recursion/issue-83150.rs create mode 100644 tests/ui/recursion/issue-83150.stderr create mode 100644 tests/ui/recursion/issue-86784.rs create mode 100644 tests/ui/recursion/issue-95134.rs create mode 100644 tests/ui/recursion/recursion.polonius.stderr create mode 100644 tests/ui/recursion/recursion.rs create mode 100644 tests/ui/recursion/recursion.stderr create mode 100644 tests/ui/recursion/recursive-enum.rs create mode 100644 tests/ui/recursion/recursive-enum.stderr create mode 100644 tests/ui/recursion/recursive-reexports.rs create mode 100644 tests/ui/recursion/recursive-reexports.stderr create mode 100644 tests/ui/recursion/recursive-requirements.rs create mode 100644 tests/ui/recursion/recursive-requirements.stderr create mode 100644 tests/ui/recursion/recursive-static-definition.rs create mode 100644 tests/ui/recursion/recursive-static-definition.stderr create mode 100644 tests/ui/recursion/recursive-types-are-not-uninhabited.rs create mode 100644 tests/ui/recursion/recursive-types-are-not-uninhabited.stderr create mode 100644 tests/ui/recursion_limit/empty.rs create mode 100644 tests/ui/recursion_limit/empty.stderr create mode 100644 tests/ui/recursion_limit/invalid_digit.rs create mode 100644 tests/ui/recursion_limit/invalid_digit.stderr create mode 100644 tests/ui/recursion_limit/invalid_digit_type.rs create mode 100644 tests/ui/recursion_limit/invalid_digit_type.stderr create mode 100644 tests/ui/recursion_limit/invalid_macro.rs create mode 100644 tests/ui/recursion_limit/invalid_macro.stderr create mode 100644 tests/ui/recursion_limit/no-value.rs create mode 100644 tests/ui/recursion_limit/no-value.stderr create mode 100644 tests/ui/recursion_limit/overflow.rs create mode 100644 tests/ui/recursion_limit/overflow.stderr create mode 100644 tests/ui/recursion_limit/zero-overflow.rs create mode 100644 tests/ui/recursion_limit/zero-overflow.stderr create mode 100644 tests/ui/recursion_limit/zero.rs create mode 100644 tests/ui/recursion_limit/zero.stderr create mode 100644 tests/ui/reexport-test-harness-main.rs create mode 100644 tests/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs create mode 100644 tests/ui/regions/closure-in-projection-issue-97405.rs create mode 100644 tests/ui/regions/closure-in-projection-issue-97405.stderr create mode 100644 tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.rs create mode 100644 tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr create mode 100644 tests/ui/regions/forall-wf-ref-reflexive.rs create mode 100644 tests/ui/regions/forall-wf-ref-reflexive.stderr create mode 100644 tests/ui/regions/forall-wf-reflexive.rs create mode 100644 tests/ui/regions/init-res-into-things.rs create mode 100644 tests/ui/regions/issue-101280.rs create mode 100644 tests/ui/regions/issue-101280.stderr create mode 100644 tests/ui/regions/issue-102374.rs create mode 100644 tests/ui/regions/issue-102374.stderr create mode 100644 tests/ui/regions/issue-102392.rs create mode 100644 tests/ui/regions/issue-102392.stderr create mode 100644 tests/ui/regions/issue-11612.rs create mode 100644 tests/ui/regions/issue-12470.rs create mode 100644 tests/ui/regions/issue-12470.stderr create mode 100644 tests/ui/regions/issue-21520.rs create mode 100644 tests/ui/regions/issue-24085.rs create mode 100644 tests/ui/regions/issue-26448-1.rs create mode 100644 tests/ui/regions/issue-26448-2.rs create mode 100644 tests/ui/regions/issue-26448-3.rs create mode 100644 tests/ui/regions/issue-2718.rs create mode 100644 tests/ui/regions/issue-28848.rs create mode 100644 tests/ui/regions/issue-28848.stderr create mode 100644 tests/ui/regions/issue-5243.rs create mode 100644 tests/ui/regions/issue-56537-closure-uses-region-from-container.rs create mode 100644 tests/ui/regions/issue-6157.rs create mode 100644 tests/ui/regions/issue-72051-member-region-hang.rs create mode 100644 tests/ui/regions/issue-78262.base.stderr create mode 100644 tests/ui/regions/issue-78262.polonius.stderr create mode 100644 tests/ui/regions/issue-78262.rs create mode 100644 tests/ui/regions/outlives-with-missing.rs create mode 100644 tests/ui/regions/outlives-with-missing.stderr create mode 100644 tests/ui/regions/owned-implies-static.rs create mode 100644 tests/ui/regions/rcvr-borrowed-to-region.rs create mode 100644 tests/ui/regions/region-borrow-params-issue-29793-big.rs create mode 100644 tests/ui/regions/region-borrow-params-issue-29793-big.stderr create mode 100644 tests/ui/regions/region-borrow-params-issue-29793-small.rs create mode 100644 tests/ui/regions/region-borrow-params-issue-29793-small.stderr create mode 100644 tests/ui/regions/region-bound-extra-bound-in-inherent-impl.rs create mode 100644 tests/ui/regions/region-bound-on-closure-outlives-call.rs create mode 100644 tests/ui/regions/region-bound-on-closure-outlives-call.stderr create mode 100644 tests/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs create mode 100644 tests/ui/regions/region-bounds-on-objects-and-type-parameters.rs create mode 100644 tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr create mode 100644 tests/ui/regions/region-invariant-static-error-reporting.rs create mode 100644 tests/ui/regions/region-invariant-static-error-reporting.stderr create mode 100644 tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs create mode 100644 tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr create mode 100644 tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs create mode 100644 tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr create mode 100644 tests/ui/regions/region-object-lifetime-1.rs create mode 100644 tests/ui/regions/region-object-lifetime-2.rs create mode 100644 tests/ui/regions/region-object-lifetime-2.stderr create mode 100644 tests/ui/regions/region-object-lifetime-3.rs create mode 100644 tests/ui/regions/region-object-lifetime-4.rs create mode 100644 tests/ui/regions/region-object-lifetime-4.stderr create mode 100644 tests/ui/regions/region-object-lifetime-5.rs create mode 100644 tests/ui/regions/region-object-lifetime-5.stderr create mode 100644 tests/ui/regions/region-object-lifetime-in-coercion.rs create mode 100644 tests/ui/regions/region-object-lifetime-in-coercion.stderr create mode 100644 tests/ui/regions/regions-addr-of-arg.rs create mode 100644 tests/ui/regions/regions-addr-of-arg.stderr create mode 100644 tests/ui/regions/regions-addr-of-interior-of-unique-box.rs create mode 100644 tests/ui/regions/regions-addr-of-ret.rs create mode 100644 tests/ui/regions/regions-addr-of-self.rs create mode 100644 tests/ui/regions/regions-addr-of-self.stderr create mode 100644 tests/ui/regions/regions-addr-of-upvar-self.rs create mode 100644 tests/ui/regions/regions-addr-of-upvar-self.stderr create mode 100644 tests/ui/regions/regions-adjusted-lvalue-op.rs create mode 100644 tests/ui/regions/regions-adjusted-lvalue-op.stderr create mode 100644 tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs create mode 100644 tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr create mode 100644 tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs create mode 100644 tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr create mode 100644 tests/ui/regions/regions-assoc-type-region-bound.rs create mode 100644 tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs create mode 100644 tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr create mode 100644 tests/ui/regions/regions-assoc-type-static-bound.rs create mode 100644 tests/ui/regions/regions-borrow-at.rs create mode 100644 tests/ui/regions/regions-borrow-evec-fixed.rs create mode 100644 tests/ui/regions/regions-borrow-evec-uniq.rs create mode 100644 tests/ui/regions/regions-borrow-uniq.rs create mode 100644 tests/ui/regions/regions-bot.rs create mode 100644 tests/ui/regions/regions-bound-lists-feature-gate-2.rs create mode 100644 tests/ui/regions/regions-bound-lists-feature-gate.rs create mode 100644 tests/ui/regions/regions-bounded-by-trait-requiring-static.rs create mode 100644 tests/ui/regions/regions-bounded-by-trait-requiring-static.stderr create mode 100644 tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs create mode 100644 tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr create mode 100644 tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs create mode 100644 tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr create mode 100644 tests/ui/regions/regions-bounded-method-type-parameters.rs create mode 100644 tests/ui/regions/regions-bounded-method-type-parameters.stderr create mode 100644 tests/ui/regions/regions-bounds.rs create mode 100644 tests/ui/regions/regions-bounds.stderr create mode 100644 tests/ui/regions/regions-close-associated-type-into-object.rs create mode 100644 tests/ui/regions/regions-close-associated-type-into-object.stderr create mode 100644 tests/ui/regions/regions-close-object-into-object-1.rs create mode 100644 tests/ui/regions/regions-close-object-into-object-1.stderr create mode 100644 tests/ui/regions/regions-close-object-into-object-2.rs create mode 100644 tests/ui/regions/regions-close-object-into-object-2.stderr create mode 100644 tests/ui/regions/regions-close-object-into-object-3.rs create mode 100644 tests/ui/regions/regions-close-object-into-object-3.stderr create mode 100644 tests/ui/regions/regions-close-object-into-object-4.rs create mode 100644 tests/ui/regions/regions-close-object-into-object-4.stderr create mode 100644 tests/ui/regions/regions-close-object-into-object-5.rs create mode 100644 tests/ui/regions/regions-close-object-into-object-5.stderr create mode 100644 tests/ui/regions/regions-close-over-type-parameter-1.rs create mode 100644 tests/ui/regions/regions-close-over-type-parameter-1.stderr create mode 100644 tests/ui/regions/regions-close-over-type-parameter-multiple.rs create mode 100644 tests/ui/regions/regions-close-over-type-parameter-multiple.stderr create mode 100644 tests/ui/regions/regions-close-over-type-parameter-successfully.rs create mode 100644 tests/ui/regions/regions-close-param-into-object.rs create mode 100644 tests/ui/regions/regions-close-param-into-object.stderr create mode 100644 tests/ui/regions/regions-copy-closure.rs create mode 100644 tests/ui/regions/regions-creating-enums.rs create mode 100644 tests/ui/regions/regions-creating-enums.stderr create mode 100644 tests/ui/regions/regions-creating-enums2.rs create mode 100644 tests/ui/regions/regions-creating-enums3.rs create mode 100644 tests/ui/regions/regions-creating-enums3.stderr create mode 100644 tests/ui/regions/regions-creating-enums4.rs create mode 100644 tests/ui/regions/regions-creating-enums4.stderr create mode 100644 tests/ui/regions/regions-creating-enums5.rs create mode 100644 tests/ui/regions/regions-debruijn-of-object.rs create mode 100644 tests/ui/regions/regions-dependent-addr-of.rs create mode 100644 tests/ui/regions/regions-dependent-autofn.rs create mode 100644 tests/ui/regions/regions-dependent-autoslice.rs create mode 100644 tests/ui/regions/regions-dependent-let-ref.rs create mode 100644 tests/ui/regions/regions-early-bound-error-method.rs create mode 100644 tests/ui/regions/regions-early-bound-error-method.stderr create mode 100644 tests/ui/regions/regions-early-bound-error.rs create mode 100644 tests/ui/regions/regions-early-bound-error.stderr create mode 100644 tests/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs create mode 100644 tests/ui/regions/regions-early-bound-trait-param.rs create mode 100644 tests/ui/regions/regions-early-bound-used-in-bound-method.rs create mode 100644 tests/ui/regions/regions-early-bound-used-in-bound.rs create mode 100644 tests/ui/regions/regions-early-bound-used-in-type-param.rs create mode 100644 tests/ui/regions/regions-escape-into-other-fn.rs create mode 100644 tests/ui/regions/regions-escape-method.rs create mode 100644 tests/ui/regions/regions-escape-method.stderr create mode 100644 tests/ui/regions/regions-escape-via-trait-or-not.rs create mode 100644 tests/ui/regions/regions-escape-via-trait-or-not.stderr create mode 100644 tests/ui/regions/regions-expl-self.rs create mode 100644 tests/ui/regions/regions-fn-subtyping-2.rs create mode 100644 tests/ui/regions/regions-fn-subtyping-return-static-fail.rs create mode 100644 tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr create mode 100644 tests/ui/regions/regions-fn-subtyping-return-static.rs create mode 100644 tests/ui/regions/regions-fn-subtyping.rs create mode 100644 tests/ui/regions/regions-free-region-ordering-callee-4.rs create mode 100644 tests/ui/regions/regions-free-region-ordering-callee-4.stderr create mode 100644 tests/ui/regions/regions-free-region-ordering-callee.rs create mode 100644 tests/ui/regions/regions-free-region-ordering-callee.stderr create mode 100644 tests/ui/regions/regions-free-region-ordering-caller.rs create mode 100644 tests/ui/regions/regions-free-region-ordering-caller.stderr create mode 100644 tests/ui/regions/regions-free-region-ordering-caller1.rs create mode 100644 tests/ui/regions/regions-free-region-ordering-caller1.stderr create mode 100644 tests/ui/regions/regions-free-region-ordering-incorrect.rs create mode 100644 tests/ui/regions/regions-free-region-ordering-incorrect.stderr create mode 100644 tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs create mode 100644 tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr create mode 100644 tests/ui/regions/regions-glb-free-free.rs create mode 100644 tests/ui/regions/regions-glb-free-free.stderr create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-1.rs create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-2.rs create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-3.rs create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-4.rs create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs create mode 100644 tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr create mode 100644 tests/ui/regions/regions-in-enums-anon.rs create mode 100644 tests/ui/regions/regions-in-enums-anon.stderr create mode 100644 tests/ui/regions/regions-in-enums.rs create mode 100644 tests/ui/regions/regions-in-enums.stderr create mode 100644 tests/ui/regions/regions-in-structs-anon.rs create mode 100644 tests/ui/regions/regions-in-structs-anon.stderr create mode 100644 tests/ui/regions/regions-in-structs.rs create mode 100644 tests/ui/regions/regions-in-structs.stderr create mode 100644 tests/ui/regions/regions-infer-at-fn-not-param.rs create mode 100644 tests/ui/regions/regions-infer-at-fn-not-param.stderr create mode 100644 tests/ui/regions/regions-infer-borrow-scope-addr-of.rs create mode 100644 tests/ui/regions/regions-infer-borrow-scope-too-big.rs create mode 100644 tests/ui/regions/regions-infer-borrow-scope-too-big.stderr create mode 100644 tests/ui/regions/regions-infer-borrow-scope-view.rs create mode 100644 tests/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs create mode 100644 tests/ui/regions/regions-infer-borrow-scope.rs create mode 100644 tests/ui/regions/regions-infer-bound-from-trait-self.rs create mode 100644 tests/ui/regions/regions-infer-bound-from-trait-self.stderr create mode 100644 tests/ui/regions/regions-infer-bound-from-trait.rs create mode 100644 tests/ui/regions/regions-infer-bound-from-trait.stderr create mode 100644 tests/ui/regions/regions-infer-call-2.rs create mode 100644 tests/ui/regions/regions-infer-call-3.rs create mode 100644 tests/ui/regions/regions-infer-call-3.stderr create mode 100644 tests/ui/regions/regions-infer-call.rs create mode 100644 tests/ui/regions/regions-infer-contravariance-due-to-decl.rs create mode 100644 tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr create mode 100644 tests/ui/regions/regions-infer-contravariance-due-to-ret.rs create mode 100644 tests/ui/regions/regions-infer-covariance-due-to-decl.rs create mode 100644 tests/ui/regions/regions-infer-covariance-due-to-decl.stderr create mode 100644 tests/ui/regions/regions-infer-invariance-due-to-decl.rs create mode 100644 tests/ui/regions/regions-infer-invariance-due-to-decl.stderr create mode 100644 tests/ui/regions/regions-infer-invariance-due-to-mutability-3.rs create mode 100644 tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr create mode 100644 tests/ui/regions/regions-infer-invariance-due-to-mutability-4.rs create mode 100644 tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr create mode 100644 tests/ui/regions/regions-infer-not-param.rs create mode 100644 tests/ui/regions/regions-infer-not-param.stderr create mode 100644 tests/ui/regions/regions-infer-paramd-indirect.rs create mode 100644 tests/ui/regions/regions-infer-paramd-indirect.stderr create mode 100644 tests/ui/regions/regions-infer-proc-static-upvar.rs create mode 100644 tests/ui/regions/regions-infer-proc-static-upvar.stderr create mode 100644 tests/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs create mode 100644 tests/ui/regions/regions-infer-region-in-fn-but-not-type.rs create mode 100644 tests/ui/regions/regions-infer-static-from-proc.rs create mode 100644 tests/ui/regions/regions-issue-21422.rs create mode 100644 tests/ui/regions/regions-issue-22246.rs create mode 100644 tests/ui/regions/regions-lifetime-bounds-on-fns.rs create mode 100644 tests/ui/regions/regions-lifetime-bounds-on-fns.stderr create mode 100644 tests/ui/regions/regions-lifetime-nonfree-late-bound.rs create mode 100644 tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs create mode 100644 tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr create mode 100644 tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs create mode 100644 tests/ui/regions/regions-link-fn-args.rs create mode 100644 tests/ui/regions/regions-lub-ref-ref-rc.rs create mode 100644 tests/ui/regions/regions-mock-codegen.rs create mode 100644 tests/ui/regions/regions-name-duplicated.rs create mode 100644 tests/ui/regions/regions-name-duplicated.stderr create mode 100644 tests/ui/regions/regions-name-static.rs create mode 100644 tests/ui/regions/regions-name-static.stderr create mode 100644 tests/ui/regions/regions-name-undeclared.rs create mode 100644 tests/ui/regions/regions-name-undeclared.stderr create mode 100644 tests/ui/regions/regions-nested-fns-2.rs create mode 100644 tests/ui/regions/regions-nested-fns-2.stderr create mode 100644 tests/ui/regions/regions-nested-fns.rs create mode 100644 tests/ui/regions/regions-nested-fns.stderr create mode 100644 tests/ui/regions/regions-no-bound-in-argument-cleanup.rs create mode 100644 tests/ui/regions/regions-no-variance-from-fn-generics.rs create mode 100644 tests/ui/regions/regions-normalize-in-where-clause-list.rs create mode 100644 tests/ui/regions/regions-normalize-in-where-clause-list.stderr create mode 100644 tests/ui/regions/regions-nullary-variant.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-enum-region.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-enum-type.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-struct-region.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs create mode 100644 tests/ui/regions/regions-outlives-nominal-type-struct-type.rs create mode 100644 tests/ui/regions/regions-outlives-projection-container-hrtb.rs create mode 100644 tests/ui/regions/regions-outlives-projection-container-hrtb.stderr create mode 100644 tests/ui/regions/regions-outlives-projection-container-wc.rs create mode 100644 tests/ui/regions/regions-outlives-projection-container-wc.stderr create mode 100644 tests/ui/regions/regions-outlives-projection-container.rs create mode 100644 tests/ui/regions/regions-outlives-projection-container.stderr create mode 100644 tests/ui/regions/regions-outlives-projection-hrtype.rs create mode 100644 tests/ui/regions/regions-outlives-projection-trait-def.rs create mode 100644 tests/ui/regions/regions-outlives-scalar.rs create mode 100644 tests/ui/regions/regions-params.rs create mode 100644 tests/ui/regions/regions-pattern-typing-issue-19552.rs create mode 100644 tests/ui/regions/regions-pattern-typing-issue-19552.stderr create mode 100644 tests/ui/regions/regions-pattern-typing-issue-19997.rs create mode 100644 tests/ui/regions/regions-pattern-typing-issue-19997.stderr create mode 100644 tests/ui/regions/regions-proc-bound-capture.rs create mode 100644 tests/ui/regions/regions-proc-bound-capture.stderr create mode 100644 tests/ui/regions/regions-reassign-let-bound-pointer.rs create mode 100644 tests/ui/regions/regions-reassign-match-bound-pointer.rs create mode 100644 tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs create mode 100644 tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr create mode 100644 tests/ui/regions/regions-reborrow-from-shorter-mut-ref.rs create mode 100644 tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr create mode 100644 tests/ui/regions/regions-ref-in-fn-arg.rs create mode 100644 tests/ui/regions/regions-ref-in-fn-arg.stderr create mode 100644 tests/ui/regions/regions-refcell.rs create mode 100644 tests/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs create mode 100644 tests/ui/regions/regions-ret-borrowed-1.rs create mode 100644 tests/ui/regions/regions-ret-borrowed-1.stderr create mode 100644 tests/ui/regions/regions-ret-borrowed.rs create mode 100644 tests/ui/regions/regions-ret-borrowed.stderr create mode 100644 tests/ui/regions/regions-ret.rs create mode 100644 tests/ui/regions/regions-ret.stderr create mode 100644 tests/ui/regions/regions-return-interior-of-option.rs create mode 100644 tests/ui/regions/regions-return-ref-to-upvar-issue-17403.rs create mode 100644 tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr create mode 100644 tests/ui/regions/regions-return-stack-allocated-vec.rs create mode 100644 tests/ui/regions/regions-return-stack-allocated-vec.stderr create mode 100644 tests/ui/regions/regions-scope-chain-example.rs create mode 100644 tests/ui/regions/regions-self-impls.rs create mode 100644 tests/ui/regions/regions-self-in-enums.rs create mode 100644 tests/ui/regions/regions-simple.rs create mode 100644 tests/ui/regions/regions-static-bound-rpass.rs create mode 100644 tests/ui/regions/regions-static-bound-rpass.stderr create mode 100644 tests/ui/regions/regions-static-bound.rs create mode 100644 tests/ui/regions/regions-static-bound.stderr create mode 100644 tests/ui/regions/regions-static-closure.rs create mode 100644 tests/ui/regions/regions-steal-closure.rs create mode 100644 tests/ui/regions/regions-steal-closure.stderr create mode 100644 tests/ui/regions/regions-trait-1.rs create mode 100644 tests/ui/regions/regions-trait-object-1.rs create mode 100644 tests/ui/regions/regions-trait-object-subtyping.rs create mode 100644 tests/ui/regions/regions-trait-object-subtyping.stderr create mode 100644 tests/ui/regions/regions-trait-variance.rs create mode 100644 tests/ui/regions/regions-trait-variance.stderr create mode 100644 tests/ui/regions/regions-undeclared.rs create mode 100644 tests/ui/regions/regions-undeclared.stderr create mode 100644 tests/ui/regions/regions-var-type-out-of-scope.rs create mode 100644 tests/ui/regions/regions-var-type-out-of-scope.stderr create mode 100644 tests/ui/regions/regions-variance-contravariant-use-contravariant.rs create mode 100644 tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs create mode 100644 tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr create mode 100644 tests/ui/regions/regions-variance-contravariant-use-covariant.rs create mode 100644 tests/ui/regions/regions-variance-contravariant-use-covariant.stderr create mode 100644 tests/ui/regions/regions-variance-covariant-use-contravariant.rs create mode 100644 tests/ui/regions/regions-variance-covariant-use-contravariant.stderr create mode 100644 tests/ui/regions/regions-variance-covariant-use-covariant.rs create mode 100644 tests/ui/regions/regions-variance-invariant-use-contravariant.rs create mode 100644 tests/ui/regions/regions-variance-invariant-use-contravariant.stderr create mode 100644 tests/ui/regions/regions-variance-invariant-use-covariant.rs create mode 100644 tests/ui/regions/regions-variance-invariant-use-covariant.stderr create mode 100644 tests/ui/regions/regions-wf-trait-object.rs create mode 100644 tests/ui/regions/regions-wf-trait-object.stderr create mode 100644 tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs create mode 100644 tests/ui/regions/type-param-outlives-reempty-issue-74429.rs create mode 100644 tests/ui/regions/wf-bound-region-in-object-type.rs create mode 100644 tests/ui/reify-intrinsic.rs create mode 100644 tests/ui/reify-intrinsic.stderr create mode 100644 tests/ui/removing-extern-crate.fixed create mode 100644 tests/ui/removing-extern-crate.rs create mode 100644 tests/ui/removing-extern-crate.stderr create mode 100644 tests/ui/repeat-expr/infer.rs create mode 100644 tests/ui/repeat-expr/repeat-expr-in-static.rs create mode 100644 tests/ui/repeat-expr/repeat-to-run-dtor-twice.rs create mode 100644 tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr create mode 100644 tests/ui/repeat-expr/repeat_count.rs create mode 100644 tests/ui/repeat-expr/repeat_count.stderr create mode 100644 tests/ui/repr/align-with-extern-c-fn.rs create mode 100644 tests/ui/repr/aligned_enum_cast.rs create mode 100644 tests/ui/repr/attr-usage-repr.rs create mode 100644 tests/ui/repr/attr-usage-repr.stderr create mode 100644 tests/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs create mode 100644 tests/ui/repr/invalid_repr_list_help.rs create mode 100644 tests/ui/repr/invalid_repr_list_help.stderr create mode 100644 tests/ui/repr/issue-83505-repr-simd.rs create mode 100644 tests/ui/repr/issue-83505-repr-simd.stderr create mode 100644 tests/ui/repr/issue-83921-ice.rs create mode 100644 tests/ui/repr/issue-83921-ice.stderr create mode 100644 tests/ui/repr/repr-align-assign.fixed create mode 100644 tests/ui/repr/repr-align-assign.rs create mode 100644 tests/ui/repr/repr-align-assign.stderr create mode 100644 tests/ui/repr/repr-align.rs create mode 100644 tests/ui/repr/repr-align.stderr create mode 100644 tests/ui/repr/repr-disallow-on-variant.rs create mode 100644 tests/ui/repr/repr-disallow-on-variant.stderr create mode 100644 tests/ui/repr/repr-packed-contains-align.rs create mode 100644 tests/ui/repr/repr-packed-contains-align.stderr create mode 100644 tests/ui/repr/repr-transparent-issue-87496.rs create mode 100644 tests/ui/repr/repr-transparent-issue-87496.stderr create mode 100644 tests/ui/repr/repr-transparent-non-exhaustive.rs create mode 100644 tests/ui/repr/repr-transparent-non-exhaustive.stderr create mode 100644 tests/ui/repr/repr-transparent-other-items.rs create mode 100644 tests/ui/repr/repr-transparent-other-items.stderr create mode 100644 tests/ui/repr/repr-transparent-other-reprs.rs create mode 100644 tests/ui/repr/repr-transparent-other-reprs.stderr create mode 100644 tests/ui/repr/repr-transparent.rs create mode 100644 tests/ui/repr/repr-transparent.stderr create mode 100644 tests/ui/repr/repr.rs create mode 100644 tests/ui/repr/repr.stderr create mode 100644 tests/ui/repr/repr_c_int_align.rs create mode 100644 tests/ui/repr/transparent-enum-too-many-variants.rs create mode 100644 tests/ui/repr/transparent-enum-too-many-variants.stderr create mode 100644 tests/ui/reserved/reserved-attr-on-macro.rs create mode 100644 tests/ui/reserved/reserved-attr-on-macro.stderr create mode 100644 tests/ui/reserved/reserved-become.rs create mode 100644 tests/ui/reserved/reserved-become.stderr create mode 100644 tests/ui/resolve/associated-fn-called-as-fn.rs create mode 100644 tests/ui/resolve/associated-fn-called-as-fn.stderr create mode 100644 tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo.rs create mode 100644 tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo2.rs create mode 100644 tests/ui/resolve/auxiliary/extern-prelude-vec.rs create mode 100644 tests/ui/resolve/auxiliary/extern-prelude.rs create mode 100644 tests/ui/resolve/auxiliary/issue-19452-aux.rs create mode 100644 tests/ui/resolve/auxiliary/issue-21221-3.rs create mode 100644 tests/ui/resolve/auxiliary/issue-21221-4.rs create mode 100644 tests/ui/resolve/auxiliary/issue-30535.rs create mode 100644 tests/ui/resolve/auxiliary/issue-3907.rs create mode 100644 tests/ui/resolve/auxiliary/issue-80079.rs create mode 100644 tests/ui/resolve/auxiliary/namespaced_enums.rs create mode 100644 tests/ui/resolve/auxiliary/privacy-struct-ctor.rs create mode 100644 tests/ui/resolve/bad-env-capture.rs create mode 100644 tests/ui/resolve/bad-env-capture.stderr create mode 100644 tests/ui/resolve/bad-env-capture2.rs create mode 100644 tests/ui/resolve/bad-env-capture2.stderr create mode 100644 tests/ui/resolve/bad-env-capture3.rs create mode 100644 tests/ui/resolve/bad-env-capture3.stderr create mode 100644 tests/ui/resolve/bad-expr-path.rs create mode 100644 tests/ui/resolve/bad-expr-path.stderr create mode 100644 tests/ui/resolve/bad-expr-path2.rs create mode 100644 tests/ui/resolve/bad-expr-path2.stderr create mode 100644 tests/ui/resolve/bad-module.rs create mode 100644 tests/ui/resolve/bad-module.stderr create mode 100644 tests/ui/resolve/bad-type-env-capture.rs create mode 100644 tests/ui/resolve/bad-type-env-capture.stderr create mode 100644 tests/ui/resolve/blind-item-local-shadow.rs create mode 100644 tests/ui/resolve/blind-item-mixed-crate-use-item.rs create mode 100644 tests/ui/resolve/blind-item-mixed-use-item.rs create mode 100644 tests/ui/resolve/block-with-trait-parent.rs create mode 100644 tests/ui/resolve/crate-called-as-function.rs create mode 100644 tests/ui/resolve/crate-called-as-function.stderr create mode 100644 tests/ui/resolve/crate-in-paths.rs create mode 100644 tests/ui/resolve/crate-in-paths.stderr create mode 100644 tests/ui/resolve/editions-crate-root-2015.rs create mode 100644 tests/ui/resolve/editions-crate-root-2015.stderr create mode 100644 tests/ui/resolve/editions-crate-root-2018.rs create mode 100644 tests/ui/resolve/editions-crate-root-2018.stderr create mode 100644 tests/ui/resolve/enums-are-namespaced-xc.rs create mode 100644 tests/ui/resolve/enums-are-namespaced-xc.stderr create mode 100644 tests/ui/resolve/enums-pats-not-idents.rs create mode 100644 tests/ui/resolve/enums-pats-not-idents.stderr create mode 100644 tests/ui/resolve/export-fully-qualified.rs create mode 100644 tests/ui/resolve/export-fully-qualified.stderr create mode 100644 tests/ui/resolve/extern-prelude-fail.rs create mode 100644 tests/ui/resolve/extern-prelude-fail.stderr create mode 100644 tests/ui/resolve/extern-prelude.rs create mode 100644 tests/ui/resolve/filter-intrinsics.rs create mode 100644 tests/ui/resolve/filter-intrinsics.stderr create mode 100644 tests/ui/resolve/impl-items-vis-unresolved.rs create mode 100644 tests/ui/resolve/impl-items-vis-unresolved.stderr create mode 100644 tests/ui/resolve/issue-100365.rs create mode 100644 tests/ui/resolve/issue-100365.stderr create mode 100644 tests/ui/resolve/issue-101749-2.rs create mode 100644 tests/ui/resolve/issue-101749-2.stderr create mode 100644 tests/ui/resolve/issue-101749.fixed create mode 100644 tests/ui/resolve/issue-101749.rs create mode 100644 tests/ui/resolve/issue-101749.stderr create mode 100644 tests/ui/resolve/issue-10200.rs create mode 100644 tests/ui/resolve/issue-10200.stderr create mode 100644 tests/ui/resolve/issue-102946.rs create mode 100644 tests/ui/resolve/issue-102946.stderr create mode 100644 tests/ui/resolve/issue-103202.rs create mode 100644 tests/ui/resolve/issue-103202.stderr create mode 100644 tests/ui/resolve/issue-103474.rs create mode 100644 tests/ui/resolve/issue-103474.stderr create mode 100644 tests/ui/resolve/issue-104700-inner_scope.rs create mode 100644 tests/ui/resolve/issue-104700-inner_scope.stderr create mode 100644 tests/ui/resolve/issue-105069.rs create mode 100644 tests/ui/resolve/issue-105069.stderr create mode 100644 tests/ui/resolve/issue-12796.rs create mode 100644 tests/ui/resolve/issue-12796.stderr create mode 100644 tests/ui/resolve/issue-14254.rs create mode 100644 tests/ui/resolve/issue-14254.stderr create mode 100644 tests/ui/resolve/issue-16058.rs create mode 100644 tests/ui/resolve/issue-16058.stderr create mode 100644 tests/ui/resolve/issue-17518.rs create mode 100644 tests/ui/resolve/issue-17518.stderr create mode 100644 tests/ui/resolve/issue-18252.rs create mode 100644 tests/ui/resolve/issue-18252.stderr create mode 100644 tests/ui/resolve/issue-19452.rs create mode 100644 tests/ui/resolve/issue-19452.stderr create mode 100644 tests/ui/resolve/issue-21221-1.rs create mode 100644 tests/ui/resolve/issue-21221-1.stderr create mode 100644 tests/ui/resolve/issue-21221-2.rs create mode 100644 tests/ui/resolve/issue-21221-2.stderr create mode 100644 tests/ui/resolve/issue-21221-3.rs create mode 100644 tests/ui/resolve/issue-21221-3.stderr create mode 100644 tests/ui/resolve/issue-21221-4.rs create mode 100644 tests/ui/resolve/issue-21221-4.stderr create mode 100644 tests/ui/resolve/issue-22692.rs create mode 100644 tests/ui/resolve/issue-22692.stderr create mode 100644 tests/ui/resolve/issue-2330.rs create mode 100644 tests/ui/resolve/issue-2330.stderr create mode 100644 tests/ui/resolve/issue-23305.rs create mode 100644 tests/ui/resolve/issue-23305.stderr create mode 100644 tests/ui/resolve/issue-2356.rs create mode 100644 tests/ui/resolve/issue-2356.stderr create mode 100644 tests/ui/resolve/issue-23716.rs create mode 100644 tests/ui/resolve/issue-23716.stderr create mode 100644 tests/ui/resolve/issue-24968.rs create mode 100644 tests/ui/resolve/issue-24968.stderr create mode 100644 tests/ui/resolve/issue-26545.rs create mode 100644 tests/ui/resolve/issue-26545.stderr create mode 100644 tests/ui/resolve/issue-3021-c.rs create mode 100644 tests/ui/resolve/issue-3021-c.stderr create mode 100644 tests/ui/resolve/issue-3021.rs create mode 100644 tests/ui/resolve/issue-3021.stderr create mode 100644 tests/ui/resolve/issue-30535.rs create mode 100644 tests/ui/resolve/issue-30535.stderr create mode 100644 tests/ui/resolve/issue-31845.rs create mode 100644 tests/ui/resolve/issue-31845.stderr create mode 100644 tests/ui/resolve/issue-33876.rs create mode 100644 tests/ui/resolve/issue-33876.stderr create mode 100644 tests/ui/resolve/issue-35675.rs create mode 100644 tests/ui/resolve/issue-35675.stderr create mode 100644 tests/ui/resolve/issue-3907-2.rs create mode 100644 tests/ui/resolve/issue-3907-2.stderr create mode 100644 tests/ui/resolve/issue-3907.rs create mode 100644 tests/ui/resolve/issue-3907.stderr create mode 100644 tests/ui/resolve/issue-39226.rs create mode 100644 tests/ui/resolve/issue-39226.stderr create mode 100644 tests/ui/resolve/issue-39559-2.rs create mode 100644 tests/ui/resolve/issue-39559-2.stderr create mode 100644 tests/ui/resolve/issue-39559.rs create mode 100644 tests/ui/resolve/issue-39559.stderr create mode 100644 tests/ui/resolve/issue-42944.rs create mode 100644 tests/ui/resolve/issue-42944.stderr create mode 100644 tests/ui/resolve/issue-49074.rs create mode 100644 tests/ui/resolve/issue-49074.stderr create mode 100644 tests/ui/resolve/issue-5035-2.rs create mode 100644 tests/ui/resolve/issue-5035-2.stderr create mode 100644 tests/ui/resolve/issue-5035.rs create mode 100644 tests/ui/resolve/issue-5035.stderr create mode 100644 tests/ui/resolve/issue-50599.rs create mode 100644 tests/ui/resolve/issue-50599.stderr create mode 100644 tests/ui/resolve/issue-5099.rs create mode 100644 tests/ui/resolve/issue-5099.stderr create mode 100644 tests/ui/resolve/issue-54379.rs create mode 100644 tests/ui/resolve/issue-54379.stderr create mode 100644 tests/ui/resolve/issue-55673.rs create mode 100644 tests/ui/resolve/issue-55673.stderr create mode 100644 tests/ui/resolve/issue-57523.rs create mode 100644 tests/ui/resolve/issue-5927.rs create mode 100644 tests/ui/resolve/issue-5927.stderr create mode 100644 tests/ui/resolve/issue-60057.rs create mode 100644 tests/ui/resolve/issue-60057.stderr create mode 100644 tests/ui/resolve/issue-65025-extern-static-parent-generics.rs create mode 100644 tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr create mode 100644 tests/ui/resolve/issue-65035-static-with-parent-generics.rs create mode 100644 tests/ui/resolve/issue-65035-static-with-parent-generics.stderr create mode 100644 tests/ui/resolve/issue-6702.rs create mode 100644 tests/ui/resolve/issue-6702.stderr create mode 100644 tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs create mode 100644 tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr create mode 100644 tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs create mode 100644 tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr create mode 100644 tests/ui/resolve/issue-73427.rs create mode 100644 tests/ui/resolve/issue-73427.stderr create mode 100644 tests/ui/resolve/issue-80079.rs create mode 100644 tests/ui/resolve/issue-80079.stderr create mode 100644 tests/ui/resolve/issue-81508.rs create mode 100644 tests/ui/resolve/issue-81508.stderr create mode 100644 tests/ui/resolve/issue-82156.rs create mode 100644 tests/ui/resolve/issue-82156.stderr create mode 100644 tests/ui/resolve/issue-82865.rs create mode 100644 tests/ui/resolve/issue-82865.stderr create mode 100644 tests/ui/resolve/issue-85348.rs create mode 100644 tests/ui/resolve/issue-85348.stderr create mode 100644 tests/ui/resolve/issue-85671.rs create mode 100644 tests/ui/resolve/issue-88472.rs create mode 100644 tests/ui/resolve/issue-88472.stderr create mode 100644 tests/ui/resolve/issue-90113.rs create mode 100644 tests/ui/resolve/issue-90113.stderr create mode 100644 tests/ui/resolve/levenshtein.rs create mode 100644 tests/ui/resolve/levenshtein.stderr create mode 100644 tests/ui/resolve/macro-determinacy-non-module.rs create mode 100644 tests/ui/resolve/missing-in-namespace.rs create mode 100644 tests/ui/resolve/missing-in-namespace.stderr create mode 100644 tests/ui/resolve/name-clash-nullary.rs create mode 100644 tests/ui/resolve/name-clash-nullary.stderr create mode 100644 tests/ui/resolve/name-collision-in-trait-fn-sig.rs create mode 100644 tests/ui/resolve/no-implicit-prelude-nested.rs create mode 100644 tests/ui/resolve/no-implicit-prelude-nested.stderr create mode 100644 tests/ui/resolve/no-implicit-prelude.rs create mode 100644 tests/ui/resolve/no-implicit-prelude.stderr create mode 100644 tests/ui/resolve/no-std-1.rs create mode 100644 tests/ui/resolve/no-std-2.rs create mode 100644 tests/ui/resolve/no-std-3.rs create mode 100644 tests/ui/resolve/pathless-extern-ok.rs create mode 100644 tests/ui/resolve/point-at-type-parameter-shadowing-another-type.rs create mode 100644 tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr create mode 100644 tests/ui/resolve/privacy-enum-ctor.rs create mode 100644 tests/ui/resolve/privacy-enum-ctor.stderr create mode 100644 tests/ui/resolve/privacy-struct-ctor.rs create mode 100644 tests/ui/resolve/privacy-struct-ctor.stderr create mode 100644 tests/ui/resolve/raw-ident-in-path.rs create mode 100644 tests/ui/resolve/raw-ident-in-path.stderr create mode 100644 tests/ui/resolve/resolve-assoc-suggestions.rs create mode 100644 tests/ui/resolve/resolve-assoc-suggestions.stderr create mode 100644 tests/ui/resolve/resolve-bad-import-prefix.rs create mode 100644 tests/ui/resolve/resolve-bad-import-prefix.stderr create mode 100644 tests/ui/resolve/resolve-bad-visibility.rs create mode 100644 tests/ui/resolve/resolve-bad-visibility.stderr create mode 100644 tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs create mode 100644 tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr create mode 100644 tests/ui/resolve/resolve-conflict-import-vs-extern-crate.rs create mode 100644 tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr create mode 100644 tests/ui/resolve/resolve-conflict-import-vs-import.fixed create mode 100644 tests/ui/resolve/resolve-conflict-import-vs-import.rs create mode 100644 tests/ui/resolve/resolve-conflict-import-vs-import.stderr create mode 100644 tests/ui/resolve/resolve-conflict-item-vs-extern-crate.rs create mode 100644 tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr create mode 100644 tests/ui/resolve/resolve-conflict-item-vs-import.rs create mode 100644 tests/ui/resolve/resolve-conflict-item-vs-import.stderr create mode 100644 tests/ui/resolve/resolve-conflict-type-vs-import.rs create mode 100644 tests/ui/resolve/resolve-conflict-type-vs-import.stderr create mode 100644 tests/ui/resolve/resolve-hint-macro.fixed create mode 100644 tests/ui/resolve/resolve-hint-macro.rs create mode 100644 tests/ui/resolve/resolve-hint-macro.stderr create mode 100644 tests/ui/resolve/resolve-inconsistent-binding-mode.rs create mode 100644 tests/ui/resolve/resolve-inconsistent-binding-mode.stderr create mode 100644 tests/ui/resolve/resolve-inconsistent-names.rs create mode 100644 tests/ui/resolve/resolve-inconsistent-names.stderr create mode 100644 tests/ui/resolve/resolve-issue-2428.rs create mode 100644 tests/ui/resolve/resolve-label.rs create mode 100644 tests/ui/resolve/resolve-label.stderr create mode 100644 tests/ui/resolve/resolve-primitive-fallback.rs create mode 100644 tests/ui/resolve/resolve-primitive-fallback.stderr create mode 100644 tests/ui/resolve/resolve-pseudo-shadowing.rs create mode 100644 tests/ui/resolve/resolve-self-in-impl-2.rs create mode 100644 tests/ui/resolve/resolve-self-in-impl-2.stderr create mode 100644 tests/ui/resolve/resolve-self-in-impl.rs create mode 100644 tests/ui/resolve/resolve-self-in-impl.stderr create mode 100644 tests/ui/resolve/resolve-speculative-adjustment.rs create mode 100644 tests/ui/resolve/resolve-speculative-adjustment.stderr create mode 100644 tests/ui/resolve/resolve-type-param-in-item-in-trait.rs create mode 100644 tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr create mode 100644 tests/ui/resolve/resolve-unknown-trait.rs create mode 100644 tests/ui/resolve/resolve-unknown-trait.stderr create mode 100644 tests/ui/resolve/resolve-variant-assoc-item.rs create mode 100644 tests/ui/resolve/resolve-variant-assoc-item.stderr create mode 100644 tests/ui/resolve/shadow-const-param.rs create mode 100644 tests/ui/resolve/shadow-const-param.stderr create mode 100644 tests/ui/resolve/suggest-path-for-tuple-struct.rs create mode 100644 tests/ui/resolve/suggest-path-for-tuple-struct.stderr create mode 100644 tests/ui/resolve/suggest-path-instead-of-mod-dot-item.rs create mode 100644 tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr create mode 100644 tests/ui/resolve/token-error-correct-2.rs create mode 100644 tests/ui/resolve/token-error-correct-2.stderr create mode 100644 tests/ui/resolve/token-error-correct-3.rs create mode 100644 tests/ui/resolve/token-error-correct-3.stderr create mode 100644 tests/ui/resolve/token-error-correct-4.fixed create mode 100644 tests/ui/resolve/token-error-correct-4.rs create mode 100644 tests/ui/resolve/token-error-correct-4.stderr create mode 100644 tests/ui/resolve/token-error-correct.rs create mode 100644 tests/ui/resolve/token-error-correct.stderr create mode 100644 tests/ui/resolve/tuple-struct-alias.rs create mode 100644 tests/ui/resolve/tuple-struct-alias.stderr create mode 100644 tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs create mode 100644 tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr create mode 100644 tests/ui/resolve/typo-suggestion-mistyped-in-path.rs create mode 100644 tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr create mode 100644 tests/ui/resolve/typo-suggestion-named-underscore.rs create mode 100644 tests/ui/resolve/typo-suggestion-named-underscore.stderr create mode 100644 tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs create mode 100644 tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr create mode 100644 tests/ui/resolve/unresolved_static_type_field.rs create mode 100644 tests/ui/resolve/unresolved_static_type_field.stderr create mode 100644 tests/ui/resolve/use-self-in-inner-fn.rs create mode 100644 tests/ui/resolve/use-self-in-inner-fn.stderr create mode 100644 tests/ui/resolve/use_suggestion.rs create mode 100644 tests/ui/resolve/use_suggestion.stderr create mode 100644 tests/ui/resolve/use_suggestion_placement.fixed create mode 100644 tests/ui/resolve/use_suggestion_placement.rs create mode 100644 tests/ui/resolve/use_suggestion_placement.stderr create mode 100644 tests/ui/resolve/visibility-indeterminate.rs create mode 100644 tests/ui/resolve/visibility-indeterminate.stderr create mode 100644 tests/ui/resource-assign-is-not-copy.rs create mode 100644 tests/ui/resource-destruct.rs create mode 100644 tests/ui/ret-bang.rs create mode 100644 tests/ui/ret-non-nil.rs create mode 100644 tests/ui/ret-non-nil.stderr create mode 100644 tests/ui/return-disjoint-regions.rs create mode 100644 tests/ui/return-disjoint-regions.stderr create mode 100644 tests/ui/return-nil.rs create mode 100644 tests/ui/return/issue-64620.rs create mode 100644 tests/ui/return/issue-64620.stderr create mode 100644 tests/ui/return/issue-82612-return-mutable-reference.rs create mode 100644 tests/ui/return/issue-82612-return-mutable-reference.stderr create mode 100644 tests/ui/return/issue-86188-return-not-in-fn-body.rs create mode 100644 tests/ui/return/issue-86188-return-not-in-fn-body.stderr create mode 100644 tests/ui/return/return-from-diverging.rs create mode 100644 tests/ui/return/return-from-diverging.stderr create mode 100644 tests/ui/return/return-impl-trait-bad.rs create mode 100644 tests/ui/return/return-impl-trait-bad.stderr create mode 100644 tests/ui/return/return-impl-trait.fixed create mode 100644 tests/ui/return/return-impl-trait.rs create mode 100644 tests/ui/return/return-impl-trait.stderr create mode 100644 tests/ui/return/return-match-array-const.rs create mode 100644 tests/ui/return/return-match-array-const.stderr create mode 100644 tests/ui/return/return-type.rs create mode 100644 tests/ui/return/return-type.stderr create mode 100644 tests/ui/return/return-unit-from-diverging.rs create mode 100644 tests/ui/return/return-unit-from-diverging.stderr create mode 100644 tests/ui/return/tail-expr-as-potential-return.rs create mode 100644 tests/ui/return/tail-expr-as-potential-return.stderr create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs create mode 100644 tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr create mode 100644 tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs create mode 100644 tests/ui/rfc-1717-dllimport/missing-link-attr.rs create mode 100644 tests/ui/rfc-1717-dllimport/missing-link-attr.stderr create mode 100644 tests/ui/rfc-1717-dllimport/multiple-renames.rs create mode 100644 tests/ui/rfc-1717-dllimport/multiple-renames.stderr create mode 100644 tests/ui/rfc-1717-dllimport/rename-modifiers.rs create mode 100644 tests/ui/rfc-1717-dllimport/rename-modifiers.stderr create mode 100644 tests/ui/rfc-1717-dllimport/rename-to-empty.rs create mode 100644 tests/ui/rfc-1717-dllimport/rename-to-empty.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/issue-103052-1.rs create mode 100644 tests/ui/rfc-1937-termination-trait/issue-103052-1.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/issue-103052-2.rs create mode 100644 tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-for-never.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-for-str.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs create mode 100644 tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/const.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/const.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/enum.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/enum.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/explicit-mut.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/explicit-mut.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/for.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/for.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/issue-44912-or.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/lit.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/lit.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/no-double-error.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/no-double-error.stderr create mode 100644 tests/ui/rfc-2005-default-binding-mode/slice.rs create mode 100644 tests/ui/rfc-2005-default-binding-mode/slice.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/struct.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/struct.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/variant.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/variant.stderr create mode 100644 tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs create mode 100644 tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs create mode 100644 tests/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs create mode 100644 tests/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs create mode 100644 tests/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs create mode 100644 tests/ui/rfc-2091-track-caller/call-chain.rs create mode 100644 tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs create mode 100644 tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr create mode 100644 tests/ui/rfc-2091-track-caller/caller-location-intrinsic.rs create mode 100644 tests/ui/rfc-2091-track-caller/const-caller-location.rs create mode 100644 tests/ui/rfc-2091-track-caller/diverging-caller-location.rs create mode 100644 tests/ui/rfc-2091-track-caller/error-odd-syntax.rs create mode 100644 tests/ui/rfc-2091-track-caller/error-odd-syntax.stderr create mode 100644 tests/ui/rfc-2091-track-caller/error-with-invalid-abi.rs create mode 100644 tests/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr create mode 100644 tests/ui/rfc-2091-track-caller/error-with-main.rs create mode 100644 tests/ui/rfc-2091-track-caller/error-with-main.stderr create mode 100644 tests/ui/rfc-2091-track-caller/error-with-naked.rs create mode 100644 tests/ui/rfc-2091-track-caller/error-with-naked.stderr create mode 100644 tests/ui/rfc-2091-track-caller/error-with-start.rs create mode 100644 tests/ui/rfc-2091-track-caller/error-with-start.stderr create mode 100644 tests/ui/rfc-2091-track-caller/intrinsic-wrapper.rs create mode 100644 tests/ui/rfc-2091-track-caller/macro-declaration.rs create mode 100644 tests/ui/rfc-2091-track-caller/only-for-fns.rs create mode 100644 tests/ui/rfc-2091-track-caller/only-for-fns.stderr create mode 100644 tests/ui/rfc-2091-track-caller/pass.rs create mode 100644 tests/ui/rfc-2091-track-caller/std-panic-locations.rs create mode 100644 tests/ui/rfc-2091-track-caller/track-caller-attribute.rs create mode 100644 tests/ui/rfc-2091-track-caller/track-caller-ffi.rs create mode 100644 tests/ui/rfc-2091-track-caller/tracked-closure.rs create mode 100644 tests/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs create mode 100644 tests/ui/rfc-2091-track-caller/tracked-fn-ptr.rs create mode 100644 tests/ui/rfc-2091-track-caller/tracked-trait-impls.rs create mode 100644 tests/ui/rfc-2091-track-caller/tracked-trait-obj.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/cross-crate.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/cross-crate.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/dont-infer-static.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/dont-infer-static.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/enum.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/enum.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-dyn.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-dyn.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-enum.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-enum.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-projection.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-projection.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-struct.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-struct.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-union.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/explicit-union.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/issue-54467.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-enum.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-enum.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-regions.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-regions.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-structs.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-structs.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-union.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/nested-union.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/privacy.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/projection.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/projection.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/reference.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/reference.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/self-dyn.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/self-dyn.stderr create mode 100644 tests/ui/rfc-2093-infer-outlives/self-structs.rs create mode 100644 tests/ui/rfc-2093-infer-outlives/self-structs.stderr create mode 100644 tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs create mode 100644 tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr create mode 100644 tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs create mode 100644 tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/not-allowed.rs create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/single-segment.rs create mode 100644 tests/ui/rfc-2126-extern-absolute-paths/single-segment.stderr create mode 100644 tests/ui/rfc-2294-if-let-guard/bindings.rs create mode 100644 tests/ui/rfc-2294-if-let-guard/bindings.stderr create mode 100644 tests/ui/rfc-2294-if-let-guard/feature-gate.rs create mode 100644 tests/ui/rfc-2294-if-let-guard/feature-gate.stderr create mode 100644 tests/ui/rfc-2294-if-let-guard/run-pass.rs create mode 100644 tests/ui/rfc-2294-if-let-guard/typeck.rs create mode 100644 tests/ui/rfc-2294-if-let-guard/typeck.stderr create mode 100644 tests/ui/rfc-2294-if-let-guard/warns.rs create mode 100644 tests/ui/rfc-2294-if-let-guard/warns.stderr create mode 100644 tests/ui/rfc-2306/convert-id-const-with-gate.rs create mode 100644 tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs create mode 100644 tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr create mode 100644 tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs create mode 100644 tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr create mode 100644 tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs create mode 100644 tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr create mode 100644 tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs create mode 100644 tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr create mode 100644 tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs create mode 100644 tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr create mode 100644 tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs create mode 100644 tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr create mode 100644 tests/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs create mode 100644 tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs create mode 100644 tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr create mode 100644 tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs create mode 100644 tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr create mode 100644 tests/ui/rfc-2457/extern_block_nonascii_forbidden.rs create mode 100644 tests/ui/rfc-2457/extern_block_nonascii_forbidden.stderr create mode 100644 tests/ui/rfc-2457/idents-normalized.rs create mode 100644 tests/ui/rfc-2457/mod_file_nonascii_forbidden.rs create mode 100644 tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr create mode 100644 tests/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs create mode 100644 tests/ui/rfc-2457/mod_inline_nonascii_allowed.rs create mode 100644 tests/ui/rfc-2457/no_mangle_nonascii_forbidden.rs create mode 100644 tests/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/ast-pretty-check.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout create mode 100644 tests/ui/rfc-2497-if-let-chains/chains-without-let.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/chains-without-let.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/disallowed-positions.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/feature-gate.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/feature-gate.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/irrefutable-lets.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/issue-88498.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/issue-90722.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/issue-92145.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/issue-93150.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/issue-93150.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/issue-99938.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/no-double-assigments.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/protect-precedences.rs create mode 100644 tests/ui/rfc-2497-if-let-chains/protect-precedences.stderr create mode 100644 tests/ui/rfc-2497-if-let-chains/then-else-blocks.rs create mode 100644 tests/ui/rfc-2565-param-attrs/attr-without-param.rs create mode 100644 tests/ui/rfc-2565-param-attrs/attr-without-param.stderr create mode 100644 tests/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs create mode 100644 tests/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs create mode 100644 tests/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-2018.rs create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-2018.stderr create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-allowed.rs create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-cfg.rs create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr create mode 100644 tests/ui/rfc-2565-param-attrs/param-attrs-pretty.rs create mode 100644 tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs create mode 100644 tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr create mode 100644 tests/ui/rfc-2627-raw-dylib/unsupported-abi.rs create mode 100644 tests/ui/rfc-2627-raw-dylib/unsupported-abi.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/assoc-type.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/call.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-closures.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-drop.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/cross-crate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/feature-gate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/gate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/gate.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/generic-bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-100222.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-102156.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-102985.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-103677.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-79450.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-88155.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-90052.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-92111.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/nested-closure.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/staged-api.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/super-traits.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/syntax.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr create mode 100644 tests/ui/rfc-2632-const-trait-impl/without-tilde.rs create mode 100644 tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr create mode 100644 tests/ui/rfcs/rfc-1014-2.rs create mode 100644 tests/ui/rfcs/rfc-1014.rs create mode 100644 tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs create mode 100644 tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs create mode 100644 tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs create mode 100644 tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs create mode 100644 tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs create mode 100644 tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs create mode 100644 tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs create mode 100644 tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs create mode 100644 tests/ui/rfcs/rfc-2302-self-struct-ctor.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs create mode 100644 tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr create mode 100644 tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs create mode 100644 tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr create mode 100644 tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs create mode 100644 tests/ui/rfcs/rfc1445/eq-allows-match.rs create mode 100644 tests/ui/rfcs/rfc1623-2.rs create mode 100644 tests/ui/rfcs/rfc1623-2.stderr create mode 100644 tests/ui/rfcs/rfc1623-3.rs create mode 100644 tests/ui/rfcs/rfc1623-3.stderr create mode 100644 tests/ui/rfcs/rfc1623.rs create mode 100644 tests/ui/rfcs/rfc1717/library-override.rs create mode 100644 tests/ui/rfcs/rfc1857-drop-order.rs create mode 100644 tests/ui/rmeta/auxiliary/rmeta-meta.rs create mode 100644 tests/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs create mode 100644 tests/ui/rmeta/auxiliary/rmeta-rlib.rs create mode 100644 tests/ui/rmeta/auxiliary/rmeta-rmeta.rs create mode 100644 tests/ui/rmeta/emit-artifact-notifications.polonius.stderr create mode 100644 tests/ui/rmeta/emit-artifact-notifications.rs create mode 100644 tests/ui/rmeta/emit-artifact-notifications.stderr create mode 100644 tests/ui/rmeta/emit-metadata-obj.rs create mode 100644 tests/ui/rmeta/rmeta-lib-pass.rs create mode 100644 tests/ui/rmeta/rmeta-pass.rs create mode 100644 tests/ui/rmeta/rmeta-priv-warn.rs create mode 100644 tests/ui/rmeta/rmeta-rpass.rs create mode 100644 tests/ui/rmeta/rmeta.rs create mode 100644 tests/ui/rmeta/rmeta.stderr create mode 100644 tests/ui/rmeta/rmeta_lib.rs create mode 100644 tests/ui/rmeta/rmeta_lib.stderr create mode 100644 tests/ui/rmeta/rmeta_meta_main.rs create mode 100644 tests/ui/rmeta/rmeta_meta_main.stderr create mode 100644 tests/ui/runtime/atomic-print.rs create mode 100644 tests/ui/runtime/backtrace-debuginfo-aux.rs create mode 100644 tests/ui/runtime/backtrace-debuginfo.rs create mode 100644 tests/ui/runtime/native-print-no-runtime.rs create mode 100644 tests/ui/runtime/out-of-stack.rs create mode 100644 tests/ui/runtime/rt-explody-panic-payloads.rs create mode 100644 tests/ui/runtime/running-with-no-runtime.rs create mode 100644 tests/ui/runtime/signal-alternate-stack-cleanup.rs create mode 100644 tests/ui/runtime/stdout-during-shutdown.rs create mode 100644 tests/ui/runtime/stdout-during-shutdown.run.stdout create mode 100644 tests/ui/rust-2018/async-ident-allowed.rs create mode 100644 tests/ui/rust-2018/async-ident-allowed.stderr create mode 100644 tests/ui/rust-2018/async-ident.fixed create mode 100644 tests/ui/rust-2018/async-ident.rs create mode 100644 tests/ui/rust-2018/async-ident.stderr create mode 100644 tests/ui/rust-2018/auxiliary/baz.rs create mode 100644 tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs create mode 100644 tests/ui/rust-2018/auxiliary/edition-lint-paths.rs create mode 100644 tests/ui/rust-2018/auxiliary/macro-use-warned-against.rs create mode 100644 tests/ui/rust-2018/auxiliary/macro-use-warned-against2.rs create mode 100644 tests/ui/rust-2018/auxiliary/remove-extern-crate.rs create mode 100644 tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs create mode 100644 tests/ui/rust-2018/auxiliary/trait-import-suggestions.rs create mode 100644 tests/ui/rust-2018/dyn-keyword.fixed create mode 100644 tests/ui/rust-2018/dyn-keyword.rs create mode 100644 tests/ui/rust-2018/dyn-keyword.stderr create mode 100644 tests/ui/rust-2018/dyn-trait-compatibility.rs create mode 100644 tests/ui/rust-2018/dyn-trait-compatibility.stderr create mode 100644 tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed create mode 100644 tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs create mode 100644 tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives.fixed create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives.rs create mode 100644 tests/ui/rust-2018/edition-lint-infer-outlives.stderr create mode 100644 tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed create mode 100644 tests/ui/rust-2018/edition-lint-nested-empty-paths.rs create mode 100644 tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr create mode 100644 tests/ui/rust-2018/edition-lint-nested-paths.fixed create mode 100644 tests/ui/rust-2018/edition-lint-nested-paths.rs create mode 100644 tests/ui/rust-2018/edition-lint-nested-paths.stderr create mode 100644 tests/ui/rust-2018/edition-lint-paths-2018.rs create mode 100644 tests/ui/rust-2018/edition-lint-paths.fixed create mode 100644 tests/ui/rust-2018/edition-lint-paths.rs create mode 100644 tests/ui/rust-2018/edition-lint-paths.stderr create mode 100644 tests/ui/rust-2018/edition-lint-uninferable-outlives.rs create mode 100644 tests/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed create mode 100644 tests/ui/rust-2018/extern-crate-idiomatic-in-2018.rs create mode 100644 tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr create mode 100644 tests/ui/rust-2018/extern-crate-idiomatic.fixed create mode 100644 tests/ui/rust-2018/extern-crate-idiomatic.rs create mode 100644 tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed create mode 100644 tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs create mode 100644 tests/ui/rust-2018/extern-crate-rename.fixed create mode 100644 tests/ui/rust-2018/extern-crate-rename.rs create mode 100644 tests/ui/rust-2018/extern-crate-rename.stderr create mode 100644 tests/ui/rust-2018/extern-crate-submod.fixed create mode 100644 tests/ui/rust-2018/extern-crate-submod.rs create mode 100644 tests/ui/rust-2018/extern-crate-submod.stderr create mode 100644 tests/ui/rust-2018/future-proofing-locals.rs create mode 100644 tests/ui/rust-2018/future-proofing-locals.stderr create mode 100644 tests/ui/rust-2018/issue-51008-1.rs create mode 100644 tests/ui/rust-2018/issue-51008.rs create mode 100644 tests/ui/rust-2018/issue-52202-use-suggestions.rs create mode 100644 tests/ui/rust-2018/issue-52202-use-suggestions.stderr create mode 100644 tests/ui/rust-2018/issue-54006.rs create mode 100644 tests/ui/rust-2018/issue-54006.stderr create mode 100644 tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed create mode 100644 tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs create mode 100644 tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr create mode 100644 tests/ui/rust-2018/local-path-suggestions-2015.rs create mode 100644 tests/ui/rust-2018/local-path-suggestions-2015.stderr create mode 100644 tests/ui/rust-2018/local-path-suggestions-2018.rs create mode 100644 tests/ui/rust-2018/local-path-suggestions-2018.stderr create mode 100644 tests/ui/rust-2018/macro-use-warned-against.rs create mode 100644 tests/ui/rust-2018/macro-use-warned-against.stderr create mode 100644 tests/ui/rust-2018/proc-macro-crate-in-paths.rs create mode 100644 tests/ui/rust-2018/remove-extern-crate.fixed create mode 100644 tests/ui/rust-2018/remove-extern-crate.rs create mode 100644 tests/ui/rust-2018/remove-extern-crate.stderr create mode 100644 tests/ui/rust-2018/suggestions-not-always-applicable.fixed create mode 100644 tests/ui/rust-2018/suggestions-not-always-applicable.rs create mode 100644 tests/ui/rust-2018/trait-import-suggestions.rs create mode 100644 tests/ui/rust-2018/trait-import-suggestions.stderr create mode 100644 tests/ui/rust-2018/try-ident.fixed create mode 100644 tests/ui/rust-2018/try-ident.rs create mode 100644 tests/ui/rust-2018/try-ident.stderr create mode 100644 tests/ui/rust-2018/try-macro.fixed create mode 100644 tests/ui/rust-2018/try-macro.rs create mode 100644 tests/ui/rust-2018/try-macro.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity-macros.rs create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity.rs create mode 100644 tests/ui/rust-2018/uniform-paths/ambiguity.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs create mode 100644 tests/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs create mode 100644 tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs create mode 100644 tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs create mode 100644 tests/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs create mode 100644 tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs create mode 100644 tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs create mode 100644 tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/cross-crate.rs create mode 100644 tests/ui/rust-2018/uniform-paths/cross-crate.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/deadlock.rs create mode 100644 tests/ui/rust-2018/uniform-paths/deadlock.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/fn-local-enum.rs create mode 100644 tests/ui/rust-2018/uniform-paths/from-decl-macro.rs create mode 100644 tests/ui/rust-2018/uniform-paths/issue-54253.rs create mode 100644 tests/ui/rust-2018/uniform-paths/issue-54253.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/issue-55779.rs create mode 100644 tests/ui/rust-2018/uniform-paths/issue-56596-2.rs create mode 100644 tests/ui/rust-2018/uniform-paths/issue-56596.rs create mode 100644 tests/ui/rust-2018/uniform-paths/issue-56596.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/issue-87932.rs create mode 100644 tests/ui/rust-2018/uniform-paths/issue-87932.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/macro-rules.rs create mode 100644 tests/ui/rust-2018/uniform-paths/macro-rules.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/prelude-fail-2.rs create mode 100644 tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/prelude-fail.rs create mode 100644 tests/ui/rust-2018/uniform-paths/prelude-fail.stderr create mode 100644 tests/ui/rust-2018/uniform-paths/prelude.rs create mode 100644 tests/ui/rust-2018/uniform-paths/redundant.rs create mode 100644 tests/ui/rust-2018/unresolved-asterisk-imports.rs create mode 100644 tests/ui/rust-2018/unresolved-asterisk-imports.stderr create mode 100644 tests/ui/rust-2021/array-into-iter-ambiguous.fixed create mode 100644 tests/ui/rust-2021/array-into-iter-ambiguous.rs create mode 100644 tests/ui/rust-2021/array-into-iter-ambiguous.stderr create mode 100644 tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs create mode 100644 tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed create mode 100644 tests/ui/rust-2021/future-prelude-collision-generic-trait.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-generic-trait.stderr create mode 100644 tests/ui/rust-2021/future-prelude-collision-generic.fixed create mode 100644 tests/ui/rust-2021/future-prelude-collision-generic.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-generic.stderr create mode 100644 tests/ui/rust-2021/future-prelude-collision-imported.fixed create mode 100644 tests/ui/rust-2021/future-prelude-collision-imported.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-imported.stderr create mode 100644 tests/ui/rust-2021/future-prelude-collision-macros.fixed create mode 100644 tests/ui/rust-2021/future-prelude-collision-macros.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-macros.stderr create mode 100644 tests/ui/rust-2021/future-prelude-collision-shadow.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-shadow.stderr create mode 100644 tests/ui/rust-2021/future-prelude-collision-turbofish.fixed create mode 100644 tests/ui/rust-2021/future-prelude-collision-turbofish.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision-turbofish.stderr create mode 100644 tests/ui/rust-2021/future-prelude-collision-unneeded.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision.fixed create mode 100644 tests/ui/rust-2021/future-prelude-collision.rs create mode 100644 tests/ui/rust-2021/future-prelude-collision.stderr create mode 100644 tests/ui/rust-2021/generic-type-collision.fixed create mode 100644 tests/ui/rust-2021/generic-type-collision.rs create mode 100644 tests/ui/rust-2021/generic-type-collision.stderr create mode 100644 tests/ui/rust-2021/inherent-dyn-collision.fixed create mode 100644 tests/ui/rust-2021/inherent-dyn-collision.rs create mode 100644 tests/ui/rust-2021/inherent-dyn-collision.stderr create mode 100644 tests/ui/rust-2021/inherent-method-collision.rs create mode 100644 tests/ui/rust-2021/panic.rs create mode 100644 tests/ui/rust-2021/panic.stderr create mode 100644 tests/ui/rust-2021/prelude2021.rs create mode 100644 tests/ui/rust-2021/reserved-prefixes-migration.fixed create mode 100644 tests/ui/rust-2021/reserved-prefixes-migration.rs create mode 100644 tests/ui/rust-2021/reserved-prefixes-migration.stderr create mode 100644 tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs create mode 100644 tests/ui/rust-2021/reserved-prefixes-via-macro-2.stderr create mode 100644 tests/ui/rust-2021/reserved-prefixes-via-macro.rs create mode 100644 tests/ui/rust-2021/reserved-prefixes.rs create mode 100644 tests/ui/rust-2021/reserved-prefixes.stderr create mode 100644 tests/ui/rustc-error.rs create mode 100644 tests/ui/rustc-error.stderr create mode 100644 tests/ui/rustc-rust-log.rs create mode 100644 tests/ui/rustdoc/README.md create mode 100644 tests/ui/rustdoc/cfg-rustdoc.rs create mode 100644 tests/ui/rustdoc/cfg-rustdoc.stderr create mode 100644 tests/ui/rustdoc/check-doc-alias-attr-location.rs create mode 100644 tests/ui/rustdoc/check-doc-alias-attr-location.stderr create mode 100644 tests/ui/rustdoc/check-doc-alias-attr.rs create mode 100644 tests/ui/rustdoc/check-doc-alias-attr.stderr create mode 100644 tests/ui/rustdoc/deny-invalid-doc-attrs.rs create mode 100644 tests/ui/rustdoc/deny-invalid-doc-attrs.stderr create mode 100644 tests/ui/rustdoc/doc-alias-crate-level.rs create mode 100644 tests/ui/rustdoc/doc-alias-crate-level.stderr create mode 100644 tests/ui/rustdoc/doc-alias-same-name.rs create mode 100644 tests/ui/rustdoc/doc-alias-same-name.stderr create mode 100644 tests/ui/rustdoc/doc-inline-extern-crate.rs create mode 100644 tests/ui/rustdoc/doc-inline-extern-crate.stderr create mode 100644 tests/ui/rustdoc/doc-test-attr-pass.rs create mode 100644 tests/ui/rustdoc/doc-test-attr.rs create mode 100644 tests/ui/rustdoc/doc-test-attr.stderr create mode 100644 tests/ui/rustdoc/doc_keyword.rs create mode 100644 tests/ui/rustdoc/doc_keyword.stderr create mode 100644 tests/ui/rustdoc/duplicate_doc_alias.rs create mode 100644 tests/ui/rustdoc/duplicate_doc_alias.stderr create mode 100644 tests/ui/rustdoc/feature-gate-doc_primitive.rs create mode 100644 tests/ui/rustdoc/feature-gate-doc_primitive.stderr create mode 100644 tests/ui/rustdoc/hidden-doc-associated-item.rs create mode 100644 tests/ui/rustdoc/renamed-features-rustdoc_internals.rs create mode 100644 tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr create mode 100644 tests/ui/rustdoc/unterminated-doc-comment.rs create mode 100644 tests/ui/rustdoc/unterminated-doc-comment.stderr create mode 100644 tests/ui/sanitize/address.rs create mode 100644 tests/ui/sanitize/badfree.rs create mode 100644 tests/ui/sanitize/cfg.rs create mode 100644 tests/ui/sanitize/crt-static.rs create mode 100644 tests/ui/sanitize/crt-static.stderr create mode 100644 tests/ui/sanitize/hwaddress.rs create mode 100644 tests/ui/sanitize/incompatible.rs create mode 100644 tests/ui/sanitize/incompatible.stderr create mode 100644 tests/ui/sanitize/inline-always.rs create mode 100644 tests/ui/sanitize/inline-always.stderr create mode 100644 tests/ui/sanitize/issue-72154-lifetime-markers.rs create mode 100644 tests/ui/sanitize/leak.rs create mode 100644 tests/ui/sanitize/memory-eager.rs create mode 100644 tests/ui/sanitize/memory-passing.rs create mode 100644 tests/ui/sanitize/memory.rs create mode 100644 tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs create mode 100644 tests/ui/sanitize/thread.rs create mode 100644 tests/ui/sanitize/unsupported-target.rs create mode 100644 tests/ui/sanitize/unsupported-target.stderr create mode 100644 tests/ui/sanitize/use-after-scope.rs create mode 100644 tests/ui/save-analysis/emit-notifications.polonius.stderr create mode 100644 tests/ui/save-analysis/emit-notifications.rs create mode 100644 tests/ui/save-analysis/emit-notifications.stderr create mode 100644 tests/ui/save-analysis/issue-26459.rs create mode 100644 tests/ui/save-analysis/issue-26459.stderr create mode 100644 tests/ui/save-analysis/issue-37323.rs create mode 100644 tests/ui/save-analysis/issue-59134-0.rs create mode 100644 tests/ui/save-analysis/issue-59134-0.stderr create mode 100644 tests/ui/save-analysis/issue-59134-1.rs create mode 100644 tests/ui/save-analysis/issue-59134-1.stderr create mode 100644 tests/ui/save-analysis/issue-63663.rs create mode 100644 tests/ui/save-analysis/issue-64659.rs create mode 100644 tests/ui/save-analysis/issue-65411.rs create mode 100644 tests/ui/save-analysis/issue-65590.rs create mode 100644 tests/ui/save-analysis/issue-68621.rs create mode 100644 tests/ui/save-analysis/issue-68621.stderr create mode 100644 tests/ui/save-analysis/issue-72267.rs create mode 100644 tests/ui/save-analysis/issue-72267.stderr create mode 100644 tests/ui/save-analysis/issue-73020.rs create mode 100644 tests/ui/save-analysis/issue-73020.stderr create mode 100644 tests/ui/save-analysis/issue-73022.rs create mode 100644 tests/ui/save-analysis/issue-89066.rs create mode 100644 tests/ui/save-analysis/issue-89066.stderr create mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr create mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr create mode 100644 tests/ui/self/arbitrary-self-types-not-object-safe.rs create mode 100644 tests/ui/self/arbitrary_self_types_nested.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime-async.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs create mode 100644 tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr create mode 100644 tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs create mode 100644 tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs create mode 100644 tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs create mode 100644 tests/ui/self/arbitrary_self_types_silly.rs create mode 100644 tests/ui/self/arbitrary_self_types_stdlib_pointers.rs create mode 100644 tests/ui/self/arbitrary_self_types_struct.rs create mode 100644 tests/ui/self/arbitrary_self_types_trait.rs create mode 100644 tests/ui/self/arbitrary_self_types_unsized_struct.rs create mode 100644 tests/ui/self/auxiliary/explicit_self_xcrate.rs create mode 100644 tests/ui/self/builtin-superkinds-self-type.rs create mode 100644 tests/ui/self/by-value-self-in-mut-slot.rs create mode 100644 tests/ui/self/class-missing-self.rs create mode 100644 tests/ui/self/class-missing-self.stderr create mode 100644 tests/ui/self/elision/README.md create mode 100644 tests/ui/self/elision/alias-async.rs create mode 100644 tests/ui/self/elision/alias.rs create mode 100644 tests/ui/self/elision/assoc-async.rs create mode 100644 tests/ui/self/elision/assoc.rs create mode 100644 tests/ui/self/elision/lt-alias-async.rs create mode 100644 tests/ui/self/elision/lt-alias.rs create mode 100644 tests/ui/self/elision/lt-assoc-async.rs create mode 100644 tests/ui/self/elision/lt-assoc.rs create mode 100644 tests/ui/self/elision/lt-ref-self-async.rs create mode 100644 tests/ui/self/elision/lt-ref-self-async.stderr create mode 100644 tests/ui/self/elision/lt-ref-self.rs create mode 100644 tests/ui/self/elision/lt-ref-self.stderr create mode 100644 tests/ui/self/elision/lt-self-async.rs create mode 100644 tests/ui/self/elision/lt-self.rs create mode 100644 tests/ui/self/elision/lt-struct-async.rs create mode 100644 tests/ui/self/elision/lt-struct.rs create mode 100644 tests/ui/self/elision/multiple-ref-self-async.rs create mode 100644 tests/ui/self/elision/multiple-ref-self.rs create mode 100644 tests/ui/self/elision/ref-alias-async.rs create mode 100644 tests/ui/self/elision/ref-alias.rs create mode 100644 tests/ui/self/elision/ref-assoc-async.rs create mode 100644 tests/ui/self/elision/ref-assoc.rs create mode 100644 tests/ui/self/elision/ref-mut-alias-async.rs create mode 100644 tests/ui/self/elision/ref-mut-alias.rs create mode 100644 tests/ui/self/elision/ref-mut-self-async.rs create mode 100644 tests/ui/self/elision/ref-mut-self-async.stderr create mode 100644 tests/ui/self/elision/ref-mut-self.rs create mode 100644 tests/ui/self/elision/ref-mut-self.stderr create mode 100644 tests/ui/self/elision/ref-mut-struct-async.rs create mode 100644 tests/ui/self/elision/ref-mut-struct-async.stderr create mode 100644 tests/ui/self/elision/ref-mut-struct.rs create mode 100644 tests/ui/self/elision/ref-mut-struct.stderr create mode 100644 tests/ui/self/elision/ref-self-async.rs create mode 100644 tests/ui/self/elision/ref-self-async.stderr create mode 100644 tests/ui/self/elision/ref-self.rs create mode 100644 tests/ui/self/elision/ref-self.stderr create mode 100644 tests/ui/self/elision/ref-struct-async.rs create mode 100644 tests/ui/self/elision/ref-struct-async.stderr create mode 100644 tests/ui/self/elision/ref-struct.rs create mode 100644 tests/ui/self/elision/ref-struct.stderr create mode 100644 tests/ui/self/elision/self-async.rs create mode 100644 tests/ui/self/elision/self.rs create mode 100644 tests/ui/self/elision/struct-async.rs create mode 100644 tests/ui/self/elision/struct.rs create mode 100644 tests/ui/self/explicit-self-closures.rs create mode 100644 tests/ui/self/explicit-self-generic.rs create mode 100644 tests/ui/self/explicit-self-objects-uniq.rs create mode 100644 tests/ui/self/explicit-self.rs create mode 100644 tests/ui/self/explicit_self_xcrate_exe.rs create mode 100644 tests/ui/self/issue-61882-2.rs create mode 100644 tests/ui/self/issue-61882-2.stderr create mode 100644 tests/ui/self/issue-61882.rs create mode 100644 tests/ui/self/issue-61882.stderr create mode 100644 tests/ui/self/move-self.rs create mode 100644 tests/ui/self/object-safety-sized-self-by-value-self.rs create mode 100644 tests/ui/self/object-safety-sized-self-generic-method.rs create mode 100644 tests/ui/self/object-safety-sized-self-return-Self.rs create mode 100644 tests/ui/self/objects-owned-object-owned-method.rs create mode 100644 tests/ui/self/point-at-arbitrary-self-type-method.rs create mode 100644 tests/ui/self/point-at-arbitrary-self-type-method.stderr create mode 100644 tests/ui/self/point-at-arbitrary-self-type-trait-method.rs create mode 100644 tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr create mode 100644 tests/ui/self/self-impl-2.rs create mode 100644 tests/ui/self/self-impl.rs create mode 100644 tests/ui/self/self-impl.stderr create mode 100644 tests/ui/self/self-in-mut-slot-default-method.rs create mode 100644 tests/ui/self/self-in-mut-slot-immediate-value.rs create mode 100644 tests/ui/self/self-in-typedefs.rs create mode 100644 tests/ui/self/self-infer.rs create mode 100644 tests/ui/self/self-infer.stderr create mode 100644 tests/ui/self/self-re-assign.rs create mode 100644 tests/ui/self/self-shadowing-import.rs create mode 100644 tests/ui/self/self-type-param.rs create mode 100644 tests/ui/self/self-vs-path-ambiguity.rs create mode 100644 tests/ui/self/self-vs-path-ambiguity.stderr create mode 100644 tests/ui/self/self_lifetime-async.rs create mode 100644 tests/ui/self/self_lifetime.rs create mode 100644 tests/ui/self/self_type_keyword-2.rs create mode 100644 tests/ui/self/self_type_keyword-2.stderr create mode 100644 tests/ui/self/self_type_keyword.rs create mode 100644 tests/ui/self/self_type_keyword.stderr create mode 100644 tests/ui/self/string-self-append.rs create mode 100644 tests/ui/self/suggest-self-2.rs create mode 100644 tests/ui/self/suggest-self-2.stderr create mode 100644 tests/ui/self/suggest-self.rs create mode 100644 tests/ui/self/suggest-self.stderr create mode 100644 tests/ui/self/ufcs-explicit-self.rs create mode 100644 tests/ui/self/uniq-self-in-mut-slot.rs create mode 100644 tests/ui/self/where-for-self.rs create mode 100644 tests/ui/sepcomp/auxiliary/sepcomp-extern-lib.rs create mode 100644 tests/ui/sepcomp/auxiliary/sepcomp_cci_lib.rs create mode 100644 tests/ui/sepcomp/auxiliary/sepcomp_lib.rs create mode 100644 tests/ui/sepcomp/sepcomp-cci.rs create mode 100644 tests/ui/sepcomp/sepcomp-extern.rs create mode 100644 tests/ui/sepcomp/sepcomp-fns-backwards.rs create mode 100644 tests/ui/sepcomp/sepcomp-fns.rs create mode 100644 tests/ui/sepcomp/sepcomp-lib-lto.rs create mode 100644 tests/ui/sepcomp/sepcomp-lib.rs create mode 100644 tests/ui/sepcomp/sepcomp-statics.rs create mode 100644 tests/ui/sepcomp/sepcomp-unwind.rs create mode 100644 tests/ui/seq-args.rs create mode 100644 tests/ui/seq-args.stderr create mode 100644 tests/ui/shadow-bool.rs create mode 100644 tests/ui/shadowed-use-visibility.rs create mode 100644 tests/ui/shadowed/shadowed-lifetime.rs create mode 100644 tests/ui/shadowed/shadowed-lifetime.stderr create mode 100644 tests/ui/shadowed/shadowed-trait-methods.rs create mode 100644 tests/ui/shadowed/shadowed-trait-methods.stderr create mode 100644 tests/ui/shadowed/shadowed-type-parameter.rs create mode 100644 tests/ui/shadowed/shadowed-type-parameter.stderr create mode 100644 tests/ui/shadowed/shadowed-use-visibility.rs create mode 100644 tests/ui/shadowed/shadowed-use-visibility.stderr create mode 100644 tests/ui/shadowed/shadowing-in-the-same-pattern.rs create mode 100644 tests/ui/shadowed/shadowing-in-the-same-pattern.stderr create mode 100644 tests/ui/short-error-format.rs create mode 100644 tests/ui/short-error-format.stderr create mode 100644 tests/ui/simd/array-trait.rs create mode 100644 tests/ui/simd/array-trait.stderr create mode 100644 tests/ui/simd/array-type.rs create mode 100644 tests/ui/simd/generics.rs create mode 100644 tests/ui/simd/intrinsic/float-math-pass.rs create mode 100644 tests/ui/simd/intrinsic/float-minmax-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-arithmetic-2.rs create mode 100644 tests/ui/simd/intrinsic/generic-arithmetic-2.stderr create mode 100644 tests/ui/simd/intrinsic/generic-arithmetic-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs create mode 100644 tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr create mode 100644 tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-as.rs create mode 100644 tests/ui/simd/intrinsic/generic-bitmask-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-bitmask.rs create mode 100644 tests/ui/simd/intrinsic/generic-bitmask.stderr create mode 100644 tests/ui/simd/intrinsic/generic-cast-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-cast-pointer-width.rs create mode 100644 tests/ui/simd/intrinsic/generic-cast.rs create mode 100644 tests/ui/simd/intrinsic/generic-cast.stderr create mode 100644 tests/ui/simd/intrinsic/generic-comparison-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-comparison.rs create mode 100644 tests/ui/simd/intrinsic/generic-comparison.stderr create mode 100644 tests/ui/simd/intrinsic/generic-elements-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-elements.rs create mode 100644 tests/ui/simd/intrinsic/generic-elements.stderr create mode 100644 tests/ui/simd/intrinsic/generic-gather-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-reduction-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-reduction.rs create mode 100644 tests/ui/simd/intrinsic/generic-reduction.stderr create mode 100644 tests/ui/simd/intrinsic/generic-select-pass.rs create mode 100644 tests/ui/simd/intrinsic/generic-select.rs create mode 100644 tests/ui/simd/intrinsic/generic-select.stderr create mode 100644 tests/ui/simd/intrinsic/generic-shuffle.rs create mode 100644 tests/ui/simd/intrinsic/generic-shuffle.stderr create mode 100644 tests/ui/simd/intrinsic/inlining-issue67557-ice.rs create mode 100644 tests/ui/simd/intrinsic/inlining-issue67557.rs create mode 100644 tests/ui/simd/intrinsic/issue-85855.rs create mode 100644 tests/ui/simd/intrinsic/issue-85855.stderr create mode 100644 tests/ui/simd/intrinsic/ptr-cast.rs create mode 100644 tests/ui/simd/issue-17170.rs create mode 100644 tests/ui/simd/issue-32947.rs create mode 100644 tests/ui/simd/issue-39720.rs create mode 100644 tests/ui/simd/issue-85915-simd-ptrs.rs create mode 100644 tests/ui/simd/issue-89193.rs create mode 100644 tests/ui/simd/libm_no_std_cant_float.rs create mode 100644 tests/ui/simd/libm_no_std_cant_float.stderr create mode 100644 tests/ui/simd/libm_std_can_float.rs create mode 100644 tests/ui/simd/monomorphize-shuffle-index.rs create mode 100644 tests/ui/simd/portable-intrinsics-arent-exposed.rs create mode 100644 tests/ui/simd/portable-intrinsics-arent-exposed.stderr create mode 100644 tests/ui/simd/shuffle-not-out-of-bounds.rs create mode 100644 tests/ui/simd/shuffle-not-out-of-bounds.stderr create mode 100644 tests/ui/simd/shuffle.rs create mode 100644 tests/ui/simd/simd-bitmask.rs create mode 100644 tests/ui/simd/size-align.rs create mode 100644 tests/ui/simd/target-feature-mixup.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-empty.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-empty.stderr create mode 100644 tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-non-primitive.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr create mode 100644 tests/ui/simd/type-generic-monomorphisation-oversized.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-oversized.stderr create mode 100644 tests/ui/simd/type-generic-monomorphisation-power-of-two.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr create mode 100644 tests/ui/simd/type-generic-monomorphisation.rs create mode 100644 tests/ui/simd/type-generic-monomorphisation.stderr create mode 100644 tests/ui/simd/type-len.rs create mode 100644 tests/ui/simd/type-len.stderr create mode 100644 tests/ui/simd/type-wide-ptr.rs create mode 100644 tests/ui/simd/type-wide-ptr.stderr create mode 100644 tests/ui/simd/wasm-simd-indirect.rs create mode 100644 tests/ui/simple_global_asm.rs create mode 100644 tests/ui/single-use-lifetime/derive-eq.rs create mode 100644 tests/ui/single-use-lifetime/fn-types.rs create mode 100644 tests/ui/single-use-lifetime/fn-types.stderr create mode 100644 tests/ui/single-use-lifetime/issue-104440.rs create mode 100644 tests/ui/single-use-lifetime/issue-104440.stderr create mode 100644 tests/ui/single-use-lifetime/one-use-in-fn-argument.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr create mode 100644 tests/ui/single-use-lifetime/one-use-in-fn-return.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr create mode 100644 tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr create mode 100644 tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr create mode 100644 tests/ui/single-use-lifetime/one-use-in-struct.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs create mode 100644 tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr create mode 100644 tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs create mode 100644 tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs create mode 100644 tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs create mode 100644 tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs create mode 100644 tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr create mode 100644 tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs create mode 100644 tests/ui/single-use-lifetime/zero-uses-in-fn.fixed create mode 100644 tests/ui/single-use-lifetime/zero-uses-in-fn.rs create mode 100644 tests/ui/single-use-lifetime/zero-uses-in-fn.stderr create mode 100644 tests/ui/single-use-lifetime/zero-uses-in-impl.rs create mode 100644 tests/ui/single-use-lifetime/zero-uses-in-impl.stderr create mode 100644 tests/ui/sized-borrowed-pointer.rs create mode 100644 tests/ui/sized-cycle-note.rs create mode 100644 tests/ui/sized-cycle-note.stderr create mode 100644 tests/ui/sized-owned-pointer.rs create mode 100644 tests/ui/sized/coinductive-1-gat.rs create mode 100644 tests/ui/sized/coinductive-1.rs create mode 100644 tests/ui/sized/coinductive-2.rs create mode 100644 tests/ui/sized/recursive-type-1.rs create mode 100644 tests/ui/sized/recursive-type-2.rs create mode 100644 tests/ui/sized/recursive-type-2.stderr create mode 100644 tests/ui/slightly-nice-generic-literal-messages.rs create mode 100644 tests/ui/slightly-nice-generic-literal-messages.stderr create mode 100644 tests/ui/span/E0046.rs create mode 100644 tests/ui/span/E0046.stderr create mode 100644 tests/ui/span/E0072.rs create mode 100644 tests/ui/span/E0072.stderr create mode 100644 tests/ui/span/E0204.rs create mode 100644 tests/ui/span/E0204.stderr create mode 100644 tests/ui/span/E0493.rs create mode 100644 tests/ui/span/E0493.stderr create mode 100644 tests/ui/span/E0535.rs create mode 100644 tests/ui/span/E0535.stderr create mode 100644 tests/ui/span/E0536.rs create mode 100644 tests/ui/span/E0536.stderr create mode 100644 tests/ui/span/E0537.rs create mode 100644 tests/ui/span/E0537.stderr create mode 100644 tests/ui/span/auxiliary/transitive_dep_three.rs create mode 100644 tests/ui/span/auxiliary/transitive_dep_two.rs create mode 100644 tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs create mode 100644 tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr create mode 100644 tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs create mode 100644 tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr create mode 100644 tests/ui/span/borrowck-call-is-borrow-issue-12224.rs create mode 100644 tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr create mode 100644 tests/ui/span/borrowck-call-method-from-mut-aliasable.rs create mode 100644 tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr create mode 100644 tests/ui/span/borrowck-fn-in-const-b.rs create mode 100644 tests/ui/span/borrowck-fn-in-const-b.stderr create mode 100644 tests/ui/span/borrowck-let-suggestion-suffixes.rs create mode 100644 tests/ui/span/borrowck-let-suggestion-suffixes.stderr create mode 100644 tests/ui/span/borrowck-object-mutability.rs create mode 100644 tests/ui/span/borrowck-object-mutability.stderr create mode 100644 tests/ui/span/borrowck-ref-into-rvalue.fixed create mode 100644 tests/ui/span/borrowck-ref-into-rvalue.rs create mode 100644 tests/ui/span/borrowck-ref-into-rvalue.stderr create mode 100644 tests/ui/span/coerce-suggestions.rs create mode 100644 tests/ui/span/coerce-suggestions.stderr create mode 100644 tests/ui/span/destructor-restrictions.rs create mode 100644 tests/ui/span/destructor-restrictions.stderr create mode 100644 tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs create mode 100644 tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr create mode 100644 tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs create mode 100644 tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr create mode 100644 tests/ui/span/dropck-object-cycle.rs create mode 100644 tests/ui/span/dropck-object-cycle.stderr create mode 100644 tests/ui/span/dropck_arr_cycle_checked.rs create mode 100644 tests/ui/span/dropck_arr_cycle_checked.stderr create mode 100644 tests/ui/span/dropck_direct_cycle_with_drop.rs create mode 100644 tests/ui/span/dropck_direct_cycle_with_drop.stderr create mode 100644 tests/ui/span/dropck_misc_variants.rs create mode 100644 tests/ui/span/dropck_misc_variants.stderr create mode 100644 tests/ui/span/dropck_vec_cycle_checked.rs create mode 100644 tests/ui/span/dropck_vec_cycle_checked.stderr create mode 100644 tests/ui/span/gated-features-attr-spans.rs create mode 100644 tests/ui/span/gated-features-attr-spans.stderr create mode 100644 tests/ui/span/impl-wrong-item-for-trait.rs create mode 100644 tests/ui/span/impl-wrong-item-for-trait.stderr create mode 100644 tests/ui/span/import-ty-params.rs create mode 100644 tests/ui/span/import-ty-params.stderr create mode 100644 tests/ui/span/issue-11925.rs create mode 100644 tests/ui/span/issue-11925.stderr create mode 100644 tests/ui/span/issue-15480.fixed create mode 100644 tests/ui/span/issue-15480.rs create mode 100644 tests/ui/span/issue-15480.stderr create mode 100644 tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs create mode 100644 tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr create mode 100644 tests/ui/span/issue-23729.rs create mode 100644 tests/ui/span/issue-23729.stderr create mode 100644 tests/ui/span/issue-23827.rs create mode 100644 tests/ui/span/issue-23827.stderr create mode 100644 tests/ui/span/issue-24356.rs create mode 100644 tests/ui/span/issue-24356.stderr create mode 100644 tests/ui/span/issue-24690.rs create mode 100644 tests/ui/span/issue-24690.stderr create mode 100644 tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs create mode 100644 tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr create mode 100644 tests/ui/span/issue-24805-dropck-trait-has-items.rs create mode 100644 tests/ui/span/issue-24805-dropck-trait-has-items.stderr create mode 100644 tests/ui/span/issue-24895-copy-clone-dropck.rs create mode 100644 tests/ui/span/issue-24895-copy-clone-dropck.stderr create mode 100644 tests/ui/span/issue-25199.rs create mode 100644 tests/ui/span/issue-25199.stderr create mode 100644 tests/ui/span/issue-26656.rs create mode 100644 tests/ui/span/issue-26656.stderr create mode 100644 tests/ui/span/issue-27522.rs create mode 100644 tests/ui/span/issue-27522.stderr create mode 100644 tests/ui/span/issue-29106.rs create mode 100644 tests/ui/span/issue-29106.stderr create mode 100644 tests/ui/span/issue-29595.rs create mode 100644 tests/ui/span/issue-29595.stderr create mode 100644 tests/ui/span/issue-33884.rs create mode 100644 tests/ui/span/issue-33884.stderr create mode 100644 tests/ui/span/issue-34264.rs create mode 100644 tests/ui/span/issue-34264.stderr create mode 100644 tests/ui/span/issue-35987.rs create mode 100644 tests/ui/span/issue-35987.stderr create mode 100644 tests/ui/span/issue-36537.rs create mode 100644 tests/ui/span/issue-36537.stderr create mode 100644 tests/ui/span/issue-37767.rs create mode 100644 tests/ui/span/issue-37767.stderr create mode 100644 tests/ui/span/issue-39018.rs create mode 100644 tests/ui/span/issue-39018.stderr create mode 100644 tests/ui/span/issue-39698.rs create mode 100644 tests/ui/span/issue-39698.stderr create mode 100644 tests/ui/span/issue-40157.rs create mode 100644 tests/ui/span/issue-40157.stderr create mode 100644 tests/ui/span/issue-42234-unknown-receiver-type.full.stderr create mode 100644 tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr create mode 100644 tests/ui/span/issue-42234-unknown-receiver-type.rs create mode 100644 tests/ui/span/issue-43927-non-ADT-derive.rs create mode 100644 tests/ui/span/issue-43927-non-ADT-derive.stderr create mode 100644 tests/ui/span/issue-71363.rs create mode 100644 tests/ui/span/issue-71363.stderr create mode 100644 tests/ui/span/issue-81800.rs create mode 100644 tests/ui/span/issue-81800.stderr create mode 100644 tests/ui/span/issue28498-reject-ex1.rs create mode 100644 tests/ui/span/issue28498-reject-ex1.stderr create mode 100644 tests/ui/span/issue28498-reject-lifetime-param.rs create mode 100644 tests/ui/span/issue28498-reject-lifetime-param.stderr create mode 100644 tests/ui/span/issue28498-reject-passed-to-fn.rs create mode 100644 tests/ui/span/issue28498-reject-passed-to-fn.stderr create mode 100644 tests/ui/span/issue28498-reject-trait-bound.rs create mode 100644 tests/ui/span/issue28498-reject-trait-bound.stderr create mode 100644 tests/ui/span/lint-unused-unsafe-thir.rs create mode 100644 tests/ui/span/lint-unused-unsafe-thir.stderr create mode 100644 tests/ui/span/lint-unused-unsafe.mir.stderr create mode 100644 tests/ui/span/lint-unused-unsafe.rs create mode 100644 tests/ui/span/macro-span-replacement.rs create mode 100644 tests/ui/span/macro-span-replacement.stderr create mode 100644 tests/ui/span/macro-ty-params.rs create mode 100644 tests/ui/span/macro-ty-params.stderr create mode 100644 tests/ui/span/method-and-field-eager-resolution.rs create mode 100644 tests/ui/span/method-and-field-eager-resolution.stderr create mode 100644 tests/ui/span/missing-unit-argument.rs create mode 100644 tests/ui/span/missing-unit-argument.stderr create mode 100644 tests/ui/span/move-closure.rs create mode 100644 tests/ui/span/move-closure.stderr create mode 100644 tests/ui/span/multiline-span-E0072.rs create mode 100644 tests/ui/span/multiline-span-E0072.stderr create mode 100644 tests/ui/span/multiline-span-simple.rs create mode 100644 tests/ui/span/multiline-span-simple.stderr create mode 100644 tests/ui/span/multispan-import-lint.rs create mode 100644 tests/ui/span/multispan-import-lint.stderr create mode 100644 tests/ui/span/mut-arg-hint.rs create mode 100644 tests/ui/span/mut-arg-hint.stderr create mode 100644 tests/ui/span/mut-ptr-cant-outlive-ref.rs create mode 100644 tests/ui/span/mut-ptr-cant-outlive-ref.stderr create mode 100644 tests/ui/span/non-existing-module-import.rs create mode 100644 tests/ui/span/non-existing-module-import.stderr create mode 100644 tests/ui/span/pub-struct-field.rs create mode 100644 tests/ui/span/pub-struct-field.stderr create mode 100644 tests/ui/span/range-2.rs create mode 100644 tests/ui/span/range-2.stderr create mode 100644 tests/ui/span/recursive-type-field.rs create mode 100644 tests/ui/span/recursive-type-field.stderr create mode 100644 tests/ui/span/regionck-unboxed-closure-lifetimes.rs create mode 100644 tests/ui/span/regionck-unboxed-closure-lifetimes.stderr create mode 100644 tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs create mode 100644 tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr create mode 100644 tests/ui/span/regions-close-over-type-parameter-2.rs create mode 100644 tests/ui/span/regions-close-over-type-parameter-2.stderr create mode 100644 tests/ui/span/regions-escape-loop-via-variable.rs create mode 100644 tests/ui/span/regions-escape-loop-via-variable.stderr create mode 100644 tests/ui/span/regions-escape-loop-via-vec.rs create mode 100644 tests/ui/span/regions-escape-loop-via-vec.stderr create mode 100644 tests/ui/span/regions-infer-borrow-scope-within-loop.rs create mode 100644 tests/ui/span/regions-infer-borrow-scope-within-loop.stderr create mode 100644 tests/ui/span/send-is-not-static-ensures-scoping.rs create mode 100644 tests/ui/span/send-is-not-static-ensures-scoping.stderr create mode 100644 tests/ui/span/send-is-not-static-std-sync-2.rs create mode 100644 tests/ui/span/send-is-not-static-std-sync-2.stderr create mode 100644 tests/ui/span/send-is-not-static-std-sync.rs create mode 100644 tests/ui/span/send-is-not-static-std-sync.stderr create mode 100644 tests/ui/span/slice-borrow.rs create mode 100644 tests/ui/span/slice-borrow.stderr create mode 100644 tests/ui/span/suggestion-non-ascii.rs create mode 100644 tests/ui/span/suggestion-non-ascii.stderr create mode 100644 tests/ui/span/transitive-dep-span.rs create mode 100644 tests/ui/span/transitive-dep-span.stderr create mode 100644 tests/ui/span/type-annotations-needed-expr.rs create mode 100644 tests/ui/span/type-annotations-needed-expr.stderr create mode 100644 tests/ui/span/type-binding.rs create mode 100644 tests/ui/span/type-binding.stderr create mode 100644 tests/ui/span/typo-suggestion.rs create mode 100644 tests/ui/span/typo-suggestion.stderr create mode 100644 tests/ui/span/unused-warning-point-at-identifier.rs create mode 100644 tests/ui/span/unused-warning-point-at-identifier.stderr create mode 100644 tests/ui/span/vec-must-not-hide-type-from-dropck.rs create mode 100644 tests/ui/span/vec-must-not-hide-type-from-dropck.stderr create mode 100644 tests/ui/span/vec_refs_data_with_early_death.rs create mode 100644 tests/ui/span/vec_refs_data_with_early_death.stderr create mode 100644 tests/ui/span/visibility-ty-params.rs create mode 100644 tests/ui/span/visibility-ty-params.stderr create mode 100644 tests/ui/span/wf-method-late-bound-regions.rs create mode 100644 tests/ui/span/wf-method-late-bound-regions.stderr create mode 100644 tests/ui/specialization/README-rpass.md create mode 100644 tests/ui/specialization/README.md create mode 100644 tests/ui/specialization/assoc-ty-graph-cycle.rs create mode 100644 tests/ui/specialization/assoc-ty-graph-cycle.stderr create mode 100644 tests/ui/specialization/auxiliary/cross_crates_defaults.rs create mode 100644 tests/ui/specialization/auxiliary/go_trait.rs create mode 100644 tests/ui/specialization/auxiliary/specialization_cross_crate.rs create mode 100644 tests/ui/specialization/const_trait_impl.rs create mode 100644 tests/ui/specialization/cross-crate-defaults.rs create mode 100644 tests/ui/specialization/cross-crate-defaults.stderr create mode 100644 tests/ui/specialization/default-associated-type-bound-1.rs create mode 100644 tests/ui/specialization/default-associated-type-bound-1.stderr create mode 100644 tests/ui/specialization/default-associated-type-bound-2.rs create mode 100644 tests/ui/specialization/default-associated-type-bound-2.stderr create mode 100644 tests/ui/specialization/default-generic-associated-type-bound.rs create mode 100644 tests/ui/specialization/default-generic-associated-type-bound.stderr create mode 100644 tests/ui/specialization/defaultimpl/allowed-cross-crate.rs create mode 100644 tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr create mode 100644 tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs create mode 100644 tests/ui/specialization/defaultimpl/out-of-order.rs create mode 100644 tests/ui/specialization/defaultimpl/out-of-order.stderr create mode 100644 tests/ui/specialization/defaultimpl/overlap-projection.rs create mode 100644 tests/ui/specialization/defaultimpl/overlap-projection.stderr create mode 100644 tests/ui/specialization/defaultimpl/projection.rs create mode 100644 tests/ui/specialization/defaultimpl/projection.stderr create mode 100644 tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs create mode 100644 tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr create mode 100644 tests/ui/specialization/defaultimpl/specialization-no-default.rs create mode 100644 tests/ui/specialization/defaultimpl/specialization-no-default.stderr create mode 100644 tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs create mode 100644 tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr create mode 100644 tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs create mode 100644 tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr create mode 100644 tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs create mode 100644 tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr create mode 100644 tests/ui/specialization/defaultimpl/specialization-wfcheck.rs create mode 100644 tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr create mode 100644 tests/ui/specialization/defaultimpl/validation.rs create mode 100644 tests/ui/specialization/defaultimpl/validation.stderr create mode 100644 tests/ui/specialization/issue-33017.rs create mode 100644 tests/ui/specialization/issue-33017.stderr create mode 100644 tests/ui/specialization/issue-35376.rs create mode 100644 tests/ui/specialization/issue-35376.stderr create mode 100644 tests/ui/specialization/issue-36804.rs create mode 100644 tests/ui/specialization/issue-36804.stderr create mode 100644 tests/ui/specialization/issue-38091-2.rs create mode 100644 tests/ui/specialization/issue-38091-2.stderr create mode 100644 tests/ui/specialization/issue-38091.rs create mode 100644 tests/ui/specialization/issue-38091.stderr create mode 100644 tests/ui/specialization/issue-39448.rs create mode 100644 tests/ui/specialization/issue-39448.stderr create mode 100644 tests/ui/specialization/issue-39618.rs create mode 100644 tests/ui/specialization/issue-39618.stderr create mode 100644 tests/ui/specialization/issue-43037.current.stderr create mode 100644 tests/ui/specialization/issue-43037.negative.stderr create mode 100644 tests/ui/specialization/issue-43037.rs create mode 100644 tests/ui/specialization/issue-44861.rs create mode 100644 tests/ui/specialization/issue-44861.stderr create mode 100644 tests/ui/specialization/issue-45814.current.stderr create mode 100644 tests/ui/specialization/issue-45814.negative.stderr create mode 100644 tests/ui/specialization/issue-45814.rs create mode 100644 tests/ui/specialization/issue-50452-fail.rs create mode 100644 tests/ui/specialization/issue-50452-fail.stderr create mode 100644 tests/ui/specialization/issue-50452.rs create mode 100644 tests/ui/specialization/issue-50452.stderr create mode 100644 tests/ui/specialization/issue-51892.rs create mode 100644 tests/ui/specialization/issue-51892.stderr create mode 100644 tests/ui/specialization/issue-52050.rs create mode 100644 tests/ui/specialization/issue-52050.stderr create mode 100644 tests/ui/specialization/issue-59435.rs create mode 100644 tests/ui/specialization/issue-59435.stderr create mode 100644 tests/ui/specialization/issue-63716-parse-async.rs create mode 100644 tests/ui/specialization/issue-63716-parse-async.stderr create mode 100644 tests/ui/specialization/issue-68830-spurious-diagnostics.rs create mode 100644 tests/ui/specialization/issue-68830-spurious-diagnostics.stderr create mode 100644 tests/ui/specialization/issue-70442.rs create mode 100644 tests/ui/specialization/issue-70442.stderr create mode 100644 tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs create mode 100644 tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs create mode 100644 tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr create mode 100644 tests/ui/specialization/min_specialization/impl-on-nonexisting.rs create mode 100644 tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr create mode 100644 tests/ui/specialization/min_specialization/impl_specialization_trait.rs create mode 100644 tests/ui/specialization/min_specialization/impl_specialization_trait.stderr create mode 100644 tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs create mode 100644 tests/ui/specialization/min_specialization/issue-79224.rs create mode 100644 tests/ui/specialization/min_specialization/issue-79224.stderr create mode 100644 tests/ui/specialization/min_specialization/repeated_projection_type.rs create mode 100644 tests/ui/specialization/min_specialization/repeated_projection_type.stderr create mode 100644 tests/ui/specialization/min_specialization/repeating_lifetimes.rs create mode 100644 tests/ui/specialization/min_specialization/repeating_lifetimes.stderr create mode 100644 tests/ui/specialization/min_specialization/repeating_param.rs create mode 100644 tests/ui/specialization/min_specialization/repeating_param.stderr create mode 100644 tests/ui/specialization/min_specialization/spec-iter.rs create mode 100644 tests/ui/specialization/min_specialization/spec-marker-supertraits.rs create mode 100644 tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr create mode 100644 tests/ui/specialization/min_specialization/spec-reference.rs create mode 100644 tests/ui/specialization/min_specialization/specialization_marker.rs create mode 100644 tests/ui/specialization/min_specialization/specialization_marker.stderr create mode 100644 tests/ui/specialization/min_specialization/specialization_super_trait.rs create mode 100644 tests/ui/specialization/min_specialization/specialization_super_trait.stderr create mode 100644 tests/ui/specialization/min_specialization/specialization_trait.rs create mode 100644 tests/ui/specialization/min_specialization/specialization_trait.stderr create mode 100644 tests/ui/specialization/min_specialization/specialize_on_marker.rs create mode 100644 tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs create mode 100644 tests/ui/specialization/min_specialization/specialize_on_static.rs create mode 100644 tests/ui/specialization/min_specialization/specialize_on_static.stderr create mode 100644 tests/ui/specialization/min_specialization/specialize_on_trait.rs create mode 100644 tests/ui/specialization/min_specialization/specialize_on_trait.stderr create mode 100644 tests/ui/specialization/non-defaulted-item-fail.rs create mode 100644 tests/ui/specialization/non-defaulted-item-fail.stderr create mode 100644 tests/ui/specialization/soundness/partial_eq_range_inclusive.rs create mode 100644 tests/ui/specialization/soundness/partial_ord_slice.rs create mode 100644 tests/ui/specialization/specialization-allowed-cross-crate.rs create mode 100644 tests/ui/specialization/specialization-allowed-cross-crate.stderr create mode 100644 tests/ui/specialization/specialization-assoc-fns.rs create mode 100644 tests/ui/specialization/specialization-assoc-fns.stderr create mode 100644 tests/ui/specialization/specialization-basics.rs create mode 100644 tests/ui/specialization/specialization-basics.stderr create mode 100644 tests/ui/specialization/specialization-cross-crate-no-gate.rs create mode 100644 tests/ui/specialization/specialization-cross-crate.rs create mode 100644 tests/ui/specialization/specialization-cross-crate.stderr create mode 100644 tests/ui/specialization/specialization-default-methods.rs create mode 100644 tests/ui/specialization/specialization-default-methods.stderr create mode 100644 tests/ui/specialization/specialization-default-projection.rs create mode 100644 tests/ui/specialization/specialization-default-projection.stderr create mode 100644 tests/ui/specialization/specialization-default-types.rs create mode 100644 tests/ui/specialization/specialization-default-types.stderr create mode 100644 tests/ui/specialization/specialization-feature-gate-default.rs create mode 100644 tests/ui/specialization/specialization-feature-gate-default.stderr create mode 100644 tests/ui/specialization/specialization-feature-gate-overlap.rs create mode 100644 tests/ui/specialization/specialization-feature-gate-overlap.stderr create mode 100644 tests/ui/specialization/specialization-no-default.rs create mode 100644 tests/ui/specialization/specialization-no-default.stderr create mode 100644 tests/ui/specialization/specialization-on-projection.rs create mode 100644 tests/ui/specialization/specialization-on-projection.stderr create mode 100644 tests/ui/specialization/specialization-out-of-order.rs create mode 100644 tests/ui/specialization/specialization-out-of-order.stderr create mode 100644 tests/ui/specialization/specialization-overlap-hygiene.rs create mode 100644 tests/ui/specialization/specialization-overlap-hygiene.stderr create mode 100644 tests/ui/specialization/specialization-overlap-negative.rs create mode 100644 tests/ui/specialization/specialization-overlap-negative.stderr create mode 100644 tests/ui/specialization/specialization-overlap-projection.rs create mode 100644 tests/ui/specialization/specialization-overlap-projection.stderr create mode 100644 tests/ui/specialization/specialization-overlap.rs create mode 100644 tests/ui/specialization/specialization-overlap.stderr create mode 100644 tests/ui/specialization/specialization-polarity.rs create mode 100644 tests/ui/specialization/specialization-polarity.stderr create mode 100644 tests/ui/specialization/specialization-projection-alias.rs create mode 100644 tests/ui/specialization/specialization-projection-alias.stderr create mode 100644 tests/ui/specialization/specialization-projection.rs create mode 100644 tests/ui/specialization/specialization-projection.stderr create mode 100644 tests/ui/specialization/specialization-supertraits.rs create mode 100644 tests/ui/specialization/specialization-supertraits.stderr create mode 100644 tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs create mode 100644 tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr create mode 100644 tests/ui/specialization/specialization-translate-projections-with-params.rs create mode 100644 tests/ui/specialization/specialization-translate-projections-with-params.stderr create mode 100644 tests/ui/specialization/specialization-translate-projections.rs create mode 100644 tests/ui/specialization/specialization-translate-projections.stderr create mode 100644 tests/ui/specialization/transmute-specialization.rs create mode 100644 tests/ui/specialization/transmute-specialization.stderr create mode 100644 tests/ui/sse2.rs create mode 100644 tests/ui/stability-attribute/accidental-stable-in-unstable.rs create mode 100644 tests/ui/stability-attribute/accidental-stable-in-unstable.stderr create mode 100644 tests/ui/stability-attribute/allow-unstable-reexport.rs create mode 100644 tests/ui/stability-attribute/allow-unstable-reexport.stderr create mode 100644 tests/ui/stability-attribute/allowed-through-unstable.rs create mode 100644 tests/ui/stability-attribute/allowed-through-unstable.stderr create mode 100644 tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs create mode 100644 tests/ui/stability-attribute/auxiliary/ctor-stability.rs create mode 100644 tests/ui/stability-attribute/auxiliary/default_body.rs create mode 100644 tests/ui/stability-attribute/auxiliary/lint-stability-reexport.rs create mode 100644 tests/ui/stability-attribute/auxiliary/lint-stability.rs create mode 100644 tests/ui/stability-attribute/auxiliary/stability-attribute-implies.rs create mode 100644 tests/ui/stability-attribute/auxiliary/stability_attribute_issue.rs create mode 100644 tests/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs create mode 100644 tests/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs create mode 100644 tests/ui/stability-attribute/auxiliary/unstable_generic_param.rs create mode 100644 tests/ui/stability-attribute/ctor-stability.rs create mode 100644 tests/ui/stability-attribute/default-body-stability-err.rs create mode 100644 tests/ui/stability-attribute/default-body-stability-err.stderr create mode 100644 tests/ui/stability-attribute/default-body-stability-ok-enables.rs create mode 100644 tests/ui/stability-attribute/default-body-stability-ok-impls.rs create mode 100644 tests/ui/stability-attribute/generics-default-stability-trait.rs create mode 100644 tests/ui/stability-attribute/generics-default-stability-trait.stderr create mode 100644 tests/ui/stability-attribute/generics-default-stability-where.rs create mode 100644 tests/ui/stability-attribute/generics-default-stability-where.stderr create mode 100644 tests/ui/stability-attribute/generics-default-stability.rs create mode 100644 tests/ui/stability-attribute/generics-default-stability.stderr create mode 100644 tests/ui/stability-attribute/issue-106589.rs create mode 100644 tests/ui/stability-attribute/issue-106589.stderr create mode 100644 tests/ui/stability-attribute/issue-28075.rs create mode 100644 tests/ui/stability-attribute/issue-28075.stderr create mode 100644 tests/ui/stability-attribute/issue-28388-3.rs create mode 100644 tests/ui/stability-attribute/issue-28388-3.stderr create mode 100644 tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs create mode 100644 tests/ui/stability-attribute/missing-const-stability.rs create mode 100644 tests/ui/stability-attribute/missing-const-stability.stderr create mode 100644 tests/ui/stability-attribute/missing-stability-attr-at-top-level.rs create mode 100644 tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-missing.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-missing.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-using-stable.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-using-unstable.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-issue-43027.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-issue.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-issue.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-non-staged.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-non-staged.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity-2.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity-2.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity-3.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity-3.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity-4.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity-4.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-sanity.stderr create mode 100644 tests/ui/stability-attribute/stability-attribute-trait-impl.rs create mode 100644 tests/ui/stability-attribute/stability-attribute-trait-impl.stderr create mode 100644 tests/ui/stability-attribute/stability-in-private-module.rs create mode 100644 tests/ui/stability-attribute/stability-in-private-module.stderr create mode 100644 tests/ui/stability-attribute/stable-in-unstable.rs create mode 100644 tests/ui/stability-attribute/stable-in-unstable.stderr create mode 100644 tests/ui/stability-attribute/suggest-vec-allocator-api.rs create mode 100644 tests/ui/stability-attribute/suggest-vec-allocator-api.stderr create mode 100644 tests/ui/stable-addr-of.rs create mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr create mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr create mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.rs create mode 100644 tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr create mode 100644 tests/ui/static/auxiliary/extern-statics.rs create mode 100644 tests/ui/static/auxiliary/issue_24843.rs create mode 100644 tests/ui/static/auxiliary/nested_item.rs create mode 100644 tests/ui/static/auxiliary/static-priv-by-default.rs create mode 100644 tests/ui/static/auxiliary/static_priv_by_default.rs create mode 100644 tests/ui/static/bad-const-type.rs create mode 100644 tests/ui/static/bad-const-type.stderr create mode 100644 tests/ui/static/issue-18118-2.rs create mode 100644 tests/ui/static/issue-18118-2.stderr create mode 100644 tests/ui/static/issue-18118.rs create mode 100644 tests/ui/static/issue-18118.stderr create mode 100644 tests/ui/static/issue-24843.rs create mode 100644 tests/ui/static/issue-34194.rs create mode 100644 tests/ui/static/issue-5216.rs create mode 100644 tests/ui/static/issue-5216.stderr create mode 100644 tests/ui/static/nested_item_main.rs create mode 100644 tests/ui/static/refer-to-other-statics-by-value.rs create mode 100644 tests/ui/static/safe-extern-statics-mut.mir.stderr create mode 100644 tests/ui/static/safe-extern-statics-mut.rs create mode 100644 tests/ui/static/safe-extern-statics-mut.thir.stderr create mode 100644 tests/ui/static/safe-extern-statics.mir.stderr create mode 100644 tests/ui/static/safe-extern-statics.rs create mode 100644 tests/ui/static/safe-extern-statics.thir.stderr create mode 100644 tests/ui/static/static-closures.rs create mode 100644 tests/ui/static/static-closures.stderr create mode 100644 tests/ui/static/static-drop-scope.rs create mode 100644 tests/ui/static/static-drop-scope.stderr create mode 100644 tests/ui/static/static-extern-type.rs create mode 100644 tests/ui/static/static-items-cant-move.rs create mode 100644 tests/ui/static/static-items-cant-move.stderr create mode 100644 tests/ui/static/static-lifetime-bound.rs create mode 100644 tests/ui/static/static-lifetime-bound.stderr create mode 100644 tests/ui/static/static-lifetime.rs create mode 100644 tests/ui/static/static-lifetime.stderr create mode 100644 tests/ui/static/static-method-privacy.rs create mode 100644 tests/ui/static/static-method-privacy.stderr create mode 100644 tests/ui/static/static-mut-bad-types.rs create mode 100644 tests/ui/static/static-mut-bad-types.stderr create mode 100644 tests/ui/static/static-mut-foreign-requires-unsafe.mir.stderr create mode 100644 tests/ui/static/static-mut-foreign-requires-unsafe.rs create mode 100644 tests/ui/static/static-mut-foreign-requires-unsafe.thir.stderr create mode 100644 tests/ui/static/static-mut-not-constant.rs create mode 100644 tests/ui/static/static-mut-not-constant.stderr create mode 100644 tests/ui/static/static-mut-not-pat.rs create mode 100644 tests/ui/static/static-mut-not-pat.stderr create mode 100644 tests/ui/static/static-mut-requires-unsafe.mir.stderr create mode 100644 tests/ui/static/static-mut-requires-unsafe.rs create mode 100644 tests/ui/static/static-mut-requires-unsafe.thir.stderr create mode 100644 tests/ui/static/static-priv-by-default2.rs create mode 100644 tests/ui/static/static-priv-by-default2.stderr create mode 100644 tests/ui/static/static-reference-to-fn-1.rs create mode 100644 tests/ui/static/static-reference-to-fn-1.stderr create mode 100644 tests/ui/static/static-reference-to-fn-2.rs create mode 100644 tests/ui/static/static-reference-to-fn-2.stderr create mode 100644 tests/ui/static/static-region-bound.rs create mode 100644 tests/ui/static/static-region-bound.stderr create mode 100644 tests/ui/static/static-vec-repeat-not-constant.rs create mode 100644 tests/ui/static/static-vec-repeat-not-constant.stderr create mode 100644 tests/ui/static/static_sized_requirement.rs create mode 100644 tests/ui/static/thread-local-in-ctfe.rs create mode 100644 tests/ui/static/thread-local-in-ctfe.stderr create mode 100644 tests/ui/statics/auxiliary/static-function-pointer-aux.rs create mode 100644 tests/ui/statics/auxiliary/static-methods-crate.rs create mode 100644 tests/ui/statics/auxiliary/static_fn_inline_xc_aux.rs create mode 100644 tests/ui/statics/auxiliary/static_fn_trait_xc_aux.rs create mode 100644 tests/ui/statics/auxiliary/static_mut_xc.rs create mode 100644 tests/ui/statics/issue-14227.mir.stderr create mode 100644 tests/ui/statics/issue-14227.rs create mode 100644 tests/ui/statics/issue-14227.thir.stderr create mode 100644 tests/ui/statics/issue-15261.rs create mode 100644 tests/ui/statics/issue-17233.rs create mode 100644 tests/ui/statics/issue-17718-static-sync.rs create mode 100644 tests/ui/statics/issue-17718-static-sync.stderr create mode 100644 tests/ui/statics/issue-17718-static-unsafe-interior.rs create mode 100644 tests/ui/statics/issue-44373-2.rs create mode 100644 tests/ui/statics/issue-44373.rs create mode 100644 tests/ui/statics/issue-44373.stderr create mode 100644 tests/ui/statics/issue-91050-1.rs create mode 100644 tests/ui/statics/issue-91050-2.rs create mode 100644 tests/ui/statics/static-fn-inline-xc.rs create mode 100644 tests/ui/statics/static-fn-trait-xc.rs create mode 100644 tests/ui/statics/static-function-pointer-xc.rs create mode 100644 tests/ui/statics/static-function-pointer.rs create mode 100644 tests/ui/statics/static-impl.rs create mode 100644 tests/ui/statics/static-method-in-trait-with-tps-intracrate.rs create mode 100644 tests/ui/statics/static-method-xcrate.rs create mode 100644 tests/ui/statics/static-methods-in-traits.rs create mode 100644 tests/ui/statics/static-methods-in-traits2.rs create mode 100644 tests/ui/statics/static-mut-xc.rs create mode 100644 tests/ui/statics/static-promotion.rs create mode 100644 tests/ui/statics/static-recursive.rs create mode 100644 tests/ui/statics/uninhabited-static.rs create mode 100644 tests/ui/statics/uninhabited-static.stderr create mode 100644 tests/ui/stats/hir-stats.rs create mode 100644 tests/ui/stats/hir-stats.stderr create mode 100644 tests/ui/std-backtrace.rs create mode 100644 tests/ui/std-uncopyable-atomics.rs create mode 100644 tests/ui/std-uncopyable-atomics.stderr create mode 100644 tests/ui/stdio-is-blocking.rs create mode 100644 tests/ui/stdlib-unit-tests/builtin-clone.rs create mode 100644 tests/ui/stdlib-unit-tests/eq-multidispatch.rs create mode 100644 tests/ui/stdlib-unit-tests/issue-21058.rs create mode 100644 tests/ui/stdlib-unit-tests/istr.rs create mode 100644 tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs create mode 100644 tests/ui/stdlib-unit-tests/matches2021.rs create mode 100644 tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs create mode 100644 tests/ui/stdlib-unit-tests/not-sync.rs create mode 100644 tests/ui/stdlib-unit-tests/not-sync.stderr create mode 100644 tests/ui/stdlib-unit-tests/raw-fat-ptr.rs create mode 100644 tests/ui/stdlib-unit-tests/seq-compare.rs create mode 100644 tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs create mode 100644 tests/ui/stmt_expr_attrs_no_feature.rs create mode 100644 tests/ui/stmt_expr_attrs_no_feature.stderr create mode 100644 tests/ui/str/str-array-assignment.rs create mode 100644 tests/ui/str/str-array-assignment.stderr create mode 100644 tests/ui/str/str-as-char.fixed create mode 100644 tests/ui/str/str-as-char.rs create mode 100644 tests/ui/str/str-as-char.stderr create mode 100644 tests/ui/str/str-concat-on-double-ref.rs create mode 100644 tests/ui/str/str-concat-on-double-ref.stderr create mode 100644 tests/ui/str/str-escape.rs create mode 100644 tests/ui/str/str-escape.stderr create mode 100644 tests/ui/str/str-idx.rs create mode 100644 tests/ui/str/str-idx.stderr create mode 100644 tests/ui/str/str-lit-type-mismatch.rs create mode 100644 tests/ui/str/str-lit-type-mismatch.stderr create mode 100644 tests/ui/str/str-mut-idx.rs create mode 100644 tests/ui/str/str-mut-idx.stderr create mode 100644 tests/ui/str/str-overrun.rs create mode 100644 tests/ui/string-box-error.rs create mode 100644 tests/ui/struct-ctor-mangling.rs create mode 100644 tests/ui/structs-enums/align-enum.rs create mode 100644 tests/ui/structs-enums/align-struct.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class_2.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class_3.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class_4.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class_6.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class_cast.rs create mode 100644 tests/ui/structs-enums/auxiliary/cci_class_trait.rs create mode 100644 tests/ui/structs-enums/auxiliary/empty-struct.rs create mode 100644 tests/ui/structs-enums/auxiliary/namespaced_enum_emulate_flat.rs create mode 100644 tests/ui/structs-enums/auxiliary/namespaced_enums.rs create mode 100644 tests/ui/structs-enums/auxiliary/newtype_struct_xc.rs create mode 100644 tests/ui/structs-enums/auxiliary/struct_destructuring_cross_crate.rs create mode 100644 tests/ui/structs-enums/auxiliary/struct_variant_xc_aux.rs create mode 100644 tests/ui/structs-enums/auxiliary/xcrate_struct_aliases.rs create mode 100644 tests/ui/structs-enums/borrow-tuple-fields.rs create mode 100644 tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs create mode 100644 tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs create mode 100644 tests/ui/structs-enums/class-cast-to-trait.rs create mode 100644 tests/ui/structs-enums/class-dtor.rs create mode 100644 tests/ui/structs-enums/class-exports.rs create mode 100644 tests/ui/structs-enums/class-impl-very-parameterized-trait.rs create mode 100644 tests/ui/structs-enums/class-implement-trait-cross-crate.rs create mode 100644 tests/ui/structs-enums/class-implement-traits.rs create mode 100644 tests/ui/structs-enums/class-method-cross-crate.rs create mode 100644 tests/ui/structs-enums/class-methods-cross-crate.rs create mode 100644 tests/ui/structs-enums/class-methods.rs create mode 100644 tests/ui/structs-enums/class-poly-methods-cross-crate.rs create mode 100644 tests/ui/structs-enums/class-poly-methods.rs create mode 100644 tests/ui/structs-enums/class-separate-impl.rs create mode 100644 tests/ui/structs-enums/class-str-field.rs create mode 100644 tests/ui/structs-enums/class-typarams.rs create mode 100644 tests/ui/structs-enums/classes-cross-crate.rs create mode 100644 tests/ui/structs-enums/classes-self-referential.rs create mode 100644 tests/ui/structs-enums/classes-simple-cross-crate.rs create mode 100644 tests/ui/structs-enums/classes-simple-method.rs create mode 100644 tests/ui/structs-enums/classes-simple.rs create mode 100644 tests/ui/structs-enums/classes.rs create mode 100644 tests/ui/structs-enums/codegen-tag-static-padding.rs create mode 100644 tests/ui/structs-enums/compare-generic-enums.rs create mode 100644 tests/ui/structs-enums/cross-crate-newtype-struct-pat.rs create mode 100644 tests/ui/structs-enums/discrim-explicit-23030.rs create mode 100644 tests/ui/structs-enums/empty-struct-braces.rs create mode 100644 tests/ui/structs-enums/empty-tag.rs create mode 100644 tests/ui/structs-enums/enum-alignment.rs create mode 100644 tests/ui/structs-enums/enum-clike-ffi-as-int.rs create mode 100644 tests/ui/structs-enums/enum-discr.rs create mode 100644 tests/ui/structs-enums/enum-discrim-autosizing.rs create mode 100644 tests/ui/structs-enums/enum-discrim-manual-sizing.rs create mode 100644 tests/ui/structs-enums/enum-discrim-range-overflow.rs create mode 100644 tests/ui/structs-enums/enum-discrim-width-stuff.rs create mode 100644 tests/ui/structs-enums/enum-disr-val-pretty.rs create mode 100644 tests/ui/structs-enums/enum-export-inheritance.rs create mode 100644 tests/ui/structs-enums/enum-layout-optimization.rs create mode 100644 tests/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs create mode 100644 tests/ui/structs-enums/enum-non-c-like-repr-c.rs create mode 100644 tests/ui/structs-enums/enum-non-c-like-repr-int.rs create mode 100644 tests/ui/structs-enums/enum-null-pointer-opt.rs create mode 100644 tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs create mode 100644 tests/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs create mode 100644 tests/ui/structs-enums/enum-univariant-repr.rs create mode 100644 tests/ui/structs-enums/enum-variants.rs create mode 100644 tests/ui/structs-enums/enum-vec-initializer.rs create mode 100644 tests/ui/structs-enums/export-abstract-tag.rs create mode 100644 tests/ui/structs-enums/export-tag-variant.rs create mode 100644 tests/ui/structs-enums/expr-if-struct.rs create mode 100644 tests/ui/structs-enums/expr-match-struct.rs create mode 100644 tests/ui/structs-enums/field-destruction-order.rs create mode 100644 tests/ui/structs-enums/foreign-struct.rs create mode 100644 tests/ui/structs-enums/functional-struct-upd.rs create mode 100644 tests/ui/structs-enums/issue-1701.rs create mode 100644 tests/ui/structs-enums/issue-2718-a.rs create mode 100644 tests/ui/structs-enums/issue-2718-a.stderr create mode 100644 tests/ui/structs-enums/issue-38002.rs create mode 100644 tests/ui/structs-enums/issue-50731.rs create mode 100644 tests/ui/structs-enums/ivec-tag.rs create mode 100644 tests/ui/structs-enums/module-qualified-struct-destructure.rs create mode 100644 tests/ui/structs-enums/multiple-reprs.rs create mode 100644 tests/ui/structs-enums/namespaced-enum-emulate-flat-xc.rs create mode 100644 tests/ui/structs-enums/namespaced-enum-emulate-flat.rs create mode 100644 tests/ui/structs-enums/namespaced-enum-glob-import-xcrate.rs create mode 100644 tests/ui/structs-enums/namespaced-enum-glob-import.rs create mode 100644 tests/ui/structs-enums/namespaced-enums-xcrate.rs create mode 100644 tests/ui/structs-enums/namespaced-enums.rs create mode 100644 tests/ui/structs-enums/nested-enum-same-names.rs create mode 100644 tests/ui/structs-enums/newtype-struct-drop-run.rs create mode 100644 tests/ui/structs-enums/newtype-struct-with-dtor.rs create mode 100644 tests/ui/structs-enums/newtype-struct-xc-2.rs create mode 100644 tests/ui/structs-enums/newtype-struct-xc.rs create mode 100644 tests/ui/structs-enums/nonzero-enum.rs create mode 100644 tests/ui/structs-enums/numeric-fields.rs create mode 100644 tests/ui/structs-enums/rec-align-u32.rs create mode 100644 tests/ui/structs-enums/rec-align-u64.rs create mode 100644 tests/ui/structs-enums/rec-auto.rs create mode 100644 tests/ui/structs-enums/rec-extend.rs create mode 100644 tests/ui/structs-enums/rec-tup.rs create mode 100644 tests/ui/structs-enums/rec.rs create mode 100644 tests/ui/structs-enums/record-pat.rs create mode 100644 tests/ui/structs-enums/resource-in-struct.rs create mode 100644 tests/ui/structs-enums/simple-generic-tag.rs create mode 100644 tests/ui/structs-enums/simple-match-generic-tag.rs create mode 100644 tests/ui/structs-enums/small-enum-range-edge.rs create mode 100644 tests/ui/structs-enums/small-enums-with-fields.rs create mode 100644 tests/ui/structs-enums/struct-aliases-xcrate.rs create mode 100644 tests/ui/structs-enums/struct-aliases.rs create mode 100644 tests/ui/structs-enums/struct-destructuring-cross-crate.rs create mode 100644 tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs create mode 100644 tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr create mode 100644 tests/ui/structs-enums/struct-field-shorthand.rs create mode 100644 tests/ui/structs-enums/struct-like-variant-construct.rs create mode 100644 tests/ui/structs-enums/struct-like-variant-match.rs create mode 100644 tests/ui/structs-enums/struct-lit-functional-no-fields.rs create mode 100644 tests/ui/structs-enums/struct-literal-dtor.rs create mode 100644 tests/ui/structs-enums/struct-new-as-field-name.rs create mode 100644 tests/ui/structs-enums/struct-order-of-eval-1.rs create mode 100644 tests/ui/structs-enums/struct-order-of-eval-2.rs create mode 100644 tests/ui/structs-enums/struct-order-of-eval-3.rs create mode 100644 tests/ui/structs-enums/struct-order-of-eval-4.rs create mode 100644 tests/ui/structs-enums/struct-partial-move-1.rs create mode 100644 tests/ui/structs-enums/struct-partial-move-2.rs create mode 100644 tests/ui/structs-enums/struct-path-associated-type.rs create mode 100644 tests/ui/structs-enums/struct-path-self.rs create mode 100644 tests/ui/structs-enums/struct-pattern-matching.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-74224.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-74224.stderr create mode 100644 tests/ui/structs-enums/struct-rec/issue-84611.rs create mode 100644 tests/ui/structs-enums/struct-rec/issue-84611.stderr create mode 100644 tests/ui/structs-enums/struct-rec/mutual-struct-recursion.rs create mode 100644 tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr create mode 100644 tests/ui/structs-enums/struct-variant-field-visibility.rs create mode 100644 tests/ui/structs-enums/struct_variant_xc.rs create mode 100644 tests/ui/structs-enums/struct_variant_xc_match.rs create mode 100644 tests/ui/structs-enums/tag-align-dyn-u64.rs create mode 100644 tests/ui/structs-enums/tag-align-dyn-variants.rs create mode 100644 tests/ui/structs-enums/tag-align-shape.rs create mode 100644 tests/ui/structs-enums/tag-align-u64.rs create mode 100644 tests/ui/structs-enums/tag-disr-val-shape.rs create mode 100644 tests/ui/structs-enums/tag-exports.rs create mode 100644 tests/ui/structs-enums/tag-in-block.rs create mode 100644 tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs create mode 100644 tests/ui/structs-enums/tag-variant-disr-val.rs create mode 100644 tests/ui/structs-enums/tag.rs create mode 100644 tests/ui/structs-enums/tuple-struct-construct.rs create mode 100644 tests/ui/structs-enums/tuple-struct-constructor-pointer.rs create mode 100644 tests/ui/structs-enums/tuple-struct-destructuring.rs create mode 100644 tests/ui/structs-enums/tuple-struct-matching.rs create mode 100644 tests/ui/structs-enums/tuple-struct-trivial.rs create mode 100644 tests/ui/structs-enums/type-sizes.rs create mode 100644 tests/ui/structs-enums/uninstantiable-struct.rs create mode 100644 tests/ui/structs-enums/unit-like-struct-drop-run.rs create mode 100644 tests/ui/structs-enums/unit-like-struct.rs create mode 100644 tests/ui/structs-enums/variant-structs-trivial.rs create mode 100644 tests/ui/structs/auxiliary/struct_field_privacy.rs create mode 100644 tests/ui/structs/auxiliary/struct_variant_privacy.rs create mode 100644 tests/ui/structs/incomplete-fn-in-struct-definition.rs create mode 100644 tests/ui/structs/incomplete-fn-in-struct-definition.stderr create mode 100644 tests/ui/structs/issue-80853.rs create mode 100644 tests/ui/structs/issue-80853.stderr create mode 100644 tests/ui/structs/large-records.rs create mode 100644 tests/ui/structs/multi-line-fru-suggestion.rs create mode 100644 tests/ui/structs/multi-line-fru-suggestion.stderr create mode 100644 tests/ui/structs/rhs-type.rs create mode 100644 tests/ui/structs/struct-base-wrong-type.rs create mode 100644 tests/ui/structs/struct-base-wrong-type.stderr create mode 100644 tests/ui/structs/struct-duplicate-comma.fixed create mode 100644 tests/ui/structs/struct-duplicate-comma.rs create mode 100644 tests/ui/structs/struct-duplicate-comma.stderr create mode 100644 tests/ui/structs/struct-field-cfg.rs create mode 100644 tests/ui/structs/struct-field-cfg.stderr create mode 100644 tests/ui/structs/struct-field-init-syntax.rs create mode 100644 tests/ui/structs/struct-field-init-syntax.stderr create mode 100644 tests/ui/structs/struct-field-privacy.rs create mode 100644 tests/ui/structs/struct-field-privacy.stderr create mode 100644 tests/ui/structs/struct-fields-decl-dupe.rs create mode 100644 tests/ui/structs/struct-fields-decl-dupe.stderr create mode 100644 tests/ui/structs/struct-fields-dupe.rs create mode 100644 tests/ui/structs/struct-fields-dupe.stderr create mode 100644 tests/ui/structs/struct-fields-hints-no-dupe.rs create mode 100644 tests/ui/structs/struct-fields-hints-no-dupe.stderr create mode 100644 tests/ui/structs/struct-fields-hints.rs create mode 100644 tests/ui/structs/struct-fields-hints.stderr create mode 100644 tests/ui/structs/struct-fields-missing.rs create mode 100644 tests/ui/structs/struct-fields-missing.stderr create mode 100644 tests/ui/structs/struct-fields-shorthand-unresolved.rs create mode 100644 tests/ui/structs/struct-fields-shorthand-unresolved.stderr create mode 100644 tests/ui/structs/struct-fields-shorthand.rs create mode 100644 tests/ui/structs/struct-fields-shorthand.stderr create mode 100644 tests/ui/structs/struct-fields-too-many.rs create mode 100644 tests/ui/structs/struct-fields-too-many.stderr create mode 100644 tests/ui/structs/struct-fields-typo.rs create mode 100644 tests/ui/structs/struct-fields-typo.stderr create mode 100644 tests/ui/structs/struct-fn-in-definition.rs create mode 100644 tests/ui/structs/struct-fn-in-definition.stderr create mode 100644 tests/ui/structs/struct-missing-comma.fixed create mode 100644 tests/ui/structs/struct-missing-comma.rs create mode 100644 tests/ui/structs/struct-missing-comma.stderr create mode 100644 tests/ui/structs/struct-pat-derived-error.rs create mode 100644 tests/ui/structs/struct-pat-derived-error.stderr create mode 100644 tests/ui/structs/struct-path-alias-bounds.rs create mode 100644 tests/ui/structs/struct-path-alias-bounds.stderr create mode 100644 tests/ui/structs/struct-path-associated-type.rs create mode 100644 tests/ui/structs/struct-path-associated-type.stderr create mode 100644 tests/ui/structs/struct-path-self-type-mismatch.rs create mode 100644 tests/ui/structs/struct-path-self-type-mismatch.stderr create mode 100644 tests/ui/structs/struct-path-self.rs create mode 100644 tests/ui/structs/struct-path-self.stderr create mode 100644 tests/ui/structs/struct-record-suggestion.fixed create mode 100644 tests/ui/structs/struct-record-suggestion.rs create mode 100644 tests/ui/structs/struct-record-suggestion.stderr create mode 100644 tests/ui/structs/struct-tuple-field-names.rs create mode 100644 tests/ui/structs/struct-tuple-field-names.stderr create mode 100644 tests/ui/structs/struct-variant-privacy-xc.rs create mode 100644 tests/ui/structs/struct-variant-privacy-xc.stderr create mode 100644 tests/ui/structs/struct-variant-privacy.rs create mode 100644 tests/ui/structs/struct-variant-privacy.stderr create mode 100644 tests/ui/structs/structure-constructor-type-mismatch.rs create mode 100644 tests/ui/structs/structure-constructor-type-mismatch.stderr create mode 100644 tests/ui/structs/suggest-private-fields.rs create mode 100644 tests/ui/structs/suggest-private-fields.stderr create mode 100644 tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs create mode 100644 tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr create mode 100644 tests/ui/structs/unresolved-struct-with-fru.rs create mode 100644 tests/ui/structs/unresolved-struct-with-fru.stderr create mode 100644 tests/ui/suggestions/abi-typo.fixed create mode 100644 tests/ui/suggestions/abi-typo.rs create mode 100644 tests/ui/suggestions/abi-typo.stderr create mode 100644 tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs create mode 100644 tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr create mode 100644 tests/ui/suggestions/args-instead-of-tuple-errors.rs create mode 100644 tests/ui/suggestions/args-instead-of-tuple-errors.stderr create mode 100644 tests/ui/suggestions/args-instead-of-tuple.fixed create mode 100644 tests/ui/suggestions/args-instead-of-tuple.rs create mode 100644 tests/ui/suggestions/args-instead-of-tuple.stderr create mode 100644 tests/ui/suggestions/as-ref-2.rs create mode 100644 tests/ui/suggestions/as-ref-2.stderr create mode 100644 tests/ui/suggestions/as-ref.rs create mode 100644 tests/ui/suggestions/as-ref.stderr create mode 100644 tests/ui/suggestions/assoc-const-as-field.rs create mode 100644 tests/ui/suggestions/assoc-const-as-field.stderr create mode 100644 tests/ui/suggestions/assoc-const-as-fn.rs create mode 100644 tests/ui/suggestions/assoc-const-as-fn.stderr create mode 100644 tests/ui/suggestions/assoc-ct-for-assoc-method.rs create mode 100644 tests/ui/suggestions/assoc-ct-for-assoc-method.stderr create mode 100644 tests/ui/suggestions/assoc-type-in-method-return.rs create mode 100644 tests/ui/suggestions/assoc-type-in-method-return.stderr create mode 100644 tests/ui/suggestions/assoc_fn_without_self.rs create mode 100644 tests/ui/suggestions/assoc_fn_without_self.stderr create mode 100644 tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs create mode 100644 tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr create mode 100644 tests/ui/suggestions/attribute-typos.rs create mode 100644 tests/ui/suggestions/attribute-typos.stderr create mode 100644 tests/ui/suggestions/auxiliary/foo.rs create mode 100644 tests/ui/suggestions/auxiliary/issue-61963-1.rs create mode 100644 tests/ui/suggestions/auxiliary/issue-61963.rs create mode 100644 tests/ui/suggestions/auxiliary/issue-81839.rs create mode 100644 tests/ui/suggestions/auxiliary/meow.rs create mode 100644 tests/ui/suggestions/auxiliary/not-object-safe.rs create mode 100644 tests/ui/suggestions/auxiliary/proc-macro-type-error.rs create mode 100644 tests/ui/suggestions/bad-hex-float-lit.rs create mode 100644 tests/ui/suggestions/bad-hex-float-lit.stderr create mode 100644 tests/ui/suggestions/bool_typo_err_suggest.rs create mode 100644 tests/ui/suggestions/bool_typo_err_suggest.stderr create mode 100644 tests/ui/suggestions/borrow-for-loop-head.rs create mode 100644 tests/ui/suggestions/borrow-for-loop-head.stderr create mode 100644 tests/ui/suggestions/bound-suggestions.fixed create mode 100644 tests/ui/suggestions/bound-suggestions.rs create mode 100644 tests/ui/suggestions/bound-suggestions.stderr create mode 100644 tests/ui/suggestions/box-future-wrong-output.rs create mode 100644 tests/ui/suggestions/box-future-wrong-output.stderr create mode 100644 tests/ui/suggestions/boxed-variant-field.rs create mode 100644 tests/ui/suggestions/boxed-variant-field.stderr create mode 100644 tests/ui/suggestions/call-boxed.rs create mode 100644 tests/ui/suggestions/call-boxed.stderr create mode 100644 tests/ui/suggestions/call-on-missing.rs create mode 100644 tests/ui/suggestions/call-on-missing.stderr create mode 100644 tests/ui/suggestions/call-on-unimplemented-ctor.rs create mode 100644 tests/ui/suggestions/call-on-unimplemented-ctor.stderr create mode 100644 tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs create mode 100644 tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr create mode 100644 tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs create mode 100644 tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr create mode 100644 tests/ui/suggestions/chain-method-call-mutation-in-place.rs create mode 100644 tests/ui/suggestions/chain-method-call-mutation-in-place.stderr create mode 100644 tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed create mode 100644 tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs create mode 100644 tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr create mode 100644 tests/ui/suggestions/const-in-struct-pat.rs create mode 100644 tests/ui/suggestions/const-in-struct-pat.stderr create mode 100644 tests/ui/suggestions/const-no-type.rs create mode 100644 tests/ui/suggestions/const-no-type.stderr create mode 100644 tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs create mode 100644 tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr create mode 100644 tests/ui/suggestions/constrain-suggest-ice.rs create mode 100644 tests/ui/suggestions/constrain-suggest-ice.stderr create mode 100644 tests/ui/suggestions/constrain-trait.fixed create mode 100644 tests/ui/suggestions/constrain-trait.rs create mode 100644 tests/ui/suggestions/constrain-trait.stderr create mode 100644 tests/ui/suggestions/copied-and-cloned.fixed create mode 100644 tests/ui/suggestions/copied-and-cloned.rs create mode 100644 tests/ui/suggestions/copied-and-cloned.stderr create mode 100644 tests/ui/suggestions/core-std-import-order-issue-83564.rs create mode 100644 tests/ui/suggestions/core-std-import-order-issue-83564.stderr create mode 100644 tests/ui/suggestions/count2len.rs create mode 100644 tests/ui/suggestions/count2len.stderr create mode 100644 tests/ui/suggestions/crate-or-module-typo.rs create mode 100644 tests/ui/suggestions/crate-or-module-typo.stderr create mode 100644 tests/ui/suggestions/deref-path-method.rs create mode 100644 tests/ui/suggestions/deref-path-method.stderr create mode 100644 tests/ui/suggestions/derive-clone-for-eq.fixed create mode 100644 tests/ui/suggestions/derive-clone-for-eq.rs create mode 100644 tests/ui/suggestions/derive-clone-for-eq.stderr create mode 100644 tests/ui/suggestions/derive-macro-missing-bounds.rs create mode 100644 tests/ui/suggestions/derive-macro-missing-bounds.stderr create mode 100644 tests/ui/suggestions/derive-trait-for-method-call.rs create mode 100644 tests/ui/suggestions/derive-trait-for-method-call.stderr create mode 100644 tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs create mode 100644 tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr create mode 100644 tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs create mode 100644 tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr create mode 100644 tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs create mode 100644 tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs create mode 100644 tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs create mode 100644 tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr create mode 100644 tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs create mode 100644 tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr create mode 100644 tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs create mode 100644 tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr create mode 100644 tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs create mode 100644 tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr create mode 100644 tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs create mode 100644 tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr create mode 100644 tests/ui/suggestions/dont-suggest-ref/simple.rs create mode 100644 tests/ui/suggestions/dont-suggest-ref/simple.stderr create mode 100644 tests/ui/suggestions/dont-suggest-try_into-in-macros.rs create mode 100644 tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr create mode 100644 tests/ui/suggestions/dont-suggest-ufcs-for-const.rs create mode 100644 tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr create mode 100644 tests/ui/suggestions/dont-try-removing-the-field.rs create mode 100644 tests/ui/suggestions/dont-try-removing-the-field.stderr create mode 100644 tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs create mode 100644 tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr create mode 100644 tests/ui/suggestions/enum-method-probe.fixed create mode 100644 tests/ui/suggestions/enum-method-probe.rs create mode 100644 tests/ui/suggestions/enum-method-probe.stderr create mode 100644 tests/ui/suggestions/enum-variant-arg-mismatch.rs create mode 100644 tests/ui/suggestions/enum-variant-arg-mismatch.stderr create mode 100644 tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs create mode 100644 tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr create mode 100644 tests/ui/suggestions/field-access-considering-privacy.rs create mode 100644 tests/ui/suggestions/field-access-considering-privacy.stderr create mode 100644 tests/ui/suggestions/field-access.fixed create mode 100644 tests/ui/suggestions/field-access.rs create mode 100644 tests/ui/suggestions/field-access.stderr create mode 100644 tests/ui/suggestions/field-has-method.rs create mode 100644 tests/ui/suggestions/field-has-method.stderr create mode 100644 tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs create mode 100644 tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr create mode 100644 tests/ui/suggestions/fn-missing-lifetime-in-item.rs create mode 100644 tests/ui/suggestions/fn-missing-lifetime-in-item.stderr create mode 100644 tests/ui/suggestions/fn-needing-specified-return-type-param.rs create mode 100644 tests/ui/suggestions/fn-needing-specified-return-type-param.stderr create mode 100644 tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs create mode 100644 tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr create mode 100644 tests/ui/suggestions/fn-or-tuple-struct-without-args.rs create mode 100644 tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr create mode 100644 tests/ui/suggestions/fn-to-method-deeply-nested.rs create mode 100644 tests/ui/suggestions/fn-to-method-deeply-nested.stderr create mode 100644 tests/ui/suggestions/fn-to-method.rs create mode 100644 tests/ui/suggestions/fn-to-method.stderr create mode 100644 tests/ui/suggestions/fn-trait-notation.fixed create mode 100644 tests/ui/suggestions/fn-trait-notation.rs create mode 100644 tests/ui/suggestions/fn-trait-notation.stderr create mode 100644 tests/ui/suggestions/for-i-in-vec.fixed create mode 100644 tests/ui/suggestions/for-i-in-vec.rs create mode 100644 tests/ui/suggestions/for-i-in-vec.stderr create mode 100644 tests/ui/suggestions/format-borrow.rs create mode 100644 tests/ui/suggestions/format-borrow.stderr create mode 100644 tests/ui/suggestions/if-let-typo.rs create mode 100644 tests/ui/suggestions/if-let-typo.stderr create mode 100644 tests/ui/suggestions/if-then-neeing-semi.rs create mode 100644 tests/ui/suggestions/if-then-neeing-semi.stderr create mode 100644 tests/ui/suggestions/ignore-nested-field-binding.fixed create mode 100644 tests/ui/suggestions/ignore-nested-field-binding.rs create mode 100644 tests/ui/suggestions/ignore-nested-field-binding.stderr create mode 100644 tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs create mode 100644 tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr create mode 100644 tests/ui/suggestions/imm-ref-trait-object-literal.rs create mode 100644 tests/ui/suggestions/imm-ref-trait-object-literal.stderr create mode 100644 tests/ui/suggestions/imm-ref-trait-object.rs create mode 100644 tests/ui/suggestions/imm-ref-trait-object.stderr create mode 100644 tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs create mode 100644 tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr create mode 100644 tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs create mode 100644 tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr create mode 100644 tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs create mode 100644 tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr create mode 100644 tests/ui/suggestions/impl-trait-missing-lifetime.rs create mode 100644 tests/ui/suggestions/impl-trait-missing-lifetime.stderr create mode 100644 tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs create mode 100644 tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr create mode 100644 tests/ui/suggestions/impl-trait-with-missing-bounds.rs create mode 100644 tests/ui/suggestions/impl-trait-with-missing-bounds.stderr create mode 100644 tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed create mode 100644 tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs create mode 100644 tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr create mode 100644 tests/ui/suggestions/import-trait-for-method-call.rs create mode 100644 tests/ui/suggestions/import-trait-for-method-call.stderr create mode 100644 tests/ui/suggestions/inner_type.fixed create mode 100644 tests/ui/suggestions/inner_type.rs create mode 100644 tests/ui/suggestions/inner_type.stderr create mode 100644 tests/ui/suggestions/inner_type2.rs create mode 100644 tests/ui/suggestions/inner_type2.stderr create mode 100644 tests/ui/suggestions/into-convert.rs create mode 100644 tests/ui/suggestions/into-convert.stderr create mode 100644 tests/ui/suggestions/into-str.rs create mode 100644 tests/ui/suggestions/into-str.stderr create mode 100644 tests/ui/suggestions/invalid-bin-op.rs create mode 100644 tests/ui/suggestions/invalid-bin-op.stderr create mode 100644 tests/ui/suggestions/issue-101065.fixed create mode 100644 tests/ui/suggestions/issue-101065.rs create mode 100644 tests/ui/suggestions/issue-101065.stderr create mode 100644 tests/ui/suggestions/issue-101421.rs create mode 100644 tests/ui/suggestions/issue-101421.stderr create mode 100644 tests/ui/suggestions/issue-101465.rs create mode 100644 tests/ui/suggestions/issue-101465.stderr create mode 100644 tests/ui/suggestions/issue-101623.rs create mode 100644 tests/ui/suggestions/issue-101623.stderr create mode 100644 tests/ui/suggestions/issue-101984.rs create mode 100644 tests/ui/suggestions/issue-101984.stderr create mode 100644 tests/ui/suggestions/issue-102354.rs create mode 100644 tests/ui/suggestions/issue-102354.stderr create mode 100644 tests/ui/suggestions/issue-102892.rs create mode 100644 tests/ui/suggestions/issue-102892.stderr create mode 100644 tests/ui/suggestions/issue-103112.rs create mode 100644 tests/ui/suggestions/issue-103112.stderr create mode 100644 tests/ui/suggestions/issue-104086-suggest-let.rs create mode 100644 tests/ui/suggestions/issue-104086-suggest-let.stderr create mode 100644 tests/ui/suggestions/issue-104287.rs create mode 100644 tests/ui/suggestions/issue-104287.stderr create mode 100644 tests/ui/suggestions/issue-104327.rs create mode 100644 tests/ui/suggestions/issue-104327.stderr create mode 100644 tests/ui/suggestions/issue-104328.rs create mode 100644 tests/ui/suggestions/issue-104328.stderr create mode 100644 tests/ui/suggestions/issue-105226.rs create mode 100644 tests/ui/suggestions/issue-105226.stderr create mode 100644 tests/ui/suggestions/issue-105494.rs create mode 100644 tests/ui/suggestions/issue-105494.stderr create mode 100644 tests/ui/suggestions/issue-105645.rs create mode 100644 tests/ui/suggestions/issue-105645.stderr create mode 100644 tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed create mode 100644 tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs create mode 100644 tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr create mode 100644 tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs create mode 100644 tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr create mode 100644 tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs create mode 100644 tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr create mode 100644 tests/ui/suggestions/issue-21673.rs create mode 100644 tests/ui/suggestions/issue-21673.stderr create mode 100644 tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs create mode 100644 tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr create mode 100644 tests/ui/suggestions/issue-52820.fixed create mode 100644 tests/ui/suggestions/issue-52820.rs create mode 100644 tests/ui/suggestions/issue-52820.stderr create mode 100644 tests/ui/suggestions/issue-53692.fixed create mode 100644 tests/ui/suggestions/issue-53692.rs create mode 100644 tests/ui/suggestions/issue-53692.stderr create mode 100644 tests/ui/suggestions/issue-57672.rs create mode 100644 tests/ui/suggestions/issue-59819.fixed create mode 100644 tests/ui/suggestions/issue-59819.rs create mode 100644 tests/ui/suggestions/issue-59819.stderr create mode 100644 tests/ui/suggestions/issue-61226.fixed create mode 100644 tests/ui/suggestions/issue-61226.rs create mode 100644 tests/ui/suggestions/issue-61226.stderr create mode 100644 tests/ui/suggestions/issue-61963.rs create mode 100644 tests/ui/suggestions/issue-61963.stderr create mode 100644 tests/ui/suggestions/issue-62843.rs create mode 100644 tests/ui/suggestions/issue-62843.stderr create mode 100644 tests/ui/suggestions/issue-64252-self-type.rs create mode 100644 tests/ui/suggestions/issue-64252-self-type.stderr create mode 100644 tests/ui/suggestions/issue-66968-suggest-sorted-words.rs create mode 100644 tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr create mode 100644 tests/ui/suggestions/issue-68049-1.rs create mode 100644 tests/ui/suggestions/issue-68049-1.stderr create mode 100644 tests/ui/suggestions/issue-68049-2.rs create mode 100644 tests/ui/suggestions/issue-68049-2.stderr create mode 100644 tests/ui/suggestions/issue-71394-no-from-impl.rs create mode 100644 tests/ui/suggestions/issue-71394-no-from-impl.stderr create mode 100644 tests/ui/suggestions/issue-72766.rs create mode 100644 tests/ui/suggestions/issue-72766.stderr create mode 100644 tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs create mode 100644 tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr create mode 100644 tests/ui/suggestions/issue-81098.rs create mode 100644 tests/ui/suggestions/issue-81098.stderr create mode 100644 tests/ui/suggestions/issue-81839.rs create mode 100644 tests/ui/suggestions/issue-81839.stderr create mode 100644 tests/ui/suggestions/issue-82361.fixed create mode 100644 tests/ui/suggestions/issue-82361.rs create mode 100644 tests/ui/suggestions/issue-82361.stderr create mode 100644 tests/ui/suggestions/issue-82566-1.rs create mode 100644 tests/ui/suggestions/issue-82566-1.stderr create mode 100644 tests/ui/suggestions/issue-82566-2.rs create mode 100644 tests/ui/suggestions/issue-82566-2.stderr create mode 100644 tests/ui/suggestions/issue-83892.fixed create mode 100644 tests/ui/suggestions/issue-83892.rs create mode 100644 tests/ui/suggestions/issue-83892.stderr create mode 100644 tests/ui/suggestions/issue-83943.fixed create mode 100644 tests/ui/suggestions/issue-83943.rs create mode 100644 tests/ui/suggestions/issue-83943.stderr create mode 100644 tests/ui/suggestions/issue-84592.rs create mode 100644 tests/ui/suggestions/issue-84592.stderr create mode 100644 tests/ui/suggestions/issue-84700.rs create mode 100644 tests/ui/suggestions/issue-84700.stderr create mode 100644 tests/ui/suggestions/issue-84973-2.rs create mode 100644 tests/ui/suggestions/issue-84973-2.stderr create mode 100644 tests/ui/suggestions/issue-84973-blacklist.rs create mode 100644 tests/ui/suggestions/issue-84973-blacklist.stderr create mode 100644 tests/ui/suggestions/issue-84973-negative.rs create mode 100644 tests/ui/suggestions/issue-84973-negative.stderr create mode 100644 tests/ui/suggestions/issue-84973.rs create mode 100644 tests/ui/suggestions/issue-84973.stderr create mode 100644 tests/ui/suggestions/issue-85347.rs create mode 100644 tests/ui/suggestions/issue-85347.stderr create mode 100644 tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs create mode 100644 tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr create mode 100644 tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs create mode 100644 tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr create mode 100644 tests/ui/suggestions/issue-86100-tuple-paren-comma.rs create mode 100644 tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr create mode 100644 tests/ui/suggestions/issue-86667.rs create mode 100644 tests/ui/suggestions/issue-86667.stderr create mode 100644 tests/ui/suggestions/issue-88730.rs create mode 100644 tests/ui/suggestions/issue-88730.stderr create mode 100644 tests/ui/suggestions/issue-89064.rs create mode 100644 tests/ui/suggestions/issue-89064.stderr create mode 100644 tests/ui/suggestions/issue-89333.rs create mode 100644 tests/ui/suggestions/issue-89333.stderr create mode 100644 tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs create mode 100644 tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr create mode 100644 tests/ui/suggestions/issue-90974.rs create mode 100644 tests/ui/suggestions/issue-90974.stderr create mode 100644 tests/ui/suggestions/issue-96223.rs create mode 100644 tests/ui/suggestions/issue-96223.stderr create mode 100644 tests/ui/suggestions/issue-96555.rs create mode 100644 tests/ui/suggestions/issue-96555.stderr create mode 100644 tests/ui/suggestions/issue-97677.fixed create mode 100644 tests/ui/suggestions/issue-97677.rs create mode 100644 tests/ui/suggestions/issue-97677.stderr create mode 100644 tests/ui/suggestions/issue-97704.fixed create mode 100644 tests/ui/suggestions/issue-97704.rs create mode 100644 tests/ui/suggestions/issue-97704.stderr create mode 100644 tests/ui/suggestions/issue-97760.rs create mode 100644 tests/ui/suggestions/issue-97760.stderr create mode 100644 tests/ui/suggestions/issue-98500.rs create mode 100644 tests/ui/suggestions/issue-98500.stderr create mode 100644 tests/ui/suggestions/issue-99080.rs create mode 100644 tests/ui/suggestions/issue-99080.stderr create mode 100644 tests/ui/suggestions/issue-99240-2.rs create mode 100644 tests/ui/suggestions/issue-99240-2.stderr create mode 100644 tests/ui/suggestions/issue-99240.rs create mode 100644 tests/ui/suggestions/issue-99240.stderr create mode 100644 tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs create mode 100644 tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr create mode 100644 tests/ui/suggestions/js-style-comparison-op.fixed create mode 100644 tests/ui/suggestions/js-style-comparison-op.rs create mode 100644 tests/ui/suggestions/js-style-comparison-op.stderr create mode 100644 tests/ui/suggestions/let-binding-init-expr-as-ty.rs create mode 100644 tests/ui/suggestions/let-binding-init-expr-as-ty.stderr create mode 100644 tests/ui/suggestions/lifetimes/issue-105544.fixed create mode 100644 tests/ui/suggestions/lifetimes/issue-105544.rs create mode 100644 tests/ui/suggestions/lifetimes/issue-105544.stderr create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs create mode 100644 tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr create mode 100644 tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs create mode 100644 tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr create mode 100644 tests/ui/suggestions/many-type-ascription.rs create mode 100644 tests/ui/suggestions/many-type-ascription.stderr create mode 100644 tests/ui/suggestions/match-ergonomics.rs create mode 100644 tests/ui/suggestions/match-ergonomics.stderr create mode 100644 tests/ui/suggestions/match-needing-semi.rs create mode 100644 tests/ui/suggestions/match-needing-semi.stderr create mode 100644 tests/ui/suggestions/match-prev-arm-needing-semi.rs create mode 100644 tests/ui/suggestions/match-prev-arm-needing-semi.stderr create mode 100644 tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs create mode 100644 tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr create mode 100644 tests/ui/suggestions/method-access-to-range-literal-typo.fixed create mode 100644 tests/ui/suggestions/method-access-to-range-literal-typo.rs create mode 100644 tests/ui/suggestions/method-access-to-range-literal-typo.stderr create mode 100644 tests/ui/suggestions/method-missing-parentheses.rs create mode 100644 tests/ui/suggestions/method-missing-parentheses.stderr create mode 100644 tests/ui/suggestions/mismatched-types-numeric-from.rs create mode 100644 tests/ui/suggestions/mismatched-types-numeric-from.stderr create mode 100644 tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed create mode 100644 tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs create mode 100644 tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr create mode 100644 tests/ui/suggestions/missing-assoc-fn.rs create mode 100644 tests/ui/suggestions/missing-assoc-fn.stderr create mode 100644 tests/ui/suggestions/missing-assoc-type-bound-restriction.rs create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs create mode 100644 tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr create mode 100644 tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed create mode 100644 tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs create mode 100644 tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr create mode 100644 tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed create mode 100644 tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs create mode 100644 tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr create mode 100644 tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs create mode 100644 tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr create mode 100644 tests/ui/suggestions/missing-lifetime-specifier.rs create mode 100644 tests/ui/suggestions/missing-lifetime-specifier.stderr create mode 100644 tests/ui/suggestions/missing-lt-for-hrtb.rs create mode 100644 tests/ui/suggestions/missing-lt-for-hrtb.stderr create mode 100644 tests/ui/suggestions/missing-trait-item.fixed create mode 100644 tests/ui/suggestions/missing-trait-item.rs create mode 100644 tests/ui/suggestions/missing-trait-item.stderr create mode 100644 tests/ui/suggestions/missing-type-param-used-in-param.fixed create mode 100644 tests/ui/suggestions/missing-type-param-used-in-param.rs create mode 100644 tests/ui/suggestions/missing-type-param-used-in-param.stderr create mode 100644 tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs create mode 100644 tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr create mode 100644 tests/ui/suggestions/multibyte-escapes.rs create mode 100644 tests/ui/suggestions/multibyte-escapes.stderr create mode 100644 tests/ui/suggestions/mut-borrow-needed-by-trait.rs create mode 100644 tests/ui/suggestions/mut-borrow-needed-by-trait.stderr create mode 100644 tests/ui/suggestions/mut-ref-reassignment.rs create mode 100644 tests/ui/suggestions/mut-ref-reassignment.stderr create mode 100644 tests/ui/suggestions/negative-literal-index.fixed create mode 100644 tests/ui/suggestions/negative-literal-index.rs create mode 100644 tests/ui/suggestions/negative-literal-index.stderr create mode 100644 tests/ui/suggestions/nested-non-tuple-tuple-struct.rs create mode 100644 tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr create mode 100644 tests/ui/suggestions/no-extern-crate-in-type.rs create mode 100644 tests/ui/suggestions/no-extern-crate-in-type.stderr create mode 100644 tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs create mode 100644 tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr create mode 100644 tests/ui/suggestions/non-existent-field-present-in-subfield.fixed create mode 100644 tests/ui/suggestions/non-existent-field-present-in-subfield.rs create mode 100644 tests/ui/suggestions/non-existent-field-present-in-subfield.stderr create mode 100644 tests/ui/suggestions/object-unsafe-trait-references-self.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-references-self.stderr create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs create mode 100644 tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr create mode 100644 tests/ui/suggestions/opaque-type-error.rs create mode 100644 tests/ui/suggestions/opaque-type-error.stderr create mode 100644 tests/ui/suggestions/option-content-move-from-tuple-match.rs create mode 100644 tests/ui/suggestions/option-content-move-from-tuple-match.stderr create mode 100644 tests/ui/suggestions/option-content-move.rs create mode 100644 tests/ui/suggestions/option-content-move.stderr create mode 100644 tests/ui/suggestions/option-content-move2.rs create mode 100644 tests/ui/suggestions/option-content-move2.stderr create mode 100644 tests/ui/suggestions/option-to-bool.rs create mode 100644 tests/ui/suggestions/option-to-bool.stderr create mode 100644 tests/ui/suggestions/parenthesized-deref-suggestion.rs create mode 100644 tests/ui/suggestions/parenthesized-deref-suggestion.stderr create mode 100644 tests/ui/suggestions/path-by-value.rs create mode 100644 tests/ui/suggestions/path-by-value.stderr create mode 100644 tests/ui/suggestions/path-display.rs create mode 100644 tests/ui/suggestions/path-display.stderr create mode 100644 tests/ui/suggestions/pattern-slice-vec.fixed create mode 100644 tests/ui/suggestions/pattern-slice-vec.rs create mode 100644 tests/ui/suggestions/pattern-slice-vec.stderr create mode 100644 tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs create mode 100644 tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr create mode 100644 tests/ui/suggestions/private-field.rs create mode 100644 tests/ui/suggestions/private-field.stderr create mode 100644 tests/ui/suggestions/raw-byte-string-prefix.rs create mode 100644 tests/ui/suggestions/raw-byte-string-prefix.stderr create mode 100644 tests/ui/suggestions/raw-name-use-suggestion.rs create mode 100644 tests/ui/suggestions/raw-name-use-suggestion.stderr create mode 100644 tests/ui/suggestions/recover-from-semicolon-trailing-item.rs create mode 100644 tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr create mode 100644 tests/ui/suggestions/recover-invalid-float.fixed create mode 100644 tests/ui/suggestions/recover-invalid-float.rs create mode 100644 tests/ui/suggestions/recover-invalid-float.stderr create mode 100644 tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs create mode 100644 tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr create mode 100644 tests/ui/suggestions/ref-pattern-binding.fixed create mode 100644 tests/ui/suggestions/ref-pattern-binding.rs create mode 100644 tests/ui/suggestions/ref-pattern-binding.stderr create mode 100644 tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs create mode 100644 tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr create mode 100644 tests/ui/suggestions/remove-as_str.rs create mode 100644 tests/ui/suggestions/remove-as_str.stderr create mode 100644 tests/ui/suggestions/restrict-type-argument.rs create mode 100644 tests/ui/suggestions/restrict-type-argument.stderr create mode 100644 tests/ui/suggestions/restrict-type-not-param.rs create mode 100644 tests/ui/suggestions/restrict-type-not-param.stderr create mode 100644 tests/ui/suggestions/return-bindings-multi.rs create mode 100644 tests/ui/suggestions/return-bindings-multi.stderr create mode 100644 tests/ui/suggestions/return-bindings.rs create mode 100644 tests/ui/suggestions/return-bindings.stderr create mode 100644 tests/ui/suggestions/return-closures.rs create mode 100644 tests/ui/suggestions/return-closures.stderr create mode 100644 tests/ui/suggestions/return-cycle-2.rs create mode 100644 tests/ui/suggestions/return-cycle-2.stderr create mode 100644 tests/ui/suggestions/return-cycle.rs create mode 100644 tests/ui/suggestions/return-cycle.stderr create mode 100644 tests/ui/suggestions/return-elided-lifetime.rs create mode 100644 tests/ui/suggestions/return-elided-lifetime.stderr create mode 100644 tests/ui/suggestions/return-without-lifetime.rs create mode 100644 tests/ui/suggestions/return-without-lifetime.stderr create mode 100644 tests/ui/suggestions/shadowed-lplace-method-2.rs create mode 100644 tests/ui/suggestions/shadowed-lplace-method-2.stderr create mode 100644 tests/ui/suggestions/shadowed-lplace-method.fixed create mode 100644 tests/ui/suggestions/shadowed-lplace-method.rs create mode 100644 tests/ui/suggestions/shadowed-lplace-method.stderr create mode 100644 tests/ui/suggestions/slice-issue-87994.rs create mode 100644 tests/ui/suggestions/slice-issue-87994.stderr create mode 100644 tests/ui/suggestions/struct-field-type-including-single-colon.rs create mode 100644 tests/ui/suggestions/struct-field-type-including-single-colon.stderr create mode 100644 tests/ui/suggestions/struct-initializer-comma.fixed create mode 100644 tests/ui/suggestions/struct-initializer-comma.rs create mode 100644 tests/ui/suggestions/struct-initializer-comma.stderr create mode 100644 tests/ui/suggestions/sugg-else-for-closure.fixed create mode 100644 tests/ui/suggestions/sugg-else-for-closure.rs create mode 100644 tests/ui/suggestions/sugg-else-for-closure.stderr create mode 100644 tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs create mode 100644 tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr create mode 100644 tests/ui/suggestions/suggest-add-self.rs create mode 100644 tests/ui/suggestions/suggest-add-self.stderr create mode 100644 tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed create mode 100644 tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs create mode 100644 tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-deref.rs create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs create mode 100644 tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr create mode 100644 tests/ui/suggestions/suggest-blanket-impl-local-trait.rs create mode 100644 tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr create mode 100644 tests/ui/suggestions/suggest-borrow-to-dyn-object.rs create mode 100644 tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr create mode 100644 tests/ui/suggestions/suggest-box.fixed create mode 100644 tests/ui/suggestions/suggest-box.rs create mode 100644 tests/ui/suggestions/suggest-box.stderr create mode 100644 tests/ui/suggestions/suggest-change-mut.rs create mode 100644 tests/ui/suggestions/suggest-change-mut.stderr create mode 100644 tests/ui/suggestions/suggest-closure-return-type-1.rs create mode 100644 tests/ui/suggestions/suggest-closure-return-type-1.stderr create mode 100644 tests/ui/suggestions/suggest-closure-return-type-2.rs create mode 100644 tests/ui/suggestions/suggest-closure-return-type-2.stderr create mode 100644 tests/ui/suggestions/suggest-closure-return-type-3.rs create mode 100644 tests/ui/suggestions/suggest-closure-return-type-3.stderr create mode 100644 tests/ui/suggestions/suggest-dereferencing-index.fixed create mode 100644 tests/ui/suggestions/suggest-dereferencing-index.rs create mode 100644 tests/ui/suggestions/suggest-dereferencing-index.stderr create mode 100644 tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs create mode 100644 tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr create mode 100644 tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs create mode 100644 tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr create mode 100644 tests/ui/suggestions/suggest-impl-trait-lifetime.fixed create mode 100644 tests/ui/suggestions/suggest-impl-trait-lifetime.rs create mode 100644 tests/ui/suggestions/suggest-impl-trait-lifetime.stderr create mode 100644 tests/ui/suggestions/suggest-labels.rs create mode 100644 tests/ui/suggestions/suggest-labels.stderr create mode 100644 tests/ui/suggestions/suggest-let-for-assignment.fixed create mode 100644 tests/ui/suggestions/suggest-let-for-assignment.rs create mode 100644 tests/ui/suggestions/suggest-let-for-assignment.stderr create mode 100644 tests/ui/suggestions/suggest-methods.rs create mode 100644 tests/ui/suggestions/suggest-methods.stderr create mode 100644 tests/ui/suggestions/suggest-move-lifetimes.rs create mode 100644 tests/ui/suggestions/suggest-move-lifetimes.stderr create mode 100644 tests/ui/suggestions/suggest-move-types.rs create mode 100644 tests/ui/suggestions/suggest-move-types.stderr create mode 100644 tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed create mode 100644 tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs create mode 100644 tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr create mode 100644 tests/ui/suggestions/suggest-mut-method-for-loop.rs create mode 100644 tests/ui/suggestions/suggest-mut-method-for-loop.stderr create mode 100644 tests/ui/suggestions/suggest-on-bare-closure-call.rs create mode 100644 tests/ui/suggestions/suggest-on-bare-closure-call.stderr create mode 100644 tests/ui/suggestions/suggest-ref-macro.rs create mode 100644 tests/ui/suggestions/suggest-ref-macro.stderr create mode 100644 tests/ui/suggestions/suggest-ref-mut.rs create mode 100644 tests/ui/suggestions/suggest-ref-mut.stderr create mode 100644 tests/ui/suggestions/suggest-remove-refs-1.fixed create mode 100644 tests/ui/suggestions/suggest-remove-refs-1.rs create mode 100644 tests/ui/suggestions/suggest-remove-refs-1.stderr create mode 100644 tests/ui/suggestions/suggest-remove-refs-2.fixed create mode 100644 tests/ui/suggestions/suggest-remove-refs-2.rs create mode 100644 tests/ui/suggestions/suggest-remove-refs-2.stderr create mode 100644 tests/ui/suggestions/suggest-remove-refs-3.fixed create mode 100644 tests/ui/suggestions/suggest-remove-refs-3.rs create mode 100644 tests/ui/suggestions/suggest-remove-refs-3.stderr create mode 100644 tests/ui/suggestions/suggest-remove-refs-4.fixed create mode 100644 tests/ui/suggestions/suggest-remove-refs-4.rs create mode 100644 tests/ui/suggestions/suggest-remove-refs-4.stderr create mode 100644 tests/ui/suggestions/suggest-remove-refs-5.fixed create mode 100644 tests/ui/suggestions/suggest-remove-refs-5.rs create mode 100644 tests/ui/suggestions/suggest-remove-refs-5.stderr create mode 100644 tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed create mode 100644 tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs create mode 100644 tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr create mode 100644 tests/ui/suggestions/suggest-split-at-mut.rs create mode 100644 tests/ui/suggestions/suggest-split-at-mut.stderr create mode 100644 tests/ui/suggestions/suggest-std-when-using-type.fixed create mode 100644 tests/ui/suggestions/suggest-std-when-using-type.rs create mode 100644 tests/ui/suggestions/suggest-std-when-using-type.stderr create mode 100644 tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs create mode 100644 tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr create mode 100644 tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs create mode 100644 tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr create mode 100644 tests/ui/suggestions/suggest-trait-items.rs create mode 100644 tests/ui/suggestions/suggest-trait-items.stderr create mode 100644 tests/ui/suggestions/suggest-tryinto-edition-change.rs create mode 100644 tests/ui/suggestions/suggest-tryinto-edition-change.stderr create mode 100644 tests/ui/suggestions/suggest-using-chars.rs create mode 100644 tests/ui/suggestions/suggest-using-chars.stderr create mode 100644 tests/ui/suggestions/suggest-variants.rs create mode 100644 tests/ui/suggestions/suggest-variants.stderr create mode 100644 tests/ui/suggestions/suggest_print_over_printf.rs create mode 100644 tests/ui/suggestions/suggest_print_over_printf.stderr create mode 100644 tests/ui/suggestions/too-many-field-suggestions.rs create mode 100644 tests/ui/suggestions/too-many-field-suggestions.stderr create mode 100644 tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed create mode 100644 tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs create mode 100644 tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr create mode 100644 tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs create mode 100644 tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr create mode 100644 tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs create mode 100644 tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr create mode 100644 tests/ui/suggestions/try-removing-the-field.rs create mode 100644 tests/ui/suggestions/try-removing-the-field.stderr create mode 100644 tests/ui/suggestions/type-ascription-and-other-error.rs create mode 100644 tests/ui/suggestions/type-ascription-and-other-error.stderr create mode 100644 tests/ui/suggestions/type-ascription-instead-of-let.rs create mode 100644 tests/ui/suggestions/type-ascription-instead-of-let.stderr create mode 100644 tests/ui/suggestions/type-ascription-instead-of-method.fixed create mode 100644 tests/ui/suggestions/type-ascription-instead-of-method.rs create mode 100644 tests/ui/suggestions/type-ascription-instead-of-method.stderr create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path-2.fixed create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path-2.rs create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path-2.stderr create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path.rs create mode 100644 tests/ui/suggestions/type-ascription-instead-of-path.stderr create mode 100644 tests/ui/suggestions/type-ascription-instead-of-variant.fixed create mode 100644 tests/ui/suggestions/type-ascription-instead-of-variant.rs create mode 100644 tests/ui/suggestions/type-ascription-instead-of-variant.stderr create mode 100644 tests/ui/suggestions/type-mismatch-byte-literal.rs create mode 100644 tests/ui/suggestions/type-mismatch-byte-literal.stderr create mode 100644 tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs create mode 100644 tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr create mode 100644 tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed create mode 100644 tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs create mode 100644 tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr create mode 100644 tests/ui/suggestions/type-not-found-in-adt-field.rs create mode 100644 tests/ui/suggestions/type-not-found-in-adt-field.stderr create mode 100644 tests/ui/suggestions/undeclared-module-alloc.rs create mode 100644 tests/ui/suggestions/undeclared-module-alloc.stderr create mode 100644 tests/ui/suggestions/unnamable-types.rs create mode 100644 tests/ui/suggestions/unnamable-types.stderr create mode 100644 tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs create mode 100644 tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr create mode 100644 tests/ui/suggestions/unsized-function-parameter.fixed create mode 100644 tests/ui/suggestions/unsized-function-parameter.rs create mode 100644 tests/ui/suggestions/unsized-function-parameter.stderr create mode 100644 tests/ui/suggestions/unused-closure-argument.rs create mode 100644 tests/ui/suggestions/unused-closure-argument.stderr create mode 100644 tests/ui/suggestions/use-placement-resolve.fixed create mode 100644 tests/ui/suggestions/use-placement-resolve.rs create mode 100644 tests/ui/suggestions/use-placement-resolve.stderr create mode 100644 tests/ui/suggestions/use-placement-typeck.fixed create mode 100644 tests/ui/suggestions/use-placement-typeck.rs create mode 100644 tests/ui/suggestions/use-placement-typeck.stderr create mode 100644 tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs create mode 100644 tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr create mode 100644 tests/ui/suggestions/while-let-typo.rs create mode 100644 tests/ui/suggestions/while-let-typo.stderr create mode 100644 tests/ui/super-at-top-level.rs create mode 100644 tests/ui/super-at-top-level.stderr create mode 100644 tests/ui/super-fast-paren-parsing.rs create mode 100644 tests/ui/super.rs create mode 100644 tests/ui/suppressed-error.rs create mode 100644 tests/ui/suppressed-error.stderr create mode 100644 tests/ui/svh-add-nothing.rs create mode 100644 tests/ui/svh/auxiliary/changing-crates-a1.rs create mode 100644 tests/ui/svh/auxiliary/changing-crates-a2.rs create mode 100644 tests/ui/svh/auxiliary/changing-crates-b.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-base.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-change-lit.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-change-significant-cfg.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-change-trait-bound.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-change-type-arg.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-change-type-ret.rs create mode 100644 tests/ui/svh/auxiliary/svh-a-change-type-static.rs create mode 100644 tests/ui/svh/auxiliary/svh-b.rs create mode 100644 tests/ui/svh/auxiliary/svh-uta-base.rs create mode 100644 tests/ui/svh/auxiliary/svh-uta-change-use-trait.rs create mode 100644 tests/ui/svh/auxiliary/svh-utb.rs create mode 100644 tests/ui/svh/changing-crates.rs create mode 100644 tests/ui/svh/changing-crates.stderr create mode 100644 tests/ui/svh/svh-change-lit.rs create mode 100644 tests/ui/svh/svh-change-lit.stderr create mode 100644 tests/ui/svh/svh-change-significant-cfg.rs create mode 100644 tests/ui/svh/svh-change-significant-cfg.stderr create mode 100644 tests/ui/svh/svh-change-trait-bound.rs create mode 100644 tests/ui/svh/svh-change-trait-bound.stderr create mode 100644 tests/ui/svh/svh-change-type-arg.rs create mode 100644 tests/ui/svh/svh-change-type-arg.stderr create mode 100644 tests/ui/svh/svh-change-type-ret.rs create mode 100644 tests/ui/svh/svh-change-type-ret.stderr create mode 100644 tests/ui/svh/svh-change-type-static.rs create mode 100644 tests/ui/svh/svh-change-type-static.stderr create mode 100644 tests/ui/svh/svh-use-trait.rs create mode 100644 tests/ui/svh/svh-use-trait.stderr create mode 100644 tests/ui/swap-1.rs create mode 100644 tests/ui/swap-overlapping.rs create mode 100644 tests/ui/switched-expectations.rs create mode 100644 tests/ui/switched-expectations.stderr create mode 100644 tests/ui/symbol-names/basic.legacy.stderr create mode 100644 tests/ui/symbol-names/basic.rs create mode 100644 tests/ui/symbol-names/basic.v0.stderr create mode 100644 tests/ui/symbol-names/const-generics-demangling.legacy.stderr create mode 100644 tests/ui/symbol-names/const-generics-demangling.rs create mode 100644 tests/ui/symbol-names/const-generics-demangling.v0.stderr create mode 100644 tests/ui/symbol-names/const-generics-str-demangling.rs create mode 100644 tests/ui/symbol-names/const-generics-str-demangling.stderr create mode 100644 tests/ui/symbol-names/const-generics-structural-demangling.rs create mode 100644 tests/ui/symbol-names/const-generics-structural-demangling.stderr create mode 100644 tests/ui/symbol-names/const-generics.rs create mode 100644 tests/ui/symbol-names/foreign-types.rs create mode 100644 tests/ui/symbol-names/foreign-types.stderr create mode 100644 tests/ui/symbol-names/impl1.legacy.stderr create mode 100644 tests/ui/symbol-names/impl1.rs create mode 100644 tests/ui/symbol-names/impl1.v0.stderr create mode 100644 tests/ui/symbol-names/impl2.rs create mode 100644 tests/ui/symbol-names/impl2.stderr create mode 100644 tests/ui/symbol-names/issue-53912.rs create mode 100644 tests/ui/symbol-names/issue-60925.legacy.stderr create mode 100644 tests/ui/symbol-names/issue-60925.rs create mode 100644 tests/ui/symbol-names/issue-60925.v0.stderr create mode 100644 tests/ui/symbol-names/issue-75326.legacy.stderr create mode 100644 tests/ui/symbol-names/issue-75326.rs create mode 100644 tests/ui/symbol-names/issue-75326.v0.stderr create mode 100644 tests/ui/symbol-names/issue-76365.rs create mode 100644 tests/ui/symbol-names/trait-objects.rs create mode 100644 tests/ui/symbol-names/trait-objects.v0.stderr create mode 100644 tests/ui/symbol-names/types.legacy.stderr create mode 100644 tests/ui/symbol-names/types.rs create mode 100644 tests/ui/symbol-names/types.verbose-legacy.stderr create mode 100644 tests/ui/symbol-names/verbose.rs create mode 100644 tests/ui/symbol-names/x86-stdcall.rs create mode 100644 tests/ui/syntax-extension-minor.rs create mode 100644 tests/ui/tag-that-dare-not-speak-its-name.rs create mode 100644 tests/ui/tag-that-dare-not-speak-its-name.stderr create mode 100644 tests/ui/tag-type-args.rs create mode 100644 tests/ui/tag-type-args.stderr create mode 100644 tests/ui/tag-variant-cast-non-nullary.fixed create mode 100644 tests/ui/tag-variant-cast-non-nullary.rs create mode 100644 tests/ui/tag-variant-cast-non-nullary.stderr create mode 100644 tests/ui/tail-call-arg-leak.rs create mode 100644 tests/ui/tail-cps.rs create mode 100644 tests/ui/tail-typeck.rs create mode 100644 tests/ui/tail-typeck.stderr create mode 100644 tests/ui/target-feature/aarch64-neon-works.rs create mode 100644 tests/ui/target-feature/feature-hierarchy.rs create mode 100644 tests/ui/target-feature/gate.rs create mode 100644 tests/ui/target-feature/gate.stderr create mode 100644 tests/ui/target-feature/invalid-attribute.rs create mode 100644 tests/ui/target-feature/invalid-attribute.stderr create mode 100644 tests/ui/target-feature/missing-plusminus-2.rs create mode 100644 tests/ui/target-feature/missing-plusminus-2.stderr create mode 100644 tests/ui/target-feature/missing-plusminus.rs create mode 100644 tests/ui/target-feature/missing-plusminus.stderr create mode 100644 tests/ui/target-feature/no-llvm-leaks.rs create mode 100644 tests/ui/target-feature/rust-specific-name-no-warnings.rs create mode 100644 tests/ui/target-feature/similar-feature-suggestion.rs create mode 100644 tests/ui/target-feature/similar-feature-suggestion.stderr create mode 100644 tests/ui/target-feature/tied-features-cli.one.stderr create mode 100644 tests/ui/target-feature/tied-features-cli.rs create mode 100644 tests/ui/target-feature/tied-features-cli.three.stderr create mode 100644 tests/ui/target-feature/tied-features-cli.two.stderr create mode 100644 tests/ui/target-feature/tied-features.rs create mode 100644 tests/ui/target-feature/tied-features.stderr create mode 100644 tests/ui/target-feature/wasm-safe.rs create mode 100644 tests/ui/terr-in-field.rs create mode 100644 tests/ui/terr-in-field.stderr create mode 100644 tests/ui/terr-sorts.rs create mode 100644 tests/ui/terr-sorts.stderr create mode 100644 tests/ui/test-attrs/auxiliary/test_macro.rs create mode 100644 tests/ui/test-attrs/decl-macro-test.rs create mode 100644 tests/ui/test-attrs/inaccessible-test-modules.rs create mode 100644 tests/ui/test-attrs/inaccessible-test-modules.stderr create mode 100644 tests/ui/test-attrs/issue-16597-empty.rs create mode 100644 tests/ui/test-attrs/issue-16597.rs create mode 100644 tests/ui/test-attrs/issue-20823.rs create mode 100644 tests/ui/test-attrs/issue-36768.rs create mode 100644 tests/ui/test-attrs/issue-52557.rs create mode 100644 tests/ui/test-attrs/issue-53675-a-test-called-panic.rs create mode 100644 tests/ui/test-attrs/run-unexported-tests.rs create mode 100644 tests/ui/test-attrs/test-attr-non-associated-functions.rs create mode 100644 tests/ui/test-attrs/test-attr-non-associated-functions.stderr create mode 100644 tests/ui/test-attrs/test-cant-be-shadowed.rs create mode 100644 tests/ui/test-attrs/test-filter-multiple.rs create mode 100644 tests/ui/test-attrs/test-filter-multiple.run.stdout create mode 100644 tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs create mode 100644 tests/ui/test-attrs/test-main-not-dead-attr.rs create mode 100644 tests/ui/test-attrs/test-main-not-dead.rs create mode 100644 tests/ui/test-attrs/test-on-not-fn.rs create mode 100644 tests/ui/test-attrs/test-on-not-fn.stderr create mode 100644 tests/ui/test-attrs/test-panic-abort-disabled.rs create mode 100644 tests/ui/test-attrs/test-panic-abort-disabled.stderr create mode 100644 tests/ui/test-attrs/test-panic-abort-nocapture.rs create mode 100644 tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr create mode 100644 tests/ui/test-attrs/test-panic-abort-nocapture.run.stdout create mode 100644 tests/ui/test-attrs/test-panic-abort.rs create mode 100644 tests/ui/test-attrs/test-panic-abort.run.stdout create mode 100644 tests/ui/test-attrs/test-panic-while-printing.rs create mode 100644 tests/ui/test-attrs/test-passed-wasm.rs create mode 100644 tests/ui/test-attrs/test-passed-wasm.run.stdout create mode 100644 tests/ui/test-attrs/test-passed.rs create mode 100644 tests/ui/test-attrs/test-passed.run.stdout create mode 100644 tests/ui/test-attrs/test-runner-hides-buried-main.rs create mode 100644 tests/ui/test-attrs/test-runner-hides-main.rs create mode 100644 tests/ui/test-attrs/test-runner-hides-start.rs create mode 100644 tests/ui/test-attrs/test-should-fail-good-message.rs create mode 100644 tests/ui/test-attrs/test-should-panic-attr.rs create mode 100644 tests/ui/test-attrs/test-should-panic-attr.stderr create mode 100644 tests/ui/test-attrs/test-thread-capture.rs create mode 100644 tests/ui/test-attrs/test-thread-capture.run.stdout create mode 100644 tests/ui/test-attrs/test-thread-nocapture.rs create mode 100644 tests/ui/test-attrs/test-thread-nocapture.run.stderr create mode 100644 tests/ui/test-attrs/test-thread-nocapture.run.stdout create mode 100644 tests/ui/test-attrs/test-type.rs create mode 100644 tests/ui/test-attrs/test-type.run.stdout create mode 100644 tests/ui/test-attrs/test-vs-cfg-test.rs create mode 100644 tests/ui/test-attrs/test-warns-dead-code.rs create mode 100644 tests/ui/test-attrs/test-warns-dead-code.stderr create mode 100644 tests/ui/thir-tree.rs create mode 100644 tests/ui/thir-tree.stdout create mode 100644 tests/ui/thread-local-mutation.rs create mode 100644 tests/ui/thread-local-mutation.stderr create mode 100644 tests/ui/thread-local-static.rs create mode 100644 tests/ui/thread-local-static.stderr create mode 100644 tests/ui/thread-local/name-collision.rs create mode 100644 tests/ui/thread-local/non-static.rs create mode 100644 tests/ui/thread-local/non-static.stderr create mode 100644 tests/ui/thread-local/thread-local-issue-37508.rs create mode 100644 tests/ui/thread-local/tls.rs create mode 100644 tests/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs create mode 100644 tests/ui/threads-sendsync/child-outlives-parent.rs create mode 100644 tests/ui/threads-sendsync/clone-with-exterior.rs create mode 100644 tests/ui/threads-sendsync/comm.rs create mode 100644 tests/ui/threads-sendsync/eprint-on-tls-drop.rs create mode 100644 tests/ui/threads-sendsync/issue-24313.rs create mode 100644 tests/ui/threads-sendsync/issue-29488.rs create mode 100644 tests/ui/threads-sendsync/issue-43733-2.rs create mode 100644 tests/ui/threads-sendsync/issue-43733.mir.stderr create mode 100644 tests/ui/threads-sendsync/issue-43733.rs create mode 100644 tests/ui/threads-sendsync/issue-43733.thir.stderr create mode 100644 tests/ui/threads-sendsync/issue-4446.rs create mode 100644 tests/ui/threads-sendsync/issue-4448.rs create mode 100644 tests/ui/threads-sendsync/issue-8827.rs create mode 100644 tests/ui/threads-sendsync/issue-9396.rs create mode 100644 tests/ui/threads-sendsync/mpsc_stress.rs create mode 100644 tests/ui/threads-sendsync/send-is-not-static-par-for.rs create mode 100644 tests/ui/threads-sendsync/send-resource.rs create mode 100644 tests/ui/threads-sendsync/send-type-inference.rs create mode 100644 tests/ui/threads-sendsync/send_str_hashmap.rs create mode 100644 tests/ui/threads-sendsync/send_str_treemap.rs create mode 100644 tests/ui/threads-sendsync/sendable-class.rs create mode 100644 tests/ui/threads-sendsync/sendfn-is-a-block.rs create mode 100644 tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs create mode 100644 tests/ui/threads-sendsync/spawn-fn.rs create mode 100644 tests/ui/threads-sendsync/spawn-types.rs create mode 100644 tests/ui/threads-sendsync/spawn.rs create mode 100644 tests/ui/threads-sendsync/spawn2.rs create mode 100644 tests/ui/threads-sendsync/spawning-with-debug.rs create mode 100644 tests/ui/threads-sendsync/std-sync-right-kind-impls.rs create mode 100644 tests/ui/threads-sendsync/sync-send-atomics.rs create mode 100644 tests/ui/threads-sendsync/sync-send-in-std.rs create mode 100644 tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs create mode 100644 tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs create mode 100644 tests/ui/threads-sendsync/task-comm-0.rs create mode 100644 tests/ui/threads-sendsync/task-comm-1.rs create mode 100644 tests/ui/threads-sendsync/task-comm-10.rs create mode 100644 tests/ui/threads-sendsync/task-comm-11.rs create mode 100644 tests/ui/threads-sendsync/task-comm-12.rs create mode 100644 tests/ui/threads-sendsync/task-comm-13.rs create mode 100644 tests/ui/threads-sendsync/task-comm-14.rs create mode 100644 tests/ui/threads-sendsync/task-comm-15.rs create mode 100644 tests/ui/threads-sendsync/task-comm-16.rs create mode 100644 tests/ui/threads-sendsync/task-comm-17.rs create mode 100644 tests/ui/threads-sendsync/task-comm-3.rs create mode 100644 tests/ui/threads-sendsync/task-comm-4.rs create mode 100644 tests/ui/threads-sendsync/task-comm-5.rs create mode 100644 tests/ui/threads-sendsync/task-comm-6.rs create mode 100644 tests/ui/threads-sendsync/task-comm-7.rs create mode 100644 tests/ui/threads-sendsync/task-comm-9.rs create mode 100644 tests/ui/threads-sendsync/task-comm-chan-nil.rs create mode 100644 tests/ui/threads-sendsync/task-life-0.rs create mode 100644 tests/ui/threads-sendsync/task-spawn-barefn.rs create mode 100644 tests/ui/threads-sendsync/task-spawn-move-and-copy.rs create mode 100644 tests/ui/threads-sendsync/task-stderr.rs create mode 100644 tests/ui/threads-sendsync/tcp-stress.rs create mode 100644 tests/ui/threads-sendsync/test-tasks-invalid-value.rs create mode 100644 tests/ui/threads-sendsync/thread-local-extern-static.rs create mode 100644 tests/ui/threads-sendsync/thread-local-syntax.rs create mode 100644 tests/ui/threads-sendsync/threads.rs create mode 100644 tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs create mode 100644 tests/ui/threads-sendsync/tls-init-on-init.rs create mode 100644 tests/ui/threads-sendsync/tls-try-with.rs create mode 100644 tests/ui/threads-sendsync/trivial-message.rs create mode 100644 tests/ui/threads-sendsync/unwind-resource.rs create mode 100644 tests/ui/threads-sendsync/yield.rs create mode 100644 tests/ui/threads-sendsync/yield1.rs create mode 100644 tests/ui/threads-sendsync/yield2.rs create mode 100644 tests/ui/tool-attributes/diagnostic_item.rs create mode 100644 tests/ui/tool-attributes/diagnostic_item.stderr create mode 100644 tests/ui/tool-attributes/diagnostic_item2.rs create mode 100644 tests/ui/tool-attributes/diagnostic_item3.rs create mode 100644 tests/ui/tool-attributes/tool-attributes-misplaced-1.rs create mode 100644 tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr create mode 100644 tests/ui/tool-attributes/tool-attributes-misplaced-2.rs create mode 100644 tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr create mode 100644 tests/ui/tool-attributes/tool-attributes-shadowing.rs create mode 100644 tests/ui/tool-attributes/tool-attributes-shadowing.stderr create mode 100644 tests/ui/tool_lints-fail.rs create mode 100644 tests/ui/tool_lints-fail.stderr create mode 100644 tests/ui/tool_lints-rpass.rs create mode 100644 tests/ui/tool_lints.rs create mode 100644 tests/ui/tool_lints.stderr create mode 100644 tests/ui/tool_lints_2018_preview.rs create mode 100644 tests/ui/track-diagnostics/track.rs create mode 100644 tests/ui/track-diagnostics/track.stderr create mode 100644 tests/ui/track-diagnostics/track2.rs create mode 100644 tests/ui/track-diagnostics/track2.stderr create mode 100644 tests/ui/track-diagnostics/track3.rs create mode 100644 tests/ui/track-diagnostics/track3.stderr create mode 100644 tests/ui/track-diagnostics/track4.rs create mode 100644 tests/ui/track-diagnostics/track4.stderr create mode 100644 tests/ui/track-diagnostics/track5.rs create mode 100644 tests/ui/track-diagnostics/track5.stderr create mode 100644 tests/ui/track-diagnostics/track6.rs create mode 100644 tests/ui/track-diagnostics/track6.stderr create mode 100644 tests/ui/trailing-comma.rs create mode 100644 tests/ui/trait-bounds/impl-bound-with-references-error.rs create mode 100644 tests/ui/trait-bounds/impl-bound-with-references-error.stderr create mode 100644 tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs create mode 100644 tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr create mode 100644 tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs create mode 100644 tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr create mode 100644 tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs create mode 100644 tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr create mode 100644 tests/ui/trait-bounds/issue-75961.rs create mode 100644 tests/ui/trait-bounds/issue-93008.rs create mode 100644 tests/ui/trait-bounds/issue-94680.rs create mode 100644 tests/ui/trait-bounds/issue-94999.rs create mode 100644 tests/ui/trait-bounds/issue-95640.rs create mode 100644 tests/ui/trait-bounds/mismatch-fn-trait.rs create mode 100644 tests/ui/trait-bounds/mismatch-fn-trait.stderr create mode 100644 tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed create mode 100644 tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs create mode 100644 tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr create mode 100644 tests/ui/trait-bounds/unsized-bound.rs create mode 100644 tests/ui/trait-bounds/unsized-bound.stderr create mode 100644 tests/ui/trait-impl-bound-suggestions.fixed create mode 100644 tests/ui/trait-impl-bound-suggestions.rs create mode 100644 tests/ui/trait-impl-bound-suggestions.stderr create mode 100644 tests/ui/trait-method-number-parameters.rs create mode 100644 tests/ui/trait-method-number-parameters.stderr create mode 100644 tests/ui/traits/alias/ambiguous.rs create mode 100644 tests/ui/traits/alias/ambiguous.stderr create mode 100644 tests/ui/traits/alias/auxiliary/greeter.rs create mode 100644 tests/ui/traits/alias/auxiliary/send_sync.rs create mode 100644 tests/ui/traits/alias/basic.rs create mode 100644 tests/ui/traits/alias/bounds.rs create mode 100644 tests/ui/traits/alias/cross-crate.rs create mode 100644 tests/ui/traits/alias/cross-crate.stderr create mode 100644 tests/ui/traits/alias/generic-default-in-dyn.rs create mode 100644 tests/ui/traits/alias/generic-default-in-dyn.stderr create mode 100644 tests/ui/traits/alias/impl.rs create mode 100644 tests/ui/traits/alias/impl.stderr create mode 100644 tests/ui/traits/alias/import-cross-crate.rs create mode 100644 tests/ui/traits/alias/import.rs create mode 100644 tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs create mode 100644 tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs create mode 100644 tests/ui/traits/alias/issue-75983.rs create mode 100644 tests/ui/traits/alias/issue-83613.rs create mode 100644 tests/ui/traits/alias/issue-83613.stderr create mode 100644 tests/ui/traits/alias/maybe-bound.rs create mode 100644 tests/ui/traits/alias/no-duplicates.rs create mode 100644 tests/ui/traits/alias/no-duplicates.stderr create mode 100644 tests/ui/traits/alias/no-extra-traits.rs create mode 100644 tests/ui/traits/alias/no-extra-traits.stderr create mode 100644 tests/ui/traits/alias/object-fail.rs create mode 100644 tests/ui/traits/alias/object-fail.stderr create mode 100644 tests/ui/traits/alias/object-wf.rs create mode 100644 tests/ui/traits/alias/object.rs create mode 100644 tests/ui/traits/alias/only-maybe-bound.rs create mode 100644 tests/ui/traits/alias/only-maybe-bound.stderr create mode 100644 tests/ui/traits/alias/self-in-const-generics.rs create mode 100644 tests/ui/traits/alias/self-in-const-generics.stderr create mode 100644 tests/ui/traits/alias/self-in-generics.rs create mode 100644 tests/ui/traits/alias/self-in-generics.stderr create mode 100644 tests/ui/traits/alias/style_lint.rs create mode 100644 tests/ui/traits/alias/style_lint.stderr create mode 100644 tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed create mode 100644 tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs create mode 100644 tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr create mode 100644 tests/ui/traits/alias/syntax-fail.rs create mode 100644 tests/ui/traits/alias/syntax-fail.stderr create mode 100644 tests/ui/traits/alias/syntax.rs create mode 100644 tests/ui/traits/alias/wf.rs create mode 100644 tests/ui/traits/alias/wf.stderr create mode 100644 tests/ui/traits/alignment-gep-tup-like-1.rs create mode 100644 tests/ui/traits/anon-static-method.rs create mode 100644 tests/ui/traits/anon_trait_static_method_exe.rs create mode 100644 tests/ui/traits/as-struct-constructor.rs create mode 100644 tests/ui/traits/as-struct-constructor.stderr create mode 100644 tests/ui/traits/assignability-trait.rs create mode 100644 tests/ui/traits/assoc-type-in-superbad.rs create mode 100644 tests/ui/traits/assoc-type-in-superbad.stderr create mode 100644 tests/ui/traits/assoc-type-in-supertrait.rs create mode 100644 tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs create mode 100644 tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs create mode 100644 tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr create mode 100644 tests/ui/traits/associated_type_bound/issue-51446.rs create mode 100644 tests/ui/traits/astconv-cycle-between-and-type.rs create mode 100644 tests/ui/traits/augmented-assignments-trait.rs create mode 100644 tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs create mode 100644 tests/ui/traits/auxiliary/go_trait.rs create mode 100644 tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs create mode 100644 tests/ui/traits/auxiliary/trait_safety_lib.rs create mode 100644 tests/ui/traits/auxiliary/traitimpl.rs create mode 100644 tests/ui/traits/bad-method-typaram-kind.rs create mode 100644 tests/ui/traits/bad-method-typaram-kind.stderr create mode 100644 tests/ui/traits/bad-sized.rs create mode 100644 tests/ui/traits/bad-sized.stderr create mode 100644 tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs create mode 100644 tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr create mode 100644 tests/ui/traits/bound/auxiliary/crate_a1.rs create mode 100644 tests/ui/traits/bound/auxiliary/crate_a2.rs create mode 100644 tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs create mode 100644 tests/ui/traits/bound/basic.rs create mode 100644 tests/ui/traits/bound/generic_trait.rs create mode 100644 tests/ui/traits/bound/impl-comparison-duplicates.rs create mode 100644 tests/ui/traits/bound/in-arc.rs create mode 100644 tests/ui/traits/bound/multiple.rs create mode 100644 tests/ui/traits/bound/not-on-bare-trait.rs create mode 100644 tests/ui/traits/bound/not-on-bare-trait.stderr create mode 100644 tests/ui/traits/bound/not-on-struct.rs create mode 100644 tests/ui/traits/bound/not-on-struct.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums-in-fns.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums-in-impls.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums-locals.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-locals.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums-rpass.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-static.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-static.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums-xc.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-xc.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums-xc1.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums-xc1.stderr create mode 100644 tests/ui/traits/bound/on-structs-and-enums.rs create mode 100644 tests/ui/traits/bound/on-structs-and-enums.stderr create mode 100644 tests/ui/traits/bound/recursion.rs create mode 100644 tests/ui/traits/bound/same-crate-name.rs create mode 100644 tests/ui/traits/bound/same-crate-name.stderr create mode 100644 tests/ui/traits/bound/sugar.rs create mode 100644 tests/ui/traits/bound/sugar.stderr create mode 100644 tests/ui/traits/bug-7183-generics.rs create mode 100644 tests/ui/traits/bug-7295.rs create mode 100644 tests/ui/traits/cache-issue-18209.rs create mode 100644 tests/ui/traits/cache-reached-depth-ice.rs create mode 100644 tests/ui/traits/cache-reached-depth-ice.stderr create mode 100644 tests/ui/traits/coercion-generic-bad.rs create mode 100644 tests/ui/traits/coercion-generic-bad.stderr create mode 100644 tests/ui/traits/coercion-generic-regions.rs create mode 100644 tests/ui/traits/coercion-generic-regions.stderr create mode 100644 tests/ui/traits/coercion-generic.rs create mode 100644 tests/ui/traits/coercion.rs create mode 100644 tests/ui/traits/composition-trivial.rs create mode 100644 tests/ui/traits/conditional-dispatch.rs create mode 100644 tests/ui/traits/conditional-model-fn.rs create mode 100644 tests/ui/traits/conservative_impl_trait.rs create mode 100644 tests/ui/traits/copy-guessing.rs create mode 100644 tests/ui/traits/copy-impl-cannot-normalize.rs create mode 100644 tests/ui/traits/copy-impl-cannot-normalize.stderr create mode 100644 tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr create mode 100644 tests/ui/traits/copy-is-not-modulo-regions.rs create mode 100644 tests/ui/traits/copy-requires-self-wf.rs create mode 100644 tests/ui/traits/cycle-cache-err-60010.rs create mode 100644 tests/ui/traits/cycle-cache-err-60010.stderr create mode 100644 tests/ui/traits/cycle-generic-bound.rs create mode 100644 tests/ui/traits/cycle-type-trait.rs create mode 100644 tests/ui/traits/default-method/auxiliary/xc.rs create mode 100644 tests/ui/traits/default-method/auxiliary/xc_2.rs create mode 100644 tests/ui/traits/default-method/bound-subst.rs create mode 100644 tests/ui/traits/default-method/bound-subst2.rs create mode 100644 tests/ui/traits/default-method/bound-subst3.rs create mode 100644 tests/ui/traits/default-method/bound-subst4.rs create mode 100644 tests/ui/traits/default-method/bound.rs create mode 100644 tests/ui/traits/default-method/macro.rs create mode 100644 tests/ui/traits/default-method/mut.rs create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of.rs create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of.stderr create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs create mode 100644 tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr create mode 100644 tests/ui/traits/default-method/self.rs create mode 100644 tests/ui/traits/default-method/supervtable.rs create mode 100644 tests/ui/traits/default-method/trivial.rs create mode 100644 tests/ui/traits/default-method/xc-2.rs create mode 100644 tests/ui/traits/default-method/xc.rs create mode 100644 tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs create mode 100644 tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr create mode 100644 tests/ui/traits/duplicate-methods.rs create mode 100644 tests/ui/traits/duplicate-methods.stderr create mode 100644 tests/ui/traits/dyn-trait.rs create mode 100644 tests/ui/traits/early-vtbl-resolution.rs create mode 100644 tests/ui/traits/elaborate-type-region.rs create mode 100644 tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs create mode 100644 tests/ui/traits/fmt-pointer-trait.rs create mode 100644 tests/ui/traits/fn-trait-cast-diagnostic.rs create mode 100644 tests/ui/traits/fn-trait-cast-diagnostic.stderr create mode 100644 tests/ui/traits/generic.rs create mode 100644 tests/ui/traits/ignore-err-impls.rs create mode 100644 tests/ui/traits/ignore-err-impls.stderr create mode 100644 tests/ui/traits/impl-1.rs create mode 100644 tests/ui/traits/impl-1.stderr create mode 100644 tests/ui/traits/impl-2.rs create mode 100644 tests/ui/traits/impl-bounds-checking.rs create mode 100644 tests/ui/traits/impl-bounds-checking.stderr create mode 100644 tests/ui/traits/impl-can-not-have-untraitful-items.rs create mode 100644 tests/ui/traits/impl-can-not-have-untraitful-items.stderr create mode 100644 tests/ui/traits/impl-different-num-params.rs create mode 100644 tests/ui/traits/impl-different-num-params.stderr create mode 100644 tests/ui/traits/impl-evaluation-order.rs create mode 100644 tests/ui/traits/impl-for-module.rs create mode 100644 tests/ui/traits/impl-for-module.stderr create mode 100644 tests/ui/traits/impl-implicit-trait.rs create mode 100644 tests/ui/traits/impl-inherent-prefer-over-trait.rs create mode 100644 tests/ui/traits/impl-method-mismatch.rs create mode 100644 tests/ui/traits/impl-method-mismatch.stderr create mode 100644 tests/ui/traits/impl-object-overlap-issue-23853.rs create mode 100644 tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs create mode 100644 tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr create mode 100644 tests/ui/traits/impl.rs create mode 100644 tests/ui/traits/impl_trait_as_trait_return_position.rs create mode 100644 tests/ui/traits/inductive-overflow/lifetime.rs create mode 100644 tests/ui/traits/inductive-overflow/lifetime.stderr create mode 100644 tests/ui/traits/inductive-overflow/simultaneous.rs create mode 100644 tests/ui/traits/inductive-overflow/simultaneous.stderr create mode 100644 tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs create mode 100644 tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr create mode 100644 tests/ui/traits/inductive-overflow/supertrait.rs create mode 100644 tests/ui/traits/inductive-overflow/supertrait.stderr create mode 100644 tests/ui/traits/inductive-overflow/two-traits.rs create mode 100644 tests/ui/traits/inductive-overflow/two-traits.stderr create mode 100644 tests/ui/traits/infer-from-object-issue-26952.rs create mode 100644 tests/ui/traits/inherent-method-order.rs create mode 100644 tests/ui/traits/inheritance/auto-xc-2.rs create mode 100644 tests/ui/traits/inheritance/auto-xc.rs create mode 100644 tests/ui/traits/inheritance/auto.rs create mode 100644 tests/ui/traits/inheritance/auxiliary/auto_xc.rs create mode 100644 tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs create mode 100644 tests/ui/traits/inheritance/auxiliary/overloading_xc.rs create mode 100644 tests/ui/traits/inheritance/auxiliary/xc_call.rs create mode 100644 tests/ui/traits/inheritance/basic.rs create mode 100644 tests/ui/traits/inheritance/call-bound-inherited.rs create mode 100644 tests/ui/traits/inheritance/call-bound-inherited2.rs create mode 100644 tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs create mode 100644 tests/ui/traits/inheritance/cast.rs create mode 100644 tests/ui/traits/inheritance/cross-trait-call-xc.rs create mode 100644 tests/ui/traits/inheritance/cross-trait-call.rs create mode 100644 tests/ui/traits/inheritance/diamond.rs create mode 100644 tests/ui/traits/inheritance/multiple-inheritors.rs create mode 100644 tests/ui/traits/inheritance/multiple-params.rs create mode 100644 tests/ui/traits/inheritance/num.rs create mode 100644 tests/ui/traits/inheritance/num0.rs create mode 100644 tests/ui/traits/inheritance/num1.rs create mode 100644 tests/ui/traits/inheritance/num2.rs create mode 100644 tests/ui/traits/inheritance/num3.rs create mode 100644 tests/ui/traits/inheritance/num5.rs create mode 100644 tests/ui/traits/inheritance/overloading-simple.rs create mode 100644 tests/ui/traits/inheritance/overloading-xc-exe.rs create mode 100644 tests/ui/traits/inheritance/overloading.rs create mode 100644 tests/ui/traits/inheritance/repeated-supertrait-ambig.rs create mode 100644 tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr create mode 100644 tests/ui/traits/inheritance/repeated-supertrait.rs create mode 100644 tests/ui/traits/inheritance/self-in-supertype.rs create mode 100644 tests/ui/traits/inheritance/self.rs create mode 100644 tests/ui/traits/inheritance/simple.rs create mode 100644 tests/ui/traits/inheritance/static.rs create mode 100644 tests/ui/traits/inheritance/static2.rs create mode 100644 tests/ui/traits/inheritance/subst.rs create mode 100644 tests/ui/traits/inheritance/subst2.rs create mode 100644 tests/ui/traits/inheritance/visibility.rs create mode 100644 tests/ui/traits/invalid_operator_trait.rs create mode 100644 tests/ui/traits/invalid_operator_trait.stderr create mode 100644 tests/ui/traits/issue-102989.rs create mode 100644 tests/ui/traits/issue-102989.stderr create mode 100644 tests/ui/traits/issue-104322.rs create mode 100644 tests/ui/traits/issue-106072.rs create mode 100644 tests/ui/traits/issue-106072.stderr create mode 100644 tests/ui/traits/issue-18400.rs create mode 100644 tests/ui/traits/issue-18400.stderr create mode 100644 tests/ui/traits/issue-18412.rs create mode 100644 tests/ui/traits/issue-20692.rs create mode 100644 tests/ui/traits/issue-20692.stderr create mode 100644 tests/ui/traits/issue-22019.rs create mode 100644 tests/ui/traits/issue-22110.rs create mode 100644 tests/ui/traits/issue-22655.rs create mode 100644 tests/ui/traits/issue-23003-overflow.rs create mode 100644 tests/ui/traits/issue-23003.rs create mode 100644 tests/ui/traits/issue-23825.rs create mode 100644 tests/ui/traits/issue-24010.rs create mode 100644 tests/ui/traits/issue-26339.rs create mode 100644 tests/ui/traits/issue-28576.rs create mode 100644 tests/ui/traits/issue-28576.stderr create mode 100644 tests/ui/traits/issue-32963.rs create mode 100644 tests/ui/traits/issue-32963.stderr create mode 100644 tests/ui/traits/issue-33140-hack-boundaries.rs create mode 100644 tests/ui/traits/issue-33140-hack-boundaries.stderr create mode 100644 tests/ui/traits/issue-33140.rs create mode 100644 tests/ui/traits/issue-33140.stderr create mode 100644 tests/ui/traits/issue-35869.rs create mode 100644 tests/ui/traits/issue-35869.stderr create mode 100644 tests/ui/traits/issue-3683.rs create mode 100644 tests/ui/traits/issue-38033.rs create mode 100644 tests/ui/traits/issue-38404.rs create mode 100644 tests/ui/traits/issue-38404.stderr create mode 100644 tests/ui/traits/issue-38604.rs create mode 100644 tests/ui/traits/issue-38604.stderr create mode 100644 tests/ui/traits/issue-3973.rs create mode 100644 tests/ui/traits/issue-3973.stderr create mode 100644 tests/ui/traits/issue-4107.rs create mode 100644 tests/ui/traits/issue-43132.rs create mode 100644 tests/ui/traits/issue-43784-supertrait.rs create mode 100644 tests/ui/traits/issue-43784-supertrait.stderr create mode 100644 tests/ui/traits/issue-50480.rs create mode 100644 tests/ui/traits/issue-50480.stderr create mode 100644 tests/ui/traits/issue-52893.rs create mode 100644 tests/ui/traits/issue-52893.stderr create mode 100644 tests/ui/traits/issue-56202.rs create mode 100644 tests/ui/traits/issue-56488.rs create mode 100644 tests/ui/traits/issue-59029-1.rs create mode 100644 tests/ui/traits/issue-59029-1.stderr create mode 100644 tests/ui/traits/issue-59029-2.rs create mode 100644 tests/ui/traits/issue-6128.rs create mode 100644 tests/ui/traits/issue-6334.rs create mode 100644 tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs create mode 100644 tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr create mode 100644 tests/ui/traits/issue-65673.rs create mode 100644 tests/ui/traits/issue-65673.stderr create mode 100644 tests/ui/traits/issue-68295.rs create mode 100644 tests/ui/traits/issue-68295.stderr create mode 100644 tests/ui/traits/issue-7013.rs create mode 100644 tests/ui/traits/issue-7013.stderr create mode 100644 tests/ui/traits/issue-70944.rs create mode 100644 tests/ui/traits/issue-71036.rs create mode 100644 tests/ui/traits/issue-71036.stderr create mode 100644 tests/ui/traits/issue-71136.rs create mode 100644 tests/ui/traits/issue-71136.stderr create mode 100644 tests/ui/traits/issue-72410.rs create mode 100644 tests/ui/traits/issue-72410.stderr create mode 100644 tests/ui/traits/issue-72455.rs create mode 100644 tests/ui/traits/issue-75627.rs create mode 100644 tests/ui/traits/issue-75627.stderr create mode 100644 tests/ui/traits/issue-77982.rs create mode 100644 tests/ui/traits/issue-77982.stderr create mode 100644 tests/ui/traits/issue-78372.rs create mode 100644 tests/ui/traits/issue-78372.stderr create mode 100644 tests/ui/traits/issue-78632.rs create mode 100644 tests/ui/traits/issue-79458.rs create mode 100644 tests/ui/traits/issue-79458.stderr create mode 100644 tests/ui/traits/issue-8153.rs create mode 100644 tests/ui/traits/issue-8153.stderr create mode 100644 tests/ui/traits/issue-82830.rs create mode 100644 tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs create mode 100644 tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr create mode 100644 tests/ui/traits/issue-84399-bad-fresh-caching.rs create mode 100644 tests/ui/traits/issue-85360-eval-obligation-ice.rs create mode 100644 tests/ui/traits/issue-85360-eval-obligation-ice.stderr create mode 100644 tests/ui/traits/issue-85735.rs create mode 100644 tests/ui/traits/issue-85735.stderr create mode 100644 tests/ui/traits/issue-87558.rs create mode 100644 tests/ui/traits/issue-87558.stderr create mode 100644 tests/ui/traits/issue-89119.rs create mode 100644 tests/ui/traits/issue-90195-2.rs create mode 100644 tests/ui/traits/issue-90195.rs create mode 100644 tests/ui/traits/issue-90662-projection-caching.rs create mode 100644 tests/ui/traits/issue-91594.rs create mode 100644 tests/ui/traits/issue-91594.stderr create mode 100644 tests/ui/traits/issue-91949-hangs-on-recursion.rs create mode 100644 tests/ui/traits/issue-91949-hangs-on-recursion.stderr create mode 100644 tests/ui/traits/issue-92292.rs create mode 100644 tests/ui/traits/issue-9394-inherited-calls.rs create mode 100644 tests/ui/traits/issue-95311.rs create mode 100644 tests/ui/traits/issue-95898.rs create mode 100644 tests/ui/traits/issue-95898.stderr create mode 100644 tests/ui/traits/issue-96664.rs create mode 100644 tests/ui/traits/issue-96665.rs create mode 100644 tests/ui/traits/issue-97576.rs create mode 100644 tests/ui/traits/issue-97576.stderr create mode 100644 tests/ui/traits/issue-97695-double-trivial-bound.rs create mode 100644 tests/ui/traits/issue-99875.rs create mode 100644 tests/ui/traits/issue-99875.stderr create mode 100644 tests/ui/traits/item-inside-macro.rs create mode 100644 tests/ui/traits/item-privacy.rs create mode 100644 tests/ui/traits/item-privacy.stderr create mode 100644 tests/ui/traits/kindck-owned-contains-1.rs create mode 100644 tests/ui/traits/map-types.rs create mode 100644 tests/ui/traits/map-types.stderr create mode 100644 tests/ui/traits/matching-lifetimes.rs create mode 100644 tests/ui/traits/matching-lifetimes.stderr create mode 100644 tests/ui/traits/method-private.rs create mode 100644 tests/ui/traits/method-private.stderr create mode 100644 tests/ui/traits/monad.rs create mode 100644 tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs create mode 100644 tests/ui/traits/multidispatch-bad.rs create mode 100644 tests/ui/traits/multidispatch-bad.stderr create mode 100644 tests/ui/traits/multidispatch-conditional-impl-not-considered.rs create mode 100644 tests/ui/traits/multidispatch-convert-ambig-dest.rs create mode 100644 tests/ui/traits/multidispatch-convert-ambig-dest.stderr create mode 100644 tests/ui/traits/multidispatch-infer-convert-target.rs create mode 100644 tests/ui/traits/multidispatch1.rs create mode 100644 tests/ui/traits/multidispatch2.rs create mode 100644 tests/ui/traits/mutual-recursion-issue-75860.rs create mode 100644 tests/ui/traits/mutual-recursion-issue-75860.stderr create mode 100644 tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs create mode 100644 tests/ui/traits/negative-impls/eager-mono.rs create mode 100644 tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs create mode 100644 tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr create mode 100644 tests/ui/traits/negative-impls/feature-gate-negative_impls.rs create mode 100644 tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr create mode 100644 tests/ui/traits/negative-impls/negated-auto-traits-error.rs create mode 100644 tests/ui/traits/negative-impls/negated-auto-traits-error.stderr create mode 100644 tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs create mode 100644 tests/ui/traits/negative-impls/negative-default-impls.rs create mode 100644 tests/ui/traits/negative-impls/negative-default-impls.stderr create mode 100644 tests/ui/traits/negative-impls/negative-impls-basic.rs create mode 100644 tests/ui/traits/negative-impls/negative-specializes-negative.rs create mode 100644 tests/ui/traits/negative-impls/negative-specializes-negative.stderr create mode 100644 tests/ui/traits/negative-impls/negative-specializes-positive-item.rs create mode 100644 tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr create mode 100644 tests/ui/traits/negative-impls/negative-specializes-positive.rs create mode 100644 tests/ui/traits/negative-impls/negative-specializes-positive.stderr create mode 100644 tests/ui/traits/negative-impls/no-items.rs create mode 100644 tests/ui/traits/negative-impls/no-items.stderr create mode 100644 tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs create mode 100644 tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr create mode 100644 tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs create mode 100644 tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr create mode 100644 tests/ui/traits/negative-impls/positive-specializes-negative.rs create mode 100644 tests/ui/traits/negative-impls/positive-specializes-negative.stderr create mode 100644 tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs create mode 100644 tests/ui/traits/new-solver/fn-trait-closure.rs create mode 100644 tests/ui/traits/new-solver/fn-trait.rs create mode 100644 tests/ui/traits/new-solver/pointer-sized.rs create mode 100644 tests/ui/traits/new-solver/pointer-sized.stderr create mode 100644 tests/ui/traits/no-fallback-multiple-impls.rs create mode 100644 tests/ui/traits/no-fallback-multiple-impls.stderr create mode 100644 tests/ui/traits/no_send-struct.rs create mode 100644 tests/ui/traits/no_send-struct.stderr create mode 100644 tests/ui/traits/normalize-supertrait.rs create mode 100644 tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs create mode 100644 tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr create mode 100644 tests/ui/traits/object-does-not-impl-trait.rs create mode 100644 tests/ui/traits/object-does-not-impl-trait.stderr create mode 100644 tests/ui/traits/object-one-type-two-traits.rs create mode 100644 tests/ui/traits/object/auto-dedup-in-impl.rs create mode 100644 tests/ui/traits/object/auto-dedup-in-impl.stderr create mode 100644 tests/ui/traits/object/auto-dedup.rs create mode 100644 tests/ui/traits/object/bounds-cycle-1.rs create mode 100644 tests/ui/traits/object/bounds-cycle-2.rs create mode 100644 tests/ui/traits/object/bounds-cycle-3.rs create mode 100644 tests/ui/traits/object/bounds-cycle-4.rs create mode 100644 tests/ui/traits/object/enforce-supertrait-projection.rs create mode 100644 tests/ui/traits/object/enforce-supertrait-projection.stderr create mode 100644 tests/ui/traits/object/exclusion.rs create mode 100644 tests/ui/traits/object/generics.rs create mode 100644 tests/ui/traits/object/issue-33140-traitobject-crate.rs create mode 100644 tests/ui/traits/object/issue-33140-traitobject-crate.stderr create mode 100644 tests/ui/traits/object/issue-44454-1.rs create mode 100644 tests/ui/traits/object/issue-44454-1.stderr create mode 100644 tests/ui/traits/object/issue-44454-2.rs create mode 100644 tests/ui/traits/object/issue-44454-2.stderr create mode 100644 tests/ui/traits/object/issue-44454-3.rs create mode 100644 tests/ui/traits/object/issue-44454-3.stderr create mode 100644 tests/ui/traits/object/lifetime-first.rs create mode 100644 tests/ui/traits/object/macro-matcher.rs create mode 100644 tests/ui/traits/object/macro-matcher.stderr create mode 100644 tests/ui/traits/object/safety.rs create mode 100644 tests/ui/traits/object/safety.stderr create mode 100644 tests/ui/traits/object/supertrait-lifetime-bound.rs create mode 100644 tests/ui/traits/object/supertrait-lifetime-bound.stderr create mode 100644 tests/ui/traits/object/vs-lifetime-2.rs create mode 100644 tests/ui/traits/object/vs-lifetime-2.stderr create mode 100644 tests/ui/traits/object/vs-lifetime.rs create mode 100644 tests/ui/traits/object/vs-lifetime.stderr create mode 100644 tests/ui/traits/object/with-lifetime-bound.rs create mode 100644 tests/ui/traits/object/with-self-in-projection-output-bad.rs create mode 100644 tests/ui/traits/object/with-self-in-projection-output-bad.stderr create mode 100644 tests/ui/traits/object/with-self-in-projection-output-good.rs create mode 100644 tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs create mode 100644 tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs create mode 100644 tests/ui/traits/operator-overloading-issue-52025.rs create mode 100644 tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs create mode 100644 tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr create mode 100644 tests/ui/traits/overlap-permitted-for-marker-traits.rs create mode 100644 tests/ui/traits/param-without-lifetime-constraint.rs create mode 100644 tests/ui/traits/param-without-lifetime-constraint.stderr create mode 100644 tests/ui/traits/parameterized-with-bounds.rs create mode 100644 tests/ui/traits/pointee-deduction.rs create mode 100644 tests/ui/traits/pointee-tail-is-generic-errors.rs create mode 100644 tests/ui/traits/pointee-tail-is-generic-errors.stderr create mode 100644 tests/ui/traits/pointee-tail-is-generic.rs create mode 100644 tests/ui/traits/principal-less-objects.rs create mode 100644 tests/ui/traits/privacy.rs create mode 100644 tests/ui/traits/project-modulo-regions.rs create mode 100644 tests/ui/traits/project-modulo-regions.with_clause.stderr create mode 100644 tests/ui/traits/project-modulo-regions.without_clause.stderr create mode 100644 tests/ui/traits/region-pointer-simple.rs create mode 100644 tests/ui/traits/reservation-impl/coherence-conflict.rs create mode 100644 tests/ui/traits/reservation-impl/coherence-conflict.stderr create mode 100644 tests/ui/traits/reservation-impl/no-use.rs create mode 100644 tests/ui/traits/reservation-impl/no-use.stderr create mode 100644 tests/ui/traits/reservation-impl/non-lattice-ok.rs create mode 100644 tests/ui/traits/reservation-impl/ok.rs create mode 100644 tests/ui/traits/resolution-in-overloaded-op.rs create mode 100644 tests/ui/traits/resolution-in-overloaded-op.stderr create mode 100644 tests/ui/traits/safety-fn-body.mir.stderr create mode 100644 tests/ui/traits/safety-fn-body.rs create mode 100644 tests/ui/traits/safety-fn-body.thir.stderr create mode 100644 tests/ui/traits/safety-inherent-impl.rs create mode 100644 tests/ui/traits/safety-inherent-impl.stderr create mode 100644 tests/ui/traits/safety-ok-cc.rs create mode 100644 tests/ui/traits/safety-ok.rs create mode 100644 tests/ui/traits/safety-trait-impl-cc.rs create mode 100644 tests/ui/traits/safety-trait-impl-cc.stderr create mode 100644 tests/ui/traits/safety-trait-impl.rs create mode 100644 tests/ui/traits/safety-trait-impl.stderr create mode 100644 tests/ui/traits/self-without-lifetime-constraint.rs create mode 100644 tests/ui/traits/self-without-lifetime-constraint.stderr create mode 100644 tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs create mode 100644 tests/ui/traits/static-method-generic-inference.rs create mode 100644 tests/ui/traits/static-method-generic-inference.stderr create mode 100644 tests/ui/traits/static-method-overwriting.rs create mode 100644 tests/ui/traits/static-outlives-a-where-clause.rs create mode 100644 tests/ui/traits/staticness-mismatch.rs create mode 100644 tests/ui/traits/staticness-mismatch.stderr create mode 100644 tests/ui/traits/suggest-deferences/issue-39029.fixed create mode 100644 tests/ui/traits/suggest-deferences/issue-39029.rs create mode 100644 tests/ui/traits/suggest-deferences/issue-39029.stderr create mode 100644 tests/ui/traits/suggest-deferences/issue-62530.fixed create mode 100644 tests/ui/traits/suggest-deferences/issue-62530.rs create mode 100644 tests/ui/traits/suggest-deferences/issue-62530.stderr create mode 100644 tests/ui/traits/suggest-deferences/multiple-0.fixed create mode 100644 tests/ui/traits/suggest-deferences/multiple-0.rs create mode 100644 tests/ui/traits/suggest-deferences/multiple-0.stderr create mode 100644 tests/ui/traits/suggest-deferences/multiple-1.rs create mode 100644 tests/ui/traits/suggest-deferences/multiple-1.stderr create mode 100644 tests/ui/traits/suggest-deferences/root-obligation.fixed create mode 100644 tests/ui/traits/suggest-deferences/root-obligation.rs create mode 100644 tests/ui/traits/suggest-deferences/root-obligation.stderr create mode 100644 tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed create mode 100644 tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs create mode 100644 tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr create mode 100644 tests/ui/traits/suggest-fully-qualified-closure.rs create mode 100644 tests/ui/traits/suggest-fully-qualified-closure.stderr create mode 100644 tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs create mode 100644 tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr create mode 100644 tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs create mode 100644 tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr create mode 100644 tests/ui/traits/suggest-where-clause.rs create mode 100644 tests/ui/traits/suggest-where-clause.stderr create mode 100644 tests/ui/traits/superdefault-generics.rs create mode 100644 tests/ui/traits/syntax-polarity.rs create mode 100644 tests/ui/traits/syntax-trait-polarity.rs create mode 100644 tests/ui/traits/syntax-trait-polarity.stderr create mode 100644 tests/ui/traits/test-2.rs create mode 100644 tests/ui/traits/test-2.stderr create mode 100644 tests/ui/traits/test.rs create mode 100644 tests/ui/traits/test.stderr create mode 100644 tests/ui/traits/to-str.rs create mode 100644 tests/ui/traits/track-obligations.rs create mode 100644 tests/ui/traits/track-obligations.stderr create mode 100644 tests/ui/traits/trait-or-new-type-instead.rs create mode 100644 tests/ui/traits/trait-or-new-type-instead.stderr create mode 100644 tests/ui/traits/trait-upcasting/basic.rs create mode 100644 tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs create mode 100644 tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs create mode 100644 tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr create mode 100644 tests/ui/traits/trait-upcasting/diamond.rs create mode 100644 tests/ui/traits/trait-upcasting/invalid-upcast.rs create mode 100644 tests/ui/traits/trait-upcasting/invalid-upcast.stderr create mode 100644 tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs create mode 100644 tests/ui/traits/trait-upcasting/lifetime.rs create mode 100644 tests/ui/traits/trait-upcasting/migrate-lint-deny.rs create mode 100644 tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr create mode 100644 tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs create mode 100644 tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr create mode 100644 tests/ui/traits/trait-upcasting/replace-vptr.rs create mode 100644 tests/ui/traits/trait-upcasting/struct.rs create mode 100644 tests/ui/traits/trait-upcasting/subtrait-method.rs create mode 100644 tests/ui/traits/trait-upcasting/subtrait-method.stderr create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-1.rs create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-1.stderr create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-2.rs create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-2.stderr create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-3.rs create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-3.stderr create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-4.rs create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-4.stderr create mode 100644 tests/ui/traits/typeclasses-eq-example-static.rs create mode 100644 tests/ui/traits/typeclasses-eq-example.rs create mode 100644 tests/ui/traits/ufcs-object.rs create mode 100644 tests/ui/traits/unspecified-self-in-trait-ref.rs create mode 100644 tests/ui/traits/unspecified-self-in-trait-ref.stderr create mode 100644 tests/ui/traits/use-before-def.rs create mode 100644 tests/ui/traits/vtable-res-trait-param.rs create mode 100644 tests/ui/traits/vtable-res-trait-param.stderr create mode 100644 tests/ui/traits/vtable/issue-91807.rs create mode 100644 tests/ui/traits/vtable/issue-97381.rs create mode 100644 tests/ui/traits/vtable/issue-97381.stderr create mode 100644 tests/ui/traits/vtable/vtable-diamond.rs create mode 100644 tests/ui/traits/vtable/vtable-diamond.stderr create mode 100644 tests/ui/traits/vtable/vtable-multi-level.rs create mode 100644 tests/ui/traits/vtable/vtable-multi-level.stderr create mode 100644 tests/ui/traits/vtable/vtable-multiple.rs create mode 100644 tests/ui/traits/vtable/vtable-multiple.stderr create mode 100644 tests/ui/traits/vtable/vtable-non-object-safe.rs create mode 100644 tests/ui/traits/vtable/vtable-non-object-safe.stderr create mode 100644 tests/ui/traits/vtable/vtable-vacant.rs create mode 100644 tests/ui/traits/vtable/vtable-vacant.stderr create mode 100644 tests/ui/traits/wf-object/maybe-bound.rs create mode 100644 tests/ui/traits/wf-object/maybe-bound.stderr create mode 100644 tests/ui/traits/wf-object/no-duplicates.rs create mode 100644 tests/ui/traits/wf-object/no-duplicates.stderr create mode 100644 tests/ui/traits/wf-object/only-maybe-bound.rs create mode 100644 tests/ui/traits/wf-object/only-maybe-bound.stderr create mode 100644 tests/ui/traits/wf-object/reverse-order.rs create mode 100644 tests/ui/traits/where-clause-vs-impl.rs create mode 100644 tests/ui/traits/with-bounds-default.rs create mode 100644 tests/ui/traits/with-dst.rs create mode 100644 tests/ui/transmutability/abstraction/abstracted_assume.rs create mode 100644 tests/ui/transmutability/abstraction/const_generic_fn.rs create mode 100644 tests/ui/transmutability/arrays/issue-103783-array-length.rs create mode 100644 tests/ui/transmutability/arrays/issue-103783-array-length.stderr create mode 100644 tests/ui/transmutability/arrays/should_have_correct_length.rs create mode 100644 tests/ui/transmutability/arrays/should_inherit_alignment.rs create mode 100644 tests/ui/transmutability/arrays/should_require_well_defined_layout.rs create mode 100644 tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr create mode 100644 tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs create mode 100644 tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr create mode 100644 tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs create mode 100644 tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr create mode 100644 tests/ui/transmutability/enums/should_order_correctly.rs create mode 100644 tests/ui/transmutability/enums/should_pad_variants.rs create mode 100644 tests/ui/transmutability/enums/should_pad_variants.stderr create mode 100644 tests/ui/transmutability/enums/should_respect_endianness.rs create mode 100644 tests/ui/transmutability/enums/should_respect_endianness.stderr create mode 100644 tests/ui/transmutability/issue-101739-1.rs create mode 100644 tests/ui/transmutability/issue-101739-1.stderr create mode 100644 tests/ui/transmutability/issue-101739-2.rs create mode 100644 tests/ui/transmutability/issue-101739-2.stderr create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr create mode 100644 tests/ui/transmutability/primitives/bool.rs create mode 100644 tests/ui/transmutability/primitives/bool.stderr create mode 100644 tests/ui/transmutability/primitives/numbers.rs create mode 100644 tests/ui/transmutability/primitives/numbers.stderr create mode 100644 tests/ui/transmutability/primitives/unit.rs create mode 100644 tests/ui/transmutability/primitives/unit.stderr create mode 100644 tests/ui/transmutability/references.rs create mode 100644 tests/ui/transmutability/references.stderr create mode 100644 tests/ui/transmutability/structs/repr/should_handle_align.rs create mode 100644 tests/ui/transmutability/structs/repr/should_handle_packed.rs create mode 100644 tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs create mode 100644 tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr create mode 100644 tests/ui/transmutability/structs/should_order_fields_correctly.rs create mode 100644 tests/ui/transmutability/unions/boolish.rs create mode 100644 tests/ui/transmutability/unions/repr/should_handle_align.rs create mode 100644 tests/ui/transmutability/unions/repr/should_handle_packed.rs create mode 100644 tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs create mode 100644 tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr create mode 100644 tests/ui/transmutability/unions/should_pad_variants.rs create mode 100644 tests/ui/transmutability/unions/should_pad_variants.stderr create mode 100644 tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs create mode 100644 tests/ui/transmutability/unions/should_reject_contraction.rs create mode 100644 tests/ui/transmutability/unions/should_reject_contraction.stderr create mode 100644 tests/ui/transmutability/unions/should_reject_disjoint.rs create mode 100644 tests/ui/transmutability/unions/should_reject_disjoint.stderr create mode 100644 tests/ui/transmutability/unions/should_reject_intersecting.rs create mode 100644 tests/ui/transmutability/unions/should_reject_intersecting.stderr create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs create mode 100644 tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr create mode 100644 tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs create mode 100644 tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs create mode 100644 tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs create mode 100644 tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr create mode 100644 tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs create mode 100644 tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs create mode 100644 tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr create mode 100644 tests/ui/transmute-equal-assoc-types.rs create mode 100644 tests/ui/transmute-non-immediate-to-immediate.rs create mode 100644 tests/ui/transmute/lifetimes.rs create mode 100644 tests/ui/transmute/main.rs create mode 100644 tests/ui/transmute/main.stderr create mode 100644 tests/ui/transmute/transmute-different-sizes.rs create mode 100644 tests/ui/transmute/transmute-different-sizes.stderr create mode 100644 tests/ui/transmute/transmute-fat-pointers.rs create mode 100644 tests/ui/transmute/transmute-fat-pointers.stderr create mode 100644 tests/ui/transmute/transmute-from-fn-item-types-error.rs create mode 100644 tests/ui/transmute/transmute-from-fn-item-types-error.stderr create mode 100644 tests/ui/transmute/transmute-impl.rs create mode 100644 tests/ui/transmute/transmute-impl.stderr create mode 100644 tests/ui/transmute/transmute-imut-to-mut.rs create mode 100644 tests/ui/transmute/transmute-imut-to-mut.stderr create mode 100644 tests/ui/transmute/transmute-padding-ice.rs create mode 100644 tests/ui/transmute/transmute-padding-ice.stderr create mode 100644 tests/ui/transmute/transmute-type-parameters.rs create mode 100644 tests/ui/transmute/transmute-type-parameters.stderr create mode 100644 tests/ui/treat-err-as-bug/delay_span_bug.rs create mode 100644 tests/ui/treat-err-as-bug/delay_span_bug.stderr create mode 100644 tests/ui/treat-err-as-bug/err.rs create mode 100644 tests/ui/treat-err-as-bug/err.stderr create mode 100644 tests/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr create mode 100644 tests/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr create mode 100644 tests/ui/trivial-bounds/issue-73021-impossible-inline.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-leak-copy.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-leak.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-leak.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-lint.rs create mode 100644 tests/ui/trivial-bounds/trivial-bounds-lint.stderr create mode 100644 tests/ui/trivial-bounds/trivial-bounds-object.rs create mode 100644 tests/ui/trivial_casts-rpass.rs create mode 100644 tests/ui/try-block/issue-45124.rs create mode 100644 tests/ui/try-block/try-block-bad-lifetime.rs create mode 100644 tests/ui/try-block/try-block-bad-lifetime.stderr create mode 100644 tests/ui/try-block/try-block-bad-type.rs create mode 100644 tests/ui/try-block/try-block-bad-type.stderr create mode 100644 tests/ui/try-block/try-block-catch.rs create mode 100644 tests/ui/try-block/try-block-catch.stderr create mode 100644 tests/ui/try-block/try-block-in-edition2015.rs create mode 100644 tests/ui/try-block/try-block-in-edition2015.stderr create mode 100644 tests/ui/try-block/try-block-in-match.rs create mode 100644 tests/ui/try-block/try-block-in-return.rs create mode 100644 tests/ui/try-block/try-block-in-while.rs create mode 100644 tests/ui/try-block/try-block-in-while.stderr create mode 100644 tests/ui/try-block/try-block-maybe-bad-lifetime.rs create mode 100644 tests/ui/try-block/try-block-maybe-bad-lifetime.stderr create mode 100644 tests/ui/try-block/try-block-opt-init.rs create mode 100644 tests/ui/try-block/try-block-opt-init.stderr create mode 100644 tests/ui/try-block/try-block-type-error.rs create mode 100644 tests/ui/try-block/try-block-type-error.stderr create mode 100644 tests/ui/try-block/try-block-unreachable-code-lint.rs create mode 100644 tests/ui/try-block/try-block-unreachable-code-lint.stderr create mode 100644 tests/ui/try-block/try-block-unused-delims.fixed create mode 100644 tests/ui/try-block/try-block-unused-delims.rs create mode 100644 tests/ui/try-block/try-block-unused-delims.stderr create mode 100644 tests/ui/try-block/try-block.rs create mode 100644 tests/ui/try-block/try-is-identifier-edition2015.rs create mode 100644 tests/ui/try-from-int-error-partial-eq.rs create mode 100644 tests/ui/try-operator-hygiene.rs create mode 100644 tests/ui/try-operator.rs create mode 100644 tests/ui/try-trait/bad-interconversion.rs create mode 100644 tests/ui/try-trait/bad-interconversion.stderr create mode 100644 tests/ui/try-trait/option-to-result.rs create mode 100644 tests/ui/try-trait/option-to-result.stderr create mode 100644 tests/ui/try-trait/try-as-monad.rs create mode 100644 tests/ui/try-trait/try-on-option-diagnostics.rs create mode 100644 tests/ui/try-trait/try-on-option-diagnostics.stderr create mode 100644 tests/ui/try-trait/try-on-option.rs create mode 100644 tests/ui/try-trait/try-on-option.stderr create mode 100644 tests/ui/try-trait/try-operator-custom.rs create mode 100644 tests/ui/try-trait/try-operator-on-main.rs create mode 100644 tests/ui/try-trait/try-operator-on-main.stderr create mode 100644 tests/ui/try-trait/try-poll.rs create mode 100644 tests/ui/try-trait/yeet-for-option.rs create mode 100644 tests/ui/try-trait/yeet-for-result.rs create mode 100644 tests/ui/tuple-index.rs create mode 100644 tests/ui/tuple/add-tuple-within-arguments.rs create mode 100644 tests/ui/tuple/add-tuple-within-arguments.stderr create mode 100644 tests/ui/tuple/array-diagnostics.rs create mode 100644 tests/ui/tuple/array-diagnostics.stderr create mode 100644 tests/ui/tuple/builtin-fail.rs create mode 100644 tests/ui/tuple/builtin-fail.stderr create mode 100644 tests/ui/tuple/builtin.rs create mode 100644 tests/ui/tuple/index-float.rs create mode 100644 tests/ui/tuple/index-invalid.rs create mode 100644 tests/ui/tuple/index-invalid.stderr create mode 100644 tests/ui/tuple/indexing-in-macro.rs create mode 100644 tests/ui/tuple/nested-index.rs create mode 100644 tests/ui/tuple/one-tuple.rs create mode 100644 tests/ui/tuple/tup.rs create mode 100644 tests/ui/tuple/tuple-arity-mismatch.rs create mode 100644 tests/ui/tuple/tuple-arity-mismatch.stderr create mode 100644 tests/ui/tuple/tuple-index-fat-types.rs create mode 100644 tests/ui/tuple/tuple-index-not-tuple.rs create mode 100644 tests/ui/tuple/tuple-index-not-tuple.stderr create mode 100644 tests/ui/tuple/tuple-index-out-of-bounds.rs create mode 100644 tests/ui/tuple/tuple-index-out-of-bounds.stderr create mode 100644 tests/ui/tuple/tuple-struct-fields/test.rs create mode 100644 tests/ui/tuple/tuple-struct-fields/test.stderr create mode 100644 tests/ui/tuple/tuple-struct-fields/test2.rs create mode 100644 tests/ui/tuple/tuple-struct-fields/test2.stderr create mode 100644 tests/ui/tuple/tuple-struct-fields/test3.rs create mode 100644 tests/ui/tuple/tuple-struct-fields/test3.stderr create mode 100644 tests/ui/tuple/wrong_argument_ice-2.rs create mode 100644 tests/ui/tuple/wrong_argument_ice-2.stderr create mode 100644 tests/ui/tuple/wrong_argument_ice-3.rs create mode 100644 tests/ui/tuple/wrong_argument_ice-3.stderr create mode 100644 tests/ui/tuple/wrong_argument_ice-4.rs create mode 100644 tests/ui/tuple/wrong_argument_ice-4.stderr create mode 100644 tests/ui/tuple/wrong_argument_ice.rs create mode 100644 tests/ui/tuple/wrong_argument_ice.stderr create mode 100644 tests/ui/tydesc-name.rs create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs create mode 100644 tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr create mode 100644 tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs create mode 100644 tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr create mode 100644 tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs create mode 100644 tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr create mode 100644 tests/ui/type-alias-enum-variants/issue-57866.rs create mode 100644 tests/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs create mode 100644 tests/ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs create mode 100644 tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs create mode 100644 tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr create mode 100644 tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs create mode 100644 tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr create mode 100644 tests/ui/type-alias-enum-variants/self-in-enum-definition.rs create mode 100644 tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr create mode 100644 tests/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs create mode 100644 tests/ui/type-alias-impl-trait/argument-types.rs create mode 100644 tests/ui/type-alias-impl-trait/assoc-projection-ice.rs create mode 100644 tests/ui/type-alias-impl-trait/assoc-type-const.rs create mode 100644 tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs create mode 100644 tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr create mode 100644 tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs create mode 100644 tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs create mode 100644 tests/ui/type-alias-impl-trait/auto-trait-leakage.rs create mode 100644 tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs create mode 100644 tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr create mode 100644 tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs create mode 100644 tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr create mode 100644 tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs create mode 100644 tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs create mode 100644 tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs create mode 100644 tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs create mode 100644 tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs create mode 100644 tests/ui/type-alias-impl-trait/bound_reduction.rs create mode 100644 tests/ui/type-alias-impl-trait/bound_reduction2.rs create mode 100644 tests/ui/type-alias-impl-trait/bound_reduction2.stderr create mode 100644 tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs create mode 100644 tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr create mode 100644 tests/ui/type-alias-impl-trait/bounds-are-checked.rs create mode 100644 tests/ui/type-alias-impl-trait/bounds-are-checked.stderr create mode 100644 tests/ui/type-alias-impl-trait/closure_args.rs create mode 100644 tests/ui/type-alias-impl-trait/closure_args2.rs create mode 100644 tests/ui/type-alias-impl-trait/closure_parent_substs.rs create mode 100644 tests/ui/type-alias-impl-trait/closure_wf_outlives.rs create mode 100644 tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr create mode 100644 tests/ui/type-alias-impl-trait/closures_in_branches.rs create mode 100644 tests/ui/type-alias-impl-trait/closures_in_branches.stderr create mode 100644 tests/ui/type-alias-impl-trait/coherence.rs create mode 100644 tests/ui/type-alias-impl-trait/coherence.stderr create mode 100644 tests/ui/type-alias-impl-trait/coherence_cross_crate.rs create mode 100644 tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr create mode 100644 tests/ui/type-alias-impl-trait/coherence_generalization.rs create mode 100644 tests/ui/type-alias-impl-trait/collect_hidden_types.rs create mode 100644 tests/ui/type-alias-impl-trait/constrain_inputs.rs create mode 100644 tests/ui/type-alias-impl-trait/constrain_inputs.stderr create mode 100644 tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs create mode 100644 tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr create mode 100644 tests/ui/type-alias-impl-trait/cross_crate_ice.rs create mode 100644 tests/ui/type-alias-impl-trait/cross_crate_ice2.rs create mode 100644 tests/ui/type-alias-impl-trait/cross_inference.rs create mode 100644 tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs create mode 100644 tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs create mode 100644 tests/ui/type-alias-impl-trait/cross_inference_rpit.rs create mode 100644 tests/ui/type-alias-impl-trait/declared_but_never_defined.rs create mode 100644 tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr create mode 100644 tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs create mode 100644 tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr create mode 100644 tests/ui/type-alias-impl-trait/defining-use-submodule.rs create mode 100644 tests/ui/type-alias-impl-trait/destructuring.rs create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses.rs create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses.stderr create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs create mode 100644 tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr create mode 100644 tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs create mode 100644 tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr create mode 100644 tests/ui/type-alias-impl-trait/fallback.rs create mode 100644 tests/ui/type-alias-impl-trait/fallback.stderr create mode 100644 tests/ui/type-alias-impl-trait/field-types.rs create mode 100644 tests/ui/type-alias-impl-trait/future.rs create mode 100644 tests/ui/type-alias-impl-trait/future.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_lifetime_param.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_nondefining_use.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_not_used.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_not_used.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_underconstrained.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_underconstrained.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic_underconstrained2.rs create mode 100644 tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr create mode 100644 tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs create mode 100644 tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds.stderr create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds2.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds3.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds_closure.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr create mode 100644 tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr create mode 100644 tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs create mode 100644 tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr create mode 100644 tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs create mode 100644 tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs create mode 100644 tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr create mode 100644 tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr create mode 100644 tests/ui/type-alias-impl-trait/incomplete-inference.rs create mode 100644 tests/ui/type-alias-impl-trait/incomplete-inference.stderr create mode 100644 tests/ui/type-alias-impl-trait/inference-cycle.rs create mode 100644 tests/ui/type-alias-impl-trait/inference-cycle.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-101750.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-104817.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-104817.stock.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-52843.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-52843.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53092-2.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-53092-2.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53092.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-53092.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53096.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-53096.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53598.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-53598.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-57700.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-57700.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-57961.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-57961.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-58662-simplified.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-58887.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-58951-2.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-58951.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-60371.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-60371.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-60407.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-60407.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-60564-working.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-60564.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-60564.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-60662.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-60662.stdout create mode 100644 tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-63279.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-63279.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-63355.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-65384.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-65384.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-65918.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-69323.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-70121.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-72793.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-74244.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-74244.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-74280.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-74280.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-74761-2.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-74761-2.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-74761.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-74761.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-77179.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-77179.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-78450.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-89686.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-89686.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-89952.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-90400-1.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-90400-1.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-90400-2.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-90400-2.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-93411.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-94429.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-94429.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-98604.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-98604.stderr create mode 100644 tests/ui/type-alias-impl-trait/issue-98608.rs create mode 100644 tests/ui/type-alias-impl-trait/issue-98608.stderr create mode 100644 tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs create mode 100644 tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr create mode 100644 tests/ui/type-alias-impl-trait/multiple_definitions.rs create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference.rs create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference.stderr create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference2.rs create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference3.rs create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr create mode 100644 tests/ui/type-alias-impl-trait/nested.rs create mode 100644 tests/ui/type-alias-impl-trait/nested.stderr create mode 100644 tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs create mode 100644 tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr create mode 100644 tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs create mode 100644 tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs create mode 100644 tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr create mode 100644 tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs create mode 100644 tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr create mode 100644 tests/ui/type-alias-impl-trait/not_a_defining_use.rs create mode 100644 tests/ui/type-alias-impl-trait/not_a_defining_use.stderr create mode 100644 tests/ui/type-alias-impl-trait/not_well_formed.rs create mode 100644 tests/ui/type-alias-impl-trait/not_well_formed.stderr create mode 100644 tests/ui/type-alias-impl-trait/outlives-bound-var.rs create mode 100644 tests/ui/type-alias-impl-trait/reveal_local.rs create mode 100644 tests/ui/type-alias-impl-trait/reveal_local.stderr create mode 100644 tests/ui/type-alias-impl-trait/self-referential-2.rs create mode 100644 tests/ui/type-alias-impl-trait/self-referential-2.stderr create mode 100644 tests/ui/type-alias-impl-trait/self-referential-3.rs create mode 100644 tests/ui/type-alias-impl-trait/self-referential-4.rs create mode 100644 tests/ui/type-alias-impl-trait/self-referential-4.stderr create mode 100644 tests/ui/type-alias-impl-trait/self-referential.rs create mode 100644 tests/ui/type-alias-impl-trait/self-referential.stderr create mode 100644 tests/ui/type-alias-impl-trait/self_implication.rs create mode 100644 tests/ui/type-alias-impl-trait/static-const-types.rs create mode 100644 tests/ui/type-alias-impl-trait/structural-match-no-leak.rs create mode 100644 tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr create mode 100644 tests/ui/type-alias-impl-trait/structural-match.rs create mode 100644 tests/ui/type-alias-impl-trait/structural-match.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs create mode 100644 tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/type_of_a_let.rs create mode 100644 tests/ui/type-alias-impl-trait/type_of_a_let.stderr create mode 100644 tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs create mode 100644 tests/ui/type-alias-impl-trait/underconstrained_generic.rs create mode 100644 tests/ui/type-alias-impl-trait/underconstrained_generic.stderr create mode 100644 tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs create mode 100644 tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr create mode 100644 tests/ui/type-alias-impl-trait/unnameable_type.rs create mode 100644 tests/ui/type-alias-impl-trait/unnameable_type.stderr create mode 100644 tests/ui/type-alias-impl-trait/unused_generic_param.rs create mode 100644 tests/ui/type-alias-impl-trait/weird-return-types.rs create mode 100644 tests/ui/type-alias-impl-trait/wf-check-fn-def.rs create mode 100644 tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr create mode 100644 tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs create mode 100644 tests/ui/type-alias-impl-trait/wf_check_closures.rs create mode 100644 tests/ui/type-alias-impl-trait/wf_check_closures.stderr create mode 100644 tests/ui/type-alias/issue-14933.rs create mode 100644 tests/ui/type-alias/issue-37515.rs create mode 100644 tests/ui/type-alias/issue-37515.stderr create mode 100644 tests/ui/type-alias/issue-62263-self-in-atb.rs create mode 100644 tests/ui/type-alias/issue-62263-self-in-atb.stderr create mode 100644 tests/ui/type-alias/issue-62305-self-assoc-ty.rs create mode 100644 tests/ui/type-alias/issue-62305-self-assoc-ty.stderr create mode 100644 tests/ui/type-alias/issue-62364-self-ty-arg.rs create mode 100644 tests/ui/type-alias/issue-62364-self-ty-arg.stderr create mode 100644 tests/ui/type-id-higher-rank-2.rs create mode 100644 tests/ui/type-inference/issue-30225.rs create mode 100644 tests/ui/type-inference/issue-30225.stderr create mode 100644 tests/ui/type-inference/or_else-multiple-type-params.rs create mode 100644 tests/ui/type-inference/or_else-multiple-type-params.stderr create mode 100644 tests/ui/type-inference/sort_by_key.rs create mode 100644 tests/ui/type-inference/sort_by_key.stderr create mode 100644 tests/ui/type-inference/unbounded-associated-type.rs create mode 100644 tests/ui/type-inference/unbounded-associated-type.stderr create mode 100644 tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs create mode 100644 tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr create mode 100644 tests/ui/type-inference/unbounded-type-param-in-fn.rs create mode 100644 tests/ui/type-inference/unbounded-type-param-in-fn.stderr create mode 100644 tests/ui/type-namespace.rs create mode 100644 tests/ui/type-param-constraints.rs create mode 100644 tests/ui/type-param.rs create mode 100644 tests/ui/type-ptr.rs create mode 100644 tests/ui/type-use-i1-versus-i8.rs create mode 100644 tests/ui/type/ascription/issue-34255-1.rs create mode 100644 tests/ui/type/ascription/issue-34255-1.stderr create mode 100644 tests/ui/type/ascription/issue-47666.fixed create mode 100644 tests/ui/type/ascription/issue-47666.rs create mode 100644 tests/ui/type/ascription/issue-47666.stderr create mode 100644 tests/ui/type/ascription/issue-54516.fixed create mode 100644 tests/ui/type/ascription/issue-54516.rs create mode 100644 tests/ui/type/ascription/issue-54516.stderr create mode 100644 tests/ui/type/ascription/issue-60933.fixed create mode 100644 tests/ui/type/ascription/issue-60933.rs create mode 100644 tests/ui/type/ascription/issue-60933.stderr create mode 100644 tests/ui/type/auxiliary/crate_a1.rs create mode 100644 tests/ui/type/auxiliary/crate_a2.rs create mode 100644 tests/ui/type/binding-assigned-block-without-tail-expression.rs create mode 100644 tests/ui/type/binding-assigned-block-without-tail-expression.stderr create mode 100644 tests/ui/type/closure-with-wrong-borrows.rs create mode 100644 tests/ui/type/closure-with-wrong-borrows.stderr create mode 100644 tests/ui/type/issue-100584.rs create mode 100644 tests/ui/type/issue-100584.stderr create mode 100644 tests/ui/type/issue-101866.rs create mode 100644 tests/ui/type/issue-101866.stderr create mode 100644 tests/ui/type/issue-102598.rs create mode 100644 tests/ui/type/issue-102598.stderr create mode 100644 tests/ui/type/issue-103271.rs create mode 100644 tests/ui/type/issue-103271.stderr create mode 100644 tests/ui/type/issue-58355.rs create mode 100644 tests/ui/type/issue-58355.stderr create mode 100644 tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs create mode 100644 tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr create mode 100644 tests/ui/type/issue-91268.rs create mode 100644 tests/ui/type/issue-91268.stderr create mode 100644 tests/ui/type/issue-94187-verbose-type-name.rs create mode 100644 tests/ui/type/missing-let-in-binding.fixed create mode 100644 tests/ui/type/missing-let-in-binding.rs create mode 100644 tests/ui/type/missing-let-in-binding.stderr create mode 100644 tests/ui/type/type-alias-bounds.rs create mode 100644 tests/ui/type/type-alias-bounds.stderr create mode 100644 tests/ui/type/type-annotation-needed.rs create mode 100644 tests/ui/type/type-annotation-needed.stderr create mode 100644 tests/ui/type/type-arg-out-of-scope.rs create mode 100644 tests/ui/type/type-arg-out-of-scope.stderr create mode 100644 tests/ui/type/type-ascription-instead-of-initializer.rs create mode 100644 tests/ui/type/type-ascription-instead-of-initializer.stderr create mode 100644 tests/ui/type/type-ascription-instead-of-statement-end.rs create mode 100644 tests/ui/type/type-ascription-instead-of-statement-end.stderr create mode 100644 tests/ui/type/type-ascription-precedence.rs create mode 100644 tests/ui/type/type-ascription-precedence.stderr create mode 100644 tests/ui/type/type-ascription-soundness.rs create mode 100644 tests/ui/type/type-ascription-soundness.stderr create mode 100644 tests/ui/type/type-ascription-with-fn-call.fixed create mode 100644 tests/ui/type/type-ascription-with-fn-call.rs create mode 100644 tests/ui/type/type-ascription-with-fn-call.stderr create mode 100644 tests/ui/type/type-ascription.rs create mode 100644 tests/ui/type/type-check-defaults.rs create mode 100644 tests/ui/type/type-check-defaults.stderr create mode 100644 tests/ui/type/type-check/assignment-expected-bool.rs create mode 100644 tests/ui/type/type-check/assignment-expected-bool.stderr create mode 100644 tests/ui/type/type-check/assignment-in-if.rs create mode 100644 tests/ui/type/type-check/assignment-in-if.stderr create mode 100644 tests/ui/type/type-check/cannot_infer_local_or_array.rs create mode 100644 tests/ui/type/type-check/cannot_infer_local_or_array.stderr create mode 100644 tests/ui/type/type-check/cannot_infer_local_or_vec.rs create mode 100644 tests/ui/type/type-check/cannot_infer_local_or_vec.stderr create mode 100644 tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs create mode 100644 tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr create mode 100644 tests/ui/type/type-check/issue-22897.rs create mode 100644 tests/ui/type/type-check/issue-22897.stderr create mode 100644 tests/ui/type/type-check/issue-40294.rs create mode 100644 tests/ui/type/type-check/issue-40294.stderr create mode 100644 tests/ui/type/type-check/issue-41314.rs create mode 100644 tests/ui/type/type-check/issue-41314.stderr create mode 100644 tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs create mode 100644 tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr create mode 100644 tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs create mode 100644 tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr create mode 100644 tests/ui/type/type-check/missing_trait_impl.rs create mode 100644 tests/ui/type/type-check/missing_trait_impl.stderr create mode 100644 tests/ui/type/type-check/point-at-inference-2.rs create mode 100644 tests/ui/type/type-check/point-at-inference-2.stderr create mode 100644 tests/ui/type/type-check/point-at-inference-3.fixed create mode 100644 tests/ui/type/type-check/point-at-inference-3.rs create mode 100644 tests/ui/type/type-check/point-at-inference-3.stderr create mode 100644 tests/ui/type/type-check/point-at-inference.rs create mode 100644 tests/ui/type/type-check/point-at-inference.stderr create mode 100644 tests/ui/type/type-check/unknown_type_for_closure.rs create mode 100644 tests/ui/type/type-check/unknown_type_for_closure.stderr create mode 100644 tests/ui/type/type-dependent-def-issue-49241.rs create mode 100644 tests/ui/type/type-dependent-def-issue-49241.stderr create mode 100644 tests/ui/type/type-error-break-tail.rs create mode 100644 tests/ui/type/type-error-break-tail.stderr create mode 100644 tests/ui/type/type-mismatch-multiple.rs create mode 100644 tests/ui/type/type-mismatch-multiple.stderr create mode 100644 tests/ui/type/type-mismatch-same-crate-name.rs create mode 100644 tests/ui/type/type-mismatch-same-crate-name.stderr create mode 100644 tests/ui/type/type-mismatch.rs create mode 100644 tests/ui/type/type-mismatch.stderr create mode 100644 tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs create mode 100644 tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr create mode 100644 tests/ui/type/type-parameter-defaults-referencing-Self.rs create mode 100644 tests/ui/type/type-parameter-defaults-referencing-Self.stderr create mode 100644 tests/ui/type/type-parameter-names.rs create mode 100644 tests/ui/type/type-parameter-names.stderr create mode 100644 tests/ui/type/type-params-in-different-spaces-1.rs create mode 100644 tests/ui/type/type-params-in-different-spaces-1.stderr create mode 100644 tests/ui/type/type-params-in-different-spaces-2.rs create mode 100644 tests/ui/type/type-params-in-different-spaces-2.stderr create mode 100644 tests/ui/type/type-params-in-different-spaces-3.rs create mode 100644 tests/ui/type/type-params-in-different-spaces-3.stderr create mode 100644 tests/ui/type/type-path-err-node-types.rs create mode 100644 tests/ui/type/type-path-err-node-types.stderr create mode 100644 tests/ui/type/type-recursive-box-shadowed.rs create mode 100644 tests/ui/type/type-recursive-box-shadowed.stderr create mode 100644 tests/ui/type/type-recursive.rs create mode 100644 tests/ui/type/type-recursive.stderr create mode 100644 tests/ui/type/type-shadow.rs create mode 100644 tests/ui/type/type-shadow.stderr create mode 100644 tests/ui/type/type-unsatisfiable.rs create mode 100644 tests/ui/type/type-unsatisfiable.usage.stderr create mode 100644 tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs create mode 100644 tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr create mode 100644 tests/ui/type_length_limit.polonius.stderr create mode 100644 tests/ui/type_length_limit.rs create mode 100644 tests/ui/type_length_limit.stderr create mode 100644 tests/ui/typeck/assign-non-lval-derefmut.fixed create mode 100644 tests/ui/typeck/assign-non-lval-derefmut.rs create mode 100644 tests/ui/typeck/assign-non-lval-derefmut.stderr create mode 100644 tests/ui/typeck/assign-non-lval-mut-ref.fixed create mode 100644 tests/ui/typeck/assign-non-lval-mut-ref.rs create mode 100644 tests/ui/typeck/assign-non-lval-mut-ref.stderr create mode 100644 tests/ui/typeck/assign-non-lval-needs-deref.rs create mode 100644 tests/ui/typeck/assign-non-lval-needs-deref.stderr create mode 100644 tests/ui/typeck/autoderef-with-param-env-error.rs create mode 100644 tests/ui/typeck/autoderef-with-param-env-error.stderr create mode 100644 tests/ui/typeck/auxiliary/issue-36708.rs create mode 100644 tests/ui/typeck/auxiliary/issue-81943-lib.rs create mode 100644 tests/ui/typeck/auxiliary/tdticc_coherence_lib.rs create mode 100644 tests/ui/typeck/auxiliary/xcrate-issue-43189-a.rs create mode 100644 tests/ui/typeck/auxiliary/xcrate-issue-43189-b.rs create mode 100644 tests/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs create mode 100644 tests/ui/typeck/auxiliary/xcrate-issue-61711-b.rs create mode 100644 tests/ui/typeck/call-block.rs create mode 100644 tests/ui/typeck/call-block.stderr create mode 100644 tests/ui/typeck/check-args-on-fn-err-2.rs create mode 100644 tests/ui/typeck/check-args-on-fn-err-2.stderr create mode 100644 tests/ui/typeck/check-args-on-fn-err.rs create mode 100644 tests/ui/typeck/check-args-on-fn-err.stderr create mode 100644 tests/ui/typeck/conversion-methods.rs create mode 100644 tests/ui/typeck/conversion-methods.stderr create mode 100644 tests/ui/typeck/deref-multi.rs create mode 100644 tests/ui/typeck/deref-multi.stderr create mode 100644 tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs create mode 100644 tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr create mode 100644 tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs create mode 100644 tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr create mode 100644 tests/ui/typeck/explain_clone_autoref.rs create mode 100644 tests/ui/typeck/explain_clone_autoref.stderr create mode 100644 tests/ui/typeck/issue-100164.fixed create mode 100644 tests/ui/typeck/issue-100164.rs create mode 100644 tests/ui/typeck/issue-100164.stderr create mode 100644 tests/ui/typeck/issue-100246.rs create mode 100644 tests/ui/typeck/issue-100246.stderr create mode 100644 tests/ui/typeck/issue-100285.rs create mode 100644 tests/ui/typeck/issue-100285.stderr create mode 100644 tests/ui/typeck/issue-103899.rs create mode 100644 tests/ui/typeck/issue-10401.rs create mode 100644 tests/ui/typeck/issue-10401.stderr create mode 100644 tests/ui/typeck/issue-104510-ice.rs create mode 100644 tests/ui/typeck/issue-104510-ice.stderr create mode 100644 tests/ui/typeck/issue-104513-ice.rs create mode 100644 tests/ui/typeck/issue-104513-ice.stderr create mode 100644 tests/ui/typeck/issue-104582.rs create mode 100644 tests/ui/typeck/issue-104582.stderr create mode 100644 tests/ui/typeck/issue-105946.rs create mode 100644 tests/ui/typeck/issue-105946.stderr create mode 100644 tests/ui/typeck/issue-10969.rs create mode 100644 tests/ui/typeck/issue-10969.stderr create mode 100644 tests/ui/typeck/issue-13853-2.rs create mode 100644 tests/ui/typeck/issue-13853-2.stderr create mode 100644 tests/ui/typeck/issue-13853-5.rs create mode 100644 tests/ui/typeck/issue-13853-5.stderr create mode 100644 tests/ui/typeck/issue-13853.rs create mode 100644 tests/ui/typeck/issue-13853.stderr create mode 100644 tests/ui/typeck/issue-18937-1.rs create mode 100644 tests/ui/typeck/issue-18937.rs create mode 100644 tests/ui/typeck/issue-18937.stderr create mode 100644 tests/ui/typeck/issue-22375.rs create mode 100644 tests/ui/typeck/issue-29124.rs create mode 100644 tests/ui/typeck/issue-29124.stderr create mode 100644 tests/ui/typeck/issue-31173.rs create mode 100644 tests/ui/typeck/issue-31173.stderr create mode 100644 tests/ui/typeck/issue-33575.rs create mode 100644 tests/ui/typeck/issue-33575.stderr create mode 100644 tests/ui/typeck/issue-36708.rs create mode 100644 tests/ui/typeck/issue-36708.stderr create mode 100644 tests/ui/typeck/issue-43189.rs create mode 100644 tests/ui/typeck/issue-43189.stderr create mode 100644 tests/ui/typeck/issue-46112.rs create mode 100644 tests/ui/typeck/issue-46112.stderr create mode 100644 tests/ui/typeck/issue-50687-ice-on-borrow.rs create mode 100644 tests/ui/typeck/issue-50687-ice-on-borrow.stderr create mode 100644 tests/ui/typeck/issue-52082-type-param-shadows-existing-type.rs create mode 100644 tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr create mode 100644 tests/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs create mode 100644 tests/ui/typeck/issue-57404.rs create mode 100644 tests/ui/typeck/issue-57404.stderr create mode 100644 tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs create mode 100644 tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr create mode 100644 tests/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs create mode 100644 tests/ui/typeck/issue-65611.rs create mode 100644 tests/ui/typeck/issue-65611.stderr create mode 100644 tests/ui/typeck/issue-67971.rs create mode 100644 tests/ui/typeck/issue-67971.stderr create mode 100644 tests/ui/typeck/issue-68590-reborrow-through-derefmut.rs create mode 100644 tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.rs create mode 100644 tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr create mode 100644 tests/ui/typeck/issue-72225-call-fnmut-through-derefmut.rs create mode 100644 tests/ui/typeck/issue-73592-borrow_mut-through-deref.fixed create mode 100644 tests/ui/typeck/issue-73592-borrow_mut-through-deref.rs create mode 100644 tests/ui/typeck/issue-73592-borrow_mut-through-deref.stderr create mode 100644 tests/ui/typeck/issue-74086.rs create mode 100644 tests/ui/typeck/issue-74086.stderr create mode 100644 tests/ui/typeck/issue-74933.rs create mode 100644 tests/ui/typeck/issue-75883.rs create mode 100644 tests/ui/typeck/issue-75883.stderr create mode 100644 tests/ui/typeck/issue-75889.rs create mode 100644 tests/ui/typeck/issue-75889.stderr create mode 100644 tests/ui/typeck/issue-79040.rs create mode 100644 tests/ui/typeck/issue-79040.stderr create mode 100644 tests/ui/typeck/issue-80207-unsized-return.rs create mode 100644 tests/ui/typeck/issue-80779.rs create mode 100644 tests/ui/typeck/issue-80779.stderr create mode 100644 tests/ui/typeck/issue-81293.rs create mode 100644 tests/ui/typeck/issue-81293.stderr create mode 100644 tests/ui/typeck/issue-81885.rs create mode 100644 tests/ui/typeck/issue-81885.stderr create mode 100644 tests/ui/typeck/issue-81943.rs create mode 100644 tests/ui/typeck/issue-81943.stderr create mode 100644 tests/ui/typeck/issue-82772.rs create mode 100644 tests/ui/typeck/issue-82772.stderr create mode 100644 tests/ui/typeck/issue-83621-placeholder-static-in-extern.rs create mode 100644 tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr create mode 100644 tests/ui/typeck/issue-83693.rs create mode 100644 tests/ui/typeck/issue-83693.stderr create mode 100644 tests/ui/typeck/issue-84160.rs create mode 100644 tests/ui/typeck/issue-84160.stderr create mode 100644 tests/ui/typeck/issue-84768.rs create mode 100644 tests/ui/typeck/issue-84768.stderr create mode 100644 tests/ui/typeck/issue-84831.rs create mode 100644 tests/ui/typeck/issue-84831.stderr create mode 100644 tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr create mode 100644 tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr create mode 100644 tests/ui/typeck/issue-86721-return-expr-ice.rs create mode 100644 tests/ui/typeck/issue-87181/empty-tuple-method.rs create mode 100644 tests/ui/typeck/issue-87181/empty-tuple-method.stderr create mode 100644 tests/ui/typeck/issue-87181/enum-variant.rs create mode 100644 tests/ui/typeck/issue-87181/enum-variant.stderr create mode 100644 tests/ui/typeck/issue-87181/tuple-field.rs create mode 100644 tests/ui/typeck/issue-87181/tuple-field.stderr create mode 100644 tests/ui/typeck/issue-87181/tuple-method.rs create mode 100644 tests/ui/typeck/issue-87181/tuple-method.stderr create mode 100644 tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs create mode 100644 tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr create mode 100644 tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs create mode 100644 tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr create mode 100644 tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs create mode 100644 tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr create mode 100644 tests/ui/typeck/issue-87935-unsized-box-expr.rs create mode 100644 tests/ui/typeck/issue-87935-unsized-box-expr.stderr create mode 100644 tests/ui/typeck/issue-88609.rs create mode 100644 tests/ui/typeck/issue-88643.rs create mode 100644 tests/ui/typeck/issue-88643.stderr create mode 100644 tests/ui/typeck/issue-88803-call-expr-method.fixed create mode 100644 tests/ui/typeck/issue-88803-call-expr-method.rs create mode 100644 tests/ui/typeck/issue-88803-call-expr-method.stderr create mode 100644 tests/ui/typeck/issue-88844.rs create mode 100644 tests/ui/typeck/issue-88844.stderr create mode 100644 tests/ui/typeck/issue-89044-wrapped-expr-method.fixed create mode 100644 tests/ui/typeck/issue-89044-wrapped-expr-method.rs create mode 100644 tests/ui/typeck/issue-89044-wrapped-expr-method.stderr create mode 100644 tests/ui/typeck/issue-89275.rs create mode 100644 tests/ui/typeck/issue-89275.stderr create mode 100644 tests/ui/typeck/issue-89806.rs create mode 100644 tests/ui/typeck/issue-89806.stderr create mode 100644 tests/ui/typeck/issue-89856.rs create mode 100644 tests/ui/typeck/issue-89856.stderr create mode 100644 tests/ui/typeck/issue-89935.rs create mode 100644 tests/ui/typeck/issue-90101.rs create mode 100644 tests/ui/typeck/issue-90101.stderr create mode 100644 tests/ui/typeck/issue-90164.rs create mode 100644 tests/ui/typeck/issue-90164.stderr create mode 100644 tests/ui/typeck/issue-90319.rs create mode 100644 tests/ui/typeck/issue-90319.stderr create mode 100644 tests/ui/typeck/issue-90483-inaccessible-field-adjustment.rs create mode 100644 tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr create mode 100644 tests/ui/typeck/issue-90804-incorrect-reference-suggestion.rs create mode 100644 tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr create mode 100644 tests/ui/typeck/issue-91210-ptr-method.fixed create mode 100644 tests/ui/typeck/issue-91210-ptr-method.rs create mode 100644 tests/ui/typeck/issue-91210-ptr-method.stderr create mode 100644 tests/ui/typeck/issue-91267.rs create mode 100644 tests/ui/typeck/issue-91267.stderr create mode 100644 tests/ui/typeck/issue-91328.fixed create mode 100644 tests/ui/typeck/issue-91328.rs create mode 100644 tests/ui/typeck/issue-91328.stderr create mode 100644 tests/ui/typeck/issue-91334.rs create mode 100644 tests/ui/typeck/issue-91334.stderr create mode 100644 tests/ui/typeck/issue-91450-inner-ty-error.rs create mode 100644 tests/ui/typeck/issue-91450-inner-ty-error.stderr create mode 100644 tests/ui/typeck/issue-91633.rs create mode 100644 tests/ui/typeck/issue-92481.rs create mode 100644 tests/ui/typeck/issue-92481.stderr create mode 100644 tests/ui/typeck/issue-93486.rs create mode 100644 tests/ui/typeck/issue-93486.stderr create mode 100644 tests/ui/typeck/issue-96530.rs create mode 100644 tests/ui/typeck/issue-96530.stderr create mode 100644 tests/ui/typeck/issue-96738.rs create mode 100644 tests/ui/typeck/issue-96738.stderr create mode 100644 tests/ui/typeck/issue-98260.rs create mode 100644 tests/ui/typeck/issue-98260.stderr create mode 100644 tests/ui/typeck/issue-98982.rs create mode 100644 tests/ui/typeck/issue-98982.stderr create mode 100644 tests/ui/typeck/missing-private-fields-in-struct-literal.rs create mode 100644 tests/ui/typeck/missing-private-fields-in-struct-literal.stderr create mode 100644 tests/ui/typeck/no-type-for-node-ice.rs create mode 100644 tests/ui/typeck/no-type-for-node-ice.stderr create mode 100644 tests/ui/typeck/nonexistent-field-not-ambiguous.rs create mode 100644 tests/ui/typeck/nonexistent-field-not-ambiguous.stderr create mode 100644 tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs create mode 100644 tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr create mode 100644 tests/ui/typeck/point-at-type-param-in-path-expr.rs create mode 100644 tests/ui/typeck/point-at-type-param-in-path-expr.stderr create mode 100644 tests/ui/typeck/point-at-type-parameter-definition.rs create mode 100644 tests/ui/typeck/point-at-type-parameter-definition.stderr create mode 100644 tests/ui/typeck/prim-with-args.fixed create mode 100644 tests/ui/typeck/prim-with-args.rs create mode 100644 tests/ui/typeck/prim-with-args.stderr create mode 100644 tests/ui/typeck/project-cache-issue-37154.rs create mode 100644 tests/ui/typeck/quiet-type-err-let-binding.rs create mode 100644 tests/ui/typeck/quiet-type-err-let-binding.stderr create mode 100644 tests/ui/typeck/remove-extra-argument.fixed create mode 100644 tests/ui/typeck/remove-extra-argument.rs create mode 100644 tests/ui/typeck/remove-extra-argument.stderr create mode 100644 tests/ui/typeck/return_type_containing_closure.rs create mode 100644 tests/ui/typeck/return_type_containing_closure.stderr create mode 100644 tests/ui/typeck/slow-lhs-suggestion.rs create mode 100644 tests/ui/typeck/slow-lhs-suggestion.stderr create mode 100644 tests/ui/typeck/struct-enum-wrong-args.rs create mode 100644 tests/ui/typeck/struct-enum-wrong-args.stderr create mode 100644 tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed create mode 100644 tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs create mode 100644 tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr create mode 100644 tests/ui/typeck/type-placeholder-fn-in-const.rs create mode 100644 tests/ui/typeck/type-placeholder-fn-in-const.stderr create mode 100644 tests/ui/typeck/typeck-builtin-bound-type-parameters.rs create mode 100644 tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr create mode 100644 tests/ui/typeck/typeck-cast-pointer-to-float.rs create mode 100644 tests/ui/typeck/typeck-cast-pointer-to-float.stderr create mode 100644 tests/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs create mode 100644 tests/ui/typeck/typeck-default-trait-impl-assoc-type.fixed create mode 100644 tests/ui/typeck/typeck-default-trait-impl-assoc-type.rs create mode 100644 tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr create mode 100644 tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs create mode 100644 tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr create mode 100644 tests/ui/typeck/typeck-default-trait-impl-negation-send.rs create mode 100644 tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr create mode 100644 tests/ui/typeck/typeck-default-trait-impl-negation-sync.rs create mode 100644 tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr create mode 100644 tests/ui/typeck/typeck-default-trait-impl-send-param.rs create mode 100644 tests/ui/typeck/typeck-default-trait-impl-send-param.stderr create mode 100644 tests/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs create mode 100644 tests/ui/typeck/typeck-unsafe-always-share.rs create mode 100644 tests/ui/typeck/typeck-unsafe-always-share.stderr create mode 100644 tests/ui/typeck/typeck_type_placeholder_1.rs create mode 100644 tests/ui/typeck/typeck_type_placeholder_item.rs create mode 100644 tests/ui/typeck/typeck_type_placeholder_item.stderr create mode 100644 tests/ui/typeck/typeck_type_placeholder_item_help.rs create mode 100644 tests/ui/typeck/typeck_type_placeholder_item_help.stderr create mode 100644 tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs create mode 100644 tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr create mode 100644 tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs create mode 100644 tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr create mode 100644 tests/ui/typeck/typeck_type_placeholder_mismatch.rs create mode 100644 tests/ui/typeck/typeck_type_placeholder_mismatch.stderr create mode 100644 tests/ui/typeck/ufcs-type-params.rs create mode 100644 tests/ui/typeck/unify-return-ty.rs create mode 100644 tests/ui/typeck/while-loop-block-cond.rs create mode 100644 tests/ui/typeck/while-loop-block-cond.stderr create mode 100644 tests/ui/typeid-intrinsic.rs create mode 100644 tests/ui/typeof/issue-100183.rs create mode 100644 tests/ui/typeof/issue-100183.stderr create mode 100644 tests/ui/typeof/issue-29184.rs create mode 100644 tests/ui/typeof/issue-29184.stderr create mode 100644 tests/ui/typeof/issue-42060.rs create mode 100644 tests/ui/typeof/issue-42060.stderr create mode 100644 tests/ui/typeof/type_mismatch.rs create mode 100644 tests/ui/typeof/type_mismatch.stderr create mode 100644 tests/ui/typestate-multi-decl.rs create mode 100644 tests/ui/ufcs-polymorphic-paths.rs create mode 100644 tests/ui/ufcs/ufcs-explicit-self-bad.rs create mode 100644 tests/ui/ufcs/ufcs-explicit-self-bad.stderr create mode 100644 tests/ui/ufcs/ufcs-partially-resolved.rs create mode 100644 tests/ui/ufcs/ufcs-partially-resolved.stderr create mode 100644 tests/ui/ufcs/ufcs-qpath-missing-params.rs create mode 100644 tests/ui/ufcs/ufcs-qpath-missing-params.stderr create mode 100644 tests/ui/ufcs/ufcs-qpath-self-mismatch.rs create mode 100644 tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr create mode 100644 tests/ui/unboxed-closures/auxiliary/unboxed-closures-cross-crate.rs create mode 100644 tests/ui/unboxed-closures/issue-18652.rs create mode 100644 tests/ui/unboxed-closures/issue-18661.rs create mode 100644 tests/ui/unboxed-closures/issue-30906.rs create mode 100644 tests/ui/unboxed-closures/issue-30906.stderr create mode 100644 tests/ui/unboxed-closures/issue-53448.rs create mode 100644 tests/ui/unboxed-closures/non-tupled-arg-mismatch.rs create mode 100644 tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr create mode 100644 tests/ui/unboxed-closures/non-tupled-call.rs create mode 100644 tests/ui/unboxed-closures/non-tupled-call.stderr create mode 100644 tests/ui/unboxed-closures/type-id-higher-rank.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-feature-gate.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-illegal-move.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-immutable-capture.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-region.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-region.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-default.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-all-traits.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-boxed.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-by-ref.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-call-fn-autoderef.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-cross-crate.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-direct-sugary-call.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-drop.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-extern-fn-hr.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-generic.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-bound.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-object-type.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-w-bound-regs-from-expected-bound.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-explicit-call-early.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnmut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-fnonce.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-kind.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-infer-upvar.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-monomorphization.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-move-from-projection-issue-30046.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-move-mutable.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-move-mutable.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-move-some-upvars-in-by-ref-closure.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-prelude.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-simple.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-single-word-env.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-static-call-fn-once.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-sugar-object.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-type-mismatch.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-wrong-abi.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr create mode 100644 tests/ui/unboxed-closures/unboxed-closures-zero-args.rs create mode 100644 tests/ui/unconstrained-none.rs create mode 100644 tests/ui/unconstrained-none.stderr create mode 100644 tests/ui/unconstrained-ref.rs create mode 100644 tests/ui/unconstrained-ref.stderr create mode 100644 tests/ui/underscore-ident-matcher.rs create mode 100644 tests/ui/underscore-ident-matcher.stderr create mode 100644 tests/ui/underscore-imports/auxiliary/duplicate.rs create mode 100644 tests/ui/underscore-imports/auxiliary/underscore-imports.rs create mode 100644 tests/ui/underscore-imports/basic.rs create mode 100644 tests/ui/underscore-imports/basic.stderr create mode 100644 tests/ui/underscore-imports/cycle.rs create mode 100644 tests/ui/underscore-imports/duplicate.rs create mode 100644 tests/ui/underscore-imports/hygiene-2.rs create mode 100644 tests/ui/underscore-imports/hygiene.rs create mode 100644 tests/ui/underscore-imports/intercrate.rs create mode 100644 tests/ui/underscore-imports/macro-expanded.rs create mode 100644 tests/ui/underscore-imports/shadow.rs create mode 100644 tests/ui/underscore-imports/shadow.stderr create mode 100644 tests/ui/underscore-imports/unused-2018.rs create mode 100644 tests/ui/underscore-imports/unused-2018.stderr create mode 100644 tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs create mode 100644 tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr create mode 100644 tests/ui/underscore-lifetime/dyn-trait-underscore.rs create mode 100644 tests/ui/underscore-lifetime/dyn-trait-underscore.stderr create mode 100644 tests/ui/underscore-lifetime/in-binder.rs create mode 100644 tests/ui/underscore-lifetime/in-binder.stderr create mode 100644 tests/ui/underscore-lifetime/in-fn-return-illegal.rs create mode 100644 tests/ui/underscore-lifetime/in-fn-return-illegal.stderr create mode 100644 tests/ui/underscore-lifetime/in-struct.rs create mode 100644 tests/ui/underscore-lifetime/in-struct.stderr create mode 100644 tests/ui/underscore-lifetime/underscore-lifetime-binders.rs create mode 100644 tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr create mode 100644 tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs create mode 100644 tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr create mode 100644 tests/ui/underscore-lifetime/underscore-outlives-bounds.rs create mode 100644 tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs create mode 100644 tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs create mode 100644 tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs create mode 100644 tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs create mode 100644 tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr create mode 100644 tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr create mode 100644 tests/ui/underscore-lifetime/where-clauses.rs create mode 100644 tests/ui/underscore-lifetime/where-clauses.stderr create mode 100644 tests/ui/underscore-lifetimes.rs create mode 100644 tests/ui/underscore-method-after-integer.rs create mode 100644 tests/ui/unevaluated_fixed_size_array_len.rs create mode 100644 tests/ui/unevaluated_fixed_size_array_len.stderr create mode 100644 tests/ui/uniform-paths/auxiliary/issue-53691.rs create mode 100644 tests/ui/uniform-paths/basic-nested.rs create mode 100644 tests/ui/uniform-paths/basic.rs create mode 100644 tests/ui/uniform-paths/issue-53691.rs create mode 100644 tests/ui/uniform-paths/macros-nested.rs create mode 100644 tests/ui/uniform-paths/macros.rs create mode 100644 tests/ui/uniform-paths/same-crate.rs create mode 100644 tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs create mode 100644 tests/ui/uninhabited/privately-uninhabited-dead-code.rs create mode 100644 tests/ui/uninhabited/privately-uninhabited-mir-call.rs create mode 100644 tests/ui/uninhabited/privately-uninhabited-mir-call.stderr create mode 100644 tests/ui/uninhabited/uninhabited-enum-cast.rs create mode 100644 tests/ui/uninhabited/uninhabited-irrefutable.rs create mode 100644 tests/ui/uninhabited/uninhabited-irrefutable.stderr create mode 100644 tests/ui/uninhabited/uninhabited-matches-feature-gated.rs create mode 100644 tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr create mode 100644 tests/ui/uninhabited/uninhabited-patterns.rs create mode 100644 tests/ui/uninhabited/uninhabited-patterns.stderr create mode 100644 tests/ui/uninit-empty-types.rs create mode 100644 tests/ui/union/auxiliary/union.rs create mode 100644 tests/ui/union/field_checks.rs create mode 100644 tests/ui/union/field_checks.stderr create mode 100644 tests/ui/union/issue-41073.rs create mode 100644 tests/ui/union/issue-41073.stderr create mode 100644 tests/ui/union/issue-81199.rs create mode 100644 tests/ui/union/issue-81199.stderr create mode 100644 tests/ui/union/issue-99375.rs create mode 100644 tests/ui/union/union-align.rs create mode 100644 tests/ui/union/union-backcomp.rs create mode 100644 tests/ui/union/union-basic.rs create mode 100644 tests/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr create mode 100644 tests/ui/union/union-borrow-move-parent-sibling.rs create mode 100644 tests/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr create mode 100644 tests/ui/union/union-const-codegen.rs create mode 100644 tests/ui/union/union-const-eval-field.rs create mode 100644 tests/ui/union/union-const-eval.rs create mode 100644 tests/ui/union/union-const-pat.rs create mode 100644 tests/ui/union/union-const-pat.stderr create mode 100644 tests/ui/union/union-copy.rs create mode 100644 tests/ui/union/union-copy.stderr create mode 100644 tests/ui/union/union-deref.mirunsafeck.stderr create mode 100644 tests/ui/union/union-deref.rs create mode 100644 tests/ui/union/union-deref.thirunsafeck.stderr create mode 100644 tests/ui/union/union-derive-clone.mirunsafeck.stderr create mode 100644 tests/ui/union/union-derive-clone.rs create mode 100644 tests/ui/union/union-derive-clone.thirunsafeck.stderr create mode 100644 tests/ui/union/union-derive-eq.mirunsafeck.stderr create mode 100644 tests/ui/union/union-derive-eq.rs create mode 100644 tests/ui/union/union-derive-eq.thirunsafeck.stderr create mode 100644 tests/ui/union/union-derive-rpass.rs create mode 100644 tests/ui/union/union-derive.rs create mode 100644 tests/ui/union/union-derive.stderr create mode 100644 tests/ui/union/union-drop-assign.rs create mode 100644 tests/ui/union/union-drop.rs create mode 100644 tests/ui/union/union-empty.rs create mode 100644 tests/ui/union/union-empty.stderr create mode 100644 tests/ui/union/union-fields-1.mirunsafeck.stderr create mode 100644 tests/ui/union/union-fields-1.rs create mode 100644 tests/ui/union/union-fields-1.thirunsafeck.stderr create mode 100644 tests/ui/union/union-fields-2.mirunsafeck.stderr create mode 100644 tests/ui/union/union-fields-2.rs create mode 100644 tests/ui/union/union-fields-2.thirunsafeck.stderr create mode 100644 tests/ui/union/union-generic-rpass.rs create mode 100644 tests/ui/union/union-generic.mirunsafeck.stderr create mode 100644 tests/ui/union/union-generic.rs create mode 100644 tests/ui/union/union-generic.thirunsafeck.stderr create mode 100644 tests/ui/union/union-inherent-method.rs create mode 100644 tests/ui/union/union-lint-dead-code.mirunsafeck.stderr create mode 100644 tests/ui/union/union-lint-dead-code.rs create mode 100644 tests/ui/union/union-lint-dead-code.thirunsafeck.stderr create mode 100644 tests/ui/union/union-macro.rs create mode 100644 tests/ui/union/union-manuallydrop-rpass.rs create mode 100644 tests/ui/union/union-move.mirunsafeck.stderr create mode 100644 tests/ui/union/union-move.rs create mode 100644 tests/ui/union/union-move.thirunsafeck.stderr create mode 100644 tests/ui/union/union-nodrop.rs create mode 100644 tests/ui/union/union-nonrepresentable.rs create mode 100644 tests/ui/union/union-nonrepresentable.stderr create mode 100644 tests/ui/union/union-nonzero.rs create mode 100644 tests/ui/union/union-overwrite.rs create mode 100644 tests/ui/union/union-packed.rs create mode 100644 tests/ui/union/union-pat-refutability.rs create mode 100644 tests/ui/union/union-repr-c.rs create mode 100644 tests/ui/union/union-repr-c.stderr create mode 100644 tests/ui/union/union-sized-field.rs create mode 100644 tests/ui/union/union-sized-field.stderr create mode 100644 tests/ui/union/union-suggest-field.mirunsafeck.stderr create mode 100644 tests/ui/union/union-suggest-field.rs create mode 100644 tests/ui/union/union-suggest-field.thirunsafeck.stderr create mode 100644 tests/ui/union/union-trait-impl.rs create mode 100644 tests/ui/union/union-transmute.rs create mode 100644 tests/ui/union/union-unsafe.mir.stderr create mode 100644 tests/ui/union/union-unsafe.rs create mode 100644 tests/ui/union/union-unsafe.thir.stderr create mode 100644 tests/ui/union/union-unsized.mirunsafeck.stderr create mode 100644 tests/ui/union/union-unsized.rs create mode 100644 tests/ui/union/union-unsized.thirunsafeck.stderr create mode 100644 tests/ui/union/union-with-drop-fields.mirunsafeck.stderr create mode 100644 tests/ui/union/union-with-drop-fields.rs create mode 100644 tests/ui/union/union-with-drop-fields.thirunsafeck.stderr create mode 100644 tests/ui/unique-object-noncopyable.rs create mode 100644 tests/ui/unique-object-noncopyable.stderr create mode 100644 tests/ui/unique-pinned-nocopy.rs create mode 100644 tests/ui/unique-pinned-nocopy.stderr create mode 100644 tests/ui/unique/unique-assign-copy.rs create mode 100644 tests/ui/unique/unique-assign-drop.rs create mode 100644 tests/ui/unique/unique-assign-generic.rs create mode 100644 tests/ui/unique/unique-assign.rs create mode 100644 tests/ui/unique/unique-autoderef-field.rs create mode 100644 tests/ui/unique/unique-autoderef-index.rs create mode 100644 tests/ui/unique/unique-cmp.rs create mode 100644 tests/ui/unique/unique-containing-tag.rs create mode 100644 tests/ui/unique/unique-create.rs create mode 100644 tests/ui/unique/unique-decl-init-copy.rs create mode 100644 tests/ui/unique/unique-decl-init.rs create mode 100644 tests/ui/unique/unique-decl-move.rs create mode 100644 tests/ui/unique/unique-decl.rs create mode 100644 tests/ui/unique/unique-deref.rs create mode 100644 tests/ui/unique/unique-destructure.rs create mode 100644 tests/ui/unique/unique-drop-complex.rs create mode 100644 tests/ui/unique/unique-ffi-symbols.rs create mode 100644 tests/ui/unique/unique-fn-arg-move.rs create mode 100644 tests/ui/unique/unique-fn-arg-mut.rs create mode 100644 tests/ui/unique/unique-fn-arg.rs create mode 100644 tests/ui/unique/unique-fn-ret.rs create mode 100644 tests/ui/unique/unique-generic-assign.rs create mode 100644 tests/ui/unique/unique-in-tag.rs create mode 100644 tests/ui/unique/unique-in-vec-copy.rs create mode 100644 tests/ui/unique/unique-in-vec.rs create mode 100644 tests/ui/unique/unique-init.rs create mode 100644 tests/ui/unique/unique-kinds.rs create mode 100644 tests/ui/unique/unique-log.rs create mode 100644 tests/ui/unique/unique-match-discrim.rs create mode 100644 tests/ui/unique/unique-move-drop.rs create mode 100644 tests/ui/unique/unique-move-temp.rs create mode 100644 tests/ui/unique/unique-move.rs create mode 100644 tests/ui/unique/unique-mutable.rs create mode 100644 tests/ui/unique/unique-object-move.rs create mode 100644 tests/ui/unique/unique-pat-2.rs create mode 100644 tests/ui/unique/unique-pat-3.rs create mode 100644 tests/ui/unique/unique-pat.rs create mode 100644 tests/ui/unique/unique-rec.rs create mode 100644 tests/ui/unique/unique-send-2.rs create mode 100644 tests/ui/unique/unique-send.rs create mode 100644 tests/ui/unique/unique-swap.rs create mode 100644 tests/ui/unit.rs create mode 100644 tests/ui/unknown-language-item.rs create mode 100644 tests/ui/unknown-language-item.stderr create mode 100644 tests/ui/unknown-lint-tool-name.rs create mode 100644 tests/ui/unknown-lint-tool-name.stderr create mode 100644 tests/ui/unknown-llvm-arg.rs create mode 100644 tests/ui/unknown-llvm-arg.stderr create mode 100644 tests/ui/unknown-tool-name.rs create mode 100644 tests/ui/unknown-tool-name.stderr create mode 100644 tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-command-line.rs create mode 100644 tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-inline.rs create mode 100644 tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs create mode 100644 tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr create mode 100644 tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs create mode 100644 tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr create mode 100644 tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs create mode 100644 tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr create mode 100644 tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs create mode 100644 tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr create mode 100644 tests/ui/unnamed_argument_mode.rs create mode 100644 tests/ui/unop-move-semantics.rs create mode 100644 tests/ui/unop-move-semantics.stderr create mode 100644 tests/ui/unop-neg-bool.rs create mode 100644 tests/ui/unop-neg-bool.stderr create mode 100644 tests/ui/unpretty-expr-fn-arg.rs create mode 100644 tests/ui/unpretty-expr-fn-arg.stdout create mode 100644 tests/ui/unpretty/avoid-crash.rs create mode 100644 tests/ui/unpretty/avoid-crash.stderr create mode 100644 tests/ui/unpretty/bad-literal.rs create mode 100644 tests/ui/unpretty/bad-literal.stderr create mode 100644 tests/ui/unpretty/bad-literal.stdout create mode 100644 tests/ui/unpretty/pretty-let-else.rs create mode 100644 tests/ui/unpretty/pretty-let-else.stdout create mode 100644 tests/ui/unreachable-code-1.rs create mode 100644 tests/ui/unreachable-code.rs create mode 100644 tests/ui/unresolved/unresolved-asterisk-imports.rs create mode 100644 tests/ui/unresolved/unresolved-asterisk-imports.stderr create mode 100644 tests/ui/unresolved/unresolved-candidates.rs create mode 100644 tests/ui/unresolved/unresolved-candidates.stderr create mode 100644 tests/ui/unresolved/unresolved-extern-mod-suggestion.rs create mode 100644 tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr create mode 100644 tests/ui/unresolved/unresolved-import-recovery.rs create mode 100644 tests/ui/unresolved/unresolved-import-recovery.stderr create mode 100644 tests/ui/unresolved/unresolved-import.rs create mode 100644 tests/ui/unresolved/unresolved-import.stderr create mode 100644 tests/ui/unsafe-fn-called-from-unsafe-blk.rs create mode 100644 tests/ui/unsafe-fn-called-from-unsafe-fn.rs create mode 100644 tests/ui/unsafe-pointer-assignability.rs create mode 100644 tests/ui/unsafe/access_union_field.mir.stderr create mode 100644 tests/ui/unsafe/access_union_field.rs create mode 100644 tests/ui/unsafe/access_union_field.thir.stderr create mode 100644 tests/ui/unsafe/auxiliary/issue-106126.rs create mode 100644 tests/ui/unsafe/inline_asm.mir.stderr create mode 100644 tests/ui/unsafe/inline_asm.rs create mode 100644 tests/ui/unsafe/inline_asm.thir.stderr create mode 100644 tests/ui/unsafe/issue-106126-good-path-bug.rs create mode 100644 tests/ui/unsafe/issue-3080.mir.stderr create mode 100644 tests/ui/unsafe/issue-3080.rs create mode 100644 tests/ui/unsafe/issue-3080.thir.stderr create mode 100644 tests/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr create mode 100644 tests/ui/unsafe/issue-45087-unreachable-unsafe.rs create mode 100644 tests/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr create mode 100644 tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr create mode 100644 tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs create mode 100644 tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr create mode 100644 tests/ui/unsafe/issue-47412.mir.stderr create mode 100644 tests/ui/unsafe/issue-47412.rs create mode 100644 tests/ui/unsafe/issue-47412.thir.stderr create mode 100644 tests/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs create mode 100644 tests/ui/unsafe/issue-87414-query-cycle.rs create mode 100644 tests/ui/unsafe/ranged_ints.mir.stderr create mode 100644 tests/ui/unsafe/ranged_ints.rs create mode 100644 tests/ui/unsafe/ranged_ints.thir.stderr create mode 100644 tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints2.rs create mode 100644 tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints2_const.rs create mode 100644 tests/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints3.rs create mode 100644 tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints3_const.rs create mode 100644 tests/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints3_match.rs create mode 100644 tests/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints4.rs create mode 100644 tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints4_const.rs create mode 100644 tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/ranged_ints_const.mir.stderr create mode 100644 tests/ui/unsafe/ranged_ints_const.rs create mode 100644 tests/ui/unsafe/ranged_ints_const.thir.stderr create mode 100644 tests/ui/unsafe/ranged_ints_macro.rs create mode 100644 tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr create mode 100644 tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs create mode 100644 tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr create mode 100644 tests/ui/unsafe/union-assignop.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/union-assignop.rs create mode 100644 tests/ui/unsafe/union-assignop.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/union-modification.rs create mode 100644 tests/ui/unsafe/union.mir.stderr create mode 100644 tests/ui/unsafe/union.rs create mode 100644 tests/ui/unsafe/union.thir.stderr create mode 100644 tests/ui/unsafe/union_access_through_block.rs create mode 100644 tests/ui/unsafe/union_destructure.mir.stderr create mode 100644 tests/ui/unsafe/union_destructure.rs create mode 100644 tests/ui/unsafe/union_wild_or_wild.rs create mode 100644 tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs create mode 100644 tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr create mode 100644 tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/unsafe-assign.rs create mode 100644 tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/unsafe-block-without-braces.rs create mode 100644 tests/ui/unsafe/unsafe-block-without-braces.stderr create mode 100644 tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr create mode 100644 tests/ui/unsafe/unsafe-borrow.rs create mode 100644 tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr create mode 100644 tests/ui/unsafe/unsafe-const-fn.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-const-fn.rs create mode 100644 tests/ui/unsafe/unsafe-const-fn.thir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-assign-deref-ptr.rs create mode 100644 tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-autoderef.rs create mode 100644 tests/ui/unsafe/unsafe-fn-autoderef.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-called-from-safe.rs create mode 100644 tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-deref-ptr.rs create mode 100644 tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-fn-used-as-value.rs create mode 100644 tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr create mode 100644 tests/ui/unsafe/unsafe-not-inherited.rs create mode 100644 tests/ui/unsafe/unsafe-not-inherited.stderr create mode 100644 tests/ui/unsafe/unsafe-subtyping.rs create mode 100644 tests/ui/unsafe/unsafe-subtyping.stderr create mode 100644 tests/ui/unsafe/unsafe-trait-impl.rs create mode 100644 tests/ui/unsafe/unsafe-trait-impl.stderr create mode 100644 tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr create mode 100644 tests/ui/unsafe/unsafe-unstable-const-fn.rs create mode 100644 tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr create mode 100644 tests/ui/unsigned-literal-negation.rs create mode 100644 tests/ui/unsigned-literal-negation.stderr create mode 100644 tests/ui/unsized-locals/autoderef.rs create mode 100644 tests/ui/unsized-locals/auxiliary/ufuncs.rs create mode 100644 tests/ui/unsized-locals/borrow-after-move.rs create mode 100644 tests/ui/unsized-locals/borrow-after-move.stderr create mode 100644 tests/ui/unsized-locals/box-fnonce.rs create mode 100644 tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs create mode 100644 tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs create mode 100644 tests/ui/unsized-locals/by-value-trait-object-safety.rs create mode 100644 tests/ui/unsized-locals/by-value-trait-object-safety.stderr create mode 100644 tests/ui/unsized-locals/double-move.rs create mode 100644 tests/ui/unsized-locals/double-move.stderr create mode 100644 tests/ui/unsized-locals/issue-30276-feature-flagged.rs create mode 100644 tests/ui/unsized-locals/issue-30276-feature-flagged.stderr create mode 100644 tests/ui/unsized-locals/issue-30276.rs create mode 100644 tests/ui/unsized-locals/issue-30276.stderr create mode 100644 tests/ui/unsized-locals/issue-50940-with-feature.rs create mode 100644 tests/ui/unsized-locals/issue-50940-with-feature.stderr create mode 100644 tests/ui/unsized-locals/issue-50940.rs create mode 100644 tests/ui/unsized-locals/issue-50940.stderr create mode 100644 tests/ui/unsized-locals/reference-unsized-locals.rs create mode 100644 tests/ui/unsized-locals/simple-unsized-locals.rs create mode 100644 tests/ui/unsized-locals/suggest-borrow.rs create mode 100644 tests/ui/unsized-locals/suggest-borrow.stderr create mode 100644 tests/ui/unsized-locals/unsized-exprs-rpass.rs create mode 100644 tests/ui/unsized-locals/unsized-exprs.rs create mode 100644 tests/ui/unsized-locals/unsized-exprs.stderr create mode 100644 tests/ui/unsized-locals/unsized-exprs2.rs create mode 100644 tests/ui/unsized-locals/unsized-exprs2.stderr create mode 100644 tests/ui/unsized-locals/unsized-exprs3.rs create mode 100644 tests/ui/unsized-locals/unsized-exprs3.stderr create mode 100644 tests/ui/unsized-locals/unsized-index.rs create mode 100644 tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs create mode 100644 tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr create mode 100644 tests/ui/unsized-locals/unsized-parameters.rs create mode 100644 tests/ui/unsized/box-instead-of-dyn-fn.rs create mode 100644 tests/ui/unsized/box-instead-of-dyn-fn.stderr create mode 100644 tests/ui/unsized/issue-30355.rs create mode 100644 tests/ui/unsized/issue-30355.stderr create mode 100644 tests/ui/unsized/issue-40231-1.rs create mode 100644 tests/ui/unsized/issue-40231-2.rs create mode 100644 tests/ui/unsized/issue-71659.rs create mode 100644 tests/ui/unsized/issue-71659.stderr create mode 100644 tests/ui/unsized/issue-75707.rs create mode 100644 tests/ui/unsized/issue-75707.stderr create mode 100644 tests/ui/unsized/issue-75899-but-gats.rs create mode 100644 tests/ui/unsized/issue-75899.rs create mode 100644 tests/ui/unsized/issue-91801.rs create mode 100644 tests/ui/unsized/issue-91801.stderr create mode 100644 tests/ui/unsized/issue-91803.rs create mode 100644 tests/ui/unsized/issue-91803.stderr create mode 100644 tests/ui/unsized/issue-97732.rs create mode 100644 tests/ui/unsized/maybe-bounds-where-cpass.rs create mode 100644 tests/ui/unsized/maybe-bounds-where.rs create mode 100644 tests/ui/unsized/maybe-bounds-where.stderr create mode 100644 tests/ui/unsized/param-mentioned-by-different-field.rs create mode 100644 tests/ui/unsized/param-mentioned-by-different-field.stderr create mode 100644 tests/ui/unsized/return-unsized-from-trait-method.rs create mode 100644 tests/ui/unsized/return-unsized-from-trait-method.stderr create mode 100644 tests/ui/unsized/unchanged-param.rs create mode 100644 tests/ui/unsized/unsized-bare-typaram.rs create mode 100644 tests/ui/unsized/unsized-bare-typaram.stderr create mode 100644 tests/ui/unsized/unsized-enum.rs create mode 100644 tests/ui/unsized/unsized-enum.stderr create mode 100644 tests/ui/unsized/unsized-enum2.rs create mode 100644 tests/ui/unsized/unsized-enum2.stderr create mode 100644 tests/ui/unsized/unsized-fn-arg.fixed create mode 100644 tests/ui/unsized/unsized-fn-arg.rs create mode 100644 tests/ui/unsized/unsized-fn-arg.stderr create mode 100644 tests/ui/unsized/unsized-fn-param.rs create mode 100644 tests/ui/unsized/unsized-fn-param.stderr create mode 100644 tests/ui/unsized/unsized-inherent-impl-self-type.rs create mode 100644 tests/ui/unsized/unsized-inherent-impl-self-type.stderr create mode 100644 tests/ui/unsized/unsized-struct.rs create mode 100644 tests/ui/unsized/unsized-struct.stderr create mode 100644 tests/ui/unsized/unsized-trait-impl-self-type.rs create mode 100644 tests/ui/unsized/unsized-trait-impl-self-type.stderr create mode 100644 tests/ui/unsized/unsized-trait-impl-trait-arg.rs create mode 100644 tests/ui/unsized/unsized-trait-impl-trait-arg.stderr create mode 100644 tests/ui/unsized/unsized-tuple-impls.rs create mode 100644 tests/ui/unsized/unsized.rs create mode 100644 tests/ui/unsized/unsized2.rs create mode 100644 tests/ui/unsized/unsized3-rpass.rs create mode 100644 tests/ui/unsized/unsized3.rs create mode 100644 tests/ui/unsized/unsized3.stderr create mode 100644 tests/ui/unsized/unsized5.rs create mode 100644 tests/ui/unsized/unsized5.stderr create mode 100644 tests/ui/unsized/unsized6.rs create mode 100644 tests/ui/unsized/unsized6.stderr create mode 100644 tests/ui/unsized/unsized7.rs create mode 100644 tests/ui/unsized/unsized7.stderr create mode 100644 tests/ui/unterminated-comment.rs create mode 100644 tests/ui/unterminated-comment.stderr create mode 100644 tests/ui/unterminated-nested-comment.rs create mode 100644 tests/ui/unterminated-nested-comment.stderr create mode 100644 tests/ui/unused-crate-deps/auxiliary/bar.rs create mode 100644 tests/ui/unused-crate-deps/auxiliary/foo.rs create mode 100644 tests/ui/unused-crate-deps/deny-attr.rs create mode 100644 tests/ui/unused-crate-deps/deny-attr.stderr create mode 100644 tests/ui/unused-crate-deps/deny-cmdline-json-silent.rs create mode 100644 tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr create mode 100644 tests/ui/unused-crate-deps/deny-cmdline-json.rs create mode 100644 tests/ui/unused-crate-deps/deny-cmdline-json.stderr create mode 100644 tests/ui/unused-crate-deps/deny-cmdline.rs create mode 100644 tests/ui/unused-crate-deps/deny-cmdline.stderr create mode 100644 tests/ui/unused-crate-deps/ignore-pathless-extern.rs create mode 100644 tests/ui/unused-crate-deps/libfib.rs create mode 100644 tests/ui/unused-crate-deps/libfib.stderr create mode 100644 tests/ui/unused-crate-deps/lint-group.rs create mode 100644 tests/ui/unused-crate-deps/suppress.rs create mode 100644 tests/ui/unused-crate-deps/test-use-ok.rs create mode 100644 tests/ui/unused-crate-deps/test.mk create mode 100644 tests/ui/unused-crate-deps/unused-aliases.rs create mode 100644 tests/ui/unused-crate-deps/unused-aliases.stderr create mode 100644 tests/ui/unused-crate-deps/use_extern_crate_2015.rs create mode 100644 tests/ui/unused-crate-deps/warn-attr.rs create mode 100644 tests/ui/unused-crate-deps/warn-attr.stderr create mode 100644 tests/ui/unused-crate-deps/warn-cmdline-json.rs create mode 100644 tests/ui/unused-crate-deps/warn-cmdline-json.stderr create mode 100644 tests/ui/unused-crate-deps/warn-cmdline-static.rs create mode 100644 tests/ui/unused-crate-deps/warn-cmdline-static.stderr create mode 100644 tests/ui/unused-crate-deps/warn-cmdline.rs create mode 100644 tests/ui/unused-crate-deps/warn-cmdline.stderr create mode 100644 tests/ui/unused-move-capture.rs create mode 100644 tests/ui/unused-move.rs create mode 100644 tests/ui/unwind-abis/feature-gate-c-unwind-enabled.rs create mode 100644 tests/ui/unwind-abis/feature-gate-c-unwind.rs create mode 100644 tests/ui/unwind-abis/feature-gate-c-unwind.stderr create mode 100644 tests/ui/unwind-abis/feature-gate-stdcall-unwind.rs create mode 100644 tests/ui/unwind-abis/feature-gate-stdcall-unwind.stderr create mode 100644 tests/ui/unwind-abis/feature-gate-system-unwind.rs create mode 100644 tests/ui/unwind-abis/feature-gate-system-unwind.stderr create mode 100644 tests/ui/unwind-abis/feature-gate-thiscall-unwind.rs create mode 100644 tests/ui/unwind-abis/feature-gate-thiscall-unwind.stderr create mode 100644 tests/ui/unwind-abis/ffi-unwind-calls-lint.rs create mode 100644 tests/ui/unwind-abis/ffi-unwind-calls-lint.stderr create mode 100644 tests/ui/unwind-no-uwtable.rs create mode 100644 tests/ui/unwind-unique.rs create mode 100644 tests/ui/use-import-export.rs create mode 100644 tests/ui/use-keyword-2.rs create mode 100644 tests/ui/use-module-level-int-consts.rs create mode 100644 tests/ui/use-nested-groups.rs create mode 100644 tests/ui/use.rs create mode 100644 tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs create mode 100644 tests/ui/use/auxiliary/use-from-trait-xc.rs create mode 100644 tests/ui/use/issue-18986.rs create mode 100644 tests/ui/use/issue-18986.stderr create mode 100644 tests/ui/use/issue-60976-extern-use-primitive-type.rs create mode 100644 tests/ui/use/use-after-move-based-on-type.rs create mode 100644 tests/ui/use/use-after-move-based-on-type.stderr create mode 100644 tests/ui/use/use-after-move-implicity-coerced-object.rs create mode 100644 tests/ui/use/use-after-move-implicity-coerced-object.stderr create mode 100644 tests/ui/use/use-after-move-self-based-on-type.rs create mode 100644 tests/ui/use/use-after-move-self-based-on-type.stderr create mode 100644 tests/ui/use/use-after-move-self.rs create mode 100644 tests/ui/use/use-after-move-self.stderr create mode 100644 tests/ui/use/use-associated-const.rs create mode 100644 tests/ui/use/use-associated-const.stderr create mode 100644 tests/ui/use/use-crate-self.rs create mode 100644 tests/ui/use/use-crate-self.stderr create mode 100644 tests/ui/use/use-from-trait-xc.rs create mode 100644 tests/ui/use/use-from-trait-xc.stderr create mode 100644 tests/ui/use/use-from-trait.rs create mode 100644 tests/ui/use/use-from-trait.stderr create mode 100644 tests/ui/use/use-keyword.rs create mode 100644 tests/ui/use/use-keyword.stderr create mode 100644 tests/ui/use/use-meta-mismatch.rs create mode 100644 tests/ui/use/use-meta-mismatch.stderr create mode 100644 tests/ui/use/use-mod.rs create mode 100644 tests/ui/use/use-mod.stderr create mode 100644 tests/ui/use/use-mod/use-mod-2.rs create mode 100644 tests/ui/use/use-mod/use-mod-2.stderr create mode 100644 tests/ui/use/use-mod/use-mod-3.rs create mode 100644 tests/ui/use/use-mod/use-mod-3.stderr create mode 100644 tests/ui/use/use-mod/use-mod-4.rs create mode 100644 tests/ui/use/use-mod/use-mod-4.stderr create mode 100644 tests/ui/use/use-mod/use-mod-5.rs create mode 100644 tests/ui/use/use-mod/use-mod-5.stderr create mode 100644 tests/ui/use/use-mod/use-mod-6.rs create mode 100644 tests/ui/use/use-mod/use-mod-6.stderr create mode 100644 tests/ui/use/use-nested-groups-error.rs create mode 100644 tests/ui/use/use-nested-groups-error.stderr create mode 100644 tests/ui/use/use-nested-groups-unused-imports.rs create mode 100644 tests/ui/use/use-nested-groups-unused-imports.stderr create mode 100644 tests/ui/use/use-paths-as-items.rs create mode 100644 tests/ui/use/use-paths-as-items.stderr create mode 100644 tests/ui/use/use-self-type.rs create mode 100644 tests/ui/use/use-self-type.stderr create mode 100644 tests/ui/use/use-super-global-path.rs create mode 100644 tests/ui/use/use-super-global-path.stderr create mode 100644 tests/ui/used.rs create mode 100644 tests/ui/used.stderr create mode 100644 tests/ui/user-defined-macro-rules.rs create mode 100644 tests/ui/using-target-feature-unstable.rs create mode 100644 tests/ui/usize-generic-argument-parent.rs create mode 100644 tests/ui/usize-generic-argument-parent.stderr create mode 100644 tests/ui/utf8-bom.rs create mode 100644 tests/ui/utf8_idents.rs create mode 100644 tests/ui/variance-intersection-of-ref-and-opt-ref.rs create mode 100644 tests/ui/variance-iterators-in-libcore.rs create mode 100644 tests/ui/variance/variance-associated-consts.rs create mode 100644 tests/ui/variance/variance-associated-consts.stderr create mode 100644 tests/ui/variance/variance-associated-types.rs create mode 100644 tests/ui/variance/variance-associated-types.stderr create mode 100644 tests/ui/variance/variance-associated-types2.rs create mode 100644 tests/ui/variance/variance-associated-types2.stderr create mode 100644 tests/ui/variance/variance-btree-invariant-types.rs create mode 100644 tests/ui/variance/variance-btree-invariant-types.stderr create mode 100644 tests/ui/variance/variance-cell-is-invariant.rs create mode 100644 tests/ui/variance/variance-cell-is-invariant.stderr create mode 100644 tests/ui/variance/variance-contravariant-arg-object.rs create mode 100644 tests/ui/variance/variance-contravariant-arg-object.stderr create mode 100644 tests/ui/variance/variance-contravariant-arg-trait-match.rs create mode 100644 tests/ui/variance/variance-contravariant-arg-trait-match.stderr create mode 100644 tests/ui/variance/variance-contravariant-self-trait-match.rs create mode 100644 tests/ui/variance/variance-contravariant-self-trait-match.stderr create mode 100644 tests/ui/variance/variance-covariant-arg-object.rs create mode 100644 tests/ui/variance/variance-covariant-arg-object.stderr create mode 100644 tests/ui/variance/variance-covariant-arg-trait-match.rs create mode 100644 tests/ui/variance/variance-covariant-arg-trait-match.stderr create mode 100644 tests/ui/variance/variance-covariant-self-trait-match.rs create mode 100644 tests/ui/variance/variance-covariant-self-trait-match.stderr create mode 100644 tests/ui/variance/variance-invariant-arg-object.rs create mode 100644 tests/ui/variance/variance-invariant-arg-object.stderr create mode 100644 tests/ui/variance/variance-invariant-arg-trait-match.rs create mode 100644 tests/ui/variance/variance-invariant-arg-trait-match.stderr create mode 100644 tests/ui/variance/variance-invariant-self-trait-match.rs create mode 100644 tests/ui/variance/variance-invariant-self-trait-match.stderr create mode 100644 tests/ui/variance/variance-issue-20533.rs create mode 100644 tests/ui/variance/variance-issue-20533.stderr create mode 100644 tests/ui/variance/variance-object-types.rs create mode 100644 tests/ui/variance/variance-object-types.stderr create mode 100644 tests/ui/variance/variance-regions-direct.rs create mode 100644 tests/ui/variance/variance-regions-direct.stderr create mode 100644 tests/ui/variance/variance-regions-indirect.rs create mode 100644 tests/ui/variance/variance-regions-indirect.stderr create mode 100644 tests/ui/variance/variance-regions-unused-direct.rs create mode 100644 tests/ui/variance/variance-regions-unused-direct.stderr create mode 100644 tests/ui/variance/variance-regions-unused-indirect.rs create mode 100644 tests/ui/variance/variance-regions-unused-indirect.stderr create mode 100644 tests/ui/variance/variance-trait-bounds.rs create mode 100644 tests/ui/variance/variance-trait-bounds.stderr create mode 100644 tests/ui/variance/variance-trait-matching.rs create mode 100644 tests/ui/variance/variance-trait-matching.stderr create mode 100644 tests/ui/variance/variance-trait-object-bound.rs create mode 100644 tests/ui/variance/variance-trait-object-bound.stderr create mode 100644 tests/ui/variance/variance-types-bounds.rs create mode 100644 tests/ui/variance/variance-types-bounds.stderr create mode 100644 tests/ui/variance/variance-types.rs create mode 100644 tests/ui/variance/variance-types.stderr create mode 100644 tests/ui/variance/variance-unused-region-param.rs create mode 100644 tests/ui/variance/variance-unused-region-param.stderr create mode 100644 tests/ui/variance/variance-unused-type-param.rs create mode 100644 tests/ui/variance/variance-unused-type-param.stderr create mode 100644 tests/ui/variance/variance-use-contravariant-struct-1.rs create mode 100644 tests/ui/variance/variance-use-contravariant-struct-1.stderr create mode 100644 tests/ui/variance/variance-use-contravariant-struct-2.rs create mode 100644 tests/ui/variance/variance-use-covariant-struct-1.rs create mode 100644 tests/ui/variance/variance-use-covariant-struct-1.stderr create mode 100644 tests/ui/variance/variance-use-covariant-struct-2.rs create mode 100644 tests/ui/variance/variance-use-invariant-struct-1.rs create mode 100644 tests/ui/variance/variance-use-invariant-struct-1.stderr create mode 100644 tests/ui/variants/auxiliary/variant-namespacing.rs create mode 100644 tests/ui/variants/variant-namespacing.rs create mode 100644 tests/ui/variants/variant-namespacing.stderr create mode 100644 tests/ui/variants/variant-size-differences.rs create mode 100644 tests/ui/variants/variant-size-differences.stderr create mode 100644 tests/ui/variants/variant-used-as-type.rs create mode 100644 tests/ui/variants/variant-used-as-type.stderr create mode 100644 tests/ui/wait-forked-but-failed-child.rs create mode 100644 tests/ui/walk-struct-literal-with.rs create mode 100644 tests/ui/walk-struct-literal-with.stderr create mode 100644 tests/ui/wasm-custom-section-relocations.rs create mode 100644 tests/ui/wasm-custom-section-relocations.stderr create mode 100644 tests/ui/wasm/simd-to-array-80108.rs create mode 100644 tests/ui/wasm/wasm-hang-issue-76281.rs create mode 100644 tests/ui/wasm/wasm-import-module.rs create mode 100644 tests/ui/wasm/wasm-import-module.stderr create mode 100644 tests/ui/weak-new-uninhabited-issue-48493.rs create mode 100644 tests/ui/weird-exit-code.rs create mode 100644 tests/ui/weird-exprs.rs create mode 100644 tests/ui/wf/hir-wf-canonicalized.rs create mode 100644 tests/ui/wf/hir-wf-canonicalized.stderr create mode 100644 tests/ui/wf/hir-wf-check-erase-regions.rs create mode 100644 tests/ui/wf/hir-wf-check-erase-regions.stderr create mode 100644 tests/ui/wf/issue-103573.rs create mode 100644 tests/ui/wf/issue-103573.stderr create mode 100644 tests/ui/wf/issue-48638.rs create mode 100644 tests/ui/wf/issue-87495.rs create mode 100644 tests/ui/wf/issue-87495.stderr create mode 100644 tests/ui/wf/issue-95665.rs create mode 100644 tests/ui/wf/issue-95665.stderr create mode 100644 tests/ui/wf/issue-96810.rs create mode 100644 tests/ui/wf/issue-96810.stderr create mode 100644 tests/ui/wf/wf-array-elem-sized.rs create mode 100644 tests/ui/wf/wf-array-elem-sized.stderr create mode 100644 tests/ui/wf/wf-complex-assoc-type.rs create mode 100644 tests/ui/wf/wf-complex-assoc-type.stderr create mode 100644 tests/ui/wf/wf-const-type.rs create mode 100644 tests/ui/wf/wf-const-type.stderr create mode 100644 tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs create mode 100644 tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr create mode 100644 tests/ui/wf/wf-convert-unsafe-trait-obj.rs create mode 100644 tests/ui/wf/wf-convert-unsafe-trait-obj.stderr create mode 100644 tests/ui/wf/wf-enum-bound.rs create mode 100644 tests/ui/wf/wf-enum-bound.stderr create mode 100644 tests/ui/wf/wf-enum-fields-struct-variant.rs create mode 100644 tests/ui/wf/wf-enum-fields-struct-variant.stderr create mode 100644 tests/ui/wf/wf-enum-fields.rs create mode 100644 tests/ui/wf/wf-enum-fields.stderr create mode 100644 tests/ui/wf/wf-fn-where-clause.rs create mode 100644 tests/ui/wf/wf-fn-where-clause.stderr create mode 100644 tests/ui/wf/wf-foreign-fn-decl-ret.rs create mode 100644 tests/ui/wf/wf-foreign-fn-decl-ret.stderr create mode 100644 tests/ui/wf/wf-impl-associated-type-region.rs create mode 100644 tests/ui/wf/wf-impl-associated-type-region.stderr create mode 100644 tests/ui/wf/wf-impl-associated-type-trait.rs create mode 100644 tests/ui/wf/wf-impl-associated-type-trait.stderr create mode 100644 tests/ui/wf/wf-impl-self-type.rs create mode 100644 tests/ui/wf/wf-impl-self-type.stderr create mode 100644 tests/ui/wf/wf-in-fn-arg.rs create mode 100644 tests/ui/wf/wf-in-fn-arg.stderr create mode 100644 tests/ui/wf/wf-in-fn-ret.rs create mode 100644 tests/ui/wf/wf-in-fn-ret.stderr create mode 100644 tests/ui/wf/wf-in-fn-type-arg.rs create mode 100644 tests/ui/wf/wf-in-fn-type-arg.stderr create mode 100644 tests/ui/wf/wf-in-fn-type-ret.rs create mode 100644 tests/ui/wf/wf-in-fn-type-ret.stderr create mode 100644 tests/ui/wf/wf-in-fn-type-static.rs create mode 100644 tests/ui/wf/wf-in-fn-type-static.stderr create mode 100644 tests/ui/wf/wf-in-fn-where-clause.rs create mode 100644 tests/ui/wf/wf-in-fn-where-clause.stderr create mode 100644 tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs create mode 100644 tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr create mode 100644 tests/ui/wf/wf-in-obj-type-static.rs create mode 100644 tests/ui/wf/wf-in-obj-type-static.stderr create mode 100644 tests/ui/wf/wf-in-obj-type-trait.rs create mode 100644 tests/ui/wf/wf-in-obj-type-trait.stderr create mode 100644 tests/ui/wf/wf-inherent-impl-method-where-clause.rs create mode 100644 tests/ui/wf/wf-inherent-impl-method-where-clause.stderr create mode 100644 tests/ui/wf/wf-inherent-impl-where-clause.rs create mode 100644 tests/ui/wf/wf-inherent-impl-where-clause.stderr create mode 100644 tests/ui/wf/wf-misc-methods-issue-28609.rs create mode 100644 tests/ui/wf/wf-misc-methods-issue-28609.stderr create mode 100644 tests/ui/wf/wf-object-safe.rs create mode 100644 tests/ui/wf/wf-object-safe.stderr create mode 100644 tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs create mode 100644 tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr create mode 100644 tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs create mode 100644 tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr create mode 100644 tests/ui/wf/wf-static-method.rs create mode 100644 tests/ui/wf/wf-static-method.stderr create mode 100644 tests/ui/wf/wf-static-type.rs create mode 100644 tests/ui/wf/wf-static-type.stderr create mode 100644 tests/ui/wf/wf-struct-bound.rs create mode 100644 tests/ui/wf/wf-struct-bound.stderr create mode 100644 tests/ui/wf/wf-struct-field.rs create mode 100644 tests/ui/wf/wf-struct-field.stderr create mode 100644 tests/ui/wf/wf-trait-associated-type-bound.rs create mode 100644 tests/ui/wf/wf-trait-associated-type-bound.stderr create mode 100644 tests/ui/wf/wf-trait-associated-type-region.rs create mode 100644 tests/ui/wf/wf-trait-associated-type-region.stderr create mode 100644 tests/ui/wf/wf-trait-associated-type-trait.rs create mode 100644 tests/ui/wf/wf-trait-associated-type-trait.stderr create mode 100644 tests/ui/wf/wf-trait-bound.rs create mode 100644 tests/ui/wf/wf-trait-bound.stderr create mode 100644 tests/ui/wf/wf-trait-default-fn-arg.rs create mode 100644 tests/ui/wf/wf-trait-default-fn-arg.stderr create mode 100644 tests/ui/wf/wf-trait-default-fn-ret.rs create mode 100644 tests/ui/wf/wf-trait-default-fn-ret.stderr create mode 100644 tests/ui/wf/wf-trait-default-fn-where-clause.rs create mode 100644 tests/ui/wf/wf-trait-default-fn-where-clause.stderr create mode 100644 tests/ui/wf/wf-trait-fn-arg.rs create mode 100644 tests/ui/wf/wf-trait-fn-arg.stderr create mode 100644 tests/ui/wf/wf-trait-fn-ret.rs create mode 100644 tests/ui/wf/wf-trait-fn-ret.stderr create mode 100644 tests/ui/wf/wf-trait-fn-where-clause.rs create mode 100644 tests/ui/wf/wf-trait-fn-where-clause.stderr create mode 100644 tests/ui/wf/wf-trait-superbound.rs create mode 100644 tests/ui/wf/wf-trait-superbound.stderr create mode 100644 tests/ui/wf/wf-unsafe-trait-obj-match.rs create mode 100644 tests/ui/wf/wf-unsafe-trait-obj-match.stderr create mode 100644 tests/ui/where-clauses/auxiliary/where_clauses_xc.rs create mode 100644 tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr create mode 100644 tests/ui/where-clauses/higher-ranked-fn-type.rs create mode 100644 tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr create mode 100644 tests/ui/where-clauses/ignore-err-clauses.rs create mode 100644 tests/ui/where-clauses/ignore-err-clauses.stderr create mode 100644 tests/ui/where-clauses/where-clause-bounds-inconsistency.rs create mode 100644 tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs create mode 100644 tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr create mode 100644 tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs create mode 100644 tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr create mode 100644 tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs create mode 100644 tests/ui/where-clauses/where-clause-method-substituion-rpass.rs create mode 100644 tests/ui/where-clauses/where-clause-method-substituion.rs create mode 100644 tests/ui/where-clauses/where-clause-method-substituion.stderr create mode 100644 tests/ui/where-clauses/where-clause-region-outlives.rs create mode 100644 tests/ui/where-clauses/where-clauses-cross-crate.rs create mode 100644 tests/ui/where-clauses/where-clauses-lifetimes.rs create mode 100644 tests/ui/where-clauses/where-clauses-method-unsatisfied.rs create mode 100644 tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr create mode 100644 tests/ui/where-clauses/where-clauses-method.rs create mode 100644 tests/ui/where-clauses/where-clauses-unboxed-closures.rs create mode 100644 tests/ui/where-clauses/where-clauses-unsatisfied.rs create mode 100644 tests/ui/where-clauses/where-clauses-unsatisfied.stderr create mode 100644 tests/ui/where-clauses/where-clauses.rs create mode 100644 tests/ui/where-clauses/where-equality-constraints.rs create mode 100644 tests/ui/where-clauses/where-equality-constraints.stderr create mode 100644 tests/ui/where-clauses/where-for-self-2.rs create mode 100644 tests/ui/where-clauses/where-for-self-2.stderr create mode 100644 tests/ui/where-clauses/where-for-self.rs create mode 100644 tests/ui/where-clauses/where-for-self.stderr create mode 100644 tests/ui/where-clauses/where-lifetime-resolution.rs create mode 100644 tests/ui/where-clauses/where-lifetime-resolution.stderr create mode 100644 tests/ui/while-type-error.rs create mode 100644 tests/ui/while-type-error.stderr create mode 100644 tests/ui/windows-subsystem-invalid.rs create mode 100644 tests/ui/windows-subsystem-invalid.stderr create mode 100644 tests/ui/write-fmt-errors.rs create mode 100644 tests/ui/writing-to-immutable-vec.rs create mode 100644 tests/ui/writing-to-immutable-vec.stderr create mode 100644 tests/ui/wrong-hashset-issue-42918.rs create mode 100644 tests/ui/wrong-mul-method-signature.rs create mode 100644 tests/ui/wrong-mul-method-signature.stderr create mode 100644 tests/ui/wrong-ret-type.rs create mode 100644 tests/ui/wrong-ret-type.stderr create mode 100644 tests/ui/xc-private-method.rs create mode 100644 tests/ui/xc-private-method.stderr create mode 100644 tests/ui/xc-private-method2.rs create mode 100644 tests/ui/xc-private-method2.stderr create mode 100644 tests/ui/xcrate/auxiliary/static_priv_by_default.rs create mode 100644 tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs create mode 100644 tests/ui/xcrate/xcrate-private-by-default.rs create mode 100644 tests/ui/xcrate/xcrate-private-by-default.stderr create mode 100644 tests/ui/xcrate/xcrate-unit-struct-2.rs create mode 100644 tests/ui/xcrate/xcrate-unit-struct.rs create mode 100644 tests/ui/xcrate/xcrate-unit-struct.stderr create mode 100644 tests/ui/zero-sized/zero-size-type-destructors.rs create mode 100644 tests/ui/zero-sized/zero-sized-binary-heap-push.rs create mode 100644 tests/ui/zero-sized/zero-sized-btreemap-insert.rs create mode 100644 tests/ui/zero-sized/zero-sized-linkedlist-push.rs create mode 100644 tests/ui/zero-sized/zero-sized-tuple-struct.rs (limited to 'tests/ui') diff --git a/tests/ui/abi/abi-sysv64-arg-passing.rs b/tests/ui/abi/abi-sysv64-arg-passing.rs new file mode 100644 index 000000000..c87353b93 --- /dev/null +++ b/tests/ui/abi/abi-sysv64-arg-passing.rs @@ -0,0 +1,448 @@ +// run-pass +// Checks if the "sysv64" calling convention behaves the same as the +// "C" calling convention on platforms where both should be the same + +// This file contains versions of the following run-pass tests with +// the calling convention changed to "sysv64" + +// cabi-int-widening +// extern-pass-char +// extern-pass-u32 +// extern-pass-u64 +// extern-pass-double +// extern-pass-empty +// extern-pass-TwoU8s +// extern-pass-TwoU16s +// extern-pass-TwoU32s +// extern-pass-TwoU64s +// extern-return-TwoU8s +// extern-return-TwoU16s +// extern-return-TwoU32s +// extern-return-TwoU64s +// foreign-fn-with-byval +// issue-28676 +// issue-62350-sysv-neg-reg-counts +// struct-return + +// ignore-android +// ignore-arm +// ignore-aarch64 +// ignore-windows + +// note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows + +#[allow(dead_code)] +#[allow(improper_ctypes)] + +#[cfg(target_arch = "x86_64")] +mod tests { + #[repr(C)] + #[derive(Copy, Clone, PartialEq, Debug)] + pub struct TwoU8s { + one: u8, two: u8 + } + + #[repr(C)] + #[derive(Copy, Clone, PartialEq, Debug)] + pub struct TwoU16s { + one: u16, two: u16 + } + + #[repr(C)] + #[derive(Copy, Clone, PartialEq, Debug)] + pub struct TwoU32s { + one: u32, two: u32 + } + + #[repr(C)] + #[derive(Copy, Clone, PartialEq, Debug)] + pub struct TwoU64s { + one: u64, two: u64 + } + + #[repr(C)] + pub struct ManyInts { + arg1: i8, + arg2: i16, + arg3: i32, + arg4: i16, + arg5: i8, + arg6: TwoU8s, + } + + #[repr(C)] + pub struct Empty; + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct S { + x: u64, + y: u64, + z: u64, + } + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct Quad { a: u64, b: u64, c: u64, d: u64 } + + #[derive(Copy, Clone)] + pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 } + + #[repr(C)] + #[derive(Copy, Clone)] + pub struct Floats { a: f64, b: u8, c: f64 } + + #[repr(C, u8)] + pub enum U8TaggedEnumOptionU64U64 { + None, + Some(u64,u64), + } + + #[repr(C, u8)] + pub enum U8TaggedEnumOptionU64 { + None, + Some(u64), + } + + #[link(name = "rust_test_helpers", kind = "static")] + extern "sysv64" { + pub fn rust_int8_to_int32(_: i8) -> i32; + pub fn rust_dbg_extern_identity_u8(v: u8) -> u8; + pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; + pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; + pub fn rust_dbg_extern_identity_double(v: f64) -> f64; + pub fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts); + pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; + pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; + pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; + pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s; + pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s; + pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s; + pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; + pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s; + pub fn get_x(x: S) -> u64; + pub fn get_y(x: S) -> u64; + pub fn get_z(x: S) -> u64; + pub fn get_c_many_params(_: *const (), _: *const (), + _: *const (), _: *const (), f: Quad) -> u64; + pub fn get_c_exhaust_sysv64_ints( + _: *const (), + _: *const (), + _: *const (), + _: *const (), + _: *const (), + _: *const (), + _: *const (), + h: QuadFloats, + ) -> f32; + pub fn rust_dbg_abi_1(q: Quad) -> Quad; + pub fn rust_dbg_abi_2(f: Floats) -> Floats; + pub fn rust_dbg_new_some_u64u64(a: u64, b: u64) -> U8TaggedEnumOptionU64U64; + pub fn rust_dbg_new_none_u64u64() -> U8TaggedEnumOptionU64U64; + pub fn rust_dbg_unpack_option_u64u64( + o: U8TaggedEnumOptionU64U64, + a: *mut u64, + b: *mut u64, + ) -> i32; + pub fn rust_dbg_new_some_u64(some: u64) -> U8TaggedEnumOptionU64; + pub fn rust_dbg_new_none_u64() -> U8TaggedEnumOptionU64; + pub fn rust_dbg_unpack_option_u64(o: U8TaggedEnumOptionU64, v: *mut u64) -> i32; + } + + pub fn cabi_int_widening() { + let x = unsafe { + rust_int8_to_int32(-1) + }; + + assert!(x == -1); + } + + pub fn extern_pass_char() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u8(22)); + } + } + + pub fn extern_pass_u32() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u32(22)); + } + } + + pub fn extern_pass_u64() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u64(22)); + } + } + + pub fn extern_pass_double() { + unsafe { + assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64)); + } + } + + pub fn extern_pass_empty() { + unsafe { + let x = ManyInts { + arg1: 2, + arg2: 3, + arg3: 4, + arg4: 5, + arg5: 6, + arg6: TwoU8s { one: 7, two: 8, } + }; + let y = ManyInts { + arg1: 1, + arg2: 2, + arg3: 3, + arg4: 4, + arg5: 5, + arg6: TwoU8s { one: 6, two: 7, } + }; + let empty = Empty; + rust_dbg_extern_empty_struct(x, empty, y); + } + } + + pub fn extern_pass_twou8s() { + unsafe { + let x = TwoU8s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU8s(x); + assert_eq!(x, y); + } + } + + pub fn extern_pass_twou16s() { + unsafe { + let x = TwoU16s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU16s(x); + assert_eq!(x, y); + } + } + + pub fn extern_pass_twou32s() { + unsafe { + let x = TwoU32s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU32s(x); + assert_eq!(x, y); + } + } + + pub fn extern_pass_twou64s() { + unsafe { + let x = TwoU64s {one: 22, two: 23}; + let y = rust_dbg_extern_identity_TwoU64s(x); + assert_eq!(x, y); + } + } + + pub fn extern_return_twou8s() { + unsafe { + let y = rust_dbg_extern_return_TwoU8s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } + } + + pub fn extern_return_twou16s() { + unsafe { + let y = rust_dbg_extern_return_TwoU16s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } + } + + pub fn extern_return_twou32s() { + unsafe { + let y = rust_dbg_extern_return_TwoU32s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } + } + + pub fn extern_return_twou64s() { + unsafe { + let y = rust_dbg_extern_return_TwoU64s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } + } + + #[inline(never)] + fn indirect_call(func: unsafe extern "sysv64" fn(s: S) -> u64, s: S) -> u64 { + unsafe { + func(s) + } + } + + pub fn foreign_fn_with_byval() { + let s = S { x: 1, y: 2, z: 3 }; + assert_eq!(s.x, indirect_call(get_x, s)); + assert_eq!(s.y, indirect_call(get_y, s)); + assert_eq!(s.z, indirect_call(get_z, s)); + } + + fn test() { + use std::ptr; + unsafe { + let null = ptr::null(); + let q = Quad { + a: 1, + b: 2, + c: 3, + d: 4 + }; + assert_eq!(get_c_many_params(null, null, null, null, q), q.c); + } + } + + pub fn issue_28676() { + test(); + } + + fn test_62350() { + use std::ptr; + unsafe { + let null = ptr::null(); + let q = QuadFloats { + a: 10.2, + b: 20.3, + c: 30.4, + d: 40.5 + }; + assert_eq!( + get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q), + q.c, + ); + } + } + + pub fn issue_62350() { + test_62350(); + } + + fn test1() { + unsafe { + let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa, + b: 0xbbbb_bbbb_bbbb_bbbb, + c: 0xcccc_cccc_cccc_cccc, + d: 0xdddd_dddd_dddd_dddd }; + let qq = rust_dbg_abi_1(q); + println!("a: {:x}", qq.a as usize); + println!("b: {:x}", qq.b as usize); + println!("c: {:x}", qq.c as usize); + println!("d: {:x}", qq.d as usize); + assert_eq!(qq.a, q.c + 1); + assert_eq!(qq.b, q.d - 1); + assert_eq!(qq.c, q.a + 1); + assert_eq!(qq.d, q.b - 1); + } + } + + fn test2() { + unsafe { + let f = Floats { a: 1.234567890e-15_f64, + b: 0b_1010_1010, + c: 1.0987654321e-15_f64 }; + let ff = rust_dbg_abi_2(f); + println!("a: {}", ff.a as f64); + println!("b: {}", ff.b as usize); + println!("c: {}", ff.c as f64); + assert_eq!(ff.a, f.c + 1.0f64); + assert_eq!(ff.b, 0xff); + assert_eq!(ff.c, f.a - 1.0f64); + } + } + + pub fn struct_return() { + test1(); + test2(); + } + + pub fn enum_passing_and_return_pair() { + let some_u64u64 = unsafe { rust_dbg_new_some_u64u64(10, 20) }; + if let U8TaggedEnumOptionU64U64::Some(a, b) = some_u64u64 { + assert_eq!(10, a); + assert_eq!(20, b); + } else { + panic!("unexpected none"); + } + + let none_u64u64 = unsafe { rust_dbg_new_none_u64u64() }; + if let U8TaggedEnumOptionU64U64::Some(_,_) = none_u64u64 { + panic!("unexpected some"); + } + + let mut a: u64 = 0; + let mut b: u64 = 0; + let r = unsafe { + rust_dbg_unpack_option_u64u64(some_u64u64, &mut a as *mut _, &mut b as *mut _) + }; + assert_eq!(1, r); + assert_eq!(10, a); + assert_eq!(20, b); + + let mut a: u64 = 0; + let mut b: u64 = 0; + let r = unsafe { + rust_dbg_unpack_option_u64u64(none_u64u64, &mut a as *mut _, &mut b as *mut _) + }; + assert_eq!(0, r); + assert_eq!(0, a); + assert_eq!(0, b); + } + + pub fn enum_passing_and_return() { + let some_u64 = unsafe { rust_dbg_new_some_u64(10) }; + if let U8TaggedEnumOptionU64::Some(v) = some_u64 { + assert_eq!(10, v); + } else { + panic!("unexpected none"); + } + + let none_u64 = unsafe { rust_dbg_new_none_u64() }; + if let U8TaggedEnumOptionU64::Some(_) = none_u64 { + panic!("unexpected some"); + } + + let mut target: u64 = 0; + let r = unsafe { rust_dbg_unpack_option_u64(some_u64, &mut target as *mut _) }; + assert_eq!(1, r); + assert_eq!(10, target); + + let mut target: u64 = 0; + let r = unsafe { rust_dbg_unpack_option_u64(none_u64, &mut target as *mut _) }; + assert_eq!(0, r); + assert_eq!(0, target); + } +} + +#[cfg(target_arch = "x86_64")] +fn main() { + use tests::*; + cabi_int_widening(); + extern_pass_char(); + extern_pass_u32(); + extern_pass_u64(); + extern_pass_double(); + extern_pass_empty(); + extern_pass_twou8s(); + extern_pass_twou16s(); + extern_pass_twou32s(); + extern_pass_twou64s(); + extern_return_twou8s(); + extern_return_twou16s(); + extern_return_twou32s(); + extern_return_twou64s(); + foreign_fn_with_byval(); + issue_28676(); + issue_62350(); + struct_return(); + enum_passing_and_return_pair(); + enum_passing_and_return(); +} + +#[cfg(not(target_arch = "x86_64"))] +fn main() { + +} diff --git a/tests/ui/abi/abi-sysv64-register-usage.rs b/tests/ui/abi/abi-sysv64-register-usage.rs new file mode 100644 index 000000000..393306936 --- /dev/null +++ b/tests/ui/abi/abi-sysv64-register-usage.rs @@ -0,0 +1,107 @@ +// run-pass +// Checks if the correct registers are being used to pass arguments +// when the sysv64 ABI is specified. + +// ignore-android +// ignore-arm +// ignore-aarch64 +// needs-asm-support + +#[cfg(target_arch = "x86_64")] +pub extern "sysv64" fn all_the_registers( + rdi: i64, + rsi: i64, + rdx: i64, + rcx: i64, + r8: i64, + r9: i64, + xmm0: f32, + xmm1: f32, + xmm2: f32, + xmm3: f32, + xmm4: f32, + xmm5: f32, + xmm6: f32, + xmm7: f32, +) -> i64 { + assert_eq!(rdi, 1); + assert_eq!(rsi, 2); + assert_eq!(rdx, 3); + assert_eq!(rcx, 4); + assert_eq!(r8, 5); + assert_eq!(r9, 6); + assert_eq!(xmm0, 1.0f32); + assert_eq!(xmm1, 2.0f32); + assert_eq!(xmm2, 4.0f32); + assert_eq!(xmm3, 8.0f32); + assert_eq!(xmm4, 16.0f32); + assert_eq!(xmm5, 32.0f32); + assert_eq!(xmm6, 64.0f32); + assert_eq!(xmm7, 128.0f32); + 42 +} + +// this struct contains 8 i64's, while only 6 can be passed in registers. +#[cfg(target_arch = "x86_64")] +#[derive(PartialEq, Eq, Debug)] +pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64); + +#[cfg(target_arch = "x86_64")] +#[inline(never)] +#[allow(improper_ctypes_definitions)] +pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct { + foo.0 *= 1; + foo.1 *= 2; + foo.2 *= 3; + foo.3 *= 4; + foo.4 *= 5; + foo.5 *= 6; + foo.6 *= 7; + foo.7 *= 8; + foo +} + +#[cfg(target_arch = "x86_64")] +pub fn main() { + use std::arch::asm; + + let result: i64; + unsafe { + asm!("mov rdi, 1", + "mov rsi, 2", + "mov rdx, 3", + "mov rcx, 4", + "mov r8, 5", + "mov r9, 6", + "mov eax, 0x3F800000", + "movd xmm0, eax", + "mov eax, 0x40000000", + "movd xmm1, eax", + "mov eax, 0x40800000", + "movd xmm2, eax", + "mov eax, 0x41000000", + "movd xmm3, eax", + "mov eax, 0x41800000", + "movd xmm4, eax", + "mov eax, 0x42000000", + "movd xmm5, eax", + "mov eax, 0x42800000", + "movd xmm6, eax", + "mov eax, 0x43000000", + "movd xmm7, eax", + "call {0}", + sym all_the_registers, + out("rax") result, + clobber_abi("sysv64"), + ); + } + assert_eq!(result, 42); + + assert_eq!( + large_struct_by_val(LargeStruct(1, 2, 3, 4, 5, 6, 7, 8)), + LargeStruct(1, 4, 9, 16, 25, 36, 49, 64) + ); +} + +#[cfg(not(target_arch = "x86_64"))] +pub fn main() {} diff --git a/tests/ui/abi/abi-typo-unstable.rs b/tests/ui/abi/abi-typo-unstable.rs new file mode 100644 index 000000000..94991a5eb --- /dev/null +++ b/tests/ui/abi/abi-typo-unstable.rs @@ -0,0 +1,6 @@ +// rust-intrinsic is unstable and not enabled, so it should not be suggested as a fix +extern "rust-intrinsec" fn rust_intrinsic() {} //~ ERROR invalid ABI + +fn main() { + rust_intrinsic(); +} diff --git a/tests/ui/abi/abi-typo-unstable.stderr b/tests/ui/abi/abi-typo-unstable.stderr new file mode 100644 index 000000000..3b346e002 --- /dev/null +++ b/tests/ui/abi/abi-typo-unstable.stderr @@ -0,0 +1,11 @@ +error[E0703]: invalid ABI: found `rust-intrinsec` + --> $DIR/abi-typo-unstable.rs:2:8 + | +LL | extern "rust-intrinsec" fn rust_intrinsic() {} + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/anon-extern-mod.rs b/tests/ui/abi/anon-extern-mod.rs new file mode 100644 index 000000000..6c7d60d4c --- /dev/null +++ b/tests/ui/abi/anon-extern-mod.rs @@ -0,0 +1,18 @@ +// run-pass +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate libc; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_get_test_int() -> libc::intptr_t; +} + +pub fn main() { + unsafe { + let _ = rust_get_test_int(); + } +} diff --git a/tests/ui/abi/c-stack-as-value.rs b/tests/ui/abi/c-stack-as-value.rs new file mode 100644 index 000000000..5bece0ba2 --- /dev/null +++ b/tests/ui/abi/c-stack-as-value.rs @@ -0,0 +1,18 @@ +// run-pass +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_get_test_int() -> libc::intptr_t; + } +} + +pub fn main() { + let _foo = rustrt::rust_get_test_int; +} diff --git a/tests/ui/abi/c-stack-returning-int64.rs b/tests/ui/abi/c-stack-returning-int64.rs new file mode 100644 index 000000000..fb3cb2083 --- /dev/null +++ b/tests/ui/abi/c-stack-returning-int64.rs @@ -0,0 +1,36 @@ +// run-pass +// ignore-wasm32-bare no libc to test with +// ignore-sgx no libc + +#![feature(rustc_private)] + +extern crate libc; + +use std::ffi::CString; + +mod mlibc { + use libc::{c_char, c_long, c_longlong}; + + extern "C" { + pub fn atol(x: *const c_char) -> c_long; + pub fn atoll(x: *const c_char) -> c_longlong; + } +} + +fn atol(s: String) -> isize { + let c = CString::new(s).unwrap(); + unsafe { mlibc::atol(c.as_ptr()) as isize } +} + +fn atoll(s: String) -> i64 { + let c = CString::new(s).unwrap(); + unsafe { mlibc::atoll(c.as_ptr()) as i64 } +} + +pub fn main() { + assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string())); + assert_eq!( + (atoll("11111111111111111".to_string()) * 10), + atoll("111111111111111110".to_string()) + ); +} diff --git a/tests/ui/abi/cabi-int-widening.rs b/tests/ui/abi/cabi-int-widening.rs new file mode 100644 index 000000000..1dbab2752 --- /dev/null +++ b/tests/ui/abi/cabi-int-widening.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_int8_to_int32(_: i8) -> i32; +} + +fn main() { + let x = unsafe { + rust_int8_to_int32(-1) + }; + + assert!(x == -1); +} diff --git a/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs b/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs new file mode 100644 index 000000000..77168be53 --- /dev/null +++ b/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:anon-extern-mod-cross-crate-1.rs +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with + +extern crate anonexternmod; + +use anonexternmod::rust_get_test_int; + +pub fn main() { + unsafe { + rust_get_test_int(); + } +} diff --git a/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs new file mode 100644 index 000000000..5cbf8093c --- /dev/null +++ b/tests/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -0,0 +1,9 @@ +#![crate_name = "anonexternmod"] +#![feature(rustc_private)] + +extern crate libc; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_get_test_int() -> libc::intptr_t; +} diff --git a/tests/ui/abi/cross-crate/duplicated-external-mods.rs b/tests/ui/abi/cross-crate/duplicated-external-mods.rs new file mode 100644 index 000000000..05a279a30 --- /dev/null +++ b/tests/ui/abi/cross-crate/duplicated-external-mods.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:anon-extern-mod-cross-crate-1.rs +// aux-build:anon-extern-mod-cross-crate-1.rs +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with + +extern crate anonexternmod; + +pub fn main() { } diff --git a/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs b/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs new file mode 100644 index 000000000..9c61518b9 --- /dev/null +++ b/tests/ui/abi/extern/auxiliary/extern-crosscrate-source.rs @@ -0,0 +1,28 @@ +#![crate_name = "externcallback"] +#![crate_type = "lib"] +#![feature(rustc_private)] + +extern crate libc; + +pub mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +pub fn fact(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { fact(data - 1) * data } +} diff --git a/tests/ui/abi/extern/extern-call-deep.rs b/tests/ui/abi/extern/extern-call-deep.rs new file mode 100644 index 000000000..db5f2ca65 --- /dev/null +++ b/tests/ui/abi/extern/extern-call-deep.rs @@ -0,0 +1,36 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with +// ignore-emscripten blows the JS stack + +#![feature(rustc_private)] + +extern crate libc; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { count(data - 1) + 1 } +} + +fn count(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + let result = count(1000); + println!("result = {}", result); + assert_eq!(result, 1000); +} diff --git a/tests/ui/abi/extern/extern-call-deep2.rs b/tests/ui/abi/extern/extern-call-deep2.rs new file mode 100644 index 000000000..60e8db159 --- /dev/null +++ b/tests/ui/abi/extern/extern-call-deep2.rs @@ -0,0 +1,41 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +#![feature(rustc_private)] + +extern crate libc; +use std::thread; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { count(data - 1) + 1 } +} + +fn count(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + // Make sure we're on a thread with small Rust stacks (main currently + // has a large stack) + thread::spawn(move || { + let result = count(1000); + println!("result = {}", result); + assert_eq!(result, 1000); + }) + .join(); +} diff --git a/tests/ui/abi/extern/extern-call-direct.rs b/tests/ui/abi/extern/extern-call-direct.rs new file mode 100644 index 000000000..19b901d49 --- /dev/null +++ b/tests/ui/abi/extern/extern-call-direct.rs @@ -0,0 +1,10 @@ +// run-pass +// Test direct calls to extern fns. + + +extern "C" fn f(x: usize) -> usize { x * 2 } + +pub fn main() { + let x = f(22); + assert_eq!(x, 44); +} diff --git a/tests/ui/abi/extern/extern-call-indirect.rs b/tests/ui/abi/extern/extern-call-indirect.rs new file mode 100644 index 000000000..886e8f6be --- /dev/null +++ b/tests/ui/abi/extern/extern-call-indirect.rs @@ -0,0 +1,35 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate libc; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { fact(data - 1) * data } +} + +fn fact(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + let result = fact(10); + println!("result = {}", result); + assert_eq!(result, 3628800); +} diff --git a/tests/ui/abi/extern/extern-call-scrub.rs b/tests/ui/abi/extern/extern-call-scrub.rs new file mode 100644 index 000000000..ff33cf31a --- /dev/null +++ b/tests/ui/abi/extern/extern-call-scrub.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(unused_must_use)] +// This time we're testing repeatedly going up and down both stacks to +// make sure the stack pointers are maintained properly in both +// directions + +// ignore-emscripten no threads support +#![feature(rustc_private)] + +extern crate libc; +use std::thread; + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_call( + cb: extern "C" fn(libc::uintptr_t) -> libc::uintptr_t, + data: libc::uintptr_t, + ) -> libc::uintptr_t; + } +} + +extern "C" fn cb(data: libc::uintptr_t) -> libc::uintptr_t { + if data == 1 { data } else { count(data - 1) + count(data - 1) } +} + +fn count(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + rustrt::rust_dbg_call(cb, n) + } +} + +pub fn main() { + // Make sure we're on a thread with small Rust stacks (main currently + // has a large stack) + thread::spawn(move || { + let result = count(12); + println!("result = {}", result); + assert_eq!(result, 2048); + }) + .join(); +} diff --git a/tests/ui/abi/extern/extern-crosscrate.rs b/tests/ui/abi/extern/extern-crosscrate.rs new file mode 100644 index 000000000..123ce20ca --- /dev/null +++ b/tests/ui/abi/extern/extern-crosscrate.rs @@ -0,0 +1,21 @@ +// run-pass +// aux-build:extern-crosscrate-source.rs +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate externcallback; +extern crate libc; + +fn fact(n: libc::uintptr_t) -> libc::uintptr_t { + unsafe { + println!("n = {}", n); + externcallback::rustrt::rust_dbg_call(externcallback::cb, n) + } +} + +pub fn main() { + let result = fact(10); + println!("result = {}", result); + assert_eq!(result, 3628800); +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU16s.rs b/tests/ui/abi/extern/extern-pass-TwoU16s.rs new file mode 100644 index 000000000..cff25511c --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU16s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU16s { + one: u16, + two: u16, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; +} + +pub fn main() { + unsafe { + let x = TwoU16s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU16s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU32s.rs b/tests/ui/abi/extern/extern-pass-TwoU32s.rs new file mode 100644 index 000000000..03a8ecf24 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU32s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU32s { + one: u32, + two: u32, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s; +} + +pub fn main() { + unsafe { + let x = TwoU32s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU32s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU64s.rs b/tests/ui/abi/extern/extern-pass-TwoU64s.rs new file mode 100644 index 000000000..8bbc987c8 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU64s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU64s { + one: u64, + two: u64, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s; +} + +pub fn main() { + unsafe { + let x = TwoU64s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU64s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-TwoU8s.rs b/tests/ui/abi/extern/extern-pass-TwoU8s.rs new file mode 100644 index 000000000..55a53c250 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-TwoU8s.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc for ffi testing + +// Test a foreign function that accepts and returns a struct +// by value. + +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct TwoU8s { + one: u8, + two: u8, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; +} + +pub fn main() { + unsafe { + let x = TwoU8s { one: 22, two: 23 }; + let y = rust_dbg_extern_identity_TwoU8s(x); + assert_eq!(x, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-char.rs b/tests/ui/abi/extern/extern-pass-char.rs new file mode 100644 index 000000000..2b10d26d1 --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-char.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +// Test a function that takes/returns a u8. + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u8(v: u8) -> u8; +} + +pub fn main() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u8(22)); + } +} diff --git a/tests/ui/abi/extern/extern-pass-double.rs b/tests/ui/abi/extern/extern-pass-double.rs new file mode 100644 index 000000000..0b556c99e --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-double.rs @@ -0,0 +1,13 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_double(v: f64) -> f64; +} + +pub fn main() { + unsafe { + assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64)); + } +} diff --git a/tests/ui/abi/extern/extern-pass-empty.rs b/tests/ui/abi/extern/extern-pass-empty.rs new file mode 100644 index 000000000..ee974f6db --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-empty.rs @@ -0,0 +1,55 @@ +// run-pass +#![allow(improper_ctypes)] // FIXME: this test is inherently not FFI-safe. + +// Test a foreign function that accepts empty struct. + +// pretty-expanded FIXME #23616 +// ignore-msvc +// ignore-emscripten emcc asserts on an empty struct as an argument + +#[repr(C)] +struct TwoU8s { + one: u8, + two: u8, +} + +#[repr(C)] +struct ManyInts { + arg1: i8, + arg2: i16, + arg3: i32, + arg4: i16, + arg5: i8, + arg6: TwoU8s, +} + +#[repr(C)] +struct Empty; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts); +} + +pub fn main() { + unsafe { + let x = ManyInts { + arg1: 2, + arg2: 3, + arg3: 4, + arg4: 5, + arg5: 6, + arg6: TwoU8s { one: 7, two: 8 }, + }; + let y = ManyInts { + arg1: 1, + arg2: 2, + arg3: 3, + arg4: 4, + arg5: 5, + arg6: TwoU8s { one: 6, two: 7 }, + }; + let empty = Empty; + rust_dbg_extern_empty_struct(x, empty, y); + } +} diff --git a/tests/ui/abi/extern/extern-pass-u32.rs b/tests/ui/abi/extern/extern-pass-u32.rs new file mode 100644 index 000000000..c9b8d52cf --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-u32.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +// Test a function that takes/returns a u32. + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; +} + +pub fn main() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u32(22)); + } +} diff --git a/tests/ui/abi/extern/extern-pass-u64.rs b/tests/ui/abi/extern/extern-pass-u64.rs new file mode 100644 index 000000000..5103129ab --- /dev/null +++ b/tests/ui/abi/extern/extern-pass-u64.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-wasm32-bare no libc for ffi testing + +// Test a call to a function that takes/returns a u64. + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; +} + +pub fn main() { + unsafe { + assert_eq!(22, rust_dbg_extern_identity_u64(22)); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU16s.rs b/tests/ui/abi/extern/extern-return-TwoU16s.rs new file mode 100644 index 000000000..2551c93a7 --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU16s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU16s { + one: u16, + two: u16, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU16s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU32s.rs b/tests/ui/abi/extern/extern-return-TwoU32s.rs new file mode 100644 index 000000000..70a42895d --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU32s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU32s { + one: u32, + two: u32, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU32s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU64s.rs b/tests/ui/abi/extern/extern-return-TwoU64s.rs new file mode 100644 index 000000000..dd264fb9c --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU64s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU64s { + one: u64, + two: u64, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU64s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/extern/extern-return-TwoU8s.rs b/tests/ui/abi/extern/extern-return-TwoU8s.rs new file mode 100644 index 000000000..b60387aed --- /dev/null +++ b/tests/ui/abi/extern/extern-return-TwoU8s.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +pub struct TwoU8s { + one: u8, + two: u8, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s; +} + +pub fn main() { + unsafe { + let y = rust_dbg_extern_return_TwoU8s(); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); + } +} diff --git a/tests/ui/abi/foreign/auxiliary/foreign_lib.rs b/tests/ui/abi/foreign/auxiliary/foreign_lib.rs new file mode 100644 index 000000000..3c649b778 --- /dev/null +++ b/tests/ui/abi/foreign/auxiliary/foreign_lib.rs @@ -0,0 +1,37 @@ +#![crate_name = "foreign_lib"] +#![feature(rustc_private)] + +pub mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_get_test_int() -> libc::intptr_t; + } +} + +pub mod rustrt2 { + extern crate libc; + + extern "C" { + pub fn rust_get_test_int() -> libc::intptr_t; + } +} + +pub mod rustrt3 { + // Different type, but same ABI (on all supported platforms). + // Ensures that we don't ICE or trigger LLVM asserts when + // importing the same symbol under different types. + // See https://github.com/rust-lang/rust/issues/32740. + extern "C" { + pub fn rust_get_test_int() -> *const u8; + } +} + +pub fn local_uses() { + unsafe { + let x = rustrt::rust_get_test_int(); + assert_eq!(x, rustrt2::rust_get_test_int()); + assert_eq!(x as *const _, rustrt3::rust_get_test_int()); + } +} diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs new file mode 100644 index 000000000..d5b90a359 --- /dev/null +++ b/tests/ui/abi/foreign/foreign-call-no-runtime.rs @@ -0,0 +1,60 @@ +// run-pass +// ignore-emscripten no threads support + +#![feature(rustc_private)] + +extern crate libc; + +use std::mem; +use std::thread; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_dbg_call(cb: extern "C" fn(libc::uintptr_t), data: libc::uintptr_t) -> libc::uintptr_t; +} + +pub fn main() { + unsafe { + thread::spawn(move || { + let i: isize = 100; + rust_dbg_call(callback_isize, mem::transmute(&i)); + }) + .join() + .unwrap(); + + thread::spawn(move || { + let i: i32 = 100; + rust_dbg_call(callback_i32, mem::transmute(&i)); + }) + .join() + .unwrap(); + + thread::spawn(move || { + let i: i64 = 100; + rust_dbg_call(callback_i64, mem::transmute(&i)); + }) + .join() + .unwrap(); + } +} + +extern "C" fn callback_isize(data: libc::uintptr_t) { + unsafe { + let data: *const isize = mem::transmute(data); + assert_eq!(*data, 100); + } +} + +extern "C" fn callback_i64(data: libc::uintptr_t) { + unsafe { + let data: *const i64 = mem::transmute(data); + assert_eq!(*data, 100); + } +} + +extern "C" fn callback_i32(data: libc::uintptr_t) { + unsafe { + let data: *const i32 = mem::transmute(data); + assert_eq!(*data, 100); + } +} diff --git a/tests/ui/abi/foreign/foreign-dupe.rs b/tests/ui/abi/foreign/foreign-dupe.rs new file mode 100644 index 000000000..3c9f0f583 --- /dev/null +++ b/tests/ui/abi/foreign/foreign-dupe.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:foreign_lib.rs +// ignore-wasm32-bare no libc to test ffi with + +// Check that we can still call duplicated extern (imported) functions +// which were declared in another crate. See issues #32740 and #32783. + + +extern crate foreign_lib; + +pub fn main() { + unsafe { + let x = foreign_lib::rustrt::rust_get_test_int(); + assert_eq!(x, foreign_lib::rustrt2::rust_get_test_int()); + assert_eq!(x as *const _, foreign_lib::rustrt3::rust_get_test_int()); + } +} diff --git a/tests/ui/abi/foreign/foreign-fn-with-byval.rs b/tests/ui/abi/foreign/foreign-fn-with-byval.rs new file mode 100644 index 000000000..f366b6ee1 --- /dev/null +++ b/tests/ui/abi/foreign/foreign-fn-with-byval.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +#[derive(Copy, Clone)] +pub struct S { + x: u64, + y: u64, + z: u64, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn get_x(x: S) -> u64; + pub fn get_y(x: S) -> u64; + pub fn get_z(x: S) -> u64; +} + +#[inline(never)] +fn indirect_call(func: unsafe extern "C" fn(s: S) -> u64, s: S) -> u64 { + unsafe { func(s) } +} + +fn main() { + let s = S { x: 1, y: 2, z: 3 }; + assert_eq!(s.x, indirect_call(get_x, s)); + assert_eq!(s.y, indirect_call(get_y, s)); + assert_eq!(s.z, indirect_call(get_z, s)); +} diff --git a/tests/ui/abi/foreign/foreign-no-abi.rs b/tests/ui/abi/foreign/foreign-no-abi.rs new file mode 100644 index 000000000..3f4f70c99 --- /dev/null +++ b/tests/ui/abi/foreign/foreign-no-abi.rs @@ -0,0 +1,22 @@ +// run-pass +// ABI is cdecl by default + +// ignore-wasm32-bare no libc to test ffi with +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + +mod rustrt { + extern crate libc; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_get_test_int() -> libc::intptr_t; + } +} + +pub fn main() { + unsafe { + rustrt::rust_get_test_int(); + } +} diff --git a/tests/ui/abi/foreign/invoke-external-foreign.rs b/tests/ui/abi/foreign/invoke-external-foreign.rs new file mode 100644 index 000000000..dbd2b4ad8 --- /dev/null +++ b/tests/ui/abi/foreign/invoke-external-foreign.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:foreign_lib.rs +// ignore-wasm32-bare no libc to test ffi with + +// The purpose of this test is to check that we can +// successfully (and safely) invoke external, cdecl +// functions from outside the crate. + +// pretty-expanded FIXME #23616 + +extern crate foreign_lib; + +pub fn main() { + unsafe { + let _foo = foreign_lib::rustrt::rust_get_test_int(); + } +} diff --git a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs new file mode 100644 index 000000000..4600bd090 --- /dev/null +++ b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -0,0 +1,192 @@ +// This test check that even if we mixup target feature of function with homogenous floats, +// the abi is sound and still produce the right answer. +// +// This is basically the same test as tests/ui/simd/target-feature-mixup.rs but for floats and +// without #[repr(simd)] + +// run-pass +// ignore-emscripten +// ignore-sgx no processes + +#![feature(avx512_target_feature)] + +#![allow(overflowing_literals)] +#![allow(unused_variables)] + +use std::process::{Command, ExitStatus}; +use std::env; + +fn main() { + if let Some(level) = env::args().nth(1) { + return test::main(&level) + } + + match std::env::var("TARGET") { + Ok(s) => { + // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled + if s.contains("i586") { + return + } + } + Err(_) => return, + } + + let me = env::current_exe().unwrap(); + for level in ["sse", "avx", "avx512"].iter() { + let status = Command::new(&me).arg(level).status().unwrap(); + if status.success() { + println!("success with {}", level); + continue + } + + // We don't actually know if our computer has the requisite target features + // for the test below. Testing for that will get added to libstd later so + // for now just assume sigill means this is a machine that can't run this test. + if is_sigill(status) { + println!("sigill with {}, assuming spurious", level); + continue + } + panic!("invalid status at {}: {}", level, status); + } +} + +#[cfg(unix)] +fn is_sigill(status: ExitStatus) -> bool { + use std::os::unix::prelude::*; + status.signal() == Some(4) +} + +#[cfg(windows)] +fn is_sigill(status: ExitStatus) -> bool { + status.code() == Some(0xc000001d) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[allow(nonstandard_style)] +mod test { + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x2(f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x4(f32, f32, f32, f32); + + #[derive(PartialEq, Debug, Clone, Copy)] + struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + + pub fn main(level: &str) { + unsafe { + main_normal(level); + main_sse(level); + if level == "sse" { + return + } + main_avx(level); + if level == "avx" { + return + } + main_avx512(level); + } + } + + macro_rules! mains { + ($( + $(#[$attr:meta])* + unsafe fn $main:ident(level: &str) { + ... + } + )*) => ($( + $(#[$attr])* + unsafe fn $main(level: &str) { + let m128 = f32x2(1., 2.); + let m256 = f32x4(3., 4., 5., 6.); + let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.); + assert_eq!(id_sse_128(m128), m128); + assert_eq!(id_sse_256(m256), m256); + assert_eq!(id_sse_512(m512), m512); + + if level == "sse" { + return + } + assert_eq!(id_avx_128(m128), m128); + assert_eq!(id_avx_256(m256), m256); + assert_eq!(id_avx_512(m512), m512); + + if level == "avx" { + return + } + assert_eq!(id_avx512_128(m128), m128); + assert_eq!(id_avx512_256(m256), m256); + assert_eq!(id_avx512_512(m512), m512); + } + )*) + } + + mains! { + unsafe fn main_normal(level: &str) { ... } + #[target_feature(enable = "sse2")] + unsafe fn main_sse(level: &str) { ... } + #[target_feature(enable = "avx")] + unsafe fn main_avx(level: &str) { ... } + #[target_feature(enable = "avx512bw")] + unsafe fn main_avx512(level: &str) { ... } + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_128(a: f32x2) -> f32x2 { + assert_eq!(a, f32x2(1., 2.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_256(a: f32x4) -> f32x4 { + assert_eq!(a, f32x4(3., 4., 5., 6.)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_512(a: f32x8) -> f32x8 { + assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + a.clone() + } +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +mod test { + pub fn main(level: &str) {} +} diff --git a/tests/ui/abi/issue-28676.rs b/tests/ui/abi/issue-28676.rs new file mode 100644 index 000000000..347a84029 --- /dev/null +++ b/tests/ui/abi/issue-28676.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code)] +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +#[derive(Copy, Clone)] +pub struct Quad { + a: u64, + b: u64, + c: u64, + d: u64, +} + +mod rustrt { + use super::Quad; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn get_c_many_params( + _: *const (), + _: *const (), + _: *const (), + _: *const (), + f: Quad, + ) -> u64; + } +} + +fn test() { + unsafe { + let null = std::ptr::null(); + let q = Quad { a: 1, b: 2, c: 3, d: 4 }; + assert_eq!(rustrt::get_c_many_params(null, null, null, null, q), q.c); + } +} + +pub fn main() { + test(); +} diff --git a/tests/ui/abi/issues/issue-22565-rust-call.rs b/tests/ui/abi/issues/issue-22565-rust-call.rs new file mode 100644 index 000000000..a572666c8 --- /dev/null +++ b/tests/ui/abi/issues/issue-22565-rust-call.rs @@ -0,0 +1,31 @@ +#![feature(unboxed_closures)] + +extern "rust-call" fn b(_i: i32) {} +//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + +trait Tr { + extern "rust-call" fn a(); + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + + extern "rust-call" fn b() {} + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument +} + +struct Foo; + +impl Foo { + extern "rust-call" fn bar() {} + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument +} + +impl Tr for Foo { + extern "rust-call" fn a() {} + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument +} + +fn main() { + b(10); + Foo::bar(); + ::a(); + ::b(); +} diff --git a/tests/ui/abi/issues/issue-22565-rust-call.stderr b/tests/ui/abi/issues/issue-22565-rust-call.stderr new file mode 100644 index 000000000..9d205b444 --- /dev/null +++ b/tests/ui/abi/issues/issue-22565-rust-call.stderr @@ -0,0 +1,33 @@ +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:3:1 + | +LL | extern "rust-call" fn b(_i: i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32` + +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:17:5 + | +LL | extern "rust-call" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:22:5 + | +LL | extern "rust-call" fn a() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:7:5 + | +LL | extern "rust-call" fn a(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/issue-22565-rust-call.rs:10:5 + | +LL | extern "rust-call" fn b() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs new file mode 100644 index 000000000..29b240518 --- /dev/null +++ b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs @@ -0,0 +1,46 @@ +// run-pass +#![allow(dead_code)] +#![allow(improper_ctypes)] + +// ignore-wasm32-bare no libc to test ffi with + +#[derive(Copy, Clone)] +pub struct QuadFloats { + a: f32, + b: f32, + c: f32, + d: f32, +} + +mod rustrt { + use super::QuadFloats; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn get_c_exhaust_sysv64_ints( + _: *const (), + _: *const (), + _: *const (), + _: *const (), + _: *const (), + _: *const (), + _: *const (), + h: QuadFloats, + ) -> f32; + } +} + +fn test() { + unsafe { + let null = std::ptr::null(); + let q = QuadFloats { a: 10.2, b: 20.3, c: 30.4, d: 40.5 }; + assert_eq!( + rustrt::get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q), + q.c, + ); + } +} + +pub fn main() { + test(); +} diff --git a/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs b/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs new file mode 100644 index 000000000..fba880d4f --- /dev/null +++ b/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs @@ -0,0 +1,39 @@ +// run-pass +// ignore-wasm +#![allow(dead_code)] +#![allow(improper_ctypes)] + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn issue_97463_leak_uninit_data(a: u32, b: u32, c: u32) -> u16; +} + +fn main() { + const C1: usize = 0x327b23c6; + const C2: usize = C1 & 0xFFFF; + + let r1: usize = 0x0; + let r2: usize = C1; + let r3: usize = 0x0; + let value: u16 = unsafe { issue_97463_leak_uninit_data(r1 as u32, r2 as u32, r3 as u32) }; + + // NOTE: as an example of the sensitivity of this test to optimization choices, + // uncommenting this block of code makes the bug go away on pnkfelix's machine. + // (But observing via `dbg!` doesn't hide the bug. At least sometimes.) + /* + println!("{}", value); + println!("{}", value as usize); + println!("{}", usize::from(value)); + println!("{}", (value as usize) & 0xFFFF); + */ + + let d1 = value; + let d2 = value as usize; + let d3 = usize::from(value); + let d4 = (value as usize) & 0xFFFF; + + let d = (&d1, &d2, &d3, &d4); + let d_ = (d1, d2, d3, d4); + + assert_eq!(((&(C2 as u16), &C2, &C2, &C2), (C2 as u16, C2, C2, C2)), (d, d_)); +} diff --git a/tests/ui/abi/lib-defaults.rs b/tests/ui/abi/lib-defaults.rs new file mode 100644 index 000000000..cd0b0bb23 --- /dev/null +++ b/tests/ui/abi/lib-defaults.rs @@ -0,0 +1,17 @@ +// run-pass +// dont-check-compiler-stderr (rust-lang/rust#54222) + +// ignore-wasm32-bare no libc to test ffi with + +// compile-flags: -lrust_test_helpers + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u32(x: u32) -> u32; +} + +fn main() { + unsafe { + rust_dbg_extern_identity_u32(42); + } +} diff --git a/tests/ui/abi/mir/mir_codegen_calls_variadic.rs b/tests/ui/abi/mir/mir_codegen_calls_variadic.rs new file mode 100644 index 000000000..b3392b9c6 --- /dev/null +++ b/tests/ui/abi/mir/mir_codegen_calls_variadic.rs @@ -0,0 +1,19 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_interesting_average(_: i64, ...) -> f64; +} + +fn test(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 { + unsafe { + rust_interesting_average( + 6, a, a as f64, b, b as f64, c, c as f64, d, d as f64, e, e as f64, f, g, + ) as i64 + } +} + +fn main() { + assert_eq!(test(10, 20, 30, 40, 50, 60_i64, 60.0_f64), 70); +} diff --git a/tests/ui/abi/nullable-pointer-ffi-compat.rs b/tests/ui/abi/nullable-pointer-ffi-compat.rs new file mode 100644 index 000000000..0647a18c3 --- /dev/null +++ b/tests/ui/abi/nullable-pointer-ffi-compat.rs @@ -0,0 +1,28 @@ +// run-pass +// #11303, #11040: +// This would previously crash on i686 Linux due to abi differences +// between returning an Option and T, where T is a non nullable +// pointer. +// If we have an enum with two variants such that one is zero sized +// and the other contains a nonnullable pointer, we don't use a +// separate discriminant. Instead we use that pointer field to differentiate +// between the 2 cases. +// Also, if the variant with the nonnullable pointer has no other fields +// then we simply express the enum as just a pointer and not wrap it +// in a struct. + + +use std::mem; + +#[inline(never)] +extern "C" fn foo(x: &isize) -> Option<&isize> { Some(x) } + +static FOO: isize = 0xDEADBEE; + +pub fn main() { + unsafe { + let f: extern "C" fn(&isize) -> &isize = + mem::transmute(foo as extern "C" fn(&isize) -> Option<&isize>); + assert_eq!(*f(&FOO), FOO); + } +} diff --git a/tests/ui/abi/numbers-arithmetic/i128-ffi.rs b/tests/ui/abi/numbers-arithmetic/i128-ffi.rs new file mode 100644 index 000000000..19edf9779 --- /dev/null +++ b/tests/ui/abi/numbers-arithmetic/i128-ffi.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(improper_ctypes)] + +// MSVC doesn't support 128 bit integers, and other Windows +// C compilers have very inconsistent views on how the ABI +// should look like. + +// ignore-windows +// ignore-32bit + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn identity(f: u128) -> u128; + fn square(f: i128) -> i128; + fn sub(f: i128, f: i128) -> i128; +} + +fn main() { + unsafe { + let a = 0x734C_C2F2_A521; + let b = 0x33EE_0E2A_54E2_59DA_A0E7_8E41; + let b_out = identity(b); + assert_eq!(b, b_out); + let a_square = square(a); + assert_eq!(b, a_square as u128); + let k = 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210; + let k_d = 0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420; + let k_out = sub(k_d, k); + assert_eq!(k, k_out); + } +} diff --git a/tests/ui/abi/rustcall-generic.rs b/tests/ui/abi/rustcall-generic.rs new file mode 100644 index 000000000..6eaccc436 --- /dev/null +++ b/tests/ui/abi/rustcall-generic.rs @@ -0,0 +1,12 @@ +// revisions: normal opt +// check-pass +//[opt] compile-flags: -Zmir-opt-level=3 + +#![feature(unboxed_closures, tuple_trait)] + +extern "rust-call" fn foo(_: T) {} + +fn main() { + foo(()); + foo((1, 2)); +} diff --git a/tests/ui/abi/segfault-no-out-of-stack.rs b/tests/ui/abi/segfault-no-out-of-stack.rs new file mode 100644 index 000000000..ab2b30894 --- /dev/null +++ b/tests/ui/abi/segfault-no-out-of-stack.rs @@ -0,0 +1,48 @@ +// run-pass + +#![allow(unused_imports)] +// ignore-emscripten can't run commands +// ignore-sgx no processes +// ignore-fuchsia must translate zircon signal to SIGSEGV/SIGBUS, FIXME (#58590) +#![feature(rustc_private)] + +extern crate libc; + +use std::env; +use std::process::{Command, ExitStatus}; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_get_null_ptr() -> *mut ::libc::c_char; +} + +#[cfg(unix)] +fn check_status(status: std::process::ExitStatus) { + use libc; + use std::os::unix::process::ExitStatusExt; + + assert!(status.signal() == Some(libc::SIGSEGV) || status.signal() == Some(libc::SIGBUS)); +} + +#[cfg(not(unix))] +fn check_status(status: std::process::ExitStatus) { + assert!(!status.success()); +} + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "segfault" { + unsafe { + *rust_get_null_ptr() = 1; + }; // trigger a segfault + } else { + let segfault = Command::new(&args[0]).arg("segfault").output().unwrap(); + let stderr = String::from_utf8_lossy(&segfault.stderr); + let stdout = String::from_utf8_lossy(&segfault.stdout); + println!("stdout: {}", stdout); + println!("stderr: {}", stderr); + println!("status: {}", segfault.status); + check_status(segfault.status); + assert!(!stderr.contains("has overflowed its stack")); + } +} diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs new file mode 100644 index 000000000..6d934538f --- /dev/null +++ b/tests/ui/abi/stack-probes-lto.rs @@ -0,0 +1,17 @@ +// run-pass +// ignore-arm +// ignore-aarch64 +// ignore-mips +// ignore-mips64 +// ignore-sparc +// ignore-sparc64 +// ignore-wasm +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-musl FIXME #31506 +// ignore-pretty +// ignore-fuchsia no exception handler registered for segfault +// compile-flags: -C lto +// no-prefer-dynamic + +include!("stack-probes.rs"); diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs new file mode 100644 index 000000000..e7b91644b --- /dev/null +++ b/tests/ui/abi/stack-probes.rs @@ -0,0 +1,85 @@ +// run-pass +// ignore-arm +// ignore-aarch64 +// ignore-mips +// ignore-mips64 +// ignore-sparc +// ignore-sparc64 +// ignore-wasm +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia no exception handler registered for segfault + +use std::env; +use std::mem::MaybeUninit; +use std::process::Command; +use std::thread; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[link_name = "rust_dbg_extern_identity_u64"] + fn black_box(u: u64); +} + +fn main() { + let args = env::args().skip(1).collect::>(); + if args.len() > 0 { + match &args[0][..] { + "main-recurse" => overflow_recurse(), + "child-recurse" => thread::spawn(overflow_recurse).join().unwrap(), + "child-frame" => overflow_frame(), + _ => panic!(), + } + return; + } + + let me = env::current_exe().unwrap(); + + // The linux kernel has some different behavior for the main thread because + // the main thread's stack can typically grow. We can't always guarantee + // that we report stack overflow on the main thread, see #43052 for some + // details + if cfg!(not(target_os = "linux")) { + assert_overflow(Command::new(&me).arg("main-recurse")); + } + assert_overflow(Command::new(&me).arg("child-recurse")); + assert_overflow(Command::new(&me).arg("child-frame")); +} + +#[allow(unconditional_recursion)] +fn recurse(array: &MaybeUninit<[u64; 1024]>) { + unsafe { + black_box(array.as_ptr() as u64); + } + let local: MaybeUninit<[u64; 1024]> = MaybeUninit::uninit(); + recurse(&local); +} + +#[inline(never)] +fn overflow_recurse() { + recurse(&MaybeUninit::uninit()); +} + +fn overflow_frame() { + // By using a 1MiB stack frame with only 512KiB stack, we'll jump over any + // guard page, even with 64K pages -- but stack probes should catch it. + const STACK_SIZE: usize = 512 * 1024; + thread::Builder::new().stack_size(STACK_SIZE).spawn(|| { + let local: MaybeUninit<[u8; 2 * STACK_SIZE]> = MaybeUninit::uninit(); + unsafe { + black_box(local.as_ptr() as u64); + } + }).unwrap().join().unwrap(); +} + +fn assert_overflow(cmd: &mut Command) { + let output = cmd.output().unwrap(); + assert!(!output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + println!("status: {}", output.status); + println!("stdout: {}", stdout); + println!("stderr: {}", stderr); + assert!(stdout.is_empty()); + assert!(stderr.contains("has overflowed its stack\n")); +} diff --git a/tests/ui/abi/stack-protector.rs b/tests/ui/abi/stack-protector.rs new file mode 100644 index 000000000..24bd2e219 --- /dev/null +++ b/tests/ui/abi/stack-protector.rs @@ -0,0 +1,99 @@ +// run-pass +// only-x86_64-unknown-linux-gnu +// revisions: ssp no-ssp +// [ssp] compile-flags: -Z stack-protector=all +// compile-flags: -C opt-level=2 +// compile-flags: -g + +use std::env; +use std::process::{Command, ExitStatus}; + +fn main() { + if env::args().len() == 1 { + // The test is initially run without arguments. Start the process again, + // this time *with* an argument; in this configuration, the test program + // will deliberately smash the stack. + let cur_argv0 = env::current_exe().unwrap(); + let mut child = Command::new(&cur_argv0); + child.arg("stacksmash"); + + if cfg!(ssp) { + assert_stack_smash_prevented(&mut child); + } else { + assert_stack_smashed(&mut child); + } + } else { + vulnerable_function(); + // If we return here the test is broken: it should either have called + // malicious_code() which terminates the process, or be caught by the + // stack check which also terminates the process. + panic!("TEST BUG: stack smash unsuccessful"); + } +} + +// Avoid inlining to make sure the return address is pushed to stack. +#[inline(never)] +fn vulnerable_function() { + let mut x = 5usize; + let stackaddr = &mut x as *mut usize; + let bad_code_ptr = malicious_code as usize; + // Overwrite the on-stack return address with the address of `malicious_code()`, + // thereby jumping to that function when returning from `vulnerable_function()`. + unsafe { fill(stackaddr, bad_code_ptr, 20); } +} + +// Use an uninlined function with its own stack frame to make sure that we don't +// clobber e.g. the counter or address local variable. +#[inline(never)] +unsafe fn fill(addr: *mut usize, val: usize, count: usize) { + let mut addr = addr; + for _ in 0..count { + *addr = val; + addr = addr.add(1); + } +} + +// We jump to malicious_code() having wreaked havoc with the previous stack +// frame and not setting up a new one. This function is therefore constrained, +// e.g. both println!() and std::process::exit() segfaults if called. We +// therefore keep the amount of work to a minimum by calling POSIX functions +// directly. +// The function is un-inlined just to make it possible to set a breakpoint here. +#[inline(never)] +fn malicious_code() { + let msg = [112u8, 119u8, 110u8, 101u8, 100u8, 33u8, 0u8]; // "pwned!\0" ascii + unsafe { + write(1, &msg as *const u8, msg.len()); + _exit(0); + } +} +extern "C" { + fn write(fd: i32, buf: *const u8, count: usize) -> isize; + fn _exit(status: i32) -> !; +} + + +fn assert_stack_smash_prevented(cmd: &mut Command) { + let (status, stdout, stderr) = run(cmd); + assert!(!status.success()); + assert!(stdout.is_empty()); + assert!(stderr.contains("stack smashing detected")); +} + +fn assert_stack_smashed(cmd: &mut Command) { + let (status, stdout, stderr) = run(cmd); + assert!(status.success()); + assert!(stdout.contains("pwned!")); + assert!(stderr.is_empty()); +} + + +fn run(cmd: &mut Command) -> (ExitStatus, String, String) { + let output = cmd.output().unwrap(); + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + println!("status: {}", output.status); + println!("stdout: {}", stdout); + println!("stderr: {}", stderr); + (output.status, stdout.to_string(), stderr.to_string()) +} diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs new file mode 100644 index 000000000..ecd8ee94a --- /dev/null +++ b/tests/ui/abi/statics/static-mut-foreign.rs @@ -0,0 +1,41 @@ +// run-pass +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate libc; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + static mut rust_dbg_static_mut: libc::c_int; + pub fn rust_dbg_static_mut_check_four(); +} + +unsafe fn static_bound(_: &'static libc::c_int) {} + +fn static_bound_set(a: &'static mut libc::c_int) { + *a = 3; +} + +unsafe fn run() { + assert_eq!(rust_dbg_static_mut, 3); + rust_dbg_static_mut = 4; + assert_eq!(rust_dbg_static_mut, 4); + rust_dbg_static_mut_check_four(); + rust_dbg_static_mut += 1; + assert_eq!(rust_dbg_static_mut, 5); + rust_dbg_static_mut *= 3; + assert_eq!(rust_dbg_static_mut, 15); + rust_dbg_static_mut = -3; + assert_eq!(rust_dbg_static_mut, -3); + static_bound(&rust_dbg_static_mut); + static_bound_set(&mut rust_dbg_static_mut); +} + +pub fn main() { + unsafe { run() } +} diff --git a/tests/ui/abi/struct-enums/struct-return.rs b/tests/ui/abi/struct-enums/struct-return.rs new file mode 100644 index 000000000..1a7984ea5 --- /dev/null +++ b/tests/ui/abi/struct-enums/struct-return.rs @@ -0,0 +1,122 @@ +// run-pass +#![allow(dead_code)] +// ignore-wasm32-bare no libc to test ffi with + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Quad { + a: u64, + b: u64, + c: u64, + d: u64, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Floats { + a: f64, + b: u8, + c: f64, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CharCharDouble { + a: u8, + b: u8, + c: f64, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CharCharFloat { + a: u8, + b: u8, + c: f32, +} + +mod rustrt { + use super::{CharCharDouble, CharCharFloat, Floats, Quad}; + + #[link(name = "rust_test_helpers", kind = "static")] + extern "C" { + pub fn rust_dbg_abi_1(q: Quad) -> Quad; + pub fn rust_dbg_abi_2(f: Floats) -> Floats; + pub fn rust_dbg_abi_3(a: CharCharDouble) -> CharCharDouble; + pub fn rust_dbg_abi_4(a: CharCharFloat) -> CharCharFloat; + } +} + +fn test1() { + unsafe { + let q = Quad { + a: 0xaaaa_aaaa_aaaa_aaaa, + b: 0xbbbb_bbbb_bbbb_bbbb, + c: 0xcccc_cccc_cccc_cccc, + d: 0xdddd_dddd_dddd_dddd, + }; + let qq = rustrt::rust_dbg_abi_1(q); + println!("a: {:x}", qq.a as usize); + println!("b: {:x}", qq.b as usize); + println!("c: {:x}", qq.c as usize); + println!("d: {:x}", qq.d as usize); + assert_eq!(qq.a, q.c + 1); + assert_eq!(qq.b, q.d - 1); + assert_eq!(qq.c, q.a + 1); + assert_eq!(qq.d, q.b - 1); + } +} + +#[cfg(target_pointer_width = "64")] +fn test2() { + unsafe { + let f = Floats { a: 1.234567890e-15_f64, b: 0b_1010_1010, c: 1.0987654321e-15_f64 }; + let ff = rustrt::rust_dbg_abi_2(f); + println!("a: {}", ff.a as f64); + println!("b: {}", ff.b as usize); + println!("c: {}", ff.c as f64); + assert_eq!(ff.a, f.c + 1.0f64); + assert_eq!(ff.b, 0xff); + assert_eq!(ff.c, f.a - 1.0f64); + } +} + +#[cfg(target_pointer_width = "32")] +fn test2() {} + +#[cfg(target_pointer_width = "64")] +fn test3() { + unsafe { + let a = CharCharDouble { a: 1, b: 2, c: 3. }; + let b = rustrt::rust_dbg_abi_3(a); + println!("a: {}", b.a); + println!("b: {}", b.b); + println!("c: {}", b.c); + assert_eq!(b.a, a.a + 1); + assert_eq!(b.b, a.b - 1); + assert_eq!(b.c, a.c + 1.0); + } +} + +#[cfg(target_pointer_width = "32")] +fn test3() {} + +fn test4() { + unsafe { + let a = CharCharFloat { a: 1, b: 2, c: 3. }; + let b = rustrt::rust_dbg_abi_4(a); + println!("a: {}", b.a); + println!("b: {}", b.b); + println!("c: {}", b.c); + assert_eq!(b.a, a.a + 1); + assert_eq!(b.b, a.b - 1); + assert_eq!(b.c, a.c + 1.0); + } +} + +pub fn main() { + test1(); + test2(); + test3(); + test4(); +} diff --git a/tests/ui/abi/union/union-c-interop.rs b/tests/ui/abi/union/union-c-interop.rs new file mode 100644 index 000000000..00f04d5b7 --- /dev/null +++ b/tests/ui/abi/union/union-c-interop.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(non_snake_case)] + +// ignore-wasm32-bare no libc to test ffi with + +#[derive(Clone, Copy)] +#[repr(C)] +struct LARGE_INTEGER_U { + LowPart: u32, + HighPart: u32, +} + +#[derive(Clone, Copy)] +#[repr(C)] +union LARGE_INTEGER { + __unnamed__: LARGE_INTEGER_U, + u: LARGE_INTEGER_U, + QuadPart: u64, +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn increment_all_parts(_: LARGE_INTEGER) -> LARGE_INTEGER; +} + +fn main() { + unsafe { + let mut li = LARGE_INTEGER { QuadPart: 0 }; + let li_c = increment_all_parts(li); + li.__unnamed__.LowPart += 1; + li.__unnamed__.HighPart += 1; + li.u.LowPart += 1; + li.u.HighPart += 1; + li.QuadPart += 1; + assert_eq!(li.QuadPart, li_c.QuadPart); + } +} diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr new file mode 100644 index 000000000..e86a73ea6 --- /dev/null +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -0,0 +1,61 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:30:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:40:1 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:43:1 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:47:1 + | +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +error: aborting due to 8 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr new file mode 100644 index 000000000..f7569c8cd --- /dev/null +++ b/tests/ui/abi/unsupported.arm.stderr @@ -0,0 +1,55 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:30:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:40:1 + | +LL | extern "x86-interrupt" fn x86() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:43:1 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:47:1 + | +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr new file mode 100644 index 000000000..7ca93516d --- /dev/null +++ b/tests/ui/abi/unsupported.i686.stderr @@ -0,0 +1,39 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:30:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs new file mode 100644 index 000000000..6427a5695 --- /dev/null +++ b/tests/ui/abi/unsupported.rs @@ -0,0 +1,53 @@ +// revisions: x64 i686 aarch64 arm +// +// [x64] needs-llvm-components: x86 +// [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +// [i686] needs-llvm-components: x86 +// [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib +// [aarch64] needs-llvm-components: aarch64 +// [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib +// [arm] needs-llvm-components: arm +// [arm] compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib +#![no_core] +#![feature( + no_core, + lang_items, + abi_ptx, + abi_msp430_interrupt, + abi_avr_interrupt, + abi_thiscall, + abi_amdgpu_kernel, + wasm_abi, + abi_x86_interrupt +)] +#[lang="sized"] +trait Sized { } + +extern "ptx-kernel" fn ptx() {} +//~^ ERROR is not a supported ABI +extern "amdgpu-kernel" fn amdgpu() {} +//~^ ERROR is not a supported ABI +extern "wasm" fn wasm() {} +//~^ ERROR is not a supported ABI +extern "aapcs" fn aapcs() {} +//[x64]~^ ERROR is not a supported ABI +//[i686]~^^ ERROR is not a supported ABI +//[aarch64]~^^^ ERROR is not a supported ABI +extern "msp430-interrupt" fn msp430() {} +//~^ ERROR is not a supported ABI +extern "avr-interrupt" fn avr() {} +//~^ ERROR is not a supported ABI +extern "x86-interrupt" fn x86() {} +//[aarch64]~^ ERROR is not a supported ABI +//[arm]~^^ ERROR is not a supported ABI +extern "thiscall" fn thiscall() {} +//[x64]~^ ERROR is not a supported ABI +//[aarch64]~^^ ERROR is not a supported ABI +//[arm]~^^^ ERROR is not a supported ABI +extern "stdcall" fn stdcall() {} +//[x64]~^ WARN use of calling convention not supported +//[x64]~^^ WARN this was previously accepted +//[aarch64]~^^^ WARN use of calling convention not supported +//[aarch64]~^^^^ WARN this was previously accepted +//[arm]~^^^^^ WARN use of calling convention not supported +//[arm]~^^^^^^ WARN this was previously accepted diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr new file mode 100644 index 000000000..26023a458 --- /dev/null +++ b/tests/ui/abi/unsupported.x64.stderr @@ -0,0 +1,55 @@ +error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:26:1 + | +LL | extern "ptx-kernel" fn ptx() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:28:1 + | +LL | extern "amdgpu-kernel" fn amdgpu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"wasm"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:30:1 + | +LL | extern "wasm" fn wasm() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"aapcs"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:32:1 + | +LL | extern "aapcs" fn aapcs() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:36:1 + | +LL | extern "msp430-interrupt" fn msp430() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:38:1 + | +LL | extern "avr-interrupt" fn avr() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"thiscall"` is not a supported ABI for the current target + --> $DIR/unsupported.rs:43:1 + | +LL | extern "thiscall" fn thiscall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of calling convention not supported on this target + --> $DIR/unsupported.rs:47:1 + | +LL | extern "stdcall" fn stdcall() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #87678 + = note: `#[warn(unsupported_calling_conventions)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/variadic-ffi.rs b/tests/ui/abi/variadic-ffi.rs new file mode 100644 index 000000000..a952ea077 --- /dev/null +++ b/tests/ui/abi/variadic-ffi.rs @@ -0,0 +1,84 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with +#![feature(c_variadic)] + +use std::ffi::VaList; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + fn rust_interesting_average(_: u64, ...) -> f64; + + // FIXME: we need to disable this lint for `VaList`, + // since it contains a `MaybeUninit` on the asmjs target, + // and this type isn't FFI-safe. This is OK for now, + // since the type is layout-compatible with `i32`. + #[cfg_attr(target_arch = "asmjs", allow(improper_ctypes))] + fn rust_valist_interesting_average(_: u64, _: VaList) -> f64; +} + +pub unsafe extern "C" fn test_valist_forward(n: u64, mut ap: ...) -> f64 { + rust_valist_interesting_average(n, ap.as_va_list()) +} + +pub unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) { + let mut ap2 = ap.clone(); + assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 30); + + // Advance one pair in the copy before checking + let mut ap2 = ap.clone(); + let _ = ap2.arg::(); + let _ = ap2.arg::(); + assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 50); + + // Advance one pair in the original + let _ = ap.arg::(); + let _ = ap.arg::(); + + let mut ap2 = ap.clone(); + assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 50); + + let mut ap2 = ap.clone(); + let _ = ap2.arg::(); + let _ = ap2.arg::(); + assert_eq!(rust_valist_interesting_average(2, ap2.as_va_list()) as i64, 70); +} + +pub fn main() { + // Call without variadic arguments + unsafe { + assert!(rust_interesting_average(0).is_nan()); + } + + // Call with direct arguments + unsafe { + assert_eq!(rust_interesting_average(1, 10i64, 10.0f64) as i64, 20); + } + + // Call with named arguments, variable number of them + let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64); + unsafe { + assert_eq!(rust_interesting_average(2, x1, x2, x3, x4) as i64, 30); + } + + // A function that takes a function pointer + unsafe fn call(fp: unsafe extern "C" fn(u64, ...) -> f64) { + let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64); + assert_eq!(fp(2, x1, x2, x3, x4) as i64, 30); + } + + unsafe { + call(rust_interesting_average); + + // Make a function pointer, pass indirectly + let x: unsafe extern "C" fn(u64, ...) -> f64 = rust_interesting_average; + call(x); + } + + unsafe { + assert_eq!(test_valist_forward(2, 10i64, 10f64, 20i64, 20f64) as i64, 30); + } + + unsafe { + test_va_copy(4, 10i64, 10f64, 20i64, 20f64, 30i64, 30f64, 40i64, 40f64); + } +} diff --git a/tests/ui/abi/x86stdcall.rs b/tests/ui/abi/x86stdcall.rs new file mode 100644 index 000000000..d1cf1319f --- /dev/null +++ b/tests/ui/abi/x86stdcall.rs @@ -0,0 +1,22 @@ +// run-pass +// only-windows +// GetLastError doesn't seem to work with stack switching + +#[cfg(windows)] +mod kernel32 { + extern "system" { + pub fn SetLastError(err: usize); + pub fn GetLastError() -> usize; + } +} + +#[cfg(windows)] +pub fn main() { + unsafe { + let expected = 1234; + kernel32::SetLastError(expected); + let actual = kernel32::GetLastError(); + println!("actual = {}", actual); + assert_eq!(expected, actual); + } +} diff --git a/tests/ui/abi/x86stdcall2.rs b/tests/ui/abi/x86stdcall2.rs new file mode 100644 index 000000000..4d508ecb2 --- /dev/null +++ b/tests/ui/abi/x86stdcall2.rs @@ -0,0 +1,27 @@ +// run-pass +// only-windows + +#![allow(non_camel_case_types)] +pub type HANDLE = usize; +pub type DWORD = u32; +pub type SIZE_T = u32; +pub type LPVOID = usize; +pub type BOOL = u8; + +mod kernel32 { + use super::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T}; + + extern "system" { + pub fn GetProcessHeap() -> HANDLE; + pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; + } +} + +pub fn main() { + let heap = unsafe { kernel32::GetProcessHeap() }; + let mem = unsafe { kernel32::HeapAlloc(heap, 0, 100) }; + assert!(mem != 0); + let res = unsafe { kernel32::HeapFree(heap, 0, mem) }; + assert!(res != 0); +} diff --git a/tests/ui/alias-uninit-value.rs b/tests/ui/alias-uninit-value.rs new file mode 100644 index 000000000..932c93245 --- /dev/null +++ b/tests/ui/alias-uninit-value.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + + + +// Regression test for issue #374 + +// pretty-expanded FIXME #23616 + +enum sty { ty_nil, } + +struct RawT {struct_: sty, cname: Option, hash: usize} + +fn mk_raw_ty(st: sty, cname: Option) -> RawT { + return RawT {struct_: st, cname: cname, hash: 0}; +} + +pub fn main() { mk_raw_ty(sty::ty_nil, None::); } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs new file mode 100644 index 000000000..cd06423e3 --- /dev/null +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs @@ -0,0 +1,18 @@ +// compile-flags:-C panic=abort + +#![feature(alloc_error_handler)] +#![no_std] +#![no_main] + +use core::alloc::Layout; + +#[alloc_error_handler] +fn oom( + info: &Layout, //~^ ERROR mismatched types +) -> () //~^^ ERROR mismatched types +{ + loop {} +} + +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr new file mode 100644 index 000000000..59192a1ec --- /dev/null +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -0,0 +1,44 @@ +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | // fn oom( +LL | || info: &Layout, +LL | || ) -> () + | ||_______- arguments to this function are incorrect +LL | | { +LL | | loop {} +LL | | } + | |__^ expected `&Layout`, found struct `Layout` + | +note: function defined here + --> $DIR/alloc-error-handler-bad-signature-1.rs:10:4 + | +LL | fn oom( + | ^^^ +LL | info: &Layout, + | ------------- + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | // fn oom( +LL | || info: &Layout, +LL | || ) -> () + | ||_______^ expected `!`, found `()` +LL | | { +LL | | loop {} +LL | | } + | |__- expected `!` because of return type + | + = note: expected type `!` + found unit type `()` + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs new file mode 100644 index 000000000..4f76257fc --- /dev/null +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs @@ -0,0 +1,17 @@ +// compile-flags:-C panic=abort + +#![feature(alloc_error_handler)] +#![no_std] +#![no_main] + +struct Layout; + +#[alloc_error_handler] +fn oom( + info: Layout, //~^ ERROR mismatched types +) { //~^^ ERROR mismatched types + loop {} +} + +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr new file mode 100644 index 000000000..7d23c2fc0 --- /dev/null +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -0,0 +1,50 @@ +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | // fn oom( +LL | || info: Layout, +LL | || ) { + | ||_- arguments to this function are incorrect +LL | | loop {} +LL | | } + | |__^ expected struct `Layout`, found struct `core::alloc::Layout` + | + = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types +note: struct `core::alloc::Layout` is defined in crate `core` + --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL +note: struct `Layout` is defined in the current crate + --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1 + | +LL | struct Layout; + | ^^^^^^^^^^^^^ +note: function defined here + --> $DIR/alloc-error-handler-bad-signature-2.rs:10:4 + | +LL | fn oom( + | ^^^ +LL | info: Layout, + | ------------ + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | // fn oom( +LL | || info: Layout, +LL | || ) { + | ||_^ expected `!`, found `()` +LL | | loop {} +LL | | } + | |__- expected `!` because of return type + | + = note: expected type `!` + found unit type `()` + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs new file mode 100644 index 000000000..ea9ad39a7 --- /dev/null +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs @@ -0,0 +1,15 @@ +// compile-flags:-C panic=abort + +#![feature(alloc_error_handler)] +#![no_std] +#![no_main] + +struct Layout; + +#[alloc_error_handler] +fn oom() -> ! { //~ ERROR function takes 0 arguments but 1 argument was supplied + loop {} +} + +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr new file mode 100644 index 000000000..77ea8ef05 --- /dev/null +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr @@ -0,0 +1,25 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1 + | +LL | #[alloc_error_handler] + | ---------------------- in this procedural macro expansion +LL | fn oom() -> ! { + | _-^^^^^^^^^^^^ +LL | | loop {} +LL | | } + | |_- argument of type `core::alloc::Layout` unexpected + | +note: function defined here + --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4 + | +LL | fn oom() -> ! { + | ^^^ + = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) +help: remove the extra argument + | +LL | fn oom() -> !() { + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/alloc-error/default-alloc-error-hook.rs b/tests/ui/alloc-error/default-alloc-error-hook.rs new file mode 100644 index 000000000..8be09500f --- /dev/null +++ b/tests/ui/alloc-error/default-alloc-error-hook.rs @@ -0,0 +1,28 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::alloc::{Layout, handle_alloc_error}; +use std::env; +use std::process::Command; +use std::str; + +fn main() { + if env::args().len() > 1 { + handle_alloc_error(Layout::new::<[u8; 42]>()) + } + + let me = env::current_exe().unwrap(); + let output = Command::new(&me).arg("next").output().unwrap(); + assert!(!output.status.success(), "{:?} is a success", output.status); + + let mut stderr = str::from_utf8(&output.stderr).unwrap(); + + // When running inside QEMU user-mode emulation, there will be an extra message printed by QEMU + // in the stderr whenever a core dump happens. Remove it before the check. + stderr = stderr + .strip_suffix("qemu: uncaught target signal 6 (Aborted) - core dumped\n") + .unwrap_or(stderr); + + assert_eq!(stderr, "memory allocation of 42 bytes failed\n"); +} diff --git a/tests/ui/allocator/allocator-args.rs b/tests/ui/allocator/allocator-args.rs new file mode 100644 index 000000000..1033f947c --- /dev/null +++ b/tests/ui/allocator/allocator-args.rs @@ -0,0 +1,13 @@ +use std::alloc::{GlobalAlloc, Layout}; + +struct A; + +unsafe impl GlobalAlloc for A { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { panic!() } + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { panic!() } +} + +#[global_allocator(malloc)] //~ ERROR malformed `global_allocator` attribute input +static S: A = A; + +fn main() {} diff --git a/tests/ui/allocator/allocator-args.stderr b/tests/ui/allocator/allocator-args.stderr new file mode 100644 index 000000000..dfff2a7e7 --- /dev/null +++ b/tests/ui/allocator/allocator-args.stderr @@ -0,0 +1,8 @@ +error: malformed `global_allocator` attribute input + --> $DIR/allocator-args.rs:10:1 + | +LL | #[global_allocator(malloc)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[global_allocator]` + +error: aborting due to previous error + diff --git a/tests/ui/allocator/auxiliary/custom-as-global.rs b/tests/ui/allocator/auxiliary/custom-as-global.rs new file mode 100644 index 000000000..a5e96e775 --- /dev/null +++ b/tests/ui/allocator/auxiliary/custom-as-global.rs @@ -0,0 +1,16 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +extern crate custom; + +use std::sync::atomic::{AtomicUsize, Ordering}; + +use custom::A; + +#[global_allocator] +static ALLOCATOR: A = A(AtomicUsize::new(0)); + +pub fn get() -> usize { + ALLOCATOR.0.load(Ordering::SeqCst) +} diff --git a/tests/ui/allocator/auxiliary/custom.rs b/tests/ui/allocator/auxiliary/custom.rs new file mode 100644 index 000000000..b0ec9ab09 --- /dev/null +++ b/tests/ui/allocator/auxiliary/custom.rs @@ -0,0 +1,21 @@ +// no-prefer-dynamic + +#![feature(allocator_api)] +#![crate_type = "rlib"] + +use std::alloc::{GlobalAlloc, System, Layout}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +pub struct A(pub AtomicUsize); + +unsafe impl GlobalAlloc for A { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + self.0.fetch_add(1, Ordering::SeqCst); + System.alloc(layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + self.0.fetch_add(1, Ordering::SeqCst); + System.dealloc(ptr, layout) + } +} diff --git a/tests/ui/allocator/auxiliary/helper.rs b/tests/ui/allocator/auxiliary/helper.rs new file mode 100644 index 000000000..008fb3501 --- /dev/null +++ b/tests/ui/allocator/auxiliary/helper.rs @@ -0,0 +1,11 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +extern crate alloc; +use alloc::fmt; + +pub fn work_with(p: &fmt::Debug) { + drop(p); +} diff --git a/tests/ui/allocator/auxiliary/system-allocator.rs b/tests/ui/allocator/auxiliary/system-allocator.rs new file mode 100644 index 000000000..97b86bbc9 --- /dev/null +++ b/tests/ui/allocator/auxiliary/system-allocator.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +use std::alloc::System; + +#[global_allocator] +static A: System = System; diff --git a/tests/ui/allocator/auxiliary/system-allocator2.rs b/tests/ui/allocator/auxiliary/system-allocator2.rs new file mode 100644 index 000000000..97b86bbc9 --- /dev/null +++ b/tests/ui/allocator/auxiliary/system-allocator2.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +use std::alloc::System; + +#[global_allocator] +static A: System = System; diff --git a/tests/ui/allocator/custom-in-block.rs b/tests/ui/allocator/custom-in-block.rs new file mode 100644 index 000000000..12813a1fc --- /dev/null +++ b/tests/ui/allocator/custom-in-block.rs @@ -0,0 +1,22 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +fn main() { + #[global_allocator] + pub static GLOBAL: A = A(AtomicUsize::new(0)); + + let n = GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/tests/ui/allocator/custom-in-submodule.rs b/tests/ui/allocator/custom-in-submodule.rs new file mode 100644 index 000000000..ea341b1ac --- /dev/null +++ b/tests/ui/allocator/custom-in-submodule.rs @@ -0,0 +1,26 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +mod submodule { + use super::*; + + #[global_allocator] + pub static GLOBAL: A = A(AtomicUsize::new(0)); +} + +fn main() { + let n = submodule::GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/tests/ui/allocator/custom.rs b/tests/ui/allocator/custom.rs new file mode 100644 index 000000000..10cbc23c4 --- /dev/null +++ b/tests/ui/allocator/custom.rs @@ -0,0 +1,59 @@ +// run-pass + +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(allocator_api)] +#![feature(slice_ptr_get)] + +extern crate helper; + +use std::alloc::{self, Allocator, Global, Layout, System}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static HITS: AtomicUsize = AtomicUsize::new(0); + +struct A; + +unsafe impl alloc::GlobalAlloc for A { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + HITS.fetch_add(1, Ordering::SeqCst); + alloc::GlobalAlloc::alloc(&System, layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + HITS.fetch_add(1, Ordering::SeqCst); + alloc::GlobalAlloc::dealloc(&System, ptr, layout) + } +} + +#[global_allocator] +static GLOBAL: A = A; + +fn main() { + println!("hello!"); + + let n = HITS.load(Ordering::SeqCst); + assert!(n > 0); + unsafe { + let layout = Layout::from_size_align(4, 2).unwrap(); + + let memory = Global.allocate(layout.clone()).unwrap(); + helper::work_with(&memory); + assert_eq!(HITS.load(Ordering::SeqCst), n + 1); + Global.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(HITS.load(Ordering::SeqCst), n + 2); + + let s = String::with_capacity(10); + helper::work_with(&s); + assert_eq!(HITS.load(Ordering::SeqCst), n + 3); + drop(s); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + + let memory = System.allocate(layout.clone()).unwrap(); + helper::work_with(&memory); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + System.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + } +} diff --git a/tests/ui/allocator/function-allocator.rs b/tests/ui/allocator/function-allocator.rs new file mode 100644 index 000000000..d53f6e9b7 --- /dev/null +++ b/tests/ui/allocator/function-allocator.rs @@ -0,0 +1,4 @@ +#[global_allocator] +fn foo() {} //~ ERROR: allocators must be statics + +fn main() {} diff --git a/tests/ui/allocator/function-allocator.stderr b/tests/ui/allocator/function-allocator.stderr new file mode 100644 index 000000000..5e47b0f0c --- /dev/null +++ b/tests/ui/allocator/function-allocator.stderr @@ -0,0 +1,8 @@ +error: allocators must be statics + --> $DIR/function-allocator.rs:2:1 + | +LL | fn foo() {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/allocator/hygiene.rs b/tests/ui/allocator/hygiene.rs new file mode 100644 index 000000000..9bd8406a2 --- /dev/null +++ b/tests/ui/allocator/hygiene.rs @@ -0,0 +1,31 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +#![allow(nonstandard_style)] + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[allow(dead_code)] +struct u8; +#[allow(dead_code)] +struct usize; +#[allow(dead_code)] +static arg0: () = (); + +#[global_allocator] +pub static GLOBAL: A = A(AtomicUsize::new(0)); + +fn main() { + let n = GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs new file mode 100644 index 000000000..289262433 --- /dev/null +++ b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs @@ -0,0 +1,84 @@ +// run-pass +// ignore-android no libc +// ignore-emscripten no libc +// ignore-sgx no libc +// ignore-wasm32 no libc +// only-linux +// compile-flags:-C panic=abort +// aux-build:helper.rs + +#![feature(rustc_private, lang_items)] +#![feature(alloc_error_handler)] +#![no_std] +#![no_main] + +extern crate alloc; +extern crate libc; + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +use alloc::boxed::Box; +use alloc::string::ToString; +use core::alloc::{GlobalAlloc, Layout}; +use core::ptr::null_mut; + +extern crate helper; + +struct MyAllocator; + +#[alloc_error_handler] +fn my_oom(layout: Layout) -> ! { + use alloc::fmt::write; + unsafe { + let size = layout.size(); + let mut s = alloc::string::String::new(); + write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap(); + libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); + libc::exit(0) + } +} + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() } + } + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +#[global_allocator] +static A: MyAllocator = MyAllocator; + +#[panic_handler] +fn panic(panic_info: &core::panic::PanicInfo) -> ! { + unsafe { + let s = panic_info.to_string(); + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); + libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len()); + libc::exit(1) + } +} + +// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed. +// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions +// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't +// unwind. So, for this test case we will define the symbol. +#[lang = "eh_personality"] +extern "C" fn rust_eh_personality() {} + +#[derive(Default, Debug)] +struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]); + +#[no_mangle] +fn main(_argc: i32, _argv: *const *const u8) -> isize { + let zero = Box::::new(Default::default()); + helper::work_with(&zero); + 1 +} diff --git a/tests/ui/allocator/no_std-alloc-error-handler-default.rs b/tests/ui/allocator/no_std-alloc-error-handler-default.rs new file mode 100644 index 000000000..56409e713 --- /dev/null +++ b/tests/ui/allocator/no_std-alloc-error-handler-default.rs @@ -0,0 +1,71 @@ +// run-pass +// ignore-android no libc +// ignore-emscripten no libc +// ignore-sgx no libc +// ignore-wasm32 no libc +// only-linux +// compile-flags:-C panic=abort +// aux-build:helper.rs + +#![feature(rustc_private, lang_items)] +#![no_std] +#![no_main] + +extern crate alloc; +extern crate libc; + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +use alloc::boxed::Box; +use alloc::string::ToString; +use core::alloc::{GlobalAlloc, Layout}; +use core::ptr::null_mut; + +extern crate helper; + +struct MyAllocator; + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() } + } + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +#[global_allocator] +static A: MyAllocator = MyAllocator; + +#[panic_handler] +fn panic(panic_info: &core::panic::PanicInfo) -> ! { + unsafe { + let s = panic_info.to_string(); + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); + libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len()); + libc::exit(0) + } +} + +// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed. +// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions +// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't +// unwind. So, for this test case we will define the symbol. +#[lang = "eh_personality"] +extern "C" fn rust_eh_personality() {} + +#[derive(Default, Debug)] +struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]); + +#[no_mangle] +fn main(_argc: i32, _argv: *const *const u8) -> isize { + let zero = Box::::new(Default::default()); + helper::work_with(&zero); + 1 +} diff --git a/tests/ui/allocator/not-an-allocator.rs b/tests/ui/allocator/not-an-allocator.rs new file mode 100644 index 000000000..4a538d4d0 --- /dev/null +++ b/tests/ui/allocator/not-an-allocator.rs @@ -0,0 +1,8 @@ +#[global_allocator] +static A: usize = 0; +//~^ ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 + +fn main() {} diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr new file mode 100644 index 000000000..62bb0679f --- /dev/null +++ b/tests/ui/allocator/not-an-allocator.stderr @@ -0,0 +1,47 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/allocator/object-safe.rs b/tests/ui/allocator/object-safe.rs new file mode 100644 index 000000000..fae7ab7fe --- /dev/null +++ b/tests/ui/allocator/object-safe.rs @@ -0,0 +1,13 @@ +// run-pass + +// Check that `Allocator` is object safe, this allows for polymorphic allocators + +#![feature(allocator_api)] + +use std::alloc::{Allocator, System}; + +fn ensure_object_safe(_: &dyn Allocator) {} + +fn main() { + ensure_object_safe(&System); +} diff --git a/tests/ui/allocator/two-allocators.rs b/tests/ui/allocator/two-allocators.rs new file mode 100644 index 000000000..aa1291e77 --- /dev/null +++ b/tests/ui/allocator/two-allocators.rs @@ -0,0 +1,9 @@ +use std::alloc::System; + +#[global_allocator] +static A: System = System; +#[global_allocator] +static B: System = System; +//~^ ERROR: cannot define multiple global allocators + +fn main() {} diff --git a/tests/ui/allocator/two-allocators.stderr b/tests/ui/allocator/two-allocators.stderr new file mode 100644 index 000000000..7a914c2a3 --- /dev/null +++ b/tests/ui/allocator/two-allocators.stderr @@ -0,0 +1,14 @@ +error: cannot define multiple global allocators + --> $DIR/two-allocators.rs:6:1 + | +LL | static A: System = System; + | -------------------------- previous global allocator defined here +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static B: System = System; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator + | + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/allocator/two-allocators2.rs b/tests/ui/allocator/two-allocators2.rs new file mode 100644 index 000000000..6dfefe19c --- /dev/null +++ b/tests/ui/allocator/two-allocators2.rs @@ -0,0 +1,12 @@ +// aux-build:system-allocator.rs +// no-prefer-dynamic +// error-pattern: the `#[global_allocator]` in + +extern crate system_allocator; + +use std::alloc::System; + +#[global_allocator] +static A: System = System; + +fn main() {} diff --git a/tests/ui/allocator/two-allocators2.stderr b/tests/ui/allocator/two-allocators2.stderr new file mode 100644 index 000000000..b1fb4421e --- /dev/null +++ b/tests/ui/allocator/two-allocators2.stderr @@ -0,0 +1,4 @@ +error: the `#[global_allocator]` in this crate conflicts with global allocator in: system_allocator + +error: aborting due to previous error + diff --git a/tests/ui/allocator/two-allocators3.rs b/tests/ui/allocator/two-allocators3.rs new file mode 100644 index 000000000..31dea2d44 --- /dev/null +++ b/tests/ui/allocator/two-allocators3.rs @@ -0,0 +1,10 @@ +// aux-build:system-allocator.rs +// aux-build:system-allocator2.rs +// no-prefer-dynamic +// error-pattern: the `#[global_allocator]` in + + +extern crate system_allocator; +extern crate system_allocator2; + +fn main() {} diff --git a/tests/ui/allocator/two-allocators3.stderr b/tests/ui/allocator/two-allocators3.stderr new file mode 100644 index 000000000..a3079113d --- /dev/null +++ b/tests/ui/allocator/two-allocators3.stderr @@ -0,0 +1,4 @@ +error: the `#[global_allocator]` in system_allocator conflicts with global allocator in: system_allocator2 + +error: aborting due to previous error + diff --git a/tests/ui/allocator/xcrate-use.rs b/tests/ui/allocator/xcrate-use.rs new file mode 100644 index 000000000..edd4df75e --- /dev/null +++ b/tests/ui/allocator/xcrate-use.rs @@ -0,0 +1,36 @@ +// run-pass + +// aux-build:custom.rs +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(allocator_api)] +#![feature(slice_ptr_get)] + +extern crate custom; +extern crate helper; + +use std::alloc::{Allocator, Global, Layout, System}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[global_allocator] +static GLOBAL: custom::A = custom::A(AtomicUsize::new(0)); + +fn main() { + unsafe { + let n = GLOBAL.0.load(Ordering::SeqCst); + let layout = Layout::from_size_align(4, 2).unwrap(); + + let memory = Global.allocate(layout.clone()).unwrap(); + helper::work_with(&memory); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + Global.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + + let memory = System.allocate(layout.clone()).unwrap(); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + helper::work_with(&memory); + System.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + } +} diff --git a/tests/ui/allocator/xcrate-use2.rs b/tests/ui/allocator/xcrate-use2.rs new file mode 100644 index 000000000..d8478fb5e --- /dev/null +++ b/tests/ui/allocator/xcrate-use2.rs @@ -0,0 +1,47 @@ +// run-pass + +// aux-build:custom.rs +// aux-build:custom-as-global.rs +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(allocator_api)] + +extern crate custom; +extern crate custom_as_global; +extern crate helper; + +use std::alloc::{alloc, dealloc, GlobalAlloc, System, Layout}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static GLOBAL: custom::A = custom::A(AtomicUsize::new(0)); + +fn main() { + unsafe { + let n = custom_as_global::get(); + let layout = Layout::from_size_align(4, 2).unwrap(); + + // Global allocator routes to the `custom_as_global` global + let ptr = alloc(layout.clone()); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 1); + dealloc(ptr, layout.clone()); + assert_eq!(custom_as_global::get(), n + 2); + + // Usage of the system allocator avoids all globals + let ptr = System.alloc(layout.clone()); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 2); + System.dealloc(ptr, layout.clone()); + assert_eq!(custom_as_global::get(), n + 2); + + // Usage of our personal allocator doesn't affect other instances + let ptr = GLOBAL.alloc(layout.clone()); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 2); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1); + GLOBAL.dealloc(ptr, layout); + assert_eq!(custom_as_global::get(), n + 2); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2); + } +} diff --git a/tests/ui/annotate-snippet/auxiliary/multispan.rs b/tests/ui/annotate-snippet/auxiliary/multispan.rs new file mode 100644 index 000000000..c05d15643 --- /dev/null +++ b/tests/ui/annotate-snippet/auxiliary/multispan.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + let mut hi_spans = vec![]; + for tree in input { + if let TokenTree::Ident(ref ident) = tree { + if ident.to_string() == "hi" { + hi_spans.push(ident.span()); + } + } + } + + if !hi_spans.is_empty() { + return Err(Span::def_site() + .error("hello to you, too!") + .span_note(hi_spans, "found these 'hi's")); + } + + Ok(()) +} + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/tests/ui/annotate-snippet/missing-type.rs b/tests/ui/annotate-snippet/missing-type.rs new file mode 100644 index 000000000..b0d8b5fba --- /dev/null +++ b/tests/ui/annotate-snippet/missing-type.rs @@ -0,0 +1,5 @@ +// compile-flags: --error-format human-annotate-rs -Z unstable-options + +pub fn main() { + let x: Iter; //~ ERROR cannot find type `Iter` in this scope +} diff --git a/tests/ui/annotate-snippet/missing-type.stderr b/tests/ui/annotate-snippet/missing-type.stderr new file mode 100644 index 000000000..c16f022a7 --- /dev/null +++ b/tests/ui/annotate-snippet/missing-type.stderr @@ -0,0 +1,6 @@ +error[E0412]: cannot find type `Iter` in this scope + --> $DIR/missing-type.rs:4:12 + | +LL | let x: Iter; + | ^^^^ not found in this scope + | diff --git a/tests/ui/annotate-snippet/multispan.rs b/tests/ui/annotate-snippet/multispan.rs new file mode 100644 index 000000000..69d7e1a9d --- /dev/null +++ b/tests/ui/annotate-snippet/multispan.rs @@ -0,0 +1,28 @@ +// aux-build:multispan.rs +// compile-flags: --error-format human-annotate-rs -Z unstable-options + +#![feature(proc_macro_hygiene)] + +extern crate multispan; + +use multispan::hello; + +fn main() { + // This one emits no error. + hello!(); + + // Exactly one 'hi'. + hello!(hi); //~ ERROR hello to you, too! + + // Now two, back to back. + hello!(hi hi); //~ ERROR hello to you, too! + + // Now three, back to back. + hello!(hi hi hi); //~ ERROR hello to you, too! + + // Now several, with spacing. + hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too! + hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too! + hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too! + hello!(hi good hi and good bye); //~ ERROR hello to you, too! +} diff --git a/tests/ui/annotate-snippet/multispan.stderr b/tests/ui/annotate-snippet/multispan.stderr new file mode 100644 index 000000000..baed54c59 --- /dev/null +++ b/tests/ui/annotate-snippet/multispan.stderr @@ -0,0 +1,42 @@ +error: hello to you, too! + --> $DIR/multispan.rs:15:5 + | +LL | hello!(hi); + | ^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:18:5 + | +LL | hello!(hi hi); + | ^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:21:5 + | +LL | hello!(hi hi hi); + | ^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:24:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:25:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:26:5 + | +LL | hello!(whoah. hi di hi di ho); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +error: hello to you, too! + --> $DIR/multispan.rs:27:5 + | +LL | hello!(hi good hi and good bye); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | diff --git a/tests/ui/anon-params/anon-params-denied-2018.rs b/tests/ui/anon-params/anon-params-denied-2018.rs new file mode 100644 index 000000000..95533cf3d --- /dev/null +++ b/tests/ui/anon-params/anon-params-denied-2018.rs @@ -0,0 +1,32 @@ +// Tests that anonymous parameters are a hard error in edition 2018. + +// edition:2018 + +trait T { + fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)` + + // Also checks with `&` + fn foo_with_ref(&mut i32); + //~^ ERROR expected one of `:`, `@`, or `|`, found `)` + + fn foo_with_qualified_path(::Baz); + //~^ ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` + + fn foo_with_qualified_path_and_ref(&::Baz); + //~^ ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` + + fn foo_with_multiple_qualified_paths(::Baz, ::Baz); + //~^ ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `,` + //~| ERROR expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` + + fn bar_with_default_impl(String, String) {} + //~^ ERROR expected one of `:` + //~| ERROR expected one of `:` + + // do not complain about missing `b` + fn baz(a:usize, b, c: usize) -> usize { //~ ERROR expected one of `:` + a + b + c + } +} + +fn main() {} diff --git a/tests/ui/anon-params/anon-params-denied-2018.stderr b/tests/ui/anon-params/anon-params-denied-2018.stderr new file mode 100644 index 000000000..bb60c898e --- /dev/null +++ b/tests/ui/anon-params/anon-params-denied-2018.stderr @@ -0,0 +1,142 @@ +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/anon-params-denied-2018.rs:6:15 + | +LL | fn foo(i32); + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo(self: i32); + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn foo(i32: TypeName); + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo(_: i32); + | ++ + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/anon-params-denied-2018.rs:9:29 + | +LL | fn foo_with_ref(&mut i32); + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo_with_ref(self: &mut i32); + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn foo_with_ref(i32: &mut TypeName); + | ~~~~~~~~~~~~~~~~~~ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo_with_ref(_: &mut i32); + | ++ + +error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` + --> $DIR/anon-params-denied-2018.rs:12:47 + | +LL | fn foo_with_qualified_path(::Baz); + | ^ expected one of 8 possible tokens + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: explicitly ignore the parameter name + | +LL | fn foo_with_qualified_path(_: ::Baz); + | ~~~~~~~~~~~~~~~~~~ + +error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` + --> $DIR/anon-params-denied-2018.rs:15:56 + | +LL | fn foo_with_qualified_path_and_ref(&::Baz); + | ^ expected one of 8 possible tokens + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: explicitly ignore the parameter name + | +LL | fn foo_with_qualified_path_and_ref(_: &::Baz); + | ~~~~~~~~~~~~~~~~~~~ + +error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `,` + --> $DIR/anon-params-denied-2018.rs:18:57 + | +LL | fn foo_with_multiple_qualified_paths(::Baz, ::Baz); + | ^ expected one of 8 possible tokens + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: explicitly ignore the parameter name + | +LL | fn foo_with_multiple_qualified_paths(_: ::Baz, ::Baz); + | ~~~~~~~~~~~~~~~~~~ + +error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)` + --> $DIR/anon-params-denied-2018.rs:18:74 + | +LL | fn foo_with_multiple_qualified_paths(::Baz, ::Baz); + | ^ expected one of 8 possible tokens + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: explicitly ignore the parameter name + | +LL | fn foo_with_multiple_qualified_paths(::Baz, _: ::Baz); + | ~~~~~~~~~~~~~~~~~~ + +error: expected one of `:`, `@`, or `|`, found `,` + --> $DIR/anon-params-denied-2018.rs:22:36 + | +LL | fn bar_with_default_impl(String, String) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn bar_with_default_impl(self: String, String) {} + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn bar_with_default_impl(String: TypeName, String) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn bar_with_default_impl(_: String, String) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/anon-params-denied-2018.rs:22:44 + | +LL | fn bar_with_default_impl(String, String) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn bar_with_default_impl(String, String: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn bar_with_default_impl(String, _: String) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `,` + --> $DIR/anon-params-denied-2018.rs:27:22 + | +LL | fn baz(a:usize, b, c: usize) -> usize { + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn baz(a:usize, b: TypeName, c: usize) -> usize { + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn baz(a:usize, _: b, c: usize) -> usize { + | ++ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/anon-params/anon-params-deprecated.fixed b/tests/ui/anon-params/anon-params-deprecated.fixed new file mode 100644 index 000000000..c09e20770 --- /dev/null +++ b/tests/ui/anon-params/anon-params-deprecated.fixed @@ -0,0 +1,19 @@ +#![warn(anonymous_parameters)] +// Test for the anonymous_parameters deprecation lint (RFC 1685) + +// check-pass +// edition:2015 +// run-rustfix + +trait T { + fn foo(_: i32); //~ WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition + + fn bar_with_default_impl(_: String, _: String) {} + //~^ WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition + //~| WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition +} + +fn main() {} diff --git a/tests/ui/anon-params/anon-params-deprecated.rs b/tests/ui/anon-params/anon-params-deprecated.rs new file mode 100644 index 000000000..6f7385da0 --- /dev/null +++ b/tests/ui/anon-params/anon-params-deprecated.rs @@ -0,0 +1,19 @@ +#![warn(anonymous_parameters)] +// Test for the anonymous_parameters deprecation lint (RFC 1685) + +// check-pass +// edition:2015 +// run-rustfix + +trait T { + fn foo(i32); //~ WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition + + fn bar_with_default_impl(String, String) {} + //~^ WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition + //~| WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition +} + +fn main() {} diff --git a/tests/ui/anon-params/anon-params-deprecated.stderr b/tests/ui/anon-params/anon-params-deprecated.stderr new file mode 100644 index 000000000..691e2c795 --- /dev/null +++ b/tests/ui/anon-params/anon-params-deprecated.stderr @@ -0,0 +1,34 @@ +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/anon-params-deprecated.rs:9:12 + | +LL | fn foo(i32); + | ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 +note: the lint level is defined here + --> $DIR/anon-params-deprecated.rs:1:9 + | +LL | #![warn(anonymous_parameters)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/anon-params-deprecated.rs:12:30 + | +LL | fn bar_with_default_impl(String, String) {} + | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/anon-params-deprecated.rs:12:38 + | +LL | fn bar_with_default_impl(String, String) {} + | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + +warning: 3 warnings emitted + diff --git a/tests/ui/anon-params/anon-params-edition-hygiene.rs b/tests/ui/anon-params/anon-params-edition-hygiene.rs new file mode 100644 index 000000000..6936205f8 --- /dev/null +++ b/tests/ui/anon-params/anon-params-edition-hygiene.rs @@ -0,0 +1,13 @@ +// check-pass +// edition:2018 +// aux-build:anon-params-edition-hygiene.rs + +// This warning is still surfaced +#![allow(anonymous_parameters)] + +#[macro_use] +extern crate anon_params_edition_hygiene; + +generate_trait_2015!(u8); + +fn main() {} diff --git a/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs b/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs new file mode 100644 index 000000000..aa4221bec --- /dev/null +++ b/tests/ui/anon-params/auxiliary/anon-params-edition-hygiene.rs @@ -0,0 +1,12 @@ +// edition:2015 + +#[macro_export] +macro_rules! generate_trait_2015 { + ($Type: ident) => { + trait Trait { + fn method($Type) {} + } + }; +} + +fn main() {} diff --git a/tests/ui/anonymous-higher-ranked-lifetime.rs b/tests/ui/anonymous-higher-ranked-lifetime.rs new file mode 100644 index 000000000..898fe22fa --- /dev/null +++ b/tests/ui/anonymous-higher-ranked-lifetime.rs @@ -0,0 +1,30 @@ +fn main() { + f1(|_: (), _: ()| {}); //~ ERROR type mismatch + f2(|_: (), _: ()| {}); //~ ERROR type mismatch + f3(|_: (), _: ()| {}); //~ ERROR type mismatch + f4(|_: (), _: ()| {}); //~ ERROR type mismatch + f5(|_: (), _: ()| {}); //~ ERROR type mismatch + g1(|_: (), _: ()| {}); //~ ERROR type mismatch + g2(|_: (), _: ()| {}); //~ ERROR type mismatch + g3(|_: (), _: ()| {}); //~ ERROR type mismatch + g4(|_: (), _: ()| {}); //~ ERROR type mismatch + h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch + h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch +} + +// Basic +fn f1(_: F) where F: Fn(&(), &()) {} +fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} +fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} +fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} +fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + +// Nested +fn g1(_: F) where F: Fn(&(), Box) {} +fn g2(_: F) where F: Fn(&(), fn(&())) {} +fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} +fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + +// Mixed +fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} +fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/anonymous-higher-ranked-lifetime.stderr new file mode 100644 index 000000000..c023d1b15 --- /dev/null +++ b/tests/ui/anonymous-higher-ranked-lifetime.stderr @@ -0,0 +1,223 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 + | +LL | f1(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:16:25 + | +LL | fn f1(_: F) where F: Fn(&(), &()) {} + | ^^^^^^^^^^^^ required by this bound in `f1` +help: consider borrowing the argument + | +LL | f1(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 + | +LL | f2(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:17:25 + | +LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f2` +help: consider borrowing the argument + | +LL | f2(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 + | +LL | f3(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:18:29 + | +LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} + | ^^^^^^^^^^^^^^^ required by this bound in `f3` +help: consider borrowing the argument + | +LL | f3(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 + | +LL | f4(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'r, 'a> fn(&'a (), &'r ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:19:25 + | +LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f4` +help: consider borrowing the argument + | +LL | f4(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 + | +LL | f5(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `f5` + --> $DIR/anonymous-higher-ranked-lifetime.rs:20:25 + | +LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `f5` +help: consider borrowing the argument + | +LL | f5(|_: &(), _: &()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 + | +LL | g1(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:23:25 + | +LL | fn g1(_: F) where F: Fn(&(), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g1` +help: consider borrowing the argument + | +LL | g1(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + | +LL | g2(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:24:25 + | +LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} + | ^^^^^^^^^^^^^^^^ required by this bound in `g2` +help: consider borrowing the argument + | +LL | g2(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 + | +LL | g3(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g3` + --> $DIR/anonymous-higher-ranked-lifetime.rs:25:25 + | +LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g3` +help: consider borrowing the argument + | +LL | g3(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + | +LL | g4(|_: (), _: ()| {}); + | ^^ -------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` + found closure signature `fn((), ()) -> _` +note: required by a bound in `g4` + --> $DIR/anonymous-higher-ranked-lifetime.rs:26:25 + | +LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `g4` +help: consider borrowing the argument + | +LL | g4(|_: &(), _: ()| {}); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 + | +LL | h1(|_: (), _: (), _: (), _: ()| {}); + | ^^ ---------------------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _` + found closure signature `fn((), (), (), ()) -> _` +note: required by a bound in `h1` + --> $DIR/anonymous-higher-ranked-lifetime.rs:29:25 + | +LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h1` +help: consider borrowing the argument + | +LL | h1(|_: &(), _: (), _: &(), _: ()| {}); + | + + + +error[E0631]: type mismatch in closure arguments + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + | +LL | h2(|_: (), _: (), _: (), _: ()| {}); + | ^^ ---------------------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'t0, 'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` + found closure signature `fn((), (), (), ()) -> _` +note: required by a bound in `h2` + --> $DIR/anonymous-higher-ranked-lifetime.rs:30:25 + | +LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2` +help: consider borrowing the argument + | +LL | h2(|_: &(), _: (), _: &(), _: ()| {}); + | + + + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/argument-suggestions/basic.rs b/tests/ui/argument-suggestions/basic.rs new file mode 100644 index 000000000..961e7a50e --- /dev/null +++ b/tests/ui/argument-suggestions/basic.rs @@ -0,0 +1,28 @@ +// Some basic "obvious" cases for the heuristic error messages added for #65853 +// One for each of the detected cases + +enum E { X, Y } +enum F { X2, Y2 } +struct G {} +struct H {} +struct X {} +struct Y {} +struct Z {} + + +fn invalid(_i: u32) {} +fn extra() {} +fn missing(_i: u32) {} +fn swapped(_i: u32, _s: &str) {} +fn permuted(_x: X, _y: Y, _z: Z) {} + +fn main() { + invalid(1.0); //~ ERROR mismatched types + extra(""); //~ ERROR function takes + missing(); //~ ERROR function takes + swapped("", 1); //~ ERROR arguments to this function are incorrect + permuted(Y {}, Z {}, X {}); //~ ERROR arguments to this function are incorrect + + let closure = |x| x; + closure(); //~ ERROR function takes +} diff --git a/tests/ui/argument-suggestions/basic.stderr b/tests/ui/argument-suggestions/basic.stderr new file mode 100644 index 000000000..062b37688 --- /dev/null +++ b/tests/ui/argument-suggestions/basic.stderr @@ -0,0 +1,103 @@ +error[E0308]: mismatched types + --> $DIR/basic.rs:20:13 + | +LL | invalid(1.0); + | ------- ^^^ expected `u32`, found floating-point number + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/basic.rs:13:4 + | +LL | fn invalid(_i: u32) {} + | ^^^^^^^ ------- + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/basic.rs:21:5 + | +LL | extra(""); + | ^^^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/basic.rs:14:4 + | +LL | fn extra() {} + | ^^^^^ +help: remove the extra argument + | +LL | extra(); + | ~~ + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/basic.rs:22:5 + | +LL | missing(); + | ^^^^^^^-- an argument of type `u32` is missing + | +note: function defined here + --> $DIR/basic.rs:15:4 + | +LL | fn missing(_i: u32) {} + | ^^^^^^^ ------- +help: provide the argument + | +LL | missing(/* u32 */); + | ~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/basic.rs:23:5 + | +LL | swapped("", 1); + | ^^^^^^^ -- - expected `&str`, found `{integer}` + | | + | expected `u32`, found `&'static str` + | +note: function defined here + --> $DIR/basic.rs:16:4 + | +LL | fn swapped(_i: u32, _s: &str) {} + | ^^^^^^^ ------- -------- +help: swap these arguments + | +LL | swapped(1, ""); + | ~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/basic.rs:24:5 + | +LL | permuted(Y {}, Z {}, X {}); + | ^^^^^^^^ ---- ---- ---- expected `Z`, found `X` + | | | + | | expected `Y`, found `Z` + | expected `X`, found `Y` + | +note: function defined here + --> $DIR/basic.rs:17:4 + | +LL | fn permuted(_x: X, _y: Y, _z: Z) {} + | ^^^^^^^^ ----- ----- ----- +help: reorder these arguments + | +LL | permuted(X {}, Y {}, Z {}); + | ~~~~~~~~~~~~~~~~~~ + +error[E0057]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/basic.rs:27:5 + | +LL | closure(); + | ^^^^^^^-- an argument is missing + | +note: closure defined here + --> $DIR/basic.rs:26:19 + | +LL | let closure = |x| x; + | ^^^ +help: provide the argument + | +LL | closure(/* x */); + | ~~~~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0057, E0061, E0308. +For more information about an error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/complex.rs b/tests/ui/argument-suggestions/complex.rs new file mode 100644 index 000000000..384cdca7e --- /dev/null +++ b/tests/ui/argument-suggestions/complex.rs @@ -0,0 +1,16 @@ +// A complex case with mixed suggestions from #65853 + +enum E { X, Y } +enum F { X2, Y2 } +struct G {} +struct H {} +struct X {} +struct Y {} +struct Z {} + +fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {} + +fn main() { + complex(1.0, H {}, &"", G{}, F::X2, Z {}, X {}, Y {}); + //~^ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/argument-suggestions/complex.stderr b/tests/ui/argument-suggestions/complex.stderr new file mode 100644 index 000000000..205a85298 --- /dev/null +++ b/tests/ui/argument-suggestions/complex.stderr @@ -0,0 +1,19 @@ +error[E0308]: arguments to this function are incorrect + --> $DIR/complex.rs:14:3 + | +LL | complex(1.0, H {}, &"", G{}, F::X2, Z {}, X {}, Y {}); + | ^^^^^^^ --- expected `u32`, found floating-point number + | +note: function defined here + --> $DIR/complex.rs:11:4 + | +LL | fn complex(_i: u32, _s: &str, _e: E, _f: F, _g: G, _x: X, _y: Y, _z: Z ) {} + | ^^^^^^^ ------- -------- ----- ----- ----- ----- ----- ----- +help: did you mean + | +LL | complex(/* u32 */, &"", /* E */, F::X2, G{}, X {}, Y {}, Z {}); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/display-is-suggestable.rs b/tests/ui/argument-suggestions/display-is-suggestable.rs new file mode 100644 index 000000000..acb61f543 --- /dev/null +++ b/tests/ui/argument-suggestions/display-is-suggestable.rs @@ -0,0 +1,8 @@ +use std::fmt::Display; + +fn foo(x: &(dyn Display + Send)) {} + +fn main() { + foo(); + //~^ ERROR function takes 1 argument but 0 arguments were supplied +} diff --git a/tests/ui/argument-suggestions/display-is-suggestable.stderr b/tests/ui/argument-suggestions/display-is-suggestable.stderr new file mode 100644 index 000000000..edd72b53e --- /dev/null +++ b/tests/ui/argument-suggestions/display-is-suggestable.stderr @@ -0,0 +1,19 @@ +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/display-is-suggestable.rs:6:5 + | +LL | foo(); + | ^^^-- an argument of type `&dyn std::fmt::Display + Send` is missing + | +note: function defined here + --> $DIR/display-is-suggestable.rs:3:4 + | +LL | fn foo(x: &(dyn Display + Send)) {} + | ^^^ ------------------------ +help: provide the argument + | +LL | foo(/* &dyn std::fmt::Display + Send */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/exotic-calls.rs b/tests/ui/argument-suggestions/exotic-calls.rs new file mode 100644 index 000000000..569a39a2b --- /dev/null +++ b/tests/ui/argument-suggestions/exotic-calls.rs @@ -0,0 +1,26 @@ +fn foo(t: T) { + t(1i32); + //~^ ERROR function takes 0 arguments but 1 argument was supplied +} + +fn bar(t: impl Fn()) { + t(1i32); + //~^ ERROR function takes 0 arguments but 1 argument was supplied +} + +fn baz() -> impl Fn() { + || {} +} + +fn baz2() { + baz()(1i32) + //~^ ERROR function takes 0 arguments but 1 argument was supplied +} + +fn qux() { + let x = || {}; + x(1i32); + //~^ ERROR function takes 0 arguments but 1 argument was supplied +} + +fn main() {} diff --git a/tests/ui/argument-suggestions/exotic-calls.stderr b/tests/ui/argument-suggestions/exotic-calls.stderr new file mode 100644 index 000000000..0580e53c5 --- /dev/null +++ b/tests/ui/argument-suggestions/exotic-calls.stderr @@ -0,0 +1,67 @@ +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/exotic-calls.rs:2:5 + | +LL | t(1i32); + | ^ ---- argument of type `i32` unexpected + | +note: callable defined here + --> $DIR/exotic-calls.rs:1:11 + | +LL | fn foo(t: T) { + | ^^^^ +help: remove the extra argument + | +LL | t(); + | ~~ + +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/exotic-calls.rs:7:5 + | +LL | t(1i32); + | ^ ---- argument of type `i32` unexpected + | +note: type parameter defined here + --> $DIR/exotic-calls.rs:6:11 + | +LL | fn bar(t: impl Fn()) { + | ^^^^^^^^^ +help: remove the extra argument + | +LL | t(); + | ~~ + +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/exotic-calls.rs:16:5 + | +LL | baz()(1i32) + | ^^^^^ ---- argument of type `i32` unexpected + | +note: opaque type defined here + --> $DIR/exotic-calls.rs:11:13 + | +LL | fn baz() -> impl Fn() { + | ^^^^^^^^^ +help: remove the extra argument + | +LL | baz()() + | ~~ + +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/exotic-calls.rs:22:5 + | +LL | x(1i32); + | ^ ---- argument of type `i32` unexpected + | +note: closure defined here + --> $DIR/exotic-calls.rs:21:13 + | +LL | let x = || {}; + | ^^ +help: remove the extra argument + | +LL | x(); + | ~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/extern-fn-arg-names.rs b/tests/ui/argument-suggestions/extern-fn-arg-names.rs new file mode 100644 index 000000000..df2fd6624 --- /dev/null +++ b/tests/ui/argument-suggestions/extern-fn-arg-names.rs @@ -0,0 +1,9 @@ +extern "Rust" { + fn dstfn(src: i32, dst: err); + //~^ ERROR cannot find type `err` in this scope +} + +fn main() { + dstfn(1); + //~^ ERROR function takes 2 arguments but 1 argument was supplied +} diff --git a/tests/ui/argument-suggestions/extern-fn-arg-names.stderr b/tests/ui/argument-suggestions/extern-fn-arg-names.stderr new file mode 100644 index 000000000..f6bc84c12 --- /dev/null +++ b/tests/ui/argument-suggestions/extern-fn-arg-names.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `err` in this scope + --> $DIR/extern-fn-arg-names.rs:2:29 + | +LL | fn dstfn(src: i32, dst: err); + | ^^^ not found in this scope + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/extern-fn-arg-names.rs:7:5 + | +LL | dstfn(1); + | ^^^^^--- an argument is missing + | +note: function defined here + --> $DIR/extern-fn-arg-names.rs:2:8 + | +LL | fn dstfn(src: i32, dst: err); + | ^^^^^ +help: provide the argument + | +LL | dstfn(1, /* dst */); + | ~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0412. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/extra_arguments.rs b/tests/ui/argument-suggestions/extra_arguments.rs new file mode 100644 index 000000000..3f83de95e --- /dev/null +++ b/tests/ui/argument-suggestions/extra_arguments.rs @@ -0,0 +1,35 @@ +fn empty() {} +fn one_arg(_a: i32) {} +fn two_arg_same(_a: i32, _b: i32) {} +fn two_arg_diff(_a: i32, _b: &str) {} + +fn main() { + empty(""); //~ ERROR function takes + + one_arg(1, 1); //~ ERROR function takes + one_arg(1, ""); //~ ERROR function takes + one_arg(1, "", 1.0); //~ ERROR function takes + + two_arg_same(1, 1, 1); //~ ERROR function takes + two_arg_same(1, 1, 1.0); //~ ERROR function takes + + two_arg_diff(1, 1, ""); //~ ERROR function takes + two_arg_diff(1, "", ""); //~ ERROR function takes + two_arg_diff(1, 1, "", ""); //~ ERROR function takes + two_arg_diff(1, "", 1, ""); //~ ERROR function takes + + // Check with weird spacing and newlines + two_arg_same(1, 1, ""); //~ ERROR function takes + two_arg_diff(1, 1, ""); //~ ERROR function takes + two_arg_same( //~ ERROR function takes + 1, + 1, + "" + ); + + two_arg_diff( //~ ERROR function takes + 1, + 1, + "" + ); +} diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr new file mode 100644 index 000000000..48787b0c3 --- /dev/null +++ b/tests/ui/argument-suggestions/extra_arguments.stderr @@ -0,0 +1,239 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/extra_arguments.rs:7:3 + | +LL | empty(""); + | ^^^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:1:4 + | +LL | fn empty() {} + | ^^^^^ +help: remove the extra argument + | +LL | empty(); + | ~~ + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/extra_arguments.rs:9:3 + | +LL | one_arg(1, 1); + | ^^^^^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:2:4 + | +LL | fn one_arg(_a: i32) {} + | ^^^^^^^ ------- +help: remove the extra argument + | +LL | one_arg(1); + | ~~~ + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/extra_arguments.rs:10:3 + | +LL | one_arg(1, ""); + | ^^^^^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:2:4 + | +LL | fn one_arg(_a: i32) {} + | ^^^^^^^ ------- +help: remove the extra argument + | +LL | one_arg(1); + | ~~~ + +error[E0061]: this function takes 1 argument but 3 arguments were supplied + --> $DIR/extra_arguments.rs:11:3 + | +LL | one_arg(1, "", 1.0); + | ^^^^^^^ -- --- argument of type `{float}` unexpected + | | + | argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:2:4 + | +LL | fn one_arg(_a: i32) {} + | ^^^^^^^ ------- +help: remove the extra arguments + | +LL | one_arg(1); + | ~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:13:3 + | +LL | two_arg_same(1, 1, 1); + | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:3:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- ------- +help: remove the extra argument + | +LL | two_arg_same(1, 1); + | ~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:14:3 + | +LL | two_arg_same(1, 1, 1.0); + | ^^^^^^^^^^^^ --- argument of type `{float}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:3:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- ------- +help: remove the extra argument + | +LL | two_arg_same(1, 1); + | ~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:16:3 + | +LL | two_arg_diff(1, 1, ""); + | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:4:4 + | +LL | fn two_arg_diff(_a: i32, _b: &str) {} + | ^^^^^^^^^^^^ ------- -------- +help: remove the extra argument + | +LL | two_arg_diff(1, ""); + | ~~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:17:3 + | +LL | two_arg_diff(1, "", ""); + | ^^^^^^^^^^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:4:4 + | +LL | fn two_arg_diff(_a: i32, _b: &str) {} + | ^^^^^^^^^^^^ ------- -------- +help: remove the extra argument + | +LL | two_arg_diff(1, ""); + | ~~~~~~~ + +error[E0061]: this function takes 2 arguments but 4 arguments were supplied + --> $DIR/extra_arguments.rs:18:3 + | +LL | two_arg_diff(1, 1, "", ""); + | ^^^^^^^^^^^^ - -- argument of type `&'static str` unexpected + | | + | argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:4:4 + | +LL | fn two_arg_diff(_a: i32, _b: &str) {} + | ^^^^^^^^^^^^ ------- -------- +help: remove the extra arguments + | +LL | two_arg_diff(1, ""); + | ~~~~~~~ + +error[E0061]: this function takes 2 arguments but 4 arguments were supplied + --> $DIR/extra_arguments.rs:19:3 + | +LL | two_arg_diff(1, "", 1, ""); + | ^^^^^^^^^^^^ - -- argument of type `&'static str` unexpected + | | + | argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:4:4 + | +LL | fn two_arg_diff(_a: i32, _b: &str) {} + | ^^^^^^^^^^^^ ------- -------- +help: remove the extra arguments + | +LL | two_arg_diff(1, ""); + | ~~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:22:3 + | +LL | two_arg_same(1, 1, ""); + | ^^^^^^^^^^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:3:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- ------- +help: remove the extra argument + | +LL | two_arg_same(1, 1); + | ~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:23:3 + | +LL | two_arg_diff(1, 1, ""); + | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:4:4 + | +LL | fn two_arg_diff(_a: i32, _b: &str) {} + | ^^^^^^^^^^^^ ------- -------- +help: remove the extra argument + | +LL | two_arg_diff(1, ""); + | ~~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:24:3 + | +LL | two_arg_same( + | ^^^^^^^^^^^^ +... +LL | "" + | -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:3:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- ------- +help: remove the extra argument + | +LL | two_arg_same(1, 1); + | ~~~~~~ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/extra_arguments.rs:30:3 + | +LL | two_arg_diff( + | ^^^^^^^^^^^^ +LL | 1, +LL | 1, + | - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/extra_arguments.rs:4:4 + | +LL | fn two_arg_diff(_a: i32, _b: &str) {} + | ^^^^^^^^^^^^ ------- -------- +help: remove the extra argument + | +LL | two_arg_diff(1, ""); + | ~~~~~~~ + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/formal-and-expected-differ.rs b/tests/ui/argument-suggestions/formal-and-expected-differ.rs new file mode 100644 index 000000000..5e3b55ca5 --- /dev/null +++ b/tests/ui/argument-suggestions/formal-and-expected-differ.rs @@ -0,0 +1,25 @@ +pub trait Foo { + type T; +} + +impl Foo for i32 { + type T = f32; +} + +pub struct U(T1, S) +where + T1: Foo; + +pub struct S(T); + +fn main() { + // The error message here isn't great -- it has to do with the fact that the + // `expected_inputs_for_expected_output` deduced inputs differs from the inputs + // that we infer from the constraints of the signature. + // + // I am not really sure what the best way of presenting this error message is, + // since right now it just suggests changing `3u32` <=> `3f32` back and forth. + let _: U<_, u32> = U(1, S(3u32)); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/argument-suggestions/formal-and-expected-differ.stderr b/tests/ui/argument-suggestions/formal-and-expected-differ.stderr new file mode 100644 index 000000000..905875b52 --- /dev/null +++ b/tests/ui/argument-suggestions/formal-and-expected-differ.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/formal-and-expected-differ.rs:22:29 + | +LL | let _: U<_, u32> = U(1, S(3u32)); + | - ^^^^^^^ expected `f32`, found `u32` + | | + | arguments to this struct are incorrect + | + = note: expected struct `S` + found struct `S` +note: tuple struct defined here + --> $DIR/formal-and-expected-differ.rs:9:12 + | +LL | pub struct U(T1, S) + | ^ + +error[E0308]: mismatched types + --> $DIR/formal-and-expected-differ.rs:22:24 + | +LL | let _: U<_, u32> = U(1, S(3u32)); + | --------- ^^^^^^^^^^^^^ expected `u32`, found `f32` + | | + | expected due to this + | + = note: expected struct `U<_, u32>` + found struct `U` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/invalid_arguments.rs b/tests/ui/argument-suggestions/invalid_arguments.rs new file mode 100644 index 000000000..53fbdd4b5 --- /dev/null +++ b/tests/ui/argument-suggestions/invalid_arguments.rs @@ -0,0 +1,43 @@ +// More nuanced test cases for invalid arguments #65853 + +struct X {} + +fn one_arg(_a: i32) {} +fn two_arg_same(_a: i32, _b: i32) {} +fn two_arg_diff(_a: i32, _b: f32) {} +fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} +fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + +fn main() { + // Providing an incorrect argument for a single parameter function + one_arg(1.0); //~ ERROR mismatched types + + // Providing one or two invalid arguments to a two parameter function + two_arg_same(1, ""); //~ ERROR mismatched types + two_arg_same("", 1); //~ ERROR mismatched types + two_arg_same("", ""); //~ ERROR arguments to this function are incorrect + two_arg_diff(1, ""); //~ ERROR mismatched types + two_arg_diff("", 1.0); //~ ERROR mismatched types + two_arg_diff("", ""); //~ ERROR arguments to this function are incorrect + + // Providing invalid arguments to a three parameter function + three_arg_diff(X{}, 1.0, ""); //~ ERROR mismatched types + three_arg_diff(1, X {}, ""); //~ ERROR mismatched types + three_arg_diff(1, 1.0, X {}); //~ ERROR mismatched types + + three_arg_diff(X {}, X {}, ""); //~ ERROR arguments to this function are incorrect + three_arg_diff(X {}, 1.0, X {}); //~ ERROR arguments to this function are incorrect + three_arg_diff(1, X {}, X {}); //~ ERROR arguments to this function are incorrect + + three_arg_diff(X {}, X {}, X {}); //~ ERROR arguments to this function are incorrect + + three_arg_repeat(X {}, 1, ""); //~ ERROR mismatched types + three_arg_repeat(1, X {}, ""); //~ ERROR mismatched types + three_arg_repeat(1, 1, X {}); //~ ERROR mismatched types + + three_arg_repeat(X {}, X {}, ""); //~ ERROR arguments to this function are incorrect + three_arg_repeat(X {}, 1, X {}); //~ ERROR arguments to this function are incorrect + three_arg_repeat(1, X {}, X{}); //~ ERROR arguments to this function are incorrect + + three_arg_repeat(X {}, X {}, X {}); //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/argument-suggestions/invalid_arguments.stderr b/tests/ui/argument-suggestions/invalid_arguments.stderr new file mode 100644 index 000000000..303f08695 --- /dev/null +++ b/tests/ui/argument-suggestions/invalid_arguments.stderr @@ -0,0 +1,299 @@ +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:13:11 + | +LL | one_arg(1.0); + | ------- ^^^ expected `i32`, found floating-point number + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:5:4 + | +LL | fn one_arg(_a: i32) {} + | ^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:16:19 + | +LL | two_arg_same(1, ""); + | ------------ ^^ expected `i32`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:6:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:17:16 + | +LL | two_arg_same("", 1); + | ------------ ^^ expected `i32`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:6:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:18:3 + | +LL | two_arg_same("", ""); + | ^^^^^^^^^^^^ -- -- expected `i32`, found `&str` + | | + | expected `i32`, found `&str` + | +note: function defined here + --> $DIR/invalid_arguments.rs:6:4 + | +LL | fn two_arg_same(_a: i32, _b: i32) {} + | ^^^^^^^^^^^^ ------- ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:19:19 + | +LL | two_arg_diff(1, ""); + | ------------ ^^ expected `f32`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:7:4 + | +LL | fn two_arg_diff(_a: i32, _b: f32) {} + | ^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:20:16 + | +LL | two_arg_diff("", 1.0); + | ------------ ^^ expected `i32`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:7:4 + | +LL | fn two_arg_diff(_a: i32, _b: f32) {} + | ^^^^^^^^^^^^ ------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:21:3 + | +LL | two_arg_diff("", ""); + | ^^^^^^^^^^^^ -- -- expected `f32`, found `&str` + | | + | expected `i32`, found `&str` + | +note: function defined here + --> $DIR/invalid_arguments.rs:7:4 + | +LL | fn two_arg_diff(_a: i32, _b: f32) {} + | ^^^^^^^^^^^^ ------- ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:24:18 + | +LL | three_arg_diff(X{}, 1.0, ""); + | -------------- ^^^ expected `i32`, found struct `X` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:25:21 + | +LL | three_arg_diff(1, X {}, ""); + | -------------- ^^^^ expected `f32`, found struct `X` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:26:26 + | +LL | three_arg_diff(1, 1.0, X {}); + | -------------- ^^^^ expected `&str`, found struct `X` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:28:3 + | +LL | three_arg_diff(X {}, X {}, ""); + | ^^^^^^^^^^^^^^ ---- ---- expected `f32`, found struct `X` + | | + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:29:3 + | +LL | three_arg_diff(X {}, 1.0, X {}); + | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X` + | | + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:30:3 + | +LL | three_arg_diff(1, X {}, X {}); + | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X` + | | + | expected `f32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:32:3 + | +LL | three_arg_diff(X {}, X {}, X {}); + | ^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X` + | | | + | | expected `f32`, found struct `X` + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:8:4 + | +LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:34:20 + | +LL | three_arg_repeat(X {}, 1, ""); + | ---------------- ^^^^ expected `i32`, found struct `X` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:35:23 + | +LL | three_arg_repeat(1, X {}, ""); + | ---------------- ^^^^ expected `i32`, found struct `X` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/invalid_arguments.rs:36:26 + | +LL | three_arg_repeat(1, 1, X {}); + | ---------------- ^^^^ expected `&str`, found struct `X` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:38:3 + | +LL | three_arg_repeat(X {}, X {}, ""); + | ^^^^^^^^^^^^^^^^ ---- ---- expected `i32`, found struct `X` + | | + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:39:3 + | +LL | three_arg_repeat(X {}, 1, X {}); + | ^^^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X` + | | + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:40:3 + | +LL | three_arg_repeat(1, X {}, X{}); + | ^^^^^^^^^^^^^^^^ ---- --- expected `&str`, found struct `X` + | | + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ ------- ------- -------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/invalid_arguments.rs:42:3 + | +LL | three_arg_repeat(X {}, X {}, X {}); + | ^^^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X` + | | | + | | expected `i32`, found struct `X` + | expected `i32`, found struct `X` + | +note: function defined here + --> $DIR/invalid_arguments.rs:9:4 + | +LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {} + | ^^^^^^^^^^^^^^^^ ------- ------- -------- + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/issue-100154.rs b/tests/ui/argument-suggestions/issue-100154.rs new file mode 100644 index 000000000..fb0af05e9 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-100154.rs @@ -0,0 +1,7 @@ +fn foo(i: impl std::fmt::Display) {} + +fn main() { + foo::<()>(()); + //~^ ERROR function takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR `()` doesn't implement `std::fmt::Display` +} diff --git a/tests/ui/argument-suggestions/issue-100154.stderr b/tests/ui/argument-suggestions/issue-100154.stderr new file mode 100644 index 000000000..1499229c3 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-100154.stderr @@ -0,0 +1,35 @@ +error[E0107]: this function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-100154.rs:4:5 + | +LL | foo::<()>(()); + | ^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: function defined here, with 0 generic parameters + --> $DIR/issue-100154.rs:1:4 + | +LL | fn foo(i: impl std::fmt::Display) {} + | ^^^ + = note: `impl Trait` cannot be explicitly specified as a generic argument + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/issue-100154.rs:4:15 + | +LL | foo::<()>(()); + | --------- ^^ `()` cannot be formatted with the default formatter + | | + | required by a bound introduced by this call + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `foo` + --> $DIR/issue-100154.rs:1:16 + | +LL | fn foo(i: impl std::fmt::Display) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0277. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/argument-suggestions/issue-100478.rs b/tests/ui/argument-suggestions/issue-100478.rs new file mode 100644 index 000000000..fb50fa115 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-100478.rs @@ -0,0 +1,52 @@ +use std::sync::Arc; +macro_rules! GenT { + ($name:tt) => { + #[derive(Default, Debug)] + struct $name { + #[allow(unused)] + val: i32, + } + + impl $name { + #[allow(unused)] + fn new(val: i32) -> Self { + $name { val } + } + } + }; +} + +GenT!(T1); +GenT!(T2); +GenT!(T3); +GenT!(T4); +GenT!(T5); +GenT!(T6); +GenT!(T7); +GenT!(T8); + +#[allow(unused)] +fn foo(p1: T1, p2: Arc, p3: T3, p4: Arc, p5: T5, p6: T6, p7: T7, p8: Arc) {} +fn three_diff(_a: T1, _b: T2, _c: T3) {} +fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {} + +fn main() { + three_diff(T2::new(0)); //~ ERROR function takes + four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308] + four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308] + + let p1 = T1::new(0); + let p2 = Arc::new(T2::new(0)); + let p3 = T3::new(0); + let p4 = Arc::new(T4::new(1)); + let p5 = T5::new(0); + let p6 = T6::new(0); + let p7 = T7::new(0); + let p8 = Arc::default(); + + foo( + //~^ 47:5: 47:8: this function takes 8 arguments but 7 arguments were supplied [E0061] + p1, //p2, + p3, p4, p5, p6, p7, p8, + ); +} diff --git a/tests/ui/argument-suggestions/issue-100478.stderr b/tests/ui/argument-suggestions/issue-100478.stderr new file mode 100644 index 000000000..df02a312c --- /dev/null +++ b/tests/ui/argument-suggestions/issue-100478.stderr @@ -0,0 +1,81 @@ +error[E0061]: this function takes 3 arguments but 1 argument was supplied + --> $DIR/issue-100478.rs:34:5 + | +LL | three_diff(T2::new(0)); + | ^^^^^^^^^^------------ + | || + | |an argument of type `T1` is missing + | an argument of type `T3` is missing + | +note: function defined here + --> $DIR/issue-100478.rs:30:4 + | +LL | fn three_diff(_a: T1, _b: T2, _c: T3) {} + | ^^^^^^^^^^ ------ ------ ------ +help: provide the arguments + | +LL | three_diff(/* T1 */, T2::new(0), /* T3 */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/issue-100478.rs:35:5 + | +LL | four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); + | ^^^^^^^^^^^^ ------------- ------------- ------------- ------------- expected `T4`, found `T2` + | | | | + | | | expected `T3`, found `T1` + | | expected `T2`, found `T4` + | expected `T1`, found `T3` + | +note: function defined here + --> $DIR/issue-100478.rs:31:4 + | +LL | fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {} + | ^^^^^^^^^^^^ ------ ------ ------ ------ +help: did you mean + | +LL | four_shuffle(T1::default(), T2::default(), T3::default(), T4::default()); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/issue-100478.rs:36:5 + | +LL | four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); + | ^^^^^^^^^^^^ ------------- ------------- ------------- expected struct `T4`, found struct `T3` + | | | + | | expected `T3`, found `T1` + | expected `T1`, found `T3` + | +note: function defined here + --> $DIR/issue-100478.rs:31:4 + | +LL | fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {} + | ^^^^^^^^^^^^ ------ ------ ------ ------ +help: swap these arguments + | +LL | four_shuffle(T1::default(), T2::default(), T3::default(), /* T4 */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 8 arguments but 7 arguments were supplied + --> $DIR/issue-100478.rs:47:5 + | +LL | foo( + | ^^^ +... +LL | p3, p4, p5, p6, p7, p8, + | -- an argument of type `Arc` is missing + | +note: function defined here + --> $DIR/issue-100478.rs:29:4 + | +LL | fn foo(p1: T1, p2: Arc, p3: T3, p4: Arc, p5: T5, p6: T6, p7: T7, p8: Arc) {} + | ^^^ ------ ----------- ------ ----------- ------ ------ ------ ----------- +help: provide the argument + | +LL | foo(p1, /* Arc */, p3, p4, p5, p6, p7, p8); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-101097.rs b/tests/ui/argument-suggestions/issue-101097.rs new file mode 100644 index 000000000..25f7f5837 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-101097.rs @@ -0,0 +1,21 @@ +struct A; +struct B; +struct C; +struct D; + +fn f( + a1: A, + a2: A, + b1: B, + b2: B, + c1: C, + c2: C, +) {} + +fn main() { + f(C, A, A, A, B, B, C); //~ ERROR function takes 6 arguments but 7 arguments were supplied [E0061] + f(C, C, A, A, B, B); //~ ERROR arguments to this function are incorrect [E0308] + f(A, A, D, D, B, B); //~ arguments to this function are incorrect [E0308] + f(C, C, B, B, A, A); //~ arguments to this function are incorrect [E0308] + f(C, C, A, B, A, A); //~ arguments to this function are incorrect [E0308] +} diff --git a/tests/ui/argument-suggestions/issue-101097.stderr b/tests/ui/argument-suggestions/issue-101097.stderr new file mode 100644 index 000000000..096f8c226 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-101097.stderr @@ -0,0 +1,160 @@ +error[E0061]: this function takes 6 arguments but 7 arguments were supplied + --> $DIR/issue-101097.rs:16:5 + | +LL | f(C, A, A, A, B, B, C); + | ^ - - - - expected `C`, found `B` + | | | | + | | | argument of type `A` unexpected + | | expected `B`, found `A` + | expected `A`, found `C` + | +note: function defined here + --> $DIR/issue-101097.rs:6:4 + | +LL | fn f( + | ^ +LL | a1: A, + | ----- +LL | a2: A, + | ----- +LL | b1: B, + | ----- +LL | b2: B, + | ----- +LL | c1: C, + | ----- +LL | c2: C, + | ----- +help: did you mean + | +LL | f(A, A, B, B, C, C); + | ~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/issue-101097.rs:17:5 + | +LL | f(C, C, A, A, B, B); + | ^ + | +note: function defined here + --> $DIR/issue-101097.rs:6:4 + | +LL | fn f( + | ^ +LL | a1: A, + | ----- +LL | a2: A, + | ----- +LL | b1: B, + | ----- +LL | b2: B, + | ----- +LL | c1: C, + | ----- +LL | c2: C, + | ----- +help: did you mean + | +LL | f(A, A, B, B, C, C); + | ~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/issue-101097.rs:18:5 + | +LL | f(A, A, D, D, B, B); + | ^ - - ---- two arguments of type `C` and `C` are missing + | | | + | | argument of type `D` unexpected + | argument of type `D` unexpected + | +note: function defined here + --> $DIR/issue-101097.rs:6:4 + | +LL | fn f( + | ^ +LL | a1: A, + | ----- +LL | a2: A, + | ----- +LL | b1: B, + | ----- +LL | b2: B, + | ----- +LL | c1: C, + | ----- +LL | c2: C, + | ----- +help: did you mean + | +LL | f(A, A, B, B, /* C */, /* C */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/issue-101097.rs:19:5 + | +LL | f(C, C, B, B, A, A); + | ^ - - - - expected `C`, found `A` + | | | | + | | | expected `C`, found `A` + | | expected `A`, found `C` + | expected `A`, found `C` + | +note: function defined here + --> $DIR/issue-101097.rs:6:4 + | +LL | fn f( + | ^ +LL | a1: A, + | ----- +LL | a2: A, + | ----- +LL | b1: B, + | ----- +LL | b2: B, + | ----- +LL | c1: C, + | ----- +LL | c2: C, + | ----- +help: did you mean + | +LL | f(A, A, B, B, C, C); + | ~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/issue-101097.rs:20:5 + | +LL | f(C, C, A, B, A, A); + | ^ - - - - - expected `C`, found `A` + | | | | | + | | | | expected `C`, found `A` + | | | expected struct `B`, found struct `A` + | | expected `A`, found `C` + | expected `A`, found `C` + | +note: function defined here + --> $DIR/issue-101097.rs:6:4 + | +LL | fn f( + | ^ +LL | a1: A, + | ----- +LL | a2: A, + | ----- +LL | b1: B, + | ----- +LL | b2: B, + | ----- +LL | c1: C, + | ----- +LL | c2: C, + | ----- +help: did you mean + | +LL | f(A, A, /* B */, B, C, C); + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-96638.rs b/tests/ui/argument-suggestions/issue-96638.rs new file mode 100644 index 000000000..5e720f174 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-96638.rs @@ -0,0 +1,9 @@ +fn f(_: usize, _: &usize, _: usize) {} + +fn arg() -> T { todo!() } + +fn main() { + let x = arg(); // `x` must be inferred + // The reference on `&x` is important to reproduce the ICE + f(&x, ""); //~ ERROR function takes 3 arguments but 2 arguments were supplied +} diff --git a/tests/ui/argument-suggestions/issue-96638.stderr b/tests/ui/argument-suggestions/issue-96638.stderr new file mode 100644 index 000000000..4d18b97c9 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-96638.stderr @@ -0,0 +1,21 @@ +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/issue-96638.rs:8:5 + | +LL | f(&x, ""); + | ^ -- -- expected `usize`, found `&str` + | | + | an argument of type `usize` is missing + | +note: function defined here + --> $DIR/issue-96638.rs:1:4 + | +LL | fn f(_: usize, _: &usize, _: usize) {} + | ^ -------- --------- -------- +help: provide the argument + | +LL | f(/* usize */, &x, /* usize */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-97197.rs b/tests/ui/argument-suggestions/issue-97197.rs new file mode 100644 index 000000000..4c22608ae --- /dev/null +++ b/tests/ui/argument-suggestions/issue-97197.rs @@ -0,0 +1,6 @@ +fn main() { + g((), ()); + //~^ ERROR function takes 6 arguments but 2 arguments were supplied +} + +pub fn g(a1: (), a2: bool, a3: bool, a4: bool, a5: bool, a6: ()) -> () {} diff --git a/tests/ui/argument-suggestions/issue-97197.stderr b/tests/ui/argument-suggestions/issue-97197.stderr new file mode 100644 index 000000000..de221ba1f --- /dev/null +++ b/tests/ui/argument-suggestions/issue-97197.stderr @@ -0,0 +1,19 @@ +error[E0061]: this function takes 6 arguments but 2 arguments were supplied + --> $DIR/issue-97197.rs:2:5 + | +LL | g((), ()); + | ^-------- multiple arguments are missing + | +note: function defined here + --> $DIR/issue-97197.rs:6:8 + | +LL | pub fn g(a1: (), a2: bool, a3: bool, a4: bool, a5: bool, a6: ()) -> () {} + | ^ ------ -------- -------- -------- -------- ------ +help: provide the arguments + | +LL | g((), /* bool */, /* bool */, /* bool */, /* bool */, ()); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-97484.rs b/tests/ui/argument-suggestions/issue-97484.rs new file mode 100644 index 000000000..9e537b0c3 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-97484.rs @@ -0,0 +1,14 @@ +struct A; +struct B; +struct C; +struct D; +struct E; +struct F; +struct G; + +fn foo(a: &A, d: D, e: &E, g: G) {} + +fn main() { + foo(&&A, B, C, D, E, F, G); + //~^ ERROR function takes 4 arguments but 7 arguments were supplied +} diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr new file mode 100644 index 000000000..caa50f14b --- /dev/null +++ b/tests/ui/argument-suggestions/issue-97484.stderr @@ -0,0 +1,27 @@ +error[E0061]: this function takes 4 arguments but 7 arguments were supplied + --> $DIR/issue-97484.rs:12:5 + | +LL | foo(&&A, B, C, D, E, F, G); + | ^^^ - - - - argument of type `F` unexpected + | | | | + | | | expected `&E`, found struct `E` + | | argument of type `C` unexpected + | argument of type `B` unexpected + | +note: function defined here + --> $DIR/issue-97484.rs:9:4 + | +LL | fn foo(a: &A, d: D, e: &E, g: G) {} + | ^^^ ----- ---- ----- ---- +help: consider borrowing here + | +LL | foo(&&A, B, C, D, &E, F, G); + | ~~ +help: remove the extra arguments + | +LL | foo(&&A, D, /* &E */, G); + | ~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/issue-98894.rs b/tests/ui/argument-suggestions/issue-98894.rs new file mode 100644 index 000000000..e421eba97 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-98894.rs @@ -0,0 +1,4 @@ +fn main() { + (|_, ()| ())(if true {} else {return;}); + //~^ ERROR function takes 2 arguments but 1 argument was supplied +} diff --git a/tests/ui/argument-suggestions/issue-98894.stderr b/tests/ui/argument-suggestions/issue-98894.stderr new file mode 100644 index 000000000..f64a83ab7 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-98894.stderr @@ -0,0 +1,19 @@ +error[E0057]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/issue-98894.rs:2:5 + | +LL | (|_, ()| ())(if true {} else {return;}); + | ^^^^^^^^^^^^--------------------------- an argument of type `()` is missing + | +note: closure defined here + --> $DIR/issue-98894.rs:2:6 + | +LL | (|_, ()| ())(if true {} else {return;}); + | ^^^^^^^ +help: provide the argument + | +LL | (|_, ()| ())(if true {} else {return;}, ()); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/issue-98897.rs b/tests/ui/argument-suggestions/issue-98897.rs new file mode 100644 index 000000000..27734f74d --- /dev/null +++ b/tests/ui/argument-suggestions/issue-98897.rs @@ -0,0 +1,4 @@ +fn main() { + (|_, ()| ())([return, ()]); + //~^ ERROR function takes 2 arguments but 1 argument was supplied +} diff --git a/tests/ui/argument-suggestions/issue-98897.stderr b/tests/ui/argument-suggestions/issue-98897.stderr new file mode 100644 index 000000000..f2c47d353 --- /dev/null +++ b/tests/ui/argument-suggestions/issue-98897.stderr @@ -0,0 +1,19 @@ +error[E0057]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/issue-98897.rs:2:5 + | +LL | (|_, ()| ())([return, ()]); + | ^^^^^^^^^^^^-------------- an argument of type `()` is missing + | +note: closure defined here + --> $DIR/issue-98897.rs:2:6 + | +LL | (|_, ()| ())([return, ()]); + | ^^^^^^^ +help: provide the argument + | +LL | (|_, ()| ())([return, ()], ()); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/issue-99482.rs b/tests/ui/argument-suggestions/issue-99482.rs new file mode 100644 index 000000000..7bbb39f8d --- /dev/null +++ b/tests/ui/argument-suggestions/issue-99482.rs @@ -0,0 +1,5 @@ +fn main() { + let f = |_: (), f: fn()| f; + let _f = f(main); + //~^ ERROR function takes 2 arguments but 1 argument was supplied +} diff --git a/tests/ui/argument-suggestions/issue-99482.stderr b/tests/ui/argument-suggestions/issue-99482.stderr new file mode 100644 index 000000000..bcf36e37c --- /dev/null +++ b/tests/ui/argument-suggestions/issue-99482.stderr @@ -0,0 +1,19 @@ +error[E0057]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/issue-99482.rs:3:14 + | +LL | let _f = f(main); + | ^ ---- an argument of type `()` is missing + | +note: closure defined here + --> $DIR/issue-99482.rs:2:13 + | +LL | let f = |_: (), f: fn()| f; + | ^^^^^^^^^^^^^^^^ +help: provide the argument + | +LL | let _f = f((), main); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/argument-suggestions/missing_arguments.rs b/tests/ui/argument-suggestions/missing_arguments.rs new file mode 100644 index 000000000..c26564641 --- /dev/null +++ b/tests/ui/argument-suggestions/missing_arguments.rs @@ -0,0 +1,40 @@ +fn one_arg(_a: i32) {} +fn two_same(_a: i32, _b: i32) {} +fn two_diff(_a: i32, _b: f32) {} +fn three_same(_a: i32, _b: i32, _c: i32) {} +fn three_diff(_a: i32, _b: f32, _c: &str) {} +fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {} +fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {} + +fn main() { + one_arg(); //~ ERROR function takes + // The headers here show the types expected, + // with formatting to emphasize which arguments are missing + /* i32 f32 */ + two_same( ); //~ ERROR function takes + two_same( 1 ); //~ ERROR function takes + two_diff( ); //~ ERROR function takes + two_diff( 1 ); //~ ERROR function takes + two_diff( 1.0 ); //~ ERROR function takes + + /* i32 i32 i32 */ + three_same( ); //~ ERROR function takes + three_same( 1 ); //~ ERROR function takes + three_same( 1, 1 ); //~ ERROR function takes + + /* i32 f32 &str */ + three_diff( 1.0, "" ); //~ ERROR function takes + three_diff( 1, "" ); //~ ERROR function takes + three_diff( 1, 1.0 ); //~ ERROR function takes + three_diff( "" ); //~ ERROR function takes + three_diff( 1.0 ); //~ ERROR function takes + three_diff( 1 ); //~ ERROR function takes + + /* i32 f32 f32 &str */ + four_repeated( ); //~ ERROR function takes + four_repeated( 1, "" ); //~ ERROR function takes + + /* i32 f32 i32 f32 &str */ + complex( ); //~ ERROR function takes + complex( 1, "" ); //~ ERROR function takes +} diff --git a/tests/ui/argument-suggestions/missing_arguments.stderr b/tests/ui/argument-suggestions/missing_arguments.stderr new file mode 100644 index 000000000..ba9ece040 --- /dev/null +++ b/tests/ui/argument-suggestions/missing_arguments.stderr @@ -0,0 +1,310 @@ +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/missing_arguments.rs:10:3 + | +LL | one_arg(); + | ^^^^^^^-- an argument of type `i32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:1:4 + | +LL | fn one_arg(_a: i32) {} + | ^^^^^^^ ------- +help: provide the argument + | +LL | one_arg(/* i32 */); + | ~~~~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 0 arguments were supplied + --> $DIR/missing_arguments.rs:14:3 + | +LL | two_same( ); + | ^^^^^^^^----------------- two arguments of type `i32` and `i32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:2:4 + | +LL | fn two_same(_a: i32, _b: i32) {} + | ^^^^^^^^ ------- ------- +help: provide the arguments + | +LL | two_same(/* i32 */, /* i32 */); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:15:3 + | +LL | two_same( 1 ); + | ^^^^^^^^----------------- an argument of type `i32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:2:4 + | +LL | fn two_same(_a: i32, _b: i32) {} + | ^^^^^^^^ ------- ------- +help: provide the argument + | +LL | two_same(1, /* i32 */); + | ~~~~~~~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 0 arguments were supplied + --> $DIR/missing_arguments.rs:16:3 + | +LL | two_diff( ); + | ^^^^^^^^----------------- two arguments of type `i32` and `f32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:3:4 + | +LL | fn two_diff(_a: i32, _b: f32) {} + | ^^^^^^^^ ------- ------- +help: provide the arguments + | +LL | two_diff(/* i32 */, /* f32 */); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:17:3 + | +LL | two_diff( 1 ); + | ^^^^^^^^----------------- an argument of type `f32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:3:4 + | +LL | fn two_diff(_a: i32, _b: f32) {} + | ^^^^^^^^ ------- ------- +help: provide the argument + | +LL | two_diff(1, /* f32 */); + | ~~~~~~~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:18:3 + | +LL | two_diff( 1.0 ); + | ^^^^^^^^ --- an argument of type `i32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:3:4 + | +LL | fn two_diff(_a: i32, _b: f32) {} + | ^^^^^^^^ ------- ------- +help: provide the argument + | +LL | two_diff(/* i32 */, 1.0); + | ~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 0 arguments were supplied + --> $DIR/missing_arguments.rs:21:3 + | +LL | three_same( ); + | ^^^^^^^^^^------------------------- three arguments of type `i32`, `i32`, and `i32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:4:4 + | +LL | fn three_same(_a: i32, _b: i32, _c: i32) {} + | ^^^^^^^^^^ ------- ------- ------- +help: provide the arguments + | +LL | three_same(/* i32 */, /* i32 */, /* i32 */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:22:3 + | +LL | three_same( 1 ); + | ^^^^^^^^^^------------------------- two arguments of type `i32` and `i32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:4:4 + | +LL | fn three_same(_a: i32, _b: i32, _c: i32) {} + | ^^^^^^^^^^ ------- ------- ------- +help: provide the arguments + | +LL | three_same(1, /* i32 */, /* i32 */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/missing_arguments.rs:23:3 + | +LL | three_same( 1, 1 ); + | ^^^^^^^^^^------------------------- an argument of type `i32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:4:4 + | +LL | fn three_same(_a: i32, _b: i32, _c: i32) {} + | ^^^^^^^^^^ ------- ------- ------- +help: provide the argument + | +LL | three_same(1, 1, /* i32 */); + | ~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/missing_arguments.rs:26:3 + | +LL | three_diff( 1.0, "" ); + | ^^^^^^^^^^ --- an argument of type `i32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:5:4 + | +LL | fn three_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the argument + | +LL | three_diff(/* i32 */, 1.0, ""); + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/missing_arguments.rs:27:3 + | +LL | three_diff( 1, "" ); + | ^^^^^^^^^^ -- an argument of type `f32` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:5:4 + | +LL | fn three_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the argument + | +LL | three_diff(1, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/missing_arguments.rs:28:3 + | +LL | three_diff( 1, 1.0 ); + | ^^^^^^^^^^------------------------- an argument of type `&str` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:5:4 + | +LL | fn three_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the argument + | +LL | three_diff(1, 1.0, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:29:3 + | +LL | three_diff( "" ); + | ^^^^^^^^^^------------------------- two arguments of type `i32` and `f32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:5:4 + | +LL | fn three_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the arguments + | +LL | three_diff(/* i32 */, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:30:3 + | +LL | three_diff( 1.0 ); + | ^^^^^^^^^^------------------------- + | | | + | | an argument of type `i32` is missing + | an argument of type `&str` is missing + | +note: function defined here + --> $DIR/missing_arguments.rs:5:4 + | +LL | fn three_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the arguments + | +LL | three_diff(/* i32 */, 1.0, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 1 argument was supplied + --> $DIR/missing_arguments.rs:31:3 + | +LL | three_diff( 1 ); + | ^^^^^^^^^^------------------------- two arguments of type `f32` and `&str` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:5:4 + | +LL | fn three_diff(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the arguments + | +LL | three_diff(1, /* f32 */, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 4 arguments but 0 arguments were supplied + --> $DIR/missing_arguments.rs:34:3 + | +LL | four_repeated( ); + | ^^^^^^^^^^^^^--------------------------------- multiple arguments are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:6:4 + | +LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {} + | ^^^^^^^^^^^^^ ------- ------- ------- -------- +help: provide the arguments + | +LL | four_repeated(/* i32 */, /* f32 */, /* f32 */, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 4 arguments but 2 arguments were supplied + --> $DIR/missing_arguments.rs:35:3 + | +LL | four_repeated( 1, "" ); + | ^^^^^^^^^^^^^--------------------------------- two arguments of type `f32` and `f32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:6:4 + | +LL | fn four_repeated(_a: i32, _b: f32, _c: f32, _d: &str) {} + | ^^^^^^^^^^^^^ ------- ------- ------- -------- +help: provide the arguments + | +LL | four_repeated(1, /* f32 */, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 5 arguments but 0 arguments were supplied + --> $DIR/missing_arguments.rs:38:3 + | +LL | complex( ); + | ^^^^^^^--------------------------------- multiple arguments are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:7:4 + | +LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {} + | ^^^^^^^ ------- ------- ------- ------- -------- +help: provide the arguments + | +LL | complex(/* i32 */, /* f32 */, /* i32 */, /* f32 */, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 5 arguments but 2 arguments were supplied + --> $DIR/missing_arguments.rs:39:3 + | +LL | complex( 1, "" ); + | ^^^^^^^--------------------------------- three arguments of type `f32`, `i32`, and `f32` are missing + | +note: function defined here + --> $DIR/missing_arguments.rs:7:4 + | +LL | fn complex(_a: i32, _b: f32, _c: i32, _d: f32, _e: &str) {} + | ^^^^^^^ ------- ------- ------- ------- -------- +help: provide the arguments + | +LL | complex(1, /* f32 */, /* i32 */, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 19 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/mixed_cases.rs b/tests/ui/argument-suggestions/mixed_cases.rs new file mode 100644 index 000000000..86e94a438 --- /dev/null +++ b/tests/ui/argument-suggestions/mixed_cases.rs @@ -0,0 +1,24 @@ +// Cases where multiple argument suggestions are mixed + +struct X {} + +fn two_args(_a: i32, _b: f32) {} +fn three_args(_a: i32, _b: f32, _c: &str) {} + +fn main() { + // Extra + Invalid + two_args(1, "", X {}); //~ ERROR function takes + three_args(1, "", X {}, ""); //~ ERROR function takes + + // Missing and Invalid + three_args(1, X {}); //~ ERROR function takes + + // Missing and Extra + three_args(1, "", X {}); //~ ERROR arguments to this function are incorrect + + // Swapped and Invalid + three_args("", X {}, 1); //~ ERROR arguments to this function are incorrect + + // Swapped and missing + three_args("", 1); //~ ERROR function takes +} diff --git a/tests/ui/argument-suggestions/mixed_cases.stderr b/tests/ui/argument-suggestions/mixed_cases.stderr new file mode 100644 index 000000000..8c525db1a --- /dev/null +++ b/tests/ui/argument-suggestions/mixed_cases.stderr @@ -0,0 +1,117 @@ +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/mixed_cases.rs:10:3 + | +LL | two_args(1, "", X {}); + | ^^^^^^^^ -- ---- argument of type `X` unexpected + | | + | expected `f32`, found `&str` + | +note: function defined here + --> $DIR/mixed_cases.rs:5:4 + | +LL | fn two_args(_a: i32, _b: f32) {} + | ^^^^^^^^ ------- ------- +help: remove the extra argument + | +LL | two_args(1, /* f32 */); + | ~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 4 arguments were supplied + --> $DIR/mixed_cases.rs:11:3 + | +LL | three_args(1, "", X {}, ""); + | ^^^^^^^^^^ -- ---- -- argument of type `&'static str` unexpected + | | | + | | argument of type `X` unexpected + | an argument of type `f32` is missing + | +note: function defined here + --> $DIR/mixed_cases.rs:6:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: did you mean + | +LL | three_args(1, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/mixed_cases.rs:14:3 + | +LL | three_args(1, X {}); + | ^^^^^^^^^^--------- + | | | + | | expected `f32`, found struct `X` + | an argument of type `&str` is missing + | +note: function defined here + --> $DIR/mixed_cases.rs:6:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: provide the argument + | +LL | three_args(1, /* f32 */, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/mixed_cases.rs:17:3 + | +LL | three_args(1, "", X {}); + | ^^^^^^^^^^ -- ---- argument of type `X` unexpected + | | + | an argument of type `f32` is missing + | +note: function defined here + --> $DIR/mixed_cases.rs:6:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: did you mean + | +LL | three_args(1, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/mixed_cases.rs:20:3 + | +LL | three_args("", X {}, 1); + | ^^^^^^^^^^ -- ---- - expected `&str`, found `{integer}` + | | | + | | expected `f32`, found struct `X` + | expected `i32`, found `&'static str` + | +note: function defined here + --> $DIR/mixed_cases.rs:6:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: swap these arguments + | +LL | three_args(1, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 3 arguments but 2 arguments were supplied + --> $DIR/mixed_cases.rs:23:3 + | +LL | three_args("", 1); + | ^^^^^^^^^^ -- - + | | | + | | an argument of type `f32` is missing + | | expected `&str`, found `{integer}` + | expected `i32`, found `&'static str` + | +note: function defined here + --> $DIR/mixed_cases.rs:6:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: did you mean + | +LL | three_args(1, /* f32 */, ""); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/argument-suggestions/permuted_arguments.rs b/tests/ui/argument-suggestions/permuted_arguments.rs new file mode 100644 index 000000000..f512fde65 --- /dev/null +++ b/tests/ui/argument-suggestions/permuted_arguments.rs @@ -0,0 +1,13 @@ +// More complicated permutations +struct X {} +struct Y {} + +fn three_args(_a: i32, _b: f32, _c: &str) {} +fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {} + +fn main() { + // b, c, a + three_args(1.0, "", 1); //~ ERROR arguments to this function are incorrect + // d, e, b, a, c + many_args(X {}, Y {}, 1, 1.0, ""); //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/argument-suggestions/permuted_arguments.stderr b/tests/ui/argument-suggestions/permuted_arguments.stderr new file mode 100644 index 000000000..655807a7f --- /dev/null +++ b/tests/ui/argument-suggestions/permuted_arguments.stderr @@ -0,0 +1,43 @@ +error[E0308]: arguments to this function are incorrect + --> $DIR/permuted_arguments.rs:10:3 + | +LL | three_args(1.0, "", 1); + | ^^^^^^^^^^ --- -- - expected `&str`, found `{integer}` + | | | + | | expected `f32`, found `&'static str` + | expected `i32`, found `{float}` + | +note: function defined here + --> $DIR/permuted_arguments.rs:5:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: reorder these arguments + | +LL | three_args(1, 1.0, ""); + | ~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/permuted_arguments.rs:12:3 + | +LL | many_args(X {}, Y {}, 1, 1.0, ""); + | ^^^^^^^^^ ---- ---- - --- -- expected `Y`, found `&'static str` + | | | | | + | | | | expected `X`, found `{float}` + | | | expected `&str`, found `{integer}` + | | expected `f32`, found `Y` + | expected `i32`, found `X` + | +note: function defined here + --> $DIR/permuted_arguments.rs:6:4 + | +LL | fn many_args(_a: i32, _b: f32, _c: &str, _d: X, _e: Y) {} + | ^^^^^^^^^ ------- ------- -------- ----- ----- +help: reorder these arguments + | +LL | many_args(1, 1.0, "", X {}, Y {}); + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/swapped_arguments.rs b/tests/ui/argument-suggestions/swapped_arguments.rs new file mode 100644 index 000000000..a21de610c --- /dev/null +++ b/tests/ui/argument-suggestions/swapped_arguments.rs @@ -0,0 +1,14 @@ +struct X {} + +fn two_args(_a: i32, _b: f32) {} +fn three_args(_a: i32, _b: f32, _c: &str) {} +fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {} + +fn main() { + two_args(1.0, 1); //~ ERROR arguments to this function are incorrect + three_args(1.0, 1, ""); //~ ERROR arguments to this function are incorrect + three_args( 1, "", 1.0); //~ ERROR arguments to this function are incorrect + three_args( "", 1.0, 1); //~ ERROR arguments to this function are incorrect + + four_args(1.0, 1, X {}, ""); //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/argument-suggestions/swapped_arguments.stderr b/tests/ui/argument-suggestions/swapped_arguments.stderr new file mode 100644 index 000000000..dabf5e952 --- /dev/null +++ b/tests/ui/argument-suggestions/swapped_arguments.stderr @@ -0,0 +1,95 @@ +error[E0308]: arguments to this function are incorrect + --> $DIR/swapped_arguments.rs:8:3 + | +LL | two_args(1.0, 1); + | ^^^^^^^^ --- - expected `f32`, found `{integer}` + | | + | expected `i32`, found `{float}` + | +note: function defined here + --> $DIR/swapped_arguments.rs:3:4 + | +LL | fn two_args(_a: i32, _b: f32) {} + | ^^^^^^^^ ------- ------- +help: swap these arguments + | +LL | two_args(1, 1.0); + | ~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/swapped_arguments.rs:9:3 + | +LL | three_args(1.0, 1, ""); + | ^^^^^^^^^^ --- - expected `f32`, found `{integer}` + | | + | expected `i32`, found `{float}` + | +note: function defined here + --> $DIR/swapped_arguments.rs:4:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: swap these arguments + | +LL | three_args(1, 1.0, ""); + | ~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/swapped_arguments.rs:10:3 + | +LL | three_args( 1, "", 1.0); + | ^^^^^^^^^^ -- --- expected `&str`, found `{float}` + | | + | expected `f32`, found `&'static str` + | +note: function defined here + --> $DIR/swapped_arguments.rs:4:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: swap these arguments + | +LL | three_args(1, 1.0, ""); + | ~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/swapped_arguments.rs:11:3 + | +LL | three_args( "", 1.0, 1); + | ^^^^^^^^^^ -- - expected `&str`, found `{integer}` + | | + | expected `i32`, found `&'static str` + | +note: function defined here + --> $DIR/swapped_arguments.rs:4:4 + | +LL | fn three_args(_a: i32, _b: f32, _c: &str) {} + | ^^^^^^^^^^ ------- ------- -------- +help: swap these arguments + | +LL | three_args(1, 1.0, ""); + | ~~~~~~~~~~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/swapped_arguments.rs:13:3 + | +LL | four_args(1.0, 1, X {}, ""); + | ^^^^^^^^^ --- - ---- -- expected `X`, found `&'static str` + | | | | + | | | expected `&str`, found `X` + | | expected `f32`, found `{integer}` + | expected `i32`, found `{float}` + | +note: function defined here + --> $DIR/swapped_arguments.rs:5:4 + | +LL | fn four_args(_a: i32, _b: f32, _c: &str, _d: X) {} + | ^^^^^^^^^ ------- ------- -------- ----- +help: did you mean + | +LL | four_args(1, 1.0, "", X {}); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/too-long.rs b/tests/ui/argument-suggestions/too-long.rs new file mode 100644 index 000000000..7ec56afae --- /dev/null +++ b/tests/ui/argument-suggestions/too-long.rs @@ -0,0 +1,41 @@ +struct Qux; + +impl Qux { + fn foo( + &self, + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, + l: i32, + ) { + } +} + +fn what( + qux: &Qux, + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: &i32, + g: i32, + h: i32, + i: i32, + j: i32, + k: i32, + l: i32, +) { + qux.foo(a, b, c, d, e, f, g, h, i, j, k, l); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/argument-suggestions/too-long.stderr b/tests/ui/argument-suggestions/too-long.stderr new file mode 100644 index 000000000..492894329 --- /dev/null +++ b/tests/ui/argument-suggestions/too-long.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/too-long.rs:37:28 + | +LL | qux.foo(a, b, c, d, e, f, g, h, i, j, k, l); + | --- ^ expected `i32`, found `&i32` + | | + | arguments to this method are incorrect + | +note: associated function defined here + --> $DIR/too-long.rs:4:8 + | +LL | fn foo( + | ^^^ +... +LL | f: i32, + | ------ +help: consider dereferencing the borrow + | +LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/argument-suggestions/two-mismatch-notes.rs b/tests/ui/argument-suggestions/two-mismatch-notes.rs new file mode 100644 index 000000000..1309041ab --- /dev/null +++ b/tests/ui/argument-suggestions/two-mismatch-notes.rs @@ -0,0 +1,11 @@ +#[derive(Copy, Clone)] +struct Wrapper(T); + +fn foo(_: fn(i32), _: Wrapper) {} + +fn f(_: u32) {} + +fn main() { + let w = Wrapper::(1isize); + foo(f, w); //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/argument-suggestions/two-mismatch-notes.stderr b/tests/ui/argument-suggestions/two-mismatch-notes.stderr new file mode 100644 index 000000000..7873cf964 --- /dev/null +++ b/tests/ui/argument-suggestions/two-mismatch-notes.stderr @@ -0,0 +1,29 @@ +error[E0308]: arguments to this function are incorrect + --> $DIR/two-mismatch-notes.rs:10:5 + | +LL | foo(f, w); + | ^^^ + | +note: expected `i32`, found `u32` + --> $DIR/two-mismatch-notes.rs:10:9 + | +LL | foo(f, w); + | ^ + = note: expected fn pointer `fn(i32)` + found fn item `fn(u32) {f}` +note: expected `i32`, found `isize` + --> $DIR/two-mismatch-notes.rs:10:12 + | +LL | foo(f, w); + | ^ + = note: expected struct `Wrapper` + found struct `Wrapper` +note: function defined here + --> $DIR/two-mismatch-notes.rs:4:4 + | +LL | fn foo(_: fn(i32), _: Wrapper) {} + | ^^^ ---------- --------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/array-break-length.rs b/tests/ui/array-slice-vec/array-break-length.rs new file mode 100644 index 000000000..60589f7c2 --- /dev/null +++ b/tests/ui/array-slice-vec/array-break-length.rs @@ -0,0 +1,9 @@ +fn main() { + loop { + |_: [_; break]| {} //~ ERROR: `break` outside of a loop + } + + loop { + |_: [_; continue]| {} //~ ERROR: `continue` outside of a loop + } +} diff --git a/tests/ui/array-slice-vec/array-break-length.stderr b/tests/ui/array-slice-vec/array-break-length.stderr new file mode 100644 index 000000000..2df7b6d7f --- /dev/null +++ b/tests/ui/array-slice-vec/array-break-length.stderr @@ -0,0 +1,15 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/array-break-length.rs:3:17 + | +LL | |_: [_; break]| {} + | ^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `continue` outside of a loop + --> $DIR/array-break-length.rs:7:17 + | +LL | |_: [_; continue]| {} + | ^^^^^^^^ cannot `continue` outside of a loop + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/array-slice-vec/array-not-vector.rs b/tests/ui/array-slice-vec/array-not-vector.rs new file mode 100644 index 000000000..5e46f015b --- /dev/null +++ b/tests/ui/array-slice-vec/array-not-vector.rs @@ -0,0 +1,12 @@ +fn main() { + let _x: i32 = [1, 2, 3]; + //~^ ERROR mismatched types + //~| expected `i32`, found array + + let x: &[i32] = &[1, 2, 3]; + let _y: &i32 = x; + //~^ ERROR mismatched types + //~| expected reference `&i32` + //~| found reference `&[i32]` + //~| expected `i32`, found slice +} diff --git a/tests/ui/array-slice-vec/array-not-vector.stderr b/tests/ui/array-slice-vec/array-not-vector.stderr new file mode 100644 index 000000000..0e187d907 --- /dev/null +++ b/tests/ui/array-slice-vec/array-not-vector.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/array-not-vector.rs:2:19 + | +LL | let _x: i32 = [1, 2, 3]; + | --- ^^^^^^^^^ expected `i32`, found array `[{integer}; 3]` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/array-not-vector.rs:7:20 + | +LL | let _y: &i32 = x; + | ---- ^ expected `i32`, found slice `[i32]` + | | + | expected due to this + | + = note: expected reference `&i32` + found reference `&[i32]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/array_const_index-0.rs b/tests/ui/array-slice-vec/array_const_index-0.rs new file mode 100644 index 000000000..96755802e --- /dev/null +++ b/tests/ui/array-slice-vec/array_const_index-0.rs @@ -0,0 +1,8 @@ +const A: &'static [i32] = &[]; +const B: i32 = (&A)[1]; +//~^ index out of bounds: the length is 0 but the index is 1 +//~| ERROR evaluation of constant value failed + +fn main() { + let _ = B; +} diff --git a/tests/ui/array-slice-vec/array_const_index-0.stderr b/tests/ui/array-slice-vec/array_const_index-0.stderr new file mode 100644 index 000000000..3b92cc766 --- /dev/null +++ b/tests/ui/array-slice-vec/array_const_index-0.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/array_const_index-0.rs:2:16 + | +LL | const B: i32 = (&A)[1]; + | ^^^^^^^ index out of bounds: the length is 0 but the index is 1 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/array-slice-vec/array_const_index-1.rs b/tests/ui/array-slice-vec/array_const_index-1.rs new file mode 100644 index 000000000..625bf06a7 --- /dev/null +++ b/tests/ui/array-slice-vec/array_const_index-1.rs @@ -0,0 +1,8 @@ +const A: [i32; 0] = []; +const B: i32 = A[1]; +//~^ index out of bounds: the length is 0 but the index is 1 +//~| ERROR evaluation of constant value failed + +fn main() { + let _ = B; +} diff --git a/tests/ui/array-slice-vec/array_const_index-1.stderr b/tests/ui/array-slice-vec/array_const_index-1.stderr new file mode 100644 index 000000000..591db268a --- /dev/null +++ b/tests/ui/array-slice-vec/array_const_index-1.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/array_const_index-1.rs:2:16 + | +LL | const B: i32 = A[1]; + | ^^^^ index out of bounds: the length is 0 but the index is 1 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/array-slice-vec/array_const_index-2.rs b/tests/ui/array-slice-vec/array_const_index-2.rs new file mode 100644 index 000000000..8ee225f5c --- /dev/null +++ b/tests/ui/array-slice-vec/array_const_index-2.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(stable_features)] + +#![feature(const_indexing)] + +fn main() { + const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47]; + const IDX: usize = 3; + const VAL: i32 = ARR[IDX]; + const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; +} diff --git a/tests/ui/array-slice-vec/bounds-check-no-overflow.rs b/tests/ui/array-slice-vec/bounds-check-no-overflow.rs new file mode 100644 index 000000000..577853a4e --- /dev/null +++ b/tests/ui/array-slice-vec/bounds-check-no-overflow.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:index out of bounds +// ignore-emscripten no processes + +use std::mem::size_of; + +fn main() { + let xs = [1, 2, 3]; + xs[usize::MAX / size_of::() + 1]; +} diff --git a/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs b/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs new file mode 100644 index 000000000..2b3ece67b --- /dev/null +++ b/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs @@ -0,0 +1,53 @@ +// run-pass +// needs-unwind +#![allow(overflowing_literals)] + +// Test that we cleanup a fixed size Box<[D; k]> properly when D has a +// destructor. + +// ignore-emscripten no threads support + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst + ); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]); + let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]); + let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]); + let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]); + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing + // the input to `_b3`. Therefore, we drop the elements of the + // partially filled array first, before we get around to dropping + // the elements of `_b1` and _b2`. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky. See similar notes in nested-vec-3; + // in essence, I would not be surprised if we change the ordering + // given in `expect` in the future. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs b/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs new file mode 100644 index 000000000..c0ca45875 --- /dev/null +++ b/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs @@ -0,0 +1,53 @@ +// run-pass +// needs-unwind +#![allow(overflowing_literals)] + +// Test that we cleanup dynamic sized Box<[D]> properly when D has a +// destructor. + +// ignore-emscripten no threads support + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst + ); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]); + let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]); + let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]); + let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]); + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing + // the input to `_b3`. Therefore, we drop the elements of the + // partially filled array first, before we get around to dropping + // the elements of `_b1` and _b2`. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky. See similar notes in nested-vec-3; + // in essence, I would not be surprised if we change the ordering + // given in `expect` in the future. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/tests/ui/array-slice-vec/byte-literals.rs b/tests/ui/array-slice-vec/byte-literals.rs new file mode 100644 index 000000000..2649c2eac --- /dev/null +++ b/tests/ui/array-slice-vec/byte-literals.rs @@ -0,0 +1,67 @@ +// run-pass +// + + +static FOO: u8 = b'\xF0'; +static BAR: &'static [u8] = b"a\xF0\t"; +static BAR_FIXED: &'static [u8; 3] = b"a\xF0\t"; +static BAZ: &'static [u8] = br"a\n"; + +pub fn main() { + let bar: &'static [u8] = b"a\xF0\t"; + let bar_fixed: &'static [u8; 3] = b"a\xF0\t"; + + assert_eq!(b'a', 97u8); + assert_eq!(b'\n', 10u8); + assert_eq!(b'\r', 13u8); + assert_eq!(b'\t', 9u8); + assert_eq!(b'\\', 92u8); + assert_eq!(b'\'', 39u8); + assert_eq!(b'\"', 34u8); + assert_eq!(b'\0', 0u8); + assert_eq!(b'\xF0', 240u8); + assert_eq!(FOO, 240u8); + + match 42 { + b'*' => {}, + _ => panic!() + } + + match 100 { + b'a' ..= b'z' => {}, + _ => panic!() + } + + let expected: &[_] = &[97u8, 10u8, 13u8, 9u8, 92u8, 39u8, 34u8, 0u8, 240u8]; + assert_eq!(b"a\n\r\t\\\'\"\0\xF0", expected); + let expected: &[_] = &[97u8, 98u8]; + assert_eq!(b"a\ + b", expected); + let expected: &[_] = &[97u8, 240u8, 9u8]; + assert_eq!(BAR, expected); + assert_eq!(BAR_FIXED, expected); + assert_eq!(bar, expected); + assert_eq!(bar_fixed, expected); + + let val = &[97u8, 10u8]; + match val { + b"a\n" => {}, + _ => panic!(), + } + + let buf = vec![97u8, 98, 99, 100]; + assert_eq!(match &buf[0..3] { + b"def" => 1, + b"abc" => 2, + _ => 3 + }, 2); + + let expected: &[_] = &[97u8, 92u8, 110u8]; + assert_eq!(BAZ, expected); + let expected: &[_] = &[97u8, 92u8, 110u8]; + assert_eq!(br"a\n", expected); + assert_eq!(br"a\n", b"a\\n"); + let expected: &[_] = &[97u8, 34u8, 35u8, 35u8, 98u8]; + assert_eq!(br###"a"##b"###, expected); + assert_eq!(br###"a"##b"###, b"a\"##b"); +} diff --git a/tests/ui/array-slice-vec/cast-in-array-size.rs b/tests/ui/array-slice-vec/cast-in-array-size.rs new file mode 100644 index 000000000..b112dcaef --- /dev/null +++ b/tests/ui/array-slice-vec/cast-in-array-size.rs @@ -0,0 +1,14 @@ +// run-pass + + +// issues #10618 and #16382 +// pretty-expanded FIXME #23616 + +const SIZE: isize = 25; + +fn main() { + let _a: [bool; 1 as usize]; + let _b: [isize; SIZE as usize] = [1; SIZE as usize]; + let _c: [bool; '\n' as usize] = [true; '\n' as usize]; + let _d: [bool; true as usize] = [true; true as usize]; +} diff --git a/tests/ui/array-slice-vec/check-static-mut-slices.rs b/tests/ui/array-slice-vec/check-static-mut-slices.rs new file mode 100644 index 000000000..b89c63403 --- /dev/null +++ b/tests/ui/array-slice-vec/check-static-mut-slices.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + +// Checks that mutable static items can have mutable slices + + +static mut TEST: &'static mut [isize] = &mut [1]; +static mut EMPTY: &'static mut [isize] = &mut []; + +pub fn main() { + unsafe { + TEST[0] += 1; + assert_eq!(TEST[0], 2); + } +} diff --git a/tests/ui/array-slice-vec/check-static-slice.rs b/tests/ui/array-slice-vec/check-static-slice.rs new file mode 100644 index 000000000..1c607d134 --- /dev/null +++ b/tests/ui/array-slice-vec/check-static-slice.rs @@ -0,0 +1,36 @@ +// run-pass + +// Check that the various ways of getting to a reference to a vec (both sized +// and unsized) work properly. + + +const AA: [isize; 3] = [1, 2, 3]; +const AB: &'static [isize; 3] = &AA; +const AC: &'static [isize] = AB; +const AD: &'static [isize] = &AA; +const AE: &'static [isize; 3] = &[1, 2, 3]; +const AF: &'static [isize] = &[1, 2, 3]; + +static CA: isize = AA[0]; +static CB: isize = AB[1]; +static CC: isize = AC[2]; +static CD: isize = AD[0]; +static CE: isize = AE[1]; +static CF: isize = AF[2]; + +static AG: &'static isize = &AA[2]; + +fn main () { + let b: &[isize] = &[1, 2, 3]; + assert_eq!(AC, b); + assert_eq!(AD, b); + assert_eq!(AF, b); + assert_eq!(*AG, 3); + + assert_eq!(CA, 1); + assert_eq!(CB, 2); + assert_eq!(CC, 3); + assert_eq!(CD, 1); + assert_eq!(CE, 2); + assert_eq!(CF, 3); +} diff --git a/tests/ui/array-slice-vec/copy-out-of-array-1.rs b/tests/ui/array-slice-vec/copy-out-of-array-1.rs new file mode 100644 index 000000000..c6d311148 --- /dev/null +++ b/tests/ui/array-slice-vec/copy-out-of-array-1.rs @@ -0,0 +1,19 @@ +// run-pass + +// Ensure that we can copy out of a fixed-size array. +// +// (Compare with ui/moves/move-out-of-array-1.rs) + +#[derive(Copy, Clone)] +struct C { _x: u8 } + +fn main() { + fn d() -> C { C { _x: 0 } } + + let _d1 = foo([d(), d(), d(), d()], 1); + let _d3 = foo([d(), d(), d(), d()], 3); +} + +fn foo(a: [C; 4], i: usize) -> C { + a[i] +} diff --git a/tests/ui/array-slice-vec/destructure-array-1.rs b/tests/ui/array-slice-vec/destructure-array-1.rs new file mode 100644 index 000000000..74d893ee5 --- /dev/null +++ b/tests/ui/array-slice-vec/destructure-array-1.rs @@ -0,0 +1,27 @@ +// run-pass + +// Ensure that we can do a destructuring bind of a fixed-size array, +// even when the element type has a destructor. + +struct D { x: u8 } + +impl Drop for D { fn drop(&mut self) { } } + +fn main() { + fn d(x: u8) -> D { D { x: x } } + + let d1 = foo([d(1), d(2), d(3), d(4)], 1); + let d3 = foo([d(5), d(6), d(7), d(8)], 3); + assert_eq!(d1.x, 2); + assert_eq!(d3.x, 8); +} + +fn foo([a, b, c, d]: [D; 4], i: usize) -> D { + match i { + 0 => a, + 1 => b, + 2 => c, + 3 => d, + _ => panic!("unmatched"), + } +} diff --git a/tests/ui/array-slice-vec/dst-raw-slice.rs b/tests/ui/array-slice-vec/dst-raw-slice.rs new file mode 100644 index 000000000..371d16f09 --- /dev/null +++ b/tests/ui/array-slice-vec/dst-raw-slice.rs @@ -0,0 +1,13 @@ +// Test bounds checking for DST raw slices + +// run-fail +// error-pattern:index out of bounds +// ignore-emscripten no processes + +#[allow(unconditional_panic)] +fn main() { + let a: *const [_] = &[1, 2, 3]; + unsafe { + let _b = (*a)[3]; + } +} diff --git a/tests/ui/array-slice-vec/empty-mutable-vec.rs b/tests/ui/array-slice-vec/empty-mutable-vec.rs new file mode 100644 index 000000000..91ab280b9 --- /dev/null +++ b/tests/ui/array-slice-vec/empty-mutable-vec.rs @@ -0,0 +1,8 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +#![allow(unused_mut)] + + +pub fn main() { let mut _v: Vec = Vec::new(); } diff --git a/tests/ui/array-slice-vec/estr-slice.rs b/tests/ui/array-slice-vec/estr-slice.rs new file mode 100644 index 000000000..cd2c17220 --- /dev/null +++ b/tests/ui/array-slice-vec/estr-slice.rs @@ -0,0 +1,50 @@ +// run-pass + + +pub fn main() { + let x = "hello"; + let v = "hello"; + let y : &str = "there"; + + println!("{}", x); + println!("{}", y); + + assert_eq!(x.as_bytes()[0], 'h' as u8); + assert_eq!(x.as_bytes()[4], 'o' as u8); + + let z : &str = "thing"; + assert_eq!(v, x); + assert_ne!(x, z); + + let a = "aaaa"; + let b = "bbbb"; + + let c = "cccc"; + let cc = "ccccc"; + + println!("{}", a); + + assert!(a < b); + assert!(a <= b); + assert_ne!(a, b); + assert!(b >= a); + assert!(b > a); + + println!("{}", b); + + assert!(a < c); + assert!(a <= c); + assert_ne!(a, c); + assert!(c >= a); + assert!(c > a); + + println!("{}", c); + + assert!(c < cc); + assert!(c <= cc); + assert_ne!(c, cc); + assert!(cc >= c); + assert!(cc > c); + + println!("{}", cc); +} diff --git a/tests/ui/array-slice-vec/evec-slice.rs b/tests/ui/array-slice-vec/evec-slice.rs new file mode 100644 index 000000000..4bdf2dbdd --- /dev/null +++ b/tests/ui/array-slice-vec/evec-slice.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(unused_assignments)] + +pub fn main() { + let x : &[isize] = &[1,2,3,4,5]; + let mut z : &[isize] = &[1,2,3,4,5]; + z = x; + assert_eq!(z[0], 1); + assert_eq!(z[4], 5); + + let a : &[isize] = &[1,1,1,1,1]; + let b : &[isize] = &[2,2,2,2,2]; + let c : &[isize] = &[2,2,2,2,3]; + let cc : &[isize] = &[2,2,2,2,2,2]; + + println!("{:?}", a); + + assert!(a < b); + assert!(a <= b); + assert!(a != b); + assert!(b >= a); + assert!(b > a); + + println!("{:?}", b); + + assert!(b < c); + assert!(b <= c); + assert!(b != c); + assert!(c >= b); + assert!(c > b); + + assert!(a < c); + assert!(a <= c); + assert!(a != c); + assert!(c >= a); + assert!(c > a); + + println!("{:?}", c); + + assert!(a < cc); + assert!(a <= cc); + assert!(a != cc); + assert!(cc >= a); + assert!(cc > a); + + println!("{:?}", cc); +} diff --git a/tests/ui/array-slice-vec/fixed_length_copy.rs b/tests/ui/array-slice-vec/fixed_length_copy.rs new file mode 100644 index 000000000..f73173e84 --- /dev/null +++ b/tests/ui/array-slice-vec/fixed_length_copy.rs @@ -0,0 +1,9 @@ +// run-pass + + +pub fn main() { + let arr = [1,2,3]; + let arr2 = arr; + assert_eq!(arr[1], 2); + assert_eq!(arr2[2], 3); +} diff --git a/tests/ui/array-slice-vec/huge-largest-array.rs b/tests/ui/array-slice-vec/huge-largest-array.rs new file mode 100644 index 000000000..9e78162c8 --- /dev/null +++ b/tests/ui/array-slice-vec/huge-largest-array.rs @@ -0,0 +1,14 @@ +// run-pass + + +use std::mem::size_of; + +#[cfg(target_pointer_width = "32")] +pub fn main() { + assert_eq!(size_of::<[u8; (1 << 31) - 1]>(), (1 << 31) - 1); +} + +#[cfg(target_pointer_width = "64")] +pub fn main() { + assert_eq!(size_of::<[u8; (1 << 47) - 1]>(), (1 << 47) - 1); +} diff --git a/tests/ui/array-slice-vec/infer_array_len.rs b/tests/ui/array-slice-vec/infer_array_len.rs new file mode 100644 index 000000000..22fe7cb88 --- /dev/null +++ b/tests/ui/array-slice-vec/infer_array_len.rs @@ -0,0 +1,21 @@ +// see issue #70529 +struct A; + +impl From for [u8; 2] { + fn from(a: A) -> Self { + [0; 2] + } +} + +impl From for [u8; 3] { + fn from(a: A) -> Self { + [0; 3] + } +} + + +fn main() { + let a = A; + let [_, _] = a.into(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/array-slice-vec/infer_array_len.stderr b/tests/ui/array-slice-vec/infer_array_len.stderr new file mode 100644 index 000000000..c2a509a19 --- /dev/null +++ b/tests/ui/array-slice-vec/infer_array_len.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/infer_array_len.rs:19:9 + | +LL | let [_, _] = a.into(); + | ^^^^^^ + | +help: consider giving this pattern a type + | +LL | let [_, _]: /* Type */ = a.into(); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/array-slice-vec/issue-15730.rs b/tests/ui/array-slice-vec/issue-15730.rs new file mode 100644 index 000000000..dacffd154 --- /dev/null +++ b/tests/ui/array-slice-vec/issue-15730.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +fn main() { + let mut array = [1, 2, 3]; + let pie_slice = &array[1..2]; +} diff --git a/tests/ui/array-slice-vec/issue-18425.rs b/tests/ui/array-slice-vec/issue-18425.rs new file mode 100644 index 000000000..354c14a75 --- /dev/null +++ b/tests/ui/array-slice-vec/issue-18425.rs @@ -0,0 +1,9 @@ +// run-pass +// Check that codegen doesn't ICE when codegenning an array repeat +// expression with a count of 1 and a non-Copy element type. + +// pretty-expanded FIXME #23616 + +fn main() { + let _ = [Box::new(1_usize); 1]; +} diff --git a/tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs b/tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs new file mode 100644 index 000000000..061b0d675 --- /dev/null +++ b/tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs @@ -0,0 +1,18 @@ +// We used to not lower the extra `b @ ..` into `b @ _` which meant that no type +// was registered for the binding `b` although it passed through resolve. +// This resulted in an ICE (#69103). + +fn main() { + let [a @ .., b @ ..] = &mut [1, 2]; + //~^ ERROR `..` can only be used once per slice pattern + b; + + let [.., c @ ..] = [1, 2]; + //~^ ERROR `..` can only be used once per slice pattern + c; + + // This never ICEd, but let's make sure it won't regress either. + let (.., d @ ..) = (1, 2); + //~^ ERROR `..` patterns are not allowed here + d; +} diff --git a/tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr b/tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr new file mode 100644 index 000000000..9432e2f0c --- /dev/null +++ b/tests/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr @@ -0,0 +1,26 @@ +error: `..` can only be used once per slice pattern + --> $DIR/issue-69103-extra-binding-subslice.rs:6:22 + | +LL | let [a @ .., b @ ..] = &mut [1, 2]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error: `..` can only be used once per slice pattern + --> $DIR/issue-69103-extra-binding-subslice.rs:10:18 + | +LL | let [.., c @ ..] = [1, 2]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error: `..` patterns are not allowed here + --> $DIR/issue-69103-extra-binding-subslice.rs:15:18 + | +LL | let (.., d @ ..) = (1, 2); + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: aborting due to 3 previous errors + diff --git a/tests/ui/array-slice-vec/ivec-pass-by-value.rs b/tests/ui/array-slice-vec/ivec-pass-by-value.rs new file mode 100644 index 000000000..e22aef963 --- /dev/null +++ b/tests/ui/array-slice-vec/ivec-pass-by-value.rs @@ -0,0 +1,4 @@ +// run-pass + +fn f(_a: Vec ) { } +pub fn main() { f(vec![1, 2, 3, 4, 5]); } diff --git a/tests/ui/array-slice-vec/match_arr_unknown_len.rs b/tests/ui/array-slice-vec/match_arr_unknown_len.rs new file mode 100644 index 000000000..d190d7054 --- /dev/null +++ b/tests/ui/array-slice-vec/match_arr_unknown_len.rs @@ -0,0 +1,8 @@ +fn is_123(x: [u32; N]) -> bool { + match x { + [1, 2] => true, //~ ERROR mismatched types + _ => false + } +} + +fn main() {} diff --git a/tests/ui/array-slice-vec/match_arr_unknown_len.stderr b/tests/ui/array-slice-vec/match_arr_unknown_len.stderr new file mode 100644 index 000000000..5e531a993 --- /dev/null +++ b/tests/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/match_arr_unknown_len.rs:3:9 + | +LL | [1, 2] => true, + | ^^^^^^ expected `2`, found `N` + | + = note: expected array `[u32; 2]` + found array `[u32; N]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/mut-vstore-expr.rs b/tests/ui/array-slice-vec/mut-vstore-expr.rs new file mode 100644 index 000000000..75b309a48 --- /dev/null +++ b/tests/ui/array-slice-vec/mut-vstore-expr.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let _x: &mut [isize] = &mut [ 1, 2, 3 ]; +} diff --git a/tests/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs b/tests/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs new file mode 100644 index 000000000..7afb9d846 --- /dev/null +++ b/tests/ui/array-slice-vec/mutability-inherits-through-fixed-length-vec.rs @@ -0,0 +1,19 @@ +// run-pass + + +fn test1() { + let mut ints = [0; 32]; + ints[0] += 1; + assert_eq!(ints[0], 1); +} + +fn test2() { + let mut ints = [0; 32]; + for i in &mut ints { *i += 22; } + for i in &ints { assert_eq!(*i, 22); } +} + +pub fn main() { + test1(); + test2(); +} diff --git a/tests/ui/array-slice-vec/mutable-alias-vec.rs b/tests/ui/array-slice-vec/mutable-alias-vec.rs new file mode 100644 index 000000000..98dd46824 --- /dev/null +++ b/tests/ui/array-slice-vec/mutable-alias-vec.rs @@ -0,0 +1,15 @@ +// run-pass + +fn grow(v: &mut Vec ) { + v.push(1); +} + +pub fn main() { + let mut v: Vec = Vec::new(); + grow(&mut v); + grow(&mut v); + grow(&mut v); + let len = v.len(); + println!("{}", len); + assert_eq!(len, 3 as usize); +} diff --git a/tests/ui/array-slice-vec/nested-vec-1.rs b/tests/ui/array-slice-vec/nested-vec-1.rs new file mode 100644 index 000000000..02a3ccf46 --- /dev/null +++ b/tests/ui/array-slice-vec/nested-vec-1.rs @@ -0,0 +1,8 @@ +// run-pass + +// Test that using the `vec!` macro nested within itself works + +fn main() { + let nested = vec![vec![1u32, 2u32, 3u32]]; + assert_eq!(nested[0][1], 2); +} diff --git a/tests/ui/array-slice-vec/nested-vec-2.rs b/tests/ui/array-slice-vec/nested-vec-2.rs new file mode 100644 index 000000000..d4a704d76 --- /dev/null +++ b/tests/ui/array-slice-vec/nested-vec-2.rs @@ -0,0 +1,15 @@ +// run-pass + +// Test that using the `vec!` macro nested within itself works +// when the contents implement Drop + +struct D(u32); + +impl Drop for D { + fn drop(&mut self) { println!("Dropping {}", self.0); } +} + +fn main() { + let nested = vec![vec![D(1u32), D(2u32), D(3u32)]]; + assert_eq!(nested[0][1].0, 2); +} diff --git a/tests/ui/array-slice-vec/nested-vec-3.rs b/tests/ui/array-slice-vec/nested-vec-3.rs new file mode 100644 index 000000000..b3ae683a8 --- /dev/null +++ b/tests/ui/array-slice-vec/nested-vec-3.rs @@ -0,0 +1,60 @@ +// run-pass +// needs-unwind +#![allow(overflowing_literals)] + +// ignore-emscripten no threads support + +// Test that using the `vec!` macro nested within itself works when +// the contents implement Drop and we hit a panic in the middle of +// construction. + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +struct D(u8); + +impl Drop for D { + fn drop(&mut self) { + println!("Dropping {}", self.0); + let old = LOG.load(Ordering::SeqCst); + let _ = LOG.compare_exchange( + old, + old << 4 | self.0 as usize, + Ordering::SeqCst, + Ordering::SeqCst, + ); + } +} + +fn main() { + fn die() -> D { panic!("Oh no"); } + let g = thread::spawn(|| { + let _nested = vec![vec![D( 1), D( 2), D( 3), D( 4)], + vec![D( 5), D( 6), D( 7), D( 8)], + vec![D( 9), D(10), die(), D(12)], + vec![D(13), D(14), D(15), D(16)]]; + }); + assert!(g.join().is_err()); + + // When the panic occurs, we will be in the midst of constructing the + // second inner vector. Therefore, we drop the elements of the + // partially filled vector first, before we get around to dropping + // the elements of the filled vector. + + // Issue 23222: The order in which the elements actually get + // dropped is a little funky: as noted above, we'll drop the 9+10 + // first, but due to #23222, they get dropped in reverse + // order. Likewise, again due to #23222, we will drop the second + // filled vec before the first filled vec. + // + // If Issue 23222 is "fixed", then presumably the corrected + // expected order of events will be 0x__9_A__1_2_3_4__5_6_7_8; + // that is, we would still drop 9+10 first, since they belong to + // the more deeply nested expression when the panic occurs. + + let expect = 0x__A_9__5_6_7_8__1_2_3_4; + let actual = LOG.load(Ordering::SeqCst); + assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} diff --git a/tests/ui/array-slice-vec/new-style-fixed-length-vec.rs b/tests/ui/array-slice-vec/new-style-fixed-length-vec.rs new file mode 100644 index 000000000..454f94be8 --- /dev/null +++ b/tests/ui/array-slice-vec/new-style-fixed-length-vec.rs @@ -0,0 +1,7 @@ +// run-pass + +static FOO: [isize; 3] = [1, 2, 3]; + +pub fn main() { + println!("{} {} {}", FOO[0], FOO[1], FOO[2]); +} diff --git a/tests/ui/array-slice-vec/rcvr-borrowed-to-slice.rs b/tests/ui/array-slice-vec/rcvr-borrowed-to-slice.rs new file mode 100644 index 000000000..17cf7e335 --- /dev/null +++ b/tests/ui/array-slice-vec/rcvr-borrowed-to-slice.rs @@ -0,0 +1,33 @@ +// run-pass + +#![allow(non_camel_case_types)] + +trait sum { + fn sum_(self) -> isize; +} + +// Note: impl on a slice +impl<'a> sum for &'a [isize] { + fn sum_(self) -> isize { + self.iter().fold(0, |a, &b| a + b) + } +} + +fn call_sum(x: &[isize]) -> isize { x.sum_() } + +pub fn main() { + let x = vec![1, 2, 3]; + let y = call_sum(&x); + println!("y=={}", y); + assert_eq!(y, 6); + + let x = vec![1, 2, 3]; + let y = x.sum_(); + println!("y=={}", y); + assert_eq!(y, 6); + + let x = vec![1, 2, 3]; + let y = x.sum_(); + println!("y=={}", y); + assert_eq!(y, 6); +} diff --git a/tests/ui/array-slice-vec/repeat_empty_ok.rs b/tests/ui/array-slice-vec/repeat_empty_ok.rs new file mode 100644 index 000000000..25463ea5e --- /dev/null +++ b/tests/ui/array-slice-vec/repeat_empty_ok.rs @@ -0,0 +1,15 @@ +#![crate_type = "lib"] + +pub struct Header<'a> { + pub value: &'a [u8], +} + +pub fn test() { + let headers = [Header{value: &[]}; 128]; + //~^ ERROR the trait bound +} + +pub fn test2() { + let headers = [Header{value: &[0]}; 128]; + //~^ ERROR the trait bound +} diff --git a/tests/ui/array-slice-vec/repeat_empty_ok.stderr b/tests/ui/array-slice-vec/repeat_empty_ok.stderr new file mode 100644 index 000000000..724bdcd92 --- /dev/null +++ b/tests/ui/array-slice-vec/repeat_empty_ok.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied + --> $DIR/repeat_empty_ok.rs:8:20 + | +LL | let headers = [Header{value: &[]}; 128]; + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Header<'_>` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0277]: the trait bound `Header<'_>: Copy` is not satisfied + --> $DIR/repeat_empty_ok.rs:13:20 + | +LL | let headers = [Header{value: &[0]}; 128]; + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Header<'_>` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/array-slice-vec/repeated-vector-syntax.rs b/tests/ui/array-slice-vec/repeated-vector-syntax.rs new file mode 100644 index 000000000..4458eb06d --- /dev/null +++ b/tests/ui/array-slice-vec/repeated-vector-syntax.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let x = [ [true]; 512 ]; + let y = [ 0; 1 ]; + + print!("["); + for xi in &x[..] { + print!("{:?}, ", &xi[..]); + } + println!("]"); + println!("{:?}", &y[..]); +} diff --git a/tests/ui/array-slice-vec/show-boxed-slice.rs b/tests/ui/array-slice-vec/show-boxed-slice.rs new file mode 100644 index 000000000..c10f779b1 --- /dev/null +++ b/tests/ui/array-slice-vec/show-boxed-slice.rs @@ -0,0 +1,8 @@ +// run-pass + +#[derive(Debug)] +struct Foo(#[allow(unused_tuple_struct_fields)] Box<[u8]>); + +pub fn main() { + println!("{:?}", Foo(Box::new([0, 1, 2]))); +} diff --git a/tests/ui/array-slice-vec/slice-2.rs b/tests/ui/array-slice-vec/slice-2.rs new file mode 100644 index 000000000..5423e295a --- /dev/null +++ b/tests/ui/array-slice-vec/slice-2.rs @@ -0,0 +1,11 @@ +// Test that slicing syntax gives errors if we have not implemented the trait. + +struct Foo; + +fn main() { + let x = Foo; + &x[..]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..]; //~ ERROR cannot index into a value of type `Foo` + &x[..Foo]; //~ ERROR cannot index into a value of type `Foo` + &x[Foo..Foo]; //~ ERROR cannot index into a value of type `Foo` +} diff --git a/tests/ui/array-slice-vec/slice-2.stderr b/tests/ui/array-slice-vec/slice-2.stderr new file mode 100644 index 000000000..561feb90f --- /dev/null +++ b/tests/ui/array-slice-vec/slice-2.stderr @@ -0,0 +1,27 @@ +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:7:6 + | +LL | &x[..]; + | ^^^^^ + +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:8:6 + | +LL | &x[Foo..]; + | ^^^^^^^^ + +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:9:6 + | +LL | &x[..Foo]; + | ^^^^^^^^ + +error[E0608]: cannot index into a value of type `Foo` + --> $DIR/slice-2.rs:10:6 + | +LL | &x[Foo..Foo]; + | ^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/array-slice-vec/slice-mut-2.rs b/tests/ui/array-slice-vec/slice-mut-2.rs new file mode 100644 index 000000000..216edbb78 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-mut-2.rs @@ -0,0 +1,8 @@ +// Test mutability and slicing syntax. + +fn main() { + let x: &[isize] = &[1, 2, 3, 4, 5]; + // Can't mutably slice an immutable slice + let slice: &mut [isize] = &mut [0, 1]; + let _ = &mut x[2..4]; //~ERROR cannot borrow `*x` as mutable, as it is behind a `&` reference +} diff --git a/tests/ui/array-slice-vec/slice-mut-2.stderr b/tests/ui/array-slice-vec/slice-mut-2.stderr new file mode 100644 index 000000000..5b040d3e4 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-mut-2.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/slice-mut-2.rs:7:18 + | +LL | let _ = &mut x[2..4]; + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let x: &[isize] = &mut [1, 2, 3, 4, 5]; + | ~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/array-slice-vec/slice-mut.rs b/tests/ui/array-slice-vec/slice-mut.rs new file mode 100644 index 000000000..e9989f0f4 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-mut.rs @@ -0,0 +1,12 @@ +// Test mutability and slicing syntax. + +fn main() { + let x: &[isize] = &[1, 2, 3, 4, 5]; + // Immutable slices are not mutable. + + let y: &mut[_] = &x[2..4]; + //~^ ERROR mismatched types + //~| expected mutable reference `&mut [_]` + //~| found reference `&[isize]` + //~| types differ in mutability +} diff --git a/tests/ui/array-slice-vec/slice-mut.stderr b/tests/ui/array-slice-vec/slice-mut.stderr new file mode 100644 index 000000000..7d34defc1 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-mut.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/slice-mut.rs:7:22 + | +LL | let y: &mut[_] = &x[2..4]; + | ------- ^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut [_]` + found reference `&[isize]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/slice-of-zero-size-elements.rs b/tests/ui/array-slice-vec/slice-of-zero-size-elements.rs new file mode 100644 index 000000000..83b08a3db --- /dev/null +++ b/tests/ui/array-slice-vec/slice-of-zero-size-elements.rs @@ -0,0 +1,53 @@ +// run-pass +#![allow(stable_features)] + +// compile-flags: -C debug-assertions + +#![feature(iter_to_slice)] + +use std::slice; + +fn foo(v: &[T]) -> Option<&[T]> { + let mut it = v.iter(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.as_slice()) +} + +fn foo_mut(v: &mut [T]) -> Option<&mut [T]> { + let mut it = v.iter_mut(); + for _ in 0..5 { + let _ = it.next(); + } + Some(it.into_slice()) +} + +pub fn main() { + // In a slice of zero-size elements the pointer is meaningless. + // Ensure iteration still works even if the pointer is at the end of the address space. + let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter().count(), 10); + + // .nth() on the iterator should also behave correctly + let mut it = slice.iter(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + + // Converting Iter to a slice should never have a null pointer + assert!(foo(slice).is_some()); + + // Test mutable iterators as well + let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) }; + assert_eq!(slice.len(), 10); + assert_eq!(slice.iter_mut().count(), 10); + + { + let mut it = slice.iter_mut(); + assert!(it.nth(5).is_some()); + assert_eq!(it.count(), 4); + } + + assert!(foo_mut(slice).is_some()) +} diff --git a/tests/ui/array-slice-vec/slice-panic-1.rs b/tests/ui/array-slice-vec/slice-panic-1.rs new file mode 100644 index 000000000..3829078ab --- /dev/null +++ b/tests/ui/array-slice-vec/slice-panic-1.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind + +// ignore-emscripten no threads support + +// Test that if a slicing expr[..] fails, the correct cleanups happen. + + +use std::thread; + +struct Foo; + +static mut DTOR_COUNT: isize = 0; + +impl Drop for Foo { + fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } +} + +fn foo() { + let x: &[_] = &[Foo, Foo]; + let _ = &x[3..4]; +} + +fn main() { + let _ = thread::spawn(move|| foo()).join(); + unsafe { assert_eq!(DTOR_COUNT, 2); } +} diff --git a/tests/ui/array-slice-vec/slice-panic-2.rs b/tests/ui/array-slice-vec/slice-panic-2.rs new file mode 100644 index 000000000..d83c611d3 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-panic-2.rs @@ -0,0 +1,31 @@ +// run-pass +// needs-unwind + +// ignore-emscripten no threads support + +// Test that if a slicing expr[..] fails, the correct cleanups happen. + + +use std::thread; + +struct Foo; + +static mut DTOR_COUNT: isize = 0; + +impl Drop for Foo { + fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } +} + +fn bar() -> usize { + panic!(); +} + +fn foo() { + let x: &[_] = &[Foo, Foo]; + let _ = &x[3..bar()]; +} + +fn main() { + let _ = thread::spawn(move|| foo()).join(); + unsafe { assert_eq!(DTOR_COUNT, 2); } +} diff --git a/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs b/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs new file mode 100644 index 000000000..521b898e7 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs @@ -0,0 +1,36 @@ +fn main() { + match "foo".to_string() { + ['f', 'o', ..] => {} + //~^ ERROR expected an array or slice, found `String` + _ => { } + }; + + // Note that this one works with default binding modes. + match &[0, 1, 2] { + [..] => {} + }; + + match &[0, 1, 2] { + &[..] => {} // ok + }; + + match [0, 1, 2] { + [0] => {}, //~ ERROR pattern requires + + [0, 1, x @ ..] => { + let a: [_; 1] = x; + } + [0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires + }; + + match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope + [] => {} + }; +} + +fn another_fn_to_avoid_suppression() { + match Default::default() + { + [] => {} //~ ERROR type annotations needed + }; +} diff --git a/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr b/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr new file mode 100644 index 000000000..70a4cbebe --- /dev/null +++ b/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr @@ -0,0 +1,34 @@ +error[E0425]: cannot find value `does_not_exist` in this scope + --> $DIR/slice-pat-type-mismatches.rs:26:11 + | +LL | match does_not_exist { + | ^^^^^^^^^^^^^^ not found in this scope + +error[E0529]: expected an array or slice, found `String` + --> $DIR/slice-pat-type-mismatches.rs:3:9 + | +LL | ['f', 'o', ..] => {} + | ^^^^^^^^^^^^^^ pattern cannot match with input type `String` + +error[E0527]: pattern requires 1 element but array has 3 + --> $DIR/slice-pat-type-mismatches.rs:18:9 + | +LL | [0] => {}, + | ^^^ expected 3 elements + +error[E0528]: pattern requires at least 4 elements but array has 3 + --> $DIR/slice-pat-type-mismatches.rs:23:9 + | +LL | [0, 1, 2, 3, x @ ..] => {} + | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements + +error[E0282]: type annotations needed + --> $DIR/slice-pat-type-mismatches.rs:34:9 + | +LL | [] => {} + | ^^ cannot infer type + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0282, E0425, E0527, E0528, E0529. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/array-slice-vec/slice-to-vec-comparison.rs b/tests/ui/array-slice-vec/slice-to-vec-comparison.rs new file mode 100644 index 000000000..7026a4900 --- /dev/null +++ b/tests/ui/array-slice-vec/slice-to-vec-comparison.rs @@ -0,0 +1,6 @@ +fn main() { + let a = &[]; + let b: &Vec = &vec![]; + a > b; + //~^ ERROR mismatched types +} diff --git a/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr b/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr new file mode 100644 index 000000000..e3b3b040f --- /dev/null +++ b/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/slice-to-vec-comparison.rs:4:9 + | +LL | a > b; + | ^ expected array of 0 elements, found struct `Vec` + | + = note: expected reference `&[_; 0]` + found reference `&Vec` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/slice.rs b/tests/ui/array-slice-vec/slice.rs new file mode 100644 index 000000000..a514e2027 --- /dev/null +++ b/tests/ui/array-slice-vec/slice.rs @@ -0,0 +1,81 @@ +// run-pass +#![allow(unused_variables)] + +// Test slicing sugar. + +extern crate core; +use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull}; + +static mut COUNT: usize = 0; + +struct Foo; + +impl Index> for Foo { + type Output = Foo; + fn index(&self, index: Range) -> &Foo { + unsafe { COUNT += 1; } + self + } +} +impl Index> for Foo { + type Output = Foo; + fn index(&self, index: RangeTo) -> &Foo { + unsafe { COUNT += 1; } + self + } +} +impl Index> for Foo { + type Output = Foo; + fn index(&self, index: RangeFrom) -> &Foo { + unsafe { COUNT += 1; } + self + } +} +impl Index for Foo { + type Output = Foo; + fn index(&self, _index: RangeFull) -> &Foo { + unsafe { COUNT += 1; } + self + } +} + +impl IndexMut> for Foo { + fn index_mut(&mut self, index: Range) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} +impl IndexMut> for Foo { + fn index_mut(&mut self, index: RangeTo) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} +impl IndexMut> for Foo { + fn index_mut(&mut self, index: RangeFrom) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} +impl IndexMut for Foo { + fn index_mut(&mut self, _index: RangeFull) -> &mut Foo { + unsafe { COUNT += 1; } + self + } +} + + +fn main() { + let mut x = Foo; + let _ = &x[..]; + let _ = &x[Foo..]; + let _ = &x[..Foo]; + let _ = &x[Foo..Foo]; + let _ = &mut x[..]; + let _ = &mut x[Foo..]; + let _ = &mut x[..Foo]; + let _ = &mut x[Foo..Foo]; + unsafe { + assert_eq!(COUNT, 8); + } +} diff --git a/tests/ui/array-slice-vec/slice_binary_search.rs b/tests/ui/array-slice-vec/slice_binary_search.rs new file mode 100644 index 000000000..4d8022ecb --- /dev/null +++ b/tests/ui/array-slice-vec/slice_binary_search.rs @@ -0,0 +1,22 @@ +// run-pass + +// Test binary_search_by_key lifetime. Issue #34683 + +#[allow(dead_code)] +#[derive(Debug)] +struct Assignment { + topic: String, + partition: i32, +} + +fn main() { + let xs = vec![ + Assignment { topic: "abc".into(), partition: 1 }, + Assignment { topic: "def".into(), partition: 2 }, + Assignment { topic: "ghi".into(), partition: 3 }, + ]; + + let key: &str = "def"; + let r = xs.binary_search_by_key(&key, |e| &e.topic); + assert_eq!(Ok(1), r.map(|i| i)); +} diff --git a/tests/ui/array-slice-vec/slice_is_sorted_by_borrow.rs b/tests/ui/array-slice-vec/slice_is_sorted_by_borrow.rs new file mode 100644 index 000000000..073280d0f --- /dev/null +++ b/tests/ui/array-slice-vec/slice_is_sorted_by_borrow.rs @@ -0,0 +1,20 @@ +// check-pass +// regression test for https://github.com/rust-lang/rust/issues/53485#issuecomment-885393452 + +#![feature(is_sorted)] + +struct A { + name: String, +} + +fn main() { + let a = &[ + A { + name: "1".to_string(), + }, + A { + name: "2".to_string(), + }, + ]; + assert!(a.is_sorted_by_key(|a| a.name.as_str())); +} diff --git a/tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs b/tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs new file mode 100644 index 000000000..97e33624b --- /dev/null +++ b/tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs @@ -0,0 +1,11 @@ +fn main() { + let a: &[u8] = &[]; + match a { + [1, tail @ .., tail @ ..] => {}, + //~^ ERROR identifier `tail` is bound more than once in the same pattern + //~| ERROR `..` can only be used once per slice pattern + _ => () + } +} + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr b/tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr new file mode 100644 index 000000000..4d6078788 --- /dev/null +++ b/tests/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr @@ -0,0 +1,24 @@ +error[E0416]: identifier `tail` is bound more than once in the same pattern + --> $DIR/subslice-only-once-semantic-restriction.rs:4:24 + | +LL | [1, tail @ .., tail @ ..] => {}, + | ^^^^ used in a pattern more than once + +error: `..` can only be used once per slice pattern + --> $DIR/subslice-only-once-semantic-restriction.rs:4:31 + | +LL | [1, tail @ .., tail @ ..] => {}, + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/subslice-only-once-semantic-restriction.rs:11:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected `()`, found integer + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0416. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs new file mode 100644 index 000000000..5a6283e9f --- /dev/null +++ b/tests/ui/array-slice-vec/subslice-patterns-const-eval-match.rs @@ -0,0 +1,96 @@ +// Test that slice subslice patterns are correctly handled in const evaluation. + +// run-pass + +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation_inner { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Compare the result of matching `$e` against `$p` using both `if let` and +// `match`. +macro_rules! compare_evaluation { + ($p:pat, $e:expr, $matches:expr, $t:ty $(,)?) => {{ + compare_evaluation_inner!(if let $p = $e as &[_] { $matches } else { None }, $t); + compare_evaluation_inner!(match $e as &[_] { $p => $matches, _ => None }, $t); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!([_, x @ .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1, 2, 3, 4), Some(x), Option<&'static $Ty>); + + compare_evaluation!([_, x @ .., _], &$arr!(1, 2), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1, 2), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1, 2), Some(x), Option<&'static $Ty>); + + compare_evaluation!([_, x @ .., _], &$arr!(1), Some(x), Option<&'static [$Ty]>); + compare_evaluation!([x, .., _], &$arr!(1), Some(x), Option<&'static $Ty>); + compare_evaluation!([_, .., x], &$arr!(1), Some(x), Option<&'static $Ty>); + } + + compare_evaluation!([N(x), .., _], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); + compare_evaluation!([_, .., N(x)], &n!(1, 2, 3, 4), Some(x), Option<&'static u8>); + + compare_evaluation!([N(x), .., _], &n!(1, 2), Some(x), Option<&'static u8>); + compare_evaluation!([_, .., N(x)], &n!(1, 2), Some(x), Option<&'static u8>); +} diff --git a/tests/ui/array-slice-vec/subslice-patterns-const-eval.rs b/tests/ui/array-slice-vec/subslice-patterns-const-eval.rs new file mode 100644 index 000000000..0b793fa01 --- /dev/null +++ b/tests/ui/array-slice-vec/subslice-patterns-const-eval.rs @@ -0,0 +1,95 @@ +// Test that array subslice patterns are correctly handled in const evaluation. + +// run-pass + +#[derive(PartialEq, Debug, Clone)] +struct N(u8); + +#[derive(PartialEq, Debug, Clone)] +struct Z; + +macro_rules! n { + ($($e:expr),* $(,)?) => { + [$(N($e)),*] + } +} + +// This macro has an unused variable so that it can be repeated base on the +// number of times a repeated variable (`$e` in `z`) occurs. +macro_rules! zed { + ($e:expr) => { Z } +} + +macro_rules! z { + ($($e:expr),* $(,)?) => { + [$(zed!($e)),*] + } +} + +// Compare constant evaluation and runtime evaluation of a given expression. +macro_rules! compare_evaluation { + ($e:expr, $t:ty $(,)?) => {{ + const CONST_EVAL: $t = $e; + const fn const_eval() -> $t { $e } + static CONST_EVAL2: $t = const_eval(); + let runtime_eval = $e; + assert_eq!(CONST_EVAL, runtime_eval); + assert_eq!(CONST_EVAL2, runtime_eval); + }} +} + +// Repeat `$test`, substituting the given macro variables with the given +// identifiers. +// +// For example: +// +// repeat! { +// ($name); X; Y: +// struct $name; +// } +// +// Expands to: +// +// struct X; struct Y; +// +// This is used to repeat the tests using both the `N` and `Z` +// types. +macro_rules! repeat { + (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => { + macro_rules! single { + ($($dollar $placeholder:ident),*) => { $($test)* } + } + $(single!($($values),+);)* + } +} + +fn main() { + repeat! { + ($arr $Ty); n, N; z, Z: + compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]); + compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]); + + compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]); + compare_evaluation!( + { let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + compare_evaluation!( + { let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x }, + &'static [$Ty; 0], + ); + + compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty); + compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty); + compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty); + } + + compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8); + + compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8); + compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8); + compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8); +} diff --git a/tests/ui/array-slice-vec/suggest-array-length.fixed b/tests/ui/array-slice-vec/suggest-array-length.fixed new file mode 100644 index 000000000..867c18a7d --- /dev/null +++ b/tests/ui/array-slice-vec/suggest-array-length.fixed @@ -0,0 +1,26 @@ +// run-rustfix +#![allow(unused_variables, dead_code, non_upper_case_globals)] + +fn main() { + const Foo: [i32; 3] = [1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + const REF_FOO: &[u8; 1] = &[1]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let foo: [i32; 3] = [1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let bar: [i32; 3] = [0; 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let ref_foo: &[i32; 3] = &[1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let ref_bar: &[i32; 3] = &[0; 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let multiple_ref_foo: &&[i32; 3] = &&[1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable +} diff --git a/tests/ui/array-slice-vec/suggest-array-length.rs b/tests/ui/array-slice-vec/suggest-array-length.rs new file mode 100644 index 000000000..f66b3d4a8 --- /dev/null +++ b/tests/ui/array-slice-vec/suggest-array-length.rs @@ -0,0 +1,26 @@ +// run-rustfix +#![allow(unused_variables, dead_code, non_upper_case_globals)] + +fn main() { + const Foo: [i32; _] = [1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + const REF_FOO: &[u8; _] = &[1]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let foo: [i32; _] = [1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let bar: [i32; _] = [0; 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let ref_foo: &[i32; _] = &[1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let ref_bar: &[i32; _] = &[0; 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable + let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; + //~^ ERROR in expressions, `_` can only be used on the left-hand side of an assignment + //~| ERROR using `_` for array lengths is unstable +} diff --git a/tests/ui/array-slice-vec/suggest-array-length.stderr b/tests/ui/array-slice-vec/suggest-array-length.stderr new file mode 100644 index 000000000..16c90a047 --- /dev/null +++ b/tests/ui/array-slice-vec/suggest-array-length.stderr @@ -0,0 +1,108 @@ +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:11:20 + | +LL | let foo: [i32; _] = [1, 2, 3]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:14:20 + | +LL | let bar: [i32; _] = [0; 3]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:17:25 + | +LL | let ref_foo: &[i32; _] = &[1, 2, 3]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:20:25 + | +LL | let ref_bar: &[i32; _] = &[0; 3]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:23:35 + | +LL | let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:5:22 + | +LL | const Foo: [i32; _] = [1, 2, 3]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/suggest-array-length.rs:8:26 + | +LL | const REF_FOO: &[u8; _] = &[1]; + | ^ `_` not allowed here + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:5:22 + | +LL | const Foo: [i32; _] = [1, 2, 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:8:26 + | +LL | const REF_FOO: &[u8; _] = &[1]; + | ^ help: consider specifying the array length: `1` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:11:20 + | +LL | let foo: [i32; _] = [1, 2, 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:14:20 + | +LL | let bar: [i32; _] = [0; 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:17:25 + | +LL | let ref_foo: &[i32; _] = &[1, 2, 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:20:25 + | +LL | let ref_bar: &[i32; _] = &[0; 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/suggest-array-length.rs:23:35 + | +LL | let multiple_ref_foo: &&[i32; _] = &&[1, 2, 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/array-slice-vec/variance-vec-covariant.rs b/tests/ui/array-slice-vec/variance-vec-covariant.rs new file mode 100644 index 000000000..d7e64132f --- /dev/null +++ b/tests/ui/array-slice-vec/variance-vec-covariant.rs @@ -0,0 +1,20 @@ +// run-pass + +// Test that vec is now covariant in its argument type. + +#![allow(dead_code)] + +fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 { + bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b +} + +fn bar<'c>(v1: Vec<&'c i32>, v2: Vec<&'c i32>) -> Option<&'c i32> { + v1.get(0).cloned().or_else(|| v2.get(0).cloned()) +} + +fn main() { + let x = 22; + let y = 44; + assert_eq!(foo(vec![&x], vec![&y]), 22); + assert_eq!(foo(vec![&y], vec![&x]), 44); +} diff --git a/tests/ui/array-slice-vec/vec-dst.rs b/tests/ui/array-slice-vec/vec-dst.rs new file mode 100644 index 000000000..c58ddbc42 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-dst.rs @@ -0,0 +1,24 @@ +// run-pass + +pub fn main() { + // Tests for indexing into Box<[T; n]>/& [T; n] + let x: [isize; 3] = [1, 2, 3]; + let mut x: Box<[isize; 3]> = x.into(); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + x[1] = 45; + assert_eq!(x[0], 1); + assert_eq!(x[1], 45); + assert_eq!(x[2], 3); + + let mut x: [isize; 3] = [1, 2, 3]; + let x: &mut [isize; 3] = &mut x; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + x[1] = 45; + assert_eq!(x[0], 1); + assert_eq!(x[1], 45); + assert_eq!(x[2], 3); +} diff --git a/tests/ui/array-slice-vec/vec-fixed-length.rs b/tests/ui/array-slice-vec/vec-fixed-length.rs new file mode 100644 index 000000000..908c39c79 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-fixed-length.rs @@ -0,0 +1,24 @@ +// run-pass + + +use std::mem::size_of; + +#[cfg(not(target_pointer_width = "64"))] +fn test_big_vec() {} + +#[cfg(target_pointer_width = "64")] +fn test_big_vec() +{ + assert_eq!(size_of::<[u8; 1 << 32]>(), (1 << 32)); +} + +fn main() { + let x: [isize; 4] = [1, 2, 3, 4]; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + assert_eq!(x[3], 4); + + assert_eq!(size_of::<[u8; 4]>(), 4); + test_big_vec(); +} diff --git a/tests/ui/array-slice-vec/vec-late-init.rs b/tests/ui/array-slice-vec/vec-late-init.rs new file mode 100644 index 000000000..5dee36082 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-late-init.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_mut)] + + +pub fn main() { + let mut later: Vec ; + if true { later = vec![1]; } else { later = vec![2]; } + println!("{}", later[0]); +} diff --git a/tests/ui/array-slice-vec/vec-macro-no-std.rs b/tests/ui/array-slice-vec/vec-macro-no-std.rs new file mode 100644 index 000000000..443895f7c --- /dev/null +++ b/tests/ui/array-slice-vec/vec-macro-no-std.rs @@ -0,0 +1,27 @@ +// run-pass + +// ignore-emscripten no no_std executables + +#![feature(lang_items, start, rustc_private)] +#![no_std] + +extern crate std as other; + +extern crate libc; + +#[macro_use] +extern crate alloc; + +use alloc::vec::Vec; + +// Issue #16806 + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + let x: Vec = vec![0, 1, 2]; + match x.last() { + Some(&2) => (), + _ => panic!(), + } + 0 +} diff --git a/tests/ui/array-slice-vec/vec-macro-rvalue-scope.rs b/tests/ui/array-slice-vec/vec-macro-rvalue-scope.rs new file mode 100644 index 000000000..bde010371 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-macro-rvalue-scope.rs @@ -0,0 +1,11 @@ +// run-pass + + +fn one() -> i32 { 1 } + +// Make sure the vec![...] macro doesn't introduce hidden rvalue +// scopes (such as blocks) around the element expressions. +pub fn main() { + assert_eq!(vec![&one(), &one(), &2], vec![&1, &1, &(one()+one())]); + assert_eq!(vec![&one(); 2], vec![&1, &one()]); +} diff --git a/tests/ui/array-slice-vec/vec-macro-with-brackets.rs b/tests/ui/array-slice-vec/vec-macro-with-brackets.rs new file mode 100644 index 000000000..6c95bd500 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-macro-with-brackets.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_variables)] + +// pretty-expanded FIXME #23616 + +macro_rules! vec [ + ($($e:expr),*) => ({ + let mut _temp = ::std::vec::Vec::new(); + $(_temp.push($e);)* + _temp + }) +]; + +pub fn main() { + let my_vec = vec![1, 2, 3, 4, 5]; +} diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs b/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs new file mode 100644 index 000000000..574a53c58 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.rs @@ -0,0 +1,3 @@ +pub fn main() { + vec![,]; //~ ERROR no rules expected the token `,` +} diff --git a/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr new file mode 100644 index 000000000..ec4a001f4 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-macro-with-comma-only.stderr @@ -0,0 +1,10 @@ +error: no rules expected the token `,` + --> $DIR/vec-macro-with-comma-only.rs:2:10 + | +LL | vec![,]; + | ^ no rules expected this token in macro call + | + = note: while trying to match end of macro + +error: aborting due to previous error + diff --git a/tests/ui/array-slice-vec/vec-macro-with-trailing-comma.rs b/tests/ui/array-slice-vec/vec-macro-with-trailing-comma.rs new file mode 100644 index 000000000..f7a51f9c4 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-macro-with-trailing-comma.rs @@ -0,0 +1,8 @@ +// run-pass + + + +pub fn main() { + assert_eq!(vec![1], vec![1,]); + assert_eq!(vec![1, 2, 3], vec![1, 2, 3,]); +} diff --git a/tests/ui/array-slice-vec/vec-matching-autoslice.rs b/tests/ui/array-slice-vec/vec-matching-autoslice.rs new file mode 100644 index 000000000..8179edf42 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-matching-autoslice.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 + +pub fn main() { + let x = [1, 2, 3]; + match x { + [2, _, _] => panic!(), + [1, a, b] => { + assert_eq!([a, b], [2, 3]); + } + [_, _, _] => panic!(), + } + + let y = ([(1, true), (2, false)], 0.5f64); + match y { + ([(1, a), (b, false)], _) => { + assert_eq!(a, true); + assert_eq!(b, 2); + } + ([_, _], 0.5) => panic!(), + ([_, _], _) => panic!(), + } +} diff --git a/tests/ui/array-slice-vec/vec-matching-fixed.rs b/tests/ui/array-slice-vec/vec-matching-fixed.rs new file mode 100644 index 000000000..fdeb7e4fd --- /dev/null +++ b/tests/ui/array-slice-vec/vec-matching-fixed.rs @@ -0,0 +1,30 @@ +// run-pass + +fn a() { + let x = [1, 2, 3]; + match x { + [1, 2, 4] => unreachable!(), + [0, 2, 3, ..] => unreachable!(), + [0, .., 3] => unreachable!(), + [0, ..] => unreachable!(), + [1, 2, 3] => (), + [_, _, _] => unreachable!(), + } + match x { + [..] => (), + } + match x { + [_, _, _, ..] => (), + } + match x { + [a, b, c] => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +pub fn main() { + a(); +} diff --git a/tests/ui/array-slice-vec/vec-matching-fold.rs b/tests/ui/array-slice-vec/vec-matching-fold.rs new file mode 100644 index 000000000..998899271 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-matching-fold.rs @@ -0,0 +1,46 @@ +// run-pass + +use std::fmt::Debug; + +fn foldl(values: &[T], + initial: U, + mut function: F) + -> U where + U: Clone+Debug, T:Debug, + F: FnMut(U, &T) -> U, +{ match values { + &[ref head, ref tail @ ..] => + foldl(tail, function(initial, head), function), + &[] => { + // FIXME: call guards + let res = initial.clone(); res + } + } +} + +fn foldr(values: &[T], + initial: U, + mut function: F) + -> U where + U: Clone, + F: FnMut(&T, U) -> U, +{ + match values { + &[ref head @ .., ref tail] => + foldr(head, function(tail, initial), function), + &[] => { + // FIXME: call guards + let res = initial.clone(); res + } + } +} + +pub fn main() { + let x = &[1, 2, 3, 4, 5]; + + let product = foldl(x, 1, |a, b| a * *b); + assert_eq!(product, 120); + + let sum = foldr(x, 0, |a, b| *a + b); + assert_eq!(sum, 15); +} diff --git a/tests/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/tests/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs new file mode 100644 index 000000000..ed34f074a --- /dev/null +++ b/tests/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(unused_variables)] + +pub fn main() { + let x = &[1, 2, 3, 4, 5]; + let x: &[isize] = &[1, 2, 3, 4, 5]; + if !x.is_empty() { + let el = match x { + &[1, ref tail @ ..] => &tail[0], + _ => unreachable!() + }; + println!("{}", *el); + } +} diff --git a/tests/ui/array-slice-vec/vec-matching.rs b/tests/ui/array-slice-vec/vec-matching.rs new file mode 100644 index 000000000..7009244aa --- /dev/null +++ b/tests/ui/array-slice-vec/vec-matching.rs @@ -0,0 +1,142 @@ +// run-pass + +fn a() { + let x = [1]; + match x { + [a] => { + assert_eq!(a, 1); + } + } +} + +fn b() { + let x = [1, 2, 3]; + match x { + [a, b, c @ ..] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + let expected: &[_] = &[3]; + assert_eq!(c, expected); + } + } + match x { + [a @ .., b, c] => { + let expected: &[_] = &[1]; + assert_eq!(a, expected); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + [a, b @ .., c] => { + assert_eq!(a, 1); + let expected: &[_] = &[2]; + assert_eq!(b, expected); + assert_eq!(c, 3); + } + } + match x { + [a, b, c] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + + +fn b_slice() { + let x : &[_] = &[1, 2, 3]; + match x { + &[a, b, ref c @ ..] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + let expected: &[_] = &[3]; + assert_eq!(c, expected); + } + _ => unreachable!() + } + match x { + &[ref a @ .., b, c] => { + let expected: &[_] = &[1]; + assert_eq!(a, expected); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + _ => unreachable!() + } + match x { + &[a, ref b @ .., c] => { + assert_eq!(a, 1); + let expected: &[_] = &[2]; + assert_eq!(b, expected); + assert_eq!(c, 3); + } + _ => unreachable!() + } + match x { + &[a, b, c] => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + _ => unreachable!() + } +} + +fn c() { + let x = [1]; + match x { + [2, ..] => panic!(), + [..] => () + } +} + +fn d() { + let x = [1, 2, 3]; + let branch = match x { + [1, 1, ..] => 0, + [1, 2, 3, ..] => 1, + [1, 2, ..] => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn e() { + let x: &[isize] = &[1, 2, 3]; + let a = match *x { + [1, 2] => 0, + [..] => 1, + }; + + assert_eq!(a, 1); + + let b = match *x { + [2, ..] => 0, + [1, 2, ..] => 1, + [_] => 2, + [..] => 3 + }; + + assert_eq!(b, 1); + + + let c = match *x { + [_, _, _, _, ..] => 0, + [1, 2, ..] => 1, + [_] => 2, + [..] => 3 + }; + + assert_eq!(c, 1); +} + +pub fn main() { + a(); + b(); + b_slice(); + c(); + d(); + e(); +} diff --git a/tests/ui/array-slice-vec/vec-mut-iter-borrow.rs b/tests/ui/array-slice-vec/vec-mut-iter-borrow.rs new file mode 100644 index 000000000..4aa737446 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-mut-iter-borrow.rs @@ -0,0 +1,7 @@ +fn main() { + let mut xs: Vec = vec![]; + + for x in &mut xs { + xs.push(1) //~ ERROR cannot borrow `xs` + } +} diff --git a/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr b/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr new file mode 100644 index 000000000..0ec263c85 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-mut-iter-borrow.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `xs` as mutable more than once at a time + --> $DIR/vec-mut-iter-borrow.rs:5:9 + | +LL | for x in &mut xs { + | ------- + | | + | first mutable borrow occurs here + | first borrow later used here +LL | xs.push(1) + | ^^^^^^^^^^ second mutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/array-slice-vec/vec-overrun.rs b/tests/ui/array-slice-vec/vec-overrun.rs new file mode 100644 index 000000000..bdc7d507d --- /dev/null +++ b/tests/ui/array-slice-vec/vec-overrun.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:index out of bounds: the len is 1 but the index is 2 +// ignore-emscripten no processes + +fn main() { + let v: Vec = vec![10]; + let x: usize = 0; + assert_eq!(v[x], 10); + // Bounds-check panic. + + assert_eq!(v[x + 2], 20); +} diff --git a/tests/ui/array-slice-vec/vec-repeat-with-cast.rs b/tests/ui/array-slice-vec/vec-repeat-with-cast.rs new file mode 100644 index 000000000..3e0e18873 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-repeat-with-cast.rs @@ -0,0 +1,5 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +pub fn main() { let _a = [0; 1 as usize]; } diff --git a/tests/ui/array-slice-vec/vec-res-add.rs b/tests/ui/array-slice-vec/vec-res-add.rs new file mode 100644 index 000000000..57b552ee5 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-res-add.rs @@ -0,0 +1,19 @@ +#[derive(Debug)] +struct R { + i:isize +} + +fn r(i:isize) -> R { R { i: i } } + +impl Drop for R { + fn drop(&mut self) {} +} + +fn main() { + // This can't make sense as it would copy the classes + let i = vec![r(0)]; + let j = vec![r(1)]; + let k = i + j; + //~^ ERROR cannot add `Vec` to `Vec` + println!("{:?}", j); +} diff --git a/tests/ui/array-slice-vec/vec-res-add.stderr b/tests/ui/array-slice-vec/vec-res-add.stderr new file mode 100644 index 000000000..751127136 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-res-add.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot add `Vec` to `Vec` + --> $DIR/vec-res-add.rs:16:15 + | +LL | let k = i + j; + | - ^ - Vec + | | + | Vec + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/array-slice-vec/vec-tail-matching.rs b/tests/ui/array-slice-vec/vec-tail-matching.rs new file mode 100644 index 000000000..5f1699227 --- /dev/null +++ b/tests/ui/array-slice-vec/vec-tail-matching.rs @@ -0,0 +1,34 @@ +// run-pass + +struct Foo { + string: &'static str +} + +pub fn main() { + let x = [ + Foo { string: "foo" }, + Foo { string: "bar" }, + Foo { string: "baz" } + ]; + match x { + [ref first, ref tail @ ..] => { + assert_eq!(first.string, "foo"); + assert_eq!(tail.len(), 2); + assert_eq!(tail[0].string, "bar"); + assert_eq!(tail[1].string, "baz"); + + match *(tail as &[_]) { + [Foo { .. }, _, Foo { .. }, ref _tail @ ..] => { + unreachable!(); + } + [Foo { string: ref a }, Foo { string: ref b }] => { + assert_eq!("bar", &a[0..a.len()]); + assert_eq!("baz", &b[0..b.len()]); + } + _ => { + unreachable!(); + } + } + } + } +} diff --git a/tests/ui/array-slice-vec/vector-cast-weirdness.rs b/tests/ui/array-slice-vec/vector-cast-weirdness.rs new file mode 100644 index 000000000..e8f2c7147 --- /dev/null +++ b/tests/ui/array-slice-vec/vector-cast-weirdness.rs @@ -0,0 +1,34 @@ +// Issue #14893. Tests that casts from vectors don't behave strangely in the +// presence of the `_` type shorthand notation. +// +// Update: after a change to the way casts are done, we have more type information +// around and so the errors here are no longer exactly the same. +// +// Update: With PR #81479 some of the previously rejected cases are now allowed. +// New test cases added. + +struct X { + y: [u8; 2], +} + +fn main() { + let x1 = X { y: [0, 0] }; + + // No longer a type mismatch - the `_` can be fully resolved by type inference. + let p1: *const u8 = &x1.y as *const _; + let p1: *mut u8 = &x1.y as *mut _; + //~^ ERROR: casting `&[u8; 2]` as `*mut u8` is invalid + let t1: *const [u8; 2] = &x1.y as *const _; + let t1: *mut [u8; 2] = &x1.y as *mut _; + //~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + let h1: *const [u8; 2] = &x1.y as *const [u8; 2]; + let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2]; + //~^ ERROR: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + + let mut x1 = X { y: [0, 0] }; + + let p1: *mut u8 = &mut x1.y as *mut _; + let p2: *const u8 = &mut x1.y as *const _; + let t1: *mut [u8; 2] = &mut x1.y as *mut _; + let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2]; +} diff --git a/tests/ui/array-slice-vec/vector-cast-weirdness.stderr b/tests/ui/array-slice-vec/vector-cast-weirdness.stderr new file mode 100644 index 000000000..6fdb1ac9e --- /dev/null +++ b/tests/ui/array-slice-vec/vector-cast-weirdness.stderr @@ -0,0 +1,21 @@ +error[E0606]: casting `&[u8; 2]` as `*mut u8` is invalid + --> $DIR/vector-cast-weirdness.rs:19:23 + | +LL | let p1: *mut u8 = &x1.y as *mut _; + | ^^^^^^^^^^^^^^^ + +error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + --> $DIR/vector-cast-weirdness.rs:22:28 + | +LL | let t1: *mut [u8; 2] = &x1.y as *mut _; + | ^^^^^^^^^^^^^^^ + +error[E0606]: casting `&[u8; 2]` as `*mut [u8; 2]` is invalid + --> $DIR/vector-cast-weirdness.rs:25:28 + | +LL | let t1: *mut [u8; 2] = &x1.y as *mut [u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/array-slice-vec/vector-no-ann-2.rs b/tests/ui/array-slice-vec/vector-no-ann-2.rs new file mode 100644 index 000000000..e2055f551 --- /dev/null +++ b/tests/ui/array-slice-vec/vector-no-ann-2.rs @@ -0,0 +1,7 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +pub fn main() { + let _quux: Box> = Box::new(Vec::new()); +} diff --git a/tests/ui/array-slice-vec/vector-no-ann.rs b/tests/ui/array-slice-vec/vector-no-ann.rs new file mode 100644 index 000000000..1f11d9c8d --- /dev/null +++ b/tests/ui/array-slice-vec/vector-no-ann.rs @@ -0,0 +1,4 @@ +fn main() { + let _foo = Vec::new(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr new file mode 100644 index 000000000..d2ea08aa4 --- /dev/null +++ b/tests/ui/array-slice-vec/vector-no-ann.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Vec` + --> $DIR/vector-no-ann.rs:2:9 + | +LL | let _foo = Vec::new(); + | ^^^^ + | +help: consider giving `_foo` an explicit type, where the type for type parameter `T` is specified + | +LL | let _foo: Vec = Vec::new(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/artificial-block.rs b/tests/ui/artificial-block.rs new file mode 100644 index 000000000..2e383e1a7 --- /dev/null +++ b/tests/ui/artificial-block.rs @@ -0,0 +1,5 @@ +// run-pass + +fn f() -> isize { { return 3; } } + +pub fn main() { assert_eq!(f(), 3); } diff --git a/tests/ui/as-precedence.rs b/tests/ui/as-precedence.rs new file mode 100644 index 000000000..feb0cb30c --- /dev/null +++ b/tests/ui/as-precedence.rs @@ -0,0 +1,10 @@ +// run-pass + +#[allow(unused_parens)] +fn main() { + assert_eq!(3 as usize * 3, 9); + assert_eq!(3 as (usize) * 3, 9); + assert_eq!(3 as (usize) / 3, 1); + assert_eq!(3 as usize + 3, 6); + assert_eq!(3 as (usize) + 3, 6); +} diff --git a/tests/ui/asm/aarch64/bad-options.rs b/tests/ui/asm/aarch64/bad-options.rs new file mode 100644 index 000000000..6172027a2 --- /dev/null +++ b/tests/ui/asm/aarch64/bad-options.rs @@ -0,0 +1,39 @@ +// only-aarch64 + +use std::arch::{asm, global_asm}; + +fn main() { + let mut foo = 0; + unsafe { + asm!("", options(nomem, readonly)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + asm!("", options(pure, nomem, noreturn)); + //~^ ERROR the `pure` and `noreturn` options are mutually exclusive + //~^^ ERROR asm with the `pure` option must have at least one output + asm!("{}", in(reg) foo, options(pure, nomem)); + //~^ ERROR asm with the `pure` option must have at least one output + asm!("{}", out(reg) foo, options(noreturn)); + //~^ ERROR asm outputs are not allowed with the `noreturn` option + } + + unsafe { + asm!("", clobber_abi("foo")); + //~^ ERROR invalid ABI for `clobber_abi` + asm!("{}", out(reg) foo, clobber_abi("C")); + //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs + asm!("", out("x0") foo, clobber_abi("C")); + } +} + +global_asm!("", options(nomem)); +//~^ ERROR expected one of +global_asm!("", options(readonly)); +//~^ ERROR expected one of +global_asm!("", options(noreturn)); +//~^ ERROR expected one of +global_asm!("", options(pure)); +//~^ ERROR expected one of +global_asm!("", options(nostack)); +//~^ ERROR expected one of +global_asm!("", options(preserves_flags)); +//~^ ERROR expected one of diff --git a/tests/ui/asm/aarch64/bad-options.stderr b/tests/ui/asm/aarch64/bad-options.stderr new file mode 100644 index 000000000..21bcc4a9c --- /dev/null +++ b/tests/ui/asm/aarch64/bad-options.stderr @@ -0,0 +1,84 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/bad-options.rs:8:18 + | +LL | asm!("", options(nomem, readonly)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with the `pure` option must have at least one output + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with the `pure` option must have at least one output + --> $DIR/bad-options.rs:13:33 + | +LL | asm!("{}", in(reg) foo, options(pure, nomem)); + | ^^^^^^^^^^^^^^^^^^^^ + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/bad-options.rs:15:20 + | +LL | asm!("{}", out(reg) foo, options(noreturn)); + | ^^^^^^^^^^^^ + +error: asm with `clobber_abi` must specify explicit registers for outputs + --> $DIR/bad-options.rs:22:20 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C")); + | ^^^^^^^^^^^^ ---------------- clobber_abi + | | + | generic outputs + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/bad-options.rs:28:25 + | +LL | global_asm!("", options(nomem)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` + --> $DIR/bad-options.rs:30:25 + | +LL | global_asm!("", options(readonly)); + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` + --> $DIR/bad-options.rs:32:25 + | +LL | global_asm!("", options(noreturn)); + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `pure` + --> $DIR/bad-options.rs:34:25 + | +LL | global_asm!("", options(pure)); + | ^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` + --> $DIR/bad-options.rs:36:25 + | +LL | global_asm!("", options(nostack)); + | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` + --> $DIR/bad-options.rs:38:25 + | +LL | global_asm!("", options(preserves_flags)); + | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-options.rs:20:18 + | +LL | asm!("", clobber_abi("foo")); + | ^^^^^^^^^^^^^^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi` + +error: aborting due to 13 previous errors + diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs new file mode 100644 index 000000000..9ccb8ed67 --- /dev/null +++ b/tests/ui/asm/aarch64/bad-reg.rs @@ -0,0 +1,61 @@ +// only-aarch64 +// compile-flags: -C target-feature=+neon + +#![feature(asm_const)] + +use std::arch::asm; + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + // Bad register/register class + + asm!("{}", in(foo) foo); + //~^ ERROR invalid register class `foo`: unknown register class + asm!("", in("foo") foo); + //~^ ERROR invalid register `foo`: unknown register + asm!("{:z}", in(reg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:r}", in(vreg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:r}", in(vreg_low16) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:a}", const 0); + //~^ ERROR asm template modifiers are not allowed for `const` arguments + asm!("{:a}", sym main); + //~^ ERROR asm template modifiers are not allowed for `sym` arguments + asm!("", in("x29") foo); + //~^ ERROR invalid register `x29`: the frame pointer cannot be used as an operand + asm!("", in("sp") foo); + //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand + asm!("", in("xzr") foo); + //~^ ERROR invalid register `xzr`: the zero register cannot be used as an operand + asm!("", in("x19") foo); + //~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm + + asm!("", in("p0") foo); + //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + //~| ERROR type `i32` cannot be used with this register class + asm!("", out("p0") _); + asm!("{}", in(preg) foo); + //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + //~| ERROR type `i32` cannot be used with this register class + asm!("{}", out(preg) _); + //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output + + // Explicit register conflicts + // (except in/lateout which don't conflict) + + asm!("", in("x0") foo, in("w0") bar); + //~^ ERROR register `x0` conflicts with register `x0` + asm!("", in("x0") foo, out("x0") bar); + //~^ ERROR register `x0` conflicts with register `x0` + asm!("", in("w0") foo, lateout("w0") bar); + asm!("", in("v0") foo, in("q0") bar); + //~^ ERROR register `v0` conflicts with register `v0` + asm!("", in("v0") foo, out("q0") bar); + //~^ ERROR register `v0` conflicts with register `v0` + asm!("", in("v0") foo, lateout("q0") bar); + } +} diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr new file mode 100644 index 000000000..0ba627dac --- /dev/null +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -0,0 +1,162 @@ +error: invalid register class `foo`: unknown register class + --> $DIR/bad-reg.rs:14:20 + | +LL | asm!("{}", in(foo) foo); + | ^^^^^^^^^^^ + +error: invalid register `foo`: unknown register + --> $DIR/bad-reg.rs:16:18 + | +LL | asm!("", in("foo") foo); + | ^^^^^^^^^^^^^ + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:18:15 + | +LL | asm!("{:z}", in(reg) foo); + | ^^^^ ----------- argument + | | + | template modifier + | + = note: the `reg` register class supports the following template modifiers: `w`, `x` + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:20:15 + | +LL | asm!("{:r}", in(vreg) foo); + | ^^^^ ------------ argument + | | + | template modifier + | + = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v` + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:22:15 + | +LL | asm!("{:r}", in(vreg_low16) foo); + | ^^^^ ------------------ argument + | | + | template modifier + | + = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v` + +error: asm template modifiers are not allowed for `const` arguments + --> $DIR/bad-reg.rs:24:15 + | +LL | asm!("{:a}", const 0); + | ^^^^ ------- argument + | | + | template modifier + +error: asm template modifiers are not allowed for `sym` arguments + --> $DIR/bad-reg.rs:26:15 + | +LL | asm!("{:a}", sym main); + | ^^^^ -------- argument + | | + | template modifier + +error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", in("x29") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", in("sp") foo); + | ^^^^^^^^^^^^ + +error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", in("xzr") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:34:18 + | +LL | asm!("", in("x19") foo); + | ^^^^^^^^^^^^^ + +error: register class `preg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:37:18 + | +LL | asm!("", in("p0") foo); + | ^^^^^^^^^^^^ + +error: register class `preg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:41:20 + | +LL | asm!("{}", in(preg) foo); + | ^^^^^^^^^^^^ + +error: register class `preg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:44:20 + | +LL | asm!("{}", out(preg) _); + | ^^^^^^^^^^^ + +error: register `x0` conflicts with register `x0` + --> $DIR/bad-reg.rs:50:32 + | +LL | asm!("", in("x0") foo, in("w0") bar); + | ------------ ^^^^^^^^^^^^ register `x0` + | | + | register `x0` + +error: register `x0` conflicts with register `x0` + --> $DIR/bad-reg.rs:52:32 + | +LL | asm!("", in("x0") foo, out("x0") bar); + | ------------ ^^^^^^^^^^^^^ register `x0` + | | + | register `x0` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:52:18 + | +LL | asm!("", in("x0") foo, out("x0") bar); + | ^^^^^^^^^^^^ + +error: register `v0` conflicts with register `v0` + --> $DIR/bad-reg.rs:55:32 + | +LL | asm!("", in("v0") foo, in("q0") bar); + | ------------ ^^^^^^^^^^^^ register `v0` + | | + | register `v0` + +error: register `v0` conflicts with register `v0` + --> $DIR/bad-reg.rs:57:32 + | +LL | asm!("", in("v0") foo, out("q0") bar); + | ------------ ^^^^^^^^^^^^^ register `v0` + | | + | register `v0` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", in("v0") foo, out("q0") bar); + | ^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:37:27 + | +LL | asm!("", in("p0") foo); + | ^^^ + | + = note: register class `preg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:41:29 + | +LL | asm!("{}", in(preg) foo); + | ^^^ + | + = note: register class `preg` supports these types: + +error: aborting due to 20 previous errors + diff --git a/tests/ui/asm/aarch64/const.rs b/tests/ui/asm/aarch64/const.rs new file mode 100644 index 000000000..de299bfdb --- /dev/null +++ b/tests/ui/asm/aarch64/const.rs @@ -0,0 +1,44 @@ +// only-aarch64 +// run-pass +// needs-asm-support +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +fn const_generic() -> usize { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const X); + a + } +} + +const fn constfn(x: usize) -> usize { + x +} + +fn main() { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const 5); + assert_eq!(a, 5); + + let b: usize; + asm!("mov {}, {}", out(reg) b, const constfn(5)); + assert_eq!(b, 5); + + let c: usize; + asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5)); + assert_eq!(c, 10); + } + + let d = const_generic::<5>(); + assert_eq!(d, 5); +} + +global_asm!("mov x0, {}", const 5); +global_asm!("mov x0, {}", const constfn(5)); +global_asm!("mov x0, {}", const constfn(5) + constfn(5)); diff --git a/tests/ui/asm/aarch64/duplicate-options.fixed b/tests/ui/asm/aarch64/duplicate-options.fixed new file mode 100644 index 000000000..fa1dd4aef --- /dev/null +++ b/tests/ui/asm/aarch64/duplicate-options.fixed @@ -0,0 +1,27 @@ +// only-aarch64 +// needs-asm-support +// run-rustfix + +use std::arch::asm; + +fn main() { + unsafe { + asm!("", options(nomem, )); + //~^ ERROR the `nomem` option was already provided + asm!("", options(preserves_flags, )); + //~^ ERROR the `preserves_flags` option was already provided + asm!("", options(nostack, preserves_flags), options()); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, ), options(), options()); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(preserves_flags, ), //~ ERROR the `noreturn` option was already provided + options( nostack), //~ ERROR the `nomem` option was already provided + options(), //~ ERROR the `noreturn` option was already provided + ); + } +} diff --git a/tests/ui/asm/aarch64/duplicate-options.rs b/tests/ui/asm/aarch64/duplicate-options.rs new file mode 100644 index 000000000..b2d3fe7d9 --- /dev/null +++ b/tests/ui/asm/aarch64/duplicate-options.rs @@ -0,0 +1,27 @@ +// only-aarch64 +// needs-asm-support +// run-rustfix + +use std::arch::asm; + +fn main() { + unsafe { + asm!("", options(nomem, nomem)); + //~^ ERROR the `nomem` option was already provided + asm!("", options(preserves_flags, preserves_flags)); + //~^ ERROR the `preserves_flags` option was already provided + asm!("", options(nostack, preserves_flags), options(nostack)); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, nostack), options(nostack), options(nostack)); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(preserves_flags, noreturn), //~ ERROR the `noreturn` option was already provided + options(nomem, nostack), //~ ERROR the `nomem` option was already provided + options(noreturn), //~ ERROR the `noreturn` option was already provided + ); + } +} diff --git a/tests/ui/asm/aarch64/duplicate-options.stderr b/tests/ui/asm/aarch64/duplicate-options.stderr new file mode 100644 index 000000000..feb3838f4 --- /dev/null +++ b/tests/ui/asm/aarch64/duplicate-options.stderr @@ -0,0 +1,56 @@ +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:9:33 + | +LL | asm!("", options(nomem, nomem)); + | ^^^^^ this option was already provided + +error: the `preserves_flags` option was already provided + --> $DIR/duplicate-options.rs:11:43 + | +LL | asm!("", options(preserves_flags, preserves_flags)); + | ^^^^^^^^^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:13:61 + | +LL | asm!("", options(nostack, preserves_flags), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:15:35 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:15:53 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:15:71 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:22:38 + | +LL | options(preserves_flags, noreturn), + | ^^^^^^^^ this option was already provided + +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:23:21 + | +LL | options(nomem, nostack), + | ^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:24:21 + | +LL | options(noreturn), + | ^^^^^^^^ this option was already provided + +error: aborting due to 9 previous errors + diff --git a/tests/ui/asm/aarch64/interpolated-idents.rs b/tests/ui/asm/aarch64/interpolated-idents.rs new file mode 100644 index 000000000..e87a88434 --- /dev/null +++ b/tests/ui/asm/aarch64/interpolated-idents.rs @@ -0,0 +1,24 @@ +// only-aarch64 +// needs-asm-support +use std::arch::asm; + +macro_rules! m { + ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident + $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident + $noreturn:ident $nostack:ident $options:ident) => { + unsafe { + asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, + //~^ ERROR asm outputs are not allowed with the `noreturn` option + const x, sym x, + $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + //~| ERROR the `pure` and `noreturn` options are mutually exclusive + } + }; +} + +fn main() { + m!(in out lateout inout inlateout const sym + pure nomem readonly preserves_flags + noreturn nostack options); +} diff --git a/tests/ui/asm/aarch64/interpolated-idents.stderr b/tests/ui/asm/aarch64/interpolated-idents.stderr new file mode 100644 index 000000000..f6c50c2e1 --- /dev/null +++ b/tests/ui/asm/aarch64/interpolated-idents.stderr @@ -0,0 +1,46 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/interpolated-idents.rs:13:13 + | +LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack options); + | |________________________________- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/interpolated-idents.rs:13:13 + | +LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack options); + | |________________________________- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/interpolated-idents.rs:10:32 + | +LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, + | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack options); + | | - + | |________________________________| + | |________________________________in this macro invocation + | |________________________________in this macro invocation + | |________________________________in this macro invocation + | in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/asm/aarch64/llvm-58384.rs b/tests/ui/asm/aarch64/llvm-58384.rs new file mode 100644 index 000000000..308f78908 --- /dev/null +++ b/tests/ui/asm/aarch64/llvm-58384.rs @@ -0,0 +1,16 @@ +// only-aarch64 +// run-pass +// needs-asm-support + +// Test that we properly work around this LLVM issue: +// https://github.com/llvm/llvm-project/issues/58384 + +use std::arch::asm; + +fn main() { + let a: i32; + unsafe { + asm!("", inout("x0") 435 => a); + } + assert_eq!(a, 435); +} diff --git a/tests/ui/asm/aarch64/may_unwind.rs b/tests/ui/asm/aarch64/may_unwind.rs new file mode 100644 index 000000000..6af8728bb --- /dev/null +++ b/tests/ui/asm/aarch64/may_unwind.rs @@ -0,0 +1,37 @@ +// only-aarch64 +// run-pass +// needs-asm-support + +#![feature(asm_unwind)] + +use std::arch::asm; +use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; + +struct Foo<'a>(&'a mut bool); + +impl Drop for Foo<'_> { + fn drop(&mut self) { + *self.0 = false; + } +} + +extern "C" fn panicky() { + resume_unwind(Box::new(())); +} + +fn main() { + let flag = &mut true; + catch_unwind(AssertUnwindSafe(|| { + let _foo = Foo(flag); + unsafe { + asm!( + "bl {}", + sym panicky, + clobber_abi("C"), + options(may_unwind) + ); + } + })) + .expect_err("expected a panic"); + assert_eq!(*flag, false); +} diff --git a/tests/ui/asm/aarch64/parse-error.rs b/tests/ui/asm/aarch64/parse-error.rs new file mode 100644 index 000000000..cbc93cd3f --- /dev/null +++ b/tests/ui/asm/aarch64/parse-error.rs @@ -0,0 +1,133 @@ +// only-aarch64 + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + asm!(); + //~^ ERROR requires at least a template string argument + asm!(foo); + //~^ ERROR asm template must be a string literal + asm!("{}" foo); + //~^ ERROR expected token: `,` + asm!("{}", foo); + //~^ ERROR expected operand, clobber_abi, options, or additional template string + asm!("{}", in foo); + //~^ ERROR expected `(`, found `foo` + asm!("{}", in(reg foo)); + //~^ ERROR expected `)`, found `foo` + asm!("{}", in(reg)); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", inout(=) foo => bar); + //~^ ERROR expected register class or explicit register + asm!("{}", inout(reg) foo =>); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", in(reg) foo => bar); + //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + asm!("{}", sym foo + bar); + //~^ ERROR expected a path for argument to `sym` + asm!("", options(foo)); + //~^ ERROR expected one of + asm!("", options(nomem foo)); + //~^ ERROR expected one of + asm!("", options(nomem, foo)); + //~^ ERROR expected one of + asm!("{}", options(), const foo); + //~^ ERROR arguments are not allowed after options + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", clobber_abi(foo)); + //~^ ERROR expected string literal + asm!("", clobber_abi("C" foo)); + //~^ ERROR expected one of `)` or `,`, found `foo` + asm!("", clobber_abi("C", foo)); + //~^ ERROR expected string literal + asm!("{}", clobber_abi("C"), const foo); + //~^ ERROR arguments are not allowed after clobber_abi + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", options(), clobber_abi("C")); + //~^ ERROR clobber_abi is not allowed after options + asm!("{}", options(), clobber_abi("C"), const foo); + //~^ ERROR clobber_abi is not allowed after options + asm!("{a}", a = const foo, a = const bar); + //~^ ERROR duplicate argument named `a` + //~^^ ERROR argument never used + //~^^^ ERROR attempt to use a non-constant value in a constant + //~^^^^ ERROR attempt to use a non-constant value in a constant + asm!("", a = in("x0") foo); + //~^ ERROR explicit register arguments cannot have names + asm!("{a}", in("x0") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("{a}", in("x0") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("{1}", in("x0") foo, const bar); + //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", options(), ""); + //~^ ERROR expected one of + asm!("{}", in(reg) foo, "{}", out(reg) foo); + //~^ ERROR expected one of + asm!(format!("{{{}}}", 0), in(reg) foo); + //~^ ERROR asm template must be a string literal + asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + //~^ ERROR asm template must be a string literal + asm!("{}", in(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inout(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inlateout(reg) _); + //~^ ERROR _ cannot be used for input operands + } +} + +const FOO: i32 = 1; +const BAR: i32 = 2; +global_asm!(); +//~^ ERROR requires at least a template string argument +global_asm!(FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{}" FOO); +//~^ ERROR expected token: `,` +global_asm!("{}", FOO); +//~^ ERROR expected operand, options, or additional template string +global_asm!("{}", const); +//~^ ERROR expected expression, found end of macro arguments +global_asm!("{}", const(reg) FOO); +//~^ ERROR expected one of +global_asm!("", options(FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem, FOO)); +//~^ ERROR expected one of +global_asm!("{}", options(), const FOO); +//~^ ERROR arguments are not allowed after options +global_asm!("", clobber_abi(FOO)); +//~^ ERROR expected string literal +global_asm!("", clobber_abi("C" FOO)); +//~^ ERROR expected one of `)` or `,`, found `FOO` +global_asm!("", clobber_abi("C", FOO)); +//~^ ERROR expected string literal +global_asm!("{}", clobber_abi("C"), const FOO); +//~^ ERROR arguments are not allowed after clobber_abi +//~^^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("", options(), clobber_abi("C")); +//~^ ERROR clobber_abi is not allowed after options +global_asm!("{}", options(), clobber_abi("C"), const FOO); +//~^ ERROR clobber_abi is not allowed after options +global_asm!("{a}", a = const FOO, a = const BAR); +//~^ ERROR duplicate argument named `a` +//~^^ ERROR argument never used +global_asm!("", options(), ""); +//~^ ERROR expected one of +global_asm!("{}", const FOO, "{}", const FOO); +//~^ ERROR expected one of +global_asm!(format!("{{{}}}", 0), const FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); +//~^ ERROR asm template must be a string literal diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr new file mode 100644 index 000000000..804966b06 --- /dev/null +++ b/tests/ui/asm/aarch64/parse-error.stderr @@ -0,0 +1,446 @@ +error: requires at least a template string argument + --> $DIR/parse-error.rs:11:9 + | +LL | asm!(); + | ^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:13:14 + | +LL | asm!(foo); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:15:19 + | +LL | asm!("{}" foo); + | ^^^ expected `,` + +error: expected operand, clobber_abi, options, or additional template string + --> $DIR/parse-error.rs:17:20 + | +LL | asm!("{}", foo); + | ^^^ expected operand, clobber_abi, options, or additional template string + +error: expected `(`, found `foo` + --> $DIR/parse-error.rs:19:23 + | +LL | asm!("{}", in foo); + | ^^^ expected `(` + +error: expected `)`, found `foo` + --> $DIR/parse-error.rs:21:27 + | +LL | asm!("{}", in(reg foo)); + | ^^^ expected `)` + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:23:27 + | +LL | asm!("{}", in(reg)); + | ^ expected expression + +error: expected register class or explicit register + --> $DIR/parse-error.rs:25:26 + | +LL | asm!("{}", inout(=) foo => bar); + | ^ + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:27:37 + | +LL | asm!("{}", inout(reg) foo =>); + | ^ expected expression + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + --> $DIR/parse-error.rs:29:32 + | +LL | asm!("{}", in(reg) foo => bar); + | ^^ expected one of 7 possible tokens + +error: expected a path for argument to `sym` + --> $DIR/parse-error.rs:31:24 + | +LL | asm!("{}", sym foo + bar); + | ^^^^^^^^^ + +error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:33:26 + | +LL | asm!("", options(foo)); + | ^^^ expected one of 10 possible tokens + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:35:32 + | +LL | asm!("", options(nomem foo)); + | ^^^ expected one of `)` or `,` + +error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:37:33 + | +LL | asm!("", options(nomem, foo)); + | ^^^ expected one of 10 possible tokens + +error: arguments are not allowed after options + --> $DIR/parse-error.rs:39:31 + | +LL | asm!("{}", options(), const foo); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: expected string literal + --> $DIR/parse-error.rs:42:30 + | +LL | asm!("", clobber_abi(foo)); + | ^^^ not a string literal + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:44:34 + | +LL | asm!("", clobber_abi("C" foo)); + | ^^^ expected one of `)` or `,` + +error: expected string literal + --> $DIR/parse-error.rs:46:35 + | +LL | asm!("", clobber_abi("C", foo)); + | ^^^ not a string literal + +error: arguments are not allowed after clobber_abi + --> $DIR/parse-error.rs:48:38 + | +LL | asm!("{}", clobber_abi("C"), const foo); + | ---------------- ^^^^^^^^^ argument + | | + | clobber_abi + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:51:29 + | +LL | asm!("", options(), clobber_abi("C")); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:53:31 + | +LL | asm!("{}", options(), clobber_abi("C"), const foo); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:55:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:55:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` + +error: explicit register arguments cannot have names + --> $DIR/parse-error.rs:60:18 + | +LL | asm!("", a = in("x0") foo); + | ^^^^^^^^^^^^^^^^ + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:62:35 + | +LL | asm!("{a}", in("x0") foo, a = const bar); + | ------------ ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:65:35 + | +LL | asm!("{a}", in("x0") foo, a = const bar); + | ------------ ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: positional arguments cannot follow named arguments or explicit register arguments + --> $DIR/parse-error.rs:68:35 + | +LL | asm!("{1}", in("x0") foo, const bar); + | ------------ ^^^^^^^^^ positional argument + | | + | explicit register argument + +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` + --> $DIR/parse-error.rs:71:29 + | +LL | asm!("", options(), ""); + | ^^ expected one of 9 possible tokens + +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:73:33 + | +LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); + | ^^^^ expected one of 9 possible tokens + +error: asm template must be a string literal + --> $DIR/parse-error.rs:75:14 + | +LL | asm!(format!("{{{}}}", 0), in(reg) foo); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:77:21 + | +LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:79:28 + | +LL | asm!("{}", in(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:81:31 + | +LL | asm!("{}", inout(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:83:35 + | +LL | asm!("{}", inlateout(reg) _); + | ^ + +error: requires at least a template string argument + --> $DIR/parse-error.rs:90:1 + | +LL | global_asm!(); + | ^^^^^^^^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:92:13 + | +LL | global_asm!(FOO); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:94:18 + | +LL | global_asm!("{}" FOO); + | ^^^ expected `,` + +error: expected operand, options, or additional template string + --> $DIR/parse-error.rs:96:19 + | +LL | global_asm!("{}", FOO); + | ^^^ expected operand, options, or additional template string + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:98:24 + | +LL | global_asm!("{}", const); + | ^ expected expression + +error: expected one of `,`, `.`, `?`, or an operator, found `FOO` + --> $DIR/parse-error.rs:100:30 + | +LL | global_asm!("{}", const(reg) FOO); + | ^^^ expected one of `,`, `.`, `?`, or an operator + +error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` + --> $DIR/parse-error.rs:102:25 + | +LL | global_asm!("", options(FOO)); + | ^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/parse-error.rs:104:25 + | +LL | global_asm!("", options(nomem FOO)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/parse-error.rs:106:25 + | +LL | global_asm!("", options(nomem, FOO)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: arguments are not allowed after options + --> $DIR/parse-error.rs:108:30 + | +LL | global_asm!("{}", options(), const FOO); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: expected string literal + --> $DIR/parse-error.rs:110:29 + | +LL | global_asm!("", clobber_abi(FOO)); + | ^^^ not a string literal + +error: expected one of `)` or `,`, found `FOO` + --> $DIR/parse-error.rs:112:33 + | +LL | global_asm!("", clobber_abi("C" FOO)); + | ^^^ expected one of `)` or `,` + +error: expected string literal + --> $DIR/parse-error.rs:114:34 + | +LL | global_asm!("", clobber_abi("C", FOO)); + | ^^^ not a string literal + +error: arguments are not allowed after clobber_abi + --> $DIR/parse-error.rs:116:37 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ---------------- ^^^^^^^^^ argument + | | + | clobber_abi + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:116:19 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ^^^^^^^^^^^^^^^^ + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:119:28 + | +LL | global_asm!("", options(), clobber_abi("C")); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:121:30 + | +LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:123:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:123:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ^^^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` + +error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` + --> $DIR/parse-error.rs:126:28 + | +LL | global_asm!("", options(), ""); + | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` + +error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:128:30 + | +LL | global_asm!("{}", const FOO, "{}", const FOO); + | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` + +error: asm template must be a string literal + --> $DIR/parse-error.rs:130:13 + | +LL | global_asm!(format!("{{{}}}", 0), const FOO); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:132:20 + | +LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +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` +... +LL | asm!("{}", options(), const foo); + | ^^^ non-constant value + +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` +... +LL | asm!("{}", clobber_abi("C"), const foo); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", in("x0") foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", in("x0") foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{1}", in("x0") foo, const bar); + | ^^^ non-constant value + +error: aborting due to 64 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/aarch64/srcloc.rs b/tests/ui/asm/aarch64/srcloc.rs new file mode 100644 index 000000000..dbb6cbb94 --- /dev/null +++ b/tests/ui/asm/aarch64/srcloc.rs @@ -0,0 +1,129 @@ +// only-aarch64 +// build-fail +// needs-asm-support +// compile-flags: -Ccodegen-units=1 + +use std::arch::asm; + +// Checks that inline asm errors are mapped to the correct line in the source code. + +fn main() { + unsafe { + asm!("invalid_instruction"); + //~^ ERROR: unrecognized instruction mnemonic + + asm!(" + invalid_instruction + "); + //~^^ ERROR: unrecognized instruction mnemonic + + asm!(r#" + invalid_instruction + "#); + //~^^ ERROR: unrecognized instruction mnemonic + + asm!(" + mov x0, x0 + invalid_instruction + mov x0, x0 + "); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!(r#" + mov x0, x0 + invalid_instruction + mov x0, x0 + "#); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!(concat!("invalid", "_", "instruction")); + //~^ ERROR: unrecognized instruction mnemonic + + asm!( + "invalid_instruction", + ); + //~^^ ERROR: unrecognized instruction mnemonic + + asm!( + "mov x0, x0", + "invalid_instruction", + "mov x0, x0", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + "mov x0, x0\n", + "invalid_instruction", + "mov x0, x0", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + "mov x0, x0", + concat!("invalid", "_", "instruction"), + "mov x0, x0", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!("mov x0", ", ", "x0"), + concat!("invalid", "_", "instruction"), + concat!("mov x0", ", ", "x0"), + ); + //~^^^ ERROR: unrecognized instruction mnemonic + + // Make sure template strings get separated + asm!( + "invalid_instruction1", + "invalid_instruction2", + ); + //~^^^ ERROR: unrecognized instruction mnemonic + //~^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + ); + //~^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", + ), + ); + //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^ ERROR: unrecognized instruction mnemonic + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", "\n", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", "\n", + ), + ); + //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^ ERROR: unrecognized instruction mnemonic + //~^^^^^^^^ ERROR: unrecognized instruction mnemonic + + asm!( + "", + "\n", + "invalid_instruction" + ); + //~^^ ERROR: unrecognized instruction mnemonic + } +} diff --git a/tests/ui/asm/aarch64/srcloc.stderr b/tests/ui/asm/aarch64/srcloc.stderr new file mode 100644 index 000000000..2e17b60b9 --- /dev/null +++ b/tests/ui/asm/aarch64/srcloc.stderr @@ -0,0 +1,290 @@ +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:12:15 + | +LL | asm!("invalid_instruction"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:16:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:21:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:27:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:34:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:39:14 + | +LL | asm!(concat!("invalid", "_", "instruction")); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:43:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:49:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:56:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:63:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:70:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:77:14 + | +LL | "invalid_instruction1", + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:78:14 + | +LL | "invalid_instruction2", + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:84:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:84:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:93:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:93:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:97:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction3 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:97:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction4 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:108:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | invalid_instruction1 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:108:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:1 + | +LL | invalid_instruction2 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:112:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction3 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:112:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction4 + | ^ + +error: unrecognized instruction mnemonic + --> $DIR/srcloc.rs:125:14 + | +LL | "invalid_instruction" + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction + | ^ + +error: aborting due to 24 previous errors + diff --git a/tests/ui/asm/aarch64/sym.rs b/tests/ui/asm/aarch64/sym.rs new file mode 100644 index 000000000..6a6cdb00d --- /dev/null +++ b/tests/ui/asm/aarch64/sym.rs @@ -0,0 +1,84 @@ +// only-aarch64 +// only-linux +// needs-asm-support +// run-pass + +#![feature(thread_local)] + +use std::arch::asm; + +extern "C" fn f1() -> i32 { + 111 +} + +// The compiler will generate a shim to hide the caller location parameter. +#[track_caller] +fn f2() -> i32 { + 222 +} + +macro_rules! call { + ($func:path) => { + unsafe { + let result: i32; + asm!("bl {}", sym $func, + out("w0") result, + out("x20") _, out("x21") _, out("x22") _, + out("x23") _, out("x24") _, out("x25") _, + out("x26") _, out("x27") _, out("x28") _, + ); + result + } + } +} + +macro_rules! static_addr { + ($s:expr) => { + unsafe { + let result: *const u32; + asm!( + // ADRP gives the address of a 4KB page from a PC-relative address + "adrp {out}, {sym}", + // We then add the remaining lower 12 bits + "add {out}, {out}, #:lo12:{sym}", + out = out(reg) result, + sym = sym $s); + result + } + } +} +macro_rules! static_tls_addr { + ($s:expr) => { + unsafe { + let result: *const u32; + asm!( + // Load the thread pointer register + "mrs {out}, TPIDR_EL0", + // Add the top 12 bits of the symbol's offset + "add {out}, {out}, :tprel_hi12:{sym}", + // And the bottom 12 bits + "add {out}, {out}, :tprel_lo12_nc:{sym}", + out = out(reg) result, + sym = sym $s + ); + result + } + } +} + +static S1: u32 = 111; +#[thread_local] +static S2: u32 = 222; + +fn main() { + assert_eq!(call!(f1), 111); + assert_eq!(call!(f2), 222); + assert_eq!(static_addr!(S1), &S1 as *const u32); + assert_eq!(static_tls_addr!(S2), &S2 as *const u32); + std::thread::spawn(|| { + assert_eq!(static_addr!(S1), &S1 as *const u32); + assert_eq!(static_tls_addr!(S2), &S2 as *const u32); + }) + .join() + .unwrap(); +} diff --git a/tests/ui/asm/aarch64/type-check-2-2.rs b/tests/ui/asm/aarch64/type-check-2-2.rs new file mode 100644 index 000000000..89f2b3bb7 --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-2-2.rs @@ -0,0 +1,35 @@ +// only-aarch64 + +#![feature(repr_simd, never_type)] + +use std::arch::{asm, global_asm}; + +#[repr(simd)] +#[derive(Clone, Copy)] +struct SimdType(f32, f32, f32, f32); + +#[repr(simd)] +struct SimdNonCopy(f32, f32, f32, f32); + +fn main() { + unsafe { + // Inputs must be initialized + + let x: u64; + asm!("{}", in(reg) x); + //~^ ERROR used binding `x` isn't initialized + let mut y: u64; + asm!("{}", inout(reg) y); + //~^ ERROR used binding `y` isn't initialized + let _ = y; + + // Outputs require mutable places + + let v: Vec = vec![0, 1, 2]; //~ ERROR cannot borrow `v` as mutable + asm!("{}", in(reg) v[0]); + asm!("{}", out(reg) v[0]); + asm!("{}", inout(reg) v[0]); + + // Sym operands must point to a function or static + } +} diff --git a/tests/ui/asm/aarch64/type-check-2-2.stderr b/tests/ui/asm/aarch64/type-check-2-2.stderr new file mode 100644 index 000000000..41f7c01dc --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-2-2.stderr @@ -0,0 +1,46 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/type-check-2-2.rs:19:28 + | +LL | let x: u64; + | - binding declared here but left uninitialized +LL | asm!("{}", in(reg) x); + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u64 = 0; + | +++ + +error[E0381]: used binding `y` isn't initialized + --> $DIR/type-check-2-2.rs:22:9 + | +LL | let mut y: u64; + | ----- binding declared here but left uninitialized +LL | asm!("{}", inout(reg) y); + | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut y: u64 = 0; + | +++ + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-2-2.rs:28:13 + | +LL | let v: Vec = vec![0, 1, 2]; + | ^ not mutable +LL | asm!("{}", in(reg) v[0]); +LL | asm!("{}", out(reg) v[0]); + | - cannot borrow as mutable +LL | asm!("{}", inout(reg) v[0]); + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec = vec![0, 1, 2]; + | +++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0381, E0596. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs new file mode 100644 index 000000000..1c71c1185 --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-2.rs @@ -0,0 +1,76 @@ +// only-aarch64 + +#![feature(repr_simd, never_type)] + +use std::arch::{asm, global_asm}; + +#[repr(simd)] +#[derive(Clone, Copy)] +struct SimdType(f32, f32, f32, f32); + +#[repr(simd)] +struct SimdNonCopy(f32, f32, f32, f32); + +fn main() { + unsafe { + // Inputs must be initialized + + // Sym operands must point to a function or static + + const C: i32 = 0; + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + asm!("{}", sym C); + //~^ ERROR invalid `sym` operand + + // Register operands must be Copy + + asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + //~^ ERROR arguments for inline assembly must be copyable + + // Register operands must be integers, floats, SIMD vectors, pointers or + // function pointers. + + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + asm!("{:v}", in(vreg) SimdType(0.0, 0.0, 0.0, 0.0)); + asm!("{}", in(reg) 0 as *const u8); + asm!("{}", in(reg) 0 as *mut u8); + asm!("{}", in(reg) main as fn()); + asm!("{}", in(reg) |x: i32| x); + //~^ ERROR cannot use value of type + asm!("{}", in(reg) vec![0]); + //~^ ERROR cannot use value of type `Vec` for inline assembly + asm!("{}", in(reg) (1, 2, 3)); + //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly + asm!("{}", in(reg) [1, 2, 3]); + //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly + + // Register inputs (but not outputs) allow references and function types + + let mut f = main; + let mut r = &mut 0; + asm!("{}", in(reg) f); + asm!("{}", inout(reg) f); + //~^ ERROR cannot use value of type `fn() {main}` for inline assembly + asm!("{}", in(reg) r); + asm!("{}", inout(reg) r); + //~^ ERROR cannot use value of type `&mut i32` for inline assembly + let _ = (f, r); + + // Type checks ignore never type + + let u: ! = unreachable!(); + asm!("{}", in(reg) u); + } +} + +// Sym operands must point to a function or static + +const C: i32 = 0; +static S: i32 = 0; +global_asm!("{}", sym S); +global_asm!("{}", sym main); +global_asm!("{}", sym C); +//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr new file mode 100644 index 000000000..875df44ff --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -0,0 +1,75 @@ +error: invalid `sym` operand + --> $DIR/type-check-2.rs:75:19 + | +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/type-check-2.rs:24:20 + | +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: arguments for inline assembly must be copyable + --> $DIR/type-check-2.rs:29:31 + | +LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `SimdNonCopy` does not implement the Copy trait + +error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:36]` for inline assembly + --> $DIR/type-check-2.rs:41:28 + | +LL | asm!("{}", in(reg) |x: i32| x); + | ^^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `Vec` for inline assembly + --> $DIR/type-check-2.rs:43:28 + | +LL | asm!("{}", in(reg) vec![0]); + | ^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot use value of type `(i32, i32, i32)` for inline assembly + --> $DIR/type-check-2.rs:45:28 + | +LL | asm!("{}", in(reg) (1, 2, 3)); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `[i32; 3]` for inline assembly + --> $DIR/type-check-2.rs:47:28 + | +LL | asm!("{}", in(reg) [1, 2, 3]); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `fn() {main}` for inline assembly + --> $DIR/type-check-2.rs:55:31 + | +LL | asm!("{}", inout(reg) f); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `&mut i32` for inline assembly + --> $DIR/type-check-2.rs:58:31 + | +LL | asm!("{}", inout(reg) r); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: aborting due to 9 previous errors + diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs new file mode 100644 index 000000000..623f6593d --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -0,0 +1,97 @@ +// only-aarch64 +// compile-flags: -C target-feature=+neon + +#![feature(repr_simd, stdsimd, asm_const)] + +use std::arch::aarch64::float64x2_t; +use std::arch::{asm, global_asm}; + +#[repr(simd)] +#[derive(Copy, Clone)] +struct Simd256bit(f64, f64, f64, f64); + +fn main() { + let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; + let f64x4 = Simd256bit(0.0, 0.0, 0.0, 0.0); + + unsafe { + // Types must be listed in the register class. + + // Success cases + asm!("{:w}", in(reg) 0u8); + asm!("{:w}", in(reg) 0u16); + asm!("{:w}", in(reg) 0u32); + asm!("{:w}", in(reg) 0f32); + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + + asm!("{:b}", in(vreg) 0u8); + asm!("{:h}", in(vreg) 0u16); + asm!("{:s}", in(vreg) 0u32); + asm!("{:s}", in(vreg) 0f32); + asm!("{:d}", in(vreg) 0u64); + asm!("{:d}", in(vreg) 0f64); + asm!("{:q}", in(vreg) f64x2); + asm!("{:v}", in(vreg) f64x2); + + // Should be the same as vreg + asm!("{:q}", in(vreg_low16) f64x2); + + // Template modifiers of a different size to the argument are fine + asm!("{:w}", in(reg) 0u64); + asm!("{:x}", in(reg) 0u32); + asm!("{:b}", in(vreg) 0u64); + asm!("{:d}", in(vreg_low16) f64x2); + + // Template modifier suggestions for sub-registers + + asm!("{}", in(reg) 0u8); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0u16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0i32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0f32); + //~^ WARN formatting may not be suitable for sub-register argument + + asm!("{}", in(vreg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) 0f32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg) 0f64); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(vreg_low16) 0f64); + //~^ WARN formatting may not be suitable for sub-register argument + + asm!("{0} {0}", in(reg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{0} {0:x}", in(reg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + + // Invalid registers + + asm!("{}", in(reg) 0i128); + //~^ ERROR type `i128` cannot be used with this register class + asm!("{}", in(reg) f64x2); + //~^ ERROR type `float64x2_t` cannot be used with this register class + asm!("{}", in(vreg) f64x4); + //~^ ERROR type `Simd256bit` cannot be used with this register class + + // Split inout operands must have compatible types + + let mut val_i16: i16; + let mut val_f32: f32; + let mut val_u32: u32; + let mut val_u64: u64; + let mut val_ptr: *mut u8; + asm!("{:x}", inout(reg) 0u16 => val_i16); + asm!("{:x}", inout(reg) 0u32 => val_f32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:x}", inout(reg) 0u32 => val_ptr); + //~^ ERROR incompatible types for asm inout argument + asm!("{:x}", inout(reg) main => val_u32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:x}", inout(reg) 0u64 => val_ptr); + asm!("{:x}", inout(reg) main => val_u64); + } +} diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr new file mode 100644 index 000000000..f710df2dc --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-3.stderr @@ -0,0 +1,147 @@ +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:48:15 + | +LL | asm!("{}", in(reg) 0u8); + | ^^ --- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + = note: `#[warn(asm_sub_register)]` on by default + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:50:15 + | +LL | asm!("{}", in(reg) 0u16); + | ^^ ---- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:52:15 + | +LL | asm!("{}", in(reg) 0i32); + | ^^ ---- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:54:15 + | +LL | asm!("{}", in(reg) 0f32); + | ^^ ---- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:57:15 + | +LL | asm!("{}", in(vreg) 0i16); + | ^^ ---- for this argument + | + = help: use `{0:h}` to have the register formatted as `h0` + = help: or use `{0:v}` to keep the default formatting of `v0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:59:15 + | +LL | asm!("{}", in(vreg) 0f32); + | ^^ ---- for this argument + | + = help: use `{0:s}` to have the register formatted as `s0` + = help: or use `{0:v}` to keep the default formatting of `v0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:61:15 + | +LL | asm!("{}", in(vreg) 0f64); + | ^^ ---- for this argument + | + = help: use `{0:d}` to have the register formatted as `d0` + = help: or use `{0:v}` to keep the default formatting of `v0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:63:15 + | +LL | asm!("{}", in(vreg_low16) 0f64); + | ^^ ---- for this argument + | + = help: use `{0:d}` to have the register formatted as `d0` + = help: or use `{0:v}` to keep the default formatting of `v0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:66:15 + | +LL | asm!("{0} {0}", in(reg) 0i16); + | ^^^ ^^^ ---- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:68:15 + | +LL | asm!("{0} {0:x}", in(reg) 0i16); + | ^^^ ---- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + +error: type `i128` cannot be used with this register class + --> $DIR/type-check-3.rs:73:28 + | +LL | asm!("{}", in(reg) 0i128); + | ^^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + +error: type `float64x2_t` cannot be used with this register class + --> $DIR/type-check-3.rs:75:28 + | +LL | asm!("{}", in(reg) f64x2); + | ^^^^^ + | + = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64 + +error: type `Simd256bit` cannot be used with this register class + --> $DIR/type-check-3.rs:77:29 + | +LL | asm!("{}", in(vreg) f64x4); + | ^^^^^ + | + = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:88:33 + | +LL | asm!("{:x}", inout(reg) 0u32 => val_f32); + | ^^^^ ^^^^^^^ type `f32` + | | + | type `u32` + | + = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:90:33 + | +LL | asm!("{:x}", inout(reg) 0u32 => val_ptr); + | ^^^^ ^^^^^^^ type `*mut u8` + | | + | type `u32` + | + = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:92:33 + | +LL | asm!("{:x}", inout(reg) main => val_u32); + | ^^^^ ^^^^^^^ type `u32` + | | + | type `fn()` + | + = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + +error: aborting due to 6 previous errors; 10 warnings emitted + diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs new file mode 100644 index 000000000..bd23755c0 --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -0,0 +1,32 @@ +// only-aarch64 +// compile-flags: -C target-feature=+neon + +#![feature(repr_simd, stdsimd, asm_const)] + +use std::arch::aarch64::float64x2_t; +use std::arch::{asm, global_asm}; + +#[repr(simd)] +#[derive(Copy, Clone)] +struct Simd256bit(f64, f64, f64, f64); + +fn main() { +} + +// Constants must be... constant + +static S: i32 = 1; +const fn const_foo(x: i32) -> i32 { + x +} +const fn const_bar(x: T) -> T { + x +} +global_asm!("{}", const S); +//~^ ERROR constants cannot refer to statics +global_asm!("{}", const const_foo(0)); +global_asm!("{}", const const_foo(S)); +//~^ ERROR constants cannot refer to statics +global_asm!("{}", const const_bar(0)); +global_asm!("{}", const const_bar(S)); +//~^ ERROR constants cannot refer to statics diff --git a/tests/ui/asm/aarch64/type-check-4.stderr b/tests/ui/asm/aarch64/type-check-4.stderr new file mode 100644 index 000000000..4837e647b --- /dev/null +++ b/tests/ui/asm/aarch64/type-check-4.stderr @@ -0,0 +1,27 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/type-check-4.rs:25:25 + | +LL | global_asm!("{}", const S); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/type-check-4.rs:28:35 + | +LL | global_asm!("{}", const const_foo(S)); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/type-check-4.rs:31:35 + | +LL | global_asm!("{}", const const_bar(S)); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/asm/bad-arch.mirunsafeck.stderr b/tests/ui/asm/bad-arch.mirunsafeck.stderr new file mode 100644 index 000000000..d7af29615 --- /dev/null +++ b/tests/ui/asm/bad-arch.mirunsafeck.stderr @@ -0,0 +1,17 @@ +error[E0472]: inline assembly is unsupported on this target + --> $DIR/bad-arch.rs:22:9 + | +LL | asm!(""); + | ^^^^^^^^ + +error[E0472]: inline assembly is unsupported on this target + --> $DIR/bad-arch.rs:27:1 + | +LL | global_asm!(""); + | ^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0472`. diff --git a/tests/ui/asm/bad-arch.rs b/tests/ui/asm/bad-arch.rs new file mode 100644 index 000000000..93309899b --- /dev/null +++ b/tests/ui/asm/bad-arch.rs @@ -0,0 +1,28 @@ +// compile-flags: --target sparc-unknown-linux-gnu +// needs-llvm-components: sparc +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! global_asm { + () => {}; +} +#[lang = "sized"] +trait Sized {} + +fn main() { + unsafe { + asm!(""); + //~^ ERROR inline assembly is unsupported on this target + } +} + +global_asm!(""); +//~^ ERROR inline assembly is unsupported on this target diff --git a/tests/ui/asm/bad-arch.thirunsafeck.stderr b/tests/ui/asm/bad-arch.thirunsafeck.stderr new file mode 100644 index 000000000..d7af29615 --- /dev/null +++ b/tests/ui/asm/bad-arch.thirunsafeck.stderr @@ -0,0 +1,17 @@ +error[E0472]: inline assembly is unsupported on this target + --> $DIR/bad-arch.rs:22:9 + | +LL | asm!(""); + | ^^^^^^^^ + +error[E0472]: inline assembly is unsupported on this target + --> $DIR/bad-arch.rs:27:1 + | +LL | global_asm!(""); + | ^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0472`. diff --git a/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr new file mode 100644 index 000000000..bb6a222b2 --- /dev/null +++ b/tests/ui/asm/bad-template.aarch64_mirunsafeck.stderr @@ -0,0 +1,197 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:31:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:33:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:33:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:36:16 + | +LL | asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:38:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:41:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:41:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:48:15 + | +LL | asm!("{}", in("x0") foo); + | ^^ ------------ explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:48:20 + | +LL | asm!("{}", in("x0") foo); + | ^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:50:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:53:18 + | +LL | asm!("", in(reg) 0, in(reg) 1); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:59:14 + | +LL | global_asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:61:14 + | +LL | global_asm!("{1}", const FOO); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:61:20 + | +LL | global_asm!("{1}", const FOO); + | ^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:64:15 + | +LL | global_asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:66:14 + | +LL | global_asm!("{}", a = const FOO); + | ^^ ------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:69:14 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:69:20 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:72:16 + | +LL | global_asm!("{:foo}", const FOO); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:74:17 + | +LL | global_asm!("", const FOO, const FOO); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/bad-template.rs:50:15 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^^^^ --- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + = note: `#[warn(asm_sub_register)]` on by default + +error: aborting due to 21 previous errors; 1 warning emitted + diff --git a/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr new file mode 100644 index 000000000..bb6a222b2 --- /dev/null +++ b/tests/ui/asm/bad-template.aarch64_thirunsafeck.stderr @@ -0,0 +1,197 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:31:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:33:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:33:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:36:16 + | +LL | asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:38:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:41:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:41:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:48:15 + | +LL | asm!("{}", in("x0") foo); + | ^^ ------------ explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:48:20 + | +LL | asm!("{}", in("x0") foo); + | ^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:50:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:53:18 + | +LL | asm!("", in(reg) 0, in(reg) 1); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:59:14 + | +LL | global_asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:61:14 + | +LL | global_asm!("{1}", const FOO); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:61:20 + | +LL | global_asm!("{1}", const FOO); + | ^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:64:15 + | +LL | global_asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:66:14 + | +LL | global_asm!("{}", a = const FOO); + | ^^ ------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:69:14 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:69:20 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:72:16 + | +LL | global_asm!("{:foo}", const FOO); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:74:17 + | +LL | global_asm!("", const FOO, const FOO); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/bad-template.rs:50:15 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^^^^ --- for this argument + | + = help: use `{0:w}` to have the register formatted as `w0` + = help: or use `{0:x}` to keep the default formatting of `x0` + = note: `#[warn(asm_sub_register)]` on by default + +error: aborting due to 21 previous errors; 1 warning emitted + diff --git a/tests/ui/asm/bad-template.rs b/tests/ui/asm/bad-template.rs new file mode 100644 index 000000000..556371747 --- /dev/null +++ b/tests/ui/asm/bad-template.rs @@ -0,0 +1,75 @@ +// revisions: x86_64_mirunsafeck aarch64_mirunsafeck x86_64_thirunsafeck aarch64_thirunsafeck + +// [x86_64_thirunsafeck] compile-flags: -Z thir-unsafeck --target x86_64-unknown-linux-gnu +// [aarch64_thirunsafeck] compile-flags: -Z thir-unsafeck --target aarch64-unknown-linux-gnu +// [x86_64_mirunsafeck] compile-flags: --target x86_64-unknown-linux-gnu +// [aarch64_mirunsafeck] compile-flags: --target aarch64-unknown-linux-gnu + +// [x86_64_thirunsafeck] needs-llvm-components: x86 +// [x86_64_mirunsafeck] needs-llvm-components: x86 +// [aarch64_thirunsafeck] needs-llvm-components: aarch64 +// [aarch64_mirunsafeck] needs-llvm-components: aarch64 + +#![feature(no_core, lang_items, rustc_attrs, asm_const)] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! global_asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} + +fn main() { + let mut foo = 0; + unsafe { + asm!("{}"); + //~^ ERROR invalid reference to argument at index 0 + asm!("{1}", in(reg) foo); + //~^ ERROR invalid reference to argument at index 1 + //~^^ ERROR argument never used + asm!("{a}"); + //~^ ERROR there is no argument named `a` + asm!("{}", a = in(reg) foo); + //~^ ERROR invalid reference to argument at index 0 + //~^^ ERROR argument never used + asm!("{1}", a = in(reg) foo); + //~^ ERROR invalid reference to argument at index 1 + //~^^ ERROR named argument never used + #[cfg(any(x86_64_thirunsafeck, x86_64_mirunsafeck))] + asm!("{}", in("eax") foo); + //[x86_64_thirunsafeck,x86_64_mirunsafeck]~^ ERROR invalid reference to argument at index 0 + #[cfg(any(aarch64_thirunsafeck, aarch64_mirunsafeck))] + asm!("{}", in("x0") foo); + //[aarch64_thirunsafeck,aarch64_mirunsafeck]~^ ERROR invalid reference to argument at index 0 + asm!("{:foo}", in(reg) foo); + //~^ ERROR asm template modifier must be a single character + //~| WARN formatting may not be suitable for sub-register argument [asm_sub_register] + asm!("", in(reg) 0, in(reg) 1); + //~^ ERROR multiple unused asm arguments + } +} + +const FOO: i32 = 1; +global_asm!("{}"); +//~^ ERROR invalid reference to argument at index 0 +global_asm!("{1}", const FOO); +//~^ ERROR invalid reference to argument at index 1 +//~^^ ERROR argument never used +global_asm!("{a}"); +//~^ ERROR there is no argument named `a` +global_asm!("{}", a = const FOO); +//~^ ERROR invalid reference to argument at index 0 +//~^^ ERROR argument never used +global_asm!("{1}", a = const FOO); +//~^ ERROR invalid reference to argument at index 1 +//~^^ ERROR named argument never used +global_asm!("{:foo}", const FOO); +//~^ ERROR asm template modifier must be a single character +global_asm!("", const FOO, const FOO); +//~^ ERROR multiple unused asm arguments diff --git a/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr new file mode 100644 index 000000000..903b5e959 --- /dev/null +++ b/tests/ui/asm/bad-template.x86_64_mirunsafeck.stderr @@ -0,0 +1,197 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:31:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:33:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:33:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:36:16 + | +LL | asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:38:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:41:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:41:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:45:15 + | +LL | asm!("{}", in("eax") foo); + | ^^ ------------- explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:45:20 + | +LL | asm!("{}", in("eax") foo); + | ^^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:50:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:53:18 + | +LL | asm!("", in(reg) 0, in(reg) 1); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:59:14 + | +LL | global_asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:61:14 + | +LL | global_asm!("{1}", const FOO); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:61:20 + | +LL | global_asm!("{1}", const FOO); + | ^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:64:15 + | +LL | global_asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:66:14 + | +LL | global_asm!("{}", a = const FOO); + | ^^ ------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:69:14 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:69:20 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:72:16 + | +LL | global_asm!("{:foo}", const FOO); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:74:17 + | +LL | global_asm!("", const FOO, const FOO); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/bad-template.rs:50:15 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^^^^ --- for this argument + | + = help: use `{0:e}` to have the register formatted as `eax` + = help: or use `{0:r}` to keep the default formatting of `rax` + = note: `#[warn(asm_sub_register)]` on by default + +error: aborting due to 21 previous errors; 1 warning emitted + diff --git a/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr new file mode 100644 index 000000000..903b5e959 --- /dev/null +++ b/tests/ui/asm/bad-template.x86_64_thirunsafeck.stderr @@ -0,0 +1,197 @@ +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:31:15 + | +LL | asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:33:15 + | +LL | asm!("{1}", in(reg) foo); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:33:21 + | +LL | asm!("{1}", in(reg) foo); + | ^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:36:16 + | +LL | asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:38:15 + | +LL | asm!("{}", a = in(reg) foo); + | ^^ --------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:38:20 + | +LL | asm!("{}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:41:15 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:41:21 + | +LL | asm!("{1}", a = in(reg) foo); + | ^^^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:45:15 + | +LL | asm!("{}", in("eax") foo); + | ^^ ------------- explicit register argument + | | + | from here + | + = note: no positional arguments were given +note: explicit register arguments cannot be used in the asm template + --> $DIR/bad-template.rs:45:20 + | +LL | asm!("{}", in("eax") foo); + | ^^^^^^^^^^^^^ + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:50:17 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:53:18 + | +LL | asm!("", in(reg) 0, in(reg) 1); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:59:14 + | +LL | global_asm!("{}"); + | ^^ from here + | + = note: no arguments were given + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:61:14 + | +LL | global_asm!("{1}", const FOO); + | ^^^ from here + | + = note: there is 1 argument + +error: argument never used + --> $DIR/bad-template.rs:61:20 + | +LL | global_asm!("{1}", const FOO); + | ^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` + +error: there is no argument named `a` + --> $DIR/bad-template.rs:64:15 + | +LL | global_asm!("{a}"); + | ^ + +error: invalid reference to argument at index 0 + --> $DIR/bad-template.rs:66:14 + | +LL | global_asm!("{}", a = const FOO); + | ^^ ------------- named argument + | | + | from here + | + = note: no positional arguments were given +note: named arguments cannot be referenced by position + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ + +error: named argument never used + --> $DIR/bad-template.rs:66:19 + | +LL | global_asm!("{}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: invalid reference to argument at index 1 + --> $DIR/bad-template.rs:69:14 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^ from here + | + = note: no positional arguments were given + +error: named argument never used + --> $DIR/bad-template.rs:69:20 + | +LL | global_asm!("{1}", a = const FOO); + | ^^^^^^^^^^^^^ named argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` + +error: asm template modifier must be a single character + --> $DIR/bad-template.rs:72:16 + | +LL | global_asm!("{:foo}", const FOO); + | ^^^ + +error: multiple unused asm arguments + --> $DIR/bad-template.rs:74:17 + | +LL | global_asm!("", const FOO, const FOO); + | ^^^^^^^^^ ^^^^^^^^^ argument never used + | | + | argument never used + | + = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/bad-template.rs:50:15 + | +LL | asm!("{:foo}", in(reg) foo); + | ^^^^^^ --- for this argument + | + = help: use `{0:e}` to have the register formatted as `eax` + = help: or use `{0:r}` to keep the default formatting of `rax` + = note: `#[warn(asm_sub_register)]` on by default + +error: aborting due to 21 previous errors; 1 warning emitted + diff --git a/tests/ui/asm/generic-const.rs b/tests/ui/asm/generic-const.rs new file mode 100644 index 000000000..caa9b7dbc --- /dev/null +++ b/tests/ui/asm/generic-const.rs @@ -0,0 +1,30 @@ +// needs-asm-support +// build-pass + +#![feature(asm_const)] + +use std::arch::asm; + +fn foofoo() {} + +unsafe fn foo() { + asm!("/* {0} */", const N); + asm!("/* {0} */", const N + 1); + asm!("/* {0} */", sym foofoo::); +} + +fn barbar() {} + +unsafe fn bar() { + asm!("/* {0} */", const std::mem::size_of::()); + asm!("/* {0} */", const std::mem::size_of::<(T, T)>()); + asm!("/* {0} */", sym barbar::); + asm!("/* {0} */", sym barbar::<(T, T)>); +} + +fn main() { + unsafe { + foo::<0>(); + bar::(); + } +} diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr new file mode 100644 index 000000000..1352fb377 --- /dev/null +++ b/tests/ui/asm/inline-syntax.arm.stderr @@ -0,0 +1,88 @@ +error: unknown directive +.intel_syntax noprefix +^ +error: unknown directive +.intel_syntax noprefix +^ +error: unknown directive + | +note: instantiated into assembly here + --> :1:1 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:32:15 + | +LL | asm!(".intel_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:35:15 + | +LL | asm!(".intel_syntax aaa noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax aaa noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:38:15 + | +LL | asm!(".att_syntax noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .att_syntax noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:41:15 + | +LL | asm!(".att_syntax bbb noprefix", "nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .att_syntax bbb noprefix + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:44:15 + | +LL | asm!(".intel_syntax noprefix; nop"); + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | .intel_syntax noprefix; nop + | ^ + +error: unknown directive + --> $DIR/inline-syntax.rs:50:13 + | +LL | .intel_syntax noprefix + | ^ + | +note: instantiated into assembly here + --> :2:13 + | +LL | .intel_syntax noprefix + | ^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs new file mode 100644 index 000000000..d06796e33 --- /dev/null +++ b/tests/ui/asm/inline-syntax.rs @@ -0,0 +1,60 @@ +// revisions: x86_64 arm +//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//[x86_64] check-pass +//[x86_64] needs-llvm-components: x86 +//[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu +//[x86_64_allowed] check-pass +//[x86_64_allowed] needs-llvm-components: x86 +//[arm] compile-flags: --target armv7-unknown-linux-gnueabihf +//[arm] build-fail +//[arm] needs-llvm-components: arm +// needs-asm-support + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] +#![cfg_attr(x86_64_allowed, allow(bad_asm_style))] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! global_asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} + +pub fn main() { + unsafe { + asm!(".intel_syntax noprefix", "nop"); + //[x86_64]~^ WARN avoid using `.intel_syntax` + //[arm]~^^ ERROR unknown directive + asm!(".intel_syntax aaa noprefix", "nop"); + //[x86_64]~^ WARN avoid using `.intel_syntax` + //[arm]~^^ ERROR unknown directive + asm!(".att_syntax noprefix", "nop"); + //[x86_64]~^ WARN avoid using `.att_syntax` + //[arm]~^^ ERROR unknown directive + asm!(".att_syntax bbb noprefix", "nop"); + //[x86_64]~^ WARN avoid using `.att_syntax` + //[arm]~^^ ERROR unknown directive + asm!(".intel_syntax noprefix; nop"); + //[x86_64]~^ WARN avoid using `.intel_syntax` + //[arm]~^^ ERROR unknown directive + + asm!( + r" + .intel_syntax noprefix + nop" + ); + //[x86_64]~^^^ WARN avoid using `.intel_syntax` + //[arm]~^^^^ ERROR unknown directive + } +} + +global_asm!(".intel_syntax noprefix", "nop"); +//[x86_64]~^ WARN avoid using `.intel_syntax` +// Assembler errors don't have line numbers, so no error on ARM diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr new file mode 100644 index 000000000..840b250f8 --- /dev/null +++ b/tests/ui/asm/inline-syntax.x86_64.stderr @@ -0,0 +1,46 @@ +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:58:14 + | +LL | global_asm!(".intel_syntax noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(bad_asm_style)]` on by default + +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:32:15 + | +LL | asm!(".intel_syntax noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:35:15 + | +LL | asm!(".intel_syntax aaa noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + --> $DIR/inline-syntax.rs:38:15 + | +LL | asm!(".att_syntax noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^ + +warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead + --> $DIR/inline-syntax.rs:41:15 + | +LL | asm!(".att_syntax bbb noprefix", "nop"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:44:15 + | +LL | asm!(".intel_syntax noprefix; nop"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: avoid using `.intel_syntax`, Intel syntax is the default + --> $DIR/inline-syntax.rs:50:13 + | +LL | .intel_syntax noprefix + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/tests/ui/asm/issue-72570.rs b/tests/ui/asm/issue-72570.rs new file mode 100644 index 000000000..bb1381634 --- /dev/null +++ b/tests/ui/asm/issue-72570.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zsave-analysis +// needs-asm-support +// Also test for #72960 + +use std::arch::asm; + +fn main() { + unsafe { + asm!("", in("invalid") "".len()); + //~^ ERROR: invalid register `invalid`: unknown register + } +} diff --git a/tests/ui/asm/issue-72570.stderr b/tests/ui/asm/issue-72570.stderr new file mode 100644 index 000000000..fa5792688 --- /dev/null +++ b/tests/ui/asm/issue-72570.stderr @@ -0,0 +1,8 @@ +error: invalid register `invalid`: unknown register + --> $DIR/issue-72570.rs:9:18 + | +LL | asm!("", in("invalid") "".len()); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/asm/issue-85247.rs b/tests/ui/asm/issue-85247.rs new file mode 100644 index 000000000..e64f5e8af --- /dev/null +++ b/tests/ui/asm/issue-85247.rs @@ -0,0 +1,26 @@ +// revisions: ropi rwpi + +// [ropi] compile-flags: --target armv7-unknown-linux-gnueabihf -C relocation-model=ropi +// [rwpi] compile-flags: --target armv7-unknown-linux-gnueabihf -C relocation-model=rwpi +// [ropi] needs-llvm-components: arm +// [rwpi] needs-llvm-components: arm +// [ropi] build-pass + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] +#![crate_type = "rlib"] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[lang = "sized"] +trait Sized {} + +// R9 is reserved as the RWPI base register +fn main() { + unsafe { + asm!("", out("r9") _); + //[rwpi]~^ cannot use register `r9` + } +} diff --git a/tests/ui/asm/issue-85247.rwpi.stderr b/tests/ui/asm/issue-85247.rwpi.stderr new file mode 100644 index 000000000..996b0933a --- /dev/null +++ b/tests/ui/asm/issue-85247.rwpi.stderr @@ -0,0 +1,8 @@ +error: cannot use register `r9`: the RWPI static base register (r9) cannot be used as an operand for inline asm + --> $DIR/issue-85247.rs:23:18 + | +LL | asm!("", out("r9") _); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/asm/issue-87802.rs b/tests/ui/asm/issue-87802.rs new file mode 100644 index 000000000..5b2e636c2 --- /dev/null +++ b/tests/ui/asm/issue-87802.rs @@ -0,0 +1,20 @@ +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 +// Make sure rustc doesn't ICE on asm! when output type is !. + +use std::arch::asm; + +fn hmm() -> ! { + let x; + unsafe { + asm!("/* {0} */", out(reg) x); + //~^ ERROR cannot use value of type `!` for inline assembly + } + x +} + +fn main() { + hmm(); +} diff --git a/tests/ui/asm/issue-87802.stderr b/tests/ui/asm/issue-87802.stderr new file mode 100644 index 000000000..de3e28fdd --- /dev/null +++ b/tests/ui/asm/issue-87802.stderr @@ -0,0 +1,10 @@ +error: cannot use value of type `!` for inline assembly + --> $DIR/issue-87802.rs:12:36 + | +LL | asm!("/* {0} */", out(reg) x); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: aborting due to previous error + diff --git a/tests/ui/asm/issue-89305.rs b/tests/ui/asm/issue-89305.rs new file mode 100644 index 000000000..05677912d --- /dev/null +++ b/tests/ui/asm/issue-89305.rs @@ -0,0 +1,16 @@ +// Regression test for #89305, where a variable was erroneously reported +// as both unused and possibly-uninitialized. + +// check-pass +// needs-asm-support + +#![warn(unused)] + +use std::arch::asm; + +fn main() { + unsafe { + let x: () = asm!("nop"); + //~^ WARNING: unused variable: `x` + } +} diff --git a/tests/ui/asm/issue-89305.stderr b/tests/ui/asm/issue-89305.stderr new file mode 100644 index 000000000..7efc51020 --- /dev/null +++ b/tests/ui/asm/issue-89305.stderr @@ -0,0 +1,15 @@ +warning: unused variable: `x` + --> $DIR/issue-89305.rs:13:13 + | +LL | let x: () = asm!("nop"); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/issue-89305.rs:7:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/tests/ui/asm/issue-92378.rs b/tests/ui/asm/issue-92378.rs new file mode 100644 index 000000000..809b0d155 --- /dev/null +++ b/tests/ui/asm/issue-92378.rs @@ -0,0 +1,31 @@ +// compile-flags: --target armv5te-unknown-linux-gnueabi +// needs-llvm-components: arm +// needs-asm-support +// build-pass + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] +#![crate_type = "rlib"] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[lang = "sized"] +trait Sized {} + +// ARM uses R11 for the frame pointer, make sure R7 is usable. +#[instruction_set(arm::a32)] +pub fn arm() { + unsafe { + asm!("", out("r7") _); + } +} + +// Thumb uses R7 for the frame pointer, make sure R11 is usable. +#[instruction_set(arm::t32)] +pub fn thumb() { + unsafe { + asm!("", out("r11") _); + } +} diff --git a/tests/ui/asm/issue-97490.rs b/tests/ui/asm/issue-97490.rs new file mode 100644 index 000000000..37862cf34 --- /dev/null +++ b/tests/ui/asm/issue-97490.rs @@ -0,0 +1,12 @@ +// check-pass +// only-x86_64 +// needs-asm-support + +pub type Yes = extern "sysv64" fn(&'static u8) -> !; + +fn main() { + unsafe { + let yes = &6 as *const _ as *const Yes; + core::arch::asm!("call {}", in(reg) yes, options(noreturn)); + } +} diff --git a/tests/ui/asm/issue-99071.rs b/tests/ui/asm/issue-99071.rs new file mode 100644 index 000000000..bb6201861 --- /dev/null +++ b/tests/ui/asm/issue-99071.rs @@ -0,0 +1,21 @@ +// compile-flags: --target thumbv6m-none-eabi +// needs-llvm-components: arm +// needs-asm-support + +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] +#![crate_type = "rlib"] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[lang = "sized"] +trait Sized {} + +pub fn foo() { + unsafe { + asm!("", in("r8") 0); + //~^ cannot use register `r8`: high registers (r8+) can only be used as clobbers in Thumb-1 code + } +} diff --git a/tests/ui/asm/issue-99071.stderr b/tests/ui/asm/issue-99071.stderr new file mode 100644 index 000000000..47386ffa4 --- /dev/null +++ b/tests/ui/asm/issue-99071.stderr @@ -0,0 +1,8 @@ +error: cannot use register `r8`: high registers (r8+) can only be used as clobbers in Thumb-1 code + --> $DIR/issue-99071.rs:18:18 + | +LL | asm!("", in("r8") 0); + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/asm/issue-99122-2.rs b/tests/ui/asm/issue-99122-2.rs new file mode 100644 index 000000000..cfb9fd90a --- /dev/null +++ b/tests/ui/asm/issue-99122-2.rs @@ -0,0 +1,21 @@ +// check-pass +// needs-asm-support +// only-x86_64 + +// This demonstrates why we need to erase regions before sized check in intrinsicck + +struct NoCopy; + +struct Wrap<'a, T, Tail: ?Sized>(&'a T, Tail); + +pub unsafe fn test() { + let i = NoCopy; + let j = Wrap(&i, ()); + let pointer = &j as *const _; + core::arch::asm!( + "nop", + in("eax") pointer, + ); +} + +fn main() {} diff --git a/tests/ui/asm/issue-99122.rs b/tests/ui/asm/issue-99122.rs new file mode 100644 index 000000000..744a563d3 --- /dev/null +++ b/tests/ui/asm/issue-99122.rs @@ -0,0 +1,13 @@ +// needs-asm-support +// only-x86_64 + +pub unsafe fn test() { + let pointer = 1u32 as *const _; + //~^ ERROR cannot cast to a pointer of an unknown kind + core::arch::asm!( + "nop", + in("eax") pointer, + ); +} + +fn main() {} diff --git a/tests/ui/asm/issue-99122.stderr b/tests/ui/asm/issue-99122.stderr new file mode 100644 index 000000000..2758a4ac4 --- /dev/null +++ b/tests/ui/asm/issue-99122.stderr @@ -0,0 +1,11 @@ +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/issue-99122.rs:5:27 + | +LL | let pointer = 1u32 as *const _; + | ^^^^^^^^ needs more type information + | + = note: the type information given here is insufficient to check whether the pointer cast is valid + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0641`. diff --git a/tests/ui/asm/may_unwind.rs b/tests/ui/asm/may_unwind.rs new file mode 100644 index 000000000..b9479c44b --- /dev/null +++ b/tests/ui/asm/may_unwind.rs @@ -0,0 +1,10 @@ +// run-pass +// needs-asm-support + +#![feature(asm_unwind)] + +use std::arch::asm; + +fn main() { + unsafe { asm!("", options(may_unwind)) }; +} diff --git a/tests/ui/asm/naked-functions-ffi.rs b/tests/ui/asm/naked-functions-ffi.rs new file mode 100644 index 000000000..c8bee504d --- /dev/null +++ b/tests/ui/asm/naked-functions-ffi.rs @@ -0,0 +1,15 @@ +// check-pass +// needs-asm-support +#![feature(naked_functions)] +#![crate_type = "lib"] + +use std::arch::asm; + +#[naked] +pub extern "C" fn naked(p: char) -> u128 { + //~^ WARN uses type `char` + //~| WARN uses type `u128` + unsafe { + asm!("", options(noreturn)); + } +} diff --git a/tests/ui/asm/naked-functions-ffi.stderr b/tests/ui/asm/naked-functions-ffi.stderr new file mode 100644 index 000000000..908881b19 --- /dev/null +++ b/tests/ui/asm/naked-functions-ffi.stderr @@ -0,0 +1,20 @@ +warning: `extern` fn uses type `char`, which is not FFI-safe + --> $DIR/naked-functions-ffi.rs:9:28 + | +LL | pub extern "C" fn naked(p: char) -> u128 { + | ^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent + = note: `#[warn(improper_ctypes_definitions)]` on by default + +warning: `extern` fn uses type `u128`, which is not FFI-safe + --> $DIR/naked-functions-ffi.rs:9:37 + | +LL | pub extern "C" fn naked(p: char) -> u128 { + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +warning: 2 warnings emitted + diff --git a/tests/ui/asm/naked-functions-unused.aarch64.stderr b/tests/ui/asm/naked-functions-unused.aarch64.stderr new file mode 100644 index 000000000..8d3c300e0 --- /dev/null +++ b/tests/ui/asm/naked-functions-unused.aarch64.stderr @@ -0,0 +1,69 @@ +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:17:32 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/naked-functions-unused.rs:5:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:17:42 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:26:38 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:26:48 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:32:41 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:32:51 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:40:40 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:40:50 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:46:43 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:46:53 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/naked-functions-unused.rs b/tests/ui/asm/naked-functions-unused.rs new file mode 100644 index 000000000..044a0e5b9 --- /dev/null +++ b/tests/ui/asm/naked-functions-unused.rs @@ -0,0 +1,87 @@ +// revisions: x86_64 aarch64 +// needs-asm-support +//[x86_64] only-x86_64 +//[aarch64] only-aarch64 +#![deny(unused)] +#![feature(naked_functions)] +#![crate_type = "lib"] + +pub trait Trait { + extern "C" fn trait_associated(a: usize, b: usize) -> usize; + extern "C" fn trait_method(&self, a: usize, b: usize) -> usize; +} + +pub mod normal { + use std::arch::asm; + + pub extern "C" fn function(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + pub struct Normal; + + impl Normal { + pub extern "C" fn associated(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + } + + impl super::Trait for Normal { + extern "C" fn trait_associated(a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + + extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + //~^ ERROR unused variable: `a` + //~| ERROR unused variable: `b` + unsafe { asm!("", options(noreturn)); } + } + } +} + +pub mod naked { + use std::arch::asm; + + #[naked] + pub extern "C" fn function(a: usize, b: usize) -> usize { + unsafe { asm!("", options(noreturn)); } + } + + pub struct Naked; + + impl Naked { + #[naked] + pub extern "C" fn associated(a: usize, b: usize) -> usize { + unsafe { asm!("", options(noreturn)); } + } + + #[naked] + pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + unsafe { asm!("", options(noreturn)); } + } + } + + impl super::Trait for Naked { + #[naked] + extern "C" fn trait_associated(a: usize, b: usize) -> usize { + unsafe { asm!("", options(noreturn)); } + } + + #[naked] + extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + unsafe { asm!("", options(noreturn)); } + } + } +} diff --git a/tests/ui/asm/naked-functions-unused.x86_64.stderr b/tests/ui/asm/naked-functions-unused.x86_64.stderr new file mode 100644 index 000000000..8d3c300e0 --- /dev/null +++ b/tests/ui/asm/naked-functions-unused.x86_64.stderr @@ -0,0 +1,69 @@ +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:17:32 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/naked-functions-unused.rs:5:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:17:42 + | +LL | pub extern "C" fn function(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:26:38 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:26:48 + | +LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:32:41 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:32:51 + | +LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:40:40 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:40:50 + | +LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/naked-functions-unused.rs:46:43 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/naked-functions-unused.rs:46:53 + | +LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs new file mode 100644 index 000000000..2f3716ca7 --- /dev/null +++ b/tests/ui/asm/naked-functions.rs @@ -0,0 +1,218 @@ +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 + +#![feature(naked_functions)] +#![feature(asm_const, asm_unwind)] +#![crate_type = "lib"] + +use std::arch::asm; + +#[repr(C)] +pub struct P { + x: u8, + y: u16, +} + +#[naked] +pub unsafe extern "C" fn patterns( + mut a: u32, + //~^ ERROR patterns not allowed in naked function parameters + &b: &i32, + //~^ ERROR patterns not allowed in naked function parameters + (None | Some(_)): Option>, + //~^ ERROR patterns not allowed in naked function parameters + P { x, y }: P, + //~^ ERROR patterns not allowed in naked function parameters +) { + asm!("", options(noreturn)) +} + +#[naked] +pub unsafe extern "C" fn inc(a: u32) -> u32 { + //~^ ERROR naked functions must contain a single asm block + a + 1 + //~^ ERROR referencing function parameters is not allowed in naked functions +} + +#[naked] +#[allow(asm_sub_register)] +pub unsafe extern "C" fn inc_asm(a: u32) -> u32 { + asm!("/* {0} */", in(reg) a, options(noreturn)); + //~^ ERROR referencing function parameters is not allowed in naked functions + //~| ERROR only `const` and `sym` operands are supported in naked functions +} + +#[naked] +pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { + //~^ ERROR naked functions must contain a single asm block + (|| a + 1)() +} + +#[naked] +pub unsafe extern "C" fn unsupported_operands() { + //~^ ERROR naked functions must contain a single asm block + let mut a = 0usize; + let mut b = 0usize; + let mut c = 0usize; + let mut d = 0usize; + let mut e = 0usize; + const F: usize = 0usize; + static G: usize = 0usize; + asm!("/* {0} {1} {2} {3} {4} {5} {6} */", + //~^ ERROR asm in naked functions must use `noreturn` option + in(reg) a, + //~^ ERROR only `const` and `sym` operands are supported in naked functions + inlateout(reg) b, + inout(reg) c, + lateout(reg) d, + out(reg) e, + const F, + sym G, + ); +} + +#[naked] +pub extern "C" fn missing_assembly() { + //~^ ERROR naked functions must contain a single asm block +} + +#[naked] +pub extern "C" fn too_many_asm_blocks() { + //~^ ERROR naked functions must contain a single asm block + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!("", options(noreturn)); +} + +pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { + #[naked] + pub extern "C" fn inner(y: usize) -> usize { + //~^ ERROR naked functions must contain a single asm block + *&y + //~^ ERROR referencing function parameters is not allowed in naked functions + } + inner +} + +#[naked] +unsafe extern "C" fn invalid_options() { + asm!("", options(nomem, preserves_flags, noreturn)); + //~^ ERROR asm options unsupported in naked functions: `nomem`, `preserves_flags` +} + +#[naked] +unsafe extern "C" fn invalid_options_continued() { + asm!("", options(readonly, nostack), options(pure)); + //~^ ERROR asm with the `pure` option must have at least one output + //~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly` + //~| ERROR asm in naked functions must use `noreturn` option +} + +#[naked] +unsafe extern "C" fn invalid_may_unwind() { + asm!("", options(noreturn, may_unwind)); + //~^ ERROR asm options unsupported in naked functions: `may_unwind` +} + +#[naked] +pub unsafe fn default_abi() { + //~^ WARN Rust ABI is unsupported in naked functions + asm!("", options(noreturn)); +} + +#[naked] +pub unsafe fn rust_abi() { + //~^ WARN Rust ABI is unsupported in naked functions + asm!("", options(noreturn)); +} + +#[naked] +pub extern "C" fn valid_a() -> T { + unsafe { + asm!("", options(noreturn)); + } +} + +#[naked] +pub extern "C" fn valid_b() { + unsafe { + { + { + asm!("", options(noreturn)); + }; + }; + } +} + +#[naked] +pub unsafe extern "C" fn valid_c() { + asm!("", options(noreturn)); +} + +#[cfg(target_arch = "x86_64")] +#[naked] +pub unsafe extern "C" fn valid_att_syntax() { + asm!("", options(noreturn, att_syntax)); +} + +#[naked] +pub unsafe extern "C" fn inline_none() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline] +//~^ ERROR naked functions cannot be inlined +pub unsafe extern "C" fn inline_hint() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline(always)] +//~^ ERROR naked functions cannot be inlined +pub unsafe extern "C" fn inline_always() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline(never)] +//~^ ERROR naked functions cannot be inlined +pub unsafe extern "C" fn inline_never() { + asm!("", options(noreturn)); +} + +#[naked] +#[inline] +//~^ ERROR naked functions cannot be inlined +#[inline(always)] +//~^ ERROR naked functions cannot be inlined +#[inline(never)] +//~^ ERROR naked functions cannot be inlined +pub unsafe extern "C" fn inline_all() { + asm!("", options(noreturn)); +} + +#[naked] +pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { + compile_error!("this is a user specified error") + //~^ ERROR this is a user specified error +} + +#[naked] +pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 { + compile_error!("this is a user specified error"); + //~^ ERROR this is a user specified error + asm!("", options(noreturn)) +} + +#[naked] +pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { + asm!(invalid_syntax) + //~^ ERROR asm template must be a string literal +} diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr new file mode 100644 index 000000000..f90967fbe --- /dev/null +++ b/tests/ui/asm/naked-functions.stderr @@ -0,0 +1,290 @@ +error: asm with the `pure` option must have at least one output + --> $DIR/naked-functions.rs:111:14 + | +LL | asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ + +error: this is a user specified error + --> $DIR/naked-functions.rs:203:5 + | +LL | compile_error!("this is a user specified error") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: this is a user specified error + --> $DIR/naked-functions.rs:209:5 + | +LL | compile_error!("this is a user specified error"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm template must be a string literal + --> $DIR/naked-functions.rs:216:10 + | +LL | asm!(invalid_syntax) + | ^^^^^^^^^^^^^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:20:5 + | +LL | mut a: u32, + | ^^^^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:22:5 + | +LL | &b: &i32, + | ^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:24:6 + | +LL | (None | Some(_)): Option>, + | ^^^^^^^^^^^^^^ + +error: patterns not allowed in naked function parameters + --> $DIR/naked-functions.rs:26:5 + | +LL | P { x, y }: P, + | ^^^^^^^^^^ + +error: referencing function parameters is not allowed in naked functions + --> $DIR/naked-functions.rs:35:5 + | +LL | a + 1 + | ^ + | + = help: follow the calling convention in asm block to use parameters + +error[E0787]: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:33:1 + | +LL | pub unsafe extern "C" fn inc(a: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | a + 1 + | ----- non-asm is unsupported in naked functions + +error: referencing function parameters is not allowed in naked functions + --> $DIR/naked-functions.rs:42:31 + | +LL | asm!("/* {0} */", in(reg) a, options(noreturn)); + | ^ + | + = help: follow the calling convention in asm block to use parameters + +error[E0787]: only `const` and `sym` operands are supported in naked functions + --> $DIR/naked-functions.rs:42:23 + | +LL | asm!("/* {0} */", in(reg) a, options(noreturn)); + | ^^^^^^^^^ + +error[E0787]: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:48:1 + | +LL | pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | (|| a + 1)() + | ------------ non-asm is unsupported in naked functions + +error[E0787]: only `const` and `sym` operands are supported in naked functions + --> $DIR/naked-functions.rs:65:10 + | +LL | in(reg) a, + | ^^^^^^^^^ +LL | +LL | inlateout(reg) b, + | ^^^^^^^^^^^^^^^^ +LL | inout(reg) c, + | ^^^^^^^^^^^^ +LL | lateout(reg) d, + | ^^^^^^^^^^^^^^ +LL | out(reg) e, + | ^^^^^^^^^^ + +error[E0787]: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:63:5 + | +LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */", +LL | | +LL | | in(reg) a, +LL | | +... | +LL | | sym G, +LL | | ); + | |_____^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | sym G, options(noreturn), + | +++++++++++++++++++ + +error[E0787]: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:54:1 + | +LL | pub unsafe extern "C" fn unsupported_operands() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | let mut a = 0usize; + | ------------------- non-asm is unsupported in naked functions +LL | let mut b = 0usize; + | ------------------- non-asm is unsupported in naked functions +LL | let mut c = 0usize; + | ------------------- non-asm is unsupported in naked functions +LL | let mut d = 0usize; + | ------------------- non-asm is unsupported in naked functions +LL | let mut e = 0usize; + | ------------------- non-asm is unsupported in naked functions + +error[E0787]: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:77:1 + | +LL | pub extern "C" fn missing_assembly() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0787]: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:84:5 + | +LL | asm!(""); + | ^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ + +error[E0787]: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:86:5 + | +LL | asm!(""); + | ^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ + +error[E0787]: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:88:5 + | +LL | asm!(""); + | ^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ + +error[E0787]: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:82:1 + | +LL | pub extern "C" fn too_many_asm_blocks() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions +LL | +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions +LL | +LL | asm!("", options(noreturn)); + | --------------------------- multiple asm blocks are unsupported in naked functions + +error: referencing function parameters is not allowed in naked functions + --> $DIR/naked-functions.rs:97:11 + | +LL | *&y + | ^ + | + = help: follow the calling convention in asm block to use parameters + +error[E0787]: naked functions must contain a single asm block + --> $DIR/naked-functions.rs:95:5 + | +LL | pub extern "C" fn inner(y: usize) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | *&y + | --- non-asm is unsupported in naked functions + +error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags` + --> $DIR/naked-functions.rs:105:5 + | +LL | asm!("", options(nomem, preserves_flags, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` + --> $DIR/naked-functions.rs:111:5 + | +LL | asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0787]: asm in naked functions must use `noreturn` option + --> $DIR/naked-functions.rs:111:5 + | +LL | asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn), options(readonly, nostack), options(pure)); + | +++++++++++++++++++ + +error[E0787]: asm options unsupported in naked functions: `may_unwind` + --> $DIR/naked-functions.rs:119:5 + | +LL | asm!("", options(noreturn, may_unwind)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: Rust ABI is unsupported in naked functions + --> $DIR/naked-functions.rs:124:1 + | +LL | pub unsafe fn default_abi() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(undefined_naked_function_abi)]` on by default + +warning: Rust ABI is unsupported in naked functions + --> $DIR/naked-functions.rs:130:1 + | +LL | pub unsafe fn rust_abi() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: naked functions cannot be inlined + --> $DIR/naked-functions.rs:170:1 + | +LL | #[inline] + | ^^^^^^^^^ + +error: naked functions cannot be inlined + --> $DIR/naked-functions.rs:177:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error: naked functions cannot be inlined + --> $DIR/naked-functions.rs:184:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ + +error: naked functions cannot be inlined + --> $DIR/naked-functions.rs:191:1 + | +LL | #[inline] + | ^^^^^^^^^ + +error: naked functions cannot be inlined + --> $DIR/naked-functions.rs:193:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error: naked functions cannot be inlined + --> $DIR/naked-functions.rs:195:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 33 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0787`. diff --git a/tests/ui/asm/naked-invalid-attr.rs b/tests/ui/asm/naked-invalid-attr.rs new file mode 100644 index 000000000..ea8f560ff --- /dev/null +++ b/tests/ui/asm/naked-invalid-attr.rs @@ -0,0 +1,52 @@ +// Checks that #[naked] attribute can be placed on function definitions only. +// +// needs-asm-support +#![feature(naked_functions)] +#![naked] //~ ERROR should be applied to a function definition + +use std::arch::asm; + +extern "C" { + #[naked] //~ ERROR should be applied to a function definition + fn f(); +} + +#[naked] //~ ERROR should be applied to a function definition +#[repr(C)] +struct S { + a: u32, + b: u32, +} + +trait Invoke { + #[naked] //~ ERROR should be applied to a function definition + extern "C" fn invoke(&self); +} + +impl Invoke for S { + #[naked] + extern "C" fn invoke(&self) { + unsafe { asm!("", options(noreturn)) } + } +} + +#[naked] +extern "C" fn ok() { + unsafe { asm!("", options(noreturn)) } +} + +impl S { + #[naked] + extern "C" fn g() { + unsafe { asm!("", options(noreturn)) } + } + + #[naked] + extern "C" fn h(&self) { + unsafe { asm!("", options(noreturn)) } + } +} + +fn main() { + #[naked] || {}; //~ ERROR should be applied to a function definition +} diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr new file mode 100644 index 000000000..e8ddccc85 --- /dev/null +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -0,0 +1,42 @@ +error: attribute should be applied to a function definition + --> $DIR/naked-invalid-attr.rs:14:1 + | +LL | #[naked] + | ^^^^^^^^ +LL | #[repr(C)] +LL | / struct S { +LL | | a: u32, +LL | | b: u32, +LL | | } + | |_- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/naked-invalid-attr.rs:51:5 + | +LL | #[naked] || {}; + | ^^^^^^^^ ----- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/naked-invalid-attr.rs:22:5 + | +LL | #[naked] + | ^^^^^^^^ +LL | extern "C" fn invoke(&self); + | ---------------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/naked-invalid-attr.rs:10:5 + | +LL | #[naked] + | ^^^^^^^^ +LL | fn f(); + | ------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/naked-invalid-attr.rs:5:1 + | +LL | #![naked] + | ^^^^^^^^^ cannot be applied to crates + +error: aborting due to 5 previous errors + diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs new file mode 100644 index 000000000..160dbf617 --- /dev/null +++ b/tests/ui/asm/named-asm-labels.rs @@ -0,0 +1,196 @@ +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 + +// Tests that the use of named labels in the `asm!` macro are linted against +// except for in `#[naked]` fns. +// Using a named label is incorrect as per the RFC because for most cases +// the compiler cannot ensure that inline asm is emitted exactly once per +// codegen unit (except for naked fns) and so the label could be duplicated +// which causes less readable LLVM errors and in the worst cases causes ICEs +// or segfaults based on system dependent behavior and codegen flags. + +#![feature(naked_functions, asm_const)] + +use std::arch::{asm, global_asm}; + +#[no_mangle] +pub static FOO: usize = 42; + +fn main() { + unsafe { + // Basic usage + asm!("bar: nop"); //~ ERROR avoid using named labels + + // No following asm + asm!("abcd:"); //~ ERROR avoid using named labels + + // Multiple labels on one line + asm!("foo: bar1: nop"); + //~^ ERROR avoid using named labels + + // Multiple lines + asm!("foo1: nop", "nop"); //~ ERROR avoid using named labels + asm!("foo2: foo3: nop", "nop"); + //~^ ERROR avoid using named labels + asm!("nop", "foo4: nop"); //~ ERROR avoid using named labels + asm!("foo5: nop", "foo6: nop"); + //~^ ERROR avoid using named labels + //~| ERROR avoid using named labels + + // Statement separator + asm!("foo7: nop; foo8: nop"); + //~^ ERROR avoid using named labels + asm!("foo9: nop; nop"); //~ ERROR avoid using named labels + asm!("nop; foo10: nop"); //~ ERROR avoid using named labels + + // Escaped newline + asm!("bar2: nop\n bar3: nop"); + //~^ ERROR avoid using named labels + asm!("bar4: nop\n nop"); //~ ERROR avoid using named labels + asm!("nop\n bar5: nop"); //~ ERROR avoid using named labels + asm!("nop\n bar6: bar7: nop"); + //~^ ERROR avoid using named labels + + // Raw strings + asm!( + r" + blah2: nop + blah3: nop + " + ); + //~^^^^ ERROR avoid using named labels + + asm!( + r###" + nop + nop ; blah4: nop + "### + ); + //~^^^ ERROR avoid using named labels + + // Non-labels + // should not trigger lint, but may be invalid asm + asm!("ab cd: nop"); + + // `blah:` does not trigger because labels need to be at the start + // of the statement, and there was already a non-label + asm!("1bar: blah: nop"); + + // Only `blah1:` should trigger + asm!("blah1: 2bar: nop"); //~ ERROR avoid using named labels + + // Duplicate labels + asm!("def: def: nop"); //~ ERROR avoid using named labels + asm!("def: nop\ndef: nop"); //~ ERROR avoid using named labels + asm!("def: nop; def: nop"); //~ ERROR avoid using named labels + + // Trying to break parsing + asm!(":"); + asm!("\n:\n"); + asm!("::::"); + + // 0x3A is a ':' + asm!("fooo\u{003A} nop"); //~ ERROR avoid using named labels + asm!("foooo\x3A nop"); //~ ERROR avoid using named labels + + // 0x0A is a newline + asm!("fooooo:\u{000A} nop"); //~ ERROR avoid using named labels + asm!("foooooo:\x0A nop"); //~ ERROR avoid using named labels + + // Intentionally breaking span finding + // equivalent to "ABC: nop" + asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); //~ ERROR avoid using named labels + + // Non-label colons - should pass + asm!("mov rax, qword ptr fs:[0]"); + + // Comments + asm!( + r" + ab: nop // ab: does foo + // cd: nop + " + ); + //~^^^^ ERROR avoid using named labels + + // Tests usage of colons in non-label positions + asm!(":lo12:FOO"); // this is apparently valid aarch64 + // is there an example that is valid x86 for this test? + asm!(":bbb nop"); + + // Test include_str in asm + asm!(include_str!("named-asm-labels.s")); //~ ERROR avoid using named labels + + // Test allowing or warning on the lint instead + #[allow(named_asm_labels)] + { + asm!("allowed: nop"); // Should not emit anything + } + + #[warn(named_asm_labels)] + { + asm!("warned: nop"); //~ WARNING avoid using named labels + } + } +} + +// Trigger on naked fns too, even though they can't be inlined, reusing a +// label or LTO can cause labels to break +#[naked] +pub extern "C" fn foo() -> i32 { + unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels +} + +// Make sure that non-naked attributes *do* still let the lint happen +#[no_mangle] +pub extern "C" fn bar() { + unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + //~^ ERROR avoid using named labels +} + +#[naked] +pub extern "C" fn aaa() { + fn _local() {} + + unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels +} + +pub fn normal() { + fn _local1() {} + + #[naked] + pub extern "C" fn bbb() { + fn _very_local() {} + + unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels + } + + fn _local2() {} +} + +// Make sure that the lint happens within closures +fn closures() { + || unsafe { + asm!("closure1: nop"); //~ ERROR avoid using named labels + }; + + move || unsafe { + asm!("closure2: nop"); //~ ERROR avoid using named labels + }; + + || { + #[naked] + unsafe extern "C" fn _nested() { + asm!("ret;", options(noreturn)); + } + + unsafe { + asm!("closure3: nop"); //~ ERROR avoid using named labels + } + }; +} + +// Don't trigger on global asm +global_asm!("aaaaaaaa: nop"); diff --git a/tests/ui/asm/named-asm-labels.s b/tests/ui/asm/named-asm-labels.s new file mode 100644 index 000000000..071356d75 --- /dev/null +++ b/tests/ui/asm/named-asm-labels.s @@ -0,0 +1,5 @@ +lab1: nop +// do more things +lab2: nop // does bar +// a: b +lab3: nop; lab4: nop diff --git a/tests/ui/asm/named-asm-labels.stderr b/tests/ui/asm/named-asm-labels.stderr new file mode 100644 index 000000000..c8380629e --- /dev/null +++ b/tests/ui/asm/named-asm-labels.stderr @@ -0,0 +1,334 @@ +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:24:15 + | +LL | asm!("bar: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + = note: `#[deny(named_asm_labels)]` on by default + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:27:15 + | +LL | asm!("abcd:"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:30:15 + | +LL | asm!("foo: bar1: nop"); + | ^^^ ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:34:15 + | +LL | asm!("foo1: nop", "nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:35:15 + | +LL | asm!("foo2: foo3: nop", "nop"); + | ^^^^ ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:37:22 + | +LL | asm!("nop", "foo4: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:38:15 + | +LL | asm!("foo5: nop", "foo6: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:38:28 + | +LL | asm!("foo5: nop", "foo6: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:43:15 + | +LL | asm!("foo7: nop; foo8: nop"); + | ^^^^ ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:45:15 + | +LL | asm!("foo9: nop; nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:46:20 + | +LL | asm!("nop; foo10: nop"); + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:49:15 + | +LL | asm!("bar2: nop\n bar3: nop"); + | ^^^^ ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:51:15 + | +LL | asm!("bar4: nop\n nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:52:21 + | +LL | asm!("nop\n bar5: nop"); + | ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:53:21 + | +LL | asm!("nop\n bar6: bar7: nop"); + | ^^^^ ^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:59:13 + | +LL | blah2: nop + | ^^^^^ +LL | blah3: nop + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:68:19 + | +LL | nop ; blah4: nop + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:82:15 + | +LL | asm!("blah1: 2bar: nop"); + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:85:15 + | +LL | asm!("def: def: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:86:15 + | +LL | asm!("def: nop\ndef: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:87:15 + | +LL | asm!("def: nop; def: nop"); + | ^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:95:15 + | +LL | asm!("fooo\u{003A} nop"); + | ^^^^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:96:15 + | +LL | asm!("foooo\x3A nop"); + | ^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:99:15 + | +LL | asm!("fooooo:\u{000A} nop"); + | ^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:100:15 + | +LL | asm!("foooooo:\x0A nop"); + | ^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:104:14 + | +LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:112:13 + | +LL | ab: nop // ab: does foo + | ^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:124:14 + | +LL | asm!(include_str!("named-asm-labels.s")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +warning: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:134:19 + | +LL | asm!("warned: nop"); + | ^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information +note: the lint level is defined here + --> $DIR/named-asm-labels.rs:132:16 + | +LL | #[warn(named_asm_labels)] + | ^^^^^^^^^^^^^^^^ + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:143:20 + | +LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:149:20 + | +LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:157:20 + | +LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:167:24 + | +LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } + | ^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:176:15 + | +LL | asm!("closure1: nop"); + | ^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:180:15 + | +LL | asm!("closure2: nop"); + | ^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: avoid using named labels in inline assembly + --> $DIR/named-asm-labels.rs:190:19 + | +LL | asm!("closure3: nop"); + | ^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: aborting due to 35 previous errors; 1 warning emitted + diff --git a/tests/ui/asm/noreturn.rs b/tests/ui/asm/noreturn.rs new file mode 100644 index 000000000..03fa087ae --- /dev/null +++ b/tests/ui/asm/noreturn.rs @@ -0,0 +1,19 @@ +// needs-asm-support +// check-pass + +#![feature(never_type)] +#![crate_type = "rlib"] + +use std::arch::asm; + +pub unsafe fn asm1() { + let _: () = asm!(""); +} + +pub unsafe fn asm2() { + let _: ! = asm!("", options(noreturn)); +} + +pub unsafe fn asm3() -> ! { + asm!("", options(noreturn)); +} diff --git a/tests/ui/asm/reg-conflict.rs b/tests/ui/asm/reg-conflict.rs new file mode 100644 index 000000000..983788a93 --- /dev/null +++ b/tests/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/tests/ui/asm/reg-conflict.stderr b/tests/ui/asm/reg-conflict.stderr new file mode 100644 index 000000000..2395566de --- /dev/null +++ b/tests/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/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs new file mode 100644 index 000000000..59f7b36af --- /dev/null +++ b/tests/ui/asm/type-check-1.rs @@ -0,0 +1,79 @@ +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +fn main() { + unsafe { + // Outputs must be place expressions + + asm!("{}", in(reg) 1 + 2); + asm!("{}", out(reg) 1 + 2); + //~^ ERROR invalid asm output + asm!("{}", inout(reg) 1 + 2); + //~^ ERROR invalid asm output + + // Operands must be sized + + let v: [u64; 3] = [0, 1, 2]; + asm!("{}", in(reg) v[..]); + //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + //~| ERROR cannot use value of type `[u64]` for inline assembly + asm!("{}", out(reg) v[..]); + //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + //~| ERROR cannot use value of type `[u64]` for inline assembly + asm!("{}", inout(reg) v[..]); + //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time + //~| ERROR cannot use value of type `[u64]` for inline assembly + + // Constants must be... constant + + let x = 0; + const fn const_foo(x: i32) -> i32 { + x + } + const fn const_bar(x: T) -> T { + x + } + asm!("{}", const x); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_foo(0)); + asm!("{}", const const_foo(x)); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_bar(0)); + asm!("{}", const const_bar(x)); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", sym x); + //~^ ERROR invalid `sym` operand + + // Const operands must be integers and must be constants. + + asm!("{}", const 0); + asm!("{}", const 0i32); + asm!("{}", const 0i128); + asm!("{}", const 0f32); + //~^ ERROR mismatched types + asm!("{}", const 0 as *mut u8); + //~^ ERROR mismatched types + asm!("{}", const &0); + //~^ ERROR mismatched types + } +} + +unsafe fn generic() { + asm!("{}", sym generic::); +} + +// Const operands must be integers and must be constants. + +global_asm!("{}", const 0); +global_asm!("{}", const 0i32); +global_asm!("{}", const 0i128); +global_asm!("{}", const 0f32); +//~^ ERROR mismatched types +global_asm!("{}", const 0 as *mut u8); +//~^ ERROR mismatched types diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr new file mode 100644 index 000000000..184513965 --- /dev/null +++ b/tests/ui/asm/type-check-1.stderr @@ -0,0 +1,144 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-check-1.rs:42:26 + | +LL | let x = 0; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | asm!("{}", const x); + | ^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-check-1.rs:45:36 + | +LL | let x = 0; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | asm!("{}", const const_foo(x)); + | ^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-check-1.rs:48:36 + | +LL | let x = 0; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | asm!("{}", const const_bar(x)); + | ^ non-constant value + +error: invalid `sym` operand + --> $DIR/type-check-1.rs:50:24 + | +LL | asm!("{}", sym x); + | ^ is a local variable + | + = help: `sym` operands must refer to either a function or a static + +error: invalid asm output + --> $DIR/type-check-1.rs:15:29 + | +LL | asm!("{}", out(reg) 1 + 2); + | ^^^^^ cannot assign to this expression + +error: invalid asm output + --> $DIR/type-check-1.rs:17:31 + | +LL | asm!("{}", inout(reg) 1 + 2); + | ^^^^^ cannot assign to this expression + +error[E0277]: the size for values of type `[u64]` cannot be known at compilation time + --> $DIR/type-check-1.rs:23:28 + | +LL | asm!("{}", in(reg) v[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u64]` + = note: all inline asm arguments must have a statically known size + +error[E0277]: the size for values of type `[u64]` cannot be known at compilation time + --> $DIR/type-check-1.rs:26:29 + | +LL | asm!("{}", out(reg) v[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u64]` + = note: all inline asm arguments must have a statically known size + +error[E0277]: the size for values of type `[u64]` cannot be known at compilation time + --> $DIR/type-check-1.rs:29:31 + | +LL | asm!("{}", inout(reg) v[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u64]` + = note: all inline asm arguments must have a statically known size + +error: cannot use value of type `[u64]` for inline assembly + --> $DIR/type-check-1.rs:23:28 + | +LL | asm!("{}", in(reg) v[..]); + | ^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `[u64]` for inline assembly + --> $DIR/type-check-1.rs:26:29 + | +LL | asm!("{}", out(reg) v[..]); + | ^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `[u64]` for inline assembly + --> $DIR/type-check-1.rs:29:31 + | +LL | asm!("{}", inout(reg) v[..]); + | ^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error[E0308]: mismatched types + --> $DIR/type-check-1.rs:58:26 + | +LL | asm!("{}", const 0f32); + | ^^^^ expected integer, found `f32` + +error[E0308]: mismatched types + --> $DIR/type-check-1.rs:60:26 + | +LL | asm!("{}", const 0 as *mut u8); + | ^^^^^^^^^^^^ expected integer, found `*mut u8` + | + = note: expected type `{integer}` + found raw pointer `*mut u8` + +error[E0308]: mismatched types + --> $DIR/type-check-1.rs:62:26 + | +LL | asm!("{}", const &0); + | ^^ expected integer, found `&{integer}` + | +help: consider removing the borrow + | +LL - asm!("{}", const &0); +LL + asm!("{}", const 0); + | + +error[E0308]: mismatched types + --> $DIR/type-check-1.rs:76:25 + | +LL | global_asm!("{}", const 0f32); + | ^^^^ expected integer, found `f32` + +error[E0308]: mismatched types + --> $DIR/type-check-1.rs:78:25 + | +LL | global_asm!("{}", const 0 as *mut u8); + | ^^^^^^^^^^^^ expected integer, found `*mut u8` + | + = note: expected type `{integer}` + found raw pointer `*mut u8` + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0277, E0308, E0435. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/asm/type-check-4.rs b/tests/ui/asm/type-check-4.rs new file mode 100644 index 000000000..666d2c677 --- /dev/null +++ b/tests/ui/asm/type-check-4.rs @@ -0,0 +1,26 @@ +// needs-asm-support +// ignore-nvptx64 +// ignore-spirv +// ignore-wasm32 + +use std::arch::asm; + +fn main() { + unsafe { + // Can't output to borrowed values. + + let mut a = 0isize; + let p = &a; + asm!("{}", out(reg) a); + //~^ cannot assign to `a` because it is borrowed + println!("{}", p); + + // Can't read from mutable borrowed values. + + let mut a = 0isize; + let p = &mut a; + asm!("{}", in(reg) a); + //~^ cannot use `a` because it was mutably borrowed + println!("{}", p); + } +} diff --git a/tests/ui/asm/type-check-4.stderr b/tests/ui/asm/type-check-4.stderr new file mode 100644 index 000000000..c97cd171b --- /dev/null +++ b/tests/ui/asm/type-check-4.stderr @@ -0,0 +1,26 @@ +error[E0506]: cannot assign to `a` because it is borrowed + --> $DIR/type-check-4.rs:14:9 + | +LL | let p = &a; + | -- borrow of `a` occurs here +LL | asm!("{}", out(reg) a); + | ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here +LL | +LL | println!("{}", p); + | - borrow later used here + +error[E0503]: cannot use `a` because it was mutably borrowed + --> $DIR/type-check-4.rs:22:28 + | +LL | let p = &mut a; + | ------ borrow of `a` occurs here +LL | asm!("{}", in(reg) a); + | ^ use of borrowed `a` +LL | +LL | println!("{}", p); + | - borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0503, E0506. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/asm/unpretty-expanded.rs b/tests/ui/asm/unpretty-expanded.rs new file mode 100644 index 000000000..25cf1c3d7 --- /dev/null +++ b/tests/ui/asm/unpretty-expanded.rs @@ -0,0 +1,4 @@ +// needs-asm-support +// check-pass +// compile-flags: -Zunpretty=expanded +core::arch::global_asm!("x: .byte 42"); diff --git a/tests/ui/asm/unpretty-expanded.stdout b/tests/ui/asm/unpretty-expanded.stdout new file mode 100644 index 000000000..ab1b5f45e --- /dev/null +++ b/tests/ui/asm/unpretty-expanded.stdout @@ -0,0 +1,10 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// needs-asm-support +// check-pass +// compile-flags: -Zunpretty=expanded +global_asm! ("x: .byte 42"); diff --git a/tests/ui/asm/x86_64/bad-clobber-abi.rs b/tests/ui/asm/x86_64/bad-clobber-abi.rs new file mode 100644 index 000000000..ddcd2065b --- /dev/null +++ b/tests/ui/asm/x86_64/bad-clobber-abi.rs @@ -0,0 +1,32 @@ +// needs-asm-support +// only-x86_64 + +use std::arch::asm; + +// checks various modes of failure for the `clobber_abi` argument (after parsing) + +fn main() { + unsafe { + asm!("", clobber_abi("C")); + asm!("", clobber_abi("foo")); + //~^ ERROR invalid ABI for `clobber_abi` + asm!("", clobber_abi("C", "foo")); + //~^ ERROR invalid ABI for `clobber_abi` + asm!("", clobber_abi("C", "C")); + //~^ ERROR `C` ABI specified multiple times + asm!("", clobber_abi("win64", "sysv64")); + asm!("", clobber_abi("win64", "efiapi")); + //~^ ERROR `win64` ABI specified multiple times + asm!("", clobber_abi("C", "foo", "C")); + //~^ ERROR invalid ABI for `clobber_abi` + //~| ERROR `C` ABI specified multiple times + asm!("", clobber_abi("win64", "foo", "efiapi")); + //~^ ERROR invalid ABI for `clobber_abi` + //~| ERROR `win64` ABI specified multiple times + asm!("", clobber_abi("C"), clobber_abi("C")); + //~^ ERROR `C` ABI specified multiple times + asm!("", clobber_abi("win64"), clobber_abi("sysv64")); + asm!("", clobber_abi("win64"), clobber_abi("efiapi")); + //~^ ERROR `win64` ABI specified multiple times + } +} diff --git a/tests/ui/asm/x86_64/bad-clobber-abi.stderr b/tests/ui/asm/x86_64/bad-clobber-abi.stderr new file mode 100644 index 000000000..46e91a395 --- /dev/null +++ b/tests/ui/asm/x86_64/bad-clobber-abi.stderr @@ -0,0 +1,88 @@ +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:11:18 + | +LL | asm!("", clobber_abi("foo")); + | ^^^^^^^^^^^^^^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:13:35 + | +LL | asm!("", clobber_abi("C", "foo")); + | ^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `C` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:15:35 + | +LL | asm!("", clobber_abi("C", "C")); + | --- ^^^ + | | + | previously specified here + +error: `win64` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:18:39 + | +LL | asm!("", clobber_abi("win64", "efiapi")); + | ------- ^^^^^^^^ + | | + | previously specified here + | + = note: these ABIs are equivalent on the current target + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:20:35 + | +LL | asm!("", clobber_abi("C", "foo", "C")); + | ^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `C` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:20:42 + | +LL | asm!("", clobber_abi("C", "foo", "C")); + | --- ^^^ + | | + | previously specified here + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-clobber-abi.rs:23:39 + | +LL | asm!("", clobber_abi("win64", "foo", "efiapi")); + | ^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `win64` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:23:46 + | +LL | asm!("", clobber_abi("win64", "foo", "efiapi")); + | ------- ^^^^^^^^ + | | + | previously specified here + | + = note: these ABIs are equivalent on the current target + +error: `C` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:26:36 + | +LL | asm!("", clobber_abi("C"), clobber_abi("C")); + | ---------------- ^^^^^^^^^^^^^^^^ + | | + | previously specified here + +error: `win64` ABI specified multiple times + --> $DIR/bad-clobber-abi.rs:29:40 + | +LL | asm!("", clobber_abi("win64"), clobber_abi("efiapi")); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^ + | | + | previously specified here + | + = note: these ABIs are equivalent on the current target + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs new file mode 100644 index 000000000..f7c2cd6c5 --- /dev/null +++ b/tests/ui/asm/x86_64/bad-options.rs @@ -0,0 +1,42 @@ +// only-x86_64 + +use std::arch::{asm, global_asm}; + +fn main() { + let mut foo = 0; + unsafe { + asm!("", options(nomem, readonly)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + asm!("", options(pure, nomem, noreturn)); + //~^ ERROR the `pure` and `noreturn` options are mutually exclusive + //~^^ ERROR asm with the `pure` option must have at least one output + asm!("{}", in(reg) foo, options(pure, nomem)); + //~^ ERROR asm with the `pure` option must have at least one output + asm!("{}", out(reg) foo, options(noreturn)); + //~^ ERROR asm outputs are not allowed with the `noreturn` option + } + + unsafe { + asm!("", clobber_abi("foo")); + //~^ ERROR invalid ABI for `clobber_abi` + asm!("{}", out(reg) foo, clobber_abi("C")); + //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs + asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); + //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs + //~| ERROR `C` ABI specified multiple times + asm!("", out("eax") foo, clobber_abi("C")); + } +} + +global_asm!("", options(nomem)); +//~^ ERROR expected one of +global_asm!("", options(readonly)); +//~^ ERROR expected one of +global_asm!("", options(noreturn)); +//~^ ERROR expected one of +global_asm!("", options(pure)); +//~^ ERROR expected one of +global_asm!("", options(nostack)); +//~^ ERROR expected one of +global_asm!("", options(preserves_flags)); +//~^ ERROR expected one of diff --git a/tests/ui/asm/x86_64/bad-options.stderr b/tests/ui/asm/x86_64/bad-options.stderr new file mode 100644 index 000000000..e2351840e --- /dev/null +++ b/tests/ui/asm/x86_64/bad-options.stderr @@ -0,0 +1,101 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/bad-options.rs:8:18 + | +LL | asm!("", options(nomem, readonly)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with the `pure` option must have at least one output + --> $DIR/bad-options.rs:10:18 + | +LL | asm!("", options(pure, nomem, noreturn)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: asm with the `pure` option must have at least one output + --> $DIR/bad-options.rs:13:33 + | +LL | asm!("{}", in(reg) foo, options(pure, nomem)); + | ^^^^^^^^^^^^^^^^^^^^ + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/bad-options.rs:15:20 + | +LL | asm!("{}", out(reg) foo, options(noreturn)); + | ^^^^^^^^^^^^ + +error: asm with `clobber_abi` must specify explicit registers for outputs + --> $DIR/bad-options.rs:22:20 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C")); + | ^^^^^^^^^^^^ ---------------- clobber_abi + | | + | generic outputs + +error: asm with `clobber_abi` must specify explicit registers for outputs + --> $DIR/bad-options.rs:24:20 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); + | ^^^^^^^^^^^^ ---------------- ---------------- clobber_abi + | | | + | | clobber_abi + | generic outputs + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/bad-options.rs:31:25 + | +LL | global_asm!("", options(nomem)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` + --> $DIR/bad-options.rs:33:25 + | +LL | global_asm!("", options(readonly)); + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` + --> $DIR/bad-options.rs:35:25 + | +LL | global_asm!("", options(noreturn)); + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `pure` + --> $DIR/bad-options.rs:37:25 + | +LL | global_asm!("", options(pure)); + | ^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` + --> $DIR/bad-options.rs:39:25 + | +LL | global_asm!("", options(nostack)); + | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` + --> $DIR/bad-options.rs:41:25 + | +LL | global_asm!("", options(preserves_flags)); + | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: invalid ABI for `clobber_abi` + --> $DIR/bad-options.rs:20:18 + | +LL | asm!("", clobber_abi("foo")); + | ^^^^^^^^^^^^^^^^^^ + | + = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` + +error: `C` ABI specified multiple times + --> $DIR/bad-options.rs:24:52 + | +LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); + | ---------------- ^^^^^^^^^^^^^^^^ + | | + | previously specified here + +error: aborting due to 15 previous errors + diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs new file mode 100644 index 000000000..f5728079a --- /dev/null +++ b/tests/ui/asm/x86_64/bad-reg.rs @@ -0,0 +1,72 @@ +// only-x86_64 +// compile-flags: -C target-feature=+avx2 + +#![feature(asm_const)] + +use std::arch::asm; + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + // Bad register/register class + + asm!("{}", in(foo) foo); + //~^ ERROR invalid register class `foo`: unknown register class + asm!("", in("foo") foo); + //~^ ERROR invalid register `foo`: unknown register + asm!("{:z}", in(reg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:r}", in(xmm_reg) foo); + //~^ ERROR invalid asm template modifier for this register class + asm!("{:a}", const 0); + //~^ ERROR asm template modifiers are not allowed for `const` arguments + asm!("{:a}", sym main); + //~^ ERROR asm template modifiers are not allowed for `sym` arguments + asm!("", in("ebp") foo); + //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand + asm!("", in("rsp") foo); + //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand + asm!("", in("ip") foo); + //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand + + asm!("", in("st(2)") foo); + //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output + //~| ERROR `i32` cannot be used with this register class + asm!("", in("mm0") foo); + //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output + //~| ERROR `i32` cannot be used with this register class + asm!("", in("k0") foo); + //~^ ERROR register class `kreg0` can only be used as a clobber, not as an input or output + //~| ERROR `i32` cannot be used with this register class + asm!("", out("st(2)") _); + asm!("", out("mm0") _); + asm!("{}", in(x87_reg) foo); + //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output + //~| ERROR `i32` cannot be used with this register class + asm!("{}", in(mmx_reg) foo); + //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output + //~| ERROR `i32` cannot be used with this register class + asm!("{}", out(x87_reg) _); + //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output + asm!("{}", out(mmx_reg) _); + //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output + + // Explicit register conflicts + // (except in/lateout which don't conflict) + + asm!("", in("eax") foo, in("al") bar); + //~^ ERROR register `al` conflicts with register `ax` + //~| ERROR `i32` cannot be used with this register class + asm!("", in("rax") foo, out("rax") bar); + //~^ ERROR register `ax` conflicts with register `ax` + asm!("", in("al") foo, lateout("al") bar); + //~^ ERROR `i32` cannot be used with this register class + //~| ERROR `i32` cannot be used with this register class + asm!("", in("xmm0") foo, in("ymm0") bar); + //~^ ERROR register `ymm0` conflicts with register `xmm0` + asm!("", in("xmm0") foo, out("ymm0") bar); + //~^ ERROR register `ymm0` conflicts with register `xmm0` + asm!("", in("xmm0") foo, lateout("ymm0") bar); + } +} diff --git a/tests/ui/asm/x86_64/bad-reg.stderr b/tests/ui/asm/x86_64/bad-reg.stderr new file mode 100644 index 000000000..82b7ebd0f --- /dev/null +++ b/tests/ui/asm/x86_64/bad-reg.stderr @@ -0,0 +1,218 @@ +error: invalid register class `foo`: unknown register class + --> $DIR/bad-reg.rs:14:20 + | +LL | asm!("{}", in(foo) foo); + | ^^^^^^^^^^^ + +error: invalid register `foo`: unknown register + --> $DIR/bad-reg.rs:16:18 + | +LL | asm!("", in("foo") foo); + | ^^^^^^^^^^^^^ + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:18:15 + | +LL | asm!("{:z}", in(reg) foo); + | ^^^^ ----------- argument + | | + | template modifier + | + = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r` + +error: invalid asm template modifier for this register class + --> $DIR/bad-reg.rs:20:15 + | +LL | asm!("{:r}", in(xmm_reg) foo); + | ^^^^ --------------- argument + | | + | template modifier + | + = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z` + +error: asm template modifiers are not allowed for `const` arguments + --> $DIR/bad-reg.rs:22:15 + | +LL | asm!("{:a}", const 0); + | ^^^^ ------- argument + | | + | template modifier + +error: asm template modifiers are not allowed for `sym` arguments + --> $DIR/bad-reg.rs:24:15 + | +LL | asm!("{:a}", sym main); + | ^^^^ -------- argument + | | + | template modifier + +error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:26:18 + | +LL | asm!("", in("ebp") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", in("rsp") foo); + | ^^^^^^^^^^^^^ + +error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", in("ip") foo); + | ^^^^^^^^^^^^ + +error: register class `x87_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:33:18 + | +LL | asm!("", in("st(2)") foo); + | ^^^^^^^^^^^^^^^ + +error: register class `mmx_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:36:18 + | +LL | asm!("", in("mm0") foo); + | ^^^^^^^^^^^^^ + +error: register class `kreg0` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:39:18 + | +LL | asm!("", in("k0") foo); + | ^^^^^^^^^^^^ + +error: register class `x87_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:44:20 + | +LL | asm!("{}", in(x87_reg) foo); + | ^^^^^^^^^^^^^^^ + +error: register class `mmx_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:47:20 + | +LL | asm!("{}", in(mmx_reg) foo); + | ^^^^^^^^^^^^^^^ + +error: register class `x87_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:50:20 + | +LL | asm!("{}", out(x87_reg) _); + | ^^^^^^^^^^^^^^ + +error: register class `mmx_reg` can only be used as a clobber, not as an input or output + --> $DIR/bad-reg.rs:52:20 + | +LL | asm!("{}", out(mmx_reg) _); + | ^^^^^^^^^^^^^^ + +error: register `al` conflicts with register `ax` + --> $DIR/bad-reg.rs:58:33 + | +LL | asm!("", in("eax") foo, in("al") bar); + | ------------- ^^^^^^^^^^^^ register `al` + | | + | register `ax` + +error: register `ax` conflicts with register `ax` + --> $DIR/bad-reg.rs:61:33 + | +LL | asm!("", in("rax") foo, out("rax") bar); + | ------------- ^^^^^^^^^^^^^^ register `ax` + | | + | register `ax` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:61:18 + | +LL | asm!("", in("rax") foo, out("rax") bar); + | ^^^^^^^^^^^^^ + +error: register `ymm0` conflicts with register `xmm0` + --> $DIR/bad-reg.rs:66:34 + | +LL | asm!("", in("xmm0") foo, in("ymm0") bar); + | -------------- ^^^^^^^^^^^^^^ register `ymm0` + | | + | register `xmm0` + +error: register `ymm0` conflicts with register `xmm0` + --> $DIR/bad-reg.rs:68:34 + | +LL | asm!("", in("xmm0") foo, out("ymm0") bar); + | -------------- ^^^^^^^^^^^^^^^ register `ymm0` + | | + | register `xmm0` + | +help: use `lateout` instead of `out` to avoid conflict + --> $DIR/bad-reg.rs:68:18 + | +LL | asm!("", in("xmm0") foo, out("ymm0") bar); + | ^^^^^^^^^^^^^^ + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:33:30 + | +LL | asm!("", in("st(2)") foo); + | ^^^ + | + = note: register class `x87_reg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:36:28 + | +LL | asm!("", in("mm0") foo); + | ^^^ + | + = note: register class `mmx_reg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:39:27 + | +LL | asm!("", in("k0") foo); + | ^^^ + | + = note: register class `kreg0` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:44:32 + | +LL | asm!("{}", in(x87_reg) foo); + | ^^^ + | + = note: register class `x87_reg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:47:32 + | +LL | asm!("{}", in(mmx_reg) foo); + | ^^^ + | + = note: register class `mmx_reg` supports these types: + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:58:42 + | +LL | asm!("", in("eax") foo, in("al") bar); + | ^^^ + | + = note: register class `reg_byte` supports these types: i8 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:63:27 + | +LL | asm!("", in("al") foo, lateout("al") bar); + | ^^^ + | + = note: register class `reg_byte` supports these types: i8 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:63:46 + | +LL | asm!("", in("al") foo, lateout("al") bar); + | ^^^ + | + = note: register class `reg_byte` supports these types: i8 + +error: aborting due to 28 previous errors + diff --git a/tests/ui/asm/x86_64/const.rs b/tests/ui/asm/x86_64/const.rs new file mode 100644 index 000000000..d523ae021 --- /dev/null +++ b/tests/ui/asm/x86_64/const.rs @@ -0,0 +1,44 @@ +// only-x86_64 +// run-pass +// needs-asm-support +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +fn const_generic() -> usize { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const X); + a + } +} + +const fn constfn(x: usize) -> usize { + x +} + +fn main() { + unsafe { + let a: usize; + asm!("mov {}, {}", out(reg) a, const 5); + assert_eq!(a, 5); + + let b: usize; + asm!("mov {}, {}", out(reg) b, const constfn(5)); + assert_eq!(b, 5); + + let c: usize; + asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5)); + assert_eq!(c, 10); + } + + let d = const_generic::<5>(); + assert_eq!(d, 5); +} + +global_asm!("mov eax, {}", const 5); +global_asm!("mov eax, {}", const constfn(5)); +global_asm!("mov eax, {}", const constfn(5) + constfn(5)); diff --git a/tests/ui/asm/x86_64/duplicate-options.fixed b/tests/ui/asm/x86_64/duplicate-options.fixed new file mode 100644 index 000000000..c5f14f5f7 --- /dev/null +++ b/tests/ui/asm/x86_64/duplicate-options.fixed @@ -0,0 +1,29 @@ +// only-x86_64 +// run-rustfix + +use std::arch::{asm, global_asm}; + +fn main() { + unsafe { + asm!("", options(nomem, )); + //~^ ERROR the `nomem` option was already provided + asm!("", options(att_syntax, )); + //~^ ERROR the `att_syntax` option was already provided + asm!("", options(nostack, att_syntax), options()); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, ), options(), options()); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(att_syntax, ), //~ ERROR the `noreturn` option was already provided + options( nostack), //~ ERROR the `nomem` option was already provided + options(), //~ ERROR the `noreturn` option was already provided + ); + } +} + +global_asm!("", options(att_syntax, )); +//~^ ERROR the `att_syntax` option was already provided diff --git a/tests/ui/asm/x86_64/duplicate-options.rs b/tests/ui/asm/x86_64/duplicate-options.rs new file mode 100644 index 000000000..a8dce1f8d --- /dev/null +++ b/tests/ui/asm/x86_64/duplicate-options.rs @@ -0,0 +1,29 @@ +// only-x86_64 +// run-rustfix + +use std::arch::{asm, global_asm}; + +fn main() { + unsafe { + asm!("", options(nomem, nomem)); + //~^ ERROR the `nomem` option was already provided + asm!("", options(att_syntax, att_syntax)); + //~^ ERROR the `att_syntax` option was already provided + asm!("", options(nostack, att_syntax), options(nostack)); + //~^ ERROR the `nostack` option was already provided + asm!("", options(nostack, nostack), options(nostack), options(nostack)); + //~^ ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + //~| ERROR the `nostack` option was already provided + asm!( + "", + options(nomem, noreturn), + options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided + options(nomem, nostack), //~ ERROR the `nomem` option was already provided + options(noreturn), //~ ERROR the `noreturn` option was already provided + ); + } +} + +global_asm!("", options(att_syntax, att_syntax)); +//~^ ERROR the `att_syntax` option was already provided diff --git a/tests/ui/asm/x86_64/duplicate-options.stderr b/tests/ui/asm/x86_64/duplicate-options.stderr new file mode 100644 index 000000000..53edf8fb9 --- /dev/null +++ b/tests/ui/asm/x86_64/duplicate-options.stderr @@ -0,0 +1,62 @@ +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:8:33 + | +LL | asm!("", options(nomem, nomem)); + | ^^^^^ this option was already provided + +error: the `att_syntax` option was already provided + --> $DIR/duplicate-options.rs:10:38 + | +LL | asm!("", options(att_syntax, att_syntax)); + | ^^^^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:12:56 + | +LL | asm!("", options(nostack, att_syntax), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:35 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:53 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `nostack` option was already provided + --> $DIR/duplicate-options.rs:14:71 + | +LL | asm!("", options(nostack, nostack), options(nostack), options(nostack)); + | ^^^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:21:33 + | +LL | options(att_syntax, noreturn), + | ^^^^^^^^ this option was already provided + +error: the `nomem` option was already provided + --> $DIR/duplicate-options.rs:22:21 + | +LL | options(nomem, nostack), + | ^^^^^ this option was already provided + +error: the `noreturn` option was already provided + --> $DIR/duplicate-options.rs:23:21 + | +LL | options(noreturn), + | ^^^^^^^^ this option was already provided + +error: the `att_syntax` option was already provided + --> $DIR/duplicate-options.rs:28:37 + | +LL | global_asm!("", options(att_syntax, att_syntax)); + | ^^^^^^^^^^ this option was already provided + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/x86_64/interpolated-idents.rs b/tests/ui/asm/x86_64/interpolated-idents.rs new file mode 100644 index 000000000..c05633ae8 --- /dev/null +++ b/tests/ui/asm/x86_64/interpolated-idents.rs @@ -0,0 +1,24 @@ +// only-x86_64 + +use std::arch::asm; + +macro_rules! m { + ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident + $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident + $noreturn:ident $nostack:ident $att_syntax:ident $options:ident) => { + unsafe { + asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, + //~^ ERROR asm outputs are not allowed with the `noreturn` option + const x, sym x, + $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax)); + //~^ ERROR the `nomem` and `readonly` options are mutually exclusive + //~| ERROR the `pure` and `noreturn` options are mutually exclusive + } + }; +} + +fn main() { + m!(in out lateout inout inlateout const sym + pure nomem readonly preserves_flags + noreturn nostack att_syntax options); +} diff --git a/tests/ui/asm/x86_64/interpolated-idents.stderr b/tests/ui/asm/x86_64/interpolated-idents.stderr new file mode 100644 index 000000000..80a8c8c77 --- /dev/null +++ b/tests/ui/asm/x86_64/interpolated-idents.stderr @@ -0,0 +1,46 @@ +error: the `nomem` and `readonly` options are mutually exclusive + --> $DIR/interpolated-idents.rs:13:13 + | +LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack att_syntax options); + | |___________________________________________- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: the `pure` and `noreturn` options are mutually exclusive + --> $DIR/interpolated-idents.rs:13:13 + | +LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack att_syntax options); + | |___________________________________________- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm outputs are not allowed with the `noreturn` option + --> $DIR/interpolated-idents.rs:10:32 + | +LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, + | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ +... +LL | / m!(in out lateout inout inlateout const sym +LL | | pure nomem readonly preserves_flags +LL | | noreturn nostack att_syntax options); + | | - + | |___________________________________________| + | |___________________________________________in this macro invocation + | |___________________________________________in this macro invocation + | |___________________________________________in this macro invocation + | in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/asm/x86_64/issue-82869.rs b/tests/ui/asm/x86_64/issue-82869.rs new file mode 100644 index 000000000..67933666e --- /dev/null +++ b/tests/ui/asm/x86_64/issue-82869.rs @@ -0,0 +1,25 @@ +// needs-asm-support +// only-x86_64 +// Make sure rustc doesn't ICE on asm! for a foreign architecture. + +#![crate_type = "rlib"] + +use std::arch::asm; + +pub unsafe fn aarch64(a: f64, b: f64) -> f64 { + let c; + asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { + || {}; + b + }); + //~^^^^ invalid register class + //~^^^^^ invalid register class + //~^^^^^^ invalid register + c +} + +pub unsafe fn x86(a: f64, b: f64) -> f64 { + let c; + asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b); + c +} diff --git a/tests/ui/asm/x86_64/issue-82869.stderr b/tests/ui/asm/x86_64/issue-82869.stderr new file mode 100644 index 000000000..3cf9d6d1c --- /dev/null +++ b/tests/ui/asm/x86_64/issue-82869.stderr @@ -0,0 +1,24 @@ +error: invalid register class `vreg`: unknown register class + --> $DIR/issue-82869.rs:11:32 + | +LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { + | ^^^^^^^^^^^ + +error: invalid register class `vreg`: unknown register class + --> $DIR/issue-82869.rs:11:45 + | +LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { + | ^^^^^^^^^^ + +error: invalid register `d0`: unknown register + --> $DIR/issue-82869.rs:11:57 + | +LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { + | _________________________________________________________^ +LL | | || {}; +LL | | b +LL | | }); + | |_____^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/asm/x86_64/issue-89875.rs b/tests/ui/asm/x86_64/issue-89875.rs new file mode 100644 index 000000000..669fd7e7e --- /dev/null +++ b/tests/ui/asm/x86_64/issue-89875.rs @@ -0,0 +1,17 @@ +// build-pass +// needs-asm-support +// only-x86_64 + +#![feature(target_feature_11)] + +use std::arch::asm; + +#[target_feature(enable = "avx")] +fn main() { + unsafe { + asm!( + "/* {} */", + out(ymm_reg) _, + ); + } +} diff --git a/tests/ui/asm/x86_64/issue-96797.rs b/tests/ui/asm/x86_64/issue-96797.rs new file mode 100644 index 000000000..954f8c5cc --- /dev/null +++ b/tests/ui/asm/x86_64/issue-96797.rs @@ -0,0 +1,24 @@ +// build-pass +// compile-flags: -O +// min-llvm-version: 14.0.5 +// needs-asm-support +// only-x86_64 +// only-linux + +// regression test for #96797 + +use std::arch::global_asm; + +#[no_mangle] +fn my_func() {} + +global_asm!("call_foobar: jmp {}", sym foobar); + +fn foobar() {} + +fn main() { + extern "Rust" { + fn call_foobar(); + } + unsafe { call_foobar() }; +} diff --git a/tests/ui/asm/x86_64/may_unwind.rs b/tests/ui/asm/x86_64/may_unwind.rs new file mode 100644 index 000000000..c11f0938d --- /dev/null +++ b/tests/ui/asm/x86_64/may_unwind.rs @@ -0,0 +1,38 @@ +// only-x86_64 +// run-pass +// needs-asm-support +// needs-unwind + +#![feature(asm_unwind)] + +use std::arch::asm; +use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; + +struct Foo<'a>(&'a mut bool); + +impl Drop for Foo<'_> { + fn drop(&mut self) { + *self.0 = false; + } +} + +extern "C" fn panicky() { + resume_unwind(Box::new(())); +} + +fn main() { + let flag = &mut true; + catch_unwind(AssertUnwindSafe(|| { + let _foo = Foo(flag); + unsafe { + asm!( + "call {}", + sym panicky, + clobber_abi("C"), + options(may_unwind) + ); + } + })) + .expect_err("expected a panic"); + assert_eq!(*flag, false); +} diff --git a/tests/ui/asm/x86_64/multiple-clobber-abi.rs b/tests/ui/asm/x86_64/multiple-clobber-abi.rs new file mode 100644 index 000000000..06589431a --- /dev/null +++ b/tests/ui/asm/x86_64/multiple-clobber-abi.rs @@ -0,0 +1,33 @@ +// run-pass +// needs-asm-support +// only-x86_64 + +// Checks that multiple clobber_abi options can be used + +use std::arch::asm; + +extern "sysv64" fn foo(x: i32) -> i32 { + x + 16 +} + +extern "win64" fn bar(x: i32) -> i32 { + x / 2 +} + +fn main() { + let x = 8; + let y: i32; + // call `foo` with `x` as the input, and then `bar` with the output of `foo` + // and output that to `y` + unsafe { + asm!( + "call {}; mov rcx, rax; call {}", + sym foo, + sym bar, + in("rdi") x, + out("rax") y, + clobber_abi("sysv64", "win64"), + ); + } + assert_eq!((x, y), (8, 12)); +} diff --git a/tests/ui/asm/x86_64/parse-error.rs b/tests/ui/asm/x86_64/parse-error.rs new file mode 100644 index 000000000..9aeb6b285 --- /dev/null +++ b/tests/ui/asm/x86_64/parse-error.rs @@ -0,0 +1,137 @@ +// only-x86_64 + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +fn main() { + let mut foo = 0; + let mut bar = 0; + unsafe { + asm!(); + //~^ ERROR requires at least a template string argument + asm!(foo); + //~^ ERROR asm template must be a string literal + asm!("{}" foo); + //~^ ERROR expected token: `,` + asm!("{}", foo); + //~^ ERROR expected operand, clobber_abi, options, or additional template string + asm!("{}", in foo); + //~^ ERROR expected `(`, found `foo` + asm!("{}", in(reg foo)); + //~^ ERROR expected `)`, found `foo` + asm!("{}", in(reg)); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", inout(=) foo => bar); + //~^ ERROR expected register class or explicit register + asm!("{}", inout(reg) foo =>); + //~^ ERROR expected expression, found end of macro arguments + asm!("{}", in(reg) foo => bar); + //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + asm!("{}", sym foo + bar); + //~^ ERROR expected a path for argument to `sym` + asm!("", options(foo)); + //~^ ERROR expected one of + asm!("", options(nomem foo)); + //~^ ERROR expected one of + asm!("", options(nomem, foo)); + //~^ ERROR expected one of + asm!("{}", options(), const foo); + //~^ ERROR arguments are not allowed after options + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", clobber_abi()); + //~^ ERROR at least one abi must be provided + asm!("", clobber_abi(foo)); + //~^ ERROR expected string literal + asm!("", clobber_abi("C" foo)); + //~^ ERROR expected one of `)` or `,`, found `foo` + asm!("", clobber_abi("C", foo)); + //~^ ERROR expected string literal + asm!("{}", clobber_abi("C"), const foo); + //~^ ERROR arguments are not allowed after clobber_abi + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", options(), clobber_abi("C")); + //~^ ERROR clobber_abi is not allowed after options + asm!("{}", options(), clobber_abi("C"), const foo); + //~^ ERROR clobber_abi is not allowed after options + asm!("{a}", a = const foo, a = const bar); + //~^ ERROR duplicate argument named `a` + //~^^ ERROR argument never used + //~^^^ ERROR attempt to use a non-constant value in a constant + //~^^^^ ERROR attempt to use a non-constant value in a constant + asm!("", a = in("eax") foo); + //~^ ERROR explicit register arguments cannot have names + asm!("{a}", in("eax") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("{a}", in("eax") foo, a = const bar); + //~^ ERROR named arguments cannot follow explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("{1}", in("eax") foo, const bar); + //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments + //~^^ ERROR attempt to use a non-constant value in a constant + asm!("", options(), ""); + //~^ ERROR expected one of + asm!("{}", in(reg) foo, "{}", out(reg) foo); + //~^ ERROR expected one of + asm!(format!("{{{}}}", 0), in(reg) foo); + //~^ ERROR asm template must be a string literal + asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + //~^ ERROR asm template must be a string literal + asm!("{}", in(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inout(reg) _); + //~^ ERROR _ cannot be used for input operands + asm!("{}", inlateout(reg) _); + //~^ ERROR _ cannot be used for input operands + } +} + +const FOO: i32 = 1; +const BAR: i32 = 2; +global_asm!(); +//~^ ERROR requires at least a template string argument +global_asm!(FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{}" FOO); +//~^ ERROR expected token: `,` +global_asm!("{}", FOO); +//~^ ERROR expected operand, options, or additional template string +global_asm!("{}", const); +//~^ ERROR expected expression, found end of macro arguments +global_asm!("{}", const(reg) FOO); +//~^ ERROR expected one of +global_asm!("", options(FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem FOO)); +//~^ ERROR expected one of +global_asm!("", options(nomem, FOO)); +//~^ ERROR expected one of +global_asm!("{}", options(), const FOO); +//~^ ERROR arguments are not allowed after options +global_asm!("", clobber_abi(FOO)); +//~^ ERROR expected string literal +global_asm!("", clobber_abi("C" FOO)); +//~^ ERROR expected one of `)` or `,`, found `FOO` +global_asm!("", clobber_abi("C", FOO)); +//~^ ERROR expected string literal +global_asm!("{}", clobber_abi("C"), const FOO); +//~^ ERROR arguments are not allowed after clobber_abi +//~^^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("", options(), clobber_abi("C")); +//~^ ERROR clobber_abi is not allowed after options +global_asm!("{}", options(), clobber_abi("C"), const FOO); +//~^ ERROR clobber_abi is not allowed after options +global_asm!("", clobber_abi("C"), clobber_abi("C")); +//~^ ERROR `clobber_abi` cannot be used with `global_asm!` +global_asm!("{a}", a = const FOO, a = const BAR); +//~^ ERROR duplicate argument named `a` +//~^^ ERROR argument never used +global_asm!("", options(), ""); +//~^ ERROR expected one of +global_asm!("{}", const FOO, "{}", const FOO); +//~^ ERROR expected one of +global_asm!(format!("{{{}}}", 0), const FOO); +//~^ ERROR asm template must be a string literal +global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); +//~^ ERROR asm template must be a string literal diff --git a/tests/ui/asm/x86_64/parse-error.stderr b/tests/ui/asm/x86_64/parse-error.stderr new file mode 100644 index 000000000..57702c37b --- /dev/null +++ b/tests/ui/asm/x86_64/parse-error.stderr @@ -0,0 +1,458 @@ +error: requires at least a template string argument + --> $DIR/parse-error.rs:11:9 + | +LL | asm!(); + | ^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:13:14 + | +LL | asm!(foo); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:15:19 + | +LL | asm!("{}" foo); + | ^^^ expected `,` + +error: expected operand, clobber_abi, options, or additional template string + --> $DIR/parse-error.rs:17:20 + | +LL | asm!("{}", foo); + | ^^^ expected operand, clobber_abi, options, or additional template string + +error: expected `(`, found `foo` + --> $DIR/parse-error.rs:19:23 + | +LL | asm!("{}", in foo); + | ^^^ expected `(` + +error: expected `)`, found `foo` + --> $DIR/parse-error.rs:21:27 + | +LL | asm!("{}", in(reg foo)); + | ^^^ expected `)` + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:23:27 + | +LL | asm!("{}", in(reg)); + | ^ expected expression + +error: expected register class or explicit register + --> $DIR/parse-error.rs:25:26 + | +LL | asm!("{}", inout(=) foo => bar); + | ^ + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:27:37 + | +LL | asm!("{}", inout(reg) foo =>); + | ^ expected expression + +error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>` + --> $DIR/parse-error.rs:29:32 + | +LL | asm!("{}", in(reg) foo => bar); + | ^^ expected one of 7 possible tokens + +error: expected a path for argument to `sym` + --> $DIR/parse-error.rs:31:24 + | +LL | asm!("{}", sym foo + bar); + | ^^^^^^^^^ + +error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:33:26 + | +LL | asm!("", options(foo)); + | ^^^ expected one of 10 possible tokens + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:35:32 + | +LL | asm!("", options(nomem foo)); + | ^^^ expected one of `)` or `,` + +error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo` + --> $DIR/parse-error.rs:37:33 + | +LL | asm!("", options(nomem, foo)); + | ^^^ expected one of 10 possible tokens + +error: arguments are not allowed after options + --> $DIR/parse-error.rs:39:31 + | +LL | asm!("{}", options(), const foo); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: at least one abi must be provided as an argument to `clobber_abi` + --> $DIR/parse-error.rs:42:30 + | +LL | asm!("", clobber_abi()); + | ^ + +error: expected string literal + --> $DIR/parse-error.rs:44:30 + | +LL | asm!("", clobber_abi(foo)); + | ^^^ not a string literal + +error: expected one of `)` or `,`, found `foo` + --> $DIR/parse-error.rs:46:34 + | +LL | asm!("", clobber_abi("C" foo)); + | ^^^ expected one of `)` or `,` + +error: expected string literal + --> $DIR/parse-error.rs:48:35 + | +LL | asm!("", clobber_abi("C", foo)); + | ^^^ not a string literal + +error: arguments are not allowed after clobber_abi + --> $DIR/parse-error.rs:50:38 + | +LL | asm!("{}", clobber_abi("C"), const foo); + | ---------------- ^^^^^^^^^ argument + | | + | clobber_abi + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:53:29 + | +LL | asm!("", options(), clobber_abi("C")); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:55:31 + | +LL | asm!("{}", options(), clobber_abi("C"), const foo); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:57:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:57:36 + | +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` + +error: explicit register arguments cannot have names + --> $DIR/parse-error.rs:62:18 + | +LL | asm!("", a = in("eax") foo); + | ^^^^^^^^^^^^^^^^^ + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:64:36 + | +LL | asm!("{a}", in("eax") foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: named arguments cannot follow explicit register arguments + --> $DIR/parse-error.rs:67:36 + | +LL | asm!("{a}", in("eax") foo, a = const bar); + | ------------- ^^^^^^^^^^^^^ named argument + | | + | explicit register argument + +error: positional arguments cannot follow named arguments or explicit register arguments + --> $DIR/parse-error.rs:70:36 + | +LL | asm!("{1}", in("eax") foo, const bar); + | ------------- ^^^^^^^^^ positional argument + | | + | explicit register argument + +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` + --> $DIR/parse-error.rs:73:29 + | +LL | asm!("", options(), ""); + | ^^ expected one of 9 possible tokens + +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:75:33 + | +LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); + | ^^^^ expected one of 9 possible tokens + +error: asm template must be a string literal + --> $DIR/parse-error.rs:77:14 + | +LL | asm!(format!("{{{}}}", 0), in(reg) foo); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:79:21 + | +LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:81:28 + | +LL | asm!("{}", in(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:83:31 + | +LL | asm!("{}", inout(reg) _); + | ^ + +error: _ cannot be used for input operands + --> $DIR/parse-error.rs:85:35 + | +LL | asm!("{}", inlateout(reg) _); + | ^ + +error: requires at least a template string argument + --> $DIR/parse-error.rs:92:1 + | +LL | global_asm!(); + | ^^^^^^^^^^^^^ + +error: asm template must be a string literal + --> $DIR/parse-error.rs:94:13 + | +LL | global_asm!(FOO); + | ^^^ + +error: expected token: `,` + --> $DIR/parse-error.rs:96:18 + | +LL | global_asm!("{}" FOO); + | ^^^ expected `,` + +error: expected operand, options, or additional template string + --> $DIR/parse-error.rs:98:19 + | +LL | global_asm!("{}", FOO); + | ^^^ expected operand, options, or additional template string + +error: expected expression, found end of macro arguments + --> $DIR/parse-error.rs:100:24 + | +LL | global_asm!("{}", const); + | ^ expected expression + +error: expected one of `,`, `.`, `?`, or an operator, found `FOO` + --> $DIR/parse-error.rs:102:30 + | +LL | global_asm!("{}", const(reg) FOO); + | ^^^ expected one of `,`, `.`, `?`, or an operator + +error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` + --> $DIR/parse-error.rs:104:25 + | +LL | global_asm!("", options(FOO)); + | ^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/parse-error.rs:106:25 + | +LL | global_asm!("", options(nomem FOO)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` + --> $DIR/parse-error.rs:108:25 + | +LL | global_asm!("", options(nomem, FOO)); + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` + +error: arguments are not allowed after options + --> $DIR/parse-error.rs:110:30 + | +LL | global_asm!("{}", options(), const FOO); + | --------- ^^^^^^^^^ argument + | | + | previous options + +error: expected string literal + --> $DIR/parse-error.rs:112:29 + | +LL | global_asm!("", clobber_abi(FOO)); + | ^^^ not a string literal + +error: expected one of `)` or `,`, found `FOO` + --> $DIR/parse-error.rs:114:33 + | +LL | global_asm!("", clobber_abi("C" FOO)); + | ^^^ expected one of `)` or `,` + +error: expected string literal + --> $DIR/parse-error.rs:116:34 + | +LL | global_asm!("", clobber_abi("C", FOO)); + | ^^^ not a string literal + +error: arguments are not allowed after clobber_abi + --> $DIR/parse-error.rs:118:37 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ---------------- ^^^^^^^^^ argument + | | + | clobber_abi + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:118:19 + | +LL | global_asm!("{}", clobber_abi("C"), const FOO); + | ^^^^^^^^^^^^^^^^ + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:121:28 + | +LL | global_asm!("", options(), clobber_abi("C")); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: clobber_abi is not allowed after options + --> $DIR/parse-error.rs:123:30 + | +LL | global_asm!("{}", options(), clobber_abi("C"), const FOO); + | --------- ^^^^^^^^^^^^^^^^ + | | + | options + +error: `clobber_abi` cannot be used with `global_asm!` + --> $DIR/parse-error.rs:125:17 + | +LL | global_asm!("", clobber_abi("C"), clobber_abi("C")); + | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ + +error: duplicate argument named `a` + --> $DIR/parse-error.rs:127:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ------------- ^^^^^^^^^^^^^ duplicate argument + | | + | previously here + +error: argument never used + --> $DIR/parse-error.rs:127:35 + | +LL | global_asm!("{a}", a = const FOO, a = const BAR); + | ^^^^^^^^^^^^^ argument never used + | + = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` + +error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""` + --> $DIR/parse-error.rs:130:28 + | +LL | global_asm!("", options(), ""); + | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym` + +error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"` + --> $DIR/parse-error.rs:132:30 + | +LL | global_asm!("{}", const FOO, "{}", const FOO); + | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym` + +error: asm template must be a string literal + --> $DIR/parse-error.rs:134:13 + | +LL | global_asm!(format!("{{{}}}", 0), const FOO); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: asm template must be a string literal + --> $DIR/parse-error.rs:136:20 + | +LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +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` +... +LL | asm!("{}", options(), const foo); + | ^^^ non-constant value + +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` +... +LL | asm!("{}", clobber_abi("C"), const foo); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", a = const foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{a}", in("eax") foo, a = const bar); + | ^^^ non-constant value + +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` +... +LL | asm!("{1}", in("eax") foo, const bar); + | ^^^ non-constant value + +error: aborting due to 66 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/x86_64/srcloc.rs b/tests/ui/asm/x86_64/srcloc.rs new file mode 100644 index 000000000..1135ad2e1 --- /dev/null +++ b/tests/ui/asm/x86_64/srcloc.rs @@ -0,0 +1,131 @@ +// only-x86_64 +// build-fail +// compile-flags: -Ccodegen-units=1 + +use std::arch::asm; + +// Checks that inline asm errors are mapped to the correct line in the source code. + +fn main() { + unsafe { + asm!("invalid_instruction"); + //~^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(" + invalid_instruction + "); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(r#" + invalid_instruction + "#); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(" + mov eax, eax + invalid_instruction + mov eax, eax + "); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(r#" + mov eax, eax + invalid_instruction + mov eax, eax + "#); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(concat!("invalid", "_", "instruction")); + //~^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); + //~^ WARN: scale factor without index register is ignored + + asm!( + "invalid_instruction", + ); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + "mov eax, eax", + "invalid_instruction", + "mov eax, eax", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + "mov eax, eax\n", + "invalid_instruction", + "mov eax, eax", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + "mov eax, eax", + concat!("invalid", "_", "instruction"), + "mov eax, eax", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!( + concat!("mov eax", ", ", "eax"), + concat!("invalid", "_", "instruction"), + concat!("mov eax", ", ", "eax"), + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + // Make sure template strings get separated + asm!( + "invalid_instruction1", + "invalid_instruction2", + ); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + ); + //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", + ), + ); + //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3' + //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4' + + asm!( + concat!( + "invalid", "_", "instruction1", "\n", + "invalid", "_", "instruction2", "\n", + ), + concat!( + "invalid", "_", "instruction3", "\n", + "invalid", "_", "instruction4", "\n", + ), + ); + //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1' + //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2' + //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3' + //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4' + + asm!( + "", + "\n", + "invalid_instruction" + ); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + } +} diff --git a/tests/ui/asm/x86_64/srcloc.stderr b/tests/ui/asm/x86_64/srcloc.stderr new file mode 100644 index 000000000..8899c1b91 --- /dev/null +++ b/tests/ui/asm/x86_64/srcloc.stderr @@ -0,0 +1,302 @@ +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:11:15 + | +LL | asm!("invalid_instruction"); + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:15:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:20:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:26:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :4:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:33:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :4:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:38:14 + | +LL | asm!(concat!("invalid", "_", "instruction")); + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +warning: scale factor without index register is ignored + --> $DIR/srcloc.rs:41:15 + | +LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax)); + | ^ + | +note: instantiated into assembly here + --> :1:23 + | +LL | movaps %xmm3, (%esi, 2) + | ^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:45:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:51:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:58:14 + | +LL | "invalid_instruction", + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:65:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:72:13 + | +LL | concat!("invalid", "_", "instruction"), + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:79:14 + | +LL | "invalid_instruction1", + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:80:14 + | +LL | "invalid_instruction2", + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:86:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:86:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:95:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:95:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction3' + --> $DIR/srcloc.rs:99:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :4:1 + | +LL | invalid_instruction3 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction4' + --> $DIR/srcloc.rs:99:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction4 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction1' + --> $DIR/srcloc.rs:110:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction1 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction2' + --> $DIR/srcloc.rs:110:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :3:1 + | +LL | invalid_instruction2 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction3' + --> $DIR/srcloc.rs:114:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction3 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction4' + --> $DIR/srcloc.rs:114:13 + | +LL | concat!( + | ^ + | +note: instantiated into assembly here + --> :6:1 + | +LL | invalid_instruction4 + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:127:14 + | +LL | "invalid_instruction" + | ^ + | +note: instantiated into assembly here + --> :5:1 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors; 1 warning emitted + diff --git a/tests/ui/asm/x86_64/sym.rs b/tests/ui/asm/x86_64/sym.rs new file mode 100644 index 000000000..93ef4f090 --- /dev/null +++ b/tests/ui/asm/x86_64/sym.rs @@ -0,0 +1,84 @@ +// only-x86_64 +// only-linux +// needs-asm-support +// run-pass + +#![feature(thread_local)] + +use std::arch::asm; + +extern "C" fn f1() -> i32 { + 111 +} + +// The compiler will generate a shim to hide the caller location parameter. +#[track_caller] +fn f2() -> i32 { + 222 +} + +macro_rules! call { + ($func:path) => { + unsafe { + let result: i32; + asm!("call {}", sym $func, + out("rax") result, + out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _, + out("r8") _, out("r9") _, out("r10") _, out("r11") _, + out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _, + out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _, + out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _, + out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _, + ); + result + } + } +} + +macro_rules! static_addr { + ($s:expr) => { + unsafe { + let result: *const u32; + // LEA performs a RIP-relative address calculation and returns the address + asm!("lea {}, [rip + {}]", out(reg) result, sym $s); + result + } + } +} +macro_rules! static_tls_addr { + ($s:expr) => { + unsafe { + let result: *const u32; + asm!( + " + # Load TLS base address + mov {out}, qword ptr fs:[0] + # Calculate the address of sym in the TLS block. The @tpoff + # relocation gives the offset of the symbol from the start + # of the TLS block. + lea {out}, [{out} + {sym}@tpoff] + ", + out = out(reg) result, + sym = sym $s + ); + result + } + } +} + +static S1: u32 = 111; +#[thread_local] +static S2: u32 = 222; + +fn main() { + assert_eq!(call!(f1), 111); + assert_eq!(call!(f2), 222); + assert_eq!(static_addr!(S1), &S1 as *const u32); + assert_eq!(static_tls_addr!(S2), &S2 as *const u32); + std::thread::spawn(|| { + assert_eq!(static_addr!(S1), &S1 as *const u32); + assert_eq!(static_tls_addr!(S2), &S2 as *const u32); + }) + .join() + .unwrap(); +} diff --git a/tests/ui/asm/x86_64/target-feature-attr.rs b/tests/ui/asm/x86_64/target-feature-attr.rs new file mode 100644 index 000000000..14490c3e0 --- /dev/null +++ b/tests/ui/asm/x86_64/target-feature-attr.rs @@ -0,0 +1,42 @@ +// only-x86_64 + +#![feature(avx512_target_feature)] + +use std::arch::asm; + +#[target_feature(enable = "avx")] +unsafe fn foo() { + let mut x = 1; + let y = 2; + asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + assert_eq!(x, 3); +} + +unsafe fn bar() { + let mut x = 1; + let y = 2; + asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + //~^ ERROR: register class `ymm_reg` requires the `avx` target feature + //~| ERROR: register class `ymm_reg` requires the `avx` target feature + //~| ERROR: register class `ymm_reg` requires the `avx` target feature + assert_eq!(x, 3); +} + +#[target_feature(enable = "avx512bw")] +unsafe fn baz() { + let x = 1; + asm!("/* {0} */", in(kreg) x); +} + +unsafe fn baz2() { + let x = 1; + asm!("/* {0} */", in(kreg) x); + //~^ ERROR: register class `kreg` requires at least one of the following target features: avx512bw, avx512f +} + +fn main() { + unsafe { + foo(); + bar(); + } +} diff --git a/tests/ui/asm/x86_64/target-feature-attr.stderr b/tests/ui/asm/x86_64/target-feature-attr.stderr new file mode 100644 index 000000000..c852726ee --- /dev/null +++ b/tests/ui/asm/x86_64/target-feature-attr.stderr @@ -0,0 +1,26 @@ +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:18:40 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^ + +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:18:55 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^ + +error: register class `ymm_reg` requires the `avx` target feature + --> $DIR/target-feature-attr.rs:18:70 + | +LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x); + | ^^^^^^^^^^^^^^^^^^ + +error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f + --> $DIR/target-feature-attr.rs:33:23 + | +LL | asm!("/* {0} */", in(kreg) x); + | ^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs new file mode 100644 index 000000000..80b29ec87 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -0,0 +1,87 @@ +// only-x86_64 + +#![feature(repr_simd, never_type)] + +use std::arch::{asm, global_asm}; + +#[repr(simd)] +struct SimdNonCopy(f32, f32, f32, f32); + +fn main() { + unsafe { + // Inputs must be initialized + + let x: u64; + asm!("{}", in(reg) x); + let mut y: u64; + asm!("{}", inout(reg) y); + let _ = y; + + // Outputs require mutable places + + let v: Vec = vec![0, 1, 2]; + asm!("{}", in(reg) v[0]); + asm!("{}", out(reg) v[0]); + asm!("{}", inout(reg) v[0]); + + // Sym operands must point to a function or static + + const C: i32 = 0; + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + asm!("{}", sym C); + //~^ ERROR invalid `sym` operand + asm!("{}", sym x); + //~^ ERROR invalid `sym` operand + + // Register operands must be Copy + + asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + //~^ ERROR arguments for inline assembly must be copyable + + // Register operands must be integers, floats, SIMD vectors, pointers or + // function pointers. + + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps()); + asm!("{}", in(reg) 0 as *const u8); + asm!("{}", in(reg) 0 as *mut u8); + asm!("{}", in(reg) main as fn()); + asm!("{}", in(reg) |x: i32| x); + //~^ ERROR cannot use value of type + asm!("{}", in(reg) vec![0]); + //~^ ERROR cannot use value of type `Vec` for inline assembly + asm!("{}", in(reg) (1, 2, 3)); + //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly + asm!("{}", in(reg) [1, 2, 3]); + //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly + + // Register inputs (but not outputs) allow references and function types + + let mut f = main; + let mut r = &mut 0; + asm!("{}", in(reg) f); + asm!("{}", inout(reg) f); + //~^ ERROR cannot use value of type `fn() {main}` for inline assembly + asm!("{}", in(reg) r); + asm!("{}", inout(reg) r); + //~^ ERROR cannot use value of type `&mut i32` for inline assembly + let _ = (f, r); + + // Type checks ignore never type + + let u: ! = unreachable!(); + asm!("{}", in(reg) u); + } +} + +// Sym operands must point to a function or static + +const C: i32 = 0; +static S: i32 = 0; +global_asm!("{}", sym S); +global_asm!("{}", sym main); +global_asm!("{}", sym C); +//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr new file mode 100644 index 000000000..d9ca25519 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -0,0 +1,83 @@ +error: invalid `sym` operand + --> $DIR/type-check-2.rs:35:24 + | +LL | asm!("{}", sym x); + | ^ is a local variable + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/type-check-2.rs:86:19 + | +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/type-check-2.rs:33:20 + | +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: arguments for inline assembly must be copyable + --> $DIR/type-check-2.rs:40:32 + | +LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `SimdNonCopy` does not implement the Copy trait + +error: cannot use value of type `[closure@$DIR/type-check-2.rs:52:28: 52:36]` for inline assembly + --> $DIR/type-check-2.rs:52:28 + | +LL | asm!("{}", in(reg) |x: i32| x); + | ^^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `Vec` for inline assembly + --> $DIR/type-check-2.rs:54:28 + | +LL | asm!("{}", in(reg) vec![0]); + | ^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot use value of type `(i32, i32, i32)` for inline assembly + --> $DIR/type-check-2.rs:56:28 + | +LL | asm!("{}", in(reg) (1, 2, 3)); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `[i32; 3]` for inline assembly + --> $DIR/type-check-2.rs:58:28 + | +LL | asm!("{}", in(reg) [1, 2, 3]); + | ^^^^^^^^^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `fn() {main}` for inline assembly + --> $DIR/type-check-2.rs:66:31 + | +LL | asm!("{}", inout(reg) f); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: cannot use value of type `&mut i32` for inline assembly + --> $DIR/type-check-2.rs:69:31 + | +LL | asm!("{}", inout(reg) r); + | ^ + | + = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/x86_64/type-check-3.rs b/tests/ui/asm/x86_64/type-check-3.rs new file mode 100644 index 000000000..89c849c75 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-3.rs @@ -0,0 +1,73 @@ +// only-x86_64 +// compile-flags: -C target-feature=+avx512f + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps}; + +fn main() { + unsafe { + // Types must be listed in the register class. + + asm!("{}", in(reg) 0i128); + //~^ ERROR type `i128` cannot be used with this register class + asm!("{}", in(reg) _mm_setzero_ps()); + //~^ ERROR type `__m128` cannot be used with this register class + asm!("{}", in(reg) _mm256_setzero_ps()); + //~^ ERROR type `__m256` cannot be used with this register class + asm!("{}", in(xmm_reg) 0u8); + //~^ ERROR type `u8` cannot be used with this register class + asm!("{:e}", in(reg) 0i32); + asm!("{}", in(xmm_reg) 0i32); + asm!("{:e}", in(reg) 0f32); + asm!("{}", in(xmm_reg) 0f32); + asm!("{}", in(xmm_reg) _mm_setzero_ps()); + asm!("{:x}", in(ymm_reg) _mm_setzero_ps()); + asm!("{}", in(kreg) 0u16); + asm!("{}", in(kreg) 0u64); + //~^ ERROR `avx512bw` target feature is not enabled + + // Template modifier suggestions for sub-registers + + asm!("{0} {0}", in(reg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{0} {0:x}", in(reg) 0i16); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0i32); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(reg) 0i64); + asm!("{}", in(ymm_reg) 0i64); + //~^ WARN formatting may not be suitable for sub-register argument + asm!("{}", in(ymm_reg) _mm256_setzero_ps()); + asm!("{:l}", in(reg) 0i16); + asm!("{:l}", in(reg) 0i32); + asm!("{:l}", in(reg) 0i64); + asm!("{:x}", in(ymm_reg) 0i64); + asm!("{:x}", in(ymm_reg) _mm256_setzero_ps()); + + // Suggest different register class for type + + asm!("{}", in(reg) 0i8); + //~^ ERROR type `i8` cannot be used with this register class + asm!("{}", in(reg_byte) 0i8); + + // Split inout operands must have compatible types + + let mut val_i16: i16; + let mut val_f32: f32; + let mut val_u32: u32; + let mut val_u64: u64; + let mut val_ptr: *mut u8; + asm!("{:r}", inout(reg) 0u16 => val_i16); + asm!("{:r}", inout(reg) 0u32 => val_f32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) 0u32 => val_ptr); + //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) main => val_u32); + //~^ ERROR incompatible types for asm inout argument + asm!("{:r}", inout(reg) 0u64 => val_ptr); + asm!("{:r}", inout(reg) main => val_u64); + } +} diff --git a/tests/ui/asm/x86_64/type-check-3.stderr b/tests/ui/asm/x86_64/type-check-3.stderr new file mode 100644 index 000000000..1baf50ff6 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-3.stderr @@ -0,0 +1,118 @@ +error: type `i128` cannot be used with this register class + --> $DIR/type-check-3.rs:14:28 + | +LL | asm!("{}", in(reg) 0i128); + | ^^^^^ + | + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 + +error: type `__m128` cannot be used with this register class + --> $DIR/type-check-3.rs:16:28 + | +LL | asm!("{}", in(reg) _mm_setzero_ps()); + | ^^^^^^^^^^^^^^^^ + | + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 + +error: type `__m256` cannot be used with this register class + --> $DIR/type-check-3.rs:18:28 + | +LL | asm!("{}", in(reg) _mm256_setzero_ps()); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 + +error: type `u8` cannot be used with this register class + --> $DIR/type-check-3.rs:20:32 + | +LL | asm!("{}", in(xmm_reg) 0u8); + | ^^^ + | + = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2 + +error: `avx512bw` target feature is not enabled + --> $DIR/type-check-3.rs:29:29 + | +LL | asm!("{}", in(kreg) 0u64); + | ^^^^ + | + = note: this is required to use type `u64` with register class `kreg` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:34:15 + | +LL | asm!("{0} {0}", in(reg) 0i16); + | ^^^ ^^^ ---- for this argument + | + = help: use `{0:x}` to have the register formatted as `ax` + = help: or use `{0:r}` to keep the default formatting of `rax` + = note: `#[warn(asm_sub_register)]` on by default + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:36:15 + | +LL | asm!("{0} {0:x}", in(reg) 0i16); + | ^^^ ---- for this argument + | + = help: use `{0:x}` to have the register formatted as `ax` + = help: or use `{0:r}` to keep the default formatting of `rax` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:38:15 + | +LL | asm!("{}", in(reg) 0i32); + | ^^ ---- for this argument + | + = help: use `{0:e}` to have the register formatted as `eax` + = help: or use `{0:r}` to keep the default formatting of `rax` + +warning: formatting may not be suitable for sub-register argument + --> $DIR/type-check-3.rs:41:15 + | +LL | asm!("{}", in(ymm_reg) 0i64); + | ^^ ---- for this argument + | + = help: use `{0:x}` to have the register formatted as `xmm0` + = help: or use `{0:y}` to keep the default formatting of `ymm0` + +error: type `i8` cannot be used with this register class + --> $DIR/type-check-3.rs:52:28 + | +LL | asm!("{}", in(reg) 0i8); + | ^^^ + | + = note: register class `reg` supports these types: i16, i32, i64, f32, f64 + = help: consider using the `reg_byte` register class instead + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:64:33 + | +LL | asm!("{:r}", inout(reg) 0u32 => val_f32); + | ^^^^ ^^^^^^^ type `f32` + | | + | type `u32` + | + = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:66:33 + | +LL | asm!("{:r}", inout(reg) 0u32 => val_ptr); + | ^^^^ ^^^^^^^ type `*mut u8` + | | + | type `u32` + | + = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + +error: incompatible types for asm inout argument + --> $DIR/type-check-3.rs:68:33 + | +LL | asm!("{:r}", inout(reg) main => val_u32); + | ^^^^ ^^^^^^^ type `u32` + | | + | type `fn()` + | + = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size + +error: aborting due to 9 previous errors; 4 warnings emitted + diff --git a/tests/ui/asm/x86_64/type-check-4.rs b/tests/ui/asm/x86_64/type-check-4.rs new file mode 100644 index 000000000..3d5d3807c --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-4.rs @@ -0,0 +1,28 @@ +// only-x86_64 +// compile-flags: -C target-feature=+avx512f + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps}; + +fn main() {} + +// Constants must be... constant + +static S: i32 = 1; +const fn const_foo(x: i32) -> i32 { + x +} +const fn const_bar(x: T) -> T { + x +} +global_asm!("{}", const S); +//~^ ERROR constants cannot refer to statics +global_asm!("{}", const const_foo(0)); +global_asm!("{}", const const_foo(S)); +//~^ ERROR constants cannot refer to statics +global_asm!("{}", const const_bar(0)); +global_asm!("{}", const const_bar(S)); +//~^ ERROR constants cannot refer to statics diff --git a/tests/ui/asm/x86_64/type-check-4.stderr b/tests/ui/asm/x86_64/type-check-4.stderr new file mode 100644 index 000000000..3875bcc21 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-4.stderr @@ -0,0 +1,27 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/type-check-4.rs:21:25 + | +LL | global_asm!("{}", const S); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/type-check-4.rs:24:35 + | +LL | global_asm!("{}", const const_foo(S)); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/type-check-4.rs:27:35 + | +LL | global_asm!("{}", const const_bar(S)); + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/asm/x86_64/type-check-5.rs b/tests/ui/asm/x86_64/type-check-5.rs new file mode 100644 index 000000000..1d579ccc9 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-5.rs @@ -0,0 +1,62 @@ +// only-x86_64 + +#![feature(repr_simd, never_type)] + +use std::arch::asm; + +#[repr(simd)] +struct SimdNonCopy(f32, f32, f32, f32); + +fn main() { + unsafe { + // Inputs must be initialized + + let x: u64; + asm!("{}", in(reg) x); + //~^ ERROR E0381 + let mut y: u64; + asm!("{}", inout(reg) y); + //~^ ERROR E0381 + let _ = y; + + // Outputs require mutable places + + let v: Vec = vec![0, 1, 2]; + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + asm!("{}", in(reg) v[0]); + asm!("{}", out(reg) v[0]); + asm!("{}", inout(reg) v[0]); + + // Sym operands must point to a function or static + + const C: i32 = 0; + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + + // Register operands must be Copy + + // Register operands must be integers, floats, SIMD vectors, pointers or + // function pointers. + + asm!("{}", in(reg) 0i64); + asm!("{}", in(reg) 0f64); + asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps()); + asm!("{}", in(reg) 0 as *const u8); + asm!("{}", in(reg) 0 as *mut u8); + asm!("{}", in(reg) main as fn()); + + // Register inputs (but not outputs) allow references and function types + + let mut f = main; + let mut r = &mut 0; + asm!("{}", in(reg) f); + asm!("{}", in(reg) r); + let _ = (f, r); + + // Type checks ignore never type + + let u: ! = unreachable!(); + asm!("{}", in(reg) u); + } +} diff --git a/tests/ui/asm/x86_64/type-check-5.stderr b/tests/ui/asm/x86_64/type-check-5.stderr new file mode 100644 index 000000000..7970e76d6 --- /dev/null +++ b/tests/ui/asm/x86_64/type-check-5.stderr @@ -0,0 +1,46 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/type-check-5.rs:15:28 + | +LL | let x: u64; + | - binding declared here but left uninitialized +LL | asm!("{}", in(reg) x); + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u64 = 0; + | +++ + +error[E0381]: used binding `y` isn't initialized + --> $DIR/type-check-5.rs:18:9 + | +LL | let mut y: u64; + | ----- binding declared here but left uninitialized +LL | asm!("{}", inout(reg) y); + | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut y: u64 = 0; + | +++ + +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/type-check-5.rs:24:13 + | +LL | let v: Vec = vec![0, 1, 2]; + | ^ not mutable +... +LL | asm!("{}", out(reg) v[0]); + | - cannot borrow as mutable +LL | asm!("{}", inout(reg) v[0]); + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec = vec![0, 1, 2]; + | +++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0381, E0596. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/assign-assign.rs b/tests/ui/assign-assign.rs new file mode 100644 index 000000000..bcf506b39 --- /dev/null +++ b/tests/ui/assign-assign.rs @@ -0,0 +1,30 @@ +// run-pass +// Issue 483 - Assignment expressions result in nil + +fn test_assign() { + let mut x: isize; + let y: () = x = 10; + assert_eq!(x, 10); + assert_eq!(y, ()); + let mut z = x = 11; + assert_eq!(x, 11); + assert_eq!(z, ()); + z = x = 12; + assert_eq!(x, 12); + assert_eq!(z, ()); +} + +fn test_assign_op() { + let mut x: isize = 0; + let y: () = x += 10; + assert_eq!(x, 10); + assert_eq!(y, ()); + let mut z = x += 11; + assert_eq!(x, 21); + assert_eq!(z, ()); + z = x += 12; + assert_eq!(x, 33); + assert_eq!(z, ()); +} + +pub fn main() { test_assign(); test_assign_op(); } diff --git a/tests/ui/assign-imm-local-twice.rs b/tests/ui/assign-imm-local-twice.rs new file mode 100644 index 000000000..b50f6ab5d --- /dev/null +++ b/tests/ui/assign-imm-local-twice.rs @@ -0,0 +1,13 @@ +fn test() { + let v: isize; + //~^ HELP consider making this binding mutable + //~| SUGGESTION mut v + v = 1; //~ NOTE first assignment + println!("v={}", v); + v = 2; //~ ERROR cannot assign twice to immutable variable + //~| NOTE cannot assign twice to immutable + println!("v={}", v); +} + +fn main() { +} diff --git a/tests/ui/assign-imm-local-twice.stderr b/tests/ui/assign-imm-local-twice.stderr new file mode 100644 index 000000000..bba5d8dff --- /dev/null +++ b/tests/ui/assign-imm-local-twice.stderr @@ -0,0 +1,15 @@ +error[E0384]: cannot assign twice to immutable variable `v` + --> $DIR/assign-imm-local-twice.rs:7:5 + | +LL | let v: isize; + | - help: consider making this binding mutable: `mut v` +... +LL | v = 1; + | ----- first assignment to `v` +LL | println!("v={}", v); +LL | v = 2; + | ^^^^^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/assoc-lang-items.rs b/tests/ui/assoc-lang-items.rs new file mode 100644 index 000000000..23453d201 --- /dev/null +++ b/tests/ui/assoc-lang-items.rs @@ -0,0 +1,21 @@ +#![feature(lang_items)] + +trait Foo { + #[lang = "dummy_lang_item_1"] //~ ERROR definition + fn foo() {} + + #[lang = "dummy_lang_item_2"] //~ ERROR definition + fn bar(); + + #[lang = "dummy_lang_item_3"] //~ ERROR definition + type MyType; +} + +struct Bar; + +impl Bar { + #[lang = "dummy_lang_item_4"] //~ ERROR definition + fn test() {} +} + +fn main() {} diff --git a/tests/ui/assoc-lang-items.stderr b/tests/ui/assoc-lang-items.stderr new file mode 100644 index 000000000..040792fb1 --- /dev/null +++ b/tests/ui/assoc-lang-items.stderr @@ -0,0 +1,27 @@ +error[E0522]: definition of an unknown language item: `dummy_lang_item_1` + --> $DIR/assoc-lang-items.rs:4:5 + | +LL | #[lang = "dummy_lang_item_1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_1` + +error[E0522]: definition of an unknown language item: `dummy_lang_item_2` + --> $DIR/assoc-lang-items.rs:7:5 + | +LL | #[lang = "dummy_lang_item_2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_2` + +error[E0522]: definition of an unknown language item: `dummy_lang_item_3` + --> $DIR/assoc-lang-items.rs:10:5 + | +LL | #[lang = "dummy_lang_item_3"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_3` + +error[E0522]: definition of an unknown language item: `dummy_lang_item_4` + --> $DIR/assoc-lang-items.rs:17:5 + | +LL | #[lang = "dummy_lang_item_4"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ definition of unknown language item `dummy_lang_item_4` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0522`. diff --git a/tests/ui/assoc-oddities-3.rs b/tests/ui/assoc-oddities-3.rs new file mode 100644 index 000000000..cd025dc8b --- /dev/null +++ b/tests/ui/assoc-oddities-3.rs @@ -0,0 +1,13 @@ +// run-pass + +fn that_odd_parse(c: bool, n: usize) -> u32 { + let x = 2; + let a = [1, 2, 3, 4]; + let b = [5, 6, 7, 7]; + x + if c { a } else { b }[n] +} + +fn main() { + assert_eq!(4, that_odd_parse(true, 1)); + assert_eq!(8, that_odd_parse(false, 1)); +} diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.rs b/tests/ui/associated-consts/assoc-const-eq-missing.rs new file mode 100644 index 000000000..5e029a12d --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-missing.rs @@ -0,0 +1,26 @@ +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + + +fn foo1>() {} +//~^ ERROR associated type +fn foo2>() {} +//~^ ERROR associated type +fn foo3>() {} +//~^ ERROR associated type + +fn main() { + foo1::(); + foo2::(); + foo3::(); +} diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr new file mode 100644 index 000000000..b4bd6456c --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr @@ -0,0 +1,21 @@ +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:15:16 + | +LL | fn foo1>() {} + | ^ associated type `Z` not found + +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:17:16 + | +LL | fn foo2>() {} + | ^ associated type `Z` not found + +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:19:16 + | +LL | fn foo3>() {} + | ^ associated type `Z` not found + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs new file mode 100644 index 000000000..c5d78469e --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -0,0 +1,31 @@ +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub trait FooTy { + type T; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +impl FooTy for Bar { + type T = usize; +} + + +fn foo>() {} +//~^ ERROR expected associated constant bound, found type +fn foo2>() {} +//~^ ERROR expected associated type bound, found constant + +fn main() { + foo::(); + foo2::(); +} diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr new file mode 100644 index 000000000..11198729e --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -0,0 +1,26 @@ +error: expected associated constant bound, found type + --> $DIR/assoc-const-ty-mismatch.rs:23:15 + | +LL | fn foo>() {} + | ^^^^^^^ + | +note: associated constant defined here + --> $DIR/assoc-const-ty-mismatch.rs:5:3 + | +LL | const N: usize; + | ^^^^^^^^^^^^^^ + +error: expected associated type bound, found constant + --> $DIR/assoc-const-ty-mismatch.rs:25:18 + | +LL | fn foo2>() {} + | ^^^^^^^^ + | +note: associated type defined here + --> $DIR/assoc-const-ty-mismatch.rs:9:3 + | +LL | type T; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-consts/assoc-const.rs b/tests/ui/associated-consts/assoc-const.rs new file mode 100644 index 000000000..9c7884c80 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const.rs @@ -0,0 +1,22 @@ +// run-pass +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +const TEST:usize = 3; + + +fn foo>() {} + +fn main() { + foo::() +} diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.rs b/tests/ui/associated-consts/associated-const-ambiguity-report.rs new file mode 100644 index 000000000..927d2c69e --- /dev/null +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.rs @@ -0,0 +1,21 @@ +trait Foo { + const ID: i32; +} + +trait Bar { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +impl Bar for i32 { + const ID: i32 = 3; +} + +const X: i32 = ::ID; //~ ERROR E0034 + +fn main() { + assert_eq!(1, X); +} diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr new file mode 100644 index 000000000..5435f2232 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/associated-const-ambiguity-report.rs:17:23 + | +LL | const X: i32 = ::ID; + | ^^ multiple `ID` found + | +note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32` + --> $DIR/associated-const-ambiguity-report.rs:10:5 + | +LL | const ID: i32 = 1; + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32` + --> $DIR/associated-const-ambiguity-report.rs:14:5 + | +LL | const ID: i32 = 3; + | ^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | const X: i32 = ::ID; + | ~~~~~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | const X: i32 = ::ID; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-consts/associated-const-array-len.rs b/tests/ui/associated-consts/associated-const-array-len.rs new file mode 100644 index 000000000..17d782427 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-array-len.rs @@ -0,0 +1,10 @@ +trait Foo { + const ID: usize; +} + +const X: [i32; ::ID] = [0, 1, 2]; +//~^ ERROR the trait bound `i32: Foo` is not satisfied + +fn main() { + assert_eq!(1, X); +} diff --git a/tests/ui/associated-consts/associated-const-array-len.stderr b/tests/ui/associated-consts/associated-const-array-len.stderr new file mode 100644 index 000000000..86c62e7b7 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-array-len.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/associated-const-array-len.rs:5:16 + | +LL | const X: [i32; ::ID] = [0, 1, 2]; + | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-consts/associated-const-const-eval.rs b/tests/ui/associated-consts/associated-const-const-eval.rs new file mode 100644 index 000000000..5a34bb97c --- /dev/null +++ b/tests/ui/associated-consts/associated-const-const-eval.rs @@ -0,0 +1,20 @@ +// run-pass + +trait Foo { + const NUM: usize; +} + +impl Foo for i32 { + const NUM: usize = 1; +} + +const FOO: usize = ::NUM; + +fn main() { + assert_eq!(1, FOO); + + match 1 { + ::NUM => {}, + _ => assert!(false) + } +} diff --git a/tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs b/tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs new file mode 100644 index 000000000..611639b84 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs @@ -0,0 +1,28 @@ +// run-pass +// aux-build:associated-const-cc-lib.rs + + +extern crate associated_const_cc_lib as foolib; + +pub struct LocalFoo; + +impl foolib::Foo for LocalFoo { + const BAR: usize = 1; +} + +const FOO_1: usize = ::BAR; +const FOO_2: usize = ::BAR; +const FOO_3: usize = foolib::InherentBar::BAR; + +fn main() { + assert_eq!(0, FOO_1); + assert_eq!(1, FOO_2); + assert_eq!(3, FOO_3); + + match 0 { + ::BAR => {}, + ::BAR => assert!(false), + foolib::InherentBar::BAR => assert!(false), + _ => assert!(false) + } +} diff --git a/tests/ui/associated-consts/associated-const-cross-crate-defaults.rs b/tests/ui/associated-consts/associated-const-cross-crate-defaults.rs new file mode 100644 index 000000000..92d9cffec --- /dev/null +++ b/tests/ui/associated-consts/associated-const-cross-crate-defaults.rs @@ -0,0 +1,22 @@ +// run-pass +// aux-build:associated-const-cc-lib.rs + + +extern crate associated_const_cc_lib as foolib; + +pub struct LocalFooUseDefault; + +impl foolib::FooDefault for LocalFooUseDefault {} + +pub struct LocalFooOverwriteDefault; + +impl foolib::FooDefault for LocalFooOverwriteDefault { + const BAR: usize = 4; +} + +fn main() { + assert_eq!(1, ::BAR); + assert_eq!(2, ::BAR); + assert_eq!(1, ::BAR); + assert_eq!(4, ::BAR); +} diff --git a/tests/ui/associated-consts/associated-const-cross-crate.rs b/tests/ui/associated-consts/associated-const-cross-crate.rs new file mode 100644 index 000000000..ecdc112e0 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-cross-crate.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:associated-const-cc-lib.rs + + +extern crate associated_const_cc_lib as foolib; + +pub struct LocalFoo; + +impl foolib::Foo for LocalFoo { + const BAR: usize = 1; +} + +fn main() { + assert_eq!(0, ::BAR); + assert_eq!(1, ::BAR); + assert_eq!(3, foolib::InherentBar::BAR); +} diff --git a/tests/ui/associated-consts/associated-const-dead-code.rs b/tests/ui/associated-consts/associated-const-dead-code.rs new file mode 100644 index 000000000..f7b676418 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-dead-code.rs @@ -0,0 +1,12 @@ +#![deny(dead_code)] + +struct MyFoo; + +impl MyFoo { + const BAR: u32 = 1; + //~^ ERROR associated constant `BAR` is never used +} + +fn main() { + let _: MyFoo = MyFoo; +} diff --git a/tests/ui/associated-consts/associated-const-dead-code.stderr b/tests/ui/associated-consts/associated-const-dead-code.stderr new file mode 100644 index 000000000..cc701cc4b --- /dev/null +++ b/tests/ui/associated-consts/associated-const-dead-code.stderr @@ -0,0 +1,14 @@ +error: associated constant `BAR` is never used + --> $DIR/associated-const-dead-code.rs:6:11 + | +LL | const BAR: u32 = 1; + | ^^^ + | +note: the lint level is defined here + --> $DIR/associated-const-dead-code.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/associated-const-generic-obligations.rs b/tests/ui/associated-consts/associated-const-generic-obligations.rs new file mode 100644 index 000000000..498e315b5 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-generic-obligations.rs @@ -0,0 +1,18 @@ +trait Foo { + type Out: Sized; +} + +impl Foo for String { + type Out = String; +} + +trait Bar: Foo { + const FROM: Self::Out; +} + +impl Bar for T { + const FROM: &'static str = "foo"; + //~^ ERROR implemented const `FROM` has an incompatible type for trait [E0326] +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-generic-obligations.stderr b/tests/ui/associated-consts/associated-const-generic-obligations.stderr new file mode 100644 index 000000000..f45fa0ad5 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-generic-obligations.stderr @@ -0,0 +1,17 @@ +error[E0326]: implemented const `FROM` has an incompatible type for trait + --> $DIR/associated-const-generic-obligations.rs:14:17 + | +LL | const FROM: &'static str = "foo"; + | ^^^^^^^^^^^^ expected associated type, found `&str` + | +note: type in trait + --> $DIR/associated-const-generic-obligations.rs:10:17 + | +LL | const FROM: Self::Out; + | ^^^^^^^^^ + = note: expected associated type `::Out` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs new file mode 100644 index 000000000..63bac9613 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs @@ -0,0 +1,11 @@ +trait Foo { + const NAME: &'static str; +} + + +impl<'a> Foo for &'a () { + const NAME: &'a str = "unit"; + //~^ ERROR const not compatible with trait +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr new file mode 100644 index 000000000..742b81535 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -0,0 +1,18 @@ +error[E0308]: const not compatible with trait + --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5 + | +LL | const NAME: &'a str = "unit"; + | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'static str` + found reference `&'a str` +note: the lifetime `'a` as defined here... + --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6 + | +LL | impl<'a> Foo for &'a () { + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-type.rs b/tests/ui/associated-consts/associated-const-impl-wrong-type.rs new file mode 100644 index 000000000..1aad749c1 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-type.rs @@ -0,0 +1,12 @@ +trait Foo { + const BAR: u32; +} + +struct SignedBar; + +impl Foo for SignedBar { + const BAR: i32 = -1; + //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326] +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr new file mode 100644 index 000000000..f3616035f --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr @@ -0,0 +1,15 @@ +error[E0326]: implemented const `BAR` has an incompatible type for trait + --> $DIR/associated-const-impl-wrong-type.rs:8:16 + | +LL | const BAR: i32 = -1; + | ^^^ expected `u32`, found `i32` + | +note: type in trait + --> $DIR/associated-const-impl-wrong-type.rs:2:16 + | +LL | const BAR: u32; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/associated-consts/associated-const-in-global-const.rs b/tests/ui/associated-consts/associated-const-in-global-const.rs new file mode 100644 index 000000000..18d7a1215 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-in-global-const.rs @@ -0,0 +1,13 @@ +// run-pass + +struct Foo; + +impl Foo { + const BAR: f32 = 1.5; +} + +const FOOBAR: f32 = ::BAR; + +fn main() { + assert_eq!(1.5f32, FOOBAR); +} diff --git a/tests/ui/associated-consts/associated-const-in-trait.rs b/tests/ui/associated-consts/associated-const-in-trait.rs new file mode 100644 index 000000000..cf5d5d859 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-in-trait.rs @@ -0,0 +1,12 @@ +// #29924 + +trait Trait { + const N: usize; +} + +impl dyn Trait { + //~^ ERROR the trait `Trait` cannot be made into an object [E0038] + const fn n() -> usize { Self::N } +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr new file mode 100644 index 000000000..60bbe385c --- /dev/null +++ b/tests/ui/associated-consts/associated-const-in-trait.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/associated-const-in-trait.rs:7:6 + | +LL | impl dyn Trait { + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/associated-const-in-trait.rs:4:11 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | const N: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `N` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-consts/associated-const-inherent-impl.rs b/tests/ui/associated-consts/associated-const-inherent-impl.rs new file mode 100644 index 000000000..c6d956dff --- /dev/null +++ b/tests/ui/associated-consts/associated-const-inherent-impl.rs @@ -0,0 +1,11 @@ +// run-pass + +struct Foo; + +impl Foo { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, Foo::ID); +} diff --git a/tests/ui/associated-consts/associated-const-marks-live-code.rs b/tests/ui/associated-consts/associated-const-marks-live-code.rs new file mode 100644 index 000000000..68eb4e25d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-marks-live-code.rs @@ -0,0 +1,15 @@ +// run-pass + +#![deny(dead_code)] + +const GLOBAL_BAR: u32 = 1; + +struct Foo; + +impl Foo { + const BAR: u32 = GLOBAL_BAR; +} + +pub fn main() { + let _: u32 = Foo::BAR; +} diff --git a/tests/ui/associated-consts/associated-const-match-patterns.rs b/tests/ui/associated-consts/associated-const-match-patterns.rs new file mode 100644 index 000000000..62c1cb983 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-match-patterns.rs @@ -0,0 +1,68 @@ +// run-pass +// aux-build:empty-struct.rs + + +extern crate empty_struct; +use empty_struct::XEmpty2 as XFoo; + +struct Foo; + +#[derive(PartialEq, Eq)] +enum Bar { + Var1, + Var2, +} + +// Use inherent and trait impls to test UFCS syntax. +impl Foo { + const MYBAR: Bar = Bar::Var2; +} + +trait HasBar { + const THEBAR: Bar; +} + +impl HasBar for Foo { + const THEBAR: Bar = Bar::Var1; +} + +impl HasBar for XFoo { + const THEBAR: Bar = Bar::Var1; +} + +fn main() { + // Inherent impl + assert!(match Bar::Var2 { + Foo::MYBAR => true, + _ => false, + }); + assert!(match Bar::Var2 { + ::MYBAR => true, + _ => false, + }); + // Trait impl + assert!(match Bar::Var1 { + Foo::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + ::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + ::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + XFoo::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + ::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + ::THEBAR => true, + _ => false, + }); +} diff --git a/tests/ui/associated-consts/associated-const-no-item.rs b/tests/ui/associated-consts/associated-const-no-item.rs new file mode 100644 index 000000000..024d14e21 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-no-item.rs @@ -0,0 +1,10 @@ +trait Foo { + const ID: i32; +} + +const X: i32 = ::ID; +//~^ ERROR no associated item named `ID` found + +fn main() { + assert_eq!(1, X); +} diff --git a/tests/ui/associated-consts/associated-const-no-item.stderr b/tests/ui/associated-consts/associated-const-no-item.stderr new file mode 100644 index 000000000..fe27da5ac --- /dev/null +++ b/tests/ui/associated-consts/associated-const-no-item.stderr @@ -0,0 +1,16 @@ +error[E0599]: no associated item named `ID` found for type `i32` in the current scope + --> $DIR/associated-const-no-item.rs:5:23 + | +LL | const X: i32 = ::ID; + | ^^ associated item not found in `i32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `ID`, perhaps you need to implement it + --> $DIR/associated-const-no-item.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs new file mode 100644 index 000000000..f32ca0ccc --- /dev/null +++ b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs @@ -0,0 +1,10 @@ +// run-pass +trait Lattice { + const BOTTOM: Self; +} + +impl Lattice for Option { + const BOTTOM: Option = None; +} + +fn main(){} diff --git a/tests/ui/associated-consts/associated-const-overwrite-default.rs b/tests/ui/associated-consts/associated-const-overwrite-default.rs new file mode 100644 index 000000000..445135aef --- /dev/null +++ b/tests/ui/associated-consts/associated-const-overwrite-default.rs @@ -0,0 +1,13 @@ +// run-pass + +trait Foo { + const ID: i32 = 2; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, ::ID); +} diff --git a/tests/ui/associated-consts/associated-const-private-impl.rs b/tests/ui/associated-consts/associated-const-private-impl.rs new file mode 100644 index 000000000..3ee3134ac --- /dev/null +++ b/tests/ui/associated-consts/associated-const-private-impl.rs @@ -0,0 +1,15 @@ +mod bar1 { + pub use self::bar2::Foo; + mod bar2 { + pub struct Foo; + + impl Foo { + const ID: i32 = 1; + } + } +} + +fn main() { + assert_eq!(1, bar1::Foo::ID); + //~^ERROR associated constant `ID` is private +} diff --git a/tests/ui/associated-consts/associated-const-private-impl.stderr b/tests/ui/associated-consts/associated-const-private-impl.stderr new file mode 100644 index 000000000..a3fa3002e --- /dev/null +++ b/tests/ui/associated-consts/associated-const-private-impl.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated constant `ID` is private + --> $DIR/associated-const-private-impl.rs:13:30 + | +LL | const ID: i32 = 1; + | ------------- private associated constant defined here +... +LL | assert_eq!(1, bar1::Foo::ID); + | ^^ private associated constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/associated-consts/associated-const-public-impl.rs b/tests/ui/associated-consts/associated-const-public-impl.rs new file mode 100644 index 000000000..787bee0ff --- /dev/null +++ b/tests/ui/associated-consts/associated-const-public-impl.rs @@ -0,0 +1,16 @@ +// run-pass + +mod bar1 { + pub use self::bar2::Foo; + mod bar2 { + pub struct Foo; + + impl Foo { + pub const ID: i32 = 1; + } + } +} + +fn main() { + assert_eq!(1, bar1::Foo::ID); +} diff --git a/tests/ui/associated-consts/associated-const-range-match-patterns.rs b/tests/ui/associated-consts/associated-const-range-match-patterns.rs new file mode 100644 index 000000000..5276869a7 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-range-match-patterns.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code, unreachable_patterns)] +#![allow(ellipsis_inclusive_range_patterns)] + +struct Foo; + +trait HasNum { + const NUM: isize; +} +impl HasNum for Foo { + const NUM: isize = 1; +} + +fn main() { + assert!(match 2 { + Foo::NUM ... 3 => true, + _ => false, + }); + assert!(match 0 { + -1 ... ::NUM => true, + _ => false, + }); + assert!(match 1 { + ::NUM ... ::NUM => true, + _ => false, + }); + + assert!(match 2 { + Foo::NUM ..= 3 => true, + _ => false, + }); + assert!(match 0 { + -1 ..= ::NUM => true, + _ => false, + }); + assert!(match 1 { + ::NUM ..= ::NUM => true, + _ => false, + }); +} diff --git a/tests/ui/associated-consts/associated-const-resolution-order.rs b/tests/ui/associated-consts/associated-const-resolution-order.rs new file mode 100644 index 000000000..d2ccd30a6 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-resolution-order.rs @@ -0,0 +1,25 @@ +// run-pass + +struct MyType; + +impl MyType { + const IMPL_IS_INHERENT: bool = true; +} + +trait MyTrait { + const IMPL_IS_INHERENT: bool; + const IMPL_IS_ON_TRAIT: bool; +} + +impl MyTrait for MyType { + const IMPL_IS_INHERENT: bool = false; + const IMPL_IS_ON_TRAIT: bool = true; +} + +fn main() { + // Check that the inherent impl is used before the trait, but that the trait + // can still be accessed. + assert!(::IMPL_IS_INHERENT); + assert!(!::IMPL_IS_INHERENT); + assert!(::IMPL_IS_ON_TRAIT); +} diff --git a/tests/ui/associated-consts/associated-const-self-type.rs b/tests/ui/associated-consts/associated-const-self-type.rs new file mode 100644 index 000000000..36e1e4ecc --- /dev/null +++ b/tests/ui/associated-consts/associated-const-self-type.rs @@ -0,0 +1,13 @@ +// run-pass + +trait MyInt { + const ONE: Self; +} + +impl MyInt for i32 { + const ONE: i32 = 1; +} + +fn main() { + assert_eq!(1, ::ONE); +} diff --git a/tests/ui/associated-consts/associated-const-trait-bound.rs b/tests/ui/associated-consts/associated-const-trait-bound.rs new file mode 100644 index 000000000..403cdbd7f --- /dev/null +++ b/tests/ui/associated-consts/associated-const-trait-bound.rs @@ -0,0 +1,21 @@ +// build-pass (FIXME(62277): could be check-pass?) + +trait ConstDefault { + const DEFAULT: Self; +} + +trait Foo: Sized {} + +trait FooExt: Foo { + type T: ConstDefault; +} + +trait Bar { + const T: F::T; +} + +impl Bar for () { + const T: F::T = ::DEFAULT; +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arms.rs b/tests/ui/associated-consts/associated-const-type-parameter-arms.rs new file mode 100644 index 000000000..3f260d84e --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arms.rs @@ -0,0 +1,29 @@ +pub enum EFoo { A, B, C, D } + +pub trait Foo { + const X: EFoo; +} + +struct Abc; + +impl Foo for Abc { + const X: EFoo = EFoo::B; +} + +struct Def; +impl Foo for Def { + const X: EFoo = EFoo::D; +} + +pub fn test(arg: EFoo) { + match arg { + A::X => println!("A::X"), + //~^ error: associated consts cannot be referenced in patterns [E0158] + B::X => println!("B::X"), + //~^ error: associated consts cannot be referenced in patterns [E0158] + _ => (), + } +} + +fn main() { +} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr new file mode 100644 index 000000000..1ccf9febd --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr @@ -0,0 +1,15 @@ +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/associated-const-type-parameter-arms.rs:20:9 + | +LL | A::X => println!("A::X"), + | ^^^^ + +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/associated-const-type-parameter-arms.rs:22:9 + | +LL | B::X => println!("B::X"), + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs new file mode 100644 index 000000000..8fe79b97d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs @@ -0,0 +1,21 @@ +pub trait Foo { + const Y: usize; +} + +struct Abc; +impl Foo for Abc { + const Y: usize = 8; +} + +struct Def; +impl Foo for Def { + const Y: usize = 33; +} + +pub fn test() { + let _array = [4; ::Y]; + //~^ ERROR constant expression depends on a generic parameter +} + +fn main() { +} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr new file mode 100644 index 000000000..0bc019b2d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22 + | +LL | let _array = [4; ::Y]; + | ^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays.rs b/tests/ui/associated-consts/associated-const-type-parameter-arrays.rs new file mode 100644 index 000000000..5152d7840 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays.rs @@ -0,0 +1,20 @@ +pub trait Foo { + const Y: usize; +} + +struct Abc; +impl Foo for Abc { + const Y: usize = 8; +} + +struct Def; +impl Foo for Def { + const Y: usize = 33; +} + +pub fn test() { + let _array: [u32; ::Y]; + //~^ ERROR generic parameters may not be used +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr new file mode 100644 index 000000000..46a54a12d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/associated-const-type-parameter-arrays.rs:16:24 + | +LL | let _array: [u32; ::Y]; + | ^ cannot perform const operation using `A` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/associated-const-type-parameters.rs b/tests/ui/associated-consts/associated-const-type-parameters.rs new file mode 100644 index 000000000..e7ead1045 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameters.rs @@ -0,0 +1,44 @@ +// run-pass + +trait Foo { + const X: i32; + fn get_x() -> i32 { + Self::X + } +} + +struct Abc; +impl Foo for Abc { + const X: i32 = 11; +} + +struct Def; +impl Foo for Def { + const X: i32 = 97; +} + +struct Proxy(#[allow(unused_tuple_struct_fields)] T); + +impl Foo for Proxy { + const X: i32 = T::X; +} + +fn sub() -> i32 { + A::X - B::X +} + +trait Bar: Foo { + const Y: i32 = Self::X; +} + +fn main() { + assert_eq!(11, Abc::X); + assert_eq!(97, Def::X); + assert_eq!(11, Abc::get_x()); + assert_eq!(97, Def::get_x()); + assert_eq!(-86, sub::()); + assert_eq!(86, sub::()); + assert_eq!(-86, sub::, Def>()); + assert_eq!(-86, sub::>()); + assert_eq!(86, sub::, Proxy>()); +} diff --git a/tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs b/tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs new file mode 100644 index 000000000..ca44c9f45 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs @@ -0,0 +1,13 @@ +// run-pass + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, ::ID); +} diff --git a/tests/ui/associated-consts/associated-const-use-default.rs b/tests/ui/associated-consts/associated-const-use-default.rs new file mode 100644 index 000000000..adf36b1ff --- /dev/null +++ b/tests/ui/associated-consts/associated-const-use-default.rs @@ -0,0 +1,11 @@ +// run-pass + +trait Foo { + const ID: i32 = 1; +} + +impl Foo for i32 {} + +fn main() { + assert_eq!(1, ::ID); +} diff --git a/tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs b/tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs new file mode 100644 index 000000000..8f01bae4f --- /dev/null +++ b/tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs @@ -0,0 +1,25 @@ +// run-pass + +// The main purpose of this test is to ensure that different impls of the same +// trait can refer to each other without setting off the static recursion check +// (as long as there's no actual recursion). + +trait Foo { + const BAR: u32; +} + +struct IsFoo1; + +impl Foo for IsFoo1 { + const BAR: u32 = 1; +} + +struct IsFoo2; + +impl Foo for IsFoo2 { + const BAR: u32 = ::BAR; +} + +fn main() { + assert_eq!(::BAR, ::BAR); +} diff --git a/tests/ui/associated-consts/associated-const.rs b/tests/ui/associated-consts/associated-const.rs new file mode 100644 index 000000000..e4b1c29f3 --- /dev/null +++ b/tests/ui/associated-consts/associated-const.rs @@ -0,0 +1,13 @@ +// run-pass + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, ::ID); +} diff --git a/tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs b/tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs new file mode 100644 index 000000000..4fcefe32c --- /dev/null +++ b/tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs @@ -0,0 +1,34 @@ +#![crate_type="lib"] + +// These items are for testing that associated consts work cross-crate. +pub trait Foo { + const BAR: usize; +} + +pub struct FooNoDefault; + +impl Foo for FooNoDefault { + const BAR: usize = 0; +} + +// These test that defaults and default resolution work cross-crate. +pub trait FooDefault { + const BAR: usize = 1; +} + +pub struct FooOverwriteDefault; + +impl FooDefault for FooOverwriteDefault { + const BAR: usize = 2; +} + +pub struct FooUseDefault; + +impl FooDefault for FooUseDefault {} + +// Test inherent impls. +pub struct InherentBar; + +impl InherentBar { + pub const BAR: usize = 3; +} diff --git a/tests/ui/associated-consts/auxiliary/empty-struct.rs b/tests/ui/associated-consts/auxiliary/empty-struct.rs new file mode 100644 index 000000000..93275e714 --- /dev/null +++ b/tests/ui/associated-consts/auxiliary/empty-struct.rs @@ -0,0 +1,9 @@ +pub struct XEmpty1 {} +pub struct XEmpty2; +pub struct XEmpty7(); + +pub enum XE { + XEmpty3 {}, + XEmpty4, + XEmpty6(), +} diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.rs b/tests/ui/associated-consts/defaults-cyclic-fail.rs new file mode 100644 index 000000000..a1c6840a0 --- /dev/null +++ b/tests/ui/associated-consts/defaults-cyclic-fail.rs @@ -0,0 +1,17 @@ +// build-fail + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + //~^ cycle detected when const-evaluating + checking `Tr::A` + + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used +impl Tr for () {} + +fn main() { + // This triggers the cycle error + assert_eq!(<() as Tr>::A, 0); +} diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr new file mode 100644 index 000000000..a1483911b --- /dev/null +++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating + checking `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:19 + | +LL | const A: u8 = Self::B; + | ^^^^^^^ + | +note: ...which requires const-evaluating + checking `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:19 + | +LL | const B: u8 = Self::A; + | ^^^^^^^ + = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle +note: cycle used when const-evaluating + checking `main::promoted[1]` + --> $DIR/defaults-cyclic-fail.rs:16:16 + | +LL | assert_eq!(<() as Tr>::A, 0); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/defaults-cyclic-pass.rs b/tests/ui/associated-consts/defaults-cyclic-pass.rs new file mode 100644 index 000000000..82105f25f --- /dev/null +++ b/tests/ui/associated-consts/defaults-cyclic-pass.rs @@ -0,0 +1,36 @@ +// run-pass + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used, matching the +// behavior without defaults. +impl Tr for () {} + +// Overriding either constant breaks the cycle +impl Tr for u8 { + const A: u8 = 42; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 100; + const B: u8 = 123; +} + +fn main() { + assert_eq!(::A, 42); + assert_eq!(::B, 42); + + assert_eq!(::A, 0); + assert_eq!(::B, 0); + + assert_eq!(::A, 100); + assert_eq!(::B, 123); +} diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.rs b/tests/ui/associated-consts/defaults-not-assumed-fail.rs new file mode 100644 index 000000000..495dfb338 --- /dev/null +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.rs @@ -0,0 +1,44 @@ +// build-fail + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; + //~^ ERROR evaluation of `<() as Tr>::B` failed +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + assert_eq!(<() as Tr>::B, 0); // causes the error above + //~^ constant + + assert_eq!(::A, 254); + assert_eq!(::B, 255); + + assert_eq!(::A, 255); + assert_eq!(::B, 0); + + assert_eq!(::A, 254); + assert_eq!(::B, 0); +} diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr new file mode 100644 index 000000000..fb7159e40 --- /dev/null +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -0,0 +1,39 @@ +error[E0080]: evaluation of `<() as Tr>::B` failed + --> $DIR/defaults-not-assumed-fail.rs:8:19 + | +LL | const B: u8 = Self::A + 1; + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:16 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/associated-consts/defaults-not-assumed-pass.rs b/tests/ui/associated-consts/defaults-not-assumed-pass.rs new file mode 100644 index 000000000..c08e05c8a --- /dev/null +++ b/tests/ui/associated-consts/defaults-not-assumed-pass.rs @@ -0,0 +1,42 @@ +// run-pass + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + //assert_eq!(<() as Tr>::B, 0); // using this is an error + + assert_eq!(::A, 254); + assert_eq!(::B, 255); + + assert_eq!(::A, 255); + assert_eq!(::B, 0); + + assert_eq!(::A, 254); + assert_eq!(::B, 0); +} diff --git a/tests/ui/associated-consts/issue-102335-const.rs b/tests/ui/associated-consts/issue-102335-const.rs new file mode 100644 index 000000000..f60cb92da --- /dev/null +++ b/tests/ui/associated-consts/issue-102335-const.rs @@ -0,0 +1,12 @@ +#![feature(associated_const_equality)] + +trait T { + type A: S = 34>; + //~^ ERROR associated type bindings are not allowed here +} + +trait S { + const C: i32; +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr new file mode 100644 index 000000000..531d15c59 --- /dev/null +++ b/tests/ui/associated-consts/issue-102335-const.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-const.rs:4:17 + | +LL | type A: S = 34>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs new file mode 100644 index 000000000..86e45f10b --- /dev/null +++ b/tests/ui/associated-consts/issue-105330.rs @@ -0,0 +1,21 @@ +pub trait TraitWAssocConst { + const A: usize; +} +pub struct Demo {} + +impl TraitWAssocConst for impl Demo { //~ ERROR E0404 + //~^ ERROR E0562 + pubconst A: str = 32; //~ ERROR expected one of +} + +fn foo>() { //~ ERROR E0658 + foo::()(); //~ ERROR E0271 + //~^ ERROR E0618 + //~| ERROR E0277 +} + +fn main>() { //~ ERROR E0131 + //~^ ERROR E0658 + foo::(); //~ ERROR E0277 + //~^ ERROR E0271 +} diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr new file mode 100644 index 000000000..30c380152 --- /dev/null +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -0,0 +1,113 @@ +error: expected one of `!` or `::`, found `A` + --> $DIR/issue-105330.rs:8:14 + | +LL | impl TraitWAssocConst for impl Demo { + | - while parsing this item list starting here +LL | +LL | pubconst A: str = 32; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error[E0404]: expected trait, found struct `Demo` + --> $DIR/issue-105330.rs:6:32 + | +LL | impl TraitWAssocConst for impl Demo { + | ^^^^ not a trait + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo>() { + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-105330.rs:17:29 + | +LL | fn main>() { + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-105330.rs:6:27 + | +LL | impl TraitWAssocConst for impl Demo { + | ^^^^^^^^^ + +error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied + --> $DIR/issue-105330.rs:12:11 + | +LL | foo::()(); + | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo` + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:11 + | +LL | fn foo>() { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `::A == 32` + --> $DIR/issue-105330.rs:12:11 + | +LL | foo::()(); + | ^^^^ expected `32`, found `::A` + | + = note: expected constant `32` + found constant `::A` +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo>() { + | ^^^^ required by this bound in `foo` + +error[E0618]: expected function, found `()` + --> $DIR/issue-105330.rs:12:5 + | +LL | fn foo>() { + | ----------------------------------- `foo::` defined here returns `()` +LL | foo::()(); + | ^^^^^^^^^^^^^-- + | | + | call expression requires function + +error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied + --> $DIR/issue-105330.rs:19:11 + | +LL | foo::(); + | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo` + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:11 + | +LL | fn foo>() { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `::A == 32` + --> $DIR/issue-105330.rs:19:11 + | +LL | foo::(); + | ^^^^ expected `32`, found `::A` + | + = note: expected constant `32` + found constant `::A` +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo>() { + | ^^^^ required by this bound in `foo` + +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-105330.rs:17:8 + | +LL | fn main>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658. +For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs new file mode 100644 index 000000000..0315938a7 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs @@ -0,0 +1,15 @@ +// Check for recursion involving references to impl-associated const. + +trait Foo { + const BAR: u32; +} + +const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + +struct GlobalImplRef; + +impl GlobalImplRef { + const BAR: u32 = IMPL_REF_BAR; //~ ERROR E0391 +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr new file mode 100644 index 000000000..be5781761 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -0,0 +1,32 @@ +error[E0391]: cycle detected when elaborating drops for `::BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:22 + | +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 + | +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 + | +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `::BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs new file mode 100644 index 000000000..4e89f6862 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs @@ -0,0 +1,17 @@ +// Check for recursion involving references to trait-associated const default. + +trait Foo { + const BAR: u32; +} + +trait FooDefault { + const BAR: u32 = DEFAULT_REF_BAR; //~ ERROR E0391 +} + +const DEFAULT_REF_BAR: u32 = ::BAR; + +struct GlobalDefaultRef; + +impl FooDefault for GlobalDefaultRef {} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr new file mode 100644 index 000000000..8347b260b --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -0,0 +1,32 @@ +error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:22 + | +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 + | +LL | const DEFAULT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30 + | +LL | const DEFAULT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `FooDefault::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 + | +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `FooDefault::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 + | +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `FooDefault::BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs new file mode 100644 index 000000000..68b653ff3 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs @@ -0,0 +1,15 @@ +// Check for recursion involving references to trait-associated const. + +trait Foo { + const BAR: u32; +} + +const TRAIT_REF_BAR: u32 = ::BAR; + +struct GlobalTraitRef; + +impl Foo for GlobalTraitRef { + const BAR: u32 = TRAIT_REF_BAR; //~ ERROR E0391 +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr new file mode 100644 index 000000000..3955a3120 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -0,0 +1,32 @@ +error[E0391]: cycle detected when elaborating drops for `::BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:22 + | +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28 + | +LL | const TRAIT_REF_BAR: u32 = ::BAR; + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 + | +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 + | +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `::BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-47814.rs b/tests/ui/associated-consts/issue-47814.rs new file mode 100644 index 000000000..a28b1c001 --- /dev/null +++ b/tests/ui/associated-consts/issue-47814.rs @@ -0,0 +1,14 @@ +struct ArpIPv4<'a> { + s: &'a u8 +} + +impl<'a> ArpIPv4<'a> { + const LENGTH: usize = 20; + + pub fn to_buffer() -> [u8; Self::LENGTH] { + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-47814.stderr b/tests/ui/associated-consts/issue-47814.stderr new file mode 100644 index 000000000..2e4ddb811 --- /dev/null +++ b/tests/ui/associated-consts/issue-47814.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-47814.rs:8:32 + | +LL | pub fn to_buffer() -> [u8; Self::LENGTH] { + | ^^^^ + | +note: not a concrete type + --> $DIR/issue-47814.rs:5:10 + | +LL | impl<'a> ArpIPv4<'a> { + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/issue-58022.rs b/tests/ui/associated-consts/issue-58022.rs new file mode 100644 index 000000000..2a8a1eaa6 --- /dev/null +++ b/tests/ui/associated-consts/issue-58022.rs @@ -0,0 +1,19 @@ +pub trait Foo: Sized { + const SIZE: usize; + + fn new(slice: &[u8; Foo::SIZE]) -> Self; + //~^ ERROR: E0790 +} + +pub struct Bar(T); + +impl Bar<[u8]> { + const SIZE: usize = 32; + + fn new(slice: &[u8; Self::SIZE]) -> Self { + Foo(Box::new(*slice)) + //~^ ERROR: expected function, tuple struct or tuple variant, found trait `Foo` + } +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr new file mode 100644 index 000000000..56d85c066 --- /dev/null +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -0,0 +1,19 @@ +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-58022.rs:4:25 + | +LL | const SIZE: usize; + | ------------------ `Foo::SIZE` defined here +LL | +LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; + | ^^^^^^^^^ cannot refer to the associated constant of trait + +error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo` + --> $DIR/issue-58022.rs:14:9 + | +LL | Foo(Box::new(*slice)) + | ^^^ not a function, tuple struct or tuple variant + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0790. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/associated-consts/issue-63496.rs b/tests/ui/associated-consts/issue-63496.rs new file mode 100644 index 000000000..67ef4e74c --- /dev/null +++ b/tests/ui/associated-consts/issue-63496.rs @@ -0,0 +1,9 @@ +trait A { + const C: usize; + + fn f() -> ([u8; A::C], [u8; A::C]); + //~^ ERROR: E0790 + //~| ERROR: E0790 +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-63496.stderr b/tests/ui/associated-consts/issue-63496.stderr new file mode 100644 index 000000000..f2a4e01ad --- /dev/null +++ b/tests/ui/associated-consts/issue-63496.stderr @@ -0,0 +1,21 @@ +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-63496.rs:4:21 + | +LL | const C: usize; + | --------------- `A::C` defined here +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ cannot refer to the associated constant of trait + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-63496.rs:4:33 + | +LL | const C: usize; + | --------------- `A::C` defined here +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ cannot refer to the associated constant of trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr new file mode 100644 index 000000000..0c3581900 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:27:22 + | +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:35 + | +LL | const NEG_REV: i32 = T::NEG + (-i32::MIN); + | ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:32:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:36 + | +LL | const ADD_REV: i32 = T::ADD + (i32::MAX+1); + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:37:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:35 + | +LL | const DIV_REV: i32 = T::DIV + (1/0); + | ^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:42:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:35 + | +LL | const OOB_REV: i32 = T::OOB + [1][1]; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr new file mode 100644 index 000000000..0c3581900 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:27:22 + | +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:35 + | +LL | const NEG_REV: i32 = T::NEG + (-i32::MIN); + | ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:32:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:36 + | +LL | const ADD_REV: i32 = T::ADD + (i32::MAX+1); + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:37:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:35 + | +LL | const DIV_REV: i32 = T::DIV + (1/0); + | ^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:42:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:35 + | +LL | const OOB_REV: i32 = T::OOB + [1][1]; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..0c3581900 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:27:22 + | +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:35 + | +LL | const NEG_REV: i32 = T::NEG + (-i32::MIN); + | ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:32:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:36 + | +LL | const ADD_REV: i32 = T::ADD + (i32::MAX+1); + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:37:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:35 + | +LL | const DIV_REV: i32 = T::DIV + (1/0); + | ^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:42:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:35 + | +LL | const OOB_REV: i32 = T::OOB + [1][1]; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs new file mode 100644 index 000000000..d4af6e864 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs @@ -0,0 +1,46 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +#![crate_type="lib"] + +pub trait Foo { + const NEG: i32; + const NEG_REV: i32; + + const ADD: i32; + const ADD_REV: i32; + + const DIV: i32; + const DIV_REV: i32; + + const OOB: i32; + const OOB_REV: i32; +} + +// These constants cannot be evaluated already (they depend on `T::N`), so they can just be linted +// like normal run-time code. But codegen works a bit different in const context, so this test +// makes sure that we still catch overflow. Also make sure we emit the same lints if we reverse the +// operands (so that the generic operand comes first). +impl Foo for Vec { + const NEG: i32 = -i32::MIN + T::NEG; + //~^ ERROR arithmetic operation will overflow + const NEG_REV: i32 = T::NEG + (-i32::MIN); + //~^ ERROR arithmetic operation will overflow + + const ADD: i32 = (i32::MAX+1) + T::ADD; + //~^ ERROR arithmetic operation will overflow + const ADD_REV: i32 = T::ADD + (i32::MAX+1); + //~^ ERROR arithmetic operation will overflow + + const DIV: i32 = (1/0) + T::DIV; + //~^ ERROR operation will panic + const DIV_REV: i32 = T::DIV + (1/0); + //~^ ERROR operation will panic + + const OOB: i32 = [1][1] + T::OOB; + //~^ ERROR operation will panic + const OOB_REV: i32 = T::OOB + [1][1]; + //~^ ERROR operation will panic +} diff --git a/tests/ui/associated-consts/issue-88599-ref-self.rs b/tests/ui/associated-consts/issue-88599-ref-self.rs new file mode 100644 index 000000000..f1144db44 --- /dev/null +++ b/tests/ui/associated-consts/issue-88599-ref-self.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait First { + const CONST: usize; +} +pub trait Second {} + +impl<'a> First for dyn Second +where + &'a Self: First, +{ + const CONST: usize = <&Self>::CONST; +} + +trait Third: First +where + [u8; Self::CONST]: +{ + const VAL: [u8; Self::CONST] = [0; Self::CONST]; +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-93775.rs b/tests/ui/associated-consts/issue-93775.rs new file mode 100644 index 000000000..7a007b732 --- /dev/null +++ b/tests/ui/associated-consts/issue-93775.rs @@ -0,0 +1,29 @@ +// build-pass +// ignore-tidy-linelength + +// Regression for #93775, needs build-pass to test it. + +#![recursion_limit = "1000"] + +use std::marker::PhantomData; + +struct Z; +struct S(PhantomData); + +type Nested = S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; + +trait AsNum { + const NUM: u32; +} + +impl AsNum for Z { + const NUM: u32 = 0; +} + +impl AsNum for S { + const NUM: u32 = T::NUM + 1; +} + +fn main() { + let _ = Nested::NUM; +} diff --git a/tests/ui/associated-consts/issue-93835.rs b/tests/ui/associated-consts/issue-93835.rs new file mode 100644 index 000000000..b2a437fcb --- /dev/null +++ b/tests/ui/associated-consts/issue-93835.rs @@ -0,0 +1,12 @@ +#![feature(type_ascription)] + +fn e() { + type_ascribe!(p, a>); + //~^ ERROR cannot find type `a` in this scope + //~| ERROR cannot find value + //~| ERROR associated const equality + //~| ERROR cannot find trait `p` in this scope + //~| ERROR associated type bounds +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-93835.stderr b/tests/ui/associated-consts/issue-93835.stderr new file mode 100644 index 000000000..be0573a13 --- /dev/null +++ b/tests/ui/associated-consts/issue-93835.stderr @@ -0,0 +1,40 @@ +error[E0425]: cannot find value `p` in this scope + --> $DIR/issue-93835.rs:4:19 + | +LL | type_ascribe!(p, a>); + | ^ not found in this scope + +error[E0412]: cannot find type `a` in this scope + --> $DIR/issue-93835.rs:4:22 + | +LL | type_ascribe!(p, a>); + | ^ not found in this scope + +error[E0405]: cannot find trait `p` in this scope + --> $DIR/issue-93835.rs:4:26 + | +LL | type_ascribe!(p, a>); + | ^ not found in this scope + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 + | +LL | type_ascribe!(p, a>); + | ^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/issue-93835.rs:4:24 + | +LL | type_ascribe!(p, a>); + | ^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0405, E0412, E0425, E0658. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/associated-consts/mismatched_impl_ty_1.rs b/tests/ui/associated-consts/mismatched_impl_ty_1.rs new file mode 100644 index 000000000..4dc6c2e47 --- /dev/null +++ b/tests/ui/associated-consts/mismatched_impl_ty_1.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MyTrait { + type ArrayType; + const SIZE: usize; + const ARRAY: Self::ArrayType; +} +impl MyTrait for () { + type ArrayType = [u8; Self::SIZE]; + const SIZE: usize = 4; + const ARRAY: [u8; Self::SIZE] = [1, 2, 3, 4]; +} + +fn main() { + let _ = <() as MyTrait>::ARRAY; +} diff --git a/tests/ui/associated-consts/mismatched_impl_ty_2.rs b/tests/ui/associated-consts/mismatched_impl_ty_2.rs new file mode 100644 index 000000000..539becfdc --- /dev/null +++ b/tests/ui/associated-consts/mismatched_impl_ty_2.rs @@ -0,0 +1,11 @@ +// run-pass +trait Trait { + const ASSOC: fn(&'static u32); +} +impl Trait for () { + const ASSOC: for<'a> fn(&'a u32) = |_| (); +} + +fn main() { + let _ = <() as Trait>::ASSOC; +} diff --git a/tests/ui/associated-consts/mismatched_impl_ty_3.rs b/tests/ui/associated-consts/mismatched_impl_ty_3.rs new file mode 100644 index 000000000..17bcc8fe5 --- /dev/null +++ b/tests/ui/associated-consts/mismatched_impl_ty_3.rs @@ -0,0 +1,11 @@ +// run-pass +trait Trait { + const ASSOC: for<'a, 'b> fn(&'a u32, &'b u32); +} +impl Trait for () { + const ASSOC: for<'a> fn(&'a u32, &'a u32) = |_, _| (); +} + +fn main() { + let _ = <() as Trait>::ASSOC; +} diff --git a/tests/ui/associated-consts/shadowed-const.rs b/tests/ui/associated-consts/shadowed-const.rs new file mode 100644 index 000000000..cfdb391d3 --- /dev/null +++ b/tests/ui/associated-consts/shadowed-const.rs @@ -0,0 +1,23 @@ +// Checking that none of these ICE, which was introduced in +// https://github.com/rust-lang/rust/issues/93553 +trait Foo { + type Bar; +} + +trait Baz: Foo { + const Bar: Self::Bar; +} + +trait Baz2: Foo { + const Bar: u32; + + fn foo() -> Self::Bar; +} + +trait Baz3 { + const BAR: usize; + const QUX: Self::BAR; + //~^ ERROR found associated const +} + +fn main() {} diff --git a/tests/ui/associated-consts/shadowed-const.stderr b/tests/ui/associated-consts/shadowed-const.stderr new file mode 100644 index 000000000..fe21d2aec --- /dev/null +++ b/tests/ui/associated-consts/shadowed-const.stderr @@ -0,0 +1,8 @@ +error: found associated const `BAR` when type was expected + --> $DIR/shadowed-const.rs:19:14 + | +LL | const QUX: Self::BAR; + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-inherent-types/assoc-inherent-no-body.rs b/tests/ui/associated-inherent-types/assoc-inherent-no-body.rs new file mode 100644 index 000000000..71f65b92e --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-no-body.rs @@ -0,0 +1,10 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + type Baz; //~ ERROR associated type in `impl` without body +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr b/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr new file mode 100644 index 000000000..387a5658d --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-no-body.stderr @@ -0,0 +1,10 @@ +error: associated type in `impl` without body + --> $DIR/assoc-inherent-no-body.rs:7:5 + | +LL | type Baz; + | ^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: aborting due to previous error + diff --git a/tests/ui/associated-inherent-types/assoc-inherent-private.rs b/tests/ui/associated-inherent-types/assoc-inherent-private.rs new file mode 100644 index 000000000..531581954 --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-private.rs @@ -0,0 +1,23 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +mod m { + pub struct T; + impl T { + type P = (); + } +} +type U = m::T::P; //~ ERROR associated type `P` is private + +mod n { + pub mod n { + pub struct T; + impl T { + pub(super) type P = bool; + } + } + type U = n::T::P; +} +type V = n::n::T::P; //~ ERROR associated type `P` is private + +fn main() {} diff --git a/tests/ui/associated-inherent-types/assoc-inherent-private.stderr b/tests/ui/associated-inherent-types/assoc-inherent-private.stderr new file mode 100644 index 000000000..d67b45dae --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-private.stderr @@ -0,0 +1,21 @@ +error[E0624]: associated type `P` is private + --> $DIR/assoc-inherent-private.rs:10:10 + | +LL | type P = (); + | ------ associated type defined here +... +LL | type U = m::T::P; + | ^^^^^^^ private associated type + +error[E0624]: associated type `P` is private + --> $DIR/assoc-inherent-private.rs:21:10 + | +LL | pub(super) type P = bool; + | ----------------- associated type defined here +... +LL | type V = n::n::T::P; + | ^^^^^^^^^^ private associated type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs b/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs new file mode 100644 index 000000000..34b4e47bf --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs @@ -0,0 +1,6 @@ +// aux-crate:aux=assoc-inherent-unstable.rs +// edition: 2021 + +type Data = aux::Owner::Data; //~ ERROR use of unstable library feature 'data' + +fn main() {} diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr new file mode 100644 index 000000000..c0be8bfd7 --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'data' + --> $DIR/assoc-inherent-unstable.rs:4:13 + | +LL | type Data = aux::Owner::Data; + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(data)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-inherent-types/assoc-inherent-use.rs b/tests/ui/associated-inherent-types/assoc-inherent-use.rs new file mode 100644 index 000000000..7ae425e2a --- /dev/null +++ b/tests/ui/associated-inherent-types/assoc-inherent-use.rs @@ -0,0 +1,14 @@ +// check-pass +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + type Bar = isize; +} + +fn main() { + let x: Foo::Bar; + x = 0isize; +} diff --git a/tests/ui/associated-inherent-types/auxiliary/assoc-inherent-unstable.rs b/tests/ui/associated-inherent-types/auxiliary/assoc-inherent-unstable.rs new file mode 100644 index 000000000..6b71ffc97 --- /dev/null +++ b/tests/ui/associated-inherent-types/auxiliary/assoc-inherent-unstable.rs @@ -0,0 +1,11 @@ +#![feature(staged_api)] +#![feature(inherent_associated_types)] +#![stable(feature = "main", since = "1.0.0")] + +#[stable(feature = "main", since = "1.0.0")] +pub struct Owner; + +impl Owner { + #[unstable(feature = "data", issue = "none")] + pub type Data = (); +} diff --git a/tests/ui/associated-inherent-types/issue-104260.rs b/tests/ui/associated-inherent-types/issue-104260.rs new file mode 100644 index 000000000..a73cd1775 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-104260.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + type Bar = u8; +} + +fn main() { + let a: Foo::Bar<()>; +} diff --git a/tests/ui/associated-inherent-types/normalize-projection-0.rs b/tests/ui/associated-inherent-types/normalize-projection-0.rs new file mode 100644 index 000000000..50763ecdd --- /dev/null +++ b/tests/ui/associated-inherent-types/normalize-projection-0.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S(T); + +impl S { + type P = ::P; +} + +trait O { + type P; +} + +impl O for i32 { + type P = String; +} + +fn main() { + let _: S::P = String::new(); +} diff --git a/tests/ui/associated-inherent-types/normalize-projection-1.rs b/tests/ui/associated-inherent-types/normalize-projection-1.rs new file mode 100644 index 000000000..2f7b2551a --- /dev/null +++ b/tests/ui/associated-inherent-types/normalize-projection-1.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S; + +impl S { + type P = ::P; +} + +trait O { + type P; +} + +impl O for i32 { + type P = String; +} + +fn main() { + let _: S::P = String::new(); +} diff --git a/tests/ui/associated-inherent-types/struct-generics.rs b/tests/ui/associated-inherent-types/struct-generics.rs new file mode 100644 index 000000000..8952b3791 --- /dev/null +++ b/tests/ui/associated-inherent-types/struct-generics.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S(T); + +impl S { + type P = T; +} + +fn main() { + type A = S<()>::P; + let _: A = (); +} diff --git a/tests/ui/associated-inherent-types/style.rs b/tests/ui/associated-inherent-types/style.rs new file mode 100644 index 000000000..8775bd19e --- /dev/null +++ b/tests/ui/associated-inherent-types/style.rs @@ -0,0 +1,12 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features, dead_code)] +#![deny(non_camel_case_types)] + +struct S; + +impl S { + type typ = (); + //~^ ERROR associated type `typ` should have an upper camel case name +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/style.stderr b/tests/ui/associated-inherent-types/style.stderr new file mode 100644 index 000000000..f83061f8c --- /dev/null +++ b/tests/ui/associated-inherent-types/style.stderr @@ -0,0 +1,14 @@ +error: associated type `typ` should have an upper camel case name + --> $DIR/style.rs:8:10 + | +LL | type typ = (); + | ^^^ help: convert the identifier to upper camel case: `Typ` + | +note: the lint level is defined here + --> $DIR/style.rs:3:9 + | +LL | #![deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed new file mode 100644 index 000000000..23f715200 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed @@ -0,0 +1,14 @@ +// run-rustfix +trait Trait {} + +trait Assoc { + type Ty; +} + +impl Assoc for dyn Trait { + type Ty = i32; +} + +fn main() { + let _x: as Assoc>::Ty; //~ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs new file mode 100644 index 000000000..9c26e339a --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs @@ -0,0 +1,14 @@ +// run-rustfix +trait Trait {} + +trait Assoc { + type Ty; +} + +impl Assoc for dyn Trait { + type Ty = i32; +} + +fn main() { + let _x: >::Ty; //~ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr new file mode 100644 index 000000000..97088b79f --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-associated-type-with-generics.rs:13:13 + | +LL | let _x: >::Ty; + | ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: ` as Assoc>::Ty` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-item/associated-item-duplicate-bounds.rs b/tests/ui/associated-item/associated-item-duplicate-bounds.rs new file mode 100644 index 000000000..242a02353 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-bounds.rs @@ -0,0 +1,11 @@ +trait Adapter { + const LINKS: usize; +} + +struct Foo { + adapter: A, + links: [u32; A::LINKS], // Shouldn't suggest bounds already there. + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr new file mode 100644 index 000000000..f2e4ca524 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/associated-item-duplicate-bounds.rs:7:18 + | +LL | links: [u32; A::LINKS], // Shouldn't suggest bounds already there. + | ^^^^^^^^ cannot perform const operation using `A` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/associated-item/associated-item-duplicate-names-2.rs b/tests/ui/associated-item/associated-item-duplicate-names-2.rs new file mode 100644 index 000000000..550c7ae39 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-names-2.rs @@ -0,0 +1,8 @@ +struct Foo; + +impl Foo { + const bar: bool = true; + fn bar() {} //~ ERROR duplicate definitions +} + +fn main() {} diff --git a/tests/ui/associated-item/associated-item-duplicate-names-2.stderr b/tests/ui/associated-item/associated-item-duplicate-names-2.stderr new file mode 100644 index 000000000..0b96a6bd7 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-names-2.stderr @@ -0,0 +1,11 @@ +error[E0592]: duplicate definitions with name `bar` + --> $DIR/associated-item-duplicate-names-2.rs:5:5 + | +LL | const bar: bool = true; + | --------------- other definition for `bar` +LL | fn bar() {} + | ^^^^^^^^ duplicate definitions for `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.rs b/tests/ui/associated-item/associated-item-duplicate-names-3.rs new file mode 100644 index 000000000..3a70a2f94 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.rs @@ -0,0 +1,20 @@ +// +// Before the introduction of the "duplicate associated type" error, the +// program below used to result in the "ambiguous associated type" error E0223, +// which is unexpected. + +trait Foo { + type Bar; +} + +struct Baz; + +impl Foo for Baz { + type Bar = i16; + type Bar = u16; //~ ERROR duplicate definitions +} + +fn main() { + let x: Baz::Bar = 5; + //~^ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr new file mode 100644 index 000000000..d0c170620 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -0,0 +1,21 @@ +error[E0201]: duplicate definitions with name `Bar`: + --> $DIR/associated-item-duplicate-names-3.rs:14:5 + | +LL | type Bar; + | --------- item in trait +... +LL | type Bar = i16; + | --------------- previous definition here +LL | type Bar = u16; + | ^^^^^^^^^^^^^^^ duplicate definition + +error[E0223]: ambiguous associated type + --> $DIR/associated-item-duplicate-names-3.rs:18:12 + | +LL | let x: Baz::Bar = 5; + | ^^^^^^^^ help: use the fully-qualified path: `::Bar` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0201, E0223. +For more information about an error, try `rustc --explain E0201`. diff --git a/tests/ui/associated-item/associated-item-duplicate-names.rs b/tests/ui/associated-item/associated-item-duplicate-names.rs new file mode 100644 index 000000000..6677fad68 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-names.rs @@ -0,0 +1,19 @@ +// Test for issue #23969 + + +trait Foo { + type Ty; + const BAR: u32; +} + +impl Foo for () { + type Ty = (); + type Ty = usize; //~ ERROR duplicate definitions + const BAR: u32 = 7; + const BAR: u32 = 8; //~ ERROR duplicate definitions +} + +fn main() { + let _: <() as Foo>::Ty = (); + let _: u32 = <() as Foo>::BAR; +} diff --git a/tests/ui/associated-item/associated-item-duplicate-names.stderr b/tests/ui/associated-item/associated-item-duplicate-names.stderr new file mode 100644 index 000000000..f89ea6e57 --- /dev/null +++ b/tests/ui/associated-item/associated-item-duplicate-names.stderr @@ -0,0 +1,25 @@ +error[E0201]: duplicate definitions with name `Ty`: + --> $DIR/associated-item-duplicate-names.rs:11:5 + | +LL | type Ty; + | -------- item in trait +... +LL | type Ty = (); + | ------------- previous definition here +LL | type Ty = usize; + | ^^^^^^^^^^^^^^^^ duplicate definition + +error[E0201]: duplicate definitions with name `BAR`: + --> $DIR/associated-item-duplicate-names.rs:13:5 + | +LL | const BAR: u32; + | --------------- item in trait +... +LL | const BAR: u32 = 7; + | ------------------- previous definition here +LL | const BAR: u32 = 8; + | ^^^^^^^^^^^^^^^^^^^ duplicate definition + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/associated-item/associated-item-enum.rs b/tests/ui/associated-item/associated-item-enum.rs new file mode 100644 index 000000000..30ba25815 --- /dev/null +++ b/tests/ui/associated-item/associated-item-enum.rs @@ -0,0 +1,20 @@ +enum Enum { Variant } + +impl Enum { + const MISSPELLABLE: i32 = 0; + fn misspellable() {} +} + +trait Trait { + fn misspellable_trait() {} +} + +impl Trait for Enum { + fn misspellable_trait() {} +} + +fn main() { + Enum::mispellable(); //~ ERROR no variant or associated item + Enum::mispellable_trait(); //~ ERROR no variant or associated item + Enum::MISPELLABLE; //~ ERROR no variant or associated item +} diff --git a/tests/ui/associated-item/associated-item-enum.stderr b/tests/ui/associated-item/associated-item-enum.stderr new file mode 100644 index 000000000..ebf3c5499 --- /dev/null +++ b/tests/ui/associated-item/associated-item-enum.stderr @@ -0,0 +1,39 @@ +error[E0599]: no variant or associated item named `mispellable` found for enum `Enum` in the current scope + --> $DIR/associated-item-enum.rs:17:11 + | +LL | enum Enum { Variant } + | --------- variant or associated item `mispellable` not found for this enum +... +LL | Enum::mispellable(); + | ^^^^^^^^^^^ + | | + | variant or associated item not found in `Enum` + | help: there is an associated function with a similar name: `misspellable` + +error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope + --> $DIR/associated-item-enum.rs:18:11 + | +LL | enum Enum { Variant } + | --------- variant or associated item `mispellable_trait` not found for this enum +... +LL | Enum::mispellable_trait(); + | ^^^^^^^^^^^^^^^^^ + | | + | variant or associated item not found in `Enum` + | help: there is an associated function with a similar name: `misspellable` + +error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `Enum` in the current scope + --> $DIR/associated-item-enum.rs:19:11 + | +LL | enum Enum { Variant } + | --------- variant or associated item `MISPELLABLE` not found for this enum +... +LL | Enum::MISPELLABLE; + | ^^^^^^^^^^^ + | | + | variant or associated item not found in `Enum` + | help: there is an associated constant with a similar name: `MISSPELLABLE` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/associated-item/associated-item-two-bounds.rs b/tests/ui/associated-item/associated-item-two-bounds.rs new file mode 100644 index 000000000..25b0d5a56 --- /dev/null +++ b/tests/ui/associated-item/associated-item-two-bounds.rs @@ -0,0 +1,16 @@ +// This test is a regression test for #34792 + +// check-pass + +pub struct A; +pub struct B; + +pub trait Foo { + type T: PartialEq + PartialEq; +} + +pub fn generic(t: F::T, a: A, b: B) -> bool { + t == a && t == b +} + +pub fn main() {} diff --git a/tests/ui/associated-item/impl-duplicate-methods.rs b/tests/ui/associated-item/impl-duplicate-methods.rs new file mode 100644 index 000000000..328d54d5a --- /dev/null +++ b/tests/ui/associated-item/impl-duplicate-methods.rs @@ -0,0 +1,9 @@ +struct Foo; + +impl Foo { + fn orange(&self) {} + fn orange(&self) {} + //~^ ERROR duplicate definitions with name `orange` [E0592] +} + +fn main() {} diff --git a/tests/ui/associated-item/impl-duplicate-methods.stderr b/tests/ui/associated-item/impl-duplicate-methods.stderr new file mode 100644 index 000000000..6f753845a --- /dev/null +++ b/tests/ui/associated-item/impl-duplicate-methods.stderr @@ -0,0 +1,11 @@ +error[E0592]: duplicate definitions with name `orange` + --> $DIR/impl-duplicate-methods.rs:5:5 + | +LL | fn orange(&self) {} + | ---------------- other definition for `orange` +LL | fn orange(&self) {} + | ^^^^^^^^^^^^^^^^ duplicate definitions for `orange` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/associated-item/issue-105449.rs b/tests/ui/associated-item/issue-105449.rs new file mode 100644 index 000000000..dd14e05fd --- /dev/null +++ b/tests/ui/associated-item/issue-105449.rs @@ -0,0 +1,59 @@ +// check-pass +// compile-flags: -C debug_assertions=yes -Zunstable-options + +#[allow(dead_code)] +fn problematic_function() +where + DefaultAlloc: FinAllok, +{ + let e = Edge2dElement; + let _ = Into::::into(e.map_reference_coords()); +} +impl Allocator for DefaultAlloc { + type Buffer = MStorage; +} +impl Allocator for DefaultAlloc { + type Buffer = MStorage; +} +impl From> for Point +where + DefaultAlloc: Allocator, +{ + fn from(_: VectorN) -> Self { + unimplemented!() + } +} +impl FinAllok for DefaultAlloc +where + DefaultAlloc: Allocator, + DefaultAlloc: Allocator +{ +} +impl FiniteElement for Edge2dElement { + fn map_reference_coords(&self) -> VectorN { + unimplemented!() + } +} +type VectorN = (N, R, >::Buffer); +struct DefaultAlloc; +struct R0; +struct R1; +struct MStorage; +struct Point; +struct Edge2dElement; +struct Ure; +trait Allocator { + type Buffer; +} +trait FinAllok: + Allocator + + Allocator + +{ +} +trait FiniteElement +where + DefaultAlloc: FinAllok, +{ + fn map_reference_coords(&self) -> VectorN; +} +fn main() {} diff --git a/tests/ui/associated-item/issue-48027.rs b/tests/ui/associated-item/issue-48027.rs new file mode 100644 index 000000000..d2b51184c --- /dev/null +++ b/tests/ui/associated-item/issue-48027.rs @@ -0,0 +1,8 @@ +trait Bar { + const X: usize; + fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: E0790 +} + +impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object + +fn main() {} diff --git a/tests/ui/associated-item/issue-48027.stderr b/tests/ui/associated-item/issue-48027.stderr new file mode 100644 index 000000000..45ea41933 --- /dev/null +++ b/tests/ui/associated-item/issue-48027.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-48027.rs:6:6 + | +LL | impl dyn Bar {} + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-48027.rs:2:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-48027.rs:3:32 + | +LL | const X: usize; + | --------------- `Bar::X` defined here +LL | fn return_n(&self) -> [u8; Bar::X]; + | ^^^^^^ cannot refer to the associated constant of trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0790. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-item/issue-87638.fixed b/tests/ui/associated-item/issue-87638.fixed new file mode 100644 index 000000000..b68977768 --- /dev/null +++ b/tests/ui/associated-item/issue-87638.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +trait Trait { + const FOO: usize; + + type Target; +} + +struct S; + +impl Trait for S { + const FOO: usize = 0; + type Target = (); +} + +fn main() { + let _: ::Target; //~ ERROR cannot find associated type `Output` in trait `Trait` + //~^ HELP maybe you meant this associated type + + let _ = ::FOO; //~ ERROR cannot find method or associated constant `BAR` in trait `Trait` + //~^ HELP maybe you meant this associated constant +} diff --git a/tests/ui/associated-item/issue-87638.rs b/tests/ui/associated-item/issue-87638.rs new file mode 100644 index 000000000..5a60b20fd --- /dev/null +++ b/tests/ui/associated-item/issue-87638.rs @@ -0,0 +1,22 @@ +// run-rustfix + +trait Trait { + const FOO: usize; + + type Target; +} + +struct S; + +impl Trait for S { + const FOO: usize = 0; + type Target = (); +} + +fn main() { + let _: ::Output; //~ ERROR cannot find associated type `Output` in trait `Trait` + //~^ HELP maybe you meant this associated type + + let _ = ::BAR; //~ ERROR cannot find method or associated constant `BAR` in trait `Trait` + //~^ HELP maybe you meant this associated constant +} diff --git a/tests/ui/associated-item/issue-87638.stderr b/tests/ui/associated-item/issue-87638.stderr new file mode 100644 index 000000000..cf6083444 --- /dev/null +++ b/tests/ui/associated-item/issue-87638.stderr @@ -0,0 +1,27 @@ +error[E0576]: cannot find associated type `Output` in trait `Trait` + --> $DIR/issue-87638.rs:17:26 + | +LL | type Target; + | ------------ associated type `Target` defined here +... +LL | let _: ::Output; + | ^^^^^^ + | | + | not found in `Trait` + | help: maybe you meant this associated type: `Target` + +error[E0576]: cannot find method or associated constant `BAR` in trait `Trait` + --> $DIR/issue-87638.rs:20:27 + | +LL | const FOO: usize; + | ----------------- associated constant `FOO` defined here +... +LL | let _ = ::BAR; + | ^^^ + | | + | not found in `Trait` + | help: maybe you meant this associated constant: `FOO` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/associated-path-shl.rs b/tests/ui/associated-path-shl.rs new file mode 100644 index 000000000..20a6fd83f --- /dev/null +++ b/tests/ui/associated-path-shl.rs @@ -0,0 +1,9 @@ +// Check that associated paths starting with `<<` are successfully parsed. + +fn main() { + let _: <::B>::C; //~ ERROR cannot find type `A` in this scope + let _ = <::B>::C; //~ ERROR cannot find type `A` in this scope + let <::B>::C; //~ ERROR cannot find type `A` in this scope + let 0 ..= <::B>::C; //~ ERROR cannot find type `A` in this scope + <::B>::C; //~ ERROR cannot find type `A` in this scope +} diff --git a/tests/ui/associated-path-shl.stderr b/tests/ui/associated-path-shl.stderr new file mode 100644 index 000000000..71ee93f48 --- /dev/null +++ b/tests/ui/associated-path-shl.stderr @@ -0,0 +1,33 @@ +error[E0412]: cannot find type `A` in this scope + --> $DIR/associated-path-shl.rs:4:14 + | +LL | let _: <::B>::C; + | ^ not found in this scope + +error[E0412]: cannot find type `A` in this scope + --> $DIR/associated-path-shl.rs:5:15 + | +LL | let _ = <::B>::C; + | ^ not found in this scope + +error[E0412]: cannot find type `A` in this scope + --> $DIR/associated-path-shl.rs:6:11 + | +LL | let <::B>::C; + | ^ not found in this scope + +error[E0412]: cannot find type `A` in this scope + --> $DIR/associated-path-shl.rs:7:17 + | +LL | let 0 ..= <::B>::C; + | ^ not found in this scope + +error[E0412]: cannot find type `A` in this scope + --> $DIR/associated-path-shl.rs:8:7 + | +LL | <::B>::C; + | ^ not found in this scope + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/associated-type-bounds/ambiguous-associated-type.rs b/tests/ui/associated-type-bounds/ambiguous-associated-type.rs new file mode 100644 index 000000000..9c47a003d --- /dev/null +++ b/tests/ui/associated-type-bounds/ambiguous-associated-type.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(associated_type_bounds)] + +pub struct Flatten +where + I: Iterator, +{ + inner: ::IntoIter, +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/ambiguous-associated-type2.rs b/tests/ui/associated-type-bounds/ambiguous-associated-type2.rs new file mode 100644 index 000000000..48de59334 --- /dev/null +++ b/tests/ui/associated-type-bounds/ambiguous-associated-type2.rs @@ -0,0 +1,10 @@ +trait Foo { + type Item; +} +trait Bar { + type Item; +} +trait Baz: Foo + Bar {} +//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391] + +fn main() {} diff --git a/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr new file mode 100644 index 000000000..4162cdaa8 --- /dev/null +++ b/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item` + --> $DIR/ambiguous-associated-type2.rs:7:1 + | +LL | trait Baz: Foo + Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again +note: cycle used when computing the super traits of `Baz` + --> $DIR/ambiguous-associated-type2.rs:7:1 + | +LL | trait Baz: Foo + Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs b/tests/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs new file mode 100644 index 000000000..49f111407 --- /dev/null +++ b/tests/ui/associated-type-bounds/assoc-type-bound-through-where-clause.rs @@ -0,0 +1,16 @@ +// Check that `where Self::Output: Copy` is turned into a bound on `Op::Output`. + +//check-pass + +trait Op +where + Self::Output: Copy, +{ + type Output; +} + +fn duplicate(x: T::Output) -> (T::Output, T::Output) { + (x, x) +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs new file mode 100644 index 000000000..4c36289f4 --- /dev/null +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -0,0 +1,36 @@ +// This test documents that `type Out = Box>;` +// is allowed and will correctly reject an opaque `type Out` which +// does not satisfy the bound `::Assoc: Copy`. +// +// FIXME(rust-lang/lang): I think this behavior is logical if we want to allow +// `dyn Trait` but we should decide if we want that. // Centril +// +// Additionally, as reported in https://github.com/rust-lang/rust/issues/63594, +// we check that the spans for the error message are sane here. + +#![feature(associated_type_bounds)] + +fn main() {} + +trait Bar { + type Assoc; +} + +trait Thing { + type Out; + fn func() -> Self::Out; +} + +struct AssocNoCopy; +impl Bar for AssocNoCopy { + type Assoc = String; +} + +impl Thing for AssocNoCopy { + type Out = Box>; + + fn func() -> Self::Out { + //~^ ERROR the trait bound `String: Copy` is not satisfied + Box::new(AssocNoCopy) + } +} diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr new file mode 100644 index 000000000..a32ab4531 --- /dev/null +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18 + | +LL | fn func() -> Self::Out { + | ^^^^^^^^^ the trait `Copy` is not implemented for `String` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/associated-item-through-where-clause.rs b/tests/ui/associated-type-bounds/associated-item-through-where-clause.rs new file mode 100644 index 000000000..3eb50ab55 --- /dev/null +++ b/tests/ui/associated-type-bounds/associated-item-through-where-clause.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Foo { + type Item; +} + +trait Bar +where + Self: Foo, +{ +} + +#[allow(dead_code)] +fn foo(_m: M) +where + M: Bar, + M::Item: Send, +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/auxiliary/fn-aux.rs b/tests/ui/associated-type-bounds/auxiliary/fn-aux.rs new file mode 100644 index 000000000..0ea23ad1d --- /dev/null +++ b/tests/ui/associated-type-bounds/auxiliary/fn-aux.rs @@ -0,0 +1,177 @@ +// Traits: + +pub trait Alpha { + fn alpha(self) -> usize; +} + +pub trait Beta { + type Gamma; + fn gamma(self) -> Self::Gamma; +} + +pub trait Delta { + fn delta(self) -> usize; +} + +pub trait Epsilon<'a> { + type Zeta; + fn zeta(&'a self) -> Self::Zeta; + + fn epsilon(&'a self) -> usize; +} + +pub trait Eta { + fn eta(self) -> usize; +} + +// Assertions: + +pub fn assert_alpha(x: T) -> usize { x.alpha() } +pub fn assert_static(_: T) -> usize { 24 } +pub fn assert_delta(x: T) -> usize { x.delta() } +pub fn assert_epsilon_specific<'a, T: 'a + Epsilon<'a>>(x: &'a T) -> usize { x.epsilon() } +pub fn assert_epsilon_forall Epsilon<'a>>() {} +pub fn assert_forall_epsilon_zeta_satisfies_eta(x: T) -> usize +where + T: for<'a> Epsilon<'a>, + for<'a> >::Zeta: Eta, +{ + x.epsilon() + x.zeta().eta() +} + +// Implementations and types: + +#[derive(Copy, Clone)] +pub struct BetaType; + +#[derive(Copy, Clone)] +pub struct GammaType; + +#[derive(Copy, Clone)] +pub struct ZetaType; + +impl Beta for BetaType { + type Gamma = GammaType; + fn gamma(self) -> Self::Gamma { GammaType } +} + +impl<'a> Beta for &'a BetaType { + type Gamma = GammaType; + fn gamma(self) -> Self::Gamma { GammaType } +} + +impl Beta for GammaType { + type Gamma = Self; + fn gamma(self) -> Self::Gamma { self } +} + +impl Alpha for GammaType { + fn alpha(self) -> usize { 42 } +} + +impl Delta for GammaType { + fn delta(self) -> usize { 1337 } +} + +impl<'a> Epsilon<'a> for GammaType { + type Zeta = ZetaType; + fn zeta(&'a self) -> Self::Zeta { ZetaType } + + fn epsilon(&'a self) -> usize { 7331 } +} + +impl Eta for ZetaType { + fn eta(self) -> usize { 7 } +} + +// Desugared forms to check against: + +pub fn desugared_bound(beta: B) -> usize +where + B: Beta, + B::Gamma: Alpha +{ + let gamma: B::Gamma = beta.gamma(); + assert_alpha::(gamma) +} + +pub fn desugared_bound_region(beta: B) -> usize +where + B: Beta, + B::Gamma: 'static, +{ + assert_static::(beta.gamma()) +} + +pub fn desugared_bound_multi(beta: B) -> usize +where + B: Copy + Beta, + B::Gamma: Alpha + 'static + Delta, +{ + assert_alpha::(beta.gamma()) + + assert_static::(beta.gamma()) + + assert_delta::(beta.gamma()) +} + +pub fn desugared_bound_region_specific<'a, B>(gamma: &'a B::Gamma) -> usize +where + B: Beta, + B::Gamma: 'a + Epsilon<'a>, +{ + assert_epsilon_specific::(gamma) +} + +pub fn desugared_bound_region_forall(beta: B) -> usize +where + B: Beta, + B::Gamma: Copy + for<'a> Epsilon<'a>, +{ + assert_epsilon_forall::(); + let g1: B::Gamma = beta.gamma(); + let g2: B::Gamma = g1; + assert_epsilon_specific::(&g1) + + assert_epsilon_specific::(&g2) +} + +pub fn desugared_bound_region_forall2(beta: B) -> usize +where + B: Beta, + B::Gamma: Copy + for<'a> Epsilon<'a>, + for<'a> >::Zeta: Eta, +{ + let gamma = beta.gamma(); + assert_forall_epsilon_zeta_satisfies_eta::(gamma) +} + +pub fn desugared_contraint_region_forall(beta: B) -> usize +where + for<'a> &'a B: Beta, + for<'a> <&'a B as Beta>::Gamma: Alpha, +{ + let g1 = beta.gamma(); + let g2 = beta.gamma(); + assert_alpha(g1) + assert_alpha(g2) +} + +pub fn desugared_bound_nested(beta: B) -> usize +where + B: Beta, + B::Gamma: Copy + Alpha + Beta, + ::Gamma: Delta, +{ + let go = beta.gamma(); + let gi = go.gamma(); + go.alpha() + gi.delta() +} + +pub fn desugared() { + let beta = BetaType; + let gamma = beta.gamma(); + + assert_eq!(42, desugared_bound(beta)); + assert_eq!(24, desugared_bound_region(beta)); + assert_eq!(42 + 24 + 1337, desugared_bound_multi(beta)); + assert_eq!(7331, desugared_bound_region_specific::(&gamma)); + assert_eq!(7331 * 2, desugared_bound_region_forall(beta)); + assert_eq!(42 + 1337, desugared_bound_nested(beta)); +} diff --git a/tests/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs b/tests/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs new file mode 100644 index 000000000..85d6c5aaf --- /dev/null +++ b/tests/ui/associated-type-bounds/auxiliary/fn-dyn-aux.rs @@ -0,0 +1,182 @@ +// Traits: + +pub trait Alpha { + fn alpha(self) -> usize; +} + +pub trait Beta { + type Gamma; + fn gamma(&self) -> Self::Gamma; +} + +pub trait Delta { + fn delta(self) -> usize; +} + +pub trait Epsilon<'a> { + type Zeta; + fn zeta(&'a self) -> Self::Zeta; + + fn epsilon(&'a self) -> usize; +} + +pub trait Eta { + fn eta(self) -> usize; +} + +// Assertions: + +pub fn assert_alpha(x: T) -> usize { x.alpha() } +pub fn assert_static(_: T) -> usize { 24 } +pub fn assert_delta(x: T) -> usize { x.delta() } +pub fn assert_epsilon_specific<'a, T: 'a + Epsilon<'a>>(x: &'a T) -> usize { x.epsilon() } +pub fn assert_epsilon_forall Epsilon<'a>>() {} +pub fn assert_forall_epsilon_zeta_satisfies_eta(x: T) -> usize +where + T: for<'a> Epsilon<'a>, + for<'a> >::Zeta: Eta, +{ + x.epsilon() + x.zeta().eta() +} + +// Implementations and types: + +#[derive(Copy, Clone)] +pub struct BetaType; + +#[derive(Copy, Clone)] +pub struct GammaType; + +#[derive(Copy, Clone)] +pub struct ZetaType; + +impl Beta for &(dyn Beta + Send) { + type Gamma = T; + fn gamma(&self) -> Self::Gamma { (*self).gamma() } +} + +impl Beta for BetaType { + type Gamma = GammaType; + fn gamma(&self) -> Self::Gamma { GammaType } +} + +impl<'a> Beta for &'a BetaType { + type Gamma = GammaType; + fn gamma(&self) -> Self::Gamma { GammaType } +} + +impl Beta for GammaType { + type Gamma = Self; + fn gamma(&self) -> Self::Gamma { Self } +} + +impl Alpha for GammaType { + fn alpha(self) -> usize { 42 } +} + +impl Delta for GammaType { + fn delta(self) -> usize { 1337 } +} + +impl<'a> Epsilon<'a> for GammaType { + type Zeta = ZetaType; + fn zeta(&'a self) -> Self::Zeta { ZetaType } + + fn epsilon(&'a self) -> usize { 7331 } +} + +impl Eta for ZetaType { + fn eta(self) -> usize { 7 } +} + +// Desugared forms to check against: + +pub fn desugared_bound(beta: &B) -> usize +where + B: Beta, + B::Gamma: Alpha +{ + let gamma: B::Gamma = beta.gamma(); + assert_alpha::(gamma) +} + +pub fn desugared_bound_region(beta: &B) -> usize +where + B: Beta, + B::Gamma: 'static, +{ + assert_static::(beta.gamma()) +} + +pub fn desugared_bound_multi(beta: B) -> usize +where + B: Copy + Beta, + B::Gamma: Alpha + 'static + Delta, +{ + assert_alpha::(beta.gamma()) + + assert_static::(beta.gamma()) + + assert_delta::(beta.gamma()) +} + +pub fn desugared_bound_region_specific<'a, B: ?Sized>(gamma: &'a B::Gamma) -> usize +where + B: Beta, + B::Gamma: 'a + Epsilon<'a>, +{ + assert_epsilon_specific::(gamma) +} + +pub fn desugared_bound_region_forall(beta: &B) -> usize +where + B: Beta, + B::Gamma: Copy + for<'a> Epsilon<'a>, +{ + assert_epsilon_forall::(); + let g1: B::Gamma = beta.gamma(); + let g2: B::Gamma = g1; + assert_epsilon_specific::(&g1) + + assert_epsilon_specific::(&g2) +} + +pub fn desugared_bound_region_forall2(beta: &B) -> usize +where + B: Beta, + B::Gamma: Copy + for<'a> Epsilon<'a>, + for<'a> >::Zeta: Eta, +{ + let gamma = beta.gamma(); + assert_forall_epsilon_zeta_satisfies_eta::(gamma) +} + +pub fn desugared_contraint_region_forall(beta: &B) -> usize +where + for<'a> &'a B: Beta, + for<'a> <&'a B as Beta>::Gamma: Alpha, +{ + let g1 = beta.gamma(); + let g2 = beta.gamma(); + assert_alpha(g1) + assert_alpha(g2) +} + +pub fn desugared_bound_nested(beta: &B) -> usize +where + B: Beta, + B::Gamma: Copy + Alpha + Beta, + ::Gamma: Delta, +{ + let go = beta.gamma(); + let gi = go.gamma(); + go.alpha() + gi.delta() +} + +pub fn desugared() { + let beta = BetaType; + let gamma = beta.gamma(); + + assert_eq!(42, desugared_bound(&beta)); + assert_eq!(24, desugared_bound_region(&beta)); + assert_eq!(42 + 24 + 1337, desugared_bound_multi(beta)); + assert_eq!(7331, desugared_bound_region_specific::(&gamma)); + assert_eq!(7331 * 2, desugared_bound_region_forall(&beta)); + assert_eq!(42 + 1337, desugared_bound_nested(&beta)); +} diff --git a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs new file mode 100644 index 000000000..d180de9be --- /dev/null +++ b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -0,0 +1,67 @@ +// NOTE: rustc cannot currently handle bounds of the form `for<'a> >::Assoc: Baz`. +// This should hopefully be fixed with Chalk. + +#![feature(associated_type_bounds)] + +use std::fmt::Debug; +use std::iter::Once; + +trait Lam { + type App; +} + +#[derive(Clone)] +struct L1; +impl<'a> Lam<&'a u8> for L1 { + type App = u8; +} + +#[derive(Clone)] +struct L2; +impl<'a, 'b> Lam<&'a &'b u8> for L2 { + type App = u8; +} + +trait Case1 { + type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + //~^ ERROR `<::C as Iterator>::Item` is not an iterator + //~| ERROR `<::C as Iterator>::Item` cannot be sent between threads safely + //~| ERROR `<::C as Iterator>::Item` cannot be shared between threads safely +} + +pub struct S1; +impl Case1 for S1 { + type C = Once>; +} + +fn assume_case1() { + fn assert_a<_0, A>() + where + A: Iterator, + _0: Debug, + { + } + assert_a::<_, T::A>(); + + fn assert_b<_0, B>() + where + B: Iterator, + _0: 'static, + { + } + assert_b::<_, T::B>(); + + fn assert_c<_0, _1, _2, C>() + where + C: Clone + Iterator, + _2: Send + Iterator, + _1: for<'a> Lam<&'a u8, App = _0>, + _0: Debug, + { + } + assert_c::<_, _, _, T::C>(); +} + +fn main() { + assume_case1(S1); +} diff --git a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr new file mode 100644 index 000000000..c23e54594 --- /dev/null +++ b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -0,0 +1,39 @@ +error[E0277]: `<::C as Iterator>::Item` cannot be sent between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36 + | +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^ `<::C as Iterator>::Item` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `<::C as Iterator>::Item` +help: consider further restricting the associated type + | +LL | trait Case1 where <::C as Iterator>::Item: Send { + | ++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0277]: `<::C as Iterator>::Item` is not an iterator + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:43 + | +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<::C as Iterator>::Item` is not an iterator + | + = help: the trait `Iterator` is not implemented for `<::C as Iterator>::Item` +help: consider further restricting the associated type + | +LL | trait Case1 where <::C as Iterator>::Item: Iterator { + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0277]: `<::C as Iterator>::Item` cannot be shared between threads safely + --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93 + | +LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; + | ^^^^ `<::C as Iterator>::Item` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `<::C as Iterator>::Item` +help: consider further restricting the associated type + | +LL | trait Case1 where <::C as Iterator>::Item: Sync { + | ++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/binder-on-bound.rs b/tests/ui/associated-type-bounds/binder-on-bound.rs new file mode 100644 index 000000000..6cba45129 --- /dev/null +++ b/tests/ui/associated-type-bounds/binder-on-bound.rs @@ -0,0 +1,9 @@ +trait Trait { + type Bound<'a>; +} + +fn foo() where Trait Bound<'a> = &'a ()> { + //~^ ERROR `for<...>` is not allowed on associated type bounds +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/binder-on-bound.stderr b/tests/ui/associated-type-bounds/binder-on-bound.stderr new file mode 100644 index 000000000..f71f72bfb --- /dev/null +++ b/tests/ui/associated-type-bounds/binder-on-bound.stderr @@ -0,0 +1,8 @@ +error: `for<...>` is not allowed on associated type bounds + --> $DIR/binder-on-bound.rs:5:22 + | +LL | fn foo() where Trait Bound<'a> = &'a ()> { + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs new file mode 100644 index 000000000..23be73501 --- /dev/null +++ b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -0,0 +1,54 @@ +#![feature(associated_type_bounds)] + +use std::fmt::Debug; +use std::iter::Empty; +use std::ops::Range; + +trait Lam { type App; } + +#[derive(Clone)] +struct L1; +impl<'a> Lam<&'a u8> for L1 { type App = u8; } + +#[derive(Clone)] +struct L2; +impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } + +trait Case1 { + type A: Iterator; + //~^ ERROR `<::A as Iterator>::Item` doesn't implement `Debug` + + type B: Iterator; +} + +pub struct S1; +impl Case1 for S1 { + type A = Empty; + type B = Range; +} + +// Ensure we don't have opaque `impl Trait` desugaring: + +// What is this supposed to mean? Rustc currently lowers `: Default` in the +// bounds of `Out`, but trait selection can't find the bound since it applies +// to a type other than `Self::Out`. +pub trait Foo { type Out: Baz; } +//~^ ERROR trait bound `<::Out as Baz>::Assoc: Default` is not satisfied +pub trait Baz { type Assoc; } + +#[derive(Default)] +struct S2; +#[derive(Default)] +struct S3; +struct S4; +struct S5; +struct S6; +struct S7; + +impl Foo for S6 { type Out = S4; } +impl Foo for S7 { type Out = S5; } + +impl Baz for S4 { type Assoc = S2; } +impl Baz for S5 { type Assoc = S3; } + +fn main() {} diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr new file mode 100644 index 000000000..4e2313bd4 --- /dev/null +++ b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr @@ -0,0 +1,26 @@ +error[E0277]: `<::A as Iterator>::Item` doesn't implement `Debug` + --> $DIR/bounds-on-assoc-in-trait.rs:18:28 + | +LL | type A: Iterator; + | ^^^^^ `<::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `<::A as Iterator>::Item` +help: consider further restricting the associated type + | +LL | trait Case1 where <::A as Iterator>::Item: Debug { + | +++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `<::Out as Baz>::Assoc: Default` is not satisfied + --> $DIR/bounds-on-assoc-in-trait.rs:35:38 + | +LL | pub trait Foo { type Out: Baz; } + | ^^^^^^^ the trait `Default` is not implemented for `<::Out as Baz>::Assoc` + | +help: consider further restricting the associated type + | +LL | pub trait Foo where <::Out as Baz>::Assoc: Default { type Out: Baz; } + | +++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/const-projection-err.gce.stderr b/tests/ui/associated-type-bounds/const-projection-err.gce.stderr new file mode 100644 index 000000000..0f1ec9ad0 --- /dev/null +++ b/tests/ui/associated-type-bounds/const-projection-err.gce.stderr @@ -0,0 +1,24 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-projection-err.rs:4:26 + | +LL | #![cfg_attr(gce, feature(generic_const_exprs))] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0271]: type mismatch resolving `::A == 1` + --> $DIR/const-projection-err.rs:14:11 + | +LL | foo::(); + | ^ expected `0`, found `1` + | +note: required by a bound in `foo` + --> $DIR/const-projection-err.rs:11:28 + | +LL | fn foo>() {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-type-bounds/const-projection-err.rs b/tests/ui/associated-type-bounds/const-projection-err.rs new file mode 100644 index 000000000..bead85630 --- /dev/null +++ b/tests/ui/associated-type-bounds/const-projection-err.rs @@ -0,0 +1,18 @@ +// revisions: stock gce + +#![feature(associated_const_equality)] +#![cfg_attr(gce, feature(generic_const_exprs))] +//[gce]~^ WARN the feature `generic_const_exprs` is incomplete + +trait TraitWAssocConst { + const A: usize; +} + +fn foo>() {} + +fn bar>() { + foo::(); + //~^ ERROR type mismatch resolving `::A == 1` +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/const-projection-err.stock.stderr b/tests/ui/associated-type-bounds/const-projection-err.stock.stderr new file mode 100644 index 000000000..bf0824259 --- /dev/null +++ b/tests/ui/associated-type-bounds/const-projection-err.stock.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `::A == 1` + --> $DIR/const-projection-err.rs:14:11 + | +LL | foo::(); + | ^ expected `1`, found `::A` + | + = note: expected constant `1` + found constant `::A` +note: required by a bound in `foo` + --> $DIR/const-projection-err.rs:11:28 + | +LL | fn foo>() {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-type-bounds/duplicate.rs b/tests/ui/associated-type-bounds/duplicate.rs new file mode 100644 index 000000000..f67410986 --- /dev/null +++ b/tests/ui/associated-type-bounds/duplicate.rs @@ -0,0 +1,259 @@ +#![feature(associated_type_bounds)] +#![feature(type_alias_impl_trait)] + +use std::iter; +use std::mem::ManuallyDrop; + +struct SI1> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + f: T, +} +struct SI2> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + f: T, +} +struct SI3> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + f: T, +} +struct SW1 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + f: T, +} +struct SW2 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + f: T, +} +struct SW3 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + f: T, +} + +enum EI1> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + V(T), +} +enum EI2> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + V(T), +} +enum EI3> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + V(T), +} +enum EW1 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + V(T), +} +enum EW2 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + V(T), +} +enum EW3 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + V(T), +} + +union UI1> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + f: ManuallyDrop, +} +union UI2> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + f: ManuallyDrop, +} +union UI3> { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + f: ManuallyDrop, +} +union UW1 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + f: ManuallyDrop, +} +union UW2 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + f: ManuallyDrop, +} +union UW3 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ + f: ManuallyDrop, +} + +fn FI1>() {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +fn FI2>() {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +fn FI3>() {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +fn FW1() +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +fn FW2() +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +fn FW3() +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} + +fn FRPIT1() -> impl Iterator { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + iter::empty() +} +fn FRPIT2() -> impl Iterator { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + iter::empty() +} +fn FRPIT3() -> impl Iterator { + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + iter::empty() +} +fn FAPIT1(_: impl Iterator) {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +fn FAPIT2(_: impl Iterator) {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +fn FAPIT3(_: impl Iterator) {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + +type TAI1> = T; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type TAI2> = T; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type TAI3> = T; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type TAW1 +where + T: Iterator, +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] += T; +type TAW2 +where + T: Iterator, +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] += T; +type TAW3 +where + T: Iterator, +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] += T; + +type ETAI1> = impl Copy; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type ETAI2> = impl Copy; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type ETAI3> = impl Copy; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type ETAI4 = impl Iterator; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type ETAI5 = impl Iterator; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type ETAI6 = impl Iterator; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + +trait TRI1> {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +trait TRI2> {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +trait TRI3> {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +trait TRS1: Iterator {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +trait TRS2: Iterator {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +trait TRS3: Iterator {} +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +trait TRW1 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +trait TRW2 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +trait TRW3 +where + T: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +trait TRSW1 +where + Self: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + //~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +trait TRSW2 +where + Self: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + //~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +trait TRSW3 +where + Self: Iterator, + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + //~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +{ +} +trait TRA1 { + type A: Iterator; + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +} +trait TRA2 { + type A: Iterator; + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +} +trait TRA3 { + type A: Iterator; + //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +} + +type TADyn1 = dyn Iterator; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type TADyn2 = Box>; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +type TADyn3 = dyn Iterator; +//~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] + +fn main() {} diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr new file mode 100644 index 000000000..c3061327f --- /dev/null +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -0,0 +1,507 @@ +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:7:36 + | +LL | struct SI1> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:11:36 + | +LL | struct SI2> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:15:39 + | +LL | struct SI3> { + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:21:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:28:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:35:32 + | +LL | T: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:41:34 + | +LL | enum EI1> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:45:34 + | +LL | enum EI2> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:49:37 + | +LL | enum EI3> { + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:55:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:62:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:69:32 + | +LL | T: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:75:35 + | +LL | union UI1> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:79:35 + | +LL | union UI2> { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:83:38 + | +LL | union UI3> { + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:89:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:96:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:103:32 + | +LL | T: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:109:32 + | +LL | fn FI1>() {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:111:32 + | +LL | fn FI2>() {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:113:35 + | +LL | fn FI3>() {} + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:117:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:123:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:129:32 + | +LL | T: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:134:42 + | +LL | fn FRPIT1() -> impl Iterator { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:138:42 + | +LL | fn FRPIT2() -> impl Iterator { + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:142:45 + | +LL | fn FRPIT3() -> impl Iterator { + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:146:40 + | +LL | fn FAPIT1(_: impl Iterator) {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:148:40 + | +LL | fn FAPIT2(_: impl Iterator) {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:150:43 + | +LL | fn FAPIT3(_: impl Iterator) {} + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:153:35 + | +LL | type TAI1> = T; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:155:35 + | +LL | type TAI2> = T; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:157:38 + | +LL | type TAI3> = T; + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:161:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:166:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:171:32 + | +LL | T: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:175:36 + | +LL | type ETAI1> = impl Copy; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:177:36 + | +LL | type ETAI2> = impl Copy; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:179:39 + | +LL | type ETAI3> = impl Copy; + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:181:40 + | +LL | type ETAI4 = impl Iterator; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:183:40 + | +LL | type ETAI5 = impl Iterator; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:185:43 + | +LL | type ETAI6 = impl Iterator; + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:188:36 + | +LL | trait TRI1> {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:190:36 + | +LL | trait TRI2> {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:192:39 + | +LL | trait TRI3> {} + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:194:34 + | +LL | trait TRS1: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:196:34 + | +LL | trait TRS2: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:198:37 + | +LL | trait TRS3: Iterator {} + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:202:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:208:29 + | +LL | T: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:214:32 + | +LL | T: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:220:32 + | +LL | Self: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:220:32 + | +LL | Self: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:227:32 + | +LL | Self: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:227:32 + | +LL | Self: Iterator, + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:234:35 + | +LL | Self: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:234:35 + | +LL | Self: Iterator, + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:252:40 + | +LL | type TADyn1 = dyn Iterator; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:254:44 + | +LL | type TADyn2 = Box>; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:256:43 + | +LL | type TADyn3 = dyn Iterator; + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:240:34 + | +LL | type A: Iterator; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:244:34 + | +LL | type A: Iterator; + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:248:37 + | +LL | type A: Iterator; + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error: aborting due to 63 previous errors + +For more information about this error, try `rustc --explain E0719`. diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs new file mode 100644 index 000000000..a8d00803a --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs @@ -0,0 +1,66 @@ +// run-pass + +#![feature(associated_type_bounds)] + +use std::ops::Add; + +trait Tr1 { type As1; fn mk(&self) -> Self::As1; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } + +fn assert_copy(x: T) { let _x = x; let _x = x; } +fn assert_static(_: T) {} +fn assert_forall_tr2 Tr2<'a>>(_: T) {} + +struct S1; +#[derive(Copy, Clone)] +struct S2; +impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } } + +type Et1 = Box>; +fn def_et1() -> Et1 { Box::new(S1) } +pub fn use_et1() { assert_copy(def_et1().mk()); } + +type Et2 = Box>; +fn def_et2() -> Et2 { Box::new(S1) } +pub fn use_et2() { assert_static(def_et2().mk()); } + +type Et3 = Box>>>>; +fn def_et3() -> Et3 { + struct A; + impl Tr1 for A { + type As1 = core::ops::Range; + fn mk(&self) -> Self::As1 { 0..10 } + } + Box::new(A) +} +pub fn use_et3() { + let _0 = def_et3().mk().clone(); + let mut s = 0u8; + for _1 in _0 { + let _2 = _1 + 1u8; + s += _2.into(); + } + assert_eq!(s, (0..10).map(|x| x + 1).sum()); +} + +type Et4 = Box Tr2<'a>>>; +fn def_et4() -> Et4 { + #[derive(Copy, Clone)] + struct A; + impl Tr1 for A { + type As1 = A; + fn mk(&self) -> A { A } + } + impl<'a> Tr2<'a> for A { + fn tr2(self) -> &'a Self { &A } + } + Box::new(A) +} +pub fn use_et4() { assert_forall_tr2(def_et4().mk()); } + +fn main() { + let _ = use_et1(); + let _ = use_et2(); + let _ = use_et3(); + let _ = use_et4(); +} diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs new file mode 100644 index 000000000..08f965452 --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs @@ -0,0 +1,73 @@ +// run-pass + +// FIXME: uncomment let binding types below when `impl_trait_in_bindings` feature is fixed. + +#![feature(associated_type_bounds)] + +use std::ops::Add; + +trait Tr1 { type As1; fn mk(&self) -> Self::As1; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } + +fn assert_copy(x: T) { let _x = x; let _x = x; } +fn assert_static(_: T) {} +fn assert_forall_tr2 Tr2<'a>>(_: T) {} + +struct S1; +#[derive(Copy, Clone)] +struct S2; +impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } } + +fn def_et1() -> Box> { + let x /* : Box> */ = Box::new(S1); + x +} +pub fn use_et1() { assert_copy(def_et1().mk()); } + +fn def_et2() -> Box> { + let x /* : Box> */ = Box::new(S1); + x +} +pub fn use_et2() { assert_static(def_et2().mk()); } + +fn def_et3() -> Box>>>> { + struct A; + impl Tr1 for A { + type As1 = core::ops::Range; + fn mk(&self) -> Self::As1 { 0..10 } + } + let x /* : Box>>>> */ + = Box::new(A); + x +} +pub fn use_et3() { + let _0 = def_et3().mk().clone(); + let mut s = 0u8; + for _1 in _0 { + let _2 = _1 + 1u8; + s += _2.into(); + } + assert_eq!(s, (0..10).map(|x| x + 1).sum()); +} + +fn def_et4() -> Box Tr2<'a>>> { + #[derive(Copy, Clone)] + struct A; + impl Tr1 for A { + type As1 = A; + fn mk(&self) -> A { A } + } + impl<'a> Tr2<'a> for A { + fn tr2(self) -> &'a Self { &A } + } + let x /* : Box Tr2<'a>>> */ = Box::new(A); + x +} +pub fn use_et4() { assert_forall_tr2(def_et4().mk()); } + +fn main() { + let _ = use_et1(); + let _ = use_et2(); + let _ = use_et3(); + let _ = use_et4(); +} diff --git a/tests/ui/associated-type-bounds/elision.rs b/tests/ui/associated-type-bounds/elision.rs new file mode 100644 index 000000000..d00def571 --- /dev/null +++ b/tests/ui/associated-type-bounds/elision.rs @@ -0,0 +1,9 @@ +#![feature(associated_type_bounds)] +#![feature(anonymous_lifetime_in_impl_trait)] + +// The same thing should happen for constraints in dyn trait. +fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr new file mode 100644 index 000000000..ea3024627 --- /dev/null +++ b/tests/ui/associated-type-bounds/elision.stderr @@ -0,0 +1,28 @@ +error[E0106]: missing lifetime specifier + --> $DIR/elision.rs:5:70 + | +LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } + | ------------------------------------------------ ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `x`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(x: &'a mut dyn Iterator>) -> Option<&'a ()> { x.next() } + | ++++ ++ ~~ ~~ + +error[E0308]: mismatched types + --> $DIR/elision.rs:5:79 + | +LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } + | ----------------------------- -------------- ^^^^^^^^ expected `&()`, found type parameter `impl Iterator` + | | | + | | expected `Option<&'static ()>` because of return type + | this type parameter + | + = note: expected enum `Option<&'static ()>` + found enum `Option>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0106, E0308. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/associated-type-bounds/entails-sized-object-safety.rs b/tests/ui/associated-type-bounds/entails-sized-object-safety.rs new file mode 100644 index 000000000..f5a9bac6e --- /dev/null +++ b/tests/ui/associated-type-bounds/entails-sized-object-safety.rs @@ -0,0 +1,26 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(associated_type_bounds)] + +trait Tr1: Sized { type As1; } +trait Tr2<'a>: Sized { type As2; } + +trait ObjTr1 { fn foo() -> Self where Self: Tr1; } +fn _assert_obj_safe_1(_: Box) {} + +trait ObjTr2 { fn foo() -> Self where Self: Tr1; } +fn _assert_obj_safe_2(_: Box) {} + +trait ObjTr3 { fn foo() -> Self where Self: Tr1 + 'static + Copy>; } +fn _assert_obj_safe_3(_: Box) {} + +trait ObjTr4 { fn foo() -> Self where Self: Tr1 Tr2<'a>>; } +fn _assert_obj_safe_4(_: Box) {} + +trait ObjTr5 { fn foo() -> Self where for<'a> Self: Tr1>; } +fn _assert_obj_safe_5(_: Box) {} + +trait ObjTr6 { fn foo() -> Self where Self: for<'a> Tr1 Tr2<'b>>>; } +fn _assert_obj_safe_6(_: Box) {} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/enum-bounds.rs b/tests/ui/associated-type-bounds/enum-bounds.rs new file mode 100644 index 000000000..193f2efe1 --- /dev/null +++ b/tests/ui/associated-type-bounds/enum-bounds.rs @@ -0,0 +1,123 @@ +// run-pass + +#![feature(associated_type_bounds)] +#![allow(dead_code)] + +trait Tr1 { type As1; } +trait Tr2 { type As2; } +trait Tr3 { type As3; } +trait Tr4<'a> { type As4; } +trait Tr5 { type As5; } + +impl Tr1 for &str { type As1 = bool; } +impl Tr2 for bool { type As2 = u8; } +impl Tr3 for u8 { type As3 = fn() -> u8; } +impl Tr1 for () { type As1 = (usize,); } +impl<'a> Tr4<'a> for (usize,) { type As4 = u8; } +impl Tr5 for bool { type As5 = u16; } + +enum En1> { + Outest(T), + Outer(T::As1), + Inner(::As2), +} + +fn wrap_en1_1(x: T) -> En1 where T: Tr1, T::As1: Tr2 { + En1::Outest(x) +} + +fn wrap_en1_2(x: T::As1) -> En1 where T: Tr1, T::As1: Tr2 { + En1::Outer(x) +} + +fn wrap_en1_3(x: ::As2) -> En1 where T: Tr1, T::As1: Tr2 { + En1::Inner(x) +} + +enum En2>> { + V0(T), + V1(T::As1), + V2(::As2), + V3(<::As2 as Tr3>::As3), +} + +enum En3> { + V0(T), + V1(&'static T::As1), +} + +enum En4<'x1, 'x2, T: Tr1 Tr4<'l>>> { + V0(&'x1 >::As4), + V1(&'x2 >::As4), +} + +enum _En5<'x1, 'x2, T: Tr1 Tr4<'l, As4: Copy>>> { + _V0(&'x1 >::As4), + _V1(&'x2 >::As4), +} + +enum En6 +where + T: Tr1, +{ + V0(T), + V1(::As2), + V2(&'static T::As1), + V3(::As5), +} + +enum _En7<'a, 'b, T> // `::As2: 'a` is implied. +where + T: Tr1, +{ + V0(&'a T), + V1(&'b ::As2), +} + +fn _make_en7<'a, 'b, T>(x: _En7<'a, 'b, T>) +where + T: Tr1, +{ + match x { + _En7::V0(x) => { + let _: &'a T = &x; + }, + _En7::V1(_) => {}, + } +} + +enum EnSelf where Self: Tr1 { + V0(T), + V1(::As1), + V2(<::As1 as Tr2>::As2), +} + +impl Tr1 for EnSelf<&'static str> { type As1 = bool; } + +fn main() { + if let En1::Outest("foo") = wrap_en1_1::<_>("foo") {} else { panic!() }; + if let En1::Outer(true) = wrap_en1_2::<&str>(true) {} else { panic!() }; + if let En1::Inner(24u8) = wrap_en1_3::<&str>(24u8) {} else { panic!() }; + + let _ = En2::<_>::V0("151571"); + let _ = En2::<&str>::V1(false); + let _ = En2::<&str>::V2(42u8); + let _ = En2::<&str>::V3(|| 12u8); + + let _ = En3::<_>::V0("deadbeef"); + let _ = En3::<&str>::V1(&true); + + let f1 = (1,); + let f2 = (2,); + let _ = En4::<()>::V0(&f1.0); + let _ = En4::<()>::V1(&f2.0); + + let _ = En6::<_>::V0("bar"); + let _ = En6::<&str>::V1(24u8); + let _ = En6::<&str>::V2(&false); + let _ = En6::<&str>::V3(12u16); + + let _ = EnSelf::<_>::V0("foo"); + let _ = EnSelf::<&'static str>::V1(true); + let _ = EnSelf::<&'static str>::V2(24u8); +} diff --git a/tests/ui/associated-type-bounds/fn-apit.rs b/tests/ui/associated-type-bounds/fn-apit.rs new file mode 100644 index 000000000..3c9f51133 --- /dev/null +++ b/tests/ui/associated-type-bounds/fn-apit.rs @@ -0,0 +1,59 @@ +// run-pass +// aux-build:fn-aux.rs + +#![allow(unused)] +#![feature(associated_type_bounds)] + +extern crate fn_aux; + +use fn_aux::*; + +fn apit_bound(beta: impl Beta) -> usize { + desugared_bound(beta) +} + +fn apit_bound_region(beta: impl Beta) -> usize { + desugared_bound_region(beta) +} + +fn apit_bound_multi( + beta: impl Copy + Beta +) -> usize { + desugared_bound_multi(beta) +} + +fn apit_bound_region_forall( + beta: impl Beta Epsilon<'a>> +) -> usize { + desugared_bound_region_forall(beta) +} + +fn apit_bound_region_forall2( + beta: impl Beta Epsilon<'a, Zeta: Eta>> +) -> usize { + desugared_bound_region_forall2(beta) +} + +fn apit_bound_nested( + beta: impl Beta> +) -> usize { + desugared_bound_nested(beta) +} + +fn apit_bound_nested2( + beta: impl Beta> +) -> usize { + desugared_bound_nested(beta) +} + +fn main() { + let beta = BetaType; + let _gamma = beta.gamma(); + + assert_eq!(42, apit_bound(beta)); + assert_eq!(24, apit_bound_region(beta)); + assert_eq!(42 + 24 + 1337, apit_bound_multi(beta)); + assert_eq!(7331 * 2, apit_bound_region_forall(beta)); + assert_eq!(42 + 1337, apit_bound_nested(beta)); + assert_eq!(42 + 1337, apit_bound_nested2(beta)); +} diff --git a/tests/ui/associated-type-bounds/fn-aux.rs b/tests/ui/associated-type-bounds/fn-aux.rs new file mode 100644 index 000000000..434bdbe99 --- /dev/null +++ b/tests/ui/associated-type-bounds/fn-aux.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:fn-aux.rs + +#![feature(associated_type_bounds)] + +extern crate fn_aux; + +use fn_aux::*; + +fn main() { + desugared(); +} diff --git a/tests/ui/associated-type-bounds/fn-dyn-apit.rs b/tests/ui/associated-type-bounds/fn-dyn-apit.rs new file mode 100644 index 000000000..c4e8092c2 --- /dev/null +++ b/tests/ui/associated-type-bounds/fn-dyn-apit.rs @@ -0,0 +1,61 @@ +// run-pass +// aux-build:fn-dyn-aux.rs + +#![allow(unused)] +#![feature(associated_type_bounds)] + +extern crate fn_dyn_aux; + +use fn_dyn_aux::*; + +// ATB, APIT (dyn trait): + +fn dyn_apit_bound(beta: &dyn Beta) -> usize { + desugared_bound(beta) +} + +fn dyn_apit_bound_region(beta: &dyn Beta) -> usize { + desugared_bound_region(beta) +} + +fn dyn_apit_bound_multi( + beta: &(dyn Beta + Send) +) -> usize { + desugared_bound_multi(beta) +} + +fn dyn_apit_bound_region_forall( + beta: &dyn Beta Epsilon<'a>> +) -> usize { + desugared_bound_region_forall(beta) +} + +fn dyn_apit_bound_region_forall2( + beta: &dyn Beta Epsilon<'a, Zeta: Eta>> +) -> usize { + desugared_bound_region_forall2(beta) +} + +fn dyn_apit_bound_nested( + beta: &dyn Beta> +) -> usize { + desugared_bound_nested(beta) +} + +fn dyn_apit_bound_nested2( + beta: &dyn Beta> +) -> usize { + desugared_bound_nested(beta) +} + +fn main() { + let beta = BetaType; + let _gamma = beta.gamma(); + + assert_eq!(42, dyn_apit_bound(&beta)); + assert_eq!(24, dyn_apit_bound_region(&beta)); + assert_eq!(42 + 24 + 1337, dyn_apit_bound_multi(&beta)); + assert_eq!(7331 * 2, dyn_apit_bound_region_forall(&beta)); + assert_eq!(42 + 1337, dyn_apit_bound_nested(&beta)); + assert_eq!(42 + 1337, dyn_apit_bound_nested2(&beta)); +} diff --git a/tests/ui/associated-type-bounds/fn-inline.rs b/tests/ui/associated-type-bounds/fn-inline.rs new file mode 100644 index 000000000..8fa7212d6 --- /dev/null +++ b/tests/ui/associated-type-bounds/fn-inline.rs @@ -0,0 +1,63 @@ +// run-pass +// aux-build:fn-aux.rs + +#![allow(unused)] +#![feature(associated_type_bounds)] + +extern crate fn_aux; + +use fn_aux::*; + +// ATB, Type parameters, Inline bounds: + +fn inline_bound>(beta: B) -> usize { + desugared_bound(beta) +} + +fn inline_bound_region>(beta: B) -> usize { + desugared_bound_region(beta) +} + +fn inline_bound_multi>( + beta: B +) -> usize { + desugared_bound_multi(beta) +} + +fn inline_bound_region_specific<'a, B: Beta>>( + gamma: &'a B::Gamma +) -> usize { + desugared_bound_region_specific::(gamma) +} + +fn inline_bound_region_forall Epsilon<'a>>>( + beta: B +) -> usize { + desugared_bound_region_forall(beta) +} + +fn inline_bound_region_forall2 Epsilon<'a, Zeta: Eta>>>( + beta: B +) -> usize { + desugared_bound_region_forall2(beta) +} + +fn inline_bound_nested>>( + beta: B +) -> usize { + desugared_bound_nested(beta) +} + +fn main() { + let beta = BetaType; + let gamma = beta.gamma(); + + assert_eq!(42, inline_bound(beta)); + assert_eq!(24, inline_bound_region(beta)); + assert_eq!(42 + 24 + 1337, inline_bound_multi(beta)); + assert_eq!(7331, inline_bound_region_specific::(&gamma)); + assert_eq!(7331 * 2, inline_bound_region_forall(beta)); + // FIXME: requires lazy normalization. + // assert_eq!(7331 * 2, inline_bound_region_forall2(beta)); + assert_eq!(42 + 1337, inline_bound_nested(beta)); +} diff --git a/tests/ui/associated-type-bounds/fn-where.rs b/tests/ui/associated-type-bounds/fn-where.rs new file mode 100644 index 000000000..9c4f82ac9 --- /dev/null +++ b/tests/ui/associated-type-bounds/fn-where.rs @@ -0,0 +1,79 @@ +// run-pass +// aux-build:fn-aux.rs + +#![allow(unused)] +#![feature(associated_type_bounds)] + +extern crate fn_aux; + +use fn_aux::*; + +// ATB, Type parameters, Where-clauses: + +fn where_bound(beta: B) -> usize +where + B: Beta +{ + desugared_bound(beta) +} + +fn where_bound_region(beta: B) -> usize +where + B: Beta +{ + desugared_bound_region(beta) +} + +fn where_bound_multi(beta: B) -> usize +where + B: Copy + Beta, +{ + desugared_bound_multi(beta) +} + +fn where_bound_region_specific<'a, B>(gamma: &'a B::Gamma) -> usize +where + B: Beta>, +{ + desugared_bound_region_specific::(gamma) +} + +fn where_bound_region_forall(beta: B) -> usize +where + B: Beta Epsilon<'a>>, +{ + desugared_bound_region_forall(beta) +} + +fn where_bound_region_forall2(beta: B) -> usize +where + B: Beta Epsilon<'a, Zeta: Eta>>, +{ + desugared_bound_region_forall2(beta) +} + +fn where_contraint_region_forall(beta: B) -> usize +where + for<'a> &'a B: Beta, +{ + desugared_contraint_region_forall(beta) +} + +fn where_bound_nested(beta: B) -> usize +where + B: Beta>, +{ + desugared_bound_nested(beta) +} + +fn main() { + let beta = BetaType; + let gamma = beta.gamma(); + + assert_eq!(42, where_bound(beta)); + assert_eq!(24, where_bound_region(beta)); + assert_eq!(42 + 24 + 1337, where_bound_multi(beta)); + assert_eq!(7331, where_bound_region_specific::(&gamma)); + assert_eq!(7331 * 2, where_bound_region_forall::(beta)); + assert_eq!(42 + 1337, where_bound_nested::(beta)); +} diff --git a/tests/ui/associated-type-bounds/fn-wrap-apit.rs b/tests/ui/associated-type-bounds/fn-wrap-apit.rs new file mode 100644 index 000000000..96df13e37 --- /dev/null +++ b/tests/ui/associated-type-bounds/fn-wrap-apit.rs @@ -0,0 +1,65 @@ +// run-pass +// aux-build:fn-aux.rs + +#![feature(associated_type_bounds)] +#![allow(dead_code)] + +extern crate fn_aux; + +use fn_aux::*; + +// ATB, APIT + Wrap: + +struct Wrap(T); + +fn wrap_apit_bound(beta: Wrap>) -> usize { + desugared_bound(beta.0) +} + +fn wrap_apit_bound_region(beta: Wrap>) -> usize { + desugared_bound_region(beta.0) +} + +fn wrap_apit_bound_multi( + beta: Wrap> +) -> usize { + desugared_bound_multi(beta.0) +} + +fn wrap_apit_bound_region_forall( + beta: Wrap Epsilon<'a>>> +) -> usize { + desugared_bound_region_forall(beta.0) +} + +fn wrap_apit_bound_region_forall2( + beta: Wrap Epsilon<'a, Zeta: Eta>>> +) -> usize { + desugared_bound_region_forall2(beta.0) +} + +fn wrap_apit_bound_nested( + beta: Wrap>> +) -> usize { + desugared_bound_nested(beta.0) +} + +fn wrap_apit_bound_nested2( + beta: Wrap>> +) -> usize { + desugared_bound_nested(beta.0) +} + +fn main() { + let beta = BetaType; + let _gamma = beta.gamma(); + + assert_eq!(42, wrap_apit_bound(Wrap(beta))); + assert_eq!(24, wrap_apit_bound_region(Wrap(beta))); + assert_eq!(42 + 24 + 1337, wrap_apit_bound_multi(Wrap(beta))); + assert_eq!(7331 * 2, wrap_apit_bound_region_forall(Wrap(beta))); + // FIXME: requires lazy normalization. + // assert_eq!(7331 * 2, wrap_apit_bound_region_forall2(Wrap(beta))); + assert_eq!(42 + 1337, wrap_apit_bound_nested(Wrap(beta))); + assert_eq!(42 + 1337, wrap_apit_bound_nested2(Wrap(beta))); +} diff --git a/tests/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs b/tests/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs new file mode 100644 index 000000000..b1e54ec04 --- /dev/null +++ b/tests/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs @@ -0,0 +1,10 @@ +// check-pass + +trait Foo {} +trait Bar { + type A; + type B; +} +trait Baz: Bar + Foo {} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/hrtb.rs b/tests/ui/associated-type-bounds/hrtb.rs new file mode 100644 index 000000000..7ab383649 --- /dev/null +++ b/tests/ui/associated-type-bounds/hrtb.rs @@ -0,0 +1,65 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a> {} +trait B<'b> {} +fn foo() +where + for<'a> T: A<'a> + 'a, +{ +} +trait C<'c>: for<'a> A<'a> + for<'b> B<'b> { + type As; +} +struct D +where + T: for<'c> C<'c, As: A<'c>>, +{ + t: std::marker::PhantomData, +} + +trait E<'e> { + type As; +} +trait F<'f>: for<'a> A<'a> + for<'e> E<'e> {} +struct G +where + for<'f> T: F<'f, As: E<'f>> + 'f, +{ + t: std::marker::PhantomData, +} + +trait I<'a, 'b, 'c> { + type As; +} +trait H<'d, 'e>: for<'f> I<'d, 'f, 'e> + 'd {} +fn foo2() +where + T: for<'g> H<'g, 'g, As: for<'h> H<'h, 'g> + 'g>, +{ +} + +fn foo3() +where + T: for<'i> H<'i, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'i, 'k, 'j> + 'j> + 'i>, +{ +} +fn foo4() +where + T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> I<'l, 'k, 'j> + 'j> + 'i>, +{ +} + +struct X<'x, 'y> { + x: std::marker::PhantomData<&'x ()>, + y: std::marker::PhantomData<&'y ()>, +} + +fn foo5() +where + T: for<'l, 'i> H<'l, 'i, As: for<'j> H<'j, 'i, As: for<'k> H<'j, 'k, As = X<'j, 'k>> + 'j> + 'i> +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/implied-region-constraints.rs b/tests/ui/associated-type-bounds/implied-region-constraints.rs new file mode 100644 index 000000000..38219da61 --- /dev/null +++ b/tests/ui/associated-type-bounds/implied-region-constraints.rs @@ -0,0 +1,45 @@ +#![feature(associated_type_bounds)] + +trait Tr1 { type As1; } +trait Tr2 { type As2; } + +struct St<'a, 'b, T: Tr1> { // `T: 'b` is *not* implied! + f0: &'a T, // `T: 'a` is implied. + f1: &'b ::As2, // `::As2: 'a` is implied. +} + +fn _bad_st<'a, 'b, T>(x: St<'a, 'b, T>) +where + T: Tr1, + T::As1: Tr2, +{ + // This should fail because `T: 'b` is not implied from `WF(St<'a, 'b, T>)`. + let _failure_proves_not_implied_outlives_region_b: &'b T = &x.f0; + //~^ ERROR lifetime may not live long enough +} + +enum En7<'a, 'b, T> // `::As2: 'a` is implied. +where + T: Tr1, + T::As1: Tr2, +{ + V0(&'a T), + V1(&'b ::As2), +} + +fn _bad_en7<'a, 'b, T>(x: En7<'a, 'b, T>) +where + T: Tr1, + T::As1: Tr2, +{ + match x { + En7::V0(x) => { + // Also fails for the same reason as above: + let _failure_proves_not_implied_outlives_region_b: &'b T = &x; + //~^ ERROR lifetime may not live long enough + }, + En7::V1(_) => {}, + } +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/implied-region-constraints.stderr b/tests/ui/associated-type-bounds/implied-region-constraints.stderr new file mode 100644 index 000000000..cddce8777 --- /dev/null +++ b/tests/ui/associated-type-bounds/implied-region-constraints.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/implied-region-constraints.rs:17:56 + | +LL | fn _bad_st<'a, 'b, T>(x: St<'a, 'b, T>) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _failure_proves_not_implied_outlives_region_b: &'b T = &x.f0; + | ^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/implied-region-constraints.rs:38:64 + | +LL | fn _bad_en7<'a, 'b, T>(x: En7<'a, 'b, T>) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _failure_proves_not_implied_outlives_region_b: &'b T = &x; + | ^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-type-bounds/inside-adt.rs b/tests/ui/associated-type-bounds/inside-adt.rs new file mode 100644 index 000000000..8eb8c44bb --- /dev/null +++ b/tests/ui/associated-type-bounds/inside-adt.rs @@ -0,0 +1,30 @@ +#![feature(associated_type_bounds)] + +use std::mem::ManuallyDrop; + +struct S1 { f: dyn Iterator } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +struct S2 { f: Box> } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +struct S3 { f: dyn Iterator } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions + +enum E1 { V(dyn Iterator) } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR the size for values of type `(dyn Iterator + 'static)` +enum E2 { V(Box>) } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +enum E3 { V(dyn Iterator) } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR the size for values of type `(dyn Iterator + 'static)` + +union U1 { f: ManuallyDrop> } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR the size for values of type `(dyn Iterator + 'static)` +union U2 { f: ManuallyDrop>> } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +union U3 { f: ManuallyDrop> } +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR the size for values of type `(dyn Iterator + 'static)` + +fn main() {} diff --git a/tests/ui/associated-type-bounds/inside-adt.stderr b/tests/ui/associated-type-bounds/inside-adt.stderr new file mode 100644 index 000000000..dbfcfa580 --- /dev/null +++ b/tests/ui/associated-type-bounds/inside-adt.stderr @@ -0,0 +1,131 @@ +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:5:29 + | +LL | struct S1 { f: dyn Iterator } + | ^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:7:33 + | +LL | struct S2 { f: Box> } + | ^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:9:29 + | +LL | struct S3 { f: dyn Iterator } + | ^^^^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:12:26 + | +LL | enum E1 { V(dyn Iterator) } + | ^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:15:30 + | +LL | enum E2 { V(Box>) } + | ^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:17:26 + | +LL | enum E3 { V(dyn Iterator) } + | ^^^^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:21:41 + | +LL | union U1 { f: ManuallyDrop> } + | ^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:24:45 + | +LL | union U2 { f: ManuallyDrop>> } + | ^^^^^^^^^^ + +error: associated type bounds are not allowed within structs, enums, or unions + --> $DIR/inside-adt.rs:26:41 + | +LL | union U3 { f: ManuallyDrop> } + | ^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `(dyn Iterator + 'static)` cannot be known at compilation time + --> $DIR/inside-adt.rs:12:13 + | +LL | enum E1 { V(dyn Iterator) } + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | enum E1 { V(&dyn Iterator) } + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | enum E1 { V(Box>) } + | ++++ + + +error[E0277]: the size for values of type `(dyn Iterator + 'static)` cannot be known at compilation time + --> $DIR/inside-adt.rs:17:13 + | +LL | enum E3 { V(dyn Iterator) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | enum E3 { V(&dyn Iterator) } + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | enum E3 { V(Box>) } + | ++++ + + +error[E0277]: the size for values of type `(dyn Iterator + 'static)` cannot be known at compilation time + --> $DIR/inside-adt.rs:21:15 + | +LL | union U1 { f: ManuallyDrop> } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `ManuallyDrop<(dyn Iterator + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = note: required because it appears within the type `ManuallyDrop<(dyn Iterator + 'static)>` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | union U1 { f: &ManuallyDrop> } + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | union U1 { f: Box>> } + | ++++ + + +error[E0277]: the size for values of type `(dyn Iterator + 'static)` cannot be known at compilation time + --> $DIR/inside-adt.rs:26:15 + | +LL | union U3 { f: ManuallyDrop> } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `ManuallyDrop<(dyn Iterator + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator + 'static)` + = note: required because it appears within the type `ManuallyDrop<(dyn Iterator + 'static)>` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | union U3 { f: &ManuallyDrop> } + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | union U3 { f: Box>> } + | ++++ + + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.rs b/tests/ui/associated-type-bounds/issue-102335-ty.rs new file mode 100644 index 000000000..363df73c1 --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-102335-ty.rs @@ -0,0 +1,12 @@ +trait T { + type A: S = ()>; + //~^ ERROR associated type bindings are not allowed here +} + +trait Q {} + +trait S { + type C: Q; +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr new file mode 100644 index 000000000..8777b2965 --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-ty.rs:2:17 + | +LL | type A: S = ()>; + | ^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-type-bounds/issue-61752.rs b/tests/ui/associated-type-bounds/issue-61752.rs new file mode 100644 index 000000000..f38ec640e --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-61752.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = (); +} + +fn a() where F::Bar: Copy {} + +fn b() where ::Bar: Copy {} + +// This used to complain about ambiguous associated types. +fn c>() where F::Bar: Copy {} + +fn main() { + a::<()>(); + b::<()>(); + c::<()>(); +} diff --git a/tests/ui/associated-type-bounds/issue-70292.rs b/tests/ui/associated-type-bounds/issue-70292.rs new file mode 100644 index 000000000..945d7688c --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-70292.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(associated_type_bounds)] + +fn foo(_: F) +where + F: for<'a> Trait, +{ +} + +trait Trait { + type Output; +} + +impl Trait for T { + type Output = (); +} + +fn main() { + foo(()); +} diff --git a/tests/ui/associated-type-bounds/issue-71443-1.rs b/tests/ui/associated-type-bounds/issue-71443-1.rs new file mode 100644 index 000000000..5d2a3e6cb --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-71443-1.rs @@ -0,0 +1,9 @@ +#![feature(associated_type_bounds)] + +struct Incorrect; + +fn hello Iterator>() { + Incorrect //~ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-71443-1.stderr b/tests/ui/associated-type-bounds/issue-71443-1.stderr new file mode 100644 index 000000000..a9459ee74 --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-71443-1.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-71443-1.rs:6:5 + | +LL | fn hello Iterator>() { + | - help: try adding a return type: `-> Incorrect` +LL | Incorrect + | ^^^^^^^^^ expected `()`, found struct `Incorrect` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-type-bounds/issue-71443-2.rs b/tests/ui/associated-type-bounds/issue-71443-2.rs new file mode 100644 index 000000000..813dcd60a --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-71443-2.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(associated_type_bounds)] + +fn hello<'b, F>() +where + for<'a> F: Iterator + 'b, +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-73818.rs b/tests/ui/associated-type-bounds/issue-73818.rs new file mode 100644 index 000000000..bb890f72a --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-73818.rs @@ -0,0 +1,25 @@ +// Test that associated type bounds are correctly normalized when checking +// default associated type values. +// check-pass + +#![allow(incomplete_features)] +#![feature(specialization)] + +#[derive(PartialEq)] +enum Never {} +trait Foo { + type Assoc: PartialEq; // PartialEq<::Assoc> +} +impl Foo for T { + default type Assoc = Never; +} + +trait Trait1 { + type Selection: PartialEq; +} +trait Trait2: PartialEq {} +impl Trait1 for T { + default type Selection = T; +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-79949.rs b/tests/ui/associated-type-bounds/issue-79949.rs new file mode 100644 index 000000000..9dd37f981 --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-79949.rs @@ -0,0 +1,25 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(associated_type_bounds)] + +trait MP { + type T<'a>; +} +struct S(String); +impl MP for S { + type T<'a> = &'a str; +} + +trait SR: MP { + fn sr(&self) -> i32 + where + for<'a> IM: T::T<'a>>>; +} + +trait T { + type T; +} +trait U {} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-81193.rs b/tests/ui/associated-type-bounds/issue-81193.rs new file mode 100644 index 000000000..d2aa54ab9 --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-81193.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a, 'b> {} + +trait B<'a, 'b, 'c> {} + +fn err<'u, 'a, F>() +where + for<'b> F: Iterator B<'a, 'b, 'c> + for<'c> A<'a, 'c>>, +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/issue-83017.rs b/tests/ui/associated-type-bounds/issue-83017.rs new file mode 100644 index 000000000..a02208661 --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-83017.rs @@ -0,0 +1,39 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait TraitA<'a> { + type AsA; +} + +trait TraitB<'a, 'b> { + type AsB; +} + +trait TraitC<'a, 'b, 'c> {} + +struct X; + +impl<'a, 'b, 'c> TraitC<'a, 'b, 'c> for X {} + +struct Y; + +impl<'a, 'b> TraitB<'a, 'b> for Y { + type AsB = X; +} + +struct Z; + +impl<'a> TraitA<'a> for Z { + type AsA = Y; +} + +fn foo() +where + for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>, +{ +} + +fn main() { + foo::(); +} diff --git a/tests/ui/associated-type-bounds/issue-99828.rs b/tests/ui/associated-type-bounds/issue-99828.rs new file mode 100644 index 000000000..7b711283f --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-99828.rs @@ -0,0 +1,11 @@ +fn get_iter(vec: &[i32]) -> impl Iterator + '_ { + //~^ ERROR expected associated type bound, found constant + //~| ERROR associated const equality is incomplete + vec.iter() +} + +fn main() { + let vec = Vec::new(); + let mut iter = get_iter(&vec); + iter.next(); +} diff --git a/tests/ui/associated-type-bounds/issue-99828.stderr b/tests/ui/associated-type-bounds/issue-99828.stderr new file mode 100644 index 000000000..dc93c47da --- /dev/null +++ b/tests/ui/associated-type-bounds/issue-99828.stderr @@ -0,0 +1,21 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/issue-99828.rs:1:43 + | +LL | fn get_iter(vec: &[i32]) -> impl Iterator + '_ { + | ^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: expected associated type bound, found constant + --> $DIR/issue-99828.rs:1:43 + | +LL | fn get_iter(vec: &[i32]) -> impl Iterator + '_ { + | ^^^^^^^^^ + | +note: associated type defined here + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs new file mode 100644 index 000000000..07d0f8f87 --- /dev/null +++ b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs @@ -0,0 +1,10 @@ +#[allow(dead_code)] +fn foo(_m: M) +where + M::Item: Temp, + //~^ ERROR cannot find trait `Temp` in this scope [E0405] + //~| ERROR associated type `Item` not found for `M` [E0220] +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr new file mode 100644 index 000000000..bc2807b03 --- /dev/null +++ b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr @@ -0,0 +1,16 @@ +error[E0405]: cannot find trait `Temp` in this scope + --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:14 + | +LL | M::Item: Temp, + | ^^^^ not found in this scope + +error[E0220]: associated type `Item` not found for `M` + --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8 + | +LL | M::Item: Temp, + | ^^^^ associated type `Item` not found + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0220, E0405. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs b/tests/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs new file mode 100644 index 000000000..77e4bd4d6 --- /dev/null +++ b/tests/ui/associated-type-bounds/order-dependent-bounds-issue-54121.rs @@ -0,0 +1,47 @@ +// check-pass + +// From https://github.com/rust-lang/rust/issues/54121/ +// +// Whether the code compiled depended on the order of the trait bounds in +// `type T: Tr + Tr` +// But both should compile as order shouldn't matter. + +trait Tr { + fn exec(a: A, b: B); +} + +trait P { + // This compiled successfully + type T: Tr + Tr; +} + +trait Q { + // This didn't compile + type T: Tr + Tr; +} + +#[allow(dead_code)] +fn f() { + ::T::exec(0u8, 0u8) +} + +#[allow(dead_code)] +fn g() { + // A mismatched types error was emitted on this line. + ::T::exec(0u8, 0u8) +} + +// Another reproduction of the same issue +trait Trait { + type Type: Into + Into + Copy; + type Type1; + type Type2; +} + +#[allow(dead_code)] +fn foo(x: T::Type) { + let _1: T::Type1 = x.into(); + let _2: T::Type2 = x.into(); +} + +fn main() { } diff --git a/tests/ui/associated-type-bounds/rpit.rs b/tests/ui/associated-type-bounds/rpit.rs new file mode 100644 index 000000000..47cadf331 --- /dev/null +++ b/tests/ui/associated-type-bounds/rpit.rs @@ -0,0 +1,64 @@ +// run-pass + +#![feature(associated_type_bounds)] + +use std::ops::Add; + +trait Tr1 { type As1; fn mk(self) -> Self::As1; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } + +fn assert_copy(x: T) { let _x = x; let _x = x; } +fn assert_static(_: T) {} +fn assert_forall_tr2 Tr2<'a>>(_: T) {} + +struct S1; +#[derive(Copy, Clone)] +struct S2; +impl Tr1 for S1 { type As1 = S2; fn mk(self) -> Self::As1 { S2 } } + +fn def_et1() -> impl Tr1 { S1 } +pub fn use_et1() { assert_copy(def_et1().mk()); } + +fn def_et2() -> impl Tr1 { S1 } +pub fn use_et2() { assert_static(def_et2().mk()); } + +fn def_et3() -> impl Tr1>>> { + struct A; + impl Tr1 for A { + type As1 = core::ops::Range; + fn mk(self) -> Self::As1 { 0..10 } + } + A +} + +pub fn use_et3() { + let _0 = def_et3().mk().clone(); + let mut s = 0u8; + for _1 in _0 { + let _2 = _1 + 1u8; + s += _2.into(); + } + assert_eq!(s, (0..10).map(|x| x + 1).sum()); +} + +fn def_et4() -> impl Tr1 Tr2<'a>> { + #[derive(Copy, Clone)] + struct A; + impl Tr1 for A { + type As1 = A; + fn mk(self) -> A { A } + } + impl<'a> Tr2<'a> for A { + fn tr2(self) -> &'a Self { &A } + } + A +} + +pub fn use_et4() { assert_forall_tr2(def_et4().mk()); } + +fn main() { + let _ = use_et1(); + let _ = use_et2(); + let _ = use_et3(); + let _ = use_et4(); +} diff --git a/tests/ui/associated-type-bounds/struct-bounds.rs b/tests/ui/associated-type-bounds/struct-bounds.rs new file mode 100644 index 000000000..2c1ce1c37 --- /dev/null +++ b/tests/ui/associated-type-bounds/struct-bounds.rs @@ -0,0 +1,116 @@ +// run-pass + +#![allow(unused)] +#![feature(associated_type_bounds)] + +trait Tr1 { type As1; } +trait Tr2 { type As2; } +trait Tr3 {} +trait Tr4<'a> { type As4; } +trait Tr5 { type As5; } + +impl Tr1 for &str { type As1 = bool; } +impl Tr2 for bool { type As2 = u8; } +impl Tr3 for u8 {} +impl Tr1 for () { type As1 = (usize,); } +impl<'a> Tr4<'a> for (usize,) { type As4 = u8; } +impl Tr5 for bool { type As5 = u16; } + +struct St1> { + outest: T, + outer: T::As1, + inner: ::As2, +} + +fn unwrap_1_st1>(x: St1) -> (T, T::As1, ::As2) { + (x.outest, x.outer, x.inner) +} + +fn unwrap_2_st1(x: St1) -> (T, T::As1, ::As2) +where + T: Tr1, + T::As1: Tr2, +{ + unwrap_1_st1(x) +} + +struct St2>> { + outest: T, + outer: T::As1, + inner: ::As2, +} + +struct St3> { + outest: T, + outer: &'static T::As1, +} + +struct St4<'x1, 'x2, T: Tr1 Tr4<'l>>> { + f1: &'x1 >::As4, + f2: &'x2 >::As4, +} + +struct St5<'x1, 'x2, T: Tr1 Tr4<'l, As4: Copy>>> { + f1: &'x1 >::As4, + f2: &'x2 >::As4, +} + +struct St6 +where + T: Tr1, +{ + f0: T, + f1: ::As2, + f2: &'static T::As1, + f3: ::As5, +} + +struct St7<'a, 'b, T> // `::As2: 'a` is implied. +where + T: Tr1, +{ + f0: &'a T, + f1: &'b ::As2, +} + +fn _use_st7<'a, 'b, T>(x: St7<'a, 'b, T>) +where + T: Tr1, + T::As1: Tr2, +{ + let _: &'a T = &x.f0; +} + +struct StSelf where Self: Tr1 { + f2: <::As1 as Tr2>::As2, +} + +impl Tr1 for StSelf<&'static str> { type As1 = bool; } + +fn main() { + let st1 = St1 { outest: "foo", outer: true, inner: 42u8 }; + assert_eq!(("foo", true, 42), unwrap_1_st1(st1)); + + let _ = St2 { outest: "foo", outer: true, inner: 42u8 }; + + let _ = St3 { outest: "foo", outer: &true }; + + let f1 = (1,); + let f2 = (2,); + let st4 = St4::<()> { f1: &f1.0, f2: &f2.0, }; + assert_eq!((&1, &2), (st4.f1, st4.f2)); + + // FIXME: requires lazy normalization. + /* + let f1 = (1,); + let f2 = (2,); + let st5 = St5::<()> { f1: &f1.0, f2: &f2.0, }; + assert_eq!((&1, &2), (st5.f1, st5.f2)); + */ + + let st6 = St6 { f0: "bar", f1: 24u8, f2: &true, f3: 12u16, }; + assert_eq!(("bar", 24, &true, 12), (st6.f0, st6.f1, st6.f2, st6.f3)); + + let stself = StSelf::<&'static str> { f2: 42u8 }; + assert_eq!(stself.f2, 42u8); +} diff --git a/tests/ui/associated-type-bounds/supertrait-referencing-self.rs b/tests/ui/associated-type-bounds/supertrait-referencing-self.rs new file mode 100644 index 000000000..c82ec01f4 --- /dev/null +++ b/tests/ui/associated-type-bounds/supertrait-referencing-self.rs @@ -0,0 +1,12 @@ +// check-pass +trait Foo { + type Bar; +} +trait Qux: Foo + AsRef {} +trait Foo2 {} + +trait Qux2: Foo2 + AsRef { + type Bar; +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/supertrait-referencing.rs b/tests/ui/associated-type-bounds/supertrait-referencing.rs new file mode 100644 index 000000000..2e9753515 --- /dev/null +++ b/tests/ui/associated-type-bounds/supertrait-referencing.rs @@ -0,0 +1,19 @@ +// check-pass + +// The goal of this test is to ensure that T: Bar +// in the where clause does not cycle + +trait Foo { + type Item; +} + +trait Bar {} + +fn baz() +where + T: Foo, + T: Bar, +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/supertrait-where-referencing-self.rs b/tests/ui/associated-type-bounds/supertrait-where-referencing-self.rs new file mode 100644 index 000000000..72a6be9ff --- /dev/null +++ b/tests/ui/associated-type-bounds/supertrait-where-referencing-self.rs @@ -0,0 +1,27 @@ +// check-pass + +// Test that we do not get a cycle due to +// resolving `Self::Bar` in the where clauses +// on a trait definition (in particular, in +// a where clause that is defining a superpredicate). + +trait Foo { + type Bar; +} +trait Qux +where + Self: Foo, + Self: AsRef, +{ +} +trait Foo2 {} + +trait Qux2 +where + Self: Foo2, + Self: AsRef, +{ + type Bar; +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs new file mode 100644 index 000000000..e223a8957 --- /dev/null +++ b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs @@ -0,0 +1,96 @@ +// run-pass + +#![feature(associated_type_bounds)] +#![feature(type_alias_impl_trait)] + +use std::ops::Add; + +trait Tr1 { + type As1; + fn mk(self) -> Self::As1; +} +trait Tr2<'a> { + fn tr2(self) -> &'a Self; +} + +fn assert_copy(x: T) { + let _x = x; + let _x = x; +} +fn assert_static(_: T) {} +fn assert_forall_tr2 Tr2<'a>>(_: T) {} + +struct S1; +#[derive(Copy, Clone)] +struct S2; +impl Tr1 for S1 { + type As1 = S2; + fn mk(self) -> Self::As1 { + S2 + } +} + +type Et1 = impl Tr1; +fn def_et1() -> Et1 { + S1 +} +pub fn use_et1() { + assert_copy(def_et1().mk()); +} + +type Et2 = impl Tr1; +fn def_et2() -> Et2 { + S1 +} +pub fn use_et2() { + assert_static(def_et2().mk()); +} + +type Et3 = impl Tr1>>>; +fn def_et3() -> Et3 { + struct A; + impl Tr1 for A { + type As1 = core::ops::Range; + fn mk(self) -> Self::As1 { + 0..10 + } + } + A +} +pub fn use_et3() { + let _0 = def_et3().mk().clone(); + let mut s = 0u8; + for _1 in _0 { + let _2 = _1 + 1u8; + s += _2.into(); + } + assert_eq!(s, (0..10).map(|x| x + 1).sum()); +} + +type Et4 = impl Tr1 Tr2<'a>>; +fn def_et4() -> Et4 { + #[derive(Copy, Clone)] + struct A; + impl Tr1 for A { + type As1 = A; + fn mk(self) -> A { + A + } + } + impl<'a> Tr2<'a> for A { + fn tr2(self) -> &'a Self { + &A + } + } + A +} +pub fn use_et4() { + assert_forall_tr2(def_et4().mk()); +} + +fn main() { + let _ = use_et1(); + let _ = use_et2(); + let _ = use_et3(); + let _ = use_et4(); +} diff --git a/tests/ui/associated-type-bounds/trait-params.rs b/tests/ui/associated-type-bounds/trait-params.rs new file mode 100644 index 000000000..b0703a4ee --- /dev/null +++ b/tests/ui/associated-type-bounds/trait-params.rs @@ -0,0 +1,116 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(associated_type_bounds)] + +use std::iter::Once; +use std::ops::Range; + +pub trait Three { type A; type B; type C; } +pub fn assert_three() {} +pub fn assert_iterator() {} +pub fn assert_copy() {} +pub fn assert_static() {} +pub fn assert_send() {} +pub fn assert_forall_into Into<&'a u8>>() {} + +struct A; struct B; +impl<'a> Into<&'a u8> for A { fn into(self) -> &'a u8 { &0 } } +impl Three for B { type A = Range; type B = Range; type C = Range; } + +trait Case1 +where + A: Iterator, + B: Iterator, + C: Iterator, + D: Iterator Into<&'a u8>>, + E: Three, B: Iterator, C: Iterator>, + Self: Three, +{ + fn _a() { + assert_iterator::(); + assert_copy::(); + } + fn _b() { + assert_iterator::(); + assert_static::(); + } + fn _c() { + assert_iterator::(); + assert_copy::(); + assert_static::(); + assert_send::(); + } + fn _d() { + assert_iterator::(); + assert_forall_into::(); + } + fn _e() { + assert_three::(); + assert_iterator::(); + assert_iterator::(); + assert_iterator::(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); + } + fn _self() { + assert_three::(); + assert_copy::(); + assert_static::(); + assert_send::(); + } +} + +struct DataCase1; +impl Three for DataCase1 { type A = u8; type B = u8; type C = u8; } +impl Case1, Range, Range, Once, B> for DataCase1 {} + +trait Case2< + A: Iterator, + B: Iterator, + C: Iterator, + D: Iterator Into<&'a u8>>, + E: Three, B: Iterator, C: Iterator>, +>: + Three +{ + fn _a() { + assert_iterator::(); + assert_copy::(); + } + fn _b() { + assert_iterator::(); + assert_static::(); + } + fn _c() { + assert_iterator::(); + assert_copy::(); + assert_static::(); + assert_send::(); + } + fn _d() { + assert_iterator::(); + assert_forall_into::(); + } + fn _e() { + assert_three::(); + assert_iterator::(); + assert_iterator::(); + assert_iterator::(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); + assert_copy::<::Item>(); + } + fn _self() { + assert_three::(); + assert_copy::(); + assert_static::(); + assert_send::(); + } +} + +struct DataCase2; +impl Three for DataCase2 { type A = u8; type B = u8; type C = u8; } +impl Case2, Range, Range, Once, B> for DataCase2 {} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/traits-assoc-anonymized.rs b/tests/ui/associated-type-bounds/traits-assoc-anonymized.rs new file mode 100644 index 000000000..a9d6eed81 --- /dev/null +++ b/tests/ui/associated-type-bounds/traits-assoc-anonymized.rs @@ -0,0 +1,33 @@ +// check-pass + +pub struct LookupInternedStorage; + +impl QueryStorageOps for LookupInternedStorage +where + Q: Query, + for<'d> Q: QueryDb<'d>, +{ + fn fmt_index(&self, db: &>::DynDb) { + <>::DynDb as HasQueryGroup>::group_storage(db); + } +} + +pub trait HasQueryGroup { + fn group_storage(&self); +} + +pub trait QueryStorageOps +where + Q: Query, +{ + fn fmt_index(&self, db: &>::DynDb); +} + +pub trait QueryDb<'d> { + type DynDb: HasQueryGroup + 'd; + type Group; +} + +pub trait Query: for<'d> QueryDb<'d> {} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/traits-assoc-type-macros.rs b/tests/ui/associated-type-bounds/traits-assoc-type-macros.rs new file mode 100644 index 000000000..d854dce38 --- /dev/null +++ b/tests/ui/associated-type-bounds/traits-assoc-type-macros.rs @@ -0,0 +1,43 @@ +// check-pass +// incremental + +// This test case makes sure that we can compile with incremental compilation +// enabled when there are macros, traits, inheritance and associated types involved. + +trait Deserializer { + type Error; +} + +trait Deserialize { + fn deserialize(_: D) -> D::Error + where + D: Deserializer; +} + +macro_rules! impl_deserialize { + ($name:ident) => { + impl Deserialize for $name { + fn deserialize(_: D) -> D::Error + where + D: Deserializer, + { + loop {} + } + } + }; +} + +macro_rules! formats { + { + $($name:ident,)* + } => { + $( + pub struct $name; + + impl_deserialize!($name); + )* + } +} +formats! { Foo, Bar, } + +fn main() {} diff --git a/tests/ui/associated-type-bounds/type-alias.rs b/tests/ui/associated-type-bounds/type-alias.rs new file mode 100644 index 000000000..f74c5ff1e --- /dev/null +++ b/tests/ui/associated-type-bounds/type-alias.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(associated_type_bounds)] + +type _TaWhere1 where T: Iterator = T; //~ WARNING type_alias_bounds +type _TaWhere2 where T: Iterator = T; //~ WARNING type_alias_bounds +type _TaWhere3 where T: Iterator = T; //~ WARNING type_alias_bounds +type _TaWhere4 where T: Iterator = T; //~ WARNING type_alias_bounds +type _TaWhere5 where T: Iterator Into<&'a u8>> = T; //~ WARNING type_alias_bounds +type _TaWhere6 where T: Iterator> = T; //~ WARNING type_alias_bounds + +type _TaInline1> = T; //~ WARNING type_alias_bounds +type _TaInline2> = T; //~ WARNING type_alias_bounds +type _TaInline3> = T; //~ WARNING type_alias_bounds +type _TaInline4> = T; //~ WARNING type_alias_bounds +type _TaInline5 Into<&'a u8>>> = T; //~ WARNING type_alias_bounds +type _TaInline6>> = T; //~ WARNING type_alias_bounds + +fn main() {} diff --git a/tests/ui/associated-type-bounds/type-alias.stderr b/tests/ui/associated-type-bounds/type-alias.stderr new file mode 100644 index 000000000..c22b80b88 --- /dev/null +++ b/tests/ui/associated-type-bounds/type-alias.stderr @@ -0,0 +1,147 @@ +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias.rs:5:25 + | +LL | type _TaWhere1 where T: Iterator = T; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(type_alias_bounds)]` on by default +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type _TaWhere1 where T: Iterator = T; +LL + type _TaWhere1 = T; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias.rs:6:25 + | +LL | type _TaWhere2 where T: Iterator = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type _TaWhere2 where T: Iterator = T; +LL + type _TaWhere2 = T; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias.rs:7:25 + | +LL | type _TaWhere3 where T: Iterator = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type _TaWhere3 where T: Iterator = T; +LL + type _TaWhere3 = T; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias.rs:8:25 + | +LL | type _TaWhere4 where T: Iterator = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type _TaWhere4 where T: Iterator = T; +LL + type _TaWhere4 = T; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias.rs:9:25 + | +LL | type _TaWhere5 where T: Iterator Into<&'a u8>> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type _TaWhere5 where T: Iterator Into<&'a u8>> = T; +LL + type _TaWhere5 = T; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias.rs:10:25 + | +LL | type _TaWhere6 where T: Iterator> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type _TaWhere6 where T: Iterator> = T; +LL + type _TaWhere6 = T; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias.rs:12:20 + | +LL | type _TaInline1> = T; + | ^^^^^^^^^^^^^^^^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type _TaInline1> = T; +LL + type _TaInline1 = T; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias.rs:13:20 + | +LL | type _TaInline2> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type _TaInline2> = T; +LL + type _TaInline2 = T; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias.rs:14:20 + | +LL | type _TaInline3> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type _TaInline3> = T; +LL + type _TaInline3 = T; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias.rs:15:20 + | +LL | type _TaInline4> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type _TaInline4> = T; +LL + type _TaInline4 = T; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias.rs:16:20 + | +LL | type _TaInline5 Into<&'a u8>>> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type _TaInline5 Into<&'a u8>>> = T; +LL + type _TaInline5 = T; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias.rs:17:20 + | +LL | type _TaInline6>> = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type _TaInline6>> = T; +LL + type _TaInline6 = T; + | + +warning: 12 warnings emitted + diff --git a/tests/ui/associated-type-bounds/union-bounds.rs b/tests/ui/associated-type-bounds/union-bounds.rs new file mode 100644 index 000000000..46e5aef04 --- /dev/null +++ b/tests/ui/associated-type-bounds/union-bounds.rs @@ -0,0 +1,123 @@ +// run-pass + +#![feature(associated_type_bounds)] + +#![allow(unused_assignments)] + +trait Tr1: Copy { type As1: Copy; } +trait Tr2: Copy { type As2: Copy; } +trait Tr3: Copy { type As3: Copy; } +trait Tr4<'a>: Copy { type As4: Copy; } +trait Tr5: Copy { type As5: Copy; } + +impl Tr1 for &str { type As1 = bool; } +impl Tr2 for bool { type As2 = u8; } +impl Tr3 for u8 { type As3 = fn() -> u8; } +impl Tr1 for () { type As1 = (usize,); } +impl<'a> Tr4<'a> for (usize,) { type As4 = u8; } +impl Tr5 for bool { type As5 = u16; } + +union Un1> { + outest: T, + outer: T::As1, + inner: ::As2, +} + +union Un2>> { + outest: T, + outer: T::As1, + inner: ::As2, +} + +union Un3> { + outest: T, + outer: &'static T::As1, +} + +union Un4<'x1, 'x2, T: Tr1 Tr4<'l>>> { + f1: &'x1 >::As4, + f2: &'x2 >::As4, +} + +union _Un5<'x1, 'x2, T: Tr1 Tr4<'l, As4: Copy>>> { + f1: &'x1 >::As4, + f2: &'x2 >::As4, +} + +union Un6 +where + T: Tr1, +{ + f0: T, + f1: ::As2, + f2: &'static T::As1, + f3: ::As5, +} + +union _Un7<'a, 'b, T> // `::As2: 'a` is implied. +where + T: Tr1, +{ + f0: &'a T, + f1: &'b ::As2, +} + +unsafe fn _use_un7<'a, 'b, T>(x: _Un7<'a, 'b, T>) +where + T: Tr1, + T::As1: Tr2, +{ + let _: &'a T = &x.f0; +} + +#[derive(Copy, Clone)] +union UnSelf where Self: Tr1, T: Copy { + f0: T, + f1: ::As1, + f2: <::As1 as Tr2>::As2, +} + +impl Tr1 for UnSelf<&'static str> { type As1 = bool; } + +fn main() { + let mut un1 = Un1 { outest: "foo" }; + un1 = Un1 { outer: true }; + assert_eq!(unsafe { un1.outer }, true); + un1 = Un1 { inner: 42u8 }; + assert_eq!(unsafe { un1.inner }, 42u8); + + let mut un2 = Un2 { outest: "bar" }; + assert_eq!(unsafe { un2.outest }, "bar"); + un2 = Un2 { outer: true }; + assert_eq!(unsafe { un2.outer }, true); + un2 = Un2 { inner: 42u8 }; + assert_eq!(unsafe { un2.inner }, 42u8); + + let mut un3 = Un3 { outest: "baz" }; + assert_eq!(unsafe { un3.outest }, "baz"); + un3 = Un3 { outer: &true }; + assert_eq!(unsafe { *un3.outer }, true); + + let f1 = (1,); + let f2 = (2,); + let mut un4 = Un4::<()> { f1: &f1.0 }; + assert_eq!(1, unsafe { *un4.f1 }); + un4 = Un4 { f2: &f2.0 }; + assert_eq!(2, unsafe { *un4.f2 }); + + let mut un6 = Un6 { f0: "bar" }; + assert_eq!(unsafe { un6.f0 }, "bar"); + un6 = Un6 { f1: 24u8 }; + assert_eq!(unsafe { un6.f1 }, 24u8); + un6 = Un6 { f2: &true }; + assert_eq!(unsafe { un6.f2 }, &true); + un6 = Un6 { f3: 12u16 }; + assert_eq!(unsafe { un6.f3 }, 12u16); + + let mut unself = UnSelf::<_> { f0: "selfish" }; + assert_eq!(unsafe { unself.f0 }, "selfish"); + unself = UnSelf { f1: true }; + assert_eq!(unsafe { unself.f1 }, true); + unself = UnSelf { f2: 24u8 }; + assert_eq!(unsafe { unself.f2 }, 24u8); +} diff --git a/tests/ui/associated-types/associate-type-bound-normalization.rs b/tests/ui/associated-types/associate-type-bound-normalization.rs new file mode 100644 index 000000000..db092970f --- /dev/null +++ b/tests/ui/associated-types/associate-type-bound-normalization.rs @@ -0,0 +1,25 @@ +// Make sure that we normalize bounds on associated types before checking them +// as candidates. + +// check-pass + +trait Mul { + type Output; +} + +trait Matrix: Mul<::Row, Output = ()> { + type Row; + + type Transpose: Matrix; +} + +fn is_mul>() {} + +fn f() { + // The unnormalized bound on `T::Transpose` is + // `Mul<::Row` which has to be normalized to be + // equal to `T::Row`. + is_mul::(); +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-item-long-paths.rs b/tests/ui/associated-types/associated-item-long-paths.rs new file mode 100644 index 000000000..aad8c487c --- /dev/null +++ b/tests/ui/associated-types/associated-item-long-paths.rs @@ -0,0 +1,47 @@ +// run-pass + +use std::mem::size_of; + +// The main point of this test is to ensure that we can parse and resolve +// associated items on associated types. + +trait Foo { + type U; +} + +trait Bar { + // Note 1: Chains of associated items in a path won't type-check. + // Note 2: Associated consts can't depend on type parameters or `Self`, + // which are the only types that an associated type can be referenced on for + // now, so we can only test methods. + fn method() -> u32; + fn generic_method() -> usize; +} + +struct MyFoo; +struct MyBar; + +impl Foo for MyFoo { + type U = MyBar; +} + +impl Bar for MyBar { + fn method() -> u32 { + 2u32 + } + fn generic_method() -> usize { + size_of::() + } +} + +fn foo() + where T: Foo, + T::U: Bar, +{ + assert_eq!(2u32, ::U::method()); + assert_eq!(8usize, ::U::generic_method::()); +} + +fn main() { + foo::(); +} diff --git a/tests/ui/associated-types/associated-type-destructuring-assignment.rs b/tests/ui/associated-types/associated-type-destructuring-assignment.rs new file mode 100644 index 000000000..f038c9ce7 --- /dev/null +++ b/tests/ui/associated-types/associated-type-destructuring-assignment.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(more_qualified_paths)] + +enum E { V() } + +fn main() { + ::V() = E::V(); // OK, destructuring assignment + ::V {} = E::V(); // OK, destructuring assignment +} diff --git a/tests/ui/associated-types/associated-type-macro.rs b/tests/ui/associated-types/associated-type-macro.rs new file mode 100644 index 000000000..22b5bca40 --- /dev/null +++ b/tests/ui/associated-types/associated-type-macro.rs @@ -0,0 +1,4 @@ +fn main() { + #[cfg(FALSE)] + <() as module>::mac!(); //~ ERROR macros cannot use qualified paths +} diff --git a/tests/ui/associated-types/associated-type-macro.stderr b/tests/ui/associated-types/associated-type-macro.stderr new file mode 100644 index 000000000..6a4cf99c4 --- /dev/null +++ b/tests/ui/associated-types/associated-type-macro.stderr @@ -0,0 +1,8 @@ +error: macros cannot use qualified paths + --> $DIR/associated-type-macro.rs:3:5 + | +LL | <() as module>::mac!(); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.rs b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.rs new file mode 100644 index 000000000..c85d41c7f --- /dev/null +++ b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.rs @@ -0,0 +1,42 @@ +// Test equality constraints in a where clause where the type being +// equated appears in a supertrait. + +pub trait Vehicle { + type Color; + + fn go(&self) { } +} + +pub trait Box { + type Color; + + fn mail(&self) { } +} + +fn a(_: C::Color) { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +fn b(_: C::Color) where C : Vehicle+Box { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +fn c(_: C::Color) where C : Vehicle, C : Box { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +struct D; +impl D where X : Vehicle { + fn d(&self, _: X::Color) where X : Box { } + //~^ ERROR ambiguous associated type `Color` in bounds of `X` +} + +trait E { + fn e(&self, _: X::Color) where X : Box; + //~^ ERROR ambiguous associated type `Color` in bounds of `X` + + fn f(&self, _: X::Color) where X : Box { } + //~^ ERROR ambiguous associated type `Color` in bounds of `X` +} + +pub fn main() { } diff --git a/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr new file mode 100644 index 000000000..236552baf --- /dev/null +++ b/tests/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr @@ -0,0 +1,129 @@ +error[E0221]: ambiguous associated type `Color` in bounds of `C` + --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:16:24 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn a(_: C::Color) { + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn a(_: ::Color) { + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn a(_: ::Color) { + | ~~~~~~~~~~~~~~~~ + +error[E0221]: ambiguous associated type `Color` in bounds of `C` + --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn b(_: C::Color) where C : Vehicle+Box { + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn b(_: ::Color) where C : Vehicle+Box { + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn b(_: ::Color) where C : Vehicle+Box { + | ~~~~~~~~~~~~~~~~ + +error[E0221]: ambiguous associated type `Color` in bounds of `C` + --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn c(_: C::Color) where C : Vehicle, C : Box { + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn c(_: ::Color) where C : Vehicle, C : Box { + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn c(_: ::Color) where C : Vehicle, C : Box { + | ~~~~~~~~~~~~~~~~ + +error[E0221]: ambiguous associated type `Color` in bounds of `X` + --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn e(&self, _: X::Color) where X : Box; + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn e(&self, _: ::Color) where X : Box; + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn e(&self, _: ::Color) where X : Box; + | ~~~~~~~~~~~~~~~~ + +error[E0221]: ambiguous associated type `Color` in bounds of `X` + --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn f(&self, _: X::Color) where X : Box { } + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn f(&self, _: ::Color) where X : Box { } + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn f(&self, _: ::Color) where X : Box { } + | ~~~~~~~~~~~~~~~~ + +error[E0221]: ambiguous associated type `Color` in bounds of `X` + --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn d(&self, _: X::Color) where X : Box { } + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn d(&self, _: ::Color) where X : Box { } + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn d(&self, _: ::Color) where X : Box { } + | ~~~~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0221`. diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs new file mode 100644 index 000000000..df19332b6 --- /dev/null +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs @@ -0,0 +1,43 @@ +// Test equality constraints in a where clause where the type being +// equated appears in a supertrait. + +pub trait Vehicle { + type Color; + + fn go(&self) { } +} + +pub trait Box { + type Color; + // + fn mail(&self) { } +} + +pub trait BoxCar : Box + Vehicle { +} + +fn dent(c: C, color: C::Color) { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +fn dent_object(c: dyn BoxCar) { + //~^ ERROR ambiguous associated type + //~| ERROR the value of the associated types +} + +fn paint(c: C, d: C::Color) { + //~^ ERROR ambiguous associated type `Color` in bounds of `C` +} + +fn dent_object_2(c: dyn BoxCar) where ::Color = COLOR { + //~^ ERROR the value of the associated types + //~| ERROR equality constraints are not yet supported in `where` clauses +} + +fn dent_object_3(c: X) +where X: BoxCar, + X: Vehicle, + X: Box +{} // OK! + +pub fn main() { } diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr new file mode 100644 index 000000000..e765f9323 --- /dev/null +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -0,0 +1,100 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:46 + | +LL | fn dent_object_2(c: dyn BoxCar) where ::Color = COLOR { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information + +error[E0221]: ambiguous associated type `Color` in bounds of `C` + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:19:32 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn dent(c: C, color: C::Color) { + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn dent(c: C, color: ::Color) { + | ~~~~~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn dent(c: C, color: ::Color) { + | ~~~~~~~~~~~~ + +error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar` + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn dent_object(c: dyn BoxCar) { + | ^^^^^^^^^^^ ambiguous associated type `Color` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: BoxCar, + T: Vehicle::Color = COLOR, + T: Box::Color = COLOR + +error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:30 + | +LL | type Color; + | ---------- `Vehicle::Color` defined here +... +LL | type Color; + | ---------- `Box::Color` defined here +... +LL | fn dent_object(c: dyn BoxCar) { + | ^^^^^^^^^^^^^^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified + | + = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types + +error[E0221]: ambiguous associated type `Color` in bounds of `C` + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:28:29 + | +LL | type Color; + | ---------- ambiguous `Color` from `Vehicle` +... +LL | type Color; + | ---------- ambiguous `Color` from `Box` +... +LL | fn paint(c: C, d: C::Color) { + | ^^^^^^^^ ambiguous associated type `Color` + | +help: use fully qualified syntax to disambiguate + | +LL | fn paint(c: C, d: ::Color) { + | ~~~~~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | fn paint(c: C, d: ::Color) { + | ~~~~~~~~~~~~ + +error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32 + | +LL | type Color; + | ---------- `Vehicle::Color` defined here +... +LL | type Color; + | ---------- `Box::Color` defined here +... +LL | fn dent_object_2(c: dyn BoxCar) where ::Color = COLOR { + | ^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified + | + = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0191, E0221, E0222. +For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/associated-type-projection-from-supertrait.rs b/tests/ui/associated-types/associated-type-projection-from-supertrait.rs new file mode 100644 index 000000000..7e05bcd30 --- /dev/null +++ b/tests/ui/associated-types/associated-type-projection-from-supertrait.rs @@ -0,0 +1,36 @@ +// Test equality constraints in a where clause where the type being +// equated appears in a supertrait. + +pub trait Vehicle { + type Color; + + fn go(&self) { } +} + +pub trait Car : Vehicle { + fn honk(&self) { } + fn chip_paint(&self, c: Self::Color) { } +} + +struct Black; +struct ModelT; +impl Vehicle for ModelT { type Color = Black; } +impl Car for ModelT { } + +struct Blue; +struct ModelU; +impl Vehicle for ModelU { type Color = Blue; } +impl Car for ModelU { } + +fn dent(c: C, color: C::Color) { c.chip_paint(color) } +fn a() { dent(ModelT, Black); } +fn b() { dent(ModelT, Blue); } //~ ERROR mismatched types +fn c() { dent(ModelU, Black); } //~ ERROR mismatched types +fn d() { dent(ModelU, Blue); } + +fn e() { ModelT.chip_paint(Black); } +fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types +fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types +fn h() { ModelU.chip_paint(Blue); } + +pub fn main() { } diff --git a/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr b/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr new file mode 100644 index 000000000..d6b18d4ed --- /dev/null +++ b/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/associated-type-projection-from-supertrait.rs:27:23 + | +LL | fn b() { dent(ModelT, Blue); } + | ---- ^^^^ expected struct `Black`, found struct `Blue` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/associated-type-projection-from-supertrait.rs:25:4 + | +LL | fn dent(c: C, color: C::Color) { c.chip_paint(color) } + | ^^^^ --------------- + +error[E0308]: mismatched types + --> $DIR/associated-type-projection-from-supertrait.rs:28:23 + | +LL | fn c() { dent(ModelU, Black); } + | ---- ^^^^^ expected struct `Blue`, found struct `Black` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/associated-type-projection-from-supertrait.rs:25:4 + | +LL | fn dent(c: C, color: C::Color) { c.chip_paint(color) } + | ^^^^ --------------- + +error[E0308]: mismatched types + --> $DIR/associated-type-projection-from-supertrait.rs:32:28 + | +LL | fn f() { ModelT.chip_paint(Blue); } + | ---------- ^^^^ expected struct `Black`, found struct `Blue` + | | + | arguments to this method are incorrect + | +note: associated function defined here + --> $DIR/associated-type-projection-from-supertrait.rs:12:8 + | +LL | fn chip_paint(&self, c: Self::Color) { } + | ^^^^^^^^^^ -------------- + +error[E0308]: mismatched types + --> $DIR/associated-type-projection-from-supertrait.rs:33:28 + | +LL | fn g() { ModelU.chip_paint(Black); } + | ---------- ^^^^^ expected struct `Blue`, found struct `Black` + | | + | arguments to this method are incorrect + | +note: associated function defined here + --> $DIR/associated-type-projection-from-supertrait.rs:12:8 + | +LL | fn chip_paint(&self, c: Self::Color) { } + | ^^^^^^^^^^ -------------- + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/associated-type-struct-construction.rs b/tests/ui/associated-types/associated-type-struct-construction.rs new file mode 100644 index 000000000..f8f8048fb --- /dev/null +++ b/tests/ui/associated-types/associated-type-struct-construction.rs @@ -0,0 +1,24 @@ +// Make sure that users can construct structs through associated types +// in both expressions and patterns + +#![feature(more_qualified_paths)] + +// check-pass +fn main() { + let ::Assoc { br } = ::Assoc { br: 2 }; + assert!(br == 2); +} + +struct StructStruct { + br: i8, +} + +struct Foo; + +trait A { + type Assoc; +} + +impl A for Foo { + type Assoc = StructStruct; +} diff --git a/tests/ui/associated-types/associated-type-tuple-struct-construction.rs b/tests/ui/associated-types/associated-type-tuple-struct-construction.rs new file mode 100644 index 000000000..d5809ecd5 --- /dev/null +++ b/tests/ui/associated-types/associated-type-tuple-struct-construction.rs @@ -0,0 +1,24 @@ +// Users cannot yet construct structs through associated types +// in both expressions and patterns + +#![feature(more_qualified_paths)] + +fn main() { + let ::Assoc(n) = ::Assoc(2); + //~^ ERROR expected method or associated constant, found associated type + //~| ERROR expected method or associated constant, found associated type + assert!(n == 2); +} + +struct TupleStruct(i8); + +struct Foo; + + +trait A { + type Assoc; +} + +impl A for Foo { + type Assoc = TupleStruct; +} diff --git a/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr b/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr new file mode 100644 index 000000000..bca7deeb5 --- /dev/null +++ b/tests/ui/associated-types/associated-type-tuple-struct-construction.stderr @@ -0,0 +1,19 @@ +error[E0575]: expected method or associated constant, found associated type `A::Assoc` + --> $DIR/associated-type-tuple-struct-construction.rs:7:32 + | +LL | let ::Assoc(n) = ::Assoc(2); + | ^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor + +error[E0575]: expected method or associated constant, found associated type `A::Assoc` + --> $DIR/associated-type-tuple-struct-construction.rs:7:9 + | +LL | let ::Assoc(n) = ::Assoc(2); + | ^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0575`. diff --git a/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs new file mode 100644 index 000000000..707bcac78 --- /dev/null +++ b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.rs @@ -0,0 +1,25 @@ +// Test that we do not ICE when the self type is `ty::err`, but rather +// just propagate the error. + +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang="sized"] +pub trait Sized { + // Empty. +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, _: RHS) -> Self::Output; +} + +fn ice(a: A) { + let r = loop {}; + r = r + a; + //~^ ERROR the trait bound `(): Add` is not satisfied +} diff --git a/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr new file mode 100644 index 000000000..8c3463a28 --- /dev/null +++ b/tests/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): Add` is not satisfied + --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:23:11 + | +LL | r = r + a; + | ^ the trait `Add` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-basic.rs b/tests/ui/associated-types/associated-types-basic.rs new file mode 100644 index 000000000..b7f6721ec --- /dev/null +++ b/tests/ui/associated-types/associated-types-basic.rs @@ -0,0 +1,14 @@ +// run-pass +trait Foo { + type T; +} + +impl Foo for i32 { + type T = isize; +} + +fn main() { + let x: ::T = 22; + let y: isize = 44; + assert_eq!(x * 2, y); +} diff --git a/tests/ui/associated-types/associated-types-binding-in-trait.rs b/tests/ui/associated-types/associated-types-binding-in-trait.rs new file mode 100644 index 000000000..2e42b3a2a --- /dev/null +++ b/tests/ui/associated-types/associated-types-binding-in-trait.rs @@ -0,0 +1,36 @@ +// run-pass +// Test a case where the associated type binding (to `bool`, in this +// case) is derived from the trait definition. Issue #21636. + + +use std::vec; + +pub trait BitIter { + type Iter: Iterator; + fn bit_iter(self) -> ::Iter; +} + +impl BitIter for Vec { + type Iter = vec::IntoIter; + fn bit_iter(self) -> ::Iter { + self.into_iter() + } +} + +fn count(arg: T) -> usize + where T: BitIter +{ + let mut sum = 0; + for i in arg.bit_iter() { + if i { + sum += 1; + } + } + sum +} + +fn main() { + let v = vec![true, false, true]; + let c = count(v); + assert_eq!(c, 2); +} diff --git a/tests/ui/associated-types/associated-types-binding-in-where-clause.rs b/tests/ui/associated-types/associated-types-binding-in-where-clause.rs new file mode 100644 index 000000000..c54bc3cd6 --- /dev/null +++ b/tests/ui/associated-types/associated-types-binding-in-where-clause.rs @@ -0,0 +1,38 @@ +// run-pass +// Test equality constraints on associated types in a where clause. + +// pretty-expanded FIXME #23616 + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +#[derive(PartialEq)] +pub struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +impl Foo for char { + type A = Bar; + fn boo(&self) -> Bar { Bar } +} + +fn foo_bar>(x: I) -> Bar { + x.boo() +} + +fn foo_uint>(x: I) -> usize { + x.boo() +} + +pub fn main() { + let a = 42; + foo_uint(a); + + let a = 'a'; + foo_bar(a); +} diff --git a/tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs b/tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs new file mode 100644 index 000000000..6b2bbbe2e --- /dev/null +++ b/tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs @@ -0,0 +1,35 @@ +// Test equality constraints in a where clause where the type being +// equated appears in a supertrait. + +pub trait Vehicle { + type Color; + + fn go(&self) { } +} + +pub trait Car : Vehicle { + fn honk(&self) { } +} + +struct Black; +struct ModelT; +impl Vehicle for ModelT { type Color = Black; } +impl Car for ModelT { } + +struct Blue; +struct ModelU; +impl Vehicle for ModelU { type Color = Blue; } +impl Car for ModelU { } + +fn black_car>(c: C) { +} + +fn blue_car>(c: C) { +} + +fn a() { black_car(ModelT); } +fn b() { blue_car(ModelT); } //~ ERROR type mismatch +fn c() { black_car(ModelU); } //~ ERROR type mismatch +fn d() { blue_car(ModelU); } + +pub fn main() { } diff --git a/tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr new file mode 100644 index 000000000..a777e064f --- /dev/null +++ b/tests/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -0,0 +1,41 @@ +error[E0271]: type mismatch resolving `::Color == Blue` + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:19 + | +LL | fn b() { blue_car(ModelT); } + | -------- ^^^^^^ type mismatch resolving `::Color == Blue` + | | + | required by a bound introduced by this call + | +note: expected this to be `Blue` + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:16:40 + | +LL | impl Vehicle for ModelT { type Color = Black; } + | ^^^^^ +note: required by a bound in `blue_car` + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:27:19 + | +LL | fn blue_car>(c: C) { + | ^^^^^^^^^^ required by this bound in `blue_car` + +error[E0271]: type mismatch resolving `::Color == Black` + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:20 + | +LL | fn c() { black_car(ModelU); } + | --------- ^^^^^^ type mismatch resolving `::Color == Black` + | | + | required by a bound introduced by this call + | +note: expected this to be `Black` + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:21:40 + | +LL | impl Vehicle for ModelU { type Color = Blue; } + | ^^^^ +note: required by a bound in `black_car` + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:24:20 + | +LL | fn black_car>(c: C) { + | ^^^^^^^^^^^ required by this bound in `black_car` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-bound-ambiguity.rs b/tests/ui/associated-types/associated-types-bound-ambiguity.rs new file mode 100644 index 000000000..9f179b645 --- /dev/null +++ b/tests/ui/associated-types/associated-types-bound-ambiguity.rs @@ -0,0 +1,23 @@ +// Make sure that if there are multiple applicable bounds on a projection, we +// consider them ambiguous. In this test we are initially trying to solve +// `Self::Repr: From<_>`, which is ambiguous until we later infer `_` to +// `{integer}`. + +// check-pass + +trait PrimeField: Sized { + type Repr: From + From; + type Repr2: From + From; + + fn method() { + Self::Repr::from(10); + Self::Repr2::from(10); + } +} + +fn function() { + T::Repr::from(10); + T::Repr2::from(10); +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-bound-failure.fixed b/tests/ui/associated-types/associated-types-bound-failure.fixed new file mode 100644 index 000000000..68ee38d16 --- /dev/null +++ b/tests/ui/associated-types/associated-types-bound-failure.fixed @@ -0,0 +1,29 @@ +// run-rustfix +// Test equality constraints on associated types in a where clause. +#![allow(dead_code)] + +pub trait ToInt { + fn to_int(&self) -> isize; +} + +pub trait GetToInt +{ + type R; + + fn get(&self) -> ::R; +} + +fn foo(g: G) -> isize + where G : GetToInt, ::R: ToInt +{ + ToInt::to_int(&g.get()) //~ ERROR E0277 +} + +fn bar(g: G) -> isize + where G::R : ToInt +{ + ToInt::to_int(&g.get()) // OK +} + +pub fn main() { +} diff --git a/tests/ui/associated-types/associated-types-bound-failure.rs b/tests/ui/associated-types/associated-types-bound-failure.rs new file mode 100644 index 000000000..31e073cc7 --- /dev/null +++ b/tests/ui/associated-types/associated-types-bound-failure.rs @@ -0,0 +1,29 @@ +// run-rustfix +// Test equality constraints on associated types in a where clause. +#![allow(dead_code)] + +pub trait ToInt { + fn to_int(&self) -> isize; +} + +pub trait GetToInt +{ + type R; + + fn get(&self) -> ::R; +} + +fn foo(g: G) -> isize + where G : GetToInt +{ + ToInt::to_int(&g.get()) //~ ERROR E0277 +} + +fn bar(g: G) -> isize + where G::R : ToInt +{ + ToInt::to_int(&g.get()) // OK +} + +pub fn main() { +} diff --git a/tests/ui/associated-types/associated-types-bound-failure.stderr b/tests/ui/associated-types/associated-types-bound-failure.stderr new file mode 100644 index 000000000..3eda22796 --- /dev/null +++ b/tests/ui/associated-types/associated-types-bound-failure.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `::R: ToInt` is not satisfied + --> $DIR/associated-types-bound-failure.rs:19:19 + | +LL | ToInt::to_int(&g.get()) + | ------------- ^^^^^^^^ the trait `ToInt` is not implemented for `::R` + | | + | required by a bound introduced by this call + | +help: consider further restricting the associated type + | +LL | where G : GetToInt, ::R: ToInt + | +++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-bound.rs b/tests/ui/associated-types/associated-types-bound.rs new file mode 100644 index 000000000..0e9a229a5 --- /dev/null +++ b/tests/ui/associated-types/associated-types-bound.rs @@ -0,0 +1,43 @@ +// run-pass +// Test equality constrai32s on associated types in a where clause. + + +pub trait ToI32 { + fn to_i32(&self) -> i32; +} + +impl ToI32 for i32 { + fn to_i32(&self) -> i32 { *self } +} + +impl ToI32 for u32 { + fn to_i32(&self) -> i32 { *self as i32 } +} + +pub trait GetToI32 +{ + type R : ToI32; + + fn get(&self) -> ::R; +} + +impl GetToI32 for i32 { + type R = i32; + fn get(&self) -> i32 { *self } +} + +impl GetToI32 for u32 { + type R = u32; + fn get(&self) -> u32 { *self } +} + +fn foo(g: G) -> i32 + where G : GetToI32 +{ + ToI32::to_i32(&g.get()) +} + +pub fn main() { + assert_eq!(foo(22i32), 22); + assert_eq!(foo(22u32), 22); +} diff --git a/tests/ui/associated-types/associated-types-cc.rs b/tests/ui/associated-types/associated-types-cc.rs new file mode 100644 index 000000000..13f1d2720 --- /dev/null +++ b/tests/ui/associated-types/associated-types-cc.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_variables)] +// aux-build:associated-types-cc-lib.rs + +// Test that we are able to reference cross-crate traits that employ +// associated types. + +extern crate associated_types_cc_lib as bar; + +use bar::Bar; + +fn foo(b: B) -> ::T { + Bar::get(None::) +} + +fn main() { + println!("{}", foo(3)); +} diff --git a/tests/ui/associated-types/associated-types-coherence-failure.rs b/tests/ui/associated-types/associated-types-coherence-failure.rs new file mode 100644 index 000000000..c33f2ac96 --- /dev/null +++ b/tests/ui/associated-types/associated-types-coherence-failure.rs @@ -0,0 +1,49 @@ +// Test that coherence detects overlap when some of the types in the +// impls are projections of associated type. Issue #20624. + +use std::marker::PhantomData; +use std::ops::Deref; + +pub struct Cow<'a, B: ?Sized>(PhantomData<(&'a (),B)>); + +/// Trait for moving into a `Cow` +pub trait IntoCow<'a, B: ?Sized> { + /// Moves `self` into `Cow` + fn into_cow(self) -> Cow<'a, B>; +} + +impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { + fn into_cow(self) -> Cow<'a, B> { + Cow(PhantomData) + } +} + +impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { +//~^ ERROR E0119 + fn into_cow(self) -> Cow<'a, B> { + self + } +} + +impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { +//~^ ERROR E0119 + fn into_cow(self) -> Cow<'a, B> { + Cow(PhantomData) + } +} + +impl ToOwned for u8 { + type Owned = &'static u8; + fn to_owned(&self) -> &'static u8 { panic!() } +} + +/// A generalization of Clone to borrowed data. +pub trait ToOwned { + type Owned; + + /// Creates owned data from borrowed data, usually by copying. + fn to_owned(&self) -> Self::Owned; +} + + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr new file mode 100644 index 000000000..40c02dca3 --- /dev/null +++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr @@ -0,0 +1,21 @@ +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>` + --> $DIR/associated-types-coherence-failure.rs:21:1 + | +LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { + | ------------------------------------------------------------ first implementation here +... +LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` + +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` + --> $DIR/associated-types-coherence-failure.rs:28:1 + | +LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { + | ------------------------------------------------------------ first implementation here +... +LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/associated-types/associated-types-conditional-dispatch.rs b/tests/ui/associated-types/associated-types-conditional-dispatch.rs new file mode 100644 index 000000000..70ee60517 --- /dev/null +++ b/tests/ui/associated-types/associated-types-conditional-dispatch.rs @@ -0,0 +1,66 @@ +// run-pass +// Test that we evaluate projection predicates to winnow out +// candidates during trait selection and method resolution (#20296). +// If we don't properly winnow out candidates based on the output type +// `Target=[A]`, then the impl marked with `(*)` is seen to conflict +// with all the others. + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomData; +use std::ops::Deref; + +pub trait MyEq { + fn eq(&self, u: &U) -> bool; +} + +impl MyEq<[B]> for [A] + where A : MyEq +{ + fn eq(&self, other: &[B]) -> bool { + self.len() == other.len() && + self.iter().zip(other).all(|(a, b)| MyEq::eq(a, b)) + } +} + +// (*) This impl conflicts with everything unless the `Target=[A]` +// constraint is considered. +impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs + where A: MyEq, Lhs: Deref +{ + fn eq(&self, other: &[B; 0]) -> bool { + MyEq::eq(&**self, other) + } +} + +struct DerefWithHelper { + pub helper: H, + pub marker: PhantomData, +} + +trait Helper { + fn helper_borrow(&self) -> &T; +} + +impl Helper for Option { + fn helper_borrow(&self) -> &T { + self.as_ref().unwrap() + } +} + +impl> Deref for DerefWithHelper { + type Target = T; + + fn deref(&self) -> &T { + self.helper.helper_borrow() + } +} + +pub fn check(x: T, y: T) -> bool { + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x), + marker: PhantomData }; + d.eq(&y) +} + +pub fn main() { +} diff --git a/tests/ui/associated-types/associated-types-constant-type.rs b/tests/ui/associated-types/associated-types-constant-type.rs new file mode 100644 index 000000000..1e4c113a5 --- /dev/null +++ b/tests/ui/associated-types/associated-types-constant-type.rs @@ -0,0 +1,31 @@ +// run-pass + +trait SignedUnsigned { + type Opposite; + fn convert(self) -> Self::Opposite; +} + +impl SignedUnsigned for isize { + type Opposite = usize; + + fn convert(self) -> usize { + self as usize + } +} + +impl SignedUnsigned for usize { + type Opposite = isize; + + fn convert(self) -> isize { + self as isize + } +} + +fn get(x: isize) -> ::Opposite { + x.convert() +} + +fn main() { + let x = get(22); + assert_eq!(22, x); +} diff --git a/tests/ui/associated-types/associated-types-doubleendediterator-object.rs b/tests/ui/associated-types/associated-types-doubleendediterator-object.rs new file mode 100644 index 000000000..05498ba63 --- /dev/null +++ b/tests/ui/associated-types/associated-types-doubleendediterator-object.rs @@ -0,0 +1,19 @@ +// run-pass + +fn pairwise_sub(mut t: Box>) -> isize { + let mut result = 0; + loop { + let front = t.next(); + let back = t.next_back(); + match (front, back) { + (Some(f), Some(b)) => { result += b - f; } + _ => { return result; } + } + } +} + +fn main() { + let v = vec![1, 2, 3, 4, 5, 6]; + let r = pairwise_sub(Box::new(v.into_iter())); + assert_eq!(r, 9); +} diff --git a/tests/ui/associated-types/associated-types-duplicate-binding-in-env-hrtb.rs b/tests/ui/associated-types/associated-types-duplicate-binding-in-env-hrtb.rs new file mode 100644 index 000000000..12ca10043 --- /dev/null +++ b/tests/ui/associated-types/associated-types-duplicate-binding-in-env-hrtb.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// Check that we do not report ambiguities when equivalent predicates +// (modulo bound lifetime names) appears in the environment +// twice. Issue #21965. + +// pretty-expanded FIXME #23616 + +fn foo(t: T) -> i32 + where T : for<'a> Fn(&'a u8) -> i32, + T : for<'b> Fn(&'b u8) -> i32, +{ + t(&3) +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-duplicate-binding-in-env.rs b/tests/ui/associated-types/associated-types-duplicate-binding-in-env.rs new file mode 100644 index 000000000..9ffccd3d8 --- /dev/null +++ b/tests/ui/associated-types/associated-types-duplicate-binding-in-env.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// Check that we do not report ambiguities when the same predicate +// appears in the environment twice. Issue #21965. + +// pretty-expanded FIXME #23616 + +trait Foo { + type B; + + fn get() -> Self::B; +} + +fn foo() -> () + where T : Foo, T : Foo +{ + ::get() +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-enum-field-named.rs b/tests/ui/associated-types/associated-types-enum-field-named.rs new file mode 100644 index 000000000..896d67213 --- /dev/null +++ b/tests/ui/associated-types/associated-types-enum-field-named.rs @@ -0,0 +1,35 @@ +// run-pass +// Test associated types appearing in struct-like enum variants. + + +use self::VarValue::*; + +pub trait UnifyKey { + type Value; + fn to_index(&self) -> usize; +} + +pub enum VarValue { + Redirect { to: K }, + Root { value: K::Value, rank: usize }, +} + +fn get<'a,K:UnifyKey>,V>(table: &'a Vec>, key: &K) -> &'a Option { + match table[key.to_index()] { + VarValue::Redirect { to: ref k } => get(table, k), + VarValue::Root { value: ref v, rank: _ } => v, + } +} + +impl UnifyKey for usize { + type Value = Option; + fn to_index(&self) -> usize { *self } +} + +fn main() { + let table = vec![/* 0 */ Redirect { to: 1 }, + /* 1 */ Redirect { to: 3 }, + /* 2 */ Root { value: Some('x'), rank: 0 }, + /* 3 */ Redirect { to: 2 }]; + assert_eq!(get(&table, &0), &Some('x')); +} diff --git a/tests/ui/associated-types/associated-types-enum-field-numbered.rs b/tests/ui/associated-types/associated-types-enum-field-numbered.rs new file mode 100644 index 000000000..77ced3c07 --- /dev/null +++ b/tests/ui/associated-types/associated-types-enum-field-numbered.rs @@ -0,0 +1,35 @@ +// run-pass +// Test associated types appearing in tuple-like enum variants. + + +use self::VarValue::*; + +pub trait UnifyKey { + type Value; + fn to_index(&self) -> usize; +} + +pub enum VarValue { + Redirect(K), + Root(K::Value, usize), +} + +fn get<'a,K:UnifyKey>,V>(table: &'a Vec>, key: &K) -> &'a Option { + match table[key.to_index()] { + VarValue::Redirect(ref k) => get(table, k), + VarValue::Root(ref v, _) => v, + } +} + +impl UnifyKey for usize { + type Value = Option; + fn to_index(&self) -> usize { *self } +} + +fn main() { + let table = vec![/* 0 */ Redirect(1), + /* 1 */ Redirect(3), + /* 2 */ Root(Some('x'), 0), + /* 3 */ Redirect(2)]; + assert_eq!(get(&table, &0), &Some('x')); +} diff --git a/tests/ui/associated-types/associated-types-eq-1.rs b/tests/ui/associated-types/associated-types-eq-1.rs new file mode 100644 index 000000000..c371138ff --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-1.rs @@ -0,0 +1,13 @@ +// Test equality constraints on associated types. Check that unsupported syntax +// does not ICE. + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +fn foo2(x: I) { + let _: A = x.boo(); //~ ERROR cannot find type `A` in this scope +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-eq-1.stderr b/tests/ui/associated-types/associated-types-eq-1.stderr new file mode 100644 index 000000000..e9ace7d25 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-1.stderr @@ -0,0 +1,20 @@ +error[E0412]: cannot find type `A` in this scope + --> $DIR/associated-types-eq-1.rs:10:12 + | +LL | fn foo2(x: I) { + | - similarly named type parameter `I` defined here +LL | let _: A = x.boo(); + | ^ + | +help: a type parameter with a similar name exists + | +LL | let _: I = x.boo(); + | ~ +help: you might be missing a type parameter + | +LL | fn foo2(x: I) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/associated-types/associated-types-eq-2.rs b/tests/ui/associated-types/associated-types-eq-2.rs new file mode 100644 index 000000000..18e38d446 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-2.rs @@ -0,0 +1,19 @@ +// Test equality constraints on associated types. Check we get an error when an +// equality constraint is used in a qualified path. + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +fn baz(x: &>::A) {} +//~^ ERROR associated type bindings are not allowed here + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr new file mode 100644 index 000000000..23ee8cd23 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-2.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/associated-types-eq-2.rs:16:30 + | +LL | fn baz(x: &>::A) {} + | ^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-types/associated-types-eq-3.rs b/tests/ui/associated-types/associated-types-eq-3.rs new file mode 100644 index 000000000..f6988dcf6 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-3.rs @@ -0,0 +1,42 @@ +// Test equality constraints on associated types. Check we get type errors +// where we should. + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { + 42 + } +} + +fn foo1>(x: I) { + let _: Bar = x.boo(); +} + +fn foo2(x: I) { + let _: Bar = x.boo(); + //~^ ERROR mismatched types + //~| found associated type `::A` + //~| expected struct `Bar`, found associated type + //~| expected struct `Bar` +} + + +pub fn baz(x: &dyn Foo) { + let _: Bar = x.boo(); +} + + +pub fn main() { + let a = 42; + foo1(a); + //~^ ERROR type mismatch resolving + baz(&a); + //~^ ERROR type mismatch resolving +} diff --git a/tests/ui/associated-types/associated-types-eq-3.stderr b/tests/ui/associated-types/associated-types-eq-3.stderr new file mode 100644 index 000000000..fbe1a1ee8 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-3.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/associated-types-eq-3.rs:23:18 + | +LL | let _: Bar = x.boo(); + | --- ^^^^^^^ expected struct `Bar`, found associated type + | | + | expected due to this + | + = note: expected struct `Bar` + found associated type `::A` +help: consider constraining the associated type `::A` to `Bar` + | +LL | fn foo2>(x: I) { + | +++++++++ + +error[E0271]: type mismatch resolving `::A == Bar` + --> $DIR/associated-types-eq-3.rs:38:10 + | +LL | foo1(a); + | ---- ^ type mismatch resolving `::A == Bar` + | | + | required by a bound introduced by this call + | +note: expected this to be `Bar` + --> $DIR/associated-types-eq-3.rs:12:14 + | +LL | type A = usize; + | ^^^^^ +note: required by a bound in `foo1` + --> $DIR/associated-types-eq-3.rs:18:16 + | +LL | fn foo1>(x: I) { + | ^^^^^ required by this bound in `foo1` + +error[E0271]: type mismatch resolving `::A == Bar` + --> $DIR/associated-types-eq-3.rs:40:9 + | +LL | baz(&a); + | ^^ type mismatch resolving `::A == Bar` + | +note: expected this to be `Bar` + --> $DIR/associated-types-eq-3.rs:12:14 + | +LL | type A = usize; + | ^^^^^ + = note: required for the cast from `isize` to the object type `dyn Foo` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.rs b/tests/ui/associated-types/associated-types-eq-expr-path.rs new file mode 100644 index 000000000..143992f29 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-expr-path.rs @@ -0,0 +1,16 @@ +// Check that an associated type cannot be bound in an expression path. + +trait Foo { + type A; + fn bar() -> isize; +} + +impl Foo for isize { + type A = usize; + fn bar() -> isize { 42 } +} + +pub fn main() { + let x: isize = Foo::::bar(); + //~^ ERROR associated type bindings are not allowed here +} diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.stderr b/tests/ui/associated-types/associated-types-eq-expr-path.stderr new file mode 100644 index 000000000..bd354cf3e --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-expr-path.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/associated-types-eq-expr-path.rs:14:26 + | +LL | let x: isize = Foo::::bar(); + | ^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-types/associated-types-eq-hr.rs b/tests/ui/associated-types/associated-types-eq-hr.rs new file mode 100644 index 000000000..dc653f7f2 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-hr.rs @@ -0,0 +1,111 @@ +// Check testing of equality constraints in a higher-ranked context. + +pub trait TheTrait { + type A; + + fn get(&self, t: T) -> Self::A; +} + +struct IntStruct { + x: isize, +} + +impl<'a> TheTrait<&'a isize> for IntStruct { + type A = &'a isize; + + fn get(&self, t: &'a isize) -> &'a isize { + t + } +} + +struct UintStruct { + x: isize, +} + +impl<'a> TheTrait<&'a isize> for UintStruct { + type A = &'a usize; + + fn get(&self, t: &'a isize) -> &'a usize { + panic!() + } +} + +struct Tuple {} + +impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + type A = &'a isize; + + fn get(&self, t: (&'a isize, &'a isize)) -> &'a isize { + t.0 + } +} + +fn foo() +where + T: for<'x> TheTrait<&'x isize, A = &'x isize>, +{ + // ok for IntStruct, but not UintStruct +} + +fn bar() +where + T: for<'x> TheTrait<&'x isize, A = &'x usize>, +{ + // ok for UintStruct, but not IntStruct +} + +fn tuple_one() +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, +{ + // not ok for tuple, two lifetimes and we pick first +} + +fn tuple_two() +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, +{ + // not ok for tuple, two lifetimes and we pick second +} + +fn tuple_three() +where + T: for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>, +{ + // ok for tuple +} + +fn tuple_four() +where + T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, +{ + // not ok for tuple, two lifetimes, and lifetime matching is invariant +} + +pub fn call_foo() { + foo::(); + foo::(); //~ ERROR type mismatch +} + +pub fn call_bar() { + bar::(); //~ ERROR type mismatch + bar::(); +} + +pub fn call_tuple_one() { + tuple_one::(); +} + +pub fn call_tuple_two() { + tuple_two::(); +} + +pub fn call_tuple_three() { + tuple_three::(); +} + +pub fn call_tuple_four() { + tuple_four::(); +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr new file mode 100644 index 000000000..6cff403b3 --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -0,0 +1,47 @@ +error[E0271]: type mismatch resolving `for<'x> >::A == &'x isize` + --> $DIR/associated-types-eq-hr.rs:87:11 + | +LL | foo::(); + | ^^^^^^^^^^ type mismatch resolving `for<'x> >::A == &'x isize` + | +note: expected this to be `&isize` + --> $DIR/associated-types-eq-hr.rs:26:14 + | +LL | type A = &'a usize; + | ^^^^^^^^^ + = note: expected reference `&isize` + found reference `&usize` +note: required by a bound in `foo` + --> $DIR/associated-types-eq-hr.rs:45:36 + | +LL | fn foo() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>, + | ^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `for<'x> >::A == &'x usize` + --> $DIR/associated-types-eq-hr.rs:91:11 + | +LL | bar::(); + | ^^^^^^^^^ type mismatch resolving `for<'x> >::A == &'x usize` + | +note: expected this to be `&usize` + --> $DIR/associated-types-eq-hr.rs:14:14 + | +LL | type A = &'a isize; + | ^^^^^^^^^ + = note: expected reference `&usize` + found reference `&isize` +note: required by a bound in `bar` + --> $DIR/associated-types-eq-hr.rs:52:36 + | +LL | fn bar() + | --- required by a bound in this +LL | where +LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, + | ^^^^^^^^^^^^^ required by this bound in `bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-eq-obj.rs b/tests/ui/associated-types/associated-types-eq-obj.rs new file mode 100644 index 000000000..c202c376c --- /dev/null +++ b/tests/ui/associated-types/associated-types-eq-obj.rs @@ -0,0 +1,25 @@ +// run-pass +// Test equality constraints on associated types inside of an object type + +// pretty-expanded FIXME #23616 + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +pub struct Bar; + +impl Foo for char { + type A = Bar; + fn boo(&self) -> Bar { Bar } +} + +fn baz(x: &dyn Foo) -> Bar { + x.boo() +} + +pub fn main() { + let a = 'a'; + baz(&a); +} diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed new file mode 100644 index 000000000..80bbef174 --- /dev/null +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused_variables)] + +trait Get { + type Value; + fn get(&self) -> ::Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + //~^ ERROR the trait bound `Self: Get` is not satisfied +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs new file mode 100644 index 000000000..0f6cea8e6 --- /dev/null +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused_variables)] + +trait Get { + type Value; + fn get(&self) -> ::Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait bound `Self: Get` is not satisfied +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr new file mode 100644 index 000000000..6552c8be7 --- /dev/null +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: Get` is not satisfied + --> $DIR/associated-types-for-unimpl-trait.rs:10:40 + | +LL | fn uhoh(&self, foo: U, bar: ::Value) {} + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-from-supertrait.rs b/tests/ui/associated-types/associated-types-from-supertrait.rs new file mode 100644 index 000000000..8f40b94c0 --- /dev/null +++ b/tests/ui/associated-types/associated-types-from-supertrait.rs @@ -0,0 +1,8 @@ +// run-pass + +trait Foo: Iterator {} +trait Bar: Foo {} + +fn main() { + let _: &dyn Bar; +} diff --git a/tests/ui/associated-types/associated-types-impl-redirect.rs b/tests/ui/associated-types/associated-types-impl-redirect.rs new file mode 100644 index 000000000..8fa20cdf4 --- /dev/null +++ b/tests/ui/associated-types/associated-types-impl-redirect.rs @@ -0,0 +1,51 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_imports)] +// Test how resolving a projection interacts with inference. In this +// case, we were eagerly unifying the type variable for the iterator +// type with `I` from the where clause, ignoring the in-scope `impl` +// for `ByRef`. The right answer was to consider the result ambiguous +// until more type information was available. + +#![feature(lang_items)] +#![no_implicit_prelude] + +use std::marker::Sized; +use std::option::Option::{None, Some, self}; + +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} + +trait IteratorExt: Iterator + Sized { + fn by_ref(&mut self) -> ByRef { + ByRef(self) + } +} + +impl IteratorExt for I where I: Iterator {} + +struct ByRef<'a, I: 'a + Iterator>(&'a mut I); + +impl<'a, I: Iterator> Iterator for ByRef<'a, I> { + type Item = I::Item; + + fn next(&mut self) -> Option< ::Item > { + self.0.next() + } +} + +fn is_iterator_of>(_: &I) {} + +fn test>(mut it: I) { + is_iterator_of::(&it.by_ref()); +} + +fn test2, I2: Iterator>(mut it: I2) { + is_iterator_of::(&it) +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.rs b/tests/ui/associated-types/associated-types-in-ambiguous-context.rs new file mode 100644 index 000000000..51b53908f --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.rs @@ -0,0 +1,29 @@ +trait Get { + type Value; + fn get(&self) -> ::Value; +} + +fn get(x: T, y: U) -> Get::Value {} +//~^ ERROR ambiguous associated type + +trait Grab { + type Value; + fn grab(&self) -> Grab::Value; + //~^ ERROR ambiguous associated type + + fn get(&self) -> Get::Value; + //~^ ERROR ambiguous associated type +} + +trait Bar {} + +trait Foo where Foo::Assoc: Bar { +//~^ ERROR ambiguous associated type + type Assoc; +} + +type X = std::ops::Deref::Target; +//~^ ERROR ambiguous associated type + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr new file mode 100644 index 000000000..00856b55d --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -0,0 +1,48 @@ +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:6:36 + | +LL | fn get(x: T, y: U) -> Get::Value {} + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get(x: T, y: U) -> ::Value {} + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:20:17 + | +LL | trait Foo where Foo::Assoc: Bar { + | ^^^^^^^^^^ help: use the fully-qualified path: `::Assoc` + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:25:10 + | +LL | type X = std::ops::Deref::Target; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Deref`, you could use the fully-qualified path + | +LL | type X = ::Target; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:11:23 + | +LL | fn grab(&self) -> Grab::Value; + | ^^^^^^^^^^^ help: use the fully-qualified path: `::Value` + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:14:22 + | +LL | fn get(&self) -> Get::Value; + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get(&self) -> ::Value; + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs new file mode 100644 index 000000000..88bb5fe0a --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs @@ -0,0 +1,17 @@ +// run-pass +// Test the case where we resolve `C::Result` and the trait bound +// itself includes a `Self::Item` shorthand. +// +// Regression test for issue #33425. + +trait ParallelIterator { + type Item; + fn drive_unindexed(self, consumer: C) -> C::Result + where C: Consumer; +} + +pub trait Consumer { + type Result; +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-in-default-method.rs b/tests/ui/associated-types/associated-types-in-default-method.rs new file mode 100644 index 000000000..80ffbf585 --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-default-method.rs @@ -0,0 +1,27 @@ +// run-pass + +trait Get { + type Value; + fn get(&self) -> &::Value; + fn grab(&self) -> &::Value { + self.get() + } +} + +struct Struct { + x: isize, +} + +impl Get for Struct { + type Value = isize; + fn get(&self) -> &isize { + &self.x + } +} + +fn main() { + let s = Struct { + x: 100, + }; + assert_eq!(*s.grab(), 100); +} diff --git a/tests/ui/associated-types/associated-types-in-fn.rs b/tests/ui/associated-types/associated-types-in-fn.rs new file mode 100644 index 000000000..9c588a528 --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-fn.rs @@ -0,0 +1,28 @@ +// run-pass + +trait Get { + type Value; + fn get(&self) -> &::Value; +} + +struct Struct { + x: isize, +} + +impl Get for Struct { + type Value = isize; + fn get(&self) -> &isize { + &self.x + } +} + +fn grab(x: &T) -> &::Value { + x.get() +} + +fn main() { + let s = Struct { + x: 100, + }; + assert_eq!(*grab(&s), 100); +} diff --git a/tests/ui/associated-types/associated-types-in-impl-generics.rs b/tests/ui/associated-types/associated-types-in-impl-generics.rs new file mode 100644 index 000000000..0ddd99cbf --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-impl-generics.rs @@ -0,0 +1,36 @@ +// run-pass + +trait Get { + type Value; + fn get(&self) -> &::Value; +} + +struct Struct { + x: isize, +} + +impl Get for Struct { + type Value = isize; + fn get(&self) -> &isize { + &self.x + } +} + +trait Grab { + type U; + fn grab(&self) -> &::U; +} + +impl Grab for T { + type U = ::Value; + fn grab(&self) -> &::Value { + self.get() + } +} + +fn main() { + let s = Struct { + x: 100, + }; + assert_eq!(*s.grab(), 100); +} diff --git a/tests/ui/associated-types/associated-types-in-inherent-method.rs b/tests/ui/associated-types/associated-types-in-inherent-method.rs new file mode 100644 index 000000000..1f29e9668 --- /dev/null +++ b/tests/ui/associated-types/associated-types-in-inherent-method.rs @@ -0,0 +1,30 @@ +// run-pass + +trait Get { + type Value; + fn get(&self) -> &::Value; +} + +struct Struct { + x: isize, +} + +impl Get for Struct { + type Value = isize; + fn get(&self) -> &isize { + &self.x + } +} + +impl Struct { + fn grab(x: &T) -> &::Value { + x.get() + } +} + +fn main() { + let s = Struct { + x: 100, + }; + assert_eq!(*Struct::grab(&s), 100); +} diff --git a/tests/ui/associated-types/associated-types-incomplete-object.rs b/tests/ui/associated-types/associated-types-incomplete-object.rs new file mode 100644 index 000000000..4627dfd2b --- /dev/null +++ b/tests/ui/associated-types/associated-types-incomplete-object.rs @@ -0,0 +1,31 @@ +// Check that the user gets an error if they omit a binding from an +// object type. + +pub trait Foo { + type A; + type B; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + type B = char; + fn boo(&self) -> usize { + 42 + } +} + +pub fn main() { + let a = &42isize as &dyn Foo; + + let b = &42isize as &dyn Foo; + //~^ ERROR the value of the associated type `B` (from trait `Foo`) must be specified + + let c = &42isize as &dyn Foo; + //~^ ERROR the value of the associated type `A` (from trait `Foo`) must be specified + + let d = &42isize as &dyn Foo; + //~^ ERROR the value of the associated types `A` (from trait `Foo`), `B` (from trait +} diff --git a/tests/ui/associated-types/associated-types-incomplete-object.stderr b/tests/ui/associated-types/associated-types-incomplete-object.stderr new file mode 100644 index 000000000..32866c714 --- /dev/null +++ b/tests/ui/associated-types/associated-types-incomplete-object.stderr @@ -0,0 +1,32 @@ +error[E0191]: the value of the associated type `B` (from trait `Foo`) must be specified + --> $DIR/associated-types-incomplete-object.rs:23:30 + | +LL | type B; + | ------ `B` defined here +... +LL | let b = &42isize as &dyn Foo; + | ^^^^^^^^^^^^ help: specify the associated type: `Foo` + +error[E0191]: the value of the associated type `A` (from trait `Foo`) must be specified + --> $DIR/associated-types-incomplete-object.rs:26:30 + | +LL | type A; + | ------ `A` defined here +... +LL | let c = &42isize as &dyn Foo; + | ^^^^^^^^^^^ help: specify the associated type: `Foo` + +error[E0191]: the value of the associated types `A` (from trait `Foo`), `B` (from trait `Foo`) must be specified + --> $DIR/associated-types-incomplete-object.rs:29:30 + | +LL | type A; + | ------ `A` defined here +LL | type B; + | ------ `B` defined here +... +LL | let d = &42isize as &dyn Foo; + | ^^^ help: specify the associated types: `Foo` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs new file mode 100644 index 000000000..3bd3f3a75 --- /dev/null +++ b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.rs @@ -0,0 +1,14 @@ +// Test that we report an error if the trait ref in a qualified type +// uses invalid type arguments. + +trait Foo { + type Bar; + fn get_bar(&self) -> Self::Bar; +} + +fn f>(t: &T) { + let u: >::Bar = t.get_bar(); + //~^ ERROR the trait bound `T: Foo` is not satisfied +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr new file mode 100644 index 000000000..8fecfdf7b --- /dev/null +++ b/tests/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Foo` is not satisfied + --> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:12 + | +LL | let u: >::Bar = t.get_bar(); + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` + | +help: consider further restricting this bound + | +LL | fn f + Foo>(t: &T) { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-issue-17359.rs b/tests/ui/associated-types/associated-types-issue-17359.rs new file mode 100644 index 000000000..88a8a6490 --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-17359.rs @@ -0,0 +1,10 @@ +// Test that we do not ICE when an impl is missing an associated type (and that we report +// a useful error, of course). + +trait Trait { + type Type; +} + +impl Trait for isize {} //~ ERROR missing: `Type` + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-issue-17359.stderr b/tests/ui/associated-types/associated-types-issue-17359.stderr new file mode 100644 index 000000000..9e40d8095 --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-17359.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Type` + --> $DIR/associated-types-issue-17359.rs:8:1 + | +LL | type Type; + | --------- `Type` from trait +... +LL | impl Trait for isize {} + | ^^^^^^^^^^^^^^^^^^^^ missing `Type` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/associated-types/associated-types-issue-20220.rs b/tests/ui/associated-types/associated-types-issue-20220.rs new file mode 100644 index 000000000..19fa7a608 --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20220.rs @@ -0,0 +1,28 @@ +// run-pass +// Test references to `Self::Item` in the trait. Issue #20220. + + +use std::vec; + +trait IntoIteratorX { + type Item; + type IntoIter: Iterator; + + fn into_iter_x(self) -> Self::IntoIter; +} + +impl IntoIteratorX for Vec { + type Item = T; + type IntoIter = vec::IntoIter; + + fn into_iter_x(self) -> vec::IntoIter { + self.into_iter() + } +} + +fn main() { + let vec = vec![1, 2, 3]; + for (i, e) in vec.into_iter().enumerate() { + assert_eq!(i+1, e); + } +} diff --git a/tests/ui/associated-types/associated-types-issue-20346.rs b/tests/ui/associated-types/associated-types-issue-20346.rs new file mode 100644 index 000000000..0cce847e1 --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20346.rs @@ -0,0 +1,35 @@ +// Test that we reliably check the value of the associated type. + +#![crate_type = "lib"] +#![no_implicit_prelude] + +use std::option::Option::{self, None, Some}; +use std::vec::Vec; + +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} + +fn is_iterator_of>(_: &I) {} + +struct Adapter { + iter: I, + found_none: bool, +} + +impl Iterator for Adapter where I: Iterator> { + type Item = T; + + fn next(&mut self) -> Option { + loop {} + } +} + +fn test_adapter>>(it: I) { + is_iterator_of::, _>(&it); // Sanity check + let adapter = Adapter { iter: it, found_none: false }; + is_iterator_of::(&adapter); // OK + is_iterator_of::, _>(&adapter); //~ ERROR type mismatch +} diff --git a/tests/ui/associated-types/associated-types-issue-20346.stderr b/tests/ui/associated-types/associated-types-issue-20346.stderr new file mode 100644 index 000000000..b1708b96e --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20346.stderr @@ -0,0 +1,27 @@ +error[E0271]: type mismatch resolving ` as Iterator>::Item == Option` + --> $DIR/associated-types-issue-20346.rs:34:36 + | +LL | fn test_adapter>>(it: I) { + | - this type parameter +... +LL | is_iterator_of::, _>(&adapter); + | ------------------------------ ^^^^^^^^ type mismatch resolving ` as Iterator>::Item == Option` + | | + | required by a bound introduced by this call + | +note: expected this to be `Option` + --> $DIR/associated-types-issue-20346.rs:23:17 + | +LL | type Item = T; + | ^ + = note: expected enum `Option` + found type parameter `T` +note: required by a bound in `is_iterator_of` + --> $DIR/associated-types-issue-20346.rs:15:34 + | +LL | fn is_iterator_of>(_: &I) {} + | ^^^^^^ required by this bound in `is_iterator_of` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-issue-20371.rs b/tests/ui/associated-types/associated-types-issue-20371.rs new file mode 100644 index 000000000..ae8a8767d --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20371.rs @@ -0,0 +1,9 @@ +// run-pass +// Test that we are able to have an impl that defines an associated type +// before the actual trait. + +// pretty-expanded FIXME #23616 + +impl X for f64 { type Y = isize; } +trait X { type Y; } +fn main() {} diff --git a/tests/ui/associated-types/associated-types-issue-21212.rs b/tests/ui/associated-types/associated-types-issue-21212.rs new file mode 100644 index 000000000..ce27eac4d --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-21212.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_variables)] +// Regression test for #21212: an overflow occurred during trait +// checking where normalizing `Self::Input` led to normalizing the +// where clauses in the environment which in turn required normalizing +// `Self::Input`. + + +pub trait Parser { + type Input; + + fn parse(input: ::Input) { + panic!() + } +} + +impl

(&self, pred: P) -> Splits where P: FnMut(&T) -> bool { + loop {} + } + + fn splitn2

(&self, n: u32, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + SliceExt2::split2(self, pred); + loop {} + } +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs new file mode 100644 index 000000000..dcfae0f37 --- /dev/null +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(unused_variables)] +// Test that we normalize associated types that appear in bounds; if +// we didn't, the call to `self.split2()` fails to type check. + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomData; + +struct Splits<'a, T, P>(PhantomData<(&'a(),T,P)>); +struct SplitsN(PhantomData); + +trait SliceExt2 { + type Item; + + fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn2<'a, P>(&'a self, n: usize, pred: P) -> SplitsN> + where P: FnMut(&Self::Item) -> bool; +} + +impl SliceExt2 for [T] { + type Item = T; + + fn split2

(&self, pred: P) -> Splits where P: FnMut(&T) -> bool { + loop {} + } + + fn splitn2

(&self, n: usize, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + self.split2(pred); + loop {} + } +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-normalize-unifield-struct.rs b/tests/ui/associated-types/associated-types-normalize-unifield-struct.rs new file mode 100644 index 000000000..a04525dcd --- /dev/null +++ b/tests/ui/associated-types/associated-types-normalize-unifield-struct.rs @@ -0,0 +1,24 @@ +// run-pass +// Regression test for issue #21010: Normalize associated types in +// various special paths in the `type_is_immediate` function. + +pub trait OffsetState: Sized {} +pub trait Offset { + type State: OffsetState; + fn dummy(&self) { } +} + +#[derive(Copy, Clone)] pub struct X; +impl Offset for X { type State = Y; } + +#[derive(Copy, Clone)] pub struct Y; +impl OffsetState for Y {} + +pub fn now() -> DateTime { from_utc(Y) } + +pub struct DateTime { pub offset: Off::State } +pub fn from_utc(offset: Off::State) -> DateTime { DateTime { offset: offset } } + +pub fn main() { + let _x = now(); +} diff --git a/tests/ui/associated-types/associated-types-outlives.rs b/tests/ui/associated-types/associated-types-outlives.rs new file mode 100644 index 000000000..55c276280 --- /dev/null +++ b/tests/ui/associated-types/associated-types-outlives.rs @@ -0,0 +1,28 @@ +// Regression test for issue #24622. The older associated types code +// was erroneously assuming that all projections outlived the current +// fn body, causing this (invalid) code to be accepted. + +pub trait Foo<'a> { + type Bar; +} + +impl<'a, T:'a> Foo<'a> for T { + type Bar = &'a T; +} + +fn denormalise<'a, T>(t: &'a T) -> >::Bar { + t +} + +pub fn free_and_use Foo<'a>, + F: for<'a> FnOnce(>::Bar)>(x: T, f: F) { + let y; + 'body: loop { // lifetime annotations added for clarity + 's: loop { y = denormalise(&x); break } + drop(x); //~ ERROR cannot move out of `x` because it is borrowed + return f(y); + } +} + +pub fn main() { +} diff --git a/tests/ui/associated-types/associated-types-outlives.stderr b/tests/ui/associated-types/associated-types-outlives.stderr new file mode 100644 index 000000000..840e33b4b --- /dev/null +++ b/tests/ui/associated-types/associated-types-outlives.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/associated-types-outlives.rs:22:14 + | +LL | 's: loop { y = denormalise(&x); break } + | -- borrow of `x` occurs here +LL | drop(x); + | ^ move out of `x` occurs here +LL | return f(y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.rs b/tests/ui/associated-types/associated-types-overridden-binding-2.rs new file mode 100644 index 000000000..fed60ccf0 --- /dev/null +++ b/tests/ui/associated-types/associated-types-overridden-binding-2.rs @@ -0,0 +1,8 @@ +#![feature(trait_alias)] + +trait I32Iterator = Iterator; + +fn main() { + let _: &dyn I32Iterator = &vec![42].into_iter(); + //~^ ERROR expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` +} diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr new file mode 100644 index 000000000..a28a0b74e --- /dev/null +++ b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -0,0 +1,11 @@ +error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` + --> $DIR/associated-types-overridden-binding-2.rs:6:43 + | +LL | let _: &dyn I32Iterator = &vec![42].into_iter(); + | ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` + | + = note: required for the cast from `std::vec::IntoIter` to the object type `dyn Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-overridden-binding.rs b/tests/ui/associated-types/associated-types-overridden-binding.rs new file mode 100644 index 000000000..9a64a06c3 --- /dev/null +++ b/tests/ui/associated-types/associated-types-overridden-binding.rs @@ -0,0 +1,11 @@ +#![feature(trait_alias)] + +trait Foo: Iterator {} +trait Bar: Foo {} //~ ERROR type annotations needed + +trait I32Iterator = Iterator; +trait U32Iterator = I32Iterator; //~ ERROR type annotations needed + +fn main() { + let _: &dyn I32Iterator; +} diff --git a/tests/ui/associated-types/associated-types-overridden-binding.stderr b/tests/ui/associated-types/associated-types-overridden-binding.stderr new file mode 100644 index 000000000..dc087e418 --- /dev/null +++ b/tests/ui/associated-types/associated-types-overridden-binding.stderr @@ -0,0 +1,27 @@ +error[E0284]: type annotations needed: cannot satisfy `::Item == i32` + --> $DIR/associated-types-overridden-binding.rs:4:12 + | +LL | trait Bar: Foo {} + | ^^^^^^^^^^^^^^^ cannot satisfy `::Item == i32` + | +note: required by a bound in `Foo` + --> $DIR/associated-types-overridden-binding.rs:3:21 + | +LL | trait Foo: Iterator {} + | ^^^^^^^^^^ required by this bound in `Foo` + +error[E0284]: type annotations needed: cannot satisfy `::Item == i32` + --> $DIR/associated-types-overridden-binding.rs:7:21 + | +LL | trait U32Iterator = I32Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `::Item == i32` + | +note: required by a bound in `I32Iterator` + --> $DIR/associated-types-overridden-binding.rs:6:30 + | +LL | trait I32Iterator = Iterator; + | ^^^^^^^^^^ required by this bound in `I32Iterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/associated-types/associated-types-overridden-default.rs b/tests/ui/associated-types/associated-types-overridden-default.rs new file mode 100644 index 000000000..3e12c9228 --- /dev/null +++ b/tests/ui/associated-types/associated-types-overridden-default.rs @@ -0,0 +1,22 @@ +// check-pass + +// Before RFC 2532, overriding one assoc. type default required overriding all +// provided defaults. + +#![feature(associated_type_defaults)] + +pub trait Tr { + type Assoc = u8; + type Assoc2 = Self::Assoc; + const C: u8 = 11; + fn foo(&self) {} +} + +impl Tr for () { + type Assoc = (); +} + +fn main() { + let _: <() as Tr>::Assoc = (); + let _: <() as Tr>::Assoc2 = (); +} diff --git a/tests/ui/associated-types/associated-types-path-1.rs b/tests/ui/associated-types/associated-types-path-1.rs new file mode 100644 index 000000000..46a5c9e7c --- /dev/null +++ b/tests/ui/associated-types/associated-types-path-1.rs @@ -0,0 +1,13 @@ +// Test that we have one and only one associated type per ref. + +pub trait Foo { + type A; +} +pub trait Bar { + type A; +} + +pub fn f1(a: T, x: T::A) {} //~ERROR associated type `A` not found +pub fn f2(a: T, x: T::A) {} //~ERROR ambiguous associated type `A` + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr new file mode 100644 index 000000000..a67f77e37 --- /dev/null +++ b/tests/ui/associated-types/associated-types-path-1.stderr @@ -0,0 +1,31 @@ +error[E0220]: associated type `A` not found for `T` + --> $DIR/associated-types-path-1.rs:10:26 + | +LL | pub fn f1(a: T, x: T::A) {} + | ^ associated type `A` not found + +error[E0221]: ambiguous associated type `A` in bounds of `T` + --> $DIR/associated-types-path-1.rs:11:34 + | +LL | type A; + | ------ ambiguous `A` from `Foo` +... +LL | type A; + | ------ ambiguous `A` from `Bar` +... +LL | pub fn f2(a: T, x: T::A) {} + | ^^^^ ambiguous associated type `A` + | +help: use fully qualified syntax to disambiguate + | +LL | pub fn f2(a: T, x: ::A) {} + | ~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | pub fn f2(a: T, x: ::A) {} + | ~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0220, E0221. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-types/associated-types-path-2.rs b/tests/ui/associated-types/associated-types-path-2.rs new file mode 100644 index 000000000..00066efcc --- /dev/null +++ b/tests/ui/associated-types/associated-types-path-2.rs @@ -0,0 +1,48 @@ +// Test type checking of uses of associated types via sugary paths. + +pub trait Foo { + type A; + + fn dummy(&self) { } +} + +impl Foo for i32 { + type A = u32; +} + +pub fn f1(a: T, x: T::A) {} +pub fn f2(a: T) -> T::A { + panic!(); +} + +pub fn f1_int_int() { + f1(2i32, 4i32); + //~^ ERROR mismatched types + //~| expected `u32`, found `i32` +} + +pub fn f1_int_uint() { + f1(2i32, 4u32); +} + +pub fn f1_uint_uint() { + f1(2u32, 4u32); + //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied +} + +pub fn f1_uint_int() { + f1(2u32, 4i32); + //~^ ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied + //~| ERROR `u32: Foo` is not satisfied +} + +pub fn f2_int() { + let _: i32 = f2(2i32); + //~^ ERROR mismatched types + //~| expected `i32`, found `u32` +} + +pub fn main() { } diff --git a/tests/ui/associated-types/associated-types-path-2.stderr b/tests/ui/associated-types/associated-types-path-2.stderr new file mode 100644 index 000000000..206f49024 --- /dev/null +++ b/tests/ui/associated-types/associated-types-path-2.stderr @@ -0,0 +1,97 @@ +error[E0308]: mismatched types + --> $DIR/associated-types-path-2.rs:19:14 + | +LL | f1(2i32, 4i32); + | -- ^^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/associated-types-path-2.rs:13:8 + | +LL | pub fn f1(a: T, x: T::A) {} + | ^^ ------- +help: change the type of the numeric literal from `i32` to `u32` + | +LL | f1(2i32, 4u32); + | ~~~ + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:29:8 + | +LL | f1(2u32, 4u32); + | -- ^^^^ the trait `Foo` is not implemented for `u32` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is implemented for `i32` +note: required by a bound in `f1` + --> $DIR/associated-types-path-2.rs:13:14 + | +LL | pub fn f1(a: T, x: T::A) {} + | ^^^ required by this bound in `f1` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:29:5 + | +LL | f1(2u32, 4u32); + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` + | + = help: the trait `Foo` is implemented for `i32` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:29:14 + | +LL | f1(2u32, 4u32); + | ^^^^ the trait `Foo` is not implemented for `u32` + | + = help: the trait `Foo` is implemented for `i32` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:36:8 + | +LL | f1(2u32, 4i32); + | -- ^^^^ the trait `Foo` is not implemented for `u32` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is implemented for `i32` +note: required by a bound in `f1` + --> $DIR/associated-types-path-2.rs:13:14 + | +LL | pub fn f1(a: T, x: T::A) {} + | ^^^ required by this bound in `f1` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:36:5 + | +LL | f1(2u32, 4i32); + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` + | + = help: the trait `Foo` is implemented for `i32` + +error[E0277]: the trait bound `u32: Foo` is not satisfied + --> $DIR/associated-types-path-2.rs:36:14 + | +LL | f1(2u32, 4i32); + | ^^^^ the trait `Foo` is not implemented for `u32` + | + = help: the trait `Foo` is implemented for `i32` + +error[E0308]: mismatched types + --> $DIR/associated-types-path-2.rs:43:18 + | +LL | let _: i32 = f2(2i32); + | --- ^^^^^^^^ expected `i32`, found `u32` + | | + | expected due to this + | +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | let _: i32 = f2(2i32).try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs new file mode 100644 index 000000000..069bf5600 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.rs @@ -0,0 +1,27 @@ +// Check projection of an associated type out of a higher-ranked +// trait-bound in the context of a function body. + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo<'a, I : for<'x> Foo<&'x isize>>( + x: >::A) +{ + let y: I::A = x; +} + +fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( + x: >::A, + y: >::A, + cond: bool) +{ + // x and y here have two distinct lifetimes: + let z: I::A = if cond { x } else { y }; + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr new file mode 100644 index 000000000..e12d42e5e --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr @@ -0,0 +1,30 @@ +error: lifetime may not live long enough + --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:29 + | +LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let z: I::A = if cond { x } else { y }; + | ^ assignment requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:40 + | +LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let z: I::A = if cond { x } else { y }; + | ^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.fixed b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.fixed new file mode 100644 index 000000000..bca69a976 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.fixed @@ -0,0 +1,37 @@ +#![allow(dead_code, unused_variables)] +// run-rustfix +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a function signature. + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo2 Foo<&'x isize>>( + x: >::A) + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters +{ + // This case is illegal because we have to instantiate `'x`, and + // we don't know what region to instantiate it with. + // + // This could perhaps be made equivalent to the examples below, + // specifically for fn signatures. +} + +fn foo3 Foo<&'x isize>>( + x: >::A) +{ + // OK, in this case we spelled out the precise regions involved, though we left one of + // them anonymous. +} + +fn foo4<'a, I : for<'x> Foo<&'x isize>>( + x: >::A) +{ + // OK, in this case we spelled out the precise regions involved. +} + + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs new file mode 100644 index 000000000..1e23dd889 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.rs @@ -0,0 +1,37 @@ +#![allow(dead_code, unused_variables)] +// run-rustfix +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a function signature. + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo2 Foo<&'x isize>>( + x: I::A) + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters +{ + // This case is illegal because we have to instantiate `'x`, and + // we don't know what region to instantiate it with. + // + // This could perhaps be made equivalent to the examples below, + // specifically for fn signatures. +} + +fn foo3 Foo<&'x isize>>( + x: >::A) +{ + // OK, in this case we spelled out the precise regions involved, though we left one of + // them anonymous. +} + +fn foo4<'a, I : for<'x> Foo<&'x isize>>( + x: >::A) +{ + // OK, in this case we spelled out the precise regions involved. +} + + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr new file mode 100644 index 000000000..c508006c3 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr @@ -0,0 +1,14 @@ +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-fn.rs:13:8 + | +LL | x: I::A) + | ^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | x: >::A) + | ~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0212`. diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs b/tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs new file mode 100644 index 000000000..ed30d86cb --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs @@ -0,0 +1,39 @@ +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a struct definition. + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +struct SomeStruct Foo<&'x isize>> { + field: I::A + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters +} + +enum SomeEnum<'b, I: for<'a> Foo<&'a isize>> { + TupleVariant(I::A), + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters + StructVariant { field: I::A }, + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters + OkVariant(&'b usize), +} + +// FIXME(eddyb) This one doesn't even compile because of the unsupported syntax. + +// struct AnotherStruct Foo<&'x isize>> { +// field: Foo<&'y isize>>::A +// } + +struct YetAnotherStruct<'a, I: for<'x> Foo<&'x isize>> { + field: >::A, +} + +struct Why<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, + 'y, 'z, 'aa, I: for<'l, 'm> Foo<&'l &'m isize>> { + field: I::A, + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr new file mode 100644 index 000000000..62a619723 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr @@ -0,0 +1,54 @@ +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-struct.rs:11:12 + | +LL | field: I::A + | ^^^^ + | +help: use a fully qualified path with explicit lifetimes + | +LL ~ struct SomeStruct<'a, I: for<'x> Foo<&'x isize>> { +LL ~ field: >::A + | + +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-struct.rs:16:18 + | +LL | TupleVariant(I::A), + | ^^^^ + | +help: use a fully qualified path with explicit lifetimes + | +LL ~ enum SomeEnum<'c, 'b, I: for<'a> Foo<&'a isize>> { +LL ~ TupleVariant(>::A), + | + +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-struct.rs:18:28 + | +LL | StructVariant { field: I::A }, + | ^^^^ + | +help: use a fully qualified path with explicit lifetimes + | +LL ~ enum SomeEnum<'c, 'b, I: for<'a> Foo<&'a isize>> { +LL | TupleVariant(I::A), +LL | +LL ~ StructVariant { field: >::A }, + | + +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-struct.rs:35:12 + | +LL | field: I::A, + | ^^^^ + | +help: use a fully qualified path with explicit lifetimes + | +LL ~ struct Why<'bb, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, +LL | 'y, 'z, 'aa, I: for<'l, 'm> Foo<&'l &'m isize>> { +LL ~ field: >::A, + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0212`. diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.fixed b/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.fixed new file mode 100644 index 000000000..66d8613f1 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.fixed @@ -0,0 +1,38 @@ +#![allow(dead_code)] +// run-rustfix +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a method definition in a trait. + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +trait SomeTrait Foo<&'x isize>> { + fn some_method(&self, arg: >::A); + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters +} + +trait AnotherTrait Foo<&'x isize>> { + fn some_method(&self, arg: >::A); +} + +trait YetAnotherTrait Foo<&'x isize>> { + fn some_method<'a>(&self, arg: >::A); +} + +trait Banana<'a> { + type Assoc: Default; +} + +struct Peach(std::marker::PhantomData); + +impl Banana<'a>> Peach { + fn mango(&self) -> >::Assoc { + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters + Default::default() + } +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs b/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs new file mode 100644 index 000000000..0a1b29de1 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.rs @@ -0,0 +1,38 @@ +#![allow(dead_code)] +// run-rustfix +// Check projection of an associated type out of a higher-ranked trait-bound +// in the context of a method definition in a trait. + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +trait SomeTrait Foo<&'x isize>> { + fn some_method(&self, arg: I::A); + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters +} + +trait AnotherTrait Foo<&'x isize>> { + fn some_method(&self, arg: >::A); +} + +trait YetAnotherTrait Foo<&'x isize>> { + fn some_method<'a>(&self, arg: >::A); +} + +trait Banana<'a> { + type Assoc: Default; +} + +struct Peach(std::marker::PhantomData); + +impl Banana<'a>> Peach { + fn mango(&self) -> X::Assoc { + //~^ ERROR cannot use the associated type of a trait with uninferred generic parameters + Default::default() + } +} + +pub fn main() {} diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr new file mode 100644 index 000000000..48433b152 --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr @@ -0,0 +1,25 @@ +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:13:32 + | +LL | fn some_method(&self, arg: I::A); + | ^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | fn some_method(&self, arg: >::A); + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0212]: cannot use the associated type of a trait with uninferred generic parameters + --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:32:24 + | +LL | fn mango(&self) -> X::Assoc { + | ^^^^^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | fn mango(&self) -> >::Assoc { + | ~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0212`. diff --git a/tests/ui/associated-types/associated-types-project-from-type-param-via-bound-in-where.rs b/tests/ui/associated-types/associated-types-project-from-type-param-via-bound-in-where.rs new file mode 100644 index 000000000..fc1dba97d --- /dev/null +++ b/tests/ui/associated-types/associated-types-project-from-type-param-via-bound-in-where.rs @@ -0,0 +1,98 @@ +// run-pass +// Various uses of `T::Item` syntax where the bound that supplies +// `Item` originates in a where-clause, not the declaration of +// `T`. Issue #20300. + +use std::marker::{PhantomData}; +use std::sync::atomic::{AtomicUsize}; +use std::sync::atomic::Ordering::SeqCst; + +static COUNTER: AtomicUsize = AtomicUsize::new(0); + +// Preamble. +trait Trait { type Item; } +struct Struct; +impl Trait for Struct { + type Item = u32; +} + +// Where-clause attached on the method which declares `T`. +struct A; +impl A { + fn foo(_x: T::Item) where T: Trait { + COUNTER.fetch_add(1, SeqCst); + } +} + +// Where-clause attached on the method to a parameter from the struct. +struct B(PhantomData); +impl B { + fn foo(_x: T::Item) where T: Trait { + COUNTER.fetch_add(10, SeqCst); + } +} + +// Where-clause attached to free fn. +fn c(_: T::Item) where T : Trait { + COUNTER.fetch_add(100, SeqCst); +} + +// Where-clause attached to defaulted and non-defaulted trait method. +trait AnotherTrait { + fn method(&self, _: T::Item) where T: Trait; + fn default_method(&self, _: T::Item) where T: Trait { + COUNTER.fetch_add(1000, SeqCst); + } +} +struct D; +impl AnotherTrait for D { + fn method(&self, _: T::Item) where T: Trait { + COUNTER.fetch_add(10000, SeqCst); + } +} + +// Where-clause attached to trait and impl containing the method. +trait YetAnotherTrait + where T : Trait +{ + fn method(&self, _: T::Item); + fn default_method(&self, _: T::Item) { + COUNTER.fetch_add(100000, SeqCst); + } +} +struct E(PhantomData); +impl YetAnotherTrait for E + where T : Trait +{ + fn method(&self, _: T::Item) { + COUNTER.fetch_add(1000000, SeqCst); + } +} + +// Where-clause attached to inherent impl containing the method. +struct F(PhantomData); +impl F where T : Trait { + fn method(&self, _: T::Item) { + COUNTER.fetch_add(10000000, SeqCst); + } +} + +// Where-clause attached to struct. +#[allow(dead_code)] +struct G where T : Trait { + data: T::Item, + phantom: PhantomData, +} + +fn main() { + A::foo::(22); + B::::foo(22); + c::(22); + D.method::(22); + D.default_method::(22); + E(PhantomData::).method(22); + E(PhantomData::).default_method(22); + F(PhantomData::).method(22); + G:: { data: 22, phantom: PhantomData }; + assert_eq!(COUNTER.load(SeqCst), 11111111); +} diff --git a/tests/ui/associated-types/associated-types-projection-bound-ambiguity.rs b/tests/ui/associated-types/associated-types-projection-bound-ambiguity.rs new file mode 100644 index 000000000..353f82e7c --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-bound-ambiguity.rs @@ -0,0 +1,16 @@ +// Check that if we have multiple applicable projection bounds we pick one (for +// backwards compatibility reasons). + +// check-pass +use std::ops::Mul; + +trait A { + type V; + type U: Mul + Mul<(), Output = ()>; +} + +fn g>() { + let y: >::Output = (); +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs new file mode 100644 index 000000000..107e6b4ce --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_variables)] +// Test that we correctly handle projection bounds appearing in the +// supertrait list (and in conjunction with overloaded operators). In +// this case, the `Result=Self` binding in the supertrait listing of +// `Int` was being ignored. + +trait Not { + type Result; + + fn not(self) -> Self::Result; +} + +trait Int: Not + Sized { + fn count_ones(self) -> usize; + fn count_zeros(self) -> usize { + // neither works + let x: Self = self.not(); + 0 + } +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs new file mode 100644 index 000000000..a59c327be --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs @@ -0,0 +1,38 @@ +// run-pass +// Test where the impl self type uses a projection from a constant type. + + +trait Int +{ + type T; + + fn dummy(&self) { } +} + +trait NonZero +{ + fn non_zero(self) -> bool; +} + +impl Int for i32 { type T = i32; } +impl Int for i64 { type T = i64; } +impl Int for u32 { type T = u32; } +impl Int for u64 { type T = u64; } + +impl NonZero for ::T { fn non_zero(self) -> bool { self != 0 } } +impl NonZero for ::T { fn non_zero(self) -> bool { self != 0 } } +impl NonZero for ::T { fn non_zero(self) -> bool { self != 0 } } +impl NonZero for ::T { fn non_zero(self) -> bool { self != 0 } } + +fn main () +{ + assert!(NonZero::non_zero(22_i32)); + assert!(NonZero::non_zero(22_i64)); + assert!(NonZero::non_zero(22_u32)); + assert!(NonZero::non_zero(22_u64)); + + assert!(!NonZero::non_zero(0_i32)); + assert!(!NonZero::non_zero(0_i64)); + assert!(!NonZero::non_zero(0_u32)); + assert!(!NonZero::non_zero(0_u64)); +} diff --git a/tests/ui/associated-types/associated-types-projection-in-object-type.rs b/tests/ui/associated-types/associated-types-projection-in-object-type.rs new file mode 100644 index 000000000..eec95a141 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-in-object-type.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +// Corrected regression test for #20831. The original did not compile. +// When fixed, it revealed another problem concerning projections that +// appear in associated type bindings in object types, which were not +// being properly flagged. + +// pretty-expanded FIXME #23616 + +use std::ops::{Shl, Shr}; +use std::cell::RefCell; + +pub trait Subscriber { + type Input; + + fn dummy(&self) { } +} + +pub trait Publisher<'a> { + type Output; + fn subscribe(&mut self, _: Box + 'a>); +} + +pub trait Processor<'a> : Subscriber + Publisher<'a> { } + +impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { } + +struct MyStruct<'a> { + sub: Box + 'a> +} + +impl<'a> Publisher<'a> for MyStruct<'a> { + type Output = u64; + fn subscribe(&mut self, t : Box + 'a>) { + self.sub = t; + } +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-projection-in-supertrait.rs b/tests/ui/associated-types/associated-types-projection-in-supertrait.rs new file mode 100644 index 000000000..ead405fcf --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-in-supertrait.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(dead_code)] +// Test that we are handle to correctly handle a projection type +// that appears in a supertrait bound. Issue #20559. + + +trait A +{ + type TA; + + fn dummy(&self) { } +} + +trait B +{ + fn foo (&self, t : TB) -> String; +} + +trait C : B<::TA> { } + +struct X; + +impl A for X +{ + type TA = i32; +} + +struct Y; + +impl C for Y { } + +// Both of these impls are required for successful compilation +impl B for Y +{ + fn foo (&self, t : i32) -> String + { + format!("First {}", t) + } +} + +fn main () +{ + let y = Y; + assert_eq!(y.foo(5), format!("First 5")); +} diff --git a/tests/ui/associated-types/associated-types-projection-in-where-clause.rs b/tests/ui/associated-types/associated-types-projection-in-where-clause.rs new file mode 100644 index 000000000..e9a26e53c --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-in-where-clause.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test a where clause that uses a non-normalized projection type. + +// pretty-expanded FIXME #23616 + +trait Int +{ + type T; + + fn dummy(&self) { } +} + +trait NonZero +{ + fn non_zero(self) -> bool; +} + +fn foo,J>(t: I) -> bool + where ::T : NonZero + // ^~~~~~~~~~~~~ canonical form is just J +{ + bar::() +} + +fn bar() -> bool { true } + +fn main () +{ +} diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed new file mode 100644 index 000000000..9bc308465 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -0,0 +1,30 @@ +// run-rustfix +// Check that we get an error when you use `::Value` in +// the trait definition even if there is no default method. + +trait Get { + type Value; +} + +trait Other { + fn okay(&self, foo: U, bar: ::Value) where Self: Get; + //~^ ERROR E0277 +} + +impl Get for () { + type Value = f32; +} + +impl Get for f64 { + type Value = u32; +} + +impl Other for () { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +impl Other for f64 { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs new file mode 100644 index 000000000..549fc8fc6 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs @@ -0,0 +1,30 @@ +// run-rustfix +// Check that we get an error when you use `::Value` in +// the trait definition even if there is no default method. + +trait Get { + type Value; +} + +trait Other { + fn okay(&self, foo: U, bar: ::Value); + //~^ ERROR E0277 +} + +impl Get for () { + type Value = f32; +} + +impl Get for f64 { + type Value = u32; +} + +impl Other for () { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +impl Other for f64 { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr new file mode 100644 index 000000000..2e67c2194 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: Get` is not satisfied + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 + | +LL | fn okay(&self, foo: U, bar: ::Value); + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn okay(&self, foo: U, bar: ::Value) where Self: Get; + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs new file mode 100644 index 000000000..3b8c8c019 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs @@ -0,0 +1,35 @@ +// run-pass +// Check that we do not get an error when you use `::Value` in +// the trait definition if there is no default method and for every impl, +// `Self` does implement `Get`. +// +// See also tests associated-types-no-suitable-supertrait +// and associated-types-no-suitable-supertrait-2, which show how small +// variants of the code below can fail. + +trait Get { + type Value; +} + +trait Other { + fn okay(&self, foo: U, bar: ::Value) + where Self: Get; +} + +impl Get for () { + type Value = f32; +} + +impl Get for f64 { + type Value = u32; +} + +impl Other for () { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +impl Other for f64 { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs new file mode 100644 index 000000000..3c830d370 --- /dev/null +++ b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Foo { + type Bar; + fn get_bar() -> >::Bar; +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-ref-from-struct.rs b/tests/ui/associated-types/associated-types-ref-from-struct.rs new file mode 100644 index 000000000..c89f6046e --- /dev/null +++ b/tests/ui/associated-types/associated-types-ref-from-struct.rs @@ -0,0 +1,51 @@ +// run-pass +// Test associated type references in structure fields. + +// pretty-expanded FIXME #23616 + +trait Test { + type V; + + fn test(&self, value: &Self::V) -> bool; +} + +struct TesterPair { + tester: T, + value: T::V, +} + +impl TesterPair { + fn new(tester: T, value: T::V) -> TesterPair { + TesterPair { tester: tester, value: value } + } + + fn test(&self) -> bool { + self.tester.test(&self.value) + } +} + +struct EqU32(u32); +impl Test for EqU32 { + type V = u32; + + fn test(&self, value: &u32) -> bool { + self.0 == *value + } +} + +struct EqI32(i32); +impl Test for EqI32 { + type V = i32; + + fn test(&self, value: &i32) -> bool { + self.0 == *value + } +} + +fn main() { + let tester = TesterPair::new(EqU32(22), 23); + tester.test(); + + let tester = TesterPair::new(EqI32(22), 23); + tester.test(); +} diff --git a/tests/ui/associated-types/associated-types-ref-in-struct-literal.rs b/tests/ui/associated-types/associated-types-ref-in-struct-literal.rs new file mode 100644 index 000000000..4a490ed03 --- /dev/null +++ b/tests/ui/associated-types/associated-types-ref-in-struct-literal.rs @@ -0,0 +1,23 @@ +// run-pass +// Test associated type references in a struct literal. Issue #20535. + + +pub trait Foo { + type Bar; + + fn dummy(&self) { } +} + +impl Foo for isize { + type Bar = isize; +} + +struct Thing { + a: F, + b: F::Bar, +} + +fn main() { + let thing = Thing{a: 1, b: 2}; + assert_eq!(thing.a + 1, thing.b); +} diff --git a/tests/ui/associated-types/associated-types-region-erasure-issue-20582.rs b/tests/ui/associated-types/associated-types-region-erasure-issue-20582.rs new file mode 100644 index 000000000..b722506db --- /dev/null +++ b/tests/ui/associated-types/associated-types-region-erasure-issue-20582.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// Regression test for #20582. This test caused an ICE related to +// inconsistent region erasure in codegen. + +// pretty-expanded FIXME #23616 + +struct Foo<'a> { + buf: &'a[u8] +} + +impl<'a> Iterator for Foo<'a> { + type Item = &'a[u8]; + + fn next(&mut self) -> Option<::Item> { + Some(self.buf) + } +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-resolve-lifetime.rs b/tests/ui/associated-types/associated-types-resolve-lifetime.rs new file mode 100644 index 000000000..52f2324d7 --- /dev/null +++ b/tests/ui/associated-types/associated-types-resolve-lifetime.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Get { + fn get(&self) -> T; +} + +trait Trait<'a> { + type T: 'static; + type U: Get<&'a isize>; + + fn dummy(&'a self) { } +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-types-return.rs b/tests/ui/associated-types/associated-types-return.rs new file mode 100644 index 000000000..997a48b03 --- /dev/null +++ b/tests/ui/associated-types/associated-types-return.rs @@ -0,0 +1,46 @@ +// run-pass +// Test equality constraints on associated types in a where clause. + + +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +#[derive(PartialEq, Debug)] +pub struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +impl Foo for Bar { + type A = isize; + fn boo(&self) -> isize { 43 } +} + +impl Foo for char { + type A = Bar; + fn boo(&self) -> Bar { Bar } +} + +fn foo1>(x: I) -> Bar { + x.boo() +} + +fn foo2(x: I) -> ::A { + x.boo() +} + +pub fn main() { + let a = 42; + assert_eq!(foo2(a), 42); + + let a = Bar; + assert_eq!(foo2(a), 43); + + let a = 'a'; + foo1(a); + assert_eq!(foo2(a), Bar); +} diff --git a/tests/ui/associated-types/associated-types-simple.rs b/tests/ui/associated-types/associated-types-simple.rs new file mode 100644 index 000000000..2e2dfd807 --- /dev/null +++ b/tests/ui/associated-types/associated-types-simple.rs @@ -0,0 +1,24 @@ +// run-pass + +trait Get { + type Value; + fn get(&self) -> &::Value; +} + +struct Struct { + x: isize, +} + +impl Get for Struct { + type Value = isize; + fn get(&self) -> &isize { + &self.x + } +} + +fn main() { + let s = Struct { + x: 100, + }; + assert_eq!(*s.get(), 100); +} diff --git a/tests/ui/associated-types/associated-types-stream.rs b/tests/ui/associated-types/associated-types-stream.rs new file mode 100644 index 000000000..c9b302b96 --- /dev/null +++ b/tests/ui/associated-types/associated-types-stream.rs @@ -0,0 +1,38 @@ +// run-pass +// Test references to the trait `Stream` in the bounds for associated +// types defined on `Stream`. Issue #20551. + +trait Stream { + type Car; + type Cdr: Stream; + + fn car(&self) -> Self::Car; + fn cdr(self) -> Self::Cdr; +} + +impl Stream for () { + type Car = (); + type Cdr = (); + fn car(&self) -> () { () } + fn cdr(self) -> () { self } +} + +impl Stream for (T, U) + where T : Clone, U : Stream +{ + type Car = T; + type Cdr = U; + fn car(&self) -> T { self.0.clone() } + fn cdr(self) -> U { self.1 } +} + +fn main() { + let p = (22, (44, (66, ()))); + assert_eq!(p.car(), 22); + + let p = p.cdr(); + assert_eq!(p.car(), 44); + + let p = p.cdr(); + assert_eq!(p.car(), 66); +} diff --git a/tests/ui/associated-types/associated-types-struct-field-named.rs b/tests/ui/associated-types/associated-types-struct-field-named.rs new file mode 100644 index 000000000..c400bf943 --- /dev/null +++ b/tests/ui/associated-types/associated-types-struct-field-named.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that we correctly normalize the type of a struct field +// which has an associated type. + + +pub trait UnifyKey { + type Value; + + fn dummy(&self) { } +} + +pub struct Node { + pub key: K, + pub value: K::Value, +} + +fn foo>,V : Clone>(node: &Node) -> Option { + node.value.clone() +} + +impl UnifyKey for i32 { + type Value = Option; +} + +impl UnifyKey for u32 { + type Value = Option; +} + +pub fn main() { + let node: Node = Node { key: 1, value: Some(22) }; + assert_eq!(foo(&node), Some(22)); + + let node: Node = Node { key: 1, value: Some(22) }; + assert_eq!(foo(&node), Some(22)); +} diff --git a/tests/ui/associated-types/associated-types-struct-field-numbered.rs b/tests/ui/associated-types/associated-types-struct-field-numbered.rs new file mode 100644 index 000000000..8612911d8 --- /dev/null +++ b/tests/ui/associated-types/associated-types-struct-field-numbered.rs @@ -0,0 +1,32 @@ +// run-pass +// Test that we correctly normalize the type of a struct field +// which has an associated type. + + +pub trait UnifyKey { + type Value; + + fn dummy(&self) { } +} + +pub struct Node(#[allow(unused_tuple_struct_fields)] K, K::Value); + +fn foo>,V : Clone>(node: &Node) -> Option { + node.1.clone() +} + +impl UnifyKey for i32 { + type Value = Option; +} + +impl UnifyKey for u32 { + type Value = Option; +} + +pub fn main() { + let node: Node = Node(1, Some(22)); + assert_eq!(foo(&node), Some(22)); + + let node: Node = Node(1, Some(22)); + assert_eq!(foo(&node), Some(22)); +} diff --git a/tests/ui/associated-types/associated-types-subtyping-1.rs b/tests/ui/associated-types/associated-types-subtyping-1.rs new file mode 100644 index 000000000..c4758f255 --- /dev/null +++ b/tests/ui/associated-types/associated-types-subtyping-1.rs @@ -0,0 +1,49 @@ +#![allow(unused_variables)] + +fn make_any() -> T { loop {} } + +trait Trait<'a> { + type Type; + + fn method(&'a self) { } +} + +fn method1<'a,'b,T>(x: &'a T, y: &'b T) + where T : for<'z> Trait<'z>, 'a : 'b +{ + // Note that &'static T <: &'a T. + let a: >::Type = make_any(); + let b: >::Type = make_any(); + let _c: >::Type = a; +} + +fn method2<'a,'b,T>(x: &'a T, y: &'b T) + where T : for<'z> Trait<'z>, 'a : 'b +{ + // Note that &'static T <: &'a T. + let a: >::Type = make_any(); + //~^ ERROR lifetime may not live long enough + let b: >::Type = make_any(); + let _c: >::Type = a; +} + +fn method3<'a,'b,T>(x: &'a T, y: &'b T) + where T : for<'z> Trait<'z>, 'a : 'b +{ + // Note that &'static T <: &'a T. + let a: >::Type = make_any(); + let b: >::Type = make_any(); + let _c: >::Type = b; + //~^ ERROR lifetime may not live long enough +} + +fn method4<'a,'b,T>(x: &'a T, y: &'b T) + where T : for<'z> Trait<'z>, 'a : 'b +{ + // Note that &'static T <: &'a T. + let a: >::Type = make_any(); + let b: >::Type = make_any(); + let _c: >::Type = b; +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-subtyping-1.stderr b/tests/ui/associated-types/associated-types-subtyping-1.stderr new file mode 100644 index 000000000..414bc048a --- /dev/null +++ b/tests/ui/associated-types/associated-types-subtyping-1.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/associated-types-subtyping-1.rs:24:12 + | +LL | fn method2<'a,'b,T>(x: &'a T, y: &'b T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let a: >::Type = make_any(); + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/associated-types-subtyping-1.rs:36:13 + | +LL | fn method3<'a,'b,T>(x: &'a T, y: &'b T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _c: >::Type = b; + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-types/associated-types-sugar-path.rs b/tests/ui/associated-types/associated-types-sugar-path.rs new file mode 100644 index 000000000..66f7672aa --- /dev/null +++ b/tests/ui/associated-types/associated-types-sugar-path.rs @@ -0,0 +1,41 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] +// Test paths to associated types using the type-parameter-only sugar. + +use std::ops::Deref; + +pub trait Foo { + type A; + fn boo(&self) -> Self::A; +} + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { + 5 + } +} + +// Using a type via a function. +pub fn bar(a: T, x: T::A) -> T::A { + let _: T::A = a.boo(); + x +} + +// Using a type via an impl. +trait C { + fn f(); + fn g(&self) { } +} +struct B(X); +impl C for B { + fn f() { + let x: T::A = panic!(); + } +} + +pub fn main() { + let z: usize = bar(2, 4); +} diff --git a/tests/ui/associated-types/associated-types-unconstrained.rs b/tests/ui/associated-types/associated-types-unconstrained.rs new file mode 100644 index 000000000..2fb27bf3c --- /dev/null +++ b/tests/ui/associated-types/associated-types-unconstrained.rs @@ -0,0 +1,16 @@ +// Check that an associated type cannot be bound in an expression path. + +trait Foo { + type A; + fn bar() -> isize; +} + +impl Foo for isize { + type A = usize; + fn bar() -> isize { 42 } +} + +pub fn main() { + let x: isize = Foo::bar(); + //~^ ERROR E0790 +} diff --git a/tests/ui/associated-types/associated-types-unconstrained.stderr b/tests/ui/associated-types/associated-types-unconstrained.stderr new file mode 100644 index 000000000..ef9b7cae0 --- /dev/null +++ b/tests/ui/associated-types/associated-types-unconstrained.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/associated-types-unconstrained.rs:14:20 + | +LL | fn bar() -> isize; + | ------------------ `Foo::bar` defined here +... +LL | let x: isize = Foo::bar(); + | ^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let x: isize = ::bar(); + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/associated-types/associated-types-unsized.fixed b/tests/ui/associated-types/associated-types-unsized.fixed new file mode 100644 index 000000000..328c8f944 --- /dev/null +++ b/tests/ui/associated-types/associated-types-unsized.fixed @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +trait Get { + type Value: ?Sized; + fn get(&self) -> ::Value; +} + +fn foo(t: T) where ::Value: Sized { + let x = t.get(); //~ ERROR the size for values of type +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-unsized.rs b/tests/ui/associated-types/associated-types-unsized.rs new file mode 100644 index 000000000..bdba4c7ff --- /dev/null +++ b/tests/ui/associated-types/associated-types-unsized.rs @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +trait Get { + type Value: ?Sized; + fn get(&self) -> ::Value; +} + +fn foo(t: T) { + let x = t.get(); //~ ERROR the size for values of type +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-unsized.stderr b/tests/ui/associated-types/associated-types-unsized.stderr new file mode 100644 index 000000000..bec9b1500 --- /dev/null +++ b/tests/ui/associated-types/associated-types-unsized.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `::Value` cannot be known at compilation time + --> $DIR/associated-types-unsized.rs:10:9 + | +LL | let x = t.get(); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `::Value` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider further restricting the associated type + | +LL | fn foo(t: T) where ::Value: Sized { + | ++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs b/tests/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs new file mode 100644 index 000000000..f2a4c6e42 --- /dev/null +++ b/tests/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs @@ -0,0 +1,46 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +// Test how resolving a projection interacts with inference. In this +// case, we were eagerly unifying the type variable for the iterator +// type with `I` from the where clause, ignoring the in-scope `impl` +// for `ByRef`. The right answer was to consider the result ambiguous +// until more type information was available. + +#![feature(lang_items)] +#![no_implicit_prelude] + +use std::marker::Sized; +use std::option::Option::{None, Some, self}; + +trait Iterator { + type Item; + + fn next(&mut self) -> Option; +} + +trait IteratorExt: Iterator + Sized { + fn by_ref(&mut self) -> ByRef { + ByRef(self) + } +} + +impl IteratorExt for I where I: Iterator {} + +struct ByRef<'a, I: 'a + Iterator>(&'a mut I); + +impl<'a, A, I> Iterator for ByRef<'a, I> where I: Iterator { + type Item = A; + + fn next(&mut self) -> Option< ::Item > { + self.0.next() + } +} + +fn is_iterator_of>(_: &I) {} + +fn test>(mut it: I) { + is_iterator_of::(&it.by_ref()); +} + +fn main() { } diff --git a/tests/ui/associated-types/auxiliary/associated-types-cc-lib.rs b/tests/ui/associated-types/auxiliary/associated-types-cc-lib.rs new file mode 100644 index 000000000..b67853587 --- /dev/null +++ b/tests/ui/associated-types/auxiliary/associated-types-cc-lib.rs @@ -0,0 +1,16 @@ +// Helper for test issue-18048, which tests associated types in a +// cross-crate scenario. + +#![crate_type="lib"] + +pub trait Bar: Sized { + type T; + + fn get(x: Option) -> ::T; +} + +impl Bar for isize { + type T = usize; + + fn get(_: Option) -> usize { 22 } +} diff --git a/tests/ui/associated-types/bound-lifetime-constrained.clause.stderr b/tests/ui/associated-types/bound-lifetime-constrained.clause.stderr new file mode 100644 index 000000000..f089f27f0 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-constrained.clause.stderr @@ -0,0 +1,15 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-constrained.rs:38:63 + | +LL | fn clause1() where T: for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32 { + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-constrained.rs:43:42 + | +LL | fn clause2() where T: for<'a> Fn() -> <() as Foo<'a>>::Item { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/associated-types/bound-lifetime-constrained.func.stderr b/tests/ui/associated-types/bound-lifetime-constrained.func.stderr new file mode 100644 index 000000000..88d15a171 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-constrained.func.stderr @@ -0,0 +1,15 @@ +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/bound-lifetime-constrained.rs:16:50 + | +LL | fn func1(_: for<'a> fn(<() as Foo<'a>>::Item) -> &'a i32) { + | ^^^^^^^ + +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/bound-lifetime-constrained.rs:23:29 + | +LL | fn func2(_: for<'a> fn() -> <() as Foo<'a>>::Item) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/associated-types/bound-lifetime-constrained.object.stderr b/tests/ui/associated-types/bound-lifetime-constrained.object.stderr new file mode 100644 index 000000000..36fa06cce --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-constrained.object.stderr @@ -0,0 +1,15 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-constrained.rs:28:60 + | +LL | fn object1(_: Box Fn(<() as Foo<'a>>::Item) -> &'a i32>) { + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-constrained.rs:33:39 + | +LL | fn object2(_: Box Fn() -> <() as Foo<'a>>::Item>) { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/associated-types/bound-lifetime-constrained.rs b/tests/ui/associated-types/bound-lifetime-constrained.rs new file mode 100644 index 000000000..4e6754c86 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-constrained.rs @@ -0,0 +1,48 @@ +// revisions: func object clause + +#![allow(dead_code)] +#![feature(rustc_attrs)] + +trait Foo<'a> { + type Item; +} + +impl<'a> Foo<'a> for() { + type Item = (); +} + +// Check that appearing in a projection input in the argument is not enough: +#[cfg(func)] +fn func1(_: for<'a> fn(<() as Foo<'a>>::Item) -> &'a i32) { + //[func]~^ ERROR E0581 +} + +// Check that appearing in a projection input in the return still +// causes an error: +#[cfg(func)] +fn func2(_: for<'a> fn() -> <() as Foo<'a>>::Item) { + //[func]~^ ERROR E0581 +} + +#[cfg(object)] +fn object1(_: Box Fn(<() as Foo<'a>>::Item) -> &'a i32>) { + //[object]~^ ERROR E0582 +} + +#[cfg(object)] +fn object2(_: Box Fn() -> <() as Foo<'a>>::Item>) { + //[object]~^ ERROR E0582 +} + +#[cfg(clause)] +fn clause1() where T: for<'a> Fn(<() as Foo<'a>>::Item) -> &'a i32 { + //[clause]~^ ERROR `Output` references lifetime `'a` +} + +#[cfg(clause)] +fn clause2() where T: for<'a> Fn() -> <() as Foo<'a>>::Item { + //[clause]~^ ERROR `Output` references lifetime `'a` +} + +#[rustc_error] +fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr new file mode 100644 index 000000000..54f4bb907 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.angle.stderr @@ -0,0 +1,27 @@ +error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:12:25 + | +LL | fn angle Foo>() { + | ^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:17:37 + | +LL | fn angle1() where T: for<'a> Foo { + | ^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:22:37 + | +LL | fn angle2() where for<'a> T: Foo { + | ^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:27:31 + | +LL | fn angle3(_: &dyn for<'a> Foo) { + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr new file mode 100644 index 000000000..4de4afb6e --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/bound-lifetime-in-binding-only.rs:52:23 + | +LL | fn elision &i32>() { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn elision &'static i32>() { + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr new file mode 100644 index 000000000..b709fae5a --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.ok.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/bound-lifetime-in-binding-only.rs:71:1 + | +LL | fn main() { } + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr b/tests/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr new file mode 100644 index 000000000..74bc84c22 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.paren.stderr @@ -0,0 +1,27 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:32:29 + | +LL | fn paren Fn() -> &'a i32>() { + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:37:41 + | +LL | fn paren1() where T: for<'a> Fn() -> &'a i32 { + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:42:41 + | +LL | fn paren2() where for<'a> T: Fn() -> &'a i32 { + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/bound-lifetime-in-binding-only.rs:47:35 + | +LL | fn paren3(_: &dyn for<'a> Fn() -> &'a i32) { + | ^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/associated-types/bound-lifetime-in-binding-only.rs b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs new file mode 100644 index 000000000..e714457ef --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-binding-only.rs @@ -0,0 +1,71 @@ +// revisions: angle paren ok elision + +#![allow(dead_code)] +#![feature(rustc_attrs)] +#![feature(unboxed_closures)] + +trait Foo { + type Item; +} + +#[cfg(angle)] +fn angle Foo>() { + //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a` +} + +#[cfg(angle)] +fn angle1() where T: for<'a> Foo { + //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a` +} + +#[cfg(angle)] +fn angle2() where for<'a> T: Foo { + //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a` +} + +#[cfg(angle)] +fn angle3(_: &dyn for<'a> Foo) { + //[angle]~^ ERROR binding for associated type `Item` references lifetime `'a` +} + +#[cfg(paren)] +fn paren Fn() -> &'a i32>() { + //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a` +} + +#[cfg(paren)] +fn paren1() where T: for<'a> Fn() -> &'a i32 { + //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a` +} + +#[cfg(paren)] +fn paren2() where for<'a> T: Fn() -> &'a i32 { + //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a` +} + +#[cfg(paren)] +fn paren3(_: &dyn for<'a> Fn() -> &'a i32) { + //[paren]~^ ERROR binding for associated type `Output` references lifetime `'a` +} + +#[cfg(elision)] +fn elision &i32>() { + //[elision]~^ ERROR E0106 +} + +struct Parameterized<'a> { x: &'a str } + +#[cfg(ok)] +fn ok1 Fn(&Parameterized<'a>) -> &'a i32>() { +} + +#[cfg(ok)] +fn ok2 Fn<(&'b Parameterized<'a>,), Output=&'a i32>>() { +} + +#[cfg(ok)] +fn ok3() where for<'a> Parameterized<'a>: Foo { +} + +#[rustc_error] +fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr new file mode 100644 index 000000000..7753d1865 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/bound-lifetime-in-return-only.rs:34:23 + | +LL | fn elision(_: fn() -> &i32) { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn elision(_: fn() -> &'static i32) { + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr new file mode 100644 index 000000000..788cf667c --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.local.stderr @@ -0,0 +1,9 @@ +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/bound-lifetime-in-return-only.rs:23:28 + | +LL | let _: for<'a> fn() -> &'a i32 = loop { }; + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr new file mode 100644 index 000000000..1c0d3ac10 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.ok.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/bound-lifetime-in-return-only.rs:49:1 + | +LL | fn main() { } + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.rs b/tests/ui/associated-types/bound-lifetime-in-return-only.rs new file mode 100644 index 000000000..a60ccb6c4 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.rs @@ -0,0 +1,49 @@ +// revisions: sig local structure ok elision + +#![allow(dead_code)] +#![feature(rustc_attrs)] +#![feature(unboxed_closures)] + +trait Foo { + type Item; +} + +#[cfg(sig)] +fn sig1(_: for<'a> fn() -> &'a i32) { + //[sig]~^ ERROR return type references lifetime `'a` +} + +#[cfg(sig)] +fn sig2(_: for<'a, 'b> fn(&'b i32) -> &'a i32) { + //[sig]~^ ERROR return type references lifetime `'a` +} + +#[cfg(local)] +fn local1() { + let _: for<'a> fn() -> &'a i32 = loop { }; + //[local]~^ ERROR return type references lifetime `'a` +} + +#[cfg(structure)] +struct Struct1 { + x: for<'a> fn() -> &'a i32 + //[structure]~^ ERROR return type references lifetime `'a` +} + +#[cfg(elision)] +fn elision(_: fn() -> &i32) { + //[elision]~^ ERROR E0106 +} + +struct Parameterized<'a> { x: &'a str } + +#[cfg(ok)] +fn ok1(_: &dyn for<'a> Fn(&Parameterized<'a>) -> &'a i32) { +} + +#[cfg(ok)] +fn ok2(_: &dyn for<'a,'b> Fn<(&'b Parameterized<'a>,), Output=&'a i32>) { +} + +#[rustc_error] +fn main() { } //[ok]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.sig.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.sig.stderr new file mode 100644 index 000000000..64dad4619 --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.sig.stderr @@ -0,0 +1,15 @@ +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/bound-lifetime-in-return-only.rs:12:28 + | +LL | fn sig1(_: for<'a> fn() -> &'a i32) { + | ^^^^^^^ + +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/bound-lifetime-in-return-only.rs:17:39 + | +LL | fn sig2(_: for<'a, 'b> fn(&'b i32) -> &'a i32) { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr b/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr new file mode 100644 index 000000000..f7833500d --- /dev/null +++ b/tests/ui/associated-types/bound-lifetime-in-return-only.structure.stderr @@ -0,0 +1,9 @@ +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/bound-lifetime-in-return-only.rs:29:24 + | +LL | x: for<'a> fn() -> &'a i32 + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/associated-types/cache/chrono-scan.rs b/tests/ui/associated-types/cache/chrono-scan.rs new file mode 100644 index 000000000..964ddc9b6 --- /dev/null +++ b/tests/ui/associated-types/cache/chrono-scan.rs @@ -0,0 +1,30 @@ +// check-pass + +#![allow(deprecated)] + +pub type ParseResult = Result; + +pub enum Item<'a> { + Literal(&'a str) +} + +pub fn colon_or_space(s: &str) -> ParseResult<&str> { + unimplemented!() +} + +pub fn timezone_offset_zulu(s: &str, colon: F) -> ParseResult<(&str, i32)> + where F: FnMut(&str) -> ParseResult<&str> { + unimplemented!() +} + +pub fn parse<'a, I>(mut s: &str, items: I) -> ParseResult<()> + where I: Iterator> { + macro_rules! try_consume { + ($e:expr) => ({ let (s_, v) = try!($e); s = s_; v }) + } + let offset = try_consume!(timezone_offset_zulu(s.trim_start(), colon_or_space)); + let offset = try_consume!(timezone_offset_zulu(s.trim_start(), colon_or_space)); + Ok(()) +} + +fn main() {} diff --git a/tests/ui/associated-types/cache/elision.rs b/tests/ui/associated-types/cache/elision.rs new file mode 100644 index 000000000..b3e1ec8ad --- /dev/null +++ b/tests/ui/associated-types/cache/elision.rs @@ -0,0 +1,23 @@ +// Check that you are allowed to implement using elision but write +// trait without elision (a bug in this cropped up during +// bootstrapping, so this is a regression test). + +// check-pass + +pub struct SplitWhitespace<'a> { + x: &'a u8 +} + +pub trait UnicodeStr { + fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>; +} + +impl UnicodeStr for str { + #[inline] + fn split_whitespace(&self) -> SplitWhitespace { + unimplemented!() + } +} + + +fn main() { } diff --git a/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr b/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr new file mode 100644 index 000000000..2ecee1341 --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-contravariant.krisskross.stderr @@ -0,0 +1,30 @@ +error: lifetime may not live long enough + --> $DIR/project-fn-ret-contravariant.rs:46:4 + | +LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/project-fn-ret-contravariant.rs:46:4 + | +LL | fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs b/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs new file mode 100644 index 000000000..f1ea6627a --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-contravariant.rs @@ -0,0 +1,50 @@ +#![feature(unboxed_closures)] + +// Test for projection cache. We should be able to project distinct +// lifetimes from `foo` as we reinstantiate it multiple times, but not +// if we do it just once. In this variant, the region `'a` is used in +// an contravariant position, which affects the results. + +// revisions: ok oneuse transmute krisskross +//[ok] check-pass +//[oneuse] check-pass + +#![allow(dead_code, unused_variables)] + +fn foo<'a>() -> &'a u32 { loop { } } + +fn bar(t: T, x: T::Output) -> T::Output + where T: FnOnce<()> +{ + t() +} + +#[cfg(ok)] // two instantiations: OK +fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + let a = bar(foo, x); + let b = bar(foo, y); + (a, b) +} + +#[cfg(oneuse)] // one instantiation: OK (surprisingly) +fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + let f /* : fn() -> &'static u32 */ = foo; // <-- inferred type annotated + let a = bar(f, x); // this is considered ok because fn args are contravariant... + let b = bar(f, y); // ...and hence we infer T to distinct values in each call. + (a, b) +} + +#[cfg(transmute)] // one instantiations: BAD +fn baz<'a,'b>(x: &'a u32) -> &'static u32 { + bar(foo, x) //[transmute]~ ERROR lifetime may not live long enough +} + +#[cfg(krisskross)] // two instantiations, mixing and matching: BAD +fn transmute<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + let a = bar(foo, y); + let b = bar(foo, x); + (a, b) //[krisskross]~ ERROR lifetime may not live long enough + //[krisskross]~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr new file mode 100644 index 000000000..6d8ab2c3f --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/project-fn-ret-contravariant.rs:39:4 + | +LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | bar(foo, x) + | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr new file mode 100644 index 000000000..ada12c7ee --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -0,0 +1,36 @@ +error: lifetime may not live long enough + --> $DIR/project-fn-ret-invariant.rs:59:5 + | +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/project-fn-ret-invariant.rs:59:5 + | +LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (a, b) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr new file mode 100644 index 000000000..77841780f --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -0,0 +1,36 @@ +error: lifetime may not live long enough + --> $DIR/project-fn-ret-invariant.rs:40:13 + | +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let f = foo; // <-- No consistent type can be inferred for `f` here. +LL | let a = bar(f, x); + | ^^^^^^^^^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/project-fn-ret-invariant.rs:42:13 + | +LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let b = bar(f, y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.rs b/tests/ui/associated-types/cache/project-fn-ret-invariant.rs new file mode 100644 index 000000000..e04337913 --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -0,0 +1,64 @@ +#![feature(unboxed_closures)] +// Test for projection cache. We should be able to project distinct +// lifetimes from `foo` as we reinstantiate it multiple times, but not +// if we do it just once. In this variant, the region `'a` is used in +// an invariant position, which affects the results. + +// revisions: ok oneuse transmute krisskross +//[ok] check-pass + +#![allow(dead_code, unused_variables)] + +use std::marker::PhantomData; + +struct Type<'a> { + // Invariant + data: PhantomData &'a u32>, +} + +fn foo<'a>() -> Type<'a> { + loop {} +} + +fn bar(t: T, x: T::Output) -> T::Output +where + T: FnOnce<()>, +{ + t() +} + +#[cfg(ok)] // two instantiations: OK +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let a = bar(foo, x); + let b = bar(foo, y); + (a, b) +} + +#[cfg(oneuse)] // one instantiation: BAD +fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let f = foo; // <-- No consistent type can be inferred for `f` here. + let a = bar(f, x); + //[oneuse]~^ ERROR lifetime may not live long enough + let b = bar(f, y); + //[oneuse]~^ ERROR lifetime may not live long enough + (a, b) +} + +#[cfg(transmute)] // one instantiations: BAD +fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { + // Cannot instantiate `foo` with any lifetime other than `'a`, + // since it is provided as input. + + bar(foo, x) //[transmute]~ ERROR lifetime may not live long enough +} + +#[cfg(krisskross)] // two instantiations, mixing and matching: BAD +fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { + let a = bar(foo, y); + let b = bar(foo, x); + (a, b) + //[krisskross]~^ ERROR lifetime may not live long enough + //[krisskross]~| ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr new file mode 100644 index 000000000..b64cb2c3d --- /dev/null +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/project-fn-ret-invariant.rs:52:5 + | +LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> { + | -- lifetime `'a` defined here +... +LL | bar(foo, x) + | ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Type<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/default-associated-types.rs b/tests/ui/associated-types/default-associated-types.rs new file mode 100644 index 000000000..aae70bffa --- /dev/null +++ b/tests/ui/associated-types/default-associated-types.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(associated_type_defaults)] + +trait Foo { + type Out: Default + ToString = T; +} + +impl Foo for () { +} + +impl Foo for () { + type Out = bool; +} + +fn main() { + assert_eq!( + <() as Foo>::Out::default().to_string(), + "0"); + assert_eq!( + <() as Foo>::Out::default().to_string(), + "false"); +} diff --git a/tests/ui/associated-types/defaults-cyclic-fail-1.rs b/tests/ui/associated-types/defaults-cyclic-fail-1.rs new file mode 100644 index 000000000..61ef01323 --- /dev/null +++ b/tests/ui/associated-types/defaults-cyclic-fail-1.rs @@ -0,0 +1,40 @@ +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay... +trait Tr { + type A = Self::B; + type B = Self::A; +} + +impl Tr for () {} + +impl Tr for u8 { + type A = u8; +} + +impl Tr for u16 { + type B = (); +} + +impl Tr for u32 { + type A = (); + type B = u8; +} + +// ...but not in an impl that redefines one of the types. +impl Tr for bool { + type A = Box; + //~^ ERROR overflow evaluating the requirement `::B == _` +} +// (the error is shown twice for some reason) + +impl Tr for usize { + type B = &'static Self::A; + //~^ ERROR overflow evaluating the requirement `::A == _` +} + +fn main() { + // We don't check that the types project correctly because the cycle errors stop compilation + // before `main` is type-checked. + // `defaults-cyclic-pass-1.rs` does this. +} diff --git a/tests/ui/associated-types/defaults-cyclic-fail-1.stderr b/tests/ui/associated-types/defaults-cyclic-fail-1.stderr new file mode 100644 index 000000000..008eddcb2 --- /dev/null +++ b/tests/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `::B == _` + --> $DIR/defaults-cyclic-fail-1.rs:26:14 + | +LL | type A = Box; + | ^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::A == _` + --> $DIR/defaults-cyclic-fail-1.rs:32:14 + | +LL | type B = &'static Self::A; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/defaults-cyclic-fail-2.rs b/tests/ui/associated-types/defaults-cyclic-fail-2.rs new file mode 100644 index 000000000..e91c9f2d2 --- /dev/null +++ b/tests/ui/associated-types/defaults-cyclic-fail-2.rs @@ -0,0 +1,41 @@ +#![feature(associated_type_defaults)] + +// A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults. + +// Having a cycle in assoc. type defaults is okay... +trait Tr { + type A = Vec; + type B = Box; +} + +impl Tr for () {} + +impl Tr for u8 { + type A = u8; +} + +impl Tr for u16 { + type B = (); +} + +impl Tr for u32 { + type A = (); + type B = u8; +} + +impl Tr for bool { + type A = Box; + //~^ ERROR overflow evaluating the requirement `::B == _` +} +// (the error is shown twice for some reason) + +impl Tr for usize { + type B = &'static Self::A; + //~^ ERROR overflow evaluating the requirement `::A == _` +} + +fn main() { + // We don't check that the types project correctly because the cycle errors stop compilation + // before `main` is type-checked. + // `defaults-cyclic-pass-2.rs` does this. +} diff --git a/tests/ui/associated-types/defaults-cyclic-fail-2.stderr b/tests/ui/associated-types/defaults-cyclic-fail-2.stderr new file mode 100644 index 000000000..d0fbab077 --- /dev/null +++ b/tests/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `::B == _` + --> $DIR/defaults-cyclic-fail-2.rs:27:14 + | +LL | type A = Box; + | ^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::A == _` + --> $DIR/defaults-cyclic-fail-2.rs:33:14 + | +LL | type B = &'static Self::A; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/defaults-cyclic-pass-1.rs b/tests/ui/associated-types/defaults-cyclic-pass-1.rs new file mode 100644 index 000000000..97c6e5bad --- /dev/null +++ b/tests/ui/associated-types/defaults-cyclic-pass-1.rs @@ -0,0 +1,56 @@ +// check-pass + +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay, as long as there's no impl +// that retains it. +trait Tr { + type A = Self::B; + type B = Self::A; + + fn f(); +} + +// An impl has to break the cycle to be accepted. +impl Tr for u8 { + type A = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = 0u8; + let _: Self::B = 0u8; + } +} + +impl Tr for String { + type B = (); + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = (); + let _: Self::B = (); + } +} + +impl Tr for () { + type A = Vec<()>; + type B = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = Vec::<()>::new(); + let _: Self::B = 0u8; + } +} + +fn main() { + // Check that both impls now have the right types (seen from outside the impls) + let _: ::A = 0u8; + let _: ::B = 0u8; + + let _: ::A = (); + let _: ::B = (); + + let _: <() as Tr>::A = Vec::<()>::new(); + let _: <() as Tr>::B = 0u8; +} diff --git a/tests/ui/associated-types/defaults-cyclic-pass-2.rs b/tests/ui/associated-types/defaults-cyclic-pass-2.rs new file mode 100644 index 000000000..69315a022 --- /dev/null +++ b/tests/ui/associated-types/defaults-cyclic-pass-2.rs @@ -0,0 +1,56 @@ +// check-pass + +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay, as long as there's no impl +// that retains it. +trait Tr { + type A = Vec; + type B = Box; + + fn f(); +} + +// An impl has to break the cycle to be accepted. +impl Tr for u8 { + type A = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = 0u8; + let _: Self::B = Box::new(0u8); + } +} + +impl Tr for String { + type B = (); + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = Vec::<()>::new(); + let _: Self::B = (); + } +} + +impl Tr for () { + type A = Vec<()>; + type B = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = Vec::<()>::new(); + let _: Self::B = 0u8; + } +} + +fn main() { + // Check that both impls now have the right types (seen from outside the impls) + let _: ::A = 0u8; + let _: ::B = Box::new(0u8); + + let _: ::A = Vec::<()>::new(); + let _: ::B = (); + + let _: <() as Tr>::A = Vec::<()>::new(); + let _: <() as Tr>::B = 0u8; +} diff --git a/tests/ui/associated-types/defaults-in-other-trait-items-pass.rs b/tests/ui/associated-types/defaults-in-other-trait-items-pass.rs new file mode 100644 index 000000000..a3bfcd8ef --- /dev/null +++ b/tests/ui/associated-types/defaults-in-other-trait-items-pass.rs @@ -0,0 +1,37 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Item = u8; + type Container = Vec; +} + +impl Tr for () {} + +impl Tr for u16 { + type Item = u16; +} + +impl Tr for String { + type Container = String; +} + +impl Tr for usize { + type Item = u32; + type Container = Vec<()>; +} + +fn main() { + let _container: <() as Tr>::Container = Vec::::new(); + let _item: <() as Tr>::Item = 0u8; + + let _container: ::Container = Vec::::new(); + let _item: ::Item = 0u16; + + let _container: ::Container = String::new(); + let _item: ::Item = 0u8; + + let _container: ::Container = Vec::<()>::new(); + let _item: ::Item = 0u32; +} diff --git a/tests/ui/associated-types/defaults-in-other-trait-items.rs b/tests/ui/associated-types/defaults-in-other-trait-items.rs new file mode 100644 index 000000000..505751969 --- /dev/null +++ b/tests/ui/associated-types/defaults-in-other-trait-items.rs @@ -0,0 +1,47 @@ +#![feature(associated_type_defaults)] + +// Associated type defaults may not be assumed inside the trait defining them. +// ie. they only resolve to `::A`, not the actual type `()` +trait Tr { + type A = (); //~ NOTE associated type defaults can't be assumed inside the trait defining them + + fn f(p: Self::A) { + let () = p; + //~^ ERROR mismatched types + //~| NOTE expected associated type, found `()` + //~| NOTE expected associated type `::A` + //~| NOTE this expression has type `::A` + } +} + +// An impl that doesn't override the type *can* assume the default. +impl Tr for () { + fn f(p: Self::A) { + let () = p; + } +} + +impl Tr for u8 { + type A = (); + + fn f(p: Self::A) { + let () = p; + } +} + +trait AssocConst { + type Ty = u8; //~ NOTE associated type defaults can't be assumed inside the trait defining them + + // Assoc. consts also cannot assume that default types hold + const C: Self::Ty = 0u8; + //~^ ERROR mismatched types + //~| NOTE expected associated type, found `u8` + //~| NOTE expected associated type `::Ty` +} + +// An impl can, however +impl AssocConst for () { + const C: Self::Ty = 0u8; +} + +fn main() {} diff --git a/tests/ui/associated-types/defaults-in-other-trait-items.stderr b/tests/ui/associated-types/defaults-in-other-trait-items.stderr new file mode 100644 index 000000000..71d421926 --- /dev/null +++ b/tests/ui/associated-types/defaults-in-other-trait-items.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> $DIR/defaults-in-other-trait-items.rs:9:13 + | +LL | type A = (); + | ------------ associated type defaults can't be assumed inside the trait defining them +... +LL | let () = p; + | ^^ - this expression has type `::A` + | | + | expected associated type, found `()` + | + = note: expected associated type `::A` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/defaults-in-other-trait-items.rs:36:25 + | +LL | type Ty = u8; + | ------------- associated type defaults can't be assumed inside the trait defining them +... +LL | const C: Self::Ty = 0u8; + | ^^^ expected associated type, found `u8` + | + = note: expected associated type `::Ty` + found type `u8` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/defaults-mixed.rs b/tests/ui/associated-types/defaults-mixed.rs new file mode 100644 index 000000000..c91b8de39 --- /dev/null +++ b/tests/ui/associated-types/defaults-mixed.rs @@ -0,0 +1,34 @@ +#![feature(associated_type_defaults)] + +// Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly. + +trait Trait { + type Foo = u8; + type Bar; +} + +// `Bar` must be specified +impl Trait for () {} +//~^ error: not all trait items implemented, missing: `Bar` + +impl Trait for bool { +//~^ error: not all trait items implemented, missing: `Bar` + type Foo = (); +} + +impl Trait for u8 { + type Bar = (); +} + +impl Trait for u16 { + type Foo = String; + type Bar = bool; +} + +fn main() { + let _: ::Foo = 0u8; + let _: ::Bar = (); + + let _: ::Foo = String::new(); + let _: ::Bar = true; +} diff --git a/tests/ui/associated-types/defaults-mixed.stderr b/tests/ui/associated-types/defaults-mixed.stderr new file mode 100644 index 000000000..0f4a6968c --- /dev/null +++ b/tests/ui/associated-types/defaults-mixed.stderr @@ -0,0 +1,21 @@ +error[E0046]: not all trait items implemented, missing: `Bar` + --> $DIR/defaults-mixed.rs:11:1 + | +LL | type Bar; + | -------- `Bar` from trait +... +LL | impl Trait for () {} + | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation + +error[E0046]: not all trait items implemented, missing: `Bar` + --> $DIR/defaults-mixed.rs:14:1 + | +LL | type Bar; + | -------- `Bar` from trait +... +LL | impl Trait for bool { + | ^^^^^^^^^^^^^^^^^^^ missing `Bar` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/associated-types/defaults-specialization.rs b/tests/ui/associated-types/defaults-specialization.rs new file mode 100644 index 000000000..553705b2a --- /dev/null +++ b/tests/ui/associated-types/defaults-specialization.rs @@ -0,0 +1,96 @@ +//! Tests the interaction of associated type defaults and specialization. + +#![feature(associated_type_defaults, specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Tr { + type Ty = u8; + + fn make() -> Self::Ty { + 0u8 + //~^ error: mismatched types + } +} + +struct A(T); +// In a `default impl`, assoc. types are defaulted as well, +// so their values can't be assumed. +default impl Tr for A { + fn make() -> u8 { 0 } + //~^ ERROR method `make` has an incompatible type for trait +} + +struct A2(T); +// ...same, but in the method body +default impl Tr for A2 { + fn make() -> Self::Ty { 0u8 } + //~^ ERROR mismatched types +} + +struct B(T); +// Explicitly defaulting the type does the same. +impl Tr for B { + default type Ty = bool; + + fn make() -> bool { true } + //~^ ERROR method `make` has an incompatible type for trait +} + +struct B2(T); +// ...same, but in the method body +impl Tr for B2 { + default type Ty = bool; + + fn make() -> Self::Ty { true } + //~^ ERROR mismatched types +} + +struct C(T); +// Only the method is defaulted, so this is fine. +impl Tr for C { + type Ty = bool; + + default fn make() -> bool { true } +} + +// Defaulted method *can* assume the type, if the default is kept. +struct D(T); +impl Tr for D { + default fn make() -> u8 { 0 } +} + +impl Tr for D { + fn make() -> u8 { 255 } +} + +struct E(T); +impl Tr for E { + default type Ty = bool; + default fn make() -> Self::Ty { panic!(); } +} + +// This impl specializes and sets `Ty`, it can rely on `Ty=String`. +impl Tr for E { + type Ty = String; + + fn make() -> String { String::new() } +} + +fn main() { + // Test that we can assume the right set of assoc. types from outside the impl + + // This is a `default impl`, which does *not* mean that `A`/`A2` actually implement the trait. + // cf. https://github.com/rust-lang/rust/issues/48515 + //let _: as Tr>::Ty = 0u8; + //let _: as Tr>::Ty = 0u8; + + let _: as Tr>::Ty = 0u8; //~ error: mismatched types + let _: as Tr>::Ty = true; //~ error: mismatched types + let _: as Tr>::Ty = 0u8; //~ error: mismatched types + let _: as Tr>::Ty = true; //~ error: mismatched types + + let _: as Tr>::Ty = true; + + let _: as Tr>::Ty = 0u8; + let _: as Tr>::Ty = 0u8; +} diff --git a/tests/ui/associated-types/defaults-specialization.stderr b/tests/ui/associated-types/defaults-specialization.stderr new file mode 100644 index 000000000..7e21f7fc3 --- /dev/null +++ b/tests/ui/associated-types/defaults-specialization.stderr @@ -0,0 +1,156 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/defaults-specialization.rs:3:38 + | +LL | #![feature(associated_type_defaults, specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:19:18 + | +LL | fn make() -> u8 { 0 } + | ^^ + | | + | expected associated type, found `u8` + | help: change the output type to match the trait: ` as Tr>::Ty` + | +note: type in trait + --> $DIR/defaults-specialization.rs:9:18 + | +LL | fn make() -> Self::Ty { + | ^^^^^^^^ + = note: expected signature `fn() -> as Tr>::Ty` + found signature `fn() -> u8` + +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:35:18 + | +LL | default type Ty = bool; + | ----------------------- expected this associated type +LL | +LL | fn make() -> bool { true } + | ^^^^ + | | + | expected associated type, found `bool` + | help: change the output type to match the trait: ` as Tr>::Ty` + | +note: type in trait + --> $DIR/defaults-specialization.rs:9:18 + | +LL | fn make() -> Self::Ty { + | ^^^^^^^^ + = note: expected signature `fn() -> as Tr>::Ty` + found signature `fn() -> bool` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:10:9 + | +LL | type Ty = u8; + | ------------- associated type defaults can't be assumed inside the trait defining them +LL | +LL | fn make() -> Self::Ty { + | -------- expected `::Ty` because of return type +LL | 0u8 + | ^^^ expected associated type, found `u8` + | + = note: expected associated type `::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:26:29 + | +LL | fn make() -> Self::Ty { 0u8 } + | -------- ^^^ expected associated type, found `u8` + | | + | expected ` as Tr>::Ty` because of return type + | + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = help: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:44:29 + | +LL | default type Ty = bool; + | ----------------------- expected this associated type +LL | +LL | fn make() -> Self::Ty { true } + | -------- ^^^^ expected associated type, found `bool` + | | + | expected ` as Tr>::Ty` because of return type + | + = note: expected associated type ` as Tr>::Ty` + found type `bool` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:87:32 + | +LL | let _: as Tr>::Ty = 0u8; + | ----------------- ^^^ expected associated type, found `u8` + | | + | expected due to this + | + = note: expected associated type ` as Tr>::Ty` + found type `u8` +help: a method is available that returns ` as Tr>::Ty` + --> $DIR/defaults-specialization.rs:9:5 + | +LL | fn make() -> Self::Ty { + | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:88:32 + | +LL | let _: as Tr>::Ty = true; + | ----------------- ^^^^ expected associated type, found `bool` + | | + | expected due to this + | + = note: expected associated type ` as Tr>::Ty` + found type `bool` +help: a method is available that returns ` as Tr>::Ty` + --> $DIR/defaults-specialization.rs:9:5 + | +LL | fn make() -> Self::Ty { + | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:89:33 + | +LL | let _: as Tr>::Ty = 0u8; + | ------------------ ^^^ expected associated type, found `u8` + | | + | expected due to this + | + = note: expected associated type ` as Tr>::Ty` + found type `u8` +help: a method is available that returns ` as Tr>::Ty` + --> $DIR/defaults-specialization.rs:9:5 + | +LL | fn make() -> Self::Ty { + | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:90:33 + | +LL | let _: as Tr>::Ty = true; + | ------------------ ^^^^ expected associated type, found `bool` + | | + | expected due to this + | + = note: expected associated type ` as Tr>::Ty` + found type `bool` +help: a method is available that returns ` as Tr>::Ty` + --> $DIR/defaults-specialization.rs:9:5 + | +LL | fn make() -> Self::Ty { + | ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make` + +error: aborting due to 9 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/associated-types/defaults-suitability.rs b/tests/ui/associated-types/defaults-suitability.rs new file mode 100644 index 000000000..504c957d9 --- /dev/null +++ b/tests/ui/associated-types/defaults-suitability.rs @@ -0,0 +1,101 @@ +//! Checks that associated type defaults are properly validated. +//! +//! This means: +//! * Default types are checked against where clauses on the assoc. type +//! (eg. `type Assoc: Clone = NotClone`) + +#![feature(associated_type_defaults)] + +struct NotClone; + +// Assoc. type bounds must hold for the default type +trait Tr { + type Ty: Clone = NotClone; + //~^ ERROR the trait bound `NotClone: Clone` is not satisfied +} + +// Where-clauses defined on the trait must also be considered +trait Tr2 +where + Self::Ty: Clone, +{ + type Ty = NotClone; + //~^ ERROR the trait bound `NotClone: Clone` is not satisfied +} + +// Involved type parameters must fulfill all bounds required by defaults that mention them +trait Foo { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `T: Clone` is not satisfied +} + +trait Bar: Sized { + // `(): Foo` might hold for some possible impls but not all. + type Assoc: Foo = (); + //~^ ERROR the trait bound `(): Foo` is not satisfied +} + +trait IsU8 {} +impl IsU8 for T {} + +// Test that mentioning the assoc. type inside where clauses is not allowed +trait C where + Vec: Clone, + Self::Assoc: IsU8, + bool: IsU8, +{ + type Assoc = u8; +} + +// Test that we get all expected errors if that default is unsuitable +trait D where + Vec: Clone, + Self::Assoc: IsU8, + bool: IsU8, +{ + type Assoc = NotClone; + //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied +} + +// Test behavior of the check when defaults refer to other defaults: + +// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be +// `Clone`. +trait Foo2 { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `>::Baz: Clone` is not satisfied + type Baz = T; +} + +// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T` +// because of the shallow substitution. If we did a deep substitution instead, +// this would be accepted. +trait Foo25 { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `>::Baz: Clone` is not satisfied + type Baz = T; +} + +// Adding the `Baz: Clone` bound isn't enough since the default is type +// parameter `T`, which also might not be `Clone`. +trait Foo3 +where + Self::Bar: Clone, + Self::Baz: Clone, +{ + type Bar = Vec; + type Baz = T; + //~^ ERROR the trait bound `T: Clone` is not satisfied +} + +// This one finally works, with `Clone` bounds on all assoc. types and the type +// parameter. +trait Foo4 +where + T: Clone, +{ + type Bar: Clone = Vec; + type Baz: Clone = T; +} + +fn main() {} diff --git a/tests/ui/associated-types/defaults-suitability.stderr b/tests/ui/associated-types/defaults-suitability.stderr new file mode 100644 index 000000000..eadad4cd5 --- /dev/null +++ b/tests/ui/associated-types/defaults-suitability.stderr @@ -0,0 +1,135 @@ +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:13:22 + | +LL | type Ty: Clone = NotClone; + | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` + | +note: required by a bound in `Tr::Ty` + --> $DIR/defaults-suitability.rs:13:14 + | +LL | type Ty: Clone = NotClone; + | ^^^^^ required by this bound in `Tr::Ty` +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:22:15 + | +LL | type Ty = NotClone; + | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` + | +note: required by a bound in `Tr2::Ty` + --> $DIR/defaults-suitability.rs:20:15 + | +LL | Self::Ty: Clone, + | ^^^^^ required by this bound in `Tr2::Ty` +LL | { +LL | type Ty = NotClone; + | -- required by a bound in this +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:28:23 + | +LL | type Bar: Clone = Vec; + | ^^^^^^ the trait `Clone` is not implemented for `T` + | + = note: required for `Vec` to implement `Clone` +note: required by a bound in `Foo::Bar` + --> $DIR/defaults-suitability.rs:28:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ required by this bound in `Foo::Bar` +help: consider restricting type parameter `T` + | +LL | trait Foo { + | +++++++++++++++++++ + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/defaults-suitability.rs:34:29 + | +LL | type Assoc: Foo = (); + | ^^ the trait `Foo` is not implemented for `()` + | +note: required by a bound in `Bar::Assoc` + --> $DIR/defaults-suitability.rs:34:17 + | +LL | type Assoc: Foo = (); + | ^^^^^^^^^ required by this bound in `Bar::Assoc` + +error[E0277]: the trait bound `NotClone: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:56:18 + | +LL | type Assoc = NotClone; + | ^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` + | +note: required by a bound in `D::Assoc` + --> $DIR/defaults-suitability.rs:53:18 + | +LL | Self::Assoc: IsU8, + | ^^^^^^^^^^^^^^^^^ required by this bound in `D::Assoc` +... +LL | type Assoc = NotClone; + | ----- required by a bound in this + +error[E0277]: the trait bound `>::Baz: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:65:23 + | +LL | type Bar: Clone = Vec; + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz` + | + = note: required for `Vec<>::Baz>` to implement `Clone` +note: required by a bound in `Foo2::Bar` + --> $DIR/defaults-suitability.rs:65:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ required by this bound in `Foo2::Bar` +help: consider further restricting the associated type + | +LL | trait Foo2 where >::Baz: Clone { + | +++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `>::Baz: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:74:23 + | +LL | type Bar: Clone = Vec; + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz` + | + = note: required for `Vec<>::Baz>` to implement `Clone` +note: required by a bound in `Foo25::Bar` + --> $DIR/defaults-suitability.rs:74:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ required by this bound in `Foo25::Bar` +help: consider further restricting the associated type + | +LL | trait Foo25 where >::Baz: Clone { + | ++++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:87:16 + | +LL | type Baz = T; + | ^ the trait `Clone` is not implemented for `T` + | +note: required by a bound in `Foo3::Baz` + --> $DIR/defaults-suitability.rs:84:16 + | +LL | Self::Baz: Clone, + | ^^^^^ required by this bound in `Foo3::Baz` +... +LL | type Baz = T; + | --- required by a bound in this +help: consider further restricting type parameter `T` + | +LL | Self::Baz: Clone, T: std::clone::Clone + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.rs b/tests/ui/associated-types/defaults-unsound-62211-1.rs new file mode 100644 index 000000000..fa6a208b4 --- /dev/null +++ b/tests/ui/associated-types/defaults-unsound-62211-1.rs @@ -0,0 +1,54 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/62211 +//! +//! The old implementation of defaults did not check whether the provided +//! default actually fulfills all bounds on the assoc. type, leading to +//! unsoundness, demonstrated here as a use-after-free. +//! +//! Note that the underlying cause of this is still not yet fixed. +//! See: https://github.com/rust-lang/rust/issues/33017 + +#![feature(associated_type_defaults)] + +use std::{ + fmt::Display, + ops::{AddAssign, Deref}, +}; + +trait UncheckedCopy: Sized { + // This Output is said to be Copy. Yet we default to Self + // and it's accepted, not knowing if Self ineed is Copy + type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + //~^ ERROR the trait bound `Self: Copy` is not satisfied + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` + + // We said the Output type was Copy, so we can Copy it freely! + fn unchecked_copy(other: &Self::Output) -> Self::Output { + (*other) + } + + fn make_origin(s: Self) -> Self::Output { + s.into() + } +} + +impl UncheckedCopy for T {} + +fn bug(origin: T) { + let origin = T::make_origin(origin); + let mut copy = T::unchecked_copy(&origin); + + // assert we indeed have 2 strings pointing to the same buffer. + assert_eq!(origin.as_ptr(), copy.as_ptr()); + + // Drop the origin. Any use of `copy` is UB. + drop(origin); + + copy += "This is invalid!"; + println!("{}", copy); +} + +fn main() { + bug(String::from("hello!")); +} diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.stderr new file mode 100644 index 000000000..5cd1cb4a1 --- /dev/null +++ b/tests/ui/associated-types/defaults-unsound-62211-1.stderr @@ -0,0 +1,68 @@ +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ `Self` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:20:86 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | +++++++++++++++++++ + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ no implementation for `Self += &'static str` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:20:47 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | +++++++++++++++++++++++++ + +error[E0277]: the trait bound `Self: Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Deref` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:20:25 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Deref { + | +++++++ + +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Copy` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:20:18 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Copy { + | ++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.rs b/tests/ui/associated-types/defaults-unsound-62211-2.rs new file mode 100644 index 000000000..c13ec776a --- /dev/null +++ b/tests/ui/associated-types/defaults-unsound-62211-2.rs @@ -0,0 +1,54 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/62211 +//! +//! The old implementation of defaults did not check whether the provided +//! default actually fulfills all bounds on the assoc. type, leading to +//! unsoundness and ICEs, the latter being demonstrated here. +//! +//! Note that the underlying cause of this is still not yet fixed. +//! See: https://github.com/rust-lang/rust/issues/33017 + +#![feature(associated_type_defaults)] + +use std::{ + fmt::Display, + ops::{AddAssign, Deref}, +}; + +trait UncheckedCopy: Sized { + // This Output is said to be Copy. Yet we default to Self + // and it's accepted, not knowing if Self ineed is Copy + type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + //~^ ERROR the trait bound `Self: Copy` is not satisfied + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` + + // We said the Output type was Copy, so we can Copy it freely! + fn unchecked_copy(other: &Self::Output) -> Self::Output { + (*other) + } + + fn make_origin(s: Self) -> Self::Output { + s.into() + } +} + +impl UncheckedCopy for T {} + +fn bug(origin: T) { + let origin = T::make_origin(origin); + let mut copy = T::unchecked_copy(&origin); + + // assert we indeed have 2 strings pointing to the same buffer. + assert_eq!(origin.as_ptr(), copy.as_ptr()); + + // Drop the origin. Any use of `copy` is UB. + drop(origin); + + copy += "This is invalid!"; + println!("{}", copy); +} + +fn main() { + bug(()); +} diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.stderr new file mode 100644 index 000000000..89319bb75 --- /dev/null +++ b/tests/ui/associated-types/defaults-unsound-62211-2.stderr @@ -0,0 +1,68 @@ +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ `Self` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:20:86 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | +++++++++++++++++++ + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ no implementation for `Self += &'static str` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:20:47 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | +++++++++++++++++++++++++ + +error[E0277]: the trait bound `Self: Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Deref` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:20:25 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Deref { + | +++++++ + +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Copy` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:20:18 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Copy { + | ++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-wf.rs b/tests/ui/associated-types/defaults-wf.rs new file mode 100644 index 000000000..99b512503 --- /dev/null +++ b/tests/ui/associated-types/defaults-wf.rs @@ -0,0 +1,11 @@ +// Check that associated type defaults are wf checked. + +#![feature(associated_type_defaults)] + +// Default types must always be wf +trait Tr3 { + type Ty = Vec<[u8]>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +fn main() {} diff --git a/tests/ui/associated-types/defaults-wf.stderr b/tests/ui/associated-types/defaults-wf.stderr new file mode 100644 index 000000000..fc830b8d6 --- /dev/null +++ b/tests/ui/associated-types/defaults-wf.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/defaults-wf.rs:7:15 + | +LL | type Ty = Vec<[u8]>; + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/higher-ranked-projection.bad.stderr b/tests/ui/associated-types/higher-ranked-projection.bad.stderr new file mode 100644 index 000000000..239f45539 --- /dev/null +++ b/tests/ui/associated-types/higher-ranked-projection.bad.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/higher-ranked-projection.rs:23:5 + | +LL | foo(()); + | ^^^^^^^ one type is more general than the other + | + = note: expected reference `&'a ()` + found reference `&()` +note: the lifetime requirement is introduced here + --> $DIR/higher-ranked-projection.rs:14:33 + | +LL | where for<'a> &'a T: Mirror + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/higher-ranked-projection.rs b/tests/ui/associated-types/higher-ranked-projection.rs new file mode 100644 index 000000000..7e6c509a2 --- /dev/null +++ b/tests/ui/associated-types/higher-ranked-projection.rs @@ -0,0 +1,25 @@ +// revisions: good bad +//[good] check-pass + +trait Mirror { + type Image; +} + +impl Mirror for T { + type Image = T; +} + +#[cfg(bad)] +fn foo(_t: T) + where for<'a> &'a T: Mirror +{} + +#[cfg(good)] +fn foo(_t: T) + where for<'a> &'a T: Mirror +{} + +fn main() { + foo(()); + //[bad]~^ ERROR mismatched types +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.rs b/tests/ui/associated-types/hr-associated-type-bound-1.rs new file mode 100644 index 000000000..db414164e --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-1.rs @@ -0,0 +1,18 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(&self, x: &Self::U) { + ::clone(x); + } +} + +impl X<'_> for i32 { + type U = str; + //~^ ERROR the trait bound `str: Clone` +} + +fn main() { + 1i32.f("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr new file mode 100644 index 000000000..73b5e1053 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-1.rs:12:14 + | +LL | type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X` + --> $DIR/hr-associated-type-bound-1.rs:3:33 + | +LL | trait X<'a> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ^^^^^ required by this bound in `X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-2.rs b/tests/ui/associated-types/hr-associated-type-bound-2.rs new file mode 100644 index 000000000..a89f61a81 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-2.rs @@ -0,0 +1,20 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(&self, x: &Self::U) { + ::clone(x); + } +} + +impl X<'_> for u32 //~ overflow evaluating the requirement `for<'b> u32: X<'b>` +where + for<'b> >::U: Clone, +{ + type U = str; +} + +fn main() { + 1u32.f("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-2.stderr new file mode 100644 index 000000000..749986f09 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-2.stderr @@ -0,0 +1,21 @@ +error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>` + --> $DIR/hr-associated-type-bound-2.rs:11:1 + | +LL | impl X<'_> for u32 + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`) +note: required for `u32` to implement `for<'b> X<'b>` + --> $DIR/hr-associated-type-bound-2.rs:11:6 + | +LL | impl X<'_> for u32 + | ^^^^^ ^^^ +LL | where +LL | for<'b> >::U: Clone, + | ----- unsatisfied trait bound introduced here + = note: 128 redundant requirements hidden + = note: required for `u32` to implement `for<'b> X<'b>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-object.rs b/tests/ui/associated-types/hr-associated-type-bound-object.rs new file mode 100644 index 000000000..e19c918c3 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-object.rs @@ -0,0 +1,14 @@ +trait X<'a> +where + for<'b> >::U: Clone, +{ + type U: ?Sized; +} +fn f<'a, T: X<'a> + ?Sized>(x: &>::U) { + //~^ ERROR the trait bound `for<'b> >::U: Clone` is not satisfied + <>::U>::clone(x); +} + +pub fn main() { + f::>("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-object.stderr b/tests/ui/associated-types/hr-associated-type-bound-object.stderr new file mode 100644 index 000000000..6d19186bd --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-object.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'b> >::U: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-object.rs:7:13 + | +LL | fn f<'a, T: X<'a> + ?Sized>(x: &>::U) { + | ^^^^^ the trait `for<'b> Clone` is not implemented for `>::U` + | +note: required by a bound in `X` + --> $DIR/hr-associated-type-bound-object.rs:3:33 + | +LL | trait X<'a> + | - required by a bound in this +LL | where +LL | for<'b> >::U: Clone, + | ^^^^^ required by this bound in `X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.rs b/tests/ui/associated-types/hr-associated-type-bound-param-1.rs new file mode 100644 index 000000000..bbeeb145d --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.rs @@ -0,0 +1,20 @@ +trait Y<'a, T: ?Sized> +where + T: Y<'a, Self>, + for<'b> >::V: Clone, + for<'b> >::V: Clone, +{ + type V: ?Sized; + fn g(&self, x: &Self::V) { + ::clone(x); + } +} + +impl<'a> Y<'a, u8> for u8 { + type V = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +fn main() { + 1u8.g("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr new file mode 100644 index 000000000..af2e61689 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-1.rs:14:14 + | +LL | type V = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `Y` + --> $DIR/hr-associated-type-bound-param-1.rs:4:36 + | +LL | trait Y<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::V: Clone, + | ^^^^^ required by this bound in `Y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.rs b/tests/ui/associated-types/hr-associated-type-bound-param-2.rs new file mode 100644 index 000000000..f74c5a859 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.rs @@ -0,0 +1,21 @@ +trait Z<'a, T: ?Sized> +where + T: Z<'a, u16>, + //~^ the trait bound `str: Clone` is not satisfied + //~| the trait bound `str: Clone` is not satisfied + for<'b> >::W: Clone, +{ + type W: ?Sized; + fn h(&self, x: &T::W) { + ::clone(x); + } +} + +impl<'a> Z<'a, u16> for u16 { + type W = str; + //~^ ERROR the trait bound `str: Clone +} + +fn main() { + 1u16.h("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr new file mode 100644 index 000000000..52294f8c9 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + | +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `Z` + --> $DIR/hr-associated-type-bound-param-2.rs:6:35 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::W: Clone, + | ^^^^^ required by this bound in `Z` + +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:15:14 + | +LL | type W = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `Z` + --> $DIR/hr-associated-type-bound-param-2.rs:6:35 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::W: Clone, + | ^^^^^ required by this bound in `Z` + +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-2.rs:3:8 + | +LL | T: Z<'a, u16>, + | ^^^^^^^^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `Z` + --> $DIR/hr-associated-type-bound-param-2.rs:6:35 + | +LL | trait Z<'a, T: ?Sized> + | - required by a bound in this +... +LL | for<'b> >::W: Clone, + | ^^^^^ required by this bound in `Z` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.rs b/tests/ui/associated-types/hr-associated-type-bound-param-3.rs new file mode 100644 index 000000000..fda7d8111 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.rs @@ -0,0 +1,19 @@ +trait X<'a, T> +where + for<'b> T: X<'b, T>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, (T,)> for (S,) { + type U = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X<(i32,)>>::f("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr new file mode 100644 index 000000000..84d5e0494 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-3.rs:13:14 + | +LL | type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X` + --> $DIR/hr-associated-type-bound-param-3.rs:4:33 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ^^^^^ required by this bound in `X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.rs b/tests/ui/associated-types/hr-associated-type-bound-param-4.rs new file mode 100644 index 000000000..20c8157ed --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.rs @@ -0,0 +1,19 @@ +trait X<'a, T> +where + for<'b> (T,): X<'b, T>, + for<'b> <(T,) as X<'b, T>>::U: Clone, +{ + type U: ?Sized; + fn f(x: &<(T,) as X<'_, T>>::U) { + <<(T,) as X<'_, T>>::U>::clone(x); + } +} + +impl X<'_, T> for (S,) { + type U = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +pub fn main() { + <(i32,) as X>::f("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr new file mode 100644 index 000000000..ee1d5d324 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-4.rs:13:14 + | +LL | type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X` + --> $DIR/hr-associated-type-bound-param-4.rs:4:36 + | +LL | trait X<'a, T> + | - required by a bound in this +... +LL | for<'b> <(T,) as X<'b, T>>::U: Clone, + | ^^^^^ required by this bound in `X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.rs b/tests/ui/associated-types/hr-associated-type-bound-param-5.rs new file mode 100644 index 000000000..d7f3151a5 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.rs @@ -0,0 +1,37 @@ +trait Cycle: Sized { + type Next: Cycle; +} + +impl Cycle for Box { + type Next = Vec; +} + +impl Cycle for Vec { + type Next = Box; +} + +trait X<'a, T: Cycle + for<'b> X<'b, T>> +where + for<'b> >::U: Clone, + for<'b> T::Next: X<'b, T::Next>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, Vec> for S { + type U = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +impl X<'_, Box> for S { + type U = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +pub fn main() { + >>::f("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr new file mode 100644 index 000000000..ece3151ba --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:26:14 + | +LL | type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X` + --> $DIR/hr-associated-type-bound-param-5.rs:17:45 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ^^^^^ required by this bound in `X` + +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/hr-associated-type-bound-param-5.rs:31:14 + | +LL | type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X` + --> $DIR/hr-associated-type-bound-param-5.rs:17:45 + | +LL | trait X<'a, T: Cycle + for<'b> X<'b, T>> + | - required by a bound in this +... +LL | for<'b> >::U: Clone, + | ^^^^^ required by this bound in `X` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.rs b/tests/ui/associated-types/hr-associated-type-bound-param-6.rs new file mode 100644 index 000000000..482047b09 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.rs @@ -0,0 +1,19 @@ +trait X<'a, T> +where + for<'b> T: X<'b, T>, + for<'b> >::U: Clone, +{ + type U: ?Sized; + fn f(x: &>::U) { + <>::U>::clone(x); + } +} + +impl X<'_, T> for (S,) { + //~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied + type U = str; +} + +pub fn main() { + <(i32,) as X>::f("abc"); +} diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr new file mode 100644 index 000000000..bd6e627a3 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied + --> $DIR/hr-associated-type-bound-param-6.rs:12:12 + | +LL | impl X<'_, T> for (S,) { + | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl X<'b, T>> X<'_, T> for (S,) { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs new file mode 100644 index 000000000..951dd9e97 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs @@ -0,0 +1,20 @@ +trait UnsafeCopy<'a, T: Copy> +where + for<'b> >::Item: std::ops::Deref, +{ + type Item; + + fn bug(item: &Self::Item) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl UnsafeCopy<'_, T> for T { + //~^ type mismatch resolving `::Target == T` + type Item = T; +} + +pub fn main() { + <&'static str>::bug(&""); +} diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr new file mode 100644 index 000000000..a65f84ae5 --- /dev/null +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -0,0 +1,24 @@ +error[E0271]: type mismatch resolving `::Target == T` + --> $DIR/hr-associated-type-projection-1.rs:13:33 + | +LL | impl UnsafeCopy<'_, T> for T { + | - this type parameter ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | + = note: expected type parameter `T` + found associated type `::Target` +note: required by a bound in `UnsafeCopy` + --> $DIR/hr-associated-type-projection-1.rs:3:64 + | +LL | trait UnsafeCopy<'a, T: Copy> + | ---------- required by a bound in this +LL | where +LL | for<'b> >::Item: std::ops::Deref, + | ^^^^^^^^^^ required by this bound in `UnsafeCopy` +help: consider further restricting this bound + | +LL | impl> UnsafeCopy<'_, T> for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/impl-trait-return-missing-constraint.rs b/tests/ui/associated-types/impl-trait-return-missing-constraint.rs new file mode 100644 index 000000000..1de1ddbe3 --- /dev/null +++ b/tests/ui/associated-types/impl-trait-return-missing-constraint.rs @@ -0,0 +1,32 @@ +trait Foo { + type Item; +} + +trait Bar: Foo {} + +struct S; + +impl Foo for S { + type Item = i32; +} +impl Bar for S {} + +struct T; + +impl Foo for T { + type Item = u32; +} +impl Bar for T {} + +fn bar() -> impl Bar { + T +} + +fn baz() -> impl Bar { + //~^ ERROR type mismatch resolving `::Item == i32` + bar() +} + +fn main() { + let _ = baz(); +} diff --git a/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr b/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr new file mode 100644 index 000000000..fbd76a64c --- /dev/null +++ b/tests/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -0,0 +1,24 @@ +error[E0271]: type mismatch resolving `::Item == i32` + --> $DIR/impl-trait-return-missing-constraint.rs:25:13 + | +LL | fn bar() -> impl Bar { + | -------- the expected opaque type +... +LL | fn baz() -> impl Bar { + | ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32` +LL | +LL | bar() + | ----- return type was inferred to be `impl Bar` here + | + = note: expected associated type `::Item` + found type `i32` + = help: consider constraining the associated type `::Item` to `i32` or calling a method that returns `::Item` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +help: consider constraining the associated type `::Item` to `i32` + | +LL | fn bar() -> impl Bar { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/impl-wf-cycle-1.rs b/tests/ui/associated-types/impl-wf-cycle-1.rs new file mode 100644 index 000000000..365eddaed --- /dev/null +++ b/tests/ui/associated-types/impl-wf-cycle-1.rs @@ -0,0 +1,27 @@ +// Regression test for #79714 + +trait Baz {} +impl Baz for () {} +impl Baz for (T,) {} + +trait Fiz {} +impl Fiz for bool {} + +trait Grault { + type A; + type B; +} + +impl Grault for (T,) +//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` +where + Self::A: Baz, + Self::B: Fiz, +{ + type A = (); + type B = bool; +} + +fn main() { + let x: <(_,) as Grault>::A = (); +} diff --git a/tests/ui/associated-types/impl-wf-cycle-1.stderr b/tests/ui/associated-types/impl-wf-cycle-1.stderr new file mode 100644 index 000000000..206060f19 --- /dev/null +++ b/tests/ui/associated-types/impl-wf-cycle-1.stderr @@ -0,0 +1,20 @@ +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-1.rs:15:1 + | +LL | impl Grault for (T,) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `(T,)` to implement `Grault` + --> $DIR/impl-wf-cycle-1.rs:15:17 + | +LL | impl Grault for (T,) + | ^^^^^^ ^^^^ +... +LL | Self::A: Baz, + | --- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `(T,)` to implement `Grault` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/impl-wf-cycle-2.rs b/tests/ui/associated-types/impl-wf-cycle-2.rs new file mode 100644 index 000000000..f2f3072e3 --- /dev/null +++ b/tests/ui/associated-types/impl-wf-cycle-2.rs @@ -0,0 +1,15 @@ +// Regression test for #79714 + +trait Grault { + type A; +} + +impl Grault for (T,) +//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _` +where + Self::A: Copy, +{ + type A = (); +} + +fn main() {} diff --git a/tests/ui/associated-types/impl-wf-cycle-2.stderr b/tests/ui/associated-types/impl-wf-cycle-2.stderr new file mode 100644 index 000000000..771ba751e --- /dev/null +++ b/tests/ui/associated-types/impl-wf-cycle-2.stderr @@ -0,0 +1,18 @@ +error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` + --> $DIR/impl-wf-cycle-2.rs:7:1 + | +LL | impl Grault for (T,) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `(T,)` to implement `Grault` + --> $DIR/impl-wf-cycle-2.rs:7:17 + | +LL | impl Grault for (T,) + | ^^^^^^ ^^^^ +... +LL | Self::A: Copy, + | ---- unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-types/issue-18655.rs b/tests/ui/associated-types/issue-18655.rs new file mode 100644 index 000000000..3d18542ac --- /dev/null +++ b/tests/ui/associated-types/issue-18655.rs @@ -0,0 +1,22 @@ +// run-pass +trait Factory { + type Product; + fn create(&self) -> ::Product; +} + +impl Factory for f64 { + type Product = f64; + fn create(&self) -> f64 { *self * *self } +} + +impl Factory for (A, B) { + type Product = (::Product, ::Product); + fn create(&self) -> (::Product, ::Product) { + let (ref a, ref b) = *self; + (a.create(), b.create()) + } +} + +fn main() { + assert_eq!((16., 25.), (4., 5.).create()); +} diff --git a/tests/ui/associated-types/issue-19081.rs b/tests/ui/associated-types/issue-19081.rs new file mode 100644 index 000000000..fbfe4c6f8 --- /dev/null +++ b/tests/ui/associated-types/issue-19081.rs @@ -0,0 +1,14 @@ +// check-pass +pub trait Hasher { + type State; + + fn hash::State + >>(&self, value: &T) -> u64; +} + +pub trait Hash { + fn hash(&self, state: &mut S); +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-19883.rs b/tests/ui/associated-types/issue-19883.rs new file mode 100644 index 000000000..5cf422043 --- /dev/null +++ b/tests/ui/associated-types/issue-19883.rs @@ -0,0 +1,16 @@ +trait From { + type Output; + + fn from(src: Src) -> >::Output; +} + +trait To: Sized { + fn to>(self) -> + >::Dst + //~^ ERROR cannot find associated type `Dst` in trait `From` + { + From::from(self) + } +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-19883.stderr b/tests/ui/associated-types/issue-19883.stderr new file mode 100644 index 000000000..bd6a86b74 --- /dev/null +++ b/tests/ui/associated-types/issue-19883.stderr @@ -0,0 +1,15 @@ +error[E0576]: cannot find associated type `Dst` in trait `From` + --> $DIR/issue-19883.rs:9:30 + | +LL | type Output; + | ------------ associated type `Output` defined here +... +LL | >::Dst + | ^^^ + | | + | not found in `From` + | help: maybe you meant this associated type: `Output` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/associated-types/issue-20005.rs b/tests/ui/associated-types/issue-20005.rs new file mode 100644 index 000000000..36350bff1 --- /dev/null +++ b/tests/ui/associated-types/issue-20005.rs @@ -0,0 +1,15 @@ +trait From { + type Result; + + fn from(src: Src) -> Self::Result; +} + +trait To { + fn to( + self + ) -> >::Result where Dst: From { //~ ERROR the size for values of type + From::from(self) + } +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-20005.stderr b/tests/ui/associated-types/issue-20005.stderr new file mode 100644 index 000000000..c8e57df0d --- /dev/null +++ b/tests/ui/associated-types/issue-20005.stderr @@ -0,0 +1,23 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-20005.rs:10:49 + | +LL | ) -> >::Result where Dst: From { + | ^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `From` + --> $DIR/issue-20005.rs:1:12 + | +LL | trait From { + | ^^^ required by this bound in `From` +help: consider further restricting `Self` + | +LL | ) -> >::Result where Dst: From, Self: Sized { + | +++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | trait From { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-20825-2.rs b/tests/ui/associated-types/issue-20825-2.rs new file mode 100644 index 000000000..b79a29730 --- /dev/null +++ b/tests/ui/associated-types/issue-20825-2.rs @@ -0,0 +1,10 @@ +// check-pass +pub trait Subscriber { + type Input; +} + +pub trait Processor: Subscriber::Input> { + type Input; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-20825.rs b/tests/ui/associated-types/issue-20825.rs new file mode 100644 index 000000000..516c304d8 --- /dev/null +++ b/tests/ui/associated-types/issue-20825.rs @@ -0,0 +1,10 @@ +pub trait Subscriber { + type Input; +} + +pub trait Processor: Subscriber { + //~^ ERROR cycle detected + type Input; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-20825.stderr b/tests/ui/associated-types/issue-20825.stderr new file mode 100644 index 000000000..be2bbd448 --- /dev/null +++ b/tests/ui/associated-types/issue-20825.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the super traits of `Processor` with associated type name `Input` + --> $DIR/issue-20825.rs:5:1 + | +LL | pub trait Processor: Subscriber { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing the super traits of `Processor` with associated type name `Input` again +note: cycle used when computing the super traits of `Processor` + --> $DIR/issue-20825.rs:5:1 + | +LL | pub trait Processor: Subscriber { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-types/issue-21363.rs b/tests/ui/associated-types/issue-21363.rs new file mode 100644 index 000000000..acc28cb43 --- /dev/null +++ b/tests/ui/associated-types/issue-21363.rs @@ -0,0 +1,15 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#![no_implicit_prelude] + +trait Iterator { + type Item; + fn dummy(&self) { } +} + +impl<'a, T> Iterator for &'a mut (dyn Iterator + 'a) { + type Item = T; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-21726.rs b/tests/ui/associated-types/issue-21726.rs new file mode 100644 index 000000000..b98cf2166 --- /dev/null +++ b/tests/ui/associated-types/issue-21726.rs @@ -0,0 +1,38 @@ +// check-pass +#![allow(dead_code)] +// Regression test for #21726: an issue arose around the rules for +// subtyping of projection types that resulted in an unconstrained +// region, yielding region inference failures. + +// pretty-expanded FIXME #23616 + +fn main() { } + +fn foo<'a>(s: &'a str) { + let b: B<()> = B::new(s, ()); + b.get_short(); +} + +trait IntoRef<'a> { + type T: Clone; + fn into_ref(self, _: &'a str) -> Self::T; +} + +impl<'a> IntoRef<'a> for () { + type T = &'a str; + fn into_ref(self, s: &'a str) -> &'a str { + s + } +} + +struct B<'a, P: IntoRef<'a>>(P::T); + +impl<'a, P: IntoRef<'a>> B<'a, P> { + fn new(s: &'a str, i: P) -> B<'a, P> { + B(i.into_ref(s)) + } + + fn get_short(&self) -> P::T { + self.0.clone() + } +} diff --git a/tests/ui/associated-types/issue-22037.rs b/tests/ui/associated-types/issue-22037.rs new file mode 100644 index 000000000..b9eb41b6e --- /dev/null +++ b/tests/ui/associated-types/issue-22037.rs @@ -0,0 +1,17 @@ +trait A { + type Output; + fn a(&self) -> ::X; + //~^ ERROR cannot find associated type `X` in trait `A` +} + +impl A for u32 { + type Output = u32; + fn a(&self) -> u32 { + 0 + } +} + +fn main() { + let a: u32 = 0; + let b: u32 = a.a(); +} diff --git a/tests/ui/associated-types/issue-22037.stderr b/tests/ui/associated-types/issue-22037.stderr new file mode 100644 index 000000000..0e019f10f --- /dev/null +++ b/tests/ui/associated-types/issue-22037.stderr @@ -0,0 +1,14 @@ +error[E0576]: cannot find associated type `X` in trait `A` + --> $DIR/issue-22037.rs:3:33 + | +LL | type Output; + | ------------ associated type `Output` defined here +LL | fn a(&self) -> ::X; + | ^ + | | + | not found in `A` + | help: maybe you meant this associated type: `Output` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/associated-types/issue-22066.rs b/tests/ui/associated-types/issue-22066.rs new file mode 100644 index 000000000..8e8ba5dc4 --- /dev/null +++ b/tests/ui/associated-types/issue-22066.rs @@ -0,0 +1,12 @@ +// check-pass +pub trait LineFormatter<'a> { + type Iter: Iterator + 'a; + fn iter(&'a self, line: &'a str) -> Self::Iter; + + fn dimensions(&'a self, line: &'a str) { + let iter: Self::Iter = self.iter(line); + <_ as IntoIterator>::into_iter(iter); + } +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-22560.rs b/tests/ui/associated-types/issue-22560.rs new file mode 100644 index 000000000..44be8817b --- /dev/null +++ b/tests/ui/associated-types/issue-22560.rs @@ -0,0 +1,15 @@ +trait Add { + type Output; +} + +trait Sub { + type Output; +} + +type Test = dyn Add + Sub; +//~^ ERROR E0393 +//~| ERROR E0191 +//~| ERROR E0393 +//~| ERROR E0225 + +fn main() { } diff --git a/tests/ui/associated-types/issue-22560.stderr b/tests/ui/associated-types/issue-22560.stderr new file mode 100644 index 000000000..2b88cf0b4 --- /dev/null +++ b/tests/ui/associated-types/issue-22560.stderr @@ -0,0 +1,56 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/issue-22560.rs:9:23 + | +LL | type Test = dyn Add + Sub; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified + --> $DIR/issue-22560.rs:9:17 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | type Output; + | ----------- `Output` defined here +... +LL | type Test = dyn Add + Sub; + | ^^^ ^^^ associated type `Output` must be specified + | | + | associated type `Output` must be specified + | +help: specify the associated types + | +LL | type Test = dyn Add + Sub; + | ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/issue-22560.rs:9:17 + | +LL | trait Add { + | ------------------- type parameter `Rhs` must be specified for this +... +LL | type Test = dyn Add + Sub; + | ^^^ help: set the type parameter to the desired type: `Add` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/issue-22560.rs:9:23 + | +LL | trait Sub { + | ------------------- type parameter `Rhs` must be specified for this +... +LL | type Test = dyn Add + Sub; + | ^^^ help: set the type parameter to the desired type: `Sub` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0191, E0225, E0393. +For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/issue-22828.rs b/tests/ui/associated-types/issue-22828.rs new file mode 100644 index 000000000..adf4dd6ce --- /dev/null +++ b/tests/ui/associated-types/issue-22828.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +// Test transitive analysis for associated types. Collected types +// should be normalized and new obligations generated. + +// pretty-expanded FIXME #23616 + +trait Foo { + type A; + fn foo(&self) {} +} + +impl Foo for usize { + type A = usize; +} + +struct Bar { inner: T::A } + +fn is_send() {} + +fn main() { + is_send::>(); +} diff --git a/tests/ui/associated-types/issue-23208.rs b/tests/ui/associated-types/issue-23208.rs new file mode 100644 index 000000000..fd4ffe5d6 --- /dev/null +++ b/tests/ui/associated-types/issue-23208.rs @@ -0,0 +1,26 @@ +// run-pass +trait TheTrait : TheSuperTrait<::Item> { + type Item; +} + +trait TheSuperTrait { + fn get(&self) -> T; +} + +impl TheTrait for i32 { + type Item = u32; +} + +impl TheSuperTrait for i32 { + fn get(&self) -> u32 { + *self as u32 + } +} + +fn foo>(t: &T) -> u32 { + t.get() +} + +fn main() { + foo::(&22); +} diff --git a/tests/ui/associated-types/issue-23595-1.rs b/tests/ui/associated-types/issue-23595-1.rs new file mode 100644 index 000000000..483c205f4 --- /dev/null +++ b/tests/ui/associated-types/issue-23595-1.rs @@ -0,0 +1,14 @@ +#![feature(associated_type_defaults)] + +use std::ops::Index; + +trait Hierarchy { + type Value; + type ChildKey; + type Children = dyn Index; + //~^ ERROR: the value of the associated types + + fn data(&self) -> Option<(Self::Value, Self::Children)>; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-23595-1.stderr b/tests/ui/associated-types/issue-23595-1.stderr new file mode 100644 index 000000000..4307477a5 --- /dev/null +++ b/tests/ui/associated-types/issue-23595-1.stderr @@ -0,0 +1,13 @@ +error[E0191]: the value of the associated types `ChildKey` (from trait `Hierarchy`), `Children` (from trait `Hierarchy`), `Value` (from trait `Hierarchy`) must be specified + --> $DIR/issue-23595-1.rs:8:58 + | +LL | type Value; + | ---------- `Value` defined here +LL | type ChildKey; + | ------------- `ChildKey` defined here +LL | type Children = dyn Index; + | ------------- `Children` defined here ^^^^^^^^^ help: specify the associated types: `Hierarchy` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/issue-23595-2.rs b/tests/ui/associated-types/issue-23595-2.rs new file mode 100644 index 000000000..2bfee7a35 --- /dev/null +++ b/tests/ui/associated-types/issue-23595-2.rs @@ -0,0 +1,10 @@ +#![feature(associated_type_defaults)] + +pub struct C {a:AType} + +pub trait A { + type B = C; + //~^ ERROR: associated type `anything_here_kills_it` not found for `Self` +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-23595-2.stderr b/tests/ui/associated-types/issue-23595-2.stderr new file mode 100644 index 000000000..dded673f6 --- /dev/null +++ b/tests/ui/associated-types/issue-23595-2.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `anything_here_kills_it` not found for `Self` + --> $DIR/issue-23595-2.rs:6:22 + | +LL | type B = C; + | ^^^^^^^^^^^^^^^^^^^^^^ associated type `anything_here_kills_it` not found + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-types/issue-24159.rs b/tests/ui/associated-types/issue-24159.rs new file mode 100644 index 000000000..49753e7bf --- /dev/null +++ b/tests/ui/associated-types/issue-24159.rs @@ -0,0 +1,37 @@ +// check-pass + +#![allow(unused)] + +trait Bar { + fn dummy(&self); +} + +trait Foo { + type A; + type B: Bar; + + fn get_b(&self) -> &Self::B; +} + +fn test_bar>(_: &B) {} + +fn test>(f: &F) { + test_bar(f.get_b()); +} + +trait Bar1 {} +trait Caz1 { + type A; + type B: Bar1; +} + +fn test1() where T: Caz1, U: Caz1 {} + +trait Bar2 {} +trait Caz2 { + type A; + type B: Bar2; +} +fn test2>() {} + +fn main() {} diff --git a/tests/ui/associated-types/issue-24204.rs b/tests/ui/associated-types/issue-24204.rs new file mode 100644 index 000000000..5a7b34595 --- /dev/null +++ b/tests/ui/associated-types/issue-24204.rs @@ -0,0 +1,25 @@ +// check-pass + +#![allow(dead_code)] + +trait MultiDispatch { + type O; +} + +trait Trait: Sized { + type A: MultiDispatch; + type B; + + fn new(u: U) -> >::O + where + Self::A: MultiDispatch; +} + +fn test>(b: i32) -> T +where + T::A: MultiDispatch, +{ + T::new(b) +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-24338.rs b/tests/ui/associated-types/issue-24338.rs new file mode 100644 index 000000000..3a2c790f8 --- /dev/null +++ b/tests/ui/associated-types/issue-24338.rs @@ -0,0 +1,21 @@ +// +// check-pass + +trait DictLike<'a> { + type ItemsIterator: Iterator; + fn get(c: Self::ItemsIterator) { + c.into_iter(); + } +} + +trait DictLike2<'a> { + type ItemsIterator: Iterator; + + fn items(&self) -> Self::ItemsIterator; + + fn get(&self) { + for _ in self.items() {} + } +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-25339.rs b/tests/ui/associated-types/issue-25339.rs new file mode 100644 index 000000000..6f8ec7009 --- /dev/null +++ b/tests/ui/associated-types/issue-25339.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![feature(associated_type_defaults)] + +use std::marker::PhantomData; + +pub trait Routing { + type Output; + fn resolve(&self, input: I); +} + +pub trait ToRouting { + type Input; + type Routing : ?Sized = dyn Routing; + fn to_routing(self) -> Self::Routing; +} + +pub struct Mount> { + action: R, + _marker: PhantomData +} + +impl> Mount { + pub fn create>(mount: &str, input: T) { + input.to_routing(); + } +} + +fn main() { +} diff --git a/tests/ui/associated-types/issue-25700-1.rs b/tests/ui/associated-types/issue-25700-1.rs new file mode 100644 index 000000000..5e71a52ba --- /dev/null +++ b/tests/ui/associated-types/issue-25700-1.rs @@ -0,0 +1,13 @@ +// run-pass +struct S(#[allow(unused_tuple_struct_fields)] Option<&'static T>); + +trait Tr { type Out; } +impl Tr for T { type Out = T; } + +impl Copy for S where S: Tr {} +impl Clone for S where S: Tr { + fn clone(&self) -> Self { *self } +} +fn main() { + S::<()>(None); +} diff --git a/tests/ui/associated-types/issue-25700-2.rs b/tests/ui/associated-types/issue-25700-2.rs new file mode 100644 index 000000000..89b1db496 --- /dev/null +++ b/tests/ui/associated-types/issue-25700-2.rs @@ -0,0 +1,23 @@ +// run-pass +pub trait Parser { + type Input; +} + +pub struct Iter(#[allow(unused_tuple_struct_fields)] P, P::Input); + +#[allow(unused_tuple_struct_fields)] +pub struct Map(P, F); +impl Parser for Map where F: FnMut(P) { + type Input = u8; +} + +trait AstId { type Untyped; } +impl AstId for u32 { type Untyped = u32; } + +fn record_type(i: Id::Untyped) -> u8 { + Iter(Map(i, |_: Id::Untyped| {}), 42).1 +} + +pub fn main() { + assert_eq!(record_type::(3), 42); +} diff --git a/tests/ui/associated-types/issue-25700.rs b/tests/ui/associated-types/issue-25700.rs new file mode 100644 index 000000000..e5b9a9752 --- /dev/null +++ b/tests/ui/associated-types/issue-25700.rs @@ -0,0 +1,14 @@ +struct S(#[allow(unused_tuple_struct_fields)] Option<&'static T>); + +trait Tr { type Out; } +impl Tr for T { type Out = T; } + +impl Copy for S where S: Tr {} +impl Clone for S where S: Tr { + fn clone(&self) -> Self { *self } +} +fn main() { + let t = S::<()>(None); + drop(t); + drop(t); //~ ERROR use of moved value +} diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr new file mode 100644 index 000000000..fa309a55c --- /dev/null +++ b/tests/ui/associated-types/issue-25700.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `t` + --> $DIR/issue-25700.rs:13:10 + | +LL | let t = S::<()>(None); + | - move occurs because `t` has type `S<()>`, which does not implement the `Copy` trait +LL | drop(t); + | - value moved here +LL | drop(t); + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/associated-types/issue-26681.rs b/tests/ui/associated-types/issue-26681.rs new file mode 100644 index 000000000..a0a8c86d9 --- /dev/null +++ b/tests/ui/associated-types/issue-26681.rs @@ -0,0 +1,20 @@ +#![feature(associated_type_defaults)] + +// This is a partial regression test for #26681, which used to fail to resolve +// `Self` in the assoc. constant, and now fails with a type mismatch because +// `Self::Fv` cannot be assumed to equal `u8` inside the trait. + +trait Foo { + type Bar; +} + +impl Foo for u8 { + type Bar = (); +} + +trait Baz { + type Fv: Foo = u8; + const C: ::Bar = 6665; //~ error: mismatched types +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-26681.stderr b/tests/ui/associated-types/issue-26681.stderr new file mode 100644 index 000000000..74411008c --- /dev/null +++ b/tests/ui/associated-types/issue-26681.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-26681.rs:17:39 + | +LL | const C: ::Bar = 6665; + | ^^^^ expected associated type, found integer + | + = note: expected associated type `<::Fv as Foo>::Bar` + found type `{integer}` + = help: consider constraining the associated type `<::Fv as Foo>::Bar` to `{integer}` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-types/issue-27675-unchecked-bounds.rs b/tests/ui/associated-types/issue-27675-unchecked-bounds.rs new file mode 100644 index 000000000..1cfc23045 --- /dev/null +++ b/tests/ui/associated-types/issue-27675-unchecked-bounds.rs @@ -0,0 +1,19 @@ +/// The compiler previously did not properly check the bound of `From` when it was used from type +/// of the dyn trait object (use in `copy_any` below). Since the associated type is under user +/// control in this usage, the compiler could be tricked to believe any type implemented any trait. +/// This would ICE, except for pure marker traits like `Copy`. It did not require providing an +/// instance of the dyn trait type, only name said type. +trait Setup { + type From: Copy; +} + +fn copy(from: &U::From) -> U::From { + *from +} + +pub fn copy_any(t: &T) -> T { + copy::>(t) + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr new file mode 100644 index 000000000..a14a273b3 --- /dev/null +++ b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-27675-unchecked-bounds.rs:15:12 + | +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `copy` + --> $DIR/issue-27675-unchecked-bounds.rs:10:12 + | +LL | fn copy(from: &U::From) -> U::From { + | ^^^^^ required by this bound in `copy` +help: consider restricting type parameter `T` + | +LL | pub fn copy_any(t: &T) -> T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-28871.rs b/tests/ui/associated-types/issue-28871.rs new file mode 100644 index 000000000..210c783de --- /dev/null +++ b/tests/ui/associated-types/issue-28871.rs @@ -0,0 +1,24 @@ +// check-pass +// Regression test for #28871. The problem is that rustc encountered +// two ways to project, one from a where clause and one from the where +// clauses on the trait definition. (In fact, in this case, the where +// clauses originated from the trait definition as well.) The true +// cause of the error is that the trait definition where clauses are +// not being normalized, and hence the two sources are considered in +// conflict, and not a duplicate. Hacky solution is to prefer where +// clauses over the data found in the trait definition. + +trait T { + type T; +} + +struct S; +impl T for S { + type T = S; +} + +trait T2 { + type T: Iterator::T>; +} + +fn main() { } diff --git a/tests/ui/associated-types/issue-31597.rs b/tests/ui/associated-types/issue-31597.rs new file mode 100644 index 000000000..2872be6d6 --- /dev/null +++ b/tests/ui/associated-types/issue-31597.rs @@ -0,0 +1,29 @@ +// check-pass +#![allow(dead_code)] +trait Make { + type Out; + + fn make() -> Self::Out; +} + +impl Make for () { + type Out = (); + + fn make() -> Self::Out {} +} + +// Also make sure we don't hit an ICE when the projection can't be known +fn f() -> ::Out { loop {} } + +// ...and that it works with a blanket impl +trait Tr { + type Assoc; +} + +impl Tr for T { + type Assoc = (); +} + +fn g() -> ::Assoc { } + +fn main() {} diff --git a/tests/ui/associated-types/issue-32350.rs b/tests/ui/associated-types/issue-32350.rs new file mode 100644 index 000000000..bda21eb0e --- /dev/null +++ b/tests/ui/associated-types/issue-32350.rs @@ -0,0 +1,29 @@ +// check-pass + +// This is another instance of the "normalizations don't work" issue with +// defaulted associated types. + +#![feature(associated_type_defaults)] + +pub trait Emitter<'a> { + type Ctxt: 'a; + type CtxtBrw: 'a = &'a Self::Ctxt; + + fn get_cx(&'a self) -> Self::CtxtBrw; +} + +struct MyCtxt; + +struct MyEmitter { + ctxt: MyCtxt +} + +impl <'a> Emitter<'a> for MyEmitter { + type Ctxt = MyCtxt; + + fn get_cx(&'a self) -> &'a MyCtxt { + &self.ctxt + } +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-36499.rs b/tests/ui/associated-types/issue-36499.rs new file mode 100644 index 000000000..7f8f13ef8 --- /dev/null +++ b/tests/ui/associated-types/issue-36499.rs @@ -0,0 +1,5 @@ +// error-pattern: aborting due to previous error + +fn main() { + 2 + +2; +} diff --git a/tests/ui/associated-types/issue-36499.stderr b/tests/ui/associated-types/issue-36499.stderr new file mode 100644 index 000000000..80e42b61d --- /dev/null +++ b/tests/ui/associated-types/issue-36499.stderr @@ -0,0 +1,14 @@ +error: leading `+` is not supported + --> $DIR/issue-36499.rs:4:9 + | +LL | 2 + +2; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - 2 + +2; +LL + 2 + 2; + | + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/issue-37808.rs b/tests/ui/associated-types/issue-37808.rs new file mode 100644 index 000000000..3701c37d0 --- /dev/null +++ b/tests/ui/associated-types/issue-37808.rs @@ -0,0 +1,19 @@ +// check-pass + +trait Parent { + type Ty; + type Assoc: Child; +} + +trait Child {} + +struct ChildWrapper(T); +impl Child for ChildWrapper where T: Child {} + +struct ParentWrapper(T); +impl> Parent for ParentWrapper { + type Ty = A; + type Assoc = ChildWrapper; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-37883.rs b/tests/ui/associated-types/issue-37883.rs new file mode 100644 index 000000000..d854f6af3 --- /dev/null +++ b/tests/ui/associated-types/issue-37883.rs @@ -0,0 +1,25 @@ +// check-pass + +use std::ops::Mul; + +fn main() {} + +trait Ring {} +trait Real: Ring {} + +trait Module: Sized + Mul<::Ring, Output = Self> { + type Ring: Ring; +} + +trait EuclideanSpace { + type Coordinates: Module; + type Real: Real; +} + +trait Translation { + fn to_vector(&self) -> E::Coordinates; + + fn powf(&self, n: ::Ring) -> E::Coordinates { + self.to_vector() * n + } +} diff --git a/tests/ui/associated-types/issue-38917.rs b/tests/ui/associated-types/issue-38917.rs new file mode 100644 index 000000000..7e898851a --- /dev/null +++ b/tests/ui/associated-types/issue-38917.rs @@ -0,0 +1,25 @@ +// check-pass + +use std::borrow::Borrow; + +trait TNode: Sized { + type ConcreteElement: TElement; +} + +trait TElement: Sized { + type ConcreteNode: TNode; +} + +trait DomTraversal { + type BorrowElement: Borrow; +} + +#[allow(dead_code)] +fn recalc_style_at() +where + E: TElement, + D: DomTraversal, +{ +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-39532.rs b/tests/ui/associated-types/issue-39532.rs new file mode 100644 index 000000000..52652cede --- /dev/null +++ b/tests/ui/associated-types/issue-39532.rs @@ -0,0 +1,14 @@ +// check-pass + +#![allow(unused)] + +trait Foo { + type Bar; + type Baz: Bar; +} + +trait Bar {} + +fn x, U>(t: &T) {} + +fn main() {} diff --git a/tests/ui/associated-types/issue-40093.rs b/tests/ui/associated-types/issue-40093.rs new file mode 100644 index 000000000..fd325ae10 --- /dev/null +++ b/tests/ui/associated-types/issue-40093.rs @@ -0,0 +1,14 @@ +// check-pass + +pub trait Test { + type Item; + type Bundle: From; +} + +fn fails() +where + T: Test, +{ +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-41868.rs b/tests/ui/associated-types/issue-41868.rs new file mode 100644 index 000000000..52bbd1f5d --- /dev/null +++ b/tests/ui/associated-types/issue-41868.rs @@ -0,0 +1,23 @@ +// check-pass + +// Defaulted assoc. types should normalize properly in impls that don't +// override them. + +#![feature(associated_type_defaults)] + +pub struct Foo; + +pub trait CanDecode: Sized { + type Output = Self; + fn read(rdr: &mut Foo) -> Option; +} + +impl CanDecode for u8 { + fn read(rdr: &mut Foo) -> Option { Some(42) } +} + +impl CanDecode for u16 { + fn read(rdr: &mut Foo) -> Option { Some(17) } +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-43475.rs b/tests/ui/associated-types/issue-43475.rs new file mode 100644 index 000000000..5f177333c --- /dev/null +++ b/tests/ui/associated-types/issue-43475.rs @@ -0,0 +1,10 @@ +// check-pass + +trait Foo { type FooT: Foo; } +impl Foo for () { type FooT = (); } +trait Bar { type BarT: Bar; } +impl Bar<()> for () { type BarT = (); } + +#[allow(dead_code)] +fn test>() { } +fn main() { } diff --git a/tests/ui/associated-types/issue-43784-associated-type.rs b/tests/ui/associated-types/issue-43784-associated-type.rs new file mode 100644 index 000000000..78815d8d3 --- /dev/null +++ b/tests/ui/associated-types/issue-43784-associated-type.rs @@ -0,0 +1,17 @@ +pub trait Partial: Copy { +} + +pub trait Complete { + type Assoc: Partial; +} + +impl Partial for T::Assoc where + T: Complete +{ +} + +impl Complete for T { + type Assoc = T; //~ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr new file mode 100644 index 000000000..50fa7d1ac --- /dev/null +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-43784-associated-type.rs:14:18 + | +LL | type Assoc = T; + | ^ the trait `Copy` is not implemented for `T` + | +note: required for `::Assoc` to implement `Partial` + --> $DIR/issue-43784-associated-type.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ +note: required by a bound in `Complete::Assoc` + --> $DIR/issue-43784-associated-type.rs:5:17 + | +LL | type Assoc: Partial; + | ^^^^^^^^^^^^^ required by this bound in `Complete::Assoc` +help: consider restricting type parameter `T` + | +LL | impl Complete for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-43924.rs b/tests/ui/associated-types/issue-43924.rs new file mode 100644 index 000000000..6a63b3e09 --- /dev/null +++ b/tests/ui/associated-types/issue-43924.rs @@ -0,0 +1,16 @@ +#![feature(associated_type_defaults)] + +// This used to cause an ICE because assoc. type defaults weren't properly +// type-checked. + +trait Foo { + type Out: Default + ToString + ?Sized = dyn ToString; //~ ERROR not satisfied +} + +impl Foo for () {} +impl Foo for () {} + +fn main() { + assert_eq!(<() as Foo>::Out::default().to_string(), "false"); + //~^ ERROR no function or associated item named `default` found for trait object +} diff --git a/tests/ui/associated-types/issue-43924.stderr b/tests/ui/associated-types/issue-43924.stderr new file mode 100644 index 000000000..526f425b2 --- /dev/null +++ b/tests/ui/associated-types/issue-43924.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `(dyn ToString + 'static): Default` is not satisfied + --> $DIR/issue-43924.rs:7:45 + | +LL | type Out: Default + ToString + ?Sized = dyn ToString; + | ^^^^^^^^^^^^ the trait `Default` is not implemented for `(dyn ToString + 'static)` + | +note: required by a bound in `Foo::Out` + --> $DIR/issue-43924.rs:7:15 + | +LL | type Out: Default + ToString + ?Sized = dyn ToString; + | ^^^^^^^ required by this bound in `Foo::Out` + +error[E0599]: no function or associated item named `default` found for trait object `(dyn ToString + 'static)` in the current scope + --> $DIR/issue-43924.rs:14:39 + | +LL | assert_eq!(<() as Foo>::Out::default().to_string(), "false"); + | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-44153.rs b/tests/ui/associated-types/issue-44153.rs new file mode 100644 index 000000000..2101cb61a --- /dev/null +++ b/tests/ui/associated-types/issue-44153.rs @@ -0,0 +1,19 @@ +pub trait Array { + type Element; +} + +pub trait Visit { + fn visit() {} +} + +impl Array for () { + type Element = (); +} + +impl<'a> Visit for () where + (): Array, +{} + +fn main() { + <() as Visit>::visit(); //~ ERROR: type mismatch resolving +} diff --git a/tests/ui/associated-types/issue-44153.stderr b/tests/ui/associated-types/issue-44153.stderr new file mode 100644 index 000000000..8bddcd955 --- /dev/null +++ b/tests/ui/associated-types/issue-44153.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `<() as Array>::Element == &()` + --> $DIR/issue-44153.rs:18:5 + | +LL | <() as Visit>::visit(); + | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array>::Element == &()` + | +note: expected this to be `&()` + --> $DIR/issue-44153.rs:10:20 + | +LL | type Element = (); + | ^^ +note: required for `()` to implement `Visit` + --> $DIR/issue-44153.rs:13:10 + | +LL | impl<'a> Visit for () where + | ^^^^^ ^^ +LL | (): Array, + | -------------- unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-47139-1.rs b/tests/ui/associated-types/issue-47139-1.rs new file mode 100644 index 000000000..c55fc3434 --- /dev/null +++ b/tests/ui/associated-types/issue-47139-1.rs @@ -0,0 +1,78 @@ +// run-pass +// Regression test for issue #47139: +// +// Coherence was encountering an (unnecessary) overflow trying to +// decide if the two impls of dummy overlap. +// +// The overflow went something like: +// +// - `&'a ?T: Insertable` ? +// - let ?T = Option ? +// - `Option: Insertable` ? +// - `Option<&'a ?U>: Insertable` ? +// - `&'a ?U: Insertable` ? +// +// While somewhere in the middle, a projection would occur, which +// broke cycle detection. +// +// It turned out that this cycle was being kicked off due to some +// extended diagnostic attempts in coherence, so removing those +// sidestepped the issue for now. + +#![allow(dead_code)] + +pub trait Insertable { + type Values; + + fn values(self) -> Self::Values; +} + +impl Insertable for Option + where + T: Insertable, + T::Values: Default, +{ + type Values = T::Values; + + fn values(self) -> Self::Values { + self.map(Insertable::values).unwrap_or_default() + } +} + +impl<'a, T> Insertable for &'a Option + where + Option<&'a T>: Insertable, +{ + type Values = as Insertable>::Values; + + fn values(self) -> Self::Values { + self.as_ref().values() + } +} + +impl<'a, T> Insertable for &'a [T] +{ + type Values = Self; + + fn values(self) -> Self::Values { + self + } +} + +trait Unimplemented { } + +trait Dummy { } + +struct Foo { t: T } + +impl<'a, U> Dummy for Foo<&'a U> + where &'a U: Insertable +{ +} + +impl Dummy for T + where T: Unimplemented +{ } + +fn main() { +} diff --git a/tests/ui/associated-types/issue-47139-2.rs b/tests/ui/associated-types/issue-47139-2.rs new file mode 100644 index 000000000..d2ef89425 --- /dev/null +++ b/tests/ui/associated-types/issue-47139-2.rs @@ -0,0 +1,66 @@ +// run-pass +// Regression test for issue #47139: +// +// Same as issue-47139-1.rs, but the impls of dummy are in the +// opposite order. This influenced the way that coherence ran and in +// some cases caused the overflow to occur when it wouldn't otherwise. +// In an effort to make the regr test more robust, I am including both +// orderings. + +#![allow(dead_code)] + +pub trait Insertable { + type Values; + + fn values(self) -> Self::Values; +} + +impl Insertable for Option + where + T: Insertable, + T::Values: Default, +{ + type Values = T::Values; + + fn values(self) -> Self::Values { + self.map(Insertable::values).unwrap_or_default() + } +} + +impl<'a, T> Insertable for &'a Option + where + Option<&'a T>: Insertable, +{ + type Values = as Insertable>::Values; + + fn values(self) -> Self::Values { + self.as_ref().values() + } +} + +impl<'a, T> Insertable for &'a [T] +{ + type Values = Self; + + fn values(self) -> Self::Values { + self + } +} + +trait Unimplemented { } + +trait Dummy { } + +struct Foo { t: T } + +impl Dummy for T + where T: Unimplemented +{ } + +impl<'a, U> Dummy for Foo<&'a U> + where &'a U: Insertable +{ +} + +fn main() { +} diff --git a/tests/ui/associated-types/issue-47385.rs b/tests/ui/associated-types/issue-47385.rs new file mode 100644 index 000000000..d43d674e9 --- /dev/null +++ b/tests/ui/associated-types/issue-47385.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(associated_type_defaults)] + +pub struct Foo; + +pub trait Bar: From<::Input> { + type Input = Self; +} + +impl Bar for Foo { + // Will compile with explicit type: + // type Input = Self; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-47814.rs b/tests/ui/associated-types/issue-47814.rs new file mode 100644 index 000000000..90e8a3bc2 --- /dev/null +++ b/tests/ui/associated-types/issue-47814.rs @@ -0,0 +1,13 @@ +struct ArpIPv4<'a> { + s: &'a u8 +} + +impl<'a> ArpIPv4<'a> { + const LENGTH: usize = 20; + + pub fn to_buffer() -> [u8; Self::LENGTH] { //~ ERROR generic `Self` types are currently not permitted in anonymous constants + unimplemented!() + } +} + +pub fn main() {} diff --git a/tests/ui/associated-types/issue-47814.stderr b/tests/ui/associated-types/issue-47814.stderr new file mode 100644 index 000000000..2e4ddb811 --- /dev/null +++ b/tests/ui/associated-types/issue-47814.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-47814.rs:8:32 + | +LL | pub fn to_buffer() -> [u8; Self::LENGTH] { + | ^^^^ + | +note: not a concrete type + --> $DIR/issue-47814.rs:5:10 + | +LL | impl<'a> ArpIPv4<'a> { + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/issue-48010.rs b/tests/ui/associated-types/issue-48010.rs new file mode 100644 index 000000000..70e30c132 --- /dev/null +++ b/tests/ui/associated-types/issue-48010.rs @@ -0,0 +1,23 @@ +// check-pass + +#![crate_type = "lib"] + +pub struct Foo; + +pub struct Path { + _inner: T::Slice, +} + +pub trait Bar: Sized { + type Slice: ?Sized; + + fn open(_: &Path); +} + +impl Bar for Foo { + type Slice = [u8]; + + fn open(_: &Path) { + unimplemented!() + } +} diff --git a/tests/ui/associated-types/issue-48551.rs b/tests/ui/associated-types/issue-48551.rs new file mode 100644 index 000000000..b95a4832b --- /dev/null +++ b/tests/ui/associated-types/issue-48551.rs @@ -0,0 +1,34 @@ +// check-pass +// Regression test for #48551. Covers a case where duplicate candidates +// arose during associated type projection. + +use std::ops::{Mul, MulAssign}; + +pub trait ClosedMul: Sized + Mul + MulAssign {} +impl ClosedMul for T +where + T: Mul + MulAssign, +{ +} + +pub trait InnerSpace: ClosedMul<::Real> { + type Real; +} + +pub trait FiniteDimVectorSpace: ClosedMul<::Field> { + type Field; +} + +pub trait FiniteDimInnerSpace + : InnerSpace + FiniteDimVectorSpace::Real> { +} + +pub trait EuclideanSpace: ClosedMul<::Real> { + type Coordinates: FiniteDimInnerSpace + + Mul + + MulAssign; + + type Real; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-50301.rs b/tests/ui/associated-types/issue-50301.rs new file mode 100644 index 000000000..47ee3e7ad --- /dev/null +++ b/tests/ui/associated-types/issue-50301.rs @@ -0,0 +1,31 @@ +// Tests that HRTBs are correctly accepted -- https://github.com/rust-lang/rust/issues/50301 +// check-pass +trait Trait +where + for<'a> &'a Self::IntoIter: IntoIterator, +{ + type IntoIter; + fn get(&self) -> Self::IntoIter; +} + +struct Impl(Vec); + +impl Trait for Impl { + type IntoIter = ImplIntoIter; + fn get(&self) -> Self::IntoIter { + ImplIntoIter(self.0.clone()) + } +} + +struct ImplIntoIter(Vec); + +impl<'a> IntoIterator for &'a ImplIntoIter { + type Item = ::Item; + type IntoIter = std::iter::Cloned>; + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter().cloned() + } +} + +fn main() { +} diff --git a/tests/ui/associated-types/issue-54108.rs b/tests/ui/associated-types/issue-54108.rs new file mode 100644 index 000000000..87f67ce4b --- /dev/null +++ b/tests/ui/associated-types/issue-54108.rs @@ -0,0 +1,41 @@ +use std::ops::Add; + +pub trait Encoder { + type Size: Add; + + fn foo(&self) -> Self::Size; +} + +pub trait SubEncoder: Encoder { + type ActualSize; + + fn bar(&self) -> Self::Size; +} + +impl Encoder for T +where + T: SubEncoder, +{ + type Size = ::ActualSize; + //~^ ERROR: cannot add `::ActualSize` to `::ActualSize` + + fn foo(&self) -> Self::Size { + self.bar() + self.bar() + } +} + +pub struct UnitEncoder; + +impl SubEncoder for UnitEncoder { + type ActualSize = (); + + fn bar(&self) {} +} + +pub fn fun(encoder: &R) { + encoder.foo(); +} + +fn main() { + fun(&UnitEncoder {}); +} diff --git a/tests/ui/associated-types/issue-54108.stderr b/tests/ui/associated-types/issue-54108.stderr new file mode 100644 index 000000000..6ff5e4542 --- /dev/null +++ b/tests/ui/associated-types/issue-54108.stderr @@ -0,0 +1,20 @@ +error[E0277]: cannot add `::ActualSize` to `::ActualSize` + --> $DIR/issue-54108.rs:19:17 + | +LL | type Size = ::ActualSize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `::ActualSize + ::ActualSize` + | + = help: the trait `Add` is not implemented for `::ActualSize` +note: required by a bound in `Encoder::Size` + --> $DIR/issue-54108.rs:4:16 + | +LL | type Size: Add; + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` +help: consider further restricting the associated type + | +LL | T: SubEncoder, ::ActualSize: Add + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-54182-1.rs b/tests/ui/associated-types/issue-54182-1.rs new file mode 100644 index 000000000..1a1e98cba --- /dev/null +++ b/tests/ui/associated-types/issue-54182-1.rs @@ -0,0 +1,92 @@ +// run-pass + +// Tests that the return type of trait methods is correctly normalized when +// checking that a method in an impl matches the trait definition when the +// return type involves a defaulted associated type. +// ie. the trait has a method with return type `-> Self::R`, and `type R = ()`, +// but the impl leaves out the return type (resulting in `()`). +// Note that specialization is not involved in this test; no items in +// implementations may be overridden. If they were, the normalization wouldn't +// happen. + +#![feature(associated_type_defaults)] + +macro_rules! overload { + ($a:expr, $b:expr) => { + overload::overload2($a, $b) + }; + ($a:expr, $b:expr, $c:expr) => { + overload::overload3($a, $b, $c) + } +} + +fn main() { + let () = overload!(42, true); + + let r: f32 = overload!("Hello world", 13.0); + assert_eq!(r, 13.0); + + let () = overload!(42, true, 42.5); + + let r: i32 = overload!("Hello world", 13.0, 42); + assert_eq!(r, 42); +} + +mod overload { + /// This trait has an assoc. type defaulting to `()`, and a required method returning a value + /// of that assoc. type. + pub trait Overload { + // type R; + type R = (); + fn overload(self) -> Self::R; + } + + // overloads for 2 args + impl Overload for (i32, bool) { + // type R = (); + + /// This function has no return type specified, and so defaults to `()`. + /// + /// This should work, but didn't, until RFC 2532 was implemented. + fn overload(self) /*-> Self::R*/ { + let (a, b) = self; // destructure args + println!("i32 and bool {:?}", (a, b)); + } + } + impl<'a> Overload for (&'a str, f32) { + type R = f32; + fn overload(self) -> Self::R { + let (a, b) = self; // destructure args + println!("&str and f32 {:?}", (a, b)); + b + } + } + + // overloads for 3 args + impl Overload for (i32, bool, f32) { + // type R = (); + fn overload(self) /*-> Self::R*/ { + let (a, b, c) = self; // destructure args + println!("i32 and bool and f32 {:?}", (a, b, c)); + } + } + impl<'a> Overload for (&'a str, f32, i32) { + type R = i32; + fn overload(self) -> Self::R { + let (a, b, c) = self; // destructure args + println!("&str and f32 and i32: {:?}", (a, b, c)); + c + } + } + + // overloads for more args + // ... + + pub fn overload2(a: A, b: B) -> R where (A, B): Overload { + (a, b).overload() + } + + pub fn overload3(a: A, b: B, c: C) -> R where (A, B, C): Overload { + (a, b, c).overload() + } +} diff --git a/tests/ui/associated-types/issue-54182-2.rs b/tests/ui/associated-types/issue-54182-2.rs new file mode 100644 index 000000000..c88c76631 --- /dev/null +++ b/tests/ui/associated-types/issue-54182-2.rs @@ -0,0 +1,19 @@ +// check-pass + +// Before RFC 2532, normalizing a defaulted assoc. type didn't work at all, +// unless the impl in question overrides that type, which makes the default +// pointless. + +#![feature(associated_type_defaults)] + +trait Tr { + type Assoc = (); +} + +impl Tr for () {} + +fn f(thing: <() as Tr>::Assoc) { + let c: () = thing; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-54467.rs b/tests/ui/associated-types/issue-54467.rs new file mode 100644 index 000000000..734bf2768 --- /dev/null +++ b/tests/ui/associated-types/issue-54467.rs @@ -0,0 +1,46 @@ +// run-pass + +pub trait Stream { + type Item; + type Error; +} + +pub trait ParseError { + type Output; +} + +impl ParseError for u32 { + type Output = (); +} + +impl Stream for () { + type Item = char; + type Error = u32; +} + +pub struct Lex<'a, I> + where I: Stream, + I::Error: ParseError, + <::Error as ParseError>::Output: 'a +{ + x: &'a >::Output +} + +pub struct Reserved<'a, I> where + I: Stream + 'a, + I::Error: ParseError, + <::Error as ParseError>::Output: 'a + +{ + x: Lex<'a, I> +} + +fn main() { + let r: Reserved<()> = Reserved { + x: Lex { + x: &() + } + }; + + let _v = r.x.x; +} diff --git a/tests/ui/associated-types/issue-55846.rs b/tests/ui/associated-types/issue-55846.rs new file mode 100644 index 000000000..bd7667523 --- /dev/null +++ b/tests/ui/associated-types/issue-55846.rs @@ -0,0 +1,39 @@ +// run-pass + +// Regression test for #55846, which once caused an ICE. + +use std::marker::PhantomData; + +struct Foo; + +struct Bar { + a: PhantomData, +} + +impl Fooifier for Foo { + type Assoc = Foo; +} + +trait Fooifier { + type Assoc; +} + +trait Barifier { + fn barify(); +} + +impl Barifier for Bar { + fn barify() { + println!("All correct!"); + } +} + +impl Bar<::Assoc> { + fn this_shouldnt_crash() { + ::Assoc>>::barify(); + } +} + +fn main() { + Bar::::this_shouldnt_crash(); +} diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs new file mode 100644 index 000000000..551f13ee1 --- /dev/null +++ b/tests/ui/associated-types/issue-59324.rs @@ -0,0 +1,26 @@ +trait NotFoo {} + +pub trait Foo: NotFoo { + type OnlyFoo; +} + +pub trait Service { + type AssocType; +} + +pub trait ThriftService: +//~^ ERROR the trait bound `Bug: Foo` is not satisfied +//~| ERROR the trait bound `Bug: Foo` is not satisfied + Service::OnlyFoo> +{ + fn get_service( + //~^ ERROR the trait bound `Bug: Foo` is not satisfied + &self, + ) -> Self::AssocType; + //~^ ERROR the trait bound `Bug: Foo` is not satisfied +} + +fn with_factory(factory: dyn ThriftService<()>) {} +//~^ ERROR the trait bound `(): Foo` is not satisfied + +fn main() {} diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr new file mode 100644 index 000000000..a84b599b5 --- /dev/null +++ b/tests/ui/associated-types/issue-59324.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `Bug: Foo` is not satisfied + --> $DIR/issue-59324.rs:11:1 + | +LL | / pub trait ThriftService: +LL | | +LL | | +LL | | Service::OnlyFoo> + | |______________________________________________^ the trait `Foo` is not implemented for `Bug` + | +help: consider further restricting this bound + | +LL | pub trait ThriftService: + | +++++ + +error[E0277]: the trait bound `Bug: Foo` is not satisfied + --> $DIR/issue-59324.rs:11:1 + | +LL | / pub trait ThriftService: +LL | | +LL | | +LL | | Service::OnlyFoo> +... | +LL | | +LL | | } + | |_^ the trait `Foo` is not implemented for `Bug` + | +help: consider further restricting this bound + | +LL | pub trait ThriftService: + | +++++ + +error[E0277]: the trait bound `Bug: Foo` is not satisfied + --> $DIR/issue-59324.rs:16:5 + | +LL | / fn get_service( +LL | | +LL | | &self, +LL | | ) -> Self::AssocType; + | |_________________________^ the trait `Foo` is not implemented for `Bug` + | +help: consider further restricting this bound + | +LL | pub trait ThriftService: + | +++++ + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/issue-59324.rs:23:29 + | +LL | fn with_factory(factory: dyn ThriftService<()>) {} + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + +error[E0277]: the trait bound `Bug: Foo` is not satisfied + --> $DIR/issue-59324.rs:19:10 + | +LL | ) -> Self::AssocType; + | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` + | +help: consider further restricting this bound + | +LL | pub trait ThriftService: + | +++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-62200.rs b/tests/ui/associated-types/issue-62200.rs new file mode 100644 index 000000000..499bbd6b6 --- /dev/null +++ b/tests/ui/associated-types/issue-62200.rs @@ -0,0 +1,16 @@ +struct S {} + +trait T<'a> { + type A; +} + +impl T<'_> for S { + type A = u32; +} + +fn foo(x: impl Fn(>::A) -> >::A) {} +//~^ ERROR binding for associated type `Output` references an anonymous lifetime +//~| NOTE lifetimes appearing in an associated or opaque type are not considered constrained +//~| NOTE consider introducing a named lifetime parameter + +fn main() {} diff --git a/tests/ui/associated-types/issue-62200.stderr b/tests/ui/associated-types/issue-62200.stderr new file mode 100644 index 000000000..04f0728f5 --- /dev/null +++ b/tests/ui/associated-types/issue-62200.stderr @@ -0,0 +1,12 @@ +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/issue-62200.rs:11:39 + | +LL | fn foo(x: impl Fn(>::A) -> >::A) {} + | ^^^^^^^^^^^^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/associated-types/issue-63591.rs b/tests/ui/associated-types/issue-63591.rs new file mode 100644 index 000000000..4d2e39f4d --- /dev/null +++ b/tests/ui/associated-types/issue-63591.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(associated_type_bounds)] +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait Bar { type Assoc; } + +trait Thing { + type Out; + fn func() -> Self::Out; +} + +struct AssocIsCopy; +impl Bar for AssocIsCopy { type Assoc = u8; } + +impl Thing for AssocIsCopy { + type Out = impl Bar; + + fn func() -> Self::Out { + AssocIsCopy + } +} diff --git a/tests/ui/associated-types/issue-63593.rs b/tests/ui/associated-types/issue-63593.rs new file mode 100644 index 000000000..8dbc24c06 --- /dev/null +++ b/tests/ui/associated-types/issue-63593.rs @@ -0,0 +1,13 @@ +#![feature(associated_type_defaults)] + +// Tests that `Self` is not assumed to implement `Sized` when used as an +// associated type default. + +trait Inner {} + +trait MyTrait { + type This = Self; //~ error: size for values of type `Self` cannot be known + fn something>(i: I); +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-63593.stderr b/tests/ui/associated-types/issue-63593.stderr new file mode 100644 index 000000000..f643ec3ff --- /dev/null +++ b/tests/ui/associated-types/issue-63593.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-63593.rs:9:17 + | +LL | type This = Self; + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `MyTrait::This` + --> $DIR/issue-63593.rs:9:5 + | +LL | type This = Self; + | ^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::This` +help: consider further restricting `Self` + | +LL | trait MyTrait: Sized { + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-64848.rs b/tests/ui/associated-types/issue-64848.rs new file mode 100644 index 000000000..77712168a --- /dev/null +++ b/tests/ui/associated-types/issue-64848.rs @@ -0,0 +1,29 @@ +// build-pass + +trait AssociatedConstant { + const DATA: (); +} + +impl AssociatedConstant for F +where + F: FnOnce() -> T, + T: AssociatedConstant, +{ + const DATA: () = T::DATA; +} + +impl AssociatedConstant for () { + const DATA: () = (); +} + +fn foo() -> impl AssociatedConstant { + () +} + +fn get_data(_: T) -> &'static () { + &T::DATA +} + +fn main() { + get_data(foo); +} diff --git a/tests/ui/associated-types/issue-64855-2.rs b/tests/ui/associated-types/issue-64855-2.rs new file mode 100644 index 000000000..1d53bd570 --- /dev/null +++ b/tests/ui/associated-types/issue-64855-2.rs @@ -0,0 +1,5 @@ +// check-pass + +pub struct Bar<'a>(&'a Self) where Self: ; + +fn main() {} diff --git a/tests/ui/associated-types/issue-64855.rs b/tests/ui/associated-types/issue-64855.rs new file mode 100644 index 000000000..81cf3ae6e --- /dev/null +++ b/tests/ui/associated-types/issue-64855.rs @@ -0,0 +1,8 @@ +pub trait Foo { + type Type; +} + +pub struct Bar(::Type) where Self: ; +//~^ ERROR the trait bound `Bar: Foo` is not satisfied + +fn main() {} diff --git a/tests/ui/associated-types/issue-64855.stderr b/tests/ui/associated-types/issue-64855.stderr new file mode 100644 index 000000000..6ad795c11 --- /dev/null +++ b/tests/ui/associated-types/issue-64855.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `Bar: Foo` is not satisfied + --> $DIR/issue-64855.rs:5:19 + | +LL | pub struct Bar(::Type) where Self: ; + | ^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-65774-1.rs b/tests/ui/associated-types/issue-65774-1.rs new file mode 100644 index 000000000..934514055 --- /dev/null +++ b/tests/ui/associated-types/issue-65774-1.rs @@ -0,0 +1,58 @@ +#![feature(associated_type_defaults)] + +trait MyDisplay { fn method(&self) { } } + +impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + +struct T; + +trait MPU { + type MpuConfig: MyDisplay = T; + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied +} + +struct S; + +impl MPU for S { } + +trait MyWrite { + fn my_write(&self, _: &dyn MyDisplay) { } +} + +trait ProcessType { + fn process_detail_fmt(&self, _: &mut dyn MyWrite); +} + +struct Process; + +impl ProcessType for Process { + fn process_detail_fmt(&self, writer: &mut dyn MyWrite) + { + + let mut val: Option<::MpuConfig> = None; + let valref: &mut ::MpuConfig = val.as_mut().unwrap(); + + // // This causes a different ICE (but its similar if you squint right): + // // + // // `Unimplemented` selecting `Binder()` during codegen + // + // writer.my_write(valref) + + // This one causes the ICE: + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), + // depth=1),Unimplemented) + let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied + closure(valref); + } +} + +fn create() -> &'static dyn ProcessType { + let input: Option<&mut Process> = None; + let process: &mut Process = input.unwrap(); + process +} + +pub fn main() { + create(); +} diff --git a/tests/ui/associated-types/issue-65774-1.stderr b/tests/ui/associated-types/issue-65774-1.stderr new file mode 100644 index 000000000..91b557555 --- /dev/null +++ b/tests/ui/associated-types/issue-65774-1.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-1.rs:10:33 + | +LL | type MpuConfig: MyDisplay = T; + | ^ the trait `MyDisplay` is not implemented for `T` + | + = help: the trait `MyDisplay` is implemented for `&'a mut T` +note: required by a bound in `MPU::MpuConfig` + --> $DIR/issue-65774-1.rs:10:21 + | +LL | type MpuConfig: MyDisplay = T; + | ^^^^^^^^^ required by this bound in `MPU::MpuConfig` + +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-1.rs:44:76 + | +LL | let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | + = help: the trait `MyDisplay` is implemented for `&'a mut T` +note: required for `&mut T` to implement `MyDisplay` + --> $DIR/issue-65774-1.rs:5:24 + | +LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + | --------- ^^^^^^^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `&mut T` to the object type `dyn MyDisplay` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-65774-2.rs b/tests/ui/associated-types/issue-65774-2.rs new file mode 100644 index 000000000..171e0893b --- /dev/null +++ b/tests/ui/associated-types/issue-65774-2.rs @@ -0,0 +1,58 @@ +#![feature(associated_type_defaults)] + +trait MyDisplay { fn method(&self) { } } + +impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + +struct T; + +trait MPU { + type MpuConfig: MyDisplay = T; + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied +} + +struct S; + +impl MPU for S { } + +trait MyWrite { + fn my_write(&self, _: &dyn MyDisplay) { } +} + +trait ProcessType { + fn process_detail_fmt(&self, _: &mut dyn MyWrite); +} + +struct Process; + +impl ProcessType for Process { + fn process_detail_fmt(&self, writer: &mut dyn MyWrite) + { + + let mut val: Option<::MpuConfig> = None; + let valref: &mut ::MpuConfig = val.as_mut().unwrap(); + + // // This causes a different ICE (but its similar if you squint right): + // // + // // `Unimplemented` selecting `Binder()` during codegen + // + writer.my_write(valref) + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied + + // This one causes the ICE: + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), + // depth=1),Unimplemented) + /*let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + closure(valref);*/ + } +} + +fn create() -> &'static dyn ProcessType { + let input: Option<&mut Process> = None; + let process: &mut Process = input.unwrap(); + process +} + +pub fn main() { + create(); +} diff --git a/tests/ui/associated-types/issue-65774-2.stderr b/tests/ui/associated-types/issue-65774-2.stderr new file mode 100644 index 000000000..c22302cdc --- /dev/null +++ b/tests/ui/associated-types/issue-65774-2.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-2.rs:10:33 + | +LL | type MpuConfig: MyDisplay = T; + | ^ the trait `MyDisplay` is not implemented for `T` + | + = help: the trait `MyDisplay` is implemented for `&'a mut T` +note: required by a bound in `MPU::MpuConfig` + --> $DIR/issue-65774-2.rs:10:21 + | +LL | type MpuConfig: MyDisplay = T; + | ^^^^^^^^^ required by this bound in `MPU::MpuConfig` + +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-2.rs:39:25 + | +LL | writer.my_write(valref) + | ^^^^^^ the trait `MyDisplay` is not implemented for `T` + | + = help: the trait `MyDisplay` is implemented for `&'a mut T` + = note: required for the cast from `T` to the object type `dyn MyDisplay` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-65934.rs b/tests/ui/associated-types/issue-65934.rs new file mode 100644 index 000000000..e17b11c5e --- /dev/null +++ b/tests/ui/associated-types/issue-65934.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Trait { + type Assoc; +} + +impl Trait for () { + type Assoc = (); +} + +fn unit() -> impl Into<<() as Trait>::Assoc> {} + +pub fn ice() { + Into::into(unit()); +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-67684.rs b/tests/ui/associated-types/issue-67684.rs new file mode 100644 index 000000000..49efe8a1b --- /dev/null +++ b/tests/ui/associated-types/issue-67684.rs @@ -0,0 +1,62 @@ +// check-pass + +#![allow(dead_code)] + +trait ParseError { + type StreamError; +} + +impl ParseError for T { + type StreamError = (); +} + +trait Stream { + type Item; + type Error: ParseError; +} + +trait Parser +where + ::PartialState: Default, +{ + type PartialState; + fn parse_mode(_: &Self, _: Self::PartialState) { + loop {} + } +} + +impl Stream for () { + type Item = (); + type Error = (); +} + +impl Parser for () { + type PartialState = (); +} + +struct AndThen(core::marker::PhantomData<(A, B)>); + +impl Parser for AndThen +where + A: Stream, + B: Into<::StreamError>, +{ + type PartialState = (); +} + +fn expr() -> impl Parser +where + A: Stream::Item>, +{ + AndThen::(core::marker::PhantomData) +} + +fn parse_mode_impl() +where + ::Error: ParseError, + A: Stream::Item>, +{ + Parser::parse_mode(&expr::(), Default::default()) +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-69398.rs b/tests/ui/associated-types/issue-69398.rs new file mode 100644 index 000000000..ca3d66b1c --- /dev/null +++ b/tests/ui/associated-types/issue-69398.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Foo { + type Bar; +} + +pub trait Broken { + type Assoc; + fn broken(&self) where Self::Assoc: Foo; +} + +impl Broken for T { + type Assoc = (); + fn broken(&self) where Self::Assoc: Foo { + let _x: ::Bar; + } +} + +fn main() { + let _m: &dyn Broken = &(); +} diff --git a/tests/ui/associated-types/issue-71113.rs b/tests/ui/associated-types/issue-71113.rs new file mode 100644 index 000000000..48de89127 --- /dev/null +++ b/tests/ui/associated-types/issue-71113.rs @@ -0,0 +1,16 @@ +// check-pass + +use std::borrow::Cow; + +enum _Recursive<'a> +where + Self: ToOwned> +{ + Variant(MyCow<'a, _Recursive<'a>>), +} + +pub struct Wrapper(T); + +pub struct MyCow<'a, T: ToOwned> + 'a>(Wrapper>); + +fn main() {} diff --git a/tests/ui/associated-types/issue-72806.rs b/tests/ui/associated-types/issue-72806.rs new file mode 100644 index 000000000..947582503 --- /dev/null +++ b/tests/ui/associated-types/issue-72806.rs @@ -0,0 +1,21 @@ +trait Bar { + type Ok; + type Sibling: Bar2; +} +trait Bar2 { + type Ok; +} + +struct Foo; +struct Foo2; + +impl Bar for Foo { + type Ok = (); + type Sibling = Foo2; + //~^ ERROR type mismatch resolving `::Ok == char` +} +impl Bar2 for Foo2 { + type Ok = u32; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-72806.stderr b/tests/ui/associated-types/issue-72806.stderr new file mode 100644 index 000000000..e95943f34 --- /dev/null +++ b/tests/ui/associated-types/issue-72806.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `::Ok == char` + --> $DIR/issue-72806.rs:14:20 + | +LL | type Sibling = Foo2; + | ^^^^ type mismatch resolving `::Ok == char` + | +note: expected this to be `char` + --> $DIR/issue-72806.rs:18:15 + | +LL | type Ok = u32; + | ^^^ +note: required by a bound in `Bar::Sibling` + --> $DIR/issue-72806.rs:3:24 + | +LL | type Sibling: Bar2; + | ^^^^^^^ required by this bound in `Bar::Sibling` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-76179.rs b/tests/ui/associated-types/issue-76179.rs new file mode 100644 index 000000000..0e086968b --- /dev/null +++ b/tests/ui/associated-types/issue-76179.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(associated_type_defaults)] + +use std::io::Read; + +trait View { + type Deserializers: Deserializer; + type RequestParams = DefaultRequestParams; +} + +struct DefaultRequestParams; + +trait Deserializer { + type Item; + fn deserialize(r: impl Read) -> Self::Item; +} + +fn main() {} diff --git a/tests/ui/associated-types/issue-82079.rs b/tests/ui/associated-types/issue-82079.rs new file mode 100644 index 000000000..8b3bad707 --- /dev/null +++ b/tests/ui/associated-types/issue-82079.rs @@ -0,0 +1,124 @@ +// revisions: default miropt +// check-pass +//[miropt]compile-flags: -Z mir-opt-level=3 +// -^ This flag is for #96395 as a regression test. + +mod convenience_operators { + use crate::{Op, Relation}; + use std::ops::AddAssign; + use std::ops::Mul; + + impl Relation { + pub fn map D2 + 'static, D2: 'static>( + self, + f: F, + ) -> Relation> { + self.map_dr(move |x, r| (f(x), r)) + } + } + + impl> Relation { + pub fn semijoin, R2, R3: AddAssign>( + self, + other: Relation, + ) -> Relation> + where + C::R: Mul, + { + self.join(other.map(|x| (x, ()))).map(|(k, x, ())| (k, x)) + } + } +} + +mod core { + mod operator { + mod join { + use super::Op; + use crate::core::Relation; + use std::ops::{AddAssign, Mul}; + struct Join { + _left: LC, + _right: RC, + } + impl< + LC: Op, + RC: Op, + K: 'static, + LD: 'static, + LR: AddAssign + Mul, + RD: 'static, + RR: AddAssign, + OR: AddAssign, + > Op for Join + { + type D = (K, LD, RD); + type R = OR; + } + impl> Relation { + pub fn join, D2: 'static, OR: AddAssign>( + self, + other: Relation, + ) -> Relation> + where + C::R: Mul, + { + Relation { + inner: Join { + _left: self.inner, + _right: other.inner, + }, + } + } + } + } + mod map { + use super::Op; + use crate::core::Relation; + use std::ops::AddAssign; + struct Map { + _inner: C, + _op: MF, + } + impl< + D1, + R1, + D2: 'static, + R2: AddAssign, + C: Op, + MF: Fn(D1, R1) -> (D2, R2), + > Op for Map + { + type D = D2; + type R = R2; + } + impl Relation { + pub fn map_dr (D2, R2), D2: 'static, R2: AddAssign>( + self, + f: F, + ) -> Relation> { + Relation { + inner: Map { + _inner: self.inner, + _op: f, + }, + } + } + } + } + use std::ops::AddAssign; + pub trait Op { + type D: 'static; + type R: AddAssign; + } + } + pub use self::operator::Op; + #[derive(Clone)] + pub struct Relation { + inner: C, + } +} + +use self::core::Op; +pub use self::core::Relation; + +fn main() {} diff --git a/tests/ui/associated-types/issue-85103.rs b/tests/ui/associated-types/issue-85103.rs new file mode 100644 index 000000000..9c6a419e9 --- /dev/null +++ b/tests/ui/associated-types/issue-85103.rs @@ -0,0 +1,9 @@ +#![feature(rustc_attrs)] + +use std::borrow::Cow; + +#[rustc_layout(debug)] +type Edges<'a, E> = Cow<'a, [E]>; +//~^ 6:1: 6:18: unable to determine layout for `<[E] as ToOwned>::Owned` because `<[E] as ToOwned>::Owned` cannot be normalized + +fn main() {} diff --git a/tests/ui/associated-types/issue-85103.stderr b/tests/ui/associated-types/issue-85103.stderr new file mode 100644 index 000000000..17f714807 --- /dev/null +++ b/tests/ui/associated-types/issue-85103.stderr @@ -0,0 +1,8 @@ +error: unable to determine layout for `<[E] as ToOwned>::Owned` because `<[E] as ToOwned>::Owned` cannot be normalized + --> $DIR/issue-85103.rs:6:1 + | +LL | type Edges<'a, E> = Cow<'a, [E]>; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-types/issue-87261.rs b/tests/ui/associated-types/issue-87261.rs new file mode 100644 index 000000000..e8548d402 --- /dev/null +++ b/tests/ui/associated-types/issue-87261.rs @@ -0,0 +1,99 @@ +trait Foo {} + +trait Trait { + type Associated; +} +trait DerivedTrait: Trait {} +trait GenericTrait { + type Associated; +} + +struct Impl; +impl Foo for Impl {} +impl Trait for Impl { + type Associated = (); +} +impl DerivedTrait for Impl {} +impl GenericTrait for Impl { + type Associated = (); +} + +fn returns_opaque() -> impl Trait + 'static { + Impl +} +fn returns_opaque_derived() -> impl DerivedTrait + 'static { + Impl +} +fn returns_opaque_foo() -> impl Trait + Foo { + Impl +} +fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { + Impl +} +fn returns_opaque_generic() -> impl GenericTrait<()> + 'static { + Impl +} +fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { + Impl +} +fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { + Impl +} + +fn accepts_trait>(_: T) {} +fn accepts_generic_trait>(_: T) {} + +fn check_generics(a: A, b: B, c: C, d: D, e: E, f: F, g: G) +where + A: Trait + 'static, + B: DerivedTrait + 'static, + C: Trait + Foo, + D: DerivedTrait + Foo, + E: GenericTrait<()> + 'static, + F: GenericTrait<()> + Foo, + G: GenericTrait<()> + GenericTrait, +{ + accepts_trait(a); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(b); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(c); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(d); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_generic_trait(e); + //~^ ERROR type mismatch resolving `>::Associated == ()` + + accepts_generic_trait(f); + //~^ ERROR type mismatch resolving `>::Associated == ()` + + accepts_generic_trait(g); + //~^ ERROR type mismatch resolving `>::Associated == ()` +} + +fn main() { + accepts_trait(returns_opaque()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(returns_opaque_derived()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(returns_opaque_foo()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_trait(returns_opaque_derived_foo()); + //~^ ERROR type mismatch resolving `::Associated == ()` + + accepts_generic_trait(returns_opaque_generic()); + //~^ ERROR type mismatch resolving ` + 'static as GenericTrait<()>>::Associated == ()` + + accepts_generic_trait(returns_opaque_generic_foo()); + //~^ ERROR type mismatch resolving ` + Foo as GenericTrait<()>>::Associated == ()` + + accepts_generic_trait(returns_opaque_generic_duplicate()); + //~^ ERROR type mismatch resolving ` + GenericTrait as GenericTrait<()>>::Associated == ()` +} diff --git a/tests/ui/associated-types/issue-87261.stderr b/tests/ui/associated-types/issue-87261.stderr new file mode 100644 index 000000000..2cce6b947 --- /dev/null +++ b/tests/ui/associated-types/issue-87261.stderr @@ -0,0 +1,294 @@ +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:56:19 + | +LL | accepts_trait(a); + | ------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` +help: consider constraining the associated type `::Associated` to `()` + | +LL | A: Trait + 'static, + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:59:19 + | +LL | accepts_trait(b); + | ------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:62:19 + | +LL | accepts_trait(c); + | ------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` +help: consider constraining the associated type `::Associated` to `()` + | +LL | C: Trait + Foo, + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:65:19 + | +LL | accepts_trait(d); + | ------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` + +error[E0271]: type mismatch resolving `>::Associated == ()` + --> $DIR/issue-87261.rs:68:27 + | +LL | accepts_generic_trait(e); + | --------------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `>::Associated` +note: required by a bound in `accepts_generic_trait` + --> $DIR/issue-87261.rs:44:46 + | +LL | fn accepts_generic_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` +help: consider constraining the associated type `>::Associated` to `()` + | +LL | E: GenericTrait<(), Associated = ()> + 'static, + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `>::Associated == ()` + --> $DIR/issue-87261.rs:71:27 + | +LL | accepts_generic_trait(f); + | --------------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `>::Associated` +note: required by a bound in `accepts_generic_trait` + --> $DIR/issue-87261.rs:44:46 + | +LL | fn accepts_generic_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` +help: consider constraining the associated type `>::Associated` to `()` + | +LL | F: GenericTrait<(), Associated = ()> + Foo, + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `>::Associated == ()` + --> $DIR/issue-87261.rs:74:27 + | +LL | accepts_generic_trait(g); + | --------------------- ^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `>::Associated` + = help: consider constraining the associated type `>::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `accepts_generic_trait` + --> $DIR/issue-87261.rs:44:46 + | +LL | fn accepts_generic_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:79:19 + | +LL | fn returns_opaque() -> impl Trait + 'static { + | -------------------- the found opaque type +... +LL | accepts_trait(returns_opaque()); + | ------------- ^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` +help: consider constraining the associated type `::Associated` to `()` + | +LL | fn returns_opaque() -> impl Trait + 'static { + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:82:19 + | +LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { + | --------------------------- the found opaque type +... +LL | accepts_trait(returns_opaque_derived()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` +help: consider constraining the associated type `::Associated` to `()` + | +LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static { + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:85:19 + | +LL | fn returns_opaque_foo() -> impl Trait + Foo { + | ---------------- the found opaque type +... +LL | accepts_trait(returns_opaque_foo()); + | ------------- ^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` +help: consider constraining the associated type `::Associated` to `()` + | +LL | fn returns_opaque_foo() -> impl Trait + Foo { + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `::Associated == ()` + --> $DIR/issue-87261.rs:88:19 + | +LL | fn returns_opaque_derived_foo() -> impl DerivedTrait + Foo { + | ----------------------- the found opaque type +... +LL | accepts_trait(returns_opaque_derived_foo()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type `::Associated` + = help: consider constraining the associated type `::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `accepts_trait` + --> $DIR/issue-87261.rs:43:27 + | +LL | fn accepts_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait` + +error[E0271]: type mismatch resolving ` + 'static as GenericTrait<()>>::Associated == ()` + --> $DIR/issue-87261.rs:91:27 + | +LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static { + | ------------------------------- the found opaque type +... +LL | accepts_generic_trait(returns_opaque_generic()); + | --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type ` + 'static as GenericTrait<()>>::Associated` +note: required by a bound in `accepts_generic_trait` + --> $DIR/issue-87261.rs:44:46 + | +LL | fn accepts_generic_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` +help: consider constraining the associated type ` + 'static as GenericTrait<()>>::Associated` to `()` + | +LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static { + | +++++++++++++++++ + +error[E0271]: type mismatch resolving ` + Foo as GenericTrait<()>>::Associated == ()` + --> $DIR/issue-87261.rs:94:27 + | +LL | fn returns_opaque_generic_foo() -> impl GenericTrait<()> + Foo { + | --------------------------- the found opaque type +... +LL | accepts_generic_trait(returns_opaque_generic_foo()); + | --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type ` + Foo as GenericTrait<()>>::Associated` +note: required by a bound in `accepts_generic_trait` + --> $DIR/issue-87261.rs:44:46 + | +LL | fn accepts_generic_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` +help: consider constraining the associated type ` + Foo as GenericTrait<()>>::Associated` to `()` + | +LL | fn returns_opaque_generic_foo() -> impl GenericTrait<(), Associated = ()> + Foo { + | +++++++++++++++++ + +error[E0271]: type mismatch resolving ` + GenericTrait as GenericTrait<()>>::Associated == ()` + --> $DIR/issue-87261.rs:97:27 + | +LL | fn returns_opaque_generic_duplicate() -> impl GenericTrait<()> + GenericTrait { + | ---------------------------------------- the found opaque type +... +LL | accepts_generic_trait(returns_opaque_generic_duplicate()); + | --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found associated type ` + GenericTrait as GenericTrait<()>>::Associated` + = help: consider constraining the associated type ` + GenericTrait as GenericTrait<()>>::Associated` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `accepts_generic_trait` + --> $DIR/issue-87261.rs:44:46 + | +LL | fn accepts_generic_trait>(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-88856.rs b/tests/ui/associated-types/issue-88856.rs new file mode 100644 index 000000000..7cae7c71c --- /dev/null +++ b/tests/ui/associated-types/issue-88856.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Trait{ + type R; + fn func(self)->Self::R; +} + +pub struct TraitImpl(pub i32); + +impl Trait for TraitImpl +where [();N/2]:, +{ + type R = Self; + fn func(self)->Self::R { + self + } +} + +fn sample(p:P,f:Convert) -> i32 +where + P:Trait,Convert:Fn(P::R)->i32 +{ + f(p.func()) +} + +fn main() { + let t = TraitImpl::<10>(4); + sample(t,|x|x.0); +} diff --git a/tests/ui/associated-types/issue-91069.rs b/tests/ui/associated-types/issue-91069.rs new file mode 100644 index 000000000..109c2eed2 --- /dev/null +++ b/tests/ui/associated-types/issue-91069.rs @@ -0,0 +1,24 @@ +// check-pass + +pub trait Associate { + type Associated; +} + +pub struct Wrap<'a> { + pub field: &'a i32, +} + +pub trait Create { + fn create() -> Self; +} + +pub fn oh_no<'a, T>() +where + Wrap<'a>: Associate, + as Associate>::Associated: Create, +{ + as Associate>::Associated::create(); +} + + +pub fn main() {} diff --git a/tests/ui/associated-types/issue-91231.rs b/tests/ui/associated-types/issue-91231.rs new file mode 100644 index 000000000..3c1cb81f0 --- /dev/null +++ b/tests/ui/associated-types/issue-91231.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(extern_types)] +#![allow(dead_code)] + +extern { + type Extern; +} + +trait Trait { + type Type; +} + +#[inline] +fn f<'a>(_: <&'a Extern as Trait>::Type) where &'a Extern: Trait {} + +fn main() {} diff --git a/tests/ui/associated-types/issue-91234.rs b/tests/ui/associated-types/issue-91234.rs new file mode 100644 index 000000000..2f6c2d3ae --- /dev/null +++ b/tests/ui/associated-types/issue-91234.rs @@ -0,0 +1,13 @@ +// check-pass + +struct Struct; + +trait Trait { + type Type; +} + +enum Enum<'a> where &'a Struct: Trait { + Variant(<&'a Struct as Trait>::Type) +} + +fn main() {} diff --git a/tests/ui/associated-types/missing-associated-types.rs b/tests/ui/associated-types/missing-associated-types.rs new file mode 100644 index 000000000..3c8410e39 --- /dev/null +++ b/tests/ui/associated-types/missing-associated-types.rs @@ -0,0 +1,27 @@ +use std::ops::{Add, Sub, Mul, Div}; +trait X: Mul + Div {} +trait Y: Div { + type A; +} +trait Z: Div { + type A; + type B; +} +trait Fine: Div {} + +type Foo = dyn Add + Sub + X + Y; +//~^ ERROR only auto traits can be used as additional traits in a trait object +//~| ERROR the value of the associated types +type Bar = dyn Add + Sub + X + Z; +//~^ ERROR only auto traits can be used as additional traits in a trait object +//~| ERROR the value of the associated types +type Baz = dyn Add + Sub + Y; +//~^ ERROR only auto traits can be used as additional traits in a trait object +//~| ERROR the value of the associated types +type Bat = dyn Add + Sub + Fine; +//~^ ERROR only auto traits can be used as additional traits in a trait object +//~| ERROR the value of the associated types +type Bal = dyn X; +//~^ ERROR the value of the associated types + +fn main() {} diff --git a/tests/ui/associated-types/missing-associated-types.stderr b/tests/ui/associated-types/missing-associated-types.stderr new file mode 100644 index 000000000..f617df984 --- /dev/null +++ b/tests/ui/associated-types/missing-associated-types.stderr @@ -0,0 +1,129 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/missing-associated-types.rs:12:32 + | +LL | type Foo = dyn Add + Sub + X + Y; + | -------- ^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + X + Y {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `Add`), `Output` (from trait `Mul`), `Output` (from trait `Sub`) must be specified + --> $DIR/missing-associated-types.rs:12:21 + | +LL | type A; + | ------ `A` defined here +... +LL | type Foo = dyn Add + Sub + X + Y; + | ^^^^^^^^ ^^^^^^^^ ^^^^^^ ^^^^^^ associated type `A` must be specified + | | | | + | | | associated type `Output` must be specified + | | associated type `Output` must be specified + | associated type `Output` must be specified + | +help: specify the associated types + | +LL | type Foo = dyn Add + Sub + X + Y; + | ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/missing-associated-types.rs:15:32 + | +LL | type Bar = dyn Add + Sub + X + Z; + | -------- ^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + X + Z {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0191]: the value of the associated types `A` (from trait `Z`), `B` (from trait `Z`), `Output` (from trait `Add`), `Output` (from trait `Div`), `Output` (from trait `Div`), `Output` (from trait `Mul`), `Output` (from trait `Sub`) must be specified + --> $DIR/missing-associated-types.rs:15:21 + | +LL | type A; + | ------ `A` defined here +LL | type B; + | ------ `B` defined here +... +LL | type Bar = dyn Add + Sub + X + Z; + | ^^^^^^^^ ^^^^^^^^ ^^^^^^ ^^^^^^ associated types `A`, `B`, `Output` must be specified + | | | | + | | | associated types `Output` (from trait `Mul`), `Output` (from trait `Div`) must be specified + | | associated type `Output` must be specified + | associated type `Output` must be specified + | +help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types + --> $DIR/missing-associated-types.rs:15:43 + | +LL | type Bar = dyn Add + Sub + X + Z; + | ^^^^^^ +help: specify the associated types + | +LL | type Bar = dyn Add + Sub + X + Z; + | ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/missing-associated-types.rs:18:32 + | +LL | type Baz = dyn Add + Sub + Y; + | -------- ^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + Y {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified + --> $DIR/missing-associated-types.rs:18:21 + | +LL | type A; + | ------ `A` defined here +... +LL | type Baz = dyn Add + Sub + Y; + | ^^^^^^^^ ^^^^^^^^ ^^^^^^ associated type `A` must be specified + | | | + | | associated type `Output` must be specified + | associated type `Output` must be specified + | +help: specify the associated types + | +LL | type Baz = dyn Add + Sub + Y; + | ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/missing-associated-types.rs:21:32 + | +LL | type Bat = dyn Add + Sub + Fine; + | -------- ^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Add + Sub + Fine {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified + --> $DIR/missing-associated-types.rs:21:21 + | +LL | type Bat = dyn Add + Sub + Fine; + | ^^^^^^^^ ^^^^^^^^ associated type `Output` must be specified + | | + | associated type `Output` must be specified + | +help: specify the associated types + | +LL | type Bat = dyn Add + Sub + Fine; + | ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0191]: the value of the associated types `Output` (from trait `Div`), `Output` (from trait `Mul`) must be specified + --> $DIR/missing-associated-types.rs:24:21 + | +LL | type Bal = dyn X; + | ^^^^^^ associated types `Output` (from trait `Mul`), `Output` (from trait `Div`) must be specified + | + = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0191, E0225. +For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/associated-types/normalization-debruijn-1.rs b/tests/ui/associated-types/normalization-debruijn-1.rs new file mode 100644 index 000000000..a5abf1ba9 --- /dev/null +++ b/tests/ui/associated-types/normalization-debruijn-1.rs @@ -0,0 +1,36 @@ +// build-pass +// edition:2018 + +// Regression test to ensure we handle debruijn indices correctly in projection +// normalization under binders. Found in crater run for #85499 + +use std::future::Future; +use std::pin::Pin; +pub enum Outcome { + Success((S, E)), +} +pub struct Request<'r> { + _marker: std::marker::PhantomData<&'r ()>, +} +pub trait FromRequest<'r>: Sized { + type Error; + fn from_request<'life0>( + request: &'r Request<'life0>, + ) -> Pin>>>; +} +impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option { + type Error = (); + fn from_request<'life0>( + request: &'r Request<'life0>, + ) -> Pin>>> { + Box::pin(async move { + let request = request; + match T::from_request(request).await { + _ => todo!(), + } + }); + todo!() + } +} + +fn main() {} diff --git a/tests/ui/associated-types/normalization-debruijn-2.rs b/tests/ui/associated-types/normalization-debruijn-2.rs new file mode 100644 index 000000000..abe248e16 --- /dev/null +++ b/tests/ui/associated-types/normalization-debruijn-2.rs @@ -0,0 +1,31 @@ +// build-pass +// edition:2018 + +// Regression test to ensure we handle debruijn indices correctly in projection +// normalization under binders. Found in crater run for #85499 + +use std::future::Future; +use std::pin::Pin; +pub enum Outcome { + Success(S), + Failure(E), +} +pub struct Request<'r> { + _marker: std::marker::PhantomData<&'r ()>, +} +pub trait FromRequest<'r>: Sized { + type Error; + fn from_request<'life0>( + request: &'r Request<'life0>, + ) -> Pin>>>; +} +pub struct S { + _marker: std::marker::PhantomData, +} +impl<'r, T: FromRequest<'r>> S { + pub async fn from_request(request: &'r Request<'_>) { + let _ = T::from_request(request).await; + } +} + +fn main() {} diff --git a/tests/ui/associated-types/normalization-debruijn-3.rs b/tests/ui/associated-types/normalization-debruijn-3.rs new file mode 100644 index 000000000..2bea78cf7 --- /dev/null +++ b/tests/ui/associated-types/normalization-debruijn-3.rs @@ -0,0 +1,41 @@ +// build-pass +// edition:2018 + +// Regression test to ensure we handle debruijn indices correctly in projection +// normalization under binders. Found in crater run for #85499 + +use std::future::{Future, Ready}; +async fn read() { + let _ = connect(&()).await; +} +async fn connect(addr: A) { + let _ = addr.to_socket_addr().await; +} +pub trait ToSocketAddr { + type Future: Future; + fn to_socket_addr(&self) -> Self::Future; +} +impl ToSocketAddr for &() { + type Future = Ready<()>; + fn to_socket_addr(&self) -> Self::Future { + unimplemented!() + } +} +struct Server; +impl Server { + fn and_then(self, _fun: F) -> AndThen { + unimplemented!() + } +} +struct AndThen { + _marker: std::marker::PhantomData, +} +pub async fn run(_: F) { +} +fn main() { + let _ = async { + let server = Server; + let verification_route = server.and_then(read); + run(verification_route).await; + }; +} diff --git a/tests/ui/associated-types/normalization-generality-2.rs b/tests/ui/associated-types/normalization-generality-2.rs new file mode 100644 index 000000000..d8790bb2d --- /dev/null +++ b/tests/ui/associated-types/normalization-generality-2.rs @@ -0,0 +1,30 @@ +// build-pass + +// Ensures that we don't regress on "implementation is not general enough" when +// normalizating under binders. Unlike `normalization-generality.rs`, this also produces +// type outlives predicates that we must ignore. + +pub unsafe trait Yokeable<'a> { + type Output: 'a; +} +pub struct Yoke Yokeable<'a>> { + _marker: std::marker::PhantomData, +} +impl Yokeable<'a>> Yoke { + pub fn project

( + &self, + _f: for<'a> fn(&>::Output, &'a ()) ->

>::Output, + ) -> Yoke

+ where + P: for<'a> Yokeable<'a>, + { + unimplemented!() + } +} +pub fn slice(y: Yoke<&'static str>) -> Yoke<&'static [u8]> { + y.project(move |yk, _| yk.as_bytes()) +} +unsafe impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T { + type Output = &'a T; +} +fn main() {} diff --git a/tests/ui/associated-types/normalization-generality.rs b/tests/ui/associated-types/normalization-generality.rs new file mode 100644 index 000000000..f8e3f5b58 --- /dev/null +++ b/tests/ui/associated-types/normalization-generality.rs @@ -0,0 +1,36 @@ +// build-pass + +// Ensures that we don't regress on "implementation is not general enough" when +// normalizating under binders. + +#![feature(no_core)] + +pub trait Yokeable<'a> { + type Output: 'a; +} + +pub struct Yoke Yokeable<'a>> { + _yokeable: Y, +} + +impl Yokeable<'a>> Yoke { + pub fn project<'this, P>( + &'this self, + _f: for<'a> fn(>::Output, &'a ()) ->

>::Output, + ) -> Yoke

+ where + P: for<'a> Yokeable<'a>, + { + unimplemented!() + } +} + +pub fn slice(y: Yoke<&'static ()>) -> Yoke<&'static ()> { + y.project(move |yk, _| yk) +} + +impl<'a, T> Yokeable<'a> for &'static T { + type Output = &'a T; +} + +fn main() {} diff --git a/tests/ui/associated-types/normalization-probe-cycle.rs b/tests/ui/associated-types/normalization-probe-cycle.rs new file mode 100644 index 000000000..9c1a488e9 --- /dev/null +++ b/tests/ui/associated-types/normalization-probe-cycle.rs @@ -0,0 +1,25 @@ +// Regression test for #77656 + +// check-pass + +trait Value: PartialOrd {} + +impl Value for T {} + +trait Distance +where + Self: PartialOrd<::Value>, + Self: PartialOrd, +{ + type Value: Value; +} + +impl Distance for T { + type Value = T; +} + +trait Proximity { + type Distance: Distance; +} + +fn main() {} diff --git a/tests/ui/associated-types/normalize-cycle-in-eval-no-region.rs b/tests/ui/associated-types/normalize-cycle-in-eval-no-region.rs new file mode 100644 index 000000000..0fd2c7079 --- /dev/null +++ b/tests/ui/associated-types/normalize-cycle-in-eval-no-region.rs @@ -0,0 +1,20 @@ +// Case that the fix for #74868 also allowed to compile + +// check-pass + +trait BoxedDsl { + type Output; +} + +impl BoxedDsl for T +where + T: BoxedDsl, +{ + type Output = ::Output; +} + +trait HandleUpdate {} + +impl HandleUpdate for T where T: BoxedDsl {} + +fn main() {} diff --git a/tests/ui/associated-types/normalize-cycle-in-eval.rs b/tests/ui/associated-types/normalize-cycle-in-eval.rs new file mode 100644 index 000000000..dff4c9051 --- /dev/null +++ b/tests/ui/associated-types/normalize-cycle-in-eval.rs @@ -0,0 +1,43 @@ +// regression test for #74868 + +// check-pass + +trait BoxedDsl<'a> { + type Output; +} + +impl<'a, T> BoxedDsl<'a> for T +where + T: BoxedDsl<'a>, +{ + type Output = >::Output; +} + +// Showing this trait is wf requires proving +// Self: HandleUpdate +// +// The impl below is a candidate for this projection, as well as the `Self: +// HandleUpdate` bound in the environment. +// We evaluate both candidates to see if we need to consider both applicable. +// Evaluating the impl candidate requires evaluating +// >::Output == () +// The above impl cause normalizing the above type normalize to itself. +// +// This previously compiled because we would generate a new region +// variable each time around the cycle, and evaluation would eventually return +// `EvaluatedToErr` from the `Self: Sized` in the impl, which would in turn +// leave the bound as the only candidate. +// +// #73452 changed this so that region variables are canonicalized when we +// normalize, which means that the projection cycle is detected before +// evaluation returns EvaluatedToErr. The cycle resulted in an error being +// emitted immediately, causing this to fail to compile. +// +// To fix this, normalization doesn't directly emit errors when it finds a +// cycle, instead letting the caller handle it. This restores the original +// behavior. +trait HandleUpdate {} + +impl HandleUpdate for T where T: BoxedDsl<'static, Output = ()> {} + +fn main() {} diff --git a/tests/ui/associated-types/object-method-numbering.rs b/tests/ui/associated-types/object-method-numbering.rs new file mode 100644 index 000000000..bf80a80f4 --- /dev/null +++ b/tests/ui/associated-types/object-method-numbering.rs @@ -0,0 +1,28 @@ +// run-pass +// Test for using an object with an associated type binding as the +// instantiation for a generic type with a bound. + + +trait SomeTrait { + type SomeType; + + fn get(&self) -> Self::SomeType; +} + +fn get_int+?Sized>(x: &T) -> i32 { + x.get() +} + +impl SomeTrait for i32 { + type SomeType = i32; + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let x = 22; + let x1: &dyn SomeTrait = &x; + let y = get_int(x1); + assert_eq!(x, y); +} diff --git a/tests/ui/associated-types/object-normalization.rs b/tests/ui/associated-types/object-normalization.rs new file mode 100644 index 000000000..1f93248e1 --- /dev/null +++ b/tests/ui/associated-types/object-normalization.rs @@ -0,0 +1,26 @@ +// ignore-tidy-linelength + +// Check that we normalize super predicates for object candidates. + +// check-pass + +use std::ops::Index; + +fn next<'a, T>(s: &'a mut dyn SVec) { + // To prove + // `dyn SVec: SVec` + // we need to show + // `dyn SVec as Index>::Output == as SVec>::Item` + // which, with the current normalization strategy, has to be eagerly + // normalized to: + // `dyn SVec as Index>::Output == T`. + let _ = s.len(); +} + +trait SVec: Index::Item> { + type Item; + + fn len(&self) -> usize; +} + +fn main() {} diff --git a/tests/ui/associated-types/param-env-normalize-cycle.rs b/tests/ui/associated-types/param-env-normalize-cycle.rs new file mode 100644 index 000000000..12db595ed --- /dev/null +++ b/tests/ui/associated-types/param-env-normalize-cycle.rs @@ -0,0 +1,39 @@ +// Minimized case from typenum that didn't compile because: +// - We tried to normalize the ParamEnv of the second impl +// - This requires trying to normalize `GrEq>>` +// - This requires proving `Square>: Sized` so that the first impl +// applies +// - This requires Providing `Square>` is well-formed, so that we +// can use the `Sized` bound on `Mul::Output` +// - This requires proving `Square: Mul` +// - But first we tried normalizing the whole obligation, including the +// ParamEnv, which leads to a cycle error. + +// check-pass + +trait PrivateSquareRoot {} + +pub trait Mul { + type Output; +} + +pub trait IsGreaterOrEqual { + type Output; +} + +pub type Square = ::Output; +pub type GrEq = >::Output; + +impl IsGreaterOrEqual for A { + type Output = (); +} + +impl PrivateSquareRoot for U +where + U: Mul, + Square: Mul, + GrEq>>: Sized, +{ +} + +fn main() {} diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.rs new file mode 100644 index 000000000..4b3d6e9d6 --- /dev/null +++ b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -0,0 +1,33 @@ +trait Bar {} + +trait Foo { + type Assoc: Bar; +} + +impl Foo for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +trait Baz +where + Self::Assoc: Bar, +{ + type Assoc; +} + +impl Baz for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +trait Bat +where + ::Assoc: Bar, +{ + type Assoc; +} + +impl Bat for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +fn main() {} diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr new file mode 100644 index 000000000..2e7a1dd2a --- /dev/null +++ b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -0,0 +1,45 @@ +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:8:18 + | +LL | type Assoc = bool; + | ^^^^ the trait `Bar` is not implemented for `bool` + | +note: required by a bound in `Foo::Assoc` + --> $DIR/point-at-type-on-obligation-failure-2.rs:4:17 + | +LL | type Assoc: Bar; + | ^^^ required by this bound in `Foo::Assoc` + +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:19:18 + | +LL | type Assoc = bool; + | ^^^^ the trait `Bar` is not implemented for `bool` + | +note: required by a bound in `Baz::Assoc` + --> $DIR/point-at-type-on-obligation-failure-2.rs:13:18 + | +LL | Self::Assoc: Bar, + | ^^^ required by this bound in `Baz::Assoc` +LL | { +LL | type Assoc; + | ----- required by a bound in this + +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:30:18 + | +LL | type Assoc = bool; + | ^^^^ the trait `Bar` is not implemented for `bool` + | +note: required by a bound in `Bat::Assoc` + --> $DIR/point-at-type-on-obligation-failure-2.rs:24:27 + | +LL | ::Assoc: Bar, + | ^^^ required by this bound in `Bat::Assoc` +LL | { +LL | type Assoc; + | ----- required by a bound in this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure.rs b/tests/ui/associated-types/point-at-type-on-obligation-failure.rs new file mode 100644 index 000000000..666660068 --- /dev/null +++ b/tests/ui/associated-types/point-at-type-on-obligation-failure.rs @@ -0,0 +1,21 @@ +trait Bar { + type Ok; + type Sibling: Bar2; +} +trait Bar2 { + type Ok; +} + +struct Foo; +struct Foo2; + +impl Bar for Foo { + type Ok = (); + type Sibling = Foo2; + //~^ ERROR type mismatch resolving `::Ok == ()` +} +impl Bar2 for Foo2 { + type Ok = u32; +} + +fn main() {} diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr b/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr new file mode 100644 index 000000000..9afbe82c3 --- /dev/null +++ b/tests/ui/associated-types/point-at-type-on-obligation-failure.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `::Ok == ()` + --> $DIR/point-at-type-on-obligation-failure.rs:14:20 + | +LL | type Sibling = Foo2; + | ^^^^ type mismatch resolving `::Ok == ()` + | +note: expected this to be `()` + --> $DIR/point-at-type-on-obligation-failure.rs:18:15 + | +LL | type Ok = u32; + | ^^^ +note: required by a bound in `Bar::Sibling` + --> $DIR/point-at-type-on-obligation-failure.rs:3:24 + | +LL | type Sibling: Bar2; + | ^^^^^^^^^^^ required by this bound in `Bar::Sibling` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/project-defer-unification.rs b/tests/ui/associated-types/project-defer-unification.rs new file mode 100644 index 000000000..547ff45c2 --- /dev/null +++ b/tests/ui/associated-types/project-defer-unification.rs @@ -0,0 +1,104 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unreachable_code)] +// A regression test extracted from image-0.3.11. The point of +// failure was in `index_colors` below. + +use std::ops::{Deref, DerefMut}; + +#[derive(Copy, Clone)] +pub struct Luma { pub data: [T; 1] } + +impl Pixel for Luma { + type Subpixel = T; +} + +pub struct ImageBuffer { + pixels: P, + c: Container, +} + +pub trait GenericImage: Sized { + type Pixel: Pixel; +} + +pub trait Pixel: Copy + Clone { + type Subpixel: Primitive; +} + +pub trait Primitive: Copy + PartialOrd + Clone { +} + +impl GenericImage for ImageBuffer +where P: Pixel + 'static, + Container: Deref + DerefMut, + P::Subpixel: 'static { + + type Pixel = P; +} + +impl Primitive for u8 { } + +impl ImageBuffer +where P: Pixel + 'static, + P::Subpixel: 'static, + Container: Deref +{ + pub fn pixels<'a>(&'a self) -> Pixels<'a, Self> { + loop { } + } + + pub fn pixels_mut(&mut self) -> PixelsMut

{ + loop { } + } +} + +pub struct Pixels<'a, I: 'a> { + image: &'a I, + x: u32, + y: u32, + width: u32, + height: u32 +} + +impl<'a, I: GenericImage> Iterator for Pixels<'a, I> { + type Item = (u32, u32, I::Pixel); + + fn next(&mut self) -> Option<(u32, u32, I::Pixel)> { + loop { } + } +} + +pub struct PixelsMut<'a, P: Pixel + 'a> where P::Subpixel: 'a { + chunks: &'a mut P::Subpixel +} + +impl<'a, P: Pixel + 'a> Iterator for PixelsMut<'a, P> where P::Subpixel: 'a { + type Item = &'a mut P; + + fn next(&mut self) -> Option<&'a mut P> { + loop { } + } +} + +pub fn index_colors(image: &ImageBuffer>) + -> ImageBuffer, Vec> +where Pix: Pixel + 'static, +{ + // When NLL-enabled, `let mut` below is deemed unnecessary (due to + // the remaining code being unreachable); so ignore that lint. + #![allow(unused_mut)] + + let mut indices: ImageBuffer<_,Vec<_>> = loop { }; + for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) { + // failured occurred here ^^ because we were requiring that we + // could project Pixel or Subpixel from `T_indices` (type of + // `indices`), but the type is insufficiently constrained + // until we reach the return below. + } + indices +} + +fn main() { } diff --git a/tests/ui/associated-types/project-recursion-limit-non-fatal.rs b/tests/ui/associated-types/project-recursion-limit-non-fatal.rs new file mode 100644 index 000000000..3e68b1401 --- /dev/null +++ b/tests/ui/associated-types/project-recursion-limit-non-fatal.rs @@ -0,0 +1,58 @@ +// Regression test for #80953. Hitting the recursion limit in projection +// is non-fatal. The above code, minimised from wundergraph shows a case +// where this is relied on. + +// check-pass + +struct AlternateTable {} +struct AlternateQuery {} + +pub trait Query {} +pub trait AsQuery { + type Query; +} +impl AsQuery for T { + type Query = Self; +} +impl AsQuery for AlternateTable { + type Query = AlternateQuery; +} + +pub trait Table: AsQuery { + type PrimaryKey; +} +impl Table for AlternateTable { + type PrimaryKey = (); +} + +pub trait FilterDsl { + type Output; +} +pub type Filter = >::Output; +impl FilterDsl for T +where + T: Table, + T::Query: FilterDsl, +{ + type Output = Filter; +} +impl FilterDsl for AlternateQuery { + type Output = &'static str; +} + +pub trait HandleDelete { + type Filter; +} +impl HandleDelete for T +where + T: Table, + T::Query: FilterDsl, + Filter: , +{ + type Filter = Filter; +} + +fn main() { + let x: ::Filter = "Hello, world"; + println!("{}", x); +} diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr new file mode 100644 index 000000000..acdc3be8c --- /dev/null +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -0,0 +1,91 @@ +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:16:17 + | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- associated function `bar` defined here +... +LL | let x: () = >::bar::<'static, char>; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {>::bar::<'static, char>}` +help: use parentheses to call this associated function + | +LL | let x: () = >::bar::<'static, char>(); + | ++ + +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:25:17 + | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- associated function `bar` defined here +... +LL | let x: () = >::bar::<'static, char>; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {>::bar::<'static, char>}` +help: use parentheses to call this associated function + | +LL | let x: () = >::bar::<'static, char>(); + | ++ + +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:33:17 + | +LL | fn baz() {} + | -------- associated function `baz` defined here +... +LL | let x: () = >::baz; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {>::baz}` +help: use parentheses to call this associated function + | +LL | let x: () = >::baz(); + | ++ + +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:41:17 + | +LL | fn foo<'z>() where &'z (): Sized { + | -------------------------------- function `foo` defined here +... +LL | let x: () = foo::<'static>; + | -- ^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {foo::<'static>}` +help: use parentheses to call this function + | +LL | let x: () = foo::<'static>(); + | ++ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/substs-ppaux.rs:49:5 + | +LL | >::bar; + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required for `str` to implement `Foo<'_, '_, u8>` + --> $DIR/substs-ppaux.rs:11:17 + | +LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} + | - ^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/substs-ppaux.rs b/tests/ui/associated-types/substs-ppaux.rs new file mode 100644 index 000000000..66cd94d7a --- /dev/null +++ b/tests/ui/associated-types/substs-ppaux.rs @@ -0,0 +1,52 @@ +// +// revisions: verbose normal +// +//[verbose] compile-flags: -Z verbose + +trait Foo<'b, 'c, S=u32> { + fn bar<'a, T>() where T: 'a {} + fn baz() {} +} + +impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} + +fn main() {} + +fn foo<'z>() where &'z (): Sized { + let x: () = >::bar::<'static, char>; + //[verbose]~^ ERROR mismatched types + //[verbose]~| expected unit type `()` + //[verbose]~| found fn item `fn() {>::bar::}` + //[normal]~^^^^ ERROR mismatched types + //[normal]~| expected unit type `()` + //[normal]~| found fn item `fn() {>::bar::<'static, char>}` + + + let x: () = >::bar::<'static, char>; + //[verbose]~^ ERROR mismatched types + //[verbose]~| expected unit type `()` + //[verbose]~| found fn item `fn() {>::bar::}` + //[normal]~^^^^ ERROR mismatched types + //[normal]~| expected unit type `()` + //[normal]~| found fn item `fn() {>::bar::<'static, char>}` + + let x: () = >::baz; + //[verbose]~^ ERROR mismatched types + //[verbose]~| expected unit type `()` + //[verbose]~| found fn item `fn() {>::baz}` + //[normal]~^^^^ ERROR mismatched types + //[normal]~| expected unit type `()` + //[normal]~| found fn item `fn() {>::baz}` + + let x: () = foo::<'static>; + //[verbose]~^ ERROR mismatched types + //[verbose]~| expected unit type `()` + //[verbose]~| found fn item `fn() {foo::}` + //[normal]~^^^^ ERROR mismatched types + //[normal]~| expected unit type `()` + //[normal]~| found fn item `fn() {foo::<'static>}` + + >::bar; + //[verbose]~^ ERROR the size for values of type + //[normal]~^^ ERROR the size for values of type +} diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr new file mode 100644 index 000000000..e4f6ba573 --- /dev/null +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -0,0 +1,91 @@ +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:16:17 + | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- associated function `bar` defined here +... +LL | let x: () = >::bar::<'static, char>; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {>::bar::}` +help: use parentheses to call this associated function + | +LL | let x: () = >::bar::<'static, char>(); + | ++ + +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:25:17 + | +LL | fn bar<'a, T>() where T: 'a {} + | --------------------------- associated function `bar` defined here +... +LL | let x: () = >::bar::<'static, char>; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {>::bar::}` +help: use parentheses to call this associated function + | +LL | let x: () = >::bar::<'static, char>(); + | ++ + +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:33:17 + | +LL | fn baz() {} + | -------- associated function `baz` defined here +... +LL | let x: () = >::baz; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {>::baz}` +help: use parentheses to call this associated function + | +LL | let x: () = >::baz(); + | ++ + +error[E0308]: mismatched types + --> $DIR/substs-ppaux.rs:41:17 + | +LL | fn foo<'z>() where &'z (): Sized { + | -------------------------------- function `foo` defined here +... +LL | let x: () = foo::<'static>; + | -- ^^^^^^^^^^^^^^ expected `()`, found fn item + | | + | expected due to this + | + = note: expected unit type `()` + found fn item `fn() {foo::}` +help: use parentheses to call this function + | +LL | let x: () = foo::<'static>(); + | ++ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/substs-ppaux.rs:49:5 + | +LL | >::bar; + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required for `str` to implement `Foo<'_#0r, '_#1r, u8>` + --> $DIR/substs-ppaux.rs:11:17 + | +LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} + | - ^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.rs b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.rs new file mode 100644 index 000000000..0474bf0a3 --- /dev/null +++ b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.rs @@ -0,0 +1,11 @@ +use std::ops::{Add, Sub, Mul, Div}; + +trait ArithmeticOps: Add + Sub + Mul + Div {} +//~^ ERROR the size for values of type `Self` cannot be known at compilation time + +impl ArithmeticOps for T where T: Add + Sub + Mul + Div { + // Nothing to implement, since T already supports the other traits. + // It has the functions it needs already +} + +fn main() {} diff --git a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr new file mode 100644 index 000000000..8e7cf86c4 --- /dev/null +++ b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/trait-with-supertraits-needing-sized-self.rs:3:22 + | +LL | trait ArithmeticOps: Add + Sub + Mul + Div {} + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Add` + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting `Self` + | +LL | trait ArithmeticOps: Add + Sub + Mul + Div + Sized {} + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/wf-cycle-2.rs b/tests/ui/associated-types/wf-cycle-2.rs new file mode 100644 index 000000000..d7467ac22 --- /dev/null +++ b/tests/ui/associated-types/wf-cycle-2.rs @@ -0,0 +1,18 @@ +// check-pass + +trait IntoIt { + type Item; +} + +impl IntoIt for I { + type Item = (); +} + +trait BaseGraph +where + ::Item: Sized, +{ + type VertexIter: IntoIt; +} + +fn main() {} diff --git a/tests/ui/associated-types/wf-cycle.rs b/tests/ui/associated-types/wf-cycle.rs new file mode 100644 index 000000000..cf6508551 --- /dev/null +++ b/tests/ui/associated-types/wf-cycle.rs @@ -0,0 +1,13 @@ +// check-pass + +trait A { + type U: Copy; +} + +trait B where + ::U: Copy, +{ + type V: A; +} + +fn main() {} diff --git a/tests/ui/async-await/argument-patterns.rs b/tests/ui/async-await/argument-patterns.rs new file mode 100644 index 000000000..b9fc1a88c --- /dev/null +++ b/tests/ui/async-await/argument-patterns.rs @@ -0,0 +1,28 @@ +// edition:2018 +// check-pass + +#![deny(unused_mut)] + +type A = Vec; + +async fn a(n: u32, mut vec: A) { + vec.push(n); +} + +async fn b(n: u32, ref mut vec: A) { + vec.push(n); +} + +async fn c(ref vec: A) { + vec.contains(&0); +} + +async fn d((a, mut b): (A, A)) { + b.push(1); +} + +async fn f((ref mut a, ref b): (A, A)) {} + +async fn g(((ref a, ref mut b), (ref mut c, ref d)): ((A, A), (A, A))) {} + +fn main() {} diff --git a/tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs b/tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs new file mode 100644 index 000000000..8e08b82b9 --- /dev/null +++ b/tests/ui/async-await/async-assoc-fn-anon-lifetimes.rs @@ -0,0 +1,23 @@ +// check-pass +// Check that the anonymous lifetimes used here aren't considered to shadow one +// another. Note that `async fn` is different to `fn` here because the lifetimes +// are numbered by HIR lowering, rather than lifetime resolution. + +// edition:2018 + +struct A<'a, 'b>(&'a &'b i32); +struct B<'a>(&'a i32); + +impl A<'_, '_> { + async fn assoc(x: &u32, y: B<'_>) { + async fn nested(x: &u32, y: A<'_, '_>) {} + } + + async fn assoc2(x: &u32, y: A<'_, '_>) { + impl A<'_, '_> { + async fn nested_assoc(x: &u32, y: B<'_>) {} + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/async-await-let-else.drop-tracking.stderr b/tests/ui/async-await/async-await-let-else.drop-tracking.stderr new file mode 100644 index 000000000..fb83ca90a --- /dev/null +++ b/tests/ui/async-await/async-await-let-else.drop-tracking.stderr @@ -0,0 +1,106 @@ +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:48:13 + | +LL | is_send(foo(Some(true))); + | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:11:14 + | +LL | let r = Rc::new(()); + | - has type `Rc<()>` which is not `Send` +LL | bar().await + | ^^^^^^ await occurs here, with `r` maybe used later +LL | }; + | - `r` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `Rc<()>` cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:50:13 + | +LL | async fn foo2(x: Option) { + | - within this `impl Future` +... +LL | is_send(foo2(Some(true))); + | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: required because it's used within this `async fn` body + --> $DIR/async-await-let-else.rs:27:29 + | +LL | async fn bar2(_: T) -> ! { + | _____________________________^ +LL | | panic!() +LL | | } + | |_^ + = note: required because it captures the following types: `ResumeTy`, `Option`, `impl Future`, `()` +note: required because it's used within this `async fn` body + --> $DIR/async-await-let-else.rs:21:32 + | +LL | async fn foo2(x: Option) { + | ________________________________^ +LL | | let Some(_) = x else { +LL | | bar2(Rc::new(())).await +LL | | }; +LL | | } + | |_^ +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:52:13 + | +LL | is_send(foo3(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:33:28 + | +LL | (Rc::new(()), bar().await); + | ----------- ^^^^^^ - `Rc::new(())` is later dropped here + | | | + | | await occurs here, with `Rc::new(())` maybe used later + | has type `Rc<()>` which is not `Send` +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:54:13 + | +LL | is_send(foo4(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:41:14 + | +LL | let r = Rc::new(()); + | - has type `Rc<()>` which is not `Send` +LL | bar().await; + | ^^^^^^ await occurs here, with `r` maybe used later +... +LL | }; + | - `r` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr b/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr new file mode 100644 index 000000000..d3c5e80a3 --- /dev/null +++ b/tests/ui/async-await/async-await-let-else.no-drop-tracking.stderr @@ -0,0 +1,90 @@ +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:48:13 + | +LL | is_send(foo(Some(true))); + | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:11:14 + | +LL | let r = Rc::new(()); + | - has type `Rc<()>` which is not `Send` +LL | bar().await + | ^^^^^^ await occurs here, with `r` maybe used later +LL | }; + | - `r` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:50:13 + | +LL | is_send(foo2(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:23:26 + | +LL | bar2(Rc::new(())).await + | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later + | | + | has type `Rc<()>` which is not `Send` +LL | }; + | - `Rc::new(())` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:52:13 + | +LL | is_send(foo3(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:33:28 + | +LL | (Rc::new(()), bar().await); + | ----------- ^^^^^^ - `Rc::new(())` is later dropped here + | | | + | | await occurs here, with `Rc::new(())` maybe used later + | has type `Rc<()>` which is not `Send` +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: future cannot be sent between threads safely + --> $DIR/async-await-let-else.rs:54:13 + | +LL | is_send(foo4(Some(true))); + | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-await-let-else.rs:41:14 + | +LL | let r = Rc::new(()); + | - has type `Rc<()>` which is not `Send` +LL | bar().await; + | ^^^^^^ await occurs here, with `r` maybe used later +... +LL | }; + | - `r` is later dropped here +note: required by a bound in `is_send` + --> $DIR/async-await-let-else.rs:19:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/async-await-let-else.rs b/tests/ui/async-await/async-await-let-else.rs new file mode 100644 index 000000000..3fb2142b9 --- /dev/null +++ b/tests/ui/async-await/async-await-let-else.rs @@ -0,0 +1,56 @@ +// edition:2021 +// revisions: drop-tracking no-drop-tracking +// [drop-tracking] compile-flags: -Zdrop-tracking=yes +// [no-drop-tracking] compile-flags: -Zdrop-tracking=no + +use std::rc::Rc; + +async fn foo(x: Option) { + let Some(_) = x else { + let r = Rc::new(()); + bar().await + }; +} + +async fn bar() -> ! { + panic!() +} + +fn is_send(_: T) {} + +async fn foo2(x: Option) { + let Some(_) = x else { + bar2(Rc::new(())).await + }; +} + +async fn bar2(_: T) -> ! { + panic!() +} + +async fn foo3(x: Option) { + let Some(_) = x else { + (Rc::new(()), bar().await); + return; + }; +} + +async fn foo4(x: Option) { + let Some(_) = x else { + let r = Rc::new(()); + bar().await; + println!("{:?}", r); + return; + }; +} + +fn main() { + is_send(foo(Some(true))); + //~^ ERROR cannot be sent between threads safely + is_send(foo2(Some(true))); + //~^ ERROR cannot be sent between threads safely + is_send(foo3(Some(true))); + //~^ ERROR cannot be sent between threads safely + is_send(foo4(Some(true))); + //~^ ERROR cannot be sent between threads safely +} diff --git a/tests/ui/async-await/async-await.rs b/tests/ui/async-await/async-await.rs new file mode 100644 index 000000000..9cabf16f8 --- /dev/null +++ b/tests/ui/async-await/async-await.rs @@ -0,0 +1,219 @@ +// run-pass + +// revisions: default nomiropt thirunsafeck +//[nomiropt]compile-flags: -Z mir-opt-level=0 +//[thirunsafeck]compile-flags: -Zthir-unsafeck + +#![allow(unused)] + +// edition: 2018 +// aux-build:arc_wake.rs + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool); + +fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } + +impl Future for WakeOnceThenComplete { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.0 { + Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn async_block(x: u8) -> impl Future { + async move { + wake_and_yield_once().await; + x + } +} + +fn async_block_with_borrow_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { + async move { + wake_and_yield_once().await; + *x + } +} + +fn async_nonmove_block(x: u8) -> impl Future { + async move { + let future = async { + wake_and_yield_once().await; + x + }; + future.await + } +} + +// see async-closure.rs for async_closure + async_closure_in_unsafe_block + +async fn async_fn(x: u8) -> u8 { + wake_and_yield_once().await; + x +} + +async fn generic_async_fn(x: T) -> T { + wake_and_yield_once().await; + x +} + +async fn async_fn_with_borrow(x: &u8) -> u8 { + wake_and_yield_once().await; + *x +} + +async fn async_fn_with_borrow_named_lifetime<'a>(x: &'a u8) -> u8 { + wake_and_yield_once().await; + *x +} + +fn async_fn_with_impl_future_named_lifetime<'a>(x: &'a u8) -> impl Future + 'a { + async move { + wake_and_yield_once().await; + *x + } +} + +async fn async_fn_multiple_args(x: &u8, _y: &u8) -> u8 { + wake_and_yield_once().await; + *x +} + +async fn async_fn_multiple_args_named_lifetime<'a>(x: &'a u8, _y: &'a u8) -> u8 { + wake_and_yield_once().await; + *x +} + +fn async_fn_with_internal_borrow(y: u8) -> impl Future { + async move { + async_fn_with_borrow_named_lifetime(&y).await + } +} + +async unsafe fn unsafe_async_fn(x: u8) -> u8 { + wake_and_yield_once().await; + x +} + +unsafe fn unsafe_fn(x: u8) -> u8 { + x +} + +fn async_block_in_unsafe_block(x: u8) -> impl Future { + unsafe { + async move { + unsafe_fn(unsafe_async_fn(x).await) + } + } +} + +struct Foo; + +trait Bar { + fn foo() {} +} + +impl Foo { + async fn async_assoc_item(x: u8) -> u8 { + unsafe { + unsafe_async_fn(x).await + } + } + + async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 { + unsafe_async_fn(x).await + } +} + +fn test_future_yields_once_then_returns(f: F) +where + F: FnOnce(u8) -> Fut, + Fut: Future, +{ + let mut fut = Box::pin(f(9)); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx)); + assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx)); +} + +fn main() { + macro_rules! test { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns($fn_name); + )* } + } + + macro_rules! test_with_borrow { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns(|x| { + async move { + $fn_name(&x).await + } + }); + )* } + } + + test! { + async_block, + async_nonmove_block, + async_fn, + generic_async_fn, + async_fn_with_internal_borrow, + async_block_in_unsafe_block, + Foo::async_assoc_item, + |x| { + async move { + unsafe { unsafe_async_fn(x).await } + } + }, + |x| { + async move { + unsafe { Foo::async_unsafe_assoc_item(x).await } + } + }, + } + test_with_borrow! { + async_block_with_borrow_named_lifetime, + async_fn_with_borrow, + async_fn_with_borrow_named_lifetime, + async_fn_with_impl_future_named_lifetime, + |x| { + async move { + async_fn_multiple_args_named_lifetime(x, x).await + } + }, + } +} diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.rs b/tests/ui/async-await/async-block-control-flow-static-semantics.rs new file mode 100644 index 000000000..bc9d12793 --- /dev/null +++ b/tests/ui/async-await/async-block-control-flow-static-semantics.rs @@ -0,0 +1,65 @@ +// Test that `async { .. }` blocks: +// 1. do not allow `break` expressions. +// 2. get targeted by `return` and not the parent function. +// 3. get targeted by `?` and not the parent function. +// +// edition:2018 + +fn main() {} + +use core::future::Future; + +fn return_targets_async_block_not_fn() -> u8 { + //~^ ERROR mismatched types + let block = async { + return 0u8; + }; + let _: &dyn Future = █ + //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8` +} + +async fn return_targets_async_block_not_async_fn() -> u8 { + //~^ ERROR mismatched types [E0308] + let block = async { + return 0u8; + }; + let _: &dyn Future = █ + //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8` +} + +fn no_break_in_async_block() { + async { + break 0u8; //~ ERROR `break` inside of an `async` block + }; +} + +fn no_break_in_async_block_even_with_outer_loop() { + loop { + async { + break 0u8; //~ ERROR `break` inside of an `async` block + }; + } +} + +struct MyErr; +fn err() -> Result { + Err(MyErr) +} + +fn rethrow_targets_async_block_not_fn() -> Result { + //~^ ERROR mismatched types + let block = async { + err()?; + Ok(()) + }; + let _: &dyn Future> = █ +} + +fn rethrow_targets_async_block_not_async_fn() -> Result { + //~^ ERROR mismatched types + let block = async { + err()?; + Ok(()) + }; + let _: &dyn Future> = █ +} diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr new file mode 100644 index 000000000..c4487eb84 --- /dev/null +++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -0,0 +1,81 @@ +error[E0267]: `break` inside of an `async` block + --> $DIR/async-block-control-flow-static-semantics.rs:32:9 + | +LL | / async { +LL | | break 0u8; + | | ^^^^^^^^^ cannot `break` inside of an `async` block +LL | | }; + | |_____- enclosing `async` block + +error[E0267]: `break` inside of an `async` block + --> $DIR/async-block-control-flow-static-semantics.rs:39:13 + | +LL | / async { +LL | | break 0u8; + | | ^^^^^^^^^ cannot `break` inside of an `async` block +LL | | }; + | |_________- enclosing `async` block + +error[E0308]: mismatched types + --> $DIR/async-block-control-flow-static-semantics.rs:21:58 + | +LL | async fn return_targets_async_block_not_async_fn() -> u8 { + | __________________________________________________________^ +LL | | +LL | | let block = async { +LL | | return 0u8; +... | +LL | | +LL | | } + | |_^ expected `u8`, found `()` + +error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to be a future that resolves to `()`, but it resolves to `u8` + --> $DIR/async-block-control-flow-static-semantics.rs:26:39 + | +LL | let _: &dyn Future = █ + | ^^^^^^ expected `()`, found `u8` + | + = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future` + +error[E0308]: mismatched types + --> $DIR/async-block-control-flow-static-semantics.rs:12:43 + | +LL | fn return_targets_async_block_not_fn() -> u8 { + | --------------------------------- ^^ expected `u8`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to be a future that resolves to `()`, but it resolves to `u8` + --> $DIR/async-block-control-flow-static-semantics.rs:17:39 + | +LL | let _: &dyn Future = █ + | ^^^^^^ expected `()`, found `u8` + | + = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future` + +error[E0308]: mismatched types + --> $DIR/async-block-control-flow-static-semantics.rs:49:44 + | +LL | fn rethrow_targets_async_block_not_fn() -> Result { + | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Result` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/async-block-control-flow-static-semantics.rs:58:50 + | +LL | fn rethrow_targets_async_block_not_async_fn() -> Result { + | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Result` + found unit type `()` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0267, E0271, E0308. +For more information about an error, try `rustc --explain E0267`. diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.fixed b/tests/ui/async-await/async-borrowck-escaping-block-error.fixed new file mode 100644 index 000000000..605cfdfe7 --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-block-error.fixed @@ -0,0 +1,18 @@ +// edition:2018 +// run-rustfix + +fn test_boxed() -> Box> { + let x = 0u32; + Box::new(async move { x } ) + //~^ ERROR E0373 +} + +fn test_ref(x: &u32) -> impl std::future::Future + '_ { + async move { *x } + //~^ ERROR E0373 +} + +fn main() { + let _ = test_boxed(); + let _ = test_ref(&0u32); +} diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.rs b/tests/ui/async-await/async-borrowck-escaping-block-error.rs new file mode 100644 index 000000000..ec752c15f --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-block-error.rs @@ -0,0 +1,18 @@ +// edition:2018 +// run-rustfix + +fn test_boxed() -> Box> { + let x = 0u32; + Box::new(async { x } ) + //~^ ERROR E0373 +} + +fn test_ref(x: &u32) -> impl std::future::Future + '_ { + async { *x } + //~^ ERROR E0373 +} + +fn main() { + let _ = test_boxed(); + let _ = test_ref(&0u32); +} diff --git a/tests/ui/async-await/async-borrowck-escaping-block-error.stderr b/tests/ui/async-await/async-borrowck-escaping-block-error.stderr new file mode 100644 index 000000000..190c59e32 --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -0,0 +1,41 @@ +error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-block-error.rs:6:14 + | +LL | Box::new(async { x } ) + | ^^^^^^^^-^^ + | | | + | | `x` is borrowed here + | may outlive borrowed value `x` + | +note: async block is returned here + --> $DIR/async-borrowck-escaping-block-error.rs:6:5 + | +LL | Box::new(async { x } ) + | ^^^^^^^^^^^^^^^^^^^^^^ +help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new(async move { x } ) + | ++++ + +error[E0373]: async block may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-block-error.rs:11:5 + | +LL | async { *x } + | ^^^^^^^^--^^ + | | | + | | `x` is borrowed here + | may outlive borrowed value `x` + | +note: async block is returned here + --> $DIR/async-borrowck-escaping-block-error.rs:11:5 + | +LL | async { *x } + | ^^^^^^^^^^^^ +help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | async move { *x } + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs new file mode 100644 index 000000000..e667b72ae --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -0,0 +1,10 @@ +// edition:2018 +#![feature(async_closure)] +fn foo() -> Box> { + let x = 0u32; + Box::new((async || x)()) + //~^ ERROR E0373 +} + +fn main() { +} diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr new file mode 100644 index 000000000..10691aad0 --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-closure-error.rs:5:15 + | +LL | Box::new((async || x)()) + | ^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/async-borrowck-escaping-closure-error.rs:5:5 + | +LL | Box::new((async || x)()) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new((async move || x)()) + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/async-closure-matches-expr.rs b/tests/ui/async-await/async-closure-matches-expr.rs new file mode 100644 index 000000000..d82fbcdc5 --- /dev/null +++ b/tests/ui/async-await/async-closure-matches-expr.rs @@ -0,0 +1,12 @@ +// build-pass +// edition:2018 + +#![feature(async_closure)] + +macro_rules! match_expr { + ($x:expr) => {} +} + +fn main() { + match_expr!(async || {}); +} diff --git a/tests/ui/async-await/async-closure.rs b/tests/ui/async-await/async-closure.rs new file mode 100644 index 000000000..12d66b19e --- /dev/null +++ b/tests/ui/async-await/async-closure.rs @@ -0,0 +1,100 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +// edition:2018 +// aux-build:arc_wake.rs + +#![feature(async_closure)] + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool); + +fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } + +impl Future for WakeOnceThenComplete { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + if self.0 { + Poll::Ready(()) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn async_closure(x: u8) -> impl Future { + (async move |x: u8| -> u8 { + wake_and_yield_once().await; + x + })(x) +} + +fn async_closure_in_unsafe_block(x: u8) -> impl Future { + (unsafe { + async move |x: u8| unsafe_fn(unsafe_async_fn(x).await) + })(x) +} + +async unsafe fn unsafe_async_fn(x: u8) -> u8 { + wake_and_yield_once().await; + x +} + +unsafe fn unsafe_fn(x: u8) -> u8 { + x +} + +fn test_future_yields_once_then_returns(f: F) +where + F: FnOnce(u8) -> Fut, + Fut: Future, +{ + let mut fut = Box::pin(f(9)); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx)); + assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx)); +} + +fn main() { + macro_rules! test { + ($($fn_name:expr,)*) => { $( + test_future_yields_once_then_returns($fn_name); + )* } + } + + test! { + async_closure, + async_closure_in_unsafe_block, + } +} diff --git a/tests/ui/async-await/async-error-span.rs b/tests/ui/async-await/async-error-span.rs new file mode 100644 index 000000000..86d459bf0 --- /dev/null +++ b/tests/ui/async-await/async-error-span.rs @@ -0,0 +1,17 @@ +// edition:2018 + +// Regression test for issue #62382. + +use std::future::Future; + +fn get_future() -> impl Future { +//~^ ERROR `()` is not a future + panic!() +} + +async fn foo() { + let a; //~ ERROR type inside `async fn` body must be known in this context + get_future().await; +} + +fn main() {} diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.stderr new file mode 100644 index 000000000..7d4447b6d --- /dev/null +++ b/tests/ui/async-await/async-error-span.stderr @@ -0,0 +1,25 @@ +error[E0277]: `()` is not a future + --> $DIR/async-error-span.rs:7:20 + | +LL | fn get_future() -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + +error[E0698]: type inside `async fn` body must be known in this context + --> $DIR/async-error-span.rs:13:9 + | +LL | let a; + | ^ cannot infer type + | +note: the type is part of the `async fn` body because of this `await` + --> $DIR/async-error-span.rs:14:17 + | +LL | get_future().await; + | ^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0698. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs b/tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs new file mode 100644 index 000000000..1c369fd74 --- /dev/null +++ b/tests/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs @@ -0,0 +1,15 @@ +// Check that `async fn` inside of an impl with `'_` +// in the header compiles correctly. +// +// Regression test for #63500. +// +// check-pass +// edition:2018 + +struct Foo<'a>(&'a u8); + +impl Foo<'_> { + async fn bar() {} +} + +fn main() { } diff --git a/tests/ui/async-await/async-fn-nonsend.rs b/tests/ui/async-await/async-fn-nonsend.rs new file mode 100644 index 000000000..d7f8d7ac5 --- /dev/null +++ b/tests/ui/async-await/async-fn-nonsend.rs @@ -0,0 +1,74 @@ +// edition:2018 +// compile-flags: --crate-type lib -Zdrop-tracking + +use std::{cell::RefCell, fmt::Debug, rc::Rc}; + +fn non_sync() -> impl Debug { + RefCell::new(()) +} + +fn non_send() -> impl Debug { + Rc::new(()) +} + +fn take_ref(_: &T) {} + +async fn fut() {} + +async fn fut_arg(_: T) {} + +async fn local_dropped_before_await() { + // this is okay now because of the drop + let x = non_send(); + drop(x); + fut().await; +} + +async fn non_send_temporary_in_match() { + // We could theoretically make this work as well (produce a `Send` future) + // for scrutinees / temporaries that can or will + // be dropped prior to the match body + // (e.g. `Copy` types). + match Some(non_send()) { + Some(_) => fut().await, + None => {} + } +} + +fn get_formatter() -> std::fmt::Formatter<'static> { + panic!() +} + +async fn non_sync_with_method_call() { + let f: &mut std::fmt::Formatter = &mut get_formatter(); + // It would by nice for this to work. + if non_sync().fmt(f).unwrap() == () { + fut().await; + } +} + +async fn non_sync_with_method_call_panic() { + let f: &mut std::fmt::Formatter = panic!(); + if non_sync().fmt(f).unwrap() == () { + fut().await; + } +} + +async fn non_sync_with_method_call_infinite_loop() { + let f: &mut std::fmt::Formatter = loop {}; + if non_sync().fmt(f).unwrap() == () { + fut().await; + } +} + +fn assert_send(_: impl Send) {} + +pub fn pass_assert() { + assert_send(local_dropped_before_await()); + assert_send(non_send_temporary_in_match()); + //~^ ERROR future cannot be sent between threads safely + assert_send(non_sync_with_method_call()); + //~^ ERROR future cannot be sent between threads safely + assert_send(non_sync_with_method_call_panic()); + assert_send(non_sync_with_method_call_infinite_loop()); +} diff --git a/tests/ui/async-await/async-fn-nonsend.stderr b/tests/ui/async-await/async-fn-nonsend.stderr new file mode 100644 index 000000000..a7b872fe4 --- /dev/null +++ b/tests/ui/async-await/async-fn-nonsend.stderr @@ -0,0 +1,49 @@ +error: future cannot be sent between threads safely + --> $DIR/async-fn-nonsend.rs:68:17 + | +LL | assert_send(non_send_temporary_in_match()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:33:25 + | +LL | match Some(non_send()) { + | ---------------- has type `Option` which is not `Send` +LL | Some(_) => fut().await, + | ^^^^^^ await occurs here, with `Some(non_send())` maybe used later +... +LL | } + | - `Some(non_send())` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/async-fn-nonsend.rs:64:24 + | +LL | fn assert_send(_: impl Send) {} + | ^^^^ required by this bound in `assert_send` + +error: future cannot be sent between threads safely + --> $DIR/async-fn-nonsend.rs:70:17 + | +LL | assert_send(non_sync_with_method_call()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` +note: future is not `Send` as this value is used across an await + --> $DIR/async-fn-nonsend.rs:46:14 + | +LL | let f: &mut std::fmt::Formatter = &mut get_formatter(); + | --------------- has type `Formatter<'_>` which is not `Send` +... +LL | fut().await; + | ^^^^^^ await occurs here, with `get_formatter()` maybe used later +LL | } +LL | } + | - `get_formatter()` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/async-fn-nonsend.rs:64:24 + | +LL | fn assert_send(_: impl Send) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/async-fn-path-elision.rs b/tests/ui/async-await/async-fn-path-elision.rs new file mode 100644 index 000000000..3f1f51c20 --- /dev/null +++ b/tests/ui/async-await/async-fn-path-elision.rs @@ -0,0 +1,13 @@ +// edition:2018 + +struct HasLifetime<'a>(&'a bool); + +async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here + if *lt.0 {} +} + +fn no_error(lt: HasLifetime) { + if *lt.0 {} +} + +fn main() {} diff --git a/tests/ui/async-await/async-fn-path-elision.stderr b/tests/ui/async-await/async-fn-path-elision.stderr new file mode 100644 index 000000000..5e0c8c299 --- /dev/null +++ b/tests/ui/async-await/async-fn-path-elision.stderr @@ -0,0 +1,15 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/async-fn-path-elision.rs:5:20 + | +LL | async fn error(lt: HasLifetime) { + | ^^^^^^^^^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +LL | async fn error(lt: HasLifetime<'_>) { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/async-await/async-fn-send-uses-nonsend.rs b/tests/ui/async-await/async-fn-send-uses-nonsend.rs new file mode 100644 index 000000000..35d9cb155 --- /dev/null +++ b/tests/ui/async-await/async-fn-send-uses-nonsend.rs @@ -0,0 +1,57 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 +// compile-flags: --crate-type lib + +use std::{ + cell::RefCell, + fmt::Debug, + rc::Rc, +}; + +fn non_sync() -> impl Debug { RefCell::new(()) } + +fn non_send() -> impl Debug { Rc::new(()) } + +fn take_ref(_: &T) {} + +async fn fut() {} + +async fn fut_arg(_: T) {} + +async fn still_send() { + fut().await; + println!("{:?} {:?}", non_send(), non_sync()); + fut().await; + drop(non_send()); + drop(non_sync()); + fut().await; + fut_arg(non_sync()).await; + + // Note: all temporaries in `if let` and `match` scrutinee + // are dropped at the *end* of the blocks, so using `non_send()` + // in either of those positions with an await in the middle will + // cause a `!Send` future. It might be nice in the future to allow + // this for `Copy` types, since they can be "dropped" early without + // affecting the end user. + if let Some(_) = Some(non_sync()) { + fut().await; + } + match Some(non_sync()) { + Some(_) => fut().await, + None => fut().await, + } + + let _ = non_send(); + fut().await; + + { + let _x = non_send(); + } + fut().await; +} + +fn assert_send(_: impl Send) {} + +pub fn pass_assert() { + assert_send(still_send()); +} diff --git a/tests/ui/async-await/async-fn-size-moved-locals.rs b/tests/ui/async-await/async-fn-size-moved-locals.rs new file mode 100644 index 000000000..79b7239f3 --- /dev/null +++ b/tests/ui/async-await/async-fn-size-moved-locals.rs @@ -0,0 +1,118 @@ +// Test that we don't duplicate storage for futures moved around in .await, and +// for futures moved into other futures. +// +// The exact sizes can change by a few bytes (we'd like to know when they do). +// What we don't want to see is the wrong multiple of 1024 (the size of BigFut) +// being reflected in the size. +// +// See issue #59123 for a full explanation. + +// needs-unwind Size of Futures change on panic=abort +// run-pass + +// edition:2018 + +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +const BIG_FUT_SIZE: usize = 1024; +struct BigFut(#[allow(unused_tuple_struct_fields)] [u8; BIG_FUT_SIZE]); + +impl BigFut { + fn new() -> Self { + BigFut([0; BIG_FUT_SIZE]) + } +} + +impl Drop for BigFut { + fn drop(&mut self) {} +} + +impl Future for BigFut { + type Output = (); + + fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} + +#[allow(dead_code)] +struct Joiner { + a: Option, + b: Option, + c: Option, +} + +impl Future for Joiner { + type Output = (); + + fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} + +fn noop() {} + +async fn single() { + let x = BigFut::new(); + x.await; +} + +async fn single_with_noop() { + let x = BigFut::new(); + noop(); + x.await; +} + +async fn joined() { + let a = BigFut::new(); + let b = BigFut::new(); + let c = BigFut::new(); + + let joiner = Joiner { + a: Some(a), + b: Some(b), + c: Some(c), + }; + joiner.await +} + +async fn joined_with_noop() { + let a = BigFut::new(); + let b = BigFut::new(); + let c = BigFut::new(); + + let joiner = Joiner { + a: Some(a), + b: Some(b), + c: Some(c), + }; + noop(); + joiner.await +} + +async fn mixed_sizes() { + let a = BigFut::new(); + let b = BigFut::new(); + let c = BigFut::new(); + let d = BigFut::new(); + let e = BigFut::new(); + let joiner = Joiner { + a: Some(a), + b: Some(b), + c: Some(c), + }; + + d.await; + e.await; + joiner.await; +} + +fn main() { + assert_eq!(1025, std::mem::size_of_val(&single())); + assert_eq!(1026, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3076, std::mem::size_of_val(&joined())); + assert_eq!(3076, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(6157, std::mem::size_of_val(&mixed_sizes())); +} diff --git a/tests/ui/async-await/async-fn-size-uninit-locals.rs b/tests/ui/async-await/async-fn-size-uninit-locals.rs new file mode 100644 index 000000000..546172693 --- /dev/null +++ b/tests/ui/async-await/async-fn-size-uninit-locals.rs @@ -0,0 +1,102 @@ +// Test that we don't store uninitialized locals in futures from `async fn`. +// +// The exact sizes can change by a few bytes (we'd like to know when they do). +// What we don't want to see is the wrong multiple of 1024 (the size of `Big`) +// being reflected in the size. + +// ignore-emscripten (sizes don't match) +// needs-unwind Size of Futures change on panic=abort +// run-pass + +// edition:2018 + +#![allow(unused_variables, unused_assignments)] + +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +const BIG_FUT_SIZE: usize = 1024; +struct Big(#[allow(unused_tuple_struct_fields)] [u8; BIG_FUT_SIZE]); + +impl Big { + fn new() -> Self { + Big([0; BIG_FUT_SIZE]) + } +} + +impl Drop for Big { + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct Joiner { + a: Option, + b: Option, + c: Option, +} + +impl Future for Joiner { + type Output = (); + + fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} + +fn noop() {} +async fn fut() {} + +async fn single() { + let x; + fut().await; + x = Big::new(); +} + +async fn single_with_noop() { + let x; + fut().await; + noop(); + x = Big::new(); + noop(); +} + +async fn joined() { + let joiner; + let a = Big::new(); + let b = Big::new(); + let c = Big::new(); + + fut().await; + joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) }; +} + +async fn joined_with_noop() { + let joiner; + let a = Big::new(); + let b = Big::new(); + let c = Big::new(); + + fut().await; + noop(); + joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) }; + noop(); +} + +async fn join_retval() -> Joiner { + let a = Big::new(); + let b = Big::new(); + let c = Big::new(); + + fut().await; + noop(); + Joiner { a: Some(a), b: Some(b), c: Some(c) } +} + +fn main() { + assert_eq!(2, std::mem::size_of_val(&single())); + assert_eq!(3, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3074, std::mem::size_of_val(&joined())); + assert_eq!(3078, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(3074, std::mem::size_of_val(&join_retval())); +} diff --git a/tests/ui/async-await/async-fn-size.rs b/tests/ui/async-await/async-fn-size.rs new file mode 100644 index 000000000..0c1f36364 --- /dev/null +++ b/tests/ui/async-await/async-fn-size.rs @@ -0,0 +1,105 @@ +// run-pass +// aux-build:arc_wake.rs +// edition:2018 + +extern crate arc_wake; + +use std::pin::Pin; +use std::future::Future; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{Context, Poll}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct WakeOnceThenComplete(bool, u8); + +impl Future for WakeOnceThenComplete { + type Output = u8; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.0 { + Poll::Ready(self.1) + } else { + cx.waker().wake_by_ref(); + self.0 = true; + Poll::Pending + } + } +} + +fn wait(fut: impl Future) -> u8 { + let mut fut = Box::pin(fut); + let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); + let waker = ArcWake::into_waker(counter.clone()); + let mut cx = Context::from_waker(&waker); + loop { + match fut.as_mut().poll(&mut cx) { + Poll::Ready(out) => return out, + Poll::Pending => (), + } + } +} + +fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) } + +async fn await1_level1() -> u8 { + base().await +} + +async fn await2_level1() -> u8 { + base().await + base().await +} + +async fn await3_level1() -> u8 { + base().await + base().await + base().await +} + +async fn await3_level2() -> u8 { + await3_level1().await + await3_level1().await + await3_level1().await +} + +async fn await3_level3() -> u8 { + await3_level2().await + await3_level2().await + await3_level2().await +} + +async fn await3_level4() -> u8 { + await3_level3().await + await3_level3().await + await3_level3().await +} + +async fn await3_level5() -> u8 { + await3_level4().await + await3_level4().await + await3_level4().await +} + +fn main() { + assert_eq!(2, std::mem::size_of_val(&base())); + assert_eq!(3, std::mem::size_of_val(&await1_level1())); + assert_eq!(4, std::mem::size_of_val(&await2_level1())); + assert_eq!(5, std::mem::size_of_val(&await3_level1())); + assert_eq!(8, std::mem::size_of_val(&await3_level2())); + assert_eq!(11, std::mem::size_of_val(&await3_level3())); + assert_eq!(14, std::mem::size_of_val(&await3_level4())); + assert_eq!(17, std::mem::size_of_val(&await3_level5())); + + assert_eq!(1, wait(base())); + assert_eq!(1, wait(await1_level1())); + assert_eq!(2, wait(await2_level1())); + assert_eq!(3, wait(await3_level1())); + assert_eq!(9, wait(await3_level2())); + assert_eq!(27, wait(await3_level3())); + assert_eq!(81, wait(await3_level4())); + assert_eq!(243, wait(await3_level5())); +} diff --git a/tests/ui/async-await/async-is-unwindsafe.rs b/tests/ui/async-await/async-is-unwindsafe.rs new file mode 100644 index 000000000..56ed28472 --- /dev/null +++ b/tests/ui/async-await/async-is-unwindsafe.rs @@ -0,0 +1,30 @@ +// edition:2018 + +fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} + +fn main() { + // A normal future created by an async block takes a `&mut Context<'_>` argument. + // That should not leak through to the whole async block. + is_unwindsafe(async { + async {}.await; // this needs an inner await point + }); + + is_unwindsafe(async { + //~^ ERROR the type `&mut Context<'_>` may not be safely transferred across an unwind boundary + use std::ptr::null; + use std::task::{Context, RawWaker, RawWakerVTable, Waker}; + let waker = unsafe { + Waker::from_raw(RawWaker::new( + null(), + &RawWakerVTable::new(|_| todo!(), |_| todo!(), |_| todo!(), |_| todo!()), + )) + }; + let mut cx = Context::from_waker(&waker); + let cx_ref = &mut cx; + + async {}.await; // this needs an inner await point + + // in this case, `&mut Context<'_>` is *truly* alive across an await point + drop(cx_ref); + }); +} diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr new file mode 100644 index 000000000..d6404b30e --- /dev/null +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -0,0 +1,38 @@ +error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary + --> $DIR/async-is-unwindsafe.rs:12:19 + | +LL | is_unwindsafe(async { + | ___________________^ +LL | | +LL | | use std::ptr::null; +LL | | use std::task::{Context, RawWaker, RawWakerVTable, Waker}; +... | +LL | | drop(cx_ref); +LL | | }); + | | ^ + | | | + | |_____`&mut Context<'_>` may not be safely transferred across an unwind boundary + | within this `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]` + | + = help: within `[async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6]`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>` + = note: `UnwindSafe` is implemented for `&std::task::Context<'_>`, but not for `&mut std::task::Context<'_>` +note: future does not implement `UnwindSafe` as this value is used across an await + --> $DIR/async-is-unwindsafe.rs:25:17 + | +LL | let cx_ref = &mut cx; + | ------ has type `&mut Context<'_>` which does not implement `UnwindSafe` +LL | +LL | async {}.await; // this needs an inner await point + | ^^^^^^ await occurs here, with `cx_ref` maybe used later +... +LL | }); + | - `cx_ref` is later dropped here +note: required by a bound in `is_unwindsafe` + --> $DIR/async-is-unwindsafe.rs:3:26 + | +LL | fn is_unwindsafe(_: impl std::panic::UnwindSafe) {} + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_unwindsafe` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-matches-expr.rs b/tests/ui/async-await/async-matches-expr.rs new file mode 100644 index 000000000..299faa058 --- /dev/null +++ b/tests/ui/async-await/async-matches-expr.rs @@ -0,0 +1,10 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +macro_rules! match_expr { + ($x:expr) => {} +} + +fn main() { + match_expr!(async {}); +} diff --git a/tests/ui/async-await/async-trait-fn.rs b/tests/ui/async-await/async-trait-fn.rs new file mode 100644 index 000000000..e2062e827 --- /dev/null +++ b/tests/ui/async-await/async-trait-fn.rs @@ -0,0 +1,11 @@ +// edition:2018 +trait T { + async fn foo() {} //~ ERROR functions in traits cannot be declared `async` + async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async` + async fn baz() { //~ ERROR functions in traits cannot be declared `async` + // Nested item must not ICE. + fn a() {} + } +} + +fn main() {} diff --git a/tests/ui/async-await/async-trait-fn.stderr b/tests/ui/async-await/async-trait-fn.stderr new file mode 100644 index 000000000..afbe25cf7 --- /dev/null +++ b/tests/ui/async-await/async-trait-fn.stderr @@ -0,0 +1,42 @@ +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:3:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:4:5 + | +LL | async fn bar(&self) {} + | -----^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/async-trait-fn.rs:5:5 + | +LL | async fn baz() { + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0706`. diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr b/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr new file mode 100644 index 000000000..2114fb59b --- /dev/null +++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr @@ -0,0 +1,35 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:14:5 + | +LL | S::f(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:17:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:23:5 + | +LL | S::f(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:24:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs b/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs new file mode 100644 index 000000000..c941dc27a --- /dev/null +++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs @@ -0,0 +1,25 @@ +// edition:2018 +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +struct S; + +impl S { + async unsafe fn f() {} +} + +async unsafe fn f() {} + +async fn g() { + S::f(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `S::f` is unsafe + f(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `f` is unsafe +} + +fn main() { + S::f(); //[mir]~ ERROR call to unsafe function is unsafe + f(); //[mir]~ ERROR call to unsafe function is unsafe +} diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr b/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr new file mode 100644 index 000000000..68d97d3fd --- /dev/null +++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:14:5 + | +LL | S::f(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:17:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/async-await/async-with-closure.rs b/tests/ui/async-await/async-with-closure.rs new file mode 100644 index 000000000..0b2255266 --- /dev/null +++ b/tests/ui/async-await/async-with-closure.rs @@ -0,0 +1,24 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +trait MyClosure { + type Args; +} + +impl MyClosure for dyn FnMut() -> R +where R: 'static { + type Args = (); +} + +struct MyStream { + x: C::Args, +} + +async fn get_future(_stream: MyStream) {} + +async fn f() { + let messages: MyStream = unimplemented!(); + get_future(messages).await; +} + +fn main() {} diff --git a/tests/ui/async-await/auxiliary/arc_wake.rs b/tests/ui/async-await/auxiliary/arc_wake.rs new file mode 100644 index 000000000..c21886f26 --- /dev/null +++ b/tests/ui/async-await/auxiliary/arc_wake.rs @@ -0,0 +1,64 @@ +// edition:2018 + +use std::sync::Arc; +use std::task::{ + Waker, RawWaker, RawWakerVTable, +}; + +macro_rules! waker_vtable { + ($ty:ident) => { + &RawWakerVTable::new( + clone_arc_raw::<$ty>, + wake_arc_raw::<$ty>, + wake_by_ref_arc_raw::<$ty>, + drop_arc_raw::<$ty>, + ) + }; +} + +pub trait ArcWake { + fn wake(self: Arc); + + fn wake_by_ref(arc_self: &Arc) { + arc_self.clone().wake() + } + + fn into_waker(wake: Arc) -> Waker where Self: Sized + { + let ptr = Arc::into_raw(wake) as *const (); + + unsafe { + Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self))) + } + } +} + +unsafe fn increase_refcount(data: *const ()) { + // Retain Arc by creating a copy + let arc: Arc = Arc::from_raw(data as *const T); + let arc_clone = arc.clone(); + // Forget the Arcs again, so that the refcount isn't decrased + let _ = Arc::into_raw(arc); + let _ = Arc::into_raw(arc_clone); +} + +unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { + increase_refcount::(data); + RawWaker::new(data, waker_vtable!(T)) +} + +unsafe fn drop_arc_raw(data: *const ()) { + // Drop Arc + let _: Arc = Arc::from_raw(data as *const T); +} + +unsafe fn wake_arc_raw(data: *const ()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake(arc); +} + +unsafe fn wake_by_ref_arc_raw(data: *const ()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake_by_ref(&arc); + let _ = Arc::into_raw(arc); +} diff --git a/tests/ui/async-await/auxiliary/issue-107036.rs b/tests/ui/async-await/auxiliary/issue-107036.rs new file mode 100644 index 000000000..c3f6141b2 --- /dev/null +++ b/tests/ui/async-await/auxiliary/issue-107036.rs @@ -0,0 +1,12 @@ +// edition:2021 + +pub trait T {} +impl T for () {} + +pub struct S {} + +impl S { + pub async fn f<'a>(&self) -> impl T + 'a { + () + } +} diff --git a/tests/ui/async-await/auxiliary/issue-72470-lib.rs b/tests/ui/async-await/auxiliary/issue-72470-lib.rs new file mode 100644 index 000000000..8383eba89 --- /dev/null +++ b/tests/ui/async-await/auxiliary/issue-72470-lib.rs @@ -0,0 +1,175 @@ +// compile-flags: -C opt-level=3 +// edition:2018 + +use std::future::Future; +use std::marker::PhantomData; +use std::pin::Pin; +use std::sync::atomic::AtomicUsize; +use std::sync::Arc; +use std::task::Poll::{Pending, Ready}; +use std::task::Waker; +use std::task::{Context, Poll}; +use std::{ + ptr, + task::{RawWaker, RawWakerVTable}, +}; + +/// Future for the [`poll_fn`] function. +pub struct PollFn { + f: F, +} + +impl Unpin for PollFn {} + +/// Creates a new future wrapping around a function returning [`Poll`]. +pub fn poll_fn(f: F) -> PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + PollFn { f } +} + +impl Future for PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + (&mut self.f)(cx) + } +} +pub fn run(future: F) -> F::Output { + BasicScheduler.block_on(future) +} + +pub(crate) struct BasicScheduler; + +impl BasicScheduler { + pub(crate) fn block_on(&mut self, mut future: F) -> F::Output + where + F: Future, + { + let waker = unsafe { Waker::from_raw(raw_waker()) }; + let mut cx = std::task::Context::from_waker(&waker); + + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + + loop { + if let Ready(v) = future.as_mut().poll(&mut cx) { + return v; + } + } + } +} + +// ===== impl Spawner ===== + +fn raw_waker() -> RawWaker { + RawWaker::new(ptr::null(), waker_vtable()) +} + +fn waker_vtable() -> &'static RawWakerVTable { + &RawWakerVTable::new( + clone_arc_raw, + wake_arc_raw, + wake_by_ref_arc_raw, + drop_arc_raw, + ) +} + +unsafe fn clone_arc_raw(_: *const ()) -> RawWaker { + raw_waker() +} + +unsafe fn wake_arc_raw(_: *const ()) {} + +unsafe fn wake_by_ref_arc_raw(_: *const ()) {} + +unsafe fn drop_arc_raw(_: *const ()) {} + +struct AtomicWaker {} + +impl AtomicWaker { + /// Create an `AtomicWaker` + fn new() -> AtomicWaker { + AtomicWaker {} + } + + fn register_by_ref(&self, _waker: &Waker) {} +} + +#[allow(dead_code)] +struct Tx { + inner: Arc>, +} + +struct Rx { + inner: Arc>, +} + +#[allow(dead_code)] +struct Chan { + tx: PhantomData, + semaphore: Sema, + rx_waker: AtomicWaker, + rx_closed: bool, +} + +fn channel() -> (Tx, Rx) { + let chan = Arc::new(Chan { + tx: PhantomData, + semaphore: Sema(AtomicUsize::new(0)), + rx_waker: AtomicWaker::new(), + rx_closed: false, + }); + + ( + Tx { + inner: chan.clone(), + }, + Rx { inner: chan }, + ) +} + +// ===== impl Rx ===== + +impl Rx { + /// Receive the next value + fn recv(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.rx_waker.register_by_ref(cx.waker()); + + if self.inner.rx_closed && self.inner.semaphore.is_idle() { + Ready(None) + } else { + Pending + } + } +} + +struct Sema(AtomicUsize); + +impl Sema { + fn is_idle(&self) -> bool { + false + } +} + +pub struct UnboundedReceiver { + chan: Rx, +} + +pub fn unbounded_channel() -> UnboundedReceiver { + let (tx, rx) = channel(); + + drop(tx); + let rx = UnboundedReceiver { chan: rx }; + + rx +} + +impl UnboundedReceiver { + pub async fn recv(&mut self) -> Option { + poll_fn(|cx| self.chan.recv(cx)).await + } +} diff --git a/tests/ui/async-await/await-into-future.rs b/tests/ui/async-await/await-into-future.rs new file mode 100644 index 000000000..8bf1385b3 --- /dev/null +++ b/tests/ui/async-await/await-into-future.rs @@ -0,0 +1,28 @@ +// run-pass +// aux-build: issue-72470-lib.rs +// edition:2021 +extern crate issue_72470_lib; +use std::{future::{Future, IntoFuture}, pin::Pin}; + +struct AwaitMe; + +impl IntoFuture for AwaitMe { + type Output = i32; + type IntoFuture = Pin>>; + + fn into_future(self) -> Self::IntoFuture { + Box::pin(me()) + } +} + +async fn me() -> i32 { + 41 +} + +async fn run() { + assert_eq!(AwaitMe.await, 41); +} + +fn main() { + issue_72470_lib::run(run()); +} diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs new file mode 100644 index 000000000..50c163999 --- /dev/null +++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.rs @@ -0,0 +1,38 @@ +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod await { //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this is accepted in the current edition + pub struct await; //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this is accepted in the current edition + } +} +use outer_mod::await::await; //~ ERROR `await` is a keyword in the 2018 edition +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this is accepted in the current edition +//~^^^ WARN this is accepted in the current edition + +struct Foo { await: () } +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this is accepted in the current edition + +impl Foo { fn await() {} } +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this is accepted in the current edition + +macro_rules! await { +//~^ ERROR `await` is a keyword in the 2018 edition +//~^^ WARN this is accepted in the current edition + () => {} +} + +fn main() { + await!(); //~ ERROR `await` is a keyword in the 2018 edition + //~^ WARN this is accepted in the current edition + + match await { await => {} } //~ ERROR `await` is a keyword in the 2018 edition + //~^ ERROR `await` is a keyword in the 2018 edition + //~^^ WARN this is accepted in the current edition + //~^^^ WARN this is accepted in the current edition +} diff --git a/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr new file mode 100644 index 000000000..d99967eb2 --- /dev/null +++ b/tests/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr @@ -0,0 +1,97 @@ +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:5:13 + | +LL | pub mod await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/2015-edition-error-various-positions.rs:2:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:7:20 + | +LL | pub struct await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:11:16 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:11:23 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:16:14 + | +LL | struct Foo { await: () } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:20:15 + | +LL | impl Foo { fn await() {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:24:14 + | +LL | macro_rules! await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:31:5 + | +LL | await!(); + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:34:11 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-error-various-positions.rs:34:19 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: aborting due to 10 previous errors + diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.fixed b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed new file mode 100644 index 000000000..117495e13 --- /dev/null +++ b/tests/ui/async-await/await-keyword/2015-edition-warning.fixed @@ -0,0 +1,27 @@ +// run-rustfix + +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod r#await { +//~^ ERROR `await` is a keyword +//~| WARN this is accepted in the current edition + pub struct r#await; +//~^ ERROR `await` is a keyword +//~| WARN this is accepted in the current edition + } +} +use outer_mod::r#await::r#await; +//~^ ERROR `await` is a keyword +//~| ERROR `await` is a keyword +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition + +fn main() { + match r#await { r#await => {} } +//~^ ERROR `await` is a keyword +//~| ERROR `await` is a keyword +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +} diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.rs b/tests/ui/async-await/await-keyword/2015-edition-warning.rs new file mode 100644 index 000000000..b3c64895c --- /dev/null +++ b/tests/ui/async-await/await-keyword/2015-edition-warning.rs @@ -0,0 +1,27 @@ +// run-rustfix + +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod await { +//~^ ERROR `await` is a keyword +//~| WARN this is accepted in the current edition + pub struct await; +//~^ ERROR `await` is a keyword +//~| WARN this is accepted in the current edition + } +} +use outer_mod::await::await; +//~^ ERROR `await` is a keyword +//~| ERROR `await` is a keyword +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition + +fn main() { + match await { await => {} } +//~^ ERROR `await` is a keyword +//~| ERROR `await` is a keyword +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +} diff --git a/tests/ui/async-await/await-keyword/2015-edition-warning.stderr b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr new file mode 100644 index 000000000..bf5c4d8d6 --- /dev/null +++ b/tests/ui/async-await/await-keyword/2015-edition-warning.stderr @@ -0,0 +1,61 @@ +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-warning.rs:7:13 + | +LL | pub mod await { + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/2015-edition-warning.rs:4:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-warning.rs:10:20 + | +LL | pub struct await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-warning.rs:15:16 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-warning.rs:15:23 + | +LL | use outer_mod::await::await; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-warning.rs:22:11 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `await` is a keyword in the 2018 edition + --> $DIR/2015-edition-warning.rs:22:19 + | +LL | match await { await => {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: aborting due to 6 previous errors + diff --git a/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs new file mode 100644 index 000000000..9e78f7c51 --- /dev/null +++ b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -0,0 +1,24 @@ +// edition:2018 + +#![allow(non_camel_case_types)] + +mod outer_mod { + pub mod await { //~ ERROR expected identifier, found keyword `await` + pub struct await; //~ ERROR expected identifier, found keyword `await` + } +} +use self::outer_mod::await::await; //~ ERROR expected identifier, found keyword `await` +//~^ ERROR expected identifier, found keyword `await` + +struct Foo { await: () } +//~^ ERROR expected identifier, found keyword `await` + +impl Foo { fn await() {} } +//~^ ERROR expected identifier, found keyword `await` + +macro_rules! await { +//~^ ERROR expected identifier, found keyword `await` + () => {} +} + +fn main() {} diff --git a/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr new file mode 100644 index 000000000..6bd8f671d --- /dev/null +++ b/tests/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr @@ -0,0 +1,81 @@ +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:6:13 + | +LL | pub mod await { + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | pub mod r#await { + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:7:20 + | +LL | pub struct await; + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | pub struct r#await; + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:10:22 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | use self::outer_mod::r#await::await; + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:10:29 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | use self::outer_mod::await::r#await; + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:13:14 + | +LL | struct Foo { await: () } + | --- ^^^^^ expected identifier, found keyword + | | + | while parsing this struct + | +help: escape `await` to use it as an identifier + | +LL | struct Foo { r#await: () } + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:16:15 + | +LL | impl Foo { fn await() {} } + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | impl Foo { fn r#await() {} } + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error-in-non-macro-position.rs:19:14 + | +LL | macro_rules! await { + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | macro_rules! r#await { + | ++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/async-await/await-keyword/2018-edition-error.rs b/tests/ui/async-await/await-keyword/2018-edition-error.rs new file mode 100644 index 000000000..7ce52259a --- /dev/null +++ b/tests/ui/async-await/await-keyword/2018-edition-error.rs @@ -0,0 +1,16 @@ +// edition:2018 +#![allow(non_camel_case_types)] + +mod outer_mod { + pub mod await { //~ ERROR expected identifier + pub struct await; //~ ERROR expected identifier + } +} +use self::outer_mod::await::await; //~ ERROR expected identifier + //~^ ERROR expected identifier, found keyword `await` + +macro_rules! await { () => {}; } //~ ERROR expected identifier, found keyword `await` + +fn main() { + await!(); //~ ERROR expected expression, found `)` +} diff --git a/tests/ui/async-await/await-keyword/2018-edition-error.stderr b/tests/ui/async-await/await-keyword/2018-edition-error.stderr new file mode 100644 index 000000000..34bfdfc71 --- /dev/null +++ b/tests/ui/async-await/await-keyword/2018-edition-error.stderr @@ -0,0 +1,63 @@ +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error.rs:5:13 + | +LL | pub mod await { + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | pub mod r#await { + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error.rs:6:20 + | +LL | pub struct await; + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | pub struct r#await; + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error.rs:9:22 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | use self::outer_mod::r#await::await; + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error.rs:9:29 + | +LL | use self::outer_mod::await::await; + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | use self::outer_mod::await::r#await; + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/2018-edition-error.rs:12:14 + | +LL | macro_rules! await { () => {}; } + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | macro_rules! r#await { () => {}; } + | ++ + +error: expected expression, found `)` + --> $DIR/2018-edition-error.rs:15:12 + | +LL | await!(); + | ^ expected expression + +error: aborting due to 6 previous errors + diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs new file mode 100644 index 000000000..554ac673d --- /dev/null +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs @@ -0,0 +1,132 @@ +// edition:2018 + +async fn bar() -> Result<(), ()> { + Ok(()) +} + +async fn foo1() -> Result<(), ()> { + let _ = await bar(); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo2() -> Result<(), ()> { + let _ = await? bar(); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo3() -> Result<(), ()> { + let _ = await bar()?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo21() -> Result<(), ()> { + let _ = await { bar() }; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo22() -> Result<(), ()> { + let _ = await(bar()); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo23() -> Result<(), ()> { + let _ = await { bar() }?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo4() -> Result<(), ()> { + let _ = (await bar())?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo5() -> Result<(), ()> { + let _ = bar().await(); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo6() -> Result<(), ()> { + let _ = bar().await()?; //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo7() -> Result<(), ()> { + let _ = bar().await; // OK + Ok(()) +} +async fn foo8() -> Result<(), ()> { + let _ = bar().await?; // OK + Ok(()) +} +fn foo9() -> Result<(), ()> { + let _ = await bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo10() -> Result<(), ()> { + let _ = await? bar(); //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo11() -> Result<(), ()> { + let _ = await bar()?; //~ ERROR incorrect use of `await` + Ok(()) +} +fn foo12() -> Result<(), ()> { + let _ = (await bar())?; //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo13() -> Result<(), ()> { + let _ = bar().await(); //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo14() -> Result<(), ()> { + let _ = bar().await()?; //~ ERROR `await` is only allowed inside `async` functions and blocks + //~^ ERROR incorrect use of `await` + Ok(()) +} +fn foo15() -> Result<(), ()> { + let _ = bar().await; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) +} +fn foo16() -> Result<(), ()> { + let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) +} +fn foo24() -> Result<(), ()> { + fn foo() -> Result<(), ()> { + let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) + } + foo() +} +fn foo25() -> Result<(), ()> { + let foo = || { + let _ = bar().await?; //~ ERROR `await` is only allowed inside `async` functions and blocks + Ok(()) + }; + foo() +} + +async fn foo26() -> Result<(), ()> { + let _ = await!(bar()); //~ ERROR incorrect use of `await` + Ok(()) +} +async fn foo27() -> Result<(), ()> { + let _ = await!(bar())?; //~ ERROR incorrect use of `await` + Ok(()) +} +fn foo28() -> Result<(), ()> { + fn foo() -> Result<(), ()> { + let _ = await!(bar())?; //~ ERROR incorrect use of `await` + //~^ ERROR `await` is only allowed inside `async` functions + Ok(()) + } + foo() +} +fn foo29() -> Result<(), ()> { + let foo = || { + let _ = await!(bar())?; //~ ERROR incorrect use of `await` + //~^ ERROR `await` is only allowed inside `async` functions + Ok(()) + }; + foo() +} + +fn main() { + match await { await => () } + //~^ ERROR expected expression, found `=>` + //~| ERROR incorrect use of `await` +} //~ ERROR expected one of `.`, `?`, `{`, or an operator, found `}` diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr new file mode 100644 index 000000000..b30f28837 --- /dev/null +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -0,0 +1,230 @@ +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:8:13 + | +LL | let _ = await bar(); + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:12:13 + | +LL | let _ = await? bar(); + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:16:13 + | +LL | let _ = await bar()?; + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:20:13 + | +LL | let _ = await { bar() }; + | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:24:13 + | +LL | let _ = await(bar()); + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:28:13 + | +LL | let _ = await { bar() }?; + | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:32:14 + | +LL | let _ = (await bar())?; + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:36:24 + | +LL | let _ = bar().await(); + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:40:24 + | +LL | let _ = bar().await()?; + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:52:13 + | +LL | let _ = await bar(); + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:57:13 + | +LL | let _ = await? bar(); + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:62:13 + | +LL | let _ = await bar()?; + | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:66:14 + | +LL | let _ = (await bar())?; + | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:71:24 + | +LL | let _ = bar().await(); + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:76:24 + | +LL | let _ = bar().await()?; + | ^^ help: `await` is not a method call, remove the parentheses + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:104:13 + | +LL | let _ = await!(bar()); + | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:108:13 + | +LL | let _ = await!(bar())?; + | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:113:17 + | +LL | let _ = await!(bar())?; + | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:121:17 + | +LL | let _ = await!(bar())?; + | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` + +error: expected expression, found `=>` + --> $DIR/incorrect-syntax-suggestions.rs:129:25 + | +LL | match await { await => () } + | ----- ^^ expected expression + | | + | while parsing this incorrect await expression + +error: incorrect use of `await` + --> $DIR/incorrect-syntax-suggestions.rs:129:11 + | +LL | match await { await => () } + | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` + +error: expected one of `.`, `?`, `{`, or an operator, found `}` + --> $DIR/incorrect-syntax-suggestions.rs:132:1 + | +LL | match await { await => () } + | ----- - expected one of `.`, `?`, `{`, or an operator + | | + | while parsing this `match` expression +... +LL | } + | ^ unexpected token + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:52:13 + | +LL | fn foo9() -> Result<(), ()> { + | ---- this is not `async` +LL | let _ = await bar(); + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:57:13 + | +LL | fn foo10() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = await? bar(); + | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:66:14 + | +LL | fn foo12() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = (await bar())?; + | ^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:71:18 + | +LL | fn foo13() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await(); + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:76:18 + | +LL | fn foo14() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await()?; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:81:18 + | +LL | fn foo15() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:85:18 + | +LL | fn foo16() -> Result<(), ()> { + | ----- this is not `async` +LL | let _ = bar().await?; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:90:22 + | +LL | fn foo() -> Result<(), ()> { + | --- this is not `async` +LL | let _ = bar().await?; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:97:22 + | +LL | let foo = || { + | -- this is not `async` +LL | let _ = bar().await?; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:113:29 + | +LL | fn foo() -> Result<(), ()> { + | --- this is not `async` +LL | let _ = await!(bar())?; + | ^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/incorrect-syntax-suggestions.rs:121:29 + | +LL | let foo = || { + | -- this is not `async` +LL | let _ = await!(bar())?; + | ^ only allowed inside `async` functions and blocks + +error: aborting due to 33 previous errors + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/await-keyword/post_expansion_error.rs b/tests/ui/async-await/await-keyword/post_expansion_error.rs new file mode 100644 index 000000000..b4c899b0d --- /dev/null +++ b/tests/ui/async-await/await-keyword/post_expansion_error.rs @@ -0,0 +1,10 @@ +// edition:2018 + +macro_rules! r#await { + () => { println!("Hello, world!") } +} + +fn main() { + await!() + //~^ ERROR expected expression, found `)` +} diff --git a/tests/ui/async-await/await-keyword/post_expansion_error.stderr b/tests/ui/async-await/await-keyword/post_expansion_error.stderr new file mode 100644 index 000000000..0996c38b3 --- /dev/null +++ b/tests/ui/async-await/await-keyword/post_expansion_error.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `)` + --> $DIR/post_expansion_error.rs:8:12 + | +LL | await!() + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/async-await/await-sequence.rs b/tests/ui/async-await/await-sequence.rs new file mode 100644 index 000000000..726c4284e --- /dev/null +++ b/tests/ui/async-await/await-sequence.rs @@ -0,0 +1,21 @@ +// edition:2021 +// compile-flags: -Z drop-tracking +// build-pass + +use std::collections::HashMap; + +fn main() { + let _ = real_main(); +} + +async fn nop() {} + +async fn real_main() { + nop().await; + nop().await; + nop().await; + nop().await; + + let mut map: HashMap<(), ()> = HashMap::new(); + map.insert((), nop().await); +} diff --git a/tests/ui/async-await/await-unsize.rs b/tests/ui/async-await/await-unsize.rs new file mode 100644 index 000000000..aa09d4bdf --- /dev/null +++ b/tests/ui/async-await/await-unsize.rs @@ -0,0 +1,14 @@ +// Regression test for #62312 + +// check-pass +// edition:2018 + +async fn make_boxed_object() -> Box { + Box::new(()) as _ +} + +async fn await_object() { + let _ = make_boxed_object().await; +} + +fn main() {} diff --git a/tests/ui/async-await/bound-normalization.rs b/tests/ui/async-await/bound-normalization.rs new file mode 100644 index 000000000..5d260682f --- /dev/null +++ b/tests/ui/async-await/bound-normalization.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +// See issue 60414 + +trait Trait { + type Assoc; +} + +async fn foo>() -> T::Assoc { + () +} + +fn main() {} diff --git a/tests/ui/async-await/conditional-and-guaranteed-initialization.rs b/tests/ui/async-await/conditional-and-guaranteed-initialization.rs new file mode 100644 index 000000000..56f4cbbd1 --- /dev/null +++ b/tests/ui/async-await/conditional-and-guaranteed-initialization.rs @@ -0,0 +1,16 @@ +// check-pass +// edition:2018 +// compile-flags: --crate-type lib + +async fn conditional_and_guaranteed_initialization(x: usize) -> usize { + let y; + if x > 5 { + y = echo(10).await; + } else { + y = get_something().await; + } + y +} + +async fn echo(x: usize) -> usize { x } +async fn get_something() -> usize { 10 } diff --git a/tests/ui/async-await/default-struct-update.rs b/tests/ui/async-await/default-struct-update.rs new file mode 100644 index 000000000..64fb6280d --- /dev/null +++ b/tests/ui/async-await/default-struct-update.rs @@ -0,0 +1,22 @@ +// build-pass +// edition:2018 +// compile-flags: -Zdrop-tracking=y + +fn main() { + let _ = foo(); +} + +async fn from_config(_: Config) {} + +async fn foo() { + from_config(Config { + nickname: None, + ..Default::default() + }) + .await; +} + +#[derive(Default)] +struct Config { + nickname: Option>, +} diff --git a/tests/ui/async-await/dont-print-desugared-async.rs b/tests/ui/async-await/dont-print-desugared-async.rs new file mode 100644 index 000000000..68341a24c --- /dev/null +++ b/tests/ui/async-await/dont-print-desugared-async.rs @@ -0,0 +1,8 @@ +// Test that we don't show variables with from async fn desugaring + +// edition:2018 + +async fn async_fn(&ref mut s: &[i32]) {} +//~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] + +fn main() {} diff --git a/tests/ui/async-await/dont-print-desugared-async.stderr b/tests/ui/async-await/dont-print-desugared-async.stderr new file mode 100644 index 000000000..d80467c7f --- /dev/null +++ b/tests/ui/async-await/dont-print-desugared-async.stderr @@ -0,0 +1,9 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/dont-print-desugared-async.rs:5:20 + | +LL | async fn async_fn(&ref mut s: &[i32]) {} + | ^^^^^^^^^ cannot borrow as mutable through `&` reference + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs new file mode 100644 index 000000000..f2f87a908 --- /dev/null +++ b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.rs @@ -0,0 +1,24 @@ +// edition:2021 + +// Test that we do not suggest `.await` when it doesn't make sense. + +struct A; + +impl A { + fn test(&self) -> i32 { + 1 + } +} + +async fn foo() -> A { + A +} + +async fn async_main() { + let x: u32 = foo().test(); + //~^ ERROR no method named `test` found for opaque type `impl Future` in the current scope +} + +fn main() { + let _ = async_main(); +} diff --git a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr new file mode 100644 index 000000000..e65d9d0e5 --- /dev/null +++ b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `test` found for opaque type `impl Future` in the current scope + --> $DIR/dont-suggest-await-on-method-return-mismatch.rs:18:24 + | +LL | let x: u32 = foo().test(); + | ^^^^ method not found in `impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/async-await/dont-suggest-missing-await.rs b/tests/ui/async-await/dont-suggest-missing-await.rs new file mode 100644 index 000000000..a8e5b38ec --- /dev/null +++ b/tests/ui/async-await/dont-suggest-missing-await.rs @@ -0,0 +1,19 @@ +// edition:2018 + +// This test ensures we don't make the suggestion in bodies that aren't `async`. + +fn take_u32(x: u32) {} + +async fn make_u32() -> u32 { + 22 +} + +async fn dont_suggest_await_in_closure() { + || { + let x = make_u32(); + take_u32(x) + //~^ ERROR mismatched types [E0308] + }; +} + +fn main() {} diff --git a/tests/ui/async-await/dont-suggest-missing-await.stderr b/tests/ui/async-await/dont-suggest-missing-await.stderr new file mode 100644 index 000000000..627bf05bb --- /dev/null +++ b/tests/ui/async-await/dont-suggest-missing-await.stderr @@ -0,0 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-missing-await.rs:14:18 + | +LL | take_u32(x) + | -------- ^ expected `u32`, found opaque type + | | + | arguments to this function are incorrect + | +note: while checking the return type of the `async fn` + --> $DIR/dont-suggest-missing-await.rs:7:24 + | +LL | async fn make_u32() -> u32 { + | ^^^ checked the `Output` of this `async fn`, found opaque type + = note: expected type `u32` + found opaque type `impl Future` +note: function defined here + --> $DIR/dont-suggest-missing-await.rs:5:4 + | +LL | fn take_u32(x: u32) {} + | ^^^^^^^^ ------ +help: consider `await`ing on the `Future` + | +LL | take_u32(x.await) + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/drop-and-assign.rs b/tests/ui/async-await/drop-and-assign.rs new file mode 100644 index 000000000..fa3f33036 --- /dev/null +++ b/tests/ui/async-await/drop-and-assign.rs @@ -0,0 +1,19 @@ +// edition:2021 +// compile-flags: -Zdrop-tracking +// build-pass + +struct A; +impl Drop for A { fn drop(&mut self) {} } + +pub async fn f() { + let mut a = A; + a = A; + drop(a); + async {}.await; +} + +fn assert_send(_: T) {} + +fn main() { + let _ = f(); +} diff --git a/tests/ui/async-await/drop-order/auxiliary/arc_wake.rs b/tests/ui/async-await/drop-order/auxiliary/arc_wake.rs new file mode 100644 index 000000000..c21886f26 --- /dev/null +++ b/tests/ui/async-await/drop-order/auxiliary/arc_wake.rs @@ -0,0 +1,64 @@ +// edition:2018 + +use std::sync::Arc; +use std::task::{ + Waker, RawWaker, RawWakerVTable, +}; + +macro_rules! waker_vtable { + ($ty:ident) => { + &RawWakerVTable::new( + clone_arc_raw::<$ty>, + wake_arc_raw::<$ty>, + wake_by_ref_arc_raw::<$ty>, + drop_arc_raw::<$ty>, + ) + }; +} + +pub trait ArcWake { + fn wake(self: Arc); + + fn wake_by_ref(arc_self: &Arc) { + arc_self.clone().wake() + } + + fn into_waker(wake: Arc) -> Waker where Self: Sized + { + let ptr = Arc::into_raw(wake) as *const (); + + unsafe { + Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self))) + } + } +} + +unsafe fn increase_refcount(data: *const ()) { + // Retain Arc by creating a copy + let arc: Arc = Arc::from_raw(data as *const T); + let arc_clone = arc.clone(); + // Forget the Arcs again, so that the refcount isn't decrased + let _ = Arc::into_raw(arc); + let _ = Arc::into_raw(arc_clone); +} + +unsafe fn clone_arc_raw(data: *const ()) -> RawWaker { + increase_refcount::(data); + RawWaker::new(data, waker_vtable!(T)) +} + +unsafe fn drop_arc_raw(data: *const ()) { + // Drop Arc + let _: Arc = Arc::from_raw(data as *const T); +} + +unsafe fn wake_arc_raw(data: *const ()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake(arc); +} + +unsafe fn wake_by_ref_arc_raw(data: *const ()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake_by_ref(&arc); + let _ = Arc::into_raw(arc); +} diff --git a/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs new file mode 100644 index 000000000..9817d377a --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs @@ -0,0 +1,270 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +#![allow(unused_variables)] + +// Test that the drop order for parameters in a fn and async fn matches up. Also test that +// parameters (used or unused) are not dropped until the async fn completes execution. +// See also #54716. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::marker::PhantomData; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check that unused bindings are dropped after the function is polled. +async fn foo_async(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foo_sync(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns are dropped after the function is polled. +async fn bar_async(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn bar_sync(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns within more complex patterns are dropped after the function +/// is polled. +async fn baz_async((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn baz_sync((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore and unused bindings within and outwith more complex patterns are dropped +/// after the function is polled. +async fn foobar_async(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foobar_sync(ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +struct Foo; + +impl Foo { + /// Check that unused bindings are dropped after the method is polled. + async fn foo_async(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method is polled. + async fn bar_async(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// is polled. + async fn baz_async((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync((ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method is polled. + async fn foobar_async( + ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync( + ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +struct Bar<'a>(PhantomData<&'a ()>); + +impl<'a> Bar<'a> { + /// Check that unused bindings are dropped after the method with self is polled. + async fn foo_async(&'a self, ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(&'a self, ref mut x: D, ref mut _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method with self is polled. + async fn bar_async(&'a self, ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(&'a self, ref mut x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// with self is polled. + async fn baz_async(&'a self, (ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync(&'a self, (ref mut x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method with self is polled. + async fn foobar_async( + &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync( + &'a self, ref mut x: D, (ref mut a, _, ref mut _c): (D, D, D), _: D, ref mut _y: D, + ) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let _ = fut.as_mut().poll(&mut cx); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())), + |l| bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods w/out self (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())), + |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + Foo::foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + Foo::foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods (see doc comment on function for what it tests). + let b = Bar(Default::default()); + assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())), + |l| b.bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| b.baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + b.foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + b.foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); +} diff --git a/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs new file mode 100644 index 000000000..6c10ead36 --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs @@ -0,0 +1,265 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +#![allow(unused_variables)] + +// Test that the drop order for parameters in a fn and async fn matches up. Also test that +// parameters (used or unused) are not dropped until the async fn completes execution. +// See also #54716. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::marker::PhantomData; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check that unused bindings are dropped after the function is polled. +async fn foo_async(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foo_sync(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns are dropped after the function is polled. +async fn bar_async(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn bar_sync(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns within more complex patterns are dropped after the function +/// is polled. +async fn baz_async((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn baz_sync((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore and unused bindings within and outwith more complex patterns are dropped +/// after the function is polled. +async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +struct Foo; + +impl Foo { + /// Check that unused bindings are dropped after the method is polled. + async fn foo_async(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method is polled. + async fn bar_async(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// is polled. + async fn baz_async((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method is polled. + async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +struct Bar<'a>(PhantomData<&'a ()>); + +impl<'a> Bar<'a> { + /// Check that unused bindings are dropped after the method with self is polled. + async fn foo_async(&'a self, x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foo_sync(&'a self, x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method with self is polled. + async fn bar_async(&'a self, x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn bar_sync(&'a self, x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// with self is polled. + async fn baz_async(&'a self, (x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn baz_sync(&'a self, (x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method with self is polled. + async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let _ = fut.as_mut().poll(&mut cx); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| bar_async(D("x", l.clone()), D("_", l.clone())), + |l| bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods w/out self (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())), + |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + Foo::foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + Foo::foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods (see doc comment on function for what it tests). + let b = Bar(Default::default()); + assert_drop_order_after_poll(|l| b.foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone()))); + assert_drop_order_after_poll(|l| b.bar_async(D("x", l.clone()), D("_", l.clone())), + |l| b.bar_sync(D("x", l.clone()), D("_", l.clone()))); + assert_drop_order_after_poll(|l| b.baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| b.baz_sync((D("x", l.clone()), D("_", l.clone())))); + assert_drop_order_after_poll( + |l| { + b.foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + b.foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); +} diff --git a/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs b/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs new file mode 100644 index 000000000..15cc9fbc8 --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs @@ -0,0 +1,176 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +#![deny(dead_code)] +#![allow(unused_variables)] +#![allow(unused_must_use)] +#![allow(path_statements)] + +// Test that the drop order for locals in a fn and async fn matches up. +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::pin::Pin; +use std::rc::Rc; +use std::sync::Arc; +use std::task::{Context, Poll}; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +struct NeverReady; + +impl Future for NeverReady { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + Poll::Pending + } +} + +async fn simple_variable_declaration_async(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); + NeverReady.await; +} + +fn simple_variable_declaration_sync(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); +} + +async fn varable_completely_contained_within_block_async(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + async { + let x = D("x", l.clone()); + } + .await; + let y = D("y", l.clone()); + NeverReady.await; +} + +fn varable_completely_contained_within_block_sync(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + { + let x = D("x", l.clone()); + } + let y = D("y", l.clone()); +} + +async fn variables_moved_into_separate_blocks_async(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); + async move { x }.await; + async move { y }.await; + NeverReady.await; +} + +fn variables_moved_into_separate_blocks_sync(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); + { + x + }; + { + y + }; +} + +async fn variables_moved_into_same_block_async(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); + async move { + x; + y; + }; + NeverReady.await; +} + +fn variables_moved_into_same_block_sync(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); + { + x; + y; + }; + return; +} + +async fn move_after_current_await_doesnt_affect_order(l: DropOrderListPtr) { + l.borrow_mut().push(DropOrder::Function); + let x = D("x", l.clone()); + let y = D("y", l.clone()); + NeverReady.await; + async move { + x; + y; + }; +} + +fn assert_drop_order_after_cancel>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let _ = fut.as_mut().poll(&mut cx); + drop(fut); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + assert_drop_order_after_cancel( + simple_variable_declaration_async, + simple_variable_declaration_sync, + ); + assert_drop_order_after_cancel( + varable_completely_contained_within_block_async, + varable_completely_contained_within_block_sync, + ); + assert_drop_order_after_cancel( + variables_moved_into_separate_blocks_async, + variables_moved_into_separate_blocks_sync, + ); + assert_drop_order_after_cancel( + variables_moved_into_same_block_async, + variables_moved_into_same_block_sync, + ); + assert_drop_order_after_cancel( + move_after_current_await_doesnt_affect_order, + simple_variable_declaration_sync, + ); +} diff --git a/tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs new file mode 100644 index 000000000..edfecb910 --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs @@ -0,0 +1,98 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +#![allow(unused_variables)] + +// Test the drop order for parameters relative to local variables and +// temporaries created in the tail return expression of the function +// body. In particular, check that this drop order is the same between +// an `async fn` and an ordinary `fn`. See #64512. + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::sync::Arc; +use std::rc::Rc; +use std::task::Context; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +/// Check drop order of temporary "temp" as compared to `x`, `y`, and `z`. +/// +/// Expected order: +/// - `z` +/// - temp +/// - `y` +/// - `x` +async fn foo_async(x: D, _y: D) { + let l = x.1.clone(); + let z = D("z", l.clone()); + l.borrow_mut().push(DropOrder::Function); + helper_async(&D("temp", l)).await +} + +async fn helper_async(v: &D) { } + +fn foo_sync(x: D, _y: D) { + let l = x.1.clone(); + let z = D("z", l.clone()); + l.borrow_mut().push(DropOrder::Function); + helper_sync(&D("temp", l)) +} + +fn helper_sync(v: &D) { } + +fn assert_drop_order_after_poll>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let r = fut.as_mut().poll(&mut cx); + + assert!(match r { + std::task::Poll::Ready(()) => true, + _ => false, + }); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_poll(|l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone()))); +} diff --git a/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs new file mode 100644 index 000000000..79dedb1ba --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.rs @@ -0,0 +1,13 @@ +// edition:2018 + +async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) { + assert_eq!(__arg1, (1, 2, 3)); //~ ERROR cannot find value `__arg1` in this scope [E0425] + assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425] +} + +async fn baz_async(ref mut x: u32, ref y: u32) { + assert_eq!(__arg0, 1); //~ ERROR cannot find value `__arg0` in this scope [E0425] + assert_eq!(__arg1, 2); //~ ERROR cannot find value `__arg1` in this scope [E0425] +} + +fn main() {} diff --git a/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr new file mode 100644 index 000000000..aa04a613f --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `__arg1` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:4:16 + | +LL | assert_eq!(__arg1, (1, 2, 3)); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `__arg2` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:5:16 + | +LL | assert_eq!(__arg2, 4); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `__arg0` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:9:16 + | +LL | assert_eq!(__arg0, 1); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `__arg1` in this scope + --> $DIR/drop-order-locals-are-hidden.rs:10:16 + | +LL | assert_eq!(__arg1, 2); + | ^^^^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/async-await/drop-order/drop-order-when-cancelled.rs b/tests/ui/async-await/drop-order/drop-order-when-cancelled.rs new file mode 100644 index 000000000..cfd68bc0d --- /dev/null +++ b/tests/ui/async-await/drop-order/drop-order-when-cancelled.rs @@ -0,0 +1,309 @@ +// aux-build:arc_wake.rs +// edition:2018 +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +// Test that the drop order for parameters in a fn and async fn matches up. Also test that +// parameters (used or unused) are not dropped until the async fn is cancelled. +// This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs + +#![allow(unused_variables)] + +extern crate arc_wake; + +use arc_wake::ArcWake; +use std::cell::RefCell; +use std::future::Future; +use std::marker::PhantomData; +use std::pin::Pin; +use std::rc::Rc; +use std::sync::Arc; +use std::task::{Context, Poll}; + +struct EmptyWaker; + +impl ArcWake for EmptyWaker { + fn wake(self: Arc) {} +} + +#[derive(Debug, Eq, PartialEq)] +enum DropOrder { + Function, + Val(&'static str), +} + +type DropOrderListPtr = Rc>>; + +struct D(&'static str, DropOrderListPtr); + +impl Drop for D { + fn drop(&mut self) { + self.1.borrow_mut().push(DropOrder::Val(self.0)); + } +} + +struct NeverReady; + +impl Future for NeverReady { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + Poll::Pending + } +} + +/// Check that unused bindings are dropped after the function is polled. +async fn foo_async(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; +} + +fn foo_sync(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns are dropped after the function is polled. +async fn bar_async(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; +} + +fn bar_sync(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore patterns within more complex patterns are dropped after the function +/// is polled. +async fn baz_async((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; +} + +fn baz_sync((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); +} + +/// Check that underscore and unused bindings within and outwith more complex patterns are dropped +/// after the function is polled. +async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; +} + +fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); +} + +struct Foo; + +impl Foo { + /// Check that unused bindings are dropped after the method is polled. + async fn foo_async(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn foo_sync(x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method is polled. + async fn bar_async(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn bar_sync(x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// is polled. + async fn baz_async((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn baz_sync((x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method is polled. + async fn foobar_async(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn foobar_sync(x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +struct Bar<'a>(PhantomData<&'a ()>); + +impl<'a> Bar<'a> { + /// Check that unused bindings are dropped after the method with self is polled. + async fn foo_async(&'a self, x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn foo_sync(&'a self, x: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns are dropped after the method with self is polled. + async fn bar_async(&'a self, x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn bar_sync(&'a self, x: D, _: D) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore patterns within more complex patterns are dropped after the method + /// with self is polled. + async fn baz_async(&'a self, (x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn baz_sync(&'a self, (x, _): (D, D)) { + x.1.borrow_mut().push(DropOrder::Function); + } + + /// Check that underscore and unused bindings within and outwith more complex patterns are + /// dropped after the method with self is polled. + async fn foobar_async(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + NeverReady.await; + } + + fn foobar_sync(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) { + x.1.borrow_mut().push(DropOrder::Function); + } +} + +fn assert_drop_order_after_cancel>( + f: impl FnOnce(DropOrderListPtr) -> Fut, + g: impl FnOnce(DropOrderListPtr), +) { + let empty = Arc::new(EmptyWaker); + let waker = ArcWake::into_waker(empty); + let mut cx = Context::from_waker(&waker); + + let actual_order = Rc::new(RefCell::new(Vec::new())); + let mut fut = Box::pin(f(actual_order.clone())); + let _ = fut.as_mut().poll(&mut cx); + + // Parameters are never dropped until the future completes. + assert_eq!(*actual_order.borrow(), vec![DropOrder::Function]); + + drop(fut); + + let expected_order = Rc::new(RefCell::new(Vec::new())); + g(expected_order.clone()); + assert_eq!(*actual_order.borrow(), *expected_order.borrow()); +} + +fn main() { + // Free functions (see doc comment on function for what it tests). + assert_drop_order_after_cancel( + |l| foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| foo_sync(D("x", l.clone()), D("_y", l.clone())), + ); + assert_drop_order_after_cancel( + |l| bar_async(D("x", l.clone()), D("_", l.clone())), + |l| bar_sync(D("x", l.clone()), D("_", l.clone())), + ); + assert_drop_order_after_cancel( + |l| baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| baz_sync((D("x", l.clone()), D("_", l.clone()))), + ); + assert_drop_order_after_cancel( + |l| { + foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods w/out self (see doc comment on function for what it tests). + assert_drop_order_after_cancel( + |l| Foo::foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| Foo::foo_sync(D("x", l.clone()), D("_y", l.clone())), + ); + assert_drop_order_after_cancel( + |l| Foo::bar_async(D("x", l.clone()), D("_", l.clone())), + |l| Foo::bar_sync(D("x", l.clone()), D("_", l.clone())), + ); + assert_drop_order_after_cancel( + |l| Foo::baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| Foo::baz_sync((D("x", l.clone()), D("_", l.clone()))), + ); + assert_drop_order_after_cancel( + |l| { + Foo::foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + Foo::foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); + + // Methods (see doc comment on function for what it tests). + let b = Bar(Default::default()); + assert_drop_order_after_cancel( + |l| b.foo_async(D("x", l.clone()), D("_y", l.clone())), + |l| b.foo_sync(D("x", l.clone()), D("_y", l.clone())), + ); + assert_drop_order_after_cancel( + |l| b.bar_async(D("x", l.clone()), D("_", l.clone())), + |l| b.bar_sync(D("x", l.clone()), D("_", l.clone())), + ); + assert_drop_order_after_cancel( + |l| b.baz_async((D("x", l.clone()), D("_", l.clone()))), + |l| b.baz_sync((D("x", l.clone()), D("_", l.clone()))), + ); + assert_drop_order_after_cancel( + |l| { + b.foobar_async( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + |l| { + b.foobar_sync( + D("x", l.clone()), + (D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())), + D("_", l.clone()), + D("_y", l.clone()), + ) + }, + ); +} diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.rs b/tests/ui/async-await/drop-track-bad-field-in-fru.rs new file mode 100644 index 000000000..28ad77675 --- /dev/null +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zdrop-tracking +// edition: 2021 + +fn main() {} + +async fn foo() { + None { value: (), ..Default::default() }.await; + //~^ ERROR `Option<_>` is not a future + //~| ERROR variant `Option<_>::None` has no field named `value` +} diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr new file mode 100644 index 000000000..819b64ad7 --- /dev/null +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr @@ -0,0 +1,23 @@ +error[E0559]: variant `Option<_>::None` has no field named `value` + --> $DIR/drop-track-bad-field-in-fru.rs:7:12 + | +LL | None { value: (), ..Default::default() }.await; + | ^^^^^ `Option<_>::None` does not have this field + +error[E0277]: `Option<_>` is not a future + --> $DIR/drop-track-bad-field-in-fru.rs:7:45 + | +LL | None { value: (), ..Default::default() }.await; + | ^^^^^^ + | | + | `Option<_>` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for `Option<_>` + = note: Option<_> must be a future or must implement `IntoFuture` to be awaited + = note: required for `Option<_>` to implement `IntoFuture` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0559. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.rs b/tests/ui/async-await/drop-track-field-assign-nonsend.rs new file mode 100644 index 000000000..b6c0fda15 --- /dev/null +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.rs @@ -0,0 +1,45 @@ +// Derived from an ICE found in tokio-xmpp during a crater run. +// edition:2021 +// compile-flags: -Zdrop-tracking + +#![allow(dead_code)] + +#[derive(Clone)] +struct InfoResult { + node: Option> +} + +struct Agent { + info_result: InfoResult +} + +impl Agent { + async fn handle(&mut self) { + let mut info = self.info_result.clone(); + info.node = None; + let element = parse_info(info); + let _ = send_element(element).await; + } +} + +struct Element { +} + +async fn send_element(_: Element) {} + +fn parse(_: &[u8]) -> Result<(), ()> { + Ok(()) +} + +fn parse_info(_: InfoResult) -> Element { + Element { } +} + +fn assert_send(_: T) {} + +fn main() { + let agent = Agent { info_result: InfoResult { node: None } }; + // FIXME: It would be nice for this to work. See #94067. + assert_send(agent.handle()); + //~^ cannot be sent between threads safely +} diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr new file mode 100644 index 000000000..d95483c81 --- /dev/null +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr @@ -0,0 +1,25 @@ +error: future cannot be sent between threads safely + --> $DIR/drop-track-field-assign-nonsend.rs:43:17 + | +LL | assert_send(agent.handle()); + | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Rc` +note: future is not `Send` as this value is used across an await + --> $DIR/drop-track-field-assign-nonsend.rs:21:38 + | +LL | let mut info = self.info_result.clone(); + | -------- has type `InfoResult` which is not `Send` +... +LL | let _ = send_element(element).await; + | ^^^^^^ await occurs here, with `mut info` maybe used later +LL | } + | - `mut info` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/drop-track-field-assign-nonsend.rs:38:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/drop-track-field-assign.rs b/tests/ui/async-await/drop-track-field-assign.rs new file mode 100644 index 000000000..3a393cd16 --- /dev/null +++ b/tests/ui/async-await/drop-track-field-assign.rs @@ -0,0 +1,44 @@ +// Derived from an ICE found in tokio-xmpp during a crater run. +// edition:2021 +// compile-flags: -Zdrop-tracking +// build-pass + +#![allow(dead_code)] + +#[derive(Clone)] +struct InfoResult { + node: Option +} + +struct Agent { + info_result: InfoResult +} + +impl Agent { + async fn handle(&mut self) { + let mut info = self.info_result.clone(); + info.node = Some("bar".into()); + let element = parse_info(info); + let _ = send_element(element).await; + } +} + +struct Element { +} + +async fn send_element(_: Element) {} + +fn parse(_: &[u8]) -> Result<(), ()> { + Ok(()) +} + +fn parse_info(_: InfoResult) -> Element { + Element { } +} + +fn main() { + let mut agent = Agent { + info_result: InfoResult { node: None } + }; + let _ = agent.handle(); +} diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs new file mode 100644 index 000000000..7f7294295 --- /dev/null +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.rs @@ -0,0 +1,106 @@ +// compile-flags: -Zdrop-tracking +// incremental +// edition: 2021 + +use std::future::*; +use std::marker::PhantomData; +use std::pin::Pin; +use std::task::*; + +fn send(_: T) {} + +pub trait Stream { + type Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; +} + +struct Empty(PhantomData T>); + +impl Stream for Empty { + type Item = T; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } +} + +pub trait FnOnce1 { + type Output; + fn call_once(self, arg: A) -> Self::Output; +} + +impl FnOnce1 for T +where + T: FnOnce(A) -> R, +{ + type Output = R; + fn call_once(self, arg: A) -> R { + self(arg) + } +} + +pub trait FnMut1: FnOnce1 { + fn call_mut(&mut self, arg: A) -> Self::Output; +} + +impl FnMut1 for T +where + T: FnMut(A) -> R, +{ + fn call_mut(&mut self, arg: A) -> R { + self(arg) + } +} + +struct Map(St, F); + +impl Stream for Map +where + St: Stream, + F: FnMut1, +{ + type Item = F::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } +} + +struct FuturesOrdered(PhantomData T::Output>); + +pub struct Buffered(St, FuturesOrdered, usize) +where + St::Item: Future; + +impl Stream for Buffered +where + St: Stream, + St::Item: Future, +{ + type Item = ::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + todo!() + } +} + +struct Next<'a, T: ?Sized>(&'a T); + +impl Future for Next<'_, St> { + type Output = Option; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + todo!() + } +} + +fn main() { + send(async { + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await + }); +} diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr new file mode 100644 index 000000000..aa9a22e9e --- /dev/null +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.stderr @@ -0,0 +1,62 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.rs b/tests/ui/async-await/edition-deny-async-fns-2015.rs new file mode 100644 index 000000000..6bd6d879a --- /dev/null +++ b/tests/ui/async-await/edition-deny-async-fns-2015.rs @@ -0,0 +1,38 @@ +// edition:2015 + +async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 + +fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in Rust 2015 + +async fn async_baz() { //~ ERROR `async fn` is not permitted in Rust 2015 + async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015 +} + +struct Foo {} + +impl Foo { + async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 +} + +trait Bar { + async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 + //~^ ERROR functions in traits cannot be declared `async` +} + +fn main() { + macro_rules! accept_item { ($x:item) => {} } + + accept_item! { + async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015 + } + + accept_item! { + impl Foo { + async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015 + } + } + + let inside_closure = || { + async fn bar() {} //~ ERROR `async fn` is not permitted in Rust 2015 + }; +} diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.stderr new file mode 100644 index 000000000..ba918eb28 --- /dev/null +++ b/tests/ui/async-await/edition-deny-async-fns-2015.stderr @@ -0,0 +1,98 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:3:1 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:5:12 + | +LL | fn baz() { async fn foo() {} } + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:7:1 + | +LL | async fn async_baz() { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:8:5 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:14:5 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:18:5 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:36:9 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:26:9 + | +LL | async fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/edition-deny-async-fns-2015.rs:31:13 + | +LL | async fn bar() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/edition-deny-async-fns-2015.rs:18:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0670, E0706. +For more information about an error, try `rustc --explain E0670`. diff --git a/tests/ui/async-await/expansion-in-attrs.rs b/tests/ui/async-await/expansion-in-attrs.rs new file mode 100644 index 000000000..af77c3463 --- /dev/null +++ b/tests/ui/async-await/expansion-in-attrs.rs @@ -0,0 +1,13 @@ +// check-pass +// edition:2018 + +macro_rules! with_doc { + ($doc: expr) => { + #[doc = $doc] + async fn f() {} + }; +} + +with_doc!(concat!("")); + +fn main() {} diff --git a/tests/ui/async-await/feature-async-closure.rs b/tests/ui/async-await/feature-async-closure.rs new file mode 100644 index 000000000..d07116b13 --- /dev/null +++ b/tests/ui/async-await/feature-async-closure.rs @@ -0,0 +1,8 @@ +// edition:2018 +// gate-test-async_closure + +fn f() { + let _ = async || {}; //~ ERROR async closures are unstable +} + +fn main() {} diff --git a/tests/ui/async-await/feature-async-closure.stderr b/tests/ui/async-await/feature-async-closure.stderr new file mode 100644 index 000000000..485a838b6 --- /dev/null +++ b/tests/ui/async-await/feature-async-closure.stderr @@ -0,0 +1,13 @@ +error[E0658]: async closures are unstable + --> $DIR/feature-async-closure.rs:5:13 + | +LL | let _ = async || {}; + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: to use an async block, remove the `||`: `async {` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/feature-gate-async_fn_in_trait.rs b/tests/ui/async-await/feature-gate-async_fn_in_trait.rs new file mode 100644 index 000000000..792f378cb --- /dev/null +++ b/tests/ui/async-await/feature-gate-async_fn_in_trait.rs @@ -0,0 +1,25 @@ +// edition:2021 + +// RPITIT is not enough to allow use of async functions +#![allow(incomplete_features)] +#![feature(return_position_impl_trait_in_trait)] + +trait T { + async fn foo(); //~ ERROR functions in traits cannot be declared `async` +} + +// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also +// feature-gate-return_position_impl_trait_in_trait.rs) +trait T2 { + async fn foo() -> impl Sized; //~ ERROR functions in traits cannot be declared `async` +} + +trait T3 { + fn foo() -> impl std::future::Future; +} + +impl T3 for () { + async fn foo() {} //~ ERROR functions in traits cannot be declared `async` +} + +fn main() {} diff --git a/tests/ui/async-await/feature-gate-async_fn_in_trait.stderr b/tests/ui/async-await/feature-gate-async_fn_in_trait.stderr new file mode 100644 index 000000000..2a5fbd1ec --- /dev/null +++ b/tests/ui/async-await/feature-gate-async_fn_in_trait.stderr @@ -0,0 +1,42 @@ +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/feature-gate-async_fn_in_trait.rs:8:5 + | +LL | async fn foo(); + | -----^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/feature-gate-async_fn_in_trait.rs:14:5 + | +LL | async fn foo() -> impl Sized; + | -----^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/feature-gate-async_fn_in_trait.rs:22:5 + | +LL | async fn foo() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0706`. diff --git a/tests/ui/async-await/feature-self-return-type.rs b/tests/ui/async-await/feature-self-return-type.rs new file mode 100644 index 000000000..41f887430 --- /dev/null +++ b/tests/ui/async-await/feature-self-return-type.rs @@ -0,0 +1,28 @@ +// edition:2018 +#![feature(impl_trait_projections)] + +// This test checks that we emit the correct borrowck error when `Self` is used as a return type. +// See #61949 for context. + +pub struct Foo<'a> { + pub bar: &'a i32, +} + +impl<'a> Foo<'a> { + pub async fn new(_bar: &'a i32) -> Self { + Foo { + bar: &22 + } + } +} + +pub async fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).await + //~^ ERROR `bar` does not live long enough + }; + drop(x); +} + +fn main() { } diff --git a/tests/ui/async-await/feature-self-return-type.stderr b/tests/ui/async-await/feature-self-return-type.stderr new file mode 100644 index 000000000..892468368 --- /dev/null +++ b/tests/ui/async-await/feature-self-return-type.stderr @@ -0,0 +1,15 @@ +error[E0597]: `bar` does not live long enough + --> $DIR/feature-self-return-type.rs:22:18 + | +LL | let x = { + | - borrow later stored here +LL | let bar = 22; +LL | Foo::new(&bar).await + | ^^^^ borrowed value does not live long enough +LL | +LL | }; + | - `bar` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/futures-api.rs b/tests/ui/async-await/futures-api.rs new file mode 100644 index 000000000..a7da058de --- /dev/null +++ b/tests/ui/async-await/futures-api.rs @@ -0,0 +1,61 @@ +// run-pass + +// aux-build:arc_wake.rs + +extern crate arc_wake; + +use std::future::Future; +use std::pin::Pin; +use std::sync::{ + Arc, + atomic::{self, AtomicUsize}, +}; +use std::task::{ + Context, Poll, +}; +use arc_wake::ArcWake; + +struct Counter { + wakes: AtomicUsize, +} + +impl ArcWake for Counter { + fn wake(self: Arc) { + Self::wake_by_ref(&self) + } + fn wake_by_ref(arc_self: &Arc) { + arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst); + } +} + +struct MyFuture; + +impl Future for MyFuture { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // Wake twice + let waker = cx.waker(); + waker.wake_by_ref(); + waker.wake_by_ref(); + Poll::Ready(()) + } +} + +fn test_waker() { + let counter = Arc::new(Counter { + wakes: AtomicUsize::new(0), + }); + let waker = ArcWake::into_waker(counter.clone()); + assert_eq!(2, Arc::strong_count(&counter)); + { + let mut context = Context::from_waker(&waker); + assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(&mut context)); + assert_eq!(2, counter.wakes.load(atomic::Ordering::SeqCst)); + } + drop(waker); + assert_eq!(1, Arc::strong_count(&counter)); +} + +fn main() { + test_waker(); +} diff --git a/tests/ui/async-await/generator-desc.rs b/tests/ui/async-await/generator-desc.rs new file mode 100644 index 000000000..500812016 --- /dev/null +++ b/tests/ui/async-await/generator-desc.rs @@ -0,0 +1,16 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +async fn one() {} +async fn two() {} + +fn fun>(f1: F, f2: F) {} +fn main() { + fun(async {}, async {}); + //~^ ERROR mismatched types + fun(one(), two()); + //~^ ERROR mismatched types + fun((async || {})(), (async || {})()); + //~^ ERROR mismatched types +} diff --git a/tests/ui/async-await/generator-desc.stderr b/tests/ui/async-await/generator-desc.stderr new file mode 100644 index 000000000..963c6ba57 --- /dev/null +++ b/tests/ui/async-await/generator-desc.stderr @@ -0,0 +1,63 @@ +error[E0308]: mismatched types + --> $DIR/generator-desc.rs:10:19 + | +LL | fun(async {}, async {}); + | -------- ^^^^^^^^ + | | | + | | expected `async` block, found a different `async` block + | | arguments to this function are incorrect + | the expected `async` block + | + = note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]` + found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]` +note: function defined here + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/generator-desc.rs:12:16 + | +LL | fun(one(), two()); + | --- ^^^^^ expected opaque type, found a different opaque type + | | + | arguments to this function are incorrect + | +note: while checking the return type of the `async fn` + --> $DIR/generator-desc.rs:5:16 + | +LL | async fn one() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/generator-desc.rs:6:16 + | +LL | async fn two() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) + found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) + = help: consider `await`ing on both `Future`s + = note: distinct uses of `impl Trait` result in different opaque types +note: function defined here + --> $DIR/generator-desc.rs:8:4 + | +LL | fn fun>(f1: F, f2: F) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/generator-desc.rs:14:26 + | +LL | fun((async || {})(), (async || {})()); + | --- -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body + | | | + | | the expected `async` closure body + | arguments to this function are incorrect + | + = note: expected `async` closure body `[async closure body@$DIR/generator-desc.rs:14:19: 14:21]` + found `async` closure body `[async closure body@$DIR/generator-desc.rs:14:36: 14:38]` +note: function defined here + --> $DIR/generator-desc.rs:8:4 + | +LL | fn fun>(f1: F, f2: F) {} + | ^^^ ----- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/generator-not-future.rs b/tests/ui/async-await/generator-not-future.rs new file mode 100644 index 000000000..37d7cfa6f --- /dev/null +++ b/tests/ui/async-await/generator-not-future.rs @@ -0,0 +1,45 @@ +// edition:2018 +#![feature(generators, generator_trait)] + +use std::future::Future; +use std::ops::Generator; + +async fn async_fn() {} +fn returns_async_block() -> impl Future { + async {} +} +fn returns_generator() -> impl Generator<(), Yield = (), Return = ()> { + || { + let _: () = yield (); + } +} + +fn takes_future(_f: impl Future) {} +fn takes_generator(_g: impl Generator) {} + +fn main() { + // okay: + takes_future(async_fn()); + takes_future(returns_async_block()); + takes_future(async {}); + takes_generator(returns_generator()); + takes_generator(|| { + let _: () = yield (); + }); + + // async futures are not generators: + takes_generator(async_fn()); + //~^ ERROR the trait bound + takes_generator(returns_async_block()); + //~^ ERROR the trait bound + takes_generator(async {}); + //~^ ERROR the trait bound + + // generators are not futures: + takes_future(returns_generator()); + //~^ ERROR is not a future + takes_future(|ctx| { + //~^ ERROR is not a future + ctx = yield (); + }); +} diff --git a/tests/ui/async-await/generator-not-future.stderr b/tests/ui/async-await/generator-not-future.stderr new file mode 100644 index 000000000..1b81b461f --- /dev/null +++ b/tests/ui/async-await/generator-not-future.stderr @@ -0,0 +1,81 @@ +error[E0277]: the trait bound `impl Future: Generator<_>` is not satisfied + --> $DIR/generator-not-future.rs:31:21 + | +LL | takes_generator(async_fn()); + | --------------- ^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes_generator` + --> $DIR/generator-not-future.rs:18:39 + | +LL | fn takes_generator(_g: impl Generator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator` + +error[E0277]: the trait bound `impl Future: Generator<_>` is not satisfied + --> $DIR/generator-not-future.rs:33:21 + | +LL | takes_generator(returns_async_block()); + | --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Generator<_>` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes_generator` + --> $DIR/generator-not-future.rs:18:39 + | +LL | fn takes_generator(_g: impl Generator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator` + +error[E0277]: the trait bound `[async block@$DIR/generator-not-future.rs:35:21: 35:29]: Generator<_>` is not satisfied + --> $DIR/generator-not-future.rs:35:21 + | +LL | takes_generator(async {}); + | --------------- ^^^^^^^^ the trait `Generator<_>` is not implemented for `[async block@$DIR/generator-not-future.rs:35:21: 35:29]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes_generator` + --> $DIR/generator-not-future.rs:18:39 + | +LL | fn takes_generator(_g: impl Generator) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_generator` + +error[E0277]: `impl Generator` is not a future + --> $DIR/generator-not-future.rs:39:18 + | +LL | takes_future(returns_generator()); + | ------------ ^^^^^^^^^^^^^^^^^^^ `impl Generator` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `impl Generator` + = note: impl Generator must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `takes_future` + --> $DIR/generator-not-future.rs:17:26 + | +LL | fn takes_future(_f: impl Future) {} + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` + +error[E0277]: `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future + --> $DIR/generator-not-future.rs:41:18 + | +LL | takes_future(|ctx| { + | _____------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | ctx = yield (); +LL | | }); + | |_____^ `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` is not a future + | + = help: the trait `Future` is not implemented for `[generator@$DIR/generator-not-future.rs:41:18: 41:23]` + = note: [generator@$DIR/generator-not-future.rs:41:18: 41:23] must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `takes_future` + --> $DIR/generator-not-future.rs:17:26 + | +LL | fn takes_future(_f: impl Future) {} + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/generics-and-bounds.rs b/tests/ui/async-await/generics-and-bounds.rs new file mode 100644 index 000000000..963b19b34 --- /dev/null +++ b/tests/ui/async-await/generics-and-bounds.rs @@ -0,0 +1,88 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 +// compile-flags: --crate-type lib + +use std::future::Future; + +pub async fn simple_generic() {} + +pub trait Foo { + fn foo(&self) {} +} + +struct FooType; +impl Foo for FooType {} + +pub async fn call_generic_bound(f: F) { + f.foo() +} + +pub async fn call_where_clause(f: F) +where + F: Foo, +{ + f.foo() +} + +pub async fn call_impl_trait(f: impl Foo) { + f.foo() +} + +pub async fn call_with_ref(f: &impl Foo) { + f.foo() +} + +pub fn async_fn_with_same_generic_params_unifies() { + let mut a = call_generic_bound(FooType); + a = call_generic_bound(FooType); + + let mut b = call_where_clause(FooType); + b = call_where_clause(FooType); + + let mut c = call_impl_trait(FooType); + c = call_impl_trait(FooType); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref(&f_one); + d = call_with_ref(&f_two); +} + +pub fn simple_generic_block() -> impl Future { + async move {} +} + +pub fn call_generic_bound_block(f: F) -> impl Future { + async move { f.foo() } +} + +pub fn call_where_clause_block(f: F) -> impl Future +where + F: Foo, +{ + async move { f.foo() } +} + +pub fn call_impl_trait_block(f: impl Foo) -> impl Future { + async move { f.foo() } +} + +pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future + 'a { + async move { f.foo() } +} + +pub fn async_block_with_same_generic_params_unifies() { + let mut a = call_generic_bound_block(FooType); + a = call_generic_bound_block(FooType); + + let mut b = call_where_clause_block(FooType); + b = call_where_clause_block(FooType); + + let mut c = call_impl_trait_block(FooType); + c = call_impl_trait_block(FooType); + + let f_one = FooType; + let f_two = FooType; + let mut d = call_with_ref_block(&f_one); + d = call_with_ref_block(&f_two); +} diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs new file mode 100644 index 000000000..974f5aaff --- /dev/null +++ b/tests/ui/async-await/in-trait/async-associated-types.rs @@ -0,0 +1,24 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(impl_trait_projections)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b { + type MyAssoc; + + async fn foo(&'a self, key: &'b T) -> Self::MyAssoc; +} + +impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U { + type MyAssoc = (&'a U, &'b T); + + async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + (self, key) + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-associated-types2.rs b/tests/ui/async-await/in-trait/async-associated-types2.rs new file mode 100644 index 000000000..e546a0579 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-associated-types2.rs @@ -0,0 +1,30 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + type Fut<'a>: Future + where + Self: 'a; + + fn foo<'a>(&'a self) -> Self::Fut<'a>; +} + +impl MyTrait for i32 { + type Fut<'a> = impl Future + 'a + where + Self: 'a; + + fn foo<'a>(&'a self) -> Self::Fut<'a> { + async { + *self + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs new file mode 100644 index 000000000..38ba29718 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::pin::Pin; + +trait MyTrait { + fn foo(&self) -> Pin + '_>>; +} + +impl MyTrait for i32 { + async fn foo(&self) -> i32 { + //~^ ERROR method `foo` has an incompatible type for trait + *self + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr new file mode 100644 index 000000000..13e722255 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -0,0 +1,17 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28 + | +LL | async fn foo(&self) -> i32 { + | ^^^ expected struct `Pin`, found opaque type + | +note: type in trait + --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22 + | +LL | fn foo(&self) -> Pin + '_>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn(&i32) -> Pin>>` + found signature `fn(&i32) -> impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs new file mode 100644 index 000000000..1b1b3cffd --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::pin::Pin; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> Pin + '_>> { + //~^ ERROR method `foo` should be async + Box::pin(async { *self }) + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr new file mode 100644 index 000000000..60fa534a6 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/async-example-desugared-boxed.rs:15:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> Pin + '_>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs new file mode 100644 index 000000000..81e1e59a3 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -0,0 +1,37 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::pin::Pin; +use std::task::Poll; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +#[derive(Clone)] +struct MyFuture(i32); + +impl Future for MyFuture { + type Output = i32; + fn poll( + self: Pin<&mut Self>, + _: &mut std::task::Context<'_>, + ) -> Poll<::Output> { + Poll::Ready(self.0) + } +} + +impl MyTrait for i32 { + // FIXME: this should eventually require `#[refine]` to compile, because it also provides + // `Clone`. + fn foo(&self) -> impl Future + Clone { + MyFuture(*self) + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs new file mode 100644 index 000000000..feeda719e --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs @@ -0,0 +1,21 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + fn foo(&self) -> impl Future + '_; +} + +impl MyTrait for i32 { + // This will break once a PR that implements #102745 is merged + async fn foo(&self) -> i32 { + *self + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs new file mode 100644 index 000000000..71473e745 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -0,0 +1,29 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::task::Poll; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +struct MyFuture; +impl Future for MyFuture { + type Output = i32; + fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll { + Poll::Ready(0) + } +} + +impl MyTrait for u32 { + fn foo(&self) -> MyFuture { + //~^ ERROR method `foo` should be async + MyFuture + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr new file mode 100644 index 000000000..567a36a86 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/async-example-desugared-manual.rs:23:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> MyFuture { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs new file mode 100644 index 000000000..fb92ec786 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example-desugared.rs @@ -0,0 +1,20 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> impl Future + '_ { + async { *self } + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs new file mode 100644 index 000000000..abf94ef74 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-example.rs @@ -0,0 +1,32 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo(&self) -> i32; + async fn bar(&self) -> i32; +} + +impl MyTrait for i32 { + async fn foo(&self) -> i32 { + *self + } + + async fn bar(&self) -> i32 { + self.foo().await + } +} + +fn main() { + let x = 5; + // Calling from non-async context + let _ = x.foo(); + let _ = x.bar(); + // Calling from async block in non-async context + async { + let _: i32 = x.foo().await; + let _: i32 = x.bar().await; + }; +} diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs new file mode 100644 index 000000000..a73d55adf --- /dev/null +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs @@ -0,0 +1,21 @@ +// check-fail +// known-bug: #102682 +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; +use std::hash::Hash; + +trait MyTrait { + async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; +} + +impl MyTrait for (T, U) { + async fn foo(&self) -> &(T, U) { + self + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr new file mode 100644 index 000000000..f1f0d7e59 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr @@ -0,0 +1,37 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics-and-bounds.rs:12:18 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics-and-bounds.rs:12:18 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics-and-bounds.rs:12:28 + | +LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs new file mode 100644 index 000000000..67000e577 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-generics.rs @@ -0,0 +1,18 @@ +// check-fail +// known-bug: #102682 +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo(&self) -> &(T, U); +} + +impl MyTrait for (T, U) { + async fn foo(&self) -> &(T, U) { + self + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr new file mode 100644 index 000000000..2f0556456 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-generics.stderr @@ -0,0 +1,37 @@ +error[E0311]: the parameter type `U` may not live long enough + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + | +note: the parameter type `U` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics.rs:9:18 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/async-generics.rs:9:18 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^ +note: ...so that the reference type `&(T, U)` does not outlive the data it points at + --> $DIR/async-generics.rs:9:28 + | +LL | async fn foo(&self) -> &(T, U); + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs new file mode 100644 index 000000000..d5481d277 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -0,0 +1,19 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait MyTrait<'a, 'b, T> { + async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized; +} + +impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { + async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + (self, key) + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs new file mode 100644 index 000000000..f298e45d2 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-lifetimes.rs @@ -0,0 +1,17 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait<'a, 'b, T> { + async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); +} + +impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U { + async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) { + (self, key) + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs new file mode 100644 index 000000000..6839abd38 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo_recursive(&self, n: usize) -> T; +} + +impl MyTrait for T where T: Copy { + async fn foo_recursive(&self, n: usize) -> T { + //~^ ERROR recursion in an `async fn` requires boxing + if n > 0 { + self.foo_recursive(n - 1).await + } else { + *self + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr new file mode 100644 index 000000000..cab173bdd --- /dev/null +++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/async-recursive-generic.rs:11:48 + | +LL | async fn foo_recursive(&self, n: usize) -> T { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs new file mode 100644 index 000000000..61119f809 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-recursive.rs @@ -0,0 +1,21 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo_recursive(&self, n: usize) -> i32; +} + +impl MyTrait for i32 { + async fn foo_recursive(&self, n: usize) -> i32 { + //~^ ERROR recursion in an `async fn` requires boxing + if n > 0 { + self.foo_recursive(n - 1).await + } else { + *self + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr new file mode 100644 index 000000000..9feff37b3 --- /dev/null +++ b/tests/ui/async-await/in-trait/async-recursive.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/async-recursive.rs:11:48 + | +LL | async fn foo_recursive(&self, n: usize) -> i32 { + | ^^^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/in-trait/bad-signatures.rs b/tests/ui/async-await/in-trait/bad-signatures.rs new file mode 100644 index 000000000..b86f1d1c1 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-signatures.rs @@ -0,0 +1,16 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete + +trait MyTrait { + async fn bar(&abc self); + //~^ ERROR expected identifier, found keyword `self` + //~| ERROR expected one of `:`, `@`, or `|`, found keyword `self` +} + +impl MyTrait for () { + async fn bar(&self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/bad-signatures.stderr b/tests/ui/async-await/in-trait/bad-signatures.stderr new file mode 100644 index 000000000..e0ba7b53e --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-signatures.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `self` + --> $DIR/bad-signatures.rs:7:23 + | +LL | async fn bar(&abc self); + | ^^^^ expected identifier, found keyword + +error: expected one of `:`, `@`, or `|`, found keyword `self` + --> $DIR/bad-signatures.rs:7:23 + | +LL | async fn bar(&abc self); + | -----^^^^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/bad-signatures.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs new file mode 100644 index 000000000..6b3b14201 --- /dev/null +++ b/tests/ui/async-await/in-trait/early-bound-1.rs @@ -0,0 +1,17 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + async fn foo(&mut self); +} + +struct MyFoo<'a>(&'a mut ()); + +impl<'a> Foo for MyFoo<'a> { + async fn foo(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs new file mode 100644 index 000000000..270443229 --- /dev/null +++ b/tests/ui/async-await/in-trait/early-bound-2.rs @@ -0,0 +1,15 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + async fn foo(&mut self); +} + +impl Foo for &mut T { + async fn foo(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs new file mode 100644 index 000000000..9598d53bc --- /dev/null +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -0,0 +1,17 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> i32 { + //~^ ERROR: method `foo` should be async + *self + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr new file mode 100644 index 000000000..579801d0f --- /dev/null +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -0,0 +1,11 @@ +error: method `foo` should be async because the method from the trait is async + --> $DIR/fn-not-async-err.rs:11:5 + | +LL | async fn foo(&self) -> i32; + | --------------------------- required because the trait method is async +... +LL | fn foo(&self) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs new file mode 100644 index 000000000..2c4ed5535 --- /dev/null +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs @@ -0,0 +1,19 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait MyTrait { + async fn foo(&self) -> i32; +} + +impl MyTrait for i32 { + fn foo(&self) -> impl Future { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562] + async { *self } + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr new file mode 100644 index 000000000..f591f1847 --- /dev/null +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr @@ -0,0 +1,12 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return + --> $DIR/fn-not-async-err2.rs:13:22 + | +LL | fn foo(&self) -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs new file mode 100644 index 000000000..52bceb3cc --- /dev/null +++ b/tests/ui/async-await/in-trait/implied-bounds.rs @@ -0,0 +1,13 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait TcpStack { + type Connection<'a>: Sized where Self: 'a; + fn connect<'a>(&'a self) -> Self::Connection<'a>; + async fn async_connect<'a>(&'a self) -> Self::Connection<'a>; +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs new file mode 100644 index 000000000..f61b34ed9 --- /dev/null +++ b/tests/ui/async-await/in-trait/issue-102138.rs @@ -0,0 +1,46 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +async fn yield_now() {} + +trait AsyncIterator { + type Item; + async fn next(&mut self) -> Option; +} + +struct YieldingRange { + counter: u32, + stop: u32, +} + +impl AsyncIterator for YieldingRange { + type Item = u32; + + async fn next(&mut self) -> Option { + if self.counter == self.stop { + None + } else { + let c = self.counter; + self.counter += 1; + yield_now().await; + Some(c) + } + } +} + +async fn async_main() { + let mut x = YieldingRange { counter: 0, stop: 10 }; + + while let Some(v) = x.next().await { + println!("Hi: {v}"); + } +} + +fn main() { + let _ = async_main(); +} diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs new file mode 100644 index 000000000..9a35f6515 --- /dev/null +++ b/tests/ui/async-await/in-trait/issue-102219.rs @@ -0,0 +1,10 @@ +// compile-flags:--crate-type=lib +// edition:2021 +// check-pass + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +trait T { + async fn foo(); +} diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs new file mode 100644 index 000000000..49c3e9fee --- /dev/null +++ b/tests/ui/async-await/in-trait/issue-102310.rs @@ -0,0 +1,15 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait SpiDevice { + async fn transaction(&mut self); +} + +impl SpiDevice for () { + async fn transaction(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs new file mode 100644 index 000000000..e396df4e5 --- /dev/null +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -0,0 +1,31 @@ +// edition:2021 +// check-pass + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +pub trait Pool { + type Conn; + + async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future>( + &'a self, + callback: F, + ) -> (); +} + +pub struct PoolImpl; +pub struct ConnImpl; + +impl Pool for PoolImpl { + type Conn = ConnImpl; + + async fn async_callback<'a, F: FnOnce(&'a Self::Conn) -> Fut, Fut: Future>( + &'a self, + _callback: F, + ) -> () { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.rs b/tests/ui/async-await/in-trait/lifetime-mismatch.rs new file mode 100644 index 000000000..45ede193c --- /dev/null +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.rs @@ -0,0 +1,20 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + +trait MyTrait { + async fn foo<'a>(&self); + async fn bar(&self); +} + +impl MyTrait for i32 { + async fn foo(&self) {} + //~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration + + async fn bar(&self) { + self.foo(); + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr new file mode 100644 index 000000000..d87adcc78 --- /dev/null +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr @@ -0,0 +1,21 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/lifetime-mismatch.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/lifetime-mismatch.rs:12:17 + | +LL | async fn foo<'a>(&self); + | ---- lifetimes in impl do not match this method in trait +... +LL | async fn foo(&self) {} + | ^ lifetimes do not match method in trait + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/async-await/in-trait/missing-send-bound.rs b/tests/ui/async-await/in-trait/missing-send-bound.rs new file mode 100644 index 000000000..78922b59b --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-send-bound.rs @@ -0,0 +1,21 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + +trait Foo { + async fn bar(); +} + +async fn test() { + T::bar().await; +} + +fn test2() { + assert_is_send(test::()); + //~^ ERROR future cannot be sent between threads safely +} + +fn assert_is_send(_: impl Send) {} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr new file mode 100644 index 000000000..5cedf3ddb --- /dev/null +++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr @@ -0,0 +1,29 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/missing-send-bound.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: future cannot be sent between threads safely + --> $DIR/missing-send-bound.rs:15:20 + | +LL | assert_is_send(test::()); + | ^^^^^^^^^^^ future returned by `test` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `impl Future` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/missing-send-bound.rs:11:5 + | +LL | T::bar().await; + | ^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` +note: required by a bound in `assert_is_send` + --> $DIR/missing-send-bound.rs:19:27 + | +LL | fn assert_is_send(_: impl Send) {} + | ^^^^ required by this bound in `assert_is_send` + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs new file mode 100644 index 000000000..41d72ebb4 --- /dev/null +++ b/tests/ui/async-await/in-trait/nested-rpit.rs @@ -0,0 +1,19 @@ +// edition: 2021 +// known-bug: #105197 +// failure-status:101 +// dont-check-compiler-stderr + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::marker::PhantomData; + +trait Lockable { + async fn lock_all_entries(&self) -> impl Future>; +} + +struct Guard<'a>(PhantomData<&'a ()>); + +fn main() {} diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/object-safety.rs new file mode 100644 index 000000000..a8bc35f7e --- /dev/null +++ b/tests/ui/async-await/in-trait/object-safety.rs @@ -0,0 +1,13 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + +trait Foo { + async fn foo(&self); +} + +fn main() { + let x: &dyn Foo = todo!(); + //~^ ERROR the trait `Foo` cannot be made into an object +} diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr new file mode 100644 index 000000000..0b318f71f --- /dev/null +++ b/tests/ui/async-await/in-trait/object-safety.stderr @@ -0,0 +1,27 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/object-safety.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:11:12 + | +LL | let x: &dyn Foo = todo!(); + | ^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:14 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | async fn foo(&self); + | ^^^ ...because method `foo` is `async` + = help: consider moving `foo` to another trait + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs new file mode 100644 index 000000000..3446761d1 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs @@ -0,0 +1,14 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + +trait A { + async fn e() { + Ok(()) + //~^ ERROR mismatched types + //~| HELP consider using a semicolon here + } +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr new file mode 100644 index 000000000..5a9b15e54 --- /dev/null +++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr @@ -0,0 +1,23 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/return-type-suggestion.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/return-type-suggestion.rs:8:9 + | +LL | Ok(()) + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found enum `Result` + | + = note: expected unit type `()` + found enum `Result<(), _>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed new file mode 100644 index 000000000..055800d23 --- /dev/null +++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed @@ -0,0 +1,8 @@ +// run-rustfix +// edition:2018 + +// Regression test for issue 79694 + +fn main() { + let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect +} diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs new file mode 100644 index 000000000..e8be16516 --- /dev/null +++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs @@ -0,0 +1,8 @@ +// run-rustfix +// edition:2018 + +// Regression test for issue 79694 + +fn main() { + let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect +} diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr b/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr new file mode 100644 index 000000000..5367b986d --- /dev/null +++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.stderr @@ -0,0 +1,13 @@ +error: the order of `move` and `async` is incorrect + --> $DIR/incorrect-move-async-order-issue-79694.rs:7:13 + | +LL | let _ = move async { }; + | ^^^^^^^^^^ + | +help: try switching the order + | +LL | let _ = async move { }; + | ~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/interior-with-const-generic-expr.rs b/tests/ui/async-await/interior-with-const-generic-expr.rs new file mode 100644 index 000000000..86ba7582d --- /dev/null +++ b/tests/ui/async-await/interior-with-const-generic-expr.rs @@ -0,0 +1,26 @@ +// edition:2018 +// run-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![allow(unused)] + +fn main() { + let x = test(); +} + +fn concat(a: [f32; A], b: [f32; B]) -> [f32; A + B] { + todo!() +} + +async fn reverse(x: [f32; A]) -> [f32; A] { + todo!() +} + +async fn test() { + let a = [0.0]; + let b = [1.0, 2.0]; + let ab = concat(a,b); + let ba = reverse(ab).await; + println!("{:?}", ba); +} diff --git a/tests/ui/async-await/issue-101715.rs b/tests/ui/async-await/issue-101715.rs new file mode 100644 index 000000000..1be5d0248 --- /dev/null +++ b/tests/ui/async-await/issue-101715.rs @@ -0,0 +1,17 @@ +// edition:2018 + +struct S; + +impl S { + fn very_long_method_name_the_longest_method_name_in_the_whole_universe(self) {} +} + +async fn foo() { + S.very_long_method_name_the_longest_method_name_in_the_whole_universe() + .await + //~^ error: `()` is not a future + //~| help: remove the `.await` + //~| help: the trait `Future` is not implemented for `()` +} + +fn main() {} diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr new file mode 100644 index 000000000..a0e8d2a89 --- /dev/null +++ b/tests/ui/async-await/issue-101715.stderr @@ -0,0 +1,16 @@ +error[E0277]: `()` is not a future + --> $DIR/issue-101715.rs:11:9 + | +LL | .await + | ^^^^^^ + | | + | `()` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-105501.rs b/tests/ui/async-await/issue-105501.rs new file mode 100644 index 000000000..f30d2a9d8 --- /dev/null +++ b/tests/ui/async-await/issue-105501.rs @@ -0,0 +1,165 @@ +// check-pass +// edition:2018 + +// This is a regression test for https://github.com/rust-lang/rust/issues/105501. +// It was minified from the published `msf-ice:0.2.1` crate which failed in a crater run. +// A faulty compiler was triggering a `higher-ranked lifetime error`: +// +// > could not prove `[async block@...]: Send` + +use mini_futures::Stream; + +fn is_send(_: impl Send) {} + +pub fn main() { + let fut = async { + let mut stream = mini_futures::iter([()]) + .then(|_| async {}) + .map(|_| async { None }) + .buffered() + .filter_map(std::future::ready); + + stream.next().await + }; + + is_send(async move { + let _: Option<()> = fut.await; + }); +} + +// this is a simplified subset of `futures::StreamExt` and related types +mod mini_futures { + use std::future::Future; + use std::pin::Pin; + use std::task::{Context, Poll}; + + pub fn iter(_: I) -> Iter + where + I: IntoIterator, + { + todo!() + } + + pub trait Stream { + type Item; + + fn then(self, _: F) -> Then + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + todo!() + } + + fn map(self, _: F) -> Map + where + F: FnMut(Self::Item) -> T, + Self: Sized, + { + todo!() + } + + fn buffered(self) -> Buffered + where + Self::Item: Future, + Self: Sized, + { + todo!() + } + + fn filter_map(self, _: F) -> FilterMap + where + F: FnMut(Self::Item) -> Fut, + Fut: Future>, + Self: Sized, + { + todo!() + } + + fn next(&mut self) -> Next<'_, Self> { + todo!() + } + } + + pub struct Iter { + __: I, + } + impl Stream for Iter + where + I: Iterator, + { + type Item = I::Item; + } + + pub struct Then { + __: (St, Fut, F), + } + impl Stream for Then + where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, + { + type Item = Fut::Output; + } + + pub struct Map { + __: (St, F), + } + impl Stream for Map + where + St: Stream, + F: FnMut1, + { + type Item = F::Output; + } + + pub trait FnMut1 { + type Output; + } + impl FnMut1 for T + where + T: FnMut(A) -> R, + { + type Output = R; + } + + pub struct Buffered + where + St: Stream, + St::Item: Future, + { + __: (St, St::Item), + } + impl Stream for Buffered + where + St: Stream, + St::Item: Future, + { + type Item = ::Output; + } + + pub struct FilterMap { + __: (St, Fut, F), + } + impl Stream for FilterMap + where + St: Stream, + F: FnMut1, + Fut: Future>, + { + type Item = T; + } + + pub struct Next<'a, St: ?Sized> { + __: &'a mut St, + } + impl Future for Next<'_, St> { + type Output = Option; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + todo!() + } + } +} diff --git a/tests/ui/async-await/issue-107036.rs b/tests/ui/async-await/issue-107036.rs new file mode 100644 index 000000000..6a22de2c9 --- /dev/null +++ b/tests/ui/async-await/issue-107036.rs @@ -0,0 +1,14 @@ +// aux-build:issue-107036.rs +// edition:2021 +// check-pass + +extern crate issue_107036; +use issue_107036::S; + +async fn f() { + S{}.f().await; +} + +fn main() { + let _ = f(); +} diff --git a/tests/ui/async-await/issue-54239-private-type-triggers-lint.rs b/tests/ui/async-await/issue-54239-private-type-triggers-lint.rs new file mode 100644 index 000000000..16cf7ad52 --- /dev/null +++ b/tests/ui/async-await/issue-54239-private-type-triggers-lint.rs @@ -0,0 +1,17 @@ +// Regression test for #54239, shouldn't trigger lint. +// check-pass +// edition:2018 + +#![deny(missing_debug_implementations)] + +struct DontLookAtMe(i32); + +async fn secret() -> DontLookAtMe { + DontLookAtMe(41) +} + +pub async fn looking() -> i32 { // Shouldn't trigger lint here. + secret().await.0 +} + +fn main() {} diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs new file mode 100644 index 000000000..61f6ed1b7 --- /dev/null +++ b/tests/ui/async-await/issue-60709.rs @@ -0,0 +1,28 @@ +// This used to compile the future down to ud2, due to uninhabited types being +// handled incorrectly in generators. +// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 + +// run-pass +// ignore-asmjs wasm2js does not support source maps yet + +use std::future::Future; +use std::task::Poll; +use std::task::Context; +use std::pin::Pin; +use std::rc::Rc; + +struct Never(); +impl Future for Never { + type Output = (); + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +fn main() { + let fut = async { + let _rc = Rc::new(()); // Also crashes with Arc + Never().await; + }; + let _bla = fut; // Moving the future is required. +} diff --git a/tests/ui/async-await/issue-61076.rs b/tests/ui/async-await/issue-61076.rs new file mode 100644 index 000000000..750fad839 --- /dev/null +++ b/tests/ui/async-await/issue-61076.rs @@ -0,0 +1,97 @@ +// edition:2018 + +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +struct T; + +struct Tuple(i32); + +struct Struct { + a: i32 +} + +impl Struct { + fn method(&self) {} +} + +impl Future for Struct { + type Output = Struct; + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { Poll::Pending } +} + +impl Future for Tuple { + type Output = Tuple; + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { Poll::Pending } +} + +impl Future for T { + type Output = Result<(), ()>; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +async fn foo() -> Result<(), ()> { + Ok(()) +} + +async fn bar() -> Result<(), ()> { + foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ NOTE the `?` operator cannot be applied to type `impl Future>` + //~| HELP the trait `Try` is not implemented for `impl Future>` + //~| HELP consider `await`ing on the `Future` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + Ok(()) +} + +async fn struct_() -> Struct { + Struct { a: 1 } +} + +async fn tuple() -> Tuple { + //~^ NOTE checked the `Output` of this `async fn`, expected opaque type + //~| NOTE while checking the return type of the `async fn` + //~| NOTE in this expansion of desugaring of `async` block or function + Tuple(1i32) +} + +async fn baz() -> Result<(), ()> { + let t = T; + t?; //~ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ NOTE the `?` operator cannot be applied to type `T` + //~| HELP the trait `Try` is not implemented for `T` + //~| HELP consider `await`ing on the `Future` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + //~| NOTE in this expansion of desugaring of operator `?` + + + let _: i32 = tuple().0; //~ ERROR no field `0` + //~^ HELP consider `await`ing on the `Future` + //~| NOTE field not available in `impl Future` + + let _: i32 = struct_().a; //~ ERROR no field `a` + //~^ HELP consider `await`ing on the `Future` + //~| NOTE field not available in `impl Future` + + struct_().method(); //~ ERROR no method named + //~^ NOTE method not found in `impl Future` + //~| HELP consider `await`ing on the `Future` + Ok(()) +} + +async fn match_() { + match tuple() { //~ HELP consider `await`ing on the `Future` + //~^ NOTE this expression has type `impl Future` + Tuple(_) => {} //~ ERROR mismatched types + //~^ NOTE expected opaque type, found struct `Tuple` + //~| NOTE expected opaque type `impl Future` + } +} + +fn main() {} diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr new file mode 100644 index 000000000..33839ea59 --- /dev/null +++ b/tests/ui/async-await/issue-61076.stderr @@ -0,0 +1,82 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-61076.rs:42:5 + | +LL | foo()?; + | ^^^^^^ the `?` operator cannot be applied to type `impl Future>` + | + = help: the trait `Try` is not implemented for `impl Future>` +help: consider `await`ing on the `Future` + | +LL | foo().await?; + | ++++++ + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-61076.rs:65:5 + | +LL | t?; + | ^^ the `?` operator cannot be applied to type `T` + | + = help: the trait `Try` is not implemented for `T` +help: consider `await`ing on the `Future` + | +LL | t.await?; + | ++++++ + +error[E0609]: no field `0` on type `impl Future` + --> $DIR/issue-61076.rs:74:26 + | +LL | let _: i32 = tuple().0; + | ^ field not available in `impl Future`, but it is available in its `Output` + | +help: consider `await`ing on the `Future` and access the field of its `Output` + | +LL | let _: i32 = tuple().await.0; + | ++++++ + +error[E0609]: no field `a` on type `impl Future` + --> $DIR/issue-61076.rs:78:28 + | +LL | let _: i32 = struct_().a; + | ^ field not available in `impl Future`, but it is available in its `Output` + | +help: consider `await`ing on the `Future` and access the field of its `Output` + | +LL | let _: i32 = struct_().await.a; + | ++++++ + +error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope + --> $DIR/issue-61076.rs:82:15 + | +LL | struct_().method(); + | ^^^^^^ method not found in `impl Future` + | +help: consider `await`ing on the `Future` and calling the method on its `Output` + | +LL | struct_().await.method(); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/issue-61076.rs:91:9 + | +LL | match tuple() { + | ------- this expression has type `impl Future` +LL | +LL | Tuple(_) => {} + | ^^^^^^^^ expected opaque type, found struct `Tuple` + | +note: while checking the return type of the `async fn` + --> $DIR/issue-61076.rs:56:21 + | +LL | async fn tuple() -> Tuple { + | ^^^^^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future` + found struct `Tuple` +help: consider `await`ing on the `Future` + | +LL | match tuple().await { + | ++++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0308, E0599, E0609. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-61452.rs b/tests/ui/async-await/issue-61452.rs new file mode 100644 index 000000000..9381251ad --- /dev/null +++ b/tests/ui/async-await/issue-61452.rs @@ -0,0 +1,13 @@ +// edition:2018 + +pub async fn f(x: Option) { + x.take(); + //~^ ERROR cannot borrow `x` as mutable, as it is not declared as mutable [E0596] +} + +pub async fn g(x: usize) { + x += 1; + //~^ ERROR cannot assign twice to immutable variable `x` [E0384] +} + +fn main() {} diff --git a/tests/ui/async-await/issue-61452.stderr b/tests/ui/async-await/issue-61452.stderr new file mode 100644 index 000000000..bf5044328 --- /dev/null +++ b/tests/ui/async-await/issue-61452.stderr @@ -0,0 +1,26 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/issue-61452.rs:4:5 + | +LL | x.take(); + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | pub async fn f(mut x: Option) { + | +++ + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/issue-61452.rs:9:5 + | +LL | pub async fn g(x: usize) { + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0384, E0596. +For more information about an error, try `rustc --explain E0384`. diff --git a/tests/ui/async-await/issue-61793.rs b/tests/ui/async-await/issue-61793.rs new file mode 100644 index 000000000..9180e1d81 --- /dev/null +++ b/tests/ui/async-await/issue-61793.rs @@ -0,0 +1,16 @@ +// This testcase used to ICE in codegen due to inconsistent field reordering +// in the generator state, claiming a ZST field was after a non-ZST field, +// while those two fields were at the same offset (which is impossible). +// That is, memory ordering of `(X, ())`, but offsets of `((), X)`. + +// build-pass +// edition:2018 + +async fn foo(_: &(), _: F) {} + +fn main() { + foo(&(), || {}); + async { + foo(&(), || {}).await; + }; +} diff --git a/tests/ui/async-await/issue-61949-self-return-type.rs b/tests/ui/async-await/issue-61949-self-return-type.rs new file mode 100644 index 000000000..d73dbc6e8 --- /dev/null +++ b/tests/ui/async-await/issue-61949-self-return-type.rs @@ -0,0 +1,28 @@ +// edition:2018 +// gate-test-impl_trait_projections + +// This test checks that `Self` is prohibited as a return type. See #61949 for context. + +pub struct Foo<'a> { + pub bar: &'a i32, +} + +impl<'a> Foo<'a> { + pub async fn new(_bar: &'a i32) -> Self { + //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + Foo { + bar: &22 + } + } +} + +async fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).await + //~^ ERROR `bar` does not live long enough + }; + drop(x); +} + +fn main() { } diff --git a/tests/ui/async-await/issue-61949-self-return-type.stderr b/tests/ui/async-await/issue-61949-self-return-type.stderr new file mode 100644 index 000000000..638b197bc --- /dev/null +++ b/tests/ui/async-await/issue-61949-self-return-type.stderr @@ -0,0 +1,25 @@ +error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/issue-61949-self-return-type.rs:11:40 + | +LL | pub async fn new(_bar: &'a i32) -> Self { + | ^^^^ help: consider spelling out the type instead: `Foo<'a>` + | + = note: see issue #103532 for more information + = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable + +error[E0597]: `bar` does not live long enough + --> $DIR/issue-61949-self-return-type.rs:22:18 + | +LL | let x = { + | - borrow later stored here +LL | let bar = 22; +LL | Foo::new(&bar).await + | ^^^^ borrowed value does not live long enough +LL | +LL | }; + | - `bar` dropped here while still borrowed + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0597, E0658. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/async-await/issue-62658.rs b/tests/ui/async-await/issue-62658.rs new file mode 100644 index 000000000..d0af01e0c --- /dev/null +++ b/tests/ui/async-await/issue-62658.rs @@ -0,0 +1,27 @@ +// This test created a generator whose size was not rounded to a multiple of its +// alignment. This caused an assertion error in codegen. + +// build-pass +// edition:2018 + +async fn noop() {} + +async fn foo() { + // This suspend should be the largest variant. + { + let x = [0u8; 17]; + noop().await; + println!("{:?}", x); + } + + // Add one variant that's aligned to 8 bytes. + { + let x = 0u64; + noop().await; + println!("{:?}", x); + } +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs new file mode 100644 index 000000000..54059b29f --- /dev/null +++ b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs @@ -0,0 +1,19 @@ +// check-pass +// edition:2018 + +struct Test(String); + +impl Test { + async fn borrow_async(&self) {} + + fn with(&mut self, s: &str) -> &mut Self { + self.0 = s.into(); + self + } +} + +async fn test() { + Test("".to_string()).with("123").borrow_async().await; +} + +fn main() { } diff --git a/tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs new file mode 100644 index 000000000..c5ea2b821 --- /dev/null +++ b/tests/ui/async-await/issue-63832-await-short-temporary-lifetime.rs @@ -0,0 +1,12 @@ +// check-pass +// edition:2018 + +async fn foo(x: &[Vec]) -> u32 { + 0 +} + +async fn bar() { + foo(&[vec![123]]).await; +} + +fn main() { } diff --git a/tests/ui/async-await/issue-64130-1-sync.rs b/tests/ui/async-await/issue-64130-1-sync.rs new file mode 100644 index 000000000..1714cec52 --- /dev/null +++ b/tests/ui/async-await/issue-64130-1-sync.rs @@ -0,0 +1,23 @@ +#![feature(negative_impls)] +// edition:2018 + +// This tests the specialized async-await-specific error when futures don't implement an +// auto trait (which is specifically Sync) due to some type that was captured. + +struct Foo; + +impl !Sync for Foo {} + +fn is_sync(t: T) { } + +async fn bar() { + let x = Foo; + baz().await; +} + +async fn baz() { } + +fn main() { + is_sync(bar()); + //~^ ERROR future cannot be shared between threads safely +} diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr new file mode 100644 index 000000000..e205de473 --- /dev/null +++ b/tests/ui/async-await/issue-64130-1-sync.stderr @@ -0,0 +1,24 @@ +error: future cannot be shared between threads safely + --> $DIR/issue-64130-1-sync.rs:21:13 + | +LL | is_sync(bar()); + | ^^^^^ future returned by `bar` is not `Sync` + | + = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` +note: future is not `Sync` as this value is used across an await + --> $DIR/issue-64130-1-sync.rs:15:10 + | +LL | let x = Foo; + | - has type `Foo` which is not `Sync` +LL | baz().await; + | ^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here +note: required by a bound in `is_sync` + --> $DIR/issue-64130-1-sync.rs:11:15 + | +LL | fn is_sync(t: T) { } + | ^^^^ required by this bound in `is_sync` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-64130-2-send.rs b/tests/ui/async-await/issue-64130-2-send.rs new file mode 100644 index 000000000..7a6e5952c --- /dev/null +++ b/tests/ui/async-await/issue-64130-2-send.rs @@ -0,0 +1,23 @@ +#![feature(negative_impls)] +// edition:2018 + +// This tests the specialized async-await-specific error when futures don't implement an +// auto trait (which is specifically Send) due to some type that was captured. + +struct Foo; + +impl !Send for Foo {} + +fn is_send(t: T) { } + +async fn bar() { + let x = Foo; + baz().await; +} + +async fn baz() { } + +fn main() { + is_send(bar()); + //~^ ERROR future cannot be sent between threads safely +} diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr new file mode 100644 index 000000000..2225000e2 --- /dev/null +++ b/tests/ui/async-await/issue-64130-2-send.stderr @@ -0,0 +1,24 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-64130-2-send.rs:21:13 + | +LL | is_send(bar()); + | ^^^^^ future returned by `bar` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `Foo` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-2-send.rs:15:10 + | +LL | let x = Foo; + | - has type `Foo` which is not `Send` +LL | baz().await; + | ^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here +note: required by a bound in `is_send` + --> $DIR/issue-64130-2-send.rs:11:15 + | +LL | fn is_send(t: T) { } + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-64130-3-other.rs b/tests/ui/async-await/issue-64130-3-other.rs new file mode 100644 index 000000000..630fb2c41 --- /dev/null +++ b/tests/ui/async-await/issue-64130-3-other.rs @@ -0,0 +1,26 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] +// edition:2018 + +// This tests the unspecialized async-await-specific error when futures don't implement an +// auto trait (which is not Send or Sync) due to some type that was captured. + +auto trait Qux {} + +struct Foo; + +impl !Qux for Foo {} + +fn is_qux(t: T) {} + +async fn bar() { + let x = Foo; + baz().await; +} + +async fn baz() {} + +fn main() { + is_qux(bar()); + //~^ ERROR the trait bound `Foo: Qux` is not satisfied in `impl Future` +} diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr new file mode 100644 index 000000000..17867a6a3 --- /dev/null +++ b/tests/ui/async-await/issue-64130-3-other.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future` + --> $DIR/issue-64130-3-other.rs:24:12 + | +LL | async fn bar() { + | - within this `impl Future` +... +LL | is_qux(bar()); + | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` + | +note: future does not implement `Qux` as this value is used across an await + --> $DIR/issue-64130-3-other.rs:18:10 + | +LL | let x = Foo; + | - has type `Foo` which does not implement `Qux` +LL | baz().await; + | ^^^^^^ await occurs here, with `x` maybe used later +LL | } + | - `x` is later dropped here +note: required by a bound in `is_qux` + --> $DIR/issue-64130-3-other.rs:14:14 + | +LL | fn is_qux(t: T) {} + | ^^^ required by this bound in `is_qux` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr new file mode 100644 index 000000000..f609e3636 --- /dev/null +++ b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr @@ -0,0 +1,26 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-64130-4-async-move.rs:19:17 + | +LL | pub fn foo() -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-4-async-move.rs:25:31 + | +LL | match client.status() { + | ------ has type `&Client` which is not `Send` +LL | 200 => { +LL | let _x = get().await; + | ^^^^^^ await occurs here, with `client` maybe used later +... +LL | } + | - `client` is later dropped here +help: consider moving this into a `let` binding to create a shorter lived borrow + --> $DIR/issue-64130-4-async-move.rs:23:15 + | +LL | match client.status() { + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr new file mode 100644 index 000000000..f609e3636 --- /dev/null +++ b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr @@ -0,0 +1,26 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-64130-4-async-move.rs:19:17 + | +LL | pub fn foo() -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-4-async-move.rs:25:31 + | +LL | match client.status() { + | ------ has type `&Client` which is not `Send` +LL | 200 => { +LL | let _x = get().await; + | ^^^^^^ await occurs here, with `client` maybe used later +... +LL | } + | - `client` is later dropped here +help: consider moving this into a `let` binding to create a shorter lived borrow + --> $DIR/issue-64130-4-async-move.rs:23:15 + | +LL | match client.status() { + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-64130-4-async-move.rs b/tests/ui/async-await/issue-64130-4-async-move.rs new file mode 100644 index 000000000..a38428fc0 --- /dev/null +++ b/tests/ui/async-await/issue-64130-4-async-move.rs @@ -0,0 +1,32 @@ +// edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] check-pass +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no +use std::any::Any; +use std::future::Future; + +struct Client(Box); + +impl Client { + fn status(&self) -> u16 { + 200 + } +} + +async fn get() {} + +pub fn foo() -> impl Future + Send { + //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely + let client = Client(Box::new(true)); + async move { + match client.status() { + 200 => { + let _x = get().await; + } + _ => (), + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.rs b/tests/ui/async-await/issue-64130-non-send-future-diags.rs new file mode 100644 index 000000000..b652d2391 --- /dev/null +++ b/tests/ui/async-await/issue-64130-non-send-future-diags.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![allow(must_not_suspend)] + +// This tests the basic example case for the async-await-specific error. + +use std::sync::Mutex; + +fn is_send(t: T) { } + +async fn foo() { + bar(&Mutex::new(22)).await; +} + +async fn bar(x: &Mutex) { + let g = x.lock().unwrap(); + baz().await; +} + +async fn baz() { } + +fn main() { + is_send(foo()); + //~^ ERROR future cannot be sent between threads safely +} diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr new file mode 100644 index 000000000..1da80d98b --- /dev/null +++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -0,0 +1,24 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-64130-non-send-future-diags.rs:23:13 + | +LL | is_send(foo()); + | ^^^^^ future returned by `foo` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-64130-non-send-future-diags.rs:17:10 + | +LL | let g = x.lock().unwrap(); + | - has type `MutexGuard<'_, u32>` which is not `Send` +LL | baz().await; + | ^^^^^^ await occurs here, with `g` maybe used later +LL | } + | - `g` is later dropped here +note: required by a bound in `is_send` + --> $DIR/issue-64130-non-send-future-diags.rs:9:15 + | +LL | fn is_send(t: T) { } + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-64391.rs b/tests/ui/async-await/issue-64391.rs new file mode 100644 index 000000000..c6faad3aa --- /dev/null +++ b/tests/ui/async-await/issue-64391.rs @@ -0,0 +1,14 @@ +// Regression test for Issue #64391. The goal here is that this +// function compiles. In the past, due to incorrect drop order for +// temporaries in the tail expression, we failed to compile this +// example. The drop order itself is directly tested in +// `drop-order/drop-order-for-temporary-in-tail-return-expr.rs`. +// +// check-pass +// edition:2018 + +async fn add(x: u32, y: u32) -> u32 { + async { x + y }.await +} + +fn main() { } diff --git a/tests/ui/async-await/issue-66312.rs b/tests/ui/async-await/issue-66312.rs new file mode 100644 index 000000000..9224971ec --- /dev/null +++ b/tests/ui/async-await/issue-66312.rs @@ -0,0 +1,14 @@ +// edition:2018 + +trait Test { + fn is_some(self: T); //~ ERROR invalid `self` parameter type +} + +async fn f() { + let x = Some(2); + if x.is_some() { + println!("Some"); + } +} + +fn main() {} diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr new file mode 100644 index 000000000..80d294a10 --- /dev/null +++ b/tests/ui/async-await/issue-66312.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid `self` parameter type: T + --> $DIR/issue-66312.rs:4:22 + | +LL | fn is_some(self: T); + | ^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/async-await/issue-66387-if-without-else.rs b/tests/ui/async-await/issue-66387-if-without-else.rs new file mode 100644 index 000000000..3ab8220b4 --- /dev/null +++ b/tests/ui/async-await/issue-66387-if-without-else.rs @@ -0,0 +1,10 @@ +// edition:2018 +async fn f() -> i32 { + if true { //~ ERROR `if` may be missing an `else` clause + return 0; + } + // An `if` block without `else` causes the type table not to have a type for this expr. + // Check that we do not unconditionally access the type table and we don't ICE. +} + +fn main() {} diff --git a/tests/ui/async-await/issue-66387-if-without-else.stderr b/tests/ui/async-await/issue-66387-if-without-else.stderr new file mode 100644 index 000000000..8155fcb56 --- /dev/null +++ b/tests/ui/async-await/issue-66387-if-without-else.stderr @@ -0,0 +1,14 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/issue-66387-if-without-else.rs:3:5 + | +LL | / if true { +LL | | return 0; +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/async-await/issue-67252-unnamed-future.rs b/tests/ui/async-await/issue-67252-unnamed-future.rs new file mode 100644 index 000000000..1a7ff6133 --- /dev/null +++ b/tests/ui/async-await/issue-67252-unnamed-future.rs @@ -0,0 +1,24 @@ +// edition:2018 +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +fn spawn(_: T) {} + +pub struct AFuture; +impl Future for AFuture{ + type Output = (); + + fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<()> { + unimplemented!() + } +} + +async fn foo() { + spawn(async { //~ ERROR future cannot be sent between threads safely + let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` + AFuture.await; + }); +} + +fn main() {} diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr new file mode 100644 index 000000000..fcba4410b --- /dev/null +++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr @@ -0,0 +1,28 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-67252-unnamed-future.rs:18:11 + | +LL | spawn(async { + | ___________^ +LL | | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` +LL | | AFuture.await; +LL | | }); + | |_____^ future created by async block is not `Send` + | + = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:18:11: 21:6]`, the trait `Send` is not implemented for `*mut ()` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-67252-unnamed-future.rs:20:16 + | +LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` + | -- has type `*mut ()` which is not `Send` +LL | AFuture.await; + | ^^^^^^ await occurs here, with `_a` maybe used later +LL | }); + | - `_a` is later dropped here +note: required by a bound in `spawn` + --> $DIR/issue-67252-unnamed-future.rs:6:13 + | +LL | fn spawn(_: T) {} + | ^^^^ required by this bound in `spawn` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-67651.rs b/tests/ui/async-await/issue-67651.rs new file mode 100644 index 000000000..bd96a3b70 --- /dev/null +++ b/tests/ui/async-await/issue-67651.rs @@ -0,0 +1,20 @@ +// edition:2018 + +trait From { + fn from(); +} + +impl From for () { + fn from() {} +} + +impl From for () { +//~^ ERROR conflicting implementations of trait + fn from() {} +} + +fn bar() -> impl core::future::Future { + async move { From::from() } +} + +fn main() {} diff --git a/tests/ui/async-await/issue-67651.stderr b/tests/ui/async-await/issue-67651.stderr new file mode 100644 index 000000000..89017f6cc --- /dev/null +++ b/tests/ui/async-await/issue-67651.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From` for type `()` + --> $DIR/issue-67651.rs:11:1 + | +LL | impl From for () { + | ---------------- first implementation here +... +LL | impl From for () { + | ^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.rs b/tests/ui/async-await/issue-67765-async-diagnostic.rs new file mode 100644 index 000000000..5093916e7 --- /dev/null +++ b/tests/ui/async-await/issue-67765-async-diagnostic.rs @@ -0,0 +1,16 @@ +// edition:2018 +// +// Regression test for issue #67765 +// Tests that we point at the proper location when giving +// a lifetime error. +fn main() {} + +async fn func<'a>() -> Result<(), &'a str> { + let s = String::new(); + + let b = &s[..]; + + Err(b)?; //~ ERROR cannot return value referencing local variable `s` + + Ok(()) +} diff --git a/tests/ui/async-await/issue-67765-async-diagnostic.stderr b/tests/ui/async-await/issue-67765-async-diagnostic.stderr new file mode 100644 index 000000000..492e06fbb --- /dev/null +++ b/tests/ui/async-await/issue-67765-async-diagnostic.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `s` + --> $DIR/issue-67765-async-diagnostic.rs:13:5 + | +LL | let b = &s[..]; + | - `s` is borrowed here +LL | +LL | Err(b)?; + | ^^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/async-await/issue-68112.drop_tracking.stderr b/tests/ui/async-await/issue-68112.drop_tracking.stderr new file mode 100644 index 000000000..f2802698f --- /dev/null +++ b/tests/ui/async-await/issue-68112.drop_tracking.stderr @@ -0,0 +1,79 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:37:18 + | +LL | require_send(send_fut); + | ^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:34:17 + | +LL | let _ = non_send_fut.await; + | ^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:46:18 + | +LL | require_send(send_fut); + | ^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:43:17 + | +LL | let _ = make_non_send_future1().await; + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `RefCell` cannot be shared between threads safely + --> $DIR/issue-68112.rs:65:18 + | +LL | require_send(send_fut); + | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `RefCell` + = note: required for `Arc>` to implement `Send` +note: required because it's used within this `async fn` body + --> $DIR/issue-68112.rs:50:31 + | +LL | async fn ready2(t: T) -> T { + | _______________________________^ +LL | | t +LL | | } + | |_^ +note: required because it appears within the type `impl Future>>` + --> $DIR/issue-68112.rs:53:31 + | +LL | fn make_non_send_future2() -> impl Future>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `Ready` +note: required because it's used within this `async` block + --> $DIR/issue-68112.rs:60:20 + | +LL | let send_fut = async { + | ____________________^ +LL | | let non_send_fut = make_non_send_future2(); +LL | | let _ = non_send_fut.await; +LL | | ready(0).await; +LL | | }; + | |_____^ +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-68112.no_drop_tracking.stderr b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr new file mode 100644 index 000000000..38eb85b30 --- /dev/null +++ b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr @@ -0,0 +1,79 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:37:18 + | +LL | require_send(send_fut); + | ^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:34:17 + | +LL | let _ = non_send_fut.await; + | ^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:46:18 + | +LL | require_send(send_fut); + | ^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:43:17 + | +LL | let _ = make_non_send_future1().await; + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future>>`, which is not `Send` +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `RefCell` cannot be shared between threads safely + --> $DIR/issue-68112.rs:65:18 + | +LL | require_send(send_fut); + | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `RefCell` + = note: required for `Arc>` to implement `Send` +note: required because it's used within this `async fn` body + --> $DIR/issue-68112.rs:50:31 + | +LL | async fn ready2(t: T) -> T { + | _______________________________^ +LL | | t +LL | | } + | |_^ +note: required because it appears within the type `impl Future>>` + --> $DIR/issue-68112.rs:53:31 + | +LL | fn make_non_send_future2() -> impl Future>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `i32`, `Ready` +note: required because it's used within this `async` block + --> $DIR/issue-68112.rs:60:20 + | +LL | let send_fut = async { + | ____________________^ +LL | | let non_send_fut = make_non_send_future2(); +LL | | let _ = non_send_fut.await; +LL | | ready(0).await; +LL | | }; + | |_____^ +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:14:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-68112.rs b/tests/ui/async-await/issue-68112.rs new file mode 100644 index 000000000..9c705137a --- /dev/null +++ b/tests/ui/async-await/issue-68112.rs @@ -0,0 +1,69 @@ +// edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no + +use std::{ + cell::RefCell, + future::Future, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; + +fn require_send(_: impl Send) {} + +struct Ready(Option); +impl Future for Ready { + type Output = T; + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().unwrap()) + } +} +fn ready(t: T) -> Ready { + Ready(Some(t)) +} + +fn make_non_send_future1() -> impl Future>> { + ready(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_fut = async { + let non_send_fut = make_non_send_future1(); + let _ = non_send_fut.await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR future cannot be sent between threads +} + +fn test1_no_let() { + let send_fut = async { + let _ = make_non_send_future1().await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR future cannot be sent between threads +} + +async fn ready2(t: T) -> T { + t +} +fn make_non_send_future2() -> impl Future>> { + ready2(Arc::new(RefCell::new(0))) +} + +// Ideally this test would have diagnostics similar to the test above, but right +// now it doesn't. +fn test2() { + let send_fut = async { + let non_send_fut = make_non_send_future2(); + let _ = non_send_fut.await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR `RefCell` cannot be shared between threads safely +} + +fn main() {} diff --git a/tests/ui/async-await/issue-68523-start.rs b/tests/ui/async-await/issue-68523-start.rs new file mode 100644 index 000000000..2ced88a16 --- /dev/null +++ b/tests/ui/async-await/issue-68523-start.rs @@ -0,0 +1,9 @@ +// edition:2018 + +#![feature(start)] + +#[start] +pub async fn start(_: isize, _: *const *const u8) -> isize { +//~^ ERROR `start` is not allowed to be `async` + 0 +} diff --git a/tests/ui/async-await/issue-68523-start.stderr b/tests/ui/async-await/issue-68523-start.stderr new file mode 100644 index 000000000..3a0a3b5de --- /dev/null +++ b/tests/ui/async-await/issue-68523-start.stderr @@ -0,0 +1,9 @@ +error[E0752]: `start` is not allowed to be `async` + --> $DIR/issue-68523-start.rs:6:1 + | +LL | pub async fn start(_: isize, _: *const *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `start` is not allowed to be `async` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0752`. diff --git a/tests/ui/async-await/issue-68523.rs b/tests/ui/async-await/issue-68523.rs new file mode 100644 index 000000000..7a67661a0 --- /dev/null +++ b/tests/ui/async-await/issue-68523.rs @@ -0,0 +1,6 @@ +// edition:2018 + +async fn main() -> Result { +//~^ ERROR `main` function is not allowed to be `async` + Ok(1) +} diff --git a/tests/ui/async-await/issue-68523.stderr b/tests/ui/async-await/issue-68523.stderr new file mode 100644 index 000000000..dfdf078e3 --- /dev/null +++ b/tests/ui/async-await/issue-68523.stderr @@ -0,0 +1,9 @@ +error[E0752]: `main` function is not allowed to be `async` + --> $DIR/issue-68523.rs:3:1 + | +LL | async fn main() -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0752`. diff --git a/tests/ui/async-await/issue-69446-fnmut-capture.rs b/tests/ui/async-await/issue-69446-fnmut-capture.rs new file mode 100644 index 000000000..842115538 --- /dev/null +++ b/tests/ui/async-await/issue-69446-fnmut-capture.rs @@ -0,0 +1,22 @@ +// Regression test for issue #69446 - we should display +// which variable is captured +// edition:2018 + +use core::future::Future; + +struct Foo; +impl Foo { + fn foo(&mut self) {} +} + +async fn bar(_: impl FnMut() -> T) +where + T: Future, +{} + +fn main() { + let mut x = Foo; + bar(move || async { //~ ERROR captured + x.foo(); + }); +} diff --git a/tests/ui/async-await/issue-69446-fnmut-capture.stderr b/tests/ui/async-await/issue-69446-fnmut-capture.stderr new file mode 100644 index 000000000..3d2b0402b --- /dev/null +++ b/tests/ui/async-await/issue-69446-fnmut-capture.stderr @@ -0,0 +1,19 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-69446-fnmut-capture.rs:19:17 + | +LL | let mut x = Foo; + | ----- variable defined here +LL | bar(move || async { + | _______________-_^ + | | | + | | inferred to be a `FnMut` closure +LL | | x.foo(); + | | - variable captured here +LL | | }); + | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-70594.rs b/tests/ui/async-await/issue-70594.rs new file mode 100644 index 000000000..9e7c5847b --- /dev/null +++ b/tests/ui/async-await/issue-70594.rs @@ -0,0 +1,11 @@ +// edition:2018 + +async fn fun() { + [1; ().await]; + //~^ error: `await` is only allowed inside `async` functions and blocks + //~| error: `.await` is not allowed in a `const` + //~| error: `.await` is not allowed in a `const` + //~| error: `()` is not a future +} + +fn main() {} diff --git a/tests/ui/async-await/issue-70594.stderr b/tests/ui/async-await/issue-70594.stderr new file mode 100644 index 000000000..d3cf57d3b --- /dev/null +++ b/tests/ui/async-await/issue-70594.stderr @@ -0,0 +1,37 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-70594.rs:4:11 + | +LL | async fn fun() { + | --- this is not `async` +LL | [1; ().await]; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0744]: `.await` is not allowed in a `const` + --> $DIR/issue-70594.rs:4:9 + | +LL | [1; ().await]; + | ^^^^^^^^ + +error[E0744]: `.await` is not allowed in a `const` + --> $DIR/issue-70594.rs:4:11 + | +LL | [1; ().await]; + | ^^^^^^ + +error[E0277]: `()` is not a future + --> $DIR/issue-70594.rs:4:11 + | +LL | [1; ().await]; + | ^^^^^^ + | | + | `()` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0728, E0744. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs new file mode 100644 index 000000000..019c56eb2 --- /dev/null +++ b/tests/ui/async-await/issue-70818.rs @@ -0,0 +1,9 @@ +// edition:2018 + +use std::future::Future; +fn foo(ty: T, ty1: U) -> impl Future + Send { + //~^ Error future cannot be sent between threads safely + async { (ty, ty1) } +} + +fn main() {} diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr new file mode 100644 index 000000000..20109d4d1 --- /dev/null +++ b/tests/ui/async-await/issue-70818.stderr @@ -0,0 +1,18 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-70818.rs:4:38 + | +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> $DIR/issue-70818.rs:6:18 + | +LL | async { (ty, ty1) } + | ^^^ has type `U` which is not `Send` +help: consider restricting type parameter `U` + | +LL | fn foo(ty: T, ty1: U) -> impl Future + Send { + | +++++++++++++++++++ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr new file mode 100644 index 000000000..721234aa4 --- /dev/null +++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -0,0 +1,34 @@ +error[E0277]: `Sender` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:13:45 + | +LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ `Sender` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Sender` + = note: required for `&Sender` to implement `Send` +note: required because it's used within this closure + --> $DIR/issue-70935-complex-spans.rs:17:13 + | +LL | baz(|| async{ + | ^^ +note: required because it's used within this `async fn` body + --> $DIR/issue-70935-complex-spans.rs:10:67 + | +LL | async fn baz(_c: impl FnMut() -> T) where T: Future { + | ___________________________________________________________________^ +LL | | } + | |_^ + = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` +note: required because it's used within this `async` block + --> $DIR/issue-70935-complex-spans.rs:16:5 + | +LL | / async move { +LL | | baz(|| async{ +LL | | foo(tx.clone()); +LL | | }).await; +LL | | } + | |_____^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr new file mode 100644 index 000000000..8036d82da --- /dev/null +++ b/tests/ui/async-await/issue-70935-complex-spans.no_drop_tracking.stderr @@ -0,0 +1,21 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-70935-complex-spans.rs:13:45 + | +LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Sync` is not implemented for `Sender` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-70935-complex-spans.rs:19:11 + | +LL | baz(|| async{ + | _____________- +LL | | foo(tx.clone()); +LL | | }).await; + | | - ^^^^^^- the value is later dropped here + | | | | + | |_________| await occurs here, with the value maybe used later + | has type `[closure@$DIR/issue-70935-complex-spans.rs:17:13: 17:15]` which is not `Send` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs new file mode 100644 index 000000000..b6d17f93a --- /dev/null +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -0,0 +1,29 @@ +// edition:2018 +// revisions: no_drop_tracking drop_tracking +// [no_drop_tracking]compile-flags:-Zdrop-tracking=no +// [drop_tracking]compile-flags:-Zdrop-tracking +// #70935: Check if we do not emit snippet +// with newlines which lead complex diagnostics. + +use std::future::Future; + +async fn baz(_c: impl FnMut() -> T) where T: Future { +} + +fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely + //[drop_tracking]~^^ ERROR `Sender` cannot be shared between threads + async move { + baz(|| async{ + foo(tx.clone()); + }).await; + } +} + +fn bar(_s: impl Future + Send) { +} + +fn main() { + let (tx, _rx) = std::sync::mpsc::channel(); + bar(foo(tx)); +} diff --git a/tests/ui/async-await/issue-71137.rs b/tests/ui/async-await/issue-71137.rs new file mode 100644 index 000000000..7695e0325 --- /dev/null +++ b/tests/ui/async-await/issue-71137.rs @@ -0,0 +1,23 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![allow(must_not_suspend)] + +use std::future::Future; +use std::sync::Mutex; + +fn fake_spawn(f: F) { } + +async fn wrong_mutex() { + let m = Mutex::new(1); + { + let mut guard = m.lock().unwrap(); + (async { "right"; }).await; + *guard += 1; + } + + (async { "wrong"; }).await; +} + +fn main() { + fake_spawn(wrong_mutex()); //~ Error future cannot be sent between threads safely +} diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr new file mode 100644 index 000000000..eade6aa2d --- /dev/null +++ b/tests/ui/async-await/issue-71137.stderr @@ -0,0 +1,25 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-71137.rs:22:14 + | +LL | fake_spawn(wrong_mutex()); + | ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-71137.rs:14:25 + | +LL | let mut guard = m.lock().unwrap(); + | --------- has type `MutexGuard<'_, i32>` which is not `Send` +LL | (async { "right"; }).await; + | ^^^^^^ await occurs here, with `mut guard` maybe used later +LL | *guard += 1; +LL | } + | - `mut guard` is later dropped here +note: required by a bound in `fake_spawn` + --> $DIR/issue-71137.rs:8:27 + | +LL | fn fake_spawn(f: F) { } + | ^^^^ required by this bound in `fake_spawn` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-72442.rs b/tests/ui/async-await/issue-72442.rs new file mode 100644 index 000000000..2280154c7 --- /dev/null +++ b/tests/ui/async-await/issue-72442.rs @@ -0,0 +1,26 @@ +// edition:2018 +// incremental + +use std::fs::File; +use std::future::Future; +use std::io::prelude::*; + +fn main() -> Result<(), Box> { + block_on(async { + { + let path = std::path::Path::new("."); + let mut f = File::open(path.to_str())?; + //~^ ERROR the trait bound + let mut src = String::new(); + f.read_to_string(&mut src)?; + Ok(()) + } + }) +} + +fn block_on(f: F) -> F::Output +where + F: Future>>, +{ + Ok(()) +} diff --git a/tests/ui/async-await/issue-72442.stderr b/tests/ui/async-await/issue-72442.stderr new file mode 100644 index 000000000..4a1705715 --- /dev/null +++ b/tests/ui/async-await/issue-72442.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Option<&str>: AsRef` is not satisfied + --> $DIR/issue-72442.rs:12:36 + | +LL | let mut f = File::open(path.to_str())?; + | ---------- ^^^^^^^^^^^^^ the trait `AsRef` is not implemented for `Option<&str>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `File::open` + --> $SRC_DIR/std/src/fs.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-72470-llvm-dominate.rs b/tests/ui/async-await/issue-72470-llvm-dominate.rs new file mode 100644 index 000000000..5bb69a073 --- /dev/null +++ b/tests/ui/async-await/issue-72470-llvm-dominate.rs @@ -0,0 +1,66 @@ +// compile-flags: -C opt-level=3 +// aux-build: issue-72470-lib.rs +// edition:2018 +// build-pass + +// Regression test for issue #72470, using the minimization +// in https://github.com/jonas-schievink/llvm-error + +extern crate issue_72470_lib; + +use std::future::Future; +use std::pin::Pin; +use std::sync::Mutex; +use std::task::Poll::{Pending, Ready}; + +#[allow(dead_code)] +enum Msg { + A(Vec<()>), + B, +} + +#[allow(dead_code)] +enum Out { + _0(Option), + Disabled, +} + +#[allow(unused_must_use)] +fn main() { + let mut rx = issue_72470_lib::unbounded_channel::(); + let entity = Mutex::new(()); + issue_72470_lib::run(async move { + { + let output = { + let mut fut = rx.recv(); + issue_72470_lib::poll_fn(|cx| { + loop { + let fut = unsafe { Pin::new_unchecked(&mut fut) }; + let out = match fut.poll(cx) { + Ready(out) => out, + Pending => { + break; + } + }; + #[allow(unused_variables)] + match &out { + Some(_msg) => {} + _ => break, + } + return Ready(Out::_0(out)); + } + Ready(Out::_0(None)) + }) + .await + }; + match output { + Out::_0(Some(_msg)) => { + entity.lock(); + } + Out::_0(None) => unreachable!(), + _ => unreachable!(), + } + } + entity.lock(); + }); +} diff --git a/tests/ui/async-await/issue-72590-type-error-sized.rs b/tests/ui/async-await/issue-72590-type-error-sized.rs new file mode 100644 index 000000000..00e098d43 --- /dev/null +++ b/tests/ui/async-await/issue-72590-type-error-sized.rs @@ -0,0 +1,22 @@ +// Regression test for issue #72590 +// Tests that we don't emit a spurious "size cannot be statically determined" error +// edition:2018 + +struct Foo { + foo: Nonexistent, //~ ERROR cannot find + other: str +} + +struct Bar { + test: Missing //~ ERROR cannot find +} + +impl Foo { + async fn frob(self) {} //~ ERROR the size +} + +impl Bar { + async fn myfn(self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr new file mode 100644 index 000000000..778423578 --- /dev/null +++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr @@ -0,0 +1,34 @@ +error[E0412]: cannot find type `Nonexistent` in this scope + --> $DIR/issue-72590-type-error-sized.rs:6:10 + | +LL | foo: Nonexistent, + | ^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/issue-72590-type-error-sized.rs:11:11 + | +LL | test: Missing + | ^^^^^^^ not found in this scope + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-72590-type-error-sized.rs:15:19 + | +LL | async fn frob(self) {} + | ^^^^ doesn't have a size known at compile-time + | + = help: within `Foo`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `Foo` + --> $DIR/issue-72590-type-error-sized.rs:5:8 + | +LL | struct Foo { + | ^^^ + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | async fn frob(&self) {} + | + + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0412. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-73050.rs b/tests/ui/async-await/issue-73050.rs new file mode 100644 index 000000000..790f24a23 --- /dev/null +++ b/tests/ui/async-await/issue-73050.rs @@ -0,0 +1,12 @@ +// check-pass +// edition:2018 + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/async-await/issue-73137.rs b/tests/ui/async-await/issue-73137.rs new file mode 100644 index 000000000..dcbe7765a --- /dev/null +++ b/tests/ui/async-await/issue-73137.rs @@ -0,0 +1,44 @@ +// Regression test for + +// run-pass +// edition:2018 +// revisions: normal drop-tracking +// [normal]compile-flags: -Zdrop-tracking=no +// [drop-tracking]compile-flags: -Zdrop-tracking + +#![allow(dead_code)] +use std::future::Future; +use std::task::{Waker, Wake, Context}; +use std::sync::Arc; + +struct DummyWaker; +impl Wake for DummyWaker { + fn wake(self: Arc) {} +} + +struct Foo { + a: usize, + b: &'static u32, +} + +#[inline(never)] +fn nop(_: T) {} + +fn main() { + let mut fut = Box::pin(async { + let action = Foo { + b: &42, + a: async { 0 }.await, + }; + + // An error in the generator transform caused `b` to be overwritten with `a` when `b` was + // borrowed. + nop(&action.b); + assert_ne!(0usize, unsafe { std::mem::transmute(action.b) }); + + async {}.await; + }); + let waker = Waker::from(Arc::new(DummyWaker)); + let mut cx = Context::from_waker(&waker); + let _ = fut.as_mut().poll(&mut cx); +} diff --git a/tests/ui/async-await/issue-73541-1.rs b/tests/ui/async-await/issue-73541-1.rs new file mode 100644 index 000000000..7fb0d6c39 --- /dev/null +++ b/tests/ui/async-await/issue-73541-1.rs @@ -0,0 +1,12 @@ +// edition:2018 + +fn main() { + 'a: loop { + async { + loop { + continue 'a + //~^ ERROR use of unreachable label `'a` + } + }; + } +} diff --git a/tests/ui/async-await/issue-73541-1.stderr b/tests/ui/async-await/issue-73541-1.stderr new file mode 100644 index 000000000..80c1fdf00 --- /dev/null +++ b/tests/ui/async-await/issue-73541-1.stderr @@ -0,0 +1,14 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-73541-1.rs:7:26 + | +LL | 'a: loop { + | -- unreachable label defined here +... +LL | continue 'a + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/async-await/issue-73541-2.rs b/tests/ui/async-await/issue-73541-2.rs new file mode 100644 index 000000000..70b4ab253 --- /dev/null +++ b/tests/ui/async-await/issue-73541-2.rs @@ -0,0 +1,20 @@ +// edition:2018 + +async fn c() { + 'a: loop { + macro_rules! b { + () => { + continue 'a + //~^ ERROR use of unreachable label `'a` + } + } + + async { + loop { + b!(); + } + }; + } +} + +fn main() { } diff --git a/tests/ui/async-await/issue-73541-2.stderr b/tests/ui/async-await/issue-73541-2.stderr new file mode 100644 index 000000000..4c9741f6f --- /dev/null +++ b/tests/ui/async-await/issue-73541-2.stderr @@ -0,0 +1,18 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-73541-2.rs:7:26 + | +LL | 'a: loop { + | -- unreachable label defined here +... +LL | continue 'a + | ^^ unreachable label `'a` +... +LL | b!(); + | ---- in this macro invocation + | + = note: labels are unreachable through functions, closures, async blocks and modules + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/async-await/issue-73541-3.rs b/tests/ui/async-await/issue-73541-3.rs new file mode 100644 index 000000000..02ca02da8 --- /dev/null +++ b/tests/ui/async-await/issue-73541-3.rs @@ -0,0 +1,9 @@ +fn main() { + 'aaaaab: loop { + || { + loop { continue 'aaaaaa } + //~^ ERROR use of undeclared label `'aaaaaa` + }; + + } +} diff --git a/tests/ui/async-await/issue-73541-3.stderr b/tests/ui/async-await/issue-73541-3.stderr new file mode 100644 index 000000000..53487aaca --- /dev/null +++ b/tests/ui/async-await/issue-73541-3.stderr @@ -0,0 +1,12 @@ +error[E0426]: use of undeclared label `'aaaaaa` + --> $DIR/issue-73541-3.rs:4:29 + | +LL | 'aaaaab: loop { + | ------- a label with a similar name exists but is unreachable +LL | || { +LL | loop { continue 'aaaaaa } + | ^^^^^^^ undeclared label `'aaaaaa` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/async-await/issue-73541.rs b/tests/ui/async-await/issue-73541.rs new file mode 100644 index 000000000..399a07cd3 --- /dev/null +++ b/tests/ui/async-await/issue-73541.rs @@ -0,0 +1,9 @@ +fn main() { + 'a: loop { + || { + loop { continue 'a } + //~^ ERROR use of unreachable label `'a` + }; + + } +} diff --git a/tests/ui/async-await/issue-73541.stderr b/tests/ui/async-await/issue-73541.stderr new file mode 100644 index 000000000..4bb466ff1 --- /dev/null +++ b/tests/ui/async-await/issue-73541.stderr @@ -0,0 +1,14 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-73541.rs:4:29 + | +LL | 'a: loop { + | -- unreachable label defined here +LL | || { +LL | loop { continue 'a } + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs new file mode 100644 index 000000000..c3423ad62 --- /dev/null +++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs @@ -0,0 +1,14 @@ +// edition:2018 +// compile-flags: -Zdrop-tracking +// Regression test for issue #73741 +// Ensures that we don't emit spurious errors when +// a type error ocurrs in an `async fn` + +async fn weird() { + 1 = 2; //~ ERROR invalid left-hand side + + let mut loop_count = 0; + async {}.await +} + +fn main() {} diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr new file mode 100644 index 000000000..d4e3b6c3b --- /dev/null +++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr @@ -0,0 +1,11 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-73741-type-err-drop-tracking.rs:8:7 + | +LL | 1 = 2; + | - ^ + | | + | cannot assign to this expression + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/async-await/issue-73741-type-err.rs b/tests/ui/async-await/issue-73741-type-err.rs new file mode 100644 index 000000000..c5b9e34ed --- /dev/null +++ b/tests/ui/async-await/issue-73741-type-err.rs @@ -0,0 +1,14 @@ +// edition:2018 +// +// Regression test for issue #73741 +// Ensures that we don't emit spurious errors when +// a type error ocurrs in an `async fn` + +async fn weird() { + 1 = 2; //~ ERROR invalid left-hand side + + let mut loop_count = 0; + async {}.await +} + +fn main() {} diff --git a/tests/ui/async-await/issue-73741-type-err.stderr b/tests/ui/async-await/issue-73741-type-err.stderr new file mode 100644 index 000000000..0b5343a98 --- /dev/null +++ b/tests/ui/async-await/issue-73741-type-err.stderr @@ -0,0 +1,11 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-73741-type-err.rs:8:7 + | +LL | 1 = 2; + | - ^ + | | + | cannot assign to this expression + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/async-await/issue-74047.rs b/tests/ui/async-await/issue-74047.rs new file mode 100644 index 000000000..2e4f3e675 --- /dev/null +++ b/tests/ui/async-await/issue-74047.rs @@ -0,0 +1,17 @@ +// edition:2018 + +use std::convert::{TryFrom, TryInto}; +use std::io; + +pub struct MyStream; +pub struct OtherStream; + +pub async fn connect() -> io::Result { + let stream: MyStream = OtherStream.try_into()?; + Ok(stream) +} + +impl TryFrom for MyStream {} +//~^ ERROR: missing + +fn main() {} diff --git a/tests/ui/async-await/issue-74047.stderr b/tests/ui/async-await/issue-74047.stderr new file mode 100644 index 000000000..28174825d --- /dev/null +++ b/tests/ui/async-await/issue-74047.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Error`, `try_from` + --> $DIR/issue-74047.rs:14:1 + | +LL | impl TryFrom for MyStream {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Error`, `try_from` in implementation + | + = help: implement the missing item: `type Error = Type;` + = help: implement the missing item: `fn try_from(_: T) -> Result>::Error> { todo!() }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs new file mode 100644 index 000000000..95683241a --- /dev/null +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs @@ -0,0 +1,37 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +// test the quality of annotations giving lifetimes names (`'1`) when async constructs are involved + +pub async fn async_fn(x: &mut i32) -> &i32 { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y +} + +pub fn async_closure(x: &mut i32) -> impl Future { + (async move || { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y + })() +} + +pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { + (async move || -> &i32 { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y + })() +} + +pub fn async_block(x: &mut i32) -> impl Future { + async move { + let y = &*x; + *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed + y + } +} + +fn main() {} diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr new file mode 100644 index 000000000..b96cab9f0 --- /dev/null +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -0,0 +1,51 @@ +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:9:5 + | +LL | pub async fn async_fn(x: &mut i32) -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:16:9 + | +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` +LL | })() + | - return type of async closure is &'1 i32 + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:24:9 + | +LL | (async move || -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:32:9 + | +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` +LL | } + | - return type of async block is &'1 i32 + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/async-await/issue-74497-lifetime-in-opaque.rs b/tests/ui/async-await/issue-74497-lifetime-in-opaque.rs new file mode 100644 index 000000000..2d765eb41 --- /dev/null +++ b/tests/ui/async-await/issue-74497-lifetime-in-opaque.rs @@ -0,0 +1,19 @@ +// edition:2018 + +// test that names give to anonymous lifetimes in opaque types like `impl Future` are correctly +// introduced in error messages + +use std::future::Future; + +pub async fn foo(_: F) +where + F: Fn(&u8) -> T, + T: Future, +{ +} + +pub async fn bar(_: &u8) {} + +fn main() { + let _ = foo(|x| bar(x)); //~ ERROR lifetime may not live long enough +} diff --git a/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr b/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr new file mode 100644 index 000000000..4427014ae --- /dev/null +++ b/tests/ui/async-await/issue-74497-lifetime-in-opaque.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-74497-lifetime-in-opaque.rs:18:21 + | +LL | let _ = foo(|x| bar(x)); + | -- ^^^^^^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure `impl Future` contains a lifetime `'2` + | has type `&'1 u8` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-75785-confusing-named-region.rs b/tests/ui/async-await/issue-75785-confusing-named-region.rs new file mode 100644 index 000000000..452614087 --- /dev/null +++ b/tests/ui/async-await/issue-75785-confusing-named-region.rs @@ -0,0 +1,13 @@ +// edition:2018 +// +// Regression test for issue #75785 +// Tests that we don't point to a confusing named +// region when emitting a diagnostic + +pub async fn async_fn(x: &mut i32) -> (&i32, &i32) { + let y = &*x; + *x += 1; //~ ERROR cannot assign to + (&32, y) +} + +fn main() {} diff --git a/tests/ui/async-await/issue-75785-confusing-named-region.stderr b/tests/ui/async-await/issue-75785-confusing-named-region.stderr new file mode 100644 index 000000000..3b731d9c6 --- /dev/null +++ b/tests/ui/async-await/issue-75785-confusing-named-region.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-75785-confusing-named-region.rs:9:5 + | +LL | pub async fn async_fn(x: &mut i32) -> (&i32, &i32) { + | - let's call the lifetime of this reference `'1` +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | *x += 1; + | ^^^^^^^ assignment to borrowed `*x` occurs here +LL | (&32, y) + | -------- returning this value requires that `*x` is borrowed for `'1` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/async-await/issue-76547.rs b/tests/ui/async-await/issue-76547.rs new file mode 100644 index 000000000..587feb624 --- /dev/null +++ b/tests/ui/async-await/issue-76547.rs @@ -0,0 +1,38 @@ +// Test for diagnostic improvement issue #76547 +// edition:2018 + +use std::{ + future::Future, + task::{Context, Poll} +}; +use std::pin::Pin; + +pub struct ListFut<'a>(&'a mut [&'a mut [u8]]); +impl<'a> Future for ListFut<'a> { + type Output = (); + + fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll { + unimplemented!() + } +} + +async fn fut(bufs: &mut [&mut [u8]]) { + ListFut(bufs).await + //~^ ERROR lifetime may not live long enough +} + +pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]); +impl<'a> Future for ListFut2<'a> { + type Output = i32; + + fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll { + unimplemented!() + } +} + +async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { + ListFut2(bufs).await + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/async-await/issue-76547.stderr b/tests/ui/async-await/issue-76547.stderr new file mode 100644 index 000000000..4d96cce82 --- /dev/null +++ b/tests/ui/async-await/issue-76547.stderr @@ -0,0 +1,32 @@ +error: lifetime may not live long enough + --> $DIR/issue-76547.rs:20:13 + | +LL | async fn fut(bufs: &mut [&mut [u8]]) { + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/issue-76547.rs:34:14 + | +LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut2(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | async fn fut2<'a>(bufs: &'a mut [&'a mut [u8]]) -> i32 { + | ++++ ++ ++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/issue-77993-2.rs b/tests/ui/async-await/issue-77993-2.rs new file mode 100644 index 000000000..4d554a0a1 --- /dev/null +++ b/tests/ui/async-await/issue-77993-2.rs @@ -0,0 +1,9 @@ +// edition:2018 + +async fn test() -> Result<(), Box> { + macro!(); + //~^ ERROR expected identifier, found `!` + Ok(()) +} + +fn main() {} diff --git a/tests/ui/async-await/issue-77993-2.stderr b/tests/ui/async-await/issue-77993-2.stderr new file mode 100644 index 000000000..64b378f83 --- /dev/null +++ b/tests/ui/async-await/issue-77993-2.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `!` + --> $DIR/issue-77993-2.rs:4:10 + | +LL | macro!(); + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-84841.rs b/tests/ui/async-await/issue-84841.rs new file mode 100644 index 000000000..ba3a1617b --- /dev/null +++ b/tests/ui/async-await/issue-84841.rs @@ -0,0 +1,16 @@ +// edition:2018 + +fn main() { + +} + +async fn foo() { + // Adding an .await here avoids the ICE + test()?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR the `?` operator can only be used in an async function that returns +} + +// Removing the const generic parameter here avoids the ICE +async fn test() { +} diff --git a/tests/ui/async-await/issue-84841.stderr b/tests/ui/async-await/issue-84841.stderr new file mode 100644 index 000000000..1e22373ba --- /dev/null +++ b/tests/ui/async-await/issue-84841.stderr @@ -0,0 +1,26 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-84841.rs:9:5 + | +LL | test()?; + | ^^^^^^^ the `?` operator cannot be applied to type `impl Future` + | + = help: the trait `Try` is not implemented for `impl Future` + +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/issue-84841.rs:9:11 + | +LL | async fn foo() { + | ________________- +LL | | // Adding an .await here avoids the ICE +LL | | test()?; + | | ^ cannot use the `?` operator in an async function that returns `()` +LL | | +LL | | +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-86507.rs b/tests/ui/async-await/issue-86507.rs new file mode 100644 index 000000000..317f03176 --- /dev/null +++ b/tests/ui/async-await/issue-86507.rs @@ -0,0 +1,25 @@ +// edition:2018 + +use ::core::pin::Pin; +use ::core::future::Future; +use ::core::marker::Send; + +trait Foo { + fn bar<'me, 'async_trait, T: Send>(x: &'me T) + -> Pin + Send + 'async_trait>> + where 'me: 'async_trait; +} + +impl Foo for () { + fn bar<'me, 'async_trait, T: Send>(x: &'me T) + -> Pin + Send + 'async_trait>> + where 'me:'async_trait { + Box::pin( //~ ERROR future cannot be sent between threads safely + async move { + let x = x; + } + ) + } +} + +fn main() { } diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr new file mode 100644 index 000000000..8c2c06da2 --- /dev/null +++ b/tests/ui/async-await/issue-86507.stderr @@ -0,0 +1,23 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-86507.rs:17:13 + | +LL | / Box::pin( +LL | | async move { +LL | | let x = x; +LL | | } +LL | | ) + | |_____________^ future created by async block is not `Send` + | +note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` + --> $DIR/issue-86507.rs:19:29 + | +LL | let x = x; + | ^ has type `&T` which is not `Send`, because `T` is not `Sync` + = note: required for the cast from `[async block@$DIR/issue-86507.rs:18:17: 20:18]` to the object type `dyn Future + Send` +help: consider further restricting this bound + | +LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) + | +++++++++++++++++++ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issue-93197.rs b/tests/ui/async-await/issue-93197.rs new file mode 100644 index 000000000..c627fe17a --- /dev/null +++ b/tests/ui/async-await/issue-93197.rs @@ -0,0 +1,16 @@ +// Regression test for #93197 +// check-pass +// edition:2021 +// compile-flags: -Zdrop-tracking + +#![feature(try_blocks)] + +use std::sync::{mpsc, mpsc::SendError}; + +pub async fn foo() { + let (tx, _) = mpsc::channel(); + + let _: Result<(), SendError<&str>> = try { tx.send("hello")?; }; +} + +fn main() {} diff --git a/tests/ui/async-await/issue-93648.rs b/tests/ui/async-await/issue-93648.rs new file mode 100644 index 000000000..4ce3ac1e8 --- /dev/null +++ b/tests/ui/async-await/issue-93648.rs @@ -0,0 +1,12 @@ +// edition:2021 +// build-pass +// compile-flags: -Zdrop-tracking + +fn main() { + let _ = async { + let mut s = (String::new(),); + s.0.push_str("abc"); + std::mem::drop(s); + async {}.await; + }; +} diff --git a/tests/ui/async-await/issue-98634.rs b/tests/ui/async-await/issue-98634.rs new file mode 100644 index 000000000..b0d38687f --- /dev/null +++ b/tests/ui/async-await/issue-98634.rs @@ -0,0 +1,50 @@ +// edition: 2021 + +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll, Waker}, +}; + +pub struct StructAsync Pin>>> { + pub callback: F, +} + +impl Future for StructAsync +where + F: Fn() -> Pin>>, +{ + type Output = (); + + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +async fn callback() {} + +struct Runtime; + +fn waker() -> &'static Waker { + todo!() +} + +impl Runtime { + #[track_caller] + pub fn block_on(&self, mut future: F) -> F::Output { + loop { + unsafe { + Pin::new_unchecked(&mut future).poll(&mut Context::from_waker(waker())); + } + } + } +} + +fn main() { + Runtime.block_on(async { + StructAsync { callback }.await; + //~^ ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + //~| ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + //~| ERROR expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + }); +} diff --git a/tests/ui/async-await/issue-98634.stderr b/tests/ui/async-await/issue-98634.stderr new file mode 100644 index 000000000..5160e48d8 --- /dev/null +++ b/tests/ui/async-await/issue-98634.stderr @@ -0,0 +1,60 @@ +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:23 + | +LL | StructAsync { callback }.await; + | ^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:9 + | +LL | StructAsync { callback }.await; + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error[E0271]: expected `fn() -> impl Future {callback}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98634.rs:45:33 + | +LL | StructAsync { callback }.await; + | ^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98634.rs:24:21 + | +LL | async fn callback() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` +note: required by a bound in `StructAsync` + --> $DIR/issue-98634.rs:9:35 + | +LL | pub struct StructAsync Pin>>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/async-await/issues/auxiliary/issue-60674.rs b/tests/ui/async-await/issues/auxiliary/issue-60674.rs new file mode 100644 index 000000000..680c6e55e --- /dev/null +++ b/tests/ui/async-await/issues/auxiliary/issue-60674.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr(_args: TokenStream, input: TokenStream) -> TokenStream { + println!("{}", input); + TokenStream::new() +} diff --git a/tests/ui/async-await/issues/auxiliary/issue_67893.rs b/tests/ui/async-await/issues/auxiliary/issue_67893.rs new file mode 100644 index 000000000..387966a50 --- /dev/null +++ b/tests/ui/async-await/issues/auxiliary/issue_67893.rs @@ -0,0 +1,10 @@ +// edition:2018 + +use std::sync::{Arc, Mutex}; + +pub async fn f(_: ()) {} + +pub async fn run() { + let x: Arc> = unimplemented!(); + f(*x.lock().unwrap()).await; +} diff --git a/tests/ui/async-await/issues/issue-102206.rs b/tests/ui/async-await/issues/issue-102206.rs new file mode 100644 index 000000000..a3a2ebc58 --- /dev/null +++ b/tests/ui/async-await/issues/issue-102206.rs @@ -0,0 +1,8 @@ +// edition:2021 + +async fn foo() {} + +fn main() { + std::mem::size_of_val(foo()); + //~^ ERROR: mismatched types +} diff --git a/tests/ui/async-await/issues/issue-102206.stderr b/tests/ui/async-await/issues/issue-102206.stderr new file mode 100644 index 000000000..2ab790ac7 --- /dev/null +++ b/tests/ui/async-await/issues/issue-102206.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/issue-102206.rs:6:27 + | +LL | std::mem::size_of_val(foo()); + | --------------------- ^^^^^ + | | | + | | expected reference, found opaque type + | | help: consider borrowing here: `&foo()` + | arguments to this function are incorrect + | +note: while checking the return type of the `async fn` + --> $DIR/issue-102206.rs:3:16 + | +LL | async fn foo() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected reference `&_` + found opaque type `impl Future` +note: function defined here + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/issues/issue-51719.rs b/tests/ui/async-await/issues/issue-51719.rs new file mode 100644 index 000000000..09241f982 --- /dev/null +++ b/tests/ui/async-await/issues/issue-51719.rs @@ -0,0 +1,12 @@ +// edition:2018 +// +// Tests that the .await syntax can't be used to make a generator + +async fn foo() {} + +fn make_generator() { + let _gen = || foo().await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-51719.stderr b/tests/ui/async-await/issues/issue-51719.stderr new file mode 100644 index 000000000..f3ce5d1c8 --- /dev/null +++ b/tests/ui/async-await/issues/issue-51719.stderr @@ -0,0 +1,11 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-51719.rs:8:24 + | +LL | let _gen = || foo().await; + | -- ^^^^^^ only allowed inside `async` functions and blocks + | | + | this is not `async` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-51751.rs b/tests/ui/async-await/issues/issue-51751.rs new file mode 100644 index 000000000..bc85a96ce --- /dev/null +++ b/tests/ui/async-await/issues/issue-51751.rs @@ -0,0 +1,11 @@ +// edition:2018 + +async fn inc(limit: i64) -> i64 { + limit + 1 +} + +fn main() { + let result = inc(10000); + let finished = result.await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/tests/ui/async-await/issues/issue-51751.stderr b/tests/ui/async-await/issues/issue-51751.stderr new file mode 100644 index 000000000..8696a5b79 --- /dev/null +++ b/tests/ui/async-await/issues/issue-51751.stderr @@ -0,0 +1,12 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-51751.rs:9:26 + | +LL | fn main() { + | ---- this is not `async` +LL | let result = inc(10000); +LL | let finished = result.await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-53249.rs b/tests/ui/async-await/issues/issue-53249.rs new file mode 100644 index 000000000..3a33af2d2 --- /dev/null +++ b/tests/ui/async-await/issues/issue-53249.rs @@ -0,0 +1,47 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] + +use std::task::{self, Poll}; +use std::future::Future; +use std::marker::Unpin; +use std::pin::Pin; + +// This is a regression test for an ICE/unbounded recursion issue relating to async-await. + +#[derive(Debug)] +#[must_use = "futures do nothing unless polled"] +pub struct Lazy { + f: Option +} + +impl Unpin for Lazy {} + +pub fn lazy(f: F) -> Lazy + where F: FnOnce(&mut task::Context) -> R, +{ + Lazy { f: Some(f) } +} + +impl Future for Lazy + where F: FnOnce(&mut task::Context) -> R, +{ + type Output = R; + + fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + Poll::Ready((self.f.take().unwrap())(cx)) + } +} + +async fn __receive(want: WantFn) -> () + where Fut: Future, WantFn: Fn(&Box) -> Fut, +{ + lazy(|_| ()).await; +} + +pub fn basic_spawn_receive() { + async { __receive(|_| async { () }).await }; +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-54752-async-block.rs b/tests/ui/async-await/issues/issue-54752-async-block.rs new file mode 100644 index 000000000..a8165ae6c --- /dev/null +++ b/tests/ui/async-await/issues/issue-54752-async-block.rs @@ -0,0 +1,7 @@ +// run-pass + +// edition:2018 +// pp-exact + +fn main() { let _a = (async { }); } +//~^ WARNING unnecessary parentheses around assigned value diff --git a/tests/ui/async-await/issues/issue-54752-async-block.stderr b/tests/ui/async-await/issues/issue-54752-async-block.stderr new file mode 100644 index 000000000..8cc849dd9 --- /dev/null +++ b/tests/ui/async-await/issues/issue-54752-async-block.stderr @@ -0,0 +1,15 @@ +warning: unnecessary parentheses around assigned value + --> $DIR/issue-54752-async-block.rs:6:22 + | +LL | fn main() { let _a = (async { }); } + | ^ ^ + | + = note: `#[warn(unused_parens)]` on by default +help: remove these parentheses + | +LL - fn main() { let _a = (async { }); } +LL + fn main() { let _a = async { }; } + | + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/issues/issue-54974.rs b/tests/ui/async-await/issues/issue-54974.rs new file mode 100644 index 000000000..b602ef153 --- /dev/null +++ b/tests/ui/async-await/issues/issue-54974.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +use std::sync::Arc; + +trait SomeTrait: Send + Sync + 'static { + fn do_something(&self); +} + +async fn my_task(obj: Arc) { + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-55324.rs b/tests/ui/async-await/issues/issue-55324.rs new file mode 100644 index 000000000..9ecb3b129 --- /dev/null +++ b/tests/ui/async-await/issues/issue-55324.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2018 + +use std::future::Future; + +async fn foo>(x: &i32, future: F) -> i32 { + let y = future.await; + *x + y +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-55809.rs b/tests/ui/async-await/issues/issue-55809.rs new file mode 100644 index 000000000..3b271775a --- /dev/null +++ b/tests/ui/async-await/issues/issue-55809.rs @@ -0,0 +1,28 @@ +// edition:2018 +// run-pass + +trait Foo { } + +impl Foo for () { } + +impl<'a, T> Foo for &'a mut T where T: Foo { } + +async fn foo_async(_v: T) -> u8 where T: Foo { + 0 +} + +async fn bad(v: T) -> u8 where T: Foo { + foo_async(v).await +} + +async fn async_main() { + let mut v = (); + + let _ = bad(&mut v).await; + let _ = foo_async(&mut v).await; + let _ = bad(v).await; +} + +fn main() { + let _ = async_main(); +} diff --git a/tests/ui/async-await/issues/issue-58885.rs b/tests/ui/async-await/issues/issue-58885.rs new file mode 100644 index 000000000..11920b072 --- /dev/null +++ b/tests/ui/async-await/issues/issue-58885.rs @@ -0,0 +1,19 @@ +// check-pass +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + &'a self, foo: &'a dyn Foo + ) -> bool + { + true + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-59001.rs b/tests/ui/async-await/issues/issue-59001.rs new file mode 100644 index 000000000..4ddebcf20 --- /dev/null +++ b/tests/ui/async-await/issues/issue-59001.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +use std::future::Future; + +async fn enter<'a, F, R>(mut callback: F) +where + F: FnMut(&'a mut i32) -> R, + R: Future + 'a, +{ + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-59972.rs b/tests/ui/async-await/issues/issue-59972.rs new file mode 100644 index 000000000..c2e24a96b --- /dev/null +++ b/tests/ui/async-await/issues/issue-59972.rs @@ -0,0 +1,34 @@ +// Incorrect handling of uninhabited types could cause us to mark generator +// types as entirely uninhabited, when they were in fact constructible. This +// caused us to hit "unreachable" code (illegal instruction on x86). + +// run-pass + +// compile-flags: --edition=2018 -Aunused + +pub enum Uninhabited { } + +fn uninhabited_async() -> Uninhabited { + unreachable!() +} + +async fn noop() { } + +async fn contains_never() { + let error = uninhabited_async(); + noop().await; + let error2 = error; +} + +async fn overlap_never() { + let error1 = uninhabited_async(); + noop().await; + let error2 = uninhabited_async(); + drop(error1); + noop().await; + drop(error2); +} + +#[allow(unused_must_use)] +fn main() { +} diff --git a/tests/ui/async-await/issues/issue-60518.rs b/tests/ui/async-await/issues/issue-60518.rs new file mode 100644 index 000000000..69bbdd0e8 --- /dev/null +++ b/tests/ui/async-await/issues/issue-60518.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 + +// This is a regression test to ensure that simple bindings (where replacement arguments aren't +// created during async fn lowering) that have their DefId used during HIR lowering (such as impl +// trait) are visited during def collection and thus have a DefId. + +async fn foo(ws: impl Iterator) {} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-60655-latebound-regions.rs b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs new file mode 100644 index 000000000..66a3b07c3 --- /dev/null +++ b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs @@ -0,0 +1,30 @@ +// Test that opaque `impl Trait` types are allowed to contain late-bound regions. + +// check-pass +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +pub type Func = impl Sized; + +// Late bound region should be allowed to escape the function, since it's bound +// in the type. +fn null_function_ptr() -> Func { + None:: fn(&'a ())> +} + +async fn async_nop(_: &u8) {} + +pub type ServeFut = impl Future; + +// Late bound regions occur in the generator witness type here. +fn serve() -> ServeFut { + async move { + let x = 5; + async_nop(&x).await + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-60674.rs b/tests/ui/async-await/issues/issue-60674.rs new file mode 100644 index 000000000..c0e34a8df --- /dev/null +++ b/tests/ui/async-await/issues/issue-60674.rs @@ -0,0 +1,19 @@ +// aux-build:issue-60674.rs +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +// This is a regression test that ensures that `mut` patterns are not lost when provided as input +// to a proc macro. + +extern crate issue_60674; + +#[issue_60674::attr] +async fn f(mut x: u8) {} + +#[issue_60674::attr] +async fn g((mut x, y, mut z): (u8, u8, u8)) {} + +#[issue_60674::attr] +async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) {} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-60674.stdout b/tests/ui/async-await/issues/issue-60674.stdout new file mode 100644 index 000000000..6f980e606 --- /dev/null +++ b/tests/ui/async-await/issues/issue-60674.stdout @@ -0,0 +1,3 @@ +async fn f(mut x : u8) {} +async fn g((mut x, y, mut z) : (u8, u8, u8)) {} +async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) {} diff --git a/tests/ui/async-await/issues/issue-61187.rs b/tests/ui/async-await/issues/issue-61187.rs new file mode 100644 index 000000000..8585a4251 --- /dev/null +++ b/tests/ui/async-await/issues/issue-61187.rs @@ -0,0 +1,7 @@ +// edition:2018 + +fn main() {} + +async fn response(data: Vec) { + data.reverse(); //~ ERROR E0596 +} diff --git a/tests/ui/async-await/issues/issue-61187.stderr b/tests/ui/async-await/issues/issue-61187.stderr new file mode 100644 index 000000000..e58f74546 --- /dev/null +++ b/tests/ui/async-await/issues/issue-61187.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable + --> $DIR/issue-61187.rs:6:5 + | +LL | data.reverse(); + | ^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | async fn response(mut data: Vec) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/async-await/issues/issue-61986.rs b/tests/ui/async-await/issues/issue-61986.rs new file mode 100644 index 000000000..879bc6912 --- /dev/null +++ b/tests/ui/async-await/issues/issue-61986.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 +// +// Tests that we properly handle StorageDead/StorageLives for temporaries +// created in async loop bodies. + +async fn bar() -> Option<()> { + Some(()) +} + +async fn listen() { + while let Some(_) = bar().await { + String::new(); + } +} + +fn main() { + listen(); +} diff --git a/tests/ui/async-await/issues/issue-62009-1.rs b/tests/ui/async-await/issues/issue-62009-1.rs new file mode 100644 index 000000000..40ccf2571 --- /dev/null +++ b/tests/ui/async-await/issues/issue-62009-1.rs @@ -0,0 +1,15 @@ +// edition:2018 + +async fn print_dur() {} + +fn main() { + async { let (); }.await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks + async { + let task1 = print_dur().await; + }.await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks + (|_| 2333).await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks + //~| ERROR is not a future +} diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr new file mode 100644 index 000000000..222afb2c7 --- /dev/null +++ b/tests/ui/async-await/issues/issue-62009-1.stderr @@ -0,0 +1,43 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-62009-1.rs:6:22 + | +LL | fn main() { + | ---- this is not `async` +LL | async { let (); }.await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-62009-1.rs:10:6 + | +LL | fn main() { + | ---- this is not `async` +... +LL | }.await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-62009-1.rs:12:15 + | +LL | fn main() { + | ---- this is not `async` +... +LL | (|_| 2333).await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future + --> $DIR/issue-62009-1.rs:12:15 + | +LL | (|_| 2333).await; + | ^^^^^^ + | | + | `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` + = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited + = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0728. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issues/issue-62009-2.rs b/tests/ui/async-await/issues/issue-62009-2.rs new file mode 100644 index 000000000..cb7336e61 --- /dev/null +++ b/tests/ui/async-await/issues/issue-62009-2.rs @@ -0,0 +1,10 @@ +// edition:2018 + +#![feature(async_closure)] + +async fn print_dur() {} + +fn main() { + (async || 2333)().await; + //~^ ERROR `await` is only allowed inside `async` functions and blocks +} diff --git a/tests/ui/async-await/issues/issue-62009-2.stderr b/tests/ui/async-await/issues/issue-62009-2.stderr new file mode 100644 index 000000000..92e9a8a69 --- /dev/null +++ b/tests/ui/async-await/issues/issue-62009-2.stderr @@ -0,0 +1,11 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/issue-62009-2.rs:8:22 + | +LL | fn main() { + | ---- this is not `async` +LL | (async || 2333)().await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/issues/issue-62097.rs b/tests/ui/async-await/issues/issue-62097.rs new file mode 100644 index 000000000..a24c84cff --- /dev/null +++ b/tests/ui/async-await/issues/issue-62097.rs @@ -0,0 +1,21 @@ +// edition:2018 +async fn foo(fun: F) +where + F: FnOnce() + 'static +{ + fun() +} + +struct Struct; + +impl Struct { + pub async fn run_dummy_fn(&self) { + foo(|| self.bar()).await; + //~^ ERROR closure may outlive the current function + //~| ERROR borrowed data escapes outside of associated function + } + + pub fn bar(&self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-62097.stderr b/tests/ui/async-await/issues/issue-62097.stderr new file mode 100644 index 000000000..786f62132 --- /dev/null +++ b/tests/ui/async-await/issues/issue-62097.stderr @@ -0,0 +1,36 @@ +error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function + --> $DIR/issue-62097.rs:13:13 + | +LL | foo(|| self.bar()).await; + | ^^ ---- `self` is borrowed here + | | + | may outlive borrowed value `self` + | +note: function requires argument type to outlive `'static` + --> $DIR/issue-62097.rs:13:9 + | +LL | foo(|| self.bar()).await; + | ^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword + | +LL | foo(move || self.bar()).await; + | ++++ + +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-62097.rs:13:9 + | +LL | pub async fn run_dummy_fn(&self) { + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` +LL | foo(|| self.bar()).await; + | ^^^^^^^^^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0373, E0521. +For more information about an error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/issues/issue-62517-1.rs b/tests/ui/async-await/issues/issue-62517-1.rs new file mode 100644 index 000000000..4689ce36a --- /dev/null +++ b/tests/ui/async-await/issues/issue-62517-1.rs @@ -0,0 +1,21 @@ +// Regression test for #62517. We used to ICE when you had an `async +// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no +// explicit lifetime bound. +// +// edition:2018 +// check-pass + +trait FirstTrait {} +trait SecondTrait { + type Item: ?Sized; +} + +async fn foo(x: &str) -> impl SecondTrait { +} + + +impl SecondTrait for T { + type Item = dyn FirstTrait; +} + +fn main() { } diff --git a/tests/ui/async-await/issues/issue-62517-2.rs b/tests/ui/async-await/issues/issue-62517-2.rs new file mode 100644 index 000000000..aaf28d6c1 --- /dev/null +++ b/tests/ui/async-await/issues/issue-62517-2.rs @@ -0,0 +1,16 @@ +// Regression test for #62517. We used to ICE when you had an `async +// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no +// explicit lifetime bound. +// +// edition:2018 +// check-pass + +trait Object {} + +trait Alpha {} + +async fn foo<'a>(_: &'a ()) -> impl Alpha {} + +impl Alpha for T { } + +fn main() { } diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs new file mode 100644 index 000000000..32bcbb111 --- /dev/null +++ b/tests/ui/async-await/issues/issue-63388-1.rs @@ -0,0 +1,19 @@ +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + &'a self, foo: &dyn Foo + ) -> &dyn Foo + { + //~^ ERROR explicit lifetime required in the type of `foo` [E0621] + foo + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr new file mode 100644 index 000000000..88542315e --- /dev/null +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -0,0 +1,15 @@ +error[E0621]: explicit lifetime required in the type of `foo` + --> $DIR/issue-63388-1.rs:13:5 + | +LL | &'a self, foo: &dyn Foo + | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` +LL | ) -> &dyn Foo +LL | / { +LL | | +LL | | foo +LL | | } + | |_____^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/async-await/issues/issue-63388-2.rs b/tests/ui/async-await/issues/issue-63388-2.rs new file mode 100644 index 000000000..90b59f96e --- /dev/null +++ b/tests/ui/async-await/issues/issue-63388-2.rs @@ -0,0 +1,19 @@ +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + foo: &dyn Foo, bar: &'a dyn Foo + ) -> &dyn Foo //~ ERROR missing lifetime specifier + { + //~^ ERROR explicit lifetime required in the type of `foo` [E0621] + foo + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-63388-2.stderr b/tests/ui/async-await/issues/issue-63388-2.stderr new file mode 100644 index 000000000..e515f227c --- /dev/null +++ b/tests/ui/async-await/issues/issue-63388-2.stderr @@ -0,0 +1,30 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-63388-2.rs:12:10 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | -------- ----------- +LL | ) -> &dyn Foo + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` +help: consider using the `'a` lifetime + | +LL | ) -> &'a dyn Foo + | ++ + +error[E0621]: explicit lifetime required in the type of `foo` + --> $DIR/issue-63388-2.rs:13:5 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` +LL | ) -> &dyn Foo +LL | / { +LL | | +LL | | foo +LL | | } + | |_____^ lifetime `'a` required + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0106, E0621. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/async-await/issues/issue-63388-3.rs b/tests/ui/async-await/issues/issue-63388-3.rs new file mode 100644 index 000000000..1a9822e02 --- /dev/null +++ b/tests/ui/async-await/issues/issue-63388-3.rs @@ -0,0 +1,17 @@ +// edition:2018 +// check-pass + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth( + &self, foo: &dyn Foo + ) { + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-63388-4.rs b/tests/ui/async-await/issues/issue-63388-4.rs new file mode 100644 index 000000000..58f9dacb3 --- /dev/null +++ b/tests/ui/async-await/issues/issue-63388-4.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 + +struct A; + +impl A { + async fn foo(&self, f: &u32) -> &A { self } +} + +fn main() { } diff --git a/tests/ui/async-await/issues/issue-64391-2.rs b/tests/ui/async-await/issues/issue-64391-2.rs new file mode 100644 index 000000000..eef2c1fb2 --- /dev/null +++ b/tests/ui/async-await/issues/issue-64391-2.rs @@ -0,0 +1,20 @@ +// Regression test for #64391 +// +// As described on the issue, the (spurious) `DROP` inserted for the +// `"".to_string()` value was causing a (spurious) unwind path that +// led us to believe that the future might be dropped after `config` +// had been dropped. This cannot, in fact, happen. +// +// check-pass +// edition:2018 + +async fn connect() { + let config = 666; + connect2(&config, "".to_string()).await +} + +async fn connect2(_config: &u32, _tls: String) { + unimplemented!() +} + +fn main() { } diff --git a/tests/ui/async-await/issues/issue-64433.rs b/tests/ui/async-await/issues/issue-64433.rs new file mode 100644 index 000000000..d900f8ed9 --- /dev/null +++ b/tests/ui/async-await/issues/issue-64433.rs @@ -0,0 +1,30 @@ +// Regression test for issue #64433. +// +// See issue-64391-2.rs for more details, as that was fixed by the +// same PR. +// +// check-pass +// edition:2018 + +#[derive(Debug)] +struct A<'a> { + inner: Vec<&'a str>, +} + +struct B {} + +impl B { + async fn something_with_a(&mut self, a: A<'_>) -> Result<(), String> { + println!("{:?}", a); + Ok(()) + } +} + +async fn can_error(some_string: &str) -> Result<(), String> { + let a = A { inner: vec![some_string, "foo"] }; + let mut b = B {}; + Ok(b.something_with_a(a).await.map(drop)?) +} + +fn main() { +} diff --git a/tests/ui/async-await/issues/issue-64477-2.rs b/tests/ui/async-await/issues/issue-64477-2.rs new file mode 100644 index 000000000..2360b57cc --- /dev/null +++ b/tests/ui/async-await/issues/issue-64477-2.rs @@ -0,0 +1,22 @@ +// Another regression test for #64477. +// +// In the past, the code generated by `format!` produced temporaries in the surrounding scope that +// borrowed the arguments through `&dyn Trait`. These temporaries do not implement `Send`, which +// meant that when `format!` was used in an async block, the resulting generator was not `Send`. +// See https://github.com/rust-lang/rust/issues/64477#issuecomment-534669068 for details +// and https://github.com/rust-lang/rust/issues/64477#issuecomment-531882958 for an example. +// +// check-pass +// edition:2018 + +async fn foo(_: String) {} + +fn bar() -> impl Send { + async move { + foo(format!("{}:{}", 1, 2)).await; + } +} + +fn main() { + let _ = bar(); +} diff --git a/tests/ui/async-await/issues/issue-64477.rs b/tests/ui/async-await/issues/issue-64477.rs new file mode 100644 index 000000000..5bd52d44a --- /dev/null +++ b/tests/ui/async-await/issues/issue-64477.rs @@ -0,0 +1,20 @@ +// Regression test for #64477. +// +// We were incorrectly claiming that the `f(x).await` future captured +// a value of type `T`, and hence that `T: Send` would have to hold. +// +// check-pass +// edition:2018 + +use std::future::Future; +use std::pin::Pin; + +fn f(_: &T) -> Pin + Send>> { + unimplemented!() +} + +pub fn g(x: &'static T) -> impl Future + Send { + async move { f(x).await } +} + +fn main() { } diff --git a/tests/ui/async-await/issues/issue-64964.rs b/tests/ui/async-await/issues/issue-64964.rs new file mode 100644 index 000000000..6d6eff486 --- /dev/null +++ b/tests/ui/async-await/issues/issue-64964.rs @@ -0,0 +1,23 @@ +// check-pass +// incremental +// compile-flags: -Z query-dep-graph +// edition:2018 + +// Regression test for ICE related to `await`ing in a method + incr. comp. (#64964) + +struct Body; +impl Body { + async fn next(&mut self) { + async {}.await + } +} + +// Another reproduction: `await`ing with a variable from for-loop. + +async fn bar() { + for x in 0..10 { + async { Some(x) }.await.unwrap(); + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-65159.rs b/tests/ui/async-await/issues/issue-65159.rs new file mode 100644 index 000000000..df2ca0257 --- /dev/null +++ b/tests/ui/async-await/issues/issue-65159.rs @@ -0,0 +1,11 @@ +// Regression test for #65159. We used to ICE. +// +// edition:2018 + +async fn copy() -> Result<()> +//~^ ERROR this enum takes 2 generic arguments +{ + Ok(()) +} + +fn main() { } diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr new file mode 100644 index 000000000..40c0e72b2 --- /dev/null +++ b/tests/ui/async-await/issues/issue-65159.stderr @@ -0,0 +1,16 @@ +error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/issue-65159.rs:5:20 + | +LL | async fn copy() -> Result<()> + | ^^^^^^ -- supplied 1 generic argument + | | + | expected 2 generic arguments + | +help: add missing generic argument + | +LL | async fn copy() -> Result<(), E> + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs new file mode 100644 index 000000000..ade386a60 --- /dev/null +++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs @@ -0,0 +1,46 @@ +// issue 65419 - Attempting to run an async fn after completion mentions generators when it should +// be talking about `async fn`s instead. + +// run-fail +// error-pattern: thread 'main' panicked at '`async fn` resumed after completion' +// edition:2018 +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +#![feature(generators, generator_trait)] + +async fn foo() { +} + +fn main() { + let mut future = Box::pin(foo()); + executor::block_on(future.as_mut()); + executor::block_on(future.as_mut()); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + + static VTABLE: RawWakerVTable = RawWakerVTable::new( + |_| unimplemented!("clone"), + |_| unimplemented!("wake"), + |_| unimplemented!("wake_by_ref"), + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs new file mode 100644 index 000000000..b4ea4c9f6 --- /dev/null +++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs @@ -0,0 +1,52 @@ +// issue 65419 - Attempting to run an async fn after completion mentions generators when it should +// be talking about `async fn`s instead. Should also test what happens when it panics. + +// run-fail +// needs-unwind +// error-pattern: thread 'main' panicked at '`async fn` resumed after panicking' +// edition:2018 +// ignore-wasm no panic or subprocess support + +#![feature(generators, generator_trait)] + +use std::panic; + +async fn foo() { + panic!(); +} + +fn main() { + let mut future = Box::pin(foo()); + panic::catch_unwind(panic::AssertUnwindSafe(|| { + executor::block_on(future.as_mut()); + })); + + executor::block_on(future.as_mut()); +} + +mod executor { + use core::{ + future::Future, + pin::Pin, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + }; + + pub fn block_on(mut future: F) -> F::Output { + let mut future = unsafe { Pin::new_unchecked(&mut future) }; + + static VTABLE: RawWakerVTable = RawWakerVTable::new( + |_| unimplemented!("clone"), + |_| unimplemented!("wake"), + |_| unimplemented!("wake_by_ref"), + |_| (), + ); + let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; + let mut context = Context::from_waker(&waker); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs new file mode 100644 index 000000000..9fc5667d6 --- /dev/null +++ b/tests/ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs @@ -0,0 +1,25 @@ +// issue 65419 - Attempting to run an `async fn` after completion mentions generators when it should +// be talking about `async fn`s instead. Regression test added to make sure generators still +// panic when resumed after completion. + +// run-fail +// error-pattern:generator resumed after completion +// edition:2018 +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +#![feature(generators, generator_trait)] + +use std::{ + ops::Generator, + pin::Pin, +}; + +fn main() { + let mut g = || { + yield; + }; + Pin::new(&mut g).resume(()); // Yields once. + Pin::new(&mut g).resume(()); // Completes here. + Pin::new(&mut g).resume(()); // Panics here. +} diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr new file mode 100644 index 000000000..1033fa6cc --- /dev/null +++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr @@ -0,0 +1,32 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-65436-raw-ptr-not-send.rs:16:17 + | +LL | assert_send(async { + | _________________^ +LL | | +LL | | bar(Foo(std::ptr::null())).await; +LL | | }) + | |_____^ future created by async block is not `Send` + | + = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:16:17: 19:6]`, the trait `Send` is not implemented for `*const u8` +note: future is not `Send` as this value is used across an await + --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35 + | +LL | bar(Foo(std::ptr::null())).await; + | ---------------- ^^^^^^- `std::ptr::null()` is later dropped here + | | | + | | await occurs here, with `std::ptr::null()` maybe used later + | has type `*const u8` which is not `Send` +help: consider moving this into a `let` binding to create a shorter lived borrow + --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13 + | +LL | bar(Foo(std::ptr::null())).await; + | ^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `assert_send` + --> $DIR/issue-65436-raw-ptr-not-send.rs:13:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs new file mode 100644 index 000000000..91edbc10d --- /dev/null +++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs @@ -0,0 +1,20 @@ +// edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] check-pass +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no + +struct Foo(*const u8); + +unsafe impl Send for Foo {} + +async fn bar(_: Foo) {} + +fn assert_send(_: T) {} + +fn main() { + assert_send(async { + //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely + bar(Foo(std::ptr::null())).await; + }) +} diff --git a/tests/ui/async-await/issues/issue-66695-static-refs.rs b/tests/ui/async-await/issues/issue-66695-static-refs.rs new file mode 100644 index 000000000..f0609713b --- /dev/null +++ b/tests/ui/async-await/issues/issue-66695-static-refs.rs @@ -0,0 +1,24 @@ +// build-pass +// edition:2018 + +static A: [i32; 5] = [1, 2, 3, 4, 5]; + +async fn fun() { + let u = A[async { 1 }.await]; + match A { + i if async { true }.await => (), + _ => (), + } +} + +fn main() { + async { + let u = A[async { 1 }.await]; + }; + async { + match A { + i if async { true }.await => (), + _ => (), + } + }; +} diff --git a/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs new file mode 100644 index 000000000..b7a976a0a --- /dev/null +++ b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs @@ -0,0 +1,15 @@ +// edition:2018 + +struct Ia(S); + +impl Ia { + fn partial(_: S) {} + fn full(self) {} + + async fn crash(self) { + Self::partial(self.0); + Self::full(self); //~ ERROR use of partially moved value: `self` + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr new file mode 100644 index 000000000..e2a735398 --- /dev/null +++ b/tests/ui/async-await/issues/issue-66958-non-copy-infered-type-arg.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of partially moved value: `self` + --> $DIR/issue-66958-non-copy-infered-type-arg.rs:11:20 + | +LL | Self::partial(self.0); + | ------ value partially moved here +LL | Self::full(self); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `self.0` has type `S`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs new file mode 100644 index 000000000..dda4a151d --- /dev/null +++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs @@ -0,0 +1,33 @@ +// build-pass +// edition:2018 + +static mut A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn is_send_sync(_: T) {} + +async fn fun() { + let u = unsafe { A[async { 1 }.await] }; + unsafe { + match A { + i if async { true }.await => (), + _ => (), + } + } +} + +fn main() { + let index_block = async { + let u = unsafe { A[async { 1 }.await] }; + }; + let match_block = async { + unsafe { + match A { + i if async { true }.await => (), + _ => (), + } + } + }; + is_send_sync(index_block); + is_send_sync(match_block); + is_send_sync(fun()); +} diff --git a/tests/ui/async-await/issues/issue-67893.rs b/tests/ui/async-await/issues/issue-67893.rs new file mode 100644 index 000000000..d73772e5f --- /dev/null +++ b/tests/ui/async-await/issues/issue-67893.rs @@ -0,0 +1,11 @@ +// aux-build: issue_67893.rs +// edition:2018 + +extern crate issue_67893; + +fn g(_: impl Send) {} + +fn main() { + g(issue_67893::run()) + //~^ ERROR future cannot be sent between threads safely +} diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr new file mode 100644 index 000000000..2ce68a782 --- /dev/null +++ b/tests/ui/async-await/issues/issue-67893.stderr @@ -0,0 +1,23 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-67893.rs:9:7 + | +LL | g(issue_67893::run()) + | ^^^^^^^^^^^^^^^^^^ future is not `Send` + | + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` +note: future is not `Send` as this value is used across an await + --> $DIR/auxiliary/issue_67893.rs:9:26 + | +LL | f(*x.lock().unwrap()).await; + | ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here + | | | + | | await occurs here, with `x.lock().unwrap()` maybe used later + | has type `MutexGuard<'_, ()>` which is not `Send` +note: required by a bound in `g` + --> $DIR/issue-67893.rs:6:14 + | +LL | fn g(_: impl Send) {} + | ^^^^ required by this bound in `g` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/issues/issue-69307-nested.rs b/tests/ui/async-await/issues/issue-69307-nested.rs new file mode 100644 index 000000000..b7cdf3987 --- /dev/null +++ b/tests/ui/async-await/issues/issue-69307-nested.rs @@ -0,0 +1,30 @@ +// Regression test for #69307 +// +// Having a `async { .. foo.await .. }` block appear inside of a `+=` +// expression was causing an ICE due to a failure to save/restore +// state in the AST numbering pass when entering a nested body. +// +// check-pass +// edition:2018 + +fn block_on(_: F) -> usize { + 0 +} + +fn main() {} + +async fn bar() { + let mut sum = 0; + sum += { + block_on(async { + baz().await; + let mut inner = 1; + inner += block_on(async { + baz().await; + 0 + }) + }) + }; +} + +async fn baz() {} diff --git a/tests/ui/async-await/issues/issue-69307.rs b/tests/ui/async-await/issues/issue-69307.rs new file mode 100644 index 000000000..59309a7f2 --- /dev/null +++ b/tests/ui/async-await/issues/issue-69307.rs @@ -0,0 +1,23 @@ +// Regression test for #69307 +// +// Having an `async { .. foo.await .. }` block appear inside of a `+=` +// expression was causing an ICE due to a failure to save/restore +// state in the AST numbering pass when entering a nested body. +// +// check-pass +// edition:2018 + +fn block_on(_: F) -> usize { + 0 +} + +fn main() {} + +async fn bar() { + let mut sum = 0; + sum += block_on(async { + baz().await; + }); +} + +async fn baz() {} diff --git a/tests/ui/async-await/issues/issue-72312.rs b/tests/ui/async-await/issues/issue-72312.rs new file mode 100644 index 000000000..74122cf00 --- /dev/null +++ b/tests/ui/async-await/issues/issue-72312.rs @@ -0,0 +1,21 @@ +// edition:2018 +fn require_static(val: T) -> T { + val +} + +struct Problem; + +impl Problem { + pub async fn start(&self) { + //~^ NOTE let's call + //~| NOTE `self` is a reference + require_static(async move { + //~^ ERROR borrowed data escapes + //~| NOTE `self` escapes + //~| NOTE argument requires + &self; + }); + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr new file mode 100644 index 000000000..aa947b690 --- /dev/null +++ b/tests/ui/async-await/issues/issue-72312.stderr @@ -0,0 +1,23 @@ +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-72312.rs:12:9 + | +LL | pub async fn start(&self) { + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` +... +LL | / require_static(async move { +LL | | +LL | | +LL | | +LL | | &self; +LL | | }); + | | ^ + | | | + | |__________`self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/async-await/issues/issue-78600.rs b/tests/ui/async-await/issues/issue-78600.rs new file mode 100644 index 000000000..8aaeaecf3 --- /dev/null +++ b/tests/ui/async-await/issues/issue-78600.rs @@ -0,0 +1,12 @@ +// edition:2018 + +struct S<'a>(&'a i32); + +impl<'a> S<'a> { + async fn new(i: &'a i32) -> Result { + //~^ ERROR: `async fn` + Ok(S(&22)) + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-78600.stderr b/tests/ui/async-await/issues/issue-78600.stderr new file mode 100644 index 000000000..37eafa996 --- /dev/null +++ b/tests/ui/async-await/issues/issue-78600.stderr @@ -0,0 +1,14 @@ +error[E0658]: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/issue-78600.rs:6:33 + | +LL | async fn new(i: &'a i32) -> Result { + | ^^^^^^^----^^^^^ + | | + | help: consider spelling out the type instead: `S<'a>` + | + = note: see issue #103532 for more information + = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/issues/issue-78654.full.stderr b/tests/ui/async-await/issues/issue-78654.full.stderr new file mode 100644 index 000000000..0d12a948c --- /dev/null +++ b/tests/ui/async-await/issues/issue-78654.full.stderr @@ -0,0 +1,19 @@ +error[E0573]: expected type, found built-in attribute `feature` + --> $DIR/issue-78654.rs:9:15 + | +LL | impl Foo { + | ^^^^^^^ not a type + +error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-78654.rs:9:6 + | +LL | impl Foo { + | ^^^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0207, E0573. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/async-await/issues/issue-78654.min.stderr b/tests/ui/async-await/issues/issue-78654.min.stderr new file mode 100644 index 000000000..0d12a948c --- /dev/null +++ b/tests/ui/async-await/issues/issue-78654.min.stderr @@ -0,0 +1,19 @@ +error[E0573]: expected type, found built-in attribute `feature` + --> $DIR/issue-78654.rs:9:15 + | +LL | impl Foo { + | ^^^^^^^ not a type + +error[E0207]: the const parameter `H` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-78654.rs:9:6 + | +LL | impl Foo { + | ^^^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0207, E0573. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/async-await/issues/issue-78654.rs b/tests/ui/async-await/issues/issue-78654.rs new file mode 100644 index 000000000..cc6dc3834 --- /dev/null +++ b/tests/ui/async-await/issues/issue-78654.rs @@ -0,0 +1,15 @@ +// edition:2018 +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo; + +impl Foo { +//~^ ERROR: expected type, found built-in attribute `feature` +//~^^ ERROR: the const parameter `H` is not constrained by the impl trait, self type, or predicates + async fn biz() {} +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-78938-async-block.rs b/tests/ui/async-await/issues/issue-78938-async-block.rs new file mode 100644 index 000000000..36f716019 --- /dev/null +++ b/tests/ui/async-await/issues/issue-78938-async-block.rs @@ -0,0 +1,33 @@ +// edition:2018 + +use std::{sync::Arc, future::Future, pin::Pin, task::{Context, Poll}}; + +async fn f() { + let room_ref = Arc::new(Vec::new()); + + let gameloop_handle = spawn(async { //~ ERROR E0373 + game_loop(Arc::clone(&room_ref)) + }); + gameloop_handle.await; +} + +fn game_loop(v: Arc>) {} + +fn spawn(future: F) -> JoinHandle +where + F: Future + Send + 'static, + F::Output: Send + 'static, +{ + loop {} +} + +struct JoinHandle; + +impl Future for JoinHandle { + type Output = (); + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + loop {} + } +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-78938-async-block.stderr b/tests/ui/async-await/issues/issue-78938-async-block.stderr new file mode 100644 index 000000000..c1a4b467f --- /dev/null +++ b/tests/ui/async-await/issues/issue-78938-async-block.stderr @@ -0,0 +1,19 @@ +error[E0373]: async block may outlive the current function, but it borrows `room_ref`, which is owned by the current function + --> $DIR/issue-78938-async-block.rs:8:33 + | +LL | let gameloop_handle = spawn(async { + | _________________________________^ +LL | | game_loop(Arc::clone(&room_ref)) + | | -------- `room_ref` is borrowed here +LL | | }); + | |_____^ may outlive borrowed value `room_ref` + | + = note: async blocks are not executed immediately and must either take a reference or ownership of outside variables they use +help: to force the async block to take ownership of `room_ref` (and any other referenced variables), use the `move` keyword + | +LL | let gameloop_handle = spawn(async move { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/async-await/issues/issue-95307.rs b/tests/ui/async-await/issues/issue-95307.rs new file mode 100644 index 000000000..f7e48070c --- /dev/null +++ b/tests/ui/async-await/issues/issue-95307.rs @@ -0,0 +1,13 @@ +// edition:2018 + +// Regression test for #95307. +// The ICE occurred on all the editions, specifying edition:2018 to reduce diagnostics. + +pub trait C { + async fn new() -> [u8; _]; + //~^ ERROR: functions in traits cannot be declared `async` + //~| ERROR: using `_` for array lengths is unstable + //~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment +} + +fn main() {} diff --git a/tests/ui/async-await/issues/issue-95307.stderr b/tests/ui/async-await/issues/issue-95307.stderr new file mode 100644 index 000000000..a497cebe3 --- /dev/null +++ b/tests/ui/async-await/issues/issue-95307.stderr @@ -0,0 +1,32 @@ +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/issue-95307.rs:7:5 + | +LL | async fn new() -> [u8; _]; + | -----^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/issue-95307.rs:7:28 + | +LL | async fn new() -> [u8; _]; + | ^ `_` not allowed here + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/issue-95307.rs:7:28 + | +LL | async fn new() -> [u8; _]; + | ^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0658, E0706. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.rs b/tests/ui/async-await/issues/non-async-enclosing-span.rs new file mode 100644 index 000000000..d47c21377 --- /dev/null +++ b/tests/ui/async-await/issues/non-async-enclosing-span.rs @@ -0,0 +1,11 @@ +// edition:2018 + +async fn do_the_thing() -> u8 { + 8 +} +// #63398: point at the enclosing scope and not the previously seen closure +fn main() { //~ NOTE this is not `async` + let x = move || {}; + let y = do_the_thing().await; //~ ERROR `await` is only allowed inside `async` functions + //~^ NOTE only allowed inside `async` functions and blocks +} diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.stderr b/tests/ui/async-await/issues/non-async-enclosing-span.stderr new file mode 100644 index 000000000..20b827479 --- /dev/null +++ b/tests/ui/async-await/issues/non-async-enclosing-span.stderr @@ -0,0 +1,12 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/non-async-enclosing-span.rs:9:27 + | +LL | fn main() { + | ---- this is not `async` +LL | let x = move || {}; +LL | let y = do_the_thing().await; + | ^^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0728`. diff --git a/tests/ui/async-await/large_moves.attribute.stderr b/tests/ui/async-await/large_moves.attribute.stderr new file mode 100644 index 000000000..0c5452475 --- /dev/null +++ b/tests/ui/async-await/large_moves.attribute.stderr @@ -0,0 +1,45 @@ +error: moving 10024 bytes + --> $DIR/large_moves.rs:13:13 + | +LL | let x = async { + | _____________^ +LL | | let y = [0; 9999]; +LL | | dbg!(y); +LL | | thing(&y).await; +LL | | dbg!(y); +LL | | }; + | |_____^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/large_moves.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 10024 bytes + --> $DIR/large_moves.rs:19:14 + | +LL | let z = (x, 42); + | ^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: moving 10024 bytes + --> $DIR/large_moves.rs:19:13 + | +LL | let z = (x, 42); + | ^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: moving 10024 bytes + --> $DIR/large_moves.rs:21:13 + | +LL | let a = z.0; + | ^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/large_moves.option.stderr b/tests/ui/async-await/large_moves.option.stderr new file mode 100644 index 000000000..0c5452475 --- /dev/null +++ b/tests/ui/async-await/large_moves.option.stderr @@ -0,0 +1,45 @@ +error: moving 10024 bytes + --> $DIR/large_moves.rs:13:13 + | +LL | let x = async { + | _____________^ +LL | | let y = [0; 9999]; +LL | | dbg!(y); +LL | | thing(&y).await; +LL | | dbg!(y); +LL | | }; + | |_____^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/large_moves.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: moving 10024 bytes + --> $DIR/large_moves.rs:19:14 + | +LL | let z = (x, 42); + | ^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: moving 10024 bytes + --> $DIR/large_moves.rs:19:13 + | +LL | let z = (x, 42); + | ^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: moving 10024 bytes + --> $DIR/large_moves.rs:21:13 + | +LL | let a = z.0; + | ^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/large_moves.rs b/tests/ui/async-await/large_moves.rs new file mode 100644 index 000000000..d43d0eec0 --- /dev/null +++ b/tests/ui/async-await/large_moves.rs @@ -0,0 +1,27 @@ +#![deny(large_assignments)] +#![feature(large_assignments)] +#![cfg_attr(attribute, move_size_limit = "1000")] +// build-fail +// only-x86_64 +// revisions: attribute option +// [option]compile-flags: -Zmove-size-limit=1000 + +// edition:2018 +// compile-flags: -Zmir-opt-level=0 + +fn main() { + let x = async { //~ ERROR large_assignments + let y = [0; 9999]; + dbg!(y); + thing(&y).await; + dbg!(y); + }; + let z = (x, 42); //~ ERROR large_assignments + //~^ ERROR large_assignments + let a = z.0; //~ ERROR large_assignments + let b = z.1; +} + +async fn thing(y: &[u8]) { + dbg!(y); +} diff --git a/tests/ui/async-await/move-part-await-return-rest-struct.rs b/tests/ui/async-await/move-part-await-return-rest-struct.rs new file mode 100644 index 000000000..39ea2aae5 --- /dev/null +++ b/tests/ui/async-await/move-part-await-return-rest-struct.rs @@ -0,0 +1,18 @@ +// build-pass +// edition:2018 +// compile-flags: --crate-type lib + +struct Small { + x: Vec, + y: Vec, +} + +// You are allowed to move out part of a struct to an async fn, you still +// have access to remaining parts after awaiting +async fn move_part_await_return_rest_struct() -> Vec { + let s = Small { x: vec![31], y: vec![19, 1441] }; + needs_vec(s.x).await; + s.y +} + +async fn needs_vec(_vec: Vec) {} diff --git a/tests/ui/async-await/move-part-await-return-rest-tuple.rs b/tests/ui/async-await/move-part-await-return-rest-tuple.rs new file mode 100644 index 000000000..7b958b98b --- /dev/null +++ b/tests/ui/async-await/move-part-await-return-rest-tuple.rs @@ -0,0 +1,12 @@ +// build-pass +// edition:2018 +// compile-flags: --crate-type lib + +async fn move_part_await_return_rest_tuple() -> Vec { + let x = (vec![3], vec![4, 4]); + drop(x.1); + echo(x.0[0]).await; + x.0 +} + +async fn echo(x: usize) -> usize { x } diff --git a/tests/ui/async-await/multiple-lifetimes/elided.rs b/tests/ui/async-await/multiple-lifetimes/elided.rs new file mode 100644 index 000000000..8258e2eff --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/elided.rs @@ -0,0 +1,10 @@ +// edition:2018 +// run-pass + +// Test that we can use async fns with multiple arbitrary lifetimes. + +async fn multiple_elided_lifetimes(_: &u8, _: &u8) {} + +fn main() { + let _ = multiple_elided_lifetimes(&22, &44); +} diff --git a/tests/ui/async-await/multiple-lifetimes/fn-ptr.rs b/tests/ui/async-await/multiple-lifetimes/fn-ptr.rs new file mode 100644 index 000000000..3912b8547 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/fn-ptr.rs @@ -0,0 +1,12 @@ +// edition:2018 +// run-pass + +// Test that we can use async fns with multiple arbitrary lifetimes. + +async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {} + +fn gimme(_: &u8) { } + +fn main() { + let _ = multiple_named_lifetimes(&22, &44, gimme); +} diff --git a/tests/ui/async-await/multiple-lifetimes/hrtb.rs b/tests/ui/async-await/multiple-lifetimes/hrtb.rs new file mode 100644 index 000000000..e788ca5ff --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/hrtb.rs @@ -0,0 +1,14 @@ +// edition:2018 +// check-pass + +// Test that we can use async fns with multiple arbitrary lifetimes. + +use std::ops::Add; + +async fn multiple_hrtb_and_single_named_lifetime_ok<'c>( + _: impl for<'a> Add<&'a u8>, + _: impl for<'b> Add<&'b u8>, + _: &'c u8, +) {} + +fn main() {} diff --git a/tests/ui/async-await/multiple-lifetimes/named.rs b/tests/ui/async-await/multiple-lifetimes/named.rs new file mode 100644 index 000000000..e8eb98102 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/named.rs @@ -0,0 +1,10 @@ +// edition:2018 +// run-pass + +// Test that we can use async fns with multiple arbitrary lifetimes. + +async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {} + +fn main() { + let _ = multiple_named_lifetimes(&22, &44); +} diff --git a/tests/ui/async-await/multiple-lifetimes/partial-relation.rs b/tests/ui/async-await/multiple-lifetimes/partial-relation.rs new file mode 100644 index 000000000..02b105999 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/partial-relation.rs @@ -0,0 +1,13 @@ +// edition:2018 +// run-pass + +async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32) + where 'b: 'a +{ + drop((a, c)); + (b, b) +} + +fn main() { + let _ = lotsa_lifetimes(&22, &44, &66); +} diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs new file mode 100644 index 000000000..f1002947f --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs @@ -0,0 +1,17 @@ +// edition:2018 +// run-pass + +// Test member constraints that appear in the `impl Trait` +// return type of an async function. +// (This used to require a feature gate.) + +trait Trait<'a, 'b> { } +impl Trait<'_, '_> for T { } + +async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { + (a, b) +} + +fn main() { + let _ = async_ret_impl_trait(&22, &44); +} diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs new file mode 100644 index 000000000..aebc77d26 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs @@ -0,0 +1,31 @@ +// edition:2018 + +// Test that a feature gate is needed to use `impl Trait` as the +// return type of an async. + +trait Trait<'a> { } +impl Trait<'_> for T { } + +// Fails to recognize that both 'a and 'b are mentioned and should thus be accepted +async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + //~^ ERROR lifetime may not live long enough + (a, b) +} + +// Only `'a` permitted in return type, not `'b`. +async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + //~^ ERROR captures lifetime that does not appear in bounds + (a, b) +} + +// As above, but `'b: 'a`, so return type can be inferred to `(&'a u8, +// &'a u8)`. +async fn async_ret_impl_trait2<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> +where + 'b: 'a, +{ + (a, b) +} + +fn main() { +} diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr new file mode 100644 index 000000000..ae4d0d585 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr @@ -0,0 +1,35 @@ +error: lifetime may not live long enough + --> $DIR/ret-impl-trait-one.rs:10:85 + | +LL | async fn async_ret_impl_trait3<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ________________________________--__--_______________________________________________^ + | | | | + | | | lifetime `'b` defined here + | | lifetime `'a` defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not appear in bounds + --> $DIR/ret-impl-trait-one.rs:16:80 + | +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> { + | ____________________________________--__________________________________________^ + | | | + | | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here +LL | | +LL | | (a, b) +LL | | } + | |_^ + | +help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/async-await/multiple-lifetimes/ret-ref.rs b/tests/ui/async-await/multiple-lifetimes/ret-ref.rs new file mode 100644 index 000000000..149c020f9 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/ret-ref.rs @@ -0,0 +1,44 @@ +// edition:2018 + +// Test that we get the expected borrow check errors when an async +// function (which takes multiple lifetimes) only returns data from +// one of them. + +async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 { + a +} + +// Both are borrowed whilst the future is live. +async fn future_live() { + let mut a = 22; + let mut b = 44; + let future = multiple_named_lifetimes(&a, &b); + a += 1; //~ ERROR cannot assign + b += 1; //~ ERROR cannot assign + let p = future.await; + drop(p); +} + +// Just the return value is live after future is awaited. +async fn just_return_live() { + let mut a = 22; + let mut b = 44; + let future = multiple_named_lifetimes(&a, &b); + let p = future.await; + a += 1; //~ ERROR cannot assign + b += 1; + drop(p); +} + +// Once `p` is dead, both `a` and `b` are unborrowed. +async fn after_both_dead() { + let mut a = 22; + let mut b = 44; + let future = multiple_named_lifetimes(&a, &b); + let p = future.await; + drop(p); + a += 1; + b += 1; +} + +fn main() { } diff --git a/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr b/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr new file mode 100644 index 000000000..d86e84033 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr @@ -0,0 +1,37 @@ +error[E0506]: cannot assign to `a` because it is borrowed + --> $DIR/ret-ref.rs:16:5 + | +LL | let future = multiple_named_lifetimes(&a, &b); + | -- borrow of `a` occurs here +LL | a += 1; + | ^^^^^^ assignment to borrowed `a` occurs here +LL | b += 1; +LL | let p = future.await; + | ------ borrow later used here + +error[E0506]: cannot assign to `b` because it is borrowed + --> $DIR/ret-ref.rs:17:5 + | +LL | let future = multiple_named_lifetimes(&a, &b); + | -- borrow of `b` occurs here +LL | a += 1; +LL | b += 1; + | ^^^^^^ assignment to borrowed `b` occurs here +LL | let p = future.await; + | ------ borrow later used here + +error[E0506]: cannot assign to `a` because it is borrowed + --> $DIR/ret-ref.rs:28:5 + | +LL | let future = multiple_named_lifetimes(&a, &b); + | -- borrow of `a` occurs here +LL | let p = future.await; +LL | a += 1; + | ^^^^^^ assignment to borrowed `a` occurs here +LL | b += 1; +LL | drop(p); + | - borrow later used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/async-await/multiple-lifetimes/variance.rs b/tests/ui/async-await/multiple-lifetimes/variance.rs new file mode 100644 index 000000000..6ed8bef95 --- /dev/null +++ b/tests/ui/async-await/multiple-lifetimes/variance.rs @@ -0,0 +1,15 @@ +// edition:2018 +// run-pass + +// Test for async fn where the parameters have distinct lifetime +// parameters that appear in all possible variances. + +async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { } + +fn take_any(_: &u8) { } +fn identify(x: &u8) -> &u8 { x } +fn give_back() -> &'static u8 { &22 } + +fn main() { + let _ = lotsa_lifetimes(take_any, identify, give_back); +} diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs new file mode 100644 index 000000000..bb2a61f03 --- /dev/null +++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs @@ -0,0 +1,13 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +async fn rec_1() { //~ ERROR recursion in an `async fn` + rec_2().await; +} + +async fn rec_2() { //~ ERROR recursion in an `async fn` + rec_1().await; +} + +fn main() {} diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr new file mode 100644 index 000000000..f789ad2a0 --- /dev/null +++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr @@ -0,0 +1,21 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18 + | +LL | async fn rec_1() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18 + | +LL | async fn rec_2() { + | ^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/nested-in-impl.rs b/tests/ui/async-await/nested-in-impl.rs new file mode 100644 index 000000000..76ed827d5 --- /dev/null +++ b/tests/ui/async-await/nested-in-impl.rs @@ -0,0 +1,15 @@ +// Test that async fn works when nested inside of +// impls with lifetime parameters. +// +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + fn test() { + async fn test() {} + } +} + +fn main() { } diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs new file mode 100644 index 000000000..963460c11 --- /dev/null +++ b/tests/ui/async-await/no-async-const.rs @@ -0,0 +1,5 @@ +// edition:2018 +// compile-flags: --crate-type lib + +pub async const fn x() {} +//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` diff --git a/tests/ui/async-await/no-async-const.stderr b/tests/ui/async-await/no-async-const.stderr new file mode 100644 index 000000000..a51dc88a4 --- /dev/null +++ b/tests/ui/async-await/no-async-const.stderr @@ -0,0 +1,13 @@ +error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const` + --> $DIR/no-async-const.rs:4:11 + | +LL | pub async const fn x() {} + | ------^^^^^ + | | | + | | expected one of `extern`, `fn`, or `unsafe` + | help: `const` must come before `async`: `const async` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: aborting due to previous error + diff --git a/tests/ui/async-await/no-const-async.rs b/tests/ui/async-await/no-const-async.rs new file mode 100644 index 000000000..cfb0ef1b3 --- /dev/null +++ b/tests/ui/async-await/no-const-async.rs @@ -0,0 +1,6 @@ +// edition:2018 +// compile-flags: --crate-type lib + +pub const async fn x() {} +//~^ ERROR functions cannot be both `const` and `async` +//~| ERROR cycle detected diff --git a/tests/ui/async-await/no-const-async.stderr b/tests/ui/async-await/no-const-async.stderr new file mode 100644 index 000000000..c5bd520aa --- /dev/null +++ b/tests/ui/async-await/no-const-async.stderr @@ -0,0 +1,42 @@ +error: functions cannot be both `const` and `async` + --> $DIR/no-const-async.rs:4:5 + | +LL | pub const async fn x() {} + | ----^^^^^-^^^^^---------- + | | | + | | `async` because of this + | `const` because of this + +error[E0391]: cycle detected when computing type of `x::{opaque#0}` + --> $DIR/no-const-async.rs:4:24 + | +LL | pub const async fn x() {} + | ^ + | +note: ...which requires borrow-checking `x`... + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `x`... + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `x`... + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/no-const-async.rs:4:1 + | +LL | pub const async fn x() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/async-await/no-move-across-await-struct.rs b/tests/ui/async-await/no-move-across-await-struct.rs new file mode 100644 index 000000000..51c9a42b3 --- /dev/null +++ b/tests/ui/async-await/no-move-across-await-struct.rs @@ -0,0 +1,16 @@ +// edition:2018 +// compile-flags: --crate-type lib + +async fn no_move_across_await_struct() -> Vec { + let s = Small { x: vec![31], y: vec![19, 1441] }; + needs_vec(s.x).await; + s.x + //~^ ERROR use of moved value: `s.x` +} + +struct Small { + x: Vec, + y: Vec, +} + +async fn needs_vec(_vec: Vec) {} diff --git a/tests/ui/async-await/no-move-across-await-struct.stderr b/tests/ui/async-await/no-move-across-await-struct.stderr new file mode 100644 index 000000000..4eaed1cf1 --- /dev/null +++ b/tests/ui/async-await/no-move-across-await-struct.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `s.x` + --> $DIR/no-move-across-await-struct.rs:7:5 + | +LL | needs_vec(s.x).await; + | --- value moved here +LL | s.x + | ^^^ value used here after move + | + = note: move occurs because `s.x` has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/no-move-across-await-tuple.rs b/tests/ui/async-await/no-move-across-await-tuple.rs new file mode 100644 index 000000000..a65633269 --- /dev/null +++ b/tests/ui/async-await/no-move-across-await-tuple.rs @@ -0,0 +1,12 @@ +// edition:2018 +// compile-flags: --crate-type lib + +async fn no_move_across_await_tuple() -> Vec { + let x = (vec![3], vec![4, 4]); + drop(x.1); + nothing().await; + x.1 + //~^ ERROR use of moved value: `x.1` +} + +async fn nothing() {} diff --git a/tests/ui/async-await/no-move-across-await-tuple.stderr b/tests/ui/async-await/no-move-across-await-tuple.stderr new file mode 100644 index 000000000..d750df991 --- /dev/null +++ b/tests/ui/async-await/no-move-across-await-tuple.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `x.1` + --> $DIR/no-move-across-await-tuple.rs:8:5 + | +LL | drop(x.1); + | --- value moved here +LL | nothing().await; +LL | x.1 + | ^^^ value used here after move + | + = note: move occurs because `x.1` has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/no-non-guaranteed-initialization.rs b/tests/ui/async-await/no-non-guaranteed-initialization.rs new file mode 100644 index 000000000..c4d81bf83 --- /dev/null +++ b/tests/ui/async-await/no-non-guaranteed-initialization.rs @@ -0,0 +1,12 @@ +// edition:2018 +// compile-flags: --crate-type lib + +async fn no_non_guaranteed_initialization(x: usize) -> usize { + let y; + if x > 5 { + y = echo(10).await; + } + y //~ ERROR E0381 +} + +async fn echo(x: usize) -> usize { x + 1 } diff --git a/tests/ui/async-await/no-non-guaranteed-initialization.stderr b/tests/ui/async-await/no-non-guaranteed-initialization.stderr new file mode 100644 index 000000000..12c15bf56 --- /dev/null +++ b/tests/ui/async-await/no-non-guaranteed-initialization.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `y` is possibly-uninitialized + --> $DIR/no-non-guaranteed-initialization.rs:9:5 + | +LL | let y; + | - binding declared here but left uninitialized +LL | if x > 5 { + | ----- if this `if` condition is `false`, `y` is not initialized +LL | y = echo(10).await; +LL | } + | - an `else` arm might be missing here, initializing `y` +LL | y + | ^ `y` used here but it is possibly-uninitialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/async-await/no-params-non-move-async-closure.rs b/tests/ui/async-await/no-params-non-move-async-closure.rs new file mode 100644 index 000000000..3b15f35c2 --- /dev/null +++ b/tests/ui/async-await/no-params-non-move-async-closure.rs @@ -0,0 +1,8 @@ +// edition:2018 + +#![feature(async_closure)] + +fn main() { + let _ = async |x: u8| {}; + //~^ ERROR `async` non-`move` closures with parameters are not currently supported +} diff --git a/tests/ui/async-await/no-params-non-move-async-closure.stderr b/tests/ui/async-await/no-params-non-move-async-closure.stderr new file mode 100644 index 000000000..1f589c516 --- /dev/null +++ b/tests/ui/async-await/no-params-non-move-async-closure.stderr @@ -0,0 +1,11 @@ +error[E0708]: `async` non-`move` closures with parameters are not currently supported + --> $DIR/no-params-non-move-async-closure.rs:6:13 + | +LL | let _ = async |x: u8| {}; + | ^^^^^^^^^^^^^ + | + = help: consider using `let` statements to manually capture variables by reference before entering an `async move` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0708`. diff --git a/tests/ui/async-await/no-std.rs b/tests/ui/async-await/no-std.rs new file mode 100644 index 000000000..63e93cdff --- /dev/null +++ b/tests/ui/async-await/no-std.rs @@ -0,0 +1,13 @@ +// edition:2018 +// check-pass + +#![no_std] +#![crate_type = "rlib"] + +use core::future::Future; + +async fn a(f: impl Future) { + f.await; +} + +fn main() {} diff --git a/tests/ui/async-await/no-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs new file mode 100644 index 000000000..f40154e16 --- /dev/null +++ b/tests/ui/async-await/no-unsafe-async.rs @@ -0,0 +1,11 @@ +// edition:2018 + +struct S; + +impl S { + #[cfg(FALSE)] + unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` +} + +#[cfg(FALSE)] +unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` diff --git a/tests/ui/async-await/no-unsafe-async.stderr b/tests/ui/async-await/no-unsafe-async.stderr new file mode 100644 index 000000000..f23d17d6b --- /dev/null +++ b/tests/ui/async-await/no-unsafe-async.stderr @@ -0,0 +1,29 @@ +error: expected one of `extern` or `fn`, found keyword `async` + --> $DIR/no-unsafe-async.rs:7:12 + | +LL | impl S { + | - while parsing this item list starting here +LL | #[cfg(FALSE)] +LL | unsafe async fn g() {} + | -------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `async` must come before `unsafe`: `async unsafe` +LL | } + | - the item list ends here + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: expected one of `extern` or `fn`, found keyword `async` + --> $DIR/no-unsafe-async.rs:11:8 + | +LL | unsafe async fn f() {} + | -------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `async` must come before `unsafe`: `async unsafe` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs new file mode 100644 index 000000000..a3167215d --- /dev/null +++ b/tests/ui/async-await/non-trivial-drop.rs @@ -0,0 +1,36 @@ +// build-pass +// edition:2018 +// compile-flags: -Zdrop-tracking=y + +#![feature(generators)] + +fn main() { + let _ = foo(); +} + +fn foo() { + || { + yield drop(Config { + nickname: NonCopy, + b: NonCopy2, + }.nickname); + }; +} + +#[derive(Default)] +struct NonCopy; +impl Drop for NonCopy { + fn drop(&mut self) {} +} + +#[derive(Default)] +struct NonCopy2; +impl Drop for NonCopy2 { + fn drop(&mut self) {} +} + +#[derive(Default)] +struct Config { + nickname: NonCopy, + b: NonCopy2, +} diff --git a/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr new file mode 100644 index 000000000..17b4ef7bd --- /dev/null +++ b/tests/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr @@ -0,0 +1,35 @@ +error[E0277]: `NotSend` cannot be sent between threads safely + --> $DIR/partial-drop-partial-reinit.rs:9:16 + | +LL | gimme_send(foo()); + | ---------- ^^^^^ `NotSend` cannot be sent between threads safely + | | + | required by a bound introduced by this call +... +LL | async fn foo() { + | - within this `impl Future` + | + = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` + = note: required because it appears within the type `(NotSend,)` + = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future` +note: required because it's used within this `async fn` body + --> $DIR/partial-drop-partial-reinit.rs:31:16 + | +LL | async fn foo() { + | ________________^ +LL | | +LL | | +LL | | let mut x = (NotSend {},); +... | +LL | | bar().await; +LL | | } + | |_^ +note: required by a bound in `gimme_send` + --> $DIR/partial-drop-partial-reinit.rs:17:18 + | +LL | fn gimme_send(t: T) { + | ^^^^ required by this bound in `gimme_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr new file mode 100644 index 000000000..34d8a159f --- /dev/null +++ b/tests/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr @@ -0,0 +1,35 @@ +error[E0277]: `NotSend` cannot be sent between threads safely + --> $DIR/partial-drop-partial-reinit.rs:9:16 + | +LL | gimme_send(foo()); + | ---------- ^^^^^ `NotSend` cannot be sent between threads safely + | | + | required by a bound introduced by this call +... +LL | async fn foo() { + | - within this `impl Future` + | + = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` + = note: required because it appears within the type `(NotSend,)` + = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future`, `()` +note: required because it's used within this `async fn` body + --> $DIR/partial-drop-partial-reinit.rs:31:16 + | +LL | async fn foo() { + | ________________^ +LL | | +LL | | +LL | | let mut x = (NotSend {},); +... | +LL | | bar().await; +LL | | } + | |_^ +note: required by a bound in `gimme_send` + --> $DIR/partial-drop-partial-reinit.rs:17:18 + | +LL | fn gimme_send(t: T) { + | ^^^^ required by this bound in `gimme_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/partial-drop-partial-reinit.rs b/tests/ui/async-await/partial-drop-partial-reinit.rs new file mode 100644 index 000000000..7d097e72f --- /dev/null +++ b/tests/ui/async-await/partial-drop-partial-reinit.rs @@ -0,0 +1,40 @@ +// edition:2021 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no +#![feature(negative_impls)] +#![allow(unused)] + +fn main() { + gimme_send(foo()); + //~^ ERROR cannot be sent between threads safely + //~| NOTE cannot be sent + //~| NOTE bound introduced by + //~| NOTE appears within the type + //~| NOTE captures the following types +} + +fn gimme_send(t: T) { + //~^ NOTE required by this bound + //~| NOTE required by a bound + drop(t); +} + +struct NotSend {} + +impl Drop for NotSend { + fn drop(&mut self) {} +} + +impl !Send for NotSend {} + +async fn foo() { + //~^ NOTE used within this `async fn` body + //~| NOTE within this `impl Future + let mut x = (NotSend {},); + drop(x.0); + x.0 = NotSend {}; + bar().await; +} + +async fn bar() {} diff --git a/tests/ui/async-await/partial-initialization-across-await.rs b/tests/ui/async-await/partial-initialization-across-await.rs new file mode 100644 index 000000000..7577aee3f --- /dev/null +++ b/tests/ui/async-await/partial-initialization-across-await.rs @@ -0,0 +1,39 @@ +// Test that we don't allow awaiting from an async fn while a local is partially +// initialized. + +// edition:2018 + +struct S { x: i32, y: i32 } +struct T(i32, i32); + +async fn noop() {} + +async fn test_tuple() { + let mut t: (i32, i32); + t.0 = 42; //~ ERROR E0381 + noop().await; + t.1 = 88; + let _ = t; +} + +async fn test_tuple_struct() { + let mut t: T; + t.0 = 42; //~ ERROR E0381 + noop().await; + t.1 = 88; + let _ = t; +} + +async fn test_struct() { + let mut t: S; + t.x = 42; //~ ERROR E0381 + noop().await; + t.y = 88; + let _ = t; +} + +fn main() { + let _ = test_tuple(); + let _ = test_tuple_struct(); + let _ = test_struct(); +} diff --git a/tests/ui/async-await/partial-initialization-across-await.stderr b/tests/ui/async-await/partial-initialization-across-await.stderr new file mode 100644 index 000000000..6a0eeffb9 --- /dev/null +++ b/tests/ui/async-await/partial-initialization-across-await.stderr @@ -0,0 +1,33 @@ +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-await.rs:13:5 + | +LL | let mut t: (i32, i32); + | ----- binding declared here but left uninitialized +LL | t.0 = 42; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-await.rs:21:5 + | +LL | let mut t: T; + | ----- binding declared here but left uninitialized +LL | t.0 = 42; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-await.rs:29:5 + | +LL | let mut t: S; + | ----- binding declared here but left uninitialized +LL | t.x = 42; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/async-await/pin-needed-to-poll-2.rs b/tests/ui/async-await/pin-needed-to-poll-2.rs new file mode 100644 index 000000000..6ce70336d --- /dev/null +++ b/tests/ui/async-await/pin-needed-to-poll-2.rs @@ -0,0 +1,48 @@ +use std::{ + future::Future, + pin::Pin, + marker::Unpin, + task::{Context, Poll}, +}; + +struct Sleep(std::marker::PhantomPinned); + +impl Future for Sleep { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} + +impl Drop for Sleep { + fn drop(&mut self) {} +} + +fn sleep() -> Sleep { + Sleep(std::marker::PhantomPinned) +} + + +struct MyFuture { + sleep: Sleep, +} + +impl MyFuture { + fn new() -> Self { + Self { + sleep: sleep(), + } + } +} + +impl Future for MyFuture { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut self.sleep).poll(cx) + //~^ ERROR `PhantomPinned` cannot be unpinned + } +} + +fn main() {} diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr new file mode 100644 index 000000000..0a6f705e2 --- /dev/null +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -0,0 +1,20 @@ +error[E0277]: `PhantomPinned` cannot be unpinned + --> $DIR/pin-needed-to-poll-2.rs:43:18 + | +LL | Pin::new(&mut self.sleep).poll(cx) + | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required because it appears within the type `Sleep` + --> $DIR/pin-needed-to-poll-2.rs:8:8 + | +LL | struct Sleep(std::marker::PhantomPinned); + | ^^^^^ +note: required by a bound in `Pin::

::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/pin-needed-to-poll.rs b/tests/ui/async-await/pin-needed-to-poll.rs new file mode 100644 index 000000000..0d1fe684f --- /dev/null +++ b/tests/ui/async-await/pin-needed-to-poll.rs @@ -0,0 +1,47 @@ +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + +struct Sleep; + +impl Future for Sleep { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} + +impl Drop for Sleep { + fn drop(&mut self) {} +} + +fn sleep() -> Sleep { + Sleep +} + + +struct MyFuture { + sleep: Sleep, +} + +impl MyFuture { + fn new() -> Self { + Self { + sleep: sleep(), + } + } +} + +impl Future for MyFuture { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.sleep.poll(cx) + //~^ ERROR no method named `poll` found for struct `Sleep` in the current scope + } +} + +fn main() {} diff --git a/tests/ui/async-await/pin-needed-to-poll.stderr b/tests/ui/async-await/pin-needed-to-poll.stderr new file mode 100644 index 000000000..b1f4a73aa --- /dev/null +++ b/tests/ui/async-await/pin-needed-to-poll.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `poll` found for struct `Sleep` in the current scope + --> $DIR/pin-needed-to-poll.rs:42:20 + | +LL | struct Sleep; + | ------------ method `poll` not found for this struct +... +LL | self.sleep.poll(cx) + | ^^^^ method not found in `Sleep` + --> $SRC_DIR/core/src/future/future.rs:LL:COL + | + = note: the method is available for `Pin<&mut Sleep>` here + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Pin::new(&mut self.sleep).poll(cx) + | +++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/async-await/proper-span-for-type-error.fixed b/tests/ui/async-await/proper-span-for-type-error.fixed new file mode 100644 index 000000000..7d43b575d --- /dev/null +++ b/tests/ui/async-await/proper-span-for-type-error.fixed @@ -0,0 +1,12 @@ +// edition:2021 +// run-rustfix +#![allow(dead_code)] + +async fn a() {} + +async fn foo() -> Result<(), i32> { + a().await; + Ok(()) //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/async-await/proper-span-for-type-error.rs b/tests/ui/async-await/proper-span-for-type-error.rs new file mode 100644 index 000000000..00ccde1bf --- /dev/null +++ b/tests/ui/async-await/proper-span-for-type-error.rs @@ -0,0 +1,11 @@ +// edition:2021 +// run-rustfix +#![allow(dead_code)] + +async fn a() {} + +async fn foo() -> Result<(), i32> { + a().await //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/async-await/proper-span-for-type-error.stderr b/tests/ui/async-await/proper-span-for-type-error.stderr new file mode 100644 index 000000000..25f05156c --- /dev/null +++ b/tests/ui/async-await/proper-span-for-type-error.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/proper-span-for-type-error.rs:8:5 + | +LL | a().await + | ^^^^^^^^^ expected enum `Result`, found `()` + | + = note: expected enum `Result<(), i32>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ a().await; +LL ~ Ok(()) + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.rs b/tests/ui/async-await/recursive-async-impl-trait-type.rs new file mode 100644 index 000000000..edc4cb8ac --- /dev/null +++ b/tests/ui/async-await/recursive-async-impl-trait-type.rs @@ -0,0 +1,10 @@ +// edition:2018 +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden when using `async` and `await`. + +async fn recursive_async_function() -> () { + //~^ ERROR recursion in an `async fn` requires boxing + recursive_async_function().await; +} + +fn main() {} diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr new file mode 100644 index 000000000..63f64f445 --- /dev/null +++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr @@ -0,0 +1,12 @@ +error[E0733]: recursion in an `async fn` requires boxing + --> $DIR/recursive-async-impl-trait-type.rs:5:40 + | +LL | async fn recursive_async_function() -> () { + | ^^ recursive `async fn` + | + = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future` + = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/async-await/repeat_count_const_in_async_fn.rs b/tests/ui/async-await/repeat_count_const_in_async_fn.rs new file mode 100644 index 000000000..ebabc3fbf --- /dev/null +++ b/tests/ui/async-await/repeat_count_const_in_async_fn.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 +// compile-flags: --crate-type=lib + +pub async fn test() { + const C: usize = 4; + foo(&mut [0u8; C]).await; +} + +async fn foo(_: &mut [u8]) {} diff --git a/tests/ui/async-await/return-ty-raw-ptr-coercion.rs b/tests/ui/async-await/return-ty-raw-ptr-coercion.rs new file mode 100644 index 000000000..9fe0869ca --- /dev/null +++ b/tests/ui/async-await/return-ty-raw-ptr-coercion.rs @@ -0,0 +1,25 @@ +// Check that we apply unsizing coercions based on the return type. +// +// Also serves as a regression test for #60424. +// +// edition:2018 +// check-pass + +#![allow(warnings)] + +use std::fmt::Debug; + +const TMP: u32 = 22; + +// Coerce from `&u32` to `*const u32` +fn raw_pointer_coercion() { + fn sync_example() -> *const u32 { + &TMP + } + + async fn async_example() -> *const u32 { + &TMP + } +} + +fn main() {} diff --git a/tests/ui/async-await/return-ty-unsize-coercion.rs b/tests/ui/async-await/return-ty-unsize-coercion.rs new file mode 100644 index 000000000..93832ef7e --- /dev/null +++ b/tests/ui/async-await/return-ty-unsize-coercion.rs @@ -0,0 +1,45 @@ +// Check that we apply unsizing coercions based on the return type. +// +// Also serves as a regression test for #60424. +// +// edition:2018 +// check-pass + +#![allow(warnings)] + +use std::fmt::Debug; + +// Unsizing coercion from `Box<&'static str>` to `Box`. +fn unsize_trait_coercion() { + fn sync_example() -> Box { + Box::new("asdf") + } + + async fn async_example() -> Box { + Box::new("asdf") + } +} + +// Unsizing coercion from `Box<[u32; N]>` to `Box<[32]>`. +fn unsize_slice_coercion() { + fn sync_example() -> Box<[u32]> { + Box::new([0]) + } + + async fn async_example() -> Box<[u32]> { + Box::new([0]) + } +} + +// Unsizing coercion from `&[&str; 1]` to `&[&str]` +fn unsize_slice_str_coercion() { + fn sync_example() -> &'static [&'static str] { + &["hi"] + } + + async fn async_example() -> &'static [&'static str] { + &["hi"] + } +} + +fn main() {} diff --git a/tests/ui/async-await/suggest-missing-await-closure.fixed b/tests/ui/async-await/suggest-missing-await-closure.fixed new file mode 100644 index 000000000..febcd0218 --- /dev/null +++ b/tests/ui/async-await/suggest-missing-await-closure.fixed @@ -0,0 +1,23 @@ +// edition:2018 +// run-rustfix + +#![feature(async_closure)] + +fn take_u32(_x: u32) {} + +async fn make_u32() -> u32 { + 22 +} + +#[allow(unused)] +async fn suggest_await_in_async_closure() { + async || { + let x = make_u32(); + take_u32(x.await) + //~^ ERROR mismatched types [E0308] + //~| HELP consider `await`ing on the `Future` + //~| SUGGESTION .await + }; +} + +fn main() {} diff --git a/tests/ui/async-await/suggest-missing-await-closure.rs b/tests/ui/async-await/suggest-missing-await-closure.rs new file mode 100644 index 000000000..faabf6ee3 --- /dev/null +++ b/tests/ui/async-await/suggest-missing-await-closure.rs @@ -0,0 +1,23 @@ +// edition:2018 +// run-rustfix + +#![feature(async_closure)] + +fn take_u32(_x: u32) {} + +async fn make_u32() -> u32 { + 22 +} + +#[allow(unused)] +async fn suggest_await_in_async_closure() { + async || { + let x = make_u32(); + take_u32(x) + //~^ ERROR mismatched types [E0308] + //~| HELP consider `await`ing on the `Future` + //~| SUGGESTION .await + }; +} + +fn main() {} diff --git a/tests/ui/async-await/suggest-missing-await-closure.stderr b/tests/ui/async-await/suggest-missing-await-closure.stderr new file mode 100644 index 000000000..a5958baff --- /dev/null +++ b/tests/ui/async-await/suggest-missing-await-closure.stderr @@ -0,0 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/suggest-missing-await-closure.rs:16:18 + | +LL | take_u32(x) + | -------- ^ expected `u32`, found opaque type + | | + | arguments to this function are incorrect + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await-closure.rs:8:24 + | +LL | async fn make_u32() -> u32 { + | ^^^ checked the `Output` of this `async fn`, found opaque type + = note: expected type `u32` + found opaque type `impl Future` +note: function defined here + --> $DIR/suggest-missing-await-closure.rs:6:4 + | +LL | fn take_u32(_x: u32) {} + | ^^^^^^^^ ------- +help: consider `await`ing on the `Future` + | +LL | take_u32(x.await) + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs new file mode 100644 index 000000000..796f82e77 --- /dev/null +++ b/tests/ui/async-await/suggest-missing-await.rs @@ -0,0 +1,74 @@ +// edition:2018 + +fn take_u32(_x: u32) {} + +async fn make_u32() -> u32 { + 22 +} + +#[allow(unused)] +async fn suggest_await_in_async_fn() { + let x = make_u32(); + take_u32(x) + //~^ ERROR mismatched types [E0308] + //~| HELP consider `await`ing on the `Future` + //~| SUGGESTION .await +} + +async fn dummy() {} + +#[allow(unused)] +async fn suggest_await_in_async_fn_return() { + dummy() + //~^ ERROR mismatched types [E0308] + //~| HELP consider `await`ing on the `Future` + //~| HELP consider using a semicolon here + //~| SUGGESTION .await +} + +#[allow(unused)] +async fn suggest_await_on_if() { + let _x = if true { + dummy() + //~^ HELP consider `await`ing on the `Future` + } else { + dummy().await + //~^ ERROR `if` and `else` have incompatible types [E0308] + }; +} + +#[allow(unused)] +async fn suggest_await_on_previous_match_arms() { + let _x = match 0usize { + 0 => dummy(), //~ HELP consider `await`ing on the `Future` + 1 => dummy(), + 2 => dummy().await, + //~^ `match` arms have incompatible types [E0308] + }; +} + +#[allow(unused)] +async fn suggest_await_on_match_expr() { + let _x = match dummy() { //~ HELP consider `await`ing on the `Future` + () => {} //~ ERROR mismatched types [E0308] + }; +} + +async fn dummy_result() -> Result<(), ()> { + Ok(()) +} + +#[allow(unused)] +async fn suggest_await_in_generic_pattern() { + match dummy_result() { + //~^ HELP consider `await`ing on the `Future` + //~| HELP consider `await`ing on the `Future` + //~| SUGGESTION .await + Ok(_) => {} + //~^ ERROR mismatched types [E0308] + Err(_) => {} + //~^ ERROR mismatched types [E0308] + } +} + +fn main() {} diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr new file mode 100644 index 000000000..1196601ac --- /dev/null +++ b/tests/ui/async-await/suggest-missing-await.stderr @@ -0,0 +1,167 @@ +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:12:14 + | +LL | take_u32(x) + | -------- ^ expected `u32`, found opaque type + | | + | arguments to this function are incorrect + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:5:24 + | +LL | async fn make_u32() -> u32 { + | ^^^ checked the `Output` of this `async fn`, found opaque type + = note: expected type `u32` + found opaque type `impl Future` +note: function defined here + --> $DIR/suggest-missing-await.rs:3:4 + | +LL | fn take_u32(_x: u32) {} + | ^^^^^^^^ ------- +help: consider `await`ing on the `Future` + | +LL | take_u32(x.await) + | ++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:22:5 + | +LL | dummy() + | ^^^^^^^ expected `()`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future` +help: consider `await`ing on the `Future` + | +LL | dummy().await + | ++++++ +help: consider using a semicolon here + | +LL | dummy(); + | + + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/suggest-missing-await.rs:35:9 + | +LL | let _x = if true { + | ______________- +LL | | dummy() + | | ------- expected because of this +LL | | +LL | | } else { +LL | | dummy().await + | | ^^^^^^^^^^^^^ expected opaque type, found `()` +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future` + found unit type `()` +help: consider `await`ing on the `Future` + | +LL | dummy().await + | ++++++ + +error[E0308]: `match` arms have incompatible types + --> $DIR/suggest-missing-await.rs:45:14 + | +LL | let _x = match 0usize { + | ______________- +LL | | 0 => dummy(), + | | ------- this is found to be of type `impl Future` +LL | | 1 => dummy(), + | | ------- this is found to be of type `impl Future` +LL | | 2 => dummy().await, + | | ^^^^^^^^^^^^^ expected opaque type, found `()` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future` + found unit type `()` +help: consider `await`ing on the `Future` + | +LL ~ 0 => dummy().await, +LL ~ 1 => dummy().await, + | + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:53:9 + | +LL | let _x = match dummy() { + | ------- this expression has type `impl Future` +LL | () => {} + | ^^ expected opaque type, found `()` + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:18:18 + | +LL | async fn dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future` + found unit type `()` +help: consider `await`ing on the `Future` + | +LL | let _x = match dummy().await { + | ++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:67:9 + | +LL | match dummy_result() { + | -------------- this expression has type `impl Future>` +... +LL | Ok(_) => {} + | ^^^^^ expected opaque type, found enum `Result` + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:57:28 + | +LL | async fn dummy_result() -> Result<(), ()> { + | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future>` + found enum `Result<_, _>` +help: consider `await`ing on the `Future` + | +LL | match dummy_result().await { + | ++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-missing-await.rs:69:9 + | +LL | match dummy_result() { + | -------------- this expression has type `impl Future>` +... +LL | Err(_) => {} + | ^^^^^^ expected opaque type, found enum `Result` + | +note: while checking the return type of the `async fn` + --> $DIR/suggest-missing-await.rs:57:28 + | +LL | async fn dummy_result() -> Result<(), ()> { + | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type + = note: expected opaque type `impl Future>` + found enum `Result<_, _>` +help: consider `await`ing on the `Future` + | +LL | match dummy_result().await { + | ++++++ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs new file mode 100644 index 000000000..4919e0a05 --- /dev/null +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs @@ -0,0 +1,47 @@ +// rustc-env:CARGO=/usr/bin/cargo + +use std::pin::Pin; +use std::future::Future; + +fn main() {} + +fn await_on_struct_missing() { + struct S; + let x = S; + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2021"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_struct_similar() { + struct S { + awai: u8, + } + let x = S { awai: 42 }; + x.await; + //~^ ERROR no field `await` on type + //~| HELP a field with a similar name exists + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2021"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_63533(x: Pin<&mut dyn Future>) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2021"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_apit(x: impl Future) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2021"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr new file mode 100644 index 000000000..409eb179e --- /dev/null +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr @@ -0,0 +1,43 @@ +error[E0609]: no field `await` on type `await_on_struct_missing::S` + --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: set `edition = "2021"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `await_on_struct_similar::S` + --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7 + | +LL | x.await; + | ^^^^^ help: a field with a similar name exists: `awai` + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: set `edition = "2021"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `Pin<&mut dyn Future>` + --> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: set `edition = "2021"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `impl Future` + --> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7 + | +LL | x.await; + | ^^^^^ + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: set `edition = "2021"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.rs b/tests/ui/async-await/suggest-switching-edition-on-await.rs new file mode 100644 index 000000000..9852e8fc9 --- /dev/null +++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs @@ -0,0 +1,45 @@ +use std::pin::Pin; +use std::future::Future; + +fn main() {} + +fn await_on_struct_missing() { + struct S; + let x = S; + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP pass `--edition 2021` to `rustc` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_struct_similar() { + struct S { + awai: u8, + } + let x = S { awai: 42 }; + x.await; + //~^ ERROR no field `await` on type + //~| HELP a field with a similar name exists + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP pass `--edition 2021` to `rustc` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_63533(x: Pin<&mut dyn Future>) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP pass `--edition 2021` to `rustc` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_apit(x: impl Future) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP pass `--edition 2021` to `rustc` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.stderr b/tests/ui/async-await/suggest-switching-edition-on-await.stderr new file mode 100644 index 000000000..ef3334381 --- /dev/null +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -0,0 +1,43 @@ +error[E0609]: no field `await` on type `await_on_struct_missing::S` + --> $DIR/suggest-switching-edition-on-await.rs:9:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `await_on_struct_similar::S` + --> $DIR/suggest-switching-edition-on-await.rs:22:7 + | +LL | x.await; + | ^^^^^ help: a field with a similar name exists: `awai` + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `Pin<&mut dyn Future>` + --> $DIR/suggest-switching-edition-on-await.rs:31:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `impl Future` + --> $DIR/suggest-switching-edition-on-await.rs:40:7 + | +LL | x.await; + | ^^^^^ + | + = note: to `.await` a `Future`, switch to Rust 2018 or later + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/async-await/track-caller/async-block.rs b/tests/ui/async-await/track-caller/async-block.rs new file mode 100644 index 000000000..8e81387c3 --- /dev/null +++ b/tests/ui/async-await/track-caller/async-block.rs @@ -0,0 +1,9 @@ +// edition:2021 + +#![feature(closure_track_caller, stmt_expr_attributes)] + +fn main() { + let _ = #[track_caller] async { + //~^ ERROR attribute should be applied to a function definition [E0739] + }; +} diff --git a/tests/ui/async-await/track-caller/async-block.stderr b/tests/ui/async-await/track-caller/async-block.stderr new file mode 100644 index 000000000..407439921 --- /dev/null +++ b/tests/ui/async-await/track-caller/async-block.stderr @@ -0,0 +1,12 @@ +error[E0739]: attribute should be applied to a function definition + --> $DIR/async-block.rs:6:13 + | +LL | let _ = #[track_caller] async { + | _____________^^^^^^^^^^^^^^^_- +LL | | +LL | | }; + | |_____- not a function definition + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0739`. diff --git a/tests/ui/async-await/track-caller/async-closure-gate.rs b/tests/ui/async-await/track-caller/async-closure-gate.rs new file mode 100644 index 000000000..d9d556855 --- /dev/null +++ b/tests/ui/async-await/track-caller/async-closure-gate.rs @@ -0,0 +1,9 @@ +// edition:2021 + +#![feature(async_closure, stmt_expr_attributes)] + +fn main() { + let _ = #[track_caller] async || { + //~^ ERROR `#[track_caller]` on closures is currently unstable [E0658] + }; +} diff --git a/tests/ui/async-await/track-caller/async-closure-gate.stderr b/tests/ui/async-await/track-caller/async-closure-gate.stderr new file mode 100644 index 000000000..498f1b43b --- /dev/null +++ b/tests/ui/async-await/track-caller/async-closure-gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[track_caller]` on closures is currently unstable + --> $DIR/async-closure-gate.rs:6:13 + | +LL | let _ = #[track_caller] async || { + | ^^^^^^^^^^^^^^^ + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/track-caller/issue-105134.rs b/tests/ui/async-await/track-caller/issue-105134.rs new file mode 100644 index 000000000..4e52b8e25 --- /dev/null +++ b/tests/ui/async-await/track-caller/issue-105134.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2021 + +#[track_caller] +fn f() { + let _ = async {}; +} + +fn main() { + f(); +} diff --git a/tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr b/tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr new file mode 100644 index 000000000..51ea225f4 --- /dev/null +++ b/tests/ui/async-await/track-caller/panic-track-caller.nofeat.stderr @@ -0,0 +1,29 @@ +warning: `#[track_caller]` on async functions is a no-op + --> $DIR/panic-track-caller.rs:50:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | / async fn bar_track_caller() { +LL | | panic!() +LL | | } + | |_- this function will not propagate the caller location + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + = note: `#[warn(ungated_async_fn_track_caller)]` on by default + +warning: `#[track_caller]` on async functions is a no-op + --> $DIR/panic-track-caller.rs:62:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | / async fn bar_assoc() { +LL | | panic!(); +LL | | } + | |_____- this function will not propagate the caller location + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +warning: 2 warnings emitted + diff --git a/tests/ui/async-await/track-caller/panic-track-caller.rs b/tests/ui/async-await/track-caller/panic-track-caller.rs new file mode 100644 index 000000000..f45243b0e --- /dev/null +++ b/tests/ui/async-await/track-caller/panic-track-caller.rs @@ -0,0 +1,113 @@ +// run-pass +// edition:2021 +// revisions: feat nofeat +// needs-unwind +#![feature(async_closure, stmt_expr_attributes)] +#![cfg_attr(feat, feature(closure_track_caller))] + +use std::future::Future; +use std::panic; +use std::sync::{Arc, Mutex}; +use std::task::{Context, Poll, Wake}; +use std::thread::{self, Thread}; + +/// A waker that wakes up the current thread when called. +struct ThreadWaker(Thread); + +impl Wake for ThreadWaker { + fn wake(self: Arc) { + self.0.unpark(); + } +} + +/// Run a future to completion on the current thread. +fn block_on(fut: impl Future) -> T { + // Pin the future so it can be polled. + let mut fut = Box::pin(fut); + + // Create a new context to be passed to the future. + let t = thread::current(); + let waker = Arc::new(ThreadWaker(t)).into(); + let mut cx = Context::from_waker(&waker); + + // Run the future to completion. + loop { + match fut.as_mut().poll(&mut cx) { + Poll::Ready(res) => return res, + Poll::Pending => thread::park(), + } + } +} + +async fn bar() { + panic!() +} + +async fn foo() { + bar().await +} + +#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op +async fn bar_track_caller() { + panic!() +} + +async fn foo_track_caller() { + bar_track_caller().await +} + +struct Foo; + +impl Foo { + #[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op + async fn bar_assoc() { + panic!(); + } +} + +async fn foo_assoc() { + Foo::bar_assoc().await +} + +// Since compilation is expected to fail for this fn when using +// `nofeat`, we test that separately in `async-closure-gate.rs` +#[cfg(feat)] +async fn foo_closure() { + let c = #[track_caller] async || { + panic!(); + }; + c().await +} + +fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { + let loc = Arc::new(Mutex::new(None)); + + let hook = panic::take_hook(); + { + let loc = loc.clone(); + panic::set_hook(Box::new(move |info| { + *loc.lock().unwrap() = info.location().map(|loc| loc.line()) + })); + } + panic::catch_unwind(f).unwrap_err(); + panic::set_hook(hook); + let x = loc.lock().unwrap().unwrap(); + x +} + +fn main() { + assert_eq!(panicked_at(|| block_on(foo())), 43); + + #[cfg(feat)] + assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56); + #[cfg(nofeat)] + assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52); + + #[cfg(feat)] + assert_eq!(panicked_at(|| block_on(foo_assoc())), 69); + #[cfg(nofeat)] + assert_eq!(panicked_at(|| block_on(foo_assoc())), 64); + + #[cfg(feat)] + assert_eq!(panicked_at(|| block_on(foo_closure())), 79); +} diff --git a/tests/ui/async-await/try-on-option-in-async.rs b/tests/ui/async-await/try-on-option-in-async.rs new file mode 100644 index 000000000..afaaed2ef --- /dev/null +++ b/tests/ui/async-await/try-on-option-in-async.rs @@ -0,0 +1,28 @@ +#![feature(async_closure)] +// edition:2018 +fn main() {} + +async fn an_async_block() -> u32 { + async { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 + } + .await +} + +async fn async_closure_containing_fn() -> u32 { + let async_closure = async || { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22_u32 + }; + + async_closure().await +} + +async fn an_async_function() -> u32 { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 +} diff --git a/tests/ui/async-await/try-on-option-in-async.stderr b/tests/ui/async-await/try-on-option-in-async.stderr new file mode 100644 index 000000000..4c7b4fa41 --- /dev/null +++ b/tests/ui/async-await/try-on-option-in-async.stderr @@ -0,0 +1,44 @@ +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-in-async.rs:8:10 + | +LL | / async { +LL | | let x: Option = None; +LL | | x?; + | | ^ cannot use the `?` operator in an async block that returns `{integer}` +LL | | 22 +LL | | } + | |_____- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual>` is not implemented for `{integer}` + +error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-in-async.rs:17:10 + | +LL | let async_closure = async || { + | __________________________________- +LL | | let x: Option = None; +LL | | x?; + | | ^ cannot use the `?` operator in an async closure that returns `u32` +LL | | 22_u32 +LL | | }; + | |_____- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual>` is not implemented for `u32` + +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-in-async.rs:26:6 + | +LL | async fn an_async_function() -> u32 { + | _____________________________________- +LL | | let x: Option = None; +LL | | x?; + | | ^ cannot use the `?` operator in an async function that returns `u32` +LL | | 22 +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromResidual>` is not implemented for `u32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/type-parameter-send.rs b/tests/ui/async-await/type-parameter-send.rs new file mode 100644 index 000000000..ab2b62aa5 --- /dev/null +++ b/tests/ui/async-await/type-parameter-send.rs @@ -0,0 +1,18 @@ +// check-pass +// compile-flags: --crate-type lib +// edition:2018 + +fn assert_send(_: F) {} + +async fn __post() -> T { + if false { + todo!() + } else { + async {}.await; + todo!() + } +} + +fn foo() { + assert_send(__post::()); +} diff --git a/tests/ui/async-await/unnecessary-await.rs b/tests/ui/async-await/unnecessary-await.rs new file mode 100644 index 000000000..24673777b --- /dev/null +++ b/tests/ui/async-await/unnecessary-await.rs @@ -0,0 +1,14 @@ +// edition:2018 + +async fn foo () { } +fn bar() -> impl std::future::Future { async {} } +fn boo() {} + +async fn baz() -> std::io::Result<()> { + foo().await; + boo().await; //~ ERROR `()` is not a future + bar().await; + std::io::Result::Ok(()) +} + +fn main() {} diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr new file mode 100644 index 000000000..dc3089336 --- /dev/null +++ b/tests/ui/async-await/unnecessary-await.stderr @@ -0,0 +1,24 @@ +error[E0277]: `()` is not a future + --> $DIR/unnecessary-await.rs:9:10 + | +LL | boo().await; + | -----^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - boo().await; +LL + boo(); + | +help: alternatively, consider making `fn boo` asynchronous + | +LL | async fn boo() {} + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/unreachable-lint-1.rs b/tests/ui/async-await/unreachable-lint-1.rs new file mode 100644 index 000000000..d63d643c4 --- /dev/null +++ b/tests/ui/async-await/unreachable-lint-1.rs @@ -0,0 +1,12 @@ +// edition:2018 +#![deny(unreachable_code)] + +async fn foo() { + return; bar().await; + //~^ ERROR unreachable statement +} + +async fn bar() { +} + +fn main() { } diff --git a/tests/ui/async-await/unreachable-lint-1.stderr b/tests/ui/async-await/unreachable-lint-1.stderr new file mode 100644 index 000000000..e93257889 --- /dev/null +++ b/tests/ui/async-await/unreachable-lint-1.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/unreachable-lint-1.rs:5:13 + | +LL | return; bar().await; + | ------ ^^^^^^^^^^^^ unreachable statement + | | + | any code following this expression is unreachable + | +note: the lint level is defined here + --> $DIR/unreachable-lint-1.rs:2:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/async-await/unreachable-lint.rs b/tests/ui/async-await/unreachable-lint.rs new file mode 100644 index 000000000..ca18cfde4 --- /dev/null +++ b/tests/ui/async-await/unreachable-lint.rs @@ -0,0 +1,13 @@ +// check-pass +// edition:2018 +#![deny(unreachable_code)] + +async fn foo() { + endless().await; +} + +async fn endless() -> ! { + loop {} +} + +fn main() { } diff --git a/tests/ui/async-await/unresolved_type_param.rs b/tests/ui/async-await/unresolved_type_param.rs new file mode 100644 index 000000000..6d6d80614 --- /dev/null +++ b/tests/ui/async-await/unresolved_type_param.rs @@ -0,0 +1,24 @@ +// Provoke an unresolved type error (T). +// Error message should pinpoint the type parameter T as needing to be bound +// (rather than give a general error message) +// edition:2018 +// compile-flags: -Zdrop-tracking + +async fn bar() -> () {} + +async fn foo() { + bar().await; + //~^ ERROR type inside `async fn` body must be known in this context + //~| ERROR type inside `async fn` body must be known in this context + //~| ERROR type inside `async fn` body must be known in this context + //~| NOTE cannot infer type for type parameter `T` + //~| NOTE cannot infer type for type parameter `T` + //~| NOTE cannot infer type for type parameter `T` + //~| NOTE the type is part of the `async fn` body because of this `await` + //~| NOTE the type is part of the `async fn` body because of this `await` + //~| NOTE the type is part of the `async fn` body because of this `await` + //~| NOTE in this expansion of desugaring of `await` + //~| NOTE in this expansion of desugaring of `await` + //~| NOTE in this expansion of desugaring of `await` +} +fn main() {} diff --git a/tests/ui/async-await/unresolved_type_param.stderr b/tests/ui/async-await/unresolved_type_param.stderr new file mode 100644 index 000000000..7236c681f --- /dev/null +++ b/tests/ui/async-await/unresolved_type_param.stderr @@ -0,0 +1,39 @@ +error[E0698]: type inside `async fn` body must be known in this context + --> $DIR/unresolved_type_param.rs:10:5 + | +LL | bar().await; + | ^^^ cannot infer type for type parameter `T` declared on the function `bar` + | +note: the type is part of the `async fn` body because of this `await` + --> $DIR/unresolved_type_param.rs:10:10 + | +LL | bar().await; + | ^^^^^^ + +error[E0698]: type inside `async fn` body must be known in this context + --> $DIR/unresolved_type_param.rs:10:5 + | +LL | bar().await; + | ^^^ cannot infer type for type parameter `T` declared on the function `bar` + | +note: the type is part of the `async fn` body because of this `await` + --> $DIR/unresolved_type_param.rs:10:10 + | +LL | bar().await; + | ^^^^^^ + +error[E0698]: type inside `async fn` body must be known in this context + --> $DIR/unresolved_type_param.rs:10:5 + | +LL | bar().await; + | ^^^ cannot infer type for type parameter `T` declared on the function `bar` + | +note: the type is part of the `async fn` body because of this `await` + --> $DIR/unresolved_type_param.rs:10:10 + | +LL | bar().await; + | ^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0698`. diff --git a/tests/ui/async-await/unused-lifetime.rs b/tests/ui/async-await/unused-lifetime.rs new file mode 100644 index 000000000..6cfd36ba9 --- /dev/null +++ b/tests/ui/async-await/unused-lifetime.rs @@ -0,0 +1,39 @@ +// Check "unused_lifetimes" lint on both async and sync functions +// Both cases should be diagnosed the same way. + +// edition:2018 + +#![deny(unused_lifetimes)] + +async fn async_wrong_without_args<'a>() {} //~ ERROR lifetime parameter `'a` never used + +async fn async_wrong_1_lifetime<'a>(_: &i32) {} //~ ERROR lifetime parameter `'a` never used + +async fn async_wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} //~ ERROR lifetime parameter `'b` never used + +async fn async_right_1_lifetime<'a>(_: &'a i32) {} + +async fn async_right_2_lifetimes<'a, 'b>(_: &'a i32, _: &'b i32) {} + +async fn async_right_trait_bound_lifetime<'a, I>(_: I) +where + I: Iterator +{} + +fn wrong_without_args<'a>() {} //~ ERROR lifetime parameter `'a` never used + +fn wrong_1_lifetime<'a>(_: &i32) {} //~ ERROR lifetime parameter `'a` never used + +fn wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} //~ ERROR lifetime parameter `'b` never used + +fn right_1_lifetime<'a>(_: &'a i32) {} + +fn right_2_lifetimes<'a, 'b>(_: &'a i32, _: &'b i32) {} + +fn right_trait_bound_lifetime<'a, I>(_: I) +where + I: Iterator +{} + + +fn main() {} diff --git a/tests/ui/async-await/unused-lifetime.stderr b/tests/ui/async-await/unused-lifetime.stderr new file mode 100644 index 000000000..5c00501a6 --- /dev/null +++ b/tests/ui/async-await/unused-lifetime.stderr @@ -0,0 +1,48 @@ +error: lifetime parameter `'a` never used + --> $DIR/unused-lifetime.rs:8:35 + | +LL | async fn async_wrong_without_args<'a>() {} + | -^^- help: elide the unused lifetime + | +note: the lint level is defined here + --> $DIR/unused-lifetime.rs:6:9 + | +LL | #![deny(unused_lifetimes)] + | ^^^^^^^^^^^^^^^^ + +error: lifetime parameter `'a` never used + --> $DIR/unused-lifetime.rs:10:33 + | +LL | async fn async_wrong_1_lifetime<'a>(_: &i32) {} + | -^^- help: elide the unused lifetime + +error: lifetime parameter `'b` never used + --> $DIR/unused-lifetime.rs:12:38 + | +LL | async fn async_wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} + | --^^ + | | + | help: elide the unused lifetime + +error: lifetime parameter `'a` never used + --> $DIR/unused-lifetime.rs:23:23 + | +LL | fn wrong_without_args<'a>() {} + | -^^- help: elide the unused lifetime + +error: lifetime parameter `'a` never used + --> $DIR/unused-lifetime.rs:25:21 + | +LL | fn wrong_1_lifetime<'a>(_: &i32) {} + | -^^- help: elide the unused lifetime + +error: lifetime parameter `'b` never used + --> $DIR/unused-lifetime.rs:27:26 + | +LL | fn wrong_2_lifetimes<'a, 'b>(_: &'a i32, _: &i32) {} + | --^^ + | | + | help: elide the unused lifetime + +error: aborting due to 6 previous errors + diff --git a/tests/ui/atomic-from-mut-not-available.rs b/tests/ui/atomic-from-mut-not-available.rs new file mode 100644 index 000000000..bf9461600 --- /dev/null +++ b/tests/ui/atomic-from-mut-not-available.rs @@ -0,0 +1,7 @@ +// only-x86 +// only-linux + +fn main() { + core::sync::atomic::AtomicU64::from_mut(&mut 0u64); + //~^ ERROR: no function or associated item named `from_mut` found for struct `AtomicU64` +} diff --git a/tests/ui/atomic-from-mut-not-available.stderr b/tests/ui/atomic-from-mut-not-available.stderr new file mode 100644 index 000000000..d1ebca8a2 --- /dev/null +++ b/tests/ui/atomic-from-mut-not-available.stderr @@ -0,0 +1,9 @@ +error[E0599]: no function or associated item named `from_mut` found for struct `AtomicU64` in the current scope + --> $DIR/atomic-from-mut-not-available.rs:5:36 + | +LL | core::sync::atomic::AtomicU64::from_mut(&mut 0u64); + | ^^^^^^^^ function or associated item not found in `AtomicU64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/attempted-access-non-fatal.rs b/tests/ui/attempted-access-non-fatal.rs new file mode 100644 index 000000000..15deb9e2f --- /dev/null +++ b/tests/ui/attempted-access-non-fatal.rs @@ -0,0 +1,10 @@ +// Check that bogus field access is non-fatal +fn main() { + let x = 0; + let _ = x.foo; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = x.bar; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 0.f; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 2.l; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 12.F; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 34.L; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] +} diff --git a/tests/ui/attempted-access-non-fatal.stderr b/tests/ui/attempted-access-non-fatal.stderr new file mode 100644 index 000000000..bff669727 --- /dev/null +++ b/tests/ui/attempted-access-non-fatal.stderr @@ -0,0 +1,59 @@ +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/attempted-access-non-fatal.rs:4:15 + | +LL | let _ = x.foo; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/attempted-access-non-fatal.rs:5:15 + | +LL | let _ = x.bar; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/attempted-access-non-fatal.rs:6:15 + | +LL | let _ = 0.f; + | ^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period and a `f32` suffix + | +LL | let _ = 0.0f32; + | ~~~~ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/attempted-access-non-fatal.rs:7:15 + | +LL | let _ = 2.l; + | ^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period and a `f64` suffix + | +LL | let _ = 2.0f64; + | ~~~~ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/attempted-access-non-fatal.rs:8:16 + | +LL | let _ = 12.F; + | ^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period and a `f32` suffix + | +LL | let _ = 12.0f32; + | ~~~~ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/attempted-access-non-fatal.rs:9:16 + | +LL | let _ = 34.L; + | ^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period and a `f64` suffix + | +LL | let _ = 34.0f64; + | ~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/attr-bad-crate-attr.rc b/tests/ui/attr-bad-crate-attr.rc new file mode 100644 index 000000000..89ba26dfd --- /dev/null +++ b/tests/ui/attr-bad-crate-attr.rc @@ -0,0 +1,4 @@ +// error-pattern: expected item + +#![attr = "val"] +#[attr = "val"] // Unterminated diff --git a/tests/ui/attr-shebang.rs b/tests/ui/attr-shebang.rs new file mode 100644 index 000000000..3b0dc096f --- /dev/null +++ b/tests/ui/attr-shebang.rs @@ -0,0 +1,5 @@ +// run-pass + +#![allow(stable_features)] +#![feature(rust1)] +pub fn main() { } diff --git a/tests/ui/attr-start.rs b/tests/ui/attr-start.rs new file mode 100644 index 000000000..677763148 --- /dev/null +++ b/tests/ui/attr-start.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + return 0; +} diff --git a/tests/ui/attr-usage-inline.rs b/tests/ui/attr-usage-inline.rs new file mode 100644 index 000000000..674c12454 --- /dev/null +++ b/tests/ui/attr-usage-inline.rs @@ -0,0 +1,25 @@ +#![allow(dead_code)] + +#[inline] +fn f() {} + +#[inline] //~ ERROR: attribute should be applied to function or closure +struct S; + +struct I { + #[inline] + i: u8, +} + +#[macro_export] +#[inline] +macro_rules! m_e { + () => {}; +} + +#[inline] //~ ERROR: attribute should be applied to function or closure +macro_rules! m { + () => {}; +} + +fn main() {} diff --git a/tests/ui/attr-usage-inline.stderr b/tests/ui/attr-usage-inline.stderr new file mode 100644 index 000000000..22a0bf47e --- /dev/null +++ b/tests/ui/attr-usage-inline.stderr @@ -0,0 +1,17 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/attr-usage-inline.rs:6:1 + | +LL | #[inline] + | ^^^^^^^^^ +LL | struct S; + | --------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/attr-usage-inline.rs:20:1 + | +LL | #[inline] + | ^^^^^^^^^ not a function or closure + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/attributes/attr-before-view-item.rs b/tests/ui/attributes/attr-before-view-item.rs new file mode 100644 index 000000000..e1588aada --- /dev/null +++ b/tests/ui/attributes/attr-before-view-item.rs @@ -0,0 +1,10 @@ +// build-pass (FIXME(62277): could be check-pass?) +// pretty-expanded FIXME #23616 + +#![feature(rustc_attrs)] +#![feature(test)] + +#[rustc_dummy = "bar"] +extern crate test; + +fn main() {} diff --git a/tests/ui/attributes/attr-before-view-item2.rs b/tests/ui/attributes/attr-before-view-item2.rs new file mode 100644 index 000000000..c1f667372 --- /dev/null +++ b/tests/ui/attributes/attr-before-view-item2.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// pretty-expanded FIXME #23616 + +#![feature(rustc_attrs)] +#![feature(test)] + +mod m { + #[rustc_dummy = "bar"] + extern crate test; +} + +fn main() {} diff --git a/tests/ui/attributes/attr-eq-token-tree.rs b/tests/ui/attributes/attr-eq-token-tree.rs new file mode 100644 index 000000000..330b11977 --- /dev/null +++ b/tests/ui/attributes/attr-eq-token-tree.rs @@ -0,0 +1,2 @@ +#[my_attr = !] //~ ERROR expected expression, found `]` +fn main() {} diff --git a/tests/ui/attributes/attr-eq-token-tree.stderr b/tests/ui/attributes/attr-eq-token-tree.stderr new file mode 100644 index 000000000..1846444b6 --- /dev/null +++ b/tests/ui/attributes/attr-eq-token-tree.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `]` + --> $DIR/attr-eq-token-tree.rs:1:14 + | +LL | #[my_attr = !] + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/attributes/attr-mix-new.rs b/tests/ui/attributes/attr-mix-new.rs new file mode 100644 index 000000000..8119df0c4 --- /dev/null +++ b/tests/ui/attributes/attr-mix-new.rs @@ -0,0 +1,11 @@ +// build-pass (FIXME(62277): could be check-pass?) +// pretty-expanded FIXME #23616 + +#![feature(rustc_attrs)] + +#[rustc_dummy(bar)] +mod foo { + #![feature(globs)] +} + +fn main() {} diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs new file mode 100644 index 000000000..158a4500b --- /dev/null +++ b/tests/ui/attributes/attrs-on-params.rs @@ -0,0 +1,8 @@ +// This checks that incorrect params on function parameters are caught + +fn function(#[inline] param: u32) { + //~^ ERROR attribute should be applied to function or closure + //~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes +} + +fn main() {} diff --git a/tests/ui/attributes/attrs-on-params.stderr b/tests/ui/attributes/attrs-on-params.stderr new file mode 100644 index 000000000..306e862cb --- /dev/null +++ b/tests/ui/attributes/attrs-on-params.stderr @@ -0,0 +1,17 @@ +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/attrs-on-params.rs:3:13 + | +LL | fn function(#[inline] param: u32) { + | ^^^^^^^^^ + +error[E0518]: attribute should be applied to function or closure + --> $DIR/attrs-on-params.rs:3:13 + | +LL | fn function(#[inline] param: u32) { + | ^^^^^^^^^----------- + | | + | not a function or closure + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-1.rs b/tests/ui/attributes/attrs-with-no-formal-in-generics-1.rs new file mode 100644 index 000000000..df9c8d894 --- /dev/null +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-1.rs @@ -0,0 +1,13 @@ +// This test checks variations on `<#[attr] 'a, #[oops]>`, where +// `#[oops]` is left dangling (that is, it is unattached, with no +// formal binding following it). + +#![feature(rustc_attrs)] + +struct RefIntPair<'a, 'b>(&'a u32, &'b u32); + +impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> { + //~^ ERROR trailing attribute after generic parameter +} + +fn main() {} diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr b/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr new file mode 100644 index 000000000..5b4f5222a --- /dev/null +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-1.stderr @@ -0,0 +1,8 @@ +error: trailing attribute after generic parameter + --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:29 + | +LL | impl<#[rustc_dummy] 'a, 'b, #[oops]> RefIntPair<'a, 'b> { + | ^^^^^^^ attributes must go before parameters + +error: aborting due to previous error + diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-2.rs b/tests/ui/attributes/attrs-with-no-formal-in-generics-2.rs new file mode 100644 index 000000000..d1d044035 --- /dev/null +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-2.rs @@ -0,0 +1,12 @@ +// This test checks variations on `<#[attr] 'a, #[oops]>`, where +// `#[oops]` is left dangling (that is, it is unattached, with no +// formal binding following it). + +#![feature(rustc_attrs)] + +struct RefAny<'a, T>(&'a T); + +impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {} +//~^ ERROR trailing attribute after generic parameter + +fn main() {} diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr b/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr new file mode 100644 index 000000000..fce3ff7de --- /dev/null +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-2.stderr @@ -0,0 +1,8 @@ +error: trailing attribute after generic parameter + --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:43 + | +LL | impl<#[rustc_dummy] 'a, #[rustc_dummy] T, #[oops]> RefAny<'a, T> {} + | ^^^^^^^ attributes must go before parameters + +error: aborting due to previous error + diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-3.rs b/tests/ui/attributes/attrs-with-no-formal-in-generics-3.rs new file mode 100644 index 000000000..3cfc70b41 --- /dev/null +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-3.rs @@ -0,0 +1,12 @@ +// This test checks variations on `<#[attr] 'a, #[oops]>`, where +// `#[oops]` is left dangling (that is, it is unattached, with no +// formal binding following it). + +struct RefIntPair<'a, 'b>(&'a u32, &'b u32); + +fn hof_lt(_: Q) + where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 + //~^ ERROR trailing attribute after generic parameter +{} + +fn main() {} diff --git a/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr b/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr new file mode 100644 index 000000000..b9ca00974 --- /dev/null +++ b/tests/ui/attributes/attrs-with-no-formal-in-generics-3.stderr @@ -0,0 +1,8 @@ +error: trailing attribute after generic parameter + --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44 + | +LL | where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32 + | ^^^^^^^ attributes must go before parameters + +error: aborting due to previous error + diff --git a/tests/ui/attributes/auxiliary/key-value-expansion.rs b/tests/ui/attributes/auxiliary/key-value-expansion.rs new file mode 100644 index 000000000..b4eb80bb5 --- /dev/null +++ b/tests/ui/attributes/auxiliary/key-value-expansion.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(EthabiContract, attributes(ethabi_contract_options))] +pub fn ethabi_derive(input: TokenStream) -> TokenStream { + Default::default() +} diff --git a/tests/ui/attributes/class-attributes-1.rs b/tests/ui/attributes/class-attributes-1.rs new file mode 100644 index 000000000..027b701e5 --- /dev/null +++ b/tests/ui/attributes/class-attributes-1.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) +// pp-exact - Make sure we actually print the attributes + +#![feature(rustc_attrs)] + +struct Cat { + name: String, +} + +impl Drop for Cat { + #[rustc_dummy] + fn drop(&mut self) { println!("{} landed on hir feet" , self . name); } +} + + +#[rustc_dummy] +fn cat(name: String) -> Cat { Cat{name: name,} } + +fn main() { let _kitty = cat("Spotty".to_string()); } diff --git a/tests/ui/attributes/class-attributes-2.rs b/tests/ui/attributes/class-attributes-2.rs new file mode 100644 index 000000000..6aba6b894 --- /dev/null +++ b/tests/ui/attributes/class-attributes-2.rs @@ -0,0 +1,31 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(rustc_attrs)] + +struct Cat { + name: String, +} + +impl Drop for Cat { + #[rustc_dummy] + /** + Actually, cats don't always land on their feet when you drop them. + */ + fn drop(&mut self) { + println!("{} landed on hir feet", self.name); + } +} + +#[rustc_dummy] +/** +Maybe it should technically be a kitten_maker. +*/ +fn cat(name: String) -> Cat { + Cat { + name: name + } +} + +fn main() { + let _kitty = cat("Spotty".to_string()); +} diff --git a/tests/ui/attributes/collapse-debuginfo-invalid.rs b/tests/ui/attributes/collapse-debuginfo-invalid.rs new file mode 100644 index 000000000..42d8982c1 --- /dev/null +++ b/tests/ui/attributes/collapse-debuginfo-invalid.rs @@ -0,0 +1,110 @@ +#![feature(collapse_debuginfo)] +#![feature(stmt_expr_attributes)] +#![feature(type_alias_impl_trait)] +#![no_std] + +// Test that the `#[collapse_debuginfo]` attribute can only be used on macro definitions. + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +extern crate std; + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +use std::collections::HashMap; + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +static FOO: u32 = 3; + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +const BAR: u32 = 3; + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +fn foo() { + let _ = #[collapse_debuginfo] || { }; +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + let _ = 3; + let _ = #[collapse_debuginfo] 3; +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + match (3, 4) { + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + _ => (), + } +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +mod bar { +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +type Map = HashMap; + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +enum Foo { + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + Variant, +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +struct Bar { + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + field: u32, +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +union Qux { + a: u32, + b: u16 +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +trait Foobar { + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + type Bar; +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +type AFoobar = impl Foobar; + +impl Foobar for Bar { + type Bar = u32; +} + +fn constraining() -> AFoobar { + Bar { field: 3 } +} + +#[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions +impl Bar { + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + const FOO: u32 = 3; + + #[collapse_debuginfo] +//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions + fn bar(&self) {} +} + +#[collapse_debuginfo] +macro_rules! finally { + ($e:expr) => { $e } +} + +fn main() {} diff --git a/tests/ui/attributes/collapse-debuginfo-invalid.stderr b/tests/ui/attributes/collapse-debuginfo-invalid.stderr new file mode 100644 index 000000000..01c476091 --- /dev/null +++ b/tests/ui/attributes/collapse-debuginfo-invalid.stderr @@ -0,0 +1,222 @@ +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:8:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | extern crate std; + | ----------------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:12:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | use std::collections::HashMap; + | ------------------------------ not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:16:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | static FOO: u32 = 3; + | -------------------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:20:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | const BAR: u32 = 3; + | ------------------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:24:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / fn foo() { +LL | | let _ = #[collapse_debuginfo] || { }; +LL | | +LL | | #[collapse_debuginfo] +... | +LL | | } +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:27:13 + | +LL | let _ = #[collapse_debuginfo] || { }; + | ^^^^^^^^^^^^^^^^^^^^^ ------ not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:29:5 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | let _ = 3; + | ---------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:32:13 + | +LL | let _ = #[collapse_debuginfo] 3; + | ^^^^^^^^^^^^^^^^^^^^^ - not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:35:9 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | _ => (), + | ------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:41:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / mod bar { +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:46:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | type Map = HashMap; + | ----------------------------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:50:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / enum Foo { +LL | | #[collapse_debuginfo] +LL | | +LL | | Variant, +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:53:5 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | Variant, + | ------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:58:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / struct Bar { +LL | | #[collapse_debuginfo] +LL | | +LL | | field: u32, +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:61:5 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | field: u32, + | ---------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:66:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / union Qux { +LL | | a: u32, +LL | | b: u16 +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:73:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / trait Foobar { +LL | | #[collapse_debuginfo] +LL | | +LL | | type Bar; +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:81:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | type AFoobar = impl Foobar; + | --------------------------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:93:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / impl Bar { +LL | | #[collapse_debuginfo] +LL | | +LL | | const FOO: u32 = 3; +... | +LL | | fn bar(&self) {} +LL | | } + | |_- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:76:5 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | type Bar; + | --------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:96:5 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | const FOO: u32 = 3; + | ------------------- not a macro definition + +error: `collapse_debuginfo` attribute should be applied to macro definitions + --> $DIR/collapse-debuginfo-invalid.rs:100:5 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn bar(&self) {} + | ---------------- not a macro definition + +error: aborting due to 22 previous errors + diff --git a/tests/ui/attributes/const-stability-on-macro.rs b/tests/ui/attributes/const-stability-on-macro.rs new file mode 100644 index 000000000..412af195d --- /dev/null +++ b/tests/ui/attributes/const-stability-on-macro.rs @@ -0,0 +1,16 @@ +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[rustc_const_stable(feature = "foo", since = "0")] +//~^ ERROR macros cannot have const stability attributes +macro_rules! foo { + () => {}; +} + +#[rustc_const_unstable(feature = "bar", issue="none")] +//~^ ERROR macros cannot have const stability attributes +macro_rules! bar { + () => {}; +} + +fn main() {} diff --git a/tests/ui/attributes/const-stability-on-macro.stderr b/tests/ui/attributes/const-stability-on-macro.stderr new file mode 100644 index 000000000..c3da02c79 --- /dev/null +++ b/tests/ui/attributes/const-stability-on-macro.stderr @@ -0,0 +1,20 @@ +error: macros cannot have const stability attributes + --> $DIR/const-stability-on-macro.rs:4:1 + | +LL | #[rustc_const_stable(feature = "foo", since = "0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute +LL | +LL | macro_rules! foo { + | ---------------- const stability attribute affects this macro + +error: macros cannot have const stability attributes + --> $DIR/const-stability-on-macro.rs:10:1 + | +LL | #[rustc_const_unstable(feature = "bar", issue="none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute +LL | +LL | macro_rules! bar { + | ---------------- const stability attribute affects this macro + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attributes/doc-attr.rs b/tests/ui/attributes/doc-attr.rs new file mode 100644 index 000000000..980d1c0e2 --- /dev/null +++ b/tests/ui/attributes/doc-attr.rs @@ -0,0 +1,25 @@ +#![crate_type = "lib"] +#![deny(warnings)] +#![doc(as_ptr)] +//~^ ERROR unknown `doc` attribute +//~^^ WARN + +#[doc(as_ptr)] +//~^ ERROR unknown `doc` attribute +//~^^ WARN +pub fn foo() {} + +#[doc(123)] +//~^ ERROR invalid `doc` attribute +//~| WARN +#[doc("hello", "bar")] +//~^ ERROR invalid `doc` attribute +//~| WARN +//~| ERROR invalid `doc` attribute +//~| WARN +#[doc(foo::bar, crate::bar::baz = "bye")] +//~^ ERROR unknown `doc` attribute +//~| WARN +//~| ERROR unknown `doc` attribute +//~| WARN +fn bar() {} diff --git a/tests/ui/attributes/doc-attr.stderr b/tests/ui/attributes/doc-attr.stderr new file mode 100644 index 000000000..68df2771f --- /dev/null +++ b/tests/ui/attributes/doc-attr.stderr @@ -0,0 +1,71 @@ +error: unknown `doc` attribute `as_ptr` + --> $DIR/doc-attr.rs:7:7 + | +LL | #[doc(as_ptr)] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 +note: the lint level is defined here + --> $DIR/doc-attr.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]` + +error: invalid `doc` attribute + --> $DIR/doc-attr.rs:12:7 + | +LL | #[doc(123)] + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: invalid `doc` attribute + --> $DIR/doc-attr.rs:15:7 + | +LL | #[doc("hello", "bar")] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: invalid `doc` attribute + --> $DIR/doc-attr.rs:15:16 + | +LL | #[doc("hello", "bar")] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: unknown `doc` attribute `foo::bar` + --> $DIR/doc-attr.rs:20:7 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: unknown `doc` attribute `crate::bar::baz` + --> $DIR/doc-attr.rs:20:17 + | +LL | #[doc(foo::bar, crate::bar::baz = "bye")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: unknown `doc` attribute `as_ptr` + --> $DIR/doc-attr.rs:3:8 + | +LL | #![doc(as_ptr)] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: aborting due to 7 previous errors + diff --git a/tests/ui/attributes/duplicated-attributes.rs b/tests/ui/attributes/duplicated-attributes.rs new file mode 100644 index 000000000..84a5abcf8 --- /dev/null +++ b/tests/ui/attributes/duplicated-attributes.rs @@ -0,0 +1,41 @@ +// Test that, if an item is annotated with a builtin attribute more than once, a warning is +// emitted. +// Tests https://github.com/rust-lang/rust/issues/90979 + +// check-pass +// compile-flags: --test + +#![feature(test)] +#![feature(cfg_eval)] + +#[test] +#[test] +//~^ WARNING duplicated attribute +fn f() {} + +// The following shouldn't trigger an error. The attribute is not duplicated. +#[test] +fn f2() {} + +// The following shouldn't trigger an error either. The second attribute is not #[test]. +#[test] +#[inline] +fn f3() {} + +extern crate test; +use test::Bencher; + +#[bench] +#[bench] +//~^ WARNING duplicated attribute +fn f4(_: &mut Bencher) {} + +#[cfg_eval] +#[cfg_eval] +//~^ WARNING duplicated attribute +struct S; + +#[cfg_eval] +struct S2; + +fn main() {} diff --git a/tests/ui/attributes/duplicated-attributes.stderr b/tests/ui/attributes/duplicated-attributes.stderr new file mode 100644 index 000000000..735d950b2 --- /dev/null +++ b/tests/ui/attributes/duplicated-attributes.stderr @@ -0,0 +1,22 @@ +warning: duplicated attribute + --> $DIR/duplicated-attributes.rs:12:1 + | +LL | #[test] + | ^^^^^^^ + | + = note: `#[warn(duplicate_macro_attributes)]` on by default + +warning: duplicated attribute + --> $DIR/duplicated-attributes.rs:29:1 + | +LL | #[bench] + | ^^^^^^^^ + +warning: duplicated attribute + --> $DIR/duplicated-attributes.rs:34:1 + | +LL | #[cfg_eval] + | ^^^^^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/attributes/extented-attribute-macro-error.rs b/tests/ui/attributes/extented-attribute-macro-error.rs new file mode 100644 index 000000000..492f84f56 --- /dev/null +++ b/tests/ui/attributes/extented-attribute-macro-error.rs @@ -0,0 +1,7 @@ +// normalize-stderr-test: "couldn't read.*" -> "couldn't read the file" + +#![doc = include_str!("../not_existing_file.md")] +struct Documented {} +//~^^ ERROR couldn't read + +fn main() {} diff --git a/tests/ui/attributes/extented-attribute-macro-error.stderr b/tests/ui/attributes/extented-attribute-macro-error.stderr new file mode 100644 index 000000000..0fcde9b7c --- /dev/null +++ b/tests/ui/attributes/extented-attribute-macro-error.stderr @@ -0,0 +1,10 @@ +error: couldn't read the file + --> $DIR/extented-attribute-macro-error.rs:3:10 + | +LL | #![doc = include_str!("../not_existing_file.md")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/attributes/field-attributes-vis-unresolved.rs b/tests/ui/attributes/field-attributes-vis-unresolved.rs new file mode 100644 index 000000000..d1bd2a1e7 --- /dev/null +++ b/tests/ui/attributes/field-attributes-vis-unresolved.rs @@ -0,0 +1,25 @@ +// Non-builtin attributes do not mess with field visibility resolution (issue #67006). + +mod internal { + struct S { + #[rustfmt::skip] + pub(in crate::internal) field: u8 // OK + } + + struct Z( + #[rustfmt::skip] + pub(in crate::internal) u8 // OK + ); +} + +struct S { + #[rustfmt::skip] + pub(in nonexistent) field: u8 //~ ERROR failed to resolve +} + +struct Z( + #[rustfmt::skip] + pub(in nonexistent) u8 //~ ERROR failed to resolve +); + +fn main() {} diff --git a/tests/ui/attributes/field-attributes-vis-unresolved.stderr b/tests/ui/attributes/field-attributes-vis-unresolved.stderr new file mode 100644 index 000000000..439762546 --- /dev/null +++ b/tests/ui/attributes/field-attributes-vis-unresolved.stderr @@ -0,0 +1,19 @@ +error[E0433]: failed to resolve: maybe a missing crate `nonexistent`? + --> $DIR/field-attributes-vis-unresolved.rs:17:12 + | +LL | pub(in nonexistent) field: u8 + | ^^^^^^^^^^^ maybe a missing crate `nonexistent`? + | + = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate + +error[E0433]: failed to resolve: maybe a missing crate `nonexistent`? + --> $DIR/field-attributes-vis-unresolved.rs:22:12 + | +LL | pub(in nonexistent) u8 + | ^^^^^^^^^^^ maybe a missing crate `nonexistent`? + | + = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/attributes/invalid-doc-attr.rs b/tests/ui/attributes/invalid-doc-attr.rs new file mode 100644 index 000000000..de004b41e --- /dev/null +++ b/tests/ui/attributes/invalid-doc-attr.rs @@ -0,0 +1,32 @@ +#![crate_type = "lib"] +#![deny(warnings)] + +#[doc(test(no_crate_inject))] +//~^ ERROR can only be applied at the crate level +//~| WARN is being phased out +//~| HELP to apply to the crate, use an inner attribute +//~| SUGGESTION #![doc(test(no_crate_inject))] +#[doc(inline)] +//~^ ERROR can only be applied to a `use` item +//~| WARN is being phased out +pub fn foo() {} + +pub mod bar { + #![doc(test(no_crate_inject))] + //~^ ERROR can only be applied at the crate level + //~| WARN is being phased out + + #[doc(test(no_crate_inject))] + //~^ ERROR can only be applied at the crate level + //~| WARN is being phased out + #[doc(inline)] + //~^ ERROR can only be applied to a `use` item + //~| WARN is being phased out + pub fn baz() {} +} + +#[doc(inline)] +#[doc(no_inline)] +//~^^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +pub use bar::baz; diff --git a/tests/ui/attributes/invalid-doc-attr.stderr b/tests/ui/attributes/invalid-doc-attr.stderr new file mode 100644 index 000000000..3c66e587b --- /dev/null +++ b/tests/ui/attributes/invalid-doc-attr.stderr @@ -0,0 +1,78 @@ +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:4:7 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read for more information +note: the lint level is defined here + --> $DIR/invalid-doc-attr.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]` +help: to apply to the crate, use an inner attribute + | +LL | #![doc(test(no_crate_inject))] + | + +error: this attribute can only be applied to a `use` item + --> $DIR/invalid-doc-attr.rs:9:7 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +... +LL | pub fn foo() {} + | ------------ not a `use` item + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read for more information + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:15:12 + | +LL | #![doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read for more information + +error: conflicting doc inlining attributes + --> $DIR/invalid-doc-attr.rs:28:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +error: this attribute can only be applied at the crate level + --> $DIR/invalid-doc-attr.rs:19:11 + | +LL | #[doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read for more information + +error: this attribute can only be applied to a `use` item + --> $DIR/invalid-doc-attr.rs:22:11 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +... +LL | pub fn baz() {} + | ------------ not a `use` item + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read for more information + +error: aborting due to 6 previous errors + diff --git a/tests/ui/attributes/issue-100631.rs b/tests/ui/attributes/issue-100631.rs new file mode 100644 index 000000000..0fefcf83f --- /dev/null +++ b/tests/ui/attributes/issue-100631.rs @@ -0,0 +1,8 @@ +// issue #100631, make sure `TyCtxt::get_attr` only called by case that compiler +// can reasonably deal with multiple attributes. +// `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`. +#[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084] +#[repr(C)] +enum Foo {} + +fn main() {} diff --git a/tests/ui/attributes/issue-100631.stderr b/tests/ui/attributes/issue-100631.stderr new file mode 100644 index 000000000..caa5351dd --- /dev/null +++ b/tests/ui/attributes/issue-100631.stderr @@ -0,0 +1,12 @@ +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/issue-100631.rs:4:1 + | +LL | #[repr(C)] + | ^^^^^^^^^^ +LL | #[repr(C)] +LL | enum Foo {} + | -------- zero-variant enum + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0084`. diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs new file mode 100644 index 000000000..6c68e6b04 --- /dev/null +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs @@ -0,0 +1,13 @@ +// This checks that the attribute validation ICE in issue #105594 doesn't +// recur. +// +// ignore-thumbv8m.base +#![feature(cmse_nonsecure_entry)] + +fn main() {} + +#[track_caller] //~ ERROR attribute should be applied to a function +static _A: () = (); + +#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function +static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr new file mode 100644 index 000000000..c6b2d6e78 --- /dev/null +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr @@ -0,0 +1,26 @@ +error[E0739]: attribute should be applied to a function definition + --> $DIR/issue-105594-invalid-attr-validation.rs:9:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | static _A: () = (); + | ------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/issue-105594-invalid-attr-validation.rs:12:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | static _B: () = (); + | ------------------- not a function definition + +error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension + --> $DIR/issue-105594-invalid-attr-validation.rs:12:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0739, E0775. +For more information about an error, try `rustc --explain E0739`. diff --git a/tests/ui/attributes/issue-40962.rs b/tests/ui/attributes/issue-40962.rs new file mode 100644 index 000000000..7b91c0681 --- /dev/null +++ b/tests/ui/attributes/issue-40962.rs @@ -0,0 +1,11 @@ +// check-pass +macro_rules! m { + ($i:meta) => { + #[derive($i)] + struct S; + } +} + +m!(Clone); + +fn main() {} diff --git a/tests/ui/attributes/issue-90873.rs b/tests/ui/attributes/issue-90873.rs new file mode 100644 index 000000000..1411f6174 --- /dev/null +++ b/tests/ui/attributes/issue-90873.rs @@ -0,0 +1,9 @@ +#![u=||{static d=||1;}] +//~^ unexpected expression +//~| cannot find attribute `u` in this scope +//~| missing type for `static` item + +#![a={impl std::ops::Neg for i8 {}}] +//~^ ERROR unexpected expression +//~| ERROR cannot find attribute `a` in this scope +//~| ERROR `main` function not found in crate `issue_90873` diff --git a/tests/ui/attributes/issue-90873.stderr b/tests/ui/attributes/issue-90873.stderr new file mode 100644 index 000000000..894ec8341 --- /dev/null +++ b/tests/ui/attributes/issue-90873.stderr @@ -0,0 +1,44 @@ +error: unexpected expression: `|| + { + static d: _ = || 1; + }` + --> $DIR/issue-90873.rs:1:6 + | +LL | #![u=||{static d=||1;}] + | ^^^^^^^^^^^^^^^^^ + +error: unexpected expression: `{ + impl std::ops::Neg for i8 {} + }` + --> $DIR/issue-90873.rs:6:6 + | +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `u` in this scope + --> $DIR/issue-90873.rs:1:4 + | +LL | #![u=||{static d=||1;}] + | ^ + +error: cannot find attribute `a` in this scope + --> $DIR/issue-90873.rs:6:4 + | +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^ + +error[E0601]: `main` function not found in crate `issue_90873` + --> $DIR/issue-90873.rs:6:37 + | +LL | #![a={impl std::ops::Neg for i8 {}}] + | ^ consider adding a `main` function to `$DIR/issue-90873.rs` + +error: missing type for `static` item + --> $DIR/issue-90873.rs:1:17 + | +LL | #![u=||{static d=||1;}] + | ^ help: provide a type for the item: `: ` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/attributes/item-attributes.rs b/tests/ui/attributes/item-attributes.rs new file mode 100644 index 000000000..c6bf6c656 --- /dev/null +++ b/tests/ui/attributes/item-attributes.rs @@ -0,0 +1,174 @@ +// These are attributes of the implicit crate. Really this just needs to parse +// for completeness since .rs files linked from .rc files support this +// notation to specify their module's attributes + +// check-pass + +#![feature(rustc_attrs)] +#![rustc_dummy = "val"] +#![rustc_dummy = "val"] +#![rustc_dummy] +#![rustc_dummy(attr5)] + +// These are attributes of the following mod +#[rustc_dummy = "val"] +#[rustc_dummy = "val"] +mod test_first_item_in_file_mod {} + +mod test_single_attr_outer { + #[rustc_dummy = "val"] + pub static X: isize = 10; + + #[rustc_dummy = "val"] + pub fn f() {} + + #[rustc_dummy = "val"] + pub mod mod1 {} + + pub mod rustrt { + #[rustc_dummy = "val"] + extern "C" {} + } +} + +mod test_multi_attr_outer { + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + pub static X: isize = 10; + + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + pub fn f() {} + + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + pub mod mod1 {} + + pub mod rustrt { + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + extern "C" {} + } + + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + struct T { + x: isize, + } +} + +mod test_stmt_single_attr_outer { + pub fn f() { + #[rustc_dummy = "val"] + static X: isize = 10; + + #[rustc_dummy = "val"] + fn f() {} + + #[rustc_dummy = "val"] + mod mod1 {} + + mod rustrt { + #[rustc_dummy = "val"] + extern "C" {} + } + } +} + +mod test_stmt_multi_attr_outer { + pub fn f() { + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + static X: isize = 10; + + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + fn f() {} + + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + mod mod1 {} + + mod rustrt { + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + extern "C" {} + } + } +} + +mod test_attr_inner { + pub mod m { + // This is an attribute of mod m + #![rustc_dummy = "val"] + } +} + +mod test_attr_inner_then_outer { + pub mod m { + // This is an attribute of mod m + #![rustc_dummy = "val"] + // This is an attribute of fn f + #[rustc_dummy = "val"] + fn f() {} + } +} + +mod test_attr_inner_then_outer_multi { + pub mod m { + // This is an attribute of mod m + #![rustc_dummy = "val"] + #![rustc_dummy = "val"] + // This is an attribute of fn f + #[rustc_dummy = "val"] + #[rustc_dummy = "val"] + fn f() {} + } +} + +mod test_distinguish_syntax_ext { + pub fn f() { + format!("test{}", "s"); + #[rustc_dummy = "val"] + fn g() {} + } +} + +mod test_other_forms { + #[rustc_dummy] + #[rustc_dummy(word)] + #[rustc_dummy(attr(word))] + #[rustc_dummy(key1 = "val", key2 = "val", attr)] + pub fn f() {} +} + +mod test_foreign_items { + pub mod rustrt { + extern "C" { + #![rustc_dummy] + + #[rustc_dummy] + fn rust_get_test_int() -> u32; + } + } +} + +// FIXME(#623): - these aren't supported yet +/*mod test_literals { + #![str = "s"] + #![char = 'c'] + #![isize = 100] + #![usize = 100_usize] + #![mach_int = 100u32] + #![float = 1.0] + #![mach_float = 1.0f32] + #![nil = ()] + #![bool = true] + mod m {} +}*/ + +fn test_fn_inner() { + #![rustc_dummy] +} + +fn main() {} diff --git a/tests/ui/attributes/key-value-expansion-on-mac.rs b/tests/ui/attributes/key-value-expansion-on-mac.rs new file mode 100644 index 000000000..c1d68d8cd --- /dev/null +++ b/tests/ui/attributes/key-value-expansion-on-mac.rs @@ -0,0 +1,14 @@ +#![feature(rustc_attrs)] + +#[rustc_dummy = stringify!(a)] // OK +macro_rules! bar { + () => {}; +} + +// FIXME?: `bar` here expands before `stringify` has a chance to expand. +// `#[rustc_dummy = ...]` is validated and dropped during expansion of `bar`, +// the "unexpected expression" errors comes from the validation. +#[rustc_dummy = stringify!(b)] //~ ERROR unexpected expression: `stringify!(b)` +bar!(); + +fn main() {} diff --git a/tests/ui/attributes/key-value-expansion-on-mac.stderr b/tests/ui/attributes/key-value-expansion-on-mac.stderr new file mode 100644 index 000000000..64ab892d9 --- /dev/null +++ b/tests/ui/attributes/key-value-expansion-on-mac.stderr @@ -0,0 +1,8 @@ +error: unexpected expression: `stringify!(b)` + --> $DIR/key-value-expansion-on-mac.rs:11:17 + | +LL | #[rustc_dummy = stringify!(b)] + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/key-value-expansion.rs b/tests/ui/attributes/key-value-expansion.rs new file mode 100644 index 000000000..83d601e5e --- /dev/null +++ b/tests/ui/attributes/key-value-expansion.rs @@ -0,0 +1,55 @@ +// Regression tests for issue #55414, expansion happens in the value of a key-value attribute, +// and the expanded expression is more complex than simply a macro call. + +// aux-build:key-value-expansion.rs + +#![feature(rustc_attrs)] + +extern crate key_value_expansion; + +// Minimized test case. + +macro_rules! bug { + ($expr:expr) => { + #[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc` + struct S; + }; +} + +// Any expressions containing macro call `X` that's more complex than `X` itself. +// Parentheses will work. +bug!((column!())); //~ ERROR unexpected expression: `(7u32)` + +// Original test case. + +macro_rules! bug { + () => { + bug!("bug" + stringify!(found)); //~ ERROR unexpected expression: `"bug" + "found"` + }; + ($test:expr) => { + #[doc = $test] + struct Test {} + }; +} + +bug!(); + +// Test case from #66804. + +macro_rules! doc_comment { + ($x:expr) => { + #[doc = $x] + extern {} + }; +} + +macro_rules! some_macro { + ($t1: ty) => { + doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} + //~^ ERROR unexpected expression: `{ + }; +} + +some_macro!(u8); + +fn main() {} diff --git a/tests/ui/attributes/key-value-expansion.stderr b/tests/ui/attributes/key-value-expansion.stderr new file mode 100644 index 000000000..1b776322a --- /dev/null +++ b/tests/ui/attributes/key-value-expansion.stderr @@ -0,0 +1,35 @@ +error: unexpected expression: `(7u32)` + --> $DIR/key-value-expansion.rs:21:6 + | +LL | bug!((column!())); + | ^^^^^^^^^^^ + +error: unexpected expression: `"bug" + "found"` + --> $DIR/key-value-expansion.rs:27:14 + | +LL | bug!("bug" + stringify!(found)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | bug!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected expression: `{ + let res = + ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""], + &[::core::fmt::ArgumentV1::new_display(&"u8")])); + res + }.as_str()` + --> $DIR/key-value-expansion.rs:48:23 + | +LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | some_macro!(u8); + | --------------- in this macro invocation + | + = note: this error originates in the macro `some_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/attributes/key-value-non-ascii.rs b/tests/ui/attributes/key-value-non-ascii.rs new file mode 100644 index 000000000..e14e2fc05 --- /dev/null +++ b/tests/ui/attributes/key-value-non-ascii.rs @@ -0,0 +1,4 @@ +#![feature(rustc_attrs)] + +#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte string literal +fn main() {} diff --git a/tests/ui/attributes/key-value-non-ascii.stderr b/tests/ui/attributes/key-value-non-ascii.stderr new file mode 100644 index 000000000..23d482de6 --- /dev/null +++ b/tests/ui/attributes/key-value-non-ascii.stderr @@ -0,0 +1,13 @@ +error: non-ASCII character in byte string literal + --> $DIR/key-value-non-ascii.rs:3:19 + | +LL | #[rustc_dummy = b"ffi.rs"] + | ^ must be ASCII + | +help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes + | +LL | #[rustc_dummy = b"/xEF/xAC/x83.rs"] + | ~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/log-backtrace.rs b/tests/ui/attributes/log-backtrace.rs new file mode 100644 index 000000000..3979d2001 --- /dev/null +++ b/tests/ui/attributes/log-backtrace.rs @@ -0,0 +1,9 @@ +// run-pass +// +// This test makes sure that log-backtrace option doesn't give a compilation error. +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr +// rustc-env:RUSTC_LOG=info +// compile-flags: -Zlog-backtrace=rustc_metadata::creader +fn main() {} diff --git a/tests/ui/attributes/main-removed-1.rs b/tests/ui/attributes/main-removed-1.rs new file mode 100644 index 000000000..0e887469d --- /dev/null +++ b/tests/ui/attributes/main-removed-1.rs @@ -0,0 +1,2 @@ +#[main] //~ ERROR cannot find attribute `main` in this scope +fn main() {} diff --git a/tests/ui/attributes/main-removed-1.stderr b/tests/ui/attributes/main-removed-1.stderr new file mode 100644 index 000000000..2422c5c3b --- /dev/null +++ b/tests/ui/attributes/main-removed-1.stderr @@ -0,0 +1,10 @@ +error: cannot find attribute `main` in this scope + --> $DIR/main-removed-1.rs:1:3 + | +LL | #[main] + | ^^^^ + | + = note: `main` is in scope, but it is a function, not an attribute + +error: aborting due to previous error + diff --git a/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs b/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs new file mode 100644 index 000000000..196b5be2d --- /dev/null +++ b/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn main(_: TokenStream, input: TokenStream) -> TokenStream { + "fn main() { println!(\"Hello Tokyo!\"); }".parse().unwrap() +} diff --git a/tests/ui/attributes/main-removed-2/main.rs b/tests/ui/attributes/main-removed-2/main.rs new file mode 100644 index 000000000..e8fecf825 --- /dev/null +++ b/tests/ui/attributes/main-removed-2/main.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:tokyo.rs +// compile-flags:--extern tokyo +// edition:2021 + +use tokyo::main; + +#[main] +fn main() { + panic!("the #[main] macro should replace this with non-panicking code") +} diff --git a/tests/ui/attributes/method-attributes.rs b/tests/ui/attributes/method-attributes.rs new file mode 100644 index 000000000..67439718b --- /dev/null +++ b/tests/ui/attributes/method-attributes.rs @@ -0,0 +1,28 @@ +// build-pass (FIXME(62277): could be check-pass?) +// pp-exact - Make sure we print all the attributes +// pretty-expanded FIXME #23616 + +#![feature(rustc_attrs)] + +#[rustc_dummy] +trait Frobable { + #[rustc_dummy] + fn frob(&self); + #[rustc_dummy] + fn defrob(&self); +} + +#[rustc_dummy] +impl Frobable for isize { + #[rustc_dummy] + fn frob(&self) { + #![rustc_dummy] + } + + #[rustc_dummy] + fn defrob(&self) { + #![rustc_dummy] + } +} + +fn main() {} diff --git a/tests/ui/attributes/multiple-invalid.rs b/tests/ui/attributes/multiple-invalid.rs new file mode 100644 index 000000000..ae044eb84 --- /dev/null +++ b/tests/ui/attributes/multiple-invalid.rs @@ -0,0 +1,10 @@ +// This test checks that all expected errors occur when there are multiple invalid attributes +// on an item. + +#[inline] +//~^ ERROR attribute should be applied to function or closure [E0518] +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +const FOO: u8 = 0; + +fn main() { } diff --git a/tests/ui/attributes/multiple-invalid.stderr b/tests/ui/attributes/multiple-invalid.stderr new file mode 100644 index 000000000..a8dba0ba3 --- /dev/null +++ b/tests/ui/attributes/multiple-invalid.stderr @@ -0,0 +1,21 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/multiple-invalid.rs:4:1 + | +LL | #[inline] + | ^^^^^^^^^ +... +LL | const FOO: u8 = 0; + | ------------------ not a function or closure + +error: attribute should be applied to a function definition + --> $DIR/multiple-invalid.rs:6:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | const FOO: u8 = 0; + | ------------------ not a function definition + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/attributes/nonterminal-expansion.rs b/tests/ui/attributes/nonterminal-expansion.rs new file mode 100644 index 000000000..97bf225f0 --- /dev/null +++ b/tests/ui/attributes/nonterminal-expansion.rs @@ -0,0 +1,18 @@ +// Macros were previously expanded in `Expr` nonterminal tokens, now they are not. + +macro_rules! pass_nonterminal { + ($n:expr) => { + #[repr(align($n))] + //~^ ERROR expected unsuffixed literal or identifier, found `n!()` + //~| ERROR incorrect `repr(align)` attribute format + struct S; + }; +} + +macro_rules! n { + () => { 32 }; +} + +pass_nonterminal!(n!()); + +fn main() {} diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr new file mode 100644 index 000000000..52376ac19 --- /dev/null +++ b/tests/ui/attributes/nonterminal-expansion.stderr @@ -0,0 +1,25 @@ +error: expected unsuffixed literal or identifier, found `n!()` + --> $DIR/nonterminal-expansion.rs:5:22 + | +LL | #[repr(align($n))] + | ^^ +... +LL | pass_nonterminal!(n!()); + | ----------------------- in this macro invocation + | + = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/nonterminal-expansion.rs:5:16 + | +LL | #[repr(align($n))] + | ^^^^^^^^^ +... +LL | pass_nonterminal!(n!()); + | ----------------------- in this macro invocation + | + = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0693`. diff --git a/tests/ui/attributes/obsolete-attr.rs b/tests/ui/attributes/obsolete-attr.rs new file mode 100644 index 000000000..7019abcaf --- /dev/null +++ b/tests/ui/attributes/obsolete-attr.rs @@ -0,0 +1,9 @@ +// Obsolete attributes fall back to unstable custom attributes. + +#[ab_isize = "stdcall"] extern "C" {} +//~^ ERROR cannot find attribute `ab_isize` in this scope + +#[fixed_stack_segment] fn f() {} +//~^ ERROR cannot find attribute `fixed_stack_segment` in this scope + +fn main() {} diff --git a/tests/ui/attributes/obsolete-attr.stderr b/tests/ui/attributes/obsolete-attr.stderr new file mode 100644 index 000000000..37c1cd0c9 --- /dev/null +++ b/tests/ui/attributes/obsolete-attr.stderr @@ -0,0 +1,14 @@ +error: cannot find attribute `fixed_stack_segment` in this scope + --> $DIR/obsolete-attr.rs:6:3 + | +LL | #[fixed_stack_segment] fn f() {} + | ^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `ab_isize` in this scope + --> $DIR/obsolete-attr.rs:3:3 + | +LL | #[ab_isize = "stdcall"] extern "C" {} + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attributes/suffixed-literal-meta.rs b/tests/ui/attributes/suffixed-literal-meta.rs new file mode 100644 index 000000000..a6531490c --- /dev/null +++ b/tests/ui/attributes/suffixed-literal-meta.rs @@ -0,0 +1,15 @@ +#![feature(rustc_attrs)] + +#[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1u16] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1u32] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1u64] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1isize] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1i8] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1i16] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1i32] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1i64] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes +#[rustc_dummy = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes +fn main() {} diff --git a/tests/ui/attributes/suffixed-literal-meta.stderr b/tests/ui/attributes/suffixed-literal-meta.stderr new file mode 100644 index 000000000..5245ffead --- /dev/null +++ b/tests/ui/attributes/suffixed-literal-meta.stderr @@ -0,0 +1,98 @@ +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:3:17 + | +LL | #[rustc_dummy = 1usize] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:4:17 + | +LL | #[rustc_dummy = 1u8] + | ^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:5:17 + | +LL | #[rustc_dummy = 1u16] + | ^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:6:17 + | +LL | #[rustc_dummy = 1u32] + | ^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:7:17 + | +LL | #[rustc_dummy = 1u64] + | ^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:8:17 + | +LL | #[rustc_dummy = 1isize] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:9:17 + | +LL | #[rustc_dummy = 1i8] + | ^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:10:17 + | +LL | #[rustc_dummy = 1i16] + | ^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:11:17 + | +LL | #[rustc_dummy = 1i32] + | ^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:12:17 + | +LL | #[rustc_dummy = 1i64] + | ^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:13:17 + | +LL | #[rustc_dummy = 1.0f32] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: suffixed literals are not allowed in attributes + --> $DIR/suffixed-literal-meta.rs:14:17 + | +LL | #[rustc_dummy = 1.0f64] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: aborting due to 12 previous errors + diff --git a/tests/ui/attributes/tool_attributes.rs b/tests/ui/attributes/tool_attributes.rs new file mode 100644 index 000000000..be4a10c0e --- /dev/null +++ b/tests/ui/attributes/tool_attributes.rs @@ -0,0 +1,13 @@ +// run-pass +// Scoped attributes should not trigger an unused attributes lint. + +#![deny(unused_attributes)] + +fn main() { + #[rustfmt::skip] + foo (); +} + +fn foo() { + assert!(true); +} diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs b/tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs new file mode 100644 index 000000000..74fbae035 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs @@ -0,0 +1,33 @@ +#![feature(rustc_private)] +extern crate libc; + +/// So tests don't have to bring libc in scope themselves +pub enum SignalHandler { + Ignore, + Default, +} + +/// Helper to assert that [`libc::SIGPIPE`] has the expected signal handler. +pub fn assert_sigpipe_handler(expected_handler: SignalHandler) { + #[cfg(unix)] + #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + target_os = "horizon", + target_os = "android", + )))] + { + let prev = unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN) }; + + let expected = match expected_handler { + SignalHandler::Ignore => libc::SIG_IGN, + SignalHandler::Default => libc::SIG_DFL, + }; + assert_eq!(prev, expected, "expected sigpipe value matches actual value"); + + // Unlikely to matter, but restore the old value anyway + unsafe { + libc::signal(libc::SIGPIPE, prev); + }; + } +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs new file mode 100644 index 000000000..d6d020c52 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs @@ -0,0 +1,4 @@ +#![feature(unix_sigpipe)] +#![unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute cannot be used at crate level + +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr new file mode 100644 index 000000000..a1fb4d678 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr @@ -0,0 +1,13 @@ +error: `unix_sigpipe` attribute cannot be used at crate level + --> $DIR/unix_sigpipe-crate.rs:2:1 + | +LL | #![unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[unix_sigpipe = "inherit"] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs new file mode 100644 index 000000000..294cb3852 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.rs @@ -0,0 +1,5 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "sig_ign"] +#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr new file mode 100644 index 000000000..2362c17a0 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-duplicates.stderr @@ -0,0 +1,14 @@ +error: multiple `unix_sigpipe` attributes + --> $DIR/unix_sigpipe-duplicates.rs:4:1 + | +LL | #[unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unix_sigpipe-duplicates.rs:3:1 + | +LL | #[unix_sigpipe = "sig_ign"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs new file mode 100644 index 000000000..0a42a5b5e --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-error.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:sigpipe-utils.rs + +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "sig_ign"] +fn main() { + extern crate sigpipe_utils; + + // #[unix_sigpipe = "sig_ign"] is active, so the legacy behavior of ignoring + // SIGPIPE shall be in effect + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs new file mode 100644 index 000000000..4f8648077 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:sigpipe-utils.rs + +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "inherit"] +fn main() { + extern crate sigpipe_utils; + + // #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored, + // instead the default handler shall be installed. (We assume that the + // process that runs these tests have the default handler.) + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs new file mode 100644 index 000000000..b5ebc07a0 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs @@ -0,0 +1,4 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe(inherit)] //~ error: malformed `unix_sigpipe` attribute input +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr new file mode 100644 index 000000000..59a87e139 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr @@ -0,0 +1,15 @@ +error: malformed `unix_sigpipe` attribute input + --> $DIR/unix_sigpipe-list.rs:3:1 + | +LL | #[unix_sigpipe(inherit)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL | #[unix_sigpipe = "inherit|sig_ign|sig_dfl"] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[unix_sigpipe] + | ~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs new file mode 100644 index 000000000..cde6719fc --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs @@ -0,0 +1,6 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` +fn f() {} + +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr new file mode 100644 index 000000000..c4b81118c --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr @@ -0,0 +1,8 @@ +error: `unix_sigpipe` attribute can only be used on `fn main()` + --> $DIR/unix_sigpipe-non-main-fn.rs:3:1 + | +LL | #[unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs new file mode 100644 index 000000000..16f727639 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs @@ -0,0 +1,8 @@ +#![feature(unix_sigpipe)] + +mod m { + #[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()` + fn main() {} +} + +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr new file mode 100644 index 000000000..a04f605ed --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr @@ -0,0 +1,8 @@ +error: `unix_sigpipe` attribute can only be used on root `fn main()` + --> $DIR/unix_sigpipe-non-root-main.rs:4:5 + | +LL | #[unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs new file mode 100644 index 000000000..100b4ce9f --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:sigpipe-utils.rs + +fn main() { + extern crate sigpipe_utils; + + // SIGPIPE shall be ignored since #[unix_sigpipe = "..."] is not used + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs new file mode 100644 index 000000000..b5adc2e55 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:sigpipe-utils.rs + +#![feature(unix_sigpipe)] + +fn main() { + extern crate sigpipe_utils; + + // Only #![feature(unix_sigpipe)] is enabled, not #[unix_sigpipe = "..."]. + // This shall not change any behavior, so we still expect SIGPIPE to be + // ignored + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs new file mode 100644 index 000000000..6befb9e95 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-rustc_main.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:sigpipe-utils.rs + +#![feature(unix_sigpipe)] +#![feature(rustc_attrs)] + +#[unix_sigpipe = "sig_dfl"] +#[rustc_main] +fn rustc_main() { + extern crate sigpipe_utils; + + // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE handler shall be + // SIG_DFL. Note that we have a #[rustc_main], but it should still work. + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs new file mode 100644 index 000000000..238c0d57a --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-sig_dfl.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:sigpipe-utils.rs + +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "sig_dfl"] +fn main() { + extern crate sigpipe_utils; + + // #[unix_sigpipe = "sig_dfl"] is active, so SIGPIPE shall NOT be ignored, instead + // the default handler shall be installed + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs new file mode 100644 index 000000000..64fd5ec4f --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs @@ -0,0 +1,6 @@ +#![feature(start)] +#![feature(unix_sigpipe)] + +#[start] +#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` +fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 } diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr new file mode 100644 index 000000000..2c9ce479b --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr @@ -0,0 +1,8 @@ +error: `unix_sigpipe` attribute can only be used on `fn main()` + --> $DIR/unix_sigpipe-start.rs:5:1 + | +LL | #[unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs new file mode 100644 index 000000000..a5e47cfeb --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs @@ -0,0 +1,6 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()` +struct S; + +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr new file mode 100644 index 000000000..c56ee60bb --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr @@ -0,0 +1,8 @@ +error: `unix_sigpipe` attribute can only be used on `fn main()` + --> $DIR/unix_sigpipe-struct.rs:3:1 + | +LL | #[unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs new file mode 100644 index 000000000..4ec25de00 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.rs @@ -0,0 +1,4 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "wrong"] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr new file mode 100644 index 000000000..a66e45aa2 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-wrong.stderr @@ -0,0 +1,8 @@ +error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` + --> $DIR/unix_sigpipe-wrong.rs:3:1 + | +LL | #[unix_sigpipe = "wrong"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe.rs new file mode 100644 index 000000000..7bf1c7350 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe.rs @@ -0,0 +1,4 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr new file mode 100644 index 000000000..1b1eda825 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe.stderr @@ -0,0 +1,8 @@ +error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` + --> $DIR/unix_sigpipe.rs:3:1 + | +LL | #[unix_sigpipe] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/unknown-attr.rs b/tests/ui/attributes/unknown-attr.rs new file mode 100644 index 000000000..70fef04e9 --- /dev/null +++ b/tests/ui/attributes/unknown-attr.rs @@ -0,0 +1,12 @@ +// Unknown attributes fall back to unstable custom attributes. + +#![feature(custom_inner_attributes)] + +#![mutable_doc] +//~^ ERROR cannot find attribute `mutable_doc` in this scope + +#[dance] mod a {} +//~^ ERROR cannot find attribute `dance` in this scope + +#[dance] fn main() {} +//~^ ERROR cannot find attribute `dance` in this scope diff --git a/tests/ui/attributes/unknown-attr.stderr b/tests/ui/attributes/unknown-attr.stderr new file mode 100644 index 000000000..85c227dc8 --- /dev/null +++ b/tests/ui/attributes/unknown-attr.stderr @@ -0,0 +1,20 @@ +error: cannot find attribute `mutable_doc` in this scope + --> $DIR/unknown-attr.rs:5:4 + | +LL | #![mutable_doc] + | ^^^^^^^^^^^ + +error: cannot find attribute `dance` in this scope + --> $DIR/unknown-attr.rs:8:3 + | +LL | #[dance] mod a {} + | ^^^^^ + +error: cannot find attribute `dance` in this scope + --> $DIR/unknown-attr.rs:11:3 + | +LL | #[dance] fn main() {} + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/attributes/unnamed-field-attributes-dup.rs b/tests/ui/attributes/unnamed-field-attributes-dup.rs new file mode 100644 index 000000000..7edfd0337 --- /dev/null +++ b/tests/ui/attributes/unnamed-field-attributes-dup.rs @@ -0,0 +1,11 @@ +// Duplicate non-builtin attributes can be used on unnamed fields. + +// check-pass + +struct S ( + #[rustfmt::skip] + #[rustfmt::skip] + u8 +); + +fn main() {} diff --git a/tests/ui/attributes/unnamed-field-attributes-vis.rs b/tests/ui/attributes/unnamed-field-attributes-vis.rs new file mode 100644 index 000000000..d12155f6d --- /dev/null +++ b/tests/ui/attributes/unnamed-field-attributes-vis.rs @@ -0,0 +1,11 @@ +// Unnamed fields don't lose their visibility due to non-builtin attributes on them. + +// check-pass + +mod m { + pub struct S(#[rustfmt::skip] pub u8); +} + +fn main() { + m::S(0); +} diff --git a/tests/ui/attributes/unnamed-field-attributes.rs b/tests/ui/attributes/unnamed-field-attributes.rs new file mode 100644 index 000000000..93f364047 --- /dev/null +++ b/tests/ui/attributes/unnamed-field-attributes.rs @@ -0,0 +1,9 @@ +// check-pass + +struct S( + #[rustfmt::skip] u8, + u16, + #[rustfmt::skip] u32, +); + +fn main() {} diff --git a/tests/ui/attributes/unrestricted-attribute-tokens.rs b/tests/ui/attributes/unrestricted-attribute-tokens.rs new file mode 100644 index 000000000..e31bc91a0 --- /dev/null +++ b/tests/ui/attributes/unrestricted-attribute-tokens.rs @@ -0,0 +1,8 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(rustc_attrs)] + +#[rustc_dummy(a b c d)] +#[rustc_dummy[a b c d]] +#[rustc_dummy{a b c d}] +fn main() {} diff --git a/tests/ui/attributes/unused-item-in-attr.rs b/tests/ui/attributes/unused-item-in-attr.rs new file mode 100644 index 000000000..70dcd5413 --- /dev/null +++ b/tests/ui/attributes/unused-item-in-attr.rs @@ -0,0 +1,6 @@ +#[w = { extern crate alloc; }] +//~^ ERROR unexpected expression: `{ +//~| ERROR cannot find attribute `w` in this scope +fn f() {} + +fn main() {} diff --git a/tests/ui/attributes/unused-item-in-attr.stderr b/tests/ui/attributes/unused-item-in-attr.stderr new file mode 100644 index 000000000..92a8f5858 --- /dev/null +++ b/tests/ui/attributes/unused-item-in-attr.stderr @@ -0,0 +1,16 @@ +error: unexpected expression: `{ + extern crate alloc; + }` + --> $DIR/unused-item-in-attr.rs:1:7 + | +LL | #[w = { extern crate alloc; }] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `w` in this scope + --> $DIR/unused-item-in-attr.rs:1:3 + | +LL | #[w = { extern crate alloc; }] + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attributes/used_with_arg.rs b/tests/ui/attributes/used_with_arg.rs new file mode 100644 index 000000000..ad80ff53f --- /dev/null +++ b/tests/ui/attributes/used_with_arg.rs @@ -0,0 +1,19 @@ +#![feature(used_with_arg)] + +#[used(linker)] +static mut USED_LINKER: [usize; 1] = [0]; + +#[used(compiler)] +static mut USED_COMPILER: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together +#[used(linker)] +static mut USED_COMPILER_LINKER2: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together +#[used(linker)] +#[used(compiler)] +#[used(linker)] +static mut USED_COMPILER_LINKER3: [usize; 1] = [0]; + +fn main() {} diff --git a/tests/ui/attributes/used_with_arg.stderr b/tests/ui/attributes/used_with_arg.stderr new file mode 100644 index 000000000..440e5c4a5 --- /dev/null +++ b/tests/ui/attributes/used_with_arg.stderr @@ -0,0 +1,18 @@ +error: `used(compiler)` and `used(linker)` can't be used together + --> $DIR/used_with_arg.rs:9:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + +error: `used(compiler)` and `used(linker)` can't be used together + --> $DIR/used_with_arg.rs:13:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attributes/used_with_arg_no_mangle.rs b/tests/ui/attributes/used_with_arg_no_mangle.rs new file mode 100644 index 000000000..d0bbe76ef --- /dev/null +++ b/tests/ui/attributes/used_with_arg_no_mangle.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(used_with_arg)] + +#[used(linker)] +#[no_mangle] // accidentally detected as `used(compiler)` +pub static GLOB: usize = 0; + +fn main() {} diff --git a/tests/ui/attributes/used_with_multi_args.rs b/tests/ui/attributes/used_with_multi_args.rs new file mode 100644 index 000000000..2e17fcfd7 --- /dev/null +++ b/tests/ui/attributes/used_with_multi_args.rs @@ -0,0 +1,6 @@ +#![feature(used_with_arg)] + +#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)` +static mut USED_COMPILER_LINKER: [usize; 1] = [0]; + +fn main() {} diff --git a/tests/ui/attributes/used_with_multi_args.stderr b/tests/ui/attributes/used_with_multi_args.stderr new file mode 100644 index 000000000..c93aafcfc --- /dev/null +++ b/tests/ui/attributes/used_with_multi_args.stderr @@ -0,0 +1,8 @@ +error: expected `used`, `used(compiler)` or `used(linker)` + --> $DIR/used_with_multi_args.rs:3:1 + | +LL | #[used(compiler, linker)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/attributes/variant-attributes.rs b/tests/ui/attributes/variant-attributes.rs new file mode 100644 index 000000000..ffcdeb52a --- /dev/null +++ b/tests/ui/attributes/variant-attributes.rs @@ -0,0 +1,37 @@ +// build-pass (FIXME(62277): could be check-pass?) +// pp-exact - Make sure we actually print the attributes +// pretty-expanded FIXME #23616 + +#![allow(non_camel_case_types)] +#![feature(rustc_attrs)] + +enum crew_of_enterprise_d { + + #[rustc_dummy] + jean_luc_picard, + + #[rustc_dummy] + william_t_riker, + + #[rustc_dummy] + beverly_crusher, + + #[rustc_dummy] + deanna_troi, + + #[rustc_dummy] + data, + + #[rustc_dummy] + worf, + + #[rustc_dummy] + geordi_la_forge, +} + +fn boldly_go(_crew_member: crew_of_enterprise_d, _where: String) { } + +fn main() { + boldly_go(crew_of_enterprise_d::worf, + "where no one has gone before".to_string()); +} diff --git a/tests/ui/attributes/z-crate-attr.rs b/tests/ui/attributes/z-crate-attr.rs new file mode 100644 index 000000000..1021774fc --- /dev/null +++ b/tests/ui/attributes/z-crate-attr.rs @@ -0,0 +1,12 @@ +// run-pass +// This test checks if an unstable feature is enabled with the -Zcrate-attr=feature(foo) flag. If +// the exact feature used here is causing problems feel free to replace it with another +// perma-unstable feature. + +// compile-flags: -Zcrate-attr=feature(abi_unadjusted) + +#![allow(dead_code)] + +extern "unadjusted" fn foo() {} + +fn main() {} diff --git a/tests/ui/attrs-resolution-errors.rs b/tests/ui/attrs-resolution-errors.rs new file mode 100644 index 000000000..8770fb1de --- /dev/null +++ b/tests/ui/attrs-resolution-errors.rs @@ -0,0 +1,40 @@ +enum FooEnum { + #[test] + //~^ ERROR expected non-macro attribute, found attribute macro + Bar(i32), +} + +struct FooStruct { + #[test] + //~^ ERROR expected non-macro attribute, found attribute macro + bar: i32, +} + +fn main() { + let foo_enum_bar = FooEnum::Bar(1); + match foo_enum_bar { + FooEnum::Bar(x) => {}, + _ => {} + } + + let foo_struct = FooStruct { bar: 1 }; + match foo_struct { + FooStruct { + #[test] bar + //~^ ERROR expected non-macro attribute, found attribute macro + } => {} + } + + match 1 { + 0 => {} + #[test] + //~^ ERROR expected non-macro attribute, found attribute macro + _ => {} + } + + let _another_foo_strunct = FooStruct { + #[test] + //~^ ERROR expected non-macro attribute, found attribute macro + bar: 1, + }; +} diff --git a/tests/ui/attrs-resolution-errors.stderr b/tests/ui/attrs-resolution-errors.stderr new file mode 100644 index 000000000..883f96e5c --- /dev/null +++ b/tests/ui/attrs-resolution-errors.stderr @@ -0,0 +1,32 @@ +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/attrs-resolution-errors.rs:2:7 + | +LL | #[test] + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/attrs-resolution-errors.rs:8:7 + | +LL | #[test] + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/attrs-resolution-errors.rs:23:15 + | +LL | #[test] bar + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/attrs-resolution-errors.rs:30:11 + | +LL | #[test] + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/attrs-resolution-errors.rs:36:11 + | +LL | #[test] + | ^^^^ not a non-macro attribute + +error: aborting due to 5 previous errors + diff --git a/tests/ui/attrs-resolution.rs b/tests/ui/attrs-resolution.rs new file mode 100644 index 000000000..680977323 --- /dev/null +++ b/tests/ui/attrs-resolution.rs @@ -0,0 +1,37 @@ +// check-pass + +enum FooEnum { + #[rustfmt::skip] + Bar(i32), +} + +struct FooStruct { + #[rustfmt::skip] + bar: i32, +} + +fn main() { + let foo_enum_bar = FooEnum::Bar(1); + match foo_enum_bar { + FooEnum::Bar(x) => {} + _ => {} + } + + let foo_struct = FooStruct { bar: 1 }; + match foo_struct { + FooStruct { + #[rustfmt::skip] bar + } => {} + } + + match 1 { + 0 => {} + #[rustfmt::skip] + _ => {} + } + + let _another_foo_strunct = FooStruct { + #[rustfmt::skip] + bar: 1, + }; +} diff --git a/tests/ui/augmented-assignments-feature-gate-cross.rs b/tests/ui/augmented-assignments-feature-gate-cross.rs new file mode 100644 index 000000000..84988feb6 --- /dev/null +++ b/tests/ui/augmented-assignments-feature-gate-cross.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:augmented_assignments.rs + +extern crate augmented_assignments; + +use augmented_assignments::Int; + +fn main() { + let mut x = Int(0); + x += 1; +} diff --git a/tests/ui/augmented-assignments-rpass.rs b/tests/ui/augmented-assignments-rpass.rs new file mode 100644 index 000000000..fb383cc57 --- /dev/null +++ b/tests/ui/augmented-assignments-rpass.rs @@ -0,0 +1,172 @@ +// run-pass + +#![allow(unused_imports)] +#![deny(unused_assignments)] + +use std::mem; +use std::ops::{ + AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, Index, MulAssign, RemAssign, + ShlAssign, ShrAssign, SubAssign, +}; + +#[derive(Debug, PartialEq)] +struct Int(i32); + +struct Slice([i32]); + +impl Slice { + fn new(slice: &mut [i32]) -> &mut Slice { + unsafe { + mem::transmute(slice) + } + } +} + +struct View<'a>(&'a mut [i32]); + +fn main() { + let mut x = Int(1); + + x += Int(2); + assert_eq!(x, Int(0b11)); + + x &= Int(0b01); + assert_eq!(x, Int(0b01)); + + x |= Int(0b10); + assert_eq!(x, Int(0b11)); + + x ^= Int(0b01); + assert_eq!(x, Int(0b10)); + + x /= Int(2); + assert_eq!(x, Int(1)); + + x *= Int(3); + assert_eq!(x, Int(3)); + + x %= Int(2); + assert_eq!(x, Int(1)); + + // overloaded RHS + x <<= 1u8; + assert_eq!(x, Int(2)); + + x <<= 1u16; + assert_eq!(x, Int(4)); + + x >>= 1u8; + assert_eq!(x, Int(2)); + + x >>= 1u16; + assert_eq!(x, Int(1)); + + x -= Int(1); + assert_eq!(x, Int(0)); + + // indexed LHS + let mut v = vec![Int(1), Int(2)]; + v[0] += Int(2); + assert_eq!(v[0], Int(3)); + + // unsized RHS + let mut array = [0, 1, 2]; + *Slice::new(&mut array) += 1; + assert_eq!(array[0], 1); + assert_eq!(array[1], 2); + assert_eq!(array[2], 3); + + // sized indirection + // check that this does *not* trigger the unused_assignments lint + let mut array = [0, 1, 2]; + let mut view = View(&mut array); + view += 1; +} + +impl AddAssign for Int { + fn add_assign(&mut self, rhs: Int) { + self.0 += rhs.0; + } +} + +impl BitAndAssign for Int { + fn bitand_assign(&mut self, rhs: Int) { + self.0 &= rhs.0; + } +} + +impl BitOrAssign for Int { + fn bitor_assign(&mut self, rhs: Int) { + self.0 |= rhs.0; + } +} + +impl BitXorAssign for Int { + fn bitxor_assign(&mut self, rhs: Int) { + self.0 ^= rhs.0; + } +} + +impl DivAssign for Int { + fn div_assign(&mut self, rhs: Int) { + self.0 /= rhs.0; + } +} + +impl MulAssign for Int { + fn mul_assign(&mut self, rhs: Int) { + self.0 *= rhs.0; + } +} + +impl RemAssign for Int { + fn rem_assign(&mut self, rhs: Int) { + self.0 %= rhs.0; + } +} + +impl ShlAssign for Int { + fn shl_assign(&mut self, rhs: u8) { + self.0 <<= rhs; + } +} + +impl ShlAssign for Int { + fn shl_assign(&mut self, rhs: u16) { + self.0 <<= rhs; + } +} + +impl ShrAssign for Int { + fn shr_assign(&mut self, rhs: u8) { + self.0 >>= rhs; + } +} + +impl ShrAssign for Int { + fn shr_assign(&mut self, rhs: u16) { + self.0 >>= rhs; + } +} + +impl SubAssign for Int { + fn sub_assign(&mut self, rhs: Int) { + self.0 -= rhs.0; + } +} + +impl AddAssign for Slice { + fn add_assign(&mut self, rhs: i32) { + for lhs in &mut self.0 { + *lhs += rhs; + } + } +} + +impl<'a> AddAssign for View<'a> { + fn add_assign(&mut self, rhs: i32) { + for lhs in self.0.iter_mut() { + *lhs += rhs; + } + } +} diff --git a/tests/ui/augmented-assignments.rs b/tests/ui/augmented-assignments.rs new file mode 100644 index 000000000..20c7fb3a9 --- /dev/null +++ b/tests/ui/augmented-assignments.rs @@ -0,0 +1,27 @@ +use std::ops::AddAssign; + +struct Int(i32); + +impl AddAssign for Int { + fn add_assign(&mut self, _: Int) { + unimplemented!() + } +} + +fn main() { + let mut x = Int(1); + x + //~^ NOTE borrow of `x` occurs here + += + x; + //~^ ERROR cannot move out of `x` because it is borrowed + //~| move out of `x` occurs here + + let y = Int(2); + //~^ HELP consider changing this to be mutable + //~| SUGGESTION mut + y //~ ERROR cannot borrow `y` as mutable, as it is not declared as mutable + //~| cannot borrow as mutable + += + Int(1); +} diff --git a/tests/ui/augmented-assignments.stderr b/tests/ui/augmented-assignments.stderr new file mode 100644 index 000000000..2910c910d --- /dev/null +++ b/tests/ui/augmented-assignments.stderr @@ -0,0 +1,24 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/augmented-assignments.rs:16:5 + | +LL | x + | - borrow of `x` occurs here +... +LL | x; + | ^ move out of `x` occurs here + +error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable + --> $DIR/augmented-assignments.rs:23:5 + | +LL | y + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut y = Int(2); + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0505, E0596. +For more information about an error, try `rustc --explain E0505`. diff --git a/tests/ui/auto-instantiate.rs b/tests/ui/auto-instantiate.rs new file mode 100644 index 000000000..a58b17828 --- /dev/null +++ b/tests/ui/auto-instantiate.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(dead_code)] +#[derive(Debug)] +struct Pair { a: T, b: U } +struct Triple { x: isize, y: isize, z: isize } + +fn f(x: T, y: U) -> Pair { return Pair {a: x, b: y}; } + +pub fn main() { + println!("{}", f(Triple {x: 3, y: 4, z: 5}, 4).a.x); + println!("{}", f(5, 6).a); +} diff --git a/tests/ui/auto-ref-slice-plus-ref.rs b/tests/ui/auto-ref-slice-plus-ref.rs new file mode 100644 index 000000000..00b279d32 --- /dev/null +++ b/tests/ui/auto-ref-slice-plus-ref.rs @@ -0,0 +1,27 @@ +fn main() { + + // Testing that method lookup does not automatically borrow + // vectors to slices then automatically create a self reference. + + let mut a = vec![0]; + a.test_mut(); //~ ERROR no method named `test_mut` found + a.test(); //~ ERROR no method named `test` found + + ([1]).test(); //~ ERROR no method named `test` found + (&[1]).test(); //~ ERROR no method named `test` found +} + +trait MyIter { + fn test_mut(&mut self); + fn test(&self); +} + +impl<'a> MyIter for &'a [isize] { + fn test_mut(&mut self) { } + fn test(&self) { } +} + +impl<'a> MyIter for &'a str { + fn test_mut(&mut self) { } + fn test(&self) { } +} diff --git a/tests/ui/auto-ref-slice-plus-ref.stderr b/tests/ui/auto-ref-slice-plus-ref.stderr new file mode 100644 index 000000000..e28830507 --- /dev/null +++ b/tests/ui/auto-ref-slice-plus-ref.stderr @@ -0,0 +1,55 @@ +error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in the current scope + --> $DIR/auto-ref-slice-plus-ref.rs:7:7 + | +LL | a.test_mut(); + | ^^^^^^^^ help: there is a method with a similar name: `get_mut` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test_mut`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for struct `Vec<{integer}>` in the current scope + --> $DIR/auto-ref-slice-plus-ref.rs:8:7 + | +LL | a.test(); + | ^^^^ method not found in `Vec<{integer}>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope + --> $DIR/auto-ref-slice-plus-ref.rs:10:11 + | +LL | ([1]).test(); + | ^^^^ method not found in `[{integer}; 1]` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope + --> $DIR/auto-ref-slice-plus-ref.rs:11:12 + | +LL | (&[1]).test(); + | ^^^^ method not found in `&[{integer}; 1]` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/auto-traits/auto-is-contextual.rs b/tests/ui/auto-traits/auto-is-contextual.rs new file mode 100644 index 000000000..a2ddd5374 --- /dev/null +++ b/tests/ui/auto-traits/auto-is-contextual.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(path_statements)] +#![allow(dead_code)] +macro_rules! auto { + () => (struct S;) +} + +auto!(); + +fn auto() {} + +fn main() { + auto(); + let auto = 10; + auto; + auto as u8; +} diff --git a/tests/ui/auto-traits/auto-trait-projection-recursion.rs b/tests/ui/auto-traits/auto-trait-projection-recursion.rs new file mode 100644 index 000000000..a36f26f02 --- /dev/null +++ b/tests/ui/auto-traits/auto-trait-projection-recursion.rs @@ -0,0 +1,34 @@ +// Checking the `Send` bound in `main` requires: +// +// checking as Y>::P: Send +// which normalizes to Box>>: Send +// which needs X>: Send +// which needs as Y>::P: Send +// +// At this point we used to normalize the predicate to `Box>>: Send` +// and continue in a loop where we created new region variables to the +// recursion limit. To avoid this we now "canonicalize" region variables to +// lowest unified region vid. This means we instead have to prove +// `Box>>: Send`, which we can because auto traits are coinductive. + +// check-pass + +// Avoid a really long error message if this regresses. +#![recursion_limit="20"] + +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box>>; +} + +struct C<'a>(&'a ()); +struct X(T::P); + +fn is_send() {} + +fn main() { + is_send::>>(); +} diff --git a/tests/ui/auto-traits/auto-trait-validation.fixed b/tests/ui/auto-traits/auto-trait-validation.fixed new file mode 100644 index 000000000..da878ac62 --- /dev/null +++ b/tests/ui/auto-traits/auto-trait-validation.fixed @@ -0,0 +1,13 @@ +#![feature(auto_traits)] + +// run-rustfix + +auto trait Generic {} +//~^ auto traits cannot have generic parameters [E0567] +auto trait Bound {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait LifetimeBound {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait MyTrait { } +//~^ auto traits cannot have associated items [E0380] +fn main() {} diff --git a/tests/ui/auto-traits/auto-trait-validation.rs b/tests/ui/auto-traits/auto-trait-validation.rs new file mode 100644 index 000000000..d43055e27 --- /dev/null +++ b/tests/ui/auto-traits/auto-trait-validation.rs @@ -0,0 +1,13 @@ +#![feature(auto_traits)] + +// run-rustfix + +auto trait Generic {} +//~^ auto traits cannot have generic parameters [E0567] +auto trait Bound : Copy {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait LifetimeBound : 'static {} +//~^ auto traits cannot have super traits or lifetime bounds [E0568] +auto trait MyTrait { fn foo() {} } +//~^ auto traits cannot have associated items [E0380] +fn main() {} diff --git a/tests/ui/auto-traits/auto-trait-validation.stderr b/tests/ui/auto-traits/auto-trait-validation.stderr new file mode 100644 index 000000000..2c380e5b0 --- /dev/null +++ b/tests/ui/auto-traits/auto-trait-validation.stderr @@ -0,0 +1,37 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/auto-trait-validation.rs:5:19 + | +LL | auto trait Generic {} + | -------^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:7:17 + | +LL | auto trait Bound : Copy {} + | -----^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/auto-trait-validation.rs:9:25 + | +LL | auto trait LifetimeBound : 'static {} + | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error[E0380]: auto traits cannot have associated items + --> $DIR/auto-trait-validation.rs:11:25 + | +LL | auto trait MyTrait { fn foo() {} } + | ------- ---^^^----- + | | | + | | help: remove these associated items + | auto trait cannot have associated items + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0380, E0567, E0568. +For more information about an error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/auto-traits.rs b/tests/ui/auto-traits/auto-traits.rs new file mode 100644 index 000000000..7b52d9c17 --- /dev/null +++ b/tests/ui/auto-traits/auto-traits.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(unused_doc_comments)] +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Auto {} +unsafe auto trait AutoUnsafe {} + +impl !Auto for bool {} +impl !AutoUnsafe for bool {} + +struct AutoBool(#[allow(unused_tuple_struct_fields)] bool); + +impl Auto for AutoBool {} +unsafe impl AutoUnsafe for AutoBool {} + +fn take_auto(_: T) {} +fn take_auto_unsafe(_: T) {} + +fn main() { + // Parse inside functions. + auto trait AutoInner {} + unsafe auto trait AutoUnsafeInner {} + + take_auto(0); + take_auto(AutoBool(true)); + take_auto_unsafe(0); + take_auto_unsafe(AutoBool(true)); + + /// Auto traits are allowed in trait object bounds. + let _: &(dyn Send + Auto) = &0; +} diff --git a/tests/ui/auto-traits/bad-generics-on-dyn.rs b/tests/ui/auto-traits/bad-generics-on-dyn.rs new file mode 100644 index 000000000..3f8ac14c7 --- /dev/null +++ b/tests/ui/auto-traits/bad-generics-on-dyn.rs @@ -0,0 +1,11 @@ +#![feature(auto_traits)] + +auto trait Trait1<'a> {} +//~^ ERROR auto traits cannot have generic parameters + +fn f<'a>(x: &dyn Trait1<'a>) +{} + +fn main() { + f(&1); +} diff --git a/tests/ui/auto-traits/bad-generics-on-dyn.stderr b/tests/ui/auto-traits/bad-generics-on-dyn.stderr new file mode 100644 index 000000000..ade69ced6 --- /dev/null +++ b/tests/ui/auto-traits/bad-generics-on-dyn.stderr @@ -0,0 +1,11 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/bad-generics-on-dyn.rs:3:18 + | +LL | auto trait Trait1<'a> {} + | ------^^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0567`. diff --git a/tests/ui/auto-traits/issue-23080-2.rs b/tests/ui/auto-traits/issue-23080-2.rs new file mode 100644 index 000000000..cb4cf6de1 --- /dev/null +++ b/tests/ui/auto-traits/issue-23080-2.rs @@ -0,0 +1,13 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +unsafe auto trait Trait { + type Output; //~ ERROR E0380 +} + +fn call_method(x: T) {} + +fn main() { + // ICE + call_method(()); +} diff --git a/tests/ui/auto-traits/issue-23080-2.stderr b/tests/ui/auto-traits/issue-23080-2.stderr new file mode 100644 index 000000000..267a712f6 --- /dev/null +++ b/tests/ui/auto-traits/issue-23080-2.stderr @@ -0,0 +1,11 @@ +error[E0380]: auto traits cannot have associated items + --> $DIR/issue-23080-2.rs:5:10 + | +LL | unsafe auto trait Trait { + | ----- auto trait cannot have associated items +LL | type Output; + | -----^^^^^^- help: remove these associated items + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/issue-23080.rs b/tests/ui/auto-traits/issue-23080.rs new file mode 100644 index 000000000..84e2ce66f --- /dev/null +++ b/tests/ui/auto-traits/issue-23080.rs @@ -0,0 +1,17 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +unsafe auto trait Trait { + fn method(&self) { //~ ERROR E0380 + println!("Hello"); + } +} + +fn call_method(x: T) { + x.method(); +} + +fn main() { + // ICE + call_method(()); +} diff --git a/tests/ui/auto-traits/issue-23080.stderr b/tests/ui/auto-traits/issue-23080.stderr new file mode 100644 index 000000000..c1b16b2f4 --- /dev/null +++ b/tests/ui/auto-traits/issue-23080.stderr @@ -0,0 +1,14 @@ +error[E0380]: auto traits cannot have associated items + --> $DIR/issue-23080.rs:5:8 + | +LL | unsafe auto trait Trait { + | ----- auto trait cannot have associated items +LL | fn method(&self) { + | _____- ^^^^^^ +LL | | println!("Hello"); +LL | | } + | |_____- help: remove these associated items + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0380`. diff --git a/tests/ui/auto-traits/issue-84075.rs b/tests/ui/auto-traits/issue-84075.rs new file mode 100644 index 000000000..a6afe24ea --- /dev/null +++ b/tests/ui/auto-traits/issue-84075.rs @@ -0,0 +1,16 @@ +// Regression test for issue #84075. + +#![feature(auto_traits)] + +auto trait Magic where Self: Copy {} //~ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/auto-traits/issue-84075.stderr b/tests/ui/auto-traits/issue-84075.stderr new file mode 100644 index 000000000..02dca598e --- /dev/null +++ b/tests/ui/auto-traits/issue-84075.stderr @@ -0,0 +1,11 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/issue-84075.rs:5:18 + | +LL | auto trait Magic where Self: Copy {} + | ----- ^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0568`. diff --git a/tests/ui/auto-traits/suspicious-impls-lint.rs b/tests/ui/auto-traits/suspicious-impls-lint.rs new file mode 100644 index 000000000..7712e84f4 --- /dev/null +++ b/tests/ui/auto-traits/suspicious-impls-lint.rs @@ -0,0 +1,50 @@ +#![deny(suspicious_auto_trait_impls)] + +use std::marker::PhantomData; + +struct MayImplementSendOk(T); +unsafe impl Send for MayImplementSendOk {} // ok + +struct MayImplementSendErr(T); +unsafe impl Send for MayImplementSendErr<&T> {} +//~^ ERROR +//~| WARNING this will change its meaning + +struct ContainsNonSendDirect(*const T); +unsafe impl Send for ContainsNonSendDirect<&T> {} // ok + +struct ContainsPtr(*const T); +struct ContainsIndirectNonSend(ContainsPtr); +unsafe impl Send for ContainsIndirectNonSend<&T> {} // ok + +struct ContainsVec(Vec); +unsafe impl Send for ContainsVec {} +//~^ ERROR +//~| WARNING this will change its meaning + +struct TwoParams(T, U); +unsafe impl Send for TwoParams {} // ok + +struct TwoParamsFlipped(T, U); +unsafe impl Send for TwoParamsFlipped {} // ok + +struct TwoParamsSame(T, U); +unsafe impl Send for TwoParamsSame {} +//~^ ERROR +//~| WARNING this will change its meaning + +pub struct WithPhantomDataNonSend(PhantomData<*const T>, U); +unsafe impl Send for WithPhantomDataNonSend {} // ok + +pub struct WithPhantomDataSend(PhantomData, U); +unsafe impl Send for WithPhantomDataSend<*const T, i8> {} +//~^ ERROR +//~| WARNING this will change its meaning + +pub struct WithLifetime<'a, T>(&'a (), T); +unsafe impl Send for WithLifetime<'static, T> {} // ok +unsafe impl Sync for WithLifetime<'static, Vec> {} +//~^ ERROR +//~| WARNING this will change its meaning + +fn main() {} diff --git a/tests/ui/auto-traits/suspicious-impls-lint.stderr b/tests/ui/auto-traits/suspicious-impls-lint.stderr new file mode 100644 index 000000000..9cd4e79f8 --- /dev/null +++ b/tests/ui/auto-traits/suspicious-impls-lint.stderr @@ -0,0 +1,82 @@ +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:9:1 + | +LL | unsafe impl Send for MayImplementSendErr<&T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 + = note: `&T` is not a generic parameter +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:8:1 + | +LL | struct MayImplementSendErr(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/suspicious-impls-lint.rs:1:9 + | +LL | #![deny(suspicious_auto_trait_impls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:21:1 + | +LL | unsafe impl Send for ContainsVec {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 + = note: `i32` is not a generic parameter +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:20:1 + | +LL | struct ContainsVec(Vec); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:32:1 + | +LL | unsafe impl Send for TwoParamsSame {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 + = note: `T` is mentioned multiple times +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:31:1 + | +LL | struct TwoParamsSame(T, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cross-crate traits with a default impl, like `Send`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:40:1 + | +LL | unsafe impl Send for WithPhantomDataSend<*const T, i8> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 + = note: `*const T` is not a generic parameter +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:39:1 + | +LL | pub struct WithPhantomDataSend(PhantomData, U); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cross-crate traits with a default impl, like `Sync`, should not be specialized + --> $DIR/suspicious-impls-lint.rs:46:1 + | +LL | unsafe impl Sync for WithLifetime<'static, Vec> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this will change its meaning in a future release! + = note: for more information, see issue #93367 + = note: `Vec` is not a generic parameter +note: try using the same sequence of generic parameters as the struct definition + --> $DIR/suspicious-impls-lint.rs:44:1 + | +LL | pub struct WithLifetime<'a, T>(&'a (), T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs new file mode 100644 index 000000000..98359ef51 --- /dev/null +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -0,0 +1,16 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 +//~^ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr new file mode 100644 index 000000000..4827916fa --- /dev/null +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -0,0 +1,19 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:17 + | +LL | auto trait Magic : Sized where Option : Magic {} + | -----^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:26 + | +LL | auto trait Magic : Sized where Option : Magic {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0568`. diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.rs b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.rs new file mode 100644 index 000000000..2a76893fe --- /dev/null +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.rs @@ -0,0 +1,39 @@ +// This test is for #29859, we need to ensure auto traits, +// (also known previously as default traits), do not have +// supertraits. Since the compiler synthesizes these +// instances on demand, we are essentially enabling +// users to write axioms if we view trait selection, +// as a proof system. +// +// For example the below test allows us to add the rule: +// forall (T : Type), T : Copy +// +// Providing a copy instance for *any* type, which +// is most definitely unsound. Imagine copying a +// type that contains a mutable reference, enabling +// mutable aliasing. +// +// You can imagine an even more dangerous test, +// which currently compiles on nightly. +// +// fn main() { +// let mut i = 10; +// let (a, b) = copy(&mut i); +// println!("{:?} {:?}", a, b); +// } + +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Magic: Copy {} //~ ERROR E0568 +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr new file mode 100644 index 000000000..d7716f4b6 --- /dev/null +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr @@ -0,0 +1,11 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/typeck-auto-trait-no-supertraits.rs:28:17 + | +LL | auto trait Magic: Copy {} + | -----^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0568`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs new file mode 100644 index 000000000..f2fb67f11 --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs @@ -0,0 +1,19 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait MyTrait {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::<(MyS2, MyS)>(); + //~^ ERROR `MyS2: MyTrait` is not satisfied +} diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr new file mode 100644 index 000000000..0c4970a72 --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` + --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:18 + | +LL | is_mytrait::<(MyS2, MyS)>(); + | ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` + | + = note: required because it appears within the type `(MyS2, MyS)` +note: required by a bound in `is_mytrait` + --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:12:18 + | +LL | fn is_mytrait() {} + | ^^^^^^^ required by this bound in `is_mytrait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs new file mode 100644 index 000000000..73ff46d05 --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs @@ -0,0 +1,23 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait MyTrait {} + +impl !MyTrait for *mut T {} + +struct MyS; + +struct MyS2; + +impl !MyTrait for MyS2 {} + +struct MyS3; + +fn is_mytrait() {} + +fn main() { + is_mytrait::(); + + is_mytrait::(); + //~^ ERROR `MyS2: MyTrait` is not satisfied +} diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr new file mode 100644 index 000000000..c575c485a --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied + --> $DIR/typeck-default-trait-impl-constituent-types.rs:21:18 + | +LL | is_mytrait::(); + | ^^^^ the trait `MyTrait` is not implemented for `MyS2` + | +note: required by a bound in `is_mytrait` + --> $DIR/typeck-default-trait-impl-constituent-types.rs:16:18 + | +LL | fn is_mytrait() {} + | ^^^^^^^ required by this bound in `is_mytrait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-negation.rs b/tests/ui/auto-traits/typeck-default-trait-impl-negation.rs new file mode 100644 index 000000000..f7f56f97f --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-negation.rs @@ -0,0 +1,29 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait MyTrait {} + +unsafe auto trait MyUnsafeTrait {} + +struct ThisImplsTrait; + +impl !MyUnsafeTrait for ThisImplsTrait {} + + +struct ThisImplsUnsafeTrait; + +impl !MyTrait for ThisImplsUnsafeTrait {} + +fn is_my_trait() {} +fn is_my_unsafe_trait() {} + +fn main() { + is_my_trait::(); + is_my_trait::(); + //~^ ERROR `ThisImplsUnsafeTrait: MyTrait` is not satisfied + + is_my_unsafe_trait::(); + //~^ ERROR `ThisImplsTrait: MyUnsafeTrait` is not satisfied + + is_my_unsafe_trait::(); +} diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-negation.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-negation.stderr new file mode 100644 index 000000000..fa8dd41da --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-negation.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `ThisImplsUnsafeTrait: MyTrait` is not satisfied + --> $DIR/typeck-default-trait-impl-negation.rs:22:19 + | +LL | is_my_trait::(); + | ^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `ThisImplsUnsafeTrait` + | +note: required by a bound in `is_my_trait` + --> $DIR/typeck-default-trait-impl-negation.rs:17:19 + | +LL | fn is_my_trait() {} + | ^^^^^^^ required by this bound in `is_my_trait` + +error[E0277]: the trait bound `ThisImplsTrait: MyUnsafeTrait` is not satisfied + --> $DIR/typeck-default-trait-impl-negation.rs:25:26 + | +LL | is_my_unsafe_trait::(); + | ^^^^^^^^^^^^^^ the trait `MyUnsafeTrait` is not implemented for `ThisImplsTrait` + | +note: required by a bound in `is_my_unsafe_trait` + --> $DIR/typeck-default-trait-impl-negation.rs:18:26 + | +LL | fn is_my_unsafe_trait() {} + | ^^^^^^^^^^^^^ required by this bound in `is_my_unsafe_trait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs new file mode 100644 index 000000000..2bbe82270 --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs @@ -0,0 +1,21 @@ +// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies +// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In +// other words, the auto impl only applies if there are no existing +// impls whose types unify. + +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Defaulted { } +impl<'a,T:Signed> Defaulted for &'a T { } +impl<'a,T:Signed> Defaulted for &'a mut T { } +fn is_defaulted() { } + +trait Signed { } +impl Signed for i32 { } + +fn main() { + is_defaulted::<&'static i32>(); + is_defaulted::<&'static u32>(); + //~^ ERROR `u32: Signed` is not satisfied +} diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr new file mode 100644 index 000000000..bd7aaf6fb --- /dev/null +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `u32: Signed` is not satisfied + --> $DIR/typeck-default-trait-impl-precedence.rs:19:20 + | +LL | is_defaulted::<&'static u32>(); + | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` + | +note: required for `&'static u32` to implement `Defaulted` + --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 + | +LL | impl<'a,T:Signed> Defaulted for &'a T { } + | ------ ^^^^^^^^^ ^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `is_defaulted` + --> $DIR/typeck-default-trait-impl-precedence.rs:12:19 + | +LL | fn is_defaulted() { } + | ^^^^^^^^^ required by this bound in `is_defaulted` +help: consider removing the leading `&`-reference + | +LL - is_defaulted::<&'static u32>(); +LL + is_defaulted::(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/autoderef-full-lval.rs b/tests/ui/autoderef-full-lval.rs new file mode 100644 index 000000000..0fadc5c98 --- /dev/null +++ b/tests/ui/autoderef-full-lval.rs @@ -0,0 +1,25 @@ +struct Clam { + x: Box, + y: Box, +} + + + +struct Fish { + a: Box, +} + +fn main() { + let a: Clam = Clam{ x: Box::new(1), y: Box::new(2) }; + let b: Clam = Clam{ x: Box::new(10), y: Box::new(20) }; + let z: isize = a.x + b.y; + //~^ ERROR cannot add `Box` to `Box` + println!("{}", z); + assert_eq!(z, 21); + let forty: Fish = Fish{ a: Box::new(40) }; + let two: Fish = Fish{ a: Box::new(2) }; + let answer: isize = forty.a + two.a; + //~^ ERROR cannot add `Box` to `Box` + println!("{}", answer); + assert_eq!(answer, 42); +} diff --git a/tests/ui/autoderef-full-lval.stderr b/tests/ui/autoderef-full-lval.stderr new file mode 100644 index 000000000..9921ce7c1 --- /dev/null +++ b/tests/ui/autoderef-full-lval.stderr @@ -0,0 +1,19 @@ +error[E0369]: cannot add `Box` to `Box` + --> $DIR/autoderef-full-lval.rs:15:24 + | +LL | let z: isize = a.x + b.y; + | --- ^ --- Box + | | + | Box + +error[E0369]: cannot add `Box` to `Box` + --> $DIR/autoderef-full-lval.rs:21:33 + | +LL | let answer: isize = forty.a + two.a; + | ------- ^ ----- Box + | | + | Box + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs b/tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs new file mode 100644 index 000000000..2482e1878 --- /dev/null +++ b/tests/ui/autoref-autoderef/auto-ref-bounded-ty-param.rs @@ -0,0 +1,29 @@ +// run-pass +trait Foo { + fn f(&self); +} + +struct Bar { + x: isize +} + +trait Baz { + fn g(&self); +} + +impl Foo for T { + fn f(&self) { + self.g(); + } +} + +impl Baz for Bar { + fn g(&self) { + println!("{}", self.x); + } +} + +pub fn main() { + let y = Bar { x: 42 }; + y.f(); +} diff --git a/tests/ui/autoref-autoderef/auto-ref-sliceable.rs b/tests/ui/autoref-autoderef/auto-ref-sliceable.rs new file mode 100644 index 000000000..e5f79d780 --- /dev/null +++ b/tests/ui/autoref-autoderef/auto-ref-sliceable.rs @@ -0,0 +1,19 @@ +// run-pass + + +trait Pushable { + fn push_val(&mut self, t: T); +} + +impl Pushable for Vec { + fn push_val(&mut self, t: T) { + self.push(t); + } +} + +pub fn main() { + let mut v = vec![1]; + v.push_val(2); + v.push_val(3); + assert_eq!(v, [1, 2, 3]); +} diff --git a/tests/ui/autoref-autoderef/auto-ref.rs b/tests/ui/autoref-autoderef/auto-ref.rs new file mode 100644 index 000000000..b77f9c342 --- /dev/null +++ b/tests/ui/autoref-autoderef/auto-ref.rs @@ -0,0 +1,19 @@ +// run-pass +struct Foo { + x: isize, +} + +trait Stuff { + fn printme(&self); +} + +impl Stuff for Foo { + fn printme(&self) { + println!("{}", self.x); + } +} + +pub fn main() { + let x = Foo { x: 3 }; + x.printme(); +} diff --git a/tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs b/tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs new file mode 100644 index 000000000..874f42282 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-and-borrow-method-receiver.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Foo { + x: isize, +} + +impl Foo { + pub fn f(&self) {} +} + +fn g(x: &mut Foo) { + x.f(); +} + +pub fn main() { +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-on-trait.rs b/tests/ui/autoref-autoderef/autoderef-method-on-trait.rs new file mode 100644 index 000000000..af747cc76 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-on-trait.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box) -> usize; +} + +impl double for usize { + fn double(self: Box) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<_> = Box::new(Box::new(3usize) as Box); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-priority.rs b/tests/ui/autoref-autoderef/autoderef-method-priority.rs new file mode 100644 index 000000000..88a5140dc --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-priority.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self) -> usize; +} + +impl double for usize { + fn double(self) -> usize { self } +} + +impl double for Box { + fn double(self) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<_> = Box::new(3); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs b/tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs new file mode 100644 index 000000000..3657e61d4 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-twice-but-not-thrice.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box) -> usize; +} + +impl double for Box { + fn double(self: Box>) -> usize { **self * 2 } +} + +pub fn main() { + let x: Box>>>> = Box::new(Box::new(Box::new(Box::new(Box::new(3))))); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method-twice.rs b/tests/ui/autoref-autoderef/autoderef-method-twice.rs new file mode 100644 index 000000000..ed86b31b8 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method-twice.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box) -> usize; +} + +impl double for usize { + fn double(self: Box) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box> = Box::new(Box::new(3)); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-method.rs b/tests/ui/autoref-autoderef/autoderef-method.rs new file mode 100644 index 000000000..5b7965e95 --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-method.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait double { + fn double(self: Box) -> usize; +} + +impl double for usize { + fn double(self: Box) -> usize { *self * 2 } +} + +pub fn main() { + let x: Box<_> = Box::new(3); + assert_eq!(x.double(), 6); +} diff --git a/tests/ui/autoref-autoderef/autoderef-privacy.rs b/tests/ui/autoref-autoderef/autoderef-privacy.rs new file mode 100644 index 000000000..841be930b --- /dev/null +++ b/tests/ui/autoref-autoderef/autoderef-privacy.rs @@ -0,0 +1,51 @@ +// run-pass +// Check we do not select a private method or field when computing autoderefs + +#![allow(unused)] + +#[derive(Default)] +pub struct Bar2 { i: i32 } +#[derive(Default)] +pub struct Baz2(i32); + +impl Bar2 { + fn f(&self) -> bool { true } +} + +mod foo { + #[derive(Default)] + pub struct Bar { i: ::Bar2 } + #[derive(Default)] + pub struct Baz(::Baz2); + + impl Bar { + fn f(&self) -> bool { false } + } + + impl ::std::ops::Deref for Bar { + type Target = ::Bar2; + fn deref(&self) -> &::Bar2 { &self.i } + } + + impl ::std::ops::Deref for Baz { + type Target = ::Baz2; + fn deref(&self) -> &::Baz2 { &self.0 } + } + + pub fn f(bar: &Bar, baz: &Baz) { + // Since the private fields and methods are visible here, there should be no autoderefs. + let _: &::Bar2 = &bar.i; + let _: &::Baz2 = &baz.0; + assert!(!bar.f()); + } +} + +fn main() { + let bar = foo::Bar::default(); + let baz = foo::Baz::default(); + foo::f(&bar, &baz); + + let _: i32 = bar.i; + let _: i32 = baz.0; + assert!(bar.f()); +} diff --git a/tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs b/tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs new file mode 100644 index 000000000..3bdc248ff --- /dev/null +++ b/tests/ui/autoref-autoderef/autoref-intermediate-types-issue-3585.rs @@ -0,0 +1,22 @@ +// run-pass + +trait Foo { + fn foo(&self) -> String; +} + +impl Foo for Box { + fn foo(&self) -> String { + format!("box {}", (**self).foo()) + } +} + +impl Foo for usize { + fn foo(&self) -> String { + format!("{}", *self) + } +} + +pub fn main() { + let x: Box<_> = Box::new(3); + assert_eq!(x.foo(), "box 3".to_string()); +} diff --git a/tests/ui/autoref-autoderef/deref-into-array.rs b/tests/ui/autoref-autoderef/deref-into-array.rs new file mode 100644 index 000000000..855a82d2f --- /dev/null +++ b/tests/ui/autoref-autoderef/deref-into-array.rs @@ -0,0 +1,17 @@ +// check-pass + +struct Test([T; 1]); + +impl std::ops::Deref for Test { + type Target = [T; 1]; + + fn deref(&self) -> &[T; 1] { + &self.0 + } +} + +fn main() { + let out = Test([(); 1]); + let blah = out.len(); + println!("{}", blah); +} diff --git a/tests/ui/autoref-autoderef/issue-38940.rs b/tests/ui/autoref-autoderef/issue-38940.rs new file mode 100644 index 000000000..d2f1c6e32 --- /dev/null +++ b/tests/ui/autoref-autoderef/issue-38940.rs @@ -0,0 +1,52 @@ +// issue-38940: error printed twice for deref recursion limit exceeded +// Test that the recursion limit can be changed. In this case, we have +// deeply nested types that will fail the `Send` check by overflow +// when the recursion limit is set very low. +// compile-flags: -Zdeduplicate-diagnostics=yes + +#![allow(dead_code)] +#![recursion_limit = "10"] +macro_rules! link { + ($outer:ident, $inner:ident) => { + struct $outer($inner); + impl $outer { + fn new() -> $outer { + $outer($inner::new()) + } + } + impl std::ops::Deref for $outer { + type Target = $inner; + fn deref(&self) -> &$inner { + &self.0 + } + } + }; +} + +struct Bottom; + +impl Bottom { + fn new() -> Bottom { + Bottom + } +} + +link!(Top, A); +link!(A, B); +link!(B, C); +link!(C, D); +link!(D, E); +link!(E, F); +link!(F, G); +link!(G, H); +link!(H, I); +link!(I, J); +link!(J, K); +link!(K, Bottom); + +fn main() { + let t = Top::new(); + let x: &Bottom = &t; + //~^ ERROR mismatched types + //~| ERROR reached the recursion limit while auto-dereferencing `J` +} diff --git a/tests/ui/autoref-autoderef/issue-38940.stderr b/tests/ui/autoref-autoderef/issue-38940.stderr new file mode 100644 index 000000000..f0b840577 --- /dev/null +++ b/tests/ui/autoref-autoderef/issue-38940.stderr @@ -0,0 +1,23 @@ +error[E0055]: reached the recursion limit while auto-dereferencing `J` + --> $DIR/issue-38940.rs:49:22 + | +LL | let x: &Bottom = &t; + | ^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`) + +error[E0308]: mismatched types + --> $DIR/issue-38940.rs:49:22 + | +LL | let x: &Bottom = &t; + | ------- ^^ expected struct `Bottom`, found struct `Top` + | | + | expected due to this + | + = note: expected reference `&Bottom` + found reference `&Top` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0055, E0308. +For more information about an error, try `rustc --explain E0055`. diff --git a/tests/ui/auxiliary/augmented_assignments.rs b/tests/ui/auxiliary/augmented_assignments.rs new file mode 100644 index 000000000..d0d3f5745 --- /dev/null +++ b/tests/ui/auxiliary/augmented_assignments.rs @@ -0,0 +1,8 @@ +use std::ops::AddAssign; + +pub struct Int(pub i32); + +impl AddAssign for Int { + fn add_assign(&mut self, _: i32) { + } +} diff --git a/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs b/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs new file mode 100644 index 000000000..5330b7a92 --- /dev/null +++ b/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs @@ -0,0 +1,11 @@ +// Helper definition for test/run-pass/check-static-recursion-foreign.rs. + +#![feature(rustc_private)] + +#![crate_name = "check_static_recursion_foreign_helper"] +#![crate_type = "lib"] + +extern crate libc; + +#[no_mangle] +pub static test_static: libc::c_int = 0; diff --git a/tests/ui/auxiliary/crate-method-reexport-grrrrrrr2.rs b/tests/ui/auxiliary/crate-method-reexport-grrrrrrr2.rs new file mode 100644 index 000000000..d08504005 --- /dev/null +++ b/tests/ui/auxiliary/crate-method-reexport-grrrrrrr2.rs @@ -0,0 +1,31 @@ +#![crate_name="crate_method_reexport_grrrrrrr2"] + +pub use name_pool::add; + +pub mod name_pool { + pub type name_pool = (); + + pub trait add { + fn add(&self, s: String); + } + + impl add for name_pool { + fn add(&self, _s: String) { + } + } +} + +pub mod rust { + pub use name_pool::add; + + pub type rt = Box<()>; + + pub trait cx { + fn cx(&self); + } + + impl cx for rt { + fn cx(&self) { + } + } +} diff --git a/tests/ui/auxiliary/default-ty-param-cross-crate-crate.rs b/tests/ui/auxiliary/default-ty-param-cross-crate-crate.rs new file mode 100644 index 000000000..d722b7876 --- /dev/null +++ b/tests/ui/auxiliary/default-ty-param-cross-crate-crate.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![crate_name = "default_param_test"] +#![feature(default_type_parameter_fallback)] + +use std::marker::PhantomData; + +pub struct Foo(PhantomData<(A, B)>); + +pub fn bleh() -> Foo { Foo(PhantomData) } diff --git a/tests/ui/auxiliary/edition-kw-macro-2015.rs b/tests/ui/auxiliary/edition-kw-macro-2015.rs new file mode 100644 index 000000000..553ba6930 --- /dev/null +++ b/tests/ui/auxiliary/edition-kw-macro-2015.rs @@ -0,0 +1,26 @@ +// edition:2015 + +#[macro_export] +macro_rules! produces_async { + () => (pub fn async() {}) +} + +#[macro_export] +macro_rules! produces_async_raw { + () => (pub fn r#async() {}) +} + +#[macro_export] +macro_rules! consumes_async { + (async) => (1) +} + +#[macro_export] +macro_rules! consumes_async_raw { + (r#async) => (1) +} + +#[macro_export] +macro_rules! passes_ident { + ($i: ident) => ($i) +} diff --git a/tests/ui/auxiliary/edition-kw-macro-2018.rs b/tests/ui/auxiliary/edition-kw-macro-2018.rs new file mode 100644 index 000000000..f1f4ee280 --- /dev/null +++ b/tests/ui/auxiliary/edition-kw-macro-2018.rs @@ -0,0 +1,26 @@ +// edition:2018 + +#[macro_export] +macro_rules! produces_async { + () => (pub fn async() {}) +} + +#[macro_export] +macro_rules! produces_async_raw { + () => (pub fn r#async() {}) +} + +#[macro_export] +macro_rules! consumes_async { + (async) => (1) +} + +#[macro_export] +macro_rules! consumes_async_raw { + (r#async) => (1) +} + +#[macro_export] +macro_rules! passes_ident { + ($i: ident) => ($i) +} diff --git a/tests/ui/auxiliary/fancy-panic.rs b/tests/ui/auxiliary/fancy-panic.rs new file mode 100644 index 000000000..35be93b05 --- /dev/null +++ b/tests/ui/auxiliary/fancy-panic.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! fancy_panic { + () => { + panic!("{}"); + }; + ($msg:expr) => { + panic!($msg) + }; +} diff --git a/tests/ui/auxiliary/hello_macro.rs b/tests/ui/auxiliary/hello_macro.rs new file mode 100644 index 000000000..a05b8d54d --- /dev/null +++ b/tests/ui/auxiliary/hello_macro.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, quote}; + +// This macro is not very interesting, but it does contain delimited tokens with +// no content - `()` and `{}` - which has caused problems in the past. +// Also, it tests that we can escape `$` via `$$`. +#[proc_macro] +pub fn hello(_: TokenStream) -> TokenStream { + quote!({ + fn hello() {} + macro_rules! m { ($$($$t:tt)*) => { $$($$t)* } } + m!(hello()); + }) +} diff --git a/tests/ui/auxiliary/impl_privacy_xc_1.rs b/tests/ui/auxiliary/impl_privacy_xc_1.rs new file mode 100644 index 000000000..367b8ec8b --- /dev/null +++ b/tests/ui/auxiliary/impl_privacy_xc_1.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] + +pub struct Fish { + pub x: isize +} + +impl Fish { + pub fn swim(&self) {} +} diff --git a/tests/ui/auxiliary/inner_static.rs b/tests/ui/auxiliary/inner_static.rs new file mode 100644 index 000000000..42dcd379d --- /dev/null +++ b/tests/ui/auxiliary/inner_static.rs @@ -0,0 +1,51 @@ +pub struct A { pub v: T } +pub struct B { pub v: T } + +pub mod test { + pub struct A { pub v: T } + + impl A { + pub fn foo(&self) -> isize { + static a: isize = 5; + return a + } + + pub fn bar(&self) -> isize { + static a: isize = 6; + return a; + } + } +} + +impl A { + pub fn foo(&self) -> isize { + static a: isize = 1; + return a + } + + pub fn bar(&self) -> isize { + static a: isize = 2; + return a; + } +} + +impl B { + pub fn foo(&self) -> isize { + static a: isize = 3; + return a + } + + pub fn bar(&self) -> isize { + static a: isize = 4; + return a; + } +} + +pub fn foo() -> isize { + let a = A { v: () }; + let b = B { v: () }; + let c = test::A { v: () }; + return a.foo() + a.bar() + + b.foo() + b.bar() + + c.foo() + c.bar(); +} diff --git a/tests/ui/auxiliary/issue-76387.rs b/tests/ui/auxiliary/issue-76387.rs new file mode 100644 index 000000000..873d2bedd --- /dev/null +++ b/tests/ui/auxiliary/issue-76387.rs @@ -0,0 +1,29 @@ +// compile-flags: -C opt-level=3 + +pub struct FatPtr { + ptr: *mut u8, + len: usize, +} + +impl FatPtr { + pub fn new(len: usize) -> FatPtr { + let ptr = Box::into_raw(vec![42u8; len].into_boxed_slice()) as *mut u8; + + FatPtr { ptr, len } + } +} + +impl std::ops::Deref for FatPtr { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + unsafe { std::slice::from_raw_parts(self.ptr, self.len) } + } +} + +impl std::ops::Drop for FatPtr { + fn drop(&mut self) { + println!("Drop"); + } +} diff --git a/tests/ui/auxiliary/kinds_in_metadata.rs b/tests/ui/auxiliary/kinds_in_metadata.rs new file mode 100644 index 000000000..2a2106ff7 --- /dev/null +++ b/tests/ui/auxiliary/kinds_in_metadata.rs @@ -0,0 +1,8 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that metadata serialization works for the `Copy` kind. + +#![crate_type="lib"] + +pub fn f() {} diff --git a/tests/ui/auxiliary/msvc-data-only-lib.rs b/tests/ui/auxiliary/msvc-data-only-lib.rs new file mode 100644 index 000000000..ccaa6d8ed --- /dev/null +++ b/tests/ui/auxiliary/msvc-data-only-lib.rs @@ -0,0 +1,5 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub static FOO: i32 = 42; diff --git a/tests/ui/auxiliary/noexporttypelib.rs b/tests/ui/auxiliary/noexporttypelib.rs new file mode 100644 index 000000000..67889cc5f --- /dev/null +++ b/tests/ui/auxiliary/noexporttypelib.rs @@ -0,0 +1,2 @@ +pub type oint = Option; +pub fn foo() -> oint { Some(3) } diff --git a/tests/ui/auxiliary/orphan-check-diagnostics.rs b/tests/ui/auxiliary/orphan-check-diagnostics.rs new file mode 100644 index 000000000..6b2c42b69 --- /dev/null +++ b/tests/ui/auxiliary/orphan-check-diagnostics.rs @@ -0,0 +1 @@ +pub trait RemoteTrait { fn dummy(&self) { } } diff --git a/tests/ui/auxiliary/pub-and-stability.rs b/tests/ui/auxiliary/pub-and-stability.rs new file mode 100644 index 000000000..ee05a07db --- /dev/null +++ b/tests/ui/auxiliary/pub-and-stability.rs @@ -0,0 +1,133 @@ +// This crate attempts to enumerate the various scenarios for how a +// type can define fields and methods with various visibilities and +// stabilities. +// +// The basic stability pattern in this file has four cases: +// 1. no stability attribute at all +// 2. a stable attribute (feature "unit_test") +// 3. an unstable attribute that unit test declares (feature "unstable_declared") +// 4. an unstable attribute that unit test fails to declare (feature "unstable_undeclared") +// +// This file also covers four kinds of visibility: private, +// pub(module), pub(crate), and pub. +// +// However, since stability attributes can only be observed in +// cross-crate linkage scenarios, there is little reason to take the +// cross-product (4 stability cases * 4 visibility cases), because the +// first three visibility cases cannot be accessed outside this crate, +// and therefore stability is only relevant when the visibility is pub +// to the whole universe. +// +// (The only reason to do so would be if one were worried about the +// compiler having some subtle bug where adding a stability attribute +// introduces a privacy violation. As a way to provide evidence that +// this is not occurring, I have put stability attributes on some +// non-pub fields, marked with SILLY below) + +#![feature(staged_api)] + +#![stable(feature = "unit_test", since = "1.0.0")] + +#[stable(feature = "unit_test", since = "1.0.0")] +pub use m::{Record, Trait, Tuple}; + +mod m { + #[derive(Default)] + #[stable(feature = "unit_test", since = "1.0.0")] + pub struct Record { + #[stable(feature = "unit_test", since = "1.0.0")] + pub a_stable_pub: i32, + #[unstable(feature = "unstable_declared", issue = "38412")] + pub a_unstable_declared_pub: i32, + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub a_unstable_undeclared_pub: i32, + #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY + pub(crate) b_crate: i32, + #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY + pub(in m) c_mod: i32, + #[stable(feature = "unit_test", since = "1.0.0")] // SILLY + d_priv: i32 + } + + #[derive(Default)] + #[stable(feature = "unit_test", since = "1.0.0")] + pub struct Tuple( + #[stable(feature = "unit_test", since = "1.0.0")] + pub i32, + #[unstable(feature = "unstable_declared", issue = "38412")] + pub i32, + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub i32, + + pub(crate) i32, + pub(in m) i32, + i32); + + impl Record { + #[stable(feature = "unit_test", since = "1.0.0")] + pub fn new() -> Self { Default::default() } + } + + impl Tuple { + #[stable(feature = "unit_test", since = "1.0.0")] + pub fn new() -> Self { Default::default() } + } + + + #[stable(feature = "unit_test", since = "1.0.0")] + pub trait Trait { + #[stable(feature = "unit_test", since = "1.0.0")] + type Type; + #[stable(feature = "unit_test", since = "1.0.0")] + fn stable_trait_method(&self) -> Self::Type; + #[unstable(feature = "unstable_undeclared", issue = "38412")] + fn unstable_undeclared_trait_method(&self) -> Self::Type; + #[unstable(feature = "unstable_declared", issue = "38412")] + fn unstable_declared_trait_method(&self) -> Self::Type; + } + + #[stable(feature = "unit_test", since = "1.0.0")] + impl Trait for Record { + type Type = i32; + fn stable_trait_method(&self) -> i32 { self.d_priv } + fn unstable_undeclared_trait_method(&self) -> i32 { self.d_priv } + fn unstable_declared_trait_method(&self) -> i32 { self.d_priv } + } + + #[stable(feature = "unit_test", since = "1.0.0")] + impl Trait for Tuple { + type Type = i32; + fn stable_trait_method(&self) -> i32 { self.3 } + fn unstable_undeclared_trait_method(&self) -> i32 { self.3 } + fn unstable_declared_trait_method(&self) -> i32 { self.3 } + } + + impl Record { + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub fn unstable_undeclared(&self) -> i32 { self.d_priv } + #[unstable(feature = "unstable_declared", issue = "38412")] + pub fn unstable_declared(&self) -> i32 { self.d_priv } + #[stable(feature = "unit_test", since = "1.0.0")] + pub fn stable(&self) -> i32 { self.d_priv } + + #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY + pub(crate) fn pub_crate(&self) -> i32 { self.d_priv } + #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY + pub(in m) fn pub_mod(&self) -> i32 { self.d_priv } + #[stable(feature = "unit_test", since = "1.0.0")] // SILLY + fn private(&self) -> i32 { self.d_priv } + } + + impl Tuple { + #[unstable(feature = "unstable_undeclared", issue = "38412")] + pub fn unstable_undeclared(&self) -> i32 { self.0 } + #[unstable(feature = "unstable_declared", issue = "38412")] + pub fn unstable_declared(&self) -> i32 { self.0 } + #[stable(feature = "unit_test", since = "1.0.0")] + pub fn stable(&self) -> i32 { self.0 } + + pub(crate) fn pub_crate(&self) -> i32 { self.0 } + pub(in m) fn pub_mod(&self) -> i32 { self.0 } + fn private(&self) -> i32 { self.0 } + } +} diff --git a/tests/ui/auxiliary/removing-extern-crate.rs b/tests/ui/auxiliary/removing-extern-crate.rs new file mode 100644 index 000000000..65e2cc340 --- /dev/null +++ b/tests/ui/auxiliary/removing-extern-crate.rs @@ -0,0 +1 @@ +// intentionally blank diff --git a/tests/ui/auxiliary/rustc-rust-log-aux.rs b/tests/ui/auxiliary/rustc-rust-log-aux.rs new file mode 100644 index 000000000..daa8e9f49 --- /dev/null +++ b/tests/ui/auxiliary/rustc-rust-log-aux.rs @@ -0,0 +1 @@ +// rustc-env:RUSTC_LOG=debug diff --git a/tests/ui/auxiliary/svh-a-base.rs b/tests/ui/auxiliary/svh-a-base.rs new file mode 100644 index 000000000..36b41fc81 --- /dev/null +++ b/tests/ui/auxiliary/svh-a-base.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +pub fn foo(_: isize) -> isize { + 3 +} + +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/auxiliary/svh-b.rs b/tests/ui/auxiliary/svh-b.rs new file mode 100644 index 000000000..57029f708 --- /dev/null +++ b/tests/ui/auxiliary/svh-b.rs @@ -0,0 +1,13 @@ +//! This is a client of the `a` crate defined in `svn-a-base.rs`. The +//! rpass and cfail tests (such as `run-pass/svh-add-comment.rs`) use +//! it by swapping in a different object code library crate built from +//! some variant of `svn-a-base.rs`, and then we are checking if the +//! compiler properly ignores or accepts the change, based on whether +//! the change could affect the downstream crate content or not +//! (#14132). + +#![crate_name = "b"] + +extern crate a; + +pub fn foo() { assert_eq!(a::foo::<()>(0), 3); } diff --git a/tests/ui/auxiliary/typeid-intrinsic-aux1.rs b/tests/ui/auxiliary/typeid-intrinsic-aux1.rs new file mode 100644 index 000000000..281c07968 --- /dev/null +++ b/tests/ui/auxiliary/typeid-intrinsic-aux1.rs @@ -0,0 +1,29 @@ +use std::any::{Any, TypeId}; + +pub struct A; +pub struct B(Option); +pub struct C(Option); +pub struct D(Option<&'static str>); +pub struct E(Result<&'static str, isize>); + +pub type F = Option; +pub type G = usize; +pub type H = &'static str; +pub type I = Box; +pub type I32Iterator = Iterator; +pub type U32Iterator = Iterator; + +pub fn id_A() -> TypeId { TypeId::of::() } +pub fn id_B() -> TypeId { TypeId::of::() } +pub fn id_C() -> TypeId { TypeId::of::() } +pub fn id_D() -> TypeId { TypeId::of::() } +pub fn id_E() -> TypeId { TypeId::of::() } +pub fn id_F() -> TypeId { TypeId::of::() } +pub fn id_G() -> TypeId { TypeId::of::() } +pub fn id_H() -> TypeId { TypeId::of::() } +pub fn id_I() -> TypeId { TypeId::of::() } + +pub fn foo() -> TypeId { TypeId::of::() } + +pub fn id_i32_iterator() -> TypeId { TypeId::of::() } +pub fn id_u32_iterator() -> TypeId { TypeId::of::() } diff --git a/tests/ui/auxiliary/typeid-intrinsic-aux2.rs b/tests/ui/auxiliary/typeid-intrinsic-aux2.rs new file mode 100644 index 000000000..281c07968 --- /dev/null +++ b/tests/ui/auxiliary/typeid-intrinsic-aux2.rs @@ -0,0 +1,29 @@ +use std::any::{Any, TypeId}; + +pub struct A; +pub struct B(Option); +pub struct C(Option); +pub struct D(Option<&'static str>); +pub struct E(Result<&'static str, isize>); + +pub type F = Option; +pub type G = usize; +pub type H = &'static str; +pub type I = Box; +pub type I32Iterator = Iterator; +pub type U32Iterator = Iterator; + +pub fn id_A() -> TypeId { TypeId::of::() } +pub fn id_B() -> TypeId { TypeId::of::() } +pub fn id_C() -> TypeId { TypeId::of::() } +pub fn id_D() -> TypeId { TypeId::of::() } +pub fn id_E() -> TypeId { TypeId::of::() } +pub fn id_F() -> TypeId { TypeId::of::() } +pub fn id_G() -> TypeId { TypeId::of::() } +pub fn id_H() -> TypeId { TypeId::of::() } +pub fn id_I() -> TypeId { TypeId::of::() } + +pub fn foo() -> TypeId { TypeId::of::() } + +pub fn id_i32_iterator() -> TypeId { TypeId::of::() } +pub fn id_u32_iterator() -> TypeId { TypeId::of::() } diff --git a/tests/ui/auxiliary/using-target-feature-unstable.rs b/tests/ui/auxiliary/using-target-feature-unstable.rs new file mode 100644 index 000000000..268202893 --- /dev/null +++ b/tests/ui/auxiliary/using-target-feature-unstable.rs @@ -0,0 +1,5 @@ +#![feature(avx512_target_feature)] + +#[inline] +#[target_feature(enable = "avx512ifma")] +pub unsafe fn foo() {} diff --git a/tests/ui/auxiliary/xc-private-method-lib.rs b/tests/ui/auxiliary/xc-private-method-lib.rs new file mode 100644 index 000000000..4d5ec6de3 --- /dev/null +++ b/tests/ui/auxiliary/xc-private-method-lib.rs @@ -0,0 +1,33 @@ +#![crate_type="lib"] + +pub struct Struct { + pub x: isize +} + +impl Struct { + fn static_meth_struct() -> Struct { + Struct { x: 1 } + } + + fn meth_struct(&self) -> isize { + self.x + } +} + +pub enum Enum { + Variant1(isize), + Variant2(isize) +} + +impl Enum { + fn static_meth_enum() -> Enum { + Enum::Variant2(10) + } + + fn meth_enum(&self) -> isize { + match *self { + Enum::Variant1(x) | + Enum::Variant2(x) => x + } + } +} diff --git a/tests/ui/backtrace-apple-no-dsymutil.rs b/tests/ui/backtrace-apple-no-dsymutil.rs new file mode 100644 index 000000000..3844ebcfd --- /dev/null +++ b/tests/ui/backtrace-apple-no-dsymutil.rs @@ -0,0 +1,29 @@ +// run-pass + +// compile-flags:-Cstrip=none +// compile-flags:-g -Csplit-debuginfo=unpacked +// only-macos + +use std::process::Command; +use std::str; + +#[inline(never)] +fn main() { + let args: Vec = std::env::args().collect(); + if args.len() >= 2 { + println!("{}", std::backtrace::Backtrace::force_capture()); + return; + } + let out = Command::new(&args[0]).env("RUST_BACKTRACE", "1").arg("foo").output().unwrap(); + let output = format!( + "{}\n{}", + str::from_utf8(&out.stdout).unwrap(), + str::from_utf8(&out.stderr).unwrap(), + ); + if out.status.success() && output.contains(file!()) { + return; + } + println!("status: {}", out.status); + println!("child output:\n\t{}", output.replace("\n", "\n\t")); + panic!("failed to find {:?} in output", file!()); +} diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace.rs new file mode 100644 index 000000000..dd73dd988 --- /dev/null +++ b/tests/ui/backtrace.rs @@ -0,0 +1,130 @@ +// run-pass +// ignore-android FIXME #17520 +// ignore-emscripten spawning processes is not supported +// ignore-openbsd no support for libbacktrace without filename +// ignore-sgx no processes +// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test +// ignore-fuchsia Backtraces not symbolized +// compile-flags:-g +// compile-flags:-Cstrip=none + +use std::env; +use std::process::{Command, Stdio}; +use std::str; + +#[inline(never)] +fn foo() { + let _v = vec![1, 2, 3]; + if env::var_os("IS_TEST").is_some() { + panic!() + } +} + +#[inline(never)] +fn double() { + struct Double; + + impl Drop for Double { + fn drop(&mut self) { panic!("twice") } + } + + let _d = Double; + + panic!("once"); +} + +fn template(me: &str) -> Command { + let mut m = Command::new(me); + m.env("IS_TEST", "1") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); + return m; +} + +fn expected(fn_name: &str) -> String { + format!(" backtrace::{}", fn_name) +} + +#[cfg(not(panic = "abort"))] +fn contains_verbose_expected(s: &str, fn_name: &str) -> bool { + // HACK(eddyb) work around the fact that verbosely demangled stack traces + // (from `RUST_BACKTRACE=full`, or, as is the case here, panic-in-panic) + // may contain symbols with hashes in them, i.e. `backtrace[...]::`. + let prefix = " backtrace"; + let suffix = &format!("::{}", fn_name); + s.match_indices(prefix).any(|(i, _)| { + s[i + prefix.len()..] + .trim_start_matches('[') + .trim_start_matches(char::is_alphanumeric) + .trim_start_matches(']') + .starts_with(suffix) + }) +} + +fn runtest(me: &str) { + // Make sure that the stack trace is printed + let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap(); + let out = p.wait_with_output().unwrap(); + assert!(!out.status.success()); + let s = str::from_utf8(&out.stderr).unwrap(); + assert!(s.contains("stack backtrace") && s.contains(&expected("foo")), + "bad output: {}", s); + assert!(s.contains(" 0:"), "the frame number should start at 0"); + + // Make sure the stack trace is *not* printed + // (Remove RUST_BACKTRACE from our own environment, in case developer + // is running `make check` with it on.) + let p = template(me).arg("fail").env_remove("RUST_BACKTRACE").spawn().unwrap(); + let out = p.wait_with_output().unwrap(); + assert!(!out.status.success()); + let s = str::from_utf8(&out.stderr).unwrap(); + assert!(!s.contains("stack backtrace") && !s.contains(&expected("foo")), + "bad output2: {}", s); + + // Make sure the stack trace is *not* printed + // (RUST_BACKTRACE=0 acts as if it were unset from our own environment, + // in case developer is running `make check` with it set.) + let p = template(me).arg("fail").env("RUST_BACKTRACE","0").spawn().unwrap(); + let out = p.wait_with_output().unwrap(); + assert!(!out.status.success()); + let s = str::from_utf8(&out.stderr).unwrap(); + assert!(!s.contains("stack backtrace") && !s.contains(" - foo"), + "bad output3: {}", s); + + #[cfg(not(panic = "abort"))] + { + // Make sure a stack trace is printed + let p = template(me).arg("double-fail").spawn().unwrap(); + let out = p.wait_with_output().unwrap(); + assert!(!out.status.success()); + let s = str::from_utf8(&out.stderr).unwrap(); + // loosened the following from double::h to double:: due to + // spurious failures on mac, 32bit, optimized + assert!(s.contains("stack backtrace") && contains_verbose_expected(s, "double"), + "bad output3: {}", s); + + // Make sure a stack trace isn't printed too many times + let p = template(me).arg("double-fail") + .env("RUST_BACKTRACE", "1").spawn().unwrap(); + let out = p.wait_with_output().unwrap(); + assert!(!out.status.success()); + let s = str::from_utf8(&out.stderr).unwrap(); + let mut i = 0; + for _ in 0..2 { + i += s[i + 10..].find("stack backtrace").unwrap() + 10; + } + assert!(s[i + 10..].find("stack backtrace").is_none(), + "bad output4: {}", s); + } +} + +fn main() { + let args: Vec = env::args().collect(); + if args.len() >= 2 && args[1] == "fail" { + foo(); + } else if args.len() >= 2 && args[1] == "double-fail" { + double(); + } else { + runtest(&args[0]); + } +} diff --git a/tests/ui/bare-fn-implements-fn-mut.rs b/tests/ui/bare-fn-implements-fn-mut.rs new file mode 100644 index 000000000..dfead4889 --- /dev/null +++ b/tests/ui/bare-fn-implements-fn-mut.rs @@ -0,0 +1,27 @@ +// run-pass + +use std::ops::FnMut; + +fn call_f(mut f: F) { + f(); +} + +fn f() { + println!("hello"); +} + +fn call_g String>(mut g: G, x: String, y: String) + -> String { + g(x, y) +} + +fn g(mut x: String, y: String) -> String { + x.push_str(&y); + x +} + +fn main() { + call_f(f); + assert_eq!(call_g(g, "foo".to_string(), "bar".to_string()), + "foobar"); +} diff --git a/tests/ui/bare-static-string.rs b/tests/ui/bare-static-string.rs new file mode 100644 index 000000000..d336dc7c6 --- /dev/null +++ b/tests/ui/bare-static-string.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let x: &'static str = "foo"; + println!("{}", x); +} diff --git a/tests/ui/bench/issue-32062.rs b/tests/ui/bench/issue-32062.rs new file mode 100644 index 000000000..7eb52196e --- /dev/null +++ b/tests/ui/bench/issue-32062.rs @@ -0,0 +1,50 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +fn main() { + let _ = test(Some(0).into_iter()); +} + +trait Parser { + type Input: Iterator; + type Output; + fn parse(self, input: Self::Input) -> Result<(Self::Output, Self::Input), ()>; + fn chain

(self, p: P) -> Chain where Self: Sized { + Chain(self, p) + } +} + +struct Token(#[allow(unused_tuple_struct_fields)] T::Item) where T: Iterator; + +impl Parser for Token where T: Iterator { + type Input = T; + type Output = T::Item; + fn parse(self, _input: Self::Input) -> Result<(Self::Output, Self::Input), ()> { + Err(()) + } +} + +struct Chain(#[allow(unused_tuple_struct_fields)] L, #[allow(unused_tuple_struct_fields)] R); + +impl Parser for Chain where L: Parser, R: Parser { + type Input = L::Input; + type Output = (L::Output, R::Output); + fn parse(self, _input: Self::Input) -> Result<(Self::Output, Self::Input), ()> { + Err(()) + } +} + +fn test(i: I) -> Result<((), I), ()> where I: Iterator { + Chain(Token(0), Token(1)) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .chain(Chain(Token(0), Token(1))) + .parse(i) + .map(|(_, i)| ((), i)) +} diff --git a/tests/ui/big-literals.rs b/tests/ui/big-literals.rs new file mode 100644 index 000000000..96ea115c8 --- /dev/null +++ b/tests/ui/big-literals.rs @@ -0,0 +1,17 @@ +// run-pass +// Catch mistakes in the overflowing literals lint. +#![deny(overflowing_literals)] + +pub fn main() { + assert_eq!(0xffffffff, (!0 as u32)); + assert_eq!(4294967295, (!0 as u32)); + assert_eq!(0xffffffffffffffff, (!0 as u64)); + assert_eq!(18446744073709551615, (!0 as u64)); + + assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647); + + assert_eq!(-3.40282356e+38_f32, f32::MIN); + assert_eq!(3.40282356e+38_f32, f32::MAX); + assert_eq!(-1.7976931348623158e+308_f64, f64::MIN); + assert_eq!(1.7976931348623158e+308_f64, f64::MAX); +} diff --git a/tests/ui/bind-by-move.rs b/tests/ui/bind-by-move.rs new file mode 100644 index 000000000..f0a9ebdd0 --- /dev/null +++ b/tests/ui/bind-by-move.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::sync::Arc; +fn dispose(_x: Arc) { } + +pub fn main() { + let p = Arc::new(true); + let x = Some(p); + match x { + Some(z) => { dispose(z); }, + None => panic!() + } +} diff --git a/tests/ui/binding/ambiguity-item.rs b/tests/ui/binding/ambiguity-item.rs new file mode 100644 index 000000000..0f48340c2 --- /dev/null +++ b/tests/ui/binding/ambiguity-item.rs @@ -0,0 +1,19 @@ +// Identifier pattern referring to an ambiguity item is an error (issue #46079). + +mod m { + pub fn f() {} +} +use m::*; + +mod n { + pub fn f() {} +} +use n::*; // OK, no conflict with `use m::*;` + +fn main() { + let v = f; //~ ERROR `f` is ambiguous + match v { + f => {} //~ ERROR `f` is ambiguous + mut f => {} // OK, unambiguously a fresh binding due to `mut` + } +} diff --git a/tests/ui/binding/ambiguity-item.stderr b/tests/ui/binding/ambiguity-item.stderr new file mode 100644 index 000000000..f36201396 --- /dev/null +++ b/tests/ui/binding/ambiguity-item.stderr @@ -0,0 +1,43 @@ +error[E0659]: `f` is ambiguous + --> $DIR/ambiguity-item.rs:14:13 + | +LL | let v = f; + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error[E0659]: `f` is ambiguous + --> $DIR/ambiguity-item.rs:16:9 + | +LL | f => {} + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/binding/bind-field-short-with-modifiers.rs b/tests/ui/binding/bind-field-short-with-modifiers.rs new file mode 100644 index 000000000..b271f84e9 --- /dev/null +++ b/tests/ui/binding/bind-field-short-with-modifiers.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(non_shorthand_field_patterns)] + +pub fn main() { + struct Foo { x: isize, y: isize } + let mut f = Foo { x: 10, y: 0 }; + match f { + Foo { ref mut x, .. } => *x = 11, + } + match f { + Foo { ref x, ref y } => { + assert_eq!(f.x, 11); + assert_eq!(f.y, 0); + } + } + match f { + Foo { mut x, y: ref mut y } => { + x = 12; + *y = 1; + } + } + assert_eq!(f.x, 11); + assert_eq!(f.y, 1); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-2.rs b/tests/ui/binding/borrowed-ptr-pattern-2.rs new file mode 100644 index 000000000..40df85b14 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-2.rs @@ -0,0 +1,13 @@ +// run-pass + +fn foo(s: &String) -> bool { + match &**s { + "kitty" => true, + _ => false + } +} + +pub fn main() { + assert!(foo(&"kitty".to_string())); + assert!(!foo(&"gata".to_string())); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-3.rs b/tests/ui/binding/borrowed-ptr-pattern-3.rs new file mode 100644 index 000000000..f2607eee8 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-3.rs @@ -0,0 +1,13 @@ +// run-pass + +fn foo<'r>(s: &'r usize) -> bool { + match s { + &3 => true, + _ => false + } +} + +pub fn main() { + assert!(foo(&3)); + assert!(!foo(&4)); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-infallible.rs b/tests/ui/binding/borrowed-ptr-pattern-infallible.rs new file mode 100644 index 000000000..1bbc03e19 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-infallible.rs @@ -0,0 +1,8 @@ +// run-pass + + +pub fn main() { + let (&x, &y) = (&3, &'a'); + assert_eq!(x, 3); + assert_eq!(y, 'a'); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-option.rs b/tests/ui/binding/borrowed-ptr-pattern-option.rs new file mode 100644 index 000000000..319b8631e --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-option.rs @@ -0,0 +1,15 @@ +// run-pass + +fn select<'r>(x: &'r Option, y: &'r Option) -> &'r Option { + match (x, y) { + (&None, &None) => x, + (&Some(_), _) => x, + (&None, &Some(_)) => y + } +} + +pub fn main() { + let x = None; + let y = Some(3); + assert_eq!(select(&x, &y).unwrap(), 3); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern.rs b/tests/ui/binding/borrowed-ptr-pattern.rs new file mode 100644 index 000000000..d5f94ab54 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern.rs @@ -0,0 +1,12 @@ +// run-pass + +fn foo(x: &T) -> T{ + match x { + &ref a => (*a).clone() + } +} + +pub fn main() { + assert_eq!(foo(&3), 3); + assert_eq!(foo(&'a'), 'a'); +} diff --git a/tests/ui/binding/const-param.rs b/tests/ui/binding/const-param.rs new file mode 100644 index 000000000..2d051808f --- /dev/null +++ b/tests/ui/binding/const-param.rs @@ -0,0 +1,10 @@ +// Identifier pattern referring to a const generic parameter is an error (issue #68853). + +fn check() { + match 1 { + N => {} //~ ERROR const parameters cannot be referenced in patterns + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/binding/const-param.stderr b/tests/ui/binding/const-param.stderr new file mode 100644 index 000000000..adda80810 --- /dev/null +++ b/tests/ui/binding/const-param.stderr @@ -0,0 +1,9 @@ +error[E0158]: const parameters cannot be referenced in patterns + --> $DIR/const-param.rs:5:9 + | +LL | N => {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/binding/empty-types-in-patterns.rs b/tests/ui/binding/empty-types-in-patterns.rs new file mode 100644 index 000000000..0d0dbcaf4 --- /dev/null +++ b/tests/ui/binding/empty-types-in-patterns.rs @@ -0,0 +1,59 @@ +// run-pass + +#![feature(never_type, never_type_fallback)] +#![feature(exhaustive_patterns)] + +#![allow(unreachable_patterns)] +#![allow(unreachable_code)] +#![allow(unused_variables)] + +#[allow(dead_code)] +fn foo(z: !) { + let x: Result = Ok(z); + + let Ok(_y) = x; + let Err(_y) = x; + + let x = [z; 1]; + + match x {}; + match x { + [q] => q, + }; +} + +fn bar(nevers: &[!]) { + match nevers { + &[] => (), + }; + + match nevers { + &[] => (), + &[_] => (), + &[_, _, _, ..] => (), + }; +} + +fn main() { + let x: Result = Ok(123); + let Ok(y) = x; + + assert_eq!(123, y); + + match x { + Ok(y) => y, + }; + + match x { + Ok(y) => y, + Err(e) => match e {}, + }; + + let x: Result = Ok(123); + match x { + Ok(y) => y, + Err(_) => unimplemented!(), + }; + + bar(&[]); +} diff --git a/tests/ui/binding/exhaustive-bool-match-sanity.rs b/tests/ui/binding/exhaustive-bool-match-sanity.rs new file mode 100644 index 000000000..f83def210 --- /dev/null +++ b/tests/ui/binding/exhaustive-bool-match-sanity.rs @@ -0,0 +1,22 @@ +// run-pass +// Issue #33540 +// We previously used to generate a 3-armed boolean `SwitchInt` in the +// MIR of the function `foo` below. #33583 changed rustc to +// generate an `If` terminator instead. This test is to just ensure +// sanity in that we generate an if-else chain giving the correct +// results. + +fn foo(x: bool, y: bool) -> u32 { + match (x, y) { + (false, _) => 0, + (_, false) => 1, + (true, true) => 2 + } +} + +fn main() { + assert_eq!(foo(false, true), 0); + assert_eq!(foo(false, false), 0); + assert_eq!(foo(true, false), 1); + assert_eq!(foo(true, true), 2); +} diff --git a/tests/ui/binding/expr-match-generic-unique1.rs b/tests/ui/binding/expr-match-generic-unique1.rs new file mode 100644 index 000000000..c5f38d815 --- /dev/null +++ b/tests/ui/binding/expr-match-generic-unique1.rs @@ -0,0 +1,18 @@ +// run-pass + +fn test_generic(expected: Box, eq: F) where F: FnOnce(Box, Box) -> bool { + let actual: Box = match true { + true => { expected.clone() }, + _ => panic!("wat") + }; + assert!(eq(expected, actual)); +} + +fn test_box() { + fn compare_box(b1: Box, b2: Box) -> bool { + return *b1 == *b2; + } + test_generic::(Box::new(true), compare_box); +} + +pub fn main() { test_box(); } diff --git a/tests/ui/binding/expr-match-generic-unique2.rs b/tests/ui/binding/expr-match-generic-unique2.rs new file mode 100644 index 000000000..8977ca68e --- /dev/null +++ b/tests/ui/binding/expr-match-generic-unique2.rs @@ -0,0 +1,16 @@ +// run-pass + +fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { + let actual: T = match true { + true => expected.clone(), + _ => panic!("wat") + }; + assert!(eq(expected, actual)); +} + +fn test_vec() { + fn compare_box(v1: Box, v2: Box) -> bool { return v1 == v2; } + test_generic::, _>(Box::new(1), compare_box); +} + +pub fn main() { test_vec(); } diff --git a/tests/ui/binding/expr-match-generic.rs b/tests/ui/binding/expr-match-generic.rs new file mode 100644 index 000000000..530fc676f --- /dev/null +++ b/tests/ui/binding/expr-match-generic.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(non_camel_case_types)] + +type compare = extern "Rust" fn(T, T) -> bool; + +fn test_generic(expected: T, eq: compare) { + let actual: T = match true { true => { expected.clone() }, _ => panic!("wat") }; + assert!((eq(expected, actual))); +} + +fn test_bool() { + fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } + test_generic::(true, compare_bool); +} + +#[derive(Clone)] +struct Pair { + a: isize, + b: isize, +} + +fn test_rec() { + fn compare_rec(t1: Pair, t2: Pair) -> bool { + t1.a == t2.a && t1.b == t2.b + } + test_generic::(Pair {a: 1, b: 2}, compare_rec); +} + +pub fn main() { test_bool(); test_rec(); } diff --git a/tests/ui/binding/expr-match-panic-all.rs b/tests/ui/binding/expr-match-panic-all.rs new file mode 100644 index 000000000..ac31b49a1 --- /dev/null +++ b/tests/ui/binding/expr-match-panic-all.rs @@ -0,0 +1,14 @@ +// run-pass + + + +// When all branches of a match expression result in panic, the entire +// match expression results in panic. + +pub fn main() { + let _x = + match true { + true => { 10 } + false => { match true { true => { panic!() } false => { panic!() } } } + }; +} diff --git a/tests/ui/binding/expr-match-panic.rs b/tests/ui/binding/expr-match-panic.rs new file mode 100644 index 000000000..4b6b6e072 --- /dev/null +++ b/tests/ui/binding/expr-match-panic.rs @@ -0,0 +1,14 @@ +// run-pass + + +fn test_simple() { + let r = match true { true => { true } false => { panic!() } }; + assert_eq!(r, true); +} + +fn test_box() { + let r = match true { true => { vec![10] } false => { panic!() } }; + assert_eq!(r[0], 10); +} + +pub fn main() { test_simple(); test_box(); } diff --git a/tests/ui/binding/expr-match-unique.rs b/tests/ui/binding/expr-match-unique.rs new file mode 100644 index 000000000..eec9e1f8b --- /dev/null +++ b/tests/ui/binding/expr-match-unique.rs @@ -0,0 +1,9 @@ +// run-pass + +// Tests for match as expressions resulting in boxed types +fn test_box() { + let res: Box<_> = match true { true => { Box::new(100) }, _ => panic!() }; + assert_eq!(*res, 100); +} + +pub fn main() { test_box(); } diff --git a/tests/ui/binding/expr-match.rs b/tests/ui/binding/expr-match.rs new file mode 100644 index 000000000..575b38fbc --- /dev/null +++ b/tests/ui/binding/expr-match.rs @@ -0,0 +1,45 @@ +// run-pass + + + + +// Tests for using match as an expression + +fn test_basic() { + let mut rs: bool = match true { true => { true } false => { false } }; + assert!((rs)); + rs = match false { true => { false } false => { true } }; + assert!((rs)); +} + +fn test_inferrence() { + let rs = match true { true => { true } false => { false } }; + assert!((rs)); +} + +fn test_alt_as_alt_head() { + // Yeah, this is kind of confusing ... + + let rs = + match match false { true => { true } false => { false } } { + true => { false } + false => { true } + }; + assert!((rs)); +} + +fn test_alt_as_block_result() { + let rs = + match false { + true => { false } + false => { match true { true => { true } false => { false } } } + }; + assert!((rs)); +} + +pub fn main() { + test_basic(); + test_inferrence(); + test_alt_as_alt_head(); + test_alt_as_block_result(); +} diff --git a/tests/ui/binding/fat-arrow-match.rs b/tests/ui/binding/fat-arrow-match.rs new file mode 100644 index 000000000..aaf5be8cf --- /dev/null +++ b/tests/ui/binding/fat-arrow-match.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +enum color { + red, + green, + blue +} + +pub fn main() { + println!("{}", match color::red { + color::red => { 1 } + color::green => { 2 } + color::blue => { 3 } + }); +} diff --git a/tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs new file mode 100644 index 000000000..0450fe8ab --- /dev/null +++ b/tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs @@ -0,0 +1,69 @@ +// run-pass +// needs-unwind +// Check that partially moved from function parameters are dropped after the +// named bindings that move from them. + + +use std::{panic, cell::RefCell}; + +struct LogDrop<'a>(i32, Context<'a>); + +#[derive(Copy, Clone)] +struct Context<'a> { + panic_on: i32, + drops: &'a RefCell>, +} + +impl<'a> Context<'a> { + fn record_drop(self, index: i32) { + self.drops.borrow_mut().push(index); + if index == self.panic_on { + panic!(); + } + } +} + +impl<'a> Drop for LogDrop<'a> { + fn drop(&mut self) { + self.1.record_drop(self.0); + } +} + +fn bindings_in_params((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} +fn bindings_with_let(a: (LogDrop, LogDrop), b: (LogDrop, LogDrop)) { + // Drop order in foo is the same as the following bindings. + // _temp2 is declared after _x to avoid a difference between `_: T` and + // `x: T` in function parameters. + let _temp1 = a; + let (_x, _) = _temp1; + + let _temp2 = b; + let (_, _y) = _temp2; +} + +fn test_drop_order(panic_on: i32, fun: fn((LogDrop, LogDrop), (LogDrop, LogDrop))) { + let context = Context { + panic_on, + drops: &RefCell::new(Vec::new()), + }; + let one = LogDrop(1, context); + let two = LogDrop(2, context); + let three = LogDrop(3, context); + let four = LogDrop(4, context); + + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + fun((three, four), (two, one)); + })); + if panic_on == 0 { + assert!(res.is_ok(), "should not have panicked"); + } else { + assert!(res.is_err(), "should have panicked"); + } + assert_eq!(*context.drops.borrow(), [1, 2, 3, 4], "incorrect drop order"); +} + +fn main() { + (0..=4).for_each(|i| test_drop_order(i, bindings_in_params)); + (0..=4).for_each(|i| test_drop_order(i, bindings_with_let)); + (0..=4).for_each(|i| test_drop_order(i, |(_x, _), (_, _y)| {})); +} diff --git a/tests/ui/binding/fn-pattern-expected-type-2.rs b/tests/ui/binding/fn-pattern-expected-type-2.rs new file mode 100644 index 000000000..130ff3d44 --- /dev/null +++ b/tests/ui/binding/fn-pattern-expected-type-2.rs @@ -0,0 +1,8 @@ +// run-pass +pub fn main() { + let v : &[(isize,isize)] = &[ (1, 2), (3, 4), (5, 6) ]; + for &(x, y) in v { + println!("{}", y); + println!("{}", x); + } +} diff --git a/tests/ui/binding/fn-pattern-expected-type.rs b/tests/ui/binding/fn-pattern-expected-type.rs new file mode 100644 index 000000000..faeb76496 --- /dev/null +++ b/tests/ui/binding/fn-pattern-expected-type.rs @@ -0,0 +1,9 @@ +// run-pass + +pub fn main() { + let f = |(x, y): (isize, isize)| { + assert_eq!(x, 1); + assert_eq!(y, 2); + }; + f((1, 2)); +} diff --git a/tests/ui/binding/func-arg-incomplete-pattern.rs b/tests/ui/binding/func-arg-incomplete-pattern.rs new file mode 100644 index 000000000..eb94ee48f --- /dev/null +++ b/tests/ui/binding/func-arg-incomplete-pattern.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +// Test that we do not leak when the arg pattern must drop part of the +// argument (in this case, the `y` field). + +struct Foo { + x: Box, + y: Box, +} + +fn foo(Foo {x, ..}: Foo) -> *const usize { + let addr: *const usize = &*x; + addr +} + +pub fn main() { + let obj: Box<_> = Box::new(1); + let objptr: *const usize = &*obj; + let f = Foo { x: obj, y: Box::new(2) }; + let xptr = foo(f); + assert_eq!(objptr, xptr); +} diff --git a/tests/ui/binding/func-arg-ref-pattern.rs b/tests/ui/binding/func-arg-ref-pattern.rs new file mode 100644 index 000000000..2d75c1214 --- /dev/null +++ b/tests/ui/binding/func-arg-ref-pattern.rs @@ -0,0 +1,26 @@ +// run-pass + +// Test argument patterns where we create refs to the inside of +// boxes. Make sure that we don't free the box as we match the +// pattern. + +#![feature(box_patterns)] + +fn getaddr(box ref x: Box) -> *const usize { + let addr: *const usize = &*x; + addr +} + +fn checkval(box ref x: Box) -> usize { + *x +} + +pub fn main() { + let obj: Box<_> = Box::new(1); + let objptr: *const usize = &*obj; + let xptr = getaddr(obj); + assert_eq!(objptr, xptr); + + let obj = Box::new(22); + assert_eq!(checkval(obj), 22); +} diff --git a/tests/ui/binding/func-arg-wild-pattern.rs b/tests/ui/binding/func-arg-wild-pattern.rs new file mode 100644 index 000000000..bcd82c679 --- /dev/null +++ b/tests/ui/binding/func-arg-wild-pattern.rs @@ -0,0 +1,12 @@ +// run-pass +// Test that we can compile code that uses a `_` in function argument +// patterns. + + +fn foo((x, _): (isize, isize)) -> isize { + x +} + +pub fn main() { + assert_eq!(foo((22, 23)), 22); +} diff --git a/tests/ui/binding/if-let.rs b/tests/ui/binding/if-let.rs new file mode 100644 index 000000000..28d57e92c --- /dev/null +++ b/tests/ui/binding/if-let.rs @@ -0,0 +1,60 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + let x = Some(3); + if let Some(y) = x { + assert_eq!(y, 3); + } else { + panic!("`if let` panicked"); + } + let mut worked = false; + if let Some(_) = x { + worked = true; + } + assert!(worked); + let clause: usize; + if let None = Some("test") { + clause = 1; + } else if 4_usize > 5 { + clause = 2; + } else if let Ok(()) = Err::<(),&'static str>("test") { + clause = 3; + } else { + clause = 4; + } + assert_eq!(clause, 4_usize); + + if 3 > 4 { + panic!("bad math"); + } else if let 1 = 2 { + panic!("bad pattern match"); + } + + enum Foo { + One, + Two(usize), + Three(String, isize) + } + + let foo = Foo::Three("three".to_string(), 42); + if let Foo::One = foo { + panic!("bad pattern match"); + } else if let Foo::Two(_x) = foo { + panic!("bad pattern match"); + } else if let Foo::Three(s, _) = foo { + assert_eq!(s, "three"); + } else { + panic!("bad else"); + } + + if false { + panic!("wat"); + } else if let a@Foo::Two(_) = Foo::Two(42_usize) { + if let Foo::Two(b) = a { + assert_eq!(b, 42_usize); + } else { + panic!("panic in nested `if let`"); + } + } +} diff --git a/tests/ui/binding/inconsistent-lifetime-mismatch.rs b/tests/ui/binding/inconsistent-lifetime-mismatch.rs new file mode 100644 index 000000000..87768c28c --- /dev/null +++ b/tests/ui/binding/inconsistent-lifetime-mismatch.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn foo(_: &[&str]) {} + +fn bad(a: &str, b: &str) { + foo(&[a, b]); +} + +fn good(a: &str, b: &str) { + foo(&[a, b]); +} + +fn main() {} diff --git a/tests/ui/binding/inferred-suffix-in-pattern-range.rs b/tests/ui/binding/inferred-suffix-in-pattern-range.rs new file mode 100644 index 000000000..079cc0a16 --- /dev/null +++ b/tests/ui/binding/inferred-suffix-in-pattern-range.rs @@ -0,0 +1,24 @@ +// run-pass + +pub fn main() { + let x = 2; + let x_message = match x { + 0 ..= 1 => { "not many".to_string() } + _ => { "lots".to_string() } + }; + assert_eq!(x_message, "lots".to_string()); + + let y = 2; + let y_message = match y { + 0 ..= 1 => { "not many".to_string() } + _ => { "lots".to_string() } + }; + assert_eq!(y_message, "lots".to_string()); + + let z = 1u64; + let z_message = match z { + 0 ..= 1 => { "not many".to_string() } + _ => { "lots".to_string() } + }; + assert_eq!(z_message, "not many".to_string()); +} diff --git a/tests/ui/binding/irrefutable-slice-patterns.rs b/tests/ui/binding/irrefutable-slice-patterns.rs new file mode 100644 index 000000000..048e1e5e9 --- /dev/null +++ b/tests/ui/binding/irrefutable-slice-patterns.rs @@ -0,0 +1,14 @@ +// run-pass + +// Regression test for #47096. + +fn foo(s: &[i32]) -> &[i32] { + let &[ref xs @ ..] = s; + xs +} + +fn main() { + let x = [1, 2, 3]; + let y = foo(&x); + assert_eq!(x, y); +} diff --git a/tests/ui/binding/issue-53114-borrow-checks.rs b/tests/ui/binding/issue-53114-borrow-checks.rs new file mode 100644 index 000000000..7646472f4 --- /dev/null +++ b/tests/ui/binding/issue-53114-borrow-checks.rs @@ -0,0 +1,84 @@ +// Issue #53114: NLL's borrow check had some deviations from the old borrow +// checker, and both had some deviations from our ideal state. This test +// captures the behavior of how `_` bindings are handled with respect to how we +// flag expressions that are meant to request unsafe blocks. +#![allow(irrefutable_let_patterns)] +struct M; + +fn let_wild_gets_moved_expr() { + let m = M; + drop(m); + let _ = m; // accepted, and want it to continue to be + + let mm = (M, M); // variation on above with `_` in substructure + let (_x, _) = mm; + let (_, _y) = mm; + let (_, _) = mm; +} + +fn match_moved_expr_to_wild() { + let m = M; + drop(m); + match m { _ => { } } // #53114: should eventually be accepted too + //~^ ERROR [E0382] + + let mm = (M, M); // variation on above with `_` in substructure + match mm { (_x, _) => { } } + match mm { (_, _y) => { } } + //~^ ERROR [E0382] + match mm { (_, _) => { } } + //~^ ERROR [E0382] +} + +fn if_let_moved_expr_to_wild() { + let m = M; + drop(m); + if let _ = m { } // #53114: should eventually be accepted too + //~^ ERROR [E0382] + + let mm = (M, M); // variation on above with `_` in substructure + if let (_x, _) = mm { } + if let (_, _y) = mm { } + //~^ ERROR [E0382] + if let (_, _) = mm { } + //~^ ERROR [E0382] +} + +fn let_wild_gets_borrowed_expr() { + let mut m = M; + let r = &mut m; + let _ = m; // accepted, and want it to continue to be + // let _x = m; // (compare with this error.) + drop(r); + + let mut mm = (M, M); // variation on above with `_` in substructure + let (r1, r2) = (&mut mm.0, &mut mm.1); + let (_, _) = mm; + drop((r1, r2)); +} + +fn match_borrowed_expr_to_wild() { + let mut m = M; + let r = &mut m; + match m { _ => {} } ; // accepted, and want it to continue to be + drop(r); + + let mut mm = (M, M); // variation on above with `_` in substructure + let (r1, r2) = (&mut mm.0, &mut mm.1); + match mm { (_, _) => { } } + drop((r1, r2)); +} + +fn if_let_borrowed_expr_to_wild() { + let mut m = M; + let r = &mut m; + if let _ = m { } // accepted, and want it to continue to be + drop(r); + + let mut mm = (M, M); // variation on above with `_` in substructure + let (r1, r2) = (&mut mm.0, &mut mm.1); + if let (_, _) = mm { } + drop((r1, r2)); +} + +fn main() { } diff --git a/tests/ui/binding/issue-53114-borrow-checks.stderr b/tests/ui/binding/issue-53114-borrow-checks.stderr new file mode 100644 index 000000000..0ec2ae883 --- /dev/null +++ b/tests/ui/binding/issue-53114-borrow-checks.stderr @@ -0,0 +1,81 @@ +error[E0382]: use of moved value: `m` + --> $DIR/issue-53114-borrow-checks.rs:22:11 + | +LL | let m = M; + | - move occurs because `m` has type `M`, which does not implement the `Copy` trait +LL | drop(m); + | - value moved here +LL | match m { _ => { } } // #53114: should eventually be accepted too + | ^ value used here after move + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:27:11 + | +LL | match mm { (_x, _) => { } } + | -- value partially moved here +LL | match mm { (_, _y) => { } } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | match mm { (ref _x, _) => { } } + | +++ + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:29:11 + | +LL | match mm { (_, _y) => { } } + | -- value partially moved here +LL | +LL | match mm { (_, _) => { } } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | match mm { (_, ref _y) => { } } + | +++ + +error[E0382]: use of moved value: `m` + --> $DIR/issue-53114-borrow-checks.rs:36:16 + | +LL | let m = M; + | - move occurs because `m` has type `M`, which does not implement the `Copy` trait +LL | drop(m); + | - value moved here +LL | if let _ = m { } // #53114: should eventually be accepted too + | ^ value used here after move + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:41:22 + | +LL | if let (_x, _) = mm { } + | -- value partially moved here +LL | if let (_, _y) = mm { } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let (ref _x, _) = mm { } + | +++ + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:43:21 + | +LL | if let (_, _y) = mm { } + | -- value partially moved here +LL | +LL | if let (_, _) = mm { } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let (_, ref _y) = mm { } + | +++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/binding/issue-53114-safety-checks.rs b/tests/ui/binding/issue-53114-safety-checks.rs new file mode 100644 index 000000000..d0eb28c57 --- /dev/null +++ b/tests/ui/binding/issue-53114-safety-checks.rs @@ -0,0 +1,51 @@ +// Issue #53114: NLL's borrow check had some deviations from the old borrow +// checker, and both had some deviations from our ideal state. This test +// captures the behavior of how `_` bindings are handled with respect to how we +// flag expressions that are meant to request unsafe blocks. + +#[derive(Copy, Clone)] +struct I(i64); +#[derive(Copy, Clone)] +struct F(f64); + +union U { a: I, b: F } + +#[repr(packed)] +struct P { + a: &'static i8, + b: &'static u32, +} + +fn let_wild_gets_unsafe_field() { + let u1 = U { a: I(0) }; + let u2 = U { a: I(1) }; + let p = P { a: &2, b: &3 }; + let _ = &p.b; //~ ERROR reference to packed field + //~^ WARN will become a hard error + let _ = u1.a; // #53114: should eventually signal error as well + let _ = &u2.a; //~ ERROR [E0133] + + // variation on above with `_` in substructure + let (_,) = (&p.b,); //~ ERROR reference to packed field + //~^ WARN will become a hard error + let (_,) = (u1.a,); //~ ERROR [E0133] + let (_,) = (&u2.a,); //~ ERROR [E0133] +} + +fn match_unsafe_field_to_wild() { + let u1 = U { a: I(0) }; + let u2 = U { a: I(1) }; + let p = P { a: &2, b: &3 }; + match &p.b { _ => { } } //~ ERROR reference to packed field + //~^ WARN will become a hard error + match u1.a { _ => { } } //~ ERROR [E0133] + match &u2.a { _ => { } } //~ ERROR [E0133] + + // variation on above with `_` in substructure + match (&p.b,) { (_,) => { } } //~ ERROR reference to packed field + //~^ WARN will become a hard error + match (u1.a,) { (_,) => { } } //~ ERROR [E0133] + match (&u2.a,) { (_,) => { } } //~ ERROR [E0133] +} + +fn main() { } diff --git a/tests/ui/binding/issue-53114-safety-checks.stderr b/tests/ui/binding/issue-53114-safety-checks.stderr new file mode 100644 index 000000000..57a065d6d --- /dev/null +++ b/tests/ui/binding/issue-53114-safety-checks.stderr @@ -0,0 +1,156 @@ +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:23:13 + | +LL | let _ = &p.b; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:29:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:39:11 + | +LL | match &p.b { _ => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:45:12 + | +LL | match (&p.b,) { (_,) => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:26:13 + | +LL | let _ = &u2.a; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:31:17 + | +LL | let (_,) = (u1.a,); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:32:17 + | +LL | let (_,) = (&u2.a,); + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:41:11 + | +LL | match u1.a { _ => { } } + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:42:11 + | +LL | match &u2.a { _ => { } } + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:47:12 + | +LL | match (u1.a,) { (_,) => { } } + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:48:12 + | +LL | match (&u2.a,) { (_,) => { } } + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0133`. +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:23:13 + | +LL | let _ = &p.b; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:29:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:39:11 + | +LL | match &p.b { _ => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:45:12 + | +LL | match (&p.b,) { (_,) => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + diff --git a/tests/ui/binding/let-assignability.rs b/tests/ui/binding/let-assignability.rs new file mode 100644 index 000000000..b85f4a96a --- /dev/null +++ b/tests/ui/binding/let-assignability.rs @@ -0,0 +1,11 @@ +// run-pass + +fn f() { + let a: Box<_> = Box::new(1); + let b: &isize = &*a; + println!("{}", b); +} + +pub fn main() { + f(); +} diff --git a/tests/ui/binding/let-destruct-ref.rs b/tests/ui/binding/let-destruct-ref.rs new file mode 100644 index 000000000..28d7294eb --- /dev/null +++ b/tests/ui/binding/let-destruct-ref.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let x = 3_usize; + let ref y = x; + assert_eq!(x, *y); +} diff --git a/tests/ui/binding/let-var-hygiene.rs b/tests/ui/binding/let-var-hygiene.rs new file mode 100644 index 000000000..571207bd7 --- /dev/null +++ b/tests/ui/binding/let-var-hygiene.rs @@ -0,0 +1,11 @@ +// run-pass +// shouldn't affect evaluation of $ex: + +macro_rules! bad_macro { + ($ex:expr) => ({let _x = 9; $ex}) +} + +pub fn main() { + let _x = 8; + assert_eq!(bad_macro!(_x),8) +} diff --git a/tests/ui/binding/match-arm-statics.rs b/tests/ui/binding/match-arm-statics.rs new file mode 100644 index 000000000..e6d17def1 --- /dev/null +++ b/tests/ui/binding/match-arm-statics.rs @@ -0,0 +1,165 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: -g +// ignore-asmjs wasm2js does not support source maps yet + +#[derive(PartialEq, Eq)] +struct NewBool(bool); + +#[derive(PartialEq, Eq)] +enum Direction { + North, + East, + South, + West +} + +#[derive(PartialEq, Eq)] +struct Foo { + bar: Option, + baz: NewBool +} + +#[derive(PartialEq, Eq)] +enum EnumWithStructVariants { + Variant1(bool), + Variant2 { + dir: Direction + } +} + +const TRUE_TRUE: (bool, bool) = (true, true); +const NONE: Option = None; +const EAST: Direction = Direction::East; +const NEW_FALSE: NewBool = NewBool(false); +const STATIC_FOO: Foo = Foo { bar: Some(Direction::South), baz: NEW_FALSE }; +const VARIANT2_NORTH: EnumWithStructVariants = EnumWithStructVariants::Variant2 { + dir: Direction::North }; + +pub mod glfw { + #[derive(Copy, Clone, PartialEq, Eq)] + pub struct InputState(usize); + + pub const RELEASE : InputState = InputState(0); + pub const PRESS : InputState = InputState(1); + pub const REPEAT : InputState = InputState(2); +} + +fn issue_6533() { + fn action_to_str(state: glfw::InputState) -> &'static str { + use glfw::{RELEASE, PRESS, REPEAT}; + match state { + RELEASE => { "Released" } + PRESS => { "Pressed" } + REPEAT => { "Repeated" } + _ => { "Unknown" } + } + } + + assert_eq!(action_to_str(glfw::RELEASE), "Released"); + assert_eq!(action_to_str(glfw::PRESS), "Pressed"); + assert_eq!(action_to_str(glfw::REPEAT), "Repeated"); +} + +fn issue_13626() { + const VAL: [u8; 1] = [0]; + match [1] { + VAL => unreachable!(), + _ => () + } +} + +fn issue_14576() { + type Foo = (i32, i32); + const ON: Foo = (1, 1); + const OFF: Foo = (0, 0); + + match (1, 1) { + OFF => unreachable!(), + ON => (), + _ => unreachable!() + } + + #[derive(PartialEq, Eq)] + enum C { D = 3, E = 4 } + const F : C = C::D; + + assert_eq!(match C::D { F => 1, _ => 2, }, 1); + + // test gaps + #[derive(PartialEq, Eq)] + enum G { H = 3, I = 5 } + const K : G = G::I; + + assert_eq!(match G::I { K => 1, _ => 2, }, 1); +} + +fn issue_13731() { + #[derive(PartialEq, Eq)] + enum A { AA(()) } + const B: A = A::AA(()); + + match A::AA(()) { + B => () + } +} + +fn issue_15393() { + #![allow(dead_code)] + #[derive(PartialEq, Eq)] + struct Flags { + bits: usize + } + + const FOO: Flags = Flags { bits: 0x01 }; + const BAR: Flags = Flags { bits: 0x02 }; + match (Flags { bits: 0x02 }) { + FOO => unreachable!(), + BAR => (), + _ => unreachable!() + } +} + +fn main() { + assert_eq!(match (true, false) { + TRUE_TRUE => 1, + (false, false) => 2, + (false, true) => 3, + (true, false) => 4 + }, 4); + + assert_eq!(match Some(Some(Direction::North)) { + Some(NONE) => 1, + Some(Some(Direction::North)) => 2, + Some(Some(EAST)) => 3, + Some(Some(Direction::South)) => 4, + Some(Some(Direction::West)) => 5, + None => 6 + }, 2); + + assert_eq!(match (Foo { bar: Some(Direction::West), baz: NewBool(true) }) { + Foo { bar: None, baz: NewBool(true) } => 1, + Foo { bar: NONE, baz: NEW_FALSE } => 2, + STATIC_FOO => 3, + Foo { bar: _, baz: NEW_FALSE } => 4, + Foo { bar: Some(Direction::West), baz: NewBool(true) } => 5, + Foo { bar: Some(Direction::South), baz: NewBool(true) } => 6, + Foo { bar: Some(EAST), .. } => 7, + Foo { bar: Some(Direction::North), baz: NewBool(true) } => 8 + }, 5); + + assert_eq!(match (EnumWithStructVariants::Variant2 { dir: Direction::North }) { + EnumWithStructVariants::Variant1(true) => 1, + EnumWithStructVariants::Variant1(false) => 2, + EnumWithStructVariants::Variant2 { dir: Direction::West } => 3, + VARIANT2_NORTH => 4, + EnumWithStructVariants::Variant2 { dir: Direction::South } => 5, + EnumWithStructVariants::Variant2 { dir: Direction::East } => 6 + }, 4); + + issue_6533(); + issue_13626(); + issue_13731(); + issue_14576(); + issue_15393(); +} diff --git a/tests/ui/binding/match-beginning-vert.rs b/tests/ui/binding/match-beginning-vert.rs new file mode 100644 index 000000000..79267400b --- /dev/null +++ b/tests/ui/binding/match-beginning-vert.rs @@ -0,0 +1,19 @@ +// run-pass +enum Foo { + A, + B, + C, + D, + E, +} +use Foo::*; + +fn main() { + for foo in &[A, B, C, D, E] { + match *foo { + | A => println!("A"), + | B | C if 1 < 2 => println!("BC!"), + | _ => {}, + } + } +} diff --git a/tests/ui/binding/match-borrowed_str.rs b/tests/ui/binding/match-borrowed_str.rs new file mode 100644 index 000000000..22782032e --- /dev/null +++ b/tests/ui/binding/match-borrowed_str.rs @@ -0,0 +1,48 @@ +// run-pass + +fn f1(ref_string: &str) -> String { + match ref_string { + "a" => "found a".to_string(), + "b" => "found b".to_string(), + _ => "not found".to_string() + } +} + +fn f2(ref_string: &str) -> String { + match ref_string { + "a" => "found a".to_string(), + "b" => "found b".to_string(), + s => format!("not found ({})", s) + } +} + +fn g1(ref_1: &str, ref_2: &str) -> String { + match (ref_1, ref_2) { + ("a", "b") => "found a,b".to_string(), + ("b", "c") => "found b,c".to_string(), + _ => "not found".to_string() + } +} + +fn g2(ref_1: &str, ref_2: &str) -> String { + match (ref_1, ref_2) { + ("a", "b") => "found a,b".to_string(), + ("b", "c") => "found b,c".to_string(), + (s1, s2) => format!("not found ({}, {})", s1, s2) + } +} + +pub fn main() { + assert_eq!(f1("b"), "found b".to_string()); + assert_eq!(f1("c"), "not found".to_string()); + assert_eq!(f1("d"), "not found".to_string()); + assert_eq!(f2("b"), "found b".to_string()); + assert_eq!(f2("c"), "not found (c)".to_string()); + assert_eq!(f2("d"), "not found (d)".to_string()); + assert_eq!(g1("b", "c"), "found b,c".to_string()); + assert_eq!(g1("c", "d"), "not found".to_string()); + assert_eq!(g1("d", "e"), "not found".to_string()); + assert_eq!(g2("b", "c"), "found b,c".to_string()); + assert_eq!(g2("c", "d"), "not found (c, d)".to_string()); + assert_eq!(g2("d", "e"), "not found (d, e)".to_string()); +} diff --git a/tests/ui/binding/match-bot-2.rs b/tests/ui/binding/match-bot-2.rs new file mode 100644 index 000000000..95b3406f0 --- /dev/null +++ b/tests/ui/binding/match-bot-2.rs @@ -0,0 +1,6 @@ +// run-pass +#![allow(unreachable_code)] +// n.b. This was only ever failing with optimization disabled. + +fn a() -> isize { match return 1 { 2 => 3, _ => panic!() } } +pub fn main() { a(); } diff --git a/tests/ui/binding/match-bot.rs b/tests/ui/binding/match-bot.rs new file mode 100644 index 000000000..5c4472c7a --- /dev/null +++ b/tests/ui/binding/match-bot.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let i: isize = + match Some::(3) { None:: => { panic!() } Some::(_) => { 5 } }; + println!("{}", i); +} diff --git a/tests/ui/binding/match-byte-array-patterns.rs b/tests/ui/binding/match-byte-array-patterns.rs new file mode 100644 index 000000000..f0c988c01 --- /dev/null +++ b/tests/ui/binding/match-byte-array-patterns.rs @@ -0,0 +1,44 @@ +// run-pass + +fn main() { + let buf = &[0u8; 4]; + match buf { + &[0, 1, 0, 0] => unimplemented!(), + b"true" => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, 1, 0, 0] => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, x, 0, 0] => assert_eq!(x, 0), + _ => unimplemented!(), + } + + let buf: &[u8] = buf; + + match buf { + &[0, 1, 0, 0] => unimplemented!(), + &[_] => unimplemented!(), + &[_, _, _, _, _, ..] => unimplemented!(), + b"true" => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, 1, 0, 0] => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, x, 0, 0] => assert_eq!(x, 0), + _ => unimplemented!(), + } +} diff --git a/tests/ui/binding/match-enum-struct-0.rs b/tests/ui/binding/match-enum-struct-0.rs new file mode 100644 index 000000000..e2623ece8 --- /dev/null +++ b/tests/ui/binding/match-enum-struct-0.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// regression test for issue #5625 + + +enum E { + Foo{f : isize}, + Bar +} + +pub fn main() { + let e = E::Bar; + match e { + E::Foo{f: _f} => panic!(), + _ => (), + } +} diff --git a/tests/ui/binding/match-enum-struct-1.rs b/tests/ui/binding/match-enum-struct-1.rs new file mode 100644 index 000000000..f035432ec --- /dev/null +++ b/tests/ui/binding/match-enum-struct-1.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] + +enum E { + Foo{f : isize}, + Bar +} + +pub fn main() { + let e = E::Foo{f: 1}; + match e { + E::Foo{..} => (), + _ => panic!(), + } + match e { + E::Foo{f: _f} => (), + _ => panic!(), + } +} diff --git a/tests/ui/binding/match-implicit-copy-unique.rs b/tests/ui/binding/match-implicit-copy-unique.rs new file mode 100644 index 000000000..74ffe2ecd --- /dev/null +++ b/tests/ui/binding/match-implicit-copy-unique.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Pair { a: Box, b: Box } + +pub fn main() { + let mut x: Box<_> = Box::new(Pair { a: Box::new(10), b: Box::new(20) }); + let x_internal = &mut *x; + match *x_internal { + Pair {a: ref mut a, b: ref mut _b} => { + assert_eq!(**a, 10); + *a = Box::new(30); + assert_eq!(**a, 30); + } + } +} diff --git a/tests/ui/binding/match-in-macro.rs b/tests/ui/binding/match-in-macro.rs new file mode 100644 index 000000000..0840cc440 --- /dev/null +++ b/tests/ui/binding/match-in-macro.rs @@ -0,0 +1,17 @@ +// run-pass + +enum Foo { + B { b1: isize, bb1: isize}, +} + +macro_rules! match_inside_expansion { + () => ( + match (Foo::B { b1:29 , bb1: 100}) { + Foo::B { b1:b2 , bb1:bb2 } => b2+bb2 + } + ) +} + +pub fn main() { + assert_eq!(match_inside_expansion!(),129); +} diff --git a/tests/ui/binding/match-join.rs b/tests/ui/binding/match-join.rs new file mode 100644 index 000000000..60f2a4584 --- /dev/null +++ b/tests/ui/binding/match-join.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_mut)] +fn foo(y: Option) { + let mut x: isize; + let mut rs: Vec = Vec::new(); + /* tests that x doesn't get put in the precondition for the + entire if expression */ + + if true { + } else { + match y { + None:: => x = 17, + _ => x = 42 + } + rs.push(x); + } + return; +} + +pub fn main() { println!("hello"); foo::(Some::(5)); } diff --git a/tests/ui/binding/match-larger-const.rs b/tests/ui/binding/match-larger-const.rs new file mode 100644 index 000000000..6f9a35320 --- /dev/null +++ b/tests/ui/binding/match-larger-const.rs @@ -0,0 +1,12 @@ +// run-pass +#[derive(Eq, PartialEq)] +pub struct Data([u8; 4]); + +const DATA: Data = Data([1, 2, 3, 4]); + +fn main() { + match DATA { + DATA => (), + _ => (), + } +} diff --git a/tests/ui/binding/match-naked-record-expr.rs b/tests/ui/binding/match-naked-record-expr.rs new file mode 100644 index 000000000..c23ff8c94 --- /dev/null +++ b/tests/ui/binding/match-naked-record-expr.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct X { x: isize } + +pub fn main() { + let _x = match 0 { + _ => X { + x: 0 + }.x + }; +} diff --git a/tests/ui/binding/match-naked-record.rs b/tests/ui/binding/match-naked-record.rs new file mode 100644 index 000000000..f7479152e --- /dev/null +++ b/tests/ui/binding/match-naked-record.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct X { x: isize } + +pub fn main() { + let _x = match 0 { + _ => X { + x: 0 + } + }; +} diff --git a/tests/ui/binding/match-path.rs b/tests/ui/binding/match-path.rs new file mode 100644 index 000000000..286214eb8 --- /dev/null +++ b/tests/ui/binding/match-path.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +// pretty-expanded FIXME #23616 + +mod m1 { + pub enum foo { foo1, foo2, } +} + +fn bar(x: m1::foo) { match x { m1::foo::foo1 => { } m1::foo::foo2 => { } } } + +pub fn main() { } diff --git a/tests/ui/binding/match-pattern-bindings.rs b/tests/ui/binding/match-pattern-bindings.rs new file mode 100644 index 000000000..4ec533677 --- /dev/null +++ b/tests/ui/binding/match-pattern-bindings.rs @@ -0,0 +1,21 @@ +// run-pass + +fn main() { + let value = Some(1); + assert_eq!(match value { + ref a @ Some(_) => a, + ref b @ None => b + }, &Some(1)); + assert_eq!(match value { + ref c @ Some(_) => c, + ref b @ None => b + }, &Some(1)); + assert_eq!(match "foobarbaz" { + b @ _ => b + }, "foobarbaz"); + let a @ _ = "foobarbaz"; + assert_eq!(a, "foobarbaz"); + let value = Some(true); + let ref a @ _ = value; + assert_eq!(a, &Some(true)); +} diff --git a/tests/ui/binding/match-pattern-lit.rs b/tests/ui/binding/match-pattern-lit.rs new file mode 100644 index 000000000..c9c6135e2 --- /dev/null +++ b/tests/ui/binding/match-pattern-lit.rs @@ -0,0 +1,15 @@ +// run-pass + + +fn altlit(f: isize) -> isize { + match f { + 10 => { println!("case 10"); return 20; } + 11 => { println!("case 11"); return 22; } + _ => panic!("the impossible happened") + } +} + +pub fn main() { + assert_eq!(altlit(10), 20); + assert_eq!(altlit(11), 22); +} diff --git a/tests/ui/binding/match-pattern-no-type-params.rs b/tests/ui/binding/match-pattern-no-type-params.rs new file mode 100644 index 000000000..1fc7ddda0 --- /dev/null +++ b/tests/ui/binding/match-pattern-no-type-params.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +enum maybe { nothing, just(T), } + +fn foo(x: maybe) { + match x { + maybe::nothing => { println!("A"); } + maybe::just(_a) => { println!("B"); } + } +} + +pub fn main() { } diff --git a/tests/ui/binding/match-pattern-simple.rs b/tests/ui/binding/match-pattern-simple.rs new file mode 100644 index 000000000..3f56cd479 --- /dev/null +++ b/tests/ui/binding/match-pattern-simple.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(dead_code)] + + +// pretty-expanded FIXME #23616 + +fn altsimple(f: isize) { match f { _x => () } } + +pub fn main() { } diff --git a/tests/ui/binding/match-phi.rs b/tests/ui/binding/match-phi.rs new file mode 100644 index 000000000..92a3f6e0f --- /dev/null +++ b/tests/ui/binding/match-phi.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] +#![allow(unused_variables)] + +enum thing { a, b, c, } + +fn foo(it: F) where F: FnOnce(isize) { it(10); } + +pub fn main() { + let mut x = true; + match thing::a { + thing::a => { x = true; foo(|_i| { } ) } + thing::b => { x = false; } + thing::c => { x = false; } + } +} diff --git a/tests/ui/binding/match-pipe-binding.rs b/tests/ui/binding/match-pipe-binding.rs new file mode 100644 index 000000000..7d4a7c708 --- /dev/null +++ b/tests/ui/binding/match-pipe-binding.rs @@ -0,0 +1,60 @@ +// run-pass + +fn test1() { + // from issue 6338 + match ((1, "a".to_string()), (2, "b".to_string())) { + ((1, a), (2, b)) | ((2, b), (1, a)) => { + assert_eq!(a, "a".to_string()); + assert_eq!(b, "b".to_string()); + }, + _ => panic!(), + } +} + +fn test2() { + match (1, 2, 3) { + (1, a, b) | (2, b, a) => { + assert_eq!(a, 2); + assert_eq!(b, 3); + }, + _ => panic!(), + } +} + +fn test3() { + match (1, 2, 3) { + (1, ref a, ref b) | (2, ref b, ref a) => { + assert_eq!(*a, 2); + assert_eq!(*b, 3); + }, + _ => panic!(), + } +} + +fn test4() { + match (1, 2, 3) { + (1, a, b) | (2, b, a) if a == 2 => { + assert_eq!(a, 2); + assert_eq!(b, 3); + }, + _ => panic!(), + } +} + +fn test5() { + match (1, 2, 3) { + (1, ref a, ref b) | (2, ref b, ref a) if *a == 2 => { + assert_eq!(*a, 2); + assert_eq!(*b, 3); + }, + _ => panic!(), + } +} + +pub fn main() { + test1(); + test2(); + test3(); + test4(); + test5(); +} diff --git a/tests/ui/binding/match-range-infer.rs b/tests/ui/binding/match-range-infer.rs new file mode 100644 index 000000000..19d1cb89d --- /dev/null +++ b/tests/ui/binding/match-range-infer.rs @@ -0,0 +1,17 @@ +// run-pass +// Test that type inference for range patterns works correctly (is bi-directional). + +pub fn main() { + match 1 { + 1 ..= 3 => {} + _ => panic!("should match range") + } + match 1 { + 1 ..= 3u16 => {} + _ => panic!("should match range with inferred start type") + } + match 1 { + 1u16 ..= 3 => {} + _ => panic!("should match range with inferred end type") + } +} diff --git a/tests/ui/binding/match-range-static.rs b/tests/ui/binding/match-range-static.rs new file mode 100644 index 000000000..f01a3505e --- /dev/null +++ b/tests/ui/binding/match-range-static.rs @@ -0,0 +1,13 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_upper_case_globals)] + +const s: isize = 1; +const e: isize = 42; + +pub fn main() { + match 7 { + s..=e => (), + _ => (), + } +} diff --git a/tests/ui/binding/match-range.rs b/tests/ui/binding/match-range.rs new file mode 100644 index 000000000..1dca84dfd --- /dev/null +++ b/tests/ui/binding/match-range.rs @@ -0,0 +1,51 @@ +// run-pass +#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 +#![feature(exclusive_range_pattern)] + +pub fn main() { + match 5_usize { + 1_usize..=5_usize => {} + _ => panic!("should match range"), + } + match 1_usize { + 1_usize..5_usize => {} + _ => panic!("should match range start"), + } + match 5_usize { + 6_usize..=7_usize => panic!("shouldn't match range"), + _ => {} + } + match 7_usize { + 6_usize..7_usize => panic!("shouldn't match range end"), + _ => {}, + } + match 5_usize { + 1_usize => panic!("should match non-first range"), + 2_usize..=6_usize => {} + _ => panic!("math is broken") + } + match 'c' { + 'a'..='z' => {} + _ => panic!("should support char ranges") + } + match -3 { + -7..=5 => {} + _ => panic!("should match signed range") + } + match 3.0f64 { + 1.0..=5.0 => {} + _ => panic!("should match float range") + } + match -1.5f64 { + -3.6..=3.6 => {} + _ => panic!("should match negative float range") + } + match 3.5 { + 0.0..3.5 => panic!("should not match the range end"), + _ => {}, + } + match 0.0 { + 0.0..3.5 => {}, + _ => panic!("should match the range start"), + } +} diff --git a/tests/ui/binding/match-reassign.rs b/tests/ui/binding/match-reassign.rs new file mode 100644 index 000000000..19b48579c --- /dev/null +++ b/tests/ui/binding/match-reassign.rs @@ -0,0 +1,21 @@ +// run-pass +// Regression test for #23698: The reassignment checker only cared +// about the last assignment in a match arm body + +// Use an extra function to make sure no extra assignments +// are introduced by macros in the match statement +fn check_eq(x: i32, y: i32) { + assert_eq!(x, y); +} + +#[allow(unused_assignments)] +fn main() { + let mut x = Box::new(1); + match x { + y => { + x = Box::new(2); + let _tmp = 1; // This assignment used to throw off the reassignment checker + check_eq(*y, 1); + } + } +} diff --git a/tests/ui/binding/match-ref-binding-in-guard-3256.rs b/tests/ui/binding/match-ref-binding-in-guard-3256.rs new file mode 100644 index 000000000..9075a34d4 --- /dev/null +++ b/tests/ui/binding/match-ref-binding-in-guard-3256.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::sync::Mutex; + +pub fn main() { + let x = Some(Mutex::new(true)); + match x { + Some(ref z) if *z.lock().unwrap() => { + assert!(*z.lock().unwrap()); + }, + _ => panic!() + } +} diff --git a/tests/ui/binding/match-ref-binding-mut-option.rs b/tests/ui/binding/match-ref-binding-mut-option.rs new file mode 100644 index 000000000..c25639b72 --- /dev/null +++ b/tests/ui/binding/match-ref-binding-mut-option.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let mut v = Some(22); + match v { + None => {} + Some(ref mut p) => { *p += 1; } + } + assert_eq!(v, Some(23)); +} diff --git a/tests/ui/binding/match-ref-binding-mut.rs b/tests/ui/binding/match-ref-binding-mut.rs new file mode 100644 index 000000000..d7afd61bc --- /dev/null +++ b/tests/ui/binding/match-ref-binding-mut.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Rec { + f: isize +} + +fn destructure(x: &mut Rec) { + match *x { + Rec {f: ref mut f} => *f += 1 + } +} + +pub fn main() { + let mut v = Rec {f: 22}; + destructure(&mut v); + assert_eq!(v.f, 23); +} diff --git a/tests/ui/binding/match-ref-binding.rs b/tests/ui/binding/match-ref-binding.rs new file mode 100644 index 000000000..ac6a07eab --- /dev/null +++ b/tests/ui/binding/match-ref-binding.rs @@ -0,0 +1,12 @@ +// run-pass + +fn destructure(x: Option) -> isize { + match x { + None => 0, + Some(ref v) => *v + } +} + +pub fn main() { + assert_eq!(destructure(Some(22)), 22); +} diff --git a/tests/ui/binding/match-ref-unsized.rs b/tests/ui/binding/match-ref-unsized.rs new file mode 100644 index 000000000..53784ebb9 --- /dev/null +++ b/tests/ui/binding/match-ref-unsized.rs @@ -0,0 +1,11 @@ +// run-pass +// Binding unsized expressions to ref patterns + +pub fn main() { + let ref a = *"abcdef"; + assert_eq!(a, "abcdef"); + + match *"12345" { + ref b => { assert_eq!(b, "12345") } + } +} diff --git a/tests/ui/binding/match-str.rs b/tests/ui/binding/match-str.rs new file mode 100644 index 000000000..0ee18ea18 --- /dev/null +++ b/tests/ui/binding/match-str.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// Issue #53 +#![allow(non_camel_case_types)] + + +pub fn main() { + match "test" { "not-test" => panic!(), "test" => (), _ => panic!() } + + enum t { tag1(String), tag2, } + + + match t::tag1("test".to_string()) { + t::tag2 => panic!(), + t::tag1(ref s) if "test" != &**s => panic!(), + t::tag1(ref s) if "test" == &**s => (), + _ => panic!() + } + + let x = match "a" { "a" => 1, "b" => 2, _ => panic!() }; + assert_eq!(x, 1); + + match "a" { "a" => { } "b" => { }, _ => panic!() } + +} diff --git a/tests/ui/binding/match-struct-0.rs b/tests/ui/binding/match-struct-0.rs new file mode 100644 index 000000000..c49f3ed61 --- /dev/null +++ b/tests/ui/binding/match-struct-0.rs @@ -0,0 +1,21 @@ +// run-pass + +struct Foo{ + f : isize, +} + +pub fn main() { + let f = Foo{f: 1}; + match f { + Foo{f: 0} => panic!(), + Foo{..} => (), + } + match f { + Foo{f: 0} => panic!(), + Foo{f: _f} => (), + } + match f { + Foo{f: 0} => panic!(), + _ => (), + } +} diff --git a/tests/ui/binding/match-tag.rs b/tests/ui/binding/match-tag.rs new file mode 100644 index 000000000..407716aa2 --- /dev/null +++ b/tests/ui/binding/match-tag.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + + +#[allow(unused_tuple_struct_fields)] +enum color { + rgb(isize, isize, isize), + rgba(isize, isize, isize, isize), + hsl(isize, isize, isize), +} + +fn process(c: color) -> isize { + let mut x: isize; + match c { + color::rgb(r, _, _) => { x = r; } + color::rgba(_, _, _, a) => { x = a; } + color::hsl(_, s, _) => { x = s; } + } + return x; +} + +pub fn main() { + let gray: color = color::rgb(127, 127, 127); + let clear: color = color::rgba(50, 150, 250, 0); + let red: color = color::hsl(0, 255, 255); + assert_eq!(process(gray), 127); + assert_eq!(process(clear), 0); + assert_eq!(process(red), 255); +} diff --git a/tests/ui/binding/match-unique-bind.rs b/tests/ui/binding/match-unique-bind.rs new file mode 100644 index 000000000..507478983 --- /dev/null +++ b/tests/ui/binding/match-unique-bind.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(box_patterns)] + +pub fn main() { + match Box::new(100) { + box x => { + println!("{}", x); + assert_eq!(x, 100); + } + } +} diff --git a/tests/ui/binding/match-unsized.rs b/tests/ui/binding/match-unsized.rs new file mode 100644 index 000000000..41937a557 --- /dev/null +++ b/tests/ui/binding/match-unsized.rs @@ -0,0 +1,9 @@ +// run-pass +fn main() { + let data: &'static str = "Hello, World!"; + match data { + &ref xs => { + assert_eq!(data, xs); + } + } +} diff --git a/tests/ui/binding/match-value-binding-in-guard-3291.rs b/tests/ui/binding/match-value-binding-in-guard-3291.rs new file mode 100644 index 000000000..0d750da79 --- /dev/null +++ b/tests/ui/binding/match-value-binding-in-guard-3291.rs @@ -0,0 +1,17 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn foo(x: Option>, b: bool) -> isize { + match x { + None => { 1 } + Some(ref x) if b => { *x.clone() } + Some(_) => { 0 } + } +} + +pub fn main() { + foo(Some(Box::new(22)), true); + foo(Some(Box::new(22)), false); + foo(None, true); + foo(None, false); +} diff --git a/tests/ui/binding/match-var-hygiene.rs b/tests/ui/binding/match-var-hygiene.rs new file mode 100644 index 000000000..43740bbcf --- /dev/null +++ b/tests/ui/binding/match-var-hygiene.rs @@ -0,0 +1,11 @@ +// run-pass +// shouldn't affect evaluation of $ex. +macro_rules! bad_macro { ($ex:expr) => ( + {match 9 {_x => $ex}} +)} + +fn main() { + match 8 { + _x => assert_eq!(bad_macro!(_x),8) + } +} diff --git a/tests/ui/binding/match-vec-alternatives.rs b/tests/ui/binding/match-vec-alternatives.rs new file mode 100644 index 000000000..af95eb95d --- /dev/null +++ b/tests/ui/binding/match-vec-alternatives.rs @@ -0,0 +1,80 @@ +// run-pass + +fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { + match (l1, l2) { + (&[], &[]) => "both empty", + (&[], &[..]) | (&[..], &[]) => "one empty", + (&[..], &[..]) => "both non-empty" + } +} + +fn match_vecs_cons<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { + match (l1, l2) { + (&[], &[]) => "both empty", + (&[], &[_, ..]) | (&[_, ..], &[]) => "one empty", + (&[_, ..], &[_, ..]) => "both non-empty" + } +} + +fn match_vecs_snoc<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { + match (l1, l2) { + (&[], &[]) => "both empty", + (&[], &[.., _]) | (&[.., _], &[]) => "one empty", + (&[.., _], &[.., _]) => "both non-empty" + } +} + +fn match_nested_vecs_cons<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str { + match (l1, l2) { + (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)", + (Some(&[_, ..]), Ok(_)) | (Some(&[_, ..]), Err(())) => "Some(non-empty), any", + (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)", + (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)", + _ => "other" + } +} + +fn match_nested_vecs_snoc<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str { + match (l1, l2) { + (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)", + (Some(&[.., _]), Ok(_)) | (Some(&[.., _]), Err(())) => "Some(non-empty), any", + (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)", + (None, Ok(&[.., _, _])) => "None, Ok(at least two elements)", + _ => "other" + } +} + +fn main() { + assert_eq!(match_vecs(&[1, 2], &[2, 3]), "both non-empty"); + assert_eq!(match_vecs(&[], &[1, 2, 3, 4]), "one empty"); + assert_eq!(match_vecs::(&[], &[]), "both empty"); + assert_eq!(match_vecs(&[1, 2, 3], &[]), "one empty"); + + assert_eq!(match_vecs_cons(&[1, 2], &[2, 3]), "both non-empty"); + assert_eq!(match_vecs_cons(&[], &[1, 2, 3, 4]), "one empty"); + assert_eq!(match_vecs_cons::(&[], &[]), "both empty"); + assert_eq!(match_vecs_cons(&[1, 2, 3], &[]), "one empty"); + + assert_eq!(match_vecs_snoc(&[1, 2], &[2, 3]), "both non-empty"); + assert_eq!(match_vecs_snoc(&[], &[1, 2, 3, 4]), "one empty"); + assert_eq!(match_vecs_snoc::(&[], &[]), "both empty"); + assert_eq!(match_vecs_snoc(&[1, 2, 3], &[]), "one empty"); + + assert_eq!(match_nested_vecs_cons(None, Ok::<&[_], ()>(&[4_usize, 2_usize])), + "None, Ok(at least two elements)"); + assert_eq!(match_nested_vecs_cons::(None, Err(())), "None, Ok(less than one element)"); + assert_eq!(match_nested_vecs_cons::(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), + "Some(empty), Ok(empty)"); + assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[1]), Err(())), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[(42, ())]), Ok::<&[_], ()>(&[(1, ())])), + "Some(non-empty), any"); + + assert_eq!(match_nested_vecs_snoc(None, Ok::<&[_], ()>(&[4_usize, 2_usize])), + "None, Ok(at least two elements)"); + assert_eq!(match_nested_vecs_snoc::(None, Err(())), "None, Ok(less than one element)"); + assert_eq!(match_nested_vecs_snoc::(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), + "Some(empty), Ok(empty)"); + assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[1]), Err(())), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[(42, ())]), Ok::<&[_], ()>(&[(1, ())])), + "Some(non-empty), any"); +} diff --git a/tests/ui/binding/match-vec-rvalue.rs b/tests/ui/binding/match-vec-rvalue.rs new file mode 100644 index 000000000..fead2254c --- /dev/null +++ b/tests/ui/binding/match-vec-rvalue.rs @@ -0,0 +1,15 @@ +// run-pass +// Tests that matching rvalues with drops does not crash. + + + +pub fn main() { + match vec![1, 2, 3] { + x => { + assert_eq!(x.len(), 3); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + } + } +} diff --git a/tests/ui/binding/match-with-ret-arm.rs b/tests/ui/binding/match-with-ret-arm.rs new file mode 100644 index 000000000..58a909641 --- /dev/null +++ b/tests/ui/binding/match-with-ret-arm.rs @@ -0,0 +1,12 @@ +// run-pass +pub fn main() { + // sometimes we have had trouble finding + // the right type for f, as we unified + // bot and u32 here + let f = match "1234".parse::().ok() { + None => return (), + Some(num) => num as u32 + }; + assert_eq!(f, 1234); + println!("{}", f) +} diff --git a/tests/ui/binding/multi-let.rs b/tests/ui/binding/multi-let.rs new file mode 100644 index 000000000..064d32a70 --- /dev/null +++ b/tests/ui/binding/multi-let.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let x = 10; + let y = x; + assert_eq!(y, 10); +} diff --git a/tests/ui/binding/mut-in-ident-patterns.rs b/tests/ui/binding/mut-in-ident-patterns.rs new file mode 100644 index 000000000..1d1dd660e --- /dev/null +++ b/tests/ui/binding/mut-in-ident-patterns.rs @@ -0,0 +1,76 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(non_camel_case_types)] +#![allow(non_shorthand_field_patterns)] + +trait Foo { + fn foo(&self, mut x: isize) -> isize { + let val = x; + x = 37 * x; + val + x + } +} + +struct X; +impl Foo for X {} + +pub fn main() { + let (a, mut b) = (23, 4); + assert_eq!(a, 23); + assert_eq!(b, 4); + b = a + b; + assert_eq!(b, 27); + + + assert_eq!(X.foo(2), 76); + + enum Bar { + Foo(isize), + Baz(f32, u8) + } + + let (x, mut y) = (32, Bar::Foo(21)); + + match x { + mut z @ 32 => { + assert_eq!(z, 32); + z = 34; + assert_eq!(z, 34); + } + _ => {} + } + + check_bar(&y); + y = Bar::Baz(10.0, 3); + check_bar(&y); + + fn check_bar(y: &Bar) { + match y { + &Bar::Foo(a) => { + assert_eq!(a, 21); + } + &Bar::Baz(a, b) => { + assert_eq!(a, 10.0); + assert_eq!(b, 3); + } + } + } + + fn foo1((x, mut y): (f64, isize), mut z: isize) -> isize { + y = 2 * 6; + z = y + (x as isize); + y - z + } + + struct A { + x: isize + } + let A { x: mut x } = A { x: 10 }; + assert_eq!(x, 10); + x = 30; + assert_eq!(x, 30); + + (|A { x: mut t }: A| { t = t+1; t })(A { x: 34 }); + +} diff --git a/tests/ui/binding/nested-matchs.rs b/tests/ui/binding/nested-matchs.rs new file mode 100644 index 000000000..29490fd48 --- /dev/null +++ b/tests/ui/binding/nested-matchs.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_mut)] // under NLL we get warning about `bar` below +fn baz() -> ! { panic!(); } + +fn foo() { + match Some::(5) { + Some::(_x) => { + let mut bar; + match None:: { None:: => { bar = 5; } _ => { baz(); } } + println!("{}", bar); + } + None:: => { println!("hello"); } + } +} + +pub fn main() { foo(); } diff --git a/tests/ui/binding/nested-pattern.rs b/tests/ui/binding/nested-pattern.rs new file mode 100644 index 000000000..7d14c9ad9 --- /dev/null +++ b/tests/ui/binding/nested-pattern.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// a bug was causing this to complain about leaked memory on exit + +enum t { foo(isize, usize), bar(isize, Option), } + +fn nested(o: t) { + match o { + t::bar(_i, Some::(_)) => { println!("wrong pattern matched"); panic!(); } + _ => { println!("succeeded"); } + } +} + +pub fn main() { nested(t::bar(1, None::)); } diff --git a/tests/ui/binding/nil-pattern.rs b/tests/ui/binding/nil-pattern.rs new file mode 100644 index 000000000..268af351d --- /dev/null +++ b/tests/ui/binding/nil-pattern.rs @@ -0,0 +1,4 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { let x = (); match x { () => { } } } diff --git a/tests/ui/binding/nullary-or-pattern.rs b/tests/ui/binding/nullary-or-pattern.rs new file mode 100644 index 000000000..7a3d9d60e --- /dev/null +++ b/tests/ui/binding/nullary-or-pattern.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(non_camel_case_types)] + +enum blah { a, b, } + +fn or_alt(q: blah) -> isize { + match q { blah::a | blah::b => { 42 } } +} + +pub fn main() { + assert_eq!(or_alt(blah::a), 42); + assert_eq!(or_alt(blah::b), 42); +} diff --git a/tests/ui/binding/optional_comma_in_match_arm.rs b/tests/ui/binding/optional_comma_in_match_arm.rs new file mode 100644 index 000000000..fc268bf2a --- /dev/null +++ b/tests/ui/binding/optional_comma_in_match_arm.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(unused_unsafe)] +// ignore-pretty issue #37199 +#![allow(while_true)] + +fn main() { + let x = 1; + + match x { + 1 => loop { break; }, + 2 => while true { break; }, + 3 => if true { () }, + 4 => if true { () } else { () }, + 5 => match () { () => () }, + 6 => { () }, + 7 => unsafe { () }, + _ => (), + } + + match x { + 1 => loop { break; } + 2 => while true { break; } + 3 => if true { () } + 4 => if true { () } else { () } + 5 => match () { () => () } + 6 => { () } + 7 => unsafe { () } + _ => () + } + + let r: &i32 = &x; + + match r { + // Absence of comma should not cause confusion between a pattern + // and a bitwise and. + &1 => if true { () } else { () } + &2 => (), + _ =>() + } +} diff --git a/tests/ui/binding/or-pattern.rs b/tests/ui/binding/or-pattern.rs new file mode 100644 index 000000000..47623a3d7 --- /dev/null +++ b/tests/ui/binding/or-pattern.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(non_camel_case_types)] + +enum blah { a(isize, isize, #[allow(unused_tuple_struct_fields)] usize), b(isize, isize), c, } + +fn or_alt(q: blah) -> isize { + match q { blah::a(x, y, _) | blah::b(x, y) => { return x + y; } blah::c => { return 0; } } +} + +pub fn main() { + assert_eq!(or_alt(blah::c), 0); + assert_eq!(or_alt(blah::a(10, 100, 0)), 110); + assert_eq!(or_alt(blah::b(20, 200)), 220); +} diff --git a/tests/ui/binding/order-drop-with-match.rs b/tests/ui/binding/order-drop-with-match.rs new file mode 100644 index 000000000..f50632ede --- /dev/null +++ b/tests/ui/binding/order-drop-with-match.rs @@ -0,0 +1,57 @@ +// run-pass + +// Test to make sure the destructors run in the right order. +// Each destructor sets it's tag in the corresponding entry +// in ORDER matching up to when it ran. +// Correct order is: matched, inner, outer + + +static mut ORDER: [usize; 3] = [0, 0, 0]; +static mut INDEX: usize = 0; + +struct A; +impl Drop for A { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = 1; + INDEX = INDEX + 1; + } + } +} + +struct B; +impl Drop for B { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = 2; + INDEX = INDEX + 1; + } + } +} + +struct C; +impl Drop for C { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = 3; + INDEX = INDEX + 1; + } + } +} + +fn main() { + { + let matched = A; + let _outer = C; + { + match matched { + _s => {} + } + let _inner = B; + } + } + unsafe { + let expected: &[_] = &[1, 2, 3]; + assert_eq!(expected, ORDER); + } +} diff --git a/tests/ui/binding/pat-ranges.rs b/tests/ui/binding/pat-ranges.rs new file mode 100644 index 000000000..19b304578 --- /dev/null +++ b/tests/ui/binding/pat-ranges.rs @@ -0,0 +1,20 @@ +// run-pass +// Parsing of range patterns + +#![allow(ellipsis_inclusive_range_patterns)] + +const NUM1: i32 = 10; + +mod m { + pub const NUM2: i32 = 16; +} + +fn main() { + if let NUM1 ... m::NUM2 = 10 {} else { panic!() } + if let ::NUM1 ... ::m::NUM2 = 11 {} else { panic!() } + if let -13 ... -10 = 12 { panic!() } else {} + + if let NUM1 ..= m::NUM2 = 10 {} else { panic!() } + if let ::NUM1 ..= ::m::NUM2 = 11 {} else { panic!() } + if let -13 ..= -10 = 12 { panic!() } else {} +} diff --git a/tests/ui/binding/pat-tuple-1.rs b/tests/ui/binding/pat-tuple-1.rs new file mode 100644 index 000000000..b09d4a22d --- /dev/null +++ b/tests/ui/binding/pat-tuple-1.rs @@ -0,0 +1,93 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3); + match x { + (a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + (.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + (a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + S(.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-2.rs b/tests/ui/binding/pat-tuple-2.rs new file mode 100644 index 000000000..810fd2641 --- /dev/null +++ b/tests/ui/binding/pat-tuple-2.rs @@ -0,0 +1,23 @@ +// run-pass +fn tuple() { + let x = (1,); + match x { + (2, ..) => panic!(), + (..) => () + } +} + +fn tuple_struct() { + struct S(u8); + + let x = S(1); + match x { + S(2, ..) => panic!(), + S(..) => () + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-3.rs b/tests/ui/binding/pat-tuple-3.rs new file mode 100644 index 000000000..9bec89861 --- /dev/null +++ b/tests/ui/binding/pat-tuple-3.rs @@ -0,0 +1,29 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3); + let branch = match x { + (1, 1, ..) => 0, + (1, 2, 3, ..) => 1, + (1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + let branch = match x { + S(1, 1, ..) => 0, + S(1, 2, 3, ..) => 1, + S(1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-4.rs b/tests/ui/binding/pat-tuple-4.rs new file mode 100644 index 000000000..71a548502 --- /dev/null +++ b/tests/ui/binding/pat-tuple-4.rs @@ -0,0 +1,57 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3); + match x { + (1, 2, 4) => unreachable!(), + (0, 2, 3, ..) => unreachable!(), + (0, .., 3) => unreachable!(), + (0, ..) => unreachable!(), + (1, 2, 3) => (), + (_, _, _) => unreachable!(), + } + match x { + (..) => (), + } + match x { + (_, _, _, ..) => (), + } + match x { + (a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(1, 2, 4) => unreachable!(), + S(0, 2, 3, ..) => unreachable!(), + S(0, .., 3) => unreachable!(), + S(0, ..) => unreachable!(), + S(1, 2, 3) => (), + S(_, _, _) => unreachable!(), + } + match x { + S(..) => (), + } + match x { + S(_, _, _, ..) => (), + } + match x { + S(a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-5.rs b/tests/ui/binding/pat-tuple-5.rs new file mode 100644 index 000000000..c8cdd37dd --- /dev/null +++ b/tests/ui/binding/pat-tuple-5.rs @@ -0,0 +1,29 @@ +// run-pass +fn tuple() { + struct S; + struct Z; + struct W; + let x = (S, Z, W); + match x { (S, ..) => {} } + match x { (.., W) => {} } + match x { (S, .., W) => {} } + match x { (.., Z, _) => {} } +} + +fn tuple_struct() { + struct SS(S, Z, W); + + struct S; + struct Z; + struct W; + let x = SS(S, Z, W); + match x { SS(S, ..) => {} } + match x { SS(.., W) => {} } + match x { SS(S, .., W) => {} } + match x { SS(.., Z, _) => {} } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-6.rs b/tests/ui/binding/pat-tuple-6.rs new file mode 100644 index 000000000..877f0e414 --- /dev/null +++ b/tests/ui/binding/pat-tuple-6.rs @@ -0,0 +1,45 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3, 4, 5); + match x { + (a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + (a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8, u8, u8); + + let x = S(1, 2, 3, 4, 5); + match x { + S(a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + S(a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-7.rs b/tests/ui/binding/pat-tuple-7.rs new file mode 100644 index 000000000..7835e2c35 --- /dev/null +++ b/tests/ui/binding/pat-tuple-7.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + #[allow(unused_parens)] + match 0 { + (pat) => assert_eq!(pat, 0) + } +} diff --git a/tests/ui/binding/pattern-bound-var-in-for-each.rs b/tests/ui/binding/pattern-bound-var-in-for-each.rs new file mode 100644 index 000000000..3f725cddc --- /dev/null +++ b/tests/ui/binding/pattern-bound-var-in-for-each.rs @@ -0,0 +1,20 @@ +// run-pass +// Tests that codegen_path checks whether a +// pattern-bound var is an upvar (when codegenning +// the for-each body) + + +fn foo(src: usize) { + + match Some(src) { + Some(src_id) => { + for _i in 0_usize..10_usize { + let yyy = src_id; + assert_eq!(yyy, 0_usize); + } + } + _ => { } + } +} + +pub fn main() { foo(0_usize); } diff --git a/tests/ui/binding/pattern-in-closure.rs b/tests/ui/binding/pattern-in-closure.rs new file mode 100644 index 000000000..3ac8d5768 --- /dev/null +++ b/tests/ui/binding/pattern-in-closure.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize +} + +pub fn main() { + let f = |(x, _): (isize, isize)| println!("{}", x + 1); + let g = |Foo { x: x, y: _y }: Foo| println!("{}", x + 1); + f((2, 3)); + g(Foo { x: 1, y: 2 }); +} diff --git a/tests/ui/binding/range-inclusive-pattern-precedence.rs b/tests/ui/binding/range-inclusive-pattern-precedence.rs new file mode 100644 index 000000000..858239bb1 --- /dev/null +++ b/tests/ui/binding/range-inclusive-pattern-precedence.rs @@ -0,0 +1,23 @@ +// run-pass +#![feature(box_patterns)] + +const VALUE: usize = 21; + +pub fn main() { + match &18 { + &(18..=18) => {} + _ => { unreachable!(); } + } + match &21 { + &(VALUE..=VALUE) => {} + _ => { unreachable!(); } + } + match Box::new(18) { + box (18..=18) => {} + _ => { unreachable!(); } + } + match Box::new(21) { + box (VALUE..=VALUE) => {} + _ => { unreachable!(); } + } +} diff --git a/tests/ui/binding/shadow.rs b/tests/ui/binding/shadow.rs new file mode 100644 index 000000000..2495c8f47 --- /dev/null +++ b/tests/ui/binding/shadow.rs @@ -0,0 +1,24 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +fn foo(c: Vec ) { + let a: isize = 5; + let mut b: Vec = Vec::new(); + + + match t::none:: { + t::some::(_) => { + for _i in &c { + println!("{}", a); + let a = 17; + b.push(a); + } + } + _ => { } + } +} + +enum t { none, some(T), } + +pub fn main() { let x = 10; let x = x + 20; assert_eq!(x, 30); foo(Vec::new()); } diff --git a/tests/ui/binding/simple-generic-match.rs b/tests/ui/binding/simple-generic-match.rs new file mode 100644 index 000000000..2cf050d01 --- /dev/null +++ b/tests/ui/binding/simple-generic-match.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum clam { a(#[allow(unused_tuple_struct_fields)] T), } + +pub fn main() { let c = clam::a(2); match c { clam::a::(_) => { } } } diff --git a/tests/ui/binding/use-uninit-match.rs b/tests/ui/binding/use-uninit-match.rs new file mode 100644 index 000000000..9250dbf0c --- /dev/null +++ b/tests/ui/binding/use-uninit-match.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +fn foo(o: myoption) -> isize { + let mut x: isize = 5; + match o { + myoption::none:: => { } + myoption::some::(_t) => { x += 1; } + } + return x; +} + +enum myoption { none, some(T), } + +pub fn main() { println!("{}", 5); } diff --git a/tests/ui/binding/use-uninit-match2.rs b/tests/ui/binding/use-uninit-match2.rs new file mode 100644 index 000000000..910273062 --- /dev/null +++ b/tests/ui/binding/use-uninit-match2.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + + +fn foo(o: myoption) -> isize { + let mut x: isize; + match o { + myoption::none:: => { panic!(); } + myoption::some::(_t) => { x = 5; } + } + return x; +} + +enum myoption { none, some(T), } + +pub fn main() { println!("{}", 5); } diff --git a/tests/ui/binding/zero_sized_subslice_match.rs b/tests/ui/binding/zero_sized_subslice_match.rs new file mode 100644 index 000000000..187c29836 --- /dev/null +++ b/tests/ui/binding/zero_sized_subslice_match.rs @@ -0,0 +1,11 @@ +// run-pass + +fn main() { + let x = [(), ()]; + + // The subslice used to go out of bounds for zero-sized array items, check that this doesn't + // happen anymore + match x { + [_, ref y @ ..] => assert_eq!(&x[1] as *const (), &y[0] as *const ()) + } +} diff --git a/tests/ui/binop/binary-minus-without-space.rs b/tests/ui/binop/binary-minus-without-space.rs new file mode 100644 index 000000000..2fbd5300d --- /dev/null +++ b/tests/ui/binop/binary-minus-without-space.rs @@ -0,0 +1,8 @@ +// run-pass +// Check that issue #954 stays fixed + + +pub fn main() { + match -1 { -1 => {}, _ => panic!("wat") } + assert_eq!(1-1, 0); +} diff --git a/tests/ui/binop/binary-op-on-double-ref.fixed b/tests/ui/binop/binary-op-on-double-ref.fixed new file mode 100644 index 000000000..de9dc19af --- /dev/null +++ b/tests/ui/binop/binary-op-on-double-ref.fixed @@ -0,0 +1,9 @@ +// run-rustfix +fn main() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let vr = v.iter().filter(|x| { + *x % 2 == 0 + //~^ ERROR cannot mod `&&{integer}` by `{integer}` + }); + println!("{:?}", vr); +} diff --git a/tests/ui/binop/binary-op-on-double-ref.rs b/tests/ui/binop/binary-op-on-double-ref.rs new file mode 100644 index 000000000..2616c560c --- /dev/null +++ b/tests/ui/binop/binary-op-on-double-ref.rs @@ -0,0 +1,9 @@ +// run-rustfix +fn main() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9]; + let vr = v.iter().filter(|x| { + x % 2 == 0 + //~^ ERROR cannot mod `&&{integer}` by `{integer}` + }); + println!("{:?}", vr); +} diff --git a/tests/ui/binop/binary-op-on-double-ref.stderr b/tests/ui/binop/binary-op-on-double-ref.stderr new file mode 100644 index 000000000..34826d2f4 --- /dev/null +++ b/tests/ui/binop/binary-op-on-double-ref.stderr @@ -0,0 +1,16 @@ +error[E0369]: cannot mod `&&{integer}` by `{integer}` + --> $DIR/binary-op-on-double-ref.rs:5:11 + | +LL | x % 2 == 0 + | - ^ - {integer} + | | + | &&{integer} + | +help: `%` can be used on `&{integer}` if you dereference the left-hand side + | +LL | *x % 2 == 0 + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs new file mode 100644 index 000000000..8e20640b5 --- /dev/null +++ b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs @@ -0,0 +1,9 @@ +// run-pass +// Tests equality between supertype and subtype of a function +// See the issue #91636 +fn foo(_a: &str) {} + +fn main() { + let x = foo as fn(&'static str); + let _ = x == foo; +} diff --git a/tests/ui/binop/binop-bitxor-str.rs b/tests/ui/binop/binop-bitxor-str.rs new file mode 100644 index 000000000..3085cce3f --- /dev/null +++ b/tests/ui/binop/binop-bitxor-str.rs @@ -0,0 +1,3 @@ +// error-pattern:no implementation for `String ^ String` + +fn main() { let x = "a".to_string() ^ "b".to_string(); } diff --git a/tests/ui/binop/binop-bitxor-str.stderr b/tests/ui/binop/binop-bitxor-str.stderr new file mode 100644 index 000000000..f236cd61e --- /dev/null +++ b/tests/ui/binop/binop-bitxor-str.stderr @@ -0,0 +1,11 @@ +error[E0369]: no implementation for `String ^ String` + --> $DIR/binop-bitxor-str.rs:3:37 + | +LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } + | --------------- ^ --------------- String + | | + | String + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binop-consume-args.rs b/tests/ui/binop/binop-consume-args.rs new file mode 100644 index 000000000..8d6c725d7 --- /dev/null +++ b/tests/ui/binop/binop-consume-args.rs @@ -0,0 +1,65 @@ +// Test that binary operators consume their arguments + +use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitXor, BitOr, Shl, Shr}; + +fn add, B>(lhs: A, rhs: B) { + lhs + rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn sub, B>(lhs: A, rhs: B) { + lhs - rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn mul, B>(lhs: A, rhs: B) { + lhs * rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn div, B>(lhs: A, rhs: B) { + lhs / rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn rem, B>(lhs: A, rhs: B) { + lhs % rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn bitand, B>(lhs: A, rhs: B) { + lhs & rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn bitor, B>(lhs: A, rhs: B) { + lhs | rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn bitxor, B>(lhs: A, rhs: B) { + lhs ^ rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn shl, B>(lhs: A, rhs: B) { + lhs << rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn shr, B>(lhs: A, rhs: B) { + lhs >> rhs; + drop(lhs); //~ ERROR use of moved value: `lhs` + drop(rhs); //~ ERROR use of moved value: `rhs` +} + +fn main() {} diff --git a/tests/ui/binop/binop-consume-args.stderr b/tests/ui/binop/binop-consume-args.stderr new file mode 100644 index 000000000..6fbbb5543 --- /dev/null +++ b/tests/ui/binop/binop-consume-args.stderr @@ -0,0 +1,333 @@ +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:7:10 + | +LL | fn add, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs + rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting this bound + | +LL | fn add + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:8:10 + | +LL | fn add, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs + rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn add, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:13:10 + | +LL | fn sub, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs - rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting this bound + | +LL | fn sub + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:14:10 + | +LL | fn sub, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs - rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn sub, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:19:10 + | +LL | fn mul, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs * rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting this bound + | +LL | fn mul + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:20:10 + | +LL | fn mul, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs * rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn mul, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:25:10 + | +LL | fn div, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs / rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting this bound + | +LL | fn div + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:26:10 + | +LL | fn div, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs / rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn div, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:31:10 + | +LL | fn rem, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs % rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting this bound + | +LL | fn rem + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:32:10 + | +LL | fn rem, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs % rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn rem, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:37:10 + | +LL | fn bitand, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs & rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: consider further restricting this bound + | +LL | fn bitand + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:38:10 + | +LL | fn bitand, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs & rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn bitand, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:43:10 + | +LL | fn bitor, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs | rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: consider further restricting this bound + | +LL | fn bitor + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:44:10 + | +LL | fn bitor, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs | rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn bitor, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:49:10 + | +LL | fn bitxor, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs ^ rhs; + | --------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: consider further restricting this bound + | +LL | fn bitxor + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:50:10 + | +LL | fn bitxor, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs ^ rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn bitxor, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:55:10 + | +LL | fn shl, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs << rhs; + | ---------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: consider further restricting this bound + | +LL | fn shl + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:56:10 + | +LL | fn shl, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs << rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn shl, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `lhs` + --> $DIR/binop-consume-args.rs:61:10 + | +LL | fn shr, B>(lhs: A, rhs: B) { + | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait +LL | lhs >> rhs; + | ---------- `lhs` moved due to usage in operator +LL | drop(lhs); + | ^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: consider further restricting this bound + | +LL | fn shr + Copy, B>(lhs: A, rhs: B) { + | ++++++ + +error[E0382]: use of moved value: `rhs` + --> $DIR/binop-consume-args.rs:62:10 + | +LL | fn shr, B>(lhs: A, rhs: B) { + | --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait +LL | lhs >> rhs; + | --- value moved here +LL | drop(lhs); +LL | drop(rhs); + | ^^^ value used here after move + | +help: consider restricting type parameter `B` + | +LL | fn shr, B: Copy>(lhs: A, rhs: B) { + | ++++++ + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/binop/binop-fail-3.rs b/tests/ui/binop/binop-fail-3.rs new file mode 100644 index 000000000..49f635e0c --- /dev/null +++ b/tests/ui/binop/binop-fail-3.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn foo() -> ! { + panic!("quux"); +} + +fn main() { + foo() == foo(); // these types wind up being defaulted to () +} diff --git a/tests/ui/binop/binop-logic-float.rs b/tests/ui/binop/binop-logic-float.rs new file mode 100644 index 000000000..1750d97ba --- /dev/null +++ b/tests/ui/binop/binop-logic-float.rs @@ -0,0 +1,3 @@ +fn main() { let x = 1.0_f32 || 2.0_f32; } +//~^ ERROR mismatched types +//~| ERROR mismatched types diff --git a/tests/ui/binop/binop-logic-float.stderr b/tests/ui/binop/binop-logic-float.stderr new file mode 100644 index 000000000..3615622ae --- /dev/null +++ b/tests/ui/binop/binop-logic-float.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/binop-logic-float.rs:1:21 + | +LL | fn main() { let x = 1.0_f32 || 2.0_f32; } + | ^^^^^^^ expected `bool`, found `f32` + +error[E0308]: mismatched types + --> $DIR/binop-logic-float.rs:1:32 + | +LL | fn main() { let x = 1.0_f32 || 2.0_f32; } + | ^^^^^^^ expected `bool`, found `f32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/binop/binop-logic-int.rs b/tests/ui/binop/binop-logic-int.rs new file mode 100644 index 000000000..e71daa2dd --- /dev/null +++ b/tests/ui/binop/binop-logic-int.rs @@ -0,0 +1,3 @@ +fn main() { let x = 1 && 2; } +//~^ ERROR mismatched types +//~| ERROR mismatched types diff --git a/tests/ui/binop/binop-logic-int.stderr b/tests/ui/binop/binop-logic-int.stderr new file mode 100644 index 000000000..50d857cd9 --- /dev/null +++ b/tests/ui/binop/binop-logic-int.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/binop-logic-int.rs:1:21 + | +LL | fn main() { let x = 1 && 2; } + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/binop-logic-int.rs:1:26 + | +LL | fn main() { let x = 1 && 2; } + | ^ expected `bool`, found integer + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/binop/binop-move-semantics.rs b/tests/ui/binop/binop-move-semantics.rs new file mode 100644 index 000000000..b5133ea7c --- /dev/null +++ b/tests/ui/binop/binop-move-semantics.rs @@ -0,0 +1,68 @@ +// Test that move restrictions are enforced on overloaded binary operations + +use std::ops::Add; + +fn double_move>(x: T) { + x + + + x; //~ ERROR: use of moved value +} + +fn move_then_borrow + Clone>(x: T) { + x + + + x.clone(); //~ ERROR: borrow of moved value +} + +fn move_borrowed>(x: T, mut y: T) { + let m = &x; + let n = &mut y; + + x //~ ERROR: cannot move out of `x` because it is borrowed + + + y; //~ ERROR: cannot move out of `y` because it is borrowed + use_mut(n); use_imm(m); +} +fn illegal_dereference>(mut x: T, y: T) { + let m = &mut x; + let n = &y; + + *m //~ ERROR: cannot move + + + *n; //~ ERROR: cannot move + use_imm(n); use_mut(m); +} +struct Foo; + +impl<'a, 'b> Add<&'b Foo> for &'a mut Foo { + type Output = (); + + fn add(self, _: &Foo) {} +} + +impl<'a, 'b> Add<&'b mut Foo> for &'a Foo { + type Output = (); + + fn add(self, _: &mut Foo) {} +} + +fn mut_plus_immut() { + let mut f = Foo; + + &mut f + + + &f; //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable +} + +fn immut_plus_mut() { + let mut f = Foo; + + &f + + + &mut f; //~ ERROR: cannot borrow `f` as mutable because it is also borrowed as immutable +} + +fn main() {} + +fn use_mut(_: &mut T) { } +fn use_imm(_: &T) { } diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr new file mode 100644 index 000000000..dae267da0 --- /dev/null +++ b/tests/ui/binop/binop-move-semantics.stderr @@ -0,0 +1,118 @@ +error[E0382]: use of moved value: `x` + --> $DIR/binop-move-semantics.rs:8:5 + | +LL | fn double_move>(x: T) { + | - move occurs because `x` has type `T`, which does not implement the `Copy` trait +LL | / x +LL | | + +LL | | x; + | | ^ + | | | + | |_____value used here after move + | `x` moved due to usage in operator + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider further restricting this bound + | +LL | fn double_move + Copy>(x: T) { + | ++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/binop-move-semantics.rs:14:5 + | +LL | fn move_then_borrow + Clone>(x: T) { + | - move occurs because `x` has type `T`, which does not implement the `Copy` trait +LL | x + | - value moved here +LL | + +LL | x.clone(); + | ^^^^^^^^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x.clone() + | ++++++++ +help: consider further restricting this bound + | +LL | fn move_then_borrow + Clone + Copy>(x: T) { + | ++++++ + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/binop-move-semantics.rs:21:5 + | +LL | let m = &x; + | -- borrow of `x` occurs here +... +LL | x + | ^ move out of `x` occurs here +... +LL | use_mut(n); use_imm(m); + | - borrow later used here + +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/binop-move-semantics.rs:23:5 + | +LL | let n = &mut y; + | ------ borrow of `y` occurs here +... +LL | y; + | ^ move out of `y` occurs here +LL | use_mut(n); use_imm(m); + | - borrow later used here + +error[E0507]: cannot move out of `*m` which is behind a mutable reference + --> $DIR/binop-move-semantics.rs:30:5 + | +LL | *m + | -^ + | | + | _____move occurs because `*m` has type `T`, which does not implement the `Copy` trait + | | +LL | | + +LL | | *n; + | |______- `*m` moved due to usage in operator + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0507]: cannot move out of `*n` which is behind a shared reference + --> $DIR/binop-move-semantics.rs:32:5 + | +LL | *n; + | ^^ move occurs because `*n` has type `T`, which does not implement the `Copy` trait + +error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable + --> $DIR/binop-move-semantics.rs:54:5 + | +LL | &mut f + | ------ + | | + | _____mutable borrow occurs here + | | +LL | | + +LL | | &f; + | | ^- + | |_____|| + | |mutable borrow later used here + | immutable borrow occurs here + +error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable + --> $DIR/binop-move-semantics.rs:62:5 + | +LL | &f + | -- + | | + | _____immutable borrow occurs here + | | +LL | | + +LL | | &mut f; + | | ^^^^^- + | |_____|____| + | | immutable borrow later used here + | mutable borrow occurs here + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0382, E0502, E0505, E0507. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/binop/binop-mul-bool.rs b/tests/ui/binop/binop-mul-bool.rs new file mode 100644 index 000000000..41494c7a0 --- /dev/null +++ b/tests/ui/binop/binop-mul-bool.rs @@ -0,0 +1,3 @@ +// error-pattern:cannot multiply `bool` by `bool` + +fn main() { let x = true * false; } diff --git a/tests/ui/binop/binop-mul-bool.stderr b/tests/ui/binop/binop-mul-bool.stderr new file mode 100644 index 000000000..8b5cde63c --- /dev/null +++ b/tests/ui/binop/binop-mul-bool.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot multiply `bool` by `bool` + --> $DIR/binop-mul-bool.rs:3:26 + | +LL | fn main() { let x = true * false; } + | ---- ^ ----- bool + | | + | bool + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binop-mul-i32-f32.rs b/tests/ui/binop/binop-mul-i32-f32.rs new file mode 100644 index 000000000..d18be51a4 --- /dev/null +++ b/tests/ui/binop/binop-mul-i32-f32.rs @@ -0,0 +1,5 @@ +fn foo(x: i32, y: f32) -> f32 { + x * y //~ ERROR cannot multiply `i32` by `f32` +} + +fn main() {} diff --git a/tests/ui/binop/binop-mul-i32-f32.stderr b/tests/ui/binop/binop-mul-i32-f32.stderr new file mode 100644 index 000000000..c986bc3fd --- /dev/null +++ b/tests/ui/binop/binop-mul-i32-f32.stderr @@ -0,0 +1,16 @@ +error[E0277]: cannot multiply `i32` by `f32` + --> $DIR/binop-mul-i32-f32.rs:2:7 + | +LL | x * y + | ^ no implementation for `i32 * f32` + | + = help: the trait `Mul` is not implemented for `i32` + = help: the following other types implement trait `Mul`: + <&'a i32 as Mul> + <&i32 as Mul<&i32>> + > + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/binop-panic.rs b/tests/ui/binop/binop-panic.rs new file mode 100644 index 000000000..44cdfffee --- /dev/null +++ b/tests/ui/binop/binop-panic.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn my_err(s: String) -> ! { + println!("{}", s); + panic!("quux"); +} + +fn main() { + 3_usize == my_err("bye".to_string()); +} diff --git a/tests/ui/binop/binop-typeck.rs b/tests/ui/binop/binop-typeck.rs new file mode 100644 index 000000000..812fe95db --- /dev/null +++ b/tests/ui/binop/binop-typeck.rs @@ -0,0 +1,8 @@ +// issue #500 + +fn main() { + let x = true; + let y = 1; + let z = x + y; + //~^ ERROR cannot add `{integer}` to `bool` +} diff --git a/tests/ui/binop/binop-typeck.stderr b/tests/ui/binop/binop-typeck.stderr new file mode 100644 index 000000000..42d910819 --- /dev/null +++ b/tests/ui/binop/binop-typeck.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot add `{integer}` to `bool` + --> $DIR/binop-typeck.rs:6:15 + | +LL | let z = x + y; + | - ^ - {integer} + | | + | bool + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/binops-issue-22743.rs b/tests/ui/binop/binops-issue-22743.rs new file mode 100644 index 000000000..393ba0a56 --- /dev/null +++ b/tests/ui/binop/binops-issue-22743.rs @@ -0,0 +1,24 @@ +// run-pass + +use std::ops::Mul; + +#[derive(Copy, Clone)] +pub struct Foo { + x: f64, +} + +impl Mul for f64 { + type Output = Foo; + + fn mul(self, rhs: Foo) -> Foo { + // intentionally do something that is not * + Foo { x: self + rhs.x } + } +} + +pub fn main() { + let f: Foo = Foo { x: 5.0 }; + let val: f64 = 3.0; + let f2: Foo = val * f; + assert_eq!(f2.x, 8.0); +} diff --git a/tests/ui/binop/binops.rs b/tests/ui/binop/binops.rs new file mode 100644 index 000000000..a7abf6087 --- /dev/null +++ b/tests/ui/binop/binops.rs @@ -0,0 +1,89 @@ +// run-pass + +#![allow(non_camel_case_types)] +// Binop corner cases + +fn test_nil() { + assert_eq!((), ()); + assert!((!(() != ()))); + assert!((!(() < ()))); + assert!((() <= ())); + assert!((!(() > ()))); + assert!((() >= ())); +} + +fn test_bool() { + assert!((!(true < false))); + assert!((!(true <= false))); + assert!((true > false)); + assert!((true >= false)); + + assert!((false < true)); + assert!((false <= true)); + assert!((!(false > true))); + assert!((!(false >= true))); + + // Bools support bitwise binops + assert_eq!(false & false, false); + assert_eq!(true & false, false); + assert_eq!(true & true, true); + assert_eq!(false | false, false); + assert_eq!(true | false, true); + assert_eq!(true | true, true); + assert_eq!(false ^ false, false); + assert_eq!(true ^ false, true); + assert_eq!(true ^ true, false); +} + +fn test_ptr() { + unsafe { + let p1: *const u8 = ::std::mem::transmute(0_usize); + let p2: *const u8 = ::std::mem::transmute(0_usize); + let p3: *const u8 = ::std::mem::transmute(1_usize); + + assert_eq!(p1, p2); + assert!(p1 != p3); + assert!(p1 < p3); + assert!(p1 <= p3); + assert!(p3 > p1); + assert!(p3 >= p3); + assert!(p1 <= p2); + assert!(p1 >= p2); + } +} + +#[derive(PartialEq, Debug)] +struct p { + x: isize, + y: isize, +} + +fn p(x: isize, y: isize) -> p { + p { + x: x, + y: y + } +} + +fn test_class() { + let q = p(1, 2); + let mut r = p(1, 2); + + unsafe { + println!("q = {:x}, r = {:x}", + (::std::mem::transmute::<*const p, usize>(&q)), + (::std::mem::transmute::<*const p, usize>(&r))); + } + assert_eq!(q, r); + r.y = 17; + assert!((r.y != q.y)); + assert_eq!(r.y, 17); + assert!((q != r)); +} + +pub fn main() { + test_nil(); + test_bool(); + test_ptr(); + test_class(); +} diff --git a/tests/ui/binop/issue-25916.rs b/tests/ui/binop/issue-25916.rs new file mode 100644 index 000000000..0b4159479 --- /dev/null +++ b/tests/ui/binop/issue-25916.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_must_use)] + +fn main() { + macro_rules! f { + () => { 0 + 0 } + } + // 16 per line + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); + f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!(); +} diff --git a/tests/ui/binop/issue-28837.rs b/tests/ui/binop/issue-28837.rs new file mode 100644 index 000000000..9719c3afa --- /dev/null +++ b/tests/ui/binop/issue-28837.rs @@ -0,0 +1,35 @@ +struct A; + +fn main() { + let a = A; + + a + a; //~ ERROR cannot add `A` to `A` + + a - a; //~ ERROR cannot subtract `A` from `A` + + a * a; //~ ERROR cannot multiply `A` by `A` + + a / a; //~ ERROR cannot divide `A` by `A` + + a % a; //~ ERROR cannot mod `A` by `A` + + a & a; //~ ERROR no implementation for `A & A` + + a | a; //~ ERROR no implementation for `A | A` + + a << a; //~ ERROR no implementation for `A << A` + + a >> a; //~ ERROR no implementation for `A >> A` + + a == a; //~ ERROR binary operation `==` cannot be applied to type `A` + + a != a; //~ ERROR binary operation `!=` cannot be applied to type `A` + + a < a; //~ ERROR binary operation `<` cannot be applied to type `A` + + a <= a; //~ ERROR binary operation `<=` cannot be applied to type `A` + + a > a; //~ ERROR binary operation `>` cannot be applied to type `A` + + a >= a; //~ ERROR binary operation `>=` cannot be applied to type `A` +} diff --git a/tests/ui/binop/issue-28837.stderr b/tests/ui/binop/issue-28837.stderr new file mode 100644 index 000000000..6e236ca52 --- /dev/null +++ b/tests/ui/binop/issue-28837.stderr @@ -0,0 +1,255 @@ +error[E0369]: cannot add `A` to `A` + --> $DIR/issue-28837.rs:6:7 + | +LL | a + a; + | - ^ - A + | | + | A + | +note: an implementation of `Add<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Add<_>` +note: the trait `Add` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: cannot subtract `A` from `A` + --> $DIR/issue-28837.rs:8:7 + | +LL | a - a; + | - ^ - A + | | + | A + | +note: an implementation of `Sub<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Sub<_>` +note: the trait `Sub` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: cannot multiply `A` by `A` + --> $DIR/issue-28837.rs:10:7 + | +LL | a * a; + | - ^ - A + | | + | A + | +note: an implementation of `Mul<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Mul<_>` +note: the trait `Mul` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: cannot divide `A` by `A` + --> $DIR/issue-28837.rs:12:7 + | +LL | a / a; + | - ^ - A + | | + | A + | +note: an implementation of `Div<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Div<_>` +note: the trait `Div` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: cannot mod `A` by `A` + --> $DIR/issue-28837.rs:14:7 + | +LL | a % a; + | - ^ - A + | | + | A + | +note: an implementation of `Rem<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Rem<_>` +note: the trait `Rem` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: no implementation for `A & A` + --> $DIR/issue-28837.rs:16:7 + | +LL | a & a; + | - ^ - A + | | + | A + | +note: an implementation of `BitAnd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `BitAnd<_>` +note: the trait `BitAnd` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error[E0369]: no implementation for `A | A` + --> $DIR/issue-28837.rs:18:7 + | +LL | a | a; + | - ^ - A + | | + | A + | +note: an implementation of `BitOr<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `BitOr<_>` +note: the trait `BitOr` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error[E0369]: no implementation for `A << A` + --> $DIR/issue-28837.rs:20:7 + | +LL | a << a; + | - ^^ - A + | | + | A + | +note: an implementation of `Shl<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Shl<_>` +note: the trait `Shl` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error[E0369]: no implementation for `A >> A` + --> $DIR/issue-28837.rs:22:7 + | +LL | a >> a; + | - ^^ - A + | | + | A + | +note: an implementation of `Shr<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `Shr<_>` +note: the trait `Shr` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error[E0369]: binary operation `==` cannot be applied to type `A` + --> $DIR/issue-28837.rs:24:7 + | +LL | a == a; + | - ^^ - A + | | + | A + | +note: an implementation of `PartialEq<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `A` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error[E0369]: binary operation `!=` cannot be applied to type `A` + --> $DIR/issue-28837.rs:26:7 + | +LL | a != a; + | - ^^ - A + | | + | A + | +note: an implementation of `PartialEq<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `A` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error[E0369]: binary operation `<` cannot be applied to type `A` + --> $DIR/issue-28837.rs:28:7 + | +LL | a < a; + | - ^ - A + | | + | A + | +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` + | +LL | #[derive(PartialEq, PartialOrd)] + | + +error[E0369]: binary operation `<=` cannot be applied to type `A` + --> $DIR/issue-28837.rs:30:7 + | +LL | a <= a; + | - ^^ - A + | | + | A + | +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` + | +LL | #[derive(PartialEq, PartialOrd)] + | + +error[E0369]: binary operation `>` cannot be applied to type `A` + --> $DIR/issue-28837.rs:32:7 + | +LL | a > a; + | - ^ - A + | | + | A + | +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` + | +LL | #[derive(PartialEq, PartialOrd)] + | + +error[E0369]: binary operation `>=` cannot be applied to type `A` + --> $DIR/issue-28837.rs:34:7 + | +LL | a >= a; + | - ^^ - A + | | + | A + | +note: an implementation of `PartialOrd<_>` might be missing for `A` + --> $DIR/issue-28837.rs:1:1 + | +LL | struct A; + | ^^^^^^^^ must implement `PartialOrd<_>` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` + | +LL | #[derive(PartialEq, PartialOrd)] + | + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/issue-3820.rs b/tests/ui/binop/issue-3820.rs new file mode 100644 index 000000000..b987a90b2 --- /dev/null +++ b/tests/ui/binop/issue-3820.rs @@ -0,0 +1,15 @@ +struct Thing { + x: isize +} + +impl Thing { + fn mul(&self, c: &isize) -> Thing { + Thing {x: self.x * *c} + } +} + +fn main() { + let u = Thing {x: 2}; + let _v = u.mul(&3); // This is ok + let w = u * 3; //~ ERROR cannot multiply `Thing` by `{integer}` +} diff --git a/tests/ui/binop/issue-3820.stderr b/tests/ui/binop/issue-3820.stderr new file mode 100644 index 000000000..c313ed603 --- /dev/null +++ b/tests/ui/binop/issue-3820.stderr @@ -0,0 +1,19 @@ +error[E0369]: cannot multiply `Thing` by `{integer}` + --> $DIR/issue-3820.rs:14:15 + | +LL | let w = u * 3; + | - ^ - {integer} + | | + | Thing + | +note: an implementation of `Mul<_>` might be missing for `Thing` + --> $DIR/issue-3820.rs:1:1 + | +LL | struct Thing { + | ^^^^^^^^^^^^ must implement `Mul<_>` +note: the trait `Mul` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/issue-77910-1.rs b/tests/ui/binop/issue-77910-1.rs new file mode 100644 index 000000000..95bbd6a60 --- /dev/null +++ b/tests/ui/binop/issue-77910-1.rs @@ -0,0 +1,11 @@ +fn foo(s: &i32) -> &i32 { + let xs; + xs +} +fn main() { + let y; + // we shouldn't ice with the bound var here. + assert_eq!(foo, y); + //~^ ERROR binary operation `==` cannot be applied to type + //~| ERROR `for<'a> fn(&'a i32) -> &'a i32 {foo}` doesn't implement `Debug` +} diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr new file mode 100644 index 000000000..263a35d98 --- /dev/null +++ b/tests/ui/binop/issue-77910-1.stderr @@ -0,0 +1,28 @@ +error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` + --> $DIR/issue-77910-1.rs:8:5 + | +LL | assert_eq!(foo, y); + | ^^^^^^^^^^^^^^^^^^ + | | + | for<'a> fn(&'a i32) -> &'a i32 {foo} + | _ + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `for<'a> fn(&'a i32) -> &'a i32 {foo}` doesn't implement `Debug` + --> $DIR/issue-77910-1.rs:8:5 + | +LL | fn foo(s: &i32) -> &i32 { + | --- consider calling this function +... +LL | assert_eq!(foo, y); + | ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}` + = help: use parentheses to call this function: `foo(/* &i32 */)` + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0369. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/issue-77910-2.rs b/tests/ui/binop/issue-77910-2.rs new file mode 100644 index 000000000..2bb48d365 --- /dev/null +++ b/tests/ui/binop/issue-77910-2.rs @@ -0,0 +1,9 @@ +fn foo(s: &i32) -> &i32 { + let xs; + xs +} +fn main() { + let y; + if foo == y {} + //~^ ERROR binary operation `==` cannot be applied to type +} diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr new file mode 100644 index 000000000..b3856b6ae --- /dev/null +++ b/tests/ui/binop/issue-77910-2.stderr @@ -0,0 +1,16 @@ +error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` + --> $DIR/issue-77910-2.rs:7:12 + | +LL | if foo == y {} + | --- ^^ - _ + | | + | for<'a> fn(&'a i32) -> &'a i32 {foo} + | +help: use parentheses to call this function + | +LL | if foo(/* &i32 */) == y {} + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/issue-93927.rs b/tests/ui/binop/issue-93927.rs new file mode 100644 index 000000000..de27c9785 --- /dev/null +++ b/tests/ui/binop/issue-93927.rs @@ -0,0 +1,20 @@ +// Regression test for #93927: suggested trait bound for T should be Eq, not PartialEq +struct MyType(T); + +impl PartialEq for MyType +where + T: Eq, +{ + fn eq(&self, other: &Self) -> bool { + true + } +} + +fn cond(val: MyType) -> bool { + val == val + //~^ ERROR binary operation `==` cannot be applied to type `MyType` +} + +fn main() { + cond(MyType(0)); +} diff --git a/tests/ui/binop/issue-93927.stderr b/tests/ui/binop/issue-93927.stderr new file mode 100644 index 000000000..75558b502 --- /dev/null +++ b/tests/ui/binop/issue-93927.stderr @@ -0,0 +1,16 @@ +error[E0369]: binary operation `==` cannot be applied to type `MyType` + --> $DIR/issue-93927.rs:14:9 + | +LL | val == val + | --- ^^ --- MyType + | | + | MyType + | +help: consider further restricting this bound + | +LL | fn cond(val: MyType) -> bool { + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/binop/operator-multidispatch.rs b/tests/ui/binop/operator-multidispatch.rs new file mode 100644 index 000000000..0d1dcfd8b --- /dev/null +++ b/tests/ui/binop/operator-multidispatch.rs @@ -0,0 +1,36 @@ +// run-pass +// Test that we can overload the `+` operator for points so that two +// points can be added, and a point can be added to an integer. + +use std::ops; + +#[derive(Debug,PartialEq,Eq)] +struct Point { + x: isize, + y: isize +} + +impl ops::Add for Point { + type Output = Point; + + fn add(self, other: Point) -> Point { + Point {x: self.x + other.x, y: self.y + other.y} + } +} + +impl ops::Add for Point { + type Output = Point; + + fn add(self, other: isize) -> Point { + Point {x: self.x + other, + y: self.y + other} + } +} + +pub fn main() { + let mut p = Point {x: 10, y: 20}; + p = p + Point {x: 101, y: 102}; + assert_eq!(p, Point {x: 111, y: 122}); + p = p + 1; + assert_eq!(p, Point {x: 112, y: 123}); +} diff --git a/tests/ui/binop/operator-overloading.rs b/tests/ui/binop/operator-overloading.rs new file mode 100644 index 000000000..6b3abcbc7 --- /dev/null +++ b/tests/ui/binop/operator-overloading.rs @@ -0,0 +1,81 @@ +// run-pass + +#![allow(unused_variables)] +use std::cmp; +use std::ops; + +#[derive(Copy, Clone, Debug)] +struct Point { + x: isize, + y: isize +} + +impl ops::Add for Point { + type Output = Point; + + fn add(self, other: Point) -> Point { + Point {x: self.x + other.x, y: self.y + other.y} + } +} + +impl ops::Sub for Point { + type Output = Point; + + fn sub(self, other: Point) -> Point { + Point {x: self.x - other.x, y: self.y - other.y} + } +} + +impl ops::Neg for Point { + type Output = Point; + + fn neg(self) -> Point { + Point {x: -self.x, y: -self.y} + } +} + +impl ops::Not for Point { + type Output = Point; + + fn not(self) -> Point { + Point {x: !self.x, y: !self.y } + } +} + +impl ops::Index for Point { + type Output = isize; + + fn index(&self, x: bool) -> &isize { + if x { + &self.x + } else { + &self.y + } + } +} + +impl cmp::PartialEq for Point { + fn eq(&self, other: &Point) -> bool { + (*self).x == (*other).x && (*self).y == (*other).y + } + fn ne(&self, other: &Point) -> bool { !(*self).eq(other) } +} + +pub fn main() { + let mut p = Point {x: 10, y: 20}; + p = p + Point {x: 101, y: 102}; + p = p - Point {x: 100, y: 100}; + assert_eq!(p + Point {x: 5, y: 5}, Point {x: 16, y: 27}); + assert_eq!(-p, Point {x: -11, y: -22}); + assert_eq!(p[true], 11); + assert_eq!(p[false], 22); + + let q = !p; + assert_eq!(q.x, !(p.x)); + assert_eq!(q.y, !(p.y)); + + // Issue #1733 + result(p[true]); +} + +fn result(i: isize) { } diff --git a/tests/ui/binop/placement-syntax.rs b/tests/ui/binop/placement-syntax.rs new file mode 100644 index 000000000..4df96dedb --- /dev/null +++ b/tests/ui/binop/placement-syntax.rs @@ -0,0 +1,6 @@ +fn main() { + let x = -5; + if x<-1 { //~ ERROR unexpected token: `<-` + println!("ok"); + } +} diff --git a/tests/ui/binop/placement-syntax.stderr b/tests/ui/binop/placement-syntax.stderr new file mode 100644 index 000000000..3fdaf4cd0 --- /dev/null +++ b/tests/ui/binop/placement-syntax.stderr @@ -0,0 +1,13 @@ +error: unexpected token: `<-` + --> $DIR/placement-syntax.rs:3:9 + | +LL | if x<-1 { + | ^^ + | +help: if you meant to write a comparison against a negative value, add a space in between `<` and `-` + | +LL | if x< -1 { + | ~~~ + +error: aborting due to previous error + diff --git a/tests/ui/binop/shift-various-bad-types.rs b/tests/ui/binop/shift-various-bad-types.rs new file mode 100644 index 000000000..31224bbca --- /dev/null +++ b/tests/ui/binop/shift-various-bad-types.rs @@ -0,0 +1,31 @@ +// Test that we can do shifts by any integral type. + +struct Panolpy { + char: char, + str: &'static str, +} + +fn foo(p: &Panolpy) { + 22 >> p.char; + //~^ ERROR E0277 + + 22 >> p.str; + //~^ ERROR E0277 + + 22 >> p; + //~^ ERROR E0277 + + let x; + 22 >> x; // ambiguity error winds up being suppressed + + 22 >> 1; + // Integer literal types are OK + + // Type of the result follows the LHS, not the RHS: + let _: i32 = 22_i64 >> 1_i32; + //~^ ERROR mismatched types + //~| expected `i32`, found `i64` +} + +fn main() { +} diff --git a/tests/ui/binop/shift-various-bad-types.stderr b/tests/ui/binop/shift-various-bad-types.stderr new file mode 100644 index 000000000..38db66f86 --- /dev/null +++ b/tests/ui/binop/shift-various-bad-types.stderr @@ -0,0 +1,71 @@ +error[E0277]: no implementation for `{integer} >> char` + --> $DIR/shift-various-bad-types.rs:9:8 + | +LL | 22 >> p.char; + | ^^ no implementation for `{integer} >> char` + | + = help: the trait `Shr` is not implemented for `{integer}` + = help: the following other types implement trait `Shr`: + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + and 568 others + +error[E0277]: no implementation for `{integer} >> &str` + --> $DIR/shift-various-bad-types.rs:12:8 + | +LL | 22 >> p.str; + | ^^ no implementation for `{integer} >> &str` + | + = help: the trait `Shr<&str>` is not implemented for `{integer}` + = help: the following other types implement trait `Shr`: + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + and 568 others + +error[E0277]: no implementation for `{integer} >> &Panolpy` + --> $DIR/shift-various-bad-types.rs:15:8 + | +LL | 22 >> p; + | ^^ no implementation for `{integer} >> &Panolpy` + | + = help: the trait `Shr<&Panolpy>` is not implemented for `{integer}` + = help: the following other types implement trait `Shr`: + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + <&'a i128 as Shr> + and 568 others + +error[E0308]: mismatched types + --> $DIR/shift-various-bad-types.rs:25:18 + | +LL | let _: i32 = 22_i64 >> 1_i32; + | --- ^^^^^^^^^^^^^^^ expected `i32`, found `i64` + | | + | expected due to this + | +help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit + | +LL | let _: i32 = (22_i64 >> 1_i32).try_into().unwrap(); + | + +++++++++++++++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/structured-compare.rs b/tests/ui/binop/structured-compare.rs new file mode 100644 index 000000000..63d30c4da --- /dev/null +++ b/tests/ui/binop/structured-compare.rs @@ -0,0 +1,30 @@ +// run-pass + +#![allow(non_camel_case_types)] + + +#[derive(Copy, Clone, Debug)] +enum foo { large, small, } + +impl PartialEq for foo { + fn eq(&self, other: &foo) -> bool { + ((*self) as usize) == ((*other) as usize) + } + fn ne(&self, other: &foo) -> bool { !(*self).eq(other) } +} + +pub fn main() { + let a = (1, 2, 3); + let b = (1, 2, 3); + assert_eq!(a, b); + assert!((a != (1, 2, 4))); + assert!((a < (1, 2, 4))); + assert!((a <= (1, 2, 4))); + assert!(((1, 2, 4) > a)); + assert!(((1, 2, 4) >= a)); + let x = foo::large; + let y = foo::small; + assert!((x != y)); + assert_eq!(x, foo::large); + assert!((x != foo::small)); +} diff --git a/tests/ui/bitwise.rs b/tests/ui/bitwise.rs new file mode 100644 index 000000000..f79ff3c6e --- /dev/null +++ b/tests/ui/bitwise.rs @@ -0,0 +1,34 @@ +// run-pass + +#[cfg(any(target_pointer_width = "32"))] +fn target() { + assert_eq!(-1000isize as usize >> 3_usize, 536870787_usize); +} + +#[cfg(any(target_pointer_width = "64"))] +fn target() { + assert_eq!(-1000isize as usize >> 3_usize, 2305843009213693827_usize); +} + +fn general() { + let mut a: isize = 1; + let mut b: isize = 2; + a ^= b; + b ^= a; + a = a ^ b; + println!("{}", a); + println!("{}", b); + assert_eq!(b, 1); + assert_eq!(a, 2); + assert_eq!(!0xf0_isize & 0xff, 0xf); + assert_eq!(0xf0_isize | 0xf, 0xff); + assert_eq!(0xf_isize << 4, 0xf0); + assert_eq!(0xf0_isize >> 4, 0xf); + assert_eq!(-16 >> 2, -4); + assert_eq!(0b1010_1010_isize | 0b0101_0101, 0xff); +} + +pub fn main() { + general(); + target(); +} diff --git a/tests/ui/blind/blind-item-block-item-shadow.rs b/tests/ui/blind/blind-item-block-item-shadow.rs new file mode 100644 index 000000000..d90ef77e2 --- /dev/null +++ b/tests/ui/blind/blind-item-block-item-shadow.rs @@ -0,0 +1,9 @@ +mod foo { pub struct Bar; } + +fn main() { + { + struct Bar; + use foo::Bar; + //~^ ERROR the name `Bar` is defined multiple times + } +} diff --git a/tests/ui/blind/blind-item-block-item-shadow.stderr b/tests/ui/blind/blind-item-block-item-shadow.stderr new file mode 100644 index 000000000..68b3f4c1a --- /dev/null +++ b/tests/ui/blind/blind-item-block-item-shadow.stderr @@ -0,0 +1,17 @@ +error[E0255]: the name `Bar` is defined multiple times + --> $DIR/blind-item-block-item-shadow.rs:6:13 + | +LL | struct Bar; + | ----------- previous definition of the type `Bar` here +LL | use foo::Bar; + | ^^^^^^^^ `Bar` reimported here + | + = note: `Bar` must be defined only once in the type namespace of this block +help: you can use `as` to change the binding name of the import + | +LL | use foo::Bar as OtherBar; + | ~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/blind/blind-item-block-middle.rs b/tests/ui/blind/blind-item-block-middle.rs new file mode 100644 index 000000000..6cd3f3bd4 --- /dev/null +++ b/tests/ui/blind/blind-item-block-middle.rs @@ -0,0 +1,9 @@ +#![allow(non_camel_case_types)] + +mod foo { pub struct bar; } + +fn main() { + let bar = 5; + //~^ ERROR mismatched types + use foo::bar; +} diff --git a/tests/ui/blind/blind-item-block-middle.stderr b/tests/ui/blind/blind-item-block-middle.stderr new file mode 100644 index 000000000..eb64fea94 --- /dev/null +++ b/tests/ui/blind/blind-item-block-middle.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/blind-item-block-middle.rs:6:9 + | +LL | mod foo { pub struct bar; } + | -------------- unit struct defined here +... +LL | let bar = 5; + | ^^^ - this expression has type `{integer}` + | | + | expected integer, found struct `bar` + | `bar` is interpreted as a unit struct, not a new binding + | help: introduce a new binding instead: `other_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/blind/blind-item-item-shadow.rs b/tests/ui/blind/blind-item-item-shadow.rs new file mode 100644 index 000000000..82d07ea70 --- /dev/null +++ b/tests/ui/blind/blind-item-item-shadow.rs @@ -0,0 +1,7 @@ +mod foo { pub mod foo { } } + +use foo::foo; +//~^ ERROR the name `foo` is defined multiple times +//~| `foo` reimported here + +fn main() {} diff --git a/tests/ui/blind/blind-item-item-shadow.stderr b/tests/ui/blind/blind-item-item-shadow.stderr new file mode 100644 index 000000000..7f9e80089 --- /dev/null +++ b/tests/ui/blind/blind-item-item-shadow.stderr @@ -0,0 +1,18 @@ +error[E0255]: the name `foo` is defined multiple times + --> $DIR/blind-item-item-shadow.rs:3:5 + | +LL | mod foo { pub mod foo { } } + | ------- previous definition of the module `foo` here +LL | +LL | use foo::foo; + | ^^^^^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::foo as other_foo; + | ~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/block-result/block-must-not-have-result-do.rs b/tests/ui/block-result/block-must-not-have-result-do.rs new file mode 100644 index 000000000..4fdb69778 --- /dev/null +++ b/tests/ui/block-result/block-must-not-have-result-do.rs @@ -0,0 +1,5 @@ +fn main() { + loop { + true //~ ERROR mismatched types + } +} diff --git a/tests/ui/block-result/block-must-not-have-result-do.stderr b/tests/ui/block-result/block-must-not-have-result-do.stderr new file mode 100644 index 000000000..914886f81 --- /dev/null +++ b/tests/ui/block-result/block-must-not-have-result-do.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-do.rs:3:9 + | +LL | true + | ^^^^ expected `()`, found `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/block-must-not-have-result-res.rs b/tests/ui/block-result/block-must-not-have-result-res.rs new file mode 100644 index 000000000..7e86274a1 --- /dev/null +++ b/tests/ui/block-result/block-must-not-have-result-res.rs @@ -0,0 +1,10 @@ +struct R; + +impl Drop for R { + fn drop(&mut self) { + true //~ ERROR mismatched types + } +} + +fn main() { +} diff --git a/tests/ui/block-result/block-must-not-have-result-res.stderr b/tests/ui/block-result/block-must-not-have-result-res.stderr new file mode 100644 index 000000000..0080d06dd --- /dev/null +++ b/tests/ui/block-result/block-must-not-have-result-res.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-res.rs:5:9 + | +LL | fn drop(&mut self) { + | - expected `()` because of default return type +LL | true + | ^^^^ expected `()`, found `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/block-must-not-have-result-while.rs b/tests/ui/block-result/block-must-not-have-result-while.rs new file mode 100644 index 000000000..418059bf2 --- /dev/null +++ b/tests/ui/block-result/block-must-not-have-result-while.rs @@ -0,0 +1,6 @@ +fn main() { + while true { //~ WARN denote infinite loops with + true //~ ERROR mismatched types + //~| expected `()`, found `bool` + } +} diff --git a/tests/ui/block-result/block-must-not-have-result-while.stderr b/tests/ui/block-result/block-must-not-have-result-while.stderr new file mode 100644 index 000000000..7f96aa289 --- /dev/null +++ b/tests/ui/block-result/block-must-not-have-result-while.stderr @@ -0,0 +1,21 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/block-must-not-have-result-while.rs:2:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-while.rs:3:9 + | +LL | / while true { +LL | | true + | | ^^^^ expected `()`, found `bool` +LL | | +LL | | } + | |_____- expected this to be `()` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/consider-removing-last-semi.fixed b/tests/ui/block-result/consider-removing-last-semi.fixed new file mode 100644 index 000000000..36a769fe5 --- /dev/null +++ b/tests/ui/block-result/consider-removing-last-semi.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +pub fn f() -> String { //~ ERROR mismatched types + 0u8; + "bla".to_string() +} + +pub fn g() -> String { //~ ERROR mismatched types + "this won't work".to_string(); + "removeme".to_string() +} + +pub fn macro_tests() -> u32 { //~ ERROR mismatched types + macro_rules! mac { + () => (1); + } + mac!() +} + +fn main() {} diff --git a/tests/ui/block-result/consider-removing-last-semi.rs b/tests/ui/block-result/consider-removing-last-semi.rs new file mode 100644 index 000000000..b9a731489 --- /dev/null +++ b/tests/ui/block-result/consider-removing-last-semi.rs @@ -0,0 +1,20 @@ +// run-rustfix + +pub fn f() -> String { //~ ERROR mismatched types + 0u8; + "bla".to_string(); +} + +pub fn g() -> String { //~ ERROR mismatched types + "this won't work".to_string(); + "removeme".to_string(); +} + +pub fn macro_tests() -> u32 { //~ ERROR mismatched types + macro_rules! mac { + () => (1); + } + mac!(); +} + +fn main() {} diff --git a/tests/ui/block-result/consider-removing-last-semi.stderr b/tests/ui/block-result/consider-removing-last-semi.stderr new file mode 100644 index 000000000..9be0367ae --- /dev/null +++ b/tests/ui/block-result/consider-removing-last-semi.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:3:15 + | +LL | pub fn f() -> String { + | - ^^^^^^ expected struct `String`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | 0u8; +LL | "bla".to_string(); + | - help: remove this semicolon to return this value + +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:8:15 + | +LL | pub fn g() -> String { + | - ^^^^^^ expected struct `String`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | "this won't work".to_string(); +LL | "removeme".to_string(); + | - help: remove this semicolon to return this value + +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:13:25 + | +LL | pub fn macro_tests() -> u32 { + | ----------- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +... +LL | mac!(); + | - help: remove this semicolon to return this value + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-11714.rs b/tests/ui/block-result/issue-11714.rs new file mode 100644 index 000000000..3dda7e801 --- /dev/null +++ b/tests/ui/block-result/issue-11714.rs @@ -0,0 +1,7 @@ +fn blah() -> i32 { //~ ERROR mismatched types + 1 + + ; +} + +fn main() { } diff --git a/tests/ui/block-result/issue-11714.stderr b/tests/ui/block-result/issue-11714.stderr new file mode 100644 index 000000000..42fb3d3d4 --- /dev/null +++ b/tests/ui/block-result/issue-11714.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-11714.rs:1:14 + | +LL | fn blah() -> i32 { + | ---- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +... +LL | ; + | - help: remove this semicolon to return this value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-13428.rs b/tests/ui/block-result/issue-13428.rs new file mode 100644 index 000000000..ac8596435 --- /dev/null +++ b/tests/ui/block-result/issue-13428.rs @@ -0,0 +1,16 @@ +// Regression test for #13428 + +fn foo() -> String { //~ ERROR mismatched types + format!("Hello {}", + "world") + // Put the trailing semicolon on its own line to test that the + // note message gets the offending semicolon exactly + ; +} + +fn bar() -> String { //~ ERROR mismatched types + "foobar".to_string() + ; +} + +pub fn main() {} diff --git a/tests/ui/block-result/issue-13428.stderr b/tests/ui/block-result/issue-13428.stderr new file mode 100644 index 000000000..2b386d10c --- /dev/null +++ b/tests/ui/block-result/issue-13428.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:3:13 + | +LL | fn foo() -> String { + | --- ^^^^^^ expected struct `String`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:11:13 + | +LL | fn bar() -> String { + | --- ^^^^^^ expected struct `String`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | "foobar".to_string() +LL | ; + | - help: remove this semicolon to return this value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-13624.rs b/tests/ui/block-result/issue-13624.rs new file mode 100644 index 000000000..4d2844cc5 --- /dev/null +++ b/tests/ui/block-result/issue-13624.rs @@ -0,0 +1,29 @@ +mod a { + pub enum Enum { + EnumStructVariant { x: u8, y: u8, z: u8 } + } + + pub fn get_enum_struct_variant() -> () { + Enum::EnumStructVariant { x: 1, y: 2, z: 3 } + //~^ ERROR mismatched types + //~| expected `()`, found enum `Enum` + } +} + +mod b { + mod test { + use a; + + fn test_enum_struct_variant() { + let enum_struct_variant = ::a::get_enum_struct_variant(); + match enum_struct_variant { + a::Enum::EnumStructVariant { x, y, z } => { + //~^ ERROR mismatched types + //~| expected `()`, found enum `Enum` + } + } + } + } +} + +fn main() {} diff --git a/tests/ui/block-result/issue-13624.stderr b/tests/ui/block-result/issue-13624.stderr new file mode 100644 index 000000000..13070b4e8 --- /dev/null +++ b/tests/ui/block-result/issue-13624.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:7:5 + | +LL | pub fn get_enum_struct_variant() -> () { + | -- expected `()` because of return type +LL | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Enum` + +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:20:9 + | +LL | match enum_struct_variant { + | ------------------- this expression has type `()` +LL | a::Enum::EnumStructVariant { x, y, z } => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Enum` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-20862.rs b/tests/ui/block-result/issue-20862.rs new file mode 100644 index 000000000..e435fd7ae --- /dev/null +++ b/tests/ui/block-result/issue-20862.rs @@ -0,0 +1,9 @@ +fn foo(x: i32) { + |y| x + y +//~^ ERROR: mismatched types +} + +fn main() { + let x = foo(5)(2); +//~^ ERROR: expected function, found `()` +} diff --git a/tests/ui/block-result/issue-20862.stderr b/tests/ui/block-result/issue-20862.stderr new file mode 100644 index 000000000..37bad64c5 --- /dev/null +++ b/tests/ui/block-result/issue-20862.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-20862.rs:2:5 + | +LL | fn foo(x: i32) { + | - help: a return type might be missing here: `-> _` +LL | |y| x + y + | ^^^^^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/issue-20862.rs:2:5: 2:8]` + +error[E0618]: expected function, found `()` + --> $DIR/issue-20862.rs:7:13 + | +LL | fn foo(x: i32) { + | -------------- `foo` defined here returns `()` +... +LL | let x = foo(5)(2); + | ^^^^^^--- + | | + | call expression requires function + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0618. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/issue-22645.rs b/tests/ui/block-result/issue-22645.rs new file mode 100644 index 000000000..5f7fb8dd3 --- /dev/null +++ b/tests/ui/block-result/issue-22645.rs @@ -0,0 +1,17 @@ +use std::ops::Add; + +trait Scalar {} +impl Scalar for f64 {} + +struct Bob; + +impl Add for Bob { + type Output = Bob; + fn add(self, rhs : RHS) -> Bob { Bob } +} + +fn main() { + let b = Bob + 3.5; + b + 3 //~ ERROR E0277 + //~^ ERROR: mismatched types +} diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr new file mode 100644 index 000000000..24341c0f5 --- /dev/null +++ b/tests/ui/block-result/issue-22645.stderr @@ -0,0 +1,28 @@ +error[E0277]: the trait bound `{integer}: Scalar` is not satisfied + --> $DIR/issue-22645.rs:15:5 + | +LL | b + 3 + | ^ the trait `Scalar` is not implemented for `{integer}` + | + = help: the trait `Scalar` is implemented for `f64` +note: required for `Bob` to implement `Add<{integer}>` + --> $DIR/issue-22645.rs:8:19 + | +LL | impl Add for Bob { + | ------ ^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here + +error[E0308]: mismatched types + --> $DIR/issue-22645.rs:15:3 + | +LL | fn main() { + | - expected `()` because of default return type +LL | let b = Bob + 3.5; +LL | b + 3 + | ^^^^^ expected `()`, found struct `Bob` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/block-result/issue-3563.rs b/tests/ui/block-result/issue-3563.rs new file mode 100644 index 000000000..0b652a1f5 --- /dev/null +++ b/tests/ui/block-result/issue-3563.rs @@ -0,0 +1,7 @@ +trait A { + fn a(&self) { + || self.b() + //~^ ERROR no method named `b` found + } +} +fn main() {} diff --git a/tests/ui/block-result/issue-3563.stderr b/tests/ui/block-result/issue-3563.stderr new file mode 100644 index 000000000..be551f6e8 --- /dev/null +++ b/tests/ui/block-result/issue-3563.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `b` found for reference `&Self` in the current scope + --> $DIR/issue-3563.rs:3:17 + | +LL | || self.b() + | ^ help: there is a method with a similar name: `a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/block-result/issue-5500.rs b/tests/ui/block-result/issue-5500.rs new file mode 100644 index 000000000..577987a45 --- /dev/null +++ b/tests/ui/block-result/issue-5500.rs @@ -0,0 +1,7 @@ +fn main() { + &panic!() + //~^ ERROR mismatched types + //~| expected unit type `()` + //~| found reference `&_` + //~| expected `()`, found reference +} diff --git a/tests/ui/block-result/issue-5500.stderr b/tests/ui/block-result/issue-5500.stderr new file mode 100644 index 000000000..211a60528 --- /dev/null +++ b/tests/ui/block-result/issue-5500.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-5500.rs:2:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | &panic!() + | ^^^^^^^^^ expected `()`, found reference + | + = note: expected unit type `()` + found reference `&_` +help: consider removing the borrow + | +LL - &panic!() +LL + panic!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/block-result/unexpected-return-on-unit.rs b/tests/ui/block-result/unexpected-return-on-unit.rs new file mode 100644 index 000000000..2fcbfe8c0 --- /dev/null +++ b/tests/ui/block-result/unexpected-return-on-unit.rs @@ -0,0 +1,14 @@ +// Test that we do some basic error correction in the tokeniser (and don't spew +// too many bogus errors). + +fn foo() -> usize { + 3 +} + +fn bar() { + foo() //~ ERROR mismatched types +} + +fn main() { + bar() +} diff --git a/tests/ui/block-result/unexpected-return-on-unit.stderr b/tests/ui/block-result/unexpected-return-on-unit.stderr new file mode 100644 index 000000000..4acb955a8 --- /dev/null +++ b/tests/ui/block-result/unexpected-return-on-unit.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/unexpected-return-on-unit.rs:9:5 + | +LL | foo() + | ^^^^^ expected `()`, found `usize` + | +help: consider using a semicolon here + | +LL | foo(); + | + +help: try adding a return type + | +LL | fn bar() -> usize { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/bogus-tag.rs b/tests/ui/bogus-tag.rs new file mode 100644 index 000000000..c594385ee --- /dev/null +++ b/tests/ui/bogus-tag.rs @@ -0,0 +1,10 @@ +enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } + +fn main() { + let red: Color = Color::Rgb(255, 0, 0); + match red { + Color::Rgb(r, g, b) => { println!("rgb"); } + Color::Hsl(h, s, l) => { println!("hsl"); } + //~^ ERROR no variant + } +} diff --git a/tests/ui/bogus-tag.stderr b/tests/ui/bogus-tag.stderr new file mode 100644 index 000000000..899ff4261 --- /dev/null +++ b/tests/ui/bogus-tag.stderr @@ -0,0 +1,12 @@ +error[E0599]: no variant or associated item named `Hsl` found for enum `Color` in the current scope + --> $DIR/bogus-tag.rs:7:16 + | +LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } + | ---------- variant or associated item `Hsl` not found for this enum +... +LL | Color::Hsl(h, s, l) => { println!("hsl"); } + | ^^^ variant or associated item not found in `Color` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/borrow-by-val-method-receiver.rs b/tests/ui/borrow-by-val-method-receiver.rs new file mode 100644 index 000000000..465bef161 --- /dev/null +++ b/tests/ui/borrow-by-val-method-receiver.rs @@ -0,0 +1,14 @@ +// run-pass + +trait Foo { + fn foo(self); +} + +impl<'a> Foo for &'a [isize] { + fn foo(self) {} +} + +pub fn main() { + let items = vec![ 3, 5, 1, 2, 4 ]; + items.foo(); +} diff --git a/tests/ui/borrowck/access-mode-in-closures.rs b/tests/ui/borrowck/access-mode-in-closures.rs new file mode 100644 index 000000000..9bd90e70a --- /dev/null +++ b/tests/ui/borrowck/access-mode-in-closures.rs @@ -0,0 +1,10 @@ +struct S(Vec); + +fn unpack(_unpack: F) where F: FnOnce(&S) -> Vec {} + +fn main() { + let _foo = unpack(|s| { + // Test that `s` is moved here. + match *s { S(v) => v } //~ ERROR cannot move out + }); +} diff --git a/tests/ui/borrowck/access-mode-in-closures.stderr b/tests/ui/borrowck/access-mode-in-closures.stderr new file mode 100644 index 000000000..abee72ba8 --- /dev/null +++ b/tests/ui/borrowck/access-mode-in-closures.stderr @@ -0,0 +1,18 @@ +error[E0507]: cannot move out of `s` which is behind a shared reference + --> $DIR/access-mode-in-closures.rs:8:15 + | +LL | match *s { S(v) => v } + | ^^ - + | | + | data moved here + | move occurs because `v` has type `Vec`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *s { S(v) => v } +LL + match s { S(v) => v } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/anonymous-region-in-apit.rs b/tests/ui/borrowck/anonymous-region-in-apit.rs new file mode 100644 index 000000000..7799a7cb1 --- /dev/null +++ b/tests/ui/borrowck/anonymous-region-in-apit.rs @@ -0,0 +1,12 @@ +#![feature(anonymous_lifetime_in_impl_trait)] + +trait Foo { + fn bar(self, baz: T); +} + +fn qux(foo: impl Foo<&str>) { + |baz: &str| foo.bar(baz); + //~^ ERROR borrowed data escapes outside of closure +} + +fn main() {} diff --git a/tests/ui/borrowck/anonymous-region-in-apit.stderr b/tests/ui/borrowck/anonymous-region-in-apit.stderr new file mode 100644 index 000000000..9e100f8ac --- /dev/null +++ b/tests/ui/borrowck/anonymous-region-in-apit.stderr @@ -0,0 +1,16 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/anonymous-region-in-apit.rs:8:17 + | +LL | fn qux(foo: impl Foo<&str>) { + | --- lifetime `'2` appears in the type of `foo` +LL | |baz: &str| foo.bar(baz); + | --- - ^^^^^^^^^^^^ + | | | | + | | | `baz` escapes the closure body here + | | | argument requires that `'1` must outlive `'2` + | | let's call the lifetime of this reference `'1` + | `baz` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/assign-never-type.rs b/tests/ui/borrowck/assign-never-type.rs new file mode 100644 index 000000000..4f30ea146 --- /dev/null +++ b/tests/ui/borrowck/assign-never-type.rs @@ -0,0 +1,14 @@ +// Regression test for issue 62165 + +// check-pass + +#![feature(never_type)] + +pub fn main() { + loop { + match None { + None => return, + Some(val) => val, + }; + }; +} diff --git a/tests/ui/borrowck/assign_mutable_fields.rs b/tests/ui/borrowck/assign_mutable_fields.rs new file mode 100644 index 000000000..b60726d0c --- /dev/null +++ b/tests/ui/borrowck/assign_mutable_fields.rs @@ -0,0 +1,22 @@ +// Currently, we do permit you to assign to individual fields of an +// uninitialized var. +// We hope to fix this at some point. +// +// FIXME(#54987) + +fn assign_both_fields_and_use() { + let mut x: (u32, u32); + x.0 = 1; //~ ERROR + x.1 = 22; + drop(x.0); + drop(x.1); +} + +fn assign_both_fields_the_use_var() { + let mut x: (u32, u32); + x.0 = 1; //~ ERROR + x.1 = 22; + drop(x); +} + +fn main() { } diff --git a/tests/ui/borrowck/assign_mutable_fields.stderr b/tests/ui/borrowck/assign_mutable_fields.stderr new file mode 100644 index 000000000..1ed92865d --- /dev/null +++ b/tests/ui/borrowck/assign_mutable_fields.stderr @@ -0,0 +1,23 @@ +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/assign_mutable_fields.rs:9:5 + | +LL | let mut x: (u32, u32); + | ----- binding declared here but left uninitialized +LL | x.0 = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/assign_mutable_fields.rs:17:5 + | +LL | let mut x: (u32, u32); + | ----- binding declared here but left uninitialized +LL | x.0 = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/async-reference-generality.rs b/tests/ui/borrowck/async-reference-generality.rs new file mode 100644 index 000000000..487d1ac81 --- /dev/null +++ b/tests/ui/borrowck/async-reference-generality.rs @@ -0,0 +1,35 @@ +// check-fail +// known-bug: #99492 +// edition: 2021 + +use std::marker::PhantomData; + +pub struct Struct(PhantomData ::Item>) +where + Self: It; + +impl It for Struct +where + I: It, +{ + type Item = (); +} + +pub trait It { + type Item; +} + +fn f() -> impl Send { + async { + let _x = Struct::, _>(PhantomData); + async {}.await; + } +} + +pub struct Empty(PhantomData T>); + +impl It for Empty { + type Item = T; +} + +fn main() {} diff --git a/tests/ui/borrowck/async-reference-generality.stderr b/tests/ui/borrowck/async-reference-generality.stderr new file mode 100644 index 000000000..af720ad29 --- /dev/null +++ b/tests/ui/borrowck/async-reference-generality.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/async-reference-generality.rs:23:5 + | +LL | / async { +LL | | let _x = Struct::, _>(PhantomData); +LL | | async {}.await; +LL | | } + | |_____^ one type is more general than the other + | + = note: expected reference `&()` + found reference `&()` + +error[E0308]: mismatched types + --> $DIR/async-reference-generality.rs:23:5 + | +LL | / async { +LL | | let _x = Struct::, _>(PhantomData); +LL | | async {}.await; +LL | | } + | |_____^ one type is more general than the other + | + = note: expected reference `&()` + found reference `&()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs new file mode 100644 index 000000000..baf31bd89 --- /dev/null +++ b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs @@ -0,0 +1,220 @@ +// Tests using a combination of pattern features has the expected borrow checking behavior +#![feature(box_patterns)] + +enum Test { + Foo, + Bar, + _Baz, +} + +// bindings_after_at + slice_patterns + +fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) { + match x { + a @ [.., _] => (), + _ => (), + }; + + &x; + //~^ ERROR borrow of moved value +} + +fn bindings_after_at_slice_patterns_borrows_binding_mut(mut x: [String; 4]) { + let r = match x { + ref mut foo @ [.., _] => Some(foo), + _ => None, + }; + + &x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_borrows_slice_mut1(mut x: [String; 4]) { + let r = match x { + ref foo @ [.., ref mut bar] => (), + //~^ ERROR cannot borrow + _ => (), + }; + + drop(r); +} + +fn bindings_after_at_slice_patterns_borrows_slice_mut2(mut x: [String; 4]) { + let r = match x { + [ref foo @ .., ref bar] => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_borrows_both(mut x: [String; 4]) { + let r = match x { + ref foo @ [.., ref bar] => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + or_patterns + +fn bindings_after_at_or_patterns_move(x: Option) { + match x { + foo @ Some(Test::Foo | Test::Bar) => (), + _ => (), + } + + &x; + //~^ ERROR borrow of moved value +} + +fn bindings_after_at_or_patterns_borrows(mut x: Option) { + let r = match x { + ref foo @ Some(Test::Foo | Test::Bar) => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_or_patterns_borrows_mut(mut x: Option) { + let r = match x { + ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo), + _ => None, + }; + + &x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + box_patterns + +fn bindings_after_at_box_patterns_borrows_both(mut x: Option>) { + let r = match x { + ref foo @ Some(box ref s) => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_box_patterns_borrows_mut(mut x: Option>) { + match x { + ref foo @ Some(box ref mut s) => (), + //~^ ERROR cannot borrow + _ => (), + }; +} + +// bindings_after_at + slice_patterns + or_patterns + +fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option; 4]) { + match x { + a @ [.., Some(Test::Foo | Test::Bar)] => (), + _ => (), + }; + + &x; + //~^ ERROR borrow of moved value +} + +fn bindings_after_at_slice_patterns_or_patterns_borrows_binding(mut x: [Option; 4]) { + let r = match x { + ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_or_patterns_borrows_slice(mut x: [Option; 4]) { + let r = match x { + ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + slice_patterns + box_patterns + +fn bindings_after_at_slice_patterns_box_patterns_borrows(mut x: [Option>; 4]) { + let r = match x { + [_, ref a @ Some(box ref b), ..] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + slice_patterns + or_patterns + box_patterns + +fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows( + mut x: [Option>; 4] +) { + let r = match x { + [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_mut( + mut x: [Option>; 4] +) { + let r = match x { + [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + _ => None, + }; + + &x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_binding( + mut x: [Option>; 4] +) { + let r = match x { + ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn main() {} diff --git a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr new file mode 100644 index 000000000..50eee1049 --- /dev/null +++ b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr @@ -0,0 +1,217 @@ +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:36:9 + | +LL | ref foo @ [.., ref mut bar] => (), + | -------^^^^^^^^-----------^ + | | | + | | mutable borrow, by `bar`, occurs here + | immutable borrow, by `foo`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9 + | +LL | ref foo @ Some(box ref mut s) => (), + | -------^^^^^^^^^^^^---------^ + | | | + | | mutable borrow, by `s`, occurs here + | immutable borrow, by `foo`, occurs here + +error[E0382]: borrow of moved value: `x` + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:18:5 + | +LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) { + | - move occurs because `x` has type `[String; 4]`, which does not implement the `Copy` trait +LL | match x { +LL | a @ [.., _] => (), + | - value moved here +... +LL | &x; + | ^^ value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ [.., _] => (), + | +++ + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:28:5 + | +LL | ref mut foo @ [.., _] => Some(foo), + | ----------- mutable borrow occurs here +... +LL | &x; + | ^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:50:5 + | +LL | [ref foo @ .., ref bar] => Some(foo), + | ------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:62:5 + | +LL | ref foo @ [.., ref bar] => Some(foo), + | ------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:76:5 + | +LL | fn bindings_after_at_or_patterns_move(x: Option) { + | - move occurs because `x` has type `Option`, which does not implement the `Copy` trait +LL | match x { +LL | foo @ Some(Test::Foo | Test::Bar) => (), + | --- value moved here +... +LL | &x; + | ^^ value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref foo @ Some(Test::Foo | Test::Bar) => (), + | +++ + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:86:5 + | +LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo), + | ------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:98:5 + | +LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo), + | ----------- mutable borrow occurs here +... +LL | &x; + | ^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:112:5 + | +LL | ref foo @ Some(box ref s) => Some(foo), + | ------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:134:5 + | +LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option; 4]) { + | - move occurs because `x` has type `[Option; 4]`, which does not implement the `Copy` trait +LL | match x { +LL | a @ [.., Some(Test::Foo | Test::Bar)] => (), + | - value moved here +... +LL | &x; + | ^^ value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ [.., Some(Test::Foo | Test::Bar)] => (), + | +++ + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:144:5 + | +LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a), + | ----- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:156:5 + | +LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b), + | ----- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:170:5 + | +LL | [_, ref a @ Some(box ref b), ..] => Some(a), + | ----- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:186:5 + | +LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + | ----- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:200:5 + | +LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + | --------- mutable borrow occurs here +... +LL | &x; + | ^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:214:5 + | +LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + | ----- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs b/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs new file mode 100644 index 000000000..57198cb95 --- /dev/null +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs @@ -0,0 +1,14 @@ +#![feature(unboxed_closures)] + +// Tests that we can't assign to or mutably borrow upvars from `Fn` +// closures (issue #17780) + +fn main() {} + +fn bar() -> impl Fn() -> usize { + let mut x = 0; + move || { + x += 1; //~ ERROR cannot assign + x + } +} diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr b/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr new file mode 100644 index 000000000..6235e0db0 --- /dev/null +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation-impl-trait.rs:11:9 + | +LL | fn bar() -> impl Fn() -> usize { + | --- ------------------ change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | move || { + | ------- in this closure +LL | x += 1; + | ^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation.rs b/tests/ui/borrowck/borrow-immutable-upvar-mutation.rs new file mode 100644 index 000000000..a3350024e --- /dev/null +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation.rs @@ -0,0 +1,56 @@ +#![feature(unboxed_closures, tuple_trait)] + +// Tests that we can't assign to or mutably borrow upvars from `Fn` +// closures (issue #17780) + +fn set(x: &mut usize) { + *x = 5; +} + +fn to_fn>(f: F) -> F { + f +} +fn to_fn_mut>(f: F) -> F { + f +} + +fn main() { + // By-ref captures + { + let mut x = 0; + let _f = to_fn(|| x = 42); //~ ERROR cannot assign + + let mut y = 0; + let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow + + let mut z = 0; + let _h = to_fn_mut(|| { + set(&mut z); + to_fn(|| z = 42); //~ ERROR cannot assign + }); + } + + // By-value captures + { + let mut x = 0; + let _f = to_fn(move || x = 42); //~ ERROR cannot assign + + let mut y = 0; + let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow + + let mut z = 0; + let _h = to_fn_mut(move || { + set(&mut z); + to_fn(move || z = 42); + //~^ ERROR cannot assign + }); + } +} + +fn foo() -> Box usize> { + let mut x = 0; + Box::new(move || { + x += 1; //~ ERROR cannot assign + x + }) +} diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr new file mode 100644 index 000000000..a0eaf1f16 --- /dev/null +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -0,0 +1,87 @@ +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:21:27 + | +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` +... +LL | let _f = to_fn(|| x = 42); + | ----- -- ^^^^^^ cannot assign + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:24:31 + | +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` +... +LL | let _g = to_fn(|| set(&mut y)); + | ----- -- ^^^^^^ cannot borrow as mutable + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:29:22 + | +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` +... +LL | to_fn(|| z = 42); + | ----- -- ^^^^^^ cannot assign + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:36:32 + | +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` +... +LL | let _f = to_fn(move || x = 42); + | ----- ------- ^^^^^^ cannot assign + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:39:36 + | +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` +... +LL | let _g = to_fn(move || set(&mut y)); + | ----- ------- ^^^^^^ cannot borrow as mutable + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:44:27 + | +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` +... +LL | to_fn(move || z = 42); + | ----- ------- ^^^^^^ cannot assign + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:53:9 + | +LL | fn foo() -> Box usize> { + | --- ---------------------- change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | Box::new(move || { + | ------- in this closure +LL | x += 1; + | ^^^^^^ cannot assign + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs b/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs new file mode 100644 index 000000000..f25fd7f66 --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-borrowed.rs @@ -0,0 +1,22 @@ +#![feature(raw_ref_op)] + +fn address_of_shared() { + let mut x = 0; + let y = &x; + + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn address_of_mutably_borrowed() { + let mut x = 0; + let y = &mut x; + + let p = &raw const x; //~ ERROR cannot borrow + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn main() {} diff --git a/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr new file mode 100644 index 000000000..6f7b7e080 --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-borrowed.stderr @@ -0,0 +1,40 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrow-raw-address-of-borrowed.rs:7:13 + | +LL | let y = &x; + | -- immutable borrow occurs here +LL | +LL | let q = &raw mut x; + | ^^^^^^^^^^ mutable borrow occurs here +LL | +LL | drop(y); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrow-raw-address-of-borrowed.rs:16:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | +LL | let p = &raw const x; + | ^^^^^^^^^^^^ immutable borrow occurs here +... +LL | drop(y); + | - mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrow-raw-address-of-borrowed.rs:17:13 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +... +LL | let q = &raw mut x; + | ^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | drop(y); + | - first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs new file mode 100644 index 000000000..e381384fe --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + let y = &mut 0; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + let y = &mut 0 as *mut i32; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs new file mode 100644 index 000000000..712873528 --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.rs @@ -0,0 +1,17 @@ +// Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`. + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +fn main() {} diff --git a/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr new file mode 100644 index 000000000..4cc1d821d --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 + | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let x = &mut 0; + | ~~~~~~ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer + --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 + | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | let x = &mut 0 as *const i32; + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs new file mode 100644 index 000000000..e1cf2dc53 --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability-ok.rs @@ -0,0 +1,44 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let mut x = 0; + let y = &raw mut x; +} + +fn mutable_address_of_closure() { + let mut x = 0; + let mut f = || { + let y = &raw mut x; + }; + f(); +} + +fn const_address_of_closure() { + let x = 0; + let f = || { + let y = &raw const x; + }; + f(); +} + +fn make_fn(f: F) -> F { f } + +fn const_address_of_fn_closure() { + let x = 0; + let f = make_fn(|| { + let y = &raw const x; + }); + f(); +} + +fn const_address_of_fn_closure_move() { + let x = 0; + let f = make_fn(move || { + let y = &raw const x; + }); + f(); +} + +fn main() {} diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability.rs b/tests/ui/borrowck/borrow-raw-address-of-mutability.rs new file mode 100644 index 000000000..320c54b80 --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability.rs @@ -0,0 +1,42 @@ +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let x = 0; + let y = &raw mut x; //~ ERROR cannot borrow +} + +fn mutable_address_of_closure() { + let x = 0; + let mut f = || { + let y = &raw mut x; //~ ERROR cannot borrow + }; + f(); +} + +fn mutable_address_of_imm_closure() { + let mut x = 0; + let f = || { + let y = &raw mut x; + }; + f(); //~ ERROR cannot borrow +} + +fn make_fn(f: F) -> F { f } + +fn mutable_address_of_fn_closure() { + let mut x = 0; + let f = make_fn(|| { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn mutable_address_of_fn_closure_move() { + let mut x = 0; + let f = make_fn(move || { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn main() {} diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr new file mode 100644 index 000000000..a77482091 --- /dev/null +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -0,0 +1,63 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:5:13 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 0; + | +++ + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:11:17 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let mut f = || { +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:21:5 + | +LL | let y = &raw mut x; + | - calling `f` requires mutable binding due to mutable borrow of `x` +LL | }; +LL | f(); + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = || { + | +++ + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:29:17 + | +LL | fn make_fn(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | let f = make_fn(|| { + | ------- -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:37:17 + | +LL | fn make_fn(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | let f = make_fn(move || { + | ------- ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrow-tuple-fields.rs b/tests/ui/borrowck/borrow-tuple-fields.rs new file mode 100644 index 000000000..c628fa49e --- /dev/null +++ b/tests/ui/borrowck/borrow-tuple-fields.rs @@ -0,0 +1,43 @@ +struct Foo(Box, isize); + +struct Bar(isize, isize); + + + + + +fn main() { + let x: (Box<_>, _) = (Box::new(1), 2); + let r = &x.0; + let y = x; //~ ERROR cannot move out of `x` because it is borrowed + + r.use_ref(); + + let mut x = (1, 2); + let a = &x.0; + let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as + a.use_ref(); + + let mut x = (1, 2); + let a = &mut x.0; + let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time + a.use_ref(); + + let x = Foo(Box::new(1), 2); + let r = &x.0; + let y = x; //~ ERROR cannot move out of `x` because it is borrowed + r.use_ref(); + + let mut x = Bar(1, 2); + let a = &x.0; + let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as + a.use_ref(); + + let mut x = Bar(1, 2); + let a = &mut x.0; + let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time + a.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrow-tuple-fields.stderr b/tests/ui/borrowck/borrow-tuple-fields.stderr new file mode 100644 index 000000000..befa751a6 --- /dev/null +++ b/tests/ui/borrowck/borrow-tuple-fields.stderr @@ -0,0 +1,65 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/borrow-tuple-fields.rs:12:13 + | +LL | let r = &x.0; + | ---- borrow of `x.0` occurs here +LL | let y = x; + | ^ move out of `x` occurs here +LL | +LL | r.use_ref(); + | ----------- borrow later used here + +error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable + --> $DIR/borrow-tuple-fields.rs:18:13 + | +LL | let a = &x.0; + | ---- immutable borrow occurs here +LL | let b = &mut x.0; + | ^^^^^^^^ mutable borrow occurs here +LL | a.use_ref(); + | ----------- immutable borrow later used here + +error[E0499]: cannot borrow `x.0` as mutable more than once at a time + --> $DIR/borrow-tuple-fields.rs:23:13 + | +LL | let a = &mut x.0; + | -------- first mutable borrow occurs here +LL | let b = &mut x.0; + | ^^^^^^^^ second mutable borrow occurs here +LL | a.use_ref(); + | ----------- first borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/borrow-tuple-fields.rs:28:13 + | +LL | let r = &x.0; + | ---- borrow of `x.0` occurs here +LL | let y = x; + | ^ move out of `x` occurs here +LL | r.use_ref(); + | ----------- borrow later used here + +error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable + --> $DIR/borrow-tuple-fields.rs:33:13 + | +LL | let a = &x.0; + | ---- immutable borrow occurs here +LL | let b = &mut x.0; + | ^^^^^^^^ mutable borrow occurs here +LL | a.use_ref(); + | ----------- immutable borrow later used here + +error[E0499]: cannot borrow `x.0` as mutable more than once at a time + --> $DIR/borrow-tuple-fields.rs:38:13 + | +LL | let a = &mut x.0; + | -------- first mutable borrow occurs here +LL | let b = &mut x.0; + | ^^^^^^^^ second mutable borrow occurs here +LL | a.use_mut(); + | ----------- first borrow later used here + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0499, E0502, E0505. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-access-permissions.rs b/tests/ui/borrowck/borrowck-access-permissions.rs new file mode 100644 index 000000000..469ad508b --- /dev/null +++ b/tests/ui/borrowck/borrowck-access-permissions.rs @@ -0,0 +1,50 @@ +static static_x : i32 = 1; +static mut static_x_mut : i32 = 1; + +fn main() { + let x = 1; + let mut x_mut = 1; + + { // borrow of local + let _y1 = &mut x; //~ ERROR [E0596] + let _y2 = &mut x_mut; // No error + } + + { // borrow of static + let _y1 = &mut static_x; //~ ERROR [E0596] + unsafe { let _y2 = &mut static_x_mut; } // No error + } + + { // borrow of deref to box + let box_x = Box::new(1); + let mut box_x_mut = Box::new(1); + + let _y1 = &mut *box_x; //~ ERROR [E0596] + let _y2 = &mut *box_x_mut; // No error + } + + { // borrow of deref to reference + let ref_x = &x; + let ref_x_mut = &mut x_mut; + + let _y1 = &mut *ref_x; //~ ERROR [E0596] + let _y2 = &mut *ref_x_mut; // No error + } + + { // borrow of deref to pointer + let ptr_x : *const _ = &x; + let ptr_mut_x : *mut _ = &mut x_mut; + + unsafe { + let _y1 = &mut *ptr_x; //~ ERROR [E0596] + let _y2 = &mut *ptr_mut_x; // No error + } + } + + { // borrowing mutably through an immutable reference + struct Foo<'a> { f: &'a mut i32, g: &'a i32 }; + let mut foo = Foo { f: &mut x_mut, g: &x }; + let foo_ref = &foo; + let _y = &mut *foo_ref.f; //~ ERROR [E0596] + } +} diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr new file mode 100644 index 000000000..26f3e2bbd --- /dev/null +++ b/tests/ui/borrowck/borrowck-access-permissions.stderr @@ -0,0 +1,64 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-access-permissions.rs:9:19 + | +LL | let _y1 = &mut x; + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 1; + | +++ + +error[E0596]: cannot borrow immutable static item `static_x` as mutable + --> $DIR/borrowck-access-permissions.rs:14:19 + | +LL | let _y1 = &mut static_x; + | ^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable + --> $DIR/borrowck-access-permissions.rs:22:19 + | +LL | let _y1 = &mut *box_x; + | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut box_x = Box::new(1); + | +++ + +error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-access-permissions.rs:30:19 + | +LL | let _y1 = &mut *ref_x; + | ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let ref_x = &mut x; + | ~~~~~~ + +error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer + --> $DIR/borrowck-access-permissions.rs:39:23 + | +LL | let _y1 = &mut *ptr_x; + | ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | let ptr_x : *const _ = &mut x; + | ~~~~~~ + +error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-access-permissions.rs:48:18 + | +LL | let _y = &mut *foo_ref.f; + | ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let foo_ref = &mut foo; + | ~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-and-init.rs b/tests/ui/borrowck/borrowck-and-init.rs new file mode 100644 index 000000000..eeb4f05d6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-and-init.rs @@ -0,0 +1,6 @@ +fn main() { + let i: isize; + + println!("{}", false && { i = 5; true }); + println!("{}", i); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-and-init.stderr b/tests/ui/borrowck/borrowck-and-init.stderr new file mode 100644 index 000000000..5abf07a31 --- /dev/null +++ b/tests/ui/borrowck/borrowck-and-init.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `i` is possibly-uninitialized + --> $DIR/borrowck-and-init.rs:5:20 + | +LL | let i: isize; + | - binding declared here but left uninitialized +LL | +LL | println!("{}", false && { i = 5; true }); + | ----- binding initialized here in some conditions +LL | println!("{}", i); + | ^ `i` used here but it is possibly-uninitialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-anon-fields-struct.rs b/tests/ui/borrowck/borrowck-anon-fields-struct.rs new file mode 100644 index 000000000..a05dfe62b --- /dev/null +++ b/tests/ui/borrowck/borrowck-anon-fields-struct.rs @@ -0,0 +1,37 @@ +// Tests that we are able to distinguish when loans borrow different +// anonymous fields of a tuple vs the same anonymous field. + +struct Y(usize, usize); + +fn distinct_variant() { + let mut y = Y(1, 2); + + let a = match y { + Y(ref mut a, _) => a + }; + + let b = match y { + Y(_, ref mut b) => b + }; + + *a += 1; + *b += 1; +} + +fn same_variant() { + let mut y = Y(1, 2); + + let a = match y { + Y(ref mut a, _) => a + }; + + let b = match y { + Y(ref mut b, _) => b //~ ERROR cannot borrow + }; + + *a += 1; + *b += 1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-anon-fields-struct.stderr b/tests/ui/borrowck/borrowck-anon-fields-struct.stderr new file mode 100644 index 000000000..7a959fb6e --- /dev/null +++ b/tests/ui/borrowck/borrowck-anon-fields-struct.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `y.0` as mutable more than once at a time + --> $DIR/borrowck-anon-fields-struct.rs:29:11 + | +LL | Y(ref mut a, _) => a + | --------- first mutable borrow occurs here +... +LL | Y(ref mut b, _) => b + | ^^^^^^^^^ second mutable borrow occurs here +... +LL | *a += 1; + | ------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-anon-fields-tuple.rs b/tests/ui/borrowck/borrowck-anon-fields-tuple.rs new file mode 100644 index 000000000..de2a8d832 --- /dev/null +++ b/tests/ui/borrowck/borrowck-anon-fields-tuple.rs @@ -0,0 +1,35 @@ +// Tests that we are able to distinguish when loans borrow different +// anonymous fields of a tuple vs the same anonymous field. + +fn distinct_variant() { + let mut y = (1, 2); + + let a = match y { + (ref mut a, _) => a + }; + + let b = match y { + (_, ref mut b) => b + }; + + *a += 1; + *b += 1; +} + +fn same_variant() { + let mut y = (1, 2); + + let a = match y { + (ref mut a, _) => a + }; + + let b = match y { + (ref mut b, _) => b //~ ERROR cannot borrow + }; + + *a += 1; + *b += 1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr b/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr new file mode 100644 index 000000000..88a8867f5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-anon-fields-tuple.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `y.0` as mutable more than once at a time + --> $DIR/borrowck-anon-fields-tuple.rs:27:10 + | +LL | (ref mut a, _) => a + | --------- first mutable borrow occurs here +... +LL | (ref mut b, _) => b + | ^^^^^^^^^ second mutable borrow occurs here +... +LL | *a += 1; + | ------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-anon-fields-variant.rs b/tests/ui/borrowck/borrowck-anon-fields-variant.rs new file mode 100644 index 000000000..6e63de913 --- /dev/null +++ b/tests/ui/borrowck/borrowck-anon-fields-variant.rs @@ -0,0 +1,46 @@ +enum Foo { + X, Y(usize, usize) +} + +fn distinct_variant() { + let mut y = Foo::Y(1, 2); + + let a = match y { + Foo::Y(ref mut a, _) => a, + Foo::X => panic!() + }; + + // While `a` and `b` are disjoint, borrowck doesn't know that `a` is not + // also used for the discriminant of `Foo`, which it would be if `a` was a + // reference. + let b = match y { + //~^ ERROR cannot use `y` + Foo::Y(_, ref mut b) => b, + Foo::X => panic!() + }; + + *a += 1; + *b += 1; +} + +fn same_variant() { + let mut y = Foo::Y(1, 2); + + let a = match y { + Foo::Y(ref mut a, _) => a, + Foo::X => panic!() + }; + + let b = match y { + //~^ ERROR cannot use `y` + Foo::Y(ref mut b, _) => b, + //~^ ERROR cannot borrow `y.0` as mutable + Foo::X => panic!() + }; + + *a += 1; + *b += 1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-anon-fields-variant.stderr b/tests/ui/borrowck/borrowck-anon-fields-variant.stderr new file mode 100644 index 000000000..98f6f00a7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-anon-fields-variant.stderr @@ -0,0 +1,40 @@ +error[E0503]: cannot use `y` because it was mutably borrowed + --> $DIR/borrowck-anon-fields-variant.rs:16:19 + | +LL | Foo::Y(ref mut a, _) => a, + | --------- borrow of `y.0` occurs here +... +LL | let b = match y { + | ^ use of borrowed `y.0` +... +LL | *a += 1; + | ------- borrow later used here + +error[E0503]: cannot use `y` because it was mutably borrowed + --> $DIR/borrowck-anon-fields-variant.rs:34:19 + | +LL | Foo::Y(ref mut a, _) => a, + | --------- borrow of `y.0` occurs here +... +LL | let b = match y { + | ^ use of borrowed `y.0` +... +LL | *a += 1; + | ------- borrow later used here + +error[E0499]: cannot borrow `y.0` as mutable more than once at a time + --> $DIR/borrowck-anon-fields-variant.rs:36:14 + | +LL | Foo::Y(ref mut a, _) => a, + | --------- first mutable borrow occurs here +... +LL | Foo::Y(ref mut b, _) => b, + | ^^^^^^^^^ second mutable borrow occurs here +... +LL | *a += 1; + | ------- first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-argument.rs b/tests/ui/borrowck/borrowck-argument.rs new file mode 100644 index 000000000..5d776d4fc --- /dev/null +++ b/tests/ui/borrowck/borrowck-argument.rs @@ -0,0 +1,34 @@ +#[derive(Copy, Clone)] +struct S; + +impl S { + fn mutate(&mut self) { + } +} + +fn func(arg: S) { + arg.mutate(); //~ ERROR: cannot borrow `arg` as mutable, as it is not declared as mutable +} + +impl S { + fn method(&self, arg: S) { + arg.mutate(); //~ ERROR: cannot borrow `arg` as mutable, as it is not declared as mutable + } +} + +trait T { + fn default(&self, arg: S) { + arg.mutate(); //~ ERROR: cannot borrow `arg` as mutable, as it is not declared as mutable + } +} + +impl T for S {} + +fn main() { + let s = S; + func(s); + s.method(s); + s.default(s); + (|arg: S| { arg.mutate() })(s); + //~^ ERROR: cannot borrow `arg` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/borrowck/borrowck-argument.stderr b/tests/ui/borrowck/borrowck-argument.stderr new file mode 100644 index 000000000..1c992dfcc --- /dev/null +++ b/tests/ui/borrowck/borrowck-argument.stderr @@ -0,0 +1,47 @@ +error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable + --> $DIR/borrowck-argument.rs:10:5 + | +LL | arg.mutate(); + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn func(mut arg: S) { + | +++ + +error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable + --> $DIR/borrowck-argument.rs:15:9 + | +LL | arg.mutate(); + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn method(&self, mut arg: S) { + | +++ + +error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable + --> $DIR/borrowck-argument.rs:21:9 + | +LL | arg.mutate(); + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn default(&self, mut arg: S) { + | +++ + +error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable + --> $DIR/borrowck-argument.rs:32:17 + | +LL | (|arg: S| { arg.mutate() })(s); + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | (|mut arg: S| { arg.mutate() })(s); + | +++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-assign-comp-idx.rs b/tests/ui/borrowck/borrowck-assign-comp-idx.rs new file mode 100644 index 000000000..f4dffeb8c --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-comp-idx.rs @@ -0,0 +1,39 @@ +struct Point { + x: isize, + y: isize, +} + +fn a() { + let mut p = vec![1]; + + // Create an immutable pointer into p's contents: + let q: &isize = &p[0]; + + p[0] = 5; //~ ERROR cannot borrow + + println!("{}", *q); +} + +fn borrow(_x: &[isize], _f: F) where F: FnOnce() {} + +fn b() { + // here we alias the mutable vector into an imm slice and try to + // modify the original: + + let mut p = vec![1]; + + borrow( + &p, + || p[0] = 5); //~ ERROR cannot borrow `p` as mutable +} + +fn c() { + // Legal because the scope of the borrow does not include the + // modification: + let mut p = vec![1]; + borrow(&p, ||{}); + p[0] = 5; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-assign-comp-idx.stderr b/tests/ui/borrowck/borrowck-assign-comp-idx.stderr new file mode 100644 index 000000000..b80174ae6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-comp-idx.stderr @@ -0,0 +1,27 @@ +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-assign-comp-idx.rs:12:5 + | +LL | let q: &isize = &p[0]; + | - immutable borrow occurs here +LL | +LL | p[0] = 5; + | ^ mutable borrow occurs here +LL | +LL | println!("{}", *q); + | -- immutable borrow later used here + +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-assign-comp-idx.rs:27:9 + | +LL | borrow( + | ------ immutable borrow later used by call +LL | &p, + | -- immutable borrow occurs here +LL | || p[0] = 5); + | ^^ - second borrow occurs due to use of `p` in closure + | | + | mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-assign-comp.rs b/tests/ui/borrowck/borrowck-assign-comp.rs new file mode 100644 index 000000000..98bb2d85a --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-comp.rs @@ -0,0 +1,36 @@ +struct Point { x: isize, y: isize } + +fn a() { + let mut p = Point {x: 3, y: 4}; + let q = &p; + + // This assignment is illegal because the field x is not + // inherently mutable; since `p` was made immutable, `p.x` is now + // immutable. Otherwise the type of &_q.x (&isize) would be wrong. + p.x = 5; //~ ERROR cannot assign to `p.x` because it is borrowed + q.x; +} + +fn c() { + // this is sort of the opposite. We take a loan to the interior of `p` + // and then try to overwrite `p` as a whole. + + let mut p = Point {x: 3, y: 4}; + let q = &p.y; + p = Point {x: 5, y: 7};//~ ERROR cannot assign to `p` because it is borrowed + p.x; // silence warning + *q; // stretch loan +} + +fn d() { + // just for completeness's sake, the easy case, where we take the + // address of a subcomponent and then modify that subcomponent: + + let mut p = Point {x: 3, y: 4}; + let q = &p.y; + p.y = 5; //~ ERROR cannot assign to `p.y` because it is borrowed + *q; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-assign-comp.stderr b/tests/ui/borrowck/borrowck-assign-comp.stderr new file mode 100644 index 000000000..2b7cef7b3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-comp.stderr @@ -0,0 +1,35 @@ +error[E0506]: cannot assign to `p.x` because it is borrowed + --> $DIR/borrowck-assign-comp.rs:10:5 + | +LL | let q = &p; + | -- borrow of `p.x` occurs here +... +LL | p.x = 5; + | ^^^^^^^ assignment to borrowed `p.x` occurs here +LL | q.x; + | --- borrow later used here + +error[E0506]: cannot assign to `p` because it is borrowed + --> $DIR/borrowck-assign-comp.rs:20:5 + | +LL | let q = &p.y; + | ---- borrow of `p` occurs here +LL | p = Point {x: 5, y: 7}; + | ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here +LL | p.x; // silence warning +LL | *q; // stretch loan + | -- borrow later used here + +error[E0506]: cannot assign to `p.y` because it is borrowed + --> $DIR/borrowck-assign-comp.rs:31:5 + | +LL | let q = &p.y; + | ---- borrow of `p.y` occurs here +LL | p.y = 5; + | ^^^^^^^ assignment to borrowed `p.y` occurs here +LL | *q; + | -- borrow later used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs b/tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs new file mode 100644 index 000000000..879c03791 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs @@ -0,0 +1,20 @@ +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +struct S<'a> { + pointer: &'a mut isize +} + +fn a(s: &S) { + *s.pointer += 1; //~ ERROR cannot assign +} + +fn b(s: &mut S) { + *s.pointer += 1; +} + +fn c(s: & &mut S) { + *s.pointer += 1; //~ ERROR cannot assign +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr b/tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr new file mode 100644 index 000000000..cbacc87a0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr @@ -0,0 +1,25 @@ +error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference + --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5 + | +LL | *s.pointer += 1; + | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn a(s: &mut S<'_>) { + | ~~~~~~~~~~ + +error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference + --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5 + | +LL | *s.pointer += 1; + | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn c(s: &mut &mut S<'_>) { + | ~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs b/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs new file mode 100644 index 000000000..f7aee2b8a --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs @@ -0,0 +1,23 @@ +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +struct S<'a> { + pointer: &'a mut isize +} + +fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> { + S { pointer: &mut *p.pointer } +} + +fn main() { + let mut x = 1; + + { + let mut y = S { pointer: &mut x }; + let z = copy_borrowed_ptr(&mut y); + *y.pointer += 1; + //~^ ERROR cannot use `*y.pointer` + //~| ERROR cannot assign to `*y.pointer` + *z.pointer += 1; + } +} diff --git a/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr b/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr new file mode 100644 index 000000000..0b21d113f --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr @@ -0,0 +1,26 @@ +error[E0503]: cannot use `*y.pointer` because it was mutably borrowed + --> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `y` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ use of borrowed `y` +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error[E0506]: cannot assign to `*y.pointer` because it is borrowed + --> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `*y.pointer` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0503, E0506. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/borrowck-assign-to-constants.rs b/tests/ui/borrowck/borrowck-assign-to-constants.rs new file mode 100644 index 000000000..5881dccf6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-constants.rs @@ -0,0 +1,6 @@ +static foo: isize = 5; + +fn main() { + // assigning to various global constants + foo = 6; //~ ERROR cannot assign to immutable static item `foo` +} diff --git a/tests/ui/borrowck/borrowck-assign-to-constants.stderr b/tests/ui/borrowck/borrowck-assign-to-constants.stderr new file mode 100644 index 000000000..864d933da --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-constants.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `foo` + --> $DIR/borrowck-assign-to-constants.rs:5:5 + | +LL | foo = 6; + | ^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrowck-assign-to-subfield.rs b/tests/ui/borrowck/borrowck-assign-to-subfield.rs new file mode 100644 index 000000000..050d702b6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assign-to-subfield.rs @@ -0,0 +1,23 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + struct A { + a: isize, + w: B, + } + struct B { + a: isize + } + let mut p = A { + a: 1, + w: B {a: 1}, + }; + + // even though `x` is not declared as a mutable field, + // `p` as a whole is mutable, so it can be modified. + p.a = 2; + + // this is true for an interior field too + p.w.a = 2; +} diff --git a/tests/ui/borrowck/borrowck-assignment-to-static-mut.rs b/tests/ui/borrowck/borrowck-assignment-to-static-mut.rs new file mode 100644 index 000000000..72bf43da9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-assignment-to-static-mut.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// Test taken from #45641 (https://github.com/rust-lang/rust/issues/45641) + +static mut Y: u32 = 0; + +unsafe fn should_ok() { + Y = 1; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs b/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs new file mode 100644 index 000000000..247e3da18 --- /dev/null +++ b/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.rs @@ -0,0 +1,16 @@ +// Tests that auto-ref can't create mutable aliases to immutable memory. + +struct Foo { + x: isize +} + +impl Foo { + pub fn printme(&mut self) { + println!("{}", self.x); + } +} + +fn main() { + let x = Foo { x: 3 }; + x.printme(); //~ ERROR cannot borrow +} diff --git a/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr new file mode 100644 index 000000000..19ef0301a --- /dev/null +++ b/tests/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:15:5 + | +LL | x.printme(); + | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = Foo { x: 3 }; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-autoref-3261.rs b/tests/ui/borrowck/borrowck-autoref-3261.rs new file mode 100644 index 000000000..2ff3d5bd3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-autoref-3261.rs @@ -0,0 +1,24 @@ +enum Either { Left(T), Right(U) } + +struct X(Either<(usize,usize), fn()>); + +impl X { + pub fn with(&self, blk: F) where F: FnOnce(&Either<(usize, usize), fn()>) { + let X(ref e) = *self; + blk(e) + } +} + +fn main() { + let mut x = X(Either::Right(main as fn())); + (&mut x).with( + |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time + match opt { + &Either::Right(ref f) => { + x = X(Either::Left((0, 0))); + (*f)() + }, + _ => panic!() + } + }) +} diff --git a/tests/ui/borrowck/borrowck-autoref-3261.stderr b/tests/ui/borrowck/borrowck-autoref-3261.stderr new file mode 100644 index 000000000..c2dfb687e --- /dev/null +++ b/tests/ui/borrowck/borrowck-autoref-3261.stderr @@ -0,0 +1,16 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-autoref-3261.rs:15:9 + | +LL | (&mut x).with( + | -------- ---- first borrow later used by call + | | + | first mutable borrow occurs here +LL | |opt| { + | ^^^^^ second mutable borrow occurs here +... +LL | x = X(Either::Left((0, 0))); + | - second borrow occurs due to use of `x` in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-free.rs b/tests/ui/borrowck/borrowck-bad-nested-calls-free.rs new file mode 100644 index 000000000..b0bb9a035 --- /dev/null +++ b/tests/ui/borrowck/borrowck-bad-nested-calls-free.rs @@ -0,0 +1,35 @@ +// Test that we detect nested calls that could free pointers evaluated +// for earlier arguments. + + + +fn rewrite(v: &mut Box) -> usize { + *v = Box::new(22); + **v +} + +fn add(v: &usize, w: usize) -> usize { + *v + w +} + +fn implicit() { + let mut a: Box<_> = Box::new(1); + + // Note the danger here: + // + // the pointer for the first argument has already been + // evaluated, but it gets freed when evaluating the second + // argument! + add( + &*a, + rewrite(&mut a)); //~ ERROR cannot borrow +} + +fn explicit() { + let mut a: Box<_> = Box::new(1); + add( + &*a, + rewrite(&mut a)); //~ ERROR cannot borrow +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-free.stderr b/tests/ui/borrowck/borrowck-bad-nested-calls-free.stderr new file mode 100644 index 000000000..e273a778f --- /dev/null +++ b/tests/ui/borrowck/borrowck-bad-nested-calls-free.stderr @@ -0,0 +1,23 @@ +error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-bad-nested-calls-free.rs:25:17 + | +LL | add( + | --- immutable borrow later used by call +LL | &*a, + | --- immutable borrow occurs here +LL | rewrite(&mut a)); + | ^^^^^^ mutable borrow occurs here + +error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-bad-nested-calls-free.rs:32:17 + | +LL | add( + | --- immutable borrow later used by call +LL | &*a, + | --- immutable borrow occurs here +LL | rewrite(&mut a)); + | ^^^^^^ mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-move.rs b/tests/ui/borrowck/borrowck-bad-nested-calls-move.rs new file mode 100644 index 000000000..b2afb6391 --- /dev/null +++ b/tests/ui/borrowck/borrowck-bad-nested-calls-move.rs @@ -0,0 +1,35 @@ +// Test that we detect nested calls that could free pointers evaluated +// for earlier arguments. + + + +fn rewrite(v: &mut Box) -> usize { + *v = Box::new(22); + **v +} + +fn add(v: &usize, w: Box) -> usize { + *v + *w +} + +fn implicit() { + let mut a: Box<_> = Box::new(1); + + // Note the danger here: + // + // the pointer for the first argument has already been + // evaluated, but it gets moved when evaluating the second + // argument! + add( + &*a, + a); //~ ERROR cannot move +} + +fn explicit() { + let mut a: Box<_> = Box::new(1); + add( + &*a, + a); //~ ERROR cannot move +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr new file mode 100644 index 000000000..371bcf2b6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr @@ -0,0 +1,23 @@ +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/borrowck-bad-nested-calls-move.rs:25:9 + | +LL | add( + | --- borrow later used by call +LL | &*a, + | --- borrow of `*a` occurs here +LL | a); + | ^ move out of `a` occurs here + +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/borrowck-bad-nested-calls-move.rs:32:9 + | +LL | add( + | --- borrow later used by call +LL | &*a, + | --- borrow of `*a` occurs here +LL | a); + | ^ move out of `a` occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-binding-mutbl.rs b/tests/ui/borrowck/borrowck-binding-mutbl.rs new file mode 100644 index 000000000..c2d2e02ec --- /dev/null +++ b/tests/ui/borrowck/borrowck-binding-mutbl.rs @@ -0,0 +1,16 @@ +// run-pass + +struct F { f: Vec } + +fn impure(_v: &[isize]) { +} + +pub fn main() { + let mut x = F {f: vec![3]}; + + match x { + F {f: ref mut v} => { + impure(v); + } + } +} diff --git a/tests/ui/borrowck/borrowck-block-unint.rs b/tests/ui/borrowck/borrowck-block-unint.rs new file mode 100644 index 000000000..8d13b25a3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-block-unint.rs @@ -0,0 +1,7 @@ +fn force(f: F) where F: FnOnce() { f(); } +fn main() { + let x: isize; + force(|| { //~ ERROR E0381 + println!("{}", x); + }); +} diff --git a/tests/ui/borrowck/borrowck-block-unint.stderr b/tests/ui/borrowck/borrowck-block-unint.stderr new file mode 100644 index 000000000..f47921a97 --- /dev/null +++ b/tests/ui/borrowck/borrowck-block-unint.stderr @@ -0,0 +1,18 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-block-unint.rs:4:11 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | force(|| { + | ^^ `x` used here but it isn't initialized +LL | println!("{}", x); + | - borrow occurs due to use in closure + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-borrow-from-expr-block.rs b/tests/ui/borrowck/borrowck-borrow-from-expr-block.rs new file mode 100644 index 000000000..24efadc30 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-expr-block.rs @@ -0,0 +1,17 @@ +// run-pass + +fn borrow(x: &isize, f: F) where F: FnOnce(&isize) { + f(x) +} + +fn test1(x: &Box) { + borrow(&*(*x).clone(), |p| { + let x_a = &**x as *const isize; + assert!((x_a as usize) != (p as *const isize as usize)); + assert_eq!(unsafe{*x_a}, *p); + }) +} + +pub fn main() { + test1(&Box::new(22)); +} diff --git a/tests/ui/borrowck/borrowck-borrow-from-owned-ptr.rs b/tests/ui/borrowck/borrowck-borrow-from-owned-ptr.rs new file mode 100644 index 000000000..353e4e9f7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-owned-ptr.rs @@ -0,0 +1,134 @@ +#[derive(Copy, Clone)] +struct Foo { + bar1: Bar, + bar2: Bar +} + +#[derive(Copy, Clone)] +struct Bar { + int1: isize, + int2: isize, +} + +fn make_foo() -> Box { panic!() } + +fn borrow_same_field_twice_mut_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_same_field_twice_mut_imm() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _bar2 = &foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_same_field_twice_imm_mut() { + let mut foo = make_foo(); + let bar1 = &foo.bar1; + let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_same_field_twice_imm_imm() { + let mut foo = make_foo(); + let bar1 = &foo.bar1; + let _bar2 = &foo.bar1; + *bar1; +} + +fn borrow_both_fields_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _bar2 = &mut foo.bar2; + *bar1; +} + +fn borrow_both_mut_pattern() { + let mut foo = make_foo(); + match *foo { + Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => { + *_bar1; + *_bar2; + } + } +} + +fn borrow_var_and_pattern() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + match *foo { + Foo { bar1: ref mut _bar1, bar2: _ } => {} + //~^ ERROR cannot borrow + } + *bar1; +} + +fn borrow_mut_and_base_imm() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo1 = &foo.bar1; //~ ERROR cannot borrow + let _foo2 = &*foo; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_mut_and_base_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_mut_and_base_mut2() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo2 = &mut *foo; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_imm_and_base_mut() { + let mut foo = make_foo(); + let bar1 = &foo.bar1.int1; + let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_imm_and_base_mut2() { + let mut foo = make_foo(); + let bar1 = &foo.bar1.int1; + let _foo2 = &mut *foo; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_imm_and_base_imm() { + let mut foo = make_foo(); + let bar1 = &foo.bar1.int1; + let _foo1 = &foo.bar1; + let _foo2 = &*foo; + *bar1; +} + +fn borrow_mut_and_imm() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _foo1 = &foo.bar2; +} + +fn borrow_mut_from_imm() { + let foo = make_foo(); + let bar1 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_long_path_both_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let foo1 = &mut foo.bar2.int2; + *bar1; + *foo1; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr b/tests/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr new file mode 100644 index 000000000..c2351aacd --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr @@ -0,0 +1,119 @@ +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-owned-ptr.rs:18:17 + | +LL | let bar1 = &mut foo.bar1; + | ------------- first mutable borrow occurs here +LL | let _bar2 = &mut foo.bar1; + | ^^^^^^^^^^^^^ second mutable borrow occurs here +LL | *bar1; + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:25:17 + | +LL | let bar1 = &mut foo.bar1; + | ------------- mutable borrow occurs here +LL | let _bar2 = &foo.bar1; + | ^^^^^^^^^ immutable borrow occurs here +LL | *bar1; + | ----- mutable borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:32:17 + | +LL | let bar1 = &foo.bar1; + | --------- immutable borrow occurs here +LL | let _bar2 = &mut foo.bar1; + | ^^^^^^^^^^^^^ mutable borrow occurs here +LL | *bar1; + | ----- immutable borrow later used here + +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-owned-ptr.rs:64:21 + | +LL | let bar1 = &mut foo.bar1; + | ------------- first mutable borrow occurs here +LL | match *foo { +LL | Foo { bar1: ref mut _bar1, bar2: _ } => {} + | ^^^^^^^^^^^^^ second mutable borrow occurs here +... +LL | *bar1; + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:73:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ mutable borrow occurs here +LL | let _foo1 = &foo.bar1; + | ^^^^^^^^^ immutable borrow occurs here +LL | let _foo2 = &*foo; +LL | *bar1; + | ----- mutable borrow later used here + +error[E0502]: cannot borrow `*foo` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:74:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ mutable borrow occurs here +LL | let _foo1 = &foo.bar1; +LL | let _foo2 = &*foo; + | ^^^^^ immutable borrow occurs here +LL | *bar1; + | ----- mutable borrow later used here + +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-owned-ptr.rs:81:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ first mutable borrow occurs here +LL | let _foo1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ second mutable borrow occurs here +LL | *bar1; + | ----- first borrow later used here + +error[E0499]: cannot borrow `*foo` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-owned-ptr.rs:88:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ first mutable borrow occurs here +LL | let _foo2 = &mut *foo; + | ^^^^^^^^^ second mutable borrow occurs here +LL | *bar1; + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:95:17 + | +LL | let bar1 = &foo.bar1.int1; + | -------------- immutable borrow occurs here +LL | let _foo1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ mutable borrow occurs here +LL | *bar1; + | ----- immutable borrow later used here + +error[E0502]: cannot borrow `*foo` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:102:17 + | +LL | let bar1 = &foo.bar1.int1; + | -------------- immutable borrow occurs here +LL | let _foo2 = &mut *foo; + | ^^^^^^^^^ mutable borrow occurs here +LL | *bar1; + | ----- immutable borrow later used here + +error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable + --> $DIR/borrowck-borrow-from-owned-ptr.rs:122:16 + | +LL | let bar1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = make_foo(); + | +++ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0499, E0502, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-borrow-from-stack-variable.rs b/tests/ui/borrowck/borrowck-borrow-from-stack-variable.rs new file mode 100644 index 000000000..231f6beab --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-stack-variable.rs @@ -0,0 +1,131 @@ +#[derive(Copy, Clone)] +struct Foo { + bar1: Bar, + bar2: Bar +} + +#[derive(Copy, Clone)] +struct Bar { + int1: isize, + int2: isize, +} + +fn make_foo() -> Foo { panic!() } + +fn borrow_same_field_twice_mut_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_same_field_twice_mut_imm() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _bar2 = &foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_same_field_twice_imm_mut() { + let mut foo = make_foo(); + let bar1 = &foo.bar1; + let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_same_field_twice_imm_imm() { + let mut foo = make_foo(); + let bar1 = &foo.bar1; + let _bar2 = &foo.bar1; + *bar1; +} + +fn borrow_both_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _bar2 = &mut foo.bar2; + *bar1; +} + +fn borrow_both_mut_pattern() { + let mut foo = make_foo(); + match foo { + Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => {} + } +} + +fn borrow_var_and_pattern() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + match foo { + Foo { bar1: ref mut _bar1, bar2: _ } => {} // + //~^ ERROR cannot borrow + } + *bar1; +} + +fn borrow_mut_and_base_imm() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo1 = &foo.bar1; //~ ERROR cannot borrow + let _foo2 = &foo; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_mut_and_base_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_mut_and_base_mut2() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo2 = &mut foo; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_imm_and_base_mut() { + let mut foo = make_foo(); + let bar1 = &foo.bar1.int1; + let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_imm_and_base_mut2() { + let mut foo = make_foo(); + let bar1 = &foo.bar1.int1; + let _foo2 = &mut foo; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_imm_and_base_imm() { + let mut foo = make_foo(); + let bar1 = &foo.bar1.int1; + let _foo1 = &foo.bar1; + let _foo2 = &foo; + *bar1; +} + +fn borrow_mut_and_imm() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1; + let _foo1 = &foo.bar2; + *bar1; +} + +fn borrow_mut_from_imm() { + let foo = make_foo(); + let bar1 = &mut foo.bar1; //~ ERROR cannot borrow + *bar1; +} + +fn borrow_long_path_both_mut() { + let mut foo = make_foo(); + let bar1 = &mut foo.bar1.int1; + let _foo1 = &mut foo.bar2.int2; + *bar1; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-borrow-from-stack-variable.stderr b/tests/ui/borrowck/borrowck-borrow-from-stack-variable.stderr new file mode 100644 index 000000000..8fcaaa883 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-stack-variable.stderr @@ -0,0 +1,119 @@ +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-stack-variable.rs:18:17 + | +LL | let bar1 = &mut foo.bar1; + | ------------- first mutable borrow occurs here +LL | let _bar2 = &mut foo.bar1; + | ^^^^^^^^^^^^^ second mutable borrow occurs here +LL | *bar1; + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:25:17 + | +LL | let bar1 = &mut foo.bar1; + | ------------- mutable borrow occurs here +LL | let _bar2 = &foo.bar1; + | ^^^^^^^^^ immutable borrow occurs here +LL | *bar1; + | ----- mutable borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:32:17 + | +LL | let bar1 = &foo.bar1; + | --------- immutable borrow occurs here +LL | let _bar2 = &mut foo.bar1; + | ^^^^^^^^^^^^^ mutable borrow occurs here +LL | *bar1; + | ----- immutable borrow later used here + +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-stack-variable.rs:61:21 + | +LL | let bar1 = &mut foo.bar1; + | ------------- first mutable borrow occurs here +LL | match foo { +LL | Foo { bar1: ref mut _bar1, bar2: _ } => {} // + | ^^^^^^^^^^^^^ second mutable borrow occurs here +... +LL | *bar1; + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:70:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ mutable borrow occurs here +LL | let _foo1 = &foo.bar1; + | ^^^^^^^^^ immutable borrow occurs here +LL | let _foo2 = &foo; +LL | *bar1; + | ----- mutable borrow later used here + +error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:71:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ mutable borrow occurs here +LL | let _foo1 = &foo.bar1; +LL | let _foo2 = &foo; + | ^^^^ immutable borrow occurs here +LL | *bar1; + | ----- mutable borrow later used here + +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-stack-variable.rs:78:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ first mutable borrow occurs here +LL | let _foo1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ second mutable borrow occurs here +LL | *bar1; + | ----- first borrow later used here + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/borrowck-borrow-from-stack-variable.rs:85:17 + | +LL | let bar1 = &mut foo.bar1.int1; + | ------------------ first mutable borrow occurs here +LL | let _foo2 = &mut foo; + | ^^^^^^^^ second mutable borrow occurs here +LL | *bar1; + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:92:17 + | +LL | let bar1 = &foo.bar1.int1; + | -------------- immutable borrow occurs here +LL | let _foo1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ mutable borrow occurs here +LL | *bar1; + | ----- immutable borrow later used here + +error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:99:17 + | +LL | let bar1 = &foo.bar1.int1; + | -------------- immutable borrow occurs here +LL | let _foo2 = &mut foo; + | ^^^^^^^^ mutable borrow occurs here +LL | *bar1; + | ----- immutable borrow later used here + +error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable + --> $DIR/borrowck-borrow-from-stack-variable.rs:120:16 + | +LL | let bar1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = make_foo(); + | +++ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0499, E0502, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-borrow-from-temporary.rs b/tests/ui/borrowck/borrowck-borrow-from-temporary.rs new file mode 100644 index 000000000..92f3ffd57 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-temporary.rs @@ -0,0 +1,14 @@ +// Test lifetimes are linked properly when we take reference +// to interior. + +fn id(x: T) -> T { x } + +struct Foo(isize); + +fn foo<'a>() -> &'a isize { + let &Foo(ref x) = &id(Foo(3)); + x //~ ERROR cannot return value referencing temporary value +} + +pub fn main() { +} diff --git a/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr b/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr new file mode 100644 index 000000000..71bf052c9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-from-temporary.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/borrowck-borrow-from-temporary.rs:10:5 + | +LL | let &Foo(ref x) = &id(Foo(3)); + | ---------- temporary value created here +LL | x + | ^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs b/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs new file mode 100644 index 000000000..6b5544a8a --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs @@ -0,0 +1,14 @@ +struct A; + +impl A { + fn foo(&mut self) { + } +} + + + +pub fn main() { + let a: Box<_> = Box::new(A); + a.foo(); + //~^ ERROR cannot borrow `*a` as mutable, as `a` is not declared as mutable [E0596] +} diff --git a/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr new file mode 100644 index 000000000..3c28ff56e --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*a` as mutable, as `a` is not declared as mutable + --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5 + | +LL | a.foo(); + | ^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut a: Box<_> = Box::new(A); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs new file mode 100644 index 000000000..7a88c3df2 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -0,0 +1,24 @@ +// Test that attempt to reborrow an `&mut` pointer in an aliasable +// location yields an error. +// +// Example from compiler/rustc_borrowck/borrowck/README.md + +fn foo(t0: & &mut isize) { + let t1 = t0; + let p: &isize = &**t0; + **t1 = 22; //~ ERROR cannot assign +} + +fn foo3(t0: &mut &mut isize) { + let t1 = &mut *t0; + let p: &isize = &**t0; //~ ERROR cannot borrow + **t1 = 22; +} + +fn foo4(t0: & &mut isize) { + let x: &mut isize = &mut **t0; //~ ERROR cannot borrow + *x += 1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr new file mode 100644 index 000000000..ce9f7aa05 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -0,0 +1,34 @@ +error[E0594]: cannot assign to `**t1`, which is behind a `&` reference + --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5 + | +LL | let t1 = t0; + | -- consider changing this binding's type to be: `&mut &mut isize` +LL | let p: &isize = &**t0; +LL | **t1 = 22; + | ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written + +error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21 + | +LL | let t1 = &mut *t0; + | -------- mutable borrow occurs here +LL | let p: &isize = &**t0; + | ^^^^^ immutable borrow occurs here +LL | **t1 = 22; + | --------- mutable borrow later used here + +error[E0596]: cannot borrow `**t0` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:19:26 + | +LL | let x: &mut isize = &mut **t0; + | ^^^^^^^^^ `t0` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo4(t0: &mut &mut isize) { + | ~~~~~~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0502, E0594, E0596. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-borrow-mut-object-twice.rs b/tests/ui/borrowck/borrowck-borrow-mut-object-twice.rs new file mode 100644 index 000000000..b4d85b60c --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-mut-object-twice.rs @@ -0,0 +1,20 @@ +// Check that `&mut` objects cannot be borrowed twice, just like +// other `&mut` pointers. + + + +trait Foo { + fn f1(&mut self) -> &(); + fn f2(&mut self); +} + +fn test(x: &mut dyn Foo) { + let y = x.f1(); + x.f2(); //~ ERROR cannot borrow `*x` as mutable + y.use_ref(); +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr b/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr new file mode 100644 index 000000000..42b6c34cd --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-mut-object-twice.stderr @@ -0,0 +1,13 @@ +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/borrowck-borrow-mut-object-twice.rs:13:5 + | +LL | let y = x.f1(); + | ------ first mutable borrow occurs here +LL | x.f2(); + | ^^^^^^ second mutable borrow occurs here +LL | y.use_ref(); + | ----------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs b/tests/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs new file mode 100644 index 000000000..5ef282c0c --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] +// Test that freezing an `&mut` pointer while referent is +// frozen is legal. +// +// Example from compiler/rustc_borrowck/borrowck/README.md + +// pretty-expanded FIXME #23616 + +fn foo<'a>(mut t0: &'a mut isize, + mut t1: &'a mut isize) { + let p: &isize = &*t0; // Freezes `*t0` + let mut t2 = &t0; + let q: &isize = &**t2; // Freezes `*t0`, but that's ok... + let r: &isize = &*t0; // ...after all, could do same thing directly. +} + +pub fn main() { +} diff --git a/tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs b/tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs new file mode 100644 index 000000000..83eab7fde --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs @@ -0,0 +1,103 @@ +// Test how overloaded deref interacts with borrows when only +// Deref and not DerefMut is implemented. + +use std::ops::Deref; +use std::rc::Rc; + +struct Point { + x: isize, + y: isize +} + +impl Point { + fn get(&self) -> (isize, isize) { + (self.x, self.y) + } + + fn set(&mut self, x: isize, y: isize) { + self.x = x; + self.y = y; + } + + fn x_ref(&self) -> &isize { + &self.x + } + + fn y_mut(&mut self) -> &mut isize { + &mut self.y + } +} + +fn deref_imm_field(x: Rc) { + let __isize = &x.y; +} + +fn deref_mut_field1(x: Rc) { + let __isize = &mut x.y; //~ ERROR cannot borrow +} + +fn deref_mut_field2(mut x: Rc) { + let __isize = &mut x.y; //~ ERROR cannot borrow +} + +fn deref_extend_field(x: &Rc) -> &isize { + &x.y +} + +fn deref_extend_mut_field1(x: &Rc) -> &mut isize { + &mut x.y //~ ERROR cannot borrow +} + +fn deref_extend_mut_field2(x: &mut Rc) -> &mut isize { + &mut x.y //~ ERROR cannot borrow +} + +fn assign_field1<'a>(x: Rc) { + x.y = 3; //~ ERROR cannot assign +} + +fn assign_field2<'a>(x: &'a Rc) { + x.y = 3; //~ ERROR cannot assign +} + +fn assign_field3<'a>(x: &'a mut Rc) { + x.y = 3; //~ ERROR cannot assign +} + +fn deref_imm_method(x: Rc) { + let __isize = x.get(); +} + +fn deref_mut_method1(x: Rc) { + x.set(0, 0); //~ ERROR cannot borrow +} + +fn deref_mut_method2(mut x: Rc) { + x.set(0, 0); //~ ERROR cannot borrow +} + +fn deref_extend_method(x: &Rc) -> &isize { + x.x_ref() +} + +fn deref_extend_mut_method1(x: &Rc) -> &mut isize { + x.y_mut() //~ ERROR cannot borrow +} + +fn deref_extend_mut_method2(x: &mut Rc) -> &mut isize { + x.y_mut() //~ ERROR cannot borrow +} + +fn assign_method1<'a>(x: Rc) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +fn assign_method2<'a>(x: &'a Rc) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +fn assign_method3<'a>(x: &'a mut Rc) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +pub fn main() {} diff --git a/tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr b/tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr new file mode 100644 index 000000000..fdf6568d8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr @@ -0,0 +1,116 @@ +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:36:19 + | +LL | let __isize = &mut x.y; + | ^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:40:19 + | +LL | let __isize = &mut x.y; + | ^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:48:5 + | +LL | &mut x.y + | ^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:52:5 + | +LL | &mut x.y + | ^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0594]: cannot assign to data in an `Rc` + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:56:5 + | +LL | x.y = 3; + | ^^^^^^^ cannot assign + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0594]: cannot assign to data in an `Rc` + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:60:5 + | +LL | x.y = 3; + | ^^^^^^^ cannot assign + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0594]: cannot assign to data in an `Rc` + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:64:5 + | +LL | x.y = 3; + | ^^^^^^^ cannot assign + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:72:5 + | +LL | x.set(0, 0); + | ^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:76:5 + | +LL | x.set(0, 0); + | ^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:84:5 + | +LL | x.y_mut() + | ^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:88:5 + | +LL | x.y_mut() + | ^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:92:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:96:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:100:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrowck-borrow-overloaded-deref.rs b/tests/ui/borrowck/borrowck-borrow-overloaded-deref.rs new file mode 100644 index 000000000..2b98a7b94 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-overloaded-deref.rs @@ -0,0 +1,43 @@ +// Test how overloaded deref interacts with borrows when only +// Deref and not DerefMut is implemented. + +use std::ops::Deref; +use std::rc::Rc; + +fn deref_imm(x: Rc) { + let __isize = &*x; +} + +fn deref_mut1(x: Rc) { + let __isize = &mut *x; //~ ERROR cannot borrow +} + +fn deref_mut2(mut x: Rc) { + let __isize = &mut *x; //~ ERROR cannot borrow +} + +fn deref_extend<'a>(x: &'a Rc) -> &'a isize { + &**x +} + +fn deref_extend_mut1<'a>(x: &'a Rc) -> &'a mut isize { + &mut **x //~ ERROR cannot borrow +} + +fn deref_extend_mut2<'a>(x: &'a mut Rc) -> &'a mut isize { + &mut **x //~ ERROR cannot borrow +} + +fn assign1<'a>(x: Rc) { + *x = 3; //~ ERROR cannot assign +} + +fn assign2<'a>(x: &'a Rc) { + **x = 3; //~ ERROR cannot assign +} + +fn assign3<'a>(x: &'a mut Rc) { + **x = 3; //~ ERROR cannot assign +} + +pub fn main() {} diff --git a/tests/ui/borrowck/borrowck-borrow-overloaded-deref.stderr b/tests/ui/borrowck/borrowck-borrow-overloaded-deref.stderr new file mode 100644 index 000000000..9ed9d2924 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrow-overloaded-deref.stderr @@ -0,0 +1,60 @@ +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-deref.rs:12:19 + | +LL | let __isize = &mut *x; + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-deref.rs:16:19 + | +LL | let __isize = &mut *x; + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-deref.rs:24:5 + | +LL | &mut **x + | ^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0596]: cannot borrow data in an `Rc` as mutable + --> $DIR/borrowck-borrow-overloaded-deref.rs:28:5 + | +LL | &mut **x + | ^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0594]: cannot assign to data in an `Rc` + --> $DIR/borrowck-borrow-overloaded-deref.rs:32:5 + | +LL | *x = 3; + | ^^^^^^ cannot assign + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0594]: cannot assign to data in an `Rc` + --> $DIR/borrowck-borrow-overloaded-deref.rs:36:5 + | +LL | **x = 3; + | ^^^^^^^ cannot assign + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error[E0594]: cannot assign to data in an `Rc` + --> $DIR/borrowck-borrow-overloaded-deref.rs:40:5 + | +LL | **x = 3; + | ^^^^^^^ cannot assign + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs new file mode 100644 index 000000000..e384aacb7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.rs @@ -0,0 +1,22 @@ +struct Defer<'a> { + x: &'a [&'a str], +} + +impl<'a> Drop for Defer<'a> { + fn drop(&mut self) { + unsafe { + println!("{:?}", self.x); + } + } +} + +fn defer<'r>(x: &'r [&'r str]) -> Defer<'r> { + Defer { + x: x + } +} + +fn main() { + let x = defer(&vec!["Goodbye", "world!"]); //~ ERROR temporary value dropped while borrowed + x.x[0]; +} diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr new file mode 100644 index 000000000..4eeec09b9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue-2.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-borrowed-uniq-rvalue-2.rs:20:20 + | +LL | let x = defer(&vec!["Goodbye", "world!"]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | x.x[0]; + | ------ borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.fixed b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.fixed new file mode 100644 index 000000000..8bf6a2f6d --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +use std::collections::HashMap; + +fn main() { + let tmp: Box<_>; + let mut buggy_map: HashMap = HashMap::new(); + let binding = Box::new(1); + buggy_map.insert(42, &*binding); //~ ERROR temporary value dropped while borrowed + + // but it is ok if we use a temporary + tmp = Box::new(2); + buggy_map.insert(43, &*tmp); +} diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs new file mode 100644 index 000000000..85481336a --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.rs @@ -0,0 +1,13 @@ +// run-rustfix + +use std::collections::HashMap; + +fn main() { + let tmp: Box<_>; + let mut buggy_map: HashMap = HashMap::new(); + buggy_map.insert(42, &*Box::new(1)); //~ ERROR temporary value dropped while borrowed + + // but it is ok if we use a temporary + tmp = Box::new(2); + buggy_map.insert(43, &*tmp); +} diff --git a/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr new file mode 100644 index 000000000..c62d5f903 --- /dev/null +++ b/tests/ui/borrowck/borrowck-borrowed-uniq-rvalue.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-borrowed-uniq-rvalue.rs:8:28 + | +LL | buggy_map.insert(42, &*Box::new(1)); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | buggy_map.insert(43, &*tmp); + | --------------------------- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Box::new(1); +LL ~ buggy_map.insert(42, &*binding); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/borrowck-box-sensitivity.rs b/tests/ui/borrowck/borrowck-box-sensitivity.rs new file mode 100644 index 000000000..e880f876f --- /dev/null +++ b/tests/ui/borrowck/borrowck-box-sensitivity.rs @@ -0,0 +1,148 @@ +// Test that `Box` is treated specially by borrow checking. This is the case +// because NLL reverted the deicision in rust-lang/rfcs#130. + +// run-pass + +struct A { + x: Box, + y: isize, +} + +struct B { + x: Box, + y: Box, +} + +struct C { + x: Box, + y: isize, +} + +struct D { + x: Box, + y: Box, +} + +fn copy_after_move() { + let a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); + let _x = a.x; + let _y = a.y; +} + +fn move_after_move() { + let a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) }); + let _x = a.x; + let _y = a.y; +} + +fn borrow_after_move() { + let a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); + let _x = a.x; + let _y = &a.y; +} + +fn move_after_borrow() { + let a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) }); + let _x = &a.x; + let _y = a.y; + use_imm(_x); +} +fn copy_after_mut_borrow() { + let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); + let _x = &mut a.x; + let _y = a.y; + use_mut(_x); +} +fn move_after_mut_borrow() { + let mut a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) }); + let _x = &mut a.x; + let _y = a.y; + use_mut(_x); +} +fn borrow_after_mut_borrow() { + let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); + let _x = &mut a.x; + let _y = &a.y; + use_mut(_x); +} +fn mut_borrow_after_borrow() { + let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 }); + let _x = &a.x; + let _y = &mut a.y; + use_imm(_x); +} +fn copy_after_move_nested() { + let a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); + let _x = a.x.x; + let _y = a.y; +} + +fn move_after_move_nested() { + let a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) }); + let _x = a.x.x; + let _y = a.y; +} + +fn borrow_after_move_nested() { + let a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); + let _x = a.x.x; + let _y = &a.y; +} + +fn move_after_borrow_nested() { + let a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) }); + let _x = &a.x.x; + let _y = a.y; + use_imm(_x); +} +fn copy_after_mut_borrow_nested() { + let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); + let _x = &mut a.x.x; + let _y = a.y; + use_mut(_x); +} +fn move_after_mut_borrow_nested() { + let mut a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) }); + let _x = &mut a.x.x; + let _y = a.y; + use_mut(_x); +} +fn borrow_after_mut_borrow_nested() { + let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); + let _x = &mut a.x.x; + let _y = &a.y; + use_mut(_x); +} +fn mut_borrow_after_borrow_nested() { + let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 }); + let _x = &a.x.x; + let _y = &mut a.y; + use_imm(_x); +} + +fn main() { + copy_after_move(); + move_after_move(); + borrow_after_move(); + + move_after_borrow(); + + copy_after_mut_borrow(); + move_after_mut_borrow(); + borrow_after_mut_borrow(); + mut_borrow_after_borrow(); + + copy_after_move_nested(); + move_after_move_nested(); + borrow_after_move_nested(); + + move_after_borrow_nested(); + + copy_after_mut_borrow_nested(); + move_after_mut_borrow_nested(); + borrow_after_mut_borrow_nested(); + mut_borrow_after_borrow_nested(); +} + +fn use_mut(_: &mut T) { } +fn use_imm(_: &T) { } diff --git a/tests/ui/borrowck/borrowck-break-uninit-2.rs b/tests/ui/borrowck/borrowck-break-uninit-2.rs new file mode 100644 index 000000000..3abca33a8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-break-uninit-2.rs @@ -0,0 +1,14 @@ +fn foo() -> isize { + let x: isize; + + while 1 != 2 { + break; + x = 0; + } + + println!("{}", x); //~ ERROR E0381 + + return 17; +} + +fn main() { println!("{}", foo()); } diff --git a/tests/ui/borrowck/borrowck-break-uninit-2.stderr b/tests/ui/borrowck/borrowck-break-uninit-2.stderr new file mode 100644 index 000000000..ea93a8f40 --- /dev/null +++ b/tests/ui/borrowck/borrowck-break-uninit-2.stderr @@ -0,0 +1,18 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-break-uninit-2.rs:9:20 + | +LL | let x: isize; + | - binding declared here but left uninitialized +... +LL | println!("{}", x); + | ^ `x` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-break-uninit.rs b/tests/ui/borrowck/borrowck-break-uninit.rs new file mode 100644 index 000000000..824f91dbc --- /dev/null +++ b/tests/ui/borrowck/borrowck-break-uninit.rs @@ -0,0 +1,14 @@ +fn foo() -> isize { + let x: isize; + + loop { + break; + x = 0; + } + + println!("{}", x); //~ ERROR E0381 + + return 17; +} + +fn main() { println!("{}", foo()); } diff --git a/tests/ui/borrowck/borrowck-break-uninit.stderr b/tests/ui/borrowck/borrowck-break-uninit.stderr new file mode 100644 index 000000000..a7a8fc2ff --- /dev/null +++ b/tests/ui/borrowck/borrowck-break-uninit.stderr @@ -0,0 +1,18 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-break-uninit.rs:9:20 + | +LL | let x: isize; + | - binding declared here but left uninitialized +... +LL | println!("{}", x); + | ^ `x` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-closures-mut-and-imm.rs b/tests/ui/borrowck/borrowck-closures-mut-and-imm.rs new file mode 100644 index 000000000..a8225f2fa --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-mut-and-imm.rs @@ -0,0 +1,87 @@ +// Tests that two closures cannot simultaneously have mutable +// and immutable access to the variable. Issue #6801. + +fn get(x: &isize) -> isize { + *x +} + +fn set(x: &mut isize) { + *x = 4; +} + + + +fn a() { + let mut x = 3; + let c1 = || x = 4; + let c2 = || x * 5; + //~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + drop(c1); +} + +fn b() { + let mut x = 3; + let c1 = || set(&mut x); + let c2 = || get(&x); + //~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + drop(c1); +} + +fn c() { + let mut x = 3; + let c1 = || set(&mut x); + let c2 = || x * 5; + //~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + drop(c1); +} + +fn d() { + let mut x = 3; + let c2 = || x * 5; + x = 5; + //~^ ERROR cannot assign to `x` because it is borrowed + drop(c2); +} + +fn e() { + let mut x = 3; + let c1 = || get(&x); + x = 5; + //~^ ERROR cannot assign to `x` because it is borrowed + drop(c1); +} + +fn f() { + let mut x: Box<_> = Box::new(3); + let c1 = || get(&*x); + *x = 5; + //~^ ERROR cannot assign to `*x` because it is borrowed + drop(c1); +} + +fn g() { + struct Foo { + f: Box + } + + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); + let c1 = || get(&*x.f); + *x.f = 5; + //~^ ERROR cannot assign to `*x.f` because it is borrowed + drop(c1); +} + +fn h() { + struct Foo { + f: Box + } + + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); + let c1 = || get(&*x.f); + let c2 = || *x.f = 5; + //~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + drop(c1); +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr b/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr new file mode 100644 index 000000000..fadcd11a5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr @@ -0,0 +1,116 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 + | +LL | let c1 = || x = 4; + | -- - first borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | let c2 = || x * 5; + | ^^ - second borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | +LL | drop(c1); + | -- mutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-closures-mut-and-imm.rs:25:14 + | +LL | let c1 = || set(&mut x); + | -- - first borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | let c2 = || get(&x); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | +LL | drop(c1); + | -- mutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-closures-mut-and-imm.rs:33:14 + | +LL | let c1 = || set(&mut x); + | -- - first borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | let c2 = || x * 5; + | ^^ - second borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | +LL | drop(c1); + | -- mutable borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/borrowck-closures-mut-and-imm.rs:41:5 + | +LL | let c2 = || x * 5; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 5; + | ^^^^^ assignment to borrowed `x` occurs here +LL | +LL | drop(c2); + | -- borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/borrowck-closures-mut-and-imm.rs:49:5 + | +LL | let c1 = || get(&x); + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 5; + | ^^^^^ assignment to borrowed `x` occurs here +LL | +LL | drop(c1); + | -- borrow later used here + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/borrowck-closures-mut-and-imm.rs:57:5 + | +LL | let c1 = || get(&*x); + | -- -- borrow occurs due to use in closure + | | + | borrow of `*x` occurs here +LL | *x = 5; + | ^^^^^^ assignment to borrowed `*x` occurs here +LL | +LL | drop(c1); + | -- borrow later used here + +error[E0506]: cannot assign to `*x.f` because it is borrowed + --> $DIR/borrowck-closures-mut-and-imm.rs:69:5 + | +LL | let c1 = || get(&*x.f); + | -- ---- borrow occurs due to use in closure + | | + | borrow of `*x.f` occurs here +LL | *x.f = 5; + | ^^^^^^^^ assignment to borrowed `*x.f` occurs here +LL | +LL | drop(c1); + | -- borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-mut-and-imm.rs:81:14 + | +LL | let c1 = || get(&*x.f); + | -- ---- first borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | let c2 = || *x.f = 5; + | ^^ ---- second borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | +LL | drop(c1); + | -- immutable borrow later used here + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0502, E0506. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-closures-mut-of-imm.rs b/tests/ui/borrowck/borrowck-closures-mut-of-imm.rs new file mode 100644 index 000000000..d7e187a2b --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-mut-of-imm.rs @@ -0,0 +1,18 @@ +// Tests that two closures cannot simultaneously have mutable +// and immutable access to the variable. Issue #6801. + +fn set(x: &mut isize) { + *x = 4; +} + +fn a(x: &isize) { + let mut c1 = || set(&mut *x); + //~^ ERROR cannot borrow + let mut c2 = || set(&mut *x); + //~^ ERROR cannot borrow + //~| ERROR two closures require unique access to `x` at the same time + c2(); c1(); +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-closures-mut-of-imm.stderr b/tests/ui/borrowck/borrowck-closures-mut-of-imm.stderr new file mode 100644 index 000000000..537ec9895 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-mut-of-imm.stderr @@ -0,0 +1,32 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-closures-mut-of-imm.rs:9:25 + | +LL | let mut c1 = || set(&mut *x); + | ^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-closures-mut-of-imm.rs:11:25 + | +LL | let mut c2 = || set(&mut *x); + | ^^^^^^^ cannot borrow as mutable + +error[E0524]: two closures require unique access to `x` at the same time + --> $DIR/borrowck-closures-mut-of-imm.rs:11:18 + | +LL | let mut c1 = || set(&mut *x); + | -- -- first borrow occurs due to use of `x` in closure + | | + | first closure is constructed here +LL | +LL | let mut c2 = || set(&mut *x); + | ^^ -- second borrow occurs due to use of `x` in closure + | | + | second closure is constructed here +... +LL | c2(); c1(); + | -- first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0524, E0596. +For more information about an error, try `rustc --explain E0524`. diff --git a/tests/ui/borrowck/borrowck-closures-mut-of-mut.rs b/tests/ui/borrowck/borrowck-closures-mut-of-mut.rs new file mode 100644 index 000000000..50c6f2c58 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-mut-of-mut.rs @@ -0,0 +1,20 @@ +// Tests that two closures cannot simultaneously both have mutable +// access to the variable. Related to issue #6801. + +fn get(x: &isize) -> isize { + *x +} + +fn set(x: &mut isize) { + *x = 4; +} + +fn a(x: &mut isize) { + let mut c1 = || set(&mut *x); + let mut c2 = || set(&mut *x); + //~^ ERROR two closures require unique access to `x` at the same time + c2(); c1(); +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr new file mode 100644 index 000000000..e5ee5a401 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-mut-of-mut.stderr @@ -0,0 +1,18 @@ +error[E0524]: two closures require unique access to `x` at the same time + --> $DIR/borrowck-closures-mut-of-mut.rs:14:18 + | +LL | let mut c1 = || set(&mut *x); + | -- -- first borrow occurs due to use of `x` in closure + | | + | first closure is constructed here +LL | let mut c2 = || set(&mut *x); + | ^^ -- second borrow occurs due to use of `x` in closure + | | + | second closure is constructed here +LL | +LL | c2(); c1(); + | -- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0524`. diff --git a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs new file mode 100644 index 000000000..0229ca37a --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs @@ -0,0 +1,117 @@ +// Check that closure captures for slice patterns are inferred correctly + +#![allow(unused_variables)] + +// run-pass + +fn arr_by_ref(x: [String; 3]) { + let r = &x; + let f = || { + let [ref y, ref z @ ..] = x; + }; + f(); + f(); + // Ensure `x` was borrowed + drop(r); + // Ensure that `x` wasn't moved from. + drop(x); +} + +fn arr_by_mut(mut x: [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = x; + }; + f(); + f(); + drop(x); +} + +fn arr_by_move(x: [String; 3]) { + let f = || { + let [y, z @ ..] = x; + }; + f(); +} + +fn arr_ref_by_ref(x: &[String; 3]) { + let r = &x; + let f = || { + let [ref y, ref z @ ..] = *x; + }; + let g = || { + let [y, z @ ..] = x; + }; + f(); + g(); + f(); + g(); + drop(r); + drop(x); +} + +fn arr_ref_by_mut(x: &mut [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = *x; + }; + f(); + f(); + let mut g = || { + let [y, z @ ..] = x; + // Ensure binding mode was chosen correctly: + std::mem::swap(y, &mut z[0]); + }; + g(); + g(); + drop(x); +} + +fn arr_box_by_move(x: Box<[String; 3]>) { + let f = || { + let [y, z @ ..] = *x; + }; + f(); +} + +fn slice_by_ref(x: &[String]) { + let r = &x; + let f = || { + if let [ref y, ref z @ ..] = *x {} + }; + let g = || { + if let [y, z @ ..] = x {} + }; + f(); + g(); + f(); + g(); + drop(r); + drop(x); +} + +fn slice_by_mut(x: &mut [String]) { + let mut f = || { + if let [ref mut y, ref mut z @ ..] = *x {} + }; + f(); + f(); + let mut g = || { + if let [y, z @ ..] = x { + // Ensure binding mode was chosen correctly: + std::mem::swap(y, &mut z[0]); + } + }; + g(); + g(); + drop(x); +} + +fn main() { + arr_by_ref(Default::default()); + arr_by_mut(Default::default()); + arr_by_move(Default::default()); + arr_ref_by_ref(&Default::default()); + arr_ref_by_mut(&mut Default::default()); + arr_box_by_move(Default::default()); + slice_by_ref(&<[_; 3]>::default()); + slice_by_mut(&mut <[_; 3]>::default()); +} diff --git a/tests/ui/borrowck/borrowck-closures-slice-patterns.rs b/tests/ui/borrowck/borrowck-closures-slice-patterns.rs new file mode 100644 index 000000000..32057d5c1 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-slice-patterns.rs @@ -0,0 +1,82 @@ +// Check that closure captures for slice patterns are inferred correctly + +fn arr_by_ref(mut x: [String; 3]) { + let f = || { + let [ref y, ref z @ ..] = x; + }; + let r = &mut x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_by_mut(mut x: [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = x; + }; + let r = &x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_by_move(x: [String; 3]) { + let f = || { + let [y, z @ ..] = x; + }; + &x; + //~^ ERROR borrow of moved value +} + +fn arr_ref_by_ref(x: &mut [String; 3]) { + let f = || { + let [ref y, ref z @ ..] = *x; + }; + let r = &mut *x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_ref_by_uniq(x: &mut [String; 3]) { + let mut f = || { + let [ref mut y, ref mut z @ ..] = *x; + }; + let r = &x; + //~^ ERROR cannot borrow + f(); +} + +fn arr_box_by_move(x: Box<[String; 3]>) { + let f = || { + let [y, z @ ..] = *x; + }; + &x; + //~^ ERROR borrow of moved value +} + +fn slice_by_ref(x: &mut [String]) { + let f = || { + if let [ref y, ref z @ ..] = *x {} + }; + let r = &mut *x; + //~^ ERROR cannot borrow + f(); +} + +fn slice_by_uniq(x: &mut [String]) { + let mut f = || { + if let [ref mut y, ref mut z @ ..] = *x {} + }; + let r = &x; + //~^ ERROR cannot borrow + f(); +} + +fn main() { + arr_by_ref(Default::default()); + arr_by_mut(Default::default()); + arr_by_move(Default::default()); + arr_ref_by_ref(&mut Default::default()); + arr_ref_by_uniq(&mut Default::default()); + arr_box_by_move(Default::default()); + slice_by_ref(&mut <[_; 3]>::default()); + slice_by_uniq(&mut <[_; 3]>::default()); +} diff --git a/tests/ui/borrowck/borrowck-closures-slice-patterns.stderr b/tests/ui/borrowck/borrowck-closures-slice-patterns.stderr new file mode 100644 index 000000000..411d85b8e --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-slice-patterns.stderr @@ -0,0 +1,114 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-slice-patterns.rs:7:13 + | +LL | let f = || { + | -- immutable borrow occurs here +LL | let [ref y, ref z @ ..] = x; + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &mut x; + | ^^^^^^ mutable borrow occurs here +LL | +LL | f(); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-closures-slice-patterns.rs:16:13 + | +LL | let mut f = || { + | -- mutable borrow occurs here +LL | let [ref mut y, ref mut z @ ..] = x; + | - first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &x; + | ^^ immutable borrow occurs here +LL | +LL | f(); + | - mutable borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrowck-closures-slice-patterns.rs:25:5 + | +LL | fn arr_by_move(x: [String; 3]) { + | - move occurs because `x` has type `[String; 3]`, which does not implement the `Copy` trait +LL | let f = || { + | -- value moved into closure here +LL | let [y, z @ ..] = x; + | - variable moved due to use in closure +LL | }; +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-slice-patterns.rs:33:13 + | +LL | let f = || { + | -- immutable borrow occurs here +LL | let [ref y, ref z @ ..] = *x; + | -- first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &mut *x; + | ^^^^^^^ mutable borrow occurs here +LL | +LL | f(); + | - immutable borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/borrowck-closures-slice-patterns.rs:42:13 + | +LL | let mut f = || { + | -- closure construction occurs here +LL | let [ref mut y, ref mut z @ ..] = *x; + | -- first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &x; + | ^^ second borrow occurs here +LL | +LL | f(); + | - first borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrowck-closures-slice-patterns.rs:51:5 + | +LL | fn arr_box_by_move(x: Box<[String; 3]>) { + | - move occurs because `x` has type `Box<[String; 3]>`, which does not implement the `Copy` trait +LL | let f = || { + | -- value moved into closure here +LL | let [y, z @ ..] = *x; + | -- variable moved due to use in closure +LL | }; +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-slice-patterns.rs:59:13 + | +LL | let f = || { + | -- immutable borrow occurs here +LL | if let [ref y, ref z @ ..] = *x {} + | -- first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &mut *x; + | ^^^^^^^ mutable borrow occurs here +LL | +LL | f(); + | - immutable borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/borrowck-closures-slice-patterns.rs:68:13 + | +LL | let mut f = || { + | -- closure construction occurs here +LL | if let [ref mut y, ref mut z @ ..] = *x {} + | -- first borrow occurs due to use of `x` in closure +LL | }; +LL | let r = &x; + | ^^ second borrow occurs here +LL | +LL | f(); + | - first borrow later used here + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0382, E0501, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-closures-two-imm.rs b/tests/ui/borrowck/borrowck-closures-two-imm.rs new file mode 100644 index 000000000..ab135194a --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-two-imm.rs @@ -0,0 +1,41 @@ +// run-pass +// Tests that two closures can simultaneously have immutable +// access to the variable, whether that immutable access be used +// for direct reads or for taking immutable ref. Also check +// that the main function can read the variable too while +// the closures are in scope. Issue #6801. + + +fn a() -> i32 { + let mut x = 3; + x += 1; + let c1 = || x * 4; + let c2 = || x * 5; + c1() * c2() * x +} + +fn get(x: &i32) -> i32 { + *x * 4 +} + +fn b() -> i32 { + let mut x = 3; + x += 1; + let c1 = || get(&x); + let c2 = || get(&x); + c1() * c2() * x +} + +fn c() -> i32 { + let mut x = 3; + x += 1; + let c1 = || x * 5; + let c2 = || get(&x); + c1() * c2() * x +} + +pub fn main() { + assert_eq!(a(), 1280); + assert_eq!(b(), 1024); + assert_eq!(c(), 1280); +} diff --git a/tests/ui/borrowck/borrowck-closures-two-mut-fail.rs b/tests/ui/borrowck/borrowck-closures-two-mut-fail.rs new file mode 100644 index 000000000..63a75cdff --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-two-mut-fail.rs @@ -0,0 +1,59 @@ +// Tests that two closures cannot simultaneously have mutable +// access to the variable, whether that mutable access be used +// for direct assignment or for taking mutable ref. Issue #6801. + + + + + + + +fn to_fn_mut(f: F) -> F { f } + +fn a() { + let mut x = 3; + let c1 = to_fn_mut(|| x = 4); + let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once + c1; +} + +fn set(x: &mut isize) { + *x = 4; +} + +fn b() { + let mut x = 3; + let c1 = to_fn_mut(|| set(&mut x)); + let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once + c1; +} + +fn c() { + let mut x = 3; + let c1 = to_fn_mut(|| x = 5); + let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once + c1; +} + +fn d() { + let mut x = 3; + let c1 = to_fn_mut(|| x = 5); + let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) + //~^ ERROR cannot borrow `x` as mutable more than once + c1; +} + +fn g() { + struct Foo { + f: Box + } + + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); + let c1 = to_fn_mut(|| set(&mut *x.f)); + let c2 = to_fn_mut(|| set(&mut *x.f)); + //~^ ERROR cannot borrow `x` as mutable more than once + c1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-closures-two-mut-fail.stderr b/tests/ui/borrowck/borrowck-closures-two-mut-fail.stderr new file mode 100644 index 000000000..fe8e7a29e --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-two-mut-fail.stderr @@ -0,0 +1,75 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut-fail.rs:16:24 + | +LL | let c1 = to_fn_mut(|| x = 4); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| x = 5); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | c1; + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut-fail.rs:27:24 + | +LL | let c1 = to_fn_mut(|| set(&mut x)); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| set(&mut x)); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | c1; + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut-fail.rs:34:24 + | +LL | let c1 = to_fn_mut(|| x = 5); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| set(&mut x)); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | c1; + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut-fail.rs:41:24 + | +LL | let c1 = to_fn_mut(|| x = 5); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | +LL | c1; + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut-fail.rs:53:24 + | +LL | let c1 = to_fn_mut(|| set(&mut *x.f)); + | -- ---- first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| set(&mut *x.f)); + | ^^ ---- second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | +LL | c1; + | -- first borrow later used here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-closures-two-mut.rs b/tests/ui/borrowck/borrowck-closures-two-mut.rs new file mode 100644 index 000000000..cdff8f9e8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-two-mut.rs @@ -0,0 +1,55 @@ +// Tests that two closures cannot simultaneously have mutable +// access to the variable, whether that mutable access be used +// for direct assignment or for taking mutable ref. Issue #6801. + + + +fn to_fn_mut(f: F) -> F { f } + +fn a() { + let mut x = 3; + let c1 = to_fn_mut(|| x = 4); + let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); +} + +fn set(x: &mut isize) { + *x = 4; +} + +fn b() { + let mut x = 3; + let c1 = to_fn_mut(|| set(&mut x)); + let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); +} + +fn c() { + let mut x = 3; + let c1 = to_fn_mut(|| x = 5); + let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); +} + +fn d() { + let mut x = 3; + let c1 = to_fn_mut(|| x = 5); + let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) + //~^ ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); +} + +fn g() { + struct Foo { + f: Box + } + + let mut x: Box<_> = Box::new(Foo { f: Box::new(3) }); + let c1 = to_fn_mut(|| set(&mut *x.f)); + let c2 = to_fn_mut(|| set(&mut *x.f)); + //~^ ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-closures-two-mut.stderr b/tests/ui/borrowck/borrowck-closures-two-mut.stderr new file mode 100644 index 000000000..21e329f43 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-two-mut.stderr @@ -0,0 +1,75 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut.rs:12:24 + | +LL | let c1 = to_fn_mut(|| x = 4); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| x = 5); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | drop((c1, c2)); + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut.rs:23:24 + | +LL | let c1 = to_fn_mut(|| set(&mut x)); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| set(&mut x)); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | drop((c1, c2)); + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut.rs:30:24 + | +LL | let c1 = to_fn_mut(|| x = 5); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| set(&mut x)); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | drop((c1, c2)); + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut.rs:37:24 + | +LL | let c1 = to_fn_mut(|| x = 5); + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | +LL | drop((c1, c2)); + | -- first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-closures-two-mut.rs:49:24 + | +LL | let c1 = to_fn_mut(|| set(&mut *x.f)); + | -- ---- first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let c2 = to_fn_mut(|| set(&mut *x.f)); + | ^^ ---- second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | +LL | drop((c1, c2)); + | -- first borrow later used here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-closures-unique-imm.rs b/tests/ui/borrowck/borrowck-closures-unique-imm.rs new file mode 100644 index 000000000..0dd004769 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-unique-imm.rs @@ -0,0 +1,18 @@ +struct Foo { + x: isize, +} + +pub fn main() { + let mut this = &mut Foo { + x: 1, + }; + let mut r = || { + let p = &this.x; + &mut this.x; //~ ERROR cannot borrow + p.use_ref(); + }; + r() +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-closures-unique-imm.stderr b/tests/ui/borrowck/borrowck-closures-unique-imm.stderr new file mode 100644 index 000000000..0c5fd39b7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-unique-imm.stderr @@ -0,0 +1,13 @@ +error[E0502]: cannot borrow `this.x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-unique-imm.rs:11:9 + | +LL | let p = &this.x; + | ------- immutable borrow occurs here +LL | &mut this.x; + | ^^^^^^^^^^^ mutable borrow occurs here +LL | p.use_ref(); + | ----------- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-closures-unique.rs b/tests/ui/borrowck/borrowck-closures-unique.rs new file mode 100644 index 000000000..67f91dfa8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-unique.rs @@ -0,0 +1,54 @@ +// Tests that a closure which requires mutable access to the referent +// of an `&mut` requires a "unique" borrow -- that is, the variable to +// be borrowed (here, `x`) will not be borrowed *mutably*, but +// may be *immutable*, but we cannot allow +// multiple borrows. + + + +fn get(x: &isize) -> isize { + *x +} + +fn set(x: &mut isize) -> isize { + *x +} + +fn a(x: &mut isize) { + let c1 = || get(x); + let c2 = || get(x); + c1(); + c2(); +} + +fn b(x: &mut isize) { + let c1 = || get(x); + let c2 = || set(x); //~ ERROR closure requires unique access to `x` + c1; +} + +fn c(x: &mut isize) { + let c1 = || get(x); + let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x` + c1; +} + +fn d(x: &mut isize) { + let c1 = || set(x); + let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time + c1; +} + +fn e(x: &'static mut isize) { + let c1 = |y: &'static mut isize| x = y; + //~^ ERROR cannot assign to `x`, as it is not declared as mutable + c1; +} + +fn f(x: &'static mut isize) { + let c1 = || x = panic!(); // OK assignment is unreachable. + c1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-closures-unique.stderr b/tests/ui/borrowck/borrowck-closures-unique.stderr new file mode 100644 index 000000000..23d3cc0e7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-unique.stderr @@ -0,0 +1,54 @@ +error[E0500]: closure requires unique access to `x` but it is already borrowed + --> $DIR/borrowck-closures-unique.rs:26:14 + | +LL | let c1 = || get(x); + | -- - first borrow occurs due to use of `x` in closure + | | + | borrow occurs here +LL | let c2 = || set(x); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | c1; + | -- first borrow later used here + +error[E0500]: closure requires unique access to `x` but it is already borrowed + --> $DIR/borrowck-closures-unique.rs:32:14 + | +LL | let c1 = || get(x); + | -- - first borrow occurs due to use of `x` in closure + | | + | borrow occurs here +LL | let c2 = || { get(x); set(x); }; + | ^^ - second borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | c1; + | -- first borrow later used here + +error[E0524]: two closures require unique access to `x` at the same time + --> $DIR/borrowck-closures-unique.rs:38:14 + | +LL | let c1 = || set(x); + | -- - first borrow occurs due to use of `x` in closure + | | + | first closure is constructed here +LL | let c2 = || set(x); + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second closure is constructed here +LL | c1; + | -- first borrow later used here + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/borrowck-closures-unique.rs:43:38 + | +LL | fn e(x: &'static mut isize) { + | - help: consider changing this to be mutable: `mut x` +LL | let c1 = |y: &'static mut isize| x = y; + | ^^^^^ cannot assign + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0500, E0524, E0594. +For more information about an error, try `rustc --explain E0500`. diff --git a/tests/ui/borrowck/borrowck-closures-use-after-free.rs b/tests/ui/borrowck/borrowck-closures-use-after-free.rs new file mode 100644 index 000000000..be5f1f873 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-use-after-free.rs @@ -0,0 +1,23 @@ +// Tests that a closure which mutates a local variable +// cannot also be supplied a borrowed version of that +// variable's contents. Issue #11192. + +struct Foo { + x: isize +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("drop {}", self.x); + } +} + + + +fn main() { + let mut ptr: Box<_> = Box::new(Foo { x: 0 }); + let mut test = |foo: &Foo| { + ptr = Box::new(Foo { x: ptr.x + 1 }); + }; + test(&*ptr); //~ ERROR cannot borrow `*ptr` +} diff --git a/tests/ui/borrowck/borrowck-closures-use-after-free.stderr b/tests/ui/borrowck/borrowck-closures-use-after-free.stderr new file mode 100644 index 000000000..30900a3b6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-closures-use-after-free.stderr @@ -0,0 +1,16 @@ +error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-closures-use-after-free.rs:22:8 + | +LL | let mut test = |foo: &Foo| { + | ----------- mutable borrow occurs here +LL | ptr = Box::new(Foo { x: ptr.x + 1 }); + | --- first borrow occurs due to use of `ptr` in closure +LL | }; +LL | test(&*ptr); + | ---- ^^^^^ immutable borrow occurs here + | | + | mutable borrow later used by call + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-consume-unsize-vec.rs b/tests/ui/borrowck/borrowck-consume-unsize-vec.rs new file mode 100644 index 000000000..347f0212c --- /dev/null +++ b/tests/ui/borrowck/borrowck-consume-unsize-vec.rs @@ -0,0 +1,12 @@ +// Check that we report an error if an upcast box is moved twice. + +fn consume(_: Box<[i32]>) { +} + +fn foo(b: Box<[i32;5]>) { + consume(b); + consume(b); //~ ERROR use of moved value +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr b/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr new file mode 100644 index 000000000..d2e9497d0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-consume-unsize-vec.stderr @@ -0,0 +1,25 @@ +error[E0382]: use of moved value: `b` + --> $DIR/borrowck-consume-unsize-vec.rs:8:13 + | +LL | fn foo(b: Box<[i32;5]>) { + | - move occurs because `b` has type `Box<[i32; 5]>`, which does not implement the `Copy` trait +LL | consume(b); + | - value moved here +LL | consume(b); + | ^ value used here after move + | +note: consider changing this parameter type in function `consume` to borrow instead if owning the value isn't necessary + --> $DIR/borrowck-consume-unsize-vec.rs:3:15 + | +LL | fn consume(_: Box<[i32]>) { + | ------- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | consume(b.clone()); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-consume-upcast-box.rs b/tests/ui/borrowck/borrowck-consume-upcast-box.rs new file mode 100644 index 000000000..6b32d185b --- /dev/null +++ b/tests/ui/borrowck/borrowck-consume-upcast-box.rs @@ -0,0 +1,14 @@ +// Check that we report an error if an upcast box is moved twice. + +trait Foo { fn dummy(&self); } + +fn consume(_: Box) { +} + +fn foo(b: Box) { + consume(b); + consume(b); //~ ERROR use of moved value +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-consume-upcast-box.stderr b/tests/ui/borrowck/borrowck-consume-upcast-box.stderr new file mode 100644 index 000000000..ed7e883ca --- /dev/null +++ b/tests/ui/borrowck/borrowck-consume-upcast-box.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `b` + --> $DIR/borrowck-consume-upcast-box.rs:10:13 + | +LL | fn foo(b: Box) { + | - move occurs because `b` has type `Box`, which does not implement the `Copy` trait +LL | consume(b); + | - value moved here +LL | consume(b); + | ^ value used here after move + | +note: consider changing this parameter type in function `consume` to borrow instead if owning the value isn't necessary + --> $DIR/borrowck-consume-upcast-box.rs:5:15 + | +LL | fn consume(_: Box) { + | ------- ^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.rs b/tests/ui/borrowck/borrowck-describe-lvalue.rs new file mode 100644 index 000000000..cdcff69d6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-describe-lvalue.rs @@ -0,0 +1,279 @@ +pub struct Foo { + x: u32 +} + +pub struct Bar(u32); + +pub enum Baz { + X(u32) +} + +union U { + a: u8, + b: u64, +} + +impl Foo { + fn x(&mut self) -> &mut u32 { &mut self.x } +} + +impl Bar { + fn x(&mut self) -> &mut u32 { &mut self.0 } +} + +impl Baz { + fn x(&mut self) -> &mut u32 { + match *self { + Baz::X(ref mut value) => value + } + } +} + +fn main() { + // Local and field from struct + { + let mut f = Foo { x: 22 }; + let x = f.x(); + f.x; //~ ERROR cannot use `f.x` because it was mutably borrowed + drop(x); + } + // Local and field from tuple-struct + { + let mut g = Bar(22); + let x = g.x(); + g.0; //~ ERROR cannot use `g.0` because it was mutably borrowed + drop(x); + } + // Local and field from tuple + { + let mut h = (22, 23); + let x = &mut h.0; + h.0; //~ ERROR cannot use `h.0` because it was mutably borrowed + drop(x); + } + // Local and field from enum + { + let mut e = Baz::X(2); + let x = e.x(); + match e { + Baz::X(value) => value //~ ERROR cannot use `e.0` because it was mutably borrowed + }; + drop(x); + } + // Local and field from union + unsafe { + let mut u = U { b: 0 }; + let x = &mut u.a; + u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed + drop(x); + } + // Deref and field from struct + { + let mut f = Box::new(Foo { x: 22 }); + let x = f.x(); + f.x; //~ ERROR cannot use `f.x` because it was mutably borrowed + drop(x); + } + // Deref and field from tuple-struct + { + let mut g = Box::new(Bar(22)); + let x = g.x(); + g.0; //~ ERROR cannot use `g.0` because it was mutably borrowed + drop(x); + } + // Deref and field from tuple + { + let mut h = Box::new((22, 23)); + let x = &mut h.0; + h.0; //~ ERROR cannot use `h.0` because it was mutably borrowed + drop(x); + } + // Deref and field from enum + { + let mut e = Box::new(Baz::X(3)); + let x = e.x(); + match *e { + Baz::X(value) => value + //~^ ERROR cannot use `e.0` because it was mutably borrowed + }; + drop(x); + } + // Deref and field from union + unsafe { + let mut u = Box::new(U { b: 0 }); + let x = &mut u.a; + u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed + drop(x); + } + // Constant index + { + let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let x = &mut v; + match v { + &[x, _, .., _, _] => println!("{}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + match v { + &[_, x, .., _, _] => println!("{}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + match v { + &[_, _, .., x, _] => println!("{}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + match v { + &[_, _, .., _, x] => println!("{}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + drop(x); + } + // Subslices + { + let mut v = &[1, 2, 3, 4, 5]; + let x = &mut v; + match v { + &[x @ ..] => println!("{:?}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + match v { + &[_, x @ ..] => println!("{:?}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + match v { + &[x @ .., _] => println!("{:?}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + match v { + &[_, x @ .., _] => println!("{:?}", x), + //~^ ERROR cannot use `v[..]` because it was mutably borrowed + _ => panic!("other case"), + } + drop(x); + } + // Downcasted field + { + enum E { A(X), B { x: X } } + + let mut e = E::A(3); + let x = &mut e; + match e { + //~^ ERROR cannot use `e` because it was mutably borrowed + E::A(ref ax) => + //~^ ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable + println!("e.ax: {:?}", ax), + E::B { x: ref bx } => + //~^ ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable + println!("e.bx: {:?}", bx), + } + drop(x); + } + // Field in field + { + struct F { x: u32, y: u32 }; + struct S { x: F, y: (u32, u32), }; + let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) }; + let x = &mut s; + match s { + S { y: (ref y0, _), .. } => + //~^ ERROR cannot borrow `s.y.0` as immutable because it is also borrowed as mutable + println!("y0: {:?}", y0), + _ => panic!("other case"), + } + match s { + S { x: F { y: ref x0, .. }, .. } => + //~^ ERROR cannot borrow `s.x.y` as immutable because it is also borrowed as mutable + println!("x0: {:?}", x0), + _ => panic!("other case"), + } + drop(x); + } + // Field of ref + { + struct Block<'a> { + current: &'a u8, + unrelated: &'a u8, + }; + + fn bump<'a>(mut block: &mut Block<'a>) { + let x = &mut block; + let p: &'a u8 = &*block.current; + //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable + // See issue rust#38899 + drop(x); + } + } + // Field of ptr + { + struct Block2 { + current: *const u8, + unrelated: *const u8, + } + + unsafe fn bump2(mut block: *mut Block2) { + let x = &mut block; + let p : *const u8 = &*(*block).current; + //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable + // See issue rust#38899 + drop(x); + } + } + // Field of index + { + struct F {x: u32, y: u32}; + let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; + let x = &mut v; + v[0].y; + //~^ ERROR cannot use `v[_].y` because it was mutably borrowed + //~| ERROR cannot use `*v` because it was mutably borrowed + drop(x); + } + // Field of constant index + { + struct F {x: u32, y: u32}; + let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; + let x = &mut v; + match v { + &[_, F {x: ref xf, ..}] => println!("{}", xf), + //~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable + _ => panic!("other case") + } + drop(x); + } + // Field from upvar + { + let mut x = 0; + || { + let y = &mut x; + &mut x; //~ ERROR cannot borrow `x` as mutable more than once at a time + *y = 1; + }; + } + // Field from upvar nested + { + let mut x = 0; + || { + || { //~ ERROR captured variable cannot escape `FnMut` closure body + let y = &mut x; + &mut x; //~ ERROR cannot borrow `x` as mutable more than once at a time + *y = 1; + drop(y); + } + }; + } + { + fn foo(x: Vec) { + let c = || { + drop(x); + drop(x); //~ ERROR use of moved value: `x` + }; + c(); + } + } +} diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.stderr b/tests/ui/borrowck/borrowck-describe-lvalue.stderr new file mode 100644 index 000000000..2c1b9c10d --- /dev/null +++ b/tests/ui/borrowck/borrowck-describe-lvalue.stderr @@ -0,0 +1,372 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-describe-lvalue.rs:254:13 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +LL | &mut x; + | ^^^^^^ second mutable borrow occurs here +LL | *y = 1; + | ------ first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-describe-lvalue.rs:264:20 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +LL | &mut x; + | ^^^^^^ second mutable borrow occurs here +LL | *y = 1; + | ------ first borrow later used here + +error: captured variable cannot escape `FnMut` closure body + --> $DIR/borrowck-describe-lvalue.rs:262:16 + | +LL | let mut x = 0; + | ----- variable defined here +LL | || { + | - inferred to be a `FnMut` closure +LL | / || { +LL | | let y = &mut x; + | | - variable captured here +LL | | &mut x; +LL | | *y = 1; +LL | | drop(y); +LL | | } + | |_________________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape +help: consider adding 'move' keyword before the nested closure + | +LL | move || { + | ++++ + +error[E0503]: cannot use `f.x` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:37:9 + | +LL | let x = f.x(); + | ----- borrow of `f` occurs here +LL | f.x; + | ^^^ use of borrowed `f` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `g.0` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:44:9 + | +LL | let x = g.x(); + | ----- borrow of `g` occurs here +LL | g.0; + | ^^^ use of borrowed `g` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `h.0` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:51:9 + | +LL | let x = &mut h.0; + | -------- borrow of `h.0` occurs here +LL | h.0; + | ^^^ use of borrowed `h.0` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `e.0` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:59:20 + | +LL | let x = e.x(); + | ----- borrow of `e` occurs here +LL | match e { +LL | Baz::X(value) => value + | ^^^^^ use of borrowed `e` +LL | }; +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `u.a` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:67:9 + | +LL | let x = &mut u.a; + | -------- borrow of `u.a` occurs here +LL | u.a; + | ^^^ use of borrowed `u.a` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `f.x` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:74:9 + | +LL | let x = f.x(); + | ----- borrow of `*f` occurs here +LL | f.x; + | ^^^ use of borrowed `*f` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `g.0` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:81:9 + | +LL | let x = g.x(); + | ----- borrow of `*g` occurs here +LL | g.0; + | ^^^ use of borrowed `*g` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `h.0` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:88:9 + | +LL | let x = &mut h.0; + | -------- borrow of `h.0` occurs here +LL | h.0; + | ^^^ use of borrowed `h.0` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `e.0` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:96:20 + | +LL | let x = e.x(); + | ----- borrow of `*e` occurs here +LL | match *e { +LL | Baz::X(value) => value + | ^^^^^ use of borrowed `*e` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `u.a` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:105:9 + | +LL | let x = &mut u.a; + | -------- borrow of `u.a` occurs here +LL | u.a; + | ^^^ use of borrowed `u.a` +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:113:15 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +LL | match v { +LL | &[x, _, .., _, _] => println!("{}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:118:18 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +... +LL | &[_, x, .., _, _] => println!("{}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:123:25 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +... +LL | &[_, _, .., x, _] => println!("{}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:128:28 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +... +LL | &[_, _, .., _, x] => println!("{}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:139:15 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +LL | match v { +LL | &[x @ ..] => println!("{:?}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:144:18 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +... +LL | &[_, x @ ..] => println!("{:?}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:149:15 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +... +LL | &[x @ .., _] => println!("{:?}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[..]` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:154:18 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +... +LL | &[_, x @ .., _] => println!("{:?}", x), + | ^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `e` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:166:15 + | +LL | let x = &mut e; + | ------ borrow of `e` occurs here +LL | match e { + | ^ use of borrowed `e` +... +LL | drop(x); + | - borrow later used here + +error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:168:18 + | +LL | let x = &mut e; + | ------ mutable borrow occurs here +... +LL | E::A(ref ax) => + | ^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:171:23 + | +LL | let x = &mut e; + | ------ mutable borrow occurs here +... +LL | E::B { x: ref bx } => + | ^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:184:22 + | +LL | let x = &mut s; + | ------ mutable borrow occurs here +LL | match s { +LL | S { y: (ref y0, _), .. } => + | ^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:190:28 + | +LL | let x = &mut s; + | ------ mutable borrow occurs here +... +LL | S { x: F { y: ref x0, .. }, .. } => + | ^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0503]: cannot use `*v` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:232:9 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +LL | v[0].y; + | ^^^^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0503]: cannot use `v[_].y` because it was mutably borrowed + --> $DIR/borrowck-describe-lvalue.rs:232:9 + | +LL | let x = &mut v; + | ------ borrow of `v` occurs here +LL | v[0].y; + | ^^^^^^ use of borrowed `v` +... +LL | drop(x); + | - borrow later used here + +error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:243:24 + | +LL | let x = &mut v; + | ------ mutable borrow occurs here +LL | match v { +LL | &[_, F {x: ref xf, ..}] => println!("{}", xf), + | ^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:206:29 + | +LL | let x = &mut block; + | ---------- mutable borrow occurs here +LL | let p: &'a u8 = &*block.current; + | ^^^^^^^^^^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-describe-lvalue.rs:221:33 + | +LL | let x = &mut block; + | ---------- mutable borrow occurs here +LL | let p : *const u8 = &*(*block).current; + | ^^^^^^^^^^^^^^^^^^ immutable borrow occurs here +... +LL | drop(x); + | - mutable borrow later used here + +error[E0382]: use of moved value: `x` + --> $DIR/borrowck-describe-lvalue.rs:274:22 + | +LL | drop(x); + | - value moved here +LL | drop(x); + | ^ value used here after move + | + = note: move occurs because `x` has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to 32 previous errors + +Some errors have detailed explanations: E0382, E0499, E0502, E0503. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-drop-from-guard.rs b/tests/ui/borrowck/borrowck-drop-from-guard.rs new file mode 100644 index 000000000..0f320af26 --- /dev/null +++ b/tests/ui/borrowck/borrowck-drop-from-guard.rs @@ -0,0 +1,20 @@ +#![feature(if_let_guard)] + +fn foo(_:String) {} + +fn main() +{ + let my_str = "hello".to_owned(); + match Some(42) { + Some(_) if { drop(my_str); false } => {} + Some(_) => {} + None => { foo(my_str); } //~ ERROR [E0382] + } + + let my_str = "hello".to_owned(); + match Some(42) { + Some(_) if let Some(()) = { drop(my_str); None } => {} + Some(_) => {} + None => { foo(my_str); } //~ ERROR [E0382] + } +} diff --git a/tests/ui/borrowck/borrowck-drop-from-guard.stderr b/tests/ui/borrowck/borrowck-drop-from-guard.stderr new file mode 100644 index 000000000..9fa28efd8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-drop-from-guard.stderr @@ -0,0 +1,37 @@ +error[E0382]: use of moved value: `my_str` + --> $DIR/borrowck-drop-from-guard.rs:11:23 + | +LL | let my_str = "hello".to_owned(); + | ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait +LL | match Some(42) { +LL | Some(_) if { drop(my_str); false } => {} + | ------ value moved here +LL | Some(_) => {} +LL | None => { foo(my_str); } + | ^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if { drop(my_str.clone()); false } => {} + | ++++++++ + +error[E0382]: use of moved value: `my_str` + --> $DIR/borrowck-drop-from-guard.rs:18:23 + | +LL | let my_str = "hello".to_owned(); + | ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait +LL | match Some(42) { +LL | Some(_) if let Some(()) = { drop(my_str); None } => {} + | ------ value moved here +LL | Some(_) => {} +LL | None => { foo(my_str); } + | ^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if let Some(()) = { drop(my_str.clone()); None } => {} + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-escaping-closure-error-1.rs b/tests/ui/borrowck/borrowck-escaping-closure-error-1.rs new file mode 100644 index 000000000..11c0610aa --- /dev/null +++ b/tests/ui/borrowck/borrowck-escaping-closure-error-1.rs @@ -0,0 +1,15 @@ +use std::thread::spawn; + +// Test that we give a custom error (E0373) for the case where a +// closure is escaping current frame, and offer a suggested code edit. +// I refrained from including the precise message here, but the +// original text as of the time of this writing is: +// +// closure may outlive the current function, but it borrows `books`, +// which is owned by the current function + +fn main() { + let mut books = vec![1,2,3]; + spawn(|| books.push(4)); + //~^ ERROR E0373 +} diff --git a/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr b/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr new file mode 100644 index 000000000..acf6b37b7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-escaping-closure-error-1.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `books`, which is owned by the current function + --> $DIR/borrowck-escaping-closure-error-1.rs:13:11 + | +LL | spawn(|| books.push(4)); + | ^^ ----- `books` is borrowed here + | | + | may outlive borrowed value `books` + | +note: function requires argument type to outlive `'static` + --> $DIR/borrowck-escaping-closure-error-1.rs:13:5 + | +LL | spawn(|| books.push(4)); + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `books` (and any other referenced variables), use the `move` keyword + | +LL | spawn(move || books.push(4)); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/borrowck/borrowck-escaping-closure-error-2.rs b/tests/ui/borrowck/borrowck-escaping-closure-error-2.rs new file mode 100644 index 000000000..b50d45563 --- /dev/null +++ b/tests/ui/borrowck/borrowck-escaping-closure-error-2.rs @@ -0,0 +1,15 @@ +// Test that we give a custom error (E0373) for the case where a +// closure is escaping current frame, and offer a suggested code edit. +// I refrained from including the precise message here, but the +// original text as of the time of this writing is: +// +// closure may outlive the current function, but it borrows `books`, +// which is owned by the current function + +fn foo<'a>(x: &'a i32) -> Box { + let mut books = vec![1,2,3]; + Box::new(|| books.push(4)) + //~^ ERROR E0373 +} + +fn main() { } diff --git a/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr b/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr new file mode 100644 index 000000000..814042539 --- /dev/null +++ b/tests/ui/borrowck/borrowck-escaping-closure-error-2.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `books`, which is owned by the current function + --> $DIR/borrowck-escaping-closure-error-2.rs:11:14 + | +LL | Box::new(|| books.push(4)) + | ^^ ----- `books` is borrowed here + | | + | may outlive borrowed value `books` + | +note: closure is returned here + --> $DIR/borrowck-escaping-closure-error-2.rs:11:5 + | +LL | Box::new(|| books.push(4)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `books` (and any other referenced variables), use the `move` keyword + | +LL | Box::new(move || books.push(4)) + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs new file mode 100644 index 000000000..dd6708582 --- /dev/null +++ b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs @@ -0,0 +1,264 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct A { a: isize, b: Box } +struct B { a: Box, b: Box } + +fn move_after_copy() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.a); + drop(x.b); +} + +fn move_after_fu_copy() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { b: Box::new(3), .. x }; + drop(x.b); +} + +fn fu_move_after_copy() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.a); + let _y = A { a: 3, .. x }; +} + +fn fu_move_after_fu_copy() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { b: Box::new(3), .. x }; + let _z = A { a: 4, .. x }; +} + +fn copy_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + drop(x.a); +} + +fn copy_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let y = A { a: 3, .. x }; + drop(x.a); +} + +fn fu_copy_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + let _y = A { b: Box::new(3), .. x }; +} + +fn fu_copy_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + let _z = A { b: Box::new(3), .. x }; +} + +fn borrow_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + let p = &x.a; + drop(*p); +} + +fn borrow_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + let p = &x.a; + drop(*p); +} + +fn move_after_borrow() { + let x = A { a: 1, b: Box::new(2) }; + let p = &x.a; + drop(x.b); + drop(*p); +} + +fn fu_move_after_borrow() { + let x = A { a: 1, b: Box::new(2) }; + let p = &x.a; + let _y = A { a: 3, .. x }; + drop(*p); +} + +fn mut_borrow_after_mut_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.a; + let q = &mut x.b; + drop(*p); + drop(**q); +} + +fn move_after_move() { + let x = B { a: Box::new(1), b: Box::new(2) }; + drop(x.a); + drop(x.b); +} + +fn move_after_fu_move() { + let x = B { a: Box::new(1), b: Box::new(2) }; + let y = B { a: Box::new(3), .. x }; + drop(x.a); +} + +fn fu_move_after_move() { + let x = B { a: Box::new(1), b: Box::new(2) }; + drop(x.a); + let z = B { a: Box::new(3), .. x }; + drop(z.b); +} + +fn fu_move_after_fu_move() { + let x = B { a: Box::new(1), b: Box::new(2) }; + let _y = B { b: Box::new(3), .. x }; + let _z = B { a: Box::new(4), .. x }; +} + +fn copy_after_assign_after_move() { + let mut x = A { a: 1, b: Box::new(2) }; + drop(x.b); + x = A { a: 3, b: Box::new(4) }; + drop(*x.b); +} + +fn copy_after_assign_after_fu_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + x = A { a: 3, b: Box::new(4) }; + drop(*x.b); +} + +fn copy_after_field_assign_after_move() { + let mut x = A { a: 1, b: Box::new(2) }; + drop(x.b); + x.b = Box::new(3); + drop(*x.b); +} + +fn copy_after_field_assign_after_fu_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + x.b = Box::new(3); + drop(*x.b); +} + +fn borrow_after_assign_after_move() { + let mut x = A { a: 1, b: Box::new(2) }; + drop(x.b); + x = A { a: 3, b: Box::new(4) }; + let p = &x.b; + drop(**p); +} + +fn borrow_after_assign_after_fu_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + x = A { a: 3, b: Box::new(4) }; + let p = &x.b; + drop(**p); +} + +fn borrow_after_field_assign_after_move() { + let mut x = A { a: 1, b: Box::new(2) }; + drop(x.b); + x.b = Box::new(3); + let p = &x.b; + drop(**p); +} + +fn borrow_after_field_assign_after_fu_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + x.b = Box::new(3); + let p = &x.b; + drop(**p); +} + +fn move_after_assign_after_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = x.b; + x = A { a: 3, b: Box::new(4) }; + drop(x.b); +} + +fn move_after_assign_after_fu_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + x = A { a: 3, b: Box::new(4) }; + drop(x.b); +} + +fn move_after_field_assign_after_move() { + let mut x = A { a: 1, b: Box::new(2) }; + drop(x.b); + x.b = Box::new(3); + drop(x.b); +} + +fn move_after_field_assign_after_fu_move() { + let mut x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + x.b = Box::new(3); + drop(x.b); +} + +fn copy_after_assign_after_uninit() { + let mut x: A; + x = A { a: 1, b: Box::new(2) }; + drop(x.a); +} + +fn borrow_after_assign_after_uninit() { + let mut x: A; + x = A { a: 1, b: Box::new(2) }; + let p = &x.a; + drop(*p); +} + +fn move_after_assign_after_uninit() { + let mut x: A; + x = A { a: 1, b: Box::new(2) }; + drop(x.b); +} + +fn main() { + move_after_copy(); + move_after_fu_copy(); + fu_move_after_copy(); + fu_move_after_fu_copy(); + copy_after_move(); + copy_after_fu_move(); + fu_copy_after_move(); + fu_copy_after_fu_move(); + + borrow_after_move(); + borrow_after_fu_move(); + move_after_borrow(); + fu_move_after_borrow(); + mut_borrow_after_mut_borrow(); + + move_after_move(); + move_after_fu_move(); + fu_move_after_move(); + fu_move_after_fu_move(); + + copy_after_assign_after_move(); + copy_after_assign_after_fu_move(); + copy_after_field_assign_after_move(); + copy_after_field_assign_after_fu_move(); + + borrow_after_assign_after_move(); + borrow_after_assign_after_fu_move(); + borrow_after_field_assign_after_move(); + borrow_after_field_assign_after_fu_move(); + + move_after_assign_after_move(); + move_after_assign_after_fu_move(); + move_after_field_assign_after_move(); + move_after_field_assign_after_fu_move(); + + copy_after_assign_after_uninit(); + borrow_after_assign_after_uninit(); + move_after_assign_after_uninit(); +} diff --git a/tests/ui/borrowck/borrowck-field-sensitivity.rs b/tests/ui/borrowck/borrowck-field-sensitivity.rs new file mode 100644 index 000000000..03edf445e --- /dev/null +++ b/tests/ui/borrowck/borrowck-field-sensitivity.rs @@ -0,0 +1,116 @@ +struct A { a: isize, b: Box } + + + +fn deref_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + drop(*x.b); //~ ERROR use of moved value: `x.b` +} + +fn deref_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let y = A { a: 3, .. x }; + drop(*x.b); //~ ERROR use of moved value: `x.b` +} + +fn borrow_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + let p = &x.b; //~ ERROR borrow of moved value: `x.b` + drop(**p); +} + +fn borrow_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + let p = &x.b; //~ ERROR borrow of moved value: `x.b` + drop(**p); +} + +fn move_after_borrow() { + let x = A { a: 1, b: Box::new(2) }; + let p = &x.b; + drop(x.b); //~ ERROR cannot move out of `x.b` because it is borrowed + drop(**p); +} + +fn fu_move_after_borrow() { + let x = A { a: 1, b: Box::new(2) }; + let p = &x.b; + let _y = A { a: 3, .. x }; //~ ERROR cannot move out of `x.b` because it is borrowed + drop(**p); +} + +fn mut_borrow_after_mut_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.a; + let q = &mut x.a; //~ ERROR cannot borrow `x.a` as mutable more than once at a time + drop(*p); + drop(*q); +} + +fn move_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + drop(x.b); //~ ERROR use of moved value: `x.b` +} + +fn move_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + drop(x.b); //~ ERROR use of moved value: `x.b` +} + +fn fu_move_after_move() { + let x = A { a: 1, b: Box::new(2) }; + drop(x.b); + let _z = A { a: 3, .. x }; //~ ERROR use of moved value: `x.b` +} + +fn fu_move_after_fu_move() { + let x = A { a: 1, b: Box::new(2) }; + let _y = A { a: 3, .. x }; + let _z = A { a: 4, .. x }; //~ ERROR use of moved value: `x.b` +} + +// The following functions aren't yet accepted, but they should be. + +fn copy_after_field_assign_after_uninit() { + let mut x: A; + x.a = 1; //~ ERROR E0381 + drop(x.a); +} + +fn borrow_after_field_assign_after_uninit() { + let mut x: A; + x.a = 1; //~ ERROR E0381 + let p = &x.a; + drop(*p); +} + +fn move_after_field_assign_after_uninit() { + let mut x: A; + x.b = Box::new(1); //~ ERROR E0381 + drop(x.b); +} + +fn main() { + deref_after_move(); + deref_after_fu_move(); + + borrow_after_move(); + borrow_after_fu_move(); + move_after_borrow(); + fu_move_after_borrow(); + mut_borrow_after_mut_borrow(); + + move_after_move(); + move_after_fu_move(); + fu_move_after_move(); + fu_move_after_fu_move(); + + copy_after_field_assign_after_uninit(); + borrow_after_field_assign_after_uninit(); + move_after_field_assign_after_uninit(); +} diff --git a/tests/ui/borrowck/borrowck-field-sensitivity.stderr b/tests/ui/borrowck/borrowck-field-sensitivity.stderr new file mode 100644 index 000000000..e009f5913 --- /dev/null +++ b/tests/ui/borrowck/borrowck-field-sensitivity.stderr @@ -0,0 +1,144 @@ +error[E0382]: use of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:8:10 + | +LL | drop(x.b); + | --- value moved here +LL | drop(*x.b); + | ^^^^ value used here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:14:10 + | +LL | let y = A { a: 3, .. x }; + | ---------------- value moved here +LL | drop(*x.b); + | ^^^^ value used here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:20:13 + | +LL | drop(x.b); + | --- value moved here +LL | let p = &x.b; + | ^^^^ value borrowed here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:27:13 + | +LL | let _y = A { a: 3, .. x }; + | ---------------- value moved here +LL | let p = &x.b; + | ^^^^ value borrowed here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0505]: cannot move out of `x.b` because it is borrowed + --> $DIR/borrowck-field-sensitivity.rs:34:10 + | +LL | let p = &x.b; + | ---- borrow of `x.b` occurs here +LL | drop(x.b); + | ^^^ move out of `x.b` occurs here +LL | drop(**p); + | --- borrow later used here + +error[E0505]: cannot move out of `x.b` because it is borrowed + --> $DIR/borrowck-field-sensitivity.rs:41:14 + | +LL | let p = &x.b; + | ---- borrow of `x.b` occurs here +LL | let _y = A { a: 3, .. x }; + | ^^^^^^^^^^^^^^^^ move out of `x.b` occurs here +LL | drop(**p); + | --- borrow later used here + +error[E0499]: cannot borrow `x.a` as mutable more than once at a time + --> $DIR/borrowck-field-sensitivity.rs:48:13 + | +LL | let p = &mut x.a; + | -------- first mutable borrow occurs here +LL | let q = &mut x.a; + | ^^^^^^^^ second mutable borrow occurs here +LL | drop(*p); + | -- first borrow later used here + +error[E0382]: use of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:56:10 + | +LL | drop(x.b); + | --- value moved here +LL | drop(x.b); + | ^^^ value used here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:62:10 + | +LL | let _y = A { a: 3, .. x }; + | ---------------- value moved here +LL | drop(x.b); + | ^^^ value used here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:68:14 + | +LL | drop(x.b); + | --- value moved here +LL | let _z = A { a: 3, .. x }; + | ^^^^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x.b` + --> $DIR/borrowck-field-sensitivity.rs:74:14 + | +LL | let _y = A { a: 3, .. x }; + | ---------------- value moved here +LL | let _z = A { a: 4, .. x }; + | ^^^^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `x.b` has type `Box`, which does not implement the `Copy` trait + +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/borrowck-field-sensitivity.rs:81:5 + | +LL | let mut x: A; + | ----- binding declared here but left uninitialized +LL | x.a = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/borrowck-field-sensitivity.rs:87:5 + | +LL | let mut x: A; + | ----- binding declared here but left uninitialized +LL | x.a = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/borrowck-field-sensitivity.rs:94:5 + | +LL | let mut x: A; + | ----- binding declared here but left uninitialized +LL | x.b = Box::new(1); + | ^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0381, E0382, E0499, E0505. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-fixed-length-vecs.rs b/tests/ui/borrowck/borrowck-fixed-length-vecs.rs new file mode 100644 index 000000000..126323d8d --- /dev/null +++ b/tests/ui/borrowck/borrowck-fixed-length-vecs.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let x = [22]; + let y = &x[0]; + assert_eq!(*y, 22); +} diff --git a/tests/ui/borrowck/borrowck-fn-in-const-a.rs b/tests/ui/borrowck/borrowck-fn-in-const-a.rs new file mode 100644 index 000000000..d4ceae296 --- /dev/null +++ b/tests/ui/borrowck/borrowck-fn-in-const-a.rs @@ -0,0 +1,12 @@ +// Check that we check fns appearing in constant declarations. +// Issue #22382. + +const MOVE: fn(&String) -> String = { + fn broken(x: &String) -> String { + return *x //~ ERROR cannot move + } + broken +}; + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-fn-in-const-a.stderr b/tests/ui/borrowck/borrowck-fn-in-const-a.stderr new file mode 100644 index 000000000..e7491afda --- /dev/null +++ b/tests/ui/borrowck/borrowck-fn-in-const-a.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*x` which is behind a shared reference + --> $DIR/borrowck-fn-in-const-a.rs:6:16 + | +LL | return *x + | ^^ move occurs because `*x` has type `String`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-fn-in-const-c.rs b/tests/ui/borrowck/borrowck-fn-in-const-c.rs new file mode 100644 index 000000000..c638cd08b --- /dev/null +++ b/tests/ui/borrowck/borrowck-fn-in-const-c.rs @@ -0,0 +1,23 @@ +// Check that we check fns appearing in constant declarations. +// Issue #22382. + +// Returning local references? +struct DropString { + inner: String +} +impl Drop for DropString { + fn drop(&mut self) { + self.inner.clear(); + self.inner.push_str("dropped"); + } +} +const LOCAL_REF: fn() -> &'static str = { + fn broken() -> &'static str { + let local = DropString { inner: format!("Some local string") }; + return &local.inner; //~ borrow may still be in use when destructor runs + } + broken +}; + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-fn-in-const-c.stderr b/tests/ui/borrowck/borrowck-fn-in-const-c.stderr new file mode 100644 index 000000000..d48866dce --- /dev/null +++ b/tests/ui/borrowck/borrowck-fn-in-const-c.stderr @@ -0,0 +1,11 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/borrowck-fn-in-const-c.rs:17:16 + | +LL | return &local.inner; + | ^^^^^^^^^^^^ returning this value requires that `local.inner` is borrowed for `'static` +LL | } + | - here, drop of `local` needs exclusive access to `local.inner`, because the type `DropString` implements the `Drop` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs new file mode 100644 index 000000000..389b8a43c --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs @@ -0,0 +1,24 @@ +// Issue #16205. + + + +struct Foo { + a: [Box; 3], +} + +fn main() { + let mut y = 1; + let x = Some(&mut y); + for &a in x.iter() { //~ ERROR cannot move out + } + + let f = Foo { + a: [Box::new(3), Box::new(4), Box::new(5)], + }; + for &a in &f.a { //~ ERROR cannot move out + } + + let x: Option> = Some(Box::new(1)); + for &a in x.iter() { //~ ERROR cannot move out + } +} diff --git a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr new file mode 100644 index 000000000..f9ced03e0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr @@ -0,0 +1,48 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15 + | +LL | for &a in x.iter() { + | - ^^^^^^^^ + | | + | data moved here + | move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - for &a in x.iter() { +LL + for a in x.iter() { + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15 + | +LL | for &a in &f.a { + | - ^^^^ + | | + | data moved here + | move occurs because `a` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - for &a in &f.a { +LL + for a in &f.a { + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15 + | +LL | for &a in x.iter() { + | - ^^^^^^^^ + | | + | data moved here + | move occurs because `a` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - for &a in x.iter() { +LL + for a in x.iter() { + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-for-loop-head-linkage.rs b/tests/ui/borrowck/borrowck-for-loop-head-linkage.rs new file mode 100644 index 000000000..a84b695aa --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-head-linkage.rs @@ -0,0 +1,10 @@ +use std::iter::repeat; + +fn main() { + let mut vector = vec![1, 2]; + for &x in &vector { + let cap = vector.capacity(); + vector.extend(repeat(0)); //~ ERROR cannot borrow + vector[1] = 5; //~ ERROR cannot borrow + } +} diff --git a/tests/ui/borrowck/borrowck-for-loop-head-linkage.stderr b/tests/ui/borrowck/borrowck-for-loop-head-linkage.stderr new file mode 100644 index 000000000..f47dce453 --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-head-linkage.stderr @@ -0,0 +1,27 @@ +error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-for-loop-head-linkage.rs:7:9 + | +LL | for &x in &vector { + | ------- + | | + | immutable borrow occurs here + | immutable borrow later used here +LL | let cap = vector.capacity(); +LL | vector.extend(repeat(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here + +error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-for-loop-head-linkage.rs:8:9 + | +LL | for &x in &vector { + | ------- + | | + | immutable borrow occurs here + | immutable borrow later used here +... +LL | vector[1] = 5; + | ^^^^^^ mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs b/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs new file mode 100644 index 000000000..f619c045b --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs @@ -0,0 +1,7 @@ +fn f() -> isize { + let mut x: isize; + for _ in 0..0 { x = 10; } + return x; //~ ERROR E0381 +} + +fn main() { f(); } diff --git a/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr b/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr new file mode 100644 index 000000000..fc1a44c3c --- /dev/null +++ b/tests/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr @@ -0,0 +1,13 @@ +error[E0381]: used binding `x` is possibly-uninitialized + --> $DIR/borrowck-for-loop-uninitialized-binding.rs:4:12 + | +LL | let mut x: isize; + | ----- binding declared here but left uninitialized +LL | for _ in 0..0 { x = 10; } + | ---- if the `for` loop runs 0 times, `x` is not initialized +LL | return x; + | ^ `x` used here but it is possibly-uninitialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-freeze-frozen-mut.rs b/tests/ui/borrowck/borrowck-freeze-frozen-mut.rs new file mode 100644 index 000000000..199931d6d --- /dev/null +++ b/tests/ui/borrowck/borrowck-freeze-frozen-mut.rs @@ -0,0 +1,28 @@ +// run-pass +// Test that a `&mut` inside of an `&` is freezable. + + +struct MutSlice<'a, T:'a> { + data: &'a mut [T] +} + +fn get<'a, T>(ms: &'a MutSlice<'a, T>, index: usize) -> &'a T { + &ms.data[index] +} + +pub fn main() { + let mut data = [1, 2, 3]; + { + let slice = MutSlice { data: &mut data }; + slice.data[0] += 4; + let index0 = get(&slice, 0); + let index1 = get(&slice, 1); + let index2 = get(&slice, 2); + assert_eq!(*index0, 5); + assert_eq!(*index1, 2); + assert_eq!(*index2, 3); + } + assert_eq!(data[0], 5); + assert_eq!(data[1], 2); + assert_eq!(data[2], 3); +} diff --git a/tests/ui/borrowck/borrowck-if-no-else.rs b/tests/ui/borrowck/borrowck-if-no-else.rs new file mode 100644 index 000000000..534d771be --- /dev/null +++ b/tests/ui/borrowck/borrowck-if-no-else.rs @@ -0,0 +1,6 @@ +fn foo(x: isize) { println!("{}", x); } + +fn main() { + let x: isize; if 1 > 2 { x = 10; } + foo(x); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-if-no-else.stderr b/tests/ui/borrowck/borrowck-if-no-else.stderr new file mode 100644 index 000000000..9eafc2c2a --- /dev/null +++ b/tests/ui/borrowck/borrowck-if-no-else.stderr @@ -0,0 +1,14 @@ +error[E0381]: used binding `x` is possibly-uninitialized + --> $DIR/borrowck-if-no-else.rs:5:9 + | +LL | let x: isize; if 1 > 2 { x = 10; } + | - ----- - an `else` arm might be missing here, initializing `x` + | | | + | | if this `if` condition is `false`, `x` is not initialized + | binding declared here but left uninitialized +LL | foo(x); + | ^ `x` used here but it is possibly-uninitialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-if-with-else.rs b/tests/ui/borrowck/borrowck-if-with-else.rs new file mode 100644 index 000000000..69d450c59 --- /dev/null +++ b/tests/ui/borrowck/borrowck-if-with-else.rs @@ -0,0 +1,11 @@ +fn foo(x: isize) { println!("{}", x); } + +fn main() { + let x: isize; + if 1 > 2 { + println!("whoops"); + } else { + x = 10; + } + foo(x); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-if-with-else.stderr b/tests/ui/borrowck/borrowck-if-with-else.stderr new file mode 100644 index 000000000..3f0fe291c --- /dev/null +++ b/tests/ui/borrowck/borrowck-if-with-else.stderr @@ -0,0 +1,14 @@ +error[E0381]: used binding `x` is possibly-uninitialized + --> $DIR/borrowck-if-with-else.rs:10:9 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | if 1 > 2 { + | ----- if this condition is `true`, `x` is not initialized +... +LL | foo(x); + | ^ `x` used here but it is possibly-uninitialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs new file mode 100644 index 000000000..97107c2e3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs @@ -0,0 +1,10 @@ +fn main() { + let mut _a = 3; + let b = &mut _a; + { + let c = &*b; + _a = 4; //~ ERROR cannot assign to `_a` because it is borrowed + drop(c); + } + drop(b); +} diff --git a/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr new file mode 100644 index 000000000..a66db05cc --- /dev/null +++ b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `_a` because it is borrowed + --> $DIR/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs:6:9 + | +LL | let b = &mut _a; + | ------- borrow of `_a` occurs here +... +LL | _a = 4; + | ^^^^^^ assignment to borrowed `_a` occurs here +... +LL | drop(b); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-in-static.rs b/tests/ui/borrowck/borrowck-in-static.rs new file mode 100644 index 000000000..a45f7b18e --- /dev/null +++ b/tests/ui/borrowck/borrowck-in-static.rs @@ -0,0 +1,12 @@ +// check that borrowck looks inside consts/statics + +static FN : &'static (dyn Fn() -> (BoxBox>) + Sync) = &|| { + let x = Box::new(0); + Box::new(|| x) //~ ERROR cannot move out of `x`, a captured variable in an `Fn` closure +}; + +fn main() { + let f = (FN)(); + f(); + f(); +} diff --git a/tests/ui/borrowck/borrowck-in-static.stderr b/tests/ui/borrowck/borrowck-in-static.stderr new file mode 100644 index 000000000..2033e4a57 --- /dev/null +++ b/tests/ui/borrowck/borrowck-in-static.stderr @@ -0,0 +1,13 @@ +error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure + --> $DIR/borrowck-in-static.rs:5:17 + | +LL | let x = Box::new(0); + | - captured outer variable +LL | Box::new(|| x) + | -- ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | | + | captured by this `Fn` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.rs new file mode 100644 index 000000000..e6476b9c1 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.rs @@ -0,0 +1,7 @@ +fn main() { + let j = || -> isize { + let i: isize; + i //~ ERROR E0381 + }; + j(); +} diff --git a/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr new file mode 100644 index 000000000..1a22b5f09 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `i` isn't initialized + --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9 + | +LL | let i: isize; + | - binding declared here but left uninitialized +LL | i + | ^ `i` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let i: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-in-fn-expr.rs b/tests/ui/borrowck/borrowck-init-in-fn-expr.rs new file mode 100644 index 000000000..7eb204a0d --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-in-fn-expr.rs @@ -0,0 +1,7 @@ +fn main() { + let f = || -> isize { + let i: isize; + i //~ ERROR E0381 + }; + println!("{}", f()); +} diff --git a/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr b/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr new file mode 100644 index 000000000..f1b9b9aa7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `i` isn't initialized + --> $DIR/borrowck-init-in-fn-expr.rs:4:9 + | +LL | let i: isize; + | - binding declared here but left uninitialized +LL | i + | ^ `i` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let i: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-in-fru.rs b/tests/ui/borrowck/borrowck-init-in-fru.rs new file mode 100644 index 000000000..c07957ab1 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-in-fru.rs @@ -0,0 +1,12 @@ +#[derive(Clone)] +struct Point { + x: isize, + y: isize, +} + +fn main() { + let mut origin: Point; + origin = Point { x: 10, ..origin }; + //~^ ERROR E0381 + origin.clone(); +} diff --git a/tests/ui/borrowck/borrowck-init-in-fru.stderr b/tests/ui/borrowck/borrowck-init-in-fru.stderr new file mode 100644 index 000000000..39b28811a --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-in-fru.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `origin` isn't initialized + --> $DIR/borrowck-init-in-fru.rs:9:14 + | +LL | let mut origin: Point; + | ---------- binding declared here but left uninitialized +LL | origin = Point { x: 10, ..origin }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut origin: Point = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-op-equal.rs b/tests/ui/borrowck/borrowck-init-op-equal.rs new file mode 100644 index 000000000..3d08c1b81 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-op-equal.rs @@ -0,0 +1,8 @@ +fn test() { + let v: isize; + v += 1; //~ ERROR E0381 + v.clone(); +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-init-op-equal.stderr b/tests/ui/borrowck/borrowck-init-op-equal.stderr new file mode 100644 index 000000000..ef0fa6df4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-op-equal.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `v` isn't initialized + --> $DIR/borrowck-init-op-equal.rs:3:5 + | +LL | let v: isize; + | - binding declared here but left uninitialized +LL | v += 1; + | ^^^^^^ `v` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let v: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-init-plus-equal.rs b/tests/ui/borrowck/borrowck-init-plus-equal.rs new file mode 100644 index 000000000..2a52a3f4e --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-plus-equal.rs @@ -0,0 +1,8 @@ +fn test() { + let mut v: isize; + v = v + 1; //~ ERROR E0381 + v.clone(); +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-init-plus-equal.stderr b/tests/ui/borrowck/borrowck-init-plus-equal.stderr new file mode 100644 index 000000000..cec053318 --- /dev/null +++ b/tests/ui/borrowck/borrowck-init-plus-equal.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `v` isn't initialized + --> $DIR/borrowck-init-plus-equal.rs:3:9 + | +LL | let mut v: isize; + | ----- binding declared here but left uninitialized +LL | v = v + 1; + | ^ `v` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut v: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-insert-during-each.rs b/tests/ui/borrowck/borrowck-insert-during-each.rs new file mode 100644 index 000000000..df967e611 --- /dev/null +++ b/tests/ui/borrowck/borrowck-insert-during-each.rs @@ -0,0 +1,26 @@ +use std::collections::HashSet; + +struct Foo { + n: HashSet, +} + +impl Foo { + pub fn foo(&mut self, mut fun: F) where F: FnMut(&isize) { + for f in &self.n { + fun(f); + } + } +} + +fn bar(f: &mut Foo) { + f.foo( + //~^ ERROR cannot borrow `*f` as mutable + |a| { //~ ERROR closure requires unique access to `f` + f.n.insert(*a); + }) +} + +fn main() { + let mut f = Foo { n: HashSet::new() }; + bar(&mut f); +} diff --git a/tests/ui/borrowck/borrowck-insert-during-each.stderr b/tests/ui/borrowck/borrowck-insert-during-each.stderr new file mode 100644 index 000000000..99d08e905 --- /dev/null +++ b/tests/ui/borrowck/borrowck-insert-during-each.stderr @@ -0,0 +1,34 @@ +error[E0501]: cannot borrow `*f` as mutable because previous closure requires unique access + --> $DIR/borrowck-insert-during-each.rs:16:5 + | +LL | f.foo( + | ^ --- first borrow later used by call + | _____| + | | +LL | | +LL | | |a| { + | | --- closure construction occurs here +LL | | f.n.insert(*a); + | | --- first borrow occurs due to use of `f` in closure +LL | | }) + | |__________^ second borrow occurs here + +error[E0500]: closure requires unique access to `f` but it is already borrowed + --> $DIR/borrowck-insert-during-each.rs:18:9 + | +LL | f.foo( + | - --- first borrow later used by call + | _____| + | | +LL | | +LL | | |a| { + | | ^^^ closure construction occurs here +LL | | f.n.insert(*a); + | | --- second borrow occurs due to use of `f` in closure +LL | | }) + | |__________- borrow occurs here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0500, E0501. +For more information about an error, try `rustc --explain E0500`. diff --git a/tests/ui/borrowck/borrowck-issue-14498.rs b/tests/ui/borrowck/borrowck-issue-14498.rs new file mode 100644 index 000000000..003533a51 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-14498.rs @@ -0,0 +1,110 @@ +// This tests that we can't modify Box<&mut T> contents while they +// are borrowed (#14498). +// +// Also includes tests of the errors reported when the Box in question +// is immutable (#14270). + + + +struct A { a: isize } +struct B<'a> { a: Box<&'a mut isize> } + +fn indirect_write_to_imm_box() { + let mut x: isize = 1; + let y: Box<_> = Box::new(&mut x); + let p = &y; + ***p = 2; //~ ERROR cannot assign to `***p` + drop(p); +} + +fn borrow_in_var_from_var() { + let mut x: isize = 1; + let mut y: Box<_> = Box::new(&mut x); + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_var_from_var_via_imm_box() { + let mut x: isize = 1; + let y: Box<_> = Box::new(&mut x); + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_var_from_field() { + let mut x = A { a: 1 }; + let mut y: Box<_> = Box::new(&mut x.a); + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_var_from_field_via_imm_box() { + let mut x = A { a: 1 }; + let y: Box<_> = Box::new(&mut x.a); + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_var() { + let mut x: isize = 1; + let mut y = B { a: Box::new(&mut x) }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_var_via_imm_box() { + let mut x: isize = 1; + let y = B { a: Box::new(&mut x) }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_field() { + let mut x = A { a: 1 }; + let mut y = B { a: Box::new(&mut x.a) }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_field_via_imm_box() { + let mut x = A { a: 1 }; + let y = B { a: Box::new(&mut x.a) }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn main() { + indirect_write_to_imm_box(); + borrow_in_var_from_var(); + borrow_in_var_from_var_via_imm_box(); + borrow_in_var_from_field(); + borrow_in_var_from_field_via_imm_box(); + borrow_in_field_from_var(); + borrow_in_field_from_var_via_imm_box(); + borrow_in_field_from_field(); + borrow_in_field_from_field_via_imm_box(); +} diff --git a/tests/ui/borrowck/borrowck-issue-14498.stderr b/tests/ui/borrowck/borrowck-issue-14498.stderr new file mode 100644 index 000000000..42a55b7a8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-14498.stderr @@ -0,0 +1,103 @@ +error[E0594]: cannot assign to `***p`, which is behind a `&` reference + --> $DIR/borrowck-issue-14498.rs:16:5 + | +LL | ***p = 2; + | ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let p = &mut y; + | ~~~~~~ + +error[E0506]: cannot assign to `**y` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:25:5 + | +LL | let p = &y; + | -- borrow of `**y` occurs here +LL | let q = &***p; +LL | **y = 2; + | ^^^^^^^ assignment to borrowed `**y` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:35:5 + | +LL | let p = &y; + | -- borrow of `**y` occurs here +LL | let q = &***p; +LL | **y = 2; + | ^^^^^^^ assignment to borrowed `**y` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:45:5 + | +LL | let p = &y; + | -- borrow of `**y` occurs here +LL | let q = &***p; +LL | **y = 2; + | ^^^^^^^ assignment to borrowed `**y` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:55:5 + | +LL | let p = &y; + | -- borrow of `**y` occurs here +LL | let q = &***p; +LL | **y = 2; + | ^^^^^^^ assignment to borrowed `**y` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y.a` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:65:5 + | +LL | let p = &y.a; + | ---- borrow of `**y.a` occurs here +LL | let q = &***p; +LL | **y.a = 2; + | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y.a` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:75:5 + | +LL | let p = &y.a; + | ---- borrow of `**y.a` occurs here +LL | let q = &***p; +LL | **y.a = 2; + | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y.a` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:85:5 + | +LL | let p = &y.a; + | ---- borrow of `**y.a` occurs here +LL | let q = &***p; +LL | **y.a = 2; + | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here +LL | drop(p); + | - borrow later used here + +error[E0506]: cannot assign to `**y.a` because it is borrowed + --> $DIR/borrowck-issue-14498.rs:95:5 + | +LL | let p = &y.a; + | ---- borrow of `**y.a` occurs here +LL | let q = &***p; +LL | **y.a = 2; + | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here +LL | drop(p); + | - borrow later used here + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0506, E0594. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-issue-2657-1.rs b/tests/ui/borrowck/borrowck-issue-2657-1.rs new file mode 100644 index 000000000..0fb2267b9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-2657-1.rs @@ -0,0 +1,14 @@ +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } + + +fn main() { + let x: Option> = Some(Box::new(1)); + match x { + Some(ref _y) => { + let _a = x; //~ ERROR cannot move + _y.use_ref(); + } + _ => {} + } +} diff --git a/tests/ui/borrowck/borrowck-issue-2657-1.stderr b/tests/ui/borrowck/borrowck-issue-2657-1.stderr new file mode 100644 index 000000000..390bb9384 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-2657-1.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/borrowck-issue-2657-1.rs:9:18 + | +LL | Some(ref _y) => { + | ------ borrow of `x.0` occurs here +LL | let _a = x; + | ^ move out of `x` occurs here +LL | _y.use_ref(); + | ------------ borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-issue-2657-2.fixed b/tests/ui/borrowck/borrowck-issue-2657-2.fixed new file mode 100644 index 000000000..625e7c3ca --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-2657-2.fixed @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + + let x: Option> = Some(Box::new(1)); + + match x { + Some(ref y) => { + let _b = y; //~ ERROR cannot move out + } + _ => {} + } +} diff --git a/tests/ui/borrowck/borrowck-issue-2657-2.rs b/tests/ui/borrowck/borrowck-issue-2657-2.rs new file mode 100644 index 000000000..f79a846e7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-2657-2.rs @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + + let x: Option> = Some(Box::new(1)); + + match x { + Some(ref y) => { + let _b = *y; //~ ERROR cannot move out + } + _ => {} + } +} diff --git a/tests/ui/borrowck/borrowck-issue-2657-2.stderr b/tests/ui/borrowck/borrowck-issue-2657-2.stderr new file mode 100644 index 000000000..850bb9ae3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-2657-2.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of `*y` which is behind a shared reference + --> $DIR/borrowck-issue-2657-2.rs:8:18 + | +LL | let _b = *y; + | ^^ move occurs because `*y` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let _b = *y; +LL + let _b = y; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-issue-48962.rs b/tests/ui/borrowck/borrowck-issue-48962.rs new file mode 100644 index 000000000..86061c8cd --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-48962.rs @@ -0,0 +1,26 @@ +struct Node { + elem: i32, + next: Option>, +} + +fn a() { + let mut node = Node { + elem: 5, + next: None, + }; + + let mut src = &mut node; + {src}; + src.next = None; //~ ERROR use of moved value: `src` [E0382] +} + +fn b() { + let mut src = &mut (22, 44); + {src}; + src.0 = 66; //~ ERROR use of moved value: `src` [E0382] +} + +fn main() { + a(); + b(); +} diff --git a/tests/ui/borrowck/borrowck-issue-48962.stderr b/tests/ui/borrowck/borrowck-issue-48962.stderr new file mode 100644 index 000000000..ee174f673 --- /dev/null +++ b/tests/ui/borrowck/borrowck-issue-48962.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `src` + --> $DIR/borrowck-issue-48962.rs:14:5 + | +LL | let mut src = &mut node; + | ------- move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait +LL | {src}; + | --- value moved here +LL | src.next = None; + | ^^^^^^^^ value used here after move + +error[E0382]: use of moved value: `src` + --> $DIR/borrowck-issue-48962.rs:20:5 + | +LL | let mut src = &mut (22, 44); + | ------- move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait +LL | {src}; + | --- value moved here +LL | src.0 = 66; + | ^^^^^^^^^^ value used here after move + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-lend-args.rs b/tests/ui/borrowck/borrowck-lend-args.rs new file mode 100644 index 000000000..d0ef2dcdd --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-args.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +fn borrow(_v: &isize) {} + +fn borrow_from_arg_imm_ref(v: Box) { + borrow(&*v); +} + +fn borrow_from_arg_mut_ref(v: &mut Box) { + borrow(&**v); +} + +fn borrow_from_arg_copy(v: Box) { + borrow(&*v); +} + +pub fn main() { +} diff --git a/tests/ui/borrowck/borrowck-lend-flow-if.rs b/tests/ui/borrowck/borrowck-lend-flow-if.rs new file mode 100644 index 000000000..19a0dd0c6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow-if.rs @@ -0,0 +1,51 @@ +// Note: the borrowck analysis is currently flow-insensitive. +// Therefore, some of these errors are marked as spurious and could be +// corrected by a simple change to the analysis. The others are +// either genuine or would require more advanced changes. The latter +// cases are noted. + + + +fn borrow(_v: &isize) {} +fn borrow_mut(_v: &mut isize) {} +fn cond() -> bool { panic!() } +fn for_func(_f: F) where F: FnOnce() -> bool { panic!() } +fn produce() -> T { panic!(); } + +fn inc(v: &mut Box) { + *v = Box::new(**v + 1); +} + +fn pre_freeze_cond() { + // In this instance, the freeze is conditional and starts before + // the mut borrow. + + let u = Box::new(0); + let mut v: Box<_> = Box::new(3); + let mut _w = &u; + if cond() { + _w = &v; + } + borrow_mut(&mut *v); //~ ERROR cannot borrow + _w.use_ref(); +} + +fn pre_freeze_else() { + // In this instance, the freeze and mut borrow are on separate sides + // of the if. + + let u = Box::new(0); + let mut v: Box<_> = Box::new(3); + let mut _w = &u; + if cond() { + _w = &v; + } else { + borrow_mut(&mut *v); + } + _w.use_ref(); +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-lend-flow-if.stderr b/tests/ui/borrowck/borrowck-lend-flow-if.stderr new file mode 100644 index 000000000..e47efc0e0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow-if.stderr @@ -0,0 +1,14 @@ +error[E0502]: cannot borrow `*v` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-lend-flow-if.rs:29:16 + | +LL | _w = &v; + | -- immutable borrow occurs here +LL | } +LL | borrow_mut(&mut *v); + | ^^^^^^^ mutable borrow occurs here +LL | _w.use_ref(); + | ------------ immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-lend-flow-loop.rs b/tests/ui/borrowck/borrowck-lend-flow-loop.rs new file mode 100644 index 000000000..548ffbd51 --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow-loop.rs @@ -0,0 +1,132 @@ +fn borrow(_v: &isize) {} +fn borrow_mut(_v: &mut isize) {} +fn cond() -> bool { panic!() } +fn produce() -> T { panic!(); } + + +fn inc(v: &mut Box) { + *v = Box::new(**v + 1); +} + + +fn loop_overarching_alias_mut() { + // In this instance, the borrow ends on the line before the loop + + let mut v: Box<_> = Box::new(3); + let mut x = &mut v; + **x += 1; + loop { + borrow(&*v); // OK + } +} + +fn block_overarching_alias_mut() { + // In this instance, the borrow encompasses the entire closure call. + + let mut v: Box<_> = Box::new(3); + let mut x = &mut v; + for _ in 0..3 { + borrow(&*v); //~ ERROR cannot borrow + } + *x = Box::new(5); +} +fn loop_aliased_mut() { + // In this instance, the borrow ends right after each assignment to _x + + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let mut _x = &w; + loop { + borrow_mut(&mut *v); // OK + _x = &v; + } +} + +fn while_aliased_mut() { + // In this instance, the borrow ends right after each assignment to _x + + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let mut _x = &w; + while cond() { + borrow_mut(&mut *v); // OK + _x = &v; + } +} + + +fn loop_aliased_mut_break() { + // In this instance, the borrow ends right after each assignment to _x + + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let mut _x = &w; + loop { + borrow_mut(&mut *v); + _x = &v; + break; + } + borrow_mut(&mut *v); // OK +} + +fn while_aliased_mut_break() { + // In this instance, the borrow ends right after each assignment to _x + + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let mut _x = &w; + while cond() { + borrow_mut(&mut *v); + _x = &v; + break; + } + borrow_mut(&mut *v); // OK +} + +fn while_aliased_mut_cond(cond: bool, cond2: bool) { + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let mut x = &mut w; + while cond { + **x += 1; + borrow(&*v); //~ ERROR cannot borrow + if cond2 { + x = &mut v; // OK + } + } +} +fn loop_break_pops_scopes<'r, F>(_v: &'r mut [usize], mut f: F) where + F: FnMut(&'r mut usize) -> bool, +{ + // Here we check that when you break out of an inner loop, the + // borrows that go out of scope as you exit the inner loop are + // removed from the bitset. + + while cond() { + while cond() { + // this borrow is limited to the scope of `r`... + let r: &'r mut usize = produce(); + if !f(&mut *r) { + break; // ...so it is not live as exit the `while` loop here + } + } + } +} + +fn loop_loop_pops_scopes<'r, F>(_v: &'r mut [usize], mut f: F) + where F: FnMut(&'r mut usize) -> bool +{ + // Similar to `loop_break_pops_scopes` but for the `loop` keyword + + while cond() { + while cond() { + // this borrow is limited to the scope of `r`... + let r: &'r mut usize = produce(); + if !f(&mut *r) { + continue; // ...so it is not live as exit (and re-enter) the `while` loop here + } + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-lend-flow-loop.stderr b/tests/ui/borrowck/borrowck-lend-flow-loop.stderr new file mode 100644 index 000000000..df7c86b85 --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow-loop.stderr @@ -0,0 +1,26 @@ +error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-lend-flow-loop.rs:29:16 + | +LL | let mut x = &mut v; + | ------ mutable borrow occurs here +LL | for _ in 0..3 { +LL | borrow(&*v); + | ^^^ immutable borrow occurs here +LL | } +LL | *x = Box::new(5); + | -- mutable borrow later used here + +error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-lend-flow-loop.rs:92:16 + | +LL | **x += 1; + | -------- mutable borrow later used here +LL | borrow(&*v); + | ^^^ immutable borrow occurs here +LL | if cond2 { +LL | x = &mut v; // OK + | ------ mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-lend-flow-match.rs b/tests/ui/borrowck/borrowck-lend-flow-match.rs new file mode 100644 index 000000000..9737bc769 --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow-match.rs @@ -0,0 +1,18 @@ +fn separate_arms() { + // Here both arms perform assignments, but only one is illegal. + + let mut x = None; + match x { + None => { + // It is ok to reassign x here, because there is in + // fact no outstanding loan of x! + x = Some(0); + } + Some(ref r) => { + x = Some(1); //~ ERROR cannot assign to `x` because it is borrowed + drop(r); + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-lend-flow-match.stderr b/tests/ui/borrowck/borrowck-lend-flow-match.stderr new file mode 100644 index 000000000..66f1cd9bd --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow-match.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/borrowck-lend-flow-match.rs:12:13 + | +LL | Some(ref r) => { + | ----- borrow of `x` occurs here +LL | x = Some(1); + | ^^^^^^^^^^^ assignment to borrowed `x` occurs here +LL | drop(r); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-lend-flow.rs b/tests/ui/borrowck/borrowck-lend-flow.rs new file mode 100644 index 000000000..564c57044 --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow.rs @@ -0,0 +1,39 @@ +// Note: the borrowck analysis is currently flow-insensitive. +// Therefore, some of these errors are marked as spurious and could be +// corrected by a simple change to the analysis. The others are +// either genuine or would require more advanced changes. The latter +// cases are noted. + + + +fn borrow(_v: &isize) {} +fn borrow_mut(_v: &mut isize) {} +fn cond() -> bool { panic!() } +fn for_func(_f: F) where F: FnOnce() -> bool { panic!() } +fn produce() -> T { panic!(); } + +fn inc(v: &mut Box) { + *v = Box::new(**v + 1); +} + +fn pre_freeze() { + // In this instance, the freeze starts before the mut borrow. + + let mut v: Box<_> = Box::new(3); + let _w = &v; + borrow_mut(&mut *v); //~ ERROR cannot borrow + _w.use_ref(); +} + +fn post_freeze() { + // In this instance, the const alias starts after the borrow. + + let mut v: Box<_> = Box::new(3); + borrow_mut(&mut *v); + let _w = &v; +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-lend-flow.stderr b/tests/ui/borrowck/borrowck-lend-flow.stderr new file mode 100644 index 000000000..40c14f54c --- /dev/null +++ b/tests/ui/borrowck/borrowck-lend-flow.stderr @@ -0,0 +1,13 @@ +error[E0502]: cannot borrow `*v` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-lend-flow.rs:24:16 + | +LL | let _w = &v; + | -- immutable borrow occurs here +LL | borrow_mut(&mut *v); + | ^^^^^^^ mutable borrow occurs here +LL | _w.use_ref(); + | ------------ immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.rs b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.rs new file mode 100644 index 000000000..e536d4040 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.rs @@ -0,0 +1,35 @@ +use std::thread; + + + +fn borrow(v: &isize, f: F) where F: FnOnce(&isize) { + f(v); +} + + + +fn box_imm() { + let v: Box<_> = Box::new(3); + let w = &v; + thread::spawn(move|| { + //~^ ERROR cannot move out of `v` because it is borrowed + println!("v={}", *v); + }); + w.use_ref(); +} + +fn box_imm_explicit() { + let v: Box<_> = Box::new(3); + let w = &v; + thread::spawn(move|| { + //~^ ERROR cannot move + println!("v={}", *v); + }); + w.use_ref(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr new file mode 100644 index 000000000..3548da35b --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr @@ -0,0 +1,31 @@ +error[E0505]: cannot move out of `v` because it is borrowed + --> $DIR/borrowck-loan-blocks-move-cc.rs:14:19 + | +LL | let w = &v; + | -- borrow of `v` occurs here +LL | thread::spawn(move|| { + | ^^^^^^ move out of `v` occurs here +LL | +LL | println!("v={}", *v); + | -- move occurs due to use in closure +LL | }); +LL | w.use_ref(); + | ----------- borrow later used here + +error[E0505]: cannot move out of `v` because it is borrowed + --> $DIR/borrowck-loan-blocks-move-cc.rs:24:19 + | +LL | let w = &v; + | -- borrow of `v` occurs here +LL | thread::spawn(move|| { + | ^^^^^^ move out of `v` occurs here +LL | +LL | println!("v={}", *v); + | -- move occurs due to use in closure +LL | }); +LL | w.use_ref(); + | ----------- borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move.rs b/tests/ui/borrowck/borrowck-loan-blocks-move.rs new file mode 100644 index 000000000..f3f443721 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-blocks-move.rs @@ -0,0 +1,19 @@ +fn take(_v: Box) { +} + + + + + +fn box_imm() { + let v = Box::new(3); + let w = &v; + take(v); //~ ERROR cannot move out of `v` because it is borrowed + w.use_ref(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr new file mode 100644 index 000000000..b5c6b101f --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `v` because it is borrowed + --> $DIR/borrowck-loan-blocks-move.rs:11:10 + | +LL | let w = &v; + | -- borrow of `v` occurs here +LL | take(v); + | ^ move out of `v` occurs here +LL | w.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs b/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs new file mode 100644 index 000000000..33d6af303 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.rs @@ -0,0 +1,18 @@ +fn borrow(v: &isize, f: F) where F: FnOnce(&isize) { + f(v); +} + + + +fn box_imm() { + let mut v: Box<_> = Box::new(3); + borrow(&*v, + |w| { //~ ERROR cannot borrow `v` as mutable + v = Box::new(4); + assert_eq!(*v, 3); + assert_eq!(*w, 4); + }) +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr b/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr new file mode 100644 index 000000000..fa5308c29 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-blocks-mut-uniq.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-loan-blocks-mut-uniq.rs:10:12 + | +LL | borrow(&*v, + | ------ --- immutable borrow occurs here + | | + | immutable borrow later used by call +LL | |w| { + | ^^^ mutable borrow occurs here +LL | v = Box::new(4); + | - second borrow occurs due to use of `v` in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-loan-in-overloaded-op.rs b/tests/ui/borrowck/borrowck-loan-in-overloaded-op.rs new file mode 100644 index 000000000..b8f1650fc --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-in-overloaded-op.rs @@ -0,0 +1,23 @@ +#![feature(box_patterns)] + + +use std::ops::Add; + +#[derive(Clone)] +struct Foo(Box); + +impl Add for Foo { + type Output = Foo; + + fn add(self, f: Foo) -> Foo { + let Foo(box i) = self; + let Foo(box j) = f; + Foo(Box::new(i + j)) + } +} + +fn main() { + let x = Foo(Box::new(3)); + let _y = {x} + x.clone(); // the `{x}` forces a move to occur + //~^ ERROR borrow of moved value: `x` +} diff --git a/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr b/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr new file mode 100644 index 000000000..e1b991620 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-in-overloaded-op.stderr @@ -0,0 +1,18 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/borrowck-loan-in-overloaded-op.rs:21:20 + | +LL | let x = Foo(Box::new(3)); + | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait +LL | let _y = {x} + x.clone(); // the `{x}` forces a move to occur + | - ^^^^^^^^^ value borrowed here after move + | | + | value moved here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = {x.clone()} + x.clone(); // the `{x}` forces a move to occur + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs new file mode 100644 index 000000000..cb801ef1b --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.rs @@ -0,0 +1,24 @@ +use std::mem; + +fn leak(mut b: Box) -> &'static mut T { + // isn't this supposed to be safe? + let inner = &mut *b as *mut _; + mem::forget(b); + unsafe { &mut *inner } +} + +fn evil(mut s: &'static mut String) +{ + // create alias + let alias: &'static mut String = s; + let inner: &str = &alias; + // free value + *s = String::new(); //~ ERROR cannot assign + let _spray = "0wned".to_owned(); + // ... and then use it + println!("{}", inner); +} + +fn main() { + evil(leak(Box::new("hello".to_owned()))); +} diff --git a/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr new file mode 100644 index 000000000..6994c837d --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `*s` because it is borrowed + --> $DIR/borrowck-loan-of-static-data-issue-27616.rs:16:5 + | +LL | let alias: &'static mut String = s; + | ------------------- - borrow of `*s` occurs here + | | + | type annotation requires that `*s` is borrowed for `'static` +... +LL | *s = String::new(); + | ^^ assignment to borrowed `*s` occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs b/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs new file mode 100644 index 000000000..4da10fd44 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.rs @@ -0,0 +1,46 @@ +use std::ops::Add; + +#[derive(Copy, Clone)] +struct Point { + x: isize, + y: isize, +} + +impl Add for Point { + type Output = isize; + + fn add(self, z: isize) -> isize { + self.x + self.y + z + } +} + +impl Point { + pub fn times(&self, z: isize) -> isize { + self.x * self.y * z + } +} + +fn a() { + let mut p = Point {x: 3, y: 4}; + + // ok (we can loan out rcvr) + p + 3; + p.times(3); +} + +fn b() { + let mut p = Point {x: 3, y: 4}; + + // Here I create an outstanding loan and check that we get conflicts: + + let q = &mut p; + + p + 3; //~ ERROR cannot use `p` + p.times(3); //~ ERROR cannot borrow `p` + + *q + 3; // OK to use the new alias `q` + q.x += 1; // and OK to mutate it +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr b/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr new file mode 100644 index 000000000..24cc4933e --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr @@ -0,0 +1,28 @@ +error[E0503]: cannot use `p` because it was mutably borrowed + --> $DIR/borrowck-loan-rcvr-overloaded-op.rs:38:5 + | +LL | let q = &mut p; + | ------ borrow of `p` occurs here +LL | +LL | p + 3; + | ^ use of borrowed `p` +... +LL | *q + 3; // OK to use the new alias `q` + | -- borrow later used here + +error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-loan-rcvr-overloaded-op.rs:39:5 + | +LL | let q = &mut p; + | ------ mutable borrow occurs here +... +LL | p.times(3); + | ^^^^^^^^^^ immutable borrow occurs here +LL | +LL | *q + 3; // OK to use the new alias `q` + | -- mutable borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0502, E0503. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-loan-rcvr.rs b/tests/ui/borrowck/borrowck-loan-rcvr.rs new file mode 100644 index 000000000..d2234e17a --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-rcvr.rs @@ -0,0 +1,40 @@ +struct Point { x: isize, y: isize } + +trait Methods { + fn impurem(&self); + fn blockm(&self, f: F) where F: FnOnce(); +} + +impl Methods for Point { + fn impurem(&self) { + } + + fn blockm(&self, f: F) where F: FnOnce() { f() } +} + +fn a() { + let mut p = Point {x: 3, y: 4}; + + // Here: it's ok to call even though receiver is mutable, because we + // can loan it out. + p.impurem(); + + // But in this case we do not honor the loan: + p.blockm(|| { //~ ERROR cannot borrow `p` as mutable + p.x = 10; + }) +} + +fn b() { + let mut p = Point {x: 3, y: 4}; + + // Here I create an outstanding loan and check that we get conflicts: + + let l = &mut p; + p.impurem(); //~ ERROR cannot borrow + + l.x += 1; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-loan-rcvr.stderr b/tests/ui/borrowck/borrowck-loan-rcvr.stderr new file mode 100644 index 000000000..1d6bd4e2e --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-rcvr.stderr @@ -0,0 +1,27 @@ +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-loan-rcvr.rs:23:14 + | +LL | p.blockm(|| { + | - ------ ^^ mutable borrow occurs here + | | | + | _____| immutable borrow later used by call + | | +LL | | p.x = 10; + | | --- second borrow occurs due to use of `p` in closure +LL | | }) + | |______- immutable borrow occurs here + +error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-loan-rcvr.rs:34:5 + | +LL | let l = &mut p; + | ------ mutable borrow occurs here +LL | p.impurem(); + | ^^^^^^^^^^^ immutable borrow occurs here +LL | +LL | l.x += 1; + | -------- mutable borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-loan-vec-content.rs b/tests/ui/borrowck/borrowck-loan-vec-content.rs new file mode 100644 index 000000000..300ec88c5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-vec-content.rs @@ -0,0 +1,24 @@ +// Here we check that it is allowed to lend out an element of a +// (locally rooted) mutable, unique vector, and that we then prevent +// modifications to the contents. + +fn takes_imm_elt(_v: &isize, f: F) where F: FnOnce() { + f(); +} + +fn has_mut_vec_and_does_not_try_to_change_it() { + let mut v: Vec = vec![1, 2, 3]; + takes_imm_elt(&v[0], || {}) +} + +fn has_mut_vec_but_tries_to_change_it() { + let mut v: Vec = vec![1, 2, 3]; + takes_imm_elt( + &v[0], + || { //~ ERROR cannot borrow `v` as mutable + v[1] = 4; + }) +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-loan-vec-content.stderr b/tests/ui/borrowck/borrowck-loan-vec-content.stderr new file mode 100644 index 000000000..6691a2396 --- /dev/null +++ b/tests/ui/borrowck/borrowck-loan-vec-content.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-loan-vec-content.rs:18:9 + | +LL | takes_imm_elt( + | ------------- immutable borrow later used by call +LL | &v[0], + | - immutable borrow occurs here +LL | || { + | ^^ mutable borrow occurs here +LL | v[1] = 4; + | - second borrow occurs due to use of `v` in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.rs b/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.rs new file mode 100644 index 000000000..b6eebd4e3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.rs @@ -0,0 +1,6 @@ +fn cplusplus_mode(x: isize) -> &'static isize { + &x + //~^ ERROR cannot return reference to function parameter `x` [E0515] +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr b/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr new file mode 100644 index 000000000..9d19de211 --- /dev/null +++ b/tests/ui/borrowck/borrowck-local-borrow-outlives-fn.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to function parameter `x` + --> $DIR/borrowck-local-borrow-outlives-fn.rs:2:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs new file mode 100644 index 000000000..ffb2da280 --- /dev/null +++ b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs @@ -0,0 +1,10 @@ +fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) { + let mut z = (0, 0); + *x = Some(&mut z.1); + //~^ ERROR `z.1` does not live long enough [E0597] + panic!("catch me for a dangling pointer!") +} + +fn main() { + cplusplus_mode_exceptionally_unsafe(&mut None); +} diff --git a/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr new file mode 100644 index 000000000..6ea6951ad --- /dev/null +++ b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr @@ -0,0 +1,15 @@ +error[E0597]: `z.1` does not live long enough + --> $DIR/borrowck-local-borrow-with-panic-outlives-fn.rs:3:15 + | +LL | *x = Some(&mut z.1); + | ----------^^^^^^^^- + | | | + | | borrowed value does not live long enough + | assignment requires that `z.1` is borrowed for `'static` +... +LL | } + | - `z.1` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/borrowck/borrowck-local-borrow.rs b/tests/ui/borrowck/borrowck-local-borrow.rs new file mode 100644 index 000000000..0aaa4e4c6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-local-borrow.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panic 1 +// ignore-emscripten no processes + +fn main() { + let x = 2; + let y = &x; + panic!("panic 1"); +} diff --git a/tests/ui/borrowck/borrowck-macro-interaction-issue-6304.rs b/tests/ui/borrowck/borrowck-macro-interaction-issue-6304.rs new file mode 100644 index 000000000..4e969f6ed --- /dev/null +++ b/tests/ui/borrowck/borrowck-macro-interaction-issue-6304.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unconditional_recursion)] + +// Check that we do not ICE when compiling this +// macro, which reuses the expression `$id` + +#![feature(box_patterns)] + +struct Foo { + a: isize +} + +pub enum Bar { + Bar1, Bar2(isize, Box), +} + +impl Foo { + fn elaborate_stm(&mut self, s: Box) -> Box { + macro_rules! declare { + ($id:expr, $rest:expr) => ({ + self.check_id($id); + Box::new(Bar::Bar2($id, $rest)) + }) + } + match s { + box Bar::Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)), + _ => panic!() + } + } + + fn check_id(&mut self, s: isize) { panic!() } +} + +pub fn main() { } diff --git a/tests/ui/borrowck/borrowck-match-already-borrowed.rs b/tests/ui/borrowck/borrowck-match-already-borrowed.rs new file mode 100644 index 000000000..a925cbbf5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-match-already-borrowed.rs @@ -0,0 +1,26 @@ +enum Foo { + A(i32), + B +} + +fn match_enum() { + let mut foo = Foo::B; + let p = &mut foo; + let _ = match foo { //~ ERROR [E0503] + Foo::B => 1, + _ => 2, + Foo::A(x) => x //~ ERROR [E0503] + }; + drop(p); +} + + +fn main() { + let mut x = 1; + let r = &mut x; + let _ = match x { + x => x + 1, //~ ERROR [E0503] + y => y + 2, //~ ERROR [E0503] + }; + drop(r); +} diff --git a/tests/ui/borrowck/borrowck-match-already-borrowed.stderr b/tests/ui/borrowck/borrowck-match-already-borrowed.stderr new file mode 100644 index 000000000..39047be9d --- /dev/null +++ b/tests/ui/borrowck/borrowck-match-already-borrowed.stderr @@ -0,0 +1,50 @@ +error[E0503]: cannot use `foo` because it was mutably borrowed + --> $DIR/borrowck-match-already-borrowed.rs:9:19 + | +LL | let p = &mut foo; + | -------- borrow of `foo` occurs here +LL | let _ = match foo { + | ^^^ use of borrowed `foo` +... +LL | drop(p); + | - borrow later used here + +error[E0503]: cannot use `foo.0` because it was mutably borrowed + --> $DIR/borrowck-match-already-borrowed.rs:12:16 + | +LL | let p = &mut foo; + | -------- borrow of `foo` occurs here +... +LL | Foo::A(x) => x + | ^ use of borrowed `foo` +LL | }; +LL | drop(p); + | - borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-match-already-borrowed.rs:22:9 + | +LL | let r = &mut x; + | ------ borrow of `x` occurs here +LL | let _ = match x { +LL | x => x + 1, + | ^ use of borrowed `x` +... +LL | drop(r); + | - borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-match-already-borrowed.rs:23:9 + | +LL | let r = &mut x; + | ------ borrow of `x` occurs here +... +LL | y => y + 2, + | ^ use of borrowed `x` +LL | }; +LL | drop(r); + | - borrow later used here + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/borrowck-match-binding-is-assignment.rs b/tests/ui/borrowck/borrowck-match-binding-is-assignment.rs new file mode 100644 index 000000000..064bf69ae --- /dev/null +++ b/tests/ui/borrowck/borrowck-match-binding-is-assignment.rs @@ -0,0 +1,41 @@ +// Test that immutable pattern bindings cannot be reassigned. + +enum E { + Foo(isize) +} + +struct S { + bar: isize, +} + +pub fn main() { + match 1 { + x => { + x += 1; //~ ERROR [E0384] + } + } + + match E::Foo(1) { + E::Foo(x) => { + x += 1; //~ ERROR [E0384] + } + } + + match (S { bar: 1 }) { + S { bar: x } => { + x += 1; //~ ERROR [E0384] + } + } + + match (1,) { + (x,) => { + x += 1; //~ ERROR [E0384] + } + } + + match [1,2,3] { + [x,_,_] => { + x += 1; //~ ERROR [E0384] + } + } +} diff --git a/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr b/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr new file mode 100644 index 000000000..dd22d7e2e --- /dev/null +++ b/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr @@ -0,0 +1,58 @@ +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/borrowck-match-binding-is-assignment.rs:14:13 + | +LL | x => { + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/borrowck-match-binding-is-assignment.rs:20:13 + | +LL | E::Foo(x) => { + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/borrowck-match-binding-is-assignment.rs:26:13 + | +LL | S { bar: x } => { + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/borrowck-match-binding-is-assignment.rs:32:13 + | +LL | (x,) => { + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/borrowck-match-binding-is-assignment.rs:38:13 + | +LL | [x,_,_] => { + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/borrowck/borrowck-move-by-capture-ok.rs b/tests/ui/borrowck/borrowck-move-by-capture-ok.rs new file mode 100644 index 000000000..e7a48ebf6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-by-capture-ok.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let bar: Box<_> = Box::new(3); + let h = || -> isize { *bar }; + assert_eq!(h(), 3); +} diff --git a/tests/ui/borrowck/borrowck-move-by-capture.rs b/tests/ui/borrowck/borrowck-move-by-capture.rs new file mode 100644 index 000000000..6f0eb1870 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-by-capture.rs @@ -0,0 +1,11 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_mut>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } + +pub fn main() { + let bar: Box<_> = Box::new(3); + let _g = to_fn_mut(|| { + let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of + }); +} diff --git a/tests/ui/borrowck/borrowck-move-by-capture.stderr b/tests/ui/borrowck/borrowck-move-by-capture.stderr new file mode 100644 index 000000000..8ddc48b2a --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-by-capture.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure + --> $DIR/borrowck-move-by-capture.rs:9:29 + | +LL | let bar: Box<_> = Box::new(3); + | --- captured outer variable +LL | let _g = to_fn_mut(|| { + | -- captured by this `FnMut` closure +LL | let _h = to_fn_once(move || -> isize { *bar }); + | ^^^^^^^^^^^^^^^^ ---- + | | | + | | variable moved due to use in closure + | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait + | move out of `bar` occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-error-with-note.fixed b/tests/ui/borrowck/borrowck-move-error-with-note.fixed new file mode 100644 index 000000000..cf6c382a6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-error-with-note.fixed @@ -0,0 +1,56 @@ +// run-rustfix +#![allow(unused)] +enum Foo { + Foo1(Box, Box), + Foo2(Box), + Foo3, +} + + + +fn blah() { + let f = &Foo::Foo1(Box::new(1), Box::new(2)); + match f { //~ ERROR cannot move out of + Foo::Foo1(num1, + num2) => (), + Foo::Foo2(num) => (), + Foo::Foo3 => () + } +} + +struct S { + f: String, + g: String +} +impl Drop for S { + fn drop(&mut self) { println!("{}", self.f); } +} + +fn move_in_match() { + match (S {f: "foo".to_string(), g: "bar".to_string()}) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + S { + f: ref _s, + g: ref _t + } => {} + } +} + +// from issue-8064 +struct A { + a: Box, +} + +fn free(_: T) {} + +fn blah2() { + let a = &A { a: Box::new(1) }; + match &a.a { //~ ERROR cannot move out of + n => { + free(n) + } + } + free(a) +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-error-with-note.rs b/tests/ui/borrowck/borrowck-move-error-with-note.rs new file mode 100644 index 000000000..f336ac4f9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-error-with-note.rs @@ -0,0 +1,56 @@ +// run-rustfix +#![allow(unused)] +enum Foo { + Foo1(Box, Box), + Foo2(Box), + Foo3, +} + + + +fn blah() { + let f = &Foo::Foo1(Box::new(1), Box::new(2)); + match *f { //~ ERROR cannot move out of + Foo::Foo1(num1, + num2) => (), + Foo::Foo2(num) => (), + Foo::Foo3 => () + } +} + +struct S { + f: String, + g: String +} +impl Drop for S { + fn drop(&mut self) { println!("{}", self.f); } +} + +fn move_in_match() { + match (S {f: "foo".to_string(), g: "bar".to_string()}) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + S { + f: _s, + g: _t + } => {} + } +} + +// from issue-8064 +struct A { + a: Box, +} + +fn free(_: T) {} + +fn blah2() { + let a = &A { a: Box::new(1) }; + match a.a { //~ ERROR cannot move out of + n => { + free(n) + } + } + free(a) +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-error-with-note.stderr b/tests/ui/borrowck/borrowck-move-error-with-note.stderr new file mode 100644 index 000000000..722c2c144 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-error-with-note.stderr @@ -0,0 +1,60 @@ +error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference + --> $DIR/borrowck-move-error-with-note.rs:13:11 + | +LL | match *f { + | ^^ +LL | Foo::Foo1(num1, + | ---- data moved here +LL | num2) => (), + | ---- ...and here +LL | Foo::Foo2(num) => (), + | --- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the dereference here + | +LL - match *f { +LL + match f { + | + +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-error-with-note.rs:30:11 + | +LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here +... +LL | f: _s, + | -- data moved here +LL | g: _t + | -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | f: ref _s, + | +++ +help: consider borrowing the pattern binding + | +LL | g: ref _t + | +++ + +error[E0507]: cannot move out of `a.a` which is behind a shared reference + --> $DIR/borrowck-move-error-with-note.rs:48:11 + | +LL | match a.a { + | ^^^ +LL | n => { + | - + | | + | data moved here + | move occurs because `n` has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &a.a { + | + + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0507, E0509. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs new file mode 100644 index 000000000..71405f7a7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs @@ -0,0 +1,17 @@ +// verify that an error is raised when trying to move out of a +// borrowed path. + + + + + +fn main() { + let a: Box> = Box::new(Box::new(2)); + let b = &a; + + let z = *a; //~ ERROR: cannot move out of `*a` because it is borrowed + b.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr new file mode 100644 index 000000000..f833abcc0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr @@ -0,0 +1,14 @@ +error[E0505]: cannot move out of `*a` because it is borrowed + --> $DIR/borrowck-move-from-subpath-of-borrowed-path.rs:12:13 + | +LL | let b = &a; + | -- borrow of `a` occurs here +LL | +LL | let z = *a; + | ^^ move out of `*a` occurs here +LL | b.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.rs b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.rs new file mode 100644 index 000000000..824da5ceb --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.rs @@ -0,0 +1,7 @@ +unsafe fn foo(x: *const Box) -> Box { + let y = *x; //~ ERROR cannot move out of `*x` which is behind a raw pointer + return y; +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr new file mode 100644 index 000000000..43fc102bd --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-from-unsafe-ptr.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of `*x` which is behind a raw pointer + --> $DIR/borrowck-move-from-unsafe-ptr.rs:2:13 + | +LL | let y = *x; + | ^^ move occurs because `*x` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let y = *x; +LL + let y = x; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-in-irrefut-pat.rs b/tests/ui/borrowck/borrowck-move-in-irrefut-pat.rs new file mode 100644 index 000000000..f4f402dd9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-in-irrefut-pat.rs @@ -0,0 +1,16 @@ +fn with(f: F) where F: FnOnce(&String) {} + +fn arg_item(&_x: &String) {} + //~^ ERROR [E0507] + +fn arg_closure() { + with(|&_x| ()) + //~^ ERROR [E0507] +} + +fn let_pat() { + let &_x = &"hi".to_string(); + //~^ ERROR [E0507] +} + +pub fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr b/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr new file mode 100644 index 000000000..21bd07332 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr @@ -0,0 +1,48 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-move-in-irrefut-pat.rs:3:13 + | +LL | fn arg_item(&_x: &String) {} + | ^-- + | | + | data moved here + | move occurs because `_x` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - fn arg_item(&_x: &String) {} +LL + fn arg_item(_x: &String) {} + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-move-in-irrefut-pat.rs:7:11 + | +LL | with(|&_x| ()) + | ^-- + | | + | data moved here + | move occurs because `_x` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with(|&_x| ()) +LL + with(|_x| ()) + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-move-in-irrefut-pat.rs:12:15 + | +LL | let &_x = &"hi".to_string(); + | -- ^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_x` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - let &_x = &"hi".to_string(); +LL + let _x = &"hi".to_string(); + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-moved-value-into-closure.rs b/tests/ui/borrowck/borrowck-move-moved-value-into-closure.rs new file mode 100644 index 000000000..72e7b5a71 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-moved-value-into-closure.rs @@ -0,0 +1,12 @@ +fn call_f isize>(f: F) -> isize { + f() +} + + + +fn main() { + let t: Box<_> = Box::new(3); + + call_f(move|| { *t + 1 }); + call_f(move|| { *t + 1 }); //~ ERROR use of moved value +} diff --git a/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr b/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr new file mode 100644 index 000000000..9509ebb7c --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-moved-value-into-closure.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `t` + --> $DIR/borrowck-move-moved-value-into-closure.rs:11:12 + | +LL | let t: Box<_> = Box::new(3); + | - move occurs because `t` has type `Box`, which does not implement the `Copy` trait +LL | +LL | call_f(move|| { *t + 1 }); + | ------ -- variable moved due to use in closure + | | + | value moved into closure here +LL | call_f(move|| { *t + 1 }); + | ^^^^^^ -- use occurs due to use in closure + | | + | value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs b/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs new file mode 100644 index 000000000..fa2d5531b --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs @@ -0,0 +1,19 @@ +// Test that attempt to move `&mut` pointer while pointee is borrowed +// yields an error. +// +// Example from compiler/rustc_borrowck/borrowck/README.md + + + +fn foo(t0: &mut isize) { + let p: &isize = &*t0; // Freezes `*t0` + let t1 = t0; //~ ERROR cannot move out of `t0` + *t1 = 22; + p.use_ref(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr new file mode 100644 index 000000000..d5ff0c501 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr @@ -0,0 +1,14 @@ +error[E0505]: cannot move out of `t0` because it is borrowed + --> $DIR/borrowck-move-mut-base-ptr.rs:10:14 + | +LL | let p: &isize = &*t0; // Freezes `*t0` + | ---- borrow of `*t0` occurs here +LL | let t1 = t0; + | ^^ move out of `t0` occurs here +LL | *t1 = 22; +LL | p.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-match.rs b/tests/ui/borrowck/borrowck-move-out-from-array-match.rs new file mode 100644 index 000000000..ced4d002b --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-match.rs @@ -0,0 +1,116 @@ +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_end() { + let a = array(); + match a { + [_, _, _x] => {} + } + match a { + [.., _y] => {} //~ ERROR use of moved value + } +} + +fn move_out_from_begin_field_and_end() { + let a = array(); + match a { + [_, _, (_x, _)] => {} + } + match a { + [.., _y] => {} //~ ERROR use of partially moved value + } +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + match a { + [_, _, (_x, _)] => {} + } + match a { + [.., (_y, _)] => {} //~ ERROR use of moved value + } +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + match a { + [_x, _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_y @ .., _, _] => {} + } +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + match a { + [.., _x] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, _, _y @ ..] => {} + } +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + match a { + [(_x, _), _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_y @ .., _, _] => {} + } +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + match a { + [.., (_x, _)] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, _, _y @ ..] => {} + } +} + +fn move_out_by_subslice_and_const_index_field() { + let a = array(); + match a { + [_y @ .., _, _] => {} + } + match a { + [(_x, _), _, _] => {} //~ ERROR use of moved value + } +} + +fn move_out_by_subslice_and_const_index_end_field() { + let a = array(); + match a { + [_, _, _y @ ..] => {} + } + match a { + [.., (_x, _)] => {} //~ ERROR use of moved value + } +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + match a { + [x @ .., _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, _y @ ..] => {} + } +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-match.stderr b/tests/ui/borrowck/borrowck-move-out-from-array-match.stderr new file mode 100644 index 000000000..67b00c1dd --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-match.stderr @@ -0,0 +1,153 @@ +error[E0382]: use of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-match.rs:13:14 + | +LL | [_, _, _x] => {} + | -- value moved here +... +LL | [.., _y] => {} + | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-match.rs:23:14 + | +LL | [_, _, (_x, _)] => {} + | -- value partially moved here +... +LL | [.., _y] => {} + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: use of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array-match.rs:33:15 + | +LL | [_, _, (_x, _)] => {} + | -- value moved here +... +LL | [.., (_y, _)] => {} + | ^^ value used here after move + | + = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-match.rs:44:11 + | +LL | [_x, _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-match.rs:55:11 + | +LL | [.., _x] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-match.rs:66:11 + | +LL | [(_x, _), _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-match.rs:77:11 + | +LL | [.., (_x, _)] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ + +error[E0382]: use of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array-match.rs:89:11 + | +LL | [_y @ .., _, _] => {} + | -- value moved here +... +LL | [(_x, _), _, _] => {} + | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _, _] => {} + | +++ + +error[E0382]: use of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array-match.rs:99:15 + | +LL | [_, _, _y @ ..] => {} + | -- value moved here +... +LL | [.., (_x, _)] => {} + | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _y @ ..] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-match.rs:110:11 + | +LL | [x @ .., _] => {} + | - value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _] => {} + | +++ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs b/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs new file mode 100644 index 000000000..97db70f34 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs @@ -0,0 +1,115 @@ +// Due to #53114, which causes a "read" of the `_` patterns, +// the borrow-checker refuses this code, while it should probably be allowed. +// Once the bug is fixed, the test, which is derived from a +// passing test for `let` statements, should become check-pass. + +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_one_from_end() { + let a = array(); + match a { + [_, _, _x] => {} + } + match a { + //~^ ERROR use of partially moved value + [.., _y, _] => {} + } +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + match a { + [_, _, (_x, _)] => {} + } + match a { + //~^ ERROR use of partially moved value + [.., (_, _y)] => {} + } +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + match a { + [_x, _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, _y @ ..] => {} + } +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + match a { + [.., _x] => {} + } + match a { + //~^ ERROR use of partially moved value + [_y @ .., _] => {} + } +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + match a { + [(_x, _), _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, _y @ ..] => {} + } +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + match a { + [.., (_x, _)] => {} + } + match a { + //~^ ERROR use of partially moved value + [_y @ .., _] => {} + } +} + +fn move_out_by_const_subslice_and_index_field() { + let a = array(); + match a { + [_, _y @ ..] => {} + } + match a { + //~^ ERROR use of partially moved value + [(_x, _), _, _] => {} + } +} + +fn move_out_by_const_subslice_and_end_index_field() { + let a = array(); + match a { + [_y @ .., _] => {} + } + match a { + //~^ ERROR use of partially moved value + [.., (_x, _)] => {} + } +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + match a { + [x @ .., _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, _y @ ..] => {} + } +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr new file mode 100644 index 000000000..47429ea3e --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr @@ -0,0 +1,138 @@ +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11 + | +LL | [_, _, _x] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11 + | +LL | [_, _, (_x, _)] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11 + | +LL | [_x, _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11 + | +LL | [.., _x] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11 + | +LL | [(_x, _), _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11 + | +LL | [.., (_x, _)] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11 + | +LL | [_, _y @ ..] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, ref _y @ ..] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11 + | +LL | [_y @ .., _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11 + | +LL | [x @ .., _, _] => {} + | - value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _, _] => {} + | +++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs b/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs new file mode 100644 index 000000000..c91b4286b --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs @@ -0,0 +1,67 @@ +// check-pass + +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_one_from_end() { + let a = array(); + let [_, _, _x] = a; + let [.., _y, _] = a; +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + let [_, _, (_x, _)] = a; + let [.., (_, _y)] = a; +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + let [_x, _, _] = a; + let [_, _y @ ..] = a; +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + let [.., _x] = a; + let [_y @ .., _] = a; +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + let [(_x, _), _, _] = a; + let [_, _y @ ..] = a; +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + let [.., (_x, _)] = a; + let [_y @ .., _] = a; +} + +fn move_out_by_const_subslice_and_index_field() { + let a = array(); + let [_, _y @ ..] = a; + let [(_x, _), _, _] = a; +} + +fn move_out_by_const_subslice_and_end_index_field() { + let a = array(); + let [_y @ .., _] = a; + let [.., (_x, _)] = a; +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + let [x @ .., _, _] = a; + let [_, _y @ ..] = a; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use-match.rs b/tests/ui/borrowck/borrowck-move-out-from-array-use-match.rs new file mode 100644 index 000000000..604a25cdc --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use-match.rs @@ -0,0 +1,150 @@ +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_end() { + let a = array(); + match a { + [_, _, _x] => {} + } + match a { + [.., ref _y] => {} //~ ERROR [E0382] + } +} + +fn move_out_from_begin_field_and_end() { + let a = array(); + match a { + [_, _, (_x, _)] => {} + } + match a { + [.., ref _y] => {} //~ ERROR [E0382] + } +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + match a { + [_, _, (_x, _)] => {} + } + match a { + [.., (ref _y, _)] => {} //~ ERROR [E0382] + } +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + match a { + [_x, _, _] => {} + } + match a { + //~^ ERROR [E0382] + [ref _y @ .., _, _] => {} + } +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + match a { + [.., _x] => {} + } + match a { + //~^ ERROR [E0382] + [_, _, ref _y @ ..] => {} + } +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + match a { + [(_x, _), _, _] => {} + } + match a { + //~^ ERROR [E0382] + [ref _y @ .., _, _] => {} + } +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + match a { + [.., (_x, _)] => {} + } + match a { + //~^ ERROR [E0382] + [_, _, ref _y @ ..] => {} + } +} + +fn move_out_by_subslice_and_const_index_field() { + let a = array(); + match a { + [_y @ .., _, _] => {} + } + match a { + [(ref _x, _), _, _] => {} //~ ERROR [E0382] + } +} + +fn move_out_by_subslice_and_const_index_end_field() { + let a = array(); + match a { + [_, _, _y @ ..] => {} + } + match a { + [.., (ref _x, _)] => {} //~ ERROR [E0382] + } +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + match a { + [x @ .., _] => {} + } + match a { + //~^ ERROR [E0382] + [_, ref _y @ ..] => {} + } +} + +// Move + Assign + +fn move_out_and_assign_end() { + let mut a = array(); + match a { + [_, _, _x] => {} + } + a[2] = Default::default(); //~ ERROR [E0382] +} + +fn move_out_and_assign_end_field() { + let mut a = array(); + match a { + [_, _, (_x, _)] => {} + } + a[2].1 = Default::default(); //~ ERROR [E0382] +} + +fn move_out_slice_and_assign_end() { + let mut a = array(); + match a { + [_, _, _x @ ..] => {} + } + a[0] = Default::default(); //~ ERROR [E0382] +} + +fn move_out_slice_and_assign_end_field() { + let mut a = array(); + match a { + [_, _, _x @ ..] => {} + } + a[0].1 = Default::default(); //~ ERROR [E0382] +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/tests/ui/borrowck/borrowck-move-out-from-array-use-match.stderr new file mode 100644 index 000000000..bfab13d42 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use-match.stderr @@ -0,0 +1,213 @@ +error[E0382]: borrow of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use-match.rs:13:14 + | +LL | [_, _, _x] => {} + | -- value moved here +... +LL | [.., ref _y] => {} + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ + +error[E0382]: borrow of partially moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14 + | +LL | [_, _, (_x, _)] => {} + | -- value partially moved here +... +LL | [.., ref _y] => {} + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: borrow of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15 + | +LL | [_, _, (_x, _)] => {} + | -- value moved here +... +LL | [.., (ref _y, _)] => {} + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11 + | +LL | [_x, _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11 + | +LL | [.., _x] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11 + | +LL | [(_x, _), _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11 + | +LL | [.., (_x, _)] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ + +error[E0382]: borrow of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11 + | +LL | [_y @ .., _, _] => {} + | -- value moved here +... +LL | [(ref _x, _), _, _] => {} + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _, _] => {} + | +++ + +error[E0382]: borrow of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15 + | +LL | [_, _, _y @ ..] => {} + | -- value moved here +... +LL | [.., (ref _x, _)] => {} + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _y @ ..] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11 + | +LL | [x @ .., _] => {} + | - value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5 + | +LL | [_, _, _x] => {} + | -- value partially moved here +LL | } +LL | a[2] = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5 + | +LL | [_, _, (_x, _)] => {} + | -- value partially moved here +LL | } +LL | a[2].1 = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5 + | +LL | [_, _, _x @ ..] => {} + | -- value partially moved here +LL | } +LL | a[0] = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x @ ..] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5 + | +LL | [_, _, _x @ ..] => {} + | -- value partially moved here +LL | } +LL | a[0].1 = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x @ ..] => {} + | +++ + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs b/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs new file mode 100644 index 000000000..017ca90b8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs @@ -0,0 +1,115 @@ +// Due to #53114, which causes a "read" of the `_` patterns, +// the borrow-checker refuses this code, while it should probably be allowed. +// Once the bug is fixed, the test, which is derived from a +// passing test for `let` statements, should become check-pass. + +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_one_from_end() { + let a = array(); + match a { + [_, _, _x] => {} + } + match a { + //~^ ERROR use of partially moved value + [.., ref _y, _] => {} + } +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + match a { + [_, _, (_x, _)] => {} + } + match a { + //~^ ERROR use of partially moved value + [.., (_, ref _y)] => {} + } +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + match a { + [_x, _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, ref _y @ ..] => {} + } +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + match a { + [.., _x] => {} + } + match a { + //~^ ERROR use of partially moved value + [ref _y @ .., _] => {} + } +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + match a { + [(_x, _), _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, ref _y @ ..] => {} + } +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + match a { + [.., (_x, _)] => {} + } + match a { + //~^ ERROR use of partially moved value + [ref _y @ .., _] => {} + } +} + +fn move_out_by_const_subslice_and_index_field() { + let a = array(); + match a { + [_, _y @ ..] => {} + } + match a { + //~^ ERROR use of partially moved value + [(ref _x, _), _, _] => {} + } +} + +fn move_out_by_const_subslice_and_end_index_field() { + let a = array(); + match a { + [_y @ .., _] => {} + } + match a { + //~^ ERROR use of partially moved value + [.., (ref _x, _)] => {} + } +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + match a { + [x @ .., _, _] => {} + } + match a { + //~^ ERROR use of partially moved value + [_, ref _y @ ..] => {} + } +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr new file mode 100644 index 000000000..8412c24fe --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr @@ -0,0 +1,138 @@ +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11 + | +LL | [_, _, _x] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11 + | +LL | [_, _, (_x, _)] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11 + | +LL | [_x, _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11 + | +LL | [.., _x] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11 + | +LL | [(_x, _), _, _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11 + | +LL | [.., (_x, _)] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11 + | +LL | [_, _y @ ..] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, ref _y @ ..] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11 + | +LL | [_y @ .., _] => {} + | -- value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _] => {} + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11 + | +LL | [x @ .., _, _] => {} + | - value partially moved here +LL | } +LL | match a { + | ^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _, _] => {} + | +++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs b/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs new file mode 100644 index 000000000..e3498cef3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs @@ -0,0 +1,67 @@ +// check-pass + +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_one_from_end() { + let a = array(); + let [_, _, _x] = a; + let [.., ref _y, _] = a; +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + let [_, _, (_x, _)] = a; + let [.., (_, ref _y)] = a; +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + let [_x, _, _] = a; + let [_, ref _y @ ..] = a; +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + let [.., _x] = a; + let [ref _y @ .., _] = a; +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + let [(_x, _), _, _] = a; + let [_, ref _y @ ..] = a; +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + let [.., (_x, _)] = a; + let [ref _y @ .., _] = a; +} + +fn move_out_by_const_subslice_and_index_field() { + let a = array(); + let [_, _y @ ..] = a; + let [(ref _x, _), _, _] = a; +} + +fn move_out_by_const_subslice_and_end_index_field() { + let a = array(); + let [_y @ .., _] = a; + let [.., (ref _x, _)] = a; +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + let [x @ .., _, _] = a; + let [_, ref _y @ ..] = a; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use.rs b/tests/ui/borrowck/borrowck-move-out-from-array-use.rs new file mode 100644 index 000000000..ad08367a3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use.rs @@ -0,0 +1,97 @@ +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_end() { + let a = array(); + let [_, _, _x] = a; + let [.., ref _y] = a; //~ ERROR [E0382] +} + +fn move_out_from_begin_field_and_end() { + let a = array(); + let [_, _, (_x, _)] = a; + let [.., ref _y] = a; //~ ERROR [E0382] +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + let [_, _, (_x, _)] = a; + let [.., (ref _y, _)] = a; //~ ERROR [E0382] +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + let [_x, _, _] = a; + let [ref _y @ .., _, _] = a; //~ ERROR [E0382] +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + let [.., _x] = a; + let [_, _, ref _y @ ..] = a; //~ ERROR [E0382] +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + let [(_x, _), _, _] = a; + let [ref _y @ .., _, _] = a; //~ ERROR [E0382] +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + let [.., (_x, _)] = a; + let [_, _, ref _y @ ..] = a; //~ ERROR [E0382] +} + +fn move_out_by_subslice_and_const_index_field() { + let a = array(); + let [_y @ .., _, _] = a; + let [(ref _x, _), _, _] = a; //~ ERROR [E0382] +} + +fn move_out_by_subslice_and_const_index_end_field() { + let a = array(); + let [_, _, _y @ ..] = a; + let [.., (ref _x, _)] = a; //~ ERROR [E0382] +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + let [x @ .., _] = a; + let [_, ref _y @ ..] = a; //~ ERROR [E0382] +} + +// Move + Assign + +fn move_out_and_assign_end() { + let mut a = array(); + let [_, _, _x] = a; + a[2] = Default::default(); //~ ERROR [E0382] +} + +fn move_out_and_assign_end_field() { + let mut a = array(); + let [_, _, (_x, _)] = a; + a[2].1 = Default::default(); //~ ERROR [E0382] +} + +fn move_out_slice_and_assign_end() { + let mut a = array(); + let [_, _, _x @ ..] = a; + a[0] = Default::default(); //~ ERROR [E0382] +} + +fn move_out_slice_and_assign_end_field() { + let mut a = array(); + let [_, _, _x @ ..] = a; + a[0].1 = Default::default(); //~ ERROR [E0382] +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array-use.stderr b/tests/ui/borrowck/borrowck-move-out-from-array-use.stderr new file mode 100644 index 000000000..e2aeaafc6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array-use.stderr @@ -0,0 +1,199 @@ +error[E0382]: borrow of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use.rs:10:14 + | +LL | let [_, _, _x] = a; + | -- value moved here +LL | let [.., ref _y] = a; + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x] = a; + | +++ + +error[E0382]: borrow of partially moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use.rs:16:14 + | +LL | let [_, _, (_x, _)] = a; + | -- value partially moved here +LL | let [.., ref _y] = a; + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ + +error[E0382]: borrow of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array-use.rs:22:15 + | +LL | let [_, _, (_x, _)] = a; + | -- value moved here +LL | let [.., (ref _y, _)] = a; + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ + +error[E0382]: borrow of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:30:10 + | +LL | let [_x, _, _] = a; + | -- value partially moved here +LL | let [ref _y @ .., _, _] = a; + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _x, _, _] = a; + | +++ + +error[E0382]: borrow of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:36:16 + | +LL | let [.., _x] = a; + | -- value partially moved here +LL | let [_, _, ref _y @ ..] = a; + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., ref _x] = a; + | +++ + +error[E0382]: borrow of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:42:10 + | +LL | let [(_x, _), _, _] = a; + | -- value partially moved here +LL | let [ref _y @ .., _, _] = a; + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [(ref _x, _), _, _] = a; + | +++ + +error[E0382]: borrow of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:48:16 + | +LL | let [.., (_x, _)] = a; + | -- value partially moved here +LL | let [_, _, ref _y @ ..] = a; + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., (ref _x, _)] = a; + | +++ + +error[E0382]: borrow of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use.rs:54:11 + | +LL | let [_y @ .., _, _] = a; + | -- value moved here +LL | let [(ref _x, _), _, _] = a; + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _y @ .., _, _] = a; + | +++ + +error[E0382]: borrow of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array-use.rs:60:15 + | +LL | let [_, _, _y @ ..] = a; + | -- value moved here +LL | let [.., (ref _x, _)] = a; + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _y @ ..] = a; + | +++ + +error[E0382]: borrow of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:68:13 + | +LL | let [x @ .., _] = a; + | - value partially moved here +LL | let [_, ref _y @ ..] = a; + | ^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref x @ .., _] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:76:5 + | +LL | let [_, _, _x] = a; + | -- value partially moved here +LL | a[2] = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:82:5 + | +LL | let [_, _, (_x, _)] = a; + | -- value partially moved here +LL | a[2].1 = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:88:5 + | +LL | let [_, _, _x @ ..] = a; + | -- value partially moved here +LL | a[0] = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x @ ..] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array-use.rs:94:5 + | +LL | let [_, _, _x @ ..] = a; + | -- value partially moved here +LL | a[0].1 = Default::default(); + | ^^^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x @ ..] = a; + | +++ + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-out-from-array.rs b/tests/ui/borrowck/borrowck-move-out-from-array.rs new file mode 100644 index 000000000..83755812f --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array.rs @@ -0,0 +1,71 @@ +fn array() -> [(String, String); 3] { + Default::default() +} + +// Const Index + Const Index + +fn move_out_from_begin_and_end() { + let a = array(); + let [_, _, _x] = a; + let [.., _y] = a; //~ ERROR [E0382] +} + +fn move_out_from_begin_field_and_end() { + let a = array(); + let [_, _, (_x, _)] = a; + let [.., _y] = a; //~ ERROR [E0382] +} + +fn move_out_from_begin_field_and_end_field() { + let a = array(); + let [_, _, (_x, _)] = a; + let [.., (_y, _)] = a; //~ ERROR [E0382] +} + +// Const Index + Slice + +fn move_out_by_const_index_and_subslice() { + let a = array(); + let [_x, _, _] = a; + let [_y @ .., _, _] = a; //~ ERROR [E0382] +} + +fn move_out_by_const_index_end_and_subslice() { + let a = array(); + let [.., _x] = a; + let [_, _, _y @ ..] = a; //~ ERROR [E0382] +} + +fn move_out_by_const_index_field_and_subslice() { + let a = array(); + let [(_x, _), _, _] = a; + let [_y @ .., _, _] = a; //~ ERROR [E0382] +} + +fn move_out_by_const_index_end_field_and_subslice() { + let a = array(); + let [.., (_x, _)] = a; + let [_, _, _y @ ..] = a; //~ ERROR [E0382] +} + +fn move_out_by_subslice_and_const_index_field() { + let a = array(); + let [_y @ .., _, _] = a; + let [(_x, _), _, _] = a; //~ ERROR [E0382] +} + +fn move_out_by_subslice_and_const_index_end_field() { + let a = array(); + let [_, _, _y @ ..] = a; + let [.., (_x, _)] = a; //~ ERROR [E0382] +} + +// Slice + Slice + +fn move_out_by_subslice_and_subslice() { + let a = array(); + let [x @ .., _] = a; + let [_, _y @ ..] = a; //~ ERROR [E0382] +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-from-array.stderr b/tests/ui/borrowck/borrowck-move-out-from-array.stderr new file mode 100644 index 000000000..dd456681f --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-from-array.stderr @@ -0,0 +1,143 @@ +error[E0382]: use of moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array.rs:10:14 + | +LL | let [_, _, _x] = a; + | -- value moved here +LL | let [.., _y] = a; + | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x] = a; + | +++ + +error[E0382]: use of partially moved value: `a[..]` + --> $DIR/borrowck-move-out-from-array.rs:16:14 + | +LL | let [_, _, (_x, _)] = a; + | -- value partially moved here +LL | let [.., _y] = a; + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ + +error[E0382]: use of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array.rs:22:15 + | +LL | let [_, _, (_x, _)] = a; + | -- value moved here +LL | let [.., (_y, _)] = a; + | ^^ value used here after move + | + = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array.rs:30:10 + | +LL | let [_x, _, _] = a; + | -- value partially moved here +LL | let [_y @ .., _, _] = a; + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _x, _, _] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array.rs:36:16 + | +LL | let [.., _x] = a; + | -- value partially moved here +LL | let [_, _, _y @ ..] = a; + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., ref _x] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array.rs:42:10 + | +LL | let [(_x, _), _, _] = a; + | -- value partially moved here +LL | let [_y @ .., _, _] = a; + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [(ref _x, _), _, _] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array.rs:48:16 + | +LL | let [.., (_x, _)] = a; + | -- value partially moved here +LL | let [_, _, _y @ ..] = a; + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., (ref _x, _)] = a; + | +++ + +error[E0382]: use of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array.rs:54:11 + | +LL | let [_y @ .., _, _] = a; + | -- value moved here +LL | let [(_x, _), _, _] = a; + | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _y @ .., _, _] = a; + | +++ + +error[E0382]: use of moved value: `a[..].0` + --> $DIR/borrowck-move-out-from-array.rs:60:15 + | +LL | let [_, _, _y @ ..] = a; + | -- value moved here +LL | let [.., (_x, _)] = a; + | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _y @ ..] = a; + | +++ + +error[E0382]: use of partially moved value: `a` + --> $DIR/borrowck-move-out-from-array.rs:68:13 + | +LL | let [x @ .., _] = a; + | - value partially moved here +LL | let [_, _y @ ..] = a; + | ^^ value used here after partial move + | + = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref x @ .., _] = a; + | +++ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs new file mode 100644 index 000000000..0b9e7102c --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs @@ -0,0 +1,6 @@ +use std::rc::Rc; + +pub fn main() { + let _x = Rc::new(vec![1, 2]).into_iter(); + //~^ ERROR [E0507] +} diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr new file mode 100644 index 000000000..87135f0bb --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr @@ -0,0 +1,19 @@ +error[E0507]: cannot move out of an `Rc` + --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:4:14 + | +LL | let _x = Rc::new(vec![1, 2]).into_iter(); + | ^^^^^^^^^^^^^^^^^^^^----------- + | | | + | | value moved due to this method call + | move occurs because value has type `Vec`, which does not implement the `Copy` trait + | +note: `into_iter` takes ownership of the receiver `self`, which moves value + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | let _x = Rc::new(vec![1, 2]).clone().into_iter(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs b/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs new file mode 100644 index 000000000..ecb135f68 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.rs @@ -0,0 +1,6 @@ +use std::rc::Rc; + +pub fn main() { + let _x = *Rc::new("hi".to_string()); + //~^ ERROR cannot move out of an `Rc` +} diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr b/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr new file mode 100644 index 000000000..599fa1e88 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-deref.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of an `Rc` + --> $DIR/borrowck-move-out-of-overloaded-deref.rs:4:14 + | +LL | let _x = *Rc::new("hi".to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let _x = *Rc::new("hi".to_string()); +LL + let _x = Rc::new("hi".to_string()); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.rs b/tests/ui/borrowck/borrowck-move-out-of-static-item.rs new file mode 100644 index 000000000..d01fb2618 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.rs @@ -0,0 +1,16 @@ +// Ensure that moves out of static items is forbidden + +struct Foo { + foo: isize, +} + +static BAR: Foo = Foo { foo: 5 }; + + +fn test(f: Foo) { + let _f = Foo{foo: 4, ..f}; +} + +fn main() { + test(BAR); //~ ERROR cannot move out of static item `BAR` [E0507] +} diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr new file mode 100644 index 000000000..edf8c954f --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of static item `BAR` + --> $DIR/borrowck-move-out-of-static-item.rs:15:10 + | +LL | test(BAR); + | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed new file mode 100644 index 000000000..c463c6559 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed @@ -0,0 +1,24 @@ +// run-rustfix +#![allow(unused)] +struct S {f:String} +impl Drop for S { + fn drop(&mut self) { println!("{}", self.f); } +} + +fn move_in_match() { + match (S {f:"foo".to_string()}) { + //~^ ERROR [E0509] + S {f:ref _s} => {} + } +} + +fn move_in_let() { + let S {f:ref _s} = S {f:"foo".to_string()}; + //~^ ERROR [E0509] +} + +fn move_in_fn_arg(S {f:ref _s}: S) { + //~^ ERROR [E0509] +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs new file mode 100644 index 000000000..93183062d --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs @@ -0,0 +1,24 @@ +// run-rustfix +#![allow(unused)] +struct S {f:String} +impl Drop for S { + fn drop(&mut self) { println!("{}", self.f); } +} + +fn move_in_match() { + match (S {f:"foo".to_string()}) { + //~^ ERROR [E0509] + S {f:_s} => {} + } +} + +fn move_in_let() { + let S {f:_s} = S {f:"foo".to_string()}; + //~^ ERROR [E0509] +} + +fn move_in_fn_arg(S {f:_s}: S) { + //~^ ERROR [E0509] +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr new file mode 100644 index 000000000..58f706c65 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr @@ -0,0 +1,49 @@ +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:9:11 + | +LL | match (S {f:"foo".to_string()}) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here +LL | +LL | S {f:_s} => {} + | -- + | | + | data moved here + | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | S {f:ref _s} => {} + | +++ + +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:16:20 + | +LL | let S {f:_s} = S {f:"foo".to_string()}; + | -- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let S {f:ref _s} = S {f:"foo".to_string()}; + | +++ + +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:20:19 + | +LL | fn move_in_fn_arg(S {f:_s}: S) { + | ^^^^^--^ + | | | + | | data moved here + | | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | cannot move out of here + | +help: consider borrowing the pattern binding + | +LL | fn move_in_fn_arg(S {f:ref _s}: S) { + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed new file mode 100644 index 000000000..bc2ddf85f --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed @@ -0,0 +1,24 @@ +// run-rustfix +#![allow(unused)] +struct S(String); +impl Drop for S { + fn drop(&mut self) { } +} + +fn move_in_match() { + match S("foo".to_string()) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + S(ref _s) => {} + } +} + +fn move_in_let() { + let S(ref _s) = S("foo".to_string()); + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait +} + +fn move_in_fn_arg(S(ref _s): S) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs new file mode 100644 index 000000000..f050bce87 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs @@ -0,0 +1,24 @@ +// run-rustfix +#![allow(unused)] +struct S(String); +impl Drop for S { + fn drop(&mut self) { } +} + +fn move_in_match() { + match S("foo".to_string()) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + S(_s) => {} + } +} + +fn move_in_let() { + let S(_s) = S("foo".to_string()); + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait +} + +fn move_in_fn_arg(S(_s): S) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr new file mode 100644 index 000000000..160a1f99f --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr @@ -0,0 +1,49 @@ +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:9:11 + | +LL | match S("foo".to_string()) { + | ^^^^^^^^^^^^^^^^^^^^ cannot move out of here +LL | +LL | S(_s) => {} + | -- + | | + | data moved here + | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | S(ref _s) => {} + | +++ + +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:16:17 + | +LL | let S(_s) = S("foo".to_string()); + | -- ^^^^^^^^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let S(ref _s) = S("foo".to_string()); + | +++ + +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:20:19 + | +LL | fn move_in_fn_arg(S(_s): S) { + | ^^--^ + | | | + | | data moved here + | | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | cannot move out of here + | +help: consider borrowing the pattern binding + | +LL | fn move_in_fn_arg(S(ref _s): S) { + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/borrowck/borrowck-move-out-of-vec-tail.rs b/tests/ui/borrowck/borrowck-move-out-of-vec-tail.rs new file mode 100644 index 000000000..8ece81a3c --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-vec-tail.rs @@ -0,0 +1,33 @@ +// Test that we do not permit moves from &[] matched by a vec pattern. + +#[derive(Clone, Debug)] +struct Foo { + string: String +} + +pub fn main() { + let x = vec![ + Foo { string: "foo".to_string() }, + Foo { string: "bar".to_string() }, + Foo { string: "baz".to_string() } + ]; + let x: &[Foo] = &x; + match *x { + [_, ref tail @ ..] => { + match tail { + //~^ ERROR cannot move out of type `[Foo]` + &[Foo { string: a }, + Foo { string: b }] => { + } + _ => { + unreachable!(); + } + } + let z = tail[0].clone(); + println!("{:?}", z); + } + _ => { + unreachable!(); + } + } +} diff --git a/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr new file mode 100644 index 000000000..9ff20a1f4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-out-of-vec-tail.stderr @@ -0,0 +1,21 @@ +error[E0508]: cannot move out of type `[Foo]`, a non-copy slice + --> $DIR/borrowck-move-out-of-vec-tail.rs:17:19 + | +LL | match tail { + | ^^^^ cannot move out of here +LL | +LL | &[Foo { string: a }, + | - data moved here +LL | Foo { string: b }] => { + | - ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - &[Foo { string: a }, +LL + [Foo { string: a }, + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.rs b/tests/ui/borrowck/borrowck-move-subcomponent.rs new file mode 100644 index 000000000..38abd1932 --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-subcomponent.rs @@ -0,0 +1,17 @@ +// Tests that the borrow checker checks all components of a path when moving +// out. + + + +struct S { + x : Box +} + +fn f(_: T) {} + +fn main() { + let a : S = S { x : Box::new(1) }; + let pb = &a; + let S { x: ax } = a; //~ ERROR cannot move out + f(pb); +} diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr new file mode 100644 index 000000000..8c9083fcf --- /dev/null +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `a.x` because it is borrowed + --> $DIR/borrowck-move-subcomponent.rs:15:14 + | +LL | let pb = &a; + | -- borrow of `a` occurs here +LL | let S { x: ax } = a; + | ^^ move out of `a.x` occurs here +LL | f(pb); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs b/tests/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs new file mode 100644 index 000000000..96d266350 --- /dev/null +++ b/tests/ui/borrowck/borrowck-multiple-borrows-interior-boxes.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test case from #39963. + +#[derive(Clone)] +struct Foo(Option>, Option>); + +fn test(f: &mut Foo) { + match *f { + Foo(Some(ref mut left), Some(ref mut right)) => match **left { + Foo(Some(ref mut left), Some(ref mut right)) => panic!(), + _ => panic!(), + }, + _ => panic!(), + } +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-multiple-captures.rs b/tests/ui/borrowck/borrowck-multiple-captures.rs new file mode 100644 index 000000000..57b3819ac --- /dev/null +++ b/tests/ui/borrowck/borrowck-multiple-captures.rs @@ -0,0 +1,61 @@ +use std::thread; + + +fn borrow(_: &T) { } + + +fn different_vars_after_borrows() { + let x1: Box<_> = Box::new(1); + let p1 = &x1; + let x2: Box<_> = Box::new(2); + let p2 = &x2; + thread::spawn(move|| { + //~^ ERROR cannot move out of `x1` because it is borrowed + //~| ERROR cannot move out of `x2` because it is borrowed + drop(x1); + drop(x2); + }); + borrow(&*p1); + borrow(&*p2); +} + +fn different_vars_after_moves() { + let x1: Box<_> = Box::new(1); + drop(x1); + let x2: Box<_> = Box::new(2); + drop(x2); + thread::spawn(move|| { + //~^ ERROR use of moved value: `x1` + //~| ERROR use of moved value: `x2` + drop(x1); + drop(x2); + }); +} + +fn same_var_after_borrow() { + let x: Box<_> = Box::new(1); + let p = &x; + thread::spawn(move|| { + //~^ ERROR cannot move out of `x` because it is borrowed + drop(x); + drop(x); //~ ERROR use of moved value: `x` + }); + borrow(&*p); +} + +fn same_var_after_move() { + let x: Box<_> = Box::new(1); + drop(x); + thread::spawn(move|| { + //~^ ERROR use of moved value: `x` + drop(x); + drop(x); //~ ERROR use of moved value: `x` + }); +} + +fn main() { + different_vars_after_borrows(); + different_vars_after_moves(); + same_var_after_borrow(); + same_var_after_move(); +} diff --git a/tests/ui/borrowck/borrowck-multiple-captures.stderr b/tests/ui/borrowck/borrowck-multiple-captures.stderr new file mode 100644 index 000000000..f94cbc30d --- /dev/null +++ b/tests/ui/borrowck/borrowck-multiple-captures.stderr @@ -0,0 +1,122 @@ +error[E0505]: cannot move out of `x1` because it is borrowed + --> $DIR/borrowck-multiple-captures.rs:12:19 + | +LL | let p1 = &x1; + | --- borrow of `x1` occurs here +... +LL | thread::spawn(move|| { + | ^^^^^^ move out of `x1` occurs here +... +LL | drop(x1); + | -- move occurs due to use in closure +... +LL | borrow(&*p1); + | ---- borrow later used here + +error[E0505]: cannot move out of `x2` because it is borrowed + --> $DIR/borrowck-multiple-captures.rs:12:19 + | +LL | let p2 = &x2; + | --- borrow of `x2` occurs here +LL | thread::spawn(move|| { + | ^^^^^^ move out of `x2` occurs here +... +LL | drop(x2); + | -- move occurs due to use in closure +... +LL | borrow(&*p2); + | ---- borrow later used here + +error[E0382]: use of moved value: `x1` + --> $DIR/borrowck-multiple-captures.rs:27:19 + | +LL | let x1: Box<_> = Box::new(1); + | -- move occurs because `x1` has type `Box`, which does not implement the `Copy` trait +LL | drop(x1); + | -- value moved here +... +LL | thread::spawn(move|| { + | ^^^^^^ value used here after move +... +LL | drop(x1); + | -- use occurs due to use in closure + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x1.clone()); + | ++++++++ + +error[E0382]: use of moved value: `x2` + --> $DIR/borrowck-multiple-captures.rs:27:19 + | +LL | let x2: Box<_> = Box::new(2); + | -- move occurs because `x2` has type `Box`, which does not implement the `Copy` trait +LL | drop(x2); + | -- value moved here +LL | thread::spawn(move|| { + | ^^^^^^ value used here after move +... +LL | drop(x2); + | -- use occurs due to use in closure + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x2.clone()); + | ++++++++ + +error[E0382]: use of moved value: `x` + --> $DIR/borrowck-multiple-captures.rs:41:14 + | +LL | drop(x); + | - value moved here +LL | drop(x); + | ^ value used here after move + | + = note: move occurs because `x` has type `Box`, which does not implement the `Copy` trait + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/borrowck-multiple-captures.rs:38:19 + | +LL | let p = &x; + | -- borrow of `x` occurs here +LL | thread::spawn(move|| { + | ^^^^^^ move out of `x` occurs here +LL | +LL | drop(x); + | - move occurs due to use in closure +... +LL | borrow(&*p); + | --- borrow later used here + +error[E0382]: use of moved value: `x` + --> $DIR/borrowck-multiple-captures.rs:52:14 + | +LL | drop(x); + | - value moved here +LL | drop(x); + | ^ value used here after move + | + = note: move occurs because `x` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/borrowck-multiple-captures.rs:49:19 + | +LL | let x: Box<_> = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | drop(x); + | - value moved here +LL | thread::spawn(move|| { + | ^^^^^^ value used here after move +LL | +LL | drop(x); + | - use occurs due to use in closure + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x.clone()); + | ++++++++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.rs b/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.rs new file mode 100644 index 000000000..a79a239cb --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.rs @@ -0,0 +1,6 @@ +fn main() { + let x: isize = 3; + let y: &mut isize = &mut x; //~ ERROR cannot borrow + *y = 5; + println!("{}", *y); +} diff --git a/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr b/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr new file mode 100644 index 000000000..20528e3f0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-mut-addr-of-imm-var.rs:3:25 + | +LL | let y: &mut isize = &mut x; + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x: isize = 3; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-mut-borrow-linear-errors.rs b/tests/ui/borrowck/borrowck-mut-borrow-linear-errors.rs new file mode 100644 index 000000000..e3d76398b --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-borrow-linear-errors.rs @@ -0,0 +1,15 @@ +// Test to ensure we only report an error for the first issued loan that +// conflicts with a new loan, as opposed to every issued loan. This keeps us +// down to O(n) errors (for n problem lines), instead of O(n^2) errors. + +fn main() { + let mut x = 1; + let mut addr = vec![]; + loop { + match 1 { + 1 => { addr.push(&mut x); } //~ ERROR [E0499] + 2 => { addr.push(&mut x); } //~ ERROR [E0499] + _ => { addr.push(&mut x); } //~ ERROR [E0499] + } + } +} diff --git a/tests/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr b/tests/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr new file mode 100644 index 000000000..d2b845619 --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr @@ -0,0 +1,35 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-mut-borrow-linear-errors.rs:10:30 + | +LL | 1 => { addr.push(&mut x); } + | ^^^^^^ second mutable borrow occurs here +LL | 2 => { addr.push(&mut x); } +LL | _ => { addr.push(&mut x); } + | ----------------- + | | | + | | first mutable borrow occurs here + | first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-mut-borrow-linear-errors.rs:11:30 + | +LL | 2 => { addr.push(&mut x); } + | ^^^^^^ second mutable borrow occurs here +LL | _ => { addr.push(&mut x); } + | ----------------- + | | | + | | first mutable borrow occurs here + | first borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-mut-borrow-linear-errors.rs:12:30 + | +LL | _ => { addr.push(&mut x); } + | ----------^^^^^^- + | | | + | | `x` was mutably borrowed here in the previous iteration of the loop + | first borrow used here, in later iteration of loop + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs b/tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs new file mode 100644 index 000000000..6174893ba --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs @@ -0,0 +1,28 @@ +// Test that attempt to mutably borrow `&mut` pointer while pointee is +// borrowed yields an error. +// +// Example from compiler/rustc_borrowck/borrowck/README.md + + + +fn foo<'a>(mut t0: &'a mut isize, + mut t1: &'a mut isize) { + let p: &isize = &*t0; // Freezes `*t0` + let mut t2 = &mut t0; //~ ERROR cannot borrow `t0` + **t2 += 1; // Mutates `*t0` + p.use_ref(); +} + +fn bar<'a>(mut t0: &'a mut isize, + mut t1: &'a mut isize) { + let p: &mut isize = &mut *t0; // Claims `*t0` + let mut t2 = &mut t0; //~ ERROR cannot borrow `t0` + **t2 += 1; // Mutates `*t0` but not through `*p` + p.use_mut(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr new file mode 100644 index 000000000..ef811b849 --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.stderr @@ -0,0 +1,26 @@ +error[E0502]: cannot borrow `t0` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:11:18 + | +LL | let p: &isize = &*t0; // Freezes `*t0` + | ---- immutable borrow occurs here +LL | let mut t2 = &mut t0; + | ^^^^^^^ mutable borrow occurs here +LL | **t2 += 1; // Mutates `*t0` +LL | p.use_ref(); + | ----------- immutable borrow later used here + +error[E0499]: cannot borrow `t0` as mutable more than once at a time + --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:19:18 + | +LL | let p: &mut isize = &mut *t0; // Claims `*t0` + | -------- first mutable borrow occurs here +LL | let mut t2 = &mut t0; + | ^^^^^^^ second mutable borrow occurs here +LL | **t2 += 1; // Mutates `*t0` but not through `*p` +LL | p.use_mut(); + | ----------- first borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs b/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs new file mode 100644 index 000000000..8e23571ce --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.rs @@ -0,0 +1,8 @@ +fn write(v: &mut [isize]) { + v[0] += 1; +} + +fn main() { + let v = vec![1, 2, 3]; + write(&mut v); //~ ERROR cannot borrow +} diff --git a/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr b/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr new file mode 100644 index 000000000..8ab472e64 --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/borrowck-mut-slice-of-imm-vec.rs:7:11 + | +LL | write(&mut v); + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v = vec![1, 2, 3]; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-mut-uniq.rs b/tests/ui/borrowck/borrowck-mut-uniq.rs new file mode 100644 index 000000000..255b4995b --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-uniq.rs @@ -0,0 +1,32 @@ +// run-pass + +use std::mem::swap; + +#[derive(Debug)] +struct Ints {sum: Box, values: Vec } + +fn add_int(x: &mut Ints, v: isize) { + *x.sum += v; + let mut values = Vec::new(); + swap(&mut values, &mut x.values); + values.push(v); + swap(&mut values, &mut x.values); +} + +fn iter_ints(x: &Ints, mut f: F) -> bool where F: FnMut(&isize) -> bool { + let l = x.values.len(); + (0..l).all(|i| f(&x.values[i])) +} + +pub fn main() { + let mut ints: Box<_> = Box::new(Ints {sum: Box::new(0), values: Vec::new()}); + add_int(&mut *ints, 22); + add_int(&mut *ints, 44); + + iter_ints(&*ints, |i| { + println!("isize = {:?}", *i); + true + }); + + println!("ints={:?}", ints); +} diff --git a/tests/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs b/tests/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs new file mode 100644 index 000000000..d2b0c0154 --- /dev/null +++ b/tests/ui/borrowck/borrowck-mut-vec-as-imm-slice.rs @@ -0,0 +1,16 @@ +// run-pass + + +fn want_slice(v: &[isize]) -> isize { + let mut sum = 0; + for i in v { sum += *i; } + sum +} + +fn has_mut_vec(v: Vec ) -> isize { + want_slice(&v) +} + +pub fn main() { + assert_eq!(has_mut_vec(vec![1, 2, 3]), 6); +} diff --git a/tests/ui/borrowck/borrowck-mutate-in-guard.rs b/tests/ui/borrowck/borrowck-mutate-in-guard.rs new file mode 100644 index 000000000..d80a9e815 --- /dev/null +++ b/tests/ui/borrowck/borrowck-mutate-in-guard.rs @@ -0,0 +1,34 @@ +#![feature(if_let_guard)] + +enum Enum<'a> { + A(&'a isize), + B(bool), +} + +fn if_guard() -> isize { + let mut n = 42; + let mut x = Enum::A(&mut n); + match x { + Enum::A(_) if { x = Enum::B(false); false } => 1, + //~^ ERROR cannot assign `x` in match guard + Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, + //~^ ERROR cannot mutably borrow `x` in match guard + Enum::A(p) => *p, + Enum::B(_) => 2, + } +} + +fn if_let_guard() -> isize { + let mut n = 42; + let mut x = Enum::A(&mut n); + match x { + Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1, + //~^ ERROR cannot assign `x` in match guard + Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1, + //~^ ERROR cannot mutably borrow `x` in match guard + Enum::A(p) => *p, + Enum::B(_) => 2, + } +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-mutate-in-guard.stderr b/tests/ui/borrowck/borrowck-mutate-in-guard.stderr new file mode 100644 index 000000000..dbb3272fd --- /dev/null +++ b/tests/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -0,0 +1,37 @@ +error[E0510]: cannot assign `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:12:25 + | +LL | match x { + | - value is immutable in match guard +LL | Enum::A(_) if { x = Enum::B(false); false } => 1, + | ^^^^^^^^^^^^^^^^^^ cannot assign + +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:14:33 + | +LL | match x { + | - value is immutable in match guard +... +LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, + | ^^^^^^ cannot mutably borrow + +error[E0510]: cannot assign `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:25:40 + | +LL | match x { + | - value is immutable in match guard +LL | Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1, + | ^^^^^^^^^^^^^^^^^^ cannot assign + +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:27:48 + | +LL | match x { + | - value is immutable in match guard +... +LL | Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1, + | ^^^^^^ cannot mutably borrow + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs b/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs new file mode 100644 index 000000000..f035049d8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.rs @@ -0,0 +1,20 @@ +struct Node_ { + a: Box +} + +enum Cycle { + Node(Node_), + Empty, +} + +fn main() { + let mut x: Box<_> = Box::new(Cycle::Node(Node_ {a: Box::new(Cycle::Empty)})); + + // Create a cycle! + match *x { + Cycle::Node(ref mut y) => { + y.a = x; //~ ERROR cannot move out of + } + Cycle::Empty => {} + }; +} diff --git a/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr b/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr new file mode 100644 index 000000000..3462b7610 --- /dev/null +++ b/tests/ui/borrowck/borrowck-no-cycle-in-exchange-heap.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/borrowck-no-cycle-in-exchange-heap.rs:16:15 + | +LL | Cycle::Node(ref mut y) => { + | --------- borrow of `x.0` occurs here +LL | y.a = x; + | --- ^ move out of `x` occurs here + | | + | borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-object-lifetime.rs b/tests/ui/borrowck/borrowck-object-lifetime.rs new file mode 100644 index 000000000..137a9adbc --- /dev/null +++ b/tests/ui/borrowck/borrowck-object-lifetime.rs @@ -0,0 +1,40 @@ +// Test that borrows that occur due to calls to object methods +// properly "claim" the object path. + + + +trait Foo { + fn borrowed(&self) -> &(); + fn mut_borrowed(&mut self) -> &(); +} + +fn borrowed_receiver(x: &dyn Foo) { + let y = x.borrowed(); + let z = x.borrowed(); + z.use_ref(); + y.use_ref(); +} + +fn mut_borrowed_receiver(x: &mut dyn Foo) { + let y = x.borrowed(); + let z = x.mut_borrowed(); //~ ERROR cannot borrow + y.use_ref(); +} + +fn mut_owned_receiver(mut x: Box) { + let y = x.borrowed(); + let z = &mut x; //~ ERROR cannot borrow + y.use_ref(); +} + +fn imm_owned_receiver(mut x: Box) { + let y = x.borrowed(); + let z = &x; + z.use_ref(); + y.use_ref(); +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-object-lifetime.stderr b/tests/ui/borrowck/borrowck-object-lifetime.stderr new file mode 100644 index 000000000..215ed760a --- /dev/null +++ b/tests/ui/borrowck/borrowck-object-lifetime.stderr @@ -0,0 +1,23 @@ +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-object-lifetime.rs:20:13 + | +LL | let y = x.borrowed(); + | ------------ immutable borrow occurs here +LL | let z = x.mut_borrowed(); + | ^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | y.use_ref(); + | ----------- immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-object-lifetime.rs:26:13 + | +LL | let y = x.borrowed(); + | ------------ immutable borrow occurs here +LL | let z = &mut x; + | ^^^^^^ mutable borrow occurs here +LL | y.use_ref(); + | ----------- immutable borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-or-init.rs b/tests/ui/borrowck/borrowck-or-init.rs new file mode 100644 index 000000000..079cf899e --- /dev/null +++ b/tests/ui/borrowck/borrowck-or-init.rs @@ -0,0 +1,6 @@ +fn main() { + let i: isize; + + println!("{}", false || { i = 5; true }); + println!("{}", i); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-or-init.stderr b/tests/ui/borrowck/borrowck-or-init.stderr new file mode 100644 index 000000000..16d66bf40 --- /dev/null +++ b/tests/ui/borrowck/borrowck-or-init.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `i` is possibly-uninitialized + --> $DIR/borrowck-or-init.rs:5:20 + | +LL | let i: isize; + | - binding declared here but left uninitialized +LL | +LL | println!("{}", false || { i = 5; true }); + | ----- binding initialized here in some conditions +LL | println!("{}", i); + | ^ `i` used here but it is possibly-uninitialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-overloaded-call.rs b/tests/ui/borrowck/borrowck-overloaded-call.rs new file mode 100644 index 000000000..7b16bf666 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-call.rs @@ -0,0 +1,80 @@ +#![feature(fn_traits, unboxed_closures)] + +use std::ops::{Fn, FnMut, FnOnce}; + +struct SFn { + x: isize, + y: isize, +} + +impl Fn<(isize,)> for SFn { + extern "rust-call" fn call(&self, (z,): (isize,)) -> isize { + self.x * self.y * z + } +} + +impl FnMut<(isize,)> for SFn { + extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) } +} + +impl FnOnce<(isize,)> for SFn { + type Output = isize; + extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) } +} + +struct SFnMut { + x: isize, + y: isize, +} + +impl FnMut<(isize,)> for SFnMut { + extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { + self.x * self.y * z + } +} + +impl FnOnce<(isize,)> for SFnMut { + type Output = isize; + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } +} + +struct SFnOnce { + x: String, +} + +impl FnOnce<(String,)> for SFnOnce { + type Output = usize; + + extern "rust-call" fn call_once(self, (z,): (String,)) -> usize { + self.x.len() + z.len() + } +} + +fn f() { + let mut s = SFn { + x: 1, + y: 2, + }; + let sp = &mut s; + s(3); //~ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable + use_mut(sp); +} +fn g() { + let s = SFnMut { + x: 1, + y: 2, + }; + s(3); //~ ERROR cannot borrow `s` as mutable, as it is not declared as mutable +} + +fn h() { + let s = SFnOnce { + x: "hello".to_string(), + }; + s(" world".to_string()); + s(" world".to_string()); //~ ERROR use of moved value: `s` +} + +fn main() {} + +fn use_mut(_: &mut T) { } diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr new file mode 100644 index 000000000..723b19f41 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -0,0 +1,36 @@ +error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-overloaded-call.rs:59:5 + | +LL | let sp = &mut s; + | ------ mutable borrow occurs here +LL | s(3); + | ^ immutable borrow occurs here +LL | use_mut(sp); + | -- mutable borrow later used here + +error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable + --> $DIR/borrowck-overloaded-call.rs:67:5 + | +LL | s(3); + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut s = SFnMut { + | +++ + +error[E0382]: use of moved value: `s` + --> $DIR/borrowck-overloaded-call.rs:75:5 + | +LL | let s = SFnOnce { + | - move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait +... +LL | s(" world".to_string()); + | - value moved here +LL | s(" world".to_string()); + | ^ value used here after move + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0502, E0596. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs new file mode 100644 index 000000000..0e3e01a93 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs @@ -0,0 +1,36 @@ +// Check that we properly record borrows when we are doing an +// overloaded, autoderef of a value obtained via an overloaded index +// operator. The accounting of the all the implicit things going on +// here is rather subtle. Issue #20232. + +use std::ops::{Deref, Index}; + +struct MyVec { x: T } + +impl Index for MyVec { + type Output = T; + fn index(&self, _: usize) -> &T { + &self.x + } +} + +struct MyPtr { x: T } + +impl Deref for MyPtr { + type Target = T; + fn deref(&self) -> &T { + &self.x + } +} + +struct Foo { f: usize } + +fn main() { + let mut v = MyVec { x: MyPtr { x: Foo { f: 22 } } }; + let i = &v[0].f; + v = MyVec { x: MyPtr { x: Foo { f: 23 } } }; + //~^ ERROR cannot assign to `v` because it is borrowed + read(*i); +} + +fn read(_: usize) { } diff --git a/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr new file mode 100644 index 000000000..5d52e4919 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `v` because it is borrowed + --> $DIR/borrowck-overloaded-index-and-overloaded-deref.rs:31:5 + | +LL | let i = &v[0].f; + | - borrow of `v` occurs here +LL | v = MyVec { x: MyPtr { x: Foo { f: 23 } } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `v` occurs here +LL | +LL | read(*i); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.rs b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.rs new file mode 100644 index 000000000..3d3a3afd3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.rs @@ -0,0 +1,97 @@ +// Test that we still see borrowck errors of various kinds when using +// indexing and autoderef in combination. + +use std::ops::{Index, IndexMut}; + + + +struct Foo { + x: isize, + y: isize, +} + +impl<'a> Index<&'a String> for Foo { + type Output = isize; + + fn index(&self, z: &String) -> &isize { + if *z == "x" { + &self.x + } else { + &self.y + } + } +} + +impl<'a> IndexMut<&'a String> for Foo { + fn index_mut(&mut self, z: &String) -> &mut isize { + if *z == "x" { + &mut self.x + } else { + &mut self.y + } + } +} + +fn test1(mut f: Box, s: String) { + let p = &mut f[&s]; + let q = &f[&s]; //~ ERROR cannot borrow + p.use_mut(); +} + +fn test2(mut f: Box, s: String) { + let p = &mut f[&s]; + let q = &mut f[&s]; //~ ERROR cannot borrow + p.use_mut(); +} + +struct Bar { + foo: Foo +} + +fn test3(mut f: Box, s: String) { + let p = &mut f.foo[&s]; + let q = &mut f.foo[&s]; //~ ERROR cannot borrow + p.use_mut(); +} + +fn test4(mut f: Box, s: String) { + let p = &f.foo[&s]; + let q = &f.foo[&s]; + p.use_ref(); +} + +fn test5(mut f: Box, s: String) { + let p = &f.foo[&s]; + let q = &mut f.foo[&s]; //~ ERROR cannot borrow + p.use_ref(); +} + +fn test6(mut f: Box, g: Foo, s: String) { + let p = &f.foo[&s]; + f.foo = g; //~ ERROR cannot assign + p.use_ref(); +} + +fn test7(mut f: Box, g: Bar, s: String) { + let p = &f.foo[&s]; + *f = g; //~ ERROR cannot assign + p.use_ref(); +} + +fn test8(mut f: Box, g: Foo, s: String) { + let p = &mut f.foo[&s]; + f.foo = g; //~ ERROR cannot assign + p.use_mut(); +} + +fn test9(mut f: Box, g: Bar, s: String) { + let p = &mut f.foo[&s]; + *f = g; //~ ERROR cannot assign + p.use_mut(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr new file mode 100644 index 000000000..087f2ac79 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr @@ -0,0 +1,84 @@ +error[E0502]: cannot borrow `*f` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-overloaded-index-autoderef.rs:37:14 + | +LL | let p = &mut f[&s]; + | - mutable borrow occurs here +LL | let q = &f[&s]; + | ^ immutable borrow occurs here +LL | p.use_mut(); + | ----------- mutable borrow later used here + +error[E0499]: cannot borrow `*f` as mutable more than once at a time + --> $DIR/borrowck-overloaded-index-autoderef.rs:43:18 + | +LL | let p = &mut f[&s]; + | - first mutable borrow occurs here +LL | let q = &mut f[&s]; + | ^ second mutable borrow occurs here +LL | p.use_mut(); + | ----------- first borrow later used here + +error[E0499]: cannot borrow `f.foo` as mutable more than once at a time + --> $DIR/borrowck-overloaded-index-autoderef.rs:53:18 + | +LL | let p = &mut f.foo[&s]; + | ----- first mutable borrow occurs here +LL | let q = &mut f.foo[&s]; + | ^^^^^ second mutable borrow occurs here +LL | p.use_mut(); + | ----------- first borrow later used here + +error[E0502]: cannot borrow `f.foo` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-overloaded-index-autoderef.rs:65:18 + | +LL | let p = &f.foo[&s]; + | ----- immutable borrow occurs here +LL | let q = &mut f.foo[&s]; + | ^^^^^ mutable borrow occurs here +LL | p.use_ref(); + | ----------- immutable borrow later used here + +error[E0506]: cannot assign to `f.foo` because it is borrowed + --> $DIR/borrowck-overloaded-index-autoderef.rs:71:5 + | +LL | let p = &f.foo[&s]; + | ----- borrow of `f.foo` occurs here +LL | f.foo = g; + | ^^^^^^^^^ assignment to borrowed `f.foo` occurs here +LL | p.use_ref(); + | ----------- borrow later used here + +error[E0506]: cannot assign to `*f` because it is borrowed + --> $DIR/borrowck-overloaded-index-autoderef.rs:77:5 + | +LL | let p = &f.foo[&s]; + | ----- borrow of `*f` occurs here +LL | *f = g; + | ^^^^^^ assignment to borrowed `*f` occurs here +LL | p.use_ref(); + | ----------- borrow later used here + +error[E0506]: cannot assign to `f.foo` because it is borrowed + --> $DIR/borrowck-overloaded-index-autoderef.rs:83:5 + | +LL | let p = &mut f.foo[&s]; + | ----- borrow of `f.foo` occurs here +LL | f.foo = g; + | ^^^^^^^^^ assignment to borrowed `f.foo` occurs here +LL | p.use_mut(); + | ----------- borrow later used here + +error[E0506]: cannot assign to `*f` because it is borrowed + --> $DIR/borrowck-overloaded-index-autoderef.rs:89:5 + | +LL | let p = &mut f.foo[&s]; + | ----- borrow of `*f` occurs here +LL | *f = g; + | ^^^^^^ assignment to borrowed `*f` occurs here +LL | p.use_mut(); + | ----------- borrow later used here + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0499, E0502, E0506. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs b/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs new file mode 100644 index 000000000..344d75cc5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.rs @@ -0,0 +1,22 @@ +use std::ops::Index; + +struct MyVec { + data: Vec, +} + +impl Index for MyVec { + type Output = T; + + fn index(&self, i: usize) -> &T { + &self.data[i] + } +} + + + +fn main() { + let v = MyVec::> { data: vec![Box::new(1), Box::new(2), Box::new(3)] }; + let good = &v[0]; // Shouldn't fail here + let bad = v[0]; + //~^ ERROR cannot move out of index of `MyVec>` +} diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr b/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr new file mode 100644 index 000000000..f5f4817e9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-move-from-vec.stderr @@ -0,0 +1,14 @@ +error[E0507]: cannot move out of index of `MyVec>` + --> $DIR/borrowck-overloaded-index-move-from-vec.rs:20:15 + | +LL | let bad = v[0]; + | ^^^^ move occurs because value has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let bad = &v[0]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-index.rs b/tests/ui/borrowck/borrowck-overloaded-index-move-index.rs new file mode 100644 index 000000000..00f448314 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-move-index.rs @@ -0,0 +1,68 @@ +use std::ops::{Index, IndexMut}; + +struct Foo { + x: isize, + y: isize, +} + +impl Index for Foo { + type Output = isize; + + fn index(&self, z: String) -> &isize { + if z == "x" { + &self.x + } else { + &self.y + } + } +} + +impl IndexMut for Foo { + fn index_mut(&mut self, z: String) -> &mut isize { + if z == "x" { + &mut self.x + } else { + &mut self.y + } + } +} + +struct Bar { + x: isize, +} + +impl Index for Bar { + type Output = isize; + + fn index<'a>(&'a self, z: isize) -> &'a isize { + &self.x + } +} + +fn main() { + let mut f = Foo { + x: 1, + y: 2, + }; + let mut s = "hello".to_string(); + let rs = &mut s; + + println!("{}", f[s]); + //~^ ERROR cannot move out of `s` because it is borrowed + + f[s] = 10; + //~^ ERROR cannot move out of `s` because it is borrowed + //~| ERROR use of moved value: `s` + + let s = Bar { + x: 1, + }; + let i = 2; + let _j = &i; + println!("{}", s[i]); // no error, i is copy + println!("{}", s[i]); + + use_mut(rs); +} + +fn use_mut(_: &mut T) { } diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr new file mode 100644 index 000000000..fb0e274c2 --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr @@ -0,0 +1,45 @@ +error[E0505]: cannot move out of `s` because it is borrowed + --> $DIR/borrowck-overloaded-index-move-index.rs:50:22 + | +LL | let rs = &mut s; + | ------ borrow of `s` occurs here +LL | +LL | println!("{}", f[s]); + | ^ move out of `s` occurs here +... +LL | use_mut(rs); + | -- borrow later used here + +error[E0505]: cannot move out of `s` because it is borrowed + --> $DIR/borrowck-overloaded-index-move-index.rs:53:7 + | +LL | let rs = &mut s; + | ------ borrow of `s` occurs here +... +LL | f[s] = 10; + | ^ move out of `s` occurs here +... +LL | use_mut(rs); + | -- borrow later used here + +error[E0382]: use of moved value: `s` + --> $DIR/borrowck-overloaded-index-move-index.rs:53:7 + | +LL | let mut s = "hello".to_string(); + | ----- move occurs because `s` has type `String`, which does not implement the `Copy` trait +... +LL | println!("{}", f[s]); + | - value moved here +... +LL | f[s] = 10; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | println!("{}", f[s.clone()]); + | ++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-overloaded-index-ref-index.rs b/tests/ui/borrowck/borrowck-overloaded-index-ref-index.rs new file mode 100644 index 000000000..8adafaa8e --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-ref-index.rs @@ -0,0 +1,59 @@ +use std::ops::{Index, IndexMut}; + +struct Foo { + x: isize, + y: isize, +} + +impl<'a> Index<&'a String> for Foo { + type Output = isize; + + fn index(&self, z: &String) -> &isize { + if *z == "x" { + &self.x + } else { + &self.y + } + } +} + +impl<'a> IndexMut<&'a String> for Foo { + fn index_mut(&mut self, z: &String) -> &mut isize { + if *z == "x" { + &mut self.x + } else { + &mut self.y + } + } +} + +struct Bar { + x: isize, +} + +impl Index for Bar { + type Output = isize; + + fn index<'a>(&'a self, z: isize) -> &'a isize { + &self.x + } +} + +fn main() { + let mut f = Foo { + x: 1, + y: 2, + }; + let mut s = "hello".to_string(); + let rs = &mut s; + println!("{}", f[&s]); + //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable + f[&s] = 10; + //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable + let s = Bar { + x: 1, + }; + s[2] = 20; + //~^ ERROR cannot assign to data in an index of `Bar` + drop(rs); +} diff --git a/tests/ui/borrowck/borrowck-overloaded-index-ref-index.stderr b/tests/ui/borrowck/borrowck-overloaded-index-ref-index.stderr new file mode 100644 index 000000000..2f92c1ebe --- /dev/null +++ b/tests/ui/borrowck/borrowck-overloaded-index-ref-index.stderr @@ -0,0 +1,35 @@ +error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-overloaded-index-ref-index.rs:49:22 + | +LL | let rs = &mut s; + | ------ mutable borrow occurs here +LL | println!("{}", f[&s]); + | ^^ immutable borrow occurs here +... +LL | drop(rs); + | -- mutable borrow later used here + +error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-overloaded-index-ref-index.rs:51:7 + | +LL | let rs = &mut s; + | ------ mutable borrow occurs here +... +LL | f[&s] = 10; + | ^^ immutable borrow occurs here +... +LL | drop(rs); + | -- mutable borrow later used here + +error[E0594]: cannot assign to data in an index of `Bar` + --> $DIR/borrowck-overloaded-index-ref-index.rs:56:5 + | +LL | s[2] = 20; + | ^^^^^^^^^ cannot assign + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Bar` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0502, E0594. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-1.rs b/tests/ui/borrowck/borrowck-partial-reinit-1.rs new file mode 100644 index 000000000..4e6951581 --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-1.rs @@ -0,0 +1,39 @@ +struct Test; + +struct Test2 { + b: Option, +} + +struct Test3(Option); + +impl Drop for Test { + fn drop(&mut self) { + println!("dropping!"); + } +} + +impl Drop for Test2 { + fn drop(&mut self) {} +} + +impl Drop for Test3 { + fn drop(&mut self) {} +} + +fn stuff() { + let mut t = Test2 { b: None }; + let u = Test; + drop(t); + t.b = Some(u); + //~^ ERROR assign of moved value: `t` + + let mut t = Test3(None); + let u = Test; + drop(t); + t.0 = Some(u); + //~^ ERROR assign of moved value: `t` +} + +fn main() { + stuff() +} diff --git a/tests/ui/borrowck/borrowck-partial-reinit-1.stderr b/tests/ui/borrowck/borrowck-partial-reinit-1.stderr new file mode 100644 index 000000000..65f2bd6cf --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-1.stderr @@ -0,0 +1,25 @@ +error[E0382]: assign of moved value: `t` + --> $DIR/borrowck-partial-reinit-1.rs:27:5 + | +LL | let mut t = Test2 { b: None }; + | ----- move occurs because `t` has type `Test2`, which does not implement the `Copy` trait +LL | let u = Test; +LL | drop(t); + | - value moved here +LL | t.b = Some(u); + | ^^^ value assigned here after move + +error[E0382]: assign of moved value: `t` + --> $DIR/borrowck-partial-reinit-1.rs:33:5 + | +LL | let mut t = Test3(None); + | ----- move occurs because `t` has type `Test3`, which does not implement the `Copy` trait +LL | let u = Test; +LL | drop(t); + | - value moved here +LL | t.0 = Some(u); + | ^^^ value assigned here after move + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-2.rs b/tests/ui/borrowck/borrowck-partial-reinit-2.rs new file mode 100644 index 000000000..06cd322e7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-2.rs @@ -0,0 +1,23 @@ +struct Test { + a: isize, + b: Option>, +} + +impl Drop for Test { + fn drop(&mut self) { + println!("Dropping {}", self.a); + } +} + +fn stuff() { + let mut t = Test { a: 1, b: None}; + let mut u = Test { a: 2, b: Some(Box::new(t))}; + t.b = Some(Box::new(u)); + //~^ ERROR assign of moved value: `t` + println!("done"); +} + +fn main() { + stuff(); + println!("Hello, world!") +} diff --git a/tests/ui/borrowck/borrowck-partial-reinit-2.stderr b/tests/ui/borrowck/borrowck-partial-reinit-2.stderr new file mode 100644 index 000000000..36a871fbb --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-2.stderr @@ -0,0 +1,13 @@ +error[E0382]: assign of moved value: `t` + --> $DIR/borrowck-partial-reinit-2.rs:15:5 + | +LL | let mut t = Test { a: 1, b: None}; + | ----- move occurs because `t` has type `Test`, which does not implement the `Copy` trait +LL | let mut u = Test { a: 2, b: Some(Box::new(t))}; + | - value moved here +LL | t.b = Some(Box::new(u)); + | ^^^ value assigned here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-3.rs b/tests/ui/borrowck/borrowck-partial-reinit-3.rs new file mode 100644 index 000000000..ca484315b --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-3.rs @@ -0,0 +1,13 @@ +use std::mem; + +struct Test { f: usize } +impl Drop for Test { + fn drop(&mut self) {} +} + +fn main() { + let mut x = (Test { f: 2 }, Test { f: 4 }); + mem::drop(x.0); + x.0.f = 3; + //~^ ERROR assign of moved value: `x.0` +} diff --git a/tests/ui/borrowck/borrowck-partial-reinit-3.stderr b/tests/ui/borrowck/borrowck-partial-reinit-3.stderr new file mode 100644 index 000000000..05f5411ee --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-3.stderr @@ -0,0 +1,13 @@ +error[E0382]: assign of moved value: `x.0` + --> $DIR/borrowck-partial-reinit-3.rs:11:5 + | +LL | mem::drop(x.0); + | --- value moved here +LL | x.0.f = 3; + | ^^^^^^^^^ value assigned here after move + | + = note: move occurs because `x.0` has type `Test`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-partial-reinit-4.rs b/tests/ui/borrowck/borrowck-partial-reinit-4.rs new file mode 100644 index 000000000..a43a19366 --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-4.rs @@ -0,0 +1,22 @@ +struct Test; + +struct Test2(Option); + +impl Drop for Test { + fn drop(&mut self) { + println!("dropping!"); + } +} + +impl Drop for Test2 { + fn drop(&mut self) {} +} + +fn stuff() { + let mut x : (Test2, Test2); + (x.0).0 = Some(Test); //~ ERROR E0381 +} + +fn main() { + stuff() +} diff --git a/tests/ui/borrowck/borrowck-partial-reinit-4.stderr b/tests/ui/borrowck/borrowck-partial-reinit-4.stderr new file mode 100644 index 000000000..d12a482cb --- /dev/null +++ b/tests/ui/borrowck/borrowck-partial-reinit-4.stderr @@ -0,0 +1,13 @@ +error[E0381]: assigned binding `x.0` isn't fully initialized + --> $DIR/borrowck-partial-reinit-4.rs:17:5 + | +LL | let mut x : (Test2, Test2); + | ----- binding declared here but left uninitialized +LL | (x.0).0 = Some(Test); + | ^^^^^^^ `x.0` assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-pat-enum.rs b/tests/ui/borrowck/borrowck-pat-enum.rs new file mode 100644 index 000000000..7f9c5544d --- /dev/null +++ b/tests/ui/borrowck/borrowck-pat-enum.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(dead_code)] +// ignore-pretty issue #37199 + +fn match_ref(v: Option) -> isize { + match v { + Some(ref i) => { + *i + } + None => {0} + } +} + +fn match_ref_unused(v: Option) { + match v { + Some(_) => {} + None => {} + } +} + +fn impure(_i: isize) { +} + +fn match_imm_reg(v: &Option) { + match *v { + Some(ref i) => {impure(*i)} // OK because immutable + None => {} + } +} + +fn match_mut_reg(v: &mut Option) { + match *v { + Some(ref i) => {impure(*i)} // OK, frozen + None => {} + } +} + +pub fn main() { +} diff --git a/tests/ui/borrowck/borrowck-pat-reassign-binding.rs b/tests/ui/borrowck/borrowck-pat-reassign-binding.rs new file mode 100644 index 000000000..f02c46fb8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-pat-reassign-binding.rs @@ -0,0 +1,15 @@ +fn main() { + let mut x: Option = None; + match x { + None => { + // Note: on this branch, no borrow has occurred. + x = Some(0); + } + Some(ref i) => { + // But on this branch, `i` is an outstanding borrow + x = Some(*i+1); //~ ERROR cannot assign to `x` because it is borrowed + drop(i); + } + } + x.clone(); // just to prevent liveness warnings +} diff --git a/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr b/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr new file mode 100644 index 000000000..9e65ccf5a --- /dev/null +++ b/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/borrowck-pat-reassign-binding.rs:10:11 + | +LL | Some(ref i) => { + | ----- borrow of `x` occurs here +LL | // But on this branch, `i` is an outstanding borrow +LL | x = Some(*i+1); + | ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here +LL | drop(i); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-pat-reassign-no-binding.rs b/tests/ui/borrowck/borrowck-pat-reassign-no-binding.rs new file mode 100644 index 000000000..1362fd8ce --- /dev/null +++ b/tests/ui/borrowck/borrowck-pat-reassign-no-binding.rs @@ -0,0 +1,14 @@ +// run-pass + +pub fn main() { + let mut x = None; + match x { + None => { + // It is ok to reassign x here, because there is in + // fact no outstanding loan of x! + x = Some(0); + } + Some(_) => { } + } + assert_eq!(x, Some(0)); +} diff --git a/tests/ui/borrowck/borrowck-reborrow-from-mut.rs b/tests/ui/borrowck/borrowck-reborrow-from-mut.rs new file mode 100644 index 000000000..eef83c5ac --- /dev/null +++ b/tests/ui/borrowck/borrowck-reborrow-from-mut.rs @@ -0,0 +1,99 @@ +struct Foo { + bar1: Bar, + bar2: Bar +} + +struct Bar { + int1: isize, + int2: isize, +} + +fn borrow_same_field_twice_mut_mut(foo: &mut Foo) { + let _bar1 = &mut foo.bar1; + let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow + use_mut(_bar1); +} +fn borrow_same_field_twice_mut_imm(foo: &mut Foo) { + let _bar1 = &mut foo.bar1; + let _bar2 = &foo.bar1; //~ ERROR cannot borrow + use_mut(_bar1); +} +fn borrow_same_field_twice_imm_mut(foo: &mut Foo) { + let _bar1 = &foo.bar1; + let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow + use_imm(_bar1); +} +fn borrow_same_field_twice_imm_imm(foo: &mut Foo) { + let _bar1 = &foo.bar1; + let _bar2 = &foo.bar1; + use_imm(_bar1); +} +fn borrow_both_mut(foo: &mut Foo) { + let _bar1 = &mut foo.bar1; + let _bar2 = &mut foo.bar2; + use_mut(_bar1); +} +fn borrow_both_mut_pattern(foo: &mut Foo) { + match *foo { + Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => + { use_mut(_bar1); use_mut(_bar2); } + } +} +fn borrow_var_and_pattern(foo: &mut Foo) { + let _bar1 = &mut foo.bar1; + match *foo { + Foo { bar1: ref mut _bar1, bar2: _ } => {} + //~^ ERROR cannot borrow + } + use_mut(_bar1); +} +fn borrow_mut_and_base_imm(foo: &mut Foo) { + let _bar1 = &mut foo.bar1.int1; + let _foo1 = &foo.bar1; //~ ERROR cannot borrow + let _foo2 = &*foo; //~ ERROR cannot borrow + use_mut(_bar1); +} +fn borrow_mut_and_base_mut(foo: &mut Foo) { + let _bar1 = &mut foo.bar1.int1; + let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow + use_mut(_bar1); +} +fn borrow_mut_and_base_mut2(foo: &mut Foo) { + let _bar1 = &mut foo.bar1.int1; + let _foo2 = &mut *foo; //~ ERROR cannot borrow + use_mut(_bar1); +} +fn borrow_imm_and_base_mut(foo: &mut Foo) { + let _bar1 = &foo.bar1.int1; + let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow + use_imm(_bar1); +} +fn borrow_imm_and_base_mut2(foo: &mut Foo) { + let _bar1 = &foo.bar1.int1; + let _foo2 = &mut *foo; //~ ERROR cannot borrow + use_imm(_bar1); +} +fn borrow_imm_and_base_imm(foo: &mut Foo) { + let _bar1 = &foo.bar1.int1; + let _foo1 = &foo.bar1; + let _foo2 = &*foo; + use_imm(_bar1); +} +fn borrow_mut_and_imm(foo: &mut Foo) { + let _bar1 = &mut foo.bar1; + let _foo1 = &foo.bar2; + use_mut(_bar1); +} +fn borrow_mut_from_imm(foo: &Foo) { + let _bar1 = &mut foo.bar1; //~ ERROR cannot borrow +} + +fn borrow_long_path_both_mut(foo: &mut Foo) { + let _bar1 = &mut foo.bar1.int1; + let _foo1 = &mut foo.bar2.int2; + use_mut(_bar1); +} +fn main() {} + +fn use_mut(_: &mut T) { } +fn use_imm(_: &T) { } diff --git a/tests/ui/borrowck/borrowck-reborrow-from-mut.stderr b/tests/ui/borrowck/borrowck-reborrow-from-mut.stderr new file mode 100644 index 000000000..d9590e446 --- /dev/null +++ b/tests/ui/borrowck/borrowck-reborrow-from-mut.stderr @@ -0,0 +1,119 @@ +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-reborrow-from-mut.rs:13:17 + | +LL | let _bar1 = &mut foo.bar1; + | ------------- first mutable borrow occurs here +LL | let _bar2 = &mut foo.bar1; + | ^^^^^^^^^^^^^ second mutable borrow occurs here +LL | use_mut(_bar1); + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-reborrow-from-mut.rs:18:17 + | +LL | let _bar1 = &mut foo.bar1; + | ------------- mutable borrow occurs here +LL | let _bar2 = &foo.bar1; + | ^^^^^^^^^ immutable borrow occurs here +LL | use_mut(_bar1); + | ----- mutable borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-reborrow-from-mut.rs:23:17 + | +LL | let _bar1 = &foo.bar1; + | --------- immutable borrow occurs here +LL | let _bar2 = &mut foo.bar1; + | ^^^^^^^^^^^^^ mutable borrow occurs here +LL | use_imm(_bar1); + | ----- immutable borrow later used here + +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-reborrow-from-mut.rs:45:21 + | +LL | let _bar1 = &mut foo.bar1; + | ------------- first mutable borrow occurs here +LL | match *foo { +LL | Foo { bar1: ref mut _bar1, bar2: _ } => {} + | ^^^^^^^^^^^^^ second mutable borrow occurs here +... +LL | use_mut(_bar1); + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-reborrow-from-mut.rs:52:17 + | +LL | let _bar1 = &mut foo.bar1.int1; + | ------------------ mutable borrow occurs here +LL | let _foo1 = &foo.bar1; + | ^^^^^^^^^ immutable borrow occurs here +LL | let _foo2 = &*foo; +LL | use_mut(_bar1); + | ----- mutable borrow later used here + +error[E0502]: cannot borrow `*foo` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-reborrow-from-mut.rs:53:17 + | +LL | let _bar1 = &mut foo.bar1.int1; + | ------------------ mutable borrow occurs here +LL | let _foo1 = &foo.bar1; +LL | let _foo2 = &*foo; + | ^^^^^ immutable borrow occurs here +LL | use_mut(_bar1); + | ----- mutable borrow later used here + +error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time + --> $DIR/borrowck-reborrow-from-mut.rs:58:17 + | +LL | let _bar1 = &mut foo.bar1.int1; + | ------------------ first mutable borrow occurs here +LL | let _foo1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ second mutable borrow occurs here +LL | use_mut(_bar1); + | ----- first borrow later used here + +error[E0499]: cannot borrow `*foo` as mutable more than once at a time + --> $DIR/borrowck-reborrow-from-mut.rs:63:17 + | +LL | let _bar1 = &mut foo.bar1.int1; + | ------------------ first mutable borrow occurs here +LL | let _foo2 = &mut *foo; + | ^^^^^^^^^ second mutable borrow occurs here +LL | use_mut(_bar1); + | ----- first borrow later used here + +error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-reborrow-from-mut.rs:68:17 + | +LL | let _bar1 = &foo.bar1.int1; + | -------------- immutable borrow occurs here +LL | let _foo1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ mutable borrow occurs here +LL | use_imm(_bar1); + | ----- immutable borrow later used here + +error[E0502]: cannot borrow `*foo` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-reborrow-from-mut.rs:73:17 + | +LL | let _bar1 = &foo.bar1.int1; + | -------------- immutable borrow occurs here +LL | let _foo2 = &mut *foo; + | ^^^^^^^^^ mutable borrow occurs here +LL | use_imm(_bar1); + | ----- immutable borrow later used here + +error[E0596]: cannot borrow `foo.bar1` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-reborrow-from-mut.rs:88:17 + | +LL | let _bar1 = &mut foo.bar1; + | ^^^^^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrow_mut_from_imm(foo: &mut Foo) { + | ~~~~~~~~ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0499, E0502, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs b/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs new file mode 100644 index 000000000..779cb3bbe --- /dev/null +++ b/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs @@ -0,0 +1,22 @@ +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +struct S<'a> { + pointer: &'a mut isize +} + +fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> { + S { pointer: &mut *p.pointer } + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let mut x = 1; + + { + let mut y = S { pointer: &mut x }; + let z = copy_borrowed_ptr(&mut y); + *y.pointer += 1; + *z.pointer += 1; + } +} diff --git a/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr b/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr new file mode 100644 index 000000000..f28c42ce2 --- /dev/null +++ b/tests/ui/borrowck/borrowck-reborrow-from-shorter-lived-andmut.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/borrowck-reborrow-from-shorter-lived-andmut.rs:9:5 + | +LL | fn copy_borrowed_ptr<'a,'b>(p: &'a mut S<'b>) -> S<'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | S { pointer: &mut *p.pointer } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/borrowck/borrowck-ref-mut-of-imm.rs b/tests/ui/borrowck/borrowck-ref-mut-of-imm.rs new file mode 100644 index 000000000..ae5bb8591 --- /dev/null +++ b/tests/ui/borrowck/borrowck-ref-mut-of-imm.rs @@ -0,0 +1,10 @@ +fn destructure(x: Option) -> isize { + match x { + None => 0, + Some(ref mut v) => *v //~ ERROR cannot borrow + } +} + +fn main() { + assert_eq!(destructure(Some(22)), 22); +} diff --git a/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr b/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr new file mode 100644 index 000000000..5cfd81bd0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-ref-mut-of-imm.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable + --> $DIR/borrowck-ref-mut-of-imm.rs:4:12 + | +LL | Some(ref mut v) => *v + | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn destructure(mut x: Option) -> isize { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/borrowck-reinit.rs b/tests/ui/borrowck/borrowck-reinit.rs new file mode 100644 index 000000000..866b3a2a8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-reinit.rs @@ -0,0 +1,7 @@ +fn main() { + let mut x = Box::new(0); + let _u = x; // error shouldn't note this move + x = Box::new(1); + drop(x); + let _ = (1,x); //~ ERROR use of moved value: `x` +} diff --git a/tests/ui/borrowck/borrowck-reinit.stderr b/tests/ui/borrowck/borrowck-reinit.stderr new file mode 100644 index 000000000..f785900d5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-reinit.stderr @@ -0,0 +1,19 @@ +error[E0382]: use of moved value: `x` + --> $DIR/borrowck-reinit.rs:6:16 + | +LL | let mut x = Box::new(0); + | ----- move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | drop(x); + | - value moved here +LL | let _ = (1,x); + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x.clone()); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs new file mode 100644 index 000000000..6f323d912 --- /dev/null +++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] +#![allow(dead_code)] +fn main() { #![rustc_error] // rust-lang/rust#49855 + // Original borrow ends at end of function + let mut x = 1; + let y = &mut x; + //~^ mutable borrow occurs here + let z = &x; //~ ERROR cannot borrow + //~^ immutable borrow occurs here + z.use_ref(); + y.use_mut(); +} + +fn foo() { + match true { + true => { + // Original borrow ends at end of match arm + let mut x = 1; + let y = &x; + //~^ immutable borrow occurs here + let z = &mut x; //~ ERROR cannot borrow + //~^ mutable borrow occurs here + z.use_mut(); + y.use_ref(); + } + false => () + } +} + +fn bar() { + // Original borrow ends at end of closure + || { + let mut x = 1; + let y = &mut x; + //~^ first mutable borrow occurs here + let z = &mut x; //~ ERROR cannot borrow + //~^ second mutable borrow occurs here + z.use_mut(); + y.use_mut(); + }; +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr new file mode 100644 index 000000000..d05996413 --- /dev/null +++ b/tests/ui/borrowck/borrowck-report-with-custom-diagnostic.stderr @@ -0,0 +1,40 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-report-with-custom-diagnostic.rs:8:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | +LL | let z = &x; + | ^^ immutable borrow occurs here +... +LL | y.use_mut(); + | ----------- mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-report-with-custom-diagnostic.rs:21:21 + | +LL | let y = &x; + | -- immutable borrow occurs here +LL | +LL | let z = &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | y.use_ref(); + | ----------- immutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrowck-report-with-custom-diagnostic.rs:36:17 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +LL | +LL | let z = &mut x; + | ^^^^^^ second mutable borrow occurs here +... +LL | y.use_mut(); + | ----------- first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs b/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs new file mode 100644 index 000000000..75e5e7fd4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.rs @@ -0,0 +1,10 @@ +// Check that when we clone a `&T` pointer we properly relate the +// lifetime of the pointer which results to the pointer being cloned. +// Bugs in method resolution have sometimes broken this connection. +// Issue #19261. + +fn leak<'a, T>(x: T) -> &'a T { + (&x).clone() //~ ERROR cannot return value referencing function parameter `x` +} + +fn main() { } diff --git a/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr b/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr new file mode 100644 index 000000000..d54449ac4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-return-variable-on-stack-via-clone.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing function parameter `x` + --> $DIR/borrowck-return-variable-on-stack-via-clone.rs:7:5 + | +LL | (&x).clone() + | ----^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `x` is borrowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-return.rs b/tests/ui/borrowck/borrowck-return.rs new file mode 100644 index 000000000..a63ffcff7 --- /dev/null +++ b/tests/ui/borrowck/borrowck-return.rs @@ -0,0 +1,6 @@ +fn f() -> isize { + let x: isize; + return x; //~ ERROR E0381 +} + +fn main() { f(); } diff --git a/tests/ui/borrowck/borrowck-return.stderr b/tests/ui/borrowck/borrowck-return.stderr new file mode 100644 index 000000000..9799357c9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-return.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-return.rs:3:12 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | return x; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-rvalues-mutable.rs b/tests/ui/borrowck/borrowck-rvalues-mutable.rs new file mode 100644 index 000000000..c4695c942 --- /dev/null +++ b/tests/ui/borrowck/borrowck-rvalues-mutable.rs @@ -0,0 +1,34 @@ +// run-pass + +struct Counter { + value: usize +} + +impl Counter { + fn new(v: usize) -> Counter { + Counter {value: v} + } + + fn inc<'a>(&'a mut self) -> &'a mut Counter { + self.value += 1; + self + } + + fn get(&self) -> usize { + self.value + } + + fn get_and_inc(&mut self) -> usize { + let v = self.value; + self.value += 1; + v + } +} + +pub fn main() { + let v = Counter::new(22).get_and_inc(); + assert_eq!(v, 22); + + let v = Counter::new(22).inc().inc().get(); + assert_eq!(v, 24); +} diff --git a/tests/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs b/tests/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs new file mode 100644 index 000000000..e89332ae3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-scope-of-deref-issue-4666.rs @@ -0,0 +1,42 @@ +// run-pass +// Tests that the scope of the pointer returned from `get()` is +// limited to the deref operation itself, and does not infect the +// block as a whole. + + +struct Box { + x: usize +} + +impl Box { + fn get(&self) -> &usize { + &self.x + } + fn set(&mut self, x: usize) { + self.x = x; + } +} + +fn fun1() { + // in the past, borrow checker behaved differently when + // init and decl of `v` were distinct + let v; + let mut a_box = Box {x: 0}; + a_box.set(22); + v = *a_box.get(); + a_box.set(v+1); + assert_eq!(23, *a_box.get()); +} + +fn fun2() { + let mut a_box = Box {x: 0}; + a_box.set(22); + let v = *a_box.get(); + a_box.set(v+1); + assert_eq!(23, *a_box.get()); +} + +pub fn main() { + fun1(); + fun2(); +} diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs new file mode 100644 index 000000000..a8e56f648 --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs @@ -0,0 +1,64 @@ +// check-pass + +fn nop(_s: &[& i32]) {} +fn nop_subslice(_s: &[i32]) {} + +fn const_index_ok(s: &mut [i32; 4]) { + let [ref first, ref second, _, ref fourth, ..] = *s; + let [_, _, ref mut third, ..] = *s; + nop(&[first, second, third, fourth]); +} + +fn const_index_from_end_ok(s: &mut [i32; 4]) { + let [.., ref fourth, ref third, _, ref first] = *s; + let [.., ref mut second, _] = *s; + nop(&[first, second, third, fourth]); +} + +fn const_index_mixed(s: &mut [i32; 6]) { + let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s; + + let [ref mut from_begin0, ..] = *s; + nop(&[from_begin0, from_end1, from_end3, from_end4]); + let [_, ref mut from_begin1, ..] = *s; + nop(&[from_begin1, from_end1, from_end3, from_end4]); + + let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s; + + let [.., ref mut from_end1] = *s; + nop(&[from_begin0, from_begin1, from_begin3, from_end1]); + let [.., ref mut from_end2, _] = *s; + nop(&[from_begin0, from_begin1, from_begin3, from_end2]); + let [.., ref mut from_end4, _, _, _] = *s; + nop(&[from_begin0, from_begin1, from_begin3, from_end4]); +} + +fn const_index_and_subslice_ok(s: &mut [i32; 4]) { + let [ref first, ref second, ..] = *s; + let [_, _, ref mut tail @ ..] = *s; + nop(&[first, second]); + nop_subslice(tail); +} + +fn const_index_and_subslice_from_end_ok(s: &mut [i32; 4]) { + let [.., ref second, ref first] = *s; + let [ref mut tail @ .., _, _] = *s; + nop(&[first, second]); + nop_subslice(tail); +} + +fn subslices(s: &mut [i32; 4]) { + let [_, _, ref s1 @ ..] = *s; + let [ref mut s2 @ .., _, _] = *s; + nop_subslice(s1); + nop_subslice(s2); +} + +fn main() { + let mut v = [1,2,3,4]; + const_index_ok(&mut v); + const_index_from_end_ok(&mut v); + const_index_and_subslice_ok(&mut v); + const_index_and_subslice_from_end_ok(&mut v); + subslices(&mut v); +} diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs new file mode 100644 index 000000000..6b210d732 --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs @@ -0,0 +1,58 @@ +fn nop(_s: &[& i32]) {} +fn nop_subslice(_s: &[i32]) {} + +fn const_index_err(s: &mut [i32; 4]) { + let [ref first, ref second, ..] = *s; + let [_, ref mut second2, ref mut third, ..] = *s; //~ERROR + nop(&[first, second, second2, third]); +} + +fn const_index_from_end_err(s: &mut [i32; 4]) { + let [.., ref fourth, ref third, _, ref first] = *s; + let [.., ref mut third2, _, _] = *s; //~ERROR + nop(&[first, third, third2, fourth]); +} + +fn const_index_mixed(s: &mut [i32; 6]) { + let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s; + + let [_, _, ref mut from_begin2, ..] = *s; //~ERROR + nop(&[from_begin2, from_end1, from_end3, from_end4]); + let [_, _, _, ref mut from_begin3, ..] = *s; //~ERROR + nop(&[from_begin3, from_end1, from_end3, from_end4]); + + let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s; + + let [.., ref mut from_end3, _, _] = *s; //~ERROR + nop(&[from_begin0, from_begin1, from_begin3, from_end3]); +} + +fn const_index_and_subslice_err(s: &mut [i32; 4]) { + let [ref first, ref second, ..] = *s; + let [_, ref mut tail @ ..] = *s; //~ERROR + nop(&[first, second]); + nop_subslice(tail); +} + +fn const_index_and_subslice_from_end_err(s: &mut [i32; 4]) { + let [.., ref second, ref first] = *s; + let [ref mut tail @ .., _] = *s; //~ERROR + nop(&[first, second]); + nop_subslice(tail); +} + +fn subslices_overlap(s: &mut [i32; 4]) { + let [_, ref s1 @ ..] = *s; + let [ref mut s2 @ .., _, _] = *s; //~ERROR + nop_subslice(s1); + nop_subslice(s2); +} + +fn main() { + let mut v = [1,2,3,4]; + const_index_err(&mut v); + const_index_from_end_err(&mut v); + const_index_and_subslice_err(&mut v); + const_index_and_subslice_from_end_err(&mut v); + subslices_overlap(&mut v); +} diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr new file mode 100644 index 000000000..f4324110c --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr @@ -0,0 +1,86 @@ +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:6:13 + | +LL | let [ref first, ref second, ..] = *s; + | ---------- immutable borrow occurs here +LL | let [_, ref mut second2, ref mut third, ..] = *s; + | ^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, second, second2, third]); + | ------ immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:12:14 + | +LL | let [.., ref fourth, ref third, _, ref first] = *s; + | --------- immutable borrow occurs here +LL | let [.., ref mut third2, _, _] = *s; + | ^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, third, third2, fourth]); + | ----- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:19:16 + | +LL | let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s; + | ------------- immutable borrow occurs here +LL | +LL | let [_, _, ref mut from_begin2, ..] = *s; + | ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin2, from_end1, from_end3, from_end4]); + | --------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:19 + | +LL | let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s; + | ------------- immutable borrow occurs here +... +LL | let [_, _, _, ref mut from_begin3, ..] = *s; + | ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin3, from_end1, from_end3, from_end4]); + | --------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:26:14 + | +LL | let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s; + | --------------- immutable borrow occurs here +LL | +LL | let [.., ref mut from_end3, _, _] = *s; + | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin0, from_begin1, from_begin3, from_end3]); + | ----------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:32:13 + | +LL | let [ref first, ref second, ..] = *s; + | ---------- immutable borrow occurs here +LL | let [_, ref mut tail @ ..] = *s; + | ^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, second]); + | ------ immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:39:10 + | +LL | let [.., ref second, ref first] = *s; + | ---------- immutable borrow occurs here +LL | let [ref mut tail @ .., _] = *s; + | ^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, second]); + | ------ immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:46:10 + | +LL | let [_, ref s1 @ ..] = *s; + | ------ immutable borrow occurs here +LL | let [ref mut s2 @ .., _, _] = *s; + | ^^^^^^^^^^ mutable borrow occurs here +LL | nop_subslice(s1); + | -- immutable borrow later used here + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs new file mode 100644 index 000000000..4367596c6 --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs @@ -0,0 +1,21 @@ +// run-pass + +fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> { + match *v { + [ref mut head, ref mut tail @ ..] => { + Some((head, tail)) + } + [] => None + } +} + +fn main() { + let mut v = [1,2,3,4]; + match mut_head_tail(&mut v) { + None => {}, + Some((h,t)) => { + *h = 1000; + t.reverse(); + } + } +} diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs new file mode 100644 index 000000000..6390dc3a9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs @@ -0,0 +1,59 @@ +// check-pass + +fn nop(_s: &[& i32]) {} +fn nop_subslice(_s: &[i32]) {} + +fn const_index_ok(s: &mut [i32]) { + if let [ref first, ref second, _, ref fourth, ..] = *s { + if let [_, _, ref mut third, ..] = *s { + nop(&[first, second, third, fourth]); + } + } +} + +fn const_index_from_end_ok(s: &mut [i32]) { + if let [.., ref fourth, ref third, _, ref first] = *s { + if let [.., ref mut second, _] = *s { + nop(&[first, second, third, fourth]); + } + } +} + +fn const_index_mixed(s: &mut [i32]) { + if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { + if let [ref mut from_begin0, ..] = *s { + nop(&[from_begin0, from_end1, from_end3, from_end4]); + } + } + if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { + if let [.., ref mut from_end1] = *s { + nop(&[from_begin0, from_begin1, from_begin3, from_end1]); + } + } +} + +fn const_index_and_subslice_ok(s: &mut [i32]) { + if let [ref first, ref second, ..] = *s { + if let [_, _, ref mut tail @ ..] = *s { + nop(&[first, second]); + nop_subslice(tail); + } + } +} + +fn const_index_and_subslice_from_end_ok(s: &mut [i32]) { + if let [.., ref second, ref first] = *s { + if let [ref mut tail @ .., _, _] = *s { + nop(&[first, second]); + nop_subslice(tail); + } + } +} + +fn main() { + let mut v = [1,2,3,4]; + const_index_ok(&mut v); + const_index_from_end_ok(&mut v); + const_index_and_subslice_ok(&mut v); + const_index_and_subslice_from_end_ok(&mut v); +} diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs new file mode 100644 index 000000000..0e1c90a1c --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs @@ -0,0 +1,79 @@ +fn nop(_s: &[& i32]) {} +fn nop_subslice(_s: &[i32]) {} + +fn const_index_err(s: &mut [i32]) { + if let [ref first, ref second, ..] = *s { + if let [_, ref mut second2, ref mut third, ..] = *s { //~ERROR + nop(&[first, second, second2, third]); + } + } +} + +fn const_index_from_end_err(s: &mut [i32]) { + if let [.., ref fourth, ref third, _, ref first] = *s { + if let [.., ref mut third2, _, _] = *s { //~ERROR + nop(&[first, third, third2, fourth]); + } + } +} + +fn const_index_mixed(s: &mut [i32]) { + if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { + if let [_, ref mut from_begin1, ..] = *s { //~ERROR + nop(&[from_begin1, from_end1, from_end3, from_end4]); + } + if let [_, _, ref mut from_begin2, ..] = *s { //~ERROR + nop(&[from_begin2, from_end1, from_end3, from_end4]); + } + if let [_, _, _, ref mut from_begin3, ..] = *s { //~ERROR + nop(&[from_begin3, from_end1, from_end3, from_end4]); + } + } + if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { + if let [.., ref mut from_end2, _] = *s { //~ERROR + nop(&[from_begin0, from_begin1, from_begin3, from_end2]); + } + if let [.., ref mut from_end3, _, _] = *s { //~ERROR + nop(&[from_begin0, from_begin1, from_begin3, from_end3]); + } + if let [.., ref mut from_end4, _, _, _] = *s { //~ERROR + nop(&[from_begin0, from_begin1, from_begin3, from_end4]); + } + } +} + +fn const_index_and_subslice_err(s: &mut [i32]) { + if let [ref first, ref second, ..] = *s { + if let [_, ref mut tail @ ..] = *s { //~ERROR + nop(&[first, second]); + nop_subslice(tail); + } + } +} + +fn const_index_and_subslice_from_end_err(s: &mut [i32]) { + if let [.., ref second, ref first] = *s { + if let [ref mut tail @ .., _] = *s { //~ERROR + nop(&[first, second]); + nop_subslice(tail); + } + } +} + +fn subslices(s: &mut [i32]) { + if let [_, _, _, ref s1 @ ..] = *s { + if let [ref mut s2 @ .., _, _, _] = *s { //~ERROR + nop_subslice(s1); + nop_subslice(s2); + } + } +} + +fn main() { + let mut v = [1,2,3,4]; + const_index_err(&mut v); + const_index_from_end_err(&mut v); + const_index_and_subslice_err(&mut v); + const_index_and_subslice_from_end_err(&mut v); + subslices(&mut v); +} diff --git a/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr new file mode 100644 index 000000000..f9a63bd49 --- /dev/null +++ b/tests/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr @@ -0,0 +1,117 @@ +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:6:20 + | +LL | if let [ref first, ref second, ..] = *s { + | ---------- immutable borrow occurs here +LL | if let [_, ref mut second2, ref mut third, ..] = *s { + | ^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, second, second2, third]); + | ------ immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:14:21 + | +LL | if let [.., ref fourth, ref third, _, ref first] = *s { + | --------- immutable borrow occurs here +LL | if let [.., ref mut third2, _, _] = *s { + | ^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, third, third2, fourth]); + | ----- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:22:20 + | +LL | if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { + | ------------- immutable borrow occurs here +LL | if let [_, ref mut from_begin1, ..] = *s { + | ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin1, from_end1, from_end3, from_end4]); + | --------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:25:23 + | +LL | if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { + | ------------- immutable borrow occurs here +... +LL | if let [_, _, ref mut from_begin2, ..] = *s { + | ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin2, from_end1, from_end3, from_end4]); + | --------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:28:26 + | +LL | if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { + | ------------- immutable borrow occurs here +... +LL | if let [_, _, _, ref mut from_begin3, ..] = *s { + | ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin3, from_end1, from_end3, from_end4]); + | --------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:33:21 + | +LL | if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { + | --------------- immutable borrow occurs here +LL | if let [.., ref mut from_end2, _] = *s { + | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin0, from_begin1, from_begin3, from_end2]); + | ----------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:36:21 + | +LL | if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { + | --------------- immutable borrow occurs here +... +LL | if let [.., ref mut from_end3, _, _] = *s { + | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin0, from_begin1, from_begin3, from_end3]); + | ----------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:39:21 + | +LL | if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { + | --------------- immutable borrow occurs here +... +LL | if let [.., ref mut from_end4, _, _, _] = *s { + | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[from_begin0, from_begin1, from_begin3, from_end4]); + | ----------- immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:47:20 + | +LL | if let [ref first, ref second, ..] = *s { + | ---------- immutable borrow occurs here +LL | if let [_, ref mut tail @ ..] = *s { + | ^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, second]); + | ------ immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:56:17 + | +LL | if let [.., ref second, ref first] = *s { + | ---------- immutable borrow occurs here +LL | if let [ref mut tail @ .., _] = *s { + | ^^^^^^^^^^^^ mutable borrow occurs here +LL | nop(&[first, second]); + | ------ immutable borrow later used here + +error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:65:17 + | +LL | if let [_, _, _, ref s1 @ ..] = *s { + | ------ immutable borrow occurs here +LL | if let [ref mut s2 @ .., _, _, _] = *s { + | ^^^^^^^^^^ mutable borrow occurs here +LL | nop_subslice(s1); + | -- immutable borrow later used here + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-static-item-in-fn.rs b/tests/ui/borrowck/borrowck-static-item-in-fn.rs new file mode 100644 index 000000000..5f4379325 --- /dev/null +++ b/tests/ui/borrowck/borrowck-static-item-in-fn.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(dead_code)] +// Regression test for issue #7740 + +// pretty-expanded FIXME #23616 + +pub fn main() { + static A: &'static char = &'A'; +} diff --git a/tests/ui/borrowck/borrowck-storage-dead.rs b/tests/ui/borrowck/borrowck-storage-dead.rs new file mode 100644 index 000000000..fe9844610 --- /dev/null +++ b/tests/ui/borrowck/borrowck-storage-dead.rs @@ -0,0 +1,24 @@ +fn ok() { + loop { + let _x = 1; + } +} + +fn also_ok() { + loop { + let _x = String::new(); + } +} + +fn fail() { + loop { + let x: i32; + let _ = x + 1; //~ERROR [E0381] + } +} + +fn main() { + ok(); + also_ok(); + fail(); +} diff --git a/tests/ui/borrowck/borrowck-storage-dead.stderr b/tests/ui/borrowck/borrowck-storage-dead.stderr new file mode 100644 index 000000000..3a413153a --- /dev/null +++ b/tests/ui/borrowck/borrowck-storage-dead.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-storage-dead.rs:16:17 + | +LL | let x: i32; + | - binding declared here but left uninitialized +LL | let _ = x + 1; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-struct-update-with-dtor.rs b/tests/ui/borrowck/borrowck-struct-update-with-dtor.rs new file mode 100644 index 000000000..1f6ed6d46 --- /dev/null +++ b/tests/ui/borrowck/borrowck-struct-update-with-dtor.rs @@ -0,0 +1,21 @@ +// Issue 4691: Ensure that functional-struct-update can only copy, not +// move, when the struct implements Drop. + +struct B; +struct S { a: isize, b: B } +impl Drop for S { fn drop(&mut self) { } } + +struct T { a: isize, mv: Box } +impl Drop for T { fn drop(&mut self) { } } + +fn f(s0:S) { + let _s2 = S{a: 2, ..s0}; + //~^ ERROR [E0509] +} + +fn g(s0:T) { + let _s2 = T{a: 2, ..s0}; + //~^ ERROR [E0509] +} + +fn main() { } diff --git a/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr b/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr new file mode 100644 index 000000000..af32f2791 --- /dev/null +++ b/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr @@ -0,0 +1,21 @@ +error[E0509]: cannot move out of type `S`, which implements the `Drop` trait + --> $DIR/borrowck-struct-update-with-dtor.rs:12:15 + | +LL | let _s2 = S{a: 2, ..s0}; + | ^^^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `s0.b` has type `B`, which does not implement the `Copy` trait + +error[E0509]: cannot move out of type `T`, which implements the `Drop` trait + --> $DIR/borrowck-struct-update-with-dtor.rs:17:15 + | +LL | let _s2 = T{a: 2, ..s0}; + | ^^^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `s0.mv` has type `Box`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/borrowck/borrowck-swap-mut-base-ptr.rs b/tests/ui/borrowck/borrowck-swap-mut-base-ptr.rs new file mode 100644 index 000000000..8170323ef --- /dev/null +++ b/tests/ui/borrowck/borrowck-swap-mut-base-ptr.rs @@ -0,0 +1,22 @@ +// Test that attempt to swap `&mut` pointer while pointee is borrowed +// yields an error. +// +// Example from compiler/rustc_borrowck/borrowck/README.md + +use std::mem::swap; + + + +fn foo<'a>(mut t0: &'a mut isize, + mut t1: &'a mut isize) { + let p: &isize = &*t0; // Freezes `*t0` + swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` + *t1 = 22; + p.use_ref(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr new file mode 100644 index 000000000..b39215b9a --- /dev/null +++ b/tests/ui/borrowck/borrowck-swap-mut-base-ptr.stderr @@ -0,0 +1,14 @@ +error[E0502]: cannot borrow `t0` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-swap-mut-base-ptr.rs:13:10 + | +LL | let p: &isize = &*t0; // Freezes `*t0` + | ---- immutable borrow occurs here +LL | swap(&mut t0, &mut t1); + | ^^^^^^^ mutable borrow occurs here +LL | *t1 = 22; +LL | p.use_ref(); + | ----------- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs new file mode 100644 index 000000000..1cf8d187c --- /dev/null +++ b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs @@ -0,0 +1,9 @@ +#![feature(thread_local)] + +#[thread_local] +static FOO: u8 = 3; + +fn assert_static(_t: &'static u8) {} +fn main() { + assert_static(&FOO); //~ ERROR [E0712] +} diff --git a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr new file mode 100644 index 000000000..26453b42f --- /dev/null +++ b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr @@ -0,0 +1,11 @@ +error[E0712]: thread-local variable borrowed past end of function + --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:8:20 + | +LL | assert_static(&FOO); + | ^^^^ thread-local variables cannot be borrowed beyond the end of the function +LL | } + | - end of enclosing function is here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0712`. diff --git a/tests/ui/borrowck/borrowck-trait-lifetime.rs b/tests/ui/borrowck/borrowck-trait-lifetime.rs new file mode 100644 index 000000000..8a6dfe76d --- /dev/null +++ b/tests/ui/borrowck/borrowck-trait-lifetime.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_imports)] +// This test verifies that casting from the same lifetime on a value +// to the same lifetime on a trait succeeds. See issue #10766. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::marker; + +fn main() { + trait T { fn foo(&self) {} } + + fn f<'a, V: T>(v: &'a V) -> &'a dyn T { + v as &'a dyn T + } +} diff --git a/tests/ui/borrowck/borrowck-unary-move.rs b/tests/ui/borrowck/borrowck-unary-move.rs new file mode 100644 index 000000000..3b4c0731f --- /dev/null +++ b/tests/ui/borrowck/borrowck-unary-move.rs @@ -0,0 +1,11 @@ +fn foo(x: Box) -> isize { + let y = &*x; + free(x); //~ ERROR cannot move out of `x` because it is borrowed + *y +} + +fn free(_x: Box) { +} + +fn main() { +} diff --git a/tests/ui/borrowck/borrowck-unary-move.stderr b/tests/ui/borrowck/borrowck-unary-move.stderr new file mode 100644 index 000000000..aab225ed4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-unary-move.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/borrowck-unary-move.rs:3:10 + | +LL | let y = &*x; + | --- borrow of `*x` occurs here +LL | free(x); + | ^ move out of `x` occurs here +LL | *y + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/borrowck-unboxed-closures.rs b/tests/ui/borrowck/borrowck-unboxed-closures.rs new file mode 100644 index 000000000..f0048dd7d --- /dev/null +++ b/tests/ui/borrowck/borrowck-unboxed-closures.rs @@ -0,0 +1,17 @@ +fn a isize>(mut f: F) { + let g = &mut f; + f(1, 2); //~ ERROR cannot borrow `f` as immutable + use_mut(g); +} +fn b isize>(f: F) { + f(1, 2); //~ ERROR cannot borrow `f` as mutable, as it is not declared as mutable +} + +fn c isize>(f: F) { + f(1, 2); + f(1, 2); //~ ERROR use of moved value +} + +fn main() {} + +fn use_mut(_: &mut T) { } diff --git a/tests/ui/borrowck/borrowck-unboxed-closures.stderr b/tests/ui/borrowck/borrowck-unboxed-closures.stderr new file mode 100644 index 000000000..363467646 --- /dev/null +++ b/tests/ui/borrowck/borrowck-unboxed-closures.stderr @@ -0,0 +1,45 @@ +error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-unboxed-closures.rs:3:5 + | +LL | let g = &mut f; + | ------ mutable borrow occurs here +LL | f(1, 2); + | ^ immutable borrow occurs here +LL | use_mut(g); + | - mutable borrow later used here + +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/borrowck-unboxed-closures.rs:7:5 + | +LL | f(1, 2); + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn b isize>(mut f: F) { + | +++ + +error[E0382]: use of moved value: `f` + --> $DIR/borrowck-unboxed-closures.rs:12:5 + | +LL | fn c isize>(f: F) { + | - move occurs because `f` has type `F`, which does not implement the `Copy` trait +LL | f(1, 2); + | ------- `f` moved due to this call +LL | f(1, 2); + | ^ value used here after move + | +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/borrowck-unboxed-closures.rs:11:5 + | +LL | f(1, 2); + | ^ +help: consider further restricting this bound + | +LL | fn c isize + Copy>(f: F) { + | ++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0502, E0596. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-uninit-after-item.rs b/tests/ui/borrowck/borrowck-uninit-after-item.rs new file mode 100644 index 000000000..e97ce6aa4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-after-item.rs @@ -0,0 +1,5 @@ +fn main() { + let bar; + fn baz(_x: isize) { } + baz(bar); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-uninit-after-item.stderr b/tests/ui/borrowck/borrowck-uninit-after-item.stderr new file mode 100644 index 000000000..071598b42 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-after-item.stderr @@ -0,0 +1,17 @@ +error[E0381]: used binding `bar` isn't initialized + --> $DIR/borrowck-uninit-after-item.rs:4:9 + | +LL | let bar; + | --- binding declared here but left uninitialized +LL | fn baz(_x: isize) { } +LL | baz(bar); + | ^^^ `bar` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let bar = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-uninit-field-access.rs b/tests/ui/borrowck/borrowck-uninit-field-access.rs new file mode 100644 index 000000000..bc931eef9 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-field-access.rs @@ -0,0 +1,30 @@ +// Check that do not allow access to fields of uninitialized or moved +// structs. + +#[derive(Default)] +struct Point { + x: isize, + y: isize, +} + +#[derive(Default)] +struct Line { + origin: Point, + middle: Point, + target: Point, +} + +impl Line { fn consume(self) { } } + +fn main() { + let mut a: Point; + let _ = a.x + 1; //~ ERROR [E0381] + + let mut line1 = Line::default(); + let _moved = line1.origin; + let _ = line1.origin.x + 1; //~ ERROR [E0382] + + let mut line2 = Line::default(); + let _moved = (line2.origin, line2.middle); + line2.consume(); //~ ERROR [E0382] +} diff --git a/tests/ui/borrowck/borrowck-uninit-field-access.stderr b/tests/ui/borrowck/borrowck-uninit-field-access.stderr new file mode 100644 index 000000000..f0f4ad704 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-field-access.stderr @@ -0,0 +1,37 @@ +error[E0381]: used binding `a` isn't initialized + --> $DIR/borrowck-uninit-field-access.rs:21:13 + | +LL | let mut a: Point; + | ----- binding declared here but left uninitialized +LL | let _ = a.x + 1; + | ^^^ `a.x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut a: Point = Default::default(); + | ++++++++++++++++++++ + +error[E0382]: use of moved value: `line1.origin` + --> $DIR/borrowck-uninit-field-access.rs:25:13 + | +LL | let _moved = line1.origin; + | ------------ value moved here +LL | let _ = line1.origin.x + 1; + | ^^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `line1.origin` has type `Point`, which does not implement the `Copy` trait + +error[E0382]: use of partially moved value: `line2` + --> $DIR/borrowck-uninit-field-access.rs:29:5 + | +LL | let _moved = (line2.origin, line2.middle); + | ------------ value partially moved here +LL | line2.consume(); + | ^^^^^ value used here after partial move + | + = note: partial move occurs because `line2.middle` has type `Point`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-uninit-in-assignop.rs b/tests/ui/borrowck/borrowck-uninit-in-assignop.rs new file mode 100644 index 000000000..92c3692bd --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-in-assignop.rs @@ -0,0 +1,34 @@ +// Tests that the use of uninitialized variable in assignment operator +// expression is detected. + +pub fn main() { + let x: isize; + x += 1; //~ ERROR E0381 + + let x: isize; + x -= 1; //~ ERROR E0381 + + let x: isize; + x *= 1; //~ ERROR E0381 + + let x: isize; + x /= 1; //~ ERROR E0381 + + let x: isize; + x %= 1; //~ ERROR E0381 + + let x: isize; + x ^= 1; //~ ERROR E0381 + + let x: isize; + x &= 1; //~ ERROR E0381 + + let x: isize; + x |= 1; //~ ERROR E0381 + + let x: isize; + x <<= 1; //~ ERROR E0381 + + let x: isize; + x >>= 1; //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr b/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr new file mode 100644 index 000000000..fdbb451bd --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr @@ -0,0 +1,133 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:6:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x += 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:9:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x -= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:12:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x *= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:15:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x /= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:18:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x %= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:21:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x ^= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:24:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x &= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:27:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x |= 1; + | ^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:30:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x <<= 1; + | ^^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-in-assignop.rs:33:5 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | x >>= 1; + | ^^^^^^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-uninit-ref-chain.rs b/tests/ui/borrowck/borrowck-uninit-ref-chain.rs new file mode 100644 index 000000000..c36b9707d --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-ref-chain.rs @@ -0,0 +1,33 @@ +struct S { + x: X, + y: Y, +} + +fn main() { + let x: &&Box; + let _y = &**x; //~ ERROR [E0381] + + let x: &&S; + let _y = &**x; //~ ERROR [E0381] + + let x: &&i32; + let _y = &**x; //~ ERROR [E0381] + + + let mut a: S; + a.x = 0; //~ ERROR [E0381] + let _b = &a.x; + + let mut a: S<&&i32, &&i32>; + a.x = &&0; //~ ERROR [E0381] + let _b = &**a.x; + + + let mut a: S; + a.x = 0; //~ ERROR [E0381] + let _b = &a.y; + + let mut a: S<&&i32, &&i32>; + a.x = &&0; //~ ERROR [E0381] + let _b = &**a.y; +} diff --git a/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr b/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr new file mode 100644 index 000000000..73fded754 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr @@ -0,0 +1,82 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-ref-chain.rs:8:14 + | +LL | let x: &&Box; + | - binding declared here but left uninitialized +LL | let _y = &**x; + | ^^^^ `**x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &&Box = todo!(); + | +++++++++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-ref-chain.rs:11:14 + | +LL | let x: &&S; + | - binding declared here but left uninitialized +LL | let _y = &**x; + | ^^^^ `**x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &&S = todo!(); + | +++++++++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit-ref-chain.rs:14:14 + | +LL | let x: &&i32; + | - binding declared here but left uninitialized +LL | let _y = &**x; + | ^^^^ `**x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &&i32 = todo!(); + | +++++++++ + +error[E0381]: partially assigned binding `a` isn't fully initialized + --> $DIR/borrowck-uninit-ref-chain.rs:18:5 + | +LL | let mut a: S; + | ----- binding declared here but left uninitialized +LL | a.x = 0; + | ^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `a` isn't fully initialized + --> $DIR/borrowck-uninit-ref-chain.rs:22:5 + | +LL | let mut a: S<&&i32, &&i32>; + | ----- binding declared here but left uninitialized +LL | a.x = &&0; + | ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `a` isn't fully initialized + --> $DIR/borrowck-uninit-ref-chain.rs:27:5 + | +LL | let mut a: S; + | ----- binding declared here but left uninitialized +LL | a.x = 0; + | ^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `a` isn't fully initialized + --> $DIR/borrowck-uninit-ref-chain.rs:31:5 + | +LL | let mut a: S<&&i32, &&i32>; + | ----- binding declared here but left uninitialized +LL | a.x = &&0; + | ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-uninit.rs b/tests/ui/borrowck/borrowck-uninit.rs new file mode 100644 index 000000000..5d0ebabb0 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit.rs @@ -0,0 +1,6 @@ +fn foo(x: isize) { println!("{}", x); } + +fn main() { + let x: isize; + foo(x); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-uninit.stderr b/tests/ui/borrowck/borrowck-uninit.stderr new file mode 100644 index 000000000..eeafc4ce1 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uninit.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-uninit.rs:5:9 + | +LL | let x: isize; + | - binding declared here but left uninitialized +LL | foo(x); + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: isize = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-union-borrow-nested.rs b/tests/ui/borrowck/borrowck-union-borrow-nested.rs new file mode 100644 index 000000000..b3a6670fa --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-borrow-nested.rs @@ -0,0 +1,31 @@ +#[derive(Clone, Copy)] +struct S { + a: u8, + b: u16, +} + +#[derive(Clone, Copy)] +union U { + s: S, + c: u32, +} + +fn main() { + unsafe { + { + let mut u = U { s: S { a: 0, b: 1 } }; + let ra = &mut u.s.a; + let b = u.s.b; // OK + ra.use_mut(); + } + { + let mut u = U { s: S { a: 0, b: 1 } }; + let ra = &mut u.s.a; + let b = u.c; //~ ERROR cannot use `u.c` because it was mutably borrowed + ra.use_mut(); + } + } +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-union-borrow-nested.stderr b/tests/ui/borrowck/borrowck-union-borrow-nested.stderr new file mode 100644 index 000000000..4bd7d54cf --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-borrow-nested.stderr @@ -0,0 +1,13 @@ +error[E0503]: cannot use `u.c` because it was mutably borrowed + --> $DIR/borrowck-union-borrow-nested.rs:24:21 + | +LL | let ra = &mut u.s.a; + | ---------- borrow of `u.s.a` occurs here +LL | let b = u.c; + | ^^^ use of borrowed `u.s.a` +LL | ra.use_mut(); + | ------------ borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/borrowck-union-borrow.rs b/tests/ui/borrowck/borrowck-union-borrow.rs new file mode 100644 index 000000000..f01915398 --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-borrow.rs @@ -0,0 +1,96 @@ +#[derive(Clone, Copy)] +union U { + a: u8, + b: u64, +} + +fn main() { + unsafe { + let mut u = U { b: 0 }; + // Imm borrow, same field + { + let ra = &u.a; + let ra2 = &u.a; // OK + drop(ra); + } + { + let ra = &u.a; + let a = u.a; // OK + drop(ra); + } + { + let ra = &u.a; + let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable + drop(ra); + } + { + let ra = &u.a; + u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed + drop(ra); + } + // Imm borrow, other field + { + let ra = &u.a; + let rb = &u.b; // OK + drop(ra); + } + { + let ra = &u.a; + let b = u.b; // OK + drop(ra); + } + { + let ra = &u.a; + let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`) + drop(ra); + } + { + let ra = &u.a; + u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed + drop(ra); + } + // Mut borrow, same field + { + let rma = &mut u.a; + let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable + drop(rma); + } + { + let ra = &mut u.a; + let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed + drop(ra); + } + { + let rma = &mut u.a; + let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time + drop(rma); + } + { + let rma = &mut u.a; + u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed + drop(rma); + } + // Mut borrow, other field + { + let rma = &mut u.a; + let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`) + drop(rma); + } + { + let ra = &mut u.a; + let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed + + drop(ra); + } + { + let rma = &mut u.a; + let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time + drop(rma); + } + { + let rma = &mut u.a; + u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed + drop(rma); + } + } +} diff --git a/tests/ui/borrowck/borrowck-union-borrow.stderr b/tests/ui/borrowck/borrowck-union-borrow.stderr new file mode 100644 index 000000000..090c7b6b5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-borrow.stderr @@ -0,0 +1,131 @@ +error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-union-borrow.rs:23:23 + | +LL | let ra = &u.a; + | ---- immutable borrow occurs here +LL | let rma = &mut u.a; + | ^^^^^^^^ mutable borrow occurs here +LL | drop(ra); + | -- immutable borrow later used here + +error[E0506]: cannot assign to `u.a` because it is borrowed + --> $DIR/borrowck-union-borrow.rs:28:13 + | +LL | let ra = &u.a; + | ---- borrow of `u.a` occurs here +LL | u.a = 1; + | ^^^^^^^ assignment to borrowed `u.a` occurs here +LL | drop(ra); + | -- borrow later used here + +error[E0502]: cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`) + --> $DIR/borrowck-union-borrow.rs:44:23 + | +LL | let ra = &u.a; + | ---- immutable borrow occurs here (via `u.a`) +LL | let rmb = &mut u.b; + | ^^^^^^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here +LL | drop(ra); + | -- immutable borrow later used here + | + = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a` + +error[E0506]: cannot assign to `u.b` because it is borrowed + --> $DIR/borrowck-union-borrow.rs:49:13 + | +LL | let ra = &u.a; + | ---- borrow of `u.b` occurs here +LL | u.b = 1; + | ^^^^^^^ assignment to borrowed `u.b` occurs here +LL | drop(ra); + | -- borrow later used here + +error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-union-borrow.rs:55:22 + | +LL | let rma = &mut u.a; + | -------- mutable borrow occurs here +LL | let ra = &u.a; + | ^^^^ immutable borrow occurs here +LL | drop(rma); + | --- mutable borrow later used here + +error[E0503]: cannot use `u.a` because it was mutably borrowed + --> $DIR/borrowck-union-borrow.rs:60:21 + | +LL | let ra = &mut u.a; + | -------- borrow of `u.a` occurs here +LL | let a = u.a; + | ^^^ use of borrowed `u.a` +LL | drop(ra); + | -- borrow later used here + +error[E0499]: cannot borrow `u.a` as mutable more than once at a time + --> $DIR/borrowck-union-borrow.rs:65:24 + | +LL | let rma = &mut u.a; + | -------- first mutable borrow occurs here +LL | let rma2 = &mut u.a; + | ^^^^^^^^ second mutable borrow occurs here +LL | drop(rma); + | --- first borrow later used here + +error[E0506]: cannot assign to `u.a` because it is borrowed + --> $DIR/borrowck-union-borrow.rs:70:13 + | +LL | let rma = &mut u.a; + | -------- borrow of `u.a` occurs here +LL | u.a = 1; + | ^^^^^^^ assignment to borrowed `u.a` occurs here +LL | drop(rma); + | --- borrow later used here + +error[E0502]: cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`) + --> $DIR/borrowck-union-borrow.rs:76:22 + | +LL | let rma = &mut u.a; + | -------- mutable borrow occurs here (via `u.a`) +LL | let rb = &u.b; + | ^^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here +LL | drop(rma); + | --- mutable borrow later used here + | + = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a` + +error[E0503]: cannot use `u.b` because it was mutably borrowed + --> $DIR/borrowck-union-borrow.rs:81:21 + | +LL | let ra = &mut u.a; + | -------- borrow of `u.a` occurs here +LL | let b = u.b; + | ^^^ use of borrowed `u.a` +LL | +LL | drop(ra); + | -- borrow later used here + +error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time + --> $DIR/borrowck-union-borrow.rs:87:24 + | +LL | let rma = &mut u.a; + | -------- first mutable borrow occurs here (via `u.a`) +LL | let rmb2 = &mut u.b; + | ^^^^^^^^ second mutable borrow occurs here (via `u.b`) +LL | drop(rma); + | --- first borrow later used here + | + = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a` + +error[E0506]: cannot assign to `u.b` because it is borrowed + --> $DIR/borrowck-union-borrow.rs:92:13 + | +LL | let rma = &mut u.a; + | -------- borrow of `u.b` occurs here +LL | u.b = 1; + | ^^^^^^^ assignment to borrowed `u.b` occurs here +LL | drop(rma); + | --- borrow later used here + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0499, E0502, E0503, E0506. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-union-move-assign.rs b/tests/ui/borrowck/borrowck-union-move-assign.rs new file mode 100644 index 000000000..4c96ccdb2 --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-move-assign.rs @@ -0,0 +1,32 @@ +use std::mem::ManuallyDrop; + +// Non-copy +struct A; +struct B; + +union U { + a: ManuallyDrop, + b: ManuallyDrop, +} + +fn main() { + unsafe { + { + let mut u = U { a: ManuallyDrop::new(A) }; + let a = u.a; + let a = u.a; //~ ERROR use of moved value: `u` + } + { + let mut u = U { a: ManuallyDrop::new(A) }; + let a = u.a; + u.a = ManuallyDrop::new(A); + let a = u.a; // OK + } + { + let mut u = U { a: ManuallyDrop::new(A) }; + let a = u.a; + u.b = ManuallyDrop::new(B); + let a = u.a; // OK + } + } +} diff --git a/tests/ui/borrowck/borrowck-union-move-assign.stderr b/tests/ui/borrowck/borrowck-union-move-assign.stderr new file mode 100644 index 000000000..af6f6fac4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-move-assign.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move-assign.rs:17:21 + | +LL | let mut u = U { a: ManuallyDrop::new(A) }; + | ----- move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = u.a; + | --- value moved here +LL | let a = u.a; + | ^^^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-union-move.rs b/tests/ui/borrowck/borrowck-union-move.rs new file mode 100644 index 000000000..510547ad5 --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-move.rs @@ -0,0 +1,86 @@ +use std::mem::ManuallyDrop; + +#[derive(Clone, Copy)] +struct Copy; +struct NonCopy; + +union Unn { + n1: ManuallyDrop, + n2: ManuallyDrop, +} +union Ucc { + c1: Copy, + c2: Copy, +} +union Ucn { + c: Copy, + n: ManuallyDrop, +} + +fn main() { + unsafe { + // 2 NonCopy + { + let mut u = Unn { n1: ManuallyDrop::new(NonCopy) }; + let a = u.n1; + let a = u.n1; //~ ERROR use of moved value: `u` + } + { + let mut u = Unn { n1: ManuallyDrop::new(NonCopy) }; + let a = u.n1; + let a = u; //~ ERROR use of moved value: `u` + } + { + let mut u = Unn { n1: ManuallyDrop::new(NonCopy) }; + let a = u.n1; + let a = u.n2; //~ ERROR use of moved value: `u` + } + // 2 Copy + { + let mut u = Ucc { c1: Copy }; + let a = u.c1; + let a = u.c1; // OK + } + { + let mut u = Ucc { c1: Copy }; + let a = u.c1; + let a = u; // OK + } + { + let mut u = Ucc { c1: Copy }; + let a = u.c1; + let a = u.c2; // OK + } + // 1 Copy, 1 NonCopy + { + let mut u = Ucn { c: Copy }; + let a = u.c; + let a = u.c; // OK + } + { + let mut u = Ucn { c: Copy }; + let a = u.n; + let a = u.n; //~ ERROR use of moved value: `u` + } + { + let mut u = Ucn { c: Copy }; + let a = u.n; + let a = u.c; //~ ERROR use of moved value: `u` + } + { + let mut u = Ucn { c: Copy }; + let a = u.c; + let a = u.n; // OK + } + { + let mut u = Ucn { c: Copy }; + let a = u.c; + let a = u; // OK + } + { + let mut u = Ucn { c: Copy }; + let a = u.n; + let a = u; //~ ERROR use of moved value: `u` + } + } +} diff --git a/tests/ui/borrowck/borrowck-union-move.stderr b/tests/ui/borrowck/borrowck-union-move.stderr new file mode 100644 index 000000000..731607fbd --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-move.stderr @@ -0,0 +1,63 @@ +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move.rs:26:21 + | +LL | let mut u = Unn { n1: ManuallyDrop::new(NonCopy) }; + | ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait +LL | let a = u.n1; + | ---- value moved here +LL | let a = u.n1; + | ^^^^ value used here after move + +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move.rs:31:21 + | +LL | let mut u = Unn { n1: ManuallyDrop::new(NonCopy) }; + | ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait +LL | let a = u.n1; + | ---- value moved here +LL | let a = u; + | ^ value used here after move + +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move.rs:36:21 + | +LL | let mut u = Unn { n1: ManuallyDrop::new(NonCopy) }; + | ----- move occurs because `u` has type `Unn`, which does not implement the `Copy` trait +LL | let a = u.n1; + | ---- value moved here +LL | let a = u.n2; + | ^^^^ value used here after move + +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move.rs:63:21 + | +LL | let mut u = Ucn { c: Copy }; + | ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait +LL | let a = u.n; + | --- value moved here +LL | let a = u.n; + | ^^^ value used here after move + +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move.rs:68:21 + | +LL | let mut u = Ucn { c: Copy }; + | ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait +LL | let a = u.n; + | --- value moved here +LL | let a = u.c; + | ^^^ value used here after move + +error[E0382]: use of moved value: `u` + --> $DIR/borrowck-union-move.rs:83:21 + | +LL | let mut u = Ucn { c: Copy }; + | ----- move occurs because `u` has type `Ucn`, which does not implement the `Copy` trait +LL | let a = u.n; + | --- value moved here +LL | let a = u; + | ^ value used here after move + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-union-uninitialized.rs b/tests/ui/borrowck/borrowck-union-uninitialized.rs new file mode 100644 index 000000000..bbe9f22aa --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-uninitialized.rs @@ -0,0 +1,18 @@ +struct S { + a: u8, +} + +union U { + a: u8, +} + +fn main() { + unsafe { + let mut s: S; + let mut u: U; + s.a = 0; //~ ERROR E0381 + u.a = 0; //~ ERROR E0381 + let sa = s.a; + let ua = u.a; + } +} diff --git a/tests/ui/borrowck/borrowck-union-uninitialized.stderr b/tests/ui/borrowck/borrowck-union-uninitialized.stderr new file mode 100644 index 000000000..b7ff5f395 --- /dev/null +++ b/tests/ui/borrowck/borrowck-union-uninitialized.stderr @@ -0,0 +1,25 @@ +error[E0381]: partially assigned binding `s` isn't fully initialized + --> $DIR/borrowck-union-uninitialized.rs:13:9 + | +LL | let mut s: S; + | ----- binding declared here but left uninitialized +LL | let mut u: U; +LL | s.a = 0; + | ^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `u` isn't fully initialized + --> $DIR/borrowck-union-uninitialized.rs:14:9 + | +LL | let mut u: U; + | ----- binding declared here but left uninitialized +LL | s.a = 0; +LL | u.a = 0; + | ^^^^^^^ `u` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-uniq-via-lend.rs b/tests/ui/borrowck/borrowck-uniq-via-lend.rs new file mode 100644 index 000000000..25d3e0b54 --- /dev/null +++ b/tests/ui/borrowck/borrowck-uniq-via-lend.rs @@ -0,0 +1,61 @@ +fn borrow(_v: &isize) {} + + + + + +fn local() { + let mut v: Box<_> = Box::new(3); + borrow(&*v); +} + +fn local_rec() { + struct F { f: Box } + let mut v = F {f: Box::new(3)}; + borrow(&*v.f); +} + +fn local_recs() { + struct F { f: G } + struct G { g: H } + struct H { h: Box } + let mut v = F {f: G {g: H {h: Box::new(3)}}}; + borrow(&*v.f.g.h); +} + +fn aliased_imm() { + let mut v: Box<_> = Box::new(3); + let w = &v; + borrow(&*v); + w.use_ref(); +} + +fn aliased_mut() { + let mut v: Box<_> = Box::new(3); + let w = &mut v; + borrow(&*v); //~ ERROR cannot borrow `*v` + w.use_mut(); +} + +fn aliased_other() { + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let x = &mut w; + borrow(&*v); + x.use_mut(); +} + +fn aliased_other_reassign() { + let mut v: Box<_> = Box::new(3); + let mut w: Box<_> = Box::new(4); + let mut x = &mut w; + x = &mut v; + borrow(&*v); //~ ERROR cannot borrow `*v` + x.use_mut(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-uniq-via-lend.stderr b/tests/ui/borrowck/borrowck-uniq-via-lend.stderr new file mode 100644 index 000000000..6dbe4c74b --- /dev/null +++ b/tests/ui/borrowck/borrowck-uniq-via-lend.stderr @@ -0,0 +1,23 @@ +error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-uniq-via-lend.rs:36:12 + | +LL | let w = &mut v; + | ------ mutable borrow occurs here +LL | borrow(&*v); + | ^^^ immutable borrow occurs here +LL | w.use_mut(); + | ----------- mutable borrow later used here + +error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-uniq-via-lend.rs:53:12 + | +LL | x = &mut v; + | ------ mutable borrow occurs here +LL | borrow(&*v); + | ^^^ immutable borrow occurs here +LL | x.use_mut(); + | ----------- mutable borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/borrowck-uniq-via-ref.rs b/tests/ui/borrowck/borrowck-uniq-via-ref.rs new file mode 100644 index 000000000..bdf7cc57a --- /dev/null +++ b/tests/ui/borrowck/borrowck-uniq-via-ref.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +struct Rec { + f: Box, +} + +struct Outer { + f: Inner +} + +struct Inner { + g: Innermost +} + +struct Innermost { + h: Box, +} + +fn borrow(_v: &isize) {} + +fn box_mut(v: &mut Box) { + borrow(&**v); // OK: &mut -> &imm +} + +fn box_mut_rec(v: &mut Rec) { + borrow(&*v.f); // OK: &mut -> &imm +} + +fn box_mut_recs(v: &mut Outer) { + borrow(&*v.f.g.h); // OK: &mut -> &imm +} + +fn box_imm(v: &Box) { + borrow(&**v); // OK +} + +fn box_imm_rec(v: &Rec) { + borrow(&*v.f); // OK +} + +fn box_imm_recs(v: &Outer) { + borrow(&*v.f.g.h); // OK +} + +pub fn main() { +} diff --git a/tests/ui/borrowck/borrowck-univariant-enum.rs b/tests/ui/borrowck/borrowck-univariant-enum.rs new file mode 100644 index 000000000..c78e94752 --- /dev/null +++ b/tests/ui/borrowck/borrowck-univariant-enum.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::cell::Cell; + +#[derive(Copy, Clone)] +enum newtype { + newvar(isize) +} + +pub fn main() { + + // Test that borrowck treats enums with a single variant + // specially. + + let x = &Cell::new(5); + let y = &Cell::new(newtype::newvar(3)); + let z = match y.get() { + newtype::newvar(b) => { + x.set(x.get() + 1); + x.get() * b + } + }; + assert_eq!(z, 18); +} diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs new file mode 100644 index 000000000..adc7dfd54 --- /dev/null +++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs @@ -0,0 +1,20 @@ +// run-pass + +// Test file taken from issue 45129 (https://github.com/rust-lang/rust/issues/45129) + +struct Foo { x: [usize; 2] } + +static mut SFOO: Foo = Foo { x: [23, 32] }; + +impl Foo { + fn x(&mut self) -> &mut usize { &mut self.x[0] } +} + +fn main() { + unsafe { + let sfoo: *mut Foo = &mut SFOO; + let x = (*sfoo).x(); + (*sfoo).x[1] += 1; + *x += 1; + } +} diff --git a/tests/ui/borrowck/borrowck-unused-mut-locals.rs b/tests/ui/borrowck/borrowck-unused-mut-locals.rs new file mode 100644 index 000000000..23ef975cb --- /dev/null +++ b/tests/ui/borrowck/borrowck-unused-mut-locals.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(dead_code)] +#![deny(unused_mut)] + +#[derive(Debug)] +struct A {} + +fn init_a() -> A { + A {} +} + +#[derive(Debug)] +struct B<'a> { + ed: &'a mut A, +} + +fn init_b<'a>(ed: &'a mut A) -> B<'a> { + B { ed } +} + +#[derive(Debug)] +struct C<'a> { + pd: &'a mut B<'a>, +} + +fn init_c<'a>(pd: &'a mut B<'a>) -> C<'a> { + C { pd } +} + +#[derive(Debug)] +struct D<'a> { + sd: &'a mut C<'a>, +} + +fn init_d<'a>(sd: &'a mut C<'a>) -> D<'a> { + D { sd } +} + +fn main() { + let mut a = init_a(); + let mut b = init_b(&mut a); + let mut c = init_c(&mut b); + + let d = init_d(&mut c); + + println!("{:?}", d) +} diff --git a/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs b/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs new file mode 100644 index 000000000..d30b1de5c --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs @@ -0,0 +1,9 @@ +fn test() { + let w: &mut [isize]; + w[5] = 0; //~ ERROR [E0381] + + let mut w: &mut [isize]; + w[5] = 0; //~ ERROR [E0381] +} + +fn main() { test(); } diff --git a/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr new file mode 100644 index 000000000..18e808f10 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr @@ -0,0 +1,29 @@ +error[E0381]: used binding `w` isn't initialized + --> $DIR/borrowck-use-in-index-lvalue.rs:3:5 + | +LL | let w: &mut [isize]; + | - binding declared here but left uninitialized +LL | w[5] = 0; + | ^^^^ `*w` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let w: &mut [isize] = todo!(); + | +++++++++ + +error[E0381]: used binding `w` isn't initialized + --> $DIR/borrowck-use-in-index-lvalue.rs:6:5 + | +LL | let mut w: &mut [isize]; + | ----- binding declared here but left uninitialized +LL | w[5] = 0; + | ^^^^ `*w` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut w: &mut [isize] = todo!(); + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs new file mode 100644 index 000000000..1cf763f66 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs @@ -0,0 +1,49 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct A { a: isize, b: Box } + +fn field_copy_after_field_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.b; + drop(x.a); + **p = 3; +} + +fn fu_field_copy_after_field_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.b; + let y = A { b: Box::new(3), .. x }; + drop(y); + **p = 4; +} + +fn field_deref_after_field_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.a; + drop(*x.b); + *p = 3; +} + +fn field_move_after_field_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.a; + drop(x.b); + *p = 3; +} + +fn fu_field_move_after_field_borrow() { + let mut x = A { a: 1, b: Box::new(2) }; + let p = &mut x.a; + let y = A { a: 3, .. x }; + drop(y); + *p = 4; +} + +fn main() { + field_copy_after_field_borrow(); + fu_field_copy_after_field_borrow(); + field_deref_after_field_borrow(); + field_move_after_field_borrow(); + fu_field_move_after_field_borrow(); +} diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow.rs b/tests/ui/borrowck/borrowck-use-mut-borrow.rs new file mode 100644 index 000000000..94f88395f --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-mut-borrow.rs @@ -0,0 +1,86 @@ +#[derive(Copy, Clone)] +struct A { a: isize, b: isize } + +struct B { a: isize, b: Box } + + + +fn var_copy_after_var_borrow() { + let mut x: isize = 1; + let p = &mut x; + drop(x); //~ ERROR cannot use `x` because it was mutably borrowed + *p = 2; +} + +fn var_copy_after_field_borrow() { + let mut x = A { a: 1, b: 2 }; + let p = &mut x.a; + drop(x); //~ ERROR cannot use `x` because it was mutably borrowed + *p = 3; +} + +fn field_copy_after_var_borrow() { + let mut x = A { a: 1, b: 2 }; + let p = &mut x; + drop(x.a); //~ ERROR cannot use `x.a` because it was mutably borrowed + p.a = 3; +} + +fn field_copy_after_field_borrow() { + let mut x = A { a: 1, b: 2 }; + let p = &mut x.a; + drop(x.a); //~ ERROR cannot use `x.a` because it was mutably borrowed + *p = 3; +} + +fn fu_field_copy_after_var_borrow() { + let mut x = A { a: 1, b: 2 }; + let p = &mut x; + let y = A { b: 3, .. x }; //~ ERROR cannot use `x.a` because it was mutably borrowed + drop(y); + p.a = 4; +} + +fn fu_field_copy_after_field_borrow() { + let mut x = A { a: 1, b: 2 }; + let p = &mut x.a; + let y = A { b: 3, .. x }; //~ ERROR cannot use `x.a` because it was mutably borrowed + drop(y); + *p = 4; +} + +fn var_deref_after_var_borrow() { + let mut x: Box = Box::new(1); + let p = &mut x; + drop(*x); //~ ERROR cannot use `*x` because it was mutably borrowed + **p = 2; +} + +fn field_deref_after_var_borrow() { + let mut x = B { a: 1, b: Box::new(2) }; + let p = &mut x; + drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed + p.a = 3; +} + +fn field_deref_after_field_borrow() { + let mut x = B { a: 1, b: Box::new(2) }; + let p = &mut x.b; + drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed + **p = 3; +} + +fn main() { + var_copy_after_var_borrow(); + var_copy_after_field_borrow(); + + field_copy_after_var_borrow(); + field_copy_after_field_borrow(); + + fu_field_copy_after_var_borrow(); + fu_field_copy_after_field_borrow(); + + var_deref_after_var_borrow(); + field_deref_after_var_borrow(); + field_deref_after_field_borrow(); +} diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow.stderr b/tests/ui/borrowck/borrowck-use-mut-borrow.stderr new file mode 100644 index 000000000..91d69c51e --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-mut-borrow.stderr @@ -0,0 +1,95 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:11:10 + | +LL | let p = &mut x; + | ------ borrow of `x` occurs here +LL | drop(x); + | ^ use of borrowed `x` +LL | *p = 2; + | ------ borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:18:10 + | +LL | let p = &mut x.a; + | -------- borrow of `x.a` occurs here +LL | drop(x); + | ^ use of borrowed `x.a` +LL | *p = 3; + | ------ borrow later used here + +error[E0503]: cannot use `x.a` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:25:10 + | +LL | let p = &mut x; + | ------ borrow of `x` occurs here +LL | drop(x.a); + | ^^^ use of borrowed `x` +LL | p.a = 3; + | ------- borrow later used here + +error[E0503]: cannot use `x.a` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:32:10 + | +LL | let p = &mut x.a; + | -------- borrow of `x.a` occurs here +LL | drop(x.a); + | ^^^ use of borrowed `x.a` +LL | *p = 3; + | ------ borrow later used here + +error[E0503]: cannot use `x.a` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:39:13 + | +LL | let p = &mut x; + | ------ borrow of `x` occurs here +LL | let y = A { b: 3, .. x }; + | ^^^^^^^^^^^^^^^^ use of borrowed `x` +LL | drop(y); +LL | p.a = 4; + | ------- borrow later used here + +error[E0503]: cannot use `x.a` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:47:13 + | +LL | let p = &mut x.a; + | -------- borrow of `x.a` occurs here +LL | let y = A { b: 3, .. x }; + | ^^^^^^^^^^^^^^^^ use of borrowed `x.a` +LL | drop(y); +LL | *p = 4; + | ------ borrow later used here + +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:55:10 + | +LL | let p = &mut x; + | ------ borrow of `x` occurs here +LL | drop(*x); + | ^^ use of borrowed `x` +LL | **p = 2; + | ------- borrow later used here + +error[E0503]: cannot use `*x.b` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:62:10 + | +LL | let p = &mut x; + | ------ borrow of `x` occurs here +LL | drop(*x.b); + | ^^^^ use of borrowed `x` +LL | p.a = 3; + | ------- borrow later used here + +error[E0503]: cannot use `*x.b` because it was mutably borrowed + --> $DIR/borrowck-use-mut-borrow.rs:69:10 + | +LL | let p = &mut x.b; + | -------- borrow of `x.b` occurs here +LL | drop(*x.b); + | ^^^^ use of borrowed `x.b` +LL | **p = 3; + | ------- borrow later used here + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs new file mode 100644 index 000000000..3ce721618 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs @@ -0,0 +1,10 @@ +// Variation on `borrowck-use-uninitialized-in-cast` in which we do a +// trait cast from an uninitialized source. Issue #20791. + +trait Foo { fn dummy(&self) { } } +impl Foo for i32 { } + +fn main() { + let x: &i32; + let y = x as *const dyn Foo; //~ ERROR [E0381] +} diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr new file mode 100644 index 000000000..55f3ff553 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13 + | +LL | let x: &i32; + | - binding declared here but left uninitialized +LL | let y = x as *const dyn Foo; + | ^ `*x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &i32 = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs new file mode 100644 index 000000000..a355a546d --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs @@ -0,0 +1,8 @@ +// Check that we detect unused values that are cast to other things. +// The problem was specified to casting to `*`, as creating unsafe +// pointers was not being fully checked. Issue #20791. + +fn main() { + let x: &i32; + let y = x as *const i32; //~ ERROR [E0381] +} diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr new file mode 100644 index 000000000..ea3d0d3ef --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13 + | +LL | let x: &i32; + | - binding declared here but left uninitialized +LL | let y = x as *const i32; + | ^ `*x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &i32 = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-element-loan.rs b/tests/ui/borrowck/borrowck-vec-pattern-element-loan.rs new file mode 100644 index 000000000..cd853b833 --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-element-loan.rs @@ -0,0 +1,31 @@ +fn a<'a>() -> &'a [isize] { + let vec = vec![1, 2, 3, 4]; + let vec: &[isize] = &vec; + let tail = match vec { + &[_, ref tail @ ..] => tail, + _ => panic!("a") + }; + tail //~ ERROR cannot return value referencing local variable `vec` +} + +fn b<'a>() -> &'a [isize] { + let vec = vec![1, 2, 3, 4]; + let vec: &[isize] = &vec; + let init = match vec { + &[ref init @ .., _] => init, + _ => panic!("b") + }; + init //~ ERROR cannot return value referencing local variable `vec` +} + +fn c<'a>() -> &'a [isize] { + let vec = vec![1, 2, 3, 4]; + let vec: &[isize] = &vec; + let slice = match vec { + &[_, ref slice @ .., _] => slice, + _ => panic!("c") + }; + slice //~ ERROR cannot return value referencing local variable `vec` +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-vec-pattern-element-loan.stderr b/tests/ui/borrowck/borrowck-vec-pattern-element-loan.stderr new file mode 100644 index 000000000..170982b16 --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-element-loan.stderr @@ -0,0 +1,30 @@ +error[E0515]: cannot return value referencing local variable `vec` + --> $DIR/borrowck-vec-pattern-element-loan.rs:8:5 + | +LL | let vec: &[isize] = &vec; + | ---- `vec` is borrowed here +... +LL | tail + | ^^^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing local variable `vec` + --> $DIR/borrowck-vec-pattern-element-loan.rs:18:5 + | +LL | let vec: &[isize] = &vec; + | ---- `vec` is borrowed here +... +LL | init + | ^^^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing local variable `vec` + --> $DIR/borrowck-vec-pattern-element-loan.rs:28:5 + | +LL | let vec: &[isize] = &vec; + | ---- `vec` is borrowed here +... +LL | slice + | ^^^^^ returns a value referencing data owned by the current function + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs b/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs new file mode 100644 index 000000000..05859c95d --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs @@ -0,0 +1,12 @@ +fn a() { + let mut v = vec![1, 2, 3]; + let vb: &mut [isize] = &mut v; + match vb { + &mut [_a, ref tail @ ..] => { + v.push(tail[0] + tail[1]); //~ ERROR cannot borrow + } + _ => {} + }; +} + +fn main() {} diff --git a/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr new file mode 100644 index 000000000..eb0f24b9b --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `v` as mutable more than once at a time + --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:6:13 + | +LL | let vb: &mut [isize] = &mut v; + | ------ first mutable borrow occurs here +... +LL | v.push(tail[0] + tail[1]); + | ^^^^^^^-------^^^^^^^^^^^ + | | | + | | first borrow later used here + | second mutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.rs new file mode 100644 index 000000000..9b8ba2ea8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -0,0 +1,11 @@ +fn main() { + let mut a = [1, 2, 3, 4]; + let t = match a { + [1, 2, ref tail @ ..] => tail, + _ => unreachable!() + }; + println!("t[0]: {}", t[0]); + a[2] = 0; //~ ERROR cannot assign to `a[_]` because it is borrowed + println!("t[0]: {}", t[0]); + t[0]; +} diff --git a/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr new file mode 100644 index 000000000..0ac7df944 --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `a[_]` because it is borrowed + --> $DIR/borrowck-vec-pattern-move-tail.rs:8:5 + | +LL | [1, 2, ref tail @ ..] => tail, + | -------- borrow of `a[_]` occurs here +... +LL | a[2] = 0; + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here +LL | println!("t[0]: {}", t[0]); + | ---- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs new file mode 100644 index 000000000..0e9284a2c --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -0,0 +1,94 @@ +#![feature(box_patterns)] + + +fn a() { + let mut vec = [Box::new(1), Box::new(2), Box::new(3)]; + match vec { + [box ref _a, _, _] => { + //~^ NOTE borrow of `vec[_]` occurs here + vec[0] = Box::new(4); //~ ERROR cannot assign + //~^ NOTE assignment to borrowed `vec[_]` occurs here + _a.use_ref(); + //~^ NOTE borrow later used here + } + } +} + +fn b() { + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; + let vec: &mut [Box] = &mut vec; + match vec { + &mut [ref _b @ ..] => { + //~^ borrow of `vec[_]` occurs here + vec[0] = Box::new(4); //~ ERROR cannot assign + //~^ NOTE assignment to borrowed `vec[_]` occurs here + _b.use_ref(); + //~^ NOTE borrow later used here + } + } +} + +fn c() { + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; + let vec: &mut [Box] = &mut vec; + match vec { + //~^ ERROR cannot move out + //~| NOTE cannot move out + &mut [_a, + //~^ NOTE data moved here + //~| NOTE move occurs because `_a` has type + //~| HELP consider removing the mutable borrow + .. + ] => { + } + _ => {} + } + let a = vec[0]; //~ ERROR cannot move out + //~| NOTE cannot move out of here + //~| NOTE move occurs because + //~| HELP consider borrowing here +} + +fn d() { + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; + let vec: &mut [Box] = &mut vec; + match vec { + //~^ ERROR cannot move out + //~| NOTE cannot move out + &mut [ + //~^ HELP consider removing the mutable borrow + _b] => {} + //~^ NOTE data moved here + //~| NOTE move occurs because `_b` has type + _ => {} + } + let a = vec[0]; //~ ERROR cannot move out + //~| NOTE cannot move out of here + //~| NOTE move occurs because + //~| HELP consider borrowing here +} + +fn e() { + let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)]; + let vec: &mut [Box] = &mut vec; + match vec { + //~^ ERROR cannot move out + //~| NOTE cannot move out + //~| NOTE move occurs because these variables have types + &mut [_a, _b, _c] => {} + //~^ NOTE data moved here + //~| NOTE and here + //~| NOTE and here + //~| HELP consider removing the mutable borrow + _ => {} + } + let a = vec[0]; //~ ERROR cannot move out + //~| NOTE cannot move out of here + //~| NOTE move occurs because + //~| HELP consider borrowing here +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr new file mode 100644 index 000000000..0dc5e64e4 --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -0,0 +1,125 @@ +error[E0506]: cannot assign to `vec[_]` because it is borrowed + --> $DIR/borrowck-vec-pattern-nesting.rs:9:13 + | +LL | [box ref _a, _, _] => { + | ------ borrow of `vec[_]` occurs here +LL | +LL | vec[0] = Box::new(4); + | ^^^^^^ assignment to borrowed `vec[_]` occurs here +LL | +LL | _a.use_ref(); + | ------------ borrow later used here + +error[E0506]: cannot assign to `vec[_]` because it is borrowed + --> $DIR/borrowck-vec-pattern-nesting.rs:23:13 + | +LL | &mut [ref _b @ ..] => { + | ------ borrow of `vec[_]` occurs here +LL | +LL | vec[0] = Box::new(4); + | ^^^^^^ assignment to borrowed `vec[_]` occurs here +LL | +LL | _b.use_ref(); + | ------------ borrow later used here + +error[E0508]: cannot move out of type `[Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:34:11 + | +LL | match vec { + | ^^^ cannot move out of here +... +LL | &mut [_a, + | -- + | | + | data moved here + | move occurs because `_a` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut [_a, +LL + [_a, + | + +error[E0508]: cannot move out of type `[Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:46:13 + | +LL | let a = vec[0]; + | ^^^^^^ + | | + | cannot move out of here + | move occurs because `vec[_]` has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &vec[0]; + | + + +error[E0508]: cannot move out of type `[Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:55:11 + | +LL | match vec { + | ^^^ cannot move out of here +... +LL | _b] => {} + | -- + | | + | data moved here + | move occurs because `_b` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut [ +LL + [ + | + +error[E0508]: cannot move out of type `[Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:65:13 + | +LL | let a = vec[0]; + | ^^^^^^ + | | + | cannot move out of here + | move occurs because `vec[_]` has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &vec[0]; + | + + +error[E0508]: cannot move out of type `[Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:74:11 + | +LL | match vec { + | ^^^ cannot move out of here +... +LL | &mut [_a, _b, _c] => {} + | -- -- -- ...and here + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut [_a, _b, _c] => {} +LL + [_a, _b, _c] => {} + | + +error[E0508]: cannot move out of type `[Box]`, a non-copy slice + --> $DIR/borrowck-vec-pattern-nesting.rs:85:13 + | +LL | let a = vec[0]; + | ^^^^^^ + | | + | cannot move out of here + | move occurs because `vec[_]` has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &vec[0]; + | + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0506, E0508. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs b/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs new file mode 100644 index 000000000..39872825c --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs @@ -0,0 +1,14 @@ +fn a<'a>() -> &'a isize { + let vec = vec![1, 2, 3, 4]; + let vec: &[isize] = &vec; + let tail = match vec { + &[_a, ref tail @ ..] => &tail[0], + _ => panic!("foo") + }; + tail //~ ERROR cannot return value referencing local variable `vec` +} + +fn main() { + let fifth = a(); + println!("{}", *fifth); +} diff --git a/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr b/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr new file mode 100644 index 000000000..7e21c55f2 --- /dev/null +++ b/tests/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `vec` + --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:8:5 + | +LL | let vec: &[isize] = &vec; + | ---- `vec` is borrowed here +... +LL | tail + | ^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/borrowck-while-break.rs b/tests/ui/borrowck/borrowck-while-break.rs new file mode 100644 index 000000000..7100b7130 --- /dev/null +++ b/tests/ui/borrowck/borrowck-while-break.rs @@ -0,0 +1,12 @@ +fn test(cond: bool) { + let v; + while cond { + v = 3; + break; + } + println!("{}", v); //~ ERROR E0381 +} + +fn main() { + test(true); +} diff --git a/tests/ui/borrowck/borrowck-while-break.stderr b/tests/ui/borrowck/borrowck-while-break.stderr new file mode 100644 index 000000000..13143d436 --- /dev/null +++ b/tests/ui/borrowck/borrowck-while-break.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `v` is possibly-uninitialized + --> $DIR/borrowck-while-break.rs:7:20 + | +LL | let v; + | - binding declared here but left uninitialized +LL | while cond { + | ---- if this condition isn't met and the `while` loop runs 0 times, `v` is not initialized +... +LL | println!("{}", v); + | ^ `v` used here but it is possibly-uninitialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-while-cond.rs b/tests/ui/borrowck/borrowck-while-cond.rs new file mode 100644 index 000000000..62a9bdd20 --- /dev/null +++ b/tests/ui/borrowck/borrowck-while-cond.rs @@ -0,0 +1,4 @@ +fn main() { + let x: bool; + while x { } //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/borrowck-while-cond.stderr b/tests/ui/borrowck/borrowck-while-cond.stderr new file mode 100644 index 000000000..5d0194989 --- /dev/null +++ b/tests/ui/borrowck/borrowck-while-cond.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/borrowck-while-cond.rs:3:11 + | +LL | let x: bool; + | - binding declared here but left uninitialized +LL | while x { } + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: bool = false; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/borrowck-while.rs b/tests/ui/borrowck/borrowck-while.rs new file mode 100644 index 000000000..f49a778eb --- /dev/null +++ b/tests/ui/borrowck/borrowck-while.rs @@ -0,0 +1,7 @@ +fn f() -> isize { + let mut x: isize; + while 1 == 1 { x = 10; } + return x; //~ ERROR E0381 +} + +fn main() { f(); } diff --git a/tests/ui/borrowck/borrowck-while.stderr b/tests/ui/borrowck/borrowck-while.stderr new file mode 100644 index 000000000..c45235990 --- /dev/null +++ b/tests/ui/borrowck/borrowck-while.stderr @@ -0,0 +1,13 @@ +error[E0381]: used binding `x` is possibly-uninitialized + --> $DIR/borrowck-while.rs:4:12 + | +LL | let mut x: isize; + | ----- binding declared here but left uninitialized +LL | while 1 == 1 { x = 10; } + | ------ if this condition isn't met and the `while` loop runs 0 times, `x` is not initialized +LL | return x; + | ^ `x` used here but it is possibly-uninitialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.rs b/tests/ui/borrowck/copy-suggestion-region-vid.rs new file mode 100644 index 000000000..dff952834 --- /dev/null +++ b/tests/ui/borrowck/copy-suggestion-region-vid.rs @@ -0,0 +1,17 @@ +pub struct DataStruct(); + +pub struct HelperStruct<'n> { + pub helpers: [Vec<&'n i64>; 2], + pub is_empty: bool, +} + +impl DataStruct { + pub fn f(&self) -> HelperStruct { + let helpers = [vec![], vec![]]; + + HelperStruct { helpers, is_empty: helpers[0].is_empty() } + //~^ ERROR borrow of moved value + } +} + +fn main() {} diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.stderr b/tests/ui/borrowck/copy-suggestion-region-vid.stderr new file mode 100644 index 000000000..1685acf87 --- /dev/null +++ b/tests/ui/borrowck/copy-suggestion-region-vid.stderr @@ -0,0 +1,14 @@ +error[E0382]: borrow of moved value: `helpers` + --> $DIR/copy-suggestion-region-vid.rs:12:43 + | +LL | let helpers = [vec![], vec![]]; + | ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait +LL | +LL | HelperStruct { helpers, is_empty: helpers[0].is_empty() } + | ------- ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move + | | + | value moved here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/disallow-possibly-uninitialized.rs b/tests/ui/borrowck/disallow-possibly-uninitialized.rs new file mode 100644 index 000000000..17de40d5b --- /dev/null +++ b/tests/ui/borrowck/disallow-possibly-uninitialized.rs @@ -0,0 +1,22 @@ +// Test that we don't allow partial initialization. +// This may be relaxed in the future (see #54987). + +fn main() { + let mut t: (u64, u64); + t.0 = 1; + //~^ ERROR E0381 + t.1 = 1; + + let mut t: (u64, u64); + t.1 = 1; + //~^ ERROR E0381 + t.0 = 1; + + let mut t: (u64, u64); + t.0 = 1; + //~^ ERROR E0381 + + let mut t: (u64,); + t.0 = 1; + //~^ ERROR E0381 +} diff --git a/tests/ui/borrowck/disallow-possibly-uninitialized.stderr b/tests/ui/borrowck/disallow-possibly-uninitialized.stderr new file mode 100644 index 000000000..9a84c6fef --- /dev/null +++ b/tests/ui/borrowck/disallow-possibly-uninitialized.stderr @@ -0,0 +1,43 @@ +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/disallow-possibly-uninitialized.rs:6:5 + | +LL | let mut t: (u64, u64); + | ----- binding declared here but left uninitialized +LL | t.0 = 1; + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/disallow-possibly-uninitialized.rs:11:5 + | +LL | let mut t: (u64, u64); + | ----- binding declared here but left uninitialized +LL | t.1 = 1; + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/disallow-possibly-uninitialized.rs:16:5 + | +LL | let mut t: (u64, u64); + | ----- binding declared here but left uninitialized +LL | t.0 = 1; + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/disallow-possibly-uninitialized.rs:20:5 + | +LL | let mut t: (u64,); + | ----- binding declared here but left uninitialized +LL | t.0 = 1; + | ^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs b/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs new file mode 100644 index 000000000..524459291 --- /dev/null +++ b/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs @@ -0,0 +1,8 @@ +fn main() { + let mut vec: Vec = Vec::new(); + let closure = move || { + vec.clear(); + let mut iter = vec.iter(); + move || { iter.next() } //~ ERROR captured variable cannot escape `FnMut` closure bod + }; +} diff --git a/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr b/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr new file mode 100644 index 000000000..78ca090fe --- /dev/null +++ b/tests/ui/borrowck/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.stderr @@ -0,0 +1,18 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/do-not-suggest-adding-move-when-closure-is-already-marked-as-move.rs:6:9 + | +LL | let mut vec: Vec = Vec::new(); + | ------- variable defined here +LL | let closure = move || { + | - inferred to be a `FnMut` closure +LL | vec.clear(); + | --- variable captured here +LL | let mut iter = vec.iter(); +LL | move || { iter.next() } + | ^^^^^^^^^^^^^^^^^^^^^^^ returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/borrowck/fsu-moves-and-copies.rs b/tests/ui/borrowck/fsu-moves-and-copies.rs new file mode 100644 index 000000000..85e0a840a --- /dev/null +++ b/tests/ui/borrowck/fsu-moves-and-copies.rs @@ -0,0 +1,95 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(stable_features)] +// Issue 4691: Ensure that functional-struct-updates operates +// correctly and moves rather than copy when appropriate. + +#![feature(core)] + +struct ncint { v: isize } +fn ncint(v: isize) -> ncint { ncint { v: v } } + +struct NoFoo { copied: isize, nocopy: ncint, } +impl NoFoo { + fn new(x:isize,y:isize) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } } +} + +struct MoveFoo { copied: isize, moved: Box, } +impl MoveFoo { + fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: Box::new(y) } } +} + +struct DropNoFoo { inner: NoFoo } +impl DropNoFoo { + fn new(x:isize,y:isize) -> DropNoFoo { DropNoFoo { inner: NoFoo::new(x,y) } } +} +impl Drop for DropNoFoo { fn drop(&mut self) { } } + +struct DropMoveFoo { inner: MoveFoo } +impl DropMoveFoo { + fn new(x:isize,y:isize) -> DropMoveFoo { DropMoveFoo { inner: MoveFoo::new(x,y) } } +} +impl Drop for DropMoveFoo { fn drop(&mut self) { } } + + +fn test0() { + // just copy implicitly copyable fields from `f`, no moves + // (and thus it is okay that these are Drop; compare against + // test ui/borrowck/borrowck-struct-update-with-dtor.rs). + + // Case 1: Nocopyable + let f = DropNoFoo::new(1, 2); + let b = DropNoFoo { inner: NoFoo { nocopy: ncint(3), ..f.inner }}; + let c = DropNoFoo { inner: NoFoo { nocopy: ncint(4), ..f.inner }}; + assert_eq!(f.inner.copied, 1); + assert_eq!(f.inner.nocopy.v, 2); + + assert_eq!(b.inner.copied, 1); + assert_eq!(b.inner.nocopy.v, 3); + + assert_eq!(c.inner.copied, 1); + assert_eq!(c.inner.nocopy.v, 4); + + // Case 2: Owned + let f = DropMoveFoo::new(5, 6); + let b = DropMoveFoo { inner: MoveFoo { moved: Box::new(7), ..f.inner }}; + let c = DropMoveFoo { inner: MoveFoo { moved: Box::new(8), ..f.inner }}; + assert_eq!(f.inner.copied, 5); + assert_eq!(*f.inner.moved, 6); + + assert_eq!(b.inner.copied, 5); + assert_eq!(*b.inner.moved, 7); + + assert_eq!(c.inner.copied, 5); + assert_eq!(*c.inner.moved, 8); +} + +fn test1() { + // copying move-by-default fields from `f`, so it moves: + let f = MoveFoo::new(11, 12); + + let b = MoveFoo {moved: Box::new(13), ..f}; + let c = MoveFoo {copied: 14, ..f}; + assert_eq!(b.copied, 11); + assert_eq!(*b.moved, 13); + assert_eq!(c.copied, 14); + assert_eq!(*c.moved, 12); +} + +fn test2() { + // move non-copyable field + let f = NoFoo::new(21, 22); + let b = NoFoo {nocopy: ncint(23), ..f}; + let c = NoFoo {copied: 24, ..f}; + assert_eq!(b.copied, 21); + assert_eq!(b.nocopy.v, 23); + assert_eq!(c.copied, 24); + assert_eq!(c.nocopy.v, 22); +} + +pub fn main() { + test0(); + test1(); + test2(); +} diff --git a/tests/ui/borrowck/immut-function-arguments.rs b/tests/ui/borrowck/immut-function-arguments.rs new file mode 100644 index 000000000..242a33e82 --- /dev/null +++ b/tests/ui/borrowck/immut-function-arguments.rs @@ -0,0 +1,9 @@ +fn f(y: Box) { + *y = 5; //~ ERROR cannot assign +} + +fn g() { + let _frob = |q: Box| { *q = 2; }; //~ ERROR cannot assign +} + +fn main() {} diff --git a/tests/ui/borrowck/immut-function-arguments.stderr b/tests/ui/borrowck/immut-function-arguments.stderr new file mode 100644 index 000000000..d5392e7d6 --- /dev/null +++ b/tests/ui/borrowck/immut-function-arguments.stderr @@ -0,0 +1,25 @@ +error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable + --> $DIR/immut-function-arguments.rs:2:5 + | +LL | *y = 5; + | ^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | fn f(mut y: Box) { + | +++ + +error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable + --> $DIR/immut-function-arguments.rs:6:35 + | +LL | let _frob = |q: Box| { *q = 2; }; + | ^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let _frob = |mut q: Box| { *q = 2; }; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/immutable-arg.rs b/tests/ui/borrowck/immutable-arg.rs new file mode 100644 index 000000000..2352d1bbe --- /dev/null +++ b/tests/ui/borrowck/immutable-arg.rs @@ -0,0 +1,6 @@ +fn foo(_x: u32) { + _x = 4; + //~^ ERROR cannot assign to immutable argument `_x` +} + +fn main() {} diff --git a/tests/ui/borrowck/immutable-arg.stderr b/tests/ui/borrowck/immutable-arg.stderr new file mode 100644 index 000000000..bddb0633a --- /dev/null +++ b/tests/ui/borrowck/immutable-arg.stderr @@ -0,0 +1,11 @@ +error[E0384]: cannot assign to immutable argument `_x` + --> $DIR/immutable-arg.rs:2:5 + | +LL | fn foo(_x: u32) { + | -- help: consider making this binding mutable: `mut _x` +LL | _x = 4; + | ^^^^^^ cannot assign to immutable argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/borrowck/index-mut-help-with-impl.rs b/tests/ui/borrowck/index-mut-help-with-impl.rs new file mode 100644 index 000000000..44b57c4a0 --- /dev/null +++ b/tests/ui/borrowck/index-mut-help-with-impl.rs @@ -0,0 +1,10 @@ +// When mutably indexing a type that implements `Index` and `IndexMut` but +// `Index::index` is being used specifically, the normal special help message +// should not mention a missing `IndexMut` impl. + +fn main() { + use std::ops::Index; + + let v = String::from("dinosaur"); + Index::index(&v, 1..2).make_ascii_uppercase(); //~ ERROR +} diff --git a/tests/ui/borrowck/index-mut-help-with-impl.stderr b/tests/ui/borrowck/index-mut-help-with-impl.stderr new file mode 100644 index 000000000..69dca7e7b --- /dev/null +++ b/tests/ui/borrowck/index-mut-help-with-impl.stderr @@ -0,0 +1,9 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/index-mut-help-with-impl.rs:9:5 + | +LL | Index::index(&v, 1..2).make_ascii_uppercase(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/index-mut-help.rs b/tests/ui/borrowck/index-mut-help.rs new file mode 100644 index 000000000..35266e113 --- /dev/null +++ b/tests/ui/borrowck/index-mut-help.rs @@ -0,0 +1,13 @@ +// When mutably indexing a type that implements `Index` but not `IndexMut`, a +// special 'help' message is added to the output. +use std::collections::HashMap; + + +fn main() { + let mut map = HashMap::new(); + map.insert("peter", "23".to_string()); + + map["peter"].clear(); //~ ERROR + map["peter"] = "0".to_string(); //~ ERROR + let _ = &mut map["peter"]; //~ ERROR +} diff --git a/tests/ui/borrowck/index-mut-help.stderr b/tests/ui/borrowck/index-mut-help.stderr new file mode 100644 index 000000000..f42d7e015 --- /dev/null +++ b/tests/ui/borrowck/index-mut-help.stderr @@ -0,0 +1,41 @@ +error[E0596]: cannot borrow data in an index of `HashMap<&str, String>` as mutable + --> $DIR/index-mut-help.rs:10:5 + | +LL | map["peter"].clear(); + | ^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>` +help: to modify a `HashMap<&str, String>` use `.get_mut()` + | +LL | map.get_mut("peter").map(|val| val.clear()); + | ~~~~~~~~~ ~~~~~~~~~~~~~~~ + + +error[E0594]: cannot assign to data in an index of `HashMap<&str, String>` + --> $DIR/index-mut-help.rs:11:5 + | +LL | map["peter"] = "0".to_string(); + | ^^^^^^^^^^^^ cannot assign + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>` +help: to modify a `HashMap<&str, String>`, use `.get_mut()`, `.insert()` or the entry API + | +LL | map.insert("peter", "0".to_string()); + | ~~~~~~~~ ~ + +LL | map.get_mut("peter").map(|val| { *val = "0".to_string(); }); + | ~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ ++++ +LL | let val = map.entry("peter").or_insert("0".to_string()); + | +++++++++ ~~~~~~~ ~~~~~~~~~~~~ + + +error[E0596]: cannot borrow data in an index of `HashMap<&str, String>` as mutable + --> $DIR/index-mut-help.rs:12:13 + | +LL | let _ = &mut map["peter"]; + | ^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>` + = help: to modify a `HashMap<&str, String>`, use `.get_mut()`, `.insert()` or the entry API + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-101119.rs b/tests/ui/borrowck/issue-101119.rs new file mode 100644 index 000000000..64e52eaac --- /dev/null +++ b/tests/ui/borrowck/issue-101119.rs @@ -0,0 +1,16 @@ +struct State; + +fn once(_: impl FnOnce()) {} + +fn fill_memory_blocks_mt(state: &mut State) { + loop { + once(move || { + //~^ ERROR use of moved value: `state` + fill_segment(state); + }); + } +} + +fn fill_segment(_: &mut State) {} + +fn main() {} diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr new file mode 100644 index 000000000..a22afdc67 --- /dev/null +++ b/tests/ui/borrowck/issue-101119.stderr @@ -0,0 +1,15 @@ +error[E0382]: use of moved value: `state` + --> $DIR/issue-101119.rs:7:14 + | +LL | fn fill_memory_blocks_mt(state: &mut State) { + | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait +LL | loop { +LL | once(move || { + | ^^^^^^^ value moved into closure here, in previous iteration of loop +LL | +LL | fill_segment(state); + | ----- use occurs due to use in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-102209.rs b/tests/ui/borrowck/issue-102209.rs new file mode 100644 index 000000000..37628bff7 --- /dev/null +++ b/tests/ui/borrowck/issue-102209.rs @@ -0,0 +1,28 @@ +use std::marker::PhantomData; + +pub struct NfaBuilder<'brand> { + brand: PhantomData<&'brand mut &'brand mut ()>, +} + +impl NfaBuilder<'_> { + pub fn with) -> R>(f: F) -> R { + Brand::with(|brand| { + f(Self { brand: brand.lt }) + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + }) + } +} + +#[derive(Clone, Copy)] +pub struct Brand<'brand> { + lt: PhantomData<&'brand mut &'brand mut ()>, +} + +impl Brand<'_> { + pub fn with) -> R>(f: F) -> R { + f(Self { lt: PhantomData }) + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-102209.stderr b/tests/ui/borrowck/issue-102209.stderr new file mode 100644 index 000000000..351de8217 --- /dev/null +++ b/tests/ui/borrowck/issue-102209.stderr @@ -0,0 +1,22 @@ +error: lifetime may not live long enough + --> $DIR/issue-102209.rs:10:29 + | +LL | impl NfaBuilder<'_> { + | -- lifetime `'2` appears in the `impl`'s self type +LL | pub fn with) -> R>(f: F) -> R { +LL | Brand::with(|brand| { + | ----- has type `Brand<'1>` +LL | f(Self { brand: brand.lt }) + | ^^^^^^^^ this usage requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/issue-102209.rs:10:29 + | +LL | impl NfaBuilder<'_> { + | -- lifetime `'1` appears in the `impl`'s self type +... +LL | f(Self { brand: brand.lt }) + | ^^^^^^^^ this usage requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/borrowck/issue-103095.rs b/tests/ui/borrowck/issue-103095.rs new file mode 100644 index 000000000..0340f3924 --- /dev/null +++ b/tests/ui/borrowck/issue-103095.rs @@ -0,0 +1,30 @@ +// check-pass + +trait FnOnceForGenericRef: FnOnce(&T) -> Self::FnOutput { + type FnOutput; +} + +impl R> FnOnceForGenericRef for F { + type FnOutput = R; +} + +struct Data> { + value: Option, + output: Option, +} + +impl> Data { + fn new(value: T, f: D) -> Self { + let output = f(&value); + Self { + value: Some(value), + output: Some(output), + } + } +} + +fn test() { + Data::new(String::new(), |_| {}); +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-103250.rs b/tests/ui/borrowck/issue-103250.rs new file mode 100644 index 000000000..46565f61c --- /dev/null +++ b/tests/ui/borrowck/issue-103250.rs @@ -0,0 +1,37 @@ +// edition:2021 + +type TranslateFn = Box String>; + +pub struct DeviceCluster { + devices: Vec, +} + +impl DeviceCluster { + pub async fn do_something(&mut self) -> Result> { + let mut last_error: Box; + + for device in &mut self.devices { + match device.do_something().await { + Ok(info) => { + return Ok(info); + } + Err(e) => {} + } + } + + Err(last_error) + //~^ ERROR used binding `last_error` isn't initialized + } +} + +pub struct Device { + translate_fn: Option, +} + +impl Device { + pub async fn do_something(&mut self) -> Result> { + Ok(String::from("")) + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-103250.stderr b/tests/ui/borrowck/issue-103250.stderr new file mode 100644 index 000000000..4a2378352 --- /dev/null +++ b/tests/ui/borrowck/issue-103250.stderr @@ -0,0 +1,17 @@ +error[E0381]: used binding `last_error` isn't initialized + --> $DIR/issue-103250.rs:22:13 + | +LL | let mut last_error: Box; + | -------------- binding declared here but left uninitialized +... +LL | Err(last_error) + | ^^^^^^^^^^ `last_error` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut last_error: Box = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-103624.rs b/tests/ui/borrowck/issue-103624.rs new file mode 100644 index 000000000..f1fa95f92 --- /dev/null +++ b/tests/ui/borrowck/issue-103624.rs @@ -0,0 +1,31 @@ +// edition:2021 + +struct StructA { + b: StructB, +} + +async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { + todo!() +} + +impl StructA { + async fn foo(&self) { + let bar = self.b.bar().await; + spawn_blocking(move || { + //~^ ERROR borrowed data escapes outside of associated function + self.b; + //~^ ERROR cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure + }) + .await; + } +} + +struct StructB {} + +impl StructB { + async fn bar(&self) -> Option { + None + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr new file mode 100644 index 000000000..e6a35dd88 --- /dev/null +++ b/tests/ui/borrowck/issue-103624.stderr @@ -0,0 +1,35 @@ +error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure + --> $DIR/issue-103624.rs:16:13 + | +LL | async fn foo(&self) { + | ----- captured outer variable +LL | let bar = self.b.bar().await; +LL | spawn_blocking(move || { + | ------- captured by this `Fn` closure +LL | +LL | self.b; + | ^^^^^^ move occurs because `self.b` has type `StructB`, which does not implement the `Copy` trait + +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-103624.rs:14:9 + | +LL | async fn foo(&self) { + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` +LL | let bar = self.b.bar().await; +LL | / spawn_blocking(move || { +LL | | +LL | | self.b; +LL | | +LL | | }) + | | ^ + | | | + | |__________`self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0507, E0521. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-104639-lifetime-order.rs b/tests/ui/borrowck/issue-104639-lifetime-order.rs new file mode 100644 index 000000000..db1f8f8d5 --- /dev/null +++ b/tests/ui/borrowck/issue-104639-lifetime-order.rs @@ -0,0 +1,10 @@ +// edition:2018 +// check-pass + +#![allow(dead_code)] +async fn fail<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, {} +async fn pass<'a, 'c, 'b>(_: &'static str) where 'a: 'c, 'b: 'c, {} +async fn pass2<'a, 'b, 'c>(_: &'static str) where 'a: 'c, 'b: 'c, 'c: 'a, {} +async fn pass3<'a, 'b, 'c>(_: &'static str) where 'a: 'b, 'b: 'c, 'c: 'a, {} + +fn main() { } diff --git a/tests/ui/borrowck/issue-10876.rs b/tests/ui/borrowck/issue-10876.rs new file mode 100644 index 000000000..22eaa119f --- /dev/null +++ b/tests/ui/borrowck/issue-10876.rs @@ -0,0 +1,17 @@ +// check-pass + +enum Nat { + S(Box), + Z +} +fn test(x: &mut Nat) { + let mut p = &mut *x; + loop { + match p { + &mut Nat::Z => break, + &mut Nat::S(ref mut n) => p = &mut *n + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-11493.fixed b/tests/ui/borrowck/issue-11493.fixed new file mode 100644 index 000000000..139bd9a07 --- /dev/null +++ b/tests/ui/borrowck/issue-11493.fixed @@ -0,0 +1,9 @@ +// run-rustfix +fn id(x: T) -> T { x } + +fn main() { + let x = Some(3); + let binding = id(5); + let y = x.as_ref().unwrap_or(&binding); //~ ERROR + let _ = &y; +} diff --git a/tests/ui/borrowck/issue-11493.rs b/tests/ui/borrowck/issue-11493.rs new file mode 100644 index 000000000..cb77f89fb --- /dev/null +++ b/tests/ui/borrowck/issue-11493.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn id(x: T) -> T { x } + +fn main() { + let x = Some(3); + let y = x.as_ref().unwrap_or(&id(5)); //~ ERROR + let _ = &y; +} diff --git a/tests/ui/borrowck/issue-11493.stderr b/tests/ui/borrowck/issue-11493.stderr new file mode 100644 index 000000000..2720b09b0 --- /dev/null +++ b/tests/ui/borrowck/issue-11493.stderr @@ -0,0 +1,19 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-11493.rs:6:35 + | +LL | let y = x.as_ref().unwrap_or(&id(5)); + | ^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | let _ = &y; + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id(5); +LL ~ let y = x.as_ref().unwrap_or(&binding); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/issue-17263.rs b/tests/ui/borrowck/issue-17263.rs new file mode 100644 index 000000000..4f560b065 --- /dev/null +++ b/tests/ui/borrowck/issue-17263.rs @@ -0,0 +1,23 @@ +// check-pass + +struct Foo { a: isize, b: isize } + +fn main() { + let mut x: Box<_> = Box::new(Foo { a: 1, b: 2 }); + let (a, b) = (&mut x.a, &mut x.b); + + let mut foo: Box<_> = Box::new(Foo { a: 1, b: 2 }); + let (c, d) = (&mut foo.a, &foo.b); + + // We explicitly use the references created above to illustrate that the + // borrow checker is accepting this code *not* because of artificially + // short lifetimes, but rather because it understands that all the + // references are of disjoint parts of memory. + use_imm(d); + use_mut(c); + use_mut(b); + use_mut(a); +} + +fn use_mut(_: &mut T) { } +fn use_imm(_: &T) { } diff --git a/tests/ui/borrowck/issue-17545.rs b/tests/ui/borrowck/issue-17545.rs new file mode 100644 index 000000000..ced6fff31 --- /dev/null +++ b/tests/ui/borrowck/issue-17545.rs @@ -0,0 +1,10 @@ +#![feature(fn_traits)] + +fn id(x: T) -> T { x } + +pub fn foo<'a, F: Fn(&'a ())>(bar: F) { + bar.call(( + &id(()), //~ ERROR temporary value dropped while borrowed + )); +} +fn main() {} diff --git a/tests/ui/borrowck/issue-17545.stderr b/tests/ui/borrowck/issue-17545.stderr new file mode 100644 index 000000000..3ae7e64d2 --- /dev/null +++ b/tests/ui/borrowck/issue-17545.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-17545.rs:7:10 + | +LL | pub fn foo<'a, F: Fn(&'a ())>(bar: F) { + | -- lifetime `'a` defined here +LL | / bar.call(( +LL | | &id(()), + | | ^^^^^^ creates a temporary value which is freed while still in use +LL | | )); + | | -- temporary value is freed at the end of this statement + | |______| + | argument requires that borrow lasts for `'a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/issue-17718-static-move.rs b/tests/ui/borrowck/issue-17718-static-move.rs new file mode 100644 index 000000000..015487a06 --- /dev/null +++ b/tests/ui/borrowck/issue-17718-static-move.rs @@ -0,0 +1,7 @@ +struct Foo; +const INIT: Foo = Foo; +static FOO: Foo = INIT; + +fn main() { + let _a = FOO; //~ ERROR: cannot move out of static item +} diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr new file mode 100644 index 000000000..65aea5b18 --- /dev/null +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -0,0 +1,14 @@ +error[E0507]: cannot move out of static item `FOO` + --> $DIR/issue-17718-static-move.rs:6:14 + | +LL | let _a = FOO; + | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let _a = &FOO; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-20801.rs b/tests/ui/borrowck/issue-20801.rs new file mode 100644 index 000000000..c3f136f28 --- /dev/null +++ b/tests/ui/borrowck/issue-20801.rs @@ -0,0 +1,37 @@ +// We used to ICE when moving out of a `*mut T` or `*const T`. + +struct T(u8); + +static mut GLOBAL_MUT_T: T = T(0); + +static GLOBAL_T: T = T(0); + +fn imm_ref() -> &'static T { + unsafe { &GLOBAL_T } +} + +fn mut_ref() -> &'static mut T { + unsafe { &mut GLOBAL_MUT_T } +} + +fn mut_ptr() -> *mut T { + unsafe { core::ptr::null_mut() } +} + +fn const_ptr() -> *const T { + unsafe { core::ptr::null() } +} + +pub fn main() { + let a = unsafe { *mut_ref() }; + //~^ ERROR cannot move out of a mutable reference + + let b = unsafe { *imm_ref() }; + //~^ ERROR cannot move out of a shared reference + + let c = unsafe { *mut_ptr() }; + //~^ ERROR cannot move out of a raw pointer + + let d = unsafe { *const_ptr() }; + //~^ ERROR cannot move out of a raw pointer +} diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr new file mode 100644 index 000000000..215bf0100 --- /dev/null +++ b/tests/ui/borrowck/issue-20801.stderr @@ -0,0 +1,51 @@ +error[E0507]: cannot move out of a mutable reference + --> $DIR/issue-20801.rs:26:22 + | +LL | let a = unsafe { *mut_ref() }; + | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let a = unsafe { *mut_ref() }; +LL + let a = unsafe { mut_ref() }; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/issue-20801.rs:29:22 + | +LL | let b = unsafe { *imm_ref() }; + | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let b = unsafe { *imm_ref() }; +LL + let b = unsafe { imm_ref() }; + | + +error[E0507]: cannot move out of a raw pointer + --> $DIR/issue-20801.rs:32:22 + | +LL | let c = unsafe { *mut_ptr() }; + | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let c = unsafe { *mut_ptr() }; +LL + let c = unsafe { mut_ptr() }; + | + +error[E0507]: cannot move out of a raw pointer + --> $DIR/issue-20801.rs:35:22 + | +LL | let d = unsafe { *const_ptr() }; + | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let d = unsafe { *const_ptr() }; +LL + let d = unsafe { const_ptr() }; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs b/tests/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs new file mode 100644 index 000000000..d45aaa843 --- /dev/null +++ b/tests/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs @@ -0,0 +1,30 @@ +// run-pass +// This is largely checking that we now accept code where temp values +// are borrowing from the input parameters (the `foo` case below). +// +// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs +// +// (The `foo2` case is just for parity with the above test, which +// shows what happens when you move the `y`-binding to the inside of +// the inner block.) + +use std::cell::RefCell; + +fn foo(x: RefCell) -> String { + x.borrow().clone() +} + +fn foo2(x: RefCell) -> String { + let y = x; + let ret = { + y.borrow().clone() + }; + ret +} + +pub fn main() { + let r = RefCell::new(format!("data")); + assert_eq!(foo(r), "data"); + let r = RefCell::new(format!("data")); + assert_eq!(foo2(r), "data"); +} diff --git a/tests/ui/borrowck/issue-24267-flow-exit.rs b/tests/ui/borrowck/issue-24267-flow-exit.rs new file mode 100644 index 000000000..c419c5840 --- /dev/null +++ b/tests/ui/borrowck/issue-24267-flow-exit.rs @@ -0,0 +1,19 @@ +// Ensure that we reject code when a nonlocal exit (`break`, +// `continue`) causes us to pop over a needed assignment. + +pub fn main() { + foo1(); + foo2(); +} + +pub fn foo1() { + let x: i32; + loop { x = break; } + println!("{}", x); //~ ERROR E0381 +} + +pub fn foo2() { + let x: i32; + for _ in 0..10 { x = continue; } + println!("{}", x); //~ ERROR E0381 +} diff --git a/tests/ui/borrowck/issue-24267-flow-exit.stderr b/tests/ui/borrowck/issue-24267-flow-exit.stderr new file mode 100644 index 000000000..58d1c8c0f --- /dev/null +++ b/tests/ui/borrowck/issue-24267-flow-exit.stderr @@ -0,0 +1,33 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/issue-24267-flow-exit.rs:12:20 + | +LL | let x: i32; + | - binding declared here but left uninitialized +LL | loop { x = break; } +LL | println!("{}", x); + | ^ `x` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/issue-24267-flow-exit.rs:18:20 + | +LL | let x: i32; + | - binding declared here but left uninitialized +LL | for _ in 0..10 { x = continue; } +LL | println!("{}", x); + | ^ `x` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-25793.rs b/tests/ui/borrowck/issue-25793.rs new file mode 100644 index 000000000..6c8dacc22 --- /dev/null +++ b/tests/ui/borrowck/issue-25793.rs @@ -0,0 +1,26 @@ +#![feature(rustc_attrs)] +macro_rules! width( + ($this:expr) => { + $this.width.unwrap() + //~^ ERROR cannot use `self.width` because it was mutably borrowed + } +); + +struct HasInfo { + width: Option +} + +impl HasInfo { + fn get_size(&mut self, n: usize) -> usize { + n + } + + fn get_other(&mut self) -> usize { + let r = &mut *self; + r.get_size(width!(self)) + } + // Above is like `self.get_size(width!(self))`, but it + // deliberately avoids NLL's two phase borrow feature. +} + +fn main() { } diff --git a/tests/ui/borrowck/issue-25793.stderr b/tests/ui/borrowck/issue-25793.stderr new file mode 100644 index 000000000..da3412f11 --- /dev/null +++ b/tests/ui/borrowck/issue-25793.stderr @@ -0,0 +1,18 @@ +error[E0503]: cannot use `self.width` because it was mutably borrowed + --> $DIR/issue-25793.rs:4:9 + | +LL | $this.width.unwrap() + | ^^^^^^^^^^^ use of borrowed `*self` +... +LL | let r = &mut *self; + | ---------- borrow of `*self` occurs here +LL | r.get_size(width!(self)) + | -------- ------------ in this macro invocation + | | + | borrow later used by call + | + = note: this error originates in the macro `width` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/issue-28934.rs b/tests/ui/borrowck/issue-28934.rs new file mode 100644 index 000000000..1e48878f6 --- /dev/null +++ b/tests/ui/borrowck/issue-28934.rs @@ -0,0 +1,25 @@ +// Regression test: issue had to do with "givens" in region inference, +// which were not being considered during the contraction phase. + +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +struct Parser<'i: 't, 't>(&'i u8, &'t u8); + +impl<'i, 't> Parser<'i, 't> { + fn parse_nested_block(&mut self, parse: F) -> Result + where for<'tt> F: FnOnce(&mut Parser<'i, 'tt>) -> T + { + panic!() + } + + fn expect_exhausted(&mut self) -> Result<(), ()> { + Ok(()) + } +} + +fn main() { + let x = 0u8; + Parser(&x, &x).parse_nested_block(|input| input.expect_exhausted()).unwrap(); +} diff --git a/tests/ui/borrowck/issue-29166.rs b/tests/ui/borrowck/issue-29166.rs new file mode 100644 index 000000000..ca819ba39 --- /dev/null +++ b/tests/ui/borrowck/issue-29166.rs @@ -0,0 +1,21 @@ +// run-pass +// This test ensures that vec.into_iter does not overconstrain element lifetime. + +pub fn main() { + original_report(); + revision_1(); + revision_2(); +} + +fn original_report() { + drop(vec![&()].into_iter()) +} + +fn revision_1() { + // below is what above `vec!` expands into at time of this writing. + drop(<[_]>::into_vec(::std::boxed::Box::new([&()])).into_iter()) +} + +fn revision_2() { + drop((match (Vec::new(), &()) { (mut v, b) => { v.push(b); v } }).into_iter()) +} diff --git a/tests/ui/borrowck/issue-31287-drop-in-guard.rs b/tests/ui/borrowck/issue-31287-drop-in-guard.rs new file mode 100644 index 000000000..5b824adc6 --- /dev/null +++ b/tests/ui/borrowck/issue-31287-drop-in-guard.rs @@ -0,0 +1,15 @@ +#![feature(if_let_guard)] + +fn main() { + let a = Some("...".to_owned()); + let b = match a { + Some(_) if { drop(a); false } => None, + x => x, //~ ERROR use of moved value: `a` + }; + + let a = Some("...".to_owned()); + let b = match a { + Some(_) if let Some(()) = { drop(a); None } => None, + x => x, //~ ERROR use of moved value: `a` + }; +} diff --git a/tests/ui/borrowck/issue-31287-drop-in-guard.stderr b/tests/ui/borrowck/issue-31287-drop-in-guard.stderr new file mode 100644 index 000000000..18f371c20 --- /dev/null +++ b/tests/ui/borrowck/issue-31287-drop-in-guard.stderr @@ -0,0 +1,35 @@ +error[E0382]: use of moved value: `a` + --> $DIR/issue-31287-drop-in-guard.rs:7:9 + | +LL | let a = Some("...".to_owned()); + | - move occurs because `a` has type `Option`, which does not implement the `Copy` trait +LL | let b = match a { +LL | Some(_) if { drop(a); false } => None, + | - value moved here +LL | x => x, + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if { drop(a.clone()); false } => None, + | ++++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/issue-31287-drop-in-guard.rs:13:9 + | +LL | let a = Some("...".to_owned()); + | - move occurs because `a` has type `Option`, which does not implement the `Copy` trait +LL | let b = match a { +LL | Some(_) if let Some(()) = { drop(a); None } => None, + | - value moved here +LL | x => x, + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if let Some(()) = { drop(a.clone()); None } => None, + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-33819.rs b/tests/ui/borrowck/issue-33819.rs new file mode 100644 index 000000000..fff5015cd --- /dev/null +++ b/tests/ui/borrowck/issue-33819.rs @@ -0,0 +1,9 @@ +fn main() { + let mut op = Some(2); + match op { + Some(ref v) => { let a = &mut v; }, + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + //~| HELP try removing `&mut` here + None => {}, + } +} diff --git a/tests/ui/borrowck/issue-33819.stderr b/tests/ui/borrowck/issue-33819.stderr new file mode 100644 index 000000000..f77fdbf2b --- /dev/null +++ b/tests/ui/borrowck/issue-33819.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/issue-33819.rs:4:34 + | +LL | Some(ref v) => { let a = &mut v; }, + | ^^^^^^ + | | + | cannot borrow as mutable + | help: try removing `&mut` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-36082.fixed b/tests/ui/borrowck/issue-36082.fixed new file mode 100644 index 000000000..8fc963a85 --- /dev/null +++ b/tests/ui/borrowck/issue-36082.fixed @@ -0,0 +1,17 @@ +// run-rustfix +use std::cell::RefCell; + +fn main() { + let mut r = 0; + let s = 0; + let x = RefCell::new((&mut r,s)); + + let binding = x.borrow(); + let val: &_ = binding.0; + //~^ ERROR temporary value dropped while borrowed [E0716] + //~| NOTE temporary value is freed at the end of this statement + //~| NOTE creates a temporary value which is freed while still in use + //~| HELP consider using a `let` binding to create a longer lived value + println!("{}", val); + //~^ borrow later used here +} diff --git a/tests/ui/borrowck/issue-36082.rs b/tests/ui/borrowck/issue-36082.rs new file mode 100644 index 000000000..20f66b4d4 --- /dev/null +++ b/tests/ui/borrowck/issue-36082.rs @@ -0,0 +1,16 @@ +// run-rustfix +use std::cell::RefCell; + +fn main() { + let mut r = 0; + let s = 0; + let x = RefCell::new((&mut r,s)); + + let val: &_ = x.borrow().0; + //~^ ERROR temporary value dropped while borrowed [E0716] + //~| NOTE temporary value is freed at the end of this statement + //~| NOTE creates a temporary value which is freed while still in use + //~| HELP consider using a `let` binding to create a longer lived value + println!("{}", val); + //~^ borrow later used here +} diff --git a/tests/ui/borrowck/issue-36082.stderr b/tests/ui/borrowck/issue-36082.stderr new file mode 100644 index 000000000..a6357f818 --- /dev/null +++ b/tests/ui/borrowck/issue-36082.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-36082.rs:9:19 + | +LL | let val: &_ = x.borrow().0; + | ^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | println!("{}", val); + | --- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = x.borrow(); +LL ~ let val: &_ = binding.0; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/borrowck/issue-41962.rs b/tests/ui/borrowck/issue-41962.rs new file mode 100644 index 000000000..38a01b138 --- /dev/null +++ b/tests/ui/borrowck/issue-41962.rs @@ -0,0 +1,9 @@ +pub fn main(){ + let maybe = Some(vec![true, true]); + + loop { + if let Some(thing) = maybe { + } + //~^^ ERROR use of moved value [E0382] + } +} diff --git a/tests/ui/borrowck/issue-41962.stderr b/tests/ui/borrowck/issue-41962.stderr new file mode 100644 index 000000000..716cc9d0c --- /dev/null +++ b/tests/ui/borrowck/issue-41962.stderr @@ -0,0 +1,15 @@ +error[E0382]: use of moved value + --> $DIR/issue-41962.rs:5:21 + | +LL | if let Some(thing) = maybe { + | ^^^^^ value moved here, in previous iteration of loop + | + = note: move occurs because value has type `Vec`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let Some(ref thing) = maybe { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-42344.rs b/tests/ui/borrowck/issue-42344.rs new file mode 100644 index 000000000..a7636edf2 --- /dev/null +++ b/tests/ui/borrowck/issue-42344.rs @@ -0,0 +1,8 @@ +static TAB: [&mut [u8]; 0] = []; + +pub unsafe fn test() { + TAB[0].iter_mut(); + //~^ ERROR cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable static item [E0596] +} + +pub fn main() {} diff --git a/tests/ui/borrowck/issue-42344.stderr b/tests/ui/borrowck/issue-42344.stderr new file mode 100644 index 000000000..29b4c8c38 --- /dev/null +++ b/tests/ui/borrowck/issue-42344.stderr @@ -0,0 +1,9 @@ +error[E0596]: cannot borrow `*TAB[_]` as mutable, as `TAB` is an immutable static item + --> $DIR/issue-42344.rs:4:5 + | +LL | TAB[0].iter_mut(); + | ^^^^^^^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-45199.rs b/tests/ui/borrowck/issue-45199.rs new file mode 100644 index 000000000..ded46e56e --- /dev/null +++ b/tests/ui/borrowck/issue-45199.rs @@ -0,0 +1,24 @@ +fn test_drop_replace() { + let b: Box; + //~^ HELP consider making this binding mutable + //~| SUGGESTION mut b + b = Box::new(1); //~ NOTE first assignment + b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b` + //~| NOTE cannot assign twice to immutable +} + +fn test_call() { + let b = Box::new(1); //~ NOTE first assignment + //~| HELP consider making this binding mutable + //~| SUGGESTION mut b + b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b` + //~| NOTE cannot assign twice to immutable +} + +fn test_args(b: Box) { //~ HELP consider making this binding mutable + //~| SUGGESTION mut b + b = Box::new(2); //~ ERROR cannot assign to immutable argument `b` + //~| NOTE cannot assign to immutable argument +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-45199.stderr b/tests/ui/borrowck/issue-45199.stderr new file mode 100644 index 000000000..47aa30908 --- /dev/null +++ b/tests/ui/borrowck/issue-45199.stderr @@ -0,0 +1,35 @@ +error[E0384]: cannot assign twice to immutable variable `b` + --> $DIR/issue-45199.rs:6:5 + | +LL | let b: Box; + | - help: consider making this binding mutable: `mut b` +... +LL | b = Box::new(1); + | - first assignment to `b` +LL | b = Box::new(2); + | ^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `b` + --> $DIR/issue-45199.rs:14:5 + | +LL | let b = Box::new(1); + | - + | | + | first assignment to `b` + | help: consider making this binding mutable: `mut b` +... +LL | b = Box::new(2); + | ^ cannot assign twice to immutable variable + +error[E0384]: cannot assign to immutable argument `b` + --> $DIR/issue-45199.rs:20:5 + | +LL | fn test_args(b: Box) { + | - help: consider making this binding mutable: `mut b` +LL | +LL | b = Box::new(2); + | ^ cannot assign to immutable argument + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/borrowck/issue-45983.rs b/tests/ui/borrowck/issue-45983.rs new file mode 100644 index 000000000..6784f6f86 --- /dev/null +++ b/tests/ui/borrowck/issue-45983.rs @@ -0,0 +1,12 @@ +// As documented in Issue #45983, this test is evaluating the quality +// of our diagnostics on erroneous code using higher-ranked closures. + +fn give_any FnOnce(&'r ())>(f: F) { + f(&()); +} + +fn main() { + let mut x = None; + give_any(|y| x = Some(y)); + //~^ ERROR borrowed data escapes outside of closure +} diff --git a/tests/ui/borrowck/issue-45983.stderr b/tests/ui/borrowck/issue-45983.stderr new file mode 100644 index 000000000..feb098c59 --- /dev/null +++ b/tests/ui/borrowck/issue-45983.stderr @@ -0,0 +1,13 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/issue-45983.rs:10:18 + | +LL | let mut x = None; + | ----- `x` declared here, outside of the closure body +LL | give_any(|y| x = Some(y)); + | - ^^^^^^^^^^^ `y` escapes the closure body here + | | + | `y` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/issue-46095.rs b/tests/ui/borrowck/issue-46095.rs new file mode 100644 index 000000000..59ddb60c9 --- /dev/null +++ b/tests/ui/borrowck/issue-46095.rs @@ -0,0 +1,30 @@ +// run-pass +struct A; + +impl A { + fn take_mutably(&mut self) {} +} + +fn identity(t: T) -> T { + t +} + +// Issue 46095 +// Built-in indexing should be used even when the index is not +// trivially an integer +// Overloaded indexing would cause wrapped to be borrowed mutably + +fn main() { + let mut a1 = A; + let mut a2 = A; + + let wrapped = [&mut a1, &mut a2]; + + { + wrapped[0 + 1 - 1].take_mutably(); + } + + { + wrapped[identity(0)].take_mutably(); + } +} diff --git a/tests/ui/borrowck/issue-46471.rs b/tests/ui/borrowck/issue-46471.rs new file mode 100644 index 000000000..8922005d2 --- /dev/null +++ b/tests/ui/borrowck/issue-46471.rs @@ -0,0 +1,7 @@ +fn foo() -> &'static u32 { + let x = 0; + &x + //~^ ERROR cannot return reference to local variable `x` [E0515] +} + +fn main() { } diff --git a/tests/ui/borrowck/issue-46471.stderr b/tests/ui/borrowck/issue-46471.stderr new file mode 100644 index 000000000..935414c1f --- /dev/null +++ b/tests/ui/borrowck/issue-46471.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-46471.rs:3:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/issue-47215-ice-from-drop-elab.rs b/tests/ui/borrowck/issue-47215-ice-from-drop-elab.rs new file mode 100644 index 000000000..e95a6b7c8 --- /dev/null +++ b/tests/ui/borrowck/issue-47215-ice-from-drop-elab.rs @@ -0,0 +1,20 @@ +// rust-lang/rust#47215: at one time, the compiler categorized +// thread-local statics as a temporary rvalue, as a way to enforce +// that they are only valid for a given lifetime. +// +// The problem with this is that you cannot move out of static items, +// but you *can* move temporary rvalues. I.e., the categorization +// above only solves half of the problem presented by thread-local +// statics. + +#![feature(thread_local)] + +#[thread_local] +static mut X: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0); + +fn main() { + unsafe { + let mut x = X; //~ ERROR cannot move out of static item `X` [E0507] + let _y = x.get_mut(); + } +} diff --git a/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr b/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr new file mode 100644 index 000000000..8d4918867 --- /dev/null +++ b/tests/ui/borrowck/issue-47215-ice-from-drop-elab.stderr @@ -0,0 +1,14 @@ +error[E0507]: cannot move out of static item `X` + --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21 + | +LL | let mut x = X; + | ^ move occurs because `X` has type `AtomicUsize`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let mut x = &X; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-51117.rs b/tests/ui/borrowck/issue-51117.rs new file mode 100644 index 000000000..e4664e4f3 --- /dev/null +++ b/tests/ui/borrowck/issue-51117.rs @@ -0,0 +1,15 @@ +// Regression test for #51117 in borrowck interaction with match +// default bindings. The borrow of `*bar` created by `baz` was failing +// to register as a conflict with `bar.take()`. + +fn main() { + let mut foo = Some("foo".to_string()); + let bar = &mut foo; + match bar { + Some(baz) => { + bar.take(); //~ ERROR cannot borrow + drop(baz); + }, + None => unreachable!(), + } +} diff --git a/tests/ui/borrowck/issue-51117.stderr b/tests/ui/borrowck/issue-51117.stderr new file mode 100644 index 000000000..ef1a16ea9 --- /dev/null +++ b/tests/ui/borrowck/issue-51117.stderr @@ -0,0 +1,13 @@ +error[E0499]: cannot borrow `*bar` as mutable more than once at a time + --> $DIR/issue-51117.rs:10:13 + | +LL | Some(baz) => { + | --- first mutable borrow occurs here +LL | bar.take(); + | ^^^^^^^^^^ second mutable borrow occurs here +LL | drop(baz); + | --- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/issue-51301.rs b/tests/ui/borrowck/issue-51301.rs new file mode 100644 index 000000000..7e0a5190f --- /dev/null +++ b/tests/ui/borrowck/issue-51301.rs @@ -0,0 +1,35 @@ +use std::any::TypeId; +use std::collections::HashMap; +use std::hash::Hash; + +trait State { + type EventType; + fn get_type_id_of_state(&self) -> TypeId; +} + +struct StateMachine { + current_state: Box>, + transition_table: + HashMap Box>>>, +} + +impl StateMachine { + fn inner_process_event(&mut self, event: EventType) -> Result<(), i8> { + let new_state_creation_function = self + .transition_table + .iter() + .find(|(&event_typeid, _)| event_typeid == self.current_state.get_type_id_of_state()) + .ok_or(1)? + .1 + .iter() + .find(|(&event_type, _)| event == event_type) + //~^ ERROR cannot move out of a shared reference + .ok_or(2)? + .1; + + self.current_state = new_state_creation_function(); + Ok(()) + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-51301.stderr b/tests/ui/borrowck/issue-51301.stderr new file mode 100644 index 000000000..6ec920cb8 --- /dev/null +++ b/tests/ui/borrowck/issue-51301.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/issue-51301.rs:25:20 + | +LL | .find(|(&event_type, _)| event == event_type) + | ^^----------^^^^ + | | + | data moved here + | move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | .find(|(&ref event_type, _)| event == event_type) + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs b/tests/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs new file mode 100644 index 000000000..7d5acb957 --- /dev/null +++ b/tests/ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs @@ -0,0 +1,21 @@ +// We used to ICE if you had a single match arm with multiple +// candidate patterns with `ref mut` identifiers used in the arm's +// guard. +// +// Also, this test expands on the original bug's example by actually +// trying to double check that we are matching against the right part +// of the input data based on which candidate pattern actually fired. + +// run-pass + +fn foo(x: &mut Result<(u32, u32), (u32, u32)>) -> u32 { + match *x { + Ok((ref mut v, _)) | Err((_, ref mut v)) if *v > 0 => { *v } + _ => { 0 } + } +} + +fn main() { + assert_eq!(foo(&mut Ok((3, 4))), 3); + assert_eq!(foo(&mut Err((3, 4))), 4); +} diff --git a/tests/ui/borrowck/issue-51415.fixed b/tests/ui/borrowck/issue-51415.fixed new file mode 100644 index 000000000..92943f6c9 --- /dev/null +++ b/tests/ui/borrowck/issue-51415.fixed @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #51415: match default bindings were failing to +// see the "move out" implied by `&s` below. + +fn main() { + let a = vec![String::from("a")]; + let opt = a.iter().enumerate().find(|(_, &ref s)| { + //~^ ERROR cannot move out + *s == String::from("d") + }).map(|(i, _)| i); + println!("{:?}", opt); +} diff --git a/tests/ui/borrowck/issue-51415.rs b/tests/ui/borrowck/issue-51415.rs new file mode 100644 index 000000000..56ed57a61 --- /dev/null +++ b/tests/ui/borrowck/issue-51415.rs @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #51415: match default bindings were failing to +// see the "move out" implied by `&s` below. + +fn main() { + let a = vec![String::from("a")]; + let opt = a.iter().enumerate().find(|(_, &s)| { + //~^ ERROR cannot move out + *s == String::from("d") + }).map(|(i, _)| i); + println!("{:?}", opt); +} diff --git a/tests/ui/borrowck/issue-51415.stderr b/tests/ui/borrowck/issue-51415.stderr new file mode 100644 index 000000000..0d486b455 --- /dev/null +++ b/tests/ui/borrowck/issue-51415.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/issue-51415.rs:7:42 + | +LL | let opt = a.iter().enumerate().find(|(_, &s)| { + | ^^^^^-^ + | | + | data moved here + | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let opt = a.iter().enumerate().find(|(_, &ref s)| { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-52713-bug.rs b/tests/ui/borrowck/issue-52713-bug.rs new file mode 100644 index 000000000..671e83dfa --- /dev/null +++ b/tests/ui/borrowck/issue-52713-bug.rs @@ -0,0 +1,17 @@ +// Regression test for a bug in #52713: this was an optimization for +// computing liveness that wound up accidentally causing the program +// below to be accepted. + +fn foo<'a>(x: &'a mut u32) -> u32 { + let mut x = 22; + let y = &x; + if false { + return x; + } + + x += 1; //~ ERROR + println!("{}", y); + return 0; +} + +fn main() { } diff --git a/tests/ui/borrowck/issue-52713-bug.stderr b/tests/ui/borrowck/issue-52713-bug.stderr new file mode 100644 index 000000000..4abb6fb2c --- /dev/null +++ b/tests/ui/borrowck/issue-52713-bug.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/issue-52713-bug.rs:12:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +... +LL | x += 1; + | ^^^^^^ assignment to borrowed `x` occurs here +LL | println!("{}", y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs b/tests/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs new file mode 100644 index 000000000..fc8a07554 --- /dev/null +++ b/tests/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs @@ -0,0 +1,21 @@ +// This is a regression test for #52967, where we discovered that in +// the initial deployment of NLL for the 2018 edition, I forgot to +// turn on two-phase-borrows in addition to `-Z borrowck=migrate`. + +// revisions: edition2015 edition2018 +//[edition2018]edition:2018 + +// run-pass + +fn the_bug() { + let mut stuff = ("left", "right"); + match stuff { + (ref mut left, _) if *left == "left" => { *left = "new left"; } + _ => {} + } + assert_eq!(stuff, ("new left", "right")); +} + +fn main() { + the_bug(); +} diff --git a/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs new file mode 100644 index 000000000..f1fd1b507 --- /dev/null +++ b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs @@ -0,0 +1,7 @@ +fn main() { + let f = move || {}; + let _action = move || { + || f() // The `nested` closure + //~^ ERROR lifetime may not live long enough + }; +} diff --git a/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr new file mode 100644 index 000000000..f0b574846 --- /dev/null +++ b/tests/ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.stderr @@ -0,0 +1,19 @@ +error: lifetime may not live long enough + --> $DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9 + | +LL | let _action = move || { + | ------- + | | | + | | return type of closure `[closure@$DIR/issue-53432-nested-closure-outlives-borrowed-value.rs:4:9: 4:11]` contains a lifetime `'2` + | lifetime `'1` represents this closure's body +LL | || f() // The `nested` closure + | ^^^^^^ returning this value requires that `'1` must outlive `'2` + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure +help: consider adding 'move' keyword before the nested closure + | +LL | move || f() // The `nested` closure + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs new file mode 100644 index 000000000..205ea10c9 --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs @@ -0,0 +1,33 @@ +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let mut t: Tuple; + t.0 = S(1); + //~^ ERROR E0381 + t.1 = 2; + println!("{:?} {:?}", t.0, t.1); + } + + { + let mut u: Tpair; + u.0 = S(1); + //~^ ERROR E0381 + u.1 = 2; + println!("{:?} {:?}", u.0, u.1); + } + + { + let mut v: Spair; + v.x = S(1); + //~^ ERROR E0381 + v.y = 2; + println!("{:?} {:?}", v.x, v.y); + } +} diff --git a/tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr new file mode 100644 index 000000000..2a0eba396 --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr @@ -0,0 +1,33 @@ +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9 + | +LL | let mut t: Tuple; + | ----- binding declared here but left uninitialized +LL | t.0 = S(1); + | ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `u` isn't fully initialized + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9 + | +LL | let mut u: Tpair; + | ----- binding declared here but left uninitialized +LL | u.0 = S(1); + | ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `v` isn't fully initialized + --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9 + | +LL | let mut v: Spair; + | ----- binding declared here but left uninitialized +LL | v.x = S(1); + | ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs new file mode 100644 index 000000000..f7fb2fd4d --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs @@ -0,0 +1,36 @@ +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let mut t: Tuple = (S(0), 0); + drop(t); + t.0 = S(1); + //~^ ERROR assign to part of moved value + t.1 = 2; + println!("{:?} {:?}", t.0, t.1); + } + + { + let mut u: Tpair = Tpair(S(0), 0); + drop(u); + u.0 = S(1); + //~^ ERROR assign to part of moved value + u.1 = 2; + println!("{:?} {:?}", u.0, u.1); + } + + { + let mut v: Spair = Spair { x: S(0), y: 0 }; + drop(v); + v.x = S(1); + //~^ ERROR assign to part of moved value + v.y = 2; + println!("{:?} {:?}", v.x, v.y); + } +} diff --git a/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.stderr b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.stderr new file mode 100644 index 000000000..b188766e2 --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.stderr @@ -0,0 +1,33 @@ +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:13:9 + | +LL | let mut t: Tuple = (S(0), 0); + | ----- move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait +LL | drop(t); + | - value moved here +LL | t.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + +error[E0382]: assign to part of moved value: `u` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:22:9 + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | ----- move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait +LL | drop(u); + | - value moved here +LL | u.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + +error[E0382]: assign to part of moved value: `v` + --> $DIR/issue-54499-field-mutation-of-moved-out-with-mut.rs:31:9 + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | ----- move occurs because `v` has type `Spair`, which does not implement the `Copy` trait +LL | drop(v); + | - value moved here +LL | v.x = S(1); + | ^^^^^^^^^^ value partially assigned here after move + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs new file mode 100644 index 000000000..498ca01e9 --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.rs @@ -0,0 +1,42 @@ +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let t: Tuple = (S(0), 0); + drop(t); + t.0 = S(1); + //~^ ERROR assign to part of moved value: `t` [E0382] + //~| ERROR cannot assign to `t.0`, as `t` is not declared as mutable [E0594] + t.1 = 2; + //~^ ERROR cannot assign to `t.1`, as `t` is not declared as mutable [E0594] + println!("{:?} {:?}", t.0, t.1); + } + + { + let u: Tpair = Tpair(S(0), 0); + drop(u); + u.0 = S(1); + //~^ ERROR assign to part of moved value: `u` [E0382] + //~| ERROR cannot assign to `u.0`, as `u` is not declared as mutable [E0594] + u.1 = 2; + //~^ ERROR cannot assign to `u.1`, as `u` is not declared as mutable [E0594] + println!("{:?} {:?}", u.0, u.1); + } + + { + let v: Spair = Spair { x: S(0), y: 0 }; + drop(v); + v.x = S(1); + //~^ ERROR assign to part of moved value: `v` [E0382] + //~| ERROR cannot assign to `v.x`, as `v` is not declared as mutable [E0594] + v.y = 2; + //~^ ERROR cannot assign to `v.y`, as `v` is not declared as mutable [E0594] + println!("{:?} {:?}", v.x, v.y); + } +} diff --git a/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr new file mode 100644 index 000000000..774b6cf0e --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr @@ -0,0 +1,100 @@ +error[E0594]: cannot assign to `t.0`, as `t` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:13:9 + | +LL | t.0 = S(1); + | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut t: Tuple = (S(0), 0); + | +++ + +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:13:9 + | +LL | let t: Tuple = (S(0), 0); + | - move occurs because `t` has type `(S, i32)`, which does not implement the `Copy` trait +LL | drop(t); + | - value moved here +LL | t.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + +error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:16:9 + | +LL | t.1 = 2; + | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut t: Tuple = (S(0), 0); + | +++ + +error[E0594]: cannot assign to `u.0`, as `u` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:24:9 + | +LL | u.0 = S(1); + | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | +++ + +error[E0382]: assign to part of moved value: `u` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:24:9 + | +LL | let u: Tpair = Tpair(S(0), 0); + | - move occurs because `u` has type `Tpair`, which does not implement the `Copy` trait +LL | drop(u); + | - value moved here +LL | u.0 = S(1); + | ^^^^^^^^^^ value partially assigned here after move + +error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9 + | +LL | u.1 = 2; + | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | +++ + +error[E0594]: cannot assign to `v.x`, as `v` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:35:9 + | +LL | v.x = S(1); + | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | +++ + +error[E0382]: assign to part of moved value: `v` + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:35:9 + | +LL | let v: Spair = Spair { x: S(0), y: 0 }; + | - move occurs because `v` has type `Spair`, which does not implement the `Copy` trait +LL | drop(v); + | - value moved here +LL | v.x = S(1); + | ^^^^^^^^^^ value partially assigned here after move + +error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable + --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 + | +LL | v.y = 2; + | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | +++ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0382, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/tests/ui/borrowck/issue-54499-field-mutation-of-never-init.rs new file mode 100644 index 000000000..50d0c40fd --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-of-never-init.rs @@ -0,0 +1,33 @@ +#![warn(unused)] +#[derive(Debug)] +struct S(i32); + +type Tuple = (S, i32); +struct Tpair(S, i32); +struct Spair { x: S, y: i32 } + +fn main() { + { + let t: Tuple; + t.0 = S(1); + //~^ ERROR E0381 + t.1 = 2; + println!("{:?} {:?}", t.0, t.1); + } + + { + let u: Tpair; + u.0 = S(1); + //~^ ERROR E0381 + u.1 = 2; + println!("{:?} {:?}", u.0, u.1); + } + + { + let v: Spair; + v.x = S(1); + //~^ ERROR E0381 + v.y = 2; + println!("{:?} {:?}", v.x, v.y); + } +} diff --git a/tests/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/tests/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr new file mode 100644 index 000000000..67a625830 --- /dev/null +++ b/tests/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr @@ -0,0 +1,33 @@ +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9 + | +LL | let t: Tuple; + | - binding declared here but left uninitialized +LL | t.0 = S(1); + | ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `u` isn't fully initialized + --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9 + | +LL | let u: Tpair; + | - binding declared here but left uninitialized +LL | u.0 = S(1); + | ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `v` isn't fully initialized + --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9 + | +LL | let v: Spair; + | - binding declared here but left uninitialized +LL | v.x = S(1); + | ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs b/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs new file mode 100644 index 000000000..3e46ee6f0 --- /dev/null +++ b/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs @@ -0,0 +1,20 @@ +#![allow(dead_code)] + +#[derive(Debug)] +struct Value; +impl Value { + fn as_array(&self) -> Option<&Vec> { + None + } +} + +fn foo(val: Value) { + let _reviewers_original: Vec = match val.as_array() { + Some(array) => { + *array //~ ERROR cannot move out of `*array` + } + None => vec![] + }; +} + +fn main() { } diff --git a/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr b/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr new file mode 100644 index 000000000..99c63e4db --- /dev/null +++ b/tests/ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of `*array` which is behind a shared reference + --> $DIR/issue-54597-reject-move-out-of-borrow-via-pat.rs:14:13 + | +LL | *array + | ^^^^^^ move occurs because `*array` has type `Vec`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - *array +LL + array + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs new file mode 100644 index 000000000..b3cce1b3a --- /dev/null +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs @@ -0,0 +1,55 @@ +// rust-lang/rust#55492: errors detected during MIR-borrowck's +// analysis of a closure body may only be caught when AST-borrowck +// looks at some parent. + +// transcribed from borrowck-closures-unique.rs +mod borrowck_closures_unique { + pub fn e(x: &'static mut isize) { + static mut Y: isize = 3; + let mut c1 = |y: &'static mut isize| x = y; + //~^ ERROR is not declared as mutable + unsafe { c1(&mut Y); } + } +} + +mod borrowck_closures_unique_grandparent { + pub fn ee(x: &'static mut isize) { + static mut Z: isize = 3; + let mut c1 = |z: &'static mut isize| { + let mut c2 = |y: &'static mut isize| x = y; + //~^ ERROR is not declared as mutable + c2(z); + }; + unsafe { c1(&mut Z); } + } +} + +// adapted from mutability_errors.rs +mod mutability_errors { + pub fn capture_assign_whole(x: (i32,)) { + || { x = (1,); }; + //~^ ERROR is not declared as mutable + } + pub fn capture_assign_part(x: (i32,)) { + || { x.0 = 1; }; + //~^ ERROR is not declared as mutable + } + pub fn capture_reborrow_whole(x: (i32,)) { + || { &mut x; }; + //~^ ERROR is not declared as mutable + } + pub fn capture_reborrow_part(x: (i32,)) { + || { &mut x.0; }; + //~^ ERROR is not declared as mutable + } +} + +fn main() { + static mut X: isize = 2; + unsafe { borrowck_closures_unique::e(&mut X); } + + mutability_errors::capture_assign_whole((1000,)); + mutability_errors::capture_assign_part((2000,)); + mutability_errors::capture_reborrow_whole((3000,)); + mutability_errors::capture_reborrow_part((4000,)); +} diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr new file mode 100644 index 000000000..4c299cdc4 --- /dev/null +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr @@ -0,0 +1,54 @@ +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46 + | +LL | pub fn e(x: &'static mut isize) { + | - help: consider changing this to be mutable: `mut x` +LL | static mut Y: isize = 3; +LL | let mut c1 = |y: &'static mut isize| x = y; + | ^^^^^ cannot assign + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:19:50 + | +LL | pub fn ee(x: &'static mut isize) { + | - help: consider changing this to be mutable: `mut x` +... +LL | let mut c2 = |y: &'static mut isize| x = y; + | ^^^^^ cannot assign + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:14 + | +LL | pub fn capture_assign_whole(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +LL | || { x = (1,); }; + | ^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:34:14 + | +LL | pub fn capture_assign_part(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +LL | || { x.0 = 1; }; + | ^^^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:38:14 + | +LL | pub fn capture_reborrow_whole(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +LL | || { &mut x; }; + | ^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:42:14 + | +LL | pub fn capture_reborrow_part(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +LL | || { &mut x.0; }; + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs b/tests/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs new file mode 100644 index 000000000..b87ef3baa --- /dev/null +++ b/tests/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs @@ -0,0 +1,31 @@ +// check-pass + +// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274 +// (for ensuring that NLL respects user-provided lifetime annotations) +// did not handle the case where the ascribed type has some expliit +// wildcards (`_`) mixed in, and it caused an internal compiler error +// (ICE). +// +// This test is just checking that we do not ICE when such things +// occur. + +struct X; +struct Y; +struct Z; + +struct Pair { x: X, y: Y } + +pub fn join(oper_a: A, oper_b: B) -> (RA, RB) +where A: FnOnce() -> RA + Send, + B: FnOnce() -> RB + Send, + RA: Send, + RB: Send +{ + (oper_a(), oper_b()) +} + +fn main() { + let ((_x, _y), _z): (_, Z) = join(|| (X, Y), || Z); + + let (Pair { x: _x, y: _y }, Z): (_, Z) = join(|| Pair { x: X, y: Y }, || Z); +} diff --git a/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs b/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs new file mode 100644 index 000000000..efa313a9d --- /dev/null +++ b/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs @@ -0,0 +1,11 @@ +fn main() { + let mut greeting = "Hello world!".to_string(); + let res = (|| (|| &greeting)())(); + + greeting = "DEALLOCATED".to_string(); + //~^ ERROR cannot assign + drop(greeting); + //~^ ERROR cannot move + + println!("thread result: {:?}", res); +} diff --git a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr new file mode 100644 index 000000000..57803247b --- /dev/null +++ b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr @@ -0,0 +1,32 @@ +error[E0506]: cannot assign to `greeting` because it is borrowed + --> $DIR/issue-58776-borrowck-scans-children.rs:5:5 + | +LL | let res = (|| (|| &greeting)())(); + | -- -------- borrow occurs due to use in closure + | | + | borrow of `greeting` occurs here +LL | +LL | greeting = "DEALLOCATED".to_string(); + | ^^^^^^^^ assignment to borrowed `greeting` occurs here +... +LL | println!("thread result: {:?}", res); + | --- borrow later used here + +error[E0505]: cannot move out of `greeting` because it is borrowed + --> $DIR/issue-58776-borrowck-scans-children.rs:7:10 + | +LL | let res = (|| (|| &greeting)())(); + | -- -------- borrow occurs due to use in closure + | | + | borrow of `greeting` occurs here +... +LL | drop(greeting); + | ^^^^^^^^ move out of `greeting` occurs here +... +LL | println!("thread result: {:?}", res); + | --- borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0505, E0506. +For more information about an error, try `rustc --explain E0505`. diff --git a/tests/ui/borrowck/issue-62007-assign-box.rs b/tests/ui/borrowck/issue-62007-assign-box.rs new file mode 100644 index 000000000..f6fbea821 --- /dev/null +++ b/tests/ui/borrowck/issue-62007-assign-box.rs @@ -0,0 +1,27 @@ +// run-pass + +// Issue #62007: assigning over a deref projection of a box (in this +// case, `*list = n;`) should be able to kill all borrows of `*list`, +// so that `*list` can be borrowed on the next iteration through the +// loop. + +#![allow(dead_code)] + +struct List { + value: T, + next: Option>>, +} + +fn to_refs(mut list: Box<&mut List>) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list.value); + if let Some(n) = list.next.as_mut() { + *list = n; + } else { + return result; + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-62007-assign-field.rs b/tests/ui/borrowck/issue-62007-assign-field.rs new file mode 100644 index 000000000..5b21c0838 --- /dev/null +++ b/tests/ui/borrowck/issue-62007-assign-field.rs @@ -0,0 +1,26 @@ +// run-pass + +// Issue #62007: assigning over a field projection (`list.0 = n;` in +// this case) should be able to kill all borrows of `list.0`, so that +// `list.0` can be borrowed on the next iteration through the loop. + +#![allow(dead_code)] + +struct List { + value: T, + next: Option>>, +} + +fn to_refs(mut list: (&mut List,)) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut (list.0).value); + if let Some(n) = (list.0).next.as_mut() { + list.0 = n; + } else { + return result; + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-62107-match-arm-scopes.rs b/tests/ui/borrowck/issue-62107-match-arm-scopes.rs new file mode 100644 index 000000000..93ce34d2f --- /dev/null +++ b/tests/ui/borrowck/issue-62107-match-arm-scopes.rs @@ -0,0 +1,12 @@ +fn main() { + let e: i32; + match e { + //~^ ERROR E0381 + ref u if true => {} + ref v if true => { + let tx = 0; + &tx; + } + _ => (), + } +} diff --git a/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr b/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr new file mode 100644 index 000000000..9683da919 --- /dev/null +++ b/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `e` isn't initialized + --> $DIR/issue-62107-match-arm-scopes.rs:3:11 + | +LL | let e: i32; + | - binding declared here but left uninitialized +LL | match e { + | ^ `e` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let e: i32 = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/issue-64453.rs b/tests/ui/borrowck/issue-64453.rs new file mode 100644 index 000000000..33d55be58 --- /dev/null +++ b/tests/ui/borrowck/issue-64453.rs @@ -0,0 +1,23 @@ +struct Project; +struct Value; + +static settings_dir: String = format!(""); +//~^ ERROR cannot call non-const fn +//~| ERROR is not yet stable as a const + +fn from_string(_: String) -> Value { + Value +} +fn set_editor(_: Value) {} + +fn main() { + let settings_data = from_string(settings_dir); + //~^ ERROR cannot move out of static item + let args: i32 = 0; + + match args { + ref x if x == &0 => set_editor(settings_data), + ref x if x == &1 => set_editor(settings_data), + _ => unimplemented!(), + } +} diff --git a/tests/ui/borrowck/issue-64453.stderr b/tests/ui/borrowck/issue-64453.stderr new file mode 100644 index 000000000..245c3a40e --- /dev/null +++ b/tests/ui/borrowck/issue-64453.stderr @@ -0,0 +1,29 @@ +error: `Arguments::<'a>::new_v1` is not yet stable as a const fn + --> $DIR/issue-64453.rs:4:31 + | +LL | static settings_dir: String = format!(""); + | ^^^^^^^^^^^ + | + = help: add `#![feature(const_fmt_arguments_new)]` to the crate attributes to enable + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const fn `format` in statics + --> $DIR/issue-64453.rs:4:31 + | +LL | static settings_dir: String = format!(""); + | ^^^^^^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0507]: cannot move out of static item `settings_dir` + --> $DIR/issue-64453.rs:14:37 + | +LL | let settings_data = from_string(settings_dir); + | ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0507. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.rs b/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.rs new file mode 100644 index 000000000..f6d0e9e04 --- /dev/null +++ b/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.rs @@ -0,0 +1,11 @@ +// Regression test for #69789: rustc generated an invalid suggestion +// when `&` reference from `&mut` iterator is mutated. + +fn main() { + for item in &mut std::iter::empty::<&'static ()>() { + //~^ NOTE this iterator yields `&` references + *item = (); + //~^ ERROR cannot assign + //~| NOTE cannot be written + } +} diff --git a/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr b/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr new file mode 100644 index 000000000..369a8c61d --- /dev/null +++ b/tests/ui/borrowck/issue-69789-iterator-mut-suggestion.stderr @@ -0,0 +1,12 @@ +error[E0594]: cannot assign to `*item`, which is behind a `&` reference + --> $DIR/issue-69789-iterator-mut-suggestion.rs:7:9 + | +LL | for item in &mut std::iter::empty::<&'static ()>() { + | -------------------------------------- this iterator yields `&` references +LL | +LL | *item = (); + | ^^^^^^^^^^ `item` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-71546.rs b/tests/ui/borrowck/issue-71546.rs new file mode 100644 index 000000000..42100edea --- /dev/null +++ b/tests/ui/borrowck/issue-71546.rs @@ -0,0 +1,17 @@ +// Regression test for #71546. +// +// Made to pass as part of fixing #98095. +// +// check-pass + +pub fn serialize_as_csv(value: &V) -> Result +where + V: 'static, + for<'a> &'a V: IntoIterator, + for<'a> <&'a V as IntoIterator>::Item: ToString + 'static, +{ + let csv_str: String = value.into_iter().map(|elem| elem.to_string()).collect::(); + Ok(csv_str) +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-7573.rs b/tests/ui/borrowck/issue-7573.rs new file mode 100644 index 000000000..7c0741153 --- /dev/null +++ b/tests/ui/borrowck/issue-7573.rs @@ -0,0 +1,41 @@ +pub struct CrateId { + local_path: String, + junk: String, +} + +impl CrateId { + fn new(s: &str) -> CrateId { + CrateId { local_path: s.to_string(), junk: "wutevs".to_string() } + } +} + +pub fn remove_package_from_database() { + let mut lines_to_use: Vec<&CrateId> = Vec::new(); + //~^ NOTE `lines_to_use` declared here, outside of the closure body + let push_id = |installed_id: &CrateId| { + //~^ NOTE `installed_id` is a reference that is only valid in the closure body + lines_to_use.push(installed_id); + //~^ ERROR borrowed data escapes outside of closure + //~| NOTE `installed_id` escapes the closure body here + }; + list_database(push_id); + + for l in &lines_to_use { + println!("{}", l.local_path); + } +} + +pub fn list_database(mut f: F) +where + F: FnMut(&CrateId), +{ + let stuff = ["foo", "bar"]; + + for l in &stuff { + f(&CrateId::new(*l)); + } +} + +pub fn main() { + remove_package_from_database(); +} diff --git a/tests/ui/borrowck/issue-7573.stderr b/tests/ui/borrowck/issue-7573.stderr new file mode 100644 index 000000000..9d86286b8 --- /dev/null +++ b/tests/ui/borrowck/issue-7573.stderr @@ -0,0 +1,15 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/issue-7573.rs:17:9 + | +LL | let mut lines_to_use: Vec<&CrateId> = Vec::new(); + | ---------------- `lines_to_use` declared here, outside of the closure body +LL | +LL | let push_id = |installed_id: &CrateId| { + | ------------ `installed_id` is a reference that is only valid in the closure body +LL | +LL | lines_to_use.push(installed_id); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/issue-80772.rs b/tests/ui/borrowck/issue-80772.rs new file mode 100644 index 000000000..1b8caa3f8 --- /dev/null +++ b/tests/ui/borrowck/issue-80772.rs @@ -0,0 +1,21 @@ +// check-pass + +trait SomeTrait {} + +pub struct Exhibit { + constant: usize, + factory: fn(&usize) -> Box, +} + +pub const A_CONSTANT: &[Exhibit] = &[ + Exhibit { + constant: 1, + factory: |_| unimplemented!(), + }, + Exhibit { + constant: "Hello world".len(), + factory: |_| unimplemented!(), + }, +]; + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-1.rs b/tests/ui/borrowck/issue-81365-1.rs new file mode 100644 index 000000000..8e212a770 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-1.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-1.stderr b/tests/ui/borrowck/issue-81365-1.stderr new file mode 100644 index 000000000..d79394834 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-1.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-1.rs:21:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-1.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-10.rs b/tests/ui/borrowck/issue-81365-10.rs new file mode 100644 index 000000000..7602e184a --- /dev/null +++ b/tests/ui/borrowck/issue-81365-10.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self.deref().target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-10.stderr b/tests/ui/borrowck/issue-81365-10.stderr new file mode 100644 index 000000000..27123ef2b --- /dev/null +++ b/tests/ui/borrowck/issue-81365-10.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-10.rs:21:9 + | +LL | let first = &self.deref().target_field; + | ------------ borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-11.rs b/tests/ui/borrowck/issue-81365-11.rs new file mode 100644 index 000000000..6b558c65d --- /dev/null +++ b/tests/ui/borrowck/issue-81365-11.rs @@ -0,0 +1,32 @@ +use std::ops::{Deref, DerefMut}; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl DerefMut for Container { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &mut self.target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-11.stderr b/tests/ui/borrowck/issue-81365-11.stderr new file mode 100644 index 000000000..0770c1366 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-11.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-11.rs:27:9 + | +LL | let first = &mut self.target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-2.rs b/tests/ui/borrowck/issue-81365-2.rs new file mode 100644 index 000000000..fbbdd93b9 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-2.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.container.target_field; + self.container.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-2.stderr b/tests/ui/borrowck/issue-81365-2.stderr new file mode 100644 index 000000000..764eaaa7c --- /dev/null +++ b/tests/ui/borrowck/issue-81365-2.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container.container_field` because it is borrowed + --> $DIR/issue-81365-2.rs:25:9 + | +LL | let first = &self.container.target_field; + | -------------- borrow of `self.container.container_field` occurs here +LL | self.container.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-2.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-3.rs b/tests/ui/borrowck/issue-81365-3.rs new file mode 100644 index 000000000..9a9e3a313 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-3.rs @@ -0,0 +1,37 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, +} + +impl Deref for Outer { + type Target = Container; + fn deref(&self) -> &Self::Target { + &self.container + } +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.container.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-3.stderr b/tests/ui/borrowck/issue-81365-3.stderr new file mode 100644 index 000000000..9447174fd --- /dev/null +++ b/tests/ui/borrowck/issue-81365-3.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container.container_field` because it is borrowed + --> $DIR/issue-81365-3.rs:32:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.container.container_field` occurs here +LL | self.container.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `Container` +note: deref defined here + --> $DIR/issue-81365-3.rs:23:5 + | +LL | type Target = Container; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-4.rs b/tests/ui/borrowck/issue-81365-4.rs new file mode 100644 index 000000000..b2643eb33 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-4.rs @@ -0,0 +1,38 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +struct Outer { + container: Container, + outer_field: bool, +} + +impl Deref for Outer { + type Target = Container; + fn deref(&self) -> &Self::Target { + &self.container + } +} + +impl Outer { + fn bad_borrow(&mut self) { + let first = &self.target_field; + self.outer_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-4.stderr b/tests/ui/borrowck/issue-81365-4.stderr new file mode 100644 index 000000000..0ab3fa927 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-4.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.outer_field` because it is borrowed + --> $DIR/issue-81365-4.rs:33:9 + | +LL | let first = &self.target_field; + | ---- borrow of `self.outer_field` occurs here +LL | self.outer_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.outer_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `Container` +note: deref defined here + --> $DIR/issue-81365-4.rs:24:5 + | +LL | type Target = Container; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-5.rs b/tests/ui/borrowck/issue-81365-5.rs new file mode 100644 index 000000000..d36b79615 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-5.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} + +impl DerefTarget { + fn get(&self) -> &bool { + &self.target_field + } +} + +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = self.get(); + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-5.stderr b/tests/ui/borrowck/issue-81365-5.stderr new file mode 100644 index 000000000..20ff229ff --- /dev/null +++ b/tests/ui/borrowck/issue-81365-5.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-5.rs:28:9 + | +LL | let first = self.get(); + | ---------- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-5.rs:19:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-6.rs b/tests/ui/borrowck/issue-81365-6.rs new file mode 100644 index 000000000..85ea77756 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-6.rs @@ -0,0 +1,23 @@ +use std::ops::Deref; + +struct Container { + target: Vec<()>, + container_field: bool, +} + +impl Deref for Container { + type Target = [()]; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &self[0]; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-6.stderr b/tests/ui/borrowck/issue-81365-6.stderr new file mode 100644 index 000000000..575aed73b --- /dev/null +++ b/tests/ui/borrowck/issue-81365-6.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-6.rs:18:9 + | +LL | let first = &self[0]; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `[()]` +note: deref defined here + --> $DIR/issue-81365-6.rs:9:5 + | +LL | type Target = [()]; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-7.rs b/tests/ui/borrowck/issue-81365-7.rs new file mode 100644 index 000000000..cbf70f11a --- /dev/null +++ b/tests/ui/borrowck/issue-81365-7.rs @@ -0,0 +1,24 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +fn bad_borrow(c: &mut Container) { + let first = &c.target_field; + c.container_field = true; //~ ERROR E0506 + first; +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-7.stderr b/tests/ui/borrowck/issue-81365-7.stderr new file mode 100644 index 000000000..52d2d9e75 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-7.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `c.container_field` because it is borrowed + --> $DIR/issue-81365-7.rs:20:5 + | +LL | let first = &c.target_field; + | - borrow of `c.container_field` occurs here +LL | c.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `c.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-7.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-8.rs b/tests/ui/borrowck/issue-81365-8.rs new file mode 100644 index 000000000..0bb1033fb --- /dev/null +++ b/tests/ui/borrowck/issue-81365-8.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &(*self).target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-8.stderr b/tests/ui/borrowck/issue-81365-8.stderr new file mode 100644 index 000000000..fd83e10a2 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-8.stderr @@ -0,0 +1,20 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-8.rs:21:9 + | +LL | let first = &(*self).target_field; + | ------- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + | + = note: borrow occurs due to deref coercion to `DerefTarget` +note: deref defined here + --> $DIR/issue-81365-8.rs:12:5 + | +LL | type Target = DerefTarget; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81365-9.rs b/tests/ui/borrowck/issue-81365-9.rs new file mode 100644 index 000000000..cd57afa28 --- /dev/null +++ b/tests/ui/borrowck/issue-81365-9.rs @@ -0,0 +1,26 @@ +use std::ops::Deref; + +struct DerefTarget { + target_field: bool, +} +struct Container { + target: DerefTarget, + container_field: bool, +} + +impl Deref for Container { + type Target = DerefTarget; + fn deref(&self) -> &Self::Target { + &self.target + } +} + +impl Container { + fn bad_borrow(&mut self) { + let first = &Deref::deref(self).target_field; + self.container_field = true; //~ ERROR E0506 + first; + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81365-9.stderr b/tests/ui/borrowck/issue-81365-9.stderr new file mode 100644 index 000000000..c7d48214f --- /dev/null +++ b/tests/ui/borrowck/issue-81365-9.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `self.container_field` because it is borrowed + --> $DIR/issue-81365-9.rs:21:9 + | +LL | let first = &Deref::deref(self).target_field; + | ---- borrow of `self.container_field` occurs here +LL | self.container_field = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here +LL | first; + | ----- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/borrowck/issue-81899.rs b/tests/ui/borrowck/issue-81899.rs new file mode 100644 index 000000000..1f1af5c7e --- /dev/null +++ b/tests/ui/borrowck/issue-81899.rs @@ -0,0 +1,15 @@ +// Regression test for #81899. +// The `panic!()` below is important to trigger the fixed ICE. + +const _CONST: &[u8] = &f(&[], |_| {}); +//~^ constant + +const fn f(_: &[u8], _: F) -> &[u8] +where + F: FnMut(&u8), +{ + panic!() //~ ERROR evaluation of constant value failed + //~^ panic +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-81899.stderr b/tests/ui/borrowck/issue-81899.stderr new file mode 100644 index 000000000..1b03bc3af --- /dev/null +++ b/tests/ui/borrowck/issue-81899.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-81899.rs:11:5 + | +LL | panic!() + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5 + | +note: inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` + --> $DIR/issue-81899.rs:11:5 + | +LL | panic!() + | ^^^^^^^^ +note: inside `_CONST` + --> $DIR/issue-81899.rs:4:24 + | +LL | const _CONST: &[u8] = &f(&[], |_| {}); + | ^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-81899.rs:4:23 + | +LL | const _CONST: &[u8] = &f(&[], |_| {}); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/borrowck/issue-82032.rs b/tests/ui/borrowck/issue-82032.rs new file mode 100644 index 000000000..4a01b60c1 --- /dev/null +++ b/tests/ui/borrowck/issue-82032.rs @@ -0,0 +1,16 @@ +use std::{fs, io::*}; +use std::collections::HashMap; + +type Handle = BufWriter; +struct Thing(HashMap); + +impl Thing { + pub fn die_horribly(&mut self) { + for v in self.0.values() { + v.flush(); + //~^ ERROR cannot borrow + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-82032.stderr b/tests/ui/borrowck/issue-82032.stderr new file mode 100644 index 000000000..25f343117 --- /dev/null +++ b/tests/ui/borrowck/issue-82032.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*v` as mutable, as it is behind a `&` reference + --> $DIR/issue-82032.rs:10:13 + | +LL | for v in self.0.values() { + | --------------- + | | | + | | help: use mutable method: `values_mut()` + | this iterator yields `&` references +LL | v.flush(); + | ^^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs new file mode 100644 index 000000000..dd0320bc5 --- /dev/null +++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs @@ -0,0 +1,24 @@ +// Regression test for #82126. Checks that mismatched lifetimes and types are +// properly handled. + +// edition:2018 + +use std::sync::Mutex; + +struct MarketMultiplier {} + +impl MarketMultiplier { + fn buy(&mut self) -> &mut usize { + todo!() + } +} + +async fn buy_lock(generator: &Mutex) -> LockedMarket<'_> { + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + //~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied + LockedMarket(generator.lock().unwrap().buy()) +} + +struct LockedMarket(T); + +fn main() {} diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr new file mode 100644 index 000000000..d2b927fb6 --- /dev/null +++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr @@ -0,0 +1,33 @@ +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:16:59 + | +LL | async fn buy_lock(generator: &Mutex) -> LockedMarket<'_> { + | ^^^^^^^^^^^^---- help: remove these generics + | | + | expected 0 lifetime arguments + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 + | +LL | struct LockedMarket(T); + | ^^^^^^^^^^^^ + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:16:59 + | +LL | async fn buy_lock(generator: &Mutex) -> LockedMarket<'_> { + | ^^^^^^^^^^^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8 + | +LL | struct LockedMarket(T); + | ^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | async fn buy_lock(generator: &Mutex) -> LockedMarket<'_, T> { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/borrowck/issue-82462.rs b/tests/ui/borrowck/issue-82462.rs new file mode 100644 index 000000000..5a3c64255 --- /dev/null +++ b/tests/ui/borrowck/issue-82462.rs @@ -0,0 +1,21 @@ +struct DroppingSlice<'a>(&'a [i32]); + +impl Drop for DroppingSlice<'_> { + fn drop(&mut self) { + println!("hi from slice"); + } +} + +impl DroppingSlice<'_> { + fn iter(&self) -> std::slice::Iter<'_, i32> { + self.0.iter() + } +} + +fn main() { + let mut v = vec![1, 2, 3, 4]; + for x in DroppingSlice(&*v).iter() { + v.push(*x); //~ERROR + break; + } +} diff --git a/tests/ui/borrowck/issue-82462.stderr b/tests/ui/borrowck/issue-82462.stderr new file mode 100644 index 000000000..a2c291f77 --- /dev/null +++ b/tests/ui/borrowck/issue-82462.stderr @@ -0,0 +1,22 @@ +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> $DIR/issue-82462.rs:18:9 + | +LL | for x in DroppingSlice(&*v).iter() { + | ------------------ + | | | + | | immutable borrow occurs here + | a temporary with access to the immutable borrow is created here ... +LL | v.push(*x); + | ^^^^^^^^^^ mutable borrow occurs here +LL | break; +LL | } + | - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice` + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | }; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs b/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs new file mode 100644 index 000000000..d301e7b35 --- /dev/null +++ b/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.rs @@ -0,0 +1,32 @@ +// rust-lang/rust#83309: The compiler tries to suggest potential +// methods that return `&mut` items. However, when it doesn't +// find such methods, it still tries to add suggestions +// which then fails an assertion later because there was +// no suggestions to make. + + +fn main() { + for v in Query.iter_mut() { + //~^ NOTE this iterator yields `&` references + *v -= 1; + //~^ ERROR cannot assign to `*v`, which is behind a `&` reference + //~| NOTE `v` is a `&` reference, so the data it refers to cannot be written + } +} + +pub struct Query; +pub struct QueryIter<'a>(&'a i32); + +impl Query { + pub fn iter_mut<'a>(&'a mut self) -> QueryIter<'a> { + todo!(); + } +} + +impl<'a> Iterator for QueryIter<'a> { + type Item = &'a i32; + + fn next(&mut self) -> Option { + todo!(); + } +} diff --git a/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr b/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr new file mode 100644 index 000000000..26ce007dd --- /dev/null +++ b/tests/ui/borrowck/issue-83309-ice-immut-in-for-loop.stderr @@ -0,0 +1,12 @@ +error[E0594]: cannot assign to `*v`, which is behind a `&` reference + --> $DIR/issue-83309-ice-immut-in-for-loop.rs:11:9 + | +LL | for v in Query.iter_mut() { + | ---------------- this iterator yields `&` references +LL | +LL | *v -= 1; + | ^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-83760.rs b/tests/ui/borrowck/issue-83760.rs new file mode 100644 index 000000000..e25b4f727 --- /dev/null +++ b/tests/ui/borrowck/issue-83760.rs @@ -0,0 +1,40 @@ +struct Struct; + +fn test1() { + let mut val = Some(Struct); + while let Some(foo) = val { //~ ERROR use of moved value + if true { + val = None; + } else { + + } + } +} + +fn test2() { + let mut foo = Some(Struct); + let _x = foo.unwrap(); + if true { + foo = Some(Struct); + } else { + } + let _y = foo; //~ ERROR use of moved value: `foo` +} + +fn test3() { + let mut foo = Some(Struct); + let _x = foo.unwrap(); + if true { + foo = Some(Struct); + } else if true { + foo = Some(Struct); + } else if true { + foo = Some(Struct); + } else if true { + foo = Some(Struct); + } else { + } + let _y = foo; //~ ERROR use of moved value: `foo` +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-83760.stderr b/tests/ui/borrowck/issue-83760.stderr new file mode 100644 index 000000000..a585bff0c --- /dev/null +++ b/tests/ui/borrowck/issue-83760.stderr @@ -0,0 +1,60 @@ +error[E0382]: use of moved value + --> $DIR/issue-83760.rs:5:20 + | +LL | while let Some(foo) = val { + | ^^^ value moved here, in previous iteration of loop +LL | if true { +LL | val = None; + | ---------- this reinitialization might get skipped + | + = note: move occurs because value has type `Struct`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | while let Some(ref foo) = val { + | +++ + +error[E0382]: use of moved value: `foo` + --> $DIR/issue-83760.rs:21:14 + | +LL | let mut foo = Some(Struct); + | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait +LL | let _x = foo.unwrap(); + | -------- `foo` moved due to this method call +LL | if true { +LL | foo = Some(Struct); + | ------------------ this reinitialization might get skipped +... +LL | let _y = foo; + | ^^^ value used here after move + | +note: `Option::::unwrap` takes ownership of the receiver `self`, which moves `foo` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0382]: use of moved value: `foo` + --> $DIR/issue-83760.rs:37:14 + | +LL | let mut foo = Some(Struct); + | ------- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait +LL | let _x = foo.unwrap(); + | -------- `foo` moved due to this method call +... +LL | let _y = foo; + | ^^^ value used here after move + | +note: these 3 reinitializations and 1 other might get skipped + --> $DIR/issue-83760.rs:30:9 + | +LL | foo = Some(Struct); + | ^^^^^^^^^^^^^^^^^^ +LL | } else if true { +LL | foo = Some(Struct); + | ^^^^^^^^^^^^^^^^^^ +LL | } else if true { +LL | foo = Some(Struct); + | ^^^^^^^^^^^^^^^^^^ +note: `Option::::unwrap` takes ownership of the receiver `self`, which moves `foo` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-85581.rs b/tests/ui/borrowck/issue-85581.rs new file mode 100644 index 000000000..ccc120c54 --- /dev/null +++ b/tests/ui/borrowck/issue-85581.rs @@ -0,0 +1,15 @@ +// Regression test of #85581. +// Checks not to suggest to add `;` when the second mutable borrow +// is in the first's scope. + +use std::collections::BinaryHeap; + +fn foo(heap: &mut BinaryHeap) { + match heap.peek_mut() { + Some(_) => { heap.pop(); }, + //~^ ERROR: cannot borrow `*heap` as mutable more than once at a time + None => (), + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-85581.stderr b/tests/ui/borrowck/issue-85581.stderr new file mode 100644 index 000000000..59ca4867f --- /dev/null +++ b/tests/ui/borrowck/issue-85581.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `*heap` as mutable more than once at a time + --> $DIR/issue-85581.rs:9:22 + | +LL | match heap.peek_mut() { + | --------------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | Some(_) => { heap.pop(); }, + | ^^^^^^^^^^ second mutable borrow occurs here +... +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs new file mode 100644 index 000000000..1598cd5d3 --- /dev/null +++ b/tests/ui/borrowck/issue-85765.rs @@ -0,0 +1,29 @@ +fn main() { + let mut test = Vec::new(); + let rofl: &Vec> = &mut test; + //~^ NOTE consider changing this binding's type to be + rofl.push(Vec::new()); + //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference + //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable + + let mut mutvar = 42; + let r = &mutvar; + //~^ HELP consider changing this to be a mutable reference + *r = 0; + //~^ ERROR cannot assign to `*r`, which is behind a `&` reference + //~| NOTE `r` is a `&` reference, so the data it refers to cannot be written + + #[rustfmt::skip] + let x: &usize = &mut{0}; + //~^ NOTE consider changing this binding's type to be + *x = 1; + //~^ ERROR cannot assign to `*x`, which is behind a `&` reference + //~| NOTE `x` is a `&` reference, so the data it refers to cannot be written + + #[rustfmt::skip] + let y: &usize = &mut(0); + //~^ NOTE consider changing this binding's type to be + *y = 1; + //~^ ERROR cannot assign to `*y`, which is behind a `&` reference + //~| NOTE `y` is a `&` reference, so the data it refers to cannot be written +} diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr new file mode 100644 index 000000000..7da7dba68 --- /dev/null +++ b/tests/ui/borrowck/issue-85765.stderr @@ -0,0 +1,42 @@ +error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference + --> $DIR/issue-85765.rs:5:5 + | +LL | let rofl: &Vec> = &mut test; + | ---- consider changing this binding's type to be: `&mut Vec>` +LL | +LL | rofl.push(Vec::new()); + | ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error[E0594]: cannot assign to `*r`, which is behind a `&` reference + --> $DIR/issue-85765.rs:12:5 + | +LL | *r = 0; + | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let r = &mut mutvar; + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/issue-85765.rs:19:5 + | +LL | let x: &usize = &mut{0}; + | - consider changing this binding's type to be: `&mut usize` +LL | +LL | *x = 1; + | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*y`, which is behind a `&` reference + --> $DIR/issue-85765.rs:26:5 + | +LL | let y: &usize = &mut(0); + | - consider changing this binding's type to be: `&mut usize` +LL | +LL | *y = 1; + | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-87456-point-to-closure.rs b/tests/ui/borrowck/issue-87456-point-to-closure.rs new file mode 100644 index 000000000..9fc12ba74 --- /dev/null +++ b/tests/ui/borrowck/issue-87456-point-to-closure.rs @@ -0,0 +1,14 @@ +// Regression test for #87456. + +fn take_mut(_val: impl FnMut()) {} + +fn main() { + let val = String::new(); + //~^ NOTE: captured outer variable + take_mut(|| { + //~^ NOTE: captured by this `FnMut` closure + let _foo: String = val; + //~^ ERROR: cannot move out of `val`, a captured variable in an `FnMut` closure [E0507] + //~| NOTE: move occurs because + }) +} diff --git a/tests/ui/borrowck/issue-87456-point-to-closure.stderr b/tests/ui/borrowck/issue-87456-point-to-closure.stderr new file mode 100644 index 000000000..afd141125 --- /dev/null +++ b/tests/ui/borrowck/issue-87456-point-to-closure.stderr @@ -0,0 +1,20 @@ +error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure + --> $DIR/issue-87456-point-to-closure.rs:10:28 + | +LL | let val = String::new(); + | --- captured outer variable +LL | +LL | take_mut(|| { + | -- captured by this `FnMut` closure +LL | +LL | let _foo: String = val; + | ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let _foo: String = &val; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/issue-88434-minimal-example.rs b/tests/ui/borrowck/issue-88434-minimal-example.rs new file mode 100644 index 000000000..b75abcb73 --- /dev/null +++ b/tests/ui/borrowck/issue-88434-minimal-example.rs @@ -0,0 +1,14 @@ +// Regression test related to issue 88434 + +const _CONST: &() = &f(&|_| {}); +//~^ constant + +const fn f(_: &F) +where + F: FnMut(&u8), +{ + panic!() //~ ERROR evaluation of constant value failed + //~^ panic +} + +fn main() { } diff --git a/tests/ui/borrowck/issue-88434-minimal-example.stderr b/tests/ui/borrowck/issue-88434-minimal-example.stderr new file mode 100644 index 000000000..a5a571c6d --- /dev/null +++ b/tests/ui/borrowck/issue-88434-minimal-example.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-88434-minimal-example.rs:10:5 + | +LL | panic!() + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5 + | +note: inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` + --> $DIR/issue-88434-minimal-example.rs:10:5 + | +LL | panic!() + | ^^^^^^^^ +note: inside `_CONST` + --> $DIR/issue-88434-minimal-example.rs:3:22 + | +LL | const _CONST: &() = &f(&|_| {}); + | ^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-88434-minimal-example.rs:3:21 + | +LL | const _CONST: &() = &f(&|_| {}); + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs new file mode 100644 index 000000000..f9134e669 --- /dev/null +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.rs @@ -0,0 +1,14 @@ +// Regression test for issue 88434 + +const _CONST: &[u8] = &f(&[], |_| {}); +//~^ constant + +const fn f(_: &[u8], _: F) -> &[u8] +where + F: FnMut(&u8), +{ + panic!() //~ ERROR evaluation of constant value failed + //~^ panic +} + +fn main() { } diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr new file mode 100644 index 000000000..00023c459 --- /dev/null +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5 + | +LL | panic!() + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5 + | +note: inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` + --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5 + | +LL | panic!() + | ^^^^^^^^ +note: inside `_CONST` + --> $DIR/issue-88434-removal-index-should-be-less.rs:3:24 + | +LL | const _CONST: &[u8] = &f(&[], |_| {}); + | ^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23 + | +LL | const _CONST: &[u8] = &f(&[], |_| {}); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs new file mode 100644 index 000000000..67407c1ea --- /dev/null +++ b/tests/ui/borrowck/issue-91206.rs @@ -0,0 +1,16 @@ +struct TestClient; + +impl TestClient { + fn get_inner_ref(&self) -> &Vec { + todo!() + } +} + +fn main() { + let client = TestClient; + let inner = client.get_inner_ref(); + //~^ NOTE consider changing this binding's type to be + inner.clear(); + //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] + //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable +} diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr new file mode 100644 index 000000000..12d8d27c5 --- /dev/null +++ b/tests/ui/borrowck/issue-91206.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference + --> $DIR/issue-91206.rs:13:5 + | +LL | let inner = client.get_inner_ref(); + | ----- consider changing this binding's type to be: `&mut Vec` +LL | +LL | inner.clear(); + | ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-92015.rs b/tests/ui/borrowck/issue-92015.rs new file mode 100644 index 000000000..16d651717 --- /dev/null +++ b/tests/ui/borrowck/issue-92015.rs @@ -0,0 +1,7 @@ +// Regression test for #92105. +// ICE when mutating immutable reference from last statement of a block. + +fn main() { + let foo = Some(&0).unwrap(); + *foo = 1; //~ ERROR cannot assign +} diff --git a/tests/ui/borrowck/issue-92015.stderr b/tests/ui/borrowck/issue-92015.stderr new file mode 100644 index 000000000..62b1183e7 --- /dev/null +++ b/tests/ui/borrowck/issue-92015.stderr @@ -0,0 +1,11 @@ +error[E0594]: cannot assign to `*foo`, which is behind a `&` reference + --> $DIR/issue-92015.rs:6:5 + | +LL | let foo = Some(&0).unwrap(); + | --- consider changing this binding's type to be: `&mut i32` +LL | *foo = 1; + | ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-92157.rs b/tests/ui/borrowck/issue-92157.rs new file mode 100644 index 000000000..6ee2320a6 --- /dev/null +++ b/tests/ui/borrowck/issue-92157.rs @@ -0,0 +1,40 @@ +#![feature(no_core)] +#![feature(lang_items)] + +#![no_core] + +#[cfg(target_os = "linux")] +#[link(name = "c")] +extern {} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + //~^ ERROR: incorrect number of parameters for the `start` lang item + 40+2 +} + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + drop_in_place(to_drop) +} + +#[lang = "add"] +trait Add { + type Output; + fn add(self, other: RHS) -> Self::Output; +} + +impl Add for isize { + type Output = isize; + fn add(self, other: isize) -> isize { + self + other + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-92157.stderr b/tests/ui/borrowck/issue-92157.stderr new file mode 100644 index 000000000..a4010d73d --- /dev/null +++ b/tests/ui/borrowck/issue-92157.stderr @@ -0,0 +1,11 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/issue-92157.rs:11:1 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `start` lang item should have four parameters, but found 3 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + diff --git a/tests/ui/borrowck/issue-93078.rs b/tests/ui/borrowck/issue-93078.rs new file mode 100644 index 000000000..2e608c5db --- /dev/null +++ b/tests/ui/borrowck/issue-93078.rs @@ -0,0 +1,15 @@ +trait Modify { + fn modify(&mut self) ; +} + +impl Modify for T { + fn modify(&mut self) {} +} + +trait Foo { + fn mute(&mut self) { + self.modify(); //~ ERROR cannot borrow `self` as mutable + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-93078.stderr b/tests/ui/borrowck/issue-93078.stderr new file mode 100644 index 000000000..771a652a1 --- /dev/null +++ b/tests/ui/borrowck/issue-93078.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-93078.rs:11:9 + | +LL | self.modify(); + | ^^^^^^^^^^^^^ cannot borrow as mutable + | + = note: as `Self` may be unsized, this call attempts to take `&mut &mut self` + = note: however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-93093.rs b/tests/ui/borrowck/issue-93093.rs new file mode 100644 index 000000000..f4db5ecaf --- /dev/null +++ b/tests/ui/borrowck/issue-93093.rs @@ -0,0 +1,14 @@ +// edition:2018 +struct S { + foo: usize, +} +impl S { + async fn bar(&self) { //~ HELP consider changing this to be a mutable reference + //~| SUGGESTION &mut self + self.foo += 1; //~ ERROR cannot assign to `self.foo`, which is behind a `&` reference [E0594] + } +} + +fn main() { + S { foo: 1 }.bar(); +} diff --git a/tests/ui/borrowck/issue-93093.stderr b/tests/ui/borrowck/issue-93093.stderr new file mode 100644 index 000000000..afa76594f --- /dev/null +++ b/tests/ui/borrowck/issue-93093.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `self.foo`, which is behind a `&` reference + --> $DIR/issue-93093.rs:8:9 + | +LL | self.foo += 1; + | ^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | async fn bar(&mut self) { + | ~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs new file mode 100644 index 000000000..95847d8d3 --- /dev/null +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs @@ -0,0 +1,14 @@ +fn foo1(s: &str) -> impl Iterator + '_ { + None.into_iter() + .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s))) + //~^ ERROR captured variable cannot escape `FnMut` closure body + //~| HELP consider adding 'move' keyword before the nested closure +} + +fn foo2(s: &str) -> impl Sized + '_ { + move |()| s.chars().map(|c| format!("{}{}", c, s)) + //~^ ERROR lifetime may not live long enough + //~| HELP consider adding 'move' keyword before the nested closure +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr new file mode 100644 index 000000000..2eae614a2 --- /dev/null +++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr @@ -0,0 +1,37 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29 + | +LL | fn foo1(s: &str) -> impl Iterator + '_ { + | - variable defined here +LL | None.into_iter() +LL | .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s))) + | - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | returns a reference to a captured variable which escapes the closure body + | | variable captured here + | inferred to be a `FnMut` closure + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape +help: consider adding 'move' keyword before the nested closure + | +LL | .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s))) + | ++++ + +error: lifetime may not live long enough + --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15 + | +LL | move |()| s.chars().map(|c| format!("{}{}", c, s)) + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure `Map, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2` + | lifetime `'1` represents this closure's body + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure +help: consider adding 'move' keyword before the nested closure + | +LL | move |()| s.chars().map(move |c| format!("{}{}", c, s)) + | ++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/borrowck/kindck-implicit-close-over-mut-var.rs b/tests/ui/borrowck/kindck-implicit-close-over-mut-var.rs new file mode 100644 index 000000000..5b5d86eec --- /dev/null +++ b/tests/ui/borrowck/kindck-implicit-close-over-mut-var.rs @@ -0,0 +1,49 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(dead_code)] +use std::thread; + +fn user(_i: isize) {} + +fn foo() { + // Here, i is *copied* into the proc (heap closure). + // Requires allocation. The proc's copy is not mutable. + let mut i = 0; + let t = thread::spawn(move|| { + user(i); + println!("spawned {}", i) + }); + i += 1; + println!("original {}", i); + t.join(); +} + +fn bar() { + // Here, the original i has not been moved, only copied, so is still + // mutable outside of the proc. + let mut i = 0; + while i < 10 { + let t = thread::spawn(move|| { + user(i); + }); + i += 1; + t.join(); + } +} + +fn car() { + // Here, i must be shadowed in the proc to be mutable. + let mut i = 0; + while i < 10 { + let t = thread::spawn(move|| { + let mut i = i; + i += 1; + user(i); + }); + i += 1; + t.join(); + } +} + +pub fn main() {} diff --git a/tests/ui/borrowck/lazy-init.rs b/tests/ui/borrowck/lazy-init.rs new file mode 100644 index 000000000..a4b5d18bb --- /dev/null +++ b/tests/ui/borrowck/lazy-init.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(unused_mut)] + + +fn foo(x: isize) { println!("{}", x); } + +pub fn main() { let mut x: isize; if 1 > 2 { x = 12; } else { x = 10; } foo(x); } diff --git a/tests/ui/borrowck/many-mutable-borrows.rs b/tests/ui/borrowck/many-mutable-borrows.rs new file mode 100644 index 000000000..3e6ea9d25 --- /dev/null +++ b/tests/ui/borrowck/many-mutable-borrows.rs @@ -0,0 +1,18 @@ +fn main() { + let v = Vec::new(); //~ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); +} diff --git a/tests/ui/borrowck/many-mutable-borrows.stderr b/tests/ui/borrowck/many-mutable-borrows.stderr new file mode 100644 index 000000000..aa0cbcffd --- /dev/null +++ b/tests/ui/borrowck/many-mutable-borrows.stderr @@ -0,0 +1,33 @@ +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/many-mutable-borrows.rs:2:9 + | +LL | let v = Vec::new(); + | ^ not mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable + | + = note: ...and 5 other attempted mutable borrows +help: consider changing this to be mutable + | +LL | let mut v = Vec::new(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/move-error-in-promoted-2.rs b/tests/ui/borrowck/move-error-in-promoted-2.rs new file mode 100644 index 000000000..13da34f39 --- /dev/null +++ b/tests/ui/borrowck/move-error-in-promoted-2.rs @@ -0,0 +1,10 @@ +// Regression test for #70934 + +struct S; + +fn foo() { + &([S][0],); + //~^ ERROR cannot move out of type `[S; 1]` +} + +fn main() {} diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr new file mode 100644 index 000000000..38dba94bd --- /dev/null +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -0,0 +1,12 @@ +error[E0508]: cannot move out of type `[S; 1]`, a non-copy array + --> $DIR/move-error-in-promoted-2.rs:6:7 + | +LL | &([S][0],); + | ^^^^^^ + | | + | cannot move out of here + | move occurs because value has type `S`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/borrowck/move-error-in-promoted.rs b/tests/ui/borrowck/move-error-in-promoted.rs new file mode 100644 index 000000000..b94db6451 --- /dev/null +++ b/tests/ui/borrowck/move-error-in-promoted.rs @@ -0,0 +1,17 @@ +// Regression test for #70934 + +fn f() { + const C: [S2; 1] = [S2]; + let _ = S1(C[0]).clone(); + //~^ ERROR cannot move out of type `[S2; 1]` +} + +#[derive(Clone)] +struct S1(S2); + +#[derive(Clone)] +struct S2; + +fn main() { + f(); +} diff --git a/tests/ui/borrowck/move-error-in-promoted.stderr b/tests/ui/borrowck/move-error-in-promoted.stderr new file mode 100644 index 000000000..a4432e38d --- /dev/null +++ b/tests/ui/borrowck/move-error-in-promoted.stderr @@ -0,0 +1,12 @@ +error[E0508]: cannot move out of type `[S2; 1]`, a non-copy array + --> $DIR/move-error-in-promoted.rs:5:16 + | +LL | let _ = S1(C[0]).clone(); + | ^^^^ + | | + | cannot move out of here + | move occurs because value has type `S2`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/borrowck/move-error-snippets-ext.rs b/tests/ui/borrowck/move-error-snippets-ext.rs new file mode 100644 index 000000000..c77f6c827 --- /dev/null +++ b/tests/ui/borrowck/move-error-snippets-ext.rs @@ -0,0 +1,7 @@ +// ignore-test + +macro_rules! aaa { + ($c:ident) => {{ + let a = $c; + }} +} diff --git a/tests/ui/borrowck/move-error-snippets.rs b/tests/ui/borrowck/move-error-snippets.rs new file mode 100644 index 000000000..64f956538 --- /dev/null +++ b/tests/ui/borrowck/move-error-snippets.rs @@ -0,0 +1,23 @@ +// Test that we don't ICE after trying to construct a cross-file snippet #63800. + +// compile-flags: --test + +#[macro_use] +#[path = "move-error-snippets-ext.rs"] +mod move_error_snippets_ext; + +struct A; + +macro_rules! sss { + () => { + #[test] + fn fff() { + static D: A = A; + aaa!(D); //~ ERROR cannot move + } + }; +} + +sss!(); + +fn main() {} diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr new file mode 100644 index 000000000..8ac711e9e --- /dev/null +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -0,0 +1,20 @@ +error[E0507]: cannot move out of static item `D` + --> $DIR/move-error-snippets-ext.rs:5:17 + | +LL | let a = $c; + | ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait + | + ::: $DIR/move-error-snippets.rs:21:1 + | +LL | sss!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | let a = &$c; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/move-from-union-field-issue-66500.rs b/tests/ui/borrowck/move-from-union-field-issue-66500.rs new file mode 100644 index 000000000..0bd2147f4 --- /dev/null +++ b/tests/ui/borrowck/move-from-union-field-issue-66500.rs @@ -0,0 +1,28 @@ +// Moving from a reference/raw pointer should be an error, even when they're +// the field of a union. + +union Pointers { + a: &'static String, + b: &'static mut String, + c: *const String, + d: *mut String, +} + +unsafe fn move_ref(u: Pointers) -> String { + *u.a + //~^ ERROR cannot move out of `*u.a` +} +unsafe fn move_ref_mut(u: Pointers) -> String { + *u.b + //~^ ERROR cannot move out of `*u.b` +} +unsafe fn move_ptr(u: Pointers) -> String { + *u.c + //~^ ERROR cannot move out of `*u.c` +} +unsafe fn move_ptr_mut(u: Pointers) -> String { + *u.d + //~^ ERROR cannot move out of `*u.d` +} + +fn main() {} diff --git a/tests/ui/borrowck/move-from-union-field-issue-66500.stderr b/tests/ui/borrowck/move-from-union-field-issue-66500.stderr new file mode 100644 index 000000000..700785827 --- /dev/null +++ b/tests/ui/borrowck/move-from-union-field-issue-66500.stderr @@ -0,0 +1,27 @@ +error[E0507]: cannot move out of `*u.a` which is behind a shared reference + --> $DIR/move-from-union-field-issue-66500.rs:12:5 + | +LL | *u.a + | ^^^^ move occurs because `*u.a` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `*u.b` which is behind a mutable reference + --> $DIR/move-from-union-field-issue-66500.rs:16:5 + | +LL | *u.b + | ^^^^ move occurs because `*u.b` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `*u.c` which is behind a raw pointer + --> $DIR/move-from-union-field-issue-66500.rs:20:5 + | +LL | *u.c + | ^^^^ move occurs because `*u.c` has type `String`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of `*u.d` which is behind a raw pointer + --> $DIR/move-from-union-field-issue-66500.rs:24:5 + | +LL | *u.d + | ^^^^ move occurs because `*u.d` has type `String`, which does not implement the `Copy` trait + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs b/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs new file mode 100644 index 000000000..4b42f9d4c --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs @@ -0,0 +1,10 @@ +// Regression test for #80913. + +fn main() { + let mut x = 42_i32; + let mut opt = Some(&mut x); + for _ in 0..5 { + if let Some(mut _x) = opt {} + //~^ ERROR: use of moved value + } +} diff --git a/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr new file mode 100644 index 000000000..55948afca --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr @@ -0,0 +1,15 @@ +error[E0382]: use of moved value + --> $DIR/move-in-pattern-mut-in-loop.rs:7:21 + | +LL | if let Some(mut _x) = opt {} + | ^^^^^^ value moved here, in previous iteration of loop + | + = note: move occurs because value has type `&mut i32`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let Some(ref mut _x) = opt {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/move-in-pattern-mut.rs b/tests/ui/borrowck/move-in-pattern-mut.rs new file mode 100644 index 000000000..b5c275bf2 --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern-mut.rs @@ -0,0 +1,23 @@ +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + +fn main() { + let s = Some(S); + if let Some(mut x) = s { + x = S; + } + foo(s); //~ ERROR use of partially moved value: `s` + let mut e = E::V { s: S }; + let E::V { s: mut x } = e; + x = S; + bar(e); //~ ERROR use of partially moved value: `e` +} diff --git a/tests/ui/borrowck/move-in-pattern-mut.stderr b/tests/ui/borrowck/move-in-pattern-mut.stderr new file mode 100644 index 000000000..dd3471e2c --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern-mut.stderr @@ -0,0 +1,33 @@ +error[E0382]: use of partially moved value: `s` + --> $DIR/move-in-pattern-mut.rs:18:9 + | +LL | if let Some(mut x) = s { + | ----- value partially moved here +... +LL | foo(s); + | ^ value used here after partial move + | + = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let Some(ref mut x) = s { + | +++ + +error[E0382]: use of partially moved value: `e` + --> $DIR/move-in-pattern-mut.rs:22:9 + | +LL | let E::V { s: mut x } = e; + | ----- value partially moved here +LL | x = S; +LL | bar(e); + | ^ value used here after partial move + | + = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let E::V { s: ref mut x } = e; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/move-in-pattern.fixed b/tests/ui/borrowck/move-in-pattern.fixed new file mode 100644 index 000000000..145893d33 --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern.fixed @@ -0,0 +1,24 @@ +// run-rustfix +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + +fn main() { + let s = Some(S); + if let Some(ref x) = s { + let _ = x; + } + foo(s); //~ ERROR use of partially moved value: `s` + let e = E::V { s: S }; + let E::V { s: ref x } = e; + let _ = x; + bar(e); //~ ERROR use of partially moved value: `e` +} diff --git a/tests/ui/borrowck/move-in-pattern.rs b/tests/ui/borrowck/move-in-pattern.rs new file mode 100644 index 000000000..14851d0f6 --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern.rs @@ -0,0 +1,24 @@ +// run-rustfix +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + +fn main() { + let s = Some(S); + if let Some(x) = s { + let _ = x; + } + foo(s); //~ ERROR use of partially moved value: `s` + let e = E::V { s: S }; + let E::V { s: x } = e; + let _ = x; + bar(e); //~ ERROR use of partially moved value: `e` +} diff --git a/tests/ui/borrowck/move-in-pattern.stderr b/tests/ui/borrowck/move-in-pattern.stderr new file mode 100644 index 000000000..250acbe59 --- /dev/null +++ b/tests/ui/borrowck/move-in-pattern.stderr @@ -0,0 +1,33 @@ +error[E0382]: use of partially moved value: `s` + --> $DIR/move-in-pattern.rs:19:9 + | +LL | if let Some(x) = s { + | - value partially moved here +... +LL | foo(s); + | ^ value used here after partial move + | + = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let Some(ref x) = s { + | +++ + +error[E0382]: use of partially moved value: `e` + --> $DIR/move-in-pattern.rs:23:9 + | +LL | let E::V { s: x } = e; + | - value partially moved here +LL | let _ = x; +LL | bar(e); + | ^ value used here after partial move + | + = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let E::V { s: ref x } = e; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.rs b/tests/ui/borrowck/move-in-static-initializer-issue-38520.rs new file mode 100644 index 000000000..c2a59a105 --- /dev/null +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.rs @@ -0,0 +1,16 @@ +// Regression test for #38520. Check that moves of `Foo` are not +// permitted as `Foo` is not copy (even in a static/const +// initializer). + +struct Foo(usize); + +const fn get(x: Foo) -> usize { + x.0 +} + +const X: Foo = Foo(22); +static Y: usize = get(*&X); //~ ERROR [E0507] +const Z: usize = get(*&X); //~ ERROR [E0507] + +fn main() { +} diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr new file mode 100644 index 000000000..6619fb42c --- /dev/null +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/move-in-static-initializer-issue-38520.rs:12:23 + | +LL | static Y: usize = get(*&X); + | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/move-in-static-initializer-issue-38520.rs:13:22 + | +LL | const Z: usize = get(*&X); + | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.fixed b/tests/ui/borrowck/mut-borrow-in-loop-2.fixed new file mode 100644 index 000000000..ceeba30a9 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct Events(R); + +struct Other; + +pub trait Trait { + fn handle(value: T) -> Self; +} + +// Blanket impl. (If you comment this out, compiler figures out that it +// is passing an `&mut` to a method that must be expecting an `&mut`, +// and injects an auto-reborrow.) +impl Trait for T where T: From { + fn handle(_: U) -> Self { unimplemented!() } +} + +impl<'a, R> Trait<&'a mut Events> for Other { + fn handle(_: &'a mut Events) -> Self { unimplemented!() } +} + +fn this_compiles<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(&mut *value); + } +} + +fn this_does_not<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(&mut *value); //~ ERROR use of moved value: `value` + } +} + +fn main() {} diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.rs b/tests/ui/borrowck/mut-borrow-in-loop-2.rs new file mode 100644 index 000000000..d13fb7e56 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct Events(R); + +struct Other; + +pub trait Trait { + fn handle(value: T) -> Self; +} + +// Blanket impl. (If you comment this out, compiler figures out that it +// is passing an `&mut` to a method that must be expecting an `&mut`, +// and injects an auto-reborrow.) +impl Trait for T where T: From { + fn handle(_: U) -> Self { unimplemented!() } +} + +impl<'a, R> Trait<&'a mut Events> for Other { + fn handle(_: &'a mut Events) -> Self { unimplemented!() } +} + +fn this_compiles<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(&mut *value); + } +} + +fn this_does_not<'a, R>(value: &'a mut Events) { + for _ in 0..3 { + Other::handle(value); //~ ERROR use of moved value: `value` + } +} + +fn main() {} diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr new file mode 100644 index 000000000..74e7067c9 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -0,0 +1,25 @@ +error[E0382]: use of moved value: `value` + --> $DIR/mut-borrow-in-loop-2.rs:31:23 + | +LL | fn this_does_not<'a, R>(value: &'a mut Events) { + | ----- move occurs because `value` has type `&mut Events`, which does not implement the `Copy` trait +LL | for _ in 0..3 { + | ------------- inside of this loop +LL | Other::handle(value); + | ^^^^^ value moved here, in previous iteration of loop + | +note: consider changing this parameter type in function `handle` to borrow instead if owning the value isn't necessary + --> $DIR/mut-borrow-in-loop-2.rs:9:22 + | +LL | fn handle(value: T) -> Self; + | ------ ^ this parameter takes ownership of the value + | | + | in this function +help: consider creating a fresh reborrow of `value` here + | +LL | Other::handle(&mut *value); + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/mut-borrow-in-loop.rs b/tests/ui/borrowck/mut-borrow-in-loop.rs new file mode 100644 index 000000000..22667906e --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-in-loop.rs @@ -0,0 +1,29 @@ +// produce special borrowck message inside all kinds of loops + +struct FuncWrapper<'a, T : 'a> { + func : fn(&'a mut T) -> () +} + +impl<'a, T : 'a> FuncWrapper<'a, T> { + fn in_loop(self, arg : &'a mut T) { + loop { + (self.func)(arg) //~ ERROR cannot borrow + } + } + + fn in_while(self, arg : &'a mut T) { + while true { //~ WARN denote infinite loops with + (self.func)(arg) //~ ERROR cannot borrow + } + } + + fn in_for(self, arg : &'a mut T) { + let v : Vec<()> = vec![]; + for _ in v.iter() { + (self.func)(arg) //~ ERROR cannot borrow + } + } +} + +fn main() { +} diff --git a/tests/ui/borrowck/mut-borrow-in-loop.stderr b/tests/ui/borrowck/mut-borrow-in-loop.stderr new file mode 100644 index 000000000..b621694a5 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-in-loop.stderr @@ -0,0 +1,47 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/mut-borrow-in-loop.rs:15:9 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0499]: cannot borrow `*arg` as mutable more than once at a time + --> $DIR/mut-borrow-in-loop.rs:10:25 + | +LL | impl<'a, T : 'a> FuncWrapper<'a, T> { + | -- lifetime `'a` defined here +... +LL | (self.func)(arg) + | ------------^^^- + | | | + | | `*arg` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*arg` is borrowed for `'a` + +error[E0499]: cannot borrow `*arg` as mutable more than once at a time + --> $DIR/mut-borrow-in-loop.rs:16:25 + | +LL | impl<'a, T : 'a> FuncWrapper<'a, T> { + | -- lifetime `'a` defined here +... +LL | (self.func)(arg) + | ------------^^^- + | | | + | | `*arg` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*arg` is borrowed for `'a` + +error[E0499]: cannot borrow `*arg` as mutable more than once at a time + --> $DIR/mut-borrow-in-loop.rs:23:25 + | +LL | impl<'a, T : 'a> FuncWrapper<'a, T> { + | -- lifetime `'a` defined here +... +LL | (self.func)(arg) + | ------------^^^- + | | | + | | `*arg` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*arg` is borrowed for `'a` + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.rs b/tests/ui/borrowck/mut-borrow-of-mut-ref.rs new file mode 100644 index 000000000..477a2aa48 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.rs @@ -0,0 +1,36 @@ +// Suggest not mutably borrowing a mutable reference +#![crate_type = "rlib"] + +pub fn f(b: &mut i32) { + //~^ ERROR cannot borrow + //~| NOTE not mutable + //~| NOTE the binding is already a mutable borrow + h(&mut b); + //~^ NOTE cannot borrow as mutable + //~| HELP try removing `&mut` here + g(&mut &mut b); + //~^ NOTE cannot borrow as mutable + //~| HELP try removing `&mut` here +} + +pub fn g(b: &mut i32) { //~ NOTE the binding is already a mutable borrow + h(&mut &mut b); + //~^ ERROR cannot borrow + //~| NOTE cannot borrow as mutable + //~| HELP try removing `&mut` here +} + +pub fn h(_: &mut i32) {} + +trait Foo { + fn bar(&mut self); +} + +impl Foo for &mut String { + fn bar(&mut self) {} +} + +pub fn baz(f: &mut String) { //~ HELP consider making the binding mutable + f.bar(); //~ ERROR cannot borrow `f` as mutable, as it is not declared as mutable + //~^ NOTE cannot borrow as mutable +} diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr b/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr new file mode 100644 index 000000000..c6f75b1c0 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr @@ -0,0 +1,59 @@ +error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable + --> $DIR/mut-borrow-of-mut-ref.rs:4:10 + | +LL | pub fn f(b: &mut i32) { + | ^ not mutable +... +LL | h(&mut b); + | ------ cannot borrow as mutable +... +LL | g(&mut &mut b); + | ------ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/mut-borrow-of-mut-ref.rs:4:13 + | +LL | pub fn f(b: &mut i32) { + | ^^^^^^^^ +help: try removing `&mut` here + | +LL - h(&mut b); +LL + h(b); + | +help: try removing `&mut` here + | +LL - g(&mut &mut b); +LL + g(&mut b); + | + +error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable + --> $DIR/mut-borrow-of-mut-ref.rs:17:12 + | +LL | h(&mut &mut b); + | ^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/mut-borrow-of-mut-ref.rs:16:13 + | +LL | pub fn g(b: &mut i32) { + | ^^^^^^^^ +help: try removing `&mut` here + | +LL - h(&mut &mut b); +LL + h(&mut b); + | + +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/mut-borrow-of-mut-ref.rs:34:5 + | +LL | f.bar(); + | ^^^^^^^ cannot borrow as mutable + | +help: consider making the binding mutable + | +LL | pub fn baz(mut f: &mut String) { + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/mut-borrow-outside-loop.rs b/tests/ui/borrowck/mut-borrow-outside-loop.rs new file mode 100644 index 000000000..c02bfbf87 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-outside-loop.rs @@ -0,0 +1,22 @@ +// ensure borrowck messages are correct outside special case +#![feature(rustc_attrs)] +fn main() { #![rustc_error] // rust-lang/rust#49855 + let mut void = (); + + let first = &mut void; + let second = &mut void; //~ ERROR cannot borrow + first.use_mut(); + second.use_mut(); + + loop { + let mut inner_void = (); + + let inner_first = &mut inner_void; + let inner_second = &mut inner_void; //~ ERROR cannot borrow + inner_second.use_mut(); + inner_first.use_mut(); + } +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/borrowck/mut-borrow-outside-loop.stderr b/tests/ui/borrowck/mut-borrow-outside-loop.stderr new file mode 100644 index 000000000..e6895b27f --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-outside-loop.stderr @@ -0,0 +1,24 @@ +error[E0499]: cannot borrow `void` as mutable more than once at a time + --> $DIR/mut-borrow-outside-loop.rs:7:18 + | +LL | let first = &mut void; + | --------- first mutable borrow occurs here +LL | let second = &mut void; + | ^^^^^^^^^ second mutable borrow occurs here +LL | first.use_mut(); + | --------------- first borrow later used here + +error[E0499]: cannot borrow `inner_void` as mutable more than once at a time + --> $DIR/mut-borrow-outside-loop.rs:15:28 + | +LL | let inner_first = &mut inner_void; + | --------------- first mutable borrow occurs here +LL | let inner_second = &mut inner_void; + | ^^^^^^^^^^^^^^^ second mutable borrow occurs here +LL | inner_second.use_mut(); +LL | inner_first.use_mut(); + | --------------------- first borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/mutability-errors.rs b/tests/ui/borrowck/mutability-errors.rs new file mode 100644 index 000000000..82116425f --- /dev/null +++ b/tests/ui/borrowck/mutability-errors.rs @@ -0,0 +1,82 @@ +// All the possible mutability error cases. + +#![allow(unused)] + +type MakeRef = fn() -> &'static (i32,); +type MakePtr = fn() -> *const (i32,); + +fn named_ref(x: &(i32,)) { + *x = (1,); //~ ERROR + x.0 = 1; //~ ERROR + &mut *x; //~ ERROR + &mut x.0; //~ ERROR +} + +fn unnamed_ref(f: MakeRef) { + *f() = (1,); //~ ERROR + f().0 = 1; //~ ERROR + &mut *f(); //~ ERROR + &mut f().0; //~ ERROR +} + +unsafe fn named_ptr(x: *const (i32,)) { + *x = (1,); //~ ERROR + (*x).0 = 1; //~ ERROR + &mut *x; //~ ERROR + &mut (*x).0; //~ ERROR +} + +unsafe fn unnamed_ptr(f: MakePtr) { + *f() = (1,); //~ ERROR + (*f()).0 = 1; //~ ERROR + &mut *f(); //~ ERROR + &mut (*f()).0; //~ ERROR +} + +fn fn_ref(f: F) -> F { f } + +fn ref_closure(mut x: (i32,)) { + fn_ref(|| { + x = (1,); //~ ERROR + x.0 = 1; //~ ERROR + &mut x; //~ ERROR + &mut x.0; //~ ERROR + }); + fn_ref(move || { + x = (1,); //~ ERROR + x.0 = 1; //~ ERROR + &mut x; //~ ERROR + &mut x.0; //~ ERROR + }); +} + +fn imm_local(x: (i32,)) { //~ ERROR + &mut x; + &mut x.0; +} + +fn imm_capture(x: (i32,)) { + || { + x = (1,); //~ ERROR + x.0 = 1; //~ ERROR + &mut x; //~ ERROR + &mut x.0; //~ ERROR + }; + move || { + x = (1,); //~ ERROR + x.0 = 1; //~ ERROR + &mut x; //~ ERROR + &mut x.0; //~ ERROR + }; +} + +static X: (i32,) = (0,); + +fn imm_static() { + X = (1,); //~ ERROR + X.0 = 1; //~ ERROR + &mut X; //~ ERROR + &mut X.0; //~ ERROR +} + +fn main() {} diff --git a/tests/ui/borrowck/mutability-errors.stderr b/tests/ui/borrowck/mutability-errors.stderr new file mode 100644 index 000000000..d7c602718 --- /dev/null +++ b/tests/ui/borrowck/mutability-errors.stderr @@ -0,0 +1,361 @@ +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/mutability-errors.rs:9:5 + | +LL | *x = (1,); + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to `x.0`, which is behind a `&` reference + --> $DIR/mutability-errors.rs:10:5 + | +LL | x.0 = 1; + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/mutability-errors.rs:11:5 + | +LL | &mut *x; + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `&` reference + --> $DIR/mutability-errors.rs:12:5 + | +LL | &mut x.0; + | ^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to data in a `&` reference + --> $DIR/mutability-errors.rs:16:5 + | +LL | *f() = (1,); + | ^^^^^^^^^^^ cannot assign + +error[E0594]: cannot assign to data in a `&` reference + --> $DIR/mutability-errors.rs:17:5 + | +LL | f().0 = 1; + | ^^^^^^^^^ cannot assign + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/mutability-errors.rs:18:5 + | +LL | &mut *f(); + | ^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/mutability-errors.rs:19:5 + | +LL | &mut f().0; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer + --> $DIR/mutability-errors.rs:23:5 + | +LL | *x = (1,); + | ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer + --> $DIR/mutability-errors.rs:24:5 + | +LL | (*x).0 = 1; + | ^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer + --> $DIR/mutability-errors.rs:25:5 + | +LL | &mut *x; + | ^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer + --> $DIR/mutability-errors.rs:26:5 + | +LL | &mut (*x).0; + | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to data in a `*const` pointer + --> $DIR/mutability-errors.rs:30:5 + | +LL | *f() = (1,); + | ^^^^^^^^^^^ cannot assign + +error[E0594]: cannot assign to data in a `*const` pointer + --> $DIR/mutability-errors.rs:31:5 + | +LL | (*f()).0 = 1; + | ^^^^^^^^^^^^ cannot assign + +error[E0596]: cannot borrow data in a `*const` pointer as mutable + --> $DIR/mutability-errors.rs:32:5 + | +LL | &mut *f(); + | ^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `*const` pointer as mutable + --> $DIR/mutability-errors.rs:33:5 + | +LL | &mut (*f()).0; + | ^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/mutability-errors.rs:40:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); + | ^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables + --> $DIR/mutability-errors.rs:41:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); +LL | x.0 = 1; + | ^^^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/mutability-errors.rs:42:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +... +LL | &mut x; + | ^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables + --> $DIR/mutability-errors.rs:43:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +... +LL | &mut x.0; + | ^^^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/mutability-errors.rs:46:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); + | ^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables + --> $DIR/mutability-errors.rs:47:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | x = (1,); +LL | x.0 = 1; + | ^^^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/mutability-errors.rs:48:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +... +LL | &mut x; + | ^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables + --> $DIR/mutability-errors.rs:49:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +... +LL | &mut x.0; + | ^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/mutability-errors.rs:53:14 + | +LL | fn imm_local(x: (i32,)) { + | ^ not mutable +LL | &mut x; + | ------ cannot borrow as mutable +LL | &mut x.0; + | -------- cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn imm_local(mut x: (i32,)) { + | +++ + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/mutability-errors.rs:60:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +LL | || { +LL | x = (1,); + | ^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable + --> $DIR/mutability-errors.rs:61:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x.0 = 1; + | ^^^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/mutability-errors.rs:62:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | &mut x; + | ^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable + --> $DIR/mutability-errors.rs:63:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | &mut x.0; + | ^^^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/mutability-errors.rs:66:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x = (1,); + | ^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable + --> $DIR/mutability-errors.rs:67:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x.0 = 1; + | ^^^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/mutability-errors.rs:68:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | &mut x; + | ^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable + --> $DIR/mutability-errors.rs:69:9 + | +LL | fn imm_capture(x: (i32,)) { + | - help: consider changing this to be mutable: `mut x` +... +LL | &mut x.0; + | ^^^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to immutable static item `X` + --> $DIR/mutability-errors.rs:76:5 + | +LL | X = (1,); + | ^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `X.0`, as `X` is an immutable static item + --> $DIR/mutability-errors.rs:77:5 + | +LL | X.0 = 1; + | ^^^^^^^ cannot assign + +error[E0596]: cannot borrow immutable static item `X` as mutable + --> $DIR/mutability-errors.rs:78:5 + | +LL | &mut X; + | ^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item + --> $DIR/mutability-errors.rs:79:5 + | +LL | &mut X.0; + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to 37 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/borrowck/or-patterns.rs b/tests/ui/borrowck/or-patterns.rs new file mode 100644 index 000000000..aeab3b92e --- /dev/null +++ b/tests/ui/borrowck/or-patterns.rs @@ -0,0 +1,62 @@ +// Test that borrow check considers all choices in an or pattern, even the +// unreachable ones. + +fn or_pattern_moves_all(x: ((String, String),)) { + match x { + ((y, _) | (_, y),) => (), + } + &x.0 .0; + //~^ ERROR borrow of moved value + &x.0 .1; + //~^ ERROR borrow of moved value +} + +fn or_pattern_borrows_all(mut x: ((String, String),)) { + let r = match x { + ((ref y, _) | (_, ref y),) => y, + }; + &mut x.0 .0; + //~^ ERROR cannot borrow + &mut x.0 .1; + //~^ ERROR cannot borrow + drop(r); +} + +fn or_pattern_borrows_all_mut(mut x: ((String, String),)) { + let r = match x { + ((ref mut y, _) | (_, ref mut y),) => y, + }; + &x.0 .0; + //~^ ERROR cannot borrow + &x.0 .1; + //~^ ERROR cannot borrow + drop(r); +} + +fn let_or_pattern_moves_all(x: ((String, String),)) { + let ((y, _) | (_, y),) = x; + &x.0 .0; + //~^ ERROR borrow of moved value + &x.0 .1; + //~^ ERROR borrow of moved value +} + +fn let_or_pattern_borrows_all(mut x: ((String, String),)) { + let ((ref r, _) | (_, ref r),) = x; + &mut x.0 .0; + //~^ ERROR cannot borrow + &mut x.0 .1; + //~^ ERROR cannot borrow + drop(r); +} + +fn let_or_pattern_borrows_all_mut(mut x: ((String, String),)) { + let ((ref mut r, _) | (_, ref mut r),) = x; + &x.0 .0; + //~^ ERROR cannot borrow + &x.0 .1; + //~^ ERROR cannot borrow + drop(r); +} + +fn main() {} diff --git a/tests/ui/borrowck/or-patterns.stderr b/tests/ui/borrowck/or-patterns.stderr new file mode 100644 index 000000000..9501798bb --- /dev/null +++ b/tests/ui/borrowck/or-patterns.stderr @@ -0,0 +1,157 @@ +error[E0382]: borrow of moved value: `x.0.0` + --> $DIR/or-patterns.rs:8:5 + | +LL | ((y, _) | (_, y),) => (), + | - value moved here +LL | } +LL | &x.0 .0; + | ^^^^^^^ value borrowed here after move + | + = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ((ref y, _) | (_, y),) => (), + | +++ + +error[E0382]: borrow of moved value: `x.0.1` + --> $DIR/or-patterns.rs:10:5 + | +LL | ((y, _) | (_, y),) => (), + | - value moved here +... +LL | &x.0 .1; + | ^^^^^^^ value borrowed here after move + | + = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ((y, _) | (_, ref y),) => (), + | +++ + +error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable + --> $DIR/or-patterns.rs:18:5 + | +LL | ((ref y, _) | (_, ref y),) => y, + | ----- immutable borrow occurs here +LL | }; +LL | &mut x.0 .0; + | ^^^^^^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable + --> $DIR/or-patterns.rs:20:5 + | +LL | ((ref y, _) | (_, ref y),) => y, + | ----- immutable borrow occurs here +... +LL | &mut x.0 .1; + | ^^^^^^^^^^^ mutable borrow occurs here +LL | +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable + --> $DIR/or-patterns.rs:29:5 + | +LL | ((ref mut y, _) | (_, ref mut y),) => y, + | --------- mutable borrow occurs here +LL | }; +LL | &x.0 .0; + | ^^^^^^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable + --> $DIR/or-patterns.rs:31:5 + | +LL | ((ref mut y, _) | (_, ref mut y),) => y, + | --------- mutable borrow occurs here +... +LL | &x.0 .1; + | ^^^^^^^ immutable borrow occurs here +LL | +LL | drop(r); + | - mutable borrow later used here + +error[E0382]: borrow of moved value: `x.0.0` + --> $DIR/or-patterns.rs:38:5 + | +LL | let ((y, _) | (_, y),) = x; + | - value moved here +LL | &x.0 .0; + | ^^^^^^^ value borrowed here after move + | + = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ((ref y, _) | (_, y),) = x; + | +++ + +error[E0382]: borrow of moved value: `x.0.1` + --> $DIR/or-patterns.rs:40:5 + | +LL | let ((y, _) | (_, y),) = x; + | - value moved here +... +LL | &x.0 .1; + | ^^^^^^^ value borrowed here after move + | + = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ((y, _) | (_, ref y),) = x; + | +++ + +error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable + --> $DIR/or-patterns.rs:46:5 + | +LL | let ((ref r, _) | (_, ref r),) = x; + | ----- immutable borrow occurs here +LL | &mut x.0 .0; + | ^^^^^^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x.0.1` as mutable because it is also borrowed as immutable + --> $DIR/or-patterns.rs:48:5 + | +LL | let ((ref r, _) | (_, ref r),) = x; + | ----- immutable borrow occurs here +... +LL | &mut x.0 .1; + | ^^^^^^^^^^^ mutable borrow occurs here +LL | +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x.0.0` as immutable because it is also borrowed as mutable + --> $DIR/or-patterns.rs:55:5 + | +LL | let ((ref mut r, _) | (_, ref mut r),) = x; + | --------- mutable borrow occurs here +LL | &x.0 .0; + | ^^^^^^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x.0.1` as immutable because it is also borrowed as mutable + --> $DIR/or-patterns.rs:57:5 + | +LL | let ((ref mut r, _) | (_, ref mut r),) = x; + | --------- mutable borrow occurs here +... +LL | &x.0 .1; + | ^^^^^^^ immutable borrow occurs here +LL | +LL | drop(r); + | - mutable borrow later used here + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs b/tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs new file mode 100644 index 000000000..3576734de --- /dev/null +++ b/tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs @@ -0,0 +1,31 @@ +// Test that we fail to promote the constant here which has a `ref +// mut` borrow. + +fn gimme_static_mut_let() -> &'static mut u32 { + let ref mut x = 1234543; + x //~ ERROR +} + +fn gimme_static_mut_let_nested() -> &'static mut u32 { + let (ref mut x, ) = (1234543, ); + x //~ ERROR +} + +fn gimme_static_mut_match() -> &'static mut u32 { + match 1234543 { //~ ERROR + ref mut x => x + } +} + +fn gimme_static_mut_match_nested() -> &'static mut u32 { + match (123443,) { //~ ERROR + (ref mut x,) => x, + } +} + +fn gimme_static_mut_ampersand() -> &'static mut u32 { + &mut 1234543 //~ ERROR +} + +fn main() { +} diff --git a/tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr b/tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr new file mode 100644 index 000000000..60af41237 --- /dev/null +++ b/tests/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr @@ -0,0 +1,50 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:6:5 + | +LL | let ref mut x = 1234543; + | ------- temporary value created here +LL | x + | ^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:11:5 + | +LL | let (ref mut x, ) = (1234543, ); + | ----------- temporary value created here +LL | x + | ^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:5 + | +LL | match 1234543 { + | ^ ------- temporary value created here + | _____| + | | +LL | | ref mut x => x +LL | | } + | |_____^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:21:5 + | +LL | match (123443,) { + | ^ --------- temporary value created here + | _____| + | | +LL | | (ref mut x,) => x, +LL | | } + | |_____^ returns a value referencing data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:27:5 + | +LL | &mut 1234543 + | ^^^^^------- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/reassignment_immutable_fields.rs b/tests/ui/borrowck/reassignment_immutable_fields.rs new file mode 100644 index 000000000..fd2ab62a4 --- /dev/null +++ b/tests/ui/borrowck/reassignment_immutable_fields.rs @@ -0,0 +1,20 @@ +// This test is currently disallowed, but we hope someday to support it. +// +// FIXME(#21232) + +fn assign_both_fields_and_use() { + let x: (u32, u32); + x.0 = 1; //~ ERROR + x.1 = 22; + drop(x.0); + drop(x.1); +} + +fn assign_both_fields_the_use_var() { + let x: (u32, u32); + x.0 = 1; //~ ERROR + x.1 = 22; + drop(x); +} + +fn main() { } diff --git a/tests/ui/borrowck/reassignment_immutable_fields.stderr b/tests/ui/borrowck/reassignment_immutable_fields.stderr new file mode 100644 index 000000000..e6b25573e --- /dev/null +++ b/tests/ui/borrowck/reassignment_immutable_fields.stderr @@ -0,0 +1,23 @@ +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/reassignment_immutable_fields.rs:7:5 + | +LL | let x: (u32, u32); + | - binding declared here but left uninitialized +LL | x.0 = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/reassignment_immutable_fields.rs:15:5 + | +LL | let x: (u32, u32); + | - binding declared here but left uninitialized +LL | x.0 = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/reassignment_immutable_fields_overlapping.rs b/tests/ui/borrowck/reassignment_immutable_fields_overlapping.rs new file mode 100644 index 000000000..d7aad6c01 --- /dev/null +++ b/tests/ui/borrowck/reassignment_immutable_fields_overlapping.rs @@ -0,0 +1,16 @@ +// This should never be allowed -- `foo.a` and `foo.b` are +// overlapping, so since `x` is not `mut` we should not permit +// reassignment. + +union Foo { + a: u32, + b: u32, +} + +unsafe fn overlapping_fields() { + let x: Foo; + x.a = 1; //~ ERROR + x.b = 22; //~ ERROR +} + +fn main() { } diff --git a/tests/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/tests/ui/borrowck/reassignment_immutable_fields_overlapping.stderr new file mode 100644 index 000000000..81e5bc45d --- /dev/null +++ b/tests/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -0,0 +1,25 @@ +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5 + | +LL | let x: Foo; + | - binding declared here but left uninitialized +LL | x.a = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable + --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5 + | +LL | x.b = 22; + | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut x: Foo; + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0381, E0594. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/reassignment_immutable_fields_twice.rs b/tests/ui/borrowck/reassignment_immutable_fields_twice.rs new file mode 100644 index 000000000..2775a54c8 --- /dev/null +++ b/tests/ui/borrowck/reassignment_immutable_fields_twice.rs @@ -0,0 +1,17 @@ +// This should never be allowed -- since `x` is not `mut`, so `x.0` +// cannot be assigned twice. + +fn var_then_field() { + let x: (u32, u32); + x = (22, 44); + x.0 = 1; //~ ERROR +} + +fn same_field_twice() { + let x: (u32, u32); + x.0 = 1; //~ ERROR + x.0 = 22; + x.1 = 44; +} + +fn main() { } diff --git a/tests/ui/borrowck/reassignment_immutable_fields_twice.stderr b/tests/ui/borrowck/reassignment_immutable_fields_twice.stderr new file mode 100644 index 000000000..ba0457809 --- /dev/null +++ b/tests/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -0,0 +1,25 @@ +error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable + --> $DIR/reassignment_immutable_fields_twice.rs:7:5 + | +LL | x.0 = 1; + | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut x: (u32, u32); + | +++ + +error[E0381]: partially assigned binding `x` isn't fully initialized + --> $DIR/reassignment_immutable_fields_twice.rs:12:5 + | +LL | let x: (u32, u32); + | - binding declared here but left uninitialized +LL | x.0 = 1; + | ^^^^^^^ `x` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0381, E0594. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs new file mode 100644 index 000000000..31eba0740 --- /dev/null +++ b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs @@ -0,0 +1,26 @@ +// Tests the suggestion to reborrow the first move site +// when we move then borrow a `&mut` ref. + +struct State; + +impl IntoIterator for &mut State { + type IntoIter = std::vec::IntoIter<()>; + type Item = (); + + fn into_iter(self) -> Self::IntoIter { + vec![].into_iter() + } +} + +fn once(f: impl FnOnce()) {} + +fn fill_memory_blocks_mt(state: &mut State) { + for _ in state {} + //~^ HELP consider creating a fresh reborrow of `state` here + fill_segment(state); + //~^ ERROR borrow of moved value: `state` +} + +fn fill_segment(state: &mut State) {} + +fn main() {} diff --git a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr new file mode 100644 index 000000000..ecd916a59 --- /dev/null +++ b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr @@ -0,0 +1,21 @@ +error[E0382]: borrow of moved value: `state` + --> $DIR/reborrow-sugg-move-then-borrow.rs:20:18 + | +LL | fn fill_memory_blocks_mt(state: &mut State) { + | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait +LL | for _ in state {} + | ----- `state` moved due to this implicit call to `.into_iter()` +LL | +LL | fill_segment(state); + | ^^^^^ value borrowed here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `state` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider creating a fresh reborrow of `state` here + | +LL | for _ in &mut *state {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs new file mode 100644 index 000000000..141ad5bd2 --- /dev/null +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.rs @@ -0,0 +1,54 @@ +// Check that explicit region bounds are allowed on the various +// nominal types (but not on other types) and that they are type +// checked. + +struct Inv<'a> { // invariant w/r/t 'a + x: &'a mut &'a isize +} + +pub trait Foo<'a, 't> { + fn no_bound<'b>(self, b: Inv<'b>); + fn has_bound<'b:'a>(self, b: Inv<'b>); + fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); +} + +impl<'a, 't> Foo<'a, 't> for &'a isize { + fn no_bound<'b:'a>(self, b: Inv<'b>) { + //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match + } + + fn has_bound<'b>(self, b: Inv<'b>) { + //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match + } + + fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + //~^ ERROR method not compatible with trait + //~| ERROR method not compatible with trait + // + // Note: This is a terrible error message. It is caused + // because, in the trait, 'b is early bound, and in the impl, + // 'c is early bound, so -- after substitution -- the + // lifetimes themselves look isomorphic. We fail because the + // lifetimes that appear in the types are in the wrong + // order. This should really be fixed by keeping more + // information about the lifetime declarations in the trait so + // that we can compare better to the impl, even in cross-crate + // cases. + } + + fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { + //~^ ERROR lifetime parameters or bounds on method `wrong_bound2` do not match the trait + } + + fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) { + } + + fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { + //~^ ERROR E0276 + } +} + +fn main() { } diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr new file mode 100644 index 000000000..930fea915 --- /dev/null +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -0,0 +1,78 @@ +error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:19:16 + | +LL | fn no_bound<'b>(self, b: Inv<'b>); + | ---- lifetimes in impl do not match this method in trait +... +LL | fn no_bound<'b:'a>(self, b: Inv<'b>) { + | ^^^^^^^ lifetimes do not match method in trait + +error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:23:17 + | +LL | fn has_bound<'b:'a>(self, b: Inv<'b>); + | ------- lifetimes in impl do not match this method in trait +... +LL | fn has_bound<'b>(self, b: Inv<'b>) { + | ^^^^ lifetimes do not match method in trait + +error[E0308]: method not compatible with trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5 + | +LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` + found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` +note: the lifetime `'c` as defined here... + --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + | +LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^ +note: ...does not necessarily outlive the lifetime `'c` as defined here + --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + | +LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^ + +error[E0308]: method not compatible with trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:27:5 + | +LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` + found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` +note: the lifetime `'c` as defined here... + --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + | +LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^ +note: ...does not necessarily outlive the lifetime `'c` as defined here + --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 + | +LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { + | ^^ + +error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration + --> $DIR/regions-bound-missing-bound-in-impl.rs:42:20 + | +LL | fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>); + | ---------------- lifetimes in impl do not match this method in trait +... +LL | fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) { + | ^ lifetimes do not match method in trait + +error[E0276]: impl has stricter requirements than trait + --> $DIR/regions-bound-missing-bound-in-impl.rs:49:26 + | +LL | fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>); + | ------------------------------------------------------- definition of `another_bound` from trait +... +LL | fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) { + | ^^ impl has extra requirement `'x: 't` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0195, E0276, E0308. +For more information about an error, try `rustc --explain E0195`. diff --git a/tests/ui/borrowck/regions-escape-bound-fn-2.rs b/tests/ui/borrowck/regions-escape-bound-fn-2.rs new file mode 100644 index 000000000..0e98d98cf --- /dev/null +++ b/tests/ui/borrowck/regions-escape-bound-fn-2.rs @@ -0,0 +1,13 @@ +fn with_int(f: F) +where + F: FnOnce(&isize), +{ + let x = 3; + f(&x); +} + +fn main() { + let mut x = None; + with_int(|y| x = Some(y)); + //~^ ERROR borrowed data escapes outside of closure +} diff --git a/tests/ui/borrowck/regions-escape-bound-fn-2.stderr b/tests/ui/borrowck/regions-escape-bound-fn-2.stderr new file mode 100644 index 000000000..14393bc8e --- /dev/null +++ b/tests/ui/borrowck/regions-escape-bound-fn-2.stderr @@ -0,0 +1,13 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/regions-escape-bound-fn-2.rs:11:18 + | +LL | let mut x = None; + | ----- `x` declared here, outside of the closure body +LL | with_int(|y| x = Some(y)); + | - ^^^^^^^^^^^ `y` escapes the closure body here + | | + | `y` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/regions-escape-bound-fn.rs b/tests/ui/borrowck/regions-escape-bound-fn.rs new file mode 100644 index 000000000..f896ae7bd --- /dev/null +++ b/tests/ui/borrowck/regions-escape-bound-fn.rs @@ -0,0 +1,13 @@ +fn with_int(f: F) +where + F: FnOnce(&isize), +{ + let x = 3; + f(&x); +} + +fn main() { + let mut x: Option<&isize> = None; + with_int(|y| x = Some(y)); + //~^ ERROR borrowed data escapes outside of closure +} diff --git a/tests/ui/borrowck/regions-escape-bound-fn.stderr b/tests/ui/borrowck/regions-escape-bound-fn.stderr new file mode 100644 index 000000000..a23fdacde --- /dev/null +++ b/tests/ui/borrowck/regions-escape-bound-fn.stderr @@ -0,0 +1,13 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/regions-escape-bound-fn.rs:11:18 + | +LL | let mut x: Option<&isize> = None; + | ----- `x` declared here, outside of the closure body +LL | with_int(|y| x = Some(y)); + | - ^^^^^^^^^^^ `y` escapes the closure body here + | | + | `y` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/regions-escape-unboxed-closure.rs b/tests/ui/borrowck/regions-escape-unboxed-closure.rs new file mode 100644 index 000000000..f01e47122 --- /dev/null +++ b/tests/ui/borrowck/regions-escape-unboxed-closure.rs @@ -0,0 +1,7 @@ +fn with_int(f: &mut dyn FnMut(&isize)) {} + +fn main() { + let mut x: Option<&isize> = None; + with_int(&mut |y| x = Some(y)); + //~^ ERROR borrowed data escapes outside of closure +} diff --git a/tests/ui/borrowck/regions-escape-unboxed-closure.stderr b/tests/ui/borrowck/regions-escape-unboxed-closure.stderr new file mode 100644 index 000000000..153f77c89 --- /dev/null +++ b/tests/ui/borrowck/regions-escape-unboxed-closure.stderr @@ -0,0 +1,13 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/regions-escape-unboxed-closure.rs:5:23 + | +LL | let mut x: Option<&isize> = None; + | ----- `x` declared here, outside of the closure body +LL | with_int(&mut |y| x = Some(y)); + | - ^^^^^^^^^^^ `y` escapes the closure body here + | | + | `y` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/borrowck/return-local-binding-from-desugaring.rs b/tests/ui/borrowck/return-local-binding-from-desugaring.rs new file mode 100644 index 000000000..c6643edf5 --- /dev/null +++ b/tests/ui/borrowck/return-local-binding-from-desugaring.rs @@ -0,0 +1,33 @@ +// To avoid leaking the names of local bindings from expressions like for loops, #60984 +// explicitly ignored them, but an assertion that `LocalKind::Var` *must* have a name would +// trigger an ICE. Before this change, this file's output would be: +// ``` +// error[E0515]: cannot return value referencing local variable `__next` +// --> return-local-binding-from-desugaring.rs:LL:CC +// | +// LL | for ref x in xs { +// | ----- `__next` is borrowed here +// ... +// LL | result +// | ^^^^^^ returns a value referencing data owned by the current function +// ``` +// FIXME: ideally `LocalKind` would carry more information to more accurately explain the problem. + +use std::collections::HashMap; +use std::hash::Hash; + +fn group_by(xs: &mut I, f: F) -> HashMap> +where + I: Iterator, + F: Fn(&I::Item) -> T, + T: Eq + Hash, +{ + let mut result = HashMap::new(); + for ref x in xs { + let key = f(x); + result.entry(key).or_insert(Vec::new()).push(x); + } + result //~ ERROR cannot return value referencing temporary value +} + +fn main() {} diff --git a/tests/ui/borrowck/return-local-binding-from-desugaring.stderr b/tests/ui/borrowck/return-local-binding-from-desugaring.stderr new file mode 100644 index 000000000..9f952542e --- /dev/null +++ b/tests/ui/borrowck/return-local-binding-from-desugaring.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/return-local-binding-from-desugaring.rs:30:5 + | +LL | for ref x in xs { + | -- temporary value created here +... +LL | result + | ^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/borrowck/slice-index-bounds-check-invalidation.rs b/tests/ui/borrowck/slice-index-bounds-check-invalidation.rs new file mode 100644 index 000000000..0e0e3cda6 --- /dev/null +++ b/tests/ui/borrowck/slice-index-bounds-check-invalidation.rs @@ -0,0 +1,82 @@ +// Test that we error if a slice is modified after it has been bounds checked +// and before we actually index it. + +fn modify_before_assert_slice_slice(x: &[&[i32]]) -> i32 { + let mut x = x; + let z: &[i32] = &[1, 2, 3]; + let y: &[&[i32]] = &[z]; + x[{ x = y; 0 }][2] // OK we haven't checked any bounds before we index `x`. +} + +fn modify_before_assert_array_slice(x: &[&[i32]; 3]) -> i32 { + let mut x = x; + let z: &[i32] = &[1, 2, 3]; + let y: &[&[i32]; 3] = &[z, z, z]; + x[{ x = y; 0 }][2] // OK we haven't checked any bounds before we index `x`. +} + +fn modify_before_assert_slice_array(x: &[&[i32; 3]]) -> i32 { + let mut x = x; + let z: &[i32; 3] = &[1, 2, 3]; + let y: &[&[i32; 3]] = &[z]; + x[{ x = y; 0 }][2] // OK we haven't checked any bounds before we index `x`. +} + +fn modify_before_assert_array_array(x: &[&[i32; 3]; 3]) -> i32 { + let mut x = x; + let z: &[i32; 3] = &[1, 2, 3]; + let y: &[&[i32; 3]; 3] = &[z, z, z]; + x[{ x = y; 0 }][2] // OK we haven't checked any bounds before we index `x`. +} + +fn modify_after_assert_slice_slice(x: &[&[i32]]) -> i32 { + let mut x = x; + let z: &[i32] = &[1, 2, 3]; + let y: &[&[i32]] = &[&z]; + x[1][{ x = y; 2}] //~ ERROR cannot assign `x` in indexing expression +} + +fn modify_after_assert_array_slice(x: &[&[i32]; 1]) -> i32 { + let mut x = x; + let z: &[i32] = &[1, 2, 3]; + let y: &[&[i32]; 1] = &[&z]; + x[0][{ x = y; 2}] // OK cannot invalidate a fixed-size array bounds check +} + +fn modify_after_assert_slice_array(x: &[&[i32; 3]]) -> i32 { + let mut x = x; + let z: &[i32; 3] = &[1, 2, 3]; + let y: &[&[i32; 3]] = &[&z]; + x[1][{ x = y; 2}] //~ ERROR cannot assign `x` in indexing expression +} + +fn modify_after_assert_array_array(x: &[&[i32; 3]; 1]) -> i32 { + let mut x = x; + let z: &[i32; 3] = &[1, 2, 3]; + let y: &[&[i32; 3]; 1] = &[&z]; + x[0][{ x = y; 2}] // OK cannot invalidate a fixed-size array bounds check +} + +fn modify_after_assert_slice_slice_array(x: &[&[[i32; 1]]]) -> i32 { + let mut x = x; + let z: &[[i32; 1]] = &[[1], [2], [3]]; + let y: &[&[[i32; 1]]] = &[&z]; + x[1][{ x = y; 2}][0] //~ ERROR cannot assign `x` in indexing expression +} + +fn modify_after_assert_slice_slice_slice(x: &[&[&[i32]]]) -> i32 { + let mut x = x; + let z: &[&[i32]] = &[&[1], &[2], &[3]]; + let y: &[&[&[i32]]] = &[z]; + x[1][{ x = y; 2}][0] //~ ERROR cannot assign `x` in indexing expression +} + + +fn main() { + println!("{}", modify_after_assert_slice_array(&[&[4, 5, 6], &[9, 10, 11]])); + println!("{}", modify_after_assert_slice_slice(&[&[4, 5, 6], &[9, 10, 11]])); + println!("{}", modify_after_assert_slice_slice_array(&[&[[4], [5], [6]], &[[9], [10], [11]]])); + println!("{}", modify_after_assert_slice_slice_slice( + &[&[&[4], &[5], &[6]], &[&[9], &[10], &[11]]]), + ); +} diff --git a/tests/ui/borrowck/slice-index-bounds-check-invalidation.stderr b/tests/ui/borrowck/slice-index-bounds-check-invalidation.stderr new file mode 100644 index 000000000..f9ed16f19 --- /dev/null +++ b/tests/ui/borrowck/slice-index-bounds-check-invalidation.stderr @@ -0,0 +1,35 @@ +error[E0510]: cannot assign `x` in indexing expression + --> $DIR/slice-index-bounds-check-invalidation.rs:36:12 + | +LL | x[1][{ x = y; 2}] + | ---- ^^^^^ cannot assign + | | + | value is immutable in indexing expression + +error[E0510]: cannot assign `x` in indexing expression + --> $DIR/slice-index-bounds-check-invalidation.rs:50:12 + | +LL | x[1][{ x = y; 2}] + | ---- ^^^^^ cannot assign + | | + | value is immutable in indexing expression + +error[E0510]: cannot assign `x` in indexing expression + --> $DIR/slice-index-bounds-check-invalidation.rs:64:12 + | +LL | x[1][{ x = y; 2}][0] + | ---- ^^^^^ cannot assign + | | + | value is immutable in indexing expression + +error[E0510]: cannot assign `x` in indexing expression + --> $DIR/slice-index-bounds-check-invalidation.rs:71:12 + | +LL | x[1][{ x = y; 2}][0] + | ---- ^^^^^ cannot assign + | | + | value is immutable in indexing expression + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/borrowck/suggest-as-ref-on-mut-closure.rs b/tests/ui/borrowck/suggest-as-ref-on-mut-closure.rs new file mode 100644 index 000000000..1dcf04618 --- /dev/null +++ b/tests/ui/borrowck/suggest-as-ref-on-mut-closure.rs @@ -0,0 +1,16 @@ +// This is not exactly right, yet. + +// Ideally we should be suggesting `as_mut` for the first case, +// and suggesting to change `as_ref` to `as_mut` in the second. + +fn x(cb: &mut Option<&mut dyn FnMut()>) { + cb.map(|cb| cb()); + //~^ ERROR cannot move out of `*cb` which is behind a mutable reference +} + +fn x2(cb: &mut Option<&mut dyn FnMut()>) { + cb.as_ref().map(|cb| cb()); + //~^ ERROR cannot borrow `*cb` as mutable, as it is behind a `&` reference +} + +fn main() {} diff --git a/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr b/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr new file mode 100644 index 000000000..4621d8793 --- /dev/null +++ b/tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr @@ -0,0 +1,25 @@ +error[E0507]: cannot move out of `*cb` which is behind a mutable reference + --> $DIR/suggest-as-ref-on-mut-closure.rs:7:5 + | +LL | cb.map(|cb| cb()); + | ^^^-------------- + | | | + | | `*cb` moved due to this method call + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents + | move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait + | +note: `Option::::map` takes ownership of the receiver `self`, which moves `*cb` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference + --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26 + | +LL | cb.as_ref().map(|cb| cb()); + | -- ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | | + | consider changing this binding's type to be: `&mut &mut dyn FnMut()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0507, E0596. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/suggest-assign-rvalue.rs b/tests/ui/borrowck/suggest-assign-rvalue.rs new file mode 100644 index 000000000..aaca9d47f --- /dev/null +++ b/tests/ui/borrowck/suggest-assign-rvalue.rs @@ -0,0 +1,57 @@ +#![allow(dead_code)] +#![feature(never_type)] + +#[derive(Debug, Default)] +struct Demo {} + +#[derive(Debug)] +struct DemoNoDef {} + +fn apple(_: u32) {} + +fn banana() { + let chaenomeles; + apple(chaenomeles); + //~^ ERROR used binding `chaenomeles` isn't initialized [E0381] +} + +fn main() { + let my_bool: bool = bool::default(); + println!("my_bool: {}", my_bool); + + let my_float: f32; + println!("my_float: {}", my_float); + //~^ ERROR used binding `my_float` isn't initialized + let demo: Demo; + println!("demo: {:?}", demo); + //~^ ERROR used binding `demo` isn't initialized + + let demo_no: DemoNoDef; + println!("demo_no: {:?}", demo_no); + //~^ ERROR used binding `demo_no` isn't initialized + + let arr: [i32; 5]; + println!("arr: {:?}", arr); + //~^ ERROR used binding `arr` isn't initialized + let foo: Vec<&str>; + println!("foo: {:?}", foo); + //~^ ERROR used binding `foo` isn't initialized + + let my_string: String; + println!("my_string: {}", my_string); + //~^ ERROR used binding `my_string` isn't initialized + + let my_int: &i32; + println!("my_int: {}", *my_int); + //~^ ERROR used binding `my_int` isn't initialized + + let hello: &str; + println!("hello: {}", hello); + //~^ ERROR used binding `hello` isn't initialized + + let never: !; + println!("never: {}", never); + //~^ ERROR used binding `never` isn't initialized [E0381] + + banana(); +} diff --git a/tests/ui/borrowck/suggest-assign-rvalue.stderr b/tests/ui/borrowck/suggest-assign-rvalue.stderr new file mode 100644 index 000000000..92acba640 --- /dev/null +++ b/tests/ui/borrowck/suggest-assign-rvalue.stderr @@ -0,0 +1,138 @@ +error[E0381]: used binding `chaenomeles` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:14:11 + | +LL | let chaenomeles; + | ----------- binding declared here but left uninitialized +LL | apple(chaenomeles); + | ^^^^^^^^^^^ `chaenomeles` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let chaenomeles = 0; + | +++ + +error[E0381]: used binding `my_float` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:23:30 + | +LL | let my_float: f32; + | -------- binding declared here but left uninitialized +LL | println!("my_float: {}", my_float); + | ^^^^^^^^ `my_float` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let my_float: f32 = 0.0; + | +++++ + +error[E0381]: used binding `demo` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:26:28 + | +LL | let demo: Demo; + | ---- binding declared here but left uninitialized +LL | println!("demo: {:?}", demo); + | ^^^^ `demo` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let demo: Demo = Default::default(); + | ++++++++++++++++++++ + +error[E0381]: used binding `demo_no` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:30:31 + | +LL | let demo_no: DemoNoDef; + | ------- binding declared here but left uninitialized +LL | println!("demo_no: {:?}", demo_no); + | ^^^^^^^ `demo_no` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let demo_no: DemoNoDef = todo!(); + | +++++++++ + +error[E0381]: used binding `arr` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:34:27 + | +LL | let arr: [i32; 5]; + | --- binding declared here but left uninitialized +LL | println!("arr: {:?}", arr); + | ^^^ `arr` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let arr: [i32; 5] = todo!(); + | +++++++++ + +error[E0381]: used binding `foo` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:37:27 + | +LL | let foo: Vec<&str>; + | --- binding declared here but left uninitialized +LL | println!("foo: {:?}", foo); + | ^^^ `foo` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let foo: Vec<&str> = vec![]; + | ++++++++ + +error[E0381]: used binding `my_string` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:41:31 + | +LL | let my_string: String; + | --------- binding declared here but left uninitialized +LL | println!("my_string: {}", my_string); + | ^^^^^^^^^ `my_string` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let my_string: String = Default::default(); + | ++++++++++++++++++++ + +error[E0381]: used binding `my_int` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:45:28 + | +LL | let my_int: &i32; + | ------ binding declared here but left uninitialized +LL | println!("my_int: {}", *my_int); + | ^^^^^^^ `*my_int` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let my_int: &i32 = todo!(); + | +++++++++ + +error[E0381]: used binding `hello` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:49:27 + | +LL | let hello: &str; + | ----- binding declared here but left uninitialized +LL | println!("hello: {}", hello); + | ^^^^^ `hello` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let hello: &str = todo!(); + | +++++++++ + +error[E0381]: used binding `never` isn't initialized + --> $DIR/suggest-assign-rvalue.rs:53:27 + | +LL | let never: !; + | ----- binding declared here but left uninitialized +LL | println!("never: {}", never); + | ^^^^^ `never` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/borrowck/suggest-local-var-double-mut.rs b/tests/ui/borrowck/suggest-local-var-double-mut.rs new file mode 100644 index 000000000..d5996ba68 --- /dev/null +++ b/tests/ui/borrowck/suggest-local-var-double-mut.rs @@ -0,0 +1,27 @@ +// See issue #77834. + +#![crate_type = "lib"] + +mod method_syntax { + struct Foo; + + impl Foo { + fn foo(&mut self, _: f32) -> i32 { todo!() } + fn bar(&mut self) -> f32 { todo!() } + fn baz(&mut self) { + self.foo(self.bar()); //~ ERROR + } + } +} + +mod fully_qualified_syntax { + struct Foo; + + impl Foo { + fn foo(&mut self, _: f32) -> i32 { todo!() } + fn bar(&mut self) -> f32 { todo!() } + fn baz(&mut self) { + Self::foo(self, Self::bar(self)); //~ ERROR + } + } +} diff --git a/tests/ui/borrowck/suggest-local-var-double-mut.stderr b/tests/ui/borrowck/suggest-local-var-double-mut.stderr new file mode 100644 index 000000000..3a43c18a7 --- /dev/null +++ b/tests/ui/borrowck/suggest-local-var-double-mut.stderr @@ -0,0 +1,44 @@ +error[E0499]: cannot borrow `*self` as mutable more than once at a time + --> $DIR/suggest-local-var-double-mut.rs:12:22 + | +LL | self.foo(self.bar()); + | ---------^^^^^^^^^^- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + | +help: try adding a local storing this argument... + --> $DIR/suggest-local-var-double-mut.rs:12:22 + | +LL | self.foo(self.bar()); + | ^^^^^^^^^^ +help: ...and then using that local as the argument to this call + --> $DIR/suggest-local-var-double-mut.rs:12:13 + | +LL | self.foo(self.bar()); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0499]: cannot borrow `*self` as mutable more than once at a time + --> $DIR/suggest-local-var-double-mut.rs:24:39 + | +LL | Self::foo(self, Self::bar(self)); + | --------- ---- ^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + | +help: try adding a local storing this argument... + --> $DIR/suggest-local-var-double-mut.rs:24:29 + | +LL | Self::foo(self, Self::bar(self)); + | ^^^^^^^^^^^^^^^ +help: ...and then using that local as the argument to this call + --> $DIR/suggest-local-var-double-mut.rs:24:13 + | +LL | Self::foo(self, Self::bar(self)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/suggest-local-var-for-vector.rs b/tests/ui/borrowck/suggest-local-var-for-vector.rs new file mode 100644 index 000000000..40f013f6a --- /dev/null +++ b/tests/ui/borrowck/suggest-local-var-for-vector.rs @@ -0,0 +1,4 @@ +fn main() { + let mut vec = vec![0u32; 420]; + vec[vec.len() - 1] = 123; //~ ERROR cannot borrow `vec` as immutable because it is also borrowed as mutable +} diff --git a/tests/ui/borrowck/suggest-local-var-for-vector.stderr b/tests/ui/borrowck/suggest-local-var-for-vector.stderr new file mode 100644 index 000000000..615fffcd5 --- /dev/null +++ b/tests/ui/borrowck/suggest-local-var-for-vector.stderr @@ -0,0 +1,24 @@ +error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable + --> $DIR/suggest-local-var-for-vector.rs:3:9 + | +LL | vec[vec.len() - 1] = 123; + | ----^^^^^^^^^----- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | mutable borrow later used here + | +help: try adding a local storing this... + --> $DIR/suggest-local-var-for-vector.rs:3:9 + | +LL | vec[vec.len() - 1] = 123; + | ^^^^^^^^^ +help: ...and then using that local here + --> $DIR/suggest-local-var-for-vector.rs:3:5 + | +LL | vec[vec.len() - 1] = 123; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/suggest-local-var-imm-and-mut.rs b/tests/ui/borrowck/suggest-local-var-imm-and-mut.rs new file mode 100644 index 000000000..bf167ba79 --- /dev/null +++ b/tests/ui/borrowck/suggest-local-var-imm-and-mut.rs @@ -0,0 +1,27 @@ +// See issue #77834. + +#![crate_type = "lib"] + +mod method_syntax { + struct Foo; + + impl Foo { + fn foo(&self, _: f32) -> i32 { todo!() } + fn bar(&mut self) -> f32 { todo!() } + fn baz(&mut self) { + self.foo(self.bar()); //~ ERROR + } + } +} + +mod fully_qualified_syntax { + struct Foo; + + impl Foo { + fn foo(&self, _: f32) -> i32 { todo!() } + fn bar(&mut self) -> f32 { todo!() } + fn baz(&mut self) { + Self::foo(self, Self::bar(self)); //~ ERROR + } + } +} diff --git a/tests/ui/borrowck/suggest-local-var-imm-and-mut.stderr b/tests/ui/borrowck/suggest-local-var-imm-and-mut.stderr new file mode 100644 index 000000000..eb934e7b7 --- /dev/null +++ b/tests/ui/borrowck/suggest-local-var-imm-and-mut.stderr @@ -0,0 +1,22 @@ +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/suggest-local-var-imm-and-mut.rs:12:22 + | +LL | self.foo(self.bar()); + | ---------^^^^^^^^^^- + | | | | + | | | mutable borrow occurs here + | | immutable borrow later used by call + | immutable borrow occurs here + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/suggest-local-var-imm-and-mut.rs:24:29 + | +LL | Self::foo(self, Self::bar(self)); + | --------- ---- ^^^^^^^^^^^^^^^ mutable borrow occurs here + | | | + | | immutable borrow occurs here + | immutable borrow later used by call + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/suggest-storing-local-var-for-vector.rs b/tests/ui/borrowck/suggest-storing-local-var-for-vector.rs new file mode 100644 index 000000000..40f013f6a --- /dev/null +++ b/tests/ui/borrowck/suggest-storing-local-var-for-vector.rs @@ -0,0 +1,4 @@ +fn main() { + let mut vec = vec![0u32; 420]; + vec[vec.len() - 1] = 123; //~ ERROR cannot borrow `vec` as immutable because it is also borrowed as mutable +} diff --git a/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr b/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr new file mode 100644 index 000000000..e3a16eddf --- /dev/null +++ b/tests/ui/borrowck/suggest-storing-local-var-for-vector.stderr @@ -0,0 +1,24 @@ +error[E0502]: cannot borrow `vec` as immutable because it is also borrowed as mutable + --> $DIR/suggest-storing-local-var-for-vector.rs:3:9 + | +LL | vec[vec.len() - 1] = 123; + | ----^^^^^^^^^----- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | mutable borrow later used here + | +help: try adding a local storing this... + --> $DIR/suggest-storing-local-var-for-vector.rs:3:9 + | +LL | vec[vec.len() - 1] = 123; + | ^^^^^^^^^ +help: ...and then using that local here + --> $DIR/suggest-storing-local-var-for-vector.rs:3:5 + | +LL | vec[vec.len() - 1] = 123; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-across-loop.rs b/tests/ui/borrowck/two-phase-across-loop.rs new file mode 100644 index 000000000..3fcea7d17 --- /dev/null +++ b/tests/ui/borrowck/two-phase-across-loop.rs @@ -0,0 +1,22 @@ +// Test that a borrow which starts as a two-phase borrow and gets +// carried around a loop winds up conflicting with itself. + +struct Foo { x: String } + +impl Foo { + fn get_string(&mut self) -> &str { + &self.x + } +} + +fn main() { + let mut foo = Foo { x: format!("Hello, world") }; + let mut strings = vec![]; + + loop { + strings.push(foo.get_string()); //~ ERROR cannot borrow `foo` as mutable + if strings.len() > 2 { break; } + } + + println!("{:?}", strings); +} diff --git a/tests/ui/borrowck/two-phase-across-loop.stderr b/tests/ui/borrowck/two-phase-across-loop.stderr new file mode 100644 index 000000000..22f9b39df --- /dev/null +++ b/tests/ui/borrowck/two-phase-across-loop.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/two-phase-across-loop.rs:17:22 + | +LL | strings.push(foo.get_string()); + | -------------^^^^^^^^^^^^^^^^- + | | | + | | `foo` was mutably borrowed here in the previous iteration of the loop + | first borrow used here, in later iteration of loop + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr new file mode 100644 index 000000000..aacf17893 --- /dev/null +++ b/tests/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr @@ -0,0 +1,47 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-activation-sharing-interference.rs:28:15 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | { let z = &x; read(z); } + | ^^ immutable borrow occurs here +LL | +LL | *y += 1; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-activation-sharing-interference.rs:36:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | let z = &x; + | ^^ immutable borrow occurs here +LL | +LL | *y += 1; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-activation-sharing-interference.rs:47:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | let z = &x; + | ^^ immutable borrow occurs here +... +LL | *y += 1; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-activation-sharing-interference.rs:58:14 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | let _z = &x; + | ^^ immutable borrow occurs here +LL | +LL | *y += 1; + | ------- mutable borrow later used here + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-activation-sharing-interference.rs b/tests/ui/borrowck/two-phase-activation-sharing-interference.rs new file mode 100644 index 000000000..8b880ff64 --- /dev/null +++ b/tests/ui/borrowck/two-phase-activation-sharing-interference.rs @@ -0,0 +1,65 @@ +// revisions: nll_target + +// The following revisions are disabled due to missing support from two-phase beyond autorefs +//[nll_beyond] compile-flags: -Z two-phase-beyond-autoref + +// This is an important corner case pointed out by Niko: one is +// allowed to initiate a shared borrow during a reservation, but it +// *must end* before the activation occurs. +// +// FIXME: for clarity, diagnostics for these cases might be better off +// if they specifically said "cannot activate mutable borrow of `x`" +// +// The convention for the listed revisions: "lxl" means lexical +// lifetimes (which can be easier to reason about). "nll" means +// non-lexical lifetimes. "nll_target" means the initial conservative +// two-phase borrows that only applies to autoref-introduced borrows. +// "nll_beyond" means the generalization of two-phase borrows to all +// `&mut`-borrows (doing so makes it easier to write code for specific +// corner cases). + +#![allow(dead_code)] + +fn read(_: &i32) { } + +fn ok() { + let mut x = 3; + let y = &mut x; + { let z = &x; read(z); } + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + *y += 1; +} + +fn not_ok() { + let mut x = 3; + let y = &mut x; + let z = &x; + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + *y += 1; + //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + //[nll_beyond]~^^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + read(z); +} + +fn should_be_ok_with_nll() { + let mut x = 3; + let y = &mut x; + let z = &x; + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + read(z); + *y += 1; + //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + // (okay with (generalized) nll today) +} + +fn should_also_eventually_be_ok_with_nll() { + let mut x = 3; + let y = &mut x; + let _z = &x; + //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + *y += 1; + //[lxl_beyond]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + // (okay with (generalized) nll today) +} + +fn main() { } diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr new file mode 100644 index 000000000..a57ceb847 --- /dev/null +++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr @@ -0,0 +1,27 @@ +error[E0503]: cannot use `i` because it was mutably borrowed + --> $DIR/two-phase-allow-access-during-reservation.rs:26:19 + | +LL | /*1*/ let p = &mut i; // (reservation of `i` starts here) + | ------ borrow of `i` occurs here +LL | +LL | /*2*/ let j = i; // OK: `i` is only reserved here + | ^ use of borrowed `i` +... +LL | /*3*/ *p += 1; // (mutable borrow of `i` starts here, since `p` is used) + | ------- borrow later used here + +error[E0503]: cannot use `i` because it was mutably borrowed + --> $DIR/two-phase-allow-access-during-reservation.rs:31:19 + | +LL | /*1*/ let p = &mut i; // (reservation of `i` starts here) + | ------ borrow of `i` occurs here +... +LL | /*4*/ let k = i; + | ^ use of borrowed `i` +... +LL | /*5*/ *p += 1; + | ------- borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs b/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs new file mode 100644 index 000000000..67d084207 --- /dev/null +++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.rs @@ -0,0 +1,37 @@ +// revisions: nll_target + +// The following revisions are disabled due to missing support for two_phase_beyond_autoref +//[nll_beyond] compile-flags: -Z two_phase_beyond_autoref + +// This is the second counter-example from Niko's blog post +// smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ +// +// It is "artificial". It is meant to illustrate directly that we +// should allow an aliasing access during reservation, but *not* while +// the mutable borrow is active. +// +// The convention for the listed revisions: "lxl" means lexical +// lifetimes (which can be easier to reason about). "nll" means +// non-lexical lifetimes. "nll_target" means the initial conservative +// two-phase borrows that only applies to autoref-introduced borrows. +// "nll_beyond" means the generalization of two-phase borrows to all +// `&mut`-borrows (doing so makes it easier to write code for specific +// corner cases). + +fn main() { + /*0*/ let mut i = 0; + + /*1*/ let p = &mut i; // (reservation of `i` starts here) + + /*2*/ let j = i; // OK: `i` is only reserved here + //[nll_target]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] + + /*3*/ *p += 1; // (mutable borrow of `i` starts here, since `p` is used) + + /*4*/ let k = i; //[nll_beyond]~ ERROR cannot use `i` because it was mutably borrowed [E0503] + //[nll_target]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] + + /*5*/ *p += 1; + + let _ = (j, k, p); +} diff --git a/tests/ui/borrowck/two-phase-baseline.rs b/tests/ui/borrowck/two-phase-baseline.rs new file mode 100644 index 000000000..994dc823d --- /dev/null +++ b/tests/ui/borrowck/two-phase-baseline.rs @@ -0,0 +1,9 @@ +// run-pass + +// This is the "goto example" for why we want two phase borrows. + +fn main() { + let mut v = vec![0, 1, 2]; + v.push(v.len()); + assert_eq!(v, [0, 1, 2, 3]); +} diff --git a/tests/ui/borrowck/two-phase-bin-ops.rs b/tests/ui/borrowck/two-phase-bin-ops.rs new file mode 100644 index 000000000..1242ae307 --- /dev/null +++ b/tests/ui/borrowck/two-phase-bin-ops.rs @@ -0,0 +1,35 @@ +// run-pass +use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; + +struct A(i32); + +macro_rules! trivial_binop { + ($Trait:ident, $m:ident) => { + impl $Trait for A { fn $m(&mut self, rhs: i32) { self.0 = rhs; } } + } +} + +trivial_binop!(AddAssign, add_assign); +trivial_binop!(SubAssign, sub_assign); +trivial_binop!(MulAssign, mul_assign); +trivial_binop!(DivAssign, div_assign); +trivial_binop!(RemAssign, rem_assign); +trivial_binop!(BitAndAssign, bitand_assign); +trivial_binop!(BitOrAssign, bitor_assign); +trivial_binop!(BitXorAssign, bitxor_assign); +trivial_binop!(ShlAssign, shl_assign); +trivial_binop!(ShrAssign, shr_assign); + +fn main() { + let mut a = A(10); + a += a.0; + a -= a.0; + a *= a.0; + a /= a.0; + a &= a.0; + a |= a.0; + a ^= a.0; + a <<= a.0; + a >>= a.0; +} diff --git a/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs b/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs new file mode 100644 index 000000000..dd2ef4e27 --- /dev/null +++ b/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.rs @@ -0,0 +1,19 @@ +// This is the third counter-example from Niko's blog post +// smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ +// +// It shows that not all nested method calls on `self` are magically +// allowed by this change. In particular, a nested `&mut` borrow is +// still disallowed. + +fn main() { + + + let mut vec = vec![0, 1]; + vec.get({ + + vec.push(2); + //~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + + 0 + }); +} diff --git a/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr b/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr new file mode 100644 index 000000000..21b0eddb9 --- /dev/null +++ b/tests/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr @@ -0,0 +1,19 @@ +error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-cannot-nest-mut-self-calls.rs:14:9 + | +LL | vec.get({ + | - --- immutable borrow later used by call + | _____| + | | +LL | | +LL | | vec.push(2); + | | ^^^^^^^^^^^ mutable borrow occurs here +LL | | +LL | | +LL | | 0 +LL | | }); + | |______- immutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-control-flow-split-before-activation.rs b/tests/ui/borrowck/two-phase-control-flow-split-before-activation.rs new file mode 100644 index 000000000..0b20e1945 --- /dev/null +++ b/tests/ui/borrowck/two-phase-control-flow-split-before-activation.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + let mut a = 0; + let mut b = 0; + let p = if maybe() { + &mut a + } else { + &mut b + }; + use_(p); +} + +fn maybe() -> bool { false } +fn use_(_: T) { } diff --git a/tests/ui/borrowck/two-phase-method-receivers.rs b/tests/ui/borrowck/two-phase-method-receivers.rs new file mode 100644 index 000000000..6b879af5a --- /dev/null +++ b/tests/ui/borrowck/two-phase-method-receivers.rs @@ -0,0 +1,15 @@ +// run-pass + +struct Foo<'a> { + x: &'a i32 +} + +impl<'a> Foo<'a> { + fn method(&mut self, _: &i32) { + } +} + +fn main() { + let a = &mut Foo { x: &22 }; + Foo::method(a, a.x); +} diff --git a/tests/ui/borrowck/two-phase-multi-mut.rs b/tests/ui/borrowck/two-phase-multi-mut.rs new file mode 100644 index 000000000..bb646d7ca --- /dev/null +++ b/tests/ui/borrowck/two-phase-multi-mut.rs @@ -0,0 +1,14 @@ +struct Foo { +} + +impl Foo { + fn method(&mut self, foo: &mut Foo) { + } +} + +fn main() { + let mut foo = Foo { }; + foo.method(&mut foo); + //~^ cannot borrow `foo` as mutable more than once at a time + //~^^ cannot borrow `foo` as mutable more than once at a time +} diff --git a/tests/ui/borrowck/two-phase-multi-mut.stderr b/tests/ui/borrowck/two-phase-multi-mut.stderr new file mode 100644 index 000000000..2e53e17a3 --- /dev/null +++ b/tests/ui/borrowck/two-phase-multi-mut.stderr @@ -0,0 +1,23 @@ +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/two-phase-multi-mut.rs:11:5 + | +LL | foo.method(&mut foo); + | ^^^^------^--------^ + | | | | + | | | first mutable borrow occurs here + | | first borrow later used by call + | second mutable borrow occurs here + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/two-phase-multi-mut.rs:11:16 + | +LL | foo.method(&mut foo); + | -----------^^^^^^^^- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/two-phase-multiple-activations.rs b/tests/ui/borrowck/two-phase-multiple-activations.rs new file mode 100644 index 000000000..53fb71ebe --- /dev/null +++ b/tests/ui/borrowck/two-phase-multiple-activations.rs @@ -0,0 +1,21 @@ +// run-pass + +use std::io::Result; + +struct Foo {} + +pub trait FakeRead { + fn read_to_end(&mut self, buf: &mut Vec) -> Result; +} + +impl FakeRead for Foo { + fn read_to_end(&mut self, _buf: &mut Vec) -> Result { + Ok(4) + } +} + +fn main() { + let mut a = Foo {}; + let mut v = Vec::new(); + a.read_to_end(&mut v).unwrap(); +} diff --git a/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr b/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr new file mode 100644 index 000000000..efd63a08a --- /dev/null +++ b/tests/ui/borrowck/two-phase-nonrecv-autoref.base.stderr @@ -0,0 +1,93 @@ +error[E0499]: cannot borrow `*f` as mutable more than once at a time + --> $DIR/two-phase-nonrecv-autoref.rs:50:11 + | +LL | f(f(10)); + | - ^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call + +error[E0382]: use of moved value: `f` + --> $DIR/two-phase-nonrecv-autoref.rs:57:11 + | +LL | fn twice_ten_so i32>(f: Box) { + | - move occurs because `f` has type `Box`, which does not implement the `Copy` trait +LL | f(f(10)); + | - ^ value used here after move + | | + | value moved here + +error[E0499]: cannot borrow `*f` as mutable more than once at a time + --> $DIR/two-phase-nonrecv-autoref.rs:62:11 + | +LL | f(f(10)); + | - ^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call + +error[E0382]: use of moved value: `f` + --> $DIR/two-phase-nonrecv-autoref.rs:69:11 + | +LL | fn twice_ten_oo(f: Box i32>) { + | - move occurs because `f` has type `Box i32>`, which does not implement the `Copy` trait +LL | f(f(10)); + | - ^ value used here after move + | | + | value moved here + +error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-nonrecv-autoref.rs:107:27 + | +LL | double_access(&mut a, &a); + | ------------- ------ ^^ immutable borrow occurs here + | | | + | | mutable borrow occurs here + | mutable borrow later used by call + +error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-nonrecv-autoref.rs:132:7 + | +LL | i[i[3]] = 4; + | --^---- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | mutable borrow later used here + | +help: try adding a local storing this... + --> $DIR/two-phase-nonrecv-autoref.rs:132:7 + | +LL | i[i[3]] = 4; + | ^^^^ +help: ...and then using that local here + --> $DIR/two-phase-nonrecv-autoref.rs:132:5 + | +LL | i[i[3]] = 4; + | ^^^^^^^ + +error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-nonrecv-autoref.rs:138:7 + | +LL | i[i[3]] = i[4]; + | --^---- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | mutable borrow later used here + | +help: try adding a local storing this... + --> $DIR/two-phase-nonrecv-autoref.rs:138:7 + | +LL | i[i[3]] = i[4]; + | ^^^^ +help: ...and then using that local here + --> $DIR/two-phase-nonrecv-autoref.rs:138:5 + | +LL | i[i[3]] = i[4]; + | ^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0382, E0499, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/two-phase-nonrecv-autoref.rs b/tests/ui/borrowck/two-phase-nonrecv-autoref.rs new file mode 100644 index 000000000..da238205b --- /dev/null +++ b/tests/ui/borrowck/two-phase-nonrecv-autoref.rs @@ -0,0 +1,166 @@ +// revisions: base + +//[g2p]compile-flags: -Z two-phase-beyond-autoref +// the above revision is disabled until two-phase-beyond-autoref support is better + +// This is a test checking that when we limit two-phase borrows to +// method receivers, we do not let other kinds of auto-ref to leak +// through. +// +// The g2p revision illustrates the "undesirable" behavior you would +// otherwise observe without limiting the phasing to autoref on method +// receivers (namely, in many cases demonstrated below, the error +// would not arise). + +use std::ops::{Index, IndexMut}; + +fn foo(x: &mut u32, y: u32) { + *x += y; +} + +fn deref_coercion(x: &mut u32) { + foo(x, *x); + // Above error is a known limitation of AST borrowck +} + +// While adding a flag to adjustments (indicating whether they +// should support two-phase borrows, here are the cases I +// encountered: +// +// - [x] Resolving overloaded_call_traits (call, call_mut, call_once) +// - [x] deref_coercion (shown above) +// - [x] coerce_unsized e.g., `&[T; n]`, `&mut [T; n] -> &[T]`, +// `&mut [T; n] -> &mut [T]`, `&Concrete -> &Trait` +// - [x] Method Call Receivers (the case we want to support!) +// - [x] ExprKind::Index and ExprKind::Unary Deref; only need to handle coerce_index_op +// - [x] overloaded_binops + +fn overloaded_call_traits() { + // Regarding overloaded call traits, note that there is no + // scenario where adding two-phase borrows should "fix" these + // cases, because either we will resolve both invocations to + // `call_mut` (in which case the inner call requires a mutable + // borrow which will conflict with the outer reservation), or we + // will resolve both to `call` (which will just work, regardless + // of two-phase borrow support), or we will resolve both to + // `call_once` (in which case the inner call requires moving the + // receiver, invalidating the outer call). + + fn twice_ten_sm i32>(f: &mut F) { + f(f(10)); + //~^ ERROR cannot borrow `*f` as mutable more than once at a time + } + fn twice_ten_si i32>(f: &mut F) { + f(f(10)); + } + fn twice_ten_so i32>(f: Box) { + f(f(10)); + //~^ ERROR use of moved value: `f` + } + + fn twice_ten_om(f: &mut dyn FnMut(i32) -> i32) { + f(f(10)); + //~^ ERROR cannot borrow `*f` as mutable more than once at a time + } + fn twice_ten_oi(f: &mut dyn Fn(i32) -> i32) { + f(f(10)); + } + fn twice_ten_oo(f: Box i32>) { + f(f(10)); + //~^ ERROR use of moved value: `f` + } + + twice_ten_sm(&mut |x| x + 1); + twice_ten_si(&mut |x| x + 1); + twice_ten_so(Box::new(|x| x + 1)); + twice_ten_om(&mut |x| x + 1); + twice_ten_oi(&mut |x| x + 1); + twice_ten_oo(Box::new(|x| x + 1)); +} + +trait TwoMethods { + fn m(&mut self, x: i32) -> i32 { x + 1 } + fn i(&self, x: i32) -> i32 { x + 1 } +} + +struct T; + +impl TwoMethods for T { } + +struct S; + +impl S { + fn m(&mut self, x: i32) -> i32 { x + 1 } + fn i(&self, x: i32) -> i32 { x + 1 } +} + +impl TwoMethods for [i32; 3] { } + +fn double_access(m: &mut [X], s: &[X]) { + m[0] = s[1]; +} + +fn coerce_unsized() { + let mut a = [1, 2, 3]; + + // This is not okay. + double_access(&mut a, &a); + //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + + // But this is okay. + a.m(a.i(10)); + // Above error is an expected limitation of AST borrowck +} + +struct I(i32); + +impl Index for I { + type Output = i32; + fn index(&self, _: i32) -> &i32 { + &self.0 + } +} + +impl IndexMut for I { + fn index_mut(&mut self, _: i32) -> &mut i32 { + &mut self.0 + } +} + +fn coerce_index_op() { + let mut i = I(10); + i[i[3]] = 4; + //~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + // Should be accepted with g2p + + i[3] = i[4]; + + i[i[3]] = i[4]; + //~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + // Should be accepted with g2p +} + +fn main() { + + // As a reminder, this is the basic case we want to ensure we handle. + let mut v = vec![1, 2, 3]; + v.push(v.len()); + // Error above is an expected limitation of AST borrowck + + // (as a rule, pnkfelix does not like to write tests with dead code.) + + deref_coercion(&mut 5); + overloaded_call_traits(); + + + let mut s = S; + s.m(s.i(10)); + // Error above is an expected limitation of AST borrowck + + let mut t = T; + t.m(t.i(10)); + // Error above is an expected limitation of AST borrowck + + coerce_unsized(); + coerce_index_op(); +} diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference-2.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference-2.rs new file mode 100644 index 000000000..27e599c6c --- /dev/null +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference-2.rs @@ -0,0 +1,29 @@ +// Test for #56254. The last example originally failed with the ast checker, was +// accidentally allowed under migrate/nll, then linted against in migrate mode +// but disallowed under NLL. Now, we accept it everywhere. + +//ignore-compare-mode-polonius + +fn double_conflicts() { + let mut v = vec![0, 1, 2]; + let shared = &v; + + v.extend(shared); + //~^ ERROR cannot borrow `v` as mutable +} + +fn activation_conflict() { + let mut v = vec![0, 1, 2]; + + v.extend(&v); + //~^ ERROR cannot borrow `v` as mutable +} + +fn reservation_allowed() { + let mut v = vec![0, 1, 2]; + let shared = &v; + + v.push(shared.len()); +} + +fn main() {} diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr b/tests/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr new file mode 100644 index 000000000..9e0f68b65 --- /dev/null +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference-2.stderr @@ -0,0 +1,25 @@ +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-reservation-sharing-interference-2.rs:11:5 + | +LL | let shared = &v; + | -- immutable borrow occurs here +LL | +LL | v.extend(shared); + | ^^------^^^^^^^^ + | | | + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-reservation-sharing-interference-2.rs:18:5 + | +LL | v.extend(&v); + | ^^------^--^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr new file mode 100644 index 000000000..e3e4057d6 --- /dev/null +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-reservation-sharing-interference.rs:32:17 + | +LL | let shared = &vec; + | ---- immutable borrow occurs here +... +LL | delay = &mut vec; + | ^^^^^^^^ mutable borrow occurs here +... +LL | shared[0]; + | ------ immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs new file mode 100644 index 000000000..0463e22b3 --- /dev/null +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs @@ -0,0 +1,45 @@ +// revisions: nll_target + +// The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs +//[nll_beyond]compile-flags: -Z two-phase-beyond-autoref +//[nll_beyond]should-fail + +// This is a corner case that the current implementation is (probably) +// treating more conservatively than is necessary. But it also does +// not seem like a terribly important use case to cover. +// +// So this test is just making a note of the current behavior, with +// the caveat that in the future, the rules may be loosened, at which +// point this test might be thrown out. +// +// The convention for the listed revisions: "lxl" means lexical +// lifetimes (which can be easier to reason about). "nll" means +// non-lexical lifetimes. "nll_target" means the initial conservative +// two-phase borrows that only applies to autoref-introduced borrows. +// "nll_beyond" means the generalization of two-phase borrows to all +// `&mut`-borrows (doing so makes it easier to write code for specific +// corner cases). + +fn main() { + let mut vec = vec![0, 1]; + let delay: &mut Vec<_>; + { + let shared = &vec; + + // we reserve here, which could (on its own) be compatible + // with the shared borrow. But in the current implementation, + // its an error. + delay = &mut vec; + //[nll_beyond]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[nll_target]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + + shared[0]; + } + + // the &mut-borrow only becomes active way down here. + // + // (At least in theory; part of the reason this test fails is that + // the constructed MIR throws in extra &mut reborrows which + // flummoxes our attempt to delay the activation point here.) + delay.push(2); +} diff --git a/tests/ui/borrowck/two-phase-sneaky.rs b/tests/ui/borrowck/two-phase-sneaky.rs new file mode 100644 index 000000000..bf06366de --- /dev/null +++ b/tests/ui/borrowck/two-phase-sneaky.rs @@ -0,0 +1,15 @@ +// This is the first counter-example from Niko's blog post +// smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ +// of a danger for code to crash if we just turned off the check for whether +// a mutable-borrow aliases another borrow. + +fn main() { + let mut v: Vec = vec![format!("Hello, ")]; + v[0].push_str({ + + v.push(format!("foo")); + //~^ ERROR cannot borrow `v` as mutable more than once at a time [E0499] + + "World!" + }); +} diff --git a/tests/ui/borrowck/two-phase-sneaky.stderr b/tests/ui/borrowck/two-phase-sneaky.stderr new file mode 100644 index 000000000..117d7ceae --- /dev/null +++ b/tests/ui/borrowck/two-phase-sneaky.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `v` as mutable more than once at a time + --> $DIR/two-phase-sneaky.rs:10:9 + | +LL | v[0].push_str({ + | - -------- first borrow later used by call + | | + | first mutable borrow occurs here +LL | +LL | v.push(format!("foo")); + | ^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/two-phase-surprise-no-conflict.rs b/tests/ui/borrowck/two-phase-surprise-no-conflict.rs new file mode 100644 index 000000000..6d37d1ded --- /dev/null +++ b/tests/ui/borrowck/two-phase-surprise-no-conflict.rs @@ -0,0 +1,167 @@ +// This is a test adapted from a minimization of the code from +// rust-lang/rust#52934, where an accidental disabling of +// two-phase-borrows (in the initial 2018 edition integration) broke +// Clippy, but the scenarios where it was breaking were subtle enough +// that we decided it warranted its own unit test, and pnkfelix +// decided to use that test as an opportunity to illustrate the cases. + +#[derive(Copy, Clone)] +struct BodyId; +enum Expr { Closure(BodyId), Others } +struct Body { value: Expr } + +struct Map { body: Body, } +impl Map { fn body(&self, _: BodyId) -> &Body { unimplemented!() } } + +struct SpanlessHash<'a> { cx: &'a Map, cx_mut: &'a mut Map } + +impl <'a> SpanlessHash<'a> { + fn demo(&mut self) { + let _mut_borrow = &mut *self; + let _access = self.cx; + //~^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503] + _mut_borrow; + } + + fn hash_expr(&mut self, e: &Expr) { + match *e { + Expr::Closure(eid) => { + // Accepted by AST-borrowck for erroneous reasons + // (rust-lang/rust#38899). + // + // Not okay without two-phase borrows: the implicit + // `&mut self` of the receiver is evaluated first, and + // that conflicts with the `self.cx` access during + // argument evaluation, as demonstrated in `fn demo` + // above. + // + // Okay if we have two-phase borrows. Note that even + // if `self.cx.body(..)` holds onto a reference into + // `self.cx`, `self.cx` is an immutable-borrow, so + // nothing in the activation for `self.hash_expr(..)` + // can interfere with that immutable borrow. + self.hash_expr(&self.cx.body(eid).value); + }, + _ => {} + } + } + + fn hash_expr_mut(&mut self, e: &Expr) { + match *e { + Expr::Closure(eid) => { + // Not okay: the call to `self.cx_mut.body(eid)` might + // hold on to some mutably borrowed state in + // `self.cx_mut`, which would then interfere with the + // eventual activation of the `self` mutable borrow + // for `self.hash_expr(..)` + self.hash_expr(&self.cx_mut.body(eid).value); + //~^ ERROR cannot borrow `*self` + }, + _ => {} + } + } +} + +struct Session; +struct Config; +trait LateLintPass<'a> { } + +struct TrivialPass; +impl TrivialPass { + fn new(_: &Session) -> Self { TrivialPass } + fn new_mut(_: &mut Session) -> Self { TrivialPass } +} + +struct CapturePass<'a> { s: &'a Session } +impl<'a> CapturePass<'a> { + fn new(s: &'a Session) -> Self { CapturePass { s } } + fn new_mut(s: &'a mut Session) -> Self { CapturePass { s } } +} + +impl<'a> LateLintPass<'a> for TrivialPass { } +impl<'a, 'b> LateLintPass<'a> for CapturePass<'b> { } + +struct Registry<'a> { sess_mut: &'a mut Session } +impl<'a> Registry<'a> { + fn register_static(&mut self, _: Box) { } + + // Note: there isn't an interesting distinction between these + // different methods explored by any of the cases in the test + // below. pnkfelix just happened to write these cases out while + // exploring variations on `dyn for <'a> Trait<'a> + 'static`, and + // then decided to keep these particular ones in. + fn register_bound(&mut self, _: Box) { } + fn register_univ(&mut self, _: Box LateLintPass<'b> + 'a>) { } + fn register_ref(&mut self, _: &dyn LateLintPass) { } +} + +fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { + // Not okay without two-phase borrows: The implicit `&mut reg` of + // the receiver is evaluaated first, and that conflicts with the + // `reg.sess_mut` access during argument evaluation. + // + // Okay if we have two-phase borrows: inner borrows do not survive + // to the actual method invocation, because `TrivialPass::new` + // cannot (according to its type) keep them alive. + let reg = mk_reg(); + reg.register_static(Box::new(TrivialPass::new(®.sess_mut))); + let reg = mk_reg(); + reg.register_bound(Box::new(TrivialPass::new(®.sess_mut))); + let reg = mk_reg(); + reg.register_univ(Box::new(TrivialPass::new(®.sess_mut))); + let reg = mk_reg(); + reg.register_ref(&TrivialPass::new(®.sess_mut)); + + // These are not okay: the inner mutable borrows immediately + // conflict with the outer borrow/reservation, even with support + // for two-phase borrows. + let reg = mk_reg(); + reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + //~^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + //~^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + //~^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + //~^ ERROR cannot borrow `reg.sess_mut` + + // These are not okay: the inner borrows may reach the actual + // method invocation, because `CapturePass::new` might (according + // to its type) keep them alive. + // + // (Also, we don't test `register_static` on CapturePass because + // that will fail to get past lifetime inference.) + let reg = mk_reg(); + reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + //~^ ERROR cannot borrow `*reg` as mutable + let reg = mk_reg(); + reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + //~^ ERROR cannot borrow `*reg` as mutable + let reg = mk_reg(); + reg.register_ref(&CapturePass::new(®.sess_mut)); + //~^ ERROR cannot borrow `*reg` as mutable + + // These are not okay: the inner mutable borrows immediately + // conflict with the outer borrow/reservation, even with support + // for two-phase borrows. + // + // (Again, we don't test `register_static` on CapturePass because + // that will fail to get past lifetime inference.) + let reg = mk_reg(); + reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + //~^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time + //~^^ ERROR cannot borrow `*reg` as mutable more than once at a time + let reg = mk_reg(); + reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + //~^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time + //~^^ ERROR cannot borrow `*reg` as mutable more than once at a time + let reg = mk_reg(); + reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + //~^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time + //~^^ ERROR cannot borrow `*reg` as mutable more than once at a time +} + +fn main() { } diff --git a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr new file mode 100644 index 000000000..5a240d900 --- /dev/null +++ b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr @@ -0,0 +1,161 @@ +error[E0503]: cannot use `self.cx` because it was mutably borrowed + --> $DIR/two-phase-surprise-no-conflict.rs:21:23 + | +LL | let _mut_borrow = &mut *self; + | ---------- borrow of `*self` occurs here +LL | let _access = self.cx; + | ^^^^^^^ use of borrowed `*self` +LL | +LL | _mut_borrow; + | ----------- borrow later used here + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:57:17 + | +LL | self.hash_expr(&self.cx_mut.body(eid).value); + | ^^^^^---------^^---------------------^^^^^^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:119:51 + | +LL | reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + | ----------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:122:54 + | +LL | reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:125:53 + | +LL | reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:128:44 + | +LL | reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:138:5 + | +LL | reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + | ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:141:5 + | +LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { + | -- lifetime `'a` defined here +... +LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + | ^^^^^^^^^^^^^^^^^^-----------------------------------------^ + | | | | + | | | immutable borrow occurs here + | | cast requires that `reg.sess_mut` is borrowed for `'a` + | mutable borrow occurs here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:144:5 + | +LL | reg.register_ref(&CapturePass::new(®.sess_mut)); + | ^^^^------------^^^^^^^^^^^^^^^^^^^-------------^^ + | | | | + | | | immutable borrow occurs here + | | immutable borrow later used by call + | mutable borrow occurs here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:154:5 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^ + | | | | + | | | first mutable borrow occurs here + | | first borrow later used by call + | second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:154:54 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:158:5 + | +LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { + | -- lifetime `'a` defined here +... +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ^^^^^^^^^^^^^^^^^^-------------------------------------------------^ + | | | | + | | | first mutable borrow occurs here + | | cast requires that `reg.sess_mut` is borrowed for `'a` + | second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:158:53 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:162:5 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | ^^^^------------^^^^^^^^^^^^^^^^^^^^^^^-----------------^^ + | | | | + | | | first mutable borrow occurs here + | | first borrow later used by call + | second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:162:44 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0499, E0502, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed new file mode 100644 index 000000000..b0c537610 --- /dev/null +++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed @@ -0,0 +1,15 @@ +// run-rustfix +// Test that a by-ref `FnMut` closure gets an error when it tries to +// consume a value. + +fn call(f: F) where F : Fn() { + f(); +} + +fn main() { + let y = vec![format!("World")]; + call(|| { + y.clone().into_iter(); + //~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure + }); +} diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs new file mode 100644 index 000000000..4666b8a33 --- /dev/null +++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs @@ -0,0 +1,15 @@ +// run-rustfix +// Test that a by-ref `FnMut` closure gets an error when it tries to +// consume a value. + +fn call(f: F) where F : Fn() { + f(); +} + +fn main() { + let y = vec![format!("World")]; + call(|| { + y.into_iter(); + //~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure + }); +} diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr new file mode 100644 index 000000000..f033d53bf --- /dev/null +++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -0,0 +1,22 @@ +error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure + --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9 + | +LL | let y = vec![format!("World")]; + | - captured outer variable +LL | call(|| { + | -- captured by this `Fn` closure +LL | y.into_iter(); + | ^ ----------- `y` moved due to this method call + | | + | move occurs because `y` has type `Vec`, which does not implement the `Copy` trait + | +note: `into_iter` takes ownership of the receiver `self`, which moves `y` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | y.clone().into_iter(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/bounds-lifetime.rs b/tests/ui/bounds-lifetime.rs new file mode 100644 index 000000000..31aa4011b --- /dev/null +++ b/tests/ui/bounds-lifetime.rs @@ -0,0 +1,7 @@ +type A = for<'b, 'a: 'b> fn(); //~ ERROR lifetime bounds cannot be used in this context +type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context +type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context +type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context +type E = dyn for Fn(); //~ ERROR only lifetime parameters can be used in this context + +fn main() {} diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr new file mode 100644 index 000000000..a0395ed49 --- /dev/null +++ b/tests/ui/bounds-lifetime.stderr @@ -0,0 +1,32 @@ +error: lifetime bounds cannot be used in this context + --> $DIR/bounds-lifetime.rs:1:22 + | +LL | type A = for<'b, 'a: 'b> fn(); + | ^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/bounds-lifetime.rs:2:22 + | +LL | type B = for<'b, 'a: 'b,> fn(); + | ^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/bounds-lifetime.rs:3:22 + | +LL | type C = for<'b, 'a: 'b +> fn(); + | ^^ + +error: only lifetime parameters can be used in this context + --> $DIR/bounds-lifetime.rs:4:18 + | +LL | type D = for<'a, T> fn(); + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/bounds-lifetime.rs:5:18 + | +LL | type E = dyn for Fn(); + | ^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/box/alloc-unstable-fail.rs b/tests/ui/box/alloc-unstable-fail.rs new file mode 100644 index 000000000..942757164 --- /dev/null +++ b/tests/ui/box/alloc-unstable-fail.rs @@ -0,0 +1,6 @@ +use std::boxed::Box; + +fn main() { + let _boxed: Box = Box::new(10); + //~^ ERROR use of unstable library feature 'allocator_api' +} diff --git a/tests/ui/box/alloc-unstable-fail.stderr b/tests/ui/box/alloc-unstable-fail.stderr new file mode 100644 index 000000000..03ae36e88 --- /dev/null +++ b/tests/ui/box/alloc-unstable-fail.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/alloc-unstable-fail.rs:4:26 + | +LL | let _boxed: Box = Box::new(10); + | ^ + | + = note: see issue #32838 for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/box/alloc-unstable.rs b/tests/ui/box/alloc-unstable.rs new file mode 100644 index 000000000..66388d0d5 --- /dev/null +++ b/tests/ui/box/alloc-unstable.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(allocator_api)] + +use std::boxed::Box; + +fn main() { + let _boxed: Box = Box::new(10); +} diff --git a/tests/ui/box/into-boxed-slice-fail.rs b/tests/ui/box/into-boxed-slice-fail.rs new file mode 100644 index 000000000..49dbb170f --- /dev/null +++ b/tests/ui/box/into-boxed-slice-fail.rs @@ -0,0 +1,14 @@ +#![feature(box_into_boxed_slice)] + +use std::boxed::Box; +use std::fmt::Debug; +fn main() { + let boxed_slice = Box::new([1,2,3]) as Box<[u8]>; + let _ = Box::into_boxed_slice(boxed_slice); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~^^ ERROR the size for values of type `[u8]` cannot be known at compilation time + let boxed_trait: Box = Box::new(5u8); + let _ = Box::into_boxed_slice(boxed_trait); + //~^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time + //~^^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time +} diff --git a/tests/ui/box/into-boxed-slice-fail.stderr b/tests/ui/box/into-boxed-slice-fail.stderr new file mode 100644 index 000000000..f102f666d --- /dev/null +++ b/tests/ui/box/into-boxed-slice-fail.stderr @@ -0,0 +1,45 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/into-boxed-slice-fail.rs:7:35 + | +LL | let _ = Box::into_boxed_slice(boxed_slice); + | --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Box::::into_boxed_slice` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/into-boxed-slice-fail.rs:7:13 + | +LL | let _ = Box::into_boxed_slice(boxed_slice); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/into-boxed-slice-fail.rs:11:35 + | +LL | let _ = Box::into_boxed_slice(boxed_trait); + | --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn Debug` +note: required by a bound in `Box::::into_boxed_slice` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/into-boxed-slice-fail.rs:11:13 + | +LL | let _ = Box::into_boxed_slice(boxed_trait); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Debug` + = note: slice and array elements must have `Sized` type + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/box/into-boxed-slice.rs b/tests/ui/box/into-boxed-slice.rs new file mode 100644 index 000000000..61b3d9152 --- /dev/null +++ b/tests/ui/box/into-boxed-slice.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(box_into_boxed_slice)] + +use std::boxed::Box; +fn main() { + assert_eq!(Box::into_boxed_slice(Box::new(5u8)), Box::new([5u8]) as Box<[u8]>); + assert_eq!(Box::into_boxed_slice(Box::new([25u8])), Box::new([[25u8]]) as Box<[[u8; 1]]>); + let a: Box<[Box<[u8; 1]>]> = Box::into_boxed_slice(Box::new(Box::new([5u8]))); + let b: Box<[Box<[u8; 1]>]> = Box::new([Box::new([5u8])]); + assert_eq!(a, b); +} diff --git a/tests/ui/box/issue-82446.rs b/tests/ui/box/issue-82446.rs new file mode 100644 index 000000000..2960f7fbc --- /dev/null +++ b/tests/ui/box/issue-82446.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/82446 +// Spurious 'help: store this in the heap' regression test +trait MyTrait {} + +struct Foo { + val: Box +} + +fn make_it(val: &Box) { + Foo { + val //~ ERROR [E0308] + }; +} + +fn main() {} diff --git a/tests/ui/box/issue-82446.stderr b/tests/ui/box/issue-82446.stderr new file mode 100644 index 000000000..037473795 --- /dev/null +++ b/tests/ui/box/issue-82446.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-82446.rs:11:9 + | +LL | val + | ^^^ expected struct `Box`, found reference + | + = note: expected struct `Box<(dyn MyTrait + 'static)>` + found reference `&Box<(dyn MyTrait + 'static)>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/box/issue-95036.rs b/tests/ui/box/issue-95036.rs new file mode 100644 index 000000000..0611fabc1 --- /dev/null +++ b/tests/ui/box/issue-95036.rs @@ -0,0 +1,22 @@ +// compile-flags: -O +// build-pass + +#![feature(allocator_api)] + +#[inline(never)] +pub fn by_ref(node: &mut Box<[u8; 1], &std::alloc::Global>) { + node[0] = 9u8; +} + +pub fn main() { + let mut node = Box::new_in([5u8], &std::alloc::Global); + node[0] = 7u8; + + std::hint::black_box(node); + + let mut node = Box::new_in([5u8], &std::alloc::Global); + + by_ref(&mut node); + + std::hint::black_box(node); +} diff --git a/tests/ui/box/large-allocator-ice.rs b/tests/ui/box/large-allocator-ice.rs new file mode 100644 index 000000000..b3a882ff0 --- /dev/null +++ b/tests/ui/box/large-allocator-ice.rs @@ -0,0 +1,29 @@ +// build-pass +#![feature(allocator_api)] +#![allow(unused_must_use)] + +use std::alloc::Allocator; + +struct BigAllocator([usize; 2]); + +unsafe impl Allocator for BigAllocator { + fn allocate( + &self, + _: std::alloc::Layout, + ) -> Result, std::alloc::AllocError> { + todo!() + } + unsafe fn deallocate(&self, _: std::ptr::NonNull, _: std::alloc::Layout) { + todo!() + } +} + +fn main() { + Box::new_in((), &std::alloc::Global); + Box::new_in((), BigAllocator([0; 2])); + generic_function(0); +} + +fn generic_function(val: T) { + *Box::new_in(val, &std::alloc::Global); +} diff --git a/tests/ui/box/leak-alloc.rs b/tests/ui/box/leak-alloc.rs new file mode 100644 index 000000000..3f0f39f44 --- /dev/null +++ b/tests/ui/box/leak-alloc.rs @@ -0,0 +1,29 @@ +#![feature(allocator_api)] + +use std::alloc::{AllocError, Allocator, Layout, System}; +use std::ptr::NonNull; + +use std::boxed::Box; + +struct Alloc {} + +unsafe impl Allocator for Alloc { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + System.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + System.deallocate(ptr, layout) + } +} + +fn use_value(_: u32) {} + +fn main() { + let alloc = Alloc {}; + let boxed = Box::new_in(10, alloc.by_ref()); + let theref = Box::leak(boxed); + drop(alloc); + //~^ ERROR cannot move out of `alloc` because it is borrowed + use_value(*theref) +} diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr new file mode 100644 index 000000000..e8a6ad099 --- /dev/null +++ b/tests/ui/box/leak-alloc.stderr @@ -0,0 +1,15 @@ +error[E0505]: cannot move out of `alloc` because it is borrowed + --> $DIR/leak-alloc.rs:26:10 + | +LL | let boxed = Box::new_in(10, alloc.by_ref()); + | -------------- borrow of `alloc` occurs here +LL | let theref = Box::leak(boxed); +LL | drop(alloc); + | ^^^^^ move out of `alloc` occurs here +LL | +LL | use_value(*theref) + | ------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/box/new-box-syntax.rs b/tests/ui/box/new-box-syntax.rs new file mode 100644 index 000000000..c56e1dd46 --- /dev/null +++ b/tests/ui/box/new-box-syntax.rs @@ -0,0 +1,27 @@ +// run-pass +// pretty-expanded FIXME #23616 + +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +#![allow(dead_code, unused_variables)] + +// Tests that the new `box` syntax works with unique pointers. + +use std::boxed::Box; + +struct Structure { + x: isize, + y: isize, +} + +pub fn main() { + let y: Box = Box::new(2); + let b: Box = Box::new(1 + 2); + let c = Box::new(3 + 4); + + let s: Box = Box::new(Structure { + x: 3, + y: 4, + }); +} diff --git a/tests/ui/box/new-box.rs b/tests/ui/box/new-box.rs new file mode 100644 index 000000000..96a3b197f --- /dev/null +++ b/tests/ui/box/new-box.rs @@ -0,0 +1,30 @@ +// run-pass + +fn f(x: Box) { + let y: &isize = &*x; + println!("{}", *x); + println!("{}", *y); +} + +trait Trait { + fn printme(&self); +} + +struct Struct; + +impl Trait for Struct { + fn printme(&self) { + println!("hello world!"); + } +} + +fn g(x: Box) { + x.printme(); + let y: &dyn Trait = &*x; + y.printme(); +} + +fn main() { + f(Box::new(1234)); + g(Box::new(Struct) as Box); +} diff --git a/tests/ui/box/new.rs b/tests/ui/box/new.rs new file mode 100644 index 000000000..be1a40cf7 --- /dev/null +++ b/tests/ui/box/new.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + let _a = Box::new(1); +} diff --git a/tests/ui/box/thin_align.rs b/tests/ui/box/thin_align.rs new file mode 100644 index 000000000..3c61d0090 --- /dev/null +++ b/tests/ui/box/thin_align.rs @@ -0,0 +1,26 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::ops::Deref; +use std::fmt; + +fn main() { + let expected = "Foo error!"; + let a: ThinBox = ThinBox::new_unsize(Foo(expected)); + let a = a.deref(); + let msg = a.to_string(); + assert_eq!(expected, msg); +} + +#[derive(Debug)] +#[repr(align(1024))] +struct Foo(&'static str); + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for Foo {} diff --git a/tests/ui/box/thin_drop.rs b/tests/ui/box/thin_drop.rs new file mode 100644 index 000000000..965613c11 --- /dev/null +++ b/tests/ui/box/thin_drop.rs @@ -0,0 +1,37 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::ops::Deref; +use std::fmt; + +fn main() { + let expected = "Foo error!"; + let mut dropped = false; + { + let foo = Foo(expected, &mut dropped); + let a: ThinBox = ThinBox::new_unsize(foo); + let a = a.deref(); + let msg = a.to_string(); + assert_eq!(expected, msg); + } + assert!(dropped); +} + +#[derive(Debug)] +#[repr(align(1024))] +struct Foo<'a>(&'static str, &'a mut bool); + +impl Drop for Foo<'_> { + fn drop(&mut self) { + *self.1 = true; + } +} + +impl fmt::Display for Foo<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Error for Foo<'_> {} diff --git a/tests/ui/box/thin_new.rs b/tests/ui/box/thin_new.rs new file mode 100644 index 000000000..53f46478b --- /dev/null +++ b/tests/ui/box/thin_new.rs @@ -0,0 +1,30 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::{fmt, mem}; + +fn main() { + let thin_error: ThinBox = ThinBox::new_unsize(Foo); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error)); + println!("{:?}", thin_error); + + let thin = ThinBox::new(42i32); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin)); + println!("{:?}", thin); + + let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_slice)); + println!("{:?}", thin_slice); +} + +#[derive(Debug)] +struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "boooo!") + } +} + +impl Error for Foo {} diff --git a/tests/ui/box/thin_zst.rs b/tests/ui/box/thin_zst.rs new file mode 100644 index 000000000..77c400d17 --- /dev/null +++ b/tests/ui/box/thin_zst.rs @@ -0,0 +1,34 @@ +#![feature(thin_box)] +// run-pass +use std::boxed::ThinBox; +use std::error::Error; +use std::{fmt, mem}; +use std::ops::DerefMut; + +const EXPECTED: &str = "boooo!"; + +fn main() { + let thin_error: ThinBox = ThinBox::new_unsize(Foo); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error)); + let msg = thin_error.to_string(); + assert_eq!(EXPECTED, msg); + + let mut thin_concrete_error: ThinBox = ThinBox::new(Foo); + assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_concrete_error)); + let msg = thin_concrete_error.to_string(); + assert_eq!(EXPECTED, msg); + let inner = thin_concrete_error.deref_mut(); + let msg = inner.to_string(); + assert_eq!(EXPECTED, msg); +} + +#[derive(Debug)] +struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", EXPECTED) + } +} + +impl Error for Foo {} diff --git a/tests/ui/break-diverging-value.rs b/tests/ui/break-diverging-value.rs new file mode 100644 index 000000000..d070fddaf --- /dev/null +++ b/tests/ui/break-diverging-value.rs @@ -0,0 +1,37 @@ +#![feature(never_type)] + +fn loop_break_return() -> i32 { + let loop_value = loop { break return 0 }; // ok +} + +fn loop_break_loop() -> i32 { + let loop_value = loop { break loop {} }; // ok +} + +fn loop_break_break() -> i32 { //~ ERROR mismatched types + let loop_value = loop { break break }; +} + +fn loop_break_return_2() -> i32 { + let loop_value = loop { break { return 0; () } }; // ok +} + +enum Void {} + +fn get_void() -> Void { + panic!() +} + +fn loop_break_void() -> i32 { //~ ERROR mismatched types + let loop_value = loop { break get_void() }; +} + +fn get_never() -> ! { + panic!() +} + +fn loop_break_never() -> i32 { + let loop_value = loop { break get_never() }; // ok +} + +fn main() {} diff --git a/tests/ui/break-diverging-value.stderr b/tests/ui/break-diverging-value.stderr new file mode 100644 index 000000000..69edcd240 --- /dev/null +++ b/tests/ui/break-diverging-value.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/break-diverging-value.rs:11:26 + | +LL | fn loop_break_break() -> i32 { + | ---------------- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/break-diverging-value.rs:25:25 + | +LL | fn loop_break_void() -> i32 { + | --------------- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/btreemap/btreemap-index-mut.rs b/tests/ui/btreemap/btreemap-index-mut.rs new file mode 100644 index 000000000..62972acab --- /dev/null +++ b/tests/ui/btreemap/btreemap-index-mut.rs @@ -0,0 +1,6 @@ +use std::collections::BTreeMap; + +fn main() { + let mut map = BTreeMap::::new(); + map[&0] = 1; //~ ERROR cannot assign +} diff --git a/tests/ui/btreemap/btreemap-index-mut.stderr b/tests/ui/btreemap/btreemap-index-mut.stderr new file mode 100644 index 000000000..26f2a4c4b --- /dev/null +++ b/tests/ui/btreemap/btreemap-index-mut.stderr @@ -0,0 +1,19 @@ +error[E0594]: cannot assign to data in an index of `BTreeMap` + --> $DIR/btreemap-index-mut.rs:5:5 + | +LL | map[&0] = 1; + | ^^^^^^^^^^^ cannot assign + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `BTreeMap` +help: to modify a `BTreeMap`, use `.get_mut()`, `.insert()` or the entry API + | +LL | map.insert(&0, 1); + | ~~~~~~~~ ~ + +LL | map.get_mut(&0).map(|val| { *val = 1; }); + | ~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ ++++ +LL | let val = map.entry(&0).or_insert(1); + | +++++++++ ~~~~~~~ ~~~~~~~~~~~~ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/btreemap/btreemap_dropck.rs b/tests/ui/btreemap/btreemap_dropck.rs new file mode 100644 index 000000000..c58727df3 --- /dev/null +++ b/tests/ui/btreemap/btreemap_dropck.rs @@ -0,0 +1,16 @@ +struct PrintOnDrop<'a>(&'a str); + +impl Drop for PrintOnDrop<'_> { + fn drop(&mut self) { + println!("printint: {}", self.0); + } +} + +use std::collections::BTreeMap; +use std::iter::FromIterator; + +fn main() { + let s = String::from("Hello World!"); + let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]); + drop(s); //~ ERROR cannot move out of `s` because it is borrowed +} diff --git a/tests/ui/btreemap/btreemap_dropck.stderr b/tests/ui/btreemap/btreemap_dropck.stderr new file mode 100644 index 000000000..e953e7ae8 --- /dev/null +++ b/tests/ui/btreemap/btreemap_dropck.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `s` because it is borrowed + --> $DIR/btreemap_dropck.rs:15:10 + | +LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]); + | -- borrow of `s` occurs here +LL | drop(s); + | ^ move out of `s` occurs here +LL | } + | - borrow might be used here, when `_map` is dropped and runs the `Drop` code for type `BTreeMap` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/btreemap/btreemap_into_iterator_lifetime.rs b/tests/ui/btreemap/btreemap_into_iterator_lifetime.rs new file mode 100644 index 000000000..fda825bc6 --- /dev/null +++ b/tests/ui/btreemap/btreemap_into_iterator_lifetime.rs @@ -0,0 +1,23 @@ +// check-pass + +use std::collections::{BTreeMap, HashMap}; + +trait Map +where + for<'a> &'a Self: IntoIterator, +{ + type Key; + type Value; +} + +impl Map for HashMap { + type Key = K; + type Value = V; +} + +impl Map for BTreeMap { + type Key = K; + type Value = V; +} + +fn main() {} diff --git a/tests/ui/builtin-clone-unwind.rs b/tests/ui/builtin-clone-unwind.rs new file mode 100644 index 000000000..16add6ff2 --- /dev/null +++ b/tests/ui/builtin-clone-unwind.rs @@ -0,0 +1,61 @@ +// run-pass +// needs-unwind + +#![allow(unused_variables)] +#![allow(unused_imports)] + +// Test that builtin implementations of `Clone` cleanup everything +// in case of unwinding. + +use std::thread; +use std::rc::Rc; + +struct S(Rc<()>); + +impl Clone for S { + fn clone(&self) -> Self { + if Rc::strong_count(&self.0) == 7 { + panic!("oops"); + } + + S(self.0.clone()) + } +} + +fn main() { + let counter = Rc::new(()); + + // Unwinding with tuples... + let ccounter = counter.clone(); + let result = std::panic::catch_unwind(move || { + let _ = ( + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter) + ).clone(); + }); + + assert!(result.is_err()); + assert_eq!( + 1, + Rc::strong_count(&counter) + ); + + // ... and with arrays. + let ccounter = counter.clone(); + let child = std::panic::catch_unwind(move || { + let _ = [ + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter) + ].clone(); + }); + + assert!(child.is_err()); + assert_eq!( + 1, + Rc::strong_count(&counter) + ); +} diff --git a/tests/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs b/tests/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs new file mode 100644 index 000000000..acfd1e13e --- /dev/null +++ b/tests/ui/builtin-superkinds/auxiliary/trait_superkinds_in_metadata.rs @@ -0,0 +1,8 @@ +// Test library crate for cross-crate usages of traits inheriting +// from the builtin kinds. Mostly tests metadata correctness. + +#![crate_type="lib"] + +pub trait RequiresShare : Sync { } +pub trait RequiresRequiresShareAndSend : RequiresShare + Send { } +pub trait RequiresCopy : Copy { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-capabilities-transitive.rs b/tests/ui/builtin-superkinds/builtin-superkinds-capabilities-transitive.rs new file mode 100644 index 000000000..1f997d371 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-capabilities-transitive.rs @@ -0,0 +1,25 @@ +// run-pass +// Tests "transitivity" of super-builtin-kinds on traits. Here, if +// we have a Foo, we know we have a Bar, and if we have a Bar, we +// know we have a Send. So if we have a Foo we should know we have +// a Send. Basically this just makes sure rustc is using +// each_bound_trait_and_supertraits in type_contents correctly. + + +use std::sync::mpsc::{channel, Sender}; + +trait Bar : Send { } +trait Foo : Bar { } + +impl Foo for T { } +impl Bar for T { } + +fn foo(val: T, chan: Sender) { + chan.send(val).unwrap(); +} + +pub fn main() { + let (tx, rx) = channel(); + foo(31337, tx); + assert_eq!(rx.recv().unwrap(), 31337); +} diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-capabilities-xc.rs b/tests/ui/builtin-superkinds/builtin-superkinds-capabilities-xc.rs new file mode 100644 index 000000000..8416bb3a3 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-capabilities-xc.rs @@ -0,0 +1,27 @@ +// run-pass +// aux-build:trait_superkinds_in_metadata.rs + +// Tests "capabilities" granted by traits with super-builtin-kinds, +// even when using them cross-crate. + + +extern crate trait_superkinds_in_metadata; + +use std::sync::mpsc::{channel, Sender, Receiver}; +use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; + +#[derive(PartialEq, Debug)] +struct X(T); + +impl RequiresShare for X { } +impl RequiresRequiresShareAndSend for X { } + +fn foo(val: T, chan: Sender) { + chan.send(val).unwrap(); +} + +pub fn main() { + let (tx, rx): (Sender>, Receiver>) = channel(); + foo(X(31337), tx); + assert_eq!(rx.recv().unwrap(), X(31337)); +} diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-capabilities.rs b/tests/ui/builtin-superkinds/builtin-superkinds-capabilities.rs new file mode 100644 index 000000000..e936f921a --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-capabilities.rs @@ -0,0 +1,21 @@ +// run-pass +// Tests "capabilities" granted by traits that inherit from super- +// builtin-kinds, e.g., if a trait requires Send to implement, then +// at usage site of that trait, we know we have the Send capability. + + +use std::sync::mpsc::{channel, Sender, Receiver}; + +trait Foo : Send { } + +impl Foo for T { } + +fn foo(val: T, chan: Sender) { + chan.send(val).unwrap(); +} + +pub fn main() { + let (tx, rx): (Sender, Receiver) = channel(); + foo(31337, tx); + assert_eq!(rx.recv().unwrap(), 31337); +} diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs new file mode 100644 index 000000000..e716489c2 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.rs @@ -0,0 +1,14 @@ +// Test for traits that inherit from multiple builtin kinds at once, +// testing that all such kinds must be present on implementing types. + +trait Foo : Send+Sync { } + +impl Foo for (T,) { } +//~^ ERROR `T` cannot be sent between threads safely [E0277] + +impl Foo for (T,T) { } +//~^ ERROR `T` cannot be shared between threads safely [E0277] + +impl Foo for (T,T,T) { } // (ok) + +fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr new file mode 100644 index 000000000..592aa4369 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -0,0 +1,37 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/builtin-superkinds-double-superkind.rs:6:32 + | +LL | impl Foo for (T,) { } + | ^^^^ `T` cannot be sent between threads safely + | + = note: required because it appears within the type `(T,)` +note: required by a bound in `Foo` + --> $DIR/builtin-superkinds-double-superkind.rs:4:13 + | +LL | trait Foo : Send+Sync { } + | ^^^^ required by this bound in `Foo` +help: consider further restricting this bound + | +LL | impl Foo for (T,) { } + | +++++++++++++++++++ + +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/builtin-superkinds-double-superkind.rs:9:24 + | +LL | impl Foo for (T,T) { } + | ^^^^^ `T` cannot be shared between threads safely + | + = note: required because it appears within the type `(T, T)` +note: required by a bound in `Foo` + --> $DIR/builtin-superkinds-double-superkind.rs:4:18 + | +LL | trait Foo : Send+Sync { } + | ^^^^ required by this bound in `Foo` +help: consider further restricting this bound + | +LL | impl Foo for (T,T) { } + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs new file mode 100644 index 000000000..b4555a180 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.rs @@ -0,0 +1,16 @@ +// aux-build:trait_superkinds_in_metadata.rs + +// Test for traits inheriting from the builtin kinds cross-crate. +// Mostly tests correctness of metadata. + +extern crate trait_superkinds_in_metadata; +use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; + +struct X(T); + +impl RequiresShare for X { } + +impl RequiresRequiresShareAndSend for X { } +//~^ ERROR `T` cannot be sent between threads safely [E0277] + +fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr new file mode 100644 index 000000000..f9d548bb8 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -0,0 +1,24 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/builtin-superkinds-in-metadata.rs:13:56 + | +LL | impl RequiresRequiresShareAndSend for X { } + | ^^^^ `T` cannot be sent between threads safely + | +note: required because it appears within the type `X` + --> $DIR/builtin-superkinds-in-metadata.rs:9:8 + | +LL | struct X(T); + | ^ +note: required by a bound in `RequiresRequiresShareAndSend` + --> $DIR/auxiliary/trait_superkinds_in_metadata.rs:7:58 + | +LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { } + | ^^^^ required by this bound in `RequiresRequiresShareAndSend` +help: consider further restricting this bound + | +LL | impl RequiresRequiresShareAndSend for X { } + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs new file mode 100644 index 000000000..cdde48871 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(unused_imports)] + +// aux-build:trait_superkinds_in_metadata.rs + +// Tests (correct) usage of trait super-builtin-kinds cross-crate. + +extern crate trait_superkinds_in_metadata; +use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare}; +use trait_superkinds_in_metadata::RequiresCopy; +use std::marker; + +#[derive(Copy, Clone)] +struct X(#[allow(unused_tuple_struct_fields)] T); + +impl RequiresShare for X { } + +impl RequiresRequiresShareAndSend for X { } + +impl RequiresCopy for X { } + +pub fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-phantom-typaram.rs b/tests/ui/builtin-superkinds/builtin-superkinds-phantom-typaram.rs new file mode 100644 index 000000000..9b80664b0 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-phantom-typaram.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(dead_code)] +// Tests that even when a type parameter doesn't implement a required +// super-builtin-kind of a trait, if the type parameter is never used, +// the type can implement the trait anyway. + +// pretty-expanded FIXME #23616 + +use std::marker; + +trait Foo : Send { } + +struct X { marker: marker::PhantomData } + +impl Foo for X { } + +pub fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.rs b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.rs new file mode 100644 index 000000000..6fba87b31 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.rs @@ -0,0 +1,17 @@ +// Tests (negatively) the ability for the Self type in default methods +// to use capabilities granted by builtin kinds as supertraits. + +use std::sync::mpsc::{channel, Sender}; + +trait Foo : Sized+Sync+'static { + fn foo(self, mut chan: Sender) { } +} + +impl Foo for T { } +//~^ ERROR the parameter type `T` may not live long enough + +fn main() { + let (tx, rx) = channel(); + 1193182.foo(tx); + assert_eq!(rx.recv(), 1193182); +} diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr new file mode 100644 index 000000000..e2b177b95 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -0,0 +1,19 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/builtin-superkinds-self-type.rs:10:16 + | +LL | impl Foo for T { } + | ^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/builtin-superkinds-self-type.rs:6:24 + | +LL | trait Foo : Sized+Sync+'static { + | ^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | impl Foo for T { } + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple.rs b/tests/ui/builtin-superkinds/builtin-superkinds-simple.rs new file mode 100644 index 000000000..1620f8d5c --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple.rs @@ -0,0 +1,9 @@ +// Basic test for traits inheriting from the builtin kinds, checking +// the type contents of the implementing type (that's not a typaram). + +trait Foo : Send { } + +impl Foo for std::rc::Rc { } +//~^ ERROR `Rc` cannot be sent between threads safely + +fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr new file mode 100644 index 000000000..8b19170b0 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr @@ -0,0 +1,16 @@ +error[E0277]: `Rc` cannot be sent between threads safely + --> $DIR/builtin-superkinds-simple.rs:6:14 + | +LL | impl Foo for std::rc::Rc { } + | ^^^^^^^^^^^^^^^ `Rc` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `Rc` +note: required by a bound in `Foo` + --> $DIR/builtin-superkinds-simple.rs:4:13 + | +LL | trait Foo : Send { } + | ^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs new file mode 100644 index 000000000..8d2477157 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs @@ -0,0 +1,10 @@ +// run-pass +// Simple test case of implementing a trait with super-builtin-kinds. + +// pretty-expanded FIXME #23616 + +trait Foo : Send { } + +impl Foo for isize { } + +pub fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs new file mode 100644 index 000000000..74ae62711 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.rs @@ -0,0 +1,8 @@ +// Basic test for traits inheriting from the builtin kinds. + +trait Foo : Send { } + +impl Foo for T { } +//~^ ERROR `T` cannot be sent between threads safely + +fn main() { } diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr new file mode 100644 index 000000000..0cfea72d5 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -0,0 +1,19 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/builtin-superkinds-typaram-not-send.rs:5:32 + | +LL | impl Foo for T { } + | ^ `T` cannot be sent between threads safely + | +note: required by a bound in `Foo` + --> $DIR/builtin-superkinds-typaram-not-send.rs:3:13 + | +LL | trait Foo : Send { } + | ^^^^ required by this bound in `Foo` +help: consider further restricting this bound + | +LL | impl Foo for T { } + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs new file mode 100644 index 000000000..f999dfff7 --- /dev/null +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs @@ -0,0 +1,11 @@ +// run-pass +// Tests correct implementation of traits with super-builtin-kinds +// using a bounded type parameter. + +// pretty-expanded FIXME #23616 + +trait Foo : Send { } + +impl Foo for T { } + +pub fn main() { } diff --git a/tests/ui/by-move-pattern-binding.rs b/tests/ui/by-move-pattern-binding.rs new file mode 100644 index 000000000..f68d18129 --- /dev/null +++ b/tests/ui/by-move-pattern-binding.rs @@ -0,0 +1,29 @@ +enum E { + Foo, + Bar(String) +} + +struct S { + x: E +} + +fn f(x: String) {} + +fn main() { + let s = S { x: E::Bar("hello".to_string()) }; + match &s.x { //~ ERROR cannot move + &E::Foo => {} + &E::Bar(identifier) => f(identifier.clone()) + }; + match &s.x { + &E::Foo => {} + &E::Bar(ref identifier) => println!("{}", *identifier) + }; + if let &E::Bar(identifier) = &s.x { //~ ERROR cannot move + f(identifier.clone()); + }; + let &E::Bar(identifier) = &s.x else { //~ ERROR cannot move + return; + }; + f(identifier.clone()); +} diff --git a/tests/ui/by-move-pattern-binding.stderr b/tests/ui/by-move-pattern-binding.stderr new file mode 100644 index 000000000..203e37dc3 --- /dev/null +++ b/tests/ui/by-move-pattern-binding.stderr @@ -0,0 +1,51 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/by-move-pattern-binding.rs:14:11 + | +LL | match &s.x { + | ^^^^ +LL | &E::Foo => {} +LL | &E::Bar(identifier) => f(identifier.clone()) + | ---------- + | | + | data moved here + | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &E::Bar(identifier) => f(identifier.clone()) +LL + E::Bar(identifier) => f(identifier.clone()) + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/by-move-pattern-binding.rs:22:34 + | +LL | if let &E::Bar(identifier) = &s.x { + | ---------- ^^^^ + | | + | data moved here + | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - if let &E::Bar(identifier) = &s.x { +LL + if let E::Bar(identifier) = &s.x { + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/by-move-pattern-binding.rs:25:31 + | +LL | let &E::Bar(identifier) = &s.x else { + | ---------- ^^^^ + | | + | data moved here + | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - let &E::Bar(identifier) = &s.x else { +LL + let E::Bar(identifier) = &s.x else { + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs new file mode 100644 index 000000000..fce6210b2 --- /dev/null +++ b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs @@ -0,0 +1,17 @@ +fn efiapi(f: extern "efiapi" fn(usize, ...)) { + //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + f(22, 44); +} +fn sysv(f: extern "sysv64" fn(usize, ...)) { + //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + f(22, 44); +} +fn win(f: extern "win64" fn(usize, ...)) { + //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + f(22, 44); +} + +fn main() {} diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr new file mode 100644 index 000000000..5b97b396f --- /dev/null +++ b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr @@ -0,0 +1,49 @@ +error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + --> $DIR/feature-gate-extended_varargs_abi_support.rs:1:14 + | +LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #100189 for more information + = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable + +error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + --> $DIR/feature-gate-extended_varargs_abi_support.rs:1:14 + | +LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + --> $DIR/feature-gate-extended_varargs_abi_support.rs:6:12 + | +LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #100189 for more information + = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable + +error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + --> $DIR/feature-gate-extended_varargs_abi_support.rs:6:12 + | +LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 + | +LL | fn win(f: extern "win64" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #100189 for more information + = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable + +error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 + | +LL | fn win(f: extern "win64" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0045, E0658. +For more information about an error, try `rustc --explain E0045`. diff --git a/tests/ui/c-variadic/issue-32201.rs b/tests/ui/c-variadic/issue-32201.rs new file mode 100644 index 000000000..f27bb1c2e --- /dev/null +++ b/tests/ui/c-variadic/issue-32201.rs @@ -0,0 +1,13 @@ +extern "C" { + fn foo(a: i32, ...); +} + +fn bar(_: *const u8) {} + +fn main() { + unsafe { + foo(0, bar); + //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function + //~| HELP cast the value to `fn(*const u8)` + } +} diff --git a/tests/ui/c-variadic/issue-32201.stderr b/tests/ui/c-variadic/issue-32201.stderr new file mode 100644 index 000000000..cedb58784 --- /dev/null +++ b/tests/ui/c-variadic/issue-32201.stderr @@ -0,0 +1,9 @@ +error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function + --> $DIR/issue-32201.rs:9:16 + | +LL | foo(0, bar); + | ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0617`. diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs new file mode 100644 index 000000000..49d5c0390 --- /dev/null +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -0,0 +1,12 @@ +// Regression test for the ICE described in issue #86053. +// error-pattern:unexpected `self` parameter in function +// error-pattern:`...` must be the last argument of a C-variadic function +// error-pattern:cannot find type `F` in this scope + + +#![feature(c_variadic)] +#![crate_type="lib"] + +fn ordering4 < 'a , 'b > ( a : , self , self , self , + self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { +} diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr new file mode 100644 index 000000000..5a02f4aa9 --- /dev/null +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -0,0 +1,81 @@ +error: expected type, found `,` + --> $DIR/issue-86053-1.rs:10:47 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^ expected type + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:10:51 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:10:58 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:10:67 + | +LL | fn ordering4 < 'a , 'b > ( a : , self , self , self , + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:11:5 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:11:20 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function + +error: unexpected `self` parameter in function + --> $DIR/issue-86053-1.rs:11:29 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^^ must be the first parameter of an associated function + +error: `...` must be the last argument of a C-variadic function + --> $DIR/issue-86053-1.rs:11:12 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/issue-86053-1.rs:11:12 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/issue-86053-1.rs:11:36 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^^^ + +error[E0412]: cannot find type `F` in this scope + --> $DIR/issue-86053-1.rs:11:48 + | +LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { + | ^ + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here + | +help: a trait with a similar name exists + | +LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) { + | ~~ +help: you might be missing a type parameter + | +LL | fn ordering4 < 'a , 'b, F > ( a : , self , self , self , + | +++ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/c-variadic/issue-86053-2.rs b/tests/ui/c-variadic/issue-86053-2.rs new file mode 100644 index 000000000..c545831f7 --- /dev/null +++ b/tests/ui/c-variadic/issue-86053-2.rs @@ -0,0 +1,11 @@ +// Regression test for the ICE caused by the example in +// https://github.com/rust-lang/rust/issues/86053#issuecomment-855672258 + +#![feature(c_variadic)] + +trait H {} + +unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} +//~^ ERROR: in type `&'static &'a ()`, reference has a longer lifetime than the data it references [E0491] + +fn main() {} diff --git a/tests/ui/c-variadic/issue-86053-2.stderr b/tests/ui/c-variadic/issue-86053-2.stderr new file mode 100644 index 000000000..815b06e77 --- /dev/null +++ b/tests/ui/c-variadic/issue-86053-2.stderr @@ -0,0 +1,16 @@ +error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/issue-86053-2.rs:8:39 + | +LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/issue-86053-2.rs:8:32 + | +LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {} + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/c-variadic/variadic-ffi-1.rs b/tests/ui/c-variadic/variadic-ffi-1.rs new file mode 100644 index 000000000..acd8a25dc --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-1.rs @@ -0,0 +1,35 @@ +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "stdcall" { + fn printf(_: *const u8, ...); + //~^ ERROR: C-variadic function must have a compatible calling convention, + // like C, cdecl, win64, sysv64 or efiapi +} + +extern "C" { + fn foo(f: isize, x: u8, ...); +} + +extern "C" fn bar(f: isize, x: u8) {} + +fn main() { + unsafe { + foo(); //~ ERROR function takes at least 2 arguments but 0 arguments were supplied + foo(1); //~ ERROR function takes at least 2 arguments but 1 argument was supplied + + let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~ ERROR mismatched types + let y: extern "C" fn(f: isize, x: u8, ...) = bar; //~ ERROR mismatched types + + foo(1, 2, 3f32); //~ ERROR can't pass + foo(1, 2, true); //~ ERROR can't pass + foo(1, 2, 1i8); //~ ERROR can't pass + foo(1, 2, 1u8); //~ ERROR can't pass + foo(1, 2, 1i16); //~ ERROR can't pass + foo(1, 2, 1u16); //~ ERROR can't pass + } +} diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr new file mode 100644 index 000000000..4beea83d8 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -0,0 +1,100 @@ +error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + --> $DIR/variadic-ffi-1.rs:9:5 + | +LL | fn printf(_: *const u8, ...); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied + --> $DIR/variadic-ffi-1.rs:22:9 + | +LL | foo(); + | ^^^-- two arguments of type `isize` and `u8` are missing + | +note: function defined here + --> $DIR/variadic-ffi-1.rs:15:8 + | +LL | fn foo(f: isize, x: u8, ...); + | ^^^ +help: provide the arguments + | +LL | foo(/* isize */, /* u8 */); + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0060]: this function takes at least 2 arguments but 1 argument was supplied + --> $DIR/variadic-ffi-1.rs:23:9 + | +LL | foo(1); + | ^^^--- an argument of type `u8` is missing + | +note: function defined here + --> $DIR/variadic-ffi-1.rs:15:8 + | +LL | fn foo(f: isize, x: u8, ...); + | ^^^ +help: provide the argument + | +LL | foo(1, /* u8 */); + | ~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-1.rs:25:56 + | +LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; + | ------------------------------------- ^^^ expected non-variadic fn, found variadic function + | | + | expected due to this + | + = note: expected fn pointer `unsafe extern "C" fn(_, _)` + found fn item `unsafe extern "C" fn(_, _, ...) {foo}` + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-1.rs:26:54 + | +LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; + | ----------------------------------- ^^^ expected variadic fn, found non-variadic function + | | + | expected due to this + | + = note: expected fn pointer `extern "C" fn(_, _, ...)` + found fn item `extern "C" fn(_, _) {bar}` + +error[E0617]: can't pass `f32` to variadic function + --> $DIR/variadic-ffi-1.rs:28:19 + | +LL | foo(1, 2, 3f32); + | ^^^^ help: cast the value to `c_double`: `3f32 as c_double` + +error[E0617]: can't pass `bool` to variadic function + --> $DIR/variadic-ffi-1.rs:29:19 + | +LL | foo(1, 2, true); + | ^^^^ help: cast the value to `c_int`: `true as c_int` + +error[E0617]: can't pass `i8` to variadic function + --> $DIR/variadic-ffi-1.rs:30:19 + | +LL | foo(1, 2, 1i8); + | ^^^ help: cast the value to `c_int`: `1i8 as c_int` + +error[E0617]: can't pass `u8` to variadic function + --> $DIR/variadic-ffi-1.rs:31:19 + | +LL | foo(1, 2, 1u8); + | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint` + +error[E0617]: can't pass `i16` to variadic function + --> $DIR/variadic-ffi-1.rs:32:19 + | +LL | foo(1, 2, 1i16); + | ^^^^ help: cast the value to `c_int`: `1i16 as c_int` + +error[E0617]: can't pass `u16` to variadic function + --> $DIR/variadic-ffi-1.rs:33:19 + | +LL | foo(1, 2, 1u16); + | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint` + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0045, E0060, E0308, E0617. +For more information about an error, try `rustc --explain E0045`. diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs new file mode 100644 index 000000000..c34b7e55f --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-2.rs @@ -0,0 +1,20 @@ +// ignore-arm stdcall isn't supported +#![feature(extended_varargs_abi_support)] + +fn baz(f: extern "stdcall" fn(usize, ...)) { + //~^ ERROR: C-variadic function must have a compatible calling convention, + // like C, cdecl, win64, sysv64 or efiapi + f(22, 44); +} + +fn sysv(f: extern "sysv64" fn(usize, ...)) { + f(22, 44); +} +fn win(f: extern "win64" fn(usize, ...)) { + f(22, 44); +} +fn efiapi(f: extern "efiapi" fn(usize, ...)) { + f(22, 44); +} + +fn main() {} diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr new file mode 100644 index 000000000..e21001eca --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -0,0 +1,9 @@ +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `win64`, `sysv64` or `efiapi` + --> $DIR/variadic-ffi-2.rs:4:11 + | +LL | fn baz(f: extern "stdcall" fn(usize, ...)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0045`. diff --git a/tests/ui/c-variadic/variadic-ffi-4.rs b/tests/ui/c-variadic/variadic-ffi-4.rs new file mode 100644 index 000000000..806403794 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-4.rs @@ -0,0 +1,38 @@ +#![crate_type = "lib"] +#![no_std] +#![feature(c_variadic)] + +use core::ffi::{VaList, VaListImpl}; + +pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { + ap + //~^ ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough +} + +pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { + ap //~ ERROR: lifetime may not live long enough +} + +pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { + let _ = ap.with_copy(|ap| ap); //~ ERROR: lifetime may not live long enough +} + +pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + *ap0 = ap1; + //~^ ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough +} + +pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + ap0 = &mut ap1; + //~^ ERROR: `ap1` does not live long enough + //~| ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough +} + +pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + *ap0 = ap1.clone(); + //~^ ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough +} diff --git a/tests/ui/c-variadic/variadic-ffi-4.stderr b/tests/ui/c-variadic/variadic-ffi-4.stderr new file mode 100644 index 000000000..6f8e53298 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-4.stderr @@ -0,0 +1,150 @@ +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:8:5 + | +LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { + | -- -- has type `VaListImpl<'1>` + | | + | lifetime `'f` defined here +LL | ap + | ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:8:5 + | +LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { + | -- -- has type `VaListImpl<'1>` + | | + | lifetime `'f` defined here +LL | ap + | ^^ function was supposed to return data with lifetime `'f` but it is returning data with lifetime `'1` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:14:5 + | +LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> { + | -- has type `VaListImpl<'1>` +LL | ap + | ^^ returning this value requires that `'1` must outlive `'static` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:18:31 + | +LL | let _ = ap.with_copy(|ap| ap); + | --- ^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure is VaList<'2, '_> + | has type `VaList<'1, '_>` + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:22:5 + | +LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | ------- ------- has type `VaListImpl<'2>` + | | + | has type `&mut VaListImpl<'1>` +LL | *ap0 = ap1; + | ^^^^ assignment requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:22:5 + | +LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | ------- ------- has type `VaListImpl<'2>` + | | + | has type `&mut VaListImpl<'1>` +LL | *ap0 = ap1; + | ^^^^ assignment requires that `'2` must outlive `'1` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:28:5 + | +LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | ------- ------- has type `VaListImpl<'2>` + | | + | has type `&mut VaListImpl<'1>` +LL | ap0 = &mut ap1; + | ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` + | + = note: requirement occurs because of a mutable reference to `VaListImpl<'_>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:28:5 + | +LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | ------- ------- has type `VaListImpl<'2>` + | | + | has type `&mut VaListImpl<'1>` +LL | ap0 = &mut ap1; + | ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1` + | + = note: requirement occurs because of a mutable reference to `VaListImpl<'_>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error[E0597]: `ap1` does not live long enough + --> $DIR/variadic-ffi-4.rs:28:11 + | +LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | - let's call the lifetime of this reference `'3` +LL | ap0 = &mut ap1; + | ------^^^^^^^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `ap1` is borrowed for `'3` +... +LL | } + | - `ap1` dropped here while still borrowed + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:35:12 + | +LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | ------- ------- has type `VaListImpl<'2>` + | | + | has type `&mut VaListImpl<'1>` +LL | *ap0 = ap1.clone(); + | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variadic-ffi-4.rs:35:12 + | +LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { + | ------- ------- has type `VaListImpl<'2>` + | | + | has type `&mut VaListImpl<'1>` +LL | *ap0 = ap1.clone(); + | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1` + | + = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant + = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` + = help: see for more information about variance + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/c-variadic/variadic-ffi-6.rs b/tests/ui/c-variadic/variadic-ffi-6.rs new file mode 100644 index 000000000..4dd8a2d45 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-6.rs @@ -0,0 +1,13 @@ +#![crate_type="lib"] +#![feature(c_variadic)] + +pub unsafe extern "C" fn use_vararg_lifetime( + x: usize, + y: ... +) -> &usize { //~ ERROR missing lifetime specifier + &0 +} + +pub unsafe extern "C" fn use_normal_arg_lifetime(x: &usize, y: ...) -> &usize { // OK + x +} diff --git a/tests/ui/c-variadic/variadic-ffi-6.stderr b/tests/ui/c-variadic/variadic-ffi-6.stderr new file mode 100644 index 000000000..4c7792d96 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-6.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/variadic-ffi-6.rs:7:6 + | +LL | ) -> &usize { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | ) -> &'static usize { + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/c-variadic/variadic-ffi-no-fixed-args.rs b/tests/ui/c-variadic/variadic-ffi-no-fixed-args.rs new file mode 100644 index 000000000..588c15a18 --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-no-fixed-args.rs @@ -0,0 +1,6 @@ +extern "C" { + fn foo(...); +//~^ ERROR C-variadic function must be declared with at least one named argument +} + +fn main() {} diff --git a/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr new file mode 100644 index 000000000..e11ba43ca --- /dev/null +++ b/tests/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -0,0 +1,8 @@ +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-no-fixed-args.rs:2:12 + | +LL | fn foo(...); + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/c-variadic/variadic-unreachable-arg-error.rs b/tests/ui/c-variadic/variadic-unreachable-arg-error.rs new file mode 100644 index 000000000..f60f6f3e8 --- /dev/null +++ b/tests/ui/c-variadic/variadic-unreachable-arg-error.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(c_variadic)] + +extern "C" { + fn foo(f: isize, x: u8, ...); +} + +fn main() { + unsafe { + // FIXME: Ideally we could give an unreachable warning + foo(1, loop {}, 1usize); + } +} diff --git a/tests/ui/can-copy-pod.rs b/tests/ui/can-copy-pod.rs new file mode 100644 index 000000000..e6c57ca3f --- /dev/null +++ b/tests/ui/can-copy-pod.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that type parameters with the `Copy` are implicitly copyable. + +#![allow(dead_code)] + +fn can_copy_copy(v: T) { + let _a = v; + let _b = v; +} + +pub fn main() {} diff --git a/tests/ui/cancel-clean-via-immediate-rvalue-ref.rs b/tests/ui/cancel-clean-via-immediate-rvalue-ref.rs new file mode 100644 index 000000000..a0a561ab2 --- /dev/null +++ b/tests/ui/cancel-clean-via-immediate-rvalue-ref.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn foo(x: &mut Box) { + *x = Box::new(5); +} + +pub fn main() { + foo(&mut Box::new(4)); +} diff --git a/tests/ui/cannot-mutate-captured-non-mut-var.rs b/tests/ui/cannot-mutate-captured-non-mut-var.rs new file mode 100644 index 000000000..952dab25b --- /dev/null +++ b/tests/ui/cannot-mutate-captured-non-mut-var.rs @@ -0,0 +1,15 @@ +#![feature(unboxed_closures, tuple_trait)] + +use std::io::Read; + +fn to_fn_once>(f: F) -> F { f } + +fn main() { + let x = 1; + to_fn_once(move|| { x = 2; }); + //~^ ERROR: cannot assign to `x`, as it is not declared as mutable + + let s = std::io::stdin(); + to_fn_once(move|| { s.read_to_end(&mut Vec::new()); }); + //~^ ERROR: cannot borrow `s` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/cannot-mutate-captured-non-mut-var.stderr b/tests/ui/cannot-mutate-captured-non-mut-var.stderr new file mode 100644 index 000000000..06b5ca407 --- /dev/null +++ b/tests/ui/cannot-mutate-captured-non-mut-var.stderr @@ -0,0 +1,20 @@ +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/cannot-mutate-captured-non-mut-var.rs:9:25 + | +LL | let x = 1; + | - help: consider changing this to be mutable: `mut x` +LL | to_fn_once(move|| { x = 2; }); + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable + --> $DIR/cannot-mutate-captured-non-mut-var.rs:13:25 + | +LL | let s = std::io::stdin(); + | - help: consider changing this to be mutable: `mut s` +LL | to_fn_once(move|| { s.read_to_end(&mut Vec::new()); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/capture1.rs b/tests/ui/capture1.rs new file mode 100644 index 000000000..2938c0845 --- /dev/null +++ b/tests/ui/capture1.rs @@ -0,0 +1,6 @@ +// error-pattern: can't capture dynamic environment in a fn item + +fn main() { + let bar: isize = 5; + fn foo() -> isize { return bar; } +} diff --git a/tests/ui/capture1.stderr b/tests/ui/capture1.stderr new file mode 100644 index 000000000..ad8434709 --- /dev/null +++ b/tests/ui/capture1.stderr @@ -0,0 +1,11 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/capture1.rs:5:32 + | +LL | fn foo() -> isize { return bar; } + | ^^^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/cast/cast-as-bool.rs b/tests/ui/cast/cast-as-bool.rs new file mode 100644 index 000000000..fbebc80d9 --- /dev/null +++ b/tests/ui/cast/cast-as-bool.rs @@ -0,0 +1,13 @@ +fn main() { + let u = 5 as bool; //~ ERROR cannot cast as `bool` + //~| HELP compare with zero instead + //~| SUGGESTION 5 != 0 + + let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool` + //~| HELP compare with zero instead + //~| SUGGESTION (1 + 2) != 0 + + let v = "hello" as bool; + //~^ ERROR casting `&'static str` as `bool` is invalid + //~| HELP consider using the `is_empty` method on `&'static str` to determine if it contains anything +} diff --git a/tests/ui/cast/cast-as-bool.stderr b/tests/ui/cast/cast-as-bool.stderr new file mode 100644 index 000000000..19ac8f10f --- /dev/null +++ b/tests/ui/cast/cast-as-bool.stderr @@ -0,0 +1,27 @@ +error[E0054]: cannot cast as `bool` + --> $DIR/cast-as-bool.rs:2:13 + | +LL | let u = 5 as bool; + | ^^^^^^^^^ help: compare with zero instead: `5 != 0` + +error[E0054]: cannot cast as `bool` + --> $DIR/cast-as-bool.rs:6:13 + | +LL | let t = (1 + 2) as bool; + | ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0` + +error[E0606]: casting `&'static str` as `bool` is invalid + --> $DIR/cast-as-bool.rs:10:13 + | +LL | let v = "hello" as bool; + | ^^^^^^^^^^^^^^^ + | +help: consider using the `is_empty` method on `&'static str` to determine if it contains anything + | +LL | let v = !"hello".is_empty(); + | + ~~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0054, E0606. +For more information about an error, try `rustc --explain E0054`. diff --git a/tests/ui/cast/cast-char.rs b/tests/ui/cast/cast-char.rs new file mode 100644 index 000000000..9634ed56f --- /dev/null +++ b/tests/ui/cast/cast-char.rs @@ -0,0 +1,10 @@ +#![deny(overflowing_literals)] + +fn main() { + const XYZ: char = 0x1F888 as char; + //~^ ERROR only `u8` can be cast into `char` + const XY: char = 129160 as char; + //~^ ERROR only `u8` can be cast into `char` + const ZYX: char = '\u{01F888}'; + println!("{}", XYZ); +} diff --git a/tests/ui/cast/cast-char.stderr b/tests/ui/cast/cast-char.stderr new file mode 100644 index 000000000..211937c9d --- /dev/null +++ b/tests/ui/cast/cast-char.stderr @@ -0,0 +1,20 @@ +error: only `u8` can be cast into `char` + --> $DIR/cast-char.rs:4:23 + | +LL | const XYZ: char = 0x1F888 as char; + | ^^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'` + | +note: the lint level is defined here + --> $DIR/cast-char.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: only `u8` can be cast into `char` + --> $DIR/cast-char.rs:6:22 + | +LL | const XY: char = 129160 as char; + | ^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/cast/cast-does-fallback.rs b/tests/ui/cast/cast-does-fallback.rs new file mode 100644 index 000000000..770f7a31c --- /dev/null +++ b/tests/ui/cast/cast-does-fallback.rs @@ -0,0 +1,12 @@ +// run-pass + +pub fn main() { + // Test that these type check correctly. + (&42u8 >> 4) as usize; + (&42u8 << 4) as usize; + + let cap = 512 * 512; + cap as u8; + // Assert `cap` did not get inferred to `u8` and overflowed. + assert_ne!(cap, 0); +} diff --git a/tests/ui/cast/cast-errors-issue-43825.rs b/tests/ui/cast/cast-errors-issue-43825.rs new file mode 100644 index 000000000..00e0da44b --- /dev/null +++ b/tests/ui/cast/cast-errors-issue-43825.rs @@ -0,0 +1,7 @@ +fn main() { + let error = error; //~ ERROR cannot find value `error` + + // These used to cause errors. + 0 as f32; + 0.0 as u32; +} diff --git a/tests/ui/cast/cast-errors-issue-43825.stderr b/tests/ui/cast/cast-errors-issue-43825.stderr new file mode 100644 index 000000000..1e77f5dbd --- /dev/null +++ b/tests/ui/cast/cast-errors-issue-43825.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `error` in this scope + --> $DIR/cast-errors-issue-43825.rs:2:17 + | +LL | let error = error; + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/cast/cast-from-nil.rs b/tests/ui/cast/cast-from-nil.rs new file mode 100644 index 000000000..b5ceef76a --- /dev/null +++ b/tests/ui/cast/cast-from-nil.rs @@ -0,0 +1,2 @@ +// error-pattern: non-primitive cast: `()` as `u32` +fn main() { let u = (assert!(true) as u32); } diff --git a/tests/ui/cast/cast-from-nil.stderr b/tests/ui/cast/cast-from-nil.stderr new file mode 100644 index 000000000..dab133cfb --- /dev/null +++ b/tests/ui/cast/cast-from-nil.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `()` as `u32` + --> $DIR/cast-from-nil.rs:2:21 + | +LL | fn main() { let u = (assert!(true) as u32); } + | ^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/cast-int-to-char.rs b/tests/ui/cast/cast-int-to-char.rs new file mode 100644 index 000000000..379956968 --- /dev/null +++ b/tests/ui/cast/cast-int-to-char.rs @@ -0,0 +1,9 @@ +fn foo(_t: T) {} + +fn main() { + foo::('0'); //~ ERROR + foo::('0'); //~ ERROR + foo::('0'); //~ ERROR + foo::('0'); //~ ERROR + foo::(0u32); //~ ERROR +} diff --git a/tests/ui/cast/cast-int-to-char.stderr b/tests/ui/cast/cast-int-to-char.stderr new file mode 100644 index 000000000..ef606b6ae --- /dev/null +++ b/tests/ui/cast/cast-int-to-char.stderr @@ -0,0 +1,89 @@ +error[E0308]: mismatched types + --> $DIR/cast-int-to-char.rs:4:16 + | +LL | foo::('0'); + | ---------- ^^^ expected `u32`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/cast-int-to-char.rs:1:4 + | +LL | fn foo(_t: T) {} + | ^^^ ----- +help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes + | +LL | foo::('0' as u32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/cast-int-to-char.rs:5:16 + | +LL | foo::('0'); + | ---------- ^^^ expected `i32`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/cast-int-to-char.rs:1:4 + | +LL | fn foo(_t: T) {} + | ^^^ ----- +help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes + | +LL | foo::('0' as i32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/cast-int-to-char.rs:6:16 + | +LL | foo::('0'); + | ---------- ^^^ expected `u64`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/cast-int-to-char.rs:1:4 + | +LL | fn foo(_t: T) {} + | ^^^ ----- +help: you can cast a `char` to a `u64`, since a `char` always occupies 4 bytes + | +LL | foo::('0' as u64); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/cast-int-to-char.rs:7:16 + | +LL | foo::('0'); + | ---------- ^^^ expected `i64`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/cast-int-to-char.rs:1:4 + | +LL | fn foo(_t: T) {} + | ^^^ ----- +help: you can cast a `char` to an `i64`, since a `char` always occupies 4 bytes + | +LL | foo::('0' as i64); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/cast-int-to-char.rs:8:17 + | +LL | foo::(0u32); + | ----------- ^^^^ expected `char`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/cast-int-to-char.rs:1:4 + | +LL | fn foo(_t: T) {} + | ^^^ ----- + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/cast/cast-macro-lhs.rs b/tests/ui/cast/cast-macro-lhs.rs new file mode 100644 index 000000000..b509b3239 --- /dev/null +++ b/tests/ui/cast/cast-macro-lhs.rs @@ -0,0 +1,12 @@ +// Test to make sure we suggest "consider casting" on the right span + +macro_rules! foo { + () => { 0 } +} + +fn main() { + let x = foo!() as *const [u8]; + //~^ ERROR cannot cast `usize` to a pointer that is wide + //~| NOTE creating a `*const [u8]` requires both an address and a length + //~| NOTE consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` +} diff --git a/tests/ui/cast/cast-macro-lhs.stderr b/tests/ui/cast/cast-macro-lhs.stderr new file mode 100644 index 000000000..db7ce57e1 --- /dev/null +++ b/tests/ui/cast/cast-macro-lhs.stderr @@ -0,0 +1,11 @@ +error[E0606]: cannot cast `usize` to a pointer that is wide + --> $DIR/cast-macro-lhs.rs:8:23 + | +LL | let x = foo!() as *const [u8]; + | ------ ^^^^^^^^^^^ creating a `*const [u8]` requires both an address and a length + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/cast-pointee-projection.rs b/tests/ui/cast/cast-pointee-projection.rs new file mode 100644 index 000000000..f51c5f20f --- /dev/null +++ b/tests/ui/cast/cast-pointee-projection.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Tag<'a> { + type Type: ?Sized; +} + +trait IntoRaw: for<'a> Tag<'a> { + fn into_raw(this: *const >::Type) -> *mut >::Type; +} + +impl Tag<'a>> IntoRaw for T { + fn into_raw(this: *const >::Type) -> *mut >::Type { + this as *mut T::Type + } +} + +fn main() {} diff --git a/tests/ui/cast/cast-region-to-uint.rs b/tests/ui/cast/cast-region-to-uint.rs new file mode 100644 index 000000000..33ec2d276 --- /dev/null +++ b/tests/ui/cast/cast-region-to-uint.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let x: isize = 3; + println!("&x={:x}", (&x as *const isize as usize)); +} diff --git a/tests/ui/cast/cast-rfc0401-2.rs b/tests/ui/cast/cast-rfc0401-2.rs new file mode 100644 index 000000000..7709aa341 --- /dev/null +++ b/tests/ui/cast/cast-rfc0401-2.rs @@ -0,0 +1,8 @@ +// RFC 401 test extracted into distinct file. This is because some the +// change to suppress "derived" errors wound up suppressing this error +// message, since the fallback for `3` doesn't occur. + +fn main() { + let _ = 3 as bool; + //~^ ERROR cannot cast as `bool` +} diff --git a/tests/ui/cast/cast-rfc0401-2.stderr b/tests/ui/cast/cast-rfc0401-2.stderr new file mode 100644 index 000000000..52f6af78a --- /dev/null +++ b/tests/ui/cast/cast-rfc0401-2.stderr @@ -0,0 +1,9 @@ +error[E0054]: cannot cast as `bool` + --> $DIR/cast-rfc0401-2.rs:6:13 + | +LL | let _ = 3 as bool; + | ^^^^^^^^^ help: compare with zero instead: `3 != 0` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0054`. diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs new file mode 100644 index 000000000..249481467 --- /dev/null +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs @@ -0,0 +1,62 @@ +// run-pass +// Check that you can cast between different pointers to trait objects +// whose vtable have the same kind (both lengths, or both trait pointers). + +#![feature(unsized_tuple_coercion)] + +trait Foo { + fn foo(&self, _: T) -> u32 { 42 } +} + +trait Bar { + fn bar(&self) { println!("Bar!"); } +} + +impl Foo for () {} +impl Foo for u32 { fn foo(&self, _: u32) -> u32 { self+43 } } +impl Bar for () {} + +unsafe fn round_trip_and_call<'a>(t: *const (dyn Foo+'a)) -> u32 { + let foo_e : *const dyn Foo = t as *const _; + let r_1 = foo_e as *mut dyn Foo; + + (&*r_1).foo(0) +} + +#[repr(C)] +struct FooS(T); +#[repr(C)] +struct BarS(T); + +fn foo_to_bar(u: *const FooS) -> *const BarS { + u as *const BarS +} + +fn tuple_i32_to_u32(u: *const (i32, T)) -> *const (u32, T) { + u as *const (u32, T) +} + + +fn main() { + let x = 4u32; + let y : &dyn Foo = &x; + let fl = unsafe { round_trip_and_call(y as *const dyn Foo) }; + assert_eq!(fl, (43+4)); + + let s = FooS([0,1,2]); + let u: &FooS<[u32]> = &s; + let u: *const FooS<[u32]> = u; + let bar_ref : *const BarS<[u32]> = foo_to_bar(u); + let z : &BarS<[u32]> = unsafe{&*bar_ref}; + assert_eq!(&z.0, &[0,1,2]); + + // this assumes that tuple reprs for (i32, _) and (u32, _) are + // the same. + let s = (0i32, [0, 1, 2]); + let u: &(i32, [u8]) = &s; + let u: *const (i32, [u8]) = u; + let u_u32 : *const (u32, [u8]) = tuple_i32_to_u32(u); + unsafe { + assert_eq!(&(*u_u32).1, &[0, 1, 2]); + } +} diff --git a/tests/ui/cast/cast-rfc0401.rs b/tests/ui/cast/cast-rfc0401.rs new file mode 100644 index 000000000..9a9875416 --- /dev/null +++ b/tests/ui/cast/cast-rfc0401.rs @@ -0,0 +1,169 @@ +// run-pass + +#![allow(dead_code)] + +use std::vec; + +enum Simple { + A, + B, + C +} + +enum Valued { + H8=163, + Z=0, + X=256, + H7=67, +} + +enum ValuedSigned { + M1=-1, + P1=1 +} + +fn main() +{ + // coercion-cast + let mut it = vec![137].into_iter(); + let itr: &mut vec::IntoIter = &mut it; + assert_eq!((itr as &mut dyn Iterator).next(), Some(137)); + assert_eq!((itr as &mut dyn Iterator).next(), None); + + assert_eq!(Some(4u32) as Option, Some(4u32)); + assert_eq!((1u32,2u32) as (u32,u32), (1,2)); + + // this isn't prim-int-cast. Check that it works. + assert_eq!(false as bool, false); + assert_eq!(true as bool, true); + + // numeric-cast + let l: u64 = 0x8090a0b0c0d0e0f0; + let lsz: usize = l as usize; + assert_eq!(l as u32, 0xc0d0e0f0); + + // numeric-cast + assert_eq!(l as u8, 0xf0); + assert_eq!(l as i8,-0x10); + assert_eq!(l as u32, 0xc0d0e0f0); + assert_eq!(l as u32 as usize as u32, l as u32); + assert_eq!(l as i32,-0x3f2f1f10); + assert_eq!(l as i32 as isize as i32, l as i32); + assert_eq!(l as i64,-0x7f6f5f4f3f2f1f10); + + assert_eq!(0 as f64, 0f64); + assert_eq!(1 as f64, 1f64); + + assert_eq!(l as f64, 9264081114510712022f64); + + assert_eq!(l as i64 as f64, -9182662959198838444f64); +// float overflow : needs fixing +// assert_eq!(l as f32 as i64 as u64, 9264082620822882088u64); +// assert_eq!(l as i64 as f32 as i64, 9182664080220408446i64); + + assert_eq!(4294967040f32 as u32, 0xffffff00u32); + assert_eq!(1.844674407370955e19f64 as u64, 0xfffffffffffff800u64); + + assert_eq!(9.223372036854775e18f64 as i64, 0x7ffffffffffffc00i64); + assert_eq!(-9.223372036854776e18f64 as i64, 0x8000000000000000u64 as i64); + + // addr-ptr-cast/ptr-addr-cast (thin ptr) + let p: *const [u8; 1] = lsz as *const [u8; 1]; + assert_eq!(p as usize, lsz); + + // ptr-ptr-cast (thin ptr) + let w: *const () = p as *const (); + assert_eq!(w as usize, lsz); + + // ptr-ptr-cast (fat->thin) + let u: *const [u8] = unsafe{&*p}; + assert_eq!(u as *const u8, p as *const u8); + assert_eq!(u as *const u16, p as *const u16); + + // ptr-ptr-cast (Length vtables) + let mut l : [u8; 2] = [0,1]; + let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _; + let w: *mut [u16] = unsafe {&mut *w}; + let w_u8 : *const [u8] = w as *const [u8]; + assert_eq!(unsafe{&*w_u8}, &l); + + let s: *mut str = w as *mut str; + let l_via_str = unsafe{&*(s as *const [u8])}; + assert_eq!(&l, l_via_str); + + // ptr-ptr-cast (Length vtables, check length is preserved) + let l: [[u8; 3]; 2] = [[3, 2, 6], [4, 5, 1]]; + let p: *const [[u8; 3]] = &l; + let p: &[[u8; 2]] = unsafe {&*(p as *const [[u8; 2]])}; + assert_eq!(p, [[3, 2], [6, 4]]); + + // enum-cast + assert_eq!(Simple::A as u8, 0); + assert_eq!(Simple::B as u8, 1); + + assert_eq!(Valued::H8 as i8, -93); + assert_eq!(Valued::H7 as i8, 67); + assert_eq!(Valued::Z as i8, 0); + + assert_eq!(Valued::H8 as u8, 163); + assert_eq!(Valued::H7 as u8, 67); + assert_eq!(Valued::Z as u8, 0); + + assert_eq!(Valued::H8 as u16, 163); + assert_eq!(Valued::Z as u16, 0); + assert_eq!(Valued::H8 as u16, 163); + assert_eq!(Valued::Z as u16, 0); + + assert_eq!(ValuedSigned::M1 as u16, 65535); + assert_eq!(ValuedSigned::M1 as i16, -1); + assert_eq!(ValuedSigned::P1 as u16, 1); + assert_eq!(ValuedSigned::P1 as i16, 1); + + // prim-int-cast + assert_eq!(false as u16, 0); + assert_eq!(true as u16, 1); + assert_eq!(false as i64, 0); + assert_eq!(true as i64, 1); + assert_eq!('a' as u32, 0x61); + assert_eq!('a' as u16, 0x61); + assert_eq!('a' as u8, 0x61); + assert_eq!('×' as u8, 0xd0); + assert_eq!('×' as u16, 0x5d0); + assert_eq!('×' as u32, 0x5d0); + assert_eq!('ðŸµ' as u8, 0x35); + assert_eq!('ðŸµ' as u16, 0xf435); + assert_eq!('ðŸµ' as u32, 0x1f435); + assert_eq!('英' as i16, -0x7d0f); + assert_eq!('英' as u16, 0x82f1); + + // u8-char-cast + assert_eq!(0x61 as char, 'a'); + assert_eq!(0u8 as char, '\0'); + assert_eq!(0xd7 as char, '×'); + + // array-ptr-cast + let x = [1,2,3]; + let first : *const u32 = &x[0]; + + assert_eq!(first, &x as *const _); + assert_eq!(first, &x as *const u32); + + // fptr-addr-cast + fn foo() { + println!("foo!"); + } + fn bar() { + println!("bar!"); + } + + assert!(foo as usize != bar as usize); + + // Taking a few bits of a function's address is totally pointless and we detect that + assert_eq!(foo as i16, foo as usize as i16); + + // fptr-ptr-cast + + assert_eq!(foo as *const u8 as usize, foo as usize); + assert!(foo as *const u32 != first); +} +fn foo() { } diff --git a/tests/ui/cast/cast-to-bare-fn.rs b/tests/ui/cast/cast-to-bare-fn.rs new file mode 100644 index 000000000..1992f2637 --- /dev/null +++ b/tests/ui/cast/cast-to-bare-fn.rs @@ -0,0 +1,10 @@ +fn foo(_x: isize) { } + +fn main() { + let v: u64 = 5; + let x = foo as extern "C" fn() -> isize; + //~^ ERROR non-primitive cast + let y = v as extern "Rust" fn(isize) -> (isize, isize); + //~^ ERROR non-primitive cast + y(x()); +} diff --git a/tests/ui/cast/cast-to-bare-fn.stderr b/tests/ui/cast/cast-to-bare-fn.stderr new file mode 100644 index 000000000..d97b0c5f8 --- /dev/null +++ b/tests/ui/cast/cast-to-bare-fn.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `fn(isize) {foo}` as `extern "C" fn() -> isize` + --> $DIR/cast-to-bare-fn.rs:5:13 + | +LL | let x = foo as extern "C" fn() -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + +error[E0605]: non-primitive cast: `u64` as `fn(isize) -> (isize, isize)` + --> $DIR/cast-to-bare-fn.rs:7:13 + | +LL | let y = v as extern "Rust" fn(isize) -> (isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/cast-to-infer-ty.rs b/tests/ui/cast/cast-to-infer-ty.rs new file mode 100644 index 000000000..053ebb621 --- /dev/null +++ b/tests/ui/cast/cast-to-infer-ty.rs @@ -0,0 +1,8 @@ +// run-pass +// Check that we allow a cast to `_` so long as the target type can be +// inferred elsewhere. + +pub fn main() { + let i: *const i32 = 0 as _; + assert!(i.is_null()); +} diff --git a/tests/ui/cast/cast-to-nil.rs b/tests/ui/cast/cast-to-nil.rs new file mode 100644 index 000000000..085bb09e6 --- /dev/null +++ b/tests/ui/cast/cast-to-nil.rs @@ -0,0 +1,2 @@ +// error-pattern: non-primitive cast: `u32` as `()` +fn main() { let u = 0u32 as (); } diff --git a/tests/ui/cast/cast-to-nil.stderr b/tests/ui/cast/cast-to-nil.stderr new file mode 100644 index 000000000..29a9baffd --- /dev/null +++ b/tests/ui/cast/cast-to-nil.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `u32` as `()` + --> $DIR/cast-to-nil.rs:2:21 + | +LL | fn main() { let u = 0u32 as (); } + | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/cast-to-unsized-trait-object-suggestion.rs b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.rs new file mode 100644 index 000000000..5342b595c --- /dev/null +++ b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.rs @@ -0,0 +1,4 @@ +fn main() { + &1 as dyn Send; //~ ERROR cast to unsized + Box::new(1) as dyn Send; //~ ERROR cast to unsized +} diff --git a/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr new file mode 100644 index 000000000..3b5b8ea69 --- /dev/null +++ b/tests/ui/cast/cast-to-unsized-trait-object-suggestion.stderr @@ -0,0 +1,19 @@ +error[E0620]: cast to unsized type: `&{integer}` as `dyn Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:2:5 + | +LL | &1 as dyn Send; + | ^^^^^^-------- + | | + | help: try casting to a reference instead: `&dyn Send` + +error[E0620]: cast to unsized type: `Box<{integer}>` as `dyn Send` + --> $DIR/cast-to-unsized-trait-object-suggestion.rs:3:5 + | +LL | Box::new(1) as dyn Send; + | ^^^^^^^^^^^^^^^-------- + | | + | help: you can cast to a `Box` instead: `Box` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0620`. diff --git a/tests/ui/cast/cast.rs b/tests/ui/cast/cast.rs new file mode 100644 index 000000000..218275c4d --- /dev/null +++ b/tests/ui/cast/cast.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(unused_assignments)] +#![allow(unused_variables)] + +pub fn main() { + let i: isize = 'Q' as isize; + assert_eq!(i, 0x51); + let u: u32 = i as u32; + assert_eq!(u, 0x51 as u32); + assert_eq!(u, 'Q' as u32); + assert_eq!(i as u8, 'Q' as u8); + assert_eq!(i as u8 as i8, 'Q' as u8 as i8); + assert_eq!(0x51 as char, 'Q'); + assert_eq!(0 as u32, false as u32); + + // Test that `_` is correctly inferred. + let x = &"hello"; + let mut y = x as *const _; + y = core::ptr::null_mut(); +} diff --git a/tests/ui/cast/casts-differing-anon.rs b/tests/ui/cast/casts-differing-anon.rs new file mode 100644 index 000000000..d4a0f9613 --- /dev/null +++ b/tests/ui/cast/casts-differing-anon.rs @@ -0,0 +1,22 @@ +use std::fmt; + +fn foo() -> Box { + let x : Box<[u8]> = Box::new([0]); + x +} +fn bar() -> Box { + let y: Box = Box::new([0]); + y +} + +fn main() { + let f = foo(); + let b = bar(); + + // this is an `*mut [u8]` in practice + let f_raw : *mut _ = Box::into_raw(f); + // this is an `*mut fmt::Debug` in practice + let mut b_raw = Box::into_raw(b); + // ... and they should not be mixable + b_raw = f_raw as *mut _; //~ ERROR is invalid +} diff --git a/tests/ui/cast/casts-differing-anon.stderr b/tests/ui/cast/casts-differing-anon.stderr new file mode 100644 index 000000000..f9abfb522 --- /dev/null +++ b/tests/ui/cast/casts-differing-anon.stderr @@ -0,0 +1,11 @@ +error[E0606]: casting `*mut impl Debug + ?Sized` as `*mut impl Debug + ?Sized` is invalid + --> $DIR/casts-differing-anon.rs:21:13 + | +LL | b_raw = f_raw as *mut _; + | ^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/casts-issue-46365.rs b/tests/ui/cast/casts-issue-46365.rs new file mode 100644 index 000000000..50aa1a856 --- /dev/null +++ b/tests/ui/cast/casts-issue-46365.rs @@ -0,0 +1,8 @@ +struct Lorem { + ipsum: Ipsum //~ ERROR cannot find type `Ipsum` +} + +fn main() { + // Testing `as` casts, so deliberately not using `ptr::null`. + let _foo: *mut Lorem = 0 as *mut _; // no error here +} diff --git a/tests/ui/cast/casts-issue-46365.stderr b/tests/ui/cast/casts-issue-46365.stderr new file mode 100644 index 000000000..841754736 --- /dev/null +++ b/tests/ui/cast/casts-issue-46365.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Ipsum` in this scope + --> $DIR/casts-issue-46365.rs:2:12 + | +LL | ipsum: Ipsum + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/cast/codegen-object-shim.rs b/tests/ui/cast/codegen-object-shim.rs new file mode 100644 index 000000000..9a85a50eb --- /dev/null +++ b/tests/ui/cast/codegen-object-shim.rs @@ -0,0 +1,6 @@ +// run-pass + +fn main() { + assert_eq!((ToString::to_string as fn(&(dyn ToString+'static)) -> String)(&"foo"), + String::from("foo")); +} diff --git a/tests/ui/cast/fat-ptr-cast-rpass.rs b/tests/ui/cast/fat-ptr-cast-rpass.rs new file mode 100644 index 000000000..f5747eb8b --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast-rpass.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(ptr_metadata)] + +trait Foo { + fn foo(&self) {} +} + +struct Bar; + +impl Foo for Bar {} + +fn main() { + // Test we can turn a fat pointer to array back into a thin pointer. + let a: *const [i32] = &[1, 2, 3]; + let b = a as *const [i32; 2]; + unsafe { + assert_eq!(*b, [1, 2]); + } + + // Test conversion to an address (usize). + let a: *const [i32; 3] = &[1, 2, 3]; + let b: *const [i32] = a; + assert_eq!(a as usize, b as *const () as usize); + + // And conversion to a void pointer/address for trait objects too. + let a: *mut dyn Foo = &mut Bar; + let b = a as *mut () as usize; + let c = a as *const () as usize; + let d = a.to_raw_parts().0 as usize; + + assert_eq!(b, d); + assert_eq!(c, d); +} diff --git a/tests/ui/cast/fat-ptr-cast.rs b/tests/ui/cast/fat-ptr-cast.rs new file mode 100644 index 000000000..b5276dc61 --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast.rs @@ -0,0 +1,33 @@ +trait Trait {} + +// Make sure casts between thin-pointer <-> fat pointer obey RFC401 +fn main() { + let a: &[i32] = &[1, 2, 3]; + let b: Box<[i32]> = Box::new([1, 2, 3]); + let p = a as *const [i32]; + let q = a.as_ptr(); + + a as usize; //~ ERROR casting + a as isize; //~ ERROR casting + a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid + a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid + b as usize; //~ ERROR non-primitive cast + p as usize; + //~^ ERROR casting + + // #22955 + q as *const [i32]; //~ ERROR cannot cast + + // #21397 + let t: *mut (dyn Trait + 'static) = 0 as *mut _; + //~^ ERROR cannot cast `usize` to a pointer that is wide + let mut fail: *const str = 0 as *const str; + //~^ ERROR cannot cast `usize` to a pointer that is wide + let mut fail2: *const str = 0isize as *const str; + //~^ ERROR cannot cast `isize` to a pointer that is wide +} + +fn foo() { + let s = 0 as *const T; + //~^ ERROR cannot cast `usize` to a pointer that may be wide +} diff --git a/tests/ui/cast/fat-ptr-cast.stderr b/tests/ui/cast/fat-ptr-cast.stderr new file mode 100644 index 000000000..18e7b68ff --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast.stderr @@ -0,0 +1,88 @@ +error[E0606]: casting `&[i32]` as `usize` is invalid + --> $DIR/fat-ptr-cast.rs:10:5 + | +LL | a as usize; + | ^^^^^^^^^^ + | + = help: cast through a raw pointer first + +error[E0606]: casting `&[i32]` as `isize` is invalid + --> $DIR/fat-ptr-cast.rs:11:5 + | +LL | a as isize; + | ^^^^^^^^^^ + | + = help: cast through a raw pointer first + +error[E0606]: casting `&[i32]` as `i16` is invalid + --> $DIR/fat-ptr-cast.rs:12:5 + | +LL | a as i16; + | ^^^^^^^^ + | + = help: cast through a raw pointer first + +error[E0606]: casting `&[i32]` as `u32` is invalid + --> $DIR/fat-ptr-cast.rs:13:5 + | +LL | a as u32; + | ^^^^^^^^ + | + = help: cast through a raw pointer first + +error[E0605]: non-primitive cast: `Box<[i32]>` as `usize` + --> $DIR/fat-ptr-cast.rs:14:5 + | +LL | b as usize; + | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0606]: casting `*const [i32]` as `usize` is invalid + --> $DIR/fat-ptr-cast.rs:15:5 + | +LL | p as usize; + | ^^^^^^^^^^ + | + = help: cast through a thin pointer first + +error[E0607]: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]` + --> $DIR/fat-ptr-cast.rs:19:5 + | +LL | q as *const [i32]; + | ^^^^^^^^^^^^^^^^^ + +error[E0606]: cannot cast `usize` to a pointer that is wide + --> $DIR/fat-ptr-cast.rs:22:46 + | +LL | let t: *mut (dyn Trait + 'static) = 0 as *mut _; + | - ^^^^^^ creating a `*mut (dyn Trait + 'static)` requires both an address and a vtable + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error[E0606]: cannot cast `usize` to a pointer that is wide + --> $DIR/fat-ptr-cast.rs:24:37 + | +LL | let mut fail: *const str = 0 as *const str; + | - ^^^^^^^^^^ creating a `*const str` requires both an address and a length + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error[E0606]: cannot cast `isize` to a pointer that is wide + --> $DIR/fat-ptr-cast.rs:26:43 + | +LL | let mut fail2: *const str = 0isize as *const str; + | ------ ^^^^^^^^^^ creating a `*const str` requires both an address and a length + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error[E0606]: cannot cast `usize` to a pointer that may be wide + --> $DIR/fat-ptr-cast.rs:31:18 + | +LL | let s = 0 as *const T; + | - ^^^^^^^^ creating a `*const T` requires both an address and type-specific metadata + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0605, E0606, E0607. +For more information about an error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-106883-is-empty.rs b/tests/ui/cast/issue-106883-is-empty.rs new file mode 100644 index 000000000..27e0816dd --- /dev/null +++ b/tests/ui/cast/issue-106883-is-empty.rs @@ -0,0 +1,27 @@ +use std::ops::Deref; + +struct Foo; + +impl Deref for Foo { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &[] + } +} + +fn main() { + let _ = "foo" as bool; + //~^ ERROR casting `&'static str` as `bool` is invalid [E0606] + + let _ = String::from("foo") as bool; + //~^ ERROR non-primitive cast: `String` as `bool` [E0605] + + let _ = Foo as bool; + //~^ ERROR non-primitive cast: `Foo` as `bool` [E0605] +} + +fn _slice(bar: &[i32]) -> bool { + bar as bool + //~^ ERROR casting `&[i32]` as `bool` is invalid [E0606] +} diff --git a/tests/ui/cast/issue-106883-is-empty.stderr b/tests/ui/cast/issue-106883-is-empty.stderr new file mode 100644 index 000000000..7115c7704 --- /dev/null +++ b/tests/ui/cast/issue-106883-is-empty.stderr @@ -0,0 +1,58 @@ +error[E0606]: casting `&'static str` as `bool` is invalid + --> $DIR/issue-106883-is-empty.rs:14:13 + | +LL | let _ = "foo" as bool; + | ^^^^^^^^^^^^^ + | +help: consider using the `is_empty` method on `&'static str` to determine if it contains anything + | +LL | let _ = !"foo".is_empty(); + | + ~~~~~~~~~~~ + +error[E0605]: non-primitive cast: `String` as `bool` + --> $DIR/issue-106883-is-empty.rs:17:13 + | +LL | let _ = String::from("foo") as bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +note: this expression `Deref`s to `str` which implements `is_empty` + --> $DIR/issue-106883-is-empty.rs:17:13 + | +LL | let _ = String::from("foo") as bool; + | ^^^^^^^^^^^^^^^^^^^ +help: consider using the `is_empty` method on `String` to determine if it contains anything + | +LL | let _ = !String::from("foo").is_empty(); + | + ~~~~~~~~~~~ + +error[E0605]: non-primitive cast: `Foo` as `bool` + --> $DIR/issue-106883-is-empty.rs:20:13 + | +LL | let _ = Foo as bool; + | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +note: this expression `Deref`s to `[u8]` which implements `is_empty` + --> $DIR/issue-106883-is-empty.rs:20:13 + | +LL | let _ = Foo as bool; + | ^^^ +help: consider using the `is_empty` method on `Foo` to determine if it contains anything + | +LL | let _ = !Foo.is_empty(); + | + ~~~~~~~~~~~ + +error[E0606]: casting `&[i32]` as `bool` is invalid + --> $DIR/issue-106883-is-empty.rs:25:5 + | +LL | bar as bool + | ^^^^^^^^^^^ + | +help: consider using the `is_empty` method on `&[i32]` to determine if it contains anything + | +LL | !bar.is_empty() + | + ~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0605, E0606. +For more information about an error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-10991.rs b/tests/ui/cast/issue-10991.rs new file mode 100644 index 000000000..c36829fdf --- /dev/null +++ b/tests/ui/cast/issue-10991.rs @@ -0,0 +1,4 @@ +fn main() { + let nil = (); + let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize` +} diff --git a/tests/ui/cast/issue-10991.stderr b/tests/ui/cast/issue-10991.stderr new file mode 100644 index 000000000..5b8a18233 --- /dev/null +++ b/tests/ui/cast/issue-10991.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `()` as `usize` + --> $DIR/issue-10991.rs:3:14 + | +LL | let _t = nil as usize; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-17444.rs b/tests/ui/cast/issue-17444.rs new file mode 100644 index 000000000..906b443c9 --- /dev/null +++ b/tests/ui/cast/issue-17444.rs @@ -0,0 +1,8 @@ +enum Test { + Foo = 0 +} + +fn main() { + let _x = Test::Foo as *const isize; + //~^ ERROR casting `Test` as `*const isize` is invalid +} diff --git a/tests/ui/cast/issue-17444.stderr b/tests/ui/cast/issue-17444.stderr new file mode 100644 index 000000000..1097079df --- /dev/null +++ b/tests/ui/cast/issue-17444.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `Test` as `*const isize` is invalid + --> $DIR/issue-17444.rs:6:14 + | +LL | let _x = Test::Foo as *const isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/cast/issue-84213.fixed b/tests/ui/cast/issue-84213.fixed new file mode 100644 index 000000000..b5c4a7752 --- /dev/null +++ b/tests/ui/cast/issue-84213.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +struct Something { + pub field: u32, +} + +fn main() { + let mut something = Something { field: 1337 }; + let _ = something.field; + + let _pointer_to_something = &something as *const Something; + //~^ ERROR: non-primitive cast + + let _mut_pointer_to_something = &mut something as *mut Something; + //~^ ERROR: non-primitive cast +} diff --git a/tests/ui/cast/issue-84213.rs b/tests/ui/cast/issue-84213.rs new file mode 100644 index 000000000..6eb81291a --- /dev/null +++ b/tests/ui/cast/issue-84213.rs @@ -0,0 +1,16 @@ +// run-rustfix + +struct Something { + pub field: u32, +} + +fn main() { + let mut something = Something { field: 1337 }; + let _ = something.field; + + let _pointer_to_something = something as *const Something; + //~^ ERROR: non-primitive cast + + let _mut_pointer_to_something = something as *mut Something; + //~^ ERROR: non-primitive cast +} diff --git a/tests/ui/cast/issue-84213.stderr b/tests/ui/cast/issue-84213.stderr new file mode 100644 index 000000000..025970e54 --- /dev/null +++ b/tests/ui/cast/issue-84213.stderr @@ -0,0 +1,25 @@ +error[E0605]: non-primitive cast: `Something` as `*const Something` + --> $DIR/issue-84213.rs:11:33 + | +LL | let _pointer_to_something = something as *const Something; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let _pointer_to_something = &something as *const Something; + | + + +error[E0605]: non-primitive cast: `Something` as `*mut Something` + --> $DIR/issue-84213.rs:14:37 + | +LL | let _mut_pointer_to_something = something as *mut Something; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let _mut_pointer_to_something = &mut something as *mut Something; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-85586.rs b/tests/ui/cast/issue-85586.rs new file mode 100644 index 000000000..78816582b --- /dev/null +++ b/tests/ui/cast/issue-85586.rs @@ -0,0 +1,10 @@ +// Check that errors for unresolved types in cast expressions are reported +// for the offending subexpression, not the whole cast expression. + +#![allow(unused_variables)] + +fn main() { + let a = [1, 2, 3].iter().sum(); + let b = (a + 1) as usize; + //~^ ERROR: type annotations needed [E0282] +} diff --git a/tests/ui/cast/issue-85586.stderr b/tests/ui/cast/issue-85586.stderr new file mode 100644 index 000000000..ed8a6fc62 --- /dev/null +++ b/tests/ui/cast/issue-85586.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/issue-85586.rs:8:13 + | +LL | let b = (a + 1) as usize; + | ^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/cast/issue-88621.rs b/tests/ui/cast/issue-88621.rs new file mode 100644 index 000000000..1679793ee --- /dev/null +++ b/tests/ui/cast/issue-88621.rs @@ -0,0 +1,11 @@ +#[repr(u8)] +enum Kind2 { + Foo() = 1, + Bar{} = 2, + Baz = 3, +} + +fn main() { + let _ = Kind2::Foo() as u8; + //~^ ERROR non-primitive cast +} diff --git a/tests/ui/cast/issue-88621.stderr b/tests/ui/cast/issue-88621.stderr new file mode 100644 index 000000000..886145c1b --- /dev/null +++ b/tests/ui/cast/issue-88621.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `Kind2` as `u8` + --> $DIR/issue-88621.rs:9:13 + | +LL | let _ = Kind2::Foo() as u8; + | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/issue-89497.fixed b/tests/ui/cast/issue-89497.fixed new file mode 100644 index 000000000..04c10a5f7 --- /dev/null +++ b/tests/ui/cast/issue-89497.fixed @@ -0,0 +1,10 @@ +// Regression test for issue #89497. + +// run-rustfix + +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; + //~^ ERROR: non-primitive cast + //~| HELP: consider borrowing the value +} diff --git a/tests/ui/cast/issue-89497.rs b/tests/ui/cast/issue-89497.rs new file mode 100644 index 000000000..76301b704 --- /dev/null +++ b/tests/ui/cast/issue-89497.rs @@ -0,0 +1,10 @@ +// Regression test for issue #89497. + +// run-rustfix + +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + //~^ ERROR: non-primitive cast + //~| HELP: consider borrowing the value +} diff --git a/tests/ui/cast/issue-89497.stderr b/tests/ui/cast/issue-89497.stderr new file mode 100644 index 000000000..bf3c3537f --- /dev/null +++ b/tests/ui/cast/issue-89497.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `*const i32` as `&'static i32` + --> $DIR/issue-89497.rs:7:45 + | +LL | let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; +LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/supported-cast.rs b/tests/ui/cast/supported-cast.rs new file mode 100644 index 000000000..ff41ce6c7 --- /dev/null +++ b/tests/ui/cast/supported-cast.rs @@ -0,0 +1,206 @@ +// run-pass + +pub fn main() { + let f = 1_usize as *const String; + println!("{:?}", f as isize); + println!("{:?}", f as usize); + println!("{:?}", f as i8); + println!("{:?}", f as i16); + println!("{:?}", f as i32); + println!("{:?}", f as i64); + println!("{:?}", f as u8); + println!("{:?}", f as u16); + println!("{:?}", f as u32); + println!("{:?}", f as u64); + + println!("{:?}", 1 as isize); + println!("{:?}", 1 as usize); + println!("{:?}", 1 as *const String); + println!("{:?}", 1 as i8); + println!("{:?}", 1 as i16); + println!("{:?}", 1 as i32); + println!("{:?}", 1 as i64); + println!("{:?}", 1 as u8); + println!("{:?}", 1 as u16); + println!("{:?}", 1 as u32); + println!("{:?}", 1 as u64); + println!("{:?}", 1 as f32); + println!("{:?}", 1 as f64); + + println!("{:?}", 1_usize as isize); + println!("{:?}", 1_usize as usize); + println!("{:?}", 1_usize as *const String); + println!("{:?}", 1_usize as i8); + println!("{:?}", 1_usize as i16); + println!("{:?}", 1_usize as i32); + println!("{:?}", 1_usize as i64); + println!("{:?}", 1_usize as u8); + println!("{:?}", 1_usize as u16); + println!("{:?}", 1_usize as u32); + println!("{:?}", 1_usize as u64); + println!("{:?}", 1_usize as f32); + println!("{:?}", 1_usize as f64); + + println!("{:?}", 1i8 as isize); + println!("{:?}", 1i8 as usize); + println!("{:?}", 1i8 as *const String); + println!("{:?}", 1i8 as i8); + println!("{:?}", 1i8 as i16); + println!("{:?}", 1i8 as i32); + println!("{:?}", 1i8 as i64); + println!("{:?}", 1i8 as u8); + println!("{:?}", 1i8 as u16); + println!("{:?}", 1i8 as u32); + println!("{:?}", 1i8 as u64); + println!("{:?}", 1i8 as f32); + println!("{:?}", 1i8 as f64); + + println!("{:?}", 1u8 as isize); + println!("{:?}", 1u8 as usize); + println!("{:?}", 1u8 as *const String); + println!("{:?}", 1u8 as i8); + println!("{:?}", 1u8 as i16); + println!("{:?}", 1u8 as i32); + println!("{:?}", 1u8 as i64); + println!("{:?}", 1u8 as u8); + println!("{:?}", 1u8 as u16); + println!("{:?}", 1u8 as u32); + println!("{:?}", 1u8 as u64); + println!("{:?}", 1u8 as f32); + println!("{:?}", 1u8 as f64); + + println!("{:?}", 1i16 as isize); + println!("{:?}", 1i16 as usize); + println!("{:?}", 1i16 as *const String); + println!("{:?}", 1i16 as i8); + println!("{:?}", 1i16 as i16); + println!("{:?}", 1i16 as i32); + println!("{:?}", 1i16 as i64); + println!("{:?}", 1i16 as u8); + println!("{:?}", 1i16 as u16); + println!("{:?}", 1i16 as u32); + println!("{:?}", 1i16 as u64); + println!("{:?}", 1i16 as f32); + println!("{:?}", 1i16 as f64); + + println!("{:?}", 1u16 as isize); + println!("{:?}", 1u16 as usize); + println!("{:?}", 1u16 as *const String); + println!("{:?}", 1u16 as i8); + println!("{:?}", 1u16 as i16); + println!("{:?}", 1u16 as i32); + println!("{:?}", 1u16 as i64); + println!("{:?}", 1u16 as u8); + println!("{:?}", 1u16 as u16); + println!("{:?}", 1u16 as u32); + println!("{:?}", 1u16 as u64); + println!("{:?}", 1u16 as f32); + println!("{:?}", 1u16 as f64); + + println!("{:?}", 1i32 as isize); + println!("{:?}", 1i32 as usize); + println!("{:?}", 1i32 as *const String); + println!("{:?}", 1i32 as i8); + println!("{:?}", 1i32 as i16); + println!("{:?}", 1i32 as i32); + println!("{:?}", 1i32 as i64); + println!("{:?}", 1i32 as u8); + println!("{:?}", 1i32 as u16); + println!("{:?}", 1i32 as u32); + println!("{:?}", 1i32 as u64); + println!("{:?}", 1i32 as f32); + println!("{:?}", 1i32 as f64); + + println!("{:?}", 1u32 as isize); + println!("{:?}", 1u32 as usize); + println!("{:?}", 1u32 as *const String); + println!("{:?}", 1u32 as i8); + println!("{:?}", 1u32 as i16); + println!("{:?}", 1u32 as i32); + println!("{:?}", 1u32 as i64); + println!("{:?}", 1u32 as u8); + println!("{:?}", 1u32 as u16); + println!("{:?}", 1u32 as u32); + println!("{:?}", 1u32 as u64); + println!("{:?}", 1u32 as f32); + println!("{:?}", 1u32 as f64); + + println!("{:?}", 1i64 as isize); + println!("{:?}", 1i64 as usize); + println!("{:?}", 1i64 as *const String); + println!("{:?}", 1i64 as i8); + println!("{:?}", 1i64 as i16); + println!("{:?}", 1i64 as i32); + println!("{:?}", 1i64 as i64); + println!("{:?}", 1i64 as u8); + println!("{:?}", 1i64 as u16); + println!("{:?}", 1i64 as u32); + println!("{:?}", 1i64 as u64); + println!("{:?}", 1i64 as f32); + println!("{:?}", 1i64 as f64); + + println!("{:?}", 1u64 as isize); + println!("{:?}", 1u64 as usize); + println!("{:?}", 1u64 as *const String); + println!("{:?}", 1u64 as i8); + println!("{:?}", 1u64 as i16); + println!("{:?}", 1u64 as i32); + println!("{:?}", 1u64 as i64); + println!("{:?}", 1u64 as u8); + println!("{:?}", 1u64 as u16); + println!("{:?}", 1u64 as u32); + println!("{:?}", 1u64 as u64); + println!("{:?}", 1u64 as f32); + println!("{:?}", 1u64 as f64); + + println!("{:?}", 1u64 as isize); + println!("{:?}", 1u64 as usize); + println!("{:?}", 1u64 as *const String); + println!("{:?}", 1u64 as i8); + println!("{:?}", 1u64 as i16); + println!("{:?}", 1u64 as i32); + println!("{:?}", 1u64 as i64); + println!("{:?}", 1u64 as u8); + println!("{:?}", 1u64 as u16); + println!("{:?}", 1u64 as u32); + println!("{:?}", 1u64 as u64); + println!("{:?}", 1u64 as f32); + println!("{:?}", 1u64 as f64); + + println!("{:?}", true as isize); + println!("{:?}", true as usize); + println!("{:?}", true as i8); + println!("{:?}", true as i16); + println!("{:?}", true as i32); + println!("{:?}", true as i64); + println!("{:?}", true as u8); + println!("{:?}", true as u16); + println!("{:?}", true as u32); + println!("{:?}", true as u64); + + println!("{:?}", 1f32 as isize); + println!("{:?}", 1f32 as usize); + println!("{:?}", 1f32 as i8); + println!("{:?}", 1f32 as i16); + println!("{:?}", 1f32 as i32); + println!("{:?}", 1f32 as i64); + println!("{:?}", 1f32 as u8); + println!("{:?}", 1f32 as u16); + println!("{:?}", 1f32 as u32); + println!("{:?}", 1f32 as u64); + println!("{:?}", 1f32 as f32); + println!("{:?}", 1f32 as f64); + + println!("{:?}", 1f64 as isize); + println!("{:?}", 1f64 as usize); + println!("{:?}", 1f64 as i8); + println!("{:?}", 1f64 as i16); + println!("{:?}", 1f64 as i32); + println!("{:?}", 1f64 as i64); + println!("{:?}", 1f64 as u8); + println!("{:?}", 1f64 as u16); + println!("{:?}", 1f64 as u32); + println!("{:?}", 1f64 as u64); + println!("{:?}", 1f64 as f32); + println!("{:?}", 1f64 as f64); +} diff --git a/tests/ui/cast/unsupported-cast.rs b/tests/ui/cast/unsupported-cast.rs new file mode 100644 index 000000000..1384ecc6e --- /dev/null +++ b/tests/ui/cast/unsupported-cast.rs @@ -0,0 +1,5 @@ +struct A; + +fn main() { + println!("{:?}", 1.0 as *const A); //~ERROR casting `f64` as `*const A` is invalid +} diff --git a/tests/ui/cast/unsupported-cast.stderr b/tests/ui/cast/unsupported-cast.stderr new file mode 100644 index 000000000..56a375a1d --- /dev/null +++ b/tests/ui/cast/unsupported-cast.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `f64` as `*const A` is invalid + --> $DIR/unsupported-cast.rs:4:20 + | +LL | println!("{:?}", 1.0 as *const A); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/catch-unwind-bang.rs b/tests/ui/catch-unwind-bang.rs new file mode 100644 index 000000000..fb3503937 --- /dev/null +++ b/tests/ui/catch-unwind-bang.rs @@ -0,0 +1,10 @@ +// run-pass +// needs-unwind + +fn worker() -> ! { + panic!() +} + +fn main() { + std::panic::catch_unwind(worker).unwrap_err(); +} diff --git a/tests/ui/cenum_impl_drop_cast.rs b/tests/ui/cenum_impl_drop_cast.rs new file mode 100644 index 000000000..96e3d967e --- /dev/null +++ b/tests/ui/cenum_impl_drop_cast.rs @@ -0,0 +1,18 @@ +#![deny(cenum_impl_drop_cast)] + +enum E { + A = 0, +} + +impl Drop for E { + fn drop(&mut self) { + println!("Drop"); + } +} + +fn main() { + let e = E::A; + let i = e as u32; + //~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop` + //~| WARN this was previously accepted +} diff --git a/tests/ui/cenum_impl_drop_cast.stderr b/tests/ui/cenum_impl_drop_cast.stderr new file mode 100644 index 000000000..b3f921c14 --- /dev/null +++ b/tests/ui/cenum_impl_drop_cast.stderr @@ -0,0 +1,31 @@ +error: cannot cast enum `E` into integer `u32` because it implements `Drop` + --> $DIR/cenum_impl_drop_cast.rs:15:13 + | +LL | let i = e as u32; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73333 +note: the lint level is defined here + --> $DIR/cenum_impl_drop_cast.rs:1:9 + | +LL | #![deny(cenum_impl_drop_cast)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: cannot cast enum `E` into integer `u32` because it implements `Drop` + --> $DIR/cenum_impl_drop_cast.rs:15:13 + | +LL | let i = e as u32; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73333 +note: the lint level is defined here + --> $DIR/cenum_impl_drop_cast.rs:1:9 + | +LL | #![deny(cenum_impl_drop_cast)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs b/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs new file mode 100644 index 000000000..24d2dc645 --- /dev/null +++ b/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs @@ -0,0 +1,38 @@ +// run-pass +// aux-build:ver-cfg-rel.rs +// revisions: assume no_assume +// [assume]compile-flags: -Z assume-incomplete-release + +#![feature(cfg_version)] + +extern crate ver_cfg_rel; + +use ver_cfg_rel::ver_cfg_rel; + +#[ver_cfg_rel("-2")] +fn foo_2() { } + +#[ver_cfg_rel("-1")] +fn foo_1() { } + +#[cfg(assume)] +#[ver_cfg_rel("0")] +fn foo() { compile_error!("wrong+0") } + +#[cfg(no_assume)] +#[ver_cfg_rel("0")] +fn foo() { } + +#[ver_cfg_rel("1")] +fn bar() { compile_error!("wrong+1") } + +#[ver_cfg_rel("2")] +fn bar() { compile_error!("wrong+2") } + +fn main() { + foo_2(); + foo_1(); + + #[cfg(no_assume)] + foo(); +} diff --git a/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs b/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs new file mode 100644 index 000000000..067c620f5 --- /dev/null +++ b/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs @@ -0,0 +1,56 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, TokenTree as Tt}; +use std::str::FromStr; + +// String containing the current version number of the tip, i.e. "1.41.2" +static VERSION_NUMBER: &str = include_str!("../../../../../src/version"); + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +struct Version { + major: i16, + minor: i16, + patch: i16, +} + +fn parse_version(s: &str) -> Option { + let mut digits = s.splitn(3, '.'); + let major = digits.next()?.parse().ok()?; + let minor = digits.next()?.parse().ok()?; + let patch = digits.next().unwrap_or("0").trim().parse().ok()?; + Some(Version { major, minor, patch }) +} + +#[proc_macro_attribute] +/// Emits a #[cfg(version)] relative to the current one, so passing +/// -1 as argument on compiler 1.50 will emit #[cfg(version("1.49.0"))], +/// while 1 will emit #[cfg(version("1.51.0"))] +pub fn ver_cfg_rel(attr: TokenStream, input: TokenStream) -> TokenStream { + let mut v_rel = None; + for a in attr.into_iter() { + match a { + Tt::Literal(l) => { + let mut s = l.to_string(); + let s = s.trim_matches('"'); + let v: i16 = s.parse().unwrap(); + v_rel = Some(v); + break; + }, + _ => panic!("{:?}", a), + } + } + let v_rel = v_rel.unwrap(); + + let mut v = parse_version(VERSION_NUMBER).unwrap(); + v.minor += v_rel; + + let attr_str = format!("#[cfg(version(\"{}.{}.{}\"))]", v.major, v.minor, v.patch); + let mut res = Vec::::new(); + res.extend(TokenStream::from_str(&attr_str).unwrap().into_iter()); + res.extend(input.into_iter()); + res.into_iter().collect() +} diff --git a/tests/ui/cfg/auxiliary/cfg_inner_static.rs b/tests/ui/cfg/auxiliary/cfg_inner_static.rs new file mode 100644 index 000000000..6a619a4e7 --- /dev/null +++ b/tests/ui/cfg/auxiliary/cfg_inner_static.rs @@ -0,0 +1,7 @@ +// this used to just ICE on compiling +pub fn foo() { + if cfg!(foo) { + static a: isize = 3; + a + } else { 3 }; +} diff --git a/tests/ui/cfg/cfg-attr-cfg.rs b/tests/ui/cfg/cfg-attr-cfg.rs new file mode 100644 index 000000000..61794e0bf --- /dev/null +++ b/tests/ui/cfg/cfg-attr-cfg.rs @@ -0,0 +1,8 @@ +// run-pass +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +// pretty-expanded FIXME #23616 + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/tests/ui/cfg/cfg-attr-crate.rs b/tests/ui/cfg/cfg-attr-crate.rs new file mode 100644 index 000000000..1d70f2f84 --- /dev/null +++ b/tests/ui/cfg/cfg-attr-crate.rs @@ -0,0 +1,8 @@ +// run-pass +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +// pretty-expanded FIXME #23616 + +#![cfg_attr(not_used, no_core)] + +fn main() { } diff --git a/tests/ui/cfg/cfg-family.rs b/tests/ui/cfg/cfg-family.rs new file mode 100644 index 000000000..c7d196a2a --- /dev/null +++ b/tests/ui/cfg/cfg-family.rs @@ -0,0 +1,12 @@ +// build-pass +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no bare family +// ignore-sgx + +#[cfg(windows)] +pub fn main() { +} + +#[cfg(unix)] +pub fn main() { +} diff --git a/tests/ui/cfg/cfg-in-crate-1.rs b/tests/ui/cfg/cfg-in-crate-1.rs new file mode 100644 index 000000000..e84300aa3 --- /dev/null +++ b/tests/ui/cfg/cfg-in-crate-1.rs @@ -0,0 +1,5 @@ +// run-pass +// compile-flags: --cfg bar -D warnings +#![cfg(bar)] + +fn main() {} diff --git a/tests/ui/cfg/cfg-macros-foo.rs b/tests/ui/cfg/cfg-macros-foo.rs new file mode 100644 index 000000000..8b112c796 --- /dev/null +++ b/tests/ui/cfg/cfg-macros-foo.rs @@ -0,0 +1,26 @@ +// run-pass +// compile-flags: --cfg foo + +// check that cfg correctly chooses between the macro impls (see also +// cfg-macros-notfoo.rs) + + +#[cfg(foo)] +#[macro_use] +mod foo { + macro_rules! bar { + () => { true } + } +} + +#[cfg(not(foo))] +#[macro_use] +mod foo { + macro_rules! bar { + () => { false } + } +} + +pub fn main() { + assert!(bar!()) +} diff --git a/tests/ui/cfg/cfg-macros-notfoo.rs b/tests/ui/cfg/cfg-macros-notfoo.rs new file mode 100644 index 000000000..292d97821 --- /dev/null +++ b/tests/ui/cfg/cfg-macros-notfoo.rs @@ -0,0 +1,26 @@ +// run-pass +// compile-flags: + +// check that cfg correctly chooses between the macro impls (see also +// cfg-macros-foo.rs) + + +#[cfg(foo)] +#[macro_use] +mod foo { + macro_rules! bar { + () => { true } + } +} + +#[cfg(not(foo))] +#[macro_use] +mod foo { + macro_rules! bar { + () => { false } + } +} + +pub fn main() { + assert!(!bar!()) +} diff --git a/tests/ui/cfg/cfg-match-arm.rs b/tests/ui/cfg/cfg-match-arm.rs new file mode 100644 index 000000000..071008f9e --- /dev/null +++ b/tests/ui/cfg/cfg-match-arm.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +enum Foo { + Bar, + Baz, +} + +fn foo(f: Foo) { + match f { + Foo::Bar => {}, + #[cfg(not(asdfa))] + Foo::Baz => {}, + #[cfg(afsd)] + Basdfwe => {} + } +} + +pub fn main() {} diff --git a/tests/ui/cfg/cfg-method-receiver-ok.rs b/tests/ui/cfg/cfg-method-receiver-ok.rs new file mode 100644 index 000000000..61ad3b8c1 --- /dev/null +++ b/tests/ui/cfg/cfg-method-receiver-ok.rs @@ -0,0 +1,14 @@ +// check-pass + +macro_rules! foo { + () => { + #[allow(unreachable_patterns)] + { + 123i32 + } + }; +} + +fn main() { + let _ = foo!().abs(); +} diff --git a/tests/ui/cfg/cfg-method-receiver.rs b/tests/ui/cfg/cfg-method-receiver.rs new file mode 100644 index 000000000..71134ff17 --- /dev/null +++ b/tests/ui/cfg/cfg-method-receiver.rs @@ -0,0 +1,11 @@ +macro_rules! cbor_map { + ($key:expr) => { + $key.signum(); + //~^ ERROR can't call method `signum` on ambiguous numeric type `{integer}` [E0689] + }; +} + +fn main() { + cbor_map! { #[cfg(test)] 4}; + //~^ ERROR removing an expression is not supported in this position +} diff --git a/tests/ui/cfg/cfg-method-receiver.stderr b/tests/ui/cfg/cfg-method-receiver.stderr new file mode 100644 index 000000000..5767a7c1b --- /dev/null +++ b/tests/ui/cfg/cfg-method-receiver.stderr @@ -0,0 +1,24 @@ +error: removing an expression is not supported in this position + --> $DIR/cfg-method-receiver.rs:9:17 + | +LL | cbor_map! { #[cfg(test)] 4}; + | ^^^^^^^^^^^^ + +error[E0689]: can't call method `signum` on ambiguous numeric type `{integer}` + --> $DIR/cfg-method-receiver.rs:3:14 + | +LL | $key.signum(); + | ^^^^^^ +... +LL | cbor_map! { #[cfg(test)] 4}; + | --------------------------- in this macro invocation + | + = note: this error originates in the macro `cbor_map` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you must specify a concrete type for this numeric value, like `i32` + | +LL | cbor_map! { #[cfg(test)] 4_i32}; + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/cfg/cfg-panic-abort.rs b/tests/ui/cfg/cfg-panic-abort.rs new file mode 100644 index 000000000..3853b598a --- /dev/null +++ b/tests/ui/cfg/cfg-panic-abort.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C panic=abort +// no-prefer-dynamic + + +#[cfg(panic = "unwind")] +pub fn bad() -> i32 { } + +#[cfg(not(panic = "abort"))] +pub fn bad() -> i32 { } + +#[cfg(panic = "some_imaginary_future_panic_handler")] +pub fn bad() -> i32 { } + +#[cfg(panic = "abort")] +pub fn main() { } diff --git a/tests/ui/cfg/cfg-panic.rs b/tests/ui/cfg/cfg-panic.rs new file mode 100644 index 000000000..2de72d54a --- /dev/null +++ b/tests/ui/cfg/cfg-panic.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: -C panic=unwind +// needs-unwind + + +#[cfg(panic = "abort")] +pub fn bad() -> i32 { } + +#[cfg(not(panic = "unwind"))] +pub fn bad() -> i32 { } + +#[cfg(panic = "some_imaginary_future_panic_handler")] +pub fn bad() -> i32 { } + +#[cfg(panic = "unwind")] +pub fn main() { } diff --git a/tests/ui/cfg/cfg-path-error.rs b/tests/ui/cfg/cfg-path-error.rs new file mode 100644 index 000000000..5bf80bd74 --- /dev/null +++ b/tests/ui/cfg/cfg-path-error.rs @@ -0,0 +1,19 @@ +// check-fail + +#[cfg(any(foo, foo::bar))] +//~^ERROR `cfg` predicate key must be an identifier +fn foo1() {} + +#[cfg(any(foo::bar, foo))] +//~^ERROR `cfg` predicate key must be an identifier +fn foo2() {} + +#[cfg(all(foo, foo::bar))] +//~^ERROR `cfg` predicate key must be an identifier +fn foo3() {} + +#[cfg(all(foo::bar, foo))] +//~^ERROR `cfg` predicate key must be an identifier +fn foo4() {} + +fn main() {} diff --git a/tests/ui/cfg/cfg-path-error.stderr b/tests/ui/cfg/cfg-path-error.stderr new file mode 100644 index 000000000..84b44b2b0 --- /dev/null +++ b/tests/ui/cfg/cfg-path-error.stderr @@ -0,0 +1,26 @@ +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-path-error.rs:3:16 + | +LL | #[cfg(any(foo, foo::bar))] + | ^^^^^^^^ + +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-path-error.rs:7:11 + | +LL | #[cfg(any(foo::bar, foo))] + | ^^^^^^^^ + +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-path-error.rs:11:16 + | +LL | #[cfg(all(foo, foo::bar))] + | ^^^^^^^^ + +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-path-error.rs:15:11 + | +LL | #[cfg(all(foo::bar, foo))] + | ^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/cfg/cfg-target-abi.rs b/tests/ui/cfg/cfg-target-abi.rs new file mode 100644 index 000000000..acc570fc8 --- /dev/null +++ b/tests/ui/cfg/cfg-target-abi.rs @@ -0,0 +1,10 @@ +// run-pass +#![feature(cfg_target_abi)] + +#[cfg(target_abi = "eabihf")] +pub fn main() { +} + +#[cfg(not(target_abi = "eabihf"))] +pub fn main() { +} diff --git a/tests/ui/cfg/cfg-target-compact-errors.rs b/tests/ui/cfg/cfg-target-compact-errors.rs new file mode 100644 index 000000000..bca2275b1 --- /dev/null +++ b/tests/ui/cfg/cfg-target-compact-errors.rs @@ -0,0 +1,17 @@ +// check-fail + +#![feature(cfg_target_compact)] + +#[cfg(target(o::o))] +//~^ ERROR `cfg` predicate key must be an identifier +fn one() {} + +#[cfg(target(os = 8))] +//~^ ERROR literal in `cfg` predicate value must be a string +fn two() {} + +#[cfg(target(os = "linux", pointer(width = "64")))] +//~^ ERROR invalid predicate `target_pointer` +fn three() {} + +fn main() {} diff --git a/tests/ui/cfg/cfg-target-compact-errors.stderr b/tests/ui/cfg/cfg-target-compact-errors.stderr new file mode 100644 index 000000000..bb858301e --- /dev/null +++ b/tests/ui/cfg/cfg-target-compact-errors.stderr @@ -0,0 +1,22 @@ +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-target-compact-errors.rs:5:14 + | +LL | #[cfg(target(o::o))] + | ^^^^ + +error[E0565]: literal in `cfg` predicate value must be a string + --> $DIR/cfg-target-compact-errors.rs:9:19 + | +LL | #[cfg(target(os = 8))] + | ^ + +error[E0537]: invalid predicate `target_pointer` + --> $DIR/cfg-target-compact-errors.rs:13:28 + | +LL | #[cfg(target(os = "linux", pointer(width = "64")))] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0537, E0565. +For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/cfg/cfg-target-compact.rs b/tests/ui/cfg/cfg-target-compact.rs new file mode 100644 index 000000000..dc95a8091 --- /dev/null +++ b/tests/ui/cfg/cfg-target-compact.rs @@ -0,0 +1,10 @@ +// run-pass +#![feature(cfg_target_compact)] + +#[cfg(target(os = "linux", pointer_width = "64"))] +pub fn main() { +} + +#[cfg(not(target(os = "linux", pointer_width = "64")))] +pub fn main() { +} diff --git a/tests/ui/cfg/cfg-target-family.rs b/tests/ui/cfg/cfg-target-family.rs new file mode 100644 index 000000000..5182cdc89 --- /dev/null +++ b/tests/ui/cfg/cfg-target-family.rs @@ -0,0 +1,13 @@ +// build-pass +// ignore-sgx + +// pretty-expanded FIXME #23616 + +#[cfg(target_family = "windows")] +pub fn main() {} + +#[cfg(target_family = "unix")] +pub fn main() {} + +#[cfg(all(target_family = "wasm", not(target_os = "emscripten")))] +pub fn main() {} diff --git a/tests/ui/cfg/cfg-target-vendor.rs b/tests/ui/cfg/cfg-target-vendor.rs new file mode 100644 index 000000000..782458516 --- /dev/null +++ b/tests/ui/cfg/cfg-target-vendor.rs @@ -0,0 +1,8 @@ +// run-pass +#[cfg(target_vendor = "unknown")] +pub fn main() { +} + +#[cfg(not(target_vendor = "unknown"))] +pub fn main() { +} diff --git a/tests/ui/cfg/cfg_attr.rs b/tests/ui/cfg/cfg_attr.rs new file mode 100644 index 000000000..c959e68ac --- /dev/null +++ b/tests/ui/cfg/cfg_attr.rs @@ -0,0 +1,50 @@ +// run-pass +// compile-flags:--cfg set1 --cfg set2 +#![allow(dead_code)] +use std::fmt::Debug; + +struct NotDebugable; + +#[cfg_attr(set1, derive(Debug))] +struct Set1; + +#[cfg_attr(notset, derive(Debug))] +struct Notset(NotDebugable); + +#[cfg_attr(not(notset), derive(Debug))] +struct NotNotset; + +#[cfg_attr(not(set1), derive(Debug))] +struct NotSet1(NotDebugable); + +#[cfg_attr(all(set1, set2), derive(Debug))] +struct AllSet1Set2; + +#[cfg_attr(all(set1, notset), derive(Debug))] +struct AllSet1Notset(NotDebugable); + +#[cfg_attr(any(set1, notset), derive(Debug))] +struct AnySet1Notset; + +#[cfg_attr(any(notset, notset2), derive(Debug))] +struct AnyNotsetNotset2(NotDebugable); + +#[cfg_attr(all(not(notset), any(set1, notset)), derive(Debug))] +struct Complex; + +#[cfg_attr(any(notset, not(any(set1, notset))), derive(Debug))] +struct ComplexNot(NotDebugable); + +#[cfg_attr(any(target_endian = "little", target_endian = "big"), derive(Debug))] +struct KeyValue; + +fn is_show() {} + +fn main() { + is_show::(); + is_show::(); + is_show::(); + is_show::(); + is_show::(); + is_show::(); +} diff --git a/tests/ui/cfg/cfg_inner_static.rs b/tests/ui/cfg/cfg_inner_static.rs new file mode 100644 index 000000000..45dbbcc10 --- /dev/null +++ b/tests/ui/cfg/cfg_inner_static.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:cfg_inner_static.rs + +// pretty-expanded FIXME #23616 + +extern crate cfg_inner_static; + +pub fn main() { + cfg_inner_static::foo(); +} diff --git a/tests/ui/cfg/cfg_stmt_expr.rs b/tests/ui/cfg/cfg_stmt_expr.rs new file mode 100644 index 000000000..6381bb2d5 --- /dev/null +++ b/tests/ui/cfg/cfg_stmt_expr.rs @@ -0,0 +1,92 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] +#![deny(non_snake_case)] +#![feature(stmt_expr_attributes)] + +fn main() { + let a = 413; + #[cfg(unset)] + let a = (); + assert_eq!(a, 413); + + let mut b = 612; + #[cfg(unset)] + { + b = 1111; + } + assert_eq!(b, 612); + + #[cfg(unset)] + undefined_fn(); + + #[cfg(unset)] + undefined_macro!(); + #[cfg(unset)] + undefined_macro![]; + #[cfg(unset)] + undefined_macro!{}; + + // pretty printer bug... + // #[cfg(unset)] + // undefined_macro!{} + + let () = (#[cfg(unset)] 341,); // Should this also work on parens? + let t = (1, #[cfg(unset)] 3, 4); + assert_eq!(t, (1, 4)); + + let f = |_: u32, _: u32| (); + f(2, 1, #[cfg(unset)] 6); + + let _: u32 = a.clone(#[cfg(unset)] undefined); + + let _: [(); 0] = [#[cfg(unset)] 126]; + let t = [#[cfg(unset)] 1, 2, 6]; + assert_eq!(t, [2, 6]); + + { + let r; + #[cfg(unset)] + (r = 5); + #[cfg(not(unset))] + (r = 10); + assert_eq!(r, 10); + } + + // check that macro expanded code works + + macro_rules! if_cfg { + ($cfg:meta? $ib:block else $eb:block) => { + { + let r; + #[cfg($cfg)] + (r = $ib); + #[cfg(not($cfg))] + (r = $eb); + r + } + } + } + + let n = if_cfg!(unset? { + 413 + } else { + 612 + }); + + assert_eq!((#[cfg(unset)] 1, #[cfg(not(unset))] 2), (2,)); + assert_eq!(n, 612); + + // check that lints work + + #[allow(non_snake_case)] + let FOOBAR = { + fn SYLADEX() {} + }; + + #[allow(non_snake_case)] + { + fn CRUXTRUDER() {} + } +} diff --git a/tests/ui/cfg/cfgs-on-items.rs b/tests/ui/cfg/cfgs-on-items.rs new file mode 100644 index 000000000..9f2fc4942 --- /dev/null +++ b/tests/ui/cfg/cfgs-on-items.rs @@ -0,0 +1,29 @@ +// run-pass +// compile-flags: --cfg fooA --cfg fooB + +// fooA AND !bar + +#[cfg(all(fooA, not(bar)))] +fn foo1() -> isize { 1 } + +// !fooA AND !bar +#[cfg(all(not(fooA), not(bar)))] +fn foo2() -> isize { 2 } + +// fooC OR (fooB AND !bar) +#[cfg(any(fooC, all(fooB, not(bar))))] +fn foo2() -> isize { 3 } + +// fooA AND bar +#[cfg(all(fooA, bar))] +fn foo3() -> isize { 2 } + +// !(fooA AND bar) +#[cfg(not(all(fooA, bar)))] +fn foo3() -> isize { 3 } + +pub fn main() { + assert_eq!(1, foo1()); + assert_eq!(3, foo2()); + assert_eq!(3, foo3()); +} diff --git a/tests/ui/cfg/conditional-compile-arch.rs b/tests/ui/cfg/conditional-compile-arch.rs new file mode 100644 index 000000000..7de561df1 --- /dev/null +++ b/tests/ui/cfg/conditional-compile-arch.rs @@ -0,0 +1,41 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#[cfg(target_arch = "x86")] +pub fn main() { } + +#[cfg(target_arch = "x86_64")] +pub fn main() { } + +#[cfg(target_arch = "arm")] +pub fn main() { } + +#[cfg(target_arch = "aarch64")] +pub fn main() { } + +#[cfg(target_arch = "mips")] +pub fn main() { } + +#[cfg(target_arch = "mips64")] +pub fn main() { } + +#[cfg(target_arch = "powerpc")] +pub fn main() { } + +#[cfg(target_arch = "powerpc64")] +pub fn main() { } + +#[cfg(target_arch = "s390x")] +pub fn main() { } + +#[cfg(target_arch = "asmjs")] +pub fn main() { } + +#[cfg(target_arch = "wasm32")] +pub fn main() { } + +#[cfg(target_arch = "sparc64")] +pub fn main() { } + +#[cfg(target_arch = "riscv64")] +pub fn main() { } diff --git a/tests/ui/cfg/conditional-compile.rs b/tests/ui/cfg/conditional-compile.rs new file mode 100644 index 000000000..69f4de431 --- /dev/null +++ b/tests/ui/cfg/conditional-compile.rs @@ -0,0 +1,155 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(improper_ctypes)] + +// Crate use statements + +#[cfg(bogus)] +use flippity; + +#[cfg(bogus)] +static b: bool = false; + +static b: bool = true; + +mod rustrt { + #[cfg(bogus)] + extern "C" { + // This symbol doesn't exist and would be a link error if this + // module was codegened + pub fn bogus(); + } + + extern "C" {} +} + +#[cfg(bogus)] +type t = isize; + +type t = bool; + +#[cfg(bogus)] +enum tg { + foo, +} + +enum tg { + bar, +} + +#[cfg(bogus)] +struct r { + i: isize, +} + +#[cfg(bogus)] +fn r(i: isize) -> r { + r { i: i } +} + +struct r { + i: isize, +} + +fn r(i: isize) -> r { + r { i: i } +} + +#[cfg(bogus)] +mod m { + // This needs to parse but would fail in typeck. Since it's not in + // the current config it should not be typechecked. + pub fn bogus() { + return 0; + } +} + +mod m { + // Submodules have slightly different code paths than the top-level + // module, so let's make sure this jazz works here as well + #[cfg(bogus)] + pub fn f() {} + + pub fn f() {} +} + +// Since the bogus configuration isn't defined main will just be +// parsed, but nothing further will be done with it +#[cfg(bogus)] +pub fn main() { + panic!() +} + +pub fn main() { + // Exercise some of the configured items in ways that wouldn't be possible + // if they had the bogus definition + assert!((b)); + let _x: t = true; + let _y: tg = tg::bar; + + test_in_fn_ctxt(); +} + +fn test_in_fn_ctxt() { + #[cfg(bogus)] + fn f() { + panic!() + } + fn f() {} + f(); + + #[cfg(bogus)] + static i: isize = 0; + static i: isize = 1; + assert_eq!(i, 1); +} + +mod test_foreign_items { + pub mod rustrt { + extern "C" { + #[cfg(bogus)] + pub fn write() -> String; + pub fn write() -> String; + } + } +} + +mod test_use_statements { + #[cfg(bogus)] + use flippity_foo; +} + +mod test_methods { + struct Foo { + bar: usize, + } + + impl Fooable for Foo { + #[cfg(bogus)] + fn what(&self) {} + + fn what(&self) {} + + #[cfg(bogus)] + fn the(&self) {} + + fn the(&self) {} + } + + trait Fooable { + #[cfg(bogus)] + fn what(&self); + + fn what(&self); + + #[cfg(bogus)] + fn the(&self); + + fn the(&self); + } +} + +#[cfg(any())] +mod nonexistent_file; // Check that unconfigured non-inline modules are not loaded or parsed. diff --git a/tests/ui/cfg/crt-static-off-works.rs b/tests/ui/cfg/crt-static-off-works.rs new file mode 100644 index 000000000..911467ee5 --- /dev/null +++ b/tests/ui/cfg/crt-static-off-works.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(stable_features)] +// compile-flags:-C target-feature=-crt-static -Z unstable-options +// ignore-musl - requires changing the linker which is hard + +#![feature(cfg_target_feature)] + +#[cfg(not(target_feature = "crt-static"))] +fn main() {} diff --git a/tests/ui/cfg/crt-static-on-works.rs b/tests/ui/cfg/crt-static-on-works.rs new file mode 100644 index 000000000..f89d1edd6 --- /dev/null +++ b/tests/ui/cfg/crt-static-on-works.rs @@ -0,0 +1,6 @@ +// run-pass +// compile-flags:-C target-feature=+crt-static +// only-msvc + +#[cfg(target_feature = "crt-static")] +fn main() {} diff --git a/tests/ui/cfg/expanded-cfg.rs b/tests/ui/cfg/expanded-cfg.rs new file mode 100644 index 000000000..baa161af7 --- /dev/null +++ b/tests/ui/cfg/expanded-cfg.rs @@ -0,0 +1,21 @@ +// check-pass + +macro_rules! mac { + {} => { + #[cfg(attr)] + mod m { + #[lang_item] + fn f() {} + + #[cfg_attr(target_thread_local, custom)] + fn g() {} + } + + #[cfg(attr)] + unconfigured_invocation!(); + } +} + +mac! {} + +fn main() {} diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs new file mode 100644 index 000000000..1f23dadc4 --- /dev/null +++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs @@ -0,0 +1,15 @@ +// check-fail +// compile-flags:--cfg foo + +#![cfg_attr(foo, crate_type="bin")] +//~^ERROR `crate_type` within +//~| WARN this was previously accepted +//~|ERROR `crate_type` within +//~| WARN this was previously accepted +#![cfg_attr(foo, crate_name="bar")] +//~^ERROR `crate_name` within +//~| WARN this was previously accepted +//~|ERROR `crate_name` within +//~| WARN this was previously accepted + +fn main() {} diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr new file mode 100644 index 000000000..9ce4710d6 --- /dev/null +++ b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr @@ -0,0 +1,39 @@ +error: `crate_type` within an `#![cfg_attr] attribute is deprecated` + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 + | +LL | #![cfg_attr(foo, crate_type="bin")] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #91632 + = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default + +error: `crate_name` within an `#![cfg_attr] attribute is deprecated` + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 + | +LL | #![cfg_attr(foo, crate_name="bar")] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #91632 + +error: `crate_type` within an `#![cfg_attr] attribute is deprecated` + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 + | +LL | #![cfg_attr(foo, crate_type="bin")] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #91632 + +error: `crate_name` within an `#![cfg_attr] attribute is deprecated` + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 + | +LL | #![cfg_attr(foo, crate_name="bar")] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #91632 + +error: aborting due to 4 previous errors + diff --git a/tests/ui/cfguard-run.rs b/tests/ui/cfguard-run.rs new file mode 100644 index 000000000..3c4f9a1f5 --- /dev/null +++ b/tests/ui/cfguard-run.rs @@ -0,0 +1,6 @@ +// run-pass +// compile-flags: -C control-flow-guard + +pub fn main() { + println!("hello, world"); +} diff --git a/tests/ui/chalkify/arithmetic.rs b/tests/ui/chalkify/arithmetic.rs new file mode 100644 index 000000000..6c78a71b0 --- /dev/null +++ b/tests/ui/chalkify/arithmetic.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +fn main() { + 1 + 2; + 3 * 6; + 2 - 5; + 17 / 6; + 23 % 11; + 4 & 6; + 7 | 15; + 4 << 7; + 123 >> 3; + 1 == 2; + 5 != 5; + 6 < 2; + 7 > 11; + 3 <= 1; + 9 >= 14; +} diff --git a/tests/ui/chalkify/assert.rs b/tests/ui/chalkify/assert.rs new file mode 100644 index 000000000..834c8935e --- /dev/null +++ b/tests/ui/chalkify/assert.rs @@ -0,0 +1,6 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +fn main() { + assert_eq!(1, 1); +} diff --git a/tests/ui/chalkify/basic.rs b/tests/ui/chalkify/basic.rs new file mode 100644 index 000000000..4a7cd9396 --- /dev/null +++ b/tests/ui/chalkify/basic.rs @@ -0,0 +1,12 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo {} + +struct Bar {} + +impl Foo for Bar {} + +fn main() -> () { + let _ = Bar {}; +} diff --git a/tests/ui/chalkify/bugs/async.rs b/tests/ui/chalkify/bugs/async.rs new file mode 100644 index 000000000..3169e4781 --- /dev/null +++ b/tests/ui/chalkify/bugs/async.rs @@ -0,0 +1,25 @@ +// edition:2021 +// known-bug: unknown +// unset-rustc-env:RUST_BACKTRACE +// compile-flags:-Z trait-solver=chalk +// error-pattern:internal compiler error +// failure-status:101 +// normalize-stderr-test "DefId([^)]*)" -> "..." +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "thread.*panicked.*\n" -> "" +// normalize-stderr-test "stack backtrace:\n" -> "" +// normalize-stderr-test "\s\d{1,}: .*\n" -> "" +// normalize-stderr-test "\s at .*\n" -> "" +// normalize-stderr-test ".*note: Some details.*\n" -> "" +// normalize-stderr-test "\n\n[ ]*\n" -> "" +// normalize-stderr-test "compiler/.*: projection" -> "projection" + +fn main() -> () {} + +async fn foo(x: u32) -> u32 { + x +} diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr new file mode 100644 index 000000000..8043f1e5a --- /dev/null +++ b/tests/ui/chalkify/bugs/async.stderr @@ -0,0 +1,58 @@ +error[E0277]: `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + --> $DIR/async.rs:23:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________- +LL | | x +LL | | } + | | ^ + | | | + | |_`[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]` + = note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `identity_future` + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:23:29: 25:2] as Future>::Output` cannot be known at compilation time + --> $DIR/async.rs:23:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________^ +LL | | x +LL | | } + | |_^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:23:29: 25:2] as Future>::Output` +note: required by a bound in `identity_future` + --> $SRC_DIR/core/src/future/mod.rs:LL:COL + +error[E0277]: `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + --> $DIR/async.rs:23:25 + | +LL | async fn foo(x: u32) -> u32 { + | ^^^ `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]` + = note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited + +error: internal compiler error: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:23:29: 25:2]], def_id: ...) }, Term::Ty(u32)), []), depth=0)` + --> $DIR/async.rs:23:25 + | +LL | async fn foo(x: u32) -> u32 { + | ^^^query stack during panic: +#0 [typeck] type-checking `foo` +#1 [thir_body] building THIR for `foo` +#2 [mir_built] building MIR for `foo` +#3 [unsafety_check_result] unsafety-checking `foo` +#4 [mir_const] preparing `foo` for borrow checking +#5 [mir_promoted] processing MIR for `foo` +#6 [mir_borrowck] borrow-checking `foo` +#7 [type_of] computing type of `foo::{opaque#0}` +#8 [check_mod_item_types] checking item types in top-level module +#9 [analysis] running analysis passes on this crate +end of query stack +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/builtin-copy-clone.rs b/tests/ui/chalkify/builtin-copy-clone.rs new file mode 100644 index 000000000..a478c006e --- /dev/null +++ b/tests/ui/chalkify/builtin-copy-clone.rs @@ -0,0 +1,45 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +// Test that `Clone` is correctly implemented for builtin types. + +#[derive(Copy, Clone)] +struct S(#[allow(unused_tuple_struct_fields)] i32); + +fn test_clone(arg: T) { + let _ = arg.clone(); +} + +fn test_copy(arg: T) { + let _ = arg; + let _ = arg; +} + +fn test_copy_clone(arg: T) { + test_copy(arg); + test_clone(arg); +} + +fn foo() { } + +fn main() { + // FIXME: add closures when they're considered WF + test_copy_clone(foo); + let f: fn() = foo; + test_copy_clone(f); + // FIXME(#86252): reinstate array test after chalk upgrade + //test_copy_clone([1; 56]); + test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1)); + test_copy_clone(()); + test_copy_clone(((1, 1), (1, 1, 1), (1.1, 1, 1, 'a'), ())); + + let a = ( + (S(1), S(0)), + ( + (S(0), S(0), S(1)), + S(0) + ) + ); + test_copy_clone(a); +} diff --git a/tests/ui/chalkify/chalk_initial_program.rs b/tests/ui/chalkify/chalk_initial_program.rs new file mode 100644 index 000000000..21de72b6f --- /dev/null +++ b/tests/ui/chalkify/chalk_initial_program.rs @@ -0,0 +1,16 @@ +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +impl Foo for i32 { } + +impl Foo for u32 { } + +fn gimme() { } + +// Note: this also tests that `std::process::Termination` is implemented for `()`. +fn main() { + gimme::(); + gimme::(); + gimme::(); //~ERROR the trait bound `f32: Foo` is not satisfied +} diff --git a/tests/ui/chalkify/chalk_initial_program.stderr b/tests/ui/chalkify/chalk_initial_program.stderr new file mode 100644 index 000000000..343c0a318 --- /dev/null +++ b/tests/ui/chalkify/chalk_initial_program.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `f32: Foo` is not satisfied + --> $DIR/chalk_initial_program.rs:15:13 + | +LL | gimme::(); + | ^^^ the trait `Foo` is not implemented for `f32` + | + = help: the following other types implement trait `Foo`: + i32 + u32 +note: required by a bound in `gimme` + --> $DIR/chalk_initial_program.rs:9:13 + | +LL | fn gimme() { } + | ^^^ required by this bound in `gimme` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/closure.rs b/tests/ui/chalkify/closure.rs new file mode 100644 index 000000000..a908a1e97 --- /dev/null +++ b/tests/ui/chalkify/closure.rs @@ -0,0 +1,38 @@ +// compile-flags: -Z trait-solver=chalk + +fn main() -> () { + let t = || {}; + t(); + + let mut a = 0; + let mut b = move || { + a = 1; + }; + b(); + + let mut c = b; + + c(); + b(); + + let mut a = 0; + let mut b = || { + a = 1; + }; + b(); + + let mut c = b; + + c(); + b(); //~ ERROR + + // FIXME(chalk): this doesn't quite work + /* + let b = |c| { + c + }; + + let a = &32; + b(a); + */ +} diff --git a/tests/ui/chalkify/closure.stderr b/tests/ui/chalkify/closure.stderr new file mode 100644 index 000000000..a33c0ba0d --- /dev/null +++ b/tests/ui/chalkify/closure.stderr @@ -0,0 +1,22 @@ +error[E0382]: borrow of moved value: `b` + --> $DIR/closure.rs:27:5 + | +LL | let mut c = b; + | - value moved here +... +LL | b(); + | ^ value borrowed here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment + --> $DIR/closure.rs:20:9 + | +LL | a = 1; + | ^ +help: consider mutably borrowing `b` + | +LL | let mut c = &mut b; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/chalkify/generic_impls.rs b/tests/ui/chalkify/generic_impls.rs new file mode 100644 index 000000000..7d33e12d8 --- /dev/null +++ b/tests/ui/chalkify/generic_impls.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +impl Foo for (T, u32) { } + +fn gimme() { } + +fn foo() { + gimme::<(T, u32)>(); + gimme::<(Option, u32)>(); + gimme::<(Option, f32)>(); //~ ERROR +} + +fn main() { + gimme::<(i32, u32)>(); + gimme::<(i32, f32)>(); //~ ERROR +} diff --git a/tests/ui/chalkify/generic_impls.stderr b/tests/ui/chalkify/generic_impls.stderr new file mode 100644 index 000000000..d4a8354d3 --- /dev/null +++ b/tests/ui/chalkify/generic_impls.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `(Option, f32): Foo` is not satisfied + --> $DIR/generic_impls.rs:12:13 + | +LL | gimme::<(Option, f32)>(); + | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(Option, f32)` + | + = help: the trait `Foo` is implemented for `(T, u32)` +note: required by a bound in `gimme` + --> $DIR/generic_impls.rs:7:13 + | +LL | fn gimme() { } + | ^^^ required by this bound in `gimme` + +error[E0277]: the trait bound `(i32, f32): Foo` is not satisfied + --> $DIR/generic_impls.rs:17:13 + | +LL | gimme::<(i32, f32)>(); + | ^^^^^^^^^^ the trait `Foo` is not implemented for `(i32, f32)` + | + = help: the trait `Foo` is implemented for `(T, u32)` +note: required by a bound in `gimme` + --> $DIR/generic_impls.rs:7:13 + | +LL | fn gimme() { } + | ^^^ required by this bound in `gimme` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/impl_wf.rs b/tests/ui/chalkify/impl_wf.rs new file mode 100644 index 000000000..c8dfd4c3a --- /dev/null +++ b/tests/ui/chalkify/impl_wf.rs @@ -0,0 +1,26 @@ +// compile-flags: -Z trait-solver=chalk + +trait Foo: Sized { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } + +impl Foo for str { } +//~^ ERROR the size for values of type `str` cannot be known at compilation time + + +// Implicit `T: Sized` bound. +impl Foo for Option { } + +trait Baz where U: Foo { } + +impl Baz for i32 { } + +impl Baz for f32 { } +//~^ ERROR the trait bound `f32: Foo` is not satisfied + +fn main() { +} diff --git a/tests/ui/chalkify/impl_wf.stderr b/tests/ui/chalkify/impl_wf.stderr new file mode 100644 index 000000000..84c32fa37 --- /dev/null +++ b/tests/ui/chalkify/impl_wf.stderr @@ -0,0 +1,29 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/impl_wf.rs:11:14 + | +LL | impl Foo for str { } + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `Foo` + --> $DIR/impl_wf.rs:3:12 + | +LL | trait Foo: Sized { } + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `f32: Foo` is not satisfied + --> $DIR/impl_wf.rs:22:19 + | +LL | impl Baz for f32 { } + | ^^^ the trait `Foo` is not implemented for `f32` + | + = help: the trait `Foo` is implemented for `i32` +note: required by a bound in `Baz` + --> $DIR/impl_wf.rs:18:31 + | +LL | trait Baz where U: Foo { } + | ^^^ required by this bound in `Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/impl_wf_2.rs b/tests/ui/chalkify/impl_wf_2.rs new file mode 100644 index 000000000..325044ad6 --- /dev/null +++ b/tests/ui/chalkify/impl_wf_2.rs @@ -0,0 +1,33 @@ +// Split out of impl_wf.rs to work around rust aborting compilation early + +// compile-flags: -Z trait-solver=chalk + +trait Foo: Sized { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } + +// Implicit `T: Sized` bound. +impl Foo for Option { } + +impl Bar for () { + type Item = i32; +} + +impl Bar for Option { + type Item = Option; +} + +impl Bar for f32 { + type Item = f32; + //~^ ERROR the trait bound `f32: Foo` is not satisfied +} + +trait Baz where U: Foo { } + +impl Baz for i32 { } + +fn main() {} diff --git a/tests/ui/chalkify/impl_wf_2.stderr b/tests/ui/chalkify/impl_wf_2.stderr new file mode 100644 index 000000000..1c1df644b --- /dev/null +++ b/tests/ui/chalkify/impl_wf_2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `f32: Foo` is not satisfied + --> $DIR/impl_wf_2.rs:25:17 + | +LL | type Item = f32; + | ^^^ the trait `Foo` is not implemented for `f32` + | + = help: the trait `Foo` is implemented for `i32` +note: required by a bound in `Bar::Item` + --> $DIR/impl_wf_2.rs:8:16 + | +LL | type Item: Foo; + | ^^^ required by this bound in `Bar::Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/inherent_impl.rs b/tests/ui/chalkify/inherent_impl.rs new file mode 100644 index 000000000..f0f24d485 --- /dev/null +++ b/tests/ui/chalkify/inherent_impl.rs @@ -0,0 +1,42 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +impl Foo for i32 { } + +struct S { + x: T, +} + +fn only_foo(_x: &T) { } + +impl S { + // Test that we have the correct environment inside an inherent method. + fn dummy_foo(&self) { + only_foo(&self.x) + } +} + +trait Bar { } +impl Bar for u32 { } + +fn only_bar() { } + +impl S { + // Test that the environment of `dummy_bar` adds up with the environment + // of the inherent impl. + fn dummy_bar(&self) { + only_foo(&self.x); + only_bar::(); + } +} + +fn main() { + let s = S { + x: 5, + }; + + s.dummy_bar::(); + s.dummy_foo(); +} diff --git a/tests/ui/chalkify/inherent_impl_min.rs b/tests/ui/chalkify/inherent_impl_min.rs new file mode 100644 index 000000000..3eda7102d --- /dev/null +++ b/tests/ui/chalkify/inherent_impl_min.rs @@ -0,0 +1,27 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +impl Foo for i32 { } + +struct S { + x: T, +} + +fn only_foo(_x: &T) { } + +impl S { + // Test that we have the correct environment inside an inherent method. + fn dummy_foo(&self) { + only_foo(&self.x) + } +} + +fn main() { + let s = S { + x: 5, + }; + + s.dummy_foo(); +} diff --git a/tests/ui/chalkify/lower_env1.rs b/tests/ui/chalkify/lower_env1.rs new file mode 100644 index 000000000..c8762001e --- /dev/null +++ b/tests/ui/chalkify/lower_env1.rs @@ -0,0 +1,14 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +#![allow(dead_code)] + +trait Foo { } + +trait Bar where Self: Foo { } + +fn bar() { +} + +fn main() { +} diff --git a/tests/ui/chalkify/lower_env2.rs b/tests/ui/chalkify/lower_env2.rs new file mode 100644 index 000000000..7d4f81f12 --- /dev/null +++ b/tests/ui/chalkify/lower_env2.rs @@ -0,0 +1,16 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +#![allow(dead_code)] + +trait Foo { } + +struct S<'a, T: ?Sized> where T: Foo { + data: &'a T, +} + +fn bar(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound +} + +fn main() { +} diff --git a/tests/ui/chalkify/lower_env3.rs b/tests/ui/chalkify/lower_env3.rs new file mode 100644 index 000000000..5b70c4abb --- /dev/null +++ b/tests/ui/chalkify/lower_env3.rs @@ -0,0 +1,16 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +#![allow(dead_code)] + +trait Foo { + fn foo(&self); +} + +impl Foo for T where T: Clone { + fn foo(&self) { + } +} + +fn main() { +} diff --git a/tests/ui/chalkify/lower_impl.rs b/tests/ui/chalkify/lower_impl.rs new file mode 100644 index 000000000..6f79b3ba3 --- /dev/null +++ b/tests/ui/chalkify/lower_impl.rs @@ -0,0 +1,17 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +impl Foo for T where T: Iterator { } + +trait Bar { + type Assoc; +} + +impl Bar for T where T: Iterator { + type Assoc = Vec; +} + +fn main() { +} diff --git a/tests/ui/chalkify/lower_struct.rs b/tests/ui/chalkify/lower_struct.rs new file mode 100644 index 000000000..6be0d4dd5 --- /dev/null +++ b/tests/ui/chalkify/lower_struct.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +struct Foo<'a, T> where Box: Clone { + _x: std::marker::PhantomData<&'a T>, +} + +fn main() { } diff --git a/tests/ui/chalkify/lower_trait.rs b/tests/ui/chalkify/lower_trait.rs new file mode 100644 index 000000000..8f5b35822 --- /dev/null +++ b/tests/ui/chalkify/lower_trait.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +trait Bar { } + +trait Foo { + type Assoc: Bar + ?Sized; +} + +fn main() { +} diff --git a/tests/ui/chalkify/lower_trait_higher_rank.rs b/tests/ui/chalkify/lower_trait_higher_rank.rs new file mode 100644 index 000000000..f04a1deea --- /dev/null +++ b/tests/ui/chalkify/lower_trait_higher_rank.rs @@ -0,0 +1,9 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 +{ +} + +fn main() { +} diff --git a/tests/ui/chalkify/lower_trait_where_clause.rs b/tests/ui/chalkify/lower_trait_where_clause.rs new file mode 100644 index 000000000..a21d2f319 --- /dev/null +++ b/tests/ui/chalkify/lower_trait_where_clause.rs @@ -0,0 +1,16 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +use std::borrow::Borrow; + +trait Foo<'a, 'b, T, U> +where + T: Borrow + ?Sized, + U: ?Sized + 'b, + 'a: 'b, + Box:, // NOTE(#53696) this checks an empty list of bounds. +{ +} + +fn main() { +} diff --git a/tests/ui/chalkify/println.rs b/tests/ui/chalkify/println.rs new file mode 100644 index 000000000..edddc3821 --- /dev/null +++ b/tests/ui/chalkify/println.rs @@ -0,0 +1,6 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +fn main() { + println!("hello"); +} diff --git a/tests/ui/chalkify/projection.rs b/tests/ui/chalkify/projection.rs new file mode 100644 index 000000000..19bb2ae14 --- /dev/null +++ b/tests/ui/chalkify/projection.rs @@ -0,0 +1,25 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +trait Bar { + type Item: Foo; +} + +impl Foo for i32 { } +impl Bar for i32 { + type Item = i32; +} + +fn only_foo() { } + +fn only_bar() { + // `T` implements `Bar` hence `::Item` must also implement `Bar` + only_foo::() +} + +fn main() { + only_bar::(); + only_foo::<::Item>(); +} diff --git a/tests/ui/chalkify/recursive_where_clause_on_type.rs b/tests/ui/chalkify/recursive_where_clause_on_type.rs new file mode 100644 index 000000000..c2c8aa6aa --- /dev/null +++ b/tests/ui/chalkify/recursive_where_clause_on_type.rs @@ -0,0 +1,30 @@ +// FIXME(chalk): should fail, see comments +// check-fail +// compile-flags: -Z trait-solver=chalk + +#![feature(trivial_bounds)] + +trait Bar { + fn foo(); +} +trait Foo: Bar { } + +struct S where S: Foo; + +impl Foo for S { +} + +fn bar() { + T::foo(); +} + +fn foo() { + bar::() +} + +fn main() { + // For some reason, the error is duplicated... + + foo::() //~ ERROR the type `S` is not well-formed + //~^ ERROR the type `S` is not well-formed +} diff --git a/tests/ui/chalkify/recursive_where_clause_on_type.stderr b/tests/ui/chalkify/recursive_where_clause_on_type.stderr new file mode 100644 index 000000000..cead5adea --- /dev/null +++ b/tests/ui/chalkify/recursive_where_clause_on_type.stderr @@ -0,0 +1,14 @@ +error: the type `S` is not well-formed + --> $DIR/recursive_where_clause_on_type.rs:28:11 + | +LL | foo::() + | ^ + +error: the type `S` is not well-formed + --> $DIR/recursive_where_clause_on_type.rs:28:5 + | +LL | foo::() + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/chalkify/super_trait.rs b/tests/ui/chalkify/super_trait.rs new file mode 100644 index 000000000..540ae51e5 --- /dev/null +++ b/tests/ui/chalkify/super_trait.rs @@ -0,0 +1,19 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo { } +trait Bar: Foo { } + +impl Foo for i32 { } +impl Bar for i32 { } + +fn only_foo() { } + +fn only_bar() { + // `T` implements `Bar` hence `T` must also implement `Foo` + only_foo::() +} + +fn main() { + only_bar::() +} diff --git a/tests/ui/chalkify/trait-objects.rs b/tests/ui/chalkify/trait-objects.rs new file mode 100644 index 000000000..144d9788b --- /dev/null +++ b/tests/ui/chalkify/trait-objects.rs @@ -0,0 +1,12 @@ +// check-pass +// compile-flags: -Z trait-solver=chalk + +use std::fmt::Display; + +fn main() { + let d: &dyn Display = &mut 3; + d.to_string(); + (&d).to_string(); + let f: &dyn Fn(i32) -> _ = &|x| x + x; + f(2); +} diff --git a/tests/ui/chalkify/trait_implied_bound.rs b/tests/ui/chalkify/trait_implied_bound.rs new file mode 100644 index 000000000..f97dbf6b7 --- /dev/null +++ b/tests/ui/chalkify/trait_implied_bound.rs @@ -0,0 +1,18 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +trait Foo { } +trait Bar where U: Foo { } + +impl Foo for i32 { } +impl Bar for i32 { } + +fn only_foo() { } + +fn only_bar>() { + only_foo::() +} + +fn main() { + only_bar::() +} diff --git a/tests/ui/chalkify/type_implied_bound.rs b/tests/ui/chalkify/type_implied_bound.rs new file mode 100644 index 000000000..70f1b4265 --- /dev/null +++ b/tests/ui/chalkify/type_implied_bound.rs @@ -0,0 +1,29 @@ +// run-pass +// compile-flags: -Z trait-solver=chalk + +trait Eq { } +trait Hash: Eq { } + +impl Eq for i32 { } +impl Hash for i32 { } + +struct Set { + _x: T, +} + +fn only_eq() { } + +fn take_a_set(_: &Set) { + // `Set` is an input type of `take_a_set`, hence we know that + // `T` must implement `Hash`, and we know in turn that `T` must + // implement `Eq`. + only_eq::() +} + +fn main() { + let set = Set { + _x: 5, + }; + + take_a_set(&set); +} diff --git a/tests/ui/chalkify/type_inference.rs b/tests/ui/chalkify/type_inference.rs new file mode 100644 index 000000000..d7167d0dc --- /dev/null +++ b/tests/ui/chalkify/type_inference.rs @@ -0,0 +1,28 @@ +// compile-flags: -Z trait-solver=chalk + +trait Foo { } +impl Foo for i32 { } + +trait Bar { } +impl Bar for i32 { } +impl Bar for u32 { } + +fn only_foo(_x: T) { } + +fn only_bar(_x: T) { } + +fn main() { + let x = 5.0; + + // The only type which implements `Foo` is `i32`, so the chalk trait solver + // is expecting a variable of type `i32`. This behavior differs from the + // old-style trait solver. I guess this will change, that's why I'm + // adding that test. + // FIXME(chalk): order of these two errors is non-deterministic, + // so let's just hide one for now + //only_foo(x); // ERROR the trait bound `f64: Foo` is not satisfied + + // Here we have two solutions so we get back the behavior of the old-style + // trait solver. + only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied +} diff --git a/tests/ui/chalkify/type_inference.stderr b/tests/ui/chalkify/type_inference.stderr new file mode 100644 index 000000000..508a6dd13 --- /dev/null +++ b/tests/ui/chalkify/type_inference.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `{float}: Bar` is not satisfied + --> $DIR/type_inference.rs:27:14 + | +LL | only_bar(x); + | -------- ^ the trait `Bar` is not implemented for `{float}` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Bar`: + i32 + u32 +note: required by a bound in `only_bar` + --> $DIR/type_inference.rs:12:16 + | +LL | fn only_bar(_x: T) { } + | ^^^ required by this bound in `only_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/type_wf.rs b/tests/ui/chalkify/type_wf.rs new file mode 100644 index 000000000..37d2f5ca8 --- /dev/null +++ b/tests/ui/chalkify/type_wf.rs @@ -0,0 +1,25 @@ +// check-fail +// compile-flags: -Z trait-solver=chalk + +trait Foo { } + +struct S { + x: T, +} + +impl Foo for i32 { } +impl Foo for Option { } + +fn main() { + let s = S { + x: 5, + }; + + let s = S { + x: 5.0, //~ ERROR the trait bound `{float}: Foo` is not satisfied + }; + + let s = S { + x: Some(5.0), + }; +} diff --git a/tests/ui/chalkify/type_wf.stderr b/tests/ui/chalkify/type_wf.stderr new file mode 100644 index 000000000..6e8daf635 --- /dev/null +++ b/tests/ui/chalkify/type_wf.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `{float}: Foo` is not satisfied + --> $DIR/type_wf.rs:19:12 + | +LL | x: 5.0, + | ^^^ the trait `Foo` is not implemented for `{float}` + | + = help: the trait `Foo` is implemented for `i32` +note: required by a bound in `S` + --> $DIR/type_wf.rs:6:13 + | +LL | struct S { + | ^^^ required by this bound in `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/char.rs b/tests/ui/char.rs new file mode 100644 index 000000000..cfb7a37af --- /dev/null +++ b/tests/ui/char.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let c: char = 'x'; + let d: char = 'x'; + assert_eq!(c, 'x'); + assert_eq!('x', c); + assert_eq!(c, c); + assert_eq!(c, d); + assert_eq!(d, c); + assert_eq!(d, 'x'); + assert_eq!('x', d); +} diff --git a/tests/ui/check-cfg/allow-at-crate-level.rs b/tests/ui/check-cfg/allow-at-crate-level.rs new file mode 100644 index 000000000..ce3383a29 --- /dev/null +++ b/tests/ui/check-cfg/allow-at-crate-level.rs @@ -0,0 +1,8 @@ +// This test check that #![allow(unexpected_cfgs)] works with --cfg +// +// check-pass +// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options + +#![allow(unexpected_cfgs)] + +fn main() {} diff --git a/tests/ui/check-cfg/allow-macro-cfg.rs b/tests/ui/check-cfg/allow-macro-cfg.rs new file mode 100644 index 000000000..8016a4d19 --- /dev/null +++ b/tests/ui/check-cfg/allow-macro-cfg.rs @@ -0,0 +1,14 @@ +// This test check that local #[allow(unexpected_cfgs)] works +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +#[allow(unexpected_cfgs)] +fn foo() { + if cfg!(FALSE) {} +} + +fn main() { + #[allow(unexpected_cfgs)] + if cfg!(FALSE) {} +} diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs new file mode 100644 index 000000000..6c869dc42 --- /dev/null +++ b/tests/ui/check-cfg/allow-same-level.rs @@ -0,0 +1,11 @@ +// This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +#[allow(unexpected_cfgs)] +#[cfg(FALSE)] +//~^ WARNING unexpected `cfg` condition name +fn bar() {} + +fn main() {} diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr new file mode 100644 index 000000000..7797de584 --- /dev/null +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name + --> $DIR/allow-same-level.rs:7:7 + | +LL | #[cfg(FALSE)] + | ^^^^^ + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs new file mode 100644 index 000000000..d14b0eae5 --- /dev/null +++ b/tests/ui/check-cfg/allow-top-level.rs @@ -0,0 +1,15 @@ +// This test check that a top-level #![allow(unexpected_cfgs)] works +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +#![allow(unexpected_cfgs)] + +#[cfg(FALSE)] +fn bar() {} + +fn foo() { + if cfg!(FALSE) {} +} + +fn main() {} diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs new file mode 100644 index 000000000..04340694d --- /dev/null +++ b/tests/ui/check-cfg/allow-upper-level.rs @@ -0,0 +1,12 @@ +// This test check that #[allow(unexpected_cfgs)] work if put on an upper level +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +#[allow(unexpected_cfgs)] +mod aa { + #[cfg(FALSE)] + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/check-cfg/compact-names.rs b/tests/ui/check-cfg/compact-names.rs new file mode 100644 index 000000000..bff807400 --- /dev/null +++ b/tests/ui/check-cfg/compact-names.rs @@ -0,0 +1,15 @@ +// This test check that we correctly emit an warning for compact cfg +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +#![feature(cfg_target_compact)] + +#[cfg(target(os = "linux", arch = "arm"))] +pub fn expected() {} + +#[cfg(target(os = "linux", architecture = "arm"))] +//~^ WARNING unexpected `cfg` condition name +pub fn unexpected() {} + +fn main() {} diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr new file mode 100644 index 000000000..f1fc4285a --- /dev/null +++ b/tests/ui/check-cfg/compact-names.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name + --> $DIR/compact-names.rs:11:28 + | +LL | #[cfg(target(os = "linux", architecture = "arm"))] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs new file mode 100644 index 000000000..1f1705784 --- /dev/null +++ b/tests/ui/check-cfg/compact-values.rs @@ -0,0 +1,15 @@ +// This test check that we correctly emit an warning for compact cfg +// +// check-pass +// compile-flags:--check-cfg=values() -Z unstable-options + +#![feature(cfg_target_compact)] + +#[cfg(target(os = "linux", arch = "arm"))] +pub fn expected() {} + +#[cfg(target(os = "linux", arch = "X"))] +//~^ WARNING unexpected `cfg` condition value +pub fn unexpected() {} + +fn main() {} diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr new file mode 100644 index 000000000..9864aa385 --- /dev/null +++ b/tests/ui/check-cfg/compact-values.stderr @@ -0,0 +1,11 @@ +warning: unexpected `cfg` condition value + --> $DIR/compact-values.rs:11:28 + | +LL | #[cfg(target(os = "linux", arch = "X"))] + | ^^^^^^^^^^ + | + = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64 + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/empty-names.rs b/tests/ui/check-cfg/empty-names.rs new file mode 100644 index 000000000..046ff0364 --- /dev/null +++ b/tests/ui/check-cfg/empty-names.rs @@ -0,0 +1,10 @@ +// Check warning for unexpected cfg +// +// check-pass +// compile-flags: --check-cfg=names() -Z unstable-options + +#[cfg(unknown_key = "value")] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/empty-names.stderr b/tests/ui/check-cfg/empty-names.stderr new file mode 100644 index 000000000..f926d1133 --- /dev/null +++ b/tests/ui/check-cfg/empty-names.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name + --> $DIR/empty-names.rs:6:7 + | +LL | #[cfg(unknown_key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/empty-values.rs b/tests/ui/check-cfg/empty-values.rs new file mode 100644 index 000000000..9bda42e5d --- /dev/null +++ b/tests/ui/check-cfg/empty-values.rs @@ -0,0 +1,10 @@ +// Check warning for unexpected cfg value +// +// check-pass +// compile-flags: --check-cfg=values() -Z unstable-options + +#[cfg(test = "value")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +fn main() {} diff --git a/tests/ui/check-cfg/empty-values.stderr b/tests/ui/check-cfg/empty-values.stderr new file mode 100644 index 000000000..a0168b2ca --- /dev/null +++ b/tests/ui/check-cfg/empty-values.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition value + --> $DIR/empty-values.rs:6:7 + | +LL | #[cfg(test = "value")] + | ^^^^---------- + | | + | help: remove the value + | + = note: no expected value for `test` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/invalid-arguments.anything_else.stderr b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr new file mode 100644 index 000000000..850924d99 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.anything_else.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `anything_else(...)` (expected `names(name1, name2, ... nameN)` or `values(name, "value1", "value2", ... "valueN")`) + diff --git a/tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr b/tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr new file mode 100644 index 000000000..8fadcc1f9 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.names_simple_ident.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `names("NOT_IDENT")` (`names()` arguments must be simple identifiers) + diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs new file mode 100644 index 000000000..5090ce3e8 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -0,0 +1,10 @@ +// Check that invalid --check-cfg are rejected +// +// check-fail +// revisions: anything_else names_simple_ident values_simple_ident values_string_literals +// [anything_else]compile-flags: -Z unstable-options --check-cfg=anything_else(...) +// [names_simple_ident]compile-flags: -Z unstable-options --check-cfg=names("NOT_IDENT") +// [values_simple_ident]compile-flags: -Z unstable-options --check-cfg=values("NOT_IDENT") +// [values_string_literals]compile-flags: -Z unstable-options --check-cfg=values(test,12) + +fn main() {} diff --git a/tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr b/tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr new file mode 100644 index 000000000..061d3f0e9 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.values_simple_ident.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `values("NOT_IDENT")` (`values()` first argument must be a simple identifier) + diff --git a/tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr b/tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr new file mode 100644 index 000000000..5853b4741 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.values_string_literals.stderr @@ -0,0 +1,2 @@ +error: invalid `--check-cfg` argument: `values(test,12)` (`values()` arguments must be string literals) + diff --git a/tests/ui/check-cfg/invalid-cfg-name.rs b/tests/ui/check-cfg/invalid-cfg-name.rs new file mode 100644 index 000000000..8499d3d44 --- /dev/null +++ b/tests/ui/check-cfg/invalid-cfg-name.rs @@ -0,0 +1,14 @@ +// Check warning for invalid configuration name +// +// edition:2018 +// check-pass +// compile-flags: --check-cfg=names() -Z unstable-options + +#[cfg(widnows)] +//~^ WARNING unexpected `cfg` condition name +pub fn f() {} + +#[cfg(windows)] +pub fn g() {} + +pub fn main() {} diff --git a/tests/ui/check-cfg/invalid-cfg-name.stderr b/tests/ui/check-cfg/invalid-cfg-name.stderr new file mode 100644 index 000000000..2bd1821c9 --- /dev/null +++ b/tests/ui/check-cfg/invalid-cfg-name.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name + --> $DIR/invalid-cfg-name.rs:7:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: did you mean: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/invalid-cfg-value.rs b/tests/ui/check-cfg/invalid-cfg-value.rs new file mode 100644 index 000000000..9e428d367 --- /dev/null +++ b/tests/ui/check-cfg/invalid-cfg-value.rs @@ -0,0 +1,18 @@ +// Check warning for invalid configuration value +// +// edition:2018 +// check-pass +// compile-flags: --check-cfg=values(feature,"serde","full") --cfg=feature="rand" -Z unstable-options + +#[cfg(feature = "sedre")] +//~^ WARNING unexpected `cfg` condition value +pub fn f() {} + +#[cfg(feature = "serde")] +pub fn g() {} + +#[cfg(feature = "rand")] +//~^ WARNING unexpected `cfg` condition value +pub fn h() {} + +pub fn main() {} diff --git a/tests/ui/check-cfg/invalid-cfg-value.stderr b/tests/ui/check-cfg/invalid-cfg-value.stderr new file mode 100644 index 000000000..60abcb188 --- /dev/null +++ b/tests/ui/check-cfg/invalid-cfg-value.stderr @@ -0,0 +1,23 @@ +warning: unexpected `cfg` condition value + --> $DIR/invalid-cfg-value.rs:7:7 + | +LL | #[cfg(feature = "sedre")] + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: full, serde + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value + --> $DIR/invalid-cfg-value.rs:14:7 + | +LL | #[cfg(feature = "rand")] + | ^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: full, serde + +warning: unexpected condition value `rand` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs new file mode 100644 index 000000000..4e488fc03 --- /dev/null +++ b/tests/ui/check-cfg/mix.rs @@ -0,0 +1,74 @@ +// This test checks the combination of well known names, their activation via names(), +// the usage of values(), and that no implicit is done with --cfg while also testing that +// we correctly lint on the `cfg!` macro and `cfg_attr` attribute. +// +// check-pass +// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options + +#[cfg(windows)] +fn do_windows_stuff() {} + +#[cfg(widnows)] +//~^ WARNING unexpected `cfg` condition name +fn do_windows_stuff() {} + +#[cfg(feature = "foo")] +fn use_foo() {} + +#[cfg(feature = "bar")] +//~^ WARNING unexpected `cfg` condition value +fn use_bar() {} + +#[cfg(feature = "zebra")] +//~^ WARNING unexpected `cfg` condition value +fn use_zebra() {} + +#[cfg_attr(uu, test)] +//~^ WARNING unexpected `cfg` condition name +fn do_test() {} + +#[cfg_attr(feature = "foo", no_mangle)] +fn do_test_foo() {} + +fn test_cfg_macro() { + cfg!(windows); + cfg!(widnows); + //~^ WARNING unexpected `cfg` condition name + cfg!(feature = "foo"); + cfg!(feature = "bar"); + //~^ WARNING unexpected `cfg` condition value + cfg!(feature = "zebra"); + //~^ WARNING unexpected `cfg` condition value + cfg!(xxx = "foo"); + //~^ WARNING unexpected `cfg` condition name + cfg!(xxx); + //~^ WARNING unexpected `cfg` condition name + cfg!(any(xxx, windows)); + //~^ WARNING unexpected `cfg` condition name + cfg!(any(feature = "bad", windows)); + //~^ WARNING unexpected `cfg` condition value + cfg!(any(windows, xxx)); + //~^ WARNING unexpected `cfg` condition name + cfg!(all(unix, xxx)); + //~^ WARNING unexpected `cfg` condition name + cfg!(all(aa, bb)); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition name + cfg!(any(aa, bb)); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition name + cfg!(any(unix, feature = "zebra")); + //~^ WARNING unexpected `cfg` condition value + cfg!(any(xxx, feature = "zebra")); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition value + cfg!(any(xxx, unix, xxx)); + //~^ WARNING unexpected `cfg` condition name + //~| WARNING unexpected `cfg` condition name + cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + //~^ WARNING unexpected `cfg` condition value + //~| WARNING unexpected `cfg` condition value + //~| WARNING unexpected `cfg` condition value +} + +fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr new file mode 100644 index 000000000..9cf887ec7 --- /dev/null +++ b/tests/ui/check-cfg/mix.stderr @@ -0,0 +1,182 @@ +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:11:7 + | +LL | #[cfg(widnows)] + | ^^^^^^^ help: did you mean: `windows` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:18:7 + | +LL | #[cfg(feature = "bar")] + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:22:7 + | +LL | #[cfg(feature = "zebra")] + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:26:12 + | +LL | #[cfg_attr(uu, test)] + | ^^ + +warning: unexpected condition value `bar` for condition name `feature` + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected values + +warning: unexpected `unknown_name` as condition name + | + = help: was set with `--cfg` but isn't in the `--check-cfg` expected names + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:35:10 + | +LL | cfg!(widnows); + | ^^^^^^^ help: did you mean: `windows` + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:38:10 + | +LL | cfg!(feature = "bar"); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:40:10 + | +LL | cfg!(feature = "zebra"); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:42:10 + | +LL | cfg!(xxx = "foo"); + | ^^^^^^^^^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:44:10 + | +LL | cfg!(xxx); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:46:14 + | +LL | cfg!(any(xxx, windows)); + | ^^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:48:14 + | +LL | cfg!(any(feature = "bad", windows)); + | ^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:50:23 + | +LL | cfg!(any(windows, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:52:20 + | +LL | cfg!(all(unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:54:14 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:54:18 + | +LL | cfg!(all(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:57:14 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:57:18 + | +LL | cfg!(any(aa, bb)); + | ^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:60:20 + | +LL | cfg!(any(unix, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:62:14 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:62:19 + | +LL | cfg!(any(xxx, feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:65:14 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition name + --> $DIR/mix.rs:65:25 + | +LL | cfg!(any(xxx, unix, xxx)); + | ^^^ + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:68:14 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:68:33 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: unexpected `cfg` condition value + --> $DIR/mix.rs:68:52 + | +LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); + | ^^^^^^^^^^^^^^^^^ + | + = note: expected values for `feature` are: foo + +warning: 27 warnings emitted + diff --git a/tests/ui/check-cfg/no-values.rs b/tests/ui/check-cfg/no-values.rs new file mode 100644 index 000000000..8c80f56cb --- /dev/null +++ b/tests/ui/check-cfg/no-values.rs @@ -0,0 +1,14 @@ +// Check that we detect unexpected value when none are allowed +// +// check-pass +// compile-flags: --check-cfg=values(test) --check-cfg=values(feature) -Z unstable-options + +#[cfg(feature = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +#[cfg(test = "foo")] +//~^ WARNING unexpected `cfg` condition value +fn do_foo() {} + +fn main() {} diff --git a/tests/ui/check-cfg/no-values.stderr b/tests/ui/check-cfg/no-values.stderr new file mode 100644 index 000000000..8c926d187 --- /dev/null +++ b/tests/ui/check-cfg/no-values.stderr @@ -0,0 +1,21 @@ +warning: unexpected `cfg` condition value + --> $DIR/no-values.rs:6:7 + | +LL | #[cfg(feature = "foo")] + | ^^^^^^^^^^^^^^^ + | + = note: no expected value for `feature` + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value + --> $DIR/no-values.rs:10:7 + | +LL | #[cfg(test = "foo")] + | ^^^^-------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/stmt-no-ice.rs b/tests/ui/check-cfg/stmt-no-ice.rs new file mode 100644 index 000000000..cf76487ed --- /dev/null +++ b/tests/ui/check-cfg/stmt-no-ice.rs @@ -0,0 +1,10 @@ +// This test checks that there is no ICE with this code +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +fn main() { + #[cfg(crossbeam_loom)] + //~^ WARNING unexpected `cfg` condition name + {} +} diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr new file mode 100644 index 000000000..da65b5969 --- /dev/null +++ b/tests/ui/check-cfg/stmt-no-ice.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name + --> $DIR/stmt-no-ice.rs:7:11 + | +LL | #[cfg(crossbeam_loom)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs new file mode 100644 index 000000000..e57fb69a1 --- /dev/null +++ b/tests/ui/check-cfg/well-known-names.rs @@ -0,0 +1,33 @@ +// This test checks that we lint on non well known names and that we don't lint on well known names +// +// check-pass +// compile-flags: --check-cfg=names() -Z unstable-options + +#[cfg(target_oz = "linux")] +//~^ WARNING unexpected `cfg` condition name +fn target_os_misspell() {} + +#[cfg(target_os = "linux")] +fn target_os() {} + +#[cfg(features = "foo")] +//~^ WARNING unexpected `cfg` condition name +fn feature_misspell() {} + +#[cfg(feature = "foo")] +fn feature() {} + +#[cfg(uniw)] +//~^ WARNING unexpected `cfg` condition name +fn unix_misspell() {} + +#[cfg(unix)] +fn unix() {} + +#[cfg(miri)] +fn miri() {} + +#[cfg(doc)] +fn doc() {} + +fn main() {} diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr new file mode 100644 index 000000000..bdbe4d29d --- /dev/null +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -0,0 +1,26 @@ +warning: unexpected `cfg` condition name + --> $DIR/well-known-names.rs:6:7 + | +LL | #[cfg(target_oz = "linux")] + | ---------^^^^^^^^^^ + | | + | help: did you mean: `target_os` + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition name + --> $DIR/well-known-names.rs:13:7 + | +LL | #[cfg(features = "foo")] + | --------^^^^^^^^ + | | + | help: did you mean: `feature` + +warning: unexpected `cfg` condition name + --> $DIR/well-known-names.rs:20:7 + | +LL | #[cfg(uniw)] + | ^^^^ help: did you mean: `unix` + +warning: 3 warnings emitted + diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs new file mode 100644 index 000000000..96375dc8d --- /dev/null +++ b/tests/ui/check-cfg/well-known-values.rs @@ -0,0 +1,42 @@ +// This test check that we lint on non well known values and that we don't lint on well known +// values +// +// check-pass +// compile-flags: --check-cfg=values() -Z unstable-options + +#[cfg(target_os = "linuz")] +//~^ WARNING unexpected `cfg` condition value +fn target_os_linux_misspell() {} + +#[cfg(target_os = "linux")] +fn target_os_linux() {} + +#[cfg(target_has_atomic = "0")] +//~^ WARNING unexpected `cfg` condition value +fn target_has_atomic_invalid() {} + +#[cfg(target_has_atomic = "8")] +fn target_has_atomic() {} + +#[cfg(unix = "aa")] +//~^ WARNING unexpected `cfg` condition value +fn unix_with_value() {} + +#[cfg(unix)] +fn unix() {} + +#[cfg(miri = "miri")] +//~^ WARNING unexpected `cfg` condition value +fn miri_with_value() {} + +#[cfg(miri)] +fn miri() {} + +#[cfg(doc = "linux")] +//~^ WARNING unexpected `cfg` condition value +fn doc_with_value() {} + +#[cfg(doc)] +fn doc() {} + +fn main() {} diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr new file mode 100644 index 000000000..69d799783 --- /dev/null +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -0,0 +1,53 @@ +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:7:7 + | +LL | #[cfg(target_os = "linuz")] + | ^^^^^^^^^^^^------- + | | + | help: did you mean: `"linux"` + | + = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vita, vxworks, wasi, watchos, windows, xous + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:14:7 + | +LL | #[cfg(target_has_atomic = "0")] + | ^^^^^^^^^^^^^^^^^^^^--- + | | + | help: did you mean: `"8"` + | + = note: expected values for `target_has_atomic` are: 128, 16, 32, 64, 8, ptr + +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:21:7 + | +LL | #[cfg(unix = "aa")] + | ^^^^------- + | | + | help: remove the value + | + = note: no expected value for `unix` + +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:28:7 + | +LL | #[cfg(miri = "miri")] + | ^^^^--------- + | | + | help: remove the value + | + = note: no expected value for `miri` + +warning: unexpected `cfg` condition value + --> $DIR/well-known-values.rs:35:7 + | +LL | #[cfg(doc = "linux")] + | ^^^---------- + | | + | help: remove the value + | + = note: no expected value for `doc` + +warning: 5 warnings emitted + diff --git a/tests/ui/check-static-immutable-mut-slices.rs b/tests/ui/check-static-immutable-mut-slices.rs new file mode 100644 index 000000000..8f9680778 --- /dev/null +++ b/tests/ui/check-static-immutable-mut-slices.rs @@ -0,0 +1,6 @@ +// Checks that immutable static items can't have mutable slices + +static TEST: &'static mut [isize] = &mut []; +//~^ ERROR mutable references are not allowed + +pub fn main() { } diff --git a/tests/ui/check-static-immutable-mut-slices.stderr b/tests/ui/check-static-immutable-mut-slices.stderr new file mode 100644 index 000000000..a32a94c13 --- /dev/null +++ b/tests/ui/check-static-immutable-mut-slices.stderr @@ -0,0 +1,9 @@ +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/check-static-immutable-mut-slices.rs:3:37 + | +LL | static TEST: &'static mut [isize] = &mut []; + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0764`. diff --git a/tests/ui/check-static-recursion-foreign.rs b/tests/ui/check-static-recursion-foreign.rs new file mode 100644 index 000000000..3072deb6c --- /dev/null +++ b/tests/ui/check-static-recursion-foreign.rs @@ -0,0 +1,23 @@ +// run-pass + +// Static recursion check shouldn't fail when given a foreign item (#18279) + +// aux-build:check_static_recursion_foreign_helper.rs +// ignore-wasm32-bare no libc to test ffi with + +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + +extern crate check_static_recursion_foreign_helper; +extern crate libc; + +use libc::c_int; + +extern "C" { + static test_static: c_int; +} + +pub static B: &'static c_int = unsafe { &test_static }; + +pub fn main() {} diff --git a/tests/ui/check-static-values-constraints.rs b/tests/ui/check-static-values-constraints.rs new file mode 100644 index 000000000..f6a577d0d --- /dev/null +++ b/tests/ui/check-static-values-constraints.rs @@ -0,0 +1,113 @@ +// Verifies all possible restrictions for statics values. + +#![allow(warnings)] +#![feature(box_syntax)] + +use std::marker; + +struct WithDtor; + +impl Drop for WithDtor { + fn drop(&mut self) {} +} + +// This enum will be used to test the following rules: +// 1. Variants are safe for static +// 2. Expr calls are allowed as long as they arguments are safe +// 3. Expr calls with unsafe arguments for statics are rejected +enum SafeEnum { + Variant1, + Variant2(isize), + Variant3(WithDtor), + Variant4(String) +} + +// These should be ok +static STATIC1: SafeEnum = SafeEnum::Variant1; +static STATIC2: SafeEnum = SafeEnum::Variant2(0); +static STATIC3: SafeEnum = SafeEnum::Variant3(WithDtor); + +enum UnsafeEnum { + Variant5, + Variant6(isize) +} + +impl Drop for UnsafeEnum { + fn drop(&mut self) {} +} + + +static STATIC4: UnsafeEnum = UnsafeEnum::Variant5; +static STATIC5: UnsafeEnum = UnsafeEnum::Variant6(0); + + +struct SafeStruct { + field1: SafeEnum, + field2: SafeEnum, +} + + +// Struct fields are safe, hence this static should be safe +static STATIC6: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, field2: SafeEnum::Variant2(0)}; + +static STATIC7: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, + field2: SafeEnum::Variant3(WithDtor)}; + +// Test variadic constructor for structs. The base struct should be examined +// as well as every field present in the constructor. +// This example shouldn't fail because all the fields are safe. +static STATIC8: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, + ..SafeStruct{field1: SafeEnum::Variant1, + field2: SafeEnum::Variant1}}; + +// This example should fail because field1 in the base struct is not safe +static STATIC9: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, + ..SafeStruct{field1: SafeEnum::Variant3(WithDtor), +//~^ ERROR destructor of + field2: SafeEnum::Variant1}}; + +struct UnsafeStruct; + +impl Drop for UnsafeStruct { + fn drop(&mut self) {} +} + +static STATIC10: UnsafeStruct = UnsafeStruct; + +struct MyOwned; + +static STATIC11: Box = box MyOwned; +//~^ ERROR allocations are not allowed in statics + +static mut STATIC12: UnsafeStruct = UnsafeStruct; + +static mut STATIC13: SafeStruct = SafeStruct{field1: SafeEnum::Variant1, + field2: SafeEnum::Variant3(WithDtor)}; + +static mut STATIC14: SafeStruct = SafeStruct { + field1: SafeEnum::Variant1, + field2: SafeEnum::Variant4("str".to_string()) +//~^ ERROR cannot call non-const fn +}; + +static STATIC15: &'static [Box] = &[ + box MyOwned, //~ ERROR allocations are not allowed in statics + box MyOwned, //~ ERROR allocations are not allowed in statics +]; + +static STATIC16: (&'static Box, &'static Box) = ( + &box MyOwned, //~ ERROR allocations are not allowed in statics + &box MyOwned, //~ ERROR allocations are not allowed in statics +); + +static mut STATIC17: SafeEnum = SafeEnum::Variant1; + +static STATIC19: Box = + box 3; +//~^ ERROR allocations are not allowed in statics + +pub fn main() { + let y = { static x: Box = box 3; x }; + //~^ ERROR allocations are not allowed in statics + //~| ERROR cannot move out of static item +} diff --git a/tests/ui/check-static-values-constraints.stderr b/tests/ui/check-static-values-constraints.stderr new file mode 100644 index 000000000..490566784 --- /dev/null +++ b/tests/ui/check-static-values-constraints.stderr @@ -0,0 +1,78 @@ +error[E0493]: destructor of `SafeStruct` cannot be evaluated at compile-time + --> $DIR/check-static-values-constraints.rs:65:43 + | +LL | ..SafeStruct{field1: SafeEnum::Variant3(WithDtor), + | ___________________________________________^ +LL | | +LL | | field2: SafeEnum::Variant1}}; + | | ^- value is dropped here + | |________________________________________________________________________________| + | the destructor for this type cannot be evaluated in statics + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:79:33 + | +LL | static STATIC11: Box = box MyOwned; + | ^^^^^^^^^^^ allocation not allowed in statics + +error[E0015]: cannot call non-const fn `::to_string` in statics + --> $DIR/check-static-values-constraints.rs:89:38 + | +LL | field2: SafeEnum::Variant4("str".to_string()) + | ^^^^^^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:94:5 + | +LL | box MyOwned, + | ^^^^^^^^^^^ allocation not allowed in statics + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:95:5 + | +LL | box MyOwned, + | ^^^^^^^^^^^ allocation not allowed in statics + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:99:6 + | +LL | &box MyOwned, + | ^^^^^^^^^^^ allocation not allowed in statics + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:100:6 + | +LL | &box MyOwned, + | ^^^^^^^^^^^ allocation not allowed in statics + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:106:5 + | +LL | box 3; + | ^^^^^ allocation not allowed in statics + +error[E0507]: cannot move out of static item `x` + --> $DIR/check-static-values-constraints.rs:110:45 + | +LL | let y = { static x: Box = box 3; x }; + | ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let y = { static x: Box = box 3; &x }; + | + + +error[E0010]: allocations are not allowed in statics + --> $DIR/check-static-values-constraints.rs:110:38 + | +LL | let y = { static x: Box = box 3; x }; + | ^^^^^ allocation not allowed in statics + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0010, E0015, E0493, E0507. +For more information about an error, try `rustc --explain E0010`. diff --git a/tests/ui/class-cast-to-trait.rs b/tests/ui/class-cast-to-trait.rs new file mode 100644 index 000000000..345d6efd2 --- /dev/null +++ b/tests/ui/class-cast-to-trait.rs @@ -0,0 +1,54 @@ +trait Noisy { + fn speak(&self); +} + +struct Cat { + meows : usize, + + how_hungry : isize, + name : String, +} + +impl Cat { + pub fn eat(&self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } + else { + println!("Not hungry!"); + return false; + } + } +} + +impl Noisy for Cat { + fn speak(&self) { self.meow(); } + +} + +impl Cat { + fn meow(&self) { + println!("Meow"); + self.meows += 1; + if self.meows % 5 == 0 { + self.how_hungry += 1; + } + } +} + +fn cat(in_x : usize, in_y : isize, in_name: String) -> Cat { + Cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } +} + + + +fn main() { + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; + nyan.eat(); //~ ERROR no method named `eat` found +} diff --git a/tests/ui/class-cast-to-trait.stderr b/tests/ui/class-cast-to-trait.stderr new file mode 100644 index 000000000..56d10d88d --- /dev/null +++ b/tests/ui/class-cast-to-trait.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `eat` found for struct `Box` in the current scope + --> $DIR/class-cast-to-trait.rs:53:8 + | +LL | nyan.eat(); + | ^^^ method not found in `Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/class-method-missing.rs b/tests/ui/class-method-missing.rs new file mode 100644 index 000000000..5dc18328f --- /dev/null +++ b/tests/ui/class-method-missing.rs @@ -0,0 +1,21 @@ +trait Animal { + fn eat(&self); +} + +struct Cat { + meows: usize, +} + +impl Animal for Cat { + //~^ ERROR not all trait items implemented, missing: `eat` +} + +fn cat(in_x : usize) -> Cat { + Cat { + meows: in_x + } +} + +fn main() { + let nyan = cat(0); +} diff --git a/tests/ui/class-method-missing.stderr b/tests/ui/class-method-missing.stderr new file mode 100644 index 000000000..3b4ac3a9a --- /dev/null +++ b/tests/ui/class-method-missing.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `eat` + --> $DIR/class-method-missing.rs:9:1 + | +LL | fn eat(&self); + | -------------- `eat` from trait +... +LL | impl Animal for Cat { + | ^^^^^^^^^^^^^^^^^^^ missing `eat` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/cleanup-rvalue-for-scope.rs b/tests/ui/cleanup-rvalue-for-scope.rs new file mode 100644 index 000000000..b6582c01f --- /dev/null +++ b/tests/ui/cleanup-rvalue-for-scope.rs @@ -0,0 +1,63 @@ +// run-pass + +#![allow(non_snake_case)] +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that the lifetime of rvalues in for loops is extended +// to the for loop itself. + +use std::ops::Drop; + +static mut FLAGS: u64 = 0; + +struct Box { f: T } +struct AddFlags { bits: u64 } + +fn AddFlags(bits: u64) -> AddFlags { + AddFlags { bits: bits } +} + +fn arg(exp: u64, _x: &AddFlags) { + check_flags(exp); +} + +fn pass(v: T) -> T { + v +} + +fn check_flags(exp: u64) { + unsafe { + let x = FLAGS; + FLAGS = 0; + println!("flags {}, expected {}", x, exp); + assert_eq!(x, exp); + } +} + +impl AddFlags { + fn check_flags(&self, exp: u64) -> &AddFlags { + check_flags(exp); + self + } + + fn bits(&self) -> u64 { + self.bits + } +} + +impl Drop for AddFlags { + fn drop(&mut self) { + unsafe { + FLAGS = FLAGS + self.bits; + } + } +} + +pub fn main() { + // The array containing [AddFlags] should not be dropped until + // after the for loop: + for x in &[AddFlags(1)] { + check_flags(0); + } + check_flags(1); +} diff --git a/tests/ui/cleanup-rvalue-scopes-cf.rs b/tests/ui/cleanup-rvalue-scopes-cf.rs new file mode 100644 index 000000000..e3cecb1bf --- /dev/null +++ b/tests/ui/cleanup-rvalue-scopes-cf.rs @@ -0,0 +1,35 @@ +// Test that the borrow checker prevents pointers to temporaries +// with statement lifetimes from escaping. + +use std::ops::Drop; + +static mut FLAGS: u64 = 0; + +struct StackBox { f: T } +struct AddFlags { bits: u64 } + +fn AddFlags(bits: u64) -> AddFlags { + AddFlags { bits: bits } +} + +fn arg(x: &AddFlags) -> &AddFlags { + x +} + +impl AddFlags { + fn get(&self) -> &AddFlags { + self + } +} + +pub fn main() { + let x1 = arg(&AddFlags(1)); //~ ERROR temporary value dropped while borrowed + let x2 = AddFlags(1).get(); //~ ERROR temporary value dropped while borrowed + let x3 = &*arg(&AddFlags(1)); //~ ERROR temporary value dropped while borrowed + let ref x4 = *arg(&AddFlags(1)); //~ ERROR temporary value dropped while borrowed + let &ref x5 = arg(&AddFlags(1)); //~ ERROR temporary value dropped while borrowed + let x6 = AddFlags(1).get(); //~ ERROR temporary value dropped while borrowed + let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() }; + //~^ ERROR temporary value dropped while borrowed + (x1, x2, x3, x4, x5, x6, x7); +} diff --git a/tests/ui/cleanup-rvalue-scopes-cf.stderr b/tests/ui/cleanup-rvalue-scopes-cf.stderr new file mode 100644 index 000000000..425cd7514 --- /dev/null +++ b/tests/ui/cleanup-rvalue-scopes-cf.stderr @@ -0,0 +1,122 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:26:19 + | +LL | let x1 = arg(&AddFlags(1)); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let x1 = arg(&binding); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:27:14 + | +LL | let x2 = AddFlags(1).get(); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let x2 = binding.get(); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:28:21 + | +LL | let x3 = &*arg(&AddFlags(1)); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let x3 = &*arg(&binding); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:29:24 + | +LL | let ref x4 = *arg(&AddFlags(1)); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let ref x4 = *arg(&binding); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:30:24 + | +LL | let &ref x5 = arg(&AddFlags(1)); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let &ref x5 = arg(&binding); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:31:14 + | +LL | let x6 = AddFlags(1).get(); + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let x6 = binding.get(); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/cleanup-rvalue-scopes-cf.rs:32:44 + | +LL | let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() }; + | ^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | +LL | (x1, x2, x3, x4, x5, x6, x7); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = AddFlags(1); +LL ~ let StackBox { f: x7 } = StackBox { f: binding.get() }; + | + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/cleanup-rvalue-scopes.rs b/tests/ui/cleanup-rvalue-scopes.rs new file mode 100644 index 000000000..b80f95b79 --- /dev/null +++ b/tests/ui/cleanup-rvalue-scopes.rs @@ -0,0 +1,130 @@ +// run-pass +#![allow(unused_braces)] +#![allow(non_snake_case)] +#![allow(unused_variables)] +// Test that destructors for rvalue temporaries run either at end of +// statement or end of block, as appropriate given the temporary +// lifetime rules. + +#![feature(box_patterns)] + +use std::ops::Drop; + +static mut FLAGS: u64 = 0; + +struct Box { f: T } +struct AddFlags { bits: u64 } + +fn AddFlags(bits: u64) -> AddFlags { + AddFlags { bits: bits } +} + +fn arg(exp: u64, _x: &AddFlags) { + check_flags(exp); +} + +fn pass(v: T) -> T { + v +} + +fn check_flags(exp: u64) { + unsafe { + let x = FLAGS; + FLAGS = 0; + println!("flags {}, expected {}", x, exp); + assert_eq!(x, exp); + } +} + +impl AddFlags { + fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags { + check_flags(exp); + self + } + + fn bits(&self) -> u64 { + self.bits + } +} + +impl Drop for AddFlags { + fn drop(&mut self) { + unsafe { + FLAGS = FLAGS + self.bits; + } + } +} + +macro_rules! end_of_block { + ($pat:pat, $expr:expr) => ( + { + println!("end_of_block({})", stringify!({let $pat = $expr;})); + + { + // Destructor here does not run until exit from the block. + let $pat = $expr; + check_flags(0); + } + check_flags(1); + } + ) +} + +macro_rules! end_of_stmt { + ($pat:pat, $expr:expr) => ( + { + println!("end_of_stmt({})", stringify!($expr)); + + { + // Destructor here run after `let` statement + // terminates. + let $pat = $expr; + check_flags(1); + } + + check_flags(0); + } + ) +} + +pub fn main() { + + // In all these cases, we trip over the rules designed to cover + // the case where we are taking addr of rvalue and storing that + // addr into a stack slot, either via `let ref` or via a `&` in + // the initializer. + + end_of_block!(_x, AddFlags(1)); + end_of_block!(_x, &AddFlags(1)); + end_of_block!(_x, & &AddFlags(1)); + end_of_block!(_x, Box { f: AddFlags(1) }); + end_of_block!(_x, Box { f: &AddFlags(1) }); + end_of_block!(_x, Box { f: &AddFlags(1) }); + end_of_block!(_x, pass(AddFlags(1))); + end_of_block!(ref _x, AddFlags(1)); + end_of_block!(AddFlags { bits: ref _x }, AddFlags(1)); + end_of_block!(&AddFlags { bits }, &AddFlags(1)); + end_of_block!((_, ref _y), (AddFlags(1), 22)); + end_of_block!(box ref _x, std::boxed::Box::new(AddFlags(1))); + end_of_block!(box _x, std::boxed::Box::new(AddFlags(1))); + end_of_block!(_, { { check_flags(0); &AddFlags(1) } }); + end_of_block!(_, &((Box { f: AddFlags(1) }).f)); + end_of_block!(_, &(([AddFlags(1)])[0])); + + // LHS does not create a ref binding, so temporary lives as long + // as statement, and we do not move the AddFlags out: + end_of_stmt!(_, AddFlags(1)); + end_of_stmt!((_, _), (AddFlags(1), 22)); + + // `&` operator appears inside an arg to a function, + // so it is not prolonged: + end_of_stmt!(ref _x, arg(0, &AddFlags(1))); + + // autoref occurs inside receiver, so temp lifetime is not + // prolonged: + end_of_stmt!(ref _x, AddFlags(1).check_flags(0).bits()); + + // No reference is created on LHS, thus RHS is moved into + // a temporary that lives just as long as the statement. + end_of_stmt!(AddFlags { bits }, AddFlags(1)); +} diff --git a/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs b/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs new file mode 100644 index 000000000..6cd3781b7 --- /dev/null +++ b/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -0,0 +1,47 @@ +// run-pass +// needs-unwind + +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_variables)] +// Test cleanup of rvalue temporary that occurs while `box` construction +// is in progress. This scenario revealed a rather terrible bug. The +// ingredients are: +// +// 1. Partial cleanup of `box` is in scope, +// 2. cleanup of return value from `get_bar()` is in scope, +// 3. do_it() panics. +// +// This led to a bug because `the top-most frame that was to be +// cleaned (which happens to be the partial cleanup of `box`) required +// multiple basic blocks, which led to us dropping part of the cleanup +// from the top-most frame. +// +// It's unclear how likely such a bug is to recur, but it seems like a +// scenario worth testing. + +// ignore-emscripten no threads support + +use std::thread; + +enum Conzabble { + Bickwick(Foo) +} + +struct Foo { field: Box } + +fn do_it(x: &[usize]) -> Foo { + panic!() +} + +fn get_bar(x: usize) -> Vec { vec![x * 2] } + +pub fn fails() { + let x = 2; + let mut y: Vec> = Vec::new(); + y.push(Box::new(Conzabble::Bickwick(do_it(&get_bar(x))))); +} + +pub fn main() { + thread::spawn(fails).join(); +} diff --git a/tests/ui/cleanup-shortcircuit.rs b/tests/ui/cleanup-shortcircuit.rs new file mode 100644 index 000000000..fe867ce1f --- /dev/null +++ b/tests/ui/cleanup-shortcircuit.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that cleanups for the RHS of shortcircuiting operators work. + +// pretty-expanded FIXME #23616 + +#![allow(deref_nullptr)] + + +use std::env; + +pub fn main() { + let args: Vec = env::args().collect(); + + // Here, the rvalue `"signal".to_string()` requires cleanup. Older versions + // of the code had a problem that the cleanup scope for this + // expression was the end of the `if`, and as the `"signal".to_string()` + // expression was never evaluated, we wound up trying to clean + // uninitialized memory. + + if args.len() >= 2 && args[1] == "signal" { + // Raise a segfault. + unsafe { *std::ptr::null_mut::() = 0; } + } +} diff --git a/tests/ui/close-over-big-then-small-data.rs b/tests/ui/close-over-big-then-small-data.rs new file mode 100644 index 000000000..429b21e8b --- /dev/null +++ b/tests/ui/close-over-big-then-small-data.rs @@ -0,0 +1,39 @@ +// run-pass + +#![allow(dead_code)] +// If we use GEPi rather than GEP_tup_like when +// storing closure data (as we used to do), the u64 would +// overwrite the u16. + +struct Pair { + a: A, b: B +} + +struct Invoker { + a: A, + b: u16, +} + +trait Invokable { + fn f(&self) -> (A, u16); +} + +impl Invokable for Invoker { + fn f(&self) -> (A, u16) { + (self.a.clone(), self.b) + } +} + +fn f(a: A, b: u16) -> Box+'static> { + Box::new(Invoker { + a: a, + b: b, + }) as Box+'static> +} + +pub fn main() { + let (a, b) = f(22_u64, 44u16).f(); + println!("a={} b={}", a, b); + assert_eq!(a, 22u64); + assert_eq!(b, 44u16); +} diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs b/tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs new file mode 100644 index 000000000..5f02e642d --- /dev/null +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs @@ -0,0 +1,38 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(warnings)] + +type Different<'a, 'b> = &'a mut (&'a (), &'b ()); +type Same<'a> = Different<'a, 'a>; + +fn with_closure_expecting_different(_: F) + where F: for<'a, 'b> FnOnce(Different<'a, 'b>) +{ +} + +fn with_closure_expecting_different_anon(_: F) + where F: FnOnce(Different<'_, '_>) +{ +} + +fn supplying_nothing_expecting_anon() { + with_closure_expecting_different_anon(|x: Different| { + }) +} + +fn supplying_nothing_expecting_named() { + with_closure_expecting_different(|x: Different| { + }) +} + +fn supplying_underscore_expecting_anon() { + with_closure_expecting_different_anon(|x: Different<'_, '_>| { + }) +} + +fn supplying_underscore_expecting_named() { + with_closure_expecting_different(|x: Different<'_, '_>| { + }) +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.rs b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs new file mode 100644 index 000000000..7f1c14027 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -0,0 +1,60 @@ +fn with_closure_expecting_fn_with_free_region(_: F) +where + F: for<'a> FnOnce(fn(&'a u32), &i32), +{ +} + +fn with_closure_expecting_fn_with_bound_region(_: F) +where + F: FnOnce(fn(&u32), &i32), +{ +} + +fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + // Here, the type given for `'x` "obscures" a region from the + // expected signature that is bound at closure level. + with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn expect_free_supply_free_from_closure() { + // A variant on the previous test. Here, the region `'a` will be + // bound at the closure level, just as is expected, so no error + // results. + type Foo<'a> = fn(&'a u32); + with_closure_expecting_fn_with_free_region(|_x: Foo<'_>, y| {}); +} + +fn expect_free_supply_bound() { + // Here, we are given a function whose region is bound at closure level, + // but we expect one bound in the argument. Error results. + with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + //~^ ERROR mismatched types +} + +fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { + // Here, we are given a `fn(&u32)` but we expect a `fn(&'x + // u32)`. In principle, this could be ok, but we demand equality. + with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + //~^ ERROR mismatched types +} + +fn expect_bound_supply_free_from_closure() { + // A variant on the previous test. Here, the region `'a` will be + // bound at the closure level, but we expect something bound at + // the argument level. + type Foo<'a> = fn(&'a u32); + with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + //~^ ERROR mismatched types + }); +} + +fn expect_bound_supply_bound<'x>(x: &'x u32) { + // No error in this case. The supplied type supplies the bound + // regions, and hence we are able to figure out the type of `y` + // from the expected type + with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {}); +} + +fn main() {} diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr new file mode 100644 index 000000000..e6ddc6068 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -0,0 +1,51 @@ +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 + | +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here +... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ + | | + | has type `fn(&'1 u32)` + | requires that `'1` must outlive `'x` + +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 + | +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here +... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ requires that `'x` must outlive `'static` + +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:32:49 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^ one type is more general than the other + | + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'a> fn(&'a u32)` + +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:39:50 + | +LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a> fn(&'a u32)` + found fn pointer `fn(&u32)` + +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:48:50 + | +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a> fn(&'a u32)` + found fn pointer `fn(&u32)` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs new file mode 100644 index 000000000..e5ec6b271 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs @@ -0,0 +1,25 @@ +fn with_closure(_: F) + where F: FnOnce(A, A) +{ +} + +fn a() { + with_closure(|x: u32, y| { + // We deduce type of `y` from `x`. + }); +} + +fn b() { + // Here we take the supplied types, resulting in an error later on. + with_closure(|x: u32, y: i32| { + //~^ ERROR type mismatch in closure arguments + }); +} + +fn c() { + with_closure(|x, y: i32| { + // We deduce type of `x` from `y`. + }); +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr new file mode 100644 index 000000000..8dccf929b --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr @@ -0,0 +1,21 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-infer-var-appearing-twice.rs:14:5 + | +LL | with_closure(|x: u32, y: i32| { + | ^^^^^^^^^^^^ ---------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(_, _) -> _` + found closure signature `fn(u32, i32) -> _` +note: required by a bound in `with_closure` + --> $DIR/expect-infer-var-appearing-twice.rs:2:14 + | +LL | fn with_closure(_: F) + | ------------ required by a bound in this +LL | where F: FnOnce(A, A) + | ^^^^^^^^^^^^ required by this bound in `with_closure` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs new file mode 100644 index 000000000..0ee738c2c --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn with_closure(_: F) + where F: FnOnce(A, &u32) +{ +} + +fn foo() { + // This version works; we infer `A` to be `u32`, and take the type + // of `y` to be `&u32`. + with_closure(|x: u32, y| {}); +} + +fn bar() { + // This version also works. + with_closure(|x: &u32, y| {}); +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs new file mode 100644 index 000000000..15711da4b --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn with_closure(_: F) + where F: FnOnce(A, &u32) +{ +} + +fn foo() { + // This version works; we infer `A` to be `u32`, and take the type + // of `y` to be `&u32`. + with_closure(|x: u32, y| {}); +} + +fn bar<'x>(x: &'x u32) { + // Same. + with_closure(|x: &'x u32, y| {}); +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs new file mode 100644 index 000000000..97d7a51a7 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs @@ -0,0 +1,19 @@ +fn with_closure(_: F) + where F: FnOnce(A, B) +{ +} + +fn a() { + // Type of `y` is unconstrained. + with_closure(|x: u32, y| {}); //~ ERROR E0282 +} + +fn b() { + with_closure(|x: u32, y: u32| {}); // OK +} + +fn c() { + with_closure(|x: u32, y: u32| {}); // OK +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr new file mode 100644 index 000000000..7a04ed738 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27 + | +LL | with_closure(|x: u32, y| {}); + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | with_closure(|x: u32, y: /* Type */| {}); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closure-expected-type/issue-24421.rs b/tests/ui/closure-expected-type/issue-24421.rs new file mode 100644 index 000000000..2e104b599 --- /dev/null +++ b/tests/ui/closure-expected-type/issue-24421.rs @@ -0,0 +1,10 @@ +// check-pass + +fn test(f: F) {} + +fn main() { + test(|x, y | {}); + test(|x:&u64, y:&u64| {}); + test(|x:&u64, y | {}); + test(|x, y:&u64| {}); +} diff --git a/tests/ui/closure_context/issue-26046-fn-mut.rs b/tests/ui/closure_context/issue-26046-fn-mut.rs new file mode 100644 index 000000000..0a015ea14 --- /dev/null +++ b/tests/ui/closure_context/issue-26046-fn-mut.rs @@ -0,0 +1,11 @@ +fn foo() -> Box { + let num = 5; + + let closure = || { //~ ERROR expected a closure that + num += 1; + }; + + Box::new(closure) +} + +fn main() {} diff --git a/tests/ui/closure_context/issue-26046-fn-mut.stderr b/tests/ui/closure_context/issue-26046-fn-mut.stderr new file mode 100644 index 000000000..f744b71c2 --- /dev/null +++ b/tests/ui/closure_context/issue-26046-fn-mut.stderr @@ -0,0 +1,16 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/issue-26046-fn-mut.rs:4:19 + | +LL | let closure = || { + | ^^ this closure implements `FnMut`, not `Fn` +LL | num += 1; + | --- closure is `FnMut` because it mutates the variable `num` here +... +LL | Box::new(closure) + | ----------------- the requirement to implement `Fn` derives from here + | + = note: required for the cast from `[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]` to the object type `dyn Fn()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closure_context/issue-26046-fn-once.rs b/tests/ui/closure_context/issue-26046-fn-once.rs new file mode 100644 index 000000000..511690e9d --- /dev/null +++ b/tests/ui/closure_context/issue-26046-fn-once.rs @@ -0,0 +1,11 @@ +fn get_closure() -> Box Vec> { + let vec = vec![1u8, 2u8]; + + let closure = move || { //~ ERROR expected a closure + vec + }; + + Box::new(closure) +} + +fn main() {} diff --git a/tests/ui/closure_context/issue-26046-fn-once.stderr b/tests/ui/closure_context/issue-26046-fn-once.stderr new file mode 100644 index 000000000..34f94f9dc --- /dev/null +++ b/tests/ui/closure_context/issue-26046-fn-once.stderr @@ -0,0 +1,16 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/issue-26046-fn-once.rs:4:19 + | +LL | let closure = move || { + | ^^^^^^^ this closure implements `FnOnce`, not `Fn` +LL | vec + | --- closure is `FnOnce` because it moves the variable `vec` out of its environment +... +LL | Box::new(closure) + | ----------------- the requirement to implement `Fn` derives from here + | + = note: required for the cast from `[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]` to the object type `dyn Fn() -> Vec` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closure_context/issue-42065.rs b/tests/ui/closure_context/issue-42065.rs new file mode 100644 index 000000000..c506600f4 --- /dev/null +++ b/tests/ui/closure_context/issue-42065.rs @@ -0,0 +1,13 @@ +use std::collections::HashMap; + +fn main() { + let dict: HashMap = HashMap::new(); + let debug_dump_dict = || { + for (key, value) in dict { + println!("{:?} - {:?}", key, value); + } + }; + debug_dump_dict(); + debug_dump_dict(); + //~^ ERROR use of moved value: `debug_dump_dict` +} diff --git a/tests/ui/closure_context/issue-42065.stderr b/tests/ui/closure_context/issue-42065.stderr new file mode 100644 index 000000000..896bb6dc6 --- /dev/null +++ b/tests/ui/closure_context/issue-42065.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `debug_dump_dict` + --> $DIR/issue-42065.rs:11:5 + | +LL | debug_dump_dict(); + | ----------------- `debug_dump_dict` moved due to this call +LL | debug_dump_dict(); + | ^^^^^^^^^^^^^^^ value used here after move + | +note: closure cannot be invoked more than once because it moves the variable `dict` out of its environment + --> $DIR/issue-42065.rs:6:29 + | +LL | for (key, value) in dict { + | ^^^^ +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/issue-42065.rs:10:5 + | +LL | debug_dump_dict(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs new file mode 100644 index 000000000..2bcbd792e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs @@ -0,0 +1,22 @@ +// edition:2021 +#![feature(rustc_attrs)] + +// Ensure that capture analysis results in arrays being completely captured. +fn main() { + let mut m = [1, 2, 3, 4, 5]; + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + m[0] += 10; + //~^ NOTE: Capturing m[] -> MutBorrow + //~| NOTE: Min Capture m[] -> MutBorrow + m[1] += 40; + //~^ NOTE: Capturing m[] -> MutBorrow + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr new file mode 100644 index 000000000..129b26456 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr @@ -0,0 +1,53 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/arrays-completely-captured.rs:8:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/arrays-completely-captured.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | m[0] += 10; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing m[] -> MutBorrow + --> $DIR/arrays-completely-captured.rs:14:9 + | +LL | m[0] += 10; + | ^ +note: Capturing m[] -> MutBorrow + --> $DIR/arrays-completely-captured.rs:17:9 + | +LL | m[1] += 40; + | ^ + +error: Min Capture analysis includes: + --> $DIR/arrays-completely-captured.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | m[0] += 10; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture m[] -> MutBorrow + --> $DIR/arrays-completely-captured.rs:14:9 + | +LL | m[0] += 10; + | ^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/by_value.rs b/tests/ui/closures/2229_closure_analysis/by_value.rs new file mode 100644 index 000000000..d8d3bbee2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/by_value.rs @@ -0,0 +1,37 @@ +// edition:2021 + +// Test that we handle derferences properly when only some of the captures are being moved with +// `capture_disjoint_fields` enabled. +#![feature(rustc_attrs)] + +#[derive(Debug, Default)] +struct SomeLargeType; +struct MuchLargerType([SomeLargeType; 32]); + +// Ensure that we don't capture any derefs when moving captures into the closures, +// i.e. only data from the enclosing stack is moved. +fn big_box() { + let s = MuchLargerType(Default::default()); + let b = Box::new(s); + let t = (b, 10); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let p = t.0.0; + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue + //~| NOTE: Min Capture t[(0, 0)] -> ByValue + println!("{} {:?}", t.1, p); + //~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow + }; + + c(); +} + +fn main() { + big_box(); +} diff --git a/tests/ui/closures/2229_closure_analysis/by_value.stderr b/tests/ui/closures/2229_closure_analysis/by_value.stderr new file mode 100644 index 000000000..097462253 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/by_value.stderr @@ -0,0 +1,58 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/by_value.rs:18:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/by_value.rs:21:5 + | +LL | / || { +LL | | +LL | | +LL | | let p = t.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue + --> $DIR/by_value.rs:24:17 + | +LL | let p = t.0.0; + | ^^^^^ +note: Capturing t[(1, 0)] -> ImmBorrow + --> $DIR/by_value.rs:27:29 + | +LL | println!("{} {:?}", t.1, p); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/by_value.rs:21:5 + | +LL | / || { +LL | | +LL | | +LL | | let p = t.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ByValue + --> $DIR/by_value.rs:24:17 + | +LL | let p = t.0.0; + | ^^^^^ +note: Min Capture t[(1, 0)] -> ImmBorrow + --> $DIR/by_value.rs:27:29 + | +LL | println!("{} {:?}", t.1, p); + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs new file mode 100644 index 000000000..dc53b3176 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -0,0 +1,33 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let p = Point { x: 10, y: 10 }; + let q = Point { x: 10, y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ImmBorrow + println!("{:?}", p.x); + //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + + println!("{:?}", q.x); + //~^ NOTE: Capturing q[(0, 0)] -> ImmBorrow + println!("{:?}", q); + //~^ NOTE: Capturing q[] -> ImmBorrow + //~| NOTE: Min Capture q[] -> ImmBorrow + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr new file mode 100644 index 000000000..fceafb9c8 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -0,0 +1,68 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-1.rs:15:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-analysis-1.rs:18:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", p); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:21:26 + | +LL | println!("{:?}", p); + | ^ +note: Capturing p[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:24:26 + | +LL | println!("{:?}", p.x); + | ^^^ +note: Capturing q[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:27:26 + | +LL | println!("{:?}", q.x); + | ^^^ +note: Capturing q[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:29:26 + | +LL | println!("{:?}", q); + | ^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-1.rs:18:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", p); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:21:26 + | +LL | println!("{:?}", p); + | ^ +note: Min Capture q[] -> ImmBorrow + --> $DIR/capture-analysis-1.rs:29:26 + | +LL | println!("{:?}", q); + | ^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs new file mode 100644 index 000000000..99d12f8d8 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -0,0 +1,28 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Point { + x: String, + y: i32, +} + +fn main() { + let mut p = Point { x: String::new(), y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = p.x; + //~^ NOTE: Capturing p[(0, 0)] -> ByValue + //~| NOTE: p[] captured as ByValue here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ByValue + //~| NOTE: p[] used here + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr new file mode 100644 index 000000000..cb44ca266 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -0,0 +1,56 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-2.rs:14:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-analysis-2.rs:17:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> ByValue + --> $DIR/capture-analysis-2.rs:20:18 + | +LL | let _x = p.x; + | ^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/capture-analysis-2.rs:23:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-2.rs:17:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ByValue + --> $DIR/capture-analysis-2.rs:20:18 + | +LL | let _x = p.x; + | ^^^ p[] captured as ByValue here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs new file mode 100644 index 000000000..3f337097d --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -0,0 +1,33 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Child { + c: String, + d: String, +} + +#[derive(Debug)] +struct Parent { + b: Child, +} + +fn main() { + let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = a.b.c; + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue + //~| NOTE: a[(0, 0)] captured as ByValue here + println!("{:?}", a.b); + //~^ NOTE: Capturing a[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture a[(0, 0)] -> ByValue + //~| NOTE: a[(0, 0)] used here + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr new file mode 100644 index 000000000..71e7bdc35 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -0,0 +1,56 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-3.rs:19:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-analysis-3.rs:22:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b.c; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0),(0, 0)] -> ByValue + --> $DIR/capture-analysis-3.rs:25:18 + | +LL | let _x = a.b.c; + | ^^^^^ +note: Capturing a[(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-3.rs:28:26 + | +LL | println!("{:?}", a.b); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-3.rs:22:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b.c; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-3.rs:25:18 + | +LL | let _x = a.b.c; + | ^^^^^ a[(0, 0)] captured as ByValue here +... +LL | println!("{:?}", a.b); + | ^^^ a[(0, 0)] used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs new file mode 100644 index 000000000..bc46ec997 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -0,0 +1,31 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct Child { + c: String, + d: String, +} + +#[derive(Debug)] +struct Parent { + b: Child, +} + +fn main() { + let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let _x = a.b; + //~^ NOTE: Capturing a[(0, 0)] -> ByValue + //~| NOTE: Min Capture a[(0, 0)] -> ByValue + println!("{:?}", a.b.c); + //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr new file mode 100644 index 000000000..7e6e625bc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -0,0 +1,53 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-analysis-4.rs:19:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-analysis-4.rs:22:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-4.rs:25:18 + | +LL | let _x = a.b; + | ^^^ +note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/capture-analysis-4.rs:28:26 + | +LL | println!("{:?}", a.b.c); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-analysis-4.rs:22:5 + | +LL | / || { +LL | | +LL | | +LL | | let _x = a.b; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ByValue + --> $DIR/capture-analysis-4.rs:25:18 + | +LL | let _x = a.b; + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs new file mode 100644 index 000000000..6fd151553 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs @@ -0,0 +1,29 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 10 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + println!("{}", p.x); + //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow + }; + + // `c` should only capture `p.x`, therefore mutating `p.y` is allowed. + let py = &mut p.y; + + c(); + *py = 20; +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr new file mode 100644 index 000000000..0f64ecf3a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-disjoint-field-struct.rs:13:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-disjoint-field-struct.rs:16:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", p.x); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> ImmBorrow + --> $DIR/capture-disjoint-field-struct.rs:19:24 + | +LL | println!("{}", p.x); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-disjoint-field-struct.rs:16:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", p.x); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[(0, 0)] -> ImmBorrow + --> $DIR/capture-disjoint-field-struct.rs:19:24 + | +LL | println!("{}", p.x); + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs new file mode 100644 index 000000000..8d3bb3262 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs @@ -0,0 +1,24 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +fn main() { + let mut t = (10, 10); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + println!("{}", t.0); + //~^ NOTE: Capturing t[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow + }; + + // `c` only captures t.0, therefore mutating t.1 is allowed. + let t1 = &mut t.1; + + c(); + *t1 = 20; +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr new file mode 100644 index 000000000..a8ca9622a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-disjoint-field-tuple.rs:8:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-disjoint-field-tuple.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", t.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0)] -> ImmBorrow + --> $DIR/capture-disjoint-field-tuple.rs:14:24 + | +LL | println!("{}", t.0); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-disjoint-field-tuple.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", t.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ImmBorrow + --> $DIR/capture-disjoint-field-tuple.rs:14:24 + | +LL | println!("{}", t.0); + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-enum-field.rs b/tests/ui/closures/2229_closure_analysis/capture-enum-field.rs new file mode 100644 index 000000000..bbe3aa31a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-enum-field.rs @@ -0,0 +1,27 @@ +// edition:2021 +// run-pass + +#[derive(Debug, PartialEq, Eq)] +pub enum Color { + RGB(u8, u8, u8), +} + +fn main() { + let mut color = Color::RGB(0, 0, 0); + let mut red = |v| { + let Color::RGB(ref mut r, _, _) = color; + *r = v; + }; + let mut green = |v| { + let Color::RGB(_, ref mut g, _) = color; + *g = v; + }; + let mut blue = |v| { + let Color::RGB(_, _, ref mut b) = color; + *b = v; + }; + red(1); + green(2); + blue(3); + assert_eq!(Color::RGB(1, 2, 3), color); +} diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.rs b/tests/ui/closures/2229_closure_analysis/capture-enums.rs new file mode 100644 index 000000000..322ae99b8 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.rs @@ -0,0 +1,62 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +enum Info { + Point(i32, i32, String), + Meta(String, Vec<(i32, i32)>) +} + +fn multi_variant_enum() { + let point = Info::Point(10, -10, "1".into()); + + let vec = Vec::new(); + let meta = Info::Meta("meta".into(), vec); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + if let Info::Point(_, _, str) = point { + //~^ NOTE: Capturing point[] -> ImmBorrow + //~| NOTE: Capturing point[(2, 0)] -> ByValue + //~| NOTE: Min Capture point[] -> ByValue + println!("{}", str); + } + + if let Info::Meta(_, v) = meta { + //~^ NOTE: Capturing meta[] -> ImmBorrow + //~| NOTE: Capturing meta[(1, 1)] -> ByValue + //~| NOTE: Min Capture meta[] -> ByValue + println!("{:?}", v); + } + }; + + c(); +} + +enum SingleVariant { + Point(i32, i32, String), +} + +fn single_variant_enum() { + let point = SingleVariant::Point(10, -10, "1".into()); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + let SingleVariant::Point(_, _, str) = point; + //~^ NOTE: Capturing point[(2, 0)] -> ByValue + //~| NOTE: Min Capture point[(2, 0)] -> ByValue + println!("{}", str); + }; + + c(); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr new file mode 100644 index 000000000..8a6ba8444 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr @@ -0,0 +1,113 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-enums.rs:16:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/capture-enums.rs:47:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/capture-enums.rs:19:5 + | +LL | / || { +LL | | +LL | | +LL | | if let Info::Point(_, _, str) = point { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing point[] -> ImmBorrow + --> $DIR/capture-enums.rs:22:41 + | +LL | if let Info::Point(_, _, str) = point { + | ^^^^^ +note: Capturing point[(2, 0)] -> ByValue + --> $DIR/capture-enums.rs:22:41 + | +LL | if let Info::Point(_, _, str) = point { + | ^^^^^ +note: Capturing meta[] -> ImmBorrow + --> $DIR/capture-enums.rs:29:35 + | +LL | if let Info::Meta(_, v) = meta { + | ^^^^ +note: Capturing meta[(1, 1)] -> ByValue + --> $DIR/capture-enums.rs:29:35 + | +LL | if let Info::Meta(_, v) = meta { + | ^^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-enums.rs:19:5 + | +LL | / || { +LL | | +LL | | +LL | | if let Info::Point(_, _, str) = point { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture point[] -> ByValue + --> $DIR/capture-enums.rs:22:41 + | +LL | if let Info::Point(_, _, str) = point { + | ^^^^^ +note: Min Capture meta[] -> ByValue + --> $DIR/capture-enums.rs:29:35 + | +LL | if let Info::Meta(_, v) = meta { + | ^^^^ + +error: First Pass analysis includes: + --> $DIR/capture-enums.rs:50:5 + | +LL | / || { +LL | | +LL | | +LL | | let SingleVariant::Point(_, _, str) = point; +... | +LL | | println!("{}", str); +LL | | }; + | |_____^ + | +note: Capturing point[(2, 0)] -> ByValue + --> $DIR/capture-enums.rs:53:47 + | +LL | let SingleVariant::Point(_, _, str) = point; + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/capture-enums.rs:50:5 + | +LL | / || { +LL | | +LL | | +LL | | let SingleVariant::Point(_, _, str) = point; +... | +LL | | println!("{}", str); +LL | | }; + | |_____^ + | +note: Min Capture point[(2, 0)] -> ByValue + --> $DIR/capture-enums.rs:53:47 + | +LL | let SingleVariant::Point(_, _, str) = point; + | ^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs new file mode 100644 index 000000000..3341166e2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -0,0 +1,50 @@ +// edition:2021 + +#![feature(rustc_attrs)] +#![allow(unused)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +#[derive(Debug)] +struct Line { + p: Point, + q: Point +} +#[derive(Debug)] +struct Plane { + a: Line, + b: Line, +} + +fn main() { + let mut p = Plane { + a: Line { + p: Point { x: 1,y: 2 }, + q: Point { x: 3,y: 4 }, + }, + b: Line { + p: Point { x: 1,y: 2 }, + q: Point { x: 3,y: 4 }, + } + }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = &p.a.p.x; + //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + p.b.q.y = 9; + //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow + //~| NOTE: p[] captured as MutBorrow here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] used here + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr new file mode 100644 index 000000000..29e1af043 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -0,0 +1,61 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/deep-multilevel-struct.rs:34:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/deep-multilevel-struct.rs:37:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &p.a.p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/deep-multilevel-struct.rs:40:18 + | +LL | let x = &p.a.p.x; + | ^^^^^^^ +note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow + --> $DIR/deep-multilevel-struct.rs:42:9 + | +LL | p.b.q.y = 9; + | ^^^^^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/deep-multilevel-struct.rs:45:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/deep-multilevel-struct.rs:37:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &p.a.p.x; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> MutBorrow + --> $DIR/deep-multilevel-struct.rs:42:9 + | +LL | p.b.q.y = 9; + | ^^^^^^^ p[] captured as MutBorrow here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs new file mode 100644 index 000000000..34b0132f3 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -0,0 +1,24 @@ +// edition:2021 +#![feature(rustc_attrs)] +#![allow(unused)] + +fn main() { + let mut t = (((1,2),(3,4)),((5,6),(7,8))); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = &t.0.0.0; + //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + t.1.1.1 = 9; + //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow + //~| NOTE: t[] captured as MutBorrow here + println!("{:?}", t); + //~^ NOTE: Min Capture t[] -> MutBorrow + //~| NOTE: Capturing t[] -> ImmBorrow + //~| NOTE: t[] used here + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr new file mode 100644 index 000000000..e91751676 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -0,0 +1,61 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/deep-multilevel-tuple.rs:8:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/deep-multilevel-tuple.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &t.0.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/deep-multilevel-tuple.rs:14:18 + | +LL | let x = &t.0.0.0; + | ^^^^^^^ +note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow + --> $DIR/deep-multilevel-tuple.rs:16:9 + | +LL | t.1.1.1 = 9; + | ^^^^^^^ +note: Capturing t[] -> ImmBorrow + --> $DIR/deep-multilevel-tuple.rs:19:26 + | +LL | println!("{:?}", t); + | ^ + +error: Min Capture analysis includes: + --> $DIR/deep-multilevel-tuple.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = &t.0.0.0; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[] -> MutBorrow + --> $DIR/deep-multilevel-tuple.rs:16:9 + | +LL | t.1.1.1 = 9; + | ^^^^^^^ t[] captured as MutBorrow here +... +LL | println!("{:?}", t); + | ^ t[] used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs new file mode 100644 index 000000000..6c65a7bf8 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs @@ -0,0 +1,77 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +// Test to ensure Index projections are handled properly during capture analysis +// The array should be moved in entirety, even though only some elements are used. +fn arrays() { + let arr: [String; 5] = [format!("A"), format!("B"), format!("C"), format!("D"), format!("E")]; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let [a, b, .., e] = arr; + //~^ NOTE: Capturing arr[Index] -> ByValue + //~| NOTE: Capturing arr[Index] -> ByValue + //~| NOTE: Capturing arr[Index] -> ByValue + //~| NOTE: Min Capture arr[] -> ByValue + assert_eq!(a, "A"); + assert_eq!(b, "B"); + assert_eq!(e, "E"); + }; + + c(); +} + +struct Point { + x: i32, + y: i32, + id: String, +} + +fn structs() { + let mut p = Point { x: 10, y: 10, id: String::new() }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let Point { x: ref mut x, y: _, id: moved_id } = p; + //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow + //~| NOTE: Capturing p[(2, 0)] -> ByValue + //~| NOTE: Min Capture p[(0, 0)] -> MutBorrow + //~| NOTE: Min Capture p[(2, 0)] -> ByValue + + println!("{}, {}", x, moved_id); + }; + c(); +} + +fn tuples() { + let mut t = (10, String::new(), (String::new(), 42)); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let (ref mut x, ref ref_str, (moved_s, _)) = t; + //~^ NOTE: Capturing t[(0, 0)] -> MutBorrow + //~| NOTE: Capturing t[(1, 0)] -> ImmBorrow + //~| NOTE: Capturing t[(2, 0),(0, 0)] -> ByValue + //~| NOTE: Min Capture t[(0, 0)] -> MutBorrow + //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(2, 0),(0, 0)] -> ByValue + + println!("{}, {} {}", x, ref_str, moved_s); + }; + c(); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr new file mode 100644 index 000000000..44fbe6d81 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr @@ -0,0 +1,178 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/destructure_patterns.rs:10:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/destructure_patterns.rs:38:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/destructure_patterns.rs:58:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/destructure_patterns.rs:13:5 + | +LL | / || { +LL | | +LL | | +LL | | let [a, b, .., e] = arr; +... | +LL | | assert_eq!(e, "E"); +LL | | }; + | |_____^ + | +note: Capturing arr[Index] -> ByValue + --> $DIR/destructure_patterns.rs:16:29 + | +LL | let [a, b, .., e] = arr; + | ^^^ +note: Capturing arr[Index] -> ByValue + --> $DIR/destructure_patterns.rs:16:29 + | +LL | let [a, b, .., e] = arr; + | ^^^ +note: Capturing arr[Index] -> ByValue + --> $DIR/destructure_patterns.rs:16:29 + | +LL | let [a, b, .., e] = arr; + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/destructure_patterns.rs:13:5 + | +LL | / || { +LL | | +LL | | +LL | | let [a, b, .., e] = arr; +... | +LL | | assert_eq!(e, "E"); +LL | | }; + | |_____^ + | +note: Min Capture arr[] -> ByValue + --> $DIR/destructure_patterns.rs:16:29 + | +LL | let [a, b, .., e] = arr; + | ^^^ + +error: First Pass analysis includes: + --> $DIR/destructure_patterns.rs:41:5 + | +LL | / || { +LL | | +LL | | +LL | | let Point { x: ref mut x, y: _, id: moved_id } = p; +... | +LL | | println!("{}, {}", x, moved_id); +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> MutBorrow + --> $DIR/destructure_patterns.rs:44:58 + | +LL | let Point { x: ref mut x, y: _, id: moved_id } = p; + | ^ +note: Capturing p[(2, 0)] -> ByValue + --> $DIR/destructure_patterns.rs:44:58 + | +LL | let Point { x: ref mut x, y: _, id: moved_id } = p; + | ^ + +error: Min Capture analysis includes: + --> $DIR/destructure_patterns.rs:41:5 + | +LL | / || { +LL | | +LL | | +LL | | let Point { x: ref mut x, y: _, id: moved_id } = p; +... | +LL | | println!("{}, {}", x, moved_id); +LL | | }; + | |_____^ + | +note: Min Capture p[(0, 0)] -> MutBorrow + --> $DIR/destructure_patterns.rs:44:58 + | +LL | let Point { x: ref mut x, y: _, id: moved_id } = p; + | ^ +note: Min Capture p[(2, 0)] -> ByValue + --> $DIR/destructure_patterns.rs:44:58 + | +LL | let Point { x: ref mut x, y: _, id: moved_id } = p; + | ^ + +error: First Pass analysis includes: + --> $DIR/destructure_patterns.rs:61:5 + | +LL | / || { +LL | | +LL | | +LL | | let (ref mut x, ref ref_str, (moved_s, _)) = t; +... | +LL | | println!("{}, {} {}", x, ref_str, moved_s); +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0)] -> MutBorrow + --> $DIR/destructure_patterns.rs:64:54 + | +LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; + | ^ +note: Capturing t[(1, 0)] -> ImmBorrow + --> $DIR/destructure_patterns.rs:64:54 + | +LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; + | ^ +note: Capturing t[(2, 0),(0, 0)] -> ByValue + --> $DIR/destructure_patterns.rs:64:54 + | +LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; + | ^ + +error: Min Capture analysis includes: + --> $DIR/destructure_patterns.rs:61:5 + | +LL | / || { +LL | | +LL | | +LL | | let (ref mut x, ref ref_str, (moved_s, _)) = t; +... | +LL | | println!("{}, {} {}", x, ref_str, moved_s); +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> MutBorrow + --> $DIR/destructure_patterns.rs:64:54 + | +LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; + | ^ +note: Min Capture t[(1, 0)] -> ImmBorrow + --> $DIR/destructure_patterns.rs:64:54 + | +LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; + | ^ +note: Min Capture t[(2, 0),(0, 0)] -> ByValue + --> $DIR/destructure_patterns.rs:64:54 + | +LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; + | ^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs new file mode 100644 index 000000000..f97e60daf --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.rs @@ -0,0 +1,85 @@ +// edition:2021 + +// Test that arrays are completely captured by closures by relying on the borrow check diagnostics + +fn arrays_1() { + let mut arr = [1, 2, 3, 4, 5]; + + let mut c = || { + arr[0] += 10; + }; + + // c will capture `arr` completely, therefore another index into the + // array can't be modified here + arr[1] += 10; + //~^ ERROR: cannot use `arr` because it was mutably borrowed + //~| ERROR: cannot use `arr[_]` because it was mutably borrowed + c(); +} + +fn arrays_2() { + let mut arr = [1, 2, 3, 4, 5]; + + let c = || { + println!("{:#?}", &arr[3..4]); + }; + + // c will capture `arr` completely, therefore another index into the + // array can't be modified here + arr[1] += 10; + //~^ ERROR: cannot assign to `arr[_]` because it is borrowed + c(); +} + +fn arrays_3() { + let mut arr = [1, 2, 3, 4, 5]; + + let c = || { + println!("{}", arr[3]); + }; + + // c will capture `arr` completely, therefore another index into the + // array can't be modified here + arr[1] += 10; + //~^ ERROR: cannot assign to `arr[_]` because it is borrowed + c(); +} + +fn arrays_4() { + let mut arr = [1, 2, 3, 4, 5]; + + let mut c = || { + arr[1] += 10; + }; + + // c will capture `arr` completely, therefore we cannot borrow another index + // into the array. + println!("{}", arr[3]); + //~^ ERROR: cannot use `arr` because it was mutably borrowed + //~| ERROR: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable + + c(); +} + +fn arrays_5() { + let mut arr = [1, 2, 3, 4, 5]; + + let mut c = || { + arr[1] += 10; + }; + + // c will capture `arr` completely, therefore we cannot borrow other indices + // into the array. + println!("{:#?}", &arr[3..2]); + //~^ ERROR: cannot borrow `arr` as immutable because it is also borrowed as mutable + + c(); +} + +fn main() { + arrays_1(); + arrays_2(); + arrays_3(); + arrays_4(); + arrays_5(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr new file mode 100644 index 000000000..4f41060dc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr @@ -0,0 +1,104 @@ +error[E0503]: cannot use `arr` because it was mutably borrowed + --> $DIR/arrays.rs:14:5 + | +LL | let mut c = || { + | -- borrow of `arr` occurs here +LL | arr[0] += 10; + | --- borrow occurs due to use of `arr` in closure +... +LL | arr[1] += 10; + | ^^^^^^ use of borrowed `arr` +... +LL | c(); + | - borrow later used here + +error[E0503]: cannot use `arr[_]` because it was mutably borrowed + --> $DIR/arrays.rs:14:5 + | +LL | let mut c = || { + | -- borrow of `arr` occurs here +LL | arr[0] += 10; + | --- borrow occurs due to use of `arr` in closure +... +LL | arr[1] += 10; + | ^^^^^^^^^^^^ use of borrowed `arr` +... +LL | c(); + | - borrow later used here + +error[E0506]: cannot assign to `arr[_]` because it is borrowed + --> $DIR/arrays.rs:29:5 + | +LL | let c = || { + | -- borrow of `arr[_]` occurs here +LL | println!("{:#?}", &arr[3..4]); + | --- borrow occurs due to use in closure +... +LL | arr[1] += 10; + | ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here +LL | +LL | c(); + | - borrow later used here + +error[E0506]: cannot assign to `arr[_]` because it is borrowed + --> $DIR/arrays.rs:43:5 + | +LL | let c = || { + | -- borrow of `arr[_]` occurs here +LL | println!("{}", arr[3]); + | --- borrow occurs due to use in closure +... +LL | arr[1] += 10; + | ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here +LL | +LL | c(); + | - borrow later used here + +error[E0503]: cannot use `arr` because it was mutably borrowed + --> $DIR/arrays.rs:57:20 + | +LL | let mut c = || { + | -- borrow of `arr` occurs here +LL | arr[1] += 10; + | --- borrow occurs due to use of `arr` in closure +... +LL | println!("{}", arr[3]); + | ^^^^^^ use of borrowed `arr` +... +LL | c(); + | - borrow later used here + +error[E0502]: cannot borrow `arr[_]` as immutable because it is also borrowed as mutable + --> $DIR/arrays.rs:57:20 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | arr[1] += 10; + | --- first borrow occurs due to use of `arr` in closure +... +LL | println!("{}", arr[3]); + | ^^^^^^ immutable borrow occurs here +... +LL | c(); + | - mutable borrow later used here + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0502]: cannot borrow `arr` as immutable because it is also borrowed as mutable + --> $DIR/arrays.rs:73:24 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | arr[1] += 10; + | --- first borrow occurs due to use of `arr` in closure +... +LL | println!("{:#?}", &arr[3..2]); + | ^^^ immutable borrow occurs here +... +LL | c(); + | - mutable borrow later used here + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0502, E0503, E0506. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs new file mode 100644 index 000000000..3664d76c2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs @@ -0,0 +1,19 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn main() { + let mut p = Point {x: 1, y: 2 }; + + let y = &mut p.y; + let mut c = || { + //~^ ERROR cannot borrow `p` as mutable more than once at a time + let x = &mut p.x; + println!("{:?}", p); + }; + c(); + *y+=1; +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr new file mode 100644 index 000000000..341d2bc65 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr @@ -0,0 +1,19 @@ +error[E0499]: cannot borrow `p` as mutable more than once at a time + --> $DIR/borrowck-1.rs:12:17 + | +LL | let y = &mut p.y; + | -------- first mutable borrow occurs here +LL | let mut c = || { + | ^^ second mutable borrow occurs here +LL | +LL | let x = &mut p.x; + | --- capture is mutable because of use here +LL | println!("{:?}", p); + | - second borrow occurs due to use of `p` in closure +... +LL | *y+=1; + | ----- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs new file mode 100644 index 000000000..ae416bab6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs @@ -0,0 +1,19 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn main() { + let mut p = Point {x: 1, y: 2 }; + + let y = &p.y; + let mut c = || { + //~^ ERROR cannot borrow `p` as mutable because it is also borrowed as immutable + println!("{:?}", p); + let x = &mut p.x; + }; + c(); + println!("{}", y); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr new file mode 100644 index 000000000..584bb862b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr @@ -0,0 +1,19 @@ +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-2.rs:12:17 + | +LL | let y = &p.y; + | ---- immutable borrow occurs here +LL | let mut c = || { + | ^^ mutable borrow occurs here +LL | +LL | println!("{:?}", p); + | - second borrow occurs due to use of `p` in closure +LL | let x = &mut p.x; + | --- capture is mutable because of use here +... +LL | println!("{}", y); + | - immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs new file mode 100644 index 000000000..00f50c33e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -0,0 +1,17 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: String, + y: String, +} +fn main() { + let mut c = { + let mut p = Point {x: "1".to_string(), y: "2".to_string() }; + || { //~ ERROR closure may outlive the current block, but it borrows `p` + let x = &mut p.x; + println!("{:?}", p); + } + }; + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr new file mode 100644 index 000000000..ee9238047 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -0,0 +1,22 @@ +error[E0373]: closure may outlive the current block, but it borrows `p`, which is owned by the current block + --> $DIR/borrowck-3.rs:11:9 + | +LL | || { + | ^^ may outlive borrowed value `p` +LL | let x = &mut p.x; +LL | println!("{:?}", p); + | - `p` is borrowed here + | +note: block requires argument type to outlive `'1` + --> $DIR/borrowck-3.rs:9:9 + | +LL | let mut c = { + | ^^^^^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs new file mode 100644 index 000000000..a2290d850 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -0,0 +1,20 @@ +// edition:2021 + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn foo () -> impl FnMut()->() { + let mut p = Point {x: 1, y: 2 }; + let mut c = || { + //~^ ERROR closure may outlive the current function, but it borrows `p` + p.x+=5; + println!("{:?}", p); + }; + c +} +fn main() { + let c = foo(); + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr new file mode 100644 index 000000000..46379a381 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -0,0 +1,22 @@ +error[E0373]: closure may outlive the current function, but it borrows `p`, which is owned by the current function + --> $DIR/borrowck-4.rs:10:17 + | +LL | let mut c = || { + | ^^ may outlive borrowed value `p` +... +LL | println!("{:?}", p); + | - `p` is borrowed here + | +note: closure is returned here + --> $DIR/borrowck-4.rs:15:5 + | +LL | c + | ^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | let mut c = move || { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs new file mode 100644 index 000000000..5ff7b1242 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs @@ -0,0 +1,26 @@ +// edition:2021 + + + +// Tests that two closures cannot simultaneously have mutable +// and immutable access to the variable. Issue #6801. + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn a() { + let mut p = Point {x: 3, y:4}; + let c2 = || p.y * 5; + let c1 = || { + //~^ ERROR cannot borrow `p` as mutable because it is also borrowed as immutable + dbg!(&p); + p.x = 4; + }; + drop(c2); +} + +fn main() { +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr new file mode 100644 index 000000000..5f1dae297 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr @@ -0,0 +1,21 @@ +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 + | +LL | let c2 = || p.y * 5; + | -- --- first borrow occurs due to use of `p.y` in closure + | | + | immutable borrow occurs here +LL | let c1 = || { + | ^^ mutable borrow occurs here +LL | +LL | dbg!(&p); + | - second borrow occurs due to use of `p` in closure +LL | p.x = 4; + | --- capture is mutable because of use here +LL | }; +LL | drop(c2); + | -- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/box.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/box.rs new file mode 100644 index 000000000..a110fa4e2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/box.rs @@ -0,0 +1,64 @@ +// edition:2021 + +// Test borrow checker when we precise capture when using boxes + +struct MetaData { x: String, name: String } +struct Data { m: MetaData } +struct BoxedData(Box); +struct EvenMoreBoxedData(Box); + +// Check diagnostics when the same path is mutated both inside and outside the closure +fn box_1() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let mut c = || { + e.0.0.m.x = format!("not-x"); + }; + + e.0.0.m.x = format!("not-x"); + //~^ ERROR: cannot assign to `e.0.0.m.x` because it is borrowed + c(); +} + +// Check diagnostics when a path is mutated inside a closure while attempting to read it outside +// the closure. +fn box_2() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let mut c = || { + e.0.0.m.x = format!("not-x"); + }; + + println!("{}", e.0.0.m.x); + //~^ ERROR: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable + c(); +} + +// Check diagnostics when a path is read inside a closure while attempting to mutate it outside +// the closure. +fn box_3() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let c = || { + println!("{}", e.0.0.m.x); + }; + + e.0.0.m.x = format!("not-x"); + //~^ ERROR: cannot assign to `e.0.0.m.x` because it is borrowed + c(); +} + +fn main() { + box_1(); + box_2(); + box_3(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr new file mode 100644 index 000000000..f8b178752 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr @@ -0,0 +1,48 @@ +error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed + --> $DIR/box.rs:21:5 + | +LL | let mut c = || { + | -- borrow of `e.0.0.m.x` occurs here +LL | e.0.0.m.x = format!("not-x"); + | --------- borrow occurs due to use in closure +... +LL | e.0.0.m.x = format!("not-x"); + | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here +LL | +LL | c(); + | - borrow later used here + +error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed as mutable + --> $DIR/box.rs:38:20 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | e.0.0.m.x = format!("not-x"); + | --------- first borrow occurs due to use of `e.0.0.m.x` in closure +... +LL | println!("{}", e.0.0.m.x); + | ^^^^^^^^^ immutable borrow occurs here +LL | +LL | c(); + | - mutable borrow later used here + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed + --> $DIR/box.rs:55:5 + | +LL | let c = || { + | -- borrow of `e.0.0.m.x` occurs here +LL | println!("{}", e.0.0.m.x); + | --------- borrow occurs due to use in closure +... +LL | e.0.0.m.x = format!("not-x"); + | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here +LL | +LL | c(); + | - borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0502, E0506. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs new file mode 100644 index 000000000..77effcb00 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.rs @@ -0,0 +1,19 @@ +// edition:2021 + +// Test that if we deref an immutable borrow to access a Place, +// then we can't mutate the final place. + +fn main() { + let mut x = (format!(""), format!("X2")); + let mut y = (&x, "Y"); + let z = (&mut y, "Z"); + + // `x.0` is mutable but we access `x` via `*z.0.0`, which is an immutable reference and + // therefore can't be mutated. + let mut c = || { + //~^ ERROR: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference + z.0.0.0 = format!("X1"); + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr new file mode 100644 index 000000000..38c530b80 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `*z.0.0` as mutable, as it is behind a `&` reference + --> $DIR/cant-mutate-imm-borrow.rs:13:17 + | +LL | let mut c = || { + | ^^ cannot borrow as mutable +LL | +LL | z.0.0.0 = format!("X1"); + | ------- mutable borrow occurs due to use of `*z.0.0` in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs new file mode 100644 index 000000000..25ee9a149 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs @@ -0,0 +1,34 @@ +// edition:2021 + +// Ensure that diagnostics for mutability error (because the root variable +// isn't mutable) work with `capture_disjoint_fields` enabled. + +fn mut_error_struct() { + let x = (10, 10); + let y = (x, 10); + let z = (y, 10); + + let mut c = || { + z.0.0.0 = 20; + //~^ ERROR: cannot assign to `z.0.0.0`, as it is not declared as mutable + }; + + c(); +} + +fn mut_error_box() { + let x = (10, 10); + let bx = Box::new(x); + + let mut c = || { + bx.0 = 20; + //~^ ERROR: cannot assign to `*bx.0`, as it is not declared as mutable + }; + + c(); +} + +fn main() { + mut_error_struct(); + mut_error_box(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr new file mode 100644 index 000000000..98414fa8a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `z.0.0.0`, as it is not declared as mutable + --> $DIR/cant-mutate-imm.rs:12:9 + | +LL | let z = (y, 10); + | - help: consider changing this to be mutable: `mut z` +... +LL | z.0.0.0 = 20; + | ^^^^^^^^^^^^ cannot assign + +error[E0594]: cannot assign to `*bx.0`, as it is not declared as mutable + --> $DIR/cant-mutate-imm.rs:24:9 + | +LL | let bx = Box::new(x); + | -- help: consider changing this to be mutable: `mut bx` +... +LL | bx.0 = 20; + | ^^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs new file mode 100644 index 000000000..f3be542e4 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.rs @@ -0,0 +1,13 @@ +// edition:2021 + +// Test that array access is not stored as part of closure kind origin + +fn expect_fn(_f: F) {} + +fn main() { + let s = [format!("s"), format!("s")]; + let c = || { //~ ERROR expected a closure that implements the `Fn` + let [_, _s] = s; + }; + expect_fn(c); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr new file mode 100644 index 000000000..309c63e52 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -0,0 +1,22 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-array-diagnostics.rs:9:13 + | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let [_, _s] = s; + | - closure is `FnOnce` because it moves the variable `s` out of its environment +LL | }; +LL | expect_fn(c); + | --------- - the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `expect_fn` + --> $DIR/closure-origin-array-diagnostics.rs:5:17 + | +LL | fn expect_fn(_f: F) {} + | ^^^^ required by this bound in `expect_fn` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs new file mode 100644 index 000000000..aa85b55b1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.rs @@ -0,0 +1,27 @@ +// edition:2021 + +// Check that precise paths are being reported back in the error message. + +enum MultiVariant { + Point(i32, i32), + Meta(i32) +} + +fn main() { + let mut point = MultiVariant::Point(10, -10,); + + let mut meta = MultiVariant::Meta(1); + + let c = || { + if let MultiVariant::Point(ref mut x, _) = point { + *x += 1; + } + + if let MultiVariant::Meta(ref mut v) = meta { + *v += 1; + } + }; + + let a = c; + let b = c; //~ ERROR use of moved value: `c` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr new file mode 100644 index 000000000..83d282aad --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `c` + --> $DIR/closure-origin-multi-variant-diagnostics.rs:26:13 + | +LL | let a = c; + | - value moved here +LL | let b = c; + | ^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment + --> $DIR/closure-origin-multi-variant-diagnostics.rs:16:52 + | +LL | if let MultiVariant::Point(ref mut x, _) = point { + | ^^^^^ +help: consider mutably borrowing `c` + | +LL | let a = &mut c; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs new file mode 100644 index 000000000..bedb103cc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.rs @@ -0,0 +1,18 @@ +// edition:2021 + + +enum SingleVariant { + Point(i32, i32), +} + +fn main() { + let mut point = SingleVariant::Point(10, -10); + + let c = || { + let SingleVariant::Point(ref mut x, _) = point; + *x += 1; + }; + + let b = c; + let a = c; //~ ERROR use of moved value: `c` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr new file mode 100644 index 000000000..46323b752 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `c` + --> $DIR/closure-origin-single-variant-diagnostics.rs:17:13 + | +LL | let b = c; + | - value moved here +LL | let a = c; + | ^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `point.0` out of its environment + --> $DIR/closure-origin-single-variant-diagnostics.rs:12:50 + | +LL | let SingleVariant::Point(ref mut x, _) = point; + | ^^^^^ +help: consider mutably borrowing `c` + | +LL | let b = &mut c; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs new file mode 100644 index 000000000..3277a83c4 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.rs @@ -0,0 +1,22 @@ +// edition:2021 + +// Check that precise paths are being reported back in the error message. + +struct Y { + y: X +} + +struct X { + a: u32, + b: u32, +} + +fn main() { + let mut x = Y { y: X { a: 5, b: 0 } }; + let hello = || { + x.y.a += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr new file mode 100644 index 000000000..25029cc7b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `hello` + --> $DIR/closure-origin-struct-diagnostics.rs:21:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.y.a` out of its environment + --> $DIR/closure-origin-struct-diagnostics.rs:17:9 + | +LL | x.y.a += 1; + | ^^^^^ +help: consider mutably borrowing `hello` + | +LL | let b = &mut hello; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs new file mode 100644 index 000000000..dc3a57ae7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.rs @@ -0,0 +1,13 @@ +// edition:2021 + +// Check that precise paths are being reported back in the error message. + +fn main() { + let mut x = (5, 0); + let hello = || { + x.0 += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr new file mode 100644 index 000000000..06ef7baf9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `hello` + --> $DIR/closure-origin-tuple-diagnostics-1.rs:12:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x.0` out of its environment + --> $DIR/closure-origin-tuple-diagnostics-1.rs:8:9 + | +LL | x.0 += 1; + | ^^^ +help: consider mutably borrowing `hello` + | +LL | let b = &mut hello; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs new file mode 100644 index 000000000..fa1328013 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.rs @@ -0,0 +1,13 @@ +// edition:2021 + +struct S(String, String); + +fn expect_fn(_f: F) {} + +fn main() { + let s = S(format!("s"), format!("s")); + let c = || { //~ ERROR expected a closure that implements the `Fn` + let s = s.1; + }; + expect_fn(c); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr new file mode 100644 index 000000000..3e77635f9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -0,0 +1,22 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-tuple-diagnostics.rs:9:13 + | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let s = s.1; + | --- closure is `FnOnce` because it moves the variable `s.1` out of its environment +LL | }; +LL | expect_fn(c); + | --------- - the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `expect_fn` + --> $DIR/closure-origin-tuple-diagnostics.rs:5:17 + | +LL | fn expect_fn(_f: F) {} + | ^^^^ required by this bound in `expect_fn` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs new file mode 100644 index 000000000..3399bc001 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.rs @@ -0,0 +1,92 @@ +// edition:2021 + +// check-pass +#![allow(unreachable_code)] +#![warn(unused)] +#![allow(dead_code)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +pub fn f() { + let mut a = 1; + let mut c = Point{ x:1, y:0 }; + + // Captured by value, but variable is dead on entry. + (move || { + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x = 1; + println!("{}", c.x); + a = 1; //~ WARN value captured by `a` is never read + println!("{}", a); + })(); + + // Read and written to, but never actually used. + (move || { + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x += 1; + a += 1; //~ WARN unused variable: `a` + })(); + + (move || { + println!("{}", c.x); + // Value is read by closure itself on later invocations. + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x += 1; + println!("{}", a); + a += 1; + })(); + let b = Box::new(42); + (move || { + println!("{}", c.x); + // Never read because this is FnOnce closure. + // This will not trigger a warning for unused variable as + // c.x will be treated as a Non-tracked place + c.x += 1; + println!("{}", a); + a += 1; //~ WARN value assigned to `a` is never read + drop(b); + })(); +} + +#[derive(Debug)] +struct MyStruct<'a> { + x: Option<& 'a str>, + y: i32, +} + +pub fn nested() { + let mut a : Option<& str>; + a = None; + let mut b : Option<& str>; + b = None; + let mut d = MyStruct{ x: None, y: 1}; + let mut e = MyStruct{ x: None, y: 1}; + (|| { + (|| { + // This will not trigger a warning for unused variable as + // d.x will be treated as a Non-tracked place + d.x = Some("d1"); + d.x = Some("d2"); + a = Some("d1"); //~ WARN value assigned to `a` is never read + a = Some("d2"); + })(); + (move || { + // This will not trigger a warning for unused variable as + //e.x will be treated as a Non-tracked place + e.x = Some("e1"); + e.x = Some("e2"); + b = Some("e1"); //~ WARN value assigned to `b` is never read + //~| WARN unused variable: `b` + b = Some("e2"); //~ WARN value assigned to `b` is never read + })(); + })(); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr new file mode 100644 index 000000000..cf414adc0 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr @@ -0,0 +1,65 @@ +warning: value captured by `a` is never read + --> $DIR/liveness.rs:24:9 + | +LL | a = 1; + | ^ + | + = help: did you mean to capture by reference instead? +note: the lint level is defined here + --> $DIR/liveness.rs:5:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `a` + --> $DIR/liveness.rs:33:9 + | +LL | a += 1; + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: value assigned to `a` is never read + --> $DIR/liveness.rs:53:9 + | +LL | a += 1; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `a` is never read + --> $DIR/liveness.rs:77:13 + | +LL | a = Some("d1"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `b` is never read + --> $DIR/liveness.rs:85:13 + | +LL | b = Some("e1"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `b` is never read + --> $DIR/liveness.rs:87:13 + | +LL | b = Some("e2"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `b` + --> $DIR/liveness.rs:85:13 + | +LL | b = Some("e1"); + | ^ + | + = help: did you mean to capture by reference instead? + +warning: 7 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs new file mode 100644 index 000000000..465c9476b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs @@ -0,0 +1,43 @@ +// edition:2021 + +// check-pass +#![warn(unused)] +#![allow(dead_code)] + +#[derive(Debug)] +struct MyStruct { + a: i32, + b: i32, +} + +pub fn unintentional_copy_one() { + let mut a = 1; + let mut last = MyStruct{ a: 1, b: 1}; + let mut f = move |s| { + // This will not trigger a warning for unused variable + // as last.a will be treated as a Non-tracked place + last.a = s; + a = s; + //~^ WARN value assigned to `a` is never read + //~| WARN unused variable: `a` + }; + f(2); + f(3); + f(4); +} + +pub fn unintentional_copy_two() { + let mut a = 1; + let mut sum = MyStruct{ a: 1, b: 0}; + (1..10).for_each(move |x| { + // This will not trigger a warning for unused variable + // as sum.b will be treated as a Non-tracked place + sum.b += x; + a += x; //~ WARN unused variable: `a` + }); +} + +fn main() { + unintentional_copy_one(); + unintentional_copy_two(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr new file mode 100644 index 000000000..0410de4c7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr @@ -0,0 +1,33 @@ +warning: value assigned to `a` is never read + --> $DIR/liveness_unintentional_copy.rs:20:9 + | +LL | a = s; + | ^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/liveness_unintentional_copy.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `a` + --> $DIR/liveness_unintentional_copy.rs:20:9 + | +LL | a = s; + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `a` + --> $DIR/liveness_unintentional_copy.rs:36:9 + | +LL | a += x; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: 3 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs new file mode 100644 index 000000000..fa73ff23f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.rs @@ -0,0 +1,28 @@ +// edition:2021 + +// Test that when a borrow checker diagnostics are emitted, it's as precise +// as the capture by the closure. + +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let mut c = || { + w.p.x += 20; + }; + + let py = &mut w.p.x; + //~^ ERROR: cannot borrow `w.p.x` as mutable more than once at a time + c(); + + *py = 20 +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr new file mode 100644 index 000000000..ac4c9c937 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time + --> $DIR/multilevel-path.rs:23:14 + | +LL | let mut c = || { + | -- first mutable borrow occurs here +LL | w.p.x += 20; + | ----- first borrow occurs due to use of `w.p.x` in closure +... +LL | let py = &mut w.p.x; + | ^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | c(); + | - first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs new file mode 100644 index 000000000..3d5a31e8b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.rs @@ -0,0 +1,37 @@ +// edition:2021 + +// Test that we can't mutate a place if we need to deref an imm-borrow +// to reach it. + +fn imm_mut_ref() { + let mut x = String::new(); + let y = String::new(); + let mref_x = &mut x; + let ref_mref_x = &mref_x; + + let c = || { + //~^ ERROR: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference + **ref_mref_x = y; + }; + + c(); +} + +fn mut_imm_ref() { + let x = String::new(); + let y = String::new(); + let mut ref_x = &x; + let mref_ref_x = &mut ref_x; + + let c = || { + //~^ ERROR: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference + **mref_ref_x = y; + }; + + c(); +} + +fn main() { + imm_mut_ref(); + mut_imm_ref(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr new file mode 100644 index 000000000..95f36fc04 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -0,0 +1,26 @@ +error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference + --> $DIR/mut_ref.rs:12:13 + | +LL | let c = || { + | ^^ `ref_mref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable +LL | +LL | **ref_mref_x = y; + | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure + | +help: consider changing this to be a mutable reference + | +LL | let ref_mref_x = &mut mref_x; + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference + --> $DIR/mut_ref.rs:26:13 + | +LL | let c = || { + | ^^ cannot borrow as mutable +LL | +LL | **mref_ref_x = y; + | ------------ mutable borrow occurs due to use of `**mref_ref_x` in closure + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs new file mode 100644 index 000000000..1488f3296 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs @@ -0,0 +1,32 @@ +// edition:2021 + +// Given how the closure desugaring is implemented (at least at the time of writing this test), +// we don't need to truncate the captured path to a reference into a packed-struct if the field +// being referenced will be moved into the closure, since it's safe to move out a field from a +// packed-struct. +// +// However to avoid surprises for the user, or issues when the closure is +// inlined we will truncate the capture to access just the struct regardless of if the field +// might get moved into the closure. +// +// It is possible for someone to try writing the code that relies on the desugaring to create a ref +// into a packed-struct. Here we test that the compiler still detects that case. +fn test_missing_unsafe_warning_on_repr_packed() { + #[repr(packed)] + struct Foo { x: String } + + let foo = Foo { x: String::new() }; + + let c = || { + println!("{}", foo.x); + //~^ ERROR: reference to packed field is unaligned + //~| WARNING: this was previously accepted by the compiler but is being phased out + let _z = foo.x; + }; + + c(); +} + +fn main() { + test_missing_unsafe_warning_on_repr_packed(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr new file mode 100644 index 000000000..508c4b911 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr @@ -0,0 +1,29 @@ +error: reference to packed field is unaligned + --> $DIR/repr_packed.rs:21:24 + | +LL | println!("{}", foo.x); + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/repr_packed.rs:21:24 + | +LL | println!("{}", foo.x); + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs new file mode 100644 index 000000000..ed2d9a3de --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.rs @@ -0,0 +1,25 @@ +// edition:2021 + +// Test that borrow checker error is accurate and that min capture pass of the +// closure analysis is working as expected. + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 20 }; + + // `p` is captured via mutable borrow. + let mut c = || { + p.x += 10; + println!("{:?}", p); + }; + + + println!("{:?}", p); + //~^ ERROR: cannot borrow `p` as immutable because it is also borrowed as mutable + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr new file mode 100644 index 000000000..06157b2af --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr @@ -0,0 +1,21 @@ +error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable + --> $DIR/simple-struct-min-capture.rs:22:22 + | +LL | let mut c = || { + | -- mutable borrow occurs here +LL | p.x += 10; + | --- capture is mutable because of use here +LL | println!("{:?}", p); + | - first borrow occurs due to use of `p` in closure +... +LL | println!("{:?}", p); + | ^ immutable borrow occurs here +LL | +LL | c(); + | - mutable borrow later used here + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs new file mode 100644 index 000000000..46b54846e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs @@ -0,0 +1,25 @@ +// edition:2021 + +// Test that we point to the correct location that results a union being captured. +// Union is special because it can't be disjointly captured. + +union A { + y: u32, + x: (), +} + +fn main() { + let mut a = A { y: 1 }; + let mut c = || { + //~^ borrow of `a.y` occurs here + let _ = unsafe { &a.y }; + let _ = &mut a; + //~^ borrow occurs due to use in closure + let _ = unsafe { &mut a.y }; + }; + a.y = 1; + //~^ cannot assign to `a.y` because it is borrowed [E0506] + //~| assignment to borrowed `a.y` occurs here + c(); + //~^ borrow later used here +} diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr new file mode 100644 index 000000000..7c34e2336 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr @@ -0,0 +1,18 @@ +error[E0506]: cannot assign to `a.y` because it is borrowed + --> $DIR/union.rs:20:5 + | +LL | let mut c = || { + | -- borrow of `a.y` occurs here +... +LL | let _ = &mut a; + | - borrow occurs due to use in closure +... +LL | a.y = 1; + | ^^^^^^^ assignment to borrowed `a.y` occurs here +... +LL | c(); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs new file mode 100644 index 000000000..269cf76e6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs @@ -0,0 +1,18 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +fn main() { + let s = format!("s"); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("This uses new capture analyysis to capture s={}", s); + //~^ NOTE: Capturing s[] -> ImmBorrow + //~| NOTE: Min Capture s[] -> ImmBorrow + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr new file mode 100644 index 000000000..b936c5ee3 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/feature-gate-capture_disjoint_fields.rs:8:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("This uses new capture analyysis to capture s={}", s); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing s[] -> ImmBorrow + --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69 + | +LL | println!("This uses new capture analyysis to capture s={}", s); + | ^ + +error: Min Capture analysis includes: + --> $DIR/feature-gate-capture_disjoint_fields.rs:11:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("This uses new capture analyysis to capture s={}", s); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture s[] -> ImmBorrow + --> $DIR/feature-gate-capture_disjoint_fields.rs:14:69 + | +LL | println!("This uses new capture analyysis to capture s={}", s); + | ^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs new file mode 100644 index 000000000..bfa3ebcd6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs @@ -0,0 +1,41 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +struct Filter { + div: i32, +} +impl Filter { + fn allowed(&self, x: i32) -> bool { + x % self.div == 1 + } +} + +struct Data { + filter: Filter, + list: Vec, +} +impl Data { + fn update(&mut self) { + // The closure passed to filter only captures self.filter, + // therefore mutating self.list is allowed. + self.list.retain( + #[rustc_capture_analysis] + |v| self.filter.allowed(*v), + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + //~| NOTE: Capturing self[Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture self[Deref,(0, 0)] -> ImmBorrow + ); + } +} + +fn main() { + let mut d = Data { filter: Filter { div: 3 }, list: Vec::new() }; + + for i in 1..10 { + d.list.push(i); + } + + d.update(); +} diff --git a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr new file mode 100644 index 000000000..10e0d076b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr @@ -0,0 +1,26 @@ +error: First Pass analysis includes: + --> $DIR/filter-on-struct-member.rs:24:13 + | +LL | |v| self.filter.allowed(*v), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: Capturing self[Deref,(0, 0)] -> ImmBorrow + --> $DIR/filter-on-struct-member.rs:24:17 + | +LL | |v| self.filter.allowed(*v), + | ^^^^^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/filter-on-struct-member.rs:24:13 + | +LL | |v| self.filter.allowed(*v), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: Min Capture self[Deref,(0, 0)] -> ImmBorrow + --> $DIR/filter-on-struct-member.rs:24:17 + | +LL | |v| self.filter.allowed(*v), + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.rs b/tests/ui/closures/2229_closure_analysis/issue-87378.rs new file mode 100644 index 000000000..75901a571 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.rs @@ -0,0 +1,26 @@ +#![feature(rustc_attrs)] + +// edition:2021 + +// Test that any precise capture on a union is truncated because it's unsafe to do so. + +union Union { + value: u64, +} + +fn main() { + let u = Union { value: 42 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + unsafe { u.value } + //~^ NOTE: Capturing u[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture u[] -> ImmBorrow + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr new file mode 100644 index 000000000..16c3f7c97 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/issue-87378.rs:14:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/issue-87378.rs:17:5 + | +LL | / || { +LL | | +LL | | +LL | | unsafe { u.value } +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing u[(0, 0)] -> ImmBorrow + --> $DIR/issue-87378.rs:20:17 + | +LL | unsafe { u.value } + | ^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/issue-87378.rs:17:5 + | +LL | / || { +LL | | +LL | | +LL | | unsafe { u.value } +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture u[] -> ImmBorrow + --> $DIR/issue-87378.rs:20:17 + | +LL | unsafe { u.value } + | ^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/issue-87987.rs b/tests/ui/closures/2229_closure_analysis/issue-87987.rs new file mode 100644 index 000000000..d26343c33 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-87987.rs @@ -0,0 +1,27 @@ +// run-pass +// edition:2021 + +struct Props { + field_1: u32, //~ WARNING: fields `field_1` and `field_2` are never read + field_2: u32, +} + +fn main() { + // Test 1 + let props_2 = Props { field_1: 1, field_2: 1 }; + + let _ = || { + let _: Props = props_2; + }; + + // Test 2 + let mut arr = [1, 3, 4, 5]; + + let mref = &mut arr; + + let _c = || match arr { + [_, _, _, _] => println!("A"), + }; + + println!("{:#?}", mref); +} diff --git a/tests/ui/closures/2229_closure_analysis/issue-87987.stderr b/tests/ui/closures/2229_closure_analysis/issue-87987.stderr new file mode 100644 index 000000000..5696a010c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-87987.stderr @@ -0,0 +1,14 @@ +warning: fields `field_1` and `field_2` are never read + --> $DIR/issue-87987.rs:5:5 + | +LL | struct Props { + | ----- fields in this struct +LL | field_1: u32, + | ^^^^^^^ +LL | field_2: u32, + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/issue-88118-2.rs b/tests/ui/closures/2229_closure_analysis/issue-88118-2.rs new file mode 100644 index 000000000..0cfb1a55b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-88118-2.rs @@ -0,0 +1,24 @@ +// edition:2021 +// run-pass +#![feature(if_let_guard)] +#[allow(unused_must_use)] +#[allow(dead_code)] + +fn print_error_count(registry: &Registry) { + |x: &Registry| { + match &x { + Registry if let _ = registry.try_find_description() => { } + //~^ WARNING: irrefutable `if let` guard pattern + _ => {} + } + }; +} + +struct Registry; +impl Registry { + pub fn try_find_description(&self) { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/issue-88118-2.stderr b/tests/ui/closures/2229_closure_analysis/issue-88118-2.stderr new file mode 100644 index 000000000..b3cb558f9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-88118-2.stderr @@ -0,0 +1,12 @@ +warning: irrefutable `if let` guard pattern + --> $DIR/issue-88118-2.rs:10:29 + | +LL | Registry if let _ = registry.try_find_description() => { } + | ^ + | + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.rs b/tests/ui/closures/2229_closure_analysis/issue-88476.rs new file mode 100644 index 000000000..f5906d306 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.rs @@ -0,0 +1,62 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +// Test that we can't move out of struct that impls `Drop`. + + +use std::rc::Rc; + +// Test that we restrict precision when moving not-`Copy` types, if any of the parent paths +// implement `Drop`. This is to ensure that we don't move out of a type that implements Drop. +pub fn test1() { + struct Foo(Rc); + + impl Drop for Foo { + fn drop(self: &mut Foo) {} + } + + let f = Foo(Rc::new(1)); + let x = #[rustc_capture_analysis] move || { + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{:?}", f.0); + //~^ NOTE: Capturing f[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture f[] -> ByValue + }; + + x(); +} + +// Test that we don't restrict precision when moving `Copy` types(i.e. when copying), +// even if any of the parent paths implement `Drop`. +fn test2() { + struct Character { + hp: u32, + name: String, + } + + impl Drop for Character { + fn drop(&mut self) {} + } + + let character = Character { hp: 100, name: format!("A") }; + + let c = #[rustc_capture_analysis] move || { + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", character.hp) + //~^ NOTE: Capturing character[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture character[(0, 0)] -> ByValue + }; + + c(); + + println!("{}", character.name); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr new file mode 100644 index 000000000..c7c9ecbbb --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr @@ -0,0 +1,97 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/issue-88476.rs:20:13 + | +LL | let x = #[rustc_capture_analysis] move || { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/issue-88476.rs:47:13 + | +LL | let c = #[rustc_capture_analysis] move || { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/issue-88476.rs:20:39 + | +LL | let x = #[rustc_capture_analysis] move || { + | _______________________________________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing f[(0, 0)] -> ImmBorrow + --> $DIR/issue-88476.rs:25:26 + | +LL | println!("{:?}", f.0); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/issue-88476.rs:20:39 + | +LL | let x = #[rustc_capture_analysis] move || { + | _______________________________________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture f[] -> ByValue + --> $DIR/issue-88476.rs:25:26 + | +LL | println!("{:?}", f.0); + | ^^^ + +error: First Pass analysis includes: + --> $DIR/issue-88476.rs:47:39 + | +LL | let c = #[rustc_capture_analysis] move || { + | _______________________________________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing character[(0, 0)] -> ImmBorrow + --> $DIR/issue-88476.rs:52:24 + | +LL | println!("{}", character.hp) + | ^^^^^^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/issue-88476.rs:47:39 + | +LL | let c = #[rustc_capture_analysis] move || { + | _______________________________________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture character[(0, 0)] -> ByValue + --> $DIR/issue-88476.rs:52:24 + | +LL | println!("{}", character.hp) + | ^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/issue-89606.rs b/tests/ui/closures/2229_closure_analysis/issue-89606.rs new file mode 100644 index 000000000..1bb6aa40f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-89606.rs @@ -0,0 +1,40 @@ +// Regression test for #89606. Used to ICE. +// +// check-pass +// revisions: twenty_eighteen twenty_twentyone +// [twenty_eighteen]compile-flags: --edition 2018 +// [twenty_twentyone]compile-flags: --edition 2021 + +struct S<'a>(Option<&'a mut i32>); + +fn by_ref(s: &mut S<'_>) { + (|| { + let S(_o) = s; + s.0 = None; + })(); +} + +fn by_value(s: S<'_>) { + (|| { + let S(ref _o) = s; + let _g = s.0; + })(); +} + +struct V<'a>((Option<&'a mut i32>,)); + +fn nested(v: &mut V<'_>) { + (|| { + let V((_o,)) = v; + v.0 = (None, ); + })(); +} + +fn main() { + let mut s = S(None); + by_ref(&mut s); + by_value(s); + + let mut v = V((None, )); + nested(&mut v); +} diff --git a/tests/ui/closures/2229_closure_analysis/issue-90465.fixed b/tests/ui/closures/2229_closure_analysis/issue-90465.fixed new file mode 100644 index 000000000..4e0b18e72 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-90465.fixed @@ -0,0 +1,35 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE lint level is defined here + +fn main() { + struct Foo(u32); + impl Drop for Foo { + fn drop(&mut self) { + println!("dropped {}", self.0); + } + } + + let f0 = Foo(0); + let f1 = Foo(1); + + let c0 = move || { + let _ = &f0; + //~^ ERROR changes to closure capture in Rust 2021 will affect drop order + //~| NOTE for more information + let _ = f0; + //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect + }; + + let c1 = move || { + let _ = &f1; + }; + + println!("dropping 0"); + drop(c0); + println!("dropping 1"); + drop(c1); + println!("dropped all"); +} +//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure diff --git a/tests/ui/closures/2229_closure_analysis/issue-90465.rs b/tests/ui/closures/2229_closure_analysis/issue-90465.rs new file mode 100644 index 000000000..466e6dbab --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-90465.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE lint level is defined here + +fn main() { + struct Foo(u32); + impl Drop for Foo { + fn drop(&mut self) { + println!("dropped {}", self.0); + } + } + + let f0 = Foo(0); + let f1 = Foo(1); + + let c0 = move || { + //~^ ERROR changes to closure capture in Rust 2021 will affect drop order + //~| NOTE for more information + let _ = f0; + //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect + }; + + let c1 = move || { + let _ = &f1; + }; + + println!("dropping 0"); + drop(c0); + println!("dropping 1"); + drop(c1); + println!("dropped all"); +} +//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure diff --git a/tests/ui/closures/2229_closure_analysis/issue-90465.stderr b/tests/ui/closures/2229_closure_analysis/issue-90465.stderr new file mode 100644 index 000000000..c1679c6b6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-90465.stderr @@ -0,0 +1,26 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/issue-90465.rs:17:14 + | +LL | let c0 = move || { + | ^^^^^^^ +... +LL | let _ = f0; + | -- in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect +... +LL | } + | - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/issue-90465.rs:3:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `f0` to be fully captured + | +LL ~ let c0 = move || { +LL + let _ = &f0; + | + +error: aborting due to previous error + diff --git a/tests/ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs b/tests/ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs new file mode 100644 index 000000000..a3b17755f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs @@ -0,0 +1,14 @@ +// ICEs if checking if there is a significant destructor causes a query cycle +// check-pass + +#![warn(rust_2021_incompatible_closure_captures)] +pub struct Foo(Bar); +pub struct Bar(Baz); +pub struct Baz(Vec); + +impl Foo { + pub fn baz(self, v: Baz) -> Baz { + (|| v)() + } +} +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/issue_88118.rs b/tests/ui/closures/2229_closure_analysis/issue_88118.rs new file mode 100644 index 000000000..453b7e04a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue_88118.rs @@ -0,0 +1,15 @@ +// Regression test for #88118. Used to ICE. +// +// check-pass + +#![allow(incomplete_features)] +#![feature(capture_disjoint_fields)] + +fn foo(handler: impl FnOnce() -> MsU + Clone + 'static) { + Box::new(move |value| { + (|_| handler.clone()())(value); + None + }) as Box Option>; +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs b/tests/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs new file mode 100644 index 000000000..4060c4093 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs @@ -0,0 +1,10 @@ +#[non_exhaustive] +pub enum E1 {} + +#[non_exhaustive] +pub enum E2 { A, B } + +#[non_exhaustive] +pub enum E3 { C } + +pub enum E4 { D } diff --git a/tests/ui/closures/2229_closure_analysis/match/issue-87097.rs b/tests/ui/closures/2229_closure_analysis/match/issue-87097.rs new file mode 100644 index 000000000..815fc0a71 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/issue-87097.rs @@ -0,0 +1,35 @@ +// run-pass +// edition:2021 + +enum Variant { + A, + B, //~ WARNING: variant `B` is never constructed +} + +struct A { + field: Variant, +} + +fn discriminant_is_a_ref() { + let here = A { field: Variant::A }; + let out_ref = &here.field; + + || match out_ref { //~ WARNING: unused closure that must be used + Variant::A => (), + Variant::B => (), + }; +} + +fn discriminant_is_a_field() { + let here = A { field: Variant::A }; + + || match here.field { //~ WARNING: unused closure that must be used + Variant::A => (), + Variant::B => (), + }; +} + +fn main() { + discriminant_is_a_ref(); + discriminant_is_a_field(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/issue-87097.stderr b/tests/ui/closures/2229_closure_analysis/match/issue-87097.stderr new file mode 100644 index 000000000..39ec71ba2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/issue-87097.stderr @@ -0,0 +1,36 @@ +warning: variant `B` is never constructed + --> $DIR/issue-87097.rs:6:5 + | +LL | enum Variant { + | ------- variant in this enum +LL | A, +LL | B, + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: unused closure that must be used + --> $DIR/issue-87097.rs:17:5 + | +LL | / || match out_ref { +LL | | Variant::A => (), +LL | | Variant::B => (), +LL | | }; + | |_____^ + | + = note: closures are lazy and do nothing unless called + = note: `#[warn(unused_must_use)]` on by default + +warning: unused closure that must be used + --> $DIR/issue-87097.rs:26:5 + | +LL | / || match here.field { +LL | | Variant::A => (), +LL | | Variant::B => (), +LL | | }; + | |_____^ + | + = note: closures are lazy and do nothing unless called + +warning: 3 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/match/issue-87426.rs b/tests/ui/closures/2229_closure_analysis/match/issue-87426.rs new file mode 100644 index 000000000..74506979a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/issue-87426.rs @@ -0,0 +1,14 @@ +// run-pass +// edition:2021 + +pub fn foo() { + let ref_x_ck = 123; + let _y = || match ref_x_ck { + 2_000_000..=3_999_999 => { println!("A")} + _ => { println!("B")} + }; +} + +fn main() { + foo(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/issue-87988.rs b/tests/ui/closures/2229_closure_analysis/match/issue-87988.rs new file mode 100644 index 000000000..27e7fabf1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/issue-87988.rs @@ -0,0 +1,19 @@ +// run-pass +// edition:2021 + +const LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: i32 = 0x01; +const LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: i32 = 0x02; + +pub fn hotplug_callback(event: i32) { + let _ = || { + match event { + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED => (), + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT => (), + _ => (), + }; + }; +} + +fn main() { + hotplug_callback(1); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/issue-88331.rs b/tests/ui/closures/2229_closure_analysis/match/issue-88331.rs new file mode 100644 index 000000000..0a6d71c68 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/issue-88331.rs @@ -0,0 +1,33 @@ +// edition:2021 + +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Opcode(pub u8); + +impl Opcode { + pub const OP1: Opcode = Opcode(0x1); +} + +pub fn example1(msg_type: Opcode) -> impl FnMut(&[u8]) { + move |i| match msg_type { + //~^ ERROR: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered + Opcode::OP1 => unimplemented!(), + } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Opcode2(Opcode); + +impl Opcode2 { + pub const OP2: Opcode2 = Opcode2(Opcode(0x1)); +} + + +pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { + + move |i| match msg_type { + //~^ ERROR: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered + Opcode2::OP2=> unimplemented!(), + } +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/issue-88331.stderr b/tests/ui/closures/2229_closure_analysis/match/issue-88331.stderr new file mode 100644 index 000000000..7e22defa9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/issue-88331.stderr @@ -0,0 +1,39 @@ +error[E0004]: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered + --> $DIR/issue-88331.rs:11:20 + | +LL | move |i| match msg_type { + | ^^^^^^^^ patterns `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered + | +note: `Opcode` defined here + --> $DIR/issue-88331.rs:4:12 + | +LL | pub struct Opcode(pub u8); + | ^^^^^^ + = note: the matched value is of type `Opcode` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Opcode::OP1 => unimplemented!(), +LL ~ Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered + --> $DIR/issue-88331.rs:27:20 + | +LL | move |i| match msg_type { + | ^^^^^^^^ patterns `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered + | +note: `Opcode2` defined here + --> $DIR/issue-88331.rs:18:12 + | +LL | pub struct Opcode2(Opcode); + | ^^^^^^^ + = note: the matched value is of type `Opcode2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Opcode2::OP2=> unimplemented!(), +LL ~ Opcode2(Opcode(0_u8)) | Opcode2(Opcode(2_u8..=u8::MAX)) => todo!(), + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs new file mode 100644 index 000000000..914ebbe26 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs @@ -0,0 +1,44 @@ +// run-pass +// edition:2021 + +const PATTERN_REF: &str = "Hello World"; +const NUMBER: i32 = 30; +const NUMBER_POINTER: *const i32 = &NUMBER; + +pub fn edge_case_ref(event: &str) { + let _ = || { + match event { + PATTERN_REF => (), + _ => (), + }; + }; +} + +pub fn edge_case_str(event: String) { + let _ = || { + match event.as_str() { + "hello" => (), + _ => (), + }; + }; +} + +pub fn edge_case_raw_ptr(event: *const i32) { + let _ = || { + match event { + NUMBER_POINTER => (), + _ => (), + }; + }; +} + +pub fn edge_case_char(event: char) { + let _ = || { + match event { + 'a' => (), + _ => (), + }; + }; +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs new file mode 100644 index 000000000..ae724f9c3 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs @@ -0,0 +1,37 @@ +// edition:2021 + +enum SingleVariant { + A +} + +struct TestStruct { + x: i32, + y: i32, + z: i32, +} + +fn edge_case_if() { + let sv = SingleVariant::A; + let condition = true; + // sv should not be captured as it is a SingleVariant + let _a = || { + match sv { + SingleVariant::A if condition => (), + _ => () + } + }; + let mut mut_sv = sv; + _a(); + + // ts should be captured + let ts = TestStruct { x: 1, y: 1, z: 1 }; + let _b = || { match ts { + TestStruct{ x: 1, .. } => (), + _ => () + }}; + let mut mut_ts = ts; + //~^ ERROR: cannot move out of `ts` because it is borrowed + _b(); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr new file mode 100644 index 000000000..1e42d73c6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr @@ -0,0 +1,17 @@ +error[E0505]: cannot move out of `ts` because it is borrowed + --> $DIR/match-edge-cases_2.rs:32:22 + | +LL | let _b = || { match ts { + | -- -- borrow occurs due to use in closure + | | + | borrow of `ts` occurs here +... +LL | let mut mut_ts = ts; + | ^^ move out of `ts` occurs here +LL | +LL | _b(); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs new file mode 100644 index 000000000..972c24c23 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs @@ -0,0 +1,54 @@ +// edition:2021 + +// aux-build:match_non_exhaustive_lib.rs + +/* The error message for non-exhaustive matches on non-local enums + * marked as non-exhaustive should mention the fact that the enum + * is marked as non-exhaustive (issue #85227). + */ + +// Ignore non_exhaustive in the same crate +#[non_exhaustive] +enum L1 { A, B } +enum L2 { C } + +extern crate match_non_exhaustive_lib; +use match_non_exhaustive_lib::{E1, E2, E3, E4}; + +fn foo() -> (L1, L2) {todo!()} +fn bar() -> (E1, E2, E3, E4) {todo!()} + +fn main() { + let (l1, l2) = foo(); + // No error for enums defined in this crate + let _a = || { match l1 { L1::A => (), L1::B => () } }; + // (except if the match is already non-exhaustive) + let _b = || { match l1 { L1::A => () } }; + //~^ ERROR: non-exhaustive patterns: `L1::B` not covered [E0004] + + // l2 should not be captured as it is a non-exhaustive SingleVariant + // defined in this crate + let _c = || { match l2 { L2::C => (), _ => () } }; + let mut mut_l2 = l2; + _c(); + + // E1 is not visibly uninhabited from here + let (e1, e2, e3, e4) = bar(); + let _d = || { match e1 {} }; + //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004] + let _e = || { match e2 { E2::A => (), E2::B => () } }; + //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] + let _f = || { match e2 { E2::A => (), E2::B => (), _ => () } }; + + // e3 should be captured as it is a non-exhaustive SingleVariant + // defined in another crate + let _g = || { match e3 { E3::C => (), _ => () } }; + let mut mut_e3 = e3; + //~^ ERROR: cannot move out of `e3` because it is borrowed + _g(); + + // e4 should not be captured as it is a SingleVariant + let _h = || { match e4 { E4::D => (), _ => () } }; + let mut mut_e4 = e4; + _h(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr new file mode 100644 index 000000000..3a5fad154 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -0,0 +1,70 @@ +error[E0004]: non-exhaustive patterns: `L1::B` not covered + --> $DIR/non-exhaustive-match.rs:26:25 + | +LL | let _b = || { match l1 { L1::A => () } }; + | ^^ pattern `L1::B` not covered + | +note: `L1` defined here + --> $DIR/non-exhaustive-match.rs:12:14 + | +LL | enum L1 { A, B } + | -- ^ not covered + = note: the matched value is of type `L1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | let _b = || { match l1 { L1::A => (), L1::B => todo!() } }; + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: type `E1` is non-empty + --> $DIR/non-exhaustive-match.rs:37:25 + | +LL | let _d = || { match e1 {} }; + | ^^ + | +note: `E1` defined here + --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1 + | +LL | pub enum E1 {} + | ^^^^^^^^^^^ + = note: the matched value is of type `E1`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let _d = || { match e1 { +LL + _ => todo!(), +LL ~ } }; + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/non-exhaustive-match.rs:39:25 + | +LL | let _e = || { match e2 { E2::A => (), E2::B => () } }; + | ^^ pattern `_` not covered + | +note: `E2` defined here + --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1 + | +LL | pub enum E2 { A, B } + | ^^^^^^^^^^^ + = note: the matched value is of type `E2`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } }; + | ++++++++++++++ + +error[E0505]: cannot move out of `e3` because it is borrowed + --> $DIR/non-exhaustive-match.rs:46:22 + | +LL | let _g = || { match e3 { E3::C => (), _ => () } }; + | -- -- borrow occurs due to use in closure + | | + | borrow of `e3` occurs here +LL | let mut mut_e3 = e3; + | ^^ move out of `e3` occurs here +LL | +LL | _g(); + | -- borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0004, E0505. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs new file mode 100644 index 000000000..69cf920de --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs @@ -0,0 +1,79 @@ +// edition:2021 + +#![feature(never_type)] + +// Should fake read the discriminant and throw an error +fn test1() { + let x: !; + let c1 = || match x { }; + //~^ ERROR E0381 +} + +// Should fake read the discriminant and throw an error +fn test2() { + let x: !; + let c2 = || match x { _ => () }; + //~^ ERROR E0381 +} + +// Testing single variant patterns +enum SingleVariant { + Points(u32) +} + +// Should fake read the discriminant and throw an error +fn test3() { + let variant: !; + let c = || { + //~^ ERROR E0381 + match variant { + SingleVariant::Points(_) => {} + } + }; + c(); +} + +// Should fake read the discriminant and throw an error +fn test4() { + let variant: !; + let c = || { //~ ERROR E0381 + match variant { + SingleVariant::Points(a) => { + println!("{:?}", a); + } + } + }; + c(); +} + +fn test5() { + let t: !; + let g: !; + + let a = || { + match g { }; //~ ERROR E0381 + let c = || { + match t { }; //~ ERROR E0381 + }; + + c(); + }; + +} + +// Should fake read the discriminant and throw an error +fn test6() { + let x: u8; + let c1 = || match x { }; + //~^ ERROR E0381 + //~| ERROR: non-exhaustive patterns: type `u8` is non-empty +} + +fn main() { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr new file mode 100644 index 000000000..ad061d93c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr @@ -0,0 +1,88 @@ +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/pattern-matching-should-fail.rs:67:23 + | +LL | let c1 = || match x { }; + | ^ + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let c1 = || match x { +LL + _ => todo!(), +LL ~ }; + | + +error[E0381]: used binding `x` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:8:23 + | +LL | let x: !; + | - binding declared here but left uninitialized +LL | let c1 = || match x { }; + | ^ `x` used here but it isn't initialized + +error[E0381]: used binding `x` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:15:14 + | +LL | let x: !; + | - binding declared here but left uninitialized +LL | let c2 = || match x { _ => () }; + | ^^ - borrow occurs due to use in closure + | | + | `x` used here but it isn't initialized + +error[E0381]: used binding `variant` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:27:13 + | +LL | let variant: !; + | ------- binding declared here but left uninitialized +LL | let c = || { + | ^^ `variant` used here but it isn't initialized +LL | +LL | match variant { + | ------- borrow occurs due to use in closure + +error[E0381]: used binding `variant` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:39:13 + | +LL | let variant: !; + | ------- binding declared here but left uninitialized +LL | let c = || { + | ^^ `variant` used here but it isn't initialized +LL | match variant { + | ------- borrow occurs due to use in closure + +error[E0381]: used binding `g` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:54:15 + | +LL | let g: !; + | - binding declared here but left uninitialized +... +LL | match g { }; + | ^ `g` used here but it isn't initialized + +error[E0381]: used binding `t` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:56:19 + | +LL | let t: !; + | - binding declared here but left uninitialized +... +LL | match t { }; + | ^ `t` used here but it isn't initialized + +error[E0381]: used binding `x` isn't initialized + --> $DIR/pattern-matching-should-fail.rs:67:23 + | +LL | let x: u8; + | - binding declared here but left uninitialized +LL | let c1 = || match x { }; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u8 = 0; + | +++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0004, E0381. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs new file mode 100644 index 000000000..56f5ac44d --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -0,0 +1,137 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +// Should capture the discriminant since a variant of a multivariant enum is +// mentioned in the match arm; the discriminant is captured by the closure regardless +// of if it creates a binding +fn test_1_should_capture() { + let variant = Some(2229); + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + match variant { + //~^ NOTE: Capturing variant[] -> ImmBorrow + //~| NOTE: Min Capture variant[] -> ImmBorrow + Some(_) => {} + _ => {} + } + }; + c(); +} + +// Should not capture the discriminant since only a wildcard is mentioned in the +// match arm +fn test_2_should_not_capture() { + let variant = Some(2229); + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + match variant { + _ => {} + } + }; + c(); +} + +// Testing single variant patterns +enum SingleVariant { + Points(u32) +} + +// Should not capture the discriminant since the single variant mentioned +// in the match arm does not trigger a binding +fn test_3_should_not_capture_single_variant() { + let variant = SingleVariant::Points(1); + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + match variant { + SingleVariant::Points(_) => {} + } + }; + c(); +} + +// Should not capture the discriminant since the single variant mentioned +// in the match arm does not trigger a binding +fn test_6_should_capture_single_variant() { + let variant = SingleVariant::Points(1); + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + match variant { + //~^ NOTE: Capturing variant[] -> ImmBorrow + //~| NOTE: Capturing variant[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture variant[] -> ImmBorrow + SingleVariant::Points(a) => { + println!("{:?}", a); + } + } + }; + c(); +} + +// Should not capture the discriminant since only wildcards are mentioned in the +// match arm +fn test_4_should_not_capture_array() { + let array: [i32; 3] = [0; 3]; + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + match array { + [_,_,_] => {} + } + }; + c(); +} + +// Testing MultiVariant patterns +enum MVariant { + A, + B, + C, +} + +// Should capture the discriminant since a variant of the multi variant enum is +// mentioned in the match arm; the discriminant is captured by the closure +// regardless of if it creates a binding +fn test_5_should_capture_multi_variant() { + let variant = MVariant::A; + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ First Pass analysis includes: + //~| Min Capture analysis includes: + match variant { + //~^ NOTE: Capturing variant[] -> ImmBorrow + //~| NOTE: Min Capture variant[] -> ImmBorrow + MVariant::A => {} + _ => {} + } + }; + c(); +} + +fn main() { + test_1_should_capture(); + test_2_should_not_capture(); + test_3_should_not_capture_single_variant(); + test_6_should_capture_single_variant(); + test_4_should_not_capture_array(); + test_5_should_capture_multi_variant(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr new file mode 100644 index 000000000..460813333 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr @@ -0,0 +1,203 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/patterns-capture-analysis.rs:10:14 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/patterns-capture-analysis.rs:31:14 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/patterns-capture-analysis.rs:52:14 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/patterns-capture-analysis.rs:68:14 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/patterns-capture-analysis.rs:90:14 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/patterns-capture-analysis.rs:114:14 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:14:5 + | +LL | / || { +LL | | +LL | | +LL | | match variant { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing variant[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:17:15 + | +LL | match variant { + | ^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/patterns-capture-analysis.rs:14:5 + | +LL | / || { +LL | | +LL | | +LL | | match variant { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture variant[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:17:15 + | +LL | match variant { + | ^^^^^^^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:34:5 + | +LL | / || { +LL | | +LL | | match variant { +LL | | _ => {} +LL | | } +LL | | }; + | |_____^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:55:5 + | +LL | / || { +LL | | +LL | | match variant { +LL | | SingleVariant::Points(_) => {} +LL | | } +LL | | }; + | |_____^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:71:5 + | +LL | / || { +LL | | +LL | | +LL | | match variant { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing variant[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:74:15 + | +LL | match variant { + | ^^^^^^^ +note: Capturing variant[(0, 0)] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:74:15 + | +LL | match variant { + | ^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/patterns-capture-analysis.rs:71:5 + | +LL | / || { +LL | | +LL | | +LL | | match variant { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture variant[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:74:15 + | +LL | match variant { + | ^^^^^^^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:93:5 + | +LL | / || { +LL | | +LL | | match array { +LL | | [_,_,_] => {} +LL | | } +LL | | }; + | |_____^ + +error: First Pass analysis includes: + --> $DIR/patterns-capture-analysis.rs:117:5 + | +LL | / || { +LL | | +LL | | +LL | | match variant { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Capturing variant[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:120:15 + | +LL | match variant { + | ^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/patterns-capture-analysis.rs:117:5 + | +LL | / || { +LL | | +LL | | +LL | | match variant { +... | +LL | | } +LL | | }; + | |_____^ + | +note: Min Capture variant[] -> ImmBorrow + --> $DIR/patterns-capture-analysis.rs:120:15 + | +LL | match variant { + | ^^^^^^^ + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed new file mode 100644 index 000000000..26703fbf8 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -0,0 +1,88 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +/* Test Send Trait Migration */ +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +fn test_send_trait() { + let mut f = 10; + let fptr = SendPointer(&mut f as *mut i32); + thread::spawn(move || { let _ = &fptr; unsafe { + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr` to be fully captured + *fptr.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` + } }); +} + +/* Test Sync Trait Migration */ +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_sync_trait() { + let mut f = 10; + let f = CustomInt(&mut f as *mut i32); + let fptr = SyncPointer(f); + thread::spawn(move || { let _ = &fptr; unsafe { + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr` to be fully captured + *fptr.0.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` + } }); +} + +/* Test Clone Trait Migration */ +struct S(Foo); +struct T(i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(Foo(0)), T(0)) + } +} + +fn test_clone_trait() { + let f = U(S(Foo(0)), T(0)); + let c = || { + let _ = &f; + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f` to be fully captured + let f_1 = f.1; + //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1` + println!("{:?}", f_1.0); + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure + +fn main() { + test_send_trait(); + test_sync_trait(); + test_clone_trait(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs new file mode 100644 index 000000000..932db51d4 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -0,0 +1,87 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +/* Test Send Trait Migration */ +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +fn test_send_trait() { + let mut f = 10; + let fptr = SendPointer(&mut f as *mut i32); + thread::spawn(move || unsafe { + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr` to be fully captured + *fptr.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` + }); +} + +/* Test Sync Trait Migration */ +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_sync_trait() { + let mut f = 10; + let f = CustomInt(&mut f as *mut i32); + let fptr = SyncPointer(f); + thread::spawn(move || unsafe { + //~^ ERROR: changes to closure capture + //~| NOTE: in Rust 2018, this closure implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr` to be fully captured + *fptr.0.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` + }); +} + +/* Test Clone Trait Migration */ +struct S(Foo); +struct T(i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(Foo(0)), T(0)) + } +} + +fn test_clone_trait() { + let f = U(S(Foo(0)), T(0)); + let c = || { + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f` to be fully captured + let f_1 = f.1; + //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1` + println!("{:?}", f_1.0); + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure + +fn main() { + test_send_trait(); + test_sync_trait(); + test_clone_trait(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr new file mode 100644 index 000000000..3a42cc8b8 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -0,0 +1,67 @@ +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/auto_traits.rs:22:19 + | +LL | thread::spawn(move || unsafe { + | ^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send` +... +LL | *fptr.0 = 20; + | ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/auto_traits.rs:2:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `fptr` to be fully captured + | +LL ~ thread::spawn(move || { let _ = &fptr; unsafe { +LL | + ... +LL | +LL ~ } }); + | + +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/auto_traits.rs:42:19 + | +LL | thread::spawn(move || unsafe { + | ^^^^^^^ + | | + | in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send` + | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync` +... +LL | *fptr.0.0 = 20; + | --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` + | + = note: for more information, see +help: add a dummy let to cause `fptr` to be fully captured + | +LL ~ thread::spawn(move || { let _ = &fptr; unsafe { +LL | + ... +LL | +LL ~ } }); + | + +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/auto_traits.rs:67:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f` is not fully captured and `f.1` does not implement `Clone` +... +LL | let f_1 = f.1; + | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1` +... +LL | } + | - in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `f` to be fully captured + | +LL ~ let c = || { +LL + let _ = &f; + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed new file mode 100644 index 000000000..9a6db588c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed @@ -0,0 +1,33 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_compatibility)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +macro_rules! m { + (@ $body:expr) => {{ + let f = || $body; + //~^ WARNING: drop order + f(); + }}; + ($body:block) => {{ + m!(@ $body); + }}; +} + +fn main() { + let a = (Foo(0), Foo(1)); + m!({ + let _ = &a; + //~^ HELP: add a dummy + let x = a.0; + println!("{:?}", x); + }); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs new file mode 100644 index 000000000..08cc24b4b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs @@ -0,0 +1,32 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_compatibility)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +macro_rules! m { + (@ $body:expr) => {{ + let f = || $body; + //~^ WARNING: drop order + f(); + }}; + ($body:block) => {{ + m!(@ $body); + }}; +} + +fn main() { + let a = (Foo(0), Foo(1)); + m!({ + //~^ HELP: add a dummy + let x = a.0; + println!("{:?}", x); + }); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr new file mode 100644 index 000000000..bb17e3a34 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr @@ -0,0 +1,33 @@ +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/closure-body-macro-fragment.rs:16:17 + | +LL | let f = || $body; + | ^^ +... +LL | }}; + | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure +... +LL | / m!({ +LL | | +LL | | let x = a.0; + | | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` +LL | | println!("{:?}", x); +LL | | }); + | |______- in this macro invocation + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/closure-body-macro-fragment.rs:4:9 + | +LL | #![warn(rust_2021_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]` + = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add a dummy let to cause `a` to be fully captured + | +LL ~ m!({ +LL + let _ = &a; + | + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed new file mode 100644 index 000000000..2652bf598 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed @@ -0,0 +1,38 @@ +// run-pass +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +#![allow(unused)] + +// Test cases for types that implement an insignificant drop (stlib defined) + +macro_rules! test_insig_dtor_for_type { + ($t: ty, $disambiguator: ident) => { + mod $disambiguator { + use std::collections::*; + use std::rc::Rc; + use std::sync::Mutex; + + fn test_for_type(t: $t) { + let tup = (Mutex::new(0), t); + + let _c = || tup.0; + } + } + }; +} + +test_insig_dtor_for_type!(i32, prim_i32); +test_insig_dtor_for_type!(Vec, vec_i32); +test_insig_dtor_for_type!(String, string); +test_insig_dtor_for_type!(Vec, vec_string); +test_insig_dtor_for_type!(HashMap, hash_map); +test_insig_dtor_for_type!(BTreeMap, btree_map); +test_insig_dtor_for_type!(LinkedList, linked_list); +test_insig_dtor_for_type!(Rc, rc_i32); +test_insig_dtor_for_type!(Rc, rc_string); +test_insig_dtor_for_type!(std::vec::IntoIter, vec_into_iter); +test_insig_dtor_for_type!(btree_map::IntoIter, btree_map_into_iter); +test_insig_dtor_for_type!(std::array::IntoIter, array_into_iter); + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs new file mode 100644 index 000000000..2652bf598 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs @@ -0,0 +1,38 @@ +// run-pass +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +#![allow(unused)] + +// Test cases for types that implement an insignificant drop (stlib defined) + +macro_rules! test_insig_dtor_for_type { + ($t: ty, $disambiguator: ident) => { + mod $disambiguator { + use std::collections::*; + use std::rc::Rc; + use std::sync::Mutex; + + fn test_for_type(t: $t) { + let tup = (Mutex::new(0), t); + + let _c = || tup.0; + } + } + }; +} + +test_insig_dtor_for_type!(i32, prim_i32); +test_insig_dtor_for_type!(Vec, vec_i32); +test_insig_dtor_for_type!(String, string); +test_insig_dtor_for_type!(Vec, vec_string); +test_insig_dtor_for_type!(HashMap, hash_map); +test_insig_dtor_for_type!(BTreeMap, btree_map); +test_insig_dtor_for_type!(LinkedList, linked_list); +test_insig_dtor_for_type!(Rc, rc_i32); +test_insig_dtor_for_type!(Rc, rc_string); +test_insig_dtor_for_type!(std::vec::IntoIter, vec_into_iter); +test_insig_dtor_for_type!(btree_map::IntoIter, btree_map_into_iter); +test_insig_dtor_for_type!(std::array::IntoIter, array_into_iter); + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed new file mode 100644 index 000000000..d985e3bb9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed @@ -0,0 +1,76 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here +#![feature(rustc_attrs)] +#![allow(unused)] + +use std::sync::Mutex; + + #[rustc_insignificant_dtor] +struct InsignificantDropPoint { + x: i32, + y: Mutex, +} + +impl Drop for InsignificantDropPoint { + fn drop(&mut self) {} +} + +struct SigDrop; + +impl Drop for SigDrop { + fn drop(&mut self) {} +} + +#[rustc_insignificant_dtor] +struct GenericStruct(T, T); + +impl Drop for GenericStruct { + fn drop(&mut self) {} +} + +struct Wrapper(GenericStruct, i32); + +// `SigDrop` implements drop and therefore needs to be migrated. +fn significant_drop_needs_migration() { + let t = (SigDrop {}, SigDrop {}); + + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// Even if a type implements an insignificant drop, if it's +// elements have a significant drop then the overall type is +// consdered to have an significant drop. Since the elements +// of `GenericStruct` implement drop, migration is required. +fn generic_struct_with_significant_drop_needs_migration() { + let t = Wrapper(GenericStruct(SigDrop {}, SigDrop {}), 5); + + // move is used to force i32 to be copied instead of being a ref + let c = move || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.1; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + +fn main() { + significant_drop_needs_migration(); + generic_struct_with_significant_drop_needs_migration(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs new file mode 100644 index 000000000..f95d34eeb --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs @@ -0,0 +1,74 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here +#![feature(rustc_attrs)] +#![allow(unused)] + +use std::sync::Mutex; + + #[rustc_insignificant_dtor] +struct InsignificantDropPoint { + x: i32, + y: Mutex, +} + +impl Drop for InsignificantDropPoint { + fn drop(&mut self) {} +} + +struct SigDrop; + +impl Drop for SigDrop { + fn drop(&mut self) {} +} + +#[rustc_insignificant_dtor] +struct GenericStruct(T, T); + +impl Drop for GenericStruct { + fn drop(&mut self) {} +} + +struct Wrapper(GenericStruct, i32); + +// `SigDrop` implements drop and therefore needs to be migrated. +fn significant_drop_needs_migration() { + let t = (SigDrop {}, SigDrop {}); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// Even if a type implements an insignificant drop, if it's +// elements have a significant drop then the overall type is +// consdered to have an significant drop. Since the elements +// of `GenericStruct` implement drop, migration is required. +fn generic_struct_with_significant_drop_needs_migration() { + let t = Wrapper(GenericStruct(SigDrop {}, SigDrop {}), 5); + + // move is used to force i32 to be copied instead of being a ref + let c = move || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.1; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + +fn main() { + significant_drop_needs_migration(); + generic_struct_with_significant_drop_needs_migration(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr new file mode 100644 index 000000000..a0795c129 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr @@ -0,0 +1,45 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop_attr_migrations.rs:39:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/insignificant_drop_attr_migrations.rs:3:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop_attr_migrations.rs:59:13 + | +LL | let c = move || { + | ^^^^^^^ +... +LL | let _t = t.1; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = move || { +LL + let _ = &t; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs new file mode 100644 index 000000000..3f184a67f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_no_migrations.rs @@ -0,0 +1,45 @@ +// run-pass + +#![deny(rust_2021_incompatible_closure_captures)] +#![feature(rustc_attrs)] +#![allow(unused)] +#[rustc_insignificant_dtor] + +struct InsignificantDropPoint { + x: i32, + y: i32, +} + +impl Drop for InsignificantDropPoint { + fn drop(&mut self) {} +} + +struct GenericStruct(T, T); + +// No drop reordering is required as the elements of `t` implement insignificant drop +fn insignificant_drop_does_not_need_migration() { + let t = (InsignificantDropPoint { x: 4, y: 9 }, InsignificantDropPoint { x: 4, y: 9 }); + + let c = || { + let _t = t.0; + }; + + c(); +} + +// Generic struct whose elements don't have significant drops don't need drop reordering +fn generic_struct_with_insignificant_drop_does_not_need_migration() { + let t = + GenericStruct(InsignificantDropPoint { x: 4, y: 9 }, InsignificantDropPoint { x: 4, y: 9 }); + + let c = || { + let _t = t.0; + }; + + c(); +} + +fn main() { + insignificant_drop_does_not_need_migration(); + generic_struct_with_insignificant_drop_does_not_need_migration(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs new file mode 100644 index 000000000..ff5d28461 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs @@ -0,0 +1,10 @@ +// run-pass + +#![warn(rust_2021_incompatible_closure_captures)] + +fn main() { + if let a = "" { + //~^ WARNING: irrefutable `if let` pattern + drop(|_: ()| drop(a)); + } +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr new file mode 100644 index 000000000..36a80e694 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr @@ -0,0 +1,12 @@ +warning: irrefutable `if let` pattern + --> $DIR/issue-78720.rs:6:8 + | +LL | if let a = "" { + | ^^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-86753.rs b/tests/ui/closures/2229_closure_analysis/migrations/issue-86753.rs new file mode 100644 index 000000000..fce9cac62 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-86753.rs @@ -0,0 +1,34 @@ +// edition:2018 +// check-pass + +#![warn(rust_2021_compatibility)] + +use std::future::Future; + +struct Runtime; + +impl Runtime { + pub fn block_on(&self, _future: F) -> F::Output { + unimplemented!() + } +} + +pub fn http(_func: F) +where + F: Fn() -> Fut, + Fut: Future, +{ + let rt = Runtime {}; + let srv = rt.block_on(async move { serve(move || async move { unimplemented!() }) }); + let _ = || rt.block_on(async { srv }); +} + +pub struct Server { + _marker: std::marker::PhantomData, +} + +pub fn serve(_new_service: S) -> Server { + unimplemented!() +} + +fn main() { } diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs b/tests/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs new file mode 100644 index 000000000..ed8cb042b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs @@ -0,0 +1,37 @@ +// Test that rustc doesn't ICE as in #90024. +// check-pass +// edition=2018 + +#![warn(rust_2021_incompatible_closure_captures)] + +// Checks there's no double-subst into the generic args, otherwise we get OOB +// MCVE by @lqd +pub struct Graph { + _edges: E, + _nodes: N, + _ix: Vec, +} +fn graph() -> Graph { + todo!() +} +fn first_ice() { + let g = graph::(); + let _ = || g; +} + +// Checks that there is a subst into the fields, otherwise we get normalization error +// MCVE by @cuviper +use std::iter::Empty; +struct Foo { + data: Vec, +} +pub fn second_ice() { + let v = Foo::> { data: vec![] }; + + (|| v.data[0])(); +} + +pub fn main() { + first_ice(); + second_ice(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/macro.fixed b/tests/ui/closures/2229_closure_analysis/migrations/macro.fixed new file mode 100644 index 000000000..31fe494dc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/macro.fixed @@ -0,0 +1,25 @@ +// run-rustfix + +// See https://github.com/rust-lang/rust/issues/87955 + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn main() { + let a = (Foo(0), Foo(1)); + let _ = || { let _ = &a; dbg!(a.0) }; + //~^ ERROR: drop order + //~| NOTE: will only capture `a.0` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `a` to be fully captured +} +//~^ NOTE: dropped here diff --git a/tests/ui/closures/2229_closure_analysis/migrations/macro.rs b/tests/ui/closures/2229_closure_analysis/migrations/macro.rs new file mode 100644 index 000000000..0f0c49749 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/macro.rs @@ -0,0 +1,25 @@ +// run-rustfix + +// See https://github.com/rust-lang/rust/issues/87955 + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn main() { + let a = (Foo(0), Foo(1)); + let _ = || dbg!(a.0); + //~^ ERROR: drop order + //~| NOTE: will only capture `a.0` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `a` to be fully captured +} +//~^ NOTE: dropped here diff --git a/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr b/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr new file mode 100644 index 000000000..c17edce72 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/macro.stderr @@ -0,0 +1,22 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/macro.rs:19:13 + | +LL | let _ = || dbg!(a.0); + | ^^ --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` +... +LL | } + | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/macro.rs:5:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `a` to be fully captured + | +LL | let _ = || { let _ = &a; dbg!(a.0) }; + | +++++++++++++ + + +error: aborting due to previous error + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed b/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed new file mode 100644 index 000000000..ce8b60725 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed @@ -0,0 +1,47 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +// Test the two possible cases for automated migartion using rustfix +// - Closure contains a block i.e. `|| { .. };` +// - Closure contains just an expr `|| ..;` + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn closure_contains_block() { + let t = (Foo(0), Foo(0)); + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +fn closure_doesnt_contain_block() { + let t = (Foo(0), Foo(0)); + let c = || { let _ = &t; t.0 }; + //~^ ERROR: drop order + //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +fn main() { + closure_contains_block(); + closure_doesnt_contain_block(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs b/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs new file mode 100644 index 000000000..2237bebd7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs @@ -0,0 +1,46 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +// Test the two possible cases for automated migartion using rustfix +// - Closure contains a block i.e. `|| { .. };` +// - Closure contains just an expr `|| ..;` + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn closure_contains_block() { + let t = (Foo(0), Foo(0)); + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +fn closure_doesnt_contain_block() { + let t = (Foo(0), Foo(0)); + let c = || t.0; + //~^ ERROR: drop order + //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +fn main() { + closure_contains_block(); + closure_doesnt_contain_block(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr new file mode 100644 index 000000000..94526487e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr @@ -0,0 +1,41 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/migrations_rustfix.rs:19:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/migrations_rustfix.rs:2:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/migrations_rustfix.rs:33:13 + | +LL | let c = || t.0; + | ^^ --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t` to be fully captured + | +LL | let c = || { let _ = &t; t.0 }; + | +++++++++++++ + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed new file mode 100644 index 000000000..ff2244a8e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -0,0 +1,50 @@ +// run-rustfix +// needs-unwind + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here +#![feature(fn_traits)] +#![feature(never_type)] + +use std::panic; + +fn foo_diverges() -> ! { + panic!() +} + +fn assert_panics(f: F) +where + F: FnOnce(), +{ + let f = panic::AssertUnwindSafe(f); + let result = panic::catch_unwind(move || { + let _ = &f; + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `UnwindSafe` + //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f` to be fully captured + f.0() + //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` + }); + if let Ok(..) = result { + panic!("diverging function returned"); + } +} + +fn test_fn_ptr_panic(mut t: T) +where + T: Fn() -> !, +{ + let as_fn = >::call; + assert_panics(|| as_fn(&t, ())); + let as_fn_mut = >::call_mut; + assert_panics(|| as_fn_mut(&mut t, ())); + let as_fn_once = >::call_once; + assert_panics(|| as_fn_once(t, ())); +} + +fn main() { + test_fn_ptr_panic(foo_diverges); + test_fn_ptr_panic(foo_diverges as fn() -> !); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs new file mode 100644 index 000000000..52e96d013 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -0,0 +1,49 @@ +// run-rustfix +// needs-unwind + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here +#![feature(fn_traits)] +#![feature(never_type)] + +use std::panic; + +fn foo_diverges() -> ! { + panic!() +} + +fn assert_panics(f: F) +where + F: FnOnce(), +{ + let f = panic::AssertUnwindSafe(f); + let result = panic::catch_unwind(move || { + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `UnwindSafe` + //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f` to be fully captured + f.0() + //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` + }); + if let Ok(..) = result { + panic!("diverging function returned"); + } +} + +fn test_fn_ptr_panic(mut t: T) +where + T: Fn() -> !, +{ + let as_fn = >::call; + assert_panics(|| as_fn(&t, ())); + let as_fn_mut = >::call_mut; + assert_panics(|| as_fn_mut(&mut t, ())); + let as_fn_once = >::call_once; + assert_panics(|| as_fn_once(t, ())); +} + +fn main() { + test_fn_ptr_panic(foo_diverges); + test_fn_ptr_panic(foo_diverges as fn() -> !); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr new file mode 100644 index 000000000..e10898f98 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -0,0 +1,26 @@ +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/mir_calls_to_shims.rs:20:38 + | +LL | let result = panic::catch_unwind(move || { + | ^^^^^^^ + | | + | in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe` + | in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe` +... +LL | f.0() + | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/mir_calls_to_shims.rs:4:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `f` to be fully captured + | +LL ~ let result = panic::catch_unwind(move || { +LL + let _ = &f; + | + +error: aborting due to previous error + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed new file mode 100644 index 000000000..173dd2e2c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed @@ -0,0 +1,157 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +#[derive(Debug)] +struct Foo(String); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +impl Foo { + fn from(s: &str) -> Self { + Self(String::from(s)) + } +} + +struct S(#[allow(unused_tuple_struct_fields)] Foo); + +#[derive(Clone)] +struct T(#[allow(unused_tuple_struct_fields)] i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(Foo::from("Hello World")), T(0)) + } +} + +fn test_multi_issues() { + let f1 = U(S(Foo::from("foo")), T(0)); + let f2 = U(S(Foo::from("bar")), T(0)); + let c = || { + let _ = (&f1, &f2); + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_2 = f2.1; + //~^ NOTE: in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure + +fn test_capturing_all_disjoint_fields_individually() { + let f1 = U(S(Foo::from("foo")), T(0)); + let c = || { + let _ = &f1; + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_2 = f1.1; + }; + + let c_clone = c.clone(); + + c_clone(); +} + +struct U1(S, T, S); + +impl Clone for U1 { + fn clone(&self) -> Self { + U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))) + } +} + +fn test_capturing_several_disjoint_fields_individually_1() { + let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); + let c = || { + let _ = &f1; + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_2 = f1.2; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2` + }; + + let c_clone = c.clone(); + + c_clone(); +} + +fn test_capturing_several_disjoint_fields_individually_2() { + let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); + let c = || { + let _ = &f1; + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_1 = f1.1; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure + +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_multi_traits_issues() { + let mut f1 = 10; + let f1 = CustomInt(&mut f1 as *mut i32); + let fptr1 = SyncPointer(f1); + + let mut f2 = 10; + let fptr2 = SendPointer(&mut f2 as *mut i32); + thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + *fptr1.0.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` + *fptr2.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0` + } }); +} + +fn main() { + test_multi_issues(); + test_capturing_all_disjoint_fields_individually(); + test_capturing_several_disjoint_fields_individually_1(); + test_capturing_several_disjoint_fields_individually_2(); + test_multi_traits_issues(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs new file mode 100644 index 000000000..cfc4555ca --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs @@ -0,0 +1,153 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +#[derive(Debug)] +struct Foo(String); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +impl Foo { + fn from(s: &str) -> Self { + Self(String::from(s)) + } +} + +struct S(#[allow(unused_tuple_struct_fields)] Foo); + +#[derive(Clone)] +struct T(#[allow(unused_tuple_struct_fields)] i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(Foo::from("Hello World")), T(0)) + } +} + +fn test_multi_issues() { + let f1 = U(S(Foo::from("foo")), T(0)); + let f2 = U(S(Foo::from("bar")), T(0)); + let c = || { + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_2 = f2.1; + //~^ NOTE: in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure + +fn test_capturing_all_disjoint_fields_individually() { + let f1 = U(S(Foo::from("foo")), T(0)); + let c = || { + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_2 = f1.1; + }; + + let c_clone = c.clone(); + + c_clone(); +} + +struct U1(S, T, S); + +impl Clone for U1 { + fn clone(&self) -> Self { + U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))) + } +} + +fn test_capturing_several_disjoint_fields_individually_1() { + let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); + let c = || { + //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures] + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_2 = f1.2; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2` + }; + + let c_clone = c.clone(); + + c_clone(); +} + +fn test_capturing_several_disjoint_fields_individually_2() { + let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar"))); + let c = || { + //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + let _f_1 = f1.1; + //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure + +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_multi_traits_issues() { + let mut f1 = 10; + let f1 = CustomInt(&mut f1 as *mut i32); + let fptr1 = SyncPointer(f1); + + let mut f2 = 10; + let fptr2 = SendPointer(&mut f2 as *mut i32); + thread::spawn(move || unsafe { + //~^ ERROR: changes to closure capture in Rust 2021 + //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send` + //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + *fptr1.0.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` + *fptr2.0 = 20; + //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0` + }); +} + +fn main() { + test_multi_issues(); + test_capturing_all_disjoint_fields_individually(); + test_capturing_several_disjoint_fields_individually_1(); + test_capturing_several_disjoint_fields_individually_2(); + test_multi_traits_issues(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr new file mode 100644 index 000000000..efb264447 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -0,0 +1,118 @@ +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/multi_diagnostics.rs:37:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` +... +LL | let _f_1 = f1.0; + | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` +LL | +LL | let _f_2 = f2.1; + | ---- in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1` +... +LL | } + | - in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/multi_diagnostics.rs:2:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `f1`, `f2` to be fully captured + | +LL ~ let c = || { +LL + let _ = (&f1, &f2); + | + +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:56:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` +... +LL | let _f_1 = f1.0; + | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` + | + = note: for more information, see +help: add a dummy let to cause `f1` to be fully captured + | +LL ~ let c = || { +LL + let _ = &f1; + | + +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:81:13 + | +LL | let c = || { + | ^^ + | | + | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` + | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.2` does not implement `Clone` +... +LL | let _f_0 = f1.0; + | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` +LL | +LL | let _f_2 = f1.2; + | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2` + | + = note: for more information, see +help: add a dummy let to cause `f1` to be fully captured + | +LL ~ let c = || { +LL + let _ = &f1; + | + +error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements + --> $DIR/multi_diagnostics.rs:100:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `f1.0` does not implement `Clone` +... +LL | let _f_0 = f1.0; + | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0` +LL | +LL | let _f_1 = f1.1; + | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1` +... +LL | } + | - + | | + | in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure + | in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `f1` to be fully captured + | +LL ~ let c = || { +LL + let _ = &f1; + | + +error: changes to closure capture in Rust 2021 will affect which traits the closure implements + --> $DIR/multi_diagnostics.rs:133:19 + | +LL | thread::spawn(move || unsafe { + | ^^^^^^^ + | | + | in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send` + | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync` + | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send` +... +LL | *fptr1.0.0 = 20; + | ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` +LL | +LL | *fptr2.0 = 20; + | -------- in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0` + | + = note: for more information, see +help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + | +LL ~ thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { +LL | + ... +LL | +LL ~ } }); + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/no_migrations.rs b/tests/ui/closures/2229_closure_analysis/migrations/no_migrations.rs new file mode 100644 index 000000000..8b75e226a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/no_migrations.rs @@ -0,0 +1,81 @@ +// run-pass + +// Set of test cases that don't need migrations + +#![deny(rust_2021_incompatible_closure_captures)] + +// Copy types as copied by the closure instead of being moved into the closure +// Therefore their drop order isn't tied to the closure and won't be requiring any +// migrations. +fn test1_only_copy_types() { + let t = (0i32, 0i32); + + let c = || { + let _t = t.0; + }; + + c(); +} + +// Same as test1 but using a move closure +fn test2_only_copy_types_move_closure() { + let t = (0i32, 0i32); + + let c = move || { + println!("{}", t.0); + }; + + c(); +} + +// Don't need to migrate if captured by ref +fn test3_only_copy_types_move_closure() { + let t = (String::new(), String::new()); + + let c = || { + println!("{}", t.0); + }; + + c(); +} + +// Test migration analysis in case of Insignificant Drop + Non Drop aggregates. +// Note in this test the closure captures a non Drop type and therefore the variable +// is only captured by ref. +fn test4_insignificant_drop_non_drop_aggregate() { + let t = (String::new(), 0i32); + + let c = || { + let _t = t.1; + }; + + c(); +} + +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +// Test migration analysis in case of Significant Drop + Non Drop aggregates. +// Note in this test the closure captures a non Drop type and therefore the variable +// is only captured by ref. +fn test5_significant_drop_non_drop_aggregate() { + let t = (Foo(0), 0i32); + + let c = || { + let _t = t.1; + }; + + c(); +} + +fn main() { + test1_only_copy_types(); + test2_only_copy_types_move_closure(); + test3_only_copy_types_move_closure(); + test4_insignificant_drop_non_drop_aggregate(); + test5_significant_drop_non_drop_aggregate(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/old_name.rs b/tests/ui/closures/2229_closure_analysis/migrations/old_name.rs new file mode 100644 index 000000000..16e3cca7b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/old_name.rs @@ -0,0 +1,9 @@ +// check-pass + +// Ensure that the old name for `rust_2021_incompatible_closure_captures` is still +// accepted by the compiler + +#![allow(disjoint_capture_migration)] +//~^ WARN lint `disjoint_capture_migration` has been renamed + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/old_name.stderr b/tests/ui/closures/2229_closure_analysis/migrations/old_name.stderr new file mode 100644 index 000000000..47cb689fa --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/old_name.stderr @@ -0,0 +1,10 @@ +warning: lint `disjoint_capture_migration` has been renamed to `rust_2021_incompatible_closure_captures` + --> $DIR/old_name.rs:6:10 + | +LL | #![allow(disjoint_capture_migration)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rust_2021_incompatible_closure_captures` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/precise.fixed b/tests/ui/closures/2229_closure_analysis/migrations/precise.fixed new file mode 100644 index 000000000..7892a72c7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/precise.fixed @@ -0,0 +1,69 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +struct ConstainsDropField(Foo, Foo); + +// Test that lint is triggered if a path that implements Drop is not captured by move +fn test_precise_analysis_drop_paths_not_captured_by_move() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + let _t = &t.1; + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +struct S; +impl Drop for S { + fn drop(&mut self) {} +} + +struct T(S, S); +struct U(T, T); + +// Test precise analysis for the lint works with paths longer than one. +fn test_precise_analysis_long_path_missing() { + let u = U(T(S, S), T(S, S)); + + let c = || { + let _ = &u; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `u` to be fully captured + let _x = u.0.0; + //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0` + let _x = u.0.1; + //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1` + let _x = u.1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure + + +fn main() { + test_precise_analysis_drop_paths_not_captured_by_move(); + test_precise_analysis_long_path_missing(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/precise.rs b/tests/ui/closures/2229_closure_analysis/migrations/precise.rs new file mode 100644 index 000000000..f5e99002b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/precise.rs @@ -0,0 +1,67 @@ +// run-rustfix + +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +struct ConstainsDropField(Foo, Foo); + +// Test that lint is triggered if a path that implements Drop is not captured by move +fn test_precise_analysis_drop_paths_not_captured_by_move() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + let _t = &t.1; + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +struct S; +impl Drop for S { + fn drop(&mut self) {} +} + +struct T(S, S); +struct U(T, T); + +// Test precise analysis for the lint works with paths longer than one. +fn test_precise_analysis_long_path_missing() { + let u = U(T(S, S), T(S, S)); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `u` to be fully captured + let _x = u.0.0; + //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0` + let _x = u.0.1; + //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1` + let _x = u.1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure + + +fn main() { + test_precise_analysis_drop_paths_not_captured_by_move(); + test_precise_analysis_long_path_missing(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/precise.stderr b/tests/ui/closures/2229_closure_analysis/migrations/precise.stderr new file mode 100644 index 000000000..eff26a4d6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/precise.stderr @@ -0,0 +1,55 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/precise.rs:20:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/precise.rs:3:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/precise.rs:45:13 + | +LL | let c = || { + | ^^ +... +LL | let _x = u.0.0; + | ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0` +LL | +LL | let _x = u.0.1; + | ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1` +LL | +LL | let _x = u.1.0; + | ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0` +... +LL | } + | - + | | + | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure + | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure + | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `u` to be fully captured + | +LL ~ let c = || { +LL + let _ = &u; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs b/tests/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs new file mode 100644 index 000000000..587d71c40 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/precise_no_migrations.rs @@ -0,0 +1,104 @@ +// run-pass + +#![deny(rust_2021_incompatible_closure_captures)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +struct ConstainsDropField(Foo, Foo); + +// Test that if all paths starting at root variable that implement Drop are captured +// then it doesn't trigger the lint. +fn test_precise_analysis_simple_1() { + let t = (Foo(10), Foo(20), Foo(30)); + + let c = || { + let _t = t.0; + let _t = t.1; + let _t = t.2; + }; + + c(); +} + +// Test that if all paths starting at root variable that implement Drop are captured +// then it doesn't trigger the lint. +fn test_precise_analysis_simple_2() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + let _t = t.0; + let _t = t.1; + }; + + c(); +} + +#[derive(Debug)] +struct ContainsAndImplsDrop(Foo); +impl Drop for ContainsAndImplsDrop { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +// If a path isn't directly captured but requires Drop, then this tests that migrations aren't +// needed if the a parent to that path is captured. +fn test_precise_analysis_parent_captured_1() { + let t = ConstainsDropField(Foo(10), Foo(20)); + + let c = || { + let _t = t; + }; + + c(); +} + +// If a path isn't directly captured but requires Drop, then this tests that migrations aren't +// needed if the a parent to that path is captured. +fn test_precise_analysis_parent_captured_2() { + let t = ContainsAndImplsDrop(Foo(10)); + + let c = || { + let _t = t; + }; + + c(); +} + +struct S; +impl Drop for S { + fn drop(&mut self) {} +} + +struct T(S, S); +struct U(T, T); + +// Test that if the path is longer than just one element, precise analysis works correctly. +fn test_precise_analysis_long_path() { + let u = U(T(S, S), T(S, S)); + + let c = || { + let _x = u.0.0; + let _x = u.0.1; + let _x = u.1.0; + let _x = u.1.1; + }; + + c(); +} + +fn main() { + test_precise_analysis_simple_1(); + test_precise_analysis_simple_2(); + + test_precise_analysis_parent_captured_1(); + test_precise_analysis_parent_captured_2(); + + test_precise_analysis_long_path(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed b/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed new file mode 100644 index 000000000..e99dbb5ab --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed @@ -0,0 +1,229 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +// Test cases for types that implement a significant drop (user defined) + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +#[derive(Debug)] +struct ConstainsDropField(Foo, #[allow(unused_tuple_struct_fields)] Foo); + +// `t` needs Drop because one of its elements needs drop, +// therefore precise capture might affect drop ordering +fn test1_all_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + let t2 = (Foo(0), Foo(0)); + + let c = || { + let _ = (&t, &t1, &t2); + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + let _t1 = t1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0` + let _t2 = t2.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure + +// String implements drop and therefore should be migrated. +// But in this test cases, `t2` is completely captured and when it is dropped won't be affected +fn test2_only_precise_paths_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + let t2 = (Foo(0), Foo(0)); + + let c = || { + let _ = (&t, &t1); + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + let _t1 = t1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0` + let _t2 = t2; + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure + +// If a variable would've not been captured by value then it would've not been +// dropped with the closure and therefore doesn't need migration. +fn test3_only_by_value_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + println!("{:?}", t1.1); + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// The root variable might not implement drop themselves but some path starting +// at the root variable might implement Drop. +// +// If this path isn't captured we need to migrate for the root variable. +fn test4_type_contains_drop_need_migration() { + let t = ConstainsDropField(Foo(0), Foo(0)); + + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// Test migration analysis in case of Drop + Non Drop aggregates. +// Note we need migration here only because the non-copy (because Drop type) is captured, +// otherwise we won't need to, since we can get away with just by ref capture in that case. +fn test5_drop_non_drop_aggregate_need_migration() { + let t = (Foo(0), Foo(0), 0i32); + + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// Test migration analysis in case of Significant and Insignificant Drop aggregates. +fn test6_significant_insignificant_drop_aggregate_need_migration() { + let t = (Foo(0), String::new()); + + let c = || { + let _ = &t; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.1; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + +// Since we are using a move closure here, both `t` and `t1` get moved +// even though they are being used by ref inside the closure. +fn test7_move_closures_non_copy_types_might_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0), Foo(0)); + + let c = move || { + let _ = (&t1, &t); + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured + println!("{:?} {:?}", t1.1, t.1); + //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1` + //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure + + +fn test8_drop_order_and_blocks() { + { + let tuple = + (Foo(0), Foo(1)); + { + let c = || { + let _ = &tuple; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0` + }; + + c(); + } + //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure + } +} + +fn test9_drop_order_and_nested_closures() { + let tuple = + (Foo(0), Foo(1)); + let b = || { + let c = || { + let _ = &tuple; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0` + }; + + c(); + }; + //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure + + b(); +} + +// Test that we migrate if drop order of Vec would be affected if T is a significant drop type +fn test10_vec_of_significant_drop_type() { + + let tup = (Foo(0), vec![Foo(3)]); + + let _c = || { let _ = &tup; tup.0 }; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tup` to be fully captured + //~| NOTE: in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0` +} +//~^ NOTE: in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure + +fn main() { + test1_all_need_migration(); + test2_only_precise_paths_need_migration(); + test3_only_by_value_need_migration(); + test4_type_contains_drop_need_migration(); + test5_drop_non_drop_aggregate_need_migration(); + test6_significant_insignificant_drop_aggregate_need_migration(); + test7_move_closures_non_copy_types_might_need_migration(); + test8_drop_order_and_blocks(); + test9_drop_order_and_nested_closures(); + test10_vec_of_significant_drop_type(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.rs b/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.rs new file mode 100644 index 000000000..62a984c9e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.rs @@ -0,0 +1,220 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +// Test cases for types that implement a significant drop (user defined) + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +#[derive(Debug)] +struct ConstainsDropField(Foo, #[allow(unused_tuple_struct_fields)] Foo); + +// `t` needs Drop because one of its elements needs drop, +// therefore precise capture might affect drop ordering +fn test1_all_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + let t2 = (Foo(0), Foo(0)); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + let _t1 = t1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0` + let _t2 = t2.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure + +// String implements drop and therefore should be migrated. +// But in this test cases, `t2` is completely captured and when it is dropped won't be affected +fn test2_only_precise_paths_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + let t2 = (Foo(0), Foo(0)); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + let _t1 = t1.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0` + let _t2 = t2; + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure + +// If a variable would've not been captured by value then it would've not been +// dropped with the closure and therefore doesn't need migration. +fn test3_only_by_value_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0)); + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + println!("{:?}", t1.1); + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// The root variable might not implement drop themselves but some path starting +// at the root variable might implement Drop. +// +// If this path isn't captured we need to migrate for the root variable. +fn test4_type_contains_drop_need_migration() { + let t = ConstainsDropField(Foo(0), Foo(0)); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// Test migration analysis in case of Drop + Non Drop aggregates. +// Note we need migration here only because the non-copy (because Drop type) is captured, +// otherwise we won't need to, since we can get away with just by ref capture in that case. +fn test5_drop_non_drop_aggregate_need_migration() { + let t = (Foo(0), Foo(0), 0i32); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.0; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + +// Test migration analysis in case of Significant and Insignificant Drop aggregates. +fn test6_significant_insignificant_drop_aggregate_need_migration() { + let t = (Foo(0), String::new()); + + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t` to be fully captured + let _t = t.1; + //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + +// Since we are using a move closure here, both `t` and `t1` get moved +// even though they are being used by ref inside the closure. +fn test7_move_closures_non_copy_types_might_need_migration() { + let t = (Foo(0), Foo(0)); + let t1 = (Foo(0), Foo(0), Foo(0)); + + let c = move || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured + println!("{:?} {:?}", t1.1, t.1); + //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1` + //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + }; + + c(); +} +//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure +//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure + + +fn test8_drop_order_and_blocks() { + { + let tuple = + (Foo(0), Foo(1)); + { + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0` + }; + + c(); + } + //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure + } +} + +fn test9_drop_order_and_nested_closures() { + let tuple = + (Foo(0), Foo(1)); + let b = || { + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0` + }; + + c(); + }; + //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure + + b(); +} + +// Test that we migrate if drop order of Vec would be affected if T is a significant drop type +fn test10_vec_of_significant_drop_type() { + + let tup = (Foo(0), vec![Foo(3)]); + + let _c = || tup.0; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tup` to be fully captured + //~| NOTE: in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0` +} +//~^ NOTE: in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure + +fn main() { + test1_all_need_migration(); + test2_only_precise_paths_need_migration(); + test3_only_by_value_need_migration(); + test4_type_contains_drop_need_migration(); + test5_drop_non_drop_aggregate_need_migration(); + test6_significant_insignificant_drop_aggregate_need_migration(); + test7_move_closures_non_copy_types_might_need_migration(); + test8_drop_order_and_blocks(); + test9_drop_order_and_nested_closures(); + test10_vec_of_significant_drop_type(); +} diff --git a/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr b/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr new file mode 100644 index 000000000..54ad20f89 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr @@ -0,0 +1,214 @@ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:25:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0` +LL | +LL | let _t2 = t2.0; + | ---- in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0` +... +LL | } + | - + | | + | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure + | in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/significant_drop.rs:2:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured + | +LL ~ let c = || { +LL + let _ = (&t, &t1, &t2); + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:50:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0` +... +LL | } + | - + | | + | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t`, `t1` to be fully captured + | +LL ~ let c = || { +LL + let _ = (&t, &t1); + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:71:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:91:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:109:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:125:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.1; + | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` +... +LL | } + | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t` to be fully captured + | +LL ~ let c = || { +LL + let _ = &t; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:143:13 + | +LL | let c = move || { + | ^^^^^^^ +... +LL | println!("{:?} {:?}", t1.1, t.1); + | ---- --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1` + | | + | in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1` +... +LL | } + | - + | | + | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure + | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `t1`, `t` to be fully captured + | +LL ~ let c = move || { +LL + let _ = (&t1, &t); + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:163:21 + | +LL | let c = || { + | ^^ +... +LL | tuple.0; + | ------- in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0` +... +LL | } + | - in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `tuple` to be fully captured + | +LL ~ let c = || { +LL + let _ = &tuple; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:181:17 + | +LL | let c = || { + | ^^ +... +LL | tuple.0; + | ------- in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0` +... +LL | }; + | - in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `tuple` to be fully captured + | +LL ~ let c = || { +LL + let _ = &tuple; + | + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:201:18 + | +LL | let _c = || tup.0; + | ^^ ----- in Rust 2018, this closure captures all of `tup`, but in Rust 2021, it will only capture `tup.0` +... +LL | } + | - in Rust 2018, `tup` is dropped here, but in Rust 2021, only `tup.0` will be dropped here as part of the closure + | + = note: for more information, see +help: add a dummy let to cause `tup` to be fully captured + | +LL | let _c = || { let _ = &tup; tup.0 }; + | +++++++++++++++ + + +error: aborting due to 10 previous errors + diff --git a/tests/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs b/tests/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs new file mode 100644 index 000000000..39cf82053 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/migrations/unpin_no_migration.rs @@ -0,0 +1,13 @@ +//run-pass +#![deny(rust_2021_incompatible_closure_captures)] +#![allow(unused_must_use)] + +fn filter_try_fold( + predicate: &mut impl FnMut() -> bool, +) -> impl FnMut() -> bool + '_ { + move || predicate() +} + +fn main() { + filter_try_fold(&mut || true); +} diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.rs b/tests/ui/closures/2229_closure_analysis/move_closure.rs new file mode 100644 index 000000000..b542fa243 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/move_closure.rs @@ -0,0 +1,222 @@ +// edition:2021 + +// Test that move closures drop derefs with `capture_disjoint_fields` enabled. + +#![feature(rustc_attrs)] + +fn simple_move_closure() { + struct S(String); + struct T(S); + + let t = T(S("s".into())); + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + t.0.0 = "new S".into(); + //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow + //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue + }; + c(); +} + +// Test move closure use reborrows when using references +fn simple_ref() { + let mut s = 10; + let ref_s = &mut s; + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + *ref_s += 10; + //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow + //~| NOTE: Min Capture ref_s[] -> ByValue + }; + c(); +} + +// Test move closure use reborrows when using references +fn struct_contains_ref_to_another_struct_1() { + struct S(String); + struct T<'a>(&'a mut S); + + let mut s = S("s".into()); + let t = T(&mut s); + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + t.0.0 = "new s".into(); + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow + //~| NOTE: Min Capture t[(0, 0)] -> ByValue + }; + + c(); +} + +// Test that we can use reborrows to read data of Copy types +// i.e. without truncating derefs +fn struct_contains_ref_to_another_struct_2() { + struct S(i32); + struct T<'a>(&'a S); + + let s = S(0); + let t = T(&s); + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let _t = t.0.0; + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(0, 0)] -> ByValue + }; + + c(); +} + +// Test that we can use truncate to move out of !Copy types +fn struct_contains_ref_to_another_struct_3() { + struct S(String); + struct T<'a>(&'a S); + + let s = S("s".into()); + let t = T(&s); + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let _t = t.0.0; + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue + //~| NOTE: Min Capture t[(0, 0)] -> ByValue + }; + + c(); +} + +// Test that derefs of box are truncated in move closures +fn truncate_box_derefs() { + struct S(i32); + + + // Content within the box is moved within the closure + let b = Box::new(S(10)); + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let _t = b.0; + //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture b[] -> ByValue + }; + + c(); + + // Content within the box is used by a shared ref and the box is the root variable + let b = Box::new(S(10)); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", b.0); + //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture b[] -> ByValue + }; + + c(); + + // Content within the box is used by a shared ref and the box is not the root variable + let b = Box::new(S(10)); + let t = (0, b); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + move || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", t.1.0); + //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(1, 0)] -> ByValue + }; +} + +struct Foo { x: i32 } + +// Ensure that even in move closures, if the data is not owned by the root variable +// then we don't truncate the derefs or a ByValue capture, rather do a reborrow +fn box_mut_1() { + let mut foo = Foo { x: 0 } ; + + let p_foo = &mut foo; + let box_p_foo = Box::new(p_foo); + + let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| First Pass analysis includes: + //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow + //~| Min Capture analysis includes: + //~| NOTE: Min Capture box_p_foo[] -> ByValue +} + +// Ensure that even in move closures, if the data is not owned by the root variable +// then we don't truncate the derefs or a ByValue capture, rather do a reborrow +fn box_mut_2() { + let foo = Foo { x: 0 } ; + + let mut box_foo = Box::new(foo); + let p_foo = &mut box_foo; + + let c = #[rustc_capture_analysis] move || p_foo.x += 10; + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| First Pass analysis includes: + //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow + //~| Min Capture analysis includes: + //~| NOTE: Min Capture p_foo[] -> ByValue +} + +// Test that move closures can take ownership of Copy type +fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { + let x = 10; + + let c = #[rustc_capture_analysis] move || x; + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| First Pass analysis includes: + //~| NOTE: Capturing x[] -> ImmBorrow + //~| Min Capture analysis includes: + //~| NOTE: Min Capture x[] -> ByValue + + c +} + +fn main() { + simple_move_closure(); + simple_ref(); + struct_contains_ref_to_another_struct_1(); + struct_contains_ref_to_another_struct_2(); + struct_contains_ref_to_another_struct_3(); + truncate_box_derefs(); + box_mut_2(); + box_mut_1(); +} diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.stderr b/tests/ui/closures/2229_closure_analysis/move_closure.stderr new file mode 100644 index 000000000..fd80e05c6 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/move_closure.stderr @@ -0,0 +1,462 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:12:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:30:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:51:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:74:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:96:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:117:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:133:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:150:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:172:13 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:189:13 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/move_closure.rs:202:13 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:202:39 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^^^^^^^^^ + | +note: Capturing x[] -> ImmBorrow + --> $DIR/move_closure.rs:202:47 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:202:39 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^^^^^^^^^ + | +note: Min Capture x[] -> ByValue + --> $DIR/move_closure.rs:202:47 + | +LL | let c = #[rustc_capture_analysis] move || x; + | ^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:15:5 + | +LL | / move || { +LL | | +LL | | +LL | | t.0.0 = "new S".into(); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),(0, 0)] -> MutBorrow + --> $DIR/move_closure.rs:18:9 + | +LL | t.0.0 = "new S".into(); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:15:5 + | +LL | / move || { +LL | | +LL | | +LL | | t.0.0 = "new S".into(); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0),(0, 0)] -> ByValue + --> $DIR/move_closure.rs:18:9 + | +LL | t.0.0 = "new S".into(); + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:33:5 + | +LL | / move || { +LL | | +LL | | +LL | | *ref_s += 10; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing ref_s[Deref] -> MutBorrow + --> $DIR/move_closure.rs:36:9 + | +LL | *ref_s += 10; + | ^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:33:5 + | +LL | / move || { +LL | | +LL | | +LL | | *ref_s += 10; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture ref_s[] -> ByValue + --> $DIR/move_closure.rs:36:9 + | +LL | *ref_s += 10; + | ^^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:54:5 + | +LL | / move || { +LL | | +LL | | +LL | | t.0.0 = "new s".into(); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow + --> $DIR/move_closure.rs:57:9 + | +LL | t.0.0 = "new s".into(); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:54:5 + | +LL | / move || { +LL | | +LL | | +LL | | t.0.0 = "new s".into(); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ByValue + --> $DIR/move_closure.rs:57:9 + | +LL | t.0.0 = "new s".into(); + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:77:5 + | +LL | / move || { +LL | | +LL | | +LL | | let _t = t.0.0; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:80:18 + | +LL | let _t = t.0.0; + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:77:5 + | +LL | / move || { +LL | | +LL | | +LL | | let _t = t.0.0; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ByValue + --> $DIR/move_closure.rs:80:18 + | +LL | let _t = t.0.0; + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:99:5 + | +LL | / move || { +LL | | +LL | | +LL | | let _t = t.0.0; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue + --> $DIR/move_closure.rs:102:18 + | +LL | let _t = t.0.0; + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:99:5 + | +LL | / move || { +LL | | +LL | | +LL | | let _t = t.0.0; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ByValue + --> $DIR/move_closure.rs:102:18 + | +LL | let _t = t.0.0; + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:120:5 + | +LL | / move || { +LL | | +LL | | +LL | | let _t = b.0; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing b[Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:123:18 + | +LL | let _t = b.0; + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:120:5 + | +LL | / move || { +LL | | +LL | | +LL | | let _t = b.0; +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture b[] -> ByValue + --> $DIR/move_closure.rs:123:18 + | +LL | let _t = b.0; + | ^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:136:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", b.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing b[Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:139:24 + | +LL | println!("{}", b.0); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:136:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", b.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture b[] -> ByValue + --> $DIR/move_closure.rs:139:24 + | +LL | println!("{}", b.0); + | ^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:153:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", t.1.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow + --> $DIR/move_closure.rs:156:24 + | +LL | println!("{}", t.1.0); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:153:5 + | +LL | / move || { +LL | | +LL | | +LL | | println!("{}", t.1.0); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(1, 0)] -> ByValue + --> $DIR/move_closure.rs:156:24 + | +LL | println!("{}", t.1.0); + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:172:39 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow + --> $DIR/move_closure.rs:172:47 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:172:39 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: Min Capture box_p_foo[] -> ByValue + --> $DIR/move_closure.rs:172:47 + | +LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; + | ^^^^^^^^^^^ + +error: First Pass analysis includes: + --> $DIR/move_closure.rs:189:39 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow + --> $DIR/move_closure.rs:189:47 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/move_closure.rs:189:39 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: Min Capture p_foo[] -> ByValue + --> $DIR/move_closure.rs:189:47 + | +LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; + | ^^^^^^^ + +error: aborting due to 33 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs new file mode 100644 index 000000000..a8a2acfa7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs @@ -0,0 +1,39 @@ +// edition:2021 + +#![feature(rustc_attrs)] +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + // Only paths that appears within the closure that directly start off + // a variable defined outside the closure are captured. + // + // Therefore `w.p` is captured + // Note that `wp.x` doesn't start off a variable defined outside the closure. + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let wp = &w.p; + //~^ NOTE: Capturing w[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture w[(0, 0)] -> ImmBorrow + println!("{}", wp.x); + }; + + // Since `c` captures `w.p` by an ImmBorrow, `w.p.y` can't be mutated. + let py = &mut w.p.y; + c(); + + *py = 20 +} diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr new file mode 100644 index 000000000..29ad1c591 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/multilevel-path-1.rs:22:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/multilevel-path-1.rs:25:5 + | +LL | / || { +LL | | +LL | | +LL | | let wp = &w.p; +... | +LL | | println!("{}", wp.x); +LL | | }; + | |_____^ + | +note: Capturing w[(0, 0)] -> ImmBorrow + --> $DIR/multilevel-path-1.rs:28:19 + | +LL | let wp = &w.p; + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/multilevel-path-1.rs:25:5 + | +LL | / || { +LL | | +LL | | +LL | | let wp = &w.p; +... | +LL | | println!("{}", wp.x); +LL | | }; + | |_____^ + | +note: Min Capture w[(0, 0)] -> ImmBorrow + --> $DIR/multilevel-path-1.rs:28:19 + | +LL | let wp = &w.p; + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs new file mode 100644 index 000000000..e21fe318c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs @@ -0,0 +1,33 @@ +// edition:2021 + +#![feature(rustc_attrs)] +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", w.p.x); + //~^ NOTE: Capturing w[(0, 0),(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow + }; + + // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`. + let py = &mut w.p.y; + c(); + + *py = 20 +} diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr new file mode 100644 index 000000000..929cba113 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/multilevel-path-2.rs:17:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/multilevel-path-2.rs:20:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", w.p.x); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing w[(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/multilevel-path-2.rs:23:24 + | +LL | println!("{}", w.p.x); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/multilevel-path-2.rs:20:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", w.p.x); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow + --> $DIR/multilevel-path-2.rs:23:24 + | +LL | println!("{}", w.p.x); + | ^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.rs b/tests/ui/closures/2229_closure_analysis/nested-closure.rs new file mode 100644 index 000000000..22eae744b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.rs @@ -0,0 +1,53 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +struct Point { + x: i32, + y: i32, +} + +// This testcase ensures that nested closures are handles properly +// - The nested closure is analyzed first. +// - The capture kind of the nested closure is accounted for by the enclosing closure +// - Any captured path by the nested closure that starts off a local variable in the enclosing +// closure is not listed as a capture of the enclosing closure. + +fn main() { + let mut p = Point { x: 5, y: 20 }; + + let mut c1 = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", p.x); + //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow + let incr = 10; + let mut c2 = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || p.y += incr; + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + //~| NOTE: Capturing p[(1, 0)] -> MutBorrow + //~| NOTE: Capturing incr[] -> ImmBorrow + //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow + //~| NOTE: Min Capture incr[] -> ImmBorrow + //~| NOTE: Capturing p[(1, 0)] -> MutBorrow + //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow + c2(); + println!("{}", p.y); + //~^ NOTE: Capturing p[(1, 0)] -> ImmBorrow + }; + + c1(); + + let px = &p.x; + + println!("{}", px); + + c1(); +} diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr new file mode 100644 index 000000000..a50d0c6a1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr @@ -0,0 +1,106 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/nested-closure.rs:19:18 + | +LL | let mut c1 = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/nested-closure.rs:29:22 + | +LL | let mut c2 = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/nested-closure.rs:32:9 + | +LL | || p.y += incr; + | ^^^^^^^^^^^^^^ + | +note: Capturing p[(1, 0)] -> MutBorrow + --> $DIR/nested-closure.rs:32:12 + | +LL | || p.y += incr; + | ^^^ +note: Capturing incr[] -> ImmBorrow + --> $DIR/nested-closure.rs:32:19 + | +LL | || p.y += incr; + | ^^^^ + +error: Min Capture analysis includes: + --> $DIR/nested-closure.rs:32:9 + | +LL | || p.y += incr; + | ^^^^^^^^^^^^^^ + | +note: Min Capture p[(1, 0)] -> MutBorrow + --> $DIR/nested-closure.rs:32:12 + | +LL | || p.y += incr; + | ^^^ +note: Min Capture incr[] -> ImmBorrow + --> $DIR/nested-closure.rs:32:19 + | +LL | || p.y += incr; + | ^^^^ + +error: First Pass analysis includes: + --> $DIR/nested-closure.rs:22:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", p.x); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> ImmBorrow + --> $DIR/nested-closure.rs:25:24 + | +LL | println!("{}", p.x); + | ^^^ +note: Capturing p[(1, 0)] -> MutBorrow + --> $DIR/nested-closure.rs:32:12 + | +LL | || p.y += incr; + | ^^^ +note: Capturing p[(1, 0)] -> ImmBorrow + --> $DIR/nested-closure.rs:42:24 + | +LL | println!("{}", p.y); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/nested-closure.rs:22:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", p.x); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[(0, 0)] -> ImmBorrow + --> $DIR/nested-closure.rs:25:24 + | +LL | println!("{}", p.x); + | ^^^ +note: Min Capture p[(1, 0)] -> MutBorrow + --> $DIR/nested-closure.rs:32:12 + | +LL | || p.y += incr; + | ^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs new file mode 100644 index 000000000..e7edc0bbc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs @@ -0,0 +1,34 @@ +// edition:2021 + +#![feature(rustc_attrs)] +#![allow(unused)] +#![allow(dead_code)] + +struct Int(i32); +struct B<'a>(&'a i32); + +const I : Int = Int(0); +const REF_I : &'static Int = &I; + + +struct MyStruct<'a> { + a: &'static Int, + b: B<'a>, +} + +fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { + let c = #[rustc_capture_analysis] || drop(&m.a.0); + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + //~| ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow + c +} + +fn main() { + let t = 0; + let s = MyStruct { a: REF_I, b: B(&t) }; + let _ = foo(&s); +} diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr new file mode 100644 index 000000000..87d5d5bee --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr @@ -0,0 +1,36 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/edge_case.rs:20:13 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/edge_case.rs:20:39 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^^^^^^^^^^^ + | +note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow + --> $DIR/edge_case.rs:20:48 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/edge_case.rs:20:39 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^^^^^^^^^^^ + | +note: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow + --> $DIR/edge_case.rs:20:48 + | +LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); + | ^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs new file mode 100644 index 000000000..033fd6f17 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs @@ -0,0 +1,27 @@ +// edition:2021 +// run-pass + +#![allow(unused)] +#![allow(dead_code)] + +struct Int(i32); +struct B<'a>(&'a i32); + +const I : Int = Int(0); +const REF_I : &'static Int = &I; + +struct MyStruct<'a> { + a: &'static Int, + b: B<'a>, +} + +fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { + let c = || drop(&m.a.0); + c +} + +fn main() { + let t = 0; + let s = MyStruct { a: REF_I, b: B(&t) }; + let _ = foo(&s); +} diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs new file mode 100644 index 000000000..0c1031931 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs @@ -0,0 +1,33 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +struct Point { + x: f32, + y: f32, +} + +struct Pentagon { + points: [Point; 5], +} + +fn main() { + let p1 = Point { x: 10.0, y: 10.0 }; + let p2 = Point { x: 7.5, y: 12.5 }; + let p3 = Point { x: 15.0, y: 15.0 }; + let p4 = Point { x: 12.5, y: 12.5 }; + let p5 = Point { x: 20.0, y: 10.0 }; + + let pent = Pentagon { points: [p1, p2, p3, p4, p5] }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", pent.points[5].x); + //~^ NOTE: Capturing pent[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture pent[(0, 0)] -> ImmBorrow + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr new file mode 100644 index 000000000..124b7bf6f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr @@ -0,0 +1,48 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/path-with-array-access.rs:23:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/path-with-array-access.rs:26:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", pent.points[5].x); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing pent[(0, 0)] -> ImmBorrow + --> $DIR/path-with-array-access.rs:29:24 + | +LL | println!("{}", pent.points[5].x); + | ^^^^^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/path-with-array-access.rs:26:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", pent.points[5].x); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture pent[(0, 0)] -> ImmBorrow + --> $DIR/path-with-array-access.rs:29:24 + | +LL | println!("{}", pent.points[5].x); + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs new file mode 100644 index 000000000..2f8cddc06 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs @@ -0,0 +1,101 @@ +// edition:2021 + +// Tests that in cases where we individually capture all the fields of a type, +// we still drop them in the order they would have been dropped in the 2018 edition. + +// NOTE: It is *critical* that the order of the min capture NOTES in the stderr output +// does *not* change! + +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct HasDrop; +impl Drop for HasDrop { + fn drop(&mut self) { + println!("dropped"); + } +} + +fn test_one() { + let a = (HasDrop, HasDrop); + let b = (HasDrop, HasDrop); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: Min Capture analysis includes: + //~| ERROR + println!("{:?}", a.0); + //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow + //~| NOTE + println!("{:?}", a.1); + //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow + //~| NOTE + + println!("{:?}", b.0); + //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow + //~| NOTE + println!("{:?}", b.1); + //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow + //~| NOTE + }; +} + +fn test_two() { + let a = (HasDrop, HasDrop); + let b = (HasDrop, HasDrop); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: Min Capture analysis includes: + //~| ERROR + println!("{:?}", a.1); + //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow + //~| NOTE + println!("{:?}", a.0); + //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow + //~| NOTE + + println!("{:?}", b.1); + //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow + //~| NOTE + println!("{:?}", b.0); + //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow + //~| NOTE + }; +} + +fn test_three() { + let a = (HasDrop, HasDrop); + let b = (HasDrop, HasDrop); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: Min Capture analysis includes: + //~| ERROR + println!("{:?}", b.1); + //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow + //~| NOTE + println!("{:?}", a.1); + //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow + //~| NOTE + println!("{:?}", a.0); + //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow + //~| NOTE + + println!("{:?}", b.0); + //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow + //~| NOTE + }; +} + +fn main() { + test_one(); + test_two(); + test_three(); +} diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr new file mode 100644 index 000000000..2d1dc8727 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr @@ -0,0 +1,228 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/preserve_field_drop_order.rs:23:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/preserve_field_drop_order.rs:49:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/preserve_field_drop_order.rs:75:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/preserve_field_drop_order.rs:26:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", a.0); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:29:26 + | +LL | println!("{:?}", a.0); + | ^^^ +note: Capturing a[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:32:26 + | +LL | println!("{:?}", a.1); + | ^^^ +note: Capturing b[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:36:26 + | +LL | println!("{:?}", b.0); + | ^^^ +note: Capturing b[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:39:26 + | +LL | println!("{:?}", b.1); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/preserve_field_drop_order.rs:26:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", a.0); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:29:26 + | +LL | println!("{:?}", a.0); + | ^^^ +note: Min Capture a[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:32:26 + | +LL | println!("{:?}", a.1); + | ^^^ +note: Min Capture b[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:36:26 + | +LL | println!("{:?}", b.0); + | ^^^ +note: Min Capture b[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:39:26 + | +LL | println!("{:?}", b.1); + | ^^^ + +error: First Pass analysis includes: + --> $DIR/preserve_field_drop_order.rs:52:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", a.1); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing a[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:55:26 + | +LL | println!("{:?}", a.1); + | ^^^ +note: Capturing a[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:58:26 + | +LL | println!("{:?}", a.0); + | ^^^ +note: Capturing b[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:62:26 + | +LL | println!("{:?}", b.1); + | ^^^ +note: Capturing b[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:65:26 + | +LL | println!("{:?}", b.0); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/preserve_field_drop_order.rs:52:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", a.1); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture a[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:58:26 + | +LL | println!("{:?}", a.0); + | ^^^ +note: Min Capture a[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:55:26 + | +LL | println!("{:?}", a.1); + | ^^^ +note: Min Capture b[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:65:26 + | +LL | println!("{:?}", b.0); + | ^^^ +note: Min Capture b[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:62:26 + | +LL | println!("{:?}", b.1); + | ^^^ + +error: First Pass analysis includes: + --> $DIR/preserve_field_drop_order.rs:78:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", b.1); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing b[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:81:26 + | +LL | println!("{:?}", b.1); + | ^^^ +note: Capturing a[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:84:26 + | +LL | println!("{:?}", a.1); + | ^^^ +note: Capturing a[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:87:26 + | +LL | println!("{:?}", a.0); + | ^^^ +note: Capturing b[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:91:26 + | +LL | println!("{:?}", b.0); + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/preserve_field_drop_order.rs:78:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{:?}", b.1); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture b[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:91:26 + | +LL | println!("{:?}", b.0); + | ^^^ +note: Min Capture b[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:81:26 + | +LL | println!("{:?}", b.1); + | ^^^ +note: Min Capture a[(0, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:87:26 + | +LL | println!("{:?}", a.0); + | ^^^ +note: Min Capture a[(1, 0)] -> ImmBorrow + --> $DIR/preserve_field_drop_order.rs:84:26 + | +LL | println!("{:?}", a.1); + | ^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs new file mode 100644 index 000000000..1cae776dd --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs @@ -0,0 +1,58 @@ +// run-pass +// check-run-results +// revisions: twenty_eighteen twenty_twentyone +// [twenty_eighteen]compile-flags: --edition 2018 +// [twenty_twentyone]compile-flags: --edition 2021 + +#[derive(Debug)] +struct Dropable(&'static str); + +impl Drop for Dropable { + fn drop(&mut self) { + println!("Dropping {}", self.0) + } +} + +#[derive(Debug)] +struct A { + x: Dropable, + y: Dropable, +} + +#[derive(Debug)] +struct B { + c: A, + d: A, +} + +#[derive(Debug)] +struct R<'a> { + c: &'a A, + d: &'a A, +} + +fn main() { + let a = A { x: Dropable("x"), y: Dropable("y") }; + + let c = move || println!("{:?} {:?}", a.y, a.x); + + c(); + + let b = B { + c: A { x: Dropable("b.c.x"), y: Dropable("b.c.y") }, + d: A { x: Dropable("b.d.x"), y: Dropable("b.d.y") }, + }; + + let d = move || println!("{:?} {:?} {:?} {:?}", b.d.y, b.d.x, b.c.y, b.c.x); + + d(); + + let r = R { + c: &A { x: Dropable("r.c.x"), y: Dropable("r.c.y") }, + d: &A { x: Dropable("r.d.x"), y: Dropable("r.d.y") }, + }; + + let e = move || println!("{:?} {:?} {:?} {:?}", r.d.y, r.d.x, r.c.y, r.c.x); + + e(); +} diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_eighteen.run.stdout b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_eighteen.run.stdout new file mode 100644 index 000000000..557d047c1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_eighteen.run.stdout @@ -0,0 +1,13 @@ +Dropable("y") Dropable("x") +Dropable("b.d.y") Dropable("b.d.x") Dropable("b.c.y") Dropable("b.c.x") +Dropable("r.d.y") Dropable("r.d.x") Dropable("r.c.y") Dropable("r.c.x") +Dropping r.d.x +Dropping r.d.y +Dropping r.c.x +Dropping r.c.y +Dropping b.c.x +Dropping b.c.y +Dropping b.d.x +Dropping b.d.y +Dropping x +Dropping y diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_twentyone.run.stdout b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_twentyone.run.stdout new file mode 100644 index 000000000..557d047c1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.twenty_twentyone.run.stdout @@ -0,0 +1,13 @@ +Dropable("y") Dropable("x") +Dropable("b.d.y") Dropable("b.d.x") Dropable("b.c.y") Dropable("b.c.x") +Dropable("r.d.y") Dropable("r.d.x") Dropable("r.c.y") Dropable("r.c.x") +Dropping r.d.x +Dropping r.d.y +Dropping r.c.x +Dropping r.c.y +Dropping b.c.x +Dropping b.c.y +Dropping b.d.x +Dropping b.d.y +Dropping x +Dropping y diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/repr_packed.rs new file mode 100644 index 000000000..f23670f63 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.rs @@ -0,0 +1,101 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +// `u8` aligned at a byte and are unaffected by repr(packed). +// Therefore we can precisely (and safely) capture references to both the fields. +fn test_alignment_not_affected() { + #[repr(packed)] + struct Foo { x: u8, y: u8 } + + let mut foo = Foo { x: 0, y: 0 }; + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let z1: &u8 = &foo.x; + //~^ NOTE: Capturing foo[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture foo[(0, 0)] -> ImmBorrow + let z2: &mut u8 = &mut foo.y; + //~^ NOTE: Capturing foo[(1, 0)] -> MutBorrow + //~| NOTE: Min Capture foo[(1, 0)] -> MutBorrow + + *z2 = 42; + + println!("({}, {})", z1, z2); + }; + + c(); +} + +// `String`, `u16` are not aligned at a one byte boundary and are thus affected by repr(packed). +// +// Here we test that the closure doesn't capture a reference point to `foo.x` but +// rather capture `foo` entirely. +fn test_alignment_affected() { + #[repr(packed)] + struct Foo { x: String, y: u16 } + + let mut foo = Foo { x: String::new(), y: 0 }; + + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let z1: &String = &foo.x; + //~^ NOTE: Capturing foo[] -> ImmBorrow + let z2: &mut u16 = &mut foo.y; + //~^ NOTE: Capturing foo[] -> MutBorrow + //~| NOTE: Min Capture foo[] -> MutBorrow + + + *z2 = 42; + + println!("({}, {})", z1, z2); + }; + + c(); +} + +// Given how the closure desugaring is implemented (at least at the time of writing this test), +// we don't need to truncate the captured path to a reference into a packed-struct if the field +// being referenced will be moved into the closure, since it's safe to move out a field from a +// packed-struct. +// +// However to avoid surprises for the user, or issues when the closure is +// inlined we will truncate the capture to access just the struct regardless of if the field +// might get moved into the closure. +fn test_truncation_when_ref_and_move() { + #[repr(packed)] + struct Foo { x: String } + + let mut foo = Foo { x: String::new() }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{}", foo.x); + //~^ NOTE: Capturing foo[] -> ImmBorrow + //~| NOTE: Min Capture foo[] -> ByValue + //~| NOTE: foo[] used here + let _z = foo.x; + //~^ NOTE: Capturing foo[(0, 0)] -> ByValue + //~| NOTE: foo[] captured as ByValue here + }; + + c(); +} + +fn main() { + test_truncation_when_ref_and_move(); + test_alignment_affected(); + test_alignment_not_affected(); +} diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr new file mode 100644 index 000000000..580061ebc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr @@ -0,0 +1,161 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/repr_packed.rs:13:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/repr_packed.rs:44:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/repr_packed.rs:79:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/repr_packed.rs:16:5 + | +LL | / || { +LL | | +LL | | +LL | | let z1: &u8 = &foo.x; +... | +LL | | println!("({}, {})", z1, z2); +LL | | }; + | |_____^ + | +note: Capturing foo[(0, 0)] -> ImmBorrow + --> $DIR/repr_packed.rs:19:24 + | +LL | let z1: &u8 = &foo.x; + | ^^^^^ +note: Capturing foo[(1, 0)] -> MutBorrow + --> $DIR/repr_packed.rs:22:32 + | +LL | let z2: &mut u8 = &mut foo.y; + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/repr_packed.rs:16:5 + | +LL | / || { +LL | | +LL | | +LL | | let z1: &u8 = &foo.x; +... | +LL | | println!("({}, {})", z1, z2); +LL | | }; + | |_____^ + | +note: Min Capture foo[(0, 0)] -> ImmBorrow + --> $DIR/repr_packed.rs:19:24 + | +LL | let z1: &u8 = &foo.x; + | ^^^^^ +note: Min Capture foo[(1, 0)] -> MutBorrow + --> $DIR/repr_packed.rs:22:32 + | +LL | let z2: &mut u8 = &mut foo.y; + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/repr_packed.rs:47:5 + | +LL | / || { +LL | | +LL | | +LL | | let z1: &String = &foo.x; +... | +LL | | println!("({}, {})", z1, z2); +LL | | }; + | |_____^ + | +note: Capturing foo[] -> ImmBorrow + --> $DIR/repr_packed.rs:50:28 + | +LL | let z1: &String = &foo.x; + | ^^^^^ +note: Capturing foo[] -> MutBorrow + --> $DIR/repr_packed.rs:52:33 + | +LL | let z2: &mut u16 = &mut foo.y; + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/repr_packed.rs:47:5 + | +LL | / || { +LL | | +LL | | +LL | | let z1: &String = &foo.x; +... | +LL | | println!("({}, {})", z1, z2); +LL | | }; + | |_____^ + | +note: Min Capture foo[] -> MutBorrow + --> $DIR/repr_packed.rs:52:33 + | +LL | let z2: &mut u16 = &mut foo.y; + | ^^^^^ + +error: First Pass analysis includes: + --> $DIR/repr_packed.rs:82:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", foo.x); +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing foo[] -> ImmBorrow + --> $DIR/repr_packed.rs:85:24 + | +LL | println!("{}", foo.x); + | ^^^^^ +note: Capturing foo[(0, 0)] -> ByValue + --> $DIR/repr_packed.rs:89:18 + | +LL | let _z = foo.x; + | ^^^^^ + +error: Min Capture analysis includes: + --> $DIR/repr_packed.rs:82:5 + | +LL | / || { +LL | | +LL | | +LL | | println!("{}", foo.x); +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture foo[] -> ByValue + --> $DIR/repr_packed.rs:85:24 + | +LL | println!("{}", foo.x); + | ^^^^^ foo[] used here +... +LL | let _z = foo.x; + | ^^^^^ foo[] captured as ByValue here + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/box.rs b/tests/ui/closures/2229_closure_analysis/run_pass/box.rs new file mode 100644 index 000000000..73aca288f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/box.rs @@ -0,0 +1,92 @@ +// edition:2021 +// run-pass + +// Test precise capture when using boxes + +struct MetaData { x: String, name: String } +struct Data { m: MetaData } +struct BoxedData(Box); +struct EvenMoreBoxedData(Box); + +// Mutate disjoint paths, one inside one outside the closure +fn box_1() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let mut c = || { + e.0.0.m.x = format!("not-x"); + }; + + e.0.0.m.name = format!("not-name"); + c(); +} + +// Mutate a path inside the closure and read a disjoint path outside the closure +fn box_2() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let mut c = || { + e.0.0.m.x = format!("not-x"); + }; + + println!("{}", e.0.0.m.name); + c(); +} + +// Read a path inside the closure and mutate a disjoint path outside the closure +fn box_3() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let mut e = EvenMoreBoxedData(Box::new(b)); + + let c = || { + println!("{}", e.0.0.m.name); + }; + + e.0.0.m.x = format!("not-x"); + c(); +} + +// Read disjoint paths, one inside the closure and one outside the closure. +fn box_4() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let e = EvenMoreBoxedData(Box::new(b)); + + let c = || { + println!("{}", e.0.0.m.name); + }; + + println!("{}", e.0.0.m.x); + c(); +} + +// Read the same path, once inside the closure and once outside the closure. +fn box_5() { + let m = MetaData { x: format!("x"), name: format!("name") }; + let d = Data { m }; + let b = BoxedData(Box::new(d)); + let e = EvenMoreBoxedData(Box::new(b)); + + let c = || { + println!("{}", e.0.0.m.name); + }; + + println!("{}", e.0.0.m.name); + c(); +} + +fn main() { + box_1(); + box_2(); + box_3(); + box_4(); + box_5(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/by_value.rs b/tests/ui/closures/2229_closure_analysis/run_pass/by_value.rs new file mode 100644 index 000000000..f8752fe1c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/by_value.rs @@ -0,0 +1,26 @@ +// edition:2021 +// run-pass + +// Test that ByValue captures compile successfully especially when the captures are +// dereferenced within the closure. + +#[derive(Debug, Default)] +struct SomeLargeType; +struct MuchLargerType([SomeLargeType; 32]); + +fn big_box() { + let s = MuchLargerType(Default::default()); + let b = Box::new(s); + let t = (b, 10); + + let c = || { + let p = t.0.0; + println!("{} {:?}", t.1, p); + }; + + c(); +} + +fn main() { + big_box(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs b/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs new file mode 100644 index 000000000..3cb1eb329 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-struct.rs @@ -0,0 +1,24 @@ +// edition:2021 +// run-pass + +// Test that we can immutably borrow field of an instance of a structure from within a closure, +// while having a mutable borrow to another field of the same instance outside the closure. + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 10 }; + + let c = || { + println!("{}", p.x); + }; + + // `c` should only capture `p.x`, therefore mutating `p.y` is allowed. + let py = &mut p.y; + + c(); + *py = 20; +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs b/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs new file mode 100644 index 000000000..0f79b7ae7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple-mut.rs @@ -0,0 +1,20 @@ +// edition:2021 +// run-pass + +// Test that we can mutate an element of a tuple from within a closure +// while immutably borrowing another element of the same tuple outside the closure. + +#![feature(rustc_attrs)] + +fn main() { + let mut t = (10, 10); + + let mut c = || { + let t1 = &mut t.1; + *t1 = 20; + }; + + // Test that `c` only captures t.1, therefore reading t.0 is allowed. + println!("{}", t.0); + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs b/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs new file mode 100644 index 000000000..81f0328b9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/capture-disjoint-field-tuple.rs @@ -0,0 +1,21 @@ +// edition:2021 +// run-pass + +// Test that we can immutably borrow an element of a tuple from within a closure, +// while having a mutable borrow to another element of the same tuple outside the closure. + +#![feature(rustc_attrs)] + +fn main() { + let mut t = (10, 10); + + let c = || { + println!("{}", t.0); + }; + + // `c` only captures t.0, therefore mutating t.1 is allowed. + let t1 = &mut t.1; + + c(); + *t1 = 20; +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs b/tests/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs new file mode 100644 index 000000000..cea02fbe1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/capture_with_wildcard_match.rs @@ -0,0 +1,27 @@ +// edition:2021 +//check-pass + +fn test1() { + let foo : [Vec; 3] = ["String".into(), "String".into(), "String".into()]; + let c = || { + match foo { _ => () }; + }; + drop(foo); + c(); +} + +fn test2() { + let foo : Option<[Vec; 3]> = Some(["String".into(), "String".into(), "String".into()]); + let c = || { + match foo { + Some(_) => 1, + _ => 2 + }; + }; + c(); +} + +fn main() { + test1(); + test2(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs b/tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs new file mode 100644 index 000000000..5c278bff9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.rs @@ -0,0 +1,21 @@ +// edition:2021 +// check-pass +#![warn(unused)] + +fn main() { + let t = (String::from("Hello"), String::from("World")); + let g = (String::from("Mr"), String::from("Goose")); + + let a = || { + let (_, g2) = g; + //~^ WARN unused variable: `g2` + let c = || { + let (_, t2) = t; + //~^ WARN unused variable: `t2` + }; + + c(); + }; + + a(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr b/tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr new file mode 100644 index 000000000..cf8bd7a0a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/destructure-pattern-closure-within-closure.stderr @@ -0,0 +1,21 @@ +warning: unused variable: `g2` + --> $DIR/destructure-pattern-closure-within-closure.rs:10:17 + | +LL | let (_, g2) = g; + | ^^ help: if this is intentional, prefix it with an underscore: `_g2` + | +note: the lint level is defined here + --> $DIR/destructure-pattern-closure-within-closure.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `t2` + --> $DIR/destructure-pattern-closure-within-closure.rs:13:21 + | +LL | let (_, t2) = t; + | ^^ help: if this is intentional, prefix it with an underscore: `_t2` + +warning: 2 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs b/tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs new file mode 100644 index 000000000..dacc2c616 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs @@ -0,0 +1,119 @@ +// edition:2021 +// check-pass +#![warn(unused)] + +struct Point { + x: u32, + y: u32, +} + +fn test1() { + let t = (String::from("Hello"), String::from("World")); + + let c = || { + let (t1, t2) = t; + //~^ WARN unused variable: `t1` + //~| WARN unused variable: `t2` + }; + + c(); +} + +fn test2() { + let t = (String::from("Hello"), String::from("World")); + + let c = || { + let (t1, _) = t; + //~^ WARN unused variable: `t1` + }; + + c(); +} + +fn test3() { + let t = (String::from("Hello"), String::from("World")); + + let c = || { + let (_, t2) = t; + //~^ WARN unused variable: `t2` + }; + + c(); +} + +fn test4() { + let t = (String::from("Hello"), String::from("World")); + + let c = || { + let (_, _) = t; + }; + + c(); +} + +fn test5() { + let t = (String::new(), String::new()); + let _c = || { + let _a = match t { + (t1, _) => t1, + }; + }; +} + +fn test6() { + let t = (String::new(), String::new()); + let _c = || { + let _a = match t { + (_, t2) => t2, + }; + }; +} + +fn test7() { + let t = (String::new(), String::new()); + let _c = || { + let _a = match t { + (t1, t2) => (t1, t2), + }; + }; +} + +fn test8() { + let x = 0; + let tup = (1, 2); + let p = Point { x: 10, y: 20 }; + + let c = || { + let _ = x; + let Point { x, y } = p; + //~^ WARN unused variable: `x` + println!("{}", y); + let (_, _) = tup; + }; + + c(); +} + +fn test9() { + let _z = 9; + let t = (String::from("Hello"), String::from("World")); + + let c = || { + let (_, t) = t; + println!("{}", t); + }; + + c(); +} + +fn main() { + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + test8(); + test9(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr b/tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr new file mode 100644 index 000000000..7706f68ba --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr @@ -0,0 +1,39 @@ +warning: unused variable: `t1` + --> $DIR/destructure_patterns.rs:14:14 + | +LL | let (t1, t2) = t; + | ^^ help: if this is intentional, prefix it with an underscore: `_t1` + | +note: the lint level is defined here + --> $DIR/destructure_patterns.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `t2` + --> $DIR/destructure_patterns.rs:14:18 + | +LL | let (t1, t2) = t; + | ^^ help: if this is intentional, prefix it with an underscore: `_t2` + +warning: unused variable: `t1` + --> $DIR/destructure_patterns.rs:26:14 + | +LL | let (t1, _) = t; + | ^^ help: if this is intentional, prefix it with an underscore: `_t1` + +warning: unused variable: `t2` + --> $DIR/destructure_patterns.rs:37:17 + | +LL | let (_, t2) = t; + | ^^ help: if this is intentional, prefix it with an underscore: `_t2` + +warning: unused variable: `x` + --> $DIR/destructure_patterns.rs:88:21 + | +LL | let Point { x, y } = p; + | ^ help: try ignoring the field: `x: _` + +warning: 5 warnings emitted + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs b/tests/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs new file mode 100644 index 000000000..03400e0ee --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/disjoint-capture-in-same-closure.rs @@ -0,0 +1,23 @@ +// edition:2021 +// run-pass + +// Tests that if a closure uses individual fields of the same object +// then that case is handled properly. + +#![allow(unused)] + +struct Struct { + x: i32, + y: i32, + s: String, +} + +fn main() { + let mut s = Struct { x: 10, y: 10, s: String::new() }; + + let mut c = { + s.x += 10; + s.y += 42; + s.s = String::from("new"); + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs new file mode 100644 index 000000000..477fdd613 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs @@ -0,0 +1,11 @@ +// edition:2021 +// check-pass +#![feature(rustc_attrs)] + +fn main() { + let mut x = 1; + let c = || { + drop(&mut x); + match x { _ => () } + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/edition.rs b/tests/ui/closures/2229_closure_analysis/run_pass/edition.rs new file mode 100644 index 000000000..20bbe1d89 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/edition.rs @@ -0,0 +1,23 @@ +// edition:2021 +// run-pass + +// Test that edition 2021 enables disjoint capture by default. + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 10 }; + + let c = || { + println!("{}", p.x); + }; + + // `c` should only capture `p.x`, therefore mutating `p.y` is allowed. + let py = &mut p.y; + + c(); + *py = 20; +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs b/tests/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs new file mode 100644 index 000000000..e19f5ff1b --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/filter-on-struct-member.rs @@ -0,0 +1,37 @@ +// edition:2021 +// run-pass + +// Test disjoint capture within an impl block + +struct Filter { + div: i32, +} +impl Filter { + fn allowed(&self, x: i32) -> bool { + x % self.div == 1 + } +} + +struct Data { + filter: Filter, + list: Vec, +} +impl Data { + fn update(&mut self) { + // The closure passed to filter only captures self.filter, + // therefore mutating self.list is allowed. + self.list.retain( + |v| self.filter.allowed(*v), + ); + } +} + +fn main() { + let mut d = Data { filter: Filter { div: 3 }, list: Vec::new() }; + + for i in 1..10 { + d.list.push(i); + } + + d.update(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs b/tests/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs new file mode 100644 index 000000000..1286613cb --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/fru_syntax.rs @@ -0,0 +1,42 @@ +// edition:2021 +// run-pass + +// Test that functional record update/struct update syntax works inside +// a closure when the feature `capture_disjoint_fields` is enabled. + +#[derive(Clone)] +struct S { + a: String, + b: String, +} + +struct T { + a: String, + s: S, +} + +fn main() { + let a = String::new(); + let b = String::new(); + let c = String::new(); + let s = S {a, b}; + let t = T { + a: c, + s: s.clone() + }; + + let c = || { + let s2 = S { + a: format!("New s2"), + ..s + }; + let s3 = S { + a: format!("New s3"), + ..t.s + }; + println!("{} {}", s2.a, s2.b); + println!("{} {} {}", s3.a, s3.b, t.a); + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs b/tests/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs new file mode 100644 index 000000000..c64475fda --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/issue-87378.rs @@ -0,0 +1,16 @@ +// edition:2021 +// check-pass + +union Union { + value: u64, +} + +fn main() { + let u = Union { value: 42 }; + + let c = || { + unsafe { u.value } + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs b/tests/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs new file mode 100644 index 000000000..25fbb6cb9 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs @@ -0,0 +1,19 @@ +// edition:2021 +// run-pass + + +fn solve(validate: F) -> Option +where + F: Fn(&mut [i8; 1]), +{ + let mut position: [i8; 1] = [1]; + Some(0).map(|_| { + validate(&mut position); + let [_x] = position; + 0 + }) +} + +fn main() { + solve(|_| ()); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs b/tests/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs new file mode 100644 index 000000000..999620530 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs @@ -0,0 +1,59 @@ +// edition:2021 +// check-pass + +use std::collections::HashMap; +use std::future::Future; +use std::pin::Pin; + +pub struct GameMode {} + +struct GameStateManager<'a> { + gamestate_stack: Vec + 'a>>, +} + +pub trait GameState<'a> {} + +async fn construct_gamestate_replay<'a>( + _gamemode: &GameMode, + _factory: &mut GameStateManager<'a>, +) -> Box + 'a> { + unimplemented!() +} + +type FutureGameState<'a, 'b> = Pin + 'a>> + 'b>>; + +struct MenuOption<'a> { + command: Box Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a>, +} + +impl<'a> MenuOption<'a> { + fn new( + _command: impl for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a, + ) -> Self { + unimplemented!() + } +} + +struct MenuState<'a> { + options: Vec>, +} + +impl<'a> GameState<'a> for MenuState<'a> {} + +pub async fn get_replay_menu<'a>( + gamemodes: &'a HashMap<&str, GameMode>, +) -> Box + 'a> { + let recordings: Vec = vec![]; + let _ = recordings + .into_iter() + .map(|entry| { + MenuOption::new(move |f| { + Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f)) + }) + }) + .collect::>(); + + todo!() +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs b/tests/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs new file mode 100644 index 000000000..f44c2af80 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs @@ -0,0 +1,47 @@ +// check-pass +// edition:2021 + +use std::rc::Rc; + +// Test that we restrict precision when moving not-`Copy` types, if any of the parent paths +// implement `Drop`. This is to ensure that we don't move out of a type that implements Drop. +pub fn test1() { + struct Foo(Rc); + + impl Drop for Foo { + fn drop(self: &mut Foo) {} + } + + let f = Foo(Rc::new(1)); + let x = move || { + println!("{:?}", f.0); + }; + + x(); +} + + +// Test that we don't restrict precision when moving `Copy` types(i.e. when copying), +// even if any of the parent paths implement `Drop`. +pub fn test2() { + struct Character { + hp: u32, + name: String, + } + + impl Drop for Character { + fn drop(&mut self) {} + } + + let character = Character { hp: 100, name: format!("A") }; + + let c = move || { + println!("{}", character.hp) + }; + + c(); + + println!("{}", character.name); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs b/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs new file mode 100644 index 000000000..d2375aa69 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/lit-pattern-matching-with-methods.rs @@ -0,0 +1,30 @@ +// edition:2021 +//check-pass +#![warn(unused)] +#![feature(rustc_attrs)] +#![feature(btree_drain_filter)] + +use std::collections::BTreeMap; +use std::panic::{catch_unwind, AssertUnwindSafe}; + +fn main() { + let mut map = BTreeMap::new(); + map.insert("a", ()); + map.insert("b", ()); + map.insert("c", ()); + + { + let mut it = map.drain_filter(|_, _| true); + catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); + let result = catch_unwind(AssertUnwindSafe(|| it.next())); + assert!(matches!(result, Ok(None))); + } + + { + let mut it = map.drain_filter(|_, _| true); + catch_unwind(AssertUnwindSafe(|| while let Some(_) = it.next() {})).unwrap_err(); + let result = catch_unwind(AssertUnwindSafe(|| it.next())); + assert!(matches!(result, Ok(None))); + } + +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/move_closure.rs b/tests/ui/closures/2229_closure_analysis/run_pass/move_closure.rs new file mode 100644 index 000000000..f76965bdd --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/move_closure.rs @@ -0,0 +1,93 @@ +// edition:2021 +// run-pass + +// Test that move closures compile properly with `capture_disjoint_fields` enabled. + +#![allow(unused)] + +fn simple_ref() { + let mut s = 10; + let ref_s = &mut s; + + let mut c = move || { + *ref_s += 10; + }; + c(); +} + +fn struct_contains_ref_to_another_struct() { + struct S(String); + struct T<'a>(&'a mut S); + + let mut s = S("s".into()); + let t = T(&mut s); + + let mut c = move || { + t.0.0 = "new s".into(); + }; + + c(); +} + +#[derive(Debug)] +struct S(String); + +#[derive(Debug)] +struct T(S); + +fn no_ref() { + let mut t = T(S("s".into())); + let mut c = move || { + t.0.0 = "new S".into(); + }; + c(); +} + +fn no_ref_nested() { + let mut t = T(S("s".into())); + let c = || { + println!("{:?}", t.0); + let mut c = move || { + t.0.0 = "new S".into(); + println!("{:?}", t.0.0); + }; + c(); + }; + c(); +} + +// Test that even if a path is moved into the closure, the closure is not FnOnce +// if the path is not moved by the closure call. +fn data_moved_but_not_fn_once() { + let x = Box::new(10i32); + + let c = move || { + // *x has type i32 which is Copy. So even though the box `x` will be moved + // into the closure, `x` is never moved when the closure is called, i.e. the + // ownership stays with the closure and therefore we can call the function multiple times. + let _x = *x; + }; + + c(); + c(); +} + +// Test that move closures can take ownership of Copy type +fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { + let x = 10; + + let c = move || x; + + c +} + +fn main() { + simple_ref(); + struct_contains_ref_to_another_struct(); + no_ref(); + no_ref_nested(); + + data_moved_but_not_fn_once(); + + returned_closure_owns_copy_type_data(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs new file mode 100644 index 000000000..624e0ff22 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-1.rs @@ -0,0 +1,33 @@ +// edition:2021 +// run-pass + +// Test that closures can capture paths that are more precise than just one level +// from the root variable. +// +// If the closures can handle such precision we should be able to mutate one path in the closure +// while being able to mutate another path outside the closure, where the two paths are disjoint +// after applying two projections on the root variable. + +#![allow(unused)] + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let mut c = || { + w.p.x += 20; + }; + + // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`. + let py = &mut w.p.y; + c(); + + *py = 20 +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs new file mode 100644 index 000000000..bd8addd37 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-2.rs @@ -0,0 +1,31 @@ +// edition:2021 +// run-pass + +#![allow(unused)] + +// If the closures can handle such precision we should be able to read one path in the closure +// while being able mutate another path outside the closure, where the two paths are disjoint +// after applying two projections on the root variable. + + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let c = || { + println!("{}", w.p.x); + }; + + // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`. + let py = &mut w.p.y; + c(); + + *py = 20 +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs new file mode 100644 index 000000000..8fc0efb60 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multilevel-path-3.rs @@ -0,0 +1,28 @@ +// edition:2021 +// run-pass + +#![allow(unused)] + +// Test that when `capture_disjoint_fields` is enabled we can read a path +// both inside and outside the closure at the same time. + +struct Point { + x: i32, + y: i32, +} +struct Wrapper { + p: Point, +} + +fn main() { + let mut w = Wrapper { p: Point { x: 10, y: 10 } }; + + let c = || { + println!("{}", w.p.x); + }; + + let px = &w.p.x; + c(); + + println!("{}", px); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs b/tests/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs new file mode 100644 index 000000000..9f0c4d96a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/mut_ref.rs @@ -0,0 +1,54 @@ +// edition:2021 +// run-pass + +// Test that we can mutate a place through a mut-borrow +// that is captured by the closure + +// Check that we can mutate when one deref is required +fn mut_ref_1() { + let mut x = String::new(); + let rx = &mut x; + + let mut c = || { + *rx = String::new(); + }; + + c(); +} + +// Similar example as mut_ref_1, we don't deref the imm-borrow here, +// and so we are allowed to mutate. +fn mut_ref_2() { + let x = String::new(); + let y = String::new(); + let mut ref_x = &x; + let m_ref_x = &mut ref_x; + + let mut c = || { + *m_ref_x = &y; + }; + + c(); +} + +// Check that we can mutate when multiple derefs of mut-borrows are required to reach +// the target place. +// It works because all derefs are mutable, if either of them was an immutable +// borrow, then we would not be able to deref. +fn mut_mut_ref() { + let mut x = String::new(); + let mut mref_x = &mut x; + let m_mref_x = &mut mref_x; + + let mut c = || { + **m_mref_x = String::new(); + }; + + c(); +} + +fn main() { + mut_ref_1(); + mut_ref_2(); + mut_mut_ref(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs b/tests/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs new file mode 100644 index 000000000..a85335438 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/mut_ref_struct_mem.rs @@ -0,0 +1,43 @@ +// edition:2021 +// run-pass + +// Test that we can mutate a place through a mut-borrow +// that is captured by the closure + +// More specifically we test that the if the mutable reference isn't root variable of a capture +// but rather accessed while accessing the precise capture. + +fn mut_tuple() { + let mut t = (10, 10); + + let t1 = (&mut t, 10); + + let mut c = || { + // Mutable because (*t.0) is mutable + t1.0.0 += 10; + }; + + c(); +} + +fn mut_tuple_nested() { + let mut t = (10, 10); + + let t1 = (&mut t, 10); + + let mut c = || { + let mut c = || { + // Mutable because (*t.0) is mutable + t1.0.0 += 10; + }; + + c(); + }; + + c(); +} + +fn main() { + mut_tuple(); + mut_tuple_nested(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs b/tests/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs new file mode 100644 index 000000000..a80b40bb4 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/nested-closure.rs @@ -0,0 +1,36 @@ +// edition:2021 +// run-pass + +// Test whether if we can do precise capture when using nested clsoure. + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 5, y: 20 }; + + // c1 should capture `p.x` via immutable borrow and + // `p.y` via mutable borrow. + let mut c1 = || { + println!("{}", p.x); + + let incr = 10; + + let mut c2 = || p.y += incr; + c2(); + + println!("{}", p.y); + }; + + c1(); + + // This should not throw an error because `p.x` is borrowed via Immutable borrow, + // and multiple immutable borrow of the same place are allowed. + let px = &p.x; + + println!("{}", px); + + c1(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs b/tests/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs new file mode 100644 index 000000000..ed222b314 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs @@ -0,0 +1,49 @@ +// edition:2021 +//check-pass +#![warn(unused)] +#![allow(dead_code)] +#![feature(rustc_attrs)] + +#[derive(Debug, Clone, Copy)] +enum PointType { + TwoD { x: u32, y: u32 }, + + ThreeD{ x: u32, y: u32, z: u32 } +} + +// Testing struct patterns +struct Points { + points: Vec, +} + +impl Points { + pub fn test1(&mut self) -> Vec { + (0..self.points.len()) + .filter_map(|i| { + let idx = i as usize; + match self.test2(idx) { + PointType::TwoD { .. } => Some(i), + PointType::ThreeD { .. } => None, + } + }) + .collect() + } + + pub fn test2(&mut self, i: usize) -> PointType { + self.points[i] + } +} + +fn main() { + let mut points = Points { + points: Vec::::new() + }; + + points.points.push(PointType::ThreeD { x:0, y:0, z:0 }); + points.points.push(PointType::TwoD{ x:0, y:0 }); + points.points.push(PointType::ThreeD{ x:0, y:0, z:0 }); + points.points.push(PointType::TwoD{ x:0, y:0 }); + + println!("{:?}", points.test1()); + println!("{:?}", points.points); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs b/tests/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs new file mode 100644 index 000000000..f3f44433c --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/tuple-struct-pattern-matching-with-methods.rs @@ -0,0 +1,43 @@ +// edition:2021 +//check-pass + +#[derive(Copy, Clone)] +enum PointType { + TwoD(u32, u32), + ThreeD(u32, u32, u32) +} + +// Testing tuple struct patterns +struct Points { + points: Vec, +} + +impl Points { + pub fn test1(&mut self) -> Vec { + (0..self.points.len()) + .filter_map(|i| { + match self.test2(i) { + PointType::TwoD (..) => Some(i), + PointType::ThreeD (..) => None, + } + }) + .collect() + } + + pub fn test2(&mut self, i: usize) -> PointType { + self.points[i] + } +} + +fn main() { + let mut points = Points { + points: Vec::::new() + }; + + points.points.push(PointType::ThreeD(0,0,0)); + points.points.push(PointType::TwoD(0,0)); + points.points.push(PointType::ThreeD(0,0,1)); + points.points.push(PointType::TwoD(0,1)); + + println!("{:?}", points.test1()); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs b/tests/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs new file mode 100644 index 000000000..3f7ddf93f --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs @@ -0,0 +1,47 @@ +// edition:2021 +// run-pass + +// Test that we can use raw ptrs when using `capture_disjoint_fields`. + +#![allow(dead_code)] + +#[derive(Debug)] +struct S { + s: String, + t: String, +} + +struct T(*const S); + +fn unsafe_imm() { + let s = "".into(); + let t = "".into(); + let my_speed: Box = Box::new(S { s, t }); + + let p : *const S = Box::into_raw(my_speed); + let t = T(p); + + let c = || unsafe { + println!("{:?}", (*t.0).s); + }; + + c(); +} + +fn unsafe_mut() { + let s = "".into(); + let t = "".into(); + let mut my_speed: Box = Box::new(S { s, t }); + let p : *mut S = &mut *my_speed; + + let c = || { + let x = unsafe { &mut (*p).s }; + *x = "s".into(); + }; + c(); +} + +fn main() { + unsafe_mut(); + unsafe_imm(); +} diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs b/tests/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs new file mode 100644 index 000000000..0206927cc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/use_of_mutable_borrow_and_fake_reads.rs @@ -0,0 +1,11 @@ +// edition:2021 +//check-pass +#![feature(rustc_attrs)] + +fn main() { + let mut x = 0; + let c = || { + &mut x; // mutable borrow of `x` + match x { _ => () } // fake read of `x` + }; +} diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs new file mode 100644 index 000000000..563095d44 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -0,0 +1,39 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +// Test to ensure that min analysis meets capture kind for all paths captured. + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn main() { + let mut p = Point { x: 10, y: 20 }; + + // + // Requirements: + // p.x -> MutBoorrow + // p -> ImmBorrow + // + // Requirements met when p is captured via MutBorrow + // + let mut c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + p.x += 10; + //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow + //~| NOTE: p[] captured as MutBorrow here + println!("{:?}", p); + //~^ NOTE: Capturing p[] -> ImmBorrow + //~| NOTE: Min Capture p[] -> MutBorrow + //~| NOTE: p[] used here + }; + + c(); +} diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr new file mode 100644 index 000000000..05d79797a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -0,0 +1,56 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/simple-struct-min-capture.rs:23:17 + | +LL | let mut c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/simple-struct-min-capture.rs:26:5 + | +LL | / || { +LL | | +LL | | +LL | | p.x += 10; +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> MutBorrow + --> $DIR/simple-struct-min-capture.rs:29:9 + | +LL | p.x += 10; + | ^^^ +note: Capturing p[] -> ImmBorrow + --> $DIR/simple-struct-min-capture.rs:32:26 + | +LL | println!("{:?}", p); + | ^ + +error: Min Capture analysis includes: + --> $DIR/simple-struct-min-capture.rs:26:5 + | +LL | / || { +LL | | +LL | | +LL | | p.x += 10; +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[] -> MutBorrow + --> $DIR/simple-struct-min-capture.rs:29:9 + | +LL | p.x += 10; + | ^^^ p[] captured as MutBorrow here +... +LL | println!("{:?}", p); + | ^ p[] used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs new file mode 100644 index 000000000..eab9f9d08 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs @@ -0,0 +1,62 @@ +// edition:2021 + +// Test that we restrict precision of a capture when we access a raw ptr, +// i.e. the capture doesn't deref the raw ptr. + + +#![feature(rustc_attrs)] + +#[derive(Debug)] +struct S { + s: String, + t: String, +} + +struct T(*const S); + +fn unsafe_imm() { + let s = "".into(); + let t = "".into(); + let my_speed: Box = Box::new(S { s, t }); + + let p : *const S = Box::into_raw(my_speed); + let t = T(p); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || unsafe { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + println!("{:?}", (*t.0).s); + //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow + }; + + c(); +} + +fn unsafe_mut() { + let s = "".into(); + let t = "".into(); + let mut my_speed: Box = Box::new(S { s, t }); + let p : *mut S = &mut *my_speed; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + let x = unsafe { &mut (*p).s }; + //~^ NOTE: Capturing p[Deref,(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture p[] -> ImmBorrow + *x = "s".into(); + }; + c(); +} + +fn main() { + unsafe_mut(); + unsafe_imm(); +} diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr new file mode 100644 index 000000000..e740a4d2d --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr @@ -0,0 +1,93 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/unsafe_ptr.rs:25:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/unsafe_ptr.rs:45:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/unsafe_ptr.rs:28:6 + | +LL | / || unsafe { +LL | | +LL | | +LL | | println!("{:?}", (*t.0).s); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow + --> $DIR/unsafe_ptr.rs:31:26 + | +LL | println!("{:?}", (*t.0).s); + | ^^^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/unsafe_ptr.rs:28:6 + | +LL | / || unsafe { +LL | | +LL | | +LL | | println!("{:?}", (*t.0).s); +LL | | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ImmBorrow + --> $DIR/unsafe_ptr.rs:31:26 + | +LL | println!("{:?}", (*t.0).s); + | ^^^^^^^^ + +error: First Pass analysis includes: + --> $DIR/unsafe_ptr.rs:48:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = unsafe { &mut (*p).s }; +... | +LL | | *x = "s".into(); +LL | | }; + | |_____^ + | +note: Capturing p[Deref,(0, 0)] -> ImmBorrow + --> $DIR/unsafe_ptr.rs:51:31 + | +LL | let x = unsafe { &mut (*p).s }; + | ^^^^^^ + +error: Min Capture analysis includes: + --> $DIR/unsafe_ptr.rs:48:5 + | +LL | / || { +LL | | +LL | | +LL | | let x = unsafe { &mut (*p).s }; +... | +LL | | *x = "s".into(); +LL | | }; + | |_____^ + | +note: Min Capture p[] -> ImmBorrow + --> $DIR/unsafe_ptr.rs:51:31 + | +LL | let x = unsafe { &mut (*p).s }; + | ^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs new file mode 100644 index 000000000..a795088a1 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs @@ -0,0 +1,73 @@ +// edition:2021 + +#![feature(rustc_attrs)] + +// Test to ensure that we can handle cases where +// let statements create no bindings are initialized +// using a Place expression +// +// Note: Currently when feature `capture_disjoint_fields` is enabled +// we can't handle such cases. So the test current use `_x` instead of +// `_` until the issue is resolved. +// Check rust-lang/project-rfc-2229#24 for status. + +struct Point { + x: i32, + y: i32, +} + +fn wild_struct() { + let p = Point { x: 10, y: 20 }; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + // FIXME(arora-aman): Change `_x` to `_` + let Point { x: _x, y: _ } = p; + //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow + //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow + }; + + c(); +} + +fn wild_tuple() { + let t = (String::new(), 10); + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + // FIXME(arora-aman): Change `_x` to `_` + let (_x, _) = t; + //~^ NOTE: Capturing t[(0, 0)] -> ByValue + //~| NOTE: Min Capture t[(0, 0)] -> ByValue + }; + + c(); +} + +fn wild_arr() { + let arr = [String::new(), String::new()]; + + let c = #[rustc_capture_analysis] + //~^ ERROR: attributes on expressions are experimental + //~| NOTE: see issue #15701 + || { + //~^ ERROR: First Pass analysis includes: + //~| ERROR: Min Capture analysis includes: + // FIXME(arora-aman): Change `_x` to `_` + let [_x, _] = arr; + //~^ NOTE: Capturing arr[Index] -> ByValue + //~| NOTE: Min Capture arr[] -> ByValue + }; + + c(); +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr new file mode 100644 index 000000000..c64378091 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr @@ -0,0 +1,138 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/wild_patterns.rs:22:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/wild_patterns.rs:40:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/wild_patterns.rs:58:13 + | +LL | let c = #[rustc_capture_analysis] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: First Pass analysis includes: + --> $DIR/wild_patterns.rs:25:5 + | +LL | / || { +LL | | +LL | | +LL | | // FIXME(arora-aman): Change `_x` to `_` +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing p[(0, 0)] -> ImmBorrow + --> $DIR/wild_patterns.rs:29:37 + | +LL | let Point { x: _x, y: _ } = p; + | ^ + +error: Min Capture analysis includes: + --> $DIR/wild_patterns.rs:25:5 + | +LL | / || { +LL | | +LL | | +LL | | // FIXME(arora-aman): Change `_x` to `_` +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture p[(0, 0)] -> ImmBorrow + --> $DIR/wild_patterns.rs:29:37 + | +LL | let Point { x: _x, y: _ } = p; + | ^ + +error: First Pass analysis includes: + --> $DIR/wild_patterns.rs:43:5 + | +LL | / || { +LL | | +LL | | +LL | | // FIXME(arora-aman): Change `_x` to `_` +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing t[(0, 0)] -> ByValue + --> $DIR/wild_patterns.rs:47:23 + | +LL | let (_x, _) = t; + | ^ + +error: Min Capture analysis includes: + --> $DIR/wild_patterns.rs:43:5 + | +LL | / || { +LL | | +LL | | +LL | | // FIXME(arora-aman): Change `_x` to `_` +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture t[(0, 0)] -> ByValue + --> $DIR/wild_patterns.rs:47:23 + | +LL | let (_x, _) = t; + | ^ + +error: First Pass analysis includes: + --> $DIR/wild_patterns.rs:61:5 + | +LL | / || { +LL | | +LL | | +LL | | // FIXME(arora-aman): Change `_x` to `_` +... | +LL | | +LL | | }; + | |_____^ + | +note: Capturing arr[Index] -> ByValue + --> $DIR/wild_patterns.rs:65:23 + | +LL | let [_x, _] = arr; + | ^^^ + +error: Min Capture analysis includes: + --> $DIR/wild_patterns.rs:61:5 + | +LL | / || { +LL | | +LL | | +LL | | // FIXME(arora-aman): Change `_x` to `_` +... | +LL | | +LL | | }; + | |_____^ + | +note: Min Capture arr[] -> ByValue + --> $DIR/wild_patterns.rs:65:23 + | +LL | let [_x, _] = arr; + | ^^^ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/add_semicolon_non_block_closure.rs b/tests/ui/closures/add_semicolon_non_block_closure.rs new file mode 100644 index 000000000..3ae91be60 --- /dev/null +++ b/tests/ui/closures/add_semicolon_non_block_closure.rs @@ -0,0 +1,11 @@ +fn foo(_f: impl Fn()) {} + +fn bar() -> i32 { + 1 +} + +fn main() { + foo(|| bar()) + //~^ ERROR mismatched types [E0308] + //~| HELP consider using a semicolon here +} diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr new file mode 100644 index 000000000..ed829fc98 --- /dev/null +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/add_semicolon_non_block_closure.rs:8:12 + | +LL | fn main() { + | - expected `()` because of default return type +LL | foo(|| bar()) + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | foo(|| { bar(); }) + | + +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/binder/async-closure-with-binder.rs b/tests/ui/closures/binder/async-closure-with-binder.rs new file mode 100644 index 000000000..4fa599d37 --- /dev/null +++ b/tests/ui/closures/binder/async-closure-with-binder.rs @@ -0,0 +1,8 @@ +// edition:2021 +#![feature(closure_lifetime_binder)] +#![feature(async_closure)] +fn main() { + for<'a> async || (); + //~^ ERROR `for<...>` binders on `async` closures are not currently supported + //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present +} diff --git a/tests/ui/closures/binder/async-closure-with-binder.stderr b/tests/ui/closures/binder/async-closure-with-binder.stderr new file mode 100644 index 000000000..1d4628b1a --- /dev/null +++ b/tests/ui/closures/binder/async-closure-with-binder.stderr @@ -0,0 +1,16 @@ +error: `for<...>` binders on `async` closures are not currently supported + --> $DIR/async-closure-with-binder.rs:5:5 + | +LL | for<'a> async || (); + | ^^^^^^^ + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/async-closure-with-binder.rs:5:5 + | +LL | for<'a> async || (); + | -------^^^^^^^^^ + | | + | `for<...>` is here + +error: aborting due to 2 previous errors + diff --git a/tests/ui/closures/binder/disallow-const.rs b/tests/ui/closures/binder/disallow-const.rs new file mode 100644 index 000000000..72ad6185d --- /dev/null +++ b/tests/ui/closures/binder/disallow-const.rs @@ -0,0 +1,6 @@ +#![feature(closure_lifetime_binder)] + +fn main() { + for || -> () {}; + //~^ ERROR only lifetime parameters can be used in this context +} diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr new file mode 100644 index 000000000..3c3b43d8c --- /dev/null +++ b/tests/ui/closures/binder/disallow-const.stderr @@ -0,0 +1,8 @@ +error: only lifetime parameters can be used in this context + --> $DIR/disallow-const.rs:4:15 + | +LL | for || -> () {}; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/closures/binder/disallow-ty.rs b/tests/ui/closures/binder/disallow-ty.rs new file mode 100644 index 000000000..bbe3d8488 --- /dev/null +++ b/tests/ui/closures/binder/disallow-ty.rs @@ -0,0 +1,6 @@ +#![feature(closure_lifetime_binder)] + +fn main() { + for || -> () {}; + //~^ ERROR only lifetime parameters can be used in this context +} diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr new file mode 100644 index 000000000..51b6773ed --- /dev/null +++ b/tests/ui/closures/binder/disallow-ty.stderr @@ -0,0 +1,8 @@ +error: only lifetime parameters can be used in this context + --> $DIR/disallow-ty.rs:4:9 + | +LL | for || -> () {}; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/closures/binder/implicit-return.rs b/tests/ui/closures/binder/implicit-return.rs new file mode 100644 index 000000000..d34e5721d --- /dev/null +++ b/tests/ui/closures/binder/implicit-return.rs @@ -0,0 +1,6 @@ +#![feature(closure_lifetime_binder)] + +fn main() { + let _f = for<'a> |_: &'a ()| {}; + //~^ implicit types in closure signatures are forbidden when `for<...>` is present +} diff --git a/tests/ui/closures/binder/implicit-return.stderr b/tests/ui/closures/binder/implicit-return.stderr new file mode 100644 index 000000000..5bfb97113 --- /dev/null +++ b/tests/ui/closures/binder/implicit-return.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-return.rs:4:34 + | +LL | let _f = for<'a> |_: &'a ()| {}; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to previous error + diff --git a/tests/ui/closures/binder/implicit-stuff.rs b/tests/ui/closures/binder/implicit-stuff.rs new file mode 100644 index 000000000..09e4c747a --- /dev/null +++ b/tests/ui/closures/binder/implicit-stuff.rs @@ -0,0 +1,27 @@ +#![feature(closure_lifetime_binder)] + +fn main() { + // Implicit types + let _ = for<> || {}; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> || -> &'a _ { &() }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> |x| -> &'a () { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> |x: &'a _| -> &'a () { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> |x: &'a Vec::<_>| -> &'a Vec::<()> { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> |x: &'a Vec<()>| -> &'a Vec<_> { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> |x: &'a _| -> &'a &'a () { x }; //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { //~ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + let _: &u8 = x; + let _: u32 = y; + let _: i32 = z; + x + }; + + // Lifetime elision + let _ = for<> |_: &()| -> () {}; //~ ERROR `&` without an explicit lifetime name cannot be used here + let _ = for<> |x: &()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here + //~| ERROR `&` without an explicit lifetime name cannot be used here + let _ = for<> |x: &'_ ()| -> &'_ () { x }; //~ ERROR `'_` cannot be used here + //~| ERROR `'_` cannot be used here + let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here + let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here +} diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr new file mode 100644 index 000000000..779a08a44 --- /dev/null +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -0,0 +1,107 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/implicit-stuff.rs:20:23 + | +LL | let _ = for<> |_: &()| -> () {}; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/implicit-stuff.rs:21:23 + | +LL | let _ = for<> |x: &()| -> &() { x }; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/implicit-stuff.rs:21:31 + | +LL | let _ = for<> |x: &()| -> &() { x }; + | ^ explicit lifetime name needed here + +error[E0637]: `'_` cannot be used here + --> $DIR/implicit-stuff.rs:23:24 + | +LL | let _ = for<> |x: &'_ ()| -> &'_ () { x }; + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/implicit-stuff.rs:23:35 + | +LL | let _ = for<> |x: &'_ ()| -> &'_ () { x }; + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/implicit-stuff.rs:25:25 + | +LL | let _ = for<'a> |x: &()| -> &'a () { x }; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/implicit-stuff.rs:26:36 + | +LL | let _ = for<'a> |x: &'a ()| -> &() { x }; + | ^ explicit lifetime name needed here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:5:22 + | +LL | let _ = for<> || {}; + | ----- ^ + | | + | `for<...>` is here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:6:31 + | +LL | let _ = for<'a> || -> &'a _ { &() }; + | ------- ^ + | | + | `for<...>` is here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:7:22 + | +LL | let _ = for<'a> |x| -> &'a () { x }; + | ------- ^ + | | + | `for<...>` is here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:8:29 + | +LL | let _ = for<'a> |x: &'a _| -> &'a () { x }; + | ------- ^ + | | + | `for<...>` is here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:9:35 + | +LL | let _ = for<'a> |x: &'a Vec::<_>| -> &'a Vec::<()> { x }; + | ------- ^ + | | + | `for<...>` is here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:10:49 + | +LL | let _ = for<'a> |x: &'a Vec<()>| -> &'a Vec<_> { x }; + | ------- `for<...>` is here ^ + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:11:29 + | +LL | let _ = for<'a> |x: &'a _| -> &'a &'a () { x }; + | ------- ^ + | | + | `for<...>` is here + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/implicit-stuff.rs:12:29 + | +LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { + | ------- ^ ^ ^ ^ + | | + | `for<...>` is here + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/closures/binder/late-bound-in-body.rs b/tests/ui/closures/binder/late-bound-in-body.rs new file mode 100644 index 000000000..bb5c7552f --- /dev/null +++ b/tests/ui/closures/binder/late-bound-in-body.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] + +fn main() { + let _ = for<'a> || -> () { + let _: &'a bool = &true; + }; +} diff --git a/tests/ui/closures/binder/nested-closures-regions.rs b/tests/ui/closures/binder/nested-closures-regions.rs new file mode 100644 index 000000000..6bfc6c80b --- /dev/null +++ b/tests/ui/closures/binder/nested-closures-regions.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(closure_lifetime_binder)] +#![feature(rustc_attrs)] + +#[rustc_regions] +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} diff --git a/tests/ui/closures/binder/nested-closures-regions.stderr b/tests/ui/closures/binder/nested-closures-regions.stderr new file mode 100644 index 000000000..b385e0ed6 --- /dev/null +++ b/tests/ui/closures/binder/nested-closures-regions.stderr @@ -0,0 +1,38 @@ +note: external requirements + --> $DIR/nested-closures-regions.rs:8:24 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0}::{closure#0} with closure substs [ + i8, + extern "rust-call" fn((&(),)), + (), + ] + = note: late-bound region is '_#4r + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + = note: where '_#2r: '_#1r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:8:5 + | +LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; + | ^^^^^^^^^^^^^^^^ + | + = note: defining type: main::{closure#0} with closure substs [ + i8, + extern "rust-call" fn(()), + (), + ] + = note: late-bound region is '_#2r + +note: no external requirements + --> $DIR/nested-closures-regions.rs:7:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = note: defining type: main + diff --git a/tests/ui/closures/binder/nested-closures.rs b/tests/ui/closures/binder/nested-closures.rs new file mode 100644 index 000000000..b3c36e7ee --- /dev/null +++ b/tests/ui/closures/binder/nested-closures.rs @@ -0,0 +1,7 @@ +// check-pass + +#![feature(closure_lifetime_binder)] + +fn main() { + for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; +} diff --git a/tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.rs b/tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.rs new file mode 100644 index 000000000..b476dd50c --- /dev/null +++ b/tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.rs @@ -0,0 +1,7 @@ +#![feature(closure_lifetime_binder)] +fn main() { + for<> |_: &'a ()| -> () {}; + //~^ ERROR use of undeclared lifetime name `'a` + for<'a> |_: &'b ()| -> () {}; + //~^ ERROR use of undeclared lifetime name `'b` +} diff --git a/tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.stderr b/tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.stderr new file mode 100644 index 000000000..1381acc15 --- /dev/null +++ b/tests/ui/closures/binder/suggestion-for-introducing-lifetime-into-binder.stderr @@ -0,0 +1,33 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/suggestion-for-introducing-lifetime-into-binder.rs:3:16 + | +LL | for<> |_: &'a ()| -> () {}; + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | for<'a, > |_: &'a ()| -> () {}; + | +++ +help: consider introducing lifetime `'a` here + | +LL | fn main<'a>() { + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/suggestion-for-introducing-lifetime-into-binder.rs:5:18 + | +LL | for<'a> |_: &'b ()| -> () {}; + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | for<'b, 'a> |_: &'b ()| -> () {}; + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn main<'b>() { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/closures/closure-array-break-length.rs b/tests/ui/closures/closure-array-break-length.rs new file mode 100644 index 000000000..fda590fda --- /dev/null +++ b/tests/ui/closures/closure-array-break-length.rs @@ -0,0 +1,7 @@ +fn main() { + |_: [_; continue]| {}; //~ ERROR: `continue` outside of a loop + + while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of a loop + + while |_: [_; break]| {} {} //~ ERROR: `break` outside of a loop +} diff --git a/tests/ui/closures/closure-array-break-length.stderr b/tests/ui/closures/closure-array-break-length.stderr new file mode 100644 index 000000000..7e0b0027a --- /dev/null +++ b/tests/ui/closures/closure-array-break-length.stderr @@ -0,0 +1,21 @@ +error[E0268]: `continue` outside of a loop + --> $DIR/closure-array-break-length.rs:2:13 + | +LL | |_: [_; continue]| {}; + | ^^^^^^^^ cannot `continue` outside of a loop + +error[E0268]: `continue` outside of a loop + --> $DIR/closure-array-break-length.rs:4:19 + | +LL | while |_: [_; continue]| {} {} + | ^^^^^^^^ cannot `continue` outside of a loop + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/closure-array-break-length.rs:6:19 + | +LL | while |_: [_; break]| {} {} + | ^^^^^ cannot `break` outside of a loop or labeled block + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs new file mode 100644 index 000000000..039cf3e04 --- /dev/null +++ b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.rs @@ -0,0 +1,11 @@ +struct X where F: FnOnce() + 'static + Send { + field: F, +} + +fn foo(blk: F) -> X where F: FnOnce() + 'static { + //~^ ERROR `F` cannot be sent between threads safely + return X { field: blk }; +} + +fn main() { +} diff --git a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr new file mode 100644 index 000000000..bf6ec5c36 --- /dev/null +++ b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -0,0 +1,19 @@ +error[E0277]: `F` cannot be sent between threads safely + --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:5:22 + | +LL | fn foo(blk: F) -> X where F: FnOnce() + 'static { + | ^^^^ `F` cannot be sent between threads safely + | +note: required by a bound in `X` + --> $DIR/closure-bounds-cant-promote-superkind-in-struct.rs:1:43 + | +LL | struct X where F: FnOnce() + 'static + Send { + | ^^^^ required by this bound in `X` +help: consider further restricting this bound + | +LL | fn foo(blk: F) -> X where F: FnOnce() + 'static + std::marker::Send { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.rs b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.rs new file mode 100644 index 000000000..7327d8256 --- /dev/null +++ b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.rs @@ -0,0 +1,13 @@ +fn bar(blk: F) where F: FnOnce() + 'static { +} + +fn foo(x: &()) { + bar(|| { + //~^ ERROR borrowed data escapes + //~| ERROR closure may outlive + let _ = x; + }) +} + +fn main() { +} diff --git a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr new file mode 100644 index 000000000..85df5c1e5 --- /dev/null +++ b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr @@ -0,0 +1,44 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 + | +LL | fn foo(x: &()) { + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the function body +LL | / bar(|| { +LL | | +LL | | +LL | | let _ = x; +LL | | }) + | | ^ + | | | + | |______`x` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:9 + | +LL | bar(|| { + | ^^ may outlive borrowed value `x` +... +LL | let _ = x; + | - `x` is borrowed here + | +note: function requires argument type to outlive `'static` + --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 + | +LL | / bar(|| { +LL | | +LL | | +LL | | let _ = x; +LL | | }) + | |______^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | bar(move || { + | ++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0373, E0521. +For more information about an error, try `rustc --explain E0373`. diff --git a/tests/ui/closures/closure-bounds-subtype.rs b/tests/ui/closures/closure-bounds-subtype.rs new file mode 100644 index 000000000..4888cbfcc --- /dev/null +++ b/tests/ui/closures/closure-bounds-subtype.rs @@ -0,0 +1,16 @@ +fn take_any(_: F) where F: FnOnce() { +} + +fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { +} + +fn give_any(f: F) where F: FnOnce() { + take_any(f); +} + +fn give_owned(f: F) where F: FnOnce() + Send { + take_any(f); + take_const_owned(f); //~ ERROR `F` cannot be shared between threads safely [E0277] +} + +fn main() {} diff --git a/tests/ui/closures/closure-bounds-subtype.stderr b/tests/ui/closures/closure-bounds-subtype.stderr new file mode 100644 index 000000000..8ad8273fc --- /dev/null +++ b/tests/ui/closures/closure-bounds-subtype.stderr @@ -0,0 +1,25 @@ +error[E0277]: `F` cannot be shared between threads safely + --> $DIR/closure-bounds-subtype.rs:13:22 + | +LL | take_const_owned(f); + | ---------------- ^ `F` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `take_const_owned` + --> $DIR/closure-bounds-subtype.rs:4:50 + | +LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { + | ^^^^ required by this bound in `take_const_owned` +help: use parentheses to call this type parameter + | +LL | take_const_owned(f()); + | ++ +help: consider further restricting this bound + | +LL | fn give_owned(f: F) where F: FnOnce() + Send + std::marker::Sync { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr new file mode 100644 index 000000000..8846ccef3 --- /dev/null +++ b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr @@ -0,0 +1,37 @@ +error: lifetime may not live long enough + --> $DIR/expect-region-supply-region-2.rs:14:30 + | +LL | fn expect_bound_supply_named<'x>() { + | -- lifetime `'x` defined here +... +LL | closure_expecting_bound(|x: &'x u32| { + | ^ - let's call the lifetime of this reference `'1` + | | + | requires that `'1` must outlive `'x` + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/expect-region-supply-region-2.rs:20:9 + | +LL | let mut f: Option<&u32> = None; + | ----- `f` declared here, outside of the closure body +... +LL | closure_expecting_bound(|x: &'x u32| { + | - `x` is a reference that is only valid in the closure body +... +LL | f = Some(x); + | ^^^^^^^^^^^ `x` escapes the closure body here + +error: lifetime may not live long enough + --> $DIR/expect-region-supply-region-2.rs:14:30 + | +LL | fn expect_bound_supply_named<'x>() { + | -- lifetime `'x` defined here +... +LL | closure_expecting_bound(|x: &'x u32| { + | ^ requires that `'x` must outlive `'static` + | + = help: consider replacing `'x` with `'static` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.rs b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.rs new file mode 100644 index 000000000..9b51bbd58 --- /dev/null +++ b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.rs @@ -0,0 +1,24 @@ +#![allow(warnings)] + +fn closure_expecting_bound(_: F) +where + F: FnOnce(&u32), +{ +} + +fn expect_bound_supply_named<'x>() { + let mut f: Option<&u32> = None; + + // Here we give a type annotation that `x` should be free. We get + // an error because of that. + closure_expecting_bound(|x: &'x u32| { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + + // Borrowck doesn't get a chance to run, but if it did it should error + // here. + f = Some(x); + }); +} + +fn main() {} diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr new file mode 100644 index 000000000..9aab51c98 --- /dev/null +++ b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.stderr @@ -0,0 +1,22 @@ +error: lifetime may not live long enough + --> $DIR/expect-region-supply-region-2.rs:14:30 + | +LL | fn expect_bound_supply_named<'x>() { + | -- lifetime `'x` defined here +... +LL | closure_expecting_bound(|x: &'x u32| { + | ^ - let's call the lifetime of this reference `'1` + | | + | requires that `'1` must outlive `'x` + +error: lifetime may not live long enough + --> $DIR/expect-region-supply-region-2.rs:14:30 + | +LL | fn expect_bound_supply_named<'x>() { + | -- lifetime `'x` defined here +... +LL | closure_expecting_bound(|x: &'x u32| { + | ^ requires that `'x` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region.rs b/tests/ui/closures/closure-expected-type/expect-region-supply-region.rs new file mode 100644 index 000000000..55c6aa795 --- /dev/null +++ b/tests/ui/closures/closure-expected-type/expect-region-supply-region.rs @@ -0,0 +1,57 @@ +#![allow(warnings)] + +fn closure_expecting_bound(_: F) +where + F: FnOnce(&u32), +{ +} + +fn closure_expecting_free<'a, F>(_: F) +where + F: FnOnce(&'a u32), +{ +} + +fn expect_bound_supply_nothing() { + // Because `x` is inferred to have a bound region, we cannot allow + // it to escape into `f`: + let mut f: Option<&u32> = None; + closure_expecting_bound(|x| { + f = Some(x); //~ ERROR borrowed data escapes outside of closure + }); +} + +fn expect_bound_supply_bound() { + // Because `x` is inferred to have a bound region, we cannot allow + // it to escape into `f`, even with an explicit type annotation on + // closure: + let mut f: Option<&u32> = None; + closure_expecting_bound(|x: &u32| { + f = Some(x); //~ ERROR borrowed data escapes outside of closure + }); +} + +fn expect_free_supply_nothing() { + let mut f: Option<&u32> = None; + closure_expecting_free(|x| f = Some(x)); // OK +} + +fn expect_free_supply_bound() { + let mut f: Option<&u32> = None; + + // Here, even though the annotation `&u32` could be seen as being + // bound in the closure, we permit it to be defined as a free + // region (which is inferred to something in the fn body). + closure_expecting_free(|x: &u32| f = Some(x)); // OK +} + +fn expect_free_supply_named<'x>() { + let mut f: Option<&u32> = None; + + // Here, even though the annotation `&u32` could be seen as being + // bound in the closure, we permit it to be defined as a free + // region (which is inferred to something in the fn body). + closure_expecting_free(|x: &'x u32| f = Some(x)); // OK +} + +fn main() {} diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr b/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr new file mode 100644 index 000000000..0d97fa7e2 --- /dev/null +++ b/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr @@ -0,0 +1,23 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/expect-region-supply-region.rs:20:9 + | +LL | let mut f: Option<&u32> = None; + | ----- `f` declared here, outside of the closure body +LL | closure_expecting_bound(|x| { + | - `x` is a reference that is only valid in the closure body +LL | f = Some(x); + | ^^^^^^^^^^^ `x` escapes the closure body here + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/expect-region-supply-region.rs:30:9 + | +LL | let mut f: Option<&u32> = None; + | ----- `f` declared here, outside of the closure body +LL | closure_expecting_bound(|x: &u32| { + | - `x` is a reference that is only valid in the closure body +LL | f = Some(x); + | ^^^^^^^^^^^ `x` escapes the closure body here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/closures/closure-expected.rs b/tests/ui/closures/closure-expected.rs new file mode 100644 index 000000000..68cac3dd8 --- /dev/null +++ b/tests/ui/closures/closure-expected.rs @@ -0,0 +1,5 @@ +fn main() { + let x = Some(1); + let y = x.or_else(4); + //~^ ERROR expected a `FnOnce<()>` closure, found `{integer}` +} diff --git a/tests/ui/closures/closure-expected.stderr b/tests/ui/closures/closure-expected.stderr new file mode 100644 index 000000000..87a5d67a4 --- /dev/null +++ b/tests/ui/closures/closure-expected.stderr @@ -0,0 +1,16 @@ +error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` + --> $DIR/closure-expected.rs:3:23 + | +LL | let y = x.or_else(4); + | ------- ^ expected an `FnOnce<()>` closure, found `{integer}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Option::::or_else` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-immutable-outer-variable.fixed b/tests/ui/closures/closure-immutable-outer-variable.fixed new file mode 100644 index 000000000..1b0feede3 --- /dev/null +++ b/tests/ui/closures/closure-immutable-outer-variable.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let mut y = true; + foo(Box::new(move || y = !y) as Box<_>); + //~^ ERROR cannot assign to `y`, as it is not declared as mutable +} diff --git a/tests/ui/closures/closure-immutable-outer-variable.rs b/tests/ui/closures/closure-immutable-outer-variable.rs new file mode 100644 index 000000000..50ec1c614 --- /dev/null +++ b/tests/ui/closures/closure-immutable-outer-variable.rs @@ -0,0 +1,13 @@ +// run-rustfix + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let y = true; + foo(Box::new(move || y = !y) as Box<_>); + //~^ ERROR cannot assign to `y`, as it is not declared as mutable +} diff --git a/tests/ui/closures/closure-immutable-outer-variable.rs.fixed b/tests/ui/closures/closure-immutable-outer-variable.rs.fixed new file mode 100644 index 000000000..5c6358beb --- /dev/null +++ b/tests/ui/closures/closure-immutable-outer-variable.rs.fixed @@ -0,0 +1,10 @@ +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let mut y = true; + foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable +} diff --git a/tests/ui/closures/closure-immutable-outer-variable.stderr b/tests/ui/closures/closure-immutable-outer-variable.stderr new file mode 100644 index 000000000..799097889 --- /dev/null +++ b/tests/ui/closures/closure-immutable-outer-variable.stderr @@ -0,0 +1,11 @@ +error[E0594]: cannot assign to `y`, as it is not declared as mutable + --> $DIR/closure-immutable-outer-variable.rs:11:26 + | +LL | let y = true; + | - help: consider changing this to be mutable: `mut y` +LL | foo(Box::new(move || y = !y) as Box<_>); + | ^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/closures/closure-move-sync.rs b/tests/ui/closures/closure-move-sync.rs new file mode 100644 index 000000000..ea2d1434c --- /dev/null +++ b/tests/ui/closures/closure-move-sync.rs @@ -0,0 +1,22 @@ +use std::thread; +use std::sync::mpsc::channel; + +fn bar() { + let (send, recv) = channel(); + let t = thread::spawn(|| { + recv.recv().unwrap(); + //~^^ ERROR `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + }); + + send.send(()); + + t.join().unwrap(); +} + +fn foo() { + let (tx, _rx) = channel(); + thread::spawn(|| tx.send(()).unwrap()); + //~^ ERROR `Sender<()>` cannot be shared between threads safely +} + +fn main() {} diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr new file mode 100644 index 000000000..64e3b51ea --- /dev/null +++ b/tests/ui/closures/closure-move-sync.stderr @@ -0,0 +1,43 @@ +error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + --> $DIR/closure-move-sync.rs:6:27 + | +LL | let t = thread::spawn(|| { + | _____________-------------_^ + | | | + | | required by a bound introduced by this call +LL | | recv.recv().unwrap(); +LL | | +LL | | }); + | |_____^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>` + = note: required for `&std::sync::mpsc::Receiver<()>` to implement `Send` +note: required because it's used within this closure + --> $DIR/closure-move-sync.rs:6:27 + | +LL | let t = thread::spawn(|| { + | ^^ +note: required by a bound in `spawn` + --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + +error[E0277]: `Sender<()>` cannot be shared between threads safely + --> $DIR/closure-move-sync.rs:18:19 + | +LL | thread::spawn(|| tx.send(()).unwrap()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `Sender<()>` + = note: required for `&Sender<()>` to implement `Send` +note: required because it's used within this closure + --> $DIR/closure-move-sync.rs:18:19 + | +LL | thread::spawn(|| tx.send(()).unwrap()); + | ^^ +note: required by a bound in `spawn` + --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-no-fn-1.rs b/tests/ui/closures/closure-no-fn-1.rs new file mode 100644 index 000000000..48c3e4725 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-1.rs @@ -0,0 +1,8 @@ +// Ensure that capturing closures are never coerced to fns +// Especially interesting as non-capturing closures can be. + +fn main() { + let mut a = 0u8; + let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/closures/closure-no-fn-1.stderr b/tests/ui/closures/closure-no-fn-1.stderr new file mode 100644 index 000000000..eab7482e6 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-1.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/closure-no-fn-1.rs:6:29 + | +LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + | ------------ ^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure + | | + | expected due to this + | + = note: expected fn pointer `fn(u8) -> u8` + found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:36]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-1.rs:6:39 + | +LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + | ^ `a` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-no-fn-2.rs b/tests/ui/closures/closure-no-fn-2.rs new file mode 100644 index 000000000..f3066f7a3 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-2.rs @@ -0,0 +1,8 @@ +// Ensure that capturing closures are never coerced to fns +// Especially interesting as non-capturing closures can be. + +fn main() { + let b = 0u8; + let bar: fn() -> u8 = || { b }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/closures/closure-no-fn-2.stderr b/tests/ui/closures/closure-no-fn-2.stderr new file mode 100644 index 000000000..e1f0143ab --- /dev/null +++ b/tests/ui/closures/closure-no-fn-2.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/closure-no-fn-2.rs:6:27 + | +LL | let bar: fn() -> u8 = || { b }; + | ---------- ^^^^^^^^ expected fn pointer, found closure + | | + | expected due to this + | + = note: expected fn pointer `fn() -> u8` + found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:29]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-2.rs:6:32 + | +LL | let bar: fn() -> u8 = || { b }; + | ^ `b` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-no-fn-3.rs b/tests/ui/closures/closure-no-fn-3.rs new file mode 100644 index 000000000..53217c2f1 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-3.rs @@ -0,0 +1,8 @@ +// Ensure that capturing closures are never coerced to fns +// Especially interesting as non-capturing closures can be. + +fn main() { + let b = 0u8; + let baz: fn() -> u8 = (|| { b }) as fn() -> u8; + //~^ ERROR non-primitive cast +} diff --git a/tests/ui/closures/closure-no-fn-3.stderr b/tests/ui/closures/closure-no-fn-3.stderr new file mode 100644 index 000000000..6009389b1 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-3.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:28: 6:30]` as `fn() -> u8` + --> $DIR/closure-no-fn-3.rs:6:27 + | +LL | let baz: fn() -> u8 = (|| { b }) as fn() -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/closures/closure-no-fn-4.rs b/tests/ui/closures/closure-no-fn-4.rs new file mode 100644 index 000000000..275bff645 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-4.rs @@ -0,0 +1,8 @@ +fn main() { + let b = 2; + let _: fn(usize) -> usize = match true { + true => |a| a + 1, + false => |a| a - b, + //~^ ERROR `match` arms have incompatible types + }; +} diff --git a/tests/ui/closures/closure-no-fn-4.stderr b/tests/ui/closures/closure-no-fn-4.stderr new file mode 100644 index 000000000..d1b704884 --- /dev/null +++ b/tests/ui/closures/closure-no-fn-4.stderr @@ -0,0 +1,24 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/closure-no-fn-4.rs:5:18 + | +LL | let _: fn(usize) -> usize = match true { + | _________________________________- +LL | | true => |a| a + 1, + | | --------- this is found to be of type `fn(usize) -> usize` +LL | | false => |a| a - b, + | | ^^^^^^^^^ expected fn pointer, found closure +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `fn(usize) -> usize` + found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:21]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-4.rs:5:26 + | +LL | false => |a| a - b, + | ^ `b` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-no-fn-5.rs b/tests/ui/closures/closure-no-fn-5.rs new file mode 100644 index 000000000..43e3e977e --- /dev/null +++ b/tests/ui/closures/closure-no-fn-5.rs @@ -0,0 +1,12 @@ +// When providing diagnostics about not being able to coerce a capturing-closure +// to fn type, we want to report only upto 4 captures. + +fn main() { + let a = 0u8; + let b = 0u8; + let c = 0u8; + let d = 0u8; + let e = 0u8; + let bar: fn() -> u8 = || { a; b; c; d; e }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/closures/closure-no-fn-5.stderr b/tests/ui/closures/closure-no-fn-5.stderr new file mode 100644 index 000000000..a33b847ea --- /dev/null +++ b/tests/ui/closures/closure-no-fn-5.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/closure-no-fn-5.rs:10:27 + | +LL | let bar: fn() -> u8 = || { a; b; c; d; e }; + | ---------- ^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure + | | + | expected due to this + | + = note: expected fn pointer `fn() -> u8` + found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:29]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-5.rs:10:32 + | +LL | let bar: fn() -> u8 = || { a; b; c; d; e }; + | ^ ^ ^ ^ `d` captured here + | | | | + | | | `c` captured here + | | `b` captured here + | `a` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-referencing-itself-issue-25954.rs b/tests/ui/closures/closure-referencing-itself-issue-25954.rs new file mode 100644 index 000000000..7dd0e5179 --- /dev/null +++ b/tests/ui/closures/closure-referencing-itself-issue-25954.rs @@ -0,0 +1,18 @@ +// Regression test for #25954: detect and reject a closure type that +// references itself. + +use std::cell::{Cell, RefCell}; + +struct A { + x: RefCell>, + b: Cell, +} + +fn main() { + let mut p = A{x: RefCell::new(None), b: Cell::new(4i32)}; + + // This is an error about types of infinite size: + let q = || p.b.set(5i32); //~ ERROR mismatched types + + *(p.x.borrow_mut()) = Some(q); +} diff --git a/tests/ui/closures/closure-referencing-itself-issue-25954.stderr b/tests/ui/closures/closure-referencing-itself-issue-25954.stderr new file mode 100644 index 000000000..8ca43cd1c --- /dev/null +++ b/tests/ui/closures/closure-referencing-itself-issue-25954.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/closure-referencing-itself-issue-25954.rs:15:13 + | +LL | let q = || p.b.set(5i32); + | ^^^^^^^^^^^^^^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-reform-bad.rs b/tests/ui/closures/closure-reform-bad.rs new file mode 100644 index 000000000..0ba48ab51 --- /dev/null +++ b/tests/ui/closures/closure-reform-bad.rs @@ -0,0 +1,12 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +fn call_bare(f: fn(&str)) { + f("Hello "); +} + +fn main() { + let string = "world!"; + let f = |s: &str| println!("{}{}", s, string); + call_bare(f) //~ ERROR mismatched types +} diff --git a/tests/ui/closures/closure-reform-bad.stderr b/tests/ui/closures/closure-reform-bad.stderr new file mode 100644 index 000000000..4c40f70b9 --- /dev/null +++ b/tests/ui/closures/closure-reform-bad.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/closure-reform-bad.rs:11:15 + | +LL | let f = |s: &str| println!("{}{}", s, string); + | --------- the found closure +LL | call_bare(f) + | --------- ^ expected fn pointer, found closure + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `for<'a> fn(&'a str)` + found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:22]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-reform-bad.rs:10:43 + | +LL | let f = |s: &str| println!("{}{}", s, string); + | ^^^^^^ `string` captured here +note: function defined here + --> $DIR/closure-reform-bad.rs:4:4 + | +LL | fn call_bare(f: fn(&str)) { + | ^^^^^^^^^ ----------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-return-type-mismatch.rs b/tests/ui/closures/closure-return-type-mismatch.rs new file mode 100644 index 000000000..1631bb303 --- /dev/null +++ b/tests/ui/closures/closure-return-type-mismatch.rs @@ -0,0 +1,17 @@ +fn main() { + || { + if false { + return "test"; + } + let a = true; + a //~ ERROR mismatched types + }; + + || -> bool { + if false { + return "hello" //~ ERROR mismatched types + }; + let b = true; + b + }; +} diff --git a/tests/ui/closures/closure-return-type-mismatch.stderr b/tests/ui/closures/closure-return-type-mismatch.stderr new file mode 100644 index 000000000..3a89d30a0 --- /dev/null +++ b/tests/ui/closures/closure-return-type-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:7:9 + | +LL | a + | ^ expected `&str`, found `bool` + | +note: return type inferred to be `&str` here + --> $DIR/closure-return-type-mismatch.rs:4:20 + | +LL | return "test"; + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:12:20 + | +LL | return "hello" + | ^^^^^^^ expected `bool`, found `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-return-type-must-be-sized.rs b/tests/ui/closures/closure-return-type-must-be-sized.rs new file mode 100644 index 000000000..8cfa02912 --- /dev/null +++ b/tests/ui/closures/closure-return-type-must-be-sized.rs @@ -0,0 +1,74 @@ +#![feature(unboxed_closures)] + +trait A { + fn a() where Self: Sized; +} + +mod a { + use crate::A; + + pub fn foo>() where F::Output: A { + F::Output::a() + } + + pub fn bar R, R: ?Sized>() {} + + pub fn baz>() where F::Output: A, F::Output: Sized { + F::Output::a() + } +} + +mod b { + use crate::A; + + pub fn foo>() where F::Output: A { + F::Output::a() + } + + pub fn bar R, R: ?Sized>() {} + + pub fn baz>() where F::Output: A, F::Output: Sized { + F::Output::a() + } +} + +mod c { + use crate::A; + + pub fn foo>() where F::Output: A { + F::Output::a() + } + + pub fn bar R, R: ?Sized>() {} + + pub fn baz>() where F::Output: A, F::Output: Sized { + F::Output::a() + } +} + +impl A for Box { + fn a() {} +} + +fn main() { + a::foo:: dyn A>(); //~ ERROR E0277 + a::bar:: dyn A, _>(); //~ ERROR E0277 + a::baz:: dyn A>(); //~ ERROR E0277 + a::foo:: Box>(); // ok + a::bar:: Box, _>(); // ok + a::baz:: Box>(); // ok + + b::foo:: dyn A>(); //~ ERROR E0277 + b::bar:: dyn A, _>(); //~ ERROR E0277 + b::baz:: dyn A>(); //~ ERROR E0277 + b::foo:: Box>(); // ok + b::bar:: Box, _>(); // ok + b::baz:: Box>(); // ok + + c::foo:: dyn A>(); //~ ERROR E0277 + c::bar:: dyn A, _>(); //~ ERROR E0277 + c::baz:: dyn A>(); //~ ERROR E0277 + c::foo:: Box>(); // ok + c::bar:: Box, _>(); // ok + c::baz:: Box>(); // ok +} diff --git a/tests/ui/closures/closure-return-type-must-be-sized.stderr b/tests/ui/closures/closure-return-type-must-be-sized.stderr new file mode 100644 index 000000000..d4fc723fa --- /dev/null +++ b/tests/ui/closures/closure-return-type-must-be-sized.stderr @@ -0,0 +1,99 @@ +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:54:5 + | +LL | a::foo:: dyn A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:55:14 + | +LL | a::bar:: dyn A, _>(); + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` +note: required by a bound in `a::bar` + --> $DIR/closure-return-type-must-be-sized.rs:14:19 + | +LL | pub fn bar R, R: ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `bar` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:56:5 + | +LL | a::baz:: dyn A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:61:5 + | +LL | b::foo:: dyn A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:62:14 + | +LL | b::bar:: dyn A, _>(); + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` +note: required by a bound in `b::bar` + --> $DIR/closure-return-type-must-be-sized.rs:28:19 + | +LL | pub fn bar R, R: ?Sized>() {} + | ^^^^^^^^^ required by this bound in `bar` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:63:5 + | +LL | b::baz:: dyn A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:68:5 + | +LL | c::foo:: dyn A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:69:14 + | +LL | c::bar:: dyn A, _>(); + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` +note: required by a bound in `c::bar` + --> $DIR/closure-return-type-must-be-sized.rs:42:19 + | +LL | pub fn bar R, R: ?Sized>() {} + | ^^^^^^^^^^^^ required by this bound in `bar` + +error[E0277]: the size for values of type `dyn A` cannot be known at compilation time + --> $DIR/closure-return-type-must-be-sized.rs:70:5 + | +LL | c::baz:: dyn A>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = note: required because it appears within the type `fn() -> dyn A` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-wrong-kind.rs b/tests/ui/closures/closure-wrong-kind.rs new file mode 100644 index 000000000..9bf38bfb6 --- /dev/null +++ b/tests/ui/closures/closure-wrong-kind.rs @@ -0,0 +1,12 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +struct X; +fn foo(_: T) {} +fn bar(_: T) {} + +fn main() { + let x = X; + let closure = |_| foo(x); //~ ERROR E0525 + bar(closure); +} diff --git a/tests/ui/closures/closure-wrong-kind.stderr b/tests/ui/closures/closure-wrong-kind.stderr new file mode 100644 index 000000000..9ea55d764 --- /dev/null +++ b/tests/ui/closures/closure-wrong-kind.stderr @@ -0,0 +1,21 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-wrong-kind.rs:10:19 + | +LL | let closure = |_| foo(x); + | ^^^ - closure is `FnOnce` because it moves the variable `x` out of its environment + | | + | this closure implements `FnOnce`, not `Fn` +LL | bar(closure); + | --- ------- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/closure-wrong-kind.rs:6:11 + | +LL | fn bar(_: T) {} + | ^^^^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/closure_cap_coerce_many_fail.rs b/tests/ui/closures/closure_cap_coerce_many_fail.rs new file mode 100644 index 000000000..9133a2921 --- /dev/null +++ b/tests/ui/closures/closure_cap_coerce_many_fail.rs @@ -0,0 +1,39 @@ +fn add(a: i32, b: i32) -> i32 { + a + b +} +fn main() { + // We shouldn't coerce capturing closure to a function + let cap = 0; + let _ = match "+" { + "+" => add, + "-" => |a, b| (a - b + cap) as i32, + _ => unimplemented!(), + }; + //~^^^ ERROR `match` arms have incompatible types + + + // We shouldn't coerce capturing closure to a non-capturing closure + let _ = match "+" { + "+" => |a, b| (a + b) as i32, + "-" => |a, b| (a - b + cap) as i32, + _ => unimplemented!(), + }; + //~^^^ ERROR `match` arms have incompatible types + + + // We shouldn't coerce non-capturing closure to a capturing closure + let _ = match "+" { + "+" => |a, b| (a + b + cap) as i32, + "-" => |a, b| (a - b) as i32, + _ => unimplemented!(), + }; + //~^^^ ERROR `match` arms have incompatible types + + // We shouldn't coerce capturing closure to a capturing closure + let _ = match "+" { + "+" => |a, b| (a + b + cap) as i32, + "-" => |a, b| (a - b + cap) as i32, + _ => unimplemented!(), + }; + //~^^^ ERROR `match` arms have incompatible types +} diff --git a/tests/ui/closures/closure_cap_coerce_many_fail.stderr b/tests/ui/closures/closure_cap_coerce_many_fail.stderr new file mode 100644 index 000000000..ca8a43328 --- /dev/null +++ b/tests/ui/closures/closure_cap_coerce_many_fail.stderr @@ -0,0 +1,82 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/closure_cap_coerce_many_fail.rs:9:16 + | +LL | let _ = match "+" { + | _____________- +LL | | "+" => add, + | | --- this is found to be of type `fn(i32, i32) -> i32 {add}` +LL | | "-" => |a, b| (a - b + cap) as i32, + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found closure +LL | | _ => unimplemented!(), +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn item `fn(i32, i32) -> i32 {add}` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:9:16: 9:22]` + +error[E0308]: `match` arms have incompatible types + --> $DIR/closure_cap_coerce_many_fail.rs:18:16 + | +LL | let _ = match "+" { + | _____________- +LL | | "+" => |a, b| (a + b) as i32, + | | --------------------- + | | | + | | the expected closure + | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22]` +LL | | "-" => |a, b| (a - b + cap) as i32, + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure +LL | | _ => unimplemented!(), +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:17:16: 17:22]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:18:16: 18:22]` + = note: no two closures, even if identical, have the same type + = help: consider boxing your closure and/or using it as a trait object + +error[E0308]: `match` arms have incompatible types + --> $DIR/closure_cap_coerce_many_fail.rs:27:16 + | +LL | let _ = match "+" { + | _____________- +LL | | "+" => |a, b| (a + b + cap) as i32, + | | --------------------------- + | | | + | | the expected closure + | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22]` +LL | | "-" => |a, b| (a - b) as i32, + | | ^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure +LL | | _ => unimplemented!(), +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:26:16: 26:22]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:27:16: 27:22]` + = note: no two closures, even if identical, have the same type + = help: consider boxing your closure and/or using it as a trait object + +error[E0308]: `match` arms have incompatible types + --> $DIR/closure_cap_coerce_many_fail.rs:35:16 + | +LL | let _ = match "+" { + | _____________- +LL | | "+" => |a, b| (a + b + cap) as i32, + | | --------------------------- + | | | + | | the expected closure + | | this is found to be of type `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22]` +LL | | "-" => |a, b| (a - b + cap) as i32, + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure +LL | | _ => unimplemented!(), +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:34:16: 34:22]` + found closure `[closure@$DIR/closure_cap_coerce_many_fail.rs:35:16: 35:22]` + = note: no two closures, even if identical, have the same type + = help: consider boxing your closure and/or using it as a trait object + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure_no_cap_coerce_many_check_pass.rs b/tests/ui/closures/closure_no_cap_coerce_many_check_pass.rs new file mode 100644 index 000000000..ce461810e --- /dev/null +++ b/tests/ui/closures/closure_no_cap_coerce_many_check_pass.rs @@ -0,0 +1,166 @@ +// check-pass +// Ensure non-capturing Closure passes CoerceMany. +fn foo(x: usize) -> usize { + 0 +} + +fn bar(x: usize) -> usize { + 1 +} + +fn main() { + // One FnDef and one non-capturing Closure + let _ = match 0 { + 0 => foo, + 2 => |a| 2, + _ => unimplemented!(), + }; + + let _ = match 0 { + 2 => |a| 2, + 0 => foo, + _ => unimplemented!(), + }; + + let _ = [foo, |a| 2]; + let _ = [|a| 2, foo]; + + + + // Two FnDefs and one non-capturing Closure + let _ = match 0 { + 0 => foo, + 1 => bar, + 2 => |a| 2, + _ => unimplemented!(), + }; + + let _ = match 0 { + 0 => foo, + 2 => |a| 2, + 1 => bar, + _ => unimplemented!(), + }; + + let _ = match 0 { + 2 => |a| 2, + 0 => foo, + 1 => bar, + _ => unimplemented!(), + }; + + let _ = [foo, bar, |a| 2]; + let _ = [foo, |a| 2, bar]; + let _ = [|a| 2, foo, bar]; + + + + // One FnDef and two non-capturing Closures + let _ = match 0 { + 0 => foo, + 1 => |a| 1, + 2 => |a| 2, + _ => unimplemented!(), + }; + + let _ = match 0 { + 1 => |a| 1, + 0 => foo, + 2 => |a| 2, + _ => unimplemented!(), + }; + + let _ = match 0 { + 1 => |a| 1, + 2 => |a| 2, + 0 => foo, + _ => unimplemented!(), + }; + + let _ = [foo, |a| 1, |a| 2]; + let _ = [|a| 1, foo, |a| 2]; + let _ = [|a| 1, |a| 2, foo]; + + + + // Three non-capturing Closures + let _ = match 0 { + 0 => |a: usize| 0, + 1 => |a| 1, + 2 => |a| 2, + _ => unimplemented!(), + }; + + let _ = [|a: usize| 0, |a| 1, |a| 2]; + + + + // Three non-capturing Closures variable + let clo0 = |a: usize| 0; + let clo1 = |a| 1; + let clo2 = |a| 2; + let _ = match 0 { + 0 => clo0, + 1 => clo1, + 2 => clo2, + _ => unimplemented!(), + }; + + let clo0 = |a: usize| 0; + let clo1 = |a| 1; + let clo2 = |a| 2; + let _ = [clo0, clo1, clo2]; + + + + // --- Function pointer related part + + // Closure is not in a variable + type FnPointer = fn(usize) -> usize; + + let _ = match 0 { + 0 => foo as FnPointer, + 2 => |a| 2, + _ => unimplemented!(), + }; + let _ = match 0 { + 2 => |a| 2, + 0 => foo as FnPointer, + _ => unimplemented!(), + }; + let _ = [foo as FnPointer, |a| 2]; + let _ = [|a| 2, foo as FnPointer]; + let _ = [foo, bar, |x| x]; + let _ = [foo as FnPointer, bar, |x| x]; + let _ = [foo, bar as FnPointer, |x| x]; + let _ = [foo, bar, (|x| x) as FnPointer]; + let _ = [foo as FnPointer, bar as FnPointer, |x| x]; + + // Closure is in a variable + let x = |a| 2; + let _ = match 0 { + 0 => foo as FnPointer, + 2 => x, + _ => unimplemented!(), + }; + let x = |a| 2; + let _ = match 0 { + 2 => x, + 0 => foo as FnPointer, + _ => unimplemented!(), + }; + let x = |a| 2; + let _ = [foo as FnPointer, x]; + let _ = [x, foo as FnPointer]; + + let x = |a| 2; + let _ = [foo, bar, x]; + let x: FnPointer = |a| 2; + let _ = [foo, bar, x]; + let x = |a| 2; + let _ = [foo, bar as FnPointer, x]; + let x = |a| 2; + let _ = [foo as FnPointer, bar, x]; + let x = |a| 2; + let _ = [foo as FnPointer, bar as FnPointer, x]; +} diff --git a/tests/ui/closures/closure_no_cap_coerce_many_run_pass.rs b/tests/ui/closures/closure_no_cap_coerce_many_run_pass.rs new file mode 100644 index 000000000..3c5fe8a55 --- /dev/null +++ b/tests/ui/closures/closure_no_cap_coerce_many_run_pass.rs @@ -0,0 +1,59 @@ +// run-pass +// Ensure non-capturing Closure passing CoerceMany work correctly. +fn foo(_: usize) -> usize { + 0 +} + +fn bar(_: usize) -> usize { + 1 +} + +fn add(a: i32, b: i32) -> i32 { + a + b +} + +fn main() { + // Coerce result check + + type FnPointer = fn(usize) -> usize; + + let c = |x| x; + let c_pointer: FnPointer = c; + assert_eq!(c_pointer(42), 42); + + let f = match 0 { + 0 => foo, + 1 => |_| 1, + _ => unimplemented!(), + }; + assert_eq!(f(42), 0); + + let f = match 2 { + 2 => |_| 2, + 0 => foo, + _ => unimplemented!(), + }; + assert_eq!(f(42), 2); + + let f = match 1 { + 0 => foo, + 1 => bar, + 2 => |_| 2, + _ => unimplemented!(), + }; + assert_eq!(f(42), 1); + + let clo0 = |_: usize| 0; + let clo1 = |_| 1; + let clo2 = |_| 2; + let f = match 0 { + 0 => clo0, + 1 => clo1, + 2 => clo2, + _ => unimplemented!(), + }; + assert_eq!(f(42), 0); + + let funcs = [add, |a, b| (a - b) as i32]; + assert_eq!([funcs[0](5, 5), funcs[1](5, 5)], [10, 0]); +} diff --git a/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.mir.stderr b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.mir.stderr new file mode 100644 index 000000000..2f9c7973b --- /dev/null +++ b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:15:23 + | +LL | let result: i32 = foo(5, 5); + | ^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:24:23 + | +LL | let result: i32 = foo(5, 5); + | ^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs new file mode 100644 index 000000000..bdb3eb23c --- /dev/null +++ b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.rs @@ -0,0 +1,25 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +// Ensure we get unsafe function after coercion +unsafe fn add(a: i32, b: i32) -> i32 { + a + b +} +fn main() { + // We can coerce non-capturing closure to unsafe function + let foo = match "+" { + "+" => add, + "-" => |a, b| (a - b) as i32, + _ => unimplemented!(), + }; + let result: i32 = foo(5, 5); //~ ERROR call to unsafe function + + + // We can coerce unsafe function to non-capturing closure + let foo = match "+" { + "-" => |a, b| (a - b) as i32, + "+" => add, + _ => unimplemented!(), + }; + let result: i32 = foo(5, 5); //~ ERROR call to unsafe function +} diff --git a/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.thir.stderr b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.thir.stderr new file mode 100644 index 000000000..2f9c7973b --- /dev/null +++ b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_0.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:15:23 + | +LL | let result: i32 = foo(5, 5); + | ^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/closure_no_cap_coerce_many_unsafe_0.rs:24:23 + | +LL | let result: i32 = foo(5, 5); + | ^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs new file mode 100644 index 000000000..a6d6125a1 --- /dev/null +++ b/tests/ui/closures/closure_no_cap_coerce_many_unsafe_1.rs @@ -0,0 +1,23 @@ +// run-pass +// Ensure we get correct unsafe function after coercion +unsafe fn add(a: i32, b: i32) -> i32 { + a + b +} +fn main() { + // We can coerce non-capturing closure to unsafe function + let foo = match "+" { + "+" => add, + "-" => |a, b| (a - b) as i32, + _ => unimplemented!(), + }; + assert_eq!(unsafe { foo(5, 5) }, 10); + + + // We can coerce unsafe function to non-capturing closure + let foo = match "-" { + "-" => |a, b| (a - b) as i32, + "+" => add, + _ => unimplemented!(), + }; + assert_eq!(unsafe { foo(5, 5) }, 0); +} diff --git a/tests/ui/closures/closure_promotion.rs b/tests/ui/closures/closure_promotion.rs new file mode 100644 index 000000000..47a8fc090 --- /dev/null +++ b/tests/ui/closures/closure_promotion.rs @@ -0,0 +1,5 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + let x: &'static _ = &|| { let z = 3; z }; +} diff --git a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr new file mode 100644 index 000000000..a60100dda --- /dev/null +++ b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:5:31 + | +LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs new file mode 100644 index 000000000..57358fbdd --- /dev/null +++ b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.rs @@ -0,0 +1,8 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +fn main() { + let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; + //~^ ERROR E0133 + let _: unsafe fn() = || unsafe { ::std::pin::Pin::new_unchecked(&0_u8); }; // OK +} diff --git a/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr new file mode 100644 index 000000000..8c516e890 --- /dev/null +++ b/tests/ui/closures/coerce-unsafe-closure-to-unsafe-fn-ptr.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `Pin::

::new_unchecked` is unsafe and requires unsafe function or block + --> $DIR/coerce-unsafe-closure-to-unsafe-fn-ptr.rs:5:31 + | +LL | let _: unsafe fn() = || { ::std::pin::Pin::new_unchecked(&0_u8); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/closures/coerce-unsafe-to-closure.rs b/tests/ui/closures/coerce-unsafe-to-closure.rs new file mode 100644 index 000000000..78bdd36f9 --- /dev/null +++ b/tests/ui/closures/coerce-unsafe-to-closure.rs @@ -0,0 +1,4 @@ +fn main() { + let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); + //~^ ERROR E0277 +} diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr new file mode 100644 index 000000000..449cd0b31 --- /dev/null +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -0,0 +1,16 @@ +error[E0277]: expected a `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + --> $DIR/coerce-unsafe-to-closure.rs:2:44 + | +LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); + | --- ^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/deeply-nested_closures.rs b/tests/ui/closures/deeply-nested_closures.rs new file mode 100644 index 000000000..a02684ee1 --- /dev/null +++ b/tests/ui/closures/deeply-nested_closures.rs @@ -0,0 +1,23 @@ +// Check that this can be compiled in a reasonable time. + +// build-pass + +fn main() { + // 96 nested closures + let x = (); + || || || || || || || || + || || || || || || || || + || || || || || || || || + || || || || || || || || + + || || || || || || || || + || || || || || || || || + || || || || || || || || + || || || || || || || || + + || || || || || || || || + || || || || || || || || + || || || || || || || || + || || || || || || || || + [&(), &x]; +} diff --git a/tests/ui/closures/diverging-closure.rs b/tests/ui/closures/diverging-closure.rs new file mode 100644 index 000000000..1213a883e --- /dev/null +++ b/tests/ui/closures/diverging-closure.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:oops +// ignore-emscripten no processes + +fn main() { + let func = || -> ! { + panic!("oops"); + }; + func(); +} diff --git a/tests/ui/closures/issue-101696.rs b/tests/ui/closures/issue-101696.rs new file mode 100644 index 000000000..0a358bd16 --- /dev/null +++ b/tests/ui/closures/issue-101696.rs @@ -0,0 +1,36 @@ +// check-pass + +use std::marker::PhantomData; + +#[derive(Default)] +struct MyType<'a> { + field: usize, + _phantom: PhantomData<&'a ()>, +} + +#[derive(Default)] +struct MyTypeVariant<'a> { + field: usize, + _phantom: PhantomData<&'a ()>, +} + +trait AsVariantTrait { + type Type; +} + +impl<'a> AsVariantTrait for MyType<'a> { + type Type = MyTypeVariant<'a>; +} + +type Variant = ::Type; + +fn foo(f: F) { + let input = T::default(); + f(input); +} + +fn main() { + foo(|a: ::Type| { + a.field; + }); +} diff --git a/tests/ui/closures/issue-102089-multiple-opaque-cast.rs b/tests/ui/closures/issue-102089-multiple-opaque-cast.rs new file mode 100644 index 000000000..043bf06a1 --- /dev/null +++ b/tests/ui/closures/issue-102089-multiple-opaque-cast.rs @@ -0,0 +1,17 @@ +// edition:2021 +// check-pass + +pub struct Example<'a, T> { + a: T, + b: &'a T, +} + +impl<'a, T> Example<'a, T> { + pub fn error_trying_to_destructure_self_in_closure(self) { + let closure = || { + let Self { a, b } = self; + }; + } +} + +fn main() {} diff --git a/tests/ui/closures/issue-10398.rs b/tests/ui/closures/issue-10398.rs new file mode 100644 index 000000000..f76d09cd0 --- /dev/null +++ b/tests/ui/closures/issue-10398.rs @@ -0,0 +1,9 @@ +fn main() { + let x: Box<_> = Box::new(1); + let f = move|| { + let _a = x; + drop(x); + //~^ ERROR: use of moved value: `x` + }; + f(); +} diff --git a/tests/ui/closures/issue-10398.stderr b/tests/ui/closures/issue-10398.stderr new file mode 100644 index 000000000..423b79daf --- /dev/null +++ b/tests/ui/closures/issue-10398.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `x` + --> $DIR/issue-10398.rs:5:14 + | +LL | let _a = x; + | - value moved here +LL | drop(x); + | ^ value used here after move + | + = note: move occurs because `x` has type `Box`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/issue-23012-supertrait-signature-inference.rs b/tests/ui/closures/issue-23012-supertrait-signature-inference.rs new file mode 100644 index 000000000..5899b703e --- /dev/null +++ b/tests/ui/closures/issue-23012-supertrait-signature-inference.rs @@ -0,0 +1,29 @@ +// check-pass +// Checks that we can infer a closure signature even if the `FnOnce` bound is +// a supertrait of the obligations we have currently registered for the Ty var. + +pub trait Receive: FnOnce(Result) { + fn receive(self, res: Result); +} + +impl)> Receive for F { + fn receive(self, res: Result) { + self(res) + } +} + +pub trait Async { + fn receive>(self, f: F); +} + +impl Async for Result { + fn receive>(self, f: F) { + f(self) + } +} + +pub fn main() { + Ok::(123).receive(|res| { + res.unwrap(); + }); +} diff --git a/tests/ui/closures/issue-41366.rs b/tests/ui/closures/issue-41366.rs new file mode 100644 index 000000000..acc1c6ae1 --- /dev/null +++ b/tests/ui/closures/issue-41366.rs @@ -0,0 +1,13 @@ +// check-pass + +trait T<'x> { + type V; +} + +impl<'g> T<'g> for u32 { + type V = u16; +} + +fn main() { + (&|_| ()) as &dyn for<'x> Fn(>::V); +} diff --git a/tests/ui/closures/issue-42463.rs b/tests/ui/closures/issue-42463.rs new file mode 100644 index 000000000..51d6ea3f7 --- /dev/null +++ b/tests/ui/closures/issue-42463.rs @@ -0,0 +1,32 @@ +// run-pass +use std::ops::{Deref, DerefMut}; + +struct CheckedDeref { + value: T, + check: F +} + +impl bool, T> Deref for CheckedDeref { + type Target = T; + fn deref(&self) -> &T { + assert!((self.check)(&self.value)); + &self.value + } +} + +impl bool, T> DerefMut for CheckedDeref { + fn deref_mut(&mut self) -> &mut T { + assert!((self.check)(&self.value)); + &mut self.value + } +} + + +fn main() { + let mut v = CheckedDeref { + value: vec![0], + check: |v: &Vec<_>| !v.is_empty() + }; + v.push(1); + assert_eq!(*v, vec![0, 1]); +} diff --git a/tests/ui/closures/issue-46742.rs b/tests/ui/closures/issue-46742.rs new file mode 100644 index 000000000..cd8dc4869 --- /dev/null +++ b/tests/ui/closures/issue-46742.rs @@ -0,0 +1,9 @@ +// check-pass +fn main() { + let _: i32 = (match "" { + "+" => ::std::ops::Add::add, + "-" => ::std::ops::Sub::sub, + "<" => |a,b| (a < b) as i32, + _ => unimplemented!(), + })(5, 5); +} diff --git a/tests/ui/closures/issue-48109.rs b/tests/ui/closures/issue-48109.rs new file mode 100644 index 000000000..ce1f2a036 --- /dev/null +++ b/tests/ui/closures/issue-48109.rs @@ -0,0 +1,14 @@ +// check-pass +fn useful(i: usize) -> usize { + i +} + +fn useful2(i: usize) -> usize { + i +} + +fn main() { + for f in &[useful, useful2, |x| x] { + println!("{}", f(6)); + } +} diff --git a/tests/ui/closures/issue-52437.rs b/tests/ui/closures/issue-52437.rs new file mode 100644 index 000000000..6ac5380a5 --- /dev/null +++ b/tests/ui/closures/issue-52437.rs @@ -0,0 +1,5 @@ +fn main() { + [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + //~^ ERROR: invalid label name `'static` + //~| ERROR: type annotations needed +} diff --git a/tests/ui/closures/issue-52437.stderr b/tests/ui/closures/issue-52437.stderr new file mode 100644 index 000000000..9ba24c7a8 --- /dev/null +++ b/tests/ui/closures/issue-52437.stderr @@ -0,0 +1,20 @@ +error: invalid label name `'static` + --> $DIR/issue-52437.rs:2:13 + | +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^^^^^^^ + +error[E0282]: type annotations needed + --> $DIR/issue-52437.rs:2:30 + | +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | [(); &(&'static: loop { |x: /* Type */| {}; }) as *const _ as usize] + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closures/issue-67123.rs b/tests/ui/closures/issue-67123.rs new file mode 100644 index 000000000..014c530e6 --- /dev/null +++ b/tests/ui/closures/issue-67123.rs @@ -0,0 +1,5 @@ +fn foo(t: T) { + || { t; t; }; //~ ERROR: use of moved value +} + +fn main() {} diff --git a/tests/ui/closures/issue-67123.stderr b/tests/ui/closures/issue-67123.stderr new file mode 100644 index 000000000..7877c7334 --- /dev/null +++ b/tests/ui/closures/issue-67123.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of moved value: `t` + --> $DIR/issue-67123.rs:2:13 + | +LL | || { t; t; }; + | - ^ value used here after move + | | + | value moved here + | + = note: move occurs because `t` has type `T`, which does not implement the `Copy` trait +help: consider restricting type parameter `T` + | +LL | fn foo(t: T) { + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/issue-6801.rs b/tests/ui/closures/issue-6801.rs new file mode 100644 index 000000000..cecb08f00 --- /dev/null +++ b/tests/ui/closures/issue-6801.rs @@ -0,0 +1,21 @@ +// Creating a stack closure which references a box and then +// transferring ownership of the box before invoking the stack +// closure results in a crash. + + + +fn twice(x: Box) -> usize { + *x * 2 +} + +fn invoke(f: F) where F: FnOnce() -> usize { + f(); +} + +fn main() { + let x : Box = Box::new(9); + let sq = || { *x * *x }; + + twice(x); //~ ERROR: cannot move out of + invoke(sq); +} diff --git a/tests/ui/closures/issue-6801.stderr b/tests/ui/closures/issue-6801.stderr new file mode 100644 index 000000000..6a40db0d5 --- /dev/null +++ b/tests/ui/closures/issue-6801.stderr @@ -0,0 +1,16 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/issue-6801.rs:19:13 + | +LL | let sq = || { *x * *x }; + | -- -- borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | +LL | twice(x); + | ^ move out of `x` occurs here +LL | invoke(sq); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/closures/issue-68025.rs b/tests/ui/closures/issue-68025.rs new file mode 100644 index 000000000..261bfd60a --- /dev/null +++ b/tests/ui/closures/issue-68025.rs @@ -0,0 +1,12 @@ +// check-pass + +fn foo(_: G, _: Box) +where + F: Fn(), + G: Fn(Box), +{ +} + +fn main() { + foo(|f| (*f)(), Box::new(|| {})); +} diff --git a/tests/ui/closures/issue-72408-nested-closures-exponential.rs b/tests/ui/closures/issue-72408-nested-closures-exponential.rs new file mode 100644 index 000000000..2d6ba9365 --- /dev/null +++ b/tests/ui/closures/issue-72408-nested-closures-exponential.rs @@ -0,0 +1,59 @@ +// build-pass + +// Closures include captured types twice in a type tree. +// +// Wrapping one closure with another leads to doubling +// the amount of types in the type tree. +// +// This test ensures that rust can handle +// deeply nested type trees with a lot +// of duplicated subtrees. + +fn dup(f: impl Fn(i32) -> i32) -> impl Fn(i32) -> i32 { + move |a| f(a * 2) +} + +fn main() { + let f = |a| a; + + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + + // Compiler dies around here if it tries + // to walk the tree exhaustively. + + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + let f = dup(f); + + println!("Type size was at least {}", f(1)); +} diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs new file mode 100644 index 000000000..4cdb9f491 --- /dev/null +++ b/tests/ui/closures/issue-78720.rs @@ -0,0 +1,19 @@ +fn server() -> impl { +//~^ ERROR at least one trait must be specified + ().map2(|| "") +} + +trait FilterBase2 { + fn map2(self, f: F) -> Map2 {} + //~^ ERROR mismatched types + //~^^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +struct Map2 { + _func: F, + //~^ ERROR cannot find type `F` in this scope +} + +impl FilterBase2 for F {} + +fn main() {} diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr new file mode 100644 index 000000000..1e860d32b --- /dev/null +++ b/tests/ui/closures/issue-78720.stderr @@ -0,0 +1,53 @@ +error: at least one trait must be specified + --> $DIR/issue-78720.rs:1:16 + | +LL | fn server() -> impl { + | ^^^^ + +error[E0412]: cannot find type `F` in this scope + --> $DIR/issue-78720.rs:13:12 + | +LL | _func: F, + | ^ + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here + | +help: a trait with a similar name exists + | +LL | _func: Fn, + | ~~ +help: you might be missing a type parameter + | +LL | struct Map2 { + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-78720.rs:7:39 + | +LL | fn map2(self, f: F) -> Map2 {} + | ^^ expected struct `Map2`, found `()` + | + = note: expected struct `Map2` + found unit type `()` + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-78720.rs:7:16 + | +LL | fn map2(self, f: F) -> Map2 {} + | ^^^^ doesn't have a size known at compile-time + | + = help: unsized fn params are gated as an unstable feature +help: consider further restricting `Self` + | +LL | fn map2(self, f: F) -> Map2 where Self: Sized {} + | +++++++++++++++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn map2(&self, f: F) -> Map2 {} + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308, E0412. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/issue-80313-mutable-borrow-in-closure.rs b/tests/ui/closures/issue-80313-mutable-borrow-in-closure.rs new file mode 100644 index 000000000..ff210ae06 --- /dev/null +++ b/tests/ui/closures/issue-80313-mutable-borrow-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr new file mode 100644 index 000000000..239f071ca --- /dev/null +++ b/tests/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -0,0 +1,17 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5 + | +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = || { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs b/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs new file mode 100644 index 000000000..8f2d8a676 --- /dev/null +++ b/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr new file mode 100644 index 000000000..1ec279f03 --- /dev/null +++ b/tests/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -0,0 +1,17 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5 + | +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = move || { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-80313-mutation-in-closure.rs b/tests/ui/closures/issue-80313-mutation-in-closure.rs new file mode 100644 index 000000000..e082ea562 --- /dev/null +++ b/tests/ui/closures/issue-80313-mutation-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/tests/ui/closures/issue-80313-mutation-in-closure.stderr b/tests/ui/closures/issue-80313-mutation-in-closure.stderr new file mode 100644 index 000000000..22a62ce73 --- /dev/null +++ b/tests/ui/closures/issue-80313-mutation-in-closure.stderr @@ -0,0 +1,17 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-closure.rs:6:5 + | +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = || { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-80313-mutation-in-move-closure.rs b/tests/ui/closures/issue-80313-mutation-in-move-closure.rs new file mode 100644 index 000000000..f66bf4e06 --- /dev/null +++ b/tests/ui/closures/issue-80313-mutation-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr b/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr new file mode 100644 index 000000000..a2222f8cc --- /dev/null +++ b/tests/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -0,0 +1,17 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-move-closure.rs:6:5 + | +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = move || { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-81700-mut-borrow.rs b/tests/ui/closures/issue-81700-mut-borrow.rs new file mode 100644 index 000000000..a27a61601 --- /dev/null +++ b/tests/ui/closures/issue-81700-mut-borrow.rs @@ -0,0 +1,5 @@ +fn foo(x: &mut u32) { + let bar = || { foo(x); }; + bar(); //~ ERROR cannot borrow +} +fn main() {} diff --git a/tests/ui/closures/issue-81700-mut-borrow.stderr b/tests/ui/closures/issue-81700-mut-borrow.stderr new file mode 100644 index 000000000..03b18c3f7 --- /dev/null +++ b/tests/ui/closures/issue-81700-mut-borrow.stderr @@ -0,0 +1,16 @@ +error[E0596]: cannot borrow `bar` as mutable, as it is not declared as mutable + --> $DIR/issue-81700-mut-borrow.rs:3:5 + | +LL | let bar = || { foo(x); }; + | - calling `bar` requires mutable binding due to mutable borrow of `x` +LL | bar(); + | ^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut bar = || { foo(x); }; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-82438-mut-without-upvar.rs b/tests/ui/closures/issue-82438-mut-without-upvar.rs new file mode 100644 index 000000000..5d88e1e77 --- /dev/null +++ b/tests/ui/closures/issue-82438-mut-without-upvar.rs @@ -0,0 +1,28 @@ +use std::error::Error; +struct A { +} + +impl A { + pub fn new() -> A { + A { + } + } + + pub fn f<'a>( + &'a self, + team_name: &'a str, + c: &'a mut dyn FnMut(String, String, u64, u64) + ) -> Result<(), Box> { + Ok(()) + } +} + + +fn main() { + let A = A::new(); + let participant_name = "A"; + + let c = |a, b, c, d| {}; + + A.f(participant_name, &mut c); //~ ERROR cannot borrow +} diff --git a/tests/ui/closures/issue-82438-mut-without-upvar.stderr b/tests/ui/closures/issue-82438-mut-without-upvar.stderr new file mode 100644 index 000000000..f0951b7d1 --- /dev/null +++ b/tests/ui/closures/issue-82438-mut-without-upvar.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable + --> $DIR/issue-82438-mut-without-upvar.rs:27:27 + | +LL | A.f(participant_name, &mut c); + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut c = |a, b, c, d| {}; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-84044-drop-non-mut.rs b/tests/ui/closures/issue-84044-drop-non-mut.rs new file mode 100644 index 000000000..aed7750f1 --- /dev/null +++ b/tests/ui/closures/issue-84044-drop-non-mut.rs @@ -0,0 +1,6 @@ +// #84044: This used to ICE. + +fn main() { + let f = || {}; + drop(&mut f); //~ ERROR cannot borrow `f` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/closures/issue-84044-drop-non-mut.stderr b/tests/ui/closures/issue-84044-drop-non-mut.stderr new file mode 100644 index 000000000..5335a056c --- /dev/null +++ b/tests/ui/closures/issue-84044-drop-non-mut.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/issue-84044-drop-non-mut.rs:5:10 + | +LL | drop(&mut f); + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = || {}; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/closures/issue-84128.rs b/tests/ui/closures/issue-84128.rs new file mode 100644 index 000000000..30733871b --- /dev/null +++ b/tests/ui/closures/issue-84128.rs @@ -0,0 +1,16 @@ +// test for issue 84128 +// missing suggestion for similar ADT type with diffetent generic parameter +// on closure ReturnNoExpression + +struct Foo(T); + +fn main() { + || { + if false { + return Foo(0); + } + + Foo(()) + //~^ ERROR mismatched types [E0308] + }; +} diff --git a/tests/ui/closures/issue-84128.stderr b/tests/ui/closures/issue-84128.stderr new file mode 100644 index 000000000..1cd8949b8 --- /dev/null +++ b/tests/ui/closures/issue-84128.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-84128.rs:13:13 + | +LL | Foo(()) + | --- ^^ expected integer, found `()` + | | + | arguments to this struct are incorrect + | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-84128.rs:13:9 + | +LL | Foo(()) + | ^^^^--^ + | | + | this argument influences the type of `Foo` +note: tuple struct defined here + --> $DIR/issue-84128.rs:5:8 + | +LL | struct Foo(T); + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/issue-87461.rs b/tests/ui/closures/issue-87461.rs new file mode 100644 index 000000000..0151080ee --- /dev/null +++ b/tests/ui/closures/issue-87461.rs @@ -0,0 +1,29 @@ +// Regression test for #87461. + +// edition:2021 + +async fn func() -> Result { + let _ = async { + Err(42u64) + }.await?; + + Ok(()) + //~^ ERROR: mismatched types [E0308] +} + +async fn func2() -> Result { + Err(42u64)?; + + Ok(()) + //~^ ERROR: mismatched types [E0308] +} + +fn main() { + || -> Result { + if true { + return Err(42u64); + } + Ok(()) + //~^ ERROR: mismatched types [E0308] + }; +} diff --git a/tests/ui/closures/issue-87461.stderr b/tests/ui/closures/issue-87461.stderr new file mode 100644 index 000000000..b492251c0 --- /dev/null +++ b/tests/ui/closures/issue-87461.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/issue-87461.rs:10:8 + | +LL | Ok(()) + | -- ^^ expected `u16`, found `()` + | | + | arguments to this enum variant are incorrect + | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:10:5 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/issue-87461.rs:17:8 + | +LL | Ok(()) + | -- ^^ expected `u16`, found `()` + | | + | arguments to this enum variant are incorrect + | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:17:5 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/issue-87461.rs:26:12 + | +LL | Ok(()) + | -- ^^ expected `u16`, found `()` + | | + | arguments to this enum variant are incorrect + | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:26:9 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/issue-87814-1.rs b/tests/ui/closures/issue-87814-1.rs new file mode 100644 index 000000000..5cf01ddf5 --- /dev/null +++ b/tests/ui/closures/issue-87814-1.rs @@ -0,0 +1,8 @@ +// check-pass +fn main() { + let mut schema_all = vec![]; + (0..42).for_each(|_x| match Err(()) as Result<(), _> { + Ok(()) => schema_all.push(()), + Err(_) => (), + }); +} diff --git a/tests/ui/closures/issue-87814-2.rs b/tests/ui/closures/issue-87814-2.rs new file mode 100644 index 000000000..efe77f90f --- /dev/null +++ b/tests/ui/closures/issue-87814-2.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() { + let mut schema_all: (Vec, Vec) = (vec![], vec![]); + + let _c = || match schema_all.0.try_reserve(1) as Result<(), _> { + Ok(()) => (), + Err(_) => (), + }; +} diff --git a/tests/ui/closures/issue-90871.rs b/tests/ui/closures/issue-90871.rs new file mode 100644 index 000000000..7ce061cd3 --- /dev/null +++ b/tests/ui/closures/issue-90871.rs @@ -0,0 +1,7 @@ +#![feature(type_ascription)] + +fn main() { + type_ascribe!(2, n([u8; || 1])) + //~^ ERROR cannot find type `n` in this scope + //~| ERROR mismatched types +} diff --git a/tests/ui/closures/issue-90871.stderr b/tests/ui/closures/issue-90871.stderr new file mode 100644 index 000000000..4a578b4d7 --- /dev/null +++ b/tests/ui/closures/issue-90871.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `n` in this scope + --> $DIR/issue-90871.rs:4:22 + | +LL | type_ascribe!(2, n([u8; || 1])) + | ^ help: a trait with a similar name exists: `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here + +error[E0308]: mismatched types + --> $DIR/issue-90871.rs:4:29 + | +LL | type_ascribe!(2, n([u8; || 1])) + | ^^^^ expected `usize`, found closure + | + = note: expected type `usize` + found closure `[closure@$DIR/issue-90871.rs:4:29: 4:31]` +help: use parentheses to call this closure + | +LL | type_ascribe!(2, n([u8; (|| 1)()])) + | + +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0412. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/issue-97607.rs b/tests/ui/closures/issue-97607.rs new file mode 100644 index 000000000..74c910ad0 --- /dev/null +++ b/tests/ui/closures/issue-97607.rs @@ -0,0 +1,12 @@ +// check-pass +#[allow(unused)] + +fn test(f: F) -> Box U + 'static> +where + F: 'static + Fn(T) -> U, + for<'a> U: 'a, // < This is the problematic line, see #97607 +{ + Box::new(move |t| f(t)) +} + +fn main() {} diff --git a/tests/ui/closures/issue-99565.rs b/tests/ui/closures/issue-99565.rs new file mode 100644 index 000000000..3a30d2ee0 --- /dev/null +++ b/tests/ui/closures/issue-99565.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] + +fn foo(_: U) {} + +fn bar() { + foo(|| {}); //~ ERROR type annotations needed +} diff --git a/tests/ui/closures/issue-99565.stderr b/tests/ui/closures/issue-99565.stderr new file mode 100644 index 000000000..0d940aa9a --- /dev/null +++ b/tests/ui/closures/issue-99565.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-99565.rs:6:5 + | +LL | foo(|| {}); + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | +help: consider specifying the generic arguments + | +LL | foo::(|| {}); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closures/local-type-mix.rs b/tests/ui/closures/local-type-mix.rs new file mode 100644 index 000000000..006e6f490 --- /dev/null +++ b/tests/ui/closures/local-type-mix.rs @@ -0,0 +1,17 @@ +// Check that using the parameter name in its type does not ICE. +// edition:2018 + +#![feature(async_closure)] + +fn main() { + let _ = |x: x| x; //~ ERROR expected type + let _ = |x: bool| -> x { x }; //~ ERROR expected type + let _ = async move |x: x| x; //~ ERROR expected type + let _ = async move |x: bool| -> x { x }; //~ ERROR expected type +} + +fn foo(x: x) {} //~ ERROR expected type +fn foo_ret(x: bool) -> x {} //~ ERROR expected type + +async fn async_foo(x: x) {} //~ ERROR expected type +async fn async_foo_ret(x: bool) -> x {} //~ ERROR expected type diff --git a/tests/ui/closures/local-type-mix.stderr b/tests/ui/closures/local-type-mix.stderr new file mode 100644 index 000000000..68c320a06 --- /dev/null +++ b/tests/ui/closures/local-type-mix.stderr @@ -0,0 +1,51 @@ +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:7:17 + | +LL | let _ = |x: x| x; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:8:26 + | +LL | let _ = |x: bool| -> x { x }; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:9:28 + | +LL | let _ = async move |x: x| x; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:10:37 + | +LL | let _ = async move |x: bool| -> x { x }; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:13:11 + | +LL | fn foo(x: x) {} + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:14:24 + | +LL | fn foo_ret(x: bool) -> x {} + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:16:23 + | +LL | async fn async_foo(x: x) {} + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:17:36 + | +LL | async fn async_foo_ret(x: bool) -> x {} + | ^ not a type + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/closures/multiple-fn-bounds.rs b/tests/ui/closures/multiple-fn-bounds.rs new file mode 100644 index 000000000..6bb4098e2 --- /dev/null +++ b/tests/ui/closures/multiple-fn-bounds.rs @@ -0,0 +1,15 @@ +fn foo bool + Fn(char) -> bool>(f: F) { + //~^ NOTE required by a bound in `foo` + //~| NOTE required by this bound in `foo` + //~| NOTE closure inferred to have a different signature due to this bound + todo!(); +} + +fn main() { + let v = true; + foo(move |x| v); + //~^ ERROR type mismatch in closure arguments + //~| NOTE expected closure signature + //~| NOTE expected due to this + //~| NOTE found signature defined here +} diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr new file mode 100644 index 000000000..32a1edb00 --- /dev/null +++ b/tests/ui/closures/multiple-fn-bounds.stderr @@ -0,0 +1,28 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/multiple-fn-bounds.rs:10:5 + | +LL | foo(move |x| v); + | ^^^ -------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(char) -> _` + found closure signature `for<'a> fn(&'a char) -> _` +note: closure inferred to have a different signature due to this bound + --> $DIR/multiple-fn-bounds.rs:1:11 + | +LL | fn foo bool + Fn(char) -> bool>(f: F) { + | ^^^^^^^^^^^^^^^^^ +note: required by a bound in `foo` + --> $DIR/multiple-fn-bounds.rs:1:31 + | +LL | fn foo bool + Fn(char) -> bool>(f: F) { + | ^^^^^^^^^^^^^^^^ required by this bound in `foo` +help: do not borrow the argument + | +LL | foo(move |char| v); + | ~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/closures/old-closure-arg-call-as.rs b/tests/ui/closures/old-closure-arg-call-as.rs new file mode 100644 index 000000000..87cf3a487 --- /dev/null +++ b/tests/ui/closures/old-closure-arg-call-as.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(non_snake_case)] + +fn asBlock(f: F) -> usize where F: FnOnce() -> usize { + return f(); +} + +pub fn main() { + let x = asBlock(|| 22); + assert_eq!(x, 22); +} diff --git a/tests/ui/closures/old-closure-arg.rs b/tests/ui/closures/old-closure-arg.rs new file mode 100644 index 000000000..bd1385e5c --- /dev/null +++ b/tests/ui/closures/old-closure-arg.rs @@ -0,0 +1,11 @@ +// run-pass +// Check usage and precedence of block arguments in expressions: +pub fn main() { + let v = vec![-1.0f64, 0.0, 1.0, 2.0, 3.0]; + + // Statement form does not require parentheses: + for i in &v { + println!("{}", *i); + } + +} diff --git a/tests/ui/closures/old-closure-explicit-types.rs b/tests/ui/closures/old-closure-explicit-types.rs new file mode 100644 index 000000000..860fcc8df --- /dev/null +++ b/tests/ui/closures/old-closure-explicit-types.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + fn as_buf(s: String, f: F) -> T where F: FnOnce(String) -> T { f(s) } + as_buf("foo".to_string(), |foo: String| -> () { println!("{}", foo) }); +} diff --git a/tests/ui/closures/old-closure-expr-precedence.rs b/tests/ui/closures/old-closure-expr-precedence.rs new file mode 100644 index 000000000..13b2fe9c3 --- /dev/null +++ b/tests/ui/closures/old-closure-expr-precedence.rs @@ -0,0 +1,62 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(unused_parens)] +// This test has some extra semis in it that the pretty-printer won't +// reproduce so we don't want to automatically reformat it + +// no-reformat + + +/* + * + * When you write a block-expression thing followed by + * a lone unary operator, you can get a surprising parse: + * + * if (...) { ... } + * -num; + * + * for example, or: + * + * if (...) { ... } + * *box; + * + * These will parse as subtraction and multiplication binops. + * To get them to parse "the way you want" you need to brace + * the leading unops: + + * if (...) { ... } + * {-num}; + * + * or alternatively, semi-separate them: + * + * if (...) { ... }; + * -num; + * + * This seems a little wonky, but the alternative is to lower + * precedence of such block-like exprs to the point where + * you have to parenthesize them to get them to occur in the + * RHS of a binop. For example, you'd have to write: + * + * 12 + (if (foo) { 13 } else { 14 }); + * + * rather than: + * + * 12 + if (foo) { 13 } else { 14 }; + * + * Since we want to maintain the ability to write the latter, + * we leave the parens-burden on the trailing unop case. + * + */ + +pub fn main() { + + let num = 12; + + assert_eq!(if (true) { 12 } else { 12 } - num, 0); + assert_eq!(12 - if (true) { 12 } else { 12 }, 0); + if (true) { 12; } {-num}; + if (true) { 12; }; {-num}; + if (true) { 12; };;; -num; + //~^ WARNING unnecessary trailing semicolons +} diff --git a/tests/ui/closures/old-closure-expr-precedence.stderr b/tests/ui/closures/old-closure-expr-precedence.stderr new file mode 100644 index 000000000..fabece1ad --- /dev/null +++ b/tests/ui/closures/old-closure-expr-precedence.stderr @@ -0,0 +1,10 @@ +warning: unnecessary trailing semicolons + --> $DIR/old-closure-expr-precedence.rs:60:21 + | +LL | if (true) { 12; };;; -num; + | ^^ help: remove these semicolons + | + = note: `#[warn(redundant_semicolons)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/old-closure-expression-remove-semicolon.fixed b/tests/ui/closures/old-closure-expression-remove-semicolon.fixed new file mode 100644 index 000000000..8aa9e952b --- /dev/null +++ b/tests/ui/closures/old-closure-expression-remove-semicolon.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +fn foo() -> i32 { + 0 +} + +fn main() { + let _x: i32 = { + //~^ ERROR mismatched types + foo() //~ HELP remove this semicolon to return this value + }; +} diff --git a/tests/ui/closures/old-closure-expression-remove-semicolon.rs b/tests/ui/closures/old-closure-expression-remove-semicolon.rs new file mode 100644 index 000000000..912c7a331 --- /dev/null +++ b/tests/ui/closures/old-closure-expression-remove-semicolon.rs @@ -0,0 +1,12 @@ +// run-rustfix + +fn foo() -> i32 { + 0 +} + +fn main() { + let _x: i32 = { + //~^ ERROR mismatched types + foo(); //~ HELP remove this semicolon to return this value + }; +} diff --git a/tests/ui/closures/old-closure-expression-remove-semicolon.stderr b/tests/ui/closures/old-closure-expression-remove-semicolon.stderr new file mode 100644 index 000000000..bc54ab4d5 --- /dev/null +++ b/tests/ui/closures/old-closure-expression-remove-semicolon.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/old-closure-expression-remove-semicolon.rs:8:19 + | +LL | let _x: i32 = { + | ___________________^ +LL | | +LL | | foo(); + | | - help: remove this semicolon to return this value +LL | | }; + | |_____^ expected `i32`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/old-closure-fn-coerce.rs b/tests/ui/closures/old-closure-fn-coerce.rs new file mode 100644 index 000000000..d993ad994 --- /dev/null +++ b/tests/ui/closures/old-closure-fn-coerce.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_braces)] + +fn force(f: F) -> isize where F: FnOnce() -> isize { return f(); } + +pub fn main() { + fn f() -> isize { return 7; } + assert_eq!(force(f), 7); + let g = {||force(f)}; + assert_eq!(g(), 7); +} diff --git a/tests/ui/closures/old-closure-iter-1.rs b/tests/ui/closures/old-closure-iter-1.rs new file mode 100644 index 000000000..caf0266cf --- /dev/null +++ b/tests/ui/closures/old-closure-iter-1.rs @@ -0,0 +1,15 @@ +// run-pass + +fn iter_vec(v: Vec , mut f: F) where F: FnMut(&T) { for x in &v { f(x); } } + +pub fn main() { + let v = vec![1, 2, 3, 4, 5, 6, 7]; + let mut odds = 0; + iter_vec(v, |i| { + if *i % 2 == 1 { + odds += 1; + } + }); + println!("{}", odds); + assert_eq!(odds, 4); +} diff --git a/tests/ui/closures/old-closure-iter-2.rs b/tests/ui/closures/old-closure-iter-2.rs new file mode 100644 index 000000000..e90c1ee81 --- /dev/null +++ b/tests/ui/closures/old-closure-iter-2.rs @@ -0,0 +1,15 @@ +// run-pass + +fn iter_vec(v: Vec, mut f: F) where F: FnMut(&T) { for x in &v { f(x); } } + +pub fn main() { + let v = vec![1, 2, 3, 4, 5]; + let mut sum = 0; + iter_vec(v.clone(), |i| { + iter_vec(v.clone(), |j| { + sum += *i * *j; + }); + }); + println!("{}", sum); + assert_eq!(sum, 225); +} diff --git a/tests/ui/closures/once-move-out-on-heap.rs b/tests/ui/closures/once-move-out-on-heap.rs new file mode 100644 index 000000000..4e2e400ce --- /dev/null +++ b/tests/ui/closures/once-move-out-on-heap.rs @@ -0,0 +1,18 @@ +// run-pass +// Testing guarantees provided by once functions. + + + +use std::sync::Arc; + +fn foo(blk: F) { + blk(); +} + +pub fn main() { + let x = Arc::new(true); + foo(move|| { + assert!(*x); + drop(x); + }); +} diff --git a/tests/ui/closures/print/closure-print-generic-1.rs b/tests/ui/closures/print/closure-print-generic-1.rs new file mode 100644 index 000000000..504b4adbe --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-1.rs @@ -0,0 +1,23 @@ +fn to_fn_once(f: F) -> F { + f +} + +fn f(y: T) { + struct Foo { + x: U, + }; + + let foo = Foo { x: "x" }; + + let c = to_fn_once(move || { + println!("{} {}", foo.x, y); + }); + + c(); + c(); + //~^ ERROR use of moved value +} + +fn main() { + f("S"); +} diff --git a/tests/ui/closures/print/closure-print-generic-1.stderr b/tests/ui/closures/print/closure-print-generic-1.stderr new file mode 100644 index 000000000..b21734f02 --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-1.stderr @@ -0,0 +1,20 @@ +error[E0382]: use of moved value: `c` + --> $DIR/closure-print-generic-1.rs:17:5 + | +LL | let c = to_fn_once(move || { + | - move occurs because `c` has type `[closure@$DIR/closure-print-generic-1.rs:12:24: 12:31]`, which does not implement the `Copy` trait +... +LL | c(); + | --- `c` moved due to this call +LL | c(); + | ^ value used here after move + | +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/closure-print-generic-1.rs:16:5 + | +LL | c(); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/print/closure-print-generic-2.rs b/tests/ui/closures/print/closure-print-generic-2.rs new file mode 100644 index 000000000..3f77fd26b --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-2.rs @@ -0,0 +1,13 @@ +mod mod1 { + pub fn f(t: T) { + let x = 20; + + let c = || println!("{} {}", t, x); + let c1: () = c; + //~^ ERROR mismatched types + } +} + +fn main() { + mod1::f(5i32); +} diff --git a/tests/ui/closures/print/closure-print-generic-2.stderr b/tests/ui/closures/print/closure-print-generic-2.stderr new file mode 100644 index 000000000..e53277a93 --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-2.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/closure-print-generic-2.rs:6:22 + | +LL | let c = || println!("{} {}", t, x); + | -- the found closure +LL | let c1: () = c; + | -- ^ expected `()`, found closure + | | + | expected due to this + | + = note: expected unit type `()` + found closure `[closure@$DIR/closure-print-generic-2.rs:5:17: 5:19]` +help: use parentheses to call this closure + | +LL | let c1: () = c(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.rs b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.rs new file mode 100644 index 000000000..07bf8fe4c --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.rs @@ -0,0 +1,16 @@ +// compile-flags: -Ztrim-diagnostic-paths=off -Zverbose + +mod mod1 { + pub fn f(t: T) + { + let x = 20; + + let c = || println!("{} {}", t, x); + let c1 : () = c; + //~^ ERROR mismatched types + } +} + +fn main() { + mod1::f(5i32); +} diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr new file mode 100644 index 000000000..ff89dd340 --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/closure-print-generic-trim-off-verbose-2.rs:9:23 + | +LL | let c = || println!("{} {}", t, x); + | -- the found closure +LL | let c1 : () = c; + | -- ^ expected `()`, found closure + | | + | expected due to this + | + = note: expected unit type `()` + found closure `[mod1::f::{closure#0} closure_substs=(unavailable) substs=[T, _#16t, extern "rust-call" fn(()), _#15t]]` +help: use parentheses to call this closure + | +LL | let c1 : () = c(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-generic-verbose-1.rs b/tests/ui/closures/print/closure-print-generic-verbose-1.rs new file mode 100644 index 000000000..67d37f1c5 --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-verbose-1.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zverbose + +fn to_fn_once(f: F) -> F { f } + +fn f(y: T) { + struct Foo { + x: U + }; + + let foo = Foo{ x: "x" }; + + let c = to_fn_once(move|| { + println!("{} {}", foo.x, y); + }); + + c(); + c(); + //~^ ERROR use of moved value +} + + +fn main() { + f("S"); +} diff --git a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr new file mode 100644 index 000000000..3ab7c66d1 --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr @@ -0,0 +1,20 @@ +error[E0382]: use of moved value: `c` + --> $DIR/closure-print-generic-verbose-1.rs:17:5 + | +LL | let c = to_fn_once(move|| { + | - move occurs because `c` has type `[f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'_#9r str>, T)]`, which does not implement the `Copy` trait +... +LL | c(); + | --- `c` moved due to this call +LL | c(); + | ^ value used here after move + | +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/closure-print-generic-verbose-1.rs:16:5 + | +LL | c(); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.rs b/tests/ui/closures/print/closure-print-generic-verbose-2.rs new file mode 100644 index 000000000..f460fedff --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.rs @@ -0,0 +1,16 @@ +// compile-flags: -Zverbose + +mod mod1 { + pub fn f(t: T) + { + let x = 20; + + let c = || println!("{} {}", t, x); + let c1 : () = c; + //~^ ERROR mismatched types + } +} + +fn main() { + mod1::f(5i32); +} diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr new file mode 100644 index 000000000..5bbf84f96 --- /dev/null +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/closure-print-generic-verbose-2.rs:9:23 + | +LL | let c = || println!("{} {}", t, x); + | -- the found closure +LL | let c1 : () = c; + | -- ^ expected `()`, found closure + | | + | expected due to this + | + = note: expected unit type `()` + found closure `[f::{closure#0} closure_substs=(unavailable) substs=[T, _#16t, extern "rust-call" fn(()), _#15t]]` +help: use parentheses to call this closure + | +LL | let c1 : () = c(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/print/closure-print-verbose.rs b/tests/ui/closures/print/closure-print-verbose.rs new file mode 100644 index 000000000..4b0438a91 --- /dev/null +++ b/tests/ui/closures/print/closure-print-verbose.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zverbose + +// Same as closure-coerce-fn-1.rs + +// Ensure that capturing closures are never coerced to fns +// Especially interesting as non-capturing closures can be. + +fn main() { + let mut a = 0u8; + let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr new file mode 100644 index 000000000..083717b33 --- /dev/null +++ b/tests/ui/closures/print/closure-print-verbose.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/closure-print-verbose.rs:10:29 + | +LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + | ------------ ^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure + | | + | expected due to this + | + = note: expected fn pointer `fn(u8) -> u8` + found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-print-verbose.rs:10:39 + | +LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + | ^ `a` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/semistatement-in-lambda.rs b/tests/ui/closures/semistatement-in-lambda.rs new file mode 100644 index 000000000..ebd55e0ba --- /dev/null +++ b/tests/ui/closures/semistatement-in-lambda.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(unused_must_use)] + +pub fn main() { + // Test that lambdas behave as unary expressions with block-like expressions + -if true { 1 } else { 2 } * 3; + || if true { 1 } else { 2 } * 3; + + // The following is invalid and parses as `if true { 1 } else { 2 }; *3` + // if true { 1 } else { 2 } * 3 +} diff --git a/tests/ui/closures/supertrait-hint-cycle-2.rs b/tests/ui/closures/supertrait-hint-cycle-2.rs new file mode 100644 index 000000000..fda81b18d --- /dev/null +++ b/tests/ui/closures/supertrait-hint-cycle-2.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Foo<'a> { + type Input; +} + +impl Foo<'_> for F { + type Input = u32; +} + +trait SuperFn: for<'a> Foo<'a> + for<'a> Fn(>::Input) {} +impl SuperFn for T where T: for<'a> Fn(>::Input) + for<'a> Foo<'a> {} + +fn needs_super(_: impl SuperFn) {} + +fn main() { + needs_super(|_: u32| {}); +} diff --git a/tests/ui/closures/supertrait-hint-cycle-3.rs b/tests/ui/closures/supertrait-hint-cycle-3.rs new file mode 100644 index 000000000..8149474df --- /dev/null +++ b/tests/ui/closures/supertrait-hint-cycle-3.rs @@ -0,0 +1,16 @@ +// check-pass + + +trait Foo<'a> { + type Input; +} + +impl Foo<'_> for F { + type Input = u32; +} + +fn needs_super Fn(>::Input) + for<'a> Foo<'a>>(_: F) {} + +fn main() { + needs_super(|_: u32| {}); +} diff --git a/tests/ui/closures/supertrait-hint-cycle.rs b/tests/ui/closures/supertrait-hint-cycle.rs new file mode 100644 index 000000000..dbb06b2ef --- /dev/null +++ b/tests/ui/closures/supertrait-hint-cycle.rs @@ -0,0 +1,65 @@ +// edition:2021 +// check-pass + +#![feature(type_alias_impl_trait)] +#![feature(closure_lifetime_binder)] + +use std::future::Future; + +trait AsyncFn: FnMut(I) -> Self::Fut { + type Fut: Future; +} + +impl AsyncFn for F +where + Fut: Future, + F: FnMut(I) -> Fut, +{ + type Fut = Fut; +} + +async fn call(mut ctx: C, mut f: F) -> Result +where + F: for<'a> AsyncFn<&'a mut C, Result>, +{ + loop { + match f(&mut ctx).await { + Ok(val) => return Ok(val), + Err(_) => continue, + } + } +} + +trait Cap<'a> {} +impl Cap<'_> for T {} + +fn works(ctx: &mut usize) { + let mut inner = 0; + + type Ret<'a, 'b: 'a> = impl Future> + 'a + Cap<'b>; + + let callback = for<'a, 'b> |c: &'a mut &'b mut usize| -> Ret<'a, 'b> { + inner += 1; + async move { + let _c = c; + Ok(1usize) + } + }; + call(ctx, callback); +} + +fn doesnt_work_but_should(ctx: &mut usize) { + let mut inner = 0; + + type Ret<'a, 'b: 'a> = impl Future> + 'a + Cap<'b>; + + call(ctx, for<'a, 'b> |c: &'a mut &'b mut usize| -> Ret<'a, 'b> { + inner += 1; + async move { + let _c = c; + Ok(1usize) + } + }); +} + +fn main() {} diff --git a/tests/ui/closures/supertrait-hint-references-assoc-ty.rs b/tests/ui/closures/supertrait-hint-references-assoc-ty.rs new file mode 100644 index 000000000..270bf14c3 --- /dev/null +++ b/tests/ui/closures/supertrait-hint-references-assoc-ty.rs @@ -0,0 +1,17 @@ +// check-pass + +pub trait Fn0: Fn(i32) -> Self::Out { + type Out; +} + +impl ()> Fn0 for F { + type Out = (); +} + +pub fn closure_typer(_: impl Fn0) {} + +fn main() { + closure_typer(move |x| { + let _: i64 = x.into(); + }); +} diff --git a/tests/ui/closures/thir-unsafeck-issue-85871.rs b/tests/ui/closures/thir-unsafeck-issue-85871.rs new file mode 100644 index 000000000..aea539b74 --- /dev/null +++ b/tests/ui/closures/thir-unsafeck-issue-85871.rs @@ -0,0 +1,20 @@ +// Tests that no ICE occurs when a closure appears inside a node +// that does not have a body when compiling with +// compile-flags: -Zthir-unsafeck=yes +// check-pass + +#![allow(dead_code)] + +struct Bug { + inner: [(); match || 1 { + _n => 42, // we may not call the closure here (E0015) + }], +} + +enum E { + V([(); { let _ = || 1; 42 }]), +} + +type Ty = [(); { let _ = || 1; 42 }]; + +fn main() {} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs new file mode 100644 index 000000000..e05dbf3bb --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs @@ -0,0 +1,11 @@ +// gate-test-abi_c_cmse_nonsecure_call +fn main() { + let non_secure_function = unsafe { + core::mem::transmute:: i32>( + //~^ ERROR [E0658] + 0x10000004, + ) + }; + let mut toto = 5; + toto += non_secure_function(toto, 2, 3, 5); +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr new file mode 100644 index 000000000..ed8e16899 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr @@ -0,0 +1,12 @@ +error[E0658]: C-cmse-nonsecure-call ABI is experimental and subject to change + --> $DIR/gate_test.rs:4:46 + | +LL | core::mem::transmute:: i32>( + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #81391 for more information + = help: add `#![feature(abi_c_cmse_nonsecure_call)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs new file mode 100644 index 000000000..bbc039bdf --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs @@ -0,0 +1,24 @@ +// build-pass +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![no_core] +#[lang="sized"] +pub trait Sized { } +#[lang="copy"] +pub trait Copy { } +impl Copy for u32 {} + +extern "rust-intrinsic" { + pub fn transmute(e: T) -> U; +} + +#[no_mangle] +pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 { + let non_secure_function = unsafe { + transmute:: u32>( + 0x10000004, + ) + }; + non_secure_function(a, b, c, d) +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs new file mode 100644 index 000000000..b8112b20a --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs @@ -0,0 +1,27 @@ +// build-fail +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] +#![no_core] +#[lang="sized"] +pub trait Sized { } +#[lang="copy"] +pub trait Copy { } +impl Copy for u32 {} + +extern "rust-intrinsic" { + pub fn transmute(e: T) -> U; +} + +#[no_mangle] +pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { + let non_secure_function = unsafe { + transmute::< + usize, + extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32> + ( + 0x10000004, + ) + }; + non_secure_function(a, b, c, d, e) +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr new file mode 100644 index 000000000..372300787 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr @@ -0,0 +1,4 @@ +error: :0:0: in function test i32 (i32, i32, i32, i32, i32): call to non-secure function would require passing arguments on stack + +error: aborting due to previous error + diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs new file mode 100644 index 000000000..f32b37090 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs @@ -0,0 +1,8 @@ +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)] +#![no_core] +#[lang="sized"] +trait Sized { } + +pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr new file mode 100644 index 000000000..08b763b26 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr @@ -0,0 +1,9 @@ +error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers + --> $DIR/wrong-abi-location-1.rs:8:1 + | +LL | pub extern "C-cmse-nonsecure-call" fn test() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0781`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs new file mode 100644 index 000000000..6f8bb24aa --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs @@ -0,0 +1,10 @@ +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, lang_items, no_core)] +#![no_core] +#[lang="sized"] +trait Sized { } + +extern "C-cmse-nonsecure-call" { //~ ERROR [E0781] + fn test(); +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr new file mode 100644 index 000000000..3ade9891e --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr @@ -0,0 +1,11 @@ +error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers + --> $DIR/wrong-abi-location-2.rs:8:1 + | +LL | / extern "C-cmse-nonsecure-call" { +LL | | fn test(); +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0781`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs new file mode 100644 index 000000000..02d5f20fe --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs @@ -0,0 +1,11 @@ +// gate-test-cmse_nonsecure_entry + +#[no_mangle] +#[cmse_nonsecure_entry] +//~^ ERROR [E0775] +//~| ERROR [E0658] +pub extern "C" fn entry_function(input: u32) -> u32 { + input + 6 +} + +fn main() {} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr new file mode 100644 index 000000000..75a29b317 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr @@ -0,0 +1,19 @@ +error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature + --> $DIR/gate_test.rs:4:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #75835 for more information + = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable + +error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension + --> $DIR/gate_test.rs:4:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0658, E0775. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs new file mode 100644 index 000000000..a839406cd --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs @@ -0,0 +1,9 @@ +// Regression test for the ICE described in #83475. + +#![crate_type="lib"] + +#![feature(cmse_nonsecure_entry)] +#[cmse_nonsecure_entry] +//~^ ERROR: attribute should be applied to a function definition +struct XEmpty2; +//~^ NOTE: not a function definition diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr new file mode 100644 index 000000000..426d82d8d --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr @@ -0,0 +1,11 @@ +error: attribute should be applied to a function definition + --> $DIR/issue-83475.rs:6:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct XEmpty2; + | --------------- not a function definition + +error: aborting due to previous error + diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs new file mode 100644 index 000000000..5591a8a58 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs @@ -0,0 +1,16 @@ +// build-pass +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } +#[lang="copy"] +trait Copy { } +impl Copy for u32 {} + +#[no_mangle] +#[cmse_nonsecure_entry] +pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { + d +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs new file mode 100644 index 000000000..39b41dac4 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs @@ -0,0 +1,16 @@ +// build-fail +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } +#[lang="copy"] +trait Copy { } +impl Copy for u32 {} + +#[no_mangle] +#[cmse_nonsecure_entry] +pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 { + e +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr new file mode 100644 index 000000000..1054c2665 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr @@ -0,0 +1,4 @@ +error: :0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack + +error: aborting due to previous error + diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs new file mode 100644 index 000000000..3783e2794 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs @@ -0,0 +1,10 @@ +// ignore-thumbv8m.main-none-eabi +#![feature(cmse_nonsecure_entry)] + +#[no_mangle] +#[cmse_nonsecure_entry] //~ ERROR [E0775] +pub extern "C" fn entry_function(input: u32) -> u32 { + input + 6 +} + +fn main() {} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr new file mode 100644 index 000000000..7e8862f9a --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr @@ -0,0 +1,9 @@ +error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension + --> $DIR/trustzone-only.rs:5:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0775`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs new file mode 100644 index 000000000..6320d2963 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs @@ -0,0 +1,13 @@ +// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +// needs-llvm-components: arm +#![feature(cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang="sized"] +trait Sized { } + +#[no_mangle] +#[cmse_nonsecure_entry] +//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776] +pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { + d +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr new file mode 100644 index 000000000..36d76c967 --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr @@ -0,0 +1,9 @@ +error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI + --> $DIR/wrong-abi.rs:9:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0776`. diff --git a/tests/ui/codegen/auxiliary/issue-97708-aux.rs b/tests/ui/codegen/auxiliary/issue-97708-aux.rs new file mode 100644 index 000000000..e296bd391 --- /dev/null +++ b/tests/ui/codegen/auxiliary/issue-97708-aux.rs @@ -0,0 +1,41 @@ +use std::{ptr::NonNull, task::Poll}; + +struct TaskRef; + +struct Header { + vtable: &'static Vtable, +} + +struct Vtable { + poll: unsafe fn(TaskRef) -> Poll<()>, + deallocate: unsafe fn(NonNull

), +} + +// in the "Header" type, which is a private type in maitake +impl Header { + pub(crate) const fn new_stub() -> Self { + unsafe fn nop(_ptr: TaskRef) -> Poll<()> { + Poll::Pending + } + + unsafe fn nop_deallocate(ptr: NonNull
) { + unreachable!("stub task ({ptr:p}) should never be deallocated!"); + } + + Self { vtable: &Vtable { poll: nop, deallocate: nop_deallocate } } + } +} + +// This is a public type in `maitake` +#[repr(transparent)] +#[cfg_attr(loom, allow(dead_code))] +pub struct TaskStub { + hdr: Header, +} + +impl TaskStub { + /// Create a new unique stub [`Task`]. + pub const fn new() -> Self { + Self { hdr: Header::new_stub() } + } +} diff --git a/tests/ui/codegen/auxiliary/llvm_pr32379.rs b/tests/ui/codegen/auxiliary/llvm_pr32379.rs new file mode 100644 index 000000000..8e4297670 --- /dev/null +++ b/tests/ui/codegen/auxiliary/llvm_pr32379.rs @@ -0,0 +1,5 @@ +pub fn pr32379(mut data: u64, f1: bool, f2: bool) -> u64 { + if f1 { data &= !2; } + if f2 { data |= 2; } + data +} diff --git a/tests/ui/codegen/init-large-type.rs b/tests/ui/codegen/init-large-type.rs new file mode 100644 index 000000000..ce905572f --- /dev/null +++ b/tests/ui/codegen/init-large-type.rs @@ -0,0 +1,23 @@ +// compile-flags: -O +// run-pass + +#![allow(unused_must_use)] +// Makes sure that zero-initializing large types is reasonably fast, +// Doing it incorrectly causes massive slowdown in LLVM during +// optimisation. + +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +#![feature(intrinsics)] + +use std::{mem, thread}; + +const SIZE: usize = 1024 * 1024; + +fn main() { + // do the test in a new thread to avoid (spurious?) stack overflows + thread::spawn(|| { + let _memory: [u8; SIZE] = unsafe { mem::zeroed() }; + }).join(); +} diff --git a/tests/ui/codegen/issue-101585-128bit-repeat.rs b/tests/ui/codegen/issue-101585-128bit-repeat.rs new file mode 100644 index 000000000..c6a686597 --- /dev/null +++ b/tests/ui/codegen/issue-101585-128bit-repeat.rs @@ -0,0 +1,14 @@ +// Regression test for issue 101585. +// run-pass + +fn main() { + fn min_array_ok() -> [i128; 1] { + [i128::MIN] + } + assert_eq!(min_array_ok(), [-170141183460469231731687303715884105728i128]); + + fn min_array_nok() -> [i128; 1] { + [i128::MIN; 1] + } + assert_eq!(min_array_nok(), [-170141183460469231731687303715884105728i128]); +} diff --git a/tests/ui/codegen/issue-16602-1.rs b/tests/ui/codegen/issue-16602-1.rs new file mode 100644 index 000000000..dd64ee75b --- /dev/null +++ b/tests/ui/codegen/issue-16602-1.rs @@ -0,0 +1,6 @@ +// run-pass +fn main() { + let mut t = [1; 2]; + t = [t[1] * 2, t[0] * 2]; + assert_eq!(&t[..], &[2, 2]); +} diff --git a/tests/ui/codegen/issue-16602-2.rs b/tests/ui/codegen/issue-16602-2.rs new file mode 100644 index 000000000..6364630ff --- /dev/null +++ b/tests/ui/codegen/issue-16602-2.rs @@ -0,0 +1,12 @@ +// run-pass +struct A { + pub x: u32, + pub y: u32, +} + +fn main() { + let mut a = A { x: 1, y: 1 }; + a = A { x: a.y * 2, y: a.x * 2 }; + assert_eq!(a.x, 2); + assert_eq!(a.y, 2); +} diff --git a/tests/ui/codegen/issue-16602-3.rs b/tests/ui/codegen/issue-16602-3.rs new file mode 100644 index 000000000..ca1ab3cc7 --- /dev/null +++ b/tests/ui/codegen/issue-16602-3.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_variables)] +#![allow(unused_assignments)] +#[derive(Debug)] +#[allow(unused_tuple_struct_fields)] +enum Foo { + Bar(u32, u32), + Baz(&'static u32, &'static u32) +} + +static NUM: u32 = 100; + +fn main () { + let mut b = Foo::Baz(&NUM, &NUM); + b = Foo::Bar(f(&b), g(&b)); +} + +static FNUM: u32 = 1; + +fn f (b: &Foo) -> u32 { + FNUM +} + +static GNUM: u32 = 2; + +fn g (b: &Foo) -> u32 { + GNUM +} diff --git a/tests/ui/codegen/issue-28950.rs b/tests/ui/codegen/issue-28950.rs new file mode 100644 index 000000000..8b55f42f3 --- /dev/null +++ b/tests/ui/codegen/issue-28950.rs @@ -0,0 +1,22 @@ +// run-pass +// ignore-emscripten no threads +// compile-flags: -O + +// Tests that the `vec!` macro does not overflow the stack when it is +// given data larger than the stack. + +// FIXME(eddyb) Improve unoptimized codegen to avoid the temporary, +// and thus run successfully even when compiled at -C opt-level=0. + +const LEN: usize = 1 << 15; + +use std::thread::Builder; + +fn main() { + assert!(Builder::new().stack_size(LEN / 2).spawn(|| { + // FIXME(eddyb) this can be vec![[0: LEN]] pending + // https://llvm.org/bugs/show_bug.cgi?id=28987 + let vec = vec![unsafe { std::mem::zeroed::<[u8; LEN]>() }]; + assert_eq!(vec.len(), 1); + }).unwrap().join().is_ok()); +} diff --git a/tests/ui/codegen/issue-55976.rs b/tests/ui/codegen/issue-55976.rs new file mode 100644 index 000000000..3142704b7 --- /dev/null +++ b/tests/ui/codegen/issue-55976.rs @@ -0,0 +1,13 @@ +// run-pass +// ^-- The above is needed as this issue is related to LLVM/codegen. +// min-llvm-version:15.0.0 +// ^-- The above is needed as this issue is fixed by the opaque pointers. + +fn main() { + type_error(|x| &x); +} + +fn type_error( + _selector: for<'a> fn(&'a Vec Fn(&'b u8)>>) -> &'a Vec>, +) { +} diff --git a/tests/ui/codegen/issue-63787.rs b/tests/ui/codegen/issue-63787.rs new file mode 100644 index 000000000..cba079b23 --- /dev/null +++ b/tests/ui/codegen/issue-63787.rs @@ -0,0 +1,36 @@ +// run-pass +// compile-flags: -O + +// Make sure that `Ref` and `RefMut` do not make false promises about aliasing, +// because once they drop, their reference/pointer can alias other writes. + +// Adapted from comex's proof of concept: +// https://github.com/rust-lang/rust/issues/63787#issuecomment-523588164 + +use std::cell::RefCell; +use std::ops::Deref; + +pub fn break_if_r_is_noalias(rc: &RefCell, r: impl Deref) -> i32 { + let ptr1 = &*r as *const i32; + let a = *r; + drop(r); + *rc.borrow_mut() = 2; + let r2 = rc.borrow(); + let ptr2 = &*r2 as *const i32; + if ptr2 != ptr1 { + panic!(); + } + // If LLVM knows the pointers are the same, and if `r` was `noalias`, + // then it may replace this with `a + a`, ignoring the earlier write. + a + *r2 +} + +fn main() { + let mut rc = RefCell::new(1); + let res = break_if_r_is_noalias(&rc, rc.borrow()); + assert_eq!(res, 3); + + *rc.get_mut() = 1; + let res = break_if_r_is_noalias(&rc, rc.borrow_mut()); + assert_eq!(res, 3); +} diff --git a/tests/ui/codegen/issue-64401.rs b/tests/ui/codegen/issue-64401.rs new file mode 100644 index 000000000..53f85c63b --- /dev/null +++ b/tests/ui/codegen/issue-64401.rs @@ -0,0 +1,51 @@ +// build-pass +// The ICE didn't happen with `cargo check` but `cargo build`. + +use std::marker::PhantomData; + +trait Owned<'a> { + type Reader; +} + +impl<'a> Owned<'a> for () { + type Reader = (); +} + +trait Handler { + fn handle(&self); +} + +struct CtxHandlerWithoutState { + message_type: PhantomData, + _function: F, +} + +impl CtxHandlerWithoutState { + pub fn new(_function: F) -> Self { + Self { + message_type: PhantomData, + _function, + } + } +} + +impl<'a, M, F> Handler for CtxHandlerWithoutState +where + F: Fn(>::Reader), + M: Owned<'a>, +{ + fn handle(&self) {} +} + +fn e_to_i Owned<'a>>(_: >::Reader) {} + +fn send_external_to_internal() +where + M: for<'a> Owned<'a>, +{ + let _: Box = Box::new(CtxHandlerWithoutState::::new(e_to_i::)); +} + +fn main() { + send_external_to_internal::<()>() +} diff --git a/tests/ui/codegen/issue-82859-slice-miscompile.rs b/tests/ui/codegen/issue-82859-slice-miscompile.rs new file mode 100644 index 000000000..b64eb4990 --- /dev/null +++ b/tests/ui/codegen/issue-82859-slice-miscompile.rs @@ -0,0 +1,19 @@ +// run-pass +// compile-flags: -Copt-level=0 -Cdebuginfo=2 + +// Make sure LLVM does not miscompile this. + +fn indirect_get_slice() -> &'static [usize] { + &[] +} + +#[inline(always)] +fn get_slice() -> &'static [usize] { + let ret = indirect_get_slice(); + ret +} + +fn main() { + let output = get_slice().len(); + assert_eq!(output, 0); +} diff --git a/tests/ui/codegen/issue-88043-bb-does-not-have-terminator.rs b/tests/ui/codegen/issue-88043-bb-does-not-have-terminator.rs new file mode 100644 index 000000000..38dfca347 --- /dev/null +++ b/tests/ui/codegen/issue-88043-bb-does-not-have-terminator.rs @@ -0,0 +1,35 @@ +// build-pass +// compile-flags: -Copt-level=0 + +// Regression test for #88043: LLVM crash when the RemoveZsts mir-opt pass is enabled. +// We should not see the error: +// `Basic Block in function '_ZN4main10take_until17h0067b8a660429bc9E' does not have terminator!` + +fn bump() -> Option { + unreachable!() +} + +fn take_until(terminate: impl Fn() -> bool) { + loop { + if terminate() { + return; + } else { + bump(); + } + } +} + +// CHECK-LABEL: @main +fn main() { + take_until(|| true); + f(None); +} + +fn f(_a: Option) -> Option { + loop { + g(); + () + } +} + +fn g() -> Option { None } diff --git a/tests/ui/codegen/issue-97708.rs b/tests/ui/codegen/issue-97708.rs new file mode 100644 index 000000000..8cb28e9f1 --- /dev/null +++ b/tests/ui/codegen/issue-97708.rs @@ -0,0 +1,9 @@ +// build-pass +// aux-build:issue-97708-aux.rs + +extern crate issue_97708_aux; +use issue_97708_aux::TaskStub; + +static TASK_STUB: TaskStub = TaskStub::new(); + +fn main() {} diff --git a/tests/ui/codegen/issue-99551.rs b/tests/ui/codegen/issue-99551.rs new file mode 100644 index 000000000..b223aff4e --- /dev/null +++ b/tests/ui/codegen/issue-99551.rs @@ -0,0 +1,20 @@ +// build-pass +#![feature(trait_upcasting)] + +pub trait A {} +pub trait B {} + +pub trait C: A + B {} +impl C for X {} + +pub fn test<'a, T>(view: T) -> Option<&'a mut dyn B> +where + T: IntoIterator, +{ + return Some(view.into_iter().next().unwrap()); +} + +fn main() { + let mut a: Vec> = Vec::new(); + test(a.iter_mut().map(|c| c.as_mut() as &mut dyn B)); +} diff --git a/tests/ui/codegen/llvm-pr32379.rs b/tests/ui/codegen/llvm-pr32379.rs new file mode 100644 index 000000000..8a1f03241 --- /dev/null +++ b/tests/ui/codegen/llvm-pr32379.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:llvm_pr32379.rs + +// LLVM PR #32379 (https://bugs.llvm.org/show_bug.cgi?id=32379), which +// applies to upstream LLVM 3.9.1, is known to cause rustc itself to be +// miscompiled on ARM (Rust issue #40593). Because cross builds don't test +// our *compiler* on ARM, have a test for the miscompilation directly. + +extern crate llvm_pr32379; + +pub fn main() { + let val = llvm_pr32379::pr32379(2, false, false); + assert_eq!(val, 2); +} diff --git a/tests/ui/codemap_tests/bad-format-args.rs b/tests/ui/codemap_tests/bad-format-args.rs new file mode 100644 index 000000000..e89a45a84 --- /dev/null +++ b/tests/ui/codemap_tests/bad-format-args.rs @@ -0,0 +1,5 @@ +fn main() { + format!(); //~ ERROR requires at least a format string argument + format!("" 1); //~ ERROR expected `,`, found `1` + format!("", 1 1); //~ ERROR expected one of +} diff --git a/tests/ui/codemap_tests/bad-format-args.stderr b/tests/ui/codemap_tests/bad-format-args.stderr new file mode 100644 index 000000000..8f79beaa9 --- /dev/null +++ b/tests/ui/codemap_tests/bad-format-args.stderr @@ -0,0 +1,22 @@ +error: requires at least a format string argument + --> $DIR/bad-format-args.rs:2:5 + | +LL | format!(); + | ^^^^^^^^^ + | + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected `,`, found `1` + --> $DIR/bad-format-args.rs:3:16 + | +LL | format!("" 1); + | ^ expected `,` + +error: expected one of `,`, `.`, `?`, or an operator, found `1` + --> $DIR/bad-format-args.rs:4:19 + | +LL | format!("", 1 1); + | ^ expected one of `,`, `.`, `?`, or an operator + +error: aborting due to 3 previous errors + diff --git a/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs b/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs new file mode 100644 index 000000000..414acfd84 --- /dev/null +++ b/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs @@ -0,0 +1,6 @@ +#![allow(dead_code)] + +trait C {} +impl dyn C { fn f() {} } //~ ERROR duplicate +impl dyn C { fn f() {} } +fn main() { } diff --git a/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr new file mode 100644 index 000000000..2c1c3c2dc --- /dev/null +++ b/tests/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -0,0 +1,11 @@ +error[E0592]: duplicate definitions with name `f` + --> $DIR/coherence-overlapping-inherent-impl-trait.rs:4:14 + | +LL | impl dyn C { fn f() {} } + | ^^^^^^ duplicate definitions for `f` +LL | impl dyn C { fn f() {} } + | ------ other definition for `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/codemap_tests/empty_span.rs b/tests/ui/codemap_tests/empty_span.rs new file mode 100644 index 000000000..7753e2ece --- /dev/null +++ b/tests/ui/codemap_tests/empty_span.rs @@ -0,0 +1,8 @@ +#![feature(negative_impls)] +fn main() { + struct Foo; + + impl !Sync for Foo {} + + unsafe impl Send for &'static Foo { } //~ ERROR cross-crate traits with a default impl +} diff --git a/tests/ui/codemap_tests/empty_span.stderr b/tests/ui/codemap_tests/empty_span.stderr new file mode 100644 index 000000000..e36f59ee5 --- /dev/null +++ b/tests/ui/codemap_tests/empty_span.stderr @@ -0,0 +1,9 @@ +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `&'static Foo` + --> $DIR/empty_span.rs:7:5 + | +LL | unsafe impl Send for &'static Foo { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0321`. diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.rs b/tests/ui/codemap_tests/huge_multispan_highlight.rs new file mode 100644 index 000000000..623c59081 --- /dev/null +++ b/tests/ui/codemap_tests/huge_multispan_highlight.rs @@ -0,0 +1,91 @@ +fn main() { + let x = "foo"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + let y = &mut x; //~ ERROR cannot borrow +} diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.stderr b/tests/ui/codemap_tests/huge_multispan_highlight.stderr new file mode 100644 index 000000000..9f8ce3b61 --- /dev/null +++ b/tests/ui/codemap_tests/huge_multispan_highlight.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/huge_multispan_highlight.rs:90:13 + | +LL | let y = &mut x; + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = "foo"; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/codemap_tests/issue-11715.rs b/tests/ui/codemap_tests/issue-11715.rs new file mode 100644 index 000000000..617d57ff7 --- /dev/null +++ b/tests/ui/codemap_tests/issue-11715.rs @@ -0,0 +1,11 @@ +#![feature(rustc_attrs)] +fn main() { #![rustc_error] // rust-lang/rust#49855 + let mut x = "foo"; + let y = &mut x; + let z = &mut x; //~ ERROR cannot borrow + z.use_mut(); + y.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/codemap_tests/issue-11715.stderr b/tests/ui/codemap_tests/issue-11715.stderr new file mode 100644 index 000000000..a6b2b2e50 --- /dev/null +++ b/tests/ui/codemap_tests/issue-11715.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/issue-11715.rs:5:13 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +LL | let z = &mut x; + | ^^^^^^ second mutable borrow occurs here +LL | z.use_mut(); +LL | y.use_mut(); + | ----------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/codemap_tests/issue-28308.rs b/tests/ui/codemap_tests/issue-28308.rs new file mode 100644 index 000000000..81493f8c4 --- /dev/null +++ b/tests/ui/codemap_tests/issue-28308.rs @@ -0,0 +1,4 @@ +fn main() { + assert!("foo"); + //~^ ERROR cannot apply unary operator `!` +} diff --git a/tests/ui/codemap_tests/issue-28308.stderr b/tests/ui/codemap_tests/issue-28308.stderr new file mode 100644 index 000000000..7daa0510c --- /dev/null +++ b/tests/ui/codemap_tests/issue-28308.stderr @@ -0,0 +1,11 @@ +error[E0600]: cannot apply unary operator `!` to type `&'static str` + --> $DIR/issue-28308.rs:2:5 + | +LL | assert!("foo"); + | ^^^^^^^^^^^^^^ cannot apply unary operator `!` + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/codemap_tests/one_line.rs b/tests/ui/codemap_tests/one_line.rs new file mode 100644 index 000000000..bb36813db --- /dev/null +++ b/tests/ui/codemap_tests/one_line.rs @@ -0,0 +1,4 @@ +fn main() { + let mut v = vec![Some("foo"), Some("bar")]; + v.push(v.pop().unwrap()); //~ ERROR cannot borrow +} diff --git a/tests/ui/codemap_tests/one_line.stderr b/tests/ui/codemap_tests/one_line.stderr new file mode 100644 index 000000000..6fe6e2613 --- /dev/null +++ b/tests/ui/codemap_tests/one_line.stderr @@ -0,0 +1,24 @@ +error[E0499]: cannot borrow `v` as mutable more than once at a time + --> $DIR/one_line.rs:3:12 + | +LL | v.push(v.pop().unwrap()); + | -------^^^^^^^---------- + | | | | + | | | second mutable borrow occurs here + | | first borrow later used by call + | first mutable borrow occurs here + | +help: try adding a local storing this argument... + --> $DIR/one_line.rs:3:12 + | +LL | v.push(v.pop().unwrap()); + | ^^^^^^^ +help: ...and then using that local as the argument to this call + --> $DIR/one_line.rs:3:5 + | +LL | v.push(v.pop().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/codemap_tests/overlapping_inherent_impls.rs b/tests/ui/codemap_tests/overlapping_inherent_impls.rs new file mode 100644 index 000000000..66af21226 --- /dev/null +++ b/tests/ui/codemap_tests/overlapping_inherent_impls.rs @@ -0,0 +1,36 @@ +// Test that you cannot define items with the same name in overlapping inherent +// impl blocks. + +#![allow(unused)] + +struct Foo; + +impl Foo { + fn id() {} //~ ERROR duplicate definitions +} + +impl Foo { + fn id() {} +} + +struct Bar(T); + +impl Bar { + fn bar(&self) {} //~ ERROR duplicate definitions +} + +impl Bar { + fn bar(&self) {} +} + +struct Baz(T); + +impl Baz { + fn baz(&self) {} //~ ERROR duplicate definitions +} + +impl Baz> { + fn baz(&self) {} +} + +fn main() {} diff --git a/tests/ui/codemap_tests/overlapping_inherent_impls.stderr b/tests/ui/codemap_tests/overlapping_inherent_impls.stderr new file mode 100644 index 000000000..6fca12e18 --- /dev/null +++ b/tests/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -0,0 +1,32 @@ +error[E0592]: duplicate definitions with name `id` + --> $DIR/overlapping_inherent_impls.rs:9:5 + | +LL | fn id() {} + | ^^^^^^^ duplicate definitions for `id` +... +LL | fn id() {} + | ------- other definition for `id` + +error[E0592]: duplicate definitions with name `bar` + --> $DIR/overlapping_inherent_impls.rs:19:5 + | +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^ duplicate definitions for `bar` +... +LL | fn bar(&self) {} + | ------------- other definition for `bar` + +error[E0592]: duplicate definitions with name `baz` + --> $DIR/overlapping_inherent_impls.rs:29:5 + | +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^ duplicate definitions for `baz` +... +LL | fn baz(&self) {} + | ------------- other definition for `baz` + | + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/codemap_tests/tab.rs b/tests/ui/codemap_tests/tab.rs new file mode 100644 index 000000000..64569f2e7 --- /dev/null +++ b/tests/ui/codemap_tests/tab.rs @@ -0,0 +1,9 @@ +// ignore-tidy-tab + +fn main() { + bar; //~ ERROR cannot find value `bar` +} + +fn foo() { + "bar boo" //~ ERROR mismatched types +} diff --git a/tests/ui/codemap_tests/tab.stderr b/tests/ui/codemap_tests/tab.stderr new file mode 100644 index 000000000..c3f19d20d --- /dev/null +++ b/tests/ui/codemap_tests/tab.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/tab.rs:4:2 + | +LL | bar; + | ^^^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/tab.rs:8:2 + | +LL | fn foo() { + | - help: try adding a return type: `-> &'static str` +LL | "bar boo" + | ^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&str` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/codemap_tests/tab_2.rs b/tests/ui/codemap_tests/tab_2.rs new file mode 100644 index 000000000..644697c32 --- /dev/null +++ b/tests/ui/codemap_tests/tab_2.rs @@ -0,0 +1,5 @@ +// ignore-tidy-tab + +fn main() { + """; //~ ERROR unterminated double quote +} diff --git a/tests/ui/codemap_tests/tab_2.stderr b/tests/ui/codemap_tests/tab_2.stderr new file mode 100644 index 000000000..0bfdc3ac2 --- /dev/null +++ b/tests/ui/codemap_tests/tab_2.stderr @@ -0,0 +1,11 @@ +error[E0765]: unterminated double quote string + --> $DIR/tab_2.rs:4:7 + | +LL | """; + | ___________________^ +LL | | } + | |__^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0765`. diff --git a/tests/ui/codemap_tests/tab_3.rs b/tests/ui/codemap_tests/tab_3.rs new file mode 100644 index 000000000..58b034d0f --- /dev/null +++ b/tests/ui/codemap_tests/tab_3.rs @@ -0,0 +1,9 @@ +// ignore-tidy-tab + +fn main() { + let some_vec = vec!["hi"]; + some_vec.into_iter(); + { + println!("{:?}", some_vec); //~ ERROR borrow of moved + } +} diff --git a/tests/ui/codemap_tests/tab_3.stderr b/tests/ui/codemap_tests/tab_3.stderr new file mode 100644 index 000000000..17bea2f36 --- /dev/null +++ b/tests/ui/codemap_tests/tab_3.stderr @@ -0,0 +1,22 @@ +error[E0382]: borrow of moved value: `some_vec` + --> $DIR/tab_3.rs:7:20 + | +LL | let some_vec = vec!["hi"]; + | -------- move occurs because `some_vec` has type `Vec<&str>`, which does not implement the `Copy` trait +LL | some_vec.into_iter(); + | ----------- `some_vec` moved due to this method call +LL | { +LL | println!("{:?}", some_vec); + | ^^^^^^^^ value borrowed here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | some_vec.clone().into_iter(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/codemap_tests/two_files.rs b/tests/ui/codemap_tests/two_files.rs new file mode 100644 index 000000000..71d97d3c2 --- /dev/null +++ b/tests/ui/codemap_tests/two_files.rs @@ -0,0 +1,7 @@ +include!("two_files_data.rs"); + +struct Baz { } + +impl Bar for Baz { } //~ ERROR expected trait, found type alias + +fn main() { } diff --git a/tests/ui/codemap_tests/two_files.stderr b/tests/ui/codemap_tests/two_files.stderr new file mode 100644 index 000000000..2eb3fd567 --- /dev/null +++ b/tests/ui/codemap_tests/two_files.stderr @@ -0,0 +1,15 @@ +error[E0404]: expected trait, found type alias `Bar` + --> $DIR/two_files.rs:5:6 + | +LL | impl Bar for Baz { } + | ^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + --> $DIR/two_files_data.rs:5:1 + | +LL | trait Bar = dyn Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/codemap_tests/two_files_data.rs b/tests/ui/codemap_tests/two_files_data.rs new file mode 100644 index 000000000..b4d2f5d3c --- /dev/null +++ b/tests/ui/codemap_tests/two_files_data.rs @@ -0,0 +1,5 @@ +// ignore-test + +trait Foo { } + +type Bar = dyn Foo; diff --git a/tests/ui/codemap_tests/unicode.expanded.stdout b/tests/ui/codemap_tests/unicode.expanded.stdout new file mode 100644 index 000000000..d14bb42b2 --- /dev/null +++ b/tests/ui/codemap_tests/unicode.expanded.stdout @@ -0,0 +1,13 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// revisions: normal expanded +//[expanded] check-pass +//[expanded]compile-flags: -Zunpretty=expanded + +extern "路濫狼áÌÌ" fn foo() {} + +fn main() {} diff --git a/tests/ui/codemap_tests/unicode.normal.stderr b/tests/ui/codemap_tests/unicode.normal.stderr new file mode 100644 index 000000000..05ceb6910 --- /dev/null +++ b/tests/ui/codemap_tests/unicode.normal.stderr @@ -0,0 +1,11 @@ +error[E0703]: invalid ABI: found `路濫狼áÌÌ` + --> $DIR/unicode.rs:5:8 + | +LL | extern "路濫狼áÌÌ" fn foo() {} + | ^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/codemap_tests/unicode.rs b/tests/ui/codemap_tests/unicode.rs new file mode 100644 index 000000000..4df9a5270 --- /dev/null +++ b/tests/ui/codemap_tests/unicode.rs @@ -0,0 +1,7 @@ +// revisions: normal expanded +//[expanded] check-pass +//[expanded]compile-flags: -Zunpretty=expanded + +extern "路濫狼áÌÌ" fn foo() {} //[normal]~ ERROR invalid ABI + +fn main() { } diff --git a/tests/ui/codemap_tests/unicode_2.rs b/tests/ui/codemap_tests/unicode_2.rs new file mode 100644 index 000000000..3301e7a18 --- /dev/null +++ b/tests/ui/codemap_tests/unicode_2.rs @@ -0,0 +1,5 @@ +fn main() { + let _ = ("aÌeÌö̲", 0u7); //~ ERROR invalid width + let _ = ("ì•„ã‚", 1i42); //~ ERROR invalid width + let _ = aÌeÌ; //~ ERROR cannot find +} diff --git a/tests/ui/codemap_tests/unicode_2.stderr b/tests/ui/codemap_tests/unicode_2.stderr new file mode 100644 index 000000000..19aae1d3c --- /dev/null +++ b/tests/ui/codemap_tests/unicode_2.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find value `aÌé` in this scope + --> $DIR/unicode_2.rs:4:13 + | +LL | let _ = aÌeÌ; + | ^^ not found in this scope + +error: invalid width `7` for integer literal + --> $DIR/unicode_2.rs:2:25 + | +LL | let _ = ("aÌeÌö̲", 0u7); + | ^^^ + | + = help: valid widths are 8, 16, 32, 64 and 128 + +error: invalid width `42` for integer literal + --> $DIR/unicode_2.rs:3:20 + | +LL | let _ = ("ì•„ã‚", 1i42); + | ^^^^ + | + = help: valid widths are 8, 16, 32, 64 and 128 + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/codemap_tests/unicode_3.rs b/tests/ui/codemap_tests/unicode_3.rs new file mode 100644 index 000000000..34582de45 --- /dev/null +++ b/tests/ui/codemap_tests/unicode_3.rs @@ -0,0 +1,6 @@ +// check-pass + +fn main() { + let s = "ZͨA͑ͦ͒͋ͤ͑̚LÌ„Í‘Í‹Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!Ì"; while true { break; } //~ WARNING while_true + println!("{}", s); +} diff --git a/tests/ui/codemap_tests/unicode_3.stderr b/tests/ui/codemap_tests/unicode_3.stderr new file mode 100644 index 000000000..a35ed99d8 --- /dev/null +++ b/tests/ui/codemap_tests/unicode_3.stderr @@ -0,0 +1,10 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/unicode_3.rs:4:45 + | +LL | let s = "ZͨA͑ͦ͒͋ͤ͑̚LÌ„Í‘Í‹Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!Ì"; while true { break; } + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/coercion/auxiliary/issue-39823.rs b/tests/ui/coercion/auxiliary/issue-39823.rs new file mode 100644 index 000000000..3af9c68f2 --- /dev/null +++ b/tests/ui/coercion/auxiliary/issue-39823.rs @@ -0,0 +1,7 @@ +#![crate_type="rlib"] + +#[derive(Debug, PartialEq)] +pub struct RemoteC(pub u32); + +#[derive(Debug, PartialEq)] +pub struct RemoteG(pub T); diff --git a/tests/ui/coercion/coerce-block-tail-26978.rs b/tests/ui/coercion/coerce-block-tail-26978.rs new file mode 100644 index 000000000..01c8ab5a8 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-26978.rs @@ -0,0 +1,11 @@ +// check-fail +fn f(_: &i32) {} + +fn main() { + let x = Box::new(1i32); + + f(&x); + f(&(x)); + f(&{x}); + //~^ ERROR mismatched types +} diff --git a/tests/ui/coercion/coerce-block-tail-26978.stderr b/tests/ui/coercion/coerce-block-tail-26978.stderr new file mode 100644 index 000000000..384debd48 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-26978.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-26978.rs:9:9 + | +LL | f(&{x}); + | ^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box` +help: consider unboxing the value + | +LL | f(&{*x}); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail-57749.rs b/tests/ui/coercion/coerce-block-tail-57749.rs new file mode 100644 index 000000000..79b5b3323 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-57749.rs @@ -0,0 +1,35 @@ +// check-fail +use std::ops::Deref; + +fn main() { + fn save(who: &str) { + println!("I'll save you, {}!", who); + } + + struct Madoka; + + impl Deref for Madoka { + type Target = str; + fn deref(&self) -> &Self::Target { + "Madoka" + } + } + + save(&{ Madoka }); + + fn reset(how: &u32) { + println!("Reset {} times", how); + } + + struct Homura; + + impl Deref for Homura { + type Target = u32; + fn deref(&self) -> &Self::Target { + &42 + } + } + + reset(&{ Homura }); + //~^ ERROR mismatched types +} diff --git a/tests/ui/coercion/coerce-block-tail-57749.stderr b/tests/ui/coercion/coerce-block-tail-57749.stderr new file mode 100644 index 000000000..d5660c81d --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-57749.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-57749.rs:33:14 + | +LL | reset(&{ Homura }); + | ^^^^^^ expected `u32`, found struct `Homura` + | +help: consider dereferencing the type + | +LL | reset(&{ *Homura }); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail-83783.rs b/tests/ui/coercion/coerce-block-tail-83783.rs new file mode 100644 index 000000000..18c8ae3bb --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-83783.rs @@ -0,0 +1,13 @@ +// check-fail +// edition:2018 +fn _consume_reference(_: &T) {} + +async fn _foo() { + _consume_reference::(&Box::new(7_i32)); + _consume_reference::(&async { Box::new(7_i32) }.await); + //~^ ERROR mismatched types + _consume_reference::<[i32]>(&vec![7_i32]); + _consume_reference::<[i32]>(&async { vec![7_i32] }.await); +} + +fn main() { } diff --git a/tests/ui/coercion/coerce-block-tail-83783.stderr b/tests/ui/coercion/coerce-block-tail-83783.stderr new file mode 100644 index 000000000..5f53606ce --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-83783.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-83783.rs:7:32 + | +LL | _consume_reference::(&async { Box::new(7_i32) }.await); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail-83850.rs b/tests/ui/coercion/coerce-block-tail-83850.rs new file mode 100644 index 000000000..77fdf9998 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-83850.rs @@ -0,0 +1,7 @@ +// check-fail +fn f(_: &[i32]) {} + +fn main() { + f(&Box::new([1, 2])); + //~^ ERROR mismatched types +} diff --git a/tests/ui/coercion/coerce-block-tail-83850.stderr b/tests/ui/coercion/coerce-block-tail-83850.stderr new file mode 100644 index 000000000..bbf607543 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail-83850.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail-83850.rs:5:7 + | +LL | f(&Box::new([1, 2])); + | - ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found struct `Box` + | | + | arguments to this function are incorrect + | + = note: expected reference `&[i32]` + found reference `&Box<[{integer}; 2]>` +note: function defined here + --> $DIR/coerce-block-tail-83850.rs:2:4 + | +LL | fn f(_: &[i32]) {} + | ^ --------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-block-tail.rs b/tests/ui/coercion/coerce-block-tail.rs new file mode 100644 index 000000000..dcbcd3762 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail.rs @@ -0,0 +1,6 @@ +// check-fail +fn main() { + let _: &str = & { String::from("hahah")}; + let _: &i32 = & { Box::new(1i32) }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/coercion/coerce-block-tail.stderr b/tests/ui/coercion/coerce-block-tail.stderr new file mode 100644 index 000000000..318cf7586 --- /dev/null +++ b/tests/ui/coercion/coerce-block-tail.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/coerce-block-tail.rs:4:23 + | +LL | let _: &i32 = & { Box::new(1i32) }; + | ^^^^^^^^^^^^^^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box` +help: consider unboxing the value + | +LL | let _: &i32 = & { *Box::new(1i32) }; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-expect-unsized-ascribed.rs b/tests/ui/coercion/coerce-expect-unsized-ascribed.rs new file mode 100644 index 000000000..d7b11317a --- /dev/null +++ b/tests/ui/coercion/coerce-expect-unsized-ascribed.rs @@ -0,0 +1,32 @@ +// A version of coerce-expect-unsized that uses type ascription. +// Doesn't work so far, but supposed to work eventually + +#![feature(box_syntax, type_ascription)] + +use std::fmt::Debug; + +pub fn main() { + let _ = type_ascribe!(box { [1, 2, 3] }, Box<[i32]>); //~ ERROR mismatched types + let _ = type_ascribe!(box if true { [1, 2, 3] } else { [1, 3, 4] }, Box<[i32]>); //~ ERROR mismatched types + let _ = type_ascribe!(box match true { true => [1, 2, 3], false => [1, 3, 4] }, Box<[i32]>); + //~^ ERROR mismatched types + let _ = type_ascribe!(box { |x| (x as u8) }, Box _>); //~ ERROR mismatched types + let _ = type_ascribe!(box if true { false } else { true }, Box); //~ ERROR mismatched types + let _ = type_ascribe!(box match true { true => 'a', false => 'b' }, Box); //~ ERROR mismatched types + + let _ = type_ascribe!(&{ [1, 2, 3] }, &[i32]); //~ ERROR mismatched types + let _ = type_ascribe!(&if true { [1, 2, 3] } else { [1, 3, 4] }, &[i32]); //~ ERROR mismatched types + let _ = type_ascribe!(&match true { true => [1, 2, 3], false => [1, 3, 4] }, &[i32]); + //~^ ERROR mismatched types + let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _); //~ ERROR mismatched types + let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug); //~ ERROR mismatched types + let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn Debug); //~ ERROR mismatched types + + let _ = type_ascribe!(Box::new([1, 2, 3]), Box<[i32]>); //~ ERROR mismatched types + let _ = type_ascribe!(Box::new(|x| (x as u8)), Box _>); //~ ERROR mismatched types + + let _ = type_ascribe!(vec![ + Box::new(|x| (x as u8)), + box |x| (x as i16 as u8), + ], Vec _>>); +} diff --git a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr new file mode 100644 index 000000000..44968244c --- /dev/null +++ b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr @@ -0,0 +1,129 @@ +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:9:27 + | +LL | let _ = type_ascribe!(box { [1, 2, 3] }, Box<[i32]>); + | ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:10:27 + | +LL | let _ = type_ascribe!(box if true { [1, 2, 3] } else { [1, 3, 4] }, Box<[i32]>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:11:27 + | +LL | let _ = type_ascribe!(box match true { true => [1, 2, 3], false => [1, 3, 4] }, Box<[i32]>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:13:27 + | +LL | let _ = type_ascribe!(box { |x| (x as u8) }, Box _>); + | ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure + | + = note: expected struct `Box u8>` + found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:33: 13:36]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:14:27 + | +LL | let _ = type_ascribe!(box if true { false } else { true }, Box); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool` + | + = note: expected struct `Box` + found struct `Box` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:15:27 + | +LL | let _ = type_ascribe!(box match true { true => 'a', false => 'b' }, Box); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char` + | + = note: expected struct `Box` + found struct `Box` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:17:27 + | +LL | let _ = type_ascribe!(&{ [1, 2, 3] }, &[i32]); + | ^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected reference `&[i32]` + found reference `&[i32; 3]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:18:27 + | +LL | let _ = type_ascribe!(&if true { [1, 2, 3] } else { [1, 3, 4] }, &[i32]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected reference `&[i32]` + found reference `&[i32; 3]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:19:27 + | +LL | let _ = type_ascribe!(&match true { true => [1, 2, 3], false => [1, 3, 4] }, &[i32]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected reference `&[i32]` + found reference `&[i32; 3]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:21:27 + | +LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _); + | ^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure + | + = note: expected reference `&dyn Fn(i32) -> u8` + found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:30: 21:33]` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:22:27 + | +LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool` + | + = note: expected reference `&dyn Debug` + found reference `&bool` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:23:27 + | +LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn Debug); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char` + | + = note: expected reference `&dyn Debug` + found reference `&char` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:25:27 + | +LL | let _ = type_ascribe!(Box::new([1, 2, 3]), Box<[i32]>); + | ^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` + | + = note: expected struct `Box<[i32]>` + found struct `Box<[i32; 3]>` + +error[E0308]: mismatched types + --> $DIR/coerce-expect-unsized-ascribed.rs:26:27 + | +LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box _>); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure + | + = note: expected struct `Box u8>` + found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:36: 26:39]>` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-expect-unsized.rs b/tests/ui/coercion/coerce-expect-unsized.rs new file mode 100644 index 000000000..eeb8fe823 --- /dev/null +++ b/tests/ui/coercion/coerce-expect-unsized.rs @@ -0,0 +1,43 @@ +// run-pass +#![allow(unused_braces)] + +use std::cell::RefCell; +use std::fmt::Debug; +use std::rc::Rc; + +// Check that coercions apply at the pointer level and don't cause +// rvalue expressions to be unsized. See #20169 for more information. + +pub fn main() { + let _: Box<[isize]> = Box::new({ [1, 2, 3] }); + let _: Box<[isize]> = Box::new(if true { [1, 2, 3] } else { [1, 3, 4] }); + let _: Box<[isize]> = Box::new(match true { true => [1, 2, 3], false => [1, 3, 4] }); + let _: Box _> = Box::new({ |x| (x as u8) }); + let _: Box = Box::new(if true { false } else { true }); + let _: Box = Box::new(match true { true => 'a', false => 'b' }); + + let _: &[isize] = &{ [1, 2, 3] }; + let _: &[isize] = &if true { [1, 2, 3] } else { [1, 3, 4] }; + let _: &[isize] = &match true { true => [1, 2, 3], false => [1, 3, 4] }; + let _: &dyn Fn(isize) -> _ = &{ |x| (x as u8) }; + let _: &dyn Debug = &if true { false } else { true }; + let _: &dyn Debug = &match true { true => 'a', false => 'b' }; + + let _: &str = &{ String::new() }; + let _: &str = &if true { String::from("...") } else { 5.to_string() }; + let _: &str = &match true { + true => format!("{}", false), + false => ["x", "y"].join("+") + }; + + let _: Box<[isize]> = Box::new([1, 2, 3]); + let _: Box _> = Box::new(|x| (x as u8)); + + let _: Rc> = Rc::new(RefCell::new([1, 2, 3])); + let _: Rc _>> = Rc::new(RefCell::new(|x| (x as u8))); + + let _: Vec _>> = vec![ + Box::new(|x| (x as u8)), + Box::new(|x| (x as i16 as u8)), + ]; +} diff --git a/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr new file mode 100644 index 000000000..980da5360 --- /dev/null +++ b/tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never-windows.rs:18:53 + | +LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `dyn std::error::Error` + +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never-windows.rs:23:49 + | +LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never-windows.rs b/tests/ui/coercion/coerce-issue-49593-box-never-windows.rs new file mode 100644 index 000000000..95d3935ca --- /dev/null +++ b/tests/ui/coercion/coerce-issue-49593-box-never-windows.rs @@ -0,0 +1,58 @@ +// revisions: nofallback fallback +// only-windows - the number of `Error` impls is platform-dependent +//[fallback] check-pass +//[nofallback] check-fail + +#![feature(never_type)] +#![cfg_attr(fallback, feature(never_type_fallback))] +#![allow(unreachable_code)] + +use std::error::Error; +use std::mem; + +fn raw_ptr_box(t: T) -> *mut T { + panic!() +} + +fn foo(x: !) -> Box { + /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn foo_raw_ptr(x: !) -> *mut dyn Error { + /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { + /* an unsize coercion won't compile here, and it is indeed not used + because there is nothing requiring the _ to be Sized */ + d as *mut _ +} + +trait Xyz {} +struct S; +struct T; +impl Xyz for S {} +impl Xyz for T {} + +fn foo_no_never() { + let mut x /* : Option */ = None; + let mut first_iter = false; + loop { + if !first_iter { + let y: Box + = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + } + + x = Some(S); + first_iter = true; + } + + let mut y : Option = None; + // assert types are equal + mem::swap(&mut x, &mut y); +} + +fn main() { +} diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr new file mode 100644 index 000000000..322681b97 --- /dev/null +++ b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:18:53 + | +LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `dyn std::error::Error` + +error[E0277]: the trait bound `(): std::error::Error` is not satisfied + --> $DIR/coerce-issue-49593-box-never.rs:23:49 + | +LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` + | + = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.rs b/tests/ui/coercion/coerce-issue-49593-box-never.rs new file mode 100644 index 000000000..16efb65ac --- /dev/null +++ b/tests/ui/coercion/coerce-issue-49593-box-never.rs @@ -0,0 +1,58 @@ +// revisions: nofallback fallback +// ignore-windows - the number of `Error` impls is platform-dependent +//[fallback] check-pass +//[nofallback] check-fail + +#![feature(never_type)] +#![cfg_attr(fallback, feature(never_type_fallback))] +#![allow(unreachable_code)] + +use std::error::Error; +use std::mem; + +fn raw_ptr_box(t: T) -> *mut T { + panic!() +} + +fn foo(x: !) -> Box { + /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn foo_raw_ptr(x: !) -> *mut dyn Error { + /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) + //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied +} + +fn no_coercion(d: *mut dyn Error) -> *mut dyn Error { + /* an unsize coercion won't compile here, and it is indeed not used + because there is nothing requiring the _ to be Sized */ + d as *mut _ +} + +trait Xyz {} +struct S; +struct T; +impl Xyz for S {} +impl Xyz for T {} + +fn foo_no_never() { + let mut x /* : Option */ = None; + let mut first_iter = false; + loop { + if !first_iter { + let y: Box + = /* Box<$0> is coerced to Box here */ Box::new(x.unwrap()); + } + + x = Some(S); + first_iter = true; + } + + let mut y : Option = None; + // assert types are equal + mem::swap(&mut x, &mut y); +} + +fn main() { +} diff --git a/tests/ui/coercion/coerce-mut.rs b/tests/ui/coercion/coerce-mut.rs new file mode 100644 index 000000000..43f0b5585 --- /dev/null +++ b/tests/ui/coercion/coerce-mut.rs @@ -0,0 +1,10 @@ +fn f(x: &mut i32) {} + +fn main() { + let x = 0; + f(&x); + //~^ ERROR mismatched types + //~| expected mutable reference `&mut i32` + //~| found reference `&{integer}` + //~| types differ in mutability +} diff --git a/tests/ui/coercion/coerce-mut.stderr b/tests/ui/coercion/coerce-mut.stderr new file mode 100644 index 000000000..11a4f3101 --- /dev/null +++ b/tests/ui/coercion/coerce-mut.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coerce-mut.rs:5:7 + | +LL | f(&x); + | - ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut i32` + found reference `&{integer}` +note: function defined here + --> $DIR/coerce-mut.rs:1:4 + | +LL | fn f(x: &mut i32) {} + | ^ ----------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-overloaded-autoderef-fail.rs b/tests/ui/coercion/coerce-overloaded-autoderef-fail.rs new file mode 100644 index 000000000..01d9c1e48 --- /dev/null +++ b/tests/ui/coercion/coerce-overloaded-autoderef-fail.rs @@ -0,0 +1,32 @@ +fn borrow_mut(x: &mut T) -> &mut T { x } +fn borrow(x: &T) -> &T { x } + +fn borrow_mut2(_: &mut T, _: &mut T) {} +fn borrow2(_: &mut T, _: &T) {} + +fn double_mut_borrow(x: &mut Box) { + let y = borrow_mut(x); + let z = borrow_mut(x); + //~^ ERROR cannot borrow `*x` as mutable more than once at a time + drop((y, z)); +} + +fn double_imm_borrow(x: &mut Box) { + let y = borrow(x); + let z = borrow(x); + **x += 1; + //~^ ERROR cannot assign to `**x` because it is borrowed + drop((y, z)); +} + +fn double_mut_borrow2(x: &mut Box) { + borrow_mut2(x, x); + //~^ ERROR cannot borrow `*x` as mutable more than once at a time +} + +fn double_borrow2(x: &mut Box) { + borrow2(x, x); + //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable +} + +pub fn main() {} diff --git a/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr b/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr new file mode 100644 index 000000000..d067c3b3a --- /dev/null +++ b/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr @@ -0,0 +1,46 @@ +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/coerce-overloaded-autoderef-fail.rs:9:24 + | +LL | let y = borrow_mut(x); + | - first mutable borrow occurs here +LL | let z = borrow_mut(x); + | ^ second mutable borrow occurs here +LL | +LL | drop((y, z)); + | - first borrow later used here + +error[E0506]: cannot assign to `**x` because it is borrowed + --> $DIR/coerce-overloaded-autoderef-fail.rs:17:5 + | +LL | let y = borrow(x); + | - borrow of `**x` occurs here +LL | let z = borrow(x); +LL | **x += 1; + | ^^^^^^^^ assignment to borrowed `**x` occurs here +LL | +LL | drop((y, z)); + | - borrow later used here + +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/coerce-overloaded-autoderef-fail.rs:23:20 + | +LL | borrow_mut2(x, x); + | ----------- - ^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + +error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable + --> $DIR/coerce-overloaded-autoderef-fail.rs:28:5 + | +LL | borrow2(x, x); + | -------^^^^-^ + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | immutable borrow later used by call + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0499, E0502, E0506. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/coercion/coerce-overloaded-autoderef.rs b/tests/ui/coercion/coerce-overloaded-autoderef.rs new file mode 100644 index 000000000..d5484607c --- /dev/null +++ b/tests/ui/coercion/coerce-overloaded-autoderef.rs @@ -0,0 +1,68 @@ +// run-pass +#![allow(unused_braces)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::rc::Rc; + +// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241. + +fn use_ref(_: &T) {} +fn use_mut(_: &mut T) {} + +fn use_rc(t: Rc) { + use_ref(&*t); // what you have to write today + use_ref(&t); // what you'd be able to write + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_mut_box(mut t: &mut Box) { + use_mut(&mut *t); // what you have to write today + use_mut(t); // what you'd be able to write + use_mut(&mut &mut &mut t); + + use_ref(&*t); // what you have to write today + use_ref(t); // what you'd be able to write + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_nested(t: &Box) { + use_ref(&**t); // what you have to write today + use_ref(t); // what you'd be able to write (note: recursive deref) + use_ref(&&&&&&t); + use_ref(&mut &&&&&t); + use_ref(&&&mut &&&t); +} + +fn use_slice(_: &[u8]) {} +fn use_slice_mut(_: &mut [u8]) {} + +fn use_vec(mut v: Vec) { + use_slice_mut(&mut v[..]); // what you have to write today + use_slice_mut(&mut v); // what you'd be able to write + use_slice_mut(&mut &mut &mut v); + + use_slice(&v[..]); // what you have to write today + use_slice(&v); // what you'd be able to write + use_slice(&&&&&&v); + use_slice(&mut &&&&&v); + use_slice(&&&mut &&&v); +} + +fn use_vec_ref(v: &Vec) { + use_slice(&v[..]); // what you have to write today + use_slice(v); // what you'd be able to write + use_slice(&&&&&&v); + use_slice(&mut &&&&&v); + use_slice(&&&mut &&&v); +} + +fn use_op_rhs(s: &mut String) { + *s += {&String::from(" ")}; +} + +pub fn main() {} diff --git a/tests/ui/coercion/coerce-reborrow-imm-ptr-arg.rs b/tests/ui/coercion/coerce-reborrow-imm-ptr-arg.rs new file mode 100644 index 000000000..f033e1b5d --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-imm-ptr-arg.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn negate(x: &isize) -> isize { + -*x +} + +fn negate_mut(y: &mut isize) -> isize { + negate(y) +} + +fn negate_imm(y: &isize) -> isize { + negate(y) +} + +pub fn main() {} diff --git a/tests/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs b/tests/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs new file mode 100644 index 000000000..64a365229 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs @@ -0,0 +1,18 @@ +// run-pass + +struct SpeechMaker { + speeches: usize +} + +impl SpeechMaker { + pub fn how_many(&self) -> usize { self.speeches } +} + +fn foo(speaker: &SpeechMaker) -> usize { + speaker.how_many() + 33 +} + +pub fn main() { + let lincoln = SpeechMaker {speeches: 22}; + assert_eq!(foo(&lincoln), 55); +} diff --git a/tests/ui/coercion/coerce-reborrow-imm-vec-arg.rs b/tests/ui/coercion/coerce-reborrow-imm-vec-arg.rs new file mode 100644 index 000000000..c2aaae1c7 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-imm-vec-arg.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn sum(x: &[isize]) -> isize { + let mut sum = 0; + for y in x { sum += *y; } + return sum; +} + +fn sum_mut(y: &mut [isize]) -> isize { + sum(y) +} + +fn sum_imm(y: &[isize]) -> isize { + sum(y) +} + +pub fn main() {} diff --git a/tests/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs b/tests/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs new file mode 100644 index 000000000..9a5652acf --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs @@ -0,0 +1,16 @@ +// run-pass + + +fn bar(v: &mut [usize]) -> Vec { + v.to_vec() +} + +fn bip(v: &[usize]) -> Vec { + v.to_vec() +} + +pub fn main() { + let mut the_vec = vec![1, 2, 3, 100]; + assert_eq!(the_vec.clone(), bar(&mut the_vec)); + assert_eq!(the_vec.clone(), bip(&the_vec)); +} diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs new file mode 100644 index 000000000..48be2d314 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs @@ -0,0 +1,6 @@ +fn test(_a: T, _b: T) {} + +fn main() { + test(&mut 7, &7); + //~^ mismatched types +} diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr new file mode 100644 index 000000000..5cbdef218 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18 + | +LL | test(&mut 7, &7); + | ---- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut {integer}` + found reference `&{integer}` +note: function defined here + --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4 + | +LL | fn test(_a: T, _b: T) {} + | ^^^^ ----- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg.rs b/tests/ui/coercion/coerce-reborrow-multi-arg.rs new file mode 100644 index 000000000..93cd0bb3e --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-multi-arg.rs @@ -0,0 +1,9 @@ +// build-pass +fn test(_a: T, _b: T) {} + +fn main() { + test(&7, &7); + test(&7, &mut 7); + test::<&i32>(&mut 7, &7); + test::<&i32>(&mut 7, &mut 7); +} diff --git a/tests/ui/coercion/coerce-reborrow-mut-ptr-arg.rs b/tests/ui/coercion/coerce-reborrow-mut-ptr-arg.rs new file mode 100644 index 000000000..76cd6793b --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-mut-ptr-arg.rs @@ -0,0 +1,25 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct SpeechMaker { + speeches: usize +} + +fn talk(x: &mut SpeechMaker) { + x.speeches += 1; +} + +fn give_a_few_speeches(speaker: &mut SpeechMaker) { + + // Here speaker is reborrowed for each call, so we don't get errors + // about speaker being moved. + + talk(speaker); + talk(speaker); + talk(speaker); +} + +pub fn main() { + let mut lincoln = SpeechMaker {speeches: 22}; + give_a_few_speeches(&mut lincoln); +} diff --git a/tests/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs b/tests/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs new file mode 100644 index 000000000..e6e7c3a51 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs @@ -0,0 +1,27 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct SpeechMaker { + speeches: usize +} + +impl SpeechMaker { + pub fn talk(&mut self) { + self.speeches += 1; + } +} + +fn give_a_few_speeches(speaker: &mut SpeechMaker) { + + // Here speaker is reborrowed for each call, so we don't get errors + // about speaker being moved. + + speaker.talk(); + speaker.talk(); + speaker.talk(); +} + +pub fn main() { + let mut lincoln = SpeechMaker {speeches: 22}; + give_a_few_speeches(&mut lincoln); +} diff --git a/tests/ui/coercion/coerce-reborrow-mut-vec-arg.rs b/tests/ui/coercion/coerce-reborrow-mut-vec-arg.rs new file mode 100644 index 000000000..2635754f1 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-mut-vec-arg.rs @@ -0,0 +1,18 @@ +// run-pass + + +fn reverse(v: &mut [usize]) { + v.reverse(); +} + +fn bar(v: &mut [usize]) { + reverse(v); + reverse(v); + reverse(v); +} + +pub fn main() { + let mut the_vec = vec![1, 2, 3, 100]; + bar(&mut the_vec); + assert_eq!(the_vec, [100, 3, 2, 1]); +} diff --git a/tests/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs b/tests/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs new file mode 100644 index 000000000..c03336ea3 --- /dev/null +++ b/tests/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs @@ -0,0 +1,14 @@ +// run-pass + + +fn bar(v: &mut [usize]) { + v.reverse(); + v.reverse(); + v.reverse(); +} + +pub fn main() { + let mut the_vec = vec![1, 2, 3, 100]; + bar(&mut the_vec); + assert_eq!(the_vec, [100, 3, 2, 1]); +} diff --git a/tests/ui/coercion/coerce-to-bang-cast.rs b/tests/ui/coercion/coerce-to-bang-cast.rs new file mode 100644 index 000000000..85598a42e --- /dev/null +++ b/tests/ui/coercion/coerce-to-bang-cast.rs @@ -0,0 +1,12 @@ +#![feature(never_type)] + +fn cast_a() { + let y = {return; 22} as !; + //~^ ERROR non-primitive cast +} + +fn cast_b() { + let y = 22 as !; //~ ERROR non-primitive cast +} + +fn main() { } diff --git a/tests/ui/coercion/coerce-to-bang-cast.stderr b/tests/ui/coercion/coerce-to-bang-cast.stderr new file mode 100644 index 000000000..50e009aa2 --- /dev/null +++ b/tests/ui/coercion/coerce-to-bang-cast.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `i32` as `!` + --> $DIR/coerce-to-bang-cast.rs:4:13 + | +LL | let y = {return; 22} as !; + | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `i32` as `!` + --> $DIR/coerce-to-bang-cast.rs:9:13 + | +LL | let y = 22 as !; + | ^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/coercion/coerce-to-bang.rs b/tests/ui/coercion/coerce-to-bang.rs new file mode 100644 index 000000000..1e06934d0 --- /dev/null +++ b/tests/ui/coercion/coerce-to-bang.rs @@ -0,0 +1,79 @@ +#![feature(never_type)] + +fn foo(x: usize, y: !, z: usize) { } + +fn call_foo_a() { + foo(return, 22, 44); + //~^ ERROR mismatched types +} + +fn call_foo_b() { + // Divergence happens in the argument itself, definitely ok. + foo(22, return, 44); +} + +fn call_foo_c() { + // This test fails because the divergence happens **after** the + // coercion to `!`: + foo(22, 44, return); //~ ERROR mismatched types +} + +fn call_foo_d() { + // This test passes because `a` has type `!`: + let a: ! = return; + let b = 22; + let c = 44; + foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. + //~^ ERROR mismatched types +} + +fn call_foo_e() { + // This test probably could pass but we don't *know* that `a` + // has type `!` so we don't let it work. + let a = return; + let b = 22; + let c = 44; + foo(a, b, c); //~ ERROR mismatched types +} + +fn call_foo_f() { + // This fn fails because `a` has type `usize`, and hence a + // reference to is it **not** considered to diverge. + let a: usize = return; + let b = 22; + let c = 44; + foo(a, b, c); //~ ERROR mismatched types +} + +fn array_a() { + // Return is coerced to `!` just fine, but `22` cannot be. + let x: [!; 2] = [return, 22]; //~ ERROR mismatched types +} + +fn array_b() { + // Error: divergence has not yet occurred. + let x: [!; 2] = [22, return]; //~ ERROR mismatched types +} + +fn tuple_a() { + // No divergence at all. + let x: (usize, !, usize) = (22, 44, 66); //~ ERROR mismatched types +} + +fn tuple_b() { + // Divergence happens before coercion: OK + let x: (usize, !, usize) = (return, 44, 66); + //~^ ERROR mismatched types +} + +fn tuple_c() { + // Divergence happens before coercion: OK + let x: (usize, !, usize) = (22, return, 66); +} + +fn tuple_d() { + // Error: divergence happens too late + let x: (usize, !, usize) = (22, 44, return); //~ ERROR mismatched types +} + +fn main() { } diff --git a/tests/ui/coercion/coerce-to-bang.stderr b/tests/ui/coercion/coerce-to-bang.stderr new file mode 100644 index 000000000..1207dc7e7 --- /dev/null +++ b/tests/ui/coercion/coerce-to-bang.stderr @@ -0,0 +1,130 @@ +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:6:17 + | +LL | foo(return, 22, 44); + | --- ^^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ ---- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:18:13 + | +LL | foo(22, 44, return); + | --- ^^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ ---- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:26:12 + | +LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. + | --- ^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ ---- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:36:12 + | +LL | foo(a, b, c); + | --- ^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ ---- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:45:12 + | +LL | foo(a, b, c); + | --- ^ expected `!`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found type `{integer}` +note: function defined here + --> $DIR/coerce-to-bang.rs:3:4 + | +LL | fn foo(x: usize, y: !, z: usize) { } + | ^^^ ---- + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:50:21 + | +LL | let x: [!; 2] = [return, 22]; + | ------ ^^^^^^^^^^^^ expected `!`, found integer + | | + | expected due to this + | + = note: expected array `[!; 2]` + found array `[{integer}; 2]` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:55:22 + | +LL | let x: [!; 2] = [22, return]; + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:60:37 + | +LL | let x: (usize, !, usize) = (22, 44, 66); + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:65:41 + | +LL | let x: (usize, !, usize) = (return, 44, 66); + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/coerce-to-bang.rs:76:37 + | +LL | let x: (usize, !, usize) = (22, 44, return); + | ^^ expected `!`, found integer + | + = note: expected type `!` + found type `{integer}` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coerce-unify-return.rs b/tests/ui/coercion/coerce-unify-return.rs new file mode 100644 index 000000000..95a7ee8fe --- /dev/null +++ b/tests/ui/coercion/coerce-unify-return.rs @@ -0,0 +1,19 @@ +// run-pass +// Check that coercions unify the expected return type of a polymorphic +// function call, instead of leaving the type variables as they were. + +// pretty-expanded FIXME #23616 + +struct Foo; +impl Foo { + fn foo(self, x: T) -> Option { Some(x) } +} + +pub fn main() { + let _: Option = Some(main); + let _: Option = Foo.foo(main); + + // The same two cases, with implicit type variables made explicit. + let _: Option = Some::<_>(main); + let _: Option = Foo.foo::<_>(main); +} diff --git a/tests/ui/coercion/coerce-unify.rs b/tests/ui/coercion/coerce-unify.rs new file mode 100644 index 000000000..f1818f9bb --- /dev/null +++ b/tests/ui/coercion/coerce-unify.rs @@ -0,0 +1,68 @@ +// run-pass +// Check that coercions can unify if-else, match arms and array elements. + +// Try to construct if-else chains, matches and arrays out of given expressions. +macro_rules! check { + ($last:expr $(, $rest:expr)+) => { + // Last expression comes first because of whacky ifs and matches. + let _ = $(if false { $rest })else+ else { $last }; + + let _ = match 0 { $(_ if false => $rest,)+ _ => $last }; + + let _ = [$($rest,)+ $last]; + } +} + +// Check all non-uniform cases of 2 and 3 expressions of 2 types. +macro_rules! check2 { + ($a:expr, $b:expr) => { + check!($a, $b); + check!($b, $a); + + check!($a, $a, $b); + check!($a, $b, $a); + check!($a, $b, $b); + + check!($b, $a, $a); + check!($b, $a, $b); + check!($b, $b, $a); + } +} + +// Check all non-uniform cases of 2 and 3 expressions of 3 types. +macro_rules! check3 { + ($a:expr, $b:expr, $c:expr) => { + // Delegate to check2 for cases where a type repeats. + check2!($a, $b); + check2!($b, $c); + check2!($a, $c); + + // Check the remaining cases, i.e., permutations of ($a, $b, $c). + check!($a, $b, $c); + check!($a, $c, $b); + check!($b, $a, $c); + check!($b, $c, $a); + check!($c, $a, $b); + check!($c, $b, $a); + } +} + +use std::mem::size_of; + +fn foo() {} +fn bar() {} + +pub fn main() { + check3!(foo, bar, foo as fn()); + check3!(size_of::, size_of::, size_of:: as fn() -> usize); + + let s = String::from("bar"); + check2!("foo", &s); + + let a = [1, 2, 3]; + let v = vec![1, 2, 3]; + check2!(&a[..], &v); + + // Make sure in-array coercion still works. + let _ = [("a", Default::default()), (Default::default(), "b"), (&s, &s)]; +} diff --git a/tests/ui/coercion/coerce-unsize-subtype.rs b/tests/ui/coercion/coerce-unsize-subtype.rs new file mode 100644 index 000000000..45b53300c --- /dev/null +++ b/tests/ui/coercion/coerce-unsize-subtype.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::rc::Rc; + +fn lub_short<'a, T>(_: &[&'a T], _: &[&'a T]) {} + +// The two arguments are a subtype of their LUB, after coercion. +fn long_and_short<'a, T>(xs: &[&'static T; 1], ys: &[&'a T; 1]) { + lub_short(xs, ys); +} + +// The argument coerces to a subtype of the return type. +fn long_to_short<'a, 'b, T>(xs: &'b [&'static T; 1]) -> &'b [&'a T] { + xs +} + +// Rc is covariant over T just like &T. +fn long_to_short_rc<'a, T>(xs: Rc<[&'static T; 1]>) -> Rc<[&'a T]> { + xs +} + +// LUB-coercion (if-else/match/array) coerces `xs: &'b [&'static T: N]` +// to a subtype of the LUB of `xs` and `ys` (i.e., `&'b [&'a T]`), +// regardless of the order they appear (in if-else/match/array). +fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) { + let _order1 = [xs, ys]; + let _order2 = [ys, xs]; +} + +// LUB-coercion should also have the exact same effect when `&'b [&'a T; N]` +// needs to be coerced, i.e., the resulting type is not &'b [&'static T], but +// rather the `&'b [&'a T]` LUB. +fn long_and_short_lub2<'a, 'b, T>(xs: &'b [&'static T], ys: &'b [&'a T; 1]) { + let _order1 = [xs, ys]; + let _order2 = [ys, xs]; +} + +fn main() {} diff --git a/tests/ui/coercion/coercion-missing-tail-expected-type.fixed b/tests/ui/coercion/coercion-missing-tail-expected-type.fixed new file mode 100644 index 000000000..713e04774 --- /dev/null +++ b/tests/ui/coercion/coercion-missing-tail-expected-type.fixed @@ -0,0 +1,16 @@ +// #41425 -- error message "mismatched types" has wrong types +// run-rustfix + +fn plus_one(x: i32) -> i32 { //~ ERROR mismatched types + x + 1 +} + +fn foo() -> Result { //~ ERROR mismatched types + Ok(1) +} + +fn main() { + let x = plus_one(5); + let _ = foo(); + println!("X = {}", x); +} diff --git a/tests/ui/coercion/coercion-missing-tail-expected-type.rs b/tests/ui/coercion/coercion-missing-tail-expected-type.rs new file mode 100644 index 000000000..e14d79d8a --- /dev/null +++ b/tests/ui/coercion/coercion-missing-tail-expected-type.rs @@ -0,0 +1,16 @@ +// #41425 -- error message "mismatched types" has wrong types +// run-rustfix + +fn plus_one(x: i32) -> i32 { //~ ERROR mismatched types + x + 1; +} + +fn foo() -> Result { //~ ERROR mismatched types + Ok(1); +} + +fn main() { + let x = plus_one(5); + let _ = foo(); + println!("X = {}", x); +} diff --git a/tests/ui/coercion/coercion-missing-tail-expected-type.stderr b/tests/ui/coercion/coercion-missing-tail-expected-type.stderr new file mode 100644 index 000000000..4c04bb113 --- /dev/null +++ b/tests/ui/coercion/coercion-missing-tail-expected-type.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:4:24 + | +LL | fn plus_one(x: i32) -> i32 { + | -------- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | x + 1; + | - help: remove this semicolon to return this value + +error[E0308]: mismatched types + --> $DIR/coercion-missing-tail-expected-type.rs:8:13 + | +LL | fn foo() -> Result { + | --- ^^^^^^^^^^^^^^^ expected enum `Result`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | Ok(1); + | - help: remove this semicolon to return this value + | + = note: expected enum `Result` + found unit type `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/coercion-slice.rs b/tests/ui/coercion/coercion-slice.rs new file mode 100644 index 000000000..b756c8f82 --- /dev/null +++ b/tests/ui/coercion/coercion-slice.rs @@ -0,0 +1,7 @@ +// Tests that we forbid coercion from `[T; n]` to `&[T]` + +fn main() { + let _: &[i32] = [0]; + //~^ ERROR mismatched types + //~| expected `&[i32]`, found array `[{integer}; 1]` +} diff --git a/tests/ui/coercion/coercion-slice.stderr b/tests/ui/coercion/coercion-slice.stderr new file mode 100644 index 000000000..42dc954ff --- /dev/null +++ b/tests/ui/coercion/coercion-slice.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/coercion-slice.rs:4:21 + | +LL | let _: &[i32] = [0]; + | ------ ^^^ + | | | + | | expected `&[i32]`, found array `[{integer}; 1]` + | | help: consider borrowing here: `&[0]` + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/issue-101066.rs b/tests/ui/coercion/issue-101066.rs new file mode 100644 index 000000000..b658ed1e9 --- /dev/null +++ b/tests/ui/coercion/issue-101066.rs @@ -0,0 +1,16 @@ +// check-pass + +use std::convert::TryFrom; + +pub trait FieldElement { + type Integer: TryFrom; + + fn valid_integer_try_from(i: N) -> Result + where + Self::Integer: TryFrom, + { + Self::Integer::try_from(i).map_err(|_| ()) + } +} + +fn main() {} diff --git a/tests/ui/coercion/issue-14589.rs b/tests/ui/coercion/issue-14589.rs new file mode 100644 index 000000000..d35ee5c73 --- /dev/null +++ b/tests/ui/coercion/issue-14589.rs @@ -0,0 +1,24 @@ +// run-pass +// All 3 expressions should work in that the argument gets +// coerced to a trait object + +// pretty-expanded FIXME #23616 + +fn main() { + send::>(Box::new(Output(0))); + Test::>::foo(Box::new(Output(0))); + Test::>::new().send(Box::new(Output(0))); +} + +fn send(_: T) {} + +struct Test { marker: std::marker::PhantomData } +impl Test { + fn new() -> Test { Test { marker: ::std::marker::PhantomData } } + fn foo(_: T) {} + fn send(&self, _: T) {} +} + +trait Foo { fn dummy(&self) { }} +struct Output(#[allow(unused_tuple_struct_fields)] isize); +impl Foo for Output {} diff --git a/tests/ui/coercion/issue-36007.rs b/tests/ui/coercion/issue-36007.rs new file mode 100644 index 000000000..78812df87 --- /dev/null +++ b/tests/ui/coercion/issue-36007.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(coerce_unsized, unsize)] + +use std::marker::Unsize; +use std::ops::CoerceUnsized; + +struct Foo(Box); + +impl CoerceUnsized> for Foo where T: Unsize {} + +struct Bar; + +trait Baz {} + +impl Baz for Bar {} + +fn main() { + let foo = Foo(Box::new(Bar)); + let foobar: Foo = foo; +} diff --git a/tests/ui/coercion/issue-37655.rs b/tests/ui/coercion/issue-37655.rs new file mode 100644 index 000000000..416854d66 --- /dev/null +++ b/tests/ui/coercion/issue-37655.rs @@ -0,0 +1,37 @@ +// check-pass +// Regression test for #37655. The problem was a false edge created by +// coercion that wound up requiring that `'a` (in `split()`) outlive +// `'b`, which shouldn't be necessary. + +#![allow(warnings)] + +trait SliceExt { + type Item; + + fn get_me(&self, index: I) -> &I::Output + where I: SliceIndex; +} + +impl SliceExt for [T] { + type Item = T; + + fn get_me(&self, index: I) -> &I::Output + where I: SliceIndex + { + panic!() + } +} + +pub trait SliceIndex { + type Output: ?Sized; +} + +impl SliceIndex for usize { + type Output = T; +} + +fn foo<'a, 'b>(split: &'b [&'a [u8]]) -> &'a [u8] { + split.get_me(0) +} + +fn main() { } diff --git a/tests/ui/coercion/issue-39823.rs b/tests/ui/coercion/issue-39823.rs new file mode 100644 index 000000000..148cf527e --- /dev/null +++ b/tests/ui/coercion/issue-39823.rs @@ -0,0 +1,25 @@ +// run-pass +// aux-build:issue-39823.rs + +extern crate issue_39823; +use issue_39823::{RemoteC, RemoteG}; + +#[derive(Debug, PartialEq)] +struct LocalC(u32); + +#[derive(Debug, PartialEq)] +struct LocalG(T); + +fn main() { + let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC; + assert_eq!(virtual_localc(1), LocalC(1)); + + let virtual_localg : &dyn Fn(_) -> LocalG = &LocalG; + assert_eq!(virtual_localg(1), LocalG(1)); + + let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC; + assert_eq!(virtual_remotec(1), RemoteC(1)); + + let virtual_remoteg : &dyn Fn(_) -> RemoteG = &RemoteG; + assert_eq!(virtual_remoteg(1), RemoteG(1)); +} diff --git a/tests/ui/coercion/issue-53475.rs b/tests/ui/coercion/issue-53475.rs new file mode 100644 index 000000000..3770c024f --- /dev/null +++ b/tests/ui/coercion/issue-53475.rs @@ -0,0 +1,13 @@ +#![feature(coerce_unsized)] + +use std::any::Any; +use std::ops::CoerceUnsized; + +struct Foo { + data: Box, +} + +impl CoerceUnsized> for Foo {} +//~^ ERROR the parameter type `T` may not live long enough + +fn main() {} diff --git a/tests/ui/coercion/issue-53475.stderr b/tests/ui/coercion/issue-53475.stderr new file mode 100644 index 000000000..522c50dca --- /dev/null +++ b/tests/ui/coercion/issue-53475.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-53475.rs:10:1 + | +LL | impl CoerceUnsized> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | impl CoerceUnsized> for Foo {} + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/coercion/issue-73886.rs b/tests/ui/coercion/issue-73886.rs new file mode 100644 index 000000000..9c0c87a5c --- /dev/null +++ b/tests/ui/coercion/issue-73886.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = &&[0] as &[_]; + //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]` + let _ = 7u32 as Option<_>; + //~^ ERROR non-primitive cast: `u32` as `Option<_>` +} diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr new file mode 100644 index 000000000..a6f8ba65a --- /dev/null +++ b/tests/ui/coercion/issue-73886.stderr @@ -0,0 +1,17 @@ +error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]` + --> $DIR/issue-73886.rs:2:13 + | +LL | let _ = &&[0] as &[_]; + | ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `u32` as `Option<_>` + --> $DIR/issue-73886.rs:4:13 + | +LL | let _ = 7u32 as Option<_>; + | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)` + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/coercion/issue-88097.rs b/tests/ui/coercion/issue-88097.rs new file mode 100644 index 000000000..e543e1bae --- /dev/null +++ b/tests/ui/coercion/issue-88097.rs @@ -0,0 +1,31 @@ +// In #88097, the compiler attempted to coerce a closure type to itself via +// a function pointer, which caused an unnecessary error. Check that this +// behavior has been fixed. + +// check-pass + +fn peculiar() -> impl Fn(u8) -> u8 { + return |x| x + 1 +} + +fn peculiar2() -> impl Fn(u8) -> u8 { + return |x| x + 1; +} + +fn peculiar3() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + return f +} + +fn peculiar4() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + f +} + +fn peculiar5() -> impl Fn(u8) -> u8 { + let f = |x| x + 1; + let g = |x| x + 2; + return if true { f } else { g } +} + +fn main() {} diff --git a/tests/ui/coercion/retslot-cast.rs b/tests/ui/coercion/retslot-cast.rs new file mode 100644 index 000000000..ae500cb15 --- /dev/null +++ b/tests/ui/coercion/retslot-cast.rs @@ -0,0 +1,22 @@ +#![allow(warnings)] + +pub fn fail(x: Option<&(Iterator+Send)>) + -> Option<&Iterator> { + // This call used to trigger an LLVM assertion because the return + // slot had type "Option<&Iterator>"* instead of + // "Option<&(Iterator+Send)>"* -- but this now yields a + // compilation error and I'm not sure how to create a comparable + // test. To ensure that this PARTICULAR failure doesn't occur + // again, though, I've left this test here, so if this ever starts + // to compile again, we can adjust the test appropriately (clearly + // it should never ICE...). -nmatsakis + inner(x) //~ ERROR mismatched types +} + +pub fn inner(x: Option<&(Iterator+Send)>) + -> Option<&(Iterator+Send)> { + x +} + + +fn main() {} diff --git a/tests/ui/coercion/retslot-cast.stderr b/tests/ui/coercion/retslot-cast.stderr new file mode 100644 index 000000000..798ce1199 --- /dev/null +++ b/tests/ui/coercion/retslot-cast.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/retslot-cast.rs:13:5 + | +LL | -> Option<&Iterator> { + | -------------------------- expected `Option<&dyn Iterator>` because of return type +... +LL | inner(x) + | ^^^^^^^^ expected trait `Iterator`, found trait `Iterator + Send` + | + = note: expected enum `Option<&dyn Iterator>` + found enum `Option<&dyn Iterator + Send>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/coercion/unsafe-coercion.rs b/tests/ui/coercion/unsafe-coercion.rs new file mode 100644 index 000000000..2478deeab --- /dev/null +++ b/tests/ui/coercion/unsafe-coercion.rs @@ -0,0 +1,17 @@ +// run-pass +// Check that safe fns are not a subtype of unsafe fns. + + +fn foo(x: i32) -> i32 { + x * 22 +} + +fn bar(x: fn(i32) -> i32) -> unsafe fn(i32) -> i32 { + x // OK, coercion! +} + +fn main() { + let f = bar(foo); + let x = unsafe { f(2) }; + assert_eq!(x, 44); +} diff --git a/tests/ui/coherence/auxiliary/coherence_copy_like_lib.rs b/tests/ui/coherence/auxiliary/coherence_copy_like_lib.rs new file mode 100644 index 000000000..b5b4802c1 --- /dev/null +++ b/tests/ui/coherence/auxiliary/coherence_copy_like_lib.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] +#![feature(fundamental)] + +pub trait MyCopy { } +impl MyCopy for i32 { } + +pub struct MyStruct(T); + +#[fundamental] +pub struct MyFundamentalStruct(T); diff --git a/tests/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs b/tests/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs new file mode 100644 index 000000000..21aaea479 --- /dev/null +++ b/tests/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] +#![feature(fundamental)] + +pub trait Misc {} + +#[fundamental] +pub trait Fundamental {} diff --git a/tests/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs b/tests/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs new file mode 100644 index 000000000..08d22fbed --- /dev/null +++ b/tests/ui/coherence/auxiliary/coherence_inherent_cc_lib.rs @@ -0,0 +1,11 @@ +// See coherence_inherent_cc.rs + +pub trait TheTrait { + fn the_fn(&self); +} + +pub struct TheStruct; + +impl TheTrait for TheStruct { + fn the_fn(&self) {} +} diff --git a/tests/ui/coherence/auxiliary/coherence_lib.rs b/tests/ui/coherence/auxiliary/coherence_lib.rs new file mode 100644 index 000000000..c22819831 --- /dev/null +++ b/tests/ui/coherence/auxiliary/coherence_lib.rs @@ -0,0 +1,15 @@ +#![crate_type="lib"] + +pub trait Remote { + fn foo(&self) { } +} + +pub trait Remote1 { + fn foo(&self, _t: T) { } +} + +pub trait Remote2 { + fn foo(&self, _t: T, _u: U) { } +} + +pub struct Pair(T,U); diff --git a/tests/ui/coherence/auxiliary/coherence_orphan_lib.rs b/tests/ui/coherence/auxiliary/coherence_orphan_lib.rs new file mode 100644 index 000000000..2664ef550 --- /dev/null +++ b/tests/ui/coherence/auxiliary/coherence_orphan_lib.rs @@ -0,0 +1,3 @@ +pub trait TheTrait { + fn the_fn(&self); +} diff --git a/tests/ui/coherence/auxiliary/error_lib.rs b/tests/ui/coherence/auxiliary/error_lib.rs new file mode 100644 index 000000000..19ff9ae62 --- /dev/null +++ b/tests/ui/coherence/auxiliary/error_lib.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +pub trait Error {} +impl !Error for &str {} diff --git a/tests/ui/coherence/auxiliary/go_trait.rs b/tests/ui/coherence/auxiliary/go_trait.rs new file mode 100644 index 000000000..aa0ec2289 --- /dev/null +++ b/tests/ui/coherence/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once(this: G, arg: isize) { + this.go_once(arg) +} + +impl GoMut for G + where G : Go +{ + default fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +impl GoOnce for G + where G : GoMut +{ + default fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/coherence/auxiliary/option_future.rs b/tests/ui/coherence/auxiliary/option_future.rs new file mode 100644 index 000000000..067de1cd8 --- /dev/null +++ b/tests/ui/coherence/auxiliary/option_future.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +pub trait Future {} + +impl !Future for Option where E: Sized {} diff --git a/tests/ui/coherence/auxiliary/re_rebalance_coherence_lib-rpass.rs b/tests/ui/coherence/auxiliary/re_rebalance_coherence_lib-rpass.rs new file mode 100644 index 000000000..9a191bad8 --- /dev/null +++ b/tests/ui/coherence/auxiliary/re_rebalance_coherence_lib-rpass.rs @@ -0,0 +1,31 @@ +pub trait Backend {} +pub trait SupportsDefaultKeyword {} + +impl SupportsDefaultKeyword for Postgres {} + +pub struct Postgres; + +impl Backend for Postgres {} + +pub struct AstPass(::std::marker::PhantomData); + +pub trait QueryFragment {} + + +#[derive(Debug, Clone, Copy)] +pub struct BatchInsert<'a, T: 'a, Tab> { + _marker: ::std::marker::PhantomData<(&'a T, Tab)>, +} + +impl<'a, T:'a, Tab, DB> QueryFragment for BatchInsert<'a, T, Tab> +where DB: SupportsDefaultKeyword + Backend, +{} + +pub trait LibToOwned { + type Owned; +} + +pub struct LibCow::Owned> { + pub t: T, + pub o: Owned, +} diff --git a/tests/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs b/tests/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs new file mode 100644 index 000000000..41b9d64d5 --- /dev/null +++ b/tests/ui/coherence/auxiliary/re_rebalance_coherence_lib.rs @@ -0,0 +1,22 @@ +pub trait Backend {} +pub trait SupportsDefaultKeyword {} + +impl SupportsDefaultKeyword for Postgres {} + +pub struct Postgres; + +impl Backend for Postgres {} + +pub struct AstPass(::std::marker::PhantomData); + +pub trait QueryFragment {} + + +#[derive(Debug, Clone, Copy)] +pub struct BatchInsert<'a, T: 'a, Tab> { + _marker: ::std::marker::PhantomData<(&'a T, Tab)>, +} + +impl<'a, T:'a, Tab, DB> QueryFragment for BatchInsert<'a, T, Tab> +where DB: SupportsDefaultKeyword + Backend, +{} diff --git a/tests/ui/coherence/auxiliary/trait-with-const-param.rs b/tests/ui/coherence/auxiliary/trait-with-const-param.rs new file mode 100644 index 000000000..a44eb14f8 --- /dev/null +++ b/tests/ui/coherence/auxiliary/trait-with-const-param.rs @@ -0,0 +1 @@ +pub trait Trait {} diff --git a/tests/ui/coherence/auxiliary/trait_impl_conflict.rs b/tests/ui/coherence/auxiliary/trait_impl_conflict.rs new file mode 100644 index 000000000..5e5f017ed --- /dev/null +++ b/tests/ui/coherence/auxiliary/trait_impl_conflict.rs @@ -0,0 +1,6 @@ +pub trait Foo { + fn foo() {} +} + +impl Foo for isize { +} diff --git a/tests/ui/coherence/coherence-all-remote.rs b/tests/ui/coherence/coherence-all-remote.rs new file mode 100644 index 000000000..5c3bfee82 --- /dev/null +++ b/tests/ui/coherence/coherence-all-remote.rs @@ -0,0 +1,9 @@ +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::Remote1; + +impl Remote1 for isize { } +//~^ ERROR E0210 + +fn main() { } diff --git a/tests/ui/coherence/coherence-all-remote.stderr b/tests/ui/coherence/coherence-all-remote.stderr new file mode 100644 index 000000000..7eca41753 --- /dev/null +++ b/tests/ui/coherence/coherence-all-remote.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/coherence-all-remote.rs:6:6 + | +LL | impl Remote1 for isize { } + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-bigint-int.rs b/tests/ui/coherence/coherence-bigint-int.rs new file mode 100644 index 000000000..02945e9da --- /dev/null +++ b/tests/ui/coherence/coherence-bigint-int.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote1; + +pub struct BigInt; + +impl Remote1 for isize { } + +fn main() { } diff --git a/tests/ui/coherence/coherence-bigint-param.rs b/tests/ui/coherence/coherence-bigint-param.rs new file mode 100644 index 000000000..c6543aaf6 --- /dev/null +++ b/tests/ui/coherence/coherence-bigint-param.rs @@ -0,0 +1,11 @@ +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::Remote1; + +pub struct BigInt; + +impl Remote1 for T { } +//~^ ERROR E0210 + +fn main() { } diff --git a/tests/ui/coherence/coherence-bigint-param.stderr b/tests/ui/coherence/coherence-bigint-param.stderr new file mode 100644 index 000000000..e8d74c917 --- /dev/null +++ b/tests/ui/coherence/coherence-bigint-param.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`) + --> $DIR/coherence-bigint-param.rs:8:6 + | +LL | impl Remote1 for T { } + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-bigint-vecint.rs b/tests/ui/coherence/coherence-bigint-vecint.rs new file mode 100644 index 000000000..a5dba90be --- /dev/null +++ b/tests/ui/coherence/coherence-bigint-vecint.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote1; + +pub struct BigInt; + +impl Remote1 for Vec { } + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs new file mode 100644 index 000000000..93a4bc5fe --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.rs @@ -0,0 +1,30 @@ +use std::fmt::Debug; +use std::default::Default; + +// Test that two blanket impls conflict (at least without negative +// bounds). After all, some other crate could implement Even or Odd +// for the same type (though this crate doesn't). + +trait MyTrait { + fn get(&self) -> usize; +} + +trait Even { } + +trait Odd { } + +impl Even for isize { } + +impl Odd for usize { } + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +impl MyTrait for T { +//~^ ERROR E0119 + + fn get(&self) -> usize { 0 } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr new file mode 100644 index 000000000..9156972a1 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-implemented.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` + --> $DIR/coherence-blanket-conflicts-with-blanket-implemented.rs:24:1 + | +LL | impl MyTrait for T { + | -------------------------- first implementation here +... +LL | impl MyTrait for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs new file mode 100644 index 000000000..950a08ff2 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.rs @@ -0,0 +1,25 @@ +use std::fmt::Debug; +use std::default::Default; + +// Test that two blanket impls conflict (at least without negative +// bounds). After all, some other crate could implement Even or Odd +// for the same type (though this crate doesn't implement them at all). + +trait MyTrait { + fn get(&self) -> usize; +} + +trait Even {} + +trait Odd {} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +impl MyTrait for T { +//~^ ERROR E0119 + fn get(&self) -> usize { 0 } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr new file mode 100644 index 000000000..8400968e1 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-blanket-unimplemented.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` + --> $DIR/coherence-blanket-conflicts-with-blanket-unimplemented.rs:20:1 + | +LL | impl MyTrait for T { + | -------------------------- first implementation here +... +LL | impl MyTrait for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs new file mode 100644 index 000000000..bccbac2ff --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.rs @@ -0,0 +1,20 @@ +// aux-build:go_trait.rs + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { +//~^ ERROR E0119 + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr new file mode 100644 index 000000000..4d7872598 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-cross-crate.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `GoMut` for type `MyThingy` + --> $DIR/coherence-blanket-conflicts-with-specific-cross-crate.rs:15:1 + | +LL | impl GoMut for MyThingy { + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `go_trait`: + - impl GoMut for G + where G: Go; + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs new file mode 100644 index 000000000..6a9db2173 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs @@ -0,0 +1,27 @@ +use std::fmt::Debug; +use std::default::Default; + +// Test that a blank impl for all T conflicts with an impl for some +// specific T, even when there are multiple type parameters involved. + +trait MyTrait { + fn get(&self) -> T; +} + +impl MyTrait for T { + fn get(&self) -> T { + panic!() + } +} + +#[derive(Clone)] +struct MyType { + dummy: usize +} + +impl MyTrait for MyType { +//~^ ERROR E0119 + fn get(&self) -> usize { (*self).clone() } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr new file mode 100644 index 000000000..c2a925213 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType` + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:22:1 + | +LL | impl MyTrait for T { + | ------------------------ first implementation here +... +LL | impl MyTrait for MyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs new file mode 100644 index 000000000..02f9217da --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.rs @@ -0,0 +1,29 @@ +// Test that a blank impl for all T:PartialEq conflicts with an impl for some +// specific T when T:PartialEq. + +trait OtherTrait { + fn noop(&self); +} + +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +struct MyType { + dummy: usize +} + +impl MyTrait for MyType { +//~^ ERROR E0119 + fn get(&self) -> usize { self.dummy } +} + +impl OtherTrait for MyType { + fn noop(&self) { } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr new file mode 100644 index 000000000..e1a5dffeb --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-trait.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType` + --> $DIR/coherence-blanket-conflicts-with-specific-trait.rs:20:1 + | +LL | impl MyTrait for T { + | -------------------------------- first implementation here +... +LL | impl MyTrait for MyType { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific.rs new file mode 100644 index 000000000..5a562ff6a --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific.rs @@ -0,0 +1,24 @@ +use std::fmt::Debug; +use std::default::Default; + +// Test that a blank impl for all T conflicts with an impl for some +// specific T. + +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +struct MyType { + dummy: usize +} + +impl MyTrait for MyType { +//~^ ERROR E0119 + fn get(&self) -> usize { self.dummy } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr new file mode 100644 index 000000000..ba60a2ea9 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyType` + --> $DIR/coherence-blanket-conflicts-with-specific.rs:19:1 + | +LL | impl MyTrait for T { + | --------------------- first implementation here +... +LL | impl MyTrait for MyType { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-blanket.rs b/tests/ui/coherence/coherence-blanket.rs new file mode 100644 index 000000000..55fa89d75 --- /dev/null +++ b/tests/ui/coherence/coherence-blanket.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_imports)] +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote1; + +pub trait Local { + fn foo(&self) { } +} + +impl Local for T { } + +fn main() { } diff --git a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs new file mode 100644 index 000000000..24b878927 --- /dev/null +++ b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.rs @@ -0,0 +1,17 @@ +#![feature(negative_impls)] +#![feature(marker_trait_attr)] + +#[marker] +trait MyTrait {} + +struct TestType(::std::marker::PhantomData); + +unsafe impl Send for TestType {} + +impl !Send for TestType {} //~ ERROR found both positive and negative implementation + +unsafe impl Send for TestType {} //~ ERROR conflicting implementations + +impl !Send for TestType {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr new file mode 100644 index 000000000..2463f38a9 --- /dev/null +++ b/tests/ui/coherence/coherence-conflicting-negative-trait-impl.stderr @@ -0,0 +1,22 @@ +error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`: + --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:1 + | +LL | unsafe impl Send for TestType {} + | ------------------------------------------------------ positive implementation here +LL | +LL | impl !Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>` + --> $DIR/coherence-conflicting-negative-trait-impl.rs:13:1 + | +LL | unsafe impl Send for TestType {} + | ------------------------------------------------------ first implementation here +... +LL | unsafe impl Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0751. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-covered-type-parameter.rs b/tests/ui/coherence/coherence-covered-type-parameter.rs new file mode 100644 index 000000000..bb95c59d1 --- /dev/null +++ b/tests/ui/coherence/coherence-covered-type-parameter.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote; + +struct Foo(T); + +impl Remote for Foo { } + +fn main() { } diff --git a/tests/ui/coherence/coherence-cow.re_a.stderr b/tests/ui/coherence/coherence-cow.re_a.stderr new file mode 100644 index 000000000..fe4b5b410 --- /dev/null +++ b/tests/ui/coherence/coherence-cow.re_a.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-cow.rs:18:1 + | +LL | impl Remote for Pair> { } + | ^^^^^^^^^^^^^^^^^^^---------------- + | | | + | | `Pair` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-cow.re_b.stderr b/tests/ui/coherence/coherence-cow.re_b.stderr new file mode 100644 index 000000000..da4ede325 --- /dev/null +++ b/tests/ui/coherence/coherence-cow.re_b.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-cow.rs:22:1 + | +LL | impl Remote for Pair,T> { } + | ^^^^^^^^^^^^^^^^^^^---------------- + | | | + | | `Pair` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-cow.re_c.stderr b/tests/ui/coherence/coherence-cow.re_c.stderr new file mode 100644 index 000000000..d1a20c0ca --- /dev/null +++ b/tests/ui/coherence/coherence-cow.re_c.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-cow.rs:26:1 + | +LL | impl Remote for Pair,U> { } + | ^^^^^^^^^^^^^^^^^^^^^---------------- + | | | + | | `Pair` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-cow.rs b/tests/ui/coherence/coherence-cow.rs new file mode 100644 index 000000000..86a8d0963 --- /dev/null +++ b/tests/ui/coherence/coherence-cow.rs @@ -0,0 +1,29 @@ +// revisions: re_a re_b re_c + +#![cfg_attr(any(), re_a, re_b, re_c)] + +// aux-build:coherence_lib.rs + +// Test that the `Pair` type reports an error if it contains type +// parameters, even when they are covered by local types. This test +// was originally intended to test the opposite, but the rules changed +// with RFC 1023 and this became illegal. + +extern crate coherence_lib as lib; +use lib::{Remote,Pair}; + +pub struct Cover(T); + +#[cfg(any(re_a))] +impl Remote for Pair> { } +//[re_a]~^ ERROR E0117 + +#[cfg(any(re_b))] +impl Remote for Pair,T> { } +//[re_b]~^ ERROR E0117 + +#[cfg(any(re_c))] +impl Remote for Pair,U> { } +//[re_c]~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-cross-crate-conflict.rs b/tests/ui/coherence/coherence-cross-crate-conflict.rs new file mode 100644 index 000000000..588630957 --- /dev/null +++ b/tests/ui/coherence/coherence-cross-crate-conflict.rs @@ -0,0 +1,13 @@ +// The error here is strictly due to orphan rules; the impl here +// generalizes the one upstream + +// aux-build:trait_impl_conflict.rs + +extern crate trait_impl_conflict; +use trait_impl_conflict::Foo; + +impl Foo for A { //~ ERROR E0210 +} + +fn main() { +} diff --git a/tests/ui/coherence/coherence-cross-crate-conflict.stderr b/tests/ui/coherence/coherence-cross-crate-conflict.stderr new file mode 100644 index 000000000..3d253d56a --- /dev/null +++ b/tests/ui/coherence/coherence-cross-crate-conflict.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/coherence-cross-crate-conflict.rs:9:6 + | +LL | impl Foo for A { + | ^ type parameter `A` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-default-trait-impl.rs b/tests/ui/coherence/coherence-default-trait-impl.rs new file mode 100644 index 000000000..d57fb4777 --- /dev/null +++ b/tests/ui/coherence/coherence-default-trait-impl.rs @@ -0,0 +1,16 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait MySafeTrait {} + +struct Foo; + +unsafe impl MySafeTrait for Foo {} +//~^ ERROR E0199 + +unsafe auto trait MyUnsafeTrait {} + +impl MyUnsafeTrait for Foo {} +//~^ ERROR E0200 + +fn main() {} diff --git a/tests/ui/coherence/coherence-default-trait-impl.stderr b/tests/ui/coherence/coherence-default-trait-impl.stderr new file mode 100644 index 000000000..7be5b92a7 --- /dev/null +++ b/tests/ui/coherence/coherence-default-trait-impl.stderr @@ -0,0 +1,28 @@ +error[E0199]: implementing the trait `MySafeTrait` is not unsafe + --> $DIR/coherence-default-trait-impl.rs:8:1 + | +LL | unsafe impl MySafeTrait for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl MySafeTrait for Foo {} +LL + impl MySafeTrait for Foo {} + | + +error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration + --> $DIR/coherence-default-trait-impl.rs:13:1 + | +LL | impl MyUnsafeTrait for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl MyUnsafeTrait for Foo {} + | ++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0199, E0200. +For more information about an error, try `rustc --explain E0199`. diff --git a/tests/ui/coherence/coherence-error-suppression.rs b/tests/ui/coherence/coherence-error-suppression.rs new file mode 100644 index 000000000..909214c1b --- /dev/null +++ b/tests/ui/coherence/coherence-error-suppression.rs @@ -0,0 +1,16 @@ +// check that error types in coherence do not cause error cascades. + +trait Foo {} + +impl Foo for i8 {} +impl Foo for i16 {} +impl Foo for i32 {} +impl Foo for i64 {} +impl Foo for DoesNotExist {} +//~^ ERROR E0412 +impl Foo for u8 {} +impl Foo for u16 {} +impl Foo for u32 {} +impl Foo for u64 {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-error-suppression.stderr b/tests/ui/coherence/coherence-error-suppression.stderr new file mode 100644 index 000000000..aadc80cb1 --- /dev/null +++ b/tests/ui/coherence/coherence-error-suppression.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `DoesNotExist` in this scope + --> $DIR/coherence-error-suppression.rs:9:14 + | +LL | impl Foo for DoesNotExist {} + | ^^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs new file mode 100644 index 000000000..99f805f7f --- /dev/null +++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs @@ -0,0 +1,26 @@ +// Test that impls for these two types are considered ovelapping: +// +// * `for<'r> fn(fn(&'r u32))` +// * `fn(fn(&'a u32)` where `'a` is free +// +// This is because, for `'a = 'static`, the two types overlap. +// Effectively for them to be equal to you get: +// +// * `for<'r> fn(fn(&'r u32)) <: fn(fn(&'static u32))` +// * true if `exists<'r> { 'r: 'static }` (obviously true) +// * `fn(fn(&'static u32)) <: for<'r> fn(fn(&'r u32))` +// * true if `forall<'r> { 'static: 'r }` (also true) + +trait Trait {} + +impl Trait for for<'r> fn(fn(&'r ())) {} +impl<'a> Trait for fn(fn(&'a ())) {} +//~^ ERROR conflicting implementations +// +// Note in particular that we do NOT get a future-compatibility warning +// here. This is because the new leak-check proposed in [MCP 295] does not +// "error" when these two types are equated. +// +// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295 + +fn main() {} diff --git a/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr new file mode 100644 index 000000000..7dabd97b9 --- /dev/null +++ b/tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` + --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 + | +LL | impl Trait for for<'r> fn(fn(&'r ())) {} + | ------------------------------------- first implementation here +LL | impl<'a> Trait for fn(fn(&'a ())) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-fn-implied-bounds.rs b/tests/ui/coherence/coherence-fn-implied-bounds.rs new file mode 100644 index 000000000..4539af9a3 --- /dev/null +++ b/tests/ui/coherence/coherence-fn-implied-bounds.rs @@ -0,0 +1,26 @@ +// Test that our leak-check is not smart enough to take implied bounds +// into account (yet). Here we have two types that look like they +// should not be equivalent, but because of the rules on implied +// bounds we ought to know that, in fact, `'a = 'b` must always hold, +// and hence they are. +// +// Rustc can't figure this out and hence it accepts the impls but +// gives a future-compatibility warning (because we'd like to make +// this an error someday). +// +// Note that while we would like to make this a hard error, we also +// give the same warning for `coherence-wasm-bindgen.rs`, which ought +// to be accepted. + +#![deny(coherence_leak_check)] + +trait Trait {} + +impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + +impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + //~^ ERROR conflicting implementations + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-fn-implied-bounds.stderr b/tests/ui/coherence/coherence-fn-implied-bounds.stderr new file mode 100644 index 000000000..201871204 --- /dev/null +++ b/tests/ui/coherence/coherence-fn-implied-bounds.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` + --> $DIR/coherence-fn-implied-bounds.rs:21:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {} + | ------------------------------------------------------------------ first implementation here +LL | +LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +note: the lint level is defined here + --> $DIR/coherence-fn-implied-bounds.rs:15:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/coherence/coherence-fn-inputs.rs b/tests/ui/coherence/coherence-fn-inputs.rs new file mode 100644 index 000000000..3afec5c54 --- /dev/null +++ b/tests/ui/coherence/coherence-fn-inputs.rs @@ -0,0 +1,25 @@ +// Test that we consider these two types completely equal: +// +// * `for<'a, 'b> fn(&'a u32, &'b u32)` +// * `for<'c> fn(&'c u32, &'c u32)` +// +// For a long time we considered these to be distinct types. But in fact they +// are equivalent, if you work through the implications of subtyping -- this is +// because: +// +// * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection) +// * `'a` and `'b` can both be equal to `'c` + +trait Trait {} +impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} +impl Trait for for<'c> fn(&'c u32, &'c u32) { + //~^ ERROR conflicting implementations + // + // Note in particular that we do NOT get a future-compatibility warning + // here. This is because the new leak-check proposed in [MCP 295] does not + // "error" when these two types are equated. + // + // [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295 +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-fn-inputs.stderr b/tests/ui/coherence/coherence-fn-inputs.stderr new file mode 100644 index 000000000..82bd8a35f --- /dev/null +++ b/tests/ui/coherence/coherence-fn-inputs.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` + --> $DIR/coherence-fn-inputs.rs:15:1 + | +LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} + | ----------------------------------------------- first implementation here +LL | impl Trait for for<'c> fn(&'c u32, &'c u32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-free-vs-bound-region.rs b/tests/ui/coherence/coherence-free-vs-bound-region.rs new file mode 100644 index 000000000..2f5c49d29 --- /dev/null +++ b/tests/ui/coherence/coherence-free-vs-bound-region.rs @@ -0,0 +1,21 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait TheTrait {} + +impl<'a> TheTrait for fn(&'a u8) {} + +impl TheTrait for fn(&u8) { + //~^ ERROR conflicting implementations of trait + //~| WARNING this was previously accepted by the compiler +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-free-vs-bound-region.stderr b/tests/ui/coherence/coherence-free-vs-bound-region.stderr new file mode 100644 index 000000000..e2d84b833 --- /dev/null +++ b/tests/ui/coherence/coherence-free-vs-bound-region.stderr @@ -0,0 +1,20 @@ +error: conflicting implementations of trait `TheTrait` for type `fn(&u8)` + --> $DIR/coherence-free-vs-bound-region.rs:16:1 + | +LL | impl<'a> TheTrait for fn(&'a u8) {} + | -------------------------------- first implementation here +LL | +LL | impl TheTrait for fn(&u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&u8)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +note: the lint level is defined here + --> $DIR/coherence-free-vs-bound-region.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.rs b/tests/ui/coherence/coherence-fundamental-trait-objects.rs new file mode 100644 index 000000000..dd127bf7f --- /dev/null +++ b/tests/ui/coherence/coherence-fundamental-trait-objects.rs @@ -0,0 +1,15 @@ +// Check that trait objects from #[fundamental] traits are not +// treated as #[fundamental] types - the 2 meanings of #[fundamental] +// are distinct. + +// aux-build:coherence_fundamental_trait_lib.rs + +extern crate coherence_fundamental_trait_lib; + +use coherence_fundamental_trait_lib::{Fundamental, Misc}; + +pub struct Local; +impl Misc for dyn Fundamental {} +//~^ ERROR E0117 + +fn main() {} diff --git a/tests/ui/coherence/coherence-fundamental-trait-objects.stderr b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr new file mode 100644 index 000000000..a35a95ef4 --- /dev/null +++ b/tests/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-fundamental-trait-objects.rs:12:1 + | +LL | impl Misc for dyn Fundamental {} + | ^^^^^^^^^^^^^^---------------------- + | | | + | | `dyn Fundamental` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impl-in-fn.rs b/tests/ui/coherence/coherence-impl-in-fn.rs new file mode 100644 index 000000000..b97197317 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-in-fn.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +pub fn main() { + #[derive(Copy, Clone)] + enum x { foo } + impl ::std::cmp::PartialEq for x { + fn eq(&self, other: &x) -> bool { + (*self) as isize == (*other) as isize + } + fn ne(&self, other: &x) -> bool { !(*self).eq(other) } + } +} diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs new file mode 100644 index 000000000..50d9a480a --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs @@ -0,0 +1,30 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +// Test for issue #56934 - that it is impossible to redundantly +// implement an auto-trait for a trait object type that contains it. + +// Negative impl variant. + +auto trait Marker1 {} +auto trait Marker2 {} + +trait Object: Marker1 {} + +// A supertrait marker is illegal... +impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371 +// ...and also a direct component. +impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371 + +// But implementing a marker if it is not present is OK. +impl !Marker2 for dyn Object {} // OK + +// A non-principal trait-object type is orphan even in its crate. +impl !Send for dyn Marker2 {} //~ ERROR E0117 + +// And impl'ing a remote marker for a local trait object is forbidden +// by one of these special orphan-like rules. +impl !Send for dyn Object {} //~ ERROR E0321 +impl !Send for dyn Object + Marker2 {} //~ ERROR E0321 + +fn main() { } diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr new file mode 100644 index 000000000..c364c707f --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr @@ -0,0 +1,39 @@ +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1 + | +LL | impl !Marker1 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1 + | +LL | impl !Marker2 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1 + | +LL | impl !Send for dyn Marker2 {} + | ^^^^^^^^^^^^^^^----------- + | | | + | | `dyn Marker2` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:27:1 + | +LL | impl !Send for dyn Object {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:28:1 + | +LL | impl !Send for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0117, E0321, E0371. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs new file mode 100644 index 000000000..faac6d983 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs @@ -0,0 +1,30 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +// Test for issue #56934 - that it is impossible to redundantly +// implement an auto-trait for a trait object type that contains it. + +// Positive impl variant. + +auto trait Marker1 {} +auto trait Marker2 {} + +trait Object: Marker1 {} + +// A supertrait marker is illegal... +impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371 +// ...and also a direct component. +impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371 + +// But implementing a marker if it is not present is OK. +impl Marker2 for dyn Object {} // OK + +// A non-principal trait-object type is orphan even in its crate. +unsafe impl Send for dyn Marker2 {} //~ ERROR E0117 + +// And impl'ing a remote marker for a local trait object is forbidden +// by one of these special orphan-like rules. +unsafe impl Send for dyn Object {} //~ ERROR E0321 +unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321 + +fn main() { } diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr new file mode 100644 index 000000000..b80429794 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr @@ -0,0 +1,39 @@ +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1 + | +LL | impl Marker1 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1` + +error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1 + | +LL | impl Marker2 for dyn Object + Marker2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2` + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1 + | +LL | unsafe impl Send for dyn Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^----------- + | | | + | | `dyn Marker2` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:27:1 + | +LL | unsafe impl Send for dyn Object {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `(dyn Object + Marker2 + 'static)` + --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:28:1 + | +LL | unsafe impl Send for dyn Object + Marker2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0117, E0321, E0371. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs b/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs new file mode 100644 index 000000000..20ff87549 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs @@ -0,0 +1,10 @@ +// Test that we give suitable error messages when the user attempts to +// impl a trait `Trait` for its own object type. + +// If the trait is not object-safe, we give a more tailored message +// because we're such schnuckels: +trait NotObjectSafe { fn eq(&self, other: Self); } +impl NotObjectSafe for dyn NotObjectSafe { } +//~^ ERROR E0038 + +fn main() { } diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr new file mode 100644 index 000000000..e9090c1b6 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `NotObjectSafe` cannot be made into an object + --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:24 + | +LL | impl NotObjectSafe for dyn NotObjectSafe { } + | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:6:43 + | +LL | trait NotObjectSafe { fn eq(&self, other: Self); } + | ------------- ^^^^ ...because method `eq` references the `Self` type in this parameter + | | + | this trait cannot be made into an object... + = help: consider moving `eq` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait.rs b/tests/ui/coherence/coherence-impl-trait-for-trait.rs new file mode 100644 index 000000000..195a37f15 --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-trait.rs @@ -0,0 +1,20 @@ +// Test that we give suitable error messages when the user attempts to +// impl a trait `Trait` for its own object type. + +trait Foo { fn dummy(&self) { } } +trait Bar: Foo { } +trait Baz: Bar { } + +// Supertraits of Baz are not legal: +impl Foo for dyn Baz { } +//~^ ERROR E0371 +impl Bar for dyn Baz { } +//~^ ERROR E0371 +impl Baz for dyn Baz { } +//~^ ERROR E0371 + +// But other random traits are: +trait Other { } +impl Other for dyn Baz { } // OK, Other not a supertrait of Baz + +fn main() { } diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait.stderr new file mode 100644 index 000000000..cf0b38c5b --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-trait.stderr @@ -0,0 +1,21 @@ +error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Foo` + --> $DIR/coherence-impl-trait-for-trait.rs:9:1 + | +LL | impl Foo for dyn Baz { } + | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Foo` + +error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Bar` + --> $DIR/coherence-impl-trait-for-trait.rs:11:1 + | +LL | impl Bar for dyn Baz { } + | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Bar` + +error[E0371]: the object type `(dyn Baz + 'static)` automatically implements the trait `Baz` + --> $DIR/coherence-impl-trait-for-trait.rs:13:1 + | +LL | impl Baz for dyn Baz { } + | ^^^^^^^^^^^^^^^^^^^^ `(dyn Baz + 'static)` automatically implements trait `Baz` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0371`. diff --git a/tests/ui/coherence/coherence-impls-copy.rs b/tests/ui/coherence/coherence-impls-copy.rs new file mode 100644 index 000000000..4204fecc3 --- /dev/null +++ b/tests/ui/coherence/coherence-impls-copy.rs @@ -0,0 +1,36 @@ +#![feature(negative_impls)] + +use std::marker::Copy; + +impl Copy for i32 {} +//~^ ERROR E0117 +enum TestE { + A +} + +struct MyType; + +struct NotSync; +impl !Sync for NotSync {} + +impl Copy for TestE {} +impl Clone for TestE { fn clone(&self) -> Self { *self } } + +impl Copy for MyType {} + +impl Copy for &'static mut MyType {} +//~^ ERROR E0206 +impl Clone for MyType { fn clone(&self) -> Self { *self } } + +impl Copy for (MyType, MyType) {} +//~^ ERROR E0206 +//~| ERROR E0117 +impl Copy for &'static NotSync {} +//~^ ERROR E0119 +impl Copy for [MyType] {} +//~^ ERROR E0206 +//~| ERROR E0117 +impl Copy for &'static [NotSync] {} +//~^ ERROR E0117 +fn main() { +} diff --git a/tests/ui/coherence/coherence-impls-copy.stderr b/tests/ui/coherence/coherence-impls-copy.stderr new file mode 100644 index 000000000..d40ffc48a --- /dev/null +++ b/tests/ui/coherence/coherence-impls-copy.stderr @@ -0,0 +1,76 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/coherence-impls-copy.rs:5:1 + | +LL | impl Copy for i32 {} + | ^^^^^^^^^^^^^^--- + | | | + | | `i32` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0119]: conflicting implementations of trait `Copy` for type `&NotSync` + --> $DIR/coherence-impls-copy.rs:28:1 + | +LL | impl Copy for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl Copy for &T + where T: ?Sized; + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-copy.rs:33:1 + | +LL | impl Copy for &'static [NotSync] {} + | ^^^^^^^^^^^^^^------------------ + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-copy.rs:25:1 + | +LL | impl Copy for (MyType, MyType) {} + | ^^^^^^^^^^^^^^---------------- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-copy.rs:30:1 + | +LL | impl Copy for [MyType] {} + | ^^^^^^^^^^^^^^-------- + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/coherence-impls-copy.rs:21:15 + | +LL | impl Copy for &'static mut MyType {} + | ^^^^^^^^^^^^^^^^^^^ type is not a structure or enumeration + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/coherence-impls-copy.rs:25:15 + | +LL | impl Copy for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration + +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/coherence-impls-copy.rs:30:15 + | +LL | impl Copy for [MyType] {} + | ^^^^^^^^ type is not a structure or enumeration + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0117, E0119, E0206. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impls-send.rs b/tests/ui/coherence/coherence-impls-send.rs new file mode 100644 index 000000000..b7b57c602 --- /dev/null +++ b/tests/ui/coherence/coherence-impls-send.rs @@ -0,0 +1,28 @@ +#![feature(negative_impls)] + +use std::marker::Copy; + +enum TestE { + A, +} + +struct MyType; + +struct NotSync; +impl !Sync for NotSync {} + +unsafe impl Send for TestE {} +unsafe impl Send for MyType {} +unsafe impl Send for (MyType, MyType) {} +//~^ ERROR E0117 + +unsafe impl Send for &'static NotSync {} +//~^ ERROR E0321 + +unsafe impl Send for [MyType] {} +//~^ ERROR E0117 + +unsafe impl Send for &'static [NotSync] {} +//~^ ERROR only traits defined in the current crate + +fn main() {} diff --git a/tests/ui/coherence/coherence-impls-send.stderr b/tests/ui/coherence/coherence-impls-send.stderr new file mode 100644 index 000000000..e1071846e --- /dev/null +++ b/tests/ui/coherence/coherence-impls-send.stderr @@ -0,0 +1,43 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-send.rs:25:1 + | +LL | unsafe impl Send for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^^^^^^^------------------ + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-send.rs:16:1 + | +LL | unsafe impl Send for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^^^^^^^---------------- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type, not `&'static NotSync` + --> $DIR/coherence-impls-send.rs:19:1 + | +LL | unsafe impl Send for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-send.rs:22:1 + | +LL | unsafe impl Send for [MyType] {} + | ^^^^^^^^^^^^^^^^^^^^^-------- + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0117, E0321. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-impls-sized.rs b/tests/ui/coherence/coherence-impls-sized.rs new file mode 100644 index 000000000..231b96ad4 --- /dev/null +++ b/tests/ui/coherence/coherence-impls-sized.rs @@ -0,0 +1,36 @@ +#![feature(negative_impls)] + +use std::marker::Copy; + +enum TestE { + A +} + +struct MyType; + +struct NotSync; +impl !Sync for NotSync {} + +impl Sized for TestE {} +//~^ ERROR E0322 + +impl Sized for MyType {} +//~^ ERROR E0322 + +impl Sized for (MyType, MyType) {} +//~^ ERROR E0322 +//~| ERROR E0117 + +impl Sized for &'static NotSync {} +//~^ ERROR E0322 + +impl Sized for [MyType] {} +//~^ ERROR E0322 +//~| ERROR E0117 + +impl Sized for &'static [NotSync] {} +//~^ ERROR E0322 +//~| ERROR E0117 + +fn main() { +} diff --git a/tests/ui/coherence/coherence-impls-sized.stderr b/tests/ui/coherence/coherence-impls-sized.stderr new file mode 100644 index 000000000..17a754452 --- /dev/null +++ b/tests/ui/coherence/coherence-impls-sized.stderr @@ -0,0 +1,73 @@ +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/coherence-impls-sized.rs:14:1 + | +LL | impl Sized for TestE {} + | ^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/coherence-impls-sized.rs:17:1 + | +LL | impl Sized for MyType {} + | ^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/coherence-impls-sized.rs:20:1 + | +LL | impl Sized for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:20:1 + | +LL | impl Sized for (MyType, MyType) {} + | ^^^^^^^^^^^^^^^---------------- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/coherence-impls-sized.rs:24:1 + | +LL | impl Sized for &'static NotSync {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/coherence-impls-sized.rs:27:1 + | +LL | impl Sized for [MyType] {} + | ^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:27:1 + | +LL | impl Sized for [MyType] {} + | ^^^^^^^^^^^^^^^-------- + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0322]: explicit impls for the `Sized` trait are not permitted + --> $DIR/coherence-impls-sized.rs:31:1 + | +LL | impl Sized for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-impls-sized.rs:31:1 + | +LL | impl Sized for &'static [NotSync] {} + | ^^^^^^^^^^^^^^^------------------ + | | | + | | this is not defined in the current crate because slices are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0117, E0322. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs new file mode 100644 index 000000000..d74d3a2a5 --- /dev/null +++ b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs @@ -0,0 +1,24 @@ +// Formerly this ICEd with the following message: +// Tried to project an inherited associated type during coherence checking, +// which is currently not supported. +// +// No we expect to run into a more user-friendly cycle error instead. +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Trait { type Assoc; } +//~^ ERROR E0391 + +impl Trait for Vec { + type Assoc = (); +} + +impl Trait for Vec {} + +impl Trait for String { + type Assoc = (); +} + +impl Trait< as Trait>::Assoc> for String {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr new file mode 100644 index 000000000..7bd50649d --- /dev/null +++ b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr @@ -0,0 +1,26 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0391]: cycle detected when building specialization graph of trait `Trait` + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1 + | +LL | trait Trait { type Assoc; } + | ^^^^^^^^^^^^^^ + | + = note: ...which immediately requires building specialization graph of trait `Trait` again +note: cycle used when coherence checking all impls of trait `Trait` + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1 + | +LL | trait Trait { type Assoc; } + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/coherence/coherence-inherited-subtyping.old.stderr b/tests/ui/coherence/coherence-inherited-subtyping.old.stderr new file mode 100644 index 000000000..4701bc0b1 --- /dev/null +++ b/tests/ui/coherence/coherence-inherited-subtyping.old.stderr @@ -0,0 +1,14 @@ +error[E0592]: duplicate definitions with name `method1` + --> $DIR/coherence-inherited-subtyping.rs:14:5 + | +LL | fn method1(&self) {} + | ^^^^^^^^^^^^^^^^^ duplicate definitions for `method1` +... +LL | fn method1(&self) {} + | ----------------- other definition for `method1` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-inherited-subtyping.re.stderr b/tests/ui/coherence/coherence-inherited-subtyping.re.stderr new file mode 100644 index 000000000..4701bc0b1 --- /dev/null +++ b/tests/ui/coherence/coherence-inherited-subtyping.re.stderr @@ -0,0 +1,14 @@ +error[E0592]: duplicate definitions with name `method1` + --> $DIR/coherence-inherited-subtyping.rs:14:5 + | +LL | fn method1(&self) {} + | ^^^^^^^^^^^^^^^^^ duplicate definitions for `method1` +... +LL | fn method1(&self) {} + | ----------------- other definition for `method1` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-inherited-subtyping.rs b/tests/ui/coherence/coherence-inherited-subtyping.rs new file mode 100644 index 000000000..8587eb779 --- /dev/null +++ b/tests/ui/coherence/coherence-inherited-subtyping.rs @@ -0,0 +1,21 @@ +// Test that two distinct impls which match subtypes of one another +// yield coherence errors (or not) depending on the variance. +// +// Note: This scenario is currently accepted, but as part of the +// universe transition (#56105) may eventually become an error. + +// revisions: old re + +struct Foo { + t: T, +} + +impl Foo fn(&'a u8, &'b u8) -> &'a u8> { + fn method1(&self) {} //~ ERROR duplicate definitions with name `method1` +} + +impl Foo fn(&'a u8, &'a u8) -> &'a u8> { + fn method1(&self) {} +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-iterator-vec-any-elem.rs b/tests/ui/coherence/coherence-iterator-vec-any-elem.rs new file mode 100644 index 000000000..43a0a5c42 --- /dev/null +++ b/tests/ui/coherence/coherence-iterator-vec-any-elem.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote1; + +struct Foo(T); + +impl Remote1 for Foo { } + +fn main() { } diff --git a/tests/ui/coherence/coherence-iterator-vec.rs b/tests/ui/coherence/coherence-iterator-vec.rs new file mode 100644 index 000000000..386fe40ac --- /dev/null +++ b/tests/ui/coherence/coherence-iterator-vec.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// aux-build:coherence_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate coherence_lib as lib; +use lib::Remote1; + +struct Foo(T); + +impl Remote1 for Foo { } + +fn main() { } diff --git a/tests/ui/coherence/coherence-lone-type-parameter.rs b/tests/ui/coherence/coherence-lone-type-parameter.rs new file mode 100644 index 000000000..5368fef76 --- /dev/null +++ b/tests/ui/coherence/coherence-lone-type-parameter.rs @@ -0,0 +1,10 @@ +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::Remote; + +impl Remote for T { } +//~^ ERROR E0210 + + +fn main() { } diff --git a/tests/ui/coherence/coherence-lone-type-parameter.stderr b/tests/ui/coherence/coherence-lone-type-parameter.stderr new file mode 100644 index 000000000..ef5b08836 --- /dev/null +++ b/tests/ui/coherence/coherence-lone-type-parameter.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/coherence-lone-type-parameter.rs:6:6 + | +LL | impl Remote for T { } + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/coherence-multidispatch-tuple.rs b/tests/ui/coherence/coherence-multidispatch-tuple.rs new file mode 100644 index 000000000..fa1d4bbb4 --- /dev/null +++ b/tests/ui/coherence/coherence-multidispatch-tuple.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 + +use std::fmt::Debug; +use std::default::Default; + +// Test that an impl for homogeneous pairs does not conflict with a +// heterogeneous pair. + +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for (T,T) { + fn get(&self) -> usize { 0 } +} + +impl MyTrait for (usize,isize) { + fn get(&self) -> usize { 0 } +} + +fn main() { +} diff --git a/tests/ui/coherence/coherence-negative-impls-copy-bad.rs b/tests/ui/coherence/coherence-negative-impls-copy-bad.rs new file mode 100644 index 000000000..563f28e22 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-impls-copy-bad.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] +#![crate_type = "lib"] + +impl !Copy for str {} +//~^ ERROR only traits defined in the current crate can be implemented + +impl !Copy for fn() {} +//~^ ERROR only traits defined in the current crate can be implemented + +impl !Copy for () {} +//~^ ERROR only traits defined in the current crate can be implemented diff --git a/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr new file mode 100644 index 000000000..2295d6315 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-impls-copy-bad.stderr @@ -0,0 +1,36 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-negative-impls-copy-bad.rs:4:1 + | +LL | impl !Copy for str {} + | ^^^^^^^^^^^^^^^--- + | | | + | | `str` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-negative-impls-copy-bad.rs:7:1 + | +LL | impl !Copy for fn() {} + | ^^^^^^^^^^^^^^^---- + | | | + | | `fn()` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-negative-impls-copy-bad.rs:10:1 + | +LL | impl !Copy for () {} + | ^^^^^^^^^^^^^^^-- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-negative-impls-copy.rs b/tests/ui/coherence/coherence-negative-impls-copy.rs new file mode 100644 index 000000000..7b29aade4 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-impls-copy.rs @@ -0,0 +1,29 @@ +// check-pass +// regression test for issue #101836 + +#![feature(negative_impls, extern_types)] +#![crate_type = "lib"] + +struct NonCopy; +struct NeverCopy(NonCopy); + +impl !Copy for NeverCopy {} + + +struct WithDrop; +impl Drop for WithDrop { fn drop(&mut self) {} } + +impl !Copy for WithDrop {} + + +struct Type; +trait Trait {} +extern { + type ExternType; +} + +impl !Copy for &mut Type {} + +impl !Copy for dyn Trait {} + +impl !Copy for ExternType {} diff --git a/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs b/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs new file mode 100644 index 000000000..b87e162ac --- /dev/null +++ b/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#![feature(negative_impls)] + +use std::marker::Send; + +struct TestType; + +impl !Send for TestType {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-negative-impls-safe.rs b/tests/ui/coherence/coherence-negative-impls-safe.rs new file mode 100644 index 000000000..4821aa6b5 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-impls-safe.rs @@ -0,0 +1,10 @@ +#![feature(negative_impls)] + +use std::marker::Send; + +struct TestType; + +unsafe impl !Send for TestType {} +//~^ ERROR E0198 + +fn main() {} diff --git a/tests/ui/coherence/coherence-negative-impls-safe.stderr b/tests/ui/coherence/coherence-negative-impls-safe.stderr new file mode 100644 index 000000000..1bd37f395 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-impls-safe.stderr @@ -0,0 +1,12 @@ +error[E0198]: negative impls cannot be unsafe + --> $DIR/coherence-negative-impls-safe.rs:7:13 + | +LL | unsafe impl !Send for TestType {} + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0198`. diff --git a/tests/ui/coherence/coherence-negative-inherent-where-bounds.rs b/tests/ui/coherence/coherence-negative-inherent-where-bounds.rs new file mode 100644 index 000000000..39ccaa6ac --- /dev/null +++ b/tests/ui/coherence/coherence-negative-inherent-where-bounds.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +trait Foo {} + +impl !Foo for u32 {} + +#[rustc_strict_coherence] +struct MyStruct(T); + +impl MyStruct { + fn method(&self) {} +} + +impl MyStruct +where + T: Foo, +{ + fn method(&self) {} +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-negative-inherent.rs b/tests/ui/coherence/coherence-negative-inherent.rs new file mode 100644 index 000000000..a9e1acc80 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-inherent.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +#[rustc_strict_coherence] +trait Foo {} + +impl !Foo for u32 {} + +struct MyStruct(T); + +impl MyStruct { + fn method(&self) {} +} + +impl MyStruct { + fn method(&self) {} +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs b/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs new file mode 100644 index 000000000..3acf0d8d3 --- /dev/null +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs @@ -0,0 +1,17 @@ +// revisions: stock with_negative_coherence +//[with_negative_coherence] check-pass + +#![feature(negative_impls)] +#![cfg_attr(with_negative_coherence, feature(with_negative_coherence))] + +trait MyPredicate<'a> {} + +impl<'a, T> !MyPredicate<'a> for &'a T where T: 'a {} + +trait MyTrait<'a> {} + +impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} +impl<'a, T> MyTrait<'a> for &'a T {} +//[stock]~^ ERROR: conflicting implementations of trait `MyTrait<'_>` for type `&_` + +fn main() {} diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr new file mode 100644 index 000000000..097cc4e0f --- /dev/null +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyTrait<'_>` for type `&_` + --> $DIR/coherence-negative-outlives-lifetimes.rs:14:1 + | +LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} + | ---------------------------------------------- first implementation here +LL | impl<'a, T> MyTrait<'a> for &'a T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.rs b/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.rs new file mode 100644 index 000000000..d466dcac1 --- /dev/null +++ b/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.rs @@ -0,0 +1,9 @@ +// Test that you cannot *directly* dispatch on lifetime requirements + +trait MyTrait { fn foo() {} } + +impl MyTrait for T {} +impl MyTrait for T {} +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr b/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr new file mode 100644 index 000000000..8a43ad7b7 --- /dev/null +++ b/tests/ui/coherence/coherence-no-direct-lifetime-dispatch.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyTrait` + --> $DIR/coherence-no-direct-lifetime-dispatch.rs:6:1 + | +LL | impl MyTrait for T {} + | --------------------- first implementation here +LL | impl MyTrait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-orphan.rs b/tests/ui/coherence/coherence-orphan.rs new file mode 100644 index 000000000..3beac04c7 --- /dev/null +++ b/tests/ui/coherence/coherence-orphan.rs @@ -0,0 +1,20 @@ +// aux-build:coherence_orphan_lib.rs +#![feature(negative_impls)] + +extern crate coherence_orphan_lib as lib; + +use lib::TheTrait; + +struct TheType; + +impl TheTrait for isize { } +//~^ ERROR E0117 + +impl TheTrait for isize { } + +impl TheTrait for TheType { } + +impl !Send for Vec { } +//~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr new file mode 100644 index 000000000..01f166a21 --- /dev/null +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -0,0 +1,26 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/coherence-orphan.rs:10:1 + | +LL | impl TheTrait for isize { } + | ^^^^^---------------^^^^^----- + | | | | + | | | `isize` is not defined in the current crate + | | `usize` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-orphan.rs:17:1 + | +LL | impl !Send for Vec { } + | ^^^^^^^^^^^^^^^---------- + | | | + | | `Vec` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-overlap-all-t-and-tuple.rs b/tests/ui/coherence/coherence-overlap-all-t-and-tuple.rs new file mode 100644 index 000000000..574a16a19 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-all-t-and-tuple.rs @@ -0,0 +1,20 @@ +// Check that we detect an overlap here in the case where: +// +// for some type X: +// T = (X,) +// T11 = X, U11 = X +// +// Seems pretty basic, but then there was issue #24241. :) + +trait From { + fn foo() {} +} + +impl From for T { +} + +impl From<(U11,)> for (T11,) { +//~^ ERROR E0119 +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr b/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr new file mode 100644 index 000000000..6a0880334 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-all-t-and-tuple.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From<(_,)>` for type `(_,)` + --> $DIR/coherence-overlap-all-t-and-tuple.rs:16:1 + | +LL | impl From for T { + | ---------------------- first implementation here +... +LL | impl From<(U11,)> for (T11,) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-double-negative.rs b/tests/ui/coherence/coherence-overlap-double-negative.rs new file mode 100644 index 000000000..1ea0ddc74 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-double-negative.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +trait A {} +trait B: A {} + +impl !A for u32 {} +impl !B for u32 {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs new file mode 100644 index 000000000..5dea33e33 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs @@ -0,0 +1,17 @@ +// Tests that we consider `T: Sugar + Fruit` to be ambiguous, even +// though no impls are found. + +struct Sweet(X); +pub trait Sugar {} +pub trait Fruit {} +impl Sweet { fn dummy(&self) { } } +//~^ ERROR E0592 +impl Sweet { fn dummy(&self) { } } + +trait Bar {} +struct A(T, X); +impl A where T: Bar { fn f(&self) {} } +//~^ ERROR E0592 +impl A { fn f(&self) {} } + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr new file mode 100644 index 000000000..bbce4b530 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr @@ -0,0 +1,23 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-downstream-inherent.rs:7:26 + | +LL | impl Sweet { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl Sweet { fn dummy(&self) { } } + | --------------- other definition for `dummy` + +error[E0592]: duplicate definitions with name `f` + --> $DIR/coherence-overlap-downstream-inherent.rs:13:38 + | +LL | impl A where T: Bar { fn f(&self) {} } + | ^^^^^^^^^^^ duplicate definitions for `f` +LL | +LL | impl A { fn f(&self) {} } + | ----------- other definition for `f` + | + = note: downstream crates may implement trait `Bar<_>` for type `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs new file mode 100644 index 000000000..738ec0e3d --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream.rs @@ -0,0 +1,17 @@ +// Tests that we consider `T: Sugar + Fruit` to be ambiguous, even +// though no impls are found. + +pub trait Sugar {} +pub trait Fruit {} +pub trait Sweet {} +impl Sweet for T { } +impl Sweet for T { } +//~^ ERROR E0119 + +pub trait Foo {} +pub trait Bar {} +impl Foo for T where T: Bar {} +impl Foo for i32 {} +//~^ ERROR E0119 + +fn main() { } diff --git a/tests/ui/coherence/coherence-overlap-downstream.stderr b/tests/ui/coherence/coherence-overlap-downstream.stderr new file mode 100644 index 000000000..7f373e595 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream.stderr @@ -0,0 +1,21 @@ +error[E0119]: conflicting implementations of trait `Sweet` + --> $DIR/coherence-overlap-downstream.rs:8:1 + | +LL | impl Sweet for T { } + | ------------------------- first implementation here +LL | impl Sweet for T { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` + --> $DIR/coherence-overlap-downstream.rs:14:1 + | +LL | impl Foo for T where T: Bar {} + | ----------------------- first implementation here +LL | impl Foo for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | + = note: downstream crates may implement trait `Bar<_>` for type `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs new file mode 100644 index 000000000..a272e620f --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs @@ -0,0 +1,13 @@ +// Tests that we consider `Box: !Sugar` to be ambiguous, even +// though we see no impl of `Sugar` for `Box`. Therefore, an overlap +// error is reported for the following pair of impls (#23516). + +pub trait Sugar {} + +struct Cake(X); + +impl Cake { fn dummy(&self) { } } +//~^ ERROR E0592 +impl Cake> { fn dummy(&self) { } } + +fn main() { } diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr new file mode 100644 index 000000000..3ad818cbc --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr @@ -0,0 +1,14 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25 + | +LL | impl Cake { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl Cake> { fn dummy(&self) { } } + | --------------- other definition for `dummy` + | + = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs new file mode 100644 index 000000000..63e42e8f4 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs @@ -0,0 +1,11 @@ +// Tests that we consider `Box: !Sugar` to be ambiguous, even +// though we see no impl of `Sugar` for `Box`. Therefore, an overlap +// error is reported for the following pair of impls (#23516). + +pub trait Sugar { fn dummy(&self) { } } +pub trait Sweet { fn dummy(&self) { } } +impl Sweet for T { } +impl Sweet for Box { } +//~^ ERROR E0119 + +fn main() { } diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.stderr new file mode 100644 index 000000000..cd3984267 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` + --> $DIR/coherence-overlap-issue-23516.rs:8:1 + | +LL | impl Sweet for T { } + | ------------------------- first implementation here +LL | impl Sweet for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-messages.rs b/tests/ui/coherence/coherence-overlap-messages.rs new file mode 100644 index 000000000..1258a2371 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-messages.rs @@ -0,0 +1,28 @@ +trait Foo { fn foo() {} } + +impl Foo for T {} +impl Foo for U {} +//~^ ERROR E0119 + + +trait Bar { fn bar() {} } + +impl Bar for (T, u8) {} +impl Bar for (u8, T) {} +//~^ ERROR E0119 + +trait Baz { fn baz() {} } + +impl Baz for T {} +impl Baz for u8 {} +//~^ ERROR E0119 + +trait Quux { fn quux() {} } + +impl Quux for T {} +impl Quux for T {} +//~^ ERROR E0119 +impl Quux for T {} +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-messages.stderr b/tests/ui/coherence/coherence-overlap-messages.stderr new file mode 100644 index 000000000..5a97296ee --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-messages.stderr @@ -0,0 +1,44 @@ +error[E0119]: conflicting implementations of trait `Foo` + --> $DIR/coherence-overlap-messages.rs:4:1 + | +LL | impl Foo for T {} + | ----------------- first implementation here +LL | impl Foo for U {} + | ^^^^^^^^^^^^^^^^^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)` + --> $DIR/coherence-overlap-messages.rs:11:1 + | +LL | impl Bar for (T, u8) {} + | ----------------------- first implementation here +LL | impl Bar for (u8, T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)` + +error[E0119]: conflicting implementations of trait `Baz` for type `u8` + --> $DIR/coherence-overlap-messages.rs:17:1 + | +LL | impl Baz for T {} + | --------------------- first implementation here +LL | impl Baz for u8 {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8` + +error[E0119]: conflicting implementations of trait `Quux<_, _>` + --> $DIR/coherence-overlap-messages.rs:23:1 + | +LL | impl Quux for T {} + | ------------------------------ first implementation here +LL | impl Quux for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Quux<_, _>` + --> $DIR/coherence-overlap-messages.rs:25:1 + | +LL | impl Quux for T {} + | ------------------------------ first implementation here +... +LL | impl Quux for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-negate-alias-strict.rs b/tests/ui/coherence/coherence-overlap-negate-alias-strict.rs new file mode 100644 index 000000000..48dffc921 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negate-alias-strict.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(trait_alias)] +#![feature(with_negative_coherence)] + +trait A {} +trait B {} +trait AB = A + B; + +impl !A for u32 {} + +#[rustc_strict_coherence] +trait C {} +impl C for T {} +impl C for u32 {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs new file mode 100644 index 000000000..a067736f6 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.rs @@ -0,0 +1,8 @@ +use std::ops::DerefMut; + +trait Foo {} +impl Foo for T {} +impl Foo for &U {} +//~^ ERROR: conflicting implementations of trait `Foo` for type `&_` [E0119] + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr new file mode 100644 index 000000000..4b55001ec --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `&_` + --> $DIR/coherence-overlap-negate-not-use-feature-gate.rs:5:1 + | +LL | impl Foo for T {} + | --------------------------- first implementation here +LL | impl Foo for &U {} + | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-negate-strict.rs b/tests/ui/coherence/coherence-overlap-negate-strict.rs new file mode 100644 index 000000000..1021d87ca --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negate-strict.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(trait_alias)] +#![feature(with_negative_coherence)] + +trait A {} +trait B {} + +impl !A for u32 {} + +#[rustc_strict_coherence] +trait C {} +impl C for T {} +impl C for u32 {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-negate-use-feature-gate.rs b/tests/ui/coherence/coherence-overlap-negate-use-feature-gate.rs new file mode 100644 index 000000000..a0dd881d1 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negate-use-feature-gate.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(with_negative_coherence)] + +use std::ops::DerefMut; + +trait Foo {} +impl Foo for T {} +impl Foo for &U {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-negative-trait.rs b/tests/ui/coherence/coherence-overlap-negative-trait.rs new file mode 100644 index 000000000..8059d23ff --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negative-trait.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:error_lib.rs +// +// Check that if we promise to not impl what would overlap it doesn't actually overlap + +#![feature(with_negative_coherence)] + +extern crate error_lib as lib; +use lib::Error; + +trait From {} + +impl From<&str> for Box {} +impl From for Box where E: Error {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-negative-trait2.rs b/tests/ui/coherence/coherence-overlap-negative-trait2.rs new file mode 100644 index 000000000..cc8c463b8 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-negative-trait2.rs @@ -0,0 +1,17 @@ +// check-pass +// aux-build:option_future.rs +// +// Check that if we promise to not impl what would overlap it doesn't actually overlap + +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +extern crate option_future as lib; +use lib::Future; + +trait Termination {} + +impl Termination for Option where E: Sized {} +impl Termination for F where F: Future + Sized {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-super-negative.rs b/tests/ui/coherence/coherence-overlap-super-negative.rs new file mode 100644 index 000000000..d296a094a --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-super-negative.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +trait Trait1: Trait2 {} +trait Trait2 {} + +struct MyType {} +impl !Trait2 for MyType {} + +#[rustc_strict_coherence] +trait Foo {} +impl Foo for T {} +impl Foo for MyType {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-trait-alias.rs b/tests/ui/coherence/coherence-overlap-trait-alias.rs new file mode 100644 index 000000000..9d9c76af9 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-trait-alias.rs @@ -0,0 +1,20 @@ +#![feature(rustc_attrs)] +#![feature(trait_alias)] +#![feature(with_negative_coherence)] + +trait A {} +trait B {} +trait AB = A + B; + +impl A for u32 {} +impl B for u32 {} + +#[rustc_strict_coherence] +trait C {} +impl C for T {} +impl C for u32 {} +//~^ ERROR +// FIXME it's giving an ungreat error but unsure if we care given that it's using an internal rustc +// attribute and an artificial code path for testing purposes + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-trait-alias.stderr b/tests/ui/coherence/coherence-overlap-trait-alias.stderr new file mode 100644 index 000000000..668b8319b --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-trait-alias.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `u32: C` + --> $DIR/coherence-overlap-trait-alias.rs:15:12 + | +LL | impl C for u32 {} + | ^^^ + | +note: multiple `impl`s satisfying `u32: C` found + --> $DIR/coherence-overlap-trait-alias.rs:14:1 + | +LL | impl C for T {} + | ^^^^^^^^^^^^^^^^^^^ +LL | impl C for u32 {} + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/coherence/coherence-overlap-upstream-inherent.rs b/tests/ui/coherence/coherence-overlap-upstream-inherent.rs new file mode 100644 index 000000000..082d753de --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-upstream-inherent.rs @@ -0,0 +1,16 @@ +// Tests that we consider `i16: Remote` to be ambiguous, even +// though the upstream crate doesn't implement it for now. + +// aux-build:coherence_lib.rs + + +extern crate coherence_lib; + +use coherence_lib::Remote; + +struct A(X); +impl A where T: Remote { fn dummy(&self) { } } +//~^ ERROR E0592 +impl A { fn dummy(&self) { } } + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr b/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr new file mode 100644 index 000000000..f355c6e85 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-upstream-inherent.stderr @@ -0,0 +1,14 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-upstream-inherent.rs:12:32 + | +LL | impl A where T: Remote { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl A { fn dummy(&self) { } } + | --------------- other definition for `dummy` + | + = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-upstream.rs b/tests/ui/coherence/coherence-overlap-upstream.rs new file mode 100644 index 000000000..8f1e6558b --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-upstream.rs @@ -0,0 +1,16 @@ +// Tests that we consider `i16: Remote` to be ambiguous, even +// though the upstream crate doesn't implement it for now. + +// aux-build:coherence_lib.rs + + +extern crate coherence_lib; + +use coherence_lib::Remote; + +trait Foo {} +impl Foo for T where T: Remote {} +impl Foo for i16 {} +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlap-upstream.stderr b/tests/ui/coherence/coherence-overlap-upstream.stderr new file mode 100644 index 000000000..f6145c188 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-upstream.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `i16` + --> $DIR/coherence-overlap-upstream.rs:13:1 + | +LL | impl Foo for T where T: Remote {} + | ----------------- first implementation here +LL | impl Foo for i16 {} + | ^^^^^^^^^^^^^^^^ conflicting implementation for `i16` + | + = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-with-regions.rs b/tests/ui/coherence/coherence-overlap-with-regions.rs new file mode 100644 index 000000000..32f01f418 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-with-regions.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(with_negative_coherence)] + +#[rustc_strict_coherence] +trait Foo {} +impl !Foo for &T where T: 'static {} + +#[rustc_strict_coherence] +trait Bar {} +impl Bar for T {} +impl Bar for &T where T: 'static {} + +fn main() {} diff --git a/tests/ui/coherence/coherence-overlapping-pairs.rs b/tests/ui/coherence/coherence-overlapping-pairs.rs new file mode 100644 index 000000000..d5d18217b --- /dev/null +++ b/tests/ui/coherence/coherence-overlapping-pairs.rs @@ -0,0 +1,11 @@ +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::Remote; + +struct Foo; + +impl Remote for lib::Pair { } +//~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-overlapping-pairs.stderr b/tests/ui/coherence/coherence-overlapping-pairs.stderr new file mode 100644 index 000000000..15c92dfeb --- /dev/null +++ b/tests/ui/coherence/coherence-overlapping-pairs.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-overlapping-pairs.rs:8:1 + | +LL | impl Remote for lib::Pair { } + | ^^^^^^^^^^^^^^^^^^^---------------- + | | | + | | `Pair` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.rs b/tests/ui/coherence/coherence-pair-covered-uncovered-1.rs new file mode 100644 index 000000000..15868ca86 --- /dev/null +++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.rs @@ -0,0 +1,15 @@ +// Test that the same coverage rules apply even if the local type appears in the +// list of type parameters, not the self type. + +// aux-build:coherence_lib.rs + + +extern crate coherence_lib as lib; +use lib::{Remote1, Pair}; + +pub struct Local(T); + +impl Remote1>> for i32 { } +//~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr new file mode 100644 index 000000000..03d787123 --- /dev/null +++ b/tests/ui/coherence/coherence-pair-covered-uncovered-1.stderr @@ -0,0 +1,15 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/coherence-pair-covered-uncovered-1.rs:12:1 + | +LL | impl Remote1>> for i32 { } + | ^^^^^^^^^^^--------------------------^^^^^--- + | | | | + | | | `i32` is not defined in the current crate + | | `Pair` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.rs b/tests/ui/coherence/coherence-pair-covered-uncovered.rs new file mode 100644 index 000000000..da970572f --- /dev/null +++ b/tests/ui/coherence/coherence-pair-covered-uncovered.rs @@ -0,0 +1,11 @@ +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::{Remote, Pair}; + +struct Local(T); + +impl Remote for Pair> { } +//~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-pair-covered-uncovered.stderr b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr new file mode 100644 index 000000000..73dfe2f57 --- /dev/null +++ b/tests/ui/coherence/coherence-pair-covered-uncovered.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-pair-covered-uncovered.rs:8:1 + | +LL | impl Remote for Pair> { } + | ^^^^^^^^^^^^^^^^^^^^^---------------- + | | | + | | `Pair` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-projection-conflict-orphan.rs b/tests/ui/coherence/coherence-projection-conflict-orphan.rs new file mode 100644 index 000000000..637dd2506 --- /dev/null +++ b/tests/ui/coherence/coherence-projection-conflict-orphan.rs @@ -0,0 +1,19 @@ +#![feature(rustc_attrs)] + +// Here we expect a coherence conflict because, even though `i32` does +// not implement `Iterator`, we cannot rely on that negative reasoning +// due to the orphan rules. Therefore, `A::Item` may yet turn out to +// be `i32`. + +pub trait Foo

{ fn foo() {} } + +pub trait Bar { + type Output: 'static; +} + +impl Foo for i32 { } + +impl Foo for A { } +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/coherence/coherence-projection-conflict-orphan.stderr b/tests/ui/coherence/coherence-projection-conflict-orphan.stderr new file mode 100644 index 000000000..b1ee0795b --- /dev/null +++ b/tests/ui/coherence/coherence-projection-conflict-orphan.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `i32` + --> $DIR/coherence-projection-conflict-orphan.rs:16:1 + | +LL | impl Foo for i32 { } + | --------------------- first implementation here +LL | +LL | impl Foo for A { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-projection-conflict-ty-param.rs b/tests/ui/coherence/coherence-projection-conflict-ty-param.rs new file mode 100644 index 000000000..3e4141fa8 --- /dev/null +++ b/tests/ui/coherence/coherence-projection-conflict-ty-param.rs @@ -0,0 +1,13 @@ +// Coherence error results because we do not know whether `T: Foo

` or not +// for the second impl. + +use std::marker::PhantomData; + +pub trait Foo

{ fn foo() {} } + +impl > Foo

for Option {} + +impl Foo for Option { } +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr b/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr new file mode 100644 index 000000000..94d242eaa --- /dev/null +++ b/tests/ui/coherence/coherence-projection-conflict-ty-param.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo<_>` for type `Option<_>` + --> $DIR/coherence-projection-conflict-ty-param.rs:10:1 + | +LL | impl > Foo

for Option {} + | ---------------------------------------- first implementation here +LL | +LL | impl Foo for Option { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Option<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-projection-conflict.rs b/tests/ui/coherence/coherence-projection-conflict.rs new file mode 100644 index 000000000..daab2a2f8 --- /dev/null +++ b/tests/ui/coherence/coherence-projection-conflict.rs @@ -0,0 +1,18 @@ +use std::marker::PhantomData; + +pub trait Foo

{ fn foo() {} } + +pub trait Bar { + type Output: 'static; +} + +impl Foo for i32 { } + +impl Foo for A { } +//~^ ERROR E0119 + +impl Bar for i32 { + type Output = i32; +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-projection-conflict.stderr b/tests/ui/coherence/coherence-projection-conflict.stderr new file mode 100644 index 000000000..7d2c584c3 --- /dev/null +++ b/tests/ui/coherence/coherence-projection-conflict.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `i32` + --> $DIR/coherence-projection-conflict.rs:11:1 + | +LL | impl Foo for i32 { } + | --------------------- first implementation here +LL | +LL | impl Foo for A { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-projection-ok-orphan.rs b/tests/ui/coherence/coherence-projection-ok-orphan.rs new file mode 100644 index 000000000..42b4b1912 --- /dev/null +++ b/tests/ui/coherence/coherence-projection-ok-orphan.rs @@ -0,0 +1,17 @@ +// Here we do not get a coherence conflict because `Baz: Iterator` +// does not hold and (due to the orphan rules), we can rely on that. + +// check-pass + +pub trait Foo

{} + +pub trait Bar { + type Output: 'static; +} + +struct Baz; +impl Foo for Baz { } + +impl Foo for A { } + +fn main() {} diff --git a/tests/ui/coherence/coherence-projection-ok.rs b/tests/ui/coherence/coherence-projection-ok.rs new file mode 100644 index 000000000..44fc02a5c --- /dev/null +++ b/tests/ui/coherence/coherence-projection-ok.rs @@ -0,0 +1,17 @@ +// check-pass + +pub trait Foo

{ + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr new file mode 100644 index 000000000..04bc46cb4 --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr @@ -0,0 +1,14 @@ +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:9:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:11:15 + | +LL | impl Const

{ + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.rs b/tests/ui/const-generics/raw-ptr-const-param-deref.rs new file mode 100644 index 000000000..65595f07d --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.rs @@ -0,0 +1,21 @@ +// Checks that pointers must not be used as the type of const params. +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +const A: u32 = 3; + +struct Const; //~ ERROR: using raw pointers as const generic parameters + +impl Const

{ //~ ERROR: using raw pointers as const generic parameters + fn get() -> u32 { + unsafe { + *P + } + } +} + +fn main() { + assert_eq!(Const::<{&A as *const _}>::get(), 3) +} diff --git a/tests/ui/const-generics/raw-ptr-const-param.full.stderr b/tests/ui/const-generics/raw-ptr-const-param.full.stderr new file mode 100644 index 000000000..69f1aae56 --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:6:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr new file mode 100644 index 000000000..310422aaf --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr @@ -0,0 +1,8 @@ +error: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param.rs:6:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/raw-ptr-const-param.rs b/tests/ui/const-generics/raw-ptr-const-param.rs new file mode 100644 index 000000000..27ef9e7d9 --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param.rs @@ -0,0 +1,11 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Const; //~ ERROR: using raw pointers as const generic parameters + +fn main() { + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; + let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>; +} diff --git a/tests/ui/const-generics/slice-const-param-mismatch.full.stderr b/tests/ui/const-generics/slice-const-param-mismatch.full.stderr new file mode 100644 index 000000000..80dd1be33 --- /dev/null +++ b/tests/ui/const-generics/slice-const-param-mismatch.full.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/slice-const-param-mismatch.rs:14:35 + | +LL | let _: ConstString<"Hello"> = ConstString::<"World">; + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"` + | | + | expected due to this + | + = note: expected struct `ConstString<"Hello">` + found struct `ConstString<"World">` + +error[E0308]: mismatched types + --> $DIR/slice-const-param-mismatch.rs:16:33 + | +LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; + | ------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"` + | | + | expected due to this + | + = note: expected struct `ConstString<"ℇ㇈↦">` + found struct `ConstString<"ℇ㇈↥">` + +error[E0308]: mismatched types + --> $DIR/slice-const-param-mismatch.rs:18:33 + | +LL | let _: ConstBytes = ConstBytes::; + | ------------------ ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"` + | | + | expected due to this + | + = note: expected struct `ConstBytes` + found struct `ConstBytes` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr new file mode 100644 index 000000000..fed802f6a --- /dev/null +++ b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -0,0 +1,20 @@ +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/slice-const-param-mismatch.rs:7:29 + | +LL | struct ConstString; + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static [u8]` is forbidden as the type of a const generic parameter + --> $DIR/slice-const-param-mismatch.rs:9:28 + | +LL | struct ConstBytes; + | ^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/slice-const-param-mismatch.rs b/tests/ui/const-generics/slice-const-param-mismatch.rs new file mode 100644 index 000000000..7127323e5 --- /dev/null +++ b/tests/ui/const-generics/slice-const-param-mismatch.rs @@ -0,0 +1,19 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + + +struct ConstString; +//[min]~^ ERROR +struct ConstBytes; +//[min]~^ ERROR + +pub fn main() { + let _: ConstString<"Hello"> = ConstString::<"Hello">; + let _: ConstString<"Hello"> = ConstString::<"World">; //[full]~ ERROR mismatched types + let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">; + let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //[full]~ ERROR mismatched types + let _: ConstBytes = ConstBytes::<{&[0x41, 0x41, 0x41]}>; + let _: ConstBytes = ConstBytes::; //[full]~ ERROR mismatched types +} diff --git a/tests/ui/const-generics/slice-const-param.rs b/tests/ui/const-generics/slice-const-param.rs new file mode 100644 index 000000000..05d21e08d --- /dev/null +++ b/tests/ui/const-generics/slice-const-param.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub fn function_with_str() -> &'static str { + STRING +} + +pub fn function_with_bytes() -> &'static [u8] { + BYTES +} + +pub fn main() { + assert_eq!(function_with_str::<"Rust">(), "Rust"); + assert_eq!(function_with_str::<"ℇ㇈↦">(), "ℇ㇈↦"); + assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::<{&[0x41, 0x41, 0x41, 0x41]}>(), b"AAAA"); +} diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.rs b/tests/ui/const-generics/sneaky-array-repeat-expr.rs new file mode 100644 index 000000000..b147c246b --- /dev/null +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.rs @@ -0,0 +1,32 @@ +trait Trait { + const Assoc: usize; +} + +impl Trait for () { + const Assoc: usize = 1; +} + + +pub const fn foo() where (): Trait { + let bar = [(); <()>::Assoc]; + //~^ error: constant expression depends on a generic parameter +} + +trait Trait2 { + const Assoc2: usize; +} + +impl Trait2 for () { + const Assoc2: usize = N - 1; +} + + +pub const fn foo2() where (): Trait2 { + let bar2 = [(); <()>::Assoc2]; + //~^ error: constant expression depends on a generic parameter +} + +fn main() { + foo::<0>(); + foo2::<0>(); +} diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr new file mode 100644 index 000000000..5c77375d3 --- /dev/null +++ b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr @@ -0,0 +1,18 @@ +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:11:20 + | +LL | let bar = [(); <()>::Assoc]; + | ^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/sneaky-array-repeat-expr.rs:25:21 + | +LL | let bar2 = [(); <()>::Assoc2]; + | ^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr new file mode 100644 index 000000000..d4b2ad6fd --- /dev/null +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -0,0 +1,56 @@ +error: `std::ops::Range` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:7:24 + | +LL | struct _Range>; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeFrom` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:12:28 + | +LL | struct _RangeFrom>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeFull` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:17:28 + | +LL | struct _RangeFull; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeInclusive` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:23:33 + | +LL | struct _RangeInclusive>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeTo` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:28:26 + | +LL | struct _RangeTo>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `RangeToInclusive` is forbidden as the type of a const generic parameter + --> $DIR/const-generics-range.rs:33:35 + | +LL | struct _RangeToInclusive>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs new file mode 100644 index 000000000..46c06f312 --- /dev/null +++ b/tests/ui/const-generics/std/const-generics-range.rs @@ -0,0 +1,37 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +// `Range` should be usable within const generics: +struct _Range>; +//[min]~^ ERROR `std::ops::Range` is forbidden +const RANGE : _Range<{ 0 .. 1000 }> = _Range; + +// `RangeFrom` should be usable within const generics: +struct _RangeFrom>; +//[min]~^ ERROR `RangeFrom` is forbidden +const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom; + +// `RangeFull` should be usable within const generics: +struct _RangeFull; +//[min]~^ ERROR `RangeFull` is forbidden +const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull; + +// Regression test for #70155 +// `RangeInclusive` should be usable within const generics: +struct _RangeInclusive>; +//[min]~^ ERROR `RangeInclusive` is forbidden +const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive; + +// `RangeTo` should be usable within const generics: +struct _RangeTo>; +//[min]~^ ERROR `RangeTo` is forbidden +const RANGE_TO : _RangeTo<{ .. 1000 }> = _RangeTo; + +// `RangeToInclusive` should be usable within const generics: +struct _RangeToInclusive>; +//[min]~^ ERROR `RangeToInclusive` is forbidden +const RANGE_TO_INCLUSIVE : _RangeToInclusive<{ ..= 999 }> = _RangeToInclusive; + +pub fn main() {} diff --git a/tests/ui/const-generics/struct-with-invalid-const-param.rs b/tests/ui/const-generics/struct-with-invalid-const-param.rs new file mode 100644 index 000000000..be1c4b0e8 --- /dev/null +++ b/tests/ui/const-generics/struct-with-invalid-const-param.rs @@ -0,0 +1,5 @@ +// Checks that a const param cannot be stored in a struct. + +struct S(C); //~ ERROR expected type, found const parameter + +fn main() {} diff --git a/tests/ui/const-generics/struct-with-invalid-const-param.stderr b/tests/ui/const-generics/struct-with-invalid-const-param.stderr new file mode 100644 index 000000000..67f497af5 --- /dev/null +++ b/tests/ui/const-generics/struct-with-invalid-const-param.stderr @@ -0,0 +1,9 @@ +error[E0573]: expected type, found const parameter `C` + --> $DIR/struct-with-invalid-const-param.rs:3:23 + | +LL | struct S(C); + | ^ not a type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/suggest_const_for_array.rs b/tests/ui/const-generics/suggest_const_for_array.rs new file mode 100644 index 000000000..f3e5a3186 --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +fn example() {} + +fn other() { + example::<[usize; 3]>(); + //~^ ERROR type provided when a const + example::<[usize; 4+5]>(); + //~^ ERROR type provided when a const +} diff --git a/tests/ui/const-generics/suggest_const_for_array.stderr b/tests/ui/const-generics/suggest_const_for_array.stderr new file mode 100644 index 000000000..a617bf2bb --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.stderr @@ -0,0 +1,15 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:6:13 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }` + +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:8:13 + | +LL | example::<[usize; 4+5]>(); + | ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/trait-const-args.rs b/tests/ui/const-generics/trait-const-args.rs new file mode 100644 index 000000000..2cdef3fb4 --- /dev/null +++ b/tests/ui/const-generics/trait-const-args.rs @@ -0,0 +1,27 @@ +// check-pass + +struct Const; +trait Foo {} + +impl Foo for Const {} + +fn foo_impl(_: impl Foo<3>) {} + +fn foo_explicit>(_: T) {} + +fn foo_where(_: T) +where + T: Foo<3>, +{ +} + +fn main() { + foo_impl(Const); + foo_impl(Const::<3>); + + foo_explicit(Const); + foo_explicit(Const::<3>); + + foo_where(Const); + foo_where(Const::<3>); +} diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr new file mode 100644 index 000000000..039c4276c --- /dev/null +++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr @@ -0,0 +1,11 @@ +error: `&'static ()` is forbidden as the type of a const generic parameter + --> $DIR/transmute-const-param-static-reference.rs:7:23 + | +LL | struct Const; + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.rs b/tests/ui/const-generics/transmute-const-param-static-reference.rs new file mode 100644 index 000000000..6b443c8bd --- /dev/null +++ b/tests/ui/const-generics/transmute-const-param-static-reference.rs @@ -0,0 +1,16 @@ +// revisions: full min +//[full] check-pass + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Const; +//[min]~^ ERROR `&'static ()` is forbidden as the type of a const generic parameter + +fn main() { + const A: &'static () = unsafe { + std::mem::transmute(10 as *const ()) + }; + + let _ = Const::<{A}>; +} diff --git a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs new file mode 100644 index 000000000..926e807fe --- /dev/null +++ b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -0,0 +1,12 @@ +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +use std::mem::MaybeUninit; + +#[repr(transparent)] +pub struct MaybeUninitWrapper(MaybeUninit<[u64; N]>); + +fn main() {} diff --git a/tests/ui/const-generics/try_unify_ignore_lifetimes.rs b/tests/ui/const-generics/try_unify_ignore_lifetimes.rs new file mode 100644 index 000000000..2ae0ae70d --- /dev/null +++ b/tests/ui/const-generics/try_unify_ignore_lifetimes.rs @@ -0,0 +1,33 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Num; + +trait NumT { + const VALUE: usize; +} + +impl NumT for Num { + const VALUE: usize = N; +} + +struct Foo<'a, N: NumT>(&'a [u32; N::VALUE]) where [(); N::VALUE]:; + +trait Bar { + type Size: NumT; + + fn bar<'a>(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +trait Baz<'a> { + type Size: NumT; + + fn baz(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/two_matching_preds.rs b/tests/ui/const-generics/two_matching_preds.rs new file mode 100644 index 000000000..de608f73e --- /dev/null +++ b/tests/ui/const-generics/two_matching_preds.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo() +where + [(); N + 1]:, + [(); N + 1]:, +{ + bar::(); +} + +fn bar() +where + [(); N + 1]:, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/type-after-const-ok.rs b/tests/ui/const-generics/type-after-const-ok.rs new file mode 100644 index 000000000..f37b0b102 --- /dev/null +++ b/tests/ui/const-generics/type-after-const-ok.rs @@ -0,0 +1,6 @@ +// run-pass +// Verifies that having generic parameters after constants is permitted +#[allow(dead_code)] +struct A(T); + +fn main() {} diff --git a/tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs b/tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs new file mode 100644 index 000000000..5dfcbba0e --- /dev/null +++ b/tests/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs @@ -0,0 +1,33 @@ +pub struct Struct(()); + +impl Struct { + pub fn new() -> Self { + Struct(()) + } + + pub fn same_ty(&self) -> (usize, usize) { + (N, M) + } + + pub fn different_ty(&self) -> (usize, u8) { + (N, M) + } + + pub fn containing_ty(&self) -> (usize, u8) { + (std::mem::size_of::() + N, M) + } + + pub fn we_have_to_go_deeper(&self) -> Struct { + Struct(()) + } +} + +pub trait Foo { + fn foo(&self) -> usize; +} + +impl Foo for Struct<7> { + fn foo(&self) -> usize { + M + } +} diff --git a/tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs b/tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs new file mode 100644 index 000000000..e84414834 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/const-arg-in-const-arg.rs @@ -0,0 +1,26 @@ +// run-pass +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + fn foo(&self) -> usize { + let f = self; + f.bar::<{ + let f = Foo; + f.bar::<7>() + }>() + N + } + + const fn bar(&self) -> usize { + M + } +} + +fn main() { + let f = Foo; + + assert_eq!(f.foo::<13>(), 20) +} diff --git a/tests/ui/const-generics/type-dependent/issue-61936.rs b/tests/ui/const-generics/type-dependent/issue-61936.rs new file mode 100644 index 000000000..7216b25f0 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-61936.rs @@ -0,0 +1,47 @@ +// run-pass + +trait SliceExt { + fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>; +} + +impl SliceExt for [T] { + fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N> { + ArrayWindowsExample{ idx: 0, slice: &self } + } +} + +struct ArrayWindowsExample<'a, T, const N: usize> { + slice: &'a [T], + idx: usize, +} + +impl <'a, T: Clone, const N: usize> Iterator for ArrayWindowsExample<'a, T, N> { + type Item = [T; N]; + fn next(&mut self) -> Option { + // Note: this is unsound for some `T` and not meant as an example + // on how to implement `ArrayWindows`. + let mut res = unsafe{ std::mem::zeroed() }; + let mut ptr = &mut res as *mut [T; N] as *mut T; + + for i in 0..N { + match self.slice[self.idx..].get(i) { + None => return None, + Some(elem) => unsafe { std::ptr::write_volatile(ptr, elem.clone())}, + }; + ptr = ptr.wrapping_add(1); + self.idx += 1; + } + + Some(res) + } +} + +const FOUR: usize = 4; + +fn main() { + let v: Vec = vec![0; 100]; + + for array in v.as_slice().array_windows_example::() { + assert_eq!(array, [0, 0, 0, 0]) + } +} diff --git a/tests/ui/const-generics/type-dependent/issue-63695.rs b/tests/ui/const-generics/type-dependent/issue-63695.rs new file mode 100644 index 000000000..08b6d4bf5 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-63695.rs @@ -0,0 +1,15 @@ +// run-pass + +trait T { + fn test(&self) -> i32 { A } +} + +struct S(); + +impl T for S {} + +fn main() { + let foo = S(); + assert_eq!(foo.test::<8i32>(), 8); + assert_eq!(foo.test::<16i32>(), 16); +} diff --git a/tests/ui/const-generics/type-dependent/issue-67144-1.rs b/tests/ui/const-generics/type-dependent/issue-67144-1.rs new file mode 100644 index 000000000..27dd51de2 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-67144-1.rs @@ -0,0 +1,25 @@ +// check-pass +struct X; + +impl X { + pub fn getn(&self) -> [u8; N] { + getn::() + } +} + +fn getn() -> [u8; N] { + unsafe { + std::mem::zeroed() + } +} + +fn main() { + // works + let [a,b,c] = getn::<3>(); + + // cannot pattern-match on an array without a fixed length + let [a,b,c] = X.getn::<3>(); + + // mismatched types, expected array `[u8; 3]` found array `[u8; _]` + let arr: [u8; 3] = X.getn::<3>(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-67144-2.rs b/tests/ui/const-generics/type-dependent/issue-67144-2.rs new file mode 100644 index 000000000..b26f551eb --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-67144-2.rs @@ -0,0 +1,19 @@ +// check-pass +struct A; + +struct X; + +impl X { + fn inner() -> A { + outer::() + } +} + +fn outer() -> A { + A +} + +fn main() { + let i: A<3usize> = outer::<3usize>(); + let o: A<3usize> = X::inner::<3usize>(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-69816.rs b/tests/ui/const-generics/type-dependent/issue-69816.rs new file mode 100644 index 000000000..cbb6b398e --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-69816.rs @@ -0,0 +1,17 @@ +// run-pass +trait IterExt: Sized + Iterator { + fn default_for_size(self) -> [Self::Item; N] + where + [Self::Item; N]: Default, + { + Default::default() + } +} + +impl IterExt for T {} + +fn main(){ + const N: usize = 10; + let arr = (0u32..10).default_for_size::(); + assert_eq!(arr, [0; 10]); +} diff --git a/tests/ui/const-generics/type-dependent/issue-70217.rs b/tests/ui/const-generics/type-dependent/issue-70217.rs new file mode 100644 index 000000000..933ca0276 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-70217.rs @@ -0,0 +1,14 @@ +// check-pass + +struct Struct; + +impl Struct { + fn method(&self) {} +} + +fn test(x: Struct) { + Struct::::method::(&x); + x.method::(); +} + +fn main() {} diff --git a/tests/ui/const-generics/type-dependent/issue-70507.rs b/tests/ui/const-generics/type-dependent/issue-70507.rs new file mode 100644 index 000000000..c72d9fbec --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-70507.rs @@ -0,0 +1,45 @@ +// run-pass + +trait ConstChunksExactTrait { + fn const_chunks_exact(&self) -> ConstChunksExact<'_, T, {N}>; +} + +impl ConstChunksExactTrait for [T] { + fn const_chunks_exact(&self) -> ConstChunksExact<'_, T, {N}> { + assert!(N != 0); + let rem = self.len() % N; + let len = self.len() - rem; + let (fst, _) = self.split_at(len); + ConstChunksExact { v: fst, } + } +} + +struct ConstChunksExact<'a, T: 'a, const N: usize> { + v: &'a [T], +} + +impl <'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<'a, T, {N}> { + type Item = &'a [T; N]; + + fn next(&mut self) -> Option { + if self.v.len() < N { + None + } else { + let (fst, snd) = self.v.split_at(N); + + self.v = snd; + let ptr = fst.as_ptr() as *const _; + Some(unsafe { &*ptr}) + } + } +} + +fn main() { + let slice = &[1i32, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].iter(); + + for a in slice.const_chunks_exact::<3>() { + assert_eq!(a, iter.next().unwrap()); + } +} diff --git a/tests/ui/const-generics/type-dependent/issue-70586.rs b/tests/ui/const-generics/type-dependent/issue-70586.rs new file mode 100644 index 000000000..346ac4b72 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-70586.rs @@ -0,0 +1,30 @@ +// check-pass +use std::marker::PhantomData; + +// This namespace is necessary for the ICE to trigger +struct Namespace; + +impl Namespace { + pub fn const_chunks_exact() -> ConstChunksExact<'static, T, N> { + ConstChunksExact { inner: PhantomData } + } +} + + +#[derive(Debug)] +pub struct ConstChunksExact<'a, T, const N: usize> { + inner: PhantomData<&'a T> +} + +impl <'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, { N }> { + type Item = &'a [T; N]; + + fn next(&mut self) -> Option { + unreachable!() + } +} + +fn main() { + let mut chunks = Namespace::const_chunks_exact::(); + let _next: &[i32; 3] = chunks.next().unwrap(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr new file mode 100644 index 000000000..b8fbb3979 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -0,0 +1,20 @@ +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-71348.rs:10:24 + | +LL | trait Get<'a, const N: &'static str> { + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-71348.rs:18:25 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs new file mode 100644 index 000000000..2ef2f066a --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.rs @@ -0,0 +1,38 @@ +// [full] run-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo { + i: i32, +} + +trait Get<'a, const N: &'static str> { + //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + type Target: 'a; + + fn get(&'a self) -> &'a Self::Target; +} + +impl Foo { + fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + where + Self: Get<'a, N>, + { + self.get() + } +} + +impl<'a> Get<'a, "int"> for Foo { + type Target = i32; + + fn get(&'a self) -> &'a Self::Target { + &self.i + } +} + +fn main() { + let foo = Foo { i: 123 }; + assert_eq!(foo.ask::<"int">(), &123); +} diff --git a/tests/ui/const-generics/type-dependent/issue-71382.rs b/tests/ui/const-generics/type-dependent/issue-71382.rs new file mode 100644 index 000000000..1c4073e36 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71382.rs @@ -0,0 +1,21 @@ +struct Test; + +fn pass() -> u8 { + 42 +} + +impl Test { + pub fn call_me(&self) -> u8 { + self.test::() + } + + fn test u8>(&self) -> u8 { + //~^ ERROR using function pointers as const generic parameters is forbidden + FN() + } +} + +fn main() { + let x = Test; + assert_eq!(x.call_me(), 42); +} diff --git a/tests/ui/const-generics/type-dependent/issue-71382.stderr b/tests/ui/const-generics/type-dependent/issue-71382.stderr new file mode 100644 index 000000000..ad522aead --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71382.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71382.rs:12:23 + | +LL | fn test u8>(&self) -> u8 { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/type-dependent/issue-71805.rs b/tests/ui/const-generics/type-dependent/issue-71805.rs new file mode 100644 index 000000000..060b89964 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71805.rs @@ -0,0 +1,38 @@ +// run-pass +use std::mem::MaybeUninit; + +trait CollectSlice<'a>: Iterator { + fn inner_array(&mut self) -> [Self::Item; N]; + + fn collect_array(&mut self) -> [Self::Item; N] { + let result = self.inner_array(); + assert!(self.next().is_none()); + result + } +} + +impl<'a, I: ?Sized> CollectSlice<'a> for I +where + I: Iterator, +{ + fn inner_array(&mut self) -> [Self::Item; N] { + let mut result: [MaybeUninit; N] = + unsafe { MaybeUninit::uninit().assume_init() }; + + let mut count = 0; + for (dest, item) in result.iter_mut().zip(self) { + *dest = MaybeUninit::new(item); + count += 1; + } + + assert_eq!(N, count); + + let temp_ptr: *const [MaybeUninit; N] = &result; + unsafe { std::ptr::read(temp_ptr as *const [Self::Item; N]) } + } +} + +fn main() { + let mut foos = [0u64; 9].iter().cloned(); + let _bar: [u64; 9] = foos.collect_array::<9_usize>(); +} diff --git a/tests/ui/const-generics/type-dependent/issue-73730.rs b/tests/ui/const-generics/type-dependent/issue-73730.rs new file mode 100644 index 000000000..5e1b8c635 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-73730.rs @@ -0,0 +1,14 @@ +// check-pass +trait Foo<'a, A>: Iterator { + fn bar(&mut self) -> *const [A; N]; +} + +impl<'a, A, I: ?Sized> Foo<'a, A> for I where I: Iterator { + fn bar(&mut self) -> *const [A; N] { + std::ptr::null() + } +} + +fn main() { + (0_u8 .. 10).bar::<10_usize>(); +} diff --git a/tests/ui/const-generics/type-dependent/non-local.rs b/tests/ui/const-generics/type-dependent/non-local.rs new file mode 100644 index 000000000..b755de30b --- /dev/null +++ b/tests/ui/const-generics/type-dependent/non-local.rs @@ -0,0 +1,21 @@ +// aux-build:type_dependent_lib.rs +// run-pass +extern crate type_dependent_lib; + +use type_dependent_lib::*; + +fn main() { + let s = Struct::<42>::new(); + assert_eq!(s.same_ty::<7>(), (42, 7)); + assert_eq!(s.different_ty::<19>(), (42, 19)); + assert_eq!(Struct::<1337>::new().different_ty::<96>(), (1337, 96)); + assert_eq!( + Struct::<18>::new() + .we_have_to_go_deeper::<19>() + .containing_ty::, 3>(), + (27, 3), + ); + + let s = Struct::<7>::new(); + assert_eq!(s.foo::<18>(), 18); +} diff --git a/tests/ui/const-generics/type-dependent/qpath.rs b/tests/ui/const-generics/type-dependent/qpath.rs new file mode 100644 index 000000000..2d678d0ac --- /dev/null +++ b/tests/ui/const-generics/type-dependent/qpath.rs @@ -0,0 +1,9 @@ +// run-pass +struct A; +impl A { + fn foo() -> usize { N + 1 } +} + +fn main() { + assert_eq!(A::foo::<7>(), 8); +} diff --git a/tests/ui/const-generics/type-dependent/simple.rs b/tests/ui/const-generics/type-dependent/simple.rs new file mode 100644 index 000000000..1b13133b5 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/simple.rs @@ -0,0 +1,9 @@ +// run-pass +struct R; + +impl R { + fn method(&self) -> u8 { N } +} +fn main() { + assert_eq!(R.method::<1u8>(), 1); +} diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr new file mode 100644 index 000000000..70bc64057 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/type-mismatch.full.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:8:27 + | +LL | assert_eq!(R.method::<1u16>(), 1); + | ^^^^ expected `u8`, found `u16` + | +help: change the type of the numeric literal from `u16` to `u8` + | +LL | assert_eq!(R.method::<1u8>(), 1); + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr new file mode 100644 index 000000000..70bc64057 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/type-mismatch.min.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:8:27 + | +LL | assert_eq!(R.method::<1u16>(), 1); + | ^^^^ expected `u8`, found `u16` + | +help: change the type of the numeric literal from `u16` to `u8` + | +LL | assert_eq!(R.method::<1u8>(), 1); + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type-dependent/type-mismatch.rs b/tests/ui/const-generics/type-dependent/type-mismatch.rs new file mode 100644 index 000000000..3335ab870 --- /dev/null +++ b/tests/ui/const-generics/type-dependent/type-mismatch.rs @@ -0,0 +1,10 @@ +// revisions: full min +struct R; + +impl R { + fn method(&self) -> u8 { N } +} +fn main() { + assert_eq!(R.method::<1u16>(), 1); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs new file mode 100644 index 000000000..4a7534e37 --- /dev/null +++ b/tests/ui/const-generics/type_mismatch.rs @@ -0,0 +1,9 @@ +fn foo() -> [u8; N] { + bar::() //~ ERROR mismatched types +} + +fn bar() -> [u8; N] {} +//~^ ERROR mismatched types +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr new file mode 100644 index 000000000..8d779bee2 --- /dev/null +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::() + | ^ expected `u8`, found `usize` + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:26 + | +LL | fn bar() -> [u8; N] {} + | --- ^^^^^^^ expected array `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:31 + | +LL | fn bar() -> [u8; N] {} + | ^ expected `usize`, found `u8` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type_not_in_scope.rs b/tests/ui/const-generics/type_not_in_scope.rs new file mode 100644 index 000000000..593370180 --- /dev/null +++ b/tests/ui/const-generics/type_not_in_scope.rs @@ -0,0 +1,11 @@ +impl X { + //~^ ERROR cannot find type + fn getn() -> [u8; N] { + getn::() + } +} +fn getn() -> [u8; N] {} +//~^ ERROR expected type, found built-in attribute `cfg_attr` +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/const-generics/type_not_in_scope.stderr b/tests/ui/const-generics/type_not_in_scope.stderr new file mode 100644 index 000000000..16796acb3 --- /dev/null +++ b/tests/ui/const-generics/type_not_in_scope.stderr @@ -0,0 +1,24 @@ +error[E0412]: cannot find type `X` in this scope + --> $DIR/type_not_in_scope.rs:1:6 + | +LL | impl X { + | ^ not found in this scope + +error[E0573]: expected type, found built-in attribute `cfg_attr` + --> $DIR/type_not_in_scope.rs:7:18 + | +LL | fn getn() -> [u8; N] {} + | ^^^^^^^^ not a type + +error[E0308]: mismatched types + --> $DIR/type_not_in_scope.rs:7:33 + | +LL | fn getn() -> [u8; N] {} + | ---- ^^^^^^^ expected array `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0412, E0573. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/type_of_anon_const.rs b/tests/ui/const-generics/type_of_anon_const.rs new file mode 100644 index 000000000..fb0d688a8 --- /dev/null +++ b/tests/ui/const-generics/type_of_anon_const.rs @@ -0,0 +1,17 @@ +// run-pass +trait T { + fn l() -> usize; + fn r() -> bool; +} + +struct S; + +impl T for S { + fn l() -> usize { N } + fn r() -> bool { M } +} + +fn main() { + assert_eq!(>::l::(), 123); + assert!(>::r::()); +} diff --git a/tests/ui/const-generics/types-mismatch-const-args.full.stderr b/tests/ui/const-generics/types-mismatch-const-args.full.stderr new file mode 100644 index 000000000..b6a22df74 --- /dev/null +++ b/tests/ui/const-generics/types-mismatch-const-args.full.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:14:41 + | +LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` + | + = note: expected constant `2` + found constant `4` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:16:41 + | +LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, _, _>` + found struct `A<'b, u32, _, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:18:41 + | +LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, 4, _>` + found struct `A<'b, u32, 2, _>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/types-mismatch-const-args.min.stderr b/tests/ui/const-generics/types-mismatch-const-args.min.stderr new file mode 100644 index 000000000..6ac93a08d --- /dev/null +++ b/tests/ui/const-generics/types-mismatch-const-args.min.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:14:41 + | +LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` + | | + | expected due to this + | + = note: expected struct `A<'_, _, 2, _>` + found struct `A<'_, _, 4, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:16:41 + | +LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, _, _>` + found struct `A<'b, u32, _, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:18:41 + | +LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32` + | | + | expected due to this + | + = note: expected struct `A<'a, u16, 4, _>` + found struct `A<'b, u32, 2, _>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/types-mismatch-const-args.rs b/tests/ui/const-generics/types-mismatch-const-args.rs new file mode 100644 index 000000000..43ef28b26 --- /dev/null +++ b/tests/ui/const-generics/types-mismatch-const-args.rs @@ -0,0 +1,22 @@ +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +// tests the diagnostic output of type mismatches for types that have const generics arguments. + +use std::marker::PhantomData; + +struct A<'a, T, const X: u32, const Y: u32> { + data: PhantomData<&'a T> +} + +fn a<'a, 'b>() { + let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types + let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types + let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types +} + +pub fn main() {} diff --git a/tests/ui/const-generics/unify_with_nested_expr.rs b/tests/ui/const-generics/unify_with_nested_expr.rs new file mode 100644 index 000000000..1271e0902 --- /dev/null +++ b/tests/ui/const-generics/unify_with_nested_expr.rs @@ -0,0 +1,18 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo() +where + [(); N + 1 + 1]:, +{ + bar(); + //~^ ERROR: type annotations +} + +fn bar() +where + [(); N + 1]:, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/unify_with_nested_expr.stderr b/tests/ui/const-generics/unify_with_nested_expr.stderr new file mode 100644 index 000000000..8bab0dff7 --- /dev/null +++ b/tests/ui/const-generics/unify_with_nested_expr.stderr @@ -0,0 +1,22 @@ +error[E0284]: type annotations needed + --> $DIR/unify_with_nested_expr.rs:8:5 + | +LL | bar(); + | ^^^ cannot infer the value of the const parameter `N` declared on the function `bar` + | +note: required by a bound in `bar` + --> $DIR/unify_with_nested_expr.rs:14:10 + | +LL | fn bar() + | --- required by a bound in this +LL | where +LL | [(); N + 1]:, + | ^^^^^ required by this bound in `bar` +help: consider specifying the generic argument + | +LL | bar::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/uninferred-consts-during-codegen-1.rs b/tests/ui/const-generics/uninferred-consts-during-codegen-1.rs new file mode 100644 index 000000000..c7270e835 --- /dev/null +++ b/tests/ui/const-generics/uninferred-consts-during-codegen-1.rs @@ -0,0 +1,15 @@ +// run-pass + +use std::fmt; + +struct Array([T; N]); + +impl fmt::Debug for Array { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.0.iter()).finish() + } +} + +fn main() { + assert_eq!(format!("{:?}", Array([1, 2, 3])), "[1, 2, 3]"); +} diff --git a/tests/ui/const-generics/uninferred-consts-during-codegen-2.rs b/tests/ui/const-generics/uninferred-consts-during-codegen-2.rs new file mode 100644 index 000000000..191caa78f --- /dev/null +++ b/tests/ui/const-generics/uninferred-consts-during-codegen-2.rs @@ -0,0 +1,15 @@ +// run-pass + +use std::fmt; + +struct Array(T); + +impl fmt::Debug for Array<[T; N]> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries((&self.0 as &[T]).iter()).finish() + } +} + +fn main() { + assert_eq!(format!("{:?}", Array([1, 2, 3])), "[1, 2, 3]"); +} diff --git a/tests/ui/const-generics/unknown_adt.rs b/tests/ui/const-generics/unknown_adt.rs new file mode 100644 index 000000000..8cdd28a8c --- /dev/null +++ b/tests/ui/const-generics/unknown_adt.rs @@ -0,0 +1,4 @@ +fn main() { + let _: UnknownStruct<7>; + //~^ ERROR cannot find type `UnknownStruct` +} diff --git a/tests/ui/const-generics/unknown_adt.stderr b/tests/ui/const-generics/unknown_adt.stderr new file mode 100644 index 000000000..0f462dd47 --- /dev/null +++ b/tests/ui/const-generics/unknown_adt.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `UnknownStruct` in this scope + --> $DIR/unknown_adt.rs:2:12 + | +LL | let _: UnknownStruct<7>; + | ^^^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/unused-const-param.rs b/tests/ui/const-generics/unused-const-param.rs new file mode 100644 index 000000000..c7f74cfac --- /dev/null +++ b/tests/ui/const-generics/unused-const-param.rs @@ -0,0 +1,5 @@ +// check-pass + +struct A; // ok + +fn main() {} diff --git a/tests/ui/const-generics/unused-type-param-suggestion.rs b/tests/ui/const-generics/unused-type-param-suggestion.rs new file mode 100644 index 000000000..2251512c4 --- /dev/null +++ b/tests/ui/const-generics/unused-type-param-suggestion.rs @@ -0,0 +1,4 @@ +#![crate_type="lib"] + +struct Example; +//~^ ERROR parameter diff --git a/tests/ui/const-generics/unused-type-param-suggestion.stderr b/tests/ui/const-generics/unused-type-param-suggestion.stderr new file mode 100644 index 000000000..807065ca1 --- /dev/null +++ b/tests/ui/const-generics/unused-type-param-suggestion.stderr @@ -0,0 +1,12 @@ +error[E0392]: parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:3:16 + | +LL | struct Example; + | ^ unused parameter + | + = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `N` to be a const parameter, use `const N: usize` instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/unused_braces.fixed b/tests/ui/const-generics/unused_braces.fixed new file mode 100644 index 000000000..4c1926387 --- /dev/null +++ b/tests/ui/const-generics/unused_braces.fixed @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +#![warn(unused_braces)] + +macro_rules! make_1 { + () => { + 1 + } +} + +struct A; + +fn main() { + let _: A<7>; // ok + let _: A<7>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok + let _: A<{make_1!()}>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.full.fixed b/tests/ui/const-generics/unused_braces.full.fixed new file mode 100644 index 000000000..46d57e0dc --- /dev/null +++ b/tests/ui/const-generics/unused_braces.full.fixed @@ -0,0 +1,16 @@ +// check-pass +// run-rustfix +// revisions: full min + +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![warn(unused_braces)] + + +struct A; + +fn main() { + let _: A<7>; // ok + let _: A<7>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.min.fixed b/tests/ui/const-generics/unused_braces.min.fixed new file mode 100644 index 000000000..46d57e0dc --- /dev/null +++ b/tests/ui/const-generics/unused_braces.min.fixed @@ -0,0 +1,16 @@ +// check-pass +// run-rustfix +// revisions: full min + +#![cfg_attr(full, feature(const_generics))] +#![cfg_attr(full, allow(incomplete_features))] +#![warn(unused_braces)] + + +struct A; + +fn main() { + let _: A<7>; // ok + let _: A<7>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.rs b/tests/ui/const-generics/unused_braces.rs new file mode 100644 index 000000000..e9f15b401 --- /dev/null +++ b/tests/ui/const-generics/unused_braces.rs @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +#![warn(unused_braces)] + +macro_rules! make_1 { + () => { + 1 + } +} + +struct A; + +fn main() { + let _: A<7>; // ok + let _: A<{ 7 }>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok + let _: A<{make_1!()}>; // ok +} diff --git a/tests/ui/const-generics/unused_braces.stderr b/tests/ui/const-generics/unused_braces.stderr new file mode 100644 index 000000000..2c8031c43 --- /dev/null +++ b/tests/ui/const-generics/unused_braces.stderr @@ -0,0 +1,19 @@ +warning: unnecessary braces around const expression + --> $DIR/unused_braces.rs:15:14 + | +LL | let _: A<{ 7 }>; + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:3:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - let _: A<{ 7 }>; +LL + let _: A<7>; + | + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/where-clauses.rs b/tests/ui/const-generics/where-clauses.rs new file mode 100644 index 000000000..aa3ca1cf6 --- /dev/null +++ b/tests/ui/const-generics/where-clauses.rs @@ -0,0 +1,30 @@ +// check-pass +trait Bar { fn bar() {} } +trait Foo: Bar {} + +fn test() where T: Foo { + >::bar(); +} + +struct Faz; + +impl Faz { + fn test() where T: Foo { + >::bar() + } +} + +trait Fiz { + fn fiz() where T: Foo { + >::bar(); + } +} + +impl Bar for u8 {} +impl Foo for u8 {} +impl Fiz for u8 {} +fn main() { + test::(); + Faz::<3>::test::(); + >::fiz::(); +} diff --git a/tests/ui/const-ptr/allowed_slices.rs b/tests/ui/const-ptr/allowed_slices.rs new file mode 100644 index 000000000..3f19cd4d8 --- /dev/null +++ b/tests/ui/const-ptr/allowed_slices.rs @@ -0,0 +1,105 @@ +// run-pass +#![feature( + slice_from_ptr_range, + const_slice_from_ptr_range, + pointer_byte_offsets, + const_pointer_byte_offsets +)] +use std::{ + mem::MaybeUninit, + ptr, + slice::{from_ptr_range, from_raw_parts}, +}; + +// Dangling is ok, as long as it's either for ZST reads or for no reads +pub static S0: &[u32] = unsafe { from_raw_parts(dangling(), 0) }; +pub static S1: &[()] = unsafe { from_raw_parts(dangling(), 3) }; + +// References are always valid of reads of a single element (basically `slice::from_ref`) +pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 1) }; +pub static S3: &[MaybeUninit<&u32>] = unsafe { from_raw_parts(&D1, 1) }; + +// Reinterpreting data is fine, as long as layouts match +pub static S4: &[u8] = unsafe { from_raw_parts((&D0) as *const _ as _, 3) }; +// This is only valid because D1 has uninitialized bytes, if it was an initialized pointer, +// that would reinterpret pointers as integers which is UB in CTFE. +pub static S5: &[MaybeUninit] = unsafe { from_raw_parts((&D1) as *const _ as _, 2) }; +// Even though u32 and [bool; 4] have different layouts, D0 has a value that +// is valid as [bool; 4], so this is not UB (it's basically a transmute) +pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; + +// Structs are considered single allocated objects, +// as long as you don't reinterpret padding as initialized +// data everything is ok. +pub static S7: &[u16] = unsafe { + let ptr = (&D2 as *const Struct as *const u16).byte_add(4); + + from_raw_parts(ptr, 3) +}; +pub static S8: &[MaybeUninit] = unsafe { + let ptr = &D2 as *const Struct as *const MaybeUninit; + + from_raw_parts(ptr, 6) +}; + +pub static R0: &[u32] = unsafe { from_ptr_range(dangling()..dangling()) }; +// from_ptr_range panics on zst +//pub static R1: &[()] = unsafe { from_ptr_range(dangling(), dangling().byte_add(3)) }; +pub static R2: &[u32] = unsafe { + let ptr = &D0 as *const u32; + from_ptr_range(ptr..ptr.add(1)) +}; +pub static R3: &[MaybeUninit<&u32>] = unsafe { + let ptr = &D1 as *const MaybeUninit<&u32>; + from_ptr_range(ptr..ptr.add(1)) +}; +pub static R4: &[u8] = unsafe { + let ptr = &D0 as *const u32 as *const u8; + from_ptr_range(ptr..ptr.add(3)) +}; +pub static R5: &[MaybeUninit] = unsafe { + let ptr = &D1 as *const MaybeUninit<&u32> as *const MaybeUninit; + from_ptr_range(ptr..ptr.add(2)) +}; +pub static R6: &[bool] = unsafe { + let ptr = &D0 as *const u32 as *const bool; + from_ptr_range(ptr..ptr.add(4)) +}; +pub static R7: &[u16] = unsafe { + let d2 = &D2; + let l = &d2.b as *const u32 as *const u16; + let r = &d2.d as *const u8 as *const u16; + + from_ptr_range(l..r) +}; +pub static R8: &[MaybeUninit] = unsafe { + let d2 = &D2; + let l = d2 as *const Struct as *const MaybeUninit; + let r = &d2.d as *const u8 as *const MaybeUninit; + + from_ptr_range(l..r) +}; + +// Using valid slice is always valid +pub static R9: &[u32] = unsafe { from_ptr_range(R0.as_ptr_range()) }; +pub static R10: &[u32] = unsafe { from_ptr_range(R2.as_ptr_range()) }; + +const D0: u32 = (1 << 16) | 1; +const D1: MaybeUninit<&u32> = MaybeUninit::uninit(); +const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 }; + +const fn dangling() -> *const T { + ptr::NonNull::dangling().as_ptr() as _ +} + +#[repr(C)] +struct Struct { + a: u8, + // _pad: [MaybeUninit; 3] + b: u32, + c: u16, + d: u8, + // _pad: [MaybeUninit; 1] +} + +fn main() {} diff --git a/tests/ui/const-ptr/forbidden_slices.rs b/tests/ui/const-ptr/forbidden_slices.rs new file mode 100644 index 000000000..192b6a46d --- /dev/null +++ b/tests/ui/const-ptr/forbidden_slices.rs @@ -0,0 +1,98 @@ +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "alloc\d+" -> "allocN" +// error-pattern: could not evaluate static initializer +#![feature( + slice_from_ptr_range, + const_slice_from_ptr_range, + pointer_byte_offsets, + const_pointer_byte_offsets +)] +use std::{ + mem::{size_of, MaybeUninit}, + ptr, + slice::{from_ptr_range, from_raw_parts}, +}; + +// Null is never valid for reads +pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) }; +pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) }; + +// Out of bounds +pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) }; + +// Reading uninitialized data +pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; //~ ERROR: it is undefined behavior to use this value +// Reinterpret pointers as integers (UB in CTFE.) +pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; //~ ERROR: it is undefined behavior to use this value +// Layout mismatch +pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; //~ ERROR: it is undefined behavior to use this value + +// Reading padding is not ok +pub static S7: &[u16] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D2 as *const Struct as *const u16).add(1); + + from_raw_parts(ptr, 4) +}; + +// Unaligned read +pub static S8: &[u64] = unsafe { + let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::(); + + from_raw_parts(ptr, 1) +}; + +pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; +pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; +pub static R2: &[u32] = unsafe { + let ptr = &D0 as *const u32; + from_ptr_range(ptr..ptr.add(2)) +}; +pub static R4: &[u8] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D1) as *const MaybeUninit<&u32> as *const u8; + from_ptr_range(ptr..ptr.add(1)) +}; +pub static R5: &[u8] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = &D3 as *const &u32; + from_ptr_range(ptr.cast()..ptr.add(1).cast()) +}; +pub static R6: &[bool] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = &D0 as *const u32 as *const bool; + from_ptr_range(ptr..ptr.add(4)) +}; +pub static R7: &[u16] = unsafe { + let ptr = (&D2 as *const Struct as *const u16).byte_add(1); + from_ptr_range(ptr..ptr.add(4)) //~ inside `R7` +}; +pub static R8: &[u64] = unsafe { + let ptr = (&D4 as *const [u32; 2] as *const u32).byte_add(1).cast::(); + from_ptr_range(ptr..ptr.add(1)) //~ inside `R8` +}; + +// This is sneaky: &D0 and &D0 point to different objects +// (even if at runtime they have the same address) +pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) }; +pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) }; + +const D0: u32 = 0x11111111; // Constant chosen for endianness-independent behavior. +const D1: MaybeUninit<&u32> = MaybeUninit::uninit(); +const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 }; +const D3: &u32 = &42; +const D4: [u32; 2] = [17, 42]; + +#[repr(C)] +struct Struct { + a: u8, + // _pad: [MaybeUninit; 3] + b: u32, + c: u16, + d: u8, + // _pad: [MaybeUninit; 1] +} + +fn main() {} diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr new file mode 100644 index 000000000..b42361872 --- /dev/null +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -0,0 +1,240 @@ +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL + | + = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) + | +note: inside `std::slice::from_raw_parts::<'_, u32>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `S0` + --> $DIR/forbidden_slices.rs:19:34 + | +LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL + | + = note: dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance) + | +note: inside `std::slice::from_raw_parts::<'_, ()>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `S1` + --> $DIR/forbidden_slices.rs:20:33 + | +LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL + | + = note: dereferencing pointer failed: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + | +note: inside `std::slice::from_raw_parts::<'_, u32>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `S2` + --> $DIR/forbidden_slices.rs:23:34 + | +LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) }; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:26:1 + | +LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:28:1 + | +LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) }; + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:30:1 + | +LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:33:1 + | +LL | pub static S7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[1]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL + | + = note: dereferencing pointer failed: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds + | +note: inside `std::slice::from_raw_parts::<'_, u64>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `S8` + --> $DIR/forbidden_slices.rs:44:5 + | +LL | from_raw_parts(ptr, 1) + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) + | +note: inside `ptr::const_ptr::::sub_ptr` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `from_ptr_range::<'_, u32>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `R0` + --> $DIR/forbidden_slices.rs:47:34 + | +LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | +note: inside `ptr::const_ptr::::sub_ptr` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `from_ptr_range::<'_, ()>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `R1` + --> $DIR/forbidden_slices.rs:48:33 + | +LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: allocN has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `ptr::const_ptr::::add` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `R2` + --> $DIR/forbidden_slices.rs:51:25 + | +LL | from_ptr_range(ptr..ptr.add(2)) + | ^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:53:1 + | +LL | pub static R4: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:58:1 + | +LL | pub static R5: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/forbidden_slices.rs:63:1 + | +LL | pub static R6: &[bool] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL + | + = note: accessing memory with alignment 1, but alignment 2 is required + | +note: inside `std::slice::from_raw_parts::<'_, u16>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `from_ptr_range::<'_, u16>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `R7` + --> $DIR/forbidden_slices.rs:70:5 + | +LL | from_ptr_range(ptr..ptr.add(4)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: allocN has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `ptr::const_ptr::::add` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `R8` + --> $DIR/forbidden_slices.rs:74:25 + | +LL | from_ptr_range(ptr..ptr.add(1)) + | ^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: `ptr_offset_from_unsigned` called on pointers into different allocations + | +note: inside `ptr::const_ptr::::sub_ptr` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `from_ptr_range::<'_, u32>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `R9` + --> $DIR/forbidden_slices.rs:79:34 + | +LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: `ptr_offset_from_unsigned` called on pointers into different allocations + | +note: inside `ptr::const_ptr::::sub_ptr` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `from_ptr_range::<'_, u32>` + --> $SRC_DIR/core/src/slice/raw.rs:LL:COL +note: inside `R10` + --> $DIR/forbidden_slices.rs:80:35 + | +LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-ptr/out_of_bounds_read.rs b/tests/ui/const-ptr/out_of_bounds_read.rs new file mode 100644 index 000000000..9dd669180 --- /dev/null +++ b/tests/ui/const-ptr/out_of_bounds_read.rs @@ -0,0 +1,15 @@ +// error-pattern: evaluation of constant value failed + +#![feature(const_ptr_read)] + +fn main() { + use std::ptr; + + const DATA: [u32; 1] = [42]; + + const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) }; + + const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; +} diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr new file mode 100644 index 000000000..3e7b09a59 --- /dev/null +++ b/tests/ui/const-ptr/out_of_bounds_read.stderr @@ -0,0 +1,46 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | +note: inside `std::ptr::read::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `_READ` + --> $DIR/out_of_bounds_read.rs:12:33 + | +LL | const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | +note: inside `std::ptr::read::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `ptr::const_ptr::::read` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `_CONST_READ` + --> $DIR/out_of_bounds_read.rs:13:39 + | +LL | const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() }; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds + | +note: inside `std::ptr::read::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `ptr::mut_ptr::::read` + --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL +note: inside `_MUT_READ` + --> $DIR/out_of_bounds_read.rs:14:37 + | +LL | const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const_prop/ice-assert-fail-div-by-zero.rs b/tests/ui/const_prop/ice-assert-fail-div-by-zero.rs new file mode 100644 index 000000000..2afbf3432 --- /dev/null +++ b/tests/ui/const_prop/ice-assert-fail-div-by-zero.rs @@ -0,0 +1,14 @@ +// check-pass + +// need to emit MIR, because const prop (which emits `unconditional_panic`) only runs if +// the `optimized_mir` query is run, which it isn't in check-only mode. +// compile-flags: --crate-type lib --emit=mir,link + +#![warn(unconditional_panic)] + +pub struct Fixed64(i64); + +// HACK: this test passes only because this is a const fn that is written to metadata +pub const fn div(f: Fixed64) { + f.0 / 0; //~ WARN will panic at runtime +} diff --git a/tests/ui/const_prop/ice-assert-fail-div-by-zero.stderr b/tests/ui/const_prop/ice-assert-fail-div-by-zero.stderr new file mode 100644 index 000000000..865c69c3c --- /dev/null +++ b/tests/ui/const_prop/ice-assert-fail-div-by-zero.stderr @@ -0,0 +1,14 @@ +warning: this operation will panic at runtime + --> $DIR/ice-assert-fail-div-by-zero.rs:13:5 + | +LL | f.0 / 0; + | ^^^^^^^ attempt to divide `_` by zero + | +note: the lint level is defined here + --> $DIR/ice-assert-fail-div-by-zero.rs:7:9 + | +LL | #![warn(unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/const_prop/inline_spans.rs b/tests/ui/const_prop/inline_spans.rs new file mode 100644 index 000000000..504f27811 --- /dev/null +++ b/tests/ui/const_prop/inline_spans.rs @@ -0,0 +1,15 @@ +// build-pass +// compile-flags: -Zmir-opt-level=3 +// Overflow can't be detected by const prop +// could only be detected after optimizations + +#![deny(warnings)] + +fn main() { + let _ = add(u8::MAX, 1); +} + +#[inline(always)] +fn add(x: u8, y: u8) -> u8 { + x + y +} diff --git a/tests/ui/const_prop/inline_spans_lint_attribute.rs b/tests/ui/const_prop/inline_spans_lint_attribute.rs new file mode 100644 index 000000000..1db53d771 --- /dev/null +++ b/tests/ui/const_prop/inline_spans_lint_attribute.rs @@ -0,0 +1,15 @@ +// Must be build-pass, because check-pass will not run const prop and thus not emit the lint anyway. +// build-pass +// compile-flags: -Zmir-opt-level=3 + +#![deny(warnings)] + +fn main() { + #[allow(arithmetic_overflow)] + let _ = add(u8::MAX, 1); +} + +#[inline(always)] +fn add(x: u8, y: u8) -> u8 { + x + y +} diff --git a/tests/ui/const_prop/issue-102553.rs b/tests/ui/const_prop/issue-102553.rs new file mode 100644 index 000000000..523a9d7ac --- /dev/null +++ b/tests/ui/const_prop/issue-102553.rs @@ -0,0 +1,24 @@ +// compile-flags: --crate-type=lib +// check-pass + +pub trait Widget { + fn boxed<'w>(self) -> Box + 'w> + where + Self: Sized + 'w; +} + +pub trait WidgetDyn {} + +impl WidgetDyn for T where T: Widget {} + +impl Widget for dyn WidgetDyn + '_ { + fn boxed<'w>(self) -> Box + 'w> + where + Self: Sized + 'w, + { + // Even though this is illegal to const evaluate, this should never + // trigger an ICE because it can never be called from actual code + // (due to the trivially false where-clause predicate). + Box::new(self) + } +} diff --git a/tests/ui/constructor-lifetime-args.rs b/tests/ui/constructor-lifetime-args.rs new file mode 100644 index 000000000..a824a44c9 --- /dev/null +++ b/tests/ui/constructor-lifetime-args.rs @@ -0,0 +1,26 @@ +// All lifetime parameters in struct constructors are currently considered early bound, +// i.e., `S::` is interpreted kinda like an associated item `S::::ctor`. +// This behavior is a bit weird, because if equivalent constructor were written manually +// it would get late bound lifetime parameters. +// Variant constructors behave in the same way, lifetime parameters are considered +// belonging to the enum and being early bound. +// https://github.com/rust-lang/rust/issues/30904 + +struct S<'a, 'b>(&'a u8, &'b u8); +enum E<'a, 'b> { + V(&'a u8), + U(&'b u8), +} + +fn main() { + S(&0, &0); // OK + S::<'static>(&0, &0); + //~^ ERROR this struct takes 2 lifetime arguments + S::<'static, 'static, 'static>(&0, &0); + //~^ ERROR this struct takes 2 lifetime arguments + E::V(&0); // OK + E::V::<'static>(&0); + //~^ ERROR this enum takes 2 lifetime arguments + E::V::<'static, 'static, 'static>(&0); + //~^ ERROR this enum takes 2 lifetime arguments +} diff --git a/tests/ui/constructor-lifetime-args.stderr b/tests/ui/constructor-lifetime-args.stderr new file mode 100644 index 000000000..bc1141b16 --- /dev/null +++ b/tests/ui/constructor-lifetime-args.stderr @@ -0,0 +1,67 @@ +error[E0107]: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/constructor-lifetime-args.rs:17:5 + | +LL | S::<'static>(&0, &0); + | ^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: struct defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/constructor-lifetime-args.rs:9:8 + | +LL | struct S<'a, 'b>(&'a u8, &'b u8); + | ^ -- -- +help: add missing lifetime argument + | +LL | S::<'static, 'static>(&0, &0); + | +++++++++ + +error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied + --> $DIR/constructor-lifetime-args.rs:19:5 + | +LL | S::<'static, 'static, 'static>(&0, &0); + | ^ ------- help: remove this lifetime argument + | | + | expected 2 lifetime arguments + | +note: struct defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/constructor-lifetime-args.rs:9:8 + | +LL | struct S<'a, 'b>(&'a u8, &'b u8); + | ^ -- -- + +error[E0107]: this enum takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/constructor-lifetime-args.rs:22:8 + | +LL | E::V::<'static>(&0); + | ^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: enum defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/constructor-lifetime-args.rs:10:6 + | +LL | enum E<'a, 'b> { + | ^ -- -- +help: add missing lifetime argument + | +LL | E::V::<'static, 'static>(&0); + | +++++++++ + +error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied + --> $DIR/constructor-lifetime-args.rs:24:8 + | +LL | E::V::<'static, 'static, 'static>(&0); + | ^ ------- help: remove this lifetime argument + | | + | expected 2 lifetime arguments + | +note: enum defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/constructor-lifetime-args.rs:10:6 + | +LL | enum E<'a, 'b> { + | ^ -- -- + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/consts/array-literal-index-oob.rs b/tests/ui/consts/array-literal-index-oob.rs new file mode 100644 index 000000000..67b49b1ba --- /dev/null +++ b/tests/ui/consts/array-literal-index-oob.rs @@ -0,0 +1,9 @@ +// build-pass +// ignore-pass (test emits codegen-time warnings and verifies that they are not errors) + +#![warn(unconditional_panic)] + +fn main() { + &{ [1, 2, 3][4] }; + //~^ WARN operation will panic +} diff --git a/tests/ui/consts/array-literal-index-oob.stderr b/tests/ui/consts/array-literal-index-oob.stderr new file mode 100644 index 000000000..54bf3af81 --- /dev/null +++ b/tests/ui/consts/array-literal-index-oob.stderr @@ -0,0 +1,14 @@ +warning: this operation will panic at runtime + --> $DIR/array-literal-index-oob.rs:7:8 + | +LL | &{ [1, 2, 3][4] }; + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + | +note: the lint level is defined here + --> $DIR/array-literal-index-oob.rs:4:9 + | +LL | #![warn(unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/consts/array-to-slice-cast.rs b/tests/ui/consts/array-to-slice-cast.rs new file mode 100644 index 000000000..796f9d1b7 --- /dev/null +++ b/tests/ui/consts/array-to-slice-cast.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +const fn foo() { + let x = [1, 2, 3, 4, 5]; + let y: &[_] = &x; + + struct Foo(bool, T); + + let x: Foo<[u8; 3]> = Foo(true, [1, 2, 3]); + let y: &Foo<[u8]> = &x; +} diff --git a/tests/ui/consts/assert-type-intrinsics.rs b/tests/ui/consts/assert-type-intrinsics.rs new file mode 100644 index 000000000..b4fd423be --- /dev/null +++ b/tests/ui/consts/assert-type-intrinsics.rs @@ -0,0 +1,23 @@ +#![feature(never_type)] +#![feature(const_assert_type2)] +#![feature(core_intrinsics)] + +use std::intrinsics; + +#[allow(invalid_value)] +fn main() { + use std::mem::MaybeUninit; + + const _BAD1: () = unsafe { + MaybeUninit::::uninit().assume_init(); + //~^ERROR: evaluation of constant value failed + }; + const _BAD2: () = { + intrinsics::assert_mem_uninitialized_valid::<&'static i32>(); + //~^ERROR: evaluation of constant value failed + }; + const _BAD3: () = { + intrinsics::assert_zero_valid::<&'static i32>(); + //~^ERROR: evaluation of constant value failed + }; +} diff --git a/tests/ui/consts/assert-type-intrinsics.stderr b/tests/ui/consts/assert-type-intrinsics.stderr new file mode 100644 index 000000000..70aec91e2 --- /dev/null +++ b/tests/ui/consts/assert-type-intrinsics.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/assert-type-intrinsics.rs:12:9 + | +LL | MaybeUninit::::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!` + +error[E0080]: evaluation of constant value failed + --> $DIR/assert-type-intrinsics.rs:16:9 + | +LL | intrinsics::assert_mem_uninitialized_valid::<&'static i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid + +error[E0080]: evaluation of constant value failed + --> $DIR/assert-type-intrinsics.rs:20:9 + | +LL | intrinsics::assert_zero_valid::<&'static i32>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/assoc-const.rs b/tests/ui/consts/assoc-const.rs new file mode 100644 index 000000000..f542f2dcb --- /dev/null +++ b/tests/ui/consts/assoc-const.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_variables)] + +trait Nat { + const VALUE: usize; +} + +struct Zero; +struct Succ(#[allow(unused_tuple_struct_fields)] N); + +impl Nat for Zero { + const VALUE: usize = 0; +} + +impl Nat for Succ { + const VALUE: usize = N::VALUE + 1; +} + +fn main() { + let x: [i32; >>>>::VALUE] = [1, 2, 3, 4]; +} diff --git a/tests/ui/consts/assoc_const_generic_impl.rs b/tests/ui/consts/assoc_const_generic_impl.rs new file mode 100644 index 000000000..3475c862b --- /dev/null +++ b/tests/ui/consts/assoc_const_generic_impl.rs @@ -0,0 +1,19 @@ +// build-fail + +trait ZeroSized: Sized { + const I_AM_ZERO_SIZED: (); + fn requires_zero_size(self); +} + +impl ZeroSized for T { + const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; //~ ERROR evaluation of `::I_AM_ZERO_SIZED` failed + fn requires_zero_size(self) { + let () = Self::I_AM_ZERO_SIZED; + println!("requires_zero_size called"); + } +} + +fn main() { + ().requires_zero_size(); + 42_u32.requires_zero_size(); +} diff --git a/tests/ui/consts/assoc_const_generic_impl.stderr b/tests/ui/consts/assoc_const_generic_impl.stderr new file mode 100644 index 000000000..854b9ce5b --- /dev/null +++ b/tests/ui/consts/assoc_const_generic_impl.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `::I_AM_ZERO_SIZED` failed + --> $DIR/assoc_const_generic_impl.rs:9:34 + | +LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4 + +note: the above error was encountered while instantiating `fn ::requires_zero_size` + --> $DIR/assoc_const_generic_impl.rs:18:5 + | +LL | 42_u32.requires_zero_size(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/associated_const_generic.rs b/tests/ui/consts/associated_const_generic.rs new file mode 100644 index 000000000..dee376cc1 --- /dev/null +++ b/tests/ui/consts/associated_const_generic.rs @@ -0,0 +1,25 @@ +// check-pass + +trait TraitA { + const VALUE: usize; +} + +struct A; +impl TraitA for A { + const VALUE: usize = 1; +} + +trait TraitB { + type MyA: TraitA; + const VALUE: usize = Self::MyA::VALUE; +} + +struct B; +impl TraitB for B { + type MyA = A; +} + +fn main() { + let _ = [0; A::VALUE]; + let _ = [0; B::VALUE]; // Indirectly refers to `A::VALUE` +} diff --git a/tests/ui/consts/async-block.rs b/tests/ui/consts/async-block.rs new file mode 100644 index 000000000..78ec8aea7 --- /dev/null +++ b/tests/ui/consts/async-block.rs @@ -0,0 +1,19 @@ +// gate-test-const_async_blocks + +// edition:2018 +// revisions: with_feature without_feature + +#![feature(rustc_attrs)] +#![cfg_attr(with_feature, feature(const_async_blocks))] + +use std::future::Future; + +// From +const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 }; +//[without_feature]~^ `async` block + +static _FUT: &(dyn Future + Sync) = &async {}; +//[without_feature]~^ `async` block + +#[rustc_error] +fn main() {} //[with_feature]~ fatal error triggered by #[rustc_error] diff --git a/tests/ui/consts/async-block.with_feature.stderr b/tests/ui/consts/async-block.with_feature.stderr new file mode 100644 index 000000000..8c6364aec --- /dev/null +++ b/tests/ui/consts/async-block.with_feature.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/async-block.rs:19:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/async-block.without_feature.stderr b/tests/ui/consts/async-block.without_feature.stderr new file mode 100644 index 000000000..751627c52 --- /dev/null +++ b/tests/ui/consts/async-block.without_feature.stderr @@ -0,0 +1,21 @@ +error[E0658]: `async` blocks are not allowed in constants + --> $DIR/async-block.rs:12:47 + | +LL | const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 }; + | ^^^^^^^^^^^ + | + = note: see issue #85368 for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable + +error[E0658]: `async` blocks are not allowed in statics + --> $DIR/async-block.rs:15:51 + | +LL | static _FUT: &(dyn Future + Sync) = &async {}; + | ^^^^^^^^ + | + = note: see issue #85368 for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/auxiliary/cci_const_block.rs b/tests/ui/consts/auxiliary/cci_const_block.rs new file mode 100644 index 000000000..ad618aab8 --- /dev/null +++ b/tests/ui/consts/auxiliary/cci_const_block.rs @@ -0,0 +1,6 @@ +pub static BLOCK_FN_DEF: fn(usize) -> usize = { + fn foo(a: usize) -> usize { + a + 10 + } + foo +}; diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs new file mode 100644 index 000000000..edc7fa81a --- /dev/null +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] +#![feature(const_closures, const_trait_impl)] +#![allow(incomplete_features)] + +pub const fn test() { + let cl = const || {}; + cl(); +} diff --git a/tests/ui/consts/auxiliary/const_fn_lib.rs b/tests/ui/consts/auxiliary/const_fn_lib.rs new file mode 100644 index 000000000..88cea60e1 --- /dev/null +++ b/tests/ui/consts/auxiliary/const_fn_lib.rs @@ -0,0 +1,22 @@ +// Crate that exports a const fn. Used for testing cross-crate. + +#![crate_type="rlib"] + +pub const fn foo() -> usize { 22 } + +pub const fn bar() -> fn() { + fn x() {} + x +} + +#[inline] +pub const fn bar_inlined() -> fn() { + fn x() {} + x +} + +#[inline(always)] +pub const fn bar_inlined_always() -> fn() { + fn x() {} + x +} diff --git a/tests/ui/consts/auxiliary/external_macro.rs b/tests/ui/consts/auxiliary/external_macro.rs new file mode 100644 index 000000000..d260634c9 --- /dev/null +++ b/tests/ui/consts/auxiliary/external_macro.rs @@ -0,0 +1,14 @@ +#![feature(allow_internal_unstable)] + +// Macro to help ensure CONST_ERR lint errors +// are not silenced in external macros. +// https://github.com/rust-lang/rust/issues/65300 + +#[macro_export] +#[allow_internal_unstable(type_ascription)] +macro_rules! static_assert { + ($test:expr) => { + #[allow(dead_code)] + const _: () = [()][!($test: bool) as usize]; + } +} diff --git a/tests/ui/consts/auxiliary/issue-17718-aux.rs b/tests/ui/consts/auxiliary/issue-17718-aux.rs new file mode 100644 index 000000000..91abdbff8 --- /dev/null +++ b/tests/ui/consts/auxiliary/issue-17718-aux.rs @@ -0,0 +1,10 @@ +use std::sync::atomic; + +pub const C1: usize = 1; +pub const C2: atomic::AtomicUsize = atomic::AtomicUsize::new(0); +pub const C3: fn() = { fn foo() {} foo }; +pub const C4: usize = C1 * C1 + C1 / C1; +pub const C5: &'static usize = &C4; + +pub static S1: usize = 3; +pub static S2: atomic::AtomicUsize = atomic::AtomicUsize::new(0); diff --git a/tests/ui/consts/auxiliary/issue-63226.rs b/tests/ui/consts/auxiliary/issue-63226.rs new file mode 100644 index 000000000..2dc9539ba --- /dev/null +++ b/tests/ui/consts/auxiliary/issue-63226.rs @@ -0,0 +1,14 @@ +pub struct VTable{ + state:extern "C" fn(), +} + +impl VTable{ + pub const fn vtable()->&'static VTable{ + Self::VTABLE + } + + const VTABLE: &'static VTable = + &VTable{state}; +} + +extern "C" fn state() {} diff --git a/tests/ui/consts/auxiliary/promotable_const_fn_lib.rs b/tests/ui/consts/auxiliary/promotable_const_fn_lib.rs new file mode 100644 index 000000000..b1d5440b4 --- /dev/null +++ b/tests/ui/consts/auxiliary/promotable_const_fn_lib.rs @@ -0,0 +1,23 @@ +// Crate that exports a const fn. Used for testing cross-crate. + +#![feature(staged_api, rustc_attrs)] +#![stable(since="1.0.0", feature = "mep")] + +#![crate_type="rlib"] + +#[rustc_promotable] +#[stable(since="1.0.0", feature = "mep")] +#[rustc_const_stable(since="1.0.0", feature = "mep")] +#[inline] +pub const fn foo() -> usize { 22 } + +#[stable(since="1.0.0", feature = "mep")] +pub struct Foo(usize); + +impl Foo { + #[stable(since="1.0.0", feature = "mep")] + #[rustc_const_stable(feature = "mep", since = "1.0.0")] + #[inline] + #[rustc_promotable] + pub const fn foo() -> usize { 22 } +} diff --git a/tests/ui/consts/bswap-const.rs b/tests/ui/consts/bswap-const.rs new file mode 100644 index 000000000..3145c21ac --- /dev/null +++ b/tests/ui/consts/bswap-const.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(core_intrinsics)] + +use std::intrinsics; + +const SWAPPED_U8: u8 = intrinsics::bswap(0x12_u8); +const SWAPPED_U16: u16 = intrinsics::bswap(0x12_34_u16); +const SWAPPED_I32: i32 = intrinsics::bswap(0x12_34_56_78_i32); + +fn main() { + assert_eq!(SWAPPED_U8, 0x12); + assert_eq!(SWAPPED_U16, 0x34_12); + assert_eq!(SWAPPED_I32, 0x78_56_34_12); +} diff --git a/tests/ui/consts/cast-discriminant-zst-enum.rs b/tests/ui/consts/cast-discriminant-zst-enum.rs new file mode 100644 index 000000000..2767f178f --- /dev/null +++ b/tests/ui/consts/cast-discriminant-zst-enum.rs @@ -0,0 +1,45 @@ +// run-pass +// Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to an i32. +use std::hint::black_box; + +#[derive(Copy, Clone)] +enum Nums { + NegOne = -1, +} + +const NEG_ONE_I8: i8 = Nums::NegOne as i8; +const NEG_ONE_I16: i16 = Nums::NegOne as i16; +const NEG_ONE_I32: i32 = Nums::NegOne as i32; +const NEG_ONE_I64: i64 = Nums::NegOne as i64; +const NEG_ONE_I128: i128 = Nums::NegOne as i128; + +fn test_as_arg(n: Nums) { + assert_eq!(-1i8, n as i8); + assert_eq!(-1i16, n as i16); + assert_eq!(-1i32, n as i32); + assert_eq!(-1i64, n as i64); + assert_eq!(-1i128, n as i128); +} + +fn main() { + let kind = Nums::NegOne; + assert_eq!(-1i8, kind as i8); + assert_eq!(-1i16, kind as i16); + assert_eq!(-1i32, kind as i32); + assert_eq!(-1i64, kind as i64); + assert_eq!(-1i128, kind as i128); + + assert_eq!(-1i8, black_box(kind) as i8); + assert_eq!(-1i16, black_box(kind) as i16); + assert_eq!(-1i32, black_box(kind) as i32); + assert_eq!(-1i64, black_box(kind) as i64); + assert_eq!(-1i128, black_box(kind) as i128); + + test_as_arg(Nums::NegOne); + + assert_eq!(-1i8, NEG_ONE_I8); + assert_eq!(-1i16, NEG_ONE_I16); + assert_eq!(-1i32, NEG_ONE_I32); + assert_eq!(-1i64, NEG_ONE_I64); + assert_eq!(-1i128, NEG_ONE_I128); +} diff --git a/tests/ui/consts/chained-constants-stackoverflow.rs b/tests/ui/consts/chained-constants-stackoverflow.rs new file mode 100644 index 000000000..a171567c5 --- /dev/null +++ b/tests/ui/consts/chained-constants-stackoverflow.rs @@ -0,0 +1,356 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/34997 + +pub const CST_1: u32 = 0; +pub const CST_2: u32 = CST_1+1; +pub const CST_3: u32 = CST_2+1; +pub const CST_4: u32 = CST_3+1; +pub const CST_5: u32 = CST_4+1; +pub const CST_6: u32 = CST_5+1; +pub const CST_7: u32 = CST_6+1; +pub const CST_8: u32 = CST_7+1; +pub const CST_9: u32 = CST_8+1; +pub const CST_10: u32 = CST_9+1; +pub const CST_11: u32 = CST_10+1; +pub const CST_12: u32 = CST_11+1; +pub const CST_13: u32 = CST_12+1; +pub const CST_14: u32 = CST_13+1; +pub const CST_15: u32 = CST_14+1; +pub const CST_16: u32 = CST_15+1; +pub const CST_17: u32 = CST_16+1; +pub const CST_18: u32 = CST_17+1; +pub const CST_19: u32 = CST_18+1; +pub const CST_20: u32 = CST_19+1; +pub const CST_21: u32 = CST_20+1; +pub const CST_22: u32 = CST_21+1; +pub const CST_23: u32 = CST_22+1; +pub const CST_24: u32 = CST_23+1; +pub const CST_25: u32 = CST_24+1; +pub const CST_26: u32 = CST_25+1; +pub const CST_27: u32 = CST_26+1; +pub const CST_28: u32 = CST_27+1; +pub const CST_29: u32 = CST_28+1; +pub const CST_30: u32 = CST_29+1; +pub const CST_31: u32 = CST_30+1; +pub const CST_32: u32 = CST_31+1; +pub const CST_33: u32 = CST_32+1; +pub const CST_34: u32 = CST_33+1; +pub const CST_35: u32 = CST_34+1; +pub const CST_36: u32 = CST_35+1; +pub const CST_37: u32 = CST_36+1; +pub const CST_38: u32 = CST_37+1; +pub const CST_39: u32 = CST_38+1; +pub const CST_40: u32 = CST_39+1; +pub const CST_41: u32 = CST_40+1; +pub const CST_42: u32 = CST_41+1; +pub const CST_43: u32 = CST_42+1; +pub const CST_44: u32 = CST_43+1; +pub const CST_45: u32 = CST_44+1; +pub const CST_46: u32 = CST_45+1; +pub const CST_47: u32 = CST_46+1; +pub const CST_48: u32 = CST_47+1; +pub const CST_49: u32 = CST_48+1; +pub const CST_50: u32 = CST_49+1; +pub const CST_51: u32 = CST_50+1; +pub const CST_52: u32 = CST_51+1; +pub const CST_53: u32 = CST_52+1; +pub const CST_54: u32 = CST_53+1; +pub const CST_55: u32 = CST_54+1; +pub const CST_56: u32 = CST_55+1; +pub const CST_57: u32 = CST_56+1; +pub const CST_58: u32 = CST_57+1; +pub const CST_59: u32 = CST_58+1; +pub const CST_60: u32 = CST_59+1; +pub const CST_61: u32 = CST_60+1; +pub const CST_62: u32 = CST_61+1; +pub const CST_63: u32 = CST_62+1; +pub const CST_64: u32 = CST_63+1; +pub const CST_65: u32 = CST_64+1; +pub const CST_66: u32 = CST_65+1; +pub const CST_67: u32 = CST_66+1; +pub const CST_68: u32 = CST_67+1; +pub const CST_69: u32 = CST_68+1; +pub const CST_70: u32 = CST_69+1; +pub const CST_71: u32 = CST_70+1; +pub const CST_72: u32 = CST_71+1; +pub const CST_73: u32 = CST_72+1; +pub const CST_74: u32 = CST_73+1; +pub const CST_75: u32 = CST_74+1; +pub const CST_76: u32 = CST_75+1; +pub const CST_77: u32 = CST_76+1; +pub const CST_78: u32 = CST_77+1; +pub const CST_79: u32 = CST_78+1; +pub const CST_80: u32 = CST_79+1; +pub const CST_81: u32 = CST_80+1; +pub const CST_82: u32 = CST_81+1; +pub const CST_83: u32 = CST_82+1; +pub const CST_84: u32 = CST_83+1; +pub const CST_85: u32 = CST_84+1; +pub const CST_86: u32 = CST_85+1; +pub const CST_87: u32 = CST_86+1; +pub const CST_88: u32 = CST_87+1; +pub const CST_89: u32 = CST_88+1; +pub const CST_90: u32 = CST_89+1; +pub const CST_91: u32 = CST_90+1; +pub const CST_92: u32 = CST_91+1; +pub const CST_93: u32 = CST_92+1; +pub const CST_94: u32 = CST_93+1; +pub const CST_95: u32 = CST_94+1; +pub const CST_96: u32 = CST_95+1; +pub const CST_97: u32 = CST_96+1; +pub const CST_98: u32 = CST_97+1; +pub const CST_99: u32 = CST_98+1; +pub const CST_100: u32 = CST_99+1; +pub const CST_101: u32 = CST_100+1; +pub const CST_102: u32 = CST_101+1; +pub const CST_103: u32 = CST_102+1; +pub const CST_104: u32 = CST_103+1; +pub const CST_105: u32 = CST_104+1; +pub const CST_106: u32 = CST_105+1; +pub const CST_107: u32 = CST_106+1; +pub const CST_108: u32 = CST_107+1; +pub const CST_109: u32 = CST_108+1; +pub const CST_110: u32 = CST_109+1; +pub const CST_111: u32 = CST_110+1; +pub const CST_112: u32 = CST_111+1; +pub const CST_113: u32 = CST_112+1; +pub const CST_114: u32 = CST_113+1; +pub const CST_115: u32 = CST_114+1; +pub const CST_116: u32 = CST_115+1; +pub const CST_117: u32 = CST_116+1; +pub const CST_118: u32 = CST_117+1; +pub const CST_119: u32 = CST_118+1; +pub const CST_120: u32 = CST_119+1; +pub const CST_121: u32 = CST_120+1; +pub const CST_122: u32 = CST_121+1; +pub const CST_123: u32 = CST_122+1; +pub const CST_124: u32 = CST_123+1; +pub const CST_125: u32 = CST_124+1; +pub const CST_126: u32 = CST_125+1; +pub const CST_127: u32 = CST_126+1; +pub const CST_128: u32 = CST_127+1; +pub const CST_129: u32 = CST_128+1; +pub const CST_130: u32 = CST_129+1; +pub const CST_131: u32 = CST_130+1; +pub const CST_132: u32 = CST_131+1; +pub const CST_133: u32 = CST_132+1; +pub const CST_134: u32 = CST_133+1; +pub const CST_135: u32 = CST_134+1; +pub const CST_136: u32 = CST_135+1; +pub const CST_137: u32 = CST_136+1; +pub const CST_138: u32 = CST_137+1; +pub const CST_139: u32 = CST_138+1; +pub const CST_140: u32 = CST_139+1; +pub const CST_141: u32 = CST_140+1; +pub const CST_142: u32 = CST_141+1; +pub const CST_143: u32 = CST_142+1; +pub const CST_144: u32 = CST_143+1; +pub const CST_145: u32 = CST_144+1; +pub const CST_146: u32 = CST_145+1; +pub const CST_147: u32 = CST_146+1; +pub const CST_148: u32 = CST_147+1; +pub const CST_149: u32 = CST_148+1; +pub const CST_150: u32 = CST_149+1; +pub const CST_151: u32 = CST_150+1; +pub const CST_152: u32 = CST_151+1; +pub const CST_153: u32 = CST_152+1; +pub const CST_154: u32 = CST_153+1; +pub const CST_155: u32 = CST_154+1; +pub const CST_156: u32 = CST_155+1; +pub const CST_157: u32 = CST_156+1; +pub const CST_158: u32 = CST_157+1; +pub const CST_159: u32 = CST_158+1; +pub const CST_160: u32 = CST_159+1; +pub const CST_161: u32 = CST_160+1; +pub const CST_162: u32 = CST_161+1; +pub const CST_163: u32 = CST_162+1; +pub const CST_164: u32 = CST_163+1; +pub const CST_165: u32 = CST_164+1; +pub const CST_166: u32 = CST_165+1; +pub const CST_167: u32 = CST_166+1; +pub const CST_168: u32 = CST_167+1; +pub const CST_169: u32 = CST_168+1; +pub const CST_170: u32 = CST_169+1; +pub const CST_171: u32 = CST_170+1; +pub const CST_172: u32 = CST_171+1; +pub const CST_173: u32 = CST_172+1; +pub const CST_174: u32 = CST_173+1; +pub const CST_175: u32 = CST_174+1; +pub const CST_176: u32 = CST_175+1; +pub const CST_177: u32 = CST_176+1; +pub const CST_178: u32 = CST_177+1; +pub const CST_179: u32 = CST_178+1; +pub const CST_180: u32 = CST_179+1; +pub const CST_181: u32 = CST_180+1; +pub const CST_182: u32 = CST_181+1; +pub const CST_183: u32 = CST_182+1; +pub const CST_184: u32 = CST_183+1; +pub const CST_185: u32 = CST_184+1; +pub const CST_186: u32 = CST_185+1; +pub const CST_187: u32 = CST_186+1; +pub const CST_188: u32 = CST_187+1; +pub const CST_189: u32 = CST_188+1; +pub const CST_190: u32 = CST_189+1; +pub const CST_191: u32 = CST_190+1; +pub const CST_192: u32 = CST_191+1; +pub const CST_193: u32 = CST_192+1; +pub const CST_194: u32 = CST_193+1; +pub const CST_195: u32 = CST_194+1; +pub const CST_196: u32 = CST_195+1; +pub const CST_197: u32 = CST_196+1; +pub const CST_198: u32 = CST_197+1; +pub const CST_199: u32 = CST_198+1; +pub const CST_200: u32 = CST_199+1; +pub const CST_201: u32 = CST_200+1; +pub const CST_202: u32 = CST_201+1; +pub const CST_203: u32 = CST_202+1; +pub const CST_204: u32 = CST_203+1; +pub const CST_205: u32 = CST_204+1; +pub const CST_206: u32 = CST_205+1; +pub const CST_207: u32 = CST_206+1; +pub const CST_208: u32 = CST_207+1; +pub const CST_209: u32 = CST_208+1; +pub const CST_210: u32 = CST_209+1; +pub const CST_211: u32 = CST_210+1; +pub const CST_212: u32 = CST_211+1; +pub const CST_213: u32 = CST_212+1; +pub const CST_214: u32 = CST_213+1; +pub const CST_215: u32 = CST_214+1; +pub const CST_216: u32 = CST_215+1; +pub const CST_217: u32 = CST_216+1; +pub const CST_218: u32 = CST_217+1; +pub const CST_219: u32 = CST_218+1; +pub const CST_220: u32 = CST_219+1; +pub const CST_221: u32 = CST_220+1; +pub const CST_222: u32 = CST_221+1; +pub const CST_223: u32 = CST_222+1; +pub const CST_224: u32 = CST_223+1; +pub const CST_225: u32 = CST_224+1; +pub const CST_226: u32 = CST_225+1; +pub const CST_227: u32 = CST_226+1; +pub const CST_228: u32 = CST_227+1; +pub const CST_229: u32 = CST_228+1; +pub const CST_230: u32 = CST_229+1; +pub const CST_231: u32 = CST_230+1; +pub const CST_232: u32 = CST_231+1; +pub const CST_233: u32 = CST_232+1; +pub const CST_234: u32 = CST_233+1; +pub const CST_235: u32 = CST_234+1; +pub const CST_236: u32 = CST_235+1; +pub const CST_237: u32 = CST_236+1; +pub const CST_238: u32 = CST_237+1; +pub const CST_239: u32 = CST_238+1; +pub const CST_240: u32 = CST_239+1; +pub const CST_241: u32 = CST_240+1; +pub const CST_242: u32 = CST_241+1; +pub const CST_243: u32 = CST_242+1; +pub const CST_244: u32 = CST_243+1; +pub const CST_245: u32 = CST_244+1; +pub const CST_246: u32 = CST_245+1; +pub const CST_247: u32 = CST_246+1; +pub const CST_248: u32 = CST_247+1; +pub const CST_249: u32 = CST_248+1; +pub const CST_250: u32 = CST_249+1; +pub const CST_251: u32 = CST_250+1; +pub const CST_252: u32 = CST_251+1; +pub const CST_253: u32 = CST_252+1; +pub const CST_254: u32 = CST_253+1; +pub const CST_255: u32 = CST_254+1; +pub const CST_256: u32 = CST_255+1; +pub const CST_257: u32 = CST_256+1; +pub const CST_258: u32 = CST_257+1; +pub const CST_259: u32 = CST_258+1; +pub const CST_260: u32 = CST_259+1; +pub const CST_261: u32 = CST_260+1; +pub const CST_262: u32 = CST_261+1; +pub const CST_263: u32 = CST_262+1; +pub const CST_264: u32 = CST_263+1; +pub const CST_265: u32 = CST_264+1; +pub const CST_266: u32 = CST_265+1; +pub const CST_267: u32 = CST_266+1; +pub const CST_268: u32 = CST_267+1; +pub const CST_269: u32 = CST_268+1; +pub const CST_270: u32 = CST_269+1; +pub const CST_271: u32 = CST_270+1; +pub const CST_272: u32 = CST_271+1; +pub const CST_273: u32 = CST_272+1; +pub const CST_274: u32 = CST_273+1; +pub const CST_275: u32 = CST_274+1; +pub const CST_276: u32 = CST_275+1; +pub const CST_277: u32 = CST_276+1; +pub const CST_278: u32 = CST_277+1; +pub const CST_279: u32 = CST_278+1; +pub const CST_280: u32 = CST_279+1; +pub const CST_281: u32 = CST_280+1; +pub const CST_282: u32 = CST_281+1; +pub const CST_283: u32 = CST_282+1; +pub const CST_284: u32 = CST_283+1; +pub const CST_285: u32 = CST_284+1; +pub const CST_286: u32 = CST_285+1; +pub const CST_287: u32 = CST_286+1; +pub const CST_288: u32 = CST_287+1; +pub const CST_289: u32 = CST_288+1; +pub const CST_290: u32 = CST_289+1; +pub const CST_291: u32 = CST_290+1; +pub const CST_292: u32 = CST_291+1; +pub const CST_293: u32 = CST_292+1; +pub const CST_294: u32 = CST_293+1; +pub const CST_295: u32 = CST_294+1; +pub const CST_296: u32 = CST_295+1; +pub const CST_297: u32 = CST_296+1; +pub const CST_298: u32 = CST_297+1; +pub const CST_299: u32 = CST_298+1; +pub const CST_300: u32 = CST_299+1; +pub const CST_301: u32 = CST_300+1; +pub const CST_302: u32 = CST_301+1; +pub const CST_303: u32 = CST_302+1; +pub const CST_304: u32 = CST_303+1; +pub const CST_305: u32 = CST_304+1; +pub const CST_306: u32 = CST_305+1; +pub const CST_307: u32 = CST_306+1; +pub const CST_308: u32 = CST_307+1; +pub const CST_309: u32 = CST_308+1; +pub const CST_310: u32 = CST_309+1; +pub const CST_311: u32 = CST_310+1; +pub const CST_312: u32 = CST_311+1; +pub const CST_313: u32 = CST_312+1; +pub const CST_314: u32 = CST_313+1; +pub const CST_315: u32 = CST_314+1; +pub const CST_316: u32 = CST_315+1; +pub const CST_317: u32 = CST_316+1; +pub const CST_318: u32 = CST_317+1; +pub const CST_319: u32 = CST_318+1; +pub const CST_320: u32 = CST_319+1; +pub const CST_321: u32 = CST_320+1; +pub const CST_322: u32 = CST_321+1; +pub const CST_323: u32 = CST_322+1; +pub const CST_324: u32 = CST_323+1; +pub const CST_325: u32 = CST_324+1; +pub const CST_326: u32 = CST_325+1; +pub const CST_327: u32 = CST_326+1; +pub const CST_328: u32 = CST_327+1; +pub const CST_329: u32 = CST_328+1; +pub const CST_330: u32 = CST_329+1; +pub const CST_331: u32 = CST_330+1; +pub const CST_332: u32 = CST_331+1; +pub const CST_333: u32 = CST_332+1; +pub const CST_334: u32 = CST_333+1; +pub const CST_335: u32 = CST_334+1; +pub const CST_336: u32 = CST_335+1; +pub const CST_337: u32 = CST_336+1; +pub const CST_338: u32 = CST_337+1; +pub const CST_339: u32 = CST_338+1; +pub const CST_340: u32 = CST_339+1; +pub const CST_341: u32 = CST_340+1; +pub const CST_342: u32 = CST_341+1; +pub const CST_343: u32 = CST_342+1; +pub const CST_344: u32 = CST_343+1; +pub const CST_345: u32 = CST_344+1; +pub const CST_346: u32 = CST_345+1; +pub const CST_347: u32 = CST_346+1; +pub const CST_348: u32 = CST_347+1; +pub const CST_349: u32 = CST_348+1; +pub const CST_350: u32 = CST_349+1; + +fn main() {} diff --git a/tests/ui/consts/check_const-feature-gated.rs b/tests/ui/consts/check_const-feature-gated.rs new file mode 100644 index 000000000..f4faab1ab --- /dev/null +++ b/tests/ui/consts/check_const-feature-gated.rs @@ -0,0 +1,7 @@ +// run-pass + +const ARR: [usize; 1] = [2]; + +fn main() { + let _ = 5 << ARR[0]; +} diff --git a/tests/ui/consts/closure-in-foreign-crate.rs b/tests/ui/consts/closure-in-foreign-crate.rs new file mode 100644 index 000000000..fc8f480e7 --- /dev/null +++ b/tests/ui/consts/closure-in-foreign-crate.rs @@ -0,0 +1,8 @@ +// aux-build:closure-in-foreign-crate.rs +// build-pass + +extern crate closure_in_foreign_crate; + +const _: () = closure_in_foreign_crate::test(); + +fn main() {} diff --git a/tests/ui/consts/closure-structural-match-issue-90013.rs b/tests/ui/consts/closure-structural-match-issue-90013.rs new file mode 100644 index 000000000..1952ddb94 --- /dev/null +++ b/tests/ui/consts/closure-structural-match-issue-90013.rs @@ -0,0 +1,7 @@ +// Regression test for issue 90013. +// check-pass +#![feature(inline_const)] + +fn main() { + const { || {} }; +} diff --git a/tests/ui/consts/const-address-of-interior-mut.rs b/tests/ui/consts/const-address-of-interior-mut.rs new file mode 100644 index 000000000..60c7c31da --- /dev/null +++ b/tests/ui/consts/const-address-of-interior-mut.rs @@ -0,0 +1,16 @@ +#![feature(raw_ref_op)] + +use std::cell::Cell; + +const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static B: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +const fn foo() { + let x = Cell::new(0); + let y = &raw const x; //~ ERROR interior mutability +} + +fn main() {} diff --git a/tests/ui/consts/const-address-of-interior-mut.stderr b/tests/ui/consts/const-address-of-interior-mut.stderr new file mode 100644 index 000000000..93120753b --- /dev/null +++ b/tests/ui/consts/const-address-of-interior-mut.stderr @@ -0,0 +1,39 @@ +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/const-address-of-interior-mut.rs:5:39 + | +LL | const A: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/const-address-of-interior-mut.rs:7:40 + | +LL | static B: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/const-address-of-interior-mut.rs:9:44 + | +LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/const-address-of-interior-mut.rs:13:13 + | +LL | let y = &raw const x; + | ^^^^^^^^^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-address-of-mut.rs b/tests/ui/consts/const-address-of-mut.rs new file mode 100644 index 000000000..3788088b8 --- /dev/null +++ b/tests/ui/consts/const-address-of-mut.rs @@ -0,0 +1,14 @@ +#![feature(raw_ref_op)] + +const A: () = { let mut x = 2; &raw mut x; }; //~ mutable reference + +static B: () = { let mut x = 2; &raw mut x; }; //~ mutable reference + +static mut C: () = { let mut x = 2; &raw mut x; }; //~ mutable reference + +const fn foo() { + let mut x = 0; + let y = &raw mut x; //~ mutable reference +} + +fn main() {} diff --git a/tests/ui/consts/const-address-of-mut.stderr b/tests/ui/consts/const-address-of-mut.stderr new file mode 100644 index 000000000..60cdcc7df --- /dev/null +++ b/tests/ui/consts/const-address-of-mut.stderr @@ -0,0 +1,39 @@ +error[E0658]: raw mutable references are not allowed in constants + --> $DIR/const-address-of-mut.rs:3:32 + | +LL | const A: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: raw mutable references are not allowed in statics + --> $DIR/const-address-of-mut.rs:5:33 + | +LL | static B: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: raw mutable references are not allowed in statics + --> $DIR/const-address-of-mut.rs:7:37 + | +LL | static mut C: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: raw mutable references are not allowed in constant functions + --> $DIR/const-address-of-mut.rs:11:13 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-address-of.rs b/tests/ui/consts/const-address-of.rs new file mode 100644 index 000000000..ba162f2a2 --- /dev/null +++ b/tests/ui/consts/const-address-of.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const A: *const i32 = &raw const *&2; +static B: () = { &raw const *&2; }; +static mut C: *const i32 = &raw const *&2; +const D: () = { let x = 2; &raw const x; }; +static E: () = { let x = 2; &raw const x; }; +static mut F: () = { let x = 2; &raw const x; }; + +const fn const_ptr() { + let x = 0; + let ptr = &raw const x; + let r = &x; + let ptr2 = &raw const *r; +} + +fn main() {} diff --git a/tests/ui/consts/const-adt-align-mismatch.rs b/tests/ui/consts/const-adt-align-mismatch.rs new file mode 100644 index 000000000..bd51bc9f2 --- /dev/null +++ b/tests/ui/consts/const-adt-align-mismatch.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(deprecated)] + +use std::mem; + +#[derive(PartialEq, Debug)] +enum Foo { + A(u32), + Bar([u16; 4]), + C +} + +// NOTE(eddyb) Don't make this a const, needs to be a static +// so it is always instantiated as a LLVM constant value. +static FOO: Foo = Foo::C; + +fn main() { + assert_eq!(FOO, Foo::C); + assert_eq!(mem::size_of::(), 12); + assert_eq!(mem::min_align_of::(), 4); +} diff --git a/tests/ui/consts/const-array-oob-arith.rs b/tests/ui/consts/const-array-oob-arith.rs new file mode 100644 index 000000000..9332cbbd4 --- /dev/null +++ b/tests/ui/consts/const-array-oob-arith.rs @@ -0,0 +1,14 @@ +const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47]; +const IDX: usize = 3; +const VAL: i32 = ARR[IDX]; +const BONG: [i32; (ARR[0] - 41) as usize] = [5]; +const BLUB: [i32; (ARR[0] - 40) as usize] = [5]; +//~^ ERROR: mismatched types +//~| expected an array with a fixed size of 2 elements, found one with 1 element +const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99]; +//~^ ERROR: mismatched types +//~| expected an array with a fixed size of 1 element, found one with 2 elements + +fn main() { + let _ = VAL; +} diff --git a/tests/ui/consts/const-array-oob-arith.stderr b/tests/ui/consts/const-array-oob-arith.stderr new file mode 100644 index 000000000..f7a55d3ca --- /dev/null +++ b/tests/ui/consts/const-array-oob-arith.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/const-array-oob-arith.rs:5:45 + | +LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5]; + | ^^^ expected an array with a fixed size of 2 elements, found one with 1 element + +error[E0308]: mismatched types + --> $DIR/const-array-oob-arith.rs:8:44 + | +LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99]; + | ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-array-oob.rs b/tests/ui/consts/const-array-oob.rs new file mode 100644 index 000000000..c747ab50c --- /dev/null +++ b/tests/ui/consts/const-array-oob.rs @@ -0,0 +1,10 @@ +const FOO: [usize; 3] = [1, 2, 3]; +const BAR: usize = FOO[5]; // no error, because the error below occurs before regular const eval + +const BLUB: [u32; FOO[4]] = [5, 6]; +//~^ ERROR evaluation of constant value failed [E0080] +//~| index out of bounds: the length is 3 but the index is 4 + +fn main() { + let _ = BAR; +} diff --git a/tests/ui/consts/const-array-oob.stderr b/tests/ui/consts/const-array-oob.stderr new file mode 100644 index 000000000..f1c5f58af --- /dev/null +++ b/tests/ui/consts/const-array-oob.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-array-oob.rs:4:19 + | +LL | const BLUB: [u32; FOO[4]] = [5, 6]; + | ^^^^^^ index out of bounds: the length is 3 but the index is 4 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-as-fn.rs b/tests/ui/consts/const-as-fn.rs new file mode 100644 index 000000000..388f907f8 --- /dev/null +++ b/tests/ui/consts/const-as-fn.rs @@ -0,0 +1,5 @@ +const FOO: usize = 0; + +fn main() { + FOO(); //~ ERROR expected function, found `usize` +} diff --git a/tests/ui/consts/const-as-fn.stderr b/tests/ui/consts/const-as-fn.stderr new file mode 100644 index 000000000..6c51ed893 --- /dev/null +++ b/tests/ui/consts/const-as-fn.stderr @@ -0,0 +1,14 @@ +error[E0618]: expected function, found `usize` + --> $DIR/const-as-fn.rs:4:5 + | +LL | const FOO: usize = 0; + | ---------------- `FOO` defined here +... +LL | FOO(); + | ^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/consts/const-autoderef.rs b/tests/ui/consts/const-autoderef.rs new file mode 100644 index 000000000..1c836318d --- /dev/null +++ b/tests/ui/consts/const-autoderef.rs @@ -0,0 +1,11 @@ +// run-pass + +const A: [u8; 1] = ['h' as u8]; +const B: u8 = (&A)[0]; +const C: &'static &'static &'static &'static [u8; 1] = & & & &A; +const D: u8 = (&C)[0]; + +pub fn main() { + assert_eq!(B, A[0]); + assert_eq!(D, A[0]); +} diff --git a/tests/ui/consts/const-big-enum.rs b/tests/ui/consts/const-big-enum.rs new file mode 100644 index 000000000..2f21e8a6d --- /dev/null +++ b/tests/ui/consts/const-big-enum.rs @@ -0,0 +1,30 @@ +// run-pass + +enum Foo { + Bar(u32), + Baz, + Quux(u64, u16) +} + +static X: Foo = Foo::Baz; + +pub fn main() { + match X { + Foo::Baz => {} + _ => panic!() + } + match Y { + Foo::Bar(s) => assert_eq!(s, 2654435769), + _ => panic!() + } + match Z { + Foo::Quux(d,h) => { + assert_eq!(d, 0x123456789abcdef0); + assert_eq!(h, 0x1234); + } + _ => panic!() + } +} + +static Y: Foo = Foo::Bar(2654435769); +static Z: Foo = Foo::Quux(0x123456789abcdef0, 0x1234); diff --git a/tests/ui/consts/const-binops.rs b/tests/ui/consts/const-binops.rs new file mode 100644 index 000000000..d038dfeb4 --- /dev/null +++ b/tests/ui/consts/const-binops.rs @@ -0,0 +1,126 @@ +// run-pass + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => ({ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", *a, *b); + }) +} + +static A: isize = -4 + 3; +static A2: usize = 3 + 3; +static B: f64 = 3.0 + 2.7; + +static C: isize = 3 - 4; +static D: usize = 3 - 3; +static E: f64 = 3.0 - 2.7; + +static E2: isize = -3 * 3; +static F: usize = 3 * 3; +static G: f64 = 3.3 * 3.3; + +static H: isize = 3 / -1; +static I: usize = 3 / 3; +static J: f64 = 3.3 / 3.3; + +static N: bool = true && false; + +static O: bool = true || false; + +static P: isize = 3 & 1; +static Q: usize = 1 & 3; + +static R: isize = 3 | 1; +static S: usize = 1 | 3; + +static T: isize = 3 ^ 1; +static U: usize = 1 ^ 3; + +static V: isize = 1 << 3; + +// NOTE: better shr coverage +static W: isize = 1024 >> 4; +static X: usize = 1024 >> 4; + +static Y: bool = 1 == 1; +static Z: bool = 1.0f64 == 1.0; + +static AA: bool = 1 <= 2; +static AB: bool = -1 <= 2; +static AC: bool = 1.0f64 <= 2.0; + +static AD: bool = 1 < 2; +static AE: bool = -1 < 2; +static AF: bool = 1.0f64 < 2.0; + +static AG: bool = 1 != 2; +static AH: bool = -1 != 2; +static AI: bool = 1.0f64 != 2.0; + +static AJ: bool = 2 >= 1; +static AK: bool = 2 >= -2; +static AL: bool = 1.0f64 >= -2.0; + +static AM: bool = 2 > 1; +static AN: bool = 2 > -2; +static AO: bool = 1.0f64 > -2.0; + +pub fn main() { + assert_eq!(A, -1); + assert_eq!(A2, 6); + assert_approx_eq!(B, 5.7); + + assert_eq!(C, -1); + assert_eq!(D, 0); + assert_approx_eq!(E, 0.3); + + assert_eq!(E2, -9); + assert_eq!(F, 9); + assert_approx_eq!(G, 10.89); + + assert_eq!(H, -3); + assert_eq!(I, 1); + assert_approx_eq!(J, 1.0); + + assert_eq!(N, false); + + assert_eq!(O, true); + + assert_eq!(P, 1); + assert_eq!(Q, 1); + + assert_eq!(R, 3); + assert_eq!(S, 3); + + assert_eq!(T, 2); + assert_eq!(U, 2); + + assert_eq!(V, 8); + + assert_eq!(W, 64); + assert_eq!(X, 64); + + assert_eq!(Y, true); + assert_eq!(Z, true); + + assert_eq!(AA, true); + assert_eq!(AB, true); + assert_eq!(AC, true); + + assert_eq!(AD, true); + assert_eq!(AE, true); + assert_eq!(AF, true); + + assert_eq!(AG, true); + assert_eq!(AH, true); + assert_eq!(AI, true); + + assert_eq!(AJ, true); + assert_eq!(AK, true); + assert_eq!(AL, true); + + assert_eq!(AM, true); + assert_eq!(AN, true); + assert_eq!(AO, true); +} diff --git a/tests/ui/consts/const-bitshift-rhs-inference.rs b/tests/ui/consts/const-bitshift-rhs-inference.rs new file mode 100644 index 000000000..cf21c296c --- /dev/null +++ b/tests/ui/consts/const-bitshift-rhs-inference.rs @@ -0,0 +1,24 @@ +// run-pass +const RHS: u8 = 8; +const IRHS: i8 = 8; +const RHS16: u16 = 8; +const IRHS16: i16 = 8; +const RHS32: u32 = 8; +const IRHS32: i32 = 8; +const RHS64: u64 = 8; +const IRHS64: i64 = 8; +const RHSUS: usize = 8; +const IRHSIS: isize = 8; + +fn main() { + let _: [&'static str; 1 << RHS] = [""; 256]; + let _: [&'static str; 1 << IRHS] = [""; 256]; + let _: [&'static str; 1 << RHS16] = [""; 256]; + let _: [&'static str; 1 << IRHS16] = [""; 256]; + let _: [&'static str; 1 << RHS32] = [""; 256]; + let _: [&'static str; 1 << IRHS32] = [""; 256]; + let _: [&'static str; 1 << RHS64] = [""; 256]; + let _: [&'static str; 1 << IRHS64] = [""; 256]; + let _: [&'static str; 1 << RHSUS] = [""; 256]; + let _: [&'static str; 1 << IRHSIS] = [""; 256]; +} diff --git a/tests/ui/consts/const-block-const-bound.rs b/tests/ui/consts/const-block-const-bound.rs new file mode 100644 index 000000000..42aa0216b --- /dev/null +++ b/tests/ui/consts/const-block-const-bound.rs @@ -0,0 +1,25 @@ +#![allow(unused)] +#![feature(const_trait_impl, inline_const, negative_impls)] + +use std::marker::Destruct; + +const fn f(x: T) {} + +struct UnconstDrop; + +impl Drop for UnconstDrop { + fn drop(&mut self) {} +} + +struct NonDrop; + +impl !Drop for NonDrop {} + +fn main() { + const { + f(UnconstDrop); + //~^ ERROR can't drop + f(NonDrop); + //~^ ERROR can't drop + } +} diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr new file mode 100644 index 000000000..b9c4d8866 --- /dev/null +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -0,0 +1,45 @@ +error[E0277]: can't drop `UnconstDrop` in const contexts + --> $DIR/const-block-const-bound.rs:20:11 + | +LL | f(UnconstDrop); + | - ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop` + | | + | required by a bound introduced by this call + | + = note: the trait bound `UnconstDrop: ~const Destruct` is not satisfied +note: required by a bound in `f` + --> $DIR/const-block-const-bound.rs:6:15 + | +LL | const fn f(x: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `f` +help: consider borrowing here + | +LL | f(&UnconstDrop); + | + +LL | f(&mut UnconstDrop); + | ++++ + +error[E0277]: can't drop `NonDrop` in const contexts + --> $DIR/const-block-const-bound.rs:22:11 + | +LL | f(NonDrop); + | - ^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop` + | | + | required by a bound introduced by this call + | + = note: the trait bound `NonDrop: ~const Destruct` is not satisfied +note: required by a bound in `f` + --> $DIR/const-block-const-bound.rs:6:15 + | +LL | const fn f(x: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `f` +help: consider borrowing here + | +LL | f(&NonDrop); + | + +LL | f(&mut NonDrop); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-block-cross-crate-fn.rs b/tests/ui/consts/const-block-cross-crate-fn.rs new file mode 100644 index 000000000..0ac3830d2 --- /dev/null +++ b/tests/ui/consts/const-block-cross-crate-fn.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:cci_const_block.rs + + +extern crate cci_const_block; + +pub fn main() { + assert_eq!(cci_const_block::BLOCK_FN_DEF(390), 400); +} diff --git a/tests/ui/consts/const-block-item-macro-codegen.rs b/tests/ui/consts/const-block-item-macro-codegen.rs new file mode 100644 index 000000000..7ad883686 --- /dev/null +++ b/tests/ui/consts/const-block-item-macro-codegen.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code)] +// General test that function items in static blocks +// can be generated with a macro. + + +struct MyType { + desc: &'static str, + data: usize, + code: fn(usize, usize) -> usize +} + +impl MyType { + fn eval(&self, a: usize) -> usize { + (self.code)(self.data, a) + } +} + +macro_rules! codegen { + ($e:expr, $v:expr) => { + { + fn generated(a: usize, b: usize) -> usize { + a - ($e * b) + } + MyType { + desc: "test", + data: $v, + code: generated + } + } + } +} + +static GENERATED_CODE_1: MyType = codegen!(2, 100); +static GENERATED_CODE_2: MyType = codegen!(5, 1000); + +pub fn main() { + assert_eq!(GENERATED_CODE_1.eval(10), 80); + assert_eq!(GENERATED_CODE_2.eval(100), 500); +} diff --git a/tests/ui/consts/const-block-item.rs b/tests/ui/consts/const-block-item.rs new file mode 100644 index 000000000..cf0d4441d --- /dev/null +++ b/tests/ui/consts/const-block-item.rs @@ -0,0 +1,41 @@ +// run-pass +#![allow(unused_imports)] + +mod foo { + pub trait Value { + fn value(&self) -> usize; + } +} + +static BLOCK_USE: usize = { + use foo::Value; + 100 +}; + +static BLOCK_STRUCT_DEF: usize = { + struct Foo { + a: usize + } + Foo{ a: 300 }.a +}; + +static BLOCK_FN_DEF: fn(usize) -> usize = { + fn foo(a: usize) -> usize { + a + 10 + } + foo +}; + +static BLOCK_MACRO_RULES: usize = { + macro_rules! baz { + () => (412) + } + baz!() +}; + +pub fn main() { + assert_eq!(BLOCK_USE, 100); + assert_eq!(BLOCK_STRUCT_DEF, 300); + assert_eq!(BLOCK_FN_DEF(390), 400); + assert_eq!(BLOCK_MACRO_RULES, 412); +} diff --git a/tests/ui/consts/const-block-non-item-statement-3.rs b/tests/ui/consts/const-block-non-item-statement-3.rs new file mode 100644 index 000000000..c513946d1 --- /dev/null +++ b/tests/ui/consts/const-block-non-item-statement-3.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(dead_code, unused)] + +type Array = [u32; { let x = 2; 5 }]; + +pub fn main() { + let _: Array = [0; 5]; +} diff --git a/tests/ui/consts/const-block-non-item-statement-rpass.rs b/tests/ui/consts/const-block-non-item-statement-rpass.rs new file mode 100644 index 000000000..3e52eb50e --- /dev/null +++ b/tests/ui/consts/const-block-non-item-statement-rpass.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code, unused)] + +#[repr(u8)] +enum Foo { + Bar = { let x = 1; 3 } +} + +pub fn main() { + assert_eq!(3, Foo::Bar as u8); +} diff --git a/tests/ui/consts/const-block-non-item-statement.rs b/tests/ui/consts/const-block-non-item-statement.rs new file mode 100644 index 000000000..07970b457 --- /dev/null +++ b/tests/ui/consts/const-block-non-item-statement.rs @@ -0,0 +1,23 @@ +// check-pass + +enum Foo { + Bar = { let x = 1; 3 } +} + + +const A: usize = { 1; 2 }; + +const B: usize = { { } 2 }; + +macro_rules! foo { + () => (()) +} + +const C: usize = { foo!(); 2 }; + +const D: usize = { let x = 4; 2 }; + +type Array = [u32; { let x = 2; 5 }]; +type Array2 = [u32; { let mut x = 2; x = 3; x}]; + +pub fn main() {} diff --git a/tests/ui/consts/const-block.rs b/tests/ui/consts/const-block.rs new file mode 100644 index 000000000..ec99c70f6 --- /dev/null +++ b/tests/ui/consts/const-block.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(unused_braces)] +#![allow(dead_code)] +#![allow(unused_unsafe)] + +use std::marker::Sync; + +struct Foo { + a: usize, + b: *const () +} + +unsafe impl Sync for Foo {} + +fn foo(a: T) -> T { + a +} + +static BLOCK_INTEGRAL: usize = { 1 }; +static BLOCK_EXPLICIT_UNIT: () = { () }; +static BLOCK_IMPLICIT_UNIT: () = { }; +static BLOCK_FLOAT: f64 = { 1.0 }; +static BLOCK_ENUM: Option = { Some(100) }; +static BLOCK_STRUCT: Foo = { Foo { a: 12, b: std::ptr::null::<()>() } }; +static BLOCK_UNSAFE: usize = unsafe { 1000 }; + +static BLOCK_FN_INFERRED: fn(usize) -> usize = { foo }; + +static BLOCK_FN: fn(usize) -> usize = { foo:: }; + +static BLOCK_ENUM_CONSTRUCTOR: fn(usize) -> Option = { Some }; + +pub fn main() { + assert_eq!(BLOCK_INTEGRAL, 1); + assert_eq!(BLOCK_EXPLICIT_UNIT, ()); + assert_eq!(BLOCK_IMPLICIT_UNIT, ()); + assert_eq!(BLOCK_FLOAT, 1.0_f64); + assert_eq!(BLOCK_STRUCT.a, 12); + assert_eq!(BLOCK_STRUCT.b, std::ptr::null::<()>()); + assert_eq!(BLOCK_ENUM, Some(100)); + assert_eq!(BLOCK_UNSAFE, 1000); + assert_eq!(BLOCK_FN_INFERRED(300), 300); + assert_eq!(BLOCK_FN(300), 300); + assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200)); +} diff --git a/tests/ui/consts/const-blocks/const-repeat.rs b/tests/ui/consts/const-blocks/const-repeat.rs new file mode 100644 index 000000000..65d02317d --- /dev/null +++ b/tests/ui/consts/const-blocks/const-repeat.rs @@ -0,0 +1,27 @@ +// run-pass + +// Repeating a *constant* of non-Copy type (not just a constant expression) is already stable. + +const EMPTY: Vec = Vec::new(); + +pub fn bar() -> [Vec; 2] { + [EMPTY; 2] +} + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + panic!("BOOM!"); + } +} + +const BOOM: Bomb = Bomb; + +fn main() { + let _x = bar(); + + // Make sure the destructor does not get called for empty arrays. `[CONST; N]` should + // instantiate (and then later drop) the const exactly `N` times. + let _x = [BOOM; 0]; +} diff --git a/tests/ui/consts/const-blocks/fn-call-in-const.rs b/tests/ui/consts/const-blocks/fn-call-in-const.rs new file mode 100644 index 000000000..20496f627 --- /dev/null +++ b/tests/ui/consts/const-blocks/fn-call-in-const.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(inline_const)] +#![allow(unused)] + +// Some type that is not copyable. +struct Bar; + +const fn type_no_copy() -> Option { + None +} + +const fn type_copy() -> u32 { + 3 +} + +const _: [u32; 2] = [type_copy(); 2]; + +// This is allowed because all promotion contexts use the explicit rules for promotability when +// inside an explicit const context. +const _: [Option; 2] = [const { type_no_copy() }; 2]; + +fn main() {} diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.rs b/tests/ui/consts/const-blocks/fn-call-in-non-const.rs new file mode 100644 index 000000000..18b4dc714 --- /dev/null +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.rs @@ -0,0 +1,16 @@ +// Some type that is not copyable. +struct Bar; + +const fn no_copy() -> Option { + None +} + +const fn copy() -> u32 { + 3 +} + +fn main() { + let _: [u32; 2] = [copy(); 2]; + let _: [Option; 2] = [no_copy(); 2]; + //~^ ERROR the trait bound `Bar: Copy` is not satisfied +} diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr new file mode 100644 index 000000000..ee352700c --- /dev/null +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/fn-call-in-non-const.rs:14:32 + | +LL | let _: [Option; 2] = [no_copy(); 2]; + | ^^^^^^^^^ the trait `Copy` is not implemented for `Bar` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` + = help: create an inline `const` block, see RFC #2920 for more information +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-blocks/migrate-fail.rs b/tests/ui/consts/const-blocks/migrate-fail.rs new file mode 100644 index 000000000..fddbfbb9d --- /dev/null +++ b/tests/ui/consts/const-blocks/migrate-fail.rs @@ -0,0 +1,22 @@ +#![allow(warnings)] + +// Some type that is not copyable. +struct Bar; + +mod non_constants { + use Bar; + + fn no_impl_copy_empty_value_multiple_elements() { + let x = None; + let arr: [Option; 2] = [x; 2]; + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] + } + + fn no_impl_copy_value_multiple_elements() { + let x = Some(Bar); + let arr: [Option; 2] = [x; 2]; + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] + } +} + +fn main() {} diff --git a/tests/ui/consts/const-blocks/migrate-fail.stderr b/tests/ui/consts/const-blocks/migrate-fail.stderr new file mode 100644 index 000000000..928ffd083 --- /dev/null +++ b/tests/ui/consts/const-blocks/migrate-fail.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/migrate-fail.rs:11:38 + | +LL | let arr: [Option; 2] = [x; 2]; + | ^ the trait `Copy` is not implemented for `Bar` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/migrate-fail.rs:17:38 + | +LL | let arr: [Option; 2] = [x; 2]; + | ^ the trait `Copy` is not implemented for `Bar` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-blocks/migrate-pass.rs b/tests/ui/consts/const-blocks/migrate-pass.rs new file mode 100644 index 000000000..fd66f5aa6 --- /dev/null +++ b/tests/ui/consts/const-blocks/migrate-pass.rs @@ -0,0 +1,125 @@ +// check-pass +#![allow(warnings)] + +// Some type that is not copyable. +struct Bar; + +mod constants { + use Bar; + + fn no_impl_copy_empty_value_no_elements() { + const FOO: Option = None; + const ARR: [Option; 0] = [FOO; 0]; + } + + fn no_impl_copy_empty_value_single_element() { + const FOO: Option = None; + const ARR: [Option; 1] = [FOO; 1]; + } + + fn no_impl_copy_empty_value_multiple_elements() { + const FOO: Option = None; + const ARR: [Option; 2] = [FOO; 2]; + } + + fn no_impl_copy_value_no_elements() { + const FOO: Option = Some(Bar); + const ARR: [Option; 0] = [FOO; 0]; + } + + fn no_impl_copy_value_single_element() { + const FOO: Option = Some(Bar); + const ARR: [Option; 1] = [FOO; 1]; + } + + fn no_impl_copy_value_multiple_elements() { + const FOO: Option = Some(Bar); + const ARR: [Option; 2] = [FOO; 2]; + } + + fn impl_copy_empty_value_no_elements() { + const FOO: Option = None; + const ARR: [Option; 0] = [FOO; 0]; + } + + fn impl_copy_empty_value_one_element() { + const FOO: Option = None; + const ARR: [Option; 1] = [FOO; 1]; + } + + fn impl_copy_empty_value_multiple_elements() { + const FOO: Option = None; + const ARR: [Option; 2] = [FOO; 2]; + } + + fn impl_copy_value_no_elements() { + const FOO: Option = Some(4); + const ARR: [Option; 0] = [FOO; 0]; + } + + fn impl_copy_value_one_element() { + const FOO: Option = Some(4); + const ARR: [Option; 1] = [FOO; 1]; + } + + fn impl_copy_value_multiple_elements() { + const FOO: Option = Some(4); + const ARR: [Option; 2] = [FOO; 2]; + } +} + +mod non_constants { + use Bar; + + fn no_impl_copy_empty_value_no_elements() { + let x = None; + let arr: [Option; 0] = [x; 0]; + } + + fn no_impl_copy_empty_value_single_element() { + let x = None; + let arr: [Option; 1] = [x; 1]; + } + + fn no_impl_copy_value_no_elements() { + let x = Some(Bar); + let arr: [Option; 0] = [x; 0]; + } + + fn no_impl_copy_value_single_element() { + let x = Some(Bar); + let arr: [Option; 1] = [x; 1]; + } + + fn impl_copy_empty_value_no_elements() { + let x: Option = None; + let arr: [Option; 0] = [x; 0]; + } + + fn impl_copy_empty_value_one_element() { + let x: Option = None; + let arr: [Option; 1] = [x; 1]; + } + + fn impl_copy_empty_value_multiple_elements() { + let x: Option = None; + let arr: [Option; 2] = [x; 2]; + } + + fn impl_copy_value_no_elements() { + let x: Option = Some(4); + let arr: [Option; 0] = [x; 0]; + } + + fn impl_copy_value_one_element() { + let x: Option = Some(4); + let arr: [Option; 1] = [x; 1]; + } + + fn impl_copy_value_multiple_elements() { + let x: Option = Some(4); + let arr: [Option; 2] = [x; 2]; + } +} + +fn main() {} diff --git a/tests/ui/consts/const-blocks/nll-fail.rs b/tests/ui/consts/const-blocks/nll-fail.rs new file mode 100644 index 000000000..fddbfbb9d --- /dev/null +++ b/tests/ui/consts/const-blocks/nll-fail.rs @@ -0,0 +1,22 @@ +#![allow(warnings)] + +// Some type that is not copyable. +struct Bar; + +mod non_constants { + use Bar; + + fn no_impl_copy_empty_value_multiple_elements() { + let x = None; + let arr: [Option; 2] = [x; 2]; + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] + } + + fn no_impl_copy_value_multiple_elements() { + let x = Some(Bar); + let arr: [Option; 2] = [x; 2]; + //~^ ERROR the trait bound `Bar: Copy` is not satisfied [E0277] + } +} + +fn main() {} diff --git a/tests/ui/consts/const-blocks/nll-fail.stderr b/tests/ui/consts/const-blocks/nll-fail.stderr new file mode 100644 index 000000000..fede00845 --- /dev/null +++ b/tests/ui/consts/const-blocks/nll-fail.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/nll-fail.rs:11:38 + | +LL | let arr: [Option; 2] = [x; 2]; + | ^ the trait `Copy` is not implemented for `Bar` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0277]: the trait bound `Bar: Copy` is not satisfied + --> $DIR/nll-fail.rs:17:38 + | +LL | let arr: [Option; 2] = [x; 2]; + | ^ the trait `Copy` is not implemented for `Bar` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Bar` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-blocks/nll-pass.rs b/tests/ui/consts/const-blocks/nll-pass.rs new file mode 100644 index 000000000..fd66f5aa6 --- /dev/null +++ b/tests/ui/consts/const-blocks/nll-pass.rs @@ -0,0 +1,125 @@ +// check-pass +#![allow(warnings)] + +// Some type that is not copyable. +struct Bar; + +mod constants { + use Bar; + + fn no_impl_copy_empty_value_no_elements() { + const FOO: Option = None; + const ARR: [Option; 0] = [FOO; 0]; + } + + fn no_impl_copy_empty_value_single_element() { + const FOO: Option = None; + const ARR: [Option; 1] = [FOO; 1]; + } + + fn no_impl_copy_empty_value_multiple_elements() { + const FOO: Option = None; + const ARR: [Option; 2] = [FOO; 2]; + } + + fn no_impl_copy_value_no_elements() { + const FOO: Option = Some(Bar); + const ARR: [Option; 0] = [FOO; 0]; + } + + fn no_impl_copy_value_single_element() { + const FOO: Option = Some(Bar); + const ARR: [Option; 1] = [FOO; 1]; + } + + fn no_impl_copy_value_multiple_elements() { + const FOO: Option = Some(Bar); + const ARR: [Option; 2] = [FOO; 2]; + } + + fn impl_copy_empty_value_no_elements() { + const FOO: Option = None; + const ARR: [Option; 0] = [FOO; 0]; + } + + fn impl_copy_empty_value_one_element() { + const FOO: Option = None; + const ARR: [Option; 1] = [FOO; 1]; + } + + fn impl_copy_empty_value_multiple_elements() { + const FOO: Option = None; + const ARR: [Option; 2] = [FOO; 2]; + } + + fn impl_copy_value_no_elements() { + const FOO: Option = Some(4); + const ARR: [Option; 0] = [FOO; 0]; + } + + fn impl_copy_value_one_element() { + const FOO: Option = Some(4); + const ARR: [Option; 1] = [FOO; 1]; + } + + fn impl_copy_value_multiple_elements() { + const FOO: Option = Some(4); + const ARR: [Option; 2] = [FOO; 2]; + } +} + +mod non_constants { + use Bar; + + fn no_impl_copy_empty_value_no_elements() { + let x = None; + let arr: [Option; 0] = [x; 0]; + } + + fn no_impl_copy_empty_value_single_element() { + let x = None; + let arr: [Option; 1] = [x; 1]; + } + + fn no_impl_copy_value_no_elements() { + let x = Some(Bar); + let arr: [Option; 0] = [x; 0]; + } + + fn no_impl_copy_value_single_element() { + let x = Some(Bar); + let arr: [Option; 1] = [x; 1]; + } + + fn impl_copy_empty_value_no_elements() { + let x: Option = None; + let arr: [Option; 0] = [x; 0]; + } + + fn impl_copy_empty_value_one_element() { + let x: Option = None; + let arr: [Option; 1] = [x; 1]; + } + + fn impl_copy_empty_value_multiple_elements() { + let x: Option = None; + let arr: [Option; 2] = [x; 2]; + } + + fn impl_copy_value_no_elements() { + let x: Option = Some(4); + let arr: [Option; 0] = [x; 0]; + } + + fn impl_copy_value_one_element() { + let x: Option = Some(4); + let arr: [Option; 1] = [x; 1]; + } + + fn impl_copy_value_multiple_elements() { + let x: Option = Some(4); + let arr: [Option; 2] = [x; 2]; + } +} + +fn main() {} diff --git a/tests/ui/consts/const-blocks/run-pass.rs b/tests/ui/consts/const-blocks/run-pass.rs new file mode 100644 index 000000000..e11f69bab --- /dev/null +++ b/tests/ui/consts/const-blocks/run-pass.rs @@ -0,0 +1,11 @@ +// run-pass + +#[derive(Debug, Eq, PartialEq)] +struct Bar; + +fn main() { + const FOO: Option = None; + const ARR: [Option; 2] = [FOO; 2]; + + assert_eq!(ARR, [None::, None::]); +} diff --git a/tests/ui/consts/const-blocks/trait-error.rs b/tests/ui/consts/const-blocks/trait-error.rs new file mode 100644 index 000000000..49d1e9b94 --- /dev/null +++ b/tests/ui/consts/const-blocks/trait-error.rs @@ -0,0 +1,7 @@ +#[derive(Copy, Clone)] +struct Foo(T); + +fn main() { + [Foo(String::new()); 4]; + //~^ ERROR the trait bound `String: Copy` is not satisfied [E0277] +} diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr new file mode 100644 index 000000000..06fa4b0b1 --- /dev/null +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/trait-error.rs:5:6 + | +LL | [Foo(String::new()); 4]; + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required for `Foo` to implement `Copy` + --> $DIR/trait-error.rs:1:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` + = help: create an inline `const` block, see RFC #2920 for more information + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-bound.rs b/tests/ui/consts/const-bound.rs new file mode 100644 index 000000000..735056a0a --- /dev/null +++ b/tests/ui/consts/const-bound.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +// Make sure const bounds work on things, and test that a few types +// are const. + +// pretty-expanded FIXME #23616 + +fn foo(x: T) -> T { x } + +struct F { field: isize } + +pub fn main() { + /*foo(1); + foo("hi".to_string()); + foo(vec![1, 2, 3]); + foo(F{field: 42}); + foo((1, 2)); + foo(@1);*/ + foo(Box::new(1)); +} diff --git a/tests/ui/consts/const-byte-str-cast.rs b/tests/ui/consts/const-byte-str-cast.rs new file mode 100644 index 000000000..65d626c29 --- /dev/null +++ b/tests/ui/consts/const-byte-str-cast.rs @@ -0,0 +1,9 @@ +// run-pass +#[deny(warnings)] + +pub fn main() { + let _ = b"x" as &[u8]; + let _ = b"y" as &[u8; 1]; + let _ = b"z" as *const u8; + let _ = "ä" as *const str; +} diff --git a/tests/ui/consts/const-call.rs b/tests/ui/consts/const-call.rs new file mode 100644 index 000000000..28e89559f --- /dev/null +++ b/tests/ui/consts/const-call.rs @@ -0,0 +1,8 @@ +fn f(x: usize) -> usize { + x +} + +fn main() { + let _ = [0; f(2)]; + //~^ ERROR cannot call non-const fn +} diff --git a/tests/ui/consts/const-call.stderr b/tests/ui/consts/const-call.stderr new file mode 100644 index 000000000..e46bcad0e --- /dev/null +++ b/tests/ui/consts/const-call.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `f` in constants + --> $DIR/const-call.rs:6:17 + | +LL | let _ = [0; f(2)]; + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-cast-different-types.rs b/tests/ui/consts/const-cast-different-types.rs new file mode 100644 index 000000000..5e6d7d899 --- /dev/null +++ b/tests/ui/consts/const-cast-different-types.rs @@ -0,0 +1,6 @@ +const a: &str = "foo"; +const b: *const u8 = a as *const u8; //~ ERROR casting +const c: *const u8 = &a as *const u8; //~ ERROR casting + +fn main() { +} diff --git a/tests/ui/consts/const-cast-different-types.stderr b/tests/ui/consts/const-cast-different-types.stderr new file mode 100644 index 000000000..9e622de2e --- /dev/null +++ b/tests/ui/consts/const-cast-different-types.stderr @@ -0,0 +1,15 @@ +error[E0606]: casting `&'static str` as `*const u8` is invalid + --> $DIR/const-cast-different-types.rs:2:22 + | +LL | const b: *const u8 = a as *const u8; + | ^^^^^^^^^^^^^^ + +error[E0606]: casting `&&'static str` as `*const u8` is invalid + --> $DIR/const-cast-different-types.rs:3:22 + | +LL | const c: *const u8 = &a as *const u8; + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/consts/const-cast-ptr-int.rs b/tests/ui/consts/const-cast-ptr-int.rs new file mode 100644 index 000000000..987d9616e --- /dev/null +++ b/tests/ui/consts/const-cast-ptr-int.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_upper_case_globals)] + +use std::ptr; + +struct TestStruct { + x: *const u8 +} + +unsafe impl Sync for TestStruct {} + +static a: TestStruct = TestStruct{x: 0 as *const u8}; + +pub fn main() { + assert_eq!(a.x, ptr::null()); +} diff --git a/tests/ui/consts/const-cast-wrong-type.rs b/tests/ui/consts/const-cast-wrong-type.rs new file mode 100644 index 000000000..6e055a2bc --- /dev/null +++ b/tests/ui/consts/const-cast-wrong-type.rs @@ -0,0 +1,5 @@ +const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8]; +const b: *const i8 = &a as *const i8; //~ ERROR mismatched types + +fn main() { +} diff --git a/tests/ui/consts/const-cast-wrong-type.stderr b/tests/ui/consts/const-cast-wrong-type.stderr new file mode 100644 index 000000000..ee186636e --- /dev/null +++ b/tests/ui/consts/const-cast-wrong-type.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/const-cast-wrong-type.rs:2:22 + | +LL | const b: *const i8 = &a as *const i8; + | ^^^^^^^^^^^^^^^ expected `u8`, found `i8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-cast.rs b/tests/ui/consts/const-cast.rs new file mode 100644 index 000000000..abeb24121 --- /dev/null +++ b/tests/ui/consts/const-cast.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_upper_case_globals)] + +struct TestStruct { + x: *const u8, +} + +unsafe impl Sync for TestStruct {} + +extern "C" fn foo() {} +const x: extern "C" fn() = foo; +static y: TestStruct = TestStruct { x: x as *const u8 }; + +pub fn main() { + assert_eq!(x as *const u8, y.x); +} diff --git a/tests/ui/consts/const-const.rs b/tests/ui/consts/const-const.rs new file mode 100644 index 000000000..85e4a72e8 --- /dev/null +++ b/tests/ui/consts/const-const.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(non_upper_case_globals)] + +const a: isize = 1; +const b: isize = a + 2; + +pub fn main() { + assert_eq!(b, 3); +} diff --git a/tests/ui/consts/const-contents.rs b/tests/ui/consts/const-contents.rs new file mode 100644 index 000000000..7ba3d4356 --- /dev/null +++ b/tests/ui/consts/const-contents.rs @@ -0,0 +1,19 @@ +// run-pass +// Issue #570 +#![allow(non_upper_case_globals)] + +static lsl : isize = 1 << 2; +static add : isize = 1 + 2; +static addf : f64 = 1.0 + 2.0; +static not : isize = !0; +static notb : bool = !true; +static neg : isize = -(1); + +pub fn main() { + assert_eq!(lsl, 4); + assert_eq!(add, 3); + assert_eq!(addf, 3.0); + assert_eq!(not, -1); + assert_eq!(notb, false); + assert_eq!(neg, -1); +} diff --git a/tests/ui/consts/const-deref-ptr.rs b/tests/ui/consts/const-deref-ptr.rs new file mode 100644 index 000000000..4aca75e3a --- /dev/null +++ b/tests/ui/consts/const-deref-ptr.rs @@ -0,0 +1,7 @@ +// Check that you can't dereference invalid raw pointers in constants. + +fn main() { + static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; + //~^ ERROR could not evaluate static initializer + println!("{}", C); +} diff --git a/tests/ui/consts/const-deref-ptr.stderr b/tests/ui/consts/const-deref-ptr.stderr new file mode 100644 index 000000000..22cb6451e --- /dev/null +++ b/tests/ui/consts/const-deref-ptr.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/const-deref-ptr.rs:4:29 + | +LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0xdeadbeef[noalloc] is a dangling pointer (it has no provenance) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-deref.rs b/tests/ui/consts/const-deref.rs new file mode 100644 index 000000000..6060d8e51 --- /dev/null +++ b/tests/ui/consts/const-deref.rs @@ -0,0 +1,8 @@ +// run-pass + +const C: &'static isize = &1000; +static D: isize = *C; + +pub fn main() { + assert_eq!(D, 1000); +} diff --git a/tests/ui/consts/const-endianess.rs b/tests/ui/consts/const-endianess.rs new file mode 100644 index 000000000..936f31954 --- /dev/null +++ b/tests/ui/consts/const-endianess.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(test)] + +extern crate test; +use test::black_box as b; // prevent promotion of the argument and const-propagation of the result + +const BE_U32: u32 = 55u32.to_be(); +const LE_U32: u32 = 55u32.to_le(); + +fn main() { + assert_eq!(BE_U32, b(55u32).to_be()); + assert_eq!(LE_U32, b(55u32).to_le()); + + #[cfg(not(target_os = "emscripten"))] + { + const BE_U128: u128 = 999999u128.to_be(); + const LE_I128: i128 = (-999999i128).to_le(); + assert_eq!(BE_U128, b(999999u128).to_be()); + assert_eq!(LE_I128, b(-999999i128).to_le()); + } +} diff --git a/tests/ui/consts/const-enum-byref-self.rs b/tests/ui/consts/const-enum-byref-self.rs new file mode 100644 index 000000000..b7e14bfb7 --- /dev/null +++ b/tests/ui/consts/const-enum-byref-self.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] + +enum E { V, VV(isize) } +static C: E = E::V; + +impl E { + pub fn method(&self) { + match *self { + E::V => {} + E::VV(..) => panic!() + } + } +} + +pub fn main() { + C.method() +} diff --git a/tests/ui/consts/const-enum-byref.rs b/tests/ui/consts/const-enum-byref.rs new file mode 100644 index 000000000..badf52946 --- /dev/null +++ b/tests/ui/consts/const-enum-byref.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +enum E { V, VV(isize) } +static C: E = E::V; + +fn f(a: &E) { + match *a { + E::V => {} + E::VV(..) => panic!() + } +} + +pub fn main() { + f(&C) +} diff --git a/tests/ui/consts/const-enum-cast.rs b/tests/ui/consts/const-enum-cast.rs new file mode 100644 index 000000000..399684951 --- /dev/null +++ b/tests/ui/consts/const-enum-cast.rs @@ -0,0 +1,41 @@ +// run-pass +#![allow(non_upper_case_globals)] + +enum A { A1, A2 } +enum B { B1=4, B2=2 } + +#[allow(dead_code)] +#[repr(align(8))] +enum Aligned { + Zero = 0, + One = 1, +} + +// regression test for https://github.com/rust-lang/rust/issues/96185 +const X: u8 = { + let aligned = Aligned::Zero; + aligned as u8 +}; + +pub fn main () { + static c1: isize = A::A2 as isize; + static c2: isize = B::B2 as isize; + let a1 = A::A2 as isize; + let a2 = B::B2 as isize; + assert_eq!(c1, 1); + assert_eq!(c2, 2); + assert_eq!(a1, 1); + assert_eq!(a2, 2); + + // Turns out that adding a let-binding generates totally different MIR. + static c1_2: isize = { let v = A::A1; v as isize }; + static c2_2: isize = { let v = B::B1; v as isize }; + let a1_2 = { let v = A::A1; v as isize }; + let a2_2 = { let v = B::B1; v as isize }; + assert_eq!(c1_2, 0); + assert_eq!(c2_2, 4); + assert_eq!(a1_2, 0); + assert_eq!(a2_2, 4); + + assert_eq!(X, 0); +} diff --git a/tests/ui/consts/const-enum-ptr.rs b/tests/ui/consts/const-enum-ptr.rs new file mode 100644 index 000000000..84f4eb840 --- /dev/null +++ b/tests/ui/consts/const-enum-ptr.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] + +enum E { V0, V1(isize) } +static C: &'static E = &E::V0; + +pub fn main() { + match *C { + E::V0 => (), + _ => panic!() + } +} diff --git a/tests/ui/consts/const-enum-struct.rs b/tests/ui/consts/const-enum-struct.rs new file mode 100644 index 000000000..ee88c9361 --- /dev/null +++ b/tests/ui/consts/const-enum-struct.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] + +enum E { V16(u16), V32(u32) } +struct S { a: E, b: u16, c: u16 } +static C: S = S { a: E::V16(0xDEAD), b: 0x600D, c: 0xBAD }; + +pub fn main() { + let n = C.b; + assert!(n != 0xBAD); + assert_eq!(n, 0x600D); +} diff --git a/tests/ui/consts/const-enum-struct2.rs b/tests/ui/consts/const-enum-struct2.rs new file mode 100644 index 000000000..6dfe63d5d --- /dev/null +++ b/tests/ui/consts/const-enum-struct2.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] + +enum E { V0, V16(u16) } +struct S { a: E, b: u16, c: u16 } +static C: S = S { a: E::V0, b: 0x600D, c: 0xBAD }; + +pub fn main() { + let n = C.b; + assert!(n != 0xBAD); + assert_eq!(n, 0x600D); +} diff --git a/tests/ui/consts/const-enum-structlike.rs b/tests/ui/consts/const-enum-structlike.rs new file mode 100644 index 000000000..0ea79aebc --- /dev/null +++ b/tests/ui/consts/const-enum-structlike.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +enum E { + S0 { s: String }, + S1 { u: usize } +} + +static C: E = E::S1 { u: 23 }; + +pub fn main() { + match C { + E::S0 { .. } => panic!(), + E::S1 { u } => assert_eq!(u, 23) + } +} diff --git a/tests/ui/consts/const-enum-tuple.rs b/tests/ui/consts/const-enum-tuple.rs new file mode 100644 index 000000000..e0363166b --- /dev/null +++ b/tests/ui/consts/const-enum-tuple.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] + +enum E { V16(u16), V32(u32) } +static C: (E, u16, u16) = (E::V16(0xDEAD), 0x600D, 0xBAD); + +pub fn main() { + let (_, n, _) = C; + assert!(n != 0xBAD); + assert_eq!(n, 0x600D); +} diff --git a/tests/ui/consts/const-enum-tuple2.rs b/tests/ui/consts/const-enum-tuple2.rs new file mode 100644 index 000000000..ef378b599 --- /dev/null +++ b/tests/ui/consts/const-enum-tuple2.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] + +enum E { V0, V16(u16) } +static C: (E, u16, u16) = (E::V0, 0x600D, 0xBAD); + +pub fn main() { + let (_, n, _) = C; + assert!(n != 0xBAD); + assert_eq!(n, 0x600D); +} diff --git a/tests/ui/consts/const-enum-tuplestruct.rs b/tests/ui/consts/const-enum-tuplestruct.rs new file mode 100644 index 000000000..f93945c6a --- /dev/null +++ b/tests/ui/consts/const-enum-tuplestruct.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] + +enum E { V16(u16), V32(u32) } +struct S(E, u16, u16); +static C: S = S(E::V16(0xDEAD), 0x600D, 0xBAD); + +pub fn main() { + let S(_, n, _) = C; + assert!(n != 0xBAD); + assert_eq!(n, 0x600D); +} diff --git a/tests/ui/consts/const-enum-tuplestruct2.rs b/tests/ui/consts/const-enum-tuplestruct2.rs new file mode 100644 index 000000000..b8aa9a315 --- /dev/null +++ b/tests/ui/consts/const-enum-tuplestruct2.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] + +enum E { V0, V16(u16) } +struct S(E, u16, u16); +static C: S = S(E::V0, 0x600D, 0xBAD); + +pub fn main() { + let S(_, n, _) = C; + assert!(n != 0xBAD); + assert_eq!(n, 0x600D); +} diff --git a/tests/ui/consts/const-enum-vec-index.rs b/tests/ui/consts/const-enum-vec-index.rs new file mode 100644 index 000000000..3f155340a --- /dev/null +++ b/tests/ui/consts/const-enum-vec-index.rs @@ -0,0 +1,30 @@ +// run-pass +#[derive(Copy, Clone)] +enum E { V1(isize), V0 } + +const C: &'static [E] = &[E::V0, E::V1(0xDEADBEE)]; +static C0: E = C[0]; +static C1: E = C[1]; +const D: &'static [E; 2] = &[E::V0, E::V1(0xDEAFBEE)]; +static D0: E = D[0]; +static D1: E = D[1]; + +pub fn main() { + match C0 { + E::V0 => (), + _ => panic!() + } + match C1 { + E::V1(n) => assert_eq!(n, 0xDEADBEE), + _ => panic!() + } + + match D0 { + E::V0 => (), + _ => panic!() + } + match D1 { + E::V1(n) => assert_eq!(n, 0xDEAFBEE), + _ => panic!() + } +} diff --git a/tests/ui/consts/const-enum-vec-ptr.rs b/tests/ui/consts/const-enum-vec-ptr.rs new file mode 100644 index 000000000..43ffe6570 --- /dev/null +++ b/tests/ui/consts/const-enum-vec-ptr.rs @@ -0,0 +1,15 @@ +// run-pass + +enum E { V1(isize), V0 } +static C: &'static [E] = &[E::V0, E::V1(0xDEADBEE), E::V0]; + +pub fn main() { + match C[1] { + E::V1(n) => assert_eq!(n, 0xDEADBEE), + _ => panic!() + } + match C[2] { + E::V0 => (), + _ => panic!() + } +} diff --git a/tests/ui/consts/const-enum-vector.rs b/tests/ui/consts/const-enum-vector.rs new file mode 100644 index 000000000..ee3739f97 --- /dev/null +++ b/tests/ui/consts/const-enum-vector.rs @@ -0,0 +1,15 @@ +// run-pass + +enum E { V1(isize), V0 } +static C: [E; 3] = [E::V0, E::V1(0xDEADBEE), E::V0]; + +pub fn main() { + match C[1] { + E::V1(n) => assert_eq!(n, 0xDEADBEE), + _ => panic!() + } + match C[2] { + E::V0 => (), + _ => panic!() + } +} diff --git a/tests/ui/consts/const-err-early.rs b/tests/ui/consts/const-err-early.rs new file mode 100644 index 000000000..a3105b4fc --- /dev/null +++ b/tests/ui/consts/const-err-early.rs @@ -0,0 +1,14 @@ +pub const A: i8 = -i8::MIN; //~ ERROR constant +pub const B: u8 = 200u8 + 200u8; //~ ERROR constant +pub const C: u8 = 200u8 * 4; //~ ERROR constant +pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR constant +pub const E: u8 = [5u8][1]; //~ ERROR constant + +fn main() { + let _a = A; + let _b = B; + let _c = C; + let _d = D; + let _e = E; + let _e = [6u8][1]; +} diff --git a/tests/ui/consts/const-err-early.stderr b/tests/ui/consts/const-err-early.stderr new file mode 100644 index 000000000..59bf637b7 --- /dev/null +++ b/tests/ui/consts/const-err-early.stderr @@ -0,0 +1,33 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-err-early.rs:1:19 + | +LL | pub const A: i8 = -i8::MIN; + | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-err-early.rs:2:19 + | +LL | pub const B: u8 = 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-err-early.rs:3:19 + | +LL | pub const C: u8 = 200u8 * 4; + | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-err-early.rs:4:19 + | +LL | pub const D: u8 = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-err-early.rs:5:19 + | +LL | pub const E: u8 = [5u8][1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err-late.rs b/tests/ui/consts/const-err-late.rs new file mode 100644 index 000000000..d2476e493 --- /dev/null +++ b/tests/ui/consts/const-err-late.rs @@ -0,0 +1,20 @@ +// build-fail +// compile-flags: -C overflow-checks=on + +#![allow(arithmetic_overflow, unconditional_panic)] + +fn black_box(_: T) { + unimplemented!() +} + +struct S(T); + +impl S { + const FOO: u8 = [5u8][1]; + //~^ ERROR evaluation of `S::::FOO` failed + //~| ERROR evaluation of `S::::FOO` failed +} + +fn main() { + black_box((S::::FOO, S::::FOO)); //~ constant +} diff --git a/tests/ui/consts/const-err-late.stderr b/tests/ui/consts/const-err-late.stderr new file mode 100644 index 000000000..c5c668189 --- /dev/null +++ b/tests/ui/consts/const-err-late.stderr @@ -0,0 +1,51 @@ +error[E0080]: evaluation of `S::::FOO` failed + --> $DIR/const-err-late.rs:13:21 + | +LL | const FOO: u8 = [5u8][1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + +note: erroneous constant used + --> $DIR/const-err-late.rs:19:16 + | +LL | black_box((S::::FOO, S::::FOO)); + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-err-late.rs:19:16 + | +LL | black_box((S::::FOO, S::::FOO)); + | ^^^^^^^^^^^^^ + +error[E0080]: evaluation of `S::::FOO` failed + --> $DIR/const-err-late.rs:13:21 + | +LL | const FOO: u8 = [5u8][1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + +note: erroneous constant used + --> $DIR/const-err-late.rs:19:31 + | +LL | black_box((S::::FOO, S::::FOO)); + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-err-late.rs:19:31 + | +LL | black_box((S::::FOO, S::::FOO)); + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-err-late.rs:19:16 + | +LL | black_box((S::::FOO, S::::FOO)); + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-err-late.rs:19:31 + | +LL | black_box((S::::FOO, S::::FOO)); + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err-multi.rs b/tests/ui/consts/const-err-multi.rs new file mode 100644 index 000000000..b265bc4c4 --- /dev/null +++ b/tests/ui/consts/const-err-multi.rs @@ -0,0 +1,12 @@ +pub const A: i8 = -i8::MIN; +//~^ ERROR constant +pub const B: i8 = A; +//~^ constant +pub const C: u8 = A as u8; +//~^ constant +pub const D: i8 = 50 - A; +//~^ constant + +fn main() { + let _ = (A, B, C, D); +} diff --git a/tests/ui/consts/const-err-multi.stderr b/tests/ui/consts/const-err-multi.stderr new file mode 100644 index 000000000..28af8e5eb --- /dev/null +++ b/tests/ui/consts/const-err-multi.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-err-multi.rs:1:19 + | +LL | pub const A: i8 = -i8::MIN; + | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow + +note: erroneous constant used + --> $DIR/const-err-multi.rs:3:19 + | +LL | pub const B: i8 = A; + | ^ + +note: erroneous constant used + --> $DIR/const-err-multi.rs:5:19 + | +LL | pub const C: u8 = A as u8; + | ^ + +note: erroneous constant used + --> $DIR/const-err-multi.rs:7:24 + | +LL | pub const D: i8 = 50 - A; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err-rpass.rs b/tests/ui/consts/const-err-rpass.rs new file mode 100644 index 000000000..e7fa10a2a --- /dev/null +++ b/tests/ui/consts/const-err-rpass.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// check for const_err regressions + +const X: *const u8 = b"" as _; +const Y: bool = 'A' == 'B'; +const Z: char = 'A'; +const W: bool = Z <= 'B'; + + +fn main() { + let _ = ((-1 as i8) << 8 - 1) as f32; + let _ = 0u8 as char; + let _ = true > false; + let _ = true >= false; + let _ = true < false; + let _ = true >= false; +} diff --git a/tests/ui/consts/const-err2.noopt.stderr b/tests/ui/consts/const-err2.noopt.stderr new file mode 100644 index 000000000..8b1688c4a --- /dev/null +++ b/tests/ui/consts/const-err2.noopt.stderr @@ -0,0 +1,48 @@ +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 + | +LL | let a = -i8::MIN; + | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 + | +LL | let a_i128 = -i128::MIN; + | ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 + | +LL | let b_i128 = i128::MIN - i128::MAX; + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to 7 previous errors + diff --git a/tests/ui/consts/const-err2.opt.stderr b/tests/ui/consts/const-err2.opt.stderr new file mode 100644 index 000000000..8b1688c4a --- /dev/null +++ b/tests/ui/consts/const-err2.opt.stderr @@ -0,0 +1,48 @@ +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 + | +LL | let a = -i8::MIN; + | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 + | +LL | let a_i128 = -i128::MIN; + | ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 + | +LL | let b_i128 = i128::MIN - i128::MAX; + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to 7 previous errors + diff --git a/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr b/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..8b1688c4a --- /dev/null +++ b/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr @@ -0,0 +1,48 @@ +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 + | +LL | let a = -i8::MIN; + | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 + | +LL | let a_i128 = -i128::MIN; + | ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 + | +LL | let b_i128 = i128::MIN - i128::MAX; + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to 7 previous errors + diff --git a/tests/ui/consts/const-err2.rs b/tests/ui/consts/const-err2.rs new file mode 100644 index 000000000..db49ec25a --- /dev/null +++ b/tests/ui/consts/const-err2.rs @@ -0,0 +1,39 @@ +// needed because negating int::MIN will behave differently between +// optimized compilation and unoptimized compilation and thus would +// lead to different lints being emitted + +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +// build-fail + +#![feature(rustc_attrs)] + +fn black_box(_: T) { + unimplemented!() +} + +fn main() { + let a = -i8::MIN; + //~^ ERROR arithmetic operation will overflow + let a_i128 = -i128::MIN; + //~^ ERROR arithmetic operation will overflow + let b = 200u8 + 200u8 + 200u8; + //~^ ERROR arithmetic operation will overflow + let b_i128 = i128::MIN - i128::MAX; + //~^ ERROR arithmetic operation will overflow + let c = 200u8 * 4; + //~^ ERROR arithmetic operation will overflow + let d = 42u8 - (42u8 + 1); + //~^ ERROR arithmetic operation will overflow + let _e = [5u8][1]; + //~^ ERROR operation will panic + black_box(a); + black_box(a_i128); + black_box(b); + black_box(b_i128); + black_box(c); + black_box(d); +} diff --git a/tests/ui/consts/const-err4.32bit.stderr b/tests/ui/consts/const-err4.32bit.stderr new file mode 100644 index 000000000..1cbf78173 --- /dev/null +++ b/tests/ui/consts/const-err4.32bit.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-err4.rs:9:21 + | +LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], + | ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err4.64bit.stderr b/tests/ui/consts/const-err4.64bit.stderr new file mode 100644 index 000000000..1cbf78173 --- /dev/null +++ b/tests/ui/consts/const-err4.64bit.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-err4.rs:9:21 + | +LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], + | ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err4.rs b/tests/ui/consts/const-err4.rs new file mode 100644 index 000000000..107dc3f82 --- /dev/null +++ b/tests/ui/consts/const-err4.rs @@ -0,0 +1,16 @@ +// stderr-per-bitwidth +#[derive(Copy, Clone)] +union Foo { + a: isize, + b: (), +} + +enum Bar { + Boo = [unsafe { Foo { b: () }.a }; 4][3], + //~^ ERROR evaluation of constant value failed + //~| uninitialized +} + +fn main() { + assert_ne!(Bar::Boo as isize, 0); +} diff --git a/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs b/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs new file mode 100644 index 000000000..ecf97223f --- /dev/null +++ b/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs @@ -0,0 +1,12 @@ +// New test for #53818: modifying static memory at compile-time is not allowed. +// The test should never compile successfully + +use std::cell::UnsafeCell; + +static mut FOO: u32 = 42; +static BOO: () = unsafe { + FOO = 5; + //~^ could not evaluate static initializer [E0080] +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr new file mode 100644 index 000000000..4b6784acf --- /dev/null +++ b/tests/ui/consts/const-eval/assign-to-static-within-other-static.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/assign-to-static-within-other-static.rs:8:5 + | +LL | FOO = 5; + | ^^^^^^^ modifying a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/auxiliary/post_monomorphization_error.rs b/tests/ui/consts/const-eval/auxiliary/post_monomorphization_error.rs new file mode 100644 index 000000000..bdeaa0cd3 --- /dev/null +++ b/tests/ui/consts/const-eval/auxiliary/post_monomorphization_error.rs @@ -0,0 +1,20 @@ +// Auxiliary crate used for testing post-monomorphization errors cross-crate. +// It duplicates the setup used in `stdarch` to validate its intrinsics' const arguments. + +struct ValidateConstImm; +impl ValidateConstImm { + pub(crate) const VALID: () = { + let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize); + }; +} + +macro_rules! static_assert_imm1 { + ($imm:ident) => { + let _ = $crate::ValidateConstImm::<$imm, 0, { (1 << 1) - 1 }>::VALID; + }; +} + +// This function triggers an error whenever the const argument does not fit in 1-bit. +pub fn stdarch_intrinsic() { + static_assert_imm1!(IMM1); +} diff --git a/tests/ui/consts/const-eval/auxiliary/stability.rs b/tests/ui/consts/const-eval/auxiliary/stability.rs new file mode 100644 index 000000000..e61595518 --- /dev/null +++ b/tests/ui/consts/const-eval/auxiliary/stability.rs @@ -0,0 +1,10 @@ +// Crate that exports a const fn. Used for testing cross-crate. + +#![crate_type="rlib"] +#![stable(feature = "rust1", since = "1.0.0")] + +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo", issue = "none")] +pub const fn foo() -> u32 { 42 } diff --git a/tests/ui/consts/const-eval/conditional_array_execution.rs b/tests/ui/consts/const-eval/conditional_array_execution.rs new file mode 100644 index 000000000..27d5383d6 --- /dev/null +++ b/tests/ui/consts/const-eval/conditional_array_execution.rs @@ -0,0 +1,8 @@ +const X: u32 = 5; +const Y: u32 = 6; +const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; +//~^ ERROR constant + +fn main() { + println!("{}", FOO); +} diff --git a/tests/ui/consts/const-eval/conditional_array_execution.stderr b/tests/ui/consts/const-eval/conditional_array_execution.stderr new file mode 100644 index 000000000..c3401fbae --- /dev/null +++ b/tests/ui/consts/const-eval/conditional_array_execution.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/conditional_array_execution.rs:3:19 + | +LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; + | ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.rs b/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.rs new file mode 100644 index 000000000..bdcf53785 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.rs @@ -0,0 +1,6 @@ +#![feature(core_intrinsics)] +fn main() { + // Test that calls to intrinsics are never promoted + let x: &'static usize = + &std::intrinsics::size_of::(); //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr b/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr new file mode 100644 index 000000000..ed6a6ee6e --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-intrinsic-promotion.stderr @@ -0,0 +1,13 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-eval-intrinsic-promotion.rs:5:10 + | +LL | let x: &'static usize = + | -------------- type annotation requires that borrow lasts for `'static` +LL | &std::intrinsics::size_of::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.rs b/tests/ui/consts/const-eval/const-eval-overflow-2.rs new file mode 100644 index 000000000..535d91359 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.rs @@ -0,0 +1,20 @@ +// Evaluation of constants in refutable patterns goes through +// different compiler control-flow paths. + +#![allow(unused_imports, warnings)] + +use std::fmt; +use std::{i8, i16, i32, i64, isize}; +use std::{u8, u16, u32, u64, usize}; + +const NEG_128: i8 = -128; +const NEG_NEG_128: i8 = -NEG_128; //~ ERROR constant + +fn main() { + match -128i8 { + NEG_NEG_128 => println!("A"), + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + _ => println!("B"), + } +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr new file mode 100644 index 000000000..7b1fe49d4 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow-2.rs:11:25 + | +LL | const NEG_NEG_128: i8 = -NEG_128; + | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow + +error: could not evaluate constant pattern + --> $DIR/const-eval-overflow-2.rs:15:9 + | +LL | NEG_NEG_128 => println!("A"), + | ^^^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const-eval-overflow-2.rs:15:9 + | +LL | NEG_NEG_128 => println!("A"), + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-3.rs b/tests/ui/consts/const-eval/const-eval-overflow-3.rs new file mode 100644 index 000000000..bcc966dc9 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-3.rs @@ -0,0 +1,27 @@ +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. + + + + + + + +#![allow(unused_imports)] + +use std::fmt; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1) as usize]; +//~^ ERROR evaluation of constant value failed + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow-3.stderr b/tests/ui/consts/const-eval/const-eval-overflow-3.stderr new file mode 100644 index 000000000..73f421b5b --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-3.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow-3.rs:18:11 + | +LL | = [0; (i8::MAX + 1) as usize]; + | ^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-3b.rs b/tests/ui/consts/const-eval/const-eval-overflow-3b.rs new file mode 100644 index 000000000..480069e67 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-3b.rs @@ -0,0 +1,26 @@ +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array expression. +// +// This is a variation of another such test, but in this case the +// types for the left- and right-hand sides of the addition do not +// match (as well as overflow). + +#![allow(unused_imports)] + +use std::fmt; + +const A_I8_I + : [u32; (i8::MAX as usize) + 1] + = [0; (i8::MAX + 1u8) as usize]; +//~^ ERROR mismatched types +//~| ERROR cannot add `u8` to `i8` + +fn main() { + foo(&A_I8_I[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr new file mode 100644 index 000000000..f19917001 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/const-eval-overflow-3b.rs:16:22 + | +LL | = [0; (i8::MAX + 1u8) as usize]; + | ^^^ expected `i8`, found `u8` + +error[E0277]: cannot add `u8` to `i8` in const contexts + --> $DIR/const-eval-overflow-3b.rs:16:20 + | +LL | = [0; (i8::MAX + 1u8) as usize]; + | ^ no implementation for `i8 + u8` + | + = help: the trait `~const Add` is not implemented for `i8` + = help: the following other types implement trait `Add`: + <&'a i8 as Add> + <&i8 as Add<&i8>> + > + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4.rs b/tests/ui/consts/const-eval/const-eval-overflow-4.rs new file mode 100644 index 000000000..762c7a968 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-4.rs @@ -0,0 +1,21 @@ +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +use std::fmt; + +const A_I8_T + : [u32; (i8::MAX as i8 + 1i8) as usize] + //~^ ERROR evaluation of constant value failed + = [0; (i8::MAX as usize) + 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4.stderr new file mode 100644 index 000000000..94f419319 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-4.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow-4.rs:11:13 + | +LL | : [u32; (i8::MAX as i8 + 1i8) as usize] + | ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4b.rs b/tests/ui/consts/const-eval/const-eval-overflow-4b.rs new file mode 100644 index 000000000..ce9c980de --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-4b.rs @@ -0,0 +1,26 @@ +// Evaluation of constants in array-elem count goes through different +// compiler control-flow paths. +// +// This test is checking the count in an array type. + +#![allow(unused_imports)] + +const A_I8_T + : [u32; (i8::MAX as i8 + 1u8) as usize] + //~^ ERROR mismatched types + //~| expected `i8`, found `u8` + //~| ERROR cannot add `u8` to `i8` + = [0; (i8::MAX as usize) + 1]; + + +const A_CHAR_USIZE + : [u32; 5u8 as char as usize] + = [0; 5]; + + +const A_BAD_CHAR_USIZE + : [u32; 5i8 as char as usize] + //~^ ERROR only `u8` can be cast as `char`, not `i8` + = [0; 5]; + +fn main() {} diff --git a/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr new file mode 100644 index 000000000..1f8e40231 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/const-eval-overflow-4b.rs:9:30 + | +LL | : [u32; (i8::MAX as i8 + 1u8) as usize] + | ^^^ expected `i8`, found `u8` + +error[E0277]: cannot add `u8` to `i8` in const contexts + --> $DIR/const-eval-overflow-4b.rs:9:28 + | +LL | : [u32; (i8::MAX as i8 + 1u8) as usize] + | ^ no implementation for `i8 + u8` + | + = help: the trait `~const Add` is not implemented for `i8` + = help: the following other types implement trait `Add`: + <&'a i8 as Add> + <&i8 as Add<&i8>> + > + + +error[E0604]: only `u8` can be cast as `char`, not `i8` + --> $DIR/const-eval-overflow-4b.rs:22:13 + | +LL | : [u32; 5i8 as char as usize] + | ^^^^^^^^^^^ invalid cast + | +help: try casting from `u8` instead + --> $DIR/const-eval-overflow-4b.rs:22:13 + | +LL | : [u32; 5i8 as char as usize] + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308, E0604. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow2.rs b/tests/ui/consts/const-eval/const-eval-overflow2.rs new file mode 100644 index 000000000..1676f7c2a --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow2.rs @@ -0,0 +1,69 @@ +#![allow(unused_imports)] + +// Note: the relevant lint pass here runs before some of the constant +// evaluation below (e.g., that performed by codegen and llvm), so if you +// change this warn to a deny, then the compiler will exit before +// those errors are detected. + +use std::fmt; + +const VALS_I8: (i8,) = + ( + i8::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I16: (i16,) = + ( + i16::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I32: (i32,) = + ( + i32::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I64: (i64,) = + ( + i64::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U8: (u8,) = + ( + u8::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U16: (u16,) = ( + u16::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U32: (u32,) = ( + u32::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U64: (u64,) = + ( + u64::MIN - 1, + ); + //~^^ ERROR evaluation of constant value failed + +fn main() { + foo(VALS_I8); + foo(VALS_I16); + foo(VALS_I32); + foo(VALS_I64); + + foo(VALS_U8); + foo(VALS_U16); + foo(VALS_U32); + foo(VALS_U64); +} + +fn foo(_: T) { +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow2.stderr b/tests/ui/consts/const-eval/const-eval-overflow2.stderr new file mode 100644 index 000000000..341c15daf --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow2.stderr @@ -0,0 +1,51 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:12:6 + | +LL | i8::MIN - 1, + | ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:18:6 + | +LL | i16::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:24:6 + | +LL | i32::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:30:6 + | +LL | i64::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:36:6 + | +LL | u8::MIN - 1, + | ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:41:6 + | +LL | u16::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:46:6 + | +LL | u32::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2.rs:52:6 + | +LL | u64::MIN - 1, + | ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow2b.rs b/tests/ui/consts/const-eval/const-eval-overflow2b.rs new file mode 100644 index 000000000..59d1df568 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow2b.rs @@ -0,0 +1,69 @@ +#![allow(unused_imports)] + +// Note: the relevant lint pass here runs before some of the constant +// evaluation below (e.g., that performed by codegen and llvm), so if you +// change this warn to a deny, then the compiler will exit before +// those errors are detected. + +use std::fmt; + +const VALS_I8: (i8,) = + ( + i8::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I16: (i16,) = + ( + i16::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I32: (i32,) = + ( + i32::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I64: (i64,) = + ( + i64::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U8: (u8,) = + ( + u8::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U16: (u16,) = ( + u16::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U32: (u32,) = ( + u32::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U64: (u64,) = + ( + u64::MAX + 1, + ); + //~^^ ERROR evaluation of constant value failed + +fn main() { + foo(VALS_I8); + foo(VALS_I16); + foo(VALS_I32); + foo(VALS_I64); + + foo(VALS_U8); + foo(VALS_U16); + foo(VALS_U32); + foo(VALS_U64); +} + +fn foo(_: T) { +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow2b.stderr b/tests/ui/consts/const-eval/const-eval-overflow2b.stderr new file mode 100644 index 000000000..e661836b4 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow2b.stderr @@ -0,0 +1,51 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:12:6 + | +LL | i8::MAX + 1, + | ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:18:6 + | +LL | i16::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:24:6 + | +LL | i32::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:30:6 + | +LL | i64::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:36:6 + | +LL | u8::MAX + 1, + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:41:6 + | +LL | u16::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:46:6 + | +LL | u32::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2b.rs:52:6 + | +LL | u64::MAX + 1, + | ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-overflow2c.rs b/tests/ui/consts/const-eval/const-eval-overflow2c.rs new file mode 100644 index 000000000..33b892601 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow2c.rs @@ -0,0 +1,69 @@ +#![allow(unused_imports)] + +// Note: the relevant lint pass here runs before some of the constant +// evaluation below (e.g., that performed by codegen and llvm), so if you +// change this warn to a deny, then the compiler will exit before +// those errors are detected. + +use std::fmt; + +const VALS_I8: (i8,) = + ( + i8::MIN * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I16: (i16,) = + ( + i16::MIN * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I32: (i32,) = + ( + i32::MIN * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_I64: (i64,) = + ( + i64::MIN * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U8: (u8,) = + ( + u8::MAX * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U16: (u16,) = ( + u16::MAX * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U32: (u32,) = ( + u32::MAX * 2, + ); + //~^^ ERROR evaluation of constant value failed + +const VALS_U64: (u64,) = + ( + u64::MAX * 2, + ); + //~^^ ERROR evaluation of constant value failed + +fn main() { + foo(VALS_I8); + foo(VALS_I16); + foo(VALS_I32); + foo(VALS_I64); + + foo(VALS_U8); + foo(VALS_U16); + foo(VALS_U32); + foo(VALS_U64); +} + +fn foo(_: T) { +} diff --git a/tests/ui/consts/const-eval/const-eval-overflow2c.stderr b/tests/ui/consts/const-eval/const-eval-overflow2c.stderr new file mode 100644 index 000000000..1fad15492 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-overflow2c.stderr @@ -0,0 +1,51 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:12:6 + | +LL | i8::MIN * 2, + | ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:18:6 + | +LL | i16::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:24:6 + | +LL | i32::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:30:6 + | +LL | i64::MIN * 2, + | ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:36:6 + | +LL | u8::MAX * 2, + | ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:41:6 + | +LL | u16::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:46:6 + | +LL | u32::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow2c.rs:52:6 + | +LL | u64::MAX * 2, + | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.rs b/tests/ui/consts/const-eval/const-eval-query-stack.rs new file mode 100644 index 000000000..8f8a8cee3 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-query-stack.rs @@ -0,0 +1,22 @@ +// compile-flags: -Ztreat-err-as-bug=1 +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=1 +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "thread.*panicked.*\n" -> "" +// normalize-stderr-test "stack backtrace:\n" -> "" +// normalize-stderr-test "\s\d{1,}: .*\n" -> "" +// normalize-stderr-test "\s at .*\n" -> "" +// normalize-stderr-test ".*note: Some details.*\n" -> "" + +#![allow(unconditional_panic)] + +const X: i32 = 1 / 0; //~ERROR constant + +fn main() { + let x: &'static i32 = &X; + println!("x={}", x); +} diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr new file mode 100644 index 000000000..b97975c4c --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr @@ -0,0 +1,13 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-query-stack.rs:17:16 + | +LL | const X: i32 = 1 / 0; + | ^^^^^ attempt to divide `1_i32` by zero + +query stack during panic: +#0 [eval_to_allocation_raw] const-evaluating + checking `X` +#1 [eval_to_const_value_raw] simplifying constant for the type system `X` +#2 [eval_to_const_value_raw] simplifying constant for the type system `X` +#3 [lint_mod] linting top-level module +#4 [analysis] running analysis passes on this crate +end of query stack diff --git a/tests/ui/consts/const-eval/const-eval-span.rs b/tests/ui/consts/const-eval/const-eval-span.rs new file mode 100644 index 000000000..82f101b47 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-span.rs @@ -0,0 +1,14 @@ +// Check that error in constant evaluation of enum discriminant +// provides the context for what caused the evaluation. + +struct S(i32); + +const CONSTANT: S = S(0); + +enum E { + V = CONSTANT, + //~^ ERROR mismatched types + //~| expected `isize`, found struct `S` +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/const-eval-span.stderr b/tests/ui/consts/const-eval/const-eval-span.stderr new file mode 100644 index 000000000..c5b001899 --- /dev/null +++ b/tests/ui/consts/const-eval/const-eval-span.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/const-eval-span.rs:9:9 + | +LL | V = CONSTANT, + | ^^^^^^^^ expected `isize`, found struct `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr new file mode 100644 index 000000000..bf98d0394 --- /dev/null +++ b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr @@ -0,0 +1,258 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:26:49 + | +LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:29:43 + | +LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:32:45 + | +LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:35:45 + | +LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:38:45 + | +LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:41:47 + | +LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:45:43 + | +LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:48:45 + | +LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:51:45 + | +LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:54:45 + | +LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:57:47 + | +LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:61:45 + | +LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:64:45 + | +LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:67:47 + | +LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:70:47 + | +LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:73:39 + | +LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:76:41 + | +LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:79:41 + | +LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:82:41 + | +LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:85:43 + | +LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:88:39 + | +LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:91:41 + | +LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:94:41 + | +LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:97:41 + | +LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:100:43 + | +LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:103:41 + | +LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:106:41 + | +LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:109:43 + | +LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/const-pointer-values-in-various-types.rs:112:43 + | +LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: aborting due to 29 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.rs new file mode 100644 index 000000000..45eed9d84 --- /dev/null +++ b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.rs @@ -0,0 +1,114 @@ +// only-x86_64 +// stderr-per-bitwidth + +#[repr(C)] +union Nonsense { + u: usize, + int_32_ref: &'static i32, + uint_8: u8, + uint_16: u16, + uint_32: u32, + uint_64: u64, + uint_128: u128, + int_8: i8, + int_16: i16, + int_32: i32, + int_64: i64, + int_128: i128, + float_32: f32, + float_64: f64, + truthy_falsey: bool, + character: char, + stringy: &'static str, +} + +fn main() { + const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; + //~^ ERROR evaluation of constant value failed + //~| uninitialized + + const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; + //~^ ERROR evaluation of constant value failed + //~| uninitialized + + const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; + //~^ ERROR evaluation of constant value failed + + const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; + //~^ ERROR evaluation of constant value failed + + const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; + //~^ ERROR evaluation of constant value failed + + const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; + //~^ ERROR evaluation of constant value failed + + const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; + //~^ ERROR evaluation of constant value failed + + const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; + //~^ ERROR evaluation of constant value failed + + const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; + //~^ ERROR evaluation of constant value failed + + const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; + //~^ ERROR evaluation of constant value failed + + const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; + //~^ ERROR evaluation of constant value failed + + const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; + //~^ ERROR evaluation of constant value failed + + const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; + //~^ ERROR evaluation of constant value failed + + const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; + //~^ ERROR evaluation of constant value failed + + const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; + //~^ ERROR evaluation of constant value failed + + const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; + //~^ ERROR evaluation of constant value failed + + const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; + //~^ ERROR evaluation of constant value failed + + const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; + //~^ ERROR evaluation of constant value failed +} diff --git a/tests/ui/consts/const-eval/const_fn_ptr.rs b/tests/ui/consts/const-eval/const_fn_ptr.rs new file mode 100644 index 000000000..b3c677c69 --- /dev/null +++ b/tests/ui/consts/const-eval/const_fn_ptr.rs @@ -0,0 +1,36 @@ +// run-pass +// compile-flags: -Zunleash-the-miri-inside-of-you + +fn double(x: usize) -> usize { x * 2 } +const fn double_const(x: usize) -> usize { x * 2 } + +const X: fn(usize) -> usize = double; +const X_CONST: fn(usize) -> usize = double_const; + +const fn bar(x: usize) -> usize { + X(x) +} + +const fn bar_const(x: usize) -> usize { + X_CONST(x) +} + +const fn foo(x: fn(usize) -> usize, y: usize) -> usize { + x(y) +} + +fn main() { + const Y: usize = bar_const(2); + assert_eq!(Y, 4); + let y = bar_const(2); + assert_eq!(y, 4); + let y = bar(2); + assert_eq!(y, 4); + + const Z: usize = foo(double_const, 2); + assert_eq!(Z, 4); + let z = foo(double_const, 2); + assert_eq!(z, 4); + let z = foo(double, 2); + assert_eq!(z, 4); +} diff --git a/tests/ui/consts/const-eval/const_fn_ptr.stderr b/tests/ui/consts/const-eval/const_fn_ptr.stderr new file mode 100644 index 000000000..ca1585f88 --- /dev/null +++ b/tests/ui/consts/const-eval/const_fn_ptr.stderr @@ -0,0 +1,20 @@ +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_fn_ptr.rs:11:5 + | +LL | X(x) + | ^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_fn_ptr.rs:15:5 + | +LL | X_CONST(x) + | ^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_fn_ptr.rs:19:5 + | +LL | x(y) + | ^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail.rs b/tests/ui/consts/const-eval/const_fn_ptr_fail.rs new file mode 100644 index 000000000..1896eba82 --- /dev/null +++ b/tests/ui/consts/const-eval/const_fn_ptr_fail.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: -Zunleash-the-miri-inside-of-you +#![allow(unused)] + +fn double(x: usize) -> usize { x * 2 } +const X: fn(usize) -> usize = double; + +const fn bar(x: usize) -> usize { + X(x) // FIXME: this should error someday +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail.stderr b/tests/ui/consts/const-eval/const_fn_ptr_fail.stderr new file mode 100644 index 000000000..ec5de5759 --- /dev/null +++ b/tests/ui/consts/const-eval/const_fn_ptr_fail.stderr @@ -0,0 +1,10 @@ +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_fn_ptr_fail.rs:9:5 + | +LL | X(x) // FIXME: this should error someday + | ^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs b/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs new file mode 100644 index 000000000..b873940c4 --- /dev/null +++ b/tests/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -0,0 +1,20 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +fn double(x: usize) -> usize { + x * 2 +} +const X: fn(usize) -> usize = double; + +const fn bar(x: fn(usize) -> usize, y: usize) -> usize { + x(y) + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed +} + +const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday +const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday + +fn main() { + assert_eq!(Y, 4); + assert_eq!(Z, 4); +} diff --git a/tests/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/tests/ui/consts/const-eval/const_fn_ptr_fail2.stderr new file mode 100644 index 000000000..0734f479f --- /dev/null +++ b/tests/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -0,0 +1,45 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_fn_ptr_fail2.rs:9:5 + | +LL | x(y) + | ^^^^ calling non-const function `double` + | +note: inside `bar` + --> $DIR/const_fn_ptr_fail2.rs:9:5 + | +LL | x(y) + | ^^^^ +note: inside `Y` + --> $DIR/const_fn_ptr_fail2.rs:14:18 + | +LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday + | ^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/const_fn_ptr_fail2.rs:9:5 + | +LL | x(y) + | ^^^^ calling non-const function `double` + | +note: inside `bar` + --> $DIR/const_fn_ptr_fail2.rs:9:5 + | +LL | x(y) + | ^^^^ +note: inside `Z` + --> $DIR/const_fn_ptr_fail2.rs:15:18 + | +LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday + | ^^^^^^^^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_fn_ptr_fail2.rs:9:5 + | +LL | x(y) + | ^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_let.rs b/tests/ui/consts/const-eval/const_let.rs new file mode 100644 index 000000000..1e2bcc55b --- /dev/null +++ b/tests/ui/consts/const-eval/const_let.rs @@ -0,0 +1,29 @@ +fn main() {} + +struct FakeNeedsDrop; + +impl Drop for FakeNeedsDrop { + fn drop(&mut self) {} +} + +// ok +const X: FakeNeedsDrop = { let x = FakeNeedsDrop; x }; + +// ok (used to incorrectly error, see #62273) +const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x }; + +// error +const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; +//~^ ERROR destructor of + +// error +const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; +//~^ ERROR destructor of + +// error +const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; +//~^ ERROR destructor of + +// error +const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; +//~^ ERROR destructor of diff --git a/tests/ui/consts/const-eval/const_let.stderr b/tests/ui/consts/const-eval/const_let.stderr new file mode 100644 index 000000000..63442f557 --- /dev/null +++ b/tests/ui/consts/const-eval/const_let.stderr @@ -0,0 +1,35 @@ +error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time + --> $DIR/const_let.rs:16:32 + | +LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x }; + | ^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time + --> $DIR/const_let.rs:20:33 + | +LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x }; + | ^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/const_let.rs:24:21 + | +LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); }; + | ^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/const_let.rs:28:22 + | +LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); }; + | ^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-eval/const_panic.rs b/tests/ui/consts/const-eval/const_panic.rs new file mode 100644 index 000000000..5b9a8f8e2 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic.rs @@ -0,0 +1,40 @@ +#![allow(non_fmt_panics)] +#![crate_type = "lib"] + +const MSG: &str = "hello"; + +const Z: () = std::panic!("cheese"); +//~^ ERROR evaluation of constant value failed + +const Z2: () = std::panic!(); +//~^ ERROR evaluation of constant value failed + +const Y: () = std::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const X: () = std::unimplemented!(); +//~^ ERROR evaluation of constant value failed + +const W: () = std::panic!(MSG); +//~^ ERROR evaluation of constant value failed + +const W2: () = std::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed + +const Z_CORE: () = core::panic!("cheese"); +//~^ ERROR evaluation of constant value failed + +const Z2_CORE: () = core::panic!(); +//~^ ERROR evaluation of constant value failed + +const Y_CORE: () = core::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const X_CORE: () = core::unimplemented!(); +//~^ ERROR evaluation of constant value failed + +const W_CORE: () = core::panic!(MSG); +//~^ ERROR evaluation of constant value failed + +const W2_CORE: () = core::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed diff --git a/tests/ui/consts/const-eval/const_panic.stderr b/tests/ui/consts/const-eval/const_panic.stderr new file mode 100644 index 000000000..0f7be4607 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic.stderr @@ -0,0 +1,99 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:6:15 + | +LL | const Z: () = std::panic!("cheese"); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:6:15 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:9:16 + | +LL | const Z2: () = std::panic!(); + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:9:16 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:12:15 + | +LL | const Y: () = std::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:12:15 + | + = note: this error originates in the macro `$crate::panic::unreachable_2015` which comes from the expansion of the macro `std::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:15:15 + | +LL | const X: () = std::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:15:15 + | + = note: this error originates in the macro `std::unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:18:15 + | +LL | const W: () = std::panic!(MSG); + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:18:15 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:21:16 + | +LL | const W2: () = std::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:21:16 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:24:20 + | +LL | const Z_CORE: () = core::panic!("cheese"); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:24:20 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:27:21 + | +LL | const Z2_CORE: () = core::panic!(); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:27:21 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:30:20 + | +LL | const Y_CORE: () = core::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:30:20 + | + = note: this error originates in the macro `$crate::panic::unreachable_2015` which comes from the expansion of the macro `core::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:33:20 + | +LL | const X_CORE: () = core::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:33:20 + | + = note: this error originates in the macro `core::unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:36:20 + | +LL | const W_CORE: () = core::panic!(MSG); + | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:36:20 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic.rs:39:21 + | +LL | const W2_CORE: () = core::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:39:21 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_panic_2021.rs b/tests/ui/consts/const-eval/const_panic_2021.rs new file mode 100644 index 000000000..4702aa2f5 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_2021.rs @@ -0,0 +1,34 @@ +// edition:2021 +#![crate_type = "lib"] + +const MSG: &str = "hello"; + +const A: () = std::panic!("blåhaj"); +//~^ ERROR evaluation of constant value failed + +const B: () = std::panic!(); +//~^ ERROR evaluation of constant value failed + +const C: () = std::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const D: () = std::unimplemented!(); +//~^ ERROR evaluation of constant value failed + +const E: () = std::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed + +const A_CORE: () = core::panic!("shark"); +//~^ ERROR evaluation of constant value failed + +const B_CORE: () = core::panic!(); +//~^ ERROR evaluation of constant value failed + +const C_CORE: () = core::unreachable!(); +//~^ ERROR evaluation of constant value failed + +const D_CORE: () = core::unimplemented!(); +//~^ ERROR evaluation of constant value failed + +const E_CORE: () = core::panic!("{}", MSG); +//~^ ERROR evaluation of constant value failed diff --git a/tests/ui/consts/const-eval/const_panic_2021.stderr b/tests/ui/consts/const-eval/const_panic_2021.stderr new file mode 100644 index 000000000..192fa3a12 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_2021.stderr @@ -0,0 +1,83 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:6:15 + | +LL | const A: () = std::panic!("blåhaj"); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:6:15 + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:9:15 + | +LL | const B: () = std::panic!(); + | ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:9:15 + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:12:15 + | +LL | const C: () = std::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:12:15 + | + = note: this error originates in the macro `$crate::panic::unreachable_2021` which comes from the expansion of the macro `std::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:15:15 + | +LL | const D: () = std::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:15:15 + | + = note: this error originates in the macro `std::unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:18:15 + | +LL | const E: () = std::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:18:15 + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:21:20 + | +LL | const A_CORE: () = core::panic!("shark"); + | ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:21:20 + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:24:20 + | +LL | const B_CORE: () = core::panic!(); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:24:20 + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:27:20 + | +LL | const C_CORE: () = core::unreachable!(); + | ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:27:20 + | + = note: this error originates in the macro `$crate::panic::unreachable_2021` which comes from the expansion of the macro `core::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:30:20 + | +LL | const D_CORE: () = core::unimplemented!(); + | ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:30:20 + | + = note: this error originates in the macro `core::unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_2021.rs:33:20 + | +LL | const E_CORE: () = core::panic!("{}", MSG); + | ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:33:20 + | + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_panic_libcore_bin.rs b/tests/ui/consts/const-eval/const_panic_libcore_bin.rs new file mode 100644 index 000000000..d4dc1a51d --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_libcore_bin.rs @@ -0,0 +1,25 @@ +#![crate_type = "bin"] +#![feature(lang_items)] +#![no_main] +#![no_std] + +use core::panic::PanicInfo; + +const Z: () = panic!("cheese"); +//~^ ERROR evaluation of constant value failed + +const Y: () = unreachable!(); +//~^ ERROR evaluation of constant value failed + +const X: () = unimplemented!(); +//~^ ERROR evaluation of constant value failed + +#[lang = "eh_personality"] +fn eh() {} +#[lang = "eh_catch_typeinfo"] +static EH_CATCH_TYPEINFO: u8 = 0; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr b/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr new file mode 100644 index 000000000..df19ed4a8 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_libcore_bin.rs:8:15 + | +LL | const Z: () = panic!("cheese"); + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_bin.rs:8:15 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_libcore_bin.rs:11:15 + | +LL | const Y: () = unreachable!(); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_bin.rs:11:15 + | + = note: this error originates in the macro `$crate::panic::unreachable_2015` which comes from the expansion of the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_libcore_bin.rs:14:15 + | +LL | const X: () = unimplemented!(); + | ^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_libcore_bin.rs:14:15 + | + = note: this error originates in the macro `unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_panic_stability.e2018.stderr b/tests/ui/consts/const-eval/const_panic_stability.e2018.stderr new file mode 100644 index 000000000..3553a18d3 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_stability.e2018.stderr @@ -0,0 +1,16 @@ +warning: panic message is not a string literal + --> $DIR/const_panic_stability.rs:14:12 + | +LL | panic!({ "foo" }); + | ^^^^^^^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: `#[warn(non_fmt_panics)]` on by default +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", { "foo" }); + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr b/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr new file mode 100644 index 000000000..9e8179181 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_stability.e2021.stderr @@ -0,0 +1,13 @@ +error: format argument must be a string literal + --> $DIR/const_panic_stability.rs:14:12 + | +LL | panic!({ "foo" }); + | ^^^^^^^^^ + | +help: you might be missing a string literal to format with + | +LL | panic!("{}", { "foo" }); + | +++++ + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/const_panic_stability.rs b/tests/ui/consts/const-eval/const_panic_stability.rs new file mode 100644 index 000000000..1aee6f27e --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_stability.rs @@ -0,0 +1,17 @@ +// revisions: e2018 e2021 +//[e2018] edition:2018 +//[e2021] edition:2021 +//[e2018] check-pass +#![crate_type = "lib"] +#![stable(feature = "foo", since = "1.0.0")] +#![feature(staged_api)] + +#[stable(feature = "foo", since = "1.0.0")] +#[rustc_const_stable(feature = "foo", since = "1.0.0")] +const fn foo() { + assert!(false); + assert!(false, "foo"); + panic!({ "foo" }); + //[e2018]~^ WARNING panic message is not a string literal + //[e2021]~^^ ERROR format argument must be a string literal +} diff --git a/tests/ui/consts/const-eval/const_panic_track_caller.rs b/tests/ui/consts/const-eval/const_panic_track_caller.rs new file mode 100644 index 000000000..9cf7a3ba7 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_track_caller.rs @@ -0,0 +1,22 @@ +#![allow(non_fmt_panics)] +#![crate_type = "lib"] + +#[track_caller] +const fn a() -> u32 { + panic!("hey") +} + +#[track_caller] +const fn b() -> u32 { + a() +} + +const fn c() -> u32 { + b() + //~^ ERROR evaluation of constant value failed + //~| NOTE the evaluated program panicked + //~| NOTE inside +} + +const X: u32 = c(); +//~^ NOTE inside diff --git a/tests/ui/consts/const-eval/const_panic_track_caller.stderr b/tests/ui/consts/const-eval/const_panic_track_caller.stderr new file mode 100644 index 000000000..846458176 --- /dev/null +++ b/tests/ui/consts/const-eval/const_panic_track_caller.stderr @@ -0,0 +1,20 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_panic_track_caller.rs:15:5 + | +LL | b() + | ^^^ the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5 + | +note: inside `c` + --> $DIR/const_panic_track_caller.rs:15:5 + | +LL | b() + | ^^^ +note: inside `X` + --> $DIR/const_panic_track_caller.rs:21:16 + | +LL | const X: u32 = c(); + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_prop_errors.rs b/tests/ui/consts/const-eval/const_prop_errors.rs new file mode 100644 index 000000000..f9a36d379 --- /dev/null +++ b/tests/ui/consts/const-eval/const_prop_errors.rs @@ -0,0 +1,14 @@ +// check-pass + +pub trait Foo { + fn foo(self) -> u32; +} + +impl Foo for T { + fn foo(self) -> u32 { + fn bar() { loop {} } + bar:: as u32 + } +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops.rs b/tests/ui/consts/const-eval/const_raw_ptr_ops.rs new file mode 100644 index 000000000..cd7c98007 --- /dev/null +++ b/tests/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -0,0 +1,6 @@ +fn main() {} + +// unconst and bad, will thus error in miri +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR can't compare +// unconst and bad, will thus error in miri +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR can't compare diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops.stderr b/tests/ui/consts/const-eval/const_raw_ptr_ops.stderr new file mode 100644 index 000000000..12244450e --- /dev/null +++ b/tests/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -0,0 +1,29 @@ +error[E0277]: can't compare `*const i32` with `_` in const contexts + --> $DIR/const_raw_ptr_ops.rs:4:43 + | +LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; + | ^^ no implementation for `*const i32 == _` + | + = help: the trait `~const PartialEq<_>` is not implemented for `*const i32` +note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const` + --> $DIR/const_raw_ptr_ops.rs:4:43 + | +LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; + | ^^ + +error[E0277]: can't compare `*const i32` with `_` in const contexts + --> $DIR/const_raw_ptr_ops.rs:6:44 + | +LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; + | ^^ no implementation for `*const i32 == _` + | + = help: the trait `~const PartialEq<_>` is not implemented for `*const i32` +note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const` + --> $DIR/const_raw_ptr_ops.rs:6:44 + | +LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs b/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs new file mode 100644 index 000000000..ec5508a1e --- /dev/null +++ b/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -0,0 +1,10 @@ +fn main() {} + +// fine +const Z: i32 = unsafe { *(&1 as *const i32) }; + +// bad, will thus error in miri +const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR evaluation of constant value failed +//~| is a dangling pointer +const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR evaluation of constant value failed +//~| is a dangling pointer diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr new file mode 100644 index 000000000..e41dea873 --- /dev/null +++ b/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_raw_ptr_ops2.rs:7:26 + | +LL | const Z2: i32 = unsafe { *(42 as *const i32) }; + | ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance) + +error[E0080]: evaluation of constant value failed + --> $DIR/const_raw_ptr_ops2.rs:9:26 + | +LL | const Z3: i32 = unsafe { *(44 as *const i32) }; + | ^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2c[noalloc] is a dangling pointer (it has no provenance) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/const_signed_pat.rs b/tests/ui/consts/const-eval/const_signed_pat.rs new file mode 100644 index 000000000..c61239bb6 --- /dev/null +++ b/tests/ui/consts/const-eval/const_signed_pat.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + const MIN: i8 = -5; + match 5i8 { + MIN..=-1 => {}, + _ => {}, + } +} diff --git a/tests/ui/consts/const-eval/dangling.rs b/tests/ui/consts/const-eval/dangling.rs new file mode 100644 index 000000000..4fcf87921 --- /dev/null +++ b/tests/ui/consts/const-eval/dangling.rs @@ -0,0 +1,10 @@ +use std::mem; + +// Make sure we error with the right kind of error on a too large slice. +const TEST: () = { unsafe { + let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); + let _val = &*slice; //~ ERROR: evaluation of constant value failed + //~| slice is bigger than largest supported object +} }; + +fn main() {} diff --git a/tests/ui/consts/const-eval/dangling.stderr b/tests/ui/consts/const-eval/dangling.stderr new file mode 100644 index 000000000..92d70573d --- /dev/null +++ b/tests/ui/consts/const-eval/dangling.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/dangling.rs:6:16 + | +LL | let _val = &*slice; + | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs new file mode 100644 index 000000000..4b3cf7073 --- /dev/null +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.rs @@ -0,0 +1,24 @@ +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "none")] + +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo", issue = "none")] +const fn foo() -> u32 { 42 } + +fn meh() -> u32 { 42 } + +const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn + +fn a() { + let _: &'static u32 = &foo(); //~ ERROR temporary value dropped while borrowed +} + +fn main() { + let _: &'static u32 = &meh(); //~ ERROR temporary value dropped while borrowed + let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr new file mode 100644 index 000000000..2e697b219 --- /dev/null +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -0,0 +1,43 @@ +error: `foo` is not yet stable as a const fn + --> $DIR/dont_promote_unstable_const_fn.rs:14:25 + | +LL | const fn bar() -> u32 { foo() } + | ^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable + +error[E0716]: temporary value dropped while borrowed + --> $DIR/dont_promote_unstable_const_fn.rs:17:28 + | +LL | let _: &'static u32 = &foo(); + | ------------ ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/dont_promote_unstable_const_fn.rs:21:28 + | +LL | let _: &'static u32 = &meh(); + | ------------ ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/dont_promote_unstable_const_fn.rs:22:26 + | +LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis(); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs new file mode 100644 index 000000000..ea35f4680 --- /dev/null +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.rs @@ -0,0 +1,10 @@ +// aux-build:stability.rs + +extern crate stability; + +use stability::foo; + +fn main() { + let _: &'static u32 = &foo(); //~ ERROR temporary value dropped while borrowed + let _x: &'static u32 = &foo(); //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr new file mode 100644 index 000000000..aa742d784 --- /dev/null +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn_cross_crate.stderr @@ -0,0 +1,24 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28 + | +LL | let _: &'static u32 = &foo(); + | ------------ ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let _x: &'static u32 = &foo(); +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29 + | +LL | let _x: &'static u32 = &foo(); + | ------------ ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/double_check.rs b/tests/ui/consts/const-eval/double_check.rs new file mode 100644 index 000000000..56ca0aa1f --- /dev/null +++ b/tests/ui/consts/const-eval/double_check.rs @@ -0,0 +1,25 @@ +// check-pass + +enum Foo { + A = 5, + B = 42, +} +enum Bar { + C = 42, + D = 99, +} +#[repr(C)] +union Union { + foo: &'static Foo, + bar: &'static Bar, + u8: &'static u8, +} +static BAR: u8 = 42; +static FOO: (&Foo, &Bar) = unsafe {( + Union { u8: &BAR }.foo, + Union { u8: &BAR }.bar, +)}; + +static FOO2: (&Foo, &Bar) = unsafe {(std::mem::transmute(&BAR), std::mem::transmute(&BAR))}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/double_check2.rs b/tests/ui/consts/const-eval/double_check2.rs new file mode 100644 index 000000000..81f5dde45 --- /dev/null +++ b/tests/ui/consts/const-eval/double_check2.rs @@ -0,0 +1,32 @@ +// check-pass + +// This test exhibits undefined behavior, but it is very expensive and complex to check for such +// UB in constants. +// Thus, we do not detect it if you create references to statics in ways that are UB. + +enum Foo { + A = 5, + B = 42, +} +enum Bar { + C = 42, + D = 99, +} +#[repr(C)] +union Union { + foo: &'static Foo, + bar: &'static Bar, + u8: &'static u8, +} +static BAR: u8 = 5; +static FOO: (&Foo, &Bar) = unsafe { + ( + // undefined behavior + Union { u8: &BAR }.foo, + Union { u8: &BAR }.bar, + ) +}; +static FOO2: (&Foo, &Bar) = unsafe { (std::mem::transmute(&BAR), std::mem::transmute(&BAR)) }; +//^ undefined behavior + +fn main() {} diff --git a/tests/ui/consts/const-eval/duration_conversion.rs b/tests/ui/consts/const-eval/duration_conversion.rs new file mode 100644 index 000000000..87b12937d --- /dev/null +++ b/tests/ui/consts/const-eval/duration_conversion.rs @@ -0,0 +1,16 @@ +// check-pass + +use std::time::Duration; + +fn main() { + const _ONE_SECOND: Duration = Duration::from_nanos(1_000_000_000); + const _ONE_MILLISECOND: Duration = Duration::from_nanos(1_000_000); + const _ONE_MICROSECOND: Duration = Duration::from_nanos(1_000); + const _ONE_NANOSECOND: Duration = Duration::from_nanos(1); + const _ONE: usize = _ONE_SECOND.as_secs() as usize; + const _TWO: usize = _ONE_MILLISECOND.subsec_millis() as usize; + const _THREE: usize = _ONE_MICROSECOND.subsec_micros() as usize; + const _FOUR: usize = _ONE_NANOSECOND.subsec_nanos() as usize; + const _0: [[u8; _ONE]; _TWO] = [[1; _ONE]; _TWO]; + const _1: [[u8; _THREE]; _FOUR] = [[3; _THREE]; _FOUR]; +} diff --git a/tests/ui/consts/const-eval/enum_discr.rs b/tests/ui/consts/const-eval/enum_discr.rs new file mode 100644 index 000000000..e09258f11 --- /dev/null +++ b/tests/ui/consts/const-eval/enum_discr.rs @@ -0,0 +1,25 @@ +// run-pass + +enum Foo { + X = 42, + Y = Foo::X as isize - 3, +} + +enum Bar { + X, + Y = Bar::X as isize + 2, +} + +enum Boo { + X = Boo::Y as isize * 2, + Y = 9, +} + +fn main() { + assert_eq!(Foo::X as isize, 42); + assert_eq!(Foo::Y as isize, 39); + assert_eq!(Bar::X as isize, 0); + assert_eq!(Bar::Y as isize, 2); + assert_eq!(Boo::X as isize, 18); + assert_eq!(Boo::Y as isize, 9); +} diff --git a/tests/ui/consts/const-eval/erroneous-const.rs b/tests/ui/consts/const-eval/erroneous-const.rs new file mode 100644 index 000000000..e0fd057a2 --- /dev/null +++ b/tests/ui/consts/const-eval/erroneous-const.rs @@ -0,0 +1,21 @@ +//! Make sure we error on erroneous consts even if they are unused. +#![allow(unconditional_panic)] + +struct PrintName(T); +impl PrintName { + const VOID: () = [()][2]; //~ERROR evaluation of `PrintName::::VOID` failed +} + +const fn no_codegen() { + if false { + // This bad constant is only used in dead code in a no-codegen function... and yet we still + // must make sure that the build fails. + let _ = PrintName::::VOID; //~ constant + } +} + +pub static FOO: () = no_codegen::(); + +fn main() { + FOO +} diff --git a/tests/ui/consts/const-eval/erroneous-const.stderr b/tests/ui/consts/const-eval/erroneous-const.stderr new file mode 100644 index 000000000..03030392a --- /dev/null +++ b/tests/ui/consts/const-eval/erroneous-const.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `PrintName::::VOID` failed + --> $DIR/erroneous-const.rs:6:22 + | +LL | const VOID: () = [()][2]; + | ^^^^^^^ index out of bounds: the length is 1 but the index is 2 + +note: erroneous constant used + --> $DIR/erroneous-const.rs:13:17 + | +LL | let _ = PrintName::::VOID; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/erroneous-const2.rs b/tests/ui/consts/const-eval/erroneous-const2.rs new file mode 100644 index 000000000..15c0f9107 --- /dev/null +++ b/tests/ui/consts/const-eval/erroneous-const2.rs @@ -0,0 +1,19 @@ +//! Make sure we error on erroneous consts even if they are unused. +#![allow(unconditional_panic)] + +struct PrintName(T); +impl PrintName { + const VOID: () = [()][2]; //~ERROR evaluation of `PrintName::::VOID` failed +} + +pub static FOO: () = { + if false { + // This bad constant is only used in dead code in a static initializer... and yet we still + // must make sure that the build fails. + let _ = PrintName::::VOID; //~ constant + } +}; + +fn main() { + FOO +} diff --git a/tests/ui/consts/const-eval/erroneous-const2.stderr b/tests/ui/consts/const-eval/erroneous-const2.stderr new file mode 100644 index 000000000..8626f4d78 --- /dev/null +++ b/tests/ui/consts/const-eval/erroneous-const2.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `PrintName::::VOID` failed + --> $DIR/erroneous-const2.rs:6:22 + | +LL | const VOID: () = [()][2]; + | ^^^^^^^ index out of bounds: the length is 1 but the index is 2 + +note: erroneous constant used + --> $DIR/erroneous-const2.rs:13:17 + | +LL | let _ = PrintName::::VOID; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/extern_fat_pointer.rs b/tests/ui/consts/const-eval/extern_fat_pointer.rs new file mode 100644 index 000000000..d91d07827 --- /dev/null +++ b/tests/ui/consts/const-eval/extern_fat_pointer.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(extern_types)] + +extern "C" { + type Opaque; +} + +const FOO: *const u8 = &42 as *const _ as *const Opaque as *const u8; + +fn main() { + let _foo = FOO; +} diff --git a/tests/ui/consts/const-eval/format.rs b/tests/ui/consts/const-eval/format.rs new file mode 100644 index 000000000..0d8b7c12d --- /dev/null +++ b/tests/ui/consts/const-eval/format.rs @@ -0,0 +1,13 @@ +const fn failure() { + panic!("{:?}", 0); + //~^ ERROR cannot call non-const formatting macro in constant functions +} + +const fn print() { + println!("{:?}", 0); + //~^ ERROR cannot call non-const formatting macro in constant functions + //~| ERROR `Arguments::<'a>::new_v1` is not yet stable as a const fn + //~| ERROR cannot call non-const fn `_print` in constant functions +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr new file mode 100644 index 000000000..4bf39db58 --- /dev/null +++ b/tests/ui/consts/const-eval/format.stderr @@ -0,0 +1,95 @@ +error[E0015]: cannot call non-const formatting macro in constant functions + --> $DIR/format.rs:2:20 + | +LL | panic!("{:?}", 0); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const formatting macro in constant functions + --> $DIR/format.rs:7:22 + | +LL | println!("{:?}", 0); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `Arguments::<'a>::new_v1` is not yet stable as a const fn + --> $DIR/format.rs:7:5 + | +LL | println!("{:?}", 0); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(const_fmt_arguments_new)]` to the crate attributes to enable + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const fn `_print` in constant functions + --> $DIR/format.rs:7:5 + | +LL | println!("{:?}", 0); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/format.rs:2:12 + | +LL | panic!("{:?}", 0); + | ^^^^^^ + +note: erroneous constant used + --> $DIR/format.rs:2:12 + | +LL | panic!("{:?}", 0); + | ^^^^^^ + +note: erroneous constant used + --> $DIR/format.rs:2:20 + | +LL | panic!("{:?}", 0); + | ^ + | + = note: this note originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/format.rs:2:20 + | +LL | panic!("{:?}", 0); + | ^ + | + = note: this note originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/format.rs:7:14 + | +LL | println!("{:?}", 0); + | ^^^^^^ + +note: erroneous constant used + --> $DIR/format.rs:7:14 + | +LL | println!("{:?}", 0); + | ^^^^^^ + +note: erroneous constant used + --> $DIR/format.rs:7:22 + | +LL | println!("{:?}", 0); + | ^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/format.rs:7:22 + | +LL | println!("{:?}", 0); + | ^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-eval/generic-slice.rs b/tests/ui/consts/const-eval/generic-slice.rs new file mode 100644 index 000000000..21360a1c4 --- /dev/null +++ b/tests/ui/consts/const-eval/generic-slice.rs @@ -0,0 +1,31 @@ +// Several variants of #64945. + +// This struct is not important, we just use it to put `T` and `'a` in scope for our associated +// consts. +struct Generic<'a, T>(std::marker::PhantomData<&'a T>); + +impl<'a, T: 'static> Generic<'a, T> { + const EMPTY_SLICE: &'a [T] = { + let x: &'a [T] = &[]; + x + }; + + const EMPTY_SLICE_REF: &'a &'static [T] = { + let x: &'static [T] = &[]; + &x + //~^ ERROR `x` does not live long enough + }; +} + +static mut INTERIOR_MUT_AND_DROP: &'static [std::cell::RefCell>] = { + let x: &[_] = &[]; + x +}; + +static mut INTERIOR_MUT_AND_DROP_REF: &'static &'static [std::cell::RefCell>] = { + let x: &[_] = &[]; + &x + //~^ ERROR `x` does not live long enough +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/generic-slice.stderr b/tests/ui/consts/const-eval/generic-slice.stderr new file mode 100644 index 000000000..c38088df4 --- /dev/null +++ b/tests/ui/consts/const-eval/generic-slice.stderr @@ -0,0 +1,30 @@ +error[E0597]: `x` does not live long enough + --> $DIR/generic-slice.rs:15:9 + | +LL | impl<'a, T: 'static> Generic<'a, T> { + | -- lifetime `'a` defined here +... +LL | &x + | ^^ + | | + | borrowed value does not live long enough + | using this value as a constant requires that `x` is borrowed for `'a` +LL | +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/generic-slice.rs:27:5 + | +LL | &x + | ^^ + | | + | borrowed value does not live long enough + | using this value as a static requires that `x` is borrowed for `'static` +LL | +LL | }; + | - `x` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs new file mode 100644 index 000000000..ac9e8b64b --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs @@ -0,0 +1,15 @@ +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const FOO: i32 = foo(); +const fn foo() -> i32 { + unsafe { + let _ = intrinsics::const_allocate(4, 3) as *mut i32; + //~^ error: evaluation of constant value failed + } + 1 +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr new file mode 100644 index 000000000..8f3b3d5f7 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr @@ -0,0 +1,20 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/alloc_intrinsic_errors.rs:9:17 + | +LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2 + | +note: inside `foo` + --> $DIR/alloc_intrinsic_errors.rs:9:17 + | +LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `FOO` + --> $DIR/alloc_intrinsic_errors.rs:6:18 + | +LL | const FOO: i32 = foo(); + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs new file mode 100644 index 000000000..0a8fc7bca --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const FOO: &i32 = foo(); + +const fn foo() -> &'static i32 { + let t = unsafe { + let i = intrinsics::const_allocate(4, 4) as * mut i32; + *i = 20; + i + }; + unsafe { &*t } +} +fn main() { + assert_eq!(*FOO, 20) +} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs new file mode 100644 index 000000000..f746f2700 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs @@ -0,0 +1,18 @@ +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const FOO: *const i32 = foo(); +//~^ ERROR untyped pointers are not allowed in constant + +const fn foo() -> &'static i32 { + let t = unsafe { + let i = intrinsics::const_allocate(4, 4) as * mut i32; + *i = 20; + i + }; + unsafe { &*t } +} +fn main() { +} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr new file mode 100644 index 000000000..00ab0dfc5 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr @@ -0,0 +1,8 @@ +error: untyped pointers are not allowed in constant + --> $DIR/alloc_intrinsic_nontransient_fail.rs:6:1 + | +LL | const FOO: *const i32 = foo(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs new file mode 100644 index 000000000..92193bb33 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_transient.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const FOO: i32 = foo(); + +const fn foo() -> i32 { + let t = unsafe { + let i = intrinsics::const_allocate(4, 4) as * mut i32; + *i = 20; + i + }; + unsafe { *t } +} +fn main() { + assert_eq!(FOO, 20); +} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr new file mode 100644 index 000000000..a0f4519ea --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc_intrinsic_uninit.rs:8:1 + | +LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; + | ^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized memory, but expected an integer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc2──╼ │ ╾──╼ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr new file mode 100644 index 000000000..d2bffa425 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc_intrinsic_uninit.rs:8:1 + | +LL | const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; + | ^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized memory, but expected an integer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc2────────╼ │ ╾──────╼ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs new file mode 100644 index 000000000..b53c9ac7a --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.rs @@ -0,0 +1,10 @@ +// stderr-per-bitwidth +// compile-test +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const BAR: &i32 = unsafe { &*(intrinsics::const_allocate(4, 4) as *mut i32) }; +//~^ error: it is undefined behavior to use this value +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs new file mode 100644 index 000000000..77871c394 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -0,0 +1,9 @@ +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32}; +//~^ error: untyped pointers are not allowed in constant + +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr new file mode 100644 index 000000000..36002b850 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -0,0 +1,8 @@ +error: untyped pointers are not allowed in constant + --> $DIR/alloc_intrinsic_untyped.rs:6:1 + | +LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32}; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs new file mode 100644 index 000000000..407e69d41 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(inline_const)] + +use std::intrinsics; + +struct ZST; + +fn main() { + const { + unsafe { + let _ = intrinsics::const_allocate(0, 0) as *mut ZST; + } + } +} diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs new file mode 100644 index 000000000..aac90cd54 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic.rs @@ -0,0 +1,36 @@ +// run-pass +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] + +use std::intrinsics; + +const _X: () = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 4, 4); +}; + +const Y: &u32 = unsafe { + let ptr = intrinsics::const_allocate(4, 4) as *mut u32; + *ptr = 42; + &*ptr +}; + +const Z: &u32 = &42; + +const _Z: () = unsafe { + let ptr1 = Y as *const _ as *mut u8; + intrinsics::const_deallocate(ptr1, 4, 4); // nop + intrinsics::const_deallocate(ptr1, 2, 4); // nop + intrinsics::const_deallocate(ptr1, 4, 2); // nop + + let ptr2 = Z as *const _ as *mut u8; + intrinsics::const_deallocate(ptr2, 4, 4); // nop + intrinsics::const_deallocate(ptr2, 2, 4); // nop + intrinsics::const_deallocate(ptr2, 4, 2); // nop +}; + +fn main() { + assert_eq!(*Y, 42); + assert_eq!(*Z, 42); +} diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs new file mode 100644 index 000000000..b6d89a58d --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.rs @@ -0,0 +1,22 @@ +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] + +use std::intrinsics; + +const _X: &'static u8 = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 4, 4); + &*ptr + //~^ error: evaluation of constant value failed +}; + +const _Y: u8 = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + let reference = &*ptr; + intrinsics::const_deallocate(ptr, 4, 4); + *reference + //~^ error: evaluation of constant value failed +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr new file mode 100644 index 000000000..4eb1c42e1 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_dangling.rs:10:5 + | +LL | &*ptr + | ^^^^^ pointer to alloc2 was dereferenced after this allocation got freed + +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_dangling.rs:18:5 + | +LL | *reference + | ^^^^^^^^^^ pointer to alloc4 was dereferenced after this allocation got freed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.rs new file mode 100644 index 000000000..4010b4769 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.rs @@ -0,0 +1,13 @@ +#![feature(core_intrinsics)] +#![feature(const_heap)] + +use std::intrinsics; + +const _X: () = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 4, 4); + intrinsics::const_deallocate(ptr, 4, 4); + //~^ error: evaluation of constant value failed +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr new file mode 100644 index 000000000..8177a0850 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_duplicate.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_duplicate.rs:9:5 + | +LL | intrinsics::const_deallocate(ptr, 4, 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.rs new file mode 100644 index 000000000..031d70fdc --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.rs @@ -0,0 +1,29 @@ +#![feature(core_intrinsics)] +#![feature(const_heap)] + +use std::intrinsics; + +const _X: () = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 4, 2); + //~^ error: evaluation of constant value failed +}; +const _Y: () = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 2, 4); + //~^ error: evaluation of constant value failed +}; + +const _Z: () = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 3, 4); + //~^ error: evaluation of constant value failed +}; + +const _W: () = unsafe { + let ptr = intrinsics::const_allocate(4, 4); + intrinsics::const_deallocate(ptr, 4, 3); + //~^ error: evaluation of constant value failed +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr new file mode 100644 index 000000000..650b409b1 --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_incorrect_layout.rs:8:5 + | +LL | intrinsics::const_deallocate(ptr, 4, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc2 has size 4 and alignment 4, but gave size 4 and alignment 2 + +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_incorrect_layout.rs:13:5 + | +LL | intrinsics::const_deallocate(ptr, 2, 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc4 has size 4 and alignment 4, but gave size 2 and alignment 4 + +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_incorrect_layout.rs:19:5 + | +LL | intrinsics::const_deallocate(ptr, 3, 4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc6 has size 4 and alignment 4, but gave size 3 and alignment 4 + +error[E0080]: evaluation of constant value failed + --> $DIR/dealloc_intrinsic_incorrect_layout.rs:25:5 + | +LL | intrinsics::const_deallocate(ptr, 4, 3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2 + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs new file mode 100644 index 000000000..84fb4d2ea --- /dev/null +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(inline_const)] + +use std::intrinsics; + +fn main() { + const { + unsafe { + let ptr1 = intrinsics::const_allocate(0, 0); + let ptr2 = intrinsics::const_allocate(0, 0); + intrinsics::const_deallocate(ptr1, 0, 0); + intrinsics::const_deallocate(ptr2, 0, 0); + } + } +} diff --git a/tests/ui/consts/const-eval/ice-generic-assoc-const.rs b/tests/ui/consts/const-eval/ice-generic-assoc-const.rs new file mode 100644 index 000000000..e514682af --- /dev/null +++ b/tests/ui/consts/const-eval/ice-generic-assoc-const.rs @@ -0,0 +1,16 @@ +// build-pass (tests post-monomorphisation failure) +#![crate_type = "lib"] + +pub trait Nullable { + const NULL: Self; + + fn is_null(&self) -> bool; +} + +impl Nullable for *const T { + const NULL: Self = core::ptr::null::(); + + fn is_null(&self) -> bool { + *self == Self::NULL + } +} diff --git a/tests/ui/consts/const-eval/ice-packed.rs b/tests/ui/consts/const-eval/ice-packed.rs new file mode 100644 index 000000000..4758a5a9d --- /dev/null +++ b/tests/ui/consts/const-eval/ice-packed.rs @@ -0,0 +1,21 @@ +// Regression test for #50356: Compiler panic when using repr(packed) +// associated constant in a match arm + +// check-pass +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(packed)] +pub struct Num(u64); + +impl Num { + pub const ZERO: Self = Num(0); +} + +pub fn decrement(a: Num) -> Num { + match a { + Num::ZERO => Num::ZERO, + a => Num(a.0 - 1) + } +} + +fn main() { +} diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs new file mode 100644 index 000000000..bc2ea3f18 --- /dev/null +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -0,0 +1,21 @@ +// build-fail + +// Regression test for #66975 +#![warn(unconditional_panic)] +#![feature(never_type)] + +struct PrintName(T); + +impl PrintName { + const VOID: ! = { let x = 0 * std::mem::size_of::(); [][x] }; + //~^ ERROR evaluation of `PrintName::<()>::VOID` failed + +} + +fn f() { + let _ = PrintName::::VOID; +} + +pub fn main() { + f::<()>(); +} diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr new file mode 100644 index 000000000..8bcd03005 --- /dev/null +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `PrintName::<()>::VOID` failed + --> $DIR/index-out-of-bounds-never-type.rs:10:61 + | +LL | const VOID: ! = { let x = 0 * std::mem::size_of::(); [][x] }; + | ^^^^^ index out of bounds: the length is 0 but the index is 0 + +note: the above error was encountered while instantiating `fn f::<()>` + --> $DIR/index-out-of-bounds-never-type.rs:20:5 + | +LL | f::<()>(); + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/index_out_of_bounds.rs b/tests/ui/consts/const-eval/index_out_of_bounds.rs new file mode 100644 index 000000000..80e0d28fe --- /dev/null +++ b/tests/ui/consts/const-eval/index_out_of_bounds.rs @@ -0,0 +1,4 @@ +static FOO: i32 = [][0]; +//~^ ERROR E0080 + +fn main() {} diff --git a/tests/ui/consts/const-eval/index_out_of_bounds.stderr b/tests/ui/consts/const-eval/index_out_of_bounds.stderr new file mode 100644 index 000000000..8bb3a0c67 --- /dev/null +++ b/tests/ui/consts/const-eval/index_out_of_bounds.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/index_out_of_bounds.rs:1:19 + | +LL | static FOO: i32 = [][0]; + | ^^^^^ index out of bounds: the length is 0 but the index is 0 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/index_out_of_bounds_propagated.rs b/tests/ui/consts/const-eval/index_out_of_bounds_propagated.rs new file mode 100644 index 000000000..608e6e112 --- /dev/null +++ b/tests/ui/consts/const-eval/index_out_of_bounds_propagated.rs @@ -0,0 +1,6 @@ +// build-fail + +fn main() { + let array = [std::env::args().len()]; + array[1]; //~ ERROR operation will panic +} diff --git a/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr new file mode 100644 index 000000000..d247d691d --- /dev/null +++ b/tests/ui/consts/const-eval/index_out_of_bounds_propagated.stderr @@ -0,0 +1,10 @@ +error: this operation will panic at runtime + --> $DIR/index_out_of_bounds_propagated.rs:5:5 + | +LL | array[1]; + | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/infinite_loop.rs b/tests/ui/consts/const-eval/infinite_loop.rs new file mode 100644 index 000000000..4babc9a28 --- /dev/null +++ b/tests/ui/consts/const-eval/infinite_loop.rs @@ -0,0 +1,12 @@ +fn main() { + // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). + // The value of `n` will loop indefinitely (4 - 2 - 1 - 4). + let _ = [(); { + let mut n = 113383; // #20 in https://oeis.org/A006884 + while n != 0 { + //~^ ERROR evaluation of constant value failed + n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; + } + n + }]; +} diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.stderr new file mode 100644 index 000000000..8b58cb279 --- /dev/null +++ b/tests/ui/consts/const-eval/infinite_loop.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/infinite_loop.rs:6:15 + | +LL | while n != 0 { + | ^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-100878.rs b/tests/ui/consts/const-eval/issue-100878.rs new file mode 100644 index 000000000..353ce5050 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-100878.rs @@ -0,0 +1,8 @@ +// This checks that the const-eval ICE in issue #100878 does not recur. +// +// build-pass +pub fn bitshift_data(data: [u8; 1]) -> u8 { + data[0] << 8 +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-104390.rs b/tests/ui/consts/const-eval/issue-104390.rs new file mode 100644 index 000000000..602d81824 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-104390.rs @@ -0,0 +1,10 @@ +fn f1() -> impl Sized { & 2E } //~ ERROR expected at least one digit in exponent +fn f2() -> impl Sized { && 2E } //~ ERROR expected at least one digit in exponent +fn f3() -> impl Sized { &'a 2E } //~ ERROR expected at least one digit in exponent +//~^ ERROR borrow expressions cannot be annotated with lifetimes +fn f4() -> impl Sized { &'static 2E } //~ ERROR expected at least one digit in exponent +//~^ ERROR borrow expressions cannot be annotated with lifetimes +fn f5() -> impl Sized { *& 2E } //~ ERROR expected at least one digit in exponent +fn f6() -> impl Sized { &'_ 2E } //~ ERROR expected at least one digit in exponent +//~^ ERROR borrow expressions cannot be annotated with lifetimes +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-104390.stderr b/tests/ui/consts/const-eval/issue-104390.stderr new file mode 100644 index 000000000..865b9996e --- /dev/null +++ b/tests/ui/consts/const-eval/issue-104390.stderr @@ -0,0 +1,65 @@ +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:1:27 + | +LL | fn f1() -> impl Sized { & 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:2:28 + | +LL | fn f2() -> impl Sized { && 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:3:29 + | +LL | fn f3() -> impl Sized { &'a 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:5:34 + | +LL | fn f4() -> impl Sized { &'static 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:7:28 + | +LL | fn f5() -> impl Sized { *& 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:8:29 + | +LL | fn f6() -> impl Sized { &'_ 2E } + | ^^ + +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/issue-104390.rs:3:25 + | +LL | fn f3() -> impl Sized { &'a 2E } + | ^--^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/issue-104390.rs:5:25 + | +LL | fn f4() -> impl Sized { &'static 2E } + | ^-------^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/issue-104390.rs:8:25 + | +LL | fn f6() -> impl Sized { &'_ 2E } + | ^--^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: aborting due to 9 previous errors + diff --git a/tests/ui/consts/const-eval/issue-43197.rs b/tests/ui/consts/const-eval/issue-43197.rs new file mode 100644 index 000000000..145463f0a --- /dev/null +++ b/tests/ui/consts/const-eval/issue-43197.rs @@ -0,0 +1,11 @@ +const fn foo(x: u32) -> u32 { + x +} + +fn main() { + const X: u32 = 0 - 1; + //~^ ERROR constant + const Y: u32 = foo(0 - 1); + //~^ ERROR constant + println!("{} {}", X, Y); +} diff --git a/tests/ui/consts/const-eval/issue-43197.stderr b/tests/ui/consts/const-eval/issue-43197.stderr new file mode 100644 index 000000000..c59f13e48 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-43197.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-43197.rs:6:20 + | +LL | const X: u32 = 0 - 1; + | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-43197.rs:8:24 + | +LL | const Y: u32 = foo(0 - 1); + | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-44578.rs b/tests/ui/consts/const-eval/issue-44578.rs new file mode 100644 index 000000000..e4dcc6230 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-44578.rs @@ -0,0 +1,27 @@ +// build-fail + +trait Foo { + const AMT: usize; +} + +enum Bar { + First(A), + Second(B), +} + +impl Foo for Bar { + const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; //~ERROR evaluation of ` as Foo>::AMT` failed +} + +impl Foo for u8 { + const AMT: usize = 1; +} + +impl Foo for u16 { + const AMT: usize = 2; +} + +fn main() { + println!("{}", as Foo>::AMT); + //~^ constant +} diff --git a/tests/ui/consts/const-eval/issue-44578.stderr b/tests/ui/consts/const-eval/issue-44578.stderr new file mode 100644 index 000000000..0cbf54480 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-44578.stderr @@ -0,0 +1,39 @@ +error[E0080]: evaluation of ` as Foo>::AMT` failed + --> $DIR/issue-44578.rs:13:24 + | +LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + +note: erroneous constant used + --> $DIR/issue-44578.rs:25:20 + | +LL | println!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/issue-44578.rs:25:20 + | +LL | println!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-44578.rs:25:20 + | +LL | println!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-44578.rs:25:20 + | +LL | println!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-47971.rs b/tests/ui/consts/const-eval/issue-47971.rs new file mode 100644 index 000000000..b98e76031 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-47971.rs @@ -0,0 +1,9 @@ +// check-pass + +struct S(pub &'static u32, pub u32); + +const fn g(ss: &S) -> &u32 { &ss.1 } + +static T: S = S(g(&T), 0); + +fn main () { } diff --git a/tests/ui/consts/const-eval/issue-49296.rs b/tests/ui/consts/const-eval/issue-49296.rs new file mode 100644 index 000000000..917777a32 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-49296.rs @@ -0,0 +1,14 @@ +// issue-49296: Unsafe shenigans in constants can result in missing errors + +use std::mem::transmute; + +const fn wat(x: u64) -> &'static u64 { + unsafe { transmute(&x) } +} + +const X: u64 = *wat(42); +//~^ ERROR evaluation of constant value failed + +fn main() { + println!("{}", X); +} diff --git a/tests/ui/consts/const-eval/issue-49296.stderr b/tests/ui/consts/const-eval/issue-49296.stderr new file mode 100644 index 000000000..cc4f1594c --- /dev/null +++ b/tests/ui/consts/const-eval/issue-49296.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-49296.rs:9:16 + | +LL | const X: u64 = *wat(42); + | ^^^^^^^^ pointer to alloc3 was dereferenced after this allocation got freed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50706.rs b/tests/ui/consts/const-eval/issue-50706.rs new file mode 100644 index 000000000..a13c27f2e --- /dev/null +++ b/tests/ui/consts/const-eval/issue-50706.rs @@ -0,0 +1,37 @@ +// check-pass + +pub struct Stats; + +#[derive(PartialEq, Eq)] +pub struct StatVariant { + pub id: u8, + _priv: (), +} + +#[derive(PartialEq, Eq)] +pub struct Stat { + pub variant: StatVariant, + pub index: usize, + _priv: (), +} + +impl Stats { + pub const TEST: StatVariant = StatVariant{id: 0, _priv: (),}; + #[allow(non_upper_case_globals)] + pub const A: Stat = Stat{ + variant: Self::TEST, + index: 0, + _priv: (),}; +} + +impl Stat { + pub fn from_index(variant: StatVariant, index: usize) -> Option { + let stat = Stat{variant, index, _priv: (),}; + match stat { + Stats::A => Some(Stats::A), + _ => None, + } + } +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-50814-2.rs b/tests/ui/consts/const-eval/issue-50814-2.rs new file mode 100644 index 000000000..53eb7b149 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-50814-2.rs @@ -0,0 +1,34 @@ +// build-fail + +trait C { + const BOO: usize; +} + +trait Foo { + const BAR: usize; +} + +struct A(T); + +impl Foo for A { + const BAR: usize = [5, 6, 7][T::BOO]; //~ ERROR evaluation of ` as Foo<()>>::BAR` failed +} + +fn foo() -> &'static usize { + & as Foo>::BAR //~ constant +} + +impl C for () { + const BOO: usize = 42; +} + +impl C for u32 { + const BOO: usize = 1; +} + +fn main() { + println!("{:x}", foo::<()>() as *const usize as usize); + println!("{:x}", foo::() as *const usize as usize); + println!("{:x}", foo::<()>()); + println!("{:x}", foo::()); +} diff --git a/tests/ui/consts/const-eval/issue-50814-2.stderr b/tests/ui/consts/const-eval/issue-50814-2.stderr new file mode 100644 index 000000000..956f7aec9 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-50814-2.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of ` as Foo<()>>::BAR` failed + --> $DIR/issue-50814-2.rs:14:24 + | +LL | const BAR: usize = [5, 6, 7][T::BOO]; + | ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42 + +note: erroneous constant used + --> $DIR/issue-50814-2.rs:18:6 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn foo::<()>` + --> $DIR/issue-50814-2.rs:30:22 + | +LL | println!("{:x}", foo::<()>() as *const usize as usize); + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50814.rs b/tests/ui/consts/const-eval/issue-50814.rs new file mode 100644 index 000000000..374ed1d93 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-50814.rs @@ -0,0 +1,26 @@ +// build-fail + +trait Unsigned { + const MAX: u8; +} + +struct U8(u8); +impl Unsigned for U8 { + const MAX: u8 = 0xff; +} + +struct Sum(A, B); + +impl Unsigned for Sum { + const MAX: u8 = A::MAX + B::MAX; + //~^ ERROR evaluation of ` as Unsigned>::MAX` failed +} + +fn foo(_: T) -> &'static u8 { + &Sum::::MAX + //~^ constant +} + +fn main() { + foo(0); +} diff --git a/tests/ui/consts/const-eval/issue-50814.stderr b/tests/ui/consts/const-eval/issue-50814.stderr new file mode 100644 index 000000000..05b6271f4 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-50814.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of ` as Unsigned>::MAX` failed + --> $DIR/issue-50814.rs:15:21 + | +LL | const MAX: u8 = A::MAX + B::MAX; + | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow + +note: erroneous constant used + --> $DIR/issue-50814.rs:20:6 + | +LL | &Sum::::MAX + | ^^^^^^^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn foo::` + --> $DIR/issue-50814.rs:25:5 + | +LL | foo(0); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-51300.rs b/tests/ui/consts/const-eval/issue-51300.rs new file mode 100644 index 000000000..8e68e8c91 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-51300.rs @@ -0,0 +1,31 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/51300 + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct Stat { + pub id: u8, + pub index: usize, +} + +impl Stat { + pub const STUDENT_HAPPINESS: Stat = Stat{ + id: 0, + index: 0, + }; + pub const STUDENT_HUNGER: Stat = Stat{ + id: 0, + index: Self::STUDENT_HAPPINESS.index + 1, + }; + +} + +pub fn from_index(id: u8, index: usize) -> Option { + let stat = Stat{id, index}; + match stat { + Stat::STUDENT_HAPPINESS => Some(Stat::STUDENT_HAPPINESS), + Stat::STUDENT_HUNGER => Some(Stat::STUDENT_HUNGER), + _ => None, + } +} + +fn main() { } diff --git a/tests/ui/consts/const-eval/issue-52475.rs b/tests/ui/consts/const-eval/issue-52475.rs new file mode 100644 index 000000000..ce65407bb --- /dev/null +++ b/tests/ui/consts/const-eval/issue-52475.rs @@ -0,0 +1,11 @@ +fn main() { + let _ = [(); { + let mut x = &0; + let mut n = 0; + while n < 5 { + n = (n + 1) % 5; //~ ERROR evaluation of constant value failed + x = &0; // Materialize a new AllocId + } + 0 + }]; +} diff --git a/tests/ui/consts/const-eval/issue-52475.stderr b/tests/ui/consts/const-eval/issue-52475.stderr new file mode 100644 index 000000000..8536ff02c --- /dev/null +++ b/tests/ui/consts/const-eval/issue-52475.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-52475.rs:6:17 + | +LL | n = (n + 1) % 5; + | ^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-53157.rs b/tests/ui/consts/const-eval/issue-53157.rs new file mode 100644 index 000000000..850338625 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-53157.rs @@ -0,0 +1,13 @@ +// check-pass + +macro_rules! m { + () => {{ + fn f(_: impl Sized) {} + f + }} +} + +fn main() { + fn f() -> impl Sized {}; + m!()(f()); +} diff --git a/tests/ui/consts/const-eval/issue-53401.rs b/tests/ui/consts/const-eval/issue-53401.rs new file mode 100644 index 000000000..31c946c3c --- /dev/null +++ b/tests/ui/consts/const-eval/issue-53401.rs @@ -0,0 +1,11 @@ +// check-pass + +pub const STATIC_TRAIT: &dyn Test = &(); + +fn main() {} + +pub trait Test { + fn test() where Self: Sized {} +} + +impl Test for () {} diff --git a/tests/ui/consts/const-eval/issue-55541.rs b/tests/ui/consts/const-eval/issue-55541.rs new file mode 100644 index 000000000..fa5a493ab --- /dev/null +++ b/tests/ui/consts/const-eval/issue-55541.rs @@ -0,0 +1,27 @@ +// check-pass + +// Test that we can handle newtypes wrapping extern types + +#![feature(extern_types)] + +use std::marker::PhantomData; + +extern "C" { + pub type ExternType; +} +unsafe impl Sync for ExternType {} +static MAGIC_FFI_STATIC: u8 = 42; + +#[repr(transparent)] +pub struct Wrapper(ExternType); +pub static MAGIC_FFI_REF: &'static Wrapper = unsafe { + std::mem::transmute(&MAGIC_FFI_STATIC) +}; + +#[repr(transparent)] +pub struct Wrapper2(PhantomData>, ExternType); +pub static MAGIC_FFI_REF2: &'static Wrapper2 = unsafe { + std::mem::transmute(&MAGIC_FFI_STATIC) +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-64908.rs b/tests/ui/consts/const-eval/issue-64908.rs new file mode 100644 index 000000000..d2e095072 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-64908.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test verifies that the `ConstProp` pass doesn't cause an ICE when evaluating polymorphic +// promoted MIR. + +pub trait ArrowPrimitiveType { + type Native; +} + +pub fn new() { + assert_eq!(0, std::mem::size_of::()); +} + +impl ArrowPrimitiveType for () { + type Native = (); +} + +fn main() { + new::<()>(); +} diff --git a/tests/ui/consts/const-eval/issue-64970.rs b/tests/ui/consts/const-eval/issue-64970.rs new file mode 100644 index 000000000..ba530438f --- /dev/null +++ b/tests/ui/consts/const-eval/issue-64970.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + foo(10); +} + +fn foo(mut n: i32) { + if false { + n = 0i32; + } + + if n > 0i32 { + let _ = 1i32 / n; + } +} diff --git a/tests/ui/consts/const-eval/issue-65394.rs b/tests/ui/consts/const-eval/issue-65394.rs new file mode 100644 index 000000000..e6639826c --- /dev/null +++ b/tests/ui/consts/const-eval/issue-65394.rs @@ -0,0 +1,13 @@ +// This test originated from #65394. We conservatively assume that `x` is still `LiveDrop` even +// after it has been moved because a mutable reference to it exists at some point in the const body. +// +// We will likely have to change this behavior before we allow `&mut` in a `const`. + +const _: Vec = { + let mut x = Vec::::new(); //~ ERROR destructor of + let r = &mut x; //~ ERROR mutable references are not allowed in constants + let y = x; + y +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-65394.stderr b/tests/ui/consts/const-eval/issue-65394.stderr new file mode 100644 index 000000000..ae6f0e937 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-65394.stderr @@ -0,0 +1,22 @@ +error[E0658]: mutable references are not allowed in constants + --> $DIR/issue-65394.rs:8:13 + | +LL | let r = &mut x; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0493]: destructor of `Vec` cannot be evaluated at compile-time + --> $DIR/issue-65394.rs:7:9 + | +LL | let mut x = Vec::::new(); + | ^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0493, E0658. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-eval/issue-70723.rs b/tests/ui/consts/const-eval/issue-70723.rs new file mode 100644 index 000000000..3c81afa67 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-70723.rs @@ -0,0 +1,3 @@ +static _X: () = loop {}; //~ ERROR could not evaluate static initializer + +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-70723.stderr b/tests/ui/consts/const-eval/issue-70723.stderr new file mode 100644 index 000000000..09fb3e060 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-70723.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/issue-70723.rs:1:17 + | +LL | static _X: () = loop {}; + | ^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-70804-fn-subtyping.rs b/tests/ui/consts/const-eval/issue-70804-fn-subtyping.rs new file mode 100644 index 000000000..abd1d32ab --- /dev/null +++ b/tests/ui/consts/const-eval/issue-70804-fn-subtyping.rs @@ -0,0 +1,9 @@ +// check-pass + +const fn nested(x: (for<'a> fn(&'a ()), String)) -> (fn(&'static ()), String) { + x +} + +pub const TEST: (fn(&'static ()), String) = nested((|_x| (), String::new())); + +fn main() {} diff --git a/tests/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs b/tests/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs new file mode 100644 index 000000000..7e235c491 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-84957-const-str-as-bytes.rs @@ -0,0 +1,28 @@ +// build-pass + +trait Foo {} + +struct Bar { + bytes: &'static [u8], + func: fn(&Box), +} +fn example(_: &Box) {} + +const BARS: &[Bar] = &[ + Bar { + bytes: "0".as_bytes(), + func: example, + }, + Bar { + bytes: "0".as_bytes(), + func: example, + }, +]; + +fn main() { + let x = todo!(); + + for bar in BARS { + (bar.func)(&x); + } +} diff --git a/tests/ui/consts/const-eval/issue-85155.rs b/tests/ui/consts/const-eval/issue-85155.rs new file mode 100644 index 000000000..c3216d53d --- /dev/null +++ b/tests/ui/consts/const-eval/issue-85155.rs @@ -0,0 +1,21 @@ +// This is a test with a setup similar to issue 85155, which triggers a const eval error: a const +// argument value is outside the range expected by the `stdarch` intrinsic. +// +// It's not the exact code mentioned in that issue because it depends both on `stdarch` intrinsics +// only available on x64, and internal implementation details of `stdarch`. But mostly because these +// are not important to trigger the diagnostics issue: it's specifically about the lack of context +// in the diagnostics of post-monomorphization errors (PMEs) for consts, happening in a dependency. +// Therefore, its setup is reproduced with an aux crate, which will similarly trigger a PME +// depending on the const argument value, like the `stdarch` intrinsics would. +// +// aux-build: post_monomorphization_error.rs +// build-fail: this is a post-monomorphization error, it passes check runs and requires building +// to actually fail. + +extern crate post_monomorphization_error; + +fn main() { + // This function triggers a PME whenever the const argument does not fit in 1-bit. + post_monomorphization_error::stdarch_intrinsic::<2>(); + //~^ NOTE the above error was encountered while instantiating +} diff --git a/tests/ui/consts/const-eval/issue-85155.stderr b/tests/ui/consts/const-eval/issue-85155.stderr new file mode 100644 index 000000000..3d2c76b7e --- /dev/null +++ b/tests/ui/consts/const-eval/issue-85155.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2, 0, 1>::VALID` failed + --> $DIR/auxiliary/post_monomorphization_error.rs:7:17 + | +LL | let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to divide `1_usize` by zero + +note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2>` + --> $DIR/issue-85155.rs:19:5 + | +LL | post_monomorphization_error::stdarch_intrinsic::<2>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-85907.rs b/tests/ui/consts/const-eval/issue-85907.rs new file mode 100644 index 000000000..6ae40ae6d --- /dev/null +++ b/tests/ui/consts/const-eval/issue-85907.rs @@ -0,0 +1,7 @@ +const fn hey() -> usize { + panic!(123); //~ ERROR argument to `panic!()` in a const context must have type `&str` +} + +fn main() { + let _: [u8; hey()] = todo!(); +} diff --git a/tests/ui/consts/const-eval/issue-85907.stderr b/tests/ui/consts/const-eval/issue-85907.stderr new file mode 100644 index 000000000..fd7b40572 --- /dev/null +++ b/tests/ui/consts/const-eval/issue-85907.stderr @@ -0,0 +1,10 @@ +error: argument to `panic!()` in a const context must have type `&str` + --> $DIR/issue-85907.rs:2:5 + | +LL | panic!(123); + | ^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/issue-91827-extern-types.rs b/tests/ui/consts/const-eval/issue-91827-extern-types.rs new file mode 100644 index 000000000..43c99799f --- /dev/null +++ b/tests/ui/consts/const-eval/issue-91827-extern-types.rs @@ -0,0 +1,56 @@ +// run-pass +// +// Test that we can handle unsized types with an extern type tail part. +// Regression test for issue #91827. + +#![feature(extern_types)] + +use std::ptr::addr_of; + +extern "C" { + type Opaque; +} + +unsafe impl Sync for Opaque {} + +#[repr(C)] +pub struct List { + len: usize, + data: [T; 0], + tail: Opaque, +} + +#[repr(C)] +pub struct ListImpl { + len: usize, + data: [T; N], +} + +impl List { + const fn as_slice(&self) -> &[T] { + unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) } + } +} + +impl ListImpl { + const fn as_list(&self) -> &List { + unsafe { std::mem::transmute(self) } + } +} + +pub static A: ListImpl = ListImpl { + len: 3, + data: [5, 6, 7], +}; +pub static A_REF: &'static List = A.as_list(); +pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list()); + +const fn tail_offset(list: &List) -> isize { + unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List as *const u8) } +} + +fn main() { + assert_eq!(A_REF.as_slice(), &[5, 6, 7]); + // Check that interpreter and code generation agree about the position of the tail field. + assert_eq!(A_TAIL_OFFSET, tail_offset(A_REF)); +} diff --git a/tests/ui/consts/const-eval/livedrop.rs b/tests/ui/consts/const-eval/livedrop.rs new file mode 100644 index 000000000..543f1f0ec --- /dev/null +++ b/tests/ui/consts/const-eval/livedrop.rs @@ -0,0 +1,17 @@ +const _: Option> = { + let mut never_returned = Some(Vec::new()); + let mut always_returned = None; //~ ERROR destructor of + + let mut i = 0; + loop { + always_returned = never_returned; + never_returned = None; + + i += 1; + if i == 10 { + break always_returned; + } + } +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/livedrop.stderr b/tests/ui/consts/const-eval/livedrop.stderr new file mode 100644 index 000000000..d04fdb70e --- /dev/null +++ b/tests/ui/consts/const-eval/livedrop.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time + --> $DIR/livedrop.rs:3:9 + | +LL | let mut always_returned = None; + | ^^^^^^^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | always_returned = never_returned; + | --------------- value is dropped here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/const-eval/match-test-ptr-null.rs b/tests/ui/consts/const-eval/match-test-ptr-null.rs new file mode 100644 index 000000000..4af97b548 --- /dev/null +++ b/tests/ui/consts/const-eval/match-test-ptr-null.rs @@ -0,0 +1,12 @@ +fn main() { + // Make sure match uses the usual pointer comparison code path -- i.e., it should complain + // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw + // bytes. + let _: [u8; 0] = [4; { + match &1 as *const i32 as usize { + //~^ ERROR pointers cannot be cast to integers during const eval + 0 => 42, + n => n, + } + }]; +} diff --git a/tests/ui/consts/const-eval/match-test-ptr-null.stderr b/tests/ui/consts/const-eval/match-test-ptr-null.stderr new file mode 100644 index 000000000..05c3951c1 --- /dev/null +++ b/tests/ui/consts/const-eval/match-test-ptr-null.stderr @@ -0,0 +1,11 @@ +error: pointers cannot be cast to integers during const eval + --> $DIR/match-test-ptr-null.rs:6:15 + | +LL | match &1 as *const i32 as usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/mod-static-with-const-fn.rs b/tests/ui/consts/const-eval/mod-static-with-const-fn.rs new file mode 100644 index 000000000..b6b74e67d --- /dev/null +++ b/tests/ui/consts/const-eval/mod-static-with-const-fn.rs @@ -0,0 +1,22 @@ +// New test for #53818: modifying static memory at compile-time is not allowed. +// The test should never compile successfully + +#![feature(const_mut_refs)] + +use std::cell::UnsafeCell; + +struct Foo(UnsafeCell); + +unsafe impl Send for Foo {} +unsafe impl Sync for Foo {} + +static FOO: Foo = Foo(UnsafeCell::new(42)); + +static BAR: () = unsafe { + *FOO.0.get() = 5; + //~^ ERROR could not evaluate static initializer +}; + +fn main() { + println!("{}", unsafe { *FOO.0.get() }); +} diff --git a/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr b/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr new file mode 100644 index 000000000..d127d1d45 --- /dev/null +++ b/tests/ui/consts/const-eval/mod-static-with-const-fn.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/mod-static-with-const-fn.rs:16:5 + | +LL | *FOO.0.get() = 5; + | ^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/no_lint_for_statically_known_error.rs b/tests/ui/consts/const-eval/no_lint_for_statically_known_error.rs new file mode 100644 index 000000000..910ca3c4b --- /dev/null +++ b/tests/ui/consts/const-eval/no_lint_for_statically_known_error.rs @@ -0,0 +1,18 @@ +// check-pass + +// if `X` were used instead of `x`, `X - 10` would result in a lint. +// This file should never produce a lint, no matter how the const +// propagator is improved. + +#![deny(warnings)] + +const X: u32 = 5; + +fn main() { + let x = X; + if x > 10 { + println!("{}", x - 10); + } else { + println!("{}", 10 - x); + } +} diff --git a/tests/ui/consts/const-eval/nrvo.rs b/tests/ui/consts/const-eval/nrvo.rs new file mode 100644 index 000000000..1d2c6acc0 --- /dev/null +++ b/tests/ui/consts/const-eval/nrvo.rs @@ -0,0 +1,26 @@ +// run-pass + +// When the NRVO is applied, the return place (`_0`) gets treated like a normal local. For example, +// its address may be taken and it may be written to indirectly. Ensure that MIRI can handle this. + +#![feature(const_mut_refs)] + +#[inline(never)] // Try to ensure that MIR optimizations don't optimize this away. +const fn init(buf: &mut [u8; 1024]) { + buf[33] = 3; + buf[444] = 4; +} + +const fn nrvo() -> [u8; 1024] { + let mut buf = [0; 1024]; + init(&mut buf); + buf +} + +const BUF: [u8; 1024] = nrvo(); + +fn main() { + assert_eq!(BUF[33], 3); + assert_eq!(BUF[19], 0); + assert_eq!(BUF[444], 4); +} diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.rs b/tests/ui/consts/const-eval/panic-assoc-never-type.rs new file mode 100644 index 000000000..28edf5144 --- /dev/null +++ b/tests/ui/consts/const-eval/panic-assoc-never-type.rs @@ -0,0 +1,15 @@ +// build-fail + +// Regression test for #66975 +#![feature(never_type)] + +struct PrintName; + +impl PrintName { + const VOID: ! = panic!(); + //~^ ERROR evaluation of constant value failed +} + +fn main() { + let _ = PrintName::VOID; //~ constant +} diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr new file mode 100644 index 000000000..7c36a3a42 --- /dev/null +++ b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr @@ -0,0 +1,23 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/panic-assoc-never-type.rs:9:21 + | +LL | const VOID: ! = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:9:21 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/panic-assoc-never-type.rs:14:13 + | +LL | let _ = PrintName::VOID; + | ^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/panic-assoc-never-type.rs:14:13 + | +LL | let _ = PrintName::VOID; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/panic-never-type.rs b/tests/ui/consts/const-eval/panic-never-type.rs new file mode 100644 index 000000000..a9e9026d9 --- /dev/null +++ b/tests/ui/consts/const-eval/panic-never-type.rs @@ -0,0 +1,9 @@ +// Regression test for #66975 +#![feature(never_type)] + +const VOID: ! = panic!(); +//~^ ERROR evaluation of constant value failed + +fn main() { + let _ = VOID; +} diff --git a/tests/ui/consts/const-eval/panic-never-type.stderr b/tests/ui/consts/const-eval/panic-never-type.stderr new file mode 100644 index 000000000..6bff14a45 --- /dev/null +++ b/tests/ui/consts/const-eval/panic-never-type.stderr @@ -0,0 +1,11 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/panic-never-type.rs:4:17 + | +LL | const VOID: ! = panic!(); + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:4:17 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs new file mode 100644 index 000000000..d6c768868 --- /dev/null +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs @@ -0,0 +1,14 @@ +// Test for the behavior described in . +#![feature(const_mut_refs)] + +const PARTIAL_OVERWRITE: () = { + let mut p = &42; + unsafe { + let ptr: *mut _ = &mut p; + *(ptr as *mut u8) = 123; //~ ERROR constant + //~| unable to overwrite parts of a pointer + } + let x = *p; +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr new file mode 100644 index 000000000..13ca4379b --- /dev/null +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr @@ -0,0 +1,12 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/partial_ptr_overwrite.rs:8:9 + | +LL | *(ptr as *mut u8) = 123; + | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4 + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/promote-static.rs b/tests/ui/consts/const-eval/promote-static.rs new file mode 100644 index 000000000..d3c663c53 --- /dev/null +++ b/tests/ui/consts/const-eval/promote-static.rs @@ -0,0 +1,14 @@ +// regression test for #67609. + +// check-pass + +static NONE: Option = None; + +static NONE_REF_REF: &&Option = { + let x = &&NONE; + x +}; + +fn main() { + println!("{:?}", NONE_REF_REF); +} diff --git a/tests/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs b/tests/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs new file mode 100644 index 000000000..edda10e6e --- /dev/null +++ b/tests/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs @@ -0,0 +1,5 @@ +// check-pass + +pub fn main() { + let y: &'static mut [u8; 0] = &mut []; +} diff --git a/tests/ui/consts/const-eval/promoted_const_fn_fail.rs b/tests/ui/consts/const-eval/promoted_const_fn_fail.rs new file mode 100644 index 000000000..656dd33e1 --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_const_fn_fail.rs @@ -0,0 +1,20 @@ +#[repr(C)] +union Bar { + a: &'static u8, + b: usize, +} + +const fn bar() -> u8 { + unsafe { + // this will error as long as this test + // is run on a system whose pointers need more + // than 8 bits + Bar { a: &42 }.b as u8 + } +} + +fn main() { + let x: &'static u8 = &(bar() + 1); //~ ERROR temporary value dropped while borrowed + let y = *x; + unreachable!(); +} diff --git a/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr b/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr new file mode 100644 index 000000000..2d4e7c83d --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_const_fn_fail.stderr @@ -0,0 +1,14 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_fn_fail.rs:17:27 + | +LL | let x: &'static u8 = &(bar() + 1); + | ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs new file mode 100644 index 000000000..5009dbcb9 --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs @@ -0,0 +1,22 @@ +#[repr(C)] +union Bar { + a: &'static u8, + b: usize, +} + +const fn bar() -> u8 { + unsafe { + // This will error as long as this test is run on a system whose + // pointers need more than 8 bits. + Bar { a: &42 }.b as u8 + } +} + +fn main() { + // This will compile, but then hard-abort at runtime. + // FIXME(oli-obk): this should instead panic (not hard-abort) at runtime. + let x: &'static u8 = &(bar() + 1); + //~^ ERROR temporary value dropped while borrowed + let y = *x; + unreachable!(); +} diff --git a/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr new file mode 100644 index 000000000..9ebae3a18 --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr @@ -0,0 +1,14 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27 + | +LL | let x: &'static u8 = &(bar() + 1); + | ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/promoted_errors.noopt.stderr b/tests/ui/consts/const-eval/promoted_errors.noopt.stderr new file mode 100644 index 000000000..2a254bfde --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_errors.noopt.stderr @@ -0,0 +1,44 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:15:5 + | +LL | 0 - 1 + | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:11:9 + | +LL | #![warn(arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:19:5 + | +LL | 1 / 0 + | ^^^^^ attempt to divide `1_i32` by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:11:30 + | +LL | #![warn(arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:23:5 + | +LL | 1 / (1 - 1) + | ^^^^^^^^^^^ attempt to divide `1_i32` by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:27:5 + | +LL | 1 / (false as i32) + | ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:31:5 + | +LL | [1, 2, 3][4] + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +warning: 5 warnings emitted + diff --git a/tests/ui/consts/const-eval/promoted_errors.opt.stderr b/tests/ui/consts/const-eval/promoted_errors.opt.stderr new file mode 100644 index 000000000..2a254bfde --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_errors.opt.stderr @@ -0,0 +1,44 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:15:5 + | +LL | 0 - 1 + | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:11:9 + | +LL | #![warn(arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:19:5 + | +LL | 1 / 0 + | ^^^^^ attempt to divide `1_i32` by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:11:30 + | +LL | #![warn(arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:23:5 + | +LL | 1 / (1 - 1) + | ^^^^^^^^^^^ attempt to divide `1_i32` by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:27:5 + | +LL | 1 / (false as i32) + | ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:31:5 + | +LL | [1, 2, 3][4] + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +warning: 5 warnings emitted + diff --git a/tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..2a254bfde --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr @@ -0,0 +1,44 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:15:5 + | +LL | 0 - 1 + | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:11:9 + | +LL | #![warn(arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:19:5 + | +LL | 1 / 0 + | ^^^^^ attempt to divide `1_i32` by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:11:30 + | +LL | #![warn(arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:23:5 + | +LL | 1 / (1 - 1) + | ^^^^^^^^^^^ attempt to divide `1_i32` by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:27:5 + | +LL | 1 / (false as i32) + | ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:31:5 + | +LL | [1, 2, 3][4] + | ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4 + +warning: 5 warnings emitted + diff --git a/tests/ui/consts/const-eval/promoted_errors.rs b/tests/ui/consts/const-eval/promoted_errors.rs new file mode 100644 index 000000000..2c42d0356 --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_errors.rs @@ -0,0 +1,52 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +// build-pass +// ignore-pass (test emits codegen-time warnings and verifies that they are not errors) + +//! This test ensures that when we promote code that fails to evaluate, the build still succeeds. + +#![warn(arithmetic_overflow, unconditional_panic)] + +// The only way to have promoteds that fail is in `const fn` called from `const`/`static`. +const fn overflow() -> u32 { + 0 - 1 + //~^ WARN this arithmetic operation will overflow +} +const fn div_by_zero1() -> i32 { + 1 / 0 + //~^ WARN this operation will panic at runtime +} +const fn div_by_zero2() -> i32 { + 1 / (1 - 1) + //~^ WARN this operation will panic at runtime +} +const fn div_by_zero3() -> i32 { + 1 / (false as i32) + //~^ WARN this operation will panic at runtime +} +const fn oob() -> i32 { + [1, 2, 3][4] + //~^ WARN this operation will panic at runtime +} + +const fn mk_false() -> bool { false } + +// An actually used constant referencing failing promoteds in dead code. +// This needs to always work. +const Y: () = { + if mk_false() { + let _x: &'static u32 = &overflow(); + let _x: &'static i32 = &div_by_zero1(); + let _x: &'static i32 = &div_by_zero2(); + let _x: &'static i32 = &div_by_zero3(); + let _x: &'static i32 = &oob(); + } + () +}; + +fn main() { + let _y = Y; +} diff --git a/tests/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/tests/ui/consts/const-eval/promoted_raw_ptr_ops.rs new file mode 100644 index 000000000..1800b0a97 --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_raw_ptr_ops.rs @@ -0,0 +1,10 @@ +fn main() { + let x: &'static bool = &(42 as *const i32 == 43 as *const i32); + //~^ ERROR temporary value dropped while borrowed + let y: &'static usize = &(&1 as *const i32 as usize + 1); + //~^ ERROR temporary value dropped while borrowed + let z: &'static i32 = &(unsafe { *(42 as *const i32) }); + //~^ ERROR temporary value dropped while borrowed + let a: &'static bool = &(main as fn() == main as fn()); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/tests/ui/consts/const-eval/promoted_raw_ptr_ops.stderr new file mode 100644 index 000000000..01fcf2ec2 --- /dev/null +++ b/tests/ui/consts/const-eval/promoted_raw_ptr_ops.stderr @@ -0,0 +1,47 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_raw_ptr_ops.rs:2:29 + | +LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_raw_ptr_ops.rs:4:30 + | +LL | let y: &'static usize = &(&1 as *const i32 as usize + 1); + | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_raw_ptr_ops.rs:6:28 + | +LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) }); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_raw_ptr_ops.rs:8:29 + | +LL | let a: &'static bool = &(main as fn() == main as fn()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr new file mode 100644 index 000000000..91a426580 --- /dev/null +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -0,0 +1,596 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:20:1 + | +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000001, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 01 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:28:1 + | +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:42:1 + | +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 01 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:44:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type Never + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 03 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:50:1 + | +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 78 00 00 00 ff ff ff ff │ x....... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:54:1 + | +LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:57:1 + | +LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 00 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:59:1 + | +LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:65:1 + | +LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 2a 00 00 00 │ *... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:71:1 + | +LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 14 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:74:1 + | +LL | const NULL_FAT_PTR: NonNull = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 00 00 00 00 ╾ALLOC_ID╼ │ ....╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:82:1 + | +LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC_ID╼ │ ╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:86:1 + | +LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC_ID╼ │ ╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:90:1 + | +LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:93:1 + | +LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:96:1 + | +LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 39 05 00 00 │ 9... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:99:1 + | +LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 39 05 00 00 │ 9... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:102:1 + | +LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 00 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:104:1 + | +LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 0d 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:106:1 + | +LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC_ID╼ │ ╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:112:1 + | +LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 01 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:137:1 + | +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ e7 03 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:139:1 + | +LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ff ff ff ff │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:141:1 + | +LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ff ff ff ff │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:144:1 + | +LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized data in `str` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:146:1 + | +LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered uninitialized data in `str` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:148:1 + | +LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:152:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ e7 03 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:154:1 + | +LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ff ff ff 7f │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:157:1 + | +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ e7 03 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:160:1 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC_ID╼ │ ╾──╼ + } + +note: erroneous constant used + --> $DIR/raw-bytes.rs:160:40 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:166:1 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC_ID╼ │ ╾──╼ + } + +note: erroneous constant used + --> $DIR/raw-bytes.rs:166:42 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:170:1 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC_ID╼ │ ╾──╼ + } + +note: erroneous constant used + --> $DIR/raw-bytes.rs:170:42 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:175:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:179:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:183:1 + | +LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:186:1 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:190:1 + | +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:194:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 00 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:196:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:201:1 + | +LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 00 10 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:205:1 + | +LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000003, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 09 00 00 00 03 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:209:1 + | +LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 01 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:210:1 + | +LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; + | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 01 00 00 00 01 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:211:1 + | +LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; + | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 01 00 00 00 2a 00 00 00 │ ....*... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:215:1 + | +LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:218:1 + | +LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) }; + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:221:1 + | +LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:225:1 + | +LL | pub static S7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[1]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID+0x2╼ 04 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:232:1 + | +LL | pub static R4: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 01 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:237:1 + | +LL | pub static R5: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼.... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:242:1 + | +LL | pub static R6: &[bool] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 04 00 00 00 │ ╾──╼.... + } + +error: aborting due to 52 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr new file mode 100644 index 000000000..e4c5e62f6 --- /dev/null +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -0,0 +1,596 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:20:1 + | +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000001, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 01 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:28:1 + | +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:42:1 + | +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 01 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:44:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type Never + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 03 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:50:1 + | +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + 78 00 00 00 ff ff ff ff │ x....... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:54:1 + | +LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:57:1 + | +LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 00 │ . + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:59:1 + | +LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:65:1 + | +LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 2a 00 00 00 │ *... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:71:1 + | +LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + 14 00 00 00 │ .... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:74:1 + | +LL | const NULL_FAT_PTR: NonNull = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 ╾ALLOC_ID╼ │ ........╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:82:1 + | +LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC_ID╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:86:1 + | +LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC_ID╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:90:1 + | +LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:93:1 + | +LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:96:1 + | +LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 39 05 00 00 00 00 00 00 │ 9....... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:99:1 + | +LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 39 05 00 00 00 00 00 00 │ 9....... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:102:1 + | +LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:104:1 + | +LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 0d 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:106:1 + | +LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC_ID╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:112:1 + | +LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 01 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:137:1 + | +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:139:1 + | +LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:141:1 + | +LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:144:1 + | +LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized data in `str` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:146:1 + | +LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered uninitialized data in `str` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:148:1 + | +LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:152:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:154:1 + | +LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:157:1 + | +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:160:1 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC_ID╼ │ ╾──────╼ + } + +note: erroneous constant used + --> $DIR/raw-bytes.rs:160:40 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:166:1 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC_ID╼ │ ╾──────╼ + } + +note: erroneous constant used + --> $DIR/raw-bytes.rs:166:42 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:170:1 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC_ID╼ │ ╾──────╼ + } + +note: erroneous constant used + --> $DIR/raw-bytes.rs:170:42 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:175:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:179:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:183:1 + | +LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:186:1 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:190:1 + | +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:194:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:196:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:201:1 + | +LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:205:1 + | +LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000003, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + 09 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 │ ................ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:209:1 + | +LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + 01 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:210:1 + | +LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; + | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:211:1 + | +LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; + | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + 01 00 00 00 00 00 00 00 2a 00 00 00 00 00 00 00 │ ........*....... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:215:1 + | +LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:218:1 + | +LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) }; + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:221:1 + | +LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:225:1 + | +LL | pub static S7: &[u16] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[1]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID+0x2╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:232:1 + | +LL | pub static R4: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:237:1 + | +LL | pub static R5: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:242:1 + | +LL | pub static R6: &[bool] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error: aborting due to 52 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs new file mode 100644 index 000000000..6c1238c0a --- /dev/null +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -0,0 +1,263 @@ +// stderr-per-bitwidth +// ignore-endian-big +// ignore-tidy-linelength +// normalize-stderr-test "╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$2╼" +// normalize-stderr-test "alloc\d+" -> "allocN" +#![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)] +#![allow(invalid_value)] + +use std::mem; +use std::alloc::Layout; +use std::ptr::NonNull; +use std::num::{NonZeroU8, NonZeroUsize}; +use std::slice::{from_ptr_range, from_raw_parts}; + +#[repr(usize)] +#[derive(Copy, Clone)] +enum Enum { + A = 0, +} +const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior + +#[repr(usize)] +#[derive(Copy, Clone)] +enum Enum2 { + A = 2, +} +const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; +//~^ ERROR is undefined behavior + +#[derive(Copy, Clone)] +enum Never {} + +// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do* +// have a discriminant. +enum UninhDiscriminant { + A, + B(!), + C, + D(Never), +} +const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; +//~^ ERROR is undefined behavior + +// Invalid enum field content (mostly to test printing of paths for enum tuple +// variants and tuples). +// Need to create something which does not clash with enum layout optimizations. +const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); +//~^ ERROR is undefined behavior + + +const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; +//~^ ERROR it is undefined behavior to use this value +const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +#[rustc_layout_scalar_valid_range_start(10)] +#[rustc_layout_scalar_valid_range_end(30)] +struct RestrictedRange1(u32); +const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; +//~^ ERROR it is undefined behavior to use this value + +#[rustc_layout_scalar_valid_range_start(30)] +#[rustc_layout_scalar_valid_range_end(10)] +struct RestrictedRange2(u32); +const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; +//~^ ERROR it is undefined behavior to use this value + +const NULL_FAT_PTR: NonNull = unsafe { +//~^ ERROR it is undefined behavior to use this value + let x: &dyn Send = &42; + let meta = std::ptr::metadata(x); + mem::transmute((0_usize, meta)) +}; + + +const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~| constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + +const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~| constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + +const NULL: &u16 = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + +const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + +const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value +const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; +//~^ ERROR it is undefined behavior to use this value +const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; +//~^ ERROR it is undefined behavior to use this value + +#[derive(Copy, Clone)] +enum Bar {} + +const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; +//~^ ERROR it is undefined behavior to use this value + + +/// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error +/// message. +#[repr(transparent)] +struct W(T); + +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} + +trait Trait {} +impl Trait for bool {} + +// custom unsized type +struct MyStr(str); + +// custom unsized type with sized fields +struct MySlice(bool, T); +type MySliceBool = MySlice<[bool]>; + +const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); +//~^ ERROR it is undefined behavior to use this value +const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; +//~^ ERROR it is undefined behavior to use this value + +const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; +//~^ ERROR it is undefined behavior to use this value +const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; +//~^ ERROR it is undefined behavior to use this value +const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; +//~^ ERROR: it is undefined behavior to use this value + +// # slice +const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice box: length too big +const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +// bad data *inside* the slice +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; +//~^ ERROR it is undefined behavior to use this value +//~| constant + + +// bad: sized field is not okay +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); +//~^ ERROR it is undefined behavior to use this value +//~| constant +// bad: unsized part is not okay +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); +//~^ ERROR it is undefined behavior to use this value +//~| constant + +// bad trait object +const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +// bad trait object +const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +// bad trait object +const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +// bad data *inside* the trait object +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a boolean + +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; +//~^ ERROR it is undefined behavior to use this value + + +// not ok, since alignment needs to be non-zero. +const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; +//~^ ERROR it is undefined behavior to use this value + +// not ok, since alignment needs to be a power of two. +const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; +//~^ ERROR it is undefined behavior to use this value + + +const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior +const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior +const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior + + +// Reading uninitialized data +pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; +//~^ ERROR: it is undefined behavior to use this value +// Reinterpret pointers as integers (UB in CTFE.) +pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) }; +//~^ ERROR: it is undefined behavior to use this value +// Layout mismatch +pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; +//~^ ERROR: it is undefined behavior to use this value + +// Reading padding is not ok +pub static S7: &[u16] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D2 as *const Struct as *const u16).add(1); + + from_raw_parts(ptr, 4) +}; + +pub static R4: &[u8] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = (&D1) as *const mem::MaybeUninit<&u32> as *const u8; + from_ptr_range(ptr..ptr.add(1)) +}; +pub static R5: &[u8] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = &D3 as *const &u32; + from_ptr_range(ptr.cast()..ptr.add(1).cast()) +}; +pub static R6: &[bool] = unsafe { + //~^ ERROR: it is undefined behavior to use this value + let ptr = &D0 as *const u32 as *const bool; + from_ptr_range(ptr..ptr.add(4)) +}; + +const D0: u32 = 0x11111111; // Constant chosen for endianness-independent behavior. +const D1: mem::MaybeUninit<&u32> = mem::MaybeUninit::uninit(); +const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 }; +const D3: &u32 = &42; + +#[repr(C)] +struct Struct { + a: u8, + // _pad: [mem::MaybeUninit; 3] + b: u32, + c: u16, + d: u8, + // _pad: [mem::MaybeUninit; 1] +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr new file mode 100644 index 000000000..032ceb246 --- /dev/null +++ b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr @@ -0,0 +1,24 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ref_to_int_match.rs:25:27 + | +LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; + | ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: could not evaluate constant pattern + --> $DIR/ref_to_int_match.rs:7:14 + | +LL | 10..=BAR => {}, + | ^^^ + +error: could not evaluate constant pattern + --> $DIR/ref_to_int_match.rs:7:14 + | +LL | 10..=BAR => {}, + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr new file mode 100644 index 000000000..032ceb246 --- /dev/null +++ b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr @@ -0,0 +1,24 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ref_to_int_match.rs:25:27 + | +LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; + | ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: could not evaluate constant pattern + --> $DIR/ref_to_int_match.rs:7:14 + | +LL | 10..=BAR => {}, + | ^^^ + +error: could not evaluate constant pattern + --> $DIR/ref_to_int_match.rs:7:14 + | +LL | 10..=BAR => {}, + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ref_to_int_match.rs b/tests/ui/consts/const-eval/ref_to_int_match.rs new file mode 100644 index 000000000..70c6e7d94 --- /dev/null +++ b/tests/ui/consts/const-eval/ref_to_int_match.rs @@ -0,0 +1,26 @@ +// stderr-per-bitwidth + +fn main() { + let n: Int = 40; + match n { + 0..=10 => {}, + 10..=BAR => {}, //~ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + _ => {}, + } +} + +#[repr(C)] +union Foo { + f: Int, + r: &'static u32, +} + +#[cfg(target_pointer_width="64")] +type Int = u64; + +#[cfg(target_pointer_width="32")] +type Int = u32; + +const BAR: Int = unsafe { Foo { r: &42 }.f }; +//~^ ERROR constant diff --git a/tests/ui/consts/const-eval/shift_overflow.rs b/tests/ui/consts/const-eval/shift_overflow.rs new file mode 100644 index 000000000..e843584b6 --- /dev/null +++ b/tests/ui/consts/const-eval/shift_overflow.rs @@ -0,0 +1,9 @@ +enum Foo { + // test that we detect overflows for non-u32 discriminants + X = 1 << ((u32::MAX as u64) + 1), //~ ERROR E0080 + Y = 42, +} + + +fn main() { +} diff --git a/tests/ui/consts/const-eval/shift_overflow.stderr b/tests/ui/consts/const-eval/shift_overflow.stderr new file mode 100644 index 000000000..e8d4076a6 --- /dev/null +++ b/tests/ui/consts/const-eval/shift_overflow.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/shift_overflow.rs:3:9 + | +LL | X = 1 << ((u32::MAX as u64) + 1), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left by `4294967296_u64`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/simd/insert_extract.rs b/tests/ui/consts/const-eval/simd/insert_extract.rs new file mode 100644 index 000000000..3472c05d1 --- /dev/null +++ b/tests/ui/consts/const-eval/simd/insert_extract.rs @@ -0,0 +1,70 @@ +// run-pass +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![feature(staged_api)] +#![stable(feature = "foo", since = "1.3.37")] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); +#[repr(simd)] struct u16x2(u16, u16); +// Make some of them array types to ensure those also work. +#[repr(simd)] struct i8x1_arr([i8; 1]); +#[repr(simd)] struct f32x4([f32; 4]); + +extern "platform-intrinsic" { + #[rustc_const_stable(feature = "foo", since = "1.3.37")] + fn simd_insert(x: T, idx: u32, val: U) -> T; + #[rustc_const_stable(feature = "foo", since = "1.3.37")] + fn simd_extract(x: T, idx: u32) -> U; +} + +fn main() { + { + const U: i8x1 = i8x1(13); + const V: i8x1 = unsafe { simd_insert(U, 0_u32, 42_i8) }; + const X0: i8 = V.0; + const Y0: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X0, 42); + assert_eq!(Y0, 42); + } + { + const U: i8x1_arr = i8x1_arr([13]); + const V: i8x1_arr = unsafe { simd_insert(U, 0_u32, 42_i8) }; + const X0: i8 = V.0[0]; + const Y0: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X0, 42); + assert_eq!(Y0, 42); + } + { + const U: u16x2 = u16x2(13, 14); + const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; + const X0: u16 = V.0; + const X1: u16 = V.1; + const Y0: u16 = unsafe { simd_extract(V, 0) }; + const Y1: u16 = unsafe { simd_extract(V, 1) }; + assert_eq!(X0, 13); + assert_eq!(X1, 42); + assert_eq!(Y0, 13); + assert_eq!(Y1, 42); + } + { + const U: f32x4 = f32x4([13., 14., 15., 16.]); + const V: f32x4 = unsafe { simd_insert(U, 1_u32, 42_f32) }; + const X0: f32 = V.0[0]; + const X1: f32 = V.0[1]; + const X2: f32 = V.0[2]; + const X3: f32 = V.0[3]; + const Y0: f32 = unsafe { simd_extract(V, 0) }; + const Y1: f32 = unsafe { simd_extract(V, 1) }; + const Y2: f32 = unsafe { simd_extract(V, 2) }; + const Y3: f32 = unsafe { simd_extract(V, 3) }; + assert_eq!(X0, 13.); + assert_eq!(X1, 42.); + assert_eq!(X2, 15.); + assert_eq!(X3, 16.); + assert_eq!(Y0, 13.); + assert_eq!(Y1, 42.); + assert_eq!(Y2, 15.); + assert_eq!(Y3, 16.); + } +} diff --git a/tests/ui/consts/const-eval/simple_with_undef.rs b/tests/ui/consts/const-eval/simple_with_undef.rs new file mode 100644 index 000000000..1a416dd46 --- /dev/null +++ b/tests/ui/consts/const-eval/simple_with_undef.rs @@ -0,0 +1,6 @@ +// check-pass + +const PARSE_BOOL: Option<&'static str> = None; +static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42); + +fn main() {} diff --git a/tests/ui/consts/const-eval/size-of-t.rs b/tests/ui/consts/const-eval/size-of-t.rs new file mode 100644 index 000000000..efbdeec70 --- /dev/null +++ b/tests/ui/consts/const-eval/size-of-t.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/69228 +// Used to give bogus suggestion about T not being Sized. + +use std::mem::size_of; + +fn foo() { + let _arr: [u8; size_of::()]; + //~^ ERROR generic parameters may not be used in const operations + //~| NOTE cannot perform const operation + //~| NOTE type parameters may not be used in const expressions +} + +fn main() {} diff --git a/tests/ui/consts/const-eval/size-of-t.stderr b/tests/ui/consts/const-eval/size-of-t.stderr new file mode 100644 index 000000000..abe641046 --- /dev/null +++ b/tests/ui/consts/const-eval/size-of-t.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/size-of-t.rs:7:30 + | +LL | let _arr: [u8; size_of::()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-eval/strlen.rs b/tests/ui/consts/const-eval/strlen.rs new file mode 100644 index 000000000..7b14a5235 --- /dev/null +++ b/tests/ui/consts/const-eval/strlen.rs @@ -0,0 +1,31 @@ +// run-pass + +const S: &str = "foo"; +pub const B: &[u8] = S.as_bytes(); +pub const C: usize = B.len(); +pub const D: bool = B.is_empty(); +pub const E: bool = S.is_empty(); +pub const F: usize = S.len(); + +pub fn foo() -> [u8; S.len()] { + let mut buf = [0; S.len()]; + for (i, &c) in S.as_bytes().iter().enumerate() { + buf[i] = c; + } + buf +} + +fn main() { + assert_eq!(&foo()[..], b"foo"); + assert_eq!(foo().len(), S.len()); + const LEN: usize = S.len(); + assert_eq!(LEN, S.len()); + assert_eq!(B, foo()); + assert_eq!(B, b"foo"); + assert_eq!(C, 3); + assert_eq!(F, 3); + assert!(!D); + assert!(!E); + const EMPTY: bool = "".is_empty(); + assert!(EMPTY); +} diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.rs b/tests/ui/consts/const-eval/transmute-const-promotion.rs new file mode 100644 index 000000000..1f0240d4b --- /dev/null +++ b/tests/ui/consts/const-eval/transmute-const-promotion.rs @@ -0,0 +1,6 @@ +use std::mem; + +fn main() { + let x: &'static u32 = unsafe { &mem::transmute(3.0f32) }; + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-eval/transmute-const-promotion.stderr b/tests/ui/consts/const-eval/transmute-const-promotion.stderr new file mode 100644 index 000000000..434a957f6 --- /dev/null +++ b/tests/ui/consts/const-eval/transmute-const-promotion.stderr @@ -0,0 +1,14 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/transmute-const-promotion.rs:4:37 + | +LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) }; + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/transmute-const.32bit.stderr b/tests/ui/consts/const-eval/transmute-const.32bit.stderr new file mode 100644 index 000000000..09fd79986 --- /dev/null +++ b/tests/ui/consts/const-eval/transmute-const.32bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/transmute-const.rs:4:1 + | +LL | static FOO: bool = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 03 │ . + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/transmute-const.64bit.stderr b/tests/ui/consts/const-eval/transmute-const.64bit.stderr new file mode 100644 index 000000000..09fd79986 --- /dev/null +++ b/tests/ui/consts/const-eval/transmute-const.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/transmute-const.rs:4:1 + | +LL | static FOO: bool = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 03 │ . + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/transmute-const.rs b/tests/ui/consts/const-eval/transmute-const.rs new file mode 100644 index 000000000..d9d0a3aea --- /dev/null +++ b/tests/ui/consts/const-eval/transmute-const.rs @@ -0,0 +1,7 @@ +// stderr-per-bitwidth +use std::mem; + +static FOO: bool = unsafe { mem::transmute(3u8) }; +//~^ ERROR it is undefined behavior to use this value + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.rs b/tests/ui/consts/const-eval/ub-enum-overwrite.rs new file mode 100644 index 000000000..086a1001d --- /dev/null +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.rs @@ -0,0 +1,18 @@ +#![feature(const_mut_refs)] + +enum E { + A(u8), + B, +} + +const _: u8 = { + let mut e = E::A(1); + let p = if let E::A(x) = &mut e { x as *mut u8 } else { unreachable!() }; + // Make sure overwriting `e` uninitializes other bytes + e = E::B; + unsafe { *p } + //~^ ERROR evaluation of constant value failed + //~| uninitialized +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr new file mode 100644 index 000000000..5750212b4 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum-overwrite.rs:13:14 + | +LL | unsafe { *p } + | ^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-enum.32bit.stderr b/tests/ui/consts/const-eval/ub-enum.32bit.stderr new file mode 100644 index 000000000..2d86bd88f --- /dev/null +++ b/tests/ui/consts/const-eval/ub-enum.32bit.stderr @@ -0,0 +1,121 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:27:1 + | +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000001, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:30:1 + | +LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:33:1 + | +LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:45:1 + | +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x00000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:47:1 + | +LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:50:1 + | +LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:59:42 + | +LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:64:1 + | +LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:81:1 + | +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:83:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type Never + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:91:1 + | +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:96:77 + | +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) }; + | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:98:77 + | +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) }; + | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-enum.64bit.stderr b/tests/ui/consts/const-eval/ub-enum.64bit.stderr new file mode 100644 index 000000000..a89d7ec5f --- /dev/null +++ b/tests/ui/consts/const-eval/ub-enum.64bit.stderr @@ -0,0 +1,121 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:27:1 + | +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000001, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:30:1 + | +LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:33:1 + | +LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:45:1 + | +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x0000000000000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:47:1 + | +LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:50:1 + | +LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:59:42 + | +LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:64:1 + | +LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:81:1 + | +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:83:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type Never + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:91:1 + | +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:96:77 + | +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) }; + | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-enum.rs:98:77 + | +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) }; + | ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-enum.rs b/tests/ui/consts/const-eval/ub-enum.rs new file mode 100644 index 000000000..8f26d9a00 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-enum.rs @@ -0,0 +1,102 @@ +// stderr-per-bitwidth +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +#![feature(never_type)] +#![allow(invalid_value)] + +use std::mem; + +#[repr(transparent)] +#[derive(Copy, Clone)] +struct Wrap(T); + +#[derive(Copy, Clone)] +enum Never {} + +// # simple enum with discriminant 0 + +#[repr(usize)] +#[derive(Copy, Clone)] +enum Enum { + A = 0, +} + +const GOOD_ENUM: Enum = unsafe { mem::transmute(0usize) }; + +const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior + +const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; +//~^ ERROR evaluation of constant value failed + +const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; +//~^ ERROR evaluation of constant value failed + +// # simple enum with discriminant 2 + +// (Potentially) invalid enum discriminant +#[repr(usize)] +#[derive(Copy, Clone)] +enum Enum2 { + A = 2, +} + +const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; +//~^ ERROR is undefined behavior +const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; +//~^ ERROR evaluation of constant value failed +// something wrapping the enum so that we test layout first, not enum +const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; +//~^ ERROR evaluation of constant value failed + +// Undef enum discriminant. +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} +const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; +//~^ ERROR evaluation of constant value failed +//~| uninitialized + +// Pointer value in an enum with a niche that is not just 0. +const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; +//~^ ERROR evaluation of constant value failed + +// # valid discriminant for uninhabited variant + +// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do* +// have a discriminant. +enum UninhDiscriminant { + A, + B(!), + C, + D(Never), +} + +const GOOD_INHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(0u8) }; // variant A +const GOOD_INHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(2u8) }; // variant C + +const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; +//~^ ERROR is undefined behavior + +// # other + +// Invalid enum field content (mostly to test printing of paths for enum tuple +// variants and tuples). +// Need to create something which does not clash with enum layout optimizations. +const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); +//~^ ERROR is undefined behavior + +// All variants are uninhabited but also have data. +// Use `0` as constant to make behavior endianness-independent. +const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) }; +//~^ ERROR evaluation of constant value failed +const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) }; +//~^ ERROR evaluation of constant value failed + +fn main() { +} diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr new file mode 100644 index 000000000..965256de2 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -0,0 +1,59 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:19:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:24:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:33:1 + | +LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:38:1 + | +LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:44:1 + | +LL | const INVALID_VTABLE_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:91:1 + | +LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; + | ^^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─allocN─╼ ╾─allocN─╼ │ ╾──╼╾──╼ + } + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr new file mode 100644 index 000000000..bd542a7a5 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -0,0 +1,59 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:19:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-incorrect-vtable.rs:24:14 + | +LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:33:1 + | +LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:38:1 + | +LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:44:1 + | +LL | const INVALID_VTABLE_UB: W<&dyn Trait> = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:91:1 + | +LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; + | ^^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────allocN───────╼ ╾───────allocN───────╼ │ ╾──────╼╾──────╼ + } + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs new file mode 100644 index 000000000..4bb30b75b --- /dev/null +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -0,0 +1,96 @@ +// This test contains code with incorrect vtables in a const context: +// - from issue 86132: a trait object with invalid alignment caused an ICE in const eval, and now +// triggers an error +// - a similar test that triggers a previously-untested const UB error: emitted close to the above +// error, it checks the correctness of the size +// +// As is, this code will only hard error when the constants are used, and the errors are emitted via +// the `#[allow]`-able `const_err` lint. However, if the transparent wrapper technique to prevent +// reborrows is used -- from `ub-wide-ptr.rs` -- these two errors reach validation and would trigger +// ICEs as tracked by #86193. So we also use the transparent wrapper to verify proper validation +// errors are emitted instead of ICEs. + +// stderr-per-bitwidth +// normalize-stderr-test "alloc\d+" -> "allocN" + +trait Trait {} + +const INVALID_VTABLE_ALIGNMENT: &dyn Trait = + unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; +//~^ ERROR evaluation of constant value failed +//~| does not point to a vtable + +const INVALID_VTABLE_SIZE: &dyn Trait = + unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; +//~^ ERROR evaluation of constant value failed +//~| does not point to a vtable + +#[repr(transparent)] +struct W(T); + +fn drop_me(_: *mut usize) {} + +const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = + unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) }; +//~^^ ERROR it is undefined behavior to use this value +//~| expected a vtable pointer + +const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = + unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) }; +//~^^ ERROR it is undefined behavior to use this value +//~| expected a vtable pointer + +// Even if the vtable has a fn ptr and a reasonable size+align, it still does not work. +const INVALID_VTABLE_UB: W<&dyn Trait> = + unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1usize))) }; +//~^^ ERROR it is undefined behavior to use this value +//~| expected a vtable pointer + +// Trying to access the data in a vtable does not work, either. + +#[derive(Copy, Clone)] +struct Wide<'a>(&'a Foo, &'static VTable); + +struct VTable { + drop: Option fn(&'a mut Foo)>, + size: usize, + align: usize, + bar: for<'a> fn(&'a Foo) -> u32, +} + +trait Bar { + fn bar(&self) -> u32; +} + +struct Foo { + foo: u32, + bar: bool, +} + +impl Bar for Foo { + fn bar(&self) -> u32 { + self.foo + } +} + +impl Drop for Foo { + fn drop(&mut self) { + assert!(!self.bar); + self.bar = true; + println!("dropping Foo"); + } +} + +#[repr(C)] +union Transmute { + t: T, + u: U, +} + +const FOO: &dyn Bar = &Foo { foo: 128, bar: false }; +const G: Wide = unsafe { Transmute { t: FOO }.u }; +//~^ ERROR it is undefined behavior to use this value +//~| encountered a dangling reference +// (it is dangling because vtables do not contain memory that can be dereferenced) + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-int-array.32bit.stderr b/tests/ui/consts/const-eval/ub-int-array.32bit.stderr new file mode 100644 index 000000000..edcde13b0 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-int-array.32bit.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-int-array.rs:15:9 + | +LL | MaybeUninit { uninit: () }.init, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-int-array.rs:30:13 + | +LL | MaybeUninit { uninit: () }.init, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-int-array.rs:56:13 + | +LL | MaybeUninit { uninit: () }.init, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-int-array.64bit.stderr b/tests/ui/consts/const-eval/ub-int-array.64bit.stderr new file mode 100644 index 000000000..edcde13b0 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-int-array.64bit.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/ub-int-array.rs:15:9 + | +LL | MaybeUninit { uninit: () }.init, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-int-array.rs:30:13 + | +LL | MaybeUninit { uninit: () }.init, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-int-array.rs:56:13 + | +LL | MaybeUninit { uninit: () }.init, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-int-array.rs b/tests/ui/consts/const-eval/ub-int-array.rs new file mode 100644 index 000000000..a68d3fb17 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-int-array.rs @@ -0,0 +1,63 @@ +// stderr-per-bitwidth +//! Test the "array of int" fast path in validity checking, and in particular whether it +//! points at the right array element. + +use std::mem; + +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} + +const UNINIT_INT_0: [u32; 3] = unsafe { + [ + MaybeUninit { uninit: () }.init, + //~^ ERROR evaluation of constant value failed + //~| uninitialized + 1, + 2, + ] +}; +const UNINIT_INT_1: [u32; 3] = unsafe { + mem::transmute( + [ + 0u8, + 0u8, + 0u8, + 0u8, + 1u8, + MaybeUninit { uninit: () }.init, + //~^ ERROR evaluation of constant value failed + //~| uninitialized + 1u8, + 1u8, + 2u8, + 2u8, + MaybeUninit { uninit: () }.init, + 2u8, + ] + ) +}; +const UNINIT_INT_2: [u32; 3] = unsafe { + mem::transmute( + [ + 0u8, + 0u8, + 0u8, + 0u8, + 1u8, + 1u8, + 1u8, + 1u8, + 2u8, + 2u8, + 2u8, + MaybeUninit { uninit: () }.init, + //~^ ERROR evaluation of constant value failed + //~| uninitialized + ] + ) +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr b/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr new file mode 100644 index 000000000..2a4b6f3b7 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `>::Output == _` + --> $DIR/ub-nonnull.rs:19:30 + | +LL | let out_of_bounds_ptr = &ptr[255]; + | ^^^^^^^^ cannot satisfy `>::Output == _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/consts/const-eval/ub-nonnull.rs b/tests/ui/consts/const-eval/ub-nonnull.rs new file mode 100644 index 000000000..a64b3a74c --- /dev/null +++ b/tests/ui/consts/const-eval/ub-nonnull.rs @@ -0,0 +1,59 @@ +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +#![feature(rustc_attrs, ptr_metadata)] +#![allow(invalid_value)] // make sure we cannot allow away the errors tested here + +use std::mem; +use std::ptr::NonNull; +use std::num::{NonZeroU8, NonZeroUsize}; + +const NON_NULL: NonNull = unsafe { mem::transmute(1usize) }; +const NON_NULL_PTR: NonNull = unsafe { mem::transmute(&1) }; + +const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { + let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle + // Use address-of-element for pointer arithmetic. This could wrap around to null! + let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed + mem::transmute(out_of_bounds_ptr) +} }; + +const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; +//~^ ERROR it is undefined behavior to use this value +const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} +const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; +//~^ ERROR evaluation of constant value failed +//~| uninitialized + +// Also test other uses of rustc_layout_scalar_valid_range_start + +#[rustc_layout_scalar_valid_range_start(10)] +#[rustc_layout_scalar_valid_range_end(30)] +struct RestrictedRange1(u32); +const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; +//~^ ERROR it is undefined behavior to use this value + +#[rustc_layout_scalar_valid_range_start(30)] +#[rustc_layout_scalar_valid_range_end(10)] +struct RestrictedRange2(u32); +const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; +//~^ ERROR it is undefined behavior to use this value + +const NULL_FAT_PTR: NonNull = unsafe { +//~^ ERROR it is undefined behavior to use this value + let x: &dyn Send = &42; + let meta = std::ptr::metadata(x); + mem::transmute((0_usize, meta)) +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr new file mode 100644 index 000000000..961648708 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -0,0 +1,81 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:14:1 + | +LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-nonnull.rs:20:30 + | +LL | let out_of_bounds_ptr = &ptr[255]; + | ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:24:1 + | +LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:26:1 + | +LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-nonnull.rs:34:36 + | +LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:43:1 + | +LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:49:1 + | +LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-nonnull.rs:52:1 + | +LL | const NULL_FAT_PTR: NonNull = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs new file mode 100644 index 000000000..369e45194 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs @@ -0,0 +1,71 @@ +// ignore-tidy-linelength +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +#![allow(invalid_value)] +#![feature(const_ptr_read)] + +use std::mem; + +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} + +const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~| constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + +const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~| constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + +const NULL: &u16 = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + +const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + + +// It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`, +// but that would fail to compile; so we ended up breaking user code that would +// have worked fine had we not promoted. +const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; +//~^ ERROR evaluation of constant value failed + +const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; +//~^ ERROR evaluation of constant value failed + +const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; +//~^ ERROR evaluation of constant value failed + +const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + +const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + +const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; +//~^ ERROR evaluation of constant value failed +//~| uninitialized + +const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value +const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; +//~^ ERROR evaluation of constant value failed +//~| uninitialized +const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; +//~^ ERROR it is undefined behavior to use this value +const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; +//~^ ERROR it is undefined behavior to use this value + + +const UNALIGNED_READ: () = unsafe { + let x = &[0u8; 4]; + let ptr = x.as_ptr().cast::(); + ptr.read(); //~ inside `UNALIGNED_READ` +}; + + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr new file mode 100644 index 000000000..ce618802b --- /dev/null +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -0,0 +1,186 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:16:1 + | +LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:20:1 + | +LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:24:1 + | +LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:27:1 + | +LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-ref-ptr.rs:34:1 + | +LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-ref-ptr.rs:37:39 + | +LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +note: erroneous constant used + --> $DIR/ub-ref-ptr.rs:37:38 + | +LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-ref-ptr.rs:40:86 + | +LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; + | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +note: erroneous constant used + --> $DIR/ub-ref-ptr.rs:40:85 + | +LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:43:1 + | +LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:46:1 + | +LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-ref-ptr.rs:49:41 + | +LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:53:1 + | +LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-ref-ptr.rs:55:38 + | +LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:58:1 + | +LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref-ptr.rs:60:1 + | +LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: accessing memory with alignment 1, but alignment 4 is required + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 +note: inside `std::ptr::read::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `ptr::const_ptr::::read` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `UNALIGNED_READ` + --> $DIR/ub-ref-ptr.rs:67:5 + | +LL | ptr.read(); + | ^^^^^^^^^^ + = note: `#[deny(invalid_alignment)]` on by default + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: accessing memory with alignment 1, but alignment 4 is required + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 +note: inside `std::ptr::read::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `ptr::const_ptr::::read` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `UNALIGNED_READ` + --> $DIR/ub-ref-ptr.rs:67:5 + | +LL | ptr.read(); + | ^^^^^^^^^^ + = note: `#[deny(invalid_alignment)]` on by default + diff --git a/tests/ui/consts/const-eval/ub-uninhabit.rs b/tests/ui/consts/const-eval/ub-uninhabit.rs new file mode 100644 index 000000000..4c4ef216d --- /dev/null +++ b/tests/ui/consts/const-eval/ub-uninhabit.rs @@ -0,0 +1,25 @@ +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" + +use std::mem; + +#[derive(Copy, Clone)] +enum Bar {} + +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} + +const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; +//~^ ERROR it is undefined behavior to use this value + +const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; +//~^ ERROR it is undefined behavior to use this value + +const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; +//~^ ERROR it is undefined behavior to use this value + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-uninhabit.stderr b/tests/ui/consts/const-eval/ub-uninhabit.stderr new file mode 100644 index 000000000..0ae376d03 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-uninhabit.stderr @@ -0,0 +1,32 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-uninhabit.rs:16:1 + | +LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {} + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-uninhabit.rs:19:1 + | +LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-uninhabit.rs:22:1 + | +LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {} + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr new file mode 100644 index 000000000..f7898e55e --- /dev/null +++ b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-upvars.rs:6:1 + | +LL | const BAD_UPVAR: &dyn FnOnce() = &{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...: encountered a null reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─alloc3──╼ ╾─alloc4──╼ │ ╾──╼╾──╼ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr new file mode 100644 index 000000000..60432380e --- /dev/null +++ b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-upvars.rs:6:1 + | +LL | const BAD_UPVAR: &dyn FnOnce() = &{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...: encountered a null reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-upvars.rs b/tests/ui/consts/const-eval/ub-upvars.rs new file mode 100644 index 000000000..ceac59870 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-upvars.rs @@ -0,0 +1,12 @@ +// stderr-per-bitwidth +#![allow(invalid_value)] // make sure we cannot allow away the errors tested here + +use std::mem; + +const BAD_UPVAR: &dyn FnOnce() = &{ //~ ERROR it is undefined behavior to use this value + let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; + let another_var = 13; + move || { let _ = bad_ref; let _ = another_var; } +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr new file mode 100644 index 000000000..39352ca84 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/ub-wide-ptr.rs:90:67 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs new file mode 100644 index 000000000..a765dc712 --- /dev/null +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -0,0 +1,159 @@ +// ignore-tidy-linelength +#![allow(unused)] + +use std::mem; + +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "offset \d+" -> "offset N" +// normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "size \d+" -> "size N" + +/// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error +/// message. +#[repr(transparent)] +struct W(T); + +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} + +trait Trait {} +impl Trait for bool {} + +// custom unsized type +struct MyStr(str); + +// custom unsized type with sized fields +struct MySlice(bool, T); +type MySliceBool = MySlice<[bool]>; + +// # str +// OK +const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) }; +// bad str +const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); +//~^ ERROR it is undefined behavior to use this value +// bad str +const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR evaluation of constant value failed +// bad str in user-defined unsized type +const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR evaluation of constant value failed +const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; +//~^ ERROR it is undefined behavior to use this value + +// uninitialized byte +const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; +//~^ ERROR it is undefined behavior to use this value +// uninitialized byte in user-defined str-like +const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; +//~^ ERROR it is undefined behavior to use this value + +// # slice +// OK +const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) }; +// bad slice: length uninit +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { +//~^ ERROR evaluation of constant value failed +//~| uninitialized + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; +// bad slice: length too big +const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice: length computation overflows +const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice: length not an int +const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR evaluation of constant value failed +// bad slice box: length too big +const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice box: length not an int +const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR evaluation of constant value failed + +// bad data *inside* the slice +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; +//~^ ERROR it is undefined behavior to use this value +//~| constant + +// good MySliceBool +const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); +// bad: sized field is not okay +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); +//~^ ERROR it is undefined behavior to use this value +//~| constant +// bad: unsized part is not okay +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); +//~^ ERROR it is undefined behavior to use this value +//~| constant + +// # raw slice +const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::MAX)) }; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { +//~^ ERROR evaluation of constant value failed +//~| uninitialized + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; + +// # trait object +// bad trait object +const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +// bad trait object +const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +// bad trait object +const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable +const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; +//~^ ERROR evaluation of constant value failed +//~| does not point to a vtable +const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; +//~^ ERROR evaluation of constant value failed +//~| does not point to a vtable +const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; +//~^ ERROR evaluation of constant value failed +//~| does not point to a vtable +const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a vtable + +// bad data *inside* the trait object +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; +//~^ ERROR it is undefined behavior to use this value +//~| expected a boolean + +// # raw trait object +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; +//~^ ERROR it is undefined behavior to use this value +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw + +// Const eval fails for these, so they need to be statics to error. +static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { + mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + //~^ ERROR could not evaluate static initializer +}; +static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { + mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) + //~^ ERROR could not evaluate static initializer +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr new file mode 100644 index 000000000..f38e7916b --- /dev/null +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -0,0 +1,297 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:38:1 + | +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:40:1 + | +LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:43:1 + | +LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:46:1 + | +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:48:1 + | +LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:52:1 + | +LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized data in `str` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:55:1 + | +LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered uninitialized data in `str` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:62:1 + | +LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:69:1 + | +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:72:1 + | +LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:75:1 + | +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:78:1 + | +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:81:1 + | +LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:85:1 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +note: erroneous constant used + --> $DIR/ub-wide-ptr.rs:85:40 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:92:1 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +note: erroneous constant used + --> $DIR/ub-wide-ptr.rs:92:42 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:96:1 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +note: erroneous constant used + --> $DIR/ub-wide-ptr.rs:96:42 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:104:1 + | +LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:113:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:117:1 + | +LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:121:1 + | +LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:124:57 + | +LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:127:57 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: evaluation of constant value failed + --> $DIR/ub-wide-ptr.rs:130:56 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:133:1 + | +LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:138:1 + | +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..: encountered 0x03, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:143:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:145:1 + | +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:151:5 + | +LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance) + +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:155:5 + | +LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + +error: aborting due to 29 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/union-const-eval-field.rs b/tests/ui/consts/const-eval/union-const-eval-field.rs new file mode 100644 index 000000000..a94fcbbfa --- /dev/null +++ b/tests/ui/consts/const-eval/union-const-eval-field.rs @@ -0,0 +1,38 @@ +// only-x86_64 + +type Field1 = i32; +type Field2 = f32; +type Field3 = i64; + +#[repr(C)] +union DummyUnion { + field1: Field1, + field2: Field2, + field3: Field3, +} + +const FLOAT1_AS_I32: i32 = 1065353216; +const UNION: DummyUnion = DummyUnion { field1: FLOAT1_AS_I32 }; + +const fn read_field1() -> Field1 { + const FIELD1: Field1 = unsafe { UNION.field1 }; + FIELD1 +} + +const fn read_field2() -> Field2 { + const FIELD2: Field2 = unsafe { UNION.field2 }; + FIELD2 +} + +const fn read_field3() -> Field3 { + const FIELD3: Field3 = unsafe { UNION.field3 }; + //~^ ERROR evaluation of constant value failed + //~| uninitialized + FIELD3 +} + +fn main() { + assert_eq!(read_field1(), FLOAT1_AS_I32); + assert_eq!(read_field2(), 1.0); + assert_eq!(read_field3(), unsafe { UNION.field3 }); +} diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr new file mode 100644 index 000000000..9899c56c0 --- /dev/null +++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/union-const-eval-field.rs:28:37 + | +LL | const FIELD3: Field3 = unsafe { UNION.field3 }; + | ^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +note: erroneous constant used + --> $DIR/union-const-eval-field.rs:31:5 + | +LL | FIELD3 + | ^^^^^^ + +note: erroneous constant used + --> $DIR/union-const-eval-field.rs:31:5 + | +LL | FIELD3 + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/union-ice.rs b/tests/ui/consts/const-eval/union-ice.rs new file mode 100644 index 000000000..dd970a355 --- /dev/null +++ b/tests/ui/consts/const-eval/union-ice.rs @@ -0,0 +1,48 @@ +// only-x86_64 + +type Field1 = i32; +type Field3 = i64; + +#[repr(C)] +union DummyUnion { + field1: Field1, + field3: Field3, +} + +const UNION: DummyUnion = DummyUnion { field1: 1065353216 }; + +const FIELD3: Field3 = unsafe { UNION.field3 }; +//~^ ERROR evaluation of constant value failed +//~| uninitialized + +const FIELD_PATH: Struct = Struct { + a: 42, + b: unsafe { UNION.field3 }, + //~^ ERROR evaluation of constant value failed + //~| uninitialized +}; + +struct Struct { + a: u8, + b: Field3, +} + +const FIELD_PATH2: Struct2 = Struct2 { + b: [ + 21, + unsafe { UNION.field3 }, + //~^ ERROR evaluation of constant value failed + //~| uninitialized + 23, + 24, + ], + a: 42, +}; + +struct Struct2 { + b: [Field3; 4], + a: u8, +} + +fn main() { +} diff --git a/tests/ui/consts/const-eval/union-ice.stderr b/tests/ui/consts/const-eval/union-ice.stderr new file mode 100644 index 000000000..bd39a0551 --- /dev/null +++ b/tests/ui/consts/const-eval/union-ice.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/union-ice.rs:14:33 + | +LL | const FIELD3: Field3 = unsafe { UNION.field3 }; + | ^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/union-ice.rs:20:17 + | +LL | b: unsafe { UNION.field3 }, + | ^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/union-ice.rs:33:18 + | +LL | unsafe { UNION.field3 }, + | ^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/union-ub.32bit.stderr b/tests/ui/consts/const-eval/union-ub.32bit.stderr new file mode 100644 index 000000000..e5c8f88be --- /dev/null +++ b/tests/ui/consts/const-eval/union-ub.32bit.stderr @@ -0,0 +1,20 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/union-ub.rs:32:1 + | +LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 2a │ * + } + +error[E0080]: evaluation of constant value failed + --> $DIR/union-ub.rs:34:36 + | +LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/union-ub.64bit.stderr b/tests/ui/consts/const-eval/union-ub.64bit.stderr new file mode 100644 index 000000000..e5c8f88be --- /dev/null +++ b/tests/ui/consts/const-eval/union-ub.64bit.stderr @@ -0,0 +1,20 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/union-ub.rs:32:1 + | +LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 2a │ * + } + +error[E0080]: evaluation of constant value failed + --> $DIR/union-ub.rs:34:36 + | +LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/union-ub.rs b/tests/ui/consts/const-eval/union-ub.rs new file mode 100644 index 000000000..043870c9c --- /dev/null +++ b/tests/ui/consts/const-eval/union-ub.rs @@ -0,0 +1,43 @@ +// stderr-per-bitwidth + +#[repr(C)] +union DummyUnion { + unit: (), + u8: u8, + bool: bool, +} + +#[repr(C)] +#[derive(Copy, Clone)] +enum Enum { + A, + B, + C, +} + +#[derive(Copy, Clone)] +#[repr(C)] +union Foo { + a: bool, + b: Enum, +} + +#[repr(C)] +union Bar { + foo: Foo, + u8: u8, +} + +// the value is not valid for bools +const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; +//~^ ERROR it is undefined behavior to use this value +const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool}; +//~^ ERROR evaluation of constant value failed +//~| uninitialized + +// The value is not valid for any union variant, but that's fine +// unions are just a convenient way to transmute bits around +const BAD_UNION: Foo = unsafe { Bar { u8: 42 }.foo }; + + +fn main() {} diff --git a/tests/ui/consts/const-eval/union_promotion.rs b/tests/ui/consts/const-eval/union_promotion.rs new file mode 100644 index 000000000..18894c45f --- /dev/null +++ b/tests/ui/consts/const-eval/union_promotion.rs @@ -0,0 +1,11 @@ +#[repr(C)] +union Foo { + a: &'static u32, + b: usize, +} + +fn main() { + let x: &'static bool = &unsafe { //~ temporary value dropped while borrowed + Foo { a: &1 }.b == Foo { a: &2 }.b + }; +} diff --git a/tests/ui/consts/const-eval/union_promotion.stderr b/tests/ui/consts/const-eval/union_promotion.stderr new file mode 100644 index 000000000..42f17de20 --- /dev/null +++ b/tests/ui/consts/const-eval/union_promotion.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/union_promotion.rs:8:29 + | +LL | let x: &'static bool = &unsafe { + | ____________-------------____^ + | | | + | | type annotation requires that borrow lasts for `'static` +LL | | Foo { a: &1 }.b == Foo { a: &2 }.b +LL | | }; + | |_____^ creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-eval/unused-broken-const.rs b/tests/ui/consts/const-eval/unused-broken-const.rs new file mode 100644 index 000000000..0d2776bc2 --- /dev/null +++ b/tests/ui/consts/const-eval/unused-broken-const.rs @@ -0,0 +1,8 @@ +// make sure that an *unused* broken const triggers an error even in a check build + +// compile-flags: --emit=dep-info,metadata + +const FOO: i32 = [][0]; +//~^ ERROR evaluation of constant value failed + +fn main() {} diff --git a/tests/ui/consts/const-eval/unused-broken-const.stderr b/tests/ui/consts/const-eval/unused-broken-const.stderr new file mode 100644 index 000000000..fbb10feb7 --- /dev/null +++ b/tests/ui/consts/const-eval/unused-broken-const.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/unused-broken-const.rs:5:18 + | +LL | const FOO: i32 = [][0]; + | ^^^^^ index out of bounds: the length is 0 but the index is 0 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/unwind-abort.rs b/tests/ui/consts/const-eval/unwind-abort.rs new file mode 100644 index 000000000..2b0e58166 --- /dev/null +++ b/tests/ui/consts/const-eval/unwind-abort.rs @@ -0,0 +1,12 @@ +#![feature(c_unwind, const_extern_fn)] + +const extern "C" fn foo() { + panic!() //~ ERROR evaluation of constant value failed +} + +const _: () = foo(); +// Ensure that the CTFE engine handles calls to `extern "C"` aborting gracefully + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/consts/const-eval/unwind-abort.stderr b/tests/ui/consts/const-eval/unwind-abort.stderr new file mode 100644 index 000000000..759ce15ab --- /dev/null +++ b/tests/ui/consts/const-eval/unwind-abort.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/unwind-abort.rs:4:5 + | +LL | panic!() + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5 + | +note: inside `foo` + --> $DIR/unwind-abort.rs:4:5 + | +LL | panic!() + | ^^^^^^^^ +note: inside `_` + --> $DIR/unwind-abort.rs:7:15 + | +LL | const _: () = foo(); + | ^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/valid-const.rs b/tests/ui/consts/const-eval/valid-const.rs new file mode 100644 index 000000000..5f47d1c4f --- /dev/null +++ b/tests/ui/consts/const-eval/valid-const.rs @@ -0,0 +1,17 @@ +// check-pass + +// Some constants that *are* valid + +use std::mem; +use std::ptr::NonNull; +use std::num::{NonZeroU8, NonZeroUsize}; + +const NON_NULL_PTR1: NonNull = unsafe { mem::transmute(1usize) }; +const NON_NULL_PTR2: NonNull = unsafe { mem::transmute(&0) }; + +const NON_NULL_U8: NonZeroU8 = unsafe { mem::transmute(1u8) }; +const NON_NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(1usize) }; + +const UNIT: () = (); + +fn main() {} diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr new file mode 100644 index 000000000..9710bf476 --- /dev/null +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr @@ -0,0 +1,61 @@ +warning: the type `!` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:4:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + = note: `#[warn(invalid_value)]` on by default + +error[E0080]: evaluation of constant value failed + --> $DIR/validate_uninhabited_zsts.rs:4:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + | +note: inside `foo` + --> $DIR/validate_uninhabited_zsts.rs:4:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `FOO` + --> $DIR/validate_uninhabited_zsts.rs:19:33 + | +LL | const FOO: [empty::Empty; 3] = [foo(); 3]; + | ^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_uninhabited_zsts.rs:21:1 + | +LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 0, align: 1) {} + +warning: the type `empty::Empty` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:21:42 + | +LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: in this struct field + --> $DIR/validate_uninhabited_zsts.rs:16:22 + | +LL | pub struct Empty(Void); + | ^^^^ +note: enums with no inhabited variants have no valid value + --> $DIR/validate_uninhabited_zsts.rs:13:5 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr new file mode 100644 index 000000000..9710bf476 --- /dev/null +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr @@ -0,0 +1,61 @@ +warning: the type `!` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:4:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + = note: `#[warn(invalid_value)]` on by default + +error[E0080]: evaluation of constant value failed + --> $DIR/validate_uninhabited_zsts.rs:4:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + | +note: inside `foo` + --> $DIR/validate_uninhabited_zsts.rs:4:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `FOO` + --> $DIR/validate_uninhabited_zsts.rs:19:33 + | +LL | const FOO: [empty::Empty; 3] = [foo(); 3]; + | ^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_uninhabited_zsts.rs:21:1 + | +LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 0, align: 1) {} + +warning: the type `empty::Empty` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:21:42 + | +LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: in this struct field + --> $DIR/validate_uninhabited_zsts.rs:16:22 + | +LL | pub struct Empty(Void); + | ^^^^ +note: enums with no inhabited variants have no valid value + --> $DIR/validate_uninhabited_zsts.rs:13:5 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs b/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs new file mode 100644 index 000000000..c0b326215 --- /dev/null +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs @@ -0,0 +1,28 @@ +// stderr-per-bitwidth + +const fn foo() -> ! { + unsafe { std::mem::transmute(()) } + //~^ ERROR evaluation of constant value failed + //~| WARN the type `!` does not permit zero-initialization [invalid_value] +} + +// Type defined in a submodule, so that it is not "visibly" +// uninhabited (which would change interpreter behavior). +pub mod empty { + #[derive(Clone, Copy)] + enum Void {} + + #[derive(Clone, Copy)] + pub struct Empty(Void); +} + +const FOO: [empty::Empty; 3] = [foo(); 3]; + +const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; +//~^ ERROR it is undefined behavior to use this value +//~| WARN the type `empty::Empty` does not permit zero-initialization + +fn main() { + FOO; + BAR; +} diff --git a/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs b/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs new file mode 100644 index 000000000..cccb7879f --- /dev/null +++ b/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs @@ -0,0 +1,28 @@ +// run-pass + +#![allow(dead_code)] + +enum Empty { } +enum Test1 { + A(u8), + B(Empty), +} +enum Test2 { + A(u8), + B(Empty), + C, +} + +fn bar() -> Option { + None +} + +fn main() { + if let Some(x) = bar() { + Test1::B(x); + } + + if let Some(x) = bar() { + Test2::B(x); + } +} diff --git a/tests/ui/consts/const-eval/zst_operand_eval.rs b/tests/ui/consts/const-eval/zst_operand_eval.rs new file mode 100644 index 000000000..5f7ddf7f7 --- /dev/null +++ b/tests/ui/consts/const-eval/zst_operand_eval.rs @@ -0,0 +1,5 @@ +// check-pass + +static ASSERT: () = [()][!(std::mem::size_of::() == 4) as usize]; + +fn main() {} diff --git a/tests/ui/consts/const-expr-addr-operator.rs b/tests/ui/consts/const-expr-addr-operator.rs new file mode 100644 index 000000000..37bf24c2f --- /dev/null +++ b/tests/ui/consts/const-expr-addr-operator.rs @@ -0,0 +1,11 @@ +// Encountered while testing #44614. +// build-pass (FIXME(62277): could be check-pass?) + +pub fn main() { + // Constant of generic type (int) + const X: &'static u32 = &22; + assert_eq!(0, match &22 { + X => 0, + _ => 1, + }); +} diff --git a/tests/ui/consts/const-expr-in-fixed-length-vec.rs b/tests/ui/consts/const-expr-in-fixed-length-vec.rs new file mode 100644 index 000000000..a9960b455 --- /dev/null +++ b/tests/ui/consts/const-expr-in-fixed-length-vec.rs @@ -0,0 +1,12 @@ +// run-pass +// Check that constant expressions can be used for declaring the +// type of a fixed length vector. + +// pretty-expanded FIXME #23616 + +pub fn main() { + + const FOO: usize = 2; + let _v: [isize; FOO*3]; + +} diff --git a/tests/ui/consts/const-expr-in-vec-repeat.rs b/tests/ui/consts/const-expr-in-vec-repeat.rs new file mode 100644 index 000000000..4eaef2505 --- /dev/null +++ b/tests/ui/consts/const-expr-in-vec-repeat.rs @@ -0,0 +1,11 @@ +// run-pass +// Check that constant expressions can be used in vec repeat syntax. + +// pretty-expanded FIXME #23616 + +pub fn main() { + + const FOO: usize = 2; + let _v = [0; FOO*3*2/2]; + +} diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs new file mode 100644 index 000000000..eccda49db --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs @@ -0,0 +1,23 @@ +#![feature(const_extern_fn)] + +extern "C" { + fn regular_in_block(); +} + +const extern "C" fn bar() { + unsafe { + regular_in_block(); + //~^ ERROR: cannot call non-const fn + } +} + +extern "C" fn regular() {} + +const extern "C" fn foo() { + unsafe { + regular(); + //~^ ERROR: cannot call non-const fn + } +} + +fn main() {} diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr new file mode 100644 index 000000000..5acf22e4b --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr @@ -0,0 +1,19 @@ +error[E0015]: cannot call non-const fn `regular_in_block` in constant functions + --> $DIR/const-extern-fn-call-extern-fn.rs:9:9 + | +LL | regular_in_block(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `regular` in constant functions + --> $DIR/const-extern-fn-call-extern-fn.rs:18:9 + | +LL | regular(); + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs new file mode 100644 index 000000000..c7078e46f --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -0,0 +1,11 @@ +#![feature(const_extern_fn)] + +const extern "C" fn unsize(x: &[u8; 3]) -> &[u8] { x } +const unsafe extern "C" fn closure() -> fn() { || {} } +const unsafe extern "C" fn use_float() { 1.0 + 1.0; } +//~^ ERROR floating point arithmetic +const extern "C" fn ptr_cast(val: *const u8) { val as usize; } +//~^ ERROR pointers cannot be cast to integers + + +fn main() {} diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr new file mode 100644 index 000000000..4bab466fb --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -0,0 +1,21 @@ +error[E0658]: floating point arithmetic is not allowed in constant functions + --> $DIR/const-extern-fn-min-const-fn.rs:5:42 + | +LL | const unsafe extern "C" fn use_float() { 1.0 + 1.0; } + | ^^^^^^^^^ + | + = note: see issue #57241 for more information + = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable + +error: pointers cannot be cast to integers during const eval + --> $DIR/const-extern-fn-min-const-fn.rs:7:48 + | +LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } + | ^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr new file mode 100644 index 000000000..34ec8aadb --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:12:5 + | +LL | foo(); + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:9:17 + | +LL | let a: [u8; foo()]; + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs new file mode 100644 index 000000000..afe645ae8 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs @@ -0,0 +1,14 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(const_extern_fn)] + +const unsafe extern "C" fn foo() -> usize { 5 } + +fn main() { + let a: [u8; foo()]; + //[mir]~^ call to unsafe function is unsafe and requires unsafe function or block + //[thir]~^^ call to unsafe function `foo` is unsafe and requires unsafe function or block + foo(); + //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe function or block +} diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr new file mode 100644 index 000000000..b313f0653 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:9:17 + | +LL | let a: [u8; foo()]; + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn.rs b/tests/ui/consts/const-extern-fn/const-extern-fn.rs new file mode 100644 index 000000000..2ce2eafd5 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/const-extern-fn.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(const_extern_fn)] + +const extern "C" fn foo1(val: u8) -> u8 { + val + 1 +} + +const extern "C" fn foo2(val: u8) -> u8 { + val + 1 +} + +const unsafe extern "C" fn bar1(val: bool) -> bool { + !val +} + +const unsafe extern "C" fn bar2(val: bool) -> bool { + !val +} + + +fn main() { + let a: [u8; foo1(25) as usize] = [0; 26]; + let b: [u8; foo2(25) as usize] = [0; 26]; + assert_eq!(a, b); + + let bar1_res = unsafe { bar1(false) }; + let bar2_res = unsafe { bar2(false) }; + assert!(bar1_res); + assert_eq!(bar1_res, bar2_res); + + let _foo1_cast: extern "C" fn(u8) -> u8 = foo1; + let _foo2_cast: extern "C" fn(u8) -> u8 = foo2; + let _bar1_cast: unsafe extern "C" fn(bool) -> bool = bar1; + let _bar2_cast: unsafe extern "C" fn(bool) -> bool = bar2; +} diff --git a/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs b/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs new file mode 100644 index 000000000..f7bed91b0 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs @@ -0,0 +1,13 @@ +// Check that `const extern fn` and `const unsafe extern fn` are feature-gated +// for certain ABIs. + +const extern fn foo1() {} +const extern "C" fn foo2() {} +const extern "Rust" fn foo3() {} +const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable +const unsafe extern fn bar1() {} +const unsafe extern "C" fn bar2() {} +const unsafe extern "Rust" fn bar3() {} +const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable + +fn main() {} diff --git a/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr b/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr new file mode 100644 index 000000000..f8c3107bd --- /dev/null +++ b/tests/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr @@ -0,0 +1,21 @@ +error[E0658]: `cdecl` as a `const fn` ABI is unstable + --> $DIR/feature-gate-const_extern_fn.rs:7:14 + | +LL | const extern "cdecl" fn foo4() {} + | ^^^^^^^ + | + = note: see issue #64926 for more information + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error[E0658]: `cdecl` as a `const fn` ABI is unstable + --> $DIR/feature-gate-const_extern_fn.rs:11:21 + | +LL | const unsafe extern "cdecl" fn bar4() {} + | ^^^^^^^ + | + = note: see issue #64926 for more information + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs new file mode 100644 index 000000000..7ced24808 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs @@ -0,0 +1,7 @@ +fn main() {} + +#[cfg(FALSE)] +fn container() { + const unsafe WhereIsFerris Now() {} + //~^ ERROR expected one of `extern` or `fn` +} diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr new file mode 100644 index 000000000..5ec9e2a91 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.stderr @@ -0,0 +1,8 @@ +error: expected one of `extern` or `fn`, found `WhereIsFerris` + --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs:5:18 + | +LL | const unsafe WhereIsFerris Now() {} + | ^^^^^^^^^^^^^ expected one of `extern` or `fn` + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs new file mode 100644 index 000000000..6f575d055 --- /dev/null +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs @@ -0,0 +1,7 @@ +fn main() {} + +#[cfg(FALSE)] +fn container() { + const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } + //~^ ERROR expected `fn` +} diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr new file mode 100644 index 000000000..ec415ec9d --- /dev/null +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.stderr @@ -0,0 +1,8 @@ +error: expected `fn`, found `PUT_ANYTHING_YOU_WANT_HERE` + --> $DIR/issue-68062-const-extern-fns-dont-need-fn-specifier.rs:5:25 + | +LL | const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `fn` + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-extern-function.rs b/tests/ui/consts/const-extern-function.rs new file mode 100644 index 000000000..01f487a7d --- /dev/null +++ b/tests/ui/consts/const-extern-function.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_upper_case_globals)] + +extern "C" fn foopy() {} + +static f: extern "C" fn() = foopy; +static s: S = S { f: foopy }; + +struct S { + f: extern "C" fn() +} + +pub fn main() { + assert!(foopy as extern "C" fn() == f); + assert!(f == s.f); +} diff --git a/tests/ui/consts/const-external-macro-const-err.rs b/tests/ui/consts/const-external-macro-const-err.rs new file mode 100644 index 000000000..5bd84330b --- /dev/null +++ b/tests/ui/consts/const-external-macro-const-err.rs @@ -0,0 +1,13 @@ +// edition:2018 +// aux-build:external_macro.rs + +// Ensure that CONST_ERR lint errors +// are not silenced in external macros. +// https://github.com/rust-lang/rust/issues/65300 + +extern crate external_macro; +use external_macro::static_assert; + +fn main() { + static_assert!(2 + 2 == 5); //~ ERROR constant +} diff --git a/tests/ui/consts/const-external-macro-const-err.stderr b/tests/ui/consts/const-external-macro-const-err.stderr new file mode 100644 index 000000000..81f6c09ff --- /dev/null +++ b/tests/ui/consts/const-external-macro-const-err.stderr @@ -0,0 +1,11 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-external-macro-const-err.rs:12:5 + | +LL | static_assert!(2 + 2 == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: this error originates in the macro `static_assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-fields-and-indexing.rs b/tests/ui/consts/const-fields-and-indexing.rs new file mode 100644 index 000000000..bb13bebf4 --- /dev/null +++ b/tests/ui/consts/const-fields-and-indexing.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +const x : [isize; 4] = [1,2,3,4]; +static p : isize = x[2]; +const y : &'static [isize] = &[1,2,3,4]; +static q : isize = y[2]; + +struct S {a: isize, b: isize} + +const s : S = S {a: 10, b: 20}; +static t : isize = s.b; + +struct K {a: isize, b: isize, c: D} +struct D { d: isize, e: isize } + +const k : K = K {a: 10, b: 20, c: D {d: 30, e: 40}}; +static m : isize = k.c.e; + +pub fn main() { + println!("{}", p); + println!("{}", q); + println!("{}", t); + assert_eq!(p, 3); + assert_eq!(q, 3); + assert_eq!(t, 20); +} diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/consts/const-float-bits-conv.rs new file mode 100644 index 000000000..fd5e42ef1 --- /dev/null +++ b/tests/ui/consts/const-float-bits-conv.rs @@ -0,0 +1,63 @@ +// compile-flags: -Zmir-opt-level=0 +// run-pass + +#![feature(const_float_bits_conv)] +#![feature(const_float_classify)] +#![allow(unused_macro_rules)] + +// Don't promote +const fn nop(x: T) -> T { x } + +macro_rules! const_assert { + ($a:expr) => { + { + const _: () = assert!($a); + assert!(nop($a)); + } + }; + ($a:expr, $b:expr) => { + { + const _: () = assert!($a == $b); + assert_eq!(nop($a), nop($b)); + } + }; +} + +fn f32() { + const_assert!((1f32).to_bits(), 0x3f800000); + const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); + const_assert!((12.5f32).to_bits(), 0x41480000); + const_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000); + const_assert!((1337f32).to_bits(), 0x44a72000); + const_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000); + const_assert!((-14.25f32).to_bits(), 0xc1640000); + const_assert!(f32::from_bits(0x3f800000), 1.0); + const_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0); + const_assert!(f32::from_bits(0x41480000), 12.5); + const_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5); + const_assert!(f32::from_bits(0x44a72000), 1337.0); + const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); + const_assert!(f32::from_bits(0xc1640000), -14.25); +} + +fn f64() { + const_assert!((1f64).to_bits(), 0x3ff0000000000000); + const_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000); + const_assert!((12.5f64).to_bits(), 0x4029000000000000); + const_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000); + const_assert!((1337f64).to_bits(), 0x4094e40000000000); + const_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000); + const_assert!((-14.25f64).to_bits(), 0xc02c800000000000); + const_assert!(f64::from_bits(0x3ff0000000000000), 1.0); + const_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0); + const_assert!(f64::from_bits(0x4029000000000000), 12.5); + const_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5); + const_assert!(f64::from_bits(0x4094e40000000000), 1337.0); + const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); + const_assert!(f64::from_bits(0xc02c800000000000), -14.25); +} + +fn main() { + f32(); + f64(); +} diff --git a/tests/ui/consts/const-float-bits-reject-conv.rs b/tests/ui/consts/const-float-bits-reject-conv.rs new file mode 100644 index 000000000..c77e99abb --- /dev/null +++ b/tests/ui/consts/const-float-bits-reject-conv.rs @@ -0,0 +1,68 @@ +// compile-flags: -Zmir-opt-level=0 +// error-pattern: cannot use f32::to_bits on a NaN +#![feature(const_float_bits_conv)] +#![feature(const_float_classify)] + +// Don't promote +const fn nop(x: T) -> T { x } + +macro_rules! const_assert { + ($a:expr) => { + { + const _: () = assert!($a); + assert!(nop($a)); + } + }; + ($a:expr, $b:expr) => { + { + const _: () = assert!($a == $b); + assert_eq!(nop($a), nop($b)); + } + }; +} + +fn f32() { + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // ...actually, let's just check that these break. :D + const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; + //~^ inside + const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555; + //~^ inside + + // The rest of the code is dead because the constants already fail to evaluate. + + const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); + const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); + + // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern. + // In practice, this seems to only cause a problem on x86, since the most widely used calling + // convention mandates that floating point values are returned on the x87 FPU stack. See #73328. + // However, during CTFE we still preserve bit patterns (though that is not a guarantee). + const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); + const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); +} + +fn f64() { + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + // ...actually, let's just check that these break. :D + const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; + //~^ inside + const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + //~^ inside + + // The rest of the code is dead because the constants already fail to evaluate. + + const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); + const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); + + // See comment above. + const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); + const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); +} + +fn main() { + f32(); + f64(); +} diff --git a/tests/ui/consts/const-float-bits-reject-conv.stderr b/tests/ui/consts/const-float-bits-reject-conv.stderr new file mode 100644 index 000000000..7ad022520 --- /dev/null +++ b/tests/ui/consts/const-float-bits-reject-conv.stderr @@ -0,0 +1,115 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/num/f32.rs:LL:COL + | + = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL + | +note: inside `core::f32::::to_bits::ct_f32_to_u32` + --> $SRC_DIR/core/src/num/f32.rs:LL:COL +note: inside `core::f32::::to_bits` + --> $SRC_DIR/core/src/num/f32.rs:LL:COL +note: inside `f32::MASKED_NAN1` + --> $DIR/const-float-bits-reject-conv.rs:28:30 + | +LL | const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/num/f32.rs:LL:COL + | + = note: the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL + | +note: inside `core::f32::::to_bits::ct_f32_to_u32` + --> $SRC_DIR/core/src/num/f32.rs:LL:COL +note: inside `core::f32::::to_bits` + --> $SRC_DIR/core/src/num/f32.rs:LL:COL +note: inside `f32::MASKED_NAN2` + --> $DIR/const-float-bits-reject-conv.rs:30:30 + | +LL | const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555; + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:35:34 + | +LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:36:34 + | +LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:42:34 + | +LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:43:34 + | +LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); + | ^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/num/f64.rs:LL:COL + | + = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL + | +note: inside `core::f64::::to_bits::ct_f64_to_u64` + --> $SRC_DIR/core/src/num/f64.rs:LL:COL +note: inside `core::f64::::to_bits` + --> $SRC_DIR/core/src/num/f64.rs:LL:COL +note: inside `f64::MASKED_NAN1` + --> $DIR/const-float-bits-reject-conv.rs:50:30 + | +LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/num/f64.rs:LL:COL + | + = note: the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL + | +note: inside `core::f64::::to_bits::ct_f64_to_u64` + --> $SRC_DIR/core/src/num/f64.rs:LL:COL +note: inside `core::f64::::to_bits` + --> $SRC_DIR/core/src/num/f64.rs:LL:COL +note: inside `f64::MASKED_NAN2` + --> $DIR/const-float-bits-reject-conv.rs:52:30 + | +LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + | ^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:57:34 + | +LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:58:34 + | +LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:61:34 + | +LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/const-float-bits-reject-conv.rs:62:34 + | +LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); + | ^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs new file mode 100644 index 000000000..74238d0dd --- /dev/null +++ b/tests/ui/consts/const-float-classify.rs @@ -0,0 +1,78 @@ +// compile-flags: -Zmir-opt-level=0 +// run-pass + +#![feature(const_float_bits_conv)] +#![feature(const_float_classify)] +#![feature(const_trait_impl)] + +// Don't promote +const fn nop(x: T) -> T { x } + +macro_rules! const_assert { + ($a:expr, $b:expr) => { + { + const _: () = assert!($a == $b); + assert_eq!(nop($a), nop($b)); + } + }; +} + +macro_rules! suite { + ( $( $tt:tt )* ) => { + fn f32() { + suite_inner!(f32 $($tt)*); + } + + fn f64() { + suite_inner!(f64 $($tt)*); + } + } + +} + +macro_rules! suite_inner { + ( + $ty:ident [$( $fn:ident ),*] + $val:expr => [$($out:ident),*] + + $( $tail:tt )* + ) => { + $( const_assert!($ty::$fn($val), $out); )* + suite_inner!($ty [$($fn),*] $($tail)*) + }; + + ( $ty:ident [$( $fn:ident ),*]) => {}; +} + +#[derive(Debug)] +struct NonDet; + +impl const PartialEq for bool { + fn eq(&self, _: &NonDet) -> bool { + true + } + fn ne(&self, _: &NonDet) -> bool { + false + } +} + +// The result of the `is_sign` methods are not checked for correctness, since LLVM does not +// guarantee anything about the signedness of NaNs. See +// https://github.com/rust-lang/rust/issues/55131. + +suite! { + [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] + -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] + 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] + 1.0 => [ false, false, true, true, true, false] + -1.0 => [ false, false, true, true, false, true] + 0.0 => [ false, false, true, false, true, false] + -0.0 => [ false, false, true, false, false, true] + 1.0 / 0.0 => [ false, true, false, false, true, false] + -1.0 / 0.0 => [ false, true, false, false, false, true] +} + +fn main() { + f32(); + f64(); +} diff --git a/tests/ui/consts/const-fn-const-eval.rs b/tests/ui/consts/const-fn-const-eval.rs new file mode 100644 index 000000000..d4da99081 --- /dev/null +++ b/tests/ui/consts/const-fn-const-eval.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] + +const fn add(x: usize, y: usize) -> usize { + x + y +} + +const ARR: [i32; add(1, 2)] = [5, 6, 7]; + +pub fn main() {} diff --git a/tests/ui/consts/const-fn-destructuring-arg.rs b/tests/ui/consts/const-fn-destructuring-arg.rs new file mode 100644 index 000000000..ea5c9ddc7 --- /dev/null +++ b/tests/ui/consts/const-fn-destructuring-arg.rs @@ -0,0 +1,7 @@ +// check-pass + +const fn i((a, b): (u32, u32)) -> u32 { + a + b +} + +fn main() {} diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs new file mode 100644 index 000000000..50b7ce1f8 --- /dev/null +++ b/tests/ui/consts/const-fn-error.rs @@ -0,0 +1,18 @@ +const X : usize = 2; + +const fn f(x: usize) -> usize { + let mut sum = 0; + for i in 0..x { + //~^ ERROR cannot convert + //~| ERROR `for` is not allowed in a `const fn` + //~| ERROR mutable references are not allowed in constant functions + //~| ERROR cannot call non-const fn + sum += i; + } + sum +} + +#[allow(unused_variables)] +fn main() { + let a : [i32; f(X)]; +} diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr new file mode 100644 index 000000000..f735b3d53 --- /dev/null +++ b/tests/ui/consts/const-fn-error.stderr @@ -0,0 +1,48 @@ +error[E0658]: `for` is not allowed in a `const fn` + --> $DIR/const-fn-error.rs:5:5 + | +LL | / for i in 0..x { +LL | | +LL | | +LL | | +LL | | +LL | | sum += i; +LL | | } + | |_____^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error[E0015]: cannot convert `std::ops::Range` into an iterator in constant functions + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs new file mode 100644 index 000000000..a40290eca --- /dev/null +++ b/tests/ui/consts/const-fn-in-vec.rs @@ -0,0 +1,7 @@ +fn main() { + // should hint to create an inline `const` block + // or to create a new `const` item + let strings: [String; 5] = [String::new(); 5]; + //~^ ERROR the trait bound `String: Copy` is not satisfied + println!("{:?}", strings); +} diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr new file mode 100644 index 000000000..9eb7524b5 --- /dev/null +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:4:33 + | +LL | let strings: [String; 5] = [String::new(); 5]; + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` + = help: create an inline `const` block, see RFC #2920 for more information + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-fn-method.rs b/tests/ui/consts/const-fn-method.rs new file mode 100644 index 000000000..002646db9 --- /dev/null +++ b/tests/ui/consts/const-fn-method.rs @@ -0,0 +1,16 @@ +// run-pass + +struct Foo { value: u32 } + +impl Foo { + const fn new() -> Foo { + Foo { value: 22 } + } +} + +const FOO: Foo = Foo::new(); + +pub fn main() { + assert_eq!(FOO.value, 22); + let _: [&'static str; Foo::new().value as usize] = ["hey"; 22]; +} diff --git a/tests/ui/consts/const-fn-mismatch.rs b/tests/ui/consts/const-fn-mismatch.rs new file mode 100644 index 000000000..3107b8128 --- /dev/null +++ b/tests/ui/consts/const-fn-mismatch.rs @@ -0,0 +1,17 @@ +// Test that we can't declare a const fn in an impl -- right now it's +// just not allowed at all, though eventually it'd make sense to allow +// it if the trait fn is const (but right now no trait fns can be +// const). + +trait Foo { + fn f() -> u32; +} + +impl Foo for u32 { + const fn f() -> u32 { + //~^ ERROR functions in traits cannot be declared const + 22 + } +} + +fn main() {} diff --git a/tests/ui/consts/const-fn-mismatch.stderr b/tests/ui/consts/const-fn-mismatch.stderr new file mode 100644 index 000000000..a86a06b3e --- /dev/null +++ b/tests/ui/consts/const-fn-mismatch.stderr @@ -0,0 +1,9 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/const-fn-mismatch.rs:11:5 + | +LL | const fn f() -> u32 { + | ^^^^^ functions in traits cannot be const + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/consts/const-fn-nested.rs b/tests/ui/consts/const-fn-nested.rs new file mode 100644 index 000000000..ef5598bf9 --- /dev/null +++ b/tests/ui/consts/const-fn-nested.rs @@ -0,0 +1,12 @@ +// run-pass +// Test a call whose argument is the result of another call. + +const fn sub(x: u32, y: u32) -> u32 { + x - y +} + +const X: u32 = sub(sub(88, 44), 22); + +fn main() { + assert_eq!(X, 22); +} diff --git a/tests/ui/consts/const-fn-not-in-trait.rs b/tests/ui/consts/const-fn-not-in-trait.rs new file mode 100644 index 000000000..00bae3f3b --- /dev/null +++ b/tests/ui/consts/const-fn-not-in-trait.rs @@ -0,0 +1,13 @@ +// Test that const fn is illegal in a trait declaration, whether or +// not a default is provided, and even with the feature gate. + +trait Foo { + const fn f() -> u32; + //~^ ERROR functions in traits cannot be declared const + const fn g() -> u32 { + //~^ ERROR functions in traits cannot be declared const + 0 + } +} + +fn main() {} diff --git a/tests/ui/consts/const-fn-not-in-trait.stderr b/tests/ui/consts/const-fn-not-in-trait.stderr new file mode 100644 index 000000000..5d364eb88 --- /dev/null +++ b/tests/ui/consts/const-fn-not-in-trait.stderr @@ -0,0 +1,15 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/const-fn-not-in-trait.rs:5:5 + | +LL | const fn f() -> u32; + | ^^^^^ functions in traits cannot be const + +error[E0379]: functions in traits cannot be declared const + --> $DIR/const-fn-not-in-trait.rs:7:5 + | +LL | const fn g() -> u32 { + | ^^^^^ functions in traits cannot be const + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/consts/const-fn-not-safe-for-const.rs b/tests/ui/consts/const-fn-not-safe-for-const.rs new file mode 100644 index 000000000..b2fe73ae9 --- /dev/null +++ b/tests/ui/consts/const-fn-not-safe-for-const.rs @@ -0,0 +1,35 @@ +// Test that we can't call random fns in a const fn or do other bad things. + +use std::mem::transmute; + +fn random() -> u32 { + 0 +} + +const fn sub(x: &u32) -> usize { + unsafe { transmute(x) } +} + +const fn sub1() -> u32 { + random() //~ ERROR E0015 +} + +static Y: u32 = 0; + +const fn get_Y() -> u32 { + Y + //~^ ERROR E0013 +} + +const fn get_Y_addr() -> &'static u32 { + &Y + //~^ ERROR E0013 +} + +const fn get() -> u32 { + let x = 22; + let y = 44; + x + y +} + +fn main() {} diff --git a/tests/ui/consts/const-fn-not-safe-for-const.stderr b/tests/ui/consts/const-fn-not-safe-for-const.stderr new file mode 100644 index 000000000..4c7effc0d --- /dev/null +++ b/tests/ui/consts/const-fn-not-safe-for-const.stderr @@ -0,0 +1,28 @@ +error[E0015]: cannot call non-const fn `random` in constant functions + --> $DIR/const-fn-not-safe-for-const.rs:14:5 + | +LL | random() + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0013]: constant functions cannot refer to statics + --> $DIR/const-fn-not-safe-for-const.rs:20:5 + | +LL | Y + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constant functions cannot refer to statics + --> $DIR/const-fn-not-safe-for-const.rs:25:6 + | +LL | &Y + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0013, E0015. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/consts/const-fn-ptr.rs b/tests/ui/consts/const-fn-ptr.rs new file mode 100644 index 000000000..b1befdf06 --- /dev/null +++ b/tests/ui/consts/const-fn-ptr.rs @@ -0,0 +1,16 @@ +const fn make_fn_ptr() -> fn() { + || {} +} + +static STAT: () = make_fn_ptr()(); +//~^ ERROR function pointer + +const CONST: () = make_fn_ptr()(); +//~^ ERROR function pointer + +const fn call_ptr() { + make_fn_ptr()(); + //~^ ERROR function pointer +} + +fn main() {} diff --git a/tests/ui/consts/const-fn-ptr.stderr b/tests/ui/consts/const-fn-ptr.stderr new file mode 100644 index 000000000..84b02a25e --- /dev/null +++ b/tests/ui/consts/const-fn-ptr.stderr @@ -0,0 +1,20 @@ +error: function pointer calls are not allowed in statics + --> $DIR/const-fn-ptr.rs:5:19 + | +LL | static STAT: () = make_fn_ptr()(); + | ^^^^^^^^^^^^^^^ + +error: function pointer calls are not allowed in constants + --> $DIR/const-fn-ptr.rs:8:19 + | +LL | const CONST: () = make_fn_ptr()(); + | ^^^^^^^^^^^^^^^ + +error: function pointer calls are not allowed in constant functions + --> $DIR/const-fn-ptr.rs:12:5 + | +LL | make_fn_ptr()(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/consts/const-fn-stability-calls-3.rs b/tests/ui/consts/const-fn-stability-calls-3.rs new file mode 100644 index 000000000..b831dee58 --- /dev/null +++ b/tests/ui/consts/const-fn-stability-calls-3.rs @@ -0,0 +1,12 @@ +// Test use of const fn from another crate without a feature gate. + +// check-pass +// aux-build:const_fn_lib.rs + +extern crate const_fn_lib; + +use const_fn_lib::foo; + +fn main() { + let x = foo(); // use outside a constant is ok +} diff --git a/tests/ui/consts/const-fn-stability-calls.rs b/tests/ui/consts/const-fn-stability-calls.rs new file mode 100644 index 000000000..138679048 --- /dev/null +++ b/tests/ui/consts/const-fn-stability-calls.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test use of const fn from another crate without a feature gate. + +// aux-build:const_fn_lib.rs + +extern crate const_fn_lib; + +use const_fn_lib::foo; + +static FOO: usize = foo(); +const BAR: usize = foo(); + +macro_rules! constant { + ($n:ident: $t:ty = $v:expr) => { + const $n: $t = $v; + } +} + +constant! { + BAZ: usize = foo() +} + +fn main() { + let x: [usize; foo()] = [42; foo()]; +} diff --git a/tests/ui/consts/const-fn-type-name-any.rs b/tests/ui/consts/const-fn-type-name-any.rs new file mode 100644 index 000000000..448c4fc04 --- /dev/null +++ b/tests/ui/consts/const-fn-type-name-any.rs @@ -0,0 +1,28 @@ +// run-pass + +#![feature(const_type_name)] +#![allow(dead_code)] + +const fn type_name_wrapper(_: &T) -> &'static str { + std::any::type_name::() +} + +struct Struct { + a: TA, + b: TB, + c: TC, +} + +type StructInstantiation = Struct; + +const CONST_STRUCT: StructInstantiation = StructInstantiation { a: 12, b: 13.7, c: false }; + +const CONST_STRUCT_NAME: &'static str = type_name_wrapper(&CONST_STRUCT); + +fn main() { + let non_const_struct = StructInstantiation { a: 87, b: 65.99, c: true }; + + let non_const_struct_name = type_name_wrapper(&non_const_struct); + + assert_eq!(CONST_STRUCT_NAME, non_const_struct_name); +} diff --git a/tests/ui/consts/const-fn-type-name.rs b/tests/ui/consts/const-fn-type-name.rs new file mode 100644 index 000000000..fd4f60cb8 --- /dev/null +++ b/tests/ui/consts/const-fn-type-name.rs @@ -0,0 +1,37 @@ +// run-pass + +#![feature(core_intrinsics)] +#![feature(const_type_name)] +#![allow(dead_code)] + +const fn type_name_wrapper(_: &T) -> &'static str { + core::intrinsics::type_name::() +} + +struct Struct { + a: TA, + b: TB, + c: TC, +} + +type StructInstantiation = Struct; + +const CONST_STRUCT: StructInstantiation = StructInstantiation { + a: 12, + b: 13.7, + c: false, +}; + +const CONST_STRUCT_NAME: &'static str = type_name_wrapper(&CONST_STRUCT); + +fn main() { + let non_const_struct = StructInstantiation { + a: 87, + b: 65.99, + c: true, + }; + + let non_const_struct_name = type_name_wrapper(&non_const_struct); + + assert_eq!(CONST_STRUCT_NAME, non_const_struct_name); +} diff --git a/tests/ui/consts/const-fn-val.rs b/tests/ui/consts/const-fn-val.rs new file mode 100644 index 000000000..e5bf4757e --- /dev/null +++ b/tests/ui/consts/const-fn-val.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_upper_case_globals)] +#![allow(overflowing_literals)] + +fn foo() -> isize { + return 0xca7f000d; +} + +struct Bar where F: FnMut() -> isize { f: F } + +static mut b : Bar isize> = Bar { f: foo as fn() -> isize}; + +pub fn main() { + unsafe { assert_eq!((b.f)(), 0xca7f000d); } +} diff --git a/tests/ui/consts/const-fn-zst-args.rs b/tests/ui/consts/const-fn-zst-args.rs new file mode 100644 index 000000000..82c27b375 --- /dev/null +++ b/tests/ui/consts/const-fn-zst-args.rs @@ -0,0 +1,14 @@ +// build-pass + +// Check that the evaluation of const-functions with +// zero-sized types as arguments compiles successfully + +struct Zst {} + +const fn foo(val: Zst) -> Zst { val } + +const FOO: Zst = foo(Zst {}); + +fn main() { + const _: Zst = FOO; +} diff --git a/tests/ui/consts/const-fn.rs b/tests/ui/consts/const-fn.rs new file mode 100644 index 000000000..59680e6e4 --- /dev/null +++ b/tests/ui/consts/const-fn.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(stable_features)] + +// A very basic test of const fn functionality. + +#![feature(const_indexing)] + +const fn add(x: u32, y: u32) -> u32 { + x + y +} + +const fn sub(x: u32, y: u32) -> u32 { + x - y +} + +const unsafe fn div(x: u32, y: u32) -> u32 { + x / y +} + +const fn generic(t: T) -> T { + t +} + +const fn generic_arr(t: [T; 1]) -> T { + t[0] +} + +const SUM: u32 = add(44, 22); +const DIFF: u32 = sub(44, 22); +const DIV: u32 = unsafe{div(44, 22)}; + +fn main() { + assert_eq!(SUM, 66); + assert!(SUM != 88); + + assert_eq!(DIFF, 22); + assert_eq!(DIV, 2); + + let _: [&'static str; sub(100, 99) as usize] = ["hi"]; + let _: [&'static str; generic(1)] = ["hi"]; + let _: [&'static str; generic_arr([1])] = ["hi"]; +} diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs new file mode 100644 index 000000000..bec7b8089 --- /dev/null +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -0,0 +1,8 @@ +// gate-test-const_for + +const _: () = { + for _ in 0..5 {} + //~^ error: `for` is not allowed in a `const` +}; + +fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr new file mode 100644 index 000000000..2ea377e09 --- /dev/null +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: `for` is not allowed in a `const` + --> $DIR/const-for-feature-gate.rs:4:5 + | +LL | for _ in 0..5 {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs new file mode 100644 index 000000000..8db248535 --- /dev/null +++ b/tests/ui/consts/const-for.rs @@ -0,0 +1,10 @@ +#![feature(const_for)] +#![feature(const_mut_refs)] + +const _: () = { + for _ in 0..5 {} + //~^ error: cannot call + //~| error: cannot convert +}; + +fn main() {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr new file mode 100644 index 000000000..3fb9787c0 --- /dev/null +++ b/tests/ui/consts/const-for.stderr @@ -0,0 +1,23 @@ +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/const-for.rs:5:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/const-for.rs:5:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-index-feature-gate.rs b/tests/ui/consts/const-index-feature-gate.rs new file mode 100644 index 000000000..3537a1790 --- /dev/null +++ b/tests/ui/consts/const-index-feature-gate.rs @@ -0,0 +1,7 @@ +// run-pass +#![allow(dead_code)] +const ARR: [usize; 1] = [2]; +const ARR2: [i32; ARR[0]] = [5, 6]; + +fn main() { +} diff --git a/tests/ui/consts/const-int-arithmetic-overflow.rs b/tests/ui/consts/const-int-arithmetic-overflow.rs new file mode 100644 index 000000000..6446e9451 --- /dev/null +++ b/tests/ui/consts/const-int-arithmetic-overflow.rs @@ -0,0 +1,25 @@ +// run-pass +// compile-flags: -O + +// Make sure arithmetic unary/binary ops actually return the right result, even when overflowing. +// We have to put them in `const fn` and turn on optimizations to avoid overflow checks. + +const fn add(x: i8, y: i8) -> i8 { x+y } +const fn sub(x: i8, y: i8) -> i8 { x-y } +const fn mul(x: i8, y: i8) -> i8 { x*y } +// div and rem are always checked, so we cannot test their result in case of overflow. +const fn neg(x: i8) -> i8 { -x } + +fn main() { + const ADD_OFLOW: i8 = add(100, 100); + assert_eq!(ADD_OFLOW, -56); + + const SUB_OFLOW: i8 = sub(100, -100); + assert_eq!(SUB_OFLOW, -56); + + const MUL_OFLOW: i8 = mul(-100, -2); + assert_eq!(MUL_OFLOW, -56); + + const NEG_OFLOW: i8 = neg(-128); + assert_eq!(NEG_OFLOW, -128); +} diff --git a/tests/ui/consts/const-int-arithmetic.rs b/tests/ui/consts/const-int-arithmetic.rs new file mode 100644 index 000000000..b9096648f --- /dev/null +++ b/tests/ui/consts/const-int-arithmetic.rs @@ -0,0 +1,138 @@ +// run-pass + +macro_rules! suite { + ($( + $fn:ident -> $ty:ty { $( $label:ident : $expr:expr, $result:expr; )* } + )*) => { $( + fn $fn() { + $( + const $label: $ty = $expr; + assert_eq!($label, $result); + )* + } + )* } +} + +suite!( + checked -> Option { + // `const_checked_int_methods` + C1: 5i8.checked_add(2), Some(7); + C2: 127i8.checked_add(2), None; + + C3: 5i8.checked_sub(2), Some(3); + C4: (-127i8).checked_sub(2), None; + + C5: 1i8.checked_mul(3), Some(3); + C6: 5i8.checked_mul(122), None; + C7: (-127i8).checked_mul(-99), None; + + C8: (i8::MIN + 1).checked_div(-1), Some(127); + C9: i8::MIN.checked_div(-1), None; + C10: 1i8.checked_div(0), None; + + C11: 5i8.checked_rem(2), Some(1); + C12: 5i8.checked_rem(0), None; + C13: i8::MIN.checked_rem(-1), None; + + C14: 5i8.checked_neg(), Some(-5); + C15: i8::MIN.checked_neg(), None; + + C16: 0x1i8.checked_shl(4), Some(0x10); + C17: 0x1i8.checked_shl(129), None; + + C18: 0x10i8.checked_shr(4), Some(0x1); + C19: 0x10i8.checked_shr(128), None; + + + C20: (-5i8).checked_abs(), Some(5); + C21: i8::MIN.checked_abs(), None; + + // `const_euclidean_int_methods` + C22: (i8::MIN + 1).checked_div_euclid(-1), Some(127); + C23: i8::MIN.checked_div_euclid(-1), None; + C24: (1i8).checked_div_euclid(0), None; + + C25: 5i8.checked_rem_euclid(2), Some(1); + C26: 5i8.checked_rem_euclid(0), None; + C27: i8::MIN.checked_rem_euclid(-1), None; + } + checked_i128 -> Option { + CHK_ADD_I128: i128::MAX.checked_add(1), None; + CHK_MUL_I128: i128::MIN.checked_mul(-1), None; + } + + saturating_and_wrapping -> i8 { + // `const_saturating_int_methods` + C28: 100i8.saturating_add(1), 101; + C29: i8::MAX.saturating_add(100), i8::MAX; + C30: i8::MIN.saturating_add(-1), i8::MIN; + + C31: 100i8.saturating_sub(127), -27; + C32: i8::MIN.saturating_sub(100), i8::MIN; + C33: i8::MAX.saturating_sub(-1), i8::MAX; + + C34: 10i8.saturating_mul(12), 120; + C35: i8::MAX.saturating_mul(10), i8::MAX; + C36: i8::MIN.saturating_mul(10), i8::MIN; + + C37: 100i8.saturating_neg(), -100; + C38: (-100i8).saturating_neg(), 100; + C39: i8::MIN.saturating_neg(), i8::MAX; + C40: i8::MAX.saturating_neg(), i8::MIN + 1; + + C57: 100i8.saturating_abs(), 100; + C58: (-100i8).saturating_abs(), 100; + C59: i8::MIN.saturating_abs(), i8::MAX; + C60: (i8::MIN + 1).saturating_abs(), i8::MAX; + + // `const_wrapping_int_methods` + C41: 100i8.wrapping_div(10), 10; + C42: (-128i8).wrapping_div(-1), -128; + + C43: 100i8.wrapping_rem(10), 0; + C44: (-128i8).wrapping_rem(-1), 0; + + // `const_euclidean_int_methods` + C45: 100i8.wrapping_div_euclid(10), 10; + C46: (-128i8).wrapping_div_euclid(-1), -128; + + C47: 100i8.wrapping_rem_euclid(10), 0; + C48: (-128i8).wrapping_rem_euclid(-1), 0; + } + saturating_and_wrapping_i128 -> i128 { + SAT_ADD_I128: i128::MAX.saturating_add(1), i128::MAX; + SAT_MUL_I128: i128::MAX.saturating_mul(2), i128::MAX; + + WRP_ADD_I128: i128::MAX.wrapping_add(1), i128::MIN; + WRP_MUL_I128: i128::MAX.wrapping_mul(3), i128::MAX-2; + } + + overflowing -> (i8, bool) { + // `const_overflowing_int_methods` + C49: 5i8.overflowing_div(2), (2, false); + C50: i8::MIN.overflowing_div(-1), (i8::MIN, true); + + C51: 5i8.overflowing_rem(2), (1, false); + C52: i8::MIN.overflowing_rem(-1), (0, true); + + // `const_euclidean_int_methods` + C53: 5i8.overflowing_div_euclid(2), (2, false); + C54: i8::MIN.overflowing_div_euclid(-1), (i8::MIN, true); + + C55: 5i8.overflowing_rem_euclid(2), (1, false); + C56: i8::MIN.overflowing_rem_euclid(-1), (0, true); + } + overflowing_i128 -> (i128, bool) { + OFL_ADD_I128: i128::MAX.overflowing_add(1), (i128::MIN, true); + OFL_MUL_I128: i128::MAX.overflowing_mul(3), (i128::MAX-2, true); + } +); + +fn main() { + checked(); + checked_i128(); + saturating_and_wrapping(); + saturating_and_wrapping_i128(); + overflowing(); + overflowing_i128(); +} diff --git a/tests/ui/consts/const-int-conversion-rpass.rs b/tests/ui/consts/const-int-conversion-rpass.rs new file mode 100644 index 000000000..4aaeeaa38 --- /dev/null +++ b/tests/ui/consts/const-int-conversion-rpass.rs @@ -0,0 +1,19 @@ +// run-pass + +const REVERSE: u32 = 0x12345678_u32.reverse_bits(); +const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]); +const FROM_LE_BYTES: i32 = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]); +const FROM_NE_BYTES: i32 = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])); +const TO_BE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_be_bytes(); +const TO_LE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_le_bytes(); +const TO_NE_BYTES: [u8; 4] = i32::MIN.to_be().to_ne_bytes(); + +fn main() { + assert_eq!(REVERSE, 0x1e6a2c48); + assert_eq!(FROM_BE_BYTES, 0x12_34_56_78); + assert_eq!(FROM_LE_BYTES, 0x78_56_34_12); + assert_eq!(FROM_NE_BYTES, i32::MIN); + assert_eq!(TO_BE_BYTES, [0x12, 0x34, 0x56, 0x78]); + assert_eq!(TO_LE_BYTES, [0x78, 0x56, 0x34, 0x12]); + assert_eq!(TO_NE_BYTES, [0x80, 0, 0, 0]); +} diff --git a/tests/ui/consts/const-int-conversion.rs b/tests/ui/consts/const-int-conversion.rs new file mode 100644 index 000000000..5a05a2b35 --- /dev/null +++ b/tests/ui/consts/const-int-conversion.rs @@ -0,0 +1,16 @@ +fn main() { + let x: &'static i32 = &(5_i32.reverse_bits()); + //~^ ERROR temporary value dropped while borrowed + let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78])); + //~^ ERROR temporary value dropped while borrowed + let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78])); + //~^ ERROR temporary value dropped while borrowed + let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]))); + //~^ ERROR temporary value dropped while borrowed + let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes()); + //~^ ERROR temporary value dropped while borrowed + let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes()); + //~^ ERROR temporary value dropped while borrowed + let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes()); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-int-conversion.stderr b/tests/ui/consts/const-int-conversion.stderr new file mode 100644 index 000000000..5dd757e3f --- /dev/null +++ b/tests/ui/consts/const-int-conversion.stderr @@ -0,0 +1,80 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:2:28 + | +LL | let x: &'static i32 = &(5_i32.reverse_bits()); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:4:28 + | +LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78])); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:6:28 + | +LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78])); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:8:28 + | +LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]))); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:10:29 + | +LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:12:29 + | +LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-conversion.rs:14:29 + | +LL | let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-int-overflowing-rpass.rs b/tests/ui/consts/const-int-overflowing-rpass.rs new file mode 100644 index 000000000..75e77fdf1 --- /dev/null +++ b/tests/ui/consts/const-int-overflowing-rpass.rs @@ -0,0 +1,47 @@ +// run-pass + +const ADD_A: (u32, bool) = 5u32.overflowing_add(2); +const ADD_B: (u32, bool) = u32::MAX.overflowing_add(1); + +const SUB_A: (u32, bool) = 5u32.overflowing_sub(2); +const SUB_B: (u32, bool) = 0u32.overflowing_sub(1); + +const MUL_A: (u32, bool) = 5u32.overflowing_mul(2); +const MUL_B: (u32, bool) = 1_000_000_000u32.overflowing_mul(10); + +const SHL_A: (u32, bool) = 0x1u32.overflowing_shl(4); +const SHL_B: (u32, bool) = 0x1u32.overflowing_shl(132); + +const SHR_A: (u32, bool) = 0x10u32.overflowing_shr(4); +const SHR_B: (u32, bool) = 0x10u32.overflowing_shr(132); + +const NEG_A: (u32, bool) = 0u32.overflowing_neg(); +const NEG_B: (u32, bool) = u32::MAX.overflowing_neg(); + +const ABS_POS: (i32, bool) = 10i32.overflowing_abs(); +const ABS_NEG: (i32, bool) = (-10i32).overflowing_abs(); +const ABS_MIN: (i32, bool) = i32::MIN.overflowing_abs(); + +fn main() { + assert_eq!(ADD_A, (7, false)); + assert_eq!(ADD_B, (0, true)); + + assert_eq!(SUB_A, (3, false)); + assert_eq!(SUB_B, (u32::MAX, true)); + + assert_eq!(MUL_A, (10, false)); + assert_eq!(MUL_B, (1410065408, true)); + + assert_eq!(SHL_A, (0x10, false)); + assert_eq!(SHL_B, (0x10, true)); + + assert_eq!(SHR_A, (0x1, false)); + assert_eq!(SHR_B, (0x1, true)); + + assert_eq!(NEG_A, (0, false)); + assert_eq!(NEG_B, (1, true)); + + assert_eq!(ABS_POS, (10, false)); + assert_eq!(ABS_NEG, (10, false)); + assert_eq!(ABS_MIN, (i32::MIN, true)); +} diff --git a/tests/ui/consts/const-int-overflowing.rs b/tests/ui/consts/const-int-overflowing.rs new file mode 100644 index 000000000..cd74c9990 --- /dev/null +++ b/tests/ui/consts/const-int-overflowing.rs @@ -0,0 +1,8 @@ +fn main() { + let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); + //~^ ERROR temporary value dropped while borrowed + let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); + //~^ ERROR temporary value dropped while borrowed + let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-int-overflowing.stderr b/tests/ui/consts/const-int-overflowing.stderr new file mode 100644 index 000000000..7d3689e6e --- /dev/null +++ b/tests/ui/consts/const-int-overflowing.stderr @@ -0,0 +1,36 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-overflowing.rs:2:36 + | +LL | let x: &'static (i32, bool) = &(5_i32.overflowing_add(3)); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-overflowing.rs:4:36 + | +LL | let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3)); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-overflowing.rs:6:36 + | +LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3)); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-int-pow-rpass.rs b/tests/ui/consts/const-int-pow-rpass.rs new file mode 100644 index 000000000..30bcb78bc --- /dev/null +++ b/tests/ui/consts/const-int-pow-rpass.rs @@ -0,0 +1,47 @@ +// run-pass + +#![feature(wrapping_next_power_of_two)] + +const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); +const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two(); +const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two(); + +const POW: u8 = 3u8.pow(5); + +const CHECKED_POW_OK: Option = 3u8.checked_pow(5); +const CHECKED_POW_OVERFLOW: Option = 3u8.checked_pow(6); + +const WRAPPING_POW: u8 = 3u8.wrapping_pow(6); +const OVERFLOWING_POW: (u8, bool) = 3u8.overflowing_pow(6); +const SATURATING_POW: u8 = 3u8.saturating_pow(6); + +const NEXT_POWER_OF_TWO: u32 = 3u32.next_power_of_two(); + +const CHECKED_NEXT_POWER_OF_TWO_OK: Option = 3u32.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_OVERFLOW: Option = + u32::MAX.checked_next_power_of_two(); + +const WRAPPING_NEXT_POWER_OF_TWO: u32 = + u32::MAX.wrapping_next_power_of_two(); + +fn main() { + assert!(!IS_POWER_OF_TWO_A); + assert!(IS_POWER_OF_TWO_B); + assert!(!IS_POWER_OF_TWO_C); + + assert_eq!(POW, 243); + + assert_eq!(CHECKED_POW_OK, Some(243)); + assert_eq!(CHECKED_POW_OVERFLOW, None); + + assert_eq!(WRAPPING_POW, 217); + assert_eq!(OVERFLOWING_POW, (217, true)); + assert_eq!(SATURATING_POW, u8::MAX); + + assert_eq!(NEXT_POWER_OF_TWO, 4); + + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OK, Some(4)); + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OVERFLOW, None); + + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO, 0); +} diff --git a/tests/ui/consts/const-int-rotate-rpass.rs b/tests/ui/consts/const-int-rotate-rpass.rs new file mode 100644 index 000000000..14f34f76c --- /dev/null +++ b/tests/ui/consts/const-int-rotate-rpass.rs @@ -0,0 +1,43 @@ +// run-pass + +const LEFT: u32 = 0x10000b3u32.rotate_left(8); +const RIGHT: u32 = 0xb301u32.rotate_right(8); + +// Rotating these should make no difference +// +// We test using 124 bits because to ensure that overlong bit shifts do +// not cause undefined behaviour. See #10183. +const LEFT_OVERFLOW: i16 = 0i16.rotate_left(124); +const RIGHT_OVERFLOW: i16 = 0i16.rotate_right(124); +const ONE_LEFT_OVERFLOW: u16 = 1u16.rotate_left(124); +const ONE_RIGHT_OVERFLOW: u16 = 1u16.rotate_right(124); + +const NON_ZERO_LEFT_OVERFLOW: u16 = 0b10u16.rotate_left(124); +const NON_ZERO_RIGHT_OVERFLOW: u16 = 0b10u16.rotate_right(124); + +// Rotating by 0 should have no effect +const ZERO_ROTATE_LEFT: i8 = 0b0010_0001i8.rotate_left(0); +const ZERO_ROTATE_RIGHT: i8 = 0b0111_1001i8.rotate_right(0); + +// Rotating by a multiple of word size should also have no effect +const MULTIPLE_ROTATE_LEFT: i32 = 0b0010_0001i32.rotate_left(128); +const MULTIPLE_ROTATE_RIGHT: i32 = 0b0010_0001i32.rotate_right(128); + +fn main() { + assert_eq!(LEFT, 0xb301); + assert_eq!(RIGHT, 0x0100_00b3); + + assert_eq!(LEFT_OVERFLOW, 0); + assert_eq!(RIGHT_OVERFLOW, 0); + assert_eq!(ONE_LEFT_OVERFLOW, 0b0001_0000_0000_0000); + assert_eq!(ONE_RIGHT_OVERFLOW, 0b0001_0000); + + assert_eq!(NON_ZERO_LEFT_OVERFLOW, 0b0010_0000_0000_0000); + assert_eq!(NON_ZERO_RIGHT_OVERFLOW, 0b0000_0000_0010_0000); + + assert_eq!(ZERO_ROTATE_LEFT, 0b0010_0001); + assert_eq!(ZERO_ROTATE_RIGHT, 0b0111_1001); + + assert_eq!(MULTIPLE_ROTATE_LEFT, 0b0010_0001); + assert_eq!(MULTIPLE_ROTATE_RIGHT, 0b0010_0001); +} diff --git a/tests/ui/consts/const-int-rotate.rs b/tests/ui/consts/const-int-rotate.rs new file mode 100644 index 000000000..3aacf854d --- /dev/null +++ b/tests/ui/consts/const-int-rotate.rs @@ -0,0 +1,6 @@ +fn main() { + let x: &'static i32 = &(5_i32.rotate_left(3)); + //~^ ERROR temporary value dropped while borrowed + let y: &'static i32 = &(5_i32.rotate_right(3)); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-int-rotate.stderr b/tests/ui/consts/const-int-rotate.stderr new file mode 100644 index 000000000..039da1c31 --- /dev/null +++ b/tests/ui/consts/const-int-rotate.stderr @@ -0,0 +1,25 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-rotate.rs:2:28 + | +LL | let x: &'static i32 = &(5_i32.rotate_left(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-rotate.rs:4:28 + | +LL | let y: &'static i32 = &(5_i32.rotate_right(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-int-saturating-arith.rs b/tests/ui/consts/const-int-saturating-arith.rs new file mode 100644 index 000000000..7edbdd4ce --- /dev/null +++ b/tests/ui/consts/const-int-saturating-arith.rs @@ -0,0 +1,33 @@ +// run-pass + +const INT_U32_NO: u32 = (42 as u32).saturating_add(2); +const INT_U32: u32 = u32::MAX.saturating_add(1); +const INT_U128: u128 = u128::MAX.saturating_add(1); +const INT_I128: i128 = i128::MAX.saturating_add(1); +const INT_I128_NEG: i128 = i128::MIN.saturating_add(-1); + +const INT_U32_NO_SUB: u32 = (42 as u32).saturating_sub(2); +const INT_U32_SUB: u32 = (1 as u32).saturating_sub(2); +const INT_I32_NO_SUB: i32 = (-42 as i32).saturating_sub(2); +const INT_I32_NEG_SUB: i32 = i32::MIN.saturating_sub(1); +const INT_I32_POS_SUB: i32 = i32::MAX.saturating_sub(-1); +const INT_U128_SUB: u128 = (0 as u128).saturating_sub(1); +const INT_I128_NEG_SUB: i128 = i128::MIN.saturating_sub(1); +const INT_I128_POS_SUB: i128 = i128::MAX.saturating_sub(-1); + +fn main() { + assert_eq!(INT_U32_NO, 44); + assert_eq!(INT_U32, u32::MAX); + assert_eq!(INT_U128, u128::MAX); + assert_eq!(INT_I128, i128::MAX); + assert_eq!(INT_I128_NEG, i128::MIN); + + assert_eq!(INT_U32_NO_SUB, 40); + assert_eq!(INT_U32_SUB, 0); + assert_eq!(INT_I32_NO_SUB, -44); + assert_eq!(INT_I32_NEG_SUB, i32::MIN); + assert_eq!(INT_I32_POS_SUB, i32::MAX); + assert_eq!(INT_U128_SUB, 0); + assert_eq!(INT_I128_NEG_SUB, i128::MIN); + assert_eq!(INT_I128_POS_SUB, i128::MAX); +} diff --git a/tests/ui/consts/const-int-sign-rpass.rs b/tests/ui/consts/const-int-sign-rpass.rs new file mode 100644 index 000000000..63c191d42 --- /dev/null +++ b/tests/ui/consts/const-int-sign-rpass.rs @@ -0,0 +1,27 @@ +// run-pass + +const NEGATIVE_A: bool = (-10i32).is_negative(); +const NEGATIVE_B: bool = 10i32.is_negative(); +const POSITIVE_A: bool = (-10i32).is_positive(); +const POSITIVE_B: bool = 10i32.is_positive(); + +const SIGNUM_POS: i32 = 10i32.signum(); +const SIGNUM_NIL: i32 = 0i32.signum(); +const SIGNUM_NEG: i32 = (-42i32).signum(); + +const ABS_A: i32 = 10i32.abs(); +const ABS_B: i32 = (-10i32).abs(); + +fn main() { + assert!(NEGATIVE_A); + assert!(!NEGATIVE_B); + assert!(!POSITIVE_A); + assert!(POSITIVE_B); + + assert_eq!(SIGNUM_POS, 1); + assert_eq!(SIGNUM_NIL, 0); + assert_eq!(SIGNUM_NEG, -1); + + assert_eq!(ABS_A, 10); + assert_eq!(ABS_B, 10); +} diff --git a/tests/ui/consts/const-int-sign.rs b/tests/ui/consts/const-int-sign.rs new file mode 100644 index 000000000..c3111ddf5 --- /dev/null +++ b/tests/ui/consts/const-int-sign.rs @@ -0,0 +1,6 @@ +fn main() { + let x: &'static bool = &(5_i32.is_negative()); + //~^ ERROR temporary value dropped while borrowed + let y: &'static bool = &(5_i32.is_positive()); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-int-sign.stderr b/tests/ui/consts/const-int-sign.stderr new file mode 100644 index 000000000..fc23d9d2b --- /dev/null +++ b/tests/ui/consts/const-int-sign.stderr @@ -0,0 +1,25 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-sign.rs:2:29 + | +LL | let x: &'static bool = &(5_i32.is_negative()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-sign.rs:4:29 + | +LL | let y: &'static bool = &(5_i32.is_positive()); + | ------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-int-unchecked.rs b/tests/ui/consts/const-int-unchecked.rs new file mode 100644 index 000000000..902a66848 --- /dev/null +++ b/tests/ui/consts/const-int-unchecked.rs @@ -0,0 +1,149 @@ +#![feature(core_intrinsics)] +#![feature(const_int_unchecked_arith)] + +use std::intrinsics; + +// The documentation of `unchecked_shl` states that it: +// +// Performs an unchecked left shift, resulting in undefined behavior when +// y < 0 or y >= N, where N is the width of T in bits. +// +// So we check this for a few `y`. + +// unsigned types: + +const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; +//~^ ERROR evaluation of constant value failed +const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; +//~^ ERROR evaluation of constant value failed +const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; +//~^ ERROR evaluation of constant value failed +const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; +//~^ ERROR evaluation of constant value failed +const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; +//~^ ERROR evaluation of constant value failed + +// signed types: + +const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; +//~^ ERROR evaluation of constant value failed +const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; +//~^ ERROR evaluation of constant value failed +const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; +//~^ ERROR evaluation of constant value failed +const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; +//~^ ERROR evaluation of constant value failed +const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; +//~^ ERROR evaluation of constant value failed + +// and make sure we capture y < 0: + +const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; +//~^ ERROR evaluation of constant value failed +const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; +//~^ ERROR evaluation of constant value failed +const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; +//~^ ERROR evaluation of constant value failed +const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; +//~^ ERROR evaluation of constant value failed +const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; +//~^ ERROR evaluation of constant value failed + +// and that there's no special relation to the value -1 by picking some +// negative values at random: + +const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; +//~^ ERROR evaluation of constant value failed +const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; +//~^ ERROR evaluation of constant value failed +const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; +//~^ ERROR evaluation of constant value failed +const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; +//~^ ERROR evaluation of constant value failed +const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; +//~^ ERROR evaluation of constant value failed + +// Repeat it all over for `unchecked_shr` + +// unsigned types: + +const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; +//~^ ERROR evaluation of constant value failed +const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; +//~^ ERROR evaluation of constant value failed +const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; +//~^ ERROR evaluation of constant value failed +const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; +//~^ ERROR evaluation of constant value failed +const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; +//~^ ERROR evaluation of constant value failed + +// signed types: + +const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; +//~^ ERROR evaluation of constant value failed +const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; +//~^ ERROR evaluation of constant value failed +const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; +//~^ ERROR evaluation of constant value failed +const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; +//~^ ERROR evaluation of constant value failed +const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; +//~^ ERROR evaluation of constant value failed + +// and make sure we capture y < 0: + +const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; +//~^ ERROR evaluation of constant value failed +const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; +//~^ ERROR evaluation of constant value failed +const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; +//~^ ERROR evaluation of constant value failed +const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; +//~^ ERROR evaluation of constant value failed +const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; +//~^ ERROR evaluation of constant value failed + +// and that there's no special relation to the value -1 by picking some +// negative values at random: + +const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; +//~^ ERROR evaluation of constant value failed +const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; +//~^ ERROR evaluation of constant value failed +const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; +//~^ ERROR evaluation of constant value failed +const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; +//~^ ERROR evaluation of constant value failed +const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; +//~^ ERROR evaluation of constant value failed + +// Other arithmetic functions: + +const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; +//~^ ERROR evaluation of constant value failed + +const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; +//~^ ERROR evaluation of constant value failed + +const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; +//~^ ERROR evaluation of constant value failed + +const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) }; +//~^ ERROR evaluation of constant value failed +const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) }; +//~^ ERROR evaluation of constant value failed + +const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) }; +//~^ ERROR evaluation of constant value failed +const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) }; +//~^ ERROR evaluation of constant value failed + +// capture fault with zero value + +const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) }; +//~^ ERROR evaluation of constant value failed +const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) }; +//~^ ERROR evaluation of constant value failed + +fn main() {} diff --git a/tests/ui/consts/const-int-unchecked.stderr b/tests/ui/consts/const-int-unchecked.stderr new file mode 100644 index 000000000..ad880d56d --- /dev/null +++ b/tests/ui/consts/const-int-unchecked.stderr @@ -0,0 +1,297 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:15:29 + | +LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:17:31 + | +LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:19:31 + | +LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:21:31 + | +LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:23:33 + | +LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:28:29 + | +LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:30:31 + | +LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:32:31 + | +LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:34:31 + | +LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:36:33 + | +LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:41:33 + | +LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:43:35 + | +LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:45:35 + | +LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:47:35 + | +LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:49:37 + | +LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:55:40 + | +LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:57:42 + | +LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:59:42 + | +LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:61:42 + | +LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:63:44 + | +LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:70:29 + | +LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:72:31 + | +LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:74:31 + | +LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:76:31 + | +LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:78:33 + | +LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:83:29 + | +LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:85:31 + | +LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:87:31 + | +LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:89:31 + | +LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:91:33 + | +LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:96:33 + | +LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:98:35 + | +LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:100:35 + | +LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:102:35 + | +LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:104:37 + | +LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:110:40 + | +LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:112:42 + | +LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:114:42 + | +LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:116:42 + | +LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:118:44 + | +LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:123:25 + | +LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:126:25 + | +LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:129:25 + | +LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul` + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:132:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dividing by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:134:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow in signed division (dividing MIN by -1) + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:137:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calculating the remainder with a divisor of zero + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:139:25 + | +LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow in signed remainder (dividing MIN by -1) + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:144:25 + | +LL | const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ctlz_nonzero` called on 0 + +error[E0080]: evaluation of constant value failed + --> $DIR/const-int-unchecked.rs:146:25 + | +LL | const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `cttz_nonzero` called on 0 + +error: aborting due to 49 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-int-wrapping-rpass.rs b/tests/ui/consts/const-int-wrapping-rpass.rs new file mode 100644 index 000000000..225d1e939 --- /dev/null +++ b/tests/ui/consts/const-int-wrapping-rpass.rs @@ -0,0 +1,47 @@ +// run-pass + +const ADD_A: u32 = 200u32.wrapping_add(55); +const ADD_B: u32 = 200u32.wrapping_add(u32::MAX); + +const SUB_A: u32 = 100u32.wrapping_sub(100); +const SUB_B: u32 = 100u32.wrapping_sub(u32::MAX); + +const MUL_A: u8 = 10u8.wrapping_mul(12); +const MUL_B: u8 = 25u8.wrapping_mul(12); + +const SHL_A: u32 = 1u32.wrapping_shl(7); +const SHL_B: u32 = 1u32.wrapping_shl(128); + +const SHR_A: u32 = 128u32.wrapping_shr(7); +const SHR_B: u32 = 128u32.wrapping_shr(128); + +const NEG_A: u32 = 5u32.wrapping_neg(); +const NEG_B: u32 = 1234567890u32.wrapping_neg(); + +const ABS_POS: i32 = 10i32.wrapping_abs(); +const ABS_NEG: i32 = (-10i32).wrapping_abs(); +const ABS_MIN: i32 = i32::MIN.wrapping_abs(); + +fn main() { + assert_eq!(ADD_A, 255); + assert_eq!(ADD_B, 199); + + assert_eq!(SUB_A, 0); + assert_eq!(SUB_B, 101); + + assert_eq!(MUL_A, 120); + assert_eq!(MUL_B, 44); + + assert_eq!(SHL_A, 128); + assert_eq!(SHL_B, 1); + + assert_eq!(SHR_A, 1); + assert_eq!(SHR_B, 128); + + assert_eq!(NEG_A, 4294967291); + assert_eq!(NEG_B, 3060399406); + + assert_eq!(ABS_POS, 10); + assert_eq!(ABS_NEG, 10); + assert_eq!(ABS_MIN, i32::MIN); +} diff --git a/tests/ui/consts/const-int-wrapping.rs b/tests/ui/consts/const-int-wrapping.rs new file mode 100644 index 000000000..50d04f964 --- /dev/null +++ b/tests/ui/consts/const-int-wrapping.rs @@ -0,0 +1,12 @@ +fn main() { + let x: &'static i32 = &(5_i32.wrapping_add(3)); + //~^ ERROR temporary value dropped while borrowed + let y: &'static i32 = &(5_i32.wrapping_sub(3)); + //~^ ERROR temporary value dropped while borrowed + let z: &'static i32 = &(5_i32.wrapping_mul(3)); + //~^ ERROR temporary value dropped while borrowed + let a: &'static i32 = &(5_i32.wrapping_shl(3)); + //~^ ERROR temporary value dropped while borrowed + let b: &'static i32 = &(5_i32.wrapping_shr(3)); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-int-wrapping.stderr b/tests/ui/consts/const-int-wrapping.stderr new file mode 100644 index 000000000..1342fadc4 --- /dev/null +++ b/tests/ui/consts/const-int-wrapping.stderr @@ -0,0 +1,58 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-wrapping.rs:2:28 + | +LL | let x: &'static i32 = &(5_i32.wrapping_add(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-wrapping.rs:4:28 + | +LL | let y: &'static i32 = &(5_i32.wrapping_sub(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-wrapping.rs:6:28 + | +LL | let z: &'static i32 = &(5_i32.wrapping_mul(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-wrapping.rs:8:28 + | +LL | let a: &'static i32 = &(5_i32.wrapping_shl(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-int-wrapping.rs:10:28 + | +LL | let b: &'static i32 = &(5_i32.wrapping_shr(3)); + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-integer-bool-ops.rs b/tests/ui/consts/const-integer-bool-ops.rs new file mode 100644 index 000000000..4110ae3e4 --- /dev/null +++ b/tests/ui/consts/const-integer-bool-ops.rs @@ -0,0 +1,85 @@ +const X: usize = 42 && 39; +//~^ ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `usize`, found `bool` +const ARR: [i32; X] = [99; 34]; +//~^ constant + +const X1: usize = 42 || 39; +//~^ ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `usize`, found `bool` +const ARR1: [i32; X1] = [99; 47]; +//~^ constant + +const X2: usize = -42 || -39; +//~^ ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `usize`, found `bool` +const ARR2: [i32; X2] = [99; 18446744073709551607]; +//~^ constant + +const X3: usize = -42 && -39; +//~^ ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `usize`, found `bool` +const ARR3: [i32; X3] = [99; 6]; +//~^ constant + +const Y: usize = 42.0 == 42.0; +//~^ ERROR mismatched types +//~| expected `usize`, found `bool` +const ARRR: [i32; Y] = [99; 1]; +//~^ constant + +const Y1: usize = 42.0 >= 42.0; +//~^ ERROR mismatched types +//~| expected `usize`, found `bool` +const ARRR1: [i32; Y1] = [99; 1]; +//~^ constant + +const Y2: usize = 42.0 <= 42.0; +//~^ ERROR mismatched types +//~| expected `usize`, found `bool` +const ARRR2: [i32; Y2] = [99; 1]; +//~^ constant + +const Y3: usize = 42.0 > 42.0; +//~^ ERROR mismatched types +//~| expected `usize`, found `bool` +const ARRR3: [i32; Y3] = [99; 0]; +//~^ constant + +const Y4: usize = 42.0 < 42.0; +//~^ ERROR mismatched types +//~| expected `usize`, found `bool` +const ARRR4: [i32; Y4] = [99; 0]; +//~^ constant + +const Y5: usize = 42.0 != 42.0; +//~^ ERROR mismatched types +//~| expected `usize`, found `bool` +const ARRR5: [i32; Y5] = [99; 0]; +//~^ constant + +fn main() { + let _ = ARR; + let _ = ARRR; + let _ = ARRR1; + let _ = ARRR2; + let _ = ARRR3; + let _ = ARRR4; + let _ = ARRR5; +} diff --git a/tests/ui/consts/const-integer-bool-ops.stderr b/tests/ui/consts/const-integer-bool-ops.stderr new file mode 100644 index 000000000..b5c3b22fd --- /dev/null +++ b/tests/ui/consts/const-integer-bool-ops.stderr @@ -0,0 +1,171 @@ +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:1:18 + | +LL | const X: usize = 42 && 39; + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:1:24 + | +LL | const X: usize = 42 && 39; + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:1:18 + | +LL | const X: usize = 42 && 39; + | ^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:8:18 + | +LL | const ARR: [i32; X] = [99; 34]; + | ^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:11:19 + | +LL | const X1: usize = 42 || 39; + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:11:25 + | +LL | const X1: usize = 42 || 39; + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:11:19 + | +LL | const X1: usize = 42 || 39; + | ^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:18:19 + | +LL | const ARR1: [i32; X1] = [99; 47]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:21:19 + | +LL | const X2: usize = -42 || -39; + | ^^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:21:26 + | +LL | const X2: usize = -42 || -39; + | ^^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:21:19 + | +LL | const X2: usize = -42 || -39; + | ^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:28:19 + | +LL | const ARR2: [i32; X2] = [99; 18446744073709551607]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:31:19 + | +LL | const X3: usize = -42 && -39; + | ^^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:31:26 + | +LL | const X3: usize = -42 && -39; + | ^^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:31:19 + | +LL | const X3: usize = -42 && -39; + | ^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:38:19 + | +LL | const ARR3: [i32; X3] = [99; 6]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:41:18 + | +LL | const Y: usize = 42.0 == 42.0; + | ^^^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:44:19 + | +LL | const ARRR: [i32; Y] = [99; 1]; + | ^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:47:19 + | +LL | const Y1: usize = 42.0 >= 42.0; + | ^^^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:50:20 + | +LL | const ARRR1: [i32; Y1] = [99; 1]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:53:19 + | +LL | const Y2: usize = 42.0 <= 42.0; + | ^^^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:56:20 + | +LL | const ARRR2: [i32; Y2] = [99; 1]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:59:19 + | +LL | const Y3: usize = 42.0 > 42.0; + | ^^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:62:20 + | +LL | const ARRR3: [i32; Y3] = [99; 0]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:65:19 + | +LL | const Y4: usize = 42.0 < 42.0; + | ^^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:68:20 + | +LL | const ARRR4: [i32; Y4] = [99; 0]; + | ^^ + +error[E0308]: mismatched types + --> $DIR/const-integer-bool-ops.rs:71:19 + | +LL | const Y5: usize = 42.0 != 42.0; + | ^^^^^^^^^^^^ expected `usize`, found `bool` + +note: erroneous constant used + --> $DIR/const-integer-bool-ops.rs:74:20 + | +LL | const ARRR5: [i32; Y5] = [99; 0]; + | ^^ + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-labeled-break.rs b/tests/ui/consts/const-labeled-break.rs new file mode 100644 index 000000000..6864f7247 --- /dev/null +++ b/tests/ui/consts/const-labeled-break.rs @@ -0,0 +1,11 @@ +// run-pass + +// Using labeled break in a while loop has caused an illegal instruction being +// generated, and an ICE later. +// +// See https://github.com/rust-lang/rust/issues/51350 for more information. + +#[allow(unreachable_code)] +const _: () = 'a: while break 'a {}; + +fn main() {} diff --git a/tests/ui/consts/const-len-underflow-separate-spans.rs b/tests/ui/consts/const-len-underflow-separate-spans.rs new file mode 100644 index 000000000..4544c8876 --- /dev/null +++ b/tests/ui/consts/const-len-underflow-separate-spans.rs @@ -0,0 +1,13 @@ +// Check that a constant-evaluation underflow highlights the correct +// spot (where the underflow occurred), while also providing the +// overall context for what caused the evaluation. + +const ONE: usize = 1; +const TWO: usize = 2; +const LEN: usize = ONE - TWO; +//~^ ERROR constant + +fn main() { + let a: [i8; LEN] = unimplemented!(); +//~^ constant +} diff --git a/tests/ui/consts/const-len-underflow-separate-spans.stderr b/tests/ui/consts/const-len-underflow-separate-spans.stderr new file mode 100644 index 000000000..269553631 --- /dev/null +++ b/tests/ui/consts/const-len-underflow-separate-spans.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-len-underflow-separate-spans.rs:7:20 + | +LL | const LEN: usize = ONE - TWO; + | ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow + +note: erroneous constant used + --> $DIR/const-len-underflow-separate-spans.rs:11:17 + | +LL | let a: [i8; LEN] = unimplemented!(); + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-len-underflow-subspans.rs b/tests/ui/consts/const-len-underflow-subspans.rs new file mode 100644 index 000000000..ed77e9078 --- /dev/null +++ b/tests/ui/consts/const-len-underflow-subspans.rs @@ -0,0 +1,11 @@ +// Check that a constant-evaluation underflow highlights the correct +// spot (where the underflow occurred). + +const ONE: usize = 1; +const TWO: usize = 2; + +fn main() { + let a: [i8; ONE - TWO] = unimplemented!(); + //~^ ERROR evaluation of constant value failed + //~| attempt to compute `1_usize - 2_usize`, which would overflow +} diff --git a/tests/ui/consts/const-len-underflow-subspans.stderr b/tests/ui/consts/const-len-underflow-subspans.stderr new file mode 100644 index 000000000..68e958b37 --- /dev/null +++ b/tests/ui/consts/const-len-underflow-subspans.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-len-underflow-subspans.rs:8:17 + | +LL | let a: [i8; ONE - TWO] = unimplemented!(); + | ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr new file mode 100644 index 000000000..08fcd1dea --- /dev/null +++ b/tests/ui/consts/const-match-check.eval1.stderr @@ -0,0 +1,21 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/const-match-check.rs:25:15 + | +LL | A = { let 0 = 0; 0 }, + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | A = { if let 0 = 0 { todo!() } 0 }, + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | A = { let _0 = 0; 0 }, + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr new file mode 100644 index 000000000..5d86ca4bf --- /dev/null +++ b/tests/ui/consts/const-match-check.eval2.stderr @@ -0,0 +1,21 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/const-match-check.rs:31:24 + | +LL | let x: [i32; { let 0 = 0; 0 }] = []; + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | let x: [i32; { if let 0 = 0 { todo!() } 0 }] = []; + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | let x: [i32; { let _0 = 0; 0 }] = []; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-match-check.matchck.stderr b/tests/ui/consts/const-match-check.matchck.stderr new file mode 100644 index 000000000..c8f66bb0f --- /dev/null +++ b/tests/ui/consts/const-match-check.matchck.stderr @@ -0,0 +1,75 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/const-match-check.rs:4:22 + | +LL | const X: i32 = { let 0 = 0; 0 }; + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | const X: i32 = { let _0 = 0; 0 }; + | + + +error[E0005]: refutable pattern in local binding + --> $DIR/const-match-check.rs:8:23 + | +LL | static Y: i32 = { let 0 = 0; 0 }; + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | static Y: i32 = { let _0 = 0; 0 }; + | + + +error[E0005]: refutable pattern in local binding + --> $DIR/const-match-check.rs:13:26 + | +LL | const X: i32 = { let 0 = 0; 0 }; + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | const X: i32 = { let _0 = 0; 0 }; + | + + +error[E0005]: refutable pattern in local binding + --> $DIR/const-match-check.rs:19:26 + | +LL | const X: i32 = { let 0 = 0; 0 }; + | ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | const X: i32 = { if let 0 = 0 { todo!() } 0 }; + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | const X: i32 = { let _0 = 0; 0 }; + | + + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-match-check.rs b/tests/ui/consts/const-match-check.rs new file mode 100644 index 000000000..60f60fa40 --- /dev/null +++ b/tests/ui/consts/const-match-check.rs @@ -0,0 +1,33 @@ +// revisions: matchck eval1 eval2 + +#[cfg(matchck)] +const X: i32 = { let 0 = 0; 0 }; +//[matchck]~^ ERROR refutable pattern in local binding + +#[cfg(matchck)] +static Y: i32 = { let 0 = 0; 0 }; +//[matchck]~^ ERROR refutable pattern in local binding + +#[cfg(matchck)] +trait Bar { + const X: i32 = { let 0 = 0; 0 }; + //[matchck]~^ ERROR refutable pattern in local binding +} + +#[cfg(matchck)] +impl Bar for () { + const X: i32 = { let 0 = 0; 0 }; + //[matchck]~^ ERROR refutable pattern in local binding +} + +#[cfg(eval1)] +enum Foo { + A = { let 0 = 0; 0 }, + //[eval1]~^ ERROR refutable pattern in local binding +} + +fn main() { + #[cfg(eval2)] + let x: [i32; { let 0 = 0; 0 }] = []; + //[eval2]~^ ERROR refutable pattern in local binding +} diff --git a/tests/ui/consts/const-match-pattern-arm.rs b/tests/ui/consts/const-match-pattern-arm.rs new file mode 100644 index 000000000..90680c019 --- /dev/null +++ b/tests/ui/consts/const-match-pattern-arm.rs @@ -0,0 +1,15 @@ +// check-pass + +const _: bool = match Some(true) { + Some(value) => true, + _ => false +}; + +const _: bool = { + match Some(true) { + Some(value) => true, + _ => false + } +}; + +fn main() {} diff --git a/tests/ui/consts/const-meth-pattern.rs b/tests/ui/consts/const-meth-pattern.rs new file mode 100644 index 000000000..1544d760a --- /dev/null +++ b/tests/ui/consts/const-meth-pattern.rs @@ -0,0 +1,18 @@ +// run-pass + +struct A; + +impl A { + const fn banana() -> bool { + true + } +} + +const ABANANA: bool = A::banana(); + +fn main() { + match true { + ABANANA => {}, + _ => panic!("what?") + } +} diff --git a/tests/ui/consts/const-multi-ref.rs b/tests/ui/consts/const-multi-ref.rs new file mode 100644 index 000000000..7e0f1a812 --- /dev/null +++ b/tests/ui/consts/const-multi-ref.rs @@ -0,0 +1,24 @@ +// Ensure that we point the user to the erroneous borrow but not to any subsequent borrows of that +// initial one. + +const _: i32 = { + let mut a = 5; + let p = &mut a; //~ ERROR mutable references are not allowed in constants + + let reborrow = {p}; + let pp = &reborrow; + let ppp = &pp; + ***ppp +}; + +const _: std::cell::Cell = { + let mut a = std::cell::Cell::new(5); + let p = &a; //~ ERROR borrowed element may contain interior mutability + + let reborrow = {p}; + let pp = &reborrow; + let ppp = &pp; + a +}; + +fn main() {} diff --git a/tests/ui/consts/const-multi-ref.stderr b/tests/ui/consts/const-multi-ref.stderr new file mode 100644 index 000000000..dd5cadfe2 --- /dev/null +++ b/tests/ui/consts/const-multi-ref.stderr @@ -0,0 +1,21 @@ +error[E0658]: mutable references are not allowed in constants + --> $DIR/const-multi-ref.rs:6:13 + | +LL | let p = &mut a; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/const-multi-ref.rs:16:13 + | +LL | let p = &a; + | ^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-mut-refs/const_mut_address_of.rs b/tests/ui/consts/const-mut-refs/const_mut_address_of.rs new file mode 100644 index 000000000..03b2f9e3c --- /dev/null +++ b/tests/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -0,0 +1,28 @@ +// check-pass +#![feature(const_mut_refs)] +#![feature(raw_ref_op)] + +struct Foo { + x: usize +} + +const fn foo() -> Foo { + Foo { x: 0 } +} + +impl Foo { + const fn bar(&mut self) -> *mut usize { + &raw mut self.x + } +} + +const fn baz(foo: &mut Foo)-> *mut usize { + &raw mut foo.x +} + +const _: () = { + foo().bar(); + baz(&mut foo()); +}; + +fn main() {} diff --git a/tests/ui/consts/const-mut-refs/const_mut_refs.rs b/tests/ui/consts/const-mut-refs/const_mut_refs.rs new file mode 100644 index 000000000..544458dfc --- /dev/null +++ b/tests/ui/consts/const-mut-refs/const_mut_refs.rs @@ -0,0 +1,35 @@ +// check-pass +#![feature(const_mut_refs)] + +struct Foo { + x: usize +} + +const fn foo() -> Foo { + Foo { x: 0 } +} + +impl Foo { + const fn bar(&mut self) -> usize { + self.x = 1; + self.x + } + +} + +const fn baz(foo: &mut Foo) -> usize { + let x = &mut foo.x; + *x = 2; + *x +} + +const fn bazz(foo: &mut Foo) -> usize { + foo.x = 3; + foo.x +} + +fn main() { + let _: [(); foo().bar()] = [(); 1]; + let _: [(); baz(&mut foo())] = [(); 2]; + let _: [(); bazz(&mut foo())] = [(); 3]; +} diff --git a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs new file mode 100644 index 000000000..ce9be4ac5 --- /dev/null +++ b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs @@ -0,0 +1,8 @@ +fn main() { + foo(&mut 5); +} + +const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references + *x + 1 + +} diff --git a/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr new file mode 100644 index 000000000..3f9bd3705 --- /dev/null +++ b/tests/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr @@ -0,0 +1,12 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/feature-gate-const_mut_refs.rs:5:14 + | +LL | const fn foo(x: &mut i32) -> i32 { + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr new file mode 100644 index 000000000..109d15a8e --- /dev/null +++ b/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr @@ -0,0 +1,31 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +note: erroneous constant used + --> $DIR/issue-76510.rs:11:70 + | +LL | let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + | ^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr new file mode 100644 index 000000000..109d15a8e --- /dev/null +++ b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -0,0 +1,31 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +note: erroneous constant used + --> $DIR/issue-76510.rs:11:70 + | +LL | let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + | ^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.rs b/tests/ui/consts/const-mut-refs/issue-76510.rs new file mode 100644 index 000000000..b853e2737 --- /dev/null +++ b/tests/ui/consts/const-mut-refs/issue-76510.rs @@ -0,0 +1,18 @@ +// stderr-per-bitwidth + +use std::mem::{transmute, ManuallyDrop}; + +const S: &'static mut str = &mut " hello "; +//~^ ERROR: mutable references are not allowed in the final value of constants +//~| ERROR: mutation through a reference is not allowed in constants +//~| ERROR: cannot borrow data in a `&` reference as mutable + +const fn trigger() -> [(); unsafe { + let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + //~^ constant + 0 + }] { + [(); 0] +} + +fn main() {} diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs new file mode 100644 index 000000000..a7d329f12 --- /dev/null +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -0,0 +1,55 @@ +#![feature(const_mut_refs)] +#![feature(raw_ref_op)] + +const NULL: *mut i32 = std::ptr::null_mut(); +const A: *const i32 = &4; + +// It could be made sound to allow it to compile, +// but we do not want to allow this to compile, +// as that would be an enormous footgun in oli-obk's opinion. +const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed + +// Ok, no actual mutable allocation exists +const B2: Option<&mut i32> = None; + +// Not ok, can't prove that no mutable allocation ends up in final value +const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed + +const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) } +const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed + +// Ok, because no references to mutable data exist here, since the `{}` moves +// its value and then takes a reference to that. +const C: *const i32 = &{ + let mut x = 42; + x += 3; + x +}; + +use std::cell::UnsafeCell; +struct NotAMutex(UnsafeCell); + +unsafe impl Sync for NotAMutex {} + +const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +// `BAR` works, because `&42` promotes immediately instead of relying on +// the enclosing scope rule. +const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); + +fn main() { + println!("{}", unsafe { *A }); + unsafe { *B = 4 } // Bad news + + unsafe { + **FOO.0.get() = 99; + assert_eq!(**FOO.0.get(), 99); + } +} diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr new file mode 100644 index 000000000..78c58b5ab --- /dev/null +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -0,0 +1,60 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/mut_ref_in_final.rs:10:21 + | +LL | const B: *mut i32 = &mut 4; + | ^^^^^^ + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:16:40 + | +LL | const B3: Option<&mut i32> = Some(&mut 42); + | ----------^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:19:42 + | +LL | const B4: Option<&mut i32> = helper(&mut 42); + | ------------^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:34:65 + | +LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:37:67 + | +LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:40:71 + | +LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0716, E0764. +For more information about an error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs new file mode 100644 index 000000000..074beaab2 --- /dev/null +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -0,0 +1,27 @@ +#![feature(const_mut_refs)] +#![feature(raw_ref_op)] + +// This file checks that our dynamic checks catch things that the static checks miss. +// We do not have static checks for these, because we do not look into function bodies. +// We treat all functions as not returning a mutable reference, because there is no way to +// do that without causing the borrow checker to complain (see the B4/helper test in +// mut_ref_in_final.rs). + +const fn helper() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour (integer as pointer), who doesn't love tests like this. + // This code never gets executed, because the static checks fail before that. + Some(&mut *(42 as *mut i32)) //~ ERROR evaluation of constant value failed + //~| 0x2a[noalloc] is a dangling pointer +} } +// The error is an evaluation error and not a validation error, so the error is reported +// directly at the site where it occurs. +const A: Option<&mut i32> = helper(); + +const fn helper2() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour (dangling pointer), who doesn't love tests like this. + // This code never gets executed, because the static checks fail before that. + Some(&mut *(&mut 42 as *mut i32)) +} } +const B: Option<&mut i32> = helper2(); //~ ERROR encountered dangling pointer in final constant + +fn main() {} diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr new file mode 100644 index 000000000..6e110dbdd --- /dev/null +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -0,0 +1,26 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10 + | +LL | Some(&mut *(42 as *mut i32)) + | ^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance) + | +note: inside `helper` + --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10 + | +LL | Some(&mut *(42 as *mut i32)) + | ^^^^^^^^^^^^^^^^^^^^^^ +note: inside `A` + --> $DIR/mut_ref_in_final_dynamic_check.rs:18:29 + | +LL | const A: Option<&mut i32> = helper(); + | ^^^^^^^^ + +error: encountered dangling pointer in final constant + --> $DIR/mut_ref_in_final_dynamic_check.rs:25:1 + | +LL | const B: Option<&mut i32> = helper2(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-needs_drop-monomorphic.rs b/tests/ui/consts/const-needs_drop-monomorphic.rs new file mode 100644 index 000000000..7402c6809 --- /dev/null +++ b/tests/ui/consts/const-needs_drop-monomorphic.rs @@ -0,0 +1,17 @@ +// Check that evaluation of needs_drop fails when T is not monomorphic. +#![feature(generic_const_exprs)] +#![allow(const_evaluatable_unchecked)] +#![allow(incomplete_features)] + +struct Bool {} +impl Bool { + fn assert() {} +} +fn f() { + Bool::<{ std::mem::needs_drop::() }>::assert(); + //~^ ERROR no function or associated item named `assert` found + //~| ERROR unconstrained generic constant +} +fn main() { + f::(); +} diff --git a/tests/ui/consts/const-needs_drop-monomorphic.stderr b/tests/ui/consts/const-needs_drop-monomorphic.stderr new file mode 100644 index 000000000..0874a70ce --- /dev/null +++ b/tests/ui/consts/const-needs_drop-monomorphic.stderr @@ -0,0 +1,20 @@ +error[E0599]: no function or associated item named `assert` found for struct `Bool<{ std::mem::needs_drop::() }>` in the current scope + --> $DIR/const-needs_drop-monomorphic.rs:11:46 + | +LL | struct Bool {} + | -------------------------- function or associated item `assert` not found for this struct +... +LL | Bool::<{ std::mem::needs_drop::() }>::assert(); + | ^^^^^^ function or associated item cannot be called on `Bool<{ std::mem::needs_drop::() }>` due to unsatisfied trait bounds + +error: unconstrained generic constant + --> $DIR/const-needs_drop-monomorphic.rs:11:5 + | +LL | Bool::<{ std::mem::needs_drop::() }>::assert(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::mem::needs_drop::() }]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/consts/const-needs_drop.rs b/tests/ui/consts/const-needs_drop.rs new file mode 100644 index 000000000..11ee7084c --- /dev/null +++ b/tests/ui/consts/const-needs_drop.rs @@ -0,0 +1,31 @@ +// run-pass + +use std::mem; + +#[allow(unused_tuple_struct_fields)] +struct Trivial(u8, f32); + +#[allow(unused_tuple_struct_fields)] +struct NonTrivial(u8, String); + +const CONST_U8: bool = mem::needs_drop::(); +const CONST_STRING: bool = mem::needs_drop::(); +const CONST_TRIVIAL: bool = mem::needs_drop::(); +const CONST_NON_TRIVIAL: bool = mem::needs_drop::(); + +static STATIC_U8: bool = mem::needs_drop::(); +static STATIC_STRING: bool = mem::needs_drop::(); +static STATIC_TRIVIAL: bool = mem::needs_drop::(); +static STATIC_NON_TRIVIAL: bool = mem::needs_drop::(); + +fn main() { + assert!(!CONST_U8); + assert!(CONST_STRING); + assert!(!CONST_TRIVIAL); + assert!(CONST_NON_TRIVIAL); + + assert!(!STATIC_U8); + assert!(STATIC_STRING); + assert!(!STATIC_TRIVIAL); + assert!(STATIC_NON_TRIVIAL); +} diff --git a/tests/ui/consts/const-negation.rs b/tests/ui/consts/const-negation.rs new file mode 100644 index 000000000..18bcdfb01 --- /dev/null +++ b/tests/ui/consts/const-negation.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(overflowing_literals)] + +fn main() { + #[cfg(target_pointer_width = "32")] + const I: isize = -2147483648isize; + #[cfg(target_pointer_width = "64")] + const I: isize = -9223372036854775808isize; + assert_eq!(i32::MIN as u64, 0xffffffff80000000); + assert_eq!(-2147483648isize as u64, 0xffffffff80000000); + assert_eq!(-2147483648i32 as u64, 0xffffffff80000000); + assert_eq!(i64::MIN as u64, 0x8000000000000000); + #[cfg(target_pointer_width = "64")] + assert_eq!(-9223372036854775808isize as u64, 0x8000000000000000); + #[cfg(target_pointer_width = "32")] + assert_eq!(-9223372036854775808isize as u64, 0); + assert_eq!(-9223372036854775808i32 as u64, 0); + const J: usize = i32::MAX as usize; + const K: usize = -1i32 as u32 as usize; + const L: usize = i32::MIN as usize; + const M: usize = i64::MIN as usize; + match 5 { + J => {}, + K => {}, + L => {}, + M => {}, + _ => {} + } + match 5 { + I => {}, + _ => {} + } +} diff --git a/tests/ui/consts/const-negative.rs b/tests/ui/consts/const-negative.rs new file mode 100644 index 000000000..1cb560936 --- /dev/null +++ b/tests/ui/consts/const-negative.rs @@ -0,0 +1,9 @@ +// run-pass +// Issue #358 +#![allow(non_upper_case_globals)] + +static toplevel_mod: isize = -1; + +pub fn main() { + assert_eq!(toplevel_mod, -1); +} diff --git a/tests/ui/consts/const-nullary-enum.rs b/tests/ui/consts/const-nullary-enum.rs new file mode 100644 index 000000000..b6574dce6 --- /dev/null +++ b/tests/ui/consts/const-nullary-enum.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +enum Foo { + Bar, + Baz, + Boo, +} + +static X: Foo = Foo::Bar; + +pub fn main() { + match X { + Foo::Bar => {} + Foo::Baz | Foo::Boo => panic!() + } + match Y { + Foo::Baz => {} + Foo::Bar | Foo::Boo => panic!() + } +} + +static Y: Foo = Foo::Baz; diff --git a/tests/ui/consts/const-nullary-univariant-enum.rs b/tests/ui/consts/const-nullary-univariant-enum.rs new file mode 100644 index 000000000..51349ad31 --- /dev/null +++ b/tests/ui/consts/const-nullary-univariant-enum.rs @@ -0,0 +1,15 @@ +// run-pass + +#[derive(Copy, Clone)] +enum Foo { + Bar = 0xDEADBEE +} + +static X: Foo = Foo::Bar; + +pub fn main() { + assert_eq!((X as usize), 0xDEADBEE); + assert_eq!((Y as usize), 0xDEADBEE); +} + +static Y: Foo = Foo::Bar; diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs new file mode 100644 index 000000000..61bdf57ff --- /dev/null +++ b/tests/ui/consts/const-pattern-irrefutable.rs @@ -0,0 +1,28 @@ +mod foo { + pub const b: u8 = 2; + pub const d: u8 = 2; +} + +use foo::b as c; +use foo::d; + +const a: u8 = 2; + +fn main() { + let a = 4; + //~^ ERROR refutable pattern in local binding + //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + let c = 4; + //~^ ERROR refutable pattern in local binding + //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + //~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + let d = 4; + //~^ ERROR refutable pattern in local binding + //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + //~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). +} diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr new file mode 100644 index 000000000..c156ea161 --- /dev/null +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -0,0 +1,48 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/const-pattern-irrefutable.rs:12:9 + | +LL | const a: u8 = 2; + | ----------- constant defined here +... +LL | let a = 4; + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `a_var` + | + = note: the matched value is of type `u8` + +error[E0005]: refutable pattern in local binding + --> $DIR/const-pattern-irrefutable.rs:17:9 + | +LL | pub const b: u8 = 2; + | --------------- constant defined here +... +LL | let c = 4; + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `c_var` + | + = note: the matched value is of type `u8` + +error[E0005]: refutable pattern in local binding + --> $DIR/const-pattern-irrefutable.rs:22:9 + | +LL | pub const d: u8 = 2; + | --------------- constant defined here +... +LL | let d = 4; + | ^ + | | + | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `d_var` + | + = note: the matched value is of type `u8` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-pattern-not-const-evaluable.rs b/tests/ui/consts/const-pattern-not-const-evaluable.rs new file mode 100644 index 000000000..dae5343fe --- /dev/null +++ b/tests/ui/consts/const-pattern-not-const-evaluable.rs @@ -0,0 +1,30 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#[derive(PartialEq, Eq)] +enum Cake { + BlackForest, + Marmor, +} +use Cake::*; + +struct Pair(A, B); + +const BOO: Pair = Pair(Marmor, BlackForest); +const FOO: Cake = BOO.1; + +const fn foo() -> Cake { + Marmor +} + +const WORKS: Cake = Marmor; + +const GOO: Cake = foo(); + +fn main() { + match BlackForest { + FOO => println!("hi"), + GOO => println!("meh"), + WORKS => println!("möp"), + _ => println!("bye"), + } +} diff --git a/tests/ui/consts/const-pattern-variant.rs b/tests/ui/consts/const-pattern-variant.rs new file mode 100644 index 000000000..80f749ed7 --- /dev/null +++ b/tests/ui/consts/const-pattern-variant.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(unreachable_patterns)] + +#[derive(PartialEq, Eq)] +enum Cake { + BlackForest, + Marmor, +} +use Cake::*; + +const BOO: (Cake, Cake) = (Marmor, BlackForest); +const FOO: Cake = BOO.1; + +const fn foo() -> Cake { + Marmor +} + +const WORKS: Cake = Marmor; + +const GOO: Cake = foo(); + +fn main() { + match BlackForest { + FOO => println!("hi"), + GOO => println!("meh"), + WORKS => println!("möp"), + _ => println!("bye"), + } +} diff --git a/tests/ui/consts/const-points-to-static.32bit.stderr b/tests/ui/consts/const-points-to-static.32bit.stderr new file mode 100644 index 000000000..c7a435a1e --- /dev/null +++ b/tests/ui/consts/const-points-to-static.32bit.stderr @@ -0,0 +1,22 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-points-to-static.rs:6:1 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc1──╼ │ ╾──╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const-points-to-static.rs:6:20 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-points-to-static.64bit.stderr b/tests/ui/consts/const-points-to-static.64bit.stderr new file mode 100644 index 000000000..4d5b8eac5 --- /dev/null +++ b/tests/ui/consts/const-points-to-static.64bit.stderr @@ -0,0 +1,22 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-points-to-static.rs:6:1 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc1────────╼ │ ╾──────╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const-points-to-static.rs:6:20 + | +LL | const TEST: &u8 = &MY_STATIC; + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-points-to-static.rs b/tests/ui/consts/const-points-to-static.rs new file mode 100644 index 000000000..ca825a1f5 --- /dev/null +++ b/tests/ui/consts/const-points-to-static.rs @@ -0,0 +1,13 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// stderr-per-bitwidth + +#![allow(dead_code)] + +const TEST: &u8 = &MY_STATIC; +//~^ ERROR it is undefined behavior to use this value +//~| encountered a reference pointing to a static variable + +static MY_STATIC: u8 = 4; + +fn main() { +} diff --git a/tests/ui/consts/const-prop-ice.rs b/tests/ui/consts/const-prop-ice.rs new file mode 100644 index 000000000..5bffe0206 --- /dev/null +++ b/tests/ui/consts/const-prop-ice.rs @@ -0,0 +1,5 @@ +// build-fail + +fn main() { + [0; 3][3u64 as usize]; //~ ERROR this operation will panic at runtime +} diff --git a/tests/ui/consts/const-prop-ice.stderr b/tests/ui/consts/const-prop-ice.stderr new file mode 100644 index 000000000..3bcf2b2de --- /dev/null +++ b/tests/ui/consts/const-prop-ice.stderr @@ -0,0 +1,10 @@ +error: this operation will panic at runtime + --> $DIR/const-prop-ice.rs:4:5 + | +LL | [0; 3][3u64 as usize]; + | ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 3 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-prop-ice2.rs b/tests/ui/consts/const-prop-ice2.rs new file mode 100644 index 000000000..d533e394c --- /dev/null +++ b/tests/ui/consts/const-prop-ice2.rs @@ -0,0 +1,7 @@ +// build-fail + +fn main() { + enum Enum { One=1 } + let xs=[0;1 as usize]; + println!("{}", xs[Enum::One as usize]); //~ ERROR this operation will panic at runtime +} diff --git a/tests/ui/consts/const-prop-ice2.stderr b/tests/ui/consts/const-prop-ice2.stderr new file mode 100644 index 000000000..2b65ffc2d --- /dev/null +++ b/tests/ui/consts/const-prop-ice2.stderr @@ -0,0 +1,10 @@ +error: this operation will panic at runtime + --> $DIR/const-prop-ice2.rs:6:20 + | +LL | println!("{}", xs[Enum::One as usize]); + | ^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/consts/const-prop-ice3.rs b/tests/ui/consts/const-prop-ice3.rs new file mode 100644 index 000000000..8ab011661 --- /dev/null +++ b/tests/ui/consts/const-prop-ice3.rs @@ -0,0 +1,7 @@ +// run-pass (ensure that const-prop is run) + +struct A(T); + +fn main() { + let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32; +} diff --git a/tests/ui/consts/const-prop-overflowing-casts.rs b/tests/ui/consts/const-prop-overflowing-casts.rs new file mode 100644 index 000000000..8cc5b9825 --- /dev/null +++ b/tests/ui/consts/const-prop-overflowing-casts.rs @@ -0,0 +1,15 @@ +// check-pass + +enum Foo { + Bar = -42, + Baz = 42, +} + +fn main() { + let _ = 0u8 as u32; + let _ = (1u32 << 31) as u16; + let _ = (1u16 << 15) as u8; + let _ = (!0u16) as u8; + let _ = (-1i16) as i8; + let _ = (Foo::Bar) as i8; +} diff --git a/tests/ui/consts/const-prop-read-static-in-const.rs b/tests/ui/consts/const-prop-read-static-in-const.rs new file mode 100644 index 000000000..214262059 --- /dev/null +++ b/tests/ui/consts/const-prop-read-static-in-const.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +#![allow(dead_code)] + +const TEST: u8 = MY_STATIC; //~ ERROR constant + +static MY_STATIC: u8 = 4; + +fn main() { +} diff --git a/tests/ui/consts/const-prop-read-static-in-const.stderr b/tests/ui/consts/const-prop-read-static-in-const.stderr new file mode 100644 index 000000000..793da6285 --- /dev/null +++ b/tests/ui/consts/const-prop-read-static-in-const.stderr @@ -0,0 +1,17 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-prop-read-static-in-const.rs:5:18 + | +LL | const TEST: u8 = MY_STATIC; + | ^^^^^^^^^ constant accesses static + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const-prop-read-static-in-const.rs:5:18 + | +LL | const TEST: u8 = MY_STATIC; + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-ptr-nonnull-rpass.rs b/tests/ui/consts/const-ptr-nonnull-rpass.rs new file mode 100644 index 000000000..67d52ad08 --- /dev/null +++ b/tests/ui/consts/const-ptr-nonnull-rpass.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(ptr_internals, test)] + +extern crate test; +use test::black_box as b; // prevent promotion of the argument and const-propagation of the result + +use std::ptr::NonNull; + +const DANGLING: NonNull = NonNull::dangling(); +const CASTED: NonNull = NonNull::cast(NonNull::::dangling()); + +pub fn main() { + // Be super-extra paranoid and cast the fn items to fn pointers before blackboxing them. + assert_eq!(DANGLING, b:: _>(NonNull::dangling)()); + assert_eq!(CASTED, b:: _>(NonNull::dangling)()); +} diff --git a/tests/ui/consts/const-ptr-nonnull.rs b/tests/ui/consts/const-ptr-nonnull.rs new file mode 100644 index 000000000..25cf6cf4a --- /dev/null +++ b/tests/ui/consts/const-ptr-nonnull.rs @@ -0,0 +1,11 @@ +use std::ptr::NonNull; + +fn main() { + let x: &'static NonNull = &(NonNull::dangling()); + //~^ ERROR temporary value dropped while borrowed + + let mut i: i32 = 10; + let non_null = NonNull::new(&mut i).unwrap(); + let x: &'static NonNull = &(non_null.cast()); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-ptr-nonnull.stderr b/tests/ui/consts/const-ptr-nonnull.stderr new file mode 100644 index 000000000..dbcb0c860 --- /dev/null +++ b/tests/ui/consts/const-ptr-nonnull.stderr @@ -0,0 +1,25 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-ptr-nonnull.rs:4:37 + | +LL | let x: &'static NonNull = &(NonNull::dangling()); + | --------------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-ptr-nonnull.rs:9:37 + | +LL | let x: &'static NonNull = &(non_null.cast()); + | --------------------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-ptr-unique-rpass.rs b/tests/ui/consts/const-ptr-unique-rpass.rs new file mode 100644 index 000000000..fc13bb98b --- /dev/null +++ b/tests/ui/consts/const-ptr-unique-rpass.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(ptr_internals, test)] + +extern crate test; +use test::black_box as b; // prevent promotion of the argument and const-propagation of the result + +use std::ptr::Unique; + + +const PTR: *mut u32 = Unique::dangling().as_ptr(); + +pub fn main() { + // Be super-extra paranoid and cast the fn items to fn pointers before blackboxing them. + assert_eq!(PTR, b:: _>(Unique::::dangling)().as_ptr()); +} diff --git a/tests/ui/consts/const-ptr-unique.rs b/tests/ui/consts/const-ptr-unique.rs new file mode 100644 index 000000000..252c5d1a9 --- /dev/null +++ b/tests/ui/consts/const-ptr-unique.rs @@ -0,0 +1,10 @@ +#![feature(ptr_internals)] + +use std::ptr::Unique; + +fn main() { + let mut i: u32 = 10; + let unique = Unique::new(&mut i).unwrap(); + let x: &'static *mut u32 = &(unique.as_ptr()); + //~^ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/const-ptr-unique.stderr b/tests/ui/consts/const-ptr-unique.stderr new file mode 100644 index 000000000..83448c3e8 --- /dev/null +++ b/tests/ui/consts/const-ptr-unique.stderr @@ -0,0 +1,14 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/const-ptr-unique.rs:8:33 + | +LL | let x: &'static *mut u32 = &(unique.as_ptr()); + | ----------------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/const-rec-and-tup.rs b/tests/ui/consts/const-rec-and-tup.rs new file mode 100644 index 000000000..0bddaf75d --- /dev/null +++ b/tests/ui/consts/const-rec-and-tup.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] +#![allow(overflowing_literals)] + +struct Pair { a: f64, b: f64 } + +struct AnotherPair { x: (i64, i64), y: Pair } + +static x : (i32,i32) = (0xfeedf00dd,0xca11ab1e); +static y : AnotherPair = AnotherPair{ x: (0xf0f0f0f0_f0f0f0f0, + 0xabababab_abababab), + y: Pair { a: 3.14159265358979323846, + b: 2.7182818284590452354 }}; + +pub fn main() { + let (p, _) = y.x; + assert_eq!(p, - 1085102592571150096); + println!("{:#x}", p); +} diff --git a/tests/ui/consts/const-region-ptrs-noncopy.rs b/tests/ui/consts/const-region-ptrs-noncopy.rs new file mode 100644 index 000000000..10b9ce896 --- /dev/null +++ b/tests/ui/consts/const-region-ptrs-noncopy.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +type Big = [u64; 8]; +struct Pair<'a> { a: isize, b: &'a Big } +const x: &'static Big = &([13, 14, 10, 13, 11, 14, 14, 15]); +const y: &'static Pair<'static> = &Pair {a: 15, b: x}; + +pub fn main() { + assert_eq!(x as *const Big, y.b as *const Big); +} diff --git a/tests/ui/consts/const-region-ptrs.rs b/tests/ui/consts/const-region-ptrs.rs new file mode 100644 index 000000000..9b94a2b11 --- /dev/null +++ b/tests/ui/consts/const-region-ptrs.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_upper_case_globals)] + +struct Pair<'a> { a: isize, b: &'a isize } + +const x: &'static isize = &10; + +const y: &'static Pair<'static> = &Pair {a: 15, b: x}; + +pub fn main() { + println!("x = {}", *x); + println!("y = {{a: {}, b: {}}}", y.a, *(y.b)); + assert_eq!(*x, 10); + assert_eq!(*(y.b), 10); +} diff --git a/tests/ui/consts/const-repeated-values.rs b/tests/ui/consts/const-repeated-values.rs new file mode 100644 index 000000000..27efb5ba2 --- /dev/null +++ b/tests/ui/consts/const-repeated-values.rs @@ -0,0 +1,10 @@ +// run-pass +const FOO: isize = 42; + +enum Bar { + Boo = *[&FOO; 4][3], +} + +fn main() { + assert_eq!(Bar::Boo as isize, 42); +} diff --git a/tests/ui/consts/const-size_of-align_of.rs b/tests/ui/consts/const-size_of-align_of.rs new file mode 100644 index 000000000..0c63dc84a --- /dev/null +++ b/tests/ui/consts/const-size_of-align_of.rs @@ -0,0 +1,51 @@ +// run-pass +#![allow(dead_code)] + +use std::mem; + +// Get around the limitations of CTFE in today's Rust. +const fn choice_u64(c: bool, a: u64, b: u64) -> u64 { + (-(c as i64) as u64) & a | (-(!c as i64) as u64) & b +} + +const fn max_usize(a: usize, b: usize) -> usize { + choice_u64(a > b, a as u64, b as u64) as usize +} + +const fn align_to(size: usize, align: usize) -> usize { + (size + (align - 1)) & !(align - 1) +} + +const fn packed_union_size_of() -> usize { + max_usize(mem::size_of::(), mem::size_of::()) +} + +const fn union_align_of() -> usize { + max_usize(mem::align_of::(), mem::align_of::()) +} + +const fn union_size_of() -> usize { + align_to(packed_union_size_of::(), union_align_of::()) +} + +macro_rules! fake_union { + ($name:ident { $a:ty, $b:ty }) => ( + struct $name { + _align: ([$a; 0], [$b; 0]), + _bytes: [u8; union_size_of::<$a, $b>()] + } + ) +} + +// Check that we can (poorly) emulate unions by +// calling size_of and align_of at compile-time. +fake_union!(U { u16, [u8; 3] }); + +fn test(u: U) { + assert_eq!(mem::size_of_val(&u._bytes), 4); +} + +fn main() { + assert_eq!(mem::size_of::(), 4); + assert_eq!(mem::align_of::(), 2); +} diff --git a/tests/ui/consts/const-size_of-cycle.rs b/tests/ui/consts/const-size_of-cycle.rs new file mode 100644 index 000000000..1f56c8bd8 --- /dev/null +++ b/tests/ui/consts/const-size_of-cycle.rs @@ -0,0 +1,7 @@ +// error-pattern: cycle detected + +struct Foo { + bytes: [u8; std::mem::size_of::()] +} + +fn main() {} diff --git a/tests/ui/consts/const-size_of-cycle.stderr b/tests/ui/consts/const-size_of-cycle.stderr new file mode 100644 index 000000000..17088d999 --- /dev/null +++ b/tests/ui/consts/const-size_of-cycle.stderr @@ -0,0 +1,29 @@ +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/const-size_of-cycle.rs:4:17 + | +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... + --> $DIR/const-size_of-cycle.rs:4:17 + | +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... + --> $DIR/const-size_of-cycle.rs:4:17 + | +LL | bytes: [u8; std::mem::size_of::()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `Foo`... + = note: ...which requires computing layout of `[u8; std::mem::size_of::()]`... + = note: ...which requires normalizing `[u8; std::mem::size_of::()]`... + = note: ...which again requires evaluating type-level constant, completing the cycle +note: cycle used when checking that `Foo` is well-formed + --> $DIR/const-size_of-cycle.rs:3:1 + | +LL | struct Foo { + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs new file mode 100644 index 000000000..4df3a793b --- /dev/null +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -0,0 +1,14 @@ +#![feature(extern_types)] +#![feature(core_intrinsics)] +#![feature(const_size_of_val, const_align_of_val)] + +use std::intrinsics::{min_align_of_val, size_of_val}; + +extern "C" { + type Opaque; +} + +const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR constant +const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR constant + +fn main() {} diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr new file mode 100644 index 000000000..ad2de0f4d --- /dev/null +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31 + | +LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout + +error[E0080]: evaluation of constant value failed + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32 + | +LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-size_of_val-align_of_val.rs b/tests/ui/consts/const-size_of_val-align_of_val.rs new file mode 100644 index 000000000..e8323e4ae --- /dev/null +++ b/tests/ui/consts/const-size_of_val-align_of_val.rs @@ -0,0 +1,55 @@ +// run-pass + +#![feature(const_size_of_val, const_align_of_val)] +#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)] + +use std::{mem, ptr}; + +struct Foo(#[allow(unused_tuple_struct_fields)] u32); + +#[derive(Clone, Copy)] +struct Bar { + _x: u8, + _y: u16, + _z: u8, +} + +union Ugh { + _a: [u8; 3], + _b: Bar, +} + +const FOO: Foo = Foo(4); +const BAR: Bar = Bar { _x: 4, _y: 1, _z: 2 }; +const UGH: Ugh = Ugh { _a: [0; 3] }; + +const SIZE_OF_FOO: usize = mem::size_of_val(&FOO); +const SIZE_OF_BAR: usize = mem::size_of_val(&BAR); +const SIZE_OF_UGH: usize = mem::size_of_val(&UGH); + +const ALIGN_OF_FOO: usize = mem::align_of_val(&FOO); +const ALIGN_OF_BAR: usize = mem::align_of_val(&BAR); +const ALIGN_OF_UGH: usize = mem::align_of_val(&UGH); + +const SIZE_OF_SLICE: usize = mem::size_of_val("foobar".as_bytes()); + +const SIZE_OF_DANGLING: usize = unsafe { mem::size_of_val_raw(0x100 as *const i32) }; +const SIZE_OF_BIG: usize = + unsafe { mem::size_of_val_raw(ptr::slice_from_raw_parts(0 as *const u8, isize::MAX as usize)) }; +const ALIGN_OF_DANGLING: usize = unsafe { mem::align_of_val_raw(0x100 as *const i16) }; + +fn main() { + assert_eq!(SIZE_OF_FOO, mem::size_of::()); + assert_eq!(SIZE_OF_BAR, mem::size_of::()); + assert_eq!(SIZE_OF_UGH, mem::size_of::()); + + assert_eq!(ALIGN_OF_FOO, mem::align_of::()); + assert_eq!(ALIGN_OF_BAR, mem::align_of::()); + assert_eq!(ALIGN_OF_UGH, mem::align_of::()); + + assert_eq!(SIZE_OF_DANGLING, mem::size_of::()); + assert_eq!(SIZE_OF_BIG, isize::MAX as usize); + assert_eq!(ALIGN_OF_DANGLING, mem::align_of::()); + + assert_eq!(SIZE_OF_SLICE, "foobar".len()); +} diff --git a/tests/ui/consts/const-slice-oob.rs b/tests/ui/consts/const-slice-oob.rs new file mode 100644 index 000000000..429b97821 --- /dev/null +++ b/tests/ui/consts/const-slice-oob.rs @@ -0,0 +1,8 @@ +const FOO: &'static[u32] = &[1, 2, 3]; +const BAR: u32 = FOO[5]; +//~^ index out of bounds: the length is 3 but the index is 5 +//~| ERROR evaluation of constant value failed + +fn main() { + let _ = BAR; +} diff --git a/tests/ui/consts/const-slice-oob.stderr b/tests/ui/consts/const-slice-oob.stderr new file mode 100644 index 000000000..746883a79 --- /dev/null +++ b/tests/ui/consts/const-slice-oob.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-slice-oob.rs:2:18 + | +LL | const BAR: u32 = FOO[5]; + | ^^^^^^ index out of bounds: the length is 3 but the index is 5 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-struct-offsets.rs b/tests/ui/consts/const-struct-offsets.rs new file mode 100644 index 000000000..26a008320 --- /dev/null +++ b/tests/ui/consts/const-struct-offsets.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![allow(non_upper_case_globals)] + +enum Foo { + IntVal(i32), + Int64Val(i64) +} + +struct Bar { + i: i32, + v: Foo +} + +static bar: Bar = Bar { i: 0, v: Foo::IntVal(0) }; + +pub fn main() {} diff --git a/tests/ui/consts/const-struct.rs b/tests/ui/consts/const-struct.rs new file mode 100644 index 000000000..db397a891 --- /dev/null +++ b/tests/ui/consts/const-struct.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +use std::cmp; + +#[derive(Debug)] +struct foo { a: isize, b: isize, c: isize } + +impl cmp::PartialEq for foo { + fn eq(&self, other: &foo) -> bool { + (*self).a == (*other).a && + (*self).b == (*other).b && + (*self).c == (*other).c + } + fn ne(&self, other: &foo) -> bool { !(*self).eq(other) } +} + +const x : foo = foo { a:1, b:2, c: 3 }; +const y : foo = foo { b:2, c:3, a: 1 }; +const z : &'static foo = &foo { a: 10, b: 22, c: 12 }; +const w : foo = foo { a:5, ..x }; + +pub fn main() { + assert_eq!(x.b, 2); + assert_eq!(x, y); + assert_eq!(z.b, 22); + assert_eq!(w.a, 5); + assert_eq!(w.c, 3); + println!("{:#x}", x.b); + println!("{:#x}", z.c); +} diff --git a/tests/ui/consts/const-suggest-feature.rs b/tests/ui/consts/const-suggest-feature.rs new file mode 100644 index 000000000..d76d01a3d --- /dev/null +++ b/tests/ui/consts/const-suggest-feature.rs @@ -0,0 +1,7 @@ +const WRITE: () = unsafe { + *std::ptr::null_mut() = 0; + //~^ ERROR dereferencing raw mutable pointers in constants is unstable + //~| HELP add `#![feature(const_mut_refs)]` to the crate attributes to enable +}; + +fn main() {} diff --git a/tests/ui/consts/const-suggest-feature.stderr b/tests/ui/consts/const-suggest-feature.stderr new file mode 100644 index 000000000..3bc1eacf3 --- /dev/null +++ b/tests/ui/consts/const-suggest-feature.stderr @@ -0,0 +1,12 @@ +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/const-suggest-feature.rs:2:5 + | +LL | *std::ptr::null_mut() = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-trait-to-trait.rs b/tests/ui/consts/const-trait-to-trait.rs new file mode 100644 index 000000000..12a2999d7 --- /dev/null +++ b/tests/ui/consts/const-trait-to-trait.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Issue #24644 - block causes a &Trait -> &Trait coercion: +trait Trait {} + +struct Bar; +impl Trait for Bar {} + +fn main() { + let x: &[&dyn Trait] = &[{ &Bar }]; +} + +// Issue #25748 - the cast causes an &Encoding -> &Encoding coercion: +pub struct UTF8Encoding; +pub const UTF_8: &'static UTF8Encoding = &UTF8Encoding; +pub trait Encoding {} +impl Encoding for UTF8Encoding {} +pub fn f() -> &'static dyn Encoding { UTF_8 as &'static dyn Encoding } + +// Root of the problem: &Trait -> &Trait coercions: +const FOO: &'static dyn Trait = &Bar; +const BAR: &'static dyn Trait = FOO; +fn foo() { let _x = BAR; } diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs new file mode 100644 index 000000000..0839c23a0 --- /dev/null +++ b/tests/ui/consts/const-try-feature-gate.rs @@ -0,0 +1,9 @@ +// gate-test-const_try + +const fn t() -> Option<()> { + Some(())?; + //~^ error: `?` is not allowed in a `const fn` + None +} + +fn main() {} diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr new file mode 100644 index 000000000..cd1a06304 --- /dev/null +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: `?` is not allowed in a `const fn` + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | + = note: see issue #74935 for more information + = help: add `#![feature(const_try)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs new file mode 100644 index 000000000..e199fd9ff --- /dev/null +++ b/tests/ui/consts/const-try.rs @@ -0,0 +1,39 @@ +// check-pass + +// Demonstrates what's needed to make use of `?` in const contexts. + +#![crate_type = "lib"] +#![feature(try_trait_v2)] +#![feature(const_trait_impl)] +#![feature(const_try)] + +use std::ops::{ControlFlow, FromResidual, Try}; + +struct TryMe; +struct Error; + +impl const FromResidual for TryMe { + fn from_residual(residual: Error) -> Self { + TryMe + } +} + +impl const Try for TryMe { + type Output = (); + type Residual = Error; + fn from_output(output: Self::Output) -> Self { + TryMe + } + fn branch(self) -> ControlFlow { + ControlFlow::Break(Error) + } +} + +const fn t() -> TryMe { + TryMe?; + TryMe +} + +const _: () = { + t(); +}; diff --git a/tests/ui/consts/const-tup-index-span.rs b/tests/ui/consts/const-tup-index-span.rs new file mode 100644 index 000000000..778a21224 --- /dev/null +++ b/tests/ui/consts/const-tup-index-span.rs @@ -0,0 +1,10 @@ +// Test spans of errors + +const TUP: (usize,) = 5usize << 64; +//~^ ERROR mismatched types +//~| expected tuple, found `usize` +const ARR: [i32; TUP.0] = []; +//~^ constant + +fn main() { +} diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr new file mode 100644 index 000000000..ad8468056 --- /dev/null +++ b/tests/ui/consts/const-tup-index-span.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/const-tup-index-span.rs:3:23 + | +LL | const TUP: (usize,) = 5usize << 64; + | ^^^^^^^^^^^^ expected tuple, found `usize` + | + = note: expected tuple `(usize,)` + found type `usize` +help: use a trailing comma to create a tuple with one element + | +LL | const TUP: (usize,) = (5usize << 64,); + | + ++ + +note: erroneous constant used + --> $DIR/const-tup-index-span.rs:6:18 + | +LL | const ARR: [i32; TUP.0] = []; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-tuple-struct.rs b/tests/ui/consts/const-tuple-struct.rs new file mode 100644 index 000000000..0144afaac --- /dev/null +++ b/tests/ui/consts/const-tuple-struct.rs @@ -0,0 +1,14 @@ +// run-pass + +struct Bar(isize, isize); + +static X: Bar = Bar(1, 2); + +pub fn main() { + match X { + Bar(x, y) => { + assert_eq!(x, 1); + assert_eq!(y, 2); + } + } +} diff --git a/tests/ui/consts/const-type-mismatch.rs b/tests/ui/consts/const-type-mismatch.rs new file mode 100644 index 000000000..6e56c046f --- /dev/null +++ b/tests/ui/consts/const-type-mismatch.rs @@ -0,0 +1,11 @@ +// `const`s shouldn't suggest `.into()` + +const TEN: u8 = 10; +const TWELVE: u16 = TEN + 2; +//~^ ERROR mismatched types [E0308] + +fn main() { + const TEN: u8 = 10; + const ALSO_TEN: u16 = TEN; + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/consts/const-type-mismatch.stderr b/tests/ui/consts/const-type-mismatch.stderr new file mode 100644 index 000000000..17bb27d4b --- /dev/null +++ b/tests/ui/consts/const-type-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/const-type-mismatch.rs:4:21 + | +LL | const TWELVE: u16 = TEN + 2; + | ^^^^^^^ expected `u16`, found `u8` + +error[E0308]: mismatched types + --> $DIR/const-type-mismatch.rs:9:27 + | +LL | const ALSO_TEN: u16 = TEN; + | ^^^ expected `u16`, found `u8` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-typeid-of-rpass.rs b/tests/ui/consts/const-typeid-of-rpass.rs new file mode 100644 index 000000000..89d57ae4f --- /dev/null +++ b/tests/ui/consts/const-typeid-of-rpass.rs @@ -0,0 +1,34 @@ +// run-pass +#![feature(const_type_id)] +#![feature(core_intrinsics)] + +use std::any::TypeId; + +struct A; + +static ID_ISIZE: TypeId = TypeId::of::(); + +pub fn main() { + assert_eq!(ID_ISIZE, TypeId::of::()); + + // sanity test of TypeId + const T: (TypeId, TypeId, TypeId) = (TypeId::of::(), + TypeId::of::<&'static str>(), + TypeId::of::()); + let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + + assert!(T.0 != T.1); + assert!(T.0 != T.2); + assert!(T.1 != T.2); + + assert_eq!(T.0, d); + assert_eq!(T.1, e); + assert_eq!(T.2, f); + + // Check fn pointer against collisions + const F: (TypeId, TypeId) = (TypeId::of:: A) -> A>(), + TypeId::of:: A, A) -> A>()); + + assert!(F.0 != F.1); +} diff --git a/tests/ui/consts/const-unit-struct.rs b/tests/ui/consts/const-unit-struct.rs new file mode 100644 index 000000000..1c9e0e8d3 --- /dev/null +++ b/tests/ui/consts/const-unit-struct.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct Foo; + +static X: Foo = Foo; + +pub fn main() { + match X { + Foo => {} + } +} diff --git a/tests/ui/consts/const-unsafe-fn.rs b/tests/ui/consts/const-unsafe-fn.rs new file mode 100644 index 000000000..72ce73f74 --- /dev/null +++ b/tests/ui/consts/const-unsafe-fn.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// A quick test of 'unsafe const fn' functionality + +const unsafe fn dummy(v: u32) -> u32 { + !v +} + +struct Type; +impl Type { + const unsafe fn new() -> Type { + Type + } +} + +const VAL: u32 = unsafe { dummy(0xFFFF) }; +const TYPE_INST: Type = unsafe { Type::new() }; + +fn main() { + assert_eq!(VAL, 0xFFFF0000); +} diff --git a/tests/ui/consts/const-unsized.rs b/tests/ui/consts/const-unsized.rs new file mode 100644 index 000000000..319b8ef97 --- /dev/null +++ b/tests/ui/consts/const-unsized.rs @@ -0,0 +1,17 @@ +use std::fmt::Debug; + +const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); +//~^ ERROR the size for values of type + +const CONST_FOO: str = *"foo"; +//~^ ERROR the size for values of type + +static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); +//~^ ERROR the size for values of type + +static STATIC_BAR: str = *"bar"; +//~^ ERROR the size for values of type + +fn main() { + println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR); +} diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr new file mode 100644 index 000000000..27b200648 --- /dev/null +++ b/tests/ui/consts/const-unsized.stderr @@ -0,0 +1,35 @@ +error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time + --> $DIR/const-unsized.rs:3:16 + | +LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/const-unsized.rs:6:18 + | +LL | const CONST_FOO: str = *"foo"; + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + +error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time + --> $DIR/const-unsized.rs:9:18 + | +LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/const-unsized.rs:12:20 + | +LL | static STATIC_BAR: str = *"bar"; + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/const-unwrap.rs b/tests/ui/consts/const-unwrap.rs new file mode 100644 index 000000000..729ae535c --- /dev/null +++ b/tests/ui/consts/const-unwrap.rs @@ -0,0 +1,13 @@ +// check-fail + +#![feature(const_option)] + +const FOO: i32 = Some(42i32).unwrap(); + +const BAR: i32 = Option::::None.unwrap(); +//~^ERROR: evaluation of constant value failed + +fn main() { + println!("{}", FOO); + println!("{}", BAR); +} diff --git a/tests/ui/consts/const-unwrap.stderr b/tests/ui/consts/const-unwrap.stderr new file mode 100644 index 000000000..d2cbe4550 --- /dev/null +++ b/tests/ui/consts/const-unwrap.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-unwrap.rs:7:18 + | +LL | const BAR: i32 = Option::::None.unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-validation-fail-55455.rs b/tests/ui/consts/const-validation-fail-55455.rs new file mode 100644 index 000000000..583074888 --- /dev/null +++ b/tests/ui/consts/const-validation-fail-55455.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/55454 +// build-pass (FIXME(62277): could be check-pass?) + +struct This(T); + +const C: This> = This(Some(&1)); + +fn main() { +} diff --git a/tests/ui/consts/const-variant-count.rs b/tests/ui/consts/const-variant-count.rs new file mode 100644 index 000000000..50eaeeb46 --- /dev/null +++ b/tests/ui/consts/const-variant-count.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(dead_code, enum_intrinsics_non_enums)] +#![feature(variant_count)] +#![feature(never_type)] + +use std::mem::variant_count; + +enum Void {} + +enum Foo { + A, + B, + C, +} + +enum Bar { + A, + B, + C, + D(usize), + E { field_1: usize, field_2: Foo }, +} + +struct Baz { + a: u32, + b: *const u8, +} + +const TEST_VOID: usize = variant_count::(); +const TEST_FOO: usize = variant_count::(); +const TEST_BAR: usize = variant_count::(); + +const NO_ICE_STRUCT: usize = variant_count::(); +const NO_ICE_BOOL: usize = variant_count::(); +const NO_ICE_PRIM: usize = variant_count::<*const u8>(); + +fn main() { + assert_eq!(TEST_VOID, 0); + assert_eq!(TEST_FOO, 3); + assert_eq!(TEST_BAR, 5); + assert_eq!(variant_count::(), 0); + assert_eq!(variant_count::(), 3); + assert_eq!(variant_count::(), 5); + assert_eq!(variant_count::>(), 2); + assert_eq!(variant_count::>(), 2); + assert_eq!(variant_count::>(), 2); +} diff --git a/tests/ui/consts/const-vec-of-fns.rs b/tests/ui/consts/const-vec-of-fns.rs new file mode 100644 index 000000000..6d90b066b --- /dev/null +++ b/tests/ui/consts/const-vec-of-fns.rs @@ -0,0 +1,25 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_upper_case_globals)] + +/*! + * Try to double-check that static fns have the right size (with or + * without dummy env ptr, as appropriate) by iterating a size-2 array. + * If the static size differs from the runtime size, the second element + * should be read as a null or otherwise wrong pointer and crash. + */ + +fn f() { } +static bare_fns: &'static [fn()] = &[f, f]; +struct S(F); +static mut closures: &'static mut [S] = &mut [S(f as fn()), S(f as fn())]; + +pub fn main() { + unsafe { + for &bare_fn in bare_fns { bare_fn() } + for closure in &mut *closures { + let S(ref mut closure) = *closure; + (*closure)() + } + } +} diff --git a/tests/ui/consts/const-vec-syntax.rs b/tests/ui/consts/const-vec-syntax.rs new file mode 100644 index 000000000..61246e44e --- /dev/null +++ b/tests/ui/consts/const-vec-syntax.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f(_: &[isize]) {} + +pub fn main() { + let v = [ 1, 2, 3 ]; + f(&v); +} diff --git a/tests/ui/consts/const-vecs-and-slices.rs b/tests/ui/consts/const-vecs-and-slices.rs new file mode 100644 index 000000000..1cdc33b7a --- /dev/null +++ b/tests/ui/consts/const-vecs-and-slices.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(non_upper_case_globals)] + +static x : [isize; 4] = [1,2,3,4]; +static y : &'static [isize] = &[1,2,3,4]; +static z : &'static [isize; 4] = &[1,2,3,4]; +static zz : &'static [isize] = &[1,2,3,4]; + +pub fn main() { + println!("{}", x[1]); + println!("{}", y[1]); + println!("{}", z[1]); + println!("{}", zz[1]); + assert_eq!(x[1], 2); + assert_eq!(x[3], 4); + assert_eq!(x[3], y[3]); + assert_eq!(z[1], 2); + assert_eq!(z[3], 4); + assert_eq!(z[3], y[3]); + assert_eq!(zz[1], 2); + assert_eq!(zz[3], 4); + assert_eq!(zz[3], y[3]); +} diff --git a/tests/ui/consts/const.rs b/tests/ui/consts/const.rs new file mode 100644 index 000000000..71fbadfa8 --- /dev/null +++ b/tests/ui/consts/const.rs @@ -0,0 +1,6 @@ +// run-pass +#![allow(non_upper_case_globals)] + +static i: isize = 10; + +pub fn main() { println!("{}", i); } diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs new file mode 100644 index 000000000..f10d1c24f --- /dev/null +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -0,0 +1,12 @@ +// run-pass +#![feature(const_type_id)] +#![feature(const_trait_impl)] + +use std::any::TypeId; + +const fn main() { + assert!(TypeId::of::() == TypeId::of::()); + assert!(TypeId::of::<()>() != TypeId::of::()); + const _A: bool = TypeId::of::() < TypeId::of::(); + // can't assert `_A` because it is not deterministic +} diff --git a/tests/ui/consts/const_constructor/const-construct-call.rs b/tests/ui/consts/const_constructor/const-construct-call.rs new file mode 100644 index 000000000..cb735d7b3 --- /dev/null +++ b/tests/ui/consts/const_constructor/const-construct-call.rs @@ -0,0 +1,110 @@ +// Test that constructors are considered to be const fns + +// run-pass + +// Ctor(..) is transformed to Ctor { 0: ... } in THIR lowering, so directly +// calling constructors doesn't require them to be const. + +type ExternalType = std::panic::AssertUnwindSafe<(Option, Result)>; + +const fn call_external_constructors_in_local_vars() -> ExternalType { + let f = Some; + let g = Err; + let h = std::panic::AssertUnwindSafe; + let x = f(5); + let y = g(false); + let z = h((x, y)); + z +} + +const CALL_EXTERNAL_CONSTRUCTORS_IN_LOCAL_VARS: ExternalType = { + let f = Some; + let g = Err; + let h = std::panic::AssertUnwindSafe; + let x = f(5); + let y = g(false); + let z = h((x, y)); + z +}; + +const fn call_external_constructors_in_temps() -> ExternalType { + let x = { Some }(5); + let y = (*&Err)(false); + let z = [std::panic::AssertUnwindSafe][0]((x, y)); + z +} + +const CALL_EXTERNAL_CONSTRUCTORS_IN_TEMPS: ExternalType = { + let x = { Some }(5); + let y = (*&Err)(false); + let z = [std::panic::AssertUnwindSafe][0]((x, y)); + z +}; + +#[derive(Debug, PartialEq)] +enum LocalOption { + Some(T), + _None, +} + +#[derive(Debug, PartialEq)] +enum LocalResult { + _Ok(T), + Err(E), +} + +#[derive(Debug, PartialEq)] +struct LocalAssertUnwindSafe(T); + +type LocalType = LocalAssertUnwindSafe<(LocalOption, LocalResult)>; + +const fn call_local_constructors_in_local_vars() -> LocalType { + let f = LocalOption::Some; + let g = LocalResult::Err; + let h = LocalAssertUnwindSafe; + let x = f(5); + let y = g(false); + let z = h((x, y)); + z +} + +const CALL_LOCAL_CONSTRUCTORS_IN_LOCAL_VARS: LocalType = { + let f = LocalOption::Some; + let g = LocalResult::Err; + let h = LocalAssertUnwindSafe; + let x = f(5); + let y = g(false); + let z = h((x, y)); + z +}; + +const fn call_local_constructors_in_temps() -> LocalType { + let x = { LocalOption::Some }(5); + let y = (*&LocalResult::Err)(false); + let z = [LocalAssertUnwindSafe][0]((x, y)); + z +} + +const CALL_LOCAL_CONSTRUCTORS_IN_TEMPS: LocalType = { + let x = { LocalOption::Some }(5); + let y = (*&LocalResult::Err)(false); + let z = [LocalAssertUnwindSafe][0]((x, y)); + z +}; + +fn main() { + assert_eq!( + ( + call_external_constructors_in_local_vars().0, + call_external_constructors_in_temps().0, + call_local_constructors_in_local_vars(), + call_local_constructors_in_temps(), + ), + ( + CALL_EXTERNAL_CONSTRUCTORS_IN_LOCAL_VARS.0, + CALL_EXTERNAL_CONSTRUCTORS_IN_TEMPS.0, + CALL_LOCAL_CONSTRUCTORS_IN_LOCAL_VARS, + CALL_LOCAL_CONSTRUCTORS_IN_TEMPS, + ) + ); +} diff --git a/tests/ui/consts/const_constructor/const_constructor_qpath.rs b/tests/ui/consts/const_constructor/const_constructor_qpath.rs new file mode 100644 index 000000000..7c55f470f --- /dev/null +++ b/tests/ui/consts/const_constructor/const_constructor_qpath.rs @@ -0,0 +1,37 @@ +// run-pass + +trait ConstDefault { + const DEFAULT: Self; +} + +#[derive(PartialEq)] +enum E { + V(i32), + W(usize), +} + +impl ConstDefault for E { + const DEFAULT: Self = Self::V(23); +} + +impl ConstDefault for Option { + const DEFAULT: Self = Self::Some(23); +} + +impl E { + const NON_DEFAULT: Self = Self::W(12); + const fn local_fn() -> Self { + Self::V(23) + } +} + +const fn explicit_qpath() -> E { + let _x = >::Some(23); + ::W(12) +} + +fn main() { + assert!(E::DEFAULT == E::local_fn()); + assert!(Option::DEFAULT == Some(23)); + assert!(E::NON_DEFAULT == explicit_qpath()); +} diff --git a/tests/ui/consts/const_discriminant.rs b/tests/ui/consts/const_discriminant.rs new file mode 100644 index 000000000..79e68590e --- /dev/null +++ b/tests/ui/consts/const_discriminant.rs @@ -0,0 +1,42 @@ +// run-pass +#![feature(const_discriminant)] +#![allow(dead_code)] + +use std::mem::{discriminant, Discriminant}; +use std::hint::black_box; + +enum Test { + A(u8), + B, + C { a: u8, b: u8 }, +} + +const TEST_A: Discriminant = discriminant(&Test::A(5)); +const TEST_A_OTHER: Discriminant = discriminant(&Test::A(17)); +const TEST_B: Discriminant = discriminant(&Test::B); + +enum Void {} + +enum SingleVariant { + V, + Never(Void), +} + +const TEST_V: Discriminant = discriminant(&SingleVariant::V); + +pub const TEST_VOID: () = { + // This is UB, but CTFE does not check validity so it does not detect this. + // This is a regression test for https://github.com/rust-lang/rust/issues/89765. + unsafe { std::mem::discriminant(&*(&() as *const () as *const Void)); }; +}; + + +fn main() { + assert_eq!(TEST_A, TEST_A_OTHER); + assert_eq!(TEST_A, discriminant(black_box(&Test::A(17)))); + assert_eq!(TEST_B, discriminant(black_box(&Test::B))); + assert_ne!(TEST_A, TEST_B); + assert_ne!(TEST_B, discriminant(black_box(&Test::C { a: 42, b: 7 }))); + + assert_eq!(TEST_V, discriminant(black_box(&SingleVariant::V))); +} diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr b/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr new file mode 100644 index 000000000..ae24f8f65 --- /dev/null +++ b/tests/ui/consts/const_fn_floating_point_arithmetic.gated.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/const_fn_floating_point_arithmetic.rs:20:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.rs b/tests/ui/consts/const_fn_floating_point_arithmetic.rs new file mode 100644 index 000000000..5e32482b2 --- /dev/null +++ b/tests/ui/consts/const_fn_floating_point_arithmetic.rs @@ -0,0 +1,20 @@ +// gate-test-const_fn_floating_point_arithmetic + +// revisions: stock gated + +#![feature(rustc_attrs)] +#![cfg_attr(gated, feature(const_fn_floating_point_arithmetic))] + +const fn add(f: f32) -> f32 { f + 2.0 } +//[stock]~^ floating point arithmetic +const fn sub(f: f32) -> f32 { 2.0 - f } +//[stock]~^ floating point arithmetic +const fn mul(f: f32, g: f32) -> f32 { f * g } +//[stock]~^ floating point arithmetic +const fn div(f: f32, g: f32) -> f32 { f / g } +//[stock]~^ floating point arithmetic +const fn neg(f: f32) -> f32 { -f } +//[stock]~^ floating point arithmetic + +#[rustc_error] +fn main() {} //[gated]~ fatal error triggered by #[rustc_error] diff --git a/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr b/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr new file mode 100644 index 000000000..ef7a60faf --- /dev/null +++ b/tests/ui/consts/const_fn_floating_point_arithmetic.stock.stderr @@ -0,0 +1,48 @@ +error[E0658]: floating point arithmetic is not allowed in constant functions + --> $DIR/const_fn_floating_point_arithmetic.rs:8:31 + | +LL | const fn add(f: f32) -> f32 { f + 2.0 } + | ^^^^^^^ + | + = note: see issue #57241 for more information + = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable + +error[E0658]: floating point arithmetic is not allowed in constant functions + --> $DIR/const_fn_floating_point_arithmetic.rs:10:31 + | +LL | const fn sub(f: f32) -> f32 { 2.0 - f } + | ^^^^^^^ + | + = note: see issue #57241 for more information + = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable + +error[E0658]: floating point arithmetic is not allowed in constant functions + --> $DIR/const_fn_floating_point_arithmetic.rs:12:39 + | +LL | const fn mul(f: f32, g: f32) -> f32 { f * g } + | ^^^^^ + | + = note: see issue #57241 for more information + = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable + +error[E0658]: floating point arithmetic is not allowed in constant functions + --> $DIR/const_fn_floating_point_arithmetic.rs:14:39 + | +LL | const fn div(f: f32, g: f32) -> f32 { f / g } + | ^^^^^ + | + = note: see issue #57241 for more information + = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable + +error[E0658]: floating point arithmetic is not allowed in constant functions + --> $DIR/const_fn_floating_point_arithmetic.rs:16:31 + | +LL | const fn neg(f: f32) -> f32 { -f } + | ^^ + | + = note: see issue #57241 for more information + = help: add `#![feature(const_fn_floating_point_arithmetic)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_fn_return_nested_fn_ptr.rs b/tests/ui/consts/const_fn_return_nested_fn_ptr.rs new file mode 100644 index 000000000..d22c78960 --- /dev/null +++ b/tests/ui/consts/const_fn_return_nested_fn_ptr.rs @@ -0,0 +1,10 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:const_fn_lib.rs + +extern crate const_fn_lib; + +fn main() { + const_fn_lib::bar()(); + const_fn_lib::bar_inlined()(); + const_fn_lib::bar_inlined_always()(); +} diff --git a/tests/ui/consts/const_fn_unsize.rs b/tests/ui/consts/const_fn_unsize.rs new file mode 100644 index 000000000..01da57320 --- /dev/null +++ b/tests/ui/consts/const_fn_unsize.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(slice_ptr_len)] + +use std::ptr::NonNull; + +#[allow(unused)] +const fn test() { + let _x = NonNull::<[i32; 0]>::dangling() as NonNull<[i32]>; +} + +// Regression test for #75118. +pub const fn dangling_slice() -> NonNull<[T]> { + NonNull::<[T; 1]>::dangling() +} + +const C: NonNull<[i32]> = dangling_slice(); + +fn main() { + assert_eq!(C.as_ptr(), NonNull::<[i32; 1]>::dangling().as_ptr() as *mut _); + assert_eq!(C.as_ptr().len(), 1); +} diff --git a/tests/ui/consts/const_forget.rs b/tests/ui/consts/const_forget.rs new file mode 100644 index 000000000..ec7dde8c9 --- /dev/null +++ b/tests/ui/consts/const_forget.rs @@ -0,0 +1,20 @@ +// check-pass + +use std::mem::forget; + +const _: () = forget(0i32); +const _: () = forget(Vec::>>::new()); + +// Writing this function signature without const-forget +// triggers compiler errors: +// 1) That we use a non-const fn inside a const fn +// 2) without the forget, it complains about the destructor of Box +// +// FIXME: this method cannot be called in const-eval yet, as Box isn't +// const constructable +#[allow(unused)] +const fn const_forget_box(b: Box) { + forget(b); +} + +fn main() {} diff --git a/tests/ui/consts/const_in_pattern/accept_structural.rs b/tests/ui/consts/const_in_pattern/accept_structural.rs new file mode 100644 index 000000000..1f56f581c --- /dev/null +++ b/tests/ui/consts/const_in_pattern/accept_structural.rs @@ -0,0 +1,66 @@ +// run-pass + +#![warn(indirect_structural_match)] + +// This test is checking our logic for structural match checking by enumerating +// the different kinds of const expressions. This test is collecting cases where +// we have accepted the const expression as a pattern in the past and wish to +// continue doing so. +// +// Even if a non-structural-match type is part of an expression in a const's +// definition, that does not necessarily disqualify the const from being a match +// pattern: in principle, we just need the types involved in the final value to +// be structurally matchable. + +// See also RFC 1445 + +#![feature(type_ascription)] + +#[derive(Copy, Clone, Debug)] +struct NoPartialEq(u32); + +#[derive(Copy, Clone, Debug)] +struct NoDerive(u32); + +// This impl makes `NoDerive` irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } +impl Eq for NoDerive { } + +type OND = Option; + +fn main() { + const FIELD1: u32 = NoPartialEq(1).0; + match 1 { FIELD1 => dbg!(FIELD1), _ => panic!("whoops"), }; + const FIELD2: u32 = NoDerive(1).0; + match 1 { FIELD2 => dbg!(FIELD2), _ => panic!("whoops"), }; + + enum CLike { One = 1, #[allow(dead_code)] Two = 2, } + const ONE_CAST: u32 = CLike::One as u32; + match 1 { ONE_CAST => dbg!(ONE_CAST), _ => panic!("whoops"), }; + + const NO_DERIVE_NONE: OND = None; + const INDIRECT: OND = NO_DERIVE_NONE; + match None { INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; + + const TUPLE: (OND, OND) = (None, None); + match (None, None) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; + + const TYPE_ASCRIPTION: OND = type_ascribe!(None, OND); + match None { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; + + const ARRAY: [OND; 2] = [None, None]; + match [None; 2] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; + + const REPEAT: [OND; 2] = [None; 2]; + match [None, None] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; + + trait Trait: Sized { const ASSOC: Option; } + impl Trait for NoDerive { const ASSOC: Option = None; } + match None { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; + + const BLOCK: OND = { NoDerive(10); None }; + match None { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; + + const ADDR_OF: &OND = &None; + match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; +} diff --git a/tests/ui/consts/const_in_pattern/auxiliary/consts.rs b/tests/ui/consts/const_in_pattern/auxiliary/consts.rs new file mode 100644 index 000000000..b438bcd9f --- /dev/null +++ b/tests/ui/consts/const_in_pattern/auxiliary/consts.rs @@ -0,0 +1,16 @@ +pub struct CustomEq; + +impl Eq for CustomEq {} +impl PartialEq for CustomEq { + fn eq(&self, _: &Self) -> bool { + false + } +} + +pub const NONE: Option = None; +pub const SOME: Option = Some(CustomEq); + +pub trait AssocConst { + const NONE: Option = None; + const SOME: Option = Some(CustomEq); +} diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.rs b/tests/ui/consts/const_in_pattern/cross-crate-fail.rs new file mode 100644 index 000000000..ab297f54d --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.rs @@ -0,0 +1,25 @@ +// aux-build:consts.rs + +#![warn(indirect_structural_match)] + +extern crate consts; + +struct Defaulted; +impl consts::AssocConst for Defaulted {} + +fn main() { + let _ = Defaulted; + match None { + consts::SOME => panic!(), + //~^ must be annotated with `#[derive(PartialEq, Eq)]` + + _ => {} + } + + match None { + ::SOME => panic!(), + //~^ must be annotated with `#[derive(PartialEq, Eq)]` + + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr new file mode 100644 index 000000000..a8066a88c --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cross-crate-fail.stderr @@ -0,0 +1,14 @@ +error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cross-crate-fail.rs:13:9 + | +LL | consts::SOME => panic!(), + | ^^^^^^^^^^^^ + +error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cross-crate-fail.rs:20:9 + | +LL | ::SOME => panic!(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/const_in_pattern/cross-crate-pass.rs b/tests/ui/consts/const_in_pattern/cross-crate-pass.rs new file mode 100644 index 000000000..1d8ecf8ae --- /dev/null +++ b/tests/ui/consts/const_in_pattern/cross-crate-pass.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:consts.rs + +#![warn(indirect_structural_match)] + +extern crate consts; +use consts::CustomEq; + +struct Defaulted; +impl consts::AssocConst for Defaulted {} + +fn main() { + let _ = Defaulted; + match Some(CustomEq) { + consts::NONE => panic!(), + _ => {} + } + + match Some(CustomEq) { + ::NONE => panic!(), + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs new file mode 100644 index 000000000..a38731ceb --- /dev/null +++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs @@ -0,0 +1,32 @@ +// run-pass + +#![warn(indirect_structural_match)] + +struct CustomEq; + +impl Eq for CustomEq {} +impl PartialEq for CustomEq { + fn eq(&self, _: &Self) -> bool { + false + } +} + +#[derive(PartialEq, Eq)] +enum Foo { + Bar, + Baz, + Qux(CustomEq), +} + +const BAR_BAZ: Foo = if 42 == 42 { + Foo::Bar +} else { + Foo::Baz +}; + +fn main() { + match Foo::Qux(CustomEq) { + BAR_BAZ => panic!(), + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs new file mode 100644 index 000000000..856d20417 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs @@ -0,0 +1,36 @@ +// check-pass + +struct CustomEq; + +impl Eq for CustomEq {} +impl PartialEq for CustomEq { + fn eq(&self, _: &Self) -> bool { + false + } +} + +#[derive(PartialEq, Eq)] +enum Foo { + Bar, + Baz, + Qux(CustomEq), +} + +// We know that `BAR_BAZ` will always be `Foo::Bar` and thus eligible for structural matching, but +// dataflow will be more conservative. +const BAR_BAZ: Foo = if 42 == 42 { + Foo::Bar +} else { + Foo::Qux(CustomEq) +}; + +fn main() { + match Foo::Qux(CustomEq) { + BAR_BAZ => panic!(), + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + //~| NOTE see issue #73448 + //~| NOTE `#[warn(nontrivial_structural_match)]` on by default + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr new file mode 100644 index 000000000..223482722 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr @@ -0,0 +1,12 @@ +warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/custom-eq-branch-warn.rs:29:9 + | +LL | BAR_BAZ => panic!(), + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73448 + = note: `#[warn(nontrivial_structural_match)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const_in_pattern/incomplete-slice.rs b/tests/ui/consts/const_in_pattern/incomplete-slice.rs new file mode 100644 index 000000000..e1ccda71d --- /dev/null +++ b/tests/ui/consts/const_in_pattern/incomplete-slice.rs @@ -0,0 +1,15 @@ +#[derive(PartialEq)] +enum E { + A, +} + +const E_SL: &[E] = &[E::A]; + +fn main() { + match &[][..] { + //~^ ERROR non-exhaustive patterns: `&_` not covered [E0004] + E_SL => {} + //~^ WARN to use a constant of type `E` in a pattern, `E` must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted by the compiler but is being phased out + } +} diff --git a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr new file mode 100644 index 000000000..ddc576ced --- /dev/null +++ b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr @@ -0,0 +1,26 @@ +warning: to use a constant of type `E` in a pattern, `E` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/incomplete-slice.rs:11:9 + | +LL | E_SL => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(indirect_structural_match)]` on by default + +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/incomplete-slice.rs:9:11 + | +LL | match &[][..] { + | ^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&[E]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ E_SL => {} +LL + &_ => todo!() + | + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/consts/const_in_pattern/issue-44333.rs b/tests/ui/consts/const_in_pattern/issue-44333.rs new file mode 100644 index 000000000..96e8795e5 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-44333.rs @@ -0,0 +1,25 @@ +// run-pass + +#![warn(pointer_structural_match)] + +type Func = fn(usize, usize) -> usize; + +fn foo(a: usize, b: usize) -> usize { a + b } +fn bar(a: usize, b: usize) -> usize { a * b } +fn test(x: usize) -> Func { + if x % 2 == 0 { foo } + else { bar } +} + +const FOO: Func = foo; +const BAR: Func = bar; + +fn main() { + match test(std::env::consts::ARCH.len()) { + FOO => println!("foo"), //~ WARN pointers in patterns behave unpredictably + //~^ WARN will become a hard error + BAR => println!("bar"), //~ WARN pointers in patterns behave unpredictably + //~^ WARN will become a hard error + _ => unreachable!(), + } +} diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr new file mode 100644 index 000000000..731ef509c --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -0,0 +1,25 @@ +warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:19:9 + | +LL | FOO => println!("foo"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:21:9 + | +LL | BAR => println!("bar"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 2 warnings emitted + diff --git a/tests/ui/consts/const_in_pattern/issue-53708.rs b/tests/ui/consts/const_in_pattern/issue-53708.rs new file mode 100644 index 000000000..355ba6379 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-53708.rs @@ -0,0 +1,11 @@ +// check-pass +// https://github.com/rust-lang/rust/issues/53708 +#[derive(PartialEq, Eq)] +struct S; + +fn main() { + const C: &S = &S; + match C { + C => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/issue-62614.rs b/tests/ui/consts/const_in_pattern/issue-62614.rs new file mode 100644 index 000000000..4ea9a2836 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-62614.rs @@ -0,0 +1,24 @@ +// run-pass + +struct Sum(u32, u32); + +impl PartialEq for Sum { + fn eq(&self, other: &Self) -> bool { self.0 + self.1 == other.0 + other.1 } +} + +impl Eq for Sum { } + +#[derive(PartialEq, Eq)] +enum Eek { + TheConst, + UnusedByTheConst(Sum) +} + +const THE_CONST: Eek = Eek::TheConst; + +pub fn main() { + match Eek::UnusedByTheConst(Sum(1,2)) { + THE_CONST => { panic!(); } + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs new file mode 100644 index 000000000..2b421f4c7 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-65466.rs @@ -0,0 +1,21 @@ +#![deny(indirect_structural_match)] + +// check-pass + +#[derive(PartialEq, Eq)] +enum O { + Some(*const T), // Can also use PhantomData + None, +} + +struct B; + +const C: &[O] = &[O::None]; + +fn main() { + let x = O::None; + match &[x][..] { + C => (), + _ => (), + } +} diff --git a/tests/ui/consts/const_in_pattern/issue-73431.rs b/tests/ui/consts/const_in_pattern/issue-73431.rs new file mode 100644 index 000000000..fa18a3af1 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-73431.rs @@ -0,0 +1,29 @@ +// run-pass + +// Regression test for https://github.com/rust-lang/rust/issues/73431. + +pub trait Zero { + const ZERO: Self; +} + +impl Zero for usize { + const ZERO: Self = 0; +} + +impl Zero for Wrapper { + const ZERO: Self = Wrapper(T::ZERO); +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Wrapper(T); + +fn is_zero(x: Wrapper) -> bool { + match x { + Zero::ZERO => true, + _ => false, + } +} + +fn main() { + let _ = is_zero(Wrapper(42)); +} diff --git a/tests/ui/consts/const_in_pattern/issue-73431.stderr b/tests/ui/consts/const_in_pattern/issue-73431.stderr new file mode 100644 index 000000000..c82dea4aa --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-73431.stderr @@ -0,0 +1 @@ +WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448. diff --git a/tests/ui/consts/const_in_pattern/issue-78057.rs b/tests/ui/consts/const_in_pattern/issue-78057.rs new file mode 100644 index 000000000..69cf8404d --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-78057.rs @@ -0,0 +1,17 @@ +#![deny(unreachable_patterns)] + +#[derive(PartialEq)] +struct Opaque(i32); + +impl Eq for Opaque {} + +const FOO: Opaque = Opaque(42); + +fn main() { + match FOO { + FOO => {}, + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => {} + //~^ ERROR unreachable pattern + } +} diff --git a/tests/ui/consts/const_in_pattern/issue-78057.stderr b/tests/ui/consts/const_in_pattern/issue-78057.stderr new file mode 100644 index 000000000..35619594f --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-78057.stderr @@ -0,0 +1,23 @@ +error: to use a constant of type `Opaque` in a pattern, `Opaque` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/issue-78057.rs:12:9 + | +LL | FOO => {}, + | ^^^ + +error: unreachable pattern + --> $DIR/issue-78057.rs:14:9 + | +LL | FOO => {}, + | --- matches any value +LL | +LL | _ => {} + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/issue-78057.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs new file mode 100644 index 000000000..fc80d51c7 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.rs @@ -0,0 +1,25 @@ +#![warn(indirect_structural_match)] + +struct NoEq; + +enum Foo { + Bar, + Baz, + Qux(NoEq), +} + +// Even though any of these values can be compared structurally, we still disallow it in a pattern +// because `Foo` does not impl `PartialEq`. +const BAR_BAZ: Foo = if 42 == 42 { + Foo::Baz +} else { + Foo::Bar +}; + +fn main() { + match Foo::Qux(NoEq) { + BAR_BAZ => panic!(), + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => {} + } +} diff --git a/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr new file mode 100644 index 000000000..e505dad69 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/no-eq-branch-fail.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/no-eq-branch-fail.rs:21:9 + | +LL | BAR_BAZ => panic!(), + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs new file mode 100644 index 000000000..a8216901c --- /dev/null +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.rs @@ -0,0 +1,32 @@ +// This test is illustrating the difference between how failing to derive +// `PartialEq` is handled compared to failing to implement it at all. + +// See also RFC 1445 + +#[derive(PartialEq, Eq)] +struct Structural(u32); + +struct NoPartialEq(u32); + +struct NoDerive(u32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +const NO_DERIVE_NONE: Option = None; +const NO_PARTIAL_EQ_NONE: Option = None; + +fn main() { + match None { + NO_DERIVE_NONE => println!("NO_DERIVE_NONE"), + _ => panic!("whoops"), + } + + match None { + NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => panic!("whoops"), + } +} diff --git a/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr new file mode 100644 index 000000000..95cfa4a9e --- /dev/null +++ b/tests/ui/consts/const_in_pattern/reject_non_partial_eq.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `NoPartialEq` in a pattern, `NoPartialEq` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_partial_eq.rs:28:9 + | +LL | NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"), + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs new file mode 100644 index 000000000..75fde0d92 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -0,0 +1,83 @@ +// This test of structural match checking enumerates the different kinds of +// const definitions, collecting cases where the const pattern is rejected. +// +// Note: Even if a non-structural-match type is part of an expression in a +// const's definition, that does not necessarily disqualify the const from being +// a match pattern: in principle, we just need the types involved in the final +// value to be structurally matchable. + +// See also RFC 1445 + +#![feature(type_ascription)] +#![warn(indirect_structural_match)] +//~^ NOTE lint level is defined here + +#[derive(Copy, Clone, Debug)] +struct NoPartialEq; + +#[derive(Copy, Clone, Debug)] +struct NoDerive; + +// This impl makes `NoDerive` irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +type OND = Option; + +struct TrivialEq(OND); + +// This impl makes `TrivialEq` trivial. +impl PartialEq for TrivialEq { fn eq(&self, _: &Self) -> bool { true } } + +impl Eq for TrivialEq { } + +fn main() { + #[derive(PartialEq, Eq, Debug)] + enum Derive { Some(X), None, } + + const ENUM: Derive = Derive::Some(NoDerive); + match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const FIELD: OND = TrivialEq(Some(NoDerive)).0; + match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const NO_DERIVE_SOME: OND = Some(NoDerive); + const INDIRECT: OND = NO_DERIVE_SOME; + match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const TUPLE: (OND, OND) = (None, Some(NoDerive)); + match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const TYPE_ASCRIPTION: OND = type_ascribe!(Some(NoDerive), OND); + match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const ARRAY: [OND; 2] = [None, Some(NoDerive)]; + match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const REPEAT: [OND; 2] = [Some(NoDerive); 2]; + match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + trait Trait: Sized { const ASSOC: Option; } + impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } + match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const BLOCK: OND = { NoDerive; Some(NoDerive) }; + match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + + const ADDR_OF: &OND = &Some(NoDerive); + match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN previously accepted by the compiler but is being phased out + //~| NOTE for more information, see issue #62411 +} diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr new file mode 100644 index 000000000..660198349 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -0,0 +1,76 @@ +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:40:36 + | +LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), }; + | ^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:44:28 + | +LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), }; + | ^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:49:27 + | +LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), }; + | ^^^^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:53:36 + | +LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), }; + | ^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:57:28 + | +LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), }; + | ^^^^^^^^^^^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:61:36 + | +LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), }; + | ^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:65:33 + | +LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; + | ^^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:65:33 + | +LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), }; + | ^^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:71:28 + | +LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; + | ^^^^^^^^^^^^^^^ + +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:75:28 + | +LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), }; + | ^^^^^ + +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/reject_non_structural.rs:79:29 + | +LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/reject_non_structural.rs:12:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors; 1 warning emitted + diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs b/tests/ui/consts/const_in_pattern/warn_corner_cases.rs new file mode 100644 index 000000000..15cf3c84d --- /dev/null +++ b/tests/ui/consts/const_in_pattern/warn_corner_cases.rs @@ -0,0 +1,41 @@ +// run-pass + +// This test is checking our logic for structural match checking by enumerating +// the different kinds of const expressions. This test is collecting cases where +// we have accepted the const expression as a pattern in the past but we want +// to begin warning the user that a future version of Rust may start rejecting +// such const expressions. + +// The specific corner cases we are exploring here are instances where the +// const-evaluator computes a value that *does* meet the conditions for +// structural-match, but the const expression itself has abstractions (like +// calls to const functions) that may fit better with a type-based analysis +// rather than a commitment to a specific value. + +#![warn(indirect_structural_match)] + +#[derive(Copy, Clone, Debug)] +struct NoDerive(#[allow(unused_tuple_struct_fields)] u32); + +// This impl makes `NoDerive` irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } +impl Eq for NoDerive { } + +fn main() { + const INDEX: Option = [None, Some(NoDerive(10))][0]; + match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + + const fn build() -> Option { None } + const CALL: Option = build(); + match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + + impl NoDerive { const fn none() -> Option { None } } + const METHOD_CALL: Option = NoDerive::none(); + match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted +} diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr b/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr new file mode 100644 index 000000000..e957a43a1 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr @@ -0,0 +1,30 @@ +warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/warn_corner_cases.rs:26:47 + | +LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73448 + = note: `#[warn(nontrivial_structural_match)]` on by default + +warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/warn_corner_cases.rs:32:47 + | +LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73448 + +warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/warn_corner_cases.rs:38:47 + | +LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73448 + +warning: 3 warnings emitted + diff --git a/tests/ui/consts/const_let_assign.rs b/tests/ui/consts/const_let_assign.rs new file mode 100644 index 000000000..b83acfb73 --- /dev/null +++ b/tests/ui/consts/const_let_assign.rs @@ -0,0 +1,10 @@ +// check-pass + +struct S(i32); + +const A: () = { + let mut s = S(0); + s.0 = 1; +}; + +fn main() {} diff --git a/tests/ui/consts/const_let_assign2.rs b/tests/ui/consts/const_let_assign2.rs new file mode 100644 index 000000000..28265c85d --- /dev/null +++ b/tests/ui/consts/const_let_assign2.rs @@ -0,0 +1,22 @@ +// check-pass + +pub struct AA { + pub data: [u8; 10], +} + +impl AA { + pub const fn new() -> Self { + let mut res: AA = AA { data: [0; 10] }; + res.data[0] = 5; + res + } +} + +static mut BB: AA = AA::new(); + +fn main() { + let ptr = unsafe { &mut BB }; + for a in ptr.data.iter() { + println!("{}", a); + } +} diff --git a/tests/ui/consts/const_let_assign3.rs b/tests/ui/consts/const_let_assign3.rs new file mode 100644 index 000000000..1f68de8ee --- /dev/null +++ b/tests/ui/consts/const_let_assign3.rs @@ -0,0 +1,27 @@ +struct S { + state: u32, +} + +impl S { + const fn foo(&mut self, x: u32) { + //~^ ERROR mutable reference + self.state = x; + } +} + +const FOO: S = { + let mut s = S { state: 42 }; + s.foo(3); //~ ERROR mutable reference + s +}; + +type Array = [u32; { + let mut x = 2; + let y = &mut x; //~ ERROR mutable reference + *y = 42; + *y +}]; + +fn main() { + assert_eq!(FOO.state, 3); +} diff --git a/tests/ui/consts/const_let_assign3.stderr b/tests/ui/consts/const_let_assign3.stderr new file mode 100644 index 000000000..b550ac545 --- /dev/null +++ b/tests/ui/consts/const_let_assign3.stderr @@ -0,0 +1,30 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/const_let_assign3.rs:6:18 + | +LL | const fn foo(&mut self, x: u32) { + | ^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/const_let_assign3.rs:14:5 + | +LL | s.foo(3); + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/const_let_assign3.rs:20:13 + | +LL | let y = &mut x; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_let_eq.rs b/tests/ui/consts/const_let_eq.rs new file mode 100644 index 000000000..818819f9f --- /dev/null +++ b/tests/ui/consts/const_let_eq.rs @@ -0,0 +1,469 @@ +// run-pass + +struct Foo(T); +struct Bar { x: T } +struct W(u32); +struct A { a: u32 } + +#[allow(redundant_semicolons)] +const fn basics((a,): (u32,)) -> u32 { + // Deferred assignment: + let b: u32; + b = a + 1; + + // Immediate assignment: + let c: u32 = b + 1; + + // Mutables: + let mut d: u32 = c + 1; + d = d + 1; + // +4 so far. + + // No effect statements work: + ; ; + 1; + + // Array projection + let mut arr: [u32; 1] = [0]; + arr[0] = 1; + d = d + arr[0]; + // +5 + + // Field projection: + let mut foo: Foo = Foo(0); + let mut bar: Bar = Bar { x: 0 }; + foo.0 = 1; + bar.x = 1; + d = d + foo.0 + bar.x; + // +7 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0)]; + arr[0].0 = 1; + d = d + arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0 }]; + arr[0].x = 1; + d = d + arr[0].x; + // +9 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([0]); + (arr.0)[0] = 1; + d = d + (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [0] }; + arr.x[0] = 1; + d = d + arr.x[0]; + // +11 + + d +} + +const fn add_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a + 1; + d += 1; + // +2 so far. + + // Array projection + let mut arr: [u32; 1] = [0]; + arr[0] += 1; + d += arr[0]; + // +3 + + // Field projection: + let mut foo: Foo = Foo(0); + let mut bar: Bar = Bar { x: 0 }; + foo.0 += 1; + bar.x += 1; + d += foo.0 + bar.x; + // +5 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0)]; + arr[0].0 += 1; + d += arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0 }]; + arr[0].x += 1; + d += arr[0].x; + // +7 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([0]); + (arr.0)[0] += 1; + d += (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [0] }; + arr.x[0] += 1; + d += arr.x[0]; + // +9 + + d +} + +const fn mul_assign(A { a }: A) -> u32 { + // Mutables: + let mut d: u32 = a + 1; + d *= 2; + // 2^1 * (a + 1) + + // Array projection + let mut arr: [u32; 1] = [1]; + arr[0] *= 2; + d *= arr[0]; + // 2^2 * (a + 1) + + // Field projection: + let mut foo: Foo = Foo(1); + let mut bar: Bar = Bar { x: 1 }; + foo.0 *= 2; + bar.x *= 2; + d *= foo.0 + bar.x; + // 2^4 * (a + 1) + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(1)]; + arr[0].0 *= 2; + d *= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 1 }]; + arr[0].x *= 2; + d *= arr[0].x; + // 2^6 * (a + 1) + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([1]); + (arr.0)[0] *= 2; + d *= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [1] }; + arr.x[0] *= 2; + d *= arr.x[0]; + // 2^8 * (a + 1) + + d +} + +const fn div_assign(a: [u32; 1]) -> u32 { + let a = a[0]; + // Mutables: + let mut d: u32 = 1024 * a; + d /= 2; + // 512 + + // Array projection + let mut arr: [u32; 1] = [4]; + arr[0] /= 2; + d /= arr[0]; + // 256 + + // Field projection: + let mut foo: Foo = Foo(4); + let mut bar: Bar = Bar { x: 4 }; + foo.0 /= 2; + bar.x /= 2; + d /= foo.0; + d /= bar.x; + // 64 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4)]; + arr[0].0 /= 2; + d /= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 4 }]; + arr[0].x /= 2; + d /= arr[0].x; + // 16 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([4]); + (arr.0)[0] /= 2; + d /= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [4] }; + arr.x[0] /= 2; + d /= arr.x[0]; + // 4 + + d +} + +const fn rem_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d %= 10; + d += 10; + + // Array projection + let mut arr: [u32; 1] = [3]; + arr[0] %= 2; + d %= 9 + arr[0]; + d += 10; + + // Field projection: + let mut foo: Foo = Foo(5); + let mut bar: Bar = Bar { x: 7 }; + foo.0 %= 2; + bar.x %= 2; + d %= 8 + foo.0 + bar.x; + d += 10; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4)]; + arr[0].0 %= 3; + d %= 9 + arr[0].0; + d += 10; + let mut arr: [Bar; 1] = [Bar { x: 7 }]; + arr[0].x %= 3; + d %= 9 + arr[0].x; + d += 10; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([6]); + (arr.0)[0] %= 5; + d %= 9 + (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [11] }; + arr.x[0] %= 5; + d %= 9 + arr.x[0]; + + d +} + +const fn sub_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d -= 1; + + // Array projection + let mut arr: [u32; 1] = [2]; + arr[0] -= 1; + d -= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(2); + let mut bar: Bar = Bar { x: 2 }; + foo.0 -= 1; + bar.x -= 1; + d -= foo.0 + bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(2)]; + arr[0].0 -= 1; + d -= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 2 }]; + arr[0].x -= 1; + d -= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([2]); + (arr.0)[0] -= 1; + d -= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [2] }; + arr.x[0] -= 1; + d -= arr.x[0]; + + d +} + +const fn shl_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d <<= 1; // 10 + + // Array projection + let mut arr: [u32; 1] = [1]; + arr[0] <<= 1; + d <<= arr[0]; // 10 << 2 + + // Field projection: + let mut foo: Foo = Foo(1); + let mut bar: Bar = Bar { x: 1 }; + foo.0 <<= 1; + bar.x <<= 1; + d <<= foo.0 + bar.x; // 1000 << 4 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(1)]; + arr[0].0 <<= 1; + d <<= arr[0].0; // 1000_0000 << 2 + let mut arr: [Bar; 1] = [Bar { x: 1 }]; + arr[0].x <<= 1; + d <<= arr[0].x; // 1000_0000_00 << 2 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([1]); + (arr.0)[0] <<= 1; + d <<= (arr.0)[0]; // 1000_0000_0000 << 2 + let mut arr: Bar<[u32; 1]> = Bar { x: [1] }; + arr.x[0] <<= 1; + d <<= arr.x[0]; // 1000_0000_0000_00 << 2 + + d +} + +const fn shr_assign(W(a): W) -> u32 { + // Mutables: + let mut d: u32 = a; + d >>= 1; // /= 2 + + // Array projection + let mut arr: [u32; 1] = [2]; + arr[0] >>= 1; + d >>= arr[0]; // /= 4 + + // Field projection: + let mut foo: Foo = Foo(2); + let mut bar: Bar = Bar { x: 2 }; + foo.0 >>= 1; + bar.x >>= 1; + d >>= foo.0 + bar.x; // /= 16 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(2)]; + arr[0].0 >>= 1; + d >>= arr[0].0; // /= 32 + let mut arr: [Bar; 1] = [Bar { x: 2 }]; + arr[0].x >>= 1; + d >>= arr[0].x; // /= 64 + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([2]); + (arr.0)[0] >>= 1; + d >>= (arr.0)[0]; // /= 128 + let mut arr: Bar<[u32; 1]> = Bar { x: [2] }; + arr.x[0] >>= 1; + d >>= arr.x[0]; // /= 256 + + d +} + +const fn bit_and_assign(W(a): W) -> u32 { + let f = 0b1111_1111_1111_1111; + + // Mutables: + let mut d: u32 = a; + d &= 0b1111_1111_1111_1110; + + // Array projection + let mut arr: [u32; 1] = [f]; + arr[0] &= 0b1111_1111_1111_1101; + d &= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(f); + let mut bar: Bar = Bar { x: f }; + foo.0 &= 0b1111_1111_1111_0111; + bar.x &= 0b1111_1111_1101_1111; + d &= foo.0 & bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(f)]; + arr[0].0 &= 0b1111_1110_1111_1111; + d &= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: f }]; + arr[0].x &= 0b1111_1101_1111_1111; + d &= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([f]); + (arr.0)[0] &= 0b1011_1111_1111_1111; + d &= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [f] }; + arr.x[0] &= 0b0111_1111_1111_1111; + d &= arr.x[0]; + + d +} + +const fn bit_or_assign(W(a): W) -> u32 { + let f = 0b0000_0000_0000_0000; + + // Mutables: + let mut d: u32 = a; + d |= 0b0000_0000_0000_0001; + + // Array projection + let mut arr: [u32; 1] = [f]; + arr[0] |= 0b0000_0000_0000_1001; + d |= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(f); + let mut bar: Bar = Bar { x: f }; + foo.0 |= 0b0000_0000_0001_0000; + bar.x |= 0b0000_0000_0100_0000; + d |= foo.0 | bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(f)]; + arr[0].0 |= 0b0000_0001_0000_0000; + d |= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: f }]; + arr[0].x |= 0b0000_0010_0000_0000; + d |= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([f]); + (arr.0)[0] |= 0b1000_0000_0000_0000; + d |= (arr.0)[0]; // /= 128 + let mut arr: Bar<[u32; 1]> = Bar { x: [f] }; + arr.x[0] |= 0b1100_0000_0000_0000; + d |= arr.x[0]; // /= 256 + + d +} + +const fn bit_xor_assign(W(a): W) -> u32 { + let f = 0b0000_0000_0000_0000; + + // Mutables: + let mut d: u32 = a; + d ^= 0b0000_0000_0000_0001; + + // Array projection + let mut arr: [u32; 1] = [f]; + arr[0] ^= 0b0000_0000_0000_0010; + d ^= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(f); + let mut bar: Bar = Bar { x: f }; + foo.0 ^= 0b0000_0000_0001_0000; + bar.x ^= 0b0000_0000_1000_0000; + d ^= foo.0 ^ bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(f)]; + arr[0].0 ^= 0b0000_0001_0000_0000; + d ^= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: f }]; + arr[0].x ^= 0b0000_0010_0000_0000; + d ^= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[u32; 1]> = Foo([f]); + (arr.0)[0] ^= 0b0100_0000_0000_0000; + d ^= (arr.0)[0]; + let mut arr: Bar<[u32; 1]> = Bar { x: [f] }; + arr.x[0] ^= 0b1000_0000_0000_0000; + d ^= arr.x[0]; + + d +} + +macro_rules! test { + ($c:ident, $e:expr, $r:expr) => { + const $c: u32 = $e; + assert_eq!($c, $r); + assert_eq!($e, $r); + } +} + +fn main() { + test!(BASICS, basics((2,)), 13); + test!(ADD, add_assign(W(1)), 10); + test!(MUL, mul_assign(A { a: 0 }), 256); + test!(DIV, div_assign([1]), 4); + test!(REM, rem_assign(W(5)), 5); + test!(SUB, sub_assign(W(8)), 0); + test!(SHL, shl_assign(W(1)), 0b1000_0000_0000_0000); + test!(SHR, shr_assign(W(256)), 1); + test!(AND, bit_and_assign(W(0b1011_1111_1111_1111_1111)), 0b0011_1100_1101_0100); + test!(OR, bit_or_assign(W(0b1011_0000_0000_0000)), 0b1111_0011_0101_1001); + test!(XOR, bit_xor_assign(W(0b0000_0000_0000_0000)), 0b1100_0011_1001_0011); +} diff --git a/tests/ui/consts/const_let_eq_float.rs b/tests/ui/consts/const_let_eq_float.rs new file mode 100644 index 000000000..e15f4b804 --- /dev/null +++ b/tests/ui/consts/const_let_eq_float.rs @@ -0,0 +1,280 @@ +// run-pass + +#![feature(const_fn_floating_point_arithmetic)] + +struct Foo(T); +struct Bar { x: T } +struct W(f32); +struct A { a: f32 } + +#[allow(redundant_semicolons)] +const fn basics((a,): (f32,)) -> f32 { + // Deferred assignment: + let b: f32; + b = a + 1.0; + + // Immediate assignment: + let c: f32 = b + 1.0; + + // Mutables: + let mut d: f32 = c + 1.0; + d = d + 1.0; + // +4 so far. + + // No effect statements work: + ; ; + 1; + + // Array projection + let mut arr: [f32; 1] = [0.0]; + arr[0] = 1.0; + d = d + arr[0]; + // +5 + + // Field projection: + let mut foo: Foo = Foo(0.0); + let mut bar: Bar = Bar { x: 0.0 }; + foo.0 = 1.0; + bar.x = 1.0; + d = d + foo.0 + bar.x; + // +7 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0.0)]; + arr[0].0 = 1.0; + d = d + arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0.0 }]; + arr[0].x = 1.0; + d = d + arr[0].x; + // +9 + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([0.0]); + (arr.0)[0] = 1.0; + d = d + (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] }; + arr.x[0] = 1.0; + d = d + arr.x[0]; + // +11 + + d +} + +const fn add_assign(W(a): W) -> f32 { + // Mutables: + let mut d: f32 = a + 1.0; + d += 1.0; + // +2 so far. + + // Array projection + let mut arr: [f32; 1] = [0.0]; + arr[0] += 1.0; + d += arr[0]; + // +3 + + // Field projection: + let mut foo: Foo = Foo(0.0); + let mut bar: Bar = Bar { x: 0.0 }; + foo.0 += 1.0; + bar.x += 1.0; + d += foo.0 + bar.x; + // +5 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(0.0)]; + arr[0].0 += 1.0; + d += arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 0.0 }]; + arr[0].x += 1.0; + d += arr[0].x; + // +7 + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([0.0]); + (arr.0)[0] += 1.0; + d += (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [0.0] }; + arr.x[0] += 1.0; + d += arr.x[0]; + // +9 + + d +} + +const fn mul_assign(A { a }: A) -> f32 { + // Mutables: + let mut d: f32 = a + 1.0; + d *= 2.0; + // 2^1 * (a + 1) + + // Array projection + let mut arr: [f32; 1] = [1.0]; + arr[0] *= 2.0; + d *= arr[0]; + // 2^2 * (a + 1) + + // Field projection: + let mut foo: Foo = Foo(1.0); + let mut bar: Bar = Bar { x: 1.0 }; + foo.0 *= 2.0; + bar.x *= 2.0; + d *= foo.0 + bar.x; + // 2^4 * (a + 1) + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(1.0)]; + arr[0].0 *= 2.0; + d *= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 1.0 }]; + arr[0].x *= 2.0; + d *= arr[0].x; + // 2^6 * (a + 1) + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([1.0]); + (arr.0)[0] *= 2.0; + d *= (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [1.0] }; + arr.x[0] *= 2.0; + d *= arr.x[0]; + // 2^8 * (a + 1) + + d +} + +const fn div_assign(a: [f32; 1]) -> f32 { + let a = a[0]; + // Mutables: + let mut d: f32 = 1024.0 * a; + d /= 2.0; + // 512 + + // Array projection + let mut arr: [f32; 1] = [4.0]; + arr[0] /= 2.0; + d /= arr[0]; + // 256 + + // Field projection: + let mut foo: Foo = Foo(4.0); + let mut bar: Bar = Bar { x: 4.0 }; + foo.0 /= 2.0; + bar.x /= 2.0; + d /= foo.0; + d /= bar.x; + // 64 + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4.0)]; + arr[0].0 /= 2.0; + d /= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 4.0 }]; + arr[0].x /= 2.0; + d /= arr[0].x; + // 16 + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([4.0]); + (arr.0)[0] /= 2.0; + d /= (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [4.0] }; + arr.x[0] /= 2.0; + d /= arr.x[0]; + // 4 + + d +} + +const fn rem_assign(W(a): W) -> f32 { + // Mutables: + let mut d: f32 = a; + d %= 10.0; + d += 10.0; + + // Array projection + let mut arr: [f32; 1] = [3.0]; + arr[0] %= 2.0; + d %= 9.0 + arr[0]; + d += 10.0; + + // Field projection: + let mut foo: Foo = Foo(5.0); + let mut bar: Bar = Bar { x: 7.0 }; + foo.0 %= 2.0; + bar.x %= 2.0; + d %= 8.0 + foo.0 + bar.x; + d += 10.0; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(4.0)]; + arr[0].0 %= 3.0; + d %= 9.0 + arr[0].0; + d += 10.0; + let mut arr: [Bar; 1] = [Bar { x: 7.0 }]; + arr[0].x %= 3.0; + d %= 9.0 + arr[0].x; + d += 10.0; + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([6.0]); + (arr.0)[0] %= 5.0; + d %= 9.0 + (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [11.0] }; + arr.x[0] %= 5.0; + d %= 9.0 + arr.x[0]; + + d +} + +const fn sub_assign(W(a): W) -> f32 { + // Mutables: + let mut d: f32 = a; + d -= 1.0; + + // Array projection + let mut arr: [f32; 1] = [2.0]; + arr[0] -= 1.0; + d -= arr[0]; + + // Field projection: + let mut foo: Foo = Foo(2.0); + let mut bar: Bar = Bar { x: 2.0 }; + foo.0 -= 1.0; + bar.x -= 1.0; + d -= foo.0 + bar.x; + + // Array + Field projection: + let mut arr: [Foo; 1] = [Foo(2.0)]; + arr[0].0 -= 1.0; + d -= arr[0].0; + let mut arr: [Bar; 1] = [Bar { x: 2.0 }]; + arr[0].x -= 1.0; + d -= arr[0].x; + + // Field + Array projection: + let mut arr: Foo<[f32; 1]> = Foo([2.0]); + (arr.0)[0] -= 1.0; + d -= (arr.0)[0]; + let mut arr: Bar<[f32; 1]> = Bar { x: [2.0] }; + arr.x[0] -= 1.0; + d -= arr.x[0]; + + d +} + +macro_rules! test { + ($c:ident, $e:expr, $r:expr) => { + const $c: f32 = $e; + assert_eq!($c, $r); + assert_eq!($e, $r); + } +} + +fn main() { + test!(BASICS, basics((2.0,)), 13.0); + test!(ADD, add_assign(W(1.0)), 10.0); + test!(MUL, mul_assign(A { a: 0.0 }), 256.0); + test!(DIV, div_assign([1.0]), 4.0); + test!(REM, rem_assign(W(5.0)), 5.0); + test!(SUB, sub_assign(W(8.0)), 0.0); +} diff --git a/tests/ui/consts/const_let_irrefutable.rs b/tests/ui/consts/const_let_irrefutable.rs new file mode 100644 index 000000000..e889abf4a --- /dev/null +++ b/tests/ui/consts/const_let_irrefutable.rs @@ -0,0 +1,11 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn main() {} + +const fn tup((a, b): (i32, i32)) -> i32 { + a + b +} + +const fn array([a, b]: [i32; 2]) -> i32 { + a + b +} diff --git a/tests/ui/consts/const_let_promote.rs b/tests/ui/consts/const_let_promote.rs new file mode 100644 index 000000000..f4661e9e4 --- /dev/null +++ b/tests/ui/consts/const_let_promote.rs @@ -0,0 +1,17 @@ +// run-pass + +use std::cell::Cell; + +const X: Option> = None; + +const Y: Option> = { + let x = None; + x +}; + +// Ensure that binding the final value of a `const` to a variable does not affect promotion. +#[allow(unused)] +fn main() { + let x: &'static _ = &X; + let y: &'static _ = &Y; +} diff --git a/tests/ui/consts/const_let_refutable.rs b/tests/ui/consts/const_let_refutable.rs new file mode 100644 index 000000000..efb134d2e --- /dev/null +++ b/tests/ui/consts/const_let_refutable.rs @@ -0,0 +1,6 @@ +fn main() {} + +const fn slice(&[a, b]: &[i32]) -> i32 { + //~^ ERROR refutable pattern in function argument + a + b +} diff --git a/tests/ui/consts/const_let_refutable.stderr b/tests/ui/consts/const_let_refutable.stderr new file mode 100644 index 000000000..d6119028f --- /dev/null +++ b/tests/ui/consts/const_let_refutable.stderr @@ -0,0 +1,11 @@ +error[E0005]: refutable pattern in function argument + --> $DIR/const_let_refutable.rs:3:16 + | +LL | const fn slice(&[a, b]: &[i32]) -> i32 { + | ^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _, ..]` not covered + | + = note: the matched value is of type `&[i32]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const_limit/const_eval_limit_not_reached.rs b/tests/ui/consts/const_limit/const_eval_limit_not_reached.rs new file mode 100644 index 000000000..629d1f02a --- /dev/null +++ b/tests/ui/consts/const_limit/const_eval_limit_not_reached.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(const_eval_limit)] + +// This needs to be higher than the number of loop iterations since each pass through the loop may +// hit more than one terminator. +#![const_eval_limit="4000"] + +const X: usize = { + let mut x = 0; + while x != 1000 { + x += 1; + } + + x +}; + +fn main() { + assert_eq!(X, 1000); +} diff --git a/tests/ui/consts/const_limit/const_eval_limit_overflow.rs b/tests/ui/consts/const_limit/const_eval_limit_overflow.rs new file mode 100644 index 000000000..1c49593cd --- /dev/null +++ b/tests/ui/consts/const_limit/const_eval_limit_overflow.rs @@ -0,0 +1,15 @@ +#![feature(const_eval_limit)] +#![const_eval_limit="18_446_744_073_709_551_615"] +//~^ ERROR `limit` must be a non-negative integer + +const CONSTANT: usize = limit(); + +fn main() { + assert_eq!(CONSTANT, 1764); +} + +const fn limit() -> usize { + let x = 42; + + x * 42 +} diff --git a/tests/ui/consts/const_limit/const_eval_limit_overflow.stderr b/tests/ui/consts/const_limit/const_eval_limit_overflow.stderr new file mode 100644 index 000000000..7f5d5e6cd --- /dev/null +++ b/tests/ui/consts/const_limit/const_eval_limit_overflow.stderr @@ -0,0 +1,10 @@ +error: `limit` must be a non-negative integer + --> $DIR/const_eval_limit_overflow.rs:2:1 + | +LL | #![const_eval_limit="18_446_744_073_709_551_615"] + | ^^^^^^^^^^^^^^^^^^^^----------------------------^ + | | + | not a valid integer + +error: aborting due to previous error + diff --git a/tests/ui/consts/const_limit/const_eval_limit_reached.rs b/tests/ui/consts/const_limit/const_eval_limit_reached.rs new file mode 100644 index 000000000..3ce038c1d --- /dev/null +++ b/tests/ui/consts/const_limit/const_eval_limit_reached.rs @@ -0,0 +1,16 @@ +#![feature(const_eval_limit)] +#![const_eval_limit = "500"] + +const X: usize = { + let mut x = 0; + while x != 1000 { + //~^ ERROR evaluation of constant value failed + x += 1; + } + + x +}; + +fn main() { + assert_eq!(X, 1000); +} diff --git a/tests/ui/consts/const_limit/const_eval_limit_reached.stderr b/tests/ui/consts/const_limit/const_eval_limit_reached.stderr new file mode 100644 index 000000000..850aebdfb --- /dev/null +++ b/tests/ui/consts/const_limit/const_eval_limit_reached.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_eval_limit_reached.rs:6:11 + | +LL | while x != 1000 { + | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs b/tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs new file mode 100644 index 000000000..61119d751 --- /dev/null +++ b/tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs @@ -0,0 +1,14 @@ +#![const_eval_limit="42"] +//~^ ERROR the `#[const_eval_limit]` attribute is an experimental feature [E0658] + +const CONSTANT: usize = limit(); + +fn main() { + assert_eq!(CONSTANT, 1764); +} + +const fn limit() -> usize { + let x = 42; + + x * 42 +} diff --git a/tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr b/tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr new file mode 100644 index 000000000..5bd29c7df --- /dev/null +++ b/tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[const_eval_limit]` attribute is an experimental feature + --> $DIR/feature-gate-const_eval_limit.rs:1:1 + | +LL | #![const_eval_limit="42"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #67217 for more information + = help: add `#![feature(const_eval_limit)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const_prop_slice_pat_ice.rs b/tests/ui/consts/const_prop_slice_pat_ice.rs new file mode 100644 index 000000000..60b06a497 --- /dev/null +++ b/tests/ui/consts/const_prop_slice_pat_ice.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() { + match &[0, 1] as &[i32] { + [a @ .., x] => {} + &[] => {} + } +} diff --git a/tests/ui/consts/const_short_circuit.rs b/tests/ui/consts/const_short_circuit.rs new file mode 100644 index 000000000..6403fbb17 --- /dev/null +++ b/tests/ui/consts/const_short_circuit.rs @@ -0,0 +1,14 @@ +// check-pass + +const _: bool = false && false; +const _: bool = true && false; +const _: bool = { + let mut x = true && false; + x +}; +const _: bool = { + let x = true && false; + x +}; + +fn main() {} diff --git a/tests/ui/consts/const_unsafe_unreachable.rs b/tests/ui/consts/const_unsafe_unreachable.rs new file mode 100644 index 000000000..1c3baec5d --- /dev/null +++ b/tests/ui/consts/const_unsafe_unreachable.rs @@ -0,0 +1,14 @@ +// run-pass + +const unsafe fn foo(x: bool) -> bool { + match x { + true => true, + false => std::hint::unreachable_unchecked(), + } +} + +const BAR: bool = unsafe { foo(true) }; + +fn main() { + assert_eq!(BAR, true); +} diff --git a/tests/ui/consts/const_unsafe_unreachable_ub.rs b/tests/ui/consts/const_unsafe_unreachable_ub.rs new file mode 100644 index 000000000..b418fea61 --- /dev/null +++ b/tests/ui/consts/const_unsafe_unreachable_ub.rs @@ -0,0 +1,14 @@ +// error-pattern: evaluation of constant value failed + +const unsafe fn foo(x: bool) -> bool { + match x { + true => true, + false => std::hint::unreachable_unchecked(), + } +} + +const BAR: bool = unsafe { foo(false) }; + +fn main() { + assert_eq!(BAR, true); +} diff --git a/tests/ui/consts/const_unsafe_unreachable_ub.stderr b/tests/ui/consts/const_unsafe_unreachable_ub.stderr new file mode 100644 index 000000000..593a51bfe --- /dev/null +++ b/tests/ui/consts/const_unsafe_unreachable_ub.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/hint.rs:LL:COL + | + = note: entering unreachable code + | +note: inside `unreachable_unchecked` + --> $SRC_DIR/core/src/hint.rs:LL:COL +note: inside `foo` + --> $DIR/const_unsafe_unreachable_ub.rs:6:18 + | +LL | false => std::hint::unreachable_unchecked(), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `BAR` + --> $DIR/const_unsafe_unreachable_ub.rs:10:28 + | +LL | const BAR: bool = unsafe { foo(false) }; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/constifconst-call-in-const-position.rs b/tests/ui/consts/constifconst-call-in-const-position.rs new file mode 100644 index 000000000..fcf01d5bc --- /dev/null +++ b/tests/ui/consts/constifconst-call-in-const-position.rs @@ -0,0 +1,22 @@ +// known-bug: #102498 + +#![feature(const_trait_impl, generic_const_exprs)] + +#[const_trait] +pub trait Tr { + fn a() -> usize; +} + +impl Tr for () { + fn a() -> usize { + 1 + } +} + +const fn foo() -> [u8; T::a()] { + [0; T::a()] +} + +fn main() { + foo::<()>(); +} diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr new file mode 100644 index 000000000..d4a445120 --- /dev/null +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -0,0 +1,18 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/constifconst-call-in-const-position.rs:3:30 + | +LL | #![feature(const_trait_impl, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0080]: evaluation of `foo::<()>::{constant#0}` failed + --> $DIR/constifconst-call-in-const-position.rs:16:38 + | +LL | const fn foo() -> [u8; T::a()] { + | ^^^^^^ calling non-const function `<() as Tr>::a` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/consts-in-patterns.rs b/tests/ui/consts/consts-in-patterns.rs new file mode 100644 index 000000000..0295204c8 --- /dev/null +++ b/tests/ui/consts/consts-in-patterns.rs @@ -0,0 +1,28 @@ +// run-pass + +const FOO: isize = 10; +const BAR: isize = 3; +const ZST: &() = unsafe { std::mem::transmute(1usize) }; +const ZST_ARR: &[u8; 0] = unsafe { std::mem::transmute(1usize) }; + +const fn foo() -> isize { 4 } +const BOO: isize = foo(); + +pub fn main() { + let x: isize = 3; + let y = match x { + FOO => 1, + BAR => 2, + BOO => 4, + _ => 3 + }; + assert_eq!(y, 2); + let z = match &() { + ZST => 9, + }; + assert_eq!(z, 9); + let z = match b"" { + ZST_ARR => 10, + }; + assert_eq!(z, 10); +} diff --git a/tests/ui/consts/control-flow/assert.rs b/tests/ui/consts/control-flow/assert.rs new file mode 100644 index 000000000..9d17f65b9 --- /dev/null +++ b/tests/ui/consts/control-flow/assert.rs @@ -0,0 +1,8 @@ +// Test that `assert` works in consts. + +const _: () = assert!(true); + +const _: () = assert!(false); +//~^ ERROR evaluation of constant value failed + +fn main() {} diff --git a/tests/ui/consts/control-flow/assert.stderr b/tests/ui/consts/control-flow/assert.stderr new file mode 100644 index 000000000..8b1ca183d --- /dev/null +++ b/tests/ui/consts/control-flow/assert.stderr @@ -0,0 +1,11 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/assert.rs:5:15 + | +LL | const _: () = assert!(false); + | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:5:15 + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/control-flow/basics.rs b/tests/ui/consts/control-flow/basics.rs new file mode 100644 index 000000000..02e5501f1 --- /dev/null +++ b/tests/ui/consts/control-flow/basics.rs @@ -0,0 +1,82 @@ +// Test basic functionality of control flow in a const context. + +// run-pass + +const X: u32 = 4; +const Y: u32 = 5; + +const ABS_DIFF: u32 = if X < Y { + Y - X +} else { + X - Y +}; + +const fn abs_diff(a: u32, b: u32) -> u32 { + match (a, b) { + (big, little) if big > little => big - little, + (little, big) => big - little, + } +} + +const fn gcd(a: u32, b: u32) -> u32 { + if b == 0 { + return a; + } + + gcd(b, a % b) +} + +const fn fib(n: u64) -> u64 { + if n == 0 { + return 0; + } + + let mut fib = (0, 1); + let mut i = 1; + while i < n { + fib = (fib.1, fib.0 + fib.1); + i += 1; + } + + fib.1 +} + +const fn is_prime(n: u64) -> bool { + if n % 2 == 0 { + return false; + } + + let mut div = 3; + loop { + if n % div == 0 { + return false; + } + + if div * div > n { + return true; + } + + div += 2; + } +} + +macro_rules! const_assert { + ($expr:expr) => { + const _: () = assert!($expr); + assert!($expr); + } +} + +fn main() { + const_assert!(abs_diff(4, 5) == abs_diff(5, 4)); + const_assert!(ABS_DIFF == abs_diff(5, 4)); + + const_assert!(gcd(48, 18) == 6); + const_assert!(gcd(18, 48) == 6); + + const_assert!(fib(2) == 1); + const_assert!(fib(8) == 21); + + const_assert!(is_prime(113)); + const_assert!(!is_prime(117)); +} diff --git a/tests/ui/consts/control-flow/drop-fail.precise.stderr b/tests/ui/consts/control-flow/drop-fail.precise.stderr new file mode 100644 index 000000000..93b5f257e --- /dev/null +++ b/tests/ui/consts/control-flow/drop-fail.precise.stderr @@ -0,0 +1,15 @@ +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:8:9 + | +LL | let x = Some(Vec::new()); + | ^ the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:39:9 + | +LL | let mut tmp = None; + | ^^^^^^^ the destructor for this type cannot be evaluated in constants + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/control-flow/drop-fail.rs b/tests/ui/consts/control-flow/drop-fail.rs new file mode 100644 index 000000000..41341f312 --- /dev/null +++ b/tests/ui/consts/control-flow/drop-fail.rs @@ -0,0 +1,62 @@ +// revisions: stock precise + +#![cfg_attr(precise, feature(const_precise_live_drops))] + +// `x` is *not* always moved into the final value and may be dropped inside the initializer. +const _: Option> = { + let y: Option> = None; + let x = Some(Vec::new()); + //[stock,precise]~^ ERROR destructor of + + if true { + x + } else { + y + } +}; + +// We only clear `NeedsDrop` if a local is moved from in entirely. This is a shortcoming of the +// existing analysis. +const _: Vec = { + let vec_tuple = (Vec::new(),); + //[stock]~^ ERROR destructor of + + vec_tuple.0 +}; + +// This applies to single-field enum variants as well. +const _: Vec = { + let x: Result<_, Vec> = Ok(Vec::new()); + //[stock]~^ ERROR destructor of + + match x { + Ok(x) | Err(x) => x, + } +}; + +const _: Option> = { + let mut some = Some(Vec::new()); + let mut tmp = None; + //[stock,precise]~^ ERROR destructor of + + let mut i = 0; + while i < 10 { + tmp = some; + some = None; + + // We can escape the loop with `Some` still in `tmp`, + // which would require that it be dropped at the end of the block. + if i > 100 { + break; + } + + some = tmp; + tmp = None; + + i += 1; + } + + some +}; + +fn main() {} diff --git a/tests/ui/consts/control-flow/drop-fail.stock.stderr b/tests/ui/consts/control-flow/drop-fail.stock.stderr new file mode 100644 index 000000000..2cc856802 --- /dev/null +++ b/tests/ui/consts/control-flow/drop-fail.stock.stderr @@ -0,0 +1,39 @@ +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:8:9 + | +LL | let x = Some(Vec::new()); + | ^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error[E0493]: destructor of `(Vec,)` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:21:9 + | +LL | let vec_tuple = (Vec::new(),); + | ^^^^^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error[E0493]: destructor of `Result, Vec>` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:29:9 + | +LL | let x: Result<_, Vec> = Ok(Vec::new()); + | ^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error[E0493]: destructor of `Option>` cannot be evaluated at compile-time + --> $DIR/drop-fail.rs:39:9 + | +LL | let mut tmp = None; + | ^^^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/control-flow/drop-pass.rs b/tests/ui/consts/control-flow/drop-pass.rs new file mode 100644 index 000000000..2a6d12768 --- /dev/null +++ b/tests/ui/consts/control-flow/drop-pass.rs @@ -0,0 +1,46 @@ +// run-pass +// revisions: stock precise + +#![allow(unused)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +// `x` is always moved into the final value and is not dropped inside the initializer. +const _: Option> = { + let y: Option> = None; + let x = Some(Vec::new()); + + if true { + x + } else { + x + } +}; + +const _: Option> = { + let x = Some(Vec::new()); + match () { + () => x, + } +}; + +const _: Option> = { + let mut some = Some(Vec::new()); + let mut tmp = None; + + let mut i = 0; + while i < 10 { + tmp = some; + some = None; + + // We can never exit the loop with `Some` in `tmp`. + + some = tmp; + tmp = None; + + i += 1; + } + + some +}; + +fn main() {} diff --git a/tests/ui/consts/control-flow/drop-precise.rs b/tests/ui/consts/control-flow/drop-precise.rs new file mode 100644 index 000000000..4ecc5ef78 --- /dev/null +++ b/tests/ui/consts/control-flow/drop-precise.rs @@ -0,0 +1,18 @@ +// run-pass +// gate-test-const_precise_live_drops + +#![feature(const_precise_live_drops)] + +const _: Vec = { + let vec_tuple = (Vec::new(),); + vec_tuple.0 +}; + +const _: Vec = { + let x: Result<_, Vec> = Ok(Vec::new()); + match x { + Ok(x) | Err(x) => x, + } +}; + +fn main() {} diff --git a/tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs b/tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs new file mode 100644 index 000000000..4320133df --- /dev/null +++ b/tests/ui/consts/control-flow/exhaustive-c-like-enum-match.rs @@ -0,0 +1,29 @@ +// Test for + +// check-pass + +enum E { + A, + B, + C +} + +const fn f(e: E) { + match e { + E::A => {} + E::B => {} + E::C => {} + } +} + +const fn g(e: E) -> usize { + match e { + _ => 0 + } +} + +fn main() { + const X: usize = g(E::C); + assert_eq!(X, 0); + assert_eq!(g(E::A), 0); +} diff --git a/tests/ui/consts/control-flow/feature-gate-const-if-match.rs b/tests/ui/consts/control-flow/feature-gate-const-if-match.rs new file mode 100644 index 000000000..cb66bc753 --- /dev/null +++ b/tests/ui/consts/control-flow/feature-gate-const-if-match.rs @@ -0,0 +1,96 @@ +// check-pass + +const _: i32 = if true { 5 } else { 6 }; + +const _: i32 = if let Some(true) = Some(false) { 0 } else { 1 }; + +const _: i32 = match 1 { + 2 => 3, + 4 => 5, + _ => 0, +}; + +static FOO: i32 = { + let x = if true { 0 } else { 1 }; + let x = match x { + 0 => 1, + _ => 0, + }; + if let Some(x) = Some(x) { x } else { 1 } +}; + +static mut BAR: i32 = { + let x = if true { 0 } else { 1 }; + let x = match x { + 0 => 1, + _ => 0, + }; + if let Some(x) = Some(x) { x } else { 1 } +}; + +const fn if_() -> i32 { + if true { 5 } else { 6 } +} + +const fn if_let(a: Option) -> i32 { + if let Some(true) = a { 0 } else { 1 } +} + +const fn match_(i: i32) -> i32 { + match i { + i if i > 10 => i, + 1 => 2, + _ => 0, + } +} + +pub trait Foo { + const IF: i32 = if true { 5 } else { 6 }; + const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + const MATCH: i32 = match 0 { + 1 => 2, + _ => 0, + }; +} + +impl Foo for () { + const IF: i32 = if true { 5 } else { 6 }; + const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 }; + const MATCH: i32 = match 0 { + 1 => 2, + _ => 0, + }; +} + +fn non_const_outside() { + const fn const_inside(y: bool) -> i32 { + let x = if y { 0 } else { 1 }; + let x = match x { + 0 => 1, + _ => 0, + }; + if let Some(x) = Some(x) { x } else { 1 } + } +} + +const fn const_outside() { + fn non_const_inside(y: bool) -> i32 { + let x = if y { 0 } else { 1 }; + let x = match x { + 0 => 1, + _ => 0, + }; + if let Some(x) = Some(x) { x } else { 1 } + } +} + +fn main() { + let _ = [0; { + let x = if false { 0 } else { 1 }; + let x = match x { + 0 => 1, + _ => 0, + }; + if let Some(x) = Some(x) { x } else { 1 } + }]; +} diff --git a/tests/ui/consts/control-flow/interior-mutability.rs b/tests/ui/consts/control-flow/interior-mutability.rs new file mode 100644 index 000000000..a6d44237b --- /dev/null +++ b/tests/ui/consts/control-flow/interior-mutability.rs @@ -0,0 +1,43 @@ +// Ensure that *any* assignment to the return place of a value with interior mutability +// disqualifies it from promotion. + +use std::cell::Cell; + +const X: Option> = { + let mut x = None; + if false { + x = Some(Cell::new(4)); + } + x +}; + +const Y: Option> = { + let mut y = Some(Cell::new(4)); + if true { + y = None; + } + y +}; + +const Z: Option> = { + let mut z = None; + let mut i = 0; + while i < 10 { + if i == 8 { + z = Some(Cell::new(4)); + } + + if i == 9 { + z = None; + } + + i += 1; + } + z +}; + +fn main() { + let x: &'static _ = &X; //~ ERROR temporary value dropped while borrowed + let y: &'static _ = &Y; //~ ERROR temporary value dropped while borrowed + let z: &'static _ = &Z; //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/control-flow/interior-mutability.stderr b/tests/ui/consts/control-flow/interior-mutability.stderr new file mode 100644 index 000000000..db2ffb91b --- /dev/null +++ b/tests/ui/consts/control-flow/interior-mutability.stderr @@ -0,0 +1,35 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:40:26 + | +LL | let x: &'static _ = &X; + | ---------- ^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:41:26 + | +LL | let y: &'static _ = &Y; + | ---------- ^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let z: &'static _ = &Z; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/interior-mutability.rs:42:26 + | +LL | let z: &'static _ = &Z; + | ---------- ^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/control-flow/issue-46843.rs b/tests/ui/consts/control-flow/issue-46843.rs new file mode 100644 index 000000000..ddddc8505 --- /dev/null +++ b/tests/ui/consts/control-flow/issue-46843.rs @@ -0,0 +1,16 @@ +enum Thing { + This, + That, +} + +fn non_const() -> Thing { + Thing::This +} + +pub const Q: i32 = match non_const() { + //~^ ERROR cannot call non-const fn + Thing::This => 1, + Thing::That => 0 +}; + +fn main() {} diff --git a/tests/ui/consts/control-flow/issue-46843.stderr b/tests/ui/consts/control-flow/issue-46843.stderr new file mode 100644 index 000000000..66227f61e --- /dev/null +++ b/tests/ui/consts/control-flow/issue-46843.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `non_const` in constants + --> $DIR/issue-46843.rs:10:26 + | +LL | pub const Q: i32 = match non_const() { + | ^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/issue-50577.rs b/tests/ui/consts/control-flow/issue-50577.rs new file mode 100644 index 000000000..beb9a44fc --- /dev/null +++ b/tests/ui/consts/control-flow/issue-50577.rs @@ -0,0 +1,6 @@ +fn main() { + enum Foo { + Drop = assert_eq!(1, 1), + //~^ ERROR `if` may be missing an `else` clause + } +} diff --git a/tests/ui/consts/control-flow/issue-50577.stderr b/tests/ui/consts/control-flow/issue-50577.stderr new file mode 100644 index 000000000..a931c89f4 --- /dev/null +++ b/tests/ui/consts/control-flow/issue-50577.stderr @@ -0,0 +1,13 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/issue-50577.rs:3:16 + | +LL | Drop = assert_eq!(1, 1), + | ^^^^^^^^^^^^^^^^ expected `isize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs new file mode 100644 index 000000000..2b8561a26 --- /dev/null +++ b/tests/ui/consts/control-flow/loop.rs @@ -0,0 +1,89 @@ +const _: () = loop { break (); }; + +static FOO: i32 = loop { break 4; }; + +const fn foo() { + loop {} +} + +pub trait Foo { + const BAR: i32 = loop { break 4; }; +} + +impl Foo for () { + const BAR: i32 = loop { break 4; }; +} + +fn non_const_outside() { + const fn const_inside() { + loop {} + } +} + +const fn const_outside() { + fn non_const_inside() { + loop {} + } +} + +fn main() { + let x = [0; { + while false {} + 4 + }]; +} + +const _: i32 = { + let mut x = 0; + + while x < 4 { + x += 1; + } + + while x < 8 { + x += 1; + } + + x +}; + +const _: i32 = { + let mut x = 0; + + for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + x += i; + } + + for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + x += i; + } + + x +}; + +const _: i32 = { + let mut x = 0; + + loop { + x += 1; + if x == 4 { + break; + } + } + + loop { + x += 1; + if x == 8 { + break; + } + } + + x +}; + +const _: i32 = { + let mut x = 0; + while let None = Some(x) { } + while let None = Some(x) { } + x +}; diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr new file mode 100644 index 000000000..5f6ad8c10 --- /dev/null +++ b/tests/ui/consts/control-flow/loop.stderr @@ -0,0 +1,25 @@ +error[E0658]: `for` is not allowed in a `const` + --> $DIR/loop.rs:53:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/loop.rs:57:5 + | +LL | / for i in 0..4 { +LL | | x += i; +LL | | } + | |_____^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/control-flow/short-circuit-let.rs b/tests/ui/consts/control-flow/short-circuit-let.rs new file mode 100644 index 000000000..8a58d06ac --- /dev/null +++ b/tests/ui/consts/control-flow/short-circuit-let.rs @@ -0,0 +1,36 @@ +// `&&` and `||` were previously forbidden in constants alongside let bindings. + +// run-pass + +const X: i32 = { + let mut x = 0; + let _ = true && { x = 1; false }; + x +}; + +const Y: bool = { + let x = true && false || true; + x +}; + +const fn truthy() -> bool { + let x = true || return false; + x +} + +const fn falsy() -> bool { + let x = true && return false; + x +} + +fn main() { + const _: () = assert!(Y); + assert!(Y); + + const _: () = assert!(X == 1); + assert_eq!(X, 1); + + const _: () = assert!(truthy()); + const _: () = assert!(!falsy()); + assert!(truthy() && !falsy()); +} diff --git a/tests/ui/consts/control-flow/short-circuit.rs b/tests/ui/consts/control-flow/short-circuit.rs new file mode 100644 index 000000000..6abe10785 --- /dev/null +++ b/tests/ui/consts/control-flow/short-circuit.rs @@ -0,0 +1,12 @@ +// run-pass + +// Test that both `&&` and `||` actually short-circuit. +// Formerly, both sides were evaluated unconditionally + +const TRUE: bool = true || panic!(); +const FALSE: bool = false && panic!(); + +fn main() { + assert!(TRUE); + assert!(!FALSE); +} diff --git a/tests/ui/consts/control-flow/single_variant_match_ice.rs b/tests/ui/consts/control-flow/single_variant_match_ice.rs new file mode 100644 index 000000000..b59be00ff --- /dev/null +++ b/tests/ui/consts/control-flow/single_variant_match_ice.rs @@ -0,0 +1,25 @@ +// check-pass + +enum Foo { + Prob, +} + +const FOO: u32 = match Foo::Prob { + Foo::Prob => 42, +}; + +const BAR: u32 = match Foo::Prob { + x => 42, +}; + +impl Foo { + pub const fn as_val(&self) -> u8 { + use self::Foo::*; + + match *self { + Prob => 0x1, + } + } +} + +fn main() {} diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs new file mode 100644 index 000000000..7d85a412b --- /dev/null +++ b/tests/ui/consts/control-flow/try.rs @@ -0,0 +1,10 @@ +// The `?` operator is still not const-evaluatable because it calls `From::from` on the error +// variant. + +const fn opt() -> Option { + let x = Some(2); + x?; //~ ERROR `?` is not allowed in a `const fn` + None +} + +fn main() {} diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr new file mode 100644 index 000000000..5aeec8fbf --- /dev/null +++ b/tests/ui/consts/control-flow/try.stderr @@ -0,0 +1,12 @@ +error[E0658]: `?` is not allowed in a `const fn` + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | + = note: see issue #74935 for more information + = help: add `#![feature(const_try)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs new file mode 100644 index 000000000..94d7bdc6b --- /dev/null +++ b/tests/ui/consts/copy-intrinsic.rs @@ -0,0 +1,52 @@ +#![stable(feature = "dummy", since = "1.0.0")] + +// ignore-tidy-linelength +#![feature(intrinsics, staged_api)] +#![feature(const_mut_refs)] +use std::mem; + +extern "rust-intrinsic" { + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + fn copy(src: *const T, dst: *mut T, count: usize); +} + +const COPY_ZERO: () = unsafe { + // Since we are not copying anything, this should be allowed. + let src = (); + let mut dst = (); + copy_nonoverlapping(&src as *const _ as *const u8, &mut dst as *mut _ as *mut u8, 0); +}; + +const COPY_OOB_1: () = unsafe { + let mut x = 0i32; + let dangle = (&mut x as *mut i32).wrapping_add(10); + // Even if the first ptr is an int ptr and this is a ZST copy, we should detect dangling 2nd ptrs. + copy_nonoverlapping(0x100 as *const i32, dangle, 0); //~ ERROR evaluation of constant value failed [E0080] + //~| pointer at offset 40 is out-of-bounds +}; +const COPY_OOB_2: () = unsafe { + let x = 0i32; + let dangle = (&x as *const i32).wrapping_add(10); + // Even if the second ptr is an int ptr and this is a ZST copy, we should detect dangling 1st ptrs. + copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); //~ ERROR evaluation of constant value failed [E0080] + //~| pointer at offset 40 is out-of-bounds +}; + +const COPY_SIZE_OVERFLOW: () = unsafe { + let x = 0; + let mut y = 0; + copy(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ ERROR evaluation of constant value failed [E0080] + //~| overflow computing total size of `copy` +}; +const COPY_NONOVERLAPPING_SIZE_OVERFLOW: () = unsafe { + let x = 0; + let mut y = 0; + copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ evaluation of constant value failed [E0080] + //~| overflow computing total size of `copy_nonoverlapping` +}; + +fn main() { +} diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr new file mode 100644 index 000000000..be41c2db3 --- /dev/null +++ b/tests/ui/consts/copy-intrinsic.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:27:5 + | +LL | copy_nonoverlapping(0x100 as *const i32, dangle, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer at offset 40 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:34:5 + | +LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc7 has size 4, so pointer at offset 40 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:41:5 + | +LL | copy(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy` + +error[E0080]: evaluation of constant value failed + --> $DIR/copy-intrinsic.rs:47:5 + | +LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.rs b/tests/ui/consts/ct-var-in-collect_all_mismatches.rs new file mode 100644 index 000000000..5fb633de9 --- /dev/null +++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.rs @@ -0,0 +1,20 @@ +struct Foo { + array: [T; N], +} + +trait Bar {} + +impl Foo { + fn trigger(self) { + self.unsatisfied() + //~^ ERROR the trait bound `T: Bar` is not satisfied + } + + fn unsatisfied(self) + where + T: Bar, + { + } +} + +fn main() {} diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr new file mode 100644 index 000000000..43fba2573 --- /dev/null +++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/ct-var-in-collect_all_mismatches.rs:9:14 + | +LL | self.unsatisfied() + | ^^^^^^^^^^^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `Foo::::unsatisfied` + --> $DIR/ct-var-in-collect_all_mismatches.rs:15:12 + | +LL | fn unsatisfied(self) + | ----------- required by a bound in this +LL | where +LL | T: Bar, + | ^^^^^^ required by this bound in `Foo::::unsatisfied` +help: consider restricting type parameter `T` + | +LL | impl, const N: usize> Foo { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/dangling-alloc-id-ice.rs b/tests/ui/consts/dangling-alloc-id-ice.rs new file mode 100644 index 000000000..d591bfc73 --- /dev/null +++ b/tests/ui/consts/dangling-alloc-id-ice.rs @@ -0,0 +1,14 @@ +// https://github.com/rust-lang/rust/issues/55223 + +union Foo<'a> { + y: &'a (), + long_live_the_unit: &'static (), +} + +const FOO: &() = { +//~^ ERROR encountered dangling pointer in final constant + let y = (); + unsafe { Foo { y: &y }.long_live_the_unit } +}; + +fn main() {} diff --git a/tests/ui/consts/dangling-alloc-id-ice.stderr b/tests/ui/consts/dangling-alloc-id-ice.stderr new file mode 100644 index 000000000..0a1cca4ca --- /dev/null +++ b/tests/ui/consts/dangling-alloc-id-ice.stderr @@ -0,0 +1,8 @@ +error: encountered dangling pointer in final constant + --> $DIR/dangling-alloc-id-ice.rs:8:1 + | +LL | const FOO: &() = { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/dangling_raw_ptr.rs b/tests/ui/consts/dangling_raw_ptr.rs new file mode 100644 index 000000000..ddd1fb1ba --- /dev/null +++ b/tests/ui/consts/dangling_raw_ptr.rs @@ -0,0 +1,8 @@ +const FOO: *const u32 = { //~ ERROR encountered dangling pointer in final constant + let x = 42; + &x +}; + +fn main() { + let x = FOO; +} diff --git a/tests/ui/consts/dangling_raw_ptr.stderr b/tests/ui/consts/dangling_raw_ptr.stderr new file mode 100644 index 000000000..bdfe1e4ef --- /dev/null +++ b/tests/ui/consts/dangling_raw_ptr.stderr @@ -0,0 +1,8 @@ +error: encountered dangling pointer in final constant + --> $DIR/dangling_raw_ptr.rs:1:1 + | +LL | const FOO: *const u32 = { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/deref_in_pattern.rs b/tests/ui/consts/deref_in_pattern.rs new file mode 100644 index 000000000..cc47b5b49 --- /dev/null +++ b/tests/ui/consts/deref_in_pattern.rs @@ -0,0 +1,12 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/25574 + +const A: [u8; 4] = *b"fooo"; + +fn main() { + match *b"xxxx" { + A => {}, + _ => {} + } +} diff --git a/tests/ui/consts/drop_box.rs b/tests/ui/consts/drop_box.rs new file mode 100644 index 000000000..679974130 --- /dev/null +++ b/tests/ui/consts/drop_box.rs @@ -0,0 +1,4 @@ +const fn f(_: Box) {} +//~^ ERROR destructor of + +fn main() {} diff --git a/tests/ui/consts/drop_box.stderr b/tests/ui/consts/drop_box.stderr new file mode 100644 index 000000000..62324939b --- /dev/null +++ b/tests/ui/consts/drop_box.stderr @@ -0,0 +1,11 @@ +error[E0493]: destructor of `Box` cannot be evaluated at compile-time + --> $DIR/drop_box.rs:1:15 + | +LL | const fn f(_: Box) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/drop_none.rs b/tests/ui/consts/drop_none.rs new file mode 100644 index 000000000..9d98d3be8 --- /dev/null +++ b/tests/ui/consts/drop_none.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +struct A; +impl Drop for A { + fn drop(&mut self) {} +} + +const FOO: Option = None; + +const BAR: () = (FOO, ()).1; + + +fn main() {} diff --git a/tests/ui/consts/drop_zst.rs b/tests/ui/consts/drop_zst.rs new file mode 100644 index 000000000..f7c70d397 --- /dev/null +++ b/tests/ui/consts/drop_zst.rs @@ -0,0 +1,17 @@ +// check-fail + +#![feature(const_precise_live_drops)] + +struct S; + +impl Drop for S { + fn drop(&mut self) { + println!("Hello!"); + } +} + +const fn foo() { + let s = S; //~ destructor +} + +fn main() {} diff --git a/tests/ui/consts/drop_zst.stderr b/tests/ui/consts/drop_zst.stderr new file mode 100644 index 000000000..37758a4cb --- /dev/null +++ b/tests/ui/consts/drop_zst.stderr @@ -0,0 +1,9 @@ +error[E0493]: destructor of `S` cannot be evaluated at compile-time + --> $DIR/drop_zst.rs:14:9 + | +LL | let s = S; + | ^ the destructor for this type cannot be evaluated in constant functions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/enum-discr-type-err.rs b/tests/ui/consts/enum-discr-type-err.rs new file mode 100644 index 000000000..5adb2fa54 --- /dev/null +++ b/tests/ui/consts/enum-discr-type-err.rs @@ -0,0 +1,30 @@ +// Test that we mark enum discriminant values as having errors, even when the +// diagnostic is deduplicated. + +struct F; +struct T; + +impl F { + const V: i32 = 0; +} + +impl T { + const V: i32 = 0; +} + +macro_rules! mac { + ($( $v: ident = $s: ident,)*) => { + enum E { + $( $v = $s::V, )* + //~^ ERROR mismatched types + //~| ERROR mismatched types + } + } +} + +mac! { + A = F, + B = T, +} + +fn main() {} diff --git a/tests/ui/consts/enum-discr-type-err.stderr b/tests/ui/consts/enum-discr-type-err.stderr new file mode 100644 index 000000000..2f97582be --- /dev/null +++ b/tests/ui/consts/enum-discr-type-err.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/enum-discr-type-err.rs:18:21 + | +LL | $( $v = $s::V, )* + | ^^^^^ expected `isize`, found `i32` +... +LL | / mac! { +LL | | A = F, +LL | | B = T, +LL | | } + | |_- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/enum-discr-type-err.rs:18:21 + | +LL | $( $v = $s::V, )* + | ^^^^^ expected `isize`, found `i32` +... +LL | / mac! { +LL | | A = F, +LL | | B = T, +LL | | } + | |_- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/eval-enum.rs b/tests/ui/consts/eval-enum.rs new file mode 100644 index 000000000..551f10e66 --- /dev/null +++ b/tests/ui/consts/eval-enum.rs @@ -0,0 +1,10 @@ +enum Test { + DivZero = 1/0, + //~^ attempt to divide `1_isize` by zero + //~| ERROR evaluation of constant value failed + RemZero = 1%0, + //~^ attempt to calculate the remainder of `1_isize` with a divisor of zero + //~| ERROR evaluation of constant value failed +} + +fn main() {} diff --git a/tests/ui/consts/eval-enum.stderr b/tests/ui/consts/eval-enum.stderr new file mode 100644 index 000000000..fb4d90348 --- /dev/null +++ b/tests/ui/consts/eval-enum.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/eval-enum.rs:2:15 + | +LL | DivZero = 1/0, + | ^^^ attempt to divide `1_isize` by zero + +error[E0080]: evaluation of constant value failed + --> $DIR/eval-enum.rs:5:15 + | +LL | RemZero = 1%0, + | ^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs new file mode 100644 index 000000000..e2f814988 --- /dev/null +++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs @@ -0,0 +1,31 @@ +// revisions: no_flag with_flag +// [no_flag] check-pass +// [with_flag] compile-flags: -Zextra-const-ub-checks +#![feature(const_ptr_read)] + +use std::mem::transmute; + +const INVALID_BOOL: () = unsafe { + let _x: bool = transmute(3u8); + //[with_flag]~^ ERROR: evaluation of constant value failed + //[with_flag]~| invalid value +}; + +const INVALID_PTR_IN_INT: () = unsafe { + let _x: usize = transmute(&3u8); + //[with_flag]~^ ERROR: evaluation of constant value failed +}; + +const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe { + let x: &[u8] = &[0; 32]; + let _x: (usize, usize) = transmute(x); + //[with_flag]~^ ERROR: evaluation of constant value failed +}; + +const UNALIGNED_PTR: () = unsafe { + let _x: &u32 = transmute(&[0u8; 4]); + //[with_flag]~^ ERROR: evaluation of constant value failed + //[with_flag]~| invalid value +}; + +fn main() {} diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr new file mode 100644 index 000000000..b2a5fd901 --- /dev/null +++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr @@ -0,0 +1,33 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/detect-extra-ub.rs:9:20 + | +LL | let _x: bool = transmute(3u8); + | ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean + +error[E0080]: evaluation of constant value failed + --> $DIR/detect-extra-ub.rs:15:21 + | +LL | let _x: usize = transmute(&3u8); + | ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/detect-extra-ub.rs:21:30 + | +LL | let _x: (usize, usize) = transmute(x); + | ^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/detect-extra-ub.rs:26:20 + | +LL | let _x: &u32 = transmute(&[0u8; 4]); + | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/extra-const-ub/issue-100771.rs b/tests/ui/consts/extra-const-ub/issue-100771.rs new file mode 100644 index 000000000..a32960328 --- /dev/null +++ b/tests/ui/consts/extra-const-ub/issue-100771.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Zextra-const-ub-checks + +#[derive(PartialEq, Eq, Copy, Clone)] +#[repr(packed)] +struct Foo { + field: (i64, u32, u32, u32), +} + +const FOO: Foo = Foo { + field: (5, 6, 7, 8), +}; + +fn main() { + match FOO { + Foo { field: (5, 6, 7, 8) } => {}, + FOO => unreachable!(), + _ => unreachable!(), + } +} diff --git a/tests/ui/consts/extra-const-ub/issue-101034.rs b/tests/ui/consts/extra-const-ub/issue-101034.rs new file mode 100644 index 000000000..e0de705c4 --- /dev/null +++ b/tests/ui/consts/extra-const-ub/issue-101034.rs @@ -0,0 +1,17 @@ +// check-pass +// compile-flags: -Zextra-const-ub-checks + +#[repr(packed)] +pub struct Foo { + bar: u8, + baa: [u32; 1], +} + +const FOOMP: Foo = Foo { + bar: 0, + baa: [69; 1], +}; + +fn main() { + let _val = FOOMP; +} diff --git a/tests/ui/consts/fn_trait_refs.rs b/tests/ui/consts/fn_trait_refs.rs new file mode 100644 index 000000000..b50749297 --- /dev/null +++ b/tests/ui/consts/fn_trait_refs.rs @@ -0,0 +1,77 @@ +// check-pass + +#![feature(const_fn_trait_ref_impls)] +#![feature(fn_traits)] +#![feature(unboxed_closures)] +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![feature(const_cmp)] +#![feature(const_refs_to_cell)] + +use std::marker::Destruct; + +const fn tester_fn(f: T) -> T::Output +where + T: ~const Fn<()> + ~const Destruct, +{ + f() +} + +const fn tester_fn_mut(mut f: T) -> T::Output +where + T: ~const FnMut<()> + ~const Destruct, +{ + f() +} + +const fn tester_fn_once(f: T) -> T::Output +where + T: ~const FnOnce<()>, +{ + f() +} + +const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) +where + T: ~const Fn<()> + ~const Destruct, +{ + ( + // impl const Fn for &F + tester_fn(&f), + // impl const FnMut for &F + tester_fn_mut(&f), + // impl const FnOnce for &F + tester_fn_once(&f), + ) +} + +const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) +where + T: ~const FnMut<()> + ~const Destruct, +{ + ( + // impl const FnMut for &mut F + tester_fn_mut(&mut f), + // impl const FnOnce for &mut F + tester_fn_once(&mut f), + ) +} +const fn test(i: i32) -> i32 { + i + 1 +} + +fn main() { + const fn one() -> i32 { + 1 + }; + const fn two() -> i32 { + 2 + }; + const _: () = { + let test_one = test_fn(one); + assert!(test_one == (1, 1, 1)); + + let test_two = test_fn_mut(two); + assert!(test_two == (2, 2)); + }; +} diff --git a/tests/ui/consts/huge-values.rs b/tests/ui/consts/huge-values.rs new file mode 100644 index 000000000..70a5b10e9 --- /dev/null +++ b/tests/ui/consts/huge-values.rs @@ -0,0 +1,17 @@ +// build-pass +// ignore-32bit + +// This test is a canary test that will essentially not compile in a reasonable time frame +// (so it'll take hours) if any of the optimizations regress. With the optimizations, these compile +// in milliseconds just as if the length were set to `1`. + +#[derive(Clone, Copy)] +struct Foo; + +fn main() { + let _ = [(); 4_000_000_000]; + let _ = [0u8; 4_000_000_000]; + let _ = [Foo; 4_000_000_000]; + let _ = [(Foo, (), Foo, ((), Foo, [0; 0])); 4_000_000_000]; + let _ = [[0; 0]; 4_000_000_000]; +} diff --git a/tests/ui/consts/ice-48279.rs b/tests/ui/consts/ice-48279.rs new file mode 100644 index 000000000..d1d90df24 --- /dev/null +++ b/tests/ui/consts/ice-48279.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_unsafe)] + +// https://github.com/rust-lang/rust/issues/48279 + +#[derive(PartialEq, Eq)] +pub struct NonZeroU32 { + value: u32 +} + +impl NonZeroU32 { + const unsafe fn new_unchecked(value: u32) -> Self { + NonZeroU32 { value } + } +} + +//pub const FOO_ATOM: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(7) }; +pub const FOO_ATOM: NonZeroU32 = unsafe { NonZeroU32 { value: 7 } }; + +fn main() { + match None { + Some(FOO_ATOM) => {} + _ => {} + } +} diff --git a/tests/ui/consts/ice-zst-static-access.rs b/tests/ui/consts/ice-zst-static-access.rs new file mode 100644 index 000000000..b68e442a5 --- /dev/null +++ b/tests/ui/consts/ice-zst-static-access.rs @@ -0,0 +1,32 @@ +// check-pass + +// This is a regression test for ICEs from +// https://github.com/rust-lang/rust/issues/71612 +// and +// https://github.com/rust-lang/rust/issues/71709 + +#[derive(Copy, Clone)] +pub struct Glfw; + +static mut GLFW: Option = None; +pub fn new() -> Glfw { + unsafe { + if let Some(glfw) = GLFW { + return glfw; + } else { + todo!() + } + }; +} + +extern "C" { + static _dispatch_queue_attr_concurrent: [u8; 0]; +} + +static DISPATCH_QUEUE_CONCURRENT: &'static [u8; 0] = + unsafe { &_dispatch_queue_attr_concurrent }; + +fn main() { + *DISPATCH_QUEUE_CONCURRENT; + new(); +} diff --git a/tests/ui/consts/inline_asm.rs b/tests/ui/consts/inline_asm.rs new file mode 100644 index 000000000..4cd7e2717 --- /dev/null +++ b/tests/ui/consts/inline_asm.rs @@ -0,0 +1,8 @@ +// needs-asm-support + +use std::arch::asm; + +const _: () = unsafe { asm!("nop") }; +//~^ ERROR inline assembly + +fn main() {} diff --git a/tests/ui/consts/inline_asm.stderr b/tests/ui/consts/inline_asm.stderr new file mode 100644 index 000000000..65a828d11 --- /dev/null +++ b/tests/ui/consts/inline_asm.stderr @@ -0,0 +1,9 @@ +error[E0015]: inline assembly is not allowed in constants + --> $DIR/inline_asm.rs:5:24 + | +LL | const _: () = unsafe { asm!("nop") }; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/int_ptr_for_zst_slices.rs b/tests/ui/consts/int_ptr_for_zst_slices.rs new file mode 100644 index 000000000..34e5bb322 --- /dev/null +++ b/tests/ui/consts/int_ptr_for_zst_slices.rs @@ -0,0 +1,5 @@ +// check-pass + +const FOO: &str = unsafe { &*(1_usize as *const [u8; 0] as *const [u8] as *const str) }; + +fn main() {} diff --git a/tests/ui/consts/intrinsic_without_const_stab.rs b/tests/ui/consts/intrinsic_without_const_stab.rs new file mode 100644 index 000000000..40ec65d51 --- /dev/null +++ b/tests/ui/consts/intrinsic_without_const_stab.rs @@ -0,0 +1,17 @@ +#![feature(intrinsics, staged_api)] +#![stable(feature = "core", since = "1.6.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[inline] +pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { + // Const stability attributes are not inherited from parent items. + extern "rust-intrinsic" { + fn copy(src: *const T, dst: *mut T, count: usize); + } + + unsafe { copy(src, dst, count) } + //~^ ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/consts/intrinsic_without_const_stab.stderr b/tests/ui/consts/intrinsic_without_const_stab.stderr new file mode 100644 index 000000000..b32b6398e --- /dev/null +++ b/tests/ui/consts/intrinsic_without_const_stab.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `copy::copy::` in constant functions + --> $DIR/intrinsic_without_const_stab.rs:13:14 + | +LL | unsafe { copy(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/intrinsic_without_const_stab_fail.rs b/tests/ui/consts/intrinsic_without_const_stab_fail.rs new file mode 100644 index 000000000..2b0745b3c --- /dev/null +++ b/tests/ui/consts/intrinsic_without_const_stab_fail.rs @@ -0,0 +1,15 @@ +#![feature(intrinsics, staged_api)] +#![stable(feature = "core", since = "1.6.0")] + +extern "rust-intrinsic" { + fn copy(src: *const T, dst: *mut T, count: usize); +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[inline] +pub const unsafe fn stuff(src: *const T, dst: *mut T, count: usize) { + unsafe { copy(src, dst, count) } //~ ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/consts/intrinsic_without_const_stab_fail.stderr b/tests/ui/consts/intrinsic_without_const_stab_fail.stderr new file mode 100644 index 000000000..fcbb37245 --- /dev/null +++ b/tests/ui/consts/intrinsic_without_const_stab_fail.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `copy::` in constant functions + --> $DIR/intrinsic_without_const_stab_fail.rs:12:14 + | +LL | unsafe { copy(src, dst, count) } + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/invalid-const-in-body.rs b/tests/ui/consts/invalid-const-in-body.rs new file mode 100644 index 000000000..f0fa3bb7b --- /dev/null +++ b/tests/ui/consts/invalid-const-in-body.rs @@ -0,0 +1,6 @@ +fn f() -> impl Sized { + 2.0E + //~^ ERROR expected at least one digit in exponent +} + +fn main() {} diff --git a/tests/ui/consts/invalid-const-in-body.stderr b/tests/ui/consts/invalid-const-in-body.stderr new file mode 100644 index 000000000..3be658359 --- /dev/null +++ b/tests/ui/consts/invalid-const-in-body.stderr @@ -0,0 +1,8 @@ +error: expected at least one digit in exponent + --> $DIR/invalid-const-in-body.rs:2:5 + | +LL | 2.0E + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs new file mode 100644 index 000000000..4d2d8fb13 --- /dev/null +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.rs @@ -0,0 +1,9 @@ +#![allow(incomplete_features)] +#![feature(inline_const_pat)] + +fn main() { + match () { + const { (|| {})() } => {} + //~^ ERROR cannot call non-const closure in constants + } +} diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr new file mode 100644 index 000000000..257ecd7f3 --- /dev/null +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -0,0 +1,13 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/invalid-inline-const-in-match-arm.rs:6:17 + | +LL | const { (|| {})() } => {} + | ^^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/invalid-union.32bit.stderr b/tests/ui/consts/invalid-union.32bit.stderr new file mode 100644 index 000000000..0dd18a557 --- /dev/null +++ b/tests/ui/consts/invalid-union.32bit.stderr @@ -0,0 +1,26 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-union.rs:41:1 + | +LL | fn main() { + | ^^^^^^^^^ constructing invalid value at ..y..0: encountered `UnsafeCell` in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc7──╼ │ ╾──╼ + } + +note: erroneous constant used + --> $DIR/invalid-union.rs:43:25 + | +LL | let _: &'static _ = &C; + | ^^ + +note: erroneous constant used + --> $DIR/invalid-union.rs:43:25 + | +LL | let _: &'static _ = &C; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/invalid-union.64bit.stderr b/tests/ui/consts/invalid-union.64bit.stderr new file mode 100644 index 000000000..07f36ee28 --- /dev/null +++ b/tests/ui/consts/invalid-union.64bit.stderr @@ -0,0 +1,26 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-union.rs:41:1 + | +LL | fn main() { + | ^^^^^^^^^ constructing invalid value at ..y..0: encountered `UnsafeCell` in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc7────────╼ │ ╾──────╼ + } + +note: erroneous constant used + --> $DIR/invalid-union.rs:43:25 + | +LL | let _: &'static _ = &C; + | ^^ + +note: erroneous constant used + --> $DIR/invalid-union.rs:43:25 + | +LL | let _: &'static _ = &C; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/invalid-union.rs b/tests/ui/consts/invalid-union.rs new file mode 100644 index 000000000..28706b4a9 --- /dev/null +++ b/tests/ui/consts/invalid-union.rs @@ -0,0 +1,44 @@ +// Check that constants with interior mutability inside unions are rejected +// during validation. +// +// Note that this test case relies on undefined behaviour to construct a +// constant with interior mutability that is "invisible" to the static checks. +// If for some reason this approach no longer works, it is should be fine to +// remove the test case. +// +// build-fail +// stderr-per-bitwidth +#![feature(const_mut_refs)] + +use std::cell::Cell; +use std::mem::ManuallyDrop; + +#[repr(C)] +struct S { + x: u32, + y: E, +} + +#[repr(u32)] +enum E { + A, + B(U) +} + +union U { + cell: ManuallyDrop>, +} + +const C: S = { + let s = S { x: 0, y: E::A }; + // Go through an &u32 reference which is definitely not allowed to mutate anything. + let p = &s.x as *const u32 as *mut u32; + // Change enum tag to E::B. + unsafe { *p.add(1) = 1 }; + s +}; + +fn main() { //~ ERROR it is undefined behavior to use this value + // FIXME the span here is wrong, sould be pointing at the line below, not above. + let _: &'static _ = &C; +} diff --git a/tests/ui/consts/invalid_promotion.rs b/tests/ui/consts/invalid_promotion.rs new file mode 100644 index 000000000..a31eaf40e --- /dev/null +++ b/tests/ui/consts/invalid_promotion.rs @@ -0,0 +1,18 @@ +// build-pass (FIXME(62277): could be check-pass?) +// note this was only reproducible with lib crates +// compile-flags: --crate-type=lib + +pub struct Hz; + +impl Hz { + pub const fn num(&self) -> u32 { + 42 + } + pub const fn normalized(&self) -> Hz { + Hz + } + + pub const fn as_u32(&self) -> u32 { + self.normalized().num() // this used to promote the `self.normalized()` + } +} diff --git a/tests/ui/consts/issue-102117.rs b/tests/ui/consts/issue-102117.rs new file mode 100644 index 000000000..3ed90aed2 --- /dev/null +++ b/tests/ui/consts/issue-102117.rs @@ -0,0 +1,30 @@ +#![feature(inline_const, const_type_id)] + +use std::alloc::Layout; +use std::any::TypeId; +use std::mem::transmute; +use std::ptr::drop_in_place; + +pub struct VTable { + layout: Layout, + type_id: TypeId, + drop_in_place: unsafe fn(*mut ()), +} + +impl VTable { + pub fn new() -> &'static Self { + const { + &VTable { + layout: Layout::new::(), + type_id: TypeId::of::(), + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough + drop_in_place: unsafe { + transmute::(drop_in_place::) + }, + } + } + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-102117.stderr b/tests/ui/consts/issue-102117.stderr new file mode 100644 index 000000000..f42bcf90f --- /dev/null +++ b/tests/ui/consts/issue-102117.stderr @@ -0,0 +1,25 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-102117.rs:19:26 + | +LL | type_id: TypeId::of::(), + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | pub fn new() -> &'static Self { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-102117.rs:19:26 + | +LL | type_id: TypeId::of::(), + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | pub fn new() -> &'static Self { + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/consts/issue-103790.rs b/tests/ui/consts/issue-103790.rs new file mode 100644 index 000000000..ea3cac605 --- /dev/null +++ b/tests/ui/consts/issue-103790.rs @@ -0,0 +1,10 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct S; +//~^ ERROR the name `S` is already used for a generic parameter in this item's generic parameters +//~| ERROR missing generics for struct `S` +//~| ERROR cycle detected when computing type of `S::S` +//~| ERROR cycle detected when computing type of `S` + +fn main() {} diff --git a/tests/ui/consts/issue-103790.stderr b/tests/ui/consts/issue-103790.stderr new file mode 100644 index 000000000..34d8ee281 --- /dev/null +++ b/tests/ui/consts/issue-103790.stderr @@ -0,0 +1,65 @@ +error[E0403]: the name `S` is already used for a generic parameter in this item's generic parameters + --> $DIR/issue-103790.rs:4:29 + | +LL | struct S; + | - ^ already used + | | + | first use of `S` + +error[E0107]: missing generics for struct `S` + --> $DIR/issue-103790.rs:4:32 + | +LL | struct S; + | ^ expected at least 1 generic argument + | +note: struct defined here, with at least 1 generic parameter: `S` + --> $DIR/issue-103790.rs:4:8 + | +LL | struct S; + | ^ ----------- +help: add missing generic argument + | +LL | struct S = { S }>; + | +++ + +error[E0391]: cycle detected when computing type of `S::S` + --> $DIR/issue-103790.rs:4:32 + | +LL | struct S; + | ^ + | + = note: ...which immediately requires computing type of `S::S` again +note: cycle used when computing type of `S` + --> $DIR/issue-103790.rs:4:1 + | +LL | struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0391]: cycle detected when computing type of `S` + --> $DIR/issue-103790.rs:4:1 + | +LL | struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires computing type of `S::S`... + --> $DIR/issue-103790.rs:4:32 + | +LL | struct S; + | ^ + = note: ...which again requires computing type of `S`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-103790.rs:1:1 + | +LL | / #![feature(generic_const_exprs)] +LL | | #![allow(incomplete_features)] +LL | | +LL | | struct S; +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0391, E0403. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/consts/issue-104155.rs b/tests/ui/consts/issue-104155.rs new file mode 100644 index 000000000..1cc8f81b0 --- /dev/null +++ b/tests/ui/consts/issue-104155.rs @@ -0,0 +1,5 @@ +// check-pass +const _: () = core::mem::forget(Box::::default); +const _: () = core::mem::forget(|| Box::::default()); + +fn main() {} diff --git a/tests/ui/consts/issue-104396.rs b/tests/ui/consts/issue-104396.rs new file mode 100644 index 000000000..315b0cf0f --- /dev/null +++ b/tests/ui/consts/issue-104396.rs @@ -0,0 +1,36 @@ +// compile-flags: -Zmir-opt-level=3 +// check-pass + +#![feature(generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +#[inline(always)] +fn from_fn_1 f32>(mut f: F) -> [f32; N] { + let mut result = [0.0; N]; + let mut i = 0; + while i < N { + result[i] = f(i); + i += 1; + } + result +} + +pub struct TestArray +where + [(); N / 2]:, +{ + array: [f32; N / 2], +} + +impl TestArray +where + [(); N / 2]:, +{ + fn from_fn_2 f32>(f: F) -> Self { + Self { array: from_fn_1(f) } + } +} + +fn main() { + TestArray::<4>::from_fn_2(|i| 0.0); +} diff --git a/tests/ui/consts/issue-104396.stderr b/tests/ui/consts/issue-104396.stderr new file mode 100644 index 000000000..5856bee09 --- /dev/null +++ b/tests/ui/consts/issue-104396.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-104396.rs:4:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/issue-104609.rs b/tests/ui/consts/issue-104609.rs new file mode 100644 index 000000000..01fd1c48c --- /dev/null +++ b/tests/ui/consts/issue-104609.rs @@ -0,0 +1,10 @@ +fn foo() { + oops; + //~^ ERROR: cannot find value `oops` in this scope +} + +unsafe fn bar() { + std::mem::transmute::<_, *mut _>(1_u8); +} + +fn main() {} diff --git a/tests/ui/consts/issue-104609.stderr b/tests/ui/consts/issue-104609.stderr new file mode 100644 index 000000000..00360c44d --- /dev/null +++ b/tests/ui/consts/issue-104609.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `oops` in this scope + --> $DIR/issue-104609.rs:2:5 + | +LL | oops; + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/consts/issue-104768.rs b/tests/ui/consts/issue-104768.rs new file mode 100644 index 000000000..3192daafa --- /dev/null +++ b/tests/ui/consts/issue-104768.rs @@ -0,0 +1,4 @@ +const A: &_ = 0_u32; +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants + +fn main() {} diff --git a/tests/ui/consts/issue-104768.stderr b/tests/ui/consts/issue-104768.stderr new file mode 100644 index 000000000..55b2b6f04 --- /dev/null +++ b/tests/ui/consts/issue-104768.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/issue-104768.rs:1:10 + | +LL | const A: &_ = 0_u32; + | ^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/consts/issue-13837.rs b/tests/ui/consts/issue-13837.rs new file mode 100644 index 000000000..645b1c0eb --- /dev/null +++ b/tests/ui/consts/issue-13837.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct TestStruct { + x: *const [isize; 2] +} + +unsafe impl Sync for TestStruct {} + +static TEST_VALUE : TestStruct = TestStruct{x: 0x1234 as *const [isize; 2]}; + +fn main() {} diff --git a/tests/ui/consts/issue-13902.rs b/tests/ui/consts/issue-13902.rs new file mode 100644 index 000000000..1afde0ebe --- /dev/null +++ b/tests/ui/consts/issue-13902.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80; +const JSVAL_TYPE_INT32: u8 = 0x01; +const JSVAL_TYPE_UNDEFINED: u8 = 0x02; +#[repr(u32)] +enum ValueTag { + JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32), + JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32), +} + +fn main() { + let _ = ValueTag::JSVAL_TAG_INT32; +} diff --git a/tests/ui/consts/issue-17074.rs b/tests/ui/consts/issue-17074.rs new file mode 100644 index 000000000..0ed81132e --- /dev/null +++ b/tests/ui/consts/issue-17074.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + +static X2: u64 = !0 as u16 as u64; +static Y2: u64 = !0 as u32 as u64; +const X: u64 = !0 as u16 as u64; +const Y: u64 = !0 as u32 as u64; + +fn main() { + assert_eq!(match 1 { + X => unreachable!(), + Y => unreachable!(), + _ => 1 + }, 1); +} diff --git a/tests/ui/consts/issue-17458.rs b/tests/ui/consts/issue-17458.rs new file mode 100644 index 000000000..44125a1c3 --- /dev/null +++ b/tests/ui/consts/issue-17458.rs @@ -0,0 +1,6 @@ +static X: usize = unsafe { core::ptr::null::() as usize }; +//~^ ERROR: pointers cannot be cast to integers during const eval + +fn main() { + assert_eq!(X, 0); +} diff --git a/tests/ui/consts/issue-17458.stderr b/tests/ui/consts/issue-17458.stderr new file mode 100644 index 000000000..8936c8d84 --- /dev/null +++ b/tests/ui/consts/issue-17458.stderr @@ -0,0 +1,11 @@ +error: pointers cannot be cast to integers during const eval + --> $DIR/issue-17458.rs:1:28 + | +LL | static X: usize = unsafe { core::ptr::null::() as usize }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: aborting due to previous error + diff --git a/tests/ui/consts/issue-17718-borrow-interior.rs b/tests/ui/consts/issue-17718-borrow-interior.rs new file mode 100644 index 000000000..5861f2186 --- /dev/null +++ b/tests/ui/consts/issue-17718-borrow-interior.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +struct S { a: usize } + +static A: S = S { a: 3 }; +static B: &'static usize = &A.a; +static C: &'static usize = &(A.a); + +static D: [usize; 1] = [1]; +static E: usize = D[0]; +static F: &'static usize = &D[0]; + +fn main() { + assert_eq!(*B, A.a); + assert_eq!(*B, A.a); + + assert_eq!(E, D[0]); + assert_eq!(*F, D[0]); +} diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs new file mode 100644 index 000000000..62bbb3b56 --- /dev/null +++ b/tests/ui/consts/issue-17718-const-bad-values.rs @@ -0,0 +1,9 @@ +const C1: &'static mut [usize] = &mut []; +//~^ ERROR: mutable references are not allowed + +static mut S: usize = 3; +const C2: &'static mut usize = unsafe { &mut S }; +//~^ ERROR: constants cannot refer to statics +//~| ERROR: constants cannot refer to statics + +fn main() {} diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr new file mode 100644 index 000000000..ce60aaa07 --- /dev/null +++ b/tests/ui/consts/issue-17718-const-bad-values.stderr @@ -0,0 +1,26 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-17718-const-bad-values.rs:1:34 + | +LL | const C1: &'static mut [usize] = &mut []; + | ^^^^^^^ + +error[E0013]: constants cannot refer to statics + --> $DIR/issue-17718-const-bad-values.rs:5:46 + | +LL | const C2: &'static mut usize = unsafe { &mut S }; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/issue-17718-const-bad-values.rs:5:46 + | +LL | const C2: &'static mut usize = unsafe { &mut S }; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0013, E0764. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/consts/issue-17718-const-borrow.rs b/tests/ui/consts/issue-17718-const-borrow.rs new file mode 100644 index 000000000..89316dbd5 --- /dev/null +++ b/tests/ui/consts/issue-17718-const-borrow.rs @@ -0,0 +1,14 @@ +use std::cell::UnsafeCell; + +const A: UnsafeCell = UnsafeCell::new(1); +const B: &'static UnsafeCell = &A; +//~^ ERROR: cannot refer to interior mutable + +struct C { a: UnsafeCell } +const D: C = C { a: UnsafeCell::new(1) }; +const E: &'static UnsafeCell = &D.a; +//~^ ERROR: cannot refer to interior mutable +const F: &'static C = &D; +//~^ ERROR: cannot refer to interior mutable + +fn main() {} diff --git a/tests/ui/consts/issue-17718-const-borrow.stderr b/tests/ui/consts/issue-17718-const-borrow.stderr new file mode 100644 index 000000000..e3ff6c923 --- /dev/null +++ b/tests/ui/consts/issue-17718-const-borrow.stderr @@ -0,0 +1,21 @@ +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/issue-17718-const-borrow.rs:4:39 + | +LL | const B: &'static UnsafeCell = &A; + | ^^ this borrow of an interior mutable value may end up in the final value + +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/issue-17718-const-borrow.rs:9:39 + | +LL | const E: &'static UnsafeCell = &D.a; + | ^^^^ this borrow of an interior mutable value may end up in the final value + +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/issue-17718-const-borrow.rs:11:23 + | +LL | const F: &'static C = &D; + | ^^ this borrow of an interior mutable value may end up in the final value + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/issue-17718-constants-not-static.rs b/tests/ui/consts/issue-17718-constants-not-static.rs new file mode 100644 index 000000000..2e6aff161 --- /dev/null +++ b/tests/ui/consts/issue-17718-constants-not-static.rs @@ -0,0 +1,9 @@ +fn id(x: T) -> T { x } + +const FOO: usize = 3; + +fn foo() -> &'static usize { &id(FOO) } +//~^ ERROR: cannot return reference to temporary value + +fn main() { +} diff --git a/tests/ui/consts/issue-17718-constants-not-static.stderr b/tests/ui/consts/issue-17718-constants-not-static.stderr new file mode 100644 index 000000000..8f3acae71 --- /dev/null +++ b/tests/ui/consts/issue-17718-constants-not-static.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/issue-17718-constants-not-static.rs:5:30 + | +LL | fn foo() -> &'static usize { &id(FOO) } + | ^------- + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/consts/issue-17718-references.rs b/tests/ui/consts/issue-17718-references.rs new file mode 100644 index 000000000..03d5f8bb3 --- /dev/null +++ b/tests/ui/consts/issue-17718-references.rs @@ -0,0 +1,24 @@ +#![allow(warnings)] + +struct Struct { a: usize } + +const C: usize = 1; +static S: usize = 1; + +const T1: &'static usize = &C; +const T2: &'static usize = &S; //~ ERROR: constants cannot refer to statics +static T3: &'static usize = &C; +static T4: &'static usize = &S; + +const T5: usize = C; +const T6: usize = S; //~ ERROR: constants cannot refer to statics +static T7: usize = C; +static T8: usize = S; + +const T9: Struct = Struct { a: C }; +const T10: Struct = Struct { a: S }; +//~^ ERROR: constants cannot refer to statics +static T11: Struct = Struct { a: C }; +static T12: Struct = Struct { a: S }; + +fn main() {} diff --git a/tests/ui/consts/issue-17718-references.stderr b/tests/ui/consts/issue-17718-references.stderr new file mode 100644 index 000000000..e3c3b369f --- /dev/null +++ b/tests/ui/consts/issue-17718-references.stderr @@ -0,0 +1,27 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/issue-17718-references.rs:9:29 + | +LL | const T2: &'static usize = &S; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/issue-17718-references.rs:14:19 + | +LL | const T6: usize = S; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constants cannot refer to statics + --> $DIR/issue-17718-references.rs:19:33 + | +LL | const T10: Struct = Struct { a: S }; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/consts/issue-17718.rs b/tests/ui/consts/issue-17718.rs new file mode 100644 index 000000000..c6341d808 --- /dev/null +++ b/tests/ui/consts/issue-17718.rs @@ -0,0 +1,75 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-17718-aux.rs + +extern crate issue_17718_aux as other; + +use std::sync::atomic::{AtomicUsize, Ordering}; + +const C1: usize = 1; +const C2: AtomicUsize = AtomicUsize::new(0); +const C3: fn() = foo; +const C4: usize = C1 * C1 + C1 / C1; +const C5: &'static usize = &C4; +const C6: usize = { + const C: usize = 3; + C +}; + +static S1: usize = 3; +static S2: AtomicUsize = AtomicUsize::new(0); + +mod test { + static A: usize = 4; + static B: &'static usize = &A; + static C: &'static usize = &(A); +} + +fn foo() {} + +fn main() { + assert_eq!(C1, 1); + assert_eq!(C3(), ()); + assert_eq!(C2.fetch_add(1, Ordering::SeqCst), 0); + assert_eq!(C2.fetch_add(1, Ordering::SeqCst), 0); + assert_eq!(C4, 2); + assert_eq!(*C5, 2); + assert_eq!(C6, 3); + assert_eq!(S1, 3); + assert_eq!(S2.fetch_add(1, Ordering::SeqCst), 0); + assert_eq!(S2.fetch_add(1, Ordering::SeqCst), 1); + + match 1 { + C1 => {} + _ => unreachable!(), + } + + let _a = C1; + let _a = C2; + let _a = C3; + let _a = C4; + let _a = C5; + let _a = C6; + let _a = S1; + + assert_eq!(other::C1, 1); + assert_eq!(other::C3(), ()); + assert_eq!(other::C2.fetch_add(1, Ordering::SeqCst), 0); + assert_eq!(other::C2.fetch_add(1, Ordering::SeqCst), 0); + assert_eq!(other::C4, 2); + assert_eq!(*other::C5, 2); + assert_eq!(other::S1, 3); + assert_eq!(other::S2.fetch_add(1, Ordering::SeqCst), 0); + assert_eq!(other::S2.fetch_add(1, Ordering::SeqCst), 1); + + let _a = other::C1; + let _a = other::C2; + let _a = other::C3; + let _a = other::C4; + let _a = other::C5; + + match 1 { + other::C1 => {} + _ => unreachable!(), + } +} diff --git a/tests/ui/consts/issue-17756.rs b/tests/ui/consts/issue-17756.rs new file mode 100644 index 000000000..1835b177f --- /dev/null +++ b/tests/ui/consts/issue-17756.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_variables)] +#![allow(non_upper_case_globals)] + +const count : usize = 2 as usize; +fn main() { + let larger : [usize; count*2]; +} diff --git a/tests/ui/consts/issue-18294.rs b/tests/ui/consts/issue-18294.rs new file mode 100644 index 000000000..77355f0d7 --- /dev/null +++ b/tests/ui/consts/issue-18294.rs @@ -0,0 +1,5 @@ +fn main() { + const X: u32 = 1; + const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers + println!("{}", Y); +} diff --git a/tests/ui/consts/issue-18294.stderr b/tests/ui/consts/issue-18294.stderr new file mode 100644 index 000000000..e0cbd2a21 --- /dev/null +++ b/tests/ui/consts/issue-18294.stderr @@ -0,0 +1,11 @@ +error: pointers cannot be cast to integers during const eval + --> $DIR/issue-18294.rs:3:31 + | +LL | const Y: usize = unsafe { &X as *const u32 as usize }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: aborting due to previous error + diff --git a/tests/ui/consts/issue-19244.rs b/tests/ui/consts/issue-19244.rs new file mode 100644 index 000000000..44d9748fd --- /dev/null +++ b/tests/ui/consts/issue-19244.rs @@ -0,0 +1,34 @@ +// run-pass + +struct MyStruct { field: usize } +struct Nested { nested: MyStruct } +struct Mix2 { nested: ((usize,),) } + +const STRUCT: MyStruct = MyStruct { field: 42 }; +const TUP: (usize,) = (43,); +const NESTED_S: Nested = Nested { nested: MyStruct { field: 5 } }; +const NESTED_T: ((usize,),) = ((4,),); +const MIX_1: ((Nested,),) = ((Nested { nested: MyStruct { field: 3 } },),); +const MIX_2: Mix2 = Mix2 { nested: ((2,),) }; +const INSTANT_1: usize = (MyStruct { field: 1 }).field; +const INSTANT_2: usize = (0,).0; + +fn main() { + let a = [0; STRUCT.field]; + let b = [0; TUP.0]; + let c = [0; NESTED_S.nested.field]; + let d = [0; (NESTED_T.0).0]; + let e = [0; (MIX_1.0).0.nested.field]; + let f = [0; (MIX_2.nested.0).0]; + let g = [0; INSTANT_1]; + let h = [0; INSTANT_2]; + + assert_eq!(a.len(), 42); + assert_eq!(b.len(), 43); + assert_eq!(c.len(), 5); + assert_eq!(d.len(), 4); + assert_eq!(e.len(), 3); + assert_eq!(f.len(), 2); + assert_eq!(g.len(), 1); + assert_eq!(h.len(), 0); +} diff --git a/tests/ui/consts/issue-21562.rs b/tests/ui/consts/issue-21562.rs new file mode 100644 index 000000000..a47d739c6 --- /dev/null +++ b/tests/ui/consts/issue-21562.rs @@ -0,0 +1,19 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +extern crate core; +use core::marker::Sync; + +static SARRAY: [i32; 1] = [11]; + +struct MyStruct { + pub arr: *const [i32], +} +unsafe impl Sync for MyStruct {} + +static mystruct: MyStruct = MyStruct { + arr: &SARRAY +}; + +fn main() {} diff --git a/tests/ui/consts/issue-21721.rs b/tests/ui/consts/issue-21721.rs new file mode 100644 index 000000000..4c1411e1e --- /dev/null +++ b/tests/ui/consts/issue-21721.rs @@ -0,0 +1,9 @@ +// run-pass + +fn main() { + static NONE: Option<((), &'static u8)> = None; + let ptr = unsafe { + *(&NONE as *const _ as *const *const u8) + }; + assert!(ptr.is_null()); +} diff --git a/tests/ui/consts/issue-23833.rs b/tests/ui/consts/issue-23833.rs new file mode 100644 index 000000000..d4128fa54 --- /dev/null +++ b/tests/ui/consts/issue-23833.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_imports)] +use std::fmt; + +const A_I8_T + : [u32; (i8::MAX as i8 - 1i8) as usize] + = [0; (i8::MAX as usize) - 1]; + +fn main() { + foo(&A_I8_T[..]); +} + +fn foo(x: T) { + println!("{:?}", x); +} diff --git a/tests/ui/consts/issue-23968-const-not-overflow.rs b/tests/ui/consts/issue-23968-const-not-overflow.rs new file mode 100644 index 000000000..b95930212 --- /dev/null +++ b/tests/ui/consts/issue-23968-const-not-overflow.rs @@ -0,0 +1,12 @@ +// run-pass +const U8_MAX_HALF: u8 = !0u8 / 2; +const U16_MAX_HALF: u16 = !0u16 / 2; +const U32_MAX_HALF: u32 = !0u32 / 2; +const U64_MAX_HALF: u64 = !0u64 / 2; + +fn main() { + assert_eq!(U8_MAX_HALF, 0x7f); + assert_eq!(U16_MAX_HALF, 0x7fff); + assert_eq!(U32_MAX_HALF, 0x7fff_ffff); + assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff); +} diff --git a/tests/ui/consts/issue-25826.rs b/tests/ui/consts/issue-25826.rs new file mode 100644 index 000000000..c340c30a1 --- /dev/null +++ b/tests/ui/consts/issue-25826.rs @@ -0,0 +1,6 @@ +fn id(t: T) -> T { t } +fn main() { + const A: bool = unsafe { id:: as *const () < id:: as *const () }; + //~^ ERROR can't compare + println!("{}", A); +} diff --git a/tests/ui/consts/issue-25826.stderr b/tests/ui/consts/issue-25826.stderr new file mode 100644 index 000000000..905c5ee6e --- /dev/null +++ b/tests/ui/consts/issue-25826.stderr @@ -0,0 +1,16 @@ +error[E0277]: can't compare `*const ()` with `*const ()` in const contexts + --> $DIR/issue-25826.rs:3:52 + | +LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; + | ^ no implementation for `*const () < *const ()` and `*const () > *const ()` + | + = help: the trait `~const PartialOrd` is not implemented for `*const ()` +note: the trait `PartialOrd` is implemented for `*const ()`, but that implementation is not `const` + --> $DIR/issue-25826.rs:3:52 + | +LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/issue-27890.rs b/tests/ui/consts/issue-27890.rs new file mode 100644 index 000000000..9f8547338 --- /dev/null +++ b/tests/ui/consts/issue-27890.rs @@ -0,0 +1,7 @@ +// run-pass +static PLUS_ONE: &'static (dyn Fn(i32) -> i32 + Sync) = (&|x: i32| { x + 1 }) + as &'static (dyn Fn(i32) -> i32 + Sync); + +fn main() { + assert_eq!(PLUS_ONE(2), 3); +} diff --git a/tests/ui/consts/issue-28113.rs b/tests/ui/consts/issue-28113.rs new file mode 100644 index 000000000..f8131c9f3 --- /dev/null +++ b/tests/ui/consts/issue-28113.rs @@ -0,0 +1,8 @@ +#![allow(warnings)] + +const X: u8 = + || -> u8 { 5 }() + //~^ ERROR cannot call non-const closure +; + +fn main() {} diff --git a/tests/ui/consts/issue-28113.stderr b/tests/ui/consts/issue-28113.stderr new file mode 100644 index 000000000..1294cc99b --- /dev/null +++ b/tests/ui/consts/issue-28113.stderr @@ -0,0 +1,13 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/issue-28113.rs:4:5 + | +LL | || -> u8 { 5 }() + | ^^^^^^^^^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-29914-2.rs b/tests/ui/consts/issue-29914-2.rs new file mode 100644 index 000000000..626de269d --- /dev/null +++ b/tests/ui/consts/issue-29914-2.rs @@ -0,0 +1,6 @@ +// run-pass +const ARR: [usize; 5] = [5, 4, 3, 2, 1]; + +fn main() { + assert_eq!(3, ARR[ARR[3]]); +} diff --git a/tests/ui/consts/issue-29914-3.rs b/tests/ui/consts/issue-29914-3.rs new file mode 100644 index 000000000..1c6c64eb3 --- /dev/null +++ b/tests/ui/consts/issue-29914-3.rs @@ -0,0 +1,7 @@ +// run-pass +const ARR: [usize; 5] = [5, 4, 3, 2, 1]; +const BLA: usize = ARR[ARR[3]]; + +fn main() { + assert_eq!(3, BLA); +} diff --git a/tests/ui/consts/issue-29914.rs b/tests/ui/consts/issue-29914.rs new file mode 100644 index 000000000..6da63664d --- /dev/null +++ b/tests/ui/consts/issue-29914.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(stable_features)] + +#![feature(const_indexing)] + +const ARR: [usize; 5] = [5, 4, 3, 2, 1]; + +fn main() { + assert_eq!(3, ARR[ARR[3]]); +} diff --git a/tests/ui/consts/issue-29927-1.rs b/tests/ui/consts/issue-29927-1.rs new file mode 100644 index 000000000..a236e4913 --- /dev/null +++ b/tests/ui/consts/issue-29927-1.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +const fn f() -> usize { + 5 +} +struct A { + field: usize, +} +fn main() { + let _ = [0; f()]; +} diff --git a/tests/ui/consts/issue-29927.rs b/tests/ui/consts/issue-29927.rs new file mode 100644 index 000000000..3385e4e6e --- /dev/null +++ b/tests/ui/consts/issue-29927.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +struct A { + field: usize, +} +const fn f() -> usize { + 5 +} +fn main() { + let _ = [0; f()]; +} diff --git a/tests/ui/consts/issue-32829-2.rs b/tests/ui/consts/issue-32829-2.rs new file mode 100644 index 000000000..d70b5a8c4 --- /dev/null +++ b/tests/ui/consts/issue-32829-2.rs @@ -0,0 +1,71 @@ +const bad : u32 = { + { + 5; + 0 + } +}; + +const bad_two : u32 = { + { + invalid(); + //~^ ERROR: cannot call non-const fn `invalid` + 0 + } +}; + +const bad_three : u32 = { + { + valid(); + 0 + } +}; + +static bad_four : u32 = { + { + 5; + 0 + } +}; + +static bad_five : u32 = { + { + invalid(); + //~^ ERROR: cannot call non-const fn `invalid` + 0 + } +}; + +static bad_six : u32 = { + { + valid(); + 0 + } +}; + +static mut bad_seven : u32 = { + { + 5; + 0 + } +}; + +static mut bad_eight : u32 = { + { + invalid(); + //~^ ERROR: cannot call non-const fn `invalid` + 0 + } +}; + +static mut bad_nine : u32 = { + { + valid(); + 0 + } +}; + + +fn invalid() {} +const fn valid() {} + +fn main() {} diff --git a/tests/ui/consts/issue-32829-2.stderr b/tests/ui/consts/issue-32829-2.stderr new file mode 100644 index 000000000..0fec35818 --- /dev/null +++ b/tests/ui/consts/issue-32829-2.stderr @@ -0,0 +1,29 @@ +error[E0015]: cannot call non-const fn `invalid` in constants + --> $DIR/issue-32829-2.rs:10:9 + | +LL | invalid(); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `invalid` in statics + --> $DIR/issue-32829-2.rs:32:9 + | +LL | invalid(); + | ^^^^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error[E0015]: cannot call non-const fn `invalid` in statics + --> $DIR/issue-32829-2.rs:54:9 + | +LL | invalid(); + | ^^^^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-32829.rs b/tests/ui/consts/issue-32829.rs new file mode 100644 index 000000000..25f323b98 --- /dev/null +++ b/tests/ui/consts/issue-32829.rs @@ -0,0 +1,6 @@ +static S : u64 = { { panic!("foo"); 0 } }; +//~^ ERROR could not evaluate static initializer + +fn main() { + println!("{:?}", S); +} diff --git a/tests/ui/consts/issue-32829.stderr b/tests/ui/consts/issue-32829.stderr new file mode 100644 index 000000000..cae5163f0 --- /dev/null +++ b/tests/ui/consts/issue-32829.stderr @@ -0,0 +1,11 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/issue-32829.rs:1:22 + | +LL | static S : u64 = { { panic!("foo"); 0 } }; + | ^^^^^^^^^^^^^ the evaluated program panicked at 'foo', $DIR/issue-32829.rs:1:22 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-33537.rs b/tests/ui/consts/issue-33537.rs new file mode 100644 index 000000000..3539aa647 --- /dev/null +++ b/tests/ui/consts/issue-33537.rs @@ -0,0 +1,14 @@ +// run-pass + +const fn foo() -> *const i8 { + b"foo" as *const _ as *const i8 +} + +const fn bar() -> i32 { + *&{(1, 2, 3).1} +} + +fn main() { + assert_eq!(foo(), b"foo" as *const _ as *const i8); + assert_eq!(bar(), 2); +} diff --git a/tests/ui/consts/issue-34784.rs b/tests/ui/consts/issue-34784.rs new file mode 100644 index 000000000..98d943470 --- /dev/null +++ b/tests/ui/consts/issue-34784.rs @@ -0,0 +1,21 @@ +// run-pass + +#![warn(pointer_structural_match)] +#![allow(dead_code)] +const C: *const u8 = &0; + +fn foo(x: *const u8) { + match x { + C => {} + _ => {} + } +} + +const D: *const [u8; 4] = b"abcd"; + +fn main() { + match D { + D => {} + _ => {} + } +} diff --git a/tests/ui/consts/issue-3521.fixed b/tests/ui/consts/issue-3521.fixed new file mode 100644 index 000000000..f76106dff --- /dev/null +++ b/tests/ui/consts/issue-3521.fixed @@ -0,0 +1,13 @@ +// run-rustfix +fn main() { + #[allow(non_upper_case_globals)] + const foo: isize = 100; + + #[derive(Debug)] + enum Stuff { + Bar = foo + //~^ ERROR attempt to use a non-constant value in a constant + } + + println!("{:?}", Stuff::Bar); +} diff --git a/tests/ui/consts/issue-3521.rs b/tests/ui/consts/issue-3521.rs new file mode 100644 index 000000000..c425a22df --- /dev/null +++ b/tests/ui/consts/issue-3521.rs @@ -0,0 +1,13 @@ +// run-rustfix +fn main() { + #[allow(non_upper_case_globals)] + let foo: isize = 100; + + #[derive(Debug)] + enum Stuff { + Bar = foo + //~^ ERROR attempt to use a non-constant value in a constant + } + + println!("{:?}", Stuff::Bar); +} diff --git a/tests/ui/consts/issue-3521.stderr b/tests/ui/consts/issue-3521.stderr new file mode 100644 index 000000000..aa42772f1 --- /dev/null +++ b/tests/ui/consts/issue-3521.stderr @@ -0,0 +1,12 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-3521.rs:8:15 + | +LL | let foo: isize = 100; + | ------- help: consider using `const` instead of `let`: `const foo` +... +LL | Bar = foo + | ^^^ non-constant value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/issue-36163.rs b/tests/ui/consts/issue-36163.rs new file mode 100644 index 000000000..340d2c399 --- /dev/null +++ b/tests/ui/consts/issue-36163.rs @@ -0,0 +1,7 @@ +const A: isize = Foo::B as isize; + +enum Foo { + B = A, //~ ERROR E0391 +} + +fn main() {} diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr new file mode 100644 index 000000000..7137c0538 --- /dev/null +++ b/tests/ui/consts/issue-36163.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{constant#0}` + --> $DIR/issue-36163.rs:4:9 + | +LL | B = A, + | ^ + | +note: ...which requires const-evaluating + checking `A`... + --> $DIR/issue-36163.rs:1:18 + | +LL | const A: isize = Foo::B as isize; + | ^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle +note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}` + --> $DIR/issue-36163.rs:4:9 + | +LL | B = A, + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/issue-37222.rs b/tests/ui/consts/issue-37222.rs new file mode 100644 index 000000000..8ea5f6b7a --- /dev/null +++ b/tests/ui/consts/issue-37222.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#[derive(Debug, PartialEq)] +enum Bar { + A(i64), + B(i32), + C, +} + +#[derive(Debug, PartialEq)] +struct Foo(Bar, u8); + +static FOO: [Foo; 2] = [Foo(Bar::C, 0), Foo(Bar::C, 0xFF)]; + +fn main() { + assert_eq!(&FOO[1], &Foo(Bar::C, 0xFF)); +} diff --git a/tests/ui/consts/issue-37550-1.rs b/tests/ui/consts/issue-37550-1.rs new file mode 100644 index 000000000..4d00ac7fd --- /dev/null +++ b/tests/ui/consts/issue-37550-1.rs @@ -0,0 +1,8 @@ +// check-pass + +const fn x() { + let t = true; + let x = || t; +} + +fn main() {} diff --git a/tests/ui/consts/issue-37550.rs b/tests/ui/consts/issue-37550.rs new file mode 100644 index 000000000..724eb2829 --- /dev/null +++ b/tests/ui/consts/issue-37550.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +const fn x() { + let t = true; + let x = || t; +} + +fn main() {} diff --git a/tests/ui/consts/issue-37991.rs b/tests/ui/consts/issue-37991.rs new file mode 100644 index 000000000..a6ac4d5ca --- /dev/null +++ b/tests/ui/consts/issue-37991.rs @@ -0,0 +1,17 @@ +// run-pass + +const fn foo() -> i64 { + 3 +} + +const fn bar(x: i64) -> i64 { + x*2 +} + +fn main() { + let val = &(foo() % 2); + assert_eq!(*val, 1); + + let val2 = &(bar(1+1) % 3); + assert_eq!(*val2, 1); +} diff --git a/tests/ui/consts/issue-39161-bogus-error.rs b/tests/ui/consts/issue-39161-bogus-error.rs new file mode 100644 index 000000000..a954385da --- /dev/null +++ b/tests/ui/consts/issue-39161-bogus-error.rs @@ -0,0 +1,13 @@ +// check-pass + +pub struct X { + pub a: i32, + pub b: i32, +} + +fn main() { + const DX: X = X { a: 0, b: 0 }; + const _X1: X = X { a: 1, ..DX }; + let _x2 = X { a: 1, b: 2, ..DX }; + const _X3: X = X { a: 1, b: 2, ..DX }; +} diff --git a/tests/ui/consts/issue-39974.rs b/tests/ui/consts/issue-39974.rs new file mode 100644 index 000000000..503647ef4 --- /dev/null +++ b/tests/ui/consts/issue-39974.rs @@ -0,0 +1,11 @@ +const LENGTH: f64 = 2; + +struct Thing { + f: [[f64; 2]; LENGTH], + //~^ ERROR mismatched types + //~| expected `usize`, found `f64` +} + +fn main() { + let _t = Thing { f: [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]] }; +} diff --git a/tests/ui/consts/issue-39974.stderr b/tests/ui/consts/issue-39974.stderr new file mode 100644 index 000000000..56365e51e --- /dev/null +++ b/tests/ui/consts/issue-39974.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-39974.rs:4:19 + | +LL | f: [[f64; 2]; LENGTH], + | ^^^^^^ expected `usize`, found `f64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/issue-43105.rs b/tests/ui/consts/issue-43105.rs new file mode 100644 index 000000000..cac12b909 --- /dev/null +++ b/tests/ui/consts/issue-43105.rs @@ -0,0 +1,13 @@ +fn xyz() -> u8 { 42 } + +const NUM: u8 = xyz(); +//~^ ERROR cannot call non-const fn + +fn main() { + match 1 { + NUM => unimplemented!(), + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + _ => unimplemented!(), + } +} diff --git a/tests/ui/consts/issue-43105.stderr b/tests/ui/consts/issue-43105.stderr new file mode 100644 index 000000000..2d1174af7 --- /dev/null +++ b/tests/ui/consts/issue-43105.stderr @@ -0,0 +1,23 @@ +error[E0015]: cannot call non-const fn `xyz` in constants + --> $DIR/issue-43105.rs:3:17 + | +LL | const NUM: u8 = xyz(); + | ^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: could not evaluate constant pattern + --> $DIR/issue-43105.rs:8:9 + | +LL | NUM => unimplemented!(), + | ^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-43105.rs:8:9 + | +LL | NUM => unimplemented!(), + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-44415.rs b/tests/ui/consts/issue-44415.rs new file mode 100644 index 000000000..d93b451be --- /dev/null +++ b/tests/ui/consts/issue-44415.rs @@ -0,0 +1,11 @@ +#![feature(core_intrinsics)] + +use std::intrinsics; + +struct Foo { + bytes: [u8; unsafe { intrinsics::size_of::() }], + //~^ ERROR cycle detected when evaluating type-level constant + x: usize, +} + +fn main() {} diff --git a/tests/ui/consts/issue-44415.stderr b/tests/ui/consts/issue-44415.stderr new file mode 100644 index 000000000..ec64b956d --- /dev/null +++ b/tests/ui/consts/issue-44415.stderr @@ -0,0 +1,29 @@ +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... + --> $DIR/issue-44415.rs:6:17 + | +LL | bytes: [u8; unsafe { intrinsics::size_of::() }], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `Foo`... + = note: ...which requires computing layout of `[u8; unsafe { intrinsics::size_of::() }]`... + = note: ...which requires normalizing `[u8; unsafe { intrinsics::size_of::() }]`... + = note: ...which again requires evaluating type-level constant, completing the cycle +note: cycle used when checking that `Foo` is well-formed + --> $DIR/issue-44415.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/issue-46553.rs b/tests/ui/consts/issue-46553.rs new file mode 100644 index 000000000..abeaf10f2 --- /dev/null +++ b/tests/ui/consts/issue-46553.rs @@ -0,0 +1,21 @@ +// run-pass + +pub struct Data { + function: fn() -> T, +} + +impl Data { + pub const fn new(function: fn() -> T) -> Data { + Data { + function: function, + } + } +} + +pub static DATA: Data = Data::new(|| { + 413i32 +}); + +fn main() { + print!("{:?}", (DATA.function)()); +} diff --git a/tests/ui/consts/issue-47789.rs b/tests/ui/consts/issue-47789.rs new file mode 100644 index 000000000..32dd909b2 --- /dev/null +++ b/tests/ui/consts/issue-47789.rs @@ -0,0 +1,10 @@ +// check-pass +#![allow(non_upper_case_globals)] + +static mut x: &'static u32 = &0; + +fn foo() { + unsafe { x = &1; } +} + +fn main() { } diff --git a/tests/ui/consts/issue-50439.rs b/tests/ui/consts/issue-50439.rs new file mode 100644 index 000000000..0be7c4054 --- /dev/null +++ b/tests/ui/consts/issue-50439.rs @@ -0,0 +1,29 @@ +#![feature(specialization)] +#![allow(incomplete_features)] + +pub trait ReflectDrop { + const REFLECT_DROP: bool = false; +} + +impl ReflectDrop for T where T: Clone {} + +pub trait PinDropInternal { + fn is_valid() + where + Self: ReflectDrop; +} + +struct Bears(T); + +default impl ReflectDrop for Bears {} + +impl PinDropInternal for Bears { + fn is_valid() + where + Self: ReflectDrop, + { + let _ = [(); 0 - !!( as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-50439.stderr b/tests/ui/consts/issue-50439.stderr new file mode 100644 index 000000000..3fbdf33b2 --- /dev/null +++ b/tests/ui/consts/issue-50439.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-50439.rs:25:22 + | +LL | let _ = [(); 0 - !!( as ReflectDrop>::REFLECT_DROP) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/consts/issue-52023-array-size-pointer-cast.rs b/tests/ui/consts/issue-52023-array-size-pointer-cast.rs new file mode 100644 index 000000000..2249d9879 --- /dev/null +++ b/tests/ui/consts/issue-52023-array-size-pointer-cast.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = [0; (&0 as *const i32) as usize]; //~ ERROR pointers cannot be cast to integers during const eval +} diff --git a/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr b/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr new file mode 100644 index 000000000..9a3d5716e --- /dev/null +++ b/tests/ui/consts/issue-52023-array-size-pointer-cast.stderr @@ -0,0 +1,11 @@ +error: pointers cannot be cast to integers during const eval + --> $DIR/issue-52023-array-size-pointer-cast.rs:2:17 + | +LL | let _ = [0; (&0 as *const i32) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: aborting due to previous error + diff --git a/tests/ui/consts/issue-52060.rs b/tests/ui/consts/issue-52060.rs new file mode 100644 index 000000000..13b914c03 --- /dev/null +++ b/tests/ui/consts/issue-52060.rs @@ -0,0 +1,7 @@ +// Regression test for https://github.com/rust-lang/rust/issues/52060 +// The compiler shouldn't ICE in this case +static A: &'static [u32] = &[1]; +static B: [u32; 1] = [0; A.len()]; +//~^ ERROR [E0013] + +fn main() {} diff --git a/tests/ui/consts/issue-52060.stderr b/tests/ui/consts/issue-52060.stderr new file mode 100644 index 000000000..95e5f2a82 --- /dev/null +++ b/tests/ui/consts/issue-52060.stderr @@ -0,0 +1,11 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/issue-52060.rs:4:26 + | +LL | static B: [u32; 1] = [0; A.len()]; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/consts/issue-54224.rs b/tests/ui/consts/issue-54224.rs new file mode 100644 index 000000000..f1947933d --- /dev/null +++ b/tests/ui/consts/issue-54224.rs @@ -0,0 +1,12 @@ +const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); //~ ERROR temporary value dropped while borrowed + +use std::borrow::Cow; + +pub const X: [u8; 3] = *b"ABC"; +pub const Y: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[X]); + + +pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]); +//~^ ERROR temporary value dropped while borrowed + +fn main() {} diff --git a/tests/ui/consts/issue-54224.stderr b/tests/ui/consts/issue-54224.stderr new file mode 100644 index 000000000..55fe55759 --- /dev/null +++ b/tests/ui/consts/issue-54224.stderr @@ -0,0 +1,23 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-54224.rs:1:39 + | +LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); + | ------^^^^^^^^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-54224.rs:9:57 + | +LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]); + | ---------------^^^^^^^^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/issue-54348.rs b/tests/ui/consts/issue-54348.rs new file mode 100644 index 000000000..5c38d7c42 --- /dev/null +++ b/tests/ui/consts/issue-54348.rs @@ -0,0 +1,7 @@ +// build-fail + +fn main() { + [1][0u64 as usize]; + [1][1.5 as usize]; //~ ERROR operation will panic + [1][1u64 as usize]; //~ ERROR operation will panic +} diff --git a/tests/ui/consts/issue-54348.stderr b/tests/ui/consts/issue-54348.stderr new file mode 100644 index 000000000..eb85f3498 --- /dev/null +++ b/tests/ui/consts/issue-54348.stderr @@ -0,0 +1,16 @@ +error: this operation will panic at runtime + --> $DIR/issue-54348.rs:5:5 + | +LL | [1][1.5 as usize]; + | ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-54348.rs:6:5 + | +LL | [1][1u64 as usize]; + | ^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/issue-54387.rs b/tests/ui/consts/issue-54387.rs new file mode 100644 index 000000000..60e3a02f4 --- /dev/null +++ b/tests/ui/consts/issue-54387.rs @@ -0,0 +1,12 @@ +// check-pass + +pub struct GstRc { + _obj: *const (), + _borrowed: bool, +} + +const FOO: Option = None; + +fn main() { + let _meh = FOO; +} diff --git a/tests/ui/consts/issue-54954.rs b/tests/ui/consts/issue-54954.rs new file mode 100644 index 000000000..520bf508f --- /dev/null +++ b/tests/ui/consts/issue-54954.rs @@ -0,0 +1,19 @@ +const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); +//~^ ERROR E0790 + +trait Tt { + const fn const_val() -> usize { + //~^ ERROR functions in traits cannot be declared const + core::mem::size_of::() + } +} + +fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + //~^ constant + //~| constant + z +} + +fn main() { + let _ = f([1f32; ARR_LEN]); +} diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr new file mode 100644 index 000000000..850558287 --- /dev/null +++ b/tests/ui/consts/issue-54954.stderr @@ -0,0 +1,34 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/issue-54954.rs:5:5 + | +LL | const fn const_val() -> usize { + | ^^^^^ functions in traits cannot be const + +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/issue-54954.rs:1:24 + | +LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait +... +LL | / const fn const_val() -> usize { +LL | | +LL | | core::mem::size_of::() +LL | | } + | |_____- `Tt::const_val` defined here + +note: erroneous constant used + --> $DIR/issue-54954.rs:11:15 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ + +note: erroneous constant used + --> $DIR/issue-54954.rs:11:34 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0379, E0790. +For more information about an error, try `rustc --explain E0379`. diff --git a/tests/ui/consts/issue-56164.rs b/tests/ui/consts/issue-56164.rs new file mode 100644 index 000000000..22c257d0b --- /dev/null +++ b/tests/ui/consts/issue-56164.rs @@ -0,0 +1,10 @@ +const fn foo() { (||{})() } +//~^ ERROR cannot call non-const closure + +const fn bad(input: fn()) { + input() + //~^ ERROR function pointer calls are not allowed +} + +fn main() { +} diff --git a/tests/ui/consts/issue-56164.stderr b/tests/ui/consts/issue-56164.stderr new file mode 100644 index 000000000..845b23d5d --- /dev/null +++ b/tests/ui/consts/issue-56164.stderr @@ -0,0 +1,31 @@ +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/issue-56164.rs:1:18 + | +LL | const fn foo() { (||{})() } + | ^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constant functions + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: function pointer calls are not allowed in constant functions + --> $DIR/issue-56164.rs:5:5 + | +LL | input() + | ^^^^^^^ + +note: erroneous constant used + --> $DIR/issue-56164.rs:1:18 + | +LL | const fn foo() { (||{})() } + | ^^^^^^ + +note: erroneous constant used + --> $DIR/issue-56164.rs:1:18 + | +LL | const fn foo() { (||{})() } + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-58435-ice-with-assoc-const.rs b/tests/ui/consts/issue-58435-ice-with-assoc-const.rs new file mode 100644 index 000000000..fac727d2d --- /dev/null +++ b/tests/ui/consts/issue-58435-ice-with-assoc-const.rs @@ -0,0 +1,18 @@ +// run-pass +// The const-evaluator was at one point ICE'ing while trying to +// evaluate the body of `fn id` during the `s.id()` call in main. + +struct S(T); + +impl S { + const ID: fn(&S) -> &S = |s| s; + pub fn id(&self) -> &Self { + Self::ID(self) // This, plus call below ... + } +} + +fn main() { + let s = S(10u32); + assert!(S::::ID(&s).0 == 10); // Works fine + assert!(s.id().0 == 10); // ... causes compiler to panic +} diff --git a/tests/ui/consts/issue-62045.rs b/tests/ui/consts/issue-62045.rs new file mode 100644 index 000000000..5abed374a --- /dev/null +++ b/tests/ui/consts/issue-62045.rs @@ -0,0 +1,5 @@ +// check-pass + +fn main() { + assert_eq!(&mut [0; 1][..], &mut []); +} diff --git a/tests/ui/consts/issue-63226.rs b/tests/ui/consts/issue-63226.rs new file mode 100644 index 000000000..deec44990 --- /dev/null +++ b/tests/ui/consts/issue-63226.rs @@ -0,0 +1,12 @@ +// aux-build:issue-63226.rs +// compile-flags:--extern issue_63226 +// edition:2018 +// build-pass +// A regression test for issue #63226. +// Checks if `const fn` is marked as reachable. + +use issue_63226::VTable; + +static ICE_ICE:&'static VTable=VTable::vtable(); + +fn main() {} diff --git a/tests/ui/consts/issue-63952.32bit.stderr b/tests/ui/consts/issue-63952.32bit.stderr new file mode 100644 index 000000000..755c7fb7d --- /dev/null +++ b/tests/ui/consts/issue-63952.32bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-63952.rs:17:1 + | +LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─alloc4──╼ ff ff ff ff │ ╾──╼.... + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-63952.64bit.stderr b/tests/ui/consts/issue-63952.64bit.stderr new file mode 100644 index 000000000..abdb9a4f7 --- /dev/null +++ b/tests/ui/consts/issue-63952.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-63952.rs:17:1 + | +LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc4────────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-63952.rs b/tests/ui/consts/issue-63952.rs new file mode 100644 index 000000000..5c83e6f45 --- /dev/null +++ b/tests/ui/consts/issue-63952.rs @@ -0,0 +1,27 @@ +// Regression test for #63952, shouldn't hang. +// stderr-per-bitwidth + +#[repr(C)] +#[derive(Copy, Clone)] +struct SliceRepr { + ptr: *const u8, + len: usize, +} + +union SliceTransmute { + repr: SliceRepr, + slice: &'static [u8], +} + +// bad slice: length too big to even exist anywhere +const SLICE_WAY_TOO_LONG: &[u8] = unsafe { //~ ERROR: it is undefined behavior to use this value + SliceTransmute { + repr: SliceRepr { + ptr: &42, + len: usize::MAX, + }, + } + .slice +}; + +fn main() {} diff --git a/tests/ui/consts/issue-64059.rs b/tests/ui/consts/issue-64059.rs new file mode 100644 index 000000000..02c8b7250 --- /dev/null +++ b/tests/ui/consts/issue-64059.rs @@ -0,0 +1,10 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +// run-pass + +fn main() { + let _ = -(-0.0); +} diff --git a/tests/ui/consts/issue-64506.rs b/tests/ui/consts/issue-64506.rs new file mode 100644 index 000000000..db3e85a7b --- /dev/null +++ b/tests/ui/consts/issue-64506.rs @@ -0,0 +1,20 @@ +// check-pass + +#[derive(Copy, Clone)] +pub struct ChildStdin { + inner: AnonPipe, +} + +#[derive(Copy, Clone)] +enum AnonPipe {} + +const FOO: () = { + union Foo { + a: ChildStdin, + b: (), + } + let x = unsafe { Foo { b: () }.a }; + let x = &x.inner; +}; + +fn main() {} diff --git a/tests/ui/consts/issue-64662.rs b/tests/ui/consts/issue-64662.rs new file mode 100644 index 000000000..e3a8c8583 --- /dev/null +++ b/tests/ui/consts/issue-64662.rs @@ -0,0 +1,10 @@ +enum Foo { + A = foo(), //~ ERROR: type annotations needed + B = foo(), //~ ERROR: type annotations needed +} + +const fn foo() -> isize { + 0 +} + +fn main() {} diff --git a/tests/ui/consts/issue-64662.stderr b/tests/ui/consts/issue-64662.stderr new file mode 100644 index 000000000..21a419711 --- /dev/null +++ b/tests/ui/consts/issue-64662.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/issue-64662.rs:2:9 + | +LL | A = foo(), + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | +help: consider specifying the generic argument + | +LL | A = foo::(), + | +++++ + +error[E0282]: type annotations needed + --> $DIR/issue-64662.rs:3:9 + | +LL | B = foo(), + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | +help: consider specifying the generic argument + | +LL | B = foo::(), + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/consts/issue-65348.rs b/tests/ui/consts/issue-65348.rs new file mode 100644 index 000000000..5eafa831d --- /dev/null +++ b/tests/ui/consts/issue-65348.rs @@ -0,0 +1,23 @@ +// check-pass + +struct Generic(T); + +impl Generic { + const ARRAY: [T; 0] = []; + const NEWTYPE_ARRAY: Generic<[T; 0]> = Generic([]); + const ARRAY_FIELD: Generic<(i32, [T; 0])> = Generic((0, [])); +} + +pub const fn array() -> &'static T { + &Generic::::ARRAY[0] +} + +pub const fn newtype_array() -> &'static T { + &Generic::::NEWTYPE_ARRAY.0[0] +} + +pub const fn array_field() -> &'static T { + &(Generic::::ARRAY_FIELD.0).1[0] +} + +fn main() {} diff --git a/tests/ui/consts/issue-66342.rs b/tests/ui/consts/issue-66342.rs new file mode 100644 index 000000000..417f69041 --- /dev/null +++ b/tests/ui/consts/issue-66342.rs @@ -0,0 +1,12 @@ +// check-pass +// only-x86_64 + +// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash. + +fn foo() -> [u8; 4 * 1024 * 1024 * 1024 * 1024] { + unimplemented!() +} + +fn main() { + foo(); +} diff --git a/tests/ui/consts/issue-66345.rs b/tests/ui/consts/issue-66345.rs new file mode 100644 index 000000000..4971d9647 --- /dev/null +++ b/tests/ui/consts/issue-66345.rs @@ -0,0 +1,24 @@ +// run-pass +// compile-flags: -Z mir-opt-level=4 + +// Checks that the compiler does not ICE when passing references to field of by-value struct +// with -Z mir-opt-level=4 + +fn do_nothing(_: &()) {} + +pub struct Foo { + bar: (), +} + +pub fn by_value_1(foo: Foo) { + do_nothing(&foo.bar); +} + +pub fn by_value_2(foo: Foo) { + do_nothing(&foo.bar); +} + +fn main() { + by_value_1(Foo { bar: () }); + by_value_2::<()>(Foo { bar: () }); +} diff --git a/tests/ui/consts/issue-66397.rs b/tests/ui/consts/issue-66397.rs new file mode 100644 index 000000000..1b4aff43b --- /dev/null +++ b/tests/ui/consts/issue-66397.rs @@ -0,0 +1,8 @@ +// check-pass +// only-x86_64 + +// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash. + +fn main() { + [0; 4 * 1024 * 1024 * 1024 * 1024]; +} diff --git a/tests/ui/consts/issue-66693-panic-in-array-len.rs b/tests/ui/consts/issue-66693-panic-in-array-len.rs new file mode 100644 index 000000000..fc0dcd7a4 --- /dev/null +++ b/tests/ui/consts/issue-66693-panic-in-array-len.rs @@ -0,0 +1,15 @@ +// This is a separate test from `issue-66693.rs` because array lengths are evaluated +// in a separate stage before `const`s and `statics` and so the error below is hit and +// the compiler exits before generating errors for the others. + +fn main() { + let _ = [0i32; panic!(2f32)]; + //~^ ERROR: argument to `panic!()` in a const context must have type `&str` + + // ensure that conforming panics are handled correctly + let _ = [false; panic!()]; + //~^ ERROR: evaluation of constant value failed + + // typechecking halts before getting to this one + let _ = ['a', panic!("panic in array len")]; +} diff --git a/tests/ui/consts/issue-66693-panic-in-array-len.stderr b/tests/ui/consts/issue-66693-panic-in-array-len.stderr new file mode 100644 index 000000000..1585ea317 --- /dev/null +++ b/tests/ui/consts/issue-66693-panic-in-array-len.stderr @@ -0,0 +1,19 @@ +error: argument to `panic!()` in a const context must have type `&str` + --> $DIR/issue-66693-panic-in-array-len.rs:6:20 + | +LL | let _ = [0i32; panic!(2f32)]; + | ^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-66693-panic-in-array-len.rs:10:21 + | +LL | let _ = [false; panic!()]; + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-66693-panic-in-array-len.rs:10:21 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-66693.rs b/tests/ui/consts/issue-66693.rs new file mode 100644 index 000000000..df45d01ec --- /dev/null +++ b/tests/ui/consts/issue-66693.rs @@ -0,0 +1,23 @@ +// Tests that the compiler does not ICE when const-evaluating a `panic!()` invocation with a +// non-`&str` argument. + +const _: () = panic!(1); +//~^ ERROR: argument to `panic!()` in a const context must have type `&str` + +static _FOO: () = panic!(true); +//~^ ERROR: argument to `panic!()` in a const context must have type `&str` + +const fn _foo() { + panic!(&1); + //~^ ERROR: argument to `panic!()` in a const context must have type `&str` +} + +// ensure that conforming panics don't cause an error +const _: () = panic!(); +static _BAR: () = panic!("panic in static"); + +const fn _bar() { + panic!("panic in const fn"); +} + +fn main() {} diff --git a/tests/ui/consts/issue-66693.stderr b/tests/ui/consts/issue-66693.stderr new file mode 100644 index 000000000..e9a3fced6 --- /dev/null +++ b/tests/ui/consts/issue-66693.stderr @@ -0,0 +1,38 @@ +error: argument to `panic!()` in a const context must have type `&str` + --> $DIR/issue-66693.rs:4:15 + | +LL | const _: () = panic!(1); + | ^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: argument to `panic!()` in a const context must have type `&str` + --> $DIR/issue-66693.rs:7:19 + | +LL | static _FOO: () = panic!(true); + | ^^^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: argument to `panic!()` in a const context must have type `&str` + --> $DIR/issue-66693.rs:11:5 + | +LL | panic!(&1); + | ^^^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-66693.rs:11:12 + | +LL | panic!(&1); + | ^^ + +note: erroneous constant used + --> $DIR/issue-66693.rs:11:12 + | +LL | panic!(&1); + | ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/consts/issue-66787.rs b/tests/ui/consts/issue-66787.rs new file mode 100644 index 000000000..612b795eb --- /dev/null +++ b/tests/ui/consts/issue-66787.rs @@ -0,0 +1,39 @@ +// build-pass +// compile-flags: --crate-type lib + +// Regression test for ICE which occurred when const propagating an enum with three variants +// one of which is uninhabited. + +pub enum ApiError {} +#[allow(dead_code)] +pub struct TokioError { + b: bool, +} +pub enum Error { + Api { + source: ApiError, + }, + Ethereum, + Tokio { + source: TokioError, + }, +} +struct Api; +impl IntoError for Api +{ + type Source = ApiError; + fn into_error(self, error: Self::Source) -> Error { + Error::Api { + source: (|v| v)(error), + } + } +} + +pub trait IntoError +{ + /// The underlying error + type Source; + + /// Combine the information to produce the error + fn into_error(self, source: Self::Source) -> E; +} diff --git a/tests/ui/consts/issue-67529.rs b/tests/ui/consts/issue-67529.rs new file mode 100644 index 000000000..dd24c2d27 --- /dev/null +++ b/tests/ui/consts/issue-67529.rs @@ -0,0 +1,11 @@ +// compile-flags: -Z mir-opt-level=3 +// run-pass + +struct Baz { + a: T +} + +fn main() { + let d : Baz<[i32; 4]> = Baz { a: [1,2,3,4] }; + assert_eq!([1, 2, 3, 4], d.a); +} diff --git a/tests/ui/consts/issue-67640.rs b/tests/ui/consts/issue-67640.rs new file mode 100644 index 000000000..4c71a2e02 --- /dev/null +++ b/tests/ui/consts/issue-67640.rs @@ -0,0 +1,24 @@ +// compile-flags: -Z mir-opt-level=4 +// run-pass + +struct X { + x: isize +} + +fn f1(a: &mut X, b: &mut isize, c: isize) -> isize { + let r = a.x + *b + c; + a.x = 0; + *b = 10; + return r; +} + +fn f2(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; } + +pub fn main() { + let mut a = X {x: 1}; + let mut b = 2; + let c = 3; + assert_eq!(f1(&mut a, &mut b, c), 6); + assert_eq!(a.x, 0); + assert_eq!(f2(a.x, |_| a.x = 50), 0); +} diff --git a/tests/ui/consts/issue-67641.rs b/tests/ui/consts/issue-67641.rs new file mode 100644 index 000000000..e5a74f156 --- /dev/null +++ b/tests/ui/consts/issue-67641.rs @@ -0,0 +1,24 @@ +// compile-flags: -Z mir-opt-level=3 +// run-pass + +use std::cell::Cell; + +#[derive(Debug)] +struct B<'a> { + a: [Cell>>; 2] +} + +impl<'a> B<'a> { + fn new() -> B<'a> { + B { a: [Cell::new(None), Cell::new(None)] } + } +} + +fn f() { + let b2 = B::new(); + b2.a[0].set(Some(&b2)); +} + +fn main() { + f(); +} diff --git a/tests/ui/consts/issue-67696-const-prop-ice.rs b/tests/ui/consts/issue-67696-const-prop-ice.rs new file mode 100644 index 000000000..ad52608b3 --- /dev/null +++ b/tests/ui/consts/issue-67696-const-prop-ice.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: --emit=mir,link +// Checks that we don't ICE due to attempting to run const prop +// on a function with unsatisifable 'where' clauses + +#![allow(unused)] + +trait A { + fn foo(&self) -> Self where Self: Copy; +} + +impl A for [fn(&())] { + fn foo(&self) -> Self where Self: Copy { *(&[] as &[_]) } +} + +impl A for i32 { + fn foo(&self) -> Self { 3 } +} + +fn main() {} diff --git a/tests/ui/consts/issue-67862.rs b/tests/ui/consts/issue-67862.rs new file mode 100644 index 000000000..b9e96a87f --- /dev/null +++ b/tests/ui/consts/issue-67862.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z mir-opt-level=3 +// run-pass + +fn e220() -> (i64, i64) { + #[inline(never)] + fn get_displacement() -> [i64; 2] { + [139776, 963904] + } + + let res = get_displacement(); + match (&res[0], &res[1]) { + (arg0, arg1) => (*arg0, *arg1), + } +} + +fn main() { + assert_eq!(e220(), (139776, 963904)); +} diff --git a/tests/ui/consts/issue-68264-overflow.rs b/tests/ui/consts/issue-68264-overflow.rs new file mode 100644 index 000000000..8f21e0648 --- /dev/null +++ b/tests/ui/consts/issue-68264-overflow.rs @@ -0,0 +1,43 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for issue #68264 +// Checks that we don't encounter overflow +// when running const-prop on functions with +// complicated bounds +pub trait Query {} + +pub trait AsQuery { + type Query: Query; +} +pub trait Table: AsQuery + Sized {} + +pub trait LimitDsl { + type Output; +} + +pub(crate) trait LoadQuery: RunQueryDsl {} + +impl AsQuery for T { + type Query = Self; +} + +impl LimitDsl for T +where + T: Table, + T::Query: LimitDsl, +{ + type Output = ::Output; +} + +pub(crate) trait RunQueryDsl: Sized { + fn first(self, _conn: &Conn) -> U + where + Self: LimitDsl, + Self::Output: LoadQuery, + { + // Overflow is caused by this function body + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-68542-closure-in-array-len.rs b/tests/ui/consts/issue-68542-closure-in-array-len.rs new file mode 100644 index 000000000..37958e791 --- /dev/null +++ b/tests/ui/consts/issue-68542-closure-in-array-len.rs @@ -0,0 +1,9 @@ +// Regression test for issue #68542 +// Tests that we don't ICE when a closure appears +// in the length part of an array. + +struct Bug { + a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure +} + +fn main() {} diff --git a/tests/ui/consts/issue-68542-closure-in-array-len.stderr b/tests/ui/consts/issue-68542-closure-in-array-len.stderr new file mode 100644 index 000000000..d23513ed7 --- /dev/null +++ b/tests/ui/consts/issue-68542-closure-in-array-len.stderr @@ -0,0 +1,13 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/issue-68542-closure-in-array-len.rs:6:13 + | +LL | a: [(); (|| { 0 })()] + | ^^^^^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-68684.rs b/tests/ui/consts/issue-68684.rs new file mode 100644 index 000000000..c98f199b6 --- /dev/null +++ b/tests/ui/consts/issue-68684.rs @@ -0,0 +1,15 @@ +// check-pass + +enum _Enum { + A(), +} + +type _E = _Enum; + +const fn _a() -> _Enum { + _E::A() +} + +const _A: _Enum = _a(); + +fn main() {} diff --git a/tests/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs b/tests/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs new file mode 100644 index 000000000..5b7c7be42 --- /dev/null +++ b/tests/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs @@ -0,0 +1,91 @@ +// build-pass +// +// (this is deliberately *not* check-pass; I have confirmed that the bug in +// question does not replicate when one uses `cargo check` alone.) + +pub enum Void {} + +enum UninhabitedUnivariant { + _Variant(Void), +} + +enum UninhabitedMultivariant2 { + _Variant(Void), + _Warriont(Void), +} + +enum UninhabitedMultivariant3 { + _Variant(Void), + _Warriont(Void), + _Worrynot(Void), +} + +#[repr(C)] +enum UninhabitedUnivariantC { + _Variant(Void), +} + +#[repr(i32)] +enum UninhabitedUnivariant32 { + _Variant(Void), +} + +fn main() { + let _seed: UninhabitedUnivariant = None.unwrap(); + match _seed { + UninhabitedUnivariant::_Variant(_x) => {} + } + + let _seed: UninhabitedMultivariant2 = None.unwrap(); + match _seed { + UninhabitedMultivariant2::_Variant(_x) => {} + UninhabitedMultivariant2::_Warriont(_x) => {} + } + + let _seed: UninhabitedMultivariant2 = None.unwrap(); + match _seed { + UninhabitedMultivariant2::_Variant(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant2 = None.unwrap(); + match _seed { + UninhabitedMultivariant2::_Warriont(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Variant(_x) => {} + UninhabitedMultivariant3::_Warriont(_x) => {} + UninhabitedMultivariant3::_Worrynot(_x) => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Variant(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Warriont(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Worrynot(_x) => {} + _ => {} + } + + let _seed: UninhabitedUnivariantC = None.unwrap(); + match _seed { + UninhabitedUnivariantC::_Variant(_x) => {} + } + + let _seed: UninhabitedUnivariant32 = None.unwrap(); + match _seed { + UninhabitedUnivariant32::_Variant(_x) => {} + } +} diff --git a/tests/ui/consts/issue-69310-array-size-lit-wrong-ty.rs b/tests/ui/consts/issue-69310-array-size-lit-wrong-ty.rs new file mode 100644 index 000000000..f0d5fea8e --- /dev/null +++ b/tests/ui/consts/issue-69310-array-size-lit-wrong-ty.rs @@ -0,0 +1,11 @@ +// This is a regression test for #69310, which was injected by #68118. +// The issue here was that as a performance optimization, +// we call the query `lit_to_const(input);`. +// However, the literal `input.lit` would not be of the type expected by `input.ty`. +// As a result, we immediately called `bug!(...)` instead of bubbling up the problem +// so that it could be handled by the caller of `lit_to_const` (`from_anon_const`). + +fn main() {} + +const A: [(); 0.1] = [()]; //~ ERROR mismatched types +const B: [(); b"a"] = [()]; //~ ERROR mismatched types diff --git a/tests/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr b/tests/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr new file mode 100644 index 000000000..7078b4bd7 --- /dev/null +++ b/tests/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-69310-array-size-lit-wrong-ty.rs:10:15 + | +LL | const A: [(); 0.1] = [()]; + | ^^^ expected `usize`, found floating-point number + +error[E0308]: mismatched types + --> $DIR/issue-69310-array-size-lit-wrong-ty.rs:11:15 + | +LL | const B: [(); b"a"] = [()]; + | ^^^^ expected `usize`, found `&[u8; 1]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/issue-69312.rs b/tests/ui/consts/issue-69312.rs new file mode 100644 index 000000000..413c67520 --- /dev/null +++ b/tests/ui/consts/issue-69312.rs @@ -0,0 +1,10 @@ +// build-pass + +// Verify that the compiler doesn't ICE during const prop while evaluating the index operation. + +#![allow(unconditional_panic)] + +fn main() { + let cols = [0u32; 0]; + cols[0]; +} diff --git a/tests/ui/consts/issue-69488.rs b/tests/ui/consts/issue-69488.rs new file mode 100644 index 000000000..46546eada --- /dev/null +++ b/tests/ui/consts/issue-69488.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(const_ptr_write)] +#![feature(const_mut_refs)] + +// Or, equivalently: `MaybeUninit`. +pub union BagOfBits { + uninit: (), + _storage: T, +} + +pub const fn make_1u8_bag() -> BagOfBits { + assert!(core::mem::size_of::() >= 1); + let mut bag = BagOfBits { uninit: () }; + unsafe { (&mut bag as *mut _ as *mut u8).write(1); }; + bag +} + +pub fn check_bag(bag: &BagOfBits) { + let val = unsafe { (bag as *const _ as *const u8).read() }; + assert_eq!(val, 1); +} + +fn main() { + check_bag(&make_1u8_bag::<[usize; 1]>()); // Fine + check_bag(&make_1u8_bag::()); // Fine + + const CONST_ARRAY_BAG: BagOfBits<[usize; 1]> = make_1u8_bag(); + check_bag(&CONST_ARRAY_BAG); // Fine. + const CONST_USIZE_BAG: BagOfBits = make_1u8_bag(); + + // Used to panic since CTFE would make the entire `BagOfBits` uninit + check_bag(&CONST_USIZE_BAG); +} diff --git a/tests/ui/consts/issue-69532.rs b/tests/ui/consts/issue-69532.rs new file mode 100644 index 000000000..0a8917812 --- /dev/null +++ b/tests/ui/consts/issue-69532.rs @@ -0,0 +1,23 @@ +// run-pass + +const fn make_nans() -> (f64, f64, f32, f32) { + let nan1: f64 = unsafe { std::mem::transmute(0x7FF0_0001_0000_0001u64) }; + let nan2: f64 = unsafe { std::mem::transmute(0x7FF0_0000_0000_0001u64) }; + + let nan1_32 = nan1 as f32; + let nan2_32 = nan2 as f32; + + (nan1, nan2, nan1_32, nan2_32) +} + +static NANS: (f64, f64, f32, f32) = make_nans(); + +fn main() { + let (nan1, nan2, nan1_32, nan2_32) = NANS; + + assert!(nan1.is_nan()); + assert!(nan2.is_nan()); + + assert!(nan1_32.is_nan()); + assert!(nan2_32.is_nan()); +} diff --git a/tests/ui/consts/issue-6991.rs b/tests/ui/consts/issue-6991.rs new file mode 100644 index 000000000..f00cd9aef --- /dev/null +++ b/tests/ui/consts/issue-6991.rs @@ -0,0 +1,8 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +static x: &'static usize = &1; +static y: usize = *x; + +fn main() {} diff --git a/tests/ui/consts/issue-70773-mir-typeck-lt-norm.rs b/tests/ui/consts/issue-70773-mir-typeck-lt-norm.rs new file mode 100644 index 000000000..dd56faa31 --- /dev/null +++ b/tests/ui/consts/issue-70773-mir-typeck-lt-norm.rs @@ -0,0 +1,16 @@ +// run-pass + +const HASH_LEN: usize = 20; +struct Hash(#[allow(unused_tuple_struct_fields)] [u8; HASH_LEN]); +fn init_hash(_: &mut [u8; HASH_LEN]) {} + +fn foo<'a>() -> &'a () { + Hash([0; HASH_LEN]); + init_hash(&mut [0; HASH_LEN]); + let (_array,) = ([0; HASH_LEN],); + &() +} + +fn main() { + foo(); +} diff --git a/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.rs b/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.rs new file mode 100644 index 000000000..b65f53450 --- /dev/null +++ b/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.rs @@ -0,0 +1,14 @@ +trait Nat { + const VALUE: usize; +} + +struct Zero; + +impl Nat for Zero { + const VALUE: i32 = 0; + //~^ ERROR implemented const `VALUE` has an incompatible type for trait +} + +fn main() { + let _: [i32; Zero::VALUE] = []; +} diff --git a/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr b/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr new file mode 100644 index 000000000..1597120fb --- /dev/null +++ b/tests/ui/consts/issue-70942-trait-vs-impl-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0326]: implemented const `VALUE` has an incompatible type for trait + --> $DIR/issue-70942-trait-vs-impl-mismatch.rs:8:18 + | +LL | const VALUE: i32 = 0; + | ^^^ expected `usize`, found `i32` + | +note: type in trait + --> $DIR/issue-70942-trait-vs-impl-mismatch.rs:2:18 + | +LL | const VALUE: usize; + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/consts/issue-73976-monomorphic.rs b/tests/ui/consts/issue-73976-monomorphic.rs new file mode 100644 index 000000000..addcc1eaa --- /dev/null +++ b/tests/ui/consts/issue-73976-monomorphic.rs @@ -0,0 +1,37 @@ +// check-pass +// +// This test is complement to the test in issue-73976-polymorphic.rs. +// In that test we ensure that polymorphic use of type_id and type_name in patterns +// will be properly rejected. This test will ensure that monomorphic use of these +// would not be wrongly rejected in patterns. + +#![feature(const_type_id)] +#![feature(const_type_name)] +#![feature(const_trait_impl)] + +use std::any::{self, TypeId}; + +pub struct GetTypeId(T); + +impl GetTypeId { + pub const VALUE: TypeId = TypeId::of::(); +} + +const fn check_type_id() -> bool { + GetTypeId::::VALUE == GetTypeId::::VALUE +} + +pub struct GetTypeNameLen(T); + +impl GetTypeNameLen { + pub const VALUE: usize = any::type_name::().len(); +} + +const fn check_type_name_len() -> bool { + matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) +} + +fn main() { + assert!(check_type_id::()); + assert!(check_type_name_len::()); +} diff --git a/tests/ui/consts/issue-73976-polymorphic.rs b/tests/ui/consts/issue-73976-polymorphic.rs new file mode 100644 index 000000000..787462da9 --- /dev/null +++ b/tests/ui/consts/issue-73976-polymorphic.rs @@ -0,0 +1,40 @@ +// This test is from #73976. We previously did not check if a type is monomorphized +// before calculating its type id, which leads to the bizarre behaviour below that +// TypeId of a generic type does not match itself. +// +// This test case should either run-pass or be rejected at compile time. +// Currently we just disallow this usage and require pattern is monomorphic. + +#![feature(const_type_id)] +#![feature(const_type_name)] + +use std::any::{self, TypeId}; + +pub struct GetTypeId(T); + +impl GetTypeId { + pub const VALUE: TypeId = TypeId::of::(); +} + +const fn check_type_id() -> bool { + matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter +} + +pub struct GetTypeNameLen(T); + +impl GetTypeNameLen { + pub const VALUE: usize = any::type_name::().len(); +} + +const fn check_type_name_len() -> bool { + matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter +} + +fn main() { + assert!(check_type_id::()); + assert!(check_type_name_len::()); +} diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr new file mode 100644 index 000000000..442ad23f2 --- /dev/null +++ b/tests/ui/consts/issue-73976-polymorphic.stderr @@ -0,0 +1,26 @@ +error: constant pattern depends on a generic parameter + --> $DIR/issue-73976-polymorphic.rs:20:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-73976-polymorphic.rs:32:42 + | +LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-73976-polymorphic.rs:20:37 + | +LL | matches!(GetTypeId::::VALUE, GetTypeId::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-73976-polymorphic.rs:32:42 + | +LL | matches!(GetTypeNameLen::::VALUE, GetTypeNameLen::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/consts/issue-76064.rs b/tests/ui/consts/issue-76064.rs new file mode 100644 index 000000000..3c153ad72 --- /dev/null +++ b/tests/ui/consts/issue-76064.rs @@ -0,0 +1,3 @@ +struct Bug([u8; panic!("panic")]); //~ ERROR evaluation of constant value failed + +fn main() {} diff --git a/tests/ui/consts/issue-76064.stderr b/tests/ui/consts/issue-76064.stderr new file mode 100644 index 000000000..67b2e90db --- /dev/null +++ b/tests/ui/consts/issue-76064.stderr @@ -0,0 +1,11 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-76064.rs:1:17 + | +LL | struct Bug([u8; panic!("panic")]); + | ^^^^^^^^^^^^^^^ the evaluated program panicked at 'panic', $DIR/issue-76064.rs:1:17 + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-77062-large-zst-array.rs b/tests/ui/consts/issue-77062-large-zst-array.rs new file mode 100644 index 000000000..0566b802e --- /dev/null +++ b/tests/ui/consts/issue-77062-large-zst-array.rs @@ -0,0 +1,5 @@ +// build-pass + +fn main() { + let _ = &[(); usize::MAX]; +} diff --git a/tests/ui/consts/issue-78655.rs b/tests/ui/consts/issue-78655.rs new file mode 100644 index 000000000..82d2d7c21 --- /dev/null +++ b/tests/ui/consts/issue-78655.rs @@ -0,0 +1,10 @@ +const FOO: *const u32 = { + let x; + &x //~ ERROR E0381 +}; + +fn main() { + let FOO = FOO; + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern +} diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr new file mode 100644 index 000000000..6b83fa0e5 --- /dev/null +++ b/tests/ui/consts/issue-78655.stderr @@ -0,0 +1,28 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/issue-78655.rs:3:5 + | +LL | let x; + | - binding declared here but left uninitialized +LL | &x + | ^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ + +error: could not evaluate constant pattern + --> $DIR/issue-78655.rs:7:9 + | +LL | let FOO = FOO; + | ^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-78655.rs:7:9 + | +LL | let FOO = FOO; + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/consts/issue-79137-monomorphic.rs b/tests/ui/consts/issue-79137-monomorphic.rs new file mode 100644 index 000000000..58e0c387f --- /dev/null +++ b/tests/ui/consts/issue-79137-monomorphic.rs @@ -0,0 +1,19 @@ +// check-pass + +// Verify that variant count intrinsic can still evaluate for types like `Option`. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::>::VALUE, GetVariantCount::>::VALUE) +} + +fn main() { + assert!(check_variant_count::<()>()); +} diff --git a/tests/ui/consts/issue-79137-toogeneric.rs b/tests/ui/consts/issue-79137-toogeneric.rs new file mode 100644 index 000000000..456035458 --- /dev/null +++ b/tests/ui/consts/issue-79137-toogeneric.rs @@ -0,0 +1,19 @@ +// Test that `variant_count` only gets evaluated once the type is concrete enough. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter +} + +fn main() { + assert!(check_variant_count::>()); +} diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr new file mode 100644 index 000000000..579e6aa09 --- /dev/null +++ b/tests/ui/consts/issue-79137-toogeneric.stderr @@ -0,0 +1,14 @@ +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:12:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:12:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/issue-79152-const-array-index.rs b/tests/ui/consts/issue-79152-const-array-index.rs new file mode 100644 index 000000000..95518e1bb --- /dev/null +++ b/tests/ui/consts/issue-79152-const-array-index.rs @@ -0,0 +1,11 @@ +// check-pass +// Regression test for issue #79152 +// +// Tests that we can index an array in a const function + +const fn foo() { + let mut array = [[0; 1]; 1]; + array[0][0] = 1; +} + +fn main() {} diff --git a/tests/ui/consts/issue-79690.64bit.stderr b/tests/ui/consts/issue-79690.64bit.stderr new file mode 100644 index 000000000..b8798a975 --- /dev/null +++ b/tests/ui/consts/issue-79690.64bit.stderr @@ -0,0 +1,14 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-79690.rs:30:1 + | +LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; + | ^^^^^^^^^^^^ constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc3────────╼ ╾───────alloc4────────╼ │ ╾──────╼╾──────╼ + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-79690.rs b/tests/ui/consts/issue-79690.rs new file mode 100644 index 000000000..56747bf5a --- /dev/null +++ b/tests/ui/consts/issue-79690.rs @@ -0,0 +1,33 @@ +// ignore-32bit +// This test gives a different error on 32-bit architectures. +// stderr-per-bitwidth + +union Transmute { + t: T, + u: U, +} +trait Bar { + fn bar(&self) -> u32; +} +struct Foo { + foo: u32, + bar: bool, +} +impl Bar for Foo { + fn bar(&self) -> u32 { + self.foo + } +} +#[derive(Copy, Clone)] +struct Fat<'a>(&'a Foo, &'static VTable); +struct VTable { + size: Foo, +} +const FOO: &dyn Bar = &Foo { + foo: 128, + bar: false, +}; +const G: Fat = unsafe { Transmute { t: FOO }.u }; +//~^ ERROR it is undefined behavior to use this value + +fn main() {} diff --git a/tests/ui/consts/issue-83182.rs b/tests/ui/consts/issue-83182.rs new file mode 100644 index 000000000..b62f903bd --- /dev/null +++ b/tests/ui/consts/issue-83182.rs @@ -0,0 +1,9 @@ +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" + +use std::mem; +struct MyStr(str); +const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; +//~^ ERROR: it is undefined behavior to use this value +fn main() {} diff --git a/tests/ui/consts/issue-83182.stderr b/tests/ui/consts/issue-83182.stderr new file mode 100644 index 000000000..1d578f910 --- /dev/null +++ b/tests/ui/consts/issue-83182.stderr @@ -0,0 +1,15 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-83182.rs:7:1 + | +LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/issue-87046.rs b/tests/ui/consts/issue-87046.rs new file mode 100644 index 000000000..4b8f9f536 --- /dev/null +++ b/tests/ui/consts/issue-87046.rs @@ -0,0 +1,33 @@ +// Regression test for the ICE described in #87046. + +#![crate_type="lib"] +#![allow(unreachable_patterns)] + +#[derive(PartialEq, Eq)] +#[repr(transparent)] +pub struct Username(str); + +pub const ROOT_USER: &Username = Username::from_str("root"); + +impl Username { + pub const fn from_str(raw: &str) -> &Self { + union Transmute<'a> { + raw: &'a str, + typed: &'a Username, + } + + unsafe { Transmute { raw }.typed } + } + + pub const fn as_str(&self) -> &str { + &self.0 + } + + pub fn is_root(&self) -> bool { + match self { + ROOT_USER => true, + //~^ ERROR: cannot use unsized non-slice type `Username` in constant patterns + _ => false, + } + } +} diff --git a/tests/ui/consts/issue-87046.stderr b/tests/ui/consts/issue-87046.stderr new file mode 100644 index 000000000..d0dbb21ce --- /dev/null +++ b/tests/ui/consts/issue-87046.stderr @@ -0,0 +1,8 @@ +error: cannot use unsized non-slice type `Username` in constant patterns + --> $DIR/issue-87046.rs:28:13 + | +LL | ROOT_USER => true, + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/issue-88071.rs b/tests/ui/consts/issue-88071.rs new file mode 100644 index 000000000..f58cdb594 --- /dev/null +++ b/tests/ui/consts/issue-88071.rs @@ -0,0 +1,18 @@ +// check-pass +// +// regression test for #88071 + +use std::collections::BTreeMap; + +pub struct CustomMap(BTreeMap); + +impl CustomMap +where + K: Ord, +{ + pub const fn new() -> Self { + CustomMap(BTreeMap::new()) + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-88649.rs b/tests/ui/consts/issue-88649.rs new file mode 100644 index 000000000..43e562b5a --- /dev/null +++ b/tests/ui/consts/issue-88649.rs @@ -0,0 +1,18 @@ +// check-pass +#![crate_type = "lib"] + +enum Foo { + Variant1(bool), + Variant2(bool), +} + +const _: () = { + let mut n = 0; + while n < 2 { + match Foo::Variant1(true) { + Foo::Variant1(x) | Foo::Variant2(x) if x => {} + _ => {} + } + n += 1; + } +}; diff --git a/tests/ui/consts/issue-89088.rs b/tests/ui/consts/issue-89088.rs new file mode 100644 index 000000000..40cc665fb --- /dev/null +++ b/tests/ui/consts/issue-89088.rs @@ -0,0 +1,22 @@ +// Regression test for the ICE described in #89088. + +// check-pass + +#![allow(indirect_structural_match)] +use std::borrow::Cow; + +const FOO: &A = &A::Field(Cow::Borrowed("foo")); + +#[derive(PartialEq, Eq)] +enum A { + Field(Cow<'static, str>) +} + +fn main() { + let var = A::Field(Cow::Borrowed("bar")); + + match &var { + FOO => todo!(), + _ => todo!() + } +} diff --git a/tests/ui/consts/issue-90762.rs b/tests/ui/consts/issue-90762.rs new file mode 100644 index 000000000..78d387386 --- /dev/null +++ b/tests/ui/consts/issue-90762.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(unreachable_code)] + +use std::sync::atomic::{AtomicBool, Ordering, AtomicUsize}; + +struct Print(usize); + +impl Drop for Print { + fn drop(&mut self) { + println!("{}", self.0); + FOO[self.0].store(true, Ordering::Relaxed); + assert_eq!(BAR.fetch_sub(1, Ordering::Relaxed), self.0); + } +} + +const A: Print = Print(0); +const B: Print = Print(1); + +static FOO: [AtomicBool; 3] = + [AtomicBool::new(false), AtomicBool::new(false), AtomicBool::new(false)]; +static BAR: AtomicUsize = AtomicUsize::new(2); + +fn main() { + loop { + std::mem::forget(({ A }, B, Print(2), break)); + } + for (i, b) in FOO.iter().enumerate() { + assert!(b.load(Ordering::Relaxed), "{} not set", i); + } + assert_eq!(BAR.fetch_add(1, Ordering::Relaxed), usize::max_value()); +} diff --git a/tests/ui/consts/issue-90870.fixed b/tests/ui/consts/issue-90870.fixed new file mode 100644 index 000000000..df44689ef --- /dev/null +++ b/tests/ui/consts/issue-90870.fixed @@ -0,0 +1,37 @@ +// Regression test for issue #90870. + +// run-rustfix + +#![allow(dead_code)] + +const fn f(a: &u8, b: &u8) -> bool { + *a == *b + //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` +} + +const fn g(a: &&&&i64, b: &&&&i64) -> bool { + ****a == ****b + //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` +} + +const fn h(mut a: &[u8], mut b: &[u8]) -> bool { + while let ([l, at @ ..], [r, bt @ ..]) = (a, b) { + if *l == *r { + //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` + a = at; + b = bt; + } else { + return false; + } + } + + a.is_empty() && b.is_empty() +} + +fn main() {} diff --git a/tests/ui/consts/issue-90870.rs b/tests/ui/consts/issue-90870.rs new file mode 100644 index 000000000..676ac73c6 --- /dev/null +++ b/tests/ui/consts/issue-90870.rs @@ -0,0 +1,37 @@ +// Regression test for issue #90870. + +// run-rustfix + +#![allow(dead_code)] + +const fn f(a: &u8, b: &u8) -> bool { + a == b + //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` +} + +const fn g(a: &&&&i64, b: &&&&i64) -> bool { + a == b + //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` +} + +const fn h(mut a: &[u8], mut b: &[u8]) -> bool { + while let ([l, at @ ..], [r, bt @ ..]) = (a, b) { + if l == r { + //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` + a = at; + b = bt; + } else { + return false; + } + } + + a.is_empty() && b.is_empty() +} + +fn main() {} diff --git a/tests/ui/consts/issue-90870.stderr b/tests/ui/consts/issue-90870.stderr new file mode 100644 index 000000000..8825efd14 --- /dev/null +++ b/tests/ui/consts/issue-90870.stderr @@ -0,0 +1,42 @@ +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/issue-90870.rs:8:5 + | +LL | a == b + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable +help: consider dereferencing here + | +LL | *a == *b + | + + + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/issue-90870.rs:15:5 + | +LL | a == b + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable +help: consider dereferencing here + | +LL | ****a == ****b + | ++++ ++++ + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/issue-90870.rs:23:12 + | +LL | if l == r { + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable +help: consider dereferencing here + | +LL | if *l == *r { + | + + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-90878-2.rs b/tests/ui/consts/issue-90878-2.rs new file mode 100644 index 000000000..e5bcecce6 --- /dev/null +++ b/tests/ui/consts/issue-90878-2.rs @@ -0,0 +1,10 @@ + #![l=|x|[b;x ]] //~ ERROR unexpected expression: `|x| [b; x]` +//~^ ERROR cannot find attribute `l` in this scope + +// notice the space at the start, +// we can't attach any attributes to this file because it needs to be at the start + +// this example has been slightly modified (adding ]] at the end), so that it actually works here +// it still produces the same issue though + +fn main() {} diff --git a/tests/ui/consts/issue-90878-2.stderr b/tests/ui/consts/issue-90878-2.stderr new file mode 100644 index 000000000..71b8d21fb --- /dev/null +++ b/tests/ui/consts/issue-90878-2.stderr @@ -0,0 +1,14 @@ +error: unexpected expression: `|x| [b; x]` + --> $DIR/issue-90878-2.rs:1:7 + | +LL | #![l=|x|[b;x ]] + | ^^^^^^^^^ + +error: cannot find attribute `l` in this scope + --> $DIR/issue-90878-2.rs:1:5 + | +LL | #![l=|x|[b;x ]] + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/issue-90878-3.rs b/tests/ui/consts/issue-90878-3.rs new file mode 100644 index 000000000..0e36646eb --- /dev/null +++ b/tests/ui/consts/issue-90878-3.rs @@ -0,0 +1,6 @@ + +fn main() { + |x: usize| [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] + // (note the newline before "fn") +} +// ignore-tidy-leading-newlines diff --git a/tests/ui/consts/issue-90878-3.stderr b/tests/ui/consts/issue-90878-3.stderr new file mode 100644 index 000000000..1bcc0eb37 --- /dev/null +++ b/tests/ui/consts/issue-90878-3.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878-3.rs:3:20 + | +LL | |x: usize| [0; x]; + | - ^ + | | + | this would need to be a `const` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/issue-90878.rs b/tests/ui/consts/issue-90878.rs new file mode 100644 index 000000000..43f6fe5f3 --- /dev/null +++ b/tests/ui/consts/issue-90878.rs @@ -0,0 +1,4 @@ + fn main() { + |x: usize| [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] + // (note the space before "fn") +} diff --git a/tests/ui/consts/issue-90878.stderr b/tests/ui/consts/issue-90878.stderr new file mode 100644 index 000000000..c038fc622 --- /dev/null +++ b/tests/ui/consts/issue-90878.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-90878.rs:2:20 + | +LL | |x: usize| [0; x]; + | - ^ + | | + | this would need to be a `const` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/issue-91434.rs b/tests/ui/consts/issue-91434.rs new file mode 100644 index 000000000..001dc708f --- /dev/null +++ b/tests/ui/consts/issue-91434.rs @@ -0,0 +1,5 @@ +fn main() { + [9; [[9E; h]]]; + //~^ ERROR: expected at least one digit in exponent + //~| ERROR: cannot find value `h` in this scope [E0425] +} diff --git a/tests/ui/consts/issue-91434.stderr b/tests/ui/consts/issue-91434.stderr new file mode 100644 index 000000000..08d3ad770 --- /dev/null +++ b/tests/ui/consts/issue-91434.stderr @@ -0,0 +1,15 @@ +error: expected at least one digit in exponent + --> $DIR/issue-91434.rs:2:11 + | +LL | [9; [[9E; h]]]; + | ^^ + +error[E0425]: cannot find value `h` in this scope + --> $DIR/issue-91434.rs:2:15 + | +LL | [9; [[9E; h]]]; + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/consts/issue-91560.fixed b/tests/ui/consts/issue-91560.fixed new file mode 100644 index 000000000..41b9d9573 --- /dev/null +++ b/tests/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/tests/ui/consts/issue-91560.rs b/tests/ui/consts/issue-91560.rs new file mode 100644 index 000000000..04592feb5 --- /dev/null +++ b/tests/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/tests/ui/consts/issue-91560.stderr b/tests/ui/consts/issue-91560.stderr new file mode 100644 index 000000000..e1b5d4cac --- /dev/null +++ b/tests/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/tests/ui/consts/issue-94371.rs b/tests/ui/consts/issue-94371.rs new file mode 100644 index 000000000..de9ff730b --- /dev/null +++ b/tests/ui/consts/issue-94371.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(const_swap)] +#![feature(const_mut_refs)] + +#[repr(C)] +struct Demo(u64, bool, u64, u32, u64, u64, u64); + +const C: (Demo, Demo) = { + let mut x = Demo(1, true, 3, 4, 5, 6, 7); + let mut y = Demo(10, false, 12, 13, 14, 15, 16); + std::mem::swap(&mut x, &mut y); + (x, y) +}; + +fn main() {} diff --git a/tests/ui/consts/issue-94675.rs b/tests/ui/consts/issue-94675.rs new file mode 100644 index 000000000..ce21ebdb9 --- /dev/null +++ b/tests/ui/consts/issue-94675.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl, const_mut_refs)] + +struct Foo<'a> { + bar: &'a mut Vec, +} + +impl<'a> Foo<'a> { + const fn spam(&mut self, baz: &mut Vec) { + self.bar[0] = baz.len(); + //~^ the trait bound `Vec: ~const Index<_>` is not satisfied + //~| the trait bound `Vec: ~const IndexMut` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/consts/issue-94675.stderr b/tests/ui/consts/issue-94675.stderr new file mode 100644 index 000000000..f4683f7f5 --- /dev/null +++ b/tests/ui/consts/issue-94675.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `Vec: ~const Index<_>` is not satisfied + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ vector indices are of type `usize` or ranges of `usize` + | + = help: the trait `~const Index<_>` is not implemented for `Vec` +note: the trait `Index<_>` is implemented for `Vec`, but that implementation is not `const` + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ + +error[E0277]: the trait bound `Vec: ~const IndexMut` is not satisfied + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ vector indices are of type `usize` or ranges of `usize` + | + = help: the trait `~const IndexMut` is not implemented for `Vec` +note: the trait `IndexMut` is implemented for `Vec`, but that implementation is not `const` + --> $DIR/issue-94675.rs:9:9 + | +LL | self.bar[0] = baz.len(); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/issue-96169.rs b/tests/ui/consts/issue-96169.rs new file mode 100644 index 000000000..14c0a1399 --- /dev/null +++ b/tests/ui/consts/issue-96169.rs @@ -0,0 +1,18 @@ +// check-pass +// compile-flags: -Zmir-opt-level=4 --emit=mir +#![allow(unused)] +fn a() -> usize { 0 } + +fn bar(_: u32) {} + +fn baz() -> *const dyn Fn(u32) { unimplemented!() } + +fn foo() { + match () { + _ if baz() == &bar as &dyn Fn(u32) => (), + () => (), + } +} + +fn main() { +} diff --git a/tests/ui/consts/issue-broken-mir.rs b/tests/ui/consts/issue-broken-mir.rs new file mode 100644 index 000000000..36f0ff921 --- /dev/null +++ b/tests/ui/consts/issue-broken-mir.rs @@ -0,0 +1,10 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/27918 + +fn main() { + match b" " { + b"1234" => {}, + _ => {}, + } +} diff --git a/tests/ui/consts/issue-miri-1910.rs b/tests/ui/consts/issue-miri-1910.rs new file mode 100644 index 000000000..29e0ea950 --- /dev/null +++ b/tests/ui/consts/issue-miri-1910.rs @@ -0,0 +1,12 @@ +// error-pattern unable to turn pointer into raw bytes +// normalize-stderr-test: "alloc[0-9]+\+0x[a-z0-9]+" -> "ALLOC" +#![feature(const_ptr_read)] + +const C: () = unsafe { + let foo = Some(&42 as *const i32); + let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3; + (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); +}; + +fn main() { +} diff --git a/tests/ui/consts/issue-miri-1910.stderr b/tests/ui/consts/issue-miri-1910.stderr new file mode 100644 index 000000000..61865b1da --- /dev/null +++ b/tests/ui/consts/issue-miri-1910.stderr @@ -0,0 +1,20 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: unable to copy parts of a pointer from memory at ALLOC + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported +note: inside `std::ptr::read::` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `ptr::const_ptr::::read` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `C` + --> $DIR/issue-miri-1910.rs:8:5 + | +LL | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/large_const_alloc.rs b/tests/ui/consts/large_const_alloc.rs new file mode 100644 index 000000000..54abaab22 --- /dev/null +++ b/tests/ui/consts/large_const_alloc.rs @@ -0,0 +1,18 @@ +// only-64bit +// on 32bit and 16bit platforms it is plausible that the maximum allocation size will succeed + +const FOO: () = { + // 128 TiB, unlikely anyone has that much RAM + let x = [0_u8; (1 << 47) - 1]; + //~^ ERROR evaluation of constant value failed +}; + +static FOO2: () = { + let x = [0_u8; (1 << 47) - 1]; + //~^ ERROR could not evaluate static initializer +}; + +fn main() { + let _ = FOO; + let _ = FOO2; +} diff --git a/tests/ui/consts/large_const_alloc.stderr b/tests/ui/consts/large_const_alloc.stderr new file mode 100644 index 000000000..25d660f12 --- /dev/null +++ b/tests/ui/consts/large_const_alloc.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/large_const_alloc.rs:6:13 + | +LL | let x = [0_u8; (1 << 47) - 1]; + | ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +error[E0080]: could not evaluate static initializer + --> $DIR/large_const_alloc.rs:11:13 + | +LL | let x = [0_u8; (1 << 47) - 1]; + | ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/locals-in-const-fn.rs b/tests/ui/consts/locals-in-const-fn.rs new file mode 100644 index 000000000..95d50171a --- /dev/null +++ b/tests/ui/consts/locals-in-const-fn.rs @@ -0,0 +1,35 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/48821 + +const fn foo(i: usize) -> usize { + let x = i; + x +} + +static FOO: usize = foo(42); + +const fn bar(mut i: usize) -> usize { + i += 8; + let x = &i; + *x +} + +static BAR: usize = bar(42); + +const fn boo(mut i: usize) -> usize { + { + let mut x = i; + x += 10; + i = x; + } + i +} + +static BOO: usize = boo(42); + +fn main() { + assert!(FOO == 42); + assert!(BAR == 50); + assert!(BOO == 52); +} diff --git a/tests/ui/consts/match-const-fn-structs.rs b/tests/ui/consts/match-const-fn-structs.rs new file mode 100644 index 000000000..5a68048c4 --- /dev/null +++ b/tests/ui/consts/match-const-fn-structs.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_variables)] + +// https://github.com/rust-lang/rust/issues/46114 + +#[derive(Eq, PartialEq)] +struct A { value: u32 } + +const fn new(value: u32) -> A { + A { value } +} + +const A_1: A = new(1); +const A_2: A = new(2); + +fn main() { + let a_str = match new(42) { + A_1 => "A 1", + A_2 => "A 2", + _ => "Unknown A", + }; +} diff --git a/tests/ui/consts/match_ice.rs b/tests/ui/consts/match_ice.rs new file mode 100644 index 000000000..632335c84 --- /dev/null +++ b/tests/ui/consts/match_ice.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/53708 + +struct S; + +#[derive(PartialEq, Eq)] +struct T; + +fn main() { + const C: &S = &S; + match C { + C => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + } + const K: &T = &T; + match K { + K => {} + } +} diff --git a/tests/ui/consts/match_ice.stderr b/tests/ui/consts/match_ice.stderr new file mode 100644 index 000000000..699b4a5e2 --- /dev/null +++ b/tests/ui/consts/match_ice.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/match_ice.rs:11:9 + | +LL | C => {} + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/min_const_fn/address_of.rs b/tests/ui/consts/min_const_fn/address_of.rs new file mode 100644 index 000000000..40d1882d7 --- /dev/null +++ b/tests/ui/consts/min_const_fn/address_of.rs @@ -0,0 +1,17 @@ +#![feature(raw_ref_op)] + +const fn mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR mutable reference +} + +struct X; + +impl X { + const fn inherent_mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR mutable reference + } +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/address_of.stderr b/tests/ui/consts/min_const_fn/address_of.stderr new file mode 100644 index 000000000..facc56651 --- /dev/null +++ b/tests/ui/consts/min_const_fn/address_of.stderr @@ -0,0 +1,21 @@ +error[E0658]: raw mutable references are not allowed in constant functions + --> $DIR/address_of.rs:5:13 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: raw mutable references are not allowed in constant functions + --> $DIR/address_of.rs:13:17 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/min_const_fn/address_of_const.rs b/tests/ui/consts/min_const_fn/address_of_const.rs new file mode 100644 index 000000000..3db19e9cd --- /dev/null +++ b/tests/ui/consts/min_const_fn/address_of_const.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const fn const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; +} + +struct X; + +impl X { + const fn inherent_const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; + } +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs new file mode 100644 index 000000000..2dbc424d3 --- /dev/null +++ b/tests/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(rustc_allow_const_fn_unstable)] + +#![feature(rustc_attrs, staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(since="1.0.0", feature = "mep")] +const fn takes_fn_ptr(_: fn()) {} + +const FN: fn() = || (); + +const fn gives_fn_ptr() { + takes_fn_ptr(FN) +} + +fn main() { + gives_fn_ptr(); +} diff --git a/tests/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs b/tests/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs new file mode 100644 index 000000000..d22115755 --- /dev/null +++ b/tests/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs @@ -0,0 +1,9 @@ +// check-pass + +use std::ptr; + +const fn test_fn(x: *const i32) { + let x2 = unsafe { ptr::addr_of!(*x) }; +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs new file mode 100644 index 000000000..258997597 --- /dev/null +++ b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.rs @@ -0,0 +1,7 @@ +const fn foo(a: i32) -> Vec { + vec![1, 2, 3] + //~^ ERROR allocations are not allowed + //~| ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr new file mode 100644 index 000000000..742341089 --- /dev/null +++ b/tests/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr @@ -0,0 +1,21 @@ +error[E0010]: allocations are not allowed in constant functions + --> $DIR/bad_const_fn_body_ice.rs:2:5 + | +LL | vec![1, 2, 3] + | ^^^^^^^^^^^^^ allocation not allowed in constant functions + | + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const fn `slice::::into_vec::` in constant functions + --> $DIR/bad_const_fn_body_ice.rs:2:5 + | +LL | vec![1, 2, 3] + | ^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0010, E0015. +For more information about an error, try `rustc --explain E0010`. diff --git a/tests/ui/consts/min_const_fn/cast_fn.rs b/tests/ui/consts/min_const_fn/cast_fn.rs new file mode 100644 index 000000000..85802a514 --- /dev/null +++ b/tests/ui/consts/min_const_fn/cast_fn.rs @@ -0,0 +1,11 @@ +// check-pass + +fn main() {} + +const fn unsize(x: &[u8; 3]) -> &[u8] { x } +const fn closure() -> fn() { || {} } +const fn closure2() { + (|| {}) as fn(); +} +const fn reify(f: fn()) -> unsafe fn() { f } +const fn reify2() { main as unsafe fn(); } diff --git a/tests/ui/consts/min_const_fn/cmp_fn_pointers.rs b/tests/ui/consts/min_const_fn/cmp_fn_pointers.rs new file mode 100644 index 000000000..9a2775688 --- /dev/null +++ b/tests/ui/consts/min_const_fn/cmp_fn_pointers.rs @@ -0,0 +1,6 @@ +const fn cmp(x: fn(), y: fn()) -> bool { + unsafe { x == y } + //~^ ERROR can't compare +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr new file mode 100644 index 000000000..8a1b20a33 --- /dev/null +++ b/tests/ui/consts/min_const_fn/cmp_fn_pointers.stderr @@ -0,0 +1,16 @@ +error[E0277]: can't compare `fn()` with `_` in const contexts + --> $DIR/cmp_fn_pointers.rs:2:16 + | +LL | unsafe { x == y } + | ^^ no implementation for `fn() == _` + | + = help: the trait `~const PartialEq<_>` is not implemented for `fn()` +note: the trait `PartialEq<_>` is implemented for `fn()`, but that implementation is not `const` + --> $DIR/cmp_fn_pointers.rs:2:16 + | +LL | unsafe { x == y } + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn.rs b/tests/ui/consts/min_const_fn/min_const_fn.rs new file mode 100644 index 000000000..c2891488c --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn.rs @@ -0,0 +1,134 @@ +// ok +const fn foo1() {} +const fn foo2(x: i32) -> i32 { x } +const fn foo3(x: T) -> T { x } +const fn foo7() { + ( + foo1(), + foo2(420), + foo3(69), + ).0 +} +const fn foo12(t: T) -> T { t } +const fn foo13(t: &T) -> &T { t } +const fn foo14<'a, T: 'a>(t: &'a T) -> &'a T { t } +const fn foo15(t: T) -> T where T: Sized { t } +const fn foo15_2(t: &T) -> &T where T: ?Sized { t } +const fn foo16(f: f32) -> f32 { f } +const fn foo17(f: f32) -> u32 { f as u32 } +const fn foo18(i: i32) -> i32 { i * 3 } +const fn foo20(b: bool) -> bool { !b } +const fn foo21(t: T, u: U) -> (T, U) { (t, u) } +const fn foo22(s: &[u8], i: usize) -> u8 { s[i] } +const FOO: u32 = 42; +const fn foo23() -> u32 { FOO } +const fn foo24() -> &'static u32 { &FOO } +const fn foo27(x: &u32) -> u32 { *x } +const fn foo28(x: u32) -> u32 { *&x } +const fn foo29(x: u32) -> i32 { x as i32 } +const fn foo31(a: bool, b: bool) -> bool { a & b } +const fn foo32(a: bool, b: bool) -> bool { a | b } +const fn foo33(a: bool, b: bool) -> bool { a & b } +const fn foo34(a: bool, b: bool) -> bool { a | b } +const fn foo35(a: bool, b: bool) -> bool { a ^ b } +struct Foo(T); +impl Foo { + const fn new(t: T) -> Self { Foo(t) } + const fn into_inner(self) -> T { self.0 } //~ destructor of + const fn get(&self) -> &T { &self.0 } + const fn get_mut(&mut self) -> &mut T { &mut self.0 } + //~^ mutable references + //~| mutable references + //~| mutable references +} +impl<'a, T> Foo { + const fn new_lt(t: T) -> Self { Foo(t) } + const fn into_inner_lt(self) -> T { self.0 } //~ destructor of + const fn get_lt(&'a self) -> &T { &self.0 } + const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + //~^ mutable references + //~| mutable references + //~| mutable references +} +impl Foo { + const fn new_s(t: T) -> Self { Foo(t) } + const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructor + const fn get_s(&self) -> &T { &self.0 } + const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + //~^ mutable references + //~| mutable references + //~| mutable references +} +impl Foo { + const fn get_sq(&self) -> &T { &self.0 } + const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + //~^ mutable references + //~| mutable references + //~| mutable references +} + + +const fn char_ops(c: char, d: char) -> bool { c == d } +const fn char_ops2(c: char, d: char) -> bool { c < d } +const fn char_ops3(c: char, d: char) -> bool { c != d } +const fn i32_ops(c: i32, d: i32) -> bool { c == d } +const fn i32_ops2(c: i32, d: i32) -> bool { c < d } +const fn i32_ops3(c: i32, d: i32) -> bool { c != d } +const fn i32_ops4(c: i32, d: i32) -> i32 { c + d } +const fn char_cast(u: u8) -> char { u as char } +const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } +const unsafe fn ret_null_ptr_no_unsafe() -> *const T { core::ptr::null() } +const unsafe fn ret_null_mut_ptr_no_unsafe() -> *mut T { core::ptr::null_mut() } + +const fn foo11(t: T) -> T { t } +const fn foo11_2(t: T) -> T { t } + +// not ok + +static BAR: u32 = 42; +const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics +const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot refer to statics +const fn foo30(x: *const u32) -> usize { x as usize } +//~^ ERROR pointers cannot be cast to integers +const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } +//~^ ERROR pointers cannot be cast to integers +const fn foo30_2(x: *mut u32) -> usize { x as usize } +//~^ ERROR pointers cannot be cast to integers +const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } +//~^ ERROR pointers cannot be cast to integers +const fn foo30_6() -> bool { let x = true; x } +const fn inc(x: &mut i32) { *x += 1 } +//~^ ERROR mutable references + +// ok +const fn foo36(a: bool, b: bool) -> bool { a && b } +const fn foo37(a: bool, b: bool) -> bool { a || b } + +fn main() {} + +impl Foo { + const fn foo(&self) {} +} + +impl Foo { + const fn foo2(&self) {} +} + +impl Foo { + const fn foo3(&self) {} +} + +struct AlanTuring(T); +const fn no_apit2(_x: AlanTuring) {} +//~^ ERROR destructor +const fn no_apit(_x: impl std::fmt::Debug) {} +//~^ ERROR destructor +const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} +const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } + +const fn no_unsafe() { unsafe {} } + +const fn traits_are_ok_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } + +const fn fn_ptrs(_x: fn()) {} +const fn fn_ptrs2() -> fn() { fn foo() {} foo } diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr new file mode 100644 index 000000000..11c79e8e2 --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -0,0 +1,213 @@ +error[E0493]: destructor of `Foo` cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:37:25 + | +LL | const fn into_inner(self) -> T { self.0 } + | ^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:39:22 + | +LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:39:36 + | +LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:39:45 + | +LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0493]: destructor of `Foo` cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:46:28 + | +LL | const fn into_inner_lt(self) -> T { self.0 } + | ^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:48:25 + | +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:48:42 + | +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:48:51 + | +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0493]: destructor of `Foo` cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:55:27 + | +LL | const fn into_inner_s(self) -> T { self.0 } + | ^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:57:24 + | +LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:57:38 + | +LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:57:47 + | +LL | const fn get_mut_s(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:64:25 + | +LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:64:39 + | +LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:64:48 + | +LL | const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 } + | ^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0013]: constant functions cannot refer to statics + --> $DIR/min_const_fn.rs:89:27 + | +LL | const fn foo25() -> u32 { BAR } + | ^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0013]: constant functions cannot refer to statics + --> $DIR/min_const_fn.rs:90:37 + | +LL | const fn foo26() -> &'static u32 { &BAR } + | ^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: pointers cannot be cast to integers during const eval + --> $DIR/min_const_fn.rs:91:42 + | +LL | const fn foo30(x: *const u32) -> usize { x as usize } + | ^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: pointers cannot be cast to integers during const eval + --> $DIR/min_const_fn.rs:93:63 + | +LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } + | ^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: pointers cannot be cast to integers during const eval + --> $DIR/min_const_fn.rs:95:42 + | +LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } + | ^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error: pointers cannot be cast to integers during const eval + --> $DIR/min_const_fn.rs:97:63 + | +LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } + | ^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/min_const_fn.rs:100:14 + | +LL | const fn inc(x: &mut i32) { *x += 1 } + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0493]: destructor of `AlanTuring` cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:122:19 + | +LL | const fn no_apit2(_x: AlanTuring) {} + | ^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time + --> $DIR/min_const_fn.rs:124:18 + | +LL | const fn no_apit(_x: impl std::fmt::Debug) {} + | ^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 24 previous errors + +Some errors have detailed explanations: E0013, E0493, E0658. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn_dyn.rs b/tests/ui/consts/min_const_fn/min_const_fn_dyn.rs new file mode 100644 index 000000000..36c888009 --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_dyn.rs @@ -0,0 +1,15 @@ +// check-pass + +struct HasDyn { + field: &'static dyn std::fmt::Debug, +} + +struct Hide(HasDyn); + +const fn no_inner_dyn_trait(_x: Hide) {} +const fn no_inner_dyn_trait2(x: Hide) { + x.0.field; +} +const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd.rs new file mode 100644 index 000000000..cb8f74186 --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd.rs @@ -0,0 +1,26 @@ +// build-pass (FIXME(62277): could be check-pass?) + +use std::cell::UnsafeCell; +use std::sync::atomic::AtomicU32; +pub struct Condvar { + condvar: UnsafeCell, +} + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +#[repr(C)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +struct NoWait(u32); + +const CONDVAR_HAS_NO_WAITERS: NoWait = NoWait(42); + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { + condvar: UnsafeCell::new(AtomicU32::new(CONDVAR_HAS_NO_WAITERS.0)), + } + } +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs new file mode 100644 index 000000000..bb240fb4a --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -0,0 +1,41 @@ +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "none")] + +#![feature(const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo", issue = "none")] +const fn foo() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn + +#[unstable(feature = "foo2", issue = "none")] +const fn foo2() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// Const-stable functions cannot rely on unstable const-eval features. +const fn bar3() -> u32 { (5f32 + 6f32) as u32 } +//~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` + +// check whether this function cannot be called even with the feature gate active +#[unstable(feature = "foo2", issue = "none")] +const fn foo2_gated() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr new file mode 100644 index 000000000..778b0e55f --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -0,0 +1,41 @@ +error: `foo` is not yet stable as a const fn + --> $DIR/min_const_fn_libstd_stability.rs:16:25 + | +LL | const fn bar() -> u32 { foo() } + | ^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `foo2` is not yet stable as a const fn + --> $DIR/min_const_fn_libstd_stability.rs:24:26 + | +LL | const fn bar2() -> u32 { foo2() } + | ^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` + --> $DIR/min_const_fn_libstd_stability.rs:29:26 + | +LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } + | ^^^^^^^^^^^^^ + | +help: if it is not part of the public API, make this function unstably const + | +LL | #[rustc_const_unstable(feature = "...", issue = "...")] + | +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks + | +LL | #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] + | + +error: `foo2_gated` is not yet stable as a const fn + --> $DIR/min_const_fn_libstd_stability.rs:39:32 + | +LL | const fn bar2_gated() -> u32 { foo2_gated() } + | ^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 4 previous errors + diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs new file mode 100644 index 000000000..a6e1788bb --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -0,0 +1,10 @@ +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } +//~^ dereferencing raw mutable pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } +//~^ dereferencing raw mutable pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } +//~^ dereferencing raw mutable pointers in constant functions + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr new file mode 100644 index 000000000..820b6433f --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -0,0 +1,30 @@ +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable + --> $DIR/min_const_fn_unsafe_bad.rs:1:77 + | +LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } + | ^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable + --> $DIR/min_const_fn_unsafe_bad.rs:4:70 + | +LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } + | ^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable + --> $DIR/min_const_fn_unsafe_bad.rs:7:83 + | +LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } + | ^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs new file mode 100644 index 000000000..02c7970de --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs @@ -0,0 +1,44 @@ +// check-pass + +const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } +const unsafe fn ret_null_ptr_no_unsafe() -> *const T { std::ptr::null() } +const unsafe fn ret_null_mut_ptr_no_unsafe() -> *mut T { std::ptr::null_mut() } +const fn no_unsafe() { unsafe {} } + +const fn call_unsafe_const_fn() -> i32 { + unsafe { ret_i32_no_unsafe() } +} +const fn call_unsafe_generic_const_fn() -> *const String { + unsafe { ret_null_ptr_no_unsafe::() } +} +const fn call_unsafe_generic_cell_const_fn() + -> *const Vec> +{ + unsafe { ret_null_mut_ptr_no_unsafe::>>() } +} + +const unsafe fn call_unsafe_const_unsafe_fn() -> i32 { + unsafe { ret_i32_no_unsafe() } +} +const unsafe fn call_unsafe_generic_const_unsafe_fn() -> *const String { + unsafe { ret_null_ptr_no_unsafe::() } +} +const unsafe fn call_unsafe_generic_cell_const_unsafe_fn() + -> *const Vec> +{ + unsafe { ret_null_mut_ptr_no_unsafe::>>() } +} + +const unsafe fn call_unsafe_const_unsafe_fn_immediate() -> i32 { + ret_i32_no_unsafe() +} +const unsafe fn call_unsafe_generic_const_unsafe_fn_immediate() -> *const String { + ret_null_ptr_no_unsafe::() +} +const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate() + -> *const Vec> +{ + ret_null_mut_ptr_no_unsafe::>>() +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs new file mode 100644 index 000000000..03084c867 --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -0,0 +1,42 @@ +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "none")] + +#![feature(const_fn_floating_point_arithmetic, foo, foo2)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo", issue = "none")] +const unsafe fn foo() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR not yet stable as a const fn + +#[unstable(feature = "foo2", issue = "none")] +const unsafe fn foo2() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR not yet stable as a const fn + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// conformity is required +const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } +//~^ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` + +// check whether this function cannot be called even with the feature gate active +#[unstable(feature = "foo2", issue = "none")] +const unsafe fn foo2_gated() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } +//~^ ERROR not yet stable as a const fn + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr new file mode 100644 index 000000000..0174cb77f --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -0,0 +1,41 @@ +error: `foo` is not yet stable as a const fn + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:16:41 + | +LL | const unsafe fn bar() -> u32 { unsafe { foo() } } + | ^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `foo2` is not yet stable as a const fn + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42 + | +LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } + | ^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:29:33 + | +LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } + | ^^^^^^^^^^^^^ + | +help: if it is not part of the public API, make this function unstably const + | +LL | #[rustc_const_unstable(feature = "...", issue = "...")] + | +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks + | +LL | #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] + | + +error: `foo2_gated` is not yet stable as a const fn + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:39:48 + | +LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } + | ^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 4 previous errors + diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs new file mode 100644 index 000000000..94b620713 --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs @@ -0,0 +1,35 @@ +#![unstable(feature = "humans", + reason = "who ever let humans program computers, + we're apparently really bad at it", + issue = "none")] + +#![feature(foo, foo2)] +#![feature(staged_api)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature="foo", issue = "none")] +const fn foo() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn + +#[unstable(feature = "foo2", issue = "none")] +const fn foo2() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn + +// check whether this function cannot be called even with the feature gate active +#[unstable(feature = "foo2", issue = "none")] +const fn foo2_gated() -> u32 { 42 } + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +// can't call non-min_const_fn +const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr new file mode 100644 index 000000000..e90ba9b91 --- /dev/null +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -0,0 +1,26 @@ +error: `foo` is not yet stable as a const fn + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:16:32 + | +LL | const unsafe fn bar() -> u32 { foo() } + | ^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `foo2` is not yet stable as a const fn + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33 + | +LL | const unsafe fn bar2() -> u32 { foo2() } + | ^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `foo2_gated` is not yet stable as a const fn + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:39 + | +LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } + | ^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 3 previous errors + diff --git a/tests/ui/consts/min_const_fn/mutable_borrow.rs b/tests/ui/consts/min_const_fn/mutable_borrow.rs new file mode 100644 index 000000000..580b1d50f --- /dev/null +++ b/tests/ui/consts/min_const_fn/mutable_borrow.rs @@ -0,0 +1,17 @@ +const fn mutable_ref_in_const() -> u8 { + let mut a = 0; + let b = &mut a; //~ ERROR mutable references + *b +} + +struct X; + +impl X { + const fn inherent_mutable_ref_in_const() -> u8 { + let mut a = 0; + let b = &mut a; //~ ERROR mutable references + *b + } +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/mutable_borrow.stderr b/tests/ui/consts/min_const_fn/mutable_borrow.stderr new file mode 100644 index 000000000..8e95a4c68 --- /dev/null +++ b/tests/ui/consts/min_const_fn/mutable_borrow.stderr @@ -0,0 +1,21 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/mutable_borrow.rs:3:13 + | +LL | let b = &mut a; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/mutable_borrow.rs:12:17 + | +LL | let b = &mut a; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/min_const_fn/promotion.rs b/tests/ui/consts/min_const_fn/promotion.rs new file mode 100644 index 000000000..fbe535c71 --- /dev/null +++ b/tests/ui/consts/min_const_fn/promotion.rs @@ -0,0 +1,17 @@ +use std::cell::Cell; + +const fn foo1() {} +const fn foo2(x: i32) -> i32 { x } +const fn foo3() -> i32 { 42 } +const fn foo4() -> Cell { Cell::new(42) } +const fn foo5() -> Option> { Some(Cell::new(42)) } +const fn foo6() -> Option> { None } + +fn main() { + let x: &'static () = &foo1(); //~ ERROR temporary value dropped while borrowed + let y: &'static i32 = &foo2(42); //~ ERROR temporary value dropped while borrowed + let z: &'static i32 = &foo3(); //~ ERROR temporary value dropped while borrowed + let a: &'static Cell = &foo4(); //~ ERROR temporary value dropped while borrowed + let a: &'static Option> = &foo5(); //~ ERROR temporary value dropped while borrowed + let a: &'static Option> = &foo6(); //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/min_const_fn/promotion.stderr b/tests/ui/consts/min_const_fn/promotion.stderr new file mode 100644 index 000000000..0b8dc0ce0 --- /dev/null +++ b/tests/ui/consts/min_const_fn/promotion.stderr @@ -0,0 +1,68 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:11:27 + | +LL | let x: &'static () = &foo1(); + | ----------- ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:12:28 + | +LL | let y: &'static i32 = &foo2(42); + | ------------ ^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:13:28 + | +LL | let z: &'static i32 = &foo3(); + | ------------ ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:14:34 + | +LL | let a: &'static Cell = &foo4(); + | ------------------ ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:15:42 + | +LL | let a: &'static Option> = &foo5(); + | -------------------------- ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let a: &'static Option> = &foo6(); +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promotion.rs:16:42 + | +LL | let a: &'static Option> = &foo6(); + | -------------------------- ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/mir_check_nonconst.rs b/tests/ui/consts/mir_check_nonconst.rs new file mode 100644 index 000000000..b6f34b922 --- /dev/null +++ b/tests/ui/consts/mir_check_nonconst.rs @@ -0,0 +1,11 @@ +#![allow(dead_code)] + +struct Foo { a: u8 } +fn bar() -> Foo { + Foo { a: 5 } +} + +static foo: Foo = bar(); +//~^ ERROR cannot call non-const fn + +fn main() {} diff --git a/tests/ui/consts/mir_check_nonconst.stderr b/tests/ui/consts/mir_check_nonconst.stderr new file mode 100644 index 000000000..1e0652722 --- /dev/null +++ b/tests/ui/consts/mir_check_nonconst.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn `bar` in statics + --> $DIR/mir_check_nonconst.rs:8:19 + | +LL | static foo: Foo = bar(); + | ^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.rs b/tests/ui/consts/miri_unleashed/abi-mismatch.rs new file mode 100644 index 000000000..205f7183b --- /dev/null +++ b/tests/ui/consts/miri_unleashed/abi-mismatch.rs @@ -0,0 +1,18 @@ +// Checks that we report ABI mismatches for "const extern fn" +// compile-flags: -Z unleash-the-miri-inside-of-you + +#![feature(const_extern_fn)] + +const extern "C" fn c_fn() {} + +const fn call_rust_fn(my_fn: extern "Rust" fn()) { + my_fn(); + //~^ ERROR could not evaluate static initializer + //~| NOTE calling a function with calling convention C using calling convention Rust + //~| NOTE inside `call_rust_fn` +} + +static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); +//~^ NOTE inside `VAL` + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/abi-mismatch.stderr b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr new file mode 100644 index 000000000..cf3fd88d0 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -0,0 +1,28 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/abi-mismatch.rs:9:5 + | +LL | my_fn(); + | ^^^^^^^ calling a function with calling convention C using calling convention Rust + | +note: inside `call_rust_fn` + --> $DIR/abi-mismatch.rs:9:5 + | +LL | my_fn(); + | ^^^^^^^ +note: inside `VAL` + --> $DIR/abi-mismatch.rs:15:18 + | +LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/abi-mismatch.rs:9:5 + | +LL | my_fn(); + | ^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/assoc_const.rs b/tests/ui/consts/miri_unleashed/assoc_const.rs new file mode 100644 index 000000000..7bb0c1b77 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/assoc_const.rs @@ -0,0 +1,30 @@ +// build-fail +// compile-flags: -Zunleash-the-miri-inside-of-you + +// a test demonstrating why we do need to run static const qualification on associated constants +// instead of just checking the final constant + +trait Foo { + const X: T; +} + +trait Bar> { + const F: u32 = (U::X, 42).1; +} + +impl Foo for () { + const X: u32 = 42; +} +impl Foo> for String { + const X: Vec = Vec::new(); +} + +impl Bar for () {} +impl Bar, String> for String {} + +fn main() { + // this is fine, but would have been forbidden by the static checks on `F` + let x = <() as Bar>::F; + // this test only causes errors due to the line below, so post-monomorphization + let y = , String>>::F; //~ constant +} diff --git a/tests/ui/consts/miri_unleashed/assoc_const.stderr b/tests/ui/consts/miri_unleashed/assoc_const.stderr new file mode 100644 index 000000000..e1da43c3a --- /dev/null +++ b/tests/ui/consts/miri_unleashed/assoc_const.stderr @@ -0,0 +1,44 @@ +error[E0080]: evaluation of `, std::string::String>>::F` failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: calling non-const function ` as Drop>::drop` + | +note: inside `std::ptr::drop_in_place::> - shim(Some(Vec))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `std::ptr::drop_in_place::<(Vec, u32)> - shim(Some((Vec, u32)))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `, String>>::F` + --> $DIR/assoc_const.rs:12:31 + | +LL | const F: u32 = (U::X, 42).1; + | ^ + +note: erroneous constant used + --> $DIR/assoc_const.rs:29:13 + | +LL | let y = , String>>::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/assoc_const.rs:29:13 + | +LL | let y = , String>>::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/assoc_const.rs:29:13 + | +LL | let y = , String>>::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/assoc_const.rs:12:20 + | +LL | const F: u32 = (U::X, 42).1; + | ^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.rs b/tests/ui/consts/miri_unleashed/assoc_const_2.rs new file mode 100644 index 000000000..aad5b3460 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/assoc_const_2.rs @@ -0,0 +1,28 @@ +// build-fail + +// a test demonstrating that const qualification cannot prevent monomorphization time errors + +trait Foo { + const X: u32; +} + +trait Bar { + const F: u32 = 100 / U::X; //~ ERROR evaluation of `>::F` failed +} + +impl Foo for () { + const X: u32 = 42; +} + +impl Foo for String { + const X: u32 = 0; +} + +impl Bar<()> for () {} +impl Bar for String {} + +fn main() { + let x = <() as Bar<()>>::F; + // this test only causes errors due to the line below, so post-monomorphization + let y = >::F; //~ constant +} diff --git a/tests/ui/consts/miri_unleashed/assoc_const_2.stderr b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr new file mode 100644 index 000000000..fc4b18056 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/assoc_const_2.stderr @@ -0,0 +1,27 @@ +error[E0080]: evaluation of `>::F` failed + --> $DIR/assoc_const_2.rs:10:20 + | +LL | const F: u32 = 100 / U::X; + | ^^^^^^^^^^ attempt to divide `100_u32` by zero + +note: erroneous constant used + --> $DIR/assoc_const_2.rs:27:13 + | +LL | let y = >::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/assoc_const_2.rs:27:13 + | +LL | let y = >::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/assoc_const_2.rs:27:13 + | +LL | let y = >::F; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs b/tests/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs new file mode 100644 index 000000000..4fc6ae66a --- /dev/null +++ b/tests/ui/consts/miri_unleashed/auxiliary/static_cross_crate.rs @@ -0,0 +1,3 @@ +pub static mut ZERO: [u8; 1] = [0]; +pub static ZERO_REF: &[u8; 1] = unsafe { &ZERO }; +pub static mut OPT_ZERO: Option = Some(0); diff --git a/tests/ui/consts/miri_unleashed/box.rs b/tests/ui/consts/miri_unleashed/box.rs new file mode 100644 index 000000000..c2a260aa1 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/box.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(box_syntax)] + +use std::mem::ManuallyDrop; + +fn main() {} + +static TEST_BAD: &mut i32 = { + &mut *(box 0) + //~^ ERROR could not evaluate static initializer + //~| NOTE calling non-const function `alloc::alloc::exchange_malloc` +}; diff --git a/tests/ui/consts/miri_unleashed/box.stderr b/tests/ui/consts/miri_unleashed/box.stderr new file mode 100644 index 000000000..bc5d4a257 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/box.stderr @@ -0,0 +1,32 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/box.rs:9:11 + | +LL | &mut *(box 0) + | ^^^^^^^ calling non-const function `alloc::alloc::exchange_malloc` + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/box.rs:9:11 + | +LL | &mut *(box 0) + | ^^^^^^^ +help: skipping check for `const_mut_refs` feature + --> $DIR/box.rs:9:16 + | +LL | &mut *(box 0) + | ^ +help: skipping check for `const_mut_refs` feature + --> $DIR/box.rs:9:5 + | +LL | &mut *(box 0) + | ^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/box.rs:9:5 + | +LL | &mut *(box 0) + | ^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr new file mode 100644 index 000000000..a6f467b9e --- /dev/null +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr @@ -0,0 +1,81 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static.rs:9:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add` + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static.rs:14:14 + | +LL | unsafe { *(&FOO as *const _ as *const usize) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static.rs:18:32 + | +LL | const READ_MUT: u32 = unsafe { MUTABLE }; + | ^^^^^^^ constant accesses static + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static.rs:20:1 + | +LL | const REF_INTERIOR_MUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc4──╼ │ ╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static.rs:27:1 + | +LL | const READ_IMMUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc5──╼ │ ╾──╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:9:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:9:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:14:17 + | +LL | unsafe { *(&FOO as *const _ as *const usize) } + | ^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:18:32 + | +LL | const READ_MUT: u32 = unsafe { MUTABLE }; + | ^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:18:32 + | +LL | const READ_MUT: u32 = unsafe { MUTABLE }; + | ^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:23:18 + | +LL | unsafe { &*(&FOO as *const _ as *const usize) } + | ^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:30:6 + | +LL | &FOO + | ^^^ + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr new file mode 100644 index 000000000..cfaf31a6e --- /dev/null +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr @@ -0,0 +1,81 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static.rs:9:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add` + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static.rs:14:14 + | +LL | unsafe { *(&FOO as *const _ as *const usize) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static.rs:18:32 + | +LL | const READ_MUT: u32 = unsafe { MUTABLE }; + | ^^^^^^^ constant accesses static + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static.rs:20:1 + | +LL | const REF_INTERIOR_MUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc4────────╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static.rs:27:1 + | +LL | const READ_IMMUT: &usize = { + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc5────────╼ │ ╾──────╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:9:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:9:5 + | +LL | FOO.fetch_add(1, Ordering::Relaxed) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:14:17 + | +LL | unsafe { *(&FOO as *const _ as *const usize) } + | ^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:18:32 + | +LL | const READ_MUT: u32 = unsafe { MUTABLE }; + | ^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:18:32 + | +LL | const READ_MUT: u32 = unsafe { MUTABLE }; + | ^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:23:18 + | +LL | unsafe { &*(&FOO as *const _ as *const usize) } + | ^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static.rs:30:6 + | +LL | &FOO + | ^^^ + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs new file mode 100644 index 000000000..7ed5a48d9 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -0,0 +1,33 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// stderr-per-bitwidth + +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; + +const MUTATE_INTERIOR_MUT: usize = { + static FOO: AtomicUsize = AtomicUsize::new(0); + FOO.fetch_add(1, Ordering::Relaxed) //~ERROR evaluation of constant value failed +}; + +const READ_INTERIOR_MUT: usize = { + static FOO: AtomicUsize = AtomicUsize::new(0); + unsafe { *(&FOO as *const _ as *const usize) } //~ERROR evaluation of constant value failed +}; + +static mut MUTABLE: u32 = 0; +const READ_MUT: u32 = unsafe { MUTABLE }; //~ERROR evaluation of constant value failed + +const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value +//~| encountered a reference pointing to a static variable + static FOO: AtomicUsize = AtomicUsize::new(0); + unsafe { &*(&FOO as *const _ as *const usize) } +}; + +// ok some day perhaps +const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value +//~| encountered a reference pointing to a static variable + static FOO: usize = 0; + &FOO +}; + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr new file mode 100644 index 000000000..6df2fe3d0 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -0,0 +1,138 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:10:1 + | +LL | const SLICE_MUT: &[u8; 1] = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc1──╼ │ ╾──╼ + } + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:34:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:15:1 + | +LL | const U8_MUT: &u8 = { + | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc1──╼ │ ╾──╼ + } + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:43:9 + | +LL | U8_MUT => true, + | ^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static_cross_crate.rs:22:15 + | +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:54:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:62:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:34:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:43:9 + | +LL | U8_MUT => true, + | ^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:54:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:62:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:12:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:12:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:17:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:17:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:17:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:22:17 + | +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr new file mode 100644 index 000000000..8802f3ada --- /dev/null +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -0,0 +1,138 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:10:1 + | +LL | const SLICE_MUT: &[u8; 1] = { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc1────────╼ │ ╾──────╼ + } + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:34:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const_refers_to_static_cross_crate.rs:15:1 + | +LL | const U8_MUT: &u8 = { + | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc1────────╼ │ ╾──────╼ + } + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:43:9 + | +LL | U8_MUT => true, + | ^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static_cross_crate.rs:22:15 + | +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:54:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:62:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:34:9 + | +LL | SLICE_MUT => true, + | ^^^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:43:9 + | +LL | U8_MUT => true, + | ^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:54:9 + | +LL | U8_MUT2 => true, + | ^^^^^^^ + +error: could not evaluate constant pattern + --> $DIR/const_refers_to_static_cross_crate.rs:62:9 + | +LL | U8_MUT3 => true, + | ^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:12:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:12:15 + | +LL | unsafe { &static_cross_crate::ZERO } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:17:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:17:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:17:15 + | +LL | unsafe { &static_cross_crate::ZERO[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:22:17 + | +LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/const_refers_to_static_cross_crate.rs:27:20 + | +LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs new file mode 100644 index 000000000..bf4f14f4d --- /dev/null +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -0,0 +1,76 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// aux-build:static_cross_crate.rs +// stderr-per-bitwidth +#![feature(exclusive_range_pattern, half_open_range_patterns_in_slices)] + +extern crate static_cross_crate; + +// Sneaky: reference to a mutable static. +// Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking! +const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value +//~| encountered a reference pointing to a static variable + unsafe { &static_cross_crate::ZERO } +}; + +const U8_MUT: &u8 = { //~ ERROR undefined behavior to use this value +//~| encountered a reference pointing to a static variable + unsafe { &static_cross_crate::ZERO[0] } +}; + +// Also test indirection that reads from other static. +const U8_MUT2: &u8 = { + unsafe { &(*static_cross_crate::ZERO_REF)[0] } + //~^ ERROR evaluation of constant value failed + //~| constant accesses static +}; +const U8_MUT3: &u8 = { + unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } } + //~^ ERROR evaluation of constant value failed + //~| constant accesses static +}; + +pub fn test(x: &[u8; 1]) -> bool { + match x { + SLICE_MUT => true, + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + &[1..] => false, + } +} + +pub fn test2(x: &u8) -> bool { + match x { + U8_MUT => true, + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + &(1..) => false, + } +} + +// We need to use these *in a pattern* to trigger the failure... likely because +// the errors above otherwise stop compilation too early? +pub fn test3(x: &u8) -> bool { + match x { + U8_MUT2 => true, + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + &(1..) => false, + } +} +pub fn test4(x: &u8) -> bool { + match x { + U8_MUT3 => true, + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern + &(1..) => false, + } +} + +fn main() { + unsafe { + static_cross_crate::ZERO[0] = 1; + } + // Now the pattern is not exhaustive any more! + test(&[0]); + test2(&0); +} diff --git a/tests/ui/consts/miri_unleashed/drop.rs b/tests/ui/consts/miri_unleashed/drop.rs new file mode 100644 index 000000000..3942e7ef7 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/drop.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// error-pattern: calling non-const function ` as Drop>::drop` + +use std::mem::ManuallyDrop; + +fn main() {} + +static TEST_OK: () = { + let v: Vec = Vec::new(); + let _v = ManuallyDrop::new(v); +}; + +// Make sure we catch executing bad drop functions. +// The actual error is tested by the error-pattern above. +static TEST_BAD: () = { + let _v: Vec = Vec::new(); +}; diff --git a/tests/ui/consts/miri_unleashed/drop.stderr b/tests/ui/consts/miri_unleashed/drop.stderr new file mode 100644 index 000000000..4f60b8820 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/drop.stderr @@ -0,0 +1,24 @@ +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: calling non-const function ` as Drop>::drop` + | +note: inside `std::ptr::drop_in_place::> - shim(Some(Vec))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `TEST_BAD` + --> $DIR/drop.rs:17:1 + | +LL | }; + | ^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/drop.rs:16:9 + | +LL | let _v: Vec = Vec::new(); + | ^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs new file mode 100644 index 000000000..c24d3338e --- /dev/null +++ b/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs @@ -0,0 +1,26 @@ +// a test demonstrating why we do need to run static const qualification on associated constants +// instead of just checking the final constant + +trait Foo { + const X: T; +} + +trait Bar> { + const F: u32 = (U::X, 42).1; //~ ERROR destructor of +} + +impl Foo for () { + const X: u32 = 42; +} + +impl Foo> for String { + const X: Vec = Vec::new(); +} + +impl Bar for () {} +impl Bar, String> for String {} + +fn main() { + let x = <() as Bar>::F; + let y = , String>>::F; +} diff --git a/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr new file mode 100644 index 000000000..45ed88b1b --- /dev/null +++ b/tests/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -0,0 +1,11 @@ +error[E0493]: destructor of `(T, u32)` cannot be evaluated at compile-time + --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:9:20 + | +LL | const F: u32 = (U::X, 42).1; + | ^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/miri_unleashed/inline_asm.rs b/tests/ui/consts/miri_unleashed/inline_asm.rs new file mode 100644 index 000000000..6fd52ceb2 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/inline_asm.rs @@ -0,0 +1,13 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// only-x86_64 + +use std::arch::asm; + +fn main() {} + +// Make sure we catch executing inline assembly. +static TEST_BAD: () = { + unsafe { asm!("nop"); } + //~^ ERROR could not evaluate static initializer + //~| NOTE inline assembly is not supported +}; diff --git a/tests/ui/consts/miri_unleashed/inline_asm.stderr b/tests/ui/consts/miri_unleashed/inline_asm.stderr new file mode 100644 index 000000000..6317cd882 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/inline_asm.stderr @@ -0,0 +1,17 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/inline_asm.rs:10:14 + | +LL | unsafe { asm!("nop"); } + | ^^^^^^^^^^^ inline assembly is not supported + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/inline_asm.rs:10:14 + | +LL | unsafe { asm!("nop"); } + | ^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs new file mode 100644 index 000000000..4e9964647 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -0,0 +1,36 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +use std::cell::UnsafeCell; + +// a test demonstrating what things we could allow with a smarter const qualification + +// this is fine because is not possible to mutate through an immutable reference. +static FOO: &&mut u32 = &&mut 42; + +// this is fine because accessing an immutable static `BAR` is equivalent to accessing `*&BAR` +// which puts the mutable reference behind an immutable one. +static BAR: &mut () = &mut (); + +struct Foo(T); + +// this is fine for the same reason as `BAR`. +static BOO: &mut Foo<()> = &mut Foo(()); + +// interior mutability is fine +struct Meh { + x: &'static UnsafeCell, +} +unsafe impl Sync for Meh {} +static MEH: Meh = Meh { + x: &UnsafeCell::new(42), +}; + +// this is fine for the same reason as `BAR`. +static OH_YES: &mut i32 = &mut 42; + +fn main() { + unsafe { + *MEH.x.get() = 99; + } + *OH_YES = 99; //~ ERROR cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item +} diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr new file mode 100644 index 000000000..3ed96701a --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -0,0 +1,37 @@ +error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item + --> $DIR/mutable_references.rs:35:5 + | +LL | *OH_YES = 99; + | ^^^^^^^^^^^^ cannot assign + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references.rs:8:26 + | +LL | static FOO: &&mut u32 = &&mut 42; + | ^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references.rs:12:23 + | +LL | static BAR: &mut () = &mut (); + | ^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references.rs:17:28 + | +LL | static BOO: &mut Foo<()> = &mut Foo(()); + | ^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references.rs:25:8 + | +LL | x: &UnsafeCell::new(42), + | ^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references.rs:29:27 + | +LL | static OH_YES: &mut i32 = &mut 42; + | ^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr new file mode 100644 index 000000000..0ea179240 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -0,0 +1,54 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:15:1 + | +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc3──╼ │ ╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:25:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...x: encountered `UnsafeCell` in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─alloc7──╼ ╾─alloc8──╼ │ ╾──╼╾──╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:29:1 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾─alloc10─╼ │ ╾──╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:16:8 + | +LL | x: &UnsafeCell::new(42), + | ^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:25:27 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:29:25 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr new file mode 100644 index 000000000..67959d256 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -0,0 +1,54 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:15:1 + | +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc3────────╼ │ ╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:25:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...x: encountered `UnsafeCell` in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc7────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:29:1 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾───────alloc10───────╼ │ ╾──────╼ + } + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:16:8 + | +LL | x: &UnsafeCell::new(42), + | ^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:25:27 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:29:25 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.rs b/tests/ui/consts/miri_unleashed/mutable_references_err.rs new file mode 100644 index 000000000..6399b122b --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.rs @@ -0,0 +1,36 @@ +// stderr-per-bitwidth +// compile-flags: -Zunleash-the-miri-inside-of-you + +use std::cell::UnsafeCell; + +// this test ensures that our mutability story is sound + +struct Meh { + x: &'static UnsafeCell, +} +unsafe impl Sync for Meh {} + +// the following will never be ok! no interior mut behind consts, because +// all allocs interned here will be marked immutable. +const MUH: Meh = Meh { //~ ERROR: it is undefined behavior to use this value + x: &UnsafeCell::new(42), +}; + +struct Synced { + x: UnsafeCell, +} +unsafe impl Sync for Synced {} + +// Make sure we also catch this behind a type-erased `dyn Trait` reference. +const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; +//~^ ERROR: it is undefined behavior to use this value + +// Make sure we also catch mutable references. +const BLUNT: &mut i32 = &mut 42; +//~^ ERROR: it is undefined behavior to use this value + +fn main() { + unsafe { + *MUH.x.get() = 99; + } +} diff --git a/tests/ui/consts/miri_unleashed/mutating_global.rs b/tests/ui/consts/miri_unleashed/mutating_global.rs new file mode 100644 index 000000000..231f4af0a --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutating_global.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +// Make sure we cannot mutate globals. + +static mut GLOBAL: i32 = 0; + +static MUTATING_GLOBAL: () = { + unsafe { + GLOBAL = 99 + //~^ ERROR could not evaluate static initializer + //~| NOTE modifying a static's initial value + } +}; + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/mutating_global.stderr b/tests/ui/consts/miri_unleashed/mutating_global.stderr new file mode 100644 index 000000000..c8770c8d7 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/mutating_global.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/mutating_global.rs:9:9 + | +LL | GLOBAL = 99 + | ^^^^^^^^^^^ modifying a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/non_const_fn.rs b/tests/ui/consts/miri_unleashed/non_const_fn.rs new file mode 100644 index 000000000..44ab60dca --- /dev/null +++ b/tests/ui/consts/miri_unleashed/non_const_fn.rs @@ -0,0 +1,11 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +// A test demonstrating that we prevent calling non-const fn during CTFE. + +fn foo() {} + +static C: () = foo(); +//~^ ERROR could not evaluate static initializer +//~| NOTE calling non-const function `foo` + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/non_const_fn.stderr b/tests/ui/consts/miri_unleashed/non_const_fn.stderr new file mode 100644 index 000000000..57836f796 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/non_const_fn.stderr @@ -0,0 +1,17 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/non_const_fn.rs:7:16 + | +LL | static C: () = foo(); + | ^^^^^ calling non-const function `foo` + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/non_const_fn.rs:7:16 + | +LL | static C: () = foo(); + | ^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/ptr_arith.rs b/tests/ui/consts/miri_unleashed/ptr_arith.rs new file mode 100644 index 000000000..4d12960b8 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/ptr_arith.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(core_intrinsics)] + +// During CTFE, we prevent pointer-to-int casts. +// Pointer comparisons are prevented in the trait system. + +static PTR_INT_CAST: () = { + let x = &0 as *const _ as usize; + //~^ ERROR could not evaluate static initializer + //~| exposing pointers + let _v = x == x; +}; + +static PTR_INT_TRANSMUTE: () = unsafe { + let x: usize = std::mem::transmute(&0); + let _v = x + 0; + //~^ ERROR could not evaluate static initializer + //~| unable to turn pointer into raw bytes +}; + +// I'd love to test pointer comparison, but that is not possible since +// their `PartialEq` impl is non-`const`. + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/ptr_arith.stderr b/tests/ui/consts/miri_unleashed/ptr_arith.stderr new file mode 100644 index 000000000..30fd3a55e --- /dev/null +++ b/tests/ui/consts/miri_unleashed/ptr_arith.stderr @@ -0,0 +1,26 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:8:13 + | +LL | let x = &0 as *const _ as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^ exposing pointers is not possible at compile-time + +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:16:14 + | +LL | let _v = x + 0; + | ^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/ptr_arith.rs:8:13 + | +LL | let x = &0 as *const _ as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/raw_mutable_const.rs b/tests/ui/consts/miri_unleashed/raw_mutable_const.rs new file mode 100644 index 000000000..5f8ec4e6e --- /dev/null +++ b/tests/ui/consts/miri_unleashed/raw_mutable_const.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +use std::cell::UnsafeCell; + +const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; +//~^ ERROR: untyped pointers are not allowed in constant + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr b/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr new file mode 100644 index 000000000..f8dc11d69 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr @@ -0,0 +1,16 @@ +error: untyped pointers are not allowed in constant + --> $DIR/raw_mutable_const.rs:5:1 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/raw_mutable_const.rs:5:38 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/consts/miri_unleashed/slice_eq.rs b/tests/ui/consts/miri_unleashed/slice_eq.rs new file mode 100644 index 000000000..83e10bf12 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/slice_eq.rs @@ -0,0 +1,13 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// run-pass + +#![feature(const_raw_ptr_comparison)] + +const EMPTY_SLICE: &[i32] = &[]; +const EMPTY_EQ: Option = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _); +const EMPTY_EQ2: Option = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _); + +fn main() { + assert!(EMPTY_EQ.is_none()); + assert!(EMPTY_EQ2.is_none()); +} diff --git a/tests/ui/consts/miri_unleashed/tls.rs b/tests/ui/consts/miri_unleashed/tls.rs new file mode 100644 index 000000000..d06d7cf19 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/tls.rs @@ -0,0 +1,23 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(thread_local)] + +use std::thread; + +#[thread_local] +static A: u8 = 0; + +// Make sure we catch accessing thread-local storage. +static TEST_BAD: () = { + unsafe { let _val = A; } + //~^ ERROR could not evaluate static initializer + //~| NOTE cannot access thread local static +}; + +// Make sure we catch taking a reference to thread-local storage. +static TEST_BAD_REF: () = { + unsafe { let _val = &A; } + //~^ ERROR could not evaluate static initializer + //~| NOTE cannot access thread local static +}; + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/tls.stderr b/tests/ui/consts/miri_unleashed/tls.stderr new file mode 100644 index 000000000..7aaeadd04 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/tls.stderr @@ -0,0 +1,28 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/tls.rs:11:25 + | +LL | unsafe { let _val = A; } + | ^ cannot access thread local static (DefId(0:4 ~ tls[78b0]::A)) + +error[E0080]: could not evaluate static initializer + --> $DIR/tls.rs:18:26 + | +LL | unsafe { let _val = &A; } + | ^ cannot access thread local static (DefId(0:4 ~ tls[78b0]::A)) + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/tls.rs:11:25 + | +LL | unsafe { let _val = A; } + | ^ +help: skipping check that does not even have a feature gate + --> $DIR/tls.rs:18:26 + | +LL | unsafe { let _val = &A; } + | ^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs new file mode 100644 index 000000000..dd2b81c5a --- /dev/null +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -0,0 +1,27 @@ +// compile-flags: -Z ui-testing=no +// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID" + +#![feature(const_swap)] +#![feature(const_mut_refs)] +use std::{ + mem::{self, MaybeUninit}, + ptr, +}; + +const X: () = { + let mut ptr1 = &1; + let mut ptr2 = &2; + + // Swap them, bytewise. + unsafe { + ptr::swap_nonoverlapping( + &mut ptr1 as *mut _ as *mut MaybeUninit, + &mut ptr2 as *mut _ as *mut MaybeUninit, + mem::size_of::<&i32>(), + ); + } +}; + +fn main() { + X +} diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr new file mode 100644 index 000000000..e6d3d5199 --- /dev/null +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -0,0 +1,28 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | + = note: unable to copy parts of a pointer from memory at ALLOC_ID + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported +note: inside `std::ptr::read::>>` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `mem::swap_simple::>>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `ptr::swap_nonoverlapping_simple_untyped::>` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `swap_nonoverlapping::>` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `X` + --> $DIR/missing_span_in_backtrace.rs:17:9 + | +17 | / ptr::swap_nonoverlapping( +18 | | &mut ptr1 as *mut _ as *mut MaybeUninit, +19 | | &mut ptr2 as *mut _ as *mut MaybeUninit, +20 | | mem::size_of::<&i32>(), +21 | | ); + | |_________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/mozjs-error.rs b/tests/ui/consts/mozjs-error.rs new file mode 100644 index 000000000..7edcadbf2 --- /dev/null +++ b/tests/ui/consts/mozjs-error.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +struct CustomAutoRooterVFTable { + trace: unsafe extern "C" fn(this: *mut i32, trc: *mut u32), +} + +unsafe trait CustomAutoTraceable: Sized { + const vftable: CustomAutoRooterVFTable = CustomAutoRooterVFTable { + trace: Self::trace, + }; + + unsafe extern "C" fn trace(this: *mut i32, trc: *mut u32) { + let this = this as *const Self; + let this = this.as_ref().unwrap(); + Self::do_trace(this, trc); + } + + fn do_trace(&self, trc: *mut u32); +} + +unsafe impl CustomAutoTraceable for () { + fn do_trace(&self, _: *mut u32) { + // nop + } +} + +fn main() { + let _ = <()>::vftable; +} diff --git a/tests/ui/consts/nested_erroneous_ctfe.rs b/tests/ui/consts/nested_erroneous_ctfe.rs new file mode 100644 index 000000000..1ec271401 --- /dev/null +++ b/tests/ui/consts/nested_erroneous_ctfe.rs @@ -0,0 +1,4 @@ +fn main() { + [9; || [9; []]]; + //~^ ERROR: mismatched types +} diff --git a/tests/ui/consts/nested_erroneous_ctfe.stderr b/tests/ui/consts/nested_erroneous_ctfe.stderr new file mode 100644 index 000000000..d579a54e9 --- /dev/null +++ b/tests/ui/consts/nested_erroneous_ctfe.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/nested_erroneous_ctfe.rs:2:16 + | +LL | [9; || [9; []]]; + | ^^ expected `usize`, found array of 0 elements + | + = note: expected type `usize` + found array `[_; 0]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/non-const-value-in-const.rs b/tests/ui/consts/non-const-value-in-const.rs new file mode 100644 index 000000000..1a20b1e09 --- /dev/null +++ b/tests/ui/consts/non-const-value-in-const.rs @@ -0,0 +1,7 @@ +fn main() { + let x = 5; + const Y: i32 = x; //~ ERROR attempt to use a non-constant value in a constant [E0435] + + let x = 5; + let _ = [0; x]; //~ ERROR attempt to use a non-constant value in a constant [E0435] +} diff --git a/tests/ui/consts/non-const-value-in-const.stderr b/tests/ui/consts/non-const-value-in-const.stderr new file mode 100644 index 000000000..0ce4b4b70 --- /dev/null +++ b/tests/ui/consts/non-const-value-in-const.stderr @@ -0,0 +1,20 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-const-value-in-const.rs:3:20 + | +LL | const Y: i32 = x; + | ------- ^ non-constant value + | | + | help: consider using `let` instead of `const`: `let Y` + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-const-value-in-const.rs:6:17 + | +LL | let x = 5; + | ----- help: consider using `const` instead of `let`: `const x` +... +LL | let _ = [0; x]; + | ^ non-constant value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/consts/non-scalar-cast.rs b/tests/ui/consts/non-scalar-cast.rs new file mode 100644 index 000000000..671366c90 --- /dev/null +++ b/tests/ui/consts/non-scalar-cast.rs @@ -0,0 +1,9 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/37448 + +fn main() { + struct A; + const FOO: &A = &(A as A); + let _x = FOO; +} diff --git a/tests/ui/consts/offset.rs b/tests/ui/consts/offset.rs new file mode 100644 index 000000000..b2c663fe6 --- /dev/null +++ b/tests/ui/consts/offset.rs @@ -0,0 +1,112 @@ +// run-pass +use std::ptr; + +#[repr(C)] +struct Struct { + a: u32, + b: u32, + c: u32, +} +static S: Struct = Struct { a: 0, b: 0, c: 0 }; + +// For these tests we use offset_from to check that two pointers are equal. +// Rust doesn't currently support comparing pointers in const fn. + +static OFFSET_NO_CHANGE: bool = unsafe { + let p1 = &S.b as *const u32; + let p2 = p1.offset(2).offset(-2); + p1.offset_from(p2) == 0 +}; +static OFFSET_MIDDLE: bool = unsafe { + let p1 = (&S.a as *const u32).offset(1); + let p2 = (&S.c as *const u32).offset(-1); + p1.offset_from(p2) == 0 +}; +// Pointing to the end of the allocation is OK +static OFFSET_END: bool = unsafe { + let p1 = (&S.a as *const u32).offset(3); + let p2 = (&S.c as *const u32).offset(1); + p1.offset_from(p2) == 0 +}; +// Casting though a differently sized type is OK +static OFFSET_U8_PTR: bool = unsafe { + let p1 = (&S.a as *const u32 as *const u8).offset(5); + let p2 = (&S.c as *const u32 as *const u8).offset(-3); + p1.offset_from(p2) == 0 +}; +// Any offset with a ZST does nothing +const OFFSET_ZST: bool = unsafe { + let pz = &() as *const (); + // offset_from can't work with ZSTs, so cast to u8 ptr + let p1 = pz.offset(5) as *const u8; + let p2 = pz.offset(isize::MIN) as *const u8; + p1.offset_from(p2) == 0 +}; +const OFFSET_ZERO: bool = unsafe { + let p = [0u8; 0].as_ptr(); + p.offset(0).offset_from(p) == 0 +}; +const OFFSET_ONE: bool = unsafe { + let p = &42u32 as *const u32; + p.offset(1).offset_from(p) == 1 +}; +const OFFSET_DANGLING: bool = unsafe { + let p = ptr::NonNull::::dangling().as_ptr(); + p.offset(0).offset_from(p) == 0 +}; +const OFFSET_UNALIGNED: bool = unsafe { + let arr = [0u8; 32]; + let p1 = arr.as_ptr(); + let p2 = (p1.offset(2) as *const u32).offset(1); + (p2 as *const u8).offset_from(p1) == 6 +}; + +const WRAP_OFFSET_NO_CHANGE: bool = unsafe { + let p1 = &42u32 as *const u32; + let p2 = p1.wrapping_offset(1000).wrapping_offset(-1000); + let p3 = p1.wrapping_offset(-1000).wrapping_offset(1000); + (p1.offset_from(p2) == 0) & (p1.offset_from(p3) == 0) +}; +const WRAP_ADDRESS_SPACE: bool = unsafe { + let p1 = &42u8 as *const u8; + let p2 = p1.wrapping_offset(isize::MIN).wrapping_offset(isize::MIN); + p1.offset_from(p2) == 0 +}; +// Wrap on the count*size_of::() calculation. +const WRAP_SIZE_OF: bool = unsafe { + // Make sure that if p1 moves backwards, we are still in range + let arr = [0u32; 2]; + let p = &arr[1] as *const u32; + // With wrapping arithmetic, isize::MAX * 4 == -4 + let wrapped = p.wrapping_offset(isize::MAX); + let backward = p.wrapping_offset(-1); + wrapped.offset_from(backward) == 0 +}; +const WRAP_INTEGER_POINTER: bool = unsafe { + let p1 = (0x42 as *const u32).wrapping_offset(4); + let p2 = 0x52 as *const u32; + p1.offset_from(p2) == 0 +}; +const WRAP_NULL: bool = unsafe { + let p1 = ptr::null::().wrapping_offset(1); + let p2 = 0x4 as *const u32; + p1.offset_from(p2) == 0 +}; + +fn main() { + assert!(OFFSET_NO_CHANGE); + assert!(OFFSET_MIDDLE); + assert!(OFFSET_END); + assert!(OFFSET_U8_PTR); + assert!(OFFSET_ZST); + assert!(OFFSET_ZERO); + assert!(OFFSET_ONE); + assert!(OFFSET_DANGLING); + assert!(OFFSET_UNALIGNED); + + assert!(WRAP_OFFSET_NO_CHANGE); + assert!(WRAP_ADDRESS_SPACE); + assert!(WRAP_SIZE_OF); + assert!(WRAP_INTEGER_POINTER); + assert!(WRAP_NULL); +} diff --git a/tests/ui/consts/offset_from.rs b/tests/ui/consts/offset_from.rs new file mode 100644 index 000000000..465147041 --- /dev/null +++ b/tests/ui/consts/offset_from.rs @@ -0,0 +1,59 @@ +// run-pass + +#![feature(const_ptr_sub_ptr)] +#![feature(ptr_sub_ptr)] + +struct Struct { + field: (), +} + +#[repr(C)] +struct Struct2 { + data: u8, + field: u8, +} + +pub const OFFSET: usize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + // The following statement is UB (taking the address of an uninitialized field). + // Const eval doesn't detect this right now, but it may stop compiling at some point + // in the future. + let field_ptr = unsafe { &(*base_ptr).field as *const () as *const u8 }; + let offset = unsafe { field_ptr.offset_from(base_ptr as *const u8) }; + offset as usize +}; + +pub const OFFSET_2: usize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct2 = &uninit as *const _ as *const Struct2; + let field_ptr = unsafe { &(*base_ptr).field as *const u8 }; + let offset = unsafe { field_ptr.offset_from(base_ptr as *const u8) }; + offset as usize +}; + +pub const OVERFLOW: isize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct2 = &uninit as *const _ as *const Struct2; + let field_ptr = unsafe { &(*base_ptr).field as *const u8 }; + unsafe { (base_ptr as *const u8).offset_from(field_ptr) } +}; + +pub const OFFSET_EQUAL_INTS: isize = { + let ptr = 1 as *const u8; + unsafe { ptr.offset_from(ptr) } +}; + +pub const OFFSET_UNSIGNED: usize = { + let a = ['a', 'b', 'c']; + let ptr = a.as_ptr(); + unsafe { ptr.add(2).sub_ptr(ptr) } +}; + +fn main() { + assert_eq!(OFFSET, 0); + assert_eq!(OFFSET_2, 1); + assert_eq!(OVERFLOW, -1); + assert_eq!(OFFSET_EQUAL_INTS, 0); + assert_eq!(OFFSET_UNSIGNED, 2); +} diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs new file mode 100644 index 000000000..51163e650 --- /dev/null +++ b/tests/ui/consts/offset_from_ub.rs @@ -0,0 +1,125 @@ +#![feature(const_ptr_sub_ptr)] +#![feature(core_intrinsics)] + +use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned}; +use std::ptr; + +#[repr(C)] +struct Struct { + data: u8, + field: u8, +} + +pub const DIFFERENT_ALLOC: usize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + let uninit2 = std::mem::MaybeUninit::::uninit(); + let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct; + let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed + //~| pointers into different allocations + offset as usize +}; + +pub const NOT_PTR: usize = { + unsafe { (42 as *const u8).offset_from(&5u8) as usize } +}; + +pub const NOT_MULTIPLE_OF_SIZE: isize = { + let data = [5u8, 6, 7]; + let base_ptr = data.as_ptr(); + let field_ptr = &data[1] as *const u8 as *const u16; + unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } //~ERROR evaluation of constant value failed + //~| 1_isize cannot be divided by 2_isize without remainder +}; + +pub const OFFSET_FROM_NULL: isize = { + let ptr = 0 as *const u8; + unsafe { ptr_offset_from(ptr, ptr) } //~ERROR evaluation of constant value failed + //~| null pointer is a dangling pointer +}; + +pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC + let ptr1 = 8 as *const u8; + let ptr2 = 16 as *const u8; + unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed + //~| 0x8[noalloc] is a dangling pointer +}; + +const OUT_OF_BOUNDS_1: isize = { + let start_ptr = &4 as *const _ as *const u8; + let length = 10; + let end_ptr = (start_ptr).wrapping_add(length); + // First ptr is out of bounds + unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed + //~| pointer to 10 bytes starting at offset 0 is out-of-bounds +}; + +const OUT_OF_BOUNDS_2: isize = { + let start_ptr = &4 as *const _ as *const u8; + let length = 10; + let end_ptr = (start_ptr).wrapping_add(length); + // Second ptr is out of bounds + unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed + //~| pointer to 10 bytes starting at offset 0 is out-of-bounds +}; + +const OUT_OF_BOUNDS_SAME: isize = { + let start_ptr = &4 as *const _ as *const u8; + let length = 10; + let end_ptr = (start_ptr).wrapping_add(length); + unsafe { ptr_offset_from(end_ptr, end_ptr) } //~ERROR evaluation of constant value failed + //~| pointer at offset 10 is out-of-bounds +}; + +pub const DIFFERENT_ALLOC_UNSIGNED: usize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + let uninit2 = std::mem::MaybeUninit::::uninit(); + let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct; + unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } //~ERROR evaluation of constant value failed + //~| pointers into different allocations +}; + +pub const TOO_FAR_APART1: isize = { + let ptr1 = ptr::null::(); + let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42); + unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed + //~| too far ahead +}; +pub const TOO_FAR_APART2: isize = { + let ptr1 = ptr::null::(); + let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42); + unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed + //~| too far before +}; + +const WRONG_ORDER_UNSIGNED: usize = { + let a = ['a', 'b', 'c']; + let p = a.as_ptr(); + unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } //~ERROR evaluation of constant value failed + //~| first pointer has smaller offset than second: 0 < 8 +}; +pub const TOO_FAR_APART_UNSIGNED: usize = { + let ptr1 = ptr::null::(); + let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42); + // This would fit into a `usize` but we still don't allow it. + unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } //~ERROR evaluation of constant value failed + //~| too far ahead +}; + +// These do NOT complain that pointers are too far apart; they pass that check (to then fail the +// next one). +pub const OFFSET_VERY_FAR1: isize = { + let ptr1 = ptr::null::(); + let ptr2 = ptr1.wrapping_offset(isize::MAX); + unsafe { ptr2.offset_from(ptr1) } + //~^ inside +}; +pub const OFFSET_VERY_FAR2: isize = { + let ptr1 = ptr::null::(); + let ptr2 = ptr1.wrapping_offset(isize::MAX); + unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) } + //~^ inside +}; + +fn main() {} diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr new file mode 100644 index 000000000..fff472968 --- /dev/null +++ b/tests/ui/consts/offset_from_ub.stderr @@ -0,0 +1,114 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:18:27 + | +LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: `ptr_offset_from` called on pointers into different allocations + | +note: inside `ptr::const_ptr::::offset_from` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `NOT_PTR` + --> $DIR/offset_from_ub.rs:24:14 + | +LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:31:14 + | +LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:37:14 + | +LL | unsafe { ptr_offset_from(ptr, ptr) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:44:14 + | +LL | unsafe { ptr_offset_from(ptr2, ptr1) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x8[noalloc] is a dangling pointer (it has no provenance) + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:53:14 + | +LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:62:14 + | +LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:70:14 + | +LL | unsafe { ptr_offset_from(end_ptr, end_ptr) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc24 has size 4, so pointer at offset 10 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:79:14 + | +LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:86:14 + | +LL | unsafe { ptr_offset_from(ptr2, ptr1) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:92:14 + | +LL | unsafe { ptr_offset_from(ptr1, ptr2) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:99:14 + | +LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8 + +error[E0080]: evaluation of constant value failed + --> $DIR/offset_from_ub.rs:106:14 + | +LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) + | +note: inside `ptr::const_ptr::::offset_from` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `OFFSET_VERY_FAR1` + --> $DIR/offset_from_ub.rs:115:14 + | +LL | unsafe { ptr2.offset_from(ptr1) } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance) + | +note: inside `ptr::const_ptr::::offset_from` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `OFFSET_VERY_FAR2` + --> $DIR/offset_from_ub.rs:121:14 + | +LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs new file mode 100644 index 000000000..1b01e4fd1 --- /dev/null +++ b/tests/ui/consts/offset_ub.rs @@ -0,0 +1,26 @@ +use std::ptr; + +// normalize-stderr-test "alloc\d+" -> "allocN" +// normalize-stderr-test "0x7f+" -> "0x7f..f" + + +pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE +pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; //~NOTE +pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; //~NOTE + +pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; //~NOTE +pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; //~NOTE +pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; //~NOTE +pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; //~NOTE +pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; //~NOTE + +pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; //~NOTE +pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_ptr().offset(4) }; //~NOTE + +// Right now, a zero offset from null is UB +pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::().offset(0) }; //~NOTE + +// Make sure that we don't panic when computing abs(offset*size_of::()) +pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) }; //~NOTE + +fn main() {} diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr new file mode 100644 index 000000000..c0c851df5 --- /dev/null +++ b/tests/ui/consts/offset_ub.stderr @@ -0,0 +1,159 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: overflowing in-bounds pointer arithmetic + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `BEFORE_START` + --> $DIR/offset_ub.rs:7:46 + | +LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `AFTER_END` + --> $DIR/offset_ub.rs:8:43 + | +LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `AFTER_ARRAY` + --> $DIR/offset_ub.rs:9:45 + | +LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: overflowing in-bounds pointer arithmetic + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `OVERFLOW` + --> $DIR/offset_ub.rs:11:43 + | +LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: overflowing in-bounds pointer arithmetic + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `UNDERFLOW` + --> $DIR/offset_ub.rs:12:44 + | +LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: overflowing in-bounds pointer arithmetic + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `OVERFLOW_ADDRESS_SPACE` + --> $DIR/offset_ub.rs:13:56 + | +LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: overflowing in-bounds pointer arithmetic + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `UNDERFLOW_ADDRESS_SPACE` + --> $DIR/offset_ub.rs:14:57 + | +LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `NEGATIVE_OFFSET` + --> $DIR/offset_ub.rs:15:49 + | +LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `ZERO_SIZED_ALLOC` + --> $DIR/offset_ub.rs:17:50 + | +LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance) + | +note: inside `ptr::mut_ptr::::offset` + --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL +note: inside `DANGLING` + --> $DIR/offset_ub.rs:18:42 + | +LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_ptr().offset(4) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance) + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `NULL_OFFSET_ZERO` + --> $DIR/offset_ub.rs:21:50 + | +LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::().offset(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance) + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `UNDERFLOW_ABS` + --> $DIR/offset_ub.rs:24:47 + | +LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/packed_pattern.rs b/tests/ui/consts/packed_pattern.rs new file mode 100644 index 000000000..370fec6fb --- /dev/null +++ b/tests/ui/consts/packed_pattern.rs @@ -0,0 +1,19 @@ +// run-pass + +#[derive(PartialEq, Eq, Copy, Clone)] +#[repr(packed)] +struct Foo { + field: (i64, u32, u32, u32), +} + +const FOO: Foo = Foo { + field: (5, 6, 7, 8), +}; + +fn main() { + match FOO { + Foo { field: (5, 6, 7, 8) } => {}, + FOO => unreachable!(), //~ WARNING unreachable pattern + _ => unreachable!(), + } +} diff --git a/tests/ui/consts/packed_pattern.stderr b/tests/ui/consts/packed_pattern.stderr new file mode 100644 index 000000000..9ca50a95e --- /dev/null +++ b/tests/ui/consts/packed_pattern.stderr @@ -0,0 +1,10 @@ +warning: unreachable pattern + --> $DIR/packed_pattern.rs:16:9 + | +LL | FOO => unreachable!(), + | ^^^ + | + = note: `#[warn(unreachable_patterns)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/packed_pattern2.rs b/tests/ui/consts/packed_pattern2.rs new file mode 100644 index 000000000..ef68d9e51 --- /dev/null +++ b/tests/ui/consts/packed_pattern2.rs @@ -0,0 +1,27 @@ +// run-pass + +#[derive(PartialEq, Eq, Copy, Clone)] +#[repr(packed)] +struct Foo { + field: (u8, u16), +} + +#[derive(PartialEq, Eq, Copy, Clone)] +#[repr(align(2))] +struct Bar { + a: Foo, +} + +const FOO: Bar = Bar { + a: Foo { + field: (5, 6), + } +}; + +fn main() { + match FOO { + Bar { a: Foo { field: (5, 6) } } => {}, + FOO => unreachable!(), //~ WARNING unreachable pattern + _ => unreachable!(), + } +} diff --git a/tests/ui/consts/packed_pattern2.stderr b/tests/ui/consts/packed_pattern2.stderr new file mode 100644 index 000000000..4dc54461e --- /dev/null +++ b/tests/ui/consts/packed_pattern2.stderr @@ -0,0 +1,10 @@ +warning: unreachable pattern + --> $DIR/packed_pattern2.rs:24:9 + | +LL | FOO => unreachable!(), + | ^^^ + | + = note: `#[warn(unreachable_patterns)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/partial_qualif.rs b/tests/ui/consts/partial_qualif.rs new file mode 100644 index 000000000..7c28b8b8a --- /dev/null +++ b/tests/ui/consts/partial_qualif.rs @@ -0,0 +1,9 @@ +use std::cell::Cell; + +const FOO: &(Cell, bool) = { + let mut a = (Cell::new(0), false); + a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)` + &{a} //~ ERROR cannot refer to interior mutable +}; + +fn main() {} diff --git a/tests/ui/consts/partial_qualif.stderr b/tests/ui/consts/partial_qualif.stderr new file mode 100644 index 000000000..32c25be21 --- /dev/null +++ b/tests/ui/consts/partial_qualif.stderr @@ -0,0 +1,9 @@ +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/partial_qualif.rs:6:5 + | +LL | &{a} + | ^^^^ this borrow of an interior mutable value may end up in the final value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/precise-drop-with-coverage.rs b/tests/ui/consts/precise-drop-with-coverage.rs new file mode 100644 index 000000000..275cb3869 --- /dev/null +++ b/tests/ui/consts/precise-drop-with-coverage.rs @@ -0,0 +1,16 @@ +// Checks that code coverage doesn't interfere with const_precise_live_drops. +// Regression test for issue #93848. +// +// check-pass +// compile-flags: --crate-type=lib -Cinstrument-coverage -Zno-profiler-runtime + +#![feature(const_precise_live_drops)] + +#[inline] +pub const fn transpose(this: Option>) -> Result, E> { + match this { + Some(Ok(x)) => Ok(Some(x)), + Some(Err(e)) => Err(e), + None => Ok(None), + } +} diff --git a/tests/ui/consts/precise-drop-with-promoted.rs b/tests/ui/consts/precise-drop-with-promoted.rs new file mode 100644 index 000000000..6f2317a5a --- /dev/null +++ b/tests/ui/consts/precise-drop-with-promoted.rs @@ -0,0 +1,9 @@ +// Regression test for issue #89938. +// check-pass +// compile-flags: --crate-type=lib +#![feature(const_precise_live_drops)] + +pub const fn f() { + let _: Option = None; + let _: &'static Option = &None; +} diff --git a/tests/ui/consts/promote-not.rs b/tests/ui/consts/promote-not.rs new file mode 100644 index 000000000..907617052 --- /dev/null +++ b/tests/ui/consts/promote-not.rs @@ -0,0 +1,68 @@ +// ignore-tidy-linelength +// Test various things that we do not want to promote. +#![allow(unconditional_panic)] + +use std::cell::Cell; + +// We do not promote mutable references. +static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed + +static mut TEST2: &'static mut [i32] = { + let x = &mut [1,2,3]; //~ ERROR temporary value dropped while borrowed + x +}; + +// We do not promote fn calls in `fn`, including `const fn`. +pub const fn promote_cal(b: bool) -> i32 { + const fn foo() { [()][42] } + + if b { + let _x: &'static () = &foo(); //~ ERROR temporary value dropped while borrowed + } + 13 +} + +// We do not promote union field accesses in `fn. +union U { x: i32, y: i32 } +pub const fn promote_union() { + let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed +} + +// We do not promote union field accesses in `const`, either. +const TEST_UNION: () = { + let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed +}; + +// In a `const`, we do not promote things with interior mutability. Not even if we "project it away". +const TEST_INTERIOR_MUT: () = { + // The "0." case is already ruled out by not permitting any interior mutability in `const`. + let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed +}; + +const TEST_DROP: String = String::new(); + +fn main() { + // We must not promote things with interior mutability. Not even if we "project it away". + let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed + let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed + + // No promotion of fallible operations. + let _val: &'static _ = &(1/0); //~ ERROR temporary value dropped while borrowed + let _val: &'static _ = &(1/(1-1)); //~ ERROR temporary value dropped while borrowed + let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed + let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed + let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed + + // No promotion of temporaries that need to be dropped. + let _val: &'static _ = &TEST_DROP; + //~^ ERROR temporary value dropped while borrowed + let _val: &'static _ = &&TEST_DROP; + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed + let _val: &'static _ = &(&TEST_DROP,); + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed + let _val: &'static _ = &[&TEST_DROP; 1]; + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/promote-not.stderr b/tests/ui/consts/promote-not.stderr new file mode 100644 index 000000000..b93358e8d --- /dev/null +++ b/tests/ui/consts/promote-not.stderr @@ -0,0 +1,215 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:8:50 + | +LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); + | ----------^^^^^^^^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:11:18 + | +LL | let x = &mut [1,2,3]; + | ^^^^^^^ creates a temporary value which is freed while still in use +LL | x + | - using this value as a static requires that borrow lasts for `'static` +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:20:32 + | +LL | let _x: &'static () = &foo(); + | ----------- ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:28:29 + | +LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:33:29 + | +LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:39:29 + | +LL | let _val: &'static _ = &(Cell::new(1), 2).1; + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:46:29 + | +LL | let _val: &'static _ = &(Cell::new(1), 2).0; + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:47:29 + | +LL | let _val: &'static _ = &(Cell::new(1), 2).1; + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:50:29 + | +LL | let _val: &'static _ = &(1/0); + | ---------- ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:51:29 + | +LL | let _val: &'static _ = &(1/(1-1)); + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:52:29 + | +LL | let _val: &'static _ = &(1%0); + | ---------- ^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:53:29 + | +LL | let _val: &'static _ = &(1%(1-1)); + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:54:29 + | +LL | let _val: &'static _ = &([1,2,3][4]+1); + | ---------- ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:57:29 + | +LL | let _val: &'static _ = &TEST_DROP; + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:59:29 + | +LL | let _val: &'static _ = &&TEST_DROP; + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:59:30 + | +LL | let _val: &'static _ = &&TEST_DROP; + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:62:29 + | +LL | let _val: &'static _ = &(&TEST_DROP,); + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:62:31 + | +LL | let _val: &'static _ = &(&TEST_DROP,); + | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:65:29 + | +LL | let _val: &'static _ = &[&TEST_DROP; 1]; + | ---------- ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:65:31 + | +LL | let _val: &'static _ = &[&TEST_DROP; 1]; + | ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/promote_borrowed_field.rs b/tests/ui/consts/promote_borrowed_field.rs new file mode 100644 index 000000000..c4841b46f --- /dev/null +++ b/tests/ui/consts/promote_borrowed_field.rs @@ -0,0 +1,12 @@ +// run-pass + +// From https://github.com/rust-lang/rust/issues/65727 + +const _: &i32 = { + let x = &(5, false).0; + x +}; + +fn main() { + let _: &'static i32 = &(5, false).0; +} diff --git a/tests/ui/consts/promote_const_let.rs b/tests/ui/consts/promote_const_let.rs new file mode 100644 index 000000000..51a0fec2e --- /dev/null +++ b/tests/ui/consts/promote_const_let.rs @@ -0,0 +1,10 @@ +fn main() { + let x: &'static u32 = { + let y = 42; + &y //~ ERROR does not live long enough + }; + let x: &'static u32 = &{ //~ ERROR temporary value dropped while borrowed + let y = 42; + y + }; +} diff --git a/tests/ui/consts/promote_const_let.stderr b/tests/ui/consts/promote_const_let.stderr new file mode 100644 index 000000000..975a235a6 --- /dev/null +++ b/tests/ui/consts/promote_const_let.stderr @@ -0,0 +1,29 @@ +error[E0597]: `y` does not live long enough + --> $DIR/promote_const_let.rs:4:9 + | +LL | let x: &'static u32 = { + | ------------ type annotation requires that `y` is borrowed for `'static` +LL | let y = 42; +LL | &y + | ^^ borrowed value does not live long enough +LL | }; + | - `y` dropped here while still borrowed + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote_const_let.rs:6:28 + | +LL | let x: &'static u32 = &{ + | ____________------------____^ + | | | + | | type annotation requires that borrow lasts for `'static` +LL | | let y = 42; +LL | | y +LL | | }; + | |_____^ creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/consts/promote_evaluation_unused_result.rs b/tests/ui/consts/promote_evaluation_unused_result.rs new file mode 100644 index 000000000..4eda785bb --- /dev/null +++ b/tests/ui/consts/promote_evaluation_unused_result.rs @@ -0,0 +1,6 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + + let _: &'static usize = &(loop {}, 1).1; +} diff --git a/tests/ui/consts/promote_fn_calls.rs b/tests/ui/consts/promote_fn_calls.rs new file mode 100644 index 000000000..8995aaacd --- /dev/null +++ b/tests/ui/consts/promote_fn_calls.rs @@ -0,0 +1,11 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:promotable_const_fn_lib.rs + +extern crate promotable_const_fn_lib; + +use promotable_const_fn_lib::{foo, Foo}; + +fn main() { + let x: &'static usize = &foo(); + let x: &'static usize = &Foo::foo(); +} diff --git a/tests/ui/consts/promote_fn_calls_std.rs b/tests/ui/consts/promote_fn_calls_std.rs new file mode 100644 index 000000000..557f6a434 --- /dev/null +++ b/tests/ui/consts/promote_fn_calls_std.rs @@ -0,0 +1,29 @@ +#![allow(deprecated, deprecated_in_future)] // can be removed if different fns are chosen +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + let x: &'static u8 = &u8::max_value(); + let x: &'static u16 = &u16::max_value(); + let x: &'static u32 = &u32::max_value(); + let x: &'static u64 = &u64::max_value(); + let x: &'static u128 = &u128::max_value(); + let x: &'static usize = &usize::max_value(); + let x: &'static u8 = &u8::min_value(); + let x: &'static u16 = &u16::min_value(); + let x: &'static u32 = &u32::min_value(); + let x: &'static u64 = &u64::min_value(); + let x: &'static u128 = &u128::min_value(); + let x: &'static usize = &usize::min_value(); + let x: &'static i8 = &i8::max_value(); + let x: &'static i16 = &i16::max_value(); + let x: &'static i32 = &i32::max_value(); + let x: &'static i64 = &i64::max_value(); + let x: &'static i128 = &i128::max_value(); + let x: &'static isize = &isize::max_value(); + let x: &'static i8 = &i8::min_value(); + let x: &'static i16 = &i16::min_value(); + let x: &'static i32 = &i32::min_value(); + let x: &'static i64 = &i64::min_value(); + let x: &'static i128 = &i128::min_value(); + let x: &'static isize = &isize::min_value(); +} diff --git a/tests/ui/consts/promoted-const-drop.rs b/tests/ui/consts/promoted-const-drop.rs new file mode 100644 index 000000000..c896c011a --- /dev/null +++ b/tests/ui/consts/promoted-const-drop.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] + +struct A(); + +impl const Drop for A { + fn drop(&mut self) {} +} + +const C: A = A(); + +fn main() { + let _: &'static A = &A(); //~ ERROR temporary value dropped while borrowed + let _: &'static [A] = &[C]; //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/promoted-const-drop.stderr b/tests/ui/consts/promoted-const-drop.stderr new file mode 100644 index 000000000..480283417 --- /dev/null +++ b/tests/ui/consts/promoted-const-drop.stderr @@ -0,0 +1,24 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted-const-drop.rs:13:26 + | +LL | let _: &'static A = &A(); + | ---------- ^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let _: &'static [A] = &[C]; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted-const-drop.rs:14:28 + | +LL | let _: &'static [A] = &[C]; + | ------------ ^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/promoted-storage.rs b/tests/ui/consts/promoted-storage.rs new file mode 100644 index 000000000..52ef685e8 --- /dev/null +++ b/tests/ui/consts/promoted-storage.rs @@ -0,0 +1,20 @@ +// Check that storage statements reset local qualification. +// check-pass +use std::cell::Cell; + +const C: Option> = { + let mut c = None; + let mut i = 0; + while i == 0 { + let mut x = None; + c = x; + x = Some(Cell::new(0)); + let _ = x; + i += 1; + } + c +}; + +fn main() { + let _: &'static _ = &C; +} diff --git a/tests/ui/consts/promoted-validation-55454.rs b/tests/ui/consts/promoted-validation-55454.rs new file mode 100644 index 000000000..23cae4fb5 --- /dev/null +++ b/tests/ui/consts/promoted-validation-55454.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/55454 +// build-pass (FIXME(62277): could be check-pass?) + +#[derive(PartialEq)] +struct This(T); + +fn main() { + This(Some(&1)) == This(Some(&1)); +} diff --git a/tests/ui/consts/promoted_const_call.rs b/tests/ui/consts/promoted_const_call.rs new file mode 100644 index 000000000..30ae73053 --- /dev/null +++ b/tests/ui/consts/promoted_const_call.rs @@ -0,0 +1,19 @@ +#![feature(const_mut_refs)] +#![feature(const_trait_impl)] +struct Panic; +impl const Drop for Panic { fn drop(&mut self) { panic!(); } } +pub const fn id(x: T) -> T { x } +pub const C: () = { + let _: &'static _ = &id(&Panic); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed +}; + +fn main() { + let _: &'static _ = &id(&Panic); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + let _: &'static _ = &&(Panic, 0).1; + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr new file mode 100644 index 000000000..83cc16f6f --- /dev/null +++ b/tests/ui/consts/promoted_const_call.stderr @@ -0,0 +1,65 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:7:26 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:7:30 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:13:26 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:13:30 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:16:26 + | +LL | let _: &'static _ = &&(Panic, 0).1; + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:16:27 + | +LL | let _: &'static _ = &&(Panic, 0).1; + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/promoted_const_call2.rs b/tests/ui/consts/promoted_const_call2.rs new file mode 100644 index 000000000..f332cd18c --- /dev/null +++ b/tests/ui/consts/promoted_const_call2.rs @@ -0,0 +1,14 @@ +#![feature(const_precise_live_drops)] +pub const fn id(x: T) -> T { x } +pub const C: () = { + let _: &'static _ = &id(&String::new()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + //~| ERROR: destructor of `String` cannot be evaluated at compile-time +}; + +fn main() { + let _: &'static _ = &id(&String::new()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/consts/promoted_const_call2.stderr b/tests/ui/consts/promoted_const_call2.stderr new file mode 100644 index 000000000..13d864ed3 --- /dev/null +++ b/tests/ui/consts/promoted_const_call2.stderr @@ -0,0 +1,50 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:4:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:4:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:11:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:11:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call2.rs:4:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_const_call3.rs b/tests/ui/consts/promoted_const_call3.rs new file mode 100644 index 000000000..6d68a2de7 --- /dev/null +++ b/tests/ui/consts/promoted_const_call3.rs @@ -0,0 +1,26 @@ +pub const fn id(x: T) -> T { x } +pub const C: () = { + let _: &'static _ = &String::new(); + //~^ ERROR: destructor of `String` cannot be evaluated at compile-time + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &id(&String::new()); + //~^ ERROR: destructor of `String` cannot be evaluated at compile-time + //~| ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + //~^ ERROR: temporary value dropped while borrowed +}; + +fn main() { + let _: &'static _ = &String::new(); + //~^ ERROR: temporary value dropped while borrowed + + let _: &'static _ = &id(&String::new()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/consts/promoted_const_call3.stderr b/tests/ui/consts/promoted_const_call3.stderr new file mode 100644 index 000000000..af17457a1 --- /dev/null +++ b/tests/ui/consts/promoted_const_call3.stderr @@ -0,0 +1,105 @@ +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:7:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:3:26 + | +LL | let _: &'static _ = &String::new(); + | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:3:26 + | +LL | let _: &'static _ = &String::new(); + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:7:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:7:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:12:26 + | +LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:17:26 + | +LL | let _: &'static _ = &String::new(); + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:20:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:20:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:24:26 + | +LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_const_call4.rs b/tests/ui/consts/promoted_const_call4.rs new file mode 100644 index 000000000..82a17b7bf --- /dev/null +++ b/tests/ui/consts/promoted_const_call4.rs @@ -0,0 +1,18 @@ +// run-pass + +use std::sync::atomic::*; + +static FLAG: AtomicBool = AtomicBool::new(false); + +struct NoisyDrop(&'static str); +impl Drop for NoisyDrop { + fn drop(&mut self) { + FLAG.store(true, Ordering::SeqCst); + } +} +fn main() { + { + let _val = &&(NoisyDrop("drop!"), 0).1; + } + assert!(FLAG.load(Ordering::SeqCst)); +} diff --git a/tests/ui/consts/promoted_const_call5.rs b/tests/ui/consts/promoted_const_call5.rs new file mode 100644 index 000000000..3ac8d358c --- /dev/null +++ b/tests/ui/consts/promoted_const_call5.rs @@ -0,0 +1,42 @@ +#![feature(rustc_attrs)] +#![feature(staged_api)] +#![stable(feature = "a", since = "1.0.0")] + +#[rustc_promotable] +#[stable(feature = "a", since = "1.0.0")] +#[rustc_const_stable(feature = "a", since = "1.0.0")] +pub const fn id(x: &'static T) -> &'static T { x } + +#[rustc_promotable] +#[stable(feature = "a", since = "1.0.0")] +#[rustc_const_stable(feature = "a", since = "1.0.0")] +pub const fn new_string() -> String { + String::new() +} + +#[rustc_promotable] +#[stable(feature = "a", since = "1.0.0")] +#[rustc_const_stable(feature = "a", since = "1.0.0")] +pub const fn new_manually_drop(t: T) -> std::mem::ManuallyDrop { + std::mem::ManuallyDrop::new(t) +} + + +const C: () = { + let _: &'static _ = &id(&new_string()); + //~^ ERROR destructor of `String` cannot be evaluated at compile-time + //~| ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &new_manually_drop(new_string()); + //~^ ERROR: temporary value dropped while borrowed +}; + +fn main() { + let _: &'static _ = &id(&new_string()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &new_manually_drop(new_string()); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/consts/promoted_const_call5.stderr b/tests/ui/consts/promoted_const_call5.stderr new file mode 100644 index 000000000..f736220b1 --- /dev/null +++ b/tests/ui/consts/promoted_const_call5.stderr @@ -0,0 +1,74 @@ +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call5.rs:26:30 + | +LL | let _: &'static _ = &id(&new_string()); + | ^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:26:26 + | +LL | let _: &'static _ = &id(&new_string()); + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:26:30 + | +LL | let _: &'static _ = &id(&new_string()); + | ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:31:26 + | +LL | let _: &'static _ = &new_manually_drop(new_string()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:36:26 + | +LL | let _: &'static _ = &id(&new_string()); + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:36:30 + | +LL | let _: &'static _ = &id(&new_string()); + | ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:40:26 + | +LL | let _: &'static _ = &new_manually_drop(new_string()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_regression.rs b/tests/ui/consts/promoted_regression.rs new file mode 100644 index 000000000..d57036ae5 --- /dev/null +++ b/tests/ui/consts/promoted_regression.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + let _ = &[("", ""); 3]; +} + +const FOO: &[(&str, &str)] = &[("", ""); 3]; +const BAR: &[(&str, &str); 5] = &[("", ""); 5]; +const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11]; diff --git a/tests/ui/consts/promotion-mutable-ref.rs b/tests/ui/consts/promotion-mutable-ref.rs new file mode 100644 index 000000000..d103c5a9d --- /dev/null +++ b/tests/ui/consts/promotion-mutable-ref.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(const_mut_refs)] + +static mut TEST: i32 = { + // We must not promote this, as CTFE needs to be able to mutate it later. + let x = &mut [1,2,3]; + x[0] += 1; + x[0] +}; + +// This still works -- it's not done via promotion. +#[allow(unused)] +static mut TEST2: &'static mut [i32] = &mut [0,1,2]; + +fn main() { + assert_eq!(unsafe { TEST }, 2); +} diff --git a/tests/ui/consts/promotion.rs b/tests/ui/consts/promotion.rs new file mode 100644 index 000000000..e379e3aea --- /dev/null +++ b/tests/ui/consts/promotion.rs @@ -0,0 +1,45 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +// build-pass + +const fn assert_static(_: &'static T) {} + +#[allow(unconditional_panic)] +const fn fail() -> i32 { + 1/0 +} +const C: i32 = { + // Promoted that fails to evaluate in dead code -- this must work + // (for backwards compatibility reasons). + if false { + assert_static(&fail()); + } + 42 +}; + +fn main() { + assert_static(&["a", "b", "c"]); + assert_static(&["d", "e", "f"]); + assert_eq!(C, 42); + + // make sure that these do not cause trouble despite overflowing + assert_static(&(0-1)); + assert_static(&-i32::MIN); + + // div-by-non-0 is okay + assert_static(&(1/1)); + assert_static(&(1%1)); + + // in-bounds array access is okay + assert_static(&([1,2,3][0] + 1)); + assert_static(&[[1,2][1]]); + + // Top-level projections are not part of the promoted, so no error here. + if false { + #[allow(unconditional_panic)] + assert_static(&[1,2,3][4]); + } +} diff --git a/tests/ui/consts/ptr_comparisons.rs b/tests/ui/consts/ptr_comparisons.rs new file mode 100644 index 000000000..f442e6138 --- /dev/null +++ b/tests/ui/consts/ptr_comparisons.rs @@ -0,0 +1,63 @@ +// compile-flags: --crate-type=lib +// normalize-stderr-32bit: "8 bytes" -> "$$TWO_WORDS bytes" +// normalize-stderr-64bit: "16 bytes" -> "$$TWO_WORDS bytes" +// normalize-stderr-32bit: "size 4" -> "size $$WORD" +// normalize-stderr-64bit: "size 8" -> "size $$WORD" + +#![feature( + core_intrinsics, + const_raw_ptr_comparison, +)] + +const FOO: &usize = &42; + +macro_rules! check { + (eq, $a:expr, $b:expr) => { + pub const _: () = + assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 1); + }; + (ne, $a:expr, $b:expr) => { + pub const _: () = + assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 0); + }; + (!, $a:expr, $b:expr) => { + pub const _: () = + assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 2); + }; +} + +check!(eq, 0, 0); +check!(ne, 0, 1); +check!(ne, FOO as *const _, 0); +check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0); +check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0); + +// We want pointers to be equal to themselves, but aren't checking this yet because +// there are some open questions (e.g. whether function pointers to the same function +// compare equal, they don't necessarily at runtime). +// The case tested here should work eventually, but does not work yet. +check!(!, FOO as *const _, FOO as *const _); + + +/////////////////////////////////////////////////////////////////////////////// +// If any of the below start compiling, make sure to add a `check` test for it. +// These invocations exist as canaries so we don't forget to check that the +// behaviour of `guaranteed_eq` and `guaranteed_ne` is still correct. +// All of these try to obtain an out of bounds pointer in some manner. If we +// can create out of bounds pointers, we can offset a pointer far enough that +// at runtime it would be zero and at compile-time it would not be zero. + +const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; + +const _: *const u8 = + unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; +//~^ ERROR evaluation of constant value failed +//~| out-of-bounds + +const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; +//~^ ERROR evaluation of constant value failed +//~| unable to turn pointer into raw bytes + +const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; +//~^ ERROR evaluation of constant value failed +//~| unable to turn pointer into raw bytes diff --git a/tests/ui/consts/ptr_comparisons.stderr b/tests/ui/consts/ptr_comparisons.stderr new file mode 100644 index 000000000..fea924d12 --- /dev/null +++ b/tests/ui/consts/ptr_comparisons.stderr @@ -0,0 +1,40 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds + | +note: inside `ptr::const_ptr::::offset` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `_` + --> $DIR/ptr_comparisons.rs:50:34 + | +LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/ptr_comparisons.rs:53:33 + | +LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds + +error[E0080]: evaluation of constant value failed + --> $DIR/ptr_comparisons.rs:57:27 + | +LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: evaluation of constant value failed + --> $DIR/ptr_comparisons.rs:61:27 + | +LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/ptr_is_null.rs b/tests/ui/consts/ptr_is_null.rs new file mode 100644 index 000000000..8babb6858 --- /dev/null +++ b/tests/ui/consts/ptr_is_null.rs @@ -0,0 +1,16 @@ +// compile-flags: --crate-type=lib +// check-pass + +#![feature(const_ptr_is_null)] + +const FOO: &usize = &42; + +pub const _: () = assert!(!(FOO as *const usize).is_null()); + +pub const _: () = assert!(!(42 as *const usize).is_null()); + +pub const _: () = assert!((0 as *const usize).is_null()); + +pub const _: () = assert!(std::ptr::null::().is_null()); + +pub const _: () = assert!(!("foo" as *const str).is_null()); diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.rs b/tests/ui/consts/qualif-indirect-mutation-fail.rs new file mode 100644 index 000000000..a6d293404 --- /dev/null +++ b/tests/ui/consts/qualif-indirect-mutation-fail.rs @@ -0,0 +1,64 @@ +// compile-flags: --crate-type=lib +#![feature(const_mut_refs)] +#![feature(const_precise_live_drops)] +#![feature(const_swap)] +#![feature(raw_ref_op)] + +// Mutable borrow of a field with drop impl. +pub const fn f() { + let mut a: (u32, Option) = (0, None); //~ ERROR destructor of + let _ = &mut a.1; +} + +// Mutable borrow of a type with drop impl. +pub const A1: () = { + let mut x = None; //~ ERROR destructor of + let mut y = Some(String::new()); + let a = &mut x; + let b = &mut y; + std::mem::swap(a, b); + std::mem::forget(y); +}; + +// Mutable borrow of a type with drop impl. +pub const A2: () = { + let mut x = None; + let mut y = Some(String::new()); + let a = &mut x; + let b = &mut y; + std::mem::swap(a, b); + std::mem::forget(y); + let _z = x; //~ ERROR destructor of +}; + +// Shared borrow of a type that might be !Freeze and Drop. +pub const fn g1() { + let x: Option = None; //~ ERROR destructor of + let _ = x.is_some(); +} + +// Shared borrow of a type that might be !Freeze and Drop. +pub const fn g2() { + let x: Option = None; + let _ = x.is_some(); + let _y = x; //~ ERROR destructor of +} + +// Mutable raw reference to a Drop type. +pub const fn address_of_mut() { + let mut x: Option = None; //~ ERROR destructor of + &raw mut x; + + let mut y: Option = None; //~ ERROR destructor of + std::ptr::addr_of_mut!(y); +} + +// Const raw reference to a Drop type. Conservatively assumed to allow mutation +// until resolution of https://github.com/rust-lang/rust/issues/56604. +pub const fn address_of_const() { + let x: Option = None; //~ ERROR destructor of + &raw const x; + + let y: Option = None; //~ ERROR destructor of + std::ptr::addr_of!(y); +} diff --git a/tests/ui/consts/qualif-indirect-mutation-fail.stderr b/tests/ui/consts/qualif-indirect-mutation-fail.stderr new file mode 100644 index 000000000..6379c00e4 --- /dev/null +++ b/tests/ui/consts/qualif-indirect-mutation-fail.stderr @@ -0,0 +1,57 @@ +error[E0493]: destructor of `(u32, Option)` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:9:9 + | +LL | let mut a: (u32, Option) = (0, None); + | ^^^^^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:15:9 + | +LL | let mut x = None; + | ^^^^^ the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:31:9 + | +LL | let _z = x; + | ^^ the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:36:9 + | +LL | let x: Option = None; + | ^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:44:9 + | +LL | let _y = x; + | ^^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:52:9 + | +LL | let mut y: Option = None; + | ^^^^^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:49:9 + | +LL | let mut x: Option = None; + | ^^^^^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:62:9 + | +LL | let y: Option = None; + | ^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `Option` cannot be evaluated at compile-time + --> $DIR/qualif-indirect-mutation-fail.rs:59:9 + | +LL | let x: Option = None; + | ^ the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/qualif-indirect-mutation-pass.rs b/tests/ui/consts/qualif-indirect-mutation-pass.rs new file mode 100644 index 000000000..06af6a03b --- /dev/null +++ b/tests/ui/consts/qualif-indirect-mutation-pass.rs @@ -0,0 +1,24 @@ +// compile-flags: --crate-type=lib +// check-pass +#![feature(const_mut_refs)] +#![feature(const_precise_live_drops)] + +// Mutable reference allows only mutation of !Drop place. +pub const fn f() { + let mut x: (Option, u32) = (None, 0); + let mut a = 10; + *(&mut a) = 11; + x.1 = a; +} + +// Mutable reference allows only mutation of !Drop place. +pub const fn g() { + let mut a: (u32, Option) = (0, None); + let _ = &mut a.0; +} + +// Shared reference does not allow for mutation. +pub const fn h() { + let x: Option = None; + let _ = &x; +} diff --git a/tests/ui/consts/qualif-union.rs b/tests/ui/consts/qualif-union.rs new file mode 100644 index 000000000..11c019be9 --- /dev/null +++ b/tests/ui/consts/qualif-union.rs @@ -0,0 +1,33 @@ +// Checks that unions use type based qualification. Regression test for issue #90268. + +use std::cell::Cell; +use std::mem::ManuallyDrop; + +union U { i: u32, c: ManuallyDrop> } + +const C1: ManuallyDrop> = { + unsafe { U { c: ManuallyDrop::new(Cell::new(0)) }.c } +}; + +const C2: ManuallyDrop> = { + unsafe { U { i : 0 }.c } +}; + +const C3: ManuallyDrop> = { + let mut u = U { i: 0 }; + u.i = 1; + unsafe { u.c } +}; + +const C4: U = U { i: 0 }; + +const C5: [U; 1] = [U {i : 0}; 1]; + +fn main() { + // Interior mutability should prevent promotion. + let _: &'static _ = &C1; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C2; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C3; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C4; //~ ERROR temporary value dropped while borrowed + let _: &'static _ = &C5; //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/consts/qualif-union.stderr b/tests/ui/consts/qualif-union.stderr new file mode 100644 index 000000000..d847cf88f --- /dev/null +++ b/tests/ui/consts/qualif-union.stderr @@ -0,0 +1,57 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:28:26 + | +LL | let _: &'static _ = &C1; + | ---------- ^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:29:26 + | +LL | let _: &'static _ = &C2; + | ---------- ^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:30:26 + | +LL | let _: &'static _ = &C3; + | ---------- ^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:31:26 + | +LL | let _: &'static _ = &C4; + | ---------- ^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | let _: &'static _ = &C5; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/qualif-union.rs:32:26 + | +LL | let _: &'static _ = &C5; + | ---------- ^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/qualif_overwrite.rs b/tests/ui/consts/qualif_overwrite.rs new file mode 100644 index 000000000..aae4e41ff --- /dev/null +++ b/tests/ui/consts/qualif_overwrite.rs @@ -0,0 +1,13 @@ +use std::cell::Cell; + +// this is overly conservative. The reset to `None` should clear `a` of all qualifications +// while we could fix this, it would be inconsistent with `qualif_overwrite_2.rs`. +// We can fix this properly in the future by allowing constants that do not depend on generics +// to be checked by an analysis on the final value instead of looking at the body. +const FOO: &Option> = { + let mut a = Some(Cell::new(0)); + a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` + &{a} //~ ERROR cannot refer to interior mutable +}; + +fn main() {} diff --git a/tests/ui/consts/qualif_overwrite.stderr b/tests/ui/consts/qualif_overwrite.stderr new file mode 100644 index 000000000..86a669c43 --- /dev/null +++ b/tests/ui/consts/qualif_overwrite.stderr @@ -0,0 +1,9 @@ +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/qualif_overwrite.rs:10:5 + | +LL | &{a} + | ^^^^ this borrow of an interior mutable value may end up in the final value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/qualif_overwrite_2.rs b/tests/ui/consts/qualif_overwrite_2.rs new file mode 100644 index 000000000..1819d9a6d --- /dev/null +++ b/tests/ui/consts/qualif_overwrite_2.rs @@ -0,0 +1,11 @@ +use std::cell::Cell; + +// const qualification is not smart enough to know about fields and always assumes that there might +// be other fields that caused the qualification +const FOO: &Option> = { + let mut a = (Some(Cell::new(0)),); + a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)` + &{a.0} //~ ERROR cannot refer to interior mutable +}; + +fn main() {} diff --git a/tests/ui/consts/qualif_overwrite_2.stderr b/tests/ui/consts/qualif_overwrite_2.stderr new file mode 100644 index 000000000..9eb123d0b --- /dev/null +++ b/tests/ui/consts/qualif_overwrite_2.stderr @@ -0,0 +1,9 @@ +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/qualif_overwrite_2.rs:8:5 + | +LL | &{a.0} + | ^^^^^^ this borrow of an interior mutable value may end up in the final value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/consts/raw-ptr-const.rs b/tests/ui/consts/raw-ptr-const.rs new file mode 100644 index 000000000..b9c542d03 --- /dev/null +++ b/tests/ui/consts/raw-ptr-const.rs @@ -0,0 +1,8 @@ +// This is a regression test for a `delay_span_bug` during interning when a constant +// evaluates to a (non-dangling) raw pointer. For now this errors; potentially it +// could also be allowed. + +const CONST_RAW: *const Vec = &Vec::new() as *const _; +//~^ ERROR untyped pointers are not allowed in constant + +fn main() {} diff --git a/tests/ui/consts/raw-ptr-const.stderr b/tests/ui/consts/raw-ptr-const.stderr new file mode 100644 index 000000000..f7b53433b --- /dev/null +++ b/tests/ui/consts/raw-ptr-const.stderr @@ -0,0 +1,8 @@ +error: untyped pointers are not allowed in constant + --> $DIR/raw-ptr-const.rs:5:1 + | +LL | const CONST_RAW: *const Vec = &Vec::new() as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/consts/raw_pointer_promoted.rs b/tests/ui/consts/raw_pointer_promoted.rs new file mode 100644 index 000000000..4c62ad444 --- /dev/null +++ b/tests/ui/consts/raw_pointer_promoted.rs @@ -0,0 +1,5 @@ +// check-pass + +pub const FOO: &'static *const i32 = &(&0 as _); + +fn main() {} diff --git a/tests/ui/consts/recursive-zst-static.default.stderr b/tests/ui/consts/recursive-zst-static.default.stderr new file mode 100644 index 000000000..d68960b09 --- /dev/null +++ b/tests/ui/consts/recursive-zst-static.default.stderr @@ -0,0 +1,25 @@ +error[E0391]: cycle detected when const-evaluating + checking `FOO` + --> $DIR/recursive-zst-static.rs:10:1 + | +LL | static FOO: () = FOO; + | ^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... + --> $DIR/recursive-zst-static.rs:10:18 + | +LL | static FOO: () = FOO; + | ^^^ + = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle +note: cycle used when linting top-level module + --> $DIR/recursive-zst-static.rs:10:1 + | +LL | / static FOO: () = FOO; +LL | | +LL | | fn main() { +LL | | FOO +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/recursive-zst-static.rs b/tests/ui/consts/recursive-zst-static.rs new file mode 100644 index 000000000..4e61634b3 --- /dev/null +++ b/tests/ui/consts/recursive-zst-static.rs @@ -0,0 +1,14 @@ +// revisions: default unleash +//[unleash]compile-flags: -Zunleash-the-miri-inside-of-you + +// This test ensures that we do not allow ZST statics to initialize themselves without ever +// actually creating a value of that type. This is important, as the ZST may have private fields +// that users can reasonably expect to only get initialized by their own code. Thus unsafe code +// can depend on this fact and will thus do unsound things when it is violated. +// See https://github.com/rust-lang/rust/issues/71078 for more details. + +static FOO: () = FOO; //~ cycle detected when const-evaluating + checking `FOO` + +fn main() { + FOO +} diff --git a/tests/ui/consts/recursive-zst-static.unleash.stderr b/tests/ui/consts/recursive-zst-static.unleash.stderr new file mode 100644 index 000000000..d68960b09 --- /dev/null +++ b/tests/ui/consts/recursive-zst-static.unleash.stderr @@ -0,0 +1,25 @@ +error[E0391]: cycle detected when const-evaluating + checking `FOO` + --> $DIR/recursive-zst-static.rs:10:1 + | +LL | static FOO: () = FOO; + | ^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... + --> $DIR/recursive-zst-static.rs:10:18 + | +LL | static FOO: () = FOO; + | ^^^ + = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle +note: cycle used when linting top-level module + --> $DIR/recursive-zst-static.rs:10:1 + | +LL | / static FOO: () = FOO; +LL | | +LL | | fn main() { +LL | | FOO +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/recursive.rs b/tests/ui/consts/recursive.rs new file mode 100644 index 000000000..5d736e31b --- /dev/null +++ b/tests/ui/consts/recursive.rs @@ -0,0 +1,10 @@ +#![allow(unused)] + +const fn f(x: T) { //~ WARN function cannot return without recursing + f(x); + //~^ ERROR evaluation of constant value failed +} + +const X: () = f(1); + +fn main() {} diff --git a/tests/ui/consts/recursive.stderr b/tests/ui/consts/recursive.stderr new file mode 100644 index 000000000..60ce64d2a --- /dev/null +++ b/tests/ui/consts/recursive.stderr @@ -0,0 +1,36 @@ +warning: function cannot return without recursing + --> $DIR/recursive.rs:3:1 + | +LL | const fn f(x: T) { + | ^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | f(x); + | ---- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0080]: evaluation of constant value failed + --> $DIR/recursive.rs:4:5 + | +LL | f(x); + | ^^^^ reached the configured maximum number of stack frames + | +note: inside `f::` + --> $DIR/recursive.rs:4:5 + | +LL | f(x); + | ^^^^ +note: [... 126 additional calls inside `f::` ...] + --> $DIR/recursive.rs:4:5 + | +LL | f(x); + | ^^^^ +note: inside `X` + --> $DIR/recursive.rs:8:15 + | +LL | const X: () = f(1); + | ^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/references.rs b/tests/ui/consts/references.rs new file mode 100644 index 000000000..d0af47a8e --- /dev/null +++ b/tests/ui/consts/references.rs @@ -0,0 +1,27 @@ +// run-pass + +const FOO: &[u8] = b"foo"; +const BAR: &[u8] = &[1, 2, 3]; + +const BOO: &i32 = &42; + +fn main() { + match &[1u8, 2, 3] as &[u8] { + FOO => panic!("a"), + BAR => println!("b"), + _ => panic!("c"), + } + + match b"foo" as &[u8] { + FOO => println!("a"), + BAR => panic!("b"), + _ => panic!("c"), + } + + #[allow(unreachable_patterns)] + match &43 { + &42 => panic!(), + BOO => panic!(), + _ => println!("d"), + } +} diff --git a/tests/ui/consts/refs_check_const_eq-issue-88384.rs b/tests/ui/consts/refs_check_const_eq-issue-88384.rs new file mode 100644 index 000000000..1496b28bd --- /dev/null +++ b/tests/ui/consts/refs_check_const_eq-issue-88384.rs @@ -0,0 +1,25 @@ +#![feature(fn_traits)] +#![feature(adt_const_params)] +//~^ WARNING the feature `adt_const_params` is incomplete + +#[derive(PartialEq, Eq)] +struct CompileTimeSettings{ + hooks: &'static[fn()], +} + +struct Foo; +//~^ ERROR using function pointers as const generic parameters is forbidden + +impl Foo { + //~^ ERROR using function pointers as const generic parameters is forbidden + fn call_hooks(){ + } +} + +fn main(){ + const SETTINGS: CompileTimeSettings = CompileTimeSettings{ + hooks: &[], + }; + + Foo::::call_hooks(); +} diff --git a/tests/ui/consts/refs_check_const_eq-issue-88384.stderr b/tests/ui/consts/refs_check_const_eq-issue-88384.stderr new file mode 100644 index 000000000..3855b5f2a --- /dev/null +++ b/tests/ui/consts/refs_check_const_eq-issue-88384.stderr @@ -0,0 +1,24 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/refs_check_const_eq-issue-88384.rs:2:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/refs_check_const_eq-issue-88384.rs:10:21 + | +LL | struct Foo; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/refs_check_const_eq-issue-88384.rs:13:15 + | +LL | impl Foo { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs b/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs new file mode 100644 index 000000000..6ce9da436 --- /dev/null +++ b/tests/ui/consts/refs_check_const_value_eq-issue-88876.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +struct FooConst {} + +const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"]; + +fn main() { + let _ = FooConst:: {}; +} diff --git a/tests/ui/consts/repeat_match.rs b/tests/ui/consts/repeat_match.rs new file mode 100644 index 000000000..20983184a --- /dev/null +++ b/tests/ui/consts/repeat_match.rs @@ -0,0 +1,12 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/45044 + +const X: [u8; 1] = [0; 1]; + +fn main() { + match &X { + &X => println!("a"), + _ => println!("b"), + }; +} diff --git a/tests/ui/consts/return-in-const-fn.rs b/tests/ui/consts/return-in-const-fn.rs new file mode 100644 index 000000000..077a33c08 --- /dev/null +++ b/tests/ui/consts/return-in-const-fn.rs @@ -0,0 +1,10 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/43754 + +const fn foo(x: usize) -> usize { + return x; +} +fn main() { + [0; foo(2)]; +} diff --git a/tests/ui/consts/rustc-const-stability-require-const.rs b/tests/ui/consts/rustc-const-stability-require-const.rs new file mode 100644 index 000000000..4fb259b33 --- /dev/null +++ b/tests/ui/consts/rustc-const-stability-require-const.rs @@ -0,0 +1,47 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "foo", since = "1.0.0")] + +#[stable(feature = "foo", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_foo", issue = "none")] +pub fn foo() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + +#[stable(feature = "bar", since = "1.0.0")] +#[rustc_const_stable(feature = "const_bar", since = "1.0.0")] +pub fn bar() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + +#[stable(feature = "potato", since = "1.0.0")] +pub struct Potato; + +impl Potato { + #[stable(feature = "salad", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_salad", issue = "none")] + pub fn salad(&self) -> &'static str { "mmmmmm" } + //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + + #[stable(feature = "roasted", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_roasted", issue = "none")] + pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" } + //~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` +} + +#[stable(feature = "bar", since = "1.0.0")] +#[rustc_const_stable(feature = "const_bar", since = "1.0.0")] +pub extern "C" fn bar_c() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + +#[stable(feature = "foo", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_foo", issue = "none")] +pub extern "C" fn foo_c() {} +//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + + +#[stable(feature = "foobar", since = "1.0.0")] +#[rustc_const_unstable(feature = "foobar_const", issue = "none")] +pub const fn foobar() {} + +#[stable(feature = "barfoo", since = "1.0.0")] +#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")] +pub const fn barfoo() {} diff --git a/tests/ui/consts/rustc-const-stability-require-const.stderr b/tests/ui/consts/rustc-const-stability-require-const.stderr new file mode 100644 index 000000000..1027b9311 --- /dev/null +++ b/tests/ui/consts/rustc-const-stability-require-const.stderr @@ -0,0 +1,86 @@ +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")] + | -------------------------------------------------------------- attribute specified here +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:7:1 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:12:1 + | +LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")] + | ------------------------------------------------------------- attribute specified here +LL | pub fn bar() {} + | ^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:12:1 + | +LL | pub fn bar() {} + | ^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:21:5 + | +LL | #[rustc_const_unstable(feature = "const_salad", issue = "none")] + | ---------------------------------------------------------------- attribute specified here +LL | pub fn salad(&self) -> &'static str { "mmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:21:5 + | +LL | pub fn salad(&self) -> &'static str { "mmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:26:5 + | +LL | #[rustc_const_unstable(feature = "const_roasted", issue = "none")] + | ------------------------------------------------------------------ attribute specified here +LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:26:5 + | +LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:32:1 + | +LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")] + | ------------------------------------------------------------- attribute specified here +LL | pub extern "C" fn bar_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:32:1 + | +LL | pub extern "C" fn bar_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const` + --> $DIR/rustc-const-stability-require-const.rs:37:1 + | +LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")] + | -------------------------------------------------------------- attribute specified here +LL | pub extern "C" fn foo_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function or method const + --> $DIR/rustc-const-stability-require-const.rs:37:1 + | +LL | pub extern "C" fn foo_c() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/consts/rustc-impl-const-stability.rs b/tests/ui/consts/rustc-impl-const-stability.rs new file mode 100644 index 000000000..0c18efa0a --- /dev/null +++ b/tests/ui/consts/rustc-impl-const-stability.rs @@ -0,0 +1,19 @@ +// check-pass + +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![stable(feature = "foo", since = "1.0.0")] + +#[stable(feature = "potato", since = "1.27.0")] +pub struct Data { + _data: u128, +} + +#[stable(feature = "potato", since = "1.27.0")] +#[rustc_const_unstable(feature = "data_foo", issue = "none")] +impl const Default for Data { + fn default() -> Data { + Data { _data: 42 } + } +} diff --git a/tests/ui/consts/rvalue-static-promotion.rs b/tests/ui/consts/rvalue-static-promotion.rs new file mode 100644 index 000000000..c48d9eae9 --- /dev/null +++ b/tests/ui/consts/rvalue-static-promotion.rs @@ -0,0 +1,19 @@ +// run-pass + +use std::cell::Cell; + +const NONE_CELL_STRING: Option> = None; + +struct Foo(#[allow(unused_tuple_struct_fields)] T); +impl Foo { + const FOO: Option> = None; +} + +fn main() { + let _: &'static u32 = &42; + let _: &'static Option = &None; + + // We should be able to peek at consts and see they're None. + let _: &'static Option> = &NONE_CELL_STRING; + let _: &'static Option> = &Foo::FOO; +} diff --git a/tests/ui/consts/self_normalization.rs b/tests/ui/consts/self_normalization.rs new file mode 100644 index 000000000..b2a34f587 --- /dev/null +++ b/tests/ui/consts/self_normalization.rs @@ -0,0 +1,16 @@ +// check-pass + +fn testfn(_arr: &mut [(); 0]) {} + +trait TestTrait { + fn method(); +} + +impl TestTrait for [(); 0] { + fn method() { + let mut arr: Self = [(); 0]; + testfn(&mut arr); + } +} + +fn main() {} diff --git a/tests/ui/consts/self_normalization2.rs b/tests/ui/consts/self_normalization2.rs new file mode 100644 index 000000000..4fca38cba --- /dev/null +++ b/tests/ui/consts/self_normalization2.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Gen { + fn gen(x: Self) -> T; +} + +struct A; + +impl Gen<[(); 0]> for A { + fn gen(x: Self) -> [(); 0] { + [] + } +} + +fn array() -> impl Gen<[(); 0]> { + A +} + +fn main() { + let [] = Gen::gen(array()); +} diff --git a/tests/ui/consts/signed_enum_discr.rs b/tests/ui/consts/signed_enum_discr.rs new file mode 100644 index 000000000..2e4395ccf --- /dev/null +++ b/tests/ui/consts/signed_enum_discr.rs @@ -0,0 +1,19 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/49181 + +#[derive(Eq, PartialEq)] +#[repr(i8)] +pub enum A { + B = -1, + C = 1, +} + +pub const D: A = A::B; + +fn main() { + match A::C { + D => {}, + _ => {} + } +} diff --git a/tests/ui/consts/stable-precise-live-drops-in-libcore.rs b/tests/ui/consts/stable-precise-live-drops-in-libcore.rs new file mode 100644 index 000000000..7cd3dbec9 --- /dev/null +++ b/tests/ui/consts/stable-precise-live-drops-in-libcore.rs @@ -0,0 +1,22 @@ +#![stable(feature = "core", since = "1.6.0")] +#![feature(staged_api)] +#![feature(const_precise_live_drops)] + +enum Either { + Left(T), + Right(S), +} + +impl Either { + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "foo", since = "1.0.0")] + pub const fn unwrap(self) -> T { + //~^ ERROR destructor of + match self { + Self::Left(t) => t, + Self::Right(t) => t, + } + } +} + +fn main() {} diff --git a/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr b/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr new file mode 100644 index 000000000..5f70391ee --- /dev/null +++ b/tests/ui/consts/stable-precise-live-drops-in-libcore.stderr @@ -0,0 +1,12 @@ +error[E0493]: destructor of `Either` cannot be evaluated at compile-time + --> $DIR/stable-precise-live-drops-in-libcore.rs:13:25 + | +LL | pub const fn unwrap(self) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/static-cycle-error.rs b/tests/ui/consts/static-cycle-error.rs new file mode 100644 index 000000000..9ce050aae --- /dev/null +++ b/tests/ui/consts/static-cycle-error.rs @@ -0,0 +1,11 @@ +// check-pass + +struct Foo { + foo: Option<&'static Foo> +} + +static FOO: Foo = Foo { + foo: Some(&FOO), +}; + +fn main() {} diff --git a/tests/ui/consts/static-raw-pointer-interning.rs b/tests/ui/consts/static-raw-pointer-interning.rs new file mode 100644 index 000000000..cab60c91e --- /dev/null +++ b/tests/ui/consts/static-raw-pointer-interning.rs @@ -0,0 +1,15 @@ +// run-pass + +static FOO: Foo = Foo { + field: &42 as *const i32, +}; + +struct Foo { + field: *const i32, +} + +unsafe impl Sync for Foo {} + +fn main() { + assert_eq!(unsafe { *FOO.field }, 42); +} diff --git a/tests/ui/consts/static-raw-pointer-interning2.rs b/tests/ui/consts/static-raw-pointer-interning2.rs new file mode 100644 index 000000000..2b915fd7c --- /dev/null +++ b/tests/ui/consts/static-raw-pointer-interning2.rs @@ -0,0 +1,15 @@ +// run-pass + +static mut FOO: Foo = Foo { + field: &mut [42] as *mut [i32] as *mut i32, +}; + +struct Foo { + field: *mut i32, +} + +unsafe impl Sync for Foo {} + +fn main() { + assert_eq!(unsafe { *FOO.field = 69; *FOO.field }, 69); +} diff --git a/tests/ui/consts/static_mut_containing_mut_ref.rs b/tests/ui/consts/static_mut_containing_mut_ref.rs new file mode 100644 index 000000000..df09c76c5 --- /dev/null +++ b/tests/ui/consts/static_mut_containing_mut_ref.rs @@ -0,0 +1,7 @@ +// build-pass (FIXME(62277): could be check-pass?) + +static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; + +pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE }; + +fn main() {} diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr new file mode 100644 index 000000000..8db75dd63 --- /dev/null +++ b/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref2.rs:7:45 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.rs b/tests/ui/consts/static_mut_containing_mut_ref2.rs new file mode 100644 index 000000000..613685460 --- /dev/null +++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs @@ -0,0 +1,11 @@ +// revisions: stock mut_refs + +#![cfg_attr(mut_refs, feature(const_mut_refs))] + +static mut STDERR_BUFFER_SPACE: u8 = 0; + +pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; +//[mut_refs]~^ ERROR could not evaluate static initializer +//[stock]~^^ ERROR mutable references are not allowed in statics + +fn main() {} diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr new file mode 100644 index 000000000..5cdcea232 --- /dev/null +++ b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr @@ -0,0 +1,12 @@ +error[E0658]: mutable references are not allowed in statics + --> $DIR/static_mut_containing_mut_ref2.rs:7:46 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/static_mut_containing_mut_ref3.rs b/tests/ui/consts/static_mut_containing_mut_ref3.rs new file mode 100644 index 000000000..c24c7e279 --- /dev/null +++ b/tests/ui/consts/static_mut_containing_mut_ref3.rs @@ -0,0 +1,6 @@ +static mut FOO: (u8, u8) = (42, 43); + +static mut BAR: () = unsafe { FOO.0 = 99; }; +//~^ ERROR could not evaluate static initializer + +fn main() {} diff --git a/tests/ui/consts/static_mut_containing_mut_ref3.stderr b/tests/ui/consts/static_mut_containing_mut_ref3.stderr new file mode 100644 index 000000000..91f9dbd8d --- /dev/null +++ b/tests/ui/consts/static_mut_containing_mut_ref3.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref3.rs:3:31 + | +LL | static mut BAR: () = unsafe { FOO.0 = 99; }; + | ^^^^^^^^^^ modifying a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/std/alloc.32bit.stderr b/tests/ui/consts/std/alloc.32bit.stderr new file mode 100644 index 000000000..8c83df53d --- /dev/null +++ b/tests/ui/consts/std/alloc.32bit.stderr @@ -0,0 +1,25 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc.rs:12:1 + | +LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc.rs:16:1 + | +LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x00000003, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/std/alloc.64bit.stderr b/tests/ui/consts/std/alloc.64bit.stderr new file mode 100644 index 000000000..addedad17 --- /dev/null +++ b/tests/ui/consts/std/alloc.64bit.stderr @@ -0,0 +1,25 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc.rs:12:1 + | +LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000000, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc.rs:16:1 + | +LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000003, but expected a valid enum tag + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/std/alloc.rs b/tests/ui/consts/std/alloc.rs new file mode 100644 index 000000000..9abf35d63 --- /dev/null +++ b/tests/ui/consts/std/alloc.rs @@ -0,0 +1,19 @@ +// stderr-per-bitwidth +// ignore-debug (the debug assertions change the error) +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +use std::alloc::Layout; + +// ok +const LAYOUT_VALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x08) }; + +// not ok, since alignment needs to be non-zero. +const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; +//~^ ERROR it is undefined behavior to use this value + +// not ok, since alignment needs to be a power of two. +const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; +//~^ ERROR it is undefined behavior to use this value + +fn main() {} diff --git a/tests/ui/consts/std/cell.rs b/tests/ui/consts/std/cell.rs new file mode 100644 index 000000000..f1ef54131 --- /dev/null +++ b/tests/ui/consts/std/cell.rs @@ -0,0 +1,46 @@ +#![feature(const_refs_to_cell)] + +use std::cell::*; + +// not ok, because this creates a dangling pointer, just like `let x = Cell::new(42).as_ptr()` would +static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); +//~^ ERROR encountered dangling pointer +const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); +//~^ ERROR encountered dangling pointer + +// Ok, these are just base values and it is the `Wrap` author's job to uphold `Send` and `Sync` +// invariants, since they used `unsafe impl`. +static FOO3: Wrap> = Wrap(Cell::new(42)); +const FOO3_CONST: Wrap> = Wrap(Cell::new(42)); + +// ok, we are referring to the memory of another static item. +static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr()); + +// not ok, the use of a constant here is equivalent to an inline declaration of the value, so +// its memory will get freed before the constant is finished evaluating, thus creating a dangling +// pointer. This would happen exactly the same at runtime. +const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); +//~^ ERROR encountered dangling pointer + +// not ok, because the `as_ptr` call takes a reference to a temporary that will get freed +// before the constant is finished evaluating. +const FOO2: *mut u32 = Cell::new(42).as_ptr(); +//~^ ERROR encountered dangling pointer + +struct IMSafeTrustMe(UnsafeCell); +unsafe impl Send for IMSafeTrustMe {} +unsafe impl Sync for IMSafeTrustMe {} + +static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5)); + + + +struct Wrap(T); +unsafe impl Send for Wrap {} +unsafe impl Sync for Wrap {} + +static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get()); + +const fn fst_ref(x: &(T, U)) -> &T { &x.0 } + +fn main() {} diff --git a/tests/ui/consts/std/cell.stderr b/tests/ui/consts/std/cell.stderr new file mode 100644 index 000000000..937fa7db0 --- /dev/null +++ b/tests/ui/consts/std/cell.stderr @@ -0,0 +1,26 @@ +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:6:1 + | +LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:8:1 + | +LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:22:1 + | +LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: encountered dangling pointer in final constant + --> $DIR/cell.rs:27:1 + | +LL | const FOO2: *mut u32 = Cell::new(42).as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/consts/std/iter.rs b/tests/ui/consts/std/iter.rs new file mode 100644 index 000000000..e9af781eb --- /dev/null +++ b/tests/ui/consts/std/iter.rs @@ -0,0 +1,9 @@ +// run-pass + +const I: std::iter::Empty = std::iter::empty(); + +fn main() { + for i in I { + panic!("magical value creation: {}", i); + } +} diff --git a/tests/ui/consts/std/slice.rs b/tests/ui/consts/std/slice.rs new file mode 100644 index 000000000..f19defc64 --- /dev/null +++ b/tests/ui/consts/std/slice.rs @@ -0,0 +1,10 @@ +// build-pass (FIXME(62277): could be check-pass?) + +struct Wrap(T); +unsafe impl Send for Wrap {} +unsafe impl Sync for Wrap {} + +static FOO: Wrap<*const u32> = Wrap([42, 44, 46].as_ptr()); +static BAR: Wrap<*const u8> = Wrap("hello".as_ptr()); + +fn main() {} diff --git a/tests/ui/consts/too_generic_eval_ice.rs b/tests/ui/consts/too_generic_eval_ice.rs new file mode 100644 index 000000000..8b3f4b714 --- /dev/null +++ b/tests/ui/consts/too_generic_eval_ice.rs @@ -0,0 +1,14 @@ +pub struct Foo(A, B); + +impl Foo { + const HOST_SIZE: usize = std::mem::size_of::(); + + pub fn crash() -> bool { + [5; Self::HOST_SIZE] == [6; 0] + //~^ ERROR constant expression depends on a generic parameter + //~| ERROR constant expression depends on a generic parameter + //~| ERROR can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]` + } +} + +fn main() {} diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr new file mode 100644 index 000000000..5af82a3e3 --- /dev/null +++ b/tests/ui/consts/too_generic_eval_ice.stderr @@ -0,0 +1,37 @@ +error: constant expression depends on a generic parameter + --> $DIR/too_generic_eval_ice.rs:7:13 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/too_generic_eval_ice.rs:7:30 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0277]: can't compare `[{integer}; Self::HOST_SIZE]` with `[{integer}; 0]` + --> $DIR/too_generic_eval_ice.rs:7:30 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^ no implementation for `[{integer}; Self::HOST_SIZE] == [{integer}; 0]` + | + = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` + = help: the following other types implement trait `PartialEq`: + <&[B] as PartialEq<[A; N]>> + <&[T] as PartialEq>> + <&mut [B] as PartialEq<[A; N]>> + <&mut [T] as PartialEq>> + <[A; N] as PartialEq<&[B]>> + <[A; N] as PartialEq<&mut [B]>> + <[A; N] as PartialEq<[B; N]>> + <[A; N] as PartialEq<[B]>> + and 3 others + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/trait_specialization.rs b/tests/ui/consts/trait_specialization.rs new file mode 100644 index 000000000..c581ef6b0 --- /dev/null +++ b/tests/ui/consts/trait_specialization.rs @@ -0,0 +1,65 @@ +// ignore-wasm32-bare which doesn't support `std::process:exit()` +// compile-flags: -Zmir-opt-level=3 +// run-pass + +// Tests that specialization does not cause optimizations running on polymorphic MIR to resolve +// to a `default` implementation. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Marker {} + +trait SpecializedTrait { + const CONST_BOOL: bool; + const CONST_STR: &'static str; + fn method() -> &'static str; +} +impl SpecializedTrait for T { + default const CONST_BOOL: bool = false; + default const CONST_STR: &'static str = "in default impl"; + #[inline(always)] + default fn method() -> &'static str { + "in default impl" + } +} +impl SpecializedTrait for T { + const CONST_BOOL: bool = true; + const CONST_STR: &'static str = "in specialized impl"; + fn method() -> &'static str { + "in specialized impl" + } +} + +fn const_bool() -> &'static str { + if ::CONST_BOOL { + "in specialized impl" + } else { + "in default impl" + } +} +fn const_str() -> &'static str { + ::CONST_STR +} +fn run_method() -> &'static str { + ::method() +} + +struct TypeA; +impl Marker for TypeA {} +struct TypeB; + +#[inline(never)] +fn exit_if_not_eq(left: &str, right: &str) { + if left != right { + std::process::exit(1); + } +} + +pub fn main() { + exit_if_not_eq("in specialized impl", const_bool::()); + exit_if_not_eq("in default impl", const_bool::()); + exit_if_not_eq("in specialized impl", const_str::()); + exit_if_not_eq("in default impl", const_str::()); + exit_if_not_eq("in specialized impl", run_method::()); + exit_if_not_eq("in default impl", run_method::()); +} diff --git a/tests/ui/consts/trait_specialization.stderr b/tests/ui/consts/trait_specialization.stderr new file mode 100644 index 000000000..10bebe8eb --- /dev/null +++ b/tests/ui/consts/trait_specialization.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait_specialization.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/transmute-const.rs b/tests/ui/consts/transmute-const.rs new file mode 100644 index 000000000..c5c3dfc4c --- /dev/null +++ b/tests/ui/consts/transmute-const.rs @@ -0,0 +1,12 @@ +// run-pass + +use std::mem; + +#[repr(transparent)] +struct Foo(#[allow(unused_tuple_struct_fields)] u32); + +const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) }; + +fn main() { + assert_eq!(TRANSMUTED_U32, 3); +} diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs new file mode 100644 index 000000000..852a5b3b4 --- /dev/null +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs @@ -0,0 +1,13 @@ +// normalize-stderr-64bit "64 bits" -> "word size" +// normalize-stderr-32bit "32 bits" -> "word size" +// normalize-stderr-64bit "128 bits" -> "2 * word size" +// normalize-stderr-32bit "64 bits" -> "2 * word size" + +fn main() { + match &b""[..] { + ZST => {} + } +} + +const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; +//~^ ERROR cannot transmute between types of different sizes diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr new file mode 100644 index 000000000..4e8470173 --- /dev/null +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-size-mismatch-before-typeck.rs:12:29 + | +LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `usize` (word size) + = note: target type: `&[u8]` (2 * word size) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/consts/try-operator.rs b/tests/ui/consts/try-operator.rs new file mode 100644 index 000000000..fe43b132c --- /dev/null +++ b/tests/ui/consts/try-operator.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(try_trait_v2)] +#![feature(const_trait_impl)] +#![feature(const_try)] +#![feature(const_convert)] + +fn main() { + const fn result() -> Result { + Err(())?; + Ok(true) + } + + const FOO: Result = result(); + assert_eq!(Err(()), FOO); + + const fn option() -> Option<()> { + None?; + Some(()) + } + const BAR: Option<()> = option(); + assert_eq!(None, BAR); +} diff --git a/tests/ui/consts/tuple-struct-constructors.rs b/tests/ui/consts/tuple-struct-constructors.rs new file mode 100644 index 000000000..1655f0eb8 --- /dev/null +++ b/tests/ui/consts/tuple-struct-constructors.rs @@ -0,0 +1,10 @@ +// run-pass + +// https://github.com/rust-lang/rust/issues/41898 + +use std::num::NonZeroU64; + +fn main() { + const FOO: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(2) }; + if let FOO = FOO {} +} diff --git a/tests/ui/consts/underscore_const_names.rs b/tests/ui/consts/underscore_const_names.rs new file mode 100644 index 000000000..d0e625bf1 --- /dev/null +++ b/tests/ui/consts/underscore_const_names.rs @@ -0,0 +1,31 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![deny(unused)] + +trait Trt {} +pub struct Str {} +impl Trt for Str {} + +macro_rules! check_impl { + ($struct:ident,$trait:ident) => { + const _ : () = { + use std::marker::PhantomData; + struct ImplementsTrait(PhantomData); + let _ = ImplementsTrait::<$struct>(PhantomData); + () + }; + } +} + +const _ : () = (); + +const _ : i32 = 42; +const _ : Str = Str{}; + +check_impl!(Str, Trt); +check_impl!(Str, Trt); + +fn main() { + check_impl!(Str, Trt); + check_impl!(Str, Trt); +} diff --git a/tests/ui/consts/uninhabited-const-issue-61744.rs b/tests/ui/consts/uninhabited-const-issue-61744.rs new file mode 100644 index 000000000..ca6449cce --- /dev/null +++ b/tests/ui/consts/uninhabited-const-issue-61744.rs @@ -0,0 +1,19 @@ +// build-fail + +pub const unsafe fn fake_type() -> T { + hint_unreachable() //~ ERROR evaluation of `::CONSTANT` failed +} + +pub const unsafe fn hint_unreachable() -> ! { + fake_type() +} + +trait Const { + const CONSTANT: i32 = unsafe { fake_type() }; +} + +impl Const for T {} + +pub fn main() -> () { + dbg!(i32::CONSTANT); //~ constant +} diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr new file mode 100644 index 000000000..3a94e1931 --- /dev/null +++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr @@ -0,0 +1,668 @@ +error[E0080]: evaluation of `::CONSTANT` failed + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ reached the configured maximum number of stack frames + | +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `hint_unreachable` + --> $DIR/uninhabited-const-issue-61744.rs:8:5 + | +LL | fake_type() + | ^^^^^^^^^^^ +note: inside `fake_type::` + --> $DIR/uninhabited-const-issue-61744.rs:4:5 + | +LL | hint_unreachable() + | ^^^^^^^^^^^^^^^^^^ +note: inside `::CONSTANT` + --> $DIR/uninhabited-const-issue-61744.rs:12:36 + | +LL | const CONSTANT: i32 = unsafe { fake_type() }; + | ^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/uninhabited-const-issue-61744.rs:18:10 + | +LL | dbg!(i32::CONSTANT); + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/uninhabited-const-issue-61744.rs:18:10 + | +LL | dbg!(i32::CONSTANT); + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/uninhabited-const-issue-61744.rs:18:10 + | +LL | dbg!(i32::CONSTANT); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/union_constant.rs b/tests/ui/consts/union_constant.rs new file mode 100644 index 000000000..508ff7e0a --- /dev/null +++ b/tests/ui/consts/union_constant.rs @@ -0,0 +1,11 @@ +// build-pass (FIXME(62277): could be check-pass?) + +union Uninit { + _never_use: *const u8, + uninit: (), +} + +const UNINIT: Uninit = Uninit { uninit: () }; +const UNINIT2: (Uninit,) = (Uninit { uninit: () }, ); + +fn main() {} diff --git a/tests/ui/consts/unnormalized-param-env.rs b/tests/ui/consts/unnormalized-param-env.rs new file mode 100644 index 000000000..a7bbe4db9 --- /dev/null +++ b/tests/ui/consts/unnormalized-param-env.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait CSpace { + type Traj; +} + +pub struct Const; + +pub trait Obstacle { + fn trajectory_free(&self, t: &FT) + where + CS::Traj: Sized, + CS: CSpace; +} + +// ----- + +const N: usize = 4; + +struct ObstacleSpace2df32; + +impl Obstacle for ObstacleSpace2df32 { + fn trajectory_free(&self, t: &TF) + where + CS::Traj: Sized, + CS: CSpace, + { + } +} + +fn main() {} diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.rs b/tests/ui/consts/unstable-const-fn-in-libcore.rs new file mode 100644 index 000000000..ca4ed8f0b --- /dev/null +++ b/tests/ui/consts/unstable-const-fn-in-libcore.rs @@ -0,0 +1,27 @@ +// This is a non-regression test for const-qualification of unstable items in libcore +// as explained in issue #67053. +// const-qualification could miss some `const fn`s if they were unstable and the feature +// gate was not enabled in libcore. + +#![stable(feature = "core", since = "1.6.0")] +#![feature(staged_api, const_trait_impl)] + +enum Opt { + Some(T), + None, +} + +impl Opt { + #[rustc_const_unstable(feature = "foo", issue = "none")] + #[stable(feature = "rust1", since = "1.0.0")] + const fn unwrap_or_else T>(self, f: F) -> T { + //~^ ERROR destructor of + //~| ERROR destructor of + match self { + Opt::Some(t) => t, + Opt::None => f(), + } + } +} + +fn main() {} diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr new file mode 100644 index 000000000..e5b00dd07 --- /dev/null +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -0,0 +1,21 @@ +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:17:60 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `Opt` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:17:54 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/unstable-precise-live-drops-in-libcore.rs b/tests/ui/consts/unstable-precise-live-drops-in-libcore.rs new file mode 100644 index 000000000..619084eaa --- /dev/null +++ b/tests/ui/consts/unstable-precise-live-drops-in-libcore.rs @@ -0,0 +1,23 @@ +// check-pass + +#![stable(feature = "core", since = "1.6.0")] +#![feature(staged_api)] +#![feature(const_precise_live_drops)] + +enum Either { + Left(T), + Right(S), +} + +impl Either { + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "foo", issue = "none")] + pub const fn unwrap(self) -> T { + match self { + Self::Left(t) => t, + Self::Right(t) => t, + } + } +} + +fn main() {} diff --git a/tests/ui/consts/unwind-abort.rs b/tests/ui/consts/unwind-abort.rs new file mode 100644 index 000000000..6c94fc7b9 --- /dev/null +++ b/tests/ui/consts/unwind-abort.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(c_unwind, const_extern_fn)] + +// We don't unwind in const-eval anyways. +const extern "C" fn foo() { + panic!() +} + +const fn bar() { + foo(); +} + +fn main() { + bar(); +} diff --git a/tests/ui/consts/validate_never_arrays.rs b/tests/ui/consts/validate_never_arrays.rs new file mode 100644 index 000000000..f96ca6839 --- /dev/null +++ b/tests/ui/consts/validate_never_arrays.rs @@ -0,0 +1,12 @@ +// Strip out raw byte dumps to make comparison platform-independent: +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" +#![feature(never_type)] + +const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior +const _: &[!; 0] = unsafe { &*(1_usize as *const [!; 0]) }; // ok +const _: &[!] = unsafe { &*(1_usize as *const [!; 0]) }; // ok +const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior +const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior + +fn main() {} diff --git a/tests/ui/consts/validate_never_arrays.stderr b/tests/ui/consts/validate_never_arrays.stderr new file mode 100644 index 000000000..12090e483 --- /dev/null +++ b/tests/ui/consts/validate_never_arrays.stderr @@ -0,0 +1,36 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_never_arrays.rs:6:1 + | +LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; + | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_never_arrays.rs:9:1 + | +LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; + | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_never_arrays.rs:10:1 + | +LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; + | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/write-to-static-mut-in-static.rs b/tests/ui/consts/write-to-static-mut-in-static.rs new file mode 100644 index 000000000..43c63fed8 --- /dev/null +++ b/tests/ui/consts/write-to-static-mut-in-static.rs @@ -0,0 +1,10 @@ +pub static mut A: u32 = 0; +pub static mut B: () = unsafe { A = 1; }; +//~^ ERROR could not evaluate static initializer + +pub static mut C: u32 = unsafe { C = 1; 0 }; +//~^ ERROR cycle detected + +pub static D: u32 = D; + +fn main() {} diff --git a/tests/ui/consts/write-to-static-mut-in-static.stderr b/tests/ui/consts/write-to-static-mut-in-static.stderr new file mode 100644 index 000000000..395b2d42f --- /dev/null +++ b/tests/ui/consts/write-to-static-mut-in-static.stderr @@ -0,0 +1,34 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/write-to-static-mut-in-static.rs:2:33 + | +LL | pub static mut B: () = unsafe { A = 1; }; + | ^^^^^ modifying a static's initial value from another static's initializer + +error[E0391]: cycle detected when const-evaluating + checking `C` + --> $DIR/write-to-static-mut-in-static.rs:5:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `C`... + --> $DIR/write-to-static-mut-in-static.rs:5:34 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^ + = note: ...which again requires const-evaluating + checking `C`, completing the cycle +note: cycle used when linting top-level module + --> $DIR/write-to-static-mut-in-static.rs:1:1 + | +LL | / pub static mut A: u32 = 0; +LL | | pub static mut B: () = unsafe { A = 1; }; +LL | | +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/write_to_mut_ref_dest.rs b/tests/ui/consts/write_to_mut_ref_dest.rs new file mode 100644 index 000000000..484ec4244 --- /dev/null +++ b/tests/ui/consts/write_to_mut_ref_dest.rs @@ -0,0 +1,17 @@ +// revisions: stock mut_refs +//[mut_refs] check-pass + +#![cfg_attr(mut_refs, feature(const_mut_refs))] + +use std::cell::Cell; + +const FOO: &u32 = { + let mut a = 42; + { + let b: *mut u32 = &mut a; //[stock]~ ERROR mutable references are not allowed in constants + unsafe { *b = 5; } //[stock]~ ERROR dereferencing raw mutable pointers in constants + } + &{a} +}; + +fn main() {} diff --git a/tests/ui/consts/write_to_mut_ref_dest.stock.stderr b/tests/ui/consts/write_to_mut_ref_dest.stock.stderr new file mode 100644 index 000000000..bb1059276 --- /dev/null +++ b/tests/ui/consts/write_to_mut_ref_dest.stock.stderr @@ -0,0 +1,21 @@ +error[E0658]: mutable references are not allowed in constants + --> $DIR/write_to_mut_ref_dest.rs:11:27 + | +LL | let b: *mut u32 = &mut a; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/write_to_mut_ref_dest.rs:12:18 + | +LL | unsafe { *b = 5; } + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/write_to_static_via_mut_ref.rs b/tests/ui/consts/write_to_static_via_mut_ref.rs new file mode 100644 index 000000000..39b830ae4 --- /dev/null +++ b/tests/ui/consts/write_to_static_via_mut_ref.rs @@ -0,0 +1,7 @@ +#![feature(const_mut_refs)] + +static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable references are not allowed +fn main() { + assert_eq!(*OH_NO, 42); + *OH_NO = 43; //~ ERROR cannot assign to `*OH_NO`, as `OH_NO` is an immutable static +} diff --git a/tests/ui/consts/write_to_static_via_mut_ref.stderr b/tests/ui/consts/write_to_static_via_mut_ref.stderr new file mode 100644 index 000000000..f64f0db6b --- /dev/null +++ b/tests/ui/consts/write_to_static_via_mut_ref.stderr @@ -0,0 +1,16 @@ +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/write_to_static_via_mut_ref.rs:3:26 + | +LL | static OH_NO: &mut i32 = &mut 42; + | ^^^^^^^ + +error[E0594]: cannot assign to `*OH_NO`, as `OH_NO` is an immutable static item + --> $DIR/write_to_static_via_mut_ref.rs:6:5 + | +LL | *OH_NO = 43; + | ^^^^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0594, E0764. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/consts/zst_no_llvm_alloc.rs b/tests/ui/consts/zst_no_llvm_alloc.rs new file mode 100644 index 000000000..2a41f708c --- /dev/null +++ b/tests/ui/consts/zst_no_llvm_alloc.rs @@ -0,0 +1,21 @@ +// run-pass + +#[repr(align(4))] +struct Foo; + +static FOO: Foo = Foo; + +fn main() { + let x: &'static () = &(); + assert_ne!(x as *const () as usize, 1); + let x: &'static Foo = &Foo; + assert_ne!(x as *const Foo as usize, 4); + + // statics must have a unique address + assert_ne!(&FOO as *const Foo as usize, 4); + + // FIXME this two tests should be assert_eq! + // this stopped working since we are promoting to constants instead of statics + assert_ne!(>::new().as_ptr(), <&[i32]>::default().as_ptr()); + assert_ne!(>::default().as_ptr(), (&[]).as_ptr()); +} diff --git a/tests/ui/copy-a-resource.rs b/tests/ui/copy-a-resource.rs new file mode 100644 index 000000000..55f2dd4ee --- /dev/null +++ b/tests/ui/copy-a-resource.rs @@ -0,0 +1,21 @@ +#[derive(Debug)] +struct Foo { + i: isize, +} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn foo(i:isize) -> Foo { + Foo { + i: i + } +} + +fn main() { + let x = foo(10); + let _y = x.clone(); + //~^ ERROR no method named `clone` found + println!("{:?}", x); +} diff --git a/tests/ui/copy-a-resource.stderr b/tests/ui/copy-a-resource.stderr new file mode 100644 index 000000000..128087f1e --- /dev/null +++ b/tests/ui/copy-a-resource.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `clone` found for struct `Foo` in the current scope + --> $DIR/copy-a-resource.rs:18:16 + | +LL | struct Foo { + | ---------- method `clone` not found for this struct +... +LL | let _y = x.clone(); + | ^^^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/crate-leading-sep.rs b/tests/ui/crate-leading-sep.rs new file mode 100644 index 000000000..ca5905fab --- /dev/null +++ b/tests/ui/crate-leading-sep.rs @@ -0,0 +1,7 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + use ::std::mem; + mem::drop(2_usize); +} diff --git a/tests/ui/crate-loading/auxiliary/crateresolve1-1.rs b/tests/ui/crate-loading/auxiliary/crateresolve1-1.rs new file mode 100644 index 000000000..bd9c8483e --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crateresolve1-1.rs @@ -0,0 +1,6 @@ +// compile-flags:-C extra-filename=-1 +// no-prefer-dynamic +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/tests/ui/crate-loading/auxiliary/crateresolve1-2.rs b/tests/ui/crate-loading/auxiliary/crateresolve1-2.rs new file mode 100644 index 000000000..bd0f08f45 --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crateresolve1-2.rs @@ -0,0 +1,6 @@ +// compile-flags:-C extra-filename=-2 +// no-prefer-dynamic +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 20 } diff --git a/tests/ui/crate-loading/auxiliary/crateresolve1-3.rs b/tests/ui/crate-loading/auxiliary/crateresolve1-3.rs new file mode 100644 index 000000000..1226c2fbb --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crateresolve1-3.rs @@ -0,0 +1,6 @@ +// compile-flags:-C extra-filename=-3 +// no-prefer-dynamic +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 30 } diff --git a/tests/ui/crate-loading/auxiliary/crateresolve2-1.rs b/tests/ui/crate-loading/auxiliary/crateresolve2-1.rs new file mode 100644 index 000000000..e9459ed07 --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crateresolve2-1.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-1 --emit=metadata +#![crate_name = "crateresolve2"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/tests/ui/crate-loading/auxiliary/crateresolve2-2.rs b/tests/ui/crate-loading/auxiliary/crateresolve2-2.rs new file mode 100644 index 000000000..c45416827 --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crateresolve2-2.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-2 --emit=metadata +#![crate_name = "crateresolve2"] +#![crate_type = "lib"] + +pub fn f() -> isize { 20 } diff --git a/tests/ui/crate-loading/auxiliary/crateresolve2-3.rs b/tests/ui/crate-loading/auxiliary/crateresolve2-3.rs new file mode 100644 index 000000000..b356db4b6 --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crateresolve2-3.rs @@ -0,0 +1,5 @@ +// compile-flags:-C extra-filename=-3 --emit=metadata +#![crate_name = "crateresolve2"] +#![crate_type = "lib"] + +pub fn f() -> isize { 30 } diff --git a/tests/ui/crate-loading/auxiliary/libfoo.rlib b/tests/ui/crate-loading/auxiliary/libfoo.rlib new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/crate-loading/auxiliary/proc-macro.rs b/tests/ui/crate-loading/auxiliary/proc-macro.rs new file mode 100644 index 000000000..52631de57 --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/proc-macro.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_name = "reproduction"] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn mac(input: TokenStream) -> TokenStream { + input +} diff --git a/tests/ui/crate-loading/crateresolve1.rs b/tests/ui/crate-loading/crateresolve1.rs new file mode 100644 index 000000000..61a1ee263 --- /dev/null +++ b/tests/ui/crate-loading/crateresolve1.rs @@ -0,0 +1,14 @@ +// aux-build:crateresolve1-1.rs +// aux-build:crateresolve1-2.rs +// aux-build:crateresolve1-3.rs + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" +// normalize-stderr-test: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" + +// NOTE: This test is duplicated at `tests/ui/error-codes/E0464.rs`. + +extern crate crateresolve1; +//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found + +fn main() {} diff --git a/tests/ui/crate-loading/crateresolve1.stderr b/tests/ui/crate-loading/crateresolve1.stderr new file mode 100644 index 000000000..7b840b526 --- /dev/null +++ b/tests/ui/crate-loading/crateresolve1.stderr @@ -0,0 +1,13 @@ +error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found + --> $DIR/crateresolve1.rs:11:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib + = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib + = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/crate-loading/crateresolve2.rs b/tests/ui/crate-loading/crateresolve2.rs new file mode 100644 index 000000000..0774c0dfd --- /dev/null +++ b/tests/ui/crate-loading/crateresolve2.rs @@ -0,0 +1,13 @@ +// check-fail + +// aux-build:crateresolve2-1.rs +// aux-build:crateresolve2-2.rs +// aux-build:crateresolve2-3.rs + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" + +extern crate crateresolve2; +//~^ ERROR multiple candidates for `rmeta` dependency `crateresolve2` found + +fn main() {} diff --git a/tests/ui/crate-loading/crateresolve2.stderr b/tests/ui/crate-loading/crateresolve2.stderr new file mode 100644 index 000000000..a36f4f022 --- /dev/null +++ b/tests/ui/crate-loading/crateresolve2.stderr @@ -0,0 +1,13 @@ +error[E0464]: multiple candidates for `rmeta` dependency `crateresolve2` found + --> $DIR/crateresolve2.rs:10:1 + | +LL | extern crate crateresolve2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta + = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta + = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/crate-loading/cross-compiled-proc-macro.rs b/tests/ui/crate-loading/cross-compiled-proc-macro.rs new file mode 100644 index 000000000..c1f433143 --- /dev/null +++ b/tests/ui/crate-loading/cross-compiled-proc-macro.rs @@ -0,0 +1,8 @@ +// edition:2018 +// compile-flags:--extern reproduction +// aux-build:proc-macro.rs +// check-pass + +reproduction::mac!(); + +fn main() {} diff --git a/tests/ui/crate-loading/invalid-rlib.rs b/tests/ui/crate-loading/invalid-rlib.rs new file mode 100644 index 000000000..aea861e32 --- /dev/null +++ b/tests/ui/crate-loading/invalid-rlib.rs @@ -0,0 +1,10 @@ +// compile-flags: --crate-type lib --extern foo={{src-base}}/crate-loading/auxiliary/libfoo.rlib +// normalize-stderr-test: "failed to mmap file '.*auxiliary/libfoo.rlib':.*" -> "failed to mmap file 'auxiliary/libfoo.rlib'" +// don't emit warn logging, it's basically the same as the errors and it's annoying to normalize +// rustc-env:RUSTC_LOG=error +// edition:2018 +#![no_std] +use ::foo; //~ ERROR invalid metadata files for crate `foo` +//~| NOTE failed to mmap file +//~^^ ERROR invalid metadata files for crate `foo` +//~| NOTE failed to mmap file diff --git a/tests/ui/crate-loading/invalid-rlib.stderr b/tests/ui/crate-loading/invalid-rlib.stderr new file mode 100644 index 000000000..3c0d23bf7 --- /dev/null +++ b/tests/ui/crate-loading/invalid-rlib.stderr @@ -0,0 +1,19 @@ +error[E0786]: found invalid metadata files for crate `foo` + --> $DIR/invalid-rlib.rs:7:7 + | +LL | use ::foo; + | ^^^ + | + = note: failed to mmap file 'auxiliary/libfoo.rlib' + +error[E0786]: found invalid metadata files for crate `foo` + --> $DIR/invalid-rlib.rs:7:7 + | +LL | use ::foo; + | ^^^ + | + = note: failed to mmap file 'auxiliary/libfoo.rlib' + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0786`. diff --git a/tests/ui/crate-loading/missing-std.rs b/tests/ui/crate-loading/missing-std.rs new file mode 100644 index 000000000..400d9f6e0 --- /dev/null +++ b/tests/ui/crate-loading/missing-std.rs @@ -0,0 +1,12 @@ +// compile-flags: --target x86_64-unknown-uefi +// needs-llvm-components: x86 +// rustc-env:CARGO=/usr/bin/cargo +#![feature(no_core)] +#![no_core] +extern crate core; +//~^ ERROR can't find crate for `core` +//~| NOTE can't find crate +//~| NOTE target may not be installed +//~| HELP consider building the standard library from source with `cargo build -Zbuild-std` +//~| HELP consider downloading the target with `rustup target add x86_64-unknown-uefi` +fn main() {} diff --git a/tests/ui/crate-loading/missing-std.stderr b/tests/ui/crate-loading/missing-std.stderr new file mode 100644 index 000000000..70bcae1e0 --- /dev/null +++ b/tests/ui/crate-loading/missing-std.stderr @@ -0,0 +1,15 @@ +error[E0463]: can't find crate for `core` + --> $DIR/missing-std.rs:6:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ can't find crate + | + = note: the `x86_64-unknown-uefi` target may not be installed + = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error: requires `sized` lang_item + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/crate-method-reexport-grrrrrrr.rs b/tests/ui/crate-method-reexport-grrrrrrr.rs new file mode 100644 index 000000000..55e05cfb2 --- /dev/null +++ b/tests/ui/crate-method-reexport-grrrrrrr.rs @@ -0,0 +1,19 @@ +// run-pass +// pretty-expanded FIXME #23616 + +// This is a regression test that the metadata for the +// name_pool::methods impl in the other crate is reachable from this +// crate. + +// aux-build:crate-method-reexport-grrrrrrr2.rs + +extern crate crate_method_reexport_grrrrrrr2; + +pub fn main() { + use crate_method_reexport_grrrrrrr2::rust::add; + use crate_method_reexport_grrrrrrr2::rust::cx; + let x: Box<_> = Box::new(()); + x.cx(); + let y = (); + y.add("hi".to_string()); +} diff --git a/tests/ui/crate-name-attr-used.rs b/tests/ui/crate-name-attr-used.rs new file mode 100644 index 000000000..ad53a5314 --- /dev/null +++ b/tests/ui/crate-name-attr-used.rs @@ -0,0 +1,8 @@ +// run-pass +// compile-flags:--crate-name crate_name_attr_used -F unused-attributes + +// pretty-expanded FIXME #23616 + +#![crate_name = "crate_name_attr_used"] + +fn main() {} diff --git a/tests/ui/crate-name-mismatch.rs b/tests/ui/crate-name-mismatch.rs new file mode 100644 index 000000000..23ad39a6f --- /dev/null +++ b/tests/ui/crate-name-mismatch.rs @@ -0,0 +1,6 @@ +// compile-flags: --crate-name foo + +#![crate_name = "bar"] +//~^ ERROR: `--crate-name` and `#[crate_name]` are required to match, but `foo` != `bar` + +fn main() {} diff --git a/tests/ui/crate-name-mismatch.stderr b/tests/ui/crate-name-mismatch.stderr new file mode 100644 index 000000000..96618570d --- /dev/null +++ b/tests/ui/crate-name-mismatch.stderr @@ -0,0 +1,8 @@ +error: `--crate-name` and `#[crate_name]` are required to match, but `foo` != `bar` + --> $DIR/crate-name-mismatch.rs:3:1 + | +LL | #![crate_name = "bar"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/cross-crate/auxiliary/cci_borrow_lib.rs b/tests/ui/cross-crate/auxiliary/cci_borrow_lib.rs new file mode 100644 index 000000000..7c57a1c66 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_borrow_lib.rs @@ -0,0 +1,3 @@ +pub fn foo(x: &usize) -> usize { + *x +} diff --git a/tests/ui/cross-crate/auxiliary/cci_capture_clause.rs b/tests/ui/cross-crate/auxiliary/cci_capture_clause.rs new file mode 100644 index 000000000..4cd001ecc --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_capture_clause.rs @@ -0,0 +1,10 @@ +use std::thread; +use std::sync::mpsc::{Receiver, channel}; + +pub fn foo(x: T) -> Receiver { + let (tx, rx) = channel(); + thread::spawn(move|| { + tx.send(x.clone()); + }); + rx +} diff --git a/tests/ui/cross-crate/auxiliary/cci_const.rs b/tests/ui/cross-crate/auxiliary/cci_const.rs new file mode 100644 index 000000000..c83b3f4a5 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_const.rs @@ -0,0 +1,6 @@ +pub extern "C" fn bar() { +} + +pub const foopy: &'static str = "hi there"; +pub const uint_val: usize = 12; +pub const uint_expr: usize = (1 << uint_val) - 1; diff --git a/tests/ui/cross-crate/auxiliary/cci_impl_lib.rs b/tests/ui/cross-crate/auxiliary/cci_impl_lib.rs new file mode 100644 index 000000000..0db0037b2 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_impl_lib.rs @@ -0,0 +1,16 @@ +#![crate_name="cci_impl_lib"] + +pub trait uint_helpers { + fn to(&self, v: usize, f: F) where F: FnMut(usize); +} + +impl uint_helpers for usize { + #[inline] + fn to(&self, v: usize, mut f: F) where F: FnMut(usize) { + let mut i = *self; + while i < v { + f(i); + i += 1; + } + } +} diff --git a/tests/ui/cross-crate/auxiliary/cci_iter_lib.rs b/tests/ui/cross-crate/auxiliary/cci_iter_lib.rs new file mode 100644 index 000000000..60c36bc7d --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_iter_lib.rs @@ -0,0 +1,11 @@ +#![crate_name="cci_iter_lib"] + +#[inline] +pub fn iter(v: &[T], mut f: F) where F: FnMut(&T) { + let mut i = 0; + let n = v.len(); + while i < n { + f(&v[i]); + i += 1; + } +} diff --git a/tests/ui/cross-crate/auxiliary/cci_nested_lib.rs b/tests/ui/cross-crate/auxiliary/cci_nested_lib.rs new file mode 100644 index 000000000..23d76ef36 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_nested_lib.rs @@ -0,0 +1,50 @@ +use std::cell::RefCell; + +pub struct Entry { + key: A, + value: B +} + +pub struct alist { + eq_fn: extern "Rust" fn(A,A) -> bool, + data: Box>>>, +} + +pub fn alist_add(lst: &alist, k: A, v: B) { + let mut data = lst.data.borrow_mut(); + (*data).push(Entry{key:k, value:v}); +} + +pub fn alist_get( + lst: &alist, + k: A) + -> B { + let eq_fn = lst.eq_fn; + let data = lst.data.borrow(); + for entry in &(*data) { + if eq_fn(entry.key.clone(), k.clone()) { + return entry.value.clone(); + } + } + panic!(); +} + +#[inline] +pub fn new_int_alist() -> alist { + fn eq_int(a: isize, b: isize) -> bool { a == b } + return alist { + eq_fn: eq_int, + data: Box::new(RefCell::new(Vec::new())), + }; +} + +#[inline] +pub fn new_int_alist_2() -> alist { + #[inline] + fn eq_int(a: isize, b: isize) -> bool { a == b } + return alist { + eq_fn: eq_int, + data: Box::new(RefCell::new(Vec::new())), + }; +} diff --git a/tests/ui/cross-crate/auxiliary/cci_no_inline_lib.rs b/tests/ui/cross-crate/auxiliary/cci_no_inline_lib.rs new file mode 100644 index 000000000..177dba217 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/cci_no_inline_lib.rs @@ -0,0 +1,12 @@ +#![crate_name="cci_no_inline_lib"] + + +// same as cci_iter_lib, more-or-less, but not marked inline +pub fn iter(v: Vec , mut f: F) where F: FnMut(usize) { + let mut i = 0; + let n = v.len(); + while i < n { + f(v[i]); + i += 1; + } +} diff --git a/tests/ui/cross-crate/auxiliary/moves_based_on_type_lib.rs b/tests/ui/cross-crate/auxiliary/moves_based_on_type_lib.rs new file mode 100644 index 000000000..7e7e3b860 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/moves_based_on_type_lib.rs @@ -0,0 +1,17 @@ +#![crate_type="lib"] + +pub struct S { + x: isize, +} + +impl Drop for S { + fn drop(&mut self) { + println!("goodbye"); + } +} + +pub fn f() { + let x = S { x: 1 }; + let y = x; + let _z = y; +} diff --git a/tests/ui/cross-crate/auxiliary/pub_static_array.rs b/tests/ui/cross-crate/auxiliary/pub_static_array.rs new file mode 100644 index 000000000..49cb76921 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/pub_static_array.rs @@ -0,0 +1 @@ +pub static ARRAY: [u8; 1] = [1]; diff --git a/tests/ui/cross-crate/auxiliary/reexported_static_methods.rs b/tests/ui/cross-crate/auxiliary/reexported_static_methods.rs new file mode 100644 index 000000000..cc961625f --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/reexported_static_methods.rs @@ -0,0 +1,43 @@ +pub use sub_foo::Foo; +pub use self::Bar as Baz; +pub use sub_foo::Boz; +pub use sub_foo::Bort; + +pub trait Bar { + fn bar() -> Self; +} + +impl Bar for isize { + fn bar() -> isize { 84 } +} + +pub mod sub_foo { + pub trait Foo { + fn foo() -> Self; + } + + impl Foo for isize { + fn foo() -> isize { 42 } + } + + pub struct Boz { + unused_str: String + } + + impl Boz { + pub fn boz(i: isize) -> bool { + i > 0 + } + } + + pub enum Bort { + Bort1, + Bort2 + } + + impl Bort { + pub fn bort() -> String { + "bort()".to_string() + } + } +} diff --git a/tests/ui/cross-crate/auxiliary/static_init_aux.rs b/tests/ui/cross-crate/auxiliary/static_init_aux.rs new file mode 100644 index 000000000..3b664f436 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/static_init_aux.rs @@ -0,0 +1,10 @@ +pub static V: &u32 = &X; +pub static F: fn() = f; + +static X: u32 = 42; + +pub fn v() -> *const u32 { + V +} + +fn f() {} diff --git a/tests/ui/cross-crate/auxiliary/xcrate-trait-lifetime-param.rs b/tests/ui/cross-crate/auxiliary/xcrate-trait-lifetime-param.rs new file mode 100644 index 000000000..7c1175f7a --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/xcrate-trait-lifetime-param.rs @@ -0,0 +1,3 @@ +pub trait FromBuf<'a> { + fn from_buf(_: &'a [u8]) -> Self; +} diff --git a/tests/ui/cross-crate/auxiliary/xcrate_address_insignificant.rs b/tests/ui/cross-crate/auxiliary/xcrate_address_insignificant.rs new file mode 100644 index 000000000..e79e334b5 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/xcrate_address_insignificant.rs @@ -0,0 +1,8 @@ +pub fn foo() -> isize { + static a: isize = 3; + a +} + +pub fn bar() -> isize { + foo::() +} diff --git a/tests/ui/cross-crate/auxiliary/xcrate_associated_type_defaults.rs b/tests/ui/cross-crate/auxiliary/xcrate_associated_type_defaults.rs new file mode 100644 index 000000000..d8a55dd34 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/xcrate_associated_type_defaults.rs @@ -0,0 +1,12 @@ +#![feature(associated_type_defaults)] + +pub trait Foo { + type Out: Default + ToString = T; +} + +impl Foo for () { +} + +impl Foo for () { + type Out = bool; +} diff --git a/tests/ui/cross-crate/auxiliary/xcrate_generic_fn_nested_return.rs b/tests/ui/cross-crate/auxiliary/xcrate_generic_fn_nested_return.rs new file mode 100644 index 000000000..2ab23b4d7 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/xcrate_generic_fn_nested_return.rs @@ -0,0 +1,16 @@ +pub struct Request { + pub id: String, + pub arg: String, +} + +pub fn decode() -> Result { + (|| { + Ok(Request { + id: "hi".to_owned(), + arg: match Err(()) { + Ok(v) => v, + Err(e) => return Err(e) + }, + }) + })() +} diff --git a/tests/ui/cross-crate/auxiliary/xcrate_static_addresses.rs b/tests/ui/cross-crate/auxiliary/xcrate_static_addresses.rs new file mode 100644 index 000000000..e18d34799 --- /dev/null +++ b/tests/ui/cross-crate/auxiliary/xcrate_static_addresses.rs @@ -0,0 +1,17 @@ +pub static global: isize = 3; + +static global0: isize = 4; + +pub static global2: &'static isize = &global0; + +pub fn verify_same(a: &'static isize) { + let a = a as *const isize as usize; + let b = &global as *const isize as usize; + assert_eq!(a, b); +} + +pub fn verify_same2(a: &'static isize) { + let a = a as *const isize as usize; + let b = global2 as *const isize as usize; + assert_eq!(a, b); +} diff --git a/tests/ui/cross-crate/cci_borrow.rs b/tests/ui/cross-crate/cci_borrow.rs new file mode 100644 index 000000000..fee6b5d03 --- /dev/null +++ b/tests/ui/cross-crate/cci_borrow.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:cci_borrow_lib.rs + +extern crate cci_borrow_lib; +use cci_borrow_lib::foo; + +pub fn main() { + let p: Box<_> = Box::new(22); + let r = foo(&*p); + println!("r={}", r); + assert_eq!(r, 22); +} diff --git a/tests/ui/cross-crate/cci_capture_clause.rs b/tests/ui/cross-crate/cci_capture_clause.rs new file mode 100644 index 000000000..ea699b5f5 --- /dev/null +++ b/tests/ui/cross-crate/cci_capture_clause.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:cci_capture_clause.rs + +// This test makes sure we can do cross-crate inlining on functions +// that use capture clauses. + +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +extern crate cci_capture_clause; + +pub fn main() { + cci_capture_clause::foo(()).recv().unwrap(); +} diff --git a/tests/ui/cross-crate/cci_impl_exe.rs b/tests/ui/cross-crate/cci_impl_exe.rs new file mode 100644 index 000000000..b11fb23eb --- /dev/null +++ b/tests/ui/cross-crate/cci_impl_exe.rs @@ -0,0 +1,18 @@ +// run-pass +// aux-build:cci_impl_lib.rs + +extern crate cci_impl_lib; +use cci_impl_lib::uint_helpers; + +pub fn main() { + //let bt0 = sys::frame_address(); + //println!("%?", bt0); + + 3.to(10, |i| { + println!("{}", i); + + //let bt1 = sys::frame_address(); + //println!("%?", bt1); + //assert_eq!(bt0, bt1); + }) +} diff --git a/tests/ui/cross-crate/cci_iter_exe.rs b/tests/ui/cross-crate/cci_iter_exe.rs new file mode 100644 index 000000000..8b58d90fe --- /dev/null +++ b/tests/ui/cross-crate/cci_iter_exe.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:cci_iter_lib.rs + +extern crate cci_iter_lib; + +pub fn main() { + //let bt0 = sys::rusti::frame_address(1); + //println!("%?", bt0); + cci_iter_lib::iter(&[1, 2, 3], |i| { + println!("{}", *i); + //assert_eq!(bt0, sys::rusti::frame_address(2)); + }) +} diff --git a/tests/ui/cross-crate/cci_nested_exe.rs b/tests/ui/cross-crate/cci_nested_exe.rs new file mode 100644 index 000000000..1c001a2a3 --- /dev/null +++ b/tests/ui/cross-crate/cci_nested_exe.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:cci_nested_lib.rs + + +extern crate cci_nested_lib; +use cci_nested_lib::*; + +pub fn main() { + let lst = new_int_alist(); + alist_add(&lst, 22, "hi".to_string()); + alist_add(&lst, 44, "ho".to_string()); + assert_eq!(alist_get(&lst, 22), "hi".to_string()); + assert_eq!(alist_get(&lst, 44), "ho".to_string()); + + let lst = new_int_alist_2(); + alist_add(&lst, 22, "hi".to_string()); + alist_add(&lst, 44, "ho".to_string()); + assert_eq!(alist_get(&lst, 22), "hi".to_string()); + assert_eq!(alist_get(&lst, 44), "ho".to_string()); +} diff --git a/tests/ui/cross-crate/cci_no_inline_exe.rs b/tests/ui/cross-crate/cci_no_inline_exe.rs new file mode 100644 index 000000000..ffc701678 --- /dev/null +++ b/tests/ui/cross-crate/cci_no_inline_exe.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:cci_no_inline_lib.rs + +extern crate cci_no_inline_lib; +use cci_no_inline_lib::iter; + +pub fn main() { + // Check that a cross-crate call function not marked as inline + // does not, in fact, get inlined. Also, perhaps more + // importantly, checks that our scheme of using + // sys::frame_address() to determine if we are inlining is + // actually working. + //let bt0 = sys::frame_address(); + //println!("%?", bt0); + iter(vec![1, 2, 3], |i| { + println!("{}", i); + + //let bt1 = sys::frame_address(); + //println!("%?", bt1); + + //assert!(bt0 != bt1); + }) +} diff --git a/tests/ui/cross-crate/const-cross-crate-const.rs b/tests/ui/cross-crate/const-cross-crate-const.rs new file mode 100644 index 000000000..92020417f --- /dev/null +++ b/tests/ui/cross-crate/const-cross-crate-const.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:cci_const.rs +#![allow(non_upper_case_globals)] + +extern crate cci_const; +static foo: &'static str = cci_const::foopy; +static a: usize = cci_const::uint_val; +static b: usize = cci_const::uint_expr + 5; + +pub fn main() { + assert_eq!(a, 12); + let foo2 = a; + assert_eq!(foo2, cci_const::uint_val); + assert_eq!(b, cci_const::uint_expr + 5); + assert_eq!(foo, cci_const::foopy); +} diff --git a/tests/ui/cross-crate/const-cross-crate-extern.rs b/tests/ui/cross-crate/const-cross-crate-extern.rs new file mode 100644 index 000000000..3c61afd5b --- /dev/null +++ b/tests/ui/cross-crate/const-cross-crate-extern.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:cci_const.rs +#![allow(non_upper_case_globals)] + +extern crate cci_const; +use cci_const::bar; +static foo: extern "C" fn() = bar; + +pub fn main() { + assert!(foo == bar); +} diff --git a/tests/ui/cross-crate/cross-crate-const-pat.rs b/tests/ui/cross-crate/cross-crate-const-pat.rs new file mode 100644 index 000000000..e8fa8485a --- /dev/null +++ b/tests/ui/cross-crate/cross-crate-const-pat.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:cci_const.rs + +// pretty-expanded FIXME #23616 + +extern crate cci_const; + +pub fn main() { + let x = cci_const::uint_val; + match x { + cci_const::uint_val => {} + _ => {} + } +} diff --git a/tests/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs b/tests/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs new file mode 100644 index 000000000..82bb95f1e --- /dev/null +++ b/tests/ui/cross-crate/issue-64872/auxiliary/a_def_obj.rs @@ -0,0 +1,16 @@ +// compile-flags: -C debuginfo=2 + +// no-prefer-dynamic +#![crate_type = "rlib"] + +pub trait Object { fn method(&self) { } } + +impl Object for u32 { } +impl Object for () { } +impl Object for &T { } + +pub fn unused() { + let ref u = 0_u32; + let _d = &u as &dyn crate::Object; + _d.method() +} diff --git a/tests/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs b/tests/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs new file mode 100644 index 000000000..21c0274b9 --- /dev/null +++ b/tests/ui/cross-crate/issue-64872/auxiliary/b_reexport_obj.rs @@ -0,0 +1,7 @@ +// compile-flags: -C debuginfo=2 -C prefer-dynamic + +#![crate_type="dylib"] + +extern crate a_def_obj; + +pub use a_def_obj::Object; diff --git a/tests/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs b/tests/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs new file mode 100644 index 000000000..611238f56 --- /dev/null +++ b/tests/ui/cross-crate/issue-64872/auxiliary/c_another_vtable_for_obj.rs @@ -0,0 +1,12 @@ +// no-prefer-dynamic +// compile-flags: -C debuginfo=2 +#![crate_type="rlib"] + +extern crate b_reexport_obj; +use b_reexport_obj::Object; + +pub fn another_dyn_debug() { + let ref u = 1_u32; + let _d = &u as &dyn crate::Object; + _d.method() +} diff --git a/tests/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs b/tests/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs new file mode 100644 index 000000000..8d73f9b66 --- /dev/null +++ b/tests/ui/cross-crate/issue-64872/auxiliary/d_chain_of_rlibs_and_dylibs.rs @@ -0,0 +1,9 @@ +// compile-flags: -C debuginfo=2 -C prefer-dynamic + +#![crate_type="rlib"] + +extern crate c_another_vtable_for_obj; + +pub fn chain() { + c_another_vtable_for_obj::another_dyn_debug(); +} diff --git a/tests/ui/cross-crate/issue-64872/issue-64872.rs b/tests/ui/cross-crate/issue-64872/issue-64872.rs new file mode 100644 index 000000000..20fe2053c --- /dev/null +++ b/tests/ui/cross-crate/issue-64872/issue-64872.rs @@ -0,0 +1,17 @@ +// run-pass + +// note that these aux-build directives must be in this order: the +// later crates depend on the earlier ones. (The particular bug that +// is being exercised here used to exhibit itself during the build of +// `chain_of_rlibs_and_dylibs.dylib`) + +// aux-build:a_def_obj.rs +// aux-build:b_reexport_obj.rs +// aux-build:c_another_vtable_for_obj.rs +// aux-build:d_chain_of_rlibs_and_dylibs.rs + +extern crate d_chain_of_rlibs_and_dylibs; + +pub fn main() { + d_chain_of_rlibs_and_dylibs::chain(); +} diff --git a/tests/ui/cross-crate/moves-based-on-type-cross-crate.rs b/tests/ui/cross-crate/moves-based-on-type-cross-crate.rs new file mode 100644 index 000000000..3881e3352 --- /dev/null +++ b/tests/ui/cross-crate/moves-based-on-type-cross-crate.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:moves_based_on_type_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate moves_based_on_type_lib; +use moves_based_on_type_lib::f; + +pub fn main() { + f(); +} diff --git a/tests/ui/cross-crate/reexported-static-methods-cross-crate.rs b/tests/ui/cross-crate/reexported-static-methods-cross-crate.rs new file mode 100644 index 000000000..8c70a1ce4 --- /dev/null +++ b/tests/ui/cross-crate/reexported-static-methods-cross-crate.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:reexported_static_methods.rs + +extern crate reexported_static_methods; + +use reexported_static_methods::Foo; +use reexported_static_methods::Baz; +use reexported_static_methods::Boz; +use reexported_static_methods::Bort; + +pub fn main() { + assert_eq!(42_isize, Foo::foo()); + assert_eq!(84_isize, Baz::bar()); + assert!(Boz::boz(1)); + assert_eq!("bort()".to_string(), Bort::bort()); +} diff --git a/tests/ui/cross-crate/static-array-across-crate.rs b/tests/ui/cross-crate/static-array-across-crate.rs new file mode 100644 index 000000000..0b84e0e6a --- /dev/null +++ b/tests/ui/cross-crate/static-array-across-crate.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// aux-build:pub_static_array.rs + +extern crate pub_static_array as array; + +use array::ARRAY; + +static X: &'static u8 = &ARRAY[0]; +static Y: &'static u8 = &(&ARRAY)[0]; +static Z: u8 = (&ARRAY)[0]; + +pub fn main() {} diff --git a/tests/ui/cross-crate/static-init.rs b/tests/ui/cross-crate/static-init.rs new file mode 100644 index 000000000..2e893c5d9 --- /dev/null +++ b/tests/ui/cross-crate/static-init.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:static_init_aux.rs +extern crate static_init_aux as aux; + +static V: &u32 = aux::V; +static F: fn() = aux::F; + +fn v() -> *const u32 { + V +} + +fn main() { + assert_eq!(aux::v(), crate::v()); + F(); +} diff --git a/tests/ui/cross-crate/xcrate-address-insignificant.rs b/tests/ui/cross-crate/xcrate-address-insignificant.rs new file mode 100644 index 000000000..33c706506 --- /dev/null +++ b/tests/ui/cross-crate/xcrate-address-insignificant.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:xcrate_address_insignificant.rs + + +extern crate xcrate_address_insignificant as foo; + +pub fn main() { + assert_eq!(foo::foo::(), foo::bar()); +} diff --git a/tests/ui/cross-crate/xcrate-associated-type-defaults.rs b/tests/ui/cross-crate/xcrate-associated-type-defaults.rs new file mode 100644 index 000000000..0f3e077d1 --- /dev/null +++ b/tests/ui/cross-crate/xcrate-associated-type-defaults.rs @@ -0,0 +1,29 @@ +// run-pass +// aux-build:xcrate_associated_type_defaults.rs + +extern crate xcrate_associated_type_defaults; +use xcrate_associated_type_defaults::Foo; + +struct LocalDefault; +impl Foo for LocalDefault {} + +struct LocalOverride; +impl Foo for LocalOverride { + type Out = bool; +} + +fn main() { + assert_eq!( + <() as Foo>::Out::default().to_string(), + "0"); + assert_eq!( + <() as Foo>::Out::default().to_string(), + "false"); + + assert_eq!( + >::Out::default().to_string(), + "0"); + assert_eq!( + >::Out::default().to_string(), + "false"); +} diff --git a/tests/ui/cross-crate/xcrate-static-addresses.rs b/tests/ui/cross-crate/xcrate-static-addresses.rs new file mode 100644 index 000000000..3c3397656 --- /dev/null +++ b/tests/ui/cross-crate/xcrate-static-addresses.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:xcrate_static_addresses.rs + +// pretty-expanded FIXME #23616 + +extern crate xcrate_static_addresses; + +use xcrate_static_addresses as other; + +pub fn main() { + other::verify_same(&other::global); + other::verify_same2(other::global2); +} diff --git a/tests/ui/cross-crate/xcrate-trait-lifetime-param.rs b/tests/ui/cross-crate/xcrate-trait-lifetime-param.rs new file mode 100644 index 000000000..1fd7eb878 --- /dev/null +++ b/tests/ui/cross-crate/xcrate-trait-lifetime-param.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +// aux-build:xcrate-trait-lifetime-param.rs + +// pretty-expanded FIXME #23616 + +extern crate xcrate_trait_lifetime_param as other; + +struct Reader<'a> { + b : &'a [u8] +} + +impl <'a> other::FromBuf<'a> for Reader<'a> { + fn from_buf(b : &'a [u8]) -> Reader<'a> { + Reader { b : b } + } +} + +pub fn main () {} diff --git a/tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs b/tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs new file mode 100644 index 000000000..4593fec51 --- /dev/null +++ b/tests/ui/cross-crate/xcrate_generic_fn_nested_return.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:xcrate_generic_fn_nested_return.rs + +extern crate xcrate_generic_fn_nested_return as test; + +pub fn main() { + assert!(test::decode::<()>().is_err()); +} diff --git a/tests/ui/cross/cross-borrow-trait.rs b/tests/ui/cross/cross-borrow-trait.rs new file mode 100644 index 000000000..180a75e3d --- /dev/null +++ b/tests/ui/cross/cross-borrow-trait.rs @@ -0,0 +1,13 @@ +// Test that cross-borrowing (implicitly converting from `Box` to `&T`) is +// forbidden when `T` is a trait. + +struct Foo; +trait Trait { fn foo(&self) {} } +impl Trait for Foo {} + +pub fn main() { + let x: Box = Box::new(Foo); + let _y: &dyn Trait = x; //~ ERROR E0308 + //~| expected reference `&dyn Trait` + //~| found struct `Box` +} diff --git a/tests/ui/cross/cross-borrow-trait.stderr b/tests/ui/cross/cross-borrow-trait.stderr new file mode 100644 index 000000000..81f309eae --- /dev/null +++ b/tests/ui/cross/cross-borrow-trait.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/cross-borrow-trait.rs:10:26 + | +LL | let _y: &dyn Trait = x; + | ---------- ^ expected `&dyn Trait`, found struct `Box` + | | + | expected due to this + | + = note: expected reference `&dyn Trait` + found struct `Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs b/tests/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs new file mode 100644 index 000000000..fbda3dbe9 --- /dev/null +++ b/tests/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs @@ -0,0 +1,13 @@ +#![crate_type = "dylib"] + +pub fn print(_args: std::fmt::Arguments) {} + +#[macro_export] +macro_rules! myprint { + ($($arg:tt)*) => ($crate::print(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! myprintln { + ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); +} diff --git a/tests/ui/cross/cross-crate-macro-backtrace/main.rs b/tests/ui/cross/cross-crate-macro-backtrace/main.rs new file mode 100644 index 000000000..f7d4330ab --- /dev/null +++ b/tests/ui/cross/cross-crate-macro-backtrace/main.rs @@ -0,0 +1,8 @@ +// aux-build:extern_macro_crate.rs +#[macro_use(myprintln, myprint)] +extern crate extern_macro_crate; + +fn main() { + myprintln!("{}"); + //~^ ERROR in format string +} diff --git a/tests/ui/cross/cross-crate-macro-backtrace/main.stderr b/tests/ui/cross/cross-crate-macro-backtrace/main.stderr new file mode 100644 index 000000000..5bd4ea97e --- /dev/null +++ b/tests/ui/cross/cross-crate-macro-backtrace/main.stderr @@ -0,0 +1,10 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/main.rs:6:5 + | +LL | myprintln!("{}"); + | ^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `concat` which comes from the expansion of the macro `myprintln` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/cross/cross-file-errors/main.rs b/tests/ui/cross/cross-file-errors/main.rs new file mode 100644 index 000000000..4219f892d --- /dev/null +++ b/tests/ui/cross/cross-file-errors/main.rs @@ -0,0 +1,7 @@ +#[macro_use] +mod underscore; + +fn main() { + underscore!(); + //~^ ERROR `_` can only be used on the left-hand side of an assignment +} diff --git a/tests/ui/cross/cross-file-errors/main.stderr b/tests/ui/cross/cross-file-errors/main.stderr new file mode 100644 index 000000000..293a300ed --- /dev/null +++ b/tests/ui/cross/cross-file-errors/main.stderr @@ -0,0 +1,15 @@ +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/underscore.rs:8:9 + | +LL | _ + | ^ `_` not allowed here + | + ::: $DIR/main.rs:5:5 + | +LL | underscore!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `underscore` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/cross/cross-file-errors/underscore.rs b/tests/ui/cross/cross-file-errors/underscore.rs new file mode 100644 index 000000000..76e72a93f --- /dev/null +++ b/tests/ui/cross/cross-file-errors/underscore.rs @@ -0,0 +1,10 @@ +// We want this file only so we can test cross-file error +// messages, but we don't want it in an external crate. +// ignore-test +#![crate_type = "lib"] + +macro_rules! underscore { + () => ( + _ + ) +} diff --git a/tests/ui/cross/cross-fn-cache-hole.rs b/tests/ui/cross/cross-fn-cache-hole.rs new file mode 100644 index 000000000..c38a5001a --- /dev/null +++ b/tests/ui/cross/cross-fn-cache-hole.rs @@ -0,0 +1,31 @@ +// Check that when there are vacuous predicates in the environment +// (which make a fn uncallable) we don't erroneously cache those and +// then consider them satisfied elsewhere. The current technique for +// doing this is to not use global caches when there is a chance that +// the environment contains such a predicate. +// We still error for `i32: Bar` pending #48214 + +trait Foo: Bar { +} + +trait Bar { } + +// We don't always check where clauses for sanity, but in this case +// wfcheck does report an error here: +fn vacuous() + where i32: Foo //~ ERROR the trait bound `i32: Bar` is not satisfied +{ + // ... the original intention was to check that we don't use that + // vacuous where clause (which could never be satisfied) to accept + // the following line and then mess up calls elsewhere. + require::(); +} + +fn require() + where A: Bar +{ +} + +fn main() { + require::(); +} diff --git a/tests/ui/cross/cross-fn-cache-hole.stderr b/tests/ui/cross/cross-fn-cache-hole.stderr new file mode 100644 index 000000000..7e15562b0 --- /dev/null +++ b/tests/ui/cross/cross-fn-cache-hole.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `i32: Bar` is not satisfied + --> $DIR/cross-fn-cache-hole.rs:16:11 + | +LL | where i32: Foo + | ^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `i32` + | + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/custom-attribute-multisegment.rs b/tests/ui/custom-attribute-multisegment.rs new file mode 100644 index 000000000..243492139 --- /dev/null +++ b/tests/ui/custom-attribute-multisegment.rs @@ -0,0 +1,6 @@ +// Unresolved multi-segment attributes are not treated as custom. + +mod existent {} + +#[existent::nonexistent] //~ ERROR failed to resolve: could not find `nonexistent` in `existent` +fn main() {} diff --git a/tests/ui/custom-attribute-multisegment.stderr b/tests/ui/custom-attribute-multisegment.stderr new file mode 100644 index 000000000..57eca211e --- /dev/null +++ b/tests/ui/custom-attribute-multisegment.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: could not find `nonexistent` in `existent` + --> $DIR/custom-attribute-multisegment.rs:5:13 + | +LL | #[existent::nonexistent] + | ^^^^^^^^^^^ could not find `nonexistent` in `existent` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/custom-test-frameworks-simple.rs b/tests/ui/custom-test-frameworks-simple.rs new file mode 100644 index 000000000..aee0040ef --- /dev/null +++ b/tests/ui/custom-test-frameworks-simple.rs @@ -0,0 +1,22 @@ +// compile-flags: --test +// run-pass + +#![feature(custom_test_frameworks)] +#![test_runner(crate::foo_runner)] + +#[cfg(test)] +fn foo_runner(ts: &[&dyn Fn(usize)->()]) { + for (i, t) in ts.iter().enumerate() { + t(i); + } +} + +#[test_case] +fn test1(i: usize) { + println!("Hi #{}", i); +} + +#[test_case] +fn test2(i: usize) { + println!("Hey #{}", i); +} diff --git a/tests/ui/custom_attribute.rs b/tests/ui/custom_attribute.rs new file mode 100644 index 000000000..495718422 --- /dev/null +++ b/tests/ui/custom_attribute.rs @@ -0,0 +1,9 @@ +#![feature(stmt_expr_attributes)] + +#[foo] //~ ERROR cannot find attribute `foo` in this scope +fn main() { + #[foo] //~ ERROR cannot find attribute `foo` in this scope + let x = (); + #[foo] //~ ERROR cannot find attribute `foo` in this scope + x +} diff --git a/tests/ui/custom_attribute.stderr b/tests/ui/custom_attribute.stderr new file mode 100644 index 000000000..4023892d2 --- /dev/null +++ b/tests/ui/custom_attribute.stderr @@ -0,0 +1,20 @@ +error: cannot find attribute `foo` in this scope + --> $DIR/custom_attribute.rs:3:3 + | +LL | #[foo] + | ^^^ + +error: cannot find attribute `foo` in this scope + --> $DIR/custom_attribute.rs:5:7 + | +LL | #[foo] + | ^^^ + +error: cannot find attribute `foo` in this scope + --> $DIR/custom_attribute.rs:7:7 + | +LL | #[foo] + | ^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs b/tests/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs new file mode 100644 index 000000000..a56e0b1f5 --- /dev/null +++ b/tests/ui/custom_test_frameworks/auxiliary/dynamic_runner.rs @@ -0,0 +1,35 @@ +use std::process::exit; + +pub trait Testable { + // Name of the test + fn name(&self) -> String; + + // Tests pass by default + fn run(&self) -> bool { + true + } + + // A test can generate subtests + fn subtests(&self) -> Vec> { + vec![] + } +} + +fn run_test(t: &dyn Testable) -> bool { + let success = t.subtests().into_iter().all(|sub_t| run_test(&*sub_t)) && t.run(); + println!("{}...{}", t.name(), if success { "SUCCESS" } else { "FAIL" }); + success +} + +pub fn runner(tests: &[&dyn Testable]) { + let mut failed = false; + for t in tests { + if !run_test(*t) { + failed = true; + } + } + + if failed { + exit(1); + } +} diff --git a/tests/ui/custom_test_frameworks/auxiliary/example_runner.rs b/tests/ui/custom_test_frameworks/auxiliary/example_runner.rs new file mode 100644 index 000000000..dd68c0685 --- /dev/null +++ b/tests/ui/custom_test_frameworks/auxiliary/example_runner.rs @@ -0,0 +1,10 @@ +pub trait Testable { + fn name(&self) -> String; + fn run(&self) -> Option; // None will be success, Some is the error message +} + +pub fn runner(tests: &[&dyn Testable]) { + for t in tests { + print!("{}........{}", t.name(), t.run().unwrap_or_else(|| "SUCCESS".to_string())); + } +} diff --git a/tests/ui/custom_test_frameworks/dynamic.rs b/tests/ui/custom_test_frameworks/dynamic.rs new file mode 100644 index 000000000..6766ec542 --- /dev/null +++ b/tests/ui/custom_test_frameworks/dynamic.rs @@ -0,0 +1,35 @@ +// run-pass +// aux-build:dynamic_runner.rs +// compile-flags:--test +#![feature(custom_test_frameworks)] +#![test_runner(dynamic_runner::runner)] + +extern crate dynamic_runner; + +pub struct AllFoo(&'static str); +struct IsFoo(String); + +impl dynamic_runner::Testable for AllFoo { + fn name(&self) -> String { + String::from(self.0) + } + + fn subtests(&self) -> Vec> { + self.0.split(" ").map(|word| + Box::new(IsFoo(word.into())) as Box + ).collect() + } +} + +impl dynamic_runner::Testable for IsFoo { + fn name(&self) -> String { + self.0.clone() + } + + fn run(&self) -> bool { + self.0 == "foo" + } +} + +#[test_case] +const TEST_2: AllFoo = AllFoo("foo foo"); diff --git a/tests/ui/custom_test_frameworks/full.rs b/tests/ui/custom_test_frameworks/full.rs new file mode 100644 index 000000000..8c8188268 --- /dev/null +++ b/tests/ui/custom_test_frameworks/full.rs @@ -0,0 +1,28 @@ +// run-pass +// aux-build:example_runner.rs +// compile-flags:--test + +#![feature(custom_test_frameworks)] +#![test_runner(example_runner::runner)] +extern crate example_runner; + +pub struct IsFoo(&'static str); + +impl example_runner::Testable for IsFoo { + fn name(&self) -> String { + self.0.to_string() + } + + fn run(&self) -> Option { + if self.0 != "foo" { + return Some(format!("{} != foo", self.0)); + } + None + } +} + +#[test_case] +const TEST_1: IsFoo = IsFoo("hello"); + +#[test_case] +const TEST_2: IsFoo = IsFoo("foo"); diff --git a/tests/ui/custom_test_frameworks/mismatch.rs b/tests/ui/custom_test_frameworks/mismatch.rs new file mode 100644 index 000000000..ac850552b --- /dev/null +++ b/tests/ui/custom_test_frameworks/mismatch.rs @@ -0,0 +1,10 @@ +// aux-build:example_runner.rs +// compile-flags:--test +#![feature(custom_test_frameworks)] +#![test_runner(example_runner::runner)] + +extern crate example_runner; + +#[test] +fn wrong_kind(){} +//~^ ERROR trait bound `TestDescAndFn: Testable` is not satisfied diff --git a/tests/ui/custom_test_frameworks/mismatch.stderr b/tests/ui/custom_test_frameworks/mismatch.stderr new file mode 100644 index 000000000..61061ae52 --- /dev/null +++ b/tests/ui/custom_test_frameworks/mismatch.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `TestDescAndFn: Testable` is not satisfied + --> $DIR/mismatch.rs:9:1 + | +LL | #[test] + | ------- in this procedural macro expansion +LL | fn wrong_kind(){} + | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn` + | + = note: required for the cast from `TestDescAndFn` to the object type `dyn Testable` + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/cycle-trait/cycle-trait-default-type-trait.rs b/tests/ui/cycle-trait/cycle-trait-default-type-trait.rs new file mode 100644 index 000000000..6175b7df1 --- /dev/null +++ b/tests/ui/cycle-trait/cycle-trait-default-type-trait.rs @@ -0,0 +1,8 @@ +// Test a cycle where a type parameter on a trait has a default that +// again references the trait. + +trait Foo> { + //~^ ERROR cycle detected +} + +fn main() { } diff --git a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr new file mode 100644 index 000000000..9d715f494 --- /dev/null +++ b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr @@ -0,0 +1,20 @@ +error[E0391]: cycle detected when computing type of `Foo::X` + --> $DIR/cycle-trait-default-type-trait.rs:4:23 + | +LL | trait Foo> { + | ^^^ + | + = note: ...which immediately requires computing type of `Foo::X` again +note: cycle used when collecting item types in top-level module + --> $DIR/cycle-trait-default-type-trait.rs:4:1 + | +LL | / trait Foo> { +LL | | +LL | | } +LL | | +LL | | fn main() { } + | |_____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.rs b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.rs new file mode 100644 index 000000000..e6ab2c790 --- /dev/null +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.rs @@ -0,0 +1,7 @@ +// Test a supertrait cycle where a trait extends itself. + +trait Chromosome: Chromosome { + //~^ ERROR cycle detected +} + +fn main() { } diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr new file mode 100644 index 000000000..f6ffcc4b5 --- /dev/null +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr @@ -0,0 +1,23 @@ +error[E0391]: cycle detected when computing the super predicates of `Chromosome` + --> $DIR/cycle-trait-supertrait-direct.rs:3:1 + | +LL | trait Chromosome: Chromosome { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires computing the super traits of `Chromosome`... + --> $DIR/cycle-trait-supertrait-direct.rs:3:19 + | +LL | trait Chromosome: Chromosome { + | ^^^^^^^^^^ + = note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cycle-trait-supertrait-direct.rs:3:1 + | +LL | / trait Chromosome: Chromosome { +LL | | +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.rs b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.rs new file mode 100644 index 000000000..9a72b65da --- /dev/null +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.rs @@ -0,0 +1,13 @@ +// Test a supertrait cycle where the first trait we find (`A`) is not +// a direct participant in the cycle. + +trait A: B { +} + +trait B: C { + //~^ ERROR cycle detected +} + +trait C: B { } + +fn main() { } diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr new file mode 100644 index 000000000..0a2284e0e --- /dev/null +++ b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr @@ -0,0 +1,31 @@ +error[E0391]: cycle detected when computing the super predicates of `B` + --> $DIR/cycle-trait-supertrait-indirect.rs:7:1 + | +LL | trait B: C { + | ^^^^^^^^^^ + | +note: ...which requires computing the super traits of `B`... + --> $DIR/cycle-trait-supertrait-indirect.rs:7:10 + | +LL | trait B: C { + | ^ +note: ...which requires computing the super predicates of `C`... + --> $DIR/cycle-trait-supertrait-indirect.rs:11:1 + | +LL | trait C: B { } + | ^^^^^^^^^^ +note: ...which requires computing the super traits of `C`... + --> $DIR/cycle-trait-supertrait-indirect.rs:11:10 + | +LL | trait C: B { } + | ^ + = note: ...which again requires computing the super predicates of `B`, completing the cycle +note: cycle used when computing the super traits of `A` + --> $DIR/cycle-trait-supertrait-indirect.rs:4:10 + | +LL | trait A: B { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs b/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs new file mode 100644 index 000000000..761539227 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs @@ -0,0 +1,23 @@ +// build-pass +// compile-flags: -Cdebuginfo=2 +// fixes issue #94725 + +#![feature(allocator_api)] + +use std::alloc::{AllocError, Allocator, Layout}; +use std::ptr::NonNull; + +struct ZST; + +unsafe impl Allocator for &ZST { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + todo!() + } + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + todo!() + } +} + +fn main() { + let _ = Box::::new_in(43, &ZST); +} diff --git a/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs b/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs new file mode 100644 index 000000000..ff764015d --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs @@ -0,0 +1,8 @@ +// build-pass +// only-linux +// +// compile-flags: -g --emit=llvm-ir -Csplit-debuginfo=unpacked +// +// Make sure that we don't explode with an error if we don't actually end up emitting any `dwo`s, +// as would be the case if we don't actually codegen anything. +#![crate_type="rlib"] diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs new file mode 100644 index 000000000..78bda2848 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs @@ -0,0 +1,16 @@ +// Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that +// causes a layout error. See https://github.com/rust-lang/rust/issues/94961. + +// compile-flags:-C debuginfo=2 +// build-fail +// error-pattern: too big for the current architecture +// normalize-stderr-64bit "18446744073709551615" -> "SIZE" +// normalize-stderr-32bit "4294967295" -> "SIZE" + +#![crate_type = "rlib"] + +pub struct Foo([T; usize::MAX]); + +pub fn foo() -> usize { + std::mem::size_of::>() +} diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr new file mode 100644 index 000000000..d5991bcf5 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr @@ -0,0 +1,4 @@ +error: values of the type `[u8; usize::MAX]` are too big for the current architecture + +error: aborting due to previous error + diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs new file mode 100644 index 000000000..fdc088dc0 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs @@ -0,0 +1,20 @@ +// Make sure the compiler does not ICE when trying to generate the debuginfo name of a type that +// causes a layout error. +// This version of the test already ICE'd before the commit that introduce the ICE described in +// https://github.com/rust-lang/rust/issues/94961. + +// compile-flags:-C debuginfo=2 +// build-fail +// error-pattern: too big for the current architecture +// normalize-stderr-64bit "18446744073709551615" -> "SIZE" +// normalize-stderr-32bit "4294967295" -> "SIZE" + +#![crate_type = "rlib"] + +pub enum Foo { + Bar([T; usize::MAX]), +} + +pub fn foo() -> usize { + std::mem::size_of::>() +} diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr new file mode 100644 index 000000000..d5991bcf5 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr @@ -0,0 +1,4 @@ +error: values of the type `[u8; usize::MAX]` are too big for the current architecture + +error: aborting due to previous error + diff --git a/tests/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs b/tests/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs new file mode 100644 index 000000000..b3f22ecf5 --- /dev/null +++ b/tests/ui/debuginfo/debuginfo_with_uninhabitable_field_and_unsized.rs @@ -0,0 +1,29 @@ +// build-pass +// compile-flags: -Cdebuginfo=2 +// fixes issue #94149 + +#![allow(dead_code)] + +pub fn main() { + let _ = Foo::::new(); +} + +pub struct Foo { + base: FooBase, + value: T, +} + +impl Foo { + pub fn new() -> Box> { + todo!() + } +} + +pub trait FooTrait {} + +pub struct FooBase { + cls: Bar, +} + +// Bar *must* be a fieldless enum +pub enum Bar {} diff --git a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs new file mode 100644 index 000000000..6c6eb5d4e --- /dev/null +++ b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs @@ -0,0 +1,20 @@ +// run-pass +// compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3 + +fn main() { + TranslatorI.visit_pre(); +} + +impl TranslatorI { + fn visit_pre(self) { + Some(()) + .map(|_| self.flags()) + .unwrap_or_else(|| self.flags()); + } +} + +struct TranslatorI; + +impl TranslatorI { + fn flags(&self) {} +} diff --git a/tests/ui/debuginfo/late-bound-projection.rs b/tests/ui/debuginfo/late-bound-projection.rs new file mode 100644 index 000000000..601807845 --- /dev/null +++ b/tests/ui/debuginfo/late-bound-projection.rs @@ -0,0 +1,7 @@ +// build-pass +// compile-flags: -Cdebuginfo=2 --crate-type=rlib +// Fixes issue #94998 + +pub trait Trait {} + +pub fn run(_: &dyn FnOnce(&()) -> Box) {} diff --git a/tests/ui/deduplicate-diagnostics.deduplicate.stderr b/tests/ui/deduplicate-diagnostics.deduplicate.stderr new file mode 100644 index 000000000..5df2c687b --- /dev/null +++ b/tests/ui/deduplicate-diagnostics.deduplicate.stderr @@ -0,0 +1,15 @@ +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:8:8 + | +LL | #[deny("literal")] + | ^^^^^^^^^ bad attribute argument + +error: cannot find derive macro `Unresolved` in this scope + --> $DIR/deduplicate-diagnostics.rs:4:10 + | +LL | #[derive(Unresolved)] + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/deduplicate-diagnostics.duplicate.stderr b/tests/ui/deduplicate-diagnostics.duplicate.stderr new file mode 100644 index 000000000..cd4700c7a --- /dev/null +++ b/tests/ui/deduplicate-diagnostics.duplicate.stderr @@ -0,0 +1,27 @@ +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:8:8 + | +LL | #[deny("literal")] + | ^^^^^^^^^ bad attribute argument + +error: cannot find derive macro `Unresolved` in this scope + --> $DIR/deduplicate-diagnostics.rs:4:10 + | +LL | #[derive(Unresolved)] + | ^^^^^^^^^^ + +error: cannot find derive macro `Unresolved` in this scope + --> $DIR/deduplicate-diagnostics.rs:4:10 + | +LL | #[derive(Unresolved)] + | ^^^^^^^^^^ + +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:8:8 + | +LL | #[deny("literal")] + | ^^^^^^^^^ bad attribute argument + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/deduplicate-diagnostics.rs b/tests/ui/deduplicate-diagnostics.rs new file mode 100644 index 000000000..7d1c4f5f8 --- /dev/null +++ b/tests/ui/deduplicate-diagnostics.rs @@ -0,0 +1,10 @@ +// revisions: duplicate deduplicate +//[deduplicate] compile-flags: -Z deduplicate-diagnostics=yes + +#[derive(Unresolved)] //~ ERROR cannot find derive macro `Unresolved` in this scope + //[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope +struct S; + +#[deny("literal")] //~ ERROR malformed lint attribute input + //[duplicate]~| ERROR malformed lint attribute input +fn main() {} diff --git a/tests/ui/deep.rs b/tests/ui/deep.rs new file mode 100644 index 000000000..2bb109c0e --- /dev/null +++ b/tests/ui/deep.rs @@ -0,0 +1,8 @@ +// run-pass +// ignore-emscripten apparently blows the stack + +fn f(x: isize) -> isize { + if x == 1 { return 1; } else { let y: isize = 1 + f(x - 1); return y; } +} + +pub fn main() { assert_eq!(f(5000), 5000); } diff --git a/tests/ui/default-method-parsing.rs b/tests/ui/default-method-parsing.rs new file mode 100644 index 000000000..9ffb8d94a --- /dev/null +++ b/tests/ui/default-method-parsing.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Foo { + fn m(&self, _:isize) { } +} + +pub fn main() { } diff --git a/tests/ui/default-method-simple.rs b/tests/ui/default-method-simple.rs new file mode 100644 index 000000000..6f7ae6a3e --- /dev/null +++ b/tests/ui/default-method-simple.rs @@ -0,0 +1,26 @@ +// run-pass + +#![allow(dead_code)] + +trait Foo { + fn f(&self) { + println!("Hello!"); + self.g(); + } + fn g(&self); +} + +struct A { + x: isize +} + +impl Foo for A { + fn g(&self) { + println!("Goodbye!"); + } +} + +pub fn main() { + let a = A { x: 1 }; + a.f(); +} diff --git a/tests/ui/defaults-well-formedness.rs b/tests/ui/defaults-well-formedness.rs new file mode 100644 index 000000000..327589061 --- /dev/null +++ b/tests/ui/defaults-well-formedness.rs @@ -0,0 +1,27 @@ +// run-pass + +#![allow(dead_code)] +trait Trait {} +struct Foo(U, V) where U: Trait; + +trait Marker {} +struct TwoParams(T, U); +impl Marker for TwoParams {} + +// Clauses with more than 1 param are not checked. +struct IndividuallyBogus(TwoParams) where TwoParams: Marker; +struct BogusTogether(T, U) where TwoParams: Marker; +// Clauses with non-defaulted params are not checked. +struct NonDefaultedInClause(TwoParams) where TwoParams: Marker; +struct DefaultedLhs(U, V) where V: Trait; +// Dependent defaults are not checked. +struct Dependent(T, U) where U: Copy; +trait SelfBound {} +// Not even for well-formedness. +struct WellFormedProjection::Item>(A, T); + +// Issue #49344, predicates with lifetimes should not be checked. +trait Scope<'a> {} +struct Request<'a, S: Scope<'a> = i32>(S, &'a ()); + +fn main() {} diff --git a/tests/ui/definition-reachable/auxiliary/field-method-macro.rs b/tests/ui/definition-reachable/auxiliary/field-method-macro.rs new file mode 100644 index 000000000..30ba70bdf --- /dev/null +++ b/tests/ui/definition-reachable/auxiliary/field-method-macro.rs @@ -0,0 +1,23 @@ +#![feature(decl_macro)] + +mod n { + pub struct B(pub(crate) p::C); + impl B { + pub fn new() -> Self { + B(p::C) + } + } + mod p { + pub struct C; + + impl C { + pub fn foo(&self) -> i32 { + 33 + } + } + } +} + +pub macro m() { + n::B::new().0.foo() +} diff --git a/tests/ui/definition-reachable/auxiliary/nested-fn-macro.rs b/tests/ui/definition-reachable/auxiliary/nested-fn-macro.rs new file mode 100644 index 000000000..a39e8c986 --- /dev/null +++ b/tests/ui/definition-reachable/auxiliary/nested-fn-macro.rs @@ -0,0 +1,11 @@ +#![feature(decl_macro)] + +mod n { + pub(crate) mod p { + pub fn f() -> i32 { 12 } + } +} + +pub macro m() { + n::p::f() +} diff --git a/tests/ui/definition-reachable/auxiliary/private-use-macro.rs b/tests/ui/definition-reachable/auxiliary/private-use-macro.rs new file mode 100644 index 000000000..4f283d9c1 --- /dev/null +++ b/tests/ui/definition-reachable/auxiliary/private-use-macro.rs @@ -0,0 +1,11 @@ +#![feature(decl_macro)] + +mod n { + pub static S: i32 = 57; +} + +use n::S; + +pub macro m() { + S +} diff --git a/tests/ui/definition-reachable/field-method.rs b/tests/ui/definition-reachable/field-method.rs new file mode 100644 index 000000000..60e895a2f --- /dev/null +++ b/tests/ui/definition-reachable/field-method.rs @@ -0,0 +1,11 @@ +// Check that functions accessible through a field visible to a macro are +// considered reachable + +// aux-build:nested-fn-macro.rs +// run-pass + +extern crate nested_fn_macro; + +fn main() { + assert_eq!(nested_fn_macro::m!(), 12); +} diff --git a/tests/ui/definition-reachable/nested-fn.rs b/tests/ui/definition-reachable/nested-fn.rs new file mode 100644 index 000000000..b665b049f --- /dev/null +++ b/tests/ui/definition-reachable/nested-fn.rs @@ -0,0 +1,11 @@ +// Check that functions visible to macros through paths with >2 segments are +// considered reachable + +// aux-build:field-method-macro.rs +// run-pass + +extern crate field_method_macro; + +fn main() { + assert_eq!(field_method_macro::m!(), 33); +} diff --git a/tests/ui/definition-reachable/private-non-types.rs b/tests/ui/definition-reachable/private-non-types.rs new file mode 100644 index 000000000..a601dabcb --- /dev/null +++ b/tests/ui/definition-reachable/private-non-types.rs @@ -0,0 +1,21 @@ +// Check that we don't require stability annotations for private modules, +// imports and fields that are accessible to opaque macros. + +// check-pass + +#![feature(decl_macro, staged_api)] +#![stable(feature = "test", since = "1.0.0")] + +extern crate std as local_std; +use local_std::marker::Copy as LocalCopy; +mod private_mod { + #[stable(feature = "test", since = "1.0.0")] + pub struct A { + pub(crate) f: i32, + } +} + +#[stable(feature = "test", since = "1.0.0")] +pub macro m() {} + +fn main() {} diff --git a/tests/ui/definition-reachable/private-types.rs b/tests/ui/definition-reachable/private-types.rs new file mode 100644 index 000000000..02c1224f4 --- /dev/null +++ b/tests/ui/definition-reachable/private-types.rs @@ -0,0 +1,19 @@ +// Check that type privacy is taken into account when considering reachability + +// check-pass + +#![feature(decl_macro, staged_api)] +#![stable(feature = "test", since = "1.0.0")] + +// Type privacy should prevent use of these in other crates, so we shouldn't +// need a stability annotation. +fn private_function() {} +struct PrivateStruct { f: () } +enum PrivateEnum { V } +union PrivateUnion { g: () } +trait PrivateTrait {} + +#[stable(feature = "test", since = "1.0.0")] +pub macro m() {} + +fn main() {} diff --git a/tests/ui/definition-reachable/private-use.rs b/tests/ui/definition-reachable/private-use.rs new file mode 100644 index 000000000..02cff0475 --- /dev/null +++ b/tests/ui/definition-reachable/private-use.rs @@ -0,0 +1,10 @@ +// Check that private use statements can be used by + +// run-pass +// aux-build:private-use-macro.rs + +extern crate private_use_macro; + +fn main() { + assert_eq!(private_use_macro::m!(), 57); +} diff --git a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs new file mode 100644 index 000000000..978c19948 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs @@ -0,0 +1,38 @@ +// Test that when a trait impl changes, fns whose body uses that trait +// must also be recompiled. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(warnings)] + +fn main() { } + +pub trait Foo: Sized { + type T; + fn method(self) { } +} + +mod x { + use Foo; + + #[rustc_if_this_changed] + impl Foo for char { type T = char; } + + impl Foo for u32 { type T = u32; } +} + +mod y { + use Foo; + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn use_char_assoc() { + // Careful here: in the representation, ::T gets + // normalized away, so at a certain point we had no edge to + // codegen. (But now codegen just depends on typeck.) + let x: ::T = 'a'; + } + + pub fn take_foo(t: T) { } +} diff --git a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr new file mode 100644 index 000000000..cdc268cff --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr @@ -0,0 +1,8 @@ +error: OK + --> $DIR/dep-graph-assoc-type-codegen.rs:29:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/dep-graph/dep-graph-caller-callee.rs b/tests/ui/dep-graph/dep-graph-caller-callee.rs new file mode 100644 index 000000000..4a3a8bb6b --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-caller-callee.rs @@ -0,0 +1,36 @@ +// Test that immediate callers have to change when callee changes, but +// not callers' callers. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +fn main() { } + +mod x { + #[rustc_if_this_changed] + pub fn x() { } +} + +mod y { + use x; + + // These dependencies SHOULD exist: + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn y() { + x::x(); + } +} + +mod z { + use y; + + // These are expected to yield errors, because changes to `x` + // affect the BODY of `y`, but not its signature. + #[rustc_then_this_would_need(typeck)] //~ ERROR no path + pub fn z() { + y::y(); + } +} diff --git a/tests/ui/dep-graph/dep-graph-caller-callee.stderr b/tests/ui/dep-graph/dep-graph-caller-callee.stderr new file mode 100644 index 000000000..4d06dc7f3 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-caller-callee.stderr @@ -0,0 +1,14 @@ +error: OK + --> $DIR/dep-graph-caller-callee.rs:21:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `x` to `typeck` + --> $DIR/dep-graph-caller-callee.rs:32:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-check-attr.rs b/tests/ui/dep-graph/dep-graph-check-attr.rs new file mode 100644 index 000000000..a45bf24f8 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-check-attr.rs @@ -0,0 +1,20 @@ +// Test that using rustc_clean/dirty/if_this_changed/then_this_would_need +// are forbidden when `-Z query-dep-graph` is not enabled. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +fn main() {} + +#[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +struct Foo { + f: T, +} + +#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +type TypeAlias = Foo; + +#[rustc_then_this_would_need(variances_of)] //~ ERROR attribute requires -Z query-dep-graph +trait Use {} diff --git a/tests/ui/dep-graph/dep-graph-check-attr.stderr b/tests/ui/dep-graph/dep-graph-check-attr.stderr new file mode 100644 index 000000000..46f4e4358 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-check-attr.stderr @@ -0,0 +1,26 @@ +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:8:1 + | +LL | #[rustc_clean(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:11:1 + | +LL | #[rustc_if_this_changed(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:16:1 + | +LL | #[rustc_clean(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:19:1 + | +LL | #[rustc_then_this_would_need(variances_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-dump.rs b/tests/ui/dep-graph/dep-graph-dump.rs new file mode 100644 index 000000000..cbc4def0e --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-dump.rs @@ -0,0 +1,6 @@ +// Test dump-dep-graph requires query-dep-graph enabled + +// incremental +// compile-flags: -Z dump-dep-graph + +fn main() {} diff --git a/tests/ui/dep-graph/dep-graph-dump.stderr b/tests/ui/dep-graph/dep-graph-dump.stderr new file mode 100644 index 000000000..ea44b8bb0 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-dump.stderr @@ -0,0 +1,2 @@ +error: can't dump dependency graph without `-Z query-dep-graph` + diff --git a/tests/ui/dep-graph/dep-graph-struct-signature.rs b/tests/ui/dep-graph/dep-graph-struct-signature.rs new file mode 100644 index 000000000..fcf9f6387 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-struct-signature.rs @@ -0,0 +1,87 @@ +// Test cases where a changing struct appears in the signature of fns +// and methods. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +fn main() { } + +#[rustc_if_this_changed] +struct WillChange { + x: u32, + y: u32 +} + +struct WontChange { + x: u32, + y: u32 +} + +// these are valid dependencies +mod signatures { + use WillChange; + + #[rustc_then_this_would_need(type_of)] //~ ERROR no path + #[rustc_then_this_would_need(associated_item)] //~ ERROR no path + #[rustc_then_this_would_need(trait_def)] //~ ERROR no path + trait Bar { + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + fn do_something(x: WillChange); + } + + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + fn some_fn(x: WillChange) { } + + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + fn new_foo(x: u32, y: u32) -> WillChange { + WillChange { x: x, y: y } + } + + #[rustc_then_this_would_need(type_of)] //~ ERROR OK + impl WillChange { + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + fn new(x: u32, y: u32) -> WillChange { loop { } } + } + + #[rustc_then_this_would_need(type_of)] //~ ERROR OK + impl WillChange { + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + fn method(&self, x: u32) { } + } + + struct WillChanges { + #[rustc_then_this_would_need(type_of)] //~ ERROR OK + x: WillChange, + #[rustc_then_this_would_need(type_of)] //~ ERROR OK + y: WillChange + } + + // The fields change, not the type itself. + #[rustc_then_this_would_need(type_of)] //~ ERROR no path + fn indirect(x: WillChanges) { } +} + +mod invalid_signatures { + use WontChange; + + #[rustc_then_this_would_need(type_of)] //~ ERROR no path + trait A { + #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path + fn do_something_else_twice(x: WontChange); + } + + #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path + fn b(x: WontChange) { } + + #[rustc_then_this_would_need(fn_sig)] //~ ERROR no path from `WillChange` + #[rustc_then_this_would_need(typeck)] //~ ERROR no path from `WillChange` + fn c(x: u32) { } +} diff --git a/tests/ui/dep-graph/dep-graph-struct-signature.stderr b/tests/ui/dep-graph/dep-graph-struct-signature.stderr new file mode 100644 index 000000000..cfe1e62d9 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-struct-signature.stderr @@ -0,0 +1,134 @@ +error: no path from `WillChange` to `type_of` + --> $DIR/dep-graph-struct-signature.rs:28:5 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `associated_item` + --> $DIR/dep-graph-struct-signature.rs:29:5 + | +LL | #[rustc_then_this_would_need(associated_item)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `trait_def` + --> $DIR/dep-graph-struct-signature.rs:30:5 + | +LL | #[rustc_then_this_would_need(trait_def)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:36:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:37:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:40:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:41:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:46:5 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:53:5 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:61:9 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:63:9 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `type_of` + --> $DIR/dep-graph-struct-signature.rs:68:5 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `type_of` + --> $DIR/dep-graph-struct-signature.rs:75:5 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `fn_sig` + --> $DIR/dep-graph-struct-signature.rs:81:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `fn_sig` + --> $DIR/dep-graph-struct-signature.rs:84:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `typeck` + --> $DIR/dep-graph-struct-signature.rs:85:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:32:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `WillChange` to `fn_sig` + --> $DIR/dep-graph-struct-signature.rs:77:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:48:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:49:9 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:55:9 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-struct-signature.rs:56:9 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 22 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs new file mode 100644 index 000000000..5da8df570 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs @@ -0,0 +1,46 @@ +// Test that adding an impl to a trait `Foo` DOES affect functions +// that only use `Bar` if they have methods in common. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_imports)] + +fn main() { } + +pub trait Foo: Sized { + fn method(self) { } +} + +pub trait Bar: Sized { + fn method(self) { } +} + +mod x { + use {Foo, Bar}; + + #[rustc_if_this_changed] + impl Foo for u32 { } + + impl Bar for char { } +} + +mod y { + use {Foo, Bar}; + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn with_char() { + char::method('a'); + } +} + +mod z { + use y; + + #[rustc_then_this_would_need(typeck)] //~ ERROR no path + pub fn z() { + y::with_char(); + } +} diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr new file mode 100644 index 000000000..6f56cbc8d --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr @@ -0,0 +1,14 @@ +error: OK + --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:33:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `x::` to `typeck` + --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:42:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs new file mode 100644 index 000000000..590475fa0 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.rs @@ -0,0 +1,45 @@ +// Test that adding an impl to a trait `Foo` does not affect functions +// that only use `Bar`, so long as they do not have methods in common. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(warnings)] + +fn main() { } + +pub trait Foo: Sized { + fn foo(self) { } +} + +pub trait Bar: Sized { + fn bar(self) { } +} + +mod x { + use {Foo, Bar}; + + #[rustc_if_this_changed] + impl Foo for char { } + + impl Bar for char { } +} + +mod y { + use {Foo, Bar}; + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn call_bar() { + char::bar('a'); + } +} + +mod z { + use y; + + #[rustc_then_this_would_need(typeck)] //~ ERROR no path + pub fn z() { + y::call_bar(); + } +} diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr new file mode 100644 index 000000000..4e1043736 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr @@ -0,0 +1,14 @@ +error: OK + --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `x::` to `typeck` + --> $DIR/dep-graph-trait-impl-two-traits.rs:41:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-trait-impl.rs b/tests/ui/dep-graph/dep-graph-trait-impl.rs new file mode 100644 index 000000000..19002965b --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-trait-impl.rs @@ -0,0 +1,61 @@ +// Test that when a trait impl changes, fns whose body uses that trait +// must also be recompiled. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(warnings)] + +fn main() { } + +pub trait Foo: Sized { + fn method(self) { } +} + +mod x { + use Foo; + + #[rustc_if_this_changed] + impl Foo for char { } + + impl Foo for u32 { } +} + +mod y { + use Foo; + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn with_char() { + char::method('a'); + } + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn take_foo_with_char() { + take_foo::('a'); + } + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn with_u32() { + u32::method(22); + } + + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + pub fn take_foo_with_u32() { + take_foo::(22); + } + + pub fn take_foo(t: T) { } +} + +mod z { + use y; + + // These are expected to yield errors, because changes to `x` + // affect the BODY of `y`, but not its signature. + #[rustc_then_this_would_need(typeck)] //~ ERROR no path + pub fn z() { + y::with_char(); + y::with_u32(); + } +} diff --git a/tests/ui/dep-graph/dep-graph-trait-impl.stderr b/tests/ui/dep-graph/dep-graph-trait-impl.stderr new file mode 100644 index 000000000..bfee6d5c8 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-trait-impl.stderr @@ -0,0 +1,32 @@ +error: OK + --> $DIR/dep-graph-trait-impl.rs:28:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-trait-impl.rs:33:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-trait-impl.rs:38:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-trait-impl.rs:43:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `x::` to `typeck` + --> $DIR/dep-graph-trait-impl.rs:56:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-type-alias.rs b/tests/ui/dep-graph/dep-graph-type-alias.rs new file mode 100644 index 000000000..0e1b3db19 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-type-alias.rs @@ -0,0 +1,56 @@ +// Test that changing what a `type` points to does not go unnoticed. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +fn main() { } + + +#[rustc_if_this_changed] +type TypeAlias = u32; + +// The type alias directly affects the type of the field, +// not the enclosing struct: +#[rustc_then_this_would_need(type_of)] //~ ERROR no path +struct Struct { + #[rustc_then_this_would_need(type_of)] //~ ERROR OK + x: TypeAlias, + y: u32 +} + +#[rustc_then_this_would_need(type_of)] //~ ERROR no path +enum Enum { + Variant1 { + #[rustc_then_this_would_need(type_of)] //~ ERROR OK + t: TypeAlias + }, + Variant2(i32) +} + +#[rustc_then_this_would_need(type_of)] //~ ERROR no path +trait Trait { + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + fn method(&self, _: TypeAlias); +} + +struct SomeType; + +#[rustc_then_this_would_need(type_of)] //~ ERROR no path +impl SomeType { + #[rustc_then_this_would_need(fn_sig)] //~ ERROR OK + #[rustc_then_this_would_need(typeck)] //~ ERROR OK + fn method(&self, _: TypeAlias) {} +} + +#[rustc_then_this_would_need(type_of)] //~ ERROR OK +type TypeAlias2 = TypeAlias; + +#[rustc_then_this_would_need(fn_sig)] //~ ERROR OK +#[rustc_then_this_would_need(typeck)] //~ ERROR OK +fn function(_: TypeAlias) { + +} diff --git a/tests/ui/dep-graph/dep-graph-type-alias.stderr b/tests/ui/dep-graph/dep-graph-type-alias.stderr new file mode 100644 index 000000000..42ac803b2 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-type-alias.stderr @@ -0,0 +1,74 @@ +error: no path from `TypeAlias` to `type_of` + --> $DIR/dep-graph-type-alias.rs:18:1 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:20:5 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `TypeAlias` to `type_of` + --> $DIR/dep-graph-type-alias.rs:25:1 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:28:9 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `TypeAlias` to `type_of` + --> $DIR/dep-graph-type-alias.rs:34:1 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: no path from `TypeAlias` to `type_of` + --> $DIR/dep-graph-type-alias.rs:42:1 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:49:1 + | +LL | #[rustc_then_this_would_need(type_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:52:1 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:53:1 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:36:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:44:5 + | +LL | #[rustc_then_this_would_need(fn_sig)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: OK + --> $DIR/dep-graph-type-alias.rs:45:5 + | +LL | #[rustc_then_this_would_need(typeck)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/dep-graph/dep-graph-variance-alias.rs b/tests/ui/dep-graph/dep-graph-variance-alias.rs new file mode 100644 index 000000000..008434696 --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-variance-alias.rs @@ -0,0 +1,22 @@ +// Test that changing what a `type` points to does not go unnoticed +// by the variance analysis. + +// incremental +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] +fn main() {} + +#[rustc_if_this_changed] +struct Foo { + f: T, +} + +type TypeAlias = Foo; + +#[rustc_then_this_would_need(variances_of)] //~ ERROR OK +struct Use { + x: TypeAlias, +} diff --git a/tests/ui/dep-graph/dep-graph-variance-alias.stderr b/tests/ui/dep-graph/dep-graph-variance-alias.stderr new file mode 100644 index 000000000..554ff455a --- /dev/null +++ b/tests/ui/dep-graph/dep-graph-variance-alias.stderr @@ -0,0 +1,8 @@ +error: OK + --> $DIR/dep-graph-variance-alias.rs:19:1 + | +LL | #[rustc_then_this_would_need(variances_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/deprecation-in-force-unstable.rs b/tests/ui/deprecation-in-force-unstable.rs new file mode 100644 index 000000000..4df9b802d --- /dev/null +++ b/tests/ui/deprecation-in-force-unstable.rs @@ -0,0 +1,5 @@ +// run-pass +// compile-flags:-Zforce-unstable-if-unmarked + +#[deprecated] // should work even with -Zforce-unstable-if-unmarked +fn main() { } diff --git a/tests/ui/deprecation/atomic_initializers.fixed b/tests/ui/deprecation/atomic_initializers.fixed new file mode 100644 index 000000000..4fb0aeeb5 --- /dev/null +++ b/tests/ui/deprecation/atomic_initializers.fixed @@ -0,0 +1,11 @@ +// run-rustfix +// check-pass + +#[allow(deprecated, unused_imports)] +use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT}; + +#[allow(dead_code)] +static FOO: AtomicIsize = AtomicIsize::new(0); +//~^ WARN use of deprecated constant + +fn main() {} diff --git a/tests/ui/deprecation/atomic_initializers.rs b/tests/ui/deprecation/atomic_initializers.rs new file mode 100644 index 000000000..1dcfd36d7 --- /dev/null +++ b/tests/ui/deprecation/atomic_initializers.rs @@ -0,0 +1,11 @@ +// run-rustfix +// check-pass + +#[allow(deprecated, unused_imports)] +use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT}; + +#[allow(dead_code)] +static FOO: AtomicIsize = ATOMIC_ISIZE_INIT; +//~^ WARN use of deprecated constant + +fn main() {} diff --git a/tests/ui/deprecation/atomic_initializers.stderr b/tests/ui/deprecation/atomic_initializers.stderr new file mode 100644 index 000000000..30fcc9de6 --- /dev/null +++ b/tests/ui/deprecation/atomic_initializers.stderr @@ -0,0 +1,14 @@ +warning: use of deprecated constant `std::sync::atomic::ATOMIC_ISIZE_INIT`: the `new` function is now preferred + --> $DIR/atomic_initializers.rs:8:27 + | +LL | static FOO: AtomicIsize = ATOMIC_ISIZE_INIT; + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default +help: replace the use of the deprecated constant + | +LL | static FOO: AtomicIsize = AtomicIsize::new(0); + | ~~~~~~~~~~~~~~~~~~~ + +warning: 1 warning emitted + diff --git a/tests/ui/deprecation/auxiliary/deprecation-lint.rs b/tests/ui/deprecation/auxiliary/deprecation-lint.rs new file mode 100644 index 000000000..948bf1cb7 --- /dev/null +++ b/tests/ui/deprecation/auxiliary/deprecation-lint.rs @@ -0,0 +1,98 @@ +#![feature(deprecated)] + +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated() {} +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_text() {} + +pub struct MethodTester; + +impl MethodTester { + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} +} + +pub trait Trait { + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} +} + +#[deprecated(since = "1.0.0", note = "text")] +pub trait DeprecatedTrait { fn dummy(&self) { } } + +impl Trait for MethodTester {} + +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedStruct { + pub i: isize +} + +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnitStruct; + +pub enum Enum { + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, +} + +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedTupleStruct(pub isize); + +pub mod nested { + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + pub i: isize + } + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + + pub enum Enum { + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + } + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(pub isize); +} + +pub struct Stable { + #[deprecated(since = "1.0.0", note = "text")] + pub override2: u8, +} + +pub struct Stable2(pub u8, pub u8, #[deprecated(since = "1.0.0", note = "text")] pub u8); + +#[deprecated(since = "1.0.0", note = "text")] +pub struct Deprecated { + pub inherit: u8, +} + +#[deprecated(since = "1.0.0", note = "text")] +pub struct Deprecated2(pub u8, + pub u8, + pub u8); + +#[deprecated(since = "1.0.0", note = "text")] +pub mod deprecated_mod { + pub fn deprecated() {} +} + +#[macro_export] +macro_rules! macro_test { + () => (deprecated()); +} + +#[macro_export] +macro_rules! macro_test_arg { + ($func:expr) => ($func); +} + +#[macro_export] +macro_rules! macro_test_arg_nested { + ($func:ident) => (macro_test_arg!($func())); +} diff --git a/tests/ui/deprecation/deprecated-macro_escape-inner.rs b/tests/ui/deprecation/deprecated-macro_escape-inner.rs new file mode 100644 index 000000000..e2957c422 --- /dev/null +++ b/tests/ui/deprecation/deprecated-macro_escape-inner.rs @@ -0,0 +1,8 @@ +// run-pass + +mod foo { + #![macro_escape] //~ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]` +} + +fn main() { +} diff --git a/tests/ui/deprecation/deprecated-macro_escape-inner.stderr b/tests/ui/deprecation/deprecated-macro_escape-inner.stderr new file mode 100644 index 000000000..5b866bbbe --- /dev/null +++ b/tests/ui/deprecation/deprecated-macro_escape-inner.stderr @@ -0,0 +1,10 @@ +warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + --> $DIR/deprecated-macro_escape-inner.rs:4:5 + | +LL | #![macro_escape] + | ^^^^^^^^^^^^^^^^ + | + = help: try an outer attribute: `#[macro_use]` + +warning: 1 warning emitted + diff --git a/tests/ui/deprecation/deprecated-macro_escape.rs b/tests/ui/deprecation/deprecated-macro_escape.rs new file mode 100644 index 000000000..4a89b4062 --- /dev/null +++ b/tests/ui/deprecation/deprecated-macro_escape.rs @@ -0,0 +1,6 @@ +// run-pass + +#[macro_escape] //~ WARNING `#[macro_escape]` is a deprecated synonym for `#[macro_use]` +mod foo {} + +fn main() {} diff --git a/tests/ui/deprecation/deprecated-macro_escape.stderr b/tests/ui/deprecation/deprecated-macro_escape.stderr new file mode 100644 index 000000000..0bb8dc17e --- /dev/null +++ b/tests/ui/deprecation/deprecated-macro_escape.stderr @@ -0,0 +1,8 @@ +warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + --> $DIR/deprecated-macro_escape.rs:3:1 + | +LL | #[macro_escape] + | ^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/deprecation/deprecated_no_stack_check.rs b/tests/ui/deprecation/deprecated_no_stack_check.rs new file mode 100644 index 000000000..8e1f5bbf0 --- /dev/null +++ b/tests/ui/deprecation/deprecated_no_stack_check.rs @@ -0,0 +1,6 @@ +#![deny(warnings)] +#![feature(no_stack_check)] +//~^ ERROR: feature has been removed [E0557] +fn main() { + +} diff --git a/tests/ui/deprecation/deprecated_no_stack_check.stderr b/tests/ui/deprecation/deprecated_no_stack_check.stderr new file mode 100644 index 000000000..141664c10 --- /dev/null +++ b/tests/ui/deprecation/deprecated_no_stack_check.stderr @@ -0,0 +1,9 @@ +error[E0557]: feature has been removed + --> $DIR/deprecated_no_stack_check.rs:2:12 + | +LL | #![feature(no_stack_check)] + | ^^^^^^^^^^^^^^ feature has been removed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/deprecation/deprecation-in-future.rs b/tests/ui/deprecation/deprecation-in-future.rs new file mode 100644 index 000000000..fb2a9a401 --- /dev/null +++ b/tests/ui/deprecation/deprecation-in-future.rs @@ -0,0 +1,13 @@ +// check-pass + +#![deny(deprecated_in_future)] + +#[deprecated(since = "99.99.99", note = "text")] +pub fn deprecated_future() {} + +fn test() { + deprecated_future(); // ok; deprecated_in_future only applies with `#![feature(staged_api)]` + //~^ WARNING use of deprecated function `deprecated_future`: text [deprecated] +} + +fn main() {} diff --git a/tests/ui/deprecation/deprecation-in-future.stderr b/tests/ui/deprecation/deprecation-in-future.stderr new file mode 100644 index 000000000..99d1c7341 --- /dev/null +++ b/tests/ui/deprecation/deprecation-in-future.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated function `deprecated_future`: text + --> $DIR/deprecation-in-future.rs:9:5 + | +LL | deprecated_future(); // ok; deprecated_in_future only applies with `#![feature(staged_api)]` + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/deprecation/deprecation-lint-2.rs b/tests/ui/deprecation/deprecation-lint-2.rs new file mode 100644 index 000000000..16ed6d4ec --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint-2.rs @@ -0,0 +1,13 @@ +// aux-build:deprecation-lint.rs +// error-pattern: use of deprecated function + +#![deny(deprecated)] + +#[macro_use] +extern crate deprecation_lint; + +use deprecation_lint::*; + +fn main() { + macro_test!(); +} diff --git a/tests/ui/deprecation/deprecation-lint-2.stderr b/tests/ui/deprecation/deprecation-lint-2.stderr new file mode 100644 index 000000000..a73e56052 --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint-2.stderr @@ -0,0 +1,15 @@ +error: use of deprecated function `deprecation_lint::deprecated`: text + --> $DIR/deprecation-lint-2.rs:12:5 + | +LL | macro_test!(); + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/deprecation-lint-2.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + = note: this error originates in the macro `macro_test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/deprecation/deprecation-lint-3.rs b/tests/ui/deprecation/deprecation-lint-3.rs new file mode 100644 index 000000000..e6e1587da --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint-3.rs @@ -0,0 +1,14 @@ +// aux-build:deprecation-lint.rs +// error-pattern: use of deprecated function + +#![deny(deprecated)] +#![allow(warnings)] + +#[macro_use] +extern crate deprecation_lint; + +use deprecation_lint::*; + +fn main() { + macro_test_arg_nested!(deprecated_text); +} diff --git a/tests/ui/deprecation/deprecation-lint-3.stderr b/tests/ui/deprecation/deprecation-lint-3.stderr new file mode 100644 index 000000000..f499ff85e --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint-3.stderr @@ -0,0 +1,14 @@ +error: use of deprecated function `deprecation_lint::deprecated_text`: text + --> $DIR/deprecation-lint-3.rs:13:28 + | +LL | macro_test_arg_nested!(deprecated_text); + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/deprecation-lint-3.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/deprecation/deprecation-lint-nested.rs b/tests/ui/deprecation/deprecation-lint-nested.rs new file mode 100644 index 000000000..589522cdb --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint-nested.rs @@ -0,0 +1,71 @@ +#![deny(deprecated)] +#![allow(warnings)] + +#[deprecated] +fn issue_35128() { + format_args!("foo"); +} + +#[deprecated] +fn issue_35128_minimal() { + static FOO: &'static str = "foo"; + let _ = FOO; +} + +#[deprecated] +mod silent { + type DeprecatedType = u8; + struct DeprecatedStruct; + fn deprecated_fn() {} + trait DeprecatedTrait {} + static DEPRECATED_STATIC: u8 = 0; + const DEPRECATED_CONST: u8 = 1; + + struct Foo(DeprecatedType); + + impl DeprecatedTrait for Foo {} + + impl Foo { + fn bar() { + deprecated_fn(); + } + } + + fn foo() -> u8 { + DEPRECATED_STATIC + + DEPRECATED_CONST + } +} + +#[deprecated] +mod loud { + #[deprecated] + type DeprecatedType = u8; + #[deprecated] + struct DeprecatedStruct; + #[deprecated] + fn deprecated_fn() {} + #[deprecated] + trait DeprecatedTrait {} + #[deprecated] + static DEPRECATED_STATIC: u8 = 0; + #[deprecated] + const DEPRECATED_CONST: u8 = 1; + + struct Foo(DeprecatedType); //~ ERROR use of deprecated type alias + + impl DeprecatedTrait for Foo {} //~ ERROR use of deprecated trait + + impl Foo { + fn bar() { //~ ERROR use of deprecated trait + deprecated_fn(); //~ ERROR use of deprecated function + } + } + + fn foo() -> u8 { + DEPRECATED_STATIC + //~ ERROR use of deprecated static + DEPRECATED_CONST //~ ERROR use of deprecated const + } +} + +fn main() {} diff --git a/tests/ui/deprecation/deprecation-lint-nested.stderr b/tests/ui/deprecation/deprecation-lint-nested.stderr new file mode 100644 index 000000000..47607b8cc --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint-nested.stderr @@ -0,0 +1,44 @@ +error: use of deprecated type alias `loud::DeprecatedType` + --> $DIR/deprecation-lint-nested.rs:55:16 + | +LL | struct Foo(DeprecatedType); + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/deprecation-lint-nested.rs:1:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: use of deprecated trait `loud::DeprecatedTrait` + --> $DIR/deprecation-lint-nested.rs:57:10 + | +LL | impl DeprecatedTrait for Foo {} + | ^^^^^^^^^^^^^^^ + +error: use of deprecated static `loud::DEPRECATED_STATIC` + --> $DIR/deprecation-lint-nested.rs:66:9 + | +LL | DEPRECATED_STATIC + + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated constant `loud::DEPRECATED_CONST` + --> $DIR/deprecation-lint-nested.rs:67:9 + | +LL | DEPRECATED_CONST + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated trait `loud::DeprecatedTrait` + --> $DIR/deprecation-lint-nested.rs:60:19 + | +LL | fn bar() { + | ^^^^^^^^^^^^^^^ + +error: use of deprecated function `loud::deprecated_fn` + --> $DIR/deprecation-lint-nested.rs:61:13 + | +LL | deprecated_fn(); + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/deprecation/deprecation-lint.rs b/tests/ui/deprecation/deprecation-lint.rs new file mode 100644 index 000000000..0417e952e --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint.rs @@ -0,0 +1,454 @@ +// aux-build:deprecation-lint.rs + +#![deny(deprecated)] +#![allow(warnings)] + +#[macro_use] +extern crate deprecation_lint; + +mod cross_crate { + use deprecation_lint::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); //~ ERROR use of deprecated function `deprecation_lint::deprecated` + foo.method_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated` + Foo::method_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated` + ::method_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated` + foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + + deprecated_text(); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text + foo.method_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text + Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text + ::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text + foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + + let _ = DeprecatedStruct { //~ ERROR use of deprecated struct `deprecation_lint::DeprecatedStruct`: text + i: 0 //~ ERROR use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text + }; + + let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `deprecation_lint::DeprecatedUnitStruct`: text + + let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated unit variant `deprecation_lint::Enum::DeprecatedVariant`: text + + let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `deprecation_lint::DeprecatedTupleStruct`: text + + let _ = nested::DeprecatedStruct { //~ ERROR use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text + i: 0 //~ ERROR use of deprecated field `deprecation_lint::nested::DeprecatedStruct::i`: text + }; + + let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `deprecation_lint::nested::DeprecatedUnitStruct`: text + + let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated unit variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text + + let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `deprecation_lint::nested::DeprecatedTupleStruct`: text + + // At the moment, the lint checker only checks stability + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text + macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + } + + fn test_method_object(foo: &Trait) { + foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + } + + struct S; + + impl DeprecatedTrait for S {} //~ ERROR use of deprecated trait `deprecation_lint::DeprecatedTrait`: text + trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated trait `deprecation_lint::DeprecatedTrait`: text + + pub fn foo() { + let x = Stable { + override2: 3, + //~^ ERROR use of deprecated field `deprecation_lint::Stable::override2`: text + }; + + let _ = x.override2; + //~^ ERROR use of deprecated field `deprecation_lint::Stable::override2`: text + + let Stable { + override2: _ + //~^ ERROR use of deprecated field `deprecation_lint::Stable::override2`: text + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.2; + //~^ ERROR use of deprecated field `deprecation_lint::Stable2::2`: text + + let Stable2(_, + _, + _) + //~^ ERROR use of deprecated field `deprecation_lint::Stable2::2`: text + = x; + // all fine + let Stable2(..) = x; + + let x = Deprecated { + //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated`: text + inherit: 1, + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated::inherit`: text + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated::inherit`: text + + let Deprecated { + //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated`: text + inherit: _, + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated::inherit`: text + } = x; + + let Deprecated + //~^ ERROR use of deprecated struct `deprecation_lint::Deprecated`: text + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated tuple struct `deprecation_lint::Deprecated2`: text + + let _ = x.0; + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::0`: text + let _ = x.1; + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::1`: text + let _ = x.2; + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::2`: text + + let Deprecated2 + //~^ ERROR use of deprecated tuple struct `deprecation_lint::Deprecated2`: text + (_, + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::0`: text + _, + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::1`: text + _) + //~^ ERROR use of deprecated field `deprecation_lint::Deprecated2::2`: text + = x; + let Deprecated2 + //~^ ERROR use of deprecated tuple struct `deprecation_lint::Deprecated2`: text + // the patterns are all fine: + (..) = x; + } +} + +mod inheritance { + use deprecation_lint::*; + + fn test_inheritance() { + deprecated_mod::deprecated(); //~ ERROR use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text + } +} + +mod this_crate { + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future() {} + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future_text() {} + + pub struct MethodTester; + + impl MethodTester { + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + } + + pub trait Trait { + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + } + + impl Trait for MethodTester {} + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + i: isize + } + pub struct UnstableStruct { + i: isize + } + pub struct StableStruct { + i: isize + } + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + + pub enum Enum { + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + } + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + + mod nested { + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + i: isize + } + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + + pub enum Enum { + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + } + + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(pub isize); + } + + fn test() { + use self::nested; + + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); //~ ERROR use of deprecated function `this_crate::deprecated` + foo.method_deprecated(); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated` + Foo::method_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated` + ::method_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated` + foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + + deprecated_text(); //~ ERROR use of deprecated function `this_crate::deprecated_text`: text + foo.method_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + ::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + + // Future deprecations are only permitted with `#![feature(staged_api)]` + deprecated_future(); //~ ERROR use of deprecated function + deprecated_future_text(); //~ ERROR use of deprecated function + + let _ = DeprecatedStruct { + //~^ ERROR use of deprecated struct `this_crate::DeprecatedStruct`: text + i: 0 //~ ERROR use of deprecated field `this_crate::DeprecatedStruct::i`: text + }; + + let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text + + let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text + + let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text + + let _ = nested::DeprecatedStruct { + //~^ ERROR use of deprecated struct `this_crate::nested::DeprecatedStruct`: text + i: 0 //~ ERROR use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text + //~| ERROR field `i` of struct `this_crate::nested::DeprecatedStruct` is private + }; + + let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text + + let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text + + let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + } + + fn test_method_object(foo: &Trait) { + foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + } + + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); + } + + fn test_fn_closure_body() { + let _ = || { + #[deprecated] + fn bar() { } + bar(); //~ ERROR use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` + }; + } + + impl MethodTester { + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); + } + } + + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } //~ ERROR use of deprecated trait `this_crate::DeprecatedTrait`: text + + trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated trait `this_crate::DeprecatedTrait`: text +} + +mod this_crate2 { + struct Stable { + #[deprecated(since = "1.0.0", note = "text")] + override2: u8, + } + + struct Stable2(u8, + u8, + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated { + inherit: u8, + } + + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated2(u8, + u8, + u8); + + pub fn foo() { + let x = Stable { + override2: 3, + //~^ ERROR use of deprecated field `this_crate2::Stable::override2`: text + }; + + let _ = x.override2; + //~^ ERROR use of deprecated field `this_crate2::Stable::override2`: text + + let Stable { + override2: _ + //~^ ERROR use of deprecated field `this_crate2::Stable::override2`: text + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.2; + //~^ ERROR use of deprecated field `this_crate2::Stable2::2`: text + + let Stable2(_, + _, + _) + //~^ ERROR use of deprecated field `this_crate2::Stable2::2`: text + = x; + // all fine + let Stable2(..) = x; + + let x = Deprecated { + //~^ ERROR use of deprecated struct `this_crate2::Deprecated`: text + inherit: 1, + //~^ ERROR use of deprecated field `this_crate2::Deprecated::inherit`: text + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated field `this_crate2::Deprecated::inherit`: text + + let Deprecated { + //~^ ERROR use of deprecated struct `this_crate2::Deprecated`: text + inherit: _, + //~^ ERROR use of deprecated field `this_crate2::Deprecated::inherit`: text + } = x; + + let Deprecated + //~^ ERROR use of deprecated struct `this_crate2::Deprecated`: text + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated tuple struct `this_crate2::Deprecated2`: text + + let _ = x.0; + //~^ ERROR use of deprecated field `this_crate2::Deprecated2::0`: text + let _ = x.1; + //~^ ERROR use of deprecated field `this_crate2::Deprecated2::1`: text + let _ = x.2; + //~^ ERROR use of deprecated field `this_crate2::Deprecated2::2`: text + + let Deprecated2 + //~^ ERROR use of deprecated tuple struct `this_crate2::Deprecated2`: text + (_, + //~^ ERROR use of deprecated field `this_crate2::Deprecated2::0`: text + _, + //~^ ERROR use of deprecated field `this_crate2::Deprecated2::1`: text + _) + //~^ ERROR use of deprecated field `this_crate2::Deprecated2::2`: text + = x; + let Deprecated2 + //~^ ERROR use of deprecated tuple struct `this_crate2::Deprecated2`: text + // the patterns are all fine: + (..) = x; + } + + #[derive(Debug)] + #[deprecated(note = "Use something else instead")] + enum DeprecatedDebugEnum { + Variant1 { value: Option }, + } + + #[allow(deprecated)] + impl DeprecatedDebugEnum { + fn new() -> Self { + DeprecatedDebugEnum::Variant1 { value: None } + } + } + + #[allow(deprecated)] + pub fn allow_dep() { + let _ = DeprecatedDebugEnum::new(); + } +} + +fn main() {} diff --git a/tests/ui/deprecation/deprecation-lint.stderr b/tests/ui/deprecation/deprecation-lint.stderr new file mode 100644 index 000000000..3842f8492 --- /dev/null +++ b/tests/ui/deprecation/deprecation-lint.stderr @@ -0,0 +1,747 @@ +error: use of deprecated function `deprecation_lint::deprecated`: text + --> $DIR/deprecation-lint.rs:16:9 + | +LL | deprecated(); + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/deprecation-lint.rs:3:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:21:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:23:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated function `deprecation_lint::deprecated_text`: text + --> $DIR/deprecation-lint.rs:25:9 + | +LL | deprecated_text(); + | ^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:30:16 + | +LL | ... Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:32:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text + --> $DIR/deprecation-lint.rs:34:17 + | +LL | let _ = DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated unit struct `deprecation_lint::DeprecatedUnitStruct`: text + --> $DIR/deprecation-lint.rs:38:17 + | +LL | let _ = DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated unit variant `deprecation_lint::Enum::DeprecatedVariant`: text + --> $DIR/deprecation-lint.rs:40:23 + | +LL | let _ = Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated tuple struct `deprecation_lint::DeprecatedTupleStruct`: text + --> $DIR/deprecation-lint.rs:42:17 + | +LL | let _ = DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text + --> $DIR/deprecation-lint.rs:44:25 + | +LL | let _ = nested::DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated unit struct `deprecation_lint::nested::DeprecatedUnitStruct`: text + --> $DIR/deprecation-lint.rs:48:25 + | +LL | let _ = nested::DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated unit variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text + --> $DIR/deprecation-lint.rs:50:31 + | +LL | ... let _ = nested::Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated tuple struct `deprecation_lint::nested::DeprecatedTupleStruct`: text + --> $DIR/deprecation-lint.rs:52:25 + | +LL | ... let _ = nested::DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated function `deprecation_lint::deprecated_text`: text + --> $DIR/deprecation-lint.rs:59:25 + | +LL | macro_test_arg!(deprecated_text()); + | ^^^^^^^^^^^^^^^ + +error: use of deprecated function `deprecation_lint::deprecated_text`: text + --> $DIR/deprecation-lint.rs:60:41 + | +LL | macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:65:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:67:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:69:16 + | +LL | ... Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:71:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text + --> $DIR/deprecation-lint.rs:81:10 + | +LL | impl DeprecatedTrait for S {} + | ^^^^^^^^^^^^^^^ + +error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text + --> $DIR/deprecation-lint.rs:82:24 + | +LL | trait LocalTrait : DeprecatedTrait { } + | ^^^^^^^^^^^^^^^ + +error: use of deprecated struct `deprecation_lint::Deprecated`: text + --> $DIR/deprecation-lint.rs:113:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `deprecation_lint::Deprecated`: text + --> $DIR/deprecation-lint.rs:122:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `deprecation_lint::Deprecated`: text + --> $DIR/deprecation-lint.rs:128:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + +error: use of deprecated tuple struct `deprecation_lint::Deprecated2`: text + --> $DIR/deprecation-lint.rs:132:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `deprecation_lint::Deprecated2`: text + --> $DIR/deprecation-lint.rs:142:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `deprecation_lint::Deprecated2`: text + --> $DIR/deprecation-lint.rs:151:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text + --> $DIR/deprecation-lint.rs:162:25 + | +LL | deprecated_mod::deprecated(); + | ^^^^^^^^^^ + +error: use of deprecated function `this_crate::deprecated`: text + --> $DIR/deprecation-lint.rs:245:9 + | +LL | deprecated(); + | ^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:250:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:252:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated function `this_crate::deprecated_text`: text + --> $DIR/deprecation-lint.rs:254:9 + | +LL | deprecated_text(); + | ^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:259:16 + | +LL | Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:261:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated function `this_crate::deprecated_future`: text + --> $DIR/deprecation-lint.rs:264:9 + | +LL | deprecated_future(); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated function `this_crate::deprecated_future_text`: text + --> $DIR/deprecation-lint.rs:265:9 + | +LL | deprecated_future_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated struct `this_crate::DeprecatedStruct`: text + --> $DIR/deprecation-lint.rs:267:17 + | +LL | let _ = DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text + --> $DIR/deprecation-lint.rs:272:17 + | +LL | let _ = DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text + --> $DIR/deprecation-lint.rs:274:23 + | +LL | let _ = Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text + --> $DIR/deprecation-lint.rs:276:17 + | +LL | let _ = DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text + --> $DIR/deprecation-lint.rs:278:25 + | +LL | let _ = nested::DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text + --> $DIR/deprecation-lint.rs:284:25 + | +LL | let _ = nested::DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text + --> $DIR/deprecation-lint.rs:286:31 + | +LL | ... let _ = nested::Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text + --> $DIR/deprecation-lint.rs:288:25 + | +LL | ... let _ = nested::DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:293:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:295:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:297:16 + | +LL | Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:299:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar` + --> $DIR/deprecation-lint.rs:317:13 + | +LL | bar(); + | ^^^ + +error: use of deprecated trait `this_crate::DeprecatedTrait`: text + --> $DIR/deprecation-lint.rs:336:10 + | +LL | impl DeprecatedTrait for S { } + | ^^^^^^^^^^^^^^^ + +error: use of deprecated trait `this_crate::DeprecatedTrait`: text + --> $DIR/deprecation-lint.rs:338:24 + | +LL | trait LocalTrait : DeprecatedTrait { } + | ^^^^^^^^^^^^^^^ + +error: use of deprecated struct `this_crate2::Deprecated`: text + --> $DIR/deprecation-lint.rs:390:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `this_crate2::Deprecated`: text + --> $DIR/deprecation-lint.rs:399:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `this_crate2::Deprecated`: text + --> $DIR/deprecation-lint.rs:405:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate2::Deprecated2`: text + --> $DIR/deprecation-lint.rs:410:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate2::Deprecated2`: text + --> $DIR/deprecation-lint.rs:420:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate2::Deprecated2`: text + --> $DIR/deprecation-lint.rs:429:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text + --> $DIR/deprecation-lint.rs:17:13 + | +LL | foo.method_deprecated(); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text + --> $DIR/deprecation-lint.rs:18:14 + | +LL | Foo::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text + --> $DIR/deprecation-lint.rs:19:16 + | +LL | ::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:20:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:22:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text + --> $DIR/deprecation-lint.rs:26:13 + | +LL | ... foo.method_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text + --> $DIR/deprecation-lint.rs:27:14 + | +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text + --> $DIR/deprecation-lint.rs:28:16 + | +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:29:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:31:16 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text + --> $DIR/deprecation-lint.rs:35:13 + | +LL | i: 0 + | ^^^^ + +error: use of deprecated field `deprecation_lint::nested::DeprecatedStruct::i`: text + --> $DIR/deprecation-lint.rs:45:13 + | +LL | i: 0 + | ^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:64:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:66:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:68:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:70:16 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:75:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:76:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Stable::override2`: text + --> $DIR/deprecation-lint.rs:86:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Stable::override2`: text + --> $DIR/deprecation-lint.rs:90:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Stable::override2`: text + --> $DIR/deprecation-lint.rs:94:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Stable2::2`: text + --> $DIR/deprecation-lint.rs:102:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `deprecation_lint::Stable2::2`: text + --> $DIR/deprecation-lint.rs:107:20 + | +LL | _) + | ^ + +error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text + --> $DIR/deprecation-lint.rs:115:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text + --> $DIR/deprecation-lint.rs:119:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Deprecated::inherit`: text + --> $DIR/deprecation-lint.rs:124:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + +error: use of deprecated field `deprecation_lint::Deprecated2::0`: text + --> $DIR/deprecation-lint.rs:135:17 + | +LL | let _ = x.0; + | ^^^ + +error: use of deprecated field `deprecation_lint::Deprecated2::1`: text + --> $DIR/deprecation-lint.rs:137:17 + | +LL | let _ = x.1; + | ^^^ + +error: use of deprecated field `deprecation_lint::Deprecated2::2`: text + --> $DIR/deprecation-lint.rs:139:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `deprecation_lint::Deprecated2::0`: text + --> $DIR/deprecation-lint.rs:144:14 + | +LL | (_, + | ^ + +error: use of deprecated field `deprecation_lint::Deprecated2::1`: text + --> $DIR/deprecation-lint.rs:146:14 + | +LL | _, + | ^ + +error: use of deprecated field `deprecation_lint::Deprecated2::2`: text + --> $DIR/deprecation-lint.rs:148:14 + | +LL | _) + | ^ + +error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/deprecation-lint.rs:246:13 + | +LL | foo.method_deprecated(); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/deprecation-lint.rs:247:14 + | +LL | Foo::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/deprecation-lint.rs:248:16 + | +LL | ::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:249:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:251:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/deprecation-lint.rs:255:13 + | +LL | ... foo.method_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/deprecation-lint.rs:256:14 + | +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/deprecation-lint.rs:257:16 + | +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:258:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:260:16 + | +LL | ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::DeprecatedStruct::i`: text + --> $DIR/deprecation-lint.rs:269:13 + | +LL | i: 0 + | ^^^^ + +error: use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text + --> $DIR/deprecation-lint.rs:280:13 + | +LL | i: 0 + | ^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:292:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:294:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:296:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:298:16 + | +LL | ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/deprecation-lint.rs:303:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/deprecation-lint.rs:304:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of deprecated field `this_crate2::Stable::override2`: text + --> $DIR/deprecation-lint.rs:363:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate2::Stable::override2`: text + --> $DIR/deprecation-lint.rs:367:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate2::Stable::override2`: text + --> $DIR/deprecation-lint.rs:371:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate2::Stable2::2`: text + --> $DIR/deprecation-lint.rs:379:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate2::Stable2::2`: text + --> $DIR/deprecation-lint.rs:384:20 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate2::Deprecated::inherit`: text + --> $DIR/deprecation-lint.rs:392:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + +error: use of deprecated field `this_crate2::Deprecated::inherit`: text + --> $DIR/deprecation-lint.rs:396:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + +error: use of deprecated field `this_crate2::Deprecated::inherit`: text + --> $DIR/deprecation-lint.rs:401:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + +error: use of deprecated field `this_crate2::Deprecated2::0`: text + --> $DIR/deprecation-lint.rs:413:17 + | +LL | let _ = x.0; + | ^^^ + +error: use of deprecated field `this_crate2::Deprecated2::1`: text + --> $DIR/deprecation-lint.rs:415:17 + | +LL | let _ = x.1; + | ^^^ + +error: use of deprecated field `this_crate2::Deprecated2::2`: text + --> $DIR/deprecation-lint.rs:417:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate2::Deprecated2::0`: text + --> $DIR/deprecation-lint.rs:422:14 + | +LL | (_, + | ^ + +error: use of deprecated field `this_crate2::Deprecated2::1`: text + --> $DIR/deprecation-lint.rs:424:14 + | +LL | _, + | ^ + +error: use of deprecated field `this_crate2::Deprecated2::2`: text + --> $DIR/deprecation-lint.rs:426:14 + | +LL | _) + | ^ + +error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private + --> $DIR/deprecation-lint.rs:280:13 + | +LL | i: 0 + | ^^^^ private field + +error: aborting due to 123 previous errors + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs new file mode 100644 index 000000000..9ea75b68f --- /dev/null +++ b/tests/ui/deprecation/deprecation-sanity.rs @@ -0,0 +1,42 @@ +// Various checks that deprecation attributes are used correctly + +mod bogus_attribute_types_1 { + #[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason' + fn f1() { } + + #[deprecated(since = "a", note)] //~ ERROR incorrect meta item + fn f2() { } + + #[deprecated(since, note = "a")] //~ ERROR incorrect meta item + fn f3() { } + + #[deprecated(since = "a", note(b))] //~ ERROR incorrect meta item + fn f5() { } + + #[deprecated(since(b), note = "a")] //~ ERROR incorrect meta item + fn f6() { } + + #[deprecated(note = b"test")] //~ ERROR literal in `deprecated` value must be a string + fn f7() { } + + #[deprecated("test")] //~ ERROR item in `deprecated` must be a key/value pair + fn f8() { } +} + +#[deprecated(since = "a", note = "b")] +#[deprecated(since = "a", note = "b")] //~ ERROR multiple `deprecated` attributes +fn multiple1() { } + +#[deprecated(since = "a", since = "b", note = "c")] //~ ERROR multiple 'since' items +fn f1() { } + +struct X; + +#[deprecated = "hello"] //~ ERROR this `#[deprecated]` annotation has no effect +impl Default for X { + fn default() -> Self { + X + } +} + +fn main() { } diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr new file mode 100644 index 000000000..8b2b480d1 --- /dev/null +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -0,0 +1,74 @@ +error: multiple `deprecated` attributes + --> $DIR/deprecation-sanity.rs:27:1 + | +LL | #[deprecated(since = "a", note = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/deprecation-sanity.rs:26:1 + | +LL | #[deprecated(since = "a", note = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0541]: unknown meta item 'reason' + --> $DIR/deprecation-sanity.rs:4:43 + | +LL | #[deprecated(since = "a", note = "a", reason)] + | ^^^^^^ expected one of `since`, `note` + +error[E0551]: incorrect meta item + --> $DIR/deprecation-sanity.rs:7:31 + | +LL | #[deprecated(since = "a", note)] + | ^^^^ + +error[E0551]: incorrect meta item + --> $DIR/deprecation-sanity.rs:10:18 + | +LL | #[deprecated(since, note = "a")] + | ^^^^^ + +error[E0551]: incorrect meta item + --> $DIR/deprecation-sanity.rs:13:31 + | +LL | #[deprecated(since = "a", note(b))] + | ^^^^^^^ + +error[E0551]: incorrect meta item + --> $DIR/deprecation-sanity.rs:16:18 + | +LL | #[deprecated(since(b), note = "a")] + | ^^^^^^^^ + +error[E0565]: literal in `deprecated` value must be a string + --> $DIR/deprecation-sanity.rs:19:25 + | +LL | #[deprecated(note = b"test")] + | -^^^^^^ + | | + | help: consider removing the prefix + +error[E0565]: item in `deprecated` must be a key/value pair + --> $DIR/deprecation-sanity.rs:22:18 + | +LL | #[deprecated("test")] + | ^^^^^^ + +error[E0538]: multiple 'since' items + --> $DIR/deprecation-sanity.rs:30:27 + | +LL | #[deprecated(since = "a", since = "b", note = "c")] + | ^^^^^^^^^^^ + +error: this `#[deprecated]` annotation has no effect + --> $DIR/deprecation-sanity.rs:35:1 + | +LL | #[deprecated = "hello"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove the unnecessary deprecation attribute + | + = note: `#[deny(useless_deprecated)]` on by default + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0538, E0541, E0551, E0565. +For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/deprecation/derive_on_deprecated.rs b/tests/ui/deprecation/derive_on_deprecated.rs new file mode 100644 index 000000000..ac771ac81 --- /dev/null +++ b/tests/ui/deprecation/derive_on_deprecated.rs @@ -0,0 +1,15 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![deny(deprecated)] + +#[deprecated = "oh no"] +#[derive(Default)] +struct X; + +#[deprecated(note="Do not use this")] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +pub struct Step { + _skip: Option, +} + +fn main() {} diff --git a/tests/ui/deprecation/derive_on_deprecated_forbidden.rs b/tests/ui/deprecation/derive_on_deprecated_forbidden.rs new file mode 100644 index 000000000..3fd434664 --- /dev/null +++ b/tests/ui/deprecation/derive_on_deprecated_forbidden.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![forbid(deprecated)] + +#[deprecated = "oh no"] +#[derive(Default)] +struct X; + +fn main() {} diff --git a/tests/ui/deprecation/feature-gate-deprecated_suggestion.rs b/tests/ui/deprecation/feature-gate-deprecated_suggestion.rs new file mode 100644 index 000000000..a2d0023e3 --- /dev/null +++ b/tests/ui/deprecation/feature-gate-deprecated_suggestion.rs @@ -0,0 +1,6 @@ +// compile-flags: --crate-type=lib + +#![no_implicit_prelude] + +#[deprecated(suggestion = "foo")] //~ ERROR suggestions on deprecated items are unstable +struct Foo {} diff --git a/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr b/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr new file mode 100644 index 000000000..438ce3349 --- /dev/null +++ b/tests/ui/deprecation/feature-gate-deprecated_suggestion.stderr @@ -0,0 +1,11 @@ +error: suggestions on deprecated items are unstable + --> $DIR/feature-gate-deprecated_suggestion.rs:5:14 + | +LL | #[deprecated(suggestion = "foo")] + | ^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(deprecated_suggestion)]` to the crate root + = note: see #94785 for more details + +error: aborting due to previous error + diff --git a/tests/ui/deprecation/invalid-literal.rs b/tests/ui/deprecation/invalid-literal.rs new file mode 100644 index 000000000..fbdfbd160 --- /dev/null +++ b/tests/ui/deprecation/invalid-literal.rs @@ -0,0 +1,4 @@ +#[deprecated = b"test"] //~ ERROR malformed `deprecated` attribute +fn foo() {} + +fn main() {} diff --git a/tests/ui/deprecation/invalid-literal.stderr b/tests/ui/deprecation/invalid-literal.stderr new file mode 100644 index 000000000..b56eedeb8 --- /dev/null +++ b/tests/ui/deprecation/invalid-literal.stderr @@ -0,0 +1,17 @@ +error: malformed `deprecated` attribute input + --> $DIR/invalid-literal.rs:1:1 + | +LL | #[deprecated = b"test"] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL | #[deprecated = "reason"] + | ~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[deprecated] + | ~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs new file mode 100644 index 000000000..c0cde75d4 --- /dev/null +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -0,0 +1,11 @@ +// The original problem in #66340 was that `find_deprecation_generic` +// called `attr.meta().unwrap()` under the assumption that the attribute +// was a well-formed `MetaItem`. + +fn main() { + foo() +} + +#[deprecated(note = test)] +//~^ ERROR expected unsuffixed literal or identifier, found `test` +fn foo() {} diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr new file mode 100644 index 000000000..24178faf8 --- /dev/null +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -0,0 +1,8 @@ +error: expected unsuffixed literal or identifier, found `test` + --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 + | +LL | #[deprecated(note = test)] + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed new file mode 100644 index 000000000..99a2b0961 --- /dev/null +++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#![deny(deprecated)] + +fn main() { + let _foo = str::trim_start(" aoeu"); //~ ERROR use of deprecated associated function `core::str::::trim_left`: superseded by `trim_start` [deprecated] + + let _bar = " aoeu".trim_start(); //~ ERROR use of deprecated associated function `core::str::::trim_left`: superseded by `trim_start` [deprecated] +} diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs new file mode 100644 index 000000000..62bf84aa3 --- /dev/null +++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#![deny(deprecated)] + +fn main() { + let _foo = str::trim_left(" aoeu"); //~ ERROR use of deprecated associated function `core::str::::trim_left`: superseded by `trim_start` [deprecated] + + let _bar = " aoeu".trim_left(); //~ ERROR use of deprecated associated function `core::str::::trim_left`: superseded by `trim_start` [deprecated] +} diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr new file mode 100644 index 000000000..8d4529526 --- /dev/null +++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr @@ -0,0 +1,29 @@ +error: use of deprecated associated function `core::str::::trim_left`: superseded by `trim_start` + --> $DIR/issue-84637-deprecated-associated-function.rs:6:21 + | +LL | let _foo = str::trim_left(" aoeu"); + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-84637-deprecated-associated-function.rs:3:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ +help: replace the use of the deprecated associated function + | +LL | let _foo = str::trim_start(" aoeu"); + | ~~~~~~~~~~ + +error: use of deprecated associated function `core::str::::trim_left`: superseded by `trim_start` + --> $DIR/issue-84637-deprecated-associated-function.rs:8:26 + | +LL | let _bar = " aoeu".trim_left(); + | ^^^^^^^^^ + | +help: replace the use of the deprecated associated function + | +LL | let _bar = " aoeu".trim_start(); + | ~~~~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/deprecation/staged-deprecation-in-future.rs b/tests/ui/deprecation/staged-deprecation-in-future.rs new file mode 100644 index 000000000..87b15ec30 --- /dev/null +++ b/tests/ui/deprecation/staged-deprecation-in-future.rs @@ -0,0 +1,18 @@ +#![deny(deprecated_in_future)] + +#![feature(staged_api)] + +#![stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] + +#[deprecated(since = "99.99.99", note = "effectively never")] +#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] +pub struct S1; + +#[deprecated(since = "TBD", note = "literally never")] +#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] +pub struct S2; + +fn main() { + let _ = S1; //~ ERROR use of unit struct `S1` that will be deprecated in future version 99.99.99: effectively never + let _ = S2; //~ ERROR use of unit struct `S2` that will be deprecated in a future Rust version: literally never +} diff --git a/tests/ui/deprecation/staged-deprecation-in-future.stderr b/tests/ui/deprecation/staged-deprecation-in-future.stderr new file mode 100644 index 000000000..13d98044a --- /dev/null +++ b/tests/ui/deprecation/staged-deprecation-in-future.stderr @@ -0,0 +1,20 @@ +error: use of unit struct `S1` that will be deprecated in future version 99.99.99: effectively never + --> $DIR/staged-deprecation-in-future.rs:16:13 + | +LL | let _ = S1; + | ^^ + | +note: the lint level is defined here + --> $DIR/staged-deprecation-in-future.rs:1:9 + | +LL | #![deny(deprecated_in_future)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of unit struct `S2` that will be deprecated in a future Rust version: literally never + --> $DIR/staged-deprecation-in-future.rs:17:13 + | +LL | let _ = S2; + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/deprecation/suggestion.fixed b/tests/ui/deprecation/suggestion.fixed new file mode 100644 index 000000000..d9fa2b56e --- /dev/null +++ b/tests/ui/deprecation/suggestion.fixed @@ -0,0 +1,43 @@ +// run-rustfix + +#![feature(staged_api)] +#![feature(deprecated_suggestion)] + +#![stable(since = "1.0.0", feature = "test")] + +#![deny(deprecated)] +#![allow(dead_code)] + +struct Foo; + +impl Foo { + #[deprecated( + since = "1.0.0", + note = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + fn deprecated(&self) {} + + fn replacement(&self) {} +} + +mod bar { + #[deprecated( + since = "1.0.0", + note = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + pub fn deprecated() {} + + pub fn replacement() {} +} + +fn main() { + let foo = Foo; + + foo.replacement(); //~ ERROR use of deprecated + + bar::replacement(); //~ ERROR use of deprecated +} diff --git a/tests/ui/deprecation/suggestion.rs b/tests/ui/deprecation/suggestion.rs new file mode 100644 index 000000000..9dc2eaf25 --- /dev/null +++ b/tests/ui/deprecation/suggestion.rs @@ -0,0 +1,43 @@ +// run-rustfix + +#![feature(staged_api)] +#![feature(deprecated_suggestion)] + +#![stable(since = "1.0.0", feature = "test")] + +#![deny(deprecated)] +#![allow(dead_code)] + +struct Foo; + +impl Foo { + #[deprecated( + since = "1.0.0", + note = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + fn deprecated(&self) {} + + fn replacement(&self) {} +} + +mod bar { + #[deprecated( + since = "1.0.0", + note = "replaced by `replacement`", + suggestion = "replacement", + )] + #[stable(since = "1.0.0", feature = "test")] + pub fn deprecated() {} + + pub fn replacement() {} +} + +fn main() { + let foo = Foo; + + foo.deprecated(); //~ ERROR use of deprecated + + bar::deprecated(); //~ ERROR use of deprecated +} diff --git a/tests/ui/deprecation/suggestion.stderr b/tests/ui/deprecation/suggestion.stderr new file mode 100644 index 000000000..c5f2fc091 --- /dev/null +++ b/tests/ui/deprecation/suggestion.stderr @@ -0,0 +1,29 @@ +error: use of deprecated function `bar::deprecated`: replaced by `replacement` + --> $DIR/suggestion.rs:42:10 + | +LL | bar::deprecated(); + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/suggestion.rs:8:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ +help: replace the use of the deprecated function + | +LL | bar::replacement(); + | ~~~~~~~~~~~ + +error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement` + --> $DIR/suggestion.rs:40:9 + | +LL | foo.deprecated(); + | ^^^^^^^^^^ + | +help: replace the use of the deprecated associated function + | +LL | foo.replacement(); + | ~~~~~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/deprecation/try-macro-suggestion.rs b/tests/ui/deprecation/try-macro-suggestion.rs new file mode 100644 index 000000000..635ceac0b --- /dev/null +++ b/tests/ui/deprecation/try-macro-suggestion.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition 2018 +fn foo() -> Result<(), ()> { + Ok(try!()); //~ ERROR use of deprecated `try` macro + Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/deprecation/try-macro-suggestion.stderr b/tests/ui/deprecation/try-macro-suggestion.stderr new file mode 100644 index 000000000..63c8a6eef --- /dev/null +++ b/tests/ui/deprecation/try-macro-suggestion.stderr @@ -0,0 +1,31 @@ +error: use of deprecated `try` macro + --> $DIR/try-macro-suggestion.rs:3:8 + | +LL | Ok(try!()); + | ^^^^^^ + | + = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated +help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax + | +LL | Ok(r#try!()); + | ++ + +error: use of deprecated `try` macro + --> $DIR/try-macro-suggestion.rs:4:8 + | +LL | Ok(try!(Ok(()))) + | ^^^^^^^^^^^^ + | + = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated +help: you can use the `?` operator instead + | +LL - Ok(try!(Ok(()))) +LL + Ok(Ok(())?) + | +help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax + | +LL | Ok(r#try!(Ok(()))) + | ++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/deref-non-pointer.rs b/tests/ui/deref-non-pointer.rs new file mode 100644 index 000000000..82ab355e6 --- /dev/null +++ b/tests/ui/deref-non-pointer.rs @@ -0,0 +1,5 @@ +fn main() { + match *1 { //~ ERROR: cannot be dereferenced + _ => { panic!(); } + } +} diff --git a/tests/ui/deref-non-pointer.stderr b/tests/ui/deref-non-pointer.stderr new file mode 100644 index 000000000..1297e496b --- /dev/null +++ b/tests/ui/deref-non-pointer.stderr @@ -0,0 +1,9 @@ +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/deref-non-pointer.rs:2:9 + | +LL | match *1 { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/deref-patterns/basic.rs b/tests/ui/deref-patterns/basic.rs new file mode 100644 index 000000000..249716040 --- /dev/null +++ b/tests/ui/deref-patterns/basic.rs @@ -0,0 +1,17 @@ +// run-pass +// check-run-results +#![feature(string_deref_patterns)] + +fn main() { + test(Some(String::from("42"))); + test(Some(String::new())); + test(None); +} + +fn test(o: Option) { + match o { + Some("42") => println!("the answer"), + Some(_) => println!("something else?"), + None => println!("nil"), + } +} diff --git a/tests/ui/deref-patterns/basic.run.stdout b/tests/ui/deref-patterns/basic.run.stdout new file mode 100644 index 000000000..e50df0582 --- /dev/null +++ b/tests/ui/deref-patterns/basic.run.stdout @@ -0,0 +1,3 @@ +the answer +something else? +nil diff --git a/tests/ui/deref-patterns/default-infer.rs b/tests/ui/deref-patterns/default-infer.rs new file mode 100644 index 000000000..050b84730 --- /dev/null +++ b/tests/ui/deref-patterns/default-infer.rs @@ -0,0 +1,9 @@ +// check-pass +#![feature(string_deref_patterns)] + +fn main() { + match <_ as Default>::default() { + "" => (), + _ => unreachable!(), + } +} diff --git a/tests/ui/deref-patterns/gate.rs b/tests/ui/deref-patterns/gate.rs new file mode 100644 index 000000000..ff50e30de --- /dev/null +++ b/tests/ui/deref-patterns/gate.rs @@ -0,0 +1,7 @@ +// gate-test-string_deref_patterns +fn main() { + match String::new() { + "" | _ => {} + //~^ mismatched types + } +} diff --git a/tests/ui/deref-patterns/gate.stderr b/tests/ui/deref-patterns/gate.stderr new file mode 100644 index 000000000..993468b5e --- /dev/null +++ b/tests/ui/deref-patterns/gate.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/gate.rs:4:9 + | +LL | match String::new() { + | ------------- this expression has type `String` +LL | "" | _ => {} + | ^^ expected struct `String`, found `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/deref-patterns/refs.rs b/tests/ui/deref-patterns/refs.rs new file mode 100644 index 000000000..97e260d27 --- /dev/null +++ b/tests/ui/deref-patterns/refs.rs @@ -0,0 +1,18 @@ +// check-pass +#![feature(string_deref_patterns)] + +fn foo(s: &String) -> i32 { + match *s { + "a" => 42, + _ => -1, + } +} + +fn bar(s: Option<&&&&String>) -> i32 { + match s { + Some(&&&&"&&&&") => 1, + _ => -1, + } +} + +fn main() {} diff --git a/tests/ui/deref-rc.rs b/tests/ui/deref-rc.rs new file mode 100644 index 000000000..9b4c63b19 --- /dev/null +++ b/tests/ui/deref-rc.rs @@ -0,0 +1,8 @@ +// run-pass + +use std::rc::Rc; + +fn main() { + let x = Rc::new([1, 2, 3, 4]); + assert_eq!(*x, [1, 2, 3, 4]); +} diff --git a/tests/ui/deref.rs b/tests/ui/deref.rs new file mode 100644 index 000000000..0d4e08ad9 --- /dev/null +++ b/tests/ui/deref.rs @@ -0,0 +1,7 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let x: Box = Box::new(10); + let _y: isize = *x; +} diff --git a/tests/ui/derive-uninhabited-enum-38885.rs b/tests/ui/derive-uninhabited-enum-38885.rs new file mode 100644 index 000000000..0089453ef --- /dev/null +++ b/tests/ui/derive-uninhabited-enum-38885.rs @@ -0,0 +1,19 @@ +// check-pass +// compile-flags: -Wunused + +// ensure there are no special warnings about uninhabited types +// when deriving Debug on an empty enum + +#[derive(Debug)] +enum Void {} + +#[derive(Debug)] +enum Foo { + Bar(u8), + Void(Void), //~ WARN variant `Void` is never constructed +} + +fn main() { + let x = Foo::Bar(42); + println!("{:?}", x); +} diff --git a/tests/ui/derive-uninhabited-enum-38885.stderr b/tests/ui/derive-uninhabited-enum-38885.stderr new file mode 100644 index 000000000..dcdf8f843 --- /dev/null +++ b/tests/ui/derive-uninhabited-enum-38885.stderr @@ -0,0 +1,14 @@ +warning: variant `Void` is never constructed + --> $DIR/derive-uninhabited-enum-38885.rs:13:5 + | +LL | enum Foo { + | --- variant in this enum +LL | Bar(u8), +LL | Void(Void), + | ^^^^ + | + = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis + = note: `-W dead-code` implied by `-W unused` + +warning: 1 warning emitted + diff --git a/tests/ui/derived-errors/issue-30580.rs b/tests/ui/derived-errors/issue-30580.rs new file mode 100644 index 000000000..6940fcf7c --- /dev/null +++ b/tests/ui/derived-errors/issue-30580.rs @@ -0,0 +1,17 @@ +// Test that we do not see uninformative region-related errors +// when we get some basic type-checking failure. See #30580. + +pub struct Foo { a: u32 } +pub struct Pass<'a, 'tcx: 'a>(&'a mut &'a (), &'a &'tcx ()); + +impl<'a, 'tcx> Pass<'a, 'tcx> +{ + pub fn tcx(&self) -> &'a &'tcx () { self.1 } + fn lol(&mut self, b: &Foo) + { + b.c; //~ ERROR no field `c` on type `&Foo` + self.tcx(); + } +} + +fn main() {} diff --git a/tests/ui/derived-errors/issue-30580.stderr b/tests/ui/derived-errors/issue-30580.stderr new file mode 100644 index 000000000..7bd0eaf77 --- /dev/null +++ b/tests/ui/derived-errors/issue-30580.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `c` on type `&Foo` + --> $DIR/issue-30580.rs:12:11 + | +LL | b.c; + | ^ help: a field with a similar name exists: `a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/derived-errors/issue-31997-1.rs b/tests/ui/derived-errors/issue-31997-1.rs new file mode 100644 index 000000000..90c1b498c --- /dev/null +++ b/tests/ui/derived-errors/issue-31997-1.rs @@ -0,0 +1,56 @@ +// Regression test for this example from #31997 -- main goal is to +// emit as minimal and precise an error set as possible. Ideally, we'd +// only emit the E0433 error below, but right now we emit two. + +use std::io::prelude::*; +// use std::collections::HashMap; +use std::io; + +#[derive(Debug)] +struct Instance { + name: String, + start: Option, + end: Option, +} + +fn main() { + let input = io::stdin(); + let mut input = input.lock(); + + let mut map = HashMap::new(); + //~^ ERROR E0433 + + for line in input.lines() { + let line = line.unwrap(); + println!("process: {}", line); + let mut parts = line.splitn(2, ":"); + let _logfile = parts.next().unwrap(); + let rest = parts.next().unwrap(); + let mut parts = line.split(" [-] "); + + let stamp = parts.next().unwrap(); + + let rest = parts.next().unwrap(); + let words = rest.split_whitespace().collect::>(); + + let instance = words.iter().find(|a| a.starts_with("i-")).unwrap(); + let name = words[1].to_owned(); + let mut entry = map.entry(instance.to_owned()).or_insert(Instance { + name: name, + start: None, + end: None, + }); + + if rest.contains("terminating") { + assert!(entry.end.is_none()); + entry.end = Some(stamp.to_string()); + } + if rest.contains("waiting for") { + assert!(entry.start.is_none()); + entry.start = Some(stamp.to_string()); + } + + } + + println!("{:?}", map); +} diff --git a/tests/ui/derived-errors/issue-31997-1.stderr b/tests/ui/derived-errors/issue-31997-1.stderr new file mode 100644 index 000000000..2f4aabf84 --- /dev/null +++ b/tests/ui/derived-errors/issue-31997-1.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: use of undeclared type `HashMap` + --> $DIR/issue-31997-1.rs:20:19 + | +LL | let mut map = HashMap::new(); + | ^^^^^^^ use of undeclared type `HashMap` + | +help: consider importing this struct + | +LL | use std::collections::HashMap; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/derived-errors/issue-31997.rs b/tests/ui/derived-errors/issue-31997.rs new file mode 100644 index 000000000..ff619313a --- /dev/null +++ b/tests/ui/derived-errors/issue-31997.rs @@ -0,0 +1,18 @@ +// Test that the resolve failure does not lead to downstream type errors. +// See issue #31997. +#![allow(deprecated)] + +trait TheTrait { } + +fn closure(x: F) -> Result + where F: FnMut() -> T, T: TheTrait, +{ + unimplemented!() +} + +fn foo() -> Result<(), ()> { + try!(closure(|| bar(core::ptr::null_mut()))); //~ ERROR cannot find function `bar` in this scope + Ok(()) +} + +fn main() { } diff --git a/tests/ui/derived-errors/issue-31997.stderr b/tests/ui/derived-errors/issue-31997.stderr new file mode 100644 index 000000000..b53c0cda8 --- /dev/null +++ b/tests/ui/derived-errors/issue-31997.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `bar` in this scope + --> $DIR/issue-31997.rs:14:21 + | +LL | try!(closure(|| bar(core::ptr::null_mut()))); + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/derives/auxiliary/derive-marker-tricky.rs b/tests/ui/derives/auxiliary/derive-marker-tricky.rs new file mode 100644 index 000000000..70345351b --- /dev/null +++ b/tests/ui/derives/auxiliary/derive-marker-tricky.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(NoMarker)] +pub fn f(input: TokenStream) -> TokenStream { + if input.to_string().contains("rustc_copy_clone_marker") { + panic!("found `#[rustc_copy_clone_marker]`"); + } + TokenStream::new() +} diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs new file mode 100644 index 000000000..6ab1fb7b0 --- /dev/null +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs @@ -0,0 +1,12 @@ +#![forbid(dead_code)] + +#[derive(Debug)] +pub struct Whatever { + pub field0: (), + field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read + field2: (), + field3: (), + field4: (), +} + +fn main() {} diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr new file mode 100644 index 000000000..7f4f78ceb --- /dev/null +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -0,0 +1,24 @@ +error: fields `field1`, `field2`, `field3`, and `field4` are never read + --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5 + | +LL | pub struct Whatever { + | -------- fields in this struct +LL | pub field0: (), +LL | field1: (), + | ^^^^^^ +LL | field2: (), + | ^^^^^^ +LL | field3: (), + | ^^^^^^ +LL | field4: (), + | ^^^^^^ + | + = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis +note: the lint level is defined here + --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11 + | +LL | #![forbid(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/derives/clone-debug-dead-code.rs b/tests/ui/derives/clone-debug-dead-code.rs new file mode 100644 index 000000000..ab49260c0 --- /dev/null +++ b/tests/ui/derives/clone-debug-dead-code.rs @@ -0,0 +1,45 @@ +// Checks that derived implementations of Clone and Debug do not +// contribute to dead code analysis (issue #84647). + +#![forbid(dead_code)] + +struct A { f: () } +//~^ ERROR: field `f` is never read + +#[derive(Clone)] +struct B { f: () } +//~^ ERROR: field `f` is never read + +#[derive(Debug)] +struct C { f: () } +//~^ ERROR: field `f` is never read + +#[derive(Debug,Clone)] +struct D { f: () } +//~^ ERROR: field `f` is never read + +struct E { f: () } +//~^ ERROR: field `f` is never read +// Custom impl, still doesn't read f +impl Clone for E { + fn clone(&self) -> Self { + Self { f: () } + } +} + +struct F { f: () } +// Custom impl that actually reads f +impl Clone for F { + fn clone(&self) -> Self { + Self { f: self.f } + } +} + +fn main() { + let _ = A { f: () }; + let _ = B { f: () }; + let _ = C { f: () }; + let _ = D { f: () }; + let _ = E { f: () }; + let _ = F { f: () }; +} diff --git a/tests/ui/derives/clone-debug-dead-code.stderr b/tests/ui/derives/clone-debug-dead-code.stderr new file mode 100644 index 000000000..38be486e3 --- /dev/null +++ b/tests/ui/derives/clone-debug-dead-code.stderr @@ -0,0 +1,54 @@ +error: field `f` is never read + --> $DIR/clone-debug-dead-code.rs:6:12 + | +LL | struct A { f: () } + | - ^ + | | + | field in this struct + | +note: the lint level is defined here + --> $DIR/clone-debug-dead-code.rs:4:11 + | +LL | #![forbid(dead_code)] + | ^^^^^^^^^ + +error: field `f` is never read + --> $DIR/clone-debug-dead-code.rs:10:12 + | +LL | struct B { f: () } + | - ^ + | | + | field in this struct + | + = note: `B` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis + +error: field `f` is never read + --> $DIR/clone-debug-dead-code.rs:14:12 + | +LL | struct C { f: () } + | - ^ + | | + | field in this struct + | + = note: `C` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis + +error: field `f` is never read + --> $DIR/clone-debug-dead-code.rs:18:12 + | +LL | struct D { f: () } + | - ^ + | | + | field in this struct + | + = note: `D` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis + +error: field `f` is never read + --> $DIR/clone-debug-dead-code.rs:21:12 + | +LL | struct E { f: () } + | - ^ + | | + | field in this struct + +error: aborting due to 5 previous errors + diff --git a/tests/ui/derives/derive-Debug-use-ufcs-struct.rs b/tests/ui/derives/derive-Debug-use-ufcs-struct.rs new file mode 100644 index 000000000..cb9dda841 --- /dev/null +++ b/tests/ui/derives/derive-Debug-use-ufcs-struct.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(warnings)] + +#[derive(Debug)] +pub struct Bar { pub t: () } + +impl Access for T {} +pub trait Access { + fn field(&self, _: impl Sized, _: impl Sized) { + panic!("got into Access::field"); + } + + fn finish(&self) -> Result<(), std::fmt::Error> { + panic!("got into Access::finish"); + } + + fn debug_struct(&self, _: impl Sized, _: impl Sized) { + panic!("got into Access::debug_struct"); + } +} + +impl MutAccess for T {} +pub trait MutAccess { + fn field(&mut self, _: impl Sized, _: impl Sized) { + panic!("got into MutAccess::field"); + } + + fn finish(&mut self) -> Result<(), std::fmt::Error> { + panic!("got into MutAccess::finish"); + } + + fn debug_struct(&mut self, _: impl Sized, _: impl Sized) { + panic!("got into MutAccess::debug_struct"); + } +} + +fn main() { + let bar = Bar { t: () }; + assert_eq!("Bar { t: () }", format!("{:?}", bar)); +} diff --git a/tests/ui/derives/derive-Debug-use-ufcs-tuple.rs b/tests/ui/derives/derive-Debug-use-ufcs-tuple.rs new file mode 100644 index 000000000..5f786769f --- /dev/null +++ b/tests/ui/derives/derive-Debug-use-ufcs-tuple.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(warnings)] + +#[derive(Debug)] +pub struct Foo(pub T); + +use std::fmt; + +impl Field for T {} +impl Finish for T {} +impl Dt for &mut fmt::Formatter<'_> {} + +pub trait Field { + fn field(&self, _: impl Sized) { + panic!("got into field"); + } +} +pub trait Finish { + fn finish(&self) -> Result<(), std::fmt::Error> { + panic!("got into finish"); + } +} +pub trait Dt { + fn debug_tuple(&self, _: &str) { + panic!("got into debug_tuple"); + } +} + +fn main() { + let foo = Foo(()); + assert_eq!("Foo(())", format!("{:?}", foo)); +} diff --git a/tests/ui/derives/derive-assoc-type-not-impl.rs b/tests/ui/derives/derive-assoc-type-not-impl.rs new file mode 100644 index 000000000..0f642d63a --- /dev/null +++ b/tests/ui/derives/derive-assoc-type-not-impl.rs @@ -0,0 +1,19 @@ +trait Foo { + type X; + fn method(&self) {} +} + +#[derive(Clone)] +struct Bar { + x: T::X, +} + +struct NotClone; + +impl Foo for NotClone { + type X = i8; +} + +fn main() { + Bar:: { x: 1 }.clone(); //~ ERROR +} diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr new file mode 100644 index 000000000..91b334b41 --- /dev/null +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -0,0 +1,31 @@ +error[E0599]: the method `clone` exists for struct `Bar`, but its trait bounds were not satisfied + --> $DIR/derive-assoc-type-not-impl.rs:18:30 + | +LL | struct Bar { + | ------------------ + | | + | method `clone` not found for this struct + | doesn't satisfy `Bar: Clone` +... +LL | struct NotClone; + | --------------- doesn't satisfy `NotClone: Clone` +... +LL | Bar:: { x: 1 }.clone(); + | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds + | +note: trait bound `NotClone: Clone` was not satisfied + --> $DIR/derive-assoc-type-not-impl.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/derives/derive-deadlock.rs b/tests/ui/derives/derive-deadlock.rs new file mode 100644 index 000000000..0137b1e5b --- /dev/null +++ b/tests/ui/derives/derive-deadlock.rs @@ -0,0 +1,6 @@ +use std as derive; + +#[derive(Default)] //~ ERROR cannot determine resolution for the attribute macro `derive` +struct S; + +fn main() {} diff --git a/tests/ui/derives/derive-deadlock.stderr b/tests/ui/derives/derive-deadlock.stderr new file mode 100644 index 000000000..8d062491c --- /dev/null +++ b/tests/ui/derives/derive-deadlock.stderr @@ -0,0 +1,10 @@ +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/derive-deadlock.rs:3:3 + | +LL | #[derive(Default)] + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to previous error + diff --git a/tests/ui/derives/derive-hygiene.rs b/tests/ui/derives/derive-hygiene.rs new file mode 100644 index 000000000..4fa83c490 --- /dev/null +++ b/tests/ui/derives/derive-hygiene.rs @@ -0,0 +1,121 @@ +// Make sure that built-in derives don't rely on the user not declaring certain +// names to work properly. + +// check-pass + +#![allow(nonstandard_style)] +#![feature(decl_macro)] + +use std::prelude::v1::test as inline; + +static f: () = (); +static cmp: () = (); +static other: () = (); +static state: () = (); +static __self_0_0: () = (); +static __self_1_0: () = (); +static __self_vi: () = (); +static __arg_1_0: () = (); +static debug_trait_builder: () = (); + +struct isize; +trait i16 {} + +trait MethodsInDerives: Sized { + fn debug_tuple(self) {} + fn debug_struct(self) {} + fn field(self) {} + fn finish(self) {} + fn clone(self) {} + fn cmp(self) {} + fn partial_cmp(self) {} + fn eq(self) {} + fn ne(self) {} + fn le(self) {} + fn lt(self) {} + fn ge(self) {} + fn gt(self) {} + fn hash(self) {} +} + +trait GenericAny {} +impl GenericAny for S {} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum __H { V(i32), } + +#[repr(i16)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum W { A, B } + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] +struct X>> { + A: A, +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] +struct Y(B) +where + B: From; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum Z { + C(C), + B { C: C }, +} + +// Make sure that we aren't using `self::` in paths, since it doesn't work in +// non-module scopes. +const NON_MODULE: () = { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum __H { V(i32), } + + #[repr(i16)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum W { A, B } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct X self::X> { + A: A, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct Y(B) + where + B: From; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum Z { + C(C), + B { C: C }, + } +}; + +macro m() { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum __H { V(i32), } + + #[repr(i16)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum W { A, B } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct X>> { + A: A, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct Y(B) + where + B: From; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum Z { + C(C), + B { C: C }, + } +} + +m!(); + +fn main() {} diff --git a/tests/ui/derives/derive-macro-const-default.rs b/tests/ui/derives/derive-macro-const-default.rs new file mode 100644 index 000000000..ce80271d2 --- /dev/null +++ b/tests/ui/derives/derive-macro-const-default.rs @@ -0,0 +1,11 @@ +// check-pass +#[derive(Clone, PartialEq, Debug)] +struct Example([T; N]); + +fn main() { + let a = Example([(); 16]); + let b = a.clone(); + if a != b { + let _c = format!("{:?}", a); + } +} diff --git a/tests/ui/derives/derive-marker-tricky.rs b/tests/ui/derives/derive-marker-tricky.rs new file mode 100644 index 000000000..730ea4714 --- /dev/null +++ b/tests/ui/derives/derive-marker-tricky.rs @@ -0,0 +1,16 @@ +// Test that `#[rustc_copy_clone_marker]` is not injected when a user-defined derive shadows +// a built-in derive in non-trivial scope (e.g. in a nested module). + +// check-pass +// aux-build:derive-marker-tricky.rs + +extern crate derive_marker_tricky; + +mod m { + use derive_marker_tricky::NoMarker as Copy; + + #[derive(Copy)] + struct S; +} + +fn main() {} diff --git a/tests/ui/derives/derive-multiple-with-packed.rs b/tests/ui/derives/derive-multiple-with-packed.rs new file mode 100644 index 000000000..e762ee357 --- /dev/null +++ b/tests/ui/derives/derive-multiple-with-packed.rs @@ -0,0 +1,10 @@ +// check-pass + +#[derive(Clone, Copy)] +#[derive(Debug)] // OK, even if `Copy` is in the different `#[derive]` +#[repr(packed)] +struct CacheRecordHeader { + field: u64, +} + +fn main() {} diff --git a/tests/ui/derives/derive-on-trait-item-or-impl-item.rs b/tests/ui/derives/derive-on-trait-item-or-impl-item.rs new file mode 100644 index 000000000..7e579ec22 --- /dev/null +++ b/tests/ui/derives/derive-on-trait-item-or-impl-item.rs @@ -0,0 +1,15 @@ +trait Foo { + #[derive(Clone)] + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + type Bar; +} + +struct Bar; + +impl Bar { + #[derive(Clone)] + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + fn bar(&self) {} +} + +fn main() {} diff --git a/tests/ui/derives/derive-on-trait-item-or-impl-item.stderr b/tests/ui/derives/derive-on-trait-item-or-impl-item.stderr new file mode 100644 index 000000000..1fd97bdd5 --- /dev/null +++ b/tests/ui/derives/derive-on-trait-item-or-impl-item.stderr @@ -0,0 +1,21 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/derive-on-trait-item-or-impl-item.rs:2:5 + | +LL | #[derive(Clone)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | type Bar; + | --------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/derive-on-trait-item-or-impl-item.rs:10:5 + | +LL | #[derive(Clone)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | fn bar(&self) {} + | ---------------- not a `struct`, `enum` or `union` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/derives/derive-partial-ord.rs b/tests/ui/derives/derive-partial-ord.rs new file mode 100644 index 000000000..9078a7ffa --- /dev/null +++ b/tests/ui/derives/derive-partial-ord.rs @@ -0,0 +1,60 @@ +// Checks that in a derived implementation of PartialOrd the lt, le, ge, gt methods are consistent +// with partial_cmp. Also verifies that implementation is consistent with that for tuples. +// +// run-pass + +#[derive(PartialEq, PartialOrd)] +struct P(f64, f64); + +fn main() { + let values: &[f64] = &[1.0, 2.0, f64::NAN]; + for a in values { + for b in values { + for c in values { + for d in values { + // Check impl for a tuple. + check(&(*a, *b), &(*c, *d)); + + // Check derived impl. + check(&P(*a, *b), &P(*c, *d)); + + // Check that impls agree with each other. + assert_eq!( + PartialOrd::partial_cmp(&(*a, *b), &(*c, *d)), + PartialOrd::partial_cmp(&P(*a, *b), &P(*c, *d)), + ); + } + } + } + } +} + +fn check(a: &T, b: &T) { + use std::cmp::Ordering::*; + match PartialOrd::partial_cmp(a, b) { + None => { + assert!(!(a < b)); + assert!(!(a <= b)); + assert!(!(a > b)); + assert!(!(a >= b)); + } + Some(Equal) => { + assert!(!(a < b)); + assert!(a <= b); + assert!(!(a > b)); + assert!(a >= b); + } + Some(Less) => { + assert!(a < b); + assert!(a <= b); + assert!(!(a > b)); + assert!(!(a >= b)); + } + Some(Greater) => { + assert!(!(a < b)); + assert!(!(a <= b)); + assert!(a > b); + assert!(a >= b); + } + } +} diff --git a/tests/ui/derives/derive-renamed.rs b/tests/ui/derives/derive-renamed.rs new file mode 100644 index 000000000..d310e5806 --- /dev/null +++ b/tests/ui/derives/derive-renamed.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2018 + +use derive as my_derive; + +#[my_derive(Debug)] +struct S; + +fn main() { + println!("{:?}", S); // OK +} diff --git a/tests/ui/derives/derives-span-Clone-enum-struct-variant.rs b/tests/ui/derives/derives-span-Clone-enum-struct-variant.rs new file mode 100644 index 000000000..b556d4424 --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Clone)] +enum Enum { + A { + x: Error //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr new file mode 100644 index 000000000..7326324b0 --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Clone` is not satisfied + --> $DIR/derives-span-Clone-enum-struct-variant.rs:9:6 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ the trait `Clone` is not implemented for `Error` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Clone-enum.rs b/tests/ui/derives/derives-span-Clone-enum.rs new file mode 100644 index 000000000..9bb4f486c --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-enum.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Clone)] +enum Enum { + A( + Error //~ ERROR + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Clone-enum.stderr b/tests/ui/derives/derives-span-Clone-enum.stderr new file mode 100644 index 000000000..229a4f7d9 --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-enum.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Clone` is not satisfied + --> $DIR/derives-span-Clone-enum.rs:9:6 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +... +LL | Error + | ^^^^^ the trait `Clone` is not implemented for `Error` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Clone-struct.rs b/tests/ui/derives/derives-span-Clone-struct.rs new file mode 100644 index 000000000..f151636f8 --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Clone)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Clone-struct.stderr b/tests/ui/derives/derives-span-Clone-struct.stderr new file mode 100644 index 000000000..96bad9eda --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Clone` is not satisfied + --> $DIR/derives-span-Clone-struct.rs:8:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ the trait `Clone` is not implemented for `Error` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Clone-tuple-struct.rs b/tests/ui/derives/derives-span-Clone-tuple-struct.rs new file mode 100644 index 000000000..7a6288532 --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Clone)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-Clone-tuple-struct.stderr b/tests/ui/derives/derives-span-Clone-tuple-struct.stderr new file mode 100644 index 000000000..b61341e57 --- /dev/null +++ b/tests/ui/derives/derives-span-Clone-tuple-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Clone` is not satisfied + --> $DIR/derives-span-Clone-tuple-struct.rs:8:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ the trait `Clone` is not implemented for `Error` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.rs b/tests/ui/derives/derives-span-Debug-enum-struct-variant.rs new file mode 100644 index 000000000..949597bc8 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Debug)] +enum Enum { + A { + x: Error //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr new file mode 100644 index 000000000..58a64a4f5 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Error` doesn't implement `Debug` + --> $DIR/derives-span-Debug-enum-struct-variant.rs:9:6 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ `Error` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `Error` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-enum.rs b/tests/ui/derives/derives-span-Debug-enum.rs new file mode 100644 index 000000000..b2a39708c --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-enum.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Debug)] +enum Enum { + A( + Error //~ ERROR + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr new file mode 100644 index 000000000..e9bb5f960 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-enum.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Error` doesn't implement `Debug` + --> $DIR/derives-span-Debug-enum.rs:9:6 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +... +LL | Error + | ^^^^^ `Error` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `Error` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-struct.rs b/tests/ui/derives/derives-span-Debug-struct.rs new file mode 100644 index 000000000..cf91c9436 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Debug)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr new file mode 100644 index 000000000..0a117c060 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-struct.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Error` doesn't implement `Debug` + --> $DIR/derives-span-Debug-struct.rs:8:5 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ `Error` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `Error` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.rs b/tests/ui/derives/derives-span-Debug-tuple-struct.rs new file mode 100644 index 000000000..cea973c91 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Debug)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr new file mode 100644 index 000000000..f2e90a418 --- /dev/null +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Error` doesn't implement `Debug` + --> $DIR/derives-span-Debug-tuple-struct.rs:8:5 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ `Error` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `Error` + = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Default-struct.rs b/tests/ui/derives/derives-span-Default-struct.rs new file mode 100644 index 000000000..71fd5829e --- /dev/null +++ b/tests/ui/derives/derives-span-Default-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Default)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Default-struct.stderr b/tests/ui/derives/derives-span-Default-struct.stderr new file mode 100644 index 000000000..d4affd535 --- /dev/null +++ b/tests/ui/derives/derives-span-Default-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Default` is not satisfied + --> $DIR/derives-span-Default-struct.rs:8:5 + | +LL | #[derive(Default)] + | ------- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ the trait `Default` is not implemented for `Error` + | + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Default-tuple-struct.rs b/tests/ui/derives/derives-span-Default-tuple-struct.rs new file mode 100644 index 000000000..463f7d230 --- /dev/null +++ b/tests/ui/derives/derives-span-Default-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Default)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-Default-tuple-struct.stderr b/tests/ui/derives/derives-span-Default-tuple-struct.stderr new file mode 100644 index 000000000..129351f59 --- /dev/null +++ b/tests/ui/derives/derives-span-Default-tuple-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Default` is not satisfied + --> $DIR/derives-span-Default-tuple-struct.rs:8:5 + | +LL | #[derive(Default)] + | ------- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ the trait `Default` is not implemented for `Error` + | + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-enum-struct-variant.rs b/tests/ui/derives/derives-span-Eq-enum-struct-variant.rs new file mode 100644 index 000000000..d2dab8687 --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(Eq,PartialEq)] +enum Enum { + A { + x: Error //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr new file mode 100644 index 000000000..2be69a30b --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `Error: Eq` is not satisfied + --> $DIR/derives-span-Eq-enum-struct-variant.rs:9:6 + | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ the trait `Eq` is not implemented for `Error` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-enum.rs b/tests/ui/derives/derives-span-Eq-enum.rs new file mode 100644 index 000000000..c6c0d4321 --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-enum.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(Eq,PartialEq)] +enum Enum { + A( + Error //~ ERROR + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Eq-enum.stderr b/tests/ui/derives/derives-span-Eq-enum.stderr new file mode 100644 index 000000000..4f4f821cc --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-enum.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `Error: Eq` is not satisfied + --> $DIR/derives-span-Eq-enum.rs:9:6 + | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +... +LL | Error + | ^^^^^ the trait `Eq` is not implemented for `Error` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-struct.rs b/tests/ui/derives/derives-span-Eq-struct.rs new file mode 100644 index 000000000..df3100398 --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(Eq,PartialEq)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Eq-struct.stderr b/tests/ui/derives/derives-span-Eq-struct.stderr new file mode 100644 index 000000000..f15659c3e --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-struct.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `Error: Eq` is not satisfied + --> $DIR/derives-span-Eq-struct.rs:8:5 + | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ the trait `Eq` is not implemented for `Error` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Eq-tuple-struct.rs b/tests/ui/derives/derives-span-Eq-tuple-struct.rs new file mode 100644 index 000000000..abf6526b9 --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(Eq,PartialEq)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-Eq-tuple-struct.stderr b/tests/ui/derives/derives-span-Eq-tuple-struct.stderr new file mode 100644 index 000000000..4e5659b35 --- /dev/null +++ b/tests/ui/derives/derives-span-Eq-tuple-struct.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `Error: Eq` is not satisfied + --> $DIR/derives-span-Eq-tuple-struct.rs:8:5 + | +LL | #[derive(Eq,PartialEq)] + | -- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ the trait `Eq` is not implemented for `Error` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-enum-struct-variant.rs b/tests/ui/derives/derives-span-Hash-enum-struct-variant.rs new file mode 100644 index 000000000..3018a7b6d --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Hash)] +enum Enum { + A { + x: Error //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr new file mode 100644 index 000000000..fe5e0e96a --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Hash` is not satisfied + --> $DIR/derives-span-Hash-enum-struct-variant.rs:9:6 + | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ the trait `Hash` is not implemented for `Error` + | + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-enum.rs b/tests/ui/derives/derives-span-Hash-enum.rs new file mode 100644 index 000000000..8ce7df18f --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-enum.rs @@ -0,0 +1,12 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +struct Error; + +#[derive(Hash)] +enum Enum { + A( + Error //~ ERROR + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Hash-enum.stderr b/tests/ui/derives/derives-span-Hash-enum.stderr new file mode 100644 index 000000000..99785b87c --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-enum.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Hash` is not satisfied + --> $DIR/derives-span-Hash-enum.rs:8:6 + | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +... +LL | Error + | ^^^^^ the trait `Hash` is not implemented for `Error` + | + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-struct.rs b/tests/ui/derives/derives-span-Hash-struct.rs new file mode 100644 index 000000000..fa5e2af6b --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Hash)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Hash-struct.stderr b/tests/ui/derives/derives-span-Hash-struct.stderr new file mode 100644 index 000000000..4db83dd13 --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Hash` is not satisfied + --> $DIR/derives-span-Hash-struct.rs:8:5 + | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ the trait `Hash` is not implemented for `Error` + | + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Hash-tuple-struct.rs b/tests/ui/derives/derives-span-Hash-tuple-struct.rs new file mode 100644 index 000000000..3822bce14 --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(Hash)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-Hash-tuple-struct.stderr b/tests/ui/derives/derives-span-Hash-tuple-struct.stderr new file mode 100644 index 000000000..8660c97e6 --- /dev/null +++ b/tests/ui/derives/derives-span-Hash-tuple-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Hash` is not satisfied + --> $DIR/derives-span-Hash-tuple-struct.rs:8:5 + | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ the trait `Hash` is not implemented for `Error` + | + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-enum-struct-variant.rs b/tests/ui/derives/derives-span-Ord-enum-struct-variant.rs new file mode 100644 index 000000000..62355cc2d --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(Eq,PartialOrd,PartialEq)] +struct Error; + +#[derive(Ord,Eq,PartialOrd,PartialEq)] +enum Enum { + A { + x: Error //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr new file mode 100644 index 000000000..6e48332c2 --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Ord` is not satisfied + --> $DIR/derives-span-Ord-enum-struct-variant.rs:9:6 + | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ the trait `Ord` is not implemented for `Error` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-enum.rs b/tests/ui/derives/derives-span-Ord-enum.rs new file mode 100644 index 000000000..72738931d --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-enum.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(Eq,PartialOrd,PartialEq)] +struct Error; + +#[derive(Ord,Eq,PartialOrd,PartialEq)] +enum Enum { + A( + Error //~ ERROR + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Ord-enum.stderr b/tests/ui/derives/derives-span-Ord-enum.stderr new file mode 100644 index 000000000..b05cf0a05 --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-enum.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Ord` is not satisfied + --> $DIR/derives-span-Ord-enum.rs:9:6 + | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +... +LL | Error + | ^^^^^ the trait `Ord` is not implemented for `Error` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-struct.rs b/tests/ui/derives/derives-span-Ord-struct.rs new file mode 100644 index 000000000..53d4c2c22 --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(Eq,PartialOrd,PartialEq)] +struct Error; + +#[derive(Ord,Eq,PartialOrd,PartialEq)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-Ord-struct.stderr b/tests/ui/derives/derives-span-Ord-struct.stderr new file mode 100644 index 000000000..c4def34a8 --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Ord` is not satisfied + --> $DIR/derives-span-Ord-struct.rs:8:5 + | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ the trait `Ord` is not implemented for `Error` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-Ord-tuple-struct.rs b/tests/ui/derives/derives-span-Ord-tuple-struct.rs new file mode 100644 index 000000000..4e09c2709 --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(Eq,PartialOrd,PartialEq)] +struct Error; + +#[derive(Ord,Eq,PartialOrd,PartialEq)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr new file mode 100644 index 000000000..a3b288d0f --- /dev/null +++ b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Error: Ord` is not satisfied + --> $DIR/derives-span-Ord-tuple-struct.rs:8:5 + | +LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] + | --- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ the trait `Ord` is not implemented for `Error` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.rs b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.rs new file mode 100644 index 000000000..67a27729d --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(PartialEq)] +enum Enum { + A { + x: Error //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr new file mode 100644 index 000000000..9953154fd --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -0,0 +1,23 @@ +error[E0369]: binary operation `==` cannot be applied to type `Error` + --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ + | +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `PartialEq<_>` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialEq-enum.rs b/tests/ui/derives/derives-span-PartialEq-enum.rs new file mode 100644 index 000000000..0becc7e0d --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-enum.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(PartialEq)] +enum Enum { + A( + Error //~ ERROR + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialEq-enum.stderr b/tests/ui/derives/derives-span-PartialEq-enum.stderr new file mode 100644 index 000000000..7c1304523 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-enum.stderr @@ -0,0 +1,23 @@ +error[E0369]: binary operation `==` cannot be applied to type `Error` + --> $DIR/derives-span-PartialEq-enum.rs:9:6 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +... +LL | Error + | ^^^^^ + | +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-enum.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `PartialEq<_>` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialEq-struct.rs b/tests/ui/derives/derives-span-PartialEq-struct.rs new file mode 100644 index 000000000..c92ef5fad --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(PartialEq)] +struct Struct { + x: Error //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialEq-struct.stderr b/tests/ui/derives/derives-span-PartialEq-struct.stderr new file mode 100644 index 000000000..ba3d6ced3 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-struct.stderr @@ -0,0 +1,23 @@ +error[E0369]: binary operation `==` cannot be applied to type `Error` + --> $DIR/derives-span-PartialEq-struct.rs:8:5 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ + | +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `PartialEq<_>` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialEq-tuple-struct.rs b/tests/ui/derives/derives-span-PartialEq-tuple-struct.rs new file mode 100644 index 000000000..10ac347aa --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + + +struct Error; + +#[derive(PartialEq)] +struct Struct( + Error //~ ERROR +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr new file mode 100644 index 000000000..ab0b56a9e --- /dev/null +++ b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -0,0 +1,23 @@ +error[E0369]: binary operation `==` cannot be applied to type `Error` + --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ + | +note: an implementation of `PartialEq<_>` might be missing for `Error` + --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1 + | +LL | struct Error; + | ^^^^^^^^^^^^ must implement `PartialEq<_>` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs new file mode 100644 index 000000000..a769c1376 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(PartialOrd,PartialEq)] +enum Enum { + A { + x: Error //~ ERROR can't compare `Error` with `Error` + } +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr new file mode 100644 index 000000000..2d19aaf68 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr @@ -0,0 +1,19 @@ +error[E0277]: can't compare `Error` with `Error` + --> $DIR/derives-span-PartialOrd-enum-struct-variant.rs:9:6 + | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +... +LL | x: Error + | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` + | + = help: the trait `PartialOrd` is not implemented for `Error` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialOrd-enum.rs b/tests/ui/derives/derives-span-PartialOrd-enum.rs new file mode 100644 index 000000000..4f0d794e4 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-enum.rs @@ -0,0 +1,13 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(PartialOrd,PartialEq)] +enum Enum { + A( + Error //~ ERROR can't compare `Error` with `Error` + ) +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialOrd-enum.stderr b/tests/ui/derives/derives-span-PartialOrd-enum.stderr new file mode 100644 index 000000000..dfbb8060f --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-enum.stderr @@ -0,0 +1,19 @@ +error[E0277]: can't compare `Error` with `Error` + --> $DIR/derives-span-PartialOrd-enum.rs:9:6 + | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +... +LL | Error + | ^^^^^ no implementation for `Error < Error` and `Error > Error` + | + = help: the trait `PartialOrd` is not implemented for `Error` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialOrd-struct.rs b/tests/ui/derives/derives-span-PartialOrd-struct.rs new file mode 100644 index 000000000..da857c674 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(PartialOrd,PartialEq)] +struct Struct { + x: Error //~ ERROR can't compare `Error` with `Error` +} + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialOrd-struct.stderr b/tests/ui/derives/derives-span-PartialOrd-struct.stderr new file mode 100644 index 000000000..ba63d86e8 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-struct.stderr @@ -0,0 +1,19 @@ +error[E0277]: can't compare `Error` with `Error` + --> $DIR/derives-span-PartialOrd-struct.rs:8:5 + | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +LL | struct Struct { +LL | x: Error + | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` + | + = help: the trait `PartialOrd` is not implemented for `Error` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/derives-span-PartialOrd-tuple-struct.rs b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.rs new file mode 100644 index 000000000..61d507670 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.rs @@ -0,0 +1,11 @@ +// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' + +#[derive(PartialEq)] +struct Error; + +#[derive(PartialOrd,PartialEq)] +struct Struct( + Error //~ ERROR can't compare `Error` with `Error` +); + +fn main() {} diff --git a/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr new file mode 100644 index 000000000..7686ed806 --- /dev/null +++ b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr @@ -0,0 +1,19 @@ +error[E0277]: can't compare `Error` with `Error` + --> $DIR/derives-span-PartialOrd-tuple-struct.rs:8:5 + | +LL | #[derive(PartialOrd,PartialEq)] + | ---------- in this derive macro expansion +LL | struct Struct( +LL | Error + | ^^^^^ no implementation for `Error < Error` and `Error > Error` + | + = help: the trait `PartialOrd` is not implemented for `Error` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Error` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialOrd)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/deriving-bounds.rs b/tests/ui/derives/deriving-bounds.rs new file mode 100644 index 000000000..95d440420 --- /dev/null +++ b/tests/ui/derives/deriving-bounds.rs @@ -0,0 +1,11 @@ +#[derive(Send)] +//~^ ERROR cannot find derive macro `Send` in this scope +//~| ERROR cannot find derive macro `Send` in this scope +struct Test; + +#[derive(Sync)] +//~^ ERROR cannot find derive macro `Sync` in this scope +//~| ERROR cannot find derive macro `Sync` in this scope +struct Test1; + +pub fn main() {} diff --git a/tests/ui/derives/deriving-bounds.stderr b/tests/ui/derives/deriving-bounds.stderr new file mode 100644 index 000000000..74ca37287 --- /dev/null +++ b/tests/ui/derives/deriving-bounds.stderr @@ -0,0 +1,50 @@ +error: cannot find derive macro `Sync` in this scope + --> $DIR/deriving-bounds.rs:6:10 + | +LL | #[derive(Sync)] + | ^^^^ + | +note: unsafe traits like `Sync` should be implemented explicitly + --> $DIR/deriving-bounds.rs:6:10 + | +LL | #[derive(Sync)] + | ^^^^ + +error: cannot find derive macro `Sync` in this scope + --> $DIR/deriving-bounds.rs:6:10 + | +LL | #[derive(Sync)] + | ^^^^ + | +note: unsafe traits like `Sync` should be implemented explicitly + --> $DIR/deriving-bounds.rs:6:10 + | +LL | #[derive(Sync)] + | ^^^^ + +error: cannot find derive macro `Send` in this scope + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + | +note: unsafe traits like `Send` should be implemented explicitly + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + +error: cannot find derive macro `Send` in this scope + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + | +note: unsafe traits like `Send` should be implemented explicitly + --> $DIR/deriving-bounds.rs:1:10 + | +LL | #[derive(Send)] + | ^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/derives/deriving-copyclone.rs b/tests/ui/derives/deriving-copyclone.rs new file mode 100644 index 000000000..06b3157a7 --- /dev/null +++ b/tests/ui/derives/deriving-copyclone.rs @@ -0,0 +1,37 @@ +// this will get a no-op Clone impl +#[derive(Copy, Clone)] +struct A { + a: i32, + b: i64 +} + +// this will get a deep Clone impl +#[derive(Copy, Clone)] +struct B { + a: i32, + b: T +} + +struct C; // not Copy or Clone +#[derive(Clone)] struct D; // Clone but not Copy + +fn is_copy(_: T) {} +fn is_clone(_: T) {} + +fn main() { + // A can be copied and cloned + is_copy(A { a: 1, b: 2 }); + is_clone(A { a: 1, b: 2 }); + + // B can be copied and cloned + is_copy(B { a: 1, b: 2 }); + is_clone(B { a: 1, b: 2 }); + + // B cannot be copied or cloned + is_copy(B { a: 1, b: C }); //~ ERROR Copy + is_clone(B { a: 1, b: C }); //~ ERROR Clone + + // B can be cloned but not copied + is_copy(B { a: 1, b: D }); //~ ERROR Copy + is_clone(B { a: 1, b: D }); +} diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr new file mode 100644 index 000000000..9c4ca01ff --- /dev/null +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -0,0 +1,75 @@ +error[E0277]: the trait bound `B: Copy` is not satisfied + --> $DIR/deriving-copyclone.rs:31:13 + | +LL | is_copy(B { a: 1, b: C }); + | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B` + | | + | required by a bound introduced by this call + | +note: required for `B` to implement `Copy` + --> $DIR/deriving-copyclone.rs:9:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `is_copy` + --> $DIR/deriving-copyclone.rs:18:15 + | +LL | fn is_copy(_: T) {} + | ^^^^ required by this bound in `is_copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | is_copy(&B { a: 1, b: C }); + | + + +error[E0277]: the trait bound `B: Clone` is not satisfied + --> $DIR/deriving-copyclone.rs:32:14 + | +LL | is_clone(B { a: 1, b: C }); + | -------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | | + | required by a bound introduced by this call + | +note: required for `B` to implement `Clone` + --> $DIR/deriving-copyclone.rs:9:16 + | +LL | #[derive(Copy, Clone)] + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `is_clone` + --> $DIR/deriving-copyclone.rs:19:16 + | +LL | fn is_clone(_: T) {} + | ^^^^^ required by this bound in `is_clone` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | is_clone(&B { a: 1, b: C }); + | + + +error[E0277]: the trait bound `B: Copy` is not satisfied + --> $DIR/deriving-copyclone.rs:35:13 + | +LL | is_copy(B { a: 1, b: D }); + | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B` + | | + | required by a bound introduced by this call + | +note: required for `B` to implement `Copy` + --> $DIR/deriving-copyclone.rs:9:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `is_copy` + --> $DIR/deriving-copyclone.rs:18:15 + | +LL | fn is_copy(_: T) {} + | ^^^^ required by this bound in `is_copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider borrowing here + | +LL | is_copy(&B { a: 1, b: D }); + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/deriving-meta-empty-trait-list.rs b/tests/ui/derives/deriving-meta-empty-trait-list.rs new file mode 100644 index 000000000..0306ce717 --- /dev/null +++ b/tests/ui/derives/deriving-meta-empty-trait-list.rs @@ -0,0 +1,8 @@ +// check-pass + +#![deny(unused)] + +#[derive()] // OK +struct _Bar; + +pub fn main() {} diff --git a/tests/ui/derives/deriving-meta-unknown-trait.rs b/tests/ui/derives/deriving-meta-unknown-trait.rs new file mode 100644 index 000000000..6463a7664 --- /dev/null +++ b/tests/ui/derives/deriving-meta-unknown-trait.rs @@ -0,0 +1,6 @@ +#[derive(Eqr)] +//~^ ERROR cannot find derive macro `Eqr` in this scope +//~| ERROR cannot find derive macro `Eqr` in this scope +struct Foo; + +pub fn main() {} diff --git a/tests/ui/derives/deriving-meta-unknown-trait.stderr b/tests/ui/derives/deriving-meta-unknown-trait.stderr new file mode 100644 index 000000000..053d34f68 --- /dev/null +++ b/tests/ui/derives/deriving-meta-unknown-trait.stderr @@ -0,0 +1,20 @@ +error: cannot find derive macro `Eqr` in this scope + --> $DIR/deriving-meta-unknown-trait.rs:1:10 + | +LL | #[derive(Eqr)] + | ^^^ help: a derive macro with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named derive macro `Eq` defined here + +error: cannot find derive macro `Eqr` in this scope + --> $DIR/deriving-meta-unknown-trait.rs:1:10 + | +LL | #[derive(Eqr)] + | ^^^ help: a derive macro with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named derive macro `Eq` defined here + +error: aborting due to 2 previous errors + diff --git a/tests/ui/derives/deriving-no-inner-impl-error-message.rs b/tests/ui/derives/deriving-no-inner-impl-error-message.rs new file mode 100644 index 000000000..b3ce31bf0 --- /dev/null +++ b/tests/ui/derives/deriving-no-inner-impl-error-message.rs @@ -0,0 +1,14 @@ +struct NoCloneOrEq; + +#[derive(PartialEq)] +struct E { + x: NoCloneOrEq //~ ERROR binary operation `==` cannot be applied to type `NoCloneOrEq` +} +#[derive(Clone)] +struct C { + x: NoCloneOrEq + //~^ ERROR `NoCloneOrEq: Clone` is not satisfied +} + + +fn main() {} diff --git a/tests/ui/derives/deriving-no-inner-impl-error-message.stderr b/tests/ui/derives/deriving-no-inner-impl-error-message.stderr new file mode 100644 index 000000000..ef8c44caa --- /dev/null +++ b/tests/ui/derives/deriving-no-inner-impl-error-message.stderr @@ -0,0 +1,39 @@ +error[E0369]: binary operation `==` cannot be applied to type `NoCloneOrEq` + --> $DIR/deriving-no-inner-impl-error-message.rs:5:5 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | struct E { +LL | x: NoCloneOrEq + | ^^^^^^^^^^^^^^ + | +note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq` + --> $DIR/deriving-no-inner-impl-error-message.rs:1:1 + | +LL | struct NoCloneOrEq; + | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied + --> $DIR/deriving-no-inner-impl-error-message.rs:9:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct C { +LL | x: NoCloneOrEq + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq` + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0369. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/derives/deriving-non-type.rs b/tests/ui/derives/deriving-non-type.rs new file mode 100644 index 000000000..9afffa900 --- /dev/null +++ b/tests/ui/derives/deriving-non-type.rs @@ -0,0 +1,30 @@ +#![allow(dead_code)] + +struct S; + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +trait T { } + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +impl S { } + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +impl T for S { } + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +static s: usize = 0; + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +const c: usize = 0; + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +mod m { } + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +extern "C" { } + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +type A = usize; + +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to `struct`s, `enum`s and `union`s +fn main() { } diff --git a/tests/ui/derives/deriving-non-type.stderr b/tests/ui/derives/deriving-non-type.stderr new file mode 100644 index 000000000..ef7ef54d1 --- /dev/null +++ b/tests/ui/derives/deriving-non-type.stderr @@ -0,0 +1,75 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:5:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | trait T { } + | ----------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:8:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | impl S { } + | ---------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:11:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | impl T for S { } + | ---------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:14:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | static s: usize = 0; + | -------------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:17:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | const c: usize = 0; + | ------------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:20:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | mod m { } + | --------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:23:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | extern "C" { } + | -------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:26:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | type A = usize; + | --------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/deriving-non-type.rs:29:1 + | +LL | #[derive(PartialEq)] + | ^^^^^^^^^^^^^^^^^^^^ not applicable here +LL | fn main() { } + | ------------- not a `struct`, `enum` or `union` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/derives/deriving-primitive.rs b/tests/ui/derives/deriving-primitive.rs new file mode 100644 index 000000000..1173eca64 --- /dev/null +++ b/tests/ui/derives/deriving-primitive.rs @@ -0,0 +1,5 @@ +#[derive(FromPrimitive)] //~ ERROR cannot find derive macro `FromPrimitive` in this scope + //~| ERROR cannot find derive macro `FromPrimitive` in this scope +enum Foo {} + +fn main() {} diff --git a/tests/ui/derives/deriving-primitive.stderr b/tests/ui/derives/deriving-primitive.stderr new file mode 100644 index 000000000..ca64c9ee7 --- /dev/null +++ b/tests/ui/derives/deriving-primitive.stderr @@ -0,0 +1,14 @@ +error: cannot find derive macro `FromPrimitive` in this scope + --> $DIR/deriving-primitive.rs:1:10 + | +LL | #[derive(FromPrimitive)] + | ^^^^^^^^^^^^^ + +error: cannot find derive macro `FromPrimitive` in this scope + --> $DIR/deriving-primitive.rs:1:10 + | +LL | #[derive(FromPrimitive)] + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/derives/deriving-with-repr-packed.rs b/tests/ui/derives/deriving-with-repr-packed.rs new file mode 100644 index 000000000..3884e3977 --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed.rs @@ -0,0 +1,45 @@ +#![deny(unaligned_references)] + +// Check that deriving certain builtin traits on certain packed structs cause +// errors. This happens when the derived trait would need to use a potentially +// misaligned reference. But there are two cases that are allowed: +// - If all the fields within the struct meet the required alignment: 1 for +// `repr(packed)`, or `N` for `repr(packed(N))`. +// - If `Default` is the only trait derived, because it doesn't involve any +// references. + +#[derive(Copy, Clone, Default, PartialEq, Eq)] +//~^ ERROR `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters +//~| hard error +//~^^^ ERROR `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters +//~| hard error +#[repr(packed)] +pub struct Foo(T, T, T); + +#[derive(Default, Hash)] +//~^ ERROR `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` +//~| hard error +#[repr(packed)] +pub struct Bar(u32, u32, u32); + +// This one is fine because the field alignment is 1. +#[derive(Default, Hash)] +#[repr(packed)] +pub struct Bar2(u8, i8, bool); + +// This one is fine because the field alignment is 2, matching `packed(2)`. +#[derive(Default, Hash)] +#[repr(packed(2))] +pub struct Bar3(u16, i16, bool); + +// This one is fine because it's not packed. +#[derive(Debug, Default)] +struct Y(usize); + +#[derive(Debug, Default)] +//~^ ERROR `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` +//~| hard error +#[repr(packed)] +struct X(Y); + +fn main() {} diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr new file mode 100644 index 000000000..0ad800c39 --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -0,0 +1,111 @@ +error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters + --> $DIR/deriving-with-repr-packed.rs:11:16 + | +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 +note: the lint level is defined here + --> $DIR/deriving-with-repr-packed.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters + --> $DIR/deriving-with-repr-packed.rs:11:32 + | +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` + --> $DIR/deriving-with-repr-packed.rs:19:19 + | +LL | #[derive(Default, Hash)] + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` + --> $DIR/deriving-with-repr-packed.rs:39:10 + | +LL | #[derive(Debug, Default)] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters + --> $DIR/deriving-with-repr-packed.rs:11:16 + | +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 +note: the lint level is defined here + --> $DIR/deriving-with-repr-packed.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters + --> $DIR/deriving-with-repr-packed.rs:11:32 + | +LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 +note: the lint level is defined here + --> $DIR/deriving-with-repr-packed.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` + --> $DIR/deriving-with-repr-packed.rs:19:19 + | +LL | #[derive(Default, Hash)] + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 +note: the lint level is defined here + --> $DIR/deriving-with-repr-packed.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` + --> $DIR/deriving-with-repr-packed.rs:39:10 + | +LL | #[derive(Debug, Default)] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 +note: the lint level is defined here + --> $DIR/deriving-with-repr-packed.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/derives/issue-36617.rs b/tests/ui/derives/issue-36617.rs new file mode 100644 index 000000000..08f293d2e --- /dev/null +++ b/tests/ui/derives/issue-36617.rs @@ -0,0 +1,16 @@ +#![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive` +//~^ ERROR `derive` attribute cannot be used at crate level + +#![test]//~ ERROR cannot determine resolution for the attribute macro `test` +//~^ ERROR `test` attribute cannot be used at crate level + +#![test_case]//~ ERROR cannot determine resolution for the attribute macro `test_case` +//~^ ERROR `test_case` attribute cannot be used at crate level + +#![bench]//~ ERROR cannot determine resolution for the attribute macro `bench` +//~^ ERROR `bench` attribute cannot be used at crate level + +#![global_allocator]//~ ERROR cannot determine resolution for the attribute macro `global_allocator` +//~^ ERROR `global_allocator` attribute cannot be used at crate level + +fn main() {} diff --git a/tests/ui/derives/issue-36617.stderr b/tests/ui/derives/issue-36617.stderr new file mode 100644 index 000000000..9cc0a29b0 --- /dev/null +++ b/tests/ui/derives/issue-36617.stderr @@ -0,0 +1,97 @@ +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/issue-36617.rs:1:4 + | +LL | #![derive(Copy)] + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-36617.rs:4:4 + | +LL | #![test] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the attribute macro `test_case` + --> $DIR/issue-36617.rs:7:4 + | +LL | #![test_case] + | ^^^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the attribute macro `bench` + --> $DIR/issue-36617.rs:10:4 + | +LL | #![bench] + | ^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the attribute macro `global_allocator` + --> $DIR/issue-36617.rs:13:4 + | +LL | #![global_allocator] + | ^^^^^^^^^^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: `derive` attribute cannot be used at crate level + --> $DIR/issue-36617.rs:1:1 + | +LL | #![derive(Copy)] + | ^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[derive(Copy)] + | ~~~~~~~~~~~~~~~ + +error: `test` attribute cannot be used at crate level + --> $DIR/issue-36617.rs:4:1 + | +LL | #![test] + | ^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[test] + | ~~~~~~~ + +error: `test_case` attribute cannot be used at crate level + --> $DIR/issue-36617.rs:7:1 + | +LL | #![test_case] + | ^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[test_case] + | ~~~~~~~~~~~~ + +error: `bench` attribute cannot be used at crate level + --> $DIR/issue-36617.rs:10:1 + | +LL | #![bench] + | ^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[bench] + | ~~~~~~~~ + +error: `global_allocator` attribute cannot be used at crate level + --> $DIR/issue-36617.rs:13:1 + | +LL | #![global_allocator] + | ^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[global_allocator] + | ~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/derives/issue-43023.rs b/tests/ui/derives/issue-43023.rs new file mode 100644 index 000000000..c0208e680 --- /dev/null +++ b/tests/ui/derives/issue-43023.rs @@ -0,0 +1,20 @@ +struct S; + +impl S { + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + fn f() { + file!(); + } +} + +trait Tr1 { + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + fn f(); +} + +trait Tr2 { + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + type F; +} + +fn main() {} diff --git a/tests/ui/derives/issue-43023.stderr b/tests/ui/derives/issue-43023.stderr new file mode 100644 index 000000000..007eb2595 --- /dev/null +++ b/tests/ui/derives/issue-43023.stderr @@ -0,0 +1,29 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43023.rs:4:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | / fn f() { +LL | | file!(); +LL | | } + | |_____- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43023.rs:11:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | fn f(); + | ------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43023.rs:16:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | type F; + | ------- not a `struct`, `enum` or `union` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/derives/issue-91492.rs b/tests/ui/derives/issue-91492.rs new file mode 100644 index 000000000..df792f118 --- /dev/null +++ b/tests/ui/derives/issue-91492.rs @@ -0,0 +1,25 @@ +// Reproduce the issue with vec +pub struct NoDerives; +fn fun1(foo: &mut Vec, bar: &[NoDerives]) { + foo.extend_from_slice(bar); //~ ERROR +} + +// Reproduce the issue with vec +// and demonstrate that other derives are ignored in the suggested output +#[derive(Default, PartialEq)] +pub struct SomeDerives; +fn fun2(foo: &mut Vec, bar: &[SomeDerives]) { + foo.extend_from_slice(bar); //~ ERROR +} + +// Try and fail to reproduce the issue without vec. +// No idea why it doesnt reproduce the issue but its still a useful test case. +struct Object(T, A); +impl Object { + fn use_clone(&self) {} +} +fn fun3(foo: Object) { + foo.use_clone(); //~ ERROR +} + +fn main() {} diff --git a/tests/ui/derives/issue-91492.stderr b/tests/ui/derives/issue-91492.stderr new file mode 100644 index 000000000..cee30ac50 --- /dev/null +++ b/tests/ui/derives/issue-91492.stderr @@ -0,0 +1,59 @@ +error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec`, but its trait bounds were not satisfied + --> $DIR/issue-91492.rs:4:9 + | +LL | pub struct NoDerives; + | -------------------- doesn't satisfy `NoDerives: Clone` +LL | fn fun1(foo: &mut Vec, bar: &[NoDerives]) { +LL | foo.extend_from_slice(bar); + | ^^^^^^^^^^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `NoDerives: Clone` +help: consider annotating `NoDerives` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `extend_from_slice` exists for mutable reference `&mut Vec`, but its trait bounds were not satisfied + --> $DIR/issue-91492.rs:12:9 + | +LL | pub struct SomeDerives; + | ---------------------- doesn't satisfy `SomeDerives: Clone` +LL | fn fun2(foo: &mut Vec, bar: &[SomeDerives]) { +LL | foo.extend_from_slice(bar); + | ^^^^^^^^^^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `SomeDerives: Clone` +help: consider annotating `SomeDerives` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `use_clone` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91492.rs:22:9 + | +LL | pub struct NoDerives; + | -------------------- doesn't satisfy `NoDerives: Clone` +... +LL | struct Object(T, A); + | ------------------- method `use_clone` not found for this struct +... +LL | foo.use_clone(); + | ^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | +note: trait bound `NoDerives: Clone` was not satisfied + --> $DIR/issue-91492.rs:18:9 + | +LL | impl Object { + | ^^^^^ ------------ + | | + | unsatisfied trait bound introduced here +help: consider annotating `NoDerives` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/derives/issue-91550.rs b/tests/ui/derives/issue-91550.rs new file mode 100644 index 000000000..56fd5ffa8 --- /dev/null +++ b/tests/ui/derives/issue-91550.rs @@ -0,0 +1,29 @@ +use std::collections::HashSet; + +/// natural case from the issue +struct Value(u32); + +fn main() { + let hs = HashSet::::new(); + hs.insert(Value(0)); //~ ERROR +} + +/// synthetic cases +pub struct NoDerives; + +struct Object(T); +impl Object { + fn use_eq(&self) {} +} +impl Object { + fn use_ord(&self) {} +} +impl Object { + fn use_ord_and_partial_ord(&self) {} +} + +fn function(foo: Object) { + foo.use_eq(); //~ ERROR + foo.use_ord(); //~ ERROR + foo.use_ord_and_partial_ord(); //~ ERROR +} diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr new file mode 100644 index 000000000..af03f0e5e --- /dev/null +++ b/tests/ui/derives/issue-91550.stderr @@ -0,0 +1,131 @@ +error[E0599]: the method `insert` exists for struct `HashSet`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:8:8 + | +LL | struct Value(u32); + | ------------ + | | + | doesn't satisfy `Value: Eq` + | doesn't satisfy `Value: Hash` + | doesn't satisfy `Value: PartialEq` +... +LL | hs.insert(Value(0)); + | ^^^^^^ + | + = note: the following trait bounds were not satisfied: + `Value: Eq` + `Value: PartialEq` + which is required by `Value: Eq` + `Value: Hash` +help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]` + | +LL | #[derive(Eq, Hash, PartialEq)] + | + +error[E0599]: the method `use_eq` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:26:9 + | +LL | pub struct NoDerives; + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: PartialEq` +LL | +LL | struct Object(T); + | ---------------- method `use_eq` not found for this struct +... +LL | foo.use_eq(); + | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | +note: trait bound `NoDerives: Eq` was not satisfied + --> $DIR/issue-91550.rs:15:9 + | +LL | impl Object { + | ^^ --------- + | | + | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialEq` + which is required by `NoDerives: Eq` +help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` + | +LL | #[derive(Eq, PartialEq)] + | + +error[E0599]: the method `use_ord` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:27:9 + | +LL | pub struct NoDerives; + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: Ord` + | doesn't satisfy `NoDerives: PartialEq` + | doesn't satisfy `NoDerives: PartialOrd` +LL | +LL | struct Object(T); + | ---------------- method `use_ord` not found for this struct +... +LL | foo.use_ord(); + | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | +note: trait bound `NoDerives: Ord` was not satisfied + --> $DIR/issue-91550.rs:18:9 + | +LL | impl Object { + | ^^^ --------- + | | + | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialOrd` + which is required by `NoDerives: Ord` + `NoDerives: PartialEq` + which is required by `NoDerives: Ord` + `NoDerives: Eq` + which is required by `NoDerives: Ord` +help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` + | +LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] + | + +error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:28:9 + | +LL | pub struct NoDerives; + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: Ord` + | doesn't satisfy `NoDerives: PartialEq` + | doesn't satisfy `NoDerives: PartialOrd` +LL | +LL | struct Object(T); + | ---------------- method `use_ord_and_partial_ord` not found for this struct +... +LL | foo.use_ord_and_partial_ord(); + | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `NoDerives: Ord` + `NoDerives: PartialOrd` + --> $DIR/issue-91550.rs:21:9 + | +LL | impl Object { + | ^^^ ^^^^^^^^^^ --------- + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialEq` + which is required by `NoDerives: Ord` + `NoDerives: Eq` + which is required by `NoDerives: Ord` + `NoDerives: PartialEq` + which is required by `NoDerives: PartialOrd` +help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` + | +LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/derives/issue-97343.rs b/tests/ui/derives/issue-97343.rs new file mode 100644 index 000000000..6f0e4d55a --- /dev/null +++ b/tests/ui/derives/issue-97343.rs @@ -0,0 +1,8 @@ +use std::fmt::Debug; + +#[derive(Debug)] +pub struct Irrelevant { //~ ERROR type arguments are not allowed on type parameter + irrelevant: Irrelevant, +} + +fn main() {} diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr new file mode 100644 index 000000000..e83bbb5b6 --- /dev/null +++ b/tests/ui/derives/issue-97343.stderr @@ -0,0 +1,21 @@ +error[E0109]: type arguments are not allowed on type parameter `Irrelevant` + --> $DIR/issue-97343.rs:4:23 + | +LL | #[derive(Debug)] + | ----- + | | + | not allowed on type parameter `Irrelevant` + | in this derive macro expansion +LL | pub struct Irrelevant { + | ^^^^^^^^^^ type argument not allowed + | +note: type parameter `Irrelevant` defined here + --> $DIR/issue-97343.rs:4:23 + | +LL | pub struct Irrelevant { + | ^^^^^^^^^^ + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/deriving/auxiliary/derive-no-std.rs b/tests/ui/deriving/auxiliary/derive-no-std.rs new file mode 100644 index 000000000..3893dc1be --- /dev/null +++ b/tests/ui/deriving/auxiliary/derive-no-std.rs @@ -0,0 +1,29 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +// Issue #16803 + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Default, Copy)] +pub struct Foo { + pub x: u32, +} + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub enum Bar { + Qux, + Quux(u32), +} + +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub enum Void {} +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub struct Empty; +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, + Debug, Copy)] +pub struct AlsoEmpty {} diff --git a/tests/ui/deriving/derive-no-std.rs b/tests/ui/deriving/derive-no-std.rs new file mode 100644 index 000000000..74c73b99c --- /dev/null +++ b/tests/ui/deriving/derive-no-std.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:derive-no-std.rs + +extern crate derive_no_std; +use derive_no_std::*; + +fn main() { + let f = Foo { x: 0 }; + assert_eq!(f.clone(), Foo::default()); + + assert!(Bar::Qux < Bar::Quux(42)); +} diff --git a/tests/ui/deriving/derive-partialord-correctness.rs b/tests/ui/deriving/derive-partialord-correctness.rs new file mode 100644 index 000000000..36763eda1 --- /dev/null +++ b/tests/ui/deriving/derive-partialord-correctness.rs @@ -0,0 +1,9 @@ +// run-pass +// Original issue: #49650 + +#[derive(PartialOrd, PartialEq)] +struct FloatWrapper(f64); + +fn main() { + assert!((0.0 / 0.0 >= 0.0) == (FloatWrapper(0.0 / 0.0) >= FloatWrapper(0.0))) +} diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs new file mode 100644 index 000000000..ba7809413 --- /dev/null +++ b/tests/ui/deriving/deriving-all-codegen.rs @@ -0,0 +1,106 @@ +// check-pass +// compile-flags: -Zunpretty=expanded +// edition:2021 +// +// This test checks the code generated for all[*] the builtin derivable traits +// on a variety of structs and enums. It protects against accidental changes to +// the generated code, and makes deliberate changes to the generated code +// easier to review. +// +// [*] It excludes `Copy` in some cases, because that changes the code +// generated for `Clone`. +// +// [*] It excludes `RustcEncodable` and `RustDecodable`, which are obsolete and +// also require the `rustc_serialize` crate. + +#![crate_type = "lib"] +#![allow(dead_code)] +#![allow(deprecated)] + +// Empty struct. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Empty; + +// A basic struct. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Point { + x: u32, + y: u32, +} + +// A large struct. +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Big { + b1: u32, b2: u32, b3: u32, b4: u32, b5: u32, b6: u32, b7: u32, b8: u32, +} + +// A struct with an unsized field. Some derives are not usable in this case. +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +struct Unsized([u32]); + +// A packed tuple struct that impls `Copy`. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[repr(packed)] +struct PackedCopy(u32); + +// A packed tuple struct that does not impl `Copy`. Note that the alignment of +// the field must be 1 for this code to be valid. Otherwise it triggers an +// error "`#[derive]` can't be used on a `#[repr(packed)]` struct that does not +// derive Copy (error E0133)" at MIR building time. This is a weird case and +// it's possible that this struct is not supposed to work, but for now it does. +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[repr(packed)] +struct PackedNonCopy(u8); + +// An empty enum. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Enum0 {} + +// A single-variant enum. +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Enum1 { + Single { x: u32 } +} + +// A C-like, fieldless enum with a single variant. +#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Fieldless1 { + #[default] + A, +} + +// A C-like, fieldless enum. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Fieldless { + #[default] + A, + B, + C, +} + +// An enum with multiple fieldless and fielded variants. +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Mixed { + #[default] + P, + Q, + R(u32), + S { d1: Option, d2: Option }, +} + +// An enum with no fieldless variants. Note that `Default` cannot be derived +// for this enum. +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +enum Fielded { + X(u32), + Y(bool), + Z(Option), +} + +// A union. Most builtin traits are not derivable for unions. +#[derive(Clone, Copy)] +pub union Union { + pub b: bool, + pub u: u32, + pub i: i32, +} diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout new file mode 100644 index 000000000..e6ee11a78 --- /dev/null +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -0,0 +1,1074 @@ +#![feature(prelude_import)] +// check-pass +// compile-flags: -Zunpretty=expanded +// edition:2021 +// +// This test checks the code generated for all[*] the builtin derivable traits +// on a variety of structs and enums. It protects against accidental changes to +// the generated code, and makes deliberate changes to the generated code +// easier to review. +// +// [*] It excludes `Copy` in some cases, because that changes the code +// generated for `Clone`. +// +// [*] It excludes `RustcEncodable` and `RustDecodable`, which are obsolete and +// also require the `rustc_serialize` crate. + +#![crate_type = "lib"] +#![allow(dead_code)] +#![allow(deprecated)] +#[prelude_import] +use std::prelude::rust_2021::*; +#[macro_use] +extern crate std; + +// Empty struct. +struct Empty; +#[automatically_derived] +impl ::core::clone::Clone for Empty { + #[inline] + fn clone(&self) -> Empty { *self } +} +#[automatically_derived] +impl ::core::marker::Copy for Empty { } +#[automatically_derived] +impl ::core::fmt::Debug for Empty { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str(f, "Empty") + } +} +#[automatically_derived] +impl ::core::default::Default for Empty { + #[inline] + fn default() -> Empty { Empty {} } +} +#[automatically_derived] +impl ::core::hash::Hash for Empty { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {} +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Empty { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Empty { + #[inline] + fn eq(&self, other: &Empty) -> bool { true } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Empty { } +#[automatically_derived] +impl ::core::cmp::Eq for Empty { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Empty { + #[inline] + fn partial_cmp(&self, other: &Empty) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Empty { + #[inline] + fn cmp(&self, other: &Empty) -> ::core::cmp::Ordering { + ::core::cmp::Ordering::Equal + } +} + +// A basic struct. +struct Point { + x: u32, + y: u32, +} +#[automatically_derived] +impl ::core::clone::Clone for Point { + #[inline] + fn clone(&self) -> Point { + let _: ::core::clone::AssertParamIsClone; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for Point { } +#[automatically_derived] +impl ::core::fmt::Debug for Point { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", + &&self.x, "y", &&self.y) + } +} +#[automatically_derived] +impl ::core::default::Default for Point { + #[inline] + fn default() -> Point { + Point { + x: ::core::default::Default::default(), + y: ::core::default::Default::default(), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Point { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.x, state); + ::core::hash::Hash::hash(&self.y, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Point { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Point { + #[inline] + fn eq(&self, other: &Point) -> bool { + self.x == other.x && self.y == other.y + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Point { } +#[automatically_derived] +impl ::core::cmp::Eq for Point { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Point { + #[inline] + fn partial_cmp(&self, other: &Point) + -> ::core::option::Option<::core::cmp::Ordering> { + match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Point { + #[inline] + fn cmp(&self, other: &Point) -> ::core::cmp::Ordering { + match ::core::cmp::Ord::cmp(&self.x, &other.x) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(&self.y, &other.y), + cmp => cmp, + } + } +} + +// A large struct. +struct Big { + b1: u32, + b2: u32, + b3: u32, + b4: u32, + b5: u32, + b6: u32, + b7: u32, + b8: u32, +} +#[automatically_derived] +impl ::core::clone::Clone for Big { + #[inline] + fn clone(&self) -> Big { + Big { + b1: ::core::clone::Clone::clone(&self.b1), + b2: ::core::clone::Clone::clone(&self.b2), + b3: ::core::clone::Clone::clone(&self.b3), + b4: ::core::clone::Clone::clone(&self.b4), + b5: ::core::clone::Clone::clone(&self.b5), + b6: ::core::clone::Clone::clone(&self.b6), + b7: ::core::clone::Clone::clone(&self.b7), + b8: ::core::clone::Clone::clone(&self.b8), + } + } +} +#[automatically_derived] +impl ::core::fmt::Debug for Big { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + let names: &'static _ = + &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; + let values: &[&dyn ::core::fmt::Debug] = + &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5, + &&self.b6, &&self.b7, &&self.b8]; + ::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", names, + values) + } +} +#[automatically_derived] +impl ::core::default::Default for Big { + #[inline] + fn default() -> Big { + Big { + b1: ::core::default::Default::default(), + b2: ::core::default::Default::default(), + b3: ::core::default::Default::default(), + b4: ::core::default::Default::default(), + b5: ::core::default::Default::default(), + b6: ::core::default::Default::default(), + b7: ::core::default::Default::default(), + b8: ::core::default::Default::default(), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Big { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.b1, state); + ::core::hash::Hash::hash(&self.b2, state); + ::core::hash::Hash::hash(&self.b3, state); + ::core::hash::Hash::hash(&self.b4, state); + ::core::hash::Hash::hash(&self.b5, state); + ::core::hash::Hash::hash(&self.b6, state); + ::core::hash::Hash::hash(&self.b7, state); + ::core::hash::Hash::hash(&self.b8, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Big { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Big { + #[inline] + fn eq(&self, other: &Big) -> bool { + self.b1 == other.b1 && self.b2 == other.b2 && self.b3 == other.b3 && + self.b4 == other.b4 && self.b5 == other.b5 && + self.b6 == other.b6 && self.b7 == other.b7 && + self.b8 == other.b8 + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Big { } +#[automatically_derived] +impl ::core::cmp::Eq for Big { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Big { + #[inline] + fn partial_cmp(&self, other: &Big) + -> ::core::option::Option<::core::cmp::Ordering> { + match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match ::core::cmp::PartialOrd::partial_cmp(&self.b2, + &other.b2) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b3, + &other.b3) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b4, + &other.b4) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b5, + &other.b5) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b6, + &other.b6) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + match ::core::cmp::PartialOrd::partial_cmp(&self.b7, + &other.b7) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => + ::core::cmp::PartialOrd::partial_cmp(&self.b8, &other.b8), + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Big { + #[inline] + fn cmp(&self, other: &Big) -> ::core::cmp::Ordering { + match ::core::cmp::Ord::cmp(&self.b1, &other.b1) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b2, &other.b2) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b3, &other.b3) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b4, &other.b4) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b5, &other.b5) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b6, &other.b6) { + ::core::cmp::Ordering::Equal => + match ::core::cmp::Ord::cmp(&self.b7, &other.b7) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(&self.b8, &other.b8), + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + }, + cmp => cmp, + } + } +} + +// A struct with an unsized field. Some derives are not usable in this case. +struct Unsized([u32]); +#[automatically_derived] +impl ::core::fmt::Debug for Unsized { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized", + &&self.0) + } +} +#[automatically_derived] +impl ::core::hash::Hash for Unsized { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.0, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Unsized { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Unsized { + #[inline] + fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Unsized { } +#[automatically_derived] +impl ::core::cmp::Eq for Unsized { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq<[u32]>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Unsized { + #[inline] + fn partial_cmp(&self, other: &Unsized) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Unsized { + #[inline] + fn cmp(&self, other: &Unsized) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} + +// A packed tuple struct that impls `Copy`. +#[repr(packed)] +struct PackedCopy(u32); +#[automatically_derived] +impl ::core::clone::Clone for PackedCopy { + #[inline] + fn clone(&self) -> PackedCopy { + let _: ::core::clone::AssertParamIsClone; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for PackedCopy { } +#[automatically_derived] +impl ::core::fmt::Debug for PackedCopy { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedCopy", + &&{ self.0 }) + } +} +#[automatically_derived] +impl ::core::default::Default for PackedCopy { + #[inline] + fn default() -> PackedCopy { + PackedCopy(::core::default::Default::default()) + } +} +#[automatically_derived] +impl ::core::hash::Hash for PackedCopy { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&{ self.0 }, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for PackedCopy { } +#[automatically_derived] +impl ::core::cmp::PartialEq for PackedCopy { + #[inline] + fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for PackedCopy { } +#[automatically_derived] +impl ::core::cmp::Eq for PackedCopy { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for PackedCopy { + #[inline] + fn partial_cmp(&self, other: &PackedCopy) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for PackedCopy { + #[inline] + fn cmp(&self, other: &PackedCopy) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 }) + } +} + +// A packed tuple struct that does not impl `Copy`. Note that the alignment of +// the field must be 1 for this code to be valid. Otherwise it triggers an +// error "`#[derive]` can't be used on a `#[repr(packed)]` struct that does not +// derive Copy (error E0133)" at MIR building time. This is a weird case and +// it's possible that this struct is not supposed to work, but for now it does. +#[repr(packed)] +struct PackedNonCopy(u8); +#[automatically_derived] +impl ::core::clone::Clone for PackedNonCopy { + #[inline] + fn clone(&self) -> PackedNonCopy { + PackedNonCopy(::core::clone::Clone::clone(&self.0)) + } +} +#[automatically_derived] +impl ::core::fmt::Debug for PackedNonCopy { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedNonCopy", + &&self.0) + } +} +#[automatically_derived] +impl ::core::default::Default for PackedNonCopy { + #[inline] + fn default() -> PackedNonCopy { + PackedNonCopy(::core::default::Default::default()) + } +} +#[automatically_derived] +impl ::core::hash::Hash for PackedNonCopy { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + ::core::hash::Hash::hash(&self.0, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for PackedNonCopy { } +#[automatically_derived] +impl ::core::cmp::PartialEq for PackedNonCopy { + #[inline] + fn eq(&self, other: &PackedNonCopy) -> bool { self.0 == other.0 } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for PackedNonCopy { } +#[automatically_derived] +impl ::core::cmp::Eq for PackedNonCopy { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for PackedNonCopy { + #[inline] + fn partial_cmp(&self, other: &PackedNonCopy) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for PackedNonCopy { + #[inline] + fn cmp(&self, other: &PackedNonCopy) -> ::core::cmp::Ordering { + ::core::cmp::Ord::cmp(&self.0, &other.0) + } +} + +// An empty enum. +enum Enum0 {} +#[automatically_derived] +impl ::core::clone::Clone for Enum0 { + #[inline] + fn clone(&self) -> Enum0 { *self } +} +#[automatically_derived] +impl ::core::marker::Copy for Enum0 { } +#[automatically_derived] +impl ::core::fmt::Debug for Enum0 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Enum0 { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Enum0 { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Enum0 { + #[inline] + fn eq(&self, other: &Enum0) -> bool { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Enum0 { } +#[automatically_derived] +impl ::core::cmp::Eq for Enum0 { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Enum0 { + #[inline] + fn partial_cmp(&self, other: &Enum0) + -> ::core::option::Option<::core::cmp::Ordering> { + unsafe { ::core::intrinsics::unreachable() } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Enum0 { + #[inline] + fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering { + unsafe { ::core::intrinsics::unreachable() } + } +} + +// A single-variant enum. +enum Enum1 { + Single { + x: u32, + }, +} +#[automatically_derived] +impl ::core::clone::Clone for Enum1 { + #[inline] + fn clone(&self) -> Enum1 { + match self { + Enum1::Single { x: __self_0 } => + Enum1::Single { x: ::core::clone::Clone::clone(__self_0) }, + } + } +} +#[automatically_derived] +impl ::core::fmt::Debug for Enum1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + Enum1::Single { x: __self_0 } => + ::core::fmt::Formatter::debug_struct_field1_finish(f, + "Single", "x", &__self_0), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Enum1 { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + match self { + Enum1::Single { x: __self_0 } => + ::core::hash::Hash::hash(__self_0, state), + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Enum1 { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Enum1 { + #[inline] + fn eq(&self, other: &Enum1) -> bool { + match (self, other) { + (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + *__self_0 == *__arg1_0, + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Enum1 { } +#[automatically_derived] +impl ::core::cmp::Eq for Enum1 { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Enum1 { + #[inline] + fn partial_cmp(&self, other: &Enum1) + -> ::core::option::Option<::core::cmp::Ordering> { + match (self, other) { + (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Enum1 { + #[inline] + fn cmp(&self, other: &Enum1) -> ::core::cmp::Ordering { + match (self, other) { + (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + } + } +} + +// A C-like, fieldless enum with a single variant. +enum Fieldless1 { + + #[default] + A, +} +#[automatically_derived] +impl ::core::clone::Clone for Fieldless1 { + #[inline] + fn clone(&self) -> Fieldless1 { Fieldless1::A } +} +#[automatically_derived] +impl ::core::fmt::Debug for Fieldless1 { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str(f, "A") + } +} +#[automatically_derived] +impl ::core::default::Default for Fieldless1 { + #[inline] + fn default() -> Fieldless1 { Self::A } +} +#[automatically_derived] +impl ::core::hash::Hash for Fieldless1 { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {} +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fieldless1 { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Fieldless1 { + #[inline] + fn eq(&self, other: &Fieldless1) -> bool { true } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fieldless1 { } +#[automatically_derived] +impl ::core::cmp::Eq for Fieldless1 { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Fieldless1 { + #[inline] + fn partial_cmp(&self, other: &Fieldless1) + -> ::core::option::Option<::core::cmp::Ordering> { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Fieldless1 { + #[inline] + fn cmp(&self, other: &Fieldless1) -> ::core::cmp::Ordering { + ::core::cmp::Ordering::Equal + } +} + +// A C-like, fieldless enum. +enum Fieldless { + + #[default] + A, + B, + C, +} +#[automatically_derived] +impl ::core::clone::Clone for Fieldless { + #[inline] + fn clone(&self) -> Fieldless { *self } +} +#[automatically_derived] +impl ::core::marker::Copy for Fieldless { } +#[automatically_derived] +impl ::core::fmt::Debug for Fieldless { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str(f, + match self { + Fieldless::A => "A", + Fieldless::B => "B", + Fieldless::C => "C", + }) + } +} +#[automatically_derived] +impl ::core::default::Default for Fieldless { + #[inline] + fn default() -> Fieldless { Self::A } +} +#[automatically_derived] +impl ::core::hash::Hash for Fieldless { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state) + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fieldless { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Fieldless { + #[inline] + fn eq(&self, other: &Fieldless) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fieldless { } +#[automatically_derived] +impl ::core::cmp::Eq for Fieldless { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () {} +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Fieldless { + #[inline] + fn partial_cmp(&self, other: &Fieldless) + -> ::core::option::Option<::core::cmp::Ordering> { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Fieldless { + #[inline] + fn cmp(&self, other: &Fieldless) -> ::core::cmp::Ordering { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) + } +} + +// An enum with multiple fieldless and fielded variants. +enum Mixed { + + #[default] + P, + Q, + R(u32), + S { + d1: Option, + d2: Option, + }, +} +#[automatically_derived] +impl ::core::clone::Clone for Mixed { + #[inline] + fn clone(&self) -> Mixed { + let _: ::core::clone::AssertParamIsClone; + let _: ::core::clone::AssertParamIsClone>; + let _: ::core::clone::AssertParamIsClone>; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for Mixed { } +#[automatically_derived] +impl ::core::fmt::Debug for Mixed { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), + Mixed::Q => ::core::fmt::Formatter::write_str(f, "Q"), + Mixed::R(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "R", + &__self_0), + Mixed::S { d1: __self_0, d2: __self_1 } => + ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", + "d1", &__self_0, "d2", &__self_1), + } + } +} +#[automatically_derived] +impl ::core::default::Default for Mixed { + #[inline] + fn default() -> Mixed { Self::P } +} +#[automatically_derived] +impl ::core::hash::Hash for Mixed { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state); + match self { + Mixed::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Mixed::S { d1: __self_0, d2: __self_1 } => { + ::core::hash::Hash::hash(__self_0, state); + ::core::hash::Hash::hash(__self_1, state) + } + _ => {} + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Mixed { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Mixed { + #[inline] + fn eq(&self, other: &Mixed) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag && + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + *__self_0 == *__arg1_0, + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + *__self_0 == *__arg1_0 && *__self_1 == *__arg1_1, + _ => true, + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Mixed { } +#[automatically_derived] +impl ::core::cmp::Eq for Mixed { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + let _: ::core::cmp::AssertParamIsEq>; + let _: ::core::cmp::AssertParamIsEq>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Mixed { + #[inline] + fn partial_cmp(&self, other: &Mixed) + -> ::core::option::Option<::core::cmp::Ordering> { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + match ::core::cmp::PartialOrd::partial_cmp(__self_0, + __arg1_0) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) + => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1), + cmp => cmp, + }, + _ => + ::core::option::Option::Some(::core::cmp::Ordering::Equal), + }, + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Mixed { + #[inline] + fn cmp(&self, other: &Mixed) -> ::core::cmp::Ordering { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) { + ::core::cmp::Ordering::Equal => + match (self, other) { + (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + d1: __arg1_0, d2: __arg1_1 }) => + match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { + ::core::cmp::Ordering::Equal => + ::core::cmp::Ord::cmp(__self_1, __arg1_1), + cmp => cmp, + }, + _ => ::core::cmp::Ordering::Equal, + }, + cmp => cmp, + } + } +} + +// An enum with no fieldless variants. Note that `Default` cannot be derived +// for this enum. +enum Fielded { X(u32), Y(bool), Z(Option), } +#[automatically_derived] +impl ::core::clone::Clone for Fielded { + #[inline] + fn clone(&self) -> Fielded { + match self { + Fielded::X(__self_0) => + Fielded::X(::core::clone::Clone::clone(__self_0)), + Fielded::Y(__self_0) => + Fielded::Y(::core::clone::Clone::clone(__self_0)), + Fielded::Z(__self_0) => + Fielded::Z(::core::clone::Clone::clone(__self_0)), + } + } +} +#[automatically_derived] +impl ::core::fmt::Debug for Fielded { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + Fielded::X(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "X", + &__self_0), + Fielded::Y(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Y", + &__self_0), + Fielded::Z(__self_0) => + ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Z", + &__self_0), + } + } +} +#[automatically_derived] +impl ::core::hash::Hash for Fielded { + fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { + let __self_tag = ::core::intrinsics::discriminant_value(self); + ::core::hash::Hash::hash(&__self_tag, state); + match self { + Fielded::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Fielded::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Fielded::Z(__self_0) => ::core::hash::Hash::hash(__self_0, state), + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fielded { } +#[automatically_derived] +impl ::core::cmp::PartialEq for Fielded { + #[inline] + fn eq(&self, other: &Fielded) -> bool { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + __self_tag == __arg1_tag && + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + *__self_0 == *__arg1_0, + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + *__self_0 == *__arg1_0, + (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + *__self_0 == *__arg1_0, + _ => unsafe { ::core::intrinsics::unreachable() } + } + } +} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fielded { } +#[automatically_derived] +impl ::core::cmp::Eq for Fielded { + #[inline] + #[doc(hidden)] + #[no_coverage] + fn assert_receiver_is_total_eq(&self) -> () { + let _: ::core::cmp::AssertParamIsEq; + let _: ::core::cmp::AssertParamIsEq; + let _: ::core::cmp::AssertParamIsEq>; + } +} +#[automatically_derived] +impl ::core::cmp::PartialOrd for Fielded { + #[inline] + fn partial_cmp(&self, other: &Fielded) + -> ::core::option::Option<::core::cmp::Ordering> { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) { + ::core::option::Option::Some(::core::cmp::Ordering::Equal) => + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), + _ => unsafe { ::core::intrinsics::unreachable() } + }, + cmp => cmp, + } + } +} +#[automatically_derived] +impl ::core::cmp::Ord for Fielded { + #[inline] + fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering { + let __self_tag = ::core::intrinsics::discriminant_value(self); + let __arg1_tag = ::core::intrinsics::discriminant_value(other); + match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) { + ::core::cmp::Ordering::Equal => + match (self, other) { + (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + ::core::cmp::Ord::cmp(__self_0, __arg1_0), + _ => unsafe { ::core::intrinsics::unreachable() } + }, + cmp => cmp, + } + } +} + +// A union. Most builtin traits are not derivable for unions. +pub union Union { + pub b: bool, + pub u: u32, + pub i: i32, +} +#[automatically_derived] +impl ::core::clone::Clone for Union { + #[inline] + fn clone(&self) -> Union { + let _: ::core::clone::AssertParamIsCopy; + *self + } +} +#[automatically_derived] +impl ::core::marker::Copy for Union { } diff --git a/tests/ui/deriving/deriving-associated-types.rs b/tests/ui/deriving/deriving-associated-types.rs new file mode 100644 index 000000000..4b1cbe80c --- /dev/null +++ b/tests/ui/deriving/deriving-associated-types.rs @@ -0,0 +1,199 @@ +// run-pass +pub trait DeclaredTrait { + type Type; +} + +impl DeclaredTrait for i32 { + type Type = i32; +} + +pub trait WhereTrait { + type Type; +} + +impl WhereTrait for i32 { + type Type = i32; +} + +// Make sure we don't add a bound that just shares a name with an associated +// type. +pub mod module { + pub type Type = i32; +} + +#[derive(PartialEq, Debug)] +struct PrivateStruct(T); + +#[derive(PartialEq, Debug)] +struct TupleStruct( + module::Type, + Option, + A, + PrivateStruct, + B, + B::Type, + Option, + ::Type, + Option<::Type>, + C, + C::Type, + Option, + ::Type, + Option<::Type>, + ::Type, +) where C: WhereTrait; + +#[derive(PartialEq, Debug)] +pub struct Struct where C: WhereTrait { + m1: module::Type, + m2: Option, + a1: A, + a2: PrivateStruct, + b: B, + b1: B::Type, + b2: Option, + b3: ::Type, + b4: Option<::Type>, + c: C, + c1: C::Type, + c2: Option, + c3: ::Type, + c4: Option<::Type>, + d: ::Type, +} + +#[derive(PartialEq, Debug)] +enum Enum where C: WhereTrait { + Unit, + Seq( + module::Type, + Option, + A, + PrivateStruct, + B, + B::Type, + Option, + ::Type, + Option<::Type>, + C, + C::Type, + Option, + ::Type, + Option<::Type>, + ::Type, + ), + Map { + m1: module::Type, + m2: Option, + a1: A, + a2: PrivateStruct, + b: B, + b1: B::Type, + b2: Option, + b3: ::Type, + b4: Option<::Type>, + c: C, + c1: C::Type, + c2: Option, + c3: ::Type, + c4: Option<::Type>, + d: ::Type, + }, +} + +fn main() { + let e: TupleStruct< + i32, + i32, + i32, + > = TupleStruct( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Struct< + i32, + i32, + i32, + > = Struct { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); + + let e = Enum::Unit::; + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Seq( + 0, + None, + 0, + PrivateStruct(0), + 0, + 0, + None, + 0, + None, + 0, + 0, + None, + 0, + None, + 0, + ); + assert_eq!(e, e); + + let e: Enum< + i32, + i32, + i32, + > = Enum::Map { + m1: 0, + m2: None, + a1: 0, + a2: PrivateStruct(0), + b: 0, + b1: 0, + b2: None, + b3: 0, + b4: None, + c: 0, + c1: 0, + c2: None, + c3: 0, + c4: None, + d: 0, + }; + assert_eq!(e, e); +} diff --git a/tests/ui/deriving/deriving-bounds.rs b/tests/ui/deriving/deriving-bounds.rs new file mode 100644 index 000000000..f0b921d0e --- /dev/null +++ b/tests/ui/deriving/deriving-bounds.rs @@ -0,0 +1,5 @@ +// run-pass +#[derive(Copy, Clone)] +struct Test; + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-clone-array.rs b/tests/ui/deriving/deriving-clone-array.rs new file mode 100644 index 000000000..4569749df --- /dev/null +++ b/tests/ui/deriving/deriving-clone-array.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +// test for issue #30244 + +#[derive(Copy, Clone)] +struct Array { + arr: [[u8; 256]; 4] +} + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-clone-enum.rs b/tests/ui/deriving/deriving-clone-enum.rs new file mode 100644 index 000000000..09e749740 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-enum.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +enum E { + A, + B(()), + C +} + +pub fn main() { + let _ = E::A.clone(); +} diff --git a/tests/ui/deriving/deriving-clone-generic-enum.rs b/tests/ui/deriving/deriving-clone-generic-enum.rs new file mode 100644 index 000000000..a344d7fc4 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-generic-enum.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +enum E { + A(T), + B(T,U), + C +} + +pub fn main() { + let _ = E::A::(1).clone(); +} diff --git a/tests/ui/deriving/deriving-clone-generic-struct.rs b/tests/ui/deriving/deriving-clone-generic-struct.rs new file mode 100644 index 000000000..4374d1594 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-generic-struct.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +#[derive(Clone)] +struct S { + foo: (), + bar: (), + baz: T, +} + +pub fn main() { + let _ = S { foo: (), bar: (), baz: 1 }.clone(); +} diff --git a/tests/ui/deriving/deriving-clone-generic-tuple-struct.rs b/tests/ui/deriving/deriving-clone-generic-tuple-struct.rs new file mode 100644 index 000000000..3480ccc10 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-generic-tuple-struct.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +#[allow(unused_tuple_struct_fields)] +struct S(T, ()); + +pub fn main() { + let _ = S(1, ()).clone(); +} diff --git a/tests/ui/deriving/deriving-clone-struct.rs b/tests/ui/deriving/deriving-clone-struct.rs new file mode 100644 index 000000000..b93cbe5f8 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-struct.rs @@ -0,0 +1,28 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +#[derive(Clone)] +struct S { + _int: isize, + _i8: i8, + _i16: i16, + _i32: i32, + _i64: i64, + + _uint: usize, + _u8: u8, + _u16: u16, + _u32: u32, + _u64: u64, + + _f32: f32, + _f64: f64, + + _bool: bool, + _char: char, + _nil: () +} + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-clone-tuple-struct.rs b/tests/ui/deriving/deriving-clone-tuple-struct.rs new file mode 100644 index 000000000..7ad3f0347 --- /dev/null +++ b/tests/ui/deriving/deriving-clone-tuple-struct.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +#[derive(Clone)] +struct S((), ()); + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-cmp-generic-enum.rs b/tests/ui/deriving/deriving-cmp-generic-enum.rs new file mode 100644 index 000000000..88da4bd06 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-enum.rs @@ -0,0 +1,44 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +enum E { + E0, + E1(T), + E2(T,T) +} + +pub fn main() { + let e0 = E::E0; + let e11 = E::E1(1); + let e12 = E::E1(2); + let e21 = E::E2(1, 1); + let e22 = E::E2(1, 2); + + // in order for both PartialOrd and Ord + let es = [e0, e11, e12, e21, e22]; + + for (i, e1) in es.iter().enumerate() { + for (j, e2) in es.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; + + // PartialEq + assert_eq!(*e1 == *e2, eq); + assert_eq!(*e1 != *e2, !eq); + + // PartialOrd + assert_eq!(*e1 < *e2, lt); + assert_eq!(*e1 > *e2, gt); + + assert_eq!(*e1 <= *e2, le); + assert_eq!(*e1 >= *e2, ge); + + // Ord + assert_eq!(e1.cmp(e2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-generic-struct-enum.rs b/tests/ui/deriving/deriving-cmp-generic-struct-enum.rs new file mode 100644 index 000000000..eeaf2ff7e --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-struct-enum.rs @@ -0,0 +1,48 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +enum ES { + ES1 { x: T }, + ES2 { x: T, y: T } +} + + +pub fn main() { + let (es11, es12, es21, es22) = (ES::ES1 { + x: 1 + }, ES::ES1 { + x: 2 + }, ES::ES2 { + x: 1, + y: 1 + }, ES::ES2 { + x: 1, + y: 2 + }); + + // in order for both PartialOrd and Ord + let ess = [es11, es12, es21, es22]; + + for (i, es1) in ess.iter().enumerate() { + for (j, es2) in ess.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let (lt, le) = (i < j, i <= j); + let (gt, ge) = (i > j, i >= j); + + // PartialEq + assert_eq!(*es1 == *es2, eq); + assert_eq!(*es1 != *es2, !eq); + + // PartialOrd + assert_eq!(*es1 < *es2, lt); + assert_eq!(*es1 > *es2, gt); + + assert_eq!(*es1 <= *es2, le); + assert_eq!(*es1 >= *es2, ge); + + // Ord + assert_eq!(es1.cmp(es2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-generic-struct.rs b/tests/ui/deriving/deriving-cmp-generic-struct.rs new file mode 100644 index 000000000..538caf439 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-struct.rs @@ -0,0 +1,40 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct S { + x: T, + y: T +} + +pub fn main() { + let s1 = S {x: 1, y: 1}; + let s2 = S {x: 1, y: 2}; + + // in order for both PartialOrd and Ord + let ss = [s1, s2]; + + for (i, s1) in ss.iter().enumerate() { + for (j, s2) in ss.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; + + // PartialEq + assert_eq!(*s1 == *s2, eq); + assert_eq!(*s1 != *s2, !eq); + + // PartialOrd + assert_eq!(*s1 < *s2, lt); + assert_eq!(*s1 > *s2, gt); + + assert_eq!(*s1 <= *s2, le); + assert_eq!(*s1 >= *s2, ge); + + // Ord + assert_eq!(s1.cmp(s2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs b/tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs new file mode 100644 index 000000000..79f58d456 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-generic-tuple-struct.rs @@ -0,0 +1,38 @@ +// run-pass +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct TS(T,T); + + +pub fn main() { + let ts1 = TS(1, 1); + let ts2 = TS(1, 2); + + // in order for both PartialOrd and Ord + let tss = [ts1, ts2]; + + for (i, ts1) in tss.iter().enumerate() { + for (j, ts2) in tss.iter().enumerate() { + let ord = i.cmp(&j); + + let eq = i == j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; + + // PartialEq + assert_eq!(*ts1 == *ts2, eq); + assert_eq!(*ts1 != *ts2, !eq); + + // PartialOrd + assert_eq!(*ts1 < *ts2, lt); + assert_eq!(*ts1 > *ts2, gt); + + assert_eq!(*ts1 <= *ts2, le); + assert_eq!(*ts1 >= *ts2, ge); + + // Ord + assert_eq!(ts1.cmp(ts2), ord); + } + } +} diff --git a/tests/ui/deriving/deriving-cmp-shortcircuit.rs b/tests/ui/deriving/deriving-cmp-shortcircuit.rs new file mode 100644 index 000000000..140373e95 --- /dev/null +++ b/tests/ui/deriving/deriving-cmp-shortcircuit.rs @@ -0,0 +1,37 @@ +// run-pass +// check that the derived impls for the comparison traits shortcircuit +// where possible, by having a type that panics when compared as the +// second element, so this passes iff the instances shortcircuit. + + +use std::cmp::Ordering; + +pub struct FailCmp; +impl PartialEq for FailCmp { + fn eq(&self, _: &FailCmp) -> bool { panic!("eq") } +} + +impl PartialOrd for FailCmp { + fn partial_cmp(&self, _: &FailCmp) -> Option { panic!("partial_cmp") } +} + +impl Eq for FailCmp {} + +impl Ord for FailCmp { + fn cmp(&self, _: &FailCmp) -> Ordering { panic!("cmp") } +} + +#[derive(PartialEq,PartialOrd,Eq,Ord)] +struct ShortCircuit { + x: isize, + y: FailCmp +} + +pub fn main() { + let a = ShortCircuit { x: 1, y: FailCmp }; + let b = ShortCircuit { x: 2, y: FailCmp }; + + assert!(a != b); + assert!(a < b); + assert_eq!(a.cmp(&b), ::std::cmp::Ordering::Less); +} diff --git a/tests/ui/deriving/deriving-copyclone.rs b/tests/ui/deriving/deriving-copyclone.rs new file mode 100644 index 000000000..f8403b1fe --- /dev/null +++ b/tests/ui/deriving/deriving-copyclone.rs @@ -0,0 +1,38 @@ +// run-pass +//! Test that #[derive(Copy, Clone)] produces a shallow copy +//! even when a member violates RFC 1521 + +use std::sync::atomic::{AtomicBool, Ordering}; + +/// A struct that pretends to be Copy, but actually does something +/// in its Clone impl +#[derive(Copy)] +struct Liar; + +/// Static cooperating with the rogue Clone impl +static CLONED: AtomicBool = AtomicBool::new(false); + +impl Clone for Liar { + fn clone(&self) -> Self { + // this makes Clone vs Copy observable + CLONED.store(true, Ordering::SeqCst); + + *self + } +} + +/// This struct is actually Copy... at least, it thinks it is! +#[derive(Copy, Clone)] +struct Innocent(#[allow(unused_tuple_struct_fields)] Liar); + +impl Innocent { + fn new() -> Self { + Innocent(Liar) + } +} + +fn main() { + let _ = Innocent::new().clone(); + // if Innocent was byte-for-byte copied, CLONED will still be false + assert!(!CLONED.load(Ordering::SeqCst)); +} diff --git a/tests/ui/deriving/deriving-default-box.rs b/tests/ui/deriving/deriving-default-box.rs new file mode 100644 index 000000000..b71e11496 --- /dev/null +++ b/tests/ui/deriving/deriving-default-box.rs @@ -0,0 +1,13 @@ +// run-pass +use std::default::Default; + +#[derive(Default)] +struct A { + foo: Box<[bool]>, +} + +pub fn main() { + let a: A = Default::default(); + let b: Box<[_]> = Box::<[bool; 0]>::new([]); + assert_eq!(a.foo, b); +} diff --git a/tests/ui/deriving/deriving-default-enum.rs b/tests/ui/deriving/deriving-default-enum.rs new file mode 100644 index 000000000..1c7a501ed --- /dev/null +++ b/tests/ui/deriving/deriving-default-enum.rs @@ -0,0 +1,27 @@ +// run-pass + +// nb: does not impl Default +#[derive(Debug, PartialEq)] +struct NotDefault; + +#[derive(Debug, Default, PartialEq)] +enum Foo { + #[default] + Alpha, + #[allow(dead_code)] + Beta(NotDefault), +} + +// #[default] on a generic enum does not add `Default` bounds to the type params. +#[derive(Default)] +enum MyOption { + #[default] + None, + #[allow(dead_code)] + Some(T), +} + +fn main() { + assert_eq!(Foo::default(), Foo::Alpha); + assert!(matches!(MyOption::::default(), MyOption::None)); +} diff --git a/tests/ui/deriving/deriving-enum-single-variant.rs b/tests/ui/deriving/deriving-enum-single-variant.rs new file mode 100644 index 000000000..1c5979c07 --- /dev/null +++ b/tests/ui/deriving/deriving-enum-single-variant.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +pub type task_id = isize; + +#[derive(PartialEq)] +pub enum Task { + TaskHandle(task_id) +} + +pub fn main() { } diff --git a/tests/ui/deriving/deriving-eq-ord-boxed-slice.rs b/tests/ui/deriving/deriving-eq-ord-boxed-slice.rs new file mode 100644 index 000000000..5b4b09836 --- /dev/null +++ b/tests/ui/deriving/deriving-eq-ord-boxed-slice.rs @@ -0,0 +1,15 @@ +// run-pass +#[derive(PartialEq, PartialOrd, Eq, Ord, Debug)] +struct Foo(Box<[u8]>); + +pub fn main() { + let a = Foo(Box::new([0, 1, 2])); + let b = Foo(Box::new([0, 1, 2])); + assert_eq!(a, b); + println!("{}", a != b); + println!("{}", a < b); + println!("{}", a <= b); + println!("{}", a == b); + println!("{}", a > b); + println!("{}", a >= b); +} diff --git a/tests/ui/deriving/deriving-hash.rs b/tests/ui/deriving/deriving-hash.rs new file mode 100644 index 000000000..16738ec4a --- /dev/null +++ b/tests/ui/deriving/deriving-hash.rs @@ -0,0 +1,96 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(deprecated)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(overflowing_literals)] + +use std::hash::{Hash, SipHasher, Hasher}; +use std::mem::size_of; + +#[derive(Hash)] +struct Person { + id: usize, + name: String, + phone: usize, +} + +// test for hygiene name collisions +#[derive(Hash)] struct __H__H; +#[derive(Hash)] enum Collision<__H> { __H { __H__H: __H } } + +#[derive(Hash)] +enum E { A=1, B } + +fn hash(t: &T) -> u64 { + let mut s = SipHasher::new(); + t.hash(&mut s); + s.finish() +} + +struct FakeHasher<'a>(&'a mut Vec); +impl<'a> Hasher for FakeHasher<'a> { + fn finish(&self) -> u64 { + unimplemented!() + } + + fn write(&mut self, bytes: &[u8]) { + self.0.extend(bytes); + } +} + +fn fake_hash(v: &mut Vec, a: A) { + a.hash(&mut FakeHasher(v)); +} + +struct OnlyOneByteHasher; +impl Hasher for OnlyOneByteHasher { + fn finish(&self) -> u64 { + unreachable!() + } + + fn write(&mut self, bytes: &[u8]) { + assert_eq!(bytes.len(), 1); + } +} + +fn main() { + let person1 = Person { + id: 5, + name: "Janet".to_string(), + phone: 555_666_7777 + }; + let person2 = Person { + id: 5, + name: "Bob".to_string(), + phone: 555_666_7777 + }; + assert_eq!(hash(&person1), hash(&person1)); + assert!(hash(&person1) != hash(&person2)); + + // test #21714 + let mut va = vec![]; + let mut vb = vec![]; + fake_hash(&mut va, E::A); + fake_hash(&mut vb, E::B); + assert!(va != vb); + + // issue #39137: single variant enum hash should not hash discriminant + #[derive(Hash)] + enum SingleVariantEnum { + A(u8), + } + let mut v = vec![]; + fake_hash(&mut v, SingleVariantEnum::A(17)); + assert_eq!(vec![17], v); + + // issue #39137 + #[repr(u8)] + #[derive(Hash)] + enum E { + A, + B, + } + E::A.hash(&mut OnlyOneByteHasher); +} diff --git a/tests/ui/deriving/deriving-in-fn.rs b/tests/ui/deriving/deriving-in-fn.rs new file mode 100644 index 000000000..07f91d059 --- /dev/null +++ b/tests/ui/deriving/deriving-in-fn.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(dead_code)] + +pub fn main() { + #[derive(Debug)] + struct Foo { + foo: isize, + } + + let f = Foo { foo: 10 }; + format!("{:?}", f); +} diff --git a/tests/ui/deriving/deriving-in-macro.rs b/tests/ui/deriving/deriving-in-macro.rs new file mode 100644 index 000000000..46e8e3783 --- /dev/null +++ b/tests/ui/deriving/deriving-in-macro.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +macro_rules! define_vec { + () => ( + mod foo { + #[derive(PartialEq)] + pub struct bar; + } + ) +} + +define_vec![]; + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-meta-multiple.rs b/tests/ui/deriving/deriving-meta-multiple.rs new file mode 100644 index 000000000..ad255be8d --- /dev/null +++ b/tests/ui/deriving/deriving-meta-multiple.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 +#![allow(deprecated)] + +use std::hash::{Hash, SipHasher}; + +// testing multiple separate deriving attributes +#[derive(PartialEq)] +#[derive(Clone)] +#[derive(Hash)] +struct Foo { + bar: usize, + baz: isize +} + +fn hash(_t: &T) {} + +pub fn main() { + let a = Foo {bar: 4, baz: -3}; + + a == a; // check for PartialEq impl w/o testing its correctness + a.clone(); // check for Clone impl w/o testing its correctness + hash(&a); // check for Hash impl w/o testing its correctness +} diff --git a/tests/ui/deriving/deriving-meta.rs b/tests/ui/deriving/deriving-meta.rs new file mode 100644 index 000000000..f2ff4f535 --- /dev/null +++ b/tests/ui/deriving/deriving-meta.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 +#![allow(deprecated)] + +use std::hash::{Hash, SipHasher}; + +#[derive(PartialEq, Clone, Hash)] +struct Foo { + bar: usize, + baz: isize +} + +fn hash(_t: &T) {} + +pub fn main() { + let a = Foo {bar: 4, baz: -3}; + + a == a; // check for PartialEq impl w/o testing its correctness + a.clone(); // check for Clone impl w/o testing its correctness + hash(&a); // check for Hash impl w/o testing its correctness +} diff --git a/tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs b/tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs new file mode 100644 index 000000000..e01b5a26f --- /dev/null +++ b/tests/ui/deriving/deriving-self-lifetime-totalord-totaleq.rs @@ -0,0 +1,16 @@ +// run-pass +use std::cmp::Ordering::{Less,Equal,Greater}; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct A<'a> { + x: &'a isize +} +pub fn main() { + let (a, b) = (A { x: &1 }, A { x: &2 }); + + assert_eq!(a.cmp(&a), Equal); + assert_eq!(b.cmp(&b), Equal); + + assert_eq!(a.cmp(&b), Less); + assert_eq!(b.cmp(&a), Greater); +} diff --git a/tests/ui/deriving/deriving-show-2.rs b/tests/ui/deriving/deriving-show-2.rs new file mode 100644 index 000000000..13d124ed4 --- /dev/null +++ b/tests/ui/deriving/deriving-show-2.rs @@ -0,0 +1,54 @@ +// run-pass +#![allow(dead_code)] +use std::fmt; + +#[derive(Debug)] +enum A {} +#[derive(Debug)] +enum B { B1, B2, B3 } +#[derive(Debug)] +enum C { C1(isize), C2(B), C3(String) } +#[derive(Debug)] +enum D { D1{ a: isize } } +#[derive(Debug)] +struct E; +#[derive(Debug)] +struct F(isize); +#[derive(Debug)] +struct G(isize, isize); +#[derive(Debug)] +struct H { a: isize } +#[derive(Debug)] +struct I { a: isize, b: isize } +#[derive(Debug)] +struct J(Custom); + +struct Custom; +impl fmt::Debug for Custom { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "yay") + } +} + +trait ToDebug { + fn to_show(&self) -> String; +} + +impl ToDebug for T { + fn to_show(&self) -> String { + format!("{:?}", self) + } +} + +pub fn main() { + assert_eq!(B::B1.to_show(), "B1".to_string()); + assert_eq!(B::B2.to_show(), "B2".to_string()); + assert_eq!(C::C1(3).to_show(), "C1(3)".to_string()); + assert_eq!(C::C2(B::B2).to_show(), "C2(B2)".to_string()); + assert_eq!(D::D1{ a: 2 }.to_show(), "D1 { a: 2 }".to_string()); + assert_eq!(E.to_show(), "E".to_string()); + assert_eq!(F(3).to_show(), "F(3)".to_string()); + assert_eq!(G(3, 4).to_show(), "G(3, 4)".to_string()); + assert_eq!(I{ a: 2, b: 4 }.to_show(), "I { a: 2, b: 4 }".to_string()); + assert_eq!(J(Custom).to_show(), "J(yay)".to_string()); +} diff --git a/tests/ui/deriving/deriving-show.rs b/tests/ui/deriving/deriving-show.rs new file mode 100644 index 000000000..eb3a8948f --- /dev/null +++ b/tests/ui/deriving/deriving-show.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +#[derive(Debug)] +struct Unit; + +#[derive(Debug)] +struct Tuple(isize, usize); + +#[derive(Debug)] +struct Struct { x: isize, y: usize } + +#[derive(Debug)] +enum Enum { + Nullary, + Variant(isize, usize), + StructVariant { x: isize, y : usize } +} + +#[derive(Debug)] +struct Pointers(*const dyn Send, *mut dyn Sync); + +macro_rules! t { + ($x:expr, $expected:expr) => { + assert_eq!(format!("{:?}", $x), $expected.to_string()) + } +} + +pub fn main() { + t!(Unit, "Unit"); + t!(Tuple(1, 2), "Tuple(1, 2)"); + t!(Struct { x: 1, y: 2 }, "Struct { x: 1, y: 2 }"); + t!(Enum::Nullary, "Nullary"); + t!(Enum::Variant(1, 2), "Variant(1, 2)"); + t!(Enum::StructVariant { x: 1, y: 2 }, "StructVariant { x: 1, y: 2 }"); +} diff --git a/tests/ui/deriving/deriving-via-extension-c-enum.rs b/tests/ui/deriving/deriving-via-extension-c-enum.rs new file mode 100644 index 000000000..7fa1a69d7 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-c-enum.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#[derive(PartialEq, Debug)] +enum Foo { + Bar, + Baz, + Boo +} + +pub fn main() { + let a = Foo::Bar; + let b = Foo::Bar; + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-via-extension-enum.rs b/tests/ui/deriving/deriving-via-extension-enum.rs new file mode 100644 index 000000000..6b58fd966 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-enum.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +#[derive(PartialEq, Debug)] +enum Foo { + Bar(isize, isize), + Baz(f64, f64) +} + +pub fn main() { + let a = Foo::Bar(1, 2); + let b = Foo::Bar(1, 2); + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-via-extension-hash-enum.rs b/tests/ui/deriving/deriving-via-extension-hash-enum.rs new file mode 100644 index 000000000..2d1ca05f4 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-hash-enum.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#[derive(Hash)] +enum Foo { + Bar(isize, char), + Baz(char, isize) +} + +#[derive(Hash)] +enum A { + B, + C, + D, + E +} + +pub fn main(){} diff --git a/tests/ui/deriving/deriving-via-extension-hash-struct.rs b/tests/ui/deriving/deriving-via-extension-hash-struct.rs new file mode 100644 index 000000000..c4037dc27 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-hash-struct.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Hash)] +struct Foo { + x: isize, + y: isize, + z: isize +} + +pub fn main() {} diff --git a/tests/ui/deriving/deriving-via-extension-struct-empty.rs b/tests/ui/deriving/deriving-via-extension-struct-empty.rs new file mode 100644 index 000000000..9fb250e84 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct-empty.rs @@ -0,0 +1,8 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo; + +pub fn main() { + assert_eq!(Foo, Foo); + assert!(!(Foo != Foo)); +} diff --git a/tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs b/tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs new file mode 100644 index 000000000..b6e6f136c --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct-like-enum-variant.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +#[derive(PartialEq, Debug)] +enum S { + X { x: isize, y: isize }, + Y +} + +pub fn main() { + let x = S::X { x: 1, y: 2 }; + assert_eq!(x, x); + assert!(!(x != x)); +} diff --git a/tests/ui/deriving/deriving-via-extension-struct-tuple.rs b/tests/ui/deriving/deriving-via-extension-struct-tuple.rs new file mode 100644 index 000000000..e84906c96 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct-tuple.rs @@ -0,0 +1,17 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo(isize, isize, String); + +pub fn main() { + let a1 = Foo(5, 6, "abc".to_string()); + let a2 = Foo(5, 6, "abc".to_string()); + let b = Foo(5, 7, "def".to_string()); + + assert_eq!(a1, a1); + assert_eq!(a2, a1); + assert!(!(a1 == b)); + + assert!(a1 != b); + assert!(!(a1 != a1)); + assert!(!(a2 != a1)); +} diff --git a/tests/ui/deriving/deriving-via-extension-struct.rs b/tests/ui/deriving/deriving-via-extension-struct.rs new file mode 100644 index 000000000..f4d8b16a0 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-struct.rs @@ -0,0 +1,16 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo { + x: isize, + y: isize, + z: isize, +} + +pub fn main() { + let a = Foo { x: 1, y: 2, z: 3 }; + let b = Foo { x: 1, y: 2, z: 3 }; + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-via-extension-type-params.rs b/tests/ui/deriving/deriving-via-extension-type-params.rs new file mode 100644 index 000000000..a5dec8ee1 --- /dev/null +++ b/tests/ui/deriving/deriving-via-extension-type-params.rs @@ -0,0 +1,16 @@ +// run-pass +#[derive(PartialEq, Hash, Debug)] +struct Foo { + x: isize, + y: T, + z: isize +} + +pub fn main() { + let a = Foo { x: 1, y: 2.0f64, z: 3 }; + let b = Foo { x: 1, y: 2.0f64, z: 3 }; + assert_eq!(a, b); + assert!(!(a != b)); + assert!(a.eq(&b)); + assert!(!a.ne(&b)); +} diff --git a/tests/ui/deriving/deriving-with-helper.rs b/tests/ui/deriving/deriving-with-helper.rs new file mode 100644 index 000000000..1c30b0b6f --- /dev/null +++ b/tests/ui/deriving/deriving-with-helper.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: --crate-type=lib + +#![feature(decl_macro)] +#![feature(lang_items)] +#![feature(no_core)] +#![feature(rustc_attrs)] + +#![no_core] + +#[rustc_builtin_macro] +macro derive() {} + +#[rustc_builtin_macro(Default, attributes(default))] +macro Default() {} + +mod default { + pub trait Default { + fn default() -> Self; + } + + impl Default for u8 { + fn default() -> u8 { + 0 + } + } +} + +#[lang = "sized"] +trait Sized {} + +#[derive(Default)] +enum S { + #[default] // OK + Foo, +} diff --git a/tests/ui/deriving/deriving-with-repr-packed.rs b/tests/ui/deriving/deriving-with-repr-packed.rs new file mode 100644 index 000000000..8ce444be1 --- /dev/null +++ b/tests/ui/deriving/deriving-with-repr-packed.rs @@ -0,0 +1,36 @@ +// run-pass +// check that derive on a packed struct does not call field +// methods with a misaligned field. + +use std::mem; + +#[derive(Copy, Clone)] +struct Aligned(usize); + +#[inline(never)] +fn check_align(ptr: *const Aligned) { + assert_eq!(ptr as usize % mem::align_of::(), + 0); +} + +impl PartialEq for Aligned { + fn eq(&self, other: &Self) -> bool { + check_align(self); + check_align(other); + self.0 == other.0 + } +} + +#[repr(packed)] +#[derive(Copy, Clone, PartialEq)] +struct Packed(Aligned, Aligned); + +#[derive(PartialEq)] +#[repr(C)] +struct Dealigned(u8, T); + +fn main() { + let d1 = Dealigned(0, Packed(Aligned(1), Aligned(2))); + let ck = d1 == d1; + assert!(ck); +} diff --git a/tests/ui/deriving/issue-103157.rs b/tests/ui/deriving/issue-103157.rs new file mode 100644 index 000000000..52b4c7898 --- /dev/null +++ b/tests/ui/deriving/issue-103157.rs @@ -0,0 +1,12 @@ +// check-fail + +#[derive(PartialEq, Eq)] +pub enum Value { + Boolean(Option), + Float(Option), //~ ERROR the trait bound `f64: Eq` is not satisfied +} + +fn main() { + let a = Value::Float(Some(f64::NAN)); + assert!(a == a); +} diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr new file mode 100644 index 000000000..b18e1e509 --- /dev/null +++ b/tests/ui/deriving/issue-103157.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `f64: Eq` is not satisfied + --> $DIR/issue-103157.rs:6:11 + | +LL | #[derive(PartialEq, Eq)] + | -- in this derive macro expansion +... +LL | Float(Option), + | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64` + | + = help: the following other types implement trait `Eq`: + i128 + i16 + i32 + i64 + i8 + isize + u128 + u16 + and 4 others + = note: required for `Option` to implement `Eq` +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/deriving/issue-105101.rs b/tests/ui/deriving/issue-105101.rs new file mode 100644 index 000000000..1a377feb9 --- /dev/null +++ b/tests/ui/deriving/issue-105101.rs @@ -0,0 +1,9 @@ +// compile-flags: --crate-type=lib + +#[derive(Default)] //~ ERROR multiple declared defaults +enum E { + #[default] + A, + #[default] + A, //~ ERROR defined multiple times +} diff --git a/tests/ui/deriving/issue-105101.stderr b/tests/ui/deriving/issue-105101.stderr new file mode 100644 index 000000000..0f6f67043 --- /dev/null +++ b/tests/ui/deriving/issue-105101.stderr @@ -0,0 +1,29 @@ +error: multiple declared defaults + --> $DIR/issue-105101.rs:3:10 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | A, + | - first default +LL | #[default] +LL | A, + | - additional default + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0428]: the name `A` is defined multiple times + --> $DIR/issue-105101.rs:8:5 + | +LL | A, + | - previous definition of the type `A` here +LL | #[default] +LL | A, + | ^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this enum + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/deriving/issue-19358.rs b/tests/ui/deriving/issue-19358.rs new file mode 100644 index 000000000..3970a4155 --- /dev/null +++ b/tests/ui/deriving/issue-19358.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(dead_code)] + +trait Trait { fn dummy(&self) { } } + +#[derive(Debug)] +struct Foo { + foo: T, +} + +#[derive(Debug)] +struct Bar where T: Trait { + bar: T, +} + +impl Trait for isize {} + +fn main() { + let a = Foo { foo: 12 }; + let b = Bar { bar: 12 }; + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/deriving/issue-3935.rs b/tests/ui/deriving/issue-3935.rs new file mode 100644 index 000000000..e98d68e0e --- /dev/null +++ b/tests/ui/deriving/issue-3935.rs @@ -0,0 +1,13 @@ +// run-pass + +#[derive(PartialEq)] +struct Bike { + name: String, +} + +pub fn main() { + let town_bike = Bike { name: "schwinn".to_string() }; + let my_bike = Bike { name: "surly".to_string() }; + + assert!(town_bike != my_bike); +} diff --git a/tests/ui/deriving/issue-58319.rs b/tests/ui/deriving/issue-58319.rs new file mode 100644 index 000000000..8041bd5bb --- /dev/null +++ b/tests/ui/deriving/issue-58319.rs @@ -0,0 +1,622 @@ +// run-pass +fn main() {} +#[derive(Clone)] +pub struct Little; +#[derive(Clone)] +#[allow(unused_tuple_struct_fields)] +pub struct Big( + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, + Little, +); diff --git a/tests/ui/deriving/issue-6341.rs b/tests/ui/deriving/issue-6341.rs new file mode 100644 index 000000000..1be1394df --- /dev/null +++ b/tests/ui/deriving/issue-6341.rs @@ -0,0 +1,11 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#[derive(PartialEq)] +struct A { x: usize } + +impl Drop for A { + fn drop(&mut self) {} +} + +pub fn main() {} diff --git a/tests/ui/deriving/issue-89188-gat-hrtb.rs b/tests/ui/deriving/issue-89188-gat-hrtb.rs new file mode 100644 index 000000000..e8118f0c6 --- /dev/null +++ b/tests/ui/deriving/issue-89188-gat-hrtb.rs @@ -0,0 +1,37 @@ +// check-pass + +trait CallWithShim: Sized { + type Shim<'s> + where + Self: 's; +} + +#[derive(Clone)] +struct ShimMethod(pub &'static dyn for<'s> Fn(&'s mut T::Shim<'s>)); + +trait CallWithShim2: Sized { + type Shim; +} + +struct S<'s>(&'s ()); + +#[derive(Clone)] +struct ShimMethod2(pub &'static dyn for<'s> Fn(&'s mut T::Shim>)); + +trait Trait<'s, 't, 'u> {} + +#[derive(Clone)] +struct ShimMethod3( + pub &'static dyn for<'s> Fn( + &'s mut T::Shim Fn(&'s mut T::Shim Trait<'s, 't, 'u>>)>, + ), +); + +trait Trait2 { + type As; +} + +#[derive(Clone)] +struct ShimMethod4(pub &'static dyn for<'s> Fn(&'s mut T::As)); + +pub fn main() {} diff --git a/tests/ui/dest-prop/skeptic-miscompile.rs b/tests/ui/dest-prop/skeptic-miscompile.rs new file mode 100644 index 000000000..4bb61dbc7 --- /dev/null +++ b/tests/ui/dest-prop/skeptic-miscompile.rs @@ -0,0 +1,24 @@ +// run-pass + +// compile-flags: -Zmir-opt-level=3 + +trait IterExt: Iterator { + fn fold_ex(mut self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let mut accum = init; + while let Some(x) = self.next() { + accum = f(accum, x); + } + accum + } +} + +impl IterExt for T {} + +fn main() { + let test = &["\n"]; + test.iter().fold_ex(String::new(), |_, b| b.to_string()); +} diff --git a/tests/ui/destructure-trait-ref.rs b/tests/ui/destructure-trait-ref.rs new file mode 100644 index 000000000..50b64aeeb --- /dev/null +++ b/tests/ui/destructure-trait-ref.rs @@ -0,0 +1,44 @@ +// The regression test for #15031 to make sure destructuring trait +// reference work properly. + +#![feature(box_patterns)] + +trait T { fn foo(&self) {} } +impl T for isize {} + + +fn main() { + // For an expression of the form: + // + // let &...&x = &..&SomeTrait; + // + // Say we have n `&` at the left hand and m `&` right hand, then: + // if n < m, we are golden; + // if n == m, it's a derefing non-derefable type error; + // if n > m, it's a type mismatch error. + + // n < m + let &x = &(&1isize as &dyn T); + let &x = &&(&1isize as &dyn T); + let &&x = &&(&1isize as &dyn T); + + // n == m + let &x = &1isize as &dyn T; //~ ERROR type `&dyn T` cannot be dereferenced + let &&x = &(&1isize as &dyn T); //~ ERROR type `&dyn T` cannot be dereferenced + let box x = Box::new(1isize) as Box; + //~^ ERROR type `Box` cannot be dereferenced + + // n > m + let &&x = &1isize as &dyn T; + //~^ ERROR mismatched types + //~| expected trait object `dyn T` + //~| found reference `&_` + let &&&x = &(&1isize as &dyn T); + //~^ ERROR mismatched types + //~| expected trait object `dyn T` + //~| found reference `&_` + let box box x = Box::new(1isize) as Box; + //~^ ERROR mismatched types + //~| expected trait object `dyn T` + //~| found struct `Box<_>` +} diff --git a/tests/ui/destructure-trait-ref.stderr b/tests/ui/destructure-trait-ref.stderr new file mode 100644 index 000000000..18a889837 --- /dev/null +++ b/tests/ui/destructure-trait-ref.stderr @@ -0,0 +1,65 @@ +error[E0033]: type `&dyn T` cannot be dereferenced + --> $DIR/destructure-trait-ref.rs:26:9 + | +LL | let &x = &1isize as &dyn T; + | ^^ type `&dyn T` cannot be dereferenced + +error[E0033]: type `&dyn T` cannot be dereferenced + --> $DIR/destructure-trait-ref.rs:27:10 + | +LL | let &&x = &(&1isize as &dyn T); + | ^^ type `&dyn T` cannot be dereferenced + +error[E0033]: type `Box` cannot be dereferenced + --> $DIR/destructure-trait-ref.rs:28:9 + | +LL | let box x = Box::new(1isize) as Box; + | ^^^^^ type `Box` cannot be dereferenced + +error[E0308]: mismatched types + --> $DIR/destructure-trait-ref.rs:32:10 + | +LL | let &&x = &1isize as &dyn T; + | ^^ ----------------- this expression has type `&dyn T` + | | + | expected trait object `dyn T`, found reference + | + = note: expected trait object `dyn T` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let &&x = &1isize as &dyn T; +LL + let &x = &1isize as &dyn T; + | + +error[E0308]: mismatched types + --> $DIR/destructure-trait-ref.rs:36:11 + | +LL | let &&&x = &(&1isize as &dyn T); + | ^^ -------------------- this expression has type `&&dyn T` + | | + | expected trait object `dyn T`, found reference + | + = note: expected trait object `dyn T` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let &&&x = &(&1isize as &dyn T); +LL + let &&x = &(&1isize as &dyn T); + | + +error[E0308]: mismatched types + --> $DIR/destructure-trait-ref.rs:40:13 + | +LL | let box box x = Box::new(1isize) as Box; + | ^^^^^ ------------------------------ this expression has type `Box` + | | + | expected trait object `dyn T`, found struct `Box` + | + = note: expected trait object `dyn T` + found struct `Box<_>` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0033, E0308. +For more information about an error, try `rustc --explain E0033`. diff --git a/tests/ui/destructuring-assignment/bad-expr-lhs.rs b/tests/ui/destructuring-assignment/bad-expr-lhs.rs new file mode 100644 index 000000000..53794783a --- /dev/null +++ b/tests/ui/destructuring-assignment/bad-expr-lhs.rs @@ -0,0 +1,9 @@ +fn main() { + 1 = 2; //~ ERROR invalid left-hand side of assignment + 1 += 2; //~ ERROR invalid left-hand side of assignment + (1, 2) = (3, 4); + //~^ ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + + None = Some(3); //~ ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/destructuring-assignment/bad-expr-lhs.stderr b/tests/ui/destructuring-assignment/bad-expr-lhs.stderr new file mode 100644 index 000000000..d29867474 --- /dev/null +++ b/tests/ui/destructuring-assignment/bad-expr-lhs.stderr @@ -0,0 +1,44 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:2:7 + | +LL | 1 = 2; + | - ^ + | | + | cannot assign to this expression + +error[E0067]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:3:7 + | +LL | 1 += 2; + | - ^^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:4:12 + | +LL | (1, 2) = (3, 4); + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:4:12 + | +LL | (1, 2) = (3, 4); + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/bad-expr-lhs.rs:8:10 + | +LL | None = Some(3); + | ---- ^ + | | + | cannot assign to this expression + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0067, E0070. +For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs new file mode 100644 index 000000000..ff867c000 --- /dev/null +++ b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.rs @@ -0,0 +1,5 @@ +fn main() { + let mut x = &0; + let mut y = &0; + (x, y) = &(1, 2); //~ ERROR mismatched types +} diff --git a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr new file mode 100644 index 000000000..950e0223e --- /dev/null +++ b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/default-match-bindings-forbidden.rs:4:5 + | +LL | (x, y) = &(1, 2); + | ^^^^^^ ------- this expression has type `&({integer}, {integer})` + | | + | expected reference, found tuple + | + = note: expected reference `&({integer}, {integer})` + found tuple `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/destructuring-assignment/drop-order.rs b/tests/ui/destructuring-assignment/drop-order.rs new file mode 100644 index 000000000..79671054c --- /dev/null +++ b/tests/ui/destructuring-assignment/drop-order.rs @@ -0,0 +1,43 @@ +// run-pass + +//! Test that let bindings and destructuring assignments have consistent drop orders + +#![allow(unused_variables, unused_assignments)] + +use std::cell::RefCell; + +thread_local! { + static DROP_ORDER: RefCell> = RefCell::new(Vec::new()); +} + +struct DropRecorder(usize); +impl Drop for DropRecorder { + fn drop(&mut self) { + DROP_ORDER.with(|d| d.borrow_mut().push(self.0)); + } +} + +fn main() { + let expected_drop_order = vec![1, 4, 5, 3, 2]; + // Check the drop order for let bindings: + { + let _ = DropRecorder(1); + let _val = DropRecorder(2); + let (x, _) = (DropRecorder(3), DropRecorder(4)); + drop(DropRecorder(5)); + } + DROP_ORDER.with(|d| { + assert_eq!(&*d.borrow(), &expected_drop_order); + d.borrow_mut().clear(); + }); + // Check that the drop order for destructuring assignment is the same: + { + let _val; + let x; + _ = DropRecorder(1); + _val = DropRecorder(2); + (x, _) = (DropRecorder(3), DropRecorder(4)); + drop(DropRecorder(5)); + } + DROP_ORDER.with(|d| assert_eq!(&*d.borrow(), &expected_drop_order)); +} diff --git a/tests/ui/destructuring-assignment/nested_destructure.rs b/tests/ui/destructuring-assignment/nested_destructure.rs new file mode 100644 index 000000000..94b3a5ff9 --- /dev/null +++ b/tests/ui/destructuring-assignment/nested_destructure.rs @@ -0,0 +1,18 @@ +// run-pass + +struct Struct { + a: S, + b: T, +} + +struct TupleStruct(S, T); + +fn main() { + let (a, b, c, d); + Struct { a: TupleStruct((a, b), c), b: [d] } = + Struct { a: TupleStruct((0, 1), 2), b: [3] }; + assert_eq!((a, b, c, d), (0, 1, 2, 3)); + + // unnested underscore: just discard + _ = 1; +} diff --git a/tests/ui/destructuring-assignment/note-unsupported.rs b/tests/ui/destructuring-assignment/note-unsupported.rs new file mode 100644 index 000000000..c69edd421 --- /dev/null +++ b/tests/ui/destructuring-assignment/note-unsupported.rs @@ -0,0 +1,22 @@ +struct S { x: u8, y: u8 } + +fn main() { + let (a, b) = (1, 2); + + (a, b) = (3, 4); + (a, b) += (3, 4); //~ ERROR invalid left-hand side of assignment + //~| ERROR binary assignment operation `+=` cannot be applied + + [a, b] = [3, 4]; + [a, b] += [3, 4]; //~ ERROR invalid left-hand side of assignment + //~| ERROR binary assignment operation `+=` cannot be applied + + let s = S { x: 3, y: 4 }; + + S { x: a, y: b } = s; + S { x: a, y: b } += s; //~ ERROR invalid left-hand side of assignment + //~| ERROR binary assignment operation `+=` cannot be applied + + S { x: a, ..s } = S { x: 3, y: 4 }; + //~^ ERROR functional record updates are not allowed in destructuring assignments +} diff --git a/tests/ui/destructuring-assignment/note-unsupported.stderr b/tests/ui/destructuring-assignment/note-unsupported.stderr new file mode 100644 index 000000000..8a88332b7 --- /dev/null +++ b/tests/ui/destructuring-assignment/note-unsupported.stderr @@ -0,0 +1,66 @@ +error: functional record updates are not allowed in destructuring assignments + --> $DIR/note-unsupported.rs:20:17 + | +LL | S { x: a, ..s } = S { x: 3, y: 4 }; + | ^ help: consider removing the trailing pattern + +error[E0368]: binary assignment operation `+=` cannot be applied to type `({integer}, {integer})` + --> $DIR/note-unsupported.rs:7:5 + | +LL | (a, b) += (3, 4); + | ------^^^^^^^^^^ + | | + | cannot use `+=` on type `({integer}, {integer})` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/note-unsupported.rs:7:12 + | +LL | (a, b) += (3, 4); + | ------ ^^ + | | + | cannot assign to this expression + +error[E0368]: binary assignment operation `+=` cannot be applied to type `[{integer}; 2]` + --> $DIR/note-unsupported.rs:11:5 + | +LL | [a, b] += [3, 4]; + | ------^^^^^^^^^^ + | | + | cannot use `+=` on type `[{integer}; 2]` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/note-unsupported.rs:11:12 + | +LL | [a, b] += [3, 4]; + | ------ ^^ + | | + | cannot assign to this expression + +error[E0368]: binary assignment operation `+=` cannot be applied to type `S` + --> $DIR/note-unsupported.rs:17:5 + | +LL | S { x: a, y: b } += s; + | ----------------^^^^^ + | | + | cannot use `+=` on type `S` + | +note: an implementation of `AddAssign<_>` might be missing for `S` + --> $DIR/note-unsupported.rs:1:1 + | +LL | struct S { x: u8, y: u8 } + | ^^^^^^^^ must implement `AddAssign<_>` +note: the trait `AddAssign` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0067]: invalid left-hand side of assignment + --> $DIR/note-unsupported.rs:17:22 + | +LL | S { x: a, y: b } += s; + | ---------------- ^^ + | | + | cannot assign to this expression + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0067, E0368. +For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/destructuring-assignment/slice_destructure.rs b/tests/ui/destructuring-assignment/slice_destructure.rs new file mode 100644 index 000000000..762c4b5e8 --- /dev/null +++ b/tests/ui/destructuring-assignment/slice_destructure.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + let (mut a, mut b); + [a, b] = [0, 1]; + assert_eq!((a, b), (0, 1)); + let mut c; + [a, .., b, c] = [1, 2, 3, 4, 5]; + assert_eq!((a, b, c), (1, 4, 5)); + [_, a, _] = [1, 2, 3]; + assert_eq!((a, b), (2, 4)); + [..] = [1, 2, 3]; + [c, ..] = [5, 6, 6]; + assert_eq!(c, 5); +} diff --git a/tests/ui/destructuring-assignment/slice_destructure_fail.rs b/tests/ui/destructuring-assignment/slice_destructure_fail.rs new file mode 100644 index 000000000..33b09eb34 --- /dev/null +++ b/tests/ui/destructuring-assignment/slice_destructure_fail.rs @@ -0,0 +1,6 @@ +fn main() { + let (mut a, mut b); + [a, .., b, ..] = [0, 1]; //~ ERROR `..` can only be used once per slice pattern + [a, a, b] = [1, 2]; //~ ERROR pattern requires 3 elements but array has 2 + [_] = [1, 2]; //~ ERROR pattern requires 1 element but array has 2 +} diff --git a/tests/ui/destructuring-assignment/slice_destructure_fail.stderr b/tests/ui/destructuring-assignment/slice_destructure_fail.stderr new file mode 100644 index 000000000..92c86feba --- /dev/null +++ b/tests/ui/destructuring-assignment/slice_destructure_fail.stderr @@ -0,0 +1,23 @@ +error: `..` can only be used once per slice pattern + --> $DIR/slice_destructure_fail.rs:3:14 + | +LL | [a, .., b, ..] = [0, 1]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error[E0527]: pattern requires 3 elements but array has 2 + --> $DIR/slice_destructure_fail.rs:4:3 + | +LL | [a, a, b] = [1, 2]; + | ^^^^^^^^^ expected 2 elements + +error[E0527]: pattern requires 1 element but array has 2 + --> $DIR/slice_destructure_fail.rs:5:3 + | +LL | [_] = [1, 2]; + | ^^^ expected 2 elements + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs b/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs new file mode 100644 index 000000000..8da7f90c5 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct-or-enum-variant-path.rs @@ -0,0 +1,34 @@ +// check-pass + +struct S; + +enum E { + V, +} + +type A = E; + +fn main() { + let mut a; + + (S, a) = (S, ()); + + (E::V, a) = (E::V, ()); + + (::V, a) = (E::V, ()); + (A::V, a) = (E::V, ()); +} + +impl S { + fn check() { + let a; + (Self, a) = (S, ()); + } +} + +impl E { + fn check() { + let a; + (Self::V, a) = (E::V, ()); + } +} diff --git a/tests/ui/destructuring-assignment/struct_destructure.rs b/tests/ui/destructuring-assignment/struct_destructure.rs new file mode 100644 index 000000000..8cceaadd7 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct_destructure.rs @@ -0,0 +1,20 @@ +// run-pass + +struct Struct { + a: S, + b: T, +} + +fn main() { + let (mut a, mut b); + Struct { a, b } = Struct { a: 0, b: 1 }; + assert_eq!((a, b), (0, 1)); + Struct { a: b, b: a } = Struct { a: 1, b: 2 }; + assert_eq!((a,b), (2, 1)); + Struct { a: _, b } = Struct { a: 1, b: 2 }; + assert_eq!((a, b), (2, 2)); + Struct { a, .. } = Struct { a: 1, b: 3 }; + assert_eq!((a, b), (1, 2)); + Struct { .. } = Struct { a: 1, b: 4 }; + assert_eq!((a, b), (1, 2)); +} diff --git a/tests/ui/destructuring-assignment/struct_destructure_fail.rs b/tests/ui/destructuring-assignment/struct_destructure_fail.rs new file mode 100644 index 000000000..c001fccd4 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct_destructure_fail.rs @@ -0,0 +1,16 @@ +struct Struct { + a: S, + b: T, +} + +fn main() { + let (mut a, b); + let mut c; + let d = Struct { a: 0, b: 1 }; + Struct { a, b, c } = Struct { a: 0, b: 1 }; //~ ERROR does not have a field named `c` + Struct { a, _ } = Struct { a: 1, b: 2 }; //~ ERROR pattern does not mention field `b` + //~| ERROR expected identifier, found reserved identifier `_` + Struct { a, ..d } = Struct { a: 1, b: 2 }; + //~^ ERROR functional record updates are not allowed in destructuring assignments + Struct { a, .. }; //~ ERROR base expression required after `..` +} diff --git a/tests/ui/destructuring-assignment/struct_destructure_fail.stderr b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr new file mode 100644 index 000000000..ae7b3d1e5 --- /dev/null +++ b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr @@ -0,0 +1,45 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/struct_destructure_fail.rs:11:17 + | +LL | Struct { a, _ } = Struct { a: 1, b: 2 }; + | ------ ^ expected identifier, found reserved identifier + | | + | while parsing this struct + +error: functional record updates are not allowed in destructuring assignments + --> $DIR/struct_destructure_fail.rs:13:19 + | +LL | Struct { a, ..d } = Struct { a: 1, b: 2 }; + | ^ help: consider removing the trailing pattern + +error: base expression required after `..` + --> $DIR/struct_destructure_fail.rs:15:19 + | +LL | Struct { a, .. }; + | ^ add a base expression here + +error[E0026]: struct `Struct` does not have a field named `c` + --> $DIR/struct_destructure_fail.rs:10:20 + | +LL | Struct { a, b, c } = Struct { a: 0, b: 1 }; + | ^ struct `Struct` does not have this field + +error[E0027]: pattern does not mention field `b` + --> $DIR/struct_destructure_fail.rs:11:5 + | +LL | Struct { a, _ } = Struct { a: 1, b: 2 }; + | ^^^^^^^^^^^^^^^ missing field `b` + | +help: include the missing field in the pattern + | +LL | Struct { a, b } = Struct { a: 1, b: 2 }; + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Struct { a, .. } = Struct { a: 1, b: 2 }; + | ~~~~~~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/destructuring-assignment/tuple_destructure.rs b/tests/ui/destructuring-assignment/tuple_destructure.rs new file mode 100644 index 000000000..2a8584029 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_destructure.rs @@ -0,0 +1,37 @@ +// run-pass + +fn main() { + let (mut a, mut b); + (a, b) = (0, 1); + assert_eq!((a, b), (0, 1)); + (b, a) = (a, b); + assert_eq!((a, b), (1, 0)); + (a, .., b) = (1, 2); + assert_eq!((a, b), (1, 2)); + (.., a) = (1, 2); + assert_eq!((a, b), (2, 2)); + (..) = (3, 4); + assert_eq!((a, b), (2, 2)); + (b, ..) = (5, 6, 7); + assert_eq!(b, 5); + (a, _) = (8, 9); + assert_eq!(a, 8); + + // Test for a non-Copy type (String): + let (mut c, mut d); + (c, d) = ("c".to_owned(), "d".to_owned()); + assert_eq!(c, "c"); + assert_eq!(d, "d"); + (d, c) = (c, d); + assert_eq!(c, "d"); + assert_eq!(d, "c"); + + // Test nesting/parentheses: + ((a, b)) = (0, 1); + assert_eq!((a, b), (0, 1)); + (((a, b)), (c)) = ((2, 3), d); + assert_eq!((a, b), (2, 3)); + assert_eq!(c, "c"); + ((a, .., b), .., (..)) = ((4, 5), ()); + assert_eq!((a, b), (4, 5)); +} diff --git a/tests/ui/destructuring-assignment/tuple_destructure_fail.rs b/tests/ui/destructuring-assignment/tuple_destructure_fail.rs new file mode 100644 index 000000000..4e3172d19 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_destructure_fail.rs @@ -0,0 +1,9 @@ +const C: i32 = 1; + +fn main() { + let (mut a, mut b); + (a, .., b, ..) = (0, 1); //~ ERROR `..` can only be used once per tuple pattern + (a, a, b) = (1, 2); //~ ERROR mismatched types + (C, ..) = (0,1); //~ ERROR invalid left-hand side of assignment + (_,) = (1, 2); //~ ERROR mismatched types +} diff --git a/tests/ui/destructuring-assignment/tuple_destructure_fail.stderr b/tests/ui/destructuring-assignment/tuple_destructure_fail.stderr new file mode 100644 index 000000000..a3004cbbe --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_destructure_fail.stderr @@ -0,0 +1,42 @@ +error: `..` can only be used once per tuple pattern + --> $DIR/tuple_destructure_fail.rs:5:16 + | +LL | (a, .., b, ..) = (0, 1); + | -- ^^ can only be used once per tuple pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/tuple_destructure_fail.rs:6:5 + | +LL | (a, a, b) = (1, 2); + | ^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `({integer}, {integer})` + found tuple `(_, _, _)` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_destructure_fail.rs:7:13 + | +LL | (C, ..) = (0,1); + | - ^ + | | + | cannot assign to this expression + +error[E0308]: mismatched types + --> $DIR/tuple_destructure_fail.rs:8:5 + | +LL | (_,) = (1, 2); + | ^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element + | + = note: expected tuple `({integer}, {integer})` + found tuple `(_,)` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0308. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/destructuring-assignment/tuple_struct_destructure.rs b/tests/ui/destructuring-assignment/tuple_struct_destructure.rs new file mode 100644 index 000000000..07b5f7a31 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_struct_destructure.rs @@ -0,0 +1,34 @@ +// run-pass + +struct TupleStruct(S, T); + +impl TupleStruct { + fn assign(self, first: &mut S, second: &mut T) { + // Test usage of `Self` instead of the struct name: + Self(*first, *second) = self + } +} + +enum Enum { + SingleVariant(S, T) +} + +type Alias = Enum; + +fn main() { + let (mut a, mut b); + TupleStruct(a, b) = TupleStruct(0, 1); + assert_eq!((a, b), (0, 1)); + TupleStruct(a, .., b) = TupleStruct(1, 2); + assert_eq!((a, b), (1, 2)); + TupleStruct(_, a) = TupleStruct(2, 2); + assert_eq!((a, b), (2, 2)); + TupleStruct(..) = TupleStruct(3, 4); + assert_eq!((a, b), (2, 2)); + TupleStruct(5,6).assign(&mut a, &mut b); + assert_eq!((a, b), (5, 6)); + Enum::SingleVariant(a, b) = Enum::SingleVariant(7, 8); + assert_eq!((a, b), (7, 8)); + Alias::SingleVariant(a, b) = Alias::SingleVariant(9, 10); + assert_eq!((a, b), (9, 10)); +} diff --git a/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs new file mode 100644 index 000000000..845f867d7 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.rs @@ -0,0 +1,44 @@ +struct TupleStruct(S, T); + +enum Enum { + SingleVariant(S, T) +} + +type Alias = Enum; + +trait Test { + fn test() -> TupleStruct { + TupleStruct(0, 0) + } +} + +impl Test for Alias {} + +fn test() -> TupleStruct { + TupleStruct(0, 0) +} + +fn main() { + let (mut a, mut b); + TupleStruct(a, .., b, ..) = TupleStruct(0, 1); + //~^ ERROR `..` can only be used once per tuple struct or variant pattern + Enum::SingleVariant(a, .., b, ..) = Enum::SingleVariant(0, 1); + //~^ ERROR `..` can only be used once per tuple struct or variant pattern + + TupleStruct(a, a, b) = TupleStruct(1, 2); + //~^ ERROR this pattern has 3 fields, but the corresponding tuple struct has 2 fields + TupleStruct(_) = TupleStruct(1, 2); + //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields + Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2); + //~^ ERROR this pattern has 3 fields, but the corresponding tuple variant has 2 fields + Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); + //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields + + // Check if `test` is recognized as not a tuple struct but a function call: + test() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment + (test)() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment + as Test>::test() = TupleStruct(0, 0); + //~^ ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr new file mode 100644 index 000000000..5cc7acba3 --- /dev/null +++ b/tests/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -0,0 +1,98 @@ +error: `..` can only be used once per tuple struct or variant pattern + --> $DIR/tuple_struct_destructure_fail.rs:23:27 + | +LL | TupleStruct(a, .., b, ..) = TupleStruct(0, 1); + | -- ^^ can only be used once per tuple struct or variant pattern + | | + | previously used here + +error: `..` can only be used once per tuple struct or variant pattern + --> $DIR/tuple_struct_destructure_fail.rs:25:35 + | +LL | Enum::SingleVariant(a, .., b, ..) = Enum::SingleVariant(0, 1); + | -- ^^ can only be used once per tuple struct or variant pattern + | | + | previously used here + +error[E0023]: this pattern has 3 fields, but the corresponding tuple struct has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:28:17 + | +LL | struct TupleStruct(S, T); + | - - tuple struct has 2 fields +... +LL | TupleStruct(a, a, b) = TupleStruct(1, 2); + | ^ ^ ^ expected 2 fields, found 3 + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:30:17 + | +LL | struct TupleStruct(S, T); + | - - tuple struct has 2 fields +... +LL | TupleStruct(_) = TupleStruct(1, 2); + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | TupleStruct(_, _) = TupleStruct(1, 2); + | +++ +help: use `..` to ignore all fields + | +LL | TupleStruct(..) = TupleStruct(1, 2); + | ~~ + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:32:25 + | +LL | SingleVariant(S, T) + | - - tuple variant has 2 fields +... +LL | Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2); + | ^ ^ ^ expected 2 fields, found 3 + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/tuple_struct_destructure_fail.rs:34:25 + | +LL | SingleVariant(S, T) + | - - tuple variant has 2 fields +... +LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); + | +++ +help: use `..` to ignore all fields + | +LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); + | ~~ + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:38:12 + | +LL | test() = TupleStruct(0, 0); + | ------ ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:40:14 + | +LL | (test)() = TupleStruct(0, 0); + | -------- ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/tuple_struct_destructure_fail.rs:42:38 + | +LL | as Test>::test() = TupleStruct(0, 0); + | -------------------------------- ^ + | | + | cannot assign to this expression + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0023, E0070. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/destructuring-assignment/warn-unused-duplication.rs b/tests/ui/destructuring-assignment/warn-unused-duplication.rs new file mode 100644 index 000000000..390f44b8a --- /dev/null +++ b/tests/ui/destructuring-assignment/warn-unused-duplication.rs @@ -0,0 +1,21 @@ +// run-pass + +#![warn(unused_assignments)] + +fn main() { + let mut a; + // Assignment occurs left-to-right. + // However, we emit warnings when this happens, so it is clear that this is happening. + (a, a) = (0, 1); //~ WARN value assigned to `a` is never read + assert_eq!(a, 1); + + // We can't always tell when a variable is being assigned to twice, which is why we don't try + // to emit an error, which would be fallible. + let mut x = 1; + (*foo(&mut x), *foo(&mut x)) = (5, 6); + assert_eq!(x, 6); +} + +fn foo<'a>(x: &'a mut u32) -> &'a mut u32 { + x +} diff --git a/tests/ui/destructuring-assignment/warn-unused-duplication.stderr b/tests/ui/destructuring-assignment/warn-unused-duplication.stderr new file mode 100644 index 000000000..e16625136 --- /dev/null +++ b/tests/ui/destructuring-assignment/warn-unused-duplication.stderr @@ -0,0 +1,15 @@ +warning: value assigned to `a` is never read + --> $DIR/warn-unused-duplication.rs:9:6 + | +LL | (a, a) = (0, 1); + | ^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/warn-unused-duplication.rs:3:9 + | +LL | #![warn(unused_assignments)] + | ^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs new file mode 100644 index 000000000..7e6b71408 --- /dev/null +++ b/tests/ui/diagnostic-width/E0271.rs @@ -0,0 +1,33 @@ +// compile-flags: --diagnostic-width=40 +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" +trait Future { + type Error; +} + +impl Future for Result { + type Error = E; +} + +impl Future for Option { + type Error = (); +} + +struct Foo; + +fn foo() -> Box> { + Box::new( //~ ERROR E0271 + Ok::<_, ()>( + Err::<(), _>( + Ok::<_, ()>( + Err::<(), _>( + Ok::<_, ()>( + Err::<(), _>(Some(5)) + ) + ) + ) + ) + ) + ) +} +fn main() { +} diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.stderr new file mode 100644 index 000000000..ed7b6651d --- /dev/null +++ b/tests/ui/diagnostic-width/E0271.stderr @@ -0,0 +1,23 @@ +error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` + --> $DIR/E0271.rs:18:5 + | +LL | / Box::new( +LL | | Ok::<_, ()>( +LL | | Err::<(), _>( +LL | | Ok::<_, ()>( +... | +LL | | ) +LL | | ) + | |_____^ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` + | +note: expected this to be `Foo` + --> $DIR/E0271.rs:8:18 + | +LL | type Error = E; + | ^ + = note: required for the cast from `Result, ...>` to the object type `dyn Future` + = note: the full name for the casted type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271/E0271.long-type-hash.txt' + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic-width/flag-human.rs b/tests/ui/diagnostic-width/flag-human.rs new file mode 100644 index 000000000..289bfbabd --- /dev/null +++ b/tests/ui/diagnostic-width/flag-human.rs @@ -0,0 +1,9 @@ +// compile-flags: --diagnostic-width=20 + +// This test checks that `-Z output-width` effects the human error output by restricting it to an +// arbitrarily low value so that the effect is visible. + +fn main() { + let _: () = 42; + //~^ ERROR mismatched types +} diff --git a/tests/ui/diagnostic-width/flag-human.stderr b/tests/ui/diagnostic-width/flag-human.stderr new file mode 100644 index 000000000..393dcf2b8 --- /dev/null +++ b/tests/ui/diagnostic-width/flag-human.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/flag-human.rs:7:17 + | +LL | ..._: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/flag-json.rs b/tests/ui/diagnostic-width/flag-json.rs new file mode 100644 index 000000000..51a1fb447 --- /dev/null +++ b/tests/ui/diagnostic-width/flag-json.rs @@ -0,0 +1,9 @@ +// compile-flags: --diagnostic-width=20 --error-format=json + +// This test checks that `-Z output-width` effects the JSON error output by restricting it to an +// arbitrarily low value so that the effect is visible. + +fn main() { + let _: () = 42; + //~^ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/diagnostic-width/flag-json.stderr b/tests/ui/diagnostic-width/flag-json.stderr new file mode 100644 index 000000000..b21391d16 --- /dev/null +++ b/tests/ui/diagnostic-width/flag-json.stderr @@ -0,0 +1,40 @@ +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/flag-json.rs","byte_start":243,"byte_end":245,"line_start":7,"line_end":7,"column_start":17,"column_end":19,"is_primary":true,"text":[{"text":" let _: () = 42;","highlight_start":17,"highlight_end":19}],"label":"expected `()`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/flag-json.rs","byte_start":238,"byte_end":240,"line_start":7,"line_end":7,"column_start":12,"column_end":14,"is_primary":false,"text":[{"text":" let _: () = 42;","highlight_start":12,"highlight_end":14}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0308]: mismatched types + --> $DIR/flag-json.rs:7:17 + | +LL | ..._: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +"} +{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error + +"} +{"message":"For more information about this error, try `rustc --explain E0308`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0308`. +"} diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs new file mode 100644 index 000000000..f021f1029 --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0308.rs @@ -0,0 +1,97 @@ +// compile-flags: --diagnostic-width=60 +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +mod a { + // Force the "short path for unique types" machinery to trip up + pub struct Atype; + pub struct Btype; + pub struct Ctype; +} + +mod b { + pub struct Atype(T, K); + pub struct Btype(T, K); + pub struct Ctype(T, K); +} + +use b::*; + +fn main() { + let x: Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok("") + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))))))))); + //~^^^^^ ERROR E0308 + + let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(""))))))))) + ))))))))))))))))) + )))))))))))))))))) + ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))); + //~^^^^^ ERROR E0308 + + let x: Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + > = (); + //~^ ERROR E0308 + + let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))); + //~^^^^^ ERROR E0308 +} diff --git a/tests/ui/diagnostic-width/long-E0308.stderr b/tests/ui/diagnostic-width/long-E0308.stderr new file mode 100644 index 000000000..1c99898bc --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0308.stderr @@ -0,0 +1,80 @@ +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:44:9 + | +LL | let x: Atype< + | _____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... + | | _____-___^ + | ||_____| + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... +LL | | Ok("") +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))))))))); + | |__________________________________^ expected struct `Atype`, found enum `Result` + | + = note: expected struct `Atype, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found enum `Result, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:57:26 + | +LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... + | __________________________^ +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))); + | |____________________________^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found enum `Result, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:88:9 + | +LL | let x: Atype< + | ____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = (); + | | - ^^ expected struct `Atype`, found `()` + | |_____| + | expected due to this + | + = note: expected struct `Atype, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:91:17 + | +LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... + | ____________--___^ + | | | + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))); + | |____________________________^ expected `()`, found enum `Result` + | + = note: expected unit type `()` + found enum `Result, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs new file mode 100644 index 000000000..1989ea886 --- /dev/null +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs @@ -0,0 +1,7 @@ +// ignore-tidy-linelength + +fn main() { + let unicode_is_fun = "Ø‱ஹ௸௵꧄.ဪ꧅⸻𒈙ð’«ï·½ð’Œ„𒈟ð’¼ð’Žð’€±ð’Œ§ð’…ƒ 𒈓ð’™ð’ŠŽð’„¡ð’…Œð’ð’€°ð’ªð’©ð’ˆ™ð’«ðªš¥"; + let _ = "ༀà¼à¼‚༃༄༅༆༇༈༉༊་༌à¼à¼Žà¼à¼à¼‘༒༓༔༕༖༗༘༙༚༛༜à¼à¼žà¼Ÿà¼ à¼¡à¼¢à¼£à¼¤à¼¥à¼¦à¼§à¼¨à¼©à¼ªà¼«à¼¬à¼­à¼®à¼¯à¼°à¼±à¼²à¼³à¼´à¼µà¼¶à¼·à¼¸à¼¹à¼ºà¼»à¼¼à¼½à¼¾à¼¿à½€à½à½‚གྷངཅཆཇ཈ཉཊཋཌà½à½Žà½à½à½‘དྷནཔཕབབྷམཙཚཛཛྷà½à½žà½Ÿà½ à½¡à½¢à½£à½¤à½¥à½¦à½§à½¨à½©à½ªà½«à½¬à½­à½®à½¯à½°à½±à½²à½³à½´à½µà½¶à½·à½¸à½¹à½ºà½»à½¼à½½à½¾à½¿à¾€à¾à¾‚྄ྃ྅྆྇ྈྉྊྋྌà¾à¾Žà¾à¾à¾‘ྒྒྷྔྕྖྗ྘ྙྚྛྜà¾à¾žà¾Ÿà¾ à¾¡à¾¢à¾£à¾¤à¾¥à¾¦à¾§à¾¨à¾©à¾ªà¾«à¾¬à¾­à¾®à¾¯à¾°à¾±à¾²à¾³à¾´à¾µà¾¶à¾·à¾¸à¾¹à¾ºà¾»à¾¼à¾½à¾¾à¾¿à¿€à¿à¿‚࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌à¿à¿Žà¿à¿à¿‘࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + //~^ ERROR cannot add `&str` to `&str` +} diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr new file mode 100644 index 000000000..bf277362d --- /dev/null +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr @@ -0,0 +1,18 @@ +error[E0369]: cannot add `&str` to `&str` + --> $DIR/non-1-width-unicode-multiline-label.rs:5:260 + | +LL | ...ཽཾཿྀà¾à¾‚྄ྃ྅྆྇ྈྉྊྋྌà¾à¾Žà¾à¾à¾‘ྒྒྷྔྕྖྗ྘ྙྚྛྜà¾à¾žà¾Ÿà¾ à¾¡à¾¢à¾£à¾¤à¾¥à¾¦à¾§à¾¨à¾©à¾ªà¾«à¾¬à¾­à¾®à¾¯à¾°à¾±à¾²à¾³à¾´à¾µà¾¶à¾·à¾¸à¾¹à¾ºà¾»à¾¼à¾½à¾¾à¾¿à¿€à¿à¿‚࿃࿄࿅࿆࿇...à¿‹à¿Œà¿à¿Žà¿à¿à¿‘࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + | -------------- ^ -------------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = "ༀà¼à¼‚༃༄༅༆༇༈༉༊་༌à¼à¼Žà¼à¼à¼‘༒༓༔༕༖༗༘༙༚༛༜à¼à¼žà¼Ÿà¼ à¼¡à¼¢à¼£à¼¤à¼¥à¼¦à¼§à¼¨à¼©à¼ªà¼«à¼¬à¼­à¼®à¼¯à¼°à¼±à¼²à¼³à¼´à¼µà¼¶à¼·à¼¸à¼¹à¼ºà¼»à¼¼à¼½à¼¾à¼¿à½€à½à½‚གྷངཅཆཇ཈ཉཊཋཌà½à½Žà½à½à½‘དྷནཔཕབབྷམཙཚཛཛྷà½à½žà½Ÿà½ à½¡à½¢à½£à½¤à½¥à½¦à½§à½¨à½©à½ªà½«à½¬à½­à½®à½¯à½°à½±à½²à½³à½´à½µà½¶à½·à½¸à½¹à½ºà½»à½¼à½½à½¾à½¿à¾€à¾à¾‚྄ྃ྅྆྇ྈྉྊྋྌà¾à¾Žà¾à¾à¾‘ྒྒྷྔྕྖྗ྘ྙྚྛྜà¾à¾žà¾Ÿà¾ à¾¡à¾¢à¾£à¾¤à¾¥à¾¦à¾§à¾¨à¾©à¾ªà¾«à¾¬à¾­à¾®à¾¯à¾°à¾±à¾²à¾³à¾´à¾µà¾¶à¾·à¾¸à¾¹à¾ºà¾»à¾¼à¾½à¾¾à¾¿à¿€à¿à¿‚࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌à¿à¿Žà¿à¿à¿‘࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs new file mode 100644 index 000000000..abd9e189a --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; +//~^ ERROR mismatched types +} diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr new file mode 100644 index 000000000..5dbb9ce45 --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-2.rs:4:311 + | +LL | ...13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let ... + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs new file mode 100644 index 000000000..8d4d1b162 --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: &str = "🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓ ☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀🦀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓ ☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4🦀🦀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄♅♆♇â™â™”♕♖♗♘♙♚♛♜â™â™žâ™Ÿâ™ â™¡â™¢â™£â™¤â™¥â™¦â™§â™¨â™©â™ªâ™«â™¬â™­â™®â™¯â™°â™±â™²â™³â™´â™µâ™¶â™·â™¸â™¹â™ºâ™»â™¼â™½â™¾â™¿âš€âšâš‚⚃⚄⚅⚆⚈⚉4"; +//~^ ERROR mismatched types +} diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr new file mode 100644 index 000000000..1e5ff9398 --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-unicode.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming-unicode.rs:4:415 + | +LL | ...♭♮♯♰♱♲♳♴♵♶♷♸♹♺♻♼♽♾♿⚀âšâš‚⚃⚄⚅⚆⚈⚉4"; let _: () = 42; let _: &str = "🦀☀â˜â˜‚☃☄★☆☇☈☉☊☋☌â˜â˜Žâ˜â˜â˜‘☒☓ ☖☗☘☙☚☛☜â˜â˜žâ˜Ÿâ˜ â˜¡â˜¢â˜£â˜¤â˜¥â˜¦â˜§â˜¨â˜©â˜ªâ˜«â˜¬â˜­â˜®â˜¯â˜°â˜±â˜²â˜³â˜´â˜µâ˜¶â˜·â˜¸â˜¹â˜ºâ˜»â˜¼â˜½â˜¾â˜¿â™€â™â™‚♃♄... + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.rs b/tests/ui/diagnostic-width/non-whitespace-trimming.rs new file mode 100644 index 000000000..f6c8d345c --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = (); +//~^ ERROR mismatched types +} diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr new file mode 100644 index 000000000..c4ff0e168 --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/non-whitespace-trimming.rs:4:241 + | +LL | ... () = (); let _: () = (); let _: () = (); let _: () = 42; let _: () = (); let _: () = (); let _: () = (); let _: () = (); let _: () = ... + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/tabs-trimming.rs b/tests/ui/diagnostic-width/tabs-trimming.rs new file mode 100644 index 000000000..ade21753b --- /dev/null +++ b/tests/ui/diagnostic-width/tabs-trimming.rs @@ -0,0 +1,13 @@ +// Test for #78438: ensure underline alignment with many tabs on the left, long line on the right + +// ignore-tidy-linelength +// ignore-tidy-tab + + fn main() { + let money = 42i32; + match money { + v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT + //~^ ERROR variable `v` is not bound in all patterns + v => println!("Enough money {}", v), + } + } diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr new file mode 100644 index 000000000..6c8d9afc7 --- /dev/null +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -0,0 +1,12 @@ +error[E0408]: variable `v` is not bound in all patterns + --> $DIR/tabs-trimming.rs:9:16 + | +LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... + | - ^ ^ pattern doesn't bind `v` + | | | + | | pattern doesn't bind `v` + | variable not in all patterns + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/diagnostic-width/whitespace-trimming-2.rs b/tests/ui/diagnostic-width/whitespace-trimming-2.rs new file mode 100644 index 000000000..c68f678aa --- /dev/null +++ b/tests/ui/diagnostic-width/whitespace-trimming-2.rs @@ -0,0 +1,8 @@ +// ignore-tidy-linelength + +fn foo() -> usize { + () +//~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/whitespace-trimming-2.stderr b/tests/ui/diagnostic-width/whitespace-trimming-2.stderr new file mode 100644 index 000000000..97a64e603 --- /dev/null +++ b/tests/ui/diagnostic-width/whitespace-trimming-2.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming-2.rs:4:187 + | +LL | ...-> usize { + | ----- expected `usize` because of return type +LL | ... () + | ^^ expected `usize`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/whitespace-trimming.rs b/tests/ui/diagnostic-width/whitespace-trimming.rs new file mode 100644 index 000000000..f747bcf17 --- /dev/null +++ b/tests/ui/diagnostic-width/whitespace-trimming.rs @@ -0,0 +1,6 @@ +// ignore-tidy-linelength + +fn main() { + let _: () = 42; +//~^ ERROR mismatched types +} diff --git a/tests/ui/diagnostic-width/whitespace-trimming.stderr b/tests/ui/diagnostic-width/whitespace-trimming.stderr new file mode 100644 index 000000000..e296d4889 --- /dev/null +++ b/tests/ui/diagnostic-width/whitespace-trimming.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/whitespace-trimming.rs:4:193 + | +LL | ... let _: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/E0178.rs b/tests/ui/did_you_mean/E0178.rs new file mode 100644 index 000000000..095df640c --- /dev/null +++ b/tests/ui/did_you_mean/E0178.rs @@ -0,0 +1,13 @@ +#![allow(bare_trait_objects)] + +trait Foo {} + +struct Bar<'a> { + w: &'a Foo + Copy, //~ ERROR expected a path + x: &'a Foo + 'a, //~ ERROR expected a path + y: &'a mut Foo + 'a, //~ ERROR expected a path + z: fn() -> Foo + 'a, //~ ERROR expected a path +} + +fn main() { +} diff --git a/tests/ui/did_you_mean/E0178.stderr b/tests/ui/did_you_mean/E0178.stderr new file mode 100644 index 000000000..58ac6e908 --- /dev/null +++ b/tests/ui/did_you_mean/E0178.stderr @@ -0,0 +1,27 @@ +error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo` + --> $DIR/E0178.rs:6:8 + | +LL | w: &'a Foo + Copy, + | ^^^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + Copy)` + +error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo` + --> $DIR/E0178.rs:7:8 + | +LL | x: &'a Foo + 'a, + | ^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + 'a)` + +error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo` + --> $DIR/E0178.rs:8:8 + | +LL | y: &'a mut Foo + 'a, + | ^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'a mut (Foo + 'a)` + +error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo` + --> $DIR/E0178.rs:9:8 + | +LL | z: fn() -> Foo + 'a, + | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0178`. diff --git a/tests/ui/did_you_mean/bad-assoc-expr.rs b/tests/ui/did_you_mean/bad-assoc-expr.rs new file mode 100644 index 000000000..1d584757f --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-expr.rs @@ -0,0 +1,36 @@ +fn main() { + let a = [1, 2, 3, 4]; + [i32; 4]::clone(&a); + //~^ ERROR missing angle brackets in associated item path + + [i32]::as_ref(&a); + //~^ ERROR missing angle brackets in associated item path + + (u8)::clone(&0); + //~^ ERROR missing angle brackets in associated item path + + (u8, u8)::clone(&(0, 0)); + //~^ ERROR missing angle brackets in associated item path + + &(u8)::clone(&0); + //~^ ERROR missing angle brackets in associated item path + + 10 + (u8)::clone(&0); + //~^ ERROR missing angle brackets in associated item path +} + +macro_rules! expr { + ($ty: ty) => ($ty::clone(&0)) + //~^ ERROR missing angle brackets in associated item path +} +macro_rules! ty { + () => (u8) +} + +fn check_macros() { + expr!(u8); + let _ = ty!()::clone(&0); + //~^ ERROR missing angle brackets in associated item path + ty!()::clone(&0); + //~^ ERROR missing angle brackets in associated item path +} diff --git a/tests/ui/did_you_mean/bad-assoc-expr.stderr b/tests/ui/did_you_mean/bad-assoc-expr.stderr new file mode 100644 index 000000000..c295cac9a --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-expr.stderr @@ -0,0 +1,61 @@ +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:3:5 + | +LL | [i32; 4]::clone(&a); + | ^^^^^^^^^^^^^^^ help: try: `<[i32; 4]>::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:6:5 + | +LL | [i32]::as_ref(&a); + | ^^^^^^^^^^^^^ help: try: `<[i32]>::as_ref` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:9:5 + | +LL | (u8)::clone(&0); + | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:12:5 + | +LL | (u8, u8)::clone(&(0, 0)); + | ^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:15:6 + | +LL | &(u8)::clone(&0); + | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:18:10 + | +LL | 10 + (u8)::clone(&0); + | ^^^^^^^^^^^ help: try: `<(u8)>::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:32:13 + | +LL | let _ = ty!()::clone(&0); + | ^^^^^^^^^^^^ help: try: `::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:34:5 + | +LL | ty!()::clone(&0); + | ^^^^^^^^^^^^ help: try: `::clone` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-expr.rs:23:19 + | +LL | ($ty: ty) => ($ty::clone(&0)) + | ^^^^^^^^^^ help: try: `<$ty>::clone` +... +LL | expr!(u8); + | --------- in this macro invocation + | + = note: this error originates in the macro `expr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 9 previous errors + diff --git a/tests/ui/did_you_mean/bad-assoc-pat.rs b/tests/ui/did_you_mean/bad-assoc-pat.rs new file mode 100644 index 000000000..3f912f7ff --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-pat.rs @@ -0,0 +1,36 @@ +fn main() { + match 0u8 { + [u8]::AssocItem => {} + //~^ ERROR missing angle brackets in associated item path + //~| ERROR no associated item named `AssocItem` found + (u8, u8)::AssocItem => {} + //~^ ERROR missing angle brackets in associated item path + //~| ERROR no associated item named `AssocItem` found + _::AssocItem => {} + //~^ ERROR missing angle brackets in associated item path + //~| ERROR no associated item named `AssocItem` found + } + match &0u8 { + &(u8,)::AssocItem => {} + //~^ ERROR missing angle brackets in associated item path + //~| ERROR no associated item named `AssocItem` found + } +} + +macro_rules! pat { + ($ty: ty) => ($ty::AssocItem) + //~^ ERROR missing angle brackets in associated item path + //~| ERROR no associated item named `AssocItem` found +} +macro_rules! ty { + () => (u8) +} + +fn check_macros() { + match 0u8 { + pat!(u8) => {} + ty!()::AssocItem => {} + //~^ ERROR missing angle brackets in associated item path + //~| ERROR no associated item named `AssocItem` found + } +} diff --git a/tests/ui/did_you_mean/bad-assoc-pat.stderr b/tests/ui/did_you_mean/bad-assoc-pat.stderr new file mode 100644 index 000000000..19d173f1b --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-pat.stderr @@ -0,0 +1,85 @@ +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-pat.rs:3:9 + | +LL | [u8]::AssocItem => {} + | ^^^^^^^^^^^^^^^ help: try: `<[u8]>::AssocItem` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-pat.rs:6:9 + | +LL | (u8, u8)::AssocItem => {} + | ^^^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocItem` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-pat.rs:9:9 + | +LL | _::AssocItem => {} + | ^^^^^^^^^^^^ help: try: `<_>::AssocItem` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-pat.rs:14:10 + | +LL | &(u8,)::AssocItem => {} + | ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-pat.rs:32:9 + | +LL | ty!()::AssocItem => {} + | ^^^^^^^^^^^^^^^^ help: try: `::AssocItem` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-pat.rs:21:19 + | +LL | ($ty: ty) => ($ty::AssocItem) + | ^^^^^^^^^^^^^^ help: try: `<$ty>::AssocItem` +... +LL | pat!(u8) => {} + | -------- in this macro invocation + | + = note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: no associated item named `AssocItem` found for slice `[u8]` in the current scope + --> $DIR/bad-assoc-pat.rs:3:15 + | +LL | [u8]::AssocItem => {} + | ^^^^^^^^^ associated item not found in `[u8]` + +error[E0599]: no associated item named `AssocItem` found for tuple `(u8, u8)` in the current scope + --> $DIR/bad-assoc-pat.rs:6:19 + | +LL | (u8, u8)::AssocItem => {} + | ^^^^^^^^^ associated item not found in `(u8, u8)` + +error[E0599]: no associated item named `AssocItem` found for type `_` in the current scope + --> $DIR/bad-assoc-pat.rs:9:12 + | +LL | _::AssocItem => {} + | ^^^^^^^^^ associated item not found in `_` + +error[E0599]: no associated item named `AssocItem` found for tuple `(u8,)` in the current scope + --> $DIR/bad-assoc-pat.rs:14:17 + | +LL | &(u8,)::AssocItem => {} + | ^^^^^^^^^ associated item not found in `(u8,)` + +error[E0599]: no associated item named `AssocItem` found for type `u8` in the current scope + --> $DIR/bad-assoc-pat.rs:21:24 + | +LL | ($ty: ty) => ($ty::AssocItem) + | ^^^^^^^^^ associated item not found in `u8` +... +LL | pat!(u8) => {} + | -------- in this macro invocation + | + = note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: no associated item named `AssocItem` found for type `u8` in the current scope + --> $DIR/bad-assoc-pat.rs:32:16 + | +LL | ty!()::AssocItem => {} + | ^^^^^^^^^ associated item not found in `u8` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/did_you_mean/bad-assoc-ty.rs b/tests/ui/did_you_mean/bad-assoc-ty.rs new file mode 100644 index 000000000..f787c416c --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-ty.rs @@ -0,0 +1,85 @@ +type A = [u8; 4]::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +type B = [u8]::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +type C = (u8)::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +type D = (u8, u8)::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +type E = _::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR the placeholder `_` is not allowed within types on item signatures for type aliases + +type F = &'static (u8)::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +// Qualified paths cannot appear in bounds, so the recovery +// should apply to the whole sum and not `(Send)`. +type G = dyn 'static + (Send)::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +// This is actually a legal path with fn-like generic arguments in the middle! +// Recovery should not apply in this context. +type H = Fn(u8) -> (u8)::Output; +//~^ ERROR ambiguous associated type +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +macro_rules! ty { + ($ty: ty) => ($ty::AssocTy); + //~^ ERROR missing angle brackets in associated item path + //~| ERROR ambiguous associated type + () => (u8); +} + +type J = ty!(u8); +type I = ty!()::AssocTy; +//~^ ERROR missing angle brackets in associated item path +//~| ERROR ambiguous associated type + +trait K {} +fn foo>(x: X) {} +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn bar(_: F) where F: Fn() -> _ {} +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn baz _>(_: F) {} +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +struct L(F) where F: Fn() -> _; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs +struct M where F: Fn() -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs + a: F, +} +enum N where F: Fn() -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for enums + Foo(F), +} + +union O where F: Fn() -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for unions + foo: F, +} + +trait P where F: Fn() -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for traits +} + +trait Q { + fn foo(_: F) where F: Fn() -> _ {} + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +fn main() {} diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr new file mode 100644 index 000000000..55096e95d --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -0,0 +1,282 @@ +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:1:10 + | +LL | type A = [u8; 4]::AssocTy; + | ^^^^^^^^^^^^^^^^ help: try: `<[u8; 4]>::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:5:10 + | +LL | type B = [u8]::AssocTy; + | ^^^^^^^^^^^^^ help: try: `<[u8]>::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:9:10 + | +LL | type C = (u8)::AssocTy; + | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:13:10 + | +LL | type D = (u8, u8)::AssocTy; + | ^^^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:17:10 + | +LL | type E = _::AssocTy; + | ^^^^^^^^^^ help: try: `<_>::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:21:19 + | +LL | type F = &'static (u8)::AssocTy; + | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:27:10 + | +LL | type G = dyn 'static + (Send)::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:46:10 + | +LL | type I = ty!()::AssocTy; + | ^^^^^^^^^^^^^^ help: try: `::AssocTy` + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:39:19 + | +LL | ($ty: ty) => ($ty::AssocTy); + | ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy` +... +LL | type J = ty!(u8); + | ------- in this macro invocation + | + = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:1:10 + | +LL | type A = [u8; 4]::AssocTy; + | ^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path + | +LL | type A = <[u8; 4] as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:5:10 + | +LL | type B = [u8]::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path + | +LL | type B = <[u8] as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:9:10 + | +LL | type C = (u8)::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type C = ::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:13:10 + | +LL | type D = (u8, u8)::AssocTy; + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path + | +LL | type D = <(u8, u8) as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases + --> $DIR/bad-assoc-ty.rs:17:10 + | +LL | type E = _::AssocTy; + | ^ not allowed in type signatures + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:21:19 + | +LL | type F = &'static (u8)::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type F = &'static ::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:27:10 + | +LL | type G = dyn 'static + (Send)::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path + | +LL | type G = <(dyn Send + 'static) as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bad-assoc-ty.rs:33:10 + | +LL | type H = Fn(u8) -> (u8)::Output; + | ^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | type H = (u8)>::Output; + | ++++ + + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:33:10 + | +LL | type H = Fn(u8) -> (u8)::Output; + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:39:19 + | +LL | ($ty: ty) => ($ty::AssocTy); + | ^^^^^^^^^^^^ +... +LL | type J = ty!(u8); + | ------- in this macro invocation + | + = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | ($ty: ty) => (::AssocTy); + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:46:10 + | +LL | type I = ty!()::AssocTy; + | ^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type I = ::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:51:13 + | +LL | fn foo>(x: X) {} + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo, T>(x: X) {} + | ~ ~ +++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:54:34 + | +LL | fn bar(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn bar(_: F) where F: Fn() -> T {} + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:57:19 + | +LL | fn baz _>(_: F) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn baz T, T>(_: F) {} + | ~+++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/bad-assoc-ty.rs:60:33 + | +LL | struct L(F) where F: Fn() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct L(F) where F: Fn() -> T; + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/bad-assoc-ty.rs:62:30 + | +LL | struct M where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct M where F: Fn() -> T { + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums + --> $DIR/bad-assoc-ty.rs:66:28 + | +LL | enum N where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | enum N where F: Fn() -> T { + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions + --> $DIR/bad-assoc-ty.rs:71:29 + | +LL | union O where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | union O where F: Fn() -> T { + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits + --> $DIR/bad-assoc-ty.rs:76:29 + | +LL | trait P where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | trait P where F: Fn() -> T { + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:81:38 + | +LL | fn foo(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo(_: F) where F: Fn() -> T {} + | +++ ~ + +error: aborting due to 28 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0121, E0223. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/did_you_mean/brackets-to-braces-single-element.rs b/tests/ui/did_you_mean/brackets-to-braces-single-element.rs new file mode 100644 index 000000000..4d0109767 --- /dev/null +++ b/tests/ui/did_you_mean/brackets-to-braces-single-element.rs @@ -0,0 +1,10 @@ +const A: [&str; 1] = { "hello" }; +//~^ ERROR mismatched types + +const B: &[u32] = &{ 1 }; +//~^ ERROR mismatched types + +const C: &&[u32; 1] = &&{ 1 }; +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr b/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr new file mode 100644 index 000000000..6ded03e45 --- /dev/null +++ b/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/brackets-to-braces-single-element.rs:1:24 + | +LL | const A: [&str; 1] = { "hello" }; + | ^^^^^^^ expected array `[&'static str; 1]`, found `&str` + | +help: to create an array, use square brackets instead of curly braces + | +LL | const A: [&str; 1] = [ "hello" ]; + | ~ ~ + +error[E0308]: mismatched types + --> $DIR/brackets-to-braces-single-element.rs:4:19 + | +LL | const B: &[u32] = &{ 1 }; + | ^^^^^^ expected slice `[u32]`, found integer + | + = note: expected reference `&'static [u32]` + found reference `&{integer}` +help: to create an array, use square brackets instead of curly braces + | +LL | const B: &[u32] = &[ 1 ]; + | ~ ~ + +error[E0308]: mismatched types + --> $DIR/brackets-to-braces-single-element.rs:7:27 + | +LL | const C: &&[u32; 1] = &&{ 1 }; + | ^ expected array `[u32; 1]`, found integer + | +help: to create an array, use square brackets instead of curly braces + | +LL | const C: &&[u32; 1] = &&[ 1 ]; + | ~ ~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/compatible-variants-in-pat.rs b/tests/ui/did_you_mean/compatible-variants-in-pat.rs new file mode 100644 index 000000000..09e12dab2 --- /dev/null +++ b/tests/ui/did_you_mean/compatible-variants-in-pat.rs @@ -0,0 +1,41 @@ +enum Foo { + Bar(Bar), +} +struct Bar { + x: i32, +} + +fn a(f: Foo) { + match f { + Bar { x } => { + //~^ ERROR mismatched types + //~| HELP try wrapping + } + } +} + +struct S; + +fn b(s: Option) { + match s { + S => { + //~^ ERROR mismatched types + //~| HELP try wrapping + //~| HELP introduce a new binding instead + } + _ => {} + } +} + +fn c(s: Result) { + match s { + S => { + //~^ ERROR mismatched types + //~| HELP try wrapping + //~| HELP introduce a new binding instead + } + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/compatible-variants-in-pat.stderr b/tests/ui/did_you_mean/compatible-variants-in-pat.stderr new file mode 100644 index 000000000..473468af6 --- /dev/null +++ b/tests/ui/did_you_mean/compatible-variants-in-pat.stderr @@ -0,0 +1,68 @@ +error[E0308]: mismatched types + --> $DIR/compatible-variants-in-pat.rs:10:9 + | +LL | match f { + | - this expression has type `Foo` +LL | Bar { x } => { + | ^^^^^^^^^ expected enum `Foo`, found struct `Bar` + | +help: try wrapping the pattern in `Foo::Bar` + | +LL | Foo::Bar(Bar { x }) => { + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants-in-pat.rs:21:9 + | +LL | struct S; + | -------- unit struct defined here +... +LL | match s { + | - this expression has type `Option` +LL | S => { + | ^ + | | + | expected enum `Option`, found struct `S` + | `S` is interpreted as a unit struct, not a new binding + | + = note: expected enum `Option` + found struct `S` +help: try wrapping the pattern in `Some` + | +LL | Some(S) => { + | +++++ + +help: introduce a new binding instead + | +LL | other_s => { + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/compatible-variants-in-pat.rs:32:9 + | +LL | struct S; + | -------- unit struct defined here +... +LL | match s { + | - this expression has type `Result` +LL | S => { + | ^ + | | + | expected enum `Result`, found struct `S` + | `S` is interpreted as a unit struct, not a new binding + | + = note: expected enum `Result` + found struct `S` +help: try wrapping the pattern in a variant of `Result` + | +LL | Ok(S) => { + | +++ + +LL | Err(S) => { + | ++++ + +help: introduce a new binding instead + | +LL | other_s => { + | ~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/compatible-variants.rs b/tests/ui/did_you_mean/compatible-variants.rs new file mode 100644 index 000000000..b1c7dc2a7 --- /dev/null +++ b/tests/ui/did_you_mean/compatible-variants.rs @@ -0,0 +1,89 @@ +enum Hey { + A(A), + B(B), +} + +struct Foo { + bar: Option, +} + +fn f() {} + +fn a() -> Option<()> { + while false { + //~^ ERROR mismatched types + f(); + } + //~^ HELP try adding an expression +} + +fn b() -> Result<(), ()> { + f() + //~^ ERROR mismatched types + //~| HELP try adding an expression +} + +fn c() -> Option<()> { + for _ in [1, 2] { + //~^ ERROR mismatched types + f(); + } + //~^ HELP try adding an expression +} + +fn d() -> Option<()> { + c()? + //~^ ERROR incompatible types + //~| HELP try removing this `?` + //~| HELP try adding an expression +} + +fn main() { + let _: Option<()> = while false {}; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Option<()> = { + while false {} + //~^ ERROR mismatched types + //~| HELP try adding an expression + }; + let _: Result = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Option = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Hey = 1; + //~^ ERROR mismatched types + //~| HELP try wrapping + let _: Hey = false; + //~^ ERROR mismatched types + //~| HELP try wrapping + let bar = 1i32; + let _ = Foo { bar }; + //~^ ERROR mismatched types + //~| HELP try wrapping +} + +enum A { + B { b: B }, +} + +struct A2(B); + +enum B { + Fst, + Snd, +} + +fn foo() { + let a: A = B::Fst; + //~^ ERROR mismatched types + //~| HELP try wrapping +} + +fn bar() { + let a: A2 = B::Fst; + //~^ ERROR mismatched types + //~| HELP try wrapping +} diff --git a/tests/ui/did_you_mean/compatible-variants.stderr b/tests/ui/did_you_mean/compatible-variants.stderr new file mode 100644 index 000000000..fe81da198 --- /dev/null +++ b/tests/ui/did_you_mean/compatible-variants.stderr @@ -0,0 +1,221 @@ +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:13:5 + | +LL | fn a() -> Option<()> { + | ---------- expected `Option<()>` because of return type +LL | / while false { +LL | | +LL | | f(); +LL | | } + | |_____^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ } +LL + None + | +LL ~ } +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:21:5 + | +LL | fn b() -> Result<(), ()> { + | -------------- expected `Result<(), ()>` because of return type +LL | f() + | ^^^ expected enum `Result`, found `()` + | + = note: expected enum `Result<(), ()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ f(); +LL + Ok(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:27:5 + | +LL | fn c() -> Option<()> { + | ---------- expected `Option<()>` because of return type +LL | / for _ in [1, 2] { +LL | | +LL | | f(); +LL | | } + | |_____^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ } +LL + None + | +LL ~ } +LL + Some(()) + | + +error[E0308]: `?` operator has incompatible types + --> $DIR/compatible-variants.rs:35:5 + | +LL | c()? + | ^^^^ expected enum `Option`, found `()` + | + = note: `?` operator cannot convert from `()` to `Option<()>` + = note: expected enum `Option<()>` + found unit type `()` +help: try removing this `?` + | +LL - c()? +LL + c() + | +help: try adding an expression at the end of the block + | +LL ~ c()?; +LL + None + | +LL ~ c()?; +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:42:25 + | +LL | let _: Option<()> = while false {}; + | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()` + | | + | expected due to this + | + = note: expected enum `Option<()>` + found unit type `()` +help: try wrapping the expression in `Some` + | +LL | let _: Option<()> = Some(while false {}); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:46:9 + | +LL | while false {} + | ^^^^^^^^^^^^^^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ while false {} +LL + None + | +LL ~ while false {} +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:50:31 + | +LL | let _: Result = 1; + | ---------------- ^ expected enum `Result`, found integer + | | + | expected due to this + | + = note: expected enum `Result` + found type `{integer}` +help: try wrapping the expression in a variant of `Result` + | +LL | let _: Result = Ok(1); + | +++ + +LL | let _: Result = Err(1); + | ++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:53:26 + | +LL | let _: Option = 1; + | ----------- ^ expected enum `Option`, found integer + | | + | expected due to this + | + = note: expected enum `Option` + found type `{integer}` +help: try wrapping the expression in `Some` + | +LL | let _: Option = Some(1); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:56:28 + | +LL | let _: Hey = 1; + | ------------- ^ expected enum `Hey`, found integer + | | + | expected due to this + | + = note: expected enum `Hey` + found type `{integer}` +help: try wrapping the expression in a variant of `Hey` + | +LL | let _: Hey = Hey::A(1); + | +++++++ + +LL | let _: Hey = Hey::B(1); + | +++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:59:29 + | +LL | let _: Hey = false; + | -------------- ^^^^^ expected enum `Hey`, found `bool` + | | + | expected due to this + | + = note: expected enum `Hey` + found type `bool` +help: try wrapping the expression in `Hey::B` + | +LL | let _: Hey = Hey::B(false); + | +++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:63:19 + | +LL | let _ = Foo { bar }; + | ^^^ expected enum `Option`, found `i32` + | + = note: expected enum `Option` + found type `i32` +help: try wrapping the expression in `Some` + | +LL | let _ = Foo { bar: Some(bar) }; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:80:16 + | +LL | let a: A = B::Fst; + | - ^^^^^^ expected enum `A`, found enum `B` + | | + | expected due to this + | +help: try wrapping the expression in `A::B` + | +LL | let a: A = A::B { b: B::Fst }; + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:86:17 + | +LL | let a: A2 = B::Fst; + | -- ^^^^^^ expected struct `A2`, found enum `B` + | | + | expected due to this + | +help: try wrapping the expression in `A2` + | +LL | let a: A2 = A2(B::Fst); + | +++ + + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/issue-103909.rs b/tests/ui/did_you_mean/issue-103909.rs new file mode 100644 index 000000000..20b67cd10 --- /dev/null +++ b/tests/ui/did_you_mean/issue-103909.rs @@ -0,0 +1,9 @@ +#![allow(unused_variables)] +use std::fs::File; + +fn main() { + if Err(err) = File::open("hello.txt") { + //~^ ERROR: cannot find value `err` in this scope + //~| ERROR: mismatched types + } +} diff --git a/tests/ui/did_you_mean/issue-103909.stderr b/tests/ui/did_you_mean/issue-103909.stderr new file mode 100644 index 000000000..864101747 --- /dev/null +++ b/tests/ui/did_you_mean/issue-103909.stderr @@ -0,0 +1,26 @@ +error[E0425]: cannot find value `err` in this scope + --> $DIR/issue-103909.rs:5:12 + | +LL | if Err(err) = File::open("hello.txt") { + | ^^^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let Err(err) = File::open("hello.txt") { + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-103909.rs:5:8 + | +LL | if Err(err) = File::open("hello.txt") { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Err(err) = File::open("hello.txt") { + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs new file mode 100644 index 000000000..1749137d4 --- /dev/null +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs @@ -0,0 +1,26 @@ +trait Foo { + fn foo(&self, a: A) -> A { + a + } +} + +trait NotRelevant { + fn nr(&self, a: A) -> A { + a + } +} + +struct Bar; + +impl Foo for Bar {} + +impl Foo for Bar {} + +impl NotRelevant for Bar {} + +fn main() { + let f1 = Bar; + + f1.foo(1usize); + //~^ error: the trait bound `Bar: Foo` is not satisfied +} diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr new file mode 100644 index 000000000..b69fcd5d3 --- /dev/null +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Bar: Foo` is not satisfied + --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:24:12 + | +LL | f1.foo(1usize); + | --- ^^^^^^ the trait `Foo` is not implemented for `Bar` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + > + > + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs new file mode 100644 index 000000000..e898b224e --- /dev/null +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs @@ -0,0 +1,30 @@ +trait Foo { + fn foo(&self, a: A) -> A { + a + } +} + +trait NotRelevant { + fn nr(&self, a: A) -> A { + a + } +} + +struct Bar; + +impl Foo for Bar {} +impl Foo for Bar {} +impl Foo for Bar {} + +impl Foo for Bar {} +impl Foo for Bar {} +impl Foo for Bar {} + +impl NotRelevant for Bar {} + +fn main() { + let f1 = Bar; + + f1.foo(1usize); + //~^ error: the trait bound `Bar: Foo` is not satisfied +} diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr new file mode 100644 index 000000000..5e0e4a011 --- /dev/null +++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Bar: Foo` is not satisfied + --> $DIR/issue-21659-show-relevant-trait-impls-2.rs:28:12 + | +LL | f1.foo(1usize); + | --- ^^^^^^ the trait `Foo` is not implemented for `Bar` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + > + > + > + > + > + > + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-31424.rs b/tests/ui/did_you_mean/issue-31424.rs new file mode 100644 index 000000000..95ccf2a4c --- /dev/null +++ b/tests/ui/did_you_mean/issue-31424.rs @@ -0,0 +1,21 @@ +// forbid-output: &mut mut self + +struct Struct; + +impl Struct { + fn foo(&mut self) { + (&mut self).bar(); //~ ERROR cannot borrow + //~^ HELP try removing `&mut` here + } + + // In this case we could keep the suggestion, but to distinguish the + // two cases is pretty hard. It's an obscure case anyway. + fn bar(self: &mut Self) { + //~^ WARN function cannot return without recursing + //~^^ HELP a `loop` may express intention better if this is on purpose + (&mut self).bar(); //~ ERROR cannot borrow + //~^ HELP try removing `&mut` here + } +} + +fn main () {} diff --git a/tests/ui/did_you_mean/issue-31424.stderr b/tests/ui/did_you_mean/issue-31424.stderr new file mode 100644 index 000000000..8fe38bf69 --- /dev/null +++ b/tests/ui/did_you_mean/issue-31424.stderr @@ -0,0 +1,49 @@ +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-31424.rs:7:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/issue-31424.rs:6:12 + | +LL | fn foo(&mut self) { + | ^^^^^^^^^ +help: try removing `&mut` here + --> $DIR/issue-31424.rs:7:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ + +warning: function cannot return without recursing + --> $DIR/issue-31424.rs:13:5 + | +LL | fn bar(self: &mut Self) { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | (&mut self).bar(); + | ----------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-31424.rs:16:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/issue-31424.rs:13:18 + | +LL | fn bar(self: &mut Self) { + | ^^^^^^^^^ +help: try removing `&mut` here + --> $DIR/issue-31424.rs:16:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-34126.rs b/tests/ui/did_you_mean/issue-34126.rs new file mode 100644 index 000000000..53516f4f2 --- /dev/null +++ b/tests/ui/did_you_mean/issue-34126.rs @@ -0,0 +1,15 @@ +struct Z { } + +impl Z { + fn run(&self, z: &mut Z) { } + fn start(&mut self) { + self.run(&mut self); //~ ERROR cannot borrow + //~| ERROR cannot borrow + //~| HELP try removing `&mut` here + } +} + +fn main() { + let mut z = Z {}; + z.start(); +} diff --git a/tests/ui/did_you_mean/issue-34126.stderr b/tests/ui/did_you_mean/issue-34126.stderr new file mode 100644 index 000000000..5343acea4 --- /dev/null +++ b/tests/ui/did_you_mean/issue-34126.stderr @@ -0,0 +1,31 @@ +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-34126.rs:6:18 + | +LL | self.run(&mut self); + | ^^^^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/issue-34126.rs:5:14 + | +LL | fn start(&mut self) { + | ^^^^^^^^^ +help: try removing `&mut` here + | +LL - self.run(&mut self); +LL + self.run(self); + | + +error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable + --> $DIR/issue-34126.rs:6:18 + | +LL | self.run(&mut self); + | ---------^^^^^^^^^- + | | | | + | | | mutable borrow occurs here + | | immutable borrow later used by call + | immutable borrow occurs here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0502, E0596. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/did_you_mean/issue-34337.rs b/tests/ui/did_you_mean/issue-34337.rs new file mode 100644 index 000000000..e89eda33f --- /dev/null +++ b/tests/ui/did_you_mean/issue-34337.rs @@ -0,0 +1,8 @@ +fn get(key: &mut String) { } + +fn main() { + let mut v: Vec = Vec::new(); + let ref mut key = v[0]; + get(&mut key); //~ ERROR cannot borrow + //~| HELP try removing `&mut` here +} diff --git a/tests/ui/did_you_mean/issue-34337.stderr b/tests/ui/did_you_mean/issue-34337.stderr new file mode 100644 index 000000000..1f18ea892 --- /dev/null +++ b/tests/ui/did_you_mean/issue-34337.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `key` as mutable, as it is not declared as mutable + --> $DIR/issue-34337.rs:6:9 + | +LL | get(&mut key); + | ^^^^^^^^ + | | + | cannot borrow as mutable + | help: try removing `&mut` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-35937.rs b/tests/ui/did_you_mean/issue-35937.rs new file mode 100644 index 000000000..ebeba74f1 --- /dev/null +++ b/tests/ui/did_you_mean/issue-35937.rs @@ -0,0 +1,21 @@ +struct Foo { + pub v: Vec +} + +fn main() { + let f = Foo { v: Vec::new() }; + f.v.push("cat".to_string()); //~ ERROR cannot borrow +} + + +struct S { + x: i32, +} +fn foo() { + let s = S { x: 42 }; + s.x += 1; //~ ERROR cannot assign +} + +fn bar(s: S) { + s.x += 1; //~ ERROR cannot assign +} diff --git a/tests/ui/did_you_mean/issue-35937.stderr b/tests/ui/did_you_mean/issue-35937.stderr new file mode 100644 index 000000000..1670da559 --- /dev/null +++ b/tests/ui/did_you_mean/issue-35937.stderr @@ -0,0 +1,37 @@ +error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable + --> $DIR/issue-35937.rs:7:5 + | +LL | f.v.push("cat".to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = Foo { v: Vec::new() }; + | +++ + +error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable + --> $DIR/issue-35937.rs:16:5 + | +LL | s.x += 1; + | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut s = S { x: 42 }; + | +++ + +error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable + --> $DIR/issue-35937.rs:20:5 + | +LL | s.x += 1; + | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | fn bar(mut s: S) { + | +++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/did_you_mean/issue-36798.rs b/tests/ui/did_you_mean/issue-36798.rs new file mode 100644 index 000000000..89d71d831 --- /dev/null +++ b/tests/ui/did_you_mean/issue-36798.rs @@ -0,0 +1,8 @@ +struct Foo { + bar: u8 +} + +fn main() { + let f = Foo { bar: 22 }; + f.baz; //~ ERROR no field +} diff --git a/tests/ui/did_you_mean/issue-36798.stderr b/tests/ui/did_you_mean/issue-36798.stderr new file mode 100644 index 000000000..98876e305 --- /dev/null +++ b/tests/ui/did_you_mean/issue-36798.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `baz` on type `Foo` + --> $DIR/issue-36798.rs:7:7 + | +LL | f.baz; + | ^^^ help: a field with a similar name exists: `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/issue-36798_unknown_field.rs b/tests/ui/did_you_mean/issue-36798_unknown_field.rs new file mode 100644 index 000000000..ef9744b4a --- /dev/null +++ b/tests/ui/did_you_mean/issue-36798_unknown_field.rs @@ -0,0 +1,8 @@ +struct Foo { + bar: u8 +} + +fn main() { + let f = Foo { bar: 22 }; + f.zz; //~ ERROR no field +} diff --git a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr new file mode 100644 index 000000000..2ed0a0924 --- /dev/null +++ b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `zz` on type `Foo` + --> $DIR/issue-36798_unknown_field.rs:7:7 + | +LL | f.zz; + | ^^ unknown field + | + = note: available fields are: `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/issue-37139.rs b/tests/ui/did_you_mean/issue-37139.rs new file mode 100644 index 000000000..6a19d85ff --- /dev/null +++ b/tests/ui/did_you_mean/issue-37139.rs @@ -0,0 +1,16 @@ +enum TestEnum { + Item(i32), +} + +fn test(_: &mut i32) { +} + +fn main() { + let mut x = TestEnum::Item(10); + match x { + TestEnum::Item(ref mut x) => { + test(&mut x); //~ ERROR cannot borrow `x` as mutable, as it is not declared as mutable + //~| HELP try removing `&mut` here + } + } +} diff --git a/tests/ui/did_you_mean/issue-37139.stderr b/tests/ui/did_you_mean/issue-37139.stderr new file mode 100644 index 000000000..dc1bdfaae --- /dev/null +++ b/tests/ui/did_you_mean/issue-37139.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/issue-37139.rs:12:18 + | +LL | test(&mut x); + | ^^^^^^ + | | + | cannot borrow as mutable + | help: try removing `&mut` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs b/tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs new file mode 100644 index 000000000..a1ef68ecf --- /dev/null +++ b/tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs @@ -0,0 +1,5 @@ +use Foo; //~ ERROR unresolved + +use Foo1; //~ ERROR unresolved + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr new file mode 100644 index 000000000..852abaed7 --- /dev/null +++ b/tests/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr @@ -0,0 +1,15 @@ +error[E0432]: unresolved import `Foo` + --> $DIR/issue-38054-do-not-show-unresolved-names.rs:1:5 + | +LL | use Foo; + | ^^^ no `Foo` in the root + +error[E0432]: unresolved import `Foo1` + --> $DIR/issue-38054-do-not-show-unresolved-names.rs:3:5 + | +LL | use Foo1; + | ^^^^ no `Foo1` in the root + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/did_you_mean/issue-38147-1.rs b/tests/ui/did_you_mean/issue-38147-1.rs new file mode 100644 index 000000000..c068a1834 --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-1.rs @@ -0,0 +1,21 @@ +struct Pass<'a> { + s: &'a mut String +} + +impl<'a> Pass<'a> { + fn f(&mut self) { + self.s.push('x'); + } +} + +struct Foo<'a> { + s: &'a mut String +} + +impl<'a> Foo<'a> { + fn f(&self) { + self.s.push('x'); //~ cannot borrow `*self.s` as mutable, as it is behind a `&` reference + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-38147-1.stderr b/tests/ui/did_you_mean/issue-38147-1.stderr new file mode 100644 index 000000000..74fb1c2ec --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-1.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference + --> $DIR/issue-38147-1.rs:17:9 + | +LL | self.s.push('x'); + | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f(&mut self) { + | ~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38147-2.rs b/tests/ui/did_you_mean/issue-38147-2.rs new file mode 100644 index 000000000..154b149b7 --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-2.rs @@ -0,0 +1,17 @@ +struct Bar<'a> { + s: &'a String, + // use wonky spaces to ensure we are creating the span correctly + longer_name: & 'a Vec +} + +impl<'a> Bar<'a> { + fn f(&mut self) { + self.s.push('x'); + //~^ ERROR cannot borrow `*self.s` as mutable, as it is behind a `&` reference + + self.longer_name.push(13); + //~^ ERROR cannot borrow `*self.longer_name` as mutable, as it is behind a `&` reference + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-38147-2.stderr b/tests/ui/did_you_mean/issue-38147-2.stderr new file mode 100644 index 000000000..7c287a7db --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-2.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference + --> $DIR/issue-38147-2.rs:9:9 + | +LL | self.s.push('x'); + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | s: &'a mut String, + | +++ + +error[E0596]: cannot borrow `*self.longer_name` as mutable, as it is behind a `&` reference + --> $DIR/issue-38147-2.rs:12:9 + | +LL | self.longer_name.push(13); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | longer_name: & 'a mut Vec + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38147-3.rs b/tests/ui/did_you_mean/issue-38147-3.rs new file mode 100644 index 000000000..40b8e0dba --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-3.rs @@ -0,0 +1,12 @@ +struct Qux<'a> { + s: &'a String +} + +impl<'a> Qux<'a> { + fn f(&self) { + self.s.push('x'); + //~^ ERROR cannot borrow `*self.s` as mutable, as it is behind a `&` reference + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-38147-3.stderr b/tests/ui/did_you_mean/issue-38147-3.stderr new file mode 100644 index 000000000..94ffe17f1 --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-3.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference + --> $DIR/issue-38147-3.rs:7:9 + | +LL | self.s.push('x'); + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | s: &'a mut String + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-38147-4.rs b/tests/ui/did_you_mean/issue-38147-4.rs new file mode 100644 index 000000000..e2028a9e6 --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-4.rs @@ -0,0 +1,9 @@ +struct Foo<'a> { + s: &'a mut String +} + +fn f(x: usize, f: &Foo) { + f.s.push('x'); //~ ERROR cannot borrow `*f.s` as mutable, as it is behind a `&` reference +} + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-38147-4.stderr b/tests/ui/did_you_mean/issue-38147-4.stderr new file mode 100644 index 000000000..d33399893 --- /dev/null +++ b/tests/ui/did_you_mean/issue-38147-4.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference + --> $DIR/issue-38147-4.rs:6:5 + | +LL | f.s.push('x'); + | ^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f(x: usize, f: &mut Foo<'_>) { + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-39544.rs b/tests/ui/did_you_mean/issue-39544.rs new file mode 100644 index 000000000..a19d3f704 --- /dev/null +++ b/tests/ui/did_you_mean/issue-39544.rs @@ -0,0 +1,50 @@ +pub enum X { + Y +} + +pub struct Z { + x: X +} + +fn main() { + let z = Z { x: X::Y }; + let _ = &mut z.x; //~ ERROR cannot borrow +} + +impl Z { + fn foo<'z>(&'z self) { + let _ = &mut self.x; //~ ERROR cannot borrow + } + + fn foo1(&self, other: &Z) { + let _ = &mut self.x; //~ ERROR cannot borrow + let _ = &mut other.x; //~ ERROR cannot borrow + } + + fn foo2<'a>(&'a self, other: &Z) { + let _ = &mut self.x; //~ ERROR cannot borrow + let _ = &mut other.x; //~ ERROR cannot borrow + } + + fn foo3<'a>(self: &'a Self, other: &Z) { + let _ = &mut self.x; //~ ERROR cannot borrow + let _ = &mut other.x; //~ ERROR cannot borrow + } + + fn foo4(other: &Z) { + let _ = &mut other.x; //~ ERROR cannot borrow + } + +} + +pub fn with_arg(z: Z, w: &Z) { + let _ = &mut z.x; //~ ERROR cannot borrow + let _ = &mut w.x; //~ ERROR cannot borrow +} + +pub fn with_tuple() { + let mut y = 0; + let x = (&y,); + *x.0 = 1; + //~^ ERROR cannot assign to `*x.0`, which is behind a `&` reference +} diff --git a/tests/ui/did_you_mean/issue-39544.stderr b/tests/ui/did_you_mean/issue-39544.stderr new file mode 100644 index 000000000..8dc0512a9 --- /dev/null +++ b/tests/ui/did_you_mean/issue-39544.stderr @@ -0,0 +1,131 @@ +error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable + --> $DIR/issue-39544.rs:11:13 + | +LL | let _ = &mut z.x; + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut z = Z { x: X::Y }; + | +++ + +error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:16:17 + | +LL | let _ = &mut self.x; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo<'z>(&'z mut self) { + | ~~~~~~~~~~~~ + +error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:20:17 + | +LL | let _ = &mut self.x; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo1(&mut self, other: &Z) { + | ~~~~~~~~~ + +error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:21:17 + | +LL | let _ = &mut other.x; + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo1(&self, other: &mut Z) { + | ~~~~~~ + +error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:25:17 + | +LL | let _ = &mut self.x; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo2<'a>(&'a mut self, other: &Z) { + | ~~~~~~~~~~~~ + +error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:26:17 + | +LL | let _ = &mut other.x; + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo2<'a>(&'a self, other: &mut Z) { + | ~~~~~~ + +error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:30:17 + | +LL | let _ = &mut self.x; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo3<'a>(self: &'a mut Self, other: &Z) { + | ~~~~~~~~~~~~ + +error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:31:17 + | +LL | let _ = &mut other.x; + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo3<'a>(self: &'a Self, other: &mut Z) { + | ~~~~~~ + +error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:35:17 + | +LL | let _ = &mut other.x; + | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo4(other: &mut Z) { + | ~~~~~~ + +error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable + --> $DIR/issue-39544.rs:41:13 + | +LL | let _ = &mut z.x; + | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | pub fn with_arg(mut z: Z, w: &Z) { + | +++ + +error[E0596]: cannot borrow `w.x` as mutable, as it is behind a `&` reference + --> $DIR/issue-39544.rs:42:13 + | +LL | let _ = &mut w.x; + | ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn with_arg(z: Z, w: &mut Z) { + | ~~~~~~ + +error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference + --> $DIR/issue-39544.rs:48:5 + | +LL | *x.0 = 1; + | ^^^^^^^^ cannot assign + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.rs b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.rs new file mode 100644 index 000000000..63a8c547c --- /dev/null +++ b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.rs @@ -0,0 +1,27 @@ +trait Foo { + fn bar(&self){} +} + +impl Foo for i8 {} +impl Foo for i8 {} +impl Foo for i8 {} +impl Foo for i8 {} +impl Foo for i8 {} + +impl Foo for u8 {} +impl Foo for u8 {} +impl Foo for u8 {} +impl Foo for u8 {} + +impl Foo for bool {} +impl Foo for bool {} +impl Foo for bool {} +impl Foo for bool {} +impl Foo for bool {} +impl Foo for bool {} + +fn main() { + Foo::::bar(&1i8); //~ ERROR is not satisfied + Foo::::bar(&1u8); //~ ERROR is not satisfied + Foo::::bar(&true); //~ ERROR is not satisfied +} diff --git a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr new file mode 100644 index 000000000..7229b9ac9 --- /dev/null +++ b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `i8: Foo` is not satisfied + --> $DIR/issue-39802-show-5-trait-impls.rs:24:21 + | +LL | Foo::::bar(&1i8); + | --------------- ^^^^ the trait `Foo` is not implemented for `i8` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + > + > + > + > + > + +error[E0277]: the trait bound `u8: Foo` is not satisfied + --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 + | +LL | Foo::::bar(&1u8); + | --------------- ^^^^ the trait `Foo` is not implemented for `u8` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + > + > + > + > + +error[E0277]: the trait bound `bool: Foo` is not satisfied + --> $DIR/issue-39802-show-5-trait-impls.rs:26:21 + | +LL | Foo::::bar(&true); + | --------------- ^^^^^ the trait `Foo` is not implemented for `bool` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + > + > + > + > + > + > + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-40006.rs b/tests/ui/did_you_mean/issue-40006.rs new file mode 100644 index 000000000..74f304d81 --- /dev/null +++ b/tests/ui/did_you_mean/issue-40006.rs @@ -0,0 +1,39 @@ +impl dyn A { + Y +} //~ ERROR expected one of `!` or `::`, found `}` + +struct S; + +trait X { + X() {} //~ ERROR expected one of `!` or `::`, found `(` + fn xxx() { ### } + L = M; + Z = { 2 + 3 }; + ::Y (); +} + +trait A { + X() {} //~ ERROR expected one of `!` or `::`, found `(` +} +trait B { + fn xxx() { ### } //~ ERROR expected +} +trait C { + L = M; //~ ERROR expected one of `!` or `::`, found `=` +} +trait D { + Z = { 2 + 3 }; //~ ERROR expected one of `!` or `::`, found `=` +} +trait E { + ::Y (); //~ ERROR expected one of +} + +impl S { + pub hello_method(&self) { //~ ERROR missing + println!("Hello"); + } +} + +fn main() { + S.hello_method(); //~ no method named `hello_method` found +} diff --git a/tests/ui/did_you_mean/issue-40006.stderr b/tests/ui/did_you_mean/issue-40006.stderr new file mode 100644 index 000000000..bdbfa4dd7 --- /dev/null +++ b/tests/ui/did_you_mean/issue-40006.stderr @@ -0,0 +1,98 @@ +error: expected one of `!` or `::`, found `}` + --> $DIR/issue-40006.rs:3:1 + | +LL | impl dyn A { + | - while parsing this item list starting here +LL | Y + | - expected one of `!` or `::` +LL | } + | ^ + | | + | unexpected token + | the item list ends here + +error: expected one of `!` or `::`, found `(` + --> $DIR/issue-40006.rs:8:6 + | +LL | trait X { + | - while parsing this item list starting here +LL | X() {} + | ^ expected one of `!` or `::` +... +LL | } + | - the item list ends here + +error: expected one of `!` or `::`, found `(` + --> $DIR/issue-40006.rs:16:6 + | +LL | trait A { + | - while parsing this item list starting here +LL | X() {} + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: expected one of `!` or `[`, found `#` + --> $DIR/issue-40006.rs:19:17 + | +LL | fn xxx() { ### } + | ^ expected one of `!` or `[` + +error: expected one of `!` or `::`, found `=` + --> $DIR/issue-40006.rs:22:7 + | +LL | trait C { + | - while parsing this item list starting here +LL | L = M; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: expected one of `!` or `::`, found `=` + --> $DIR/issue-40006.rs:25:7 + | +LL | trait D { + | - while parsing this item list starting here +LL | Z = { 2 + 3 }; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: expected one of `!` or `::`, found `(` + --> $DIR/issue-40006.rs:28:9 + | +LL | trait E { + | - while parsing this item list starting here +LL | ::Y (); + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: missing `fn` for method definition + --> $DIR/issue-40006.rs:32:8 + | +LL | impl S { + | - while parsing this item list starting here +LL | pub hello_method(&self) { + | ^ +... +LL | } + | - the item list ends here + | +help: add `fn` here to parse `hello_method` as a public method + | +LL | pub fn hello_method(&self) { + | ++ + +error[E0599]: no method named `hello_method` found for struct `S` in the current scope + --> $DIR/issue-40006.rs:38:7 + | +LL | struct S; + | -------- method `hello_method` not found for this struct +... +LL | S.hello_method(); + | ^^^^^^^^^^^^ method not found in `S` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/did_you_mean/issue-40396.rs b/tests/ui/did_you_mean/issue-40396.rs new file mode 100644 index 000000000..5497ba2e1 --- /dev/null +++ b/tests/ui/did_you_mean/issue-40396.rs @@ -0,0 +1,29 @@ +fn main() { + (0..13).collect>(); + //~^ ERROR comparison operators cannot be chained + //~| HELP use `::<...>` instead + Vec::new(); + //~^ ERROR comparison operators cannot be chained + //~| HELP use `::<...>` instead + (0..13).collect(); + //~^ ERROR comparison operators cannot be chained + //~| HELP use `::<...>` instead + let x = std::collections::HashMap::new(); //~ ERROR expected one of + //~^ HELP use `::<...>` instead + let x: () = 42; //~ ERROR mismatched types + let x = { + std::collections::HashMap::new() //~ ERROR expected one of + //~^ HELP use `::<...>` instead + }; + let x: () = 42; //~ ERROR mismatched types + let x = { + std::collections::HashMap::new(); //~ ERROR expected one of + //~^ HELP use `::<...>` instead + let x: () = 42; //~ ERROR mismatched types + }; + { + std::collections::HashMap::new(1, 2); //~ ERROR expected one of + //~^ HELP use `::<...>` instead + let x: () = 32; //~ ERROR mismatched types + }; +} diff --git a/tests/ui/did_you_mean/issue-40396.stderr b/tests/ui/did_you_mean/issue-40396.stderr new file mode 100644 index 000000000..d0249efd0 --- /dev/null +++ b/tests/ui/did_you_mean/issue-40396.stderr @@ -0,0 +1,112 @@ +error: comparison operators cannot be chained + --> $DIR/issue-40396.rs:2:20 + | +LL | (0..13).collect>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | (0..13).collect::>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/issue-40396.rs:5:8 + | +LL | Vec::new(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | Vec::::new(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/issue-40396.rs:8:20 + | +LL | (0..13).collect(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | (0..13).collect::(); + | ++ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + --> $DIR/issue-40396.rs:11:43 + | +LL | let x = std::collections::HashMap::new(); + | ^ expected one of 8 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let x = std::collections::HashMap::::new(); + | ++ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `,` + --> $DIR/issue-40396.rs:15:39 + | +LL | std::collections::HashMap::new() + | ^ expected one of 8 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | std::collections::HashMap::::new() + | ++ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `,` + --> $DIR/issue-40396.rs:20:39 + | +LL | std::collections::HashMap::new(); + | ^ expected one of 8 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | std::collections::HashMap::::new(); + | ++ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `,` + --> $DIR/issue-40396.rs:25:39 + | +LL | std::collections::HashMap::new(1, 2); + | ^ expected one of 8 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | std::collections::HashMap::::new(1, 2); + | ++ + +error[E0308]: mismatched types + --> $DIR/issue-40396.rs:13:17 + | +LL | let x: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-40396.rs:18:17 + | +LL | let x: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-40396.rs:22:21 + | +LL | let x: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-40396.rs:27:21 + | +LL | let x: () = 32; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/issue-40823.rs b/tests/ui/did_you_mean/issue-40823.rs new file mode 100644 index 000000000..0f8c74554 --- /dev/null +++ b/tests/ui/did_you_mean/issue-40823.rs @@ -0,0 +1,4 @@ +fn main() { + let mut buf = &[1, 2, 3, 4]; + buf.iter_mut(); //~ ERROR cannot borrow `*buf` as mutable, as it is behind a `&` reference +} diff --git a/tests/ui/did_you_mean/issue-40823.stderr b/tests/ui/did_you_mean/issue-40823.stderr new file mode 100644 index 000000000..aadd69889 --- /dev/null +++ b/tests/ui/did_you_mean/issue-40823.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference + --> $DIR/issue-40823.rs:3:5 + | +LL | buf.iter_mut(); + | ^^^^^^^^^^^^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let mut buf = &mut [1, 2, 3, 4]; + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed b/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed new file mode 100644 index 000000000..e566ed488 --- /dev/null +++ b/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _x = !1; //~ ERROR cannot be used as a unary operator + let _y = !1; //~ ERROR unexpected `1` after identifier + let _z = !false; //~ ERROR unexpected keyword `false` after identifier + let _a = !true; //~ ERROR unexpected keyword `true` after identifier + let v = 1 + 2; + let _v = !v; //~ ERROR unexpected `v` after identifier +} diff --git a/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs b/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs new file mode 100644 index 000000000..1708a8050 --- /dev/null +++ b/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _x = ~1; //~ ERROR cannot be used as a unary operator + let _y = not 1; //~ ERROR unexpected `1` after identifier + let _z = not false; //~ ERROR unexpected keyword `false` after identifier + let _a = not true; //~ ERROR unexpected keyword `true` after identifier + let v = 1 + 2; + let _v = not v; //~ ERROR unexpected `v` after identifier +} diff --git a/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr b/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr new file mode 100644 index 000000000..2a3242abe --- /dev/null +++ b/tests/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr @@ -0,0 +1,40 @@ +error: `~` cannot be used as a unary operator + --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:4:14 + | +LL | let _x = ~1; + | ^ help: use `!` to perform bitwise not + +error: unexpected `1` after identifier + --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:5:18 + | +LL | let _y = not 1; + | ----^ + | | + | help: use `!` to perform bitwise not + +error: unexpected keyword `false` after identifier + --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:6:18 + | +LL | let _z = not false; + | ----^^^^^ + | | + | help: use `!` to perform logical negation + +error: unexpected keyword `true` after identifier + --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:7:18 + | +LL | let _a = not true; + | ----^^^^ + | | + | help: use `!` to perform logical negation + +error: unexpected `v` after identifier + --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:9:18 + | +LL | let _v = not v; + | ----^ + | | + | help: use `!` to perform logical negation or bitwise not + +error: aborting due to 5 previous errors + diff --git a/tests/ui/did_you_mean/issue-42599_available_fields_note.rs b/tests/ui/did_you_mean/issue-42599_available_fields_note.rs new file mode 100644 index 000000000..c377dfc12 --- /dev/null +++ b/tests/ui/did_you_mean/issue-42599_available_fields_note.rs @@ -0,0 +1,37 @@ +mod submodule { + + #[derive(Default)] + pub struct Demo { + pub favorite_integer: isize, + secret_integer: isize, + pub innocently_misspellable: (), + another_field: bool, + yet_another_field: bool, + always_more_fields: bool, + and_ever: bool, + } + + impl Demo { + fn new_with_secret_two() -> Self { + Self { secret_integer: 2, inocently_mispellable: () } + //~^ ERROR no field + } + + fn new_with_secret_three() -> Self { + Self { secret_integer: 3, egregiously_nonexistent_field: () } + //~^ ERROR no field + } + } + +} + +fn main() { + use submodule::Demo; + + let demo = Demo::default(); + let innocent_field_misaccess = demo.inocently_mispellable; + //~^ ERROR no field + // note shouldn't suggest private fields + let egregious_field_misaccess = demo.egregiously_nonexistent_field; + //~^ ERROR no field +} diff --git a/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr new file mode 100644 index 000000000..dbd9dc1bc --- /dev/null +++ b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr @@ -0,0 +1,32 @@ +error[E0560]: struct `Demo` has no field named `inocently_mispellable` + --> $DIR/issue-42599_available_fields_note.rs:16:39 + | +LL | Self { secret_integer: 2, inocently_mispellable: () } + | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` + +error[E0560]: struct `Demo` has no field named `egregiously_nonexistent_field` + --> $DIR/issue-42599_available_fields_note.rs:21:39 + | +LL | Self { secret_integer: 3, egregiously_nonexistent_field: () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Demo` does not have this field + | + = note: available fields are: `favorite_integer`, `secret_integer`, `innocently_misspellable`, `another_field`, `yet_another_field` ... and 2 others + +error[E0609]: no field `inocently_mispellable` on type `Demo` + --> $DIR/issue-42599_available_fields_note.rs:32:41 + | +LL | let innocent_field_misaccess = demo.inocently_mispellable; + | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` + +error[E0609]: no field `egregiously_nonexistent_field` on type `Demo` + --> $DIR/issue-42599_available_fields_note.rs:35:42 + | +LL | let egregious_field_misaccess = demo.egregiously_nonexistent_field; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field + | + = note: available fields are: `favorite_integer`, `innocently_misspellable` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0560, E0609. +For more information about an error, try `rustc --explain E0560`. diff --git a/tests/ui/did_you_mean/issue-42764.rs b/tests/ui/did_you_mean/issue-42764.rs new file mode 100644 index 000000000..eb96c2480 --- /dev/null +++ b/tests/ui/did_you_mean/issue-42764.rs @@ -0,0 +1,30 @@ +enum DoubleOption { + FirstSome(T), + AlternativeSome(T), + Nothing, +} + +fn this_function_expects_a_double_option(d: DoubleOption) {} + +fn main() { + let n: usize = 42; + this_function_expects_a_double_option(n); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in a variant of `DoubleOption` +} + + +// But don't issue the "try using a variant" help if the one-"variant" ADT is +// actually a one-field struct. + +struct Payload; + +struct Wrapper { payload: Payload } + +struct Context { wrapper: Wrapper } + +fn overton() { + let _c = Context { wrapper: Payload{} }; + //~^ ERROR mismatched types + //~| try wrapping the expression in `Wrapper` +} diff --git a/tests/ui/did_you_mean/issue-42764.stderr b/tests/ui/did_you_mean/issue-42764.stderr new file mode 100644 index 000000000..6a7fd8fe2 --- /dev/null +++ b/tests/ui/did_you_mean/issue-42764.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/issue-42764.rs:11:43 + | +LL | this_function_expects_a_double_option(n); + | ------------------------------------- ^ expected enum `DoubleOption`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected enum `DoubleOption<_>` + found type `usize` +note: function defined here + --> $DIR/issue-42764.rs:7:4 + | +LL | fn this_function_expects_a_double_option(d: DoubleOption) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------ +help: try wrapping the expression in a variant of `DoubleOption` + | +LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n)); + | ++++++++++++++++++++++++ + +LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)); + | ++++++++++++++++++++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/issue-42764.rs:27:33 + | +LL | let _c = Context { wrapper: Payload{} }; + | ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload` + | +help: try wrapping the expression in `Wrapper` + | +LL | let _c = Context { wrapper: Wrapper { payload: Payload{} } }; + | ++++++++++++++++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs b/tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs new file mode 100644 index 000000000..9602d2746 --- /dev/null +++ b/tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.rs @@ -0,0 +1,36 @@ +enum Example { Ex(String), NotEx } + +enum Void {} + +enum ManyVariants { + One, + Two, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine, + Ten, +} + +fn result_test() { + let x = Option(1); //~ ERROR expected function, tuple struct or tuple variant, found enum + + if let Option(_) = x { //~ ERROR expected tuple struct or tuple variant, found enum + println!("It is OK."); + } + + let y = Example::Ex(String::from("test")); + + if let Example(_) = y { //~ ERROR expected tuple struct or tuple variant, found enum + println!("It is OK."); + } + + let y = Void(); //~ ERROR expected function, tuple struct or tuple variant, found enum + + let z = ManyVariants(); //~ ERROR expected function, tuple struct or tuple variant, found enum +} + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr new file mode 100644 index 000000000..9dde5b3eb --- /dev/null +++ b/tests/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr @@ -0,0 +1,66 @@ +error[E0532]: expected tuple struct or tuple variant, found enum `Option` + --> $DIR/issue-43871-enum-instead-of-variant.rs:21:12 + | +LL | if let Option(_) = x { + | ^^^^^^ help: try to match against one of the enum's variants: `std::option::Option::Some` + | + = help: you might have meant to match against the enum's non-tuple variant + +error[E0532]: expected tuple struct or tuple variant, found enum `Example` + --> $DIR/issue-43871-enum-instead-of-variant.rs:27:12 + | +LL | if let Example(_) = y { + | ^^^^^^^ help: try to match against one of the enum's variants: `Example::Ex` + | + = help: you might have meant to match against the enum's non-tuple variant +note: the enum is defined here + --> $DIR/issue-43871-enum-instead-of-variant.rs:1:1 + | +LL | enum Example { Ex(String), NotEx } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0423]: expected function, tuple struct or tuple variant, found enum `Option` + --> $DIR/issue-43871-enum-instead-of-variant.rs:19:13 + | +LL | let x = Option(1); + | ^^^^^^ help: try to construct one of the enum's variants: `std::option::Option::Some` + | + = help: you might have meant to construct the enum's non-tuple variant + +error[E0423]: expected function, tuple struct or tuple variant, found enum `Void` + --> $DIR/issue-43871-enum-instead-of-variant.rs:31:13 + | +LL | let y = Void(); + | ^^^^ + | + = help: the enum has no tuple variants to construct +note: the enum is defined here + --> $DIR/issue-43871-enum-instead-of-variant.rs:3:1 + | +LL | enum Void {} + | ^^^^^^^^^^^^ + +error[E0423]: expected function, tuple struct or tuple variant, found enum `ManyVariants` + --> $DIR/issue-43871-enum-instead-of-variant.rs:33:13 + | +LL | let z = ManyVariants(); + | ^^^^^^^^^^^^ + | + = help: the enum has no tuple variants to construct + = help: you might have meant to construct one of the enum's non-tuple variants +note: the enum is defined here + --> $DIR/issue-43871-enum-instead-of-variant.rs:5:1 + | +LL | / enum ManyVariants { +LL | | One, +LL | | Two, +LL | | Three, +... | +LL | | Ten, +LL | | } + | |_^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0423, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs new file mode 100644 index 000000000..63e8b2ba0 --- /dev/null +++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs @@ -0,0 +1,17 @@ +#![allow(unused)] + +struct PersonalityInventory { + expressivity: f32, + instrumentality: f32 +} + +impl PersonalityInventory { + fn expressivity(&self) -> f32 { + match *self { + PersonalityInventory { expressivity: exp, ... } => exp + //~^ ERROR expected field pattern, found `...` + } + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr new file mode 100644 index 000000000..bfe1ed328 --- /dev/null +++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr @@ -0,0 +1,8 @@ +error: expected field pattern, found `...` + --> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55 + | +LL | PersonalityInventory { expressivity: exp, ... } => exp + | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + +error: aborting due to previous error + diff --git a/tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs b/tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs new file mode 100644 index 000000000..df697ccb6 --- /dev/null +++ b/tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs @@ -0,0 +1,34 @@ +fn gratitude() { + let for_you = false; + if not for_you { + //~^ ERROR unexpected `for_you` after identifier + println!("I couldn't"); + } +} + +fn qualification() { + let the_worst = true; + while not the_worst { + //~^ ERROR unexpected `the_worst` after identifier + println!("still pretty bad"); + } +} + +fn should_we() { + let not = true; + if not // lack of braces is [sic] + println!("Then when?"); + //~^ ERROR expected `{`, found `; + //~| ERROR unexpected `println` after identifier +} + +fn sleepy() { + let resource = not 2; + //~^ ERROR unexpected `2` after identifier +} + +fn main() { + let be_smothered_out_before = true; + let young_souls = not be_smothered_out_before; + //~^ ERROR unexpected `be_smothered_out_before` after identifier +} diff --git a/tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr new file mode 100644 index 000000000..14918ba89 --- /dev/null +++ b/tests/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -0,0 +1,56 @@ +error: unexpected `for_you` after identifier + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:3:12 + | +LL | if not for_you { + | ----^^^^^^^ + | | + | help: use `!` to perform logical negation or bitwise not + +error: unexpected `the_worst` after identifier + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:11:15 + | +LL | while not the_worst { + | ----^^^^^^^^^ + | | + | help: use `!` to perform logical negation or bitwise not + +error: unexpected `println` after identifier + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:9 + | +LL | if not // lack of braces is [sic] + | ----- help: use `!` to perform logical negation or bitwise not +LL | println!("Then when?"); + | ^^^^^^^ + +error: expected `{`, found `;` + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31 + | +LL | println!("Then when?"); + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:19:8 + | +LL | if not // lack of braces is [sic] + | ________^ +LL | | println!("Then when?"); + | |______________________________^ + +error: unexpected `2` after identifier + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 + | +LL | let resource = not 2; + | ----^ + | | + | help: use `!` to perform bitwise not + +error: unexpected `be_smothered_out_before` after identifier + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:32:27 + | +LL | let young_souls = not be_smothered_out_before; + | ----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: use `!` to perform logical negation or bitwise not + +error: aborting due to 6 previous errors + diff --git a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs new file mode 100644 index 000000000..43b5f6d54 --- /dev/null +++ b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs @@ -0,0 +1,87 @@ +#![allow(unused)] + +#[derive(Copy, Clone)] +enum Nucleotide { + Adenine, + Thymine, + Cytosine, + Guanine +} + +#[derive(Clone)] +struct Autosome; + +#[derive(Clone)] +enum Allosome { + X(Vec), + Y(Vec) +} + +impl Allosome { + fn is_x(&self) -> bool { + match *self { + Allosome::X(_) => true, + Allosome::Y(_) => false, + } + } +} + +#[derive(Clone)] +struct Genome { + autosomes: [Autosome; 22], + allosomes: (Allosome, Allosome) +} + +fn find_start_codon(strand: &[Nucleotide]) -> Option { + let mut reading_frame = strand.windows(3); + // (missing parentheses in `while let` tuple pattern) + while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") { + //~^ ERROR unexpected `,` in pattern + // ... + } + None +} + +fn find_thr(strand: &[Nucleotide]) -> Option { + let mut reading_frame = strand.windows(3); + let mut i = 0; + // (missing parentheses in `if let` tuple pattern) + if let b1, b2, b3 = reading_frame.next().unwrap() { + //~^ ERROR unexpected `,` in pattern + // ... + } + None +} + +fn is_thr(codon: (Nucleotide, Nucleotide, Nucleotide)) -> bool { + match codon { + // (missing parentheses in match arm tuple pattern) + Nucleotide::Adenine, Nucleotide::Cytosine, _ => true + //~^ ERROR unexpected `,` in pattern + _ => false + } +} + +fn analyze_female_sex_chromosomes(women: &[Genome]) { + // (missing parentheses in `for` tuple pattern) + for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) { + //~^ ERROR unexpected `,` in pattern + // ... + } +} + +fn analyze_male_sex_chromosomes(men: &[Genome]) { + // (missing parentheses in pattern with `@` binding) + for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) { + //~^ ERROR unexpected `,` in pattern + // ... + } +} + +fn main() { + let genomes = Vec::new(); + // (missing parentheses in `let` pattern) + let women, men: (Vec, Vec) = genomes.iter().cloned() + //~^ ERROR unexpected `,` in pattern + .partition(|g: &Genome| g.allosomes.0.is_x() && g.allosomes.1.is_x()); +} diff --git a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr new file mode 100644 index 000000000..a3c607b59 --- /dev/null +++ b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr @@ -0,0 +1,74 @@ +error: unexpected `,` in pattern + --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:38:17 + | +LL | while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") { + | ----- ^ + | | + | while parsing the condition of this `while` expression + | +help: try adding parentheses to match on a tuple + | +LL | while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") { + | + + + +error: unexpected `,` in pattern + --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:49:14 + | +LL | if let b1, b2, b3 = reading_frame.next().unwrap() { + | ^ + | +help: try adding parentheses to match on a tuple + | +LL | if let (b1, b2, b3) = reading_frame.next().unwrap() { + | + + + +error: unexpected `,` in pattern + --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:59:28 + | +LL | Nucleotide::Adenine, Nucleotide::Cytosine, _ => true + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true + | + + +help: ...or a vertical bar to match on multiple alternatives + | +LL | Nucleotide::Adenine | Nucleotide::Cytosine | _ => true + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: unexpected `,` in pattern + --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:67:10 + | +LL | for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) { + | ^ + | +help: try adding parentheses to match on a tuple + | +LL | for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) { + | + + + +error: unexpected `,` in pattern + --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10 + | +LL | for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) { + | ^ + | +help: try adding parentheses to match on a tuple + | +LL | for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) { + | + + + +error: unexpected `,` in pattern + --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14 + | +LL | let women, men: (Vec, Vec) = genomes.iter().cloned() + | ^ + | +help: try adding parentheses to match on a tuple + | +LL | let (women, men): (Vec, Vec) = genomes.iter().cloned() + | + + + +error: aborting due to 6 previous errors + diff --git a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs new file mode 100644 index 000000000..66d562d2e --- /dev/null +++ b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs @@ -0,0 +1,6 @@ +const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kgâ»Â¹â‹…sâ»Â² +//~^ ERROR expected at least one digit in exponent +//~| ERROR unknown start of token: \u{2212} +//~| ERROR cannot subtract `{integer}` from `{float}` + +fn main() {} diff --git a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr new file mode 100644 index 000000000..81f3f2694 --- /dev/null +++ b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -0,0 +1,38 @@ +error: expected at least one digit in exponent + --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:47 + | +LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kgâ»Â¹â‹…sâ»Â² + | ^^^^^^ + +error: unknown start of token: \u{2212} + --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53 + | +LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kgâ»Â¹â‹…sâ»Â² + | ^ + | +help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it is not + | +LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kgâ»Â¹â‹…sâ»Â² + | ~ + +error[E0277]: cannot subtract `{integer}` from `{float}` in const contexts + --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53 + | +LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kgâ»Â¹â‹…sâ»Â² + | ^ no implementation for `{float} - {integer}` + | + = help: the trait `~const Sub<{integer}>` is not implemented for `{float}` + = help: the following other types implement trait `Sub`: + <&'a f32 as Sub> + <&'a f64 as Sub> + <&'a i128 as Sub> + <&'a i16 as Sub> + <&'a i32 as Sub> + <&'a i64 as Sub> + <&'a i8 as Sub> + <&'a isize as Sub> + and 48 others + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs b/tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs new file mode 100644 index 000000000..73f1856ca --- /dev/null +++ b/tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs @@ -0,0 +1,19 @@ +fn main() { + let sixteen: f32 = 16; + //~^ ERROR mismatched types + //~| HELP use a float literal + let a_million_and_seventy: f64 = 1_000_070; + //~^ ERROR mismatched types + //~| HELP use a float literal + let negative_nine: f32 = -9; + //~^ ERROR mismatched types + //~| HELP use a float literal + + + // only base-10 literals get the suggestion + + let sixteen_again: f64 = 0x10; + //~^ ERROR mismatched types + let and_once_more: f32 = 0o20; + //~^ ERROR mismatched types +} diff --git a/tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr b/tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr new file mode 100644 index 000000000..6f853ccab --- /dev/null +++ b/tests/ui/did_you_mean/issue-53280-expected-float-found-integer-literal.stderr @@ -0,0 +1,49 @@ +error[E0308]: mismatched types + --> $DIR/issue-53280-expected-float-found-integer-literal.rs:2:24 + | +LL | let sixteen: f32 = 16; + | --- ^^ + | | | + | | expected `f32`, found integer + | | help: use a float literal: `16.0` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-53280-expected-float-found-integer-literal.rs:5:38 + | +LL | let a_million_and_seventy: f64 = 1_000_070; + | --- ^^^^^^^^^ + | | | + | | expected `f64`, found integer + | | help: use a float literal: `1_000_070.0` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-53280-expected-float-found-integer-literal.rs:8:30 + | +LL | let negative_nine: f32 = -9; + | --- ^^ + | | | + | | expected `f32`, found integer + | | help: use a float literal: `-9.0` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-53280-expected-float-found-integer-literal.rs:15:30 + | +LL | let sixteen_again: f64 = 0x10; + | --- ^^^^ expected `f64`, found integer + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-53280-expected-float-found-integer-literal.rs:17:30 + | +LL | let and_once_more: f32 = 0o20; + | --- ^^^^ expected `f32`, found integer + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs b/tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs new file mode 100644 index 000000000..44421b077 --- /dev/null +++ b/tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs @@ -0,0 +1,57 @@ +fn main() {} + +fn test_and() { + let a = true; + let b = false; + + let _ = a and b; //~ ERROR `and` is not a logical operator + + if a and b { //~ ERROR `and` is not a logical operator + println!("both"); + } + + let _recovery_witness: () = 0; //~ ERROR mismatched types +} + +fn test_or() { + let a = true; + let b = false; + + let _ = a or b; //~ ERROR `or` is not a logical operator + + if a or b { //~ ERROR `or` is not a logical operator + println!("both"); + } +} + +fn test_and_par() { + let a = true; + let b = false; + if (a and b) { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_or_par() { + let a = true; + let b = false; + if (a or b) { //~ ERROR `or` is not a logical operator + println!("both"); + } +} + +fn test_while_and() { + let a = true; + let b = false; + while a and b { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_while_or() { + let a = true; + let b = false; + while a or b { //~ ERROR `or` is not a logical operator + println!("both"); + } +} diff --git a/tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr new file mode 100644 index 000000000..cbe59e8e0 --- /dev/null +++ b/tests/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr @@ -0,0 +1,75 @@ +error: `and` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15 + | +LL | let _ = a and b; + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `and` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10 + | +LL | if a and b { + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15 + | +LL | let _ = a or b; + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10 + | +LL | if a or b { + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `and` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11 + | +LL | if (a and b) { + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11 + | +LL | if (a or b) { + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `and` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13 + | +LL | while a and b { + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13 + | +LL | while a or b { + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error[E0308]: mismatched types + --> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/issue-54109-without-witness.fixed b/tests/ui/did_you_mean/issue-54109-without-witness.fixed new file mode 100644 index 000000000..5079a37f4 --- /dev/null +++ b/tests/ui/did_you_mean/issue-54109-without-witness.fixed @@ -0,0 +1,61 @@ +// run-rustfix + +// This test is to check if suggestions can be applied automatically. + +#![allow(dead_code, unused_parens)] + +fn main() {} + +fn test_and() { + let a = true; + let b = false; + + let _ = a && b; //~ ERROR `and` is not a logical operator + + if a && b { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_or() { + let a = true; + let b = false; + + let _ = a || b; //~ ERROR `or` is not a logical operator + + if a || b { //~ ERROR `or` is not a logical operator + println!("both"); + } +} + +fn test_and_par() { + let a = true; + let b = false; + if (a && b) { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_or_par() { + let a = true; + let b = false; + if (a || b) { //~ ERROR `or` is not a logical operator + println!("both"); + } +} + +fn test_while_and() { + let a = true; + let b = false; + while a && b { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_while_or() { + let a = true; + let b = false; + while a || b { //~ ERROR `or` is not a logical operator + println!("both"); + } +} diff --git a/tests/ui/did_you_mean/issue-54109-without-witness.rs b/tests/ui/did_you_mean/issue-54109-without-witness.rs new file mode 100644 index 000000000..00660a938 --- /dev/null +++ b/tests/ui/did_you_mean/issue-54109-without-witness.rs @@ -0,0 +1,61 @@ +// run-rustfix + +// This test is to check if suggestions can be applied automatically. + +#![allow(dead_code, unused_parens)] + +fn main() {} + +fn test_and() { + let a = true; + let b = false; + + let _ = a and b; //~ ERROR `and` is not a logical operator + + if a and b { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_or() { + let a = true; + let b = false; + + let _ = a or b; //~ ERROR `or` is not a logical operator + + if a or b { //~ ERROR `or` is not a logical operator + println!("both"); + } +} + +fn test_and_par() { + let a = true; + let b = false; + if (a and b) { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_or_par() { + let a = true; + let b = false; + if (a or b) { //~ ERROR `or` is not a logical operator + println!("both"); + } +} + +fn test_while_and() { + let a = true; + let b = false; + while a and b { //~ ERROR `and` is not a logical operator + println!("both"); + } +} + +fn test_while_or() { + let a = true; + let b = false; + while a or b { //~ ERROR `or` is not a logical operator + println!("both"); + } +} diff --git a/tests/ui/did_you_mean/issue-54109-without-witness.stderr b/tests/ui/did_you_mean/issue-54109-without-witness.stderr new file mode 100644 index 000000000..6455b0863 --- /dev/null +++ b/tests/ui/did_you_mean/issue-54109-without-witness.stderr @@ -0,0 +1,66 @@ +error: `and` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:13:15 + | +LL | let _ = a and b; + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `and` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:15:10 + | +LL | if a and b { + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:24:15 + | +LL | let _ = a or b; + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:26:10 + | +LL | if a or b { + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `and` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:34:11 + | +LL | if (a and b) { + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:42:11 + | +LL | if (a or b) { + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `and` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:50:13 + | +LL | while a and b { + | ^^^ help: use `&&` to perform logical conjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: `or` is not a logical operator + --> $DIR/issue-54109-without-witness.rs:58:13 + | +LL | while a or b { + | ^^ help: use `||` to perform logical disjunction + | + = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators + +error: aborting due to 8 previous errors + diff --git a/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs new file mode 100644 index 000000000..264cfa449 --- /dev/null +++ b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs @@ -0,0 +1,15 @@ +enum PutDown { Set } +enum AffixHeart { Set } +enum CauseToBe { Set } +enum Determine { Set } +enum TableDishesAction { Set } +enum Solidify { Set } +enum UnorderedCollection { Set } + +fn setup() -> Set { Set } +//~^ ERROR cannot find type `Set` in this scope +//~| ERROR cannot find value `Set` in this scope + +fn main() { + setup(); +} diff --git a/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr new file mode 100644 index 000000000..abc040c05 --- /dev/null +++ b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr @@ -0,0 +1,40 @@ +error[E0412]: cannot find type `Set` in this scope + --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:15 + | +LL | fn setup() -> Set { Set } + | ^^^ not found in this scope + | +help: there is an enum variant `AffixHeart::Set` and 7 others; try using the variant's enum + | +LL | fn setup() -> AffixHeart { Set } + | ~~~~~~~~~~ +LL | fn setup() -> CauseToBe { Set } + | ~~~~~~~~~ +LL | fn setup() -> Determine { Set } + | ~~~~~~~~~ +LL | fn setup() -> PutDown { Set } + | ~~~~~~~ + and 3 other candidates + +error[E0425]: cannot find value `Set` in this scope + --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21 + | +LL | fn setup() -> Set { Set } + | ^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use AffixHeart::Set; + | +LL | use CauseToBe::Set; + | +LL | use Determine::Set; + | +LL | use PutDown::Set; + | + and 3 other candidates + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs new file mode 100644 index 000000000..070ffaa1e --- /dev/null +++ b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs @@ -0,0 +1,18 @@ +fn main() {} + +const FOO: [u8; 3] = { + //~^ ERROR this is a block expression, not an array + 1, 2, 3 +}; + +const BAR: [&str; 3] = {"one", "two", "three"}; +//~^ ERROR this is a block expression, not an array + +fn foo() { + {1, 2, 3}; + //~^ ERROR this is a block expression, not an array +} + +fn bar() { + 1, 2, 3 //~ ERROR expected one of +} diff --git a/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr new file mode 100644 index 000000000..d5ad1a72b --- /dev/null +++ b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr @@ -0,0 +1,48 @@ +error: this is a block expression, not an array + --> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22 + | +LL | const FOO: [u8; 3] = { + | ______________________^ +LL | | +LL | | 1, 2, 3 +LL | | }; + | |_^ + | +help: to make an array, use square brackets instead of curly braces + | +LL ~ const FOO: [u8; 3] = [ +LL | +LL | 1, 2, 3 +LL ~ ]; + | + +error: this is a block expression, not an array + --> $DIR/issue-87830-try-brackets-for-arrays.rs:8:24 + | +LL | const BAR: [&str; 3] = {"one", "two", "three"}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to make an array, use square brackets instead of curly braces + | +LL | const BAR: [&str; 3] = ["one", "two", "three"]; + | ~ ~ + +error: this is a block expression, not an array + --> $DIR/issue-87830-try-brackets-for-arrays.rs:12:5 + | +LL | {1, 2, 3}; + | ^^^^^^^^^ + | +help: to make an array, use square brackets instead of curly braces + | +LL | [1, 2, 3]; + | ~ ~ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-87830-try-brackets-for-arrays.rs:17:6 + | +LL | 1, 2, 3 + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 4 previous errors + diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs new file mode 100644 index 000000000..0efc7daa3 --- /dev/null +++ b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.rs @@ -0,0 +1,24 @@ +#[derive(Default)] +pub struct A { + #[doc(hidden)] + pub hello: i32, + pub bye: i32, +} + +#[derive(Default)] +pub struct B { + pub hello: i32, + pub bye: i32, +} + +fn main() { + A::default().hey; + //~^ ERROR no field `hey` on type `A` + //~| NOTE unknown field + //~| NOTE available fields are: `bye` + + B::default().hey; + //~^ ERROR no field `hey` on type `B` + //~| NOTE unknown field + //~| NOTE available fields are: `hello`, `bye` +} diff --git a/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr new file mode 100644 index 000000000..784986d3b --- /dev/null +++ b/tests/ui/did_you_mean/issue-93210-ignore-doc-hidden.stderr @@ -0,0 +1,19 @@ +error[E0609]: no field `hey` on type `A` + --> $DIR/issue-93210-ignore-doc-hidden.rs:15:18 + | +LL | A::default().hey; + | ^^^ unknown field + | + = note: available fields are: `bye` + +error[E0609]: no field `hey` on type `B` + --> $DIR/issue-93210-ignore-doc-hidden.rs:20:18 + | +LL | B::default().hey; + | ^^^ unknown field + | + = note: available fields are: `hello`, `bye` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/did_you_mean/pub-macro-rules.rs b/tests/ui/did_you_mean/pub-macro-rules.rs new file mode 100644 index 000000000..c5393703f --- /dev/null +++ b/tests/ui/did_you_mean/pub-macro-rules.rs @@ -0,0 +1,16 @@ +#[macro_use] mod bleh { + pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation + ($n:ident) => ( + fn $n () -> i32 { + 1 + } + ) + } + +} + +foo!(meh); + +fn main() { + println!("{}", meh()); +} diff --git a/tests/ui/did_you_mean/pub-macro-rules.stderr b/tests/ui/did_you_mean/pub-macro-rules.stderr new file mode 100644 index 000000000..0bde5783b --- /dev/null +++ b/tests/ui/did_you_mean/pub-macro-rules.stderr @@ -0,0 +1,8 @@ +error: can't qualify macro_rules invocation with `pub` + --> $DIR/pub-macro-rules.rs:2:5 + | +LL | pub macro_rules! foo { + | ^^^ help: try exporting the macro: `#[macro_export]` + +error: aborting due to previous error + diff --git a/tests/ui/did_you_mean/recursion_limit.rs b/tests/ui/did_you_mean/recursion_limit.rs new file mode 100644 index 000000000..38db12960 --- /dev/null +++ b/tests/ui/did_you_mean/recursion_limit.rs @@ -0,0 +1,35 @@ +// Test that the recursion limit can be changed and that the compiler +// suggests a fix. In this case, we have deeply nested types that will +// fail the `Send` check by overflow when the recursion limit is set +// very low. + +#![allow(dead_code)] +#![recursion_limit="10"] + +macro_rules! link { + ($id:ident, $t:ty) => { + enum $id { $id($t) } + } +} + +link! { A, B } +link! { B, C } +link! { C, D } +link! { D, E } +link! { E, F } +link! { F, G } +link! { G, H } +link! { H, I } +link! { I, J } +link! { J, K } +link! { K, L } +link! { L, M } +link! { M, N } + +enum N { N(usize) } + +fn is_send() { } + +fn main() { + is_send::(); //~ ERROR overflow evaluating the requirement +} diff --git a/tests/ui/did_you_mean/recursion_limit.stderr b/tests/ui/did_you_mean/recursion_limit.stderr new file mode 100644 index 000000000..247fe4b5b --- /dev/null +++ b/tests/ui/did_you_mean/recursion_limit.stderr @@ -0,0 +1,66 @@ +error[E0275]: overflow evaluating the requirement `K: Send` + --> $DIR/recursion_limit.rs:34:5 + | +LL | is_send::(); + | ^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit`) +note: required because it appears within the type `J` + --> $DIR/recursion_limit.rs:24:9 + | +LL | link! { J, K } + | ^ +note: required because it appears within the type `I` + --> $DIR/recursion_limit.rs:23:9 + | +LL | link! { I, J } + | ^ +note: required because it appears within the type `H` + --> $DIR/recursion_limit.rs:22:9 + | +LL | link! { H, I } + | ^ +note: required because it appears within the type `G` + --> $DIR/recursion_limit.rs:21:9 + | +LL | link! { G, H } + | ^ +note: required because it appears within the type `F` + --> $DIR/recursion_limit.rs:20:9 + | +LL | link! { F, G } + | ^ +note: required because it appears within the type `E` + --> $DIR/recursion_limit.rs:19:9 + | +LL | link! { E, F } + | ^ +note: required because it appears within the type `D` + --> $DIR/recursion_limit.rs:18:9 + | +LL | link! { D, E } + | ^ +note: required because it appears within the type `C` + --> $DIR/recursion_limit.rs:17:9 + | +LL | link! { C, D } + | ^ +note: required because it appears within the type `B` + --> $DIR/recursion_limit.rs:16:9 + | +LL | link! { B, C } + | ^ +note: required because it appears within the type `A` + --> $DIR/recursion_limit.rs:15:9 + | +LL | link! { A, B } + | ^ +note: required by a bound in `is_send` + --> $DIR/recursion_limit.rs:31:14 + | +LL | fn is_send() { } + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/did_you_mean/recursion_limit_deref.rs b/tests/ui/did_you_mean/recursion_limit_deref.rs new file mode 100644 index 000000000..41bbca661 --- /dev/null +++ b/tests/ui/did_you_mean/recursion_limit_deref.rs @@ -0,0 +1,53 @@ +// Test that the recursion limit can be changed and that the compiler +// suggests a fix. In this case, we have a long chain of Deref impls +// which will cause an overflow during the autoderef loop. +// compile-flags: -Zdeduplicate-diagnostics=yes + +#![allow(dead_code)] +#![recursion_limit="10"] + +macro_rules! link { + ($outer:ident, $inner:ident) => { + struct $outer($inner); + + impl $outer { + fn new() -> $outer { + $outer($inner::new()) + } + } + + impl std::ops::Deref for $outer { + type Target = $inner; + + fn deref(&self) -> &$inner { + &self.0 + } + } + } +} + +struct Bottom; +impl Bottom { + fn new() -> Bottom { + Bottom + } +} + +link!(Top, A); +link!(A, B); +link!(B, C); +link!(C, D); +link!(D, E); +link!(E, F); +link!(F, G); +link!(G, H); +link!(H, I); +link!(I, J); +link!(J, K); +link!(K, Bottom); + +fn main() { + let t = Top::new(); + let x: &Bottom = &t; //~ ERROR mismatched types + //~^ error recursion limit +} diff --git a/tests/ui/did_you_mean/recursion_limit_deref.stderr b/tests/ui/did_you_mean/recursion_limit_deref.stderr new file mode 100644 index 000000000..a6b5681a6 --- /dev/null +++ b/tests/ui/did_you_mean/recursion_limit_deref.stderr @@ -0,0 +1,23 @@ +error[E0055]: reached the recursion limit while auto-dereferencing `J` + --> $DIR/recursion_limit_deref.rs:51:22 + | +LL | let x: &Bottom = &t; + | ^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_deref`) + +error[E0308]: mismatched types + --> $DIR/recursion_limit_deref.rs:51:22 + | +LL | let x: &Bottom = &t; + | ------- ^^ expected struct `Bottom`, found struct `Top` + | | + | expected due to this + | + = note: expected reference `&Bottom` + found reference `&Top` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0055, E0308. +For more information about an error, try `rustc --explain E0055`. diff --git a/tests/ui/did_you_mean/recursion_limit_macro.rs b/tests/ui/did_you_mean/recursion_limit_macro.rs new file mode 100644 index 000000000..a68a5ece7 --- /dev/null +++ b/tests/ui/did_you_mean/recursion_limit_macro.rs @@ -0,0 +1,15 @@ +// Test that the recursion limit can be changed and that the compiler +// suggests a fix. In this case, we have a recursing macro that will +// overflow if the number of arguments surpasses the recursion limit. + +#![allow(dead_code)] +#![recursion_limit="10"] + +macro_rules! recurse { + () => { }; + ($t:tt $($tail:tt)*) => { recurse!($($tail)*) }; //~ ERROR recursion limit +} + +fn main() { + recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); +} diff --git a/tests/ui/did_you_mean/recursion_limit_macro.stderr b/tests/ui/did_you_mean/recursion_limit_macro.stderr new file mode 100644 index 000000000..71855cf1e --- /dev/null +++ b/tests/ui/did_you_mean/recursion_limit_macro.stderr @@ -0,0 +1,14 @@ +error: recursion limit reached while expanding `recurse!` + --> $DIR/recursion_limit_macro.rs:10:31 + | +LL | ($t:tt $($tail:tt)*) => { recurse!($($tail)*) }; + | ^^^^^^^^^^^^^^^^^^^ +... +LL | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); + | ------------------------------------------------- in this macro invocation + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_macro`) + = note: this error originates in the macro `recurse` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed new file mode 100644 index 000000000..4963790c3 --- /dev/null +++ b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused)] + +trait Foo: Sized { + fn bar(i: i32, t: T, s: &Self) -> (T, i32); +} + +impl Foo for () { + fn bar(i: i32, t: usize, s: &()) -> (usize, i32) { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + (1, 2) + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs new file mode 100644 index 000000000..ddf39c9c8 --- /dev/null +++ b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused)] + +trait Foo: Sized { + fn bar(i: i32, t: T, s: &Self) -> (T, i32); +} + +impl Foo for () { + fn bar(i: _, t: _, s: _) -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + (1, 2) + } +} + +fn main() {} diff --git a/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr new file mode 100644 index 000000000..730836a40 --- /dev/null +++ b/tests/ui/did_you_mean/replace-impl-infer-ty-from-trait.stderr @@ -0,0 +1,18 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/replace-impl-infer-ty-from-trait.rs:9:15 + | +LL | fn bar(i: _, t: _, s: _) -> _ { + | ^ ^ ^ ^ not allowed in type signatures + | | | | + | | | not allowed in type signatures + | | not allowed in type signatures + | not allowed in type signatures + | +help: try replacing `_` with the types in the corresponding trait method signature + | +LL | fn bar(i: i32, t: usize, s: &()) -> (usize, i32) { + | ~~~ ~~~~~ ~~~ ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs new file mode 100644 index 000000000..c9a097d36 --- /dev/null +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs @@ -0,0 +1,7 @@ +#![allow(bare_trait_objects)] + +fn main() { + let _: &Copy + 'static; //~ ERROR expected a path + //~^ ERROR cannot be made into an object + let _: &'static Copy + 'static; //~ ERROR expected a path +} diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr new file mode 100644 index 000000000..68734cd4c --- /dev/null +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -0,0 +1,25 @@ +error[E0178]: expected a path on the left-hand side of `+`, not `&Copy` + --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 + | +LL | let _: &Copy + 'static; + | ^^^^^^^^^^^^^^^ help: try adding parentheses: `&(Copy + 'static)` + +error[E0178]: expected a path on the left-hand side of `+`, not `&'static Copy` + --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12 + | +LL | let _: &'static Copy + 'static; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&'static (Copy + 'static)` + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 + | +LL | let _: &Copy + 'static; + | ^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0178. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/did_you_mean/use_instead_of_import.fixed b/tests/ui/did_you_mean/use_instead_of_import.fixed new file mode 100644 index 000000000..a8aae76f4 --- /dev/null +++ b/tests/ui/did_you_mean/use_instead_of_import.fixed @@ -0,0 +1,23 @@ +// run-rustfix + +use std::{ + //~^ ERROR expected item, found `import` + io::Write, + rc::Rc, +}; + +use std::time::Duration; +//~^ ERROR expected item, found `require` + +use std::time::Instant; +//~^ ERROR expected item, found `include` + +pub use std::io; +//~^ ERROR expected item, found `using` + +fn main() { + let x = Rc::new(1); + let _ = write!(io::stdout(), "{:?}", x); + let _ = Duration::new(5, 0); + let _ = Instant::now(); +} diff --git a/tests/ui/did_you_mean/use_instead_of_import.rs b/tests/ui/did_you_mean/use_instead_of_import.rs new file mode 100644 index 000000000..2db7c2407 --- /dev/null +++ b/tests/ui/did_you_mean/use_instead_of_import.rs @@ -0,0 +1,23 @@ +// run-rustfix + +import std::{ + //~^ ERROR expected item, found `import` + io::Write, + rc::Rc, +}; + +require std::time::Duration; +//~^ ERROR expected item, found `require` + +include std::time::Instant; +//~^ ERROR expected item, found `include` + +pub using std::io; +//~^ ERROR expected item, found `using` + +fn main() { + let x = Rc::new(1); + let _ = write!(io::stdout(), "{:?}", x); + let _ = Duration::new(5, 0); + let _ = Instant::now(); +} diff --git a/tests/ui/did_you_mean/use_instead_of_import.stderr b/tests/ui/did_you_mean/use_instead_of_import.stderr new file mode 100644 index 000000000..2aac8f68c --- /dev/null +++ b/tests/ui/did_you_mean/use_instead_of_import.stderr @@ -0,0 +1,26 @@ +error: expected item, found `import` + --> $DIR/use_instead_of_import.rs:3:1 + | +LL | import std::{ + | ^^^^^^ help: items are imported using the `use` keyword + +error: expected item, found `require` + --> $DIR/use_instead_of_import.rs:9:1 + | +LL | require std::time::Duration; + | ^^^^^^^ help: items are imported using the `use` keyword + +error: expected item, found `include` + --> $DIR/use_instead_of_import.rs:12:1 + | +LL | include std::time::Instant; + | ^^^^^^^ help: items are imported using the `use` keyword + +error: expected item, found `using` + --> $DIR/use_instead_of_import.rs:15:5 + | +LL | pub using std::io; + | ^^^^^ help: items are imported using the `use` keyword + +error: aborting due to 4 previous errors + diff --git a/tests/ui/directory_ownership/foo/compiletest-ignore-dir b/tests/ui/directory_ownership/foo/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs b/tests/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/directory_ownership/foo/mod_file_not_owning/aux2.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs b/tests/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/directory_ownership/foo/mod_file_not_owning_aux2.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/directory_ownership/macro-expanded-mod.rs b/tests/ui/directory_ownership/macro-expanded-mod.rs new file mode 100644 index 000000000..fa81769e5 --- /dev/null +++ b/tests/ui/directory_ownership/macro-expanded-mod.rs @@ -0,0 +1,15 @@ +// Test that macro-expanded non-inline modules behave correctly + +macro_rules! mod_decl { + ($i:ident) => { + mod $i; //~ ERROR cannot declare a non-inline module inside a block + }; +} + +mod macro_expanded_mod_helper { + mod_decl!(foo); // This should search in the folder `macro_expanded_mod_helper` +} + +fn main() { + mod_decl!(foo); +} diff --git a/tests/ui/directory_ownership/macro-expanded-mod.stderr b/tests/ui/directory_ownership/macro-expanded-mod.stderr new file mode 100644 index 000000000..8976341b1 --- /dev/null +++ b/tests/ui/directory_ownership/macro-expanded-mod.stderr @@ -0,0 +1,13 @@ +error: cannot declare a non-inline module inside a block unless it has a path attribute + --> $DIR/macro-expanded-mod.rs:5:9 + | +LL | mod $i; + | ^^^^^^^ +... +LL | mod_decl!(foo); + | -------------- in this macro invocation + | + = note: this error originates in the macro `mod_decl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs new file mode 100644 index 000000000..01c087dbc --- /dev/null +++ b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs @@ -0,0 +1 @@ +// ignore-test not a test, auxiliary diff --git a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs new file mode 100644 index 000000000..2ec1c8bcc --- /dev/null +++ b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs @@ -0,0 +1,3 @@ +// ignore-test not a test, auxiliary + +mod_decl!(bar); diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs new file mode 100644 index 000000000..eb5e8e3e1 --- /dev/null +++ b/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs @@ -0,0 +1,6 @@ +// ignore-test this is not a test + +macro_rules! m { + () => { mod mod_file_not_owning_aux2; } +} +m!(); diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir b/tests/ui/directory_ownership/mod_file_not_owning_aux1/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/directory_ownership/mod_file_not_owning_aux1/mod_file_not_owning_aux2.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs new file mode 100644 index 000000000..920938c4a --- /dev/null +++ b/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs @@ -0,0 +1 @@ +// ignore-test this is not a test diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs new file mode 100644 index 000000000..6e4a39289 --- /dev/null +++ b/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs @@ -0,0 +1,3 @@ +// ignore-test this is not a test + +mod mod_file_not_owning_aux2; diff --git a/tests/ui/directory_ownership/non-inline-mod-restriction.rs b/tests/ui/directory_ownership/non-inline-mod-restriction.rs new file mode 100644 index 000000000..de4f81665 --- /dev/null +++ b/tests/ui/directory_ownership/non-inline-mod-restriction.rs @@ -0,0 +1,5 @@ +// Test that non-inline modules are not allowed inside blocks. + +fn main() { + mod foo; //~ ERROR cannot declare a non-inline module inside a block +} diff --git a/tests/ui/directory_ownership/non-inline-mod-restriction.stderr b/tests/ui/directory_ownership/non-inline-mod-restriction.stderr new file mode 100644 index 000000000..64189bee4 --- /dev/null +++ b/tests/ui/directory_ownership/non-inline-mod-restriction.stderr @@ -0,0 +1,8 @@ +error: cannot declare a non-inline module inside a block unless it has a path attribute + --> $DIR/non-inline-mod-restriction.rs:4:5 + | +LL | mod foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed new file mode 100644 index 000000000..ae0a84eea --- /dev/null +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed @@ -0,0 +1,21 @@ +// run-rustfix +struct X { + x: String, +} + +impl Drop for X { + fn drop(&mut self) { + println!("value: {}", self.x); + } +} + +fn unwrap(x: X) -> String { + let X { x: ref y } = x; //~ ERROR cannot move out of type + y.to_string() +} + +fn main() { + let x = X { x: "hello".to_string() }; + let y = unwrap(x); + println!("contents: {}", y); +} diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs new file mode 100644 index 000000000..c8db78610 --- /dev/null +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs @@ -0,0 +1,21 @@ +// run-rustfix +struct X { + x: String, +} + +impl Drop for X { + fn drop(&mut self) { + println!("value: {}", self.x); + } +} + +fn unwrap(x: X) -> String { + let X { x: y } = x; //~ ERROR cannot move out of type + y.to_string() +} + +fn main() { + let x = X { x: "hello".to_string() }; + let y = unwrap(x); + println!("contents: {}", y); +} diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr new file mode 100644 index 000000000..596ad4bf7 --- /dev/null +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr @@ -0,0 +1,17 @@ +error[E0509]: cannot move out of type `X`, which implements the `Drop` trait + --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:13:22 + | +LL | let X { x: y } = x; + | - ^ cannot move out of here + | | + | data moved here + | move occurs because `y` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let X { x: ref y } = x; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed new file mode 100644 index 000000000..c8a451efe --- /dev/null +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed @@ -0,0 +1,19 @@ +// run-rustfix +struct X { + x: String, +} + +impl Drop for X { + fn drop(&mut self) { + println!("value: {}", self.x); + } +} + +fn main() { + let x = X { x: "hello".to_string() }; + + match x { + //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait + X { x: ref y } => println!("contents: {}", y) + } +} diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs new file mode 100644 index 000000000..815567ffe --- /dev/null +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs @@ -0,0 +1,19 @@ +// run-rustfix +struct X { + x: String, +} + +impl Drop for X { + fn drop(&mut self) { + println!("value: {}", self.x); + } +} + +fn main() { + let x = X { x: "hello".to_string() }; + + match x { + //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait + X { x: y } => println!("contents: {}", y) + } +} diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr new file mode 100644 index 000000000..e32a4dd44 --- /dev/null +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr @@ -0,0 +1,20 @@ +error[E0509]: cannot move out of type `X`, which implements the `Drop` trait + --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:11 + | +LL | match x { + | ^ cannot move out of here +LL | +LL | X { x: y } => println!("contents: {}", y) + | - + | | + | data moved here + | move occurs because `y` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | X { x: ref y } => println!("contents: {}", y) + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/disambiguate-identical-names.rs b/tests/ui/disambiguate-identical-names.rs new file mode 100644 index 000000000..708d2cd76 --- /dev/null +++ b/tests/ui/disambiguate-identical-names.rs @@ -0,0 +1,15 @@ +pub mod submod { + // Create ambiguity with the std::vec::Vec item: + pub struct Vec; +} + +fn test(_v: &Vec>) { +} + +fn main() { + let v = std::collections::HashMap::new(); + v.insert(3u8, 1u8); + + test(&v); + //~^ ERROR mismatched types +} diff --git a/tests/ui/disambiguate-identical-names.stderr b/tests/ui/disambiguate-identical-names.stderr new file mode 100644 index 000000000..87560c4c7 --- /dev/null +++ b/tests/ui/disambiguate-identical-names.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/disambiguate-identical-names.rs:13:10 + | +LL | test(&v); + | ---- ^^ expected struct `Vec`, found struct `HashMap` + | | + | arguments to this function are incorrect + | + = note: expected reference `&std::vec::Vec>` + found reference `&HashMap` +note: function defined here + --> $DIR/disambiguate-identical-names.rs:6:4 + | +LL | fn test(_v: &Vec>) { + | ^^^^ ------------------ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/discrim/discrim-ill-typed.rs b/tests/ui/discrim/discrim-ill-typed.rs new file mode 100644 index 000000000..3cf0ea0e6 --- /dev/null +++ b/tests/ui/discrim/discrim-ill-typed.rs @@ -0,0 +1,114 @@ +// When explicit discriminant value has +// a type that does not match the representation +// type, rustc should fail gracefully. + +// See also run-pass/discrim-explicit-23030.rs where the input types +// are correct. + +#![allow(dead_code, unused_variables, unused_imports)] + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = 0_u8, + //~^ ERROR mismatched types + //~| expected `i8`, found `u8` + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = 0_i8, + //~^ ERROR mismatched types + //~| expected `u8`, found `i8` + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = 0_u16, + //~^ ERROR mismatched types + //~| expected `i16`, found `u16` + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = 0_i16, + //~^ ERROR mismatched types + //~| expected `u16`, found `i16` + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = 0_u32, + //~^ ERROR mismatched types + //~| expected `i32`, found `u32` + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = 0_i32, + //~^ ERROR mismatched types + //~| expected `u32`, found `i32` + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = 0_u64, + //~^ ERROR mismatched types + //~| expected `i64`, found `u64` + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = 0_i64, + //~^ ERROR mismatched types + //~| expected `u64`, found `i64` + } + + let x = A::Ok; +} + +fn main() { } diff --git a/tests/ui/discrim/discrim-ill-typed.stderr b/tests/ui/discrim/discrim-ill-typed.stderr new file mode 100644 index 000000000..27f516341 --- /dev/null +++ b/tests/ui/discrim/discrim-ill-typed.stderr @@ -0,0 +1,91 @@ +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:15:16 + | +LL | OhNo = 0_u8, + | ^^^^ expected `i8`, found `u8` + | +help: change the type of the numeric literal from `u8` to `i8` + | +LL | OhNo = 0_i8, + | ~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:28:16 + | +LL | OhNo = 0_i8, + | ^^^^ expected `u8`, found `i8` + | +help: change the type of the numeric literal from `i8` to `u8` + | +LL | OhNo = 0_u8, + | ~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:41:16 + | +LL | OhNo = 0_u16, + | ^^^^^ expected `i16`, found `u16` + | +help: change the type of the numeric literal from `u16` to `i16` + | +LL | OhNo = 0_i16, + | ~~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:54:16 + | +LL | OhNo = 0_i16, + | ^^^^^ expected `u16`, found `i16` + | +help: change the type of the numeric literal from `i16` to `u16` + | +LL | OhNo = 0_u16, + | ~~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:67:16 + | +LL | OhNo = 0_u32, + | ^^^^^ expected `i32`, found `u32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | OhNo = 0_i32, + | ~~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:80:16 + | +LL | OhNo = 0_i32, + | ^^^^^ expected `u32`, found `i32` + | +help: change the type of the numeric literal from `i32` to `u32` + | +LL | OhNo = 0_u32, + | ~~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:93:16 + | +LL | OhNo = 0_u64, + | ^^^^^ expected `i64`, found `u64` + | +help: change the type of the numeric literal from `u64` to `i64` + | +LL | OhNo = 0_i64, + | ~~~ + +error[E0308]: mismatched types + --> $DIR/discrim-ill-typed.rs:106:16 + | +LL | OhNo = 0_i64, + | ^^^^^ expected `u64`, found `i64` + | +help: change the type of the numeric literal from `i64` to `u64` + | +LL | OhNo = 0_u64, + | ~~~ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/discrim/discrim-overflow-2.rs b/tests/ui/discrim/discrim-overflow-2.rs new file mode 100644 index 000000000..ca24317c5 --- /dev/null +++ b/tests/ui/discrim/discrim-overflow-2.rs @@ -0,0 +1,80 @@ +// Issue 23030: Detect overflowing discriminant +// +// Check that we detect the overflow even if enum is not used. + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } +} + +fn main() { } diff --git a/tests/ui/discrim/discrim-overflow-2.stderr b/tests/ui/discrim/discrim-overflow-2.stderr new file mode 100644 index 000000000..3ca84c667 --- /dev/null +++ b/tests/ui/discrim/discrim-overflow-2.stderr @@ -0,0 +1,67 @@ +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:13:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 127 + | + = note: explicitly set `OhNo = -128` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:22:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 255 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:31:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 32767 + | + = note: explicitly set `OhNo = -32768` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:40:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 65535 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:49:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 2147483647 + | + = note: explicitly set `OhNo = -2147483648` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:58:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 4294967295 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:67:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 9223372036854775807 + | + = note: explicitly set `OhNo = -9223372036854775808` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow-2.rs:76:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 18446744073709551615 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0370`. diff --git a/tests/ui/discrim/discrim-overflow.rs b/tests/ui/discrim/discrim-overflow.rs new file mode 100644 index 000000000..774ced93c --- /dev/null +++ b/tests/ui/discrim/discrim-overflow.rs @@ -0,0 +1,99 @@ +// Issue 23030: Detect overflowing discriminant + +// See also run-pass/discrim-explicit-23030.rs where the suggested +// workaround is tested. + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } + + let x = A::Ok; +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } + + let x = A::Ok; +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + } + + let x = A::Ok; +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + //~| overflowed on value after 65535 + } + + let x = A::Ok; +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + //~| overflowed on value after 2147483647 + } + + let x = A::Ok; +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + //~| overflowed on value after 4294967295 + } + + let x = A::Ok; +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + //~| overflowed on value after 9223372036854775807 + } + + let x = A::Ok; +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo, //~ ERROR enum discriminant overflowed [E0370] + //~| overflowed on value after 18446744073709551615 + } + + let x = A::Ok; +} + +fn main() { } diff --git a/tests/ui/discrim/discrim-overflow.stderr b/tests/ui/discrim/discrim-overflow.stderr new file mode 100644 index 000000000..1b331bb1b --- /dev/null +++ b/tests/ui/discrim/discrim-overflow.stderr @@ -0,0 +1,67 @@ +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:11:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 127 + | + = note: explicitly set `OhNo = -128` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:22:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 255 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:33:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 32767 + | + = note: explicitly set `OhNo = -32768` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:44:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 65535 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:56:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 2147483647 + | + = note: explicitly set `OhNo = -2147483648` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:68:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 4294967295 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:80:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 9223372036854775807 + | + = note: explicitly set `OhNo = -9223372036854775808` if that is desired outcome + +error[E0370]: enum discriminant overflowed + --> $DIR/discrim-overflow.rs:92:9 + | +LL | OhNo, + | ^^^^ overflowed on value after 18446744073709551615 + | + = note: explicitly set `OhNo = 0` if that is desired outcome + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0370`. diff --git a/tests/ui/diverging-fallback-method-chain.rs b/tests/ui/diverging-fallback-method-chain.rs new file mode 100644 index 000000000..ba9f05c64 --- /dev/null +++ b/tests/ui/diverging-fallback-method-chain.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(unused_imports)] +// Test a regression found when building compiler. The `produce()` +// error type `T` winds up getting unified with result of `x.parse()`; +// the type of the closure given to `unwrap_or_else` needs to be +// inferred to `usize`. + +use std::num::ParseIntError; + +fn produce() -> Result<&'static str, T> { + Ok("22") +} + +fn main() { + let x: usize = produce() + .and_then(|x| x.parse()) + .unwrap_or_else(|_| panic!()); + println!("{}", x); +} diff --git a/tests/ui/diverging-fallback-option.rs b/tests/ui/diverging-fallback-option.rs new file mode 100644 index 000000000..46bdfc96d --- /dev/null +++ b/tests/ui/diverging-fallback-option.rs @@ -0,0 +1,14 @@ +// run-pass + +#![allow(warnings)] + +// Here the type of `c` is `Option`, where `?T` is unconstrained. +// Because there is data-flow from the `{ return; }` block, which +// diverges and hence has type `!`, into `c`, we will default `?T` to +// `!`, and hence this code compiles rather than failing and requiring +// a type annotation. + +fn main() { + let c = Some({ return; }); + c.unwrap(); +} diff --git a/tests/ui/diverging-fn-tail-35849.rs b/tests/ui/diverging-fn-tail-35849.rs new file mode 100644 index 000000000..f21ce2973 --- /dev/null +++ b/tests/ui/diverging-fn-tail-35849.rs @@ -0,0 +1,8 @@ +fn assert_sizeof() -> ! { + unsafe { + ::std::mem::transmute::(panic!()) + //~^ ERROR mismatched types + } +} + +fn main() { } diff --git a/tests/ui/diverging-fn-tail-35849.stderr b/tests/ui/diverging-fn-tail-35849.stderr new file mode 100644 index 000000000..21361489a --- /dev/null +++ b/tests/ui/diverging-fn-tail-35849.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/diverging-fn-tail-35849.rs:3:9 + | +LL | fn assert_sizeof() -> ! { + | - expected `!` because of return type +LL | unsafe { +LL | ::std::mem::transmute::(panic!()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found array `[u8; 8]` + | + = note: expected type `!` + found array `[u8; 8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/does-nothing.rs b/tests/ui/does-nothing.rs new file mode 100644 index 000000000..e4992e2cf --- /dev/null +++ b/tests/ui/does-nothing.rs @@ -0,0 +1,2 @@ +fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); } +//~^ ERROR cannot find value `this_does_nothing_what_the` in this scope diff --git a/tests/ui/does-nothing.stderr b/tests/ui/does-nothing.stderr new file mode 100644 index 000000000..dca792315 --- /dev/null +++ b/tests/ui/does-nothing.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `this_does_nothing_what_the` in this scope + --> $DIR/does-nothing.rs:1:32 + | +LL | fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs b/tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs new file mode 100644 index 000000000..bbab6f877 --- /dev/null +++ b/tests/ui/dollar-crate/dollar-crate-is-keyword-2.rs @@ -0,0 +1,13 @@ +mod a {} + +macro_rules! m { + () => { + use a::$crate; //~ ERROR unresolved import `a::$crate` + use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position + type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position + } +} + +m!(); + +fn main() {} diff --git a/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr b/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr new file mode 100644 index 000000000..d46029710 --- /dev/null +++ b/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr @@ -0,0 +1,37 @@ +error[E0433]: failed to resolve: `$crate` in paths can only be used in start position + --> $DIR/dollar-crate-is-keyword-2.rs:6:16 + | +LL | use a::$crate::b; + | ^^^^^^ `$crate` in paths can only be used in start position +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0432]: unresolved import `a::$crate` + --> $DIR/dollar-crate-is-keyword-2.rs:5:13 + | +LL | use a::$crate; + | ^^^^^^^^^ no `$crate` in `a` +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: `$crate` in paths can only be used in start position + --> $DIR/dollar-crate-is-keyword-2.rs:7:21 + | +LL | type A = a::$crate; + | ^^^^^^ `$crate` in paths can only be used in start position +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/dollar-crate/dollar-crate-is-keyword.rs b/tests/ui/dollar-crate/dollar-crate-is-keyword.rs new file mode 100644 index 000000000..d625163dc --- /dev/null +++ b/tests/ui/dollar-crate/dollar-crate-is-keyword.rs @@ -0,0 +1,17 @@ +macro_rules! m { + () => { + // Avoid having more than one `$crate`-named item in the same module, + // as even though they error, they still parse as `$crate` and conflict. + mod foo { + struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate` + } + + use $crate; //~ ERROR `$crate` may not be imported + use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate` + //~^ ERROR `$crate` may not be imported + } +} + +m!(); + +fn main() {} diff --git a/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr b/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr new file mode 100644 index 000000000..b02782230 --- /dev/null +++ b/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr @@ -0,0 +1,46 @@ +error: expected identifier, found reserved identifier `$crate` + --> $DIR/dollar-crate-is-keyword.rs:6:20 + | +LL | struct $crate {} + | ^^^^^^ expected identifier, found reserved identifier +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected identifier, found reserved identifier `$crate` + --> $DIR/dollar-crate-is-keyword.rs:10:23 + | +LL | use $crate as $crate; + | ^^^^^^ expected identifier, found reserved identifier +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `$crate` may not be imported + --> $DIR/dollar-crate-is-keyword.rs:9:9 + | +LL | use $crate; + | ^^^^^^^^^^^ +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `$crate` may not be imported + --> $DIR/dollar-crate-is-keyword.rs:10:9 + | +LL | use $crate as $crate; + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + diff --git a/tests/ui/dont-suggest-private-trait-method.rs b/tests/ui/dont-suggest-private-trait-method.rs new file mode 100644 index 000000000..6e2b1abd1 --- /dev/null +++ b/tests/ui/dont-suggest-private-trait-method.rs @@ -0,0 +1,6 @@ +struct T; + +fn main() { + T::new(); + //~^ ERROR no function or associated item named `new` found +} diff --git a/tests/ui/dont-suggest-private-trait-method.stderr b/tests/ui/dont-suggest-private-trait-method.stderr new file mode 100644 index 000000000..1492670dc --- /dev/null +++ b/tests/ui/dont-suggest-private-trait-method.stderr @@ -0,0 +1,12 @@ +error[E0599]: no function or associated item named `new` found for struct `T` in the current scope + --> $DIR/dont-suggest-private-trait-method.rs:4:8 + | +LL | struct T; + | -------- function or associated item `new` not found for this struct +... +LL | T::new(); + | ^^^ function or associated item not found in `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/double-ref.rs b/tests/ui/double-ref.rs new file mode 100644 index 000000000..e68b86833 --- /dev/null +++ b/tests/ui/double-ref.rs @@ -0,0 +1,36 @@ +// run-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn check_expr() { + let _: & usize = &1; + let _: & & usize = &&1; + let _: & & & usize = &&&1; + let _: & & & usize = & &&1; + let _: & & & & usize = &&&&1; + let _: & & & & usize = & &&&1; + let _: & & & & & usize = &&&&&1; +} + +fn check_ty() { + let _: &usize = & 1; + let _: &&usize = & & 1; + let _: &&&usize = & & & 1; + let _: & &&usize = & & & 1; + let _: &&&&usize = & & & & 1; + let _: & &&&usize = & & & & 1; + let _: &&&&&usize = & & & & & 1; +} + +fn check_pat() { + let &_ = & 1_usize; + let &&_ = & & 1_usize; + let &&&_ = & & & 1_usize; + let & &&_ = & & & 1_usize; + let &&&&_ = & & & & 1_usize; + let & &&&_ = & & & & 1_usize; + let &&&&&_ = & & & & & 1_usize; +} + +pub fn main() {} diff --git a/tests/ui/double-type-import.rs b/tests/ui/double-type-import.rs new file mode 100644 index 000000000..6b1eb65d5 --- /dev/null +++ b/tests/ui/double-type-import.rs @@ -0,0 +1,13 @@ +mod foo { + pub use self::bar::X; + use self::bar::X; + //~^ ERROR the name `X` is defined multiple times + + mod bar { + pub struct X; + } +} + +fn main() { + let _ = foo::X; +} diff --git a/tests/ui/double-type-import.stderr b/tests/ui/double-type-import.stderr new file mode 100644 index 000000000..a2f30d82e --- /dev/null +++ b/tests/ui/double-type-import.stderr @@ -0,0 +1,13 @@ +error[E0252]: the name `X` is defined multiple times + --> $DIR/double-type-import.rs:3:9 + | +LL | pub use self::bar::X; + | ------------ previous import of the type `X` here +LL | use self::bar::X; + | ^^^^^^^^^^^^ `X` reimported here + | + = note: `X` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/drop-bounds/drop-bounds-impl-drop.rs b/tests/ui/drop-bounds/drop-bounds-impl-drop.rs new file mode 100644 index 000000000..063efc7b3 --- /dev/null +++ b/tests/ui/drop-bounds/drop-bounds-impl-drop.rs @@ -0,0 +1,14 @@ +// run-pass +#![deny(drop_bounds)] +// As a special exemption, `impl Drop` in the return position raises no error. +// This allows a convenient way to return an unnamed drop guard. +fn voldemort_type() -> impl Drop { + struct Voldemort; + impl Drop for Voldemort { + fn drop(&mut self) {} + } + Voldemort +} +fn main() { + let _ = voldemort_type(); +} diff --git a/tests/ui/drop-bounds/drop-bounds.rs b/tests/ui/drop-bounds/drop-bounds.rs new file mode 100644 index 000000000..c73538278 --- /dev/null +++ b/tests/ui/drop-bounds/drop-bounds.rs @@ -0,0 +1,19 @@ +#![deny(drop_bounds)] +fn foo() {} //~ ERROR +fn bar() +where + U: Drop, //~ ERROR +{ +} +fn baz(_x: impl Drop) {} //~ ERROR +struct Foo { //~ ERROR + _x: T +} +struct Bar where U: Drop { //~ ERROR + _x: U +} +trait Baz: Drop { //~ ERROR +} +impl Baz for T { //~ ERROR +} +fn main() {} diff --git a/tests/ui/drop-bounds/drop-bounds.stderr b/tests/ui/drop-bounds/drop-bounds.stderr new file mode 100644 index 000000000..3ffb855a5 --- /dev/null +++ b/tests/ui/drop-bounds/drop-bounds.stderr @@ -0,0 +1,50 @@ +error: bounds on `T: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:2:11 + | +LL | fn foo() {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/drop-bounds.rs:1:9 + | +LL | #![deny(drop_bounds)] + | ^^^^^^^^^^^ + +error: bounds on `U: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:5:8 + | +LL | U: Drop, + | ^^^^ + +error: bounds on `impl Drop: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:8:17 + | +LL | fn baz(_x: impl Drop) {} + | ^^^^ + +error: bounds on `T: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:9:15 + | +LL | struct Foo { + | ^^^^ + +error: bounds on `U: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:12:24 + | +LL | struct Bar where U: Drop { + | ^^^^ + +error: bounds on `Self: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:15:12 + | +LL | trait Baz: Drop { + | ^^^^ + +error: bounds on `T: Drop` are most likely incorrect, consider instead using `std::mem::needs_drop` to detect whether a type can be trivially dropped + --> $DIR/drop-bounds.rs:17:9 + | +LL | impl Baz for T { + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/drop/auxiliary/dropck_eyepatch_extern_crate.rs b/tests/ui/drop/auxiliary/dropck_eyepatch_extern_crate.rs new file mode 100644 index 000000000..270d5de7a --- /dev/null +++ b/tests/ui/drop/auxiliary/dropck_eyepatch_extern_crate.rs @@ -0,0 +1,50 @@ +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself, +// and that this attributes effects are preserved when importing +// the type from another crate. +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +use std::cell::RefCell; + +pub trait Foo { fn foo(&self, _: &str); } + +pub struct Dt(pub &'static str, pub A); +pub struct Dr<'a, B:'a+Foo>(pub &'static str, pub &'a B); +pub struct Pt(pub &'static str, pub A, pub B); +pub struct Pr<'a, 'b, B:'a+'b+Foo>(pub &'static str, pub &'a B, pub &'b B); +pub struct St(pub &'static str, pub A); +pub struct Sr<'a, B:'a+Foo>(pub &'static str, pub &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +impl<'a, B: Foo> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +unsafe impl<#[may_dangle] A, B: Foo> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: Foo> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} + +impl Foo for RefCell { + fn foo(&self, s: &str) { + let s2 = format!("{}|{}", *self.borrow(), s); + *self.borrow_mut() = s2; + } +} + +impl<'a, T:Foo> Foo for &'a T { + fn foo(&self, s: &str) { + (*self).foo(s); + } +} diff --git a/tests/ui/drop/auxiliary/inline_dtor.rs b/tests/ui/drop/auxiliary/inline_dtor.rs new file mode 100644 index 000000000..5eee89fdc --- /dev/null +++ b/tests/ui/drop/auxiliary/inline_dtor.rs @@ -0,0 +1,8 @@ +#![crate_name="inline_dtor"] + +pub struct Foo; + +impl Drop for Foo { + #[inline] + fn drop(&mut self) {} +} diff --git a/tests/ui/drop/auxiliary/issue-10028.rs b/tests/ui/drop/auxiliary/issue-10028.rs new file mode 100644 index 000000000..135f26f40 --- /dev/null +++ b/tests/ui/drop/auxiliary/issue-10028.rs @@ -0,0 +1,9 @@ +pub struct ZeroLengthThingWithDestructor; +impl Drop for ZeroLengthThingWithDestructor { + fn drop(&mut self) {} +} +impl ZeroLengthThingWithDestructor { + pub fn new() -> ZeroLengthThingWithDestructor { + ZeroLengthThingWithDestructor + } +} diff --git a/tests/ui/drop/drop-foreign-fundamental.rs b/tests/ui/drop/drop-foreign-fundamental.rs new file mode 100644 index 000000000..c43df40d6 --- /dev/null +++ b/tests/ui/drop/drop-foreign-fundamental.rs @@ -0,0 +1,23 @@ +use std::ops::Deref; +use std::pin::Pin; + +struct Whatever(T); + +impl Deref for Whatever { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +struct A; + +impl Drop for Pin> { + //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions + fn drop(&mut self) {} +} + +fn main() { + let x = Pin::new(Whatever(1.0f32)); +} diff --git a/tests/ui/drop/drop-foreign-fundamental.stderr b/tests/ui/drop/drop-foreign-fundamental.stderr new file mode 100644 index 000000000..fbd1ba085 --- /dev/null +++ b/tests/ui/drop/drop-foreign-fundamental.stderr @@ -0,0 +1,9 @@ +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/drop-foreign-fundamental.rs:16:15 + | +LL | impl Drop for Pin> { + | ^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0120`. diff --git a/tests/ui/drop/drop-if-let-binding.rs b/tests/ui/drop/drop-if-let-binding.rs new file mode 100644 index 000000000..9c1ac4e0c --- /dev/null +++ b/tests/ui/drop/drop-if-let-binding.rs @@ -0,0 +1,7 @@ +// build-pass +// regression test for issue #88307 +// compile-flags: -C opt-level=s + +fn main() { + if let Some(_val) = Option::::None {} +} diff --git a/tests/ui/drop/drop-on-empty-block-exit.rs b/tests/ui/drop/drop-on-empty-block-exit.rs new file mode 100644 index 000000000..ef3a90a53 --- /dev/null +++ b/tests/ui/drop/drop-on-empty-block-exit.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +enum t { foo(Box), } + +pub fn main() { + let tt = t::foo(Box::new(10)); + match tt { t::foo(_z) => { } } +} diff --git a/tests/ui/drop/drop-on-ret.rs b/tests/ui/drop/drop-on-ret.rs new file mode 100644 index 000000000..290e274f3 --- /dev/null +++ b/tests/ui/drop/drop-on-ret.rs @@ -0,0 +1,15 @@ +// run-pass + + + +// pretty-expanded FIXME #23616 + +fn f() -> isize { + if true { + let _s: String = "should not leak".to_string(); + return 1; + } + return 0; +} + +pub fn main() { f(); } diff --git a/tests/ui/drop/drop-struct-as-object.rs b/tests/ui/drop/drop-struct-as-object.rs new file mode 100644 index 000000000..377027a4f --- /dev/null +++ b/tests/ui/drop/drop-struct-as-object.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(unused_variables)] +#![allow(non_upper_case_globals)] + +// Test that destructor on a struct runs successfully after the struct +// is boxed and converted to an object. + +static mut value: usize = 0; + +struct Cat { + name : usize, +} + +trait Dummy { + fn get(&self) -> usize; +} + +impl Dummy for Cat { + fn get(&self) -> usize { self.name } +} + +impl Drop for Cat { + fn drop(&mut self) { + unsafe { value = self.name; } + } +} + +pub fn main() { + { + let x = Box::new(Cat {name: 22}); + let nyan: Box = x as Box; + } + unsafe { + assert_eq!(value, 22); + } +} diff --git a/tests/ui/drop/drop-trait-enum.rs b/tests/ui/drop/drop-trait-enum.rs new file mode 100644 index 000000000..d2b77650a --- /dev/null +++ b/tests/ui/drop/drop-trait-enum.rs @@ -0,0 +1,94 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +// ignore-emscripten no threads support +// needs-unwind + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +#[derive(PartialEq, Debug)] +enum Message { + Dropped, + DestructorRan +} + +struct SendOnDrop { + sender: Sender +} + +impl Drop for SendOnDrop { + fn drop(&mut self) { + self.sender.send(Message::Dropped).unwrap(); + } +} + +enum Foo { + SimpleVariant(Sender), + NestedVariant(Box, SendOnDrop, Sender), + FailingVariant { on_drop: SendOnDrop } +} + +impl Drop for Foo { + fn drop(&mut self) { + match self { + &mut Foo::SimpleVariant(ref mut sender) => { + sender.send(Message::DestructorRan).unwrap(); + } + &mut Foo::NestedVariant(_, _, ref mut sender) => { + sender.send(Message::DestructorRan).unwrap(); + } + &mut Foo::FailingVariant { .. } => { + panic!("Failed"); + } + } + } +} + +pub fn main() { + let (sender, receiver) = channel(); + { + let v = Foo::SimpleVariant(sender); + } + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().ok(), None); + + let (sender, receiver) = channel(); + { + let v = Foo::NestedVariant(Box::new(42), SendOnDrop { sender: sender.clone() }, sender); + } + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().ok(), None); + + let (sender, receiver) = channel(); + let t = thread::spawn(move|| { + let v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } }; + }); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().ok(), None); + drop(t.join()); + + let (sender, receiver) = channel(); + let t = { + thread::spawn(move|| { + let mut v = Foo::NestedVariant(Box::new(42), SendOnDrop { + sender: sender.clone() + }, sender.clone()); + v = Foo::NestedVariant(Box::new(42), + SendOnDrop { sender: sender.clone() }, + sender.clone()); + v = Foo::SimpleVariant(sender.clone()); + v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } }; + }) + }; + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().unwrap(), Message::DestructorRan); + assert_eq!(receiver.recv().unwrap(), Message::Dropped); + assert_eq!(receiver.recv().ok(), None); + drop(t.join()); +} diff --git a/tests/ui/drop/drop-trait-generic.rs b/tests/ui/drop/drop-trait-generic.rs new file mode 100644 index 000000000..cdefb680c --- /dev/null +++ b/tests/ui/drop/drop-trait-generic.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +struct S { + x: T +} + +impl ::std::ops::Drop for S { + fn drop(&mut self) { + println!("bye"); + } +} + +pub fn main() { + let _x = S { x: 1 }; +} diff --git a/tests/ui/drop/drop-trait.rs b/tests/ui/drop/drop-trait.rs new file mode 100644 index 000000000..d93f77180 --- /dev/null +++ b/tests/ui/drop/drop-trait.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +struct Foo { + x: isize +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("bye"); + } +} + +pub fn main() { + let _x: Foo = Foo { x: 3 }; +} diff --git a/tests/ui/drop/drop-uninhabited-enum.rs b/tests/ui/drop/drop-uninhabited-enum.rs new file mode 100644 index 000000000..b3566f685 --- /dev/null +++ b/tests/ui/drop/drop-uninhabited-enum.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +enum Foo { } + +impl Drop for Foo { + fn drop(&mut self) { } +} + +fn foo(x: Foo) { } + +fn main() { } diff --git a/tests/ui/drop/drop-with-type-ascription-1.rs b/tests/ui/drop/drop-with-type-ascription-1.rs new file mode 100644 index 000000000..e5a1a48df --- /dev/null +++ b/tests/ui/drop/drop-with-type-ascription-1.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + let foo = "hello".to_string(); + let foo: Vec<&str> = foo.split_whitespace().collect(); + let invalid_string = &foo[0]; + assert_eq!(*invalid_string, "hello"); +} diff --git a/tests/ui/drop/drop-with-type-ascription-2.rs b/tests/ui/drop/drop-with-type-ascription-2.rs new file mode 100644 index 000000000..fb70ad48e --- /dev/null +++ b/tests/ui/drop/drop-with-type-ascription-2.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + let args = vec!["foobie", "asdf::asdf"]; + let arr: Vec<&str> = args[1].split("::").collect(); + assert_eq!(arr[0], "asdf"); + assert_eq!(arr[0], "asdf"); +} diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs new file mode 100644 index 000000000..5ce1fd54a --- /dev/null +++ b/tests/ui/drop/drop_order.rs @@ -0,0 +1,292 @@ +// run-pass +// compile-flags: -Z validate-mir +#![feature(let_chains)] + +use std::cell::RefCell; +use std::convert::TryInto; + +#[derive(Default)] +struct DropOrderCollector(RefCell>); + +struct LoudDrop<'a>(&'a DropOrderCollector, u32); + +impl Drop for LoudDrop<'_> { + fn drop(&mut self) { + println!("{}", self.1); + self.0.0.borrow_mut().push(self.1); + } +} + +impl DropOrderCollector { + fn option_loud_drop(&self, n: u32) -> Option { + Some(LoudDrop(self, n)) + } + + fn loud_drop(&self, n: u32) -> LoudDrop { + LoudDrop(self, n) + } + + fn print(&self, n: u32) { + println!("{}", n); + self.0.borrow_mut().push(n) + } + + fn if_(&self) { + if self.option_loud_drop(1).is_some() { + self.print(2); + } + + if self.option_loud_drop(3).is_none() { + unreachable!(); + } else if self.option_loud_drop(4).is_some() { + self.print(5); + } + + if { + if self.option_loud_drop(6).is_some() && self.option_loud_drop(7).is_some() { + self.loud_drop(8); + true + } else { + false + } + } { + self.print(9); + } + } + + fn if_let(&self) { + if let None = self.option_loud_drop(2) { + unreachable!(); + } else { + self.print(1); + } + + if let Some(_) = self.option_loud_drop(4) { + self.print(3); + } + + if let Some(_d) = self.option_loud_drop(6) { + self.print(5); + } + } + + fn match_(&self) { + match self.option_loud_drop(2) { + _any => self.print(1), + } + + match self.option_loud_drop(4) { + _ => self.print(3), + } + + match self.option_loud_drop(6) { + Some(_) => self.print(5), + _ => unreachable!(), + } + + match { + let _ = self.loud_drop(7); + let _d = self.loud_drop(9); + self.print(8); + () + } { + () => self.print(10), + } + + match { + match self.option_loud_drop(14) { + _ => { + self.print(11); + self.option_loud_drop(13) + } + } + } { + _ => self.print(12), + } + + match { + loop { + break match self.option_loud_drop(16) { + _ => { + self.print(15); + self.option_loud_drop(18) + } + }; + } + } { + _ => self.print(17), + } + } + + fn and_chain(&self) { + // issue-103107 + if self.option_loud_drop(1).is_some() // 1 + && self.option_loud_drop(2).is_some() // 2 + && self.option_loud_drop(3).is_some() // 3 + && self.option_loud_drop(4).is_some() // 4 + && self.option_loud_drop(5).is_some() // 5 + { + self.print(6); // 6 + } + + let _ = self.option_loud_drop(7).is_some() // 1 + && self.option_loud_drop(8).is_some() // 2 + && self.option_loud_drop(9).is_some(); // 3 + self.print(10); // 4 + + // Test associativity + if self.option_loud_drop(11).is_some() // 1 + && (self.option_loud_drop(12).is_some() // 2 + && self.option_loud_drop(13).is_some() // 3 + && self.option_loud_drop(14).is_some()) // 4 + && self.option_loud_drop(15).is_some() // 5 + { + self.print(16); // 6 + } + } + + fn or_chain(&self) { + // issue-103107 + if self.option_loud_drop(1).is_none() // 1 + || self.option_loud_drop(2).is_none() // 2 + || self.option_loud_drop(3).is_none() // 3 + || self.option_loud_drop(4).is_none() // 4 + || self.option_loud_drop(5).is_some() // 5 + { + self.print(6); // 6 + } + + let _ = self.option_loud_drop(7).is_none() // 1 + || self.option_loud_drop(8).is_none() // 2 + || self.option_loud_drop(9).is_none(); // 3 + self.print(10); // 4 + + // Test associativity + if self.option_loud_drop(11).is_none() // 1 + || (self.option_loud_drop(12).is_none() // 2 + || self.option_loud_drop(13).is_none() // 3 + || self.option_loud_drop(14).is_none()) // 4 + || self.option_loud_drop(15).is_some() // 5 + { + self.print(16); // 6 + } + } + + fn mixed_and_or_chain(&self) { + // issue-103107 + if self.option_loud_drop(1).is_none() // 1 + || self.option_loud_drop(2).is_none() // 2 + || self.option_loud_drop(3).is_some() // 3 + && self.option_loud_drop(4).is_some() // 4 + && self.option_loud_drop(5).is_none() // 5 + || self.option_loud_drop(6).is_none() // 6 + || self.option_loud_drop(7).is_some() // 7 + { + self.print(8); // 8 + } + } + + fn let_chain(&self) { + // take the "then" branch + if self.option_loud_drop(1).is_some() // 1 + && self.option_loud_drop(2).is_some() // 2 + && let Some(_d) = self.option_loud_drop(4) { // 4 + self.print(3); // 3 + } + + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(8) { // 4 + unreachable!(); + } else { + self.print(7); // 3 + } + + // let exprs interspersed + if self.option_loud_drop(9).is_some() // 1 + && let Some(_d) = self.option_loud_drop(13) // 5 + && self.option_loud_drop(10).is_some() // 2 + && let Some(_e) = self.option_loud_drop(12) { // 4 + self.print(11); // 3 + } + + // let exprs first + if let Some(_d) = self.option_loud_drop(18) // 5 + && let Some(_e) = self.option_loud_drop(17) // 4 + && self.option_loud_drop(14).is_some() // 1 + && self.option_loud_drop(15).is_some() { // 2 + self.print(16); // 3 + } + + // let exprs last + if self.option_loud_drop(19).is_some() // 1 + && self.option_loud_drop(20).is_some() // 2 + && let Some(_d) = self.option_loud_drop(23) // 5 + && let Some(_e) = self.option_loud_drop(22) { // 4 + self.print(21); // 3 + } + } + + fn while_(&self) { + let mut v = self.option_loud_drop(4); + while let Some(_d) = v + && self.option_loud_drop(1).is_some() + && self.option_loud_drop(2).is_some() { + self.print(3); + v = None; + } + } + + fn assert_sorted(self) { + assert!( + self.0 + .into_inner() + .into_iter() + .enumerate() + .all(|(idx, item)| idx + 1 == item.try_into().unwrap()) + ); + } +} + +fn main() { + println!("-- if --"); + let collector = DropOrderCollector::default(); + collector.if_(); + collector.assert_sorted(); + + println!("-- and chain --"); + let collector = DropOrderCollector::default(); + collector.and_chain(); + collector.assert_sorted(); + + println!("-- or chain --"); + let collector = DropOrderCollector::default(); + collector.or_chain(); + collector.assert_sorted(); + + println!("-- mixed and/or chain --"); + let collector = DropOrderCollector::default(); + collector.mixed_and_or_chain(); + collector.assert_sorted(); + + println!("-- if let --"); + let collector = DropOrderCollector::default(); + collector.if_let(); + collector.assert_sorted(); + + println!("-- match --"); + let collector = DropOrderCollector::default(); + collector.match_(); + collector.assert_sorted(); + + println!("-- let chain --"); + let collector = DropOrderCollector::default(); + collector.let_chain(); + collector.assert_sorted(); + + println!("-- while --"); + let collector = DropOrderCollector::default(); + collector.while_(); + collector.assert_sorted(); +} diff --git a/tests/ui/drop/dropck-eyepatch-extern-crate.rs b/tests/ui/drop/dropck-eyepatch-extern-crate.rs new file mode 100644 index 000000000..fecfd5edf --- /dev/null +++ b/tests/ui/drop/dropck-eyepatch-extern-crate.rs @@ -0,0 +1,39 @@ +// run-pass +// aux-build:dropck_eyepatch_extern_crate.rs + +extern crate dropck_eyepatch_extern_crate as other; + +use other::{Dt,Dr,Pt,Pr,St,Sr}; + +fn main() { + use std::cell::RefCell; + + struct CheckOnDrop(RefCell, &'static str); + impl Drop for CheckOnDrop { + fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } + } + + let c_long; + let (c, dt, dr, pt, pr, st, sr) + : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = CheckOnDrop(RefCell::new("c_long".to_string()), + "c_long|pr|pt|dr|dt"); + c = CheckOnDrop(RefCell::new("c".to_string()), + "c"); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long.0); + dr = Dr("dr", &c_long.0); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c.0, &c_long.0); + pr = Pr("pr", &c.0, &c_long.0); + + // No error: St and Sr have no destructor. + st = St("st", &c.0); + sr = Sr("sr", &c.0); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); + assert_eq!(*c_long.0.borrow(), "c_long"); + assert_eq!(*c.0.borrow(), "c"); +} diff --git a/tests/ui/drop/dropck-eyepatch-reorder.rs b/tests/ui/drop/dropck-eyepatch-reorder.rs new file mode 100644 index 000000000..0d7af3d4f --- /dev/null +++ b/tests/ui/drop/dropck-eyepatch-reorder.rs @@ -0,0 +1,79 @@ +// run-pass +#![feature(dropck_eyepatch)] + +// The point of this test is to test uses of `#[may_dangle]` attribute +// where the formal declaration order (in the impl generics) does not +// match the actual usage order (in the type instantiation). +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +trait Foo { fn foo(&self, _: &str); } + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+Foo>(&'static str, &'a B); +struct Pt(&'static str, #[allow(unused_tuple_struct_fields)] A, B); +struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B, &'b B); +struct St(&'static str, #[allow(unused_tuple_struct_fields)] A); +struct Sr<'a, B:'a+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +impl<'a, B: Foo> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +unsafe impl Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} +unsafe impl<'b, #[may_dangle] 'a, B: Foo> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} + +fn main() { + use std::cell::RefCell; + + impl Foo for RefCell { + fn foo(&self, s: &str) { + let s2 = format!("{}|{}", *self.borrow(), s); + *self.borrow_mut() = s2; + } + } + + impl<'a, T:Foo> Foo for &'a T { + fn foo(&self, s: &str) { + (*self).foo(s); + } + } + + struct CheckOnDrop(RefCell, &'static str); + impl Drop for CheckOnDrop { + fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } + } + + let c_long; + let (c, dt, dr, pt, pr, st, sr) + : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = CheckOnDrop(RefCell::new("c_long".to_string()), + "c_long|pr|pt|dr|dt"); + c = CheckOnDrop(RefCell::new("c".to_string()), + "c"); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long.0); + dr = Dr("dr", &c_long.0); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c.0, &c_long.0); + pr = Pr("pr", &c.0, &c_long.0); + + // No error: St and Sr have no destructor. + st = St("st", &c.0); + sr = Sr("sr", &c.0); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); + assert_eq!(*c_long.0.borrow(), "c_long"); + assert_eq!(*c.0.borrow(), "c"); +} diff --git a/tests/ui/drop/dropck-eyepatch.rs b/tests/ui/drop/dropck-eyepatch.rs new file mode 100644 index 000000000..3c4840d5c --- /dev/null +++ b/tests/ui/drop/dropck-eyepatch.rs @@ -0,0 +1,102 @@ +// run-pass +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself. +// +// Here we test that a model use of `#[may_dangle]` will compile and run. +// +// The illustration is made concrete by comparison with two variations +// on the type with `#[may_dangle]`: +// +// 1. an analogous type that does not implement `Drop` (and thus +// should exhibit maximal flexibility with respect to dropck), and +// +// 2. an analogous type that does not use `#[may_dangle]` (and thus +// should exhibit the standard limitations imposed by dropck. +// +// The types in this file follow a pattern, {D,P,S}{t,r}, where: +// +// - D means "I implement Drop" +// +// - P means "I implement Drop but guarantee my (first) parameter is +// pure, i.e., not accessed from the destructor"; no other parameters +// are pure. +// +// - S means "I do not implement Drop" +// +// - t suffix is used when the first generic is a type +// +// - r suffix is used when the first generic is a lifetime. + +trait Foo { fn foo(&self, _: &str); } + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+Foo>(&'static str, &'a B); +struct Pt(&'static str, #[allow(unused_tuple_struct_fields)] A, B); +struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B, &'b B); +struct St(&'static str, #[allow(unused_tuple_struct_fields)] A); +struct Sr<'a, B:'a+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +impl<'a, B: Foo> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } +} +unsafe impl<#[may_dangle] A, B: Foo> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: Foo> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } +} + +fn main() { + use std::cell::RefCell; + + impl Foo for RefCell { + fn foo(&self, s: &str) { + let s2 = format!("{}|{}", *self.borrow(), s); + *self.borrow_mut() = s2; + } + } + + impl<'a, T:Foo> Foo for &'a T { + fn foo(&self, s: &str) { + (*self).foo(s); + } + } + + struct CheckOnDrop(RefCell, &'static str); + impl Drop for CheckOnDrop { + fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } + } + + let c_long; + let (c, dt, dr, pt, pr, st, sr) + : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); + c_long = CheckOnDrop(RefCell::new("c_long".to_string()), + "c_long|pr|pt|dr|dt"); + c = CheckOnDrop(RefCell::new("c".to_string()), + "c"); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long.0); + dr = Dr("dr", &c_long.0); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c.0, &c_long.0); + pr = Pr("pr", &c.0, &c_long.0); + + // No error: St and Sr have no destructor. + st = St("st", &c.0); + sr = Sr("sr", &c.0); + + println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); + assert_eq!(*c_long.0.borrow(), "c_long"); + assert_eq!(*c.0.borrow(), "c"); +} diff --git a/tests/ui/drop/dropck_legal_cycles.rs b/tests/ui/drop/dropck_legal_cycles.rs new file mode 100644 index 000000000..6a0fe7784 --- /dev/null +++ b/tests/ui/drop/dropck_legal_cycles.rs @@ -0,0 +1,1183 @@ +// run-pass +// This test exercises cases where cyclic structure is legal, +// including when the cycles go through data-structures such +// as `Vec` or `TypedArena`. +// +// The intent is to cover as many such cases as possible, ensuring +// that if the compiler did not complain circa Rust 1.x (1.2 as of +// this writing), then it will continue to not complain in the future. +// +// Note that while some of the tests are only exercising using the +// given collection as a "backing store" for a set of nodes that hold +// the actual cycle (and thus the cycle does not go through the +// collection itself in such cases), in general we *do* want to make +// sure to have at least one example exercising a cycle that goes +// through the collection, for every collection type that supports +// this. + +// HIGH LEVEL DESCRIPTION OF THE TEST ARCHITECTURE +// ----------------------------------------------- +// +// We pick a data structure and want to make a cyclic construction +// from it. Each test of interest is labelled starting with "Cycle N: +// { ... }" where N is the test number and the "..."`is filled in with +// a graphviz-style description of the graph structure that the +// author believes is being made. So "{ a -> b, b -> (c,d), (c,d) -> e }" +// describes a line connected to a diamond: +// +// c +// / \ +// a - b e +// \ / +// d +// +// (Note that the above directed graph is actually acyclic.) +// +// The different graph structures are often composed of different data +// types. Some may be built atop `Vec`, others atop `HashMap`, etc. +// +// For each graph structure, we actually *confirm* that a cycle exists +// (as a safe-guard against a test author accidentally leaving it out) +// by traversing each graph and "proving" that a cycle exists within it. +// +// To do this, while trying to keep the code uniform (despite working +// with different underlying collection and smart-pointer types), we +// have a standard traversal API: +// +// 1. every node in the graph carries a `mark` (a u32, init'ed to 0). +// +// 2. every node provides a method to visit its children +// +// 3. a traversal attmepts to visit the nodes of the graph and prove that +// it sees the same node twice. It does this by setting the mark of each +// node to a fresh non-zero value, and if it sees the current mark, it +// "knows" that it must have found a cycle, and stops attempting further +// traversal. +// +// 4. each traversal is controlled by a bit-string that tells it which child +// it visit when it can take different paths. As a simple example, +// in a binary tree, 0 could mean "left" (and 1, "right"), so that +// "00010" means "left, left, left, right, left". (In general it will +// read as many bits as it needs to choose one child.) +// +// The graphs in this test are all meant to be very small, and thus +// short bitstrings of less than 64 bits should always suffice. +// +// (An earlier version of this test infrastructure simply had any +// given traversal visit all children it encountered, in a +// depth-first manner; one problem with this approach is that an +// acyclic graph can still have sharing, which would then be treated +// as a repeat mark and reported as a detected cycle.) +// +// The travseral code is a little more complicated because it has been +// programmed in a somewhat defensive manner. For example it also has +// a max threshold for the number of nodes it will visit, to guard +// against scenarios where the nodes are not correctly setting their +// mark when asked. There are various other methods not discussed here +// that are for aiding debugging the test when it runs, such as the +// `name` method that all nodes provide. +// +// So each test: +// +// 1. allocates the nodes in the graph, +// +// 2. sets up the links in the graph, +// +// 3. clones the "ContextData" +// +// 4. chooses a new current mark value for this test +// +// 5. initiates a traversal, potentially from multiple starting points +// (aka "roots"), with a given control-string (potentially a +// different string for each root). if it does start from a +// distinct root, then such a test should also increment the +// current mark value, so that this traversal is considered +// distinct from the prior one on this graph structure. +// +// Note that most of the tests work with the default control string +// of all-zeroes. +// +// 6. assert that the context confirms that it actually saw a cycle (since a traversal +// might have terminated, e.g., on a tree structure that contained no cycles). + +use std::cell::{Cell, RefCell}; +use std::cmp::Ordering; +use std::collections::BinaryHeap; +use std::collections::HashMap; +use std::collections::LinkedList; +use std::collections::VecDeque; +use std::collections::btree_map::BTreeMap; +use std::collections::btree_set::BTreeSet; +use std::hash::{Hash, Hasher}; +use std::rc::Rc; +use std::sync::{Arc, RwLock, Mutex}; + +const PRINT: bool = false; + +pub fn main() { + let c_orig = ContextData { + curr_depth: 0, + max_depth: 3, + visited: 0, + max_visits: 1000, + skipped: 0, + curr_mark: 0, + saw_prev_marked: false, + control_bits: 0, + }; + + // SANITY CHECK FOR TEST SUITE (thus unnumbered) + // Not a cycle: { v[0] -> (v[1], v[2]), v[1] -> v[3], v[2] -> v[3] }; + let v: Vec = vec![Named::new("s0"), + Named::new("s1"), + Named::new("s2"), + Named::new("s3")]; + v[0].next.set((Some(&v[1]), Some(&v[2]))); + v[1].next.set((Some(&v[3]), None)); + v[2].next.set((Some(&v[3]), None)); + v[3].next.set((None, None)); + + let mut c = c_orig.clone(); + c.curr_mark = 10; + assert!(!c.saw_prev_marked); + v[0].descend_into_self(&mut c); + assert!(!c.saw_prev_marked); // <-- different from below, b/c acyclic above + + if PRINT { println!(); } + + // Cycle 1: { v[0] -> v[1], v[1] -> v[0] }; + // does not exercise `v` itself + let v: Vec = vec![Named::new("s0"), + Named::new("s1")]; + v[0].next.set(Some(&v[1])); + v[1].next.set(Some(&v[0])); + + let mut c = c_orig.clone(); + c.curr_mark = 10; + assert!(!c.saw_prev_marked); + v[0].descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 2: { v[0] -> v, v[1] -> v } + let v: V = Named::new("v"); + v.contents[0].set(Some(&v)); + v.contents[1].set(Some(&v)); + + let mut c = c_orig.clone(); + c.curr_mark = 20; + assert!(!c.saw_prev_marked); + v.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 3: { hk0 -> hv0, hv0 -> hk0, hk1 -> hv1, hv1 -> hk1 }; + // does not exercise `h` itself + + let mut h: HashMap = HashMap::new(); + h.insert(Named::new("hk0"), Named::new("hv0")); + h.insert(Named::new("hk1"), Named::new("hv1")); + for (key, val) in h.iter() { + val.next.set(Some(key)); + key.next.set(Some(val)); + } + + let mut c = c_orig.clone(); + c.curr_mark = 30; + for (key, _) in h.iter() { + c.curr_mark += 1; + c.saw_prev_marked = false; + key.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + } + + if PRINT { println!(); } + + // Cycle 4: { h -> (hmk0,hmv0,hmk1,hmv1), {hmk0,hmv0,hmk1,hmv1} -> h } + + let mut h: HashMap = HashMap::new(); + h.insert(Named::new("hmk0"), Named::new("hmv0")); + h.insert(Named::new("hmk0"), Named::new("hmv0")); + for (key, val) in h.iter() { + val.contents.set(Some(&h)); + key.contents.set(Some(&h)); + } + + let mut c = c_orig.clone(); + c.max_depth = 2; + c.curr_mark = 40; + for (key, _) in h.iter() { + c.curr_mark += 1; + c.saw_prev_marked = false; + key.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + // break; + } + + if PRINT { println!(); } + + // Cycle 5: { vd[0] -> vd[1], vd[1] -> vd[0] }; + // does not exercise vd itself + let mut vd: VecDeque = VecDeque::new(); + vd.push_back(Named::new("d0")); + vd.push_back(Named::new("d1")); + vd[0].next.set(Some(&vd[1])); + vd[1].next.set(Some(&vd[0])); + + let mut c = c_orig.clone(); + c.curr_mark = 50; + assert!(!c.saw_prev_marked); + vd[0].descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 6: { vd -> (vd0, vd1), {vd0, vd1} -> vd } + let mut vd: VecDeque = VecDeque::new(); + vd.push_back(Named::new("vd0")); + vd.push_back(Named::new("vd1")); + vd[0].contents.set(Some(&vd)); + vd[1].contents.set(Some(&vd)); + + let mut c = c_orig.clone(); + c.curr_mark = 60; + assert!(!c.saw_prev_marked); + vd[0].descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 7: { vm -> (vm0, vm1), {vm0, vm1} -> vm } + let mut vm: HashMap = HashMap::new(); + vm.insert(0, Named::new("vm0")); + vm.insert(1, Named::new("vm1")); + vm[&0].contents.set(Some(&vm)); + vm[&1].contents.set(Some(&vm)); + + let mut c = c_orig.clone(); + c.curr_mark = 70; + assert!(!c.saw_prev_marked); + vm[&0].descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 8: { ll -> (ll0, ll1), {ll0, ll1} -> ll } + let mut ll: LinkedList = LinkedList::new(); + ll.push_back(Named::new("ll0")); + ll.push_back(Named::new("ll1")); + for e in &ll { + e.contents.set(Some(&ll)); + } + + let mut c = c_orig.clone(); + c.curr_mark = 80; + for e in &ll { + c.curr_mark += 1; + c.saw_prev_marked = false; + e.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + // break; + } + + if PRINT { println!(); } + + // Cycle 9: { bh -> (bh0, bh1), {bh0, bh1} -> bh } + let mut bh: BinaryHeap = BinaryHeap::new(); + bh.push(Named::new("bh0")); + bh.push(Named::new("bh1")); + for b in bh.iter() { + b.contents.set(Some(&bh)); + } + + let mut c = c_orig.clone(); + c.curr_mark = 90; + for b in &bh { + c.curr_mark += 1; + c.saw_prev_marked = false; + b.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + // break; + } + + if PRINT { println!(); } + + // Cycle 10: { btm -> (btk0, btv1), {bt0, bt1} -> btm } + let mut btm: BTreeMap = BTreeMap::new(); + btm.insert(Named::new("btk0"), Named::new("btv0")); + btm.insert(Named::new("btk1"), Named::new("btv1")); + for (k, v) in btm.iter() { + k.contents.set(Some(&btm)); + v.contents.set(Some(&btm)); + } + + let mut c = c_orig.clone(); + c.curr_mark = 100; + for (k, _) in &btm { + c.curr_mark += 1; + c.saw_prev_marked = false; + k.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + // break; + } + + if PRINT { println!(); } + + // Cycle 10: { bts -> (bts0, bts1), {bts0, bts1} -> btm } + let mut bts: BTreeSet = BTreeSet::new(); + bts.insert(Named::new("bts0")); + bts.insert(Named::new("bts1")); + for v in bts.iter() { + v.contents.set(Some(&bts)); + } + + let mut c = c_orig.clone(); + c.curr_mark = 100; + for b in &bts { + c.curr_mark += 1; + c.saw_prev_marked = false; + b.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + // break; + } + + if PRINT { println!(); } + + // Cycle 11: { rc0 -> (rc1, rc2), rc1 -> (), rc2 -> rc0 } + let (rc0, rc1, rc2): (RCRC, RCRC, RCRC); + rc0 = RCRC::new("rcrc0"); + rc1 = RCRC::new("rcrc1"); + rc2 = RCRC::new("rcrc2"); + rc0.0.borrow_mut().children.0 = Some(&rc1); + rc0.0.borrow_mut().children.1 = Some(&rc2); + rc2.0.borrow_mut().children.0 = Some(&rc0); + + let mut c = c_orig.clone(); + c.control_bits = 0b1; + c.curr_mark = 110; + assert!(!c.saw_prev_marked); + rc0.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // We want to take the previous Rc case and generalize it to Arc. + // + // We can use refcells if we're single-threaded (as this test is). + // If one were to generalize these constructions to a + // multi-threaded context, then it might seem like we could choose + // between either an RwLock or a Mutex to hold the owned arcs on + // each node. + // + // Part of the point of this test is to actually confirm that the + // cycle exists by traversing it. We can do that just fine with an + // RwLock (since we can grab the child pointers in read-only + // mode), but we cannot lock a std::sync::Mutex to guard reading + // from each node via the same pattern, since once you hit the + // cycle, you'll be trying to acquiring the same lock twice. + // (We deal with this by exiting the traversal early if try_lock fails.) + + // Cycle 12: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, refcells + let (arc0, arc1, arc2): (ARCRC, ARCRC, ARCRC); + arc0 = ARCRC::new("arcrc0"); + arc1 = ARCRC::new("arcrc1"); + arc2 = ARCRC::new("arcrc2"); + arc0.0.borrow_mut().children.0 = Some(&arc1); + arc0.0.borrow_mut().children.1 = Some(&arc2); + arc2.0.borrow_mut().children.0 = Some(&arc0); + + let mut c = c_orig.clone(); + c.control_bits = 0b1; + c.curr_mark = 110; + assert!(!c.saw_prev_marked); + arc0.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 13: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, rwlocks + let (arc0, arc1, arc2): (ARCRW, ARCRW, ARCRW); + arc0 = ARCRW::new("arcrw0"); + arc1 = ARCRW::new("arcrw1"); + arc2 = ARCRW::new("arcrw2"); + arc0.0.write().unwrap().children.0 = Some(&arc1); + arc0.0.write().unwrap().children.1 = Some(&arc2); + arc2.0.write().unwrap().children.0 = Some(&arc0); + + let mut c = c_orig.clone(); + c.control_bits = 0b1; + c.curr_mark = 110; + assert!(!c.saw_prev_marked); + arc0.descend_into_self(&mut c); + assert!(c.saw_prev_marked); + + if PRINT { println!(); } + + // Cycle 14: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, mutexs + let (arc0, arc1, arc2): (ARCM, ARCM, ARCM); + arc0 = ARCM::new("arcm0"); + arc1 = ARCM::new("arcm1"); + arc2 = ARCM::new("arcm2"); + arc0.1.lock().unwrap().children.0 = Some(&arc1); + arc0.1.lock().unwrap().children.1 = Some(&arc2); + arc2.1.lock().unwrap().children.0 = Some(&arc0); + + let mut c = c_orig.clone(); + c.control_bits = 0b1; + c.curr_mark = 110; + assert!(!c.saw_prev_marked); + arc0.descend_into_self(&mut c); + assert!(c.saw_prev_marked); +} + +trait Named { + fn new(_: &'static str) -> Self; + fn name(&self) -> &str; +} + +trait Marked { + fn mark(&self) -> M; + fn set_mark(&self, mark: M); +} + +struct S<'a> { + name: &'static str, + mark: Cell, + next: Cell>>, +} + +impl<'a> Named for S<'a> { + fn new(name: &'static str) -> S<'a> { + S { name: name, mark: Cell::new(0), next: Cell::new(None) } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for S<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +struct S2<'a> { + name: &'static str, + mark: Cell, + next: Cell<(Option<&'a S2<'a>>, Option<&'a S2<'a>>)>, +} + +impl<'a> Named for S2<'a> { + fn new(name: &'static str) -> S2<'a> { + S2 { name: name, mark: Cell::new(0), next: Cell::new((None, None)) } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for S2<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { + self.mark.set(mark); + } +} + +struct V<'a> { + name: &'static str, + mark: Cell, + contents: Vec>>>, +} + +impl<'a> Named for V<'a> { + fn new(name: &'static str) -> V<'a> { + V { name: name, + mark: Cell::new(0), + contents: vec![Cell::new(None), Cell::new(None)] + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for V<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +#[derive(Eq)] +struct H<'a> { + name: &'static str, + mark: Cell, + next: Cell>>, +} + +impl<'a> Named for H<'a> { + fn new(name: &'static str) -> H<'a> { + H { name: name, mark: Cell::new(0), next: Cell::new(None) } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for H<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +impl<'a> PartialEq for H<'a> { + fn eq(&self, rhs: &H<'a>) -> bool { + self.name == rhs.name + } +} + +impl<'a> Hash for H<'a> { + fn hash(&self, state: &mut H) { + self.name.hash(state) + } +} + +#[derive(Eq)] +struct HM<'a> { + name: &'static str, + mark: Cell, + contents: Cell, HM<'a>>>>, +} + +impl<'a> Named for HM<'a> { + fn new(name: &'static str) -> HM<'a> { + HM { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for HM<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +impl<'a> PartialEq for HM<'a> { + fn eq(&self, rhs: &HM<'a>) -> bool { + self.name == rhs.name + } +} + +impl<'a> Hash for HM<'a> { + fn hash(&self, state: &mut H) { + self.name.hash(state) + } +} + + +struct VD<'a> { + name: &'static str, + mark: Cell, + contents: Cell>>>, +} + +impl<'a> Named for VD<'a> { + fn new(name: &'static str) -> VD<'a> { + VD { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for VD<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +struct VM<'a> { + name: &'static str, + mark: Cell, + contents: Cell>>>, +} + +impl<'a> Named for VM<'a> { + fn new(name: &'static str) -> VM<'a> { + VM { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for VM<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +struct LL<'a> { + name: &'static str, + mark: Cell, + contents: Cell>>>, +} + +impl<'a> Named for LL<'a> { + fn new(name: &'static str) -> LL<'a> { + LL { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for LL<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +struct BH<'a> { + name: &'static str, + mark: Cell, + contents: Cell>>>, +} + +impl<'a> Named for BH<'a> { + fn new(name: &'static str) -> BH<'a> { + BH { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for BH<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +impl<'a> Eq for BH<'a> { } + +impl<'a> PartialEq for BH<'a> { + fn eq(&self, rhs: &BH<'a>) -> bool { + self.name == rhs.name + } +} + +impl<'a> PartialOrd for BH<'a> { + fn partial_cmp(&self, rhs: &BH<'a>) -> Option { + Some(self.cmp(rhs)) + } +} + +impl<'a> Ord for BH<'a> { + fn cmp(&self, rhs: &BH<'a>) -> Ordering { + self.name.cmp(rhs.name) + } +} + +struct BTM<'a> { + name: &'static str, + mark: Cell, + contents: Cell, BTM<'a>>>>, +} + +impl<'a> Named for BTM<'a> { + fn new(name: &'static str) -> BTM<'a> { + BTM { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for BTM<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +impl<'a> Eq for BTM<'a> { } + +impl<'a> PartialEq for BTM<'a> { + fn eq(&self, rhs: &BTM<'a>) -> bool { + self.name == rhs.name + } +} + +impl<'a> PartialOrd for BTM<'a> { + fn partial_cmp(&self, rhs: &BTM<'a>) -> Option { + Some(self.cmp(rhs)) + } +} + +impl<'a> Ord for BTM<'a> { + fn cmp(&self, rhs: &BTM<'a>) -> Ordering { + self.name.cmp(rhs.name) + } +} + +struct BTS<'a> { + name: &'static str, + mark: Cell, + contents: Cell>>>, +} + +impl<'a> Named for BTS<'a> { + fn new(name: &'static str) -> BTS<'a> { + BTS { name: name, + mark: Cell::new(0), + contents: Cell::new(None) + } + } + fn name(&self) -> &str { self.name } +} + +impl<'a> Marked for BTS<'a> { + fn mark(&self) -> u32 { self.mark.get() } + fn set_mark(&self, mark: u32) { self.mark.set(mark); } +} + +impl<'a> Eq for BTS<'a> { } + +impl<'a> PartialEq for BTS<'a> { + fn eq(&self, rhs: &BTS<'a>) -> bool { + self.name == rhs.name + } +} + +impl<'a> PartialOrd for BTS<'a> { + fn partial_cmp(&self, rhs: &BTS<'a>) -> Option { + Some(self.cmp(rhs)) + } +} + +impl<'a> Ord for BTS<'a> { + fn cmp(&self, rhs: &BTS<'a>) -> Ordering { + self.name.cmp(rhs.name) + } +} + +#[derive(Clone)] +struct RCRCData<'a> { + name: &'static str, + mark: Cell, + children: (Option<&'a RCRC<'a>>, Option<&'a RCRC<'a>>), +} +#[derive(Clone)] +struct RCRC<'a>(Rc>>); + +impl<'a> Named for RCRC<'a> { + fn new(name: &'static str) -> Self { + RCRC(Rc::new(RefCell::new(RCRCData { + name: name, mark: Cell::new(0), children: (None, None), }))) + } + fn name(&self) -> &str { self.0.borrow().name } +} + +impl<'a> Marked for RCRC<'a> { + fn mark(&self) -> u32 { self.0.borrow().mark.get() } + fn set_mark(&self, mark: u32) { self.0.borrow().mark.set(mark); } +} + +impl<'a> Children<'a> for RCRC<'a> { + fn count_children(&self) -> usize { 2 } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + let children = &self.0.borrow().children; + let child = match index { + 0 => if let Some(child) = children.0 { child } else { return; }, + 1 => if let Some(child) = children.1 { child } else { return; }, + _ => panic!("bad children"), + }; + // println!("S2 {} descending into child {} at index {}", self.name, child.name, index); + child.descend_into_self(context); + } +} +#[derive(Clone)] +struct ARCRCData<'a> { + name: &'static str, + mark: Cell, + children: (Option<&'a ARCRC<'a>>, Option<&'a ARCRC<'a>>), +} +#[derive(Clone)] +struct ARCRC<'a>(Arc>>); + +impl<'a> Named for ARCRC<'a> { + fn new(name: &'static str) -> Self { + ARCRC(Arc::new(RefCell::new(ARCRCData { + name: name, mark: Cell::new(0), children: (None, None), }))) + } + fn name(&self) -> &str { self.0.borrow().name } +} + +impl<'a> Marked for ARCRC<'a> { + fn mark(&self) -> u32 { self.0.borrow().mark.get() } + fn set_mark(&self, mark: u32) { self.0.borrow().mark.set(mark); } +} + +impl<'a> Children<'a> for ARCRC<'a> { + fn count_children(&self) -> usize { 2 } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + let children = &self.0.borrow().children; + match index { + 0 => if let Some(ref child) = children.0 { + child.descend_into_self(context); + }, + 1 => if let Some(ref child) = children.1 { + child.descend_into_self(context); + }, + _ => panic!("bad children!"), + } + } +} + +#[derive(Clone)] +struct ARCMData<'a> { + mark: Cell, + children: (Option<&'a ARCM<'a>>, Option<&'a ARCM<'a>>), +} + +#[derive(Clone)] +struct ARCM<'a>(&'static str, Arc>>); + +impl<'a> Named for ARCM<'a> { + fn new(name: &'static str) -> Self { + ARCM(name, Arc::new(Mutex::new(ARCMData { + mark: Cell::new(0), children: (None, None), }))) + } + fn name(&self) -> &str { self.0 } +} + +impl<'a> Marked for ARCM<'a> { + fn mark(&self) -> u32 { self.1.lock().unwrap().mark.get() } + fn set_mark(&self, mark: u32) { self.1.lock().unwrap().mark.set(mark); } +} + +impl<'a> Children<'a> for ARCM<'a> { + fn count_children(&self) -> usize { 2 } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + let ref children = if let Ok(data) = self.1.try_lock() { + data.children + } else { return; }; + match index { + 0 => if let Some(ref child) = children.0 { + child.descend_into_self(context); + }, + 1 => if let Some(ref child) = children.1 { + child.descend_into_self(context); + }, + _ => panic!("bad children!"), + } + } +} + +#[derive(Clone)] +struct ARCRWData<'a> { + name: &'static str, + mark: Cell, + children: (Option<&'a ARCRW<'a>>, Option<&'a ARCRW<'a>>), +} + +#[derive(Clone)] +struct ARCRW<'a>(Arc>>); + +impl<'a> Named for ARCRW<'a> { + fn new(name: &'static str) -> Self { + ARCRW(Arc::new(RwLock::new(ARCRWData { + name: name, mark: Cell::new(0), children: (None, None), }))) + } + fn name(&self) -> &str { self.0.read().unwrap().name } +} + +impl<'a> Marked for ARCRW<'a> { + fn mark(&self) -> u32 { self.0.read().unwrap().mark.get() } + fn set_mark(&self, mark: u32) { self.0.read().unwrap().mark.set(mark); } +} + +impl<'a> Children<'a> for ARCRW<'a> { + fn count_children(&self) -> usize { 2 } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + let children = &self.0.read().unwrap().children; + match index { + 0 => if let Some(ref child) = children.0 { + child.descend_into_self(context); + }, + 1 => if let Some(ref child) = children.1 { + child.descend_into_self(context); + }, + _ => panic!("bad children!"), + } + } +} + +trait Context { + fn next_index(&mut self, len: usize) -> usize; + fn should_act(&self) -> bool; + fn increase_visited(&mut self); + fn increase_skipped(&mut self); + fn increase_depth(&mut self); + fn decrease_depth(&mut self); +} + +trait PrePost { + fn pre(&mut self, _: &T); + fn post(&mut self, _: &T); + fn hit_limit(&mut self, _: &T); +} + +trait Children<'a> { + fn count_children(&self) -> usize; + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized; + + fn next_child(&self, context: &mut C) + where C: Context + PrePost, Self: Sized + { + let index = context.next_index(self.count_children()); + self.descend_one_child(context, index); + } + + fn descend_into_self(&self, context: &mut C) + where C: Context + PrePost, Self: Sized + { + context.pre(self); + if context.should_act() { + context.increase_visited(); + context.increase_depth(); + self.next_child(context); + context.decrease_depth(); + } else { + context.hit_limit(self); + context.increase_skipped(); + } + context.post(self); + } + + fn descend<'b, C>(&self, c: &Cell>, context: &mut C) + where C: Context + PrePost, Self: Sized + { + if let Some(r) = c.get() { + r.descend_into_self(context); + } + } +} + +impl<'a> Children<'a> for S<'a> { + fn count_children(&self) -> usize { 1 } + fn descend_one_child(&self, context: &mut C, _: usize) + where C: Context + PrePost, Self: Sized { + self.descend(&self.next, context); + } +} + +impl<'a> Children<'a> for S2<'a> { + fn count_children(&self) -> usize { 2 } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + let children = self.next.get(); + let child = match index { + 0 => if let Some(child) = children.0 { child } else { return; }, + 1 => if let Some(child) = children.1 { child } else { return; }, + _ => panic!("bad children"), + }; + // println!("S2 {} descending into child {} at index {}", self.name, child.name, index); + child.descend_into_self(context); + } +} + +impl<'a> Children<'a> for V<'a> { + fn count_children(&self) -> usize { self.contents.len() } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + if let Some(child) = self.contents[index].get() { + child.descend_into_self(context); + } + } +} + +impl<'a> Children<'a> for H<'a> { + fn count_children(&self) -> usize { 1 } + fn descend_one_child(&self, context: &mut C, _: usize) + where C: Context + PrePost, Self: Sized + { + self.descend(&self.next, context); + } +} + +impl<'a> Children<'a> for HM<'a> { + fn count_children(&self) -> usize { + if let Some(m) = self.contents.get() { 2 * m.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + if let Some(ref hm) = self.contents.get() { + if let Some((k, v)) = hm.iter().nth(index / 2) { + [k, v][index % 2].descend_into_self(context); + } + } + } +} + +impl<'a> Children<'a> for VD<'a> { + fn count_children(&self) -> usize { + if let Some(d) = self.contents.get() { d.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost, Self: Sized + { + if let Some(ref vd) = self.contents.get() { + if let Some(r) = vd.iter().nth(index) { + r.descend_into_self(context); + } + } + } +} + +impl<'a> Children<'a> for VM<'a> { + fn count_children(&self) -> usize { + if let Some(m) = self.contents.get() { m.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost> + { + if let Some(ref vd) = self.contents.get() { + if let Some((_idx, r)) = vd.iter().nth(index) { + r.descend_into_self(context); + } + } + } +} + +impl<'a> Children<'a> for LL<'a> { + fn count_children(&self) -> usize { + if let Some(l) = self.contents.get() { l.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost> + { + if let Some(ref ll) = self.contents.get() { + if let Some(r) = ll.iter().nth(index) { + r.descend_into_self(context); + } + } + } +} + +impl<'a> Children<'a> for BH<'a> { + fn count_children(&self) -> usize { + if let Some(h) = self.contents.get() { h.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost> + { + if let Some(ref bh) = self.contents.get() { + if let Some(r) = bh.iter().nth(index) { + r.descend_into_self(context); + } + } + } +} + +impl<'a> Children<'a> for BTM<'a> { + fn count_children(&self) -> usize { + if let Some(m) = self.contents.get() { 2 * m.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost> + { + if let Some(ref bh) = self.contents.get() { + if let Some((k, v)) = bh.iter().nth(index / 2) { + [k, v][index % 2].descend_into_self(context); + } + } + } +} + +impl<'a> Children<'a> for BTS<'a> { + fn count_children(&self) -> usize { + if let Some(s) = self.contents.get() { s.iter().count() } else { 0 } + } + fn descend_one_child(&self, context: &mut C, index: usize) + where C: Context + PrePost> + { + if let Some(ref bh) = self.contents.get() { + if let Some(r) = bh.iter().nth(index) { + r.descend_into_self(context); + } + } + } +} + +#[derive(Copy, Clone)] +struct ContextData { + curr_depth: usize, + max_depth: usize, + visited: usize, + max_visits: usize, + skipped: usize, + curr_mark: u32, + saw_prev_marked: bool, + control_bits: u64, +} + +impl Context for ContextData { + fn next_index(&mut self, len: usize) -> usize { + if len < 2 { return 0; } + let mut pow2 = len.next_power_of_two(); + let _pow2_orig = pow2; + let mut idx = 0; + let mut bits = self.control_bits; + while pow2 > 1 { + idx = (idx << 1) | (bits & 1) as usize; + bits = bits >> 1; + pow2 = pow2 >> 1; + } + idx = idx % len; + // println!("next_index({} [{:b}]) says {}, pre(bits): {:b} post(bits): {:b}", + // len, _pow2_orig, idx, self.control_bits, bits); + self.control_bits = bits; + return idx; + } + fn should_act(&self) -> bool { + self.curr_depth < self.max_depth && self.visited < self.max_visits + } + fn increase_visited(&mut self) { self.visited += 1; } + fn increase_skipped(&mut self) { self.skipped += 1; } + fn increase_depth(&mut self) { self.curr_depth += 1; } + fn decrease_depth(&mut self) { self.curr_depth -= 1; } +} + +impl> PrePost for ContextData { + fn pre(&mut self, t: &T) { + for _ in 0..self.curr_depth { + if PRINT { print!(" "); } + } + if PRINT { println!("prev {}", t.name()); } + if t.mark() == self.curr_mark { + for _ in 0..self.curr_depth { + if PRINT { print!(" "); } + } + if PRINT { println!("(probably previously marked)"); } + self.saw_prev_marked = true; + } + t.set_mark(self.curr_mark); + } + fn post(&mut self, t: &T) { + for _ in 0..self.curr_depth { + if PRINT { print!(" "); } + } + if PRINT { println!("post {}", t.name()); } + } + fn hit_limit(&mut self, t: &T) { + for _ in 0..self.curr_depth { + if PRINT { print!(" "); } + } + if PRINT { println!("LIMIT {}", t.name()); } + } +} diff --git a/tests/ui/drop/dynamic-drop-async.rs b/tests/ui/drop/dynamic-drop-async.rs new file mode 100644 index 000000000..8f1cc6691 --- /dev/null +++ b/tests/ui/drop/dynamic-drop-async.rs @@ -0,0 +1,332 @@ +// Test that values are not leaked in async functions, even in the cases where: +// * Dropping one of the values panics while running the future. +// * The future is dropped at one of its suspend points. +// * Dropping one of the values panics while dropping the future. + +// run-pass +// needs-unwind +// edition:2018 + +#![allow(unused)] + +use std::{ + cell::{Cell, RefCell}, + future::Future, + marker::Unpin, + panic, + pin::Pin, + ptr, + rc::Rc, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, +}; + +struct InjectedFailure; + +struct Defer { + ready: bool, + value: Option, +} + +impl Future for Defer { + type Output = T; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + if self.ready { + Poll::Ready(self.value.take().unwrap()) + } else { + self.ready = true; + Poll::Pending + } + } +} + +/// Allocator tracks the creation and destruction of `Ptr`s. +/// The `failing_op`-th operation will panic. +struct Allocator { + data: RefCell>, + failing_op: usize, + cur_ops: Cell, +} + +impl panic::UnwindSafe for Allocator {} +impl panic::RefUnwindSafe for Allocator {} + +impl Drop for Allocator { + fn drop(&mut self) { + let data = self.data.borrow(); + if data.iter().any(|d| *d) { + panic!("missing free: {:?}", data); + } + } +} + +impl Allocator { + fn new(failing_op: usize) -> Self { + Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) } + } + fn alloc(&self) -> impl Future> + '_ { + self.fallible_operation(); + + let mut data = self.data.borrow_mut(); + + let addr = data.len(); + data.push(true); + Defer { ready: false, value: Some(Ptr(addr, self)) } + } + fn fallible_operation(&self) { + self.cur_ops.set(self.cur_ops.get() + 1); + + if self.cur_ops.get() == self.failing_op { + panic::panic_any(InjectedFailure); + } + } +} + +// Type that tracks whether it was dropped and can panic when it's created or +// destroyed. +struct Ptr<'a>(usize, &'a Allocator); +impl<'a> Drop for Ptr<'a> { + fn drop(&mut self) { + match self.1.data.borrow_mut()[self.0] { + false => panic!("double free at index {:?}", self.0), + ref mut d => *d = false, + } + + self.1.fallible_operation(); + } +} + +async fn dynamic_init(a: Rc, c: bool) { + let _x; + if c { + _x = Some(a.alloc().await); + } +} + +async fn dynamic_drop(a: Rc, c: bool) { + let x = a.alloc().await; + if c { + Some(x) + } else { + None + }; +} + +struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>); +async fn struct_dynamic_drop(a: Rc, c0: bool, c1: bool, c: bool) { + for i in 0..2 { + let x; + let y; + if (c0 && i == 0) || (c1 && i == 1) { + x = (a.alloc().await, a.alloc().await, a.alloc().await); + y = TwoPtrs(a.alloc().await, a.alloc().await); + if c { + drop(x.1); + a.alloc().await; + drop(y.0); + a.alloc().await; + } + } + } +} + +async fn field_assignment(a: Rc, c0: bool) { + let mut x = (TwoPtrs(a.alloc().await, a.alloc().await), a.alloc().await); + + x.1 = a.alloc().await; + x.1 = a.alloc().await; + + let f = (x.0).0; + a.alloc().await; + if c0 { + (x.0).0 = f; + } + a.alloc().await; +} + +async fn assignment(a: Rc, c0: bool, c1: bool) { + let mut _v = a.alloc().await; + let mut _w = a.alloc().await; + if c0 { + drop(_v); + } + _v = _w; + if c1 { + _w = a.alloc().await; + } +} + +async fn array_simple(a: Rc) { + let _x = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await]; +} + +async fn vec_simple(a: Rc) { + let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await]; +} + +async fn mixed_drop_and_nondrop(a: Rc) { + // check that destructor panics handle drop + // and non-drop blocks in the same scope correctly. + // + // Surprisingly enough, this used to not work. + let (x, y, z); + x = a.alloc().await; + y = 5; + z = a.alloc().await; +} + +#[allow(unreachable_code)] +async fn vec_unreachable(a: Rc) { + let _x = vec![a.alloc().await, a.alloc().await, a.alloc().await, return]; +} + +async fn slice_pattern_one_of(a: Rc, i: usize) { + let array = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await]; + let _x = match i { + 0 => { + let [a, ..] = array; + a + } + 1 => { + let [_, a, ..] = array; + a + } + 2 => { + let [_, _, a, _] = array; + a + } + 3 => { + let [_, _, _, a] = array; + a + } + _ => panic!("unmatched"), + }; + a.alloc().await; +} + +async fn subslice_pattern_from_end_with_drop(a: Rc, arg: bool, arg2: bool) { + let arr = [a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await]; + if arg2 { + drop(arr); + return; + } + + if arg { + let [.., _x, _] = arr; + } else { + let [_, _y @ ..] = arr; + } + a.alloc().await; +} + +async fn subslice_pattern_reassign(a: Rc) { + let mut ar = [a.alloc().await, a.alloc().await, a.alloc().await]; + let [_, _, _x] = ar; + ar = [a.alloc().await, a.alloc().await, a.alloc().await]; + let [_, _y @ ..] = ar; + a.alloc().await; +} + +async fn move_ref_pattern(a: Rc) { + let mut tup = (a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await); + let (ref _a, ref mut _b, _c, mut _d) = tup; + a.alloc().await; +} + +fn run_test(cx: &mut Context<'_>, ref f: F) +where + F: Fn(Rc) -> G, + G: Future, +{ + for polls in 0.. { + // Run without any panics to find which operations happen after the + // penultimate `poll`. + let first_alloc = Rc::new(Allocator::new(usize::MAX)); + let mut fut = Box::pin(f(first_alloc.clone())); + let mut ops_before_last_poll = 0; + let mut completed = false; + for _ in 0..polls { + ops_before_last_poll = first_alloc.cur_ops.get(); + if let Poll::Ready(()) = fut.as_mut().poll(cx) { + completed = true; + } + } + drop(fut); + + // Start at `ops_before_last_poll` so that we will always be able to + // `poll` the expected number of times. + for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() { + let alloc = Rc::new(Allocator::new(failing_op + 1)); + let f = &f; + let cx = &mut *cx; + let result = panic::catch_unwind(panic::AssertUnwindSafe(move || { + let mut fut = Box::pin(f(alloc)); + for _ in 0..polls { + let _ = fut.as_mut().poll(cx); + } + drop(fut); + })); + match result { + Ok(..) => panic!("test executed more ops on first call"), + Err(e) => { + if e.downcast_ref::().is_none() { + panic::resume_unwind(e); + } + } + } + } + + if completed { + break; + } + } +} + +fn clone_waker(data: *const ()) -> RawWaker { + RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop)) +} + +fn main() { + let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) }; + let context = &mut Context::from_waker(&waker); + + run_test(context, |a| dynamic_init(a, false)); + run_test(context, |a| dynamic_init(a, true)); + run_test(context, |a| dynamic_drop(a, false)); + run_test(context, |a| dynamic_drop(a, true)); + + run_test(context, |a| assignment(a, false, false)); + run_test(context, |a| assignment(a, false, true)); + run_test(context, |a| assignment(a, true, false)); + run_test(context, |a| assignment(a, true, true)); + + run_test(context, |a| array_simple(a)); + run_test(context, |a| vec_simple(a)); + run_test(context, |a| vec_unreachable(a)); + + run_test(context, |a| struct_dynamic_drop(a, false, false, false)); + run_test(context, |a| struct_dynamic_drop(a, false, false, true)); + run_test(context, |a| struct_dynamic_drop(a, false, true, false)); + run_test(context, |a| struct_dynamic_drop(a, false, true, true)); + run_test(context, |a| struct_dynamic_drop(a, true, false, false)); + run_test(context, |a| struct_dynamic_drop(a, true, false, true)); + run_test(context, |a| struct_dynamic_drop(a, true, true, false)); + run_test(context, |a| struct_dynamic_drop(a, true, true, true)); + + run_test(context, |a| field_assignment(a, false)); + run_test(context, |a| field_assignment(a, true)); + + run_test(context, |a| mixed_drop_and_nondrop(a)); + + run_test(context, |a| slice_pattern_one_of(a, 0)); + run_test(context, |a| slice_pattern_one_of(a, 1)); + run_test(context, |a| slice_pattern_one_of(a, 2)); + run_test(context, |a| slice_pattern_one_of(a, 3)); + + run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test(context, |a| subslice_pattern_reassign(a)); + + run_test(context, |a| move_ref_pattern(a)); +} diff --git a/tests/ui/drop/dynamic-drop.rs b/tests/ui/drop/dynamic-drop.rs new file mode 100644 index 000000000..9e51d3ada --- /dev/null +++ b/tests/ui/drop/dynamic-drop.rs @@ -0,0 +1,520 @@ +// run-pass +// needs-unwind + +#![feature(generators, generator_trait)] + +#![allow(unused_assignments)] +#![allow(unused_variables)] + +use std::cell::{Cell, RefCell}; +use std::mem::ManuallyDrop; +use std::ops::Generator; +use std::panic; +use std::pin::Pin; + +struct InjectedFailure; + +struct Allocator { + data: RefCell>, + failing_op: usize, + cur_ops: Cell, +} + +impl panic::UnwindSafe for Allocator {} +impl panic::RefUnwindSafe for Allocator {} + +impl Drop for Allocator { + fn drop(&mut self) { + let data = self.data.borrow(); + if data.iter().any(|d| *d) { + panic!("missing free: {:?}", data); + } + } +} + +impl Allocator { + fn new(failing_op: usize) -> Self { + Allocator { + failing_op: failing_op, + cur_ops: Cell::new(0), + data: RefCell::new(vec![]) + } + } + fn alloc(&self) -> Ptr<'_> { + self.cur_ops.set(self.cur_ops.get() + 1); + + if self.cur_ops.get() == self.failing_op { + panic::panic_any(InjectedFailure); + } + + let mut data = self.data.borrow_mut(); + let addr = data.len(); + data.push(true); + Ptr(addr, self) + } + // FIXME(#47949) Any use of this indicates a bug in rustc: we should never + // be leaking values in the cases here. + // + // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the + // `failing_op` is in the list of exception. + fn alloc_leaked(&self, exceptions: Vec) -> Ptr<'_> { + let ptr = self.alloc(); + + if exceptions.iter().any(|operation| *operation == self.failing_op) { + let mut data = self.data.borrow_mut(); + data[ptr.0] = false; + } + ptr + } +} + +struct Ptr<'a>(usize, &'a Allocator); +impl<'a> Drop for Ptr<'a> { + fn drop(&mut self) { + match self.1.data.borrow_mut()[self.0] { + false => { + panic!("double free at index {:?}", self.0) + } + ref mut d => *d = false + } + + self.1.cur_ops.set(self.1.cur_ops.get()+1); + + if self.1.cur_ops.get() == self.1.failing_op { + panic::panic_any(InjectedFailure); + } + } +} + +fn dynamic_init(a: &Allocator, c: bool) { + let _x; + if c { + _x = Some(a.alloc()); + } +} + +fn dynamic_drop(a: &Allocator, c: bool) { + let x = a.alloc(); + if c { + Some(x) + } else { + None + }; +} + +struct TwoPtrs<'a>(Ptr<'a>, #[allow(unused_tuple_struct_fields)] Ptr<'a>); +fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) { + for i in 0..2 { + let x; + let y; + if (c0 && i == 0) || (c1 && i == 1) { + x = (a.alloc(), a.alloc(), a.alloc()); + y = TwoPtrs(a.alloc(), a.alloc()); + if c { + drop(x.1); + drop(y.0); + } + } + } +} + +fn field_assignment(a: &Allocator, c0: bool) { + let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc()); + + x.1 = a.alloc(); + x.1 = a.alloc(); + + let f = (x.0).0; + if c0 { + (x.0).0 = f; + } +} + +fn assignment2(a: &Allocator, c0: bool, c1: bool) { + let mut _v = a.alloc(); + let mut _w = a.alloc(); + if c0 { + drop(_v); + } + _v = _w; + if c1 { + _w = a.alloc(); + } +} + +fn assignment1(a: &Allocator, c0: bool) { + let mut _v = a.alloc(); + let mut _w = a.alloc(); + if c0 { + drop(_v); + } + _v = _w; +} + +union Boxy { + a: ManuallyDrop, + b: ManuallyDrop, +} + +fn union1(a: &Allocator) { + unsafe { + let mut u = Boxy { a: ManuallyDrop::new(a.alloc()) }; + *u.b = a.alloc(); // drops first alloc + drop(ManuallyDrop::into_inner(u.a)); + } +} + +fn array_simple(a: &Allocator) { + let _x = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; +} + +fn vec_simple(a: &Allocator) { + let _x = vec![a.alloc(), a.alloc(), a.alloc(), a.alloc()]; +} + +fn generator(a: &Allocator, run_count: usize) { + assert!(run_count < 4); + + let mut gen = || { + (a.alloc(), + yield a.alloc(), + a.alloc(), + yield a.alloc() + ); + }; + for _ in 0..run_count { + Pin::new(&mut gen).resume(()); + } +} + +fn mixed_drop_and_nondrop(a: &Allocator) { + // check that destructor panics handle drop + // and non-drop blocks in the same scope correctly. + // + // Surprisingly enough, this used to not work. + let (x, y, z); + x = a.alloc(); + y = 5; + z = a.alloc(); +} + +#[allow(unreachable_code)] +fn vec_unreachable(a: &Allocator) { + let _x = vec![a.alloc(), a.alloc(), a.alloc(), return]; +} + +fn slice_pattern_first(a: &Allocator) { + let[_x, ..] = [a.alloc(), a.alloc(), a.alloc()]; +} + +fn slice_pattern_middle(a: &Allocator) { + let[_, _x, _] = [a.alloc(), a.alloc(), a.alloc()]; +} + +fn slice_pattern_two(a: &Allocator) { + let[_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; +} + +fn slice_pattern_last(a: &Allocator) { + let[.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; +} + +fn slice_pattern_one_of(a: &Allocator, i: usize) { + let array = [a.alloc(), a.alloc(), a.alloc(), a.alloc()]; + let _x = match i { + 0 => { let [a, ..] = array; a } + 1 => { let [_, a, ..] = array; a } + 2 => { let [_, _, a, _] = array; a } + 3 => { let [_, _, _, a] = array; a } + _ => panic!("unmatched"), + }; +} + +fn subslice_pattern_from_end(a: &Allocator, arg: bool) { + let a = [a.alloc(), a.alloc(), a.alloc()]; + if arg { + let[.., _x, _] = a; + } else { + let[_, _y @ ..] = a; + } +} + +fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) { + let a = [a.alloc(), a.alloc(), a.alloc(), a.alloc(), a.alloc()]; + if arg2 { + drop(a); + return; + } + + if arg { + let[.., _x, _] = a; + } else { + let[_, _y @ ..] = a; + } +} + +fn slice_pattern_reassign(a: &Allocator) { + let mut ar = [a.alloc(), a.alloc()]; + let[_, _x] = ar; + ar = [a.alloc(), a.alloc()]; + let[.., _y] = ar; +} + +fn subslice_pattern_reassign(a: &Allocator) { + let mut ar = [a.alloc(), a.alloc(), a.alloc()]; + let[_, _, _x] = ar; + ar = [a.alloc(), a.alloc(), a.alloc()]; + let[_, _y @ ..] = ar; +} + +fn index_field_mixed_ends(a: &Allocator) { + let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())]; + let[(_x, _), ..] = ar; + let[(_, _y), _] = ar; + let[_, (_, _w)] = ar; + let[.., (_z, _)] = ar; +} + +fn subslice_mixed_min_lengths(a: &Allocator, c: i32) { + let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())]; + match c { + 0 => { let[_x, ..] = ar; } + 1 => { let[_x, _, ..] = ar; } + 2 => { let[_x, _] = ar; } + 3 => { let[(_x, _), _, ..] = ar; } + 4 => { let[.., (_x, _)] = ar; } + 5 => { let[.., (_x, _), _] = ar; } + 6 => { let [_y @ ..] = ar; } + _ => { let [_y @ .., _] = ar; } + } +} + +fn bindings_after_at_dynamic_init_move(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + let _x; + + if let bar @ Some(_) = foo { + _x = bar; + } +} + +fn bindings_after_at_dynamic_init_ref(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + let _x; + + if let bar @ Some(_baz) = &foo { + _x = bar; + } +} + +fn bindings_after_at_dynamic_drop_move(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + + if let bar @ Some(_) = foo { + bar + } else { + None + }; +} + +fn bindings_after_at_dynamic_drop_ref(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + + if let bar @ Some(_baz) = &foo { + bar + } else { + &None + }; +} + +fn move_ref_pattern(a: &Allocator) { + let mut tup = (a.alloc(), a.alloc(), a.alloc(), a.alloc()); + let (ref _a, ref mut _b, _c, mut _d) = tup; +} + +fn panic_after_return(a: &Allocator) -> Ptr<'_> { + // Panic in the drop of `p` or `q` can leak + let exceptions = vec![8, 9]; + a.alloc(); + let p = a.alloc(); + { + a.alloc(); + let p = a.alloc(); + // FIXME (#47949) We leak values when we panic in a destructor after + // evaluating an expression with `rustc_mir::build::Builder::into`. + a.alloc_leaked(exceptions) + } +} + +fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> { + // Panic in the drop of `p` or `q` can leak + let exceptions = vec![8, 9]; + a.alloc(); + let p = a.alloc(); + { + a.alloc(); + let q = a.alloc(); + // FIXME (#47949) + return a.alloc_leaked(exceptions); + } +} + +fn panic_after_init(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; + a.alloc(); + let p = a.alloc(); + let q = { + a.alloc(); + let r = a.alloc(); + // FIXME (#47949) + a.alloc_leaked(exceptions) + }; +} + +fn panic_after_init_temp(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; + a.alloc(); + let p = a.alloc(); + { + a.alloc(); + let r = a.alloc(); + // FIXME (#47949) + a.alloc_leaked(exceptions) + }; +} + +fn panic_after_init_by_loop(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; + a.alloc(); + let p = a.alloc(); + let q = loop { + a.alloc(); + let r = a.alloc(); + // FIXME (#47949) + break a.alloc_leaked(exceptions); + }; +} + +fn run_test(mut f: F) + where F: FnMut(&Allocator) +{ + let first_alloc = Allocator::new(usize::MAX); + f(&first_alloc); + + for failing_op in 1..first_alloc.cur_ops.get()+1 { + let alloc = Allocator::new(failing_op); + let alloc = &alloc; + let f = panic::AssertUnwindSafe(&mut f); + let result = panic::catch_unwind(move || { + f.0(alloc); + }); + match result { + Ok(..) => panic!("test executed {} ops but now {}", + first_alloc.cur_ops.get(), alloc.cur_ops.get()), + Err(e) => { + if e.downcast_ref::().is_none() { + panic::resume_unwind(e); + } + } + } + } +} + +fn run_test_nopanic(mut f: F) + where F: FnMut(&Allocator) +{ + let first_alloc = Allocator::new(usize::MAX); + f(&first_alloc); +} + +fn main() { + run_test(|a| dynamic_init(a, false)); + run_test(|a| dynamic_init(a, true)); + run_test(|a| dynamic_drop(a, false)); + run_test(|a| dynamic_drop(a, true)); + + run_test(|a| assignment2(a, false, false)); + run_test(|a| assignment2(a, false, true)); + run_test(|a| assignment2(a, true, false)); + run_test(|a| assignment2(a, true, true)); + + run_test(|a| assignment1(a, false)); + run_test(|a| assignment1(a, true)); + + run_test(|a| array_simple(a)); + run_test(|a| vec_simple(a)); + run_test(|a| vec_unreachable(a)); + + run_test(|a| struct_dynamic_drop(a, false, false, false)); + run_test(|a| struct_dynamic_drop(a, false, false, true)); + run_test(|a| struct_dynamic_drop(a, false, true, false)); + run_test(|a| struct_dynamic_drop(a, false, true, true)); + run_test(|a| struct_dynamic_drop(a, true, false, false)); + run_test(|a| struct_dynamic_drop(a, true, false, true)); + run_test(|a| struct_dynamic_drop(a, true, true, false)); + run_test(|a| struct_dynamic_drop(a, true, true, true)); + + run_test(|a| field_assignment(a, false)); + run_test(|a| field_assignment(a, true)); + + run_test(|a| generator(a, 0)); + run_test(|a| generator(a, 1)); + run_test(|a| generator(a, 2)); + run_test(|a| generator(a, 3)); + + run_test(|a| mixed_drop_and_nondrop(a)); + + run_test(|a| slice_pattern_first(a)); + run_test(|a| slice_pattern_middle(a)); + run_test(|a| slice_pattern_two(a)); + run_test(|a| slice_pattern_last(a)); + run_test(|a| slice_pattern_one_of(a, 0)); + run_test(|a| slice_pattern_one_of(a, 1)); + run_test(|a| slice_pattern_one_of(a, 2)); + run_test(|a| slice_pattern_one_of(a, 3)); + + run_test(|a| subslice_pattern_from_end(a, true)); + run_test(|a| subslice_pattern_from_end(a, false)); + run_test(|a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test(|a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test(|a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test(|a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test(|a| slice_pattern_reassign(a)); + run_test(|a| subslice_pattern_reassign(a)); + + run_test(|a| index_field_mixed_ends(a)); + run_test(|a| subslice_mixed_min_lengths(a, 0)); + run_test(|a| subslice_mixed_min_lengths(a, 1)); + run_test(|a| subslice_mixed_min_lengths(a, 2)); + run_test(|a| subslice_mixed_min_lengths(a, 3)); + run_test(|a| subslice_mixed_min_lengths(a, 4)); + run_test(|a| subslice_mixed_min_lengths(a, 5)); + run_test(|a| subslice_mixed_min_lengths(a, 6)); + run_test(|a| subslice_mixed_min_lengths(a, 7)); + + run_test(|a| move_ref_pattern(a)); + + run_test(|a| { + panic_after_return(a); + }); + run_test(|a| { + panic_after_return_expr(a); + }); + run_test(|a| panic_after_init(a)); + run_test(|a| panic_after_init_temp(a)); + run_test(|a| panic_after_init_by_loop(a)); + + run_test(|a| bindings_after_at_dynamic_init_move(a, true)); + run_test(|a| bindings_after_at_dynamic_init_move(a, false)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, false)); + + run_test_nopanic(|a| union1(a)); +} diff --git a/tests/ui/drop/issue-100276.rs b/tests/ui/drop/issue-100276.rs new file mode 100644 index 000000000..6401a8d14 --- /dev/null +++ b/tests/ui/drop/issue-100276.rs @@ -0,0 +1,12 @@ +// check-pass +// compile-flags: -Z validate-mir +#![feature(let_chains)] + +fn let_chains(entry: std::io::Result) { + if let Ok(entry) = entry + && let Some(s) = entry.file_name().to_str() + && s.contains("") + {} +} + +fn main() {} diff --git a/tests/ui/drop/issue-10028.rs b/tests/ui/drop/issue-10028.rs new file mode 100644 index 000000000..1692470e8 --- /dev/null +++ b/tests/ui/drop/issue-10028.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-10028.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_10028 as issue10028; + +use issue10028::ZeroLengthThingWithDestructor; + +struct Foo { + zero_length_thing: ZeroLengthThingWithDestructor +} + +fn make_foo() -> Foo { + Foo { zero_length_thing: ZeroLengthThingWithDestructor::new() } +} + +fn main() { + let _f:Foo = make_foo(); +} diff --git a/tests/ui/drop/issue-103107.rs b/tests/ui/drop/issue-103107.rs new file mode 100644 index 000000000..5f4475956 --- /dev/null +++ b/tests/ui/drop/issue-103107.rs @@ -0,0 +1,37 @@ +// check-pass +// compile-flags: -Z validate-mir + +struct Foo<'a>(&'a mut u32); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + *self.0 = 0; + } +} + +fn and() { + let mut foo = 0; + // This used to compile also before the fix + if true && *Foo(&mut foo).0 == 0 && ({ foo = 0; true}) {} + + // This used to fail before the fix + if *Foo(&mut foo).0 == 0 && ({ foo = 0; true}) {} + + println!("{foo}"); +} + +fn or() { + let mut foo = 0; + // This used to compile also before the fix + if false || *Foo(&mut foo).0 == 1 || ({ foo = 0; true}) {} + + // This used to fail before the fix + if *Foo(&mut foo).0 == 1 || ({ foo = 0; true}) {} + + println!("{foo}"); +} + +fn main() { + and(); + or(); +} diff --git a/tests/ui/drop/issue-17718-const-destructors.rs b/tests/ui/drop/issue-17718-const-destructors.rs new file mode 100644 index 000000000..c9a729c7b --- /dev/null +++ b/tests/ui/drop/issue-17718-const-destructors.rs @@ -0,0 +1,10 @@ +// check-pass +#![allow(dead_code)] +struct A; +impl Drop for A { + fn drop(&mut self) {} +} + +const FOO: A = A; + +fn main() {} diff --git a/tests/ui/drop/issue-21486.rs b/tests/ui/drop/issue-21486.rs new file mode 100644 index 000000000..46d6ccd56 --- /dev/null +++ b/tests/ui/drop/issue-21486.rs @@ -0,0 +1,77 @@ +// run-pass +#![allow(unreachable_code)] +// Issue #21486: Make sure that all structures are dropped, even when +// created via FRU and control-flow breaks in the middle of +// construction. + +use std::sync::atomic::{Ordering, AtomicUsize}; + +#[derive(Debug)] +struct Noisy(u8); +impl Drop for Noisy { + fn drop(&mut self) { + // println!("splat #{}", self.0); + event(self.0); + } +} + +#[allow(dead_code)] +#[derive(Debug)] +struct Foo { n0: Noisy, n1: Noisy } +impl Foo { + fn vals(&self) -> (u8, u8) { (self.n0.0, self.n1.0) } +} + +fn leak_1_ret() -> Foo { + let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) }; + Foo { n0: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, + .._old_foo + }; +} + +fn leak_2_ret() -> Foo { + let _old_foo = Foo { n0: Noisy(1), n1: Noisy(2) }; + Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, + .._old_foo + }; +} + +// In this case, the control flow break happens *before* we construct +// `Foo(Noisy(1),Noisy(2))`, so there should be no record of it in the +// event log. +fn leak_3_ret() -> Foo { + let _old_foo = || Foo { n0: Noisy(1), n1: Noisy(2) }; + Foo { n1: { return Foo { n0: Noisy(3), n1: Noisy(4) } }, + .._old_foo() + }; +} + +pub fn main() { + reset_log(); + assert_eq!(leak_1_ret().vals(), (3,4)); + assert_eq!(0x01_02_03_04, event_log()); + + reset_log(); + assert_eq!(leak_2_ret().vals(), (3,4)); + assert_eq!(0x01_02_03_04, event_log()); + + reset_log(); + assert_eq!(leak_3_ret().vals(), (3,4)); + assert_eq!(0x03_04, event_log()); +} + +static LOG: AtomicUsize = AtomicUsize::new(0); + +fn reset_log() { + LOG.store(0, Ordering::SeqCst); +} + +fn event_log() -> usize { + LOG.load(Ordering::SeqCst) +} + +fn event(tag: u8) { + let old_log = LOG.load(Ordering::SeqCst); + let new_log = (old_log << 8) + tag as usize; + LOG.store(new_log, Ordering::SeqCst); +} diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs new file mode 100644 index 000000000..a99f260dd --- /dev/null +++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs @@ -0,0 +1,162 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// This test is ensuring that parameters are indeed dropped after +// temporaries in a fn body. + +use std::cell::RefCell; + +use self::d::D; + +pub fn main() { + let log = RefCell::new(vec![]); + d::println("created empty log"); + test(&log); + + assert_eq!(&log.borrow()[..], + [ + // created empty log + // +-- Make D(da_0, 0) + // | +-- Make D(de_1, 1) + // | | calling foo + // | | entered foo + // | | +-- Make D(de_2, 2) + // | | | +-- Make D(da_1, 3) + // | | | | +-- Make D(de_3, 4) + // | | | | | +-- Make D(de_4, 5) + 3, // | | | +-- Drop D(da_1, 3) + // | | | | | + 4, // | | | +-- Drop D(de_3, 4) + // | | | | + // | | | | eval tail of foo + // | | | +-- Make D(de_5, 6) + // | | | | +-- Make D(de_6, 7) + 5, // | | | | | +-- Drop D(de_4, 5) + // | | | | | + 2, // | | +-- Drop D(de_2, 2) + // | | | | + 6, // | | +-- Drop D(de_5, 6) + // | | | + 1, // | +-- Drop D(de_1, 1) + // | | + 0, // +-- Drop D(da_0, 0) + // | + // | result D(de_6, 7) + 7 // +-- Drop D(de_6, 7) + + ]); +} + +fn test<'a>(log: d::Log<'a>) { + let da = D::new("da", 0, log); + let de = D::new("de", 1, log); + d::println("calling foo"); + let result = foo(da, de); + d::println(&format!("result {}", result)); +} + +fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> { + d::println("entered foo"); + let de2 = de1.incr(); // creates D(de_2, 2) + let de4 = { + let _da1 = da0.incr(); // creates D(da_1, 3) + de2.incr().incr() // creates D(de_3, 4) and D(de_4, 5) + }; + d::println("eval tail of foo"); + de4.incr().incr() // creates D(de_5, 6) and D(de_6, 7) +} + +// This module provides simultaneous printouts of the dynamic extents +// of all of the D values, in addition to logging the order that each +// is dropped. + +const PREF_INDENT: u32 = 16; + +pub mod d { + #![allow(unused_parens)] + use std::fmt; + use std::mem; + use std::cell::RefCell; + + static mut counter: u32 = 0; + static mut trails: u64 = 0; + + pub type Log<'a> = &'a RefCell>; + + pub fn current_width() -> u32 { + unsafe { max_width() - trails.leading_zeros() } + } + + pub fn max_width() -> u32 { + unsafe { + (mem::size_of_val(&trails)*8) as u32 + } + } + + pub fn indent_println(my_trails: u32, s: &str) { + let mut indent: String = String::new(); + for i in 0..my_trails { + unsafe { + if trails & (1 << i) != 0 { + indent = indent + "| "; + } else { + indent = indent + " "; + } + } + } + println!("{}{}", indent, s); + } + + pub fn println(s: &str) { + indent_println(super::PREF_INDENT, s); + } + + fn first_avail() -> u32 { + unsafe { + for i in 0..64 { + if trails & (1 << i) == 0 { + return i; + } + } + } + panic!("exhausted trails"); + } + + pub struct D<'a> { + name: &'static str, i: u32, uid: u32, trail: u32, log: Log<'a> + } + + impl<'a> fmt::Display for D<'a> { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + write!(w, "D({}_{}, {})", self.name, self.i, self.uid) + } + } + + impl<'a> D<'a> { + pub fn new(name: &'static str, i: u32, log: Log<'a>) -> D<'a> { + unsafe { + let trail = first_avail(); + let ctr = counter; + counter += 1; + trails |= (1 << trail); + let ret = D { + name: name, i: i, log: log, uid: ctr, trail: trail + }; + indent_println(trail, &format!("+-- Make {}", ret)); + ret + } + } + pub fn incr(&self) -> D<'a> { + D::new(self.name, self.i + 1, self.log) + } + } + + impl<'a> Drop for D<'a> { + fn drop(&mut self) { + unsafe { trails &= !(1 << self.trail); }; + self.log.borrow_mut().push(self.uid); + indent_println(self.trail, &format!("+-- Drop {}", self)); + indent_println(::PREF_INDENT, ""); + } + } +} diff --git a/tests/ui/drop/issue-2734.rs b/tests/ui/drop/issue-2734.rs new file mode 100644 index 000000000..df4f394dc --- /dev/null +++ b/tests/ui/drop/issue-2734.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +trait hax { + fn dummy(&self) { } +} +impl hax for A { } + +fn perform_hax(x: Box) -> Box { + Box::new(x) as Box +} + +fn deadcode() { + perform_hax(Box::new("deadcode".to_string())); +} + +pub fn main() { + let _ = perform_hax(Box::new(42)); +} diff --git a/tests/ui/drop/issue-30018-nopanic.rs b/tests/ui/drop/issue-30018-nopanic.rs new file mode 100644 index 000000000..291bab273 --- /dev/null +++ b/tests/ui/drop/issue-30018-nopanic.rs @@ -0,0 +1,103 @@ +// run-pass +#![allow(unreachable_code)] +// More thorough regression test for Issues #30018 and #30822. This +// attempts to explore different ways that array element construction +// (for both scratch arrays and non-scratch ones) interacts with +// breaks in the control-flow, in terms of the order of evaluation of +// the destructors (which may change; see RFC Issue 744) and the +// number of times that the destructor evaluates for each value (which +// should never exceed 1; this latter case is what #30822 is about). + +use std::cell::RefCell; + +struct D<'a>(&'a RefCell>, i32); + +impl<'a> Drop for D<'a> { + fn drop(&mut self) { + println!("Dropping D({})", self.1); + (self.0).borrow_mut().push(self.1); + } +} + +fn main() { + println!("Start"); + break_during_elem(); + break_after_whole(); + println!("Finis"); +} + +fn break_during_elem() { + let log = &RefCell::new(Vec::new()); + + // CASE 1: Fixed-size array itself is stored in _r slot. + loop { + let _r = [D(log, 10), + D(log, 11), + { D(log, 12); break; }, + D(log, 13)]; + } + assert_eq!(&log.borrow()[..], &[12, 11, 10]); + log.borrow_mut().clear(); + + // CASE 2: Slice (borrow of array) is stored in _r slot. + // This is the case that is actually being reported in #30018. + loop { + let _r = &[D(log, 20), + D(log, 21), + { D(log, 22); break; }, + D(log, 23)]; + } + assert_eq!(&log.borrow()[..], &[22, 21, 20]); + log.borrow_mut().clear(); + + // CASE 3: (Borrow of) slice-index of array is stored in _r slot. + loop { + let _r = &[D(log, 30), + D(log, 31), + { D(log, 32); break; }, + D(log, 33)][..]; + } + assert_eq!(&log.borrow()[..], &[32, 31, 30]); + log.borrow_mut().clear(); +} + +// The purpose of these functions is to test what happens when we +// panic after an array has been constructed in its entirety. +// +// It is meant to act as proof that we still need to continue +// scheduling the destruction of an array even after we've scheduling +// drop for its elements during construction; the latter is tested by +// `fn break_during_elem()`. +fn break_after_whole() { + let log = &RefCell::new(Vec::new()); + + // CASE 1: Fixed-size array itself is stored in _r slot. + loop { + let _r = [D(log, 10), + D(log, 11), + D(log, 12)]; + break; + } + assert_eq!(&log.borrow()[..], &[10, 11, 12]); + log.borrow_mut().clear(); + + // CASE 2: Slice (borrow of array) is stored in _r slot. + loop { + let _r = &[D(log, 20), + D(log, 21), + D(log, 22)]; + break; + } + assert_eq!(&log.borrow()[..], &[20, 21, 22]); + log.borrow_mut().clear(); + + // CASE 3: (Borrow of) slice-index of array is stored in _r slot. + loop { + let _r = &[D(log, 30), + D(log, 31), + D(log, 32)][..]; + break; + } + assert_eq!(&log.borrow()[..], &[30, 31, 32]); + log.borrow_mut().clear(); +} diff --git a/tests/ui/drop/issue-35546.rs b/tests/ui/drop/issue-35546.rs new file mode 100644 index 000000000..004679a62 --- /dev/null +++ b/tests/ui/drop/issue-35546.rs @@ -0,0 +1,20 @@ +// build-pass +#![allow(dead_code)] +// Regression test for #35546. Check that we are able to codegen +// this. Before we had problems because of the drop glue signature +// around dropping a trait object (specifically, when dropping the +// `value` field of `Node`). + +struct Node { + next: Option>>, + value: T, +} + +fn clear(head: &mut Option>>) { + match head.take() { + Some(node) => *head = node.next, + None => (), + } +} + +fn main() {} diff --git a/tests/ui/drop/issue-48962.rs b/tests/ui/drop/issue-48962.rs new file mode 100644 index 000000000..80d815379 --- /dev/null +++ b/tests/ui/drop/issue-48962.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(unused_must_use)] +// Test that we are able to reinitialize box with moved referent +static mut ORDER: [usize; 3] = [0, 0, 0]; +static mut INDEX: usize = 0; + +struct Dropee (usize); + +impl Drop for Dropee { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = self.0; + INDEX = INDEX + 1; + } + } +} + +fn add_sentintel() { + unsafe { + ORDER[INDEX] = 2; + INDEX = INDEX + 1; + } +} + +fn main() { + let mut x = Box::new(Dropee(1)); + *x; // move out from `*x` + add_sentintel(); + *x = Dropee(3); // re-initialize `*x` + {x}; // drop value + unsafe { + assert_eq!(ORDER, [1, 2, 3]); + } +} diff --git a/tests/ui/drop/issue-90752-raw-ptr-shenanigans.rs b/tests/ui/drop/issue-90752-raw-ptr-shenanigans.rs new file mode 100644 index 000000000..4e67b3594 --- /dev/null +++ b/tests/ui/drop/issue-90752-raw-ptr-shenanigans.rs @@ -0,0 +1,41 @@ +// run-pass + +use std::cell::RefCell; + +struct S<'a>(i32, &'a RefCell>); + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { + self.1.borrow_mut().push(self.0); + } +} + +fn test(drops: &RefCell>) { + let mut foo = None; + let pfoo: *mut _ = &mut foo; + + match foo { + None => (), + _ => return, + } + + // Both S(0) and S(1) should be dropped, but aren't. + unsafe { *pfoo = Some((S(0, drops), S(1, drops))); } + + match foo { + Some((_x, _)) => {} + _ => {} + } +} + +fn main() { + let drops = RefCell::new(Vec::new()); + test(&drops); + + // Ideally, we want this... + //assert_eq!(*drops.borrow(), &[0, 1]); + + // But the delayed access through the raw pointer confuses drop elaboration, + // causing S(1) to be leaked. + assert_eq!(*drops.borrow(), &[0]); +} diff --git a/tests/ui/drop/issue-90752.rs b/tests/ui/drop/issue-90752.rs new file mode 100644 index 000000000..4395e45e7 --- /dev/null +++ b/tests/ui/drop/issue-90752.rs @@ -0,0 +1,32 @@ +// run-pass + +use std::cell::RefCell; + +struct S<'a>(i32, &'a RefCell>); + +impl<'a> Drop for S<'a> { + fn drop(&mut self) { + self.1.borrow_mut().push(self.0); + } +} + +fn test(drops: &RefCell>) { + let mut foo = None; + match foo { + None => (), + _ => return, + } + + *(&mut foo) = Some((S(0, drops), S(1, drops))); // Both S(0) and S(1) should be dropped + + match foo { + Some((_x, _)) => {} + _ => {} + } +} + +fn main() { + let drops = RefCell::new(Vec::new()); + test(&drops); + assert_eq!(*drops.borrow(), &[0, 1]); +} diff --git a/tests/ui/drop/no-drop-flag-size.rs b/tests/ui/drop/no-drop-flag-size.rs new file mode 100644 index 000000000..103e70ef6 --- /dev/null +++ b/tests/ui/drop/no-drop-flag-size.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +use std::mem::size_of; + +struct Test { + a: T +} + +impl Drop for Test { + fn drop(&mut self) { } +} + +pub fn main() { + assert_eq!(size_of::(), size_of::>()); +} diff --git a/tests/ui/drop/nondrop-cycle.rs b/tests/ui/drop/nondrop-cycle.rs new file mode 100644 index 000000000..29070f917 --- /dev/null +++ b/tests/ui/drop/nondrop-cycle.rs @@ -0,0 +1,31 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::cell::Cell; + +struct C<'a> { + p: Cell>>, +} + +impl<'a> C<'a> { + fn new() -> C<'a> { C { p: Cell::new(None) } } +} + +fn f1() { + let (c1, c2) = (C::new(), C::new()); + c1.p.set(Some(&c2)); + c2.p.set(Some(&c1)); +} + +fn f2() { + let (c1, c2); + c1 = C::new(); + c2 = C::new(); + c1.p.set(Some(&c2)); + c2.p.set(Some(&c1)); +} + +fn main() { + f1(); + f2(); +} diff --git a/tests/ui/drop/repeat-drop-2.rs b/tests/ui/drop/repeat-drop-2.rs new file mode 100644 index 000000000..3cfacea5e --- /dev/null +++ b/tests/ui/drop/repeat-drop-2.rs @@ -0,0 +1,15 @@ +fn borrowck_catch() { + let foo = String::new(); + let _bar = foo; + let _baz = [foo; 0]; //~ ERROR use of moved value: `foo` [E0382] +} + +const _: [String; 0] = [String::new(); 0]; +//~^ ERROR destructor of `String` cannot be evaluated at compile-time [E0493] + +fn must_be_init() { + let x: u8; + let _ = [x; 0]; //~ ERROR E0381 +} + +fn main() {} diff --git a/tests/ui/drop/repeat-drop-2.stderr b/tests/ui/drop/repeat-drop-2.stderr new file mode 100644 index 000000000..f030228f7 --- /dev/null +++ b/tests/ui/drop/repeat-drop-2.stderr @@ -0,0 +1,41 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/repeat-drop-2.rs:4:17 + | +LL | let foo = String::new(); + | --- move occurs because `foo` has type `String`, which does not implement the `Copy` trait +LL | let _bar = foo; + | --- value moved here +LL | let _baz = [foo; 0]; + | ^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _bar = foo.clone(); + | ++++++++ + +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/repeat-drop-2.rs:7:25 + | +LL | const _: [String; 0] = [String::new(); 0]; + | -^^^^^^^^^^^^^---- + | || + | |the destructor for this type cannot be evaluated in constants + | value is dropped here + +error[E0381]: used binding `x` isn't initialized + --> $DIR/repeat-drop-2.rs:12:14 + | +LL | let x: u8; + | - binding declared here but left uninitialized +LL | let _ = [x; 0]; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: u8 = 0; + | +++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0381, E0382, E0493. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/drop/repeat-drop.rs b/tests/ui/drop/repeat-drop.rs new file mode 100644 index 000000000..8fd46ecaf --- /dev/null +++ b/tests/ui/drop/repeat-drop.rs @@ -0,0 +1,118 @@ +// run-pass +// needs-unwind + +static mut CHECK: usize = 0; + +struct DropChecker(usize); + +impl Drop for DropChecker { + fn drop(&mut self) { + unsafe { + if CHECK != self.0 - 1 { + panic!("Found {}, should have found {}", CHECK, self.0 - 1); + } + CHECK = self.0; + } + } +} + +macro_rules! check_drops { + ($l:literal) => { + unsafe { assert_eq!(CHECK, $l) } + }; +} + +struct DropPanic; + +impl Drop for DropPanic { + fn drop(&mut self) { + panic!() + } +} + +fn value_zero() { + unsafe { CHECK = 0 }; + let foo = DropChecker(1); + let v: [DropChecker; 0] = [foo; 0]; + check_drops!(1); + std::mem::drop(v); + check_drops!(1); +} + +fn value_one() { + unsafe { CHECK = 0 }; + let foo = DropChecker(1); + let v: [DropChecker; 1] = [foo; 1]; + check_drops!(0); + std::mem::drop(v); + check_drops!(1); +} + +const DROP_CHECKER: DropChecker = DropChecker(1); + +fn const_zero() { + unsafe { CHECK = 0 }; + let v: [DropChecker; 0] = [DROP_CHECKER; 0]; + check_drops!(0); + std::mem::drop(v); + check_drops!(0); +} + +fn const_one() { + unsafe { CHECK = 0 }; + let v: [DropChecker; 1] = [DROP_CHECKER; 1]; + check_drops!(0); + std::mem::drop(v); + check_drops!(1); +} + +fn const_generic_zero() { + unsafe { CHECK = 0 }; + let v: [DropChecker; N] = [DROP_CHECKER; N]; + check_drops!(0); + std::mem::drop(v); + check_drops!(0); +} + +fn const_generic_one() { + unsafe { CHECK = 0 }; + let v: [DropChecker; N] = [DROP_CHECKER; N]; + check_drops!(0); + std::mem::drop(v); + check_drops!(1); +} + +// Make sure that things are allowed to promote as expected + +fn allow_promote() { + unsafe { CHECK = 0 }; + let foo = DropChecker(1); + let v: &'static [DropChecker; 0] = &[foo; 0]; + check_drops!(1); + std::mem::drop(v); + check_drops!(1); +} + +// Verify that unwinding in the drop causes the right things to drop in the right order +fn on_unwind() { + unsafe { CHECK = 0 }; + std::panic::catch_unwind(|| { + let panic = DropPanic; + let _local = DropChecker(2); + let _v = (DropChecker(1), [panic; 0]); + std::process::abort(); + }) + .unwrap_err(); + check_drops!(2); +} + +fn main() { + value_zero(); + value_one(); + const_zero(); + const_one(); + const_generic_zero::<0>(); + const_generic_one::<1>(); + allow_promote(); + on_unwind(); +} diff --git a/tests/ui/drop/terminate-in-initializer.rs b/tests/ui/drop/terminate-in-initializer.rs new file mode 100644 index 000000000..66f267aa7 --- /dev/null +++ b/tests/ui/drop/terminate-in-initializer.rs @@ -0,0 +1,34 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +// Issue #787 +// Don't try to clean up uninitialized locals + + +use std::thread; + +fn test_break() { loop { let _x: Box = break; } } + +fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box = continue; } } + +fn test_ret() { let _x: Box = return; } + +fn test_panic() { + fn f() { let _x: Box = panic!(); } + thread::spawn(move|| f() ).join().unwrap_err(); +} + +fn test_panic_indirect() { + fn f() -> ! { panic!(); } + fn g() { let _x: Box = f(); } + thread::spawn(move|| g() ).join().unwrap_err(); +} + +pub fn main() { + test_break(); + test_cont(); + test_ret(); + test_panic(); + test_panic_indirect(); +} diff --git a/tests/ui/drop/use_inline_dtor.rs b/tests/ui/drop/use_inline_dtor.rs new file mode 100644 index 000000000..ac916de46 --- /dev/null +++ b/tests/ui/drop/use_inline_dtor.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:inline_dtor.rs + +// pretty-expanded FIXME #23616 + +extern crate inline_dtor; + +pub fn main() { + let _x = inline_dtor::Foo; +} diff --git a/tests/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs b/tests/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs new file mode 100644 index 000000000..e07082957 --- /dev/null +++ b/tests/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs @@ -0,0 +1,37 @@ +#![feature(dropck_eyepatch)] + +// This is a support file for ../dropck-eyepatch-extern-crate.rs +// +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself, +// and that this attribute's effects are preserved when importing +// the type from another crate. +// +// See also ../dropck-eyepatch.rs for more information about the general +// structure of the test. + +use std::fmt; + +pub struct Dt(pub &'static str, pub A); +pub struct Dr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B); +pub struct Pt(pub &'static str, pub A, pub B); +pub struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(pub &'static str, pub &'a B, pub &'b B); +pub struct St(pub &'static str, pub A); +pub struct Sr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} diff --git a/tests/ui/dropck/cleanup-arm-conditional.rs b/tests/ui/dropck/cleanup-arm-conditional.rs new file mode 100644 index 000000000..38c717089 --- /dev/null +++ b/tests/ui/dropck/cleanup-arm-conditional.rs @@ -0,0 +1,39 @@ +// run-pass + +#![allow(stable_features)] +#![allow(unused_imports)] +// Test that cleanup scope for temporaries created in a match +// arm is confined to the match arm itself. + +// pretty-expanded FIXME #23616 + +#![feature(os)] + +use std::os; + +struct Test { x: isize } + +impl Test { + fn get_x(&self) -> Option> { + Some(Box::new(self.x)) + } +} + +fn do_something(t: &Test) -> isize { + + // The cleanup scope for the result of `t.get_x()` should be the + // arm itself and not the match, otherwise we'll (potentially) get + // a crash trying to free an uninitialized stack slot. + + match t { + &Test { x: 2 } if t.get_x().is_some() => { + t.x * 2 + } + _ => { 22 } + } +} + +pub fn main() { + let t = Test { x: 1 }; + do_something(&t); +} diff --git a/tests/ui/dropck/drop-on-non-struct.rs b/tests/ui/dropck/drop-on-non-struct.rs new file mode 100644 index 000000000..145eab126 --- /dev/null +++ b/tests/ui/dropck/drop-on-non-struct.rs @@ -0,0 +1,14 @@ +impl<'a> Drop for &'a mut isize { + //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions + //~^^ ERROR E0117 + fn drop(&mut self) { + println!("kaboom"); + } +} + +impl Drop for Nonexistent { + //~^ ERROR cannot find type `Nonexistent` + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/dropck/drop-on-non-struct.stderr b/tests/ui/dropck/drop-on-non-struct.stderr new file mode 100644 index 000000000..e8fbe5e97 --- /dev/null +++ b/tests/ui/dropck/drop-on-non-struct.stderr @@ -0,0 +1,27 @@ +error[E0412]: cannot find type `Nonexistent` in this scope + --> $DIR/drop-on-non-struct.rs:9:15 + | +LL | impl Drop for Nonexistent { + | ^^^^^^^^^^^ not found in this scope + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/drop-on-non-struct.rs:1:1 + | +LL | impl<'a> Drop for &'a mut isize { + | ^^^^^^^^^^^^^^^^^^------------- + | | | + | | `isize` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/drop-on-non-struct.rs:1:19 + | +LL | impl<'a> Drop for &'a mut isize { + | ^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0117, E0120, E0412. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/dropck/drop-with-active-borrows-1.rs b/tests/ui/dropck/drop-with-active-borrows-1.rs new file mode 100644 index 000000000..1e924af29 --- /dev/null +++ b/tests/ui/dropck/drop-with-active-borrows-1.rs @@ -0,0 +1,8 @@ +fn main() { + let a = "".to_string(); + let b: Vec<&str> = a.lines().collect(); + drop(a); //~ ERROR cannot move out of `a` because it is borrowed + for s in &b { + println!("{}", *s); + } +} diff --git a/tests/ui/dropck/drop-with-active-borrows-1.stderr b/tests/ui/dropck/drop-with-active-borrows-1.stderr new file mode 100644 index 000000000..8d6a7f372 --- /dev/null +++ b/tests/ui/dropck/drop-with-active-borrows-1.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/drop-with-active-borrows-1.rs:4:10 + | +LL | let b: Vec<&str> = a.lines().collect(); + | --------- borrow of `a` occurs here +LL | drop(a); + | ^ move out of `a` occurs here +LL | for s in &b { + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/dropck/drop-with-active-borrows-2.rs b/tests/ui/dropck/drop-with-active-borrows-2.rs new file mode 100644 index 000000000..cf4cb3dbe --- /dev/null +++ b/tests/ui/dropck/drop-with-active-borrows-2.rs @@ -0,0 +1,9 @@ +fn read_lines_borrowed<'a>() -> Vec<&'a str> { + let raw_lines: Vec = vec!["foo ".to_string(), " bar".to_string()]; + raw_lines.iter().map(|l| l.trim()).collect() + //~^ ERROR cannot return value referencing local variable `raw_lines` +} + +fn main() { + println!("{:?}", read_lines_borrowed()); +} diff --git a/tests/ui/dropck/drop-with-active-borrows-2.stderr b/tests/ui/dropck/drop-with-active-borrows-2.stderr new file mode 100644 index 000000000..24650dfac --- /dev/null +++ b/tests/ui/dropck/drop-with-active-borrows-2.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `raw_lines` + --> $DIR/drop-with-active-borrows-2.rs:3:5 + | +LL | raw_lines.iter().map(|l| l.trim()).collect() + | ----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `raw_lines` is borrowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/dropck/dropck-eyepatch-extern-crate.rs b/tests/ui/dropck/dropck-eyepatch-extern-crate.rs new file mode 100644 index 000000000..b8f303554 --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch-extern-crate.rs @@ -0,0 +1,82 @@ +// aux-build:dropck_eyepatch_extern_crate.rs + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself, +// and that this attribute's effects are preserved when importing +// the type from another crate. +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. +extern crate dropck_eyepatch_extern_crate as other; + +use other::{Dt,Dr,Pt,Pr,St,Sr}; + +fn main() { + use std::cell::Cell; + + // We use separate blocks with separate variable to prevent the error + // messages from being deduplicated. + + { + let c_long; + let (mut dt, mut dr): (Dt<_>, Dr<_>); + c_long = Cell::new(1); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long); + dr = Dr("dr", &c_long); + } + + { + let (c, mut dt, mut dr): (Cell<_>, Dt<_>, Dr<_>); + c = Cell::new(1); + + // No Error: destructor order precisely modelled + dt = Dt("dt", &c); + dr = Dr("dr", &c); + } + + { + let (mut dt, mut dr, c_shortest): (Dt<_>, Dr<_>, Cell<_>); + c_shortest = Cell::new(1); + + // Error: `c_shortest` dies too soon for the references in dtors to be valid. + dt = Dt("dt", &c_shortest); + //~^ ERROR `c_shortest` does not live long enough + dr = Dr("dr", &c_shortest); + } + + { + let c_long; + let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>); + c_long = Cell::new(1); + c_shortest = Cell::new(1); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c_shortest, &c_long); + pr = Pr("pr", &c_shortest, &c_long); + } + + { + let c_long; + let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>); + c_long = Cell::new(1); + c_shortest = Cell::new(1); + // Error: Drop impl's assertion does not apply to `B` nor `&'b _` + pt = Pt("pt", &c_long, &c_shortest); + //~^ ERROR `c_shortest` does not live long enough + pr = Pr("pr", &c_long, &c_shortest); + } + + { + let (st, sr, c_shortest): (St<_>, Sr<_>, Cell<_>); + c_shortest = Cell::new(1); + // No error: St and Sr have no destructor. + st = St("st", &c_shortest); + sr = Sr("sr", &c_shortest); + } +} + +fn use_imm(_: &T) { } diff --git a/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr b/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr new file mode 100644 index 000000000..5d5340557 --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr @@ -0,0 +1,31 @@ +error[E0597]: `c_shortest` does not live long enough + --> $DIR/dropck-eyepatch-extern-crate.rs:46:23 + | +LL | dt = Dt("dt", &c_shortest); + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c_shortest` dropped here while still borrowed + | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c_shortest` does not live long enough + --> $DIR/dropck-eyepatch-extern-crate.rs:68:32 + | +LL | pt = Pt("pt", &c_long, &c_shortest); + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c_shortest` dropped here while still borrowed + | borrow might be used here, when `pt` is dropped and runs the `Drop` code for type `Pt` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs b/tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs new file mode 100644 index 000000000..6869ab1c4 --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs @@ -0,0 +1,35 @@ +#![feature(dropck_eyepatch)] + +// This test ensures that a use of `#[may_dangle]` is rejected if +// it is not attached to an `unsafe impl`. + +use std::fmt; + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} + +fn main() { +} diff --git a/tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr new file mode 100644 index 000000000..5cec2bcb0 --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -0,0 +1,27 @@ +error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:21:1 + | +LL | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + | ++++++ + +error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute + --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1 + | +LL | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + | ++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0569`. diff --git a/tests/ui/dropck/dropck-eyepatch-reorder.rs b/tests/ui/dropck/dropck-eyepatch-reorder.rs new file mode 100644 index 000000000..44552b3fc --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch-reorder.rs @@ -0,0 +1,100 @@ +#![feature(dropck_eyepatch)] + +// The point of this test is to test uses of `#[may_dangle]` attribute +// where the formal declaration order (in the impl generics) does not +// match the actual usage order (in the type instantiation). +// +// See also dropck-eyepatch.rs for more information about the general +// structure of the test. + +use std::fmt; + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +unsafe impl Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +unsafe impl<'b, #[may_dangle] 'a, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} + +fn main() { + use std::cell::Cell; + + // We use separate blocks with separate variable to prevent the error + // messages from being deduplicated. + + { + let c_long; + let (mut dt, mut dr): (Dt<_>, Dr<_>); + c_long = Cell::new(1); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long); + dr = Dr("dr", &c_long); + } + + { + let (c, mut dt, mut dr): (Cell<_>, Dt<_>, Dr<_>); + c = Cell::new(1); + + // No Error: destructor order precisely modelled + dt = Dt("dt", &c); + dr = Dr("dr", &c); + } + + { + let (mut dt, mut dr, c_shortest): (Dt<_>, Dr<_>, Cell<_>); + c_shortest = Cell::new(1); + + // Error: `c_shortest` dies too soon for the references in dtors to be valid. + dt = Dt("dt", &c_shortest); + //~^ ERROR `c_shortest` does not live long enough + dr = Dr("dr", &c_shortest); + } + + { + let c_long; + let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>); + c_long = Cell::new(1); + c_shortest = Cell::new(1); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c_shortest, &c_long); + pr = Pr("pr", &c_shortest, &c_long); + } + + { + let c_long; + let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>); + c_long = Cell::new(1); + c_shortest = Cell::new(1); + // Error: Drop impl's assertion does not apply to `B` nor `&'b _` + pt = Pt("pt", &c_long, &c_shortest); + //~^ ERROR `c_shortest` does not live long enough + pr = Pr("pr", &c_long, &c_shortest); + } + + { + let (st, sr, c_shortest): (St<_>, Sr<_>, Cell<_>); + c_shortest = Cell::new(1); + // No error: St and Sr have no destructor. + st = St("st", &c_shortest); + sr = Sr("sr", &c_shortest); + } +} + +fn use_imm(_: &T) { } diff --git a/tests/ui/dropck/dropck-eyepatch-reorder.stderr b/tests/ui/dropck/dropck-eyepatch-reorder.stderr new file mode 100644 index 000000000..5055cdd8b --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch-reorder.stderr @@ -0,0 +1,31 @@ +error[E0597]: `c_shortest` does not live long enough + --> $DIR/dropck-eyepatch-reorder.rs:64:23 + | +LL | dt = Dt("dt", &c_shortest); + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c_shortest` dropped here while still borrowed + | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c_shortest` does not live long enough + --> $DIR/dropck-eyepatch-reorder.rs:86:32 + | +LL | pt = Pt("pt", &c_long, &c_shortest); + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c_shortest` dropped here while still borrowed + | borrow might be used here, when `pt` is dropped and runs the `Drop` code for type `Pt` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dropck/dropck-eyepatch.rs b/tests/ui/dropck/dropck-eyepatch.rs new file mode 100644 index 000000000..ec1c68561 --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch.rs @@ -0,0 +1,123 @@ +#![feature(dropck_eyepatch)] + +// The point of this test is to illustrate that the `#[may_dangle]` +// attribute specifically allows, in the context of a type +// implementing `Drop`, a generic parameter to be instantiated with a +// lifetime that does not strictly outlive the owning type itself. +// +// Here we test that only the expected errors are issued. +// +// The illustration is made concrete by comparison with two variations +// on the type with `#[may_dangle]`: +// +// 1. an analogous type that does not implement `Drop` (and thus +// should exhibit maximal flexibility with respect to dropck), and +// +// 2. an analogous type that does not use `#[may_dangle]` (and thus +// should exhibit the standard limitations imposed by dropck. +// +// The types in this file follow a pattern, {D,P,S}{t,r}, where: +// +// - D means "I implement Drop" +// +// - P means "I implement Drop but guarantee my (first) parameter is +// pure, i.e., not accessed from the destructor"; no other parameters +// are pure. +// +// - S means "I do not implement Drop" +// +// - t suffix is used when the first generic is a type +// +// - r suffix is used when the first generic is a lifetime. + +use std::fmt; + +struct Dt(&'static str, A); +struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B); +struct Pt(&'static str, A, B); +struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B); +struct St(&'static str, A); +struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B); + +impl Drop for Dt { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +impl<'a, B: fmt::Debug> Drop for Dr<'a, B> { + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); } +} +unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + // (unsafe to access self.1 due to #[may_dangle] on A) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} +unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + // (unsafe to access self.1 due to #[may_dangle] on 'a) + fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } +} + + +fn main() { + use std::cell::Cell; + + // We use separate blocks with separate variable to prevent the error + // messages from being deduplicated. + + { + let c_long; + let (mut dt, mut dr): (Dt<_>, Dr<_>); + c_long = Cell::new(1); + + // No error: sufficiently long-lived state can be referenced in dtors + dt = Dt("dt", &c_long); + dr = Dr("dr", &c_long); + } + + { + let (c, mut dt, mut dr): (Cell<_>, Dt<_>, Dr<_>); + c = Cell::new(1); + + // No Error: destructor order precisely modelled + dt = Dt("dt", &c); + dr = Dr("dr", &c); + } + + { + let (mut dt, mut dr, c_shortest): (Dt<_>, Dr<_>, Cell<_>); + c_shortest = Cell::new(1); + + // Error: `c_shortest` dies too soon for the references in dtors to be valid. + dt = Dt("dt", &c_shortest); + //~^ ERROR `c_shortest` does not live long enough + dr = Dr("dr", &c_shortest); + } + + { + let c_long; + let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>); + c_long = Cell::new(1); + c_shortest = Cell::new(1); + + // No error: Drop impl asserts .1 (A and &'a _) are not accessed + pt = Pt("pt", &c_shortest, &c_long); + pr = Pr("pr", &c_shortest, &c_long); + } + + { + let c_long; + let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>); + c_long = Cell::new(1); + c_shortest = Cell::new(1); + // Error: Drop impl's assertion does not apply to `B` nor `&'b _` + pt = Pt("pt", &c_long, &c_shortest); + //~^ ERROR `c_shortest` does not live long enough + pr = Pr("pr", &c_long, &c_shortest); + } + + { + let (st, sr, c_shortest): (St<_>, Sr<_>, Cell<_>); + c_shortest = Cell::new(1); + // No error: St and Sr have no destructor. + st = St("st", &c_shortest); + sr = Sr("sr", &c_shortest); + } +} +fn use_imm(_: &T) { } diff --git a/tests/ui/dropck/dropck-eyepatch.stderr b/tests/ui/dropck/dropck-eyepatch.stderr new file mode 100644 index 000000000..21295e6c6 --- /dev/null +++ b/tests/ui/dropck/dropck-eyepatch.stderr @@ -0,0 +1,31 @@ +error[E0597]: `c_shortest` does not live long enough + --> $DIR/dropck-eyepatch.rs:88:23 + | +LL | dt = Dt("dt", &c_shortest); + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c_shortest` dropped here while still borrowed + | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c_shortest` does not live long enough + --> $DIR/dropck-eyepatch.rs:110:32 + | +LL | pt = Pt("pt", &c_long, &c_shortest); + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c_shortest` dropped here while still borrowed + | borrow might be used here, when `pt` is dropped and runs the `Drop` code for type `Pt` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dropck/dropck-union.rs b/tests/ui/dropck/dropck-union.rs new file mode 100644 index 000000000..5a9965db5 --- /dev/null +++ b/tests/ui/dropck/dropck-union.rs @@ -0,0 +1,38 @@ +use std::cell::Cell; +use std::ops::Deref; +use std::mem::ManuallyDrop; + +union Wrap { x: ManuallyDrop } + +impl Drop for Wrap { + fn drop(&mut self) { + unsafe { std::ptr::drop_in_place(&mut *self.x as *mut T); } + } +} + +impl Wrap { + fn new(x: T) -> Self { + Wrap { x: ManuallyDrop::new(x) } + } +} + +impl Deref for Wrap { + type Target = T; + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { + &self.x + } + } +} + +struct C<'a>(Cell>>); + +impl<'a> Drop for C<'a> { + fn drop(&mut self) {} +} + +fn main() { + let v : Wrap = Wrap::new(C(Cell::new(None))); + v.0.set(Some(&v)); //~ ERROR: `v` does not live long enough +} diff --git a/tests/ui/dropck/dropck-union.stderr b/tests/ui/dropck/dropck-union.stderr new file mode 100644 index 000000000..854e29385 --- /dev/null +++ b/tests/ui/dropck/dropck-union.stderr @@ -0,0 +1,14 @@ +error[E0597]: `v` does not live long enough + --> $DIR/dropck-union.rs:37:18 + | +LL | v.0.set(Some(&v)); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `v` dropped here while still borrowed + | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Wrap` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dropck/dropck_fn_type.rs b/tests/ui/dropck/dropck_fn_type.rs new file mode 100644 index 000000000..2934217df --- /dev/null +++ b/tests/ui/dropck/dropck_fn_type.rs @@ -0,0 +1,20 @@ +// run-pass +//! Regression test for #58311, regarding the usage of Fn types in drop impls + +// All of this Drop impls should compile. + +#[allow(dead_code)] +struct S [u8; 1]>(F); + +impl [u8; 1]> Drop for S { + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct P [A; 10]>(F); + +impl [A; 10]> Drop for P { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs new file mode 100644 index 000000000..43c1c7759 --- /dev/null +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs @@ -0,0 +1,26 @@ +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + + +enum FingerTree { + Single(T), + // Bug report said Digit after Box would stack overflow (versus + // Digit before Box; see dropck_no_diverge_on_nonregular_2). + Deep( + Box>>, + Digit, + ) +} + +fn main() { + let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + FingerTree::Single(1); +} diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr new file mode 100644 index 000000000..3e39d15f9 --- /dev/null +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr @@ -0,0 +1,11 @@ +error[E0320]: overflow while adding drop-check rules for FingerTree + --> $DIR/dropck_no_diverge_on_nonregular_1.rs:24:9 + | +LL | let ft = + | ^^ + | + = note: overflowed on FingerTree>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs new file mode 100644 index 000000000..edd07652e --- /dev/null +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs @@ -0,0 +1,25 @@ +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + +enum FingerTree { + Single(T), + // Bug report said Digit before Box would infinite loop (versus + // Digit after Box; see dropck_no_diverge_on_nonregular_1). + Deep( + Digit, + Box>>, + ) +} + +fn main() { + let ft = //~ ERROR overflow while adding drop-check rules for FingerTree + FingerTree::Single(1); +} diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr new file mode 100644 index 000000000..dbb743544 --- /dev/null +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr @@ -0,0 +1,11 @@ +error[E0320]: overflow while adding drop-check rules for FingerTree + --> $DIR/dropck_no_diverge_on_nonregular_2.rs:23:9 + | +LL | let ft = + | ^^ + | + = note: overflowed on FingerTree>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs new file mode 100644 index 000000000..af7402ca4 --- /dev/null +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs @@ -0,0 +1,35 @@ +// Issue 22443: Reject code using non-regular types that would +// otherwise cause dropck to loop infinitely. +// +// This version is just checking that we still sanely handle a trivial +// wrapper around the non-regular type. (It also demonstrates how the +// error messages will report different types depending on which type +// dropck is analyzing.) + +use std::marker::PhantomData; + +struct Digit { + elem: T +} + +struct Node { m: PhantomData<&'static T> } + +enum FingerTree { + Single(T), + // According to the bug report, Digit before Box would infinite loop. + Deep( + Digit, + Box>>, + ) +} + +enum Wrapper { + Simple, + Other(FingerTree), +} + +fn main() { + let w = //~ ERROR overflow while adding drop-check rules for Option + Some(Wrapper::Simple::); + //~^ ERROR overflow while adding drop-check rules for Wrapper +} diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr new file mode 100644 index 000000000..deaf116b6 --- /dev/null +++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr @@ -0,0 +1,19 @@ +error[E0320]: overflow while adding drop-check rules for Option> + --> $DIR/dropck_no_diverge_on_nonregular_3.rs:32:9 + | +LL | let w = + | ^ + | + = note: overflowed on FingerTree>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +error[E0320]: overflow while adding drop-check rules for Wrapper + --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14 + | +LL | Some(Wrapper::Simple::); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: overflowed on FingerTree>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/dropck/dropck_trait_cycle_checked.rs b/tests/ui/dropck/dropck_trait_cycle_checked.rs new file mode 100644 index 000000000..be6ec3e4e --- /dev/null +++ b/tests/ui/dropck/dropck_trait_cycle_checked.rs @@ -0,0 +1,121 @@ +// Reject mixing cyclic structure and Drop when using trait +// objects to hide the cross-references. +// +// (Compare against ui/span/dropck_vec_cycle_checked.rs) + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId { + v: T +} + +#[allow(non_snake_case)] +fn CheckId(t: T) -> CheckId { CheckId{ v: t } } + +impl Drop for CheckId { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +trait Obj<'a> : HasId { + fn set0(&self, b: &'a Box>); + fn set1(&self, b: &'a Box>); +} + +struct O<'a> { + id: Id, + obj0: CheckId>>>>, + obj1: CheckId>>>>, +} + +impl<'a> HasId for O<'a> { + fn count(&self) -> usize { self.id.count() } +} + +impl<'a> O<'a> { + fn new() -> Box> { + Box::new(O { + id: Id::new(), + obj0: CheckId(Cell::new(None)), + obj1: CheckId(Cell::new(None)), + }) + } +} + +impl<'a> HasId for Cell>>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(c) => c.count(), + } + } +} + +impl<'a> Obj<'a> for O<'a> { + fn set0(&self, b: &'a Box>) { + self.obj0.v.set(Some(b)) + } + fn set1(&self, b: &'a Box>) { + self.obj1.v.set(Some(b)) + } +} + + +fn f() { + let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + o1.set0(&o2); //~ ERROR `o2` does not live long enough + o1.set1(&o3); //~ ERROR `o3` does not live long enough + o2.set0(&o2); //~ ERROR `o2` does not live long enough + o2.set1(&o3); //~ ERROR `o3` does not live long enough + o3.set0(&o1); //~ ERROR `o1` does not live long enough + o3.set1(&o2); //~ ERROR `o2` does not live long enough +} + +fn main() { + f(); +} diff --git a/tests/ui/dropck/dropck_trait_cycle_checked.stderr b/tests/ui/dropck/dropck_trait_cycle_checked.stderr new file mode 100644 index 000000000..dc3fbed59 --- /dev/null +++ b/tests/ui/dropck/dropck_trait_cycle_checked.stderr @@ -0,0 +1,73 @@ +error[E0597]: `o2` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:111:13 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o2` is borrowed for `'static` +LL | o1.set0(&o2); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `o2` dropped here while still borrowed + +error[E0597]: `o3` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:112:13 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o3` is borrowed for `'static` +LL | o1.set0(&o2); +LL | o1.set1(&o3); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `o3` dropped here while still borrowed + +error[E0597]: `o2` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:113:13 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o2` is borrowed for `'static` +... +LL | o2.set0(&o2); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `o2` dropped here while still borrowed + +error[E0597]: `o3` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:114:13 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o3` is borrowed for `'static` +... +LL | o2.set1(&o3); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `o3` dropped here while still borrowed + +error[E0597]: `o1` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:115:13 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o1` is borrowed for `'static` +... +LL | o3.set0(&o1); + | ^^^ borrowed value does not live long enough +LL | o3.set1(&o2); +LL | } + | - `o1` dropped here while still borrowed + +error[E0597]: `o2` does not live long enough + --> $DIR/dropck_trait_cycle_checked.rs:116:13 + | +LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); + | -------- cast requires that `o2` is borrowed for `'static` +... +LL | o3.set1(&o2); + | ^^^ borrowed value does not live long enough +LL | } + | - `o2` dropped here while still borrowed + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dropck/dropck_traits.rs b/tests/ui/dropck/dropck_traits.rs new file mode 100644 index 000000000..98e8e88a2 --- /dev/null +++ b/tests/ui/dropck/dropck_traits.rs @@ -0,0 +1,68 @@ +// run-pass +//! Regression test for #34426, regarding HRTB in drop impls + +// All of this Drop impls should compile. + +pub trait Lifetime<'a> {} +impl<'a> Lifetime<'a> for i32 {} + +#[allow(dead_code)] +struct Foo +where + for<'a> L: Lifetime<'a>, +{ + l: L, +} + +impl Drop for Foo +where + for<'a> L: Lifetime<'a>, +{ + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct Foo2 +where + for<'a> L: Lifetime<'a>, +{ + l: L, +} + +impl Lifetime<'a>> Drop for Foo2 +where + for<'x> T: Lifetime<'x>, +{ + fn drop(&mut self) {} +} + +pub trait Lifetime2<'a, 'b> {} +impl<'a, 'b> Lifetime2<'a, 'b> for i32 {} + +#[allow(dead_code)] +struct Bar +where + for<'a, 'b> L: Lifetime2<'a, 'b>, +{ + l: L, +} + +impl Drop for Bar +where + for<'a, 'b> L: Lifetime2<'a, 'b>, +{ + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct FnHolder Fn(&'a T, dyn for<'b> Lifetime2<'a, 'b>) -> u8>(T); + +impl Fn(&'a T, dyn for<'b> Lifetime2<'a, 'b>) -> u8> Drop for FnHolder { + fn drop(&mut self) {} +} + +fn main() { + let _foo = Foo { l: 0 }; + + let _bar = Bar { l: 0 }; +} diff --git a/tests/ui/dropck/issue-24805-dropck-itemless.rs b/tests/ui/dropck/issue-24805-dropck-itemless.rs new file mode 100644 index 000000000..45761b61c --- /dev/null +++ b/tests/ui/dropck/issue-24805-dropck-itemless.rs @@ -0,0 +1,77 @@ +// run-pass + +// Check that item-less traits do not cause dropck to inject extra +// region constraints. + +#![allow(non_camel_case_types)] + +#![feature(dropck_eyepatch)] + +trait UserDefined { } + +impl UserDefined for i32 { } +impl<'a, T> UserDefined for &'a T { } + +// e.g., `impl_drop!(Send, D_Send)` expands to: +// ```rust +// struct D_Send(T); +// impl Drop for D_Send { fn drop(&mut self) { } } +// ``` +macro_rules! impl_drop { + ($Bound:ident, $Id:ident) => { + struct $Id(#[allow(unused_tuple_struct_fields)] T); + unsafe impl <#[may_dangle] T: $Bound> Drop for $Id { + fn drop(&mut self) { } + } + } +} + +impl_drop!{Send, D_Send} +impl_drop!{Sized, D_Sized} + +// See note below regarding Issue 24895 +// impl_drop!{Copy, D_Copy} + +impl_drop!{Sync, D_Sync} +impl_drop!{UserDefined, D_UserDefined} + +macro_rules! body { + ($id:ident) => { { + // `_d` and `d1` are assigned the *same* lifetime by region inference ... + let (_d, d1); + + d1 = $id(1); + // ... we store a reference to `d1` within `_d` ... + _d = $id(&d1); + + // ... a *conservative* dropck will thus complain, because it + // thinks Drop of _d could access the already dropped `d1`. + } } +} + +fn f_send() { body!(D_Send) } +fn f_sized() { body!(D_Sized) } +fn f_sync() { body!(D_Sync) } + +// Issue 24895: Copy: Clone implies `impl Drop for ...` can +// access a user-defined clone() method, which causes this test case +// to fail. +// +// If 24895 is resolved by removing the `Copy: Clone` relationship, +// then this definition and the call below should be uncommented. If +// it is resolved by deciding to keep the `Copy: Clone` relationship, +// then this comment and the associated bits of code can all be +// removed. + +// fn f_copy() { body!(D_Copy) } + +fn f_userdefined() { body!(D_UserDefined) } + +fn main() { + f_send(); + f_sized(); + // See note above regarding Issue 24895. + // f_copy(); + f_sync(); + f_userdefined(); +} diff --git a/tests/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs b/tests/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs new file mode 100644 index 000000000..43c0bfb26 --- /dev/null +++ b/tests/ui/dropck/issue-28498-ugeh-with-lifetime-param.rs @@ -0,0 +1,38 @@ +// run-pass + +// Demonstrate the use of the unguarded escape hatch with a lifetime param +// to assert that destructor will not access any dead data. +// +// Compare with ui/span/issue28498-reject-lifetime-param.rs + +#![feature(dropck_eyepatch)] + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<'a>(u32, &'a ScribbleOnDrop); + +unsafe impl<#[may_dangle] 'a> Drop for Foo<'a> { + fn drop(&mut self) { + // Use of `may_dangle` is sound, because destructor never accesses `self.1`. + println!("Dropping Foo({}, _)", self.0); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); + foo1 = Foo(1, &first_dropped); + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs b/tests/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs new file mode 100644 index 000000000..04d0d3203 --- /dev/null +++ b/tests/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs @@ -0,0 +1,46 @@ +// run-pass + +// Demonstrate the use of the unguarded escape hatch with a type param in negative position +// to assert that destructor will not access any dead data. +// +// Compare with ui/span/issue28498-reject-lifetime-param.rs + +// Demonstrate that a type param in negative position causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs + +#![feature(dropck_eyepatch)] + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo(u32, T, #[allow(unused_tuple_struct_fields)] Box fn(&'r T) -> String>); + +unsafe impl<#[may_dangle] T> Drop for Foo { + fn drop(&mut self) { + // Use of `may_dangle` is sound, because destructor never passes a `self.1` + // to the callback (in `self.2`) despite having it available. + println!("Dropping Foo({}, _)", self.0); + } +} + +fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) } + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped, Box::new(callback)); + foo1 = Foo(1, &first_dropped, Box::new(callback)); + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/dropck/issue-28498-ugeh-with-trait-bound.rs b/tests/ui/dropck/issue-28498-ugeh-with-trait-bound.rs new file mode 100644 index 000000000..61d11cf38 --- /dev/null +++ b/tests/ui/dropck/issue-28498-ugeh-with-trait-bound.rs @@ -0,0 +1,41 @@ +// run-pass + +// Demonstrate the use of the unguarded escape hatch with a trait bound +// to assert that destructor will not access any dead data. +// +// Compare with ui/span/issue28498-reject-trait-bound.rs + +#![feature(dropck_eyepatch)] + +use std::fmt; + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo(u32, T); + +unsafe impl<#[may_dangle] T: fmt::Debug> Drop for Foo { + fn drop(&mut self) { + // Use of `may_dangle` is sound, because destructor never accesses + // the `Debug::fmt` method of `T`, despite having it available. + println!("Dropping Foo({}, _)", self.0); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); + foo1 = Foo(1, &first_dropped); + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/dropck/issue-29844.rs b/tests/ui/dropck/issue-29844.rs new file mode 100644 index 000000000..e08942da5 --- /dev/null +++ b/tests/ui/dropck/issue-29844.rs @@ -0,0 +1,24 @@ +// run-pass +use std::sync::Arc; + +pub struct DescriptorSet<'a> { + pub slots: Vec> +} + +pub trait ResourcesTrait<'r>: Sized { + type DescriptorSet: 'r; +} + +pub struct Resources; + +impl<'a> ResourcesTrait<'a> for Resources { + type DescriptorSet = DescriptorSet<'a>; +} + +pub enum AttachInfo<'a, R: ResourcesTrait<'a>> { + NextDescriptorSet(Arc) +} + +fn main() { + let _x = DescriptorSet {slots: Vec::new()}; +} diff --git a/tests/ui/dropck/issue-34053.rs b/tests/ui/dropck/issue-34053.rs new file mode 100644 index 000000000..fa23ae8f9 --- /dev/null +++ b/tests/ui/dropck/issue-34053.rs @@ -0,0 +1,30 @@ +// run-pass +use std::sync::atomic::{AtomicUsize, Ordering}; + +static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); + +struct A(i32); + +impl Drop for A { + fn drop(&mut self) { + // update global drop count + DROP_COUNTER.fetch_add(1, Ordering::SeqCst); + } +} + +static FOO: A = A(123); +const BAR: A = A(456); + +impl A { + const BAZ: A = A(789); +} + +fn main() { + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 0); + assert_eq!(&FOO.0, &123); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 0); + assert_eq!(BAR.0, 456); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 1); + assert_eq!(A::BAZ.0, 789); + assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); +} diff --git a/tests/ui/dropck/issue-38868.rs b/tests/ui/dropck/issue-38868.rs new file mode 100644 index 000000000..b0e5c3713 --- /dev/null +++ b/tests/ui/dropck/issue-38868.rs @@ -0,0 +1,13 @@ +pub struct List { + head: T, +} + +impl Drop for List { //~ ERROR E0366 + fn drop(&mut self) { + panic!() + } +} + +fn main() { + List { head: 0 }; +} diff --git a/tests/ui/dropck/issue-38868.stderr b/tests/ui/dropck/issue-38868.stderr new file mode 100644 index 000000000..ec81c2ea6 --- /dev/null +++ b/tests/ui/dropck/issue-38868.stderr @@ -0,0 +1,16 @@ +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/issue-38868.rs:5:1 + | +LL | impl Drop for List { + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `i32` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/issue-38868.rs:1:1 + | +LL | pub struct List { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0366`. diff --git a/tests/ui/dropck/issue-54943-1.rs b/tests/ui/dropck/issue-54943-1.rs new file mode 100644 index 000000000..ec682d960 --- /dev/null +++ b/tests/ui/dropck/issue-54943-1.rs @@ -0,0 +1,13 @@ +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. + +// check-pass + +fn foo(_t: T) { +} + +fn main() { + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/tests/ui/dropck/issue-54943-2.rs b/tests/ui/dropck/issue-54943-2.rs new file mode 100644 index 000000000..d400ae58d --- /dev/null +++ b/tests/ui/dropck/issue-54943-2.rs @@ -0,0 +1,16 @@ +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. In particular, this test is in unreachable +// code as the initial fix for this ICE only worked if the code was reachable. + +// check-pass + +fn foo(_t: T) { +} + +fn main() { + return; + + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/tests/ui/dropck/reject-specialized-drops-8142.rs b/tests/ui/dropck/reject-specialized-drops-8142.rs new file mode 100644 index 000000000..7a3bbe7cb --- /dev/null +++ b/tests/ui/dropck/reject-specialized-drops-8142.rs @@ -0,0 +1,75 @@ +// Issue 8142: Test that Drop impls cannot be specialized beyond the +// predicates attached to the type definition itself. +trait Bound { fn foo(&self) { } } +struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } +struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } +struct M<'m> { x: &'m i8 } +struct N<'n> { x: &'n i8 } +struct O { x: *const To } +struct P { x: *const Tp } +struct Q { x: *const Tq } +struct R { x: *const Tr } +struct S { x: *const Ts } +struct T<'t,Ts:'t> { x: &'t Ts } +struct U; +struct V { x: *const Tva, y: *const Tvb } +struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } +struct X; +struct Y; + +enum Enum { Variant(T) } +struct TupleStruct(T); +union Union { f: T } + +impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT + //~^ ERROR `Drop` impl requires `'adds_bnd: 'al` + fn drop(&mut self) { } } + +impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT + //~^ ERROR `Drop` impl requires `'adds_bnd: 'al` + fn drop(&mut self) { } } + +impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT + +impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impls cannot be specialized + +impl Drop for O { fn drop(&mut self) { } } // ACCEPT + +impl Drop for P { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impls cannot be specialized + +impl Drop for Q { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + +impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsRBnd: 'rbnd` + +impl Drop for S { fn drop(&mut self) { } } // ACCEPT + +impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT + +impl Drop for U { fn drop(&mut self) { } } // ACCEPT + +impl Drop for V { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impls cannot be specialized + +impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impls cannot be specialized + +impl Drop for X<3> { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impls cannot be specialized + +impl Drop for Y { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impls cannot be specialized + +impl Drop for Enum { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + +impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + +impl Drop for Union { fn drop(&mut self) { } } // REJECT +//~^ ERROR `Drop` impl requires `AddsBnd: Bound` + +pub fn main() { } diff --git a/tests/ui/dropck/reject-specialized-drops-8142.stderr b/tests/ui/dropck/reject-specialized-drops-8142.stderr new file mode 100644 index 000000000..cb48221c6 --- /dev/null +++ b/tests/ui/dropck/reject-specialized-drops-8142.stderr @@ -0,0 +1,166 @@ +error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:24:20 + | +LL | impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT + | ^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:4:1 + | +LL | struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^^^^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `'adds_bnd: 'al` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:28:67 + | +LL | impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT + | ^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:5:1 + | +LL | struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^^^^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:34:1 + | +LL | impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `'static` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:7:1 + | +LL | struct N<'n> { x: &'n i8 } + | ^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:39:1 + | +LL | impl Drop for P { fn drop(&mut self) { } } // REJECT + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `i8` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:9:1 + | +LL | struct P { x: *const Tp } + | ^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:42:14 + | +LL | impl Drop for Q { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:10:1 + | +LL | struct Q { x: *const Tq } + | ^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsRBnd: 'rbnd` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:45:21 + | +LL | impl<'rbnd,AddsRBnd:'rbnd> Drop for R { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:11:1 + | +LL | struct R { x: *const Tr } + | ^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:54:1 + | +LL | impl Drop for V { fn drop(&mut self) { } } // REJECT + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `One` is mentioned multiple times +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:15:1 + | +LL | struct V { x: *const Tva, y: *const Tvb } + | ^^^^^^^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:57:1 + | +LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `'lw` is mentioned multiple times +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:16:1 + | +LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^^^^^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:60:1 + | +LL | impl Drop for X<3> { fn drop(&mut self) { } } // REJECT + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `3` is not a generic parameter +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:17:1 + | +LL | struct X; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0366]: `Drop` impls cannot be specialized + --> $DIR/reject-specialized-drops-8142.rs:63:1 + | +LL | impl Drop for Y { fn drop(&mut self) { } } // REJECT + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Ca` is mentioned multiple times +note: use the same sequence of generic lifetime, type and const parameters as the struct definition + --> $DIR/reject-specialized-drops-8142.rs:18:1 + | +LL | struct Y; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:66:14 + | +LL | impl Drop for Enum { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:20:1 + | +LL | enum Enum { Variant(T) } + | ^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the struct it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:69:14 + | +LL | impl Drop for TupleStruct { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:21:1 + | +LL | struct TupleStruct(T); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the union it is implemented for does not + --> $DIR/reject-specialized-drops-8142.rs:72:21 + | +LL | impl Drop for Union { fn drop(&mut self) { } } // REJECT + | ^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/reject-specialized-drops-8142.rs:22:1 + | +LL | union Union { f: T } + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0366, E0367. +For more information about an error, try `rustc --explain E0366`. diff --git a/tests/ui/dropck/relate_lt_in_type_outlives_bound.rs b/tests/ui/dropck/relate_lt_in_type_outlives_bound.rs new file mode 100644 index 000000000..42530d317 --- /dev/null +++ b/tests/ui/dropck/relate_lt_in_type_outlives_bound.rs @@ -0,0 +1,13 @@ +struct Wrapper<'a, T>(&'a T) +where + T: 'a; + +impl<'a, T> Drop for Wrapper<'a, T> +where + T: 'static, + //~^ error: `Drop` impl requires `T: 'static` but the struct it is implemented for does not +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr b/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr new file mode 100644 index 000000000..3d9685db6 --- /dev/null +++ b/tests/ui/dropck/relate_lt_in_type_outlives_bound.stderr @@ -0,0 +1,15 @@ +error[E0367]: `Drop` impl requires `T: 'static` but the struct it is implemented for does not + --> $DIR/relate_lt_in_type_outlives_bound.rs:7:8 + | +LL | T: 'static, + | ^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/relate_lt_in_type_outlives_bound.rs:1:1 + | +LL | struct Wrapper<'a, T>(&'a T) + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/dst/dst-bad-assign-2.rs b/tests/ui/dst/dst-bad-assign-2.rs new file mode 100644 index 000000000..7ba31bf2e --- /dev/null +++ b/tests/ui/dst/dst-bad-assign-2.rs @@ -0,0 +1,38 @@ +// Forbid assignment into a dynamically sized type. + +struct Fat { + f1: isize, + f2: &'static str, + ptr: T +} + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; + let z: Box = Box::new(Bar1 {f: 36}); + f5.ptr = *z; + //~^ ERROR the size for values of type + +} diff --git a/tests/ui/dst/dst-bad-assign-2.stderr b/tests/ui/dst/dst-bad-assign-2.stderr new file mode 100644 index 000000000..6c9e2971c --- /dev/null +++ b/tests/ui/dst/dst-bad-assign-2.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time + --> $DIR/dst-bad-assign-2.rs:35:5 + | +LL | f5.ptr = *z; + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn ToBar` + = note: the left-hand-side of an assignment must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-assign-3.rs b/tests/ui/dst/dst-bad-assign-3.rs new file mode 100644 index 000000000..d05b3937c --- /dev/null +++ b/tests/ui/dst/dst-bad-assign-3.rs @@ -0,0 +1,39 @@ +// Forbid assignment into a dynamically sized type. + +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat = &mut (5, "some str", Bar1 {f :42}); + let z: Box = Box::new(Bar1 {f: 36}); + f5.2 = Bar1 {f: 36}; + //~^ ERROR mismatched types + //~| expected trait object `dyn ToBar`, found struct `Bar1` + //~| expected trait object `dyn ToBar` + //~| found struct `Bar1` + //~| ERROR the size for values of type +} diff --git a/tests/ui/dst/dst-bad-assign-3.stderr b/tests/ui/dst/dst-bad-assign-3.stderr new file mode 100644 index 000000000..b326dbbbc --- /dev/null +++ b/tests/ui/dst/dst-bad-assign-3.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/dst-bad-assign-3.rs:33:12 + | +LL | f5.2 = Bar1 {f: 36}; + | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding + | + = note: expected trait object `dyn ToBar` + found struct `Bar1` + +error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time + --> $DIR/dst-bad-assign-3.rs:33:5 + | +LL | f5.2 = Bar1 {f: 36}; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn ToBar` + = note: the left-hand-side of an assignment must have a statically known size + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-assign.rs b/tests/ui/dst/dst-bad-assign.rs new file mode 100644 index 000000000..496e01ae0 --- /dev/null +++ b/tests/ui/dst/dst-bad-assign.rs @@ -0,0 +1,41 @@ +// Forbid assignment into a dynamically sized type. + +struct Fat { + f1: isize, + f2: &'static str, + ptr: T +} + +#[derive(PartialEq,Eq)] +struct Bar; + +#[derive(PartialEq,Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +pub fn main() { + // Assignment. + let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; + let z: Box = Box::new(Bar1 {f: 36}); + f5.ptr = Bar1 {f: 36}; + //~^ ERROR mismatched types + //~| expected trait object `dyn ToBar`, found struct `Bar1` + //~| expected trait object `dyn ToBar` + //~| found struct `Bar1` + //~| ERROR the size for values of type +} diff --git a/tests/ui/dst/dst-bad-assign.stderr b/tests/ui/dst/dst-bad-assign.stderr new file mode 100644 index 000000000..614f21387 --- /dev/null +++ b/tests/ui/dst/dst-bad-assign.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/dst-bad-assign.rs:35:14 + | +LL | f5.ptr = Bar1 {f: 36}; + | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1` + | | + | expected due to the type of this binding + | + = note: expected trait object `dyn ToBar` + found struct `Bar1` + +error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time + --> $DIR/dst-bad-assign.rs:35:5 + | +LL | f5.ptr = Bar1 {f: 36}; + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn ToBar` + = note: the left-hand-side of an assignment must have a statically known size + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-coerce1.rs b/tests/ui/dst/dst-bad-coerce1.rs new file mode 100644 index 000000000..7ef237e39 --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce1.rs @@ -0,0 +1,36 @@ +// Attempt to change the type as well as unsizing. + +#![feature(unsized_tuple_coercion)] + +struct Fat { + ptr: T +} + +struct Foo; +trait Bar { fn bar(&self) {} } + +pub fn main() { + // With a vec of isize. + let f1 = Fat { ptr: [1, 2, 3] }; + let f2: &Fat<[isize; 3]> = &f1; + let f3: &Fat<[usize]> = f2; + //~^ ERROR mismatched types + + // With a trait. + let f1 = Fat { ptr: Foo }; + let f2: &Fat = &f1; + let f3: &Fat = f2; + //~^ ERROR `Foo: Bar` is not satisfied + + // Tuple with a vec of isize. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &([usize],) = f2; + //~^ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &(dyn Bar,) = f2; + //~^ ERROR `Foo: Bar` is not satisfied +} diff --git a/tests/ui/dst/dst-bad-coerce1.stderr b/tests/ui/dst/dst-bad-coerce1.stderr new file mode 100644 index 000000000..594acff85 --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce1.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce1.rs:16:29 + | +LL | let f3: &Fat<[usize]> = f2; + | ------------- ^^ expected slice `[usize]`, found array `[isize; 3]` + | | + | expected due to this + | + = note: expected reference `&Fat<[usize]>` + found reference `&Fat<[isize; 3]>` + +error[E0277]: the trait bound `Foo: Bar` is not satisfied + --> $DIR/dst-bad-coerce1.rs:22:29 + | +LL | let f3: &Fat = f2; + | ^^ the trait `Bar` is not implemented for `Foo` + | + = note: required for the cast from `Foo` to the object type `dyn Bar` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce1.rs:28:27 + | +LL | let f3: &([usize],) = f2; + | ----------- ^^ expected slice `[usize]`, found array `[isize; 3]` + | | + | expected due to this + | + = note: expected reference `&([usize],)` + found reference `&([isize; 3],)` + +error[E0277]: the trait bound `Foo: Bar` is not satisfied + --> $DIR/dst-bad-coerce1.rs:34:27 + | +LL | let f3: &(dyn Bar,) = f2; + | ^^ the trait `Bar` is not implemented for `Foo` + | + = note: required for the cast from `Foo` to the object type `dyn Bar` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-coerce2.rs b/tests/ui/dst/dst-bad-coerce2.rs new file mode 100644 index 000000000..e7ce20b89 --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce2.rs @@ -0,0 +1,31 @@ +// Attempt to change the mutability as well as unsizing. + +struct Fat { + ptr: T +} + +struct Foo; +trait Bar {} +impl Bar for Foo {} + +pub fn main() { + // With a vec of ints. + let f1 = Fat { ptr: [1, 2, 3] }; + let f2: &Fat<[isize; 3]> = &f1; + let f3: &mut Fat<[isize]> = f2; //~ ERROR mismatched types + + // With a trait. + let f1 = Fat { ptr: Foo }; + let f2: &Fat = &f1; + let f3: &mut Fat = f2; //~ ERROR mismatched types + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; + let f3: &mut ([isize],) = f2; //~ ERROR mismatched types + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; + let f3: &mut (dyn Bar,) = f2; //~ ERROR mismatched types +} diff --git a/tests/ui/dst/dst-bad-coerce2.stderr b/tests/ui/dst/dst-bad-coerce2.stderr new file mode 100644 index 000000000..3ded96cfb --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce2.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce2.rs:15:33 + | +LL | let f3: &mut Fat<[isize]> = f2; + | ----------------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Fat<[isize]>` + found reference `&Fat<[isize; 3]>` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce2.rs:20:33 + | +LL | let f3: &mut Fat = f2; + | ----------------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Fat` + found reference `&Fat` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce2.rs:25:31 + | +LL | let f3: &mut ([isize],) = f2; + | --------------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut ([isize],)` + found reference `&([isize; 3],)` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce2.rs:30:31 + | +LL | let f3: &mut (dyn Bar,) = f2; + | --------------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut (dyn Bar,)` + found reference `&(Foo,)` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dst/dst-bad-coerce3.rs b/tests/ui/dst/dst-bad-coerce3.rs new file mode 100644 index 000000000..fd5ee3b57 --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce3.rs @@ -0,0 +1,37 @@ +// Attempt to extend the lifetime as well as unsizing. + +#![feature(unsized_tuple_coercion)] + +struct Fat { + ptr: T +} + +struct Foo; +trait Bar { fn bar(&self) {} } +impl Bar for Foo {} + +fn baz<'a>() { + // With a vec of ints. + let f1 = Fat { ptr: [1, 2, 3] }; + let f2: &Fat<[isize; 3]> = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a Fat<[isize]> = f2; + + // With a trait. + let f1 = Fat { ptr: Foo }; + let f2: &Fat = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a Fat = f2; + + // Tuple with a vec of ints. + let f1 = ([1, 2, 3],); + let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a ([isize],) = f2; + + // Tuple with a trait. + let f1 = (Foo,); + let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough + let f3: &'a (dyn Bar,) = f2; +} + +pub fn main() { + baz(); +} diff --git a/tests/ui/dst/dst-bad-coerce3.stderr b/tests/ui/dst/dst-bad-coerce3.stderr new file mode 100644 index 000000000..957e98bbe --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce3.stderr @@ -0,0 +1,58 @@ +error[E0597]: `f1` does not live long enough + --> $DIR/dst-bad-coerce3.rs:16:32 + | +LL | fn baz<'a>() { + | -- lifetime `'a` defined here +... +LL | let f2: &Fat<[isize; 3]> = &f1; + | ^^^ borrowed value does not live long enough +LL | let f3: &'a Fat<[isize]> = f2; + | ---------------- type annotation requires that `f1` is borrowed for `'a` +... +LL | } + | - `f1` dropped here while still borrowed + +error[E0597]: `f1` does not live long enough + --> $DIR/dst-bad-coerce3.rs:21:25 + | +LL | fn baz<'a>() { + | -- lifetime `'a` defined here +... +LL | let f2: &Fat = &f1; + | ^^^ borrowed value does not live long enough +LL | let f3: &'a Fat = f2; + | ---------------- type annotation requires that `f1` is borrowed for `'a` +... +LL | } + | - `f1` dropped here while still borrowed + +error[E0597]: `f1` does not live long enough + --> $DIR/dst-bad-coerce3.rs:26:30 + | +LL | fn baz<'a>() { + | -- lifetime `'a` defined here +... +LL | let f2: &([isize; 3],) = &f1; + | ^^^ borrowed value does not live long enough +LL | let f3: &'a ([isize],) = f2; + | -------------- type annotation requires that `f1` is borrowed for `'a` +... +LL | } + | - `f1` dropped here while still borrowed + +error[E0597]: `f1` does not live long enough + --> $DIR/dst-bad-coerce3.rs:31:23 + | +LL | fn baz<'a>() { + | -- lifetime `'a` defined here +... +LL | let f2: &(Foo,) = &f1; + | ^^^ borrowed value does not live long enough +LL | let f3: &'a (dyn Bar,) = f2; + | -------------- type annotation requires that `f1` is borrowed for `'a` +LL | } + | - `f1` dropped here while still borrowed + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/dst/dst-bad-coerce4.rs b/tests/ui/dst/dst-bad-coerce4.rs new file mode 100644 index 000000000..f63da60d2 --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce4.rs @@ -0,0 +1,25 @@ +// Attempt to coerce from unsized to sized. + +#![feature(unsized_tuple_coercion)] + +struct Fat { + ptr: T +} + +pub fn main() { + // With a vec of isizes. + let f1: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] }; + let f2: &Fat<[isize; 3]> = f1; + //~^ ERROR mismatched types + //~| expected array `[isize; 3]`, found slice `[isize]` + //~| expected reference `&Fat<[isize; 3]>` + //~| found reference `&Fat<[isize]>` + + // Tuple with a vec of isizes. + let f1: &([isize],) = &([1, 2, 3],); + let f2: &([isize; 3],) = f1; + //~^ ERROR mismatched types + //~| expected array `[isize; 3]`, found slice `[isize]` + //~| expected reference `&([isize; 3],)` + //~| found reference `&([isize],)` +} diff --git a/tests/ui/dst/dst-bad-coerce4.stderr b/tests/ui/dst/dst-bad-coerce4.stderr new file mode 100644 index 000000000..4c9954f35 --- /dev/null +++ b/tests/ui/dst/dst-bad-coerce4.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce4.rs:12:32 + | +LL | let f2: &Fat<[isize; 3]> = f1; + | ---------------- ^^ expected array `[isize; 3]`, found slice `[isize]` + | | + | expected due to this + | + = note: expected reference `&Fat<[isize; 3]>` + found reference `&Fat<[isize]>` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coerce4.rs:20:30 + | +LL | let f2: &([isize; 3],) = f1; + | -------------- ^^ expected array `[isize; 3]`, found slice `[isize]` + | | + | expected due to this + | + = note: expected reference `&([isize; 3],)` + found reference `&([isize],)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dst/dst-bad-coercions.rs b/tests/ui/dst/dst-bad-coercions.rs new file mode 100644 index 000000000..bffef378c --- /dev/null +++ b/tests/ui/dst/dst-bad-coercions.rs @@ -0,0 +1,26 @@ +// Test implicit coercions involving DSTs and raw pointers. + +struct S; +trait T {} +impl T for S {} + +struct Foo { + f: T +} + +pub fn main() { + // Test that we cannot convert from *-ptr to &S and &T + let x: *const S = &S; + let y: &S = x; //~ ERROR mismatched types + let y: &dyn T = x; //~ ERROR mismatched types + + // Test that we cannot convert from *-ptr to &S and &T (mut version) + let x: *mut S = &mut S; + let y: &S = x; //~ ERROR mismatched types + let y: &dyn T = x; //~ ERROR mismatched types + + // Test that we cannot convert an immutable ptr to a mutable one using *-ptrs + let x: &mut dyn T = &S; //~ ERROR mismatched types + let x: *mut dyn T = &S; //~ ERROR mismatched types + let x: *mut S = &S; //~ ERROR mismatched types +} diff --git a/tests/ui/dst/dst-bad-coercions.stderr b/tests/ui/dst/dst-bad-coercions.stderr new file mode 100644 index 000000000..0d6f4d020 --- /dev/null +++ b/tests/ui/dst/dst-bad-coercions.stderr @@ -0,0 +1,80 @@ +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:14:17 + | +LL | let y: &S = x; + | -- ^ expected `&S`, found `*const S` + | | + | expected due to this + | + = note: expected reference `&S` + found raw pointer `*const S` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:15:21 + | +LL | let y: &dyn T = x; + | ------ ^ expected `&dyn T`, found `*const S` + | | + | expected due to this + | + = note: expected reference `&dyn T` + found raw pointer `*const S` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:19:17 + | +LL | let y: &S = x; + | -- ^ expected `&S`, found `*mut S` + | | + | expected due to this + | + = note: expected reference `&S` + found raw pointer `*mut S` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:20:21 + | +LL | let y: &dyn T = x; + | ------ ^ expected `&dyn T`, found `*mut S` + | | + | expected due to this + | + = note: expected reference `&dyn T` + found raw pointer `*mut S` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:23:25 + | +LL | let x: &mut dyn T = &S; + | ---------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut dyn T` + found reference `&S` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:24:25 + | +LL | let x: *mut dyn T = &S; + | ---------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut dyn T` + found reference `&S` + +error[E0308]: mismatched types + --> $DIR/dst-bad-coercions.rs:25:21 + | +LL | let x: *mut S = &S; + | ------ ^^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut S` + found reference `&S` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dst/dst-bad-deep-2.rs b/tests/ui/dst/dst-bad-deep-2.rs new file mode 100644 index 000000000..e58739913 --- /dev/null +++ b/tests/ui/dst/dst-bad-deep-2.rs @@ -0,0 +1,13 @@ +// Try to initialise a DST struct where the lost information is deeply nested. +// This is an error because it requires an unsized rvalue. This is a problem +// because it would require stack allocation of an unsized temporary (*g in the +// test). + +#![feature(unsized_tuple_coercion)] + +pub fn main() { + let f: ([isize; 3],) = ([5, 6, 7],); + let g: &([isize],) = &f; + let h: &(([isize],),) = &(*g,); + //~^ ERROR the size for values of type +} diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr new file mode 100644 index 000000000..b22850814 --- /dev/null +++ b/tests/ui/dst/dst-bad-deep-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the size for values of type `[isize]` cannot be known at compilation time + --> $DIR/dst-bad-deep-2.rs:11:30 + | +LL | let h: &(([isize],),) = &(*g,); + | ^^^^^ doesn't have a size known at compile-time + | + = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]` + = note: required because it appears within the type `([isize],)` + = note: required because it appears within the type `(([isize],),)` + = note: tuples must have a statically known size to be initialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-bad-deep.rs b/tests/ui/dst/dst-bad-deep.rs new file mode 100644 index 000000000..a42672960 --- /dev/null +++ b/tests/ui/dst/dst-bad-deep.rs @@ -0,0 +1,15 @@ +// Try to initialise a DST struct where the lost information is deeply nested. +// This is an error because it requires an unsized rvalue. This is a problem +// because it would require stack allocation of an unsized temporary (*g in the +// test). + +struct Fat { + ptr: T +} + +pub fn main() { + let f: Fat<[isize; 3]> = Fat { ptr: [5, 6, 7] }; + let g: &Fat<[isize]> = &f; + let h: &Fat> = &Fat { ptr: *g }; + //~^ ERROR the size for values of type +} diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr new file mode 100644 index 000000000..98db79591 --- /dev/null +++ b/tests/ui/dst/dst-bad-deep.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `[isize]` cannot be known at compilation time + --> $DIR/dst-bad-deep.rs:13:34 + | +LL | let h: &Fat> = &Fat { ptr: *g }; + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Fat>`, the trait `Sized` is not implemented for `[isize]` +note: required because it appears within the type `Fat<[isize]>` + --> $DIR/dst-bad-deep.rs:6:8 + | +LL | struct Fat { + | ^^^ + = note: structs must have a statically known size to be initialized + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-index.rs b/tests/ui/dst/dst-index.rs new file mode 100644 index 000000000..2f2c5df46 --- /dev/null +++ b/tests/ui/dst/dst-index.rs @@ -0,0 +1,37 @@ +// Test that overloaded index expressions with DST result types +// can't be used as rvalues + +use std::ops::Index; +use std::fmt::Debug; + +#[derive(Copy, Clone)] +struct S; + +impl Index for S { + type Output = str; + + fn index(&self, _: usize) -> &str { + "hello" + } +} + +#[derive(Copy, Clone)] +struct T; + +impl Index for T { + type Output = dyn Debug + 'static; + + fn index<'a>(&'a self, idx: usize) -> &'a (dyn Debug + 'static) { + static x: usize = 42; + &x + } +} + +fn main() { + S[0]; + //~^ ERROR cannot move out of index of `S` + //~^^ ERROR E0161 + T[0]; + //~^ ERROR cannot move out of index of `T` + //~^^ ERROR E0161 +} diff --git a/tests/ui/dst/dst-index.stderr b/tests/ui/dst/dst-index.stderr new file mode 100644 index 000000000..d38af3f89 --- /dev/null +++ b/tests/ui/dst/dst-index.stderr @@ -0,0 +1,28 @@ +error[E0161]: cannot move a value of type `str` + --> $DIR/dst-index.rs:31:5 + | +LL | S[0]; + | ^^^^ the size of `str` cannot be statically determined + +error[E0161]: cannot move a value of type `dyn Debug` + --> $DIR/dst-index.rs:34:5 + | +LL | T[0]; + | ^^^^ the size of `dyn Debug` cannot be statically determined + +error[E0507]: cannot move out of index of `S` + --> $DIR/dst-index.rs:31:5 + | +LL | S[0]; + | ^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of index of `T` + --> $DIR/dst-index.rs:34:5 + | +LL | T[0]; + | ^^^^ move occurs because value has type `dyn Debug`, which does not implement the `Copy` trait + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0161, E0507. +For more information about an error, try `rustc --explain E0161`. diff --git a/tests/ui/dst/dst-object-from-unsized-type.rs b/tests/ui/dst/dst-object-from-unsized-type.rs new file mode 100644 index 000000000..3cd5b1ed6 --- /dev/null +++ b/tests/ui/dst/dst-object-from-unsized-type.rs @@ -0,0 +1,27 @@ +// Test that we cannot create objects from unsized types. + +trait Foo { fn foo(&self) {} } +impl Foo for str {} +impl Foo for [u8] {} + +fn test1(t: &T) { + let u: &dyn Foo = t; + //~^ ERROR the size for values of type +} + +fn test2(t: &T) { + let v: &dyn Foo = t as &dyn Foo; + //~^ ERROR the size for values of type +} + +fn test3() { + let _: &[&dyn Foo] = &["hi"]; + //~^ ERROR the size for values of type +} + +fn test4(x: &[u8]) { + let _: &dyn Foo = x as &dyn Foo; + //~^ ERROR the size for values of type +} + +fn main() { } diff --git a/tests/ui/dst/dst-object-from-unsized-type.stderr b/tests/ui/dst/dst-object-from-unsized-type.stderr new file mode 100644 index 000000000..e24c96ebe --- /dev/null +++ b/tests/ui/dst/dst-object-from-unsized-type.stderr @@ -0,0 +1,51 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/dst-object-from-unsized-type.rs:8:23 + | +LL | fn test1(t: &T) { + | - this type parameter needs to be `std::marker::Sized` +LL | let u: &dyn Foo = t; + | ^ doesn't have a size known at compile-time + | + = note: required for the cast from `T` to the object type `dyn Foo` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn test1(t: &T) { +LL + fn test1(t: &T) { + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/dst-object-from-unsized-type.rs:13:23 + | +LL | fn test2(t: &T) { + | - this type parameter needs to be `std::marker::Sized` +LL | let v: &dyn Foo = t as &dyn Foo; + | ^ doesn't have a size known at compile-time + | + = note: required for the cast from `T` to the object type `dyn Foo` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn test2(t: &T) { +LL + fn test2(t: &T) { + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dst-object-from-unsized-type.rs:18:28 + | +LL | let _: &[&dyn Foo] = &["hi"]; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn Foo` + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/dst-object-from-unsized-type.rs:23:23 + | +LL | let _: &dyn Foo = x as &dyn Foo; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: required for the cast from `[u8]` to the object type `dyn Foo` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-rvalue.rs b/tests/ui/dst/dst-rvalue.rs new file mode 100644 index 000000000..fbb32cac1 --- /dev/null +++ b/tests/ui/dst/dst-rvalue.rs @@ -0,0 +1,10 @@ +// Check that dynamically sized rvalues are forbidden + +pub fn main() { + let _x: Box = Box::new(*"hello world"); + //~^ ERROR E0277 + + let array: &[isize] = &[1, 2, 3]; + let _x: Box<[isize]> = Box::new(*array); + //~^ ERROR E0277 +} diff --git a/tests/ui/dst/dst-rvalue.stderr b/tests/ui/dst/dst-rvalue.stderr new file mode 100644 index 000000000..8d0a82b70 --- /dev/null +++ b/tests/ui/dst/dst-rvalue.stderr @@ -0,0 +1,27 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dst-rvalue.rs:4:33 + | +LL | let _x: Box = Box::new(*"hello world"); + | -------- ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error[E0277]: the size for values of type `[isize]` cannot be known at compilation time + --> $DIR/dst-rvalue.rs:8:37 + | +LL | let _x: Box<[isize]> = Box::new(*array); + | -------- ^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[isize]` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dst/dst-sized-trait-param.rs b/tests/ui/dst/dst-sized-trait-param.rs new file mode 100644 index 000000000..cfd59197b --- /dev/null +++ b/tests/ui/dst/dst-sized-trait-param.rs @@ -0,0 +1,13 @@ +// Check that when you implement a trait that has a sized type +// parameter, the corresponding value must be sized. Also that the +// self type must be sized if appropriate. + +trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized + +impl Foo<[isize]> for usize { } +//~^ ERROR the size for values of type + +impl Foo for [usize] { } +//~^ ERROR the size for values of type + +pub fn main() { } diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr new file mode 100644 index 000000000..60e9de903 --- /dev/null +++ b/tests/ui/dst/dst-sized-trait-param.stderr @@ -0,0 +1,33 @@ +error[E0277]: the size for values of type `[isize]` cannot be known at compilation time + --> $DIR/dst-sized-trait-param.rs:7:6 + | +LL | impl Foo<[isize]> for usize { } + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[isize]` +note: required by a bound in `Foo` + --> $DIR/dst-sized-trait-param.rs:5:11 + | +LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized + | ^ required by this bound in `Foo` +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized + | ++++++++ + +error[E0277]: the size for values of type `[usize]` cannot be known at compilation time + --> $DIR/dst-sized-trait-param.rs:10:21 + | +LL | impl Foo for [usize] { } + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[usize]` +note: required by a bound in `Foo` + --> $DIR/dst-sized-trait-param.rs:5:16 + | +LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized + | ^^^^^ required by this bound in `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dupe-first-attr.rc b/tests/ui/dupe-first-attr.rc new file mode 100644 index 000000000..8b7025b7b --- /dev/null +++ b/tests/ui/dupe-first-attr.rc @@ -0,0 +1,24 @@ +// Regression test for a problem with the first mod attribute +// being applied to every mod + +// pretty-expanded FIXME #23616 + +#[cfg(target_os = "linux")] +mod hello; + +#[cfg(target_os = "macos")] +mod hello; + +#[cfg(target_os = "windows")] +mod hello; + +#[cfg(target_os = "freebsd")] +mod hello; + +#[cfg(target_os = "dragonfly")] +mod hello; + +#[cfg(target_os = "android")] +mod hello; + +pub fn main() { } diff --git a/tests/ui/duplicate/dupe-symbols-1.rs b/tests/ui/duplicate/dupe-symbols-1.rs new file mode 100644 index 000000000..28e329b56 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-1.rs @@ -0,0 +1,14 @@ +// build-fail + +// +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +pub fn a() { +} + +#[export_name="fail"] +pub fn b() { +//~^ symbol `fail` is already defined +} diff --git a/tests/ui/duplicate/dupe-symbols-1.stderr b/tests/ui/duplicate/dupe-symbols-1.stderr new file mode 100644 index 000000000..933ed5e89 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-1.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/dupe-symbols-1.rs:12:1 + | +LL | pub fn b() { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-2.rs b/tests/ui/duplicate/dupe-symbols-2.rs new file mode 100644 index 000000000..e303a790b --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-2.rs @@ -0,0 +1,18 @@ +// build-fail + +// +#![crate_type="rlib"] +#![allow(warnings)] + +pub mod a { + #[no_mangle] + pub extern "C" fn fail() { + } +} + +pub mod b { + #[no_mangle] + pub extern "C" fn fail() { + //~^ symbol `fail` is already defined + } +} diff --git a/tests/ui/duplicate/dupe-symbols-2.stderr b/tests/ui/duplicate/dupe-symbols-2.stderr new file mode 100644 index 000000000..b132eae4b --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-2.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/dupe-symbols-2.rs:15:5 + | +LL | pub extern "C" fn fail() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-3.rs b/tests/ui/duplicate/dupe-symbols-3.rs new file mode 100644 index 000000000..1af2fe98e --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-3.rs @@ -0,0 +1,14 @@ +// build-fail + +// +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +pub fn a() { +} + +#[no_mangle] +pub fn fail() { +//~^ symbol `fail` is already defined +} diff --git a/tests/ui/duplicate/dupe-symbols-3.stderr b/tests/ui/duplicate/dupe-symbols-3.stderr new file mode 100644 index 000000000..6300b4908 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-3.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/dupe-symbols-3.rs:12:1 + | +LL | pub fn fail() { + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-4.rs b/tests/ui/duplicate/dupe-symbols-4.rs new file mode 100644 index 000000000..de6610c3e --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-4.rs @@ -0,0 +1,24 @@ +// build-fail + +// +// error-pattern: symbol `fail` is already defined +#![crate_type="rlib"] +#![allow(warnings)] + + +pub trait A { + fn fail(self); +} + +struct B; +struct C; + +impl A for B { + #[no_mangle] + fn fail(self) {} +} + +impl A for C { + #[no_mangle] + fn fail(self) {} +} diff --git a/tests/ui/duplicate/dupe-symbols-4.stderr b/tests/ui/duplicate/dupe-symbols-4.stderr new file mode 100644 index 000000000..1407a4883 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-4.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/dupe-symbols-4.rs:23:5 + | +LL | fn fail(self) {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-5.rs b/tests/ui/duplicate/dupe-symbols-5.rs new file mode 100644 index 000000000..ea801cef6 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-5.rs @@ -0,0 +1,13 @@ +// build-fail + +// +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +static HELLO: u8 = 0; + +#[export_name="fail"] +pub fn b() { +//~^ symbol `fail` is already defined +} diff --git a/tests/ui/duplicate/dupe-symbols-5.stderr b/tests/ui/duplicate/dupe-symbols-5.stderr new file mode 100644 index 000000000..558f868a0 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-5.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/dupe-symbols-5.rs:11:1 + | +LL | pub fn b() { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-6.rs b/tests/ui/duplicate/dupe-symbols-6.rs new file mode 100644 index 000000000..018f4bb7f --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-6.rs @@ -0,0 +1,11 @@ +// build-fail + +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +static HELLO: u8 = 0; + +#[export_name="fail"] +static HELLO_TWICE: u16 = 0; +//~^ symbol `fail` is already defined diff --git a/tests/ui/duplicate/dupe-symbols-6.stderr b/tests/ui/duplicate/dupe-symbols-6.stderr new file mode 100644 index 000000000..6692a63dc --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-6.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/dupe-symbols-6.rs:10:1 + | +LL | static HELLO_TWICE: u16 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-7.rs b/tests/ui/duplicate/dupe-symbols-7.rs new file mode 100644 index 000000000..633ca4c31 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-7.rs @@ -0,0 +1,12 @@ +// build-fail + +// +// error-pattern: entry symbol `main` declared multiple times + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +#![allow(warnings)] + +#[no_mangle] +fn main(){} diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr new file mode 100644 index 000000000..1455f0e75 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-7.stderr @@ -0,0 +1,10 @@ +error: entry symbol `main` declared multiple times + --> $DIR/dupe-symbols-7.rs:12:1 + | +LL | fn main(){} + | ^^^^^^^^^ + | + = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/dupe-symbols-8.rs b/tests/ui/duplicate/dupe-symbols-8.rs new file mode 100644 index 000000000..ce7fa24a9 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-8.rs @@ -0,0 +1,12 @@ +// build-fail +// error-pattern: entry symbol `main` declared multiple times +// +// See #67946. + +#![allow(warnings)] +fn main() { + extern "Rust" { + fn main(); + } + unsafe { main(); } +} diff --git a/tests/ui/duplicate/dupe-symbols-8.stderr b/tests/ui/duplicate/dupe-symbols-8.stderr new file mode 100644 index 000000000..8d6a79e12 --- /dev/null +++ b/tests/ui/duplicate/dupe-symbols-8.stderr @@ -0,0 +1,10 @@ +error: entry symbol `main` declared multiple times + --> $DIR/dupe-symbols-8.rs:7:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + +error: aborting due to previous error + diff --git a/tests/ui/duplicate/duplicate-check-macro-exports.rs b/tests/ui/duplicate/duplicate-check-macro-exports.rs new file mode 100644 index 000000000..9ba28acfd --- /dev/null +++ b/tests/ui/duplicate/duplicate-check-macro-exports.rs @@ -0,0 +1,6 @@ +pub use std::panic; + +#[macro_export] +macro_rules! panic { () => {} } //~ ERROR the name `panic` is defined multiple times + +fn main() {} diff --git a/tests/ui/duplicate/duplicate-check-macro-exports.stderr b/tests/ui/duplicate/duplicate-check-macro-exports.stderr new file mode 100644 index 000000000..ba723b38b --- /dev/null +++ b/tests/ui/duplicate/duplicate-check-macro-exports.stderr @@ -0,0 +1,18 @@ +error[E0255]: the name `panic` is defined multiple times + --> $DIR/duplicate-check-macro-exports.rs:4:1 + | +LL | pub use std::panic; + | ---------- previous import of the macro `panic` here +... +LL | macro_rules! panic { () => {} } + | ^^^^^^^^^^^^^^^^^^ `panic` redefined here + | + = note: `panic` must be defined only once in the macro namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use std::panic as other_panic; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/duplicate/duplicate-parameter.rs b/tests/ui/duplicate/duplicate-parameter.rs new file mode 100644 index 000000000..e5b21bbcd --- /dev/null +++ b/tests/ui/duplicate/duplicate-parameter.rs @@ -0,0 +1,5 @@ +fn f(a: isize, a: isize) {} +//~^ ERROR identifier `a` is bound more than once in this parameter list + +fn main() { +} diff --git a/tests/ui/duplicate/duplicate-parameter.stderr b/tests/ui/duplicate/duplicate-parameter.stderr new file mode 100644 index 000000000..f3ef0bcf3 --- /dev/null +++ b/tests/ui/duplicate/duplicate-parameter.stderr @@ -0,0 +1,9 @@ +error[E0415]: identifier `a` is bound more than once in this parameter list + --> $DIR/duplicate-parameter.rs:1:16 + | +LL | fn f(a: isize, a: isize) {} + | ^ used as parameter more than once + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0415`. diff --git a/tests/ui/duplicate/duplicate-type-parameter.rs b/tests/ui/duplicate/duplicate-type-parameter.rs new file mode 100644 index 000000000..2751b3c8d --- /dev/null +++ b/tests/ui/duplicate/duplicate-type-parameter.rs @@ -0,0 +1,29 @@ +type Foo = Option; +//~^ ERROR the name `T` is already used + +struct Bar(T); +//~^ ERROR the name `T` is already used + +struct Baz { +//~^ ERROR the name `T` is already used + x: T, +} + +enum Boo { +//~^ ERROR the name `T` is already used + A(T), + B, +} + +fn quux(x: T) {} +//~^ ERROR the name `T` is already used + +trait Qux {} +//~^ ERROR the name `T` is already used + +impl Qux for Option {} +//~^ ERROR the name `T` is already used +//~^^ ERROR the type parameter `T` is not constrained + +fn main() { +} diff --git a/tests/ui/duplicate/duplicate-type-parameter.stderr b/tests/ui/duplicate/duplicate-type-parameter.stderr new file mode 100644 index 000000000..628f898d5 --- /dev/null +++ b/tests/ui/duplicate/duplicate-type-parameter.stderr @@ -0,0 +1,66 @@ +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:1:12 + | +LL | type Foo = Option; + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:4:14 + | +LL | struct Bar(T); + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:7:14 + | +LL | struct Baz { + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:12:12 + | +LL | enum Boo { + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:18:11 + | +LL | fn quux(x: T) {} + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:21:13 + | +LL | trait Qux {} + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate-type-parameter.rs:24:8 + | +LL | impl Qux for Option {} + | - ^ already used + | | + | first use of `T` + +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/duplicate-type-parameter.rs:24:8 + | +LL | impl Qux for Option {} + | ^ unconstrained type parameter + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0207, E0403. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/duplicate_entry_error.rs b/tests/ui/duplicate_entry_error.rs new file mode 100644 index 000000000..776ecedea --- /dev/null +++ b/tests/ui/duplicate_entry_error.rs @@ -0,0 +1,16 @@ +// normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" +// note-pattern: first defined in crate `std`. + +// Test for issue #31788 and E0152 + +#![feature(lang_items)] + +use std::panic::PanicInfo; + +#[lang = "panic_impl"] +fn panic_impl(info: &PanicInfo) -> ! { +//~^ ERROR: found duplicate lang item `panic_impl` + loop {} +} + +fn main() {} diff --git a/tests/ui/duplicate_entry_error.stderr b/tests/ui/duplicate_entry_error.stderr new file mode 100644 index 000000000..6d078dfbd --- /dev/null +++ b/tests/ui/duplicate_entry_error.stderr @@ -0,0 +1,13 @@ +error[E0152]: found duplicate lang item `panic_impl` + --> $DIR/duplicate_entry_error.rs:11:1 + | +LL | fn panic_impl(info: &PanicInfo) -> ! { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `std` (which `duplicate_entry_error` depends on) + = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib + = note: second definition in the local crate (`duplicate_entry_error`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/dyn-drop/dyn-drop.rs b/tests/ui/dyn-drop/dyn-drop.rs new file mode 100644 index 000000000..e1668a3f1 --- /dev/null +++ b/tests/ui/dyn-drop/dyn-drop.rs @@ -0,0 +1,16 @@ +#![deny(dyn_drop)] +#![allow(bare_trait_objects)] +fn foo(_: Box) {} //~ ERROR +fn bar(_: &dyn Drop) {} //~ERROR +fn baz(_: *mut Drop) {} //~ ERROR +struct Foo { + _x: Box //~ ERROR +} +trait Bar { + type T: ?Sized; +} +struct Baz {} +impl Bar for Baz { + type T = dyn Drop; //~ ERROR +} +fn main() {} diff --git a/tests/ui/dyn-drop/dyn-drop.stderr b/tests/ui/dyn-drop/dyn-drop.stderr new file mode 100644 index 000000000..1b1dbc4d1 --- /dev/null +++ b/tests/ui/dyn-drop/dyn-drop.stderr @@ -0,0 +1,38 @@ +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/dyn-drop.rs:3:19 + | +LL | fn foo(_: Box) {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/dyn-drop.rs:1:9 + | +LL | #![deny(dyn_drop)] + | ^^^^^^^^ + +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/dyn-drop.rs:4:16 + | +LL | fn bar(_: &dyn Drop) {} + | ^^^^ + +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/dyn-drop.rs:5:16 + | +LL | fn baz(_: *mut Drop) {} + | ^^^^ + +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/dyn-drop.rs:7:15 + | +LL | _x: Box + | ^^^^ + +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/dyn-drop.rs:14:16 + | +LL | type T = dyn Drop; + | ^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed new file mode 100644 index 000000000..c815080fc --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.fixed @@ -0,0 +1,82 @@ +// Under the 2015 edition with the keyword_idents lint, `dyn` is not +// entirely acceptable as an identifier. We currently do not attempt +// to detect or fix uses of `dyn` under a macro. Since we are testing +// this file via `rustfix`, we want the rustfix output to be +// compilable; so the macros here carefully use `dyn` "correctly." +// +// edition:2015 +// run-rustfix + +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod r#dyn { +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + pub struct r#dyn; +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + } +} +use outer_mod::r#dyn::r#dyn; +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + +fn main() { + match r#dyn { r#dyn => {} } +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + macro_defn::r#dyn(); +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + + macro_defn::boxed(); +} + +mod macro_defn { + use super::Trait; + + macro_rules! r#dyn { +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + + // Note that we do not lint nor fix occurrences under macros + ($dyn:tt) => { (Box, Box<$dyn Trait>) } + } + + pub fn r#dyn() -> ::outer_mod::r#dyn::r#dyn { +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + ::outer_mod::r#dyn::r#dyn +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + } + + + + pub fn boxed() -> r#dyn!( + //~^ ERROR `dyn` is a keyword + //~| WARN this is accepted in the current edition + + // Note that we do not lint nor fix occurrences under macros + dyn + ) + { + (Box::new(1), Box::new(2)) + } +} + +pub trait Trait { } + +impl Trait for u32 { } diff --git a/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs new file mode 100644 index 000000000..6cdc70714 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.rs @@ -0,0 +1,82 @@ +// Under the 2015 edition with the keyword_idents lint, `dyn` is not +// entirely acceptable as an identifier. We currently do not attempt +// to detect or fix uses of `dyn` under a macro. Since we are testing +// this file via `rustfix`, we want the rustfix output to be +// compilable; so the macros here carefully use `dyn` "correctly." +// +// edition:2015 +// run-rustfix + +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod dyn { +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + pub struct dyn; +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + } +} +use outer_mod::dyn::dyn; +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + +fn main() { + match dyn { dyn => {} } +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + macro_defn::dyn(); +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + + macro_defn::boxed(); +} + +mod macro_defn { + use super::Trait; + + macro_rules! dyn { +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + + // Note that we do not lint nor fix occurrences under macros + ($dyn:tt) => { (Box, Box<$dyn Trait>) } + } + + pub fn dyn() -> ::outer_mod::dyn::dyn { +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + ::outer_mod::dyn::dyn +//~^ ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition +//~| ERROR `dyn` is a keyword +//~| WARN this is accepted in the current edition + } + + + + pub fn boxed() -> dyn!( + //~^ ERROR `dyn` is a keyword + //~| WARN this is accepted in the current edition + + // Note that we do not lint nor fix occurrences under macros + dyn + ) + { + (Box::new(1), Box::new(2)) + } +} + +pub trait Trait { } + +impl Trait for u32 { } diff --git a/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr new file mode 100644 index 000000000..89aded913 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr @@ -0,0 +1,133 @@ +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:14:13 + | +LL | pub mod dyn { + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:11:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:17:20 + | +LL | pub struct dyn; + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:22:16 + | +LL | use outer_mod::dyn::dyn; + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:22:21 + | +LL | use outer_mod::dyn::dyn; + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:29:11 + | +LL | match dyn { dyn => {} } + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:29:17 + | +LL | match dyn { dyn => {} } + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:34:17 + | +LL | macro_defn::dyn(); + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:44:18 + | +LL | macro_rules! dyn { + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:12 + | +LL | pub fn dyn() -> ::outer_mod::dyn::dyn { + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:34 + | +LL | pub fn dyn() -> ::outer_mod::dyn::dyn { + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:52:39 + | +LL | pub fn dyn() -> ::outer_mod::dyn::dyn { + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:59:22 + | +LL | ::outer_mod::dyn::dyn + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:59:27 + | +LL | ::outer_mod::dyn::dyn + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-2015-edition-keyword-ident-lint.rs:68:23 + | +LL | pub fn boxed() -> dyn!( + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: aborting due to 14 previous errors + diff --git a/tests/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs b/tests/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs new file mode 100644 index 000000000..bda2ed17e --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs @@ -0,0 +1,52 @@ +// Under the 2015 edition with the keyword_idents lint, `dyn` is +// not entirely acceptable as an identifier. +// +// We currently do not attempt to detect or fix uses of `dyn` as an +// identifier under a macro, including under the declarative `macro` +// forms from macros 1.2 and macros 2.0. +// +// check-pass +// edition:2015 + +#![feature(decl_macro)] +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod r#dyn { + pub struct r#dyn; + } +} + +// Here we are illustrating that the current lint does not flag the +// occurrences of `dyn` in this macro definition; however, it +// certainly *could* (and it would be nice if it did), since these +// occurrences are not compatible with the 2018 edition's +// interpretation of `dyn` as a keyword. +macro defn_has_dyn_idents() { ::outer_mod::dyn::dyn } + +struct X; +trait Trait { fn hello(&self) { }} +impl Trait for X { } + +macro tt_trait($arg:tt) { & $arg Trait } +macro id_trait($id:ident) { & $id Trait } + +fn main() { + defn_has_dyn_idents!(); + + // Here we are illustrating that the current lint does not flag + // the occurrences of `dyn` in these macro invocations. It + // definitely should *not* flag the one in `tt_trait`, since that + // is expanding in a valid fashion to `&dyn Trait`. + // + // It is arguable whether it would be valid to flag the occurrence + // in `id_trait`, since that macro specifies that it takes an + // `ident` as its input. + fn f_tt(x: &X) -> tt_trait!(dyn) { x } + fn f_id(x: &X) -> id_trait!(dyn) { x } + + let x = X; + f_tt(&x).hello(); + f_id(&x).hello(); +} diff --git a/tests/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs b/tests/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs new file mode 100644 index 000000000..472f6b5c8 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs @@ -0,0 +1,57 @@ +// Under the 2015 edition with the keyword_idents lint, `dyn` is +// not entirely acceptable as an identifier. +// +// We currently do not attempt to detect or fix uses of `dyn` as an +// identifier under a macro. +// +// check-pass +// edition:2015 + +#![allow(non_camel_case_types)] +#![deny(keyword_idents)] + +mod outer_mod { + pub mod r#dyn { + pub struct r#dyn; + } +} + +// Here we are illustrating that the current lint does not flag the +// occurrences of `dyn` in this macro definition; however, it +// certainly *could* (and it would be nice if it did), since these +// occurrences are not compatible with the 2018 edition's +// interpretation of `dyn` as a keyword. +macro_rules! defn_has_dyn_idents { + () => { ::outer_mod::dyn::dyn } +} + +struct X; +trait Trait { fn hello(&self) { }} +impl Trait for X { } + +macro_rules! tt_trait { + ($arg:tt) => { & $arg Trait } +} + +macro_rules! id_trait { + ($id:ident) => { & $id Trait } +} + +fn main() { + defn_has_dyn_idents!(); + + // Here we are illustrating that the current lint does not flag + // the occurrences of `dyn` in these macro invocations. It + // definitely should *not* flag the one in `tt_trait`, since that + // is expanding in a valid fashion to `&dyn Trait`. + // + // It is arguable whether it would be valid to flag the occurrence + // in `id_trait`, since that macro specifies that it takes an + // `ident` as its input. + fn f_tt(x: &X) -> tt_trait!(dyn) { x } + fn f_id(x: &X) -> id_trait!(dyn) { x } + + let x = X; + f_tt(&x).hello(); + f_id(&x).hello(); +} diff --git a/tests/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs b/tests/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs new file mode 100644 index 000000000..d6a33c08d --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs @@ -0,0 +1,28 @@ +// Under the 2015 edition without the keyword_idents lint, `dyn` is +// entirely acceptable as an identifier. +// +// check-pass +// edition:2015 + +#![allow(non_camel_case_types)] + +mod outer_mod { + pub mod dyn { + pub struct dyn; + } +} +use outer_mod::dyn::dyn; + +fn main() { + match dyn { dyn => {} } + macro_defn::dyn(); +} +mod macro_defn { + macro_rules! dyn { + () => { ::outer_mod::dyn::dyn } + } + + pub fn dyn() -> ::outer_mod::dyn::dyn { + dyn!() + } +} diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs new file mode 100644 index 000000000..a074b5fa5 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs @@ -0,0 +1,24 @@ +// edition:2018 +#[deny(bare_trait_objects)] + +fn function(x: &SomeTrait, y: Box) { + //~^ ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let _x: &SomeTrait = todo!(); + //~^ ERROR trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} + +trait SomeTrait {} + +fn main() {} diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr new file mode 100644 index 000000000..6bafff919 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -0,0 +1,98 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:4:17 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/dyn-2018-edition-lint.rs:2:8 + | +LL | #[deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: use `dyn` + | +LL | fn function(x: &dyn SomeTrait, y: Box) { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:4:35 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | fn function(x: &SomeTrait, y: Box) { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:17:14 + | +LL | let _x: &SomeTrait = todo!(); + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let _x: &dyn SomeTrait = todo!(); + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:4:17 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | fn function(x: &dyn SomeTrait, y: Box) { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:4:17 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | fn function(x: &dyn SomeTrait, y: Box) { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:4:35 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | fn function(x: &SomeTrait, y: Box) { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2018-edition-lint.rs:4:35 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | fn function(x: &SomeTrait, y: Box) { + | +++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs new file mode 100644 index 000000000..0f05d8753 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs @@ -0,0 +1,11 @@ +// edition:2021 + +fn function(x: &SomeTrait, y: Box) { + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword + let _x: &SomeTrait = todo!(); +} + +trait SomeTrait {} + +fn main() {} diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr new file mode 100644 index 000000000..08ee77116 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr @@ -0,0 +1,25 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/dyn-2021-edition-error.rs:3:17 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | fn function(x: &dyn SomeTrait, y: Box) { + | +++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/dyn-2021-edition-error.rs:3:35 + | +LL | fn function(x: &SomeTrait, y: Box) { + | ^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | fn function(x: &SomeTrait, y: Box) { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-keyword/dyn-angle-brackets.fixed b/tests/ui/dyn-keyword/dyn-angle-brackets.fixed new file mode 100644 index 000000000..00069a3e7 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-angle-brackets.fixed @@ -0,0 +1,21 @@ +// See https://github.com/rust-lang/rust/issues/88508 +// run-rustfix +// edition:2018 +#![deny(bare_trait_objects)] +#![allow(dead_code)] +#![allow(unused_imports)] + +use std::fmt; + +#[derive(Debug)] +pub struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + ::fmt(self, f) + //~^ ERROR trait objects without an explicit `dyn` are deprecated + //~| WARNING this is accepted in the current edition + } +} + +fn main() {} diff --git a/tests/ui/dyn-keyword/dyn-angle-brackets.rs b/tests/ui/dyn-keyword/dyn-angle-brackets.rs new file mode 100644 index 000000000..ee5fee4cf --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-angle-brackets.rs @@ -0,0 +1,21 @@ +// See https://github.com/rust-lang/rust/issues/88508 +// run-rustfix +// edition:2018 +#![deny(bare_trait_objects)] +#![allow(dead_code)] +#![allow(unused_imports)] + +use std::fmt; + +#[derive(Debug)] +pub struct Foo; + +impl fmt::Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + ::fmt(self, f) + //~^ ERROR trait objects without an explicit `dyn` are deprecated + //~| WARNING this is accepted in the current edition + } +} + +fn main() {} diff --git a/tests/ui/dyn-keyword/dyn-angle-brackets.stderr b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr new file mode 100644 index 000000000..0bb764d71 --- /dev/null +++ b/tests/ui/dyn-keyword/dyn-angle-brackets.stderr @@ -0,0 +1,20 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-angle-brackets.rs:15:10 + | +LL | ::fmt(self, f) + | ^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/dyn-angle-brackets.rs:4:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: use `dyn` + | +LL | ::fmt(self, f) + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs b/tests/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs new file mode 100644 index 000000000..59e7f9a60 --- /dev/null +++ b/tests/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs @@ -0,0 +1,27 @@ +// check-pass +// edition:2015 +// +// rust-lang/rust#56327: Some occurrences of `dyn` within a macro are +// not instances of identifiers, and thus should *not* be caught by the +// keyword_ident lint. +// +// Otherwise, rustfix replaces the type `Box` with +// `Box`, which is injecting a bug rather than fixing +// anything. + +#![deny(rust_2018_compatibility)] +#![allow(dyn_drop)] + +macro_rules! foo { + () => { + fn generated_foo() { + let _x: Box; + } + } +} + +foo!(); + +fn main() { + generated_foo(); +} diff --git a/tests/ui/dyn-star/align.normal.stderr b/tests/ui/dyn-star/align.normal.stderr new file mode 100644 index 000000000..53c2cbeac --- /dev/null +++ b/tests/ui/dyn-star/align.normal.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/align.rs:4:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dyn-star/align.over_aligned.stderr b/tests/ui/dyn-star/align.over_aligned.stderr new file mode 100644 index 000000000..62e28efab --- /dev/null +++ b/tests/ui/dyn-star/align.over_aligned.stderr @@ -0,0 +1,20 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/align.rs:4:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: `AlignedUsize` needs to be a pointer-sized type + --> $DIR/align.rs:15:13 + | +LL | let x = AlignedUsize(12) as dyn* Debug; + | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-sized type + | + = help: the trait `PointerSized` is not implemented for `AlignedUsize` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/align.rs b/tests/ui/dyn-star/align.rs new file mode 100644 index 000000000..fb41a05a0 --- /dev/null +++ b/tests/ui/dyn-star/align.rs @@ -0,0 +1,17 @@ +// revisions: normal over_aligned +//[normal] check-pass + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +use std::fmt::Debug; + +#[cfg_attr(over_aligned, repr(C, align(1024)))] +#[cfg_attr(not(over_aligned), repr(C))] +#[derive(Debug)] +struct AlignedUsize(usize); + +fn main() { + let x = AlignedUsize(12) as dyn* Debug; + //[over_aligned]~^ ERROR `AlignedUsize` needs to be a pointer-sized type +} diff --git a/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs b/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs new file mode 100644 index 000000000..7673c7936 --- /dev/null +++ b/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs @@ -0,0 +1,10 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +pub fn require_dyn_star_display(_: dyn* Display) {} + +fn works_locally() { + require_dyn_star_display(1usize); +} diff --git a/tests/ui/dyn-star/box.rs b/tests/ui/dyn-star/box.rs new file mode 100644 index 000000000..d1f1819d9 --- /dev/null +++ b/tests/ui/dyn-star/box.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags: -C opt-level=0 + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +fn make_dyn_star() -> dyn* Display { + Box::new(42) as dyn* Display +} + +fn main() { + let x = make_dyn_star(); + + println!("{x}"); +} diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs new file mode 100644 index 000000000..e19e36cc7 --- /dev/null +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs @@ -0,0 +1,15 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +fn dyn_debug(_: (dyn* Debug + '_)) { + +} + +fn polymorphic(t: &T) { + dyn_debug(t); + //~^ ERROR `&T` needs to be a pointer-sized type +} + +fn main() {} diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr new file mode 100644 index 000000000..53ccbe43d --- /dev/null +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr @@ -0,0 +1,15 @@ +error[E0277]: `&T` needs to be a pointer-sized type + --> $DIR/check-size-at-cast-polymorphic-bad.rs:11:15 + | +LL | dyn_debug(t); + | ^ `&T` needs to be a pointer-sized type + | + = help: the trait `PointerSized` is not implemented for `&T` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn polymorphic(t: &T) where &T: PointerSized { + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic.rs new file mode 100644 index 000000000..5c0a3d256 --- /dev/null +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +fn dyn_debug(_: (dyn* Debug + '_)) { + +} + +fn polymorphic(t: &T) { + dyn_debug(t); +} + +fn main() {} diff --git a/tests/ui/dyn-star/check-size-at-cast.rs b/tests/ui/dyn-star/check-size-at-cast.rs new file mode 100644 index 000000000..1f22f7983 --- /dev/null +++ b/tests/ui/dyn-star/check-size-at-cast.rs @@ -0,0 +1,10 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +fn main() { + let i = [1, 2, 3, 4] as dyn* Debug; + //~^ ERROR `[i32; 4]` needs to be a pointer-sized type + dbg!(i); +} diff --git a/tests/ui/dyn-star/check-size-at-cast.stderr b/tests/ui/dyn-star/check-size-at-cast.stderr new file mode 100644 index 000000000..af2a1ccf7 --- /dev/null +++ b/tests/ui/dyn-star/check-size-at-cast.stderr @@ -0,0 +1,11 @@ +error[E0277]: `[i32; 4]` needs to be a pointer-sized type + --> $DIR/check-size-at-cast.rs:7:13 + | +LL | let i = [1, 2, 3, 4] as dyn* Debug; + | ^^^^^^^^^^^^ `[i32; 4]` needs to be a pointer-sized type + | + = help: the trait `PointerSized` is not implemented for `[i32; 4]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/const.rs b/tests/ui/dyn-star/const.rs new file mode 100644 index 000000000..67e3ab7ab --- /dev/null +++ b/tests/ui/dyn-star/const.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(dyn_star)] +#![allow(unused, incomplete_features)] + +use std::fmt::Debug; + +fn make_dyn_star() { + let i = 42usize; + let dyn_i: dyn* Debug = i; +} + +fn main() { + make_dyn_star(); +} diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.rs b/tests/ui/dyn-star/dispatch-on-pin-mut.rs new file mode 100644 index 000000000..5774c8b2a --- /dev/null +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.rs @@ -0,0 +1,52 @@ +// run-pass +// edition:2021 +// check-run-results + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +use std::future::Future; + +async fn foo(f: dyn* Future) { + println!("value: {}", f.await); +} + +async fn async_main() { + foo(Box::pin(async { 1 })).await +} + +// ------------------------------------------------------------------------- // +// Implementation Details Below... + +use std::pin::Pin; +use std::task::*; + +pub fn noop_waker() -> Waker { + let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE); + + // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld + unsafe { Waker::from_raw(raw) } +} + +const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); + +unsafe fn noop_clone(_p: *const ()) -> RawWaker { + RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE) +} + +unsafe fn noop(_p: *const ()) {} + +fn main() { + let mut fut = async_main(); + + // Poll loop, just to test the future... + let waker = noop_waker(); + let ctx = &mut Context::from_waker(&waker); + + loop { + match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { + Poll::Pending => {} + Poll::Ready(()) => break, + } + } +} diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.run.stdout b/tests/ui/dyn-star/dispatch-on-pin-mut.run.stdout new file mode 100644 index 000000000..96c5ca698 --- /dev/null +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.run.stdout @@ -0,0 +1 @@ +value: 1 diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.stderr b/tests/ui/dyn-star/dispatch-on-pin-mut.stderr new file mode 100644 index 000000000..cb9c78158 --- /dev/null +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/dispatch-on-pin-mut.rs:5:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.rs b/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.rs new file mode 100644 index 000000000..c12b16f16 --- /dev/null +++ b/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.rs @@ -0,0 +1,27 @@ +// run-pass +// check-run-results + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +trait AddOne { + fn add1(&mut self) -> usize; +} + +impl AddOne for usize { + fn add1(&mut self) -> usize { + *self += 1; + *self + } +} + +fn add_one(i: &mut (dyn* AddOne + '_)) -> usize { + i.add1() +} + +fn main() { + let mut x = 42usize as dyn* AddOne; + + println!("{}", add_one(&mut x)); + println!("{}", add_one(&mut x)); +} diff --git a/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout b/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout new file mode 100644 index 000000000..b4db3ed70 --- /dev/null +++ b/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout @@ -0,0 +1,2 @@ +43 +44 diff --git a/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr b/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr new file mode 100644 index 000000000..bcd014f8d --- /dev/null +++ b/tests/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/dont-unsize-coerce-dyn-star.rs:4:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dyn-star/drop.rs b/tests/ui/dyn-star/drop.rs new file mode 100644 index 000000000..1478498c0 --- /dev/null +++ b/tests/ui/dyn-star/drop.rs @@ -0,0 +1,23 @@ +// run-pass +// check-run-results +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +#[derive(Debug)] +struct Foo(usize); + +impl Drop for Foo { + fn drop(&mut self) { + println!("destructor called"); + } +} + +fn make_dyn_star(i: Foo) { + let _dyn_i: dyn* Debug = i; +} + +fn main() { + make_dyn_star(Foo(42)); +} diff --git a/tests/ui/dyn-star/drop.run.stdout b/tests/ui/dyn-star/drop.run.stdout new file mode 100644 index 000000000..dadb33ccf --- /dev/null +++ b/tests/ui/dyn-star/drop.run.stdout @@ -0,0 +1 @@ +destructor called diff --git a/tests/ui/dyn-star/dyn-async-trait.rs b/tests/ui/dyn-star/dyn-async-trait.rs new file mode 100644 index 000000000..9b27133b4 --- /dev/null +++ b/tests/ui/dyn-star/dyn-async-trait.rs @@ -0,0 +1,36 @@ +// check-pass +// edition: 2021 + +// This test case is meant to demonstrate how close we can get to async +// functions in dyn traits with the current level of dyn* support. + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::future::Future; + +trait DynAsyncCounter { + fn increment<'a>(&'a mut self) -> dyn* Future + 'a; +} + +struct MyCounter { + count: usize, +} + +impl DynAsyncCounter for MyCounter { + fn increment<'a>(&'a mut self) -> dyn* Future + 'a { + Box::pin(async { + self.count += 1; + self.count + }) + } +} + +async fn do_counter(counter: &mut dyn DynAsyncCounter) -> usize { + counter.increment().await +} + +fn main() { + let mut counter = MyCounter { count: 0 }; + let _ = do_counter(&mut counter); +} diff --git a/tests/ui/dyn-star/dyn-star-to-dyn.rs b/tests/ui/dyn-star/dyn-star-to-dyn.rs new file mode 100644 index 000000000..a6d9df952 --- /dev/null +++ b/tests/ui/dyn-star/dyn-star-to-dyn.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +fn main() { + let x: dyn* Send = &(); + let x = Box::new(x) as Box; +} diff --git a/tests/ui/dyn-star/dyn-star-to-dyn.stderr b/tests/ui/dyn-star/dyn-star-to-dyn.stderr new file mode 100644 index 000000000..03aedf5f7 --- /dev/null +++ b/tests/ui/dyn-star/dyn-star-to-dyn.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/dyn-star-to-dyn.rs:3:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dyn-star/dyn-to-rigid.rs b/tests/ui/dyn-star/dyn-to-rigid.rs new file mode 100644 index 000000000..e80ee1590 --- /dev/null +++ b/tests/ui/dyn-star/dyn-to-rigid.rs @@ -0,0 +1,11 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +trait Tr {} + +fn f(x: dyn* Tr) -> usize { + x as usize + //~^ ERROR casting `(dyn* Tr + 'static)` as `usize` is invalid +} + +fn main() {} diff --git a/tests/ui/dyn-star/dyn-to-rigid.stderr b/tests/ui/dyn-star/dyn-to-rigid.stderr new file mode 100644 index 000000000..588e6d97e --- /dev/null +++ b/tests/ui/dyn-star/dyn-to-rigid.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `(dyn* Tr + 'static)` as `usize` is invalid + --> $DIR/dyn-to-rigid.rs:7:5 + | +LL | x as usize + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/dyn-star/error.rs b/tests/ui/dyn-star/error.rs new file mode 100644 index 000000000..d8261387e --- /dev/null +++ b/tests/ui/dyn-star/error.rs @@ -0,0 +1,13 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo {} + +fn make_dyn_star() { + let i = 42; + let dyn_i: dyn* Foo = i; //~ ERROR trait bound `{integer}: Foo` is not satisfied +} + +fn main() {} diff --git a/tests/ui/dyn-star/error.stderr b/tests/ui/dyn-star/error.stderr new file mode 100644 index 000000000..ae54b9ca7 --- /dev/null +++ b/tests/ui/dyn-star/error.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `{integer}: Foo` is not satisfied + --> $DIR/error.rs:10:27 + | +LL | let dyn_i: dyn* Foo = i; + | ^ the trait `Foo` is not implemented for `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/feature-gate-dyn_star.rs b/tests/ui/dyn-star/feature-gate-dyn_star.rs new file mode 100644 index 000000000..4756661cf --- /dev/null +++ b/tests/ui/dyn-star/feature-gate-dyn_star.rs @@ -0,0 +1,9 @@ +// Feature gate test for dyn_star + +/// dyn* is not necessarily the final surface syntax (if we have one at all), +/// but for now we will support it to aid in writing tests independently. +pub fn dyn_star_parameter(_: &dyn* Send) { + //~^ dyn* trait objects are unstable +} + +fn main() {} diff --git a/tests/ui/dyn-star/feature-gate-dyn_star.stderr b/tests/ui/dyn-star/feature-gate-dyn_star.stderr new file mode 100644 index 000000000..c3449b627 --- /dev/null +++ b/tests/ui/dyn-star/feature-gate-dyn_star.stderr @@ -0,0 +1,12 @@ +error[E0658]: dyn* trait objects are unstable + --> $DIR/feature-gate-dyn_star.rs:5:31 + | +LL | pub fn dyn_star_parameter(_: &dyn* Send) { + | ^^^^^^^^^ + | + = note: see issue #102425 for more information + = help: add `#![feature(dyn_star)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/dyn-star/issue-102430.rs b/tests/ui/dyn-star/issue-102430.rs new file mode 100644 index 000000000..244ecda66 --- /dev/null +++ b/tests/ui/dyn-star/issue-102430.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +trait AddOne { + fn add1(&mut self) -> usize; +} + +impl AddOne for usize { + fn add1(&mut self) -> usize { + *self += 1; + *self + } +} + +impl AddOne for &mut usize { + fn add1(&mut self) -> usize { + (*self).add1() + } +} + +fn add_one(mut i: dyn* AddOne + '_) -> usize { + i.add1() +} + +fn main() { + let mut x = 42usize; + let y = &mut x as (dyn* AddOne + '_); + + println!("{}", add_one(y)); +} diff --git a/tests/ui/dyn-star/make-dyn-star.rs b/tests/ui/dyn-star/make-dyn-star.rs new file mode 100644 index 000000000..e5255a64b --- /dev/null +++ b/tests/ui/dyn-star/make-dyn-star.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +fn make_dyn_star(i: usize) { + let _dyn_i: dyn* Debug = i; +} + +fn make_dyn_star_explicit(i: usize) { + let _dyn_i: dyn* Debug = i as dyn* Debug; +} + +fn main() { + make_dyn_star(42); + make_dyn_star_explicit(42); +} diff --git a/tests/ui/dyn-star/method.rs b/tests/ui/dyn-star/method.rs new file mode 100644 index 000000000..5a77640f0 --- /dev/null +++ b/tests/ui/dyn-star/method.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +trait Foo { + fn get(&self) -> usize; +} + +impl Foo for usize { + fn get(&self) -> usize { + *self + } +} + +fn invoke_dyn_star(i: dyn* Foo) -> usize { + i.get() +} + +fn make_and_invoke_dyn_star(i: usize) -> usize { + let dyn_i: dyn* Foo = i; + invoke_dyn_star(dyn_i) +} + +fn main() { + println!("{}", make_and_invoke_dyn_star(42)); +} diff --git a/tests/ui/dyn-star/no-explicit-dyn-star-cast.rs b/tests/ui/dyn-star/no-explicit-dyn-star-cast.rs new file mode 100644 index 000000000..67240c8e8 --- /dev/null +++ b/tests/ui/dyn-star/no-explicit-dyn-star-cast.rs @@ -0,0 +1,13 @@ +use std::fmt::Debug; + +fn make_dyn_star() { + let i = 42usize; + let dyn_i: dyn* Debug = i as dyn* Debug; + //~^ ERROR casting `usize` as `dyn* Debug` is invalid + //~| ERROR dyn* trait objects are unstable + //~| ERROR dyn* trait objects are unstable +} + +fn main() { + make_dyn_star(); +} diff --git a/tests/ui/dyn-star/no-explicit-dyn-star-cast.stderr b/tests/ui/dyn-star/no-explicit-dyn-star-cast.stderr new file mode 100644 index 000000000..eb9c93305 --- /dev/null +++ b/tests/ui/dyn-star/no-explicit-dyn-star-cast.stderr @@ -0,0 +1,28 @@ +error[E0658]: dyn* trait objects are unstable + --> $DIR/no-explicit-dyn-star-cast.rs:5:16 + | +LL | let dyn_i: dyn* Debug = i as dyn* Debug; + | ^^^^^^^^^^ + | + = note: see issue #102425 for more information + = help: add `#![feature(dyn_star)]` to the crate attributes to enable + +error[E0658]: dyn* trait objects are unstable + --> $DIR/no-explicit-dyn-star-cast.rs:5:34 + | +LL | let dyn_i: dyn* Debug = i as dyn* Debug; + | ^^^^^^^^^^ + | + = note: see issue #102425 for more information + = help: add `#![feature(dyn_star)]` to the crate attributes to enable + +error[E0606]: casting `usize` as `dyn* Debug` is invalid + --> $DIR/no-explicit-dyn-star-cast.rs:5:29 + | +LL | let dyn_i: dyn* Debug = i as dyn* Debug; + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0606, E0658. +For more information about an error, try `rustc --explain E0606`. diff --git a/tests/ui/dyn-star/no-explicit-dyn-star.rs b/tests/ui/dyn-star/no-explicit-dyn-star.rs new file mode 100644 index 000000000..4f726b7c6 --- /dev/null +++ b/tests/ui/dyn-star/no-explicit-dyn-star.rs @@ -0,0 +1,8 @@ +// aux-build:dyn-star-foreign.rs + +extern crate dyn_star_foreign; + +fn main() { + dyn_star_foreign::require_dyn_star_display(1usize as _); + //~^ ERROR casting `usize` as `dyn* std::fmt::Display` is invalid +} diff --git a/tests/ui/dyn-star/no-explicit-dyn-star.stderr b/tests/ui/dyn-star/no-explicit-dyn-star.stderr new file mode 100644 index 000000000..49706fae1 --- /dev/null +++ b/tests/ui/dyn-star/no-explicit-dyn-star.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `usize` as `dyn* std::fmt::Display` is invalid + --> $DIR/no-explicit-dyn-star.rs:6:48 + | +LL | dyn_star_foreign::require_dyn_star_display(1usize as _); + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.rs b/tests/ui/dyn-star/no-implicit-dyn-star.rs new file mode 100644 index 000000000..d9470e284 --- /dev/null +++ b/tests/ui/dyn-star/no-implicit-dyn-star.rs @@ -0,0 +1,8 @@ +// aux-build:dyn-star-foreign.rs + +extern crate dyn_star_foreign; + +fn main() { + dyn_star_foreign::require_dyn_star_display(1usize); + //~^ ERROR mismatched types +} diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.stderr b/tests/ui/dyn-star/no-implicit-dyn-star.stderr new file mode 100644 index 000000000..a3f4d21ca --- /dev/null +++ b/tests/ui/dyn-star/no-implicit-dyn-star.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/no-implicit-dyn-star.rs:6:48 + | +LL | dyn_star_foreign::require_dyn_star_display(1usize); + | ------------------------------------------ ^^^^^^ expected trait object `dyn Display`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected trait object `(dyn* std::fmt::Display + 'static)` + found type `usize` +note: function defined here + --> $DIR/auxiliary/dyn-star-foreign.rs:6:8 + | +LL | pub fn require_dyn_star_display(_: dyn* Display) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs new file mode 100644 index 000000000..a4eb669e3 --- /dev/null +++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs @@ -0,0 +1,13 @@ +#![feature(dyn_star, trait_upcasting)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +trait A: B {} +trait B {} +impl A for usize {} +impl B for usize {} + +fn main() { + let x: Box = Box::new(1usize as dyn* A); + let y: Box = x; + //~^ ERROR mismatched types +} diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr new file mode 100644 index 000000000..c7f1a4b9a --- /dev/null +++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr @@ -0,0 +1,23 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/no-unsize-coerce-dyn-trait.rs:1:12 + | +LL | #![feature(dyn_star, trait_upcasting)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/no-unsize-coerce-dyn-trait.rs:11:26 + | +LL | let y: Box = x; + | ----------- ^ expected trait `B`, found trait `A` + | | + | expected due to this + | + = note: expected struct `Box` + found struct `Box` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/dyn-star/return.rs b/tests/ui/dyn-star/return.rs new file mode 100644 index 000000000..fa3d8d7d5 --- /dev/null +++ b/tests/ui/dyn-star/return.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +fn _foo() -> dyn* Unpin { + 4usize +} + +fn main() {} diff --git a/tests/ui/dyn-star/return.stderr b/tests/ui/dyn-star/return.stderr new file mode 100644 index 000000000..9c2656829 --- /dev/null +++ b/tests/ui/dyn-star/return.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/return.rs:3:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/dyn-star/syntax.rs b/tests/ui/dyn-star/syntax.rs new file mode 100644 index 000000000..618c72562 --- /dev/null +++ b/tests/ui/dyn-star/syntax.rs @@ -0,0 +1,11 @@ +// Make sure we can parse the `dyn* Trait` syntax +// +// check-pass + +#![feature(dyn_star)] +#![allow(incomplete_features)] + +pub fn dyn_star_parameter(_: dyn* Send) { +} + +fn main() {} diff --git a/tests/ui/dyn-star/unsize-into-ref-dyn-star.rs b/tests/ui/dyn-star/unsize-into-ref-dyn-star.rs new file mode 100644 index 000000000..1e8cafe15 --- /dev/null +++ b/tests/ui/dyn-star/unsize-into-ref-dyn-star.rs @@ -0,0 +1,9 @@ +#![feature(dyn_star)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +fn main() { + let i = 42 as &dyn* Debug; + //~^ ERROR non-primitive cast: `i32` as `&dyn* Debug` +} diff --git a/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr b/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr new file mode 100644 index 000000000..f6444a60a --- /dev/null +++ b/tests/ui/dyn-star/unsize-into-ref-dyn-star.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `i32` as `&dyn* Debug` + --> $DIR/unsize-into-ref-dyn-star.rs:7:13 + | +LL | let i = 42 as &dyn* Debug; + | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/dyn-star/upcast.rs b/tests/ui/dyn-star/upcast.rs new file mode 100644 index 000000000..c667ac143 --- /dev/null +++ b/tests/ui/dyn-star/upcast.rs @@ -0,0 +1,32 @@ +// known-bug: #104800 + +#![feature(dyn_star, trait_upcasting)] + +trait Foo: Bar { + fn hello(&self); +} + +trait Bar { + fn world(&self); +} + +struct W(usize); + +impl Foo for W { + fn hello(&self) { + println!("hello!"); + } +} + +impl Bar for W { + fn world(&self) { + println!("world!"); + } +} + +fn main() { + let w: dyn* Foo = W(0); + w.hello(); + let w: dyn* Bar = w; + w.world(); +} diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr new file mode 100644 index 000000000..74ccd6a18 --- /dev/null +++ b/tests/ui/dyn-star/upcast.stderr @@ -0,0 +1,20 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/upcast.rs:3:12 + | +LL | #![feature(dyn_star, trait_upcasting)] + | ^^^^^^^^ + | + = note: see issue #102425 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: `dyn* Foo` needs to be a pointer-sized type + --> $DIR/upcast.rs:30:23 + | +LL | let w: dyn* Bar = w; + | ^ `dyn* Foo` needs to be a pointer-sized type + | + = help: the trait `PointerSized` is not implemented for `dyn* Foo` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dynamically-sized-types/dst-coerce-custom.rs b/tests/ui/dynamically-sized-types/dst-coerce-custom.rs new file mode 100644 index 000000000..24d83eb53 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-coerce-custom.rs @@ -0,0 +1,43 @@ +// run-pass +// Test a very simple custom DST coercion. + +#![feature(unsize, coerce_unsized)] + +use std::ops::CoerceUnsized; +use std::marker::Unsize; + +struct Bar { + x: *const T, +} + +impl, U: ?Sized> CoerceUnsized> for Bar {} + +trait Baz { + fn get(&self) -> i32; +} + +impl Baz for i32 { + fn get(&self) -> i32 { + *self + } +} + +fn main() { + // Arrays. + let a: Bar<[i32; 3]> = Bar { x: &[1, 2, 3] }; + // This is the actual coercion. + let b: Bar<[i32]> = a; + + unsafe { + assert_eq!((*b.x)[0], 1); + assert_eq!((*b.x)[1], 2); + assert_eq!((*b.x)[2], 3); + } + + // Trait objects. + let a: Bar = Bar { x: &42 }; + let b: Bar = a; + unsafe { + assert_eq!((*b.x).get(), 42); + } +} diff --git a/tests/ui/dynamically-sized-types/dst-coerce-rc.rs b/tests/ui/dynamically-sized-types/dst-coerce-rc.rs new file mode 100644 index 000000000..683fa6850 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-coerce-rc.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(unused_variables)] +#![allow(stable_features)] +// Test a very simple custom DST coercion. + +#![feature(core, rc_weak)] + +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +trait Baz { + fn get(&self) -> i32; +} + +impl Baz for i32 { + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let a: Rc<[i32; 3]> = Rc::new([1, 2, 3]); + let b: Rc<[i32]> = a; + assert_eq!(b[0], 1); + assert_eq!(b[1], 2); + assert_eq!(b[2], 3); + + let a: Rc = Rc::new(42); + let b: Rc = a.clone(); + assert_eq!(b.get(), 42); + + let c: Weak = Rc::downgrade(&a); + let d: Weak = c.clone(); + + let _c = b.clone(); + + let a: Rc> = Rc::new(RefCell::new(42)); + let b: Rc> = a.clone(); + assert_eq!(b.borrow().get(), 42); + // FIXME + let c: Weak> = Rc::downgrade(&a) as Weak<_>; +} diff --git a/tests/ui/dynamically-sized-types/dst-coercions.rs b/tests/ui/dynamically-sized-types/dst-coercions.rs new file mode 100644 index 000000000..66688e93f --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-coercions.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_variables)] +// Test coercions involving DST and/or raw pointers + +// pretty-expanded FIXME #23616 + +struct S; +trait T { fn dummy(&self) { } } +impl T for S {} + +pub fn main() { + let x: &dyn T = &S; + // Test we can convert from &-ptr to *-ptr of trait objects + let x: *const dyn T = &S; + + // Test we can convert from &-ptr to *-ptr of struct pointer (not DST) + let x: *const S = &S; + + // As above, but mut + let x: &mut dyn T = &mut S; + let x: *mut dyn T = &mut S; + + let x: *mut S = &mut S; + + // Test we can change the mutability from mut to const. + let x: &dyn T = &mut S; + let x: *const dyn T = &mut S; +} diff --git a/tests/ui/dynamically-sized-types/dst-deref-mut.rs b/tests/ui/dynamically-sized-types/dst-deref-mut.rs new file mode 100644 index 000000000..1d62f42bd --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-deref-mut.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that a custom deref with a fat pointer return type does not ICE + + +use std::ops::{Deref, DerefMut}; + +pub struct Arr { + ptr: Box<[usize]> +} + +impl Deref for Arr { + type Target = [usize]; + + fn deref(&self) -> &[usize] { + panic!(); + } +} + +impl DerefMut for Arr { + fn deref_mut(&mut self) -> &mut [usize] { + &mut *self.ptr + } +} + +pub fn foo(arr: &mut Arr) { + let x: &mut [usize] = &mut **arr; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); +} + +fn main() { + let mut a = Arr { ptr: Box::new([1, 2, 3]) }; + foo(&mut a); +} diff --git a/tests/ui/dynamically-sized-types/dst-deref.rs b/tests/ui/dynamically-sized-types/dst-deref.rs new file mode 100644 index 000000000..0a350bac1 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-deref.rs @@ -0,0 +1,30 @@ +// run-pass +// Test that a custom deref with a fat pointer return type does not ICE + + +use std::ops::Deref; + +pub struct Arr { + ptr: Box<[usize]> +} + +impl Deref for Arr { + type Target = [usize]; + + fn deref(&self) -> &[usize] { + &*self.ptr + } +} + +pub fn foo(arr: &Arr) { + assert_eq!(arr.len(), 3); + let x: &[usize] = &**arr; + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); +} + +fn main() { + let a = Arr { ptr: Box::new([1, 2, 3]) }; + foo(&a); +} diff --git a/tests/ui/dynamically-sized-types/dst-field-align.rs b/tests/ui/dynamically-sized-types/dst-field-align.rs new file mode 100644 index 000000000..6c338e999 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-field-align.rs @@ -0,0 +1,67 @@ +// run-pass +#![allow(dead_code)] +struct Foo { + a: u16, + b: T +} + +trait Bar { + fn get(&self) -> usize; +} + +impl Bar for usize { + fn get(&self) -> usize { *self } +} + +struct Baz { + a: T +} + +struct HasDrop { + ptr: Box, + data: T +} + +fn main() { + // Test that zero-offset works properly + let b : Baz = Baz { a: 7 }; + assert_eq!(b.a.get(), 7); + let b : &Baz = &b; + assert_eq!(b.a.get(), 7); + + // Test that the field is aligned properly + let f : Foo = Foo { a: 0, b: 11 }; + assert_eq!(f.b.get(), 11); + let ptr1 : *const u8 = &f.b as *const _ as *const u8; + + let f : &Foo = &f; + let ptr2 : *const u8 = &f.b as *const _ as *const u8; + assert_eq!(f.b.get(), 11); + + // The pointers should be the same + assert_eq!(ptr1, ptr2); + + // Test that nested DSTs work properly + let f : Foo> = Foo { a: 0, b: Foo { a: 1, b: 17 }}; + assert_eq!(f.b.b.get(), 17); + let f : &Foo> = &f; + assert_eq!(f.b.b.get(), 17); + + // Test that get the pointer via destructuring works + + let f : Foo = Foo { a: 0, b: 11 }; + let f : &Foo = &f; + let &Foo { a: _, b: ref bar } = f; + assert_eq!(bar.get(), 11); + + // Make sure that drop flags don't screw things up + + let d : HasDrop> = HasDrop { + ptr: Box::new(0), + data: Baz { a: [1,2,3,4] } + }; + assert_eq!([1,2,3,4], d.data.a); + + let d : &HasDrop> = &d; + assert_eq!(&[1,2,3,4], &d.data.a); +} diff --git a/tests/ui/dynamically-sized-types/dst-index.rs b/tests/ui/dynamically-sized-types/dst-index.rs new file mode 100644 index 000000000..8aa65bbfd --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-index.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(unused_variables)] +// Test that overloaded index expressions with DST result types +// work and don't ICE. + +use std::ops::Index; +use std::fmt::Debug; + +struct S; + +impl Index for S { + type Output = str; + + fn index<'a>(&'a self, _: usize) -> &'a str { + "hello" + } +} + +struct T; + +impl Index for T { + type Output = dyn Debug + 'static; + + fn index<'a>(&'a self, idx: usize) -> &'a (dyn Debug + 'static) { + static X: usize = 42; + &X as &(dyn Debug + 'static) + } +} + +fn main() { + assert_eq!(&S[0], "hello"); + let _ = &T[0]; + // let x = &x as &Debug; +} diff --git a/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs b/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs new file mode 100644 index 000000000..0a6c49111 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-irrefutable-bind.rs @@ -0,0 +1,27 @@ +// run-pass +#![feature(unsized_tuple_coercion)] + +struct Test(T); + +fn main() { + let x = Test([1,2,3]); + let x : &Test<[i32]> = &x; + + let & ref _y = x; + + // Make sure binding to a fat pointer behind a reference + // still works + let slice = &[1,2,3]; + let x = Test(&slice); + let Test(&_slice) = x; + + + let x = (10, [1,2,3]); + let x : &(i32, [i32]) = &x; + + let & ref _y = x; + + let slice = &[1,2,3]; + let x = (10, &slice); + let (_, &_slice) = x; +} diff --git a/tests/ui/dynamically-sized-types/dst-raw.rs b/tests/ui/dynamically-sized-types/dst-raw.rs new file mode 100644 index 000000000..0893b02e7 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-raw.rs @@ -0,0 +1,138 @@ +// run-pass +// Test DST raw pointers + + +#![feature(unsized_tuple_coercion)] + +trait Trait { + fn foo(&self) -> isize; +} + +struct A { + f: isize +} +impl Trait for A { + fn foo(&self) -> isize { + self.f + } +} + +struct Foo { + f: T +} + +pub fn main() { + // raw trait object + let x = A { f: 42 }; + let z: *const dyn Trait = &x; + let r = unsafe { + (&*z).foo() + }; + assert_eq!(r, 42); + + // raw DST struct + let p = Foo {f: A { f: 42 }}; + let o: *const Foo = &p; + let r = unsafe { + (&*o).f.foo() + }; + assert_eq!(r, 42); + + // raw DST tuple + let p = (A { f: 42 },); + let o: *const (dyn Trait,) = &p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + + // raw slice + let a: *const [_] = &[1, 2, 3]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + // raw slice with explicit cast + let a = &[1, 2, 3] as *const [i32]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + // raw DST struct with slice + let c: *const Foo<[_]> = &Foo {f: [1, 2, 3]}; + unsafe { + let b = (&*c).f[0]; + assert_eq!(b, 1); + let len = (&*c).f.len(); + assert_eq!(len, 3); + } + + // raw DST tuple with slice + let c: *const ([_],) = &([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } + + // all of the above with *mut + let mut x = A { f: 42 }; + let z: *mut dyn Trait = &mut x; + let r = unsafe { + (&*z).foo() + }; + assert_eq!(r, 42); + + let mut p = Foo {f: A { f: 42 }}; + let o: *mut Foo = &mut p; + let r = unsafe { + (&*o).f.foo() + }; + assert_eq!(r, 42); + + let mut p = (A { f: 42 },); + let o: *mut (dyn Trait,) = &mut p; + let r = unsafe { + (&*o).0.foo() + }; + assert_eq!(r, 42); + + let a: *mut [_] = &mut [1, 2, 3]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + let a = &mut [1, 2, 3] as *mut [i32]; + unsafe { + let b = (*a)[2]; + assert_eq!(b, 3); + let len = (*a).len(); + assert_eq!(len, 3); + } + + let c: *mut Foo<[_]> = &mut Foo {f: [1, 2, 3]}; + unsafe { + let b = (&*c).f[0]; + assert_eq!(b, 1); + let len = (&*c).f.len(); + assert_eq!(len, 3); + } + + let c: *mut ([_],) = &mut ([1, 2, 3],); + unsafe { + let b = (&*c).0[0]; + assert_eq!(b, 1); + let len = (&*c).0.len(); + assert_eq!(len, 3); + } +} diff --git a/tests/ui/dynamically-sized-types/dst-struct-sole.rs b/tests/ui/dynamically-sized-types/dst-struct-sole.rs new file mode 100644 index 000000000..6ca07fcf8 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-struct-sole.rs @@ -0,0 +1,76 @@ +// run-pass +// As dst-struct.rs, but the unsized field is the only field in the struct. + + +struct Fat { + ptr: T +} + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.ptr; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.ptr[1], 2); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.ptr; + let bar = Bar; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.ptr[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = Fat { ptr: [1, 2, 3] }; + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] }; + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = Fat { ptr: [bar, bar, bar] }; + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &Fat { ptr: [bar, bar, bar] }; + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut Fat { ptr: [1, 2, 3] }; + f5.ptr[1] = 34; + assert_eq!(f5.ptr[0], 1); + assert_eq!(f5.ptr[1], 34); + assert_eq!(f5.ptr[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &Fat { ptr: [] }; + assert!(f5.ptr.is_empty()); + let f5: &Fat<[Bar]> = &Fat { ptr: [] }; + assert!(f5.ptr.is_empty()); +} diff --git a/tests/ui/dynamically-sized-types/dst-struct.rs b/tests/ui/dynamically-sized-types/dst-struct.rs new file mode 100644 index 000000000..5da9381f8 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-struct.rs @@ -0,0 +1,121 @@ +// run-pass + +struct Fat { + f1: isize, + f2: &'static str, + ptr: T +} + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.ptr; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.ptr[1], 2); + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.ptr; + let bar = Bar; + assert_eq!(x.ptr.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.ptr[1].to_bar(), bar); + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); +} + +fn foo3(x: &Fat>) { + let y = &x.ptr.ptr; + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); + assert_eq!(x.ptr.f1, 8); + assert_eq!(x.ptr.f2, "deep str"); + assert_eq!(x.ptr.ptr.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.ptr.ptr[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = Fat { f1: 5, f2: "some str", ptr: [bar, bar, bar] }; + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [bar, bar, bar] }; + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }; + f5.ptr[1] = 34; + assert_eq!(f5.ptr[0], 1); + assert_eq!(f5.ptr[1], 34); + assert_eq!(f5.ptr[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &Fat { f1: 5, f2: "some str", ptr: [] }; + assert!(f5.ptr.is_empty()); + let f5: &Fat<[Bar]> = &Fat { f1: 5, f2: "some str", ptr: [] }; + assert!(f5.ptr.is_empty()); + + // Deeply nested. + let f1 = Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} }; + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat> = f2; + foo3(f3); + let f4: &Fat> = &f1; + foo3(f4); + let f5: &Fat> = + &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: [1, 2, 3]} }; + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box> = Box::new(Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }); + foo(&*f1); + let f2 : Box> = f1; + foo(&*f2); + + let f3 : Box> = + Box::>::new(Fat { f1: 5, f2: "some str", ptr: [1, 2, 3] }); + foo(&*f3); +} diff --git a/tests/ui/dynamically-sized-types/dst-trait-tuple.rs b/tests/ui/dynamically-sized-types/dst-trait-tuple.rs new file mode 100644 index 000000000..c1e45215a --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-trait-tuple.rs @@ -0,0 +1,102 @@ +// run-pass +#![allow(type_alias_bounds)] + +#![allow(unused_features)] +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!(x.2.to_bar(), Bar); + assert_eq!(x.2.to_val(), 42); + + let y = &x.2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &dyn ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat>) { + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.to_bar(), Bar); + assert_eq!((x.2).2.to_val(), 42); + + let y = &(x.2).2; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = (5, "some str", Bar1 {f :42}); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat = f2; + foo(f3); + let f4: &Fat = &f1; + foo(f4); + let f5: &Fat = &(5, "some str", Bar1 {f :42}); + foo(f5); + + // Zero size object. + let f6: &Fat = &(5, "some str", Bar); + assert_eq!(f6.2.to_bar(), Bar); + + // &* + // + let f7: Box = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = (5, "some str", (8, "deep str", Bar1 {f :42})); + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat> = f2; + baz(f3); + let f4: &Fat> = &f1; + baz(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", Bar1 {f :42})); + baz(f5); +} diff --git a/tests/ui/dynamically-sized-types/dst-trait.rs b/tests/ui/dynamically-sized-types/dst-trait.rs new file mode 100644 index 000000000..7ac6f0392 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-trait.rs @@ -0,0 +1,104 @@ +// run-pass + +struct Fat { + f1: isize, + f2: &'static str, + ptr: T +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +#[derive(Copy, Clone, PartialEq, Eq)] +struct Bar1 { + f: isize +} + +trait ToBar { + fn to_bar(&self) -> Bar; + fn to_val(&self) -> isize; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } + fn to_val(&self) -> isize { + 0 + } +} +impl ToBar for Bar1 { + fn to_bar(&self) -> Bar { + Bar + } + fn to_val(&self) -> isize { + self.f + } +} + +// x is a fat pointer +fn foo(x: &Fat) { + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); + assert_eq!(x.ptr.to_bar(), Bar); + assert_eq!(x.ptr.to_val(), 42); + + let y = &x.ptr; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); +} + +fn bar(x: &dyn ToBar) { + assert_eq!(x.to_bar(), Bar); + assert_eq!(x.to_val(), 42); +} + +fn baz(x: &Fat>) { + assert_eq!(x.f1, 5); + assert_eq!(x.f2, "some str"); + assert_eq!(x.ptr.f1, 8); + assert_eq!(x.ptr.f2, "deep str"); + assert_eq!(x.ptr.ptr.to_bar(), Bar); + assert_eq!(x.ptr.ptr.to_val(), 42); + + let y = &x.ptr.ptr; + assert_eq!(y.to_bar(), Bar); + assert_eq!(y.to_val(), 42); + +} + +pub fn main() { + let f1 = Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat = f2; + foo(f3); + let f4: &Fat = &f1; + foo(f4); + let f5: &Fat = &Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; + foo(f5); + + // Zero size object. + let f6: &Fat = &Fat { f1: 5, f2: "some str", ptr: Bar }; + assert_eq!(f6.ptr.to_bar(), Bar); + + // &* + // + let f7: Box = Box::new(Bar1 {f :42}); + bar(&*f7); + + // Deep nesting + let f1 = + Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} }; + baz(&f1); + let f2 = &f1; + baz(f2); + let f3: &Fat> = f2; + baz(f3); + let f4: &Fat> = &f1; + baz(f4); + let f5: &Fat> = + &Fat { f1: 5, f2: "some str", ptr: Fat { f1: 8, f2: "deep str", ptr: Bar1 {f :42}} }; + baz(f5); +} diff --git a/tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs b/tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs new file mode 100644 index 000000000..26b923f43 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-tuple-no-reorder.rs @@ -0,0 +1,26 @@ +// run-pass + +#![feature(unsized_tuple_coercion)] + +// Ensure that unsizable fields that might be accessed don't get reordered + +fn nonzero_size() { + let sized: (u8, [u32; 2]) = (123, [456, 789]); + let unsize: &(u8, [u32]) = &sized; + assert_eq!(unsize.0, 123); + assert_eq!(unsize.1.len(), 2); + assert_eq!(unsize.1[0], 456); + assert_eq!(unsize.1[1], 789); +} + +fn zst() { + let sized: (u8, [u32; 0]) = (123, []); + let unsize: &(u8, [u32]) = &sized; + assert_eq!(unsize.0, 123); + assert_eq!(unsize.1.len(), 0); +} + +pub fn main() { + nonzero_size(); + zst(); +} diff --git a/tests/ui/dynamically-sized-types/dst-tuple-sole.rs b/tests/ui/dynamically-sized-types/dst-tuple-sole.rs new file mode 100644 index 000000000..606689da0 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-tuple-sole.rs @@ -0,0 +1,79 @@ +// run-pass +#![allow(stable_features)] +#![allow(type_alias_bounds)] + +// As dst-tuple.rs, but the unsized field is the only field in the tuple. + + +#![feature(unsized_tuple_coercion)] + +type Fat = (T,); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.0; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.0[1], 2); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.0; + let bar = Bar; + assert_eq!(x.0.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.0[1].to_bar(), bar); +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = ([1, 2, 3],); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &([1, 2, 3],); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = ([bar, bar, bar],); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &([bar, bar, bar],); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],); + f5.0[1] = 34; + assert_eq!(f5.0[0], 1); + assert_eq!(f5.0[1], 34); + assert_eq!(f5.0[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &([],); + assert!(f5.0.is_empty()); + let f5: &Fat<[Bar]> = &([],); + assert!(f5.0.is_empty()); +} diff --git a/tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs b/tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs new file mode 100644 index 000000000..b0cefe770 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(unsized_tuple_coercion)] + +// Check that we do not change the offsets of ZST fields when unsizing + +fn scalar_layout() { + let sized: &(u8, [(); 13]) = &(123, [(); 13]); + let unsize: &(u8, [()]) = sized; + assert_eq!(sized.1.as_ptr(), unsize.1.as_ptr()); +} + +fn scalarpair_layout() { + let sized: &(u8, u16, [(); 13]) = &(123, 456, [(); 13]); + let unsize: &(u8, u16, [()]) = sized; + assert_eq!(sized.2.as_ptr(), unsize.2.as_ptr()); +} + +pub fn main() { + scalar_layout(); + scalarpair_layout(); +} diff --git a/tests/ui/dynamically-sized-types/dst-tuple.rs b/tests/ui/dynamically-sized-types/dst-tuple.rs new file mode 100644 index 000000000..604ac5112 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-tuple.rs @@ -0,0 +1,119 @@ +// run-pass +#![allow(type_alias_bounds)] + +#![feature(unsized_tuple_coercion)] + +type Fat = (isize, &'static str, T); + +// x is a fat pointer +fn foo(x: &Fat<[isize]>) { + let y = &x.2; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!(x.2[1], 2); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo2(x: &Fat<[T]>) { + let y = &x.2; + let bar = Bar; + assert_eq!(x.2.len(), 3); + assert_eq!(y[0].to_bar(), bar); + assert_eq!(x.2[1].to_bar(), bar); + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); +} + +fn foo3(x: &Fat>) { + let y = &(x.2).2; + assert_eq!(x.0, 5); + assert_eq!(x.1, "some str"); + assert_eq!((x.2).0, 8); + assert_eq!((x.2).1, "deep str"); + assert_eq!((x.2).2.len(), 3); + assert_eq!(y[0], 1); + assert_eq!((x.2).2[1], 2); +} + + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Bar; + +trait ToBar { + fn to_bar(&self) -> Bar; +} + +impl ToBar for Bar { + fn to_bar(&self) -> Bar { + *self + } +} + +pub fn main() { + // With a vec of ints. + let f1 = (5, "some str", [1, 2, 3]); + foo(&f1); + let f2 = &f1; + foo(f2); + let f3: &Fat<[isize]> = f2; + foo(f3); + let f4: &Fat<[isize]> = &f1; + foo(f4); + let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]); + foo(f5); + + // With a vec of Bars. + let bar = Bar; + let f1 = (5, "some str", [bar, bar, bar]); + foo2(&f1); + let f2 = &f1; + foo2(f2); + let f3: &Fat<[Bar]> = f2; + foo2(f3); + let f4: &Fat<[Bar]> = &f1; + foo2(f4); + let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]); + foo2(f5); + + // Assignment. + let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]); + f5.2[1] = 34; + assert_eq!(f5.2[0], 1); + assert_eq!(f5.2[1], 34); + assert_eq!(f5.2[2], 3); + + // Zero size vec. + let f5: &Fat<[isize]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + let f5: &Fat<[Bar]> = &(5, "some str", []); + assert!(f5.2.is_empty()); + + // Deeply nested. + let f1 = (5, "some str", (8, "deep str", [1, 2, 3])); + foo3(&f1); + let f2 = &f1; + foo3(f2); + let f3: &Fat> = f2; + foo3(f3); + let f4: &Fat> = &f1; + foo3(f4); + let f5: &Fat> = &(5, "some str", (8, "deep str", [1, 2, 3])); + foo3(f5); + + // Box. + let f1 = Box::new([1, 2, 3]); + assert_eq!((*f1)[1], 2); + let f2: Box<[isize]> = f1; + assert_eq!((*f2)[1], 2); + + // Nested Box. + let f1 : Box> = Box::new((5, "some str", [1, 2, 3])); + foo(&*f1); + let f2 : Box> = f1; + foo(&*f2); + + let f3 : Box> = + Box::>::new((5, "some str", [1, 2, 3])); + foo(&*f3); +} diff --git a/tests/ui/early-ret-binop-add.rs b/tests/ui/early-ret-binop-add.rs new file mode 100644 index 000000000..2b5df52a5 --- /dev/null +++ b/tests/ui/early-ret-binop-add.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unreachable_code)] +// pretty-expanded FIXME #23616 + +use std::ops::Add; + +fn wsucc + Copy>(n: T) -> T { n + { return n } } + +pub fn main() { } diff --git a/tests/ui/editions/async-block-2015.rs b/tests/ui/editions/async-block-2015.rs new file mode 100644 index 000000000..3daf4930c --- /dev/null +++ b/tests/ui/editions/async-block-2015.rs @@ -0,0 +1,30 @@ +async fn foo() { +//~^ ERROR `async fn` is not permitted in Rust 2015 +//~| NOTE to use `async fn`, switch to Rust 2018 or later +//~| HELP pass `--edition 2021` to `rustc` +//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide + + let x = async {}; + //~^ ERROR cannot find struct, variant or union type `async` in this scope + //~| NOTE `async` blocks are only allowed in Rust 2018 or later + let y = async { //~ NOTE `async` blocks are only allowed in Rust 2018 or later + let x = 42; + //~^ ERROR expected identifier, found keyword `let` + //~| NOTE expected identifier, found keyword + //~| HELP pass `--edition 2021` to `rustc` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide + 42 + }; + let z = async { //~ NOTE `async` blocks are only allowed in Rust 2018 or later + 42 + //~^ ERROR expected identifier, found `42` + //~| NOTE expected identifier + //~| HELP pass `--edition 2021` to `rustc` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide + }; + y.await; + z.await; + x +} + +fn main() {} diff --git a/tests/ui/editions/async-block-2015.stderr b/tests/ui/editions/async-block-2015.stderr new file mode 100644 index 000000000..b792b8c1e --- /dev/null +++ b/tests/ui/editions/async-block-2015.stderr @@ -0,0 +1,41 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/async-block-2015.rs:1:1 + | +LL | async fn foo() { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: expected identifier, found keyword `let` + --> $DIR/async-block-2015.rs:11:9 + | +LL | let y = async { + | ----- `async` blocks are only allowed in Rust 2018 or later +LL | let x = 42; + | ^^^ expected identifier, found keyword + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: expected identifier, found `42` + --> $DIR/async-block-2015.rs:19:9 + | +LL | let z = async { + | ----- `async` blocks are only allowed in Rust 2018 or later +LL | 42 + | ^^ expected identifier + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0422]: cannot find struct, variant or union type `async` in this scope + --> $DIR/async-block-2015.rs:7:13 + | +LL | let x = async {}; + | ^^^^^ `async` blocks are only allowed in Rust 2018 or later + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0422, E0670. +For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/editions/auxiliary/absolute.rs b/tests/ui/editions/auxiliary/absolute.rs new file mode 100644 index 000000000..d596f9735 --- /dev/null +++ b/tests/ui/editions/auxiliary/absolute.rs @@ -0,0 +1 @@ +pub struct Path; diff --git a/tests/ui/editions/auxiliary/edition-extern-crate-allowed.rs b/tests/ui/editions/auxiliary/edition-extern-crate-allowed.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/editions/auxiliary/edition-extern-crate-allowed.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/editions/auxiliary/edition-imports-2015.rs b/tests/ui/editions/auxiliary/edition-imports-2015.rs new file mode 100644 index 000000000..c72331ca2 --- /dev/null +++ b/tests/ui/editions/auxiliary/edition-imports-2015.rs @@ -0,0 +1,31 @@ +// edition:2015 + +#[macro_export] +macro_rules! gen_imports { () => { + use import::Path; + use std::collections::LinkedList; + + fn check_absolute() { + ::absolute::Path; + ::std::collections::LinkedList::::new(); + } +}} + +#[macro_export] +macro_rules! gen_glob { () => { + use *; +}} + +#[macro_export] +macro_rules! gen_gated { () => { + fn check_gated() { + enum E { A } + use E::*; + } +}} + +#[macro_export] +macro_rules! gen_ambiguous { () => { + use Ambiguous; + type A = ::edition_imports_2015::Path; +}} diff --git a/tests/ui/editions/auxiliary/edition-imports-2018.rs b/tests/ui/editions/auxiliary/edition-imports-2018.rs new file mode 100644 index 000000000..b08dc499a --- /dev/null +++ b/tests/ui/editions/auxiliary/edition-imports-2018.rs @@ -0,0 +1,17 @@ +// edition:2018 + +#[macro_export] +macro_rules! gen_imports { () => { + use import::Path; + use std::collections::LinkedList; + + fn check_absolute() { + ::absolute::Path; + ::std::collections::LinkedList::::new(); + } +}} + +#[macro_export] +macro_rules! gen_glob { () => { + use *; +}} diff --git a/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs b/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs new file mode 100644 index 000000000..7cfd128f2 --- /dev/null +++ b/tests/ui/editions/auxiliary/edition-kw-macro-2015.rs @@ -0,0 +1,28 @@ +// edition:2015 + +#![allow(keyword_idents)] + +#[macro_export] +macro_rules! produces_async { + () => (pub fn async() {}) +} + +#[macro_export] +macro_rules! produces_async_raw { + () => (pub fn r#async() {}) +} + +#[macro_export] +macro_rules! consumes_async { + (async) => (1) +} + +#[macro_export] +macro_rules! consumes_async_raw { + (r#async) => (1) +} + +#[macro_export] +macro_rules! passes_ident { + ($i: ident) => ($i) +} diff --git a/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs b/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs new file mode 100644 index 000000000..d07c0218d --- /dev/null +++ b/tests/ui/editions/auxiliary/edition-kw-macro-2018.rs @@ -0,0 +1,28 @@ +// edition:2018 + +#![allow(keyword_idents)] + +#[macro_export] +macro_rules! produces_async { + () => (pub fn async() {}) +} + +#[macro_export] +macro_rules! produces_async_raw { + () => (pub fn r#async() {}) +} + +#[macro_export] +macro_rules! consumes_async { + (async) => (1) +} + +#[macro_export] +macro_rules! consumes_async_raw { + (r#async) => (1) +} + +#[macro_export] +macro_rules! passes_ident { + ($i: ident) => ($i) +} diff --git a/tests/ui/editions/dyn-trait-sugg-2021.rs b/tests/ui/editions/dyn-trait-sugg-2021.rs new file mode 100644 index 000000000..de0444b63 --- /dev/null +++ b/tests/ui/editions/dyn-trait-sugg-2021.rs @@ -0,0 +1,12 @@ +// edition:2021 + +trait Foo {} + +impl dyn Foo { + fn hi(_x: T) {} +} + +fn main() { + Foo::hi(123); + //~^ ERROR trait objects must include the `dyn` keyword +} diff --git a/tests/ui/editions/dyn-trait-sugg-2021.stderr b/tests/ui/editions/dyn-trait-sugg-2021.stderr new file mode 100644 index 000000000..8c68dec1d --- /dev/null +++ b/tests/ui/editions/dyn-trait-sugg-2021.stderr @@ -0,0 +1,14 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/dyn-trait-sugg-2021.rs:10:5 + | +LL | Foo::hi(123); + | ^^^ + | +help: add `dyn` keyword before this trait + | +LL | ::hi(123); + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/editions/edition-extern-crate-allowed.rs b/tests/ui/editions/edition-extern-crate-allowed.rs new file mode 100644 index 000000000..8d142cea5 --- /dev/null +++ b/tests/ui/editions/edition-extern-crate-allowed.rs @@ -0,0 +1,10 @@ +// aux-build:edition-extern-crate-allowed.rs +// edition:2015 +// check-pass + +#![warn(rust_2018_idioms)] + +extern crate edition_extern_crate_allowed; +//~^ WARNING unused extern crate + +fn main() {} diff --git a/tests/ui/editions/edition-extern-crate-allowed.stderr b/tests/ui/editions/edition-extern-crate-allowed.stderr new file mode 100644 index 000000000..dde774c52 --- /dev/null +++ b/tests/ui/editions/edition-extern-crate-allowed.stderr @@ -0,0 +1,15 @@ +warning: unused extern crate + --> $DIR/edition-extern-crate-allowed.rs:7:1 + | +LL | extern crate edition_extern_crate_allowed; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/edition-extern-crate-allowed.rs:5:9 + | +LL | #![warn(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]` + +warning: 1 warning emitted + diff --git a/tests/ui/editions/edition-feature-ok.rs b/tests/ui/editions/edition-feature-ok.rs new file mode 100644 index 000000000..69242fd71 --- /dev/null +++ b/tests/ui/editions/edition-feature-ok.rs @@ -0,0 +1,5 @@ +// check-pass + +#![feature(rust_2018_preview)] + +fn main() {} diff --git a/tests/ui/editions/edition-feature-redundant.rs b/tests/ui/editions/edition-feature-redundant.rs new file mode 100644 index 000000000..1049a2da8 --- /dev/null +++ b/tests/ui/editions/edition-feature-redundant.rs @@ -0,0 +1,7 @@ +// edition:2018 +// check-pass + +#![feature(rust_2018_preview)] +//~^ WARN the feature `rust_2018_preview` is included in the Rust 2018 edition + +fn main() {} diff --git a/tests/ui/editions/edition-feature-redundant.stderr b/tests/ui/editions/edition-feature-redundant.stderr new file mode 100644 index 000000000..b11e616d7 --- /dev/null +++ b/tests/ui/editions/edition-feature-redundant.stderr @@ -0,0 +1,9 @@ +warning[E0705]: the feature `rust_2018_preview` is included in the Rust 2018 edition + --> $DIR/edition-feature-redundant.rs:4:12 + | +LL | #![feature(rust_2018_preview)] + | ^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0705`. diff --git a/tests/ui/editions/edition-imports-2015.rs b/tests/ui/editions/edition-imports-2015.rs new file mode 100644 index 000000000..5ba45b19d --- /dev/null +++ b/tests/ui/editions/edition-imports-2015.rs @@ -0,0 +1,26 @@ +// edition:2015 +// compile-flags:--extern absolute +// aux-build:edition-imports-2018.rs +// aux-build:absolute.rs + +#[macro_use] +extern crate edition_imports_2018; + +mod check { + mod import { + pub struct Path; + } + + gen_imports!(); // OK + + fn check() { + Path; + LinkedList::::new(); + } +} + +mod check_glob { + gen_glob!(); //~ ERROR cannot glob-import all possible crates +} + +fn main() {} diff --git a/tests/ui/editions/edition-imports-2015.stderr b/tests/ui/editions/edition-imports-2015.stderr new file mode 100644 index 000000000..3f38e6f8e --- /dev/null +++ b/tests/ui/editions/edition-imports-2015.stderr @@ -0,0 +1,10 @@ +error: cannot glob-import all possible crates + --> $DIR/edition-imports-2015.rs:23:5 + | +LL | gen_glob!(); + | ^^^^^^^^^^^ + | + = note: this error originates in the macro `gen_glob` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/editions/edition-imports-2018.rs b/tests/ui/editions/edition-imports-2018.rs new file mode 100644 index 000000000..dcdbf0d05 --- /dev/null +++ b/tests/ui/editions/edition-imports-2018.rs @@ -0,0 +1,27 @@ +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + gen_imports!(); // OK + + fn check() { + Path; + LinkedList::::new(); + } +} + +mod check_glob { + gen_glob!(); //~ ERROR cannot glob-import all possible crates +} + +fn main() {} diff --git a/tests/ui/editions/edition-imports-2018.stderr b/tests/ui/editions/edition-imports-2018.stderr new file mode 100644 index 000000000..e7f760e49 --- /dev/null +++ b/tests/ui/editions/edition-imports-2018.stderr @@ -0,0 +1,10 @@ +error: cannot glob-import all possible crates + --> $DIR/edition-imports-2018.rs:24:5 + | +LL | gen_glob!(); + | ^^^^^^^^^^^ + | + = note: this error originates in the macro `gen_glob` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/tests/ui/editions/edition-imports-virtual-2015-ambiguity.rs new file mode 100644 index 000000000..3fffb30c6 --- /dev/null +++ b/tests/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -0,0 +1,20 @@ +// check-pass +// edition:2018 +// compile-flags:--extern edition_imports_2015 +// aux-build:edition-imports-2015.rs + +mod edition_imports_2015 { + pub struct Path; +} + +pub struct Ambiguous {} + +mod check { + pub struct Ambiguous {} + + fn check() { + edition_imports_2015::gen_ambiguous!(); // OK + } +} + +fn main() {} diff --git a/tests/ui/editions/edition-imports-virtual-2015-gated.rs b/tests/ui/editions/edition-imports-virtual-2015-gated.rs new file mode 100644 index 000000000..634d3e9a4 --- /dev/null +++ b/tests/ui/editions/edition-imports-virtual-2015-gated.rs @@ -0,0 +1,11 @@ +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod check { + gen_gated!(); //~ ERROR unresolved import `E` +} + +fn main() {} diff --git a/tests/ui/editions/edition-imports-virtual-2015-gated.stderr b/tests/ui/editions/edition-imports-virtual-2015-gated.stderr new file mode 100644 index 000000000..e4bdd2821 --- /dev/null +++ b/tests/ui/editions/edition-imports-virtual-2015-gated.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `E` + --> $DIR/edition-imports-virtual-2015-gated.rs:8:5 + | +LL | gen_gated!(); + | ^^^^^^^^^^^^ could not find `E` in the list of imported crates + | + = note: this error originates in the macro `gen_gated` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/editions/edition-keywords-2015-2015-expansion.rs b/tests/ui/editions/edition-keywords-2015-2015-expansion.rs new file mode 100644 index 000000000..b2695bea5 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2015-expansion.rs @@ -0,0 +1,17 @@ +// edition:2015 +// aux-build:edition-kw-macro-2015.rs +// check-pass + +#![allow(keyword_idents)] + +#[macro_use] +extern crate edition_kw_macro_2015; + +mod one_async { + produces_async! {} // OK +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.rs b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs new file mode 100644 index 000000000..d1752a7ec --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.rs @@ -0,0 +1,26 @@ +// edition:2015 +// aux-build:edition-kw-macro-2015.rs + +#[macro_use] +extern crate edition_kw_macro_2015; + +mod module { + pub fn async() {} +} + +pub fn check_async() { + let mut async = 1; // OK + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async_raw!(r#async); // OK + + if passes_ident!(async) == 1 {} // OK + if passes_ident!(r#async) == 1 {} // OK + module::async(); // OK + module::r#async(); // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr new file mode 100644 index 000000000..39944622d --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2015-parsing.stderr @@ -0,0 +1,26 @@ +error: no rules expected the token `r#async` + --> $DIR/edition-keywords-2015-2015-parsing.rs:16:31 + | +LL | r#async = consumes_async!(r#async); + | ^^^^^^^ no rules expected this token in macro call + | +note: while trying to match `async` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6 + | +LL | (async) => (1) + | ^^^^^ + +error: no rules expected the token `async` + --> $DIR/edition-keywords-2015-2015-parsing.rs:17:35 + | +LL | r#async = consumes_async_raw!(async); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match `r#async` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:22:6 + | +LL | (r#async) => (1) + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/editions/edition-keywords-2015-2015.rs b/tests/ui/editions/edition-keywords-2015-2015.rs new file mode 100644 index 000000000..943d203b8 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2015.rs @@ -0,0 +1,36 @@ +// run-pass + +#![allow(unused_mut)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +// edition:2015 +// aux-build:edition-kw-macro-2015.rs + +#[macro_use] +extern crate edition_kw_macro_2015; + +pub fn check_async() { + let mut async = 1; // OK + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + // r#async = consumes_async!(r#async); // ERROR, not a match + // r#async = consumes_async_raw!(async); // ERROR, not a match + r#async = consumes_async_raw!(r#async); // OK + + if passes_ident!(async) == 1 {} // OK + if passes_ident!(r#async) == 1 {} // OK + one_async::async(); // OK + one_async::r#async(); // OK + two_async::async(); // OK + two_async::r#async(); // OK +} + +mod one_async { + produces_async! {} // OK +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2015-2018-expansion.rs b/tests/ui/editions/edition-keywords-2015-2018-expansion.rs new file mode 100644 index 000000000..9f34a3887 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2018-expansion.rs @@ -0,0 +1,14 @@ +// edition:2015 +// aux-build:edition-kw-macro-2018.rs + +#[macro_use] +extern crate edition_kw_macro_2018; + +mod one_async { + produces_async! {} //~ ERROR expected identifier, found keyword +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr b/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr new file mode 100644 index 000000000..570bbac2b --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2015-2018-expansion.rs:8:5 + | +LL | produces_async! {} + | ^^^^^^^^^^^^^^^^^^ expected identifier, found keyword + | + = note: this error originates in the macro `produces_async` (in Nightly builds, run with -Z macro-backtrace for more info) +help: escape `async` to use it as an identifier + --> $DIR/auxiliary/edition-kw-macro-2018.rs:7:19 + | +LL | () => (pub fn r#async() {}) + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.rs b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs new file mode 100644 index 000000000..44455f438 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.rs @@ -0,0 +1,26 @@ +// edition:2015 +// aux-build:edition-kw-macro-2018.rs + +#[macro_use] +extern crate edition_kw_macro_2018; + +mod module { + pub fn async() {} +} + +pub fn check_async() { + let mut async = 1; // OK + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async_raw!(r#async); // OK + + if passes_ident!(async) == 1 {} // OK + if passes_ident!(r#async) == 1 {} // OK + module::async(); // OK + module::r#async(); // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr new file mode 100644 index 000000000..fa83908e6 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2018-parsing.stderr @@ -0,0 +1,26 @@ +error: no rules expected the token `r#async` + --> $DIR/edition-keywords-2015-2018-parsing.rs:16:31 + | +LL | r#async = consumes_async!(r#async); + | ^^^^^^^ no rules expected this token in macro call + | +note: while trying to match `async` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6 + | +LL | (async) => (1) + | ^^^^^ + +error: no rules expected the token `async` + --> $DIR/edition-keywords-2015-2018-parsing.rs:17:35 + | +LL | r#async = consumes_async_raw!(async); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match `r#async` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:22:6 + | +LL | (r#async) => (1) + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/editions/edition-keywords-2015-2018.rs b/tests/ui/editions/edition-keywords-2015-2018.rs new file mode 100644 index 000000000..8c3397c95 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2015-2018.rs @@ -0,0 +1,36 @@ +// run-pass + +#![allow(unused_mut)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +// edition:2015 +// aux-build:edition-kw-macro-2018.rs + +#[macro_use] +extern crate edition_kw_macro_2018; + +pub fn check_async() { + let mut async = 1; // OK + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + // r#async = consumes_async!(r#async); // ERROR, not a match + // r#async = consumes_async_raw!(async); // ERROR, not a match + r#async = consumes_async_raw!(r#async); // OK + + if passes_ident!(async) == 1 {} // OK + if passes_ident!(r#async) == 1 {} // OK + // one_async::async(); // ERROR, unresolved name + // one_async::r#async(); // ERROR, unresolved name + two_async::async(); // OK + two_async::r#async(); // OK +} + +mod one_async { + // produces_async! {} // ERROR, reserved +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2018-2015-expansion.rs b/tests/ui/editions/edition-keywords-2018-2015-expansion.rs new file mode 100644 index 000000000..707d8e95c --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2015-expansion.rs @@ -0,0 +1,17 @@ +// edition:2018 +// aux-build:edition-kw-macro-2015.rs +// check-pass + +#![allow(keyword_idents)] + +#[macro_use] +extern crate edition_kw_macro_2015; + +mod one_async { + produces_async! {} // OK +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs new file mode 100644 index 000000000..d5ed9fb9a --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -0,0 +1,30 @@ +// edition:2018 +// aux-build:edition-kw-macro-2015.rs + +#![feature(async_closure)] + +fn main() {} + +#[macro_use] +extern crate edition_kw_macro_2015; + +mod module { + pub fn r#async() {} +} + +pub fn check_async() { + let mut async = 1; //~ ERROR expected identifier, found keyword `async` + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async_raw!(r#async); // OK + + if passes_ident!(async) == 1 {} + if passes_ident!(r#async) == 1 {} // OK + module::async(); //~ ERROR expected identifier, found keyword `async` + module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr new file mode 100644 index 000000000..1a4a94e97 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -0,0 +1,68 @@ +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:16:13 + | +LL | let mut async = 1; + | ^^^^^ expected identifier, found keyword + | +help: escape `async` to use it as an identifier + | +LL | let mut r#async = 1; + | ++ + +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13 + | +LL | module::async(); + | ^^^^^ expected identifier, found keyword + | +help: escape `async` to use it as an identifier + | +LL | module::r#async(); + | ++ + +error: no rules expected the token `r#async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31 + | +LL | r#async = consumes_async!(r#async); + | ^^^^^^^ no rules expected this token in macro call + | +note: while trying to match `async` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6 + | +LL | (async) => (1) + | ^^^^^ + +error: no rules expected the token `async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35 + | +LL | r#async = consumes_async_raw!(async); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match `r#async` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:22:6 + | +LL | (r#async) => (1) + | ^^^^^^^ + +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:27:23 + | +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` + | + ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8 + | +LL | if passes_ident!(async) == 1 {} + | -------------------- in this macro invocation + +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/editions/edition-keywords-2018-2015.rs b/tests/ui/editions/edition-keywords-2018-2015.rs new file mode 100644 index 000000000..2cb2dfb18 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2015.rs @@ -0,0 +1,34 @@ +// run-pass + +#![allow(unused_assignments)] +// edition:2018 +// aux-build:edition-kw-macro-2015.rs + +#[macro_use] +extern crate edition_kw_macro_2015; + +pub fn check_async() { + // let mut async = 1; // ERROR, reserved + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + // r#async = consumes_async!(r#async); // ERROR, not a match + // r#async = consumes_async_raw!(async); // ERROR, not a match + r#async = consumes_async_raw!(r#async); // OK + + // if passes_ident!(async) == 1 {} // ERROR, reserved + if passes_ident!(r#async) == 1 {} // OK + // one_async::async(); // ERROR, reserved + one_async::r#async(); // OK + // two_async::async(); // ERROR, reserved + two_async::r#async(); // OK +} + +mod one_async { + produces_async! {} // OK +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2018-2018-expansion.rs b/tests/ui/editions/edition-keywords-2018-2018-expansion.rs new file mode 100644 index 000000000..a8e69fed6 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2018-expansion.rs @@ -0,0 +1,14 @@ +// edition:2018 +// aux-build:edition-kw-macro-2018.rs + +#[macro_use] +extern crate edition_kw_macro_2018; + +mod one_async { + produces_async! {} //~ ERROR expected identifier, found keyword `async` +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr b/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr new file mode 100644 index 000000000..69f275746 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2018-expansion.rs:8:5 + | +LL | produces_async! {} + | ^^^^^^^^^^^^^^^^^^ expected identifier, found keyword + | + = note: this error originates in the macro `produces_async` (in Nightly builds, run with -Z macro-backtrace for more info) +help: escape `async` to use it as an identifier + --> $DIR/auxiliary/edition-kw-macro-2018.rs:7:19 + | +LL | () => (pub fn r#async() {}) + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs new file mode 100644 index 000000000..044ab249f --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -0,0 +1,30 @@ +// edition:2018 +// aux-build:edition-kw-macro-2018.rs + +#![feature(async_closure)] + +fn main() {} + +#[macro_use] +extern crate edition_kw_macro_2018; + +mod module { + pub fn r#async() {} +} + +pub fn check_async() { + let mut async = 1; //~ ERROR expected identifier, found keyword `async` + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` + r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` + r#async = consumes_async_raw!(r#async); // OK + + if passes_ident!(async) == 1 {} + if passes_ident!(r#async) == 1 {} // OK + module::async(); //~ ERROR expected identifier, found keyword `async` + module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr new file mode 100644 index 000000000..19eb7ac98 --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -0,0 +1,68 @@ +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:16:13 + | +LL | let mut async = 1; + | ^^^^^ expected identifier, found keyword + | +help: escape `async` to use it as an identifier + | +LL | let mut r#async = 1; + | ++ + +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:26:13 + | +LL | module::async(); + | ^^^^^ expected identifier, found keyword + | +help: escape `async` to use it as an identifier + | +LL | module::r#async(); + | ++ + +error: no rules expected the token `r#async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:20:31 + | +LL | r#async = consumes_async!(r#async); + | ^^^^^^^ no rules expected this token in macro call + | +note: while trying to match `async` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6 + | +LL | (async) => (1) + | ^^^^^ + +error: no rules expected the token `async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:21:35 + | +LL | r#async = consumes_async_raw!(async); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match `r#async` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:22:6 + | +LL | (r#async) => (1) + | ^^^^^^^ + +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:27:23 + | +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` + | + ::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8 + | +LL | if passes_ident!(async) == 1 {} + | -------------------- in this macro invocation + +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2018-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/editions/edition-keywords-2018-2018.rs b/tests/ui/editions/edition-keywords-2018-2018.rs new file mode 100644 index 000000000..5043440aa --- /dev/null +++ b/tests/ui/editions/edition-keywords-2018-2018.rs @@ -0,0 +1,34 @@ +// run-pass + +#![allow(unused_assignments)] +// edition:2018 +// aux-build:edition-kw-macro-2018.rs + +#[macro_use] +extern crate edition_kw_macro_2018; + +pub fn check_async() { + // let mut async = 1; // ERROR, reserved + let mut r#async = 1; // OK + + r#async = consumes_async!(async); // OK + // r#async = consumes_async!(r#async); // ERROR, not a match + // r#async = consumes_async_raw!(async); // ERROR, not a match + r#async = consumes_async_raw!(r#async); // OK + + // if passes_ident!(async) == 1 {} // ERROR, reserved + if passes_ident!(r#async) == 1 {} // OK + // one_async::async(); // ERROR, reserved + // one_async::r#async(); // ERROR, unresolved name + // two_async::async(); // ERROR, reserved + two_async::r#async(); // OK +} + +mod one_async { + // produces_async! {} // ERROR, reserved +} +mod two_async { + produces_async_raw! {} // OK +} + +fn main() {} diff --git a/tests/ui/editions/edition-raw-pointer-method-2015.rs b/tests/ui/editions/edition-raw-pointer-method-2015.rs new file mode 100644 index 000000000..fcfe493c1 --- /dev/null +++ b/tests/ui/editions/edition-raw-pointer-method-2015.rs @@ -0,0 +1,12 @@ +// edition:2015 + +// tests that editions work with the tyvar warning-turned-error + +#[deny(warnings)] +fn main() { + let x = 0; + let y = &x as *const _; + let _ = y.is_null(); + //~^ error: type annotations needed [tyvar_behind_raw_pointer] + //~^^ warning: this is accepted in the current edition +} diff --git a/tests/ui/editions/edition-raw-pointer-method-2015.stderr b/tests/ui/editions/edition-raw-pointer-method-2015.stderr new file mode 100644 index 000000000..612dd17e7 --- /dev/null +++ b/tests/ui/editions/edition-raw-pointer-method-2015.stderr @@ -0,0 +1,17 @@ +error: type annotations needed + --> $DIR/edition-raw-pointer-method-2015.rs:9:15 + | +LL | let _ = y.is_null(); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #46906 +note: the lint level is defined here + --> $DIR/edition-raw-pointer-method-2015.rs:5:8 + | +LL | #[deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(tyvar_behind_raw_pointer)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.rs b/tests/ui/editions/edition-raw-pointer-method-2018.rs new file mode 100644 index 000000000..af0b2d6bd --- /dev/null +++ b/tests/ui/editions/edition-raw-pointer-method-2018.rs @@ -0,0 +1,11 @@ +// edition:2018 + +// tests that editions work with the tyvar warning-turned-error + +#[deny(warnings)] +fn main() { + let x = 0; + let y = &x as *const _; + let _ = y.is_null(); + //~^ error: the type of this value must be known to call a method on a raw pointer on it [E0699] +} diff --git a/tests/ui/editions/edition-raw-pointer-method-2018.stderr b/tests/ui/editions/edition-raw-pointer-method-2018.stderr new file mode 100644 index 000000000..23452495b --- /dev/null +++ b/tests/ui/editions/edition-raw-pointer-method-2018.stderr @@ -0,0 +1,9 @@ +error[E0699]: the type of this value must be known to call a method on a raw pointer on it + --> $DIR/edition-raw-pointer-method-2018.rs:9:15 + | +LL | let _ = y.is_null(); + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0699`. diff --git a/tests/ui/editions/epoch-gate-feature.rs b/tests/ui/editions/epoch-gate-feature.rs new file mode 100644 index 000000000..5f7feb534 --- /dev/null +++ b/tests/ui/editions/epoch-gate-feature.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_variables)] +// Checks if the correct registers are being used to pass arguments +// when the sysv64 ABI is specified. + +#![feature(rust_2018_preview)] + +pub trait Foo {} + +// should compile without the dyn trait feature flag +fn foo(x: &dyn Foo) {} + +pub fn main() {} diff --git a/tests/ui/elide-errors-on-mismatched-tuple.rs b/tests/ui/elide-errors-on-mismatched-tuple.rs new file mode 100644 index 000000000..7d87b0a77 --- /dev/null +++ b/tests/ui/elide-errors-on-mismatched-tuple.rs @@ -0,0 +1,18 @@ +// Hide irrelevant E0277 errors (#50333) + +trait T {} + +struct A; +impl T for A {} +impl A { + fn new() -> Self { + Self {} + } +} + +fn main() { + let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three + //~^ ERROR mismatched types + let ts: Vec<&dyn T> = vec![&a, &b, &c]; + // There is no E0277 error above, as `a`, `b` and `c` are `TyErr` +} diff --git a/tests/ui/elide-errors-on-mismatched-tuple.stderr b/tests/ui/elide-errors-on-mismatched-tuple.stderr new file mode 100644 index 000000000..e0537ff6f --- /dev/null +++ b/tests/ui/elide-errors-on-mismatched-tuple.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/elide-errors-on-mismatched-tuple.rs:14:9 + | +LL | let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three + | ^^^^^^^^^ -------------------- this expression has type `(A, A)` + | | + | expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `(A, A)` + found tuple `(_, _, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/elided-test.rs b/tests/ui/elided-test.rs new file mode 100644 index 000000000..b3f4446f1 --- /dev/null +++ b/tests/ui/elided-test.rs @@ -0,0 +1,7 @@ +// error-pattern: `main` function not found + +// Since we're not compiling a test runner this function should be elided +// and the build will fail because main doesn't exist +#[test] +fn main() { +} diff --git a/tests/ui/elided-test.stderr b/tests/ui/elided-test.stderr new file mode 100644 index 000000000..c74c307c4 --- /dev/null +++ b/tests/ui/elided-test.stderr @@ -0,0 +1,9 @@ +error[E0601]: `main` function not found in crate `elided_test` + --> $DIR/elided-test.rs:7:2 + | +LL | } + | ^ consider adding a `main` function to `$DIR/elided-test.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/else-if.rs b/tests/ui/else-if.rs new file mode 100644 index 000000000..77d8d1abf --- /dev/null +++ b/tests/ui/else-if.rs @@ -0,0 +1,20 @@ +// run-pass + +pub fn main() { + if 1 == 2 { + assert!((false)); + } else if 2 == 3 { + assert!((false)); + } else if 3 == 4 { assert!((false)); } else { assert!((true)); } + if 1 == 2 { assert!((false)); } else if 2 == 2 { assert!((true)); } + if 1 == 2 { + assert!((false)); + } else if 2 == 2 { + if 1 == 1 { + assert!((true)); + } else { if 2 == 1 { assert!((false)); } else { assert!((false)); } } + } + if 1 == 2 { + assert!((false)); + } else { if 1 == 2 { assert!((false)); } else { assert!((true)); } } +} diff --git a/tests/ui/empty-allocation-non-null.rs b/tests/ui/empty-allocation-non-null.rs new file mode 100644 index 000000000..925bddd5e --- /dev/null +++ b/tests/ui/empty-allocation-non-null.rs @@ -0,0 +1,14 @@ +// run-pass + +pub fn main() { + assert!(Some(Box::new(())).is_some()); + + let xs: Box<[()]> = Box::<[(); 0]>::new([]); + assert!(Some(xs).is_some()); + + struct Foo; + assert!(Some(Box::new(Foo)).is_some()); + + let ys: Box<[Foo]> = Box::<[Foo; 0]>::new([]); + assert!(Some(ys).is_some()); +} diff --git a/tests/ui/empty-allocation-rvalue-non-null.rs b/tests/ui/empty-allocation-rvalue-non-null.rs new file mode 100644 index 000000000..2f5a5c4bb --- /dev/null +++ b/tests/ui/empty-allocation-rvalue-non-null.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +pub fn main() { + let x = *Box::new(()); +} diff --git a/tests/ui/empty-type-parameter-list.rs b/tests/ui/empty-type-parameter-list.rs new file mode 100644 index 000000000..e168cd03b --- /dev/null +++ b/tests/ui/empty-type-parameter-list.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that empty type parameter list (<>) is synonymous with +// no type parameters at all + +struct S<>; +trait T<> {} +enum E<> { V } +impl<> T<> for S<> {} +impl T for E {} +fn foo<>() {} +fn bar() {} + +fn main() { + let _ = S; + let _ = S::<>; + let _ = E::V; + let _ = E::<>::V; + foo(); + foo::<>(); + + // Test that we can supply <> to non generic things + bar::<>(); + let _: i32<>; +} diff --git a/tests/ui/empty/auxiliary/empty-struct.rs b/tests/ui/empty/auxiliary/empty-struct.rs new file mode 100644 index 000000000..3fb40f6bf --- /dev/null +++ b/tests/ui/empty/auxiliary/empty-struct.rs @@ -0,0 +1,9 @@ +pub struct XEmpty1 {} +pub struct XEmpty2; +pub struct XEmpty6(); + +pub enum XE { + XEmpty3 {}, + XEmpty4, + XEmpty5(), +} diff --git a/tests/ui/empty/auxiliary/two_macros.rs b/tests/ui/empty/auxiliary/two_macros.rs new file mode 100644 index 000000000..2330c75c8 --- /dev/null +++ b/tests/ui/empty/auxiliary/two_macros.rs @@ -0,0 +1,5 @@ +#[macro_export] +macro_rules! macro_one { () => ("one") } + +#[macro_export] +macro_rules! macro_two { () => ("two") } diff --git a/tests/ui/empty/empty-attributes.rs b/tests/ui/empty/empty-attributes.rs new file mode 100644 index 000000000..d319227b2 --- /dev/null +++ b/tests/ui/empty/empty-attributes.rs @@ -0,0 +1,17 @@ +#![feature(lint_reasons)] + +#![deny(unused_attributes)] +#![allow()] //~ ERROR unused attribute +#![expect()] //~ ERROR unused attribute +#![warn()] //~ ERROR unused attribute +#![deny()] //~ ERROR unused attribute +#![forbid()] //~ ERROR unused attribute +#![feature()] //~ ERROR unused attribute + +#[repr()] //~ ERROR unused attribute +pub struct S; + +#[target_feature()] //~ ERROR unused attribute +pub unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/empty/empty-attributes.stderr b/tests/ui/empty/empty-attributes.stderr new file mode 100644 index 000000000..01d0d5a6b --- /dev/null +++ b/tests/ui/empty/empty-attributes.stderr @@ -0,0 +1,71 @@ +error: unused attribute + --> $DIR/empty-attributes.rs:11:1 + | +LL | #[repr()] + | ^^^^^^^^^ help: remove this attribute + | + = note: attribute `repr` with an empty list has no effect +note: the lint level is defined here + --> $DIR/empty-attributes.rs:3:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/empty-attributes.rs:14:1 + | +LL | #[target_feature()] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `target_feature` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:4:1 + | +LL | #![allow()] + | ^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:5:1 + | +LL | #![expect()] + | ^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `expect` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:6:1 + | +LL | #![warn()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: attribute `warn` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:7:1 + | +LL | #![deny()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: attribute `deny` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:8:1 + | +LL | #![forbid()] + | ^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `forbid` with an empty list has no effect + +error: unused attribute + --> $DIR/empty-attributes.rs:9:1 + | +LL | #![feature()] + | ^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `feature` with an empty list has no effect + +error: aborting due to 8 previous errors + diff --git a/tests/ui/empty/empty-comment.rs b/tests/ui/empty/empty-comment.rs new file mode 100644 index 000000000..174274d28 --- /dev/null +++ b/tests/ui/empty/empty-comment.rs @@ -0,0 +1,11 @@ +// `/**/` was previously regarded as a doc comment because it starts with `/**` and ends with `*/`. +// This could break some internal logic that assumes the length of a doc comment is at least 5, +// leading to an ICE. + +macro_rules! one_arg_macro { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); +} + +fn main() { + one_arg_macro!(/**/); //~ ERROR unexpected end +} diff --git a/tests/ui/empty/empty-comment.stderr b/tests/ui/empty/empty-comment.stderr new file mode 100644 index 000000000..7cc8d8fe9 --- /dev/null +++ b/tests/ui/empty/empty-comment.stderr @@ -0,0 +1,17 @@ +error: unexpected end of macro invocation + --> $DIR/empty-comment.rs:10:5 + | +LL | macro_rules! one_arg_macro { + | -------------------------- when calling this macro +... +LL | one_arg_macro!(/**/); + | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$fmt:expr` + --> $DIR/empty-comment.rs:6:6 + | +LL | ($fmt:expr) => (print!(concat!($fmt, "\n"))); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/empty/empty-linkname.rs b/tests/ui/empty/empty-linkname.rs new file mode 100644 index 000000000..7113d913c --- /dev/null +++ b/tests/ui/empty/empty-linkname.rs @@ -0,0 +1,4 @@ +#[link(name = "")] //~ ERROR: link name must not be empty +extern "C" {} + +fn main() {} diff --git a/tests/ui/empty/empty-linkname.stderr b/tests/ui/empty/empty-linkname.stderr new file mode 100644 index 000000000..adcf3670d --- /dev/null +++ b/tests/ui/empty/empty-linkname.stderr @@ -0,0 +1,9 @@ +error[E0454]: link name must not be empty + --> $DIR/empty-linkname.rs:1:15 + | +LL | #[link(name = "")] + | ^^ empty link name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0454`. diff --git a/tests/ui/empty/empty-macro-use.rs b/tests/ui/empty/empty-macro-use.rs new file mode 100644 index 000000000..846004e66 --- /dev/null +++ b/tests/ui/empty/empty-macro-use.rs @@ -0,0 +1,9 @@ +// aux-build:two_macros.rs + +#[macro_use()] +extern crate two_macros; + +pub fn main() { + macro_two!(); + //~^ ERROR cannot find macro +} diff --git a/tests/ui/empty/empty-macro-use.stderr b/tests/ui/empty/empty-macro-use.stderr new file mode 100644 index 000000000..e0b3b8685 --- /dev/null +++ b/tests/ui/empty/empty-macro-use.stderr @@ -0,0 +1,11 @@ +error: cannot find macro `macro_two` in this scope + --> $DIR/empty-macro-use.rs:7:5 + | +LL | macro_two!(); + | ^^^^^^^^^ + | + = help: consider importing this macro: + two_macros::macro_two + +error: aborting due to previous error + diff --git a/tests/ui/empty/empty-never-array.rs b/tests/ui/empty/empty-never-array.rs new file mode 100644 index 000000000..fd9334610 --- /dev/null +++ b/tests/ui/empty/empty-never-array.rs @@ -0,0 +1,18 @@ +#![feature(never_type)] + +enum Helper { + T(T, [!; 0]), + #[allow(dead_code)] + U(U), +} + +fn transmute(t: T) -> U { + let Helper::U(u) = Helper::T(t, []); + //~^ ERROR refutable pattern in local binding + //~| `Helper::T(_, _)` not covered + u +} + +fn main() { + println!("{:?}", transmute::<&str, (*const u8, u64)>("type safety")); +} diff --git a/tests/ui/empty/empty-never-array.stderr b/tests/ui/empty/empty-never-array.stderr new file mode 100644 index 000000000..a488e484b --- /dev/null +++ b/tests/ui/empty/empty-never-array.stderr @@ -0,0 +1,24 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/empty-never-array.rs:10:9 + | +LL | let Helper::U(u) = Helper::T(t, []); + | ^^^^^^^^^^^^ pattern `Helper::T(_, _)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Helper` defined here + --> $DIR/empty-never-array.rs:3:6 + | +LL | enum Helper { + | ^^^^^^ +LL | T(T, [!; 0]), + | - not covered + = note: the matched value is of type `Helper` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Helper::U(u) = Helper::T(t, []) else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/empty/empty-struct-braces-expr.rs b/tests/ui/empty/empty-struct-braces-expr.rs new file mode 100644 index 000000000..2aab3e777 --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-expr.rs @@ -0,0 +1,29 @@ +// Can't use empty braced struct as constant or constructor function + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty1 {} + +enum E { + Empty3 {} +} + +fn main() { + let e1 = Empty1; //~ ERROR expected value, found struct `Empty1` + let e1 = Empty1(); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `Empty1` + let e3 = E::Empty3; //~ ERROR expected value, found struct variant `E::Empty3` + let e3 = E::Empty3(); + //~^ ERROR expected value, found struct variant `E::Empty3` + + let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1` + let xe1 = XEmpty1(); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `XEmpty1` + let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for enum + let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for enum + + XE::Empty1 {}; //~ ERROR no variant named `Empty1` found for enum `empty_struct::XE` +} diff --git a/tests/ui/empty/empty-struct-braces-expr.stderr b/tests/ui/empty/empty-struct-braces-expr.stderr new file mode 100644 index 000000000..0e580aede --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-expr.stderr @@ -0,0 +1,130 @@ +error[E0423]: expected value, found struct `Empty1` + --> $DIR/empty-struct-braces-expr.rs:15:14 + | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... +LL | let e1 = Empty1; + | ^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:2:1 + | +LL | pub struct XEmpty2; + | ------------------ similarly named unit struct `XEmpty2` defined here + | +help: use struct literal syntax instead + | +LL | let e1 = Empty1 {}; + | ~~~~~~~~~ +help: a unit struct with a similar name exists + | +LL | let e1 = XEmpty2; + | ~~~~~~~ + +error[E0423]: expected value, found struct `XEmpty1` + --> $DIR/empty-struct-braces-expr.rs:22:15 + | +LL | let xe1 = XEmpty1; + | ^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:1:1 + | +LL | pub struct XEmpty1 {} + | ------------------ `XEmpty1` defined here +LL | pub struct XEmpty2; + | ------------------ similarly named unit struct `XEmpty2` defined here + | +help: use struct literal syntax instead + | +LL | let xe1 = XEmpty1 {}; + | ~~~~~~~~~~ +help: a unit struct with a similar name exists + | +LL | let xe1 = XEmpty2; + | ~~~~~~~ + +error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1` + --> $DIR/empty-struct-braces-expr.rs:16:14 + | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... +LL | let e1 = Empty1(); + | ^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:2:1 + | +LL | pub struct XEmpty2; + | ------------------ similarly named unit struct `XEmpty2` defined here + | +help: use struct literal syntax instead + | +LL | let e1 = Empty1 {}; + | ~~~~~~~~~ +help: a unit struct with a similar name exists + | +LL | let e1 = XEmpty2(); + | ~~~~~~~ + +error[E0533]: expected value, found struct variant `E::Empty3` + --> $DIR/empty-struct-braces-expr.rs:18:14 + | +LL | let e3 = E::Empty3; + | ^^^^^^^^^ not a value + +error[E0533]: expected value, found struct variant `E::Empty3` + --> $DIR/empty-struct-braces-expr.rs:19:14 + | +LL | let e3 = E::Empty3(); + | ^^^^^^^^^ not a value + +error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1` + --> $DIR/empty-struct-braces-expr.rs:23:15 + | +LL | let xe1 = XEmpty1(); + | ^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:1:1 + | +LL | pub struct XEmpty1 {} + | ------------------ `XEmpty1` defined here +LL | pub struct XEmpty2; + | ------------------ similarly named unit struct `XEmpty2` defined here + | +help: use struct literal syntax instead + | +LL | let xe1 = XEmpty1 {}; + | ~~~~~~~~~~ +help: a unit struct with a similar name exists + | +LL | let xe1 = XEmpty2(); + | ~~~~~~~ + +error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope + --> $DIR/empty-struct-braces-expr.rs:25:19 + | +LL | let xe3 = XE::Empty3; + | ^^^^^^ + | | + | variant or associated item not found in `XE` + | help: there is a variant with a similar name: `XEmpty3` + +error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope + --> $DIR/empty-struct-braces-expr.rs:26:19 + | +LL | let xe3 = XE::Empty3(); + | ^^^^^^ + | | + | variant or associated item not found in `XE` + | help: there is a variant with a similar name: `XEmpty3` + +error[E0599]: no variant named `Empty1` found for enum `empty_struct::XE` + --> $DIR/empty-struct-braces-expr.rs:28:9 + | +LL | XE::Empty1 {}; + | ^^^^^^ help: there is a variant with a similar name: `XEmpty3` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0423, E0533, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/empty/empty-struct-braces-pat-1.rs b/tests/ui/empty/empty-struct-braces-pat-1.rs new file mode 100644 index 000000000..9bed93f9c --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-pat-1.rs @@ -0,0 +1,34 @@ +// Can't use empty braced struct as constant pattern + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty1 {} + +enum E { + Empty3 {} +} + +fn main() { + let e1 = Empty1 {}; + let e3 = E::Empty3 {}; + let xe1 = XEmpty1 {}; + let xe3 = XE::XEmpty3 {}; + + match e1 { + Empty1 => () // Not an error, `Empty1` is interpreted as a new binding + } + match e3 { + E::Empty3 => () + //~^ ERROR expected unit struct, unit variant or constant, found struct variant `E::Empty3` + } + match xe1 { + XEmpty1 => () // Not an error, `XEmpty1` is interpreted as a new binding + } + match xe3 { + XE::XEmpty3 => () + //~^ ERROR expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3` + } +} diff --git a/tests/ui/empty/empty-struct-braces-pat-1.stderr b/tests/ui/empty/empty-struct-braces-pat-1.stderr new file mode 100644 index 000000000..14e09fc27 --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-pat-1.stderr @@ -0,0 +1,15 @@ +error[E0533]: expected unit struct, unit variant or constant, found struct variant `E::Empty3` + --> $DIR/empty-struct-braces-pat-1.rs:24:9 + | +LL | E::Empty3 => () + | ^^^^^^^^^ not a unit struct, unit variant or constant + +error[E0533]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3` + --> $DIR/empty-struct-braces-pat-1.rs:31:9 + | +LL | XE::XEmpty3 => () + | ^^^^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/empty/empty-struct-braces-pat-2.rs b/tests/ui/empty/empty-struct-braces-pat-2.rs new file mode 100644 index 000000000..cfe4641f3 --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-pat-2.rs @@ -0,0 +1,26 @@ +// Can't use empty braced struct as enum pattern + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty1 {} + +fn main() { + let e1 = Empty1 {}; + let xe1 = XEmpty1 {}; + + match e1 { + Empty1() => () //~ ERROR expected tuple struct or tuple variant, found struct `Empty1` + } + match xe1 { + XEmpty1() => () //~ ERROR expected tuple struct or tuple variant, found struct `XEmpty1` + } + match e1 { + Empty1(..) => () //~ ERROR expected tuple struct or tuple variant, found struct `Empty1` + } + match xe1 { + XEmpty1(..) => () //~ ERROR expected tuple struct or tuple variant, found struct `XEmpty1` + } +} diff --git a/tests/ui/empty/empty-struct-braces-pat-2.stderr b/tests/ui/empty/empty-struct-braces-pat-2.stderr new file mode 100644 index 000000000..7fb5cb203 --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-pat-2.stderr @@ -0,0 +1,95 @@ +error[E0532]: expected tuple struct or tuple variant, found struct `Empty1` + --> $DIR/empty-struct-braces-pat-2.rs:15:9 + | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... +LL | Empty1() => () + | ^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 + | +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use struct pattern syntax instead + | +LL | Empty1 {} => () + | ~~~~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6() => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1` + --> $DIR/empty-struct-braces-pat-2.rs:18:9 + | +LL | XEmpty1() => () + | ^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:1:1 + | +LL | pub struct XEmpty1 {} + | ------------------ `XEmpty1` defined here +LL | pub struct XEmpty2; +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use struct pattern syntax instead + | +LL | XEmpty1 {} => () + | ~~~~~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6() => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found struct `Empty1` + --> $DIR/empty-struct-braces-pat-2.rs:21:9 + | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... +LL | Empty1(..) => () + | ^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 + | +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use struct pattern syntax instead + | +LL | Empty1 {} => () + | ~~~~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6(..) => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found struct `XEmpty1` + --> $DIR/empty-struct-braces-pat-2.rs:24:9 + | +LL | XEmpty1(..) => () + | ^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:1:1 + | +LL | pub struct XEmpty1 {} + | ------------------ `XEmpty1` defined here +LL | pub struct XEmpty2; +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use struct pattern syntax instead + | +LL | XEmpty1 {} => () + | ~~~~~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6(..) => () + | ~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/empty/empty-struct-braces-pat-3.rs b/tests/ui/empty/empty-struct-braces-pat-3.rs new file mode 100644 index 000000000..54d547eef --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-pat-3.rs @@ -0,0 +1,32 @@ +// Can't use empty braced struct as enum pattern + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +enum E { + Empty3 {} +} + +fn main() { + let e3 = E::Empty3 {}; + let xe3 = XE::XEmpty3 {}; + + match e3 { + E::Empty3() => () + //~^ ERROR expected tuple struct or tuple variant, found struct variant `E::Empty3` + } + match xe3 { + XE::XEmpty3() => () + //~^ ERROR expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` + } + match e3 { + E::Empty3(..) => () + //~^ ERROR expected tuple struct or tuple variant, found struct variant `E::Empty3` + } + match xe3 { + XE::XEmpty3(..) => () + //~^ ERROR expected tuple struct or tuple variant, found struct variant `XE::XEmpty3 + } +} diff --git a/tests/ui/empty/empty-struct-braces-pat-3.stderr b/tests/ui/empty/empty-struct-braces-pat-3.stderr new file mode 100644 index 000000000..00c8b12e6 --- /dev/null +++ b/tests/ui/empty/empty-struct-braces-pat-3.stderr @@ -0,0 +1,27 @@ +error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3` + --> $DIR/empty-struct-braces-pat-3.rs:17:9 + | +LL | E::Empty3() => () + | ^^^^^^^^^^^ not a tuple struct or tuple variant + +error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` + --> $DIR/empty-struct-braces-pat-3.rs:21:9 + | +LL | XE::XEmpty3() => () + | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3` + --> $DIR/empty-struct-braces-pat-3.rs:25:9 + | +LL | E::Empty3(..) => () + | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` + --> $DIR/empty-struct-braces-pat-3.rs:29:9 + | +LL | XE::XEmpty3(..) => () + | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/empty/empty-struct-tuple-pat.rs b/tests/ui/empty/empty-struct-tuple-pat.rs new file mode 100644 index 000000000..47da8a306 --- /dev/null +++ b/tests/ui/empty/empty-struct-tuple-pat.rs @@ -0,0 +1,37 @@ +// Can't use unit struct as enum pattern + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty2(); + +enum E { + Empty4() +} + +// remove attribute after warning cycle and promoting warnings to errors +fn main() { + let e2 = Empty2(); + let e4 = E::Empty4(); + let xe6 = XEmpty6(); + let xe5 = XE::XEmpty5(); + + match e2 { + Empty2 => () //~ ERROR match bindings cannot shadow tuple structs + } + match xe6 { + XEmpty6 => () //~ ERROR match bindings cannot shadow tuple structs + } + + match e4 { + E::Empty4 => () + //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `E::Empty4` + } + match xe5 { + XE::XEmpty5 => (), + //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `XE::XEmpty5` + _ => {}, + } +} diff --git a/tests/ui/empty/empty-struct-tuple-pat.stderr b/tests/ui/empty/empty-struct-tuple-pat.stderr new file mode 100644 index 000000000..8d0f75d20 --- /dev/null +++ b/tests/ui/empty/empty-struct-tuple-pat.stderr @@ -0,0 +1,59 @@ +error[E0530]: match bindings cannot shadow tuple structs + --> $DIR/empty-struct-tuple-pat.rs:22:9 + | +LL | struct Empty2(); + | ---------------- the tuple struct `Empty2` is defined here +... +LL | Empty2 => () + | ^^^^^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `Empty2(..)` + +error[E0530]: match bindings cannot shadow tuple structs + --> $DIR/empty-struct-tuple-pat.rs:25:9 + | +LL | use empty_struct::*; + | --------------- the tuple struct `XEmpty6` is imported here +... +LL | XEmpty6 => () + | ^^^^^^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `XEmpty6(..)` + +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::Empty4` + --> $DIR/empty-struct-tuple-pat.rs:29:9 + | +LL | Empty4() + | -------- `E::Empty4` defined here +... +LL | E::Empty4 => () + | ^^^^^^^^^ help: use the tuple variant pattern syntax instead: `E::Empty4()` + +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `XE::XEmpty5` + --> $DIR/empty-struct-tuple-pat.rs:33:9 + | +LL | XE::XEmpty5 => (), + | ^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:7:5 + | +LL | XEmpty4, + | ------- similarly named unit variant `XEmpty4` defined here +LL | XEmpty5(), + | ------- `XE::XEmpty5` defined here + | +help: use the tuple variant pattern syntax instead + | +LL | XE::XEmpty5(/* fields */) => (), + | ~~~~~~~~~~~~~~~~~~~~~~~~~ +help: a unit variant with a similar name exists + | +LL | XE::XEmpty4 => (), + | ~~~~~~~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0530, E0532. +For more information about an error, try `rustc --explain E0530`. diff --git a/tests/ui/empty/empty-struct-unit-expr.rs b/tests/ui/empty/empty-struct-unit-expr.rs new file mode 100644 index 000000000..8f3688a2a --- /dev/null +++ b/tests/ui/empty/empty-struct-unit-expr.rs @@ -0,0 +1,21 @@ +// Can't use unit struct as constructor function + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty2; + +enum E { + Empty4 +} + +fn main() { + let e2 = Empty2(); //~ ERROR expected function, found struct `Empty2` + let e4 = E::Empty4(); + //~^ ERROR expected function, found enum variant `E::Empty4` [E0618] + let xe2 = XEmpty2(); //~ ERROR expected function, found struct `XEmpty2` + let xe4 = XE::XEmpty4(); + //~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618] +} diff --git a/tests/ui/empty/empty-struct-unit-expr.stderr b/tests/ui/empty/empty-struct-unit-expr.stderr new file mode 100644 index 000000000..e97209527 --- /dev/null +++ b/tests/ui/empty/empty-struct-unit-expr.stderr @@ -0,0 +1,65 @@ +error[E0618]: expected function, found struct `Empty2` + --> $DIR/empty-struct-unit-expr.rs:15:14 + | +LL | struct Empty2; + | ------------- struct `Empty2` defined here +... +LL | let e2 = Empty2(); + | ^^^^^^-- + | | + | call expression requires function + | +help: `Empty2` is a unit struct, and does not take parentheses to be constructed + | +LL - let e2 = Empty2(); +LL + let e2 = Empty2; + | + +error[E0618]: expected function, found enum variant `E::Empty4` + --> $DIR/empty-struct-unit-expr.rs:16:14 + | +LL | Empty4 + | ------ enum variant `E::Empty4` defined here +... +LL | let e4 = E::Empty4(); + | ^^^^^^^^^-- + | | + | call expression requires function + | +help: `E::Empty4` is a unit enum variant, and does not take parentheses to be constructed + | +LL - let e4 = E::Empty4(); +LL + let e4 = E::Empty4; + | + +error[E0618]: expected function, found struct `XEmpty2` + --> $DIR/empty-struct-unit-expr.rs:18:15 + | +LL | let xe2 = XEmpty2(); + | ^^^^^^^-- + | | + | call expression requires function + | +help: `XEmpty2` is a unit struct, and does not take parentheses to be constructed + | +LL - let xe2 = XEmpty2(); +LL + let xe2 = XEmpty2; + | + +error[E0618]: expected function, found enum variant `XE::XEmpty4` + --> $DIR/empty-struct-unit-expr.rs:19:15 + | +LL | let xe4 = XE::XEmpty4(); + | ^^^^^^^^^^^-- + | | + | call expression requires function + | +help: `XE::XEmpty4` is a unit enum variant, and does not take parentheses to be constructed + | +LL - let xe4 = XE::XEmpty4(); +LL + let xe4 = XE::XEmpty4; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/empty/empty-struct-unit-pat.rs b/tests/ui/empty/empty-struct-unit-pat.rs new file mode 100644 index 000000000..44a1e9e3d --- /dev/null +++ b/tests/ui/empty/empty-struct-unit-pat.rs @@ -0,0 +1,54 @@ +// Can't use unit struct as tuple struct pattern + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty2; + +enum E { + Empty4 +} + +fn main() { + let e2 = Empty2; + let e4 = E::Empty4; + let xe2 = XEmpty2; + let xe4 = XE::XEmpty4; + + match e2 { + Empty2() => () //~ ERROR expected tuple struct or tuple variant, found unit struct `Empty2` + } + match xe2 { + XEmpty2() => () + //~^ ERROR expected tuple struct or tuple variant, found unit struct `XEmpty2` + } + match e2 { + Empty2(..) => () + //~^ ERROR expected tuple struct or tuple variant, found unit struct `Empty2` + } + match xe2 { + XEmpty2(..) => () + //~^ ERROR expected tuple struct or tuple variant, found unit struct `XEmpty2` + } + + match e4 { + E::Empty4() => () + //~^ ERROR expected tuple struct or tuple variant, found unit variant `E::Empty4` + } + match xe4 { + XE::XEmpty4() => (), + //~^ ERROR expected tuple struct or tuple variant, found unit variant `XE::XEmpty4` + _ => {}, + } + match e4 { + E::Empty4(..) => () + //~^ ERROR expected tuple struct or tuple variant, found unit variant `E::Empty4` + } + match xe4 { + XE::XEmpty4(..) => (), + //~^ ERROR expected tuple struct or tuple variant, found unit variant `XE::XEmpty4` + _ => {}, + } +} diff --git a/tests/ui/empty/empty-struct-unit-pat.stderr b/tests/ui/empty/empty-struct-unit-pat.stderr new file mode 100644 index 000000000..5c0b4cffa --- /dev/null +++ b/tests/ui/empty/empty-struct-unit-pat.stderr @@ -0,0 +1,155 @@ +error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2` + --> $DIR/empty-struct-unit-pat.rs:21:9 + | +LL | struct Empty2; + | -------------- `Empty2` defined here +... +LL | Empty2() => () + | ^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 + | +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use this syntax instead + | +LL | Empty2 => () + | ~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6() => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2` + --> $DIR/empty-struct-unit-pat.rs:24:9 + | +LL | XEmpty2() => () + | ^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:2:1 + | +LL | pub struct XEmpty2; + | ------------------ `XEmpty2` defined here +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use this syntax instead + | +LL | XEmpty2 => () + | ~~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6() => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `Empty2` + --> $DIR/empty-struct-unit-pat.rs:28:9 + | +LL | struct Empty2; + | -------------- `Empty2` defined here +... +LL | Empty2(..) => () + | ^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:3:1 + | +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use this syntax instead + | +LL | Empty2 => () + | ~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6(..) => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `XEmpty2` + --> $DIR/empty-struct-unit-pat.rs:32:9 + | +LL | XEmpty2(..) => () + | ^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:2:1 + | +LL | pub struct XEmpty2; + | ------------------ `XEmpty2` defined here +LL | pub struct XEmpty6(); + | ------------------ similarly named tuple struct `XEmpty6` defined here + | +help: use this syntax instead + | +LL | XEmpty2 => () + | ~~~~~~~ +help: a tuple struct with a similar name exists + | +LL | XEmpty6(..) => () + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4` + --> $DIR/empty-struct-unit-pat.rs:37:9 + | +LL | Empty4 + | ------ `E::Empty4` defined here +... +LL | E::Empty4() => () + | ^^^^^^^^^^^ help: use this syntax instead: `E::Empty4` + +error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4` + --> $DIR/empty-struct-unit-pat.rs:41:9 + | +LL | XE::XEmpty4() => (), + | ^^^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:7:5 + | +LL | XEmpty4, + | ------- `XE::XEmpty4` defined here +LL | XEmpty5(), + | ------- similarly named tuple variant `XEmpty5` defined here + | +help: use this syntax instead + | +LL | XE::XEmpty4 => (), + | ~~~~~~~~~~~ +help: a tuple variant with a similar name exists + | +LL | XE::XEmpty5() => (), + | ~~~~~~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E::Empty4` + --> $DIR/empty-struct-unit-pat.rs:46:9 + | +LL | Empty4 + | ------ `E::Empty4` defined here +... +LL | E::Empty4(..) => () + | ^^^^^^^^^^^^^ help: use this syntax instead: `E::Empty4` + +error[E0532]: expected tuple struct or tuple variant, found unit variant `XE::XEmpty4` + --> $DIR/empty-struct-unit-pat.rs:50:9 + | +LL | XE::XEmpty4(..) => (), + | ^^^^^^^^^^^^^^^ + | + ::: $DIR/auxiliary/empty-struct.rs:7:5 + | +LL | XEmpty4, + | ------- `XE::XEmpty4` defined here +LL | XEmpty5(), + | ------- similarly named tuple variant `XEmpty5` defined here + | +help: use this syntax instead + | +LL | XE::XEmpty4 => (), + | ~~~~~~~~~~~ +help: a tuple variant with a similar name exists + | +LL | XE::XEmpty5(..) => (), + | ~~~~~~~ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/empty/issue-37026.rs b/tests/ui/empty/issue-37026.rs new file mode 100644 index 000000000..fd678a717 --- /dev/null +++ b/tests/ui/empty/issue-37026.rs @@ -0,0 +1,8 @@ +// aux-build:empty-struct.rs + +extern crate empty_struct; + +fn main() { + let empty_struct::XEmpty2 = (); //~ ERROR mismatched types + let empty_struct::XEmpty6(..) = (); //~ ERROR mismatched types +} diff --git a/tests/ui/empty/issue-37026.stderr b/tests/ui/empty/issue-37026.stderr new file mode 100644 index 000000000..48a4a5bca --- /dev/null +++ b/tests/ui/empty/issue-37026.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-37026.rs:6:9 + | +LL | let empty_struct::XEmpty2 = (); + | ^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()` + | | + | expected `()`, found struct `XEmpty2` + +error[E0308]: mismatched types + --> $DIR/issue-37026.rs:7:9 + | +LL | let empty_struct::XEmpty6(..) = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()` + | | + | expected `()`, found struct `XEmpty6` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/empty/no-link.rs b/tests/ui/empty/no-link.rs new file mode 100644 index 000000000..c80e61b45 --- /dev/null +++ b/tests/ui/empty/no-link.rs @@ -0,0 +1,9 @@ +// check-pass +// aux-build:empty-struct.rs + +#[no_link] +extern crate empty_struct; + +fn main() { + empty_struct::XEmpty1 {}; +} diff --git a/tests/ui/empty_global_asm.rs b/tests/ui/empty_global_asm.rs new file mode 100644 index 000000000..af13762d1 --- /dev/null +++ b/tests/ui/empty_global_asm.rs @@ -0,0 +1,8 @@ +// needs-asm-support +// run-pass + +use std::arch::global_asm; + +global_asm!(""); + +fn main() {} diff --git a/tests/ui/entry-point/auxiliary/main_functions.rs b/tests/ui/entry-point/auxiliary/main_functions.rs new file mode 100644 index 000000000..cc7992a42 --- /dev/null +++ b/tests/ui/entry-point/auxiliary/main_functions.rs @@ -0,0 +1 @@ +pub fn boilerplate() {} diff --git a/tests/ui/entry-point/imported_main_conflict.rs b/tests/ui/entry-point/imported_main_conflict.rs new file mode 100644 index 000000000..e8c70b065 --- /dev/null +++ b/tests/ui/entry-point/imported_main_conflict.rs @@ -0,0 +1,7 @@ +#![feature(imported_main)] +//~^ ERROR `main` is ambiguous +mod m1 { pub(crate) fn main() {} } +mod m2 { pub(crate) fn main() {} } + +use m1::*; +use m2::*; diff --git a/tests/ui/entry-point/imported_main_conflict.stderr b/tests/ui/entry-point/imported_main_conflict.stderr new file mode 100644 index 000000000..8fadd0e19 --- /dev/null +++ b/tests/ui/entry-point/imported_main_conflict.stderr @@ -0,0 +1,19 @@ +error[E0659]: `main` is ambiguous + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `main` could refer to the function imported here + --> $DIR/imported_main_conflict.rs:6:5 + | +LL | use m1::*; + | ^^^^^ + = help: consider adding an explicit import of `main` to disambiguate +note: `main` could also refer to the function imported here + --> $DIR/imported_main_conflict.rs:7:5 + | +LL | use m2::*; + | ^^^^^ + = help: consider adding an explicit import of `main` to disambiguate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs new file mode 100644 index 000000000..405d6e2a9 --- /dev/null +++ b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs @@ -0,0 +1,11 @@ +#![feature(imported_main)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] +pub mod foo { + type MainFn = impl Fn(); + + fn bar() {} + pub const BAR: MainFn = bar; +} + +use foo::BAR as main; //~ ERROR `main` function not found in crate diff --git a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr new file mode 100644 index 000000000..fabb6ffb0 --- /dev/null +++ b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr @@ -0,0 +1,11 @@ +error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden` + --> $DIR/imported_main_const_fn_item_type_forbidden.rs:11:22 + | +LL | use foo::BAR as main; + | ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs` + | | + | non-function item at `crate::main` is found + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/entry-point/imported_main_const_forbidden.rs b/tests/ui/entry-point/imported_main_const_forbidden.rs new file mode 100644 index 000000000..1508280c0 --- /dev/null +++ b/tests/ui/entry-point/imported_main_const_forbidden.rs @@ -0,0 +1,6 @@ +#![feature(imported_main)] +pub mod foo { + pub const BAR: usize = 42; +} + +use foo::BAR as main; //~ ERROR `main` function not found in crate diff --git a/tests/ui/entry-point/imported_main_const_forbidden.stderr b/tests/ui/entry-point/imported_main_const_forbidden.stderr new file mode 100644 index 000000000..9d8b40dc3 --- /dev/null +++ b/tests/ui/entry-point/imported_main_const_forbidden.stderr @@ -0,0 +1,11 @@ +error[E0601]: `main` function not found in crate `imported_main_const_forbidden` + --> $DIR/imported_main_const_forbidden.rs:6:22 + | +LL | use foo::BAR as main; + | ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_forbidden.rs` + | | + | non-function item at `crate::main` is found + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/entry-point/imported_main_from_extern_crate.rs b/tests/ui/entry-point/imported_main_from_extern_crate.rs new file mode 100644 index 000000000..4fddfc44a --- /dev/null +++ b/tests/ui/entry-point/imported_main_from_extern_crate.rs @@ -0,0 +1,7 @@ +// run-pass +// aux-build:main_functions.rs + +#![feature(imported_main)] + +extern crate main_functions; +pub use main_functions::boilerplate as main; diff --git a/tests/ui/entry-point/imported_main_from_inner_mod.rs b/tests/ui/entry-point/imported_main_from_inner_mod.rs new file mode 100644 index 000000000..45750072a --- /dev/null +++ b/tests/ui/entry-point/imported_main_from_inner_mod.rs @@ -0,0 +1,9 @@ +// run-pass +#![feature(imported_main)] + +pub mod foo { + pub fn bar() { + println!("Hello world!"); + } +} +use foo::bar as main; diff --git a/tests/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs b/tests/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs new file mode 100644 index 000000000..4762fbb7c --- /dev/null +++ b/tests/ui/entry-point/imported_main_unused_not_trigger_feature_gate.rs @@ -0,0 +1,11 @@ +// check-pass +#![feature(rustc_attrs)] + +#[rustc_main] +fn actual_main() {} + +mod foo { + pub(crate) fn something() {} +} + +use foo::something as main; diff --git a/tests/ui/enum-discriminant/actually_not_an_enum-discriminant.rs b/tests/ui/enum-discriminant/actually_not_an_enum-discriminant.rs new file mode 100644 index 000000000..6a566ab3a --- /dev/null +++ b/tests/ui/enum-discriminant/actually_not_an_enum-discriminant.rs @@ -0,0 +1,49 @@ +// run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::discriminant_value; + +struct Zst; + +struct Struct { + _a: u32, +} + +union Union { + _a: u32, +} + +fn check(v: u8) { + assert_eq!(v, 0); +} + +pub fn generic() +where + for<'a> T: Fn(&'a isize), +{ + let v: Vec = Vec::new(); + let _: u8 = discriminant_value(&v); +} + +fn main() { + // check that we use `u8` as the discriminant value + // for everything that is not an enum. + check(discriminant_value(&true)); + check(discriminant_value(&'a')); + check(discriminant_value(&7)); + check(discriminant_value(&7.0)); + check(discriminant_value(&Zst)); + check(discriminant_value(&Struct { _a: 7 })); + check(discriminant_value(&Union { _a: 7 })); + check(discriminant_value(&[7, 77])); + check(discriminant_value(&(7 as *const ()))); + check(discriminant_value(&(7 as *mut ()))); + check(discriminant_value(&&7)); + check(discriminant_value(&&mut 7)); + check(discriminant_value(&check)); + let fn_ptr: fn(u8) = check; + check(discriminant_value(&fn_ptr)); + let hrtb: for<'a> fn(&'a str) -> &'a str = |x| x; + check(discriminant_value(&hrtb)); + check(discriminant_value(&(7, 77, 777))); +} diff --git a/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs b/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs new file mode 100644 index 000000000..a6e5f70fd --- /dev/null +++ b/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs @@ -0,0 +1,8 @@ +#![crate_type="lib"] + +enum Enum { +//~^ ERROR `#[repr(inttype)]` must be specified + Unit = 1, + Tuple() = 2, + Struct{} = 3, +} diff --git a/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr new file mode 100644 index 000000000..8cee74696 --- /dev/null +++ b/tests/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr @@ -0,0 +1,9 @@ +error[E0732]: `#[repr(inttype)]` must be specified + --> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1 + | +LL | enum Enum { + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0732`. diff --git a/tests/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/tests/ui/enum-discriminant/arbitrary_enum_discriminant.rs new file mode 100644 index 000000000..83e74a6e6 --- /dev/null +++ b/tests/ui/enum-discriminant/arbitrary_enum_discriminant.rs @@ -0,0 +1,43 @@ +// run-pass +#![feature(test)] + +extern crate test; + +use test::black_box; + +#[allow(dead_code)] +#[repr(u8)] +enum Enum { + Unit = 3, + Tuple(u16) = 2, + Struct { + a: u8, + b: u16, + } = 1, +} + +impl Enum { + const unsafe fn tag(&self) -> u8 { + *(self as *const Self as *const u8) + } +} + +fn main() { + const UNIT: Enum = Enum::Unit; + const TUPLE: Enum = Enum::Tuple(5); + const STRUCT: Enum = Enum::Struct{a: 7, b: 11}; + + // Ensure discriminants are correct during runtime execution + assert_eq!(3, unsafe { black_box(UNIT).tag() }); + assert_eq!(2, unsafe { black_box(TUPLE).tag() }); + assert_eq!(1, unsafe { black_box(STRUCT).tag() }); + + // Ensure discriminants are correct during CTFE + const UNIT_TAG: u8 = unsafe { UNIT.tag() }; + const TUPLE_TAG: u8 = unsafe { TUPLE.tag() }; + const STRUCT_TAG: u8 = unsafe { STRUCT.tag() }; + + assert_eq!(3, UNIT_TAG); + assert_eq!(2, TUPLE_TAG); + assert_eq!(1, STRUCT_TAG); +} diff --git a/tests/ui/enum-discriminant/discriminant_size.rs b/tests/ui/enum-discriminant/discriminant_size.rs new file mode 100644 index 000000000..b939a70df --- /dev/null +++ b/tests/ui/enum-discriminant/discriminant_size.rs @@ -0,0 +1,54 @@ +// run-pass +#![feature(core_intrinsics, repr128)] +//~^ WARN the feature `repr128` is incomplete + +use std::intrinsics::discriminant_value; + +enum E1 { + A, + B, +} + +#[repr(i8)] +enum E2 { + A = 7, + B = -2, +} + +#[repr(C)] +enum E3 { + A = 42, + B = 100, +} + +#[repr(i128)] +enum E4 { + A = 0x1223_3445_5667_7889, + B = -0x1223_3445_5667_7889, +} + +fn main() { + let mut target: [isize; 3] = [0, 0, 0]; + target[1] = discriminant_value(&E1::A); + assert_eq!(target, [0, 0, 0]); + target[1] = discriminant_value(&E1::B); + assert_eq!(target, [0, 1, 0]); + + let mut target: [i8; 3] = [0, 0, 0]; + target[1] = discriminant_value(&E2::A); + assert_eq!(target, [0, 7, 0]); + target[1] = discriminant_value(&E2::B); + assert_eq!(target, [0, -2, 0]); + + let mut target: [isize; 3] = [0, 0, 0]; + target[1] = discriminant_value(&E3::A); + assert_eq!(target, [0, 42, 0]); + target[1] = discriminant_value(&E3::B); + assert_eq!(target, [0, 100, 0]); + + let mut target: [i128; 3] = [0, 0, 0]; + target[1] = discriminant_value(&E4::A); + assert_eq!(target, [0, 0x1223_3445_5667_7889, 0]); + target[1] = discriminant_value(&E4::B); + assert_eq!(target, [0, -0x1223_3445_5667_7889, 0]); +} diff --git a/tests/ui/enum-discriminant/discriminant_size.stderr b/tests/ui/enum-discriminant/discriminant_size.stderr new file mode 100644 index 000000000..9b1505b5c --- /dev/null +++ b/tests/ui/enum-discriminant/discriminant_size.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/discriminant_size.rs:2:29 + | +LL | #![feature(core_intrinsics, repr128)] + | ^^^^^^^ + | + = note: see issue #56071 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/enum-discriminant/discriminant_value-wrapper.rs b/tests/ui/enum-discriminant/discriminant_value-wrapper.rs new file mode 100644 index 000000000..8e162d5c4 --- /dev/null +++ b/tests/ui/enum-discriminant/discriminant_value-wrapper.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(enum_intrinsics_non_enums)] + +use std::mem; + +#[allow(unused_tuple_struct_fields)] +enum ADT { + First(u32, u32), + Second(u64) +} + +pub fn main() { + assert!(mem::discriminant(&ADT::First(0,0)) == mem::discriminant(&ADT::First(1,1))); + assert!(mem::discriminant(&ADT::Second(5)) == mem::discriminant(&ADT::Second(6))); + assert!(mem::discriminant(&ADT::First(2,2)) != mem::discriminant(&ADT::Second(2))); + + let _ = mem::discriminant(&10); + let _ = mem::discriminant(&"test"); +} diff --git a/tests/ui/enum-discriminant/discriminant_value.rs b/tests/ui/enum-discriminant/discriminant_value.rs new file mode 100644 index 000000000..f3dfac298 --- /dev/null +++ b/tests/ui/enum-discriminant/discriminant_value.rs @@ -0,0 +1,82 @@ +// run-pass +#![allow(stable_features)] +#![feature(core, core_intrinsics)] + +extern crate core; +use core::intrinsics::discriminant_value; + +enum CLike1 { + A, + B, + C, + D +} + +enum CLike2 { + A = 5, + B = 2, + C = 19, + D +} + +#[repr(i8)] +enum CLike3 { + A = 5, + B, + C = -1, + D +} + +#[allow(unused_tuple_struct_fields)] +enum ADT { + First(u32, u32), + Second(u64) +} + +enum NullablePointer { + Something(#[allow(unused_tuple_struct_fields)] &'static u32), + Nothing +} + +static CONST : u32 = 0xBEEF; + +#[allow(dead_code)] +#[repr(isize)] +enum Mixed { + Unit = 3, + Tuple(u16) = 2, + Struct { + a: u8, + b: u16, + } = 1, +} + +pub fn main() { + assert_eq!(discriminant_value(&CLike1::A), 0isize); + assert_eq!(discriminant_value(&CLike1::B), 1); + assert_eq!(discriminant_value(&CLike1::C), 2); + assert_eq!(discriminant_value(&CLike1::D), 3); + + assert_eq!(discriminant_value(&CLike2::A), 5isize); + assert_eq!(discriminant_value(&CLike2::B), 2); + assert_eq!(discriminant_value(&CLike2::C), 19); + assert_eq!(discriminant_value(&CLike2::D), 20); + + assert_eq!(discriminant_value(&CLike3::A), 5i8); + assert_eq!(discriminant_value(&CLike3::B), 6); + assert_eq!(discriminant_value(&CLike3::C), -1); + assert_eq!(discriminant_value(&CLike3::D), 0); + + assert_eq!(discriminant_value(&ADT::First(0,0)), 0isize); + assert_eq!(discriminant_value(&ADT::Second(5)), 1); + + assert_eq!(discriminant_value(&NullablePointer::Nothing), 1isize); + assert_eq!(discriminant_value(&NullablePointer::Something(&CONST)), 0); + + assert_eq!(discriminant_value(&10), 0u8); + assert_eq!(discriminant_value(&"test"), 0u8); + + assert_eq!(discriminant_value(&Mixed::Unit), 3isize); + assert_eq!(discriminant_value(&Mixed::Tuple(5)), 2); + assert_eq!(discriminant_value(&Mixed::Struct{a: 7, b: 11}), 1); +} diff --git a/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.rs b/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.rs new file mode 100644 index 000000000..4760ca548 --- /dev/null +++ b/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.rs @@ -0,0 +1,14 @@ +#![feature(discriminant_kind)] + +use std::marker::DiscriminantKind; + +enum Uninhabited {} + +struct NewType; + +impl DiscriminantKind for NewType { + //~^ ERROR explicit impls for the `DiscriminantKind` trait are not permitted + type Discriminant = Uninhabited; +} + +fn main() {} diff --git a/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr b/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr new file mode 100644 index 000000000..38cfd13b9 --- /dev/null +++ b/tests/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr @@ -0,0 +1,9 @@ +error[E0322]: explicit impls for the `DiscriminantKind` trait are not permitted + --> $DIR/forbidden-discriminant-kind-impl.rs:9:1 + | +LL | impl DiscriminantKind for NewType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `DiscriminantKind` not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0322`. diff --git a/tests/ui/enum-discriminant/get_discr.rs b/tests/ui/enum-discriminant/get_discr.rs new file mode 100644 index 000000000..71eea4e0f --- /dev/null +++ b/tests/ui/enum-discriminant/get_discr.rs @@ -0,0 +1,114 @@ +// run-pass + +// Now that there are several variations on the code generated in +// `codegen_get_discr`, let's make sure the various cases yield the correct +// result. + +// To get the discriminant of an E value, there are no shortcuts - we must +// do the full algorithm. +#[repr(u8)] +pub enum X1 { + _1 = 1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, + _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, + _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, + _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, + _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, + _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128, + _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144, + _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176, + _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192, + _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, + _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224, + _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, +} + +#[repr(i8)] +pub enum X2 { + _1 = -1, _2 = 0, _3 = 1, +} + +#[repr(i8)] +pub enum X3 { + _1 = -128, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, + _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, + _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, + _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, + _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, + _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128, + _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144, + _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176, + _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192, + _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, + _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224, + _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, +} + +#[repr(i8)] +pub enum X4 { + _1 = -126, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, + _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, + _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, + _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, + _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, + _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, + _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, + _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128, + _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144, + _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, + _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176, + _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192, + _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, + _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224, + _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240, + _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, +} + +pub enum E { + A(X), + B, + C, +} + +pub fn match_e(e: E) -> u8 { + use E::*; + match e { + A(_) => 0, + B => 1, + C => 2, + } +} + +fn main() { + assert_eq!(match_e(E::A(X1::_1)), 0); + assert_eq!(match_e(E::A(X1::_2)), 0); + assert_eq!(match_e(E::A(X1::_254)), 0); + assert_eq!(match_e(E::::B), 1); + assert_eq!(match_e(E::::C), 2); + assert_eq!(match_e(E::A(X2::_1)), 0); + assert_eq!(match_e(E::A(X2::_2)), 0); + assert_eq!(match_e(E::A(X2::_3)), 0); + assert_eq!(match_e(E::::B), 1); + assert_eq!(match_e(E::::C), 2); + assert_eq!(match_e(E::A(X3::_1)), 0); + assert_eq!(match_e(E::A(X3::_2)), 0); + assert_eq!(match_e(E::A(X3::_254)), 0); + assert_eq!(match_e(E::::B), 1); + assert_eq!(match_e(E::::C), 2); + assert_eq!(match_e(E::A(X4::_1)), 0); + assert_eq!(match_e(E::A(X4::_2)), 0); + assert_eq!(match_e(E::A(X4::_254)), 0); + assert_eq!(match_e(E::::B), 1); + assert_eq!(match_e(E::::C), 2); + assert_eq!(match_e(E::A(false)), 0); + assert_eq!(match_e(E::A(true)), 0); + assert_eq!(match_e(E::::B), 1); + assert_eq!(match_e(E::::C), 2); +} diff --git a/tests/ui/enum-discriminant/issue-104519.rs b/tests/ui/enum-discriminant/issue-104519.rs new file mode 100644 index 000000000..c4630f76b --- /dev/null +++ b/tests/ui/enum-discriminant/issue-104519.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(dead_code)] + +enum OpenResult { + Ok(()), + Err(()), + TransportErr(TransportErr), +} + +#[repr(i32)] +enum TransportErr { + UnknownMethod = -2, +} + +#[inline(never)] +fn some_match(result: OpenResult) -> u8 { + match result { + OpenResult::Ok(()) => 0, + _ => 1, + } +} + +fn main() { + let result = OpenResult::Ok(()); + assert_eq!(some_match(result), 0); + + let result = OpenResult::Ok(()); + match result { + OpenResult::Ok(()) => (), + _ => unreachable!("message a"), + } + match result { + OpenResult::Ok(()) => (), + _ => unreachable!("message b"), + } +} diff --git a/tests/ui/enum-discriminant/issue-43398.rs b/tests/ui/enum-discriminant/issue-43398.rs new file mode 100644 index 000000000..581db033f --- /dev/null +++ b/tests/ui/enum-discriminant/issue-43398.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(core_intrinsics)] +#![feature(repr128)] +//~^ WARN the feature `repr128` is incomplete + +#[repr(i128)] +enum Big { A, B } + +fn main() { + println!("{} {:?}", + std::intrinsics::discriminant_value(&Big::A), + std::mem::discriminant(&Big::B)); +} diff --git a/tests/ui/enum-discriminant/issue-43398.stderr b/tests/ui/enum-discriminant/issue-43398.stderr new file mode 100644 index 000000000..fc7bbd062 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-43398.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-43398.rs:4:12 + | +LL | #![feature(repr128)] + | ^^^^^^^ + | + = note: see issue #56071 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/enum-discriminant/issue-46519.rs b/tests/ui/enum-discriminant/issue-46519.rs new file mode 100644 index 000000000..0567923b7 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-46519.rs @@ -0,0 +1,30 @@ +// run-pass +// compile-flags:--test -O + +// needs-unwind + +#[test] +#[should_panic(expected = "creating inhabited type")] +fn test() { + FontLanguageOverride::system_font(SystemFont::new()); +} + +pub enum FontLanguageOverride { + Normal, + Override(&'static str), + System(SystemFont) +} + +pub enum SystemFont {} + +impl FontLanguageOverride { + fn system_font(f: SystemFont) -> Self { + FontLanguageOverride::System(f) + } +} + +impl SystemFont { + fn new() -> Self { + panic!("creating inhabited type") + } +} diff --git a/tests/ui/enum-discriminant/issue-51582.rs b/tests/ui/enum-discriminant/issue-51582.rs new file mode 100644 index 000000000..40a70c623 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-51582.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(core_intrinsics)] + +#[repr(i8)] +pub enum Enum { + VariantA, + VariantB, +} + +fn make_b() -> Enum { Enum::VariantB } + +fn main() { + assert_eq!(1, make_b() as i8); + assert_eq!(1, make_b() as u8); + assert_eq!(1, make_b() as i32); + assert_eq!(1, make_b() as u32); + assert_eq!(1, std::intrinsics::discriminant_value(&make_b())); +} diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs new file mode 100644 index 000000000..ad9fcc25b --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs @@ -0,0 +1,16 @@ +#![feature(core_intrinsics)] + +extern crate core; +use core::intrinsics::discriminant_value; + +#[repr(usize)] +enum MyWeirdOption { + None = 0, + Some(T) = std::mem::size_of::(), + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() { + assert_eq!(discriminant_value(&MyWeirdOption::::None), 0); + assert_eq!(discriminant_value(&MyWeirdOption::Some(0u8)), 1); +} diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr new file mode 100644 index 000000000..e4e10468d --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-70453-generics-in-discr-ice-2.rs:9:35 + | +LL | Some(T) = std::mem::size_of::(), + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs new file mode 100644 index 000000000..a0fb788a5 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs @@ -0,0 +1,17 @@ +#![feature(core_intrinsics)] + +extern crate core; +use core::intrinsics::discriminant_value; + +#[repr(usize)] +enum MyWeirdOption { +//~^ ERROR parameter `T` is never used + None = 0, + Some = std::mem::size_of::(), + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() { + assert_eq!(discriminant_value(&MyWeirdOption::::None), 0); + assert_eq!(discriminant_value(&MyWeirdOption::::Some), 1); +} diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr new file mode 100644 index 000000000..7ea8a3912 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-70453-generics-in-discr-ice.rs:10:32 + | +LL | Some = std::mem::size_of::(), + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `T` is never used + --> $DIR/issue-70453-generics-in-discr-ice.rs:7:20 + | +LL | enum MyWeirdOption { + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs new file mode 100644 index 000000000..42a062239 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs @@ -0,0 +1,16 @@ +#![feature(core_intrinsics)] + +extern crate core; +use core::intrinsics::discriminant_value; + +#[repr(usize)] +enum MyWeirdOption { + None = 0, + Some(T) = core::mem::size_of::<*mut T>(), + //~^ ERROR generic parameters may not be used +} + +fn main() { + assert_eq!(discriminant_value(&MyWeirdOption::<()>::None), 0); + assert_eq!(discriminant_value(&MyWeirdOption::Some(())), core::mem::size_of::()); +} diff --git a/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr new file mode 100644 index 000000000..0a7a63160 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-70453-polymorphic-ctfe.rs:9:41 + | +LL | Some(T) = core::mem::size_of::<*mut T>(), + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/enum-discriminant/issue-70509-partial_eq.rs b/tests/ui/enum-discriminant/issue-70509-partial_eq.rs new file mode 100644 index 000000000..3adac7b72 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70509-partial_eq.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(repr128)] +//~^ WARN the feature `repr128` is incomplete + +#[derive(PartialEq, Debug)] +#[repr(i128)] +enum Test { + A(Box) = 0, + B(usize) = u64::MAX as i128 + 1, +} + +fn main() { + assert_ne!(Test::A(Box::new(2)), Test::B(0)); + // This previously caused a segfault. + // + // See https://github.com/rust-lang/rust/issues/70509#issuecomment-620654186 + // for a detailed explanation. +} diff --git a/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr b/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr new file mode 100644 index 000000000..2eef930c3 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-70509-partial_eq.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-70509-partial_eq.rs:2:12 + | +LL | #![feature(repr128)] + | ^^^^^^^ + | + = note: see issue #56071 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/enum-discriminant/issue-72554.rs b/tests/ui/enum-discriminant/issue-72554.rs new file mode 100644 index 000000000..54f7e9ac5 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-72554.rs @@ -0,0 +1,22 @@ +use std::collections::BTreeSet; + +#[derive(Hash)] +pub enum ElemDerived { + //~^ ERROR recursive type `ElemDerived` has infinite size + A(ElemDerived) +} + + +pub enum Elem { + Derived(ElemDerived) +} + +pub struct Set(BTreeSet); + +impl Set { + pub fn into_iter(self) -> impl Iterator { + self.0.into_iter() + } +} + +fn main() {} diff --git a/tests/ui/enum-discriminant/issue-72554.stderr b/tests/ui/enum-discriminant/issue-72554.stderr new file mode 100644 index 000000000..d12be539f --- /dev/null +++ b/tests/ui/enum-discriminant/issue-72554.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `ElemDerived` has infinite size + --> $DIR/issue-72554.rs:4:1 + | +LL | pub enum ElemDerived { + | ^^^^^^^^^^^^^^^^^^^^ +LL | +LL | A(ElemDerived) + | ----------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | A(Box) + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/enum-discriminant/issue-90038.rs b/tests/ui/enum-discriminant/issue-90038.rs new file mode 100644 index 000000000..5e98eccd9 --- /dev/null +++ b/tests/ui/enum-discriminant/issue-90038.rs @@ -0,0 +1,21 @@ +// run-pass + +#[repr(u32)] +pub enum Foo { + // Greater than or equal to 2 + A = 2, +} + +pub enum Bar { + A(Foo), + // More than two const variants + B, + C, +} + +fn main() { + match Bar::A(Foo::A) { + Bar::A(_) => (), + _ => unreachable!(), + } +} diff --git a/tests/ui/enum-discriminant/niche-prefer-zero.rs b/tests/ui/enum-discriminant/niche-prefer-zero.rs new file mode 100644 index 000000000..f20607a89 --- /dev/null +++ b/tests/ui/enum-discriminant/niche-prefer-zero.rs @@ -0,0 +1,14 @@ +// Check that niche selection prefers zero. +// See https://github.com/rust-lang/rust/pull/87794 +// run-pass +#[repr(u8)] +pub enum Size { + One = 1, + Two = 2, + Three = 3, +} + +fn main() { + // check that `None` is zero + assert_eq!(0, unsafe { std::mem::transmute::, u8>(None) }); +} diff --git a/tests/ui/enum-discriminant/niche.rs b/tests/ui/enum-discriminant/niche.rs new file mode 100644 index 000000000..8d3061050 --- /dev/null +++ b/tests/ui/enum-discriminant/niche.rs @@ -0,0 +1,109 @@ +// run-pass + +//! Make sure that we read and write enum discriminants correctly for corner cases caused +//! by layout optimizations. + +const OVERFLOW: usize = { + // Tests for https://github.com/rust-lang/rust/issues/62138. + #[repr(u8)] + #[allow(dead_code)] + enum WithWraparoundInvalidValues { + X = 1, + Y = 254, + } + + #[allow(dead_code)] + enum Foo { + A, + B, + C(WithWraparoundInvalidValues), + } + + let x = Foo::B; + match x { + Foo::B => 0, + _ => panic!(), + } +}; + +const MORE_OVERFLOW: usize = { + pub enum Infallible {} + + // The check that the `bool` field of `V1` is encoding a "niche variant" + // (i.e. not `V1`, so `V3` or `V4`) used to be mathematically incorrect, + // causing valid `V1` values to be interpreted as other variants. + #[allow(dead_code)] + pub enum E1 { + V1 { f: bool }, + V2 { f: Infallible }, + V3, + V4, + } + + // Computing the discriminant used to be done using the niche type (here `u8`, + // from the `bool` field of `V1`), overflowing for variants with large enough + // indices (`V3` and `V4`), causing them to be interpreted as other variants. + #[allow(dead_code)] + pub enum E2 { + V1 { f: bool }, + + /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), + _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), + _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), + _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), + _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), + _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), + _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), + _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), + _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), + _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), + _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), + _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), + _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), + _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), + _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), + _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), + _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), + _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), + _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), + _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), + _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), + _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), + _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), + _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), + _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), + _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), + _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), + _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), + _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), + _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), + _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), + _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), + + V3, + V4, + } + + if let E1::V2 { .. } = (E1::V1 { f: true }) { + unreachable!() + } + if let E1::V1 { .. } = (E1::V1 { f: true }) { + } else { + unreachable!() + } + + if let E2::V1 { .. } = E2::V3:: { + unreachable!() + } + if let E2::V3 { .. } = E2::V3:: { + } else { + unreachable!() + } + + 0 +}; + +fn main() { + assert_eq!(OVERFLOW, 0); + assert_eq!(MORE_OVERFLOW, 0); +} diff --git a/tests/ui/enum-discriminant/repr128.rs b/tests/ui/enum-discriminant/repr128.rs new file mode 100644 index 000000000..00021a07b --- /dev/null +++ b/tests/ui/enum-discriminant/repr128.rs @@ -0,0 +1,45 @@ +// run-pass +#![feature(repr128, core_intrinsics, discriminant_kind)] +//~^ WARN the feature `repr128` is incomplete + +use std::intrinsics::discriminant_value; +use std::marker::DiscriminantKind; + +#[repr(i128)] +enum Signed { + Zero = 0, + Staircase = 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f, + U64Limit = u64::MAX as i128 + 1, + SmallNegative = -1, + BigNegative = i128::MIN, + Next, +} + +#[repr(u128)] +enum Unsigned { + Zero = 0, + Staircase = 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f, + U64Limit = u64::MAX as u128 + 1, + Next, +} + +fn discr(v: T, value: U) +where + ::Discriminant: PartialEq, +{ + assert!(discriminant_value(&v) == value); +} + +fn main() { + discr(Signed::Zero, 0); + discr(Signed::Staircase, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f); + discr(Signed::U64Limit, u64::MAX as i128 + 1); + discr(Signed::SmallNegative, -1); + discr(Signed::BigNegative, i128::MIN); + discr(Signed::Next, i128::MIN + 1); + + discr(Unsigned::Zero, 0); + discr(Unsigned::Staircase, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f); + discr(Unsigned::U64Limit, u64::MAX as u128 + 1); + discr(Unsigned::Next, u64::MAX as u128 + 2); +} diff --git a/tests/ui/enum-discriminant/repr128.stderr b/tests/ui/enum-discriminant/repr128.stderr new file mode 100644 index 000000000..da8d75c11 --- /dev/null +++ b/tests/ui/enum-discriminant/repr128.stderr @@ -0,0 +1,11 @@ +warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/repr128.rs:2:12 + | +LL | #![feature(repr128, core_intrinsics, discriminant_kind)] + | ^^^^^^^ + | + = note: see issue #56071 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/enum/enum-and-module-in-same-scope.rs b/tests/ui/enum/enum-and-module-in-same-scope.rs new file mode 100644 index 000000000..cc6e199bd --- /dev/null +++ b/tests/ui/enum/enum-and-module-in-same-scope.rs @@ -0,0 +1,10 @@ +enum Foo { + X +} + +mod Foo { //~ ERROR the name `Foo` is defined multiple times + pub static X: isize = 42; + fn f() { f() } // Check that this does not result in a resolution error +} + +fn main() {} diff --git a/tests/ui/enum/enum-and-module-in-same-scope.stderr b/tests/ui/enum/enum-and-module-in-same-scope.stderr new file mode 100644 index 000000000..538898c2f --- /dev/null +++ b/tests/ui/enum/enum-and-module-in-same-scope.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/enum-and-module-in-same-scope.rs:5:1 + | +LL | enum Foo { + | -------- previous definition of the type `Foo` here +... +LL | mod Foo { + | ^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/enum/enum-discrim-autosizing.rs b/tests/ui/enum/enum-discrim-autosizing.rs new file mode 100644 index 000000000..fc94d281c --- /dev/null +++ b/tests/ui/enum/enum-discrim-autosizing.rs @@ -0,0 +1,14 @@ +// With no repr attribute the discriminant will default to isize. +// On 32-bit architectures this is equivalent to i32 so the variants +// collide. On other architectures we need compilation to fail anyway, +// so force the repr. +#[cfg_attr(not(target_pointer_width = "32"), repr(i32))] +enum Eu64 { + //~^ ERROR discriminant value `0` assigned more than once + Au64 = 0, + //~^NOTE `0` assigned here + Bu64 = 0x8000_0000_0000_0000 + //~^NOTE `0` (overflowed from `9223372036854775808`) assigned here +} + +fn main() {} diff --git a/tests/ui/enum/enum-discrim-autosizing.stderr b/tests/ui/enum/enum-discrim-autosizing.stderr new file mode 100644 index 000000000..be3d7c64e --- /dev/null +++ b/tests/ui/enum/enum-discrim-autosizing.stderr @@ -0,0 +1,15 @@ +error[E0081]: discriminant value `0` assigned more than once + --> $DIR/enum-discrim-autosizing.rs:6:1 + | +LL | enum Eu64 { + | ^^^^^^^^^ +LL | +LL | Au64 = 0, + | - `0` assigned here +LL | +LL | Bu64 = 0x8000_0000_0000_0000 + | --------------------- `0` (overflowed from `9223372036854775808`) assigned here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0081`. diff --git a/tests/ui/enum/enum-discrim-too-small.rs b/tests/ui/enum/enum-discrim-too-small.rs new file mode 100644 index 000000000..e49841402 --- /dev/null +++ b/tests/ui/enum/enum-discrim-too-small.rs @@ -0,0 +1,38 @@ +#[repr(u8)] +enum Eu8 { + Au8 = 23, + Bu8 = 223, + Cu8 = -23, + //~^ ERROR cannot apply unary operator `-` to type `u8` +} + +#[repr(u16)] +enum Eu16 { + Au16 = 23, + Bu16 = 55555, + Cu16 = -22333, + //~^ ERROR cannot apply unary operator `-` to type `u16` +} + +#[repr(u32)] +enum Eu32 { + Au32 = 23, + Bu32 = 3_000_000_000, + Cu32 = -2_000_000_000, + //~^ ERROR cannot apply unary operator `-` to type `u32` +} + +#[repr(u64)] +enum Eu64 { + Au32 = 23, + Bu32 = 3_000_000_000, + Cu32 = -2_000_000_000, + //~^ ERROR cannot apply unary operator `-` to type `u64` +} + +// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a +// little counterintuitive, but since the discriminant can store all the bits, and extracting it +// with a cast requires specifying the signedness, there is no loss of information in those cases. +// This also applies to isize and usize on 64-bit targets. + +pub fn main() { } diff --git a/tests/ui/enum/enum-discrim-too-small.stderr b/tests/ui/enum/enum-discrim-too-small.stderr new file mode 100644 index 000000000..40205d95b --- /dev/null +++ b/tests/ui/enum/enum-discrim-too-small.stderr @@ -0,0 +1,35 @@ +error[E0600]: cannot apply unary operator `-` to type `u8` + --> $DIR/enum-discrim-too-small.rs:5:11 + | +LL | Cu8 = -23, + | ^^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `u16` + --> $DIR/enum-discrim-too-small.rs:13:12 + | +LL | Cu16 = -22333, + | ^^^^^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/enum-discrim-too-small.rs:21:12 + | +LL | Cu32 = -2_000_000_000, + | ^^^^^^^^^^^^^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `u64` + --> $DIR/enum-discrim-too-small.rs:29:12 + | +LL | Cu32 = -2_000_000_000, + | ^^^^^^^^^^^^^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/enum/enum-discrim-too-small2.rs b/tests/ui/enum/enum-discrim-too-small2.rs new file mode 100644 index 000000000..85cd73d6f --- /dev/null +++ b/tests/ui/enum/enum-discrim-too-small2.rs @@ -0,0 +1,37 @@ +#![deny(overflowing_literals)] +#![allow(dead_code)] + +#[repr(i8)] +enum Ei8 { + Ai8 = 23, + Bi8 = -23, + Ci8 = 223, //~ ERROR literal out of range for `i8` +} + +#[repr(i16)] +enum Ei16 { + Ai16 = 23, + Bi16 = -22333, + Ci16 = 55555, //~ ERROR literal out of range for `i16` +} + +#[repr(i32)] +enum Ei32 { + Ai32 = 23, + Bi32 = -2_000_000_000, + Ci32 = 3_000_000_000, //~ ERROR literal out of range for `i32` +} + +#[repr(i64)] +enum Ei64 { + Ai64 = 23, + Bi64 = -9223372036854775808, + Ci64 = 9223372036854775809, //~ ERROR literal out of range for `i64` +} + +// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a +// little counterintuitive, but since the discriminant can store all the bits, and extracting it +// with a cast requires specifying the signedness, there is no loss of information in those cases. +// This also applies to isize and usize on 64-bit targets. + +pub fn main() { } diff --git a/tests/ui/enum/enum-discrim-too-small2.stderr b/tests/ui/enum/enum-discrim-too-small2.stderr new file mode 100644 index 000000000..f79f7a043 --- /dev/null +++ b/tests/ui/enum/enum-discrim-too-small2.stderr @@ -0,0 +1,43 @@ +error: literal out of range for `i8` + --> $DIR/enum-discrim-too-small2.rs:8:11 + | +LL | Ci8 = 223, + | ^^^ + | + = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/enum-discrim-too-small2.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `i16` + --> $DIR/enum-discrim-too-small2.rs:15:12 + | +LL | Ci16 = 55555, + | ^^^^^ + | + = note: the literal `55555` does not fit into the type `i16` whose range is `-32768..=32767` + = help: consider using the type `u16` instead + +error: literal out of range for `i32` + --> $DIR/enum-discrim-too-small2.rs:22:12 + | +LL | Ci32 = 3_000_000_000, + | ^^^^^^^^^^^^^ + | + = note: the literal `3_000_000_000` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i64` + --> $DIR/enum-discrim-too-small2.rs:29:12 + | +LL | Ci64 = 9223372036854775809, + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `u64` instead + +error: aborting due to 4 previous errors + diff --git a/tests/ui/enum/enum-in-scope.rs b/tests/ui/enum/enum-in-scope.rs new file mode 100644 index 000000000..df14bc62e --- /dev/null +++ b/tests/ui/enum/enum-in-scope.rs @@ -0,0 +1,7 @@ +#![allow(non_camel_case_types)] + +struct hello(isize); + +fn main() { + let hello = 0; //~ERROR let bindings cannot shadow tuple structs +} diff --git a/tests/ui/enum/enum-in-scope.stderr b/tests/ui/enum/enum-in-scope.stderr new file mode 100644 index 000000000..49a01abcb --- /dev/null +++ b/tests/ui/enum/enum-in-scope.stderr @@ -0,0 +1,12 @@ +error[E0530]: let bindings cannot shadow tuple structs + --> $DIR/enum-in-scope.rs:6:9 + | +LL | struct hello(isize); + | -------------------- the tuple struct `hello` is defined here +... +LL | let hello = 0; + | ^^^^^ cannot be named the same as a tuple struct + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/enum/enum-size-variance.rs b/tests/ui/enum/enum-size-variance.rs new file mode 100644 index 000000000..082bd0dcf --- /dev/null +++ b/tests/ui/enum/enum-size-variance.rs @@ -0,0 +1,35 @@ +// run-pass + +#![warn(variant_size_differences)] +#![allow(dead_code)] + +// Note that the following test works because all fields of the enum variants are of the same size. +// If this test is modified and the reordering logic in librustc/ty/layout.rs kicks in, it fails. + +enum Enum1 { } + +enum Enum2 { A, B, C } + +enum Enum3 { D(i64), E, F } + +enum Enum4 { H(i64), I(i64), J } + +enum Enum5 { + L(i64, i64, i64, i64), //~ WARNING three times larger + M(i64), + N +} + +enum Enum6 { + O(T), + P(U), + Q(i64) +} + +#[allow(variant_size_differences)] +enum Enum7 { + R(i64, i64, i64, i64), + S(i64), + T +} +pub fn main() { } diff --git a/tests/ui/enum/enum-size-variance.stderr b/tests/ui/enum/enum-size-variance.stderr new file mode 100644 index 000000000..6012033dc --- /dev/null +++ b/tests/ui/enum/enum-size-variance.stderr @@ -0,0 +1,14 @@ +warning: enum variant is more than three times larger (32 bytes) than the next largest + --> $DIR/enum-size-variance.rs:18:5 + | +LL | L(i64, i64, i64, i64), + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/enum-size-variance.rs:3:9 + | +LL | #![warn(variant_size_differences)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/enum/enum-to-float-cast-2.rs b/tests/ui/enum/enum-to-float-cast-2.rs new file mode 100644 index 000000000..c861b5ed9 --- /dev/null +++ b/tests/ui/enum/enum-to-float-cast-2.rs @@ -0,0 +1,18 @@ +// Tests that enum-to-float casts are disallowed. + +enum E { + L0 = -1, + H0 = 1 +} + +enum F { + L1 = 1, + H1 = 0xFFFFFFFFFFFFFFFF +} + +pub fn main() { + let a = E::L0 as f32; //~ ERROR casting + let c = F::H1 as f32; //~ ERROR casting + assert_eq!(a, -1.0f32); + assert_eq!(c, -1.0f32); +} diff --git a/tests/ui/enum/enum-to-float-cast-2.stderr b/tests/ui/enum/enum-to-float-cast-2.stderr new file mode 100644 index 000000000..2bc414098 --- /dev/null +++ b/tests/ui/enum/enum-to-float-cast-2.stderr @@ -0,0 +1,19 @@ +error[E0606]: casting `E` as `f32` is invalid + --> $DIR/enum-to-float-cast-2.rs:14:13 + | +LL | let a = E::L0 as f32; + | ^^^^^^^^^^^^ + | + = help: cast through an integer first + +error[E0606]: casting `F` as `f32` is invalid + --> $DIR/enum-to-float-cast-2.rs:15:13 + | +LL | let c = F::H1 as f32; + | ^^^^^^^^^^^^ + | + = help: cast through an integer first + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/enum/enum-to-float-cast.rs b/tests/ui/enum/enum-to-float-cast.rs new file mode 100644 index 000000000..05acdfd34 --- /dev/null +++ b/tests/ui/enum/enum-to-float-cast.rs @@ -0,0 +1,21 @@ +// Tests that enum-to-float casts are disallowed. + +enum E { + L0 = -1, + H0 = 1 +} + +enum F { + L1 = 1, + H1 = 0xFFFFFFFFFFFFFFFF +} + +static C0: f32 = E::L0 as f32; //~ ERROR casting +static C1: f32 = F::H1 as f32; //~ ERROR casting + +pub fn main() { + let b = C0; + let d = C1; + assert_eq!(b, -1.0f32); + assert_eq!(d, -1.0f32); +} diff --git a/tests/ui/enum/enum-to-float-cast.stderr b/tests/ui/enum/enum-to-float-cast.stderr new file mode 100644 index 000000000..191606d8d --- /dev/null +++ b/tests/ui/enum/enum-to-float-cast.stderr @@ -0,0 +1,19 @@ +error[E0606]: casting `E` as `f32` is invalid + --> $DIR/enum-to-float-cast.rs:13:18 + | +LL | static C0: f32 = E::L0 as f32; + | ^^^^^^^^^^^^ + | + = help: cast through an integer first + +error[E0606]: casting `F` as `f32` is invalid + --> $DIR/enum-to-float-cast.rs:14:18 + | +LL | static C1: f32 = F::H1 as f32; + | ^^^^^^^^^^^^ + | + = help: cast through an integer first + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/enum/enum-variant-type-2.rs b/tests/ui/enum/enum-variant-type-2.rs new file mode 100644 index 000000000..27286a0a3 --- /dev/null +++ b/tests/ui/enum/enum-variant-type-2.rs @@ -0,0 +1,9 @@ +// Test that enum variants are not actually types. + +enum Foo { + Bar +} + +fn foo(x: Foo::Bar) {} //~ ERROR expected type, found variant `Foo::Bar` + +fn main() {} diff --git a/tests/ui/enum/enum-variant-type-2.stderr b/tests/ui/enum/enum-variant-type-2.stderr new file mode 100644 index 000000000..7e8453c61 --- /dev/null +++ b/tests/ui/enum/enum-variant-type-2.stderr @@ -0,0 +1,12 @@ +error[E0573]: expected type, found variant `Foo::Bar` + --> $DIR/enum-variant-type-2.rs:7:11 + | +LL | fn foo(x: Foo::Bar) {} + | ^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/enum/issue-42747.rs b/tests/ui/enum/issue-42747.rs new file mode 100644 index 000000000..fec658782 --- /dev/null +++ b/tests/ui/enum/issue-42747.rs @@ -0,0 +1,46 @@ +// run-pass +macro_rules! fooN { + ($cur:ident $prev:ty) => { + #[allow(dead_code)] + enum $cur { + Empty, + First($prev), + Second($prev), + Third($prev), + Fourth($prev), + } + } +} + +fooN!(Foo0 ()); +fooN!(Foo1 Foo0); +fooN!(Foo2 Foo1); +fooN!(Foo3 Foo2); +fooN!(Foo4 Foo3); +fooN!(Foo5 Foo4); +fooN!(Foo6 Foo5); +fooN!(Foo7 Foo6); +fooN!(Foo8 Foo7); +fooN!(Foo9 Foo8); +fooN!(Foo10 Foo9); +fooN!(Foo11 Foo10); +fooN!(Foo12 Foo11); +fooN!(Foo13 Foo12); +fooN!(Foo14 Foo13); +fooN!(Foo15 Foo14); +fooN!(Foo16 Foo15); +fooN!(Foo17 Foo16); +fooN!(Foo18 Foo17); +fooN!(Foo19 Foo18); +fooN!(Foo20 Foo19); +fooN!(Foo21 Foo20); +fooN!(Foo22 Foo21); +fooN!(Foo23 Foo22); +fooN!(Foo24 Foo23); +fooN!(Foo25 Foo24); +fooN!(Foo26 Foo25); +fooN!(Foo27 Foo26); + +fn main() { + let _foo = Foo27::Empty; +} diff --git a/tests/ui/enum/issue-67945-1.rs b/tests/ui/enum/issue-67945-1.rs new file mode 100644 index 000000000..f4697344c --- /dev/null +++ b/tests/ui/enum/issue-67945-1.rs @@ -0,0 +1,8 @@ +enum Bug { //~ ERROR parameter `S` is never used + Var = { + let x: S = 0; //~ ERROR generic parameters may not be used + 0 + }, +} + +fn main() {} diff --git a/tests/ui/enum/issue-67945-1.stderr b/tests/ui/enum/issue-67945-1.stderr new file mode 100644 index 000000000..8f1b5b38e --- /dev/null +++ b/tests/ui/enum/issue-67945-1.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-1.rs:3:16 + | +LL | let x: S = 0; + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-1.rs:1:10 + | +LL | enum Bug { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/enum/issue-67945-2.rs b/tests/ui/enum/issue-67945-2.rs new file mode 100644 index 000000000..2eb123b73 --- /dev/null +++ b/tests/ui/enum/issue-67945-2.rs @@ -0,0 +1,8 @@ +#![feature(type_ascription)] + +enum Bug { //~ ERROR parameter `S` is never used + Var = type_ascribe!(0, S), + //~^ ERROR generic parameters may not be used +} + +fn main() {} diff --git a/tests/ui/enum/issue-67945-2.stderr b/tests/ui/enum/issue-67945-2.stderr new file mode 100644 index 000000000..63d3521af --- /dev/null +++ b/tests/ui/enum/issue-67945-2.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-2.rs:4:28 + | +LL | Var = type_ascribe!(0, S), + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-2.rs:3:10 + | +LL | enum Bug { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/enum/nested-enum.rs b/tests/ui/enum/nested-enum.rs new file mode 100644 index 000000000..80957b8a1 --- /dev/null +++ b/tests/ui/enum/nested-enum.rs @@ -0,0 +1,8 @@ +enum Foo { + enum Bar { Baz }, //~ ERROR `enum` definition cannot be nested inside `enum` + struct Quux { field: u8 }, //~ ERROR `struct` definition cannot be nested inside `enum` + union Wibble { field: u8 }, //~ ERROR `union` definition cannot be nested inside `enum` + Bat, +} + +fn main() { } diff --git a/tests/ui/enum/nested-enum.stderr b/tests/ui/enum/nested-enum.stderr new file mode 100644 index 000000000..7d6f57e88 --- /dev/null +++ b/tests/ui/enum/nested-enum.stderr @@ -0,0 +1,26 @@ +error: `enum` definition cannot be nested inside `enum` + --> $DIR/nested-enum.rs:2:5 + | +LL | enum Bar { Baz }, + | ^^^^------------ + | | + | help: consider creating a new `enum` definition instead of nesting + +error: `struct` definition cannot be nested inside `enum` + --> $DIR/nested-enum.rs:3:5 + | +LL | struct Quux { field: u8 }, + | ^^^^^^------------------- + | | + | help: consider creating a new `struct` definition instead of nesting + +error: `union` definition cannot be nested inside `enum` + --> $DIR/nested-enum.rs:4:5 + | +LL | union Wibble { field: u8 }, + | ^^^^^--------------------- + | | + | help: consider creating a new `union` definition instead of nesting + +error: aborting due to 3 previous errors + diff --git a/tests/ui/enum/suggest-default-attribute.rs b/tests/ui/enum/suggest-default-attribute.rs new file mode 100644 index 000000000..1d7567e60 --- /dev/null +++ b/tests/ui/enum/suggest-default-attribute.rs @@ -0,0 +1,8 @@ +pub enum Test { //~ HELP consider adding a derive + #[default] + //~^ ERROR cannot find attribute `default` in this scope + First, + Second, +} + +fn main() {} diff --git a/tests/ui/enum/suggest-default-attribute.stderr b/tests/ui/enum/suggest-default-attribute.stderr new file mode 100644 index 000000000..fb830d3f7 --- /dev/null +++ b/tests/ui/enum/suggest-default-attribute.stderr @@ -0,0 +1,14 @@ +error: cannot find attribute `default` in this scope + --> $DIR/suggest-default-attribute.rs:2:7 + | +LL | #[default] + | ^^^^^^^ + | +help: consider adding a derive + | +LL + #[derive(Default)] +LL ~ pub enum Test { + | + +error: aborting due to previous error + diff --git a/tests/ui/enum/union-in-enum.rs b/tests/ui/enum/union-in-enum.rs new file mode 100644 index 000000000..048913e25 --- /dev/null +++ b/tests/ui/enum/union-in-enum.rs @@ -0,0 +1,13 @@ +// This test checks that the union keyword +// is accepted as the name of an enum variant +// when not followed by an identifier +// This special case exists because `union` is a contextual keyword. + +#![allow(warnings)] + +// check-pass + +enum A { union } +enum B { union {} } +enum C { union() } +fn main(){} diff --git a/tests/ui/env-args-reverse-iterator.rs b/tests/ui/env-args-reverse-iterator.rs new file mode 100644 index 000000000..7f06718c0 --- /dev/null +++ b/tests/ui/env-args-reverse-iterator.rs @@ -0,0 +1,38 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env::args; +use std::process::Command; + +fn assert_reverse_iterator_for_program_arguments(program_name: &str) { + let args: Vec<_> = args().rev().collect(); + + assert!(args.len() == 4); + assert_eq!(args[0], "c"); + assert_eq!(args[1], "b"); + assert_eq!(args[2], "a"); + assert_eq!(args[3], program_name); + + println!("passed"); +} + +fn main() { + let mut args = args(); + let me = args.next().unwrap(); + + if let Some(_) = args.next() { + assert_reverse_iterator_for_program_arguments(&me); + return + } + + let output = Command::new(&me) + .arg("a") + .arg("b") + .arg("c") + .output() + .unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); +} diff --git a/tests/ui/env-funky-keys.rs b/tests/ui/env-funky-keys.rs new file mode 100644 index 000000000..46e20d8c6 --- /dev/null +++ b/tests/ui/env-funky-keys.rs @@ -0,0 +1,43 @@ +// run-pass +// Ignore this test on Android, because it segfaults there. + +// ignore-android +// ignore-windows +// ignore-emscripten no execve +// ignore-sgx no execve +// ignore-vxworks no execve +// ignore-fuchsia no 'execve' +// no-prefer-dynamic + +#![feature(rustc_private)] + +extern crate libc; + +use libc::c_char; +use libc::execve; +use std::env; +use std::ffi::CString; +use std::os::unix::prelude::*; +use std::ptr; + +fn main() { + if env::args_os().count() == 2 { + for (key, value) in env::vars_os() { + panic!("found env value {:?} {:?}", key, value); + } + return; + } + + let current_exe = CString::new(env::current_exe() + .unwrap() + .as_os_str() + .as_bytes()).unwrap(); + let new_env_var = CString::new("FOOBAR").unwrap(); + let filename: *const c_char = current_exe.as_ptr(); + let argv: &[*const c_char] = &[filename, filename, ptr::null()]; + let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()]; + unsafe { + execve(filename, &argv[0], &envp[0]); + } + panic!("execve failed"); +} diff --git a/tests/ui/env-null-vars.rs b/tests/ui/env-null-vars.rs new file mode 100644 index 000000000..10582a8a5 --- /dev/null +++ b/tests/ui/env-null-vars.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(unused_imports)] + +// ignore-windows +// ignore-wasm32-bare no libc to test ffi with + +// issue-53200 + +#![feature(rustc_private)] +extern crate libc; + +use std::env; + +// FIXME: more platforms? +#[cfg(target_os = "linux")] +fn main() { + unsafe { libc::clearenv(); } + assert_eq!(env::vars().count(), 0); +} + +#[cfg(not(target_os = "linux"))] +fn main() {} diff --git a/tests/ui/env-vars.rs b/tests/ui/env-vars.rs new file mode 100644 index 000000000..f5035bb2c --- /dev/null +++ b/tests/ui/env-vars.rs @@ -0,0 +1,20 @@ +// run-pass +// ignore-wasm32-bare no env vars + +use std::env::*; + +fn main() { + for (k, v) in vars_os() { + // On Windows, the environment variable NUMBER_OF_PROCESSORS has special meaning. + // Unfortunately, you can get different answers, depending on whether you are + // enumerating all environment variables or querying a specific variable. + // This was causing this test to fail on machines with more than 64 processors. + if cfg!(target_os = "windows") && k == "NUMBER_OF_PROCESSORS" { + continue; + } + + let v2 = var_os(&k); + assert!(v2.as_ref().map(|s| &**s) == Some(&*v), + "bad vars->var transition: {:?} {:?} {:?}", k, v, v2); + } +} diff --git a/tests/ui/error-codes/E0001.rs b/tests/ui/error-codes/E0001.rs new file mode 100644 index 000000000..2c95f02bf --- /dev/null +++ b/tests/ui/error-codes/E0001.rs @@ -0,0 +1,10 @@ +#![deny(unreachable_patterns)] + +fn main() { + let foo = Some(1); + match foo { + Some(_) => {/* ... */} + None => {/* ... */} + _ => {/* ... */} //~ ERROR unreachable pattern + } +} diff --git a/tests/ui/error-codes/E0001.stderr b/tests/ui/error-codes/E0001.stderr new file mode 100644 index 000000000..577c49032 --- /dev/null +++ b/tests/ui/error-codes/E0001.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/E0001.rs:8:9 + | +LL | _ => {/* ... */} + | ^ + | +note: the lint level is defined here + --> $DIR/E0001.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/error-codes/E0004-2.rs b/tests/ui/error-codes/E0004-2.rs new file mode 100644 index 000000000..c7612fd50 --- /dev/null +++ b/tests/ui/error-codes/E0004-2.rs @@ -0,0 +1,5 @@ +fn main() { + let x = Some(1); + + match x { } //~ ERROR E0004 +} diff --git a/tests/ui/error-codes/E0004-2.stderr b/tests/ui/error-codes/E0004-2.stderr new file mode 100644 index 000000000..e829bac19 --- /dev/null +++ b/tests/ui/error-codes/E0004-2.stderr @@ -0,0 +1,25 @@ +error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered + --> $DIR/E0004-2.rs:4:11 + | +LL | match x { } + | ^ patterns `None` and `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match x { +LL + None | Some(_) => todo!(), +LL ~ } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/error-codes/E0004.rs b/tests/ui/error-codes/E0004.rs new file mode 100644 index 000000000..1ee9d2bad --- /dev/null +++ b/tests/ui/error-codes/E0004.rs @@ -0,0 +1,12 @@ +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +fn main() { + let x = Terminator::HastaLaVistaBaby; + + match x { //~ ERROR E0004 + Terminator::TalkToMyHand => {} + } +} diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr new file mode 100644 index 000000000..4ac8c904f --- /dev/null +++ b/tests/ui/error-codes/E0004.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `Terminator::HastaLaVistaBaby` not covered + --> $DIR/E0004.rs:9:11 + | +LL | match x { + | ^ pattern `Terminator::HastaLaVistaBaby` not covered + | +note: `Terminator` defined here + --> $DIR/E0004.rs:2:5 + | +LL | enum Terminator { + | ---------- +LL | HastaLaVistaBaby, + | ^^^^^^^^^^^^^^^^ not covered + = note: the matched value is of type `Terminator` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Terminator::TalkToMyHand => {} +LL + Terminator::HastaLaVistaBaby => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/error-codes/E0005.rs b/tests/ui/error-codes/E0005.rs new file mode 100644 index 000000000..f4730697e --- /dev/null +++ b/tests/ui/error-codes/E0005.rs @@ -0,0 +1,4 @@ +fn main() { + let x = Some(1); + let Some(y) = x; //~ ERROR E0005 +} diff --git a/tests/ui/error-codes/E0005.stderr b/tests/ui/error-codes/E0005.stderr new file mode 100644 index 000000000..4692b6641 --- /dev/null +++ b/tests/ui/error-codes/E0005.stderr @@ -0,0 +1,17 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/E0005.rs:3:9 + | +LL | let Some(y) = x; + | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Some(y) = x else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/error-codes/E0010-teach.rs b/tests/ui/error-codes/E0010-teach.rs new file mode 100644 index 000000000..fc5dffb37 --- /dev/null +++ b/tests/ui/error-codes/E0010-teach.rs @@ -0,0 +1,8 @@ +// compile-flags: -Z teach + +#![feature(box_syntax)] +#![allow(warnings)] + +const CON : Box = box 0; //~ ERROR E0010 + +fn main() {} diff --git a/tests/ui/error-codes/E0010-teach.stderr b/tests/ui/error-codes/E0010-teach.stderr new file mode 100644 index 000000000..33de9fd68 --- /dev/null +++ b/tests/ui/error-codes/E0010-teach.stderr @@ -0,0 +1,11 @@ +error[E0010]: allocations are not allowed in constants + --> $DIR/E0010-teach.rs:6:24 + | +LL | const CON : Box = box 0; + | ^^^^^ allocation not allowed in constants + | + = note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0010`. diff --git a/tests/ui/error-codes/E0010.rs b/tests/ui/error-codes/E0010.rs new file mode 100644 index 000000000..e62997640 --- /dev/null +++ b/tests/ui/error-codes/E0010.rs @@ -0,0 +1,6 @@ +#![feature(box_syntax)] +#![allow(warnings)] + +const CON : Box = box 0; //~ ERROR E0010 + +fn main() {} diff --git a/tests/ui/error-codes/E0010.stderr b/tests/ui/error-codes/E0010.stderr new file mode 100644 index 000000000..0042333b9 --- /dev/null +++ b/tests/ui/error-codes/E0010.stderr @@ -0,0 +1,9 @@ +error[E0010]: allocations are not allowed in constants + --> $DIR/E0010.rs:4:24 + | +LL | const CON : Box = box 0; + | ^^^^^ allocation not allowed in constants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0010`. diff --git a/tests/ui/error-codes/E0013.rs b/tests/ui/error-codes/E0013.rs new file mode 100644 index 000000000..9b3982a78 --- /dev/null +++ b/tests/ui/error-codes/E0013.rs @@ -0,0 +1,4 @@ +static X: i32 = 42; +const Y: i32 = X; //~ ERROR constants cannot refer to statics [E0013] + +fn main() {} diff --git a/tests/ui/error-codes/E0013.stderr b/tests/ui/error-codes/E0013.stderr new file mode 100644 index 000000000..dc22053a6 --- /dev/null +++ b/tests/ui/error-codes/E0013.stderr @@ -0,0 +1,11 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/E0013.rs:2:16 + | +LL | const Y: i32 = X; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/error-codes/E0015.rs b/tests/ui/error-codes/E0015.rs new file mode 100644 index 000000000..b0211358d --- /dev/null +++ b/tests/ui/error-codes/E0015.rs @@ -0,0 +1,8 @@ +fn create_some() -> Option { + Some(1) +} + +const FOO: Option = create_some(); +//~^ ERROR cannot call non-const fn `create_some` in constants [E0015] + +fn main() {} diff --git a/tests/ui/error-codes/E0015.stderr b/tests/ui/error-codes/E0015.stderr new file mode 100644 index 000000000..ec1ce47b2 --- /dev/null +++ b/tests/ui/error-codes/E0015.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `create_some` in constants + --> $DIR/E0015.rs:5:25 + | +LL | const FOO: Option = create_some(); + | ^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs new file mode 100644 index 000000000..c211ad1a2 --- /dev/null +++ b/tests/ui/error-codes/E0017.rs @@ -0,0 +1,14 @@ +static X: i32 = 1; +const C: i32 = 2; +static mut M: i32 = 3; + +const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed + //~| WARN taking a mutable +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 + //~| ERROR cannot borrow + //~| ERROR mutable references are not allowed + +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed + //~| WARN taking a mutable +static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not +fn main() {} diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr new file mode 100644 index 000000000..6e48f9582 --- /dev/null +++ b/tests/ui/error-codes/E0017.stderr @@ -0,0 +1,72 @@ +warning: taking a mutable reference to a `const` item + --> $DIR/E0017.rs:5:30 + | +LL | const CR: &'static mut i32 = &mut C; + | ^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/E0017.rs:2:1 + | +LL | const C: i32 = 2; + | ^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/E0017.rs:5:30 + | +LL | const CR: &'static mut i32 = &mut C; + | ^^^^^^ + +error[E0658]: mutation through a reference is not allowed in statics + --> $DIR/E0017.rs:7:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0017.rs:7:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ + +error[E0596]: cannot borrow immutable static item `X` as mutable + --> $DIR/E0017.rs:7:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ cannot borrow as mutable + +warning: taking a mutable reference to a `const` item + --> $DIR/E0017.rs:11:38 + | +LL | static CONST_REF: &'static mut i32 = &mut C; + | ^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/E0017.rs:2:1 + | +LL | const C: i32 = 2; + | ^^^^^^^^^^^^ + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0017.rs:11:38 + | +LL | static CONST_REF: &'static mut i32 = &mut C; + | ^^^^^^ + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0017.rs:13:52 + | +LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; + | ^^^^^^ + +error: aborting due to 6 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/error-codes/E0023.rs b/tests/ui/error-codes/E0023.rs new file mode 100644 index 000000000..7ac22bb71 --- /dev/null +++ b/tests/ui/error-codes/E0023.rs @@ -0,0 +1,17 @@ +enum Fruit { + Apple(String, String), + Pear(u32), + Orange((String, String)), + Banana(()), +} + +fn main() { + let x = Fruit::Apple(String::new(), String::new()); + match x { + Fruit::Apple(a) => {}, //~ ERROR E0023 + Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 + Fruit::Pear(1, 2) => {}, //~ ERROR E0023 + Fruit::Orange(a, b) => {}, //~ ERROR E0023 + Fruit::Banana() => {}, //~ ERROR E0023 + } +} diff --git a/tests/ui/error-codes/E0023.stderr b/tests/ui/error-codes/E0023.stderr new file mode 100644 index 000000000..3e321b037 --- /dev/null +++ b/tests/ui/error-codes/E0023.stderr @@ -0,0 +1,63 @@ +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/E0023.rs:11:22 + | +LL | Apple(String, String), + | ------ ------ tuple variant has 2 fields +... +LL | Fruit::Apple(a) => {}, + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Fruit::Apple(a, _) => {}, + | +++ + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/E0023.rs:12:22 + | +LL | Apple(String, String), + | ------ ------ tuple variant has 2 fields +... +LL | Fruit::Apple(a, b, c) => {}, + | ^ ^ ^ expected 2 fields, found 3 + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:13:21 + | +LL | Pear(u32), + | --- tuple variant has 1 field +... +LL | Fruit::Pear(1, 2) => {}, + | ^ ^ expected 1 field, found 2 + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:14:23 + | +LL | Orange((String, String)), + | ---------------- tuple variant has 1 field +... +LL | Fruit::Orange(a, b) => {}, + | ^ ^ expected 1 field, found 2 + | +help: missing parentheses + | +LL | Fruit::Orange((a, b)) => {}, + | + + + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:15:9 + | +LL | Banana(()), + | -- tuple variant has 1 field +... +LL | Fruit::Banana() => {}, + | ^^^^^^^^^^^^^^^ expected 1 field, found 0 + | +help: missing parentheses + | +LL | Fruit::Banana(()) => {}, + | + + + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/error-codes/E0025.rs b/tests/ui/error-codes/E0025.rs new file mode 100644 index 000000000..549269a75 --- /dev/null +++ b/tests/ui/error-codes/E0025.rs @@ -0,0 +1,10 @@ +struct Foo { + a: u8, + b: u8, +} + +fn main() { + let x = Foo { a:1, b:2 }; + let Foo { a: x, a: y, b: 0 } = x; + //~^ ERROR field `a` bound multiple times in the pattern +} diff --git a/tests/ui/error-codes/E0025.stderr b/tests/ui/error-codes/E0025.stderr new file mode 100644 index 000000000..dfec6d027 --- /dev/null +++ b/tests/ui/error-codes/E0025.stderr @@ -0,0 +1,11 @@ +error[E0025]: field `a` bound multiple times in the pattern + --> $DIR/E0025.rs:8:21 + | +LL | let Foo { a: x, a: y, b: 0 } = x; + | ---- ^^^^ multiple uses of `a` in pattern + | | + | first use of `a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0025`. diff --git a/tests/ui/error-codes/E0026-teach.rs b/tests/ui/error-codes/E0026-teach.rs new file mode 100644 index 000000000..7c51004ff --- /dev/null +++ b/tests/ui/error-codes/E0026-teach.rs @@ -0,0 +1,14 @@ +// compile-flags: -Z teach + +struct Thing { + x: u32, + y: u32 +} + +fn main() { + let thing = Thing { x: 0, y: 0 }; + match thing { + Thing { x, y, z } => {} + //~^ ERROR struct `Thing` does not have a field named `z` [E0026] + } +} diff --git a/tests/ui/error-codes/E0026-teach.stderr b/tests/ui/error-codes/E0026-teach.stderr new file mode 100644 index 000000000..1a80edcbb --- /dev/null +++ b/tests/ui/error-codes/E0026-teach.stderr @@ -0,0 +1,13 @@ +error[E0026]: struct `Thing` does not have a field named `z` + --> $DIR/E0026-teach.rs:11:23 + | +LL | Thing { x, y, z } => {} + | ^ struct `Thing` does not have this field + | + = note: This error indicates that a struct pattern attempted to extract a non-existent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched. + + If you are using shorthand field patterns but want to refer to the struct field by a different name, you should rename it explicitly. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0026`. diff --git a/tests/ui/error-codes/E0026.rs b/tests/ui/error-codes/E0026.rs new file mode 100644 index 000000000..0b1ea1c7b --- /dev/null +++ b/tests/ui/error-codes/E0026.rs @@ -0,0 +1,12 @@ +struct Thing { + x: u32, + y: u32 +} + +fn main() { + let thing = Thing { x: 0, y: 0 }; + match thing { + Thing { x, y, z } => {} + //~^ ERROR struct `Thing` does not have a field named `z` [E0026] + } +} diff --git a/tests/ui/error-codes/E0026.stderr b/tests/ui/error-codes/E0026.stderr new file mode 100644 index 000000000..031481812 --- /dev/null +++ b/tests/ui/error-codes/E0026.stderr @@ -0,0 +1,9 @@ +error[E0026]: struct `Thing` does not have a field named `z` + --> $DIR/E0026.rs:9:23 + | +LL | Thing { x, y, z } => {} + | ^ struct `Thing` does not have this field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0026`. diff --git a/tests/ui/error-codes/E0027.rs b/tests/ui/error-codes/E0027.rs new file mode 100644 index 000000000..e7eca1ce5 --- /dev/null +++ b/tests/ui/error-codes/E0027.rs @@ -0,0 +1,24 @@ +struct Dog { + name: String, + age: u32, +} + + +fn main() { + let d = Dog { name: "Rusty".to_string(), age: 8 }; + + match d { + Dog { age: x } => {} //~ ERROR pattern does not mention field `name` + } + match d { + // trailing comma + Dog { name: x, } => {} //~ ERROR pattern does not mention field `age` + } + match d { + // trailing comma with weird whitespace + Dog { name: x , } => {} //~ ERROR pattern does not mention field `age` + } + match d { + Dog {} => {} //~ ERROR pattern does not mention fields `name`, `age` + } +} diff --git a/tests/ui/error-codes/E0027.stderr b/tests/ui/error-codes/E0027.stderr new file mode 100644 index 000000000..9ae97e4a9 --- /dev/null +++ b/tests/ui/error-codes/E0027.stderr @@ -0,0 +1,63 @@ +error[E0027]: pattern does not mention field `name` + --> $DIR/E0027.rs:11:9 + | +LL | Dog { age: x } => {} + | ^^^^^^^^^^^^^^ missing field `name` + | +help: include the missing field in the pattern + | +LL | Dog { age: x, name } => {} + | ~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Dog { age: x, .. } => {} + | ~~~~~~ + +error[E0027]: pattern does not mention field `age` + --> $DIR/E0027.rs:15:9 + | +LL | Dog { name: x, } => {} + | ^^^^^^^^^^^^^^^^ missing field `age` + | +help: include the missing field in the pattern + | +LL | Dog { name: x, age } => {} + | ~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Dog { name: x, .. } => {} + | ~~~~~~ + +error[E0027]: pattern does not mention field `age` + --> $DIR/E0027.rs:19:9 + | +LL | Dog { name: x , } => {} + | ^^^^^^^^^^^^^^^^^^ missing field `age` + | +help: include the missing field in the pattern + | +LL | Dog { name: x, age } => {} + | ~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Dog { name: x, .. } => {} + | ~~~~~~ + +error[E0027]: pattern does not mention fields `name`, `age` + --> $DIR/E0027.rs:22:9 + | +LL | Dog {} => {} + | ^^^^^^ missing fields `name`, `age` + | +help: include the missing fields in the pattern + | +LL | Dog { name, age } => {} + | ~~~~~~~~~~~~~ +help: if you don't care about these missing fields, you can explicitly ignore them + | +LL | Dog { .. } => {} + | ~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/error-codes/E0029-teach.rs b/tests/ui/error-codes/E0029-teach.rs new file mode 100644 index 000000000..3ff8cb348 --- /dev/null +++ b/tests/ui/error-codes/E0029-teach.rs @@ -0,0 +1,11 @@ +// compile-flags: -Z teach + +fn main() { + let s = "hoho"; + + match s { + "hello" ..= "world" => {} + //~^ ERROR only `char` and numeric types are allowed in range patterns + _ => {} + } +} diff --git a/tests/ui/error-codes/E0029-teach.stderr b/tests/ui/error-codes/E0029-teach.stderr new file mode 100644 index 000000000..b89b2e7d1 --- /dev/null +++ b/tests/ui/error-codes/E0029-teach.stderr @@ -0,0 +1,14 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/E0029-teach.rs:7:9 + | +LL | "hello" ..= "world" => {} + | -------^^^^^------- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric + | + = note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/error-codes/E0029.rs b/tests/ui/error-codes/E0029.rs new file mode 100644 index 000000000..d9b53e113 --- /dev/null +++ b/tests/ui/error-codes/E0029.rs @@ -0,0 +1,9 @@ +fn main() { + let s = "hoho"; + + match s { + "hello" ..= "world" => {} + //~^ ERROR only `char` and numeric types are allowed in range patterns + _ => {} + } +} diff --git a/tests/ui/error-codes/E0029.stderr b/tests/ui/error-codes/E0029.stderr new file mode 100644 index 000000000..f7250b39d --- /dev/null +++ b/tests/ui/error-codes/E0029.stderr @@ -0,0 +1,12 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/E0029.rs:5:9 + | +LL | "hello" ..= "world" => {} + | -------^^^^^------- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/error-codes/E0030-teach.rs b/tests/ui/error-codes/E0030-teach.rs new file mode 100644 index 000000000..8caa4f093 --- /dev/null +++ b/tests/ui/error-codes/E0030-teach.rs @@ -0,0 +1,9 @@ +// compile-flags: -Z teach + +fn main() { + match 5u32 { + 1000 ..= 5 => {} + //~^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper + } +} diff --git a/tests/ui/error-codes/E0030-teach.stderr b/tests/ui/error-codes/E0030-teach.stderr new file mode 100644 index 000000000..800f66416 --- /dev/null +++ b/tests/ui/error-codes/E0030-teach.stderr @@ -0,0 +1,17 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/E0030-teach.rs:5:9 + | +LL | 1000 ..= 5 => {} + | ^^^^ lower bound larger than upper bound + | + = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/E0030-teach.rs:5:9 + | +LL | 1000 ..= 5 => {} + | ^^^^ lower bound larger than upper bound + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0030`. diff --git a/tests/ui/error-codes/E0030.rs b/tests/ui/error-codes/E0030.rs new file mode 100644 index 000000000..a5d8f8726 --- /dev/null +++ b/tests/ui/error-codes/E0030.rs @@ -0,0 +1,7 @@ +fn main() { + match 5u32 { + 1000 ..= 5 => {} + //~^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper + } +} diff --git a/tests/ui/error-codes/E0030.stderr b/tests/ui/error-codes/E0030.stderr new file mode 100644 index 000000000..8a6114024 --- /dev/null +++ b/tests/ui/error-codes/E0030.stderr @@ -0,0 +1,15 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/E0030.rs:3:9 + | +LL | 1000 ..= 5 => {} + | ^^^^ lower bound larger than upper bound + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/E0030.rs:3:9 + | +LL | 1000 ..= 5 => {} + | ^^^^ lower bound larger than upper bound + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0030`. diff --git a/tests/ui/error-codes/E0033-teach.rs b/tests/ui/error-codes/E0033-teach.rs new file mode 100644 index 000000000..289561bad --- /dev/null +++ b/tests/ui/error-codes/E0033-teach.rs @@ -0,0 +1,14 @@ +// compile-flags: -Z teach +trait SomeTrait { + fn foo(&self); +} +struct S; +impl SomeTrait for S { + fn foo(&self) {} +} +fn main() { + let trait_obj: &dyn SomeTrait = &S; + + let &invalid = trait_obj; + //~^ ERROR E0033 +} diff --git a/tests/ui/error-codes/E0033-teach.stderr b/tests/ui/error-codes/E0033-teach.stderr new file mode 100644 index 000000000..31bc6719a --- /dev/null +++ b/tests/ui/error-codes/E0033-teach.stderr @@ -0,0 +1,13 @@ +error[E0033]: type `&dyn SomeTrait` cannot be dereferenced + --> $DIR/E0033-teach.rs:12:9 + | +LL | let &invalid = trait_obj; + | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced + | + = note: This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer. + + You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0033`. diff --git a/tests/ui/error-codes/E0033.rs b/tests/ui/error-codes/E0033.rs new file mode 100644 index 000000000..bd6ec2072 --- /dev/null +++ b/tests/ui/error-codes/E0033.rs @@ -0,0 +1,13 @@ +trait SomeTrait { + fn foo(&self); +} +struct S; +impl SomeTrait for S { + fn foo(&self) {} +} +fn main() { + let trait_obj: &dyn SomeTrait = &S; + + let &invalid = trait_obj; + //~^ ERROR E0033 +} diff --git a/tests/ui/error-codes/E0033.stderr b/tests/ui/error-codes/E0033.stderr new file mode 100644 index 000000000..ab2e780ee --- /dev/null +++ b/tests/ui/error-codes/E0033.stderr @@ -0,0 +1,9 @@ +error[E0033]: type `&dyn SomeTrait` cannot be dereferenced + --> $DIR/E0033.rs:11:9 + | +LL | let &invalid = trait_obj; + | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0033`. diff --git a/tests/ui/error-codes/E0034.rs b/tests/ui/error-codes/E0034.rs new file mode 100644 index 000000000..f962da115 --- /dev/null +++ b/tests/ui/error-codes/E0034.rs @@ -0,0 +1,21 @@ +struct Test; + +trait Trait1 { + fn foo(); +} + +trait Trait2 { + fn foo(); +} + +impl Trait1 for Test { + fn foo() {} +} + +impl Trait2 for Test { + fn foo() {} +} + +fn main() { + Test::foo() //~ ERROR multiple applicable items in scope +} diff --git a/tests/ui/error-codes/E0034.stderr b/tests/ui/error-codes/E0034.stderr new file mode 100644 index 000000000..e29621702 --- /dev/null +++ b/tests/ui/error-codes/E0034.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/E0034.rs:20:11 + | +LL | Test::foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `Trait1` for the type `Test` + --> $DIR/E0034.rs:12:5 + | +LL | fn foo() {} + | ^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `Trait2` for the type `Test` + --> $DIR/E0034.rs:16:5 + | +LL | fn foo() {} + | ^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | ::foo() + | ~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | ::foo() + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/error-codes/E0038.rs b/tests/ui/error-codes/E0038.rs new file mode 100644 index 000000000..9757e2ab1 --- /dev/null +++ b/tests/ui/error-codes/E0038.rs @@ -0,0 +1,11 @@ +trait Trait { + fn foo(&self) -> Self; +} + +fn call_foo(x: Box) { + //~^ ERROR E0038 + let y = x.foo(); +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0038.stderr b/tests/ui/error-codes/E0038.stderr new file mode 100644 index 000000000..3773d6f52 --- /dev/null +++ b/tests/ui/error-codes/E0038.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/E0038.rs:5:20 + | +LL | fn call_foo(x: Box) { + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/E0038.rs:2:22 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | fn foo(&self) -> Self; + | ^^^^ ...because method `foo` references the `Self` type in its return type + = help: consider moving `foo` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/error-codes/E0040.fixed b/tests/ui/error-codes/E0040.fixed new file mode 100644 index 000000000..139dc8f94 --- /dev/null +++ b/tests/ui/error-codes/E0040.fixed @@ -0,0 +1,18 @@ +// run-rustfix +struct Foo { + x: i32, +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let mut x = Foo { x: -7 }; + x.x = 0; + println!("{}", x.x); + drop(x); + //~^ ERROR E0040 +} diff --git a/tests/ui/error-codes/E0040.rs b/tests/ui/error-codes/E0040.rs new file mode 100644 index 000000000..9ffc42d0c --- /dev/null +++ b/tests/ui/error-codes/E0040.rs @@ -0,0 +1,18 @@ +// run-rustfix +struct Foo { + x: i32, +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let mut x = Foo { x: -7 }; + x.x = 0; + println!("{}", x.x); + x.drop(); + //~^ ERROR E0040 +} diff --git a/tests/ui/error-codes/E0040.stderr b/tests/ui/error-codes/E0040.stderr new file mode 100644 index 000000000..9fcda1a93 --- /dev/null +++ b/tests/ui/error-codes/E0040.stderr @@ -0,0 +1,12 @@ +error[E0040]: explicit use of destructor method + --> $DIR/E0040.rs:16:7 + | +LL | x.drop(); + | --^^^^-- + | | | + | | explicit destructor calls not allowed + | help: consider using `drop` function: `drop(x)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/error-codes/E0044.rs b/tests/ui/error-codes/E0044.rs new file mode 100644 index 000000000..d9cdaf83c --- /dev/null +++ b/tests/ui/error-codes/E0044.rs @@ -0,0 +1,8 @@ +extern "C" { + fn sqrt(f: T) -> T; +//~^ ERROR foreign items may not have type parameters [E0044] +//~| HELP replace the type parameters with concrete types +//~| NOTE can't have type parameters +} + +fn main() {} diff --git a/tests/ui/error-codes/E0044.stderr b/tests/ui/error-codes/E0044.stderr new file mode 100644 index 000000000..e889c167b --- /dev/null +++ b/tests/ui/error-codes/E0044.stderr @@ -0,0 +1,11 @@ +error[E0044]: foreign items may not have type parameters + --> $DIR/E0044.rs:2:5 + | +LL | fn sqrt(f: T) -> T; + | ^^^^^^^^^^^^^^^^^^^^^^ can't have type parameters + | + = help: replace the type parameters with concrete types like `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/error-codes/E0045.rs b/tests/ui/error-codes/E0045.rs new file mode 100644 index 000000000..fb3df56f7 --- /dev/null +++ b/tests/ui/error-codes/E0045.rs @@ -0,0 +1,4 @@ +extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045 + +fn main() { +} diff --git a/tests/ui/error-codes/E0045.stderr b/tests/ui/error-codes/E0045.stderr new file mode 100644 index 000000000..fcc613b11 --- /dev/null +++ b/tests/ui/error-codes/E0045.stderr @@ -0,0 +1,9 @@ +error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + --> $DIR/E0045.rs:1:17 + | +LL | extern "Rust" { fn foo(x: u8, ...); } + | ^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0045`. diff --git a/tests/ui/error-codes/E0049.rs b/tests/ui/error-codes/E0049.rs new file mode 100644 index 000000000..3dd910019 --- /dev/null +++ b/tests/ui/error-codes/E0049.rs @@ -0,0 +1,22 @@ +trait Foo { + fn foo(x: T) -> Self; +} + +struct Bar; + +impl Foo for Bar { + fn foo(x: bool) -> Self { Bar } //~ ERROR E0049 +} + +trait Fuzz { + fn fuzz(x: A, y: B) -> Self; +} + +struct Baz; + +impl Fuzz for Baz { + fn fuzz(x: bool, y: bool) -> Self { Baz } //~ ERROR E0049 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0049.stderr b/tests/ui/error-codes/E0049.stderr new file mode 100644 index 000000000..c0cd31faa --- /dev/null +++ b/tests/ui/error-codes/E0049.stderr @@ -0,0 +1,23 @@ +error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/E0049.rs:8:11 + | +LL | fn foo(x: T) -> Self; + | - expected 1 type parameter +... +LL | fn foo(x: bool) -> Self { Bar } + | ^ found 0 type parameters + +error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters + --> $DIR/E0049.rs:18:12 + | +LL | fn fuzz(x: A, y: B) -> Self; + | - - + | | + | expected 2 type parameters +... +LL | fn fuzz(x: bool, y: bool) -> Self { Baz } + | ^ found 0 type parameters + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/error-codes/E0050.rs b/tests/ui/error-codes/E0050.rs new file mode 100644 index 000000000..98fb62785 --- /dev/null +++ b/tests/ui/error-codes/E0050.rs @@ -0,0 +1,16 @@ +trait Foo { + fn foo(&self, x: u8) -> bool; + fn bar(&self, x: u8, y: u8, z: u8); + fn less(&self); +} + +struct Bar; + +impl Foo for Bar { + fn foo(&self) -> bool { true } //~ ERROR E0050 + fn bar(&self) { } //~ ERROR E0050 + fn less(&self, x: u8, y: u8, z: u8) { } //~ ERROR E0050 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0050.stderr b/tests/ui/error-codes/E0050.stderr new file mode 100644 index 000000000..fe9ac5e8e --- /dev/null +++ b/tests/ui/error-codes/E0050.stderr @@ -0,0 +1,30 @@ +error[E0050]: method `foo` has 1 parameter but the declaration in trait `Foo::foo` has 2 + --> $DIR/E0050.rs:10:12 + | +LL | fn foo(&self, x: u8) -> bool; + | ------------ trait requires 2 parameters +... +LL | fn foo(&self) -> bool { true } + | ^^^^^ expected 2 parameters, found 1 + +error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 4 + --> $DIR/E0050.rs:11:12 + | +LL | fn bar(&self, x: u8, y: u8, z: u8); + | -------------------------- trait requires 4 parameters +... +LL | fn bar(&self) { } + | ^^^^^ expected 4 parameters, found 1 + +error[E0050]: method `less` has 4 parameters but the declaration in trait `Foo::less` has 1 + --> $DIR/E0050.rs:12:13 + | +LL | fn less(&self); + | ----- trait requires 1 parameter +... +LL | fn less(&self, x: u8, y: u8, z: u8) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter, found 4 + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/error-codes/E0054.rs b/tests/ui/error-codes/E0054.rs new file mode 100644 index 000000000..55bda4ead --- /dev/null +++ b/tests/ui/error-codes/E0054.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 5; + let x_is_nonzero = x as bool; //~ ERROR E0054 +} diff --git a/tests/ui/error-codes/E0054.stderr b/tests/ui/error-codes/E0054.stderr new file mode 100644 index 000000000..6b1092760 --- /dev/null +++ b/tests/ui/error-codes/E0054.stderr @@ -0,0 +1,9 @@ +error[E0054]: cannot cast as `bool` + --> $DIR/E0054.rs:3:24 + | +LL | let x_is_nonzero = x as bool; + | ^^^^^^^^^ help: compare with zero instead: `x != 0` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0054`. diff --git a/tests/ui/error-codes/E0055.rs b/tests/ui/error-codes/E0055.rs new file mode 100644 index 000000000..fd5804bbc --- /dev/null +++ b/tests/ui/error-codes/E0055.rs @@ -0,0 +1,13 @@ +#![recursion_limit="4"] +struct Foo; + +impl Foo { + fn foo(&self) {} +} + +fn main() { + let foo = Foo; + let ref_foo = &&&&&Foo; + ref_foo.foo(); + //~^ ERROR E0055 +} diff --git a/tests/ui/error-codes/E0055.stderr b/tests/ui/error-codes/E0055.stderr new file mode 100644 index 000000000..a52c90962 --- /dev/null +++ b/tests/ui/error-codes/E0055.stderr @@ -0,0 +1,11 @@ +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` + --> $DIR/E0055.rs:11:13 + | +LL | ref_foo.foo(); + | ^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`E0055`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0055`. diff --git a/tests/ui/error-codes/E0057.rs b/tests/ui/error-codes/E0057.rs new file mode 100644 index 000000000..83f941f65 --- /dev/null +++ b/tests/ui/error-codes/E0057.rs @@ -0,0 +1,6 @@ +fn main() { + let f = |x| x * 3; + let a = f(); //~ ERROR E0057 + let b = f(4); + let c = f(2, 3); //~ ERROR E0057 +} diff --git a/tests/ui/error-codes/E0057.stderr b/tests/ui/error-codes/E0057.stderr new file mode 100644 index 000000000..163737895 --- /dev/null +++ b/tests/ui/error-codes/E0057.stderr @@ -0,0 +1,35 @@ +error[E0057]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/E0057.rs:3:13 + | +LL | let a = f(); + | ^-- an argument is missing + | +note: closure defined here + --> $DIR/E0057.rs:2:13 + | +LL | let f = |x| x * 3; + | ^^^ +help: provide the argument + | +LL | let a = f(/* x */); + | ~~~~~~~~~ + +error[E0057]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/E0057.rs:5:13 + | +LL | let c = f(2, 3); + | ^ - argument of type `{integer}` unexpected + | +note: closure defined here + --> $DIR/E0057.rs:2:13 + | +LL | let f = |x| x * 3; + | ^^^ +help: remove the extra argument + | +LL | let c = f(2); + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/error-codes/E0059.rs b/tests/ui/error-codes/E0059.rs new file mode 100644 index 000000000..f775089bf --- /dev/null +++ b/tests/ui/error-codes/E0059.rs @@ -0,0 +1,6 @@ +#![feature(unboxed_closures)] + +fn foo>(f: F) -> F::Output { f(3) } //~ ERROR E0059 + +fn main() { +} diff --git a/tests/ui/error-codes/E0059.stderr b/tests/ui/error-codes/E0059.stderr new file mode 100644 index 000000000..4f6abb22a --- /dev/null +++ b/tests/ui/error-codes/E0059.stderr @@ -0,0 +1,12 @@ +error[E0059]: type parameter to bare `Fn` trait must be a tuple + --> $DIR/E0059.rs:3:11 + | +LL | fn foo>(f: F) -> F::Output { f(3) } + | ^^^^^^^ the trait `Tuple` is not implemented for `i32` + | +note: required by a bound in `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0059`. diff --git a/tests/ui/error-codes/E0060.rs b/tests/ui/error-codes/E0060.rs new file mode 100644 index 000000000..7050a1dff --- /dev/null +++ b/tests/ui/error-codes/E0060.rs @@ -0,0 +1,8 @@ +extern "C" { + fn printf(_: *const u8, ...) -> u32; +} + +fn main() { + unsafe { printf(); } + //~^ ERROR E0060 +} diff --git a/tests/ui/error-codes/E0060.stderr b/tests/ui/error-codes/E0060.stderr new file mode 100644 index 000000000..934a18d89 --- /dev/null +++ b/tests/ui/error-codes/E0060.stderr @@ -0,0 +1,19 @@ +error[E0060]: this function takes at least 1 argument but 0 arguments were supplied + --> $DIR/E0060.rs:6:14 + | +LL | unsafe { printf(); } + | ^^^^^^-- an argument of type `*const u8` is missing + | +note: function defined here + --> $DIR/E0060.rs:2:8 + | +LL | fn printf(_: *const u8, ...) -> u32; + | ^^^^^^ +help: provide the argument + | +LL | unsafe { printf(/* *const u8 */); } + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0060`. diff --git a/tests/ui/error-codes/E0061.rs b/tests/ui/error-codes/E0061.rs new file mode 100644 index 000000000..b6fae6c63 --- /dev/null +++ b/tests/ui/error-codes/E0061.rs @@ -0,0 +1,11 @@ +fn f(a: u16, b: &str) {} + +fn f2(a: u16) {} + +fn main() { + f(0); + //~^ ERROR E0061 + + f2(); + //~^ ERROR E0061 +} diff --git a/tests/ui/error-codes/E0061.stderr b/tests/ui/error-codes/E0061.stderr new file mode 100644 index 000000000..fa4ccbe66 --- /dev/null +++ b/tests/ui/error-codes/E0061.stderr @@ -0,0 +1,35 @@ +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/E0061.rs:6:5 + | +LL | f(0); + | ^--- an argument of type `&str` is missing + | +note: function defined here + --> $DIR/E0061.rs:1:4 + | +LL | fn f(a: u16, b: &str) {} + | ^ ------ ------- +help: provide the argument + | +LL | f(0, /* &str */); + | ~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/E0061.rs:9:5 + | +LL | f2(); + | ^^-- an argument of type `u16` is missing + | +note: function defined here + --> $DIR/E0061.rs:3:4 + | +LL | fn f2(a: u16) {} + | ^^ ------ +help: provide the argument + | +LL | f2(/* u16 */); + | ~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/error-codes/E0062.rs b/tests/ui/error-codes/E0062.rs new file mode 100644 index 000000000..3b7f88750 --- /dev/null +++ b/tests/ui/error-codes/E0062.rs @@ -0,0 +1,11 @@ +struct Foo { + x: i32 +} + +fn main() { + let x = Foo { + x: 0, + x: 0, + //~^ ERROR E0062 + }; +} diff --git a/tests/ui/error-codes/E0062.stderr b/tests/ui/error-codes/E0062.stderr new file mode 100644 index 000000000..a3e140995 --- /dev/null +++ b/tests/ui/error-codes/E0062.stderr @@ -0,0 +1,11 @@ +error[E0062]: field `x` specified more than once + --> $DIR/E0062.rs:8:9 + | +LL | x: 0, + | ---- first use of `x` +LL | x: 0, + | ^ used more than once + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0062`. diff --git a/tests/ui/error-codes/E0063.rs b/tests/ui/error-codes/E0063.rs new file mode 100644 index 000000000..48c9c13f0 --- /dev/null +++ b/tests/ui/error-codes/E0063.rs @@ -0,0 +1,38 @@ +struct SingleFoo { + x: i32 +} + +struct PluralFoo { + x: i32, + y: i32, + z: i32 +} + +struct TruncatedFoo { + a: i32, + b: i32, + x: i32, + y: i32, + z: i32 +} + +struct TruncatedPluralFoo { + a: i32, + b: i32, + c: i32, + x: i32, + y: i32, + z: i32 +} + + +fn main() { + let w = SingleFoo { }; + //~^ ERROR missing field `x` in initializer of `SingleFoo` + let x = PluralFoo {x: 1}; + //~^ ERROR missing fields `y` and `z` in initializer of `PluralFoo` + let y = TruncatedFoo{x:1}; + //~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` + let z = TruncatedPluralFoo{x:1}; + //~^ ERROR missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` +} diff --git a/tests/ui/error-codes/E0063.stderr b/tests/ui/error-codes/E0063.stderr new file mode 100644 index 000000000..235e20402 --- /dev/null +++ b/tests/ui/error-codes/E0063.stderr @@ -0,0 +1,27 @@ +error[E0063]: missing field `x` in initializer of `SingleFoo` + --> $DIR/E0063.rs:30:13 + | +LL | let w = SingleFoo { }; + | ^^^^^^^^^ missing `x` + +error[E0063]: missing fields `y` and `z` in initializer of `PluralFoo` + --> $DIR/E0063.rs:32:13 + | +LL | let x = PluralFoo {x: 1}; + | ^^^^^^^^^ missing `y` and `z` + +error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` + --> $DIR/E0063.rs:34:13 + | +LL | let y = TruncatedFoo{x:1}; + | ^^^^^^^^^^^^ missing `a`, `b`, `y` and 1 other field + +error[E0063]: missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` + --> $DIR/E0063.rs:36:13 + | +LL | let z = TruncatedPluralFoo{x:1}; + | ^^^^^^^^^^^^^^^^^^ missing `a`, `b`, `c` and 2 other fields + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/error-codes/E0067.rs b/tests/ui/error-codes/E0067.rs new file mode 100644 index 000000000..5925443dd --- /dev/null +++ b/tests/ui/error-codes/E0067.rs @@ -0,0 +1,6 @@ +use std::collections::LinkedList; + +fn main() { + LinkedList::new() += 1; //~ ERROR E0368 + //~^ ERROR E0067 +} diff --git a/tests/ui/error-codes/E0067.stderr b/tests/ui/error-codes/E0067.stderr new file mode 100644 index 000000000..ec0358cb7 --- /dev/null +++ b/tests/ui/error-codes/E0067.stderr @@ -0,0 +1,20 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `LinkedList<_>` + --> $DIR/E0067.rs:4:5 + | +LL | LinkedList::new() += 1; + | -----------------^^^^^ + | | + | cannot use `+=` on type `LinkedList<_>` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/E0067.rs:4:23 + | +LL | LinkedList::new() += 1; + | ----------------- ^^ + | | + | cannot assign to this expression + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0067, E0368. +For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/error-codes/E0069.rs b/tests/ui/error-codes/E0069.rs new file mode 100644 index 000000000..a4ba9fd8d --- /dev/null +++ b/tests/ui/error-codes/E0069.rs @@ -0,0 +1,7 @@ +fn foo() -> u8 { + return; + //~^ ERROR `return;` in a function whose return type is not `()` +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0069.stderr b/tests/ui/error-codes/E0069.stderr new file mode 100644 index 000000000..ff9bbe01d --- /dev/null +++ b/tests/ui/error-codes/E0069.stderr @@ -0,0 +1,11 @@ +error[E0069]: `return;` in a function whose return type is not `()` + --> $DIR/E0069.rs:2:5 + | +LL | fn foo() -> u8 { + | -- expected `u8` because of this return type +LL | return; + | ^^^^^^ return type is not `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0069`. diff --git a/tests/ui/error-codes/E0070.rs b/tests/ui/error-codes/E0070.rs new file mode 100644 index 000000000..3aae0c9ff --- /dev/null +++ b/tests/ui/error-codes/E0070.rs @@ -0,0 +1,12 @@ +const SOME_CONST : i32 = 12; + +fn some_other_func() {} + +fn some_function() { + SOME_CONST = 14; //~ ERROR E0070 + 1 = 3; //~ ERROR E0070 + some_other_func() = 4; //~ ERROR E0070 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0070.stderr b/tests/ui/error-codes/E0070.stderr new file mode 100644 index 000000000..8868bc257 --- /dev/null +++ b/tests/ui/error-codes/E0070.stderr @@ -0,0 +1,27 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/E0070.rs:6:16 + | +LL | SOME_CONST = 14; + | ---------- ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/E0070.rs:7:7 + | +LL | 1 = 3; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/E0070.rs:8:23 + | +LL | some_other_func() = 4; + | ----------------- ^ + | | + | cannot assign to this expression + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/error-codes/E0071.rs b/tests/ui/error-codes/E0071.rs new file mode 100644 index 000000000..bd8469de7 --- /dev/null +++ b/tests/ui/error-codes/E0071.rs @@ -0,0 +1,7 @@ +enum Foo {} +type FooAlias = Foo; + +fn main() { + let u = FooAlias { value: 0 }; + //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071] +} diff --git a/tests/ui/error-codes/E0071.stderr b/tests/ui/error-codes/E0071.stderr new file mode 100644 index 000000000..ae312fc40 --- /dev/null +++ b/tests/ui/error-codes/E0071.stderr @@ -0,0 +1,9 @@ +error[E0071]: expected struct, variant or union type, found enum `Foo` + --> $DIR/E0071.rs:5:13 + | +LL | let u = FooAlias { value: 0 }; + | ^^^^^^^^ not a struct + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0071`. diff --git a/tests/ui/error-codes/E0075.rs b/tests/ui/error-codes/E0075.rs new file mode 100644 index 000000000..7feab0a8b --- /dev/null +++ b/tests/ui/error-codes/E0075.rs @@ -0,0 +1,7 @@ +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad; //~ ERROR E0075 + +fn main() { +} diff --git a/tests/ui/error-codes/E0075.stderr b/tests/ui/error-codes/E0075.stderr new file mode 100644 index 000000000..3f927726a --- /dev/null +++ b/tests/ui/error-codes/E0075.stderr @@ -0,0 +1,9 @@ +error[E0075]: SIMD vector cannot be empty + --> $DIR/E0075.rs:4:1 + | +LL | struct Bad; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0075`. diff --git a/tests/ui/error-codes/E0076.rs b/tests/ui/error-codes/E0076.rs new file mode 100644 index 000000000..a27072eb7 --- /dev/null +++ b/tests/ui/error-codes/E0076.rs @@ -0,0 +1,8 @@ +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(u16, u32, u32); +//~^ ERROR E0076 + +fn main() { +} diff --git a/tests/ui/error-codes/E0076.stderr b/tests/ui/error-codes/E0076.stderr new file mode 100644 index 000000000..7d4ff8798 --- /dev/null +++ b/tests/ui/error-codes/E0076.stderr @@ -0,0 +1,9 @@ +error[E0076]: SIMD vector should be homogeneous + --> $DIR/E0076.rs:4:1 + | +LL | struct Bad(u16, u32, u32); + | ^^^^^^^^^^ SIMD elements must have the same type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0076`. diff --git a/tests/ui/error-codes/E0077.rs b/tests/ui/error-codes/E0077.rs new file mode 100644 index 000000000..fa2d5e24f --- /dev/null +++ b/tests/ui/error-codes/E0077.rs @@ -0,0 +1,7 @@ +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad(String); //~ ERROR E0077 + +fn main() { +} diff --git a/tests/ui/error-codes/E0077.stderr b/tests/ui/error-codes/E0077.stderr new file mode 100644 index 000000000..9a84b2ec4 --- /dev/null +++ b/tests/ui/error-codes/E0077.stderr @@ -0,0 +1,9 @@ +error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type + --> $DIR/E0077.rs:4:1 + | +LL | struct Bad(String); + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0077`. diff --git a/tests/ui/error-codes/E0080.rs b/tests/ui/error-codes/E0080.rs new file mode 100644 index 000000000..ea3264b61 --- /dev/null +++ b/tests/ui/error-codes/E0080.rs @@ -0,0 +1,8 @@ +enum Enum { + X = (1 << 500), //~ ERROR E0080 + //~| attempt to shift left by `500_i32`, which would overflow + Y = (1 / 0) //~ ERROR E0080 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0080.stderr b/tests/ui/error-codes/E0080.stderr new file mode 100644 index 000000000..60ed9a435 --- /dev/null +++ b/tests/ui/error-codes/E0080.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/E0080.rs:2:9 + | +LL | X = (1 << 500), + | ^^^^^^^^^^ attempt to shift left by `500_i32`, which would overflow + +error[E0080]: evaluation of constant value failed + --> $DIR/E0080.rs:4:9 + | +LL | Y = (1 / 0) + | ^^^^^^^ attempt to divide `1_isize` by zero + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/error-codes/E0081.rs b/tests/ui/error-codes/E0081.rs new file mode 100644 index 000000000..f53fda864 --- /dev/null +++ b/tests/ui/error-codes/E0081.rs @@ -0,0 +1,54 @@ +enum Enum { + //~^ ERROR discriminant value `3` assigned more than once + P = 3, + //~^ NOTE `3` assigned here + X = 3, + //~^ NOTE `3` assigned here + Y = 5 +} + +#[repr(u8)] +enum EnumOverflowRepr { + //~^ ERROR discriminant value `1` assigned more than once + P = 257, + //~^ NOTE `1` (overflowed from `257`) assigned here + X = 513, + //~^ NOTE `1` (overflowed from `513`) assigned here +} + +#[repr(i8)] +enum NegDisEnum { + //~^ ERROR discriminant value `-1` assigned more than once + First = -1, + //~^ NOTE `-1` assigned here + Second = -2, + //~^ NOTE discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1) + Last, + //~^ NOTE `-1` assigned here +} + +enum MultipleDuplicates { + //~^ ERROR discriminant value `0` assigned more than once + //~^^ ERROR discriminant value `-2` assigned more than once + V0, + //~^ NOTE `0` assigned here + V1 = 0, + //~^ NOTE `0` assigned here + V2, + V3, + V4 = 0, + //~^ NOTE `0` assigned here + V5 = -2, + //~^ NOTE discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0) + //~^^ NOTE `-2` assigned here + V6, + V7, + //~^ NOTE `0` assigned here + V8 = -3, + //~^ NOTE discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2) + V9, + //~^ NOTE `-2` assigned here +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0081.stderr b/tests/ui/error-codes/E0081.stderr new file mode 100644 index 000000000..d4b21f689 --- /dev/null +++ b/tests/ui/error-codes/E0081.stderr @@ -0,0 +1,78 @@ +error[E0081]: discriminant value `3` assigned more than once + --> $DIR/E0081.rs:1:1 + | +LL | enum Enum { + | ^^^^^^^^^ +LL | +LL | P = 3, + | - `3` assigned here +LL | +LL | X = 3, + | - `3` assigned here + +error[E0081]: discriminant value `1` assigned more than once + --> $DIR/E0081.rs:11:1 + | +LL | enum EnumOverflowRepr { + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | P = 257, + | --- `1` (overflowed from `257`) assigned here +LL | +LL | X = 513, + | --- `1` (overflowed from `513`) assigned here + +error[E0081]: discriminant value `-1` assigned more than once + --> $DIR/E0081.rs:20:1 + | +LL | enum NegDisEnum { + | ^^^^^^^^^^^^^^^ +LL | +LL | First = -1, + | -- `-1` assigned here +LL | +LL | Second = -2, + | ------ discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1) +LL | +LL | Last, + | ---- `-1` assigned here + +error[E0081]: discriminant value `0` assigned more than once + --> $DIR/E0081.rs:30:1 + | +LL | enum MultipleDuplicates { + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | V0, + | -- `0` assigned here +LL | +LL | V1 = 0, + | - `0` assigned here +... +LL | V4 = 0, + | - `0` assigned here +LL | +LL | V5 = -2, + | -- discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0) +... +LL | V7, + | -- `0` assigned here + +error[E0081]: discriminant value `-2` assigned more than once + --> $DIR/E0081.rs:30:1 + | +LL | enum MultipleDuplicates { + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | V5 = -2, + | -- `-2` assigned here +... +LL | V8 = -3, + | -- discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2) +LL | +LL | V9, + | -- `-2` assigned here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0081`. diff --git a/tests/ui/error-codes/E0084.rs b/tests/ui/error-codes/E0084.rs new file mode 100644 index 000000000..a550e0412 --- /dev/null +++ b/tests/ui/error-codes/E0084.rs @@ -0,0 +1,5 @@ +#[repr(i32)] //~ ERROR: E0084 +enum Foo {} + +fn main() { +} diff --git a/tests/ui/error-codes/E0084.stderr b/tests/ui/error-codes/E0084.stderr new file mode 100644 index 000000000..e1bda22b8 --- /dev/null +++ b/tests/ui/error-codes/E0084.stderr @@ -0,0 +1,11 @@ +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/E0084.rs:1:1 + | +LL | #[repr(i32)] + | ^^^^^^^^^^^^ +LL | enum Foo {} + | -------- zero-variant enum + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0084`. diff --git a/tests/ui/error-codes/E0091.rs b/tests/ui/error-codes/E0091.rs new file mode 100644 index 000000000..2427f5cfe --- /dev/null +++ b/tests/ui/error-codes/E0091.rs @@ -0,0 +1,5 @@ +type Foo = u32; //~ ERROR E0091 +type Foo2 = Box; //~ ERROR E0091 + +fn main() { +} diff --git a/tests/ui/error-codes/E0091.stderr b/tests/ui/error-codes/E0091.stderr new file mode 100644 index 000000000..a596b75e4 --- /dev/null +++ b/tests/ui/error-codes/E0091.stderr @@ -0,0 +1,15 @@ +error[E0091]: type parameter `T` is unused + --> $DIR/E0091.rs:1:10 + | +LL | type Foo = u32; + | ^ unused type parameter + +error[E0091]: type parameter `B` is unused + --> $DIR/E0091.rs:2:14 + | +LL | type Foo2 = Box; + | ^ unused type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0091`. diff --git a/tests/ui/error-codes/E0092.rs b/tests/ui/error-codes/E0092.rs new file mode 100644 index 000000000..ddaace98b --- /dev/null +++ b/tests/ui/error-codes/E0092.rs @@ -0,0 +1,7 @@ +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn atomic_foo(); //~ ERROR E0092 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0092.stderr b/tests/ui/error-codes/E0092.stderr new file mode 100644 index 000000000..2d590a8e1 --- /dev/null +++ b/tests/ui/error-codes/E0092.stderr @@ -0,0 +1,9 @@ +error[E0092]: unrecognized atomic operation function: `foo` + --> $DIR/E0092.rs:3:5 + | +LL | fn atomic_foo(); + | ^^^^^^^^^^^^^^^^ unrecognized atomic operation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0092`. diff --git a/tests/ui/error-codes/E0093.rs b/tests/ui/error-codes/E0093.rs new file mode 100644 index 000000000..a2f0b1ae4 --- /dev/null +++ b/tests/ui/error-codes/E0093.rs @@ -0,0 +1,8 @@ +#![feature(intrinsics)] +extern "rust-intrinsic" { + fn foo(); + //~^ ERROR E0093 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0093.stderr b/tests/ui/error-codes/E0093.stderr new file mode 100644 index 000000000..cb0305593 --- /dev/null +++ b/tests/ui/error-codes/E0093.stderr @@ -0,0 +1,9 @@ +error[E0093]: unrecognized intrinsic function: `foo` + --> $DIR/E0093.rs:3:5 + | +LL | fn foo(); + | ^^^^^^^^^ unrecognized intrinsic + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0093`. diff --git a/tests/ui/error-codes/E0094.rs b/tests/ui/error-codes/E0094.rs new file mode 100644 index 000000000..a2ec932c1 --- /dev/null +++ b/tests/ui/error-codes/E0094.rs @@ -0,0 +1,9 @@ +#![feature(intrinsics)] + +extern "rust-intrinsic" { + #[rustc_safe_intrinsic] + fn size_of() -> usize; //~ ERROR E0094 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0094.stderr b/tests/ui/error-codes/E0094.stderr new file mode 100644 index 000000000..531cd4c78 --- /dev/null +++ b/tests/ui/error-codes/E0094.stderr @@ -0,0 +1,9 @@ +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/E0094.rs:5:15 + | +LL | fn size_of() -> usize; + | ^^^^^^ expected 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0094`. diff --git a/tests/ui/error-codes/E0106.rs b/tests/ui/error-codes/E0106.rs new file mode 100644 index 000000000..cc3438727 --- /dev/null +++ b/tests/ui/error-codes/E0106.rs @@ -0,0 +1,26 @@ +struct Foo { + x: &bool, + //~^ ERROR E0106 +} +enum Bar { + A(u8), + B(&bool), + //~^ ERROR E0106 +} +type MyStr = &str; + //~^ ERROR E0106 + +struct Baz<'a>(&'a str); +struct Buzz<'a, 'b>(&'a str, &'b str); + +struct Quux { + baz: Baz, + //~^ ERROR E0106 + //~| expected named lifetime parameter + buzz: Buzz, + //~^ ERROR E0106 + //~| expected 2 lifetime parameters +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0106.stderr b/tests/ui/error-codes/E0106.stderr new file mode 100644 index 000000000..d11a24f77 --- /dev/null +++ b/tests/ui/error-codes/E0106.stderr @@ -0,0 +1,66 @@ +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:2:8 + | +LL | x: &bool, + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct Foo<'a> { +LL ~ x: &'a bool, + | + +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:7:7 + | +LL | B(&bool), + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ enum Bar<'a> { +LL | A(u8), +LL ~ B(&'a bool), + | + +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:10:14 + | +LL | type MyStr = &str; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type MyStr<'a> = &'a str; + | ++++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/E0106.rs:17:10 + | +LL | baz: Baz, + | ^^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct Quux<'a> { +LL ~ baz: Baz<'a>, + | + +error[E0106]: missing lifetime specifiers + --> $DIR/E0106.rs:20:11 + | +LL | buzz: Buzz, + | ^^^^ expected 2 lifetime parameters + | +help: consider introducing a named lifetime parameter + | +LL ~ struct Quux<'a> { +LL | baz: Baz, +LL | +LL | +LL ~ buzz: Buzz<'a, 'a>, + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/error-codes/E0107.rs b/tests/ui/error-codes/E0107.rs new file mode 100644 index 000000000..d369fc2a5 --- /dev/null +++ b/tests/ui/error-codes/E0107.rs @@ -0,0 +1,60 @@ +struct Foo<'a>(&'a str); +struct Buzz<'a, 'b>(&'a str, &'b str); +struct Qux<'a, T>(&'a T); +struct Quux(T); + +enum Bar { + A, + B, + C, +} + +struct Baz<'a, 'b, 'c> { + buzz: Buzz<'a>, + //~^ ERROR this struct takes 2 lifetime arguments + //~| HELP add missing lifetime argument + + bar: Bar<'a>, + //~^ ERROR this enum takes 0 lifetime arguments + //~| HELP remove these generics + + foo2: Foo<'a, 'b, 'c>, + //~^ ERROR this struct takes 1 lifetime argument + //~| HELP remove these lifetime arguments + + qux1: Qux<'a, 'b, i32>, + //~^ ERROR this struct takes 1 lifetime argument + //~| HELP remove this lifetime argument + + qux2: Qux<'a, i32, 'b>, + //~^ ERROR this struct takes 1 lifetime argument + //~| HELP remove this lifetime argument + + qux3: Qux<'a, 'b, 'c, i32>, + //~^ ERROR this struct takes 1 lifetime argument + //~| HELP remove these lifetime arguments + + qux4: Qux<'a, i32, 'b, 'c>, + //~^ ERROR this struct takes 1 lifetime argument + //~| HELP remove these lifetime arguments + + qux5: Qux<'a, 'b, i32, 'c>, + //~^ ERROR this struct takes 1 lifetime argument + //~| HELP remove this lifetime argument + + quux: Quux<'a, i32, 'b>, + //~^ ERROR this struct takes 0 lifetime arguments + //~| HELP remove this lifetime argument +} + +pub trait T { + type A; + type B; +} + +fn trait_bound_generic>(_i: I) { + //~^ ERROR this trait takes 0 generic arguments + //~| HELP replace the generic bounds with the associated types +} + +fn main() {} diff --git a/tests/ui/error-codes/E0107.stderr b/tests/ui/error-codes/E0107.stderr new file mode 100644 index 000000000..03430f8fa --- /dev/null +++ b/tests/ui/error-codes/E0107.stderr @@ -0,0 +1,149 @@ +error[E0107]: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/E0107.rs:13:11 + | +LL | buzz: Buzz<'a>, + | ^^^^ -- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: struct defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/E0107.rs:2:8 + | +LL | struct Buzz<'a, 'b>(&'a str, &'b str); + | ^^^^ -- -- +help: add missing lifetime argument + | +LL | buzz: Buzz<'a, 'a>, + | ++++ + +error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/E0107.rs:17:10 + | +LL | bar: Bar<'a>, + | ^^^---- help: remove these generics + | | + | expected 0 lifetime arguments + | +note: enum defined here, with 0 lifetime parameters + --> $DIR/E0107.rs:6:6 + | +LL | enum Bar { + | ^^^ + +error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/E0107.rs:21:11 + | +LL | foo2: Foo<'a, 'b, 'c>, + | ^^^ ------ help: remove these lifetime arguments + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/E0107.rs:1:8 + | +LL | struct Foo<'a>(&'a str); + | ^^^ -- + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/E0107.rs:25:11 + | +LL | qux1: Qux<'a, 'b, i32>, + | ^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/E0107.rs:3:8 + | +LL | struct Qux<'a, T>(&'a T); + | ^^^ -- + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/E0107.rs:29:11 + | +LL | qux2: Qux<'a, i32, 'b>, + | ^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/E0107.rs:3:8 + | +LL | struct Qux<'a, T>(&'a T); + | ^^^ -- + +error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/E0107.rs:33:11 + | +LL | qux3: Qux<'a, 'b, 'c, i32>, + | ^^^ ------ help: remove these lifetime arguments + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/E0107.rs:3:8 + | +LL | struct Qux<'a, T>(&'a T); + | ^^^ -- + +error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/E0107.rs:37:11 + | +LL | qux4: Qux<'a, i32, 'b, 'c>, + | ^^^ ------ help: remove these lifetime arguments + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/E0107.rs:3:8 + | +LL | struct Qux<'a, T>(&'a T); + | ^^^ -- + +error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied + --> $DIR/E0107.rs:41:11 + | +LL | qux5: Qux<'a, 'b, i32, 'c>, + | ^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/E0107.rs:3:8 + | +LL | struct Qux<'a, T>(&'a T); + | ^^^ -- + +error[E0107]: this struct takes 0 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/E0107.rs:45:11 + | +LL | quux: Quux<'a, i32, 'b>, + | ^^^^ -- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/E0107.rs:4:8 + | +LL | struct Quux(T); + | ^^^^ + +error[E0107]: this trait takes 0 generic arguments but 2 generic arguments were supplied + --> $DIR/E0107.rs:55:27 + | +LL | fn trait_bound_generic>(_i: I) { + | ^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/E0107.rs:50:11 + | +LL | pub trait T { + | ^ +help: replace the generic bounds with the associated types + | +LL | fn trait_bound_generic>(_i: I) { + | +++ +++ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/error-codes/E0109.rs b/tests/ui/error-codes/E0109.rs new file mode 100644 index 000000000..2e3825649 --- /dev/null +++ b/tests/ui/error-codes/E0109.rs @@ -0,0 +1,4 @@ +type X = u32; //~ ERROR E0109 + +fn main() { +} diff --git a/tests/ui/error-codes/E0109.stderr b/tests/ui/error-codes/E0109.stderr new file mode 100644 index 000000000..8f4cb86de --- /dev/null +++ b/tests/ui/error-codes/E0109.stderr @@ -0,0 +1,17 @@ +error[E0109]: type arguments are not allowed on builtin type `u32` + --> $DIR/E0109.rs:1:14 + | +LL | type X = u32; + | --- ^^^ type argument not allowed + | | + | not allowed on builtin type `u32` + | +help: primitive type `u32` doesn't have generic parameters + | +LL - type X = u32; +LL + type X = u32; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/error-codes/E0110.rs b/tests/ui/error-codes/E0110.rs new file mode 100644 index 000000000..314c7f5af --- /dev/null +++ b/tests/ui/error-codes/E0110.rs @@ -0,0 +1,3 @@ +type X = u32<'static>; //~ ERROR E0109 + +fn main() {} diff --git a/tests/ui/error-codes/E0110.stderr b/tests/ui/error-codes/E0110.stderr new file mode 100644 index 000000000..4ce2a0a41 --- /dev/null +++ b/tests/ui/error-codes/E0110.stderr @@ -0,0 +1,17 @@ +error[E0109]: lifetime arguments are not allowed on builtin type `u32` + --> $DIR/E0110.rs:1:14 + | +LL | type X = u32<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `u32` + | +help: primitive type `u32` doesn't have generic parameters + | +LL - type X = u32<'static>; +LL + type X = u32; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/error-codes/E0116.rs b/tests/ui/error-codes/E0116.rs new file mode 100644 index 000000000..898beb10b --- /dev/null +++ b/tests/ui/error-codes/E0116.rs @@ -0,0 +1,5 @@ +impl Vec {} +//~^ ERROR E0116 + +fn main() { +} diff --git a/tests/ui/error-codes/E0116.stderr b/tests/ui/error-codes/E0116.stderr new file mode 100644 index 000000000..a5ceeb4a5 --- /dev/null +++ b/tests/ui/error-codes/E0116.stderr @@ -0,0 +1,11 @@ +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/E0116.rs:1:1 + | +LL | impl Vec {} + | ^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0116`. diff --git a/tests/ui/error-codes/E0117.rs b/tests/ui/error-codes/E0117.rs new file mode 100644 index 000000000..406d24e36 --- /dev/null +++ b/tests/ui/error-codes/E0117.rs @@ -0,0 +1,4 @@ +impl Drop for u32 {} //~ ERROR E0117 +//~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions + +fn main() {} diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr new file mode 100644 index 000000000..f144aa9f7 --- /dev/null +++ b/tests/ui/error-codes/E0117.stderr @@ -0,0 +1,21 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/E0117.rs:1:1 + | +LL | impl Drop for u32 {} + | ^^^^^^^^^^^^^^--- + | | | + | | `u32` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/E0117.rs:1:15 + | +LL | impl Drop for u32 {} + | ^^^ must be a struct, enum, or union in the current crate + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0117, E0120. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/error-codes/E0118.rs b/tests/ui/error-codes/E0118.rs new file mode 100644 index 000000000..a61ba7bbf --- /dev/null +++ b/tests/ui/error-codes/E0118.rs @@ -0,0 +1,7 @@ +impl T { //~ ERROR E0118 + fn get_state(&self) -> String { + String::new() + } +} + +fn main() {} diff --git a/tests/ui/error-codes/E0118.stderr b/tests/ui/error-codes/E0118.stderr new file mode 100644 index 000000000..8c6fa7947 --- /dev/null +++ b/tests/ui/error-codes/E0118.stderr @@ -0,0 +1,11 @@ +error[E0118]: no nominal type found for inherent implementation + --> $DIR/E0118.rs:1:9 + | +LL | impl T { + | ^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0118`. diff --git a/tests/ui/error-codes/E0119.rs b/tests/ui/error-codes/E0119.rs new file mode 100644 index 000000000..7f89e5a1a --- /dev/null +++ b/tests/ui/error-codes/E0119.rs @@ -0,0 +1,18 @@ +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for T { + fn get(&self) -> usize { 0 } +} + +struct Foo { + value: usize +} + +impl MyTrait for Foo { //~ ERROR E0119 + fn get(&self) -> usize { self.value } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0119.stderr b/tests/ui/error-codes/E0119.stderr new file mode 100644 index 000000000..e08a2c7fc --- /dev/null +++ b/tests/ui/error-codes/E0119.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `Foo` + --> $DIR/E0119.rs:13:1 + | +LL | impl MyTrait for T { + | --------------------- first implementation here +... +LL | impl MyTrait for Foo { + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/E0120.rs b/tests/ui/error-codes/E0120.rs new file mode 100644 index 000000000..a0a301a06 --- /dev/null +++ b/tests/ui/error-codes/E0120.rs @@ -0,0 +1,8 @@ +trait MyTrait { fn foo() {} } + +impl Drop for dyn MyTrait { + //~^ ERROR E0120 + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/error-codes/E0120.stderr b/tests/ui/error-codes/E0120.stderr new file mode 100644 index 000000000..75778f1f9 --- /dev/null +++ b/tests/ui/error-codes/E0120.stderr @@ -0,0 +1,9 @@ +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/E0120.rs:3:15 + | +LL | impl Drop for dyn MyTrait { + | ^^^^^^^^^^^ must be a struct, enum, or union in the current crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0120`. diff --git a/tests/ui/error-codes/E0121.rs b/tests/ui/error-codes/E0121.rs new file mode 100644 index 000000000..98cd6d54c --- /dev/null +++ b/tests/ui/error-codes/E0121.rs @@ -0,0 +1,5 @@ +fn foo() -> _ { 5 } //~ ERROR E0121 + +static BAR: _ = "test"; //~ ERROR E0121 + +fn main() {} diff --git a/tests/ui/error-codes/E0121.stderr b/tests/ui/error-codes/E0121.stderr new file mode 100644 index 000000000..023d7e011 --- /dev/null +++ b/tests/ui/error-codes/E0121.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/E0121.rs:1:13 + | +LL | fn foo() -> _ { 5 } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/E0121.rs:3:13 + | +LL | static BAR: _ = "test"; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/error-codes/E0124.rs b/tests/ui/error-codes/E0124.rs new file mode 100644 index 000000000..9d6a716a6 --- /dev/null +++ b/tests/ui/error-codes/E0124.rs @@ -0,0 +1,8 @@ +struct Foo { + field1: i32, + field1: i32, + //~^ ERROR field `field1` is already declared [E0124] +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0124.stderr b/tests/ui/error-codes/E0124.stderr new file mode 100644 index 000000000..73819a89d --- /dev/null +++ b/tests/ui/error-codes/E0124.stderr @@ -0,0 +1,11 @@ +error[E0124]: field `field1` is already declared + --> $DIR/E0124.rs:3:5 + | +LL | field1: i32, + | ----------- `field1` first declared here +LL | field1: i32, + | ^^^^^^^^^^^ field already declared + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/error-codes/E0128.rs b/tests/ui/error-codes/E0128.rs new file mode 100644 index 000000000..f42c32b91 --- /dev/null +++ b/tests/ui/error-codes/E0128.rs @@ -0,0 +1,7 @@ +struct Foo { //~ ERROR E0128 + field1: T, + field2: U, +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0128.stderr b/tests/ui/error-codes/E0128.stderr new file mode 100644 index 000000000..eb66d4693 --- /dev/null +++ b/tests/ui/error-codes/E0128.stderr @@ -0,0 +1,9 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/E0128.rs:1:14 + | +LL | struct Foo { + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/error-codes/E0130.rs b/tests/ui/error-codes/E0130.rs new file mode 100644 index 000000000..d52350789 --- /dev/null +++ b/tests/ui/error-codes/E0130.rs @@ -0,0 +1,6 @@ +extern "C" { + fn foo((a, b): (u32, u32)); +//~^ ERROR E0130 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0130.stderr b/tests/ui/error-codes/E0130.stderr new file mode 100644 index 000000000..a45571f40 --- /dev/null +++ b/tests/ui/error-codes/E0130.stderr @@ -0,0 +1,9 @@ +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/E0130.rs:2:12 + | +LL | fn foo((a, b): (u32, u32)); + | ^^^^^^ pattern not allowed in foreign function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0130`. diff --git a/tests/ui/error-codes/E0131.rs b/tests/ui/error-codes/E0131.rs new file mode 100644 index 000000000..3ed739949 --- /dev/null +++ b/tests/ui/error-codes/E0131.rs @@ -0,0 +1,3 @@ +fn main() { + //~^ ERROR E0131 +} diff --git a/tests/ui/error-codes/E0131.stderr b/tests/ui/error-codes/E0131.stderr new file mode 100644 index 000000000..4467e19e9 --- /dev/null +++ b/tests/ui/error-codes/E0131.stderr @@ -0,0 +1,9 @@ +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/E0131.rs:1:8 + | +LL | fn main() { + | ^^^ `main` cannot have generic parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/error-codes/E0132.rs b/tests/ui/error-codes/E0132.rs new file mode 100644 index 000000000..fb5e5d7b9 --- /dev/null +++ b/tests/ui/error-codes/E0132.rs @@ -0,0 +1,7 @@ +#![feature(start)] + +#[start] +fn f< T >() {} //~ ERROR E0132 + +fn main() { +} diff --git a/tests/ui/error-codes/E0132.stderr b/tests/ui/error-codes/E0132.stderr new file mode 100644 index 000000000..c21363756 --- /dev/null +++ b/tests/ui/error-codes/E0132.stderr @@ -0,0 +1,9 @@ +error[E0132]: start function is not allowed to have type parameters + --> $DIR/E0132.rs:4:5 + | +LL | fn f< T >() {} + | ^^^^^ start function cannot have type parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0132`. diff --git a/tests/ui/error-codes/E0133.mir.stderr b/tests/ui/error-codes/E0133.mir.stderr new file mode 100644 index 000000000..b11d5e2c2 --- /dev/null +++ b/tests/ui/error-codes/E0133.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/E0133.rs:7:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/error-codes/E0133.rs b/tests/ui/error-codes/E0133.rs new file mode 100644 index 000000000..dee1475ba --- /dev/null +++ b/tests/ui/error-codes/E0133.rs @@ -0,0 +1,9 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +unsafe fn f() { return; } + +fn main() { + f(); + //~^ ERROR E0133 +} diff --git a/tests/ui/error-codes/E0133.thir.stderr b/tests/ui/error-codes/E0133.thir.stderr new file mode 100644 index 000000000..f1d7aba2a --- /dev/null +++ b/tests/ui/error-codes/E0133.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block + --> $DIR/E0133.rs:7:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/error-codes/E0138.rs b/tests/ui/error-codes/E0138.rs new file mode 100644 index 000000000..6f3c36282 --- /dev/null +++ b/tests/ui/error-codes/E0138.rs @@ -0,0 +1,8 @@ +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize { 0 } +//~^ ERROR E0138 diff --git a/tests/ui/error-codes/E0138.stderr b/tests/ui/error-codes/E0138.stderr new file mode 100644 index 000000000..fa8c39427 --- /dev/null +++ b/tests/ui/error-codes/E0138.stderr @@ -0,0 +1,12 @@ +error[E0138]: multiple `start` functions + --> $DIR/E0138.rs:7:1 + | +LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } + | ---------------------------------------------------- previous `#[start]` function here +... +LL | fn f(argc: isize, argv: *const *const u8) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0138`. diff --git a/tests/ui/error-codes/E0152.rs b/tests/ui/error-codes/E0152.rs new file mode 100644 index 000000000..ee8e5e6df --- /dev/null +++ b/tests/ui/error-codes/E0152.rs @@ -0,0 +1,8 @@ +// normalize-stderr-test "loaded from .*liballoc-.*.rlib" -> "loaded from SYSROOT/liballoc-*.rlib" +#![feature(lang_items)] + +#[lang = "owned_box"] +struct Foo(T); //~ ERROR E0152 + +fn main() { +} diff --git a/tests/ui/error-codes/E0152.stderr b/tests/ui/error-codes/E0152.stderr new file mode 100644 index 000000000..29f7e4ad6 --- /dev/null +++ b/tests/ui/error-codes/E0152.stderr @@ -0,0 +1,13 @@ +error[E0152]: found duplicate lang item `owned_box` + --> $DIR/E0152.rs:5:1 + | +LL | struct Foo(T); + | ^^^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `alloc` (which `std` depends on) + = note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib + = note: second definition in the local crate (`E0152`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/error-codes/E0161.base.stderr b/tests/ui/error-codes/E0161.base.stderr new file mode 100644 index 000000000..15d98b657 --- /dev/null +++ b/tests/ui/error-codes/E0161.base.stderr @@ -0,0 +1,9 @@ +error[E0161]: cannot move a value of type `dyn Bar` + --> $DIR/E0161.rs:16:5 + | +LL | x.f(); + | ^^^^^ the size of `dyn Bar` cannot be statically determined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0161`. diff --git a/tests/ui/error-codes/E0161.rs b/tests/ui/error-codes/E0161.rs new file mode 100644 index 000000000..c906e3c35 --- /dev/null +++ b/tests/ui/error-codes/E0161.rs @@ -0,0 +1,20 @@ +// Check that E0161 is a hard error in all possible configurations that might +// affect it. + +// revisions: base ul +//[base] check-fail +//[ul] check-pass + +#![allow(incomplete_features)] +#![cfg_attr(ul, feature(unsized_locals))] + +trait Bar { + fn f(self); +} + +fn foo(x: Box) { + x.f(); + //[base]~^ ERROR E0161 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0164.rs b/tests/ui/error-codes/E0164.rs new file mode 100644 index 000000000..2d412f754 --- /dev/null +++ b/tests/ui/error-codes/E0164.rs @@ -0,0 +1,14 @@ +enum Foo {} + +impl Foo { + const B: u8 = 0; +} + +fn bar(foo: Foo) -> u32 { + match foo { + Foo::B(i) => i, //~ ERROR E0164 + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0164.stderr b/tests/ui/error-codes/E0164.stderr new file mode 100644 index 000000000..5a80d6ec3 --- /dev/null +++ b/tests/ui/error-codes/E0164.stderr @@ -0,0 +1,9 @@ +error[E0164]: expected tuple struct or tuple variant, found associated constant `Foo::B` + --> $DIR/E0164.rs:9:9 + | +LL | Foo::B(i) => i, + | ^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/error-codes/E0184.rs b/tests/ui/error-codes/E0184.rs new file mode 100644 index 000000000..0c448e4ad --- /dev/null +++ b/tests/ui/error-codes/E0184.rs @@ -0,0 +1,10 @@ +#[derive(Copy)] //~ ERROR E0184 +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr new file mode 100644 index 000000000..bb3017b6e --- /dev/null +++ b/tests/ui/error-codes/E0184.stderr @@ -0,0 +1,11 @@ +error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor + --> $DIR/E0184.rs:1:10 + | +LL | #[derive(Copy)] + | ^^^^ `Copy` not allowed on types with destructors + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0184`. diff --git a/tests/ui/error-codes/E0185.rs b/tests/ui/error-codes/E0185.rs new file mode 100644 index 000000000..45eb8b0f2 --- /dev/null +++ b/tests/ui/error-codes/E0185.rs @@ -0,0 +1,15 @@ +trait Foo { + fn foo(); + //~^ NOTE trait method declared without `&self` +} + +struct Bar; + +impl Foo for Bar { + fn foo(&self) {} + //~^ ERROR E0185 + //~| NOTE `&self` used in impl +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0185.stderr b/tests/ui/error-codes/E0185.stderr new file mode 100644 index 000000000..8a99c0688 --- /dev/null +++ b/tests/ui/error-codes/E0185.stderr @@ -0,0 +1,12 @@ +error[E0185]: method `foo` has a `&self` declaration in the impl, but not in the trait + --> $DIR/E0185.rs:9:5 + | +LL | fn foo(); + | --------- trait method declared without `&self` +... +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ `&self` used in impl + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0185`. diff --git a/tests/ui/error-codes/E0186.rs b/tests/ui/error-codes/E0186.rs new file mode 100644 index 000000000..83ef78ef2 --- /dev/null +++ b/tests/ui/error-codes/E0186.rs @@ -0,0 +1,13 @@ +trait Foo { + fn foo(&self); //~ `&self` used in trait +} + +struct Bar; + +impl Foo for Bar { + fn foo() {} //~ ERROR E0186 + //~^ expected `&self` in impl +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0186.stderr b/tests/ui/error-codes/E0186.stderr new file mode 100644 index 000000000..8971d61fc --- /dev/null +++ b/tests/ui/error-codes/E0186.stderr @@ -0,0 +1,12 @@ +error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl + --> $DIR/E0186.rs:8:5 + | +LL | fn foo(&self); + | -------------- `&self` used in trait +... +LL | fn foo() {} + | ^^^^^^^^ expected `&self` in impl + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0186`. diff --git a/tests/ui/error-codes/E0191.rs b/tests/ui/error-codes/E0191.rs new file mode 100644 index 000000000..22f739b9e --- /dev/null +++ b/tests/ui/error-codes/E0191.rs @@ -0,0 +1,7 @@ +trait Trait { + type Bar; +} + +type Foo = dyn Trait; //~ ERROR E0191 + +fn main() {} diff --git a/tests/ui/error-codes/E0191.stderr b/tests/ui/error-codes/E0191.stderr new file mode 100644 index 000000000..cf80c9c46 --- /dev/null +++ b/tests/ui/error-codes/E0191.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified + --> $DIR/E0191.rs:5:16 + | +LL | type Bar; + | -------- `Bar` defined here +... +LL | type Foo = dyn Trait; + | ^^^^^ help: specify the associated type: `Trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/error-codes/E0194.rs b/tests/ui/error-codes/E0194.rs new file mode 100644 index 000000000..8a43f38fc --- /dev/null +++ b/tests/ui/error-codes/E0194.rs @@ -0,0 +1,8 @@ +trait Foo { + fn do_something(&self) -> T; + fn do_something_else(&self, bar: T); + //~^ ERROR E0403 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0194.stderr b/tests/ui/error-codes/E0194.stderr new file mode 100644 index 000000000..f2c908eea --- /dev/null +++ b/tests/ui/error-codes/E0194.stderr @@ -0,0 +1,12 @@ +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/E0194.rs:3:26 + | +LL | trait Foo { + | - first use of `T` +LL | fn do_something(&self) -> T; +LL | fn do_something_else(&self, bar: T); + | ^ already used + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0195.rs b/tests/ui/error-codes/E0195.rs new file mode 100644 index 000000000..f712ee42b --- /dev/null +++ b/tests/ui/error-codes/E0195.rs @@ -0,0 +1,15 @@ +trait Trait { + fn bar<'a,'b:'a>(x: &'a str, y: &'b str); + //~^ NOTE lifetimes in impl do not match this method in trait +} + +struct Foo; + +impl Trait for Foo { + fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 + //~^ NOTE lifetimes do not match method in trait + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0195.stderr b/tests/ui/error-codes/E0195.stderr new file mode 100644 index 000000000..6eaa1750e --- /dev/null +++ b/tests/ui/error-codes/E0195.stderr @@ -0,0 +1,12 @@ +error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration + --> $DIR/E0195.rs:9:11 + | +LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); + | ---------- lifetimes in impl do not match this method in trait +... +LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { + | ^^^^^^^ lifetimes do not match method in trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/error-codes/E0197.rs b/tests/ui/error-codes/E0197.rs new file mode 100644 index 000000000..4025a1f6c --- /dev/null +++ b/tests/ui/error-codes/E0197.rs @@ -0,0 +1,6 @@ +struct Foo; + +unsafe impl Foo { } //~ ERROR E0197 + +fn main() { +} diff --git a/tests/ui/error-codes/E0197.stderr b/tests/ui/error-codes/E0197.stderr new file mode 100644 index 000000000..35e104264 --- /dev/null +++ b/tests/ui/error-codes/E0197.stderr @@ -0,0 +1,11 @@ +error[E0197]: inherent impls cannot be unsafe + --> $DIR/E0197.rs:3:13 + | +LL | unsafe impl Foo { } + | ------ ^^^ inherent impl for this type + | | + | unsafe because of this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0197`. diff --git a/tests/ui/error-codes/E0198.rs b/tests/ui/error-codes/E0198.rs new file mode 100644 index 000000000..041bbe8fd --- /dev/null +++ b/tests/ui/error-codes/E0198.rs @@ -0,0 +1,8 @@ +#![feature(negative_impls)] + +struct Foo; + +unsafe impl !Send for Foo { } //~ ERROR E0198 + +fn main() { +} diff --git a/tests/ui/error-codes/E0198.stderr b/tests/ui/error-codes/E0198.stderr new file mode 100644 index 000000000..bb2efefb4 --- /dev/null +++ b/tests/ui/error-codes/E0198.stderr @@ -0,0 +1,12 @@ +error[E0198]: negative impls cannot be unsafe + --> $DIR/E0198.rs:5:13 + | +LL | unsafe impl !Send for Foo { } + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0198`. diff --git a/tests/ui/error-codes/E0199.rs b/tests/ui/error-codes/E0199.rs new file mode 100644 index 000000000..2421bf0a5 --- /dev/null +++ b/tests/ui/error-codes/E0199.rs @@ -0,0 +1,9 @@ +#![feature(negative_impls)] + +struct Foo; + +trait Bar { } +unsafe impl Bar for Foo { } //~ ERROR implementing the trait `Bar` is not unsafe [E0199] + +fn main() { +} diff --git a/tests/ui/error-codes/E0199.stderr b/tests/ui/error-codes/E0199.stderr new file mode 100644 index 000000000..68c308b15 --- /dev/null +++ b/tests/ui/error-codes/E0199.stderr @@ -0,0 +1,15 @@ +error[E0199]: implementing the trait `Bar` is not unsafe + --> $DIR/E0199.rs:6:1 + | +LL | unsafe impl Bar for Foo { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl Bar for Foo { } +LL + impl Bar for Foo { } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0199`. diff --git a/tests/ui/error-codes/E0200.rs b/tests/ui/error-codes/E0200.rs new file mode 100644 index 000000000..24806a6cb --- /dev/null +++ b/tests/ui/error-codes/E0200.rs @@ -0,0 +1,8 @@ +struct Foo; + +unsafe trait Bar { } + +impl Bar for Foo { } //~ ERROR E0200 + +fn main() { +} diff --git a/tests/ui/error-codes/E0200.stderr b/tests/ui/error-codes/E0200.stderr new file mode 100644 index 000000000..c70a2d4f3 --- /dev/null +++ b/tests/ui/error-codes/E0200.stderr @@ -0,0 +1,15 @@ +error[E0200]: the trait `Bar` requires an `unsafe impl` declaration + --> $DIR/E0200.rs:5:1 + | +LL | impl Bar for Foo { } + | ^^^^^^^^^^^^^^^^ + | + = note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl Bar for Foo { } + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0200`. diff --git a/tests/ui/error-codes/E0201.rs b/tests/ui/error-codes/E0201.rs new file mode 100644 index 000000000..04b37091b --- /dev/null +++ b/tests/ui/error-codes/E0201.rs @@ -0,0 +1,22 @@ +struct Foo(u8); + +impl Foo { + fn bar(&self) -> bool { self.0 > 5 } + fn bar() {} //~ ERROR E0592 +} + +trait Baz { + type Quux; + fn baz(&self) -> bool; +} + +impl Baz for Foo { + type Quux = u32; + + fn baz(&self) -> bool { true } + fn baz(&self) -> bool { self.0 > 5 } //~ ERROR E0201 + type Quux = u32; //~ ERROR E0201 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0201.stderr b/tests/ui/error-codes/E0201.stderr new file mode 100644 index 000000000..608ff6917 --- /dev/null +++ b/tests/ui/error-codes/E0201.stderr @@ -0,0 +1,35 @@ +error[E0201]: duplicate definitions with name `baz`: + --> $DIR/E0201.rs:17:5 + | +LL | fn baz(&self) -> bool; + | ---------------------- item in trait +... +LL | fn baz(&self) -> bool { true } + | ------------------------------ previous definition here +LL | fn baz(&self) -> bool { self.0 > 5 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + +error[E0201]: duplicate definitions with name `Quux`: + --> $DIR/E0201.rs:18:5 + | +LL | type Quux; + | ---------- item in trait +... +LL | type Quux = u32; + | ---------------- previous definition here +... +LL | type Quux = u32; + | ^^^^^^^^^^^^^^^^ duplicate definition + +error[E0592]: duplicate definitions with name `bar` + --> $DIR/E0201.rs:5:5 + | +LL | fn bar(&self) -> bool { self.0 > 5 } + | --------------------- other definition for `bar` +LL | fn bar() {} + | ^^^^^^^^ duplicate definitions for `bar` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0201, E0592. +For more information about an error, try `rustc --explain E0201`. diff --git a/tests/ui/error-codes/E0206.rs b/tests/ui/error-codes/E0206.rs new file mode 100644 index 000000000..0f3d427ce --- /dev/null +++ b/tests/ui/error-codes/E0206.rs @@ -0,0 +1,8 @@ +#[derive(Copy, Clone)] +struct Bar; + +impl Copy for &'static mut Bar { } +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() { +} diff --git a/tests/ui/error-codes/E0206.stderr b/tests/ui/error-codes/E0206.stderr new file mode 100644 index 000000000..57ae2647d --- /dev/null +++ b/tests/ui/error-codes/E0206.stderr @@ -0,0 +1,9 @@ +error[E0206]: the trait `Copy` may not be implemented for this type + --> $DIR/E0206.rs:4:15 + | +LL | impl Copy for &'static mut Bar { } + | ^^^^^^^^^^^^^^^^ type is not a structure or enumeration + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0206`. diff --git a/tests/ui/error-codes/E0207.rs b/tests/ui/error-codes/E0207.rs new file mode 100644 index 000000000..7f5d4ab51 --- /dev/null +++ b/tests/ui/error-codes/E0207.rs @@ -0,0 +1,10 @@ +struct Foo; + +impl Foo { //~ ERROR E0207 + fn get(&self) -> T { + ::default() + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0207.stderr b/tests/ui/error-codes/E0207.stderr new file mode 100644 index 000000000..5ef51ed86 --- /dev/null +++ b/tests/ui/error-codes/E0207.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/E0207.rs:3:6 + | +LL | impl Foo { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/error-codes/E0208.rs b/tests/ui/error-codes/E0208.rs new file mode 100644 index 000000000..c67d42889 --- /dev/null +++ b/tests/ui/error-codes/E0208.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +#[rustc_variance] +struct Foo<'a, T> { //~ ERROR [-, o] + t: &'a mut T, +} + +fn main() {} diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr new file mode 100644 index 000000000..dbbb41e79 --- /dev/null +++ b/tests/ui/error-codes/E0208.stderr @@ -0,0 +1,8 @@ +error: [-, o] + --> $DIR/E0208.rs:4:1 + | +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/error-codes/E0214.rs b/tests/ui/error-codes/E0214.rs new file mode 100644 index 000000000..fd73189f9 --- /dev/null +++ b/tests/ui/error-codes/E0214.rs @@ -0,0 +1,4 @@ +fn main() { + let v: Vec(&str) = vec!["foo"]; + //~^ ERROR E0214 +} diff --git a/tests/ui/error-codes/E0214.stderr b/tests/ui/error-codes/E0214.stderr new file mode 100644 index 000000000..e0179aac2 --- /dev/null +++ b/tests/ui/error-codes/E0214.stderr @@ -0,0 +1,14 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/E0214.rs:2:12 + | +LL | let v: Vec(&str) = vec!["foo"]; + | ^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | let v: Vec<&str> = vec!["foo"]; + | ~ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/error-codes/E0220.rs b/tests/ui/error-codes/E0220.rs new file mode 100644 index 000000000..e11a570df --- /dev/null +++ b/tests/ui/error-codes/E0220.rs @@ -0,0 +1,8 @@ +trait Trait { + type Bar; +} + +type Foo = dyn Trait; //~ ERROR E0220 + //~| ERROR E0191 +fn main() { +} diff --git a/tests/ui/error-codes/E0220.stderr b/tests/ui/error-codes/E0220.stderr new file mode 100644 index 000000000..11763ce78 --- /dev/null +++ b/tests/ui/error-codes/E0220.stderr @@ -0,0 +1,19 @@ +error[E0220]: associated type `F` not found for `Trait` + --> $DIR/E0220.rs:5:22 + | +LL | type Foo = dyn Trait; + | ^ associated type `F` not found + +error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified + --> $DIR/E0220.rs:5:16 + | +LL | type Bar; + | -------- `Bar` defined here +... +LL | type Foo = dyn Trait; + | ^^^^^^^^^^^^ help: specify the associated type: `Trait` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0191, E0220. +For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/error-codes/E0221.rs b/tests/ui/error-codes/E0221.rs new file mode 100644 index 000000000..7c7e139a0 --- /dev/null +++ b/tests/ui/error-codes/E0221.rs @@ -0,0 +1,27 @@ +trait T1 {} +trait T2 {} + +trait Foo { + type A: T1; +} + +trait Bar : Foo { + type A: T2; + fn do_something() { + let _: Self::A; + //~^ ERROR E0221 + } +} + +trait T3 {} + +trait My : std::str::FromStr { + type Err: T3; + fn test() { + let _: Self::Err; + //~^ ERROR E0221 + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr new file mode 100644 index 000000000..5414d77ad --- /dev/null +++ b/tests/ui/error-codes/E0221.stderr @@ -0,0 +1,39 @@ +error[E0221]: ambiguous associated type `A` in bounds of `Self` + --> $DIR/E0221.rs:11:16 + | +LL | type A: T1; + | ---------- ambiguous `A` from `Foo` +... +LL | type A: T2; + | ---------- ambiguous `A` from `Bar` +LL | fn do_something() { +LL | let _: Self::A; + | ^^^^^^^ ambiguous associated type `A` + | +help: use fully qualified syntax to disambiguate + | +LL | let _: ::A; + | ~~~~~~~~~~~~~~~ +help: use fully qualified syntax to disambiguate + | +LL | let _: ::A; + | ~~~~~~~~~~~~~~~ + +error[E0221]: ambiguous associated type `Err` in bounds of `Self` + --> $DIR/E0221.rs:21:16 + | +LL | type Err: T3; + | ------------ ambiguous `Err` from `My` +LL | fn test() { +LL | let _: Self::Err; + | ^^^^^^^^^ ambiguous associated type `Err` + | + = note: associated type `Self` could derive from `FromStr` +help: use fully qualified syntax to disambiguate + | +LL | let _: ::Err; + | ~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0221`. diff --git a/tests/ui/error-codes/E0223.rs b/tests/ui/error-codes/E0223.rs new file mode 100644 index 000000000..2fe252de2 --- /dev/null +++ b/tests/ui/error-codes/E0223.rs @@ -0,0 +1,10 @@ +trait MyTrait { type X; } +struct MyStruct; +impl MyTrait for MyStruct { + type X = (); +} + +fn main() { + let foo: MyTrait::X; + //~^ ERROR ambiguous associated type +} diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr new file mode 100644 index 000000000..42945e42f --- /dev/null +++ b/tests/ui/error-codes/E0223.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/E0223.rs:8:14 + | +LL | let foo: MyTrait::X; + | ^^^^^^^^^^ help: use the fully-qualified path: `::X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/error-codes/E0225.rs b/tests/ui/error-codes/E0225.rs new file mode 100644 index 000000000..b50f68e64 --- /dev/null +++ b/tests/ui/error-codes/E0225.rs @@ -0,0 +1,10 @@ +#![feature(trait_alias)] + +trait Foo = std::io::Read + std::io::Write; + +fn main() { + let _: Box; + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + let _: Box; + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] +} diff --git a/tests/ui/error-codes/E0225.stderr b/tests/ui/error-codes/E0225.stderr new file mode 100644 index 000000000..a4b33a0b7 --- /dev/null +++ b/tests/ui/error-codes/E0225.stderr @@ -0,0 +1,31 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/E0225.rs:6:36 + | +LL | let _: Box; + | ------------- ^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/E0225.rs:8:20 + | +LL | trait Foo = std::io::Read + std::io::Write; + | ------------- -------------- additional non-auto trait + | | + | first non-auto trait +... +LL | let _: Box; + | ^^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/error-codes/E0227.rs b/tests/ui/error-codes/E0227.rs new file mode 100644 index 000000000..0f0a781d2 --- /dev/null +++ b/tests/ui/error-codes/E0227.rs @@ -0,0 +1,12 @@ +trait Foo<'foo>: 'foo {} +trait Bar<'bar>: 'bar {} + +trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {} + +struct Baz<'foo, 'bar> { + baz: dyn FooBar<'foo, 'bar>, + //~^ ERROR ambiguous lifetime bound, explicit lifetime bound required +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0227.stderr b/tests/ui/error-codes/E0227.stderr new file mode 100644 index 000000000..26de5b4c4 --- /dev/null +++ b/tests/ui/error-codes/E0227.stderr @@ -0,0 +1,9 @@ +error[E0227]: ambiguous lifetime bound, explicit lifetime bound required + --> $DIR/E0227.rs:7:10 + | +LL | baz: dyn FooBar<'foo, 'bar>, + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0227`. diff --git a/tests/ui/error-codes/E0229.rs b/tests/ui/error-codes/E0229.rs new file mode 100644 index 000000000..4c1934107 --- /dev/null +++ b/tests/ui/error-codes/E0229.rs @@ -0,0 +1,17 @@ +pub trait Foo { + type A; + fn boo(&self) -> ::A; +} + +struct Bar; + +impl Foo for isize { + type A = usize; + fn boo(&self) -> usize { 42 } +} + +fn baz(x: &>::A) {} +//~^ ERROR associated type bindings are not allowed here [E0229] + +fn main() { +} diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr new file mode 100644 index 000000000..46793314b --- /dev/null +++ b/tests/ui/error-codes/E0229.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/E0229.rs:13:25 + | +LL | fn baz(x: &>::A) {} + | ^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/error-codes/E0252.rs b/tests/ui/error-codes/E0252.rs new file mode 100644 index 000000000..6b5163417 --- /dev/null +++ b/tests/ui/error-codes/E0252.rs @@ -0,0 +1,15 @@ +#![allow(non_camel_case_types)] + +use foo::baz; +use bar::baz; //~ ERROR E0252 + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0252.stderr b/tests/ui/error-codes/E0252.stderr new file mode 100644 index 000000000..2722dfe5e --- /dev/null +++ b/tests/ui/error-codes/E0252.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `baz` is defined multiple times + --> $DIR/E0252.rs:4:5 + | +LL | use foo::baz; + | -------- previous import of the type `baz` here +LL | use bar::baz; + | ^^^^^^^^ `baz` reimported here + | + = note: `baz` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::baz as other_baz; + | ~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/error-codes/E0253.rs b/tests/ui/error-codes/E0253.rs new file mode 100644 index 000000000..284b16da8 --- /dev/null +++ b/tests/ui/error-codes/E0253.rs @@ -0,0 +1,10 @@ +mod foo { + pub trait MyTrait { + fn do_something(); + } +} + +use foo::MyTrait::do_something; + //~^ ERROR E0253 + +fn main() {} diff --git a/tests/ui/error-codes/E0253.stderr b/tests/ui/error-codes/E0253.stderr new file mode 100644 index 000000000..8f21a0aab --- /dev/null +++ b/tests/ui/error-codes/E0253.stderr @@ -0,0 +1,9 @@ +error[E0253]: `do_something` is not directly importable + --> $DIR/E0253.rs:7:5 + | +LL | use foo::MyTrait::do_something; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0253`. diff --git a/tests/ui/error-codes/E0254.rs b/tests/ui/error-codes/E0254.rs new file mode 100644 index 000000000..e291268be --- /dev/null +++ b/tests/ui/error-codes/E0254.rs @@ -0,0 +1,14 @@ +#![allow(non_camel_case_types)] + +extern crate alloc; + +mod foo { + pub trait alloc { + fn do_something(); + } +} + +use foo::alloc; +//~^ ERROR E0254 + +fn main() {} diff --git a/tests/ui/error-codes/E0254.stderr b/tests/ui/error-codes/E0254.stderr new file mode 100644 index 000000000..b098f8e1a --- /dev/null +++ b/tests/ui/error-codes/E0254.stderr @@ -0,0 +1,18 @@ +error[E0254]: the name `alloc` is defined multiple times + --> $DIR/E0254.rs:11:5 + | +LL | extern crate alloc; + | ------------------- previous import of the extern crate `alloc` here +... +LL | use foo::alloc; + | ^^^^^^^^^^ `alloc` reimported here + | + = note: `alloc` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::alloc as other_alloc; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/error-codes/E0255.rs b/tests/ui/error-codes/E0255.rs new file mode 100644 index 000000000..d1c21eb79 --- /dev/null +++ b/tests/ui/error-codes/E0255.rs @@ -0,0 +1,9 @@ +use bar::foo; + +fn foo() {} //~ ERROR E0255 + +mod bar { + pub fn foo() {} +} + +fn main() {} diff --git a/tests/ui/error-codes/E0255.stderr b/tests/ui/error-codes/E0255.stderr new file mode 100644 index 000000000..352c5ba5b --- /dev/null +++ b/tests/ui/error-codes/E0255.stderr @@ -0,0 +1,18 @@ +error[E0255]: the name `foo` is defined multiple times + --> $DIR/E0255.rs:3:1 + | +LL | use bar::foo; + | -------- previous import of the value `foo` here +LL | +LL | fn foo() {} + | ^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::foo as other_foo; + | ~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/error-codes/E0259.rs b/tests/ui/error-codes/E0259.rs new file mode 100644 index 000000000..e7e94d586 --- /dev/null +++ b/tests/ui/error-codes/E0259.rs @@ -0,0 +1,8 @@ +#![feature(rustc_private)] + +extern crate alloc; + +extern crate libc as alloc; +//~^ ERROR E0259 + +fn main() {} diff --git a/tests/ui/error-codes/E0259.stderr b/tests/ui/error-codes/E0259.stderr new file mode 100644 index 000000000..06cbc5b4f --- /dev/null +++ b/tests/ui/error-codes/E0259.stderr @@ -0,0 +1,18 @@ +error[E0259]: the name `alloc` is defined multiple times + --> $DIR/E0259.rs:5:1 + | +LL | extern crate alloc; + | ------------------- previous import of the extern crate `alloc` here +LL | +LL | extern crate libc as alloc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `alloc` reimported here + | + = note: `alloc` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate libc as other_alloc; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/error-codes/E0260.rs b/tests/ui/error-codes/E0260.rs new file mode 100644 index 000000000..f7eb220b0 --- /dev/null +++ b/tests/ui/error-codes/E0260.rs @@ -0,0 +1,10 @@ +extern crate alloc; + +mod alloc { +//~^ ERROR the name `alloc` is defined multiple times [E0260] + pub trait MyTrait { + fn do_something(); + } +} + +fn main() {} diff --git a/tests/ui/error-codes/E0260.stderr b/tests/ui/error-codes/E0260.stderr new file mode 100644 index 000000000..2d3305bd1 --- /dev/null +++ b/tests/ui/error-codes/E0260.stderr @@ -0,0 +1,18 @@ +error[E0260]: the name `alloc` is defined multiple times + --> $DIR/E0260.rs:3:1 + | +LL | extern crate alloc; + | ------------------- previous import of the extern crate `alloc` here +LL | +LL | mod alloc { + | ^^^^^^^^^ `alloc` redefined here + | + = note: `alloc` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate alloc as other_alloc; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0260`. diff --git a/tests/ui/error-codes/E0261.rs b/tests/ui/error-codes/E0261.rs new file mode 100644 index 000000000..f05e09aa0 --- /dev/null +++ b/tests/ui/error-codes/E0261.rs @@ -0,0 +1,9 @@ +fn foo(x: &'a str) { } //~ ERROR E0261 + //~| undeclared lifetime + +struct Foo { + x: &'a str, //~ ERROR E0261 + //~| undeclared lifetime +} + +fn main() {} diff --git a/tests/ui/error-codes/E0261.stderr b/tests/ui/error-codes/E0261.stderr new file mode 100644 index 000000000..0eab2dc0e --- /dev/null +++ b/tests/ui/error-codes/E0261.stderr @@ -0,0 +1,19 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/E0261.rs:1:12 + | +LL | fn foo(x: &'a str) { } + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/E0261.rs:5:9 + | +LL | struct Foo { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | x: &'a str, + | ^^ undeclared lifetime + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/error-codes/E0262.rs b/tests/ui/error-codes/E0262.rs new file mode 100644 index 000000000..55264f138 --- /dev/null +++ b/tests/ui/error-codes/E0262.rs @@ -0,0 +1,4 @@ +fn foo<'static>(x: &'static str) { } //~ ERROR E0262 + //~| 'static is a reserved lifetime name + +fn main() {} diff --git a/tests/ui/error-codes/E0262.stderr b/tests/ui/error-codes/E0262.stderr new file mode 100644 index 000000000..ad90b7171 --- /dev/null +++ b/tests/ui/error-codes/E0262.stderr @@ -0,0 +1,9 @@ +error[E0262]: invalid lifetime parameter name: `'static` + --> $DIR/E0262.rs:1:8 + | +LL | fn foo<'static>(x: &'static str) { } + | ^^^^^^^ 'static is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0262`. diff --git a/tests/ui/error-codes/E0263.rs b/tests/ui/error-codes/E0263.rs new file mode 100644 index 000000000..92917678e --- /dev/null +++ b/tests/ui/error-codes/E0263.rs @@ -0,0 +1,5 @@ +fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { + //~^ ERROR E0403 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0263.stderr b/tests/ui/error-codes/E0263.stderr new file mode 100644 index 000000000..e3f9aea29 --- /dev/null +++ b/tests/ui/error-codes/E0263.stderr @@ -0,0 +1,11 @@ +error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters + --> $DIR/E0263.rs:1:16 + | +LL | fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { + | -- ^^ already used + | | + | first use of `'a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0264.rs b/tests/ui/error-codes/E0264.rs new file mode 100644 index 000000000..6adaf01fb --- /dev/null +++ b/tests/ui/error-codes/E0264.rs @@ -0,0 +1,8 @@ +#![feature(lang_items)] + +extern "C" { + #[lang = "cake"] + fn cake(); //~ ERROR E0264 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0264.stderr b/tests/ui/error-codes/E0264.stderr new file mode 100644 index 000000000..e8e35a12c --- /dev/null +++ b/tests/ui/error-codes/E0264.stderr @@ -0,0 +1,9 @@ +error[E0264]: unknown external lang item: `cake` + --> $DIR/E0264.rs:5:5 + | +LL | fn cake(); + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0264`. diff --git a/tests/ui/error-codes/E0267.rs b/tests/ui/error-codes/E0267.rs new file mode 100644 index 000000000..45e875a0a --- /dev/null +++ b/tests/ui/error-codes/E0267.rs @@ -0,0 +1,3 @@ +fn main() { + let w = || { break; }; //~ ERROR E0267 +} diff --git a/tests/ui/error-codes/E0267.stderr b/tests/ui/error-codes/E0267.stderr new file mode 100644 index 000000000..1f8657373 --- /dev/null +++ b/tests/ui/error-codes/E0267.stderr @@ -0,0 +1,11 @@ +error[E0267]: `break` inside of a closure + --> $DIR/E0267.rs:2:18 + | +LL | let w = || { break; }; + | -- ^^^^^ cannot `break` inside of a closure + | | + | enclosing closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0267`. diff --git a/tests/ui/error-codes/E0268.rs b/tests/ui/error-codes/E0268.rs new file mode 100644 index 000000000..742ba5441 --- /dev/null +++ b/tests/ui/error-codes/E0268.rs @@ -0,0 +1,3 @@ +fn main() { + break; //~ ERROR E0268 +} diff --git a/tests/ui/error-codes/E0268.stderr b/tests/ui/error-codes/E0268.stderr new file mode 100644 index 000000000..6422e8a94 --- /dev/null +++ b/tests/ui/error-codes/E0268.stderr @@ -0,0 +1,9 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/E0268.rs:2:5 + | +LL | break; + | ^^^^^ cannot `break` outside of a loop or labeled block + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/error-codes/E0271.rs b/tests/ui/error-codes/E0271.rs new file mode 100644 index 000000000..f27190754 --- /dev/null +++ b/tests/ui/error-codes/E0271.rs @@ -0,0 +1,11 @@ +trait Trait { type AssociatedType; } + +fn foo(t: T) where T: Trait { + println!("in foo"); +} + +impl Trait for i8 { type AssociatedType = &'static str; } + +fn main() { + foo(3_i8); //~ ERROR E0271 +} diff --git a/tests/ui/error-codes/E0271.stderr b/tests/ui/error-codes/E0271.stderr new file mode 100644 index 000000000..1e2f43834 --- /dev/null +++ b/tests/ui/error-codes/E0271.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `::AssociatedType == u32` + --> $DIR/E0271.rs:10:9 + | +LL | foo(3_i8); + | --- ^^^^ type mismatch resolving `::AssociatedType == u32` + | | + | required by a bound introduced by this call + | +note: expected this to be `u32` + --> $DIR/E0271.rs:7:43 + | +LL | impl Trait for i8 { type AssociatedType = &'static str; } + | ^^^^^^^^^^^^ +note: required by a bound in `foo` + --> $DIR/E0271.rs:3:32 + | +LL | fn foo(t: T) where T: Trait { + | ^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/error-codes/E0275.rs b/tests/ui/error-codes/E0275.rs new file mode 100644 index 000000000..95d7f85f1 --- /dev/null +++ b/tests/ui/error-codes/E0275.rs @@ -0,0 +1,9 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" +trait Foo {} + +struct Bar(T); + +impl Foo for T where Bar: Foo {} //~ ERROR E0275 + +fn main() { +} diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr new file mode 100644 index 000000000..cf9a7f69b --- /dev/null +++ b/tests/ui/error-codes/E0275.stderr @@ -0,0 +1,19 @@ +error[E0275]: overflow evaluating the requirement `Bar>>>>>>: Foo` + --> $DIR/E0275.rs:6:33 + | +LL | impl Foo for T where Bar: Foo {} + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) +note: required for `Bar>>>>>>>>>>>>>>>>>>>>` to implement `Foo` + --> $DIR/E0275.rs:6:9 + | +LL | impl Foo for T where Bar: Foo {} + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/error-codes/E0275/E0275.long-type-hash.txt' + = note: 127 redundant requirements hidden + = note: required for `Bar` to implement `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/error-codes/E0276.rs b/tests/ui/error-codes/E0276.rs new file mode 100644 index 000000000..5e3d9f602 --- /dev/null +++ b/tests/ui/error-codes/E0276.rs @@ -0,0 +1,10 @@ +trait Foo { + fn foo(x: T); +} + +impl Foo for bool { + fn foo(x: T) where T: Copy {} //~ ERROR E0276 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0276.stderr b/tests/ui/error-codes/E0276.stderr new file mode 100644 index 000000000..1013f041b --- /dev/null +++ b/tests/ui/error-codes/E0276.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/E0276.rs:6:30 + | +LL | fn foo(x: T); + | ---------------- definition of `foo` from trait +... +LL | fn foo(x: T) where T: Copy {} + | ^^^^ impl has extra requirement `T: Copy` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/error-codes/E0277-2.rs b/tests/ui/error-codes/E0277-2.rs new file mode 100644 index 000000000..428518705 --- /dev/null +++ b/tests/ui/error-codes/E0277-2.rs @@ -0,0 +1,18 @@ +struct Foo { + bar: Bar +} + +struct Bar { + baz: Baz +} + +struct Baz { + x: *const u8 +} + +fn is_send() { } + +fn main() { + is_send::(); + //~^ ERROR `*const u8` cannot be sent between threads safely +} diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr new file mode 100644 index 000000000..a2abf3793 --- /dev/null +++ b/tests/ui/error-codes/E0277-2.stderr @@ -0,0 +1,31 @@ +error[E0277]: `*const u8` cannot be sent between threads safely + --> $DIR/E0277-2.rs:16:15 + | +LL | is_send::(); + | ^^^ `*const u8` cannot be sent between threads safely + | + = help: within `Foo`, the trait `Send` is not implemented for `*const u8` +note: required because it appears within the type `Baz` + --> $DIR/E0277-2.rs:9:8 + | +LL | struct Baz { + | ^^^ +note: required because it appears within the type `Bar` + --> $DIR/E0277-2.rs:5:8 + | +LL | struct Bar { + | ^^^ +note: required because it appears within the type `Foo` + --> $DIR/E0277-2.rs:1:8 + | +LL | struct Foo { + | ^^^ +note: required by a bound in `is_send` + --> $DIR/E0277-2.rs:13:15 + | +LL | fn is_send() { } + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0277-3.rs b/tests/ui/error-codes/E0277-3.rs new file mode 100644 index 000000000..428be7961 --- /dev/null +++ b/tests/ui/error-codes/E0277-3.rs @@ -0,0 +1,8 @@ +fn foo(_: T) {} + +struct S; + +fn main() { + foo(S); + //~^ ERROR can't compare `S` with `S` +} diff --git a/tests/ui/error-codes/E0277-3.stderr b/tests/ui/error-codes/E0277-3.stderr new file mode 100644 index 000000000..0127e1ccc --- /dev/null +++ b/tests/ui/error-codes/E0277-3.stderr @@ -0,0 +1,22 @@ +error[E0277]: can't compare `S` with `S` + --> $DIR/E0277-3.rs:6:9 + | +LL | foo(S); + | --- ^ no implementation for `S == S` + | | + | required by a bound introduced by this call + | + = help: the trait `PartialEq` is not implemented for `S` +note: required by a bound in `foo` + --> $DIR/E0277-3.rs:1:11 + | +LL | fn foo(_: T) {} + | ^^^^^^^^^ required by this bound in `foo` +help: consider annotating `S` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0277.rs b/tests/ui/error-codes/E0277.rs new file mode 100644 index 000000000..f0de4e3de --- /dev/null +++ b/tests/ui/error-codes/E0277.rs @@ -0,0 +1,17 @@ +use std::path::Path; + +trait Foo { + fn bar(&self); +} + +fn some_func(foo: T) { + foo.bar(); +} + +fn f(p: Path) { } +//~^ ERROR the size for values of type + +fn main() { + some_func(5i32); + //~^ ERROR the trait bound `i32: Foo` is not satisfied +} diff --git a/tests/ui/error-codes/E0277.stderr b/tests/ui/error-codes/E0277.stderr new file mode 100644 index 000000000..2b4784d7e --- /dev/null +++ b/tests/ui/error-codes/E0277.stderr @@ -0,0 +1,31 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/E0277.rs:11:6 + | +LL | fn f(p: Path) { } + | ^ doesn't have a size known at compile-time + | + = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `Path` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn f(p: &Path) { } + | + + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/E0277.rs:15:15 + | +LL | some_func(5i32); + | --------- ^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `some_func` + --> $DIR/E0277.rs:7:17 + | +LL | fn some_func(foo: T) { + | ^^^ required by this bound in `some_func` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0282.rs b/tests/ui/error-codes/E0282.rs new file mode 100644 index 000000000..f1f93b3ae --- /dev/null +++ b/tests/ui/error-codes/E0282.rs @@ -0,0 +1,4 @@ +fn main() { + let x = "hello".chars().rev().collect(); + //~^ ERROR E0282 +} diff --git a/tests/ui/error-codes/E0282.stderr b/tests/ui/error-codes/E0282.stderr new file mode 100644 index 000000000..892d3a81f --- /dev/null +++ b/tests/ui/error-codes/E0282.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/E0282.rs:2:9 + | +LL | let x = "hello".chars().rev().collect(); + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: Vec<_> = "hello".chars().rev().collect(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/error-codes/E0283.rs b/tests/ui/error-codes/E0283.rs new file mode 100644 index 000000000..0643af4b7 --- /dev/null +++ b/tests/ui/error-codes/E0283.rs @@ -0,0 +1,37 @@ +trait Generator { + fn create() -> u32; +} + +struct Impl; + +impl Generator for Impl { + fn create() -> u32 { 1 } +} + +impl Impl { + fn new() -> Self { + Impl{} + } +} + +impl Into for Impl { + fn into(self) -> u32 { 1 } +} + +fn foo(bar: u32) {} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let cont: u32 = Generator::create(); //~ ERROR E0790 +} + +fn buzz() { + let foo_impl = Impl::new(); + let bar = foo_impl.into() * 1u32; //~ ERROR E0283 + foo(bar); +} diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr new file mode 100644 index 000000000..90316c6e9 --- /dev/null +++ b/tests/ui/error-codes/E0283.stderr @@ -0,0 +1,37 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0283.rs:30:21 + | +LL | fn create() -> u32; + | ------------------- `Generator::create` defined here +... +LL | let cont: u32 = Generator::create(); + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use a fully-qualified path to a specific available implementation (2 found) + | +LL | let cont: u32 = ::create(); + | ++++++++ + + +error[E0283]: type annotations needed + --> $DIR/E0283.rs:35:24 + | +LL | let bar = foo_impl.into() * 1u32; + | ^^^^ + | +note: multiple `impl`s satisfying `Impl: Into<_>` found + --> $DIR/E0283.rs:17:1 + | +LL | impl Into for Impl { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: and another `impl` found in the `core` crate: + - impl Into for T + where U: From; +help: try using a fully qualified path to specify the expected types + | +LL | let bar = >::into(foo_impl) * 1u32; + | ++++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0283, E0790. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/error-codes/E0297.rs b/tests/ui/error-codes/E0297.rs new file mode 100644 index 000000000..27c7960d9 --- /dev/null +++ b/tests/ui/error-codes/E0297.rs @@ -0,0 +1,6 @@ +fn main() { + let xs : Vec> = vec![Some(1), None]; + + for Some(x) in xs {} + //~^ ERROR E0005 +} diff --git a/tests/ui/error-codes/E0297.stderr b/tests/ui/error-codes/E0297.stderr new file mode 100644 index 000000000..293028f5f --- /dev/null +++ b/tests/ui/error-codes/E0297.stderr @@ -0,0 +1,11 @@ +error[E0005]: refutable pattern in `for` loop binding + --> $DIR/E0297.rs:4:9 + | +LL | for Some(x) in xs {} + | ^^^^^^^ pattern `None` not covered + | + = note: the matched value is of type `Option` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/error-codes/E0308-2.rs b/tests/ui/error-codes/E0308-2.rs new file mode 100644 index 000000000..157f992da --- /dev/null +++ b/tests/ui/error-codes/E0308-2.rs @@ -0,0 +1,12 @@ +trait DynEq {} + +impl<'a> PartialEq for &'a (dyn DynEq + 'static) { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Eq for &dyn DynEq {} //~ ERROR E0308 + +fn main() { +} diff --git a/tests/ui/error-codes/E0308-2.stderr b/tests/ui/error-codes/E0308-2.stderr new file mode 100644 index 000000000..3a8a81a73 --- /dev/null +++ b/tests/ui/error-codes/E0308-2.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/E0308-2.rs:9:13 + | +LL | impl Eq for &dyn DynEq {} + | ^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `<&dyn DynEq as PartialEq>` + found trait `<&(dyn DynEq + 'static) as PartialEq>` +note: the anonymous lifetime as defined here... + --> $DIR/E0308-2.rs:9:13 + | +LL | impl Eq for &dyn DynEq {} + | ^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0308-4.rs b/tests/ui/error-codes/E0308-4.rs new file mode 100644 index 000000000..aaf7ef5bd --- /dev/null +++ b/tests/ui/error-codes/E0308-4.rs @@ -0,0 +1,7 @@ +fn main() { + let x = 1u8; + match x { + 0u8..=3i8 => (), //~ ERROR E0308 + _ => () + } +} diff --git a/tests/ui/error-codes/E0308-4.stderr b/tests/ui/error-codes/E0308-4.stderr new file mode 100644 index 000000000..39c067637 --- /dev/null +++ b/tests/ui/error-codes/E0308-4.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/E0308-4.rs:4:15 + | +LL | match x { + | - this expression has type `u8` +LL | 0u8..=3i8 => (), + | --- ^^^ expected `u8`, found `i8` + | | + | this is of type `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0308.rs b/tests/ui/error-codes/E0308.rs new file mode 100644 index 000000000..dd9e0b284 --- /dev/null +++ b/tests/ui/error-codes/E0308.rs @@ -0,0 +1,10 @@ +#![feature(intrinsics)] +#![feature(rustc_attrs)] + +extern "rust-intrinsic" { + #[rustc_safe_intrinsic] + fn size_of(); //~ ERROR E0308 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr new file mode 100644 index 000000000..187b775f9 --- /dev/null +++ b/tests/ui/error-codes/E0308.stderr @@ -0,0 +1,12 @@ +error[E0308]: intrinsic has wrong type + --> $DIR/E0308.rs:6:5 + | +LL | fn size_of(); + | ^^^^^^^^^^^^^^^^ expected `()`, found `usize` + | + = note: expected fn pointer `extern "rust-intrinsic" fn()` + found fn pointer `extern "rust-intrinsic" fn() -> usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0311.fixed b/tests/ui/error-codes/E0311.fixed new file mode 100644 index 000000000..4410a4d70 --- /dev/null +++ b/tests/ui/error-codes/E0311.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +#![allow(warnings)] + +fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { + with_restriction::(x) //~ ERROR E0311 +} + +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x +} + +fn main() {} diff --git a/tests/ui/error-codes/E0311.rs b/tests/ui/error-codes/E0311.rs new file mode 100644 index 000000000..99e454f4d --- /dev/null +++ b/tests/ui/error-codes/E0311.rs @@ -0,0 +1,13 @@ +// run-rustfix + +#![allow(warnings)] + +fn no_restriction(x: &()) -> &() { + with_restriction::(x) //~ ERROR E0311 +} + +fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { + x +} + +fn main() {} diff --git a/tests/ui/error-codes/E0311.stderr b/tests/ui/error-codes/E0311.stderr new file mode 100644 index 000000000..b0e6dd1e2 --- /dev/null +++ b/tests/ui/error-codes/E0311.stderr @@ -0,0 +1,24 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/E0311.rs:6:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/E0311.rs:5:25 + | +LL | fn no_restriction(x: &()) -> &() { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/E0311.rs:6:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { + | +++ ++++ ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/error-codes/E0328.rs b/tests/ui/error-codes/E0328.rs new file mode 100644 index 000000000..ef55f44dd --- /dev/null +++ b/tests/ui/error-codes/E0328.rs @@ -0,0 +1,10 @@ +#![feature(unsize)] + +use std::marker::Unsize; + +pub struct MyType; + +impl Unsize for MyType {} +//~^ ERROR explicit impls for the `Unsize` trait are not permitted [E0328] + +fn main() {} diff --git a/tests/ui/error-codes/E0328.stderr b/tests/ui/error-codes/E0328.stderr new file mode 100644 index 000000000..70e6baf69 --- /dev/null +++ b/tests/ui/error-codes/E0328.stderr @@ -0,0 +1,9 @@ +error[E0328]: explicit impls for the `Unsize` trait are not permitted + --> $DIR/E0328.rs:7:1 + | +LL | impl Unsize for MyType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unsize` not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0328`. diff --git a/tests/ui/error-codes/E0365.rs b/tests/ui/error-codes/E0365.rs new file mode 100644 index 000000000..464109247 --- /dev/null +++ b/tests/ui/error-codes/E0365.rs @@ -0,0 +1,8 @@ +mod foo { + pub const X: u32 = 1; +} + +pub use foo as foo2; +//~^ ERROR `foo` is only public within the crate, and cannot be re-exported outside [E0365] + +fn main() {} diff --git a/tests/ui/error-codes/E0365.stderr b/tests/ui/error-codes/E0365.stderr new file mode 100644 index 000000000..5bfcf1394 --- /dev/null +++ b/tests/ui/error-codes/E0365.stderr @@ -0,0 +1,11 @@ +error[E0365]: `foo` is only public within the crate, and cannot be re-exported outside + --> $DIR/E0365.rs:5:9 + | +LL | pub use foo as foo2; + | ^^^^^^^^^^^ re-export of crate public `foo` + | + = note: consider declaring type or module `foo` with `pub` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0365`. diff --git a/tests/ui/error-codes/E0370.rs b/tests/ui/error-codes/E0370.rs new file mode 100644 index 000000000..32a66b63b --- /dev/null +++ b/tests/ui/error-codes/E0370.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] + +#[deny(overflowing_literals)] +#[repr(i64)] +enum Foo { + X = 0x7fffffffffffffff, + Y, //~ ERROR E0370 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0370.stderr b/tests/ui/error-codes/E0370.stderr new file mode 100644 index 000000000..7fb622ee8 --- /dev/null +++ b/tests/ui/error-codes/E0370.stderr @@ -0,0 +1,11 @@ +error[E0370]: enum discriminant overflowed + --> $DIR/E0370.rs:7:5 + | +LL | Y, + | ^ overflowed on value after 9223372036854775807 + | + = note: explicitly set `Y = -9223372036854775808` if that is desired outcome + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0370`. diff --git a/tests/ui/error-codes/E0374.rs b/tests/ui/error-codes/E0374.rs new file mode 100644 index 000000000..41fcedc32 --- /dev/null +++ b/tests/ui/error-codes/E0374.rs @@ -0,0 +1,11 @@ +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, +} + +impl CoerceUnsized> for Foo //~ ERROR E0374 + where T: CoerceUnsized {} + +fn main() {} diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr new file mode 100644 index 000000000..68e15e6f8 --- /dev/null +++ b/tests/ui/error-codes/E0374.stderr @@ -0,0 +1,9 @@ +error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced, none found + --> $DIR/E0374.rs:8:1 + | +LL | impl CoerceUnsized> for Foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0374`. diff --git a/tests/ui/error-codes/E0375.rs b/tests/ui/error-codes/E0375.rs new file mode 100644 index 000000000..0c03a8761 --- /dev/null +++ b/tests/ui/error-codes/E0375.rs @@ -0,0 +1,13 @@ +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: i32, + b: T, + c: U, +} + +impl CoerceUnsized> for Foo {} +//~^ ERROR E0375 + +fn main() {} diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr new file mode 100644 index 000000000..a68b3af5a --- /dev/null +++ b/tests/ui/error-codes/E0375.stderr @@ -0,0 +1,12 @@ +error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions + --> $DIR/E0375.rs:10:12 + | +LL | impl CoerceUnsized> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions + | + = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0375`. diff --git a/tests/ui/error-codes/E0376.rs b/tests/ui/error-codes/E0376.rs new file mode 100644 index 000000000..f092eb02c --- /dev/null +++ b/tests/ui/error-codes/E0376.rs @@ -0,0 +1,10 @@ +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +struct Foo { + a: T, +} + +impl CoerceUnsized for Foo {} //~ ERROR E0376 + +fn main() {} diff --git a/tests/ui/error-codes/E0376.stderr b/tests/ui/error-codes/E0376.stderr new file mode 100644 index 000000000..e91efb045 --- /dev/null +++ b/tests/ui/error-codes/E0376.stderr @@ -0,0 +1,9 @@ +error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion between structures + --> $DIR/E0376.rs:8:1 + | +LL | impl CoerceUnsized for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0376`. diff --git a/tests/ui/error-codes/E0377.rs b/tests/ui/error-codes/E0377.rs new file mode 100644 index 000000000..6da2c2095 --- /dev/null +++ b/tests/ui/error-codes/E0377.rs @@ -0,0 +1,14 @@ +#![feature(coerce_unsized)] +use std::ops::CoerceUnsized; + +pub struct Foo { + field_with_unsized_type: T, +} + +pub struct Bar { + field_with_unsized_type: T, +} + +impl CoerceUnsized> for Foo where T: CoerceUnsized {} //~ ERROR E0377 + +fn main() {} diff --git a/tests/ui/error-codes/E0377.stderr b/tests/ui/error-codes/E0377.stderr new file mode 100644 index 000000000..bf7d8c8d3 --- /dev/null +++ b/tests/ui/error-codes/E0377.stderr @@ -0,0 +1,9 @@ +error[E0377]: the trait `CoerceUnsized` may only be implemented for a coercion between structures with the same definition; expected `Foo`, found `Bar` + --> $DIR/E0377.rs:12:1 + | +LL | impl CoerceUnsized> for Foo where T: CoerceUnsized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0377`. diff --git a/tests/ui/error-codes/E0388.rs b/tests/ui/error-codes/E0388.rs new file mode 100644 index 000000000..6049d95f0 --- /dev/null +++ b/tests/ui/error-codes/E0388.rs @@ -0,0 +1,13 @@ +static X: i32 = 1; +const C: i32 = 2; + +const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed + //~| WARN taking a mutable +static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow + //~| ERROR E0658 + //~| ERROR mutable references are not allowed + +static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed + //~| WARN taking a mutable + +fn main() {} diff --git a/tests/ui/error-codes/E0388.stderr b/tests/ui/error-codes/E0388.stderr new file mode 100644 index 000000000..b51aa263d --- /dev/null +++ b/tests/ui/error-codes/E0388.stderr @@ -0,0 +1,66 @@ +warning: taking a mutable reference to a `const` item + --> $DIR/E0388.rs:4:30 + | +LL | const CR: &'static mut i32 = &mut C; + | ^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/E0388.rs:2:1 + | +LL | const C: i32 = 2; + | ^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/E0388.rs:4:30 + | +LL | const CR: &'static mut i32 = &mut C; + | ^^^^^^ + +error[E0658]: mutation through a reference is not allowed in statics + --> $DIR/E0388.rs:6:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0388.rs:6:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ + +error[E0596]: cannot borrow immutable static item `X` as mutable + --> $DIR/E0388.rs:6:39 + | +LL | static STATIC_REF: &'static mut i32 = &mut X; + | ^^^^^^ cannot borrow as mutable + +warning: taking a mutable reference to a `const` item + --> $DIR/E0388.rs:10:38 + | +LL | static CONST_REF: &'static mut i32 = &mut C; + | ^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/E0388.rs:2:1 + | +LL | const C: i32 = 2; + | ^^^^^^^^^^^^ + +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/E0388.rs:10:38 + | +LL | static CONST_REF: &'static mut i32 = &mut C; + | ^^^^^^ + +error: aborting due to 5 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/error-codes/E0389.rs b/tests/ui/error-codes/E0389.rs new file mode 100644 index 000000000..41172b362 --- /dev/null +++ b/tests/ui/error-codes/E0389.rs @@ -0,0 +1,10 @@ +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + let fancy_ref = &(&mut fancy); + fancy_ref.num = 6; //~ ERROR cannot assign to `fancy_ref.num`, which is behind a `&` reference + println!("{}", fancy_ref.num); +} diff --git a/tests/ui/error-codes/E0389.stderr b/tests/ui/error-codes/E0389.stderr new file mode 100644 index 000000000..51c4c92ad --- /dev/null +++ b/tests/ui/error-codes/E0389.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference + --> $DIR/E0389.rs:8:5 + | +LL | fancy_ref.num = 6; + | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let fancy_ref = &mut (&mut fancy); + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/error-codes/E0390.rs b/tests/ui/error-codes/E0390.rs new file mode 100644 index 000000000..507483dec --- /dev/null +++ b/tests/ui/error-codes/E0390.rs @@ -0,0 +1,10 @@ +struct Foo { + x: i32 +} + +impl *mut Foo {} //~ ERROR E0390 + +impl fn(Foo) {} //~ ERROR E0390 + +fn main() { +} diff --git a/tests/ui/error-codes/E0390.stderr b/tests/ui/error-codes/E0390.stderr new file mode 100644 index 000000000..0e5a9ca76 --- /dev/null +++ b/tests/ui/error-codes/E0390.stderr @@ -0,0 +1,19 @@ +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/E0390.rs:5:6 + | +LL | impl *mut Foo {} + | ^^^^^^^^ + | + = help: consider using an extension trait instead + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/E0390.rs:7:6 + | +LL | impl fn(Foo) {} + | ^^^^^^^ + | + = help: consider using an extension trait instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0390`. diff --git a/tests/ui/error-codes/E0392.rs b/tests/ui/error-codes/E0392.rs new file mode 100644 index 000000000..c98d900b6 --- /dev/null +++ b/tests/ui/error-codes/E0392.rs @@ -0,0 +1,4 @@ +enum Foo { Bar } //~ ERROR E0392 + +fn main() { +} diff --git a/tests/ui/error-codes/E0392.stderr b/tests/ui/error-codes/E0392.stderr new file mode 100644 index 000000000..622402999 --- /dev/null +++ b/tests/ui/error-codes/E0392.stderr @@ -0,0 +1,12 @@ +error[E0392]: parameter `T` is never used + --> $DIR/E0392.rs:1:10 + | +LL | enum Foo { Bar } + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/error-codes/E0393.rs b/tests/ui/error-codes/E0393.rs new file mode 100644 index 000000000..0c1a36980 --- /dev/null +++ b/tests/ui/error-codes/E0393.rs @@ -0,0 +1,7 @@ +trait A {} + +fn together_we_will_rule_the_galaxy(son: &dyn A) {} +//~^ ERROR E0393 + +fn main() { +} diff --git a/tests/ui/error-codes/E0393.stderr b/tests/ui/error-codes/E0393.stderr new file mode 100644 index 000000000..d9f70b729 --- /dev/null +++ b/tests/ui/error-codes/E0393.stderr @@ -0,0 +1,14 @@ +error[E0393]: the type parameter `T` must be explicitly specified + --> $DIR/E0393.rs:3:47 + | +LL | trait A {} + | --------------- type parameter `T` must be specified for this +LL | +LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} + | ^ help: set the type parameter to the desired type: `A` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/error-codes/E0396-fixed.rs b/tests/ui/error-codes/E0396-fixed.rs new file mode 100644 index 000000000..fe20da1a8 --- /dev/null +++ b/tests/ui/error-codes/E0396-fixed.rs @@ -0,0 +1,9 @@ +#![feature(const_mut_refs)] + +const REG_ADDR: *mut u8 = 0x5f3759df as *mut u8; + +const VALUE: u8 = unsafe { *REG_ADDR }; +//~^ ERROR evaluation of constant value failed + +fn main() { +} diff --git a/tests/ui/error-codes/E0396-fixed.stderr b/tests/ui/error-codes/E0396-fixed.stderr new file mode 100644 index 000000000..2efbd6989 --- /dev/null +++ b/tests/ui/error-codes/E0396-fixed.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/E0396-fixed.rs:5:28 + | +LL | const VALUE: u8 = unsafe { *REG_ADDR }; + | ^^^^^^^^^ dereferencing pointer failed: 0x5f3759df[noalloc] is a dangling pointer (it has no provenance) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/error-codes/E0396.rs b/tests/ui/error-codes/E0396.rs new file mode 100644 index 000000000..4415b70e7 --- /dev/null +++ b/tests/ui/error-codes/E0396.rs @@ -0,0 +1,18 @@ +const REG_ADDR: *mut u8 = 0x5f3759df as *mut u8; + +const VALUE: u8 = unsafe { *REG_ADDR }; +//~^ ERROR dereferencing raw mutable pointers in constants is unstable + +const unsafe fn unreachable() -> ! { + use std::convert::Infallible; + + const INFALLIBLE: *mut Infallible = &[] as *const [Infallible] as *const _ as _; + match *INFALLIBLE {} + //~^ ERROR dereferencing raw mutable pointers in constant functions is unstable + + const BAD: () = unsafe { match *INFALLIBLE {} }; + //~^ ERROR dereferencing raw mutable pointers in constants is unstable +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0396.stderr b/tests/ui/error-codes/E0396.stderr new file mode 100644 index 000000000..8c87f4067 --- /dev/null +++ b/tests/ui/error-codes/E0396.stderr @@ -0,0 +1,30 @@ +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/E0396.rs:3:28 + | +LL | const VALUE: u8 = unsafe { *REG_ADDR }; + | ^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: dereferencing raw mutable pointers in constant functions is unstable + --> $DIR/E0396.rs:10:11 + | +LL | match *INFALLIBLE {} + | ^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: dereferencing raw mutable pointers in constants is unstable + --> $DIR/E0396.rs:13:36 + | +LL | const BAD: () = unsafe { match *INFALLIBLE {} }; + | ^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/error-codes/E0401.rs b/tests/ui/error-codes/E0401.rs new file mode 100644 index 000000000..8f8d6b87e --- /dev/null +++ b/tests/ui/error-codes/E0401.rs @@ -0,0 +1,32 @@ +trait Baz {} + +fn foo(x: T) { + fn bfnr, W: Fn()>(y: T) { //~ ERROR E0401 + } + fn baz, + W: Fn()> + (y: T) { //~ ERROR E0401 + } + bfnr(x); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + + +struct A { + inner: T, +} + +impl Iterator for A { + type Item = u8; + fn next(&mut self) -> Option { + fn helper(sel: &Self) -> u8 { //~ ERROR E0401 + unimplemented!(); + } + Some(helper(self)) + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr new file mode 100644 index 000000000..fa4b91cac --- /dev/null +++ b/tests/ui/error-codes/E0401.stderr @@ -0,0 +1,70 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/E0401.rs:4:39 + | +LL | fn foo(x: T) { + | - type parameter from outer function +LL | fn bfnr, W: Fn()>(y: T) { + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `T,` + +error[E0401]: can't use generic parameters from outer function + --> $DIR/E0401.rs:9:16 + | +LL | fn foo(x: T) { + | - type parameter from outer function +... +LL | fn baz $DIR/E0401.rs:24:25 + | +LL | impl Iterator for A { + | ---- `Self` type implicitly declared here, by this `impl` +... +LL | fn helper(sel: &Self) -> u8 { + | ^^^^ + | | + | use of generic parameter from outer function + | use a type here instead + +error[E0282]: type annotations needed + --> $DIR/E0401.rs:11:5 + | +LL | bfnr(x); + | ^^^^ cannot infer type of the type parameter `U` declared on the function `bfnr` + | +help: consider specifying the generic arguments + | +LL | bfnr::(x); + | +++++++++++ + +error[E0283]: type annotations needed + --> $DIR/E0401.rs:11:5 + | +LL | bfnr(x); + | ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr` + | + = note: multiple `impl`s satisfying `_: Fn<()>` found in the following crates: `alloc`, `core`: + - impl Fn for &F + where A: Tuple, F: Fn, F: ?Sized; + - impl Fn for Box + where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; +note: required by a bound in `bfnr` + --> $DIR/E0401.rs:4:30 + | +LL | fn bfnr, W: Fn()>(y: T) { + | ^^^^ required by this bound in `bfnr` +help: consider specifying the generic arguments + | +LL | bfnr::(x); + | +++++++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0282, E0283, E0401. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/error-codes/E0403.rs b/tests/ui/error-codes/E0403.rs new file mode 100644 index 000000000..8bccb631a --- /dev/null +++ b/tests/ui/error-codes/E0403.rs @@ -0,0 +1,4 @@ +fn foo(s: T, u: T) {} //~ ERROR E0403 + +fn main() { +} diff --git a/tests/ui/error-codes/E0403.stderr b/tests/ui/error-codes/E0403.stderr new file mode 100644 index 000000000..d76a58a7c --- /dev/null +++ b/tests/ui/error-codes/E0403.stderr @@ -0,0 +1,11 @@ +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/E0403.rs:1:11 + | +LL | fn foo(s: T, u: T) {} + | - ^ already used + | | + | first use of `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/error-codes/E0404.rs b/tests/ui/error-codes/E0404.rs new file mode 100644 index 000000000..b17333724 --- /dev/null +++ b/tests/ui/error-codes/E0404.rs @@ -0,0 +1,8 @@ +struct Foo; +struct Bar; + +impl Foo for Bar {} //~ ERROR E0404 + +fn main() {} + +fn baz(_: T) {} //~ ERROR E0404 diff --git a/tests/ui/error-codes/E0404.stderr b/tests/ui/error-codes/E0404.stderr new file mode 100644 index 000000000..4ccb6c572 --- /dev/null +++ b/tests/ui/error-codes/E0404.stderr @@ -0,0 +1,15 @@ +error[E0404]: expected trait, found struct `Foo` + --> $DIR/E0404.rs:4:6 + | +LL | impl Foo for Bar {} + | ^^^ not a trait + +error[E0404]: expected trait, found struct `Foo` + --> $DIR/E0404.rs:8:11 + | +LL | fn baz(_: T) {} + | ^^^ not a trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/error-codes/E0405.rs b/tests/ui/error-codes/E0405.rs new file mode 100644 index 000000000..f03c4e19b --- /dev/null +++ b/tests/ui/error-codes/E0405.rs @@ -0,0 +1,6 @@ +struct Foo; + +impl SomeTrait for Foo {} //~ ERROR E0405 + +fn main() { +} diff --git a/tests/ui/error-codes/E0405.stderr b/tests/ui/error-codes/E0405.stderr new file mode 100644 index 000000000..a22afe6f3 --- /dev/null +++ b/tests/ui/error-codes/E0405.stderr @@ -0,0 +1,9 @@ +error[E0405]: cannot find trait `SomeTrait` in this scope + --> $DIR/E0405.rs:3:6 + | +LL | impl SomeTrait for Foo {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/error-codes/E0407.rs b/tests/ui/error-codes/E0407.rs new file mode 100644 index 000000000..962bd5741 --- /dev/null +++ b/tests/ui/error-codes/E0407.rs @@ -0,0 +1,14 @@ +trait Foo { + fn a(); +} + +struct Bar; + +impl Foo for Bar { + fn a() {} + fn b() {} + //~^ ERROR E0407 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0407.stderr b/tests/ui/error-codes/E0407.stderr new file mode 100644 index 000000000..6f6d1ff6a --- /dev/null +++ b/tests/ui/error-codes/E0407.stderr @@ -0,0 +1,12 @@ +error[E0407]: method `b` is not a member of trait `Foo` + --> $DIR/E0407.rs:9:5 + | +LL | fn b() {} + | ^^^-^^^^^ + | | | + | | help: there is an associated function with a similar name: `a` + | not a member of trait `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0407`. diff --git a/tests/ui/error-codes/E0408.rs b/tests/ui/error-codes/E0408.rs new file mode 100644 index 000000000..e91a98f38 --- /dev/null +++ b/tests/ui/error-codes/E0408.rs @@ -0,0 +1,8 @@ +fn main() { + let x = Some(0); + + match x { + Some(y) | None => {} //~ ERROR variable `y` is not bound in all patterns + _ => () + } +} diff --git a/tests/ui/error-codes/E0408.stderr b/tests/ui/error-codes/E0408.stderr new file mode 100644 index 000000000..132a94322 --- /dev/null +++ b/tests/ui/error-codes/E0408.stderr @@ -0,0 +1,11 @@ +error[E0408]: variable `y` is not bound in all patterns + --> $DIR/E0408.rs:5:19 + | +LL | Some(y) | None => {} + | - ^^^^ pattern doesn't bind `y` + | | + | variable not in all patterns + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/error-codes/E0411.rs b/tests/ui/error-codes/E0411.rs new file mode 100644 index 000000000..872370f2a --- /dev/null +++ b/tests/ui/error-codes/E0411.rs @@ -0,0 +1,3 @@ +fn main() { + ::foo; //~ ERROR E0411 +} diff --git a/tests/ui/error-codes/E0411.stderr b/tests/ui/error-codes/E0411.stderr new file mode 100644 index 000000000..4c99f9fcb --- /dev/null +++ b/tests/ui/error-codes/E0411.stderr @@ -0,0 +1,11 @@ +error[E0411]: cannot find type `Self` in this scope + --> $DIR/E0411.rs:2:6 + | +LL | fn main() { + | ---- `Self` not allowed in a function +LL | ::foo; + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0411`. diff --git a/tests/ui/error-codes/E0412.rs b/tests/ui/error-codes/E0412.rs new file mode 100644 index 000000000..5f922a50a --- /dev/null +++ b/tests/ui/error-codes/E0412.rs @@ -0,0 +1,4 @@ +impl Something {} //~ ERROR E0412 + +fn main() { +} diff --git a/tests/ui/error-codes/E0412.stderr b/tests/ui/error-codes/E0412.stderr new file mode 100644 index 000000000..7bdaa1807 --- /dev/null +++ b/tests/ui/error-codes/E0412.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Something` in this scope + --> $DIR/E0412.rs:1:6 + | +LL | impl Something {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/error-codes/E0415.rs b/tests/ui/error-codes/E0415.rs new file mode 100644 index 000000000..6177ac35b --- /dev/null +++ b/tests/ui/error-codes/E0415.rs @@ -0,0 +1,4 @@ +fn foo(f: i32, f: i32) {} //~ ERROR E0415 + +fn main() { +} diff --git a/tests/ui/error-codes/E0415.stderr b/tests/ui/error-codes/E0415.stderr new file mode 100644 index 000000000..c2b8fdc7c --- /dev/null +++ b/tests/ui/error-codes/E0415.stderr @@ -0,0 +1,9 @@ +error[E0415]: identifier `f` is bound more than once in this parameter list + --> $DIR/E0415.rs:1:16 + | +LL | fn foo(f: i32, f: i32) {} + | ^ used as parameter more than once + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0415`. diff --git a/tests/ui/error-codes/E0416.rs b/tests/ui/error-codes/E0416.rs new file mode 100644 index 000000000..88eece07a --- /dev/null +++ b/tests/ui/error-codes/E0416.rs @@ -0,0 +1,5 @@ +fn main() { + match (1, 2) { + (x, x) => {} //~ ERROR E0416 + } +} diff --git a/tests/ui/error-codes/E0416.stderr b/tests/ui/error-codes/E0416.stderr new file mode 100644 index 000000000..78acac5c6 --- /dev/null +++ b/tests/ui/error-codes/E0416.stderr @@ -0,0 +1,9 @@ +error[E0416]: identifier `x` is bound more than once in the same pattern + --> $DIR/E0416.rs:3:13 + | +LL | (x, x) => {} + | ^ used in a pattern more than once + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0416`. diff --git a/tests/ui/error-codes/E0423.rs b/tests/ui/error-codes/E0423.rs new file mode 100644 index 000000000..5080a5e05 --- /dev/null +++ b/tests/ui/error-codes/E0423.rs @@ -0,0 +1,22 @@ +fn main () { + struct Foo { a: bool }; + + let f = Foo(); //~ ERROR E0423 +} + +fn bar() { + struct S { x: i32, y: i32 } + #[derive(PartialEq)] + struct T {} + + if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); } + //~^ ERROR struct literals are not allowed here + if T {} == T {} { println!("Ok"); } + //~^ ERROR E0423 + //~| ERROR expected expression, found `==` +} + +fn foo() { + for _ in std::ops::Range { start: 0, end: 10 } {} + //~^ ERROR struct literals are not allowed here +} diff --git a/tests/ui/error-codes/E0423.stderr b/tests/ui/error-codes/E0423.stderr new file mode 100644 index 000000000..ac70d905d --- /dev/null +++ b/tests/ui/error-codes/E0423.stderr @@ -0,0 +1,63 @@ +error: struct literals are not allowed here + --> $DIR/E0423.rs:12:32 + | +LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); } + | ^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if let S { x: _x, y: 2 } = (S { x: 1, y: 2 }) { println!("Ok"); } + | + + + +error: expected expression, found `==` + --> $DIR/E0423.rs:14:13 + | +LL | if T {} == T {} { println!("Ok"); } + | ^^ expected expression + +error: struct literals are not allowed here + --> $DIR/E0423.rs:20:14 + | +LL | for _ in std::ops::Range { start: 0, end: 10 } {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | for _ in (std::ops::Range { start: 0, end: 10 }) {} + | + + + +error[E0423]: expected value, found struct `T` + --> $DIR/E0423.rs:14:8 + | +LL | if T {} == T {} { println!("Ok"); } + | ^ not a value + | +help: surround the struct literal with parentheses + | +LL | if (T {}) == T {} { println!("Ok"); } + | + + + +error[E0423]: expected function, tuple struct or tuple variant, found struct `Foo` + --> $DIR/E0423.rs:4:13 + | +LL | struct Foo { a: bool }; + | ---------------------- `Foo` defined here +LL | +LL | let f = Foo(); + | ^^^^^ +... +LL | fn foo() { + | -------- similarly named function `foo` defined here + | +help: use struct literal syntax instead + | +LL | let f = Foo { a: val }; + | ~~~~~~~~~~~~~~ +help: a function with a similar name exists + | +LL | let f = foo(); + | ~~~ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/error-codes/E0424.rs b/tests/ui/error-codes/E0424.rs new file mode 100644 index 000000000..6e531942c --- /dev/null +++ b/tests/ui/error-codes/E0424.rs @@ -0,0 +1,21 @@ +struct Foo; + +impl Foo { + fn bar(self) {} + + fn foo() { + self.bar(); //~ ERROR E0424 + } + + fn baz(_: i32) { + self.bar(); //~ ERROR E0424 + } + + fn qux() { + let _ = || self.bar(); //~ ERROR E0424 + } +} + +fn main () { + let self = "self"; //~ ERROR E0424 +} diff --git a/tests/ui/error-codes/E0424.stderr b/tests/ui/error-codes/E0424.stderr new file mode 100644 index 000000000..d02da3e4e --- /dev/null +++ b/tests/ui/error-codes/E0424.stderr @@ -0,0 +1,50 @@ +error[E0424]: expected value, found module `self` + --> $DIR/E0424.rs:7:9 + | +LL | fn foo() { + | --- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn foo(&self) { + | +++++ + +error[E0424]: expected value, found module `self` + --> $DIR/E0424.rs:11:9 + | +LL | fn baz(_: i32) { + | --- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn baz(&self, _: i32) { + | ++++++ + +error[E0424]: expected value, found module `self` + --> $DIR/E0424.rs:15:20 + | +LL | fn qux() { + | --- this function doesn't have a `self` parameter +LL | let _ = || self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn qux(&self) { + | +++++ + +error[E0424]: expected unit struct, unit variant or constant, found module `self` + --> $DIR/E0424.rs:20:9 + | +LL | fn main () { + | ---- this function can't have a `self` parameter +LL | let self = "self"; + | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0424`. diff --git a/tests/ui/error-codes/E0425.rs b/tests/ui/error-codes/E0425.rs new file mode 100644 index 000000000..ec234ae99 --- /dev/null +++ b/tests/ui/error-codes/E0425.rs @@ -0,0 +1,8 @@ +trait Foo { + fn bar() { + elf; //~ ERROR E0425 + } +} + +fn main () { +} diff --git a/tests/ui/error-codes/E0425.stderr b/tests/ui/error-codes/E0425.stderr new file mode 100644 index 000000000..9ef4608da --- /dev/null +++ b/tests/ui/error-codes/E0425.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `elf` in this scope + --> $DIR/E0425.rs:3:9 + | +LL | elf; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/error-codes/E0426.rs b/tests/ui/error-codes/E0426.rs new file mode 100644 index 000000000..7a1dcde49 --- /dev/null +++ b/tests/ui/error-codes/E0426.rs @@ -0,0 +1,6 @@ +fn main () { + loop { + break 'a; + //~^ ERROR E0426 + } +} diff --git a/tests/ui/error-codes/E0426.stderr b/tests/ui/error-codes/E0426.stderr new file mode 100644 index 000000000..035f2eb86 --- /dev/null +++ b/tests/ui/error-codes/E0426.stderr @@ -0,0 +1,9 @@ +error[E0426]: use of undeclared label `'a` + --> $DIR/E0426.rs:3:15 + | +LL | break 'a; + | ^^ undeclared label `'a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/error-codes/E0428.rs b/tests/ui/error-codes/E0428.rs new file mode 100644 index 000000000..eb9594fb8 --- /dev/null +++ b/tests/ui/error-codes/E0428.rs @@ -0,0 +1,5 @@ +struct Bar; //~ previous definition of the type `Bar` here +struct Bar; //~ ERROR E0428 + +fn main () { +} diff --git a/tests/ui/error-codes/E0428.stderr b/tests/ui/error-codes/E0428.stderr new file mode 100644 index 000000000..205bcf342 --- /dev/null +++ b/tests/ui/error-codes/E0428.stderr @@ -0,0 +1,13 @@ +error[E0428]: the name `Bar` is defined multiple times + --> $DIR/E0428.rs:2:1 + | +LL | struct Bar; + | ----------- previous definition of the type `Bar` here +LL | struct Bar; + | ^^^^^^^^^^^ `Bar` redefined here + | + = note: `Bar` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/error-codes/E0429.rs b/tests/ui/error-codes/E0429.rs new file mode 100644 index 000000000..e74b27a78 --- /dev/null +++ b/tests/ui/error-codes/E0429.rs @@ -0,0 +1,4 @@ +use std::fmt::self; //~ ERROR E0429 + +fn main () { +} diff --git a/tests/ui/error-codes/E0429.stderr b/tests/ui/error-codes/E0429.stderr new file mode 100644 index 000000000..08b99232e --- /dev/null +++ b/tests/ui/error-codes/E0429.stderr @@ -0,0 +1,19 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/E0429.rs:1:13 + | +LL | use std::fmt::self; + | ^^^^^^ + | +help: consider importing the module directly + | +LL - use std::fmt::self; +LL + use std::fmt; + | +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use std::fmt::{self}; + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/error-codes/E0430.rs b/tests/ui/error-codes/E0430.rs new file mode 100644 index 000000000..ba2f671d6 --- /dev/null +++ b/tests/ui/error-codes/E0430.rs @@ -0,0 +1,5 @@ +use std::fmt::{self, self}; //~ ERROR E0430 + //~^ ERROR E0252 + +fn main () { +} diff --git a/tests/ui/error-codes/E0430.stderr b/tests/ui/error-codes/E0430.stderr new file mode 100644 index 000000000..69a0d6e11 --- /dev/null +++ b/tests/ui/error-codes/E0430.stderr @@ -0,0 +1,22 @@ +error[E0430]: `self` import can only appear once in an import list + --> $DIR/E0430.rs:1:16 + | +LL | use std::fmt::{self, self}; + | ^^^^ ---- another `self` import appears here + | | + | can only appear once in an import list + +error[E0252]: the name `fmt` is defined multiple times + --> $DIR/E0430.rs:1:22 + | +LL | use std::fmt::{self, self}; + | ---- ^^^^ `fmt` reimported here + | | + | previous import of the module `fmt` here + | + = note: `fmt` must be defined only once in the type namespace of this module + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0252, E0430. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/error-codes/E0431.rs b/tests/ui/error-codes/E0431.rs new file mode 100644 index 000000000..2e2ccba17 --- /dev/null +++ b/tests/ui/error-codes/E0431.rs @@ -0,0 +1,4 @@ +use {self}; //~ ERROR E0431 + +fn main () { +} diff --git a/tests/ui/error-codes/E0431.stderr b/tests/ui/error-codes/E0431.stderr new file mode 100644 index 000000000..adfd2d923 --- /dev/null +++ b/tests/ui/error-codes/E0431.stderr @@ -0,0 +1,9 @@ +error[E0431]: `self` import can only appear in an import list with a non-empty prefix + --> $DIR/E0431.rs:1:6 + | +LL | use {self}; + | ^^^^ can only appear in an import list with a non-empty prefix + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0431`. diff --git a/tests/ui/error-codes/E0432.rs b/tests/ui/error-codes/E0432.rs new file mode 100644 index 000000000..1fc95f945 --- /dev/null +++ b/tests/ui/error-codes/E0432.rs @@ -0,0 +1,4 @@ +use something::Foo; //~ ERROR E0432 + +fn main () { +} diff --git a/tests/ui/error-codes/E0432.stderr b/tests/ui/error-codes/E0432.stderr new file mode 100644 index 000000000..ed9536f16 --- /dev/null +++ b/tests/ui/error-codes/E0432.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `something` + --> $DIR/E0432.rs:1:5 + | +LL | use something::Foo; + | ^^^^^^^^^ maybe a missing crate `something`? + | + = help: consider adding `extern crate something` to use the `something` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/error-codes/E0433.rs b/tests/ui/error-codes/E0433.rs new file mode 100644 index 000000000..d555e6542 --- /dev/null +++ b/tests/ui/error-codes/E0433.rs @@ -0,0 +1,3 @@ +fn main () { + let map = NonExistingMap::new(); //~ ERROR E0433 +} diff --git a/tests/ui/error-codes/E0433.stderr b/tests/ui/error-codes/E0433.stderr new file mode 100644 index 000000000..265d8885c --- /dev/null +++ b/tests/ui/error-codes/E0433.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared type `NonExistingMap` + --> $DIR/E0433.rs:2:15 + | +LL | let map = NonExistingMap::new(); + | ^^^^^^^^^^^^^^ use of undeclared type `NonExistingMap` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/error-codes/E0434.rs b/tests/ui/error-codes/E0434.rs new file mode 100644 index 000000000..db7037ee1 --- /dev/null +++ b/tests/ui/error-codes/E0434.rs @@ -0,0 +1,9 @@ +fn foo() { + let y = 5; + fn bar() -> u32 { + y //~ ERROR E0434 + } +} + +fn main () { +} diff --git a/tests/ui/error-codes/E0434.stderr b/tests/ui/error-codes/E0434.stderr new file mode 100644 index 000000000..14508ccbc --- /dev/null +++ b/tests/ui/error-codes/E0434.stderr @@ -0,0 +1,11 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/E0434.rs:4:9 + | +LL | y + | ^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/error-codes/E0435.fixed b/tests/ui/error-codes/E0435.fixed new file mode 100644 index 000000000..fdf896d2d --- /dev/null +++ b/tests/ui/error-codes/E0435.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main () { + #[allow(non_upper_case_globals)] + const foo: usize = 42; + let _: [u8; foo]; //~ ERROR E0435 +} diff --git a/tests/ui/error-codes/E0435.rs b/tests/ui/error-codes/E0435.rs new file mode 100644 index 000000000..d9354efb8 --- /dev/null +++ b/tests/ui/error-codes/E0435.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main () { + #[allow(non_upper_case_globals)] + let foo: usize = 42; + let _: [u8; foo]; //~ ERROR E0435 +} diff --git a/tests/ui/error-codes/E0435.stderr b/tests/ui/error-codes/E0435.stderr new file mode 100644 index 000000000..fc08fade9 --- /dev/null +++ b/tests/ui/error-codes/E0435.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/E0435.rs:5:17 + | +LL | let foo: usize = 42; + | ------- help: consider using `const` instead of `let`: `const foo` +LL | let _: [u8; foo]; + | ^^^ non-constant value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/error-codes/E0437.rs b/tests/ui/error-codes/E0437.rs new file mode 100644 index 000000000..f8c15007d --- /dev/null +++ b/tests/ui/error-codes/E0437.rs @@ -0,0 +1,8 @@ +trait Foo {} + +impl Foo for i32 { + type Bar = bool; //~ ERROR E0437 +} + +fn main () { +} diff --git a/tests/ui/error-codes/E0437.stderr b/tests/ui/error-codes/E0437.stderr new file mode 100644 index 000000000..217b16403 --- /dev/null +++ b/tests/ui/error-codes/E0437.stderr @@ -0,0 +1,9 @@ +error[E0437]: type `Bar` is not a member of trait `Foo` + --> $DIR/E0437.rs:4:5 + | +LL | type Bar = bool; + | ^^^^^^^^^^^^^^^^ not a member of trait `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0437`. diff --git a/tests/ui/error-codes/E0438.rs b/tests/ui/error-codes/E0438.rs new file mode 100644 index 000000000..02898b886 --- /dev/null +++ b/tests/ui/error-codes/E0438.rs @@ -0,0 +1,8 @@ +trait Bar {} + +impl Bar for i32 { + const BAR: bool = true; //~ ERROR E0438 +} + +fn main () { +} diff --git a/tests/ui/error-codes/E0438.stderr b/tests/ui/error-codes/E0438.stderr new file mode 100644 index 000000000..853f0c3c2 --- /dev/null +++ b/tests/ui/error-codes/E0438.stderr @@ -0,0 +1,9 @@ +error[E0438]: const `BAR` is not a member of trait `Bar` + --> $DIR/E0438.rs:4:5 + | +LL | const BAR: bool = true; + | ^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0438`. diff --git a/tests/ui/error-codes/E0445.rs b/tests/ui/error-codes/E0445.rs new file mode 100644 index 000000000..a9a3aee25 --- /dev/null +++ b/tests/ui/error-codes/E0445.rs @@ -0,0 +1,12 @@ +trait Foo { + fn dummy(&self) { } +} + +pub trait Bar : Foo {} +//~^ ERROR private trait `Foo` in public interface [E0445] +pub struct Bar2(pub T); +//~^ ERROR private trait `Foo` in public interface [E0445] +pub fn foo (t: T) {} +//~^ ERROR private trait `Foo` in public interface [E0445] + +fn main() {} diff --git a/tests/ui/error-codes/E0445.stderr b/tests/ui/error-codes/E0445.stderr new file mode 100644 index 000000000..23b7a3350 --- /dev/null +++ b/tests/ui/error-codes/E0445.stderr @@ -0,0 +1,30 @@ +error[E0445]: private trait `Foo` in public interface + --> $DIR/E0445.rs:5:1 + | +LL | trait Foo { + | --------- `Foo` declared as private +... +LL | pub trait Bar : Foo {} + | ^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `Foo` in public interface + --> $DIR/E0445.rs:7:1 + | +LL | trait Foo { + | --------- `Foo` declared as private +... +LL | pub struct Bar2(pub T); + | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `Foo` in public interface + --> $DIR/E0445.rs:9:1 + | +LL | trait Foo { + | --------- `Foo` declared as private +... +LL | pub fn foo (t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0445`. diff --git a/tests/ui/error-codes/E0446.rs b/tests/ui/error-codes/E0446.rs new file mode 100644 index 000000000..f61c7e546 --- /dev/null +++ b/tests/ui/error-codes/E0446.rs @@ -0,0 +1,9 @@ +mod foo { + struct Bar(u32); + + pub fn bar() -> Bar { //~ ERROR E0446 + Bar(0) + } +} + +fn main() {} diff --git a/tests/ui/error-codes/E0446.stderr b/tests/ui/error-codes/E0446.stderr new file mode 100644 index 000000000..b6a195c40 --- /dev/null +++ b/tests/ui/error-codes/E0446.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `Bar` in public interface + --> $DIR/E0446.rs:4:5 + | +LL | struct Bar(u32); + | ---------- `Bar` declared as private +LL | +LL | pub fn bar() -> Bar { + | ^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/error-codes/E0449.rs b/tests/ui/error-codes/E0449.rs new file mode 100644 index 000000000..eba0d479e --- /dev/null +++ b/tests/ui/error-codes/E0449.rs @@ -0,0 +1,14 @@ +struct Bar; + +trait Foo { + fn foo(); +} + +pub impl Bar {} //~ ERROR E0449 + +pub impl Foo for Bar { //~ ERROR E0449 + pub fn foo() {} //~ ERROR E0449 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0449.stderr b/tests/ui/error-codes/E0449.stderr new file mode 100644 index 000000000..8221a5e0a --- /dev/null +++ b/tests/ui/error-codes/E0449.stderr @@ -0,0 +1,23 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/E0449.rs:7:1 + | +LL | pub impl Bar {} + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual impl items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/E0449.rs:9:1 + | +LL | pub impl Foo for Bar { + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/E0449.rs:10:5 + | +LL | pub fn foo() {} + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/error-codes/E0451.rs b/tests/ui/error-codes/E0451.rs new file mode 100644 index 000000000..aa8f051af --- /dev/null +++ b/tests/ui/error-codes/E0451.rs @@ -0,0 +1,19 @@ +mod bar { + pub struct Foo { + pub a: isize, + b: isize, + } + + pub struct FooTuple ( + pub isize, + isize, + ); +} + +fn pat_match(foo: bar::Foo) { + let bar::Foo{a, b} = foo; //~ ERROR E0451 +} + +fn main() { + let f = bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 +} diff --git a/tests/ui/error-codes/E0451.stderr b/tests/ui/error-codes/E0451.stderr new file mode 100644 index 000000000..419cf117e --- /dev/null +++ b/tests/ui/error-codes/E0451.stderr @@ -0,0 +1,15 @@ +error[E0451]: field `b` of struct `Foo` is private + --> $DIR/E0451.rs:14:21 + | +LL | let bar::Foo{a, b} = foo; + | ^ private field + +error[E0451]: field `b` of struct `Foo` is private + --> $DIR/E0451.rs:18:29 + | +LL | let f = bar::Foo{ a: 0, b: 0 }; + | ^^^^ private field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/error-codes/E0452.rs b/tests/ui/error-codes/E0452.rs new file mode 100644 index 000000000..5066cd99b --- /dev/null +++ b/tests/ui/error-codes/E0452.rs @@ -0,0 +1,6 @@ +#![allow(foo = "")] //~ ERROR E0452 + //~| ERROR E0452 + //~| ERROR E0452 + //~| ERROR E0452 +fn main() { +} diff --git a/tests/ui/error-codes/E0452.stderr b/tests/ui/error-codes/E0452.stderr new file mode 100644 index 000000000..f67b740ff --- /dev/null +++ b/tests/ui/error-codes/E0452.stderr @@ -0,0 +1,27 @@ +error[E0452]: malformed lint attribute input + --> $DIR/E0452.rs:1:10 + | +LL | #![allow(foo = "")] + | ^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/E0452.rs:1:10 + | +LL | #![allow(foo = "")] + | ^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/E0452.rs:1:10 + | +LL | #![allow(foo = "")] + | ^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/E0452.rs:1:10 + | +LL | #![allow(foo = "")] + | ^^^^^^^^ bad attribute argument + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/error-codes/E0453.rs b/tests/ui/error-codes/E0453.rs new file mode 100644 index 000000000..ca9573c5b --- /dev/null +++ b/tests/ui/error-codes/E0453.rs @@ -0,0 +1,7 @@ +#![forbid(non_snake_case)] + +#[allow(non_snake_case)] +//~^ ERROR allow(non_snake_case) incompatible +//~| ERROR allow(non_snake_case) incompatible +fn main() { +} diff --git a/tests/ui/error-codes/E0453.stderr b/tests/ui/error-codes/E0453.stderr new file mode 100644 index 000000000..f982ed26f --- /dev/null +++ b/tests/ui/error-codes/E0453.stderr @@ -0,0 +1,21 @@ +error[E0453]: allow(non_snake_case) incompatible with previous forbid + --> $DIR/E0453.rs:3:9 + | +LL | #![forbid(non_snake_case)] + | -------------- `forbid` level set here +LL | +LL | #[allow(non_snake_case)] + | ^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(non_snake_case) incompatible with previous forbid + --> $DIR/E0453.rs:3:9 + | +LL | #![forbid(non_snake_case)] + | -------------- `forbid` level set here +LL | +LL | #[allow(non_snake_case)] + | ^^^^^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/error-codes/E0454.rs b/tests/ui/error-codes/E0454.rs new file mode 100644 index 000000000..ff5478382 --- /dev/null +++ b/tests/ui/error-codes/E0454.rs @@ -0,0 +1,5 @@ +#[link(name = "")] extern "C" {} +//~^ ERROR E0454 + +fn main() { +} diff --git a/tests/ui/error-codes/E0454.stderr b/tests/ui/error-codes/E0454.stderr new file mode 100644 index 000000000..b9a506fee --- /dev/null +++ b/tests/ui/error-codes/E0454.stderr @@ -0,0 +1,9 @@ +error[E0454]: link name must not be empty + --> $DIR/E0454.rs:1:15 + | +LL | #[link(name = "")] extern "C" {} + | ^^ empty link name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0454`. diff --git a/tests/ui/error-codes/E0458.rs b/tests/ui/error-codes/E0458.rs new file mode 100644 index 000000000..35e7e84d4 --- /dev/null +++ b/tests/ui/error-codes/E0458.rs @@ -0,0 +1,5 @@ +#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR E0458 + //~| ERROR E0459 + +fn main() { +} diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr new file mode 100644 index 000000000..e641bba54 --- /dev/null +++ b/tests/ui/error-codes/E0458.stderr @@ -0,0 +1,16 @@ +error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib + --> $DIR/E0458.rs:1:15 + | +LL | #[link(kind = "wonderful_unicorn")] extern "C" {} + | ^^^^^^^^^^^^^^^^^^^ unknown link kind + +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/E0458.rs:1:1 + | +LL | #[link(kind = "wonderful_unicorn")] extern "C" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0458, E0459. +For more information about an error, try `rustc --explain E0458`. diff --git a/tests/ui/error-codes/E0459.rs b/tests/ui/error-codes/E0459.rs new file mode 100644 index 000000000..c56d8f0a8 --- /dev/null +++ b/tests/ui/error-codes/E0459.rs @@ -0,0 +1,4 @@ +#[link(kind = "dylib")] extern "C" {} //~ ERROR E0459 + +fn main() { +} diff --git a/tests/ui/error-codes/E0459.stderr b/tests/ui/error-codes/E0459.stderr new file mode 100644 index 000000000..8f0dd25e0 --- /dev/null +++ b/tests/ui/error-codes/E0459.stderr @@ -0,0 +1,9 @@ +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/E0459.rs:1:1 + | +LL | #[link(kind = "dylib")] extern "C" {} + | ^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0459`. diff --git a/tests/ui/error-codes/E0462.rs b/tests/ui/error-codes/E0462.rs new file mode 100644 index 000000000..f839ee783 --- /dev/null +++ b/tests/ui/error-codes/E0462.rs @@ -0,0 +1,11 @@ +// aux-build:found-staticlib.rs + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" +// normalize-stderr-test: "(lib)?found_staticlib\.[a-z]+" -> "libfound_staticlib.somelib" + +extern crate found_staticlib; //~ ERROR E0462 + +fn main() { + found_staticlib::foo(); +} diff --git a/tests/ui/error-codes/E0462.stderr b/tests/ui/error-codes/E0462.stderr new file mode 100644 index 000000000..43e27965f --- /dev/null +++ b/tests/ui/error-codes/E0462.stderr @@ -0,0 +1,13 @@ +error[E0462]: found staticlib `found_staticlib` instead of rlib or dylib + --> $DIR/E0462.rs:7:1 + | +LL | extern crate found_staticlib; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the following crate versions were found: + crate `found_staticlib`: $TEST_BUILD_DIR/error-codes/E0462/auxiliary/libfound_staticlib.somelib + = help: please recompile that crate using --crate-type lib + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0462`. diff --git a/tests/ui/error-codes/E0463.rs b/tests/ui/error-codes/E0463.rs new file mode 100644 index 000000000..683565281 --- /dev/null +++ b/tests/ui/error-codes/E0463.rs @@ -0,0 +1,7 @@ +#![feature(plugin)] +#![plugin(cookie_monster)] +//~^ ERROR E0463 +extern crate cake_is_a_lie; + +fn main() { +} diff --git a/tests/ui/error-codes/E0463.stderr b/tests/ui/error-codes/E0463.stderr new file mode 100644 index 000000000..1aa66e1ec --- /dev/null +++ b/tests/ui/error-codes/E0463.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `cookie_monster` + --> $DIR/E0463.rs:2:11 + | +LL | #![plugin(cookie_monster)] + | ^^^^^^^^^^^^^^ can't find crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/error-codes/E0464.rs b/tests/ui/error-codes/E0464.rs new file mode 100644 index 000000000..47717fbd5 --- /dev/null +++ b/tests/ui/error-codes/E0464.rs @@ -0,0 +1,14 @@ +// aux-build:crateresolve1-1.rs +// aux-build:crateresolve1-2.rs +// aux-build:crateresolve1-3.rs + +// normalize-stderr-test: "\.nll/" -> "/" +// normalize-stderr-test: "\\\?\\" -> "" +// normalize-stderr-test: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" + +// NOTE: This test is duplicated from `tests/ui/crate-loading/crateresolve1.rs`. + +extern crate crateresolve1; +//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found + +fn main() {} diff --git a/tests/ui/error-codes/E0464.stderr b/tests/ui/error-codes/E0464.stderr new file mode 100644 index 000000000..574270f94 --- /dev/null +++ b/tests/ui/error-codes/E0464.stderr @@ -0,0 +1,13 @@ +error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found + --> $DIR/E0464.rs:11:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib + = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib + = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0464`. diff --git a/tests/ui/error-codes/E0478.rs b/tests/ui/error-codes/E0478.rs new file mode 100644 index 000000000..b1562dc0a --- /dev/null +++ b/tests/ui/error-codes/E0478.rs @@ -0,0 +1,8 @@ +trait Wedding<'t>: 't { } + +struct Prince<'kiss, 'SnowWhite> { + child: Box + 'SnowWhite>, //~ ERROR E0478 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0478.stderr b/tests/ui/error-codes/E0478.stderr new file mode 100644 index 000000000..ec650085a --- /dev/null +++ b/tests/ui/error-codes/E0478.stderr @@ -0,0 +1,20 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/E0478.rs:4:12 + | +LL | child: Box + 'SnowWhite>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined here + --> $DIR/E0478.rs:3:22 + | +LL | struct Prince<'kiss, 'SnowWhite> { + | ^^^^^^^^^^ +note: but lifetime parameter must outlive the lifetime `'kiss` as defined here + --> $DIR/E0478.rs:3:15 + | +LL | struct Prince<'kiss, 'SnowWhite> { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/error-codes/E0492.rs b/tests/ui/error-codes/E0492.rs new file mode 100644 index 000000000..2c735fcc9 --- /dev/null +++ b/tests/ui/error-codes/E0492.rs @@ -0,0 +1,10 @@ +use std::sync::atomic::AtomicUsize; + +const A: AtomicUsize = AtomicUsize::new(0); +const B: &'static AtomicUsize = &A; //~ ERROR E0492 +static C: &'static AtomicUsize = &A; //~ ERROR E0492 + +const NONE: &'static Option = &None; + +fn main() { +} diff --git a/tests/ui/error-codes/E0492.stderr b/tests/ui/error-codes/E0492.stderr new file mode 100644 index 000000000..557c977e8 --- /dev/null +++ b/tests/ui/error-codes/E0492.stderr @@ -0,0 +1,17 @@ +error[E0492]: constants cannot refer to interior mutable data + --> $DIR/E0492.rs:4:33 + | +LL | const B: &'static AtomicUsize = &A; + | ^^ this borrow of an interior mutable value may end up in the final value + +error[E0492]: statics cannot refer to interior mutable data + --> $DIR/E0492.rs:5:34 + | +LL | static C: &'static AtomicUsize = &A; + | ^^ this borrow of an interior mutable value may end up in the final value + | + = help: to fix this, the value can be extracted to a separate `static` item and then referenced + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0492`. diff --git a/tests/ui/error-codes/E0496.rs b/tests/ui/error-codes/E0496.rs new file mode 100644 index 000000000..b57c9c79e --- /dev/null +++ b/tests/ui/error-codes/E0496.rs @@ -0,0 +1,11 @@ +struct Foo<'a> { + a: &'a i32, +} + +impl<'a> Foo<'a> { + fn f<'a>(x: &'a i32) { //~ ERROR E0496 + } +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0496.stderr b/tests/ui/error-codes/E0496.stderr new file mode 100644 index 000000000..80ca2b1fb --- /dev/null +++ b/tests/ui/error-codes/E0496.stderr @@ -0,0 +1,11 @@ +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/E0496.rs:6:10 + | +LL | impl<'a> Foo<'a> { + | -- first declared here +LL | fn f<'a>(x: &'a i32) { + | ^^ lifetime `'a` already in scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0496`. diff --git a/tests/ui/error-codes/E0499.rs b/tests/ui/error-codes/E0499.rs new file mode 100644 index 000000000..919f97c8a --- /dev/null +++ b/tests/ui/error-codes/E0499.rs @@ -0,0 +1,10 @@ +fn main() { + let mut i = 0; + let mut x = &mut i; + let mut a = &mut i; //~ ERROR E0499 + a.use_mut(); + x.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/error-codes/E0499.stderr b/tests/ui/error-codes/E0499.stderr new file mode 100644 index 000000000..af5a1e186 --- /dev/null +++ b/tests/ui/error-codes/E0499.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `i` as mutable more than once at a time + --> $DIR/E0499.rs:4:17 + | +LL | let mut x = &mut i; + | ------ first mutable borrow occurs here +LL | let mut a = &mut i; + | ^^^^^^ second mutable borrow occurs here +LL | a.use_mut(); +LL | x.use_mut(); + | ----------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/error-codes/E0501.rs b/tests/ui/error-codes/E0501.rs new file mode 100644 index 000000000..3e39d9a63 --- /dev/null +++ b/tests/ui/error-codes/E0501.rs @@ -0,0 +1,24 @@ +fn inside_closure(x: &mut i32) { +} + +fn outside_closure_1(x: &mut i32) { +} + +fn outside_closure_2(x: &i32) { +} + +fn foo(a: &mut i32) { + let bar = || { + inside_closure(a) + }; + outside_closure_1(a); + //~^ ERROR cannot borrow `*a` as mutable because previous closure requires unique access + + outside_closure_2(a); + //~^ ERROR cannot borrow `*a` as immutable because previous closure requires unique access + + drop(bar); +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0501.stderr b/tests/ui/error-codes/E0501.stderr new file mode 100644 index 000000000..53d98d7e1 --- /dev/null +++ b/tests/ui/error-codes/E0501.stderr @@ -0,0 +1,31 @@ +error[E0501]: cannot borrow `*a` as mutable because previous closure requires unique access + --> $DIR/E0501.rs:14:23 + | +LL | let bar = || { + | -- closure construction occurs here +LL | inside_closure(a) + | - first borrow occurs due to use of `a` in closure +LL | }; +LL | outside_closure_1(a); + | ^ second borrow occurs here +... +LL | drop(bar); + | --- first borrow later used here + +error[E0501]: cannot borrow `*a` as immutable because previous closure requires unique access + --> $DIR/E0501.rs:17:23 + | +LL | let bar = || { + | -- closure construction occurs here +LL | inside_closure(a) + | - first borrow occurs due to use of `a` in closure +... +LL | outside_closure_2(a); + | ^ second borrow occurs here +... +LL | drop(bar); + | --- first borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0501`. diff --git a/tests/ui/error-codes/E0502.rs b/tests/ui/error-codes/E0502.rs new file mode 100644 index 000000000..958380ece --- /dev/null +++ b/tests/ui/error-codes/E0502.rs @@ -0,0 +1,12 @@ +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + let ref y = a; + bar(a); //~ ERROR E0502 + y.use_ref(); +} + +fn main() { +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/error-codes/E0502.stderr b/tests/ui/error-codes/E0502.stderr new file mode 100644 index 000000000..94cc89754 --- /dev/null +++ b/tests/ui/error-codes/E0502.stderr @@ -0,0 +1,13 @@ +error[E0502]: cannot borrow `*a` as mutable because it is also borrowed as immutable + --> $DIR/E0502.rs:4:5 + | +LL | let ref y = a; + | ----- immutable borrow occurs here +LL | bar(a); + | ^^^^^^ mutable borrow occurs here +LL | y.use_ref(); + | ----------- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/error-codes/E0503.rs b/tests/ui/error-codes/E0503.rs new file mode 100644 index 000000000..88f5fc1bb --- /dev/null +++ b/tests/ui/error-codes/E0503.rs @@ -0,0 +1,9 @@ +fn main() { + let mut value = 3; + let _borrow = &mut value; + let _sum = value + 1; //~ ERROR E0503 + _borrow.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/error-codes/E0503.stderr b/tests/ui/error-codes/E0503.stderr new file mode 100644 index 000000000..fafe363eb --- /dev/null +++ b/tests/ui/error-codes/E0503.stderr @@ -0,0 +1,13 @@ +error[E0503]: cannot use `value` because it was mutably borrowed + --> $DIR/E0503.rs:4:16 + | +LL | let _borrow = &mut value; + | ---------- borrow of `value` occurs here +LL | let _sum = value + 1; + | ^^^^^ use of borrowed `value` +LL | _borrow.use_mut(); + | ----------------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/error-codes/E0504.rs b/tests/ui/error-codes/E0504.rs new file mode 100644 index 000000000..c2658bef6 --- /dev/null +++ b/tests/ui/error-codes/E0504.rs @@ -0,0 +1,15 @@ +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { //~ ERROR E0505 + println!("child function: {}", fancy_num.num); + }; + + x(); + println!("main function: {}", fancy_ref.num); +} diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr new file mode 100644 index 000000000..e677e8916 --- /dev/null +++ b/tests/ui/error-codes/E0504.stderr @@ -0,0 +1,17 @@ +error[E0505]: cannot move out of `fancy_num` because it is borrowed + --> $DIR/E0504.rs:9:13 + | +LL | let fancy_ref = &fancy_num; + | ---------- borrow of `fancy_num` occurs here +LL | +LL | let x = move || { + | ^^^^^^^ move out of `fancy_num` occurs here +LL | println!("child function: {}", fancy_num.num); + | ------------- move occurs due to use in closure +... +LL | println!("main function: {}", fancy_ref.num); + | ------------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/error-codes/E0505.rs b/tests/ui/error-codes/E0505.rs new file mode 100644 index 000000000..941f5f219 --- /dev/null +++ b/tests/ui/error-codes/E0505.rs @@ -0,0 +1,15 @@ +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(x); //~ ERROR E0505 + _ref_to_val.use_ref(); + } +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr new file mode 100644 index 000000000..bd3f37f54 --- /dev/null +++ b/tests/ui/error-codes/E0505.stderr @@ -0,0 +1,13 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/E0505.rs:9:13 + | +LL | let _ref_to_val: &Value = &x; + | -- borrow of `x` occurs here +LL | eat(x); + | ^ move out of `x` occurs here +LL | _ref_to_val.use_ref(); + | --------------------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/error-codes/E0506.rs b/tests/ui/error-codes/E0506.rs new file mode 100644 index 000000000..062a44a52 --- /dev/null +++ b/tests/ui/error-codes/E0506.rs @@ -0,0 +1,11 @@ +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + fancy_num = FancyNum { num: 6 }; //~ ERROR [E0506] + + println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); +} diff --git a/tests/ui/error-codes/E0506.stderr b/tests/ui/error-codes/E0506.stderr new file mode 100644 index 000000000..d70406b75 --- /dev/null +++ b/tests/ui/error-codes/E0506.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `fancy_num` because it is borrowed + --> $DIR/E0506.rs:8:5 + | +LL | let fancy_ref = &fancy_num; + | ---------- borrow of `fancy_num` occurs here +LL | fancy_num = FancyNum { num: 6 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here +LL | +LL | println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); + | ------------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/error-codes/E0507.rs b/tests/ui/error-codes/E0507.rs new file mode 100644 index 000000000..bae90a44c --- /dev/null +++ b/tests/ui/error-codes/E0507.rs @@ -0,0 +1,13 @@ +use std::cell::RefCell; + +struct TheDarkKnight; + +impl TheDarkKnight { + fn nothing_is_true(self) {} +} + +fn main() { + let x = RefCell::new(TheDarkKnight); + + x.borrow().nothing_is_true(); //~ ERROR E0507 +} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr new file mode 100644 index 000000000..03630f389 --- /dev/null +++ b/tests/ui/error-codes/E0507.stderr @@ -0,0 +1,18 @@ +error[E0507]: cannot move out of dereference of `Ref<'_, TheDarkKnight>` + --> $DIR/E0507.rs:12:5 + | +LL | x.borrow().nothing_is_true(); + | ^^^^^^^^^^^----------------- + | | | + | | value moved due to this method call + | move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait + | +note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, which moves value + --> $DIR/E0507.rs:6:24 + | +LL | fn nothing_is_true(self) {} + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/error-codes/E0508-fail.rs b/tests/ui/error-codes/E0508-fail.rs new file mode 100644 index 000000000..072c3d661 --- /dev/null +++ b/tests/ui/error-codes/E0508-fail.rs @@ -0,0 +1,6 @@ +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + let _value = array[0]; //~ ERROR [E0508] +} diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr new file mode 100644 index 000000000..208ba3072 --- /dev/null +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -0,0 +1,17 @@ +error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array + --> $DIR/E0508-fail.rs:5:18 + | +LL | let _value = array[0]; + | ^^^^^^^^ + | | + | cannot move out of here + | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let _value = &array[0]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/error-codes/E0508.rs b/tests/ui/error-codes/E0508.rs new file mode 100644 index 000000000..072c3d661 --- /dev/null +++ b/tests/ui/error-codes/E0508.rs @@ -0,0 +1,6 @@ +struct NonCopy; + +fn main() { + let array = [NonCopy; 1]; + let _value = array[0]; //~ ERROR [E0508] +} diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr new file mode 100644 index 000000000..df2d3b0d3 --- /dev/null +++ b/tests/ui/error-codes/E0508.stderr @@ -0,0 +1,17 @@ +error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array + --> $DIR/E0508.rs:5:18 + | +LL | let _value = array[0]; + | ^^^^^^^^ + | | + | cannot move out of here + | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let _value = &array[0]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/error-codes/E0509.rs b/tests/ui/error-codes/E0509.rs new file mode 100644 index 000000000..b2665c4cc --- /dev/null +++ b/tests/ui/error-codes/E0509.rs @@ -0,0 +1,18 @@ +struct FancyNum { + num: usize +} + +struct DropStruct { + fancy: FancyNum +} + +impl Drop for DropStruct { + fn drop(&mut self) { + } +} + +fn main() { + let drop_struct = DropStruct{fancy: FancyNum{num: 5}}; + let fancy_field = drop_struct.fancy; //~ ERROR E0509 + println!("Fancy: {}", fancy_field.num); +} diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr new file mode 100644 index 000000000..c00d9142e --- /dev/null +++ b/tests/ui/error-codes/E0509.stderr @@ -0,0 +1,17 @@ +error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait + --> $DIR/E0509.rs:16:23 + | +LL | let fancy_field = drop_struct.fancy; + | ^^^^^^^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let fancy_field = &drop_struct.fancy; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/error-codes/E0511.rs b/tests/ui/error-codes/E0511.rs new file mode 100644 index 000000000..a52f81a6c --- /dev/null +++ b/tests/ui/error-codes/E0511.rs @@ -0,0 +1,11 @@ +// build-fail + +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +fn main() { + unsafe { simd_add(0, 1); } //~ ERROR E0511 +} diff --git a/tests/ui/error-codes/E0511.stderr b/tests/ui/error-codes/E0511.stderr new file mode 100644 index 000000000..d797b10d5 --- /dev/null +++ b/tests/ui/error-codes/E0511.stderr @@ -0,0 +1,9 @@ +error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/E0511.rs:10:14 + | +LL | unsafe { simd_add(0, 1); } + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/error-codes/E0512.rs b/tests/ui/error-codes/E0512.rs new file mode 100644 index 000000000..e70992aee --- /dev/null +++ b/tests/ui/error-codes/E0512.rs @@ -0,0 +1,5 @@ +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } //~ ERROR E0512 +} diff --git a/tests/ui/error-codes/E0512.stderr b/tests/ui/error-codes/E0512.stderr new file mode 100644 index 000000000..3fecce542 --- /dev/null +++ b/tests/ui/error-codes/E0512.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/E0512.rs:4:23 + | +LL | unsafe { takes_u8(::std::mem::transmute(0u16)); } + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u16` (16 bits) + = note: target type: `u8` (8 bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/error-codes/E0516.rs b/tests/ui/error-codes/E0516.rs new file mode 100644 index 000000000..834bb6309 --- /dev/null +++ b/tests/ui/error-codes/E0516.rs @@ -0,0 +1,4 @@ +fn main() { + let x: typeof(92) = 92; //~ ERROR E0516 + //~| reserved keyword +} diff --git a/tests/ui/error-codes/E0516.stderr b/tests/ui/error-codes/E0516.stderr new file mode 100644 index 000000000..5243b7caf --- /dev/null +++ b/tests/ui/error-codes/E0516.stderr @@ -0,0 +1,14 @@ +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/E0516.rs:2:12 + | +LL | let x: typeof(92) = 92; + | ^^^^^^^^^^ reserved keyword + | +help: consider replacing `typeof(...)` with an actual type + | +LL | let x: i32 = 92; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0516`. diff --git a/tests/ui/error-codes/E0517.rs b/tests/ui/error-codes/E0517.rs new file mode 100644 index 000000000..1dcaa2d74 --- /dev/null +++ b/tests/ui/error-codes/E0517.rs @@ -0,0 +1,15 @@ +#[repr(C)] //~ ERROR: E0517 +type Foo = u8; + +#[repr(packed)] //~ ERROR: E0517 +enum Foo2 {Bar, Baz} + +#[repr(u8)] //~ ERROR: E0517 +struct Foo3 {bar: bool, baz: bool} + +#[repr(C)] //~ ERROR: E0517 +impl Foo3 { +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0517.stderr b/tests/ui/error-codes/E0517.stderr new file mode 100644 index 000000000..2f90d4d0b --- /dev/null +++ b/tests/ui/error-codes/E0517.stderr @@ -0,0 +1,36 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/E0517.rs:1:8 + | +LL | #[repr(C)] + | ^ +LL | type Foo = u8; + | -------------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/E0517.rs:4:8 + | +LL | #[repr(packed)] + | ^^^^^^ +LL | enum Foo2 {Bar, Baz} + | -------------------- not a struct or union + +error[E0517]: attribute should be applied to an enum + --> $DIR/E0517.rs:7:8 + | +LL | #[repr(u8)] + | ^^ +LL | struct Foo3 {bar: bool, baz: bool} + | ---------------------------------- not an enum + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/E0517.rs:10:8 + | +LL | #[repr(C)] + | ^ +LL | / impl Foo3 { +LL | | } + | |_- not a struct, enum, or union + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/error-codes/E0518.rs b/tests/ui/error-codes/E0518.rs new file mode 100644 index 000000000..9c99702ad --- /dev/null +++ b/tests/ui/error-codes/E0518.rs @@ -0,0 +1,9 @@ +#[inline(always)] //~ ERROR: E0518 +struct Foo; + +#[inline(never)] //~ ERROR: E0518 +impl Foo { +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0518.stderr b/tests/ui/error-codes/E0518.stderr new file mode 100644 index 000000000..561446f81 --- /dev/null +++ b/tests/ui/error-codes/E0518.stderr @@ -0,0 +1,20 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/E0518.rs:1:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ +LL | struct Foo; + | ----------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/E0518.rs:4:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ +LL | / impl Foo { +LL | | } + | |_- not a function or closure + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/error-codes/E0519.rs b/tests/ui/error-codes/E0519.rs new file mode 100644 index 000000000..269ffd632 --- /dev/null +++ b/tests/ui/error-codes/E0519.rs @@ -0,0 +1,8 @@ +// no need to create a new aux file, we can use an existing. +// aux-build: crateresolve1-1.rs + +// set same metadata as `crateresolve1` +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +extern crate crateresolve1; //~ ERROR E0519 diff --git a/tests/ui/error-codes/E0519.stderr b/tests/ui/error-codes/E0519.stderr new file mode 100644 index 000000000..e24fc4aaa --- /dev/null +++ b/tests/ui/error-codes/E0519.stderr @@ -0,0 +1,9 @@ +error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `crateresolve1` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. + --> $DIR/E0519.rs:8:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0519`. diff --git a/tests/ui/error-codes/E0520.rs b/tests/ui/error-codes/E0520.rs new file mode 100644 index 000000000..ead78b7ff --- /dev/null +++ b/tests/ui/error-codes/E0520.rs @@ -0,0 +1,22 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait SpaceLlama { + fn fly(&self); +} + +impl SpaceLlama for T { + default fn fly(&self) {} +} + +impl SpaceLlama for T { + fn fly(&self) {} +} + +impl SpaceLlama for i32 { + default fn fly(&self) {} + //~^ ERROR E0520 +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0520.stderr b/tests/ui/error-codes/E0520.stderr new file mode 100644 index 000000000..12ecead13 --- /dev/null +++ b/tests/ui/error-codes/E0520.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/E0520.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/E0520.rs:17:5 + | +LL | impl SpaceLlama for T { + | ------------------------------- parent `impl` is here +... +LL | default fn fly(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly` + | + = note: to specialize, `fly` in the parent `impl` must be marked `default` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/error-codes/E0522.rs b/tests/ui/error-codes/E0522.rs new file mode 100644 index 000000000..1414e8240 --- /dev/null +++ b/tests/ui/error-codes/E0522.rs @@ -0,0 +1,9 @@ +#![feature(lang_items)] + +#[lang = "cookie"] +fn cookie() -> ! { +//~^^ ERROR definition of an unknown language item: `cookie` [E0522] + loop {} +} + +fn main() {} diff --git a/tests/ui/error-codes/E0522.stderr b/tests/ui/error-codes/E0522.stderr new file mode 100644 index 000000000..0a8a41598 --- /dev/null +++ b/tests/ui/error-codes/E0522.stderr @@ -0,0 +1,9 @@ +error[E0522]: definition of an unknown language item: `cookie` + --> $DIR/E0522.rs:3:1 + | +LL | #[lang = "cookie"] + | ^^^^^^^^^^^^^^^^^^ definition of unknown language item `cookie` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0522`. diff --git a/tests/ui/error-codes/E0527.rs b/tests/ui/error-codes/E0527.rs new file mode 100644 index 000000000..af055ff26 --- /dev/null +++ b/tests/ui/error-codes/E0527.rs @@ -0,0 +1,9 @@ +fn main() { + let r = &[1, 2, 3, 4]; + match r { + &[a, b] => { + //~^ ERROR E0527 + println!("a={}, b={}", a, b); + } + } +} diff --git a/tests/ui/error-codes/E0527.stderr b/tests/ui/error-codes/E0527.stderr new file mode 100644 index 000000000..a2e6288b2 --- /dev/null +++ b/tests/ui/error-codes/E0527.stderr @@ -0,0 +1,9 @@ +error[E0527]: pattern requires 2 elements but array has 4 + --> $DIR/E0527.rs:4:10 + | +LL | &[a, b] => { + | ^^^^^^ expected 4 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/error-codes/E0528.rs b/tests/ui/error-codes/E0528.rs new file mode 100644 index 000000000..0a337c961 --- /dev/null +++ b/tests/ui/error-codes/E0528.rs @@ -0,0 +1,8 @@ +fn main() { + let r = &[1, 2]; + match r { + &[a, b, c, rest @ ..] => { + //~^ ERROR E0528 + } + } +} diff --git a/tests/ui/error-codes/E0528.stderr b/tests/ui/error-codes/E0528.stderr new file mode 100644 index 000000000..21615f954 --- /dev/null +++ b/tests/ui/error-codes/E0528.stderr @@ -0,0 +1,9 @@ +error[E0528]: pattern requires at least 3 elements but array has 2 + --> $DIR/E0528.rs:4:10 + | +LL | &[a, b, c, rest @ ..] => { + | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0528`. diff --git a/tests/ui/error-codes/E0529.rs b/tests/ui/error-codes/E0529.rs new file mode 100644 index 000000000..a82bc9ebc --- /dev/null +++ b/tests/ui/error-codes/E0529.rs @@ -0,0 +1,8 @@ +fn main() { + let r: f32 = 1.0; + match r { + [a, b] => { + //~^ ERROR E0529 + } + } +} diff --git a/tests/ui/error-codes/E0529.stderr b/tests/ui/error-codes/E0529.stderr new file mode 100644 index 000000000..96b22bb22 --- /dev/null +++ b/tests/ui/error-codes/E0529.stderr @@ -0,0 +1,9 @@ +error[E0529]: expected an array or slice, found `f32` + --> $DIR/E0529.rs:4:9 + | +LL | [a, b] => { + | ^^^^^^ pattern cannot match with input type `f32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/error-codes/E0530.rs b/tests/ui/error-codes/E0530.rs new file mode 100644 index 000000000..5bc40964f --- /dev/null +++ b/tests/ui/error-codes/E0530.rs @@ -0,0 +1,8 @@ +fn main() { + static TEST: i32 = 0; + + let r: (i32, i32) = (0, 0); + match r { + TEST => {} //~ ERROR E0530 + } +} diff --git a/tests/ui/error-codes/E0530.stderr b/tests/ui/error-codes/E0530.stderr new file mode 100644 index 000000000..c31214413 --- /dev/null +++ b/tests/ui/error-codes/E0530.stderr @@ -0,0 +1,12 @@ +error[E0530]: match bindings cannot shadow statics + --> $DIR/E0530.rs:6:9 + | +LL | static TEST: i32 = 0; + | --------------------- the static `TEST` is defined here +... +LL | TEST => {} + | ^^^^ cannot be named the same as a static + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/error-codes/E0532.rs b/tests/ui/error-codes/E0532.rs new file mode 100644 index 000000000..486da0e02 --- /dev/null +++ b/tests/ui/error-codes/E0532.rs @@ -0,0 +1,14 @@ +fn main() { + let value = 1; + + match SomeStruct(value) { + StructConst1(_) => { }, + //~^ ERROR expected tuple struct or tuple variant, found constant `StructConst1` + _ => { }, + } + + struct SomeStruct(u8); + + const StructConst1 : SomeStruct = SomeStruct(1); + const StructConst2 : SomeStruct = SomeStruct(2); +} diff --git a/tests/ui/error-codes/E0532.stderr b/tests/ui/error-codes/E0532.stderr new file mode 100644 index 000000000..eeccadccc --- /dev/null +++ b/tests/ui/error-codes/E0532.stderr @@ -0,0 +1,9 @@ +error[E0532]: expected tuple struct or tuple variant, found constant `StructConst1` + --> $DIR/E0532.rs:5:9 + | +LL | StructConst1(_) => { }, + | ^^^^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/error-codes/E0534.rs b/tests/ui/error-codes/E0534.rs new file mode 100644 index 000000000..a42424994 --- /dev/null +++ b/tests/ui/error-codes/E0534.rs @@ -0,0 +1,6 @@ +#[inline()] //~ ERROR E0534 +pub fn something() {} + +fn main() { + something(); +} diff --git a/tests/ui/error-codes/E0534.stderr b/tests/ui/error-codes/E0534.stderr new file mode 100644 index 000000000..23f9cd7ce --- /dev/null +++ b/tests/ui/error-codes/E0534.stderr @@ -0,0 +1,9 @@ +error[E0534]: expected one argument + --> $DIR/E0534.rs:1:1 + | +LL | #[inline()] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0534`. diff --git a/tests/ui/error-codes/E0559.rs b/tests/ui/error-codes/E0559.rs new file mode 100644 index 000000000..c6d04ff14 --- /dev/null +++ b/tests/ui/error-codes/E0559.rs @@ -0,0 +1,8 @@ +enum Field { + Fool { x: u32 }, +} + +fn main() { + let s = Field::Fool { joke: 0 }; + //~^ ERROR E0559 +} diff --git a/tests/ui/error-codes/E0559.stderr b/tests/ui/error-codes/E0559.stderr new file mode 100644 index 000000000..63ee1cd78 --- /dev/null +++ b/tests/ui/error-codes/E0559.stderr @@ -0,0 +1,11 @@ +error[E0559]: variant `Field::Fool` has no field named `joke` + --> $DIR/E0559.rs:6:27 + | +LL | let s = Field::Fool { joke: 0 }; + | ^^^^ `Field::Fool` does not have this field + | + = note: available fields are: `x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0559`. diff --git a/tests/ui/error-codes/E0560.rs b/tests/ui/error-codes/E0560.rs new file mode 100644 index 000000000..1d60f8948 --- /dev/null +++ b/tests/ui/error-codes/E0560.rs @@ -0,0 +1,8 @@ +struct Simba { + mother: u32, +} + +fn main() { + let s = Simba { mother: 1, father: 0 }; + //~^ ERROR E0560 +} diff --git a/tests/ui/error-codes/E0560.stderr b/tests/ui/error-codes/E0560.stderr new file mode 100644 index 000000000..6b634f185 --- /dev/null +++ b/tests/ui/error-codes/E0560.stderr @@ -0,0 +1,11 @@ +error[E0560]: struct `Simba` has no field named `father` + --> $DIR/E0560.rs:6:32 + | +LL | let s = Simba { mother: 1, father: 0 }; + | ^^^^^^ `Simba` does not have this field + | + = note: available fields are: `mother` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/error-codes/E0565-1.rs b/tests/ui/error-codes/E0565-1.rs new file mode 100644 index 000000000..30fba0191 --- /dev/null +++ b/tests/ui/error-codes/E0565-1.rs @@ -0,0 +1,5 @@ +// deprecated doesn't currently support literals +#[deprecated("since")] //~ ERROR E0565 +fn f() { } + +fn main() { } diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr new file mode 100644 index 000000000..1283a9c5e --- /dev/null +++ b/tests/ui/error-codes/E0565-1.stderr @@ -0,0 +1,9 @@ +error[E0565]: item in `deprecated` must be a key/value pair + --> $DIR/E0565-1.rs:2:14 + | +LL | #[deprecated("since")] + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/error-codes/E0565-2.rs b/tests/ui/error-codes/E0565-2.rs new file mode 100644 index 000000000..0319ecb11 --- /dev/null +++ b/tests/ui/error-codes/E0565-2.rs @@ -0,0 +1,5 @@ +// repr currently doesn't support literals +#[deprecated(since = b"1.29", note = "hi")] //~ ERROR E0565 +struct A { } + +fn main() { } diff --git a/tests/ui/error-codes/E0565-2.stderr b/tests/ui/error-codes/E0565-2.stderr new file mode 100644 index 000000000..097871bd3 --- /dev/null +++ b/tests/ui/error-codes/E0565-2.stderr @@ -0,0 +1,11 @@ +error[E0565]: literal in `deprecated` value must be a string + --> $DIR/E0565-2.rs:2:22 + | +LL | #[deprecated(since = b"1.29", note = "hi")] + | -^^^^^^ + | | + | help: consider removing the prefix + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/error-codes/E0565.rs b/tests/ui/error-codes/E0565.rs new file mode 100644 index 000000000..df76f6b13 --- /dev/null +++ b/tests/ui/error-codes/E0565.rs @@ -0,0 +1,5 @@ +// repr currently doesn't support literals +#[repr("C")] //~ ERROR E0565 +struct A {} + +fn main() {} diff --git a/tests/ui/error-codes/E0565.stderr b/tests/ui/error-codes/E0565.stderr new file mode 100644 index 000000000..6ed90c0ae --- /dev/null +++ b/tests/ui/error-codes/E0565.stderr @@ -0,0 +1,9 @@ +error[E0565]: meta item in `repr` must be an identifier + --> $DIR/E0565.rs:2:8 + | +LL | #[repr("C")] + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/error-codes/E0572.rs b/tests/ui/error-codes/E0572.rs new file mode 100644 index 000000000..cb842c933 --- /dev/null +++ b/tests/ui/error-codes/E0572.rs @@ -0,0 +1,3 @@ +const FOO: u32 = return 0; //~ ERROR E0572 + +fn main() {} diff --git a/tests/ui/error-codes/E0572.stderr b/tests/ui/error-codes/E0572.stderr new file mode 100644 index 000000000..36619f8de --- /dev/null +++ b/tests/ui/error-codes/E0572.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/E0572.rs:1:18 + | +LL | const FOO: u32 = return 0; + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/error-codes/E0582.rs b/tests/ui/error-codes/E0582.rs new file mode 100644 index 000000000..ff25012d0 --- /dev/null +++ b/tests/ui/error-codes/E0582.rs @@ -0,0 +1,42 @@ +// This test was derived from the wasm and parsell crates. They +// stopped compiling when #32330 is fixed. + +#![allow(dead_code, unused_variables)] + +use std::str::Chars; + +pub trait HasOutput { + type Output; +} + +#[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)] +pub enum Token<'a> { + Begin(&'a str) +} + +fn mk_unexpected_char_err<'a>() -> Option<&'a i32> { + unimplemented!() +} + +fn foo<'a>(data: &mut Chars<'a>) { + bar(mk_unexpected_char_err) +} + +fn bar(t: F) + // No type can satisfy this requirement, since `'a` does not + // appear in any of the input types: + where F: for<'a> Fn() -> Option<&'a i32> + //~^ ERROR E0582 +{ +} + +fn baz(t: F) + // No type can satisfy this requirement, since `'a` does not + // appear in any of the input types: + where F: for<'a> Iterator + //~^ ERROR E0582 +{ +} + +fn main() { +} diff --git a/tests/ui/error-codes/E0582.stderr b/tests/ui/error-codes/E0582.stderr new file mode 100644 index 000000000..81a2f0046 --- /dev/null +++ b/tests/ui/error-codes/E0582.stderr @@ -0,0 +1,15 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/E0582.rs:28:30 + | +LL | where F: for<'a> Fn() -> Option<&'a i32> + | ^^^^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Item` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/E0582.rs:36:31 + | +LL | where F: for<'a> Iterator + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/error-codes/E0583.rs b/tests/ui/error-codes/E0583.rs new file mode 100644 index 000000000..969de79c0 --- /dev/null +++ b/tests/ui/error-codes/E0583.rs @@ -0,0 +1,4 @@ +mod module_that_doesnt_exist; //~ ERROR E0583 + +fn main() { +} diff --git a/tests/ui/error-codes/E0583.stderr b/tests/ui/error-codes/E0583.stderr new file mode 100644 index 000000000..c7bbbf114 --- /dev/null +++ b/tests/ui/error-codes/E0583.stderr @@ -0,0 +1,11 @@ +error[E0583]: file not found for module `module_that_doesnt_exist` + --> $DIR/E0583.rs:1:1 + | +LL | mod module_that_doesnt_exist; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs" or "$DIR/module_that_doesnt_exist/mod.rs" + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/error-codes/E0585.rs b/tests/ui/error-codes/E0585.rs new file mode 100644 index 000000000..890b77b53 --- /dev/null +++ b/tests/ui/error-codes/E0585.rs @@ -0,0 +1,4 @@ +fn main() { + /// Hello! I'm useless... + //~^ ERROR E0585 +} diff --git a/tests/ui/error-codes/E0585.stderr b/tests/ui/error-codes/E0585.stderr new file mode 100644 index 000000000..53c82fb41 --- /dev/null +++ b/tests/ui/error-codes/E0585.stderr @@ -0,0 +1,11 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/E0585.rs:2:5 + | +LL | /// Hello! I'm useless... + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/error-codes/E0586.rs b/tests/ui/error-codes/E0586.rs new file mode 100644 index 000000000..2ab8a2959 --- /dev/null +++ b/tests/ui/error-codes/E0586.rs @@ -0,0 +1,4 @@ +fn main() { + let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1..=]; //~ ERROR E0586 +} diff --git a/tests/ui/error-codes/E0586.stderr b/tests/ui/error-codes/E0586.stderr new file mode 100644 index 000000000..0bbf9a608 --- /dev/null +++ b/tests/ui/error-codes/E0586.stderr @@ -0,0 +1,11 @@ +error[E0586]: inclusive range with no end + --> $DIR/E0586.rs:3:19 + | +LL | let x = &tmp[1..=]; + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/error-codes/E0594.rs b/tests/ui/error-codes/E0594.rs new file mode 100644 index 000000000..8b0cae7e1 --- /dev/null +++ b/tests/ui/error-codes/E0594.rs @@ -0,0 +1,5 @@ +static NUM: i32 = 18; + +fn main() { + NUM = 20; //~ ERROR cannot assign to immutable static item `NUM` +} diff --git a/tests/ui/error-codes/E0594.stderr b/tests/ui/error-codes/E0594.stderr new file mode 100644 index 000000000..f4d96f4e4 --- /dev/null +++ b/tests/ui/error-codes/E0594.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `NUM` + --> $DIR/E0594.rs:4:5 + | +LL | NUM = 20; + | ^^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/error-codes/E0596.rs b/tests/ui/error-codes/E0596.rs new file mode 100644 index 000000000..9e2f5ee76 --- /dev/null +++ b/tests/ui/error-codes/E0596.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 1; + let y = &mut x; //~ ERROR [E0596] +} diff --git a/tests/ui/error-codes/E0596.stderr b/tests/ui/error-codes/E0596.stderr new file mode 100644 index 000000000..3f9aebcc8 --- /dev/null +++ b/tests/ui/error-codes/E0596.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/E0596.rs:3:13 + | +LL | let y = &mut x; + | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 1; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/error-codes/E0597.rs b/tests/ui/error-codes/E0597.rs new file mode 100644 index 000000000..7217e3512 --- /dev/null +++ b/tests/ui/error-codes/E0597.rs @@ -0,0 +1,12 @@ +struct Foo<'a> { + x: Option<&'a u32>, +} + +fn main() { + let mut x = Foo { x: None }; + let y = 0; + x.x = Some(&y); + //~^ `y` does not live long enough [E0597] +} + +impl<'a> Drop for Foo<'a> { fn drop(&mut self) { } } diff --git a/tests/ui/error-codes/E0597.stderr b/tests/ui/error-codes/E0597.stderr new file mode 100644 index 000000000..b4a1180ad --- /dev/null +++ b/tests/ui/error-codes/E0597.stderr @@ -0,0 +1,17 @@ +error[E0597]: `y` does not live long enough + --> $DIR/E0597.rs:8:16 + | +LL | x.x = Some(&y); + | ^^ borrowed value does not live long enough +LL | +LL | } + | - + | | + | `y` dropped here while still borrowed + | borrow might be used here, when `x` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/error-codes/E0599.rs b/tests/ui/error-codes/E0599.rs new file mode 100644 index 000000000..a2d7bb2dc --- /dev/null +++ b/tests/ui/error-codes/E0599.rs @@ -0,0 +1,5 @@ +struct Foo; + +fn main() { + || if let Foo::NotEvenReal() = Foo {}; //~ ERROR E0599 +} diff --git a/tests/ui/error-codes/E0599.stderr b/tests/ui/error-codes/E0599.stderr new file mode 100644 index 000000000..a1fb58f48 --- /dev/null +++ b/tests/ui/error-codes/E0599.stderr @@ -0,0 +1,12 @@ +error[E0599]: no associated item named `NotEvenReal` found for struct `Foo` in the current scope + --> $DIR/E0599.rs:4:20 + | +LL | struct Foo; + | ---------- associated item `NotEvenReal` not found for this struct +... +LL | || if let Foo::NotEvenReal() = Foo {}; + | ^^^^^^^^^^^ associated item not found in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/error-codes/E0600.rs b/tests/ui/error-codes/E0600.rs new file mode 100644 index 000000000..7731d8619 --- /dev/null +++ b/tests/ui/error-codes/E0600.rs @@ -0,0 +1,3 @@ +fn main() { + !"a"; //~ ERROR E0600 +} diff --git a/tests/ui/error-codes/E0600.stderr b/tests/ui/error-codes/E0600.stderr new file mode 100644 index 000000000..95ac4510c --- /dev/null +++ b/tests/ui/error-codes/E0600.stderr @@ -0,0 +1,9 @@ +error[E0600]: cannot apply unary operator `!` to type `&'static str` + --> $DIR/E0600.rs:2:5 + | +LL | !"a"; + | ^^^^ cannot apply unary operator `!` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/error-codes/E0601.rs b/tests/ui/error-codes/E0601.rs new file mode 100644 index 000000000..4380ddeac --- /dev/null +++ b/tests/ui/error-codes/E0601.rs @@ -0,0 +1 @@ +//~ ERROR `main` function not found diff --git a/tests/ui/error-codes/E0601.stderr b/tests/ui/error-codes/E0601.stderr new file mode 100644 index 000000000..a687f5756 --- /dev/null +++ b/tests/ui/error-codes/E0601.stderr @@ -0,0 +1,9 @@ +error[E0601]: `main` function not found in crate `E0601` + --> $DIR/E0601.rs:1:37 + | +LL | + | ^ consider adding a `main` function to `$DIR/E0601.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/error-codes/E0602.rs b/tests/ui/error-codes/E0602.rs new file mode 100644 index 000000000..8fadce526 --- /dev/null +++ b/tests/ui/error-codes/E0602.rs @@ -0,0 +1,6 @@ +// compile-flags:-D bogus + +// error-pattern:E0602 +// error-pattern:requested on the command line with `-D bogus` + +fn main() {} diff --git a/tests/ui/error-codes/E0602.stderr b/tests/ui/error-codes/E0602.stderr new file mode 100644 index 000000000..2b3722633 --- /dev/null +++ b/tests/ui/error-codes/E0602.stderr @@ -0,0 +1,11 @@ +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/error-codes/E0603.rs b/tests/ui/error-codes/E0603.rs new file mode 100644 index 000000000..24a9ba887 --- /dev/null +++ b/tests/ui/error-codes/E0603.rs @@ -0,0 +1,7 @@ +mod SomeModule { + const PRIVATE: u32 = 0x_a_bad_1dea_u32; +} + +fn main() { + SomeModule::PRIVATE; //~ ERROR E0603 +} diff --git a/tests/ui/error-codes/E0603.stderr b/tests/ui/error-codes/E0603.stderr new file mode 100644 index 000000000..ee902584f --- /dev/null +++ b/tests/ui/error-codes/E0603.stderr @@ -0,0 +1,15 @@ +error[E0603]: constant `PRIVATE` is private + --> $DIR/E0603.rs:6:17 + | +LL | SomeModule::PRIVATE; + | ^^^^^^^ private constant + | +note: the constant `PRIVATE` is defined here + --> $DIR/E0603.rs:2:5 + | +LL | const PRIVATE: u32 = 0x_a_bad_1dea_u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/error-codes/E0604.rs b/tests/ui/error-codes/E0604.rs new file mode 100644 index 000000000..b9c0d1f92 --- /dev/null +++ b/tests/ui/error-codes/E0604.rs @@ -0,0 +1,3 @@ +fn main() { + 1u32 as char; //~ ERROR E0604 +} diff --git a/tests/ui/error-codes/E0604.stderr b/tests/ui/error-codes/E0604.stderr new file mode 100644 index 000000000..68da03928 --- /dev/null +++ b/tests/ui/error-codes/E0604.stderr @@ -0,0 +1,12 @@ +error[E0604]: only `u8` can be cast as `char`, not `u32` + --> $DIR/E0604.rs:2:5 + | +LL | 1u32 as char; + | ^^^^^^^^^^^^ + | | + | invalid cast + | help: try `char::from_u32` instead: `char::from_u32(1u32)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0604`. diff --git a/tests/ui/error-codes/E0605.rs b/tests/ui/error-codes/E0605.rs new file mode 100644 index 000000000..cfbf1aa2b --- /dev/null +++ b/tests/ui/error-codes/E0605.rs @@ -0,0 +1,7 @@ +fn main() { + let x = 0u8; + x as Vec; //~ ERROR E0605 + + let v = std::ptr::null::(); + v as &u8; //~ ERROR E0605 +} diff --git a/tests/ui/error-codes/E0605.stderr b/tests/ui/error-codes/E0605.stderr new file mode 100644 index 000000000..e385b3394 --- /dev/null +++ b/tests/ui/error-codes/E0605.stderr @@ -0,0 +1,21 @@ +error[E0605]: non-primitive cast: `u8` as `Vec` + --> $DIR/E0605.rs:3:5 + | +LL | x as Vec; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `*const u8` as `&u8` + --> $DIR/E0605.rs:6:5 + | +LL | v as &u8; + | ^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL - v as &u8; +LL + &*v; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/error-codes/E0606.rs b/tests/ui/error-codes/E0606.rs new file mode 100644 index 000000000..6f6c65138 --- /dev/null +++ b/tests/ui/error-codes/E0606.rs @@ -0,0 +1,4 @@ +fn main() { + let x = &(&0u8 as u8); //~ ERROR E0606 + x as u8; //~ casting `&u8` as `u8` is invalid [E0606] +} diff --git a/tests/ui/error-codes/E0606.stderr b/tests/ui/error-codes/E0606.stderr new file mode 100644 index 000000000..2492eb299 --- /dev/null +++ b/tests/ui/error-codes/E0606.stderr @@ -0,0 +1,26 @@ +error[E0606]: casting `&u8` as `u8` is invalid + --> $DIR/E0606.rs:2:14 + | +LL | let x = &(&0u8 as u8); + | ^^^^^^^^^^^^ + | +help: remove the unneeded borrow + | +LL - let x = &(&0u8 as u8); +LL + let x = &(0u8 as u8); + | + +error[E0606]: casting `&u8` as `u8` is invalid + --> $DIR/E0606.rs:3:5 + | +LL | x as u8; + | ^^^^^^^ + | +help: dereference the expression + | +LL | *x as u8; + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/error-codes/E0607.rs b/tests/ui/error-codes/E0607.rs new file mode 100644 index 000000000..65001c471 --- /dev/null +++ b/tests/ui/error-codes/E0607.rs @@ -0,0 +1,4 @@ +fn main() { + let v = core::ptr::null::(); + v as *const [u8]; //~ ERROR E0607 +} diff --git a/tests/ui/error-codes/E0607.stderr b/tests/ui/error-codes/E0607.stderr new file mode 100644 index 000000000..a0fe02c1c --- /dev/null +++ b/tests/ui/error-codes/E0607.stderr @@ -0,0 +1,9 @@ +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` + --> $DIR/E0607.rs:3:5 + | +LL | v as *const [u8]; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0607`. diff --git a/tests/ui/error-codes/E0608.rs b/tests/ui/error-codes/E0608.rs new file mode 100644 index 000000000..1e342d668 --- /dev/null +++ b/tests/ui/error-codes/E0608.rs @@ -0,0 +1,3 @@ +fn main() { + 0u8[2]; //~ ERROR E0608 +} diff --git a/tests/ui/error-codes/E0608.stderr b/tests/ui/error-codes/E0608.stderr new file mode 100644 index 000000000..3aec50993 --- /dev/null +++ b/tests/ui/error-codes/E0608.stderr @@ -0,0 +1,9 @@ +error[E0608]: cannot index into a value of type `u8` + --> $DIR/E0608.rs:2:5 + | +LL | 0u8[2]; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/error-codes/E0609.rs b/tests/ui/error-codes/E0609.rs new file mode 100644 index 000000000..e3a97f2fb --- /dev/null +++ b/tests/ui/error-codes/E0609.rs @@ -0,0 +1,12 @@ +struct Foo { + x: u32, +} +struct Bar; + +fn main() { + let x = Foo { x: 0 }; + let _ = x.foo; //~ ERROR E0609 + + let y = Bar; + y.1; //~ ERROR E0609 +} diff --git a/tests/ui/error-codes/E0609.stderr b/tests/ui/error-codes/E0609.stderr new file mode 100644 index 000000000..797e95d02 --- /dev/null +++ b/tests/ui/error-codes/E0609.stderr @@ -0,0 +1,17 @@ +error[E0609]: no field `foo` on type `Foo` + --> $DIR/E0609.rs:8:15 + | +LL | let _ = x.foo; + | ^^^ unknown field + | + = note: available fields are: `x` + +error[E0609]: no field `1` on type `Bar` + --> $DIR/E0609.rs:11:7 + | +LL | y.1; + | ^ unknown field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/error-codes/E0610.rs b/tests/ui/error-codes/E0610.rs new file mode 100644 index 000000000..de246f371 --- /dev/null +++ b/tests/ui/error-codes/E0610.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 0; + let _ = x.foo; //~ ERROR E0610 +} diff --git a/tests/ui/error-codes/E0610.stderr b/tests/ui/error-codes/E0610.stderr new file mode 100644 index 000000000..a2966eea4 --- /dev/null +++ b/tests/ui/error-codes/E0610.stderr @@ -0,0 +1,9 @@ +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/E0610.rs:3:15 + | +LL | let _ = x.foo; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/error-codes/E0614.rs b/tests/ui/error-codes/E0614.rs new file mode 100644 index 000000000..6b4817b69 --- /dev/null +++ b/tests/ui/error-codes/E0614.rs @@ -0,0 +1,4 @@ +fn main() { + let y = 0u32; + *y; //~ ERROR E0614 +} diff --git a/tests/ui/error-codes/E0614.stderr b/tests/ui/error-codes/E0614.stderr new file mode 100644 index 000000000..598117c2b --- /dev/null +++ b/tests/ui/error-codes/E0614.stderr @@ -0,0 +1,9 @@ +error[E0614]: type `u32` cannot be dereferenced + --> $DIR/E0614.rs:3:5 + | +LL | *y; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/error-codes/E0615.rs b/tests/ui/error-codes/E0615.rs new file mode 100644 index 000000000..d04e4d5f7 --- /dev/null +++ b/tests/ui/error-codes/E0615.rs @@ -0,0 +1,12 @@ +struct Foo { + x: u32, +} + +impl Foo { + fn method(&self) {} +} + +fn main() { + let f = Foo { x: 0 }; + f.method; //~ ERROR E0615 +} diff --git a/tests/ui/error-codes/E0615.stderr b/tests/ui/error-codes/E0615.stderr new file mode 100644 index 000000000..c12e1a3a6 --- /dev/null +++ b/tests/ui/error-codes/E0615.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `method` on type `Foo` + --> $DIR/E0615.rs:11:7 + | +LL | f.method; + | ^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | f.method(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/error-codes/E0616.rs b/tests/ui/error-codes/E0616.rs new file mode 100644 index 000000000..98f87a83b --- /dev/null +++ b/tests/ui/error-codes/E0616.rs @@ -0,0 +1,14 @@ +mod a { + pub struct Foo { + x: u32, + } + + impl Foo { + pub fn new() -> Foo { Foo { x: 0 } } + } +} + +fn main() { + let f = a::Foo::new(); + f.x; //~ ERROR E0616 +} diff --git a/tests/ui/error-codes/E0616.stderr b/tests/ui/error-codes/E0616.stderr new file mode 100644 index 000000000..da349ed2f --- /dev/null +++ b/tests/ui/error-codes/E0616.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `x` of struct `Foo` is private + --> $DIR/E0616.rs:13:7 + | +LL | f.x; + | ^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/error-codes/E0617.rs b/tests/ui/error-codes/E0617.rs new file mode 100644 index 000000000..b71ba0ed8 --- /dev/null +++ b/tests/ui/error-codes/E0617.rs @@ -0,0 +1,26 @@ +extern "C" { + fn printf(c: *const i8, ...); +} + +fn main() { + unsafe { + printf(::std::ptr::null(), 0f32); + //~^ ERROR can't pass `f32` to variadic function + //~| HELP cast the value to `c_double` + printf(::std::ptr::null(), 0i8); + //~^ ERROR can't pass `i8` to variadic function + //~| HELP cast the value to `c_int` + printf(::std::ptr::null(), 0i16); + //~^ ERROR can't pass `i16` to variadic function + //~| HELP cast the value to `c_int` + printf(::std::ptr::null(), 0u8); + //~^ ERROR can't pass `u8` to variadic function + //~| HELP cast the value to `c_uint` + printf(::std::ptr::null(), 0u16); + //~^ ERROR can't pass `u16` to variadic function + //~| HELP cast the value to `c_uint` + printf(::std::ptr::null(), printf); + //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function + //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` + } +} diff --git a/tests/ui/error-codes/E0617.stderr b/tests/ui/error-codes/E0617.stderr new file mode 100644 index 000000000..ea91ad082 --- /dev/null +++ b/tests/ui/error-codes/E0617.stderr @@ -0,0 +1,44 @@ +error[E0617]: can't pass `f32` to variadic function + --> $DIR/E0617.rs:7:36 + | +LL | printf(::std::ptr::null(), 0f32); + | ^^^^ help: cast the value to `c_double`: `0f32 as c_double` + +error[E0617]: can't pass `i8` to variadic function + --> $DIR/E0617.rs:10:36 + | +LL | printf(::std::ptr::null(), 0i8); + | ^^^ help: cast the value to `c_int`: `0i8 as c_int` + +error[E0617]: can't pass `i16` to variadic function + --> $DIR/E0617.rs:13:36 + | +LL | printf(::std::ptr::null(), 0i16); + | ^^^^ help: cast the value to `c_int`: `0i16 as c_int` + +error[E0617]: can't pass `u8` to variadic function + --> $DIR/E0617.rs:16:36 + | +LL | printf(::std::ptr::null(), 0u8); + | ^^^ help: cast the value to `c_uint`: `0u8 as c_uint` + +error[E0617]: can't pass `u16` to variadic function + --> $DIR/E0617.rs:19:36 + | +LL | printf(::std::ptr::null(), 0u16); + | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` + +error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function + --> $DIR/E0617.rs:22:36 + | +LL | printf(::std::ptr::null(), printf); + | ^^^^^^ + | +help: cast the value to `unsafe extern "C" fn(*const i8, ...)` + | +LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0617`. diff --git a/tests/ui/error-codes/E0618.rs b/tests/ui/error-codes/E0618.rs new file mode 100644 index 000000000..2616e7134 --- /dev/null +++ b/tests/ui/error-codes/E0618.rs @@ -0,0 +1,11 @@ +enum X { + Entry, +} + +fn main() { + X::Entry(); + //~^ ERROR expected function, found enum variant `X::Entry` [E0618] + let x = 0i32; + x(); + //~^ ERROR expected function, found `i32` [E0618] +} diff --git a/tests/ui/error-codes/E0618.stderr b/tests/ui/error-codes/E0618.stderr new file mode 100644 index 000000000..793ec02a8 --- /dev/null +++ b/tests/ui/error-codes/E0618.stderr @@ -0,0 +1,30 @@ +error[E0618]: expected function, found enum variant `X::Entry` + --> $DIR/E0618.rs:6:5 + | +LL | Entry, + | ----- enum variant `X::Entry` defined here +... +LL | X::Entry(); + | ^^^^^^^^-- + | | + | call expression requires function + | +help: `X::Entry` is a unit enum variant, and does not take parentheses to be constructed + | +LL - X::Entry(); +LL + X::Entry; + | + +error[E0618]: expected function, found `i32` + --> $DIR/E0618.rs:9:5 + | +LL | let x = 0i32; + | - `x` has type `i32` +LL | x(); + | ^-- + | | + | call expression requires function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/error-codes/E0620.rs b/tests/ui/error-codes/E0620.rs new file mode 100644 index 000000000..2831413ea --- /dev/null +++ b/tests/ui/error-codes/E0620.rs @@ -0,0 +1,3 @@ +fn main() { + let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620 +} diff --git a/tests/ui/error-codes/E0620.stderr b/tests/ui/error-codes/E0620.stderr new file mode 100644 index 000000000..65152b2b7 --- /dev/null +++ b/tests/ui/error-codes/E0620.stderr @@ -0,0 +1,15 @@ +error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]` + --> $DIR/E0620.rs:2:16 + | +LL | let _foo = &[1_usize, 2] as [usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using an implicit coercion to `&[usize]` instead + --> $DIR/E0620.rs:2:16 + | +LL | let _foo = &[1_usize, 2] as [usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0620`. diff --git a/tests/ui/error-codes/E0621-does-not-trigger-for-closures.rs b/tests/ui/error-codes/E0621-does-not-trigger-for-closures.rs new file mode 100644 index 000000000..44f174c0f --- /dev/null +++ b/tests/ui/error-codes/E0621-does-not-trigger-for-closures.rs @@ -0,0 +1,16 @@ +// Test that we give the generic error when one of the free regions is +// bound in a closure (rather than suggesting a change to the signature +// of the closure, which is not specified in `foo` but rather in `invoke`). + +fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32 +where F: FnOnce(&'a i32, &i32) -> &'a i32 +{ + let y = 22; + f(x, &y) +} + +fn foo<'a>(x: &'a i32) { + invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr new file mode 100644 index 000000000..b9edeb834 --- /dev/null +++ b/tests/ui/error-codes/E0621-does-not-trigger-for-closures.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/E0621-does-not-trigger-for-closures.rs:13:45 + | +LL | invoke(&x, |a, b| if a > b { a } else { b }); + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 i32 + | has type `&'1 i32` + +error: aborting due to previous error + diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs new file mode 100644 index 000000000..ae7378a70 --- /dev/null +++ b/tests/ui/error-codes/E0622.rs @@ -0,0 +1,6 @@ +#![feature(intrinsics)] +extern "rust-intrinsic" { + pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + //~^ ERROR intrinsic must be a function [E0622] +} +fn main() { unsafe { breakpoint(); } } diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr new file mode 100644 index 000000000..8466dfe38 --- /dev/null +++ b/tests/ui/error-codes/E0622.stderr @@ -0,0 +1,9 @@ +error[E0622]: intrinsic must be a function + --> $DIR/E0622.rs:3:5 + | +LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0622`. diff --git a/tests/ui/error-codes/E0624.rs b/tests/ui/error-codes/E0624.rs new file mode 100644 index 000000000..4c68b70fb --- /dev/null +++ b/tests/ui/error-codes/E0624.rs @@ -0,0 +1,12 @@ +mod inner { + pub struct Foo; + + impl Foo { + fn method(&self) {} + } +} + +fn main() { + let foo = inner::Foo; + foo.method(); //~ ERROR associated function `method` is private [E0624] +} diff --git a/tests/ui/error-codes/E0624.stderr b/tests/ui/error-codes/E0624.stderr new file mode 100644 index 000000000..e59b8a8ae --- /dev/null +++ b/tests/ui/error-codes/E0624.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `method` is private + --> $DIR/E0624.rs:11:9 + | +LL | fn method(&self) {} + | ---------------- private associated function defined here +... +LL | foo.method(); + | ^^^^^^ private associated function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/error-codes/E0637.rs b/tests/ui/error-codes/E0637.rs new file mode 100644 index 000000000..382ce3ed0 --- /dev/null +++ b/tests/ui/error-codes/E0637.rs @@ -0,0 +1,17 @@ +fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + //~^ ERROR: `'_` cannot be used here [E0637] + //~| ERROR: missing lifetime specifier + if str1.len() > str2.len() { + str1 + } else { + str2 + } +} + +fn and_without_explicit_lifetime() +where + T: Into<&u32>, //~ ERROR: `&` without an explicit lifetime name cannot be used here [E0637] +{ +} + +fn main() {} diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr new file mode 100644 index 000000000..78341735e --- /dev/null +++ b/tests/ui/error-codes/E0637.stderr @@ -0,0 +1,34 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/E0637.rs:1:24 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | ^^ `'_` is a reserved lifetime name + +error[E0106]: missing lifetime specifier + --> $DIR/E0637.rs:1:62 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | ------- ------- ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `str1` or `str2` +help: consider introducing a named lifetime parameter + | +LL | fn underscore_lifetime<'a, '_>(str1: &'a str, str2: &'a str) -> &'a str { + | +++ ~~ ~~ ~~ + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/E0637.rs:13:13 + | +LL | T: Into<&u32>, + | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/E0637.rs:13:8 + | +LL | T: Into<&u32>, + | ^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/error-codes/E0642.fixed b/tests/ui/error-codes/E0642.fixed new file mode 100644 index 000000000..fc6255e02 --- /dev/null +++ b/tests/ui/error-codes/E0642.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +#![allow(unused)] // for rustfix + +#[derive(Clone, Copy)] +struct S; + +trait T { + fn foo(_: (i32, i32)); //~ ERROR patterns aren't allowed in methods without bodies + + fn bar(_: (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies + + fn method(_: S) {} //~ ERROR patterns aren't allowed in methods without bodies + + fn f(&ident: &S) {} // ok + fn g(&&ident: &&S) {} // ok + fn h(mut ident: S) {} // ok +} + +fn main() {} diff --git a/tests/ui/error-codes/E0642.rs b/tests/ui/error-codes/E0642.rs new file mode 100644 index 000000000..5f85f3935 --- /dev/null +++ b/tests/ui/error-codes/E0642.rs @@ -0,0 +1,20 @@ +// run-rustfix + +#![allow(unused)] // for rustfix + +#[derive(Clone, Copy)] +struct S; + +trait T { + fn foo((x, y): (i32, i32)); //~ ERROR patterns aren't allowed in methods without bodies + + fn bar((x, y): (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies + + fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies + + fn f(&ident: &S) {} // ok + fn g(&&ident: &&S) {} // ok + fn h(mut ident: S) {} // ok +} + +fn main() {} diff --git a/tests/ui/error-codes/E0642.stderr b/tests/ui/error-codes/E0642.stderr new file mode 100644 index 000000000..dd9e28ad4 --- /dev/null +++ b/tests/ui/error-codes/E0642.stderr @@ -0,0 +1,36 @@ +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/E0642.rs:9:12 + | +LL | fn foo((x, y): (i32, i32)); + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL | fn foo(_: (i32, i32)); + | ~ + +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/E0642.rs:11:12 + | +LL | fn bar((x, y): (i32, i32)) {} + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL | fn bar(_: (i32, i32)) {} + | ~ + +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/E0642.rs:13:15 + | +LL | fn method(S { .. }: S) {} + | ^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL | fn method(_: S) {} + | ~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/error-codes/E0646.rs b/tests/ui/error-codes/E0646.rs new file mode 100644 index 000000000..bb62428f5 --- /dev/null +++ b/tests/ui/error-codes/E0646.rs @@ -0,0 +1 @@ +fn main() where (): Copy {} //~ ERROR [E0646] diff --git a/tests/ui/error-codes/E0646.stderr b/tests/ui/error-codes/E0646.stderr new file mode 100644 index 000000000..069401b3f --- /dev/null +++ b/tests/ui/error-codes/E0646.stderr @@ -0,0 +1,9 @@ +error[E0646]: `main` function is not allowed to have a `where` clause + --> $DIR/E0646.rs:1:11 + | +LL | fn main() where (): Copy {} + | ^^^^^^^^^^^^^^ `main` cannot have a `where` clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0646`. diff --git a/tests/ui/error-codes/E0647.rs b/tests/ui/error-codes/E0647.rs new file mode 100644 index 000000000..fc085511c --- /dev/null +++ b/tests/ui/error-codes/E0647.rs @@ -0,0 +1,9 @@ +#![no_std] +#![feature(start)] + +extern crate std; + +#[start] +fn start(_: isize, _: *const *const u8) -> isize where (): Copy { //~ ERROR [E0647] + 0 +} diff --git a/tests/ui/error-codes/E0647.stderr b/tests/ui/error-codes/E0647.stderr new file mode 100644 index 000000000..08cedfaef --- /dev/null +++ b/tests/ui/error-codes/E0647.stderr @@ -0,0 +1,9 @@ +error[E0647]: start function is not allowed to have a `where` clause + --> $DIR/E0647.rs:7:50 + | +LL | fn start(_: isize, _: *const *const u8) -> isize where (): Copy { + | ^^^^^^^^^^^^^^ start function cannot have a `where` clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0647`. diff --git a/tests/ui/error-codes/E0648.rs b/tests/ui/error-codes/E0648.rs new file mode 100644 index 000000000..8408a78c7 --- /dev/null +++ b/tests/ui/error-codes/E0648.rs @@ -0,0 +1,4 @@ +#[export_name="\0foo"] //~ ERROR E0648 +pub fn bar() {} + +fn main() {} diff --git a/tests/ui/error-codes/E0648.stderr b/tests/ui/error-codes/E0648.stderr new file mode 100644 index 000000000..1a65825c7 --- /dev/null +++ b/tests/ui/error-codes/E0648.stderr @@ -0,0 +1,9 @@ +error[E0648]: `export_name` may not contain null characters + --> $DIR/E0648.rs:1:1 + | +LL | #[export_name="\0foo"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0648`. diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs new file mode 100644 index 000000000..cb11de13f --- /dev/null +++ b/tests/ui/error-codes/E0657.rs @@ -0,0 +1,26 @@ +#![allow(warnings)] + +trait Id {} +trait Lt<'a> {} + +impl<'a> Lt<'a> for () {} +impl Id for T {} + +fn free_fn_capture_hrtb_in_impl_trait() + -> Box Id>> + //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] +{ + Box::new(()) +} + +struct Foo; +impl Foo { + fn impl_fn_capture_hrtb_in_impl_trait() + -> Box Id>> + //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level + { + Box::new(()) + } +} + +fn main() {} diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr new file mode 100644 index 000000000..df76b45a5 --- /dev/null +++ b/tests/ui/error-codes/E0657.stderr @@ -0,0 +1,15 @@ +error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level + --> $DIR/E0657.rs:10:31 + | +LL | -> Box Id>> + | ^^ + +error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level + --> $DIR/E0657.rs:19:35 + | +LL | -> Box Id>> + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/error-codes/E0658.rs b/tests/ui/error-codes/E0658.rs new file mode 100644 index 000000000..9c9b95d70 --- /dev/null +++ b/tests/ui/error-codes/E0658.rs @@ -0,0 +1,6 @@ +#[repr(u128)] +enum Foo { //~ ERROR E0658 + Bar(u64), +} + +fn main() {} diff --git a/tests/ui/error-codes/E0658.stderr b/tests/ui/error-codes/E0658.stderr new file mode 100644 index 000000000..8d4234845 --- /dev/null +++ b/tests/ui/error-codes/E0658.stderr @@ -0,0 +1,12 @@ +error[E0658]: repr with 128-bit type is unstable + --> $DIR/E0658.rs:2:1 + | +LL | enum Foo { + | ^^^^^^^^ + | + = note: see issue #56071 for more information + = help: add `#![feature(repr128)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/error-codes/E0659.rs b/tests/ui/error-codes/E0659.rs new file mode 100644 index 000000000..c00026bb7 --- /dev/null +++ b/tests/ui/error-codes/E0659.rs @@ -0,0 +1,16 @@ +mod moon { + pub fn foo() {} +} + +mod earth { + pub fn foo() {} +} + +mod collider { + pub use moon::*; + pub use earth::*; +} + +fn main() { + collider::foo(); //~ ERROR E0659 +} diff --git a/tests/ui/error-codes/E0659.stderr b/tests/ui/error-codes/E0659.stderr new file mode 100644 index 000000000..b0c73c636 --- /dev/null +++ b/tests/ui/error-codes/E0659.stderr @@ -0,0 +1,23 @@ +error[E0659]: `foo` is ambiguous + --> $DIR/E0659.rs:15:15 + | +LL | collider::foo(); + | ^^^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `foo` could refer to the function imported here + --> $DIR/E0659.rs:10:13 + | +LL | pub use moon::*; + | ^^^^^^^ + = help: consider adding an explicit import of `foo` to disambiguate +note: `foo` could also refer to the function imported here + --> $DIR/E0659.rs:11:13 + | +LL | pub use earth::*; + | ^^^^^^^^ + = help: consider adding an explicit import of `foo` to disambiguate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/error-codes/E0705.rs b/tests/ui/error-codes/E0705.rs new file mode 100644 index 000000000..05abcb629 --- /dev/null +++ b/tests/ui/error-codes/E0705.rs @@ -0,0 +1,10 @@ +// check-pass + +// This is a stub feature that doesn't control anything, so to make tidy happy, +// gate-test-test_2018_feature + +#![feature(test_2018_feature)] +//~^ WARN the feature `test_2018_feature` is included in the Rust 2018 edition +#![feature(rust_2018_preview)] + +fn main() {} diff --git a/tests/ui/error-codes/E0705.stderr b/tests/ui/error-codes/E0705.stderr new file mode 100644 index 000000000..6fa843158 --- /dev/null +++ b/tests/ui/error-codes/E0705.stderr @@ -0,0 +1,9 @@ +warning[E0705]: the feature `test_2018_feature` is included in the Rust 2018 edition + --> $DIR/E0705.rs:6:12 + | +LL | #![feature(test_2018_feature)] + | ^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + +For more information about this error, try `rustc --explain E0705`. diff --git a/tests/ui/error-codes/E0711.rs b/tests/ui/error-codes/E0711.rs new file mode 100644 index 000000000..7b1a217bd --- /dev/null +++ b/tests/ui/error-codes/E0711.rs @@ -0,0 +1,18 @@ +// copied from: tests/ui/feature-gates/stability-attribute-consistency.rs + +#![feature(staged_api)] + +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "foo", since = "1.0.0")] +fn foo_stable_1_0_0() {} + +#[stable(feature = "foo", since = "1.29.0")] +//~^ ERROR feature `foo` is declared stable since 1.29.0 +fn foo_stable_1_29_0() {} + +#[unstable(feature = "foo", issue = "none")] +//~^ ERROR feature `foo` is declared unstable +fn foo_unstable() {} + +fn main() {} diff --git a/tests/ui/error-codes/E0711.stderr b/tests/ui/error-codes/E0711.stderr new file mode 100644 index 000000000..f39cb4ecd --- /dev/null +++ b/tests/ui/error-codes/E0711.stderr @@ -0,0 +1,15 @@ +error[E0711]: feature `foo` is declared stable since 1.29.0, but was previously declared stable since 1.0.0 + --> $DIR/E0711.rs:10:1 + | +LL | #[stable(feature = "foo", since = "1.29.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0711]: feature `foo` is declared unstable, but was previously declared stable + --> $DIR/E0711.rs:14:1 + | +LL | #[unstable(feature = "foo", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0711`. diff --git a/tests/ui/error-codes/E0718.rs b/tests/ui/error-codes/E0718.rs new file mode 100644 index 000000000..909cae0ba --- /dev/null +++ b/tests/ui/error-codes/E0718.rs @@ -0,0 +1,7 @@ +#![feature(lang_items)] + +// Box is expected to be a struct, so this will error. +#[lang = "owned_box"] //~ ERROR language item must be applied to a struct +static X: u32 = 42; + +fn main() {} diff --git a/tests/ui/error-codes/E0718.stderr b/tests/ui/error-codes/E0718.stderr new file mode 100644 index 000000000..30378dd16 --- /dev/null +++ b/tests/ui/error-codes/E0718.stderr @@ -0,0 +1,9 @@ +error[E0718]: `owned_box` language item must be applied to a struct + --> $DIR/E0718.rs:4:1 + | +LL | #[lang = "owned_box"] + | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/error-codes/E0719.rs b/tests/ui/error-codes/E0719.rs new file mode 100644 index 000000000..3311e1909 --- /dev/null +++ b/tests/ui/error-codes/E0719.rs @@ -0,0 +1,14 @@ +trait Foo: Iterator {} +//~^ ERROR is already specified + +type Unit = (); + +fn test() -> Box> { +//~^ ERROR is already specified + Box::new(None.into_iter()) +} + +fn main() { + let _: &dyn Iterator; + test(); +} diff --git a/tests/ui/error-codes/E0719.stderr b/tests/ui/error-codes/E0719.stderr new file mode 100644 index 000000000..b342d6343 --- /dev/null +++ b/tests/ui/error-codes/E0719.stderr @@ -0,0 +1,19 @@ +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/E0719.rs:1:33 + | +LL | trait Foo: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/E0719.rs:6:42 + | +LL | fn test() -> Box> { + | --------- ^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0719`. diff --git a/tests/ui/error-codes/E0730.rs b/tests/ui/error-codes/E0730.rs new file mode 100644 index 000000000..04f5e5d42 --- /dev/null +++ b/tests/ui/error-codes/E0730.rs @@ -0,0 +1,8 @@ +fn is_123(x: [u32; N]) -> bool { + match x { + [1, 2, ..] => true, //~ ERROR cannot pattern-match on an array without a fixed length + _ => false + } +} + +fn main() {} diff --git a/tests/ui/error-codes/E0730.stderr b/tests/ui/error-codes/E0730.stderr new file mode 100644 index 000000000..067e8c57c --- /dev/null +++ b/tests/ui/error-codes/E0730.stderr @@ -0,0 +1,9 @@ +error[E0730]: cannot pattern-match on an array without a fixed length + --> $DIR/E0730.rs:3:9 + | +LL | [1, 2, ..] => true, + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0730`. diff --git a/tests/ui/error-codes/E0746.fixed b/tests/ui/error-codes/E0746.fixed new file mode 100644 index 000000000..ca8319aa0 --- /dev/null +++ b/tests/ui/error-codes/E0746.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code)] +struct Struct; +trait Trait {} +impl Trait for Struct {} +impl Trait for u32 {} + +fn foo() -> impl Trait { Struct } +//~^ ERROR E0746 + +fn bar() -> impl Trait { //~ ERROR E0746 + if true { + return 0; + } + 42 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0746.rs b/tests/ui/error-codes/E0746.rs new file mode 100644 index 000000000..bf5ba8fff --- /dev/null +++ b/tests/ui/error-codes/E0746.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code)] +struct Struct; +trait Trait {} +impl Trait for Struct {} +impl Trait for u32 {} + +fn foo() -> dyn Trait { Struct } +//~^ ERROR E0746 + +fn bar() -> dyn Trait { //~ ERROR E0746 + if true { + return 0; + } + 42 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0746.stderr b/tests/ui/error-codes/E0746.stderr new file mode 100644 index 000000000..2153b59ad --- /dev/null +++ b/tests/ui/error-codes/E0746.stderr @@ -0,0 +1,27 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/E0746.rs:8:13 + | +LL | fn foo() -> dyn Trait { Struct } + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait` + | +LL | fn foo() -> impl Trait { Struct } + | ~~~~~~~~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/E0746.rs:11:13 + | +LL | fn bar() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait` + | +LL | fn bar() -> impl Trait { + | ~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/error-codes/E0767.rs b/tests/ui/error-codes/E0767.rs new file mode 100644 index 000000000..14215d36a --- /dev/null +++ b/tests/ui/error-codes/E0767.rs @@ -0,0 +1,8 @@ +fn main() { + 'a: loop { + || { + //~^ ERROR mismatched types + loop { break 'a; } //~ ERROR E0767 + } + } +} diff --git a/tests/ui/error-codes/E0767.stderr b/tests/ui/error-codes/E0767.stderr new file mode 100644 index 000000000..ee8524730 --- /dev/null +++ b/tests/ui/error-codes/E0767.stderr @@ -0,0 +1,27 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/E0767.rs:5:26 + | +LL | 'a: loop { + | -- unreachable label defined here +... +LL | loop { break 'a; } + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error[E0308]: mismatched types + --> $DIR/E0767.rs:3:9 + | +LL | / || { +LL | | +LL | | loop { break 'a; } +LL | | } + | |_________^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/E0767.rs:3:9: 3:11]` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0767. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0771.rs b/tests/ui/error-codes/E0771.rs new file mode 100644 index 000000000..67e7d106a --- /dev/null +++ b/tests/ui/error-codes/E0771.rs @@ -0,0 +1,8 @@ +#![feature(adt_const_params)] +//~^ WARN the feature `adt_const_params` is incomplete + +fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0771 + +fn main() { + function_with_str::<"Hello, world!">() +} diff --git a/tests/ui/error-codes/E0771.stderr b/tests/ui/error-codes/E0771.stderr new file mode 100644 index 000000000..b759399a9 --- /dev/null +++ b/tests/ui/error-codes/E0771.stderr @@ -0,0 +1,20 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/E0771.rs:4:41 + | +LL | fn function_with_str<'a, const STRING: &'a str>() {} + | ^^ + | + = note: for more information, see issue #74052 + +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/E0771.rs:1:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/error-codes/E0777.rs b/tests/ui/error-codes/E0777.rs new file mode 100644 index 000000000..ff70f7368 --- /dev/null +++ b/tests/ui/error-codes/E0777.rs @@ -0,0 +1,7 @@ +#[derive("Clone")] //~ ERROR E0777 +#[derive("Clone +")] +//~^^ ERROR E0777 +struct Foo; + +fn main() {} diff --git a/tests/ui/error-codes/E0777.stderr b/tests/ui/error-codes/E0777.stderr new file mode 100644 index 000000000..14697d89e --- /dev/null +++ b/tests/ui/error-codes/E0777.stderr @@ -0,0 +1,21 @@ +error[E0777]: expected path to a trait, found literal + --> $DIR/E0777.rs:1:10 + | +LL | #[derive("Clone")] + | ^^^^^^^ not a trait + | + = help: try using `#[derive(Clone)]` + +error[E0777]: expected path to a trait, found literal + --> $DIR/E0777.rs:2:10 + | +LL | #[derive("Clone + | __________^ +LL | | ")] + | |_^ not a trait + | + = help: for example, write `#[derive(Debug)]` for `Debug` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0777`. diff --git a/tests/ui/error-codes/E0778.rs b/tests/ui/error-codes/E0778.rs new file mode 100644 index 000000000..74653886d --- /dev/null +++ b/tests/ui/error-codes/E0778.rs @@ -0,0 +1,4 @@ +#[instruction_set()] //~ ERROR +fn no_isa_defined() {} + +fn main() {} diff --git a/tests/ui/error-codes/E0778.stderr b/tests/ui/error-codes/E0778.stderr new file mode 100644 index 000000000..42647e5c6 --- /dev/null +++ b/tests/ui/error-codes/E0778.stderr @@ -0,0 +1,9 @@ +error[E0778]: `#[instruction_set]` requires an argument + --> $DIR/E0778.rs:1:1 + | +LL | #[instruction_set()] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0778`. diff --git a/tests/ui/error-codes/E0779.rs b/tests/ui/error-codes/E0779.rs new file mode 100644 index 000000000..c32dae12c --- /dev/null +++ b/tests/ui/error-codes/E0779.rs @@ -0,0 +1,2 @@ +#[instruction_set(arm::magic)] //~ ERROR +fn main() {} diff --git a/tests/ui/error-codes/E0779.stderr b/tests/ui/error-codes/E0779.stderr new file mode 100644 index 000000000..7c6a119a0 --- /dev/null +++ b/tests/ui/error-codes/E0779.stderr @@ -0,0 +1,9 @@ +error[E0779]: invalid instruction set specified + --> $DIR/E0779.rs:1:1 + | +LL | #[instruction_set(arm::magic)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0779`. diff --git a/tests/ui/error-codes/E0790.rs b/tests/ui/error-codes/E0790.rs new file mode 100644 index 000000000..d99006d2d --- /dev/null +++ b/tests/ui/error-codes/E0790.rs @@ -0,0 +1,53 @@ +mod inner { + pub trait MyTrait { + const MY_ASSOC_CONST: (); + + fn my_fn(); + } + + pub struct MyStruct; + + impl MyTrait for MyStruct { + const MY_ASSOC_CONST: () = (); + + fn my_fn() {} + } + + fn call() { + MyTrait::my_fn(); //~ ERROR E0790 + } + + fn use_const() { + let _ = MyTrait::MY_ASSOC_CONST; //~ ERROR E0790 + } +} + +fn call_inner() { + inner::MyTrait::my_fn(); //~ ERROR E0790 +} + +fn use_const_inner() { + let _ = inner::MyTrait::MY_ASSOC_CONST; //~ ERROR E0790 +} + +trait MyTrait2 { + fn my_fn(); +} + +struct Impl1; + +impl MyTrait2 for Impl1 { + fn my_fn() {} +} + +struct Impl2; + +impl MyTrait2 for Impl2 { + fn my_fn() {} +} + +fn call_multiple_impls() { + MyTrait2::my_fn(); //~ ERROR E0790 +} + +fn main() {} diff --git a/tests/ui/error-codes/E0790.stderr b/tests/ui/error-codes/E0790.stderr new file mode 100644 index 000000000..fc025a3fc --- /dev/null +++ b/tests/ui/error-codes/E0790.stderr @@ -0,0 +1,73 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:17:9 + | +LL | fn my_fn(); + | ----------- `MyTrait::my_fn` defined here +... +LL | MyTrait::my_fn(); + | ^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | ::my_fn(); + | ++++++++++++ + + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:21:17 + | +LL | const MY_ASSOC_CONST: (); + | ------------------------- `MyTrait::MY_ASSOC_CONST` defined here +... +LL | let _ = MyTrait::MY_ASSOC_CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let _ = ::MY_ASSOC_CONST; + | ++++++++++++ + + +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:26:5 + | +LL | fn my_fn(); + | ----------- `MyTrait::my_fn` defined here +... +LL | inner::MyTrait::my_fn(); + | ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | ::my_fn(); + | ++++++++++++ + + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:30:13 + | +LL | const MY_ASSOC_CONST: (); + | ------------------------- `MyTrait::MY_ASSOC_CONST` defined here +... +LL | let _ = inner::MyTrait::MY_ASSOC_CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let _ = ::MY_ASSOC_CONST; + | ++++++++++++ + + +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:50:5 + | +LL | fn my_fn(); + | ----------- `MyTrait2::my_fn` defined here +... +LL | MyTrait2::my_fn(); + | ^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use a fully-qualified path to a specific available implementation (2 found) + | +LL | ::my_fn(); + | +++++++++ + + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/error-codes/auxiliary/crateresolve1-1.rs b/tests/ui/error-codes/auxiliary/crateresolve1-1.rs new file mode 100644 index 000000000..bd9c8483e --- /dev/null +++ b/tests/ui/error-codes/auxiliary/crateresolve1-1.rs @@ -0,0 +1,6 @@ +// compile-flags:-C extra-filename=-1 +// no-prefer-dynamic +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/tests/ui/error-codes/auxiliary/crateresolve1-2.rs b/tests/ui/error-codes/auxiliary/crateresolve1-2.rs new file mode 100644 index 000000000..bd0f08f45 --- /dev/null +++ b/tests/ui/error-codes/auxiliary/crateresolve1-2.rs @@ -0,0 +1,6 @@ +// compile-flags:-C extra-filename=-2 +// no-prefer-dynamic +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 20 } diff --git a/tests/ui/error-codes/auxiliary/crateresolve1-3.rs b/tests/ui/error-codes/auxiliary/crateresolve1-3.rs new file mode 100644 index 000000000..1226c2fbb --- /dev/null +++ b/tests/ui/error-codes/auxiliary/crateresolve1-3.rs @@ -0,0 +1,6 @@ +// compile-flags:-C extra-filename=-3 +// no-prefer-dynamic +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 30 } diff --git a/tests/ui/error-codes/auxiliary/found-staticlib.rs b/tests/ui/error-codes/auxiliary/found-staticlib.rs new file mode 100644 index 000000000..04e2c5978 --- /dev/null +++ b/tests/ui/error-codes/auxiliary/found-staticlib.rs @@ -0,0 +1,4 @@ +// no-prefer-dynamic +#![crate_type = "staticlib"] + +pub fn foo() {} diff --git a/tests/ui/error-codes/e0119/auxiliary/complex_impl_support.rs b/tests/ui/error-codes/e0119/auxiliary/complex_impl_support.rs new file mode 100644 index 000000000..ad5bb107f --- /dev/null +++ b/tests/ui/error-codes/e0119/auxiliary/complex_impl_support.rs @@ -0,0 +1,22 @@ +use std::marker::PhantomData; + +pub trait External {} + +pub struct M<'a, 'b, 'c, T, U, V> { + a: PhantomData<&'a ()>, + b: PhantomData<&'b ()>, + c: PhantomData<&'c ()>, + d: PhantomData, + e: PhantomData, + f: PhantomData, +} + +impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box, V, W>) +where + 'b: 'a, + T: 'a, + U: (FnOnce(T) -> V) + 'static, + V: Iterator + Clone, + W: std::ops::Add, + W::Output: Copy, +{} diff --git a/tests/ui/error-codes/e0119/auxiliary/issue-23563-a.rs b/tests/ui/error-codes/e0119/auxiliary/issue-23563-a.rs new file mode 100644 index 000000000..141f36369 --- /dev/null +++ b/tests/ui/error-codes/e0119/auxiliary/issue-23563-a.rs @@ -0,0 +1,25 @@ +// Ref: https://github.com/rust-lang/rust/issues/23563#issuecomment-260751672 + +pub trait LolTo { + fn convert_to(&self) -> T; +} + +pub trait LolInto: Sized { + fn convert_into(self) -> T; +} + +pub trait LolFrom { + fn from(_: T) -> Self; +} + +impl<'a, T: ?Sized, U> LolInto for &'a T where T: LolTo { + fn convert_into(self) -> U { + self.convert_to() + } +} + +impl LolFrom for U where T: LolInto { + fn from(t: T) -> U { + t.convert_into() + } +} diff --git a/tests/ui/error-codes/e0119/complex-impl.rs b/tests/ui/error-codes/e0119/complex-impl.rs new file mode 100644 index 000000000..9149e4ce5 --- /dev/null +++ b/tests/ui/error-codes/e0119/complex-impl.rs @@ -0,0 +1,11 @@ +// aux-build:complex_impl_support.rs + +extern crate complex_impl_support; + +use complex_impl_support::{External, M}; + +struct Q; + +impl External for (Q, R) {} //~ ERROR only traits defined + +fn main() {} diff --git a/tests/ui/error-codes/e0119/complex-impl.stderr b/tests/ui/error-codes/e0119/complex-impl.stderr new file mode 100644 index 000000000..654073eec --- /dev/null +++ b/tests/ui/error-codes/e0119/complex-impl.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/complex-impl.rs:9:1 + | +LL | impl External for (Q, R) {} + | ^^^^^^^^^^^^^^^^^^^^^------ + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/error-codes/e0119/conflict-with-std.rs b/tests/ui/error-codes/e0119/conflict-with-std.rs new file mode 100644 index 000000000..c9db2bab1 --- /dev/null +++ b/tests/ui/error-codes/e0119/conflict-with-std.rs @@ -0,0 +1,26 @@ +use std::marker::PhantomData; +use std::convert::{TryFrom, AsRef}; + +struct Q; +impl AsRef for Box { //~ ERROR conflicting implementations + fn as_ref(&self) -> &Q { + &**self + } +} + +struct S; +impl From for S { //~ ERROR conflicting implementations + fn from(s: S) -> S { + s + } +} + +struct X; +impl TryFrom for X { //~ ERROR conflicting implementations + type Error = (); + fn try_from(u: X) -> Result { + Ok(u) + } +} + +fn main() {} diff --git a/tests/ui/error-codes/e0119/conflict-with-std.stderr b/tests/ui/error-codes/e0119/conflict-with-std.stderr new file mode 100644 index 000000000..ef888a1c2 --- /dev/null +++ b/tests/ui/error-codes/e0119/conflict-with-std.stderr @@ -0,0 +1,32 @@ +error[E0119]: conflicting implementations of trait `AsRef` for type `Box` + --> $DIR/conflict-with-std.rs:5:1 + | +LL | impl AsRef for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `alloc`: + - impl AsRef for Box + where A: Allocator, T: ?Sized; + +error[E0119]: conflicting implementations of trait `From` for type `S` + --> $DIR/conflict-with-std.rs:12:1 + | +LL | impl From for S { + | ^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl From for T; + +error[E0119]: conflicting implementations of trait `TryFrom` for type `X` + --> $DIR/conflict-with-std.rs:19:1 + | +LL | impl TryFrom for X { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl TryFrom for T + where U: Into; + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/e0119/issue-23563.rs b/tests/ui/error-codes/e0119/issue-23563.rs new file mode 100644 index 000000000..f578560c5 --- /dev/null +++ b/tests/ui/error-codes/e0119/issue-23563.rs @@ -0,0 +1,29 @@ +// aux-build:issue-23563-a.rs + +// Ref: https://github.com/rust-lang/rust/issues/23563#issuecomment-260751672 + +extern crate issue_23563_a as a; + +use a::LolFrom; +use a::LolInto; +use a::LolTo; + +struct LocalType(Option); + +impl<'a, T> LolFrom<&'a [T]> for LocalType { //~ ERROR conflicting implementations of trait + fn from(_: &'a [T]) -> LocalType { LocalType(None) } +} + +impl LolInto> for LocalType { + fn convert_into(self) -> LocalType { + self + } +} + +impl LolTo> for [u8] { + fn convert_to(&self) -> LocalType { + LocalType(None) + } +} + +fn main() {} diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr new file mode 100644 index 000000000..1b2d64282 --- /dev/null +++ b/tests/ui/error-codes/e0119/issue-23563.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `LolFrom<&[_]>` for type `LocalType<_>` + --> $DIR/issue-23563.rs:13:1 + | +LL | impl<'a, T> LolFrom<&'a [T]> for LocalType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `issue_23563_a`: + - impl LolFrom for U + where T: LolInto; + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/e0119/issue-27403.rs b/tests/ui/error-codes/e0119/issue-27403.rs new file mode 100644 index 000000000..b03a564ff --- /dev/null +++ b/tests/ui/error-codes/e0119/issue-27403.rs @@ -0,0 +1,11 @@ +pub struct GenX { + inner: S, +} + +impl Into for GenX { //~ ERROR conflicting implementations + fn into(self) -> S { + self.inner + } +} + +fn main() {} diff --git a/tests/ui/error-codes/e0119/issue-27403.stderr b/tests/ui/error-codes/e0119/issue-27403.stderr new file mode 100644 index 000000000..9b3345c23 --- /dev/null +++ b/tests/ui/error-codes/e0119/issue-27403.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Into<_>` for type `GenX<_>` + --> $DIR/issue-27403.rs:5:1 + | +LL | impl Into for GenX { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl Into for T + where U: From; + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/e0119/issue-28981.rs b/tests/ui/error-codes/e0119/issue-28981.rs new file mode 100644 index 000000000..5fb7e9a99 --- /dev/null +++ b/tests/ui/error-codes/e0119/issue-28981.rs @@ -0,0 +1,7 @@ +use std::ops::Deref; + +struct Foo; + +impl Deref for Foo { } //~ ERROR must be used + +fn main() {} diff --git a/tests/ui/error-codes/e0119/issue-28981.stderr b/tests/ui/error-codes/e0119/issue-28981.stderr new file mode 100644 index 000000000..97b570bc7 --- /dev/null +++ b/tests/ui/error-codes/e0119/issue-28981.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/issue-28981.rs:5:6 + | +LL | impl Deref for Foo { } + | ^^^ type parameter `Foo` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/error-codes/e0119/so-37347311.rs b/tests/ui/error-codes/e0119/so-37347311.rs new file mode 100644 index 000000000..d5f624bc4 --- /dev/null +++ b/tests/ui/error-codes/e0119/so-37347311.rs @@ -0,0 +1,17 @@ +// Ref: https://stackoverflow.com/q/37347311 + +trait Storage { + type Error; +} + +enum MyError { + StorageProblem(S::Error), +} + +impl From for MyError { //~ ERROR conflicting implementations + fn from(error: S::Error) -> MyError { + MyError::StorageProblem(error) + } +} + +fn main() {} diff --git a/tests/ui/error-codes/e0119/so-37347311.stderr b/tests/ui/error-codes/e0119/so-37347311.stderr new file mode 100644 index 000000000..99367e808 --- /dev/null +++ b/tests/ui/error-codes/e0119/so-37347311.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From>` for type `MyError<_>` + --> $DIR/so-37347311.rs:11:1 + | +LL | impl From for MyError { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl From for T; + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/ex-E0611.rs b/tests/ui/error-codes/ex-E0611.rs new file mode 100644 index 000000000..f18a3619f --- /dev/null +++ b/tests/ui/error-codes/ex-E0611.rs @@ -0,0 +1,12 @@ +mod a { + pub struct Foo(u32); + + impl Foo { + pub fn new() -> Foo { Foo(0) } + } +} + +fn main() { + let y = a::Foo::new(); + y.0; //~ ERROR field `0` of struct `Foo` is private +} diff --git a/tests/ui/error-codes/ex-E0611.stderr b/tests/ui/error-codes/ex-E0611.stderr new file mode 100644 index 000000000..1da7b33be --- /dev/null +++ b/tests/ui/error-codes/ex-E0611.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `0` of struct `Foo` is private + --> $DIR/ex-E0611.rs:11:6 + | +LL | y.0; + | ^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/error-codes/ex-E0612.rs b/tests/ui/error-codes/ex-E0612.rs new file mode 100644 index 000000000..c8ea53ae9 --- /dev/null +++ b/tests/ui/error-codes/ex-E0612.rs @@ -0,0 +1,6 @@ +struct Foo(u32); + +fn main() { + let y = Foo(0); + y.1; //~ ERROR no field `1` on type `Foo` +} diff --git a/tests/ui/error-codes/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr new file mode 100644 index 000000000..b21b6fdfc --- /dev/null +++ b/tests/ui/error-codes/ex-E0612.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `1` on type `Foo` + --> $DIR/ex-E0612.rs:5:6 + | +LL | y.1; + | ^ help: a field with a similar name exists: `0` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/error-festival.rs b/tests/ui/error-festival.rs new file mode 100644 index 000000000..356564e54 --- /dev/null +++ b/tests/ui/error-festival.rs @@ -0,0 +1,43 @@ +enum Question { + Yes, + No, +} + +mod foo { + const FOO: u32 = 0; +} + +fn main() { + let x = "a"; + x += 2; + //~^ ERROR E0368 + y = 2; + //~^ ERROR E0425 + x.z(); + //~^ ERROR E0599 + + !Question::Yes; + //~^ ERROR E0600 + + foo::FOO; + //~^ ERROR E0603 + + 0u32 as char; + //~^ ERROR E0604 + + let x = 0u8; + x as Vec; + //~^ ERROR E0605 + + let x = 5; + let x_is_nonzero = x as bool; + //~^ ERROR E0054 + + let x = &0u8; + let y: u32 = x as u32; + //~^ ERROR E0606 + + let v = core::ptr::null::(); + v as *const [u8]; + //~^ ERROR E0607 +} diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr new file mode 100644 index 000000000..e8ee1d969 --- /dev/null +++ b/tests/ui/error-festival.stderr @@ -0,0 +1,88 @@ +error[E0425]: cannot find value `y` in this scope + --> $DIR/error-festival.rs:14:5 + | +LL | y = 2; + | ^ help: a local variable with a similar name exists: `x` + +error[E0603]: constant `FOO` is private + --> $DIR/error-festival.rs:22:10 + | +LL | foo::FOO; + | ^^^ private constant + | +note: the constant `FOO` is defined here + --> $DIR/error-festival.rs:7:5 + | +LL | const FOO: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0368]: binary assignment operation `+=` cannot be applied to type `&str` + --> $DIR/error-festival.rs:12:5 + | +LL | x += 2; + | -^^^^^ + | | + | cannot use `+=` on type `&str` + +error[E0599]: no method named `z` found for reference `&str` in the current scope + --> $DIR/error-festival.rs:16:7 + | +LL | x.z(); + | ^ method not found in `&str` + +error[E0600]: cannot apply unary operator `!` to type `Question` + --> $DIR/error-festival.rs:19:5 + | +LL | !Question::Yes; + | ^^^^^^^^^^^^^^ cannot apply unary operator `!` + | +note: an implementation of `Not` might be missing for `Question` + --> $DIR/error-festival.rs:1:1 + | +LL | enum Question { + | ^^^^^^^^^^^^^ must implement `Not` +note: the trait `Not` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error[E0604]: only `u8` can be cast as `char`, not `u32` + --> $DIR/error-festival.rs:25:5 + | +LL | 0u32 as char; + | ^^^^^^^^^^^^ + | | + | invalid cast + | help: try `char::from_u32` instead: `char::from_u32(0u32)` + +error[E0605]: non-primitive cast: `u8` as `Vec` + --> $DIR/error-festival.rs:29:5 + | +LL | x as Vec; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0054]: cannot cast as `bool` + --> $DIR/error-festival.rs:33:24 + | +LL | let x_is_nonzero = x as bool; + | ^^^^^^^^^ help: compare with zero instead: `x != 0` + +error[E0606]: casting `&u8` as `u32` is invalid + --> $DIR/error-festival.rs:37:18 + | +LL | let y: u32 = x as u32; + | ^^^^^^^^ + | +help: dereference the expression + | +LL | let y: u32 = *x as u32; + | + + +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` + --> $DIR/error-festival.rs:41:5 + | +LL | v as *const [u8]; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0054, E0368, E0425, E0599, E0600, E0603, E0604, E0605, E0606... +For more information about an error, try `rustc --explain E0054`. diff --git a/tests/ui/error-should-say-copy-not-pod.rs b/tests/ui/error-should-say-copy-not-pod.rs new file mode 100644 index 000000000..40c4730ef --- /dev/null +++ b/tests/ui/error-should-say-copy-not-pod.rs @@ -0,0 +1,7 @@ +// Tests that the error message uses the word Copy, not Pod. + +fn check_bound(_: T) {} + +fn main() { + check_bound("nocopy".to_string()); //~ ERROR : Copy` is not satisfied +} diff --git a/tests/ui/error-should-say-copy-not-pod.stderr b/tests/ui/error-should-say-copy-not-pod.stderr new file mode 100644 index 000000000..637eb27db --- /dev/null +++ b/tests/ui/error-should-say-copy-not-pod.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/error-should-say-copy-not-pod.rs:6:17 + | +LL | check_bound("nocopy".to_string()); + | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_bound` + --> $DIR/error-should-say-copy-not-pod.rs:3:18 + | +LL | fn check_bound(_: T) {} + | ^^^^ required by this bound in `check_bound` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/auxiliary/remapped_dep.rs b/tests/ui/errors/auxiliary/remapped_dep.rs new file mode 100644 index 000000000..f9bb7bf89 --- /dev/null +++ b/tests/ui/errors/auxiliary/remapped_dep.rs @@ -0,0 +1,4 @@ +// compile-flags: --remap-path-prefix={{src-base}}/errors/auxiliary=remapped-aux +// no-remap-src-base: Manually remap, so the remapped path remains in .stderr file. + +pub struct SomeStruct {} // This line should be show as part of the error. diff --git a/tests/ui/errors/issue-104621-extern-bad-file.rs b/tests/ui/errors/issue-104621-extern-bad-file.rs new file mode 100644 index 000000000..3f13d6052 --- /dev/null +++ b/tests/ui/errors/issue-104621-extern-bad-file.rs @@ -0,0 +1,8 @@ +// compile-flags: --extern foo={{src-base}}/errors/issue-104621-extern-bad-file.rs +// only-linux + +extern crate foo; +//~^ ERROR extern location for foo is of an unknown type +//~| ERROR file name should be lib*.rlib or lib*.so +//~| ERROR can't find crate for `foo` [E0463] +fn main() {} diff --git a/tests/ui/errors/issue-104621-extern-bad-file.stderr b/tests/ui/errors/issue-104621-extern-bad-file.stderr new file mode 100644 index 000000000..b8500ad0e --- /dev/null +++ b/tests/ui/errors/issue-104621-extern-bad-file.stderr @@ -0,0 +1,21 @@ +error: extern location for foo is of an unknown type: $DIR/issue-104621-extern-bad-file.rs + --> $DIR/issue-104621-extern-bad-file.rs:4:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ + +error: file name should be lib*.rlib or lib*.so + --> $DIR/issue-104621-extern-bad-file.rs:4:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ + +error[E0463]: can't find crate for `foo` + --> $DIR/issue-104621-extern-bad-file.rs:4:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/errors/issue-104621-extern-not-file.rs b/tests/ui/errors/issue-104621-extern-not-file.rs new file mode 100644 index 000000000..899e45a30 --- /dev/null +++ b/tests/ui/errors/issue-104621-extern-not-file.rs @@ -0,0 +1,4 @@ +// compile-flags: --extern foo=. + +extern crate foo; //~ ERROR extern location for foo is not a file: . +fn main() {} diff --git a/tests/ui/errors/issue-104621-extern-not-file.stderr b/tests/ui/errors/issue-104621-extern-not-file.stderr new file mode 100644 index 000000000..5aaf97413 --- /dev/null +++ b/tests/ui/errors/issue-104621-extern-not-file.stderr @@ -0,0 +1,8 @@ +error: extern location for foo is not a file: . + --> $DIR/issue-104621-extern-not-file.rs:3:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.rs b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.rs new file mode 100644 index 000000000..a1c7af128 --- /dev/null +++ b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.rs @@ -0,0 +1,10 @@ +// check-pass + +trait X { + fn test(x: u32, ( +//~^ WARN anonymous parameters are deprecated and will be removed in the next edition +//~^^ WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + )) {} +} + +fn main() {} diff --git a/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr new file mode 100644 index 000000000..08eb8cfac --- /dev/null +++ b/tests/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr @@ -0,0 +1,23 @@ +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/issue-89280-emitter-overflow-splice-lines.rs:4:21 + | +LL | fn test(x: u32, ( + | _____________________^ +LL | | +LL | | +LL | | )) {} + | |_____^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + = note: `#[warn(anonymous_parameters)]` on by default +help: try naming the parameter or explicitly ignoring it + | +LL ~ fn test(x: u32, _: ( +LL + +LL + +LL ~ )) {} + | + +warning: 1 warning emitted + diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs new file mode 100644 index 000000000..272c6bd3f --- /dev/null +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.rs @@ -0,0 +1,25 @@ +// Emit additional suggestion to correct the trait implementation +// on a pointer +use std::{fmt, marker}; + +struct LocalType; + +impl fmt::Display for *mut LocalType { +//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types +//~| NOTE impl doesn't use only types from inside the current crate +//~| NOTE `*mut LocalType` is not defined in the current crate because raw pointers are always foreign +//~| NOTE define and implement a trait or new type instead +//~| HELP consider introducing a new wrapper type + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "This not compile") + } +} + +impl marker::Copy for *mut T { +//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types +//~| NOTE impl doesn't use only types from inside the current crate +//~| NOTE `*mut T` is not defined in the current crate because raw pointers are always foreign +//~| NOTE define and implement a trait or new type instead +} + +fn main() {} diff --git a/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr new file mode 100644 index 000000000..78d7a47de --- /dev/null +++ b/tests/ui/errors/issue-99572-impl-trait-on-pointer.stderr @@ -0,0 +1,31 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-99572-impl-trait-on-pointer.rs:7:1 + | +LL | impl fmt::Display for *mut LocalType { + | ^^^^^^^^^^^^^^^^^^^^^^-------------- + | | | + | | `*mut LocalType` is not defined in the current crate because raw pointers are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead +help: consider introducing a new wrapper type + | +LL + struct WrapperType(*mut LocalType); +LL + +LL ~ impl fmt::Display for WrapperType { + | + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-99572-impl-trait-on-pointer.rs:18:1 + | +LL | impl marker::Copy for *mut T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^------ + | | | + | | `*mut T` is not defined in the current crate because raw pointers are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr new file mode 100644 index 000000000..51e3b776c --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-reverse.local-self.stderr @@ -0,0 +1,14 @@ +error[E0423]: expected value, found struct `remapped_dep::SomeStruct` + --> $DIR/remap-path-prefix-reverse.rs:16:13 + | +LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}` + | + ::: remapped-aux/remapped_dep.rs:4:1 + | +LL | pub struct SomeStruct {} // This line should be show as part of the error. + | --------------------- `remapped_dep::SomeStruct` defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr new file mode 100644 index 000000000..51e3b776c --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-reverse.remapped-self.stderr @@ -0,0 +1,14 @@ +error[E0423]: expected value, found struct `remapped_dep::SomeStruct` + --> $DIR/remap-path-prefix-reverse.rs:16:13 + | +LL | let _ = remapped_dep::SomeStruct; // ~ERROR E0423 + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `remapped_dep::SomeStruct {}` + | + ::: remapped-aux/remapped_dep.rs:4:1 + | +LL | pub struct SomeStruct {} // This line should be show as part of the error. + | --------------------- `remapped_dep::SomeStruct` defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/errors/remap-path-prefix-reverse.rs b/tests/ui/errors/remap-path-prefix-reverse.rs new file mode 100644 index 000000000..71c80063c --- /dev/null +++ b/tests/ui/errors/remap-path-prefix-reverse.rs @@ -0,0 +1,17 @@ +// aux-build:remapped_dep.rs +// compile-flags: --remap-path-prefix={{src-base}}/errors/auxiliary=remapped-aux + +// revisions: local-self remapped-self +// [local-self] no-remap-src-base: The hack should work regardless of remapping. +// [remapped-self] remap-src-base + +// Verify that the expected source code is shown. +// error-pattern: pub struct SomeStruct {} // This line should be show + +extern crate remapped_dep; + +fn main() { + // The actual error is irrelevant. The important part it that is should show + // a snippet of the dependency's source. + let _ = remapped_dep::SomeStruct; // ~ERROR E0423 +} diff --git a/tests/ui/errors/remap-path-prefix.rs b/tests/ui/errors/remap-path-prefix.rs new file mode 100644 index 000000000..393b8e22f --- /dev/null +++ b/tests/ui/errors/remap-path-prefix.rs @@ -0,0 +1,17 @@ +// compile-flags: --remap-path-prefix={{src-base}}=remapped +// no-remap-src-base: Manually remap, so the remapped path remains in .stderr file. + +// The remapped paths are not normalized by compiletest. +// normalize-stderr-test: "\\(errors)" -> "/$1" + +// The remapped paths aren't recognized by compiletest, so we +// cannot use line-specific patterns. +// error-pattern: E0425 + +fn main() { + // We cannot actually put an ERROR marker here because + // the file name in the error message is not what the + // test framework expects (since the filename gets remapped). + // We still test the expected error in the stderr file. + ferris +} diff --git a/tests/ui/errors/remap-path-prefix.stderr b/tests/ui/errors/remap-path-prefix.stderr new file mode 100644 index 000000000..62dbd4b88 --- /dev/null +++ b/tests/ui/errors/remap-path-prefix.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `ferris` in this scope + --> remapped/errors/remap-path-prefix.rs:16:5 + | +LL | ferris + | ^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/exclusive-drop-and-copy.rs b/tests/ui/exclusive-drop-and-copy.rs new file mode 100644 index 000000000..7a251671e --- /dev/null +++ b/tests/ui/exclusive-drop-and-copy.rs @@ -0,0 +1,17 @@ +// issue #20126 + +#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented +struct Bar(::std::marker::PhantomData); + +impl Drop for Bar { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/exclusive-drop-and-copy.stderr b/tests/ui/exclusive-drop-and-copy.stderr new file mode 100644 index 000000000..8649c8abb --- /dev/null +++ b/tests/ui/exclusive-drop-and-copy.stderr @@ -0,0 +1,19 @@ +error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor + --> $DIR/exclusive-drop-and-copy.rs:3:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ `Copy` not allowed on types with destructors + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor + --> $DIR/exclusive-drop-and-copy.rs:10:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ `Copy` not allowed on types with destructors + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0184`. diff --git a/tests/ui/exec-env.rs b/tests/ui/exec-env.rs new file mode 100644 index 000000000..d7f15bcae --- /dev/null +++ b/tests/ui/exec-env.rs @@ -0,0 +1,10 @@ +// run-pass +// exec-env:TEST_EXEC_ENV=22 +// ignore-emscripten FIXME: issue #31622 +// ignore-sgx unsupported + +use std::env; + +pub fn main() { + assert_eq!(env::var("TEST_EXEC_ENV"), Ok("22".to_string())); +} diff --git a/tests/ui/explain.rs b/tests/ui/explain.rs new file mode 100644 index 000000000..5364d92e0 --- /dev/null +++ b/tests/ui/explain.rs @@ -0,0 +1,2 @@ +// compile-flags: --explain E0591 +// check-pass diff --git a/tests/ui/explain.stdout b/tests/ui/explain.stdout new file mode 100644 index 000000000..ef1d866c3 --- /dev/null +++ b/tests/ui/explain.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) { + /* ... */ +} + +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/explicit-i-suffix.rs b/tests/ui/explicit-i-suffix.rs new file mode 100644 index 000000000..40c7e4751 --- /dev/null +++ b/tests/ui/explicit-i-suffix.rs @@ -0,0 +1,14 @@ +// run-pass + +#![allow(unused_must_use)] +// pretty-expanded FIXME #23616 + +pub fn main() { + let x: isize = 8; + let y = 9; + x + y; + + let q: isize = -8; + let r = -9; + q + r; +} diff --git a/tests/ui/explicit/explicit-call-to-dtor.fixed b/tests/ui/explicit/explicit-call-to-dtor.fixed new file mode 100644 index 000000000..91a4ca608 --- /dev/null +++ b/tests/ui/explicit/explicit-call-to-dtor.fixed @@ -0,0 +1,16 @@ +// run-rustfix +struct Foo { + x: isize +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let x = Foo { x: 3 }; + println!("{}", x.x); + drop(x); //~ ERROR explicit use of destructor method +} diff --git a/tests/ui/explicit/explicit-call-to-dtor.rs b/tests/ui/explicit/explicit-call-to-dtor.rs new file mode 100644 index 000000000..0656871eb --- /dev/null +++ b/tests/ui/explicit/explicit-call-to-dtor.rs @@ -0,0 +1,16 @@ +// run-rustfix +struct Foo { + x: isize +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +fn main() { + let x = Foo { x: 3 }; + println!("{}", x.x); + x.drop(); //~ ERROR explicit use of destructor method +} diff --git a/tests/ui/explicit/explicit-call-to-dtor.stderr b/tests/ui/explicit/explicit-call-to-dtor.stderr new file mode 100644 index 000000000..f3c9bf6cc --- /dev/null +++ b/tests/ui/explicit/explicit-call-to-dtor.stderr @@ -0,0 +1,12 @@ +error[E0040]: explicit use of destructor method + --> $DIR/explicit-call-to-dtor.rs:15:7 + | +LL | x.drop(); + | --^^^^-- + | | | + | | explicit destructor calls not allowed + | help: consider using `drop` function: `drop(x)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed new file mode 100644 index 000000000..47c4c9f67 --- /dev/null +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed @@ -0,0 +1,26 @@ +// run-rustfix +struct Foo { + x: isize +} + +#[allow(drop_bounds)] +trait Bar: Drop { + fn blah(&self); +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +impl Bar for Foo { + fn blah(&self) { + drop(self); //~ ERROR explicit use of destructor method + } +} + +fn main() { + let x = Foo { x: 3 }; + println!("{}", x.x); +} diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs new file mode 100644 index 000000000..c698de50c --- /dev/null +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs @@ -0,0 +1,26 @@ +// run-rustfix +struct Foo { + x: isize +} + +#[allow(drop_bounds)] +trait Bar: Drop { + fn blah(&self); +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("kaboom"); + } +} + +impl Bar for Foo { + fn blah(&self) { + self.drop(); //~ ERROR explicit use of destructor method + } +} + +fn main() { + let x = Foo { x: 3 }; + println!("{}", x.x); +} diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr new file mode 100644 index 000000000..7f5106eb5 --- /dev/null +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr @@ -0,0 +1,12 @@ +error[E0040]: explicit use of destructor method + --> $DIR/explicit-call-to-supertrait-dtor.rs:19:14 + | +LL | self.drop(); + | -----^^^^-- + | | | + | | explicit destructor calls not allowed + | help: consider using `drop` function: `drop(self)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/explicit/explicit-self-lifetime-mismatch.rs b/tests/ui/explicit/explicit-self-lifetime-mismatch.rs new file mode 100644 index 000000000..a9a6f50fb --- /dev/null +++ b/tests/ui/explicit/explicit-self-lifetime-mismatch.rs @@ -0,0 +1,20 @@ +struct Foo<'a,'b> { + x: &'a isize, + y: &'b isize, +} + +impl<'a,'b> Foo<'a,'b> { + fn bar(self: + Foo<'b,'a> + //~^ ERROR mismatched `self` parameter type + //~| expected struct `Foo<'a, 'b>` + //~| found struct `Foo<'b, 'a>` + //~| lifetime mismatch + //~| ERROR mismatched `self` parameter type + //~| expected struct `Foo<'a, 'b>` + //~| found struct `Foo<'b, 'a>` + //~| lifetime mismatch + ) {} +} + +fn main() {} diff --git a/tests/ui/explicit/explicit-self-lifetime-mismatch.stderr b/tests/ui/explicit/explicit-self-lifetime-mismatch.stderr new file mode 100644 index 000000000..d5ffa8f1b --- /dev/null +++ b/tests/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched `self` parameter type + --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 + | +LL | Foo<'b,'a> + | ^^^^^^^^^^ lifetime mismatch + | + = note: expected struct `Foo<'a, 'b>` + found struct `Foo<'b, 'a>` +note: the lifetime `'b` as defined here... + --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 + | +LL | impl<'a,'b> Foo<'a,'b> { + | ^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 + | +LL | impl<'a,'b> Foo<'a,'b> { + | ^^ + +error[E0308]: mismatched `self` parameter type + --> $DIR/explicit-self-lifetime-mismatch.rs:8:12 + | +LL | Foo<'b,'a> + | ^^^^^^^^^^ lifetime mismatch + | + = note: expected struct `Foo<'a, 'b>` + found struct `Foo<'b, 'a>` +note: the lifetime `'a` as defined here... + --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 + | +LL | impl<'a,'b> Foo<'a,'b> { + | ^^ +note: ...does not necessarily outlive the lifetime `'b` as defined here + --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 + | +LL | impl<'a,'b> Foo<'a,'b> { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/explore-issue-38412.rs b/tests/ui/explore-issue-38412.rs new file mode 100644 index 000000000..46d952df7 --- /dev/null +++ b/tests/ui/explore-issue-38412.rs @@ -0,0 +1,64 @@ +// aux-build:pub-and-stability.rs + +// A big point of this test is that we *declare* `unstable_declared`, +// but do *not* declare `unstable_undeclared`. This way we can check +// that the compiler is letting in uses of declared feature-gated +// stuff but still rejecting uses of undeclared feature-gated stuff. +#![feature(unstable_declared)] + +extern crate pub_and_stability; +use pub_and_stability::{Record, Trait, Tuple}; + +fn main() { + // Okay + let Record { .. } = Record::new(); + + // Okay + let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new(); + + let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = + Record::new(); + //~^^ ERROR use of unstable library feature 'unstable_undeclared' + + let r = Record::new(); + let t = Tuple::new(); + + r.a_stable_pub; + r.a_unstable_declared_pub; + r.a_unstable_undeclared_pub; //~ ERROR use of unstable library feature + r.b_crate; //~ ERROR is private + r.c_mod; //~ ERROR is private + r.d_priv; //~ ERROR is private + + t.0; + t.1; + t.2; //~ ERROR use of unstable library feature + t.3; //~ ERROR is private + t.4; //~ ERROR is private + t.5; //~ ERROR is private + + r.stable_trait_method(); + r.unstable_declared_trait_method(); + r.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature + + r.stable(); + r.unstable_declared(); + r.unstable_undeclared(); //~ ERROR use of unstable library feature + + r.pub_crate(); //~ ERROR `pub_crate` is private + r.pub_mod(); //~ ERROR `pub_mod` is private + r.private(); //~ ERROR `private` is private + + let t = Tuple::new(); + t.stable_trait_method(); + t.unstable_declared_trait_method(); + t.unstable_undeclared_trait_method(); //~ ERROR use of unstable library feature + + t.stable(); + t.unstable_declared(); + t.unstable_undeclared(); //~ ERROR use of unstable library feature + + t.pub_crate(); //~ ERROR `pub_crate` is private + t.pub_mod(); //~ ERROR `pub_mod` is private + t.private(); //~ ERROR `private` is private +} diff --git a/tests/ui/explore-issue-38412.stderr b/tests/ui/explore-issue-38412.stderr new file mode 100644 index 000000000..08dadb4db --- /dev/null +++ b/tests/ui/explore-issue-38412.stderr @@ -0,0 +1,169 @@ +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:19:63 + | +LL | let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:28:5 + | +LL | r.a_unstable_undeclared_pub; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0616]: field `b_crate` of struct `Record` is private + --> $DIR/explore-issue-38412.rs:29:7 + | +LL | r.b_crate; + | ^^^^^^^ private field + +error[E0616]: field `c_mod` of struct `Record` is private + --> $DIR/explore-issue-38412.rs:30:7 + | +LL | r.c_mod; + | ^^^^^ private field + +error[E0616]: field `d_priv` of struct `Record` is private + --> $DIR/explore-issue-38412.rs:31:7 + | +LL | r.d_priv; + | ^^^^^^ private field + +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:35:5 + | +LL | t.2; + | ^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0616]: field `3` of struct `pub_and_stability::Tuple` is private + --> $DIR/explore-issue-38412.rs:36:7 + | +LL | t.3; + | ^ private field + +error[E0616]: field `4` of struct `pub_and_stability::Tuple` is private + --> $DIR/explore-issue-38412.rs:37:7 + | +LL | t.4; + | ^ private field + +error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private + --> $DIR/explore-issue-38412.rs:38:7 + | +LL | t.5; + | ^ private field + +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:42:7 + | +LL | r.unstable_undeclared_trait_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:46:7 + | +LL | r.unstable_undeclared(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0624]: associated function `pub_crate` is private + --> $DIR/explore-issue-38412.rs:48:7 + | +LL | r.pub_crate(); + | ^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:114:9 + | +LL | pub(crate) fn pub_crate(&self) -> i32 { self.d_priv } + | ------------------------------------- private associated function defined here + +error[E0624]: associated function `pub_mod` is private + --> $DIR/explore-issue-38412.rs:49:7 + | +LL | r.pub_mod(); + | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:116:9 + | +LL | pub(in m) fn pub_mod(&self) -> i32 { self.d_priv } + | ---------------------------------- private associated function defined here + +error[E0624]: associated function `private` is private + --> $DIR/explore-issue-38412.rs:50:7 + | +LL | r.private(); + | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:118:9 + | +LL | fn private(&self) -> i32 { self.d_priv } + | ------------------------ private associated function defined here + +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:55:7 + | +LL | t.unstable_undeclared_trait_method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_undeclared' + --> $DIR/explore-issue-38412.rs:59:7 + | +LL | t.unstable_undeclared(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38412 for more information + = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable + +error[E0624]: associated function `pub_crate` is private + --> $DIR/explore-issue-38412.rs:61:7 + | +LL | t.pub_crate(); + | ^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:129:9 + | +LL | pub(crate) fn pub_crate(&self) -> i32 { self.0 } + | ------------------------------------- private associated function defined here + +error[E0624]: associated function `pub_mod` is private + --> $DIR/explore-issue-38412.rs:62:7 + | +LL | t.pub_mod(); + | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:130:9 + | +LL | pub(in m) fn pub_mod(&self) -> i32 { self.0 } + | ---------------------------------- private associated function defined here + +error[E0624]: associated function `private` is private + --> $DIR/explore-issue-38412.rs:63:7 + | +LL | t.private(); + | ^^^^^^^ private associated function + | + ::: $DIR/auxiliary/pub-and-stability.rs:131:9 + | +LL | fn private(&self) -> i32 { self.0 } + | ------------------------ private associated function defined here + +error: aborting due to 19 previous errors + +Some errors have detailed explanations: E0616, E0624, E0658. +For more information about an error, try `rustc --explain E0616`. diff --git a/tests/ui/expr-block-fn.rs b/tests/ui/expr-block-fn.rs new file mode 100644 index 000000000..1cac2cac0 --- /dev/null +++ b/tests/ui/expr-block-fn.rs @@ -0,0 +1,9 @@ +// run-pass + +fn test_fn() { + fn ten() -> isize { return 10; } + let rs = ten; + assert_eq!(rs(), 10); +} + +pub fn main() { test_fn(); } diff --git a/tests/ui/expr-block-generic-unique1.rs b/tests/ui/expr-block-generic-unique1.rs new file mode 100644 index 000000000..14603a2c7 --- /dev/null +++ b/tests/ui/expr-block-generic-unique1.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_braces)] + +fn test_generic(expected: Box, eq: F) where T: Clone, F: FnOnce(Box, Box) -> bool { + let actual: Box = { expected.clone() }; + assert!(eq(expected, actual)); +} + +fn test_box() { + fn compare_box(b1: Box, b2: Box) -> bool { + println!("{}", *b1); + println!("{}", *b2); + return *b1 == *b2; + } + test_generic::(Box::new(true), compare_box); +} + +pub fn main() { test_box(); } diff --git a/tests/ui/expr-block-generic-unique2.rs b/tests/ui/expr-block-generic-unique2.rs new file mode 100644 index 000000000..7879c144b --- /dev/null +++ b/tests/ui/expr-block-generic-unique2.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_braces)] + +fn test_generic(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool { + let actual: T = { expected.clone() }; + assert!(eq(expected, actual)); +} + +fn test_vec() { + fn compare_vec(v1: Box, v2: Box) -> bool { return v1 == v2; } + test_generic::, _>(Box::new(1), compare_vec); +} + +pub fn main() { test_vec(); } diff --git a/tests/ui/expr-block-generic.rs b/tests/ui/expr-block-generic.rs new file mode 100644 index 000000000..29c7c4221 --- /dev/null +++ b/tests/ui/expr-block-generic.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(unused_braces)] + +fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { + let actual: T = { expected.clone() }; + assert!(eq(expected, actual)); +} + +fn test_bool() { + fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } + test_generic::(true, compare_bool); +} + +#[derive(Clone)] +struct Pair { + a: isize, + b: isize, +} + +fn test_rec() { + fn compare_rec(t1: Pair, t2: Pair) -> bool { + t1.a == t2.a && t1.b == t2.b + } + test_generic::(Pair {a: 1, b: 2}, compare_rec); +} + +pub fn main() { test_bool(); test_rec(); } diff --git a/tests/ui/expr-block.rs b/tests/ui/expr-block.rs new file mode 100644 index 000000000..ff87595c9 --- /dev/null +++ b/tests/ui/expr-block.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_braces)] +#![allow(dead_code)] + +// Tests for standalone blocks as expressions + +fn test_basic() { let rs: bool = { true }; assert!((rs)); } + +struct RS { v1: isize, v2: isize } + +fn test_rec() { let rs = { RS {v1: 10, v2: 20} }; assert_eq!(rs.v2, 20); } + +fn test_filled_with_stuff() { + let rs = { let mut a = 0; while a < 10 { a += 1; } a }; + assert_eq!(rs, 10); +} + +pub fn main() { test_basic(); test_rec(); test_filled_with_stuff(); } diff --git a/tests/ui/expr-copy.rs b/tests/ui/expr-copy.rs new file mode 100644 index 000000000..1c6ae0381 --- /dev/null +++ b/tests/ui/expr-copy.rs @@ -0,0 +1,18 @@ +// run-pass + +fn f(arg: &mut A) { + arg.a = 100; +} + +#[derive(Copy, Clone)] +struct A { a: isize } + +pub fn main() { + let mut x = A {a: 10}; + f(&mut x); + assert_eq!(x.a, 100); + x.a = 20; + let mut y = x; + f(&mut y); + assert_eq!(x.a, 20); +} diff --git a/tests/ui/expr-if-generic.rs b/tests/ui/expr-if-generic.rs new file mode 100644 index 000000000..32ed6d9be --- /dev/null +++ b/tests/ui/expr-if-generic.rs @@ -0,0 +1,29 @@ +// run-pass + +fn test_generic(expected: T, not_expected: T, eq: F) where + T: Clone, + F: FnOnce(T, T) -> bool, +{ + let actual: T = if true { expected.clone() } else { not_expected }; + assert!(eq(expected, actual)); +} + +fn test_bool() { + fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } + test_generic::(true, false, compare_bool); +} + +#[derive(Clone)] +struct Pair { + a: isize, + b: isize, +} + +fn test_rec() { + fn compare_rec(t1: Pair, t2: Pair) -> bool { + t1.a == t2.a && t1.b == t2.b + } + test_generic::(Pair{a: 1, b: 2}, Pair{a: 2, b: 3}, compare_rec); +} + +pub fn main() { test_bool(); test_rec(); } diff --git a/tests/ui/expr-if-panic-all.rs b/tests/ui/expr-if-panic-all.rs new file mode 100644 index 000000000..f915a7d9d --- /dev/null +++ b/tests/ui/expr-if-panic-all.rs @@ -0,0 +1,11 @@ +// run-pass +// When all branches of an if expression result in panic, the entire if +// expression results in panic. + +pub fn main() { + let _x = if true { + 10 + } else { + if true { panic!() } else { panic!() } + }; +} diff --git a/tests/ui/expr-if-unique.rs b/tests/ui/expr-if-unique.rs new file mode 100644 index 000000000..862326835 --- /dev/null +++ b/tests/ui/expr-if-unique.rs @@ -0,0 +1,9 @@ +// run-pass + +// Tests for if as expressions returning boxed types +fn test_box() { + let rs: Box<_> = if true { Box::new(100) } else { Box::new(101) }; + assert_eq!(*rs, 100); +} + +pub fn main() { test_box(); } diff --git a/tests/ui/expr-scope.rs b/tests/ui/expr-scope.rs new file mode 100644 index 000000000..9976b6814 --- /dev/null +++ b/tests/ui/expr-scope.rs @@ -0,0 +1,7 @@ +// run-pass +// Regression test for issue #762 + +// pretty-expanded FIXME #23616 + +pub fn f() { } +pub fn main() { return ::f(); } diff --git a/tests/ui/expr/compound-assignment/eval-order.rs b/tests/ui/expr/compound-assignment/eval-order.rs new file mode 100644 index 000000000..658adae19 --- /dev/null +++ b/tests/ui/expr/compound-assignment/eval-order.rs @@ -0,0 +1,76 @@ +// Test evaluation order of operands of the compound assignment operators + +// run-pass + +use std::ops::AddAssign; + +enum Side { + Lhs, + Rhs, +} + +// In the following tests, we place our value into a wrapper type so that we +// can do an element access as the outer place expression. If we just had the +// block expression, it'd be a value expression and not compile. +struct Wrapper(T); + +// Evaluation order for `a op= b` where typeof(a) and typeof(b) are primitives +// is first `b` then `a`. +fn primitive_compound() { + let mut side_order = vec![]; + let mut int = Wrapper(0); + + { + side_order.push(Side::Lhs); + int + }.0 += { + side_order.push(Side::Rhs); + 0 + }; + + assert!(matches!(side_order[..], [Side::Rhs, Side::Lhs])); +} + +// Evaluation order for `a op=b` otherwise is first `a` then `b`. +fn generic_compound + Default>() { + let mut side_order = vec![]; + let mut add_assignable: Wrapper = Wrapper(Default::default()); + + { + side_order.push(Side::Lhs); + add_assignable + }.0 += { + side_order.push(Side::Rhs); + Default::default() + }; + + assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs])); +} + +fn custom_compound() { + struct Custom; + + impl AddAssign<()> for Custom { + fn add_assign(&mut self, _: ()) { + // this block purposely left blank + } + } + + let mut side_order = vec![]; + let mut custom = Wrapper(Custom); + + { + side_order.push(Side::Lhs); + custom + }.0 += { + side_order.push(Side::Rhs); + }; + + assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs])); +} + +fn main() { + primitive_compound(); + generic_compound::(); + custom_compound(); +} diff --git a/tests/ui/expr/if-bot.rs b/tests/ui/expr/if-bot.rs new file mode 100644 index 000000000..0f09db530 --- /dev/null +++ b/tests/ui/expr/if-bot.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let i: isize = if false { panic!() } else { 5 }; + println!("{}", i); +} diff --git a/tests/ui/expr/if/attrs/bad-cfg.rs b/tests/ui/expr/if/attrs/bad-cfg.rs new file mode 100644 index 000000000..3f84929a0 --- /dev/null +++ b/tests/ui/expr/if/attrs/bad-cfg.rs @@ -0,0 +1,5 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression +} diff --git a/tests/ui/expr/if/attrs/bad-cfg.stderr b/tests/ui/expr/if/attrs/bad-cfg.stderr new file mode 100644 index 000000000..8a2890886 --- /dev/null +++ b/tests/ui/expr/if/attrs/bad-cfg.stderr @@ -0,0 +1,8 @@ +error: removing an expression is not supported in this position + --> $DIR/bad-cfg.rs:4:13 + | +LL | let _ = #[cfg(FALSE)] if true {}; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/expr/if/attrs/builtin-if-attr.rs b/tests/ui/expr/if/attrs/builtin-if-attr.rs new file mode 100644 index 000000000..7e2906615 --- /dev/null +++ b/tests/ui/expr/if/attrs/builtin-if-attr.rs @@ -0,0 +1,12 @@ +// check-pass + +fn main() { + #[allow(unused_variables)] + if true { + let a = 1; + } else if false { + let b = 1; + } else { + let c = 1; + } +} diff --git a/tests/ui/expr/if/attrs/cfg-false-if-attr.rs b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs new file mode 100644 index 000000000..1f77a1bb3 --- /dev/null +++ b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs @@ -0,0 +1,43 @@ +// check-pass + +#[cfg(FALSE)] +fn simple_attr() { + #[attr] if true {} + #[allow_warnings] if true {} +} + +#[cfg(FALSE)] +fn if_else_chain() { + #[first_attr] if true { + } else if false { + } else { + } +} + +#[cfg(FALSE)] +fn if_let() { + #[attr] if let Some(_) = Some(true) {} +} + +fn bar() { + #[cfg(FALSE)] + if true { + let x: () = true; // Should not error due to the #[cfg(FALSE)] + } + + #[cfg_attr(not(unset_attr), cfg(FALSE))] + if true { + let a: () = true; // Should not error due to the applied #[cfg(FALSE)] + } +} + +macro_rules! custom_macro { + ($expr:expr) => {} +} + +custom_macro! { + #[attr] if true {} +} + + +fn main() {} diff --git a/tests/ui/expr/if/attrs/else-attrs.rs b/tests/ui/expr/if/attrs/else-attrs.rs new file mode 100644 index 000000000..85da7cf6b --- /dev/null +++ b/tests/ui/expr/if/attrs/else-attrs.rs @@ -0,0 +1,25 @@ +#[cfg(FALSE)] +fn if_else_parse_error() { + if true { + } #[attr] else if false { //~ ERROR expected + } +} + +#[cfg(FALSE)] +fn else_attr_ifparse_error() { + if true { + } else #[attr] if false { //~ ERROR outer attributes are not allowed + } else { + } +} + +#[cfg(FALSE)] +fn else_parse_error() { + if true { + } else if false { + } #[attr] else { //~ ERROR expected + } +} + +fn main() { +} diff --git a/tests/ui/expr/if/attrs/else-attrs.stderr b/tests/ui/expr/if/attrs/else-attrs.stderr new file mode 100644 index 000000000..273337705 --- /dev/null +++ b/tests/ui/expr/if/attrs/else-attrs.stderr @@ -0,0 +1,26 @@ +error: expected expression, found keyword `else` + --> $DIR/else-attrs.rs:4:15 + | +LL | } #[attr] else if false { + | ^^^^ expected expression + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/else-attrs.rs:11:12 + | +LL | } else #[attr] if false { + | _______----_^^^^^^^_- + | | | | + | | | help: remove the attributes + | | the branch belongs to this `else` +LL | | } else { +LL | | } + | |_____- the attributes are attached to this branch + +error: expected expression, found keyword `else` + --> $DIR/else-attrs.rs:20:15 + | +LL | } #[attr] else { + | ^^^^ expected expression + +error: aborting due to 3 previous errors + diff --git a/tests/ui/expr/if/attrs/gate-whole-expr.rs b/tests/ui/expr/if/attrs/gate-whole-expr.rs new file mode 100644 index 000000000..63772d54b --- /dev/null +++ b/tests/ui/expr/if/attrs/gate-whole-expr.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + let x = 1; + + #[cfg(FALSE)] + if false { + x = 2; + } else if true { + x = 3; + } else { + x = 4; + } + assert_eq!(x, 1); +} diff --git a/tests/ui/expr/if/attrs/let-chains-attr.rs b/tests/ui/expr/if/attrs/let-chains-attr.rs new file mode 100644 index 000000000..2cd873114 --- /dev/null +++ b/tests/ui/expr/if/attrs/let-chains-attr.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(let_chains)] + +#[cfg(FALSE)] +fn foo() { + #[attr] + if let Some(_) = Some(true) && let Ok(_) = Ok(1) { + } else if let Some(false) = Some(true) { + } +} + +fn main() {} diff --git a/tests/ui/expr/if/attrs/stmt-expr-gated.rs b/tests/ui/expr/if/attrs/stmt-expr-gated.rs new file mode 100644 index 000000000..38599c8e6 --- /dev/null +++ b/tests/ui/expr/if/attrs/stmt-expr-gated.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions + } else if false { + } else { + }; +} diff --git a/tests/ui/expr/if/attrs/stmt-expr-gated.stderr b/tests/ui/expr/if/attrs/stmt-expr-gated.stderr new file mode 100644 index 000000000..47dac39a9 --- /dev/null +++ b/tests/ui/expr/if/attrs/stmt-expr-gated.stderr @@ -0,0 +1,12 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt-expr-gated.rs:2:13 + | +LL | let _ = #[deny(warnings)] if true { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/expr/if/bad-if-let-suggestion.rs b/tests/ui/expr/if/bad-if-let-suggestion.rs new file mode 100644 index 000000000..a8b2a2830 --- /dev/null +++ b/tests/ui/expr/if/bad-if-let-suggestion.rs @@ -0,0 +1,24 @@ +// FIXME(compiler-errors): This really should suggest `let` on the RHS of the +// `&&` operator, but that's kinda hard to do because of precedence. +// Instead, for now we just make sure not to suggest `if let let`. +fn a() { + if let x = 1 && i = 2 {} + //~^ ERROR cannot find value `i` in this scope + //~| ERROR `let` expressions in this position are unstable + //~| ERROR mismatched types + //~| ERROR `let` expressions are not supported here +} + +fn b() { + if (i + j) = i {} + //~^ ERROR cannot find value `i` in this scope + //~| ERROR cannot find value `i` in this scope + //~| ERROR cannot find value `j` in this scope +} + +fn c() { + if x[0] = 1 {} + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/tests/ui/expr/if/bad-if-let-suggestion.stderr b/tests/ui/expr/if/bad-if-let-suggestion.stderr new file mode 100644 index 000000000..3a53a20b4 --- /dev/null +++ b/tests/ui/expr/if/bad-if-let-suggestion.stderr @@ -0,0 +1,74 @@ +error: `let` expressions are not supported here + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:5:21 + | +LL | if let x = 1 && i = 2 {} + | ^ not found in this scope + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:9 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `j` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:13 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:18 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `x` in this scope + --> $DIR/bad-if-let-suggestion.rs:20:8 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if x[0] = 1 {} + | ^ help: a function with a similar name exists: `a` + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if let x = 1 && i == 2 {} + | + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0425, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/expr-if-panic-fn.rs b/tests/ui/expr/if/expr-if-panic-fn.rs new file mode 100644 index 000000000..36e49785a --- /dev/null +++ b/tests/ui/expr/if/expr-if-panic-fn.rs @@ -0,0 +1,20 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn f() -> ! { + panic!() +} + +fn g() -> isize { + let x = if true { + f() + } else { + 10 + }; + return x; +} + +fn main() { + g(); +} diff --git a/tests/ui/expr/if/expr-if-panic-pass.rs b/tests/ui/expr/if/expr-if-panic-pass.rs new file mode 100644 index 000000000..6069cd835 --- /dev/null +++ b/tests/ui/expr/if/expr-if-panic-pass.rs @@ -0,0 +1,18 @@ +// run-pass + +fn test_if_panic() { + let x = if false { panic!() } else { 10 }; + assert_eq!(x, 10); +} + +fn test_else_panic() { + let x = if true { 10 } else { panic!() }; + assert_eq!(x, 10); +} + +fn test_elseif_panic() { + let x = if false { 0 } else if false { panic!() } else { 10 }; + assert_eq!(x, 10); +} + +pub fn main() { test_if_panic(); test_else_panic(); test_elseif_panic(); } diff --git a/tests/ui/expr/if/expr-if-panic.rs b/tests/ui/expr/if/expr-if-panic.rs new file mode 100644 index 000000000..520ee0870 --- /dev/null +++ b/tests/ui/expr/if/expr-if-panic.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn main() { + let _x = if false { + 0 + } else if true { + panic!() + } else { + 10 + }; +} diff --git a/tests/ui/expr/if/expr-if.rs b/tests/ui/expr/if/expr-if.rs new file mode 100644 index 000000000..2b8474ff4 --- /dev/null +++ b/tests/ui/expr/if/expr-if.rs @@ -0,0 +1,52 @@ +// run-pass +// Tests for if as expressions + +fn test_if() { let rs: bool = if true { true } else { false }; assert!((rs)); } + +fn test_else() { + let rs: bool = if false { false } else { true }; + assert!((rs)); +} + +fn test_elseif1() { + let rs: bool = if true { true } else if true { false } else { false }; + assert!((rs)); +} + +fn test_elseif2() { + let rs: bool = if false { false } else if true { true } else { false }; + assert!((rs)); +} + +fn test_elseif3() { + let rs: bool = if false { false } else if false { false } else { true }; + assert!((rs)); +} + +fn test_inferrence() { + let rs = if true { true } else { false }; + assert!((rs)); +} + +fn test_if_as_if_condition() { + let rs1 = if if false { false } else { true } { true } else { false }; + assert!((rs1)); + let rs2 = if if true { false } else { true } { false } else { true }; + assert!((rs2)); +} + +fn test_if_as_block_result() { + let rs = if true { if false { false } else { true } } else { false }; + assert!((rs)); +} + +pub fn main() { + test_if(); + test_else(); + test_elseif1(); + test_elseif2(); + test_elseif3(); + test_inferrence(); + test_if_as_if_condition(); + test_if_as_block_result(); +} diff --git a/tests/ui/expr/if/if-branch-types.rs b/tests/ui/expr/if/if-branch-types.rs new file mode 100644 index 000000000..c125ba306 --- /dev/null +++ b/tests/ui/expr/if/if-branch-types.rs @@ -0,0 +1,5 @@ +fn main() { + let x = if true { 10i32 } else { 10u32 }; + //~^ ERROR `if` and `else` have incompatible types + //~| expected `i32`, found `u32` +} diff --git a/tests/ui/expr/if/if-branch-types.stderr b/tests/ui/expr/if/if-branch-types.stderr new file mode 100644 index 000000000..d2bba8821 --- /dev/null +++ b/tests/ui/expr/if/if-branch-types.stderr @@ -0,0 +1,16 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-branch-types.rs:2:38 + | +LL | let x = if true { 10i32 } else { 10u32 }; + | ----- ^^^^^ expected `i32`, found `u32` + | | + | expected because of this + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | let x = if true { 10i32 } else { 10i32 }; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-check-panic.rs b/tests/ui/expr/if/if-check-panic.rs new file mode 100644 index 000000000..037cd427c --- /dev/null +++ b/tests/ui/expr/if/if-check-panic.rs @@ -0,0 +1,25 @@ +// run-fail +// error-pattern:Number is odd +// ignore-emscripten no processes + +fn even(x: usize) -> bool { + if x < 2 { + return false; + } else if x == 2 { + return true; + } else { + return even(x - 2); + } +} + +fn foo(x: usize) { + if even(x) { + println!("{}", x); + } else { + panic!("Number is odd"); + } +} + +fn main() { + foo(3); +} diff --git a/tests/ui/expr/if/if-check.rs b/tests/ui/expr/if/if-check.rs new file mode 100644 index 000000000..6593225e7 --- /dev/null +++ b/tests/ui/expr/if/if-check.rs @@ -0,0 +1,17 @@ +// run-pass + +fn even(x: usize) -> bool { + if x < 2 { + return false; + } else if x == 2 { return true; } else { return even(x - 2); } +} + +fn foo(x: usize) { + if even(x) { + println!("{}", x); + } else { + panic!(); + } +} + +pub fn main() { foo(2); } diff --git a/tests/ui/expr/if/if-cond-bot.rs b/tests/ui/expr/if/if-cond-bot.rs new file mode 100644 index 000000000..bcd114678 --- /dev/null +++ b/tests/ui/expr/if/if-cond-bot.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn my_err(s: String) -> ! { + println!("{}", s); + panic!("quux"); +} + +fn main() { + if my_err("bye".to_string()) { + } +} diff --git a/tests/ui/expr/if/if-else-type-mismatch.rs b/tests/ui/expr/if/if-else-type-mismatch.rs new file mode 100644 index 000000000..1a0a36df2 --- /dev/null +++ b/tests/ui/expr/if/if-else-type-mismatch.rs @@ -0,0 +1,46 @@ +fn main() { + let _ = if true { + 1i32 + } else { + 2u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { 42i32 } else { 42u32 }; + //~^ ERROR `if` and `else` have incompatible types + let _ = if true { + 3u32; + } else { + 4u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 5u32 + } else { + 6u32; + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 7i32; + } else { + 8u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 9i32 + } else { + 10u32; + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + + } else { + 11u32 + }; + //~^^ ERROR `if` and `else` have incompatible types + let _ = if true { + 12i32 + } else { + + }; + //~^^^ ERROR `if` and `else` have incompatible types +} diff --git a/tests/ui/expr/if/if-else-type-mismatch.stderr b/tests/ui/expr/if/if-else-type-mismatch.stderr new file mode 100644 index 000000000..f1fffdb1e --- /dev/null +++ b/tests/ui/expr/if/if-else-type-mismatch.stderr @@ -0,0 +1,116 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:5:9 + | +LL | let _ = if true { + | _____________- +LL | | 1i32 + | | ---- expected because of this +LL | | } else { +LL | | 2u32 + | | ^^^^ expected `i32`, found `u32` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 2i32 + | ~~~ + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:8:38 + | +LL | let _ = if true { 42i32 } else { 42u32 }; + | ----- ^^^^^ expected `i32`, found `u32` + | | + | expected because of this + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | let _ = if true { 42i32 } else { 42i32 }; + | ~~~ + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:13:9 + | +LL | let _ = if true { + | _____________- +LL | | 3u32; + | | ----- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | } else { +LL | | 4u32 + | | ^^^^ expected `()`, found `u32` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:19:9 + | +LL | let _ = if true { + | _____________- +LL | | 5u32 + | | ---- expected because of this +LL | | } else { +LL | | 6u32; + | | ^^^^- + | | | | + | | | help: consider removing this semicolon + | | expected `u32`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:25:9 + | +LL | let _ = if true { + | _____________- +LL | | 7i32; + | | ----- expected because of this +LL | | } else { +LL | | 8u32 + | | ^^^^ expected `()`, found `u32` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:31:9 + | +LL | let _ = if true { + | _____________- +LL | | 9i32 + | | ---- expected because of this +LL | | } else { +LL | | 10u32; + | | ^^^^^^ expected `i32`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:37:9 + | +LL | let _ = if true { + | _____________________- +LL | | +LL | | } else { + | |_____- expected because of this +LL | 11u32 + | ^^^^^ expected `()`, found `u32` + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-else-type-mismatch.rs:42:12 + | +LL | let _ = if true { + | ------- `if` and `else` have incompatible types +LL | 12i32 + | ----- expected because of this +LL | } else { + | ____________^ +LL | | +LL | | }; + | |_____^ expected `i32`, found `()` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-let-arm-types.rs b/tests/ui/expr/if/if-let-arm-types.rs new file mode 100644 index 000000000..1e8260a01 --- /dev/null +++ b/tests/ui/expr/if/if-let-arm-types.rs @@ -0,0 +1,11 @@ +fn main() { + if let Some(b) = None { + //~^ NOTE `if` and `else` have incompatible types + () + //~^ NOTE expected because of this + } else { + 1 + }; + //~^^ ERROR: `if` and `else` have incompatible types + //~| NOTE expected `()`, found integer +} diff --git a/tests/ui/expr/if/if-let-arm-types.stderr b/tests/ui/expr/if/if-let-arm-types.stderr new file mode 100644 index 000000000..b40a0f479 --- /dev/null +++ b/tests/ui/expr/if/if-let-arm-types.stderr @@ -0,0 +1,17 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-let-arm-types.rs:7:9 + | +LL | / if let Some(b) = None { +LL | | +LL | | () + | | -- expected because of this +LL | | +LL | | } else { +LL | | 1 + | | ^ expected `()`, found integer +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-let.rs b/tests/ui/expr/if/if-let.rs new file mode 100644 index 000000000..7fdd2be95 --- /dev/null +++ b/tests/ui/expr/if/if-let.rs @@ -0,0 +1,49 @@ +// check-pass + +fn macros() { + macro_rules! foo { + ($p:pat, $e:expr, $b:block) => {{ + if let $p = $e $b + //~^ WARN irrefutable `if let` + //~| WARN irrefutable `if let` + }} + } + macro_rules! bar{ + ($p:pat, $e:expr, $b:block) => {{ + foo!($p, $e, $b) + }} + } + + foo!(a, 1, { + println!("irrefutable pattern"); + }); + bar!(a, 1, { + println!("irrefutable pattern"); + }); +} + +pub fn main() { + if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } + + if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } else if true { + println!("else-if in irrefutable `if let`"); + } else { + println!("else in irrefutable `if let`"); + } + + if let 1 = 2 { + println!("refutable pattern"); + } else if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } + + if true { + println!("if"); + } else if let a = 1 { //~ WARN irrefutable `if let` + println!("irrefutable pattern"); + } +} diff --git a/tests/ui/expr/if/if-let.stderr b/tests/ui/expr/if/if-let.stderr new file mode 100644 index 000000000..c4bba3cb1 --- /dev/null +++ b/tests/ui/expr/if/if-let.stderr @@ -0,0 +1,69 @@ +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:6:16 + | +LL | if let $p = $e $b + | ^^^ +... +LL | / foo!(a, 1, { +LL | | println!("irrefutable pattern"); +LL | | }); + | |______- in this macro invocation + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:6:16 + | +LL | if let $p = $e $b + | ^^^ +... +LL | / bar!(a, 1, { +LL | | println!("irrefutable pattern"); +LL | | }); + | |______- in this macro invocation + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: this warning originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:26:8 + | +LL | if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:30:8 + | +LL | if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:40:15 + | +LL | } else if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: irrefutable `if let` pattern + --> $DIR/if-let.rs:46:15 + | +LL | } else if let a = 1 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +warning: 6 warnings emitted + diff --git a/tests/ui/expr/if/if-loop.rs b/tests/ui/expr/if/if-loop.rs new file mode 100644 index 000000000..06d0bdf45 --- /dev/null +++ b/tests/ui/expr/if/if-loop.rs @@ -0,0 +1,8 @@ +// check-pass + +// This used to ICE because the "if" being unreachable was not handled correctly +fn err() { + if loop {} {} +} + +fn main() {} diff --git a/tests/ui/expr/if/if-no-match-bindings.rs b/tests/ui/expr/if/if-no-match-bindings.rs new file mode 100644 index 000000000..ca3df0fdd --- /dev/null +++ b/tests/ui/expr/if/if-no-match-bindings.rs @@ -0,0 +1,28 @@ +// Checks for `if` expressions with respect to default match bindings. +// Specifically, we do not accept `if cond { ... }` where `cond: &mut? bool`. +// Meanwhile, `match cond { true => ..., _ => ... }` does accept that. + +// FIXME(@rust-lang/lang-team): consider relaxing this? + +fn b_ref<'a>() -> &'a bool { &true } +fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + +fn main() { + // This is OK: + match b_ref() { true => {}, _ => {} } + match b_mut_ref() { true => {}, _ => {} } + match &true { true => {}, _ => {} } + match &mut true { true => {}, _ => {} } + + // This is NOT: + if b_ref() {} //~ ERROR mismatched types [E0308] + if b_mut_ref() {} //~ ERROR mismatched types [E0308] + if &true {} //~ ERROR mismatched types [E0308] + if &mut true {} //~ ERROR mismatched types [E0308] + + // This is also NOT: + while b_ref() {} //~ ERROR mismatched types [E0308] + while b_mut_ref() {} //~ ERROR mismatched types [E0308] + while &true {} //~ ERROR mismatched types [E0308] + while &mut true {} //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr new file mode 100644 index 000000000..737a5d604 --- /dev/null +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -0,0 +1,95 @@ +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:18:8 + | +LL | if b_ref() {} + | ^^^^^^^ expected `bool`, found `&bool` + | +help: consider dereferencing the borrow + | +LL | if *b_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:19:8 + | +LL | if b_mut_ref() {} + | ^^^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider dereferencing the borrow + | +LL | if *b_mut_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:20:8 + | +LL | if &true {} + | ^^^^^ expected `bool`, found `&bool` + | +help: consider removing the borrow + | +LL - if &true {} +LL + if true {} + | + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:21:8 + | +LL | if &mut true {} + | ^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider removing the borrow + | +LL - if &mut true {} +LL + if true {} + | + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:24:11 + | +LL | while b_ref() {} + | ^^^^^^^ expected `bool`, found `&bool` + | +help: consider dereferencing the borrow + | +LL | while *b_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:25:11 + | +LL | while b_mut_ref() {} + | ^^^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider dereferencing the borrow + | +LL | while *b_mut_ref() {} + | + + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:26:11 + | +LL | while &true {} + | ^^^^^ expected `bool`, found `&bool` + | +help: consider removing the borrow + | +LL - while &true {} +LL + while true {} + | + +error[E0308]: mismatched types + --> $DIR/if-no-match-bindings.rs:27:11 + | +LL | while &mut true {} + | ^^^^^^^^^ expected `bool`, found `&mut bool` + | +help: consider removing the borrow + | +LL - while &mut true {} +LL + while true {} + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-ret.rs b/tests/ui/expr/if/if-ret.rs new file mode 100644 index 000000000..896072ce7 --- /dev/null +++ b/tests/ui/expr/if/if-ret.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(unused_parens)] +// pretty-expanded FIXME #23616 + +fn foo() { if (return) { } } //~ WARNING unreachable block in `if` + +pub fn main() { foo(); } diff --git a/tests/ui/expr/if/if-ret.stderr b/tests/ui/expr/if/if-ret.stderr new file mode 100644 index 000000000..8ced271aa --- /dev/null +++ b/tests/ui/expr/if/if-ret.stderr @@ -0,0 +1,12 @@ +warning: unreachable block in `if` or `while` expression + --> $DIR/if-ret.rs:6:24 + | +LL | fn foo() { if (return) { } } + | -------- ^^^ unreachable block in `if` or `while` expression + | | + | any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/expr/if/if-typeck.rs b/tests/ui/expr/if/if-typeck.rs new file mode 100644 index 000000000..d8c262bd6 --- /dev/null +++ b/tests/ui/expr/if/if-typeck.rs @@ -0,0 +1,10 @@ +// error-pattern:mismatched types +// issue #513 + +fn f() { } + +fn main() { + + // f is not a bool + if f { } +} diff --git a/tests/ui/expr/if/if-typeck.stderr b/tests/ui/expr/if/if-typeck.stderr new file mode 100644 index 000000000..74ed0ed0a --- /dev/null +++ b/tests/ui/expr/if/if-typeck.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/if-typeck.rs:9:8 + | +LL | if f { } + | ^ expected `bool`, found fn item + | + = note: expected type `bool` + found fn item `fn() {f}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-without-block.rs b/tests/ui/expr/if/if-without-block.rs new file mode 100644 index 000000000..5add9dfda --- /dev/null +++ b/tests/ui/expr/if/if-without-block.rs @@ -0,0 +1,7 @@ +fn main() { + let n = 1; + if 5 == { + //~^ ERROR this `if` expression is missing a block after the condition + println!("five"); + } +} diff --git a/tests/ui/expr/if/if-without-block.stderr b/tests/ui/expr/if/if-without-block.stderr new file mode 100644 index 000000000..2d1ee04ce --- /dev/null +++ b/tests/ui/expr/if/if-without-block.stderr @@ -0,0 +1,14 @@ +error: this `if` expression is missing a block after the condition + --> $DIR/if-without-block.rs:3:5 + | +LL | if 5 == { + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/if-without-block.rs:3:8 + | +LL | if 5 == { + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/expr/if/if-without-else-as-fn-expr.rs b/tests/ui/expr/if/if-without-else-as-fn-expr.rs new file mode 100644 index 000000000..19fbfb27b --- /dev/null +++ b/tests/ui/expr/if/if-without-else-as-fn-expr.rs @@ -0,0 +1,49 @@ +fn foo(bar: usize) -> usize { + if bar % 5 == 0 { + return 3; + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +fn foo2(bar: usize) -> usize { + let x: usize = if bar % 5 == 0 { + return 3; + }; + //~^^^ ERROR `if` may be missing an `else` clause + x +} + +fn foo3(bar: usize) -> usize { + if bar % 5 == 0 { + 3 + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +fn foo_let(bar: usize) -> usize { + if let 0 = 1 { + return 3; + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +fn foo2_let(bar: usize) -> usize { + let x: usize = if let 0 = 1 { + return 3; + }; + //~^^^ ERROR `if` may be missing an `else` clause + x +} + +fn foo3_let(bar: usize) -> usize { + if let 0 = 1 { + 3 + } + //~^^^ ERROR `if` may be missing an `else` clause +} + +// FIXME(60254): deduplicate first error in favor of second. + +fn main() { + let _ = foo(1); +} diff --git a/tests/ui/expr/if/if-without-else-as-fn-expr.stderr b/tests/ui/expr/if/if-without-else-as-fn-expr.stderr new file mode 100644 index 000000000..4daf27493 --- /dev/null +++ b/tests/ui/expr/if/if-without-else-as-fn-expr.stderr @@ -0,0 +1,83 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:2:5 + | +LL | fn foo(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if bar % 5 == 0 { +LL | | return 3; +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:9:20 + | +LL | let x: usize = if bar % 5 == 0 { + | _________-__________^ + | | | + | | expected because of this assignment +LL | | return 3; +LL | | }; + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:17:5 + | +LL | fn foo3(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if bar % 5 == 0 { +LL | | 3 +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:24:5 + | +LL | fn foo_let(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if let 0 = 1 { +LL | | return 3; +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:31:20 + | +LL | let x: usize = if let 0 = 1 { + | _________-__________^ + | | | + | | expected because of this assignment +LL | | return 3; +LL | | }; + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-as-fn-expr.rs:39:5 + | +LL | fn foo3_let(bar: usize) -> usize { + | ----- expected `usize` because of this return type +LL | / if let 0 = 1 { +LL | | 3 +LL | | } + | |_____^ expected `usize`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/if/if-without-else-result.rs b/tests/ui/expr/if/if-without-else-result.rs new file mode 100644 index 000000000..95604758a --- /dev/null +++ b/tests/ui/expr/if/if-without-else-result.rs @@ -0,0 +1,6 @@ +fn main() { + let a = if true { true }; + //~^ ERROR `if` may be missing an `else` clause [E0317] + //~| expected `bool`, found `()` + println!("{}", a); +} diff --git a/tests/ui/expr/if/if-without-else-result.stderr b/tests/ui/expr/if/if-without-else-result.stderr new file mode 100644 index 000000000..317faf7c6 --- /dev/null +++ b/tests/ui/expr/if/if-without-else-result.stderr @@ -0,0 +1,15 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/if-without-else-result.rs:2:13 + | +LL | let a = if true { true }; + | ^^^^^^^^^^----^^ + | | | + | | found here + | expected `bool`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/if/issue-4201.rs b/tests/ui/expr/if/issue-4201.rs new file mode 100644 index 000000000..59c465b9e --- /dev/null +++ b/tests/ui/expr/if/issue-4201.rs @@ -0,0 +1,9 @@ +fn main() { + let a = if true { + 0 + } else if false { +//~^ ERROR `if` may be missing an `else` clause +//~| expected integer, found `()` + 1 + }; +} diff --git a/tests/ui/expr/if/issue-4201.stderr b/tests/ui/expr/if/issue-4201.stderr new file mode 100644 index 000000000..612fe7764 --- /dev/null +++ b/tests/ui/expr/if/issue-4201.stderr @@ -0,0 +1,18 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/issue-4201.rs:4:12 + | +LL | } else if false { + | ____________^ +LL | | +LL | | +LL | | 1 + | | - found here +LL | | }; + | |_____^ expected integer, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed b/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed new file mode 100644 index 000000000..c50b9a12b --- /dev/null +++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed @@ -0,0 +1,19 @@ +// This snippet ensures that no attempt to recover on a semicolon instead of +// comma is made next to a closure body. +// +// If this recovery happens, then plenty of errors are emitted. Here, we expect +// only one error. +// +// This is part of issue #88065: +// https://github.com/rust-lang/rust/issues/88065 + +// run-rustfix + +fn main() { + let num = 5; + (1..num).reduce(|a, b| { + //~^ ERROR: closure bodies that contain statements must be surrounded by braces + println!("{}", a); + a * b + }).unwrap(); +} diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.rs b/tests/ui/expr/malformed_closure/missing_braces_around_block.rs new file mode 100644 index 000000000..58c81f3a6 --- /dev/null +++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.rs @@ -0,0 +1,19 @@ +// This snippet ensures that no attempt to recover on a semicolon instead of +// comma is made next to a closure body. +// +// If this recovery happens, then plenty of errors are emitted. Here, we expect +// only one error. +// +// This is part of issue #88065: +// https://github.com/rust-lang/rust/issues/88065 + +// run-rustfix + +fn main() { + let num = 5; + (1..num).reduce(|a, b| + //~^ ERROR: closure bodies that contain statements must be surrounded by braces + println!("{}", a); + a * b + ).unwrap(); +} diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr b/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr new file mode 100644 index 000000000..dac9a8cfc --- /dev/null +++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr @@ -0,0 +1,38 @@ +error: closure bodies that contain statements must be surrounded by braces + --> $DIR/missing_braces_around_block.rs:14:26 + | +LL | (1..num).reduce(|a, b| + | ^ +... +LL | ).unwrap(); + | ^ + | +note: statement found outside of a block + --> $DIR/missing_braces_around_block.rs:16:26 + | +LL | println!("{}", a); + | -----------------^ this `;` turns the preceding closure into a statement + | | + | this expression is a statement because of the trailing semicolon +note: the closure body may be incorrectly delimited + --> $DIR/missing_braces_around_block.rs:14:21 + | +LL | (1..num).reduce(|a, b| + | _____________________^ +LL | | +LL | | println!("{}", a); + | |_________________________^ this is the parsed closure... +LL | a * b +LL | ).unwrap(); + | - ...but likely you meant the closure to end here +help: try adding braces + | +LL ~ (1..num).reduce(|a, b| { +LL | +LL | println!("{}", a); +LL | a * b +LL ~ }).unwrap(); + | + +error: aborting due to previous error + diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure.rs b/tests/ui/expr/malformed_closure/ruby_style_closure.rs new file mode 100644 index 000000000..fdec072b8 --- /dev/null +++ b/tests/ui/expr/malformed_closure/ruby_style_closure.rs @@ -0,0 +1,15 @@ +// Part of issue #27300. +// The problem here is that ruby-style closures are parsed as blocks whose +// first statement is a closure. See the issue for more details: +// https://github.com/rust-lang/rust/issues/27300 + +// Note: this test represents what the compiler currently emits. The error +// message will be improved later. + +fn main() { + let p = Some(45).and_then({ + |x| println!("doubling {}", x); + Some(x * 2) + //~^ ERROR: cannot find value `x` in this scope + }); +} diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure.stderr new file mode 100644 index 000000000..e8b34121b --- /dev/null +++ b/tests/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/ruby_style_closure.rs:12:14 + | +LL | Some(x * 2) + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/ext-expand-inner-exprs.rs b/tests/ui/ext-expand-inner-exprs.rs new file mode 100644 index 000000000..5bbdf5ec9 --- /dev/null +++ b/tests/ui/ext-expand-inner-exprs.rs @@ -0,0 +1,7 @@ +// run-pass + +static FOO : &'static str = concat!(concat!("hel", "lo"), "world"); + +pub fn main() { + assert_eq!(FOO, "helloworld"); +} diff --git a/tests/ui/ext-nonexistent.rs b/tests/ui/ext-nonexistent.rs new file mode 100644 index 000000000..e65b16543 --- /dev/null +++ b/tests/ui/ext-nonexistent.rs @@ -0,0 +1,2 @@ +// error-pattern:cannot find macro +fn main() { iamnotanextensionthatexists!(""); } diff --git a/tests/ui/ext-nonexistent.stderr b/tests/ui/ext-nonexistent.stderr new file mode 100644 index 000000000..f3aa83fd5 --- /dev/null +++ b/tests/ui/ext-nonexistent.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `iamnotanextensionthatexists` in this scope + --> $DIR/ext-nonexistent.rs:2:13 + | +LL | fn main() { iamnotanextensionthatexists!(""); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/extenv/extenv-arg-2-not-string-literal.rs b/tests/ui/extenv/extenv-arg-2-not-string-literal.rs new file mode 100644 index 000000000..66dced478 --- /dev/null +++ b/tests/ui/extenv/extenv-arg-2-not-string-literal.rs @@ -0,0 +1 @@ +fn main() { env!("one", 10); } //~ ERROR: expected string literal diff --git a/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr b/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr new file mode 100644 index 000000000..258e2b347 --- /dev/null +++ b/tests/ui/extenv/extenv-arg-2-not-string-literal.stderr @@ -0,0 +1,8 @@ +error: expected string literal + --> $DIR/extenv-arg-2-not-string-literal.rs:1:25 + | +LL | fn main() { env!("one", 10); } + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/extenv/extenv-no-args.rs b/tests/ui/extenv/extenv-no-args.rs new file mode 100644 index 000000000..9f221ed10 --- /dev/null +++ b/tests/ui/extenv/extenv-no-args.rs @@ -0,0 +1 @@ +fn main() { env!(); } //~ ERROR: env! takes 1 or 2 arguments diff --git a/tests/ui/extenv/extenv-no-args.stderr b/tests/ui/extenv/extenv-no-args.stderr new file mode 100644 index 000000000..318ed635b --- /dev/null +++ b/tests/ui/extenv/extenv-no-args.stderr @@ -0,0 +1,8 @@ +error: env! takes 1 or 2 arguments + --> $DIR/extenv-no-args.rs:1:13 + | +LL | fn main() { env!(); } + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/extenv/extenv-not-defined-custom.rs b/tests/ui/extenv/extenv-not-defined-custom.rs new file mode 100644 index 000000000..30b72783f --- /dev/null +++ b/tests/ui/extenv/extenv-not-defined-custom.rs @@ -0,0 +1 @@ +fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } //~ ERROR: my error message diff --git a/tests/ui/extenv/extenv-not-defined-custom.stderr b/tests/ui/extenv/extenv-not-defined-custom.stderr new file mode 100644 index 000000000..e7da4e046 --- /dev/null +++ b/tests/ui/extenv/extenv-not-defined-custom.stderr @@ -0,0 +1,10 @@ +error: my error message + --> $DIR/extenv-not-defined-custom.rs:1:13 + | +LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/extenv/extenv-not-defined-default.rs b/tests/ui/extenv/extenv-not-defined-default.rs new file mode 100644 index 000000000..30a06a254 --- /dev/null +++ b/tests/ui/extenv/extenv-not-defined-default.rs @@ -0,0 +1,4 @@ +fn main() { + env!("__HOPEFULLY_NOT_DEFINED__"); + //~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined +} diff --git a/tests/ui/extenv/extenv-not-defined-default.stderr b/tests/ui/extenv/extenv-not-defined-default.stderr new file mode 100644 index 000000000..884875dca --- /dev/null +++ b/tests/ui/extenv/extenv-not-defined-default.stderr @@ -0,0 +1,10 @@ +error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined + --> $DIR/extenv-not-defined-default.rs:2:5 + | +LL | env!("__HOPEFULLY_NOT_DEFINED__"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/extenv/extenv-not-string-literal.rs b/tests/ui/extenv/extenv-not-string-literal.rs new file mode 100644 index 000000000..3eaa0b5da --- /dev/null +++ b/tests/ui/extenv/extenv-not-string-literal.rs @@ -0,0 +1 @@ +fn main() { env!(10, "two"); } //~ ERROR: expected string literal diff --git a/tests/ui/extenv/extenv-not-string-literal.stderr b/tests/ui/extenv/extenv-not-string-literal.stderr new file mode 100644 index 000000000..342a9f709 --- /dev/null +++ b/tests/ui/extenv/extenv-not-string-literal.stderr @@ -0,0 +1,8 @@ +error: expected string literal + --> $DIR/extenv-not-string-literal.rs:1:18 + | +LL | fn main() { env!(10, "two"); } + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/extenv/extenv-too-many-args.rs b/tests/ui/extenv/extenv-too-many-args.rs new file mode 100644 index 000000000..1adbee583 --- /dev/null +++ b/tests/ui/extenv/extenv-too-many-args.rs @@ -0,0 +1 @@ +fn main() { env!("one", "two", "three"); } //~ ERROR: env! takes 1 or 2 arguments diff --git a/tests/ui/extenv/extenv-too-many-args.stderr b/tests/ui/extenv/extenv-too-many-args.stderr new file mode 100644 index 000000000..54150a332 --- /dev/null +++ b/tests/ui/extenv/extenv-too-many-args.stderr @@ -0,0 +1,8 @@ +error: env! takes 1 or 2 arguments + --> $DIR/extenv-too-many-args.rs:1:13 + | +LL | fn main() { env!("one", "two", "three"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/extenv/issue-55897.rs b/tests/ui/extenv/issue-55897.rs new file mode 100644 index 000000000..b7533f413 --- /dev/null +++ b/tests/ui/extenv/issue-55897.rs @@ -0,0 +1,20 @@ +use prelude::*; //~ ERROR unresolved import `prelude` + +mod unresolved_env { + use env; //~ ERROR unresolved import `env` + + include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + //~^ ERROR cannot determine resolution for the macro `env` +} + +mod nonexistent_env { + include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + //~^ ERROR environment variable `NON_EXISTENT` not defined +} + +mod erroneous_literal { + include!(concat!("NON_EXISTENT"suffix, "/data.rs")); + //~^ ERROR suffixes on string literals are invalid +} + +fn main() {} diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr new file mode 100644 index 000000000..92e8a44b5 --- /dev/null +++ b/tests/ui/extenv/issue-55897.stderr @@ -0,0 +1,45 @@ +error: environment variable `NON_EXISTENT` not defined + --> $DIR/issue-55897.rs:11:22 + | +LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: suffixes on string literals are invalid + --> $DIR/issue-55897.rs:16:22 + | +LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs")); + | ^^^^^^^^^^^^^^^^^^^^ invalid suffix `suffix` + +error[E0432]: unresolved import `prelude` + --> $DIR/issue-55897.rs:1:5 + | +LL | use prelude::*; + | ^^^^^^^ + | | + | unresolved import + | help: a similar path exists: `std::prelude` + +error[E0432]: unresolved import `env` + --> $DIR/issue-55897.rs:4:9 + | +LL | use env; + | ^^^ no `env` in the root + | +help: consider importing this module instead + | +LL | use std::env; + | ~~~~~~~~ + +error: cannot determine resolution for the macro `env` + --> $DIR/issue-55897.rs:6:22 + | +LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/extern-flag/auxiliary/somedep.rs b/tests/ui/extern-flag/auxiliary/somedep.rs new file mode 100644 index 000000000..dd2f373f8 --- /dev/null +++ b/tests/ui/extern-flag/auxiliary/somedep.rs @@ -0,0 +1,3 @@ +pub fn somefun() {} + +pub struct S; diff --git a/tests/ui/extern-flag/empty-extern-arg.rs b/tests/ui/extern-flag/empty-extern-arg.rs new file mode 100644 index 000000000..2f4ae7d8e --- /dev/null +++ b/tests/ui/extern-flag/empty-extern-arg.rs @@ -0,0 +1,6 @@ +// compile-flags: --extern std= +// error-pattern: extern location for std does not exist +// needs-unwind since it affects the error output +// ignore-emscripten missing eh_catch_typeinfo lang item + +fn main() {} diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr new file mode 100644 index 000000000..54b5e66fc --- /dev/null +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -0,0 +1,11 @@ +error: extern location for std does not exist: + +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + | + = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library + = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/extern-flag/multiple-opts.rs b/tests/ui/extern-flag/multiple-opts.rs new file mode 100644 index 000000000..3dc2f1d73 --- /dev/null +++ b/tests/ui/extern-flag/multiple-opts.rs @@ -0,0 +1,20 @@ +// aux-crate:priv,noprelude:somedep=somedep.rs +// compile-flags: -Zunstable-options +// edition:2018 + +// Test for multiple options to --extern. Can't test for errors from both +// options at the same time, so this only checks that noprelude is honored. + +#![warn(exported_private_dependencies)] + +// Module to avoid adding to prelude. +pub mod m { + extern crate somedep; + pub struct PublicType { + pub field: somedep::S, + } +} + +fn main() { + somedep::somefun(); //~ ERROR failed to resolve +} diff --git a/tests/ui/extern-flag/multiple-opts.stderr b/tests/ui/extern-flag/multiple-opts.stderr new file mode 100644 index 000000000..5088fb1c4 --- /dev/null +++ b/tests/ui/extern-flag/multiple-opts.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `somedep` + --> $DIR/multiple-opts.rs:19:5 + | +LL | somedep::somefun(); + | ^^^^^^^ use of undeclared crate or module `somedep` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/extern-flag/no-nounused.rs b/tests/ui/extern-flag/no-nounused.rs new file mode 100644 index 000000000..5ec755952 --- /dev/null +++ b/tests/ui/extern-flag/no-nounused.rs @@ -0,0 +1,6 @@ +// aux-crate:somedep=somedep.rs +// compile-flags: -Zunstable-options -Dunused-crate-dependencies +// edition:2018 + +fn main() { //~ ERROR external crate `somedep` unused in `no_nounused` +} diff --git a/tests/ui/extern-flag/no-nounused.stderr b/tests/ui/extern-flag/no-nounused.stderr new file mode 100644 index 000000000..6446c5323 --- /dev/null +++ b/tests/ui/extern-flag/no-nounused.stderr @@ -0,0 +1,10 @@ +error: external crate `somedep` unused in `no_nounused`: remove the dependency or add `use somedep as _;` + --> $DIR/no-nounused.rs:5:1 + | +LL | fn main() { + | ^ + | + = note: requested on the command line with `-D unused-crate-dependencies` + +error: aborting due to previous error + diff --git a/tests/ui/extern-flag/noprelude-and-prelude.rs b/tests/ui/extern-flag/noprelude-and-prelude.rs new file mode 100644 index 000000000..e6a150b9e --- /dev/null +++ b/tests/ui/extern-flag/noprelude-and-prelude.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-crate:noprelude:somedep=somedep.rs +// compile-flags: -Zunstable-options --extern somedep +// edition:2018 + +// Having a flag with `noprelude` and one without, will add to the prelude. + +fn main() { + somedep::somefun(); +} diff --git a/tests/ui/extern-flag/noprelude-resolves.rs b/tests/ui/extern-flag/noprelude-resolves.rs new file mode 100644 index 000000000..f69f552b6 --- /dev/null +++ b/tests/ui/extern-flag/noprelude-resolves.rs @@ -0,0 +1,11 @@ +// check-pass +// aux-crate:noprelude:somedep=somedep.rs +// compile-flags: -Zunstable-options +// edition:2018 + +// `extern crate` can be used to add to prelude. +extern crate somedep; + +fn main() { + somedep::somefun(); +} diff --git a/tests/ui/extern-flag/noprelude.rs b/tests/ui/extern-flag/noprelude.rs new file mode 100644 index 000000000..cdbf34091 --- /dev/null +++ b/tests/ui/extern-flag/noprelude.rs @@ -0,0 +1,7 @@ +// aux-crate:noprelude:somedep=somedep.rs +// compile-flags: -Zunstable-options +// edition:2018 + +fn main() { + somedep::somefun(); //~ ERROR failed to resolve +} diff --git a/tests/ui/extern-flag/noprelude.stderr b/tests/ui/extern-flag/noprelude.stderr new file mode 100644 index 000000000..578787216 --- /dev/null +++ b/tests/ui/extern-flag/noprelude.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `somedep` + --> $DIR/noprelude.rs:6:5 + | +LL | somedep::somefun(); + | ^^^^^^^ use of undeclared crate or module `somedep` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/extern-flag/nounused.rs b/tests/ui/extern-flag/nounused.rs new file mode 100644 index 000000000..2513986bb --- /dev/null +++ b/tests/ui/extern-flag/nounused.rs @@ -0,0 +1,7 @@ +// check-pass +// aux-crate:nounused:somedep=somedep.rs +// compile-flags: -Zunstable-options -Dunused-crate-dependencies +// edition:2018 + +fn main() { +} diff --git a/tests/ui/extern-flag/public-and-private.rs b/tests/ui/extern-flag/public-and-private.rs new file mode 100644 index 000000000..a3a81cbf3 --- /dev/null +++ b/tests/ui/extern-flag/public-and-private.rs @@ -0,0 +1,13 @@ +// aux-crate:priv:somedep=somedep.rs +// compile-flags: -Zunstable-options --extern somedep +// edition:2018 + +#![deny(exported_private_dependencies)] + +// Having a flag with `priv` and one without, will remain private (it is sticky). + +pub struct PublicType { + pub field: somedep::S, //~ ERROR from private dependency +} + +fn main() {} diff --git a/tests/ui/extern-flag/public-and-private.stderr b/tests/ui/extern-flag/public-and-private.stderr new file mode 100644 index 000000000..9dfc10eff --- /dev/null +++ b/tests/ui/extern-flag/public-and-private.stderr @@ -0,0 +1,14 @@ +error: type `S` from private dependency 'somedep' in public interface + --> $DIR/public-and-private.rs:10:5 + | +LL | pub field: somedep::S, + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/public-and-private.rs:5:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/extern/auxiliary/extern-take-value.rs b/tests/ui/extern/auxiliary/extern-take-value.rs new file mode 100644 index 000000000..56256aa19 --- /dev/null +++ b/tests/ui/extern/auxiliary/extern-take-value.rs @@ -0,0 +1,5 @@ +pub extern "C" fn f() -> i32 { 1 } +pub extern "C" fn g() -> i32 { 2 } + +pub fn get_f() -> extern "C" fn() -> i32 { f } +pub fn get_g() -> extern "C" fn() -> i32 { g } diff --git a/tests/ui/extern/auxiliary/extern-types-inherent-impl.rs b/tests/ui/extern/auxiliary/extern-types-inherent-impl.rs new file mode 100644 index 000000000..a1efe1818 --- /dev/null +++ b/tests/ui/extern/auxiliary/extern-types-inherent-impl.rs @@ -0,0 +1,9 @@ +#![feature(extern_types)] + +extern "C" { + pub type CrossCrate; +} + +impl CrossCrate { + pub fn foo(&self) {} +} diff --git a/tests/ui/extern/auxiliary/extern_calling_convention.rs b/tests/ui/extern/auxiliary/extern_calling_convention.rs new file mode 100644 index 000000000..e24cf9fda --- /dev/null +++ b/tests/ui/extern/auxiliary/extern_calling_convention.rs @@ -0,0 +1,26 @@ +// Make sure Rust generates the correct calling convention for extern +// functions. + +#[inline(never)] +#[cfg(target_arch = "x86_64")] +pub extern "win64" fn foo(a: isize, b: isize, c: isize, d: isize) { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 4); + + println!("a: {}, b: {}, c: {}, d: {}", + a, b, c, d) +} + +#[inline(never)] +#[cfg(not(target_arch = "x86_64"))] +pub extern "C" fn foo(a: isize, b: isize, c: isize, d: isize) { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 4); + + println!("a: {}, b: {}, c: {}, d: {}", + a, b, c, d) +} diff --git a/tests/ui/extern/auxiliary/extern_mod_ordering_lib.rs b/tests/ui/extern/auxiliary/extern_mod_ordering_lib.rs new file mode 100644 index 000000000..7357f5970 --- /dev/null +++ b/tests/ui/extern/auxiliary/extern_mod_ordering_lib.rs @@ -0,0 +1,5 @@ +#![crate_type="lib"] + +pub mod extern_mod_ordering_lib { + pub fn f() {} +} diff --git a/tests/ui/extern/auxiliary/fat_drop.rs b/tests/ui/extern/auxiliary/fat_drop.rs new file mode 100644 index 000000000..768d29876 --- /dev/null +++ b/tests/ui/extern/auxiliary/fat_drop.rs @@ -0,0 +1,13 @@ +pub static mut DROPPED: bool = false; + +pub struct S { + _unsized: [u8] +} + +impl Drop for S { + fn drop(&mut self) { + unsafe { + DROPPED = true; + } + } +} diff --git a/tests/ui/extern/auxiliary/invalid-utf8.txt b/tests/ui/extern/auxiliary/invalid-utf8.txt new file mode 100644 index 000000000..dc1115b82 --- /dev/null +++ b/tests/ui/extern/auxiliary/invalid-utf8.txt @@ -0,0 +1 @@ +Ã( \ No newline at end of file diff --git a/tests/ui/extern/auxiliary/issue-80074-macro.rs b/tests/ui/extern/auxiliary/issue-80074-macro.rs new file mode 100644 index 000000000..30e0f19ab --- /dev/null +++ b/tests/ui/extern/auxiliary/issue-80074-macro.rs @@ -0,0 +1,4 @@ +// edition:2018 + +macro_rules! foo_ { () => {}; } +use foo_ as foo; diff --git a/tests/ui/extern/auxiliary/m1.rs b/tests/ui/extern/auxiliary/m1.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/extern/auxiliary/m1.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/extern/auxiliary/m2.rs b/tests/ui/extern/auxiliary/m2.rs new file mode 100644 index 000000000..c5c0bc606 --- /dev/null +++ b/tests/ui/extern/auxiliary/m2.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/tests/ui/extern/auxiliary/no-mangle-associated-fn.rs b/tests/ui/extern/auxiliary/no-mangle-associated-fn.rs new file mode 100644 index 000000000..7fc73c76c --- /dev/null +++ b/tests/ui/extern/auxiliary/no-mangle-associated-fn.rs @@ -0,0 +1,21 @@ +#![crate_type = "lib"] + +struct Bar; + +impl Bar { + #[no_mangle] + fn bar() -> u8 { + 2 + } +} + +trait Foo { + fn baz() -> u8; +} + +impl Foo for Bar { + #[no_mangle] + fn baz() -> u8 { + 3 + } +} diff --git a/tests/ui/extern/auxiliary/reexport-should-still-link.rs b/tests/ui/extern/auxiliary/reexport-should-still-link.rs new file mode 100644 index 000000000..237ea8dfc --- /dev/null +++ b/tests/ui/extern/auxiliary/reexport-should-still-link.rs @@ -0,0 +1,5 @@ +pub use foo::bar; + +mod foo { + pub fn bar() {} +} diff --git a/tests/ui/extern/extern-1.rs b/tests/ui/extern/extern-1.rs new file mode 100644 index 000000000..66e560501 --- /dev/null +++ b/tests/ui/extern/extern-1.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +extern "C" fn f() { +} + +pub fn main() { +} diff --git a/tests/ui/extern/extern-calling-convention-test.rs b/tests/ui/extern/extern-calling-convention-test.rs new file mode 100644 index 000000000..7231a7cde --- /dev/null +++ b/tests/ui/extern/extern-calling-convention-test.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:extern_calling_convention.rs + +// pretty-expanded FIXME #23616 + +extern crate extern_calling_convention; + +use extern_calling_convention::foo; + +pub fn main() { + foo(1, 2, 3, 4); +} diff --git a/tests/ui/extern/extern-compare-with-return-type.rs b/tests/ui/extern/extern-compare-with-return-type.rs new file mode 100644 index 000000000..42693d3a0 --- /dev/null +++ b/tests/ui/extern/extern-compare-with-return-type.rs @@ -0,0 +1,27 @@ +// run-pass + +// Tests that we can compare various kinds of extern fn signatures. +#![allow(non_camel_case_types)] + +// `dbg!()` differentiates these functions to ensure they won't be merged. +extern "C" fn voidret1() { dbg!() } +extern "C" fn voidret2() { dbg!() } + +extern "C" fn uintret() -> usize { 22 } + +extern "C" fn uintvoidret(_x: usize) {} + +extern "C" fn uintuintuintuintret(x: usize, y: usize, z: usize) -> usize { x+y+z } +type uintuintuintuintret = extern "C" fn(usize,usize,usize) -> usize; + +pub fn main() { + assert!(voidret1 as extern "C" fn() == voidret1 as extern "C" fn()); + assert!(voidret1 as extern "C" fn() != voidret2 as extern "C" fn()); + + assert!(uintret as extern "C" fn() -> usize == uintret as extern "C" fn() -> usize); + + assert!(uintvoidret as extern "C" fn(usize) == uintvoidret as extern "C" fn(usize)); + + assert!(uintuintuintuintret as uintuintuintuintret == + uintuintuintuintret as uintuintuintuintret); +} diff --git a/tests/ui/extern/extern-const.fixed b/tests/ui/extern/extern-const.fixed new file mode 100644 index 000000000..9d96b4f63 --- /dev/null +++ b/tests/ui/extern/extern-const.fixed @@ -0,0 +1,26 @@ +// Check extern items cannot be const + `rustfix` suggests using +// extern static. +// +// #54388: an unused reference to an undefined static may or may not +// compile. To sidestep this by using one that *is* defined. + +// run-rustfix +// ignore-wasm32-bare no external library to link to. +// ignore-asmjs wasm2js does not support source maps yet +// compile-flags: -g +#![feature(rustc_private)] +extern crate libc; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + static rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const` +} + +fn main() { + // We suggest turning the (illegal) extern `const` into an extern `static`, + // but this also requires `unsafe` (a deny-by-default lint at comment time, + // future error; Issue #36247) + unsafe { + let _x = rust_dbg_static_mut; + } +} diff --git a/tests/ui/extern/extern-const.rs b/tests/ui/extern/extern-const.rs new file mode 100644 index 000000000..7cef5b349 --- /dev/null +++ b/tests/ui/extern/extern-const.rs @@ -0,0 +1,26 @@ +// Check extern items cannot be const + `rustfix` suggests using +// extern static. +// +// #54388: an unused reference to an undefined static may or may not +// compile. To sidestep this by using one that *is* defined. + +// run-rustfix +// ignore-wasm32-bare no external library to link to. +// ignore-asmjs wasm2js does not support source maps yet +// compile-flags: -g +#![feature(rustc_private)] +extern crate libc; + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const` +} + +fn main() { + // We suggest turning the (illegal) extern `const` into an extern `static`, + // but this also requires `unsafe` (a deny-by-default lint at comment time, + // future error; Issue #36247) + unsafe { + let _x = rust_dbg_static_mut; + } +} diff --git a/tests/ui/extern/extern-const.stderr b/tests/ui/extern/extern-const.stderr new file mode 100644 index 000000000..7f67adbdb --- /dev/null +++ b/tests/ui/extern/extern-const.stderr @@ -0,0 +1,12 @@ +error: extern items cannot be `const` + --> $DIR/extern-const.rs:16:11 + | +LL | const rust_dbg_static_mut: libc::c_int; + | ------^^^^^^^^^^^^^^^^^^^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/tests/ui/extern/extern-crate-multiple-missing.rs b/tests/ui/extern/extern-crate-multiple-missing.rs new file mode 100644 index 000000000..a6560ca78 --- /dev/null +++ b/tests/ui/extern/extern-crate-multiple-missing.rs @@ -0,0 +1,10 @@ +// If multiple `extern crate` resolutions fail each of them should produce an error +extern crate bar; //~ ERROR can't find crate for `bar` +extern crate foo; //~ ERROR can't find crate for `foo` + +fn main() { + // If the crate name introduced by `extern crate` failed to resolve then subsequent + // derived paths do not emit additional errors + foo::something(); + bar::something(); +} diff --git a/tests/ui/extern/extern-crate-multiple-missing.stderr b/tests/ui/extern/extern-crate-multiple-missing.stderr new file mode 100644 index 000000000..893bb4fb2 --- /dev/null +++ b/tests/ui/extern/extern-crate-multiple-missing.stderr @@ -0,0 +1,15 @@ +error[E0463]: can't find crate for `bar` + --> $DIR/extern-crate-multiple-missing.rs:2:1 + | +LL | extern crate bar; + | ^^^^^^^^^^^^^^^^^ can't find crate + +error[E0463]: can't find crate for `foo` + --> $DIR/extern-crate-multiple-missing.rs:3:1 + | +LL | extern crate foo; + | ^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/extern/extern-crate-rename.rs b/tests/ui/extern/extern-crate-rename.rs new file mode 100644 index 000000000..fc8afc3e1 --- /dev/null +++ b/tests/ui/extern/extern-crate-rename.rs @@ -0,0 +1,8 @@ +// aux-build:m1.rs +// aux-build:m2.rs + + +extern crate m1; +extern crate m2 as m1; //~ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/extern/extern-crate-rename.stderr b/tests/ui/extern/extern-crate-rename.stderr new file mode 100644 index 000000000..5f1477955 --- /dev/null +++ b/tests/ui/extern/extern-crate-rename.stderr @@ -0,0 +1,17 @@ +error[E0259]: the name `m1` is defined multiple times + --> $DIR/extern-crate-rename.rs:6:1 + | +LL | extern crate m1; + | ---------------- previous import of the extern crate `m1` here +LL | extern crate m2 as m1; + | ^^^^^^^^^^^^^^^^^^^^^^ `m1` reimported here + | + = note: `m1` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate m2 as other_m1; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/extern/extern-crate-visibility.rs b/tests/ui/extern/extern-crate-visibility.rs new file mode 100644 index 000000000..cda1227cc --- /dev/null +++ b/tests/ui/extern/extern-crate-visibility.rs @@ -0,0 +1,24 @@ +mod foo { + extern crate core; +} + +// Check that private crates can be used from outside their modules, albeit with warnings +use foo::core::cell; //~ ERROR crate import `core` is private + +fn f() { + foo::core::cell::Cell::new(0); //~ ERROR crate import `core` is private + + use foo::*; + mod core {} // Check that private crates are not glob imported +} + +mod bar { + pub extern crate core; +} + +mod baz { + pub use bar::*; + use self::core::cell; // Check that public extern crates are glob imported +} + +fn main() {} diff --git a/tests/ui/extern/extern-crate-visibility.stderr b/tests/ui/extern/extern-crate-visibility.stderr new file mode 100644 index 000000000..9eeb83ae1 --- /dev/null +++ b/tests/ui/extern/extern-crate-visibility.stderr @@ -0,0 +1,27 @@ +error[E0603]: crate import `core` is private + --> $DIR/extern-crate-visibility.rs:6:10 + | +LL | use foo::core::cell; + | ^^^^ private crate import + | +note: the crate import `core` is defined here + --> $DIR/extern-crate-visibility.rs:2:5 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ + +error[E0603]: crate import `core` is private + --> $DIR/extern-crate-visibility.rs:9:10 + | +LL | foo::core::cell::Cell::new(0); + | ^^^^ private crate import + | +note: the crate import `core` is defined here + --> $DIR/extern-crate-visibility.rs:2:5 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/extern/extern-ffi-fn-with-body.rs b/tests/ui/extern/extern-ffi-fn-with-body.rs new file mode 100644 index 000000000..ef234e8af --- /dev/null +++ b/tests/ui/extern/extern-ffi-fn-with-body.rs @@ -0,0 +1,11 @@ +extern "C" { + fn foo() -> i32 { //~ ERROR incorrect function inside `extern` block + return 0; + } +} + +extern "C" fn bar() -> i32 { + return 0; +} + +fn main() {} diff --git a/tests/ui/extern/extern-ffi-fn-with-body.stderr b/tests/ui/extern/extern-ffi-fn-with-body.stderr new file mode 100644 index 000000000..079c9cecd --- /dev/null +++ b/tests/ui/extern/extern-ffi-fn-with-body.stderr @@ -0,0 +1,18 @@ +error: incorrect function inside `extern` block + --> $DIR/extern-ffi-fn-with-body.rs:2:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn foo() -> i32 { + | ________^^^__________- + | | | + | | cannot have a body +LL | | return 0; +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/tests/ui/extern/extern-foreign-crate.rs b/tests/ui/extern/extern-foreign-crate.rs new file mode 100644 index 000000000..7f774c442 --- /dev/null +++ b/tests/ui/extern/extern-foreign-crate.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +extern crate std as mystd; + +pub fn main() {} diff --git a/tests/ui/extern/extern-macro.rs b/tests/ui/extern/extern-macro.rs new file mode 100644 index 000000000..ab974e628 --- /dev/null +++ b/tests/ui/extern/extern-macro.rs @@ -0,0 +1,6 @@ +// #41719 + +fn main() { + enum Foo {} + let _ = Foo::bar!(); //~ ERROR failed to resolve: partially resolved path in a macro +} diff --git a/tests/ui/extern/extern-macro.stderr b/tests/ui/extern/extern-macro.stderr new file mode 100644 index 000000000..5b7a72073 --- /dev/null +++ b/tests/ui/extern/extern-macro.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: partially resolved path in a macro + --> $DIR/extern-macro.rs:5:13 + | +LL | let _ = Foo::bar!(); + | ^^^^^^^^ partially resolved path in a macro + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/extern/extern-main-fn.rs b/tests/ui/extern/extern-main-fn.rs new file mode 100644 index 000000000..bb1468a70 --- /dev/null +++ b/tests/ui/extern/extern-main-fn.rs @@ -0,0 +1 @@ +extern "C" fn main() {} //~ ERROR: `main` function has wrong type [E0580] diff --git a/tests/ui/extern/extern-main-fn.stderr b/tests/ui/extern/extern-main-fn.stderr new file mode 100644 index 000000000..136c95753 --- /dev/null +++ b/tests/ui/extern/extern-main-fn.stderr @@ -0,0 +1,12 @@ +error[E0580]: `main` function has wrong type + --> $DIR/extern-main-fn.rs:1:1 + | +LL | extern "C" fn main() {} + | ^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn + | + = note: expected fn pointer `fn()` + found fn pointer `extern "C" fn()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/extern/extern-main-issue-86110.rs b/tests/ui/extern/extern-main-issue-86110.rs new file mode 100644 index 000000000..83af7a14c --- /dev/null +++ b/tests/ui/extern/extern-main-issue-86110.rs @@ -0,0 +1,7 @@ +// missing and missing2 exist to make sure that the error only happens on a `main` declaration +extern "C" { + fn missing(); + fn main(); + //~^ the `main` function cannot be declared in an `extern` block + fn missing2(); +} diff --git a/tests/ui/extern/extern-main-issue-86110.stderr b/tests/ui/extern/extern-main-issue-86110.stderr new file mode 100644 index 000000000..18dfddc46 --- /dev/null +++ b/tests/ui/extern/extern-main-issue-86110.stderr @@ -0,0 +1,8 @@ +error: the `main` function cannot be declared in an `extern` block + --> $DIR/extern-main-issue-86110.rs:4:5 + | +LL | fn main(); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/extern/extern-methods.rs b/tests/ui/extern/extern-methods.rs new file mode 100644 index 000000000..22792c113 --- /dev/null +++ b/tests/ui/extern/extern-methods.rs @@ -0,0 +1,29 @@ +// run-pass +// only-x86 + +trait A { + extern "fastcall" fn test1(i: i32); + extern "C" fn test2(i: i32); +} + +struct S; +impl S { + extern "stdcall" fn test3(i: i32) { + assert_eq!(i, 3); + } +} + +impl A for S { + extern "fastcall" fn test1(i: i32) { + assert_eq!(i, 1); + } + extern "C" fn test2(i: i32) { + assert_eq!(i, 2); + } +} + +fn main() { + ::test1(1); + ::test2(2); + S::test3(3); +} diff --git a/tests/ui/extern/extern-mod-abi.rs b/tests/ui/extern/extern-mod-abi.rs new file mode 100644 index 000000000..c543394cc --- /dev/null +++ b/tests/ui/extern/extern-mod-abi.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +extern "C" { + fn pow(x: f64, y: f64) -> f64; +} + +pub fn main() {} diff --git a/tests/ui/extern/extern-mod-ordering-exe.rs b/tests/ui/extern/extern-mod-ordering-exe.rs new file mode 100644 index 000000000..d7cc4dffb --- /dev/null +++ b/tests/ui/extern/extern-mod-ordering-exe.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:extern_mod_ordering_lib.rs + +// pretty-expanded FIXME #23616 + +extern crate extern_mod_ordering_lib; + +use extern_mod_ordering_lib::extern_mod_ordering_lib as the_lib; + +pub fn main() { + the_lib::f(); +} diff --git a/tests/ui/extern/extern-no-mangle.rs b/tests/ui/extern/extern-no-mangle.rs new file mode 100644 index 000000000..ab7c9824a --- /dev/null +++ b/tests/ui/extern/extern-no-mangle.rs @@ -0,0 +1,30 @@ +#![warn(unused_attributes)] + +// Tests that placing the #[no_mangle] attribute on a foreign fn or static emits +// a specialized warning. +// The previous warning only talks about a "function or static" but foreign fns/statics +// are also not allowed to have #[no_mangle] + +// build-pass + +extern "C" { + #[no_mangle] + //~^ WARNING `#[no_mangle]` has no effect on a foreign static + //~^^ WARNING this was previously accepted by the compiler + pub static FOO: u8; + + #[no_mangle] + //~^ WARNING `#[no_mangle]` has no effect on a foreign function + //~^^ WARNING this was previously accepted by the compiler + pub fn bar(); +} + +fn no_new_warn() { + // Should emit the generic "not a function or static" warning + #[no_mangle] + //~^ WARNING attribute should be applied to a free function, impl method or static + //~^^ WARNING this was previously accepted by the compiler + let x = 0_u8; +} + +fn main() {} diff --git a/tests/ui/extern/extern-no-mangle.stderr b/tests/ui/extern/extern-no-mangle.stderr new file mode 100644 index 000000000..f20ee158a --- /dev/null +++ b/tests/ui/extern/extern-no-mangle.stderr @@ -0,0 +1,42 @@ +warning: attribute should be applied to a free function, impl method or static + --> $DIR/extern-no-mangle.rs:24:5 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ +... +LL | let x = 0_u8; + | ------------- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/extern-no-mangle.rs:1:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: `#[no_mangle]` has no effect on a foreign static + --> $DIR/extern-no-mangle.rs:11:5 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute +... +LL | pub static FOO: u8; + | ------------------- foreign static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: symbol names in extern blocks are not mangled + +warning: `#[no_mangle]` has no effect on a foreign function + --> $DIR/extern-no-mangle.rs:16:5 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute +... +LL | pub fn bar(); + | ------------- foreign function + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: symbol names in extern blocks are not mangled + +warning: 3 warnings emitted + diff --git a/tests/ui/extern/extern-prelude-core.rs b/tests/ui/extern/extern-prelude-core.rs new file mode 100644 index 000000000..56206425f --- /dev/null +++ b/tests/ui/extern/extern-prelude-core.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(lang_items, start)] +#![no_std] + +extern crate std as other; + +mod foo { + pub fn test() { + let x = core::cmp::min(2, 3); + assert_eq!(x, 2); + } +} + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + foo::test(); + 0 +} diff --git a/tests/ui/extern/extern-prelude-no-speculative.rs b/tests/ui/extern/extern-prelude-no-speculative.rs new file mode 100644 index 000000000..3ba124159 --- /dev/null +++ b/tests/ui/extern/extern-prelude-no-speculative.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(unused_variables)] +// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere + +mod m { + pub struct LooksLikeExternCrate; +} + +fn main() { + // OK, speculative resolution for `unused_qualifications` doesn't try + // to resolve this as an extern crate and load that crate + let s = m::LooksLikeExternCrate {}; +} diff --git a/tests/ui/extern/extern-prelude-std.rs b/tests/ui/extern/extern-prelude-std.rs new file mode 100644 index 000000000..b5627fad9 --- /dev/null +++ b/tests/ui/extern/extern-prelude-std.rs @@ -0,0 +1,12 @@ +// run-pass + +mod foo { + pub fn test() { + let x = std::cmp::min(2, 3); + assert_eq!(x, 2); + } +} + +fn main() { + foo::test(); +} diff --git a/tests/ui/extern/extern-pub.rs b/tests/ui/extern/extern-pub.rs new file mode 100644 index 000000000..0b95045a0 --- /dev/null +++ b/tests/ui/extern/extern-pub.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +extern "C" { + pub fn free(p: *const u8); +} + +pub fn main() {} diff --git a/tests/ui/extern/extern-rust.rs b/tests/ui/extern/extern-rust.rs new file mode 100644 index 000000000..7cea8be59 --- /dev/null +++ b/tests/ui/extern/extern-rust.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#[repr(C)] +pub struct Foo(u32); + +// ICE trigger, bad handling of differing types between rust and external ABIs +pub extern "C" fn bar() -> Foo { + Foo(0) +} + +fn main() {} diff --git a/tests/ui/extern/extern-static-size-overflow.rs b/tests/ui/extern/extern-static-size-overflow.rs new file mode 100644 index 000000000..a96ce0cf4 --- /dev/null +++ b/tests/ui/extern/extern-static-size-overflow.rs @@ -0,0 +1,43 @@ +#[repr(C)] +struct ReallyBig { + _a: [u8; usize::MAX], +} + +// The limit for "too big for the current architecture" is dependent on the target pointer size +// however it's artificially limited on 64 bits +// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound() +const fn max_size() -> usize { + #[cfg(target_pointer_width = "16")] + { + 1 << 15 + } + + #[cfg(target_pointer_width = "32")] + { + 1 << 31 + } + + #[cfg(target_pointer_width = "64")] + { + 1 << 47 + } + + #[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" + )))] + { + isize::MAX as usize + } +} + +extern "C" { + static FOO: [u8; 1]; + static BAR: [u8; max_size() - 1]; + static BAZ: [u8; max_size()]; //~ ERROR extern static is too large + static UWU: [usize; usize::MAX]; //~ ERROR extern static is too large + static A: ReallyBig; //~ ERROR extern static is too large +} + +fn main() {} diff --git a/tests/ui/extern/extern-static-size-overflow.stderr b/tests/ui/extern/extern-static-size-overflow.stderr new file mode 100644 index 000000000..1c9263995 --- /dev/null +++ b/tests/ui/extern/extern-static-size-overflow.stderr @@ -0,0 +1,20 @@ +error: extern static is too large for the current architecture + --> $DIR/extern-static-size-overflow.rs:38:5 + | +LL | static BAZ: [u8; max_size()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: extern static is too large for the current architecture + --> $DIR/extern-static-size-overflow.rs:39:5 + | +LL | static UWU: [usize; usize::MAX]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: extern static is too large for the current architecture + --> $DIR/extern-static-size-overflow.rs:40:5 + | +LL | static A: ReallyBig; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/extern/extern-take-value.rs b/tests/ui/extern/extern-take-value.rs new file mode 100644 index 000000000..c09a77436 --- /dev/null +++ b/tests/ui/extern/extern-take-value.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:extern-take-value.rs + +extern crate extern_take_value; + +pub fn main() { + let a: extern "C" fn() -> i32 = extern_take_value::get_f(); + let b: extern "C" fn() -> i32 = extern_take_value::get_f(); + let c: extern "C" fn() -> i32 = extern_take_value::get_g(); + + assert!(a == b); + assert!(a != c); +} diff --git a/tests/ui/extern/extern-thiscall.rs b/tests/ui/extern/extern-thiscall.rs new file mode 100644 index 000000000..717df57ec --- /dev/null +++ b/tests/ui/extern/extern-thiscall.rs @@ -0,0 +1,25 @@ +// run-pass +// only-x86 + +#![feature(abi_thiscall)] + +trait A { + extern "thiscall" fn test1(i: i32); +} + +struct S; + +impl A for S { + extern "thiscall" fn test1(i: i32) { + assert_eq!(i, 1); + } +} + +extern "thiscall" fn test2(i: i32) { + assert_eq!(i, 2); +} + +fn main() { + ::test1(1); + test2(2); +} diff --git a/tests/ui/extern/extern-type-diag-not-similar.rs b/tests/ui/extern/extern-type-diag-not-similar.rs new file mode 100644 index 000000000..39d00a6c1 --- /dev/null +++ b/tests/ui/extern/extern-type-diag-not-similar.rs @@ -0,0 +1,22 @@ +// We previously mentioned other extern types in the error message here. +// +// Two extern types shouldn't really be considered similar just +// because they are both extern types. + +#![feature(extern_types)] +extern { + type ShouldNotBeMentioned; +} + +extern { + type Foo; +} + +unsafe impl Send for ShouldNotBeMentioned {} + +fn assert_send() {} + +fn main() { + assert_send::() + //~^ ERROR `Foo` cannot be sent between threads safely +} diff --git a/tests/ui/extern/extern-type-diag-not-similar.stderr b/tests/ui/extern/extern-type-diag-not-similar.stderr new file mode 100644 index 000000000..75836f7ec --- /dev/null +++ b/tests/ui/extern/extern-type-diag-not-similar.stderr @@ -0,0 +1,16 @@ +error[E0277]: `Foo` cannot be sent between threads safely + --> $DIR/extern-type-diag-not-similar.rs:20:19 + | +LL | assert_send::() + | ^^^ `Foo` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `Foo` +note: required by a bound in `assert_send` + --> $DIR/extern-type-diag-not-similar.rs:17:19 + | +LL | fn assert_send() {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-distinct-types.rs b/tests/ui/extern/extern-types-distinct-types.rs new file mode 100644 index 000000000..4da049b78 --- /dev/null +++ b/tests/ui/extern/extern-types-distinct-types.rs @@ -0,0 +1,12 @@ +#![feature(extern_types)] + +extern "C" { + type A; + type B; +} + +fn foo(r: &A) -> &B { + r //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/extern/extern-types-distinct-types.stderr b/tests/ui/extern/extern-types-distinct-types.stderr new file mode 100644 index 000000000..ca25aa64e --- /dev/null +++ b/tests/ui/extern/extern-types-distinct-types.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/extern-types-distinct-types.rs:9:5 + | +LL | type A; + | ------ the found foreign type +LL | type B; + | ------ the expected foreign type +... +LL | fn foo(r: &A) -> &B { + | -- expected `&B` because of return type +LL | r + | ^ expected extern type `B`, found extern type `A` + | + = note: expected reference `&B` + found reference `&A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/extern/extern-types-inherent-impl.rs b/tests/ui/extern/extern-types-inherent-impl.rs new file mode 100644 index 000000000..3f09ac7b8 --- /dev/null +++ b/tests/ui/extern/extern-types-inherent-impl.rs @@ -0,0 +1,26 @@ +// Test that inherent impls can be defined for extern types. + +// check-pass +// aux-build:extern-types-inherent-impl.rs + +#![feature(extern_types)] + +extern crate extern_types_inherent_impl; +use extern_types_inherent_impl::CrossCrate; + +extern "C" { + type Local; +} + +impl Local { + fn foo(&self) {} +} + +fn use_foo(x: &Local, y: &CrossCrate) { + Local::foo(x); + x.foo(); + CrossCrate::foo(y); + y.foo(); +} + +fn main() {} diff --git a/tests/ui/extern/extern-types-manual-sync-send.rs b/tests/ui/extern/extern-types-manual-sync-send.rs new file mode 100644 index 000000000..87eb3f622 --- /dev/null +++ b/tests/ui/extern/extern-types-manual-sync-send.rs @@ -0,0 +1,19 @@ +// run-pass +// Test that unsafe impl for Sync/Send can be provided for extern types. + +#![feature(extern_types)] + +extern "C" { + type A; +} + +unsafe impl Sync for A {} +unsafe impl Send for A {} + +fn assert_sync() {} +fn assert_send() {} + +fn main() { + assert_sync::(); + assert_send::(); +} diff --git a/tests/ui/extern/extern-types-not-sync-send.rs b/tests/ui/extern/extern-types-not-sync-send.rs new file mode 100644 index 000000000..ba82caced --- /dev/null +++ b/tests/ui/extern/extern-types-not-sync-send.rs @@ -0,0 +1,18 @@ +// Make sure extern types are !Sync and !Send. + +#![feature(extern_types)] + +extern "C" { + type A; +} + +fn assert_sync() {} +fn assert_send() {} + +fn main() { + assert_sync::(); + //~^ ERROR `A` cannot be shared between threads safely [E0277] + + assert_send::(); + //~^ ERROR `A` cannot be sent between threads safely [E0277] +} diff --git a/tests/ui/extern/extern-types-not-sync-send.stderr b/tests/ui/extern/extern-types-not-sync-send.stderr new file mode 100644 index 000000000..7865ddeda --- /dev/null +++ b/tests/ui/extern/extern-types-not-sync-send.stderr @@ -0,0 +1,29 @@ +error[E0277]: `A` cannot be shared between threads safely + --> $DIR/extern-types-not-sync-send.rs:13:19 + | +LL | assert_sync::(); + | ^ `A` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `A` +note: required by a bound in `assert_sync` + --> $DIR/extern-types-not-sync-send.rs:9:28 + | +LL | fn assert_sync() {} + | ^^^^ required by this bound in `assert_sync` + +error[E0277]: `A` cannot be sent between threads safely + --> $DIR/extern-types-not-sync-send.rs:16:19 + | +LL | assert_send::(); + | ^ `A` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `A` +note: required by a bound in `assert_send` + --> $DIR/extern-types-not-sync-send.rs:10:28 + | +LL | fn assert_send() {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-pointer-cast.rs b/tests/ui/extern/extern-types-pointer-cast.rs new file mode 100644 index 000000000..de6955bfa --- /dev/null +++ b/tests/ui/extern/extern-types-pointer-cast.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +// Test that pointers to extern types can be cast from/to usize, +// despite being !Sized. +#![feature(extern_types)] + +extern "C" { + type A; +} + +struct Foo { + x: u8, + tail: A, +} + +struct Bar { + x: u8, + tail: T, +} + +#[cfg(target_pointer_width = "32")] +const MAGIC: usize = 0xdeadbeef; +#[cfg(target_pointer_width = "64")] +const MAGIC: usize = 0x12345678deadbeef; + +fn main() { + assert_eq!((MAGIC as *const A) as usize, MAGIC); + assert_eq!((MAGIC as *const Foo) as usize, MAGIC); + assert_eq!((MAGIC as *const Bar) as usize, MAGIC); + assert_eq!((MAGIC as *const Bar>) as usize, MAGIC); +} diff --git a/tests/ui/extern/extern-types-size_of_val.rs b/tests/ui/extern/extern-types-size_of_val.rs new file mode 100644 index 000000000..3b02ea28e --- /dev/null +++ b/tests/ui/extern/extern-types-size_of_val.rs @@ -0,0 +1,15 @@ +// run-pass +#![feature(extern_types)] + +use std::mem::{align_of_val, size_of_val}; + +extern "C" { + type A; +} + +fn main() { + let x: &A = unsafe { &*(1usize as *const A) }; + + assert_eq!(size_of_val(x), 0); + assert_eq!(align_of_val(x), 1); +} diff --git a/tests/ui/extern/extern-types-thin-pointer.rs b/tests/ui/extern/extern-types-thin-pointer.rs new file mode 100644 index 000000000..b85fc4886 --- /dev/null +++ b/tests/ui/extern/extern-types-thin-pointer.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] +// Test that pointers and references to extern types are thin, ie they have the same size and +// alignment as a pointer to (). +#![feature(extern_types)] + +use std::mem::{align_of, size_of}; + +extern "C" { + type A; +} + +struct Foo { + x: u8, + tail: A, +} + +struct Bar { + x: u8, + tail: T, +} + +fn assert_thin() { + assert_eq!(size_of::<*const T>(), size_of::<*const ()>()); + assert_eq!(align_of::<*const T>(), align_of::<*const ()>()); + + assert_eq!(size_of::<*mut T>(), size_of::<*mut ()>()); + assert_eq!(align_of::<*mut T>(), align_of::<*mut ()>()); + + assert_eq!(size_of::<&T>(), size_of::<&()>()); + assert_eq!(align_of::<&T>(), align_of::<&()>()); + + assert_eq!(size_of::<&mut T>(), size_of::<&mut ()>()); + assert_eq!(align_of::<&mut T>(), align_of::<&mut ()>()); +} + +fn main() { + assert_thin::(); + assert_thin::(); + assert_thin::>(); + assert_thin::>>(); +} diff --git a/tests/ui/extern/extern-types-trait-impl.rs b/tests/ui/extern/extern-types-trait-impl.rs new file mode 100644 index 000000000..656101ed5 --- /dev/null +++ b/tests/ui/extern/extern-types-trait-impl.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +// Test that traits can be implemented for extern types. +#![feature(extern_types)] + +extern "C" { + type A; +} + +trait Foo { + fn foo(&self) {} +} + +impl Foo for A { + fn foo(&self) {} +} + +fn assert_foo() {} + +fn use_foo(x: &dyn Foo) { + x.foo(); +} + +fn main() { + assert_foo::(); +} diff --git a/tests/ui/extern/extern-types-unsized.rs b/tests/ui/extern/extern-types-unsized.rs new file mode 100644 index 000000000..94a222a7e --- /dev/null +++ b/tests/ui/extern/extern-types-unsized.rs @@ -0,0 +1,33 @@ +// Make sure extern types are !Sized. + +#![feature(extern_types)] + +extern "C" { + type A; +} + +struct Foo { + x: u8, + tail: A, +} + +struct Bar { + x: u8, + tail: T, +} + +fn assert_sized() {} + +fn main() { + assert_sized::(); + //~^ ERROR the size for values of type + + assert_sized::(); + //~^ ERROR the size for values of type + + assert_sized::>(); + //~^ ERROR the size for values of type + + assert_sized::>>(); + //~^ ERROR the size for values of type +} diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr new file mode 100644 index 000000000..a79caced1 --- /dev/null +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -0,0 +1,86 @@ +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/extern-types-unsized.rs:22:20 + | +LL | assert_sized::(); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `A` +note: required by a bound in `assert_sized` + --> $DIR/extern-types-unsized.rs:19:17 + | +LL | fn assert_sized() {} + | ^ required by this bound in `assert_sized` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn assert_sized() {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/extern-types-unsized.rs:25:20 + | +LL | assert_sized::(); + | ^^^ doesn't have a size known at compile-time + | + = help: within `Foo`, the trait `Sized` is not implemented for `A` +note: required because it appears within the type `Foo` + --> $DIR/extern-types-unsized.rs:9:8 + | +LL | struct Foo { + | ^^^ +note: required by a bound in `assert_sized` + --> $DIR/extern-types-unsized.rs:19:17 + | +LL | fn assert_sized() {} + | ^ required by this bound in `assert_sized` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn assert_sized() {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/extern-types-unsized.rs:28:20 + | +LL | assert_sized::>(); + | ^^^^^^ doesn't have a size known at compile-time + | + = help: within `Bar`, the trait `Sized` is not implemented for `A` +note: required because it appears within the type `Bar` + --> $DIR/extern-types-unsized.rs:14:8 + | +LL | struct Bar { + | ^^^ +note: required by a bound in `assert_sized` + --> $DIR/extern-types-unsized.rs:19:17 + | +LL | fn assert_sized() {} + | ^ required by this bound in `assert_sized` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn assert_sized() {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/extern-types-unsized.rs:31:20 + | +LL | assert_sized::>>(); + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Bar>`, the trait `Sized` is not implemented for `A` +note: required because it appears within the type `Bar` + --> $DIR/extern-types-unsized.rs:14:8 + | +LL | struct Bar { + | ^^^ +note: required by a bound in `assert_sized` + --> $DIR/extern-types-unsized.rs:19:17 + | +LL | fn assert_sized() {} + | ^ required by this bound in `assert_sized` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn assert_sized() {} + | ++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-vectorcall.rs b/tests/ui/extern/extern-vectorcall.rs new file mode 100644 index 000000000..a283573c9 --- /dev/null +++ b/tests/ui/extern/extern-vectorcall.rs @@ -0,0 +1,27 @@ +// run-pass +// revisions: x64 x32 +// [x64]only-x86_64 +// [x32]only-x86 + +#![feature(abi_vectorcall)] + +trait A { + extern "vectorcall" fn test1(i: i32); +} + +struct S; + +impl A for S { + extern "vectorcall" fn test1(i: i32) { + assert_eq!(i, 1); + } +} + +extern "vectorcall" fn test2(i: i32) { + assert_eq!(i, 2); +} + +fn main() { + ::test1(1); + test2(2); +} diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs new file mode 100644 index 000000000..a72aa4171 --- /dev/null +++ b/tests/ui/extern/extern-with-type-bounds.rs @@ -0,0 +1,22 @@ +#![feature(intrinsics)] + +extern "rust-intrinsic" { + // Real example from libcore + #[rustc_safe_intrinsic] + fn type_id() -> u64; + + // Silent bounds made explicit to make sure they are actually + // resolved. + fn transmute(val: T) -> U; + + // Bounds aren't checked right now, so this should work + // even though it's incorrect. + #[rustc_safe_intrinsic] + fn size_of() -> usize; + + // Unresolved bounds should still error. + fn align_of() -> usize; + //~^ ERROR cannot find trait `NoSuchTrait` in this scope +} + +fn main() {} diff --git a/tests/ui/extern/extern-with-type-bounds.stderr b/tests/ui/extern/extern-with-type-bounds.stderr new file mode 100644 index 000000000..88be1e5dd --- /dev/null +++ b/tests/ui/extern/extern-with-type-bounds.stderr @@ -0,0 +1,9 @@ +error[E0405]: cannot find trait `NoSuchTrait` in this scope + --> $DIR/extern-with-type-bounds.rs:18:20 + | +LL | fn align_of() -> usize; + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/extern/extern-wrong-value-type.rs b/tests/ui/extern/extern-wrong-value-type.rs new file mode 100644 index 000000000..337865ec1 --- /dev/null +++ b/tests/ui/extern/extern-wrong-value-type.rs @@ -0,0 +1,11 @@ +extern "C" fn f() { +} + +fn is_fn(_: F) where F: Fn() {} + +fn main() { + // extern functions are extern "C" fn + let _x: extern "C" fn() = f; // OK + is_fn(f); + //~^ ERROR expected a `Fn<()>` closure, found `extern "C" fn() {f}` +} diff --git a/tests/ui/extern/extern-wrong-value-type.stderr b/tests/ui/extern/extern-wrong-value-type.stderr new file mode 100644 index 000000000..ff2934a2b --- /dev/null +++ b/tests/ui/extern/extern-wrong-value-type.stderr @@ -0,0 +1,19 @@ +error[E0277]: expected a `Fn<()>` closure, found `extern "C" fn() {f}` + --> $DIR/extern-wrong-value-type.rs:9:11 + | +LL | is_fn(f); + | ----- ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}` + = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `is_fn` + --> $DIR/extern-wrong-value-type.rs:4:28 + | +LL | fn is_fn(_: F) where F: Fn() {} + | ^^^^ required by this bound in `is_fn` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern_fat_drop.rs b/tests/ui/extern/extern_fat_drop.rs new file mode 100644 index 000000000..1cd12c2ca --- /dev/null +++ b/tests/ui/extern/extern_fat_drop.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:fat_drop.rs + +extern crate fat_drop; + +fn main() { + unsafe { + let data: &mut [u8] = &mut [0]; + let s: &mut fat_drop::S = std::mem::transmute::<&mut [u8], _>(data); + std::ptr::drop_in_place(s); + assert!(fat_drop::DROPPED); + } +} diff --git a/tests/ui/extern/issue-10025.rs b/tests/ui/extern/issue-10025.rs new file mode 100644 index 000000000..4439b4685 --- /dev/null +++ b/tests/ui/extern/issue-10025.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(dead_code)] + +unsafe extern fn foo() {} +unsafe extern "C" fn bar() {} + +fn main() { + let _a: unsafe extern fn() = foo; + let _a: unsafe extern "C" fn() = foo; +} diff --git a/tests/ui/extern/issue-10763.rs b/tests/ui/extern/issue-10763.rs new file mode 100644 index 000000000..627a8c238 --- /dev/null +++ b/tests/ui/extern/issue-10763.rs @@ -0,0 +1,7 @@ +// build-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +extern "Rust" fn foo() {} + +fn main() {} diff --git a/tests/ui/extern/issue-10764-rpass.rs b/tests/ui/extern/issue-10764-rpass.rs new file mode 100644 index 000000000..42ed1ae93 --- /dev/null +++ b/tests/ui/extern/issue-10764-rpass.rs @@ -0,0 +1,4 @@ +// run-pass +// pretty-expanded FIXME #23616 + +extern "Rust" fn main() {} diff --git a/tests/ui/extern/issue-13655.rs b/tests/ui/extern/issue-13655.rs new file mode 100644 index 000000000..6dd184799 --- /dev/null +++ b/tests/ui/extern/issue-13655.rs @@ -0,0 +1,32 @@ +// run-pass +#![feature(fn_traits, unboxed_closures)] +use std::ops::Fn; + +struct Foo(T); + +impl Fn<()> for Foo { + extern "rust-call" fn call(&self, _: ()) -> T { + match *self { + Foo(t) => t + } + } +} + +impl FnMut<()> for Foo { + extern "rust-call" fn call_mut(&mut self, _: ()) -> T { + self.call(()) + } +} + +impl FnOnce<()> for Foo { + type Output = T; + + extern "rust-call" fn call_once(self, _: ()) -> T { + self.call(()) + } +} + +fn main() { + let t: u8 = 1; + println!("{}", Foo(t)()); +} diff --git a/tests/ui/extern/issue-28324.mir.stderr b/tests/ui/extern/issue-28324.mir.stderr new file mode 100644 index 000000000..aff8bf792 --- /dev/null +++ b/tests/ui/extern/issue-28324.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-28324.rs:8:24 + | +LL | pub static BAZ: u32 = *&error_message_count; + | ^^^^^^^^^^^^^^^^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/extern/issue-28324.rs b/tests/ui/extern/issue-28324.rs new file mode 100644 index 000000000..fbe83e325 --- /dev/null +++ b/tests/ui/extern/issue-28324.rs @@ -0,0 +1,11 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +extern "C" { + static error_message_count: u32; +} + +pub static BAZ: u32 = *&error_message_count; +//~^ ERROR use of extern static is unsafe and requires + +fn main() {} diff --git a/tests/ui/extern/issue-28324.thir.stderr b/tests/ui/extern/issue-28324.thir.stderr new file mode 100644 index 000000000..c696c3598 --- /dev/null +++ b/tests/ui/extern/issue-28324.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-28324.rs:8:25 + | +LL | pub static BAZ: u32 = *&error_message_count; + | ^^^^^^^^^^^^^^^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.rs b/tests/ui/extern/issue-36122-accessing-externed-dst.rs new file mode 100644 index 000000000..5f886ff57 --- /dev/null +++ b/tests/ui/extern/issue-36122-accessing-externed-dst.rs @@ -0,0 +1,6 @@ +fn main() { + extern "C" { + static symbol: [usize]; //~ ERROR: the size for values of type + } + println!("{}", symbol[0]); +} diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr new file mode 100644 index 000000000..5f78775f5 --- /dev/null +++ b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr @@ -0,0 +1,11 @@ +error[E0277]: the size for values of type `[usize]` cannot be known at compilation time + --> $DIR/issue-36122-accessing-externed-dst.rs:3:24 + | +LL | static symbol: [usize]; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[usize]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs new file mode 100644 index 000000000..233120c92 --- /dev/null +++ b/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -0,0 +1,64 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine +// should still run destructors as it unwinds the stack. However, +// bugs with how the nounwind LLVM attribute was applied led to this +// simple case being mishandled *if* you had fat LTO turned on. + +// Unlike issue-64655-extern-rust-must-allow-unwind.rs, the issue +// embodied in this test cropped up regardless of optimization level. +// Therefore it seemed worthy of being enshrined as a dedicated unit +// test. + +// LTO settings cannot be combined with -C prefer-dynamic +// no-prefer-dynamic + +// The revisions just enumerate lto settings (the opt-level appeared irrelevant in practice) + +// revisions: no thin fat +//[no]compile-flags: -C lto=no +//[thin]compile-flags: -C lto=thin +//[fat]compile-flags: -C lto=fat + +#![feature(core_panic)] + +// (For some reason, reproducing the LTO issue requires pulling in std +// explicitly this way.) +#![no_std] +extern crate std; + +fn main() { + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::boxed::Box; + + static SHARED: AtomicUsize = AtomicUsize::new(0); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); + + let old_hook = std::panic::take_hook(); + + std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. + + let handle = std::thread::spawn(|| { + struct Droppable; + impl Drop for Droppable { + fn drop(&mut self) { + SHARED.fetch_add(1, Ordering::SeqCst); + } + } + + let _guard = Droppable; + core::panicking::panic("???"); + }); + + let wait = handle.join(); + + // Reinstate handler to ease observation of assertion failures. + std::panic::set_hook(old_hook); + + assert!(wait.is_err()); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); +} diff --git a/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs new file mode 100644 index 000000000..3b263e58c --- /dev/null +++ b/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -0,0 +1,83 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine +// should still run destructors as it unwinds the stack. However, +// bugs with how the nounwind LLVM attribute was applied led to this +// simple case being mishandled *if* you had optimization *and* fat +// LTO turned on. + +// This test is the closest thing to a "regression test" we can do +// without actually spawning subprocesses and comparing stderr +// results. +// +// This test takes the code from the above issue and adapts it to +// better fit our test infrastructure: +// +// * Instead of relying on `println!` to observe whether the destructor +// is run, we instead run the code in a spawned thread and +// communicate the destructor's operation via a synchronous atomic +// in static memory. +// +// * To keep the output from confusing a casual user, we override the +// panic hook to be a no-op (rather than printing a message to +// stderr). +// +// (pnkfelix has confirmed by hand that these additions do not mask +// the underlying bug.) + +// LTO settings cannot be combined with -C prefer-dynamic +// no-prefer-dynamic + +// The revisions combine each lto setting with each optimization +// setting; pnkfelix observed three differing behaviors at opt-levels +// 0/1/2+3 for this test, so it seems prudent to be thorough. + +// revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2 fat3 + +//[no0]compile-flags: -C opt-level=0 -C lto=no +//[no1]compile-flags: -C opt-level=1 -C lto=no +//[no2]compile-flags: -C opt-level=2 -C lto=no +//[no3]compile-flags: -C opt-level=3 -C lto=no +//[thin0]compile-flags: -C opt-level=0 -C lto=thin +//[thin1]compile-flags: -C opt-level=1 -C lto=thin +//[thin2]compile-flags: -C opt-level=2 -C lto=thin +//[thin3]compile-flags: -C opt-level=3 -C lto=thin +//[fat0]compile-flags: -C opt-level=0 -C lto=fat +//[fat1]compile-flags: -C opt-level=1 -C lto=fat +//[fat2]compile-flags: -C opt-level=2 -C lto=fat +//[fat3]compile-flags: -C opt-level=3 -C lto=fat + +fn main() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static SHARED: AtomicUsize = AtomicUsize::new(0); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); + + let old_hook = std::panic::take_hook(); + + std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. + + let handle = std::thread::spawn(|| { + struct Droppable; + impl Drop for Droppable { + fn drop(&mut self) { + SHARED.fetch_add(1, Ordering::SeqCst); + } + } + + let _guard = Droppable; + None::<()>.expect("???"); + }); + + let wait = handle.join(); + + // reinstate handler to ease observation of assertion failures. + std::panic::set_hook(old_hook); + + assert!(wait.is_err()); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); +} diff --git a/tests/ui/extern/issue-80074.rs b/tests/ui/extern/issue-80074.rs new file mode 100644 index 000000000..f83027d4a --- /dev/null +++ b/tests/ui/extern/issue-80074.rs @@ -0,0 +1,10 @@ +// edition:2018 +// build-pass +// aux-crate:issue_80074=issue-80074-macro.rs + +#[macro_use] +extern crate issue_80074; + +fn main() { + foo!(); +} diff --git a/tests/ui/extern/issue-95829.rs b/tests/ui/extern/issue-95829.rs new file mode 100644 index 000000000..3379148ae --- /dev/null +++ b/tests/ui/extern/issue-95829.rs @@ -0,0 +1,10 @@ +// edition:2018 + +extern { + async fn L() { //~ ERROR: incorrect function inside `extern` block + //~^ ERROR: functions in `extern` blocks cannot have qualifiers + async fn M() {} + } +} + +fn main() {} diff --git a/tests/ui/extern/issue-95829.stderr b/tests/ui/extern/issue-95829.stderr new file mode 100644 index 000000000..b902f0ef8 --- /dev/null +++ b/tests/ui/extern/issue-95829.stderr @@ -0,0 +1,32 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-95829.rs:4:14 + | +LL | extern { + | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | async fn L() { + | ______________^___- + | | | + | | cannot have a body +LL | | +LL | | async fn M() {} +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/issue-95829.rs:4:14 + | +LL | extern { + | ------ in this `extern` block +LL | async fn L() { + | ^ + | +help: remove the qualifiers + | +LL | fn L() { + | ~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/extern/no-mangle-associated-fn.rs b/tests/ui/extern/no-mangle-associated-fn.rs new file mode 100644 index 000000000..ecd44abbf --- /dev/null +++ b/tests/ui/extern/no-mangle-associated-fn.rs @@ -0,0 +1,37 @@ +// aux-build: no-mangle-associated-fn.rs +// run-pass + +extern crate no_mangle_associated_fn; + +struct Foo; + +impl Foo { + #[no_mangle] + fn foo() -> u8 { + 1 + } +} + +trait Bar { + fn qux() -> u8; +} + +impl Bar for Foo { + #[no_mangle] + fn qux() -> u8 { + 4 + } +} + +fn main() { + extern "Rust" { + fn foo() -> u8; + fn bar() -> u8; + fn baz() -> u8; + fn qux() -> u8; + } + assert_eq!(unsafe { foo() }, 1); + assert_eq!(unsafe { bar() }, 2); + assert_eq!(unsafe { baz() }, 3); + assert_eq!(unsafe { qux() }, 4); +} diff --git a/tests/ui/extern/not-in-block.rs b/tests/ui/extern/not-in-block.rs new file mode 100644 index 000000000..d3bcafdef --- /dev/null +++ b/tests/ui/extern/not-in-block.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +extern fn none_fn(x: bool) -> i32; +//~^ ERROR free function without a body +extern "C" fn c_fn(x: bool) -> i32; +//~^ ERROR free function without a body diff --git a/tests/ui/extern/not-in-block.stderr b/tests/ui/extern/not-in-block.stderr new file mode 100644 index 000000000..2544949ab --- /dev/null +++ b/tests/ui/extern/not-in-block.stderr @@ -0,0 +1,32 @@ +error: free function without a body + --> $DIR/not-in-block.rs:3:1 + | +LL | extern fn none_fn(x: bool) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: provide a definition for the function + | +LL | extern fn none_fn(x: bool) -> i32 { } + | ~~~~~~~~~~ +help: if you meant to declare an externally defined function, use an `extern` block + | +LL | extern { fn none_fn(x: bool) -> i32; } + | ~~~~~~~~ + + +error: free function without a body + --> $DIR/not-in-block.rs:5:1 + | +LL | extern "C" fn c_fn(x: bool) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: provide a definition for the function + | +LL | extern "C" fn c_fn(x: bool) -> i32 { } + | ~~~~~~~~~~ +help: if you meant to declare an externally defined function, use an `extern` block + | +LL | extern "C" { fn c_fn(x: bool) -> i32; } + | ~~~~~~~~~~~~ + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/extoption_env-no-args.rs b/tests/ui/extoption_env-no-args.rs new file mode 100644 index 000000000..bc5f77bc6 --- /dev/null +++ b/tests/ui/extoption_env-no-args.rs @@ -0,0 +1 @@ +fn main() { option_env!(); } //~ ERROR: option_env! takes 1 argument diff --git a/tests/ui/extoption_env-no-args.stderr b/tests/ui/extoption_env-no-args.stderr new file mode 100644 index 000000000..65067942b --- /dev/null +++ b/tests/ui/extoption_env-no-args.stderr @@ -0,0 +1,8 @@ +error: option_env! takes 1 argument + --> $DIR/extoption_env-no-args.rs:1:13 + | +LL | fn main() { option_env!(); } + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/extoption_env-not-defined.rs b/tests/ui/extoption_env-not-defined.rs new file mode 100644 index 000000000..4014902ff --- /dev/null +++ b/tests/ui/extoption_env-not-defined.rs @@ -0,0 +1,5 @@ +// run-pass + +pub fn main() { + assert!(option_env!("__HOPEFULLY_DOESNT_EXIST__").is_none()); +} diff --git a/tests/ui/extoption_env-not-string-literal.rs b/tests/ui/extoption_env-not-string-literal.rs new file mode 100644 index 000000000..27c3a8e83 --- /dev/null +++ b/tests/ui/extoption_env-not-string-literal.rs @@ -0,0 +1 @@ +fn main() { option_env!(10); } //~ ERROR: argument must be a string literal diff --git a/tests/ui/extoption_env-not-string-literal.stderr b/tests/ui/extoption_env-not-string-literal.stderr new file mode 100644 index 000000000..272751916 --- /dev/null +++ b/tests/ui/extoption_env-not-string-literal.stderr @@ -0,0 +1,8 @@ +error: argument must be a string literal + --> $DIR/extoption_env-not-string-literal.rs:1:25 + | +LL | fn main() { option_env!(10); } + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/extoption_env-too-many-args.rs b/tests/ui/extoption_env-too-many-args.rs new file mode 100644 index 000000000..ecc8b61ac --- /dev/null +++ b/tests/ui/extoption_env-too-many-args.rs @@ -0,0 +1 @@ +fn main() { option_env!("one", "two"); } //~ ERROR: option_env! takes 1 argument diff --git a/tests/ui/extoption_env-too-many-args.stderr b/tests/ui/extoption_env-too-many-args.stderr new file mode 100644 index 000000000..a34e60b64 --- /dev/null +++ b/tests/ui/extoption_env-too-many-args.stderr @@ -0,0 +1,8 @@ +error: option_env! takes 1 argument + --> $DIR/extoption_env-too-many-args.rs:1:13 + | +LL | fn main() { option_env!("one", "two"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/fact.rs b/tests/ui/fact.rs new file mode 100644 index 000000000..c6c2f57e7 --- /dev/null +++ b/tests/ui/fact.rs @@ -0,0 +1,26 @@ +// run-pass + +fn f(x: isize) -> isize { + // println!("in f:"); + + println!("{}", x); + if x == 1 { + // println!("bottoming out"); + + return 1; + } else { + // println!("recurring"); + + let y: isize = x * f(x - 1); + // println!("returned"); + + println!("{}", y); + return y; + } +} + +pub fn main() { + assert_eq!(f(5), 120); + // println!("all done"); + +} diff --git a/tests/ui/fail-simple.rs b/tests/ui/fail-simple.rs new file mode 100644 index 000000000..cd81a5d0a --- /dev/null +++ b/tests/ui/fail-simple.rs @@ -0,0 +1,3 @@ +fn main() { + panic!(@); //~ ERROR no rules expected the token `@` +} diff --git a/tests/ui/fail-simple.stderr b/tests/ui/fail-simple.stderr new file mode 100644 index 000000000..af8f54291 --- /dev/null +++ b/tests/ui/fail-simple.stderr @@ -0,0 +1,10 @@ +error: no rules expected the token `@` + --> $DIR/fail-simple.rs:2:12 + | +LL | panic!(@); + | ^ no rules expected this token in macro call + | + = note: while trying to match end of macro + +error: aborting due to previous error + diff --git a/tests/ui/feature-gates/allow-features-empty.rs b/tests/ui/feature-gates/allow-features-empty.rs new file mode 100644 index 000000000..88a609349 --- /dev/null +++ b/tests/ui/feature-gates/allow-features-empty.rs @@ -0,0 +1,8 @@ +// compile-flags: -Z allow_features= +// Note: This test uses rustc internal flags because they will never stabilize. + +#![feature(lang_items)] //~ ERROR + +#![feature(unknown_stdlib_feature)] //~ ERROR + +fn main() {} diff --git a/tests/ui/feature-gates/allow-features-empty.stderr b/tests/ui/feature-gates/allow-features-empty.stderr new file mode 100644 index 000000000..f88b3ea0a --- /dev/null +++ b/tests/ui/feature-gates/allow-features-empty.stderr @@ -0,0 +1,15 @@ +error[E0725]: the feature `lang_items` is not in the list of allowed features + --> $DIR/allow-features-empty.rs:4:12 + | +LL | #![feature(lang_items)] + | ^^^^^^^^^^ + +error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features + --> $DIR/allow-features-empty.rs:6:12 + | +LL | #![feature(unknown_stdlib_feature)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0725`. diff --git a/tests/ui/feature-gates/allow-features.rs b/tests/ui/feature-gates/allow-features.rs new file mode 100644 index 000000000..2ce4701a8 --- /dev/null +++ b/tests/ui/feature-gates/allow-features.rs @@ -0,0 +1,8 @@ +// compile-flags: -Z allow_features=lang_items +// Note: This test uses rustc internal flags because they will never stabilize. + +#![feature(lang_items)] + +#![feature(unknown_stdlib_feature)] //~ ERROR + +fn main() {} diff --git a/tests/ui/feature-gates/allow-features.stderr b/tests/ui/feature-gates/allow-features.stderr new file mode 100644 index 000000000..9caf48dd1 --- /dev/null +++ b/tests/ui/feature-gates/allow-features.stderr @@ -0,0 +1,9 @@ +error[E0725]: the feature `unknown_stdlib_feature` is not in the list of allowed features + --> $DIR/allow-features.rs:6:12 + | +LL | #![feature(unknown_stdlib_feature)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0725`. diff --git a/tests/ui/feature-gates/auxiliary/cfg-target-thread-local.rs b/tests/ui/feature-gates/auxiliary/cfg-target-thread-local.rs new file mode 100644 index 000000000..bd5c8f81c --- /dev/null +++ b/tests/ui/feature-gates/auxiliary/cfg-target-thread-local.rs @@ -0,0 +1,7 @@ +#![feature(thread_local)] +#![feature(cfg_target_thread_local)] +#![crate_type = "lib"] + +#[no_mangle] +#[cfg_attr(target_thread_local, thread_local)] +pub static FOO: u32 = 3; diff --git a/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis b/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis new file mode 100644 index 000000000..6eb47e3d8 --- /dev/null +++ b/tests/ui/feature-gates/auxiliary/debugger-visualizer.natvis @@ -0,0 +1,3 @@ + + + diff --git a/tests/ui/feature-gates/auxiliary/pub_dep.rs b/tests/ui/feature-gates/auxiliary/pub_dep.rs new file mode 100644 index 000000000..3ebafd953 --- /dev/null +++ b/tests/ui/feature-gates/auxiliary/pub_dep.rs @@ -0,0 +1 @@ +pub struct PubType; diff --git a/tests/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs b/tests/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs new file mode 100644 index 000000000..41b9d64d5 --- /dev/null +++ b/tests/ui/feature-gates/auxiliary/re_rebalance_coherence_lib.rs @@ -0,0 +1,22 @@ +pub trait Backend {} +pub trait SupportsDefaultKeyword {} + +impl SupportsDefaultKeyword for Postgres {} + +pub struct Postgres; + +impl Backend for Postgres {} + +pub struct AstPass(::std::marker::PhantomData); + +pub trait QueryFragment {} + + +#[derive(Debug, Clone, Copy)] +pub struct BatchInsert<'a, T: 'a, Tab> { + _marker: ::std::marker::PhantomData<(&'a T, Tab)>, +} + +impl<'a, T:'a, Tab, DB> QueryFragment for BatchInsert<'a, T, Tab> +where DB: SupportsDefaultKeyword + Backend, +{} diff --git a/tests/ui/feature-gates/bench.rs b/tests/ui/feature-gates/bench.rs new file mode 100644 index 000000000..8de390bec --- /dev/null +++ b/tests/ui/feature-gates/bench.rs @@ -0,0 +1,9 @@ +// edition:2018 + +#[bench] //~ ERROR use of unstable library feature 'test' + //~| WARN this was previously accepted +fn bench() {} + +use bench as _; //~ ERROR use of unstable library feature 'test' + //~| WARN this was previously accepted +fn main() {} diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr new file mode 100644 index 000000000..5f0aaf925 --- /dev/null +++ b/tests/ui/feature-gates/bench.stderr @@ -0,0 +1,21 @@ +error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable + --> $DIR/bench.rs:3:3 + | +LL | #[bench] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + = note: `#[deny(soft_unstable)]` on by default + +error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable + --> $DIR/bench.rs:7:5 + | +LL | use bench as _; + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/duplicate-features.rs b/tests/ui/feature-gates/duplicate-features.rs new file mode 100644 index 000000000..d8f781805 --- /dev/null +++ b/tests/ui/feature-gates/duplicate-features.rs @@ -0,0 +1,9 @@ +#![allow(stable_features)] + +#![feature(rust1)] +#![feature(rust1)] //~ ERROR the feature `rust1` has already been declared + +#![feature(if_let)] +#![feature(if_let)] //~ ERROR the feature `if_let` has already been declared + +fn main() {} diff --git a/tests/ui/feature-gates/duplicate-features.stderr b/tests/ui/feature-gates/duplicate-features.stderr new file mode 100644 index 000000000..dbde806f6 --- /dev/null +++ b/tests/ui/feature-gates/duplicate-features.stderr @@ -0,0 +1,15 @@ +error[E0636]: the feature `if_let` has already been declared + --> $DIR/duplicate-features.rs:7:12 + | +LL | #![feature(if_let)] + | ^^^^^^ + +error[E0636]: the feature `rust1` has already been declared + --> $DIR/duplicate-features.rs:4:12 + | +LL | #![feature(rust1)] + | ^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0636`. diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs new file mode 100644 index 000000000..05461297a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs @@ -0,0 +1,51 @@ +// needs-llvm-components: avr +// compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Test that the AVR interrupt ABI cannot be used when avr_interrupt +// feature gate is not used. + +extern "avr-non-blocking-interrupt" fn fu() {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +extern "avr-interrupt" fn f() {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + +trait T { + extern "avr-interrupt" fn m(); + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn mu(); + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + + extern "avr-interrupt" fn dm() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn dmu() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +} + +struct S; +impl T for S { + extern "avr-interrupt" fn m() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn mu() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +} + +impl S { + extern "avr-interrupt" fn im() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + extern "avr-non-blocking-interrupt" fn imu() {} + //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +} + +type TA = extern "avr-interrupt" fn(); +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +type TAU = extern "avr-non-blocking-interrupt" fn(); +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental + +extern "avr-interrupt" {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental +extern "avr-non-blocking-interrupt" {} +//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr new file mode 100644 index 000000000..d017d03a3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr @@ -0,0 +1,129 @@ +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:11:8 + | +LL | extern "avr-non-blocking-interrupt" fn fu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:13:8 + | +LL | extern "avr-interrupt" fn f() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:17:12 + | +LL | extern "avr-interrupt" fn m(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:19:12 + | +LL | extern "avr-non-blocking-interrupt" fn mu(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:22:12 + | +LL | extern "avr-interrupt" fn dm() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:24:12 + | +LL | extern "avr-non-blocking-interrupt" fn dmu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:30:12 + | +LL | extern "avr-interrupt" fn m() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:32:12 + | +LL | extern "avr-non-blocking-interrupt" fn mu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:37:12 + | +LL | extern "avr-interrupt" fn im() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:39:12 + | +LL | extern "avr-non-blocking-interrupt" fn imu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:43:18 + | +LL | type TA = extern "avr-interrupt" fn(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:45:19 + | +LL | type TAU = extern "avr-non-blocking-interrupt" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:48:8 + | +LL | extern "avr-interrupt" {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change + --> $DIR/feature-gate-abi-avr-interrupt.rs:50:8 + | +LL | extern "avr-non-blocking-interrupt" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69664 for more information + = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs new file mode 100644 index 000000000..8b7d8066a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs @@ -0,0 +1,34 @@ +// needs-llvm-components: msp430 +// compile-flags: --target=msp430-none-elf --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "msp430-interrupt" fn f() {} +//~^ ERROR msp430-interrupt ABI is experimental + +trait T { + extern "msp430-interrupt" fn m(); + //~^ ERROR msp430-interrupt ABI is experimental + + extern "msp430-interrupt" fn dm() {} + //~^ ERROR msp430-interrupt ABI is experimental +} + +struct S; +impl T for S { + extern "msp430-interrupt" fn m() {} + //~^ ERROR msp430-interrupt ABI is experimental +} + +impl S { + extern "msp430-interrupt" fn im() {} + //~^ ERROR msp430-interrupt ABI is experimental +} + +type TA = extern "msp430-interrupt" fn(); +//~^ ERROR msp430-interrupt ABI is experimental + +extern "msp430-interrupt" {} +//~^ ERROR msp430-interrupt ABI is experimental diff --git a/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr new file mode 100644 index 000000000..c19ec9789 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr @@ -0,0 +1,66 @@ +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:8:8 + | +LL | extern "msp430-interrupt" fn f() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:12:12 + | +LL | extern "msp430-interrupt" fn m(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:15:12 + | +LL | extern "msp430-interrupt" fn dm() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:21:12 + | +LL | extern "msp430-interrupt" fn m() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:26:12 + | +LL | extern "msp430-interrupt" fn im() {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:30:18 + | +LL | type TA = extern "msp430-interrupt" fn(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error[E0658]: msp430-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-msp430-interrupt.rs:33:8 + | +LL | extern "msp430-interrupt" {} + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #38487 for more information + = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs new file mode 100644 index 000000000..7c3e4d10d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs @@ -0,0 +1,28 @@ +// needs-llvm-components: x86 +// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental +trait Tr { + extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental + extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental +} + +struct S; + +// Methods in trait impl +impl Tr for S { + extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental +} + +// Methods in inherent impl +impl S { + extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental +} + +type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental + +extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental diff --git a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr new file mode 100644 index 000000000..3b727a745 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr @@ -0,0 +1,66 @@ +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:8:8 + | +LL | extern "x86-interrupt" fn f7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:10:12 + | +LL | extern "x86-interrupt" fn m7(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:11:12 + | +LL | extern "x86-interrupt" fn dm7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:18:12 + | +LL | extern "x86-interrupt" fn m7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:23:12 + | +LL | extern "x86-interrupt" fn im7() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:26:18 + | +LL | type A7 = extern "x86-interrupt" fn(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error[E0658]: x86-interrupt ABI is experimental and subject to change + --> $DIR/feature-gate-abi-x86-interrupt.rs:28:8 + | +LL | extern "x86-interrupt" {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #40180 for more information + = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi.rs b/tests/ui/feature-gates/feature-gate-abi.rs new file mode 100644 index 000000000..712655f97 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi.rs @@ -0,0 +1,60 @@ +// gate-test-intrinsics +// gate-test-platform_intrinsics +// compile-flags: --crate-type=rlib + +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } + +#[lang="tuple_trait"] +trait Tuple { } + +// Functions +extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in +extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in +extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change + +// Methods in trait definition +trait Tr { + extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in + extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in + extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change + + extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change +} + +struct S; + +// Methods in trait impl +impl Tr for S { + extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in + extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in + extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change +} + +// Methods in inherent impl +impl S { + extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change + //~^ ERROR intrinsic must be in + extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental + //~^ ERROR intrinsic must be in + extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change +} + +// Function pointer types +type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change +type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental +type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change + +// Foreign modules +extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change +extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental +extern "rust-call" {} //~ ERROR rust-call ABI is subject to change diff --git a/tests/ui/feature-gates/feature-gate-abi.stderr b/tests/ui/feature-gates/feature-gate-abi.stderr new file mode 100644 index 000000000..e9791b951 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi.stderr @@ -0,0 +1,216 @@ +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:15:8 + | +LL | extern "rust-intrinsic" fn f1() {} + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: platform intrinsics are experimental and possibly buggy + --> $DIR/feature-gate-abi.rs:17:8 + | +LL | extern "platform-intrinsic" fn f2() {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:19:8 + | +LL | extern "rust-call" fn f4(_: ()) {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:23:12 + | +LL | extern "rust-intrinsic" fn m1(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: platform intrinsics are experimental and possibly buggy + --> $DIR/feature-gate-abi.rs:25:12 + | +LL | extern "platform-intrinsic" fn m2(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:27:12 + | +LL | extern "rust-call" fn m4(_: ()); + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:29:12 + | +LL | extern "rust-call" fn dm4(_: ()) {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:36:12 + | +LL | extern "rust-intrinsic" fn m1() {} + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: platform intrinsics are experimental and possibly buggy + --> $DIR/feature-gate-abi.rs:38:12 + | +LL | extern "platform-intrinsic" fn m2() {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:40:12 + | +LL | extern "rust-call" fn m4(_: ()) {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:45:12 + | +LL | extern "rust-intrinsic" fn im1() {} + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: platform intrinsics are experimental and possibly buggy + --> $DIR/feature-gate-abi.rs:47:12 + | +LL | extern "platform-intrinsic" fn im2() {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:49:12 + | +LL | extern "rust-call" fn im4(_: ()) {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:53:18 + | +LL | type A1 = extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: platform intrinsics are experimental and possibly buggy + --> $DIR/feature-gate-abi.rs:54:18 + | +LL | type A2 = extern "platform-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:55:18 + | +LL | type A4 = extern "rust-call" fn(_: ()); + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-abi.rs:58:8 + | +LL | extern "rust-intrinsic" {} + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: platform intrinsics are experimental and possibly buggy + --> $DIR/feature-gate-abi.rs:59:8 + | +LL | extern "platform-intrinsic" {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-abi.rs:60:8 + | +LL | extern "rust-call" {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:23:32 + | +LL | extern "rust-intrinsic" fn m1(); + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:25:36 + | +LL | extern "platform-intrinsic" fn m2(); + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:15:33 + | +LL | extern "rust-intrinsic" fn f1() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:17:37 + | +LL | extern "platform-intrinsic" fn f2() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:36:37 + | +LL | extern "rust-intrinsic" fn m1() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:38:41 + | +LL | extern "platform-intrinsic" fn m2() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:45:38 + | +LL | extern "rust-intrinsic" fn im1() {} + | ^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-abi.rs:47:42 + | +LL | extern "platform-intrinsic" fn im2() {} + | ^^ + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs new file mode 100644 index 000000000..465b81d7f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs @@ -0,0 +1,30 @@ +// compile-flags: --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "amdgpu-kernel" fn fu() {} //~ ERROR amdgpu-kernel ABI is experimental +//~^ ERROR is not a supported ABI + +trait T { + extern "amdgpu-kernel" fn mu(); //~ ERROR amdgpu-kernel ABI is experimental + extern "amdgpu-kernel" fn dmu() {} //~ ERROR amdgpu-kernel ABI is experimental + //~^ ERROR is not a supported ABI +} + +struct S; +impl T for S { + extern "amdgpu-kernel" fn mu() {} //~ ERROR amdgpu-kernel ABI is experimental + //~^ ERROR is not a supported ABI +} + +impl S { + extern "amdgpu-kernel" fn imu() {} //~ ERROR amdgpu-kernel ABI is experimental + //~^ ERROR is not a supported ABI +} + +type TAU = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental + +extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental +//~^ ERROR is not a supported ABI diff --git a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr new file mode 100644 index 000000000..c89ab7bae --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr @@ -0,0 +1,97 @@ +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:8 + | +LL | extern "amdgpu-kernel" fn fu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:11:12 + | +LL | extern "amdgpu-kernel" fn mu(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:12 + | +LL | extern "amdgpu-kernel" fn dmu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:12 + | +LL | extern "amdgpu-kernel" fn mu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:12 + | +LL | extern "amdgpu-kernel" fn imu() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:27:19 + | +LL | type TAU = extern "amdgpu-kernel" fn(); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0658]: amdgpu-kernel ABI is experimental and subject to change + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:8 + | +LL | extern "amdgpu-kernel" {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #51575 for more information + = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:1 + | +LL | extern "amdgpu-kernel" {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:1 + | +LL | extern "amdgpu-kernel" fn fu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:5 + | +LL | extern "amdgpu-kernel" fn dmu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:5 + | +LL | extern "amdgpu-kernel" fn mu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target + --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:5 + | +LL | extern "amdgpu-kernel" fn imu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0570, E0658. +For more information about an error, try `rustc --explain E0570`. diff --git a/tests/ui/feature-gates/feature-gate-abi_ptx.rs b/tests/ui/feature-gates/feature-gate-abi_ptx.rs new file mode 100644 index 000000000..e3405641e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_ptx.rs @@ -0,0 +1,26 @@ +// needs-llvm-components: nvptx +// compile-flags: --target=nvptx64-nvidia-cuda --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "ptx-kernel" fn fu() {} //~ ERROR PTX ABIs are experimental + +trait T { + extern "ptx-kernel" fn mu(); //~ ERROR PTX ABIs are experimental + extern "ptx-kernel" fn dmu() {} //~ ERROR PTX ABIs are experimental +} + +struct S; +impl T for S { + extern "ptx-kernel" fn mu() {} //~ ERROR PTX ABIs are experimental +} + +impl S { + extern "ptx-kernel" fn imu() {} //~ ERROR PTX ABIs are experimental +} + +type TAU = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental + +extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental diff --git a/tests/ui/feature-gates/feature-gate-abi_ptx.stderr b/tests/ui/feature-gates/feature-gate-abi_ptx.stderr new file mode 100644 index 000000000..40782d361 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_ptx.stderr @@ -0,0 +1,66 @@ +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:8:8 + | +LL | extern "ptx-kernel" fn fu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:11:12 + | +LL | extern "ptx-kernel" fn mu(); + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:12:12 + | +LL | extern "ptx-kernel" fn dmu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:17:12 + | +LL | extern "ptx-kernel" fn mu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:21:12 + | +LL | extern "ptx-kernel" fn imu() {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:24:19 + | +LL | type TAU = extern "ptx-kernel" fn(); + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error[E0658]: PTX ABIs are experimental and subject to change + --> $DIR/feature-gate-abi_ptx.rs:26:8 + | +LL | extern "ptx-kernel" {} + | ^^^^^^^^^^^^ + | + = note: see issue #38788 for more information + = help: add `#![feature(abi_ptx)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs b/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs new file mode 100644 index 000000000..35a7d7328 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs @@ -0,0 +1,7 @@ +extern "unadjusted" fn foo() { +//~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable +} + +fn main() { + foo(); +} diff --git a/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr b/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr new file mode 100644 index 000000000..1757befec --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr @@ -0,0 +1,11 @@ +error[E0658]: unadjusted ABI is an implementation detail and perma-unstable + --> $DIR/feature-gate-abi_unadjusted.rs:1:8 + | +LL | extern "unadjusted" fn foo() { + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_unadjusted)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.rs b/tests/ui/feature-gates/feature-gate-adt_const_params.rs new file mode 100644 index 000000000..8a3bcf259 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-adt_const_params.rs @@ -0,0 +1,2 @@ +struct Foo; //~ ERROR `&'static str` is forbidden +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr new file mode 100644 index 000000000..d8f089a28 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr @@ -0,0 +1,11 @@ +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/feature-gate-adt_const_params.rs:1:24 + | +LL | struct Foo; + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs new file mode 100644 index 000000000..78d189d20 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs @@ -0,0 +1,16 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +use core::alloc::Layout; + +#[alloc_error_handler] //~ ERROR use of unstable library feature 'alloc_error_handler' +fn oom(info: Layout) -> ! { + loop {} +} + +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr new file mode 100644 index 000000000..f414eb463 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'alloc_error_handler' + --> $DIR/feature-gate-alloc-error-handler.rs:8:3 + | +LL | #[alloc_error_handler] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51540 for more information + = help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allocator_internals.rs b/tests/ui/feature-gates/feature-gate-allocator_internals.rs new file mode 100644 index 000000000..a17d17da6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allocator_internals.rs @@ -0,0 +1,3 @@ +#![default_lib_allocator] //~ ERROR: attribute is an experimental feature + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-allocator_internals.stderr b/tests/ui/feature-gates/feature-gate-allocator_internals.stderr new file mode 100644 index 000000000..6e276f7bc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allocator_internals.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[default_lib_allocator]` attribute is an experimental feature + --> $DIR/feature-gate-allocator_internals.rs:1:1 + | +LL | #![default_lib_allocator] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(allocator_internals)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs new file mode 100644 index 000000000..9f604aafd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.rs @@ -0,0 +1,17 @@ +// gate-test-allow_internal_unsafe + +#![allow(unused_macros)] + +macro_rules! bar { + () => { + // more layers don't help: + #[allow_internal_unsafe] //~ ERROR allow_internal_unsafe side-steps + macro_rules! baz { + () => {} + } + } +} + +bar!(); + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr new file mode 100644 index 000000000..4621bc0b3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -0,0 +1,15 @@ +error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint + --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:8:9 + | +LL | #[allow_internal_unsafe] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | bar!(); + | ------ in this macro invocation + | + = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs new file mode 100644 index 000000000..ee48f9516 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.rs @@ -0,0 +1,17 @@ +// gate-test-allow_internal_unstable + +#![allow(unused_macros)] + +macro_rules! bar { + () => { + // more layers don't help: + #[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps + macro_rules! baz { + () => {} + } + } +} + +bar!(); + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr new file mode 100644 index 000000000..1232d13a4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -0,0 +1,15 @@ +error[E0658]: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:8:9 + | +LL | #[allow_internal_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | bar!(); + | ------ in this macro invocation + | + = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs new file mode 100644 index 000000000..8b13f1bf2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs @@ -0,0 +1,8 @@ +// checks that this attribute is caught on non-macro items. +// this needs a different test since this is done after expansion + +#[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps +//~| ERROR attribute should +struct S; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr new file mode 100644 index 000000000..df7773ba4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr @@ -0,0 +1,20 @@ +error[E0658]: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-allow-internal-unstable-struct.rs:4:1 + | +LL | #[allow_internal_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable + +error: attribute should be applied to a macro + --> $DIR/feature-gate-allow-internal-unstable-struct.rs:4:1 + | +LL | #[allow_internal_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct S; + | --------- not a macro + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable.rs b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.rs new file mode 100644 index 000000000..0a1b6acd9 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.rs @@ -0,0 +1,8 @@ +#![allow(unused_macros)] + +#[allow_internal_unstable()] //~ ERROR allow_internal_unstable side-steps +macro_rules! foo { + () => {} +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr new file mode 100644 index 000000000..3c1a4bfc7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable.stderr @@ -0,0 +1,11 @@ +error[E0658]: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-allow-internal-unstable.rs:3:1 + | +LL | #[allow_internal_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs new file mode 100644 index 000000000..47ca7e349 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs @@ -0,0 +1,29 @@ +use std::{ + ops::Deref, +}; + +struct Ptr(Box); + +impl Deref for Ptr { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +trait Foo { + fn foo(self: Ptr); //~ ERROR `Ptr` cannot be used as the type of `self` without +} + +struct Bar; + +impl Foo for Bar { + fn foo(self: Ptr) {} //~ ERROR `Ptr` cannot be used as the type of `self` without +} + +impl Bar { + fn bar(self: Box>) {} //~ ERROR `Box>` cannot be used as the +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr new file mode 100644 index 000000000..a1c69a5af --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr @@ -0,0 +1,33 @@ +error[E0658]: `Ptr` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary-self-types.rs:22:18 + | +LL | fn foo(self: Ptr) {} + | ^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0658]: `Box>` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary-self-types.rs:26:18 + | +LL | fn bar(self: Box>) {} + | ^^^^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0658]: `Ptr` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary-self-types.rs:16:18 + | +LL | fn foo(self: Ptr); + | ^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs new file mode 100644 index 000000000..f7e94117e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.rs @@ -0,0 +1,18 @@ +struct Foo; + +impl Foo { + fn foo(self: *const Self) {} + //~^ ERROR `*const Foo` cannot be used as the type of `self` without +} + +trait Bar { + fn bar(self: *const Self); + //~^ ERROR `*const Self` cannot be used as the type of `self` without +} + +impl Bar for () { + fn bar(self: *const Self) {} + //~^ ERROR `*const ()` cannot be used as the type of `self` without +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr new file mode 100644 index 000000000..a9f611b87 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -0,0 +1,33 @@ +error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18 + | +LL | fn foo(self: *const Self) {} + | ^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 + | +LL | fn bar(self: *const Self) {} + | ^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature + --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18 + | +LL | fn bar(self: *const Self); + | ^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_const.rs b/tests/ui/feature-gates/feature-gate-asm_const.rs new file mode 100644 index 000000000..936918a3c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_const.rs @@ -0,0 +1,16 @@ +// only-x86_64 + +use std::arch::asm; + +unsafe fn foo() { + asm!("mov eax, {}", const N + 1); + //~^ ERROR const operands for inline assembly are unstable +} + +fn main() { + unsafe { + foo::<0>(); + asm!("mov eax, {}", const 123); + //~^ ERROR const operands for inline assembly are unstable + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_const.stderr b/tests/ui/feature-gates/feature-gate-asm_const.stderr new file mode 100644 index 000000000..c248374ec --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_const.stderr @@ -0,0 +1,21 @@ +error[E0658]: const operands for inline assembly are unstable + --> $DIR/feature-gate-asm_const.rs:6:25 + | +LL | asm!("mov eax, {}", const N + 1); + | ^^^^^^^^^^^ + | + = note: see issue #93332 for more information + = help: add `#![feature(asm_const)]` to the crate attributes to enable + +error[E0658]: const operands for inline assembly are unstable + --> $DIR/feature-gate-asm_const.rs:13:29 + | +LL | asm!("mov eax, {}", const 123); + | ^^^^^^^^^ + | + = note: see issue #93332 for more information + = help: add `#![feature(asm_const)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_arch.rs b/tests/ui/feature-gates/feature-gate-asm_experimental_arch.rs new file mode 100644 index 000000000..53e2a4d13 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_arch.rs @@ -0,0 +1,21 @@ +// compile-flags: --target mips-unknown-linux-gnu +// needs-llvm-components: mips + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +unsafe fn main() { + asm!(""); + //~^ ERROR inline assembly is not stable yet on this architecture +} diff --git a/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr b/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr new file mode 100644 index 000000000..4a859430e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_experimental_arch.stderr @@ -0,0 +1,12 @@ +error[E0658]: inline assembly is not stable yet on this architecture + --> $DIR/feature-gate-asm_experimental_arch.rs:19:5 + | +LL | asm!(""); + | ^^^^^^^^ + | + = note: see issue #93335 for more information + = help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_unwind.rs b/tests/ui/feature-gates/feature-gate-asm_unwind.rs new file mode 100644 index 000000000..df161b600 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_unwind.rs @@ -0,0 +1,10 @@ +// only-x86_64 + +use std::arch::asm; + +fn main() { + unsafe { + asm!("", options(may_unwind)); + //~^ ERROR the `may_unwind` option is unstable + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_unwind.stderr b/tests/ui/feature-gates/feature-gate-asm_unwind.stderr new file mode 100644 index 000000000..05e66acb5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_unwind.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `may_unwind` option is unstable + --> $DIR/feature-gate-asm_unwind.rs:7:9 + | +LL | asm!("", options(may_unwind)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93334 for more information + = help: add `#![feature(asm_unwind)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-assoc-type-defaults.rs b/tests/ui/feature-gates/feature-gate-assoc-type-defaults.rs new file mode 100644 index 000000000..d7c6a9f97 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-assoc-type-defaults.rs @@ -0,0 +1,7 @@ +// gate-test-associated_type_defaults + +trait Foo { + type Bar = u8; //~ ERROR associated type defaults are unstable +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr b/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr new file mode 100644 index 000000000..9edad6153 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-assoc-type-defaults.stderr @@ -0,0 +1,12 @@ +error[E0658]: associated type defaults are unstable + --> $DIR/feature-gate-assoc-type-defaults.rs:4:5 + | +LL | type Bar = u8; + | ^^^^^^^^^^^^^^ + | + = note: see issue #29661 for more information + = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-associated_const_equality.rs b/tests/ui/feature-gates/feature-gate-associated_const_equality.rs new file mode 100644 index 000000000..2534c527b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-associated_const_equality.rs @@ -0,0 +1,15 @@ +pub trait TraitWAssocConst { + const A: usize; +} +pub struct Demo {} + +impl TraitWAssocConst for Demo { + const A: usize = 32; +} + +fn foo>() {} +//~^ ERROR associated const equality + +fn main() { + foo::(); +} diff --git a/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr b/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr new file mode 100644 index 000000000..6563fbcba --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr @@ -0,0 +1,12 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/feature-gate-associated_const_equality.rs:10:28 + | +LL | fn foo>() {} + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs new file mode 100644 index 000000000..4e0203274 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -0,0 +1,76 @@ +// compile-flags: -Zsave-analysis +// This is also a regression test for #69415 and the above flag is needed. + +use std::mem::ManuallyDrop; + +trait Tr1 { type As1: Copy; } +trait Tr2 { type As2: Copy; } + +struct S1; +#[derive(Copy, Clone)] +struct S2; +impl Tr1 for S1 { type As1 = S2; } + +trait _Tr3 { + type A: Iterator; + //~^ ERROR associated type bounds are unstable + //~| ERROR the trait bound `<::A as Iterator>::Item: Copy` is not satisfied + + type B: Iterator; + //~^ ERROR associated type bounds are unstable +} + +struct _St1> { +//~^ ERROR associated type bounds are unstable + outest: T, + outer: T::As1, + inner: ::As2, +} + +enum _En1> { +//~^ ERROR associated type bounds are unstable + Outest(T), + Outer(T::As1), + Inner(::As2), +} + +union _Un1> { +//~^ ERROR associated type bounds are unstable + outest: ManuallyDrop, + outer: ManuallyDrop, + inner: ManuallyDrop<::As2>, +} + +type _TaWhere1 where T: Iterator = T; +//~^ ERROR associated type bounds are unstable + +fn _apit(_: impl Tr1) {} +//~^ ERROR associated type bounds are unstable +fn _apit_dyn(_: &dyn Tr1) {} +//~^ ERROR associated type bounds are unstable + +fn _rpit() -> impl Tr1 { S1 } +//~^ ERROR associated type bounds are unstable + +fn _rpit_dyn() -> Box> { Box::new(S1) } +//~^ ERROR associated type bounds are unstable + +const _cdef: impl Tr1 = S1; +//~^ ERROR associated type bounds are unstable +//~| ERROR `impl Trait` only allowed in function and inherent method return types +// FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. +// const _cdef_dyn: &dyn Tr1 = &S1; + +static _sdef: impl Tr1 = S1; +//~^ ERROR associated type bounds are unstable +//~| ERROR `impl Trait` only allowed in function and inherent method return types +// FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. +// static _sdef_dyn: &dyn Tr1 = &S1; + +fn main() { + let _: impl Tr1 = S1; + //~^ ERROR associated type bounds are unstable + //~| ERROR `impl Trait` only allowed in function and inherent method return types + // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. + // let _: &dyn Tr1 = &S1; +} diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr new file mode 100644 index 000000000..5be1d97a0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -0,0 +1,150 @@ +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:15:22 + | +LL | type A: Iterator; + | ^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:19:22 + | +LL | type B: Iterator; + | ^^^^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:23:20 + | +LL | struct _St1> { + | ^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:30:18 + | +LL | enum _En1> { + | ^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:37:19 + | +LL | union _Un1> { + | ^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:44:37 + | +LL | type _TaWhere1 where T: Iterator = T; + | ^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:47:22 + | +LL | fn _apit(_: impl Tr1) {} + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:49:26 + | +LL | fn _apit_dyn(_: &dyn Tr1) {} + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:52:24 + | +LL | fn _rpit() -> impl Tr1 { S1 } + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:55:31 + | +LL | fn _rpit_dyn() -> Box> { Box::new(S1) } + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:58:23 + | +LL | const _cdef: impl Tr1 = S1; + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:64:24 + | +LL | static _sdef: impl Tr1 = S1; + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/feature-gate-associated_type_bounds.rs:71:21 + | +LL | let _: impl Tr1 = S1; + | ^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/feature-gate-associated_type_bounds.rs:58:14 + | +LL | const _cdef: impl Tr1 = S1; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/feature-gate-associated_type_bounds.rs:64:15 + | +LL | static _sdef: impl Tr1 = S1; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/feature-gate-associated_type_bounds.rs:71:12 + | +LL | let _: impl Tr1 = S1; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied + --> $DIR/feature-gate-associated_type_bounds.rs:15:28 + | +LL | type A: Iterator; + | ^^^^ the trait `Copy` is not implemented for `<::A as Iterator>::Item` + | +help: consider further restricting the associated type + | +LL | trait _Tr3 where <::A as Iterator>::Item: Copy { + | +++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0277, E0562, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.rs b/tests/ui/feature-gates/feature-gate-auto-traits.rs new file mode 100644 index 000000000..80cfa9cee --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-auto-traits.rs @@ -0,0 +1,12 @@ +// Test that default and negative trait implementations are gated by +// `auto_traits` feature gate + +struct DummyStruct; + +auto trait AutoDummyTrait {} +//~^ ERROR auto traits are experimental and possibly buggy + +impl !AutoDummyTrait for DummyStruct {} +//~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.stderr b/tests/ui/feature-gates/feature-gate-auto-traits.stderr new file mode 100644 index 000000000..e01541816 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-auto-traits.stderr @@ -0,0 +1,21 @@ +error[E0658]: auto traits are experimental and possibly buggy + --> $DIR/feature-gate-auto-traits.rs:6:1 + | +LL | auto trait AutoDummyTrait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + +error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now + --> $DIR/feature-gate-auto-traits.rs:9:6 + | +LL | impl !AutoDummyTrait for DummyStruct {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #68318 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-box-expr.rs b/tests/ui/feature-gates/feature-gate-box-expr.rs new file mode 100644 index 000000000..870253d2f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-box-expr.rs @@ -0,0 +1,14 @@ +// gate-test-box_syntax + +// Check that `box EXPR` is feature-gated. +// +// See also feature-gate-placement-expr.rs +// +// (Note that the two tests are separated since the checks appear to +// be performed at distinct phases, with an abort_if_errors call +// separating them.) + +fn main() { + let x = box 'c'; //~ ERROR box expression syntax is experimental + println!("x: {}", x); +} diff --git a/tests/ui/feature-gates/feature-gate-box-expr.stderr b/tests/ui/feature-gates/feature-gate-box-expr.stderr new file mode 100644 index 000000000..af864b25f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-box-expr.stderr @@ -0,0 +1,12 @@ +error[E0658]: box expression syntax is experimental; you can call `Box::new` instead + --> $DIR/feature-gate-box-expr.rs:12:13 + | +LL | let x = box 'c'; + | ^^^^^^^ + | + = note: see issue #49733 for more information + = help: add `#![feature(box_syntax)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-box_patterns.rs b/tests/ui/feature-gates/feature-gate-box_patterns.rs new file mode 100644 index 000000000..8bec16a97 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-box_patterns.rs @@ -0,0 +1,4 @@ +fn main() { + let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental + println!("x: {}", x); +} diff --git a/tests/ui/feature-gates/feature-gate-box_patterns.stderr b/tests/ui/feature-gates/feature-gate-box_patterns.stderr new file mode 100644 index 000000000..601ec46a4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-box_patterns.stderr @@ -0,0 +1,12 @@ +error[E0658]: box pattern syntax is experimental + --> $DIR/feature-gate-box_patterns.rs:2:9 + | +LL | let box x = Box::new('c'); + | ^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-box_syntax.rs b/tests/ui/feature-gates/feature-gate-box_syntax.rs new file mode 100644 index 000000000..778660cc0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-box_syntax.rs @@ -0,0 +1,6 @@ +// Test that the use of the box syntax is gated by `box_syntax` feature gate. + +fn main() { + let x = box 3; + //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead +} diff --git a/tests/ui/feature-gates/feature-gate-box_syntax.stderr b/tests/ui/feature-gates/feature-gate-box_syntax.stderr new file mode 100644 index 000000000..dcf8eeed7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-box_syntax.stderr @@ -0,0 +1,12 @@ +error[E0658]: box expression syntax is experimental; you can call `Box::new` instead + --> $DIR/feature-gate-box_syntax.rs:4:13 + | +LL | let x = box 3; + | ^^^^^ + | + = note: see issue #49733 for more information + = help: add `#![feature(box_syntax)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.rs b/tests/ui/feature-gates/feature-gate-c_variadic.rs new file mode 100644 index 000000000..8b40c36c7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic.rs @@ -0,0 +1,4 @@ +#![crate_type="lib"] + +pub unsafe extern "C" fn test(_: i32, ap: ...) { } +//~^ C-variadic functions are unstable diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.stderr b/tests/ui/feature-gates/feature-gate-c_variadic.stderr new file mode 100644 index 000000000..7b3af8d99 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic.stderr @@ -0,0 +1,12 @@ +error[E0658]: C-variadic functions are unstable + --> $DIR/feature-gate-c_variadic.rs:3:1 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44930 for more information + = help: add `#![feature(c_variadic)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-abi.rs b/tests/ui/feature-gates/feature-gate-cfg-target-abi.rs new file mode 100644 index 000000000..d005dc3ad --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-abi.rs @@ -0,0 +1,13 @@ +#[cfg(target_abi = "x")] //~ ERROR `cfg(target_abi)` is experimental +struct Foo(u64, u64); + +#[cfg_attr(target_abi = "x", x)] //~ ERROR `cfg(target_abi)` is experimental +struct Bar(u64, u64); + +#[cfg(not(any(all(target_abi = "x"))))] //~ ERROR `cfg(target_abi)` is experimental +fn foo() {} + +fn main() { + cfg!(target_abi = "x"); + //~^ ERROR `cfg(target_abi)` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-abi.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-abi.stderr new file mode 100644 index 000000000..013705d48 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-abi.stderr @@ -0,0 +1,39 @@ +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:1:7 + | +LL | #[cfg(target_abi = "x")] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:4:12 + | +LL | #[cfg_attr(target_abi = "x", x)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:7:19 + | +LL | #[cfg(not(any(all(target_abi = "x"))))] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error[E0658]: `cfg(target_abi)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-abi.rs:11:10 + | +LL | cfg!(target_abi = "x"); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #80970 for more information + = help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs b/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs new file mode 100644 index 000000000..df81b7d22 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-compact.rs @@ -0,0 +1,13 @@ +#[cfg(target(os = "x"))] //~ ERROR compact `cfg(target(..))` is experimental +struct Foo(u64, u64); + +#[cfg_attr(target(os = "x"), x)] //~ ERROR compact `cfg(target(..))` is experimental +struct Bar(u64, u64); + +#[cfg(not(any(all(target(os = "x")))))] //~ ERROR compact `cfg(target(..))` is experimental +fn foo() {} + +fn main() { + cfg!(target(os = "x")); + //~^ ERROR compact `cfg(target(..))` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr new file mode 100644 index 000000000..be6fe23de --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-compact.stderr @@ -0,0 +1,39 @@ +error[E0658]: compact `cfg(target(..))` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-compact.rs:1:7 + | +LL | #[cfg(target(os = "x"))] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #96901 for more information + = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable + +error[E0658]: compact `cfg(target(..))` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-compact.rs:4:12 + | +LL | #[cfg_attr(target(os = "x"), x)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #96901 for more information + = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable + +error[E0658]: compact `cfg(target(..))` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-compact.rs:7:19 + | +LL | #[cfg(not(any(all(target(os = "x")))))] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #96901 for more information + = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable + +error[E0658]: compact `cfg(target(..))` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-compact.rs:11:10 + | +LL | cfg!(target(os = "x")); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #96901 for more information + = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.rs new file mode 100644 index 000000000..3d692a070 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.rs @@ -0,0 +1,14 @@ +fn main() { + cfg!(target_has_atomic_equal_alignment = "8"); + //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + cfg!(target_has_atomic_equal_alignment = "16"); + //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + cfg!(target_has_atomic_equal_alignment = "32"); + //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + cfg!(target_has_atomic_equal_alignment = "64"); + //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + cfg!(target_has_atomic_equal_alignment = "128"); + //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + cfg!(target_has_atomic_equal_alignment = "ptr"); + //~^ ERROR `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.stderr new file mode 100644 index 000000000..8ad3b034a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic-equal-alignment.stderr @@ -0,0 +1,57 @@ +error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic-equal-alignment.rs:2:10 + | +LL | cfg!(target_has_atomic_equal_alignment = "8"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93822 for more information + = help: add `#![feature(cfg_target_has_atomic_equal_alignment)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic-equal-alignment.rs:4:10 + | +LL | cfg!(target_has_atomic_equal_alignment = "16"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93822 for more information + = help: add `#![feature(cfg_target_has_atomic_equal_alignment)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic-equal-alignment.rs:6:10 + | +LL | cfg!(target_has_atomic_equal_alignment = "32"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93822 for more information + = help: add `#![feature(cfg_target_has_atomic_equal_alignment)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic-equal-alignment.rs:8:10 + | +LL | cfg!(target_has_atomic_equal_alignment = "64"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93822 for more information + = help: add `#![feature(cfg_target_has_atomic_equal_alignment)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic-equal-alignment.rs:10:10 + | +LL | cfg!(target_has_atomic_equal_alignment = "128"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93822 for more information + = help: add `#![feature(cfg_target_has_atomic_equal_alignment)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_equal_alignment)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic-equal-alignment.rs:12:10 + | +LL | cfg!(target_has_atomic_equal_alignment = "ptr"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #93822 for more information + = help: add `#![feature(cfg_target_has_atomic_equal_alignment)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs new file mode 100644 index 000000000..df9c51cb1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs @@ -0,0 +1,14 @@ +fn main() { + cfg!(target_has_atomic_load_store = "8"); + //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change + cfg!(target_has_atomic_load_store = "16"); + //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change + cfg!(target_has_atomic_load_store = "32"); + //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change + cfg!(target_has_atomic_load_store = "64"); + //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change + cfg!(target_has_atomic_load_store = "128"); + //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change + cfg!(target_has_atomic_load_store = "ptr"); + //~^ ERROR `cfg(target_has_atomic_load_store)` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr new file mode 100644 index 000000000..b9e6830a9 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr @@ -0,0 +1,57 @@ +error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic.rs:2:10 + | +LL | cfg!(target_has_atomic_load_store = "8"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94039 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic.rs:4:10 + | +LL | cfg!(target_has_atomic_load_store = "16"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94039 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic.rs:6:10 + | +LL | cfg!(target_has_atomic_load_store = "32"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94039 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic.rs:8:10 + | +LL | cfg!(target_has_atomic_load_store = "64"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94039 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic.rs:10:10 + | +LL | cfg!(target_has_atomic_load_store = "128"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94039 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error[E0658]: `cfg(target_has_atomic_load_store)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-atomic.rs:12:10 + | +LL | cfg!(target_has_atomic_load_store = "ptr"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94039 for more information + = help: add `#![feature(cfg_target_has_atomic)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs new file mode 100644 index 000000000..b600ad23e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -0,0 +1,16 @@ +// ignore-windows +// aux-build:cfg-target-thread-local.rs + +#![feature(thread_local)] + +extern crate cfg_target_thread_local; + +extern "C" { + #[cfg_attr(target_thread_local, thread_local)] + //~^ `cfg(target_thread_local)` is experimental and subject to change + static FOO: u32; +} + +fn main() { + assert_eq!(FOO, 3); +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr new file mode 100644 index 000000000..af59c7141 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(target_thread_local)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-thread-local.rs:9:16 + | +LL | #[cfg_attr(target_thread_local, thread_local)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29594 for more information + = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-version.rs b/tests/ui/feature-gates/feature-gate-cfg-version.rs new file mode 100644 index 000000000..e35784a68 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-version.rs @@ -0,0 +1,49 @@ +#[cfg(version(42))] //~ ERROR: expected a version literal +//~^ ERROR `cfg(version)` is experimental and subject to change +fn foo() {} +#[cfg(version(1.20))] //~ ERROR: expected a version literal +//~^ ERROR `cfg(version)` is experimental and subject to change +fn foo() -> bool { true } +#[cfg(version("1.44"))] +//~^ ERROR `cfg(version)` is experimental and subject to change +fn foo() -> bool { true } +#[cfg(not(version("1.44")))] +//~^ ERROR `cfg(version)` is experimental and subject to change +fn foo() -> bool { false } + +#[cfg(version("1.43", "1.44", "1.45"))] //~ ERROR: expected single version literal +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version(false))] //~ ERROR: expected a version literal +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("foo"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("999"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("-1"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("65536"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("0"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { true } +#[cfg(version("1.0"))] +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { true } +#[cfg(version("1.65536.2"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() -> bool { false } +#[cfg(version("1.20.0-stable"))] //~ WARNING: unknown version literal format +//~^ ERROR `cfg(version)` is experimental and subject to change +fn bar() {} + +fn main() { + assert!(foo()); + assert!(bar()); + assert!(cfg!(version("1.42"))); //~ ERROR `cfg(version)` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-version.stderr b/tests/ui/feature-gates/feature-gate-cfg-version.stderr new file mode 100644 index 000000000..ae899d409 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-version.stderr @@ -0,0 +1,204 @@ +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:1:7 + | +LL | #[cfg(version(42))] + | ^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: expected a version literal + --> $DIR/feature-gate-cfg-version.rs:1:15 + | +LL | #[cfg(version(42))] + | ^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:4:7 + | +LL | #[cfg(version(1.20))] + | ^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: expected a version literal + --> $DIR/feature-gate-cfg-version.rs:4:15 + | +LL | #[cfg(version(1.20))] + | ^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:7:7 + | +LL | #[cfg(version("1.44"))] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:10:11 + | +LL | #[cfg(not(version("1.44")))] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:14:7 + | +LL | #[cfg(version("1.43", "1.44", "1.45"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: expected single version literal + --> $DIR/feature-gate-cfg-version.rs:14:7 + | +LL | #[cfg(version("1.43", "1.44", "1.45"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:17:7 + | +LL | #[cfg(version(false))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: expected a version literal + --> $DIR/feature-gate-cfg-version.rs:17:15 + | +LL | #[cfg(version(false))] + | ^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:20:7 + | +LL | #[cfg(version("foo"))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:20:15 + | +LL | #[cfg(version("foo"))] + | ^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:23:7 + | +LL | #[cfg(version("999"))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:23:15 + | +LL | #[cfg(version("999"))] + | ^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:26:7 + | +LL | #[cfg(version("-1"))] + | ^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:26:15 + | +LL | #[cfg(version("-1"))] + | ^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:29:7 + | +LL | #[cfg(version("65536"))] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:29:15 + | +LL | #[cfg(version("65536"))] + | ^^^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:32:7 + | +LL | #[cfg(version("0"))] + | ^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:32:15 + | +LL | #[cfg(version("0"))] + | ^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:35:7 + | +LL | #[cfg(version("1.0"))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:38:7 + | +LL | #[cfg(version("1.65536.2"))] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:38:15 + | +LL | #[cfg(version("1.65536.2"))] + | ^^^^^^^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:41:7 + | +LL | #[cfg(version("1.20.0-stable"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +warning: unknown version literal format, assuming it refers to a future version + --> $DIR/feature-gate-cfg-version.rs:41:15 + | +LL | #[cfg(version("1.20.0-stable"))] + | ^^^^^^^^^^^^^^^ + +error[E0658]: `cfg(version)` is experimental and subject to change + --> $DIR/feature-gate-cfg-version.rs:48:18 + | +LL | assert!(cfg!(version("1.42"))); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #64796 for more information + = help: add `#![feature(cfg_version)]` to the crate attributes to enable + +error: aborting due to 19 previous errors; 7 warnings emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs b/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs new file mode 100644 index 000000000..c3e7cc9ed --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs @@ -0,0 +1,3 @@ +#[cfg(not(sanitize = "thread"))] +//~^ `cfg(sanitize)` is experimental +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr b/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr new file mode 100644 index 000000000..8088585da --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg_sanitize.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(sanitize)` is experimental and subject to change + --> $DIR/feature-gate-cfg_sanitize.rs:1:11 + | +LL | #[cfg(not(sanitize = "thread"))] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #39699 for more information + = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-check-cfg.rs b/tests/ui/feature-gates/feature-gate-check-cfg.rs new file mode 100644 index 000000000..4012a3b04 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-check-cfg.rs @@ -0,0 +1,3 @@ +// compile-flags: --check-cfg "names()" + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-check-cfg.stderr b/tests/ui/feature-gates/feature-gate-check-cfg.stderr new file mode 100644 index 000000000..9b27c2bc0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-check-cfg.stderr @@ -0,0 +1,2 @@ +error: the `-Z unstable-options` flag must also be passed to enable the flag `check-cfg` + diff --git a/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.rs b/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.rs new file mode 100644 index 000000000..b0b494fa3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.rs @@ -0,0 +1,8 @@ +fn main() { + for<> || -> () {}; + //~^ ERROR `for<...>` binders for closures are experimental + for<'a> || -> () {}; + //~^ ERROR `for<...>` binders for closures are experimental + for<'a, 'b> |_: &'a ()| -> () {}; + //~^ ERROR `for<...>` binders for closures are experimental +} diff --git a/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr b/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr new file mode 100644 index 000000000..aea5cfeed --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-closure_lifetime_binder.stderr @@ -0,0 +1,33 @@ +error[E0658]: `for<...>` binders for closures are experimental + --> $DIR/feature-gate-closure_lifetime_binder.rs:2:5 + | +LL | for<> || -> () {}; + | ^^^^^ + | + = note: see issue #97362 for more information + = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable + = help: consider removing `for<...>` + +error[E0658]: `for<...>` binders for closures are experimental + --> $DIR/feature-gate-closure_lifetime_binder.rs:4:5 + | +LL | for<'a> || -> () {}; + | ^^^^^^^ + | + = note: see issue #97362 for more information + = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable + = help: consider removing `for<...>` + +error[E0658]: `for<...>` binders for closures are experimental + --> $DIR/feature-gate-closure_lifetime_binder.rs:6:5 + | +LL | for<'a, 'b> |_: &'a ()| -> () {}; + | ^^^^^^^^^^^ + | + = note: see issue #97362 for more information + = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable + = help: consider removing `for<...>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs new file mode 100644 index 000000000..a8d63a814 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs @@ -0,0 +1,7 @@ +#![feature(stmt_expr_attributes)] +#![feature(generators)] + +fn main() { + let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures + let _generator = #[track_caller] || { yield; }; //~ `#[track_caller]` on closures +} diff --git a/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr new file mode 100644 index 000000000..ed63d74fe --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr @@ -0,0 +1,21 @@ +error[E0658]: `#[track_caller]` on closures is currently unstable + --> $DIR/feature-gate-closure_track_caller.rs:5:20 + | +LL | let _closure = #[track_caller] || {}; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +error[E0658]: `#[track_caller]` on closures is currently unstable + --> $DIR/feature-gate-closure_track_caller.rs:6:22 + | +LL | let _generator = #[track_caller] || { yield; }; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-collapse_debuginfo.rs b/tests/ui/feature-gates/feature-gate-collapse_debuginfo.rs new file mode 100644 index 000000000..f73bf579f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-collapse_debuginfo.rs @@ -0,0 +1,7 @@ +#[collapse_debuginfo] +//~^ ERROR the `#[collapse_debuginfo]` attribute is an experimental feature +macro_rules! foo { + ($e:expr) => { $e } +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr b/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr new file mode 100644 index 000000000..2cbde893a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-collapse_debuginfo.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[collapse_debuginfo]` attribute is an experimental feature + --> $DIR/feature-gate-collapse_debuginfo.rs:1:1 + | +LL | #[collapse_debuginfo] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #100758 for more information + = help: add `#![feature(collapse_debuginfo)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-compiler-builtins.rs b/tests/ui/feature-gates/feature-gate-compiler-builtins.rs new file mode 100644 index 000000000..0d64f1fdc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-compiler-builtins.rs @@ -0,0 +1,3 @@ +#![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr b/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr new file mode 100644 index 000000000..9d04aef86 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-compiler-builtins.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable + --> $DIR/feature-gate-compiler-builtins.rs:1:1 + | +LL | #![compiler_builtins] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(compiler_builtins)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.rs b/tests/ui/feature-gates/feature-gate-concat_bytes.rs new file mode 100644 index 000000000..07d63cb11 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_bytes.rs @@ -0,0 +1,4 @@ +fn main() { + let a = concat_bytes!(b'A', b"BC"); //~ ERROR use of unstable library feature 'concat_bytes' + assert_eq!(a, &[65, 66, 67]); +} diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr new file mode 100644 index 000000000..4b3ee4c19 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'concat_bytes' + --> $DIR/feature-gate-concat_bytes.rs:2:13 + | +LL | let a = concat_bytes!(b'A', b"BC"); + | ^^^^^^^^^^^^ + | + = note: see issue #87555 for more information + = help: add `#![feature(concat_bytes)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.rs b/tests/ui/feature-gates/feature-gate-concat_idents.rs new file mode 100644 index 000000000..68caf3d71 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_idents.rs @@ -0,0 +1,9 @@ +const XY_1: i32 = 10; + +fn main() { + const XY_2: i32 = 20; + let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable + let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable + assert_eq!(a, 10); + assert_eq!(b, 20); +} diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.stderr b/tests/ui/feature-gates/feature-gate-concat_idents.stderr new file mode 100644 index 000000000..0454fd494 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_idents.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change + --> $DIR/feature-gate-concat_idents.rs:5:13 + | +LL | let a = concat_idents!(X, Y_1); + | ^^^^^^^^^^^^^ + | + = note: see issue #29599 for more information + = help: add `#![feature(concat_idents)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change + --> $DIR/feature-gate-concat_idents.rs:6:13 + | +LL | let b = concat_idents!(X, Y_2); + | ^^^^^^^^^^^^^ + | + = note: see issue #29599 for more information + = help: add `#![feature(concat_idents)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.rs b/tests/ui/feature-gates/feature-gate-concat_idents2.rs new file mode 100644 index 000000000..9660ffeaf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_idents2.rs @@ -0,0 +1,4 @@ +fn main() { + concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough + //~| ERROR cannot find value `ab` in this scope +} diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr new file mode 100644 index 000000000..8663bc7ca --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change + --> $DIR/feature-gate-concat_idents2.rs:2:5 + | +LL | concat_idents!(a, b); + | ^^^^^^^^^^^^^ + | + = note: see issue #29599 for more information + = help: add `#![feature(concat_idents)]` to the crate attributes to enable + +error[E0425]: cannot find value `ab` in this scope + --> $DIR/feature-gate-concat_idents2.rs:2:5 + | +LL | concat_idents!(a, b); + | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `concat_idents` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.rs b/tests/ui/feature-gates/feature-gate-concat_idents3.rs new file mode 100644 index 000000000..81710fd9f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_idents3.rs @@ -0,0 +1,7 @@ +const XY_1: i32 = 10; + +fn main() { + const XY_2: i32 = 20; + assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable + assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable +} diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr new file mode 100644 index 000000000..1316107a3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change + --> $DIR/feature-gate-concat_idents3.rs:5:20 + | +LL | assert_eq!(10, concat_idents!(X, Y_1)); + | ^^^^^^^^^^^^^ + | + = note: see issue #29599 for more information + = help: add `#![feature(concat_idents)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change + --> $DIR/feature-gate-concat_idents3.rs:6:20 + | +LL | assert_eq!(20, concat_idents!(X, Y_2)); + | ^^^^^^^^^^^^^ + | + = note: see issue #29599 for more information + = help: add `#![feature(concat_idents)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-const-indexing.rs b/tests/ui/feature-gates/feature-gate-const-indexing.rs new file mode 100644 index 000000000..2b1067b34 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const-indexing.rs @@ -0,0 +1,8 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47]; + const IDX: usize = 3; + const VAL: i32 = ARR[IDX]; + const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; +} diff --git a/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs new file mode 100644 index 000000000..63159ed05 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-const_refs_to_cell.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(const_refs_to_cell)] + +const FOO: () = { + let x = std::cell::Cell::new(42); + let y = &x; +}; + +fn main() { + FOO; +} diff --git a/tests/ui/feature-gates/feature-gate-custom_attribute.rs b/tests/ui/feature-gates/feature-gate-custom_attribute.rs new file mode 100644 index 000000000..936cab268 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_attribute.rs @@ -0,0 +1,18 @@ +// Check that literals in attributes parse just fine. + +#[fake_attr] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(100)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(1, 2, 3)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr("hello")] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(name = "hello")] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR cannot find attribute `fake_attr` in th +#[fake_attr(key = "hello", val = 10)] //~ ERROR cannot find attribute `fake_attr` in this scop +#[fake_attr(key("hello"), val(10))] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(enabled = true, disabled = false)] //~ ERROR cannot find attribute `fake_attr` in +#[fake_attr(true)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(pi = 3.14159)] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_attr(b"hi")] //~ ERROR cannot find attribute `fake_attr` in this scope +#[fake_doc(r"doc")] //~ ERROR cannot find attribute `fake_doc` in this scope +struct Q {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-custom_attribute.stderr b/tests/ui/feature-gates/feature-gate-custom_attribute.stderr new file mode 100644 index 000000000..b7c45ec1f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_attribute.stderr @@ -0,0 +1,80 @@ +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:3:3 + | +LL | #[fake_attr] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:4:3 + | +LL | #[fake_attr(100)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:5:3 + | +LL | #[fake_attr(1, 2, 3)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:6:3 + | +LL | #[fake_attr("hello")] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:7:3 + | +LL | #[fake_attr(name = "hello")] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:8:3 + | +LL | #[fake_attr(1, "hi", key = 12, true, false)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:9:3 + | +LL | #[fake_attr(key = "hello", val = 10)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:10:3 + | +LL | #[fake_attr(key("hello"), val(10))] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:11:3 + | +LL | #[fake_attr(enabled = true, disabled = false)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:12:3 + | +LL | #[fake_attr(true)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:13:3 + | +LL | #[fake_attr(pi = 3.14159)] + | ^^^^^^^^^ + +error: cannot find attribute `fake_attr` in this scope + --> $DIR/feature-gate-custom_attribute.rs:14:3 + | +LL | #[fake_attr(b"hi")] + | ^^^^^^^^^ + +error: cannot find attribute `fake_doc` in this scope + --> $DIR/feature-gate-custom_attribute.rs:15:3 + | +LL | #[fake_doc(r"doc")] + | ^^^^^^^^ + +error: aborting due to 13 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-custom_attribute2.rs b/tests/ui/feature-gates/feature-gate-custom_attribute2.rs new file mode 100644 index 000000000..724e53deb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_attribute2.rs @@ -0,0 +1,58 @@ +// This test ensures that attributes on formals in generic parameter +// lists are included when we are checking for unstable attributes. + +struct StLt<#[lt_struct] 'a>(&'a u32); +//~^ ERROR cannot find attribute `lt_struct` in this scope +struct StTy<#[ty_struct] I>(I); +//~^ ERROR cannot find attribute `ty_struct` in this scope + +enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } +//~^ ERROR cannot find attribute `lt_enum` in this scope +enum EnTy<#[ty_enum] J> { A(J), B } +//~^ ERROR cannot find attribute `ty_enum` in this scope + +trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } +//~^ ERROR cannot find attribute `lt_trait` in this scope +trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } +//~^ ERROR cannot find attribute `ty_trait` in this scope + +type TyLt<#[lt_type] 'd> = &'d u32; +//~^ ERROR cannot find attribute `lt_type` in this scope +type TyTy<#[ty_type] L> = (L, ); +//~^ ERROR cannot find attribute `ty_type` in this scope + +impl<#[lt_inherent] 'e> StLt<'e> { } +//~^ ERROR cannot find attribute `lt_inherent` in this scope +impl<#[ty_inherent] M> StTy { } +//~^ ERROR cannot find attribute `ty_inherent` in this scope + +impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { + //~^ ERROR cannot find attribute `lt_impl_for` in this scope + fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } } +} +impl<#[ty_impl_for] N> TrTy for StTy { + //~^ ERROR cannot find attribute `ty_impl_for` in this scope + fn foo(&self, _: N) { } +} + +fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } +//~^ ERROR cannot find attribute `lt_fn` in this scope +fn f_ty<#[ty_fn] O>(_: O) { } +//~^ ERROR cannot find attribute `ty_fn` in this scope + +impl StTy { + fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } + //~^ ERROR cannot find attribute `lt_meth` in this scope + fn m_ty<#[ty_meth] P>(_: P) { } + //~^ ERROR cannot find attribute `ty_meth` in this scope +} + +fn hof_lt(_: Q) + where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 + //~^ ERROR cannot find attribute `lt_hof` in this scope +{ +} + +fn main() { + +} diff --git a/tests/ui/feature-gates/feature-gate-custom_attribute2.stderr b/tests/ui/feature-gates/feature-gate-custom_attribute2.stderr new file mode 100644 index 000000000..f22871117 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_attribute2.stderr @@ -0,0 +1,104 @@ +error: cannot find attribute `lt_struct` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:4:15 + | +LL | struct StLt<#[lt_struct] 'a>(&'a u32); + | ^^^^^^^^^ + +error: cannot find attribute `ty_struct` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:6:15 + | +LL | struct StTy<#[ty_struct] I>(I); + | ^^^^^^^^^ + +error: cannot find attribute `lt_enum` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:9:13 + | +LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B } + | ^^^^^^^ + +error: cannot find attribute `ty_enum` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:11:13 + | +LL | enum EnTy<#[ty_enum] J> { A(J), B } + | ^^^^^^^ + +error: cannot find attribute `lt_trait` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:14:14 + | +LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } + | ^^^^^^^^ + +error: cannot find attribute `ty_trait` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:16:14 + | +LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); } + | ^^^^^^^^ + +error: cannot find attribute `lt_type` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:19:13 + | +LL | type TyLt<#[lt_type] 'd> = &'d u32; + | ^^^^^^^ + +error: cannot find attribute `ty_type` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:21:13 + | +LL | type TyTy<#[ty_type] L> = (L, ); + | ^^^^^^^ + +error: cannot find attribute `lt_inherent` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:24:8 + | +LL | impl<#[lt_inherent] 'e> StLt<'e> { } + | ^^^^^^^^^^^ + +error: cannot find attribute `ty_inherent` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:26:8 + | +LL | impl<#[ty_inherent] M> StTy { } + | ^^^^^^^^^^^ + +error: cannot find attribute `lt_impl_for` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:29:8 + | +LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> { + | ^^^^^^^^^^^ + +error: cannot find attribute `ty_impl_for` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:33:8 + | +LL | impl<#[ty_impl_for] N> TrTy for StTy { + | ^^^^^^^^^^^ + +error: cannot find attribute `lt_fn` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:38:11 + | +LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } + | ^^^^^ + +error: cannot find attribute `ty_fn` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:40:11 + | +LL | fn f_ty<#[ty_fn] O>(_: O) { } + | ^^^^^ + +error: cannot find attribute `lt_meth` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:44:15 + | +LL | fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } + | ^^^^^^^ + +error: cannot find attribute `ty_meth` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:46:15 + | +LL | fn m_ty<#[ty_meth] P>(_: P) { } + | ^^^^^^^ + +error: cannot find attribute `lt_hof` in this scope + --> $DIR/feature-gate-custom_attribute2.rs:51:21 + | +LL | where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 + | ^^^^^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.rs b/tests/ui/feature-gates/feature-gate-custom_mir.rs new file mode 100644 index 000000000..0126dde2f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_mir.rs @@ -0,0 +1,12 @@ +#![feature(core_intrinsics)] + +extern crate core; + +#[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite +pub fn foo(_x: i32) -> i32 { + 0 +} + +fn main() { + assert_eq!(2, foo(2)); +} diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr new file mode 100644 index 000000000..3c149d30d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite + --> $DIR/feature-gate-custom_mir.rs:5:1 + | +LL | #[custom_mir(dialect = "built")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.rs b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.rs new file mode 100644 index 000000000..83bb153ba --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.rs @@ -0,0 +1,6 @@ +#![test_runner(main)] //~ ERROR custom test frameworks are an unstable feature + +#[test_case] //~ ERROR custom test frameworks are an unstable feature +fn f() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr new file mode 100644 index 000000000..b65b009a3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'custom_test_frameworks': custom test frameworks are an unstable feature + --> $DIR/feature-gate-custom_test_frameworks.rs:3:3 + | +LL | #[test_case] + | ^^^^^^^^^ + | + = note: see issue #50297 for more information + = help: add `#![feature(custom_test_frameworks)]` to the crate attributes to enable + +error[E0658]: custom test frameworks are an unstable feature + --> $DIR/feature-gate-custom_test_frameworks.rs:1:1 + | +LL | #![test_runner(main)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #50297 for more information + = help: add `#![feature(custom_test_frameworks)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-debugger-visualizer.rs b/tests/ui/feature-gates/feature-gate-debugger-visualizer.rs new file mode 100644 index 000000000..4c4dc450d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-debugger-visualizer.rs @@ -0,0 +1,3 @@ +#![debugger_visualizer(natvis_file = "auxiliary/debugger-visualizer.natvis")] //~ ERROR the `#[debugger_visualizer]` attribute is an experimental feature + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr b/tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr new file mode 100644 index 000000000..e9367fbc6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[debugger_visualizer]` attribute is an experimental feature + --> $DIR/feature-gate-debugger-visualizer.rs:1:1 + | +LL | #![debugger_visualizer(natvis_file = "auxiliary/debugger-visualizer.natvis")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #95939 for more information + = help: add `#![feature(debugger_visualizer)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-decl_macro.rs b/tests/ui/feature-gates/feature-gate-decl_macro.rs new file mode 100644 index 000000000..d002c5dbb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-decl_macro.rs @@ -0,0 +1,5 @@ +#![allow(unused_macros)] + +macro m() {} //~ ERROR `macro` is experimental + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-decl_macro.stderr b/tests/ui/feature-gates/feature-gate-decl_macro.stderr new file mode 100644 index 000000000..800caf252 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-decl_macro.stderr @@ -0,0 +1,12 @@ +error[E0658]: `macro` is experimental + --> $DIR/feature-gate-decl_macro.rs:3:1 + | +LL | macro m() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs new file mode 100644 index 000000000..33038e24b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs @@ -0,0 +1,12 @@ +#![allow(unused)] + +fn avg(_: T) {} +//~^ ERROR defaults for type parameters are only allowed +//~| WARN this was previously accepted + +struct S(T); +impl S {} +//~^ ERROR defaults for type parameters are only allowed +//~| WARN this was previously accepted + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr new file mode 100644 index 000000000..308de2692 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr @@ -0,0 +1,21 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-deprecated_safe.rs b/tests/ui/feature-gates/feature-gate-deprecated_safe.rs new file mode 100644 index 000000000..d5f4a4705 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-deprecated_safe.rs @@ -0,0 +1,7 @@ +#[deprecated_safe(since = "TBD", note = "...")] //~ ERROR: the `#[deprecated_safe]` attribute is an experimental feature +unsafe fn deprecated_safe_fn() {} + +#[deprecated_safe(since = "TBD", note = "...")] //~ ERROR: the `#[deprecated_safe]` attribute is an experimental feature +unsafe trait DeprecatedSafeTrait {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-deprecated_safe.stderr b/tests/ui/feature-gates/feature-gate-deprecated_safe.stderr new file mode 100644 index 000000000..5e98a1faa --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-deprecated_safe.stderr @@ -0,0 +1,21 @@ +error[E0658]: the `#[deprecated_safe]` attribute is an experimental feature + --> $DIR/feature-gate-deprecated_safe.rs:1:1 + | +LL | #[deprecated_safe(since = "TBD", note = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94978 for more information + = help: add `#![feature(deprecated_safe)]` to the crate attributes to enable + +error[E0658]: the `#[deprecated_safe]` attribute is an experimental feature + --> $DIR/feature-gate-deprecated_safe.rs:4:1 + | +LL | #[deprecated_safe(since = "TBD", note = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #94978 for more information + = help: add `#![feature(deprecated_safe)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_cfg.rs b/tests/ui/feature-gates/feature-gate-doc_cfg.rs new file mode 100644 index 000000000..b12b8a105 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-doc_cfg.rs @@ -0,0 +1,2 @@ +#[doc(cfg(unix))] //~ ERROR: `#[doc(cfg)]` is experimental +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-doc_cfg.stderr b/tests/ui/feature-gates/feature-gate-doc_cfg.stderr new file mode 100644 index 000000000..fe88e08c1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-doc_cfg.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[doc(cfg)]` is experimental + --> $DIR/feature-gate-doc_cfg.rs:1:1 + | +LL | #[doc(cfg(unix))] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #43781 for more information + = help: add `#![feature(doc_cfg)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_masked.rs b/tests/ui/feature-gates/feature-gate-doc_masked.rs new file mode 100644 index 000000000..bde3af6b5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-doc_masked.rs @@ -0,0 +1,4 @@ +#[doc(masked)] //~ ERROR: `#[doc(masked)]` is experimental +extern crate std as realstd; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-doc_masked.stderr b/tests/ui/feature-gates/feature-gate-doc_masked.stderr new file mode 100644 index 000000000..80522b6ee --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-doc_masked.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[doc(masked)]` is experimental + --> $DIR/feature-gate-doc_masked.rs:1:1 + | +LL | #[doc(masked)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #44027 for more information + = help: add `#![feature(doc_masked)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs b/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs new file mode 100644 index 000000000..7f3392ead --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-doc_notable_trait.rs @@ -0,0 +1,4 @@ +#[doc(notable_trait)] //~ ERROR: `#[doc(notable_trait)]` is experimental +trait SomeTrait {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr b/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr new file mode 100644 index 000000000..1f9bef40c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-doc_notable_trait.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[doc(notable_trait)]` is experimental + --> $DIR/feature-gate-doc_notable_trait.rs:1:1 + | +LL | #[doc(notable_trait)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #45040 for more information + = help: add `#![feature(doc_notable_trait)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs new file mode 100644 index 000000000..ded08b93f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.rs @@ -0,0 +1,6 @@ +pub fn main() { + match 22 { + 0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental + _ => {} + } +} diff --git a/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr new file mode 100644 index 000000000..6d7f4844a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr @@ -0,0 +1,12 @@ +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9 + | +LL | 0 .. 3 => {} + | ^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs new file mode 100644 index 000000000..f0cc9ea70 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs @@ -0,0 +1,9 @@ +#![feature(never_type)] + +fn foo() -> Result { + Ok(123) +} + +fn main() { + let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding +} diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr new file mode 100644 index 000000000..49e7ab608 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -0,0 +1,17 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/feature-gate-exhaustive-patterns.rs:8:9 + | +LL | let Ok(_x) = foo(); + | ^^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = foo() else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.rs b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.rs new file mode 100644 index 000000000..cff273ce2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.rs @@ -0,0 +1,5 @@ +use core::default; //~ ERROR unresolved import `core` + +fn main() { + let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve +} diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr new file mode 100644 index 000000000..3bae23a4a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr @@ -0,0 +1,20 @@ +error[E0432]: unresolved import `core` + --> $DIR/feature-gate-extern_absolute_paths.rs:1:5 + | +LL | use core::default; + | ^^^^ maybe a missing crate `core`? + | + = help: consider adding `extern crate core` to use the `core` crate + +error[E0433]: failed to resolve: maybe a missing crate `core`? + --> $DIR/feature-gate-extern_absolute_paths.rs:4:19 + | +LL | let _: u8 = ::core::default::Default(); + | ^^^^ maybe a missing crate `core`? + | + = help: consider adding `extern crate core` to use the `core` crate + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/feature-gates/feature-gate-extern_prelude.rs b/tests/ui/feature-gates/feature-gate-extern_prelude.rs new file mode 100644 index 000000000..237099e79 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-extern_prelude.rs @@ -0,0 +1 @@ +can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-` diff --git a/tests/ui/feature-gates/feature-gate-extern_prelude.stderr b/tests/ui/feature-gates/feature-gate-extern_prelude.stderr new file mode 100644 index 000000000..d72e47e9e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-extern_prelude.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `-` + --> $DIR/feature-gate-extern_prelude.rs:1:4 + | +LL | can-only-test-this-in-run-make-fulldeps + | ^ expected one of `!` or `::` + +error: aborting due to previous error + diff --git a/tests/ui/feature-gates/feature-gate-extern_types.rs b/tests/ui/feature-gates/feature-gate-extern_types.rs new file mode 100644 index 000000000..103f8eed6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-extern_types.rs @@ -0,0 +1,5 @@ +extern "C" { + type T; //~ ERROR extern types are experimental +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-extern_types.stderr b/tests/ui/feature-gates/feature-gate-extern_types.stderr new file mode 100644 index 000000000..923fae400 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-extern_types.stderr @@ -0,0 +1,12 @@ +error[E0658]: extern types are experimental + --> $DIR/feature-gate-extern_types.rs:2:5 + | +LL | type T; + | ^^^^^^^ + | + = note: see issue #43467 for more information + = help: add `#![feature(extern_types)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-feature-gate.rs b/tests/ui/feature-gates/feature-gate-feature-gate.rs new file mode 100644 index 000000000..3c98e16a1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-feature-gate.rs @@ -0,0 +1,4 @@ +#![forbid(unstable_features)] +#![feature(intrinsics)] //~ ERROR unstable feature + +fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-feature-gate.stderr b/tests/ui/feature-gates/feature-gate-feature-gate.stderr new file mode 100644 index 000000000..ad97741da --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-feature-gate.stderr @@ -0,0 +1,14 @@ +error: unstable feature + --> $DIR/feature-gate-feature-gate.rs:2:12 + | +LL | #![feature(intrinsics)] + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/feature-gate-feature-gate.rs:1:11 + | +LL | #![forbid(unstable_features)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.rs b/tests/ui/feature-gates/feature-gate-ffi_const.rs new file mode 100644 index 000000000..9f3d783cc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-ffi_const.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +extern "C" { + #[ffi_const] //~ ERROR the `#[ffi_const]` attribute is an experimental feature + pub fn foo(); +} diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.stderr b/tests/ui/feature-gates/feature-gate-ffi_const.stderr new file mode 100644 index 000000000..bed6a2ce4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-ffi_const.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[ffi_const]` attribute is an experimental feature + --> $DIR/feature-gate-ffi_const.rs:4:5 + | +LL | #[ffi_const] + | ^^^^^^^^^^^^ + | + = note: see issue #58328 for more information + = help: add `#![feature(ffi_const)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.rs b/tests/ui/feature-gates/feature-gate-ffi_pure.rs new file mode 100644 index 000000000..b0dfa01ff --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-ffi_pure.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +extern "C" { + #[ffi_pure] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature + pub fn foo(); +} diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr new file mode 100644 index 000000000..2b0308fd6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[ffi_pure]` attribute is an experimental feature + --> $DIR/feature-gate-ffi_pure.rs:4:5 + | +LL | #[ffi_pure] + | ^^^^^^^^^^^ + | + = note: see issue #58329 for more information + = help: add `#![feature(ffi_pure)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs new file mode 100644 index 000000000..f35453435 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +extern "C" { + #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature + pub fn foo(); +} diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr new file mode 100644 index 000000000..3585355ab --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature + --> $DIR/feature-gate-ffi_returns_twice.rs:4:5 + | +LL | #[ffi_returns_twice] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #58314 for more information + = help: add `#![feature(ffi_returns_twice)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-fn_align.rs b/tests/ui/feature-gates/feature-gate-fn_align.rs new file mode 100644 index 000000000..ea873dba2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fn_align.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +#[repr(align(16))] //~ ERROR `repr(align)` attributes on functions are unstable +fn requires_alignment() {} diff --git a/tests/ui/feature-gates/feature-gate-fn_align.stderr b/tests/ui/feature-gates/feature-gate-fn_align.stderr new file mode 100644 index 000000000..5ff124e48 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fn_align.stderr @@ -0,0 +1,12 @@ +error[E0658]: `repr(align)` attributes on functions are unstable + --> $DIR/feature-gate-fn_align.rs:3:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + | + = note: see issue #82232 for more information + = help: add `#![feature(fn_align)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-format_args_nl.rs b/tests/ui/feature-gates/feature-gate-format_args_nl.rs new file mode 100644 index 000000000..aeee2fbad --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-format_args_nl.rs @@ -0,0 +1,3 @@ +fn main() { + format_args_nl!(""); //~ ERROR `format_args_nl` is only for internal language use +} diff --git a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr new file mode 100644 index 000000000..b211e2f8e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'format_args_nl': `format_args_nl` is only for internal language use and is subject to change + --> $DIR/feature-gate-format_args_nl.rs:2:5 + | +LL | format_args_nl!(""); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(format_args_nl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-fundamental.rs b/tests/ui/feature-gates/feature-gate-fundamental.rs new file mode 100644 index 000000000..70e013392 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fundamental.rs @@ -0,0 +1,4 @@ +#[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature +struct Fundamental; + +fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-fundamental.stderr b/tests/ui/feature-gates/feature-gate-fundamental.stderr new file mode 100644 index 000000000..1ae8d9128 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-fundamental.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[fundamental]` attribute is an experimental feature + --> $DIR/feature-gate-fundamental.rs:1:1 + | +LL | #[fundamental] + | ^^^^^^^^^^^^^^ + | + = note: see issue #29635 for more information + = help: add `#![feature(fundamental)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-generators.rs b/tests/ui/feature-gates/feature-gate-generators.rs new file mode 100644 index 000000000..931fee134 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-generators.rs @@ -0,0 +1,10 @@ +fn main() { + yield true; //~ ERROR yield syntax is experimental + //~^ ERROR yield expression outside of generator literal +} + +#[cfg(FALSE)] +fn foo() { + yield; //~ ERROR yield syntax is experimental + yield 0; //~ ERROR yield syntax is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-generators.stderr b/tests/ui/feature-gates/feature-gate-generators.stderr new file mode 100644 index 000000000..dfea178a6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-generators.stderr @@ -0,0 +1,37 @@ +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:2:5 + | +LL | yield true; + | ^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:8:5 + | +LL | yield; + | ^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:9:5 + | +LL | yield 0; + | ^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0627]: yield expression outside of generator literal + --> $DIR/feature-gate-generators.rs:2:5 + | +LL | yield true; + | ^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0627, E0658. +For more information about an error, try `rustc --explain E0627`. diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr new file mode 100644 index 000000000..56123a983 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr @@ -0,0 +1,43 @@ +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/feature-gate-generic_arg_infer.rs:11:27 + | +LL | let _x: [u8; 3] = [0; _]; + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/feature-gate-generic_arg_infer.rs:14:18 + | +LL | let _y: [u8; _] = [0; 3]; + | ^ `_` not allowed here + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/feature-gate-generic_arg_infer.rs:14:18 + | +LL | let _y: [u8; _] = [0; 3]; + | ^ help: consider specifying the array length: `3` + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-generic_arg_infer.rs:20:20 + | +LL | let _x = foo::<_>([1,2]); + | ^ + | + = help: const arguments cannot yet be inferred with `_` + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error[E0658]: using `_` for array lengths is unstable + --> $DIR/feature-gate-generic_arg_infer.rs:11:27 + | +LL | let _x: [u8; 3] = [0; _]; + | ^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs new file mode 100644 index 000000000..afd14b784 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs @@ -0,0 +1,23 @@ +// [feature] run-pass +// revisions: normal feature + +#![cfg_attr(feature, feature(generic_arg_infer))] + +fn foo(_: [u8; N]) -> [u8; N] { + [0; N] +} + +fn bar() { + let _x: [u8; 3] = [0; _]; + //[normal]~^ ERROR: using `_` for array lengths is unstable + //[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment + let _y: [u8; _] = [0; 3]; + //[normal]~^ ERROR: using `_` for array lengths is unstable + //[normal]~| ERROR: in expressions, `_` can only be used on the left-hand side of an assignment +} + +fn main() { + let _x = foo::<_>([1,2]); + //[normal]~^ ERROR: type provided when a constant was expected + let _y = bar(); +} diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs new file mode 100644 index 000000000..7842d44ac --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs @@ -0,0 +1,4 @@ +// This feature doesn't *currently* fire on any specific code; it's just a +// behavior change. Future changes might. +#[rustc_error] //~ the +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr new file mode 100644 index 000000000..bb1622628 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable + --> $DIR/feature-gate-generic_associated_types_extended.rs:3:1 + | +LL | #[rustc_error] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs new file mode 100644 index 000000000..0db8088f7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs @@ -0,0 +1,6 @@ +fn f() -> impl Fn() -> impl Sized { || () } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return +fn g() -> &'static dyn Fn() -> impl Sized { &|| () } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr new file mode 100644 index 000000000..760dcb615 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -0,0 +1,21 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 + | +LL | fn f() -> impl Fn() -> impl Sized { || () } + | ^^^^^^^^^^ + | + = note: see issue #99697 for more information + = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 + | +LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } + | ^^^^^^^^^^ + | + = note: see issue #99697 for more information + = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/feature-gates/feature-gate-imported_main.rs b/tests/ui/feature-gates/feature-gate-imported_main.rs new file mode 100644 index 000000000..b351d0d0e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-imported_main.rs @@ -0,0 +1,6 @@ +pub mod foo { + pub fn bar() { + println!("Hello world!"); + } +} +use foo::bar as main; //~ ERROR using an imported function as entry point diff --git a/tests/ui/feature-gates/feature-gate-imported_main.stderr b/tests/ui/feature-gates/feature-gate-imported_main.stderr new file mode 100644 index 000000000..3b879fdfc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-imported_main.stderr @@ -0,0 +1,12 @@ +error[E0658]: using an imported function as entry point `main` is experimental + --> $DIR/feature-gate-imported_main.rs:6:5 + | +LL | use foo::bar as main; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #28937 for more information + = help: add `#![feature(imported_main)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-inherent_associated_types.rs b/tests/ui/feature-gates/feature-gate-inherent_associated_types.rs new file mode 100644 index 000000000..fc7c6dbc0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-inherent_associated_types.rs @@ -0,0 +1,10 @@ +// Test that inherent associated types cannot be used when inherent_associated_types +// feature gate is not used. + +struct Foo; + +impl Foo { + type Bar = isize; //~ERROR inherent associated types are unstable +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr b/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr new file mode 100644 index 000000000..76e65d239 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-inherent_associated_types.stderr @@ -0,0 +1,12 @@ +error[E0658]: inherent associated types are unstable + --> $DIR/feature-gate-inherent_associated_types.rs:7:5 + | +LL | type Bar = isize; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-inline_const.rs b/tests/ui/feature-gates/feature-gate-inline_const.rs new file mode 100644 index 000000000..43ff90d23 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-inline_const.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = const { + //~^ ERROR inline-const is experimental [E0658] + true + }; +} diff --git a/tests/ui/feature-gates/feature-gate-inline_const.stderr b/tests/ui/feature-gates/feature-gate-inline_const.stderr new file mode 100644 index 000000000..be2f56715 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-inline_const.stderr @@ -0,0 +1,12 @@ +error[E0658]: inline-const is experimental + --> $DIR/feature-gate-inline_const.rs:2:13 + | +LL | let _ = const { + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.rs b/tests/ui/feature-gates/feature-gate-inline_const_pat.rs new file mode 100644 index 000000000..3d0df289f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-inline_const_pat.rs @@ -0,0 +1,4 @@ +fn main() { + let const { () } = (); + //~^ ERROR inline-const in pattern position is experimental [E0658] +} diff --git a/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr new file mode 100644 index 000000000..ca533d850 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-inline_const_pat.stderr @@ -0,0 +1,12 @@ +error[E0658]: inline-const in pattern position is experimental + --> $DIR/feature-gate-inline_const_pat.rs:2:9 + | +LL | let const { () } = (); + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.rs b/tests/ui/feature-gates/feature-gate-intrinsics.rs new file mode 100644 index 000000000..e0dc3cc57 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-intrinsics.rs @@ -0,0 +1,8 @@ +extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change + fn bar(); //~ ERROR unrecognized intrinsic function: `bar` +} + +extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change +//~^ ERROR intrinsic must be in + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr new file mode 100644 index 000000000..8f943d357 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr @@ -0,0 +1,32 @@ +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-intrinsics.rs:1:8 + | +LL | extern "rust-intrinsic" { + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gate-intrinsics.rs:5:8 + | +LL | extern "rust-intrinsic" fn baz() {} + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error[E0093]: unrecognized intrinsic function: `bar` + --> $DIR/feature-gate-intrinsics.rs:2:5 + | +LL | fn bar(); + | ^^^^^^^^^ unrecognized intrinsic + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/feature-gate-intrinsics.rs:5:34 + | +LL | extern "rust-intrinsic" fn baz() {} + | ^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0093, E0658. +For more information about an error, try `rustc --explain E0093`. diff --git a/tests/ui/feature-gates/feature-gate-is_sorted.rs b/tests/ui/feature-gates/feature-gate-is_sorted.rs new file mode 100644 index 000000000..359ed835b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-is_sorted.rs @@ -0,0 +1,13 @@ +fn main() { + // Assert `Iterator` methods are unstable + assert!([1, 2, 2, 9].iter().is_sorted()); + //~^ ERROR: use of unstable library feature 'is_sorted': new API + assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs())); + //~^ ERROR: use of unstable library feature 'is_sorted': new API + + // Assert `[T]` methods are unstable + assert!([1, 2, 2, 9].is_sorted()); + //~^ ERROR: use of unstable library feature 'is_sorted': new API + assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs())); + //~^ ERROR: use of unstable library feature 'is_sorted': new API +} diff --git a/tests/ui/feature-gates/feature-gate-is_sorted.stderr b/tests/ui/feature-gates/feature-gate-is_sorted.stderr new file mode 100644 index 000000000..ccac82707 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-is_sorted.stderr @@ -0,0 +1,39 @@ +error[E0658]: use of unstable library feature 'is_sorted': new API + --> $DIR/feature-gate-is_sorted.rs:3:33 + | +LL | assert!([1, 2, 2, 9].iter().is_sorted()); + | ^^^^^^^^^ + | + = note: see issue #53485 for more information + = help: add `#![feature(is_sorted)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'is_sorted': new API + --> $DIR/feature-gate-is_sorted.rs:5:39 + | +LL | assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs())); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #53485 for more information + = help: add `#![feature(is_sorted)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'is_sorted': new API + --> $DIR/feature-gate-is_sorted.rs:9:26 + | +LL | assert!([1, 2, 2, 9].is_sorted()); + | ^^^^^^^^^ + | + = note: see issue #53485 for more information + = help: add `#![feature(is_sorted)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'is_sorted': new API + --> $DIR/feature-gate-is_sorted.rs:11:32 + | +LL | assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs())); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #53485 for more information + = help: add `#![feature(is_sorted)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-lang-items.rs b/tests/ui/feature-gates/feature-gate-lang-items.rs new file mode 100644 index 000000000..93262f217 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-lang-items.rs @@ -0,0 +1,5 @@ +#[lang = "foo"] //~ ERROR language items are subject to change + //~^ ERROR definition of an unknown language item: `foo` +trait Foo {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-lang-items.stderr b/tests/ui/feature-gates/feature-gate-lang-items.stderr new file mode 100644 index 000000000..c2496863f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-lang-items.stderr @@ -0,0 +1,18 @@ +error[E0658]: language items are subject to change + --> $DIR/feature-gate-lang-items.rs:1:1 + | +LL | #[lang = "foo"] + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(lang_items)]` to the crate attributes to enable + +error[E0522]: definition of an unknown language item: `foo` + --> $DIR/feature-gate-lang-items.rs:1:1 + | +LL | #[lang = "foo"] + | ^^^^^^^^^^^^^^^ definition of unknown language item `foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0522, E0658. +For more information about an error, try `rustc --explain E0522`. diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.rs b/tests/ui/feature-gates/feature-gate-large-assignments.rs new file mode 100644 index 000000000..7e9e574bf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-large-assignments.rs @@ -0,0 +1,5 @@ +// check that `move_size_limit is feature-gated + +#![move_size_limit = "42"] //~ ERROR the `#[move_size_limit]` attribute is an experimental feature + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-large-assignments.stderr b/tests/ui/feature-gates/feature-gate-large-assignments.stderr new file mode 100644 index 000000000..8ddc3043e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-large-assignments.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[move_size_limit]` attribute is an experimental feature + --> $DIR/feature-gate-large-assignments.rs:3:1 + | +LL | #![move_size_limit = "42"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83518 for more information + = help: add `#![feature(large_assignments)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-link_cfg.rs b/tests/ui/feature-gates/feature-gate-link_cfg.rs new file mode 100644 index 000000000..d30ee3bcf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link_cfg.rs @@ -0,0 +1,5 @@ +#[link(name = "foo", cfg(foo))] +//~^ ERROR: is unstable +extern "C" {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-link_cfg.stderr b/tests/ui/feature-gates/feature-gate-link_cfg.stderr new file mode 100644 index 000000000..8f47d5965 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link_cfg.stderr @@ -0,0 +1,12 @@ +error[E0658]: link cfg is unstable + --> $DIR/feature-gate-link_cfg.rs:1:22 + | +LL | #[link(name = "foo", cfg(foo))] + | ^^^^^^^^ + | + = note: see issue #37406 for more information + = help: add `#![feature(link_cfg)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs b/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs new file mode 100644 index 000000000..7391ea94e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.rs @@ -0,0 +1,7 @@ +extern "C" { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; +//~^ ERROR linking to LLVM intrinsics is experimental +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr b/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr new file mode 100644 index 000000000..6bce5b823 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link_llvm_intrinsics.stderr @@ -0,0 +1,12 @@ +error[E0658]: linking to LLVM intrinsics is experimental + --> $DIR/feature-gate-link_llvm_intrinsics.rs:3:5 + | +LL | fn sqrt(x: f32) -> f32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29602 for more information + = help: add `#![feature(link_llvm_intrinsics)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-linkage.rs b/tests/ui/feature-gates/feature-gate-linkage.rs new file mode 100644 index 000000000..505f31ec6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-linkage.rs @@ -0,0 +1,6 @@ +extern "C" { + #[linkage = "extern_weak"] static foo: *mut isize; + //~^ ERROR: the `linkage` attribute is experimental and not portable +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-linkage.stderr b/tests/ui/feature-gates/feature-gate-linkage.stderr new file mode 100644 index 000000000..a1c73e555 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-linkage.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `linkage` attribute is experimental and not portable across platforms + --> $DIR/feature-gate-linkage.rs:2:5 + | +LL | #[linkage = "extern_weak"] static foo: *mut isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29603 for more information + = help: add `#![feature(linkage)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-lint-reasons.rs b/tests/ui/feature-gates/feature-gate-lint-reasons.rs new file mode 100644 index 000000000..7756074e2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-lint-reasons.rs @@ -0,0 +1,5 @@ +#![warn(nonstandard_style, reason = "the standard should be respected")] +//~^ ERROR lint reasons are experimental +//~| ERROR lint reasons are experimental + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-lint-reasons.stderr b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr new file mode 100644 index 000000000..12793c7a2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-lint-reasons.stderr @@ -0,0 +1,21 @@ +error[E0658]: lint reasons are experimental + --> $DIR/feature-gate-lint-reasons.rs:1:28 + | +LL | #![warn(nonstandard_style, reason = "the standard should be respected")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54503 for more information + = help: add `#![feature(lint_reasons)]` to the crate attributes to enable + +error[E0658]: lint reasons are experimental + --> $DIR/feature-gate-lint-reasons.rs:1:28 + | +LL | #![warn(nonstandard_style, reason = "the standard should be respected")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54503 for more information + = help: add `#![feature(lint_reasons)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-log_syntax.rs b/tests/ui/feature-gates/feature-gate-log_syntax.rs new file mode 100644 index 000000000..181f66cb0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-log_syntax.rs @@ -0,0 +1,3 @@ +fn main() { + log_syntax!() //~ ERROR `log_syntax!` is not stable enough +} diff --git a/tests/ui/feature-gates/feature-gate-log_syntax.stderr b/tests/ui/feature-gates/feature-gate-log_syntax.stderr new file mode 100644 index 000000000..fdc1c8553 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-log_syntax.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not stable enough for use and is subject to change + --> $DIR/feature-gate-log_syntax.rs:2:5 + | +LL | log_syntax!() + | ^^^^^^^^^^ + | + = note: see issue #29598 for more information + = help: add `#![feature(log_syntax)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-log_syntax.stdout b/tests/ui/feature-gates/feature-gate-log_syntax.stdout new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-log_syntax.stdout @@ -0,0 +1 @@ + diff --git a/tests/ui/feature-gates/feature-gate-log_syntax2.rs b/tests/ui/feature-gates/feature-gate-log_syntax2.rs new file mode 100644 index 000000000..db1a96f1f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-log_syntax2.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{:?}", log_syntax!()); //~ ERROR `log_syntax!` is not stable +} diff --git a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr new file mode 100644 index 000000000..6deb4a46c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not stable enough for use and is subject to change + --> $DIR/feature-gate-log_syntax2.rs:2:22 + | +LL | println!("{:?}", log_syntax!()); + | ^^^^^^^^^^ + | + = note: see issue #29598 for more information + = help: add `#![feature(log_syntax)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-log_syntax2.stdout b/tests/ui/feature-gates/feature-gate-log_syntax2.stdout new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-log_syntax2.stdout @@ -0,0 +1 @@ + diff --git a/tests/ui/feature-gates/feature-gate-marker_trait_attr.rs b/tests/ui/feature-gates/feature-gate-marker_trait_attr.rs new file mode 100644 index 000000000..5050c4792 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-marker_trait_attr.rs @@ -0,0 +1,9 @@ +use std::fmt::{Debug, Display}; + +#[marker] trait ExplicitMarker {} +//~^ ERROR the `#[marker]` attribute is an experimental feature + +impl ExplicitMarker for T {} +impl ExplicitMarker for T {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr b/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr new file mode 100644 index 000000000..e3c3756fd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-marker_trait_attr.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[marker]` attribute is an experimental feature + --> $DIR/feature-gate-marker_trait_attr.rs:3:1 + | +LL | #[marker] trait ExplicitMarker {} + | ^^^^^^^^^ + | + = note: see issue #29864 for more information + = help: add `#![feature(marker_trait_attr)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-may-dangle.rs b/tests/ui/feature-gates/feature-gate-may-dangle.rs new file mode 100644 index 000000000..23db92c15 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-may-dangle.rs @@ -0,0 +1,11 @@ +// gate-test-dropck_eyepatch + +// Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent. + +struct Pt(A); +unsafe impl<#[may_dangle] A> Drop for Pt { + //~^ ERROR `may_dangle` has unstable semantics and may be removed in the future + fn drop(&mut self) { } +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-may-dangle.stderr b/tests/ui/feature-gates/feature-gate-may-dangle.stderr new file mode 100644 index 000000000..d47a76a50 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-may-dangle.stderr @@ -0,0 +1,12 @@ +error[E0658]: `may_dangle` has unstable semantics and may be removed in the future + --> $DIR/feature-gate-may-dangle.rs:6:13 + | +LL | unsafe impl<#[may_dangle] A> Drop for Pt { + | ^^^^^^^^^^^^^ + | + = note: see issue #34761 for more information + = help: add `#![feature(dropck_eyepatch)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.rs b/tests/ui/feature-gates/feature-gate-min_const_fn.rs new file mode 100644 index 000000000..8f9b43300 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-min_const_fn.rs @@ -0,0 +1,35 @@ +// Test use of min_const_fn without feature gate. + +const fn foo() -> usize { 0 } // stabilized + +trait Foo { + const fn foo() -> u32; //~ ERROR functions in traits cannot be declared const + const fn bar() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const +} + +impl Foo for u32 { + const fn foo() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const +} + +trait Bar {} + +impl dyn Bar { + const fn baz() -> u32 { 0 } // stabilized +} + +static FOO: usize = foo(); +const BAR: usize = foo(); + +macro_rules! constant { + ($n:ident: $t:ty = $v:expr) => { + const $n: $t = $v; + } +} + +constant! { + BAZ: usize = foo() +} + +fn main() { + let x: [usize; foo()] = []; +} diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr new file mode 100644 index 000000000..d7a585913 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr @@ -0,0 +1,21 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/feature-gate-min_const_fn.rs:6:5 + | +LL | const fn foo() -> u32; + | ^^^^^ functions in traits cannot be const + +error[E0379]: functions in traits cannot be declared const + --> $DIR/feature-gate-min_const_fn.rs:7:5 + | +LL | const fn bar() -> u32 { 0 } + | ^^^^^ functions in traits cannot be const + +error[E0379]: functions in traits cannot be declared const + --> $DIR/feature-gate-min_const_fn.rs:11:5 + | +LL | const fn foo() -> u32 { 0 } + | ^^^^^ functions in traits cannot be const + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/feature-gates/feature-gate-more-qualified-paths.rs b/tests/ui/feature-gates/feature-gate-more-qualified-paths.rs new file mode 100644 index 000000000..2e05acbfa --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-more-qualified-paths.rs @@ -0,0 +1,27 @@ +fn main() { + // destructure through a qualified path + let ::Assoc { br } = StructStruct { br: 2 }; + //~^ ERROR usage of qualified paths in this context is experimental + let _ = ::Assoc { br: 2 }; + //~^ ERROR usage of qualified paths in this context is experimental + let ::V(..) = E::V(0); + //~^ ERROR usage of qualified paths in this context is experimental +} + +struct StructStruct { + br: i8, +} + +struct Foo; + +trait A { + type Assoc; +} + +impl A for Foo { + type Assoc = StructStruct; +} + +enum E { + V(u8) +} diff --git a/tests/ui/feature-gates/feature-gate-more-qualified-paths.stderr b/tests/ui/feature-gates/feature-gate-more-qualified-paths.stderr new file mode 100644 index 000000000..80ebcabcf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-more-qualified-paths.stderr @@ -0,0 +1,30 @@ +error[E0658]: usage of qualified paths in this context is experimental + --> $DIR/feature-gate-more-qualified-paths.rs:3:9 + | +LL | let ::Assoc { br } = StructStruct { br: 2 }; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #86935 for more information + = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable + +error[E0658]: usage of qualified paths in this context is experimental + --> $DIR/feature-gate-more-qualified-paths.rs:5:13 + | +LL | let _ = ::Assoc { br: 2 }; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #86935 for more information + = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable + +error[E0658]: usage of qualified paths in this context is experimental + --> $DIR/feature-gate-more-qualified-paths.rs:7:9 + | +LL | let ::V(..) = E::V(0); + | ^^^^^^ + | + = note: see issue #86935 for more information + = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs new file mode 100644 index 000000000..8e93b1941 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -0,0 +1,17 @@ +// needs-asm-support + +use std::arch::asm; + +#[naked] +//~^ the `#[naked]` attribute is an experimental feature +extern "C" fn naked() { + asm!("", options(noreturn)) +} + +#[naked] +//~^ the `#[naked]` attribute is an experimental feature +extern "C" fn naked_2() -> isize { + asm!("", options(noreturn)) +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr new file mode 100644 index 000000000..4378fb363 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -0,0 +1,21 @@ +error[E0658]: the `#[naked]` attribute is an experimental feature + --> $DIR/feature-gate-naked_functions.rs:5:1 + | +LL | #[naked] + | ^^^^^^^^ + | + = note: see issue #32408 for more information + = help: add `#![feature(naked_functions)]` to the crate attributes to enable + +error[E0658]: the `#[naked]` attribute is an experimental feature + --> $DIR/feature-gate-naked_functions.rs:11:1 + | +LL | #[naked] + | ^^^^^^^^ + | + = note: see issue #32408 for more information + = help: add `#![feature(naked_functions)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs new file mode 100644 index 000000000..132bc6ab0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs @@ -0,0 +1,5 @@ +#[link(name = "foo", kind = "dylib", modifiers = "+as-needed")] +//~^ ERROR: linking modifier `as-needed` is unstable +extern "C" {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr new file mode 100644 index 000000000..2ef6a1c04 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr @@ -0,0 +1,12 @@ +error[E0658]: linking modifier `as-needed` is unstable + --> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:50 + | +LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")] + | ^^^^^^^^^^^^ + | + = note: see issue #81490 for more information + = help: add `#![feature(native_link_modifiers_as_needed)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-needs-allocator.rs b/tests/ui/feature-gates/feature-gate-needs-allocator.rs new file mode 100644 index 000000000..08954944b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-needs-allocator.rs @@ -0,0 +1,3 @@ +#![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-needs-allocator.stderr b/tests/ui/feature-gates/feature-gate-needs-allocator.stderr new file mode 100644 index 000000000..2b213aceb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-needs-allocator.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[needs_allocator]` attribute is an experimental feature + --> $DIR/feature-gate-needs-allocator.rs:1:1 + | +LL | #![needs_allocator] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(allocator_internals)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-negate-unsigned.rs b/tests/ui/feature-gates/feature-gate-negate-unsigned.rs new file mode 100644 index 000000000..05e04f3e2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-negate-unsigned.rs @@ -0,0 +1,18 @@ +// Test that negating unsigned integers doesn't compile + +struct S; +impl std::ops::Neg for S { + type Output = u32; + fn neg(self) -> u32 { 0 } +} + +fn main() { + let _max: usize = -1; + //~^ ERROR cannot apply unary operator `-` to type `usize` + + let x = 5u8; + let _y = -x; + //~^ ERROR cannot apply unary operator `-` to type `u8` + + -S; // should not trigger the gate; issue 26840 +} diff --git a/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr b/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr new file mode 100644 index 000000000..d1f4ed5cb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-negate-unsigned.stderr @@ -0,0 +1,22 @@ +error[E0600]: cannot apply unary operator `-` to type `usize` + --> $DIR/feature-gate-negate-unsigned.rs:10:23 + | +LL | let _max: usize = -1; + | ^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `usize`: `usize::MAX` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `u8` + --> $DIR/feature-gate-negate-unsigned.rs:14:14 + | +LL | let _y = -x; + | ^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/feature-gates/feature-gate-never_type.rs b/tests/ui/feature-gates/feature-gate-never_type.rs new file mode 100644 index 000000000..be8c27dbb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-never_type.rs @@ -0,0 +1,17 @@ +// Test that ! errors when used in illegal positions with feature(never_type) disabled + +trait Foo { + type Wub; +} + +type Ma = (u32, !, i32); //~ ERROR type is experimental +type Meeshka = Vec; //~ ERROR type is experimental +type Mow = &'static fn(!) -> !; //~ ERROR type is experimental +type Skwoz = &'static mut !; //~ ERROR type is experimental + +impl Foo for Meeshka { + type Wub = !; //~ ERROR type is experimental +} + +fn main() { +} diff --git a/tests/ui/feature-gates/feature-gate-never_type.stderr b/tests/ui/feature-gates/feature-gate-never_type.stderr new file mode 100644 index 000000000..0a59cae9c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-never_type.stderr @@ -0,0 +1,48 @@ +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:7:17 + | +LL | type Ma = (u32, !, i32); + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:8:20 + | +LL | type Meeshka = Vec; + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:9:24 + | +LL | type Mow = &'static fn(!) -> !; + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:10:27 + | +LL | type Skwoz = &'static mut !; + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:13:16 + | +LL | type Wub = !; + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-no_core.rs b/tests/ui/feature-gates/feature-gate-no_core.rs new file mode 100644 index 000000000..706efd786 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-no_core.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] + +#![no_core] //~ ERROR the `#[no_core]` attribute is an experimental feature + +pub struct S {} diff --git a/tests/ui/feature-gates/feature-gate-no_core.stderr b/tests/ui/feature-gates/feature-gate-no_core.stderr new file mode 100644 index 000000000..8430a9ec6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-no_core.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_core]` attribute is an experimental feature + --> $DIR/feature-gate-no_core.rs:3:1 + | +LL | #![no_core] + | ^^^^^^^^^^^ + | + = note: see issue #29639 for more information + = help: add `#![feature(no_core)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-no_coverage.rs b/tests/ui/feature-gates/feature-gate-no_coverage.rs new file mode 100644 index 000000000..fd4c6f760 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-no_coverage.rs @@ -0,0 +1,13 @@ +#![crate_type = "lib"] + +#[derive(PartialEq, Eq)] // ensure deriving `Eq` does not enable `feature(no_coverage)` +struct Foo { + a: u8, + b: u32, +} + +#[no_coverage] //~ ERROR the `#[no_coverage]` attribute is an experimental feature +fn requires_feature_no_coverage() -> bool { + let bar = Foo { a: 0, b: 0 }; + bar == Foo { a: 0, b: 0 } +} diff --git a/tests/ui/feature-gates/feature-gate-no_coverage.stderr b/tests/ui/feature-gates/feature-gate-no_coverage.stderr new file mode 100644 index 000000000..f7167e0b7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-no_coverage.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_coverage]` attribute is an experimental feature + --> $DIR/feature-gate-no_coverage.rs:9:1 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + | + = note: see issue #84605 for more information + = help: add `#![feature(no_coverage)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-no_sanitize.rs b/tests/ui/feature-gates/feature-gate-no_sanitize.rs new file mode 100644 index 000000000..66a9263e1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-no_sanitize.rs @@ -0,0 +1,4 @@ +#[no_sanitize(address)] +//~^ the `#[no_sanitize]` attribute is an experimental feature +fn main() { +} diff --git a/tests/ui/feature-gates/feature-gate-no_sanitize.stderr b/tests/ui/feature-gates/feature-gate-no_sanitize.stderr new file mode 100644 index 000000000..399335700 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-no_sanitize.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_sanitize]` attribute is an experimental feature + --> $DIR/feature-gate-no_sanitize.rs:1:1 + | +LL | #[no_sanitize(address)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #39699 for more information + = help: add `#![feature(no_sanitize)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs new file mode 100644 index 000000000..9b646060a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.rs @@ -0,0 +1,34 @@ +// check-fail + +#![deny(non_exhaustive_omitted_patterns)] +//~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` +//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` +#![allow(non_exhaustive_omitted_patterns)] +//~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` +//~| WARNING unknown lint: `non_exhaustive_omitted_patterns` + +fn main() { + enum Foo { + A, B, C, + } + + #[allow(non_exhaustive_omitted_patterns)] + //~^ WARNING unknown lint: `non_exhaustive_omitted_patterns` + //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` + //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` + //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` + match Foo::A { + Foo::A => {} + Foo::B => {} + } + //~^^^^ ERROR non-exhaustive patterns: `Foo::C` not covered + + match Foo::A { + Foo::A => {} + Foo::B => {} + #[warn(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^^ WARNING unknown lint: `non_exhaustive_omitted_patterns` + //~| WARNING unknown lint: `non_exhaustive_omitted_patterns` +} diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr new file mode 100644 index 000000000..4d79ce3c6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr @@ -0,0 +1,124 @@ +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 + | +LL | #![deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 + | +LL | #![allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:3:1 + | +LL | #![deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1 + | +LL | #![allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:15:5 + | +LL | #[allow(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +warning: unknown lint: `non_exhaustive_omitted_patterns` + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:29:9 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `non_exhaustive_omitted_patterns` lint is unstable + = note: see issue #89554 for more information + = help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable + +error[E0004]: non-exhaustive patterns: `Foo::C` not covered + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:20:11 + | +LL | match Foo::A { + | ^^^^^^ pattern `Foo::C` not covered + | +note: `Foo` defined here + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:12:15 + | +LL | enum Foo { + | --- +LL | A, B, C, + | ^ not covered + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Foo::B => {} +LL + Foo::C => todo!() + | + +error: aborting due to previous error; 10 warnings emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs new file mode 100644 index 000000000..37348e476 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs @@ -0,0 +1,41 @@ +// Test that the use of the non object-safe trait objects +// are gated by `object_safe_for_dispatch` feature gate. + +trait NonObjectSafe1: Sized {} + +trait NonObjectSafe2 { + fn static_fn() {} +} + +trait NonObjectSafe3 { + fn foo(&self); +} + +trait NonObjectSafe4 { + fn foo(&self, s: &Self); +} + +fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { + //~^ ERROR E0038 + loop {} +} + +fn takes_non_object_safe_box(obj: Box) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_rc() -> std::rc::Rc { + //~^ ERROR E0038 + loop {} +} + +trait Trait {} + +impl Trait for dyn NonObjectSafe1 {} +//~^ ERROR E0038 + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr new file mode 100644 index 000000000..d76c697fe --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -0,0 +1,83 @@ +error[E0038]: the trait `NonObjectSafe1` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 + | +LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 + | +LL | trait NonObjectSafe1: Sized {} + | -------------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error[E0038]: the trait `NonObjectSafe2` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:45 + | +LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe2` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-object_safe_for_dispatch.rs:7:8 + | +LL | trait NonObjectSafe2 { + | -------------- this trait cannot be made into an object... +LL | fn static_fn() {} + | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter +help: consider turning `static_fn` into a method by giving it a `&self` argument + | +LL | fn static_fn(&self) {} + | +++++ +help: alternatively, consider constraining `static_fn` so it does not apply to trait objects + | +LL | fn static_fn() where Self: Sized {} + | +++++++++++++++++ + +error[E0038]: the trait `NonObjectSafe3` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 + | +LL | fn takes_non_object_safe_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8 + | +LL | trait NonObjectSafe3 { + | -------------- this trait cannot be made into an object... +LL | fn foo(&self); + | ^^^ ...because method `foo` has generic type parameters + = help: consider moving `foo` to another trait + +error[E0038]: the trait `NonObjectSafe4` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:47 + | +LL | fn return_non_object_safe_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 + | +LL | trait NonObjectSafe4 { + | -------------- this trait cannot be made into an object... +LL | fn foo(&self, s: &Self); + | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait + +error[E0038]: the trait `NonObjectSafe1` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 + | +LL | impl Trait for dyn NonObjectSafe1 {} + | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 + | +LL | trait NonObjectSafe1: Sized {} + | -------------- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs b/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs new file mode 100644 index 000000000..66bf79738 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.rs @@ -0,0 +1,2 @@ +#[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr b/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr new file mode 100644 index 000000000..a5ec3599f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-omit-gdb-pretty-printer-section.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite + --> $DIR/feature-gate-omit-gdb-pretty-printer-section.rs:1:1 + | +LL | #[omit_gdb_pretty_printer_section] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(omit_gdb_pretty_printer_section)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs new file mode 100644 index 000000000..15aa3a6af --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs @@ -0,0 +1,18 @@ +#![crate_type="rlib"] +#![optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature + +#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature +mod module { + +#[optimize(size)] //~ ERROR the `#[optimize]` attribute is an experimental feature +fn size() {} + +#[optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature +fn speed() {} + +#[optimize(banana)] +//~^ ERROR the `#[optimize]` attribute is an experimental feature +//~| ERROR E0722 +fn not_known() {} + +} diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr new file mode 100644 index 000000000..a3ced3515 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -0,0 +1,55 @@ +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:7:1 + | +LL | #[optimize(size)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:10:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:13:1 + | +LL | #[optimize(banana)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:4:1 + | +LL | #[optimize(size)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + +error[E0658]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:2:1 + | +LL | #![optimize(speed)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 for more information + = help: add `#![feature(optimize_attribute)]` to the crate attributes to enable + +error[E0722]: invalid argument + --> $DIR/feature-gate-optimize_attribute.rs:13:12 + | +LL | #[optimize(banana)] + | ^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0658, E0722. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.rs b/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.rs new file mode 100644 index 000000000..6922d6f83 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.rs @@ -0,0 +1,9 @@ +use std::fmt::{Debug, Display}; + +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for T {} +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr b/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr new file mode 100644 index 000000000..0526c6dc8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-overlapping_marker_traits.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyMarker` + --> $DIR/feature-gate-overlapping_marker_traits.rs:6:1 + | +LL | impl MyMarker for T {} + | ------------------------------- first implementation here +LL | impl MyMarker for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs new file mode 100644 index 000000000..4c77180b7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs @@ -0,0 +1,17 @@ +fn main() { + match 0usize { + //~^ ERROR non-exhaustive patterns: `_` not covered + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `usize` + //~| NOTE `usize` does not have a fixed maximum value + 0..=usize::MAX => {} + } + + match 0isize { + //~^ ERROR non-exhaustive patterns: `_` not covered + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `isize` + //~| NOTE `isize` does not have a fixed maximum value + isize::MIN..=isize::MAX => {} + } +} diff --git a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr new file mode 100644 index 000000000..b55106833 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr @@ -0,0 +1,33 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/feature-gate-precise_pointer_size_matching.rs:2:11 + | +LL | match 0usize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 0..=usize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ isize::MIN..=isize::MAX => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/feature-gates/feature-gate-prelude_import.rs b/tests/ui/feature-gates/feature-gate-prelude_import.rs new file mode 100644 index 000000000..a338bf973 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-prelude_import.rs @@ -0,0 +1,4 @@ +#[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only +use std::prelude::v1::*; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-prelude_import.stderr b/tests/ui/feature-gates/feature-gate-prelude_import.stderr new file mode 100644 index 000000000..8686aed8f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-prelude_import.stderr @@ -0,0 +1,11 @@ +error[E0658]: `#[prelude_import]` is for use by rustc only + --> $DIR/feature-gate-prelude_import.rs:1:1 + | +LL | #[prelude_import] + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(prelude_import)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-profiler-runtime.rs b/tests/ui/feature-gates/feature-gate-profiler-runtime.rs new file mode 100644 index 000000000..f8a709634 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-profiler-runtime.rs @@ -0,0 +1,3 @@ +#![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr b/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr new file mode 100644 index 000000000..18e6503c5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-profiler-runtime.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable + --> $DIR/feature-gate-profiler-runtime.rs:1:1 + | +LL | #![profiler_runtime] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(profiler_runtime)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-public_private_dependencies.rs b/tests/ui/feature-gates/feature-gate-public_private_dependencies.rs new file mode 100644 index 000000000..b8fb4b8dc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-public_private_dependencies.rs @@ -0,0 +1,20 @@ +// This test is different from other feature gate tests. +// Instead of checking that an error occurs without the feature gate, +// it checks that *no* errors/warnings occurs without the feature gate. +// This is due to the fact that 'public_private_dependencies' just enables +// a lint, so disabling it shouldn't cause any code to stop compiling. + +// run-pass +// aux-build:pub_dep.rs + +// Without ![feature(public_private_dependencies)], +// this should do nothing/ +#![deny(exported_private_dependencies)] + +extern crate pub_dep; + +pub struct Foo { + pub field: pub_dep::PubType +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-2.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-2.rs new file mode 100644 index 000000000..fc47a9061 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-2.rs @@ -0,0 +1,12 @@ +// only-x86 +#[link(name = "foo")] +extern "C" { + #[link_ordinal(42)] + //~^ ERROR: `#[link_ordinal]` is unstable on x86 + fn foo(); + #[link_ordinal(5)] + //~^ ERROR: `#[link_ordinal]` is unstable on x86 + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr new file mode 100644 index 000000000..0e900760d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr @@ -0,0 +1,21 @@ +error[E0658]: `#[link_ordinal]` is unstable on x86 + --> $DIR/feature-gate-raw-dylib-2.rs:4:5 + | +LL | #[link_ordinal(42)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #58713 for more information + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error[E0658]: `#[link_ordinal]` is unstable on x86 + --> $DIR/feature-gate-raw-dylib-2.rs:7:5 + | +LL | #[link_ordinal(5)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #58713 for more information + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs new file mode 100644 index 000000000..295f502d6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs @@ -0,0 +1,8 @@ +// only-windows +// only-x86 +#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] +//~^ ERROR link kind `raw-dylib` is unstable on x86 +//~| ERROR import name type is unstable +extern "C" {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr new file mode 100644 index 000000000..d6b165b76 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr @@ -0,0 +1,21 @@ +error[E0658]: link kind `raw-dylib` is unstable on x86 + --> $DIR/feature-gate-raw-dylib-import-name-type.rs:3:29 + | +LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] + | ^^^^^^^^^^^ + | + = note: see issue #58713 for more information + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error[E0658]: import name type is unstable + --> $DIR/feature-gate-raw-dylib-import-name-type.rs:3:61 + | +LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] + | ^^^^^^^^^^^ + | + = note: see issue #58713 for more information + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib.rs b/tests/ui/feature-gates/feature-gate-raw-dylib.rs new file mode 100644 index 000000000..291cca8fd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib.rs @@ -0,0 +1,7 @@ +// only-windows +// only-x86 +#[link(name = "foo", kind = "raw-dylib")] +//~^ ERROR: link kind `raw-dylib` is unstable on x86 +extern "C" {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib.stderr new file mode 100644 index 000000000..f02241e49 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib.stderr @@ -0,0 +1,12 @@ +error[E0658]: link kind `raw-dylib` is unstable on x86 + --> $DIR/feature-gate-raw-dylib.rs:3:29 + | +LL | #[link(name = "foo", kind = "raw-dylib")] + | ^^^^^^^^^^^ + | + = note: see issue #58713 for more information + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-register_tool.rs b/tests/ui/feature-gates/feature-gate-register_tool.rs new file mode 100644 index 000000000..e59959328 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-register_tool.rs @@ -0,0 +1,3 @@ +#![register_tool(tool)] //~ ERROR the `#[register_tool]` attribute is an experimental feature + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-register_tool.stderr b/tests/ui/feature-gates/feature-gate-register_tool.stderr new file mode 100644 index 000000000..9ffaaa8de --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-register_tool.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[register_tool]` attribute is an experimental feature + --> $DIR/feature-gate-register_tool.rs:1:1 + | +LL | #![register_tool(tool)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #66079 for more information + = help: add `#![feature(register_tool)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.rs b/tests/ui/feature-gates/feature-gate-repr-simd.rs new file mode 100644 index 000000000..c527404f5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-repr-simd.rs @@ -0,0 +1,9 @@ +#[repr(simd)] //~ error: SIMD types are experimental +struct Foo(u64, u64); + +#[repr(C)] //~ ERROR conflicting representation hints +//~^ WARN this was previously accepted +#[repr(simd)] //~ error: SIMD types are experimental +struct Bar(u64, u64); + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.stderr b/tests/ui/feature-gates/feature-gate-repr-simd.stderr new file mode 100644 index 000000000..5b1270a19 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-repr-simd.stderr @@ -0,0 +1,35 @@ +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/feature-gate-repr-simd.rs:1:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/feature-gate-repr-simd.rs:6:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error[E0566]: conflicting representation hints + --> $DIR/feature-gate-repr-simd.rs:4:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | #[repr(simd)] + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0566, E0658. +For more information about an error, try `rustc --explain E0566`. diff --git a/tests/ui/feature-gates/feature-gate-repr128.rs b/tests/ui/feature-gates/feature-gate-repr128.rs new file mode 100644 index 000000000..0290874dd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-repr128.rs @@ -0,0 +1,6 @@ +#[repr(u128)] +enum A { //~ ERROR repr with 128-bit type is unstable + A(u64) +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-repr128.stderr b/tests/ui/feature-gates/feature-gate-repr128.stderr new file mode 100644 index 000000000..3999a6d2d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-repr128.stderr @@ -0,0 +1,12 @@ +error[E0658]: repr with 128-bit type is unstable + --> $DIR/feature-gate-repr128.rs:2:1 + | +LL | enum A { + | ^^^^^^ + | + = note: see issue #56071 for more information + = help: add `#![feature(repr128)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs new file mode 100644 index 000000000..637765fff --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs @@ -0,0 +1,18 @@ +// edition:2021 + +// async_fn_in_trait is not enough to allow use of RPITIT +#![allow(incomplete_features)] +#![feature(async_fn_in_trait)] + +trait Foo { + fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return + fn baz() -> Box; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return +} + +// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also +// feature-gate-async_fn_in_trait.rs) +trait AsyncFoo { + async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr new file mode 100644 index 000000000..aeabed4a6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr @@ -0,0 +1,30 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17 + | +LL | fn bar() -> impl Sized; + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21 + | +LL | fn baz() -> Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23 + | +LL | async fn bar() -> impl Sized; + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs b/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs new file mode 100644 index 000000000..9ba8e32ac --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs @@ -0,0 +1,21 @@ +#![crate_type = "lib"] + +extern "rust-cold" fn fu() {} //~ ERROR rust-cold is experimental + +trait T { + extern "rust-cold" fn mu(); //~ ERROR rust-cold is experimental + extern "rust-cold" fn dmu() {} //~ ERROR rust-cold is experimental +} + +struct S; +impl T for S { + extern "rust-cold" fn mu() {} //~ ERROR rust-cold is experimental +} + +impl S { + extern "rust-cold" fn imu() {} //~ ERROR rust-cold is experimental +} + +type TAU = extern "rust-cold" fn(); //~ ERROR rust-cold is experimental + +extern "rust-cold" {} //~ ERROR rust-cold is experimental diff --git a/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr b/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr new file mode 100644 index 000000000..ab7e5f036 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr @@ -0,0 +1,66 @@ +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:3:8 + | +LL | extern "rust-cold" fn fu() {} + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:6:12 + | +LL | extern "rust-cold" fn mu(); + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:7:12 + | +LL | extern "rust-cold" fn dmu() {} + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:12:12 + | +LL | extern "rust-cold" fn mu() {} + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:16:12 + | +LL | extern "rust-cold" fn imu() {} + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:19:19 + | +LL | type TAU = extern "rust-cold" fn(); + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error[E0658]: rust-cold is experimental and subject to change + --> $DIR/feature-gate-rust_cold_cc.rs:21:8 + | +LL | extern "rust-cold" {} + | ^^^^^^^^^^^ + | + = note: see issue #97544 for more information + = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs new file mode 100644 index 000000000..19d8fa87f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.rs @@ -0,0 +1,6 @@ +#![allow(unused_macros)] + +#[rustc_allow_const_fn_unstable()] //~ ERROR rustc_allow_const_fn_unstable side-steps +const fn foo() { } + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr new file mode 100644 index 000000000..a549cb64e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-allow-const-fn-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: rustc_allow_const_fn_unstable side-steps feature gating and stability checks + --> $DIR/feature-gate-rustc-allow-const-fn-unstable.rs:3:1 + | +LL | #[rustc_allow_const_fn_unstable()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #69399 for more information + = help: add `#![feature(rustc_allow_const_fn_unstable)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs new file mode 100644 index 000000000..667bc9f8d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs @@ -0,0 +1,7 @@ +// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. + +#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable +#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable +#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr new file mode 100644 index 000000000..45a095903 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -0,0 +1,27 @@ +error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable + --> $DIR/feature-gate-rustc-attrs-1.rs:3:1 + | +LL | #[rustc_variance] + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable + --> $DIR/feature-gate-rustc-attrs-1.rs:4:1 + | +LL | #[rustc_error] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable + --> $DIR/feature-gate-rustc-attrs-1.rs:5:1 + | +LL | #[rustc_nonnull_optimization_guaranteed] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs.rs new file mode 100644 index 000000000..c985298a3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs.rs @@ -0,0 +1,23 @@ +// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. + +#![feature(decl_macro)] + +mod rustc { pub macro unknown() {} } +mod unknown { pub macro rustc() {} } + +#[rustc::unknown] +//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler +//~| ERROR expected attribute, found macro `rustc::unknown` +fn f() {} + +#[unknown::rustc] +//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler +//~| ERROR expected attribute, found macro `unknown::rustc` +fn g() {} + +#[rustc_dummy] +//~^ ERROR the `#[rustc_dummy]` attribute is just used for rustc unit tests +#[rustc_unknown] +//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler +//~| ERROR cannot find attribute `rustc_unknown` in this scope +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr new file mode 100644 index 000000000..1517a7a5c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -0,0 +1,47 @@ +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/feature-gate-rustc-attrs.rs:8:3 + | +LL | #[rustc::unknown] + | ^^^^^ + +error: expected attribute, found macro `rustc::unknown` + --> $DIR/feature-gate-rustc-attrs.rs:8:3 + | +LL | #[rustc::unknown] + | ^^^^^^^^^^^^^^ not an attribute + +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/feature-gate-rustc-attrs.rs:13:12 + | +LL | #[unknown::rustc] + | ^^^^^ + +error: expected attribute, found macro `unknown::rustc` + --> $DIR/feature-gate-rustc-attrs.rs:13:3 + | +LL | #[unknown::rustc] + | ^^^^^^^^^^^^^^ not an attribute + +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/feature-gate-rustc-attrs.rs:20:3 + | +LL | #[rustc_unknown] + | ^^^^^^^^^^^^^ + +error: cannot find attribute `rustc_unknown` in this scope + --> $DIR/feature-gate-rustc-attrs.rs:20:3 + | +LL | #[rustc_unknown] + | ^^^^^^^^^^^^^ + +error[E0658]: the `#[rustc_dummy]` attribute is just used for rustc unit tests and will never be stable + --> $DIR/feature-gate-rustc-attrs.rs:18:1 + | +LL | #[rustc_dummy] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs new file mode 100644 index 000000000..d7daaaaa1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs @@ -0,0 +1,7 @@ +// Test internal const fn feature gate. + +#[rustc_const_unstable(feature="fzzzzzt")] //~ stability attributes may not be used outside +pub const fn bazinga() {} + +fn main() { +} diff --git a/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr new file mode 100644 index 000000000..48493b786 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.stderr @@ -0,0 +1,9 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/feature-gate-rustc_const_unstable.rs:3:1 + | +LL | #[rustc_const_unstable(feature="fzzzzzt")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs new file mode 100644 index 000000000..58306a4cf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -0,0 +1,10 @@ +#[doc(keyword = "match")] //~ ERROR: `#[doc(keyword)]` is meant for internal use only +/// wonderful +mod foo {} + +trait Mine {} + +#[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only +impl Mine for (T,) {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr new file mode 100644 index 000000000..c4272a2c0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -0,0 +1,21 @@ +error[E0658]: `#[doc(keyword)]` is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:1:1 + | +LL | #[doc(keyword = "match")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable + +error[E0658]: `#[doc(fake_variadic)]` is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:7:1 + | +LL | #[doc(fake_variadic)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-simd-ffi.rs b/tests/ui/feature-gates/feature-gate-simd-ffi.rs new file mode 100644 index 000000000..abffa4a10 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-simd-ffi.rs @@ -0,0 +1,13 @@ +#![feature(repr_simd)] +#![allow(dead_code)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct LocalSimd(u8, u8); + +extern "C" { + fn baz() -> LocalSimd; //~ ERROR use of SIMD type + fn qux(x: LocalSimd); //~ ERROR use of SIMD type +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-simd-ffi.stderr b/tests/ui/feature-gates/feature-gate-simd-ffi.stderr new file mode 100644 index 000000000..8166b6baa --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-simd-ffi.stderr @@ -0,0 +1,18 @@ +error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code + --> $DIR/feature-gate-simd-ffi.rs:9:17 + | +LL | fn baz() -> LocalSimd; + | ^^^^^^^^^ + | + = help: add `#![feature(simd_ffi)]` to the crate attributes to enable + +error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code + --> $DIR/feature-gate-simd-ffi.rs:10:15 + | +LL | fn qux(x: LocalSimd); + | ^^^^^^^^^ + | + = help: add `#![feature(simd_ffi)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-simd.rs b/tests/ui/feature-gates/feature-gate-simd.rs new file mode 100644 index 000000000..d01d33de2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-simd.rs @@ -0,0 +1,11 @@ +// pretty-expanded FIXME #23616 + +#[repr(simd)] //~ ERROR SIMD types are experimental +struct RGBA { + r: f32, + g: f32, + b: f32, + a: f32 +} + +pub fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-simd.stderr b/tests/ui/feature-gates/feature-gate-simd.stderr new file mode 100644 index 000000000..6e0e0b270 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-simd.stderr @@ -0,0 +1,12 @@ +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/feature-gate-simd.rs:3:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-staged_api.rs b/tests/ui/feature-gates/feature-gate-staged_api.rs new file mode 100644 index 000000000..2571ab5d1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-staged_api.rs @@ -0,0 +1,14 @@ +#![stable(feature = "a", since = "b")] +//~^ ERROR stability attributes may not be used outside of the standard library +mod inner_private_module { + // UnnameableTypeAlias isn't marked as reachable, so no stability annotation is required here + pub type UnnameableTypeAlias = u8; +} + +#[stable(feature = "a", since = "b")] +//~^ ERROR stability attributes may not be used outside of the standard library +pub fn f() -> inner_private_module::UnnameableTypeAlias { + 0 +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-staged_api.stderr b/tests/ui/feature-gates/feature-gate-staged_api.stderr new file mode 100644 index 000000000..951bb5a17 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-staged_api.stderr @@ -0,0 +1,15 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/feature-gate-staged_api.rs:8:1 + | +LL | #[stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/feature-gate-staged_api.rs:1:1 + | +LL | #![stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/feature-gate-start.rs b/tests/ui/feature-gates/feature-gate-start.rs new file mode 100644 index 000000000..e617f1c47 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-start.rs @@ -0,0 +1,3 @@ +#[start] +fn foo(_: isize, _: *const *const u8) -> isize { 0 } +//~^ ERROR `#[start]` functions are experimental diff --git a/tests/ui/feature-gates/feature-gate-start.stderr b/tests/ui/feature-gates/feature-gate-start.stderr new file mode 100644 index 000000000..eec9d1a29 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-start.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[start]` functions are experimental and their signature may change over time + --> $DIR/feature-gate-start.rs:2:1 + | +LL | fn foo(_: isize, _: *const *const u8) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29633 for more information + = help: add `#![feature(start)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs new file mode 100644 index 000000000..f213e8933 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs @@ -0,0 +1,4 @@ +const X: i32 = #[allow(dead_code)] 8; +//~^ ERROR attributes on expressions are experimental + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr new file mode 100644 index 000000000..57ffaed78 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr @@ -0,0 +1,12 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/feature-gate-stmt_expr_attributes.rs:1:16 + | +LL | const X: i32 = #[allow(dead_code)] 8; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.rs b/tests/ui/feature-gates/feature-gate-strict_provenance.rs new file mode 100644 index 000000000..75d0ee570 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-strict_provenance.rs @@ -0,0 +1,19 @@ +// check-pass + +#![deny(fuzzy_provenance_casts)] +//~^ WARNING unknown lint: `fuzzy_provenance_casts` +//~| WARNING unknown lint: `fuzzy_provenance_casts` +//~| WARNING unknown lint: `fuzzy_provenance_casts` +#![deny(lossy_provenance_casts)] +//~^ WARNING unknown lint: `lossy_provenance_casts` +//~| WARNING unknown lint: `lossy_provenance_casts` +//~| WARNING unknown lint: `lossy_provenance_casts` + +fn main() { + // no warnings emitted since the lints are not activated + + let _dangling = 16_usize as *const u8; + + let x: u8 = 37; + let _addr: usize = &x as *const u8 as usize; +} diff --git a/tests/ui/feature-gates/feature-gate-strict_provenance.stderr b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr new file mode 100644 index 000000000..751da87cc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-strict_provenance.stderr @@ -0,0 +1,63 @@ +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `fuzzy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:3:1 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `fuzzy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: unknown lint: `lossy_provenance_casts` + --> $DIR/feature-gate-strict_provenance.rs:7:1 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `lossy_provenance_casts` lint is unstable + = note: see issue #95228 for more information + = help: add `#![feature(strict_provenance)]` to the crate attributes to enable + +warning: 6 warnings emitted + diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs b/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs new file mode 100644 index 000000000..c398394cb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.rs @@ -0,0 +1,9 @@ +// check-pass + +// `test_unstable_lint` is for testing and should never be stabilized. +#![allow(test_unstable_lint)] +//~^ WARNING unknown lint: `test_unstable_lint` +//~| WARNING unknown lint: `test_unstable_lint` +//~| WARNING unknown lint: `test_unstable_lint` + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr new file mode 100644 index 000000000..b4d6aa658 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-test_unstable_lint.stderr @@ -0,0 +1,30 @@ +warning: unknown lint: `test_unstable_lint` + --> $DIR/feature-gate-test_unstable_lint.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `test_unstable_lint` + --> $DIR/feature-gate-test_unstable_lint.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +warning: unknown lint: `test_unstable_lint` + --> $DIR/feature-gate-test_unstable_lint.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +warning: 3 warnings emitted + diff --git a/tests/ui/feature-gates/feature-gate-thread_local.rs b/tests/ui/feature-gates/feature-gate-thread_local.rs new file mode 100644 index 000000000..0efae1f6b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-thread_local.rs @@ -0,0 +1,11 @@ +// Test that `#[thread_local]` attribute is gated by `thread_local` +// feature gate. +// +// (Note that the `thread_local!` macro is explicitly *not* gated; it +// is given permission to expand into this unstable attribute even +// when the surrounding context does not have permission to use it.) + +#[thread_local] //~ ERROR `#[thread_local]` is an experimental feature +static FOO: i32 = 3; + +pub fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-thread_local.stderr b/tests/ui/feature-gates/feature-gate-thread_local.stderr new file mode 100644 index 000000000..6352e9087 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-thread_local.stderr @@ -0,0 +1,12 @@ +error[E0658]: `#[thread_local]` is an experimental feature, and does not currently handle destructors + --> $DIR/feature-gate-thread_local.rs:8:1 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #29594 for more information + = help: add `#![feature(thread_local)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trace_macros.rs b/tests/ui/feature-gates/feature-gate-trace_macros.rs new file mode 100644 index 000000000..07159b7b5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trace_macros.rs @@ -0,0 +1,3 @@ +fn main() { + trace_macros!(true); //~ ERROR: `trace_macros` is not stable +} diff --git a/tests/ui/feature-gates/feature-gate-trace_macros.stderr b/tests/ui/feature-gates/feature-gate-trace_macros.stderr new file mode 100644 index 000000000..3978d4111 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trace_macros.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change + --> $DIR/feature-gate-trace_macros.rs:2:5 + | +LL | trace_macros!(true); + | ^^^^^^^^^^^^ + | + = note: see issue #29598 for more information + = help: add `#![feature(trace_macros)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trait-alias.rs b/tests/ui/feature-gates/feature-gate-trait-alias.rs new file mode 100644 index 000000000..819085add --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trait-alias.rs @@ -0,0 +1,4 @@ +trait Foo = Default; +//~^ ERROR trait aliases are experimental + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-trait-alias.stderr b/tests/ui/feature-gates/feature-gate-trait-alias.stderr new file mode 100644 index 000000000..41cd6dbd8 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trait-alias.stderr @@ -0,0 +1,12 @@ +error[E0658]: trait aliases are experimental + --> $DIR/feature-gate-trait-alias.rs:1:1 + | +LL | trait Foo = Default; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #41517 for more information + = help: add `#![feature(trait_alias)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.rs b/tests/ui/feature-gates/feature-gate-trait_upcasting.rs new file mode 100644 index 000000000..e4102f1cf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trait_upcasting.rs @@ -0,0 +1,13 @@ +trait Foo {} + +trait Bar: Foo {} + +impl Foo for () {} + +impl Bar for () {} + +fn main() { + let bar: &dyn Bar = &(); + let foo: &dyn Foo = bar; + //~^ ERROR trait upcasting coercion is experimental [E0658] +} diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr b/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr new file mode 100644 index 000000000..93afa7845 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr @@ -0,0 +1,13 @@ +error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental + --> $DIR/feature-gate-trait_upcasting.rs:11:25 + | +LL | let foo: &dyn Foo = bar; + | ^^^ + | + = note: see issue #65991 for more information + = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable + = note: required when coercing `&dyn Bar` into `&dyn Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-transparent_unions.rs b/tests/ui/feature-gates/feature-gate-transparent_unions.rs new file mode 100644 index 000000000..73cac0a49 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-transparent_unions.rs @@ -0,0 +1,7 @@ +#[repr(transparent)] +union OkButUnstableUnion { //~ ERROR transparent unions are unstable + field: u8, + zst: (), +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-transparent_unions.stderr b/tests/ui/feature-gates/feature-gate-transparent_unions.stderr new file mode 100644 index 000000000..65c8fe052 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-transparent_unions.stderr @@ -0,0 +1,12 @@ +error[E0658]: transparent unions are unstable + --> $DIR/feature-gate-transparent_unions.rs:2:1 + | +LL | union OkButUnstableUnion { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #60405 for more information + = help: add `#![feature(transparent_unions)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds-lint.rs b/tests/ui/feature-gates/feature-gate-trivial_bounds-lint.rs new file mode 100644 index 000000000..8f68d5d6d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds-lint.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(unused)] +#![deny(trivial_bounds)] // Ignored without the trivial_bounds feature flag. + +struct A where i32: Copy; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.rs b/tests/ui/feature-gates/feature-gate-trivial_bounds.rs new file mode 100644 index 000000000..3dbaf5dea --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.rs @@ -0,0 +1,69 @@ +#![allow(unused)] +#![allow(type_alias_bounds)] + +pub trait Foo { + fn test(&self); +} + +fn generic_function(x: X) {} + +enum E where i32: Foo { V } //~ ERROR + +struct S where i32: Foo; //~ ERROR + +trait T where i32: Foo {} //~ ERROR + +union U where i32: Foo { f: i32 } //~ ERROR + +type Y where i32: Foo = (); // OK - bound is ignored + +impl Foo for () where i32: Foo { //~ ERROR + fn test(&self) { + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); + } +} + +fn f() where i32: Foo //~ ERROR +{ + let s = S; + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn use_op(s: String) -> String where String: ::std::ops::Neg { //~ ERROR + -s +} + +fn use_for() where i32: Iterator { //~ ERROR + for _ in 2i32 {} +} + +trait A {} + +impl A for i32 {} + +struct Dst { + x: X, +} + +struct TwoStrs(str, str) where str: Sized; //~ ERROR + + +fn unsized_local() where Dst: Sized { //~ ERROR + let x: Dst = *(Box::new(Dst { x: 1 }) as Box>); +} + +fn return_str() -> str where str: Sized { //~ ERROR + *"Sized".to_string().into_boxed_str() +} + +// This is currently accepted because the function pointer isn't +// considered global. +fn global_hr(x: fn(&())) where fn(&()): Foo { // OK + x.test(); +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr new file mode 100644 index 000000000..1b87ebd9f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -0,0 +1,118 @@ +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:10:14 + | +LL | enum E where i32: Foo { V } + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` + | + = help: the trait `Foo` is implemented for `()` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:12:16 + | +LL | struct S where i32: Foo; + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` + | + = help: the trait `Foo` is implemented for `()` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:14:15 + | +LL | trait T where i32: Foo {} + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` + | + = help: the trait `Foo` is implemented for `()` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:16:15 + | +LL | union U where i32: Foo { f: i32 } + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` + | + = help: the trait `Foo` is implemented for `()` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:20:23 + | +LL | impl Foo for () where i32: Foo { + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` + | + = help: the trait `Foo` is implemented for `()` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:28:14 + | +LL | fn f() where i32: Foo + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` + | + = help: the trait `Foo` is implemented for `()` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `String: Neg` is not satisfied + --> $DIR/feature-gate-trivial_bounds.rs:36:38 + | +LL | fn use_op(s: String) -> String where String: ::std::ops::Neg { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Neg` is not implemented for `String` + | + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: `i32` is not an iterator + --> $DIR/feature-gate-trivial_bounds.rs:40:20 + | +LL | fn use_for() where i32: Iterator { + | ^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/feature-gate-trivial_bounds.rs:52:32 + | +LL | struct TwoStrs(str, str) where str: Sized; + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-trivial_bounds.rs:55:26 + | +LL | fn unsized_local() where Dst: Sized { + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` +note: required because it appears within the type `Dst<(dyn A + 'static)>` + --> $DIR/feature-gate-trivial_bounds.rs:48:8 + | +LL | struct Dst { + | ^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/feature-gate-trivial_bounds.rs:59:30 + | +LL | fn return_str() -> str where str: Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.rs b/tests/ui/feature-gates/feature-gate-try_blocks.rs new file mode 100644 index 000000000..06cadd82c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-try_blocks.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition 2018 + +pub fn main() { + let try_result: Option<_> = try { //~ ERROR `try` expression is experimental + let x = 5; + x + }; + assert_eq!(try_result, Some(5)); +} diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.stderr b/tests/ui/feature-gates/feature-gate-try_blocks.stderr new file mode 100644 index 000000000..022409f95 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-try_blocks.stderr @@ -0,0 +1,16 @@ +error[E0658]: `try` expression is experimental + --> $DIR/feature-gate-try_blocks.rs:4:33 + | +LL | let try_result: Option<_> = try { + | _________________________________^ +LL | | let x = 5; +LL | | x +LL | | }; + | |_____^ + | + = note: see issue #31436 for more information + = help: add `#![feature(try_blocks)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs new file mode 100644 index 000000000..6dfd7f684 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -0,0 +1,34 @@ +// ignore-compare-mode-chalk +// check-pass +#![feature(type_alias_impl_trait)] +use std::fmt::Debug; + +type Foo = impl Debug; + +struct Bar(Foo); +fn define() -> Bar { + Bar(42) +} + +type Foo2 = impl Debug; + +fn define2() { + let x = || -> Foo2 { 42 }; +} + +type Foo3 = impl Debug; + +fn define3(x: Foo3) { + let y: i32 = x; +} +fn define3_1() { + define3(42) +} + +type Foo4 = impl Debug; + +fn define4() { + let y: Foo4 = 42; +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.rs b/tests/ui/feature-gates/feature-gate-type_ascription.rs new file mode 100644 index 000000000..7a5971573 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-type_ascription.rs @@ -0,0 +1,5 @@ +// Type ascription is unstable + +fn main() { + let a = 10: u8; //~ ERROR type ascription is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.stderr b/tests/ui/feature-gates/feature-gate-type_ascription.stderr new file mode 100644 index 000000000..615d5b9a1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-type_ascription.stderr @@ -0,0 +1,12 @@ +error[E0658]: type ascription is experimental + --> $DIR/feature-gate-type_ascription.rs:4:13 + | +LL | let a = 10: u8; + | ^^^^^^ + | + = note: see issue #23416 for more information + = help: add `#![feature(type_ascription)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs new file mode 100644 index 000000000..eecf2046c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs @@ -0,0 +1,37 @@ +// Test that manual impls of the `Fn` traits are not possible without +// a feature gate. In fact, the specialized check for these cases +// never triggers (yet), because they encounter other problems around +// angle bracket vs parentheses notation. + +#![feature(fn_traits)] + +struct Foo; +impl Fn<()> for Foo { +//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change +//~| ERROR manual implementations of `Fn` are experimental + extern "rust-call" fn call(self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change +} +struct Foo1; +impl FnOnce() for Foo1 { +//~^ ERROR associated type bindings are not allowed here +//~| ERROR manual implementations of `FnOnce` are experimental + extern "rust-call" fn call_once(self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change +} +struct Bar; +impl FnMut<()> for Bar { +//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change +//~| ERROR manual implementations of `FnMut` are experimental + extern "rust-call" fn call_mut(&self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change +} +struct Baz; +impl FnOnce<()> for Baz { +//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change +//~| ERROR manual implementations of `FnOnce` are experimental + extern "rust-call" fn call_once(&self, args: ()) -> () {} + //~^ ERROR rust-call ABI is subject to change +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr new file mode 100644 index 000000000..f647380ef --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -0,0 +1,105 @@ +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:12:12 + | +LL | extern "rust-call" fn call(self, args: ()) -> () {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:19:12 + | +LL | extern "rust-call" fn call_once(self, args: ()) -> () {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:26:12 + | +LL | extern "rust-call" fn call_mut(&self, args: ()) -> () {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:33:12 + | +LL | extern "rust-call" fn call_once(&self, args: ()) -> () {} + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6 + | +LL | impl Fn<()> for Foo { + | ^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0183]: manual implementations of `Fn` are experimental + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:6 + | +LL | impl Fn<()> for Foo { + | ^^^^^^ manual implementations of `Fn` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0183]: manual implementations of `FnOnce` are experimental + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6 + | +LL | impl FnOnce() for Foo1 { + | ^^^^^^^^ manual implementations of `FnOnce` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0229]: associated type bindings are not allowed here + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6 + | +LL | impl FnOnce() for Foo1 { + | ^^^^^^^^ associated type not allowed here + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6 + | +LL | impl FnMut<()> for Bar { + | ^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0183]: manual implementations of `FnMut` are experimental + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6 + | +LL | impl FnMut<()> for Bar { + | ^^^^^^^^^ manual implementations of `FnMut` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6 + | +LL | impl FnOnce<()> for Baz { + | ^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0183]: manual implementations of `FnOnce` are experimental + --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:6 + | +LL | impl FnOnce<()> for Baz { + | ^^^^^^^^^^ manual implementations of `FnOnce` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0183, E0229, E0658. +For more information about an error, try `rustc --explain E0183`. diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs new file mode 100644 index 000000000..42f7c5f0f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs @@ -0,0 +1,9 @@ +#![allow(dead_code)] + +fn foo(mut f: F) { + f.call(()); //~ ERROR use of unstable library feature 'fn_traits' + f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits' + f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits' +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr new file mode 100644 index 000000000..c61382c64 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr @@ -0,0 +1,30 @@ +error[E0658]: use of unstable library feature 'fn_traits' + --> $DIR/feature-gate-unboxed-closures-method-calls.rs:4:7 + | +LL | f.call(()); + | ^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(fn_traits)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'fn_traits' + --> $DIR/feature-gate-unboxed-closures-method-calls.rs:5:7 + | +LL | f.call_mut(()); + | ^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(fn_traits)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'fn_traits' + --> $DIR/feature-gate-unboxed-closures-method-calls.rs:6:7 + | +LL | f.call_once(()); + | ^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(fn_traits)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs new file mode 100644 index 000000000..25c90492e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs @@ -0,0 +1,9 @@ +#![allow(dead_code)] + +fn foo(mut f: F) { + Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits' + FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits' + FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits' +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr new file mode 100644 index 000000000..50eaeecde --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr @@ -0,0 +1,30 @@ +error[E0658]: use of unstable library feature 'fn_traits' + --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:4:5 + | +LL | Fn::call(&f, ()); + | ^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(fn_traits)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'fn_traits' + --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:5:5 + | +LL | FnMut::call_mut(&mut f, ()); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(fn_traits)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'fn_traits' + --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:6:5 + | +LL | FnOnce::call_once(f, ()); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(fn_traits)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures.rs new file mode 100644 index 000000000..ebc5a2536 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures.rs @@ -0,0 +1,18 @@ +#![feature(fn_traits)] + +struct Test; + +impl FnOnce<(u32, u32)> for Test { +//~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change +//~| ERROR manual implementations of `FnOnce` are experimental + type Output = u32; + + extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { + a + b + } + //~^^^ ERROR rust-call ABI is subject to change +} + +fn main() { + assert_eq!(Test(1u32, 2u32), 3u32); +} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr new file mode 100644 index 000000000..a763c28de --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr @@ -0,0 +1,30 @@ +error[E0658]: rust-call ABI is subject to change + --> $DIR/feature-gate-unboxed-closures.rs:10:12 + | +LL | extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { + | ^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/feature-gate-unboxed-closures.rs:5:6 + | +LL | impl FnOnce<(u32, u32)> for Test { + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0183]: manual implementations of `FnOnce` are experimental + --> $DIR/feature-gate-unboxed-closures.rs:5:6 + | +LL | impl FnOnce<(u32, u32)> for Test { + | ^^^^^^^^^^^^^^^^^^ manual implementations of `FnOnce` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0183, E0658. +For more information about an error, try `rustc --explain E0183`. diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs b/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs new file mode 100644 index 000000000..46dc3f6cc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unix_sigpipe.rs @@ -0,0 +1,4 @@ +#![crate_type = "bin"] + +#[unix_sigpipe = "inherit"] //~ the `#[unix_sigpipe]` attribute is an experimental feature +fn main () {} diff --git a/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr b/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr new file mode 100644 index 000000000..cf3284467 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unix_sigpipe.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[unix_sigpipe]` attribute is an experimental feature + --> $DIR/feature-gate-unix_sigpipe.rs:3:1 + | +LL | #[unix_sigpipe = "inherit"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #97889 for more information + = help: add `#![feature(unix_sigpipe)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs new file mode 100644 index 000000000..0680d2344 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs @@ -0,0 +1,17 @@ +// edition:2018 +#![forbid(incomplete_features, unsafe_code)] +#![feature(unsafe_pin_internals)] +//~^ ERROR the feature `unsafe_pin_internals` is incomplete and may not be safe to use + +use core::{marker::PhantomPinned, pin::Pin}; + +/// The `unsafe_pin_internals` is indeed unsound. +fn non_unsafe_pin_new_unchecked(pointer: &mut T) -> Pin<&mut T> { + Pin { pointer } +} + +fn main() { + let mut self_referential = PhantomPinned; + let _: Pin<&mut PhantomPinned> = non_unsafe_pin_new_unchecked(&mut self_referential); + core::mem::forget(self_referential); // move and disable drop glue! +} diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr new file mode 100644 index 000000000..4d0c931b4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr @@ -0,0 +1,14 @@ +error: the feature `unsafe_pin_internals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/feature-gate-unsafe_pin_internals.rs:3:12 + | +LL | #![feature(unsafe_pin_internals)] + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/feature-gate-unsafe_pin_internals.rs:2:11 + | +LL | #![forbid(incomplete_features, unsafe_code)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs b/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs new file mode 100644 index 000000000..c04e57843 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs @@ -0,0 +1,30 @@ +#![allow(unused, bare_trait_objects)] +#[repr(align(256))] +struct A { + v: u8, +} + +trait Foo { + fn foo(&self); +} + +impl Foo for A { + fn foo(&self) { + assert_eq!(self as *const A as usize % 256, 0); + } +} + +fn foo(x: dyn Foo) { //~ ERROR [E0277] + x.foo() +} + +fn bar(x: Foo) { //~ ERROR [E0277] + x.foo() +} + +fn qux(_: [()]) {} //~ ERROR [E0277] + +fn main() { + let x: Box = Box::new(A { v: 22 }); + foo(*x); //~ ERROR [E0277] +} diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr new file mode 100644 index 000000000..92c713926 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr @@ -0,0 +1,60 @@ +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:17:8 + | +LL | fn foo(x: dyn Foo) { + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn foo(x: impl Foo) { + | ~~~~ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(x: &dyn Foo) { + | + + +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:21:8 + | +LL | fn bar(x: Foo) { + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn bar(x: impl Foo) { + | ++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn bar(x: &Foo) { + | + + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:25:8 + | +LL | fn qux(_: [()]) {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn qux(_: &[()]) {} + | + + +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:29:9 + | +LL | foo(*x); + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-unsized_locals.rs b/tests/ui/feature-gates/feature-gate-unsized_locals.rs new file mode 100644 index 000000000..3686e7b37 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_locals.rs @@ -0,0 +1,5 @@ +fn f(f: dyn FnOnce()) {} +//~^ ERROR E0277 + +fn main() { +} diff --git a/tests/ui/feature-gates/feature-gate-unsized_locals.stderr b/tests/ui/feature-gates/feature-gate-unsized_locals.stderr new file mode 100644 index 000000000..9aeeb88cf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_locals.stderr @@ -0,0 +1,20 @@ +error[E0277]: the size for values of type `(dyn FnOnce() + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-unsized_locals.rs:1:6 + | +LL | fn f(f: dyn FnOnce()) {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn FnOnce() + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn f(f: impl FnOnce()) {} + | ~~~~ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn f(f: &dyn FnOnce()) {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs new file mode 100644 index 000000000..c3d62a231 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs @@ -0,0 +1,4 @@ +fn main() { + let _ : &(dyn Send,) = &((),); + //~^ ERROR unsized tuple coercion is not stable enough +} diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr new file mode 100644 index 000000000..bea6cee0a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.stderr @@ -0,0 +1,12 @@ +error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change + --> $DIR/feature-gate-unsized_tuple_coercion.rs:2:28 + | +LL | let _ : &(dyn Send,) = &((),); + | ^^^^^^ + | + = note: see issue #42877 for more information + = help: add `#![feature(unsized_tuple_coercion)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-used_with_arg.rs b/tests/ui/feature-gates/feature-gate-used_with_arg.rs new file mode 100644 index 000000000..1c8f01bde --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-used_with_arg.rs @@ -0,0 +1,7 @@ +#[used(linker)] //~ ERROR `#[used(linker)]` is currently unstable +static mut USED_LINKER: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `#[used(compiler)]` is currently unstable +static mut USED_COMPILER: [usize; 1] = [0]; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-used_with_arg.stderr b/tests/ui/feature-gates/feature-gate-used_with_arg.stderr new file mode 100644 index 000000000..d115bf4e3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-used_with_arg.stderr @@ -0,0 +1,21 @@ +error[E0658]: `#[used(linker)]` is currently unstable + --> $DIR/feature-gate-used_with_arg.rs:1:1 + | +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #93798 for more information + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + +error[E0658]: `#[used(compiler)]` is currently unstable + --> $DIR/feature-gate-used_with_arg.rs:4:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #93798 for more information + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-vectorcall.rs b/tests/ui/feature-gates/feature-gate-vectorcall.rs new file mode 100644 index 000000000..5a6c6d288 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-vectorcall.rs @@ -0,0 +1,31 @@ +// gate-test-abi_vectorcall +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Test that the "vectorcall-unwind" ABI is feature-gated, and cannot be used when +// the `c_unwind` feature gate is not used. + +extern "vectorcall" fn f() {} //~ ERROR vectorcall is experimental + +trait T { + extern "vectorcall" fn m(); //~ ERROR vectorcall is experimental + + extern "vectorcall" fn dm() {} //~ ERROR vectorcall is experimental +} + +struct S; +impl T for S { + extern "vectorcall" fn m() {} //~ ERROR vectorcall is experimental +} + +impl S { + extern "vectorcall" fn im() {} //~ ERROR vectorcall is experimental +} + +type TA = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental + +extern "vectorcall" {} //~ ERROR vectorcall is experimental diff --git a/tests/ui/feature-gates/feature-gate-vectorcall.stderr b/tests/ui/feature-gates/feature-gate-vectorcall.stderr new file mode 100644 index 000000000..55ee76ec3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-vectorcall.stderr @@ -0,0 +1,59 @@ +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:12:8 + | +LL | extern "vectorcall" fn f() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:15:12 + | +LL | extern "vectorcall" fn m(); + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:17:12 + | +LL | extern "vectorcall" fn dm() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:22:12 + | +LL | extern "vectorcall" fn m() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:26:12 + | +LL | extern "vectorcall" fn im() {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:29:18 + | +LL | type TA = extern "vectorcall" fn(); + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-vectorcall.rs:31:8 + | +LL | extern "vectorcall" {} + | ^^^^^^^^^^^^ + | + = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-wasm_abi.rs b/tests/ui/feature-gates/feature-gate-wasm_abi.rs new file mode 100644 index 000000000..222c88daf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-wasm_abi.rs @@ -0,0 +1,26 @@ +// needs-llvm-components: webassembly +// compile-flags: --target=wasm32-unknown-unknown --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +extern "wasm" fn fu() {} //~ ERROR wasm ABI is experimental + +trait T { + extern "wasm" fn mu(); //~ ERROR wasm ABI is experimental + extern "wasm" fn dmu() {} //~ ERROR wasm ABI is experimental +} + +struct S; +impl T for S { + extern "wasm" fn mu() {} //~ ERROR wasm ABI is experimental +} + +impl S { + extern "wasm" fn imu() {} //~ ERROR wasm ABI is experimental +} + +type TAU = extern "wasm" fn(); //~ ERROR wasm ABI is experimental + +extern "wasm" {} //~ ERROR wasm ABI is experimental diff --git a/tests/ui/feature-gates/feature-gate-wasm_abi.stderr b/tests/ui/feature-gates/feature-gate-wasm_abi.stderr new file mode 100644 index 000000000..0140002e3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-wasm_abi.stderr @@ -0,0 +1,66 @@ +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:8:8 + | +LL | extern "wasm" fn fu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:11:12 + | +LL | extern "wasm" fn mu(); + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:12:12 + | +LL | extern "wasm" fn dmu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:17:12 + | +LL | extern "wasm" fn mu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:21:12 + | +LL | extern "wasm" fn imu() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:24:19 + | +LL | type TAU = extern "wasm" fn(); + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:26:8 + | +LL | extern "wasm" {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.rs b/tests/ui/feature-gates/feature-gate-with_negative_coherence.rs new file mode 100644 index 000000000..d1d0a6a90 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.rs @@ -0,0 +1,8 @@ +trait Foo { } + +impl Foo for T { } + +impl Foo for &T { } +//~^ ERROR conflicting implementations of trait `Foo` for type `&_` [E0119] + +fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr new file mode 100644 index 000000000..d4c201b5d --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `&_` + --> $DIR/feature-gate-with_negative_coherence.rs:5:1 + | +LL | impl Foo for T { } + | ------------------------------------- first implementation here +LL | +LL | impl Foo for &T { } + | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs new file mode 100644 index 000000000..a33bd3450 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs @@ -0,0 +1,19 @@ +// compile-flags: --edition 2021 + +pub fn demo() -> Option { + #[cfg(nope)] + { + do yeet //~ ERROR `do yeet` expression is experimental + } + + Some(1) +} + +#[cfg(nope)] +pub fn alternative() -> Result<(), String> { + do yeet "hello"; //~ ERROR `do yeet` expression is experimental +} + +fn main() { + demo(); +} diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr new file mode 100644 index 000000000..f90c379bd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.stderr @@ -0,0 +1,21 @@ +error[E0658]: `do yeet` expression is experimental + --> $DIR/feature-gate-yeet_expr-in-cfg.rs:6:9 + | +LL | do yeet + | ^^^^^^^ + | + = note: see issue #96373 for more information + = help: add `#![feature(yeet_expr)]` to the crate attributes to enable + +error[E0658]: `do yeet` expression is experimental + --> $DIR/feature-gate-yeet_expr-in-cfg.rs:14:5 + | +LL | do yeet "hello"; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #96373 for more information + = help: add `#![feature(yeet_expr)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr.rs b/tests/ui/feature-gates/feature-gate-yeet_expr.rs new file mode 100644 index 000000000..978a84cf6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-yeet_expr.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition 2018 + +pub fn demo() -> Option { + do yeet //~ ERROR `do yeet` expression is experimental +} + +pub fn main() -> Result<(), String> { + do yeet "hello"; //~ ERROR `do yeet` expression is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr.stderr b/tests/ui/feature-gates/feature-gate-yeet_expr.stderr new file mode 100644 index 000000000..8d1b92370 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-yeet_expr.stderr @@ -0,0 +1,21 @@ +error[E0658]: `do yeet` expression is experimental + --> $DIR/feature-gate-yeet_expr.rs:4:5 + | +LL | do yeet + | ^^^^^^^ + | + = note: see issue #96373 for more information + = help: add `#![feature(yeet_expr)]` to the crate attributes to enable + +error[E0658]: `do yeet` expression is experimental + --> $DIR/feature-gate-yeet_expr.rs:8:5 + | +LL | do yeet "hello"; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #96373 for more information + = help: add `#![feature(yeet_expr)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs new file mode 100644 index 000000000..1285cca6b --- /dev/null +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs @@ -0,0 +1,14 @@ +// tests that input to a macro is checked for use of gated features. If this +// test succeeds due to the acceptance of a feature, pick a new feature to +// test. Not ideal, but oh well :( + +fn main() { + let a = &[1, 2, 3]; + println!("{}", { + extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change + fn atomic_fence(); + } + atomic_fence(); + 42 + }); +} diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr new file mode 100644 index 000000000..218e02927 --- /dev/null +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -0,0 +1,11 @@ +error[E0658]: intrinsics are subject to change + --> $DIR/feature-gated-feature-in-macro-arg.rs:8:16 + | +LL | extern "rust-intrinsic" { + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(intrinsics)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/gated-bad-feature.rs b/tests/ui/feature-gates/gated-bad-feature.rs new file mode 100644 index 000000000..51f2db555 --- /dev/null +++ b/tests/ui/feature-gates/gated-bad-feature.rs @@ -0,0 +1,10 @@ +#![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] +//~^ ERROR malformed `feature` +//~| ERROR malformed `feature` +//~| ERROR unknown feature `foo` +//~| ERROR unknown feature `foo_bar_baz` +#![feature] //~ ERROR malformed `feature` attribute +#![feature = "foo"] //~ ERROR malformed `feature` attribute +#![feature(test_removed_feature)] //~ ERROR: feature has been removed + +fn main() {} diff --git a/tests/ui/feature-gates/gated-bad-feature.stderr b/tests/ui/feature-gates/gated-bad-feature.stderr new file mode 100644 index 000000000..2d01bdf3c --- /dev/null +++ b/tests/ui/feature-gates/gated-bad-feature.stderr @@ -0,0 +1,46 @@ +error[E0556]: malformed `feature` attribute input + --> $DIR/gated-bad-feature.rs:1:25 + | +LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] + | ^^^^^^^^ help: expected just one word: `foo` + +error[E0556]: malformed `feature` attribute input + --> $DIR/gated-bad-feature.rs:1:35 + | +LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] + | ^^^^^^^^^^^ help: expected just one word: `foo` + +error[E0557]: feature has been removed + --> $DIR/gated-bad-feature.rs:8:12 + | +LL | #![feature(test_removed_feature)] + | ^^^^^^^^^^^^^^^^^^^^ feature has been removed + +error: malformed `feature` attribute input + --> $DIR/gated-bad-feature.rs:6:1 + | +LL | #![feature] + | ^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]` + +error: malformed `feature` attribute input + --> $DIR/gated-bad-feature.rs:7:1 + | +LL | #![feature = "foo"] + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]` + +error[E0635]: unknown feature `foo_bar_baz` + --> $DIR/gated-bad-feature.rs:1:12 + | +LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] + | ^^^^^^^^^^^ + +error[E0635]: unknown feature `foo` + --> $DIR/gated-bad-feature.rs:1:48 + | +LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)] + | ^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0556, E0557, E0635. +For more information about an error, try `rustc --explain E0556`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.rs b/tests/ui/feature-gates/issue-43106-gating-of-bench.rs new file mode 100644 index 000000000..796325b79 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.rs @@ -0,0 +1,10 @@ +// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. +// See issue-12997-1.rs and issue-12997-2.rs to see how `#[bench]` is +// handled in "weird places" when `--test` is passed. + +#![feature(custom_inner_attributes)] + +#![bench = "4100"] +//~^ ERROR cannot determine resolution for the attribute macro `bench` +//~^^ ERROR `bench` attribute cannot be used at crate level +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr new file mode 100644 index 000000000..6b3322119 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr @@ -0,0 +1,21 @@ +error: cannot determine resolution for the attribute macro `bench` + --> $DIR/issue-43106-gating-of-bench.rs:7:4 + | +LL | #![bench = "4100"] + | ^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: `bench` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-bench.rs:7:1 + | +LL | #![bench = "4100"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[bench = "4100"] + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs new file mode 100644 index 000000000..1fe133ac2 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -0,0 +1,160 @@ +//~ NOTE: not an `extern crate` item +//~^ NOTE: not a free function, impl method or static +//~^^ NOTE: not a function or closure +// This is testing whether various builtin attributes signals an +// error or warning when put in "weird" places. +// +// (This file sits on its own because it actually signals an error, +// which would mess up the treatment of other cases in +// issue-43106-gating-of-builtin-attrs.rs) + + +#![macro_export] +//~^ ERROR: `macro_export` attribute cannot be used at crate level +#![rustc_main] //~ ERROR: the `#[rustc_main]` attribute is used internally to specify +//~^ ERROR: `rustc_main` attribute cannot be used at crate level +#![start] +//~^ ERROR: `start` attribute cannot be used at crate level +#![repr()] +//~^ ERROR: `repr` attribute cannot be used at crate level +#![path = "3800"] +//~^ ERROR: `path` attribute cannot be used at crate level +#![automatically_derived] +//~^ ERROR: `automatically_derived` attribute cannot be used at crate level +#![no_mangle] +#![no_link] +//~^ ERROR: attribute should be applied to an `extern crate` item +#![export_name = "2200"] +//~^ ERROR: attribute should be applied to a free function, impl method or static +#![inline] +//~^ ERROR: attribute should be applied to function or closure +#[inline] +//~^ ERROR attribute should be applied to function or closure +mod inline { + //~^ NOTE not a function or closure + + mod inner { #![inline] } + //~^ ERROR attribute should be applied to function or closure + //~| NOTE not a function or closure + + #[inline = "2100"] fn f() { } + //~^ ERROR attribute must be of the form + //~| WARN this was previously accepted + //~| NOTE #[deny(ill_formed_attribute_input)]` on by default + //~| NOTE for more information, see issue #57571 + + #[inline] struct S; + //~^ ERROR attribute should be applied to function or closure + //~| NOTE not a function or closure + + #[inline] type T = S; + //~^ ERROR attribute should be applied to function or closure + //~| NOTE not a function or closure + + #[inline] impl S { } + //~^ ERROR attribute should be applied to function or closure + //~| NOTE not a function or closure +} + +#[no_link] +//~^ ERROR attribute should be applied to an `extern crate` item +mod no_link { + //~^ NOTE not an `extern crate` item + + mod inner { #![no_link] } + //~^ ERROR attribute should be applied to an `extern crate` item + //~| NOTE not an `extern crate` item + + #[no_link] fn f() { } + //~^ ERROR attribute should be applied to an `extern crate` item + //~| NOTE not an `extern crate` item + + #[no_link] struct S; + //~^ ERROR attribute should be applied to an `extern crate` item + //~| NOTE not an `extern crate` item + + #[no_link]type T = S; + //~^ ERROR attribute should be applied to an `extern crate` item + //~| NOTE not an `extern crate` item + + #[no_link] impl S { } + //~^ ERROR attribute should be applied to an `extern crate` item + //~| NOTE not an `extern crate` item +} + +#[export_name = "2200"] +//~^ ERROR attribute should be applied to a free function, impl method or static +mod export_name { + //~^ NOTE not a free function, impl method or static + + mod inner { #![export_name="2200"] } + //~^ ERROR attribute should be applied to a free function, impl method or static + //~| NOTE not a free function, impl method or static + + #[export_name = "2200"] fn f() { } + + #[export_name = "2200"] struct S; + //~^ ERROR attribute should be applied to a free function, impl method or static + //~| NOTE not a free function, impl method or static + + #[export_name = "2200"] type T = S; + //~^ ERROR attribute should be applied to a free function, impl method or static + //~| NOTE not a free function, impl method or static + + #[export_name = "2200"] impl S { } + //~^ ERROR attribute should be applied to a free function, impl method or static + //~| NOTE not a free function, impl method or static + + trait Tr { + #[export_name = "2200"] fn foo(); + //~^ ERROR attribute should be applied to a free function, impl method or static + //~| NOTE not a free function, impl method or static + + #[export_name = "2200"] fn bar() {} + //~^ ERROR attribute should be applied to a free function, impl method or static + //~| NOTE not a free function, impl method or static + } +} + +#[start] +//~^ ERROR: `start` attribute can only be used on functions +mod start { + mod inner { #![start] } + //~^ ERROR: `start` attribute can only be used on functions + + // for `fn f()` case, see feature-gate-start.rs + + #[start] struct S; + //~^ ERROR: `start` attribute can only be used on functions + + #[start] type T = S; + //~^ ERROR: `start` attribute can only be used on functions + + #[start] impl S { } + //~^ ERROR: `start` attribute can only be used on functions +} + +#[repr(C)] +//~^ ERROR: attribute should be applied to a struct, enum, or union +mod repr { +//~^ NOTE not a struct, enum, or union + mod inner { #![repr(C)] } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + #[repr(C)] fn f() { } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + struct S; + + #[repr(C)] type T = S; + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union + + #[repr(C)] impl S { } + //~^ ERROR: attribute should be applied to a struct, enum, or union + //~| NOTE not a struct, enum, or union +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr new file mode 100644 index 000000000..787670404 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -0,0 +1,310 @@ +error[E0658]: the `#[rustc_main]` attribute is used internally to specify test entry point function + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 + | +LL | #![rustc_main] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5 + | +LL | #[inline = "2100"] fn f() { } + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + = note: `#[deny(ill_formed_attribute_input)]` on by default + +error: `start` attribute can only be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:1 + | +LL | #[start] + | ^^^^^^^^ + +error: `start` attribute can only be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:122:17 + | +LL | mod inner { #![start] } + | ^^^^^^^^^ + +error: `start` attribute can only be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:5 + | +LL | #[start] struct S; + | ^^^^^^^^ + +error: `start` attribute can only be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:130:5 + | +LL | #[start] type T = S; + | ^^^^^^^^ + +error: `start` attribute can only be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:5 + | +LL | #[start] impl S { } + | ^^^^^^^^ + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:31:1 + | +LL | #[inline] + | ^^^^^^^^^ +LL | +LL | / mod inline { +LL | | +LL | | +LL | | mod inner { #![inline] } +... | +LL | | +LL | | } + | |_- not a function or closure + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:59:1 + | +LL | #[no_link] + | ^^^^^^^^^^ +LL | +LL | / mod no_link { +LL | | +LL | | +LL | | mod inner { #![no_link] } +... | +LL | | +LL | | } + | |_- not an `extern crate` item + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:1 + | +LL | #[export_name = "2200"] + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / mod export_name { +LL | | +LL | | +LL | | mod inner { #![export_name="2200"] } +... | +LL | | } +LL | | } + | |_- not a free function, impl method or static + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | / mod repr { +LL | | +LL | | mod inner { #![repr(C)] } +LL | | +... | +LL | | +LL | | } + | |_- not a struct, enum, or union + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 + | +LL | #![no_link] + | ^^^^^^^^^^^ not an `extern crate` item + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1 + | +LL | #![export_name = "2200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1 + | +LL | #![inline] + | ^^^^^^^^^^ not a function or closure + +error: `macro_export` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 + | +LL | #![macro_export] + | ^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[macro_export] + | + +error: `rustc_main` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 + | +LL | #![rustc_main] + | ^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[rustc_main] + | ~~~~~~~~~~~~~ + +error: `start` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1 + | +LL | #![start] + | ^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[start] + | + +error: `repr` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:18:1 + | +LL | #![repr()] + | ^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[repr()] + | + +error: `path` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:20:1 + | +LL | #![path = "3800"] + | ^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[path = "3800"] + | + +error: `automatically_derived` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:22:1 + | +LL | #![automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[automatically_derived] + | + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:17 + | +LL | mod inner { #![inline] } + | ------------^^^^^^^^^^-- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 + | +LL | #[inline] struct S; + | ^^^^^^^^^ --------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5 + | +LL | #[inline] type T = S; + | ^^^^^^^^^ ----------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:5 + | +LL | #[inline] impl S { } + | ^^^^^^^^^ ---------- not a function or closure + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:64:17 + | +LL | mod inner { #![no_link] } + | ------------^^^^^^^^^^^-- not an `extern crate` item + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:68:5 + | +LL | #[no_link] fn f() { } + | ^^^^^^^^^^ ---------- not an `extern crate` item + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:72:5 + | +LL | #[no_link] struct S; + | ^^^^^^^^^^ --------- not an `extern crate` item + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:76:5 + | +LL | #[no_link]type T = S; + | ^^^^^^^^^^----------- not an `extern crate` item + +error: attribute should be applied to an `extern crate` item + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:5 + | +LL | #[no_link] impl S { } + | ^^^^^^^^^^ ---------- not an `extern crate` item + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:17 + | +LL | mod inner { #![export_name="2200"] } + | ------------^^^^^^^^^^^^^^^^^^^^^^-- not a free function, impl method or static + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5 + | +LL | #[export_name = "2200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:5 + | +LL | #[export_name = "2200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:104:5 + | +LL | #[export_name = "2200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a free function, impl method or static + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:9 + | +LL | #[export_name = "2200"] fn foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static + +error: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:9 + | +LL | #[export_name = "2200"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:25 + | +LL | mod inner { #![repr(C)] } + | --------------------^---- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12 + | +LL | #[repr(C)] fn f() { } + | ^ ---------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12 + | +LL | #[repr(C)] type T = S; + | ^ ----------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12 + | +LL | #[repr(C)] impl S { } + | ^ ---------- not a struct, enum, or union + +error: aborting due to 39 previous errors + +Some errors have detailed explanations: E0517, E0518, E0658. +For more information about an error, try `rustc --explain E0517`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs new file mode 100644 index 000000000..1fa315f3d --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -0,0 +1,772 @@ +//~ NOTE not a function +//~| NOTE not a foreign function or static +//~| NOTE cannot be applied to crates +//~| NOTE not an `extern` block +// This test enumerates as many compiler-builtin ungated attributes as +// possible (that is, all the mutually compatible ones), and checks +// that we get "expected" (*) warnings for each in the various weird +// places that users might put them in the syntax. +// +// (*): The word "expected" is in quotes above because the cases where +// warnings are and are not emitted might not match a user's intuition +// nor the rustc developers' intent. I am really just trying to +// capture today's behavior in a test, not so that it become enshrined +// as the absolute behavior going forward, but rather so that we do +// not change the behavior in the future without even being *aware* of +// the change when it happens. +// +// At the time of authoring, the attributes here are listed in the +// order that they occur in `librustc_feature`. +// +// Any builtin attributes that: +// +// - are not stable, or +// +// - could not be included here covering the same cases as the other +// attributes without raising an *error* from rustc (note though +// that warnings are of course expected) +// +// have their own test case referenced by filename in an inline +// comment. +// +// The test feeds numeric inputs to each attribute that accepts them +// without error. We do this for two reasons: (1.) to exercise how +// inputs are handled by each, and (2.) to ease searching for related +// occurrences in the source text. + +// check-pass + +#![feature(test)] +#![warn(unused_attributes, unknown_lints)] +//~^ NOTE the lint level is defined here +//~| NOTE the lint level is defined here + +// UNGATED WHITE-LISTED BUILT-IN ATTRIBUTES + +#![warn(x5400)] //~ WARN unknown lint: `x5400` +#![allow(x5300)] //~ WARN unknown lint: `x5300` +#![forbid(x5200)] //~ WARN unknown lint: `x5200` +#![deny(x5100)] //~ WARN unknown lint: `x5100` +#![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs) +// skipping testing of cfg +// skipping testing of cfg_attr +#![should_panic] //~ WARN `#[should_panic]` only has an effect +#![ignore] //~ WARN `#[ignore]` only has an effect on functions +#![no_implicit_prelude] +#![reexport_test_harness_main = "2900"] +// see gated-link-args.rs +// see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700" +// (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600") +#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect +#![doc = "2400"] +#![cold] //~ WARN attribute should be applied to a function +//~^ WARN this was previously accepted +#![link()] //~ WARN attribute should be applied to an `extern` block +//~^ WARN this was previously accepted +#![link_name = "1900"] +//~^ WARN attribute should be applied to a foreign function +//~^^ WARN this was previously accepted by the compiler +#![link_section = "1800"] +//~^ WARN attribute should be applied to a function or static +//~^^ WARN this was previously accepted by the compiler +#![must_use] +//~^ WARN `#[must_use]` has no effect +// see issue-43106-gating-of-stable.rs +// see issue-43106-gating-of-unstable.rs +// see issue-43106-gating-of-deprecated.rs +#![windows_subsystem = "windows"] + +// UNGATED CRATE-LEVEL BUILT-IN ATTRIBUTES + +#![crate_name = "0900"] +#![crate_type = "bin"] // cannot pass "0800" here + +#![crate_id = "10"] +//~^ WARN use of deprecated attribute +//~| HELP remove this attribute +//~| NOTE `#[warn(deprecated)]` on by default + +// FIXME(#44232) we should warn that this isn't used. +#![feature(rust1)] +//~^ WARN no longer requires an attribute to enable +//~| NOTE `#[warn(stable_features)]` on by default + +#![no_start] +//~^ WARN use of deprecated attribute +//~| HELP remove this attribute + +// (cannot easily gating state of crate-level #[no_main]; but non crate-level is below at "0400") +#![no_builtins] +#![recursion_limit = "0200"] +#![type_length_limit = "0100"] + +// USES OF BUILT-IN ATTRIBUTES IN OTHER ("UNUSUAL") PLACES + +#[warn(x5400)] +//~^ WARN unknown lint: `x5400` +mod warn { + mod inner { #![warn(x5400)] } + //~^ WARN unknown lint: `x5400` + + #[warn(x5400)] fn f() { } + //~^ WARN unknown lint: `x5400` + + #[warn(x5400)] struct S; + //~^ WARN unknown lint: `x5400` + + #[warn(x5400)] type T = S; + //~^ WARN unknown lint: `x5400` + + #[warn(x5400)] impl S { } + //~^ WARN unknown lint: `x5400` +} + +#[allow(x5300)] +//~^ WARN unknown lint: `x5300` +mod allow { + mod inner { #![allow(x5300)] } + //~^ WARN unknown lint: `x5300` + + #[allow(x5300)] fn f() { } + //~^ WARN unknown lint: `x5300` + + #[allow(x5300)] struct S; + //~^ WARN unknown lint: `x5300` + + #[allow(x5300)] type T = S; + //~^ WARN unknown lint: `x5300` + + #[allow(x5300)] impl S { } + //~^ WARN unknown lint: `x5300` +} + +#[forbid(x5200)] +//~^ WARN unknown lint: `x5200` +mod forbid { + mod inner { #![forbid(x5200)] } + //~^ WARN unknown lint: `x5200` + + #[forbid(x5200)] fn f() { } + //~^ WARN unknown lint: `x5200` + + #[forbid(x5200)] struct S; + //~^ WARN unknown lint: `x5200` + + #[forbid(x5200)] type T = S; + //~^ WARN unknown lint: `x5200` + + #[forbid(x5200)] impl S { } + //~^ WARN unknown lint: `x5200` +} + +#[deny(x5100)] +//~^ WARN unknown lint: `x5100` +mod deny { + mod inner { #![deny(x5100)] } + //~^ WARN unknown lint: `x5100` + + #[deny(x5100)] fn f() { } + //~^ WARN unknown lint: `x5100` + + #[deny(x5100)] struct S; + //~^ WARN unknown lint: `x5100` + + #[deny(x5100)] type T = S; + //~^ WARN unknown lint: `x5100` + + #[deny(x5100)] impl S { } + //~^ WARN unknown lint: `x5100` +} + +#[macro_use] +mod macro_use { + mod inner { #![macro_use] } + + #[macro_use] fn f() { } + //~^ `#[macro_use]` only has an effect + + #[macro_use] struct S; + //~^ `#[macro_use]` only has an effect + + #[macro_use] type T = S; + //~^ `#[macro_use]` only has an effect + + #[macro_use] impl S { } + //~^ `#[macro_use]` only has an effect +} + +#[macro_export] +//~^ WARN `#[macro_export]` only has an effect on macro definitions +mod macro_export { + mod inner { #![macro_export] } + //~^ WARN `#[macro_export]` only has an effect on macro definitions + + #[macro_export] fn f() { } + //~^ WARN `#[macro_export]` only has an effect on macro definitions + + #[macro_export] struct S; + //~^ WARN `#[macro_export]` only has an effect on macro definitions + + #[macro_export] type T = S; + //~^ WARN `#[macro_export]` only has an effect on macro definitions + + #[macro_export] impl S { } + //~^ WARN `#[macro_export]` only has an effect on macro definitions +} + +// At time of unit test authorship, if compiling without `--test` then +// non-crate-level #[test] attributes seem to be ignored. + +#[test] +mod test { mod inner { #![test] } + + fn f() { } + + struct S; + + type T = S; + + impl S { } +} + +// At time of unit test authorship, if compiling without `--test` then +// non-crate-level #[bench] attributes seem to be ignored. + +#[bench] +mod bench { + mod inner { #![bench] } + + #[bench] + struct S; + + #[bench] + type T = S; + + #[bench] + impl S { } +} + +#[path = "3800"] +mod path { + mod inner { #![path="3800"] } + + #[path = "3800"] fn f() { } + //~^ WARN `#[path]` only has an effect + + #[path = "3800"] struct S; + //~^ WARN `#[path]` only has an effect + + #[path = "3800"] type T = S; + //~^ WARN `#[path]` only has an effect + + #[path = "3800"] impl S { } + //~^ WARN `#[path]` only has an effect +} + +#[automatically_derived] +//~^ WARN `#[automatically_derived]` only has an effect +mod automatically_derived { + mod inner { #![automatically_derived] } + //~^ WARN `#[automatically_derived] + + #[automatically_derived] fn f() { } + //~^ WARN `#[automatically_derived] + + #[automatically_derived] struct S; + //~^ WARN `#[automatically_derived] + + #[automatically_derived] type T = S; + //~^ WARN `#[automatically_derived] + + #[automatically_derived] impl S { } +} + +#[no_mangle] +//~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +mod no_mangle { + //~^ NOTE not a free function, impl method or static + mod inner { #![no_mangle] } + //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a free function, impl method or static + + #[no_mangle] fn f() { } + + #[no_mangle] struct S; + //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a free function, impl method or static + + #[no_mangle] type T = S; + //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a free function, impl method or static + + #[no_mangle] impl S { } + //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a free function, impl method or static + + trait Tr { + #[no_mangle] fn foo(); + //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a free function, impl method or static + + #[no_mangle] fn bar() {} + //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a free function, impl method or static + } +} + +#[should_panic] +//~^ WARN `#[should_panic]` only has an effect on +mod should_panic { + mod inner { #![should_panic] } + //~^ WARN `#[should_panic]` only has an effect on + + #[should_panic] fn f() { } + + #[should_panic] struct S; + //~^ WARN `#[should_panic]` only has an effect on + + #[should_panic] type T = S; + //~^ WARN `#[should_panic]` only has an effect on + + #[should_panic] impl S { } + //~^ WARN `#[should_panic]` only has an effect on +} + +#[ignore] +//~^ WARN `#[ignore]` only has an effect on functions +mod ignore { + mod inner { #![ignore] } + //~^ WARN `#[ignore]` only has an effect on functions + + #[ignore] fn f() { } + + #[ignore] struct S; + //~^ WARN `#[ignore]` only has an effect on functions + + #[ignore] type T = S; + //~^ WARN `#[ignore]` only has an effect on functions + + #[ignore] impl S { } + //~^ WARN `#[ignore]` only has an effect on functions +} + +#[no_implicit_prelude] +mod no_implicit_prelude { + mod inner { #![no_implicit_prelude] } + + #[no_implicit_prelude] fn f() { } + //~^ WARN `#[no_implicit_prelude]` only has an effect + + #[no_implicit_prelude] struct S; + //~^ WARN `#[no_implicit_prelude]` only has an effect + + #[no_implicit_prelude] type T = S; + //~^ WARN `#[no_implicit_prelude]` only has an effect + + #[no_implicit_prelude] impl S { } + //~^ WARN `#[no_implicit_prelude]` only has an effect +} + +#[reexport_test_harness_main = "2900"] +//~^ WARN crate-level attribute should be +mod reexport_test_harness_main { + mod inner { #![reexport_test_harness_main="2900"] } + //~^ WARN crate-level attribute should be + + #[reexport_test_harness_main = "2900"] fn f() { } + //~^ WARN crate-level attribute should be + + #[reexport_test_harness_main = "2900"] struct S; + //~^ WARN crate-level attribute should be + + #[reexport_test_harness_main = "2900"] type T = S; + //~^ WARN crate-level attribute should be + + #[reexport_test_harness_main = "2900"] impl S { } + //~^ WARN crate-level attribute should be +} + +// Cannot feed "2700" to `#[macro_escape]` without signaling an error. +#[macro_escape] +//~^ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]` +mod macro_escape { + mod inner { #![macro_escape] } + //~^ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + //~| HELP try an outer attribute: `#[macro_use]` + + #[macro_escape] fn f() { } + //~^ WARN `#[macro_escape]` only has an effect + + #[macro_escape] struct S; + //~^ WARN `#[macro_escape]` only has an effect + + #[macro_escape] type T = S; + //~^ WARN `#[macro_escape]` only has an effect + + #[macro_escape] impl S { } + //~^ WARN `#[macro_escape]` only has an effect +} + +#[no_std] +//~^ WARN crate-level attribute should be an inner attribute +mod no_std { + mod inner { #![no_std] } +//~^ WARN crate-level attribute should be in the root module + + #[no_std] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[no_std] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[no_std] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[no_std] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +// At time of authorship, #[proc_macro_derive = "2500"] signals error +// when it occurs on a mod (apart from crate-level). Therefore it goes +// into its own file; see issue-43106-gating-of-proc_macro_derive.rs + +#[doc = "2400"] +mod doc { + mod inner { #![doc="2400"] } + + #[doc = "2400"] fn f() { } + + #[doc = "2400"] struct S; + + #[doc = "2400"] type T = S; + + #[doc = "2400"] impl S { } +} + +#[cold] +//~^ WARN attribute should be applied to a function +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +mod cold { + //~^ NOTE not a function + + mod inner { #![cold] } + //~^ WARN attribute should be applied to a function + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function + + #[cold] fn f() { } + + #[cold] struct S; + //~^ WARN attribute should be applied to a function + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function + + #[cold] type T = S; + //~^ WARN attribute should be applied to a function + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function + + #[cold] impl S { } + //~^ WARN attribute should be applied to a function + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function +} + +#[link_name = "1900"] +//~^ WARN attribute should be applied to a foreign function or static [unused_attributes] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +mod link_name { + //~^ NOTE not a foreign function or static + + #[link_name = "1900"] + //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| HELP try `#[link(name = "1900")]` instead + extern "C" { } + //~^ NOTE not a foreign function or static + + mod inner { #![link_name="1900"] } + //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a foreign function or static + + #[link_name = "1900"] fn f() { } + //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a foreign function or static + + #[link_name = "1900"] struct S; + //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a foreign function or static + + #[link_name = "1900"] type T = S; + //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a foreign function or static + + #[link_name = "1900"] impl S { } + //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a foreign function or static +} + +#[link_section = "1800"] +//~^ WARN attribute should be applied to a function or static [unused_attributes] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +mod link_section { + //~^ NOTE not a function or static + + mod inner { #![link_section="1800"] } + //~^ WARN attribute should be applied to a function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function or static + + #[link_section = "1800"] fn f() { } + + #[link_section = "1800"] struct S; + //~^ WARN attribute should be applied to a function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function or static + + #[link_section = "1800"] type T = S; + //~^ WARN attribute should be applied to a function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function or static + + #[link_section = "1800"] impl S { } + //~^ WARN attribute should be applied to a function or static [unused_attributes] + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| NOTE not a function or static +} + + +// Note that this is a `check-pass` test, so it will never invoke the linker. + +#[link()] +//~^ WARN attribute should be applied to an `extern` block +//~| WARN this was previously accepted +mod link { + //~^ NOTE not an `extern` block + + mod inner { #![link()] } + //~^ WARN attribute should be applied to an `extern` block + //~| WARN this was previously accepted + //~| NOTE not an `extern` block + + #[link()] fn f() { } + //~^ WARN attribute should be applied to an `extern` block + //~| WARN this was previously accepted + //~| NOTE not an `extern` block + + #[link()] struct S; + //~^ WARN attribute should be applied to an `extern` block + //~| WARN this was previously accepted + //~| NOTE not an `extern` block + + #[link()] type T = S; + //~^ WARN attribute should be applied to an `extern` block + //~| WARN this was previously accepted + //~| NOTE not an `extern` block + + #[link()] impl S { } + //~^ WARN attribute should be applied to an `extern` block + //~| WARN this was previously accepted + //~| NOTE not an `extern` block + + #[link()] extern "Rust" {} + //~^ WARN attribute should be applied to an `extern` block + //~| WARN this was previously accepted +} + +struct StructForDeprecated; + +#[deprecated] +mod deprecated { + mod inner { #![deprecated] } + + #[deprecated] fn f() { } + + #[deprecated] struct S1; + + #[deprecated] type T = super::StructForDeprecated; + + #[deprecated] impl super::StructForDeprecated { } +} + +#[must_use] //~ WARN `#[must_use]` has no effect +mod must_use { + mod inner { #![must_use] } //~ WARN `#[must_use]` has no effect + + #[must_use] fn f() { } + + #[must_use] struct S; + + #[must_use] type T = S; //~ WARN `#[must_use]` has no effect + + #[must_use] impl S { } //~ WARN `#[must_use]` has no effect +} + +#[windows_subsystem = "windows"] +//~^ WARN crate-level attribute should be an inner attribute +mod windows_subsystem { + mod inner { #![windows_subsystem="windows"] } + //~^ WARN crate-level attribute should be in the root module + + #[windows_subsystem = "windows"] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[windows_subsystem = "windows"] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[windows_subsystem = "windows"] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[windows_subsystem = "windows"] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES + +#[crate_name = "0900"] +//~^ WARN crate-level attribute should be an inner attribute +mod crate_name { + mod inner { #![crate_name="0900"] } +//~^ WARN crate-level attribute should be in the root module + + #[crate_name = "0900"] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[crate_name = "0900"] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[crate_name = "0900"] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[crate_name = "0900"] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +#[crate_type = "0800"] +//~^ WARN crate-level attribute should be an inner attribute +mod crate_type { + mod inner { #![crate_type="0800"] } +//~^ WARN crate-level attribute should be in the root module + + #[crate_type = "0800"] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[crate_type = "0800"] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[crate_type = "0800"] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[crate_type = "0800"] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +#[feature(x0600)] +//~^ WARN crate-level attribute should be an inner attribute +mod feature { + mod inner { #![feature(x0600)] } +//~^ WARN crate-level attribute should be in the root module + + #[feature(x0600)] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[feature(x0600)] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[feature(x0600)] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[feature(x0600)] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + + +#[no_main] +//~^ WARN crate-level attribute should be an inner attribute +mod no_main_1 { + mod inner { #![no_main] } +//~^ WARN crate-level attribute should be in the root module + + #[no_main] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[no_main] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[no_main] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[no_main] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +#[no_builtins] +//~^ WARN crate-level attribute should be an inner attribute +mod no_builtins { + mod inner { #![no_builtins] } + //~^ WARN crate-level attribute should be in the root module + + #[no_builtins] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[no_builtins] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[no_builtins] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[no_builtins] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +#[recursion_limit="0200"] +//~^ WARN crate-level attribute should be an inner attribute +mod recursion_limit { + mod inner { #![recursion_limit="0200"] } +//~^ WARN crate-level attribute should be in the root module + + #[recursion_limit="0200"] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[recursion_limit="0200"] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[recursion_limit="0200"] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[recursion_limit="0200"] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +#[type_length_limit="0100"] +//~^ WARN crate-level attribute should be an inner attribute +mod type_length_limit { + mod inner { #![type_length_limit="0100"] } +//~^ WARN crate-level attribute should be in the root module + + #[type_length_limit="0100"] fn f() { } + //~^ WARN crate-level attribute should be an inner attribute + + #[type_length_limit="0100"] struct S; + //~^ WARN crate-level attribute should be an inner attribute + + #[type_length_limit="0100"] type T = S; + //~^ WARN crate-level attribute should be an inner attribute + + #[type_length_limit="0100"] impl S { } + //~^ WARN crate-level attribute should be an inner attribute +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr new file mode 100644 index 000000000..300392679 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -0,0 +1,1181 @@ +warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:17 + | +LL | mod inner { #![macro_escape] } + | ^^^^^^^^^^^^^^^^ + | + = help: try an outer attribute: `#[macro_use]` + +warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:1 + | +LL | #[macro_escape] + | ^^^^^^^^^^^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:9 + | +LL | #![warn(x5400)] + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:28 + | +LL | #![warn(unused_attributes, unknown_lints)] + | ^^^^^^^^^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:10 + | +LL | #![allow(x5300)] + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:48:11 + | +LL | #![forbid(x5200)] + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:9 + | +LL | #![deny(x5100)] + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8 + | +LL | #[warn(x5400)] + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:108:25 + | +LL | mod inner { #![warn(x5400)] } + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:12 + | +LL | #[warn(x5400)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:12 + | +LL | #[warn(x5400)] struct S; + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:12 + | +LL | #[warn(x5400)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5400` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12 + | +LL | #[warn(x5400)] impl S { } + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:9 + | +LL | #[allow(x5300)] + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:26 + | +LL | mod inner { #![allow(x5300)] } + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:13 + | +LL | #[allow(x5300)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:13 + | +LL | #[allow(x5300)] struct S; + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:13 + | +LL | #[allow(x5300)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5300` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13 + | +LL | #[allow(x5300)] impl S { } + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:10 + | +LL | #[forbid(x5200)] + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:27 + | +LL | mod inner { #![forbid(x5200)] } + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:14 + | +LL | #[forbid(x5200)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:14 + | +LL | #[forbid(x5200)] struct S; + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:14 + | +LL | #[forbid(x5200)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5200` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14 + | +LL | #[forbid(x5200)] impl S { } + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:8 + | +LL | #[deny(x5100)] + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:25 + | +LL | mod inner { #![deny(x5100)] } + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:12 + | +LL | #[deny(x5100)] fn f() { } + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:12 + | +LL | #[deny(x5100)] struct S; + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:12 + | +LL | #[deny(x5100)] type T = S; + | ^^^^^ + +warning: unknown lint: `x5100` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12 + | +LL | #[deny(x5100)] impl S { } + | ^^^^^ + +warning: use of deprecated attribute `crate_id`: no longer used. + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1 + | +LL | #![crate_id = "10"] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated attribute `no_start`: no longer used. + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1 + | +LL | #![no_start] + | ^^^^^^^^^^^^ help: remove this attribute + +warning: `#[macro_export]` only has an effect on macro definitions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:9 + | +LL | #![warn(unused_attributes, unknown_lints)] + | ^^^^^^^^^^^^^^^^^ + +warning: `#[automatically_derived]` only has an effect on implementation blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ +... +LL | / mod no_mangle { +LL | | +LL | | mod inner { #![no_mangle] } +LL | | +... | +LL | | } +LL | | } + | |_- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: `#[should_panic]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:1 + | +LL | #[should_panic] + | ^^^^^^^^^^^^^^^ + +warning: `#[ignore]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:1 + | +LL | #[ignore] + | ^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:1 + | +LL | #[reexport_test_harness_main = "2900"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1 + | +LL | #[no_std] + | ^^^^^^^^^ + +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:453:1 + | +LL | #[cold] + | ^^^^^^^ +... +LL | / mod cold { +LL | | +LL | | +LL | | mod inner { #![cold] } +... | +LL | | +LL | | } + | |_- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:482:1 + | +LL | #[link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | / mod link_name { +LL | | +LL | | +LL | | #[link_name = "1900"] +... | +LL | | +LL | | } + | |_- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:1 + | +LL | #[link_section = "1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / mod link_section { +LL | | +LL | | +LL | | mod inner { #![link_section="1800"] } +... | +LL | | +LL | | } + | |_- not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:553:1 + | +LL | #[link()] + | ^^^^^^^^^ +... +LL | / mod link { +LL | | +LL | | +LL | | mod inner { #![link()] } +... | +LL | | +LL | | } + | |_- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: `#[must_use]` has no effect when applied to a module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:604:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:1 + | +LL | #[windows_subsystem = "windows"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:1 + | +LL | #[crate_name = "0900"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:1 + | +LL | #[crate_type = "0800"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:1 + | +LL | #[feature(x0600)] + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:1 + | +LL | #[no_main] + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:1 + | +LL | #[no_builtins] + | ^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:1 + | +LL | #[recursion_limit="0200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:1 + | +LL | #[type_length_limit="0100"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[should_panic]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 + | +LL | #![should_panic] + | ^^^^^^^^^^^^^^^^ + +warning: `#[ignore]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1 + | +LL | #![ignore] + | ^^^^^^^^^^ + +warning: `#[proc_macro_derive]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 + | +LL | #![proc_macro_derive()] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 + | +LL | #![cold] + | ^^^^^^^^ cannot be applied to crates + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 + | +LL | #![link()] + | ^^^^^^^^^^ not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 + | +LL | #![link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 + | +LL | #![link_section = "1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: `#[must_use]` has no effect when applied to a module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 + | +LL | #![must_use] + | ^^^^^^^^^^^^ + +warning: `#[macro_use]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:5 + | +LL | #[macro_use] fn f() { } + | ^^^^^^^^^^^^ + +warning: `#[macro_use]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:188:5 + | +LL | #[macro_use] struct S; + | ^^^^^^^^^^^^ + +warning: `#[macro_use]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5 + | +LL | #[macro_use] type T = S; + | ^^^^^^^^^^^^ + +warning: `#[macro_use]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:5 + | +LL | #[macro_use] impl S { } + | ^^^^^^^^^^^^ + +warning: `#[macro_export]` only has an effect on macro definitions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:17 + | +LL | mod inner { #![macro_export] } + | ^^^^^^^^^^^^^^^^ + +warning: `#[macro_export]` only has an effect on macro definitions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5 + | +LL | #[macro_export] fn f() { } + | ^^^^^^^^^^^^^^^ + +warning: `#[macro_export]` only has an effect on macro definitions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:5 + | +LL | #[macro_export] struct S; + | ^^^^^^^^^^^^^^^ + +warning: `#[macro_export]` only has an effect on macro definitions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5 + | +LL | #[macro_export] type T = S; + | ^^^^^^^^^^^^^^^ + +warning: `#[macro_export]` only has an effect on macro definitions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5 + | +LL | #[macro_export] impl S { } + | ^^^^^^^^^^^^^^^ + +warning: `#[path]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5 + | +LL | #[path = "3800"] fn f() { } + | ^^^^^^^^^^^^^^^^ + +warning: `#[path]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5 + | +LL | #[path = "3800"] struct S; + | ^^^^^^^^^^^^^^^^ + +warning: `#[path]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5 + | +LL | #[path = "3800"] type T = S; + | ^^^^^^^^^^^^^^^^ + +warning: `#[path]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:5 + | +LL | #[path = "3800"] impl S { } + | ^^^^^^^^^^^^^^^^ + +warning: `#[automatically_derived]` only has an effect on implementation blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:17 + | +LL | mod inner { #![automatically_derived] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[automatically_derived]` only has an effect on implementation blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:272:5 + | +LL | #[automatically_derived] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[automatically_derived]` only has an effect on implementation blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:5 + | +LL | #[automatically_derived] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[automatically_derived]` only has an effect on implementation blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:5 + | +LL | #[automatically_derived] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:17 + | +LL | mod inner { #![no_mangle] } + | ------------^^^^^^^^^^^^^-- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:296:5 + | +LL | #[no_mangle] struct S; + | ^^^^^^^^^^^^ --------- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:5 + | +LL | #[no_mangle] type T = S; + | ^^^^^^^^^^^^ ----------- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:306:5 + | +LL | #[no_mangle] impl S { } + | ^^^^^^^^^^^^ ---------- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:312:9 + | +LL | #[no_mangle] fn foo(); + | ^^^^^^^^^^^^ --------- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a free function, impl method or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:317:9 + | +LL | #[no_mangle] fn bar() {} + | ^^^^^^^^^^^^ ----------- not a free function, impl method or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: `#[should_panic]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:327:17 + | +LL | mod inner { #![should_panic] } + | ^^^^^^^^^^^^^^^^ + +warning: `#[should_panic]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5 + | +LL | #[should_panic] struct S; + | ^^^^^^^^^^^^^^^ + +warning: `#[should_panic]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5 + | +LL | #[should_panic] type T = S; + | ^^^^^^^^^^^^^^^ + +warning: `#[should_panic]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5 + | +LL | #[should_panic] impl S { } + | ^^^^^^^^^^^^^^^ + +warning: `#[ignore]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:17 + | +LL | mod inner { #![ignore] } + | ^^^^^^^^^^ + +warning: `#[ignore]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5 + | +LL | #[ignore] struct S; + | ^^^^^^^^^ + +warning: `#[ignore]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:5 + | +LL | #[ignore] type T = S; + | ^^^^^^^^^ + +warning: `#[ignore]` only has an effect on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:356:5 + | +LL | #[ignore] impl S { } + | ^^^^^^^^^ + +warning: `#[no_implicit_prelude]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5 + | +LL | #[no_implicit_prelude] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[no_implicit_prelude]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5 + | +LL | #[no_implicit_prelude] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[no_implicit_prelude]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 + | +LL | #[no_implicit_prelude] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[no_implicit_prelude]` only has an effect on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5 + | +LL | #[no_implicit_prelude] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:17 + | +LL | mod inner { #![reexport_test_harness_main="2900"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5 + | +LL | #[reexport_test_harness_main = "2900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5 + | +LL | #[reexport_test_harness_main = "2900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5 + | +LL | #[reexport_test_harness_main = "2900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5 + | +LL | #[reexport_test_harness_main = "2900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `#[macro_escape]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5 + | +LL | #[macro_escape] fn f() { } + | ^^^^^^^^^^^^^^^ + +warning: `#[macro_escape]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:5 + | +LL | #[macro_escape] struct S; + | ^^^^^^^^^^^^^^^ + +warning: `#[macro_escape]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5 + | +LL | #[macro_escape] type T = S; + | ^^^^^^^^^^^^^^^ + +warning: `#[macro_escape]` only has an effect on `extern crate` and modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:413:5 + | +LL | #[macro_escape] impl S { } + | ^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17 + | +LL | mod inner { #![no_std] } + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 + | +LL | #[no_std] fn f() { } + | ^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5 + | +LL | #[no_std] struct S; + | ^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5 + | +LL | #[no_std] type T = S; + | ^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5 + | +LL | #[no_std] impl S { } + | ^^^^^^^^^ + +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:459:17 + | +LL | mod inner { #![cold] } + | ------------^^^^^^^^-- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 + | +LL | #[cold] struct S; + | ^^^^^^^ --------- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:5 + | +LL | #[cold] type T = S; + | ^^^^^^^ ----------- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function definition + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5 + | +LL | #[cold] impl S { } + | ^^^^^^^ ---------- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 + | +LL | #[link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | extern "C" { } + | -------------- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +help: try `#[link(name = "1900")]` instead + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 + | +LL | #[link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:17 + | +LL | mod inner { #![link_name="1900"] } + | ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5 + | +LL | #[link_name = "1900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5 + | +LL | #[link_name = "1900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5 + | +LL | #[link_name = "1900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5 + | +LL | #[link_name = "1900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:17 + | +LL | mod inner { #![link_section="1800"] } + | ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:534:5 + | +LL | #[link_section = "1800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:5 + | +LL | #[link_section = "1800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5 + | +LL | #[link_section = "1800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:17 + | +LL | mod inner { #![link()] } + | ------------^^^^^^^^^^-- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:564:5 + | +LL | #[link()] fn f() { } + | ^^^^^^^^^ ---------- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:569:5 + | +LL | #[link()] struct S; + | ^^^^^^^^^ --------- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:574:5 + | +LL | #[link()] type T = S; + | ^^^^^^^^^ ----------- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:579:5 + | +LL | #[link()] impl S { } + | ^^^^^^^^^ ---------- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:584:5 + | +LL | #[link()] extern "Rust" {} + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: `#[must_use]` has no effect when applied to a module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:606:17 + | +LL | mod inner { #![must_use] } + | ^^^^^^^^^^^^ + +warning: `#[must_use]` has no effect when applied to a type alias + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:612:5 + | +LL | #[must_use] type T = S; + | ^^^^^^^^^^^ + +warning: `#[must_use]` has no effect when applied to an implementation block + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:5 + | +LL | #[must_use] impl S { } + | ^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:17 + | +LL | mod inner { #![windows_subsystem="windows"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5 + | +LL | #[windows_subsystem = "windows"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5 + | +LL | #[windows_subsystem = "windows"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:5 + | +LL | #[windows_subsystem = "windows"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:632:5 + | +LL | #[windows_subsystem = "windows"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:17 + | +LL | mod inner { #![crate_name="0900"] } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5 + | +LL | #[crate_name = "0900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5 + | +LL | #[crate_name = "0900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5 + | +LL | #[crate_name = "0900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:653:5 + | +LL | #[crate_name = "0900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17 + | +LL | mod inner { #![crate_type="0800"] } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5 + | +LL | #[crate_type = "0800"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5 + | +LL | #[crate_type = "0800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5 + | +LL | #[crate_type = "0800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5 + | +LL | #[crate_type = "0800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:17 + | +LL | mod inner { #![feature(x0600)] } + | ^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5 + | +LL | #[feature(x0600)] fn f() { } + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5 + | +LL | #[feature(x0600)] struct S; + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + | +LL | #[feature(x0600)] type T = S; + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5 + | +LL | #[feature(x0600)] impl S { } + | ^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:17 + | +LL | mod inner { #![no_main] } + | ^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5 + | +LL | #[no_main] fn f() { } + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 + | +LL | #[no_main] struct S; + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 + | +LL | #[no_main] type T = S; + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5 + | +LL | #[no_main] impl S { } + | ^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:17 + | +LL | mod inner { #![no_builtins] } + | ^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + | +LL | #[no_builtins] fn f() { } + | ^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 + | +LL | #[no_builtins] struct S; + | ^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 + | +LL | #[no_builtins] type T = S; + | ^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 + | +LL | #[no_builtins] impl S { } + | ^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:17 + | +LL | mod inner { #![recursion_limit="0200"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 + | +LL | #[recursion_limit="0200"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5 + | +LL | #[recursion_limit="0200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 + | +LL | #[recursion_limit="0200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5 + | +LL | #[recursion_limit="0200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be in the root module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:17 + | +LL | mod inner { #![type_length_limit="0100"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 + | +LL | #[type_length_limit="0100"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5 + | +LL | #[type_length_limit="0100"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 + | +LL | #[type_length_limit="0100"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5 + | +LL | #[type_length_limit="0100"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:12 + | +LL | #![feature(rust1)] + | ^^^^^ + | + = note: `#[warn(stable_features)]` on by default + +warning: 173 warnings emitted + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-deprecated.rs b/tests/ui/feature-gates/issue-43106-gating-of-deprecated.rs new file mode 100644 index 000000000..5e1d08dd9 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-deprecated.rs @@ -0,0 +1,12 @@ +// This test just shows that a crate-level `#![deprecated]` does not +// signal a warning or error. (This file sits on its own because a +// crate-level `#![deprecated]` causes all that crate's item +// definitions to be deprecated, which is a pain to work with.) +// +// (For non-crate-level cases, see issue-43106-gating-of-builtin-attrs.rs) + +// check-pass + +#![deprecated] + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive-2.rs b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.rs new file mode 100644 index 000000000..3276309f7 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.rs @@ -0,0 +1,20 @@ +// This test checks cases where the derive-macro does not exist. + +mod derive { + #[derive(x3300)] + //~^ ERROR cannot find derive macro `x3300` in this scope + //~| ERROR cannot find derive macro `x3300` in this scope + union U { f: i32 } + + #[derive(x3300)] + //~^ ERROR cannot find derive macro `x3300` in this scope + //~| ERROR cannot find derive macro `x3300` in this scope + enum E { } + + #[derive(x3300)] + //~^ ERROR cannot find derive macro `x3300` in this scope + //~| ERROR cannot find derive macro `x3300` in this scope + struct S; +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr new file mode 100644 index 000000000..ab1659173 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-derive-2.stderr @@ -0,0 +1,38 @@ +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:14:14 + | +LL | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:14:14 + | +LL | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:9:14 + | +LL | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:9:14 + | +LL | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 + | +LL | #[derive(x3300)] + | ^^^^^ + +error: cannot find derive macro `x3300` in this scope + --> $DIR/issue-43106-gating-of-derive-2.rs:4:14 + | +LL | #[derive(x3300)] + | ^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive.rs b/tests/ui/feature-gates/issue-43106-gating-of-derive.rs new file mode 100644 index 000000000..86a352251 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-derive.rs @@ -0,0 +1,33 @@ +// `#![derive]` raises errors when it occurs at contexts other than ADT +// definitions. + +#[derive(Debug)] +//~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s +mod derive { + mod inner { #![derive(Debug)] } + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + //~| ERROR inner macro attributes are unstable + + #[derive(Debug)] + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + fn derive() { } + + #[derive(Copy, Clone)] // (can't derive Debug for unions) + union U { f: i32 } + + #[derive(Debug)] + struct S; + + #[derive(Debug)] + enum E { } + + #[derive(Debug)] + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + type T = S; + + #[derive(Debug)] + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + impl S { } +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr new file mode 100644 index 000000000..bb8651ffb --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-derive.stderr @@ -0,0 +1,64 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43106-gating-of-derive.rs:4:1 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | / mod derive { +LL | | mod inner { #![derive(Debug)] } +LL | | +LL | | +... | +LL | | impl S { } +LL | | } + | |_- not a `struct`, `enum` or `union` + +error[E0658]: inner macro attributes are unstable + --> $DIR/issue-43106-gating-of-derive.rs:7:20 + | +LL | mod inner { #![derive(Debug)] } + | ^^^^^^ + | + = note: see issue #54726 for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43106-gating-of-derive.rs:7:17 + | +LL | mod inner { #![derive(Debug)] } + | ------------^^^^^^^^^^^^^^^^^-- + | | | + | | not applicable here + | not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43106-gating-of-derive.rs:11:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | fn derive() { } + | --------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43106-gating-of-derive.rs:24:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | type T = S; + | ----------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-43106-gating-of-derive.rs:28:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | +LL | impl S { } + | ---------- not a `struct`, `enum` or `union` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0658, E0774. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_escape.rs b/tests/ui/feature-gates/issue-43106-gating-of-macro_escape.rs new file mode 100644 index 000000000..de00bc4cb --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_escape.rs @@ -0,0 +1,11 @@ +// Testing that crate-level `#![macro_escape]` is not gated beyond a +// depecation warning. This file sits on its own, because crate-level +// `#![macro_escape]` is incompatible with crate-level `#![macro_use]` +// already present in issue-43106-gating-of-builtin-attrs. + +// check-pass + +#![macro_escape] +//~^ WARN `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_escape.stderr b/tests/ui/feature-gates/issue-43106-gating-of-macro_escape.stderr new file mode 100644 index 000000000..0eaec5202 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_escape.stderr @@ -0,0 +1,10 @@ +warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` + --> $DIR/issue-43106-gating-of-macro_escape.rs:8:1 + | +LL | #![macro_escape] + | ^^^^^^^^^^^^^^^^ + | + = help: try an outer attribute: `#[macro_use]` + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs new file mode 100644 index 000000000..6a7ef7939 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs @@ -0,0 +1,25 @@ +// This is just a check-list of the cases where feeding arguments to +// `#[macro_use]` is rejected. (The cases where no error is emitted +// corresponds to cases where the attribute is currently unused, so we +// get that warning; see issue-43106-gating-of-builtin-attrs.rs + +#![macro_use(my_macro)] +//~^ ERROR arguments to `macro_use` are not allowed here + +#[macro_use(my_macro)] +//~^ ERROR arguments to `macro_use` are not allowed here +mod macro_escape { + mod inner { #![macro_use(my_macro)] } + //~^ ERROR arguments to `macro_use` are not allowed here + + #[macro_use = "2700"] struct S; + //~^ ERROR malformed `macro_use` attribute + + #[macro_use] fn f() { } + + #[macro_use] type T = S; + + #[macro_use] impl S { } +} + +fn main() { } diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr new file mode 100644 index 000000000..9a12851f2 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr @@ -0,0 +1,33 @@ +error: arguments to `macro_use` are not allowed here + --> $DIR/issue-43106-gating-of-macro_use.rs:12:17 + | +LL | mod inner { #![macro_use(my_macro)] } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: arguments to `macro_use` are not allowed here + --> $DIR/issue-43106-gating-of-macro_use.rs:9:1 + | +LL | #[macro_use(my_macro)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: arguments to `macro_use` are not allowed here + --> $DIR/issue-43106-gating-of-macro_use.rs:6:1 + | +LL | #![macro_use(my_macro)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: malformed `macro_use` attribute input + --> $DIR/issue-43106-gating-of-macro_use.rs:15:5 + | +LL | #[macro_use = "2700"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL | #[macro_use(name1, name2, ...)] struct S; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[macro_use] struct S; + | ~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs new file mode 100644 index 000000000..a94ffd602 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs @@ -0,0 +1,34 @@ +// At time of authorship, #[proc_macro_derive = "2500"] will emit an +// error when it occurs on a mod (apart from crate-level), but will +// not descend further into the mod for other occurrences of the same +// error. +// +// This file sits on its own because the "weird" occurrences here +// signal errors, making it incompatible with the "warnings only" +// nature of issue-43106-gating-of-builtin-attrs.rs + +#[proc_macro_derive()] +//~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions +mod proc_macro_derive1 { + mod inner { #![proc_macro_derive()] } + // (no error issued here if there was one on outer module) +} + +mod proc_macro_derive2 { + mod inner { #![proc_macro_derive()] } + //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + + #[proc_macro_derive()] fn f() { } + //~^ ERROR the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` + + #[proc_macro_derive()] struct S; + //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + + #[proc_macro_derive()] type T = S; + //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + + #[proc_macro_derive()] impl S { } + //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr new file mode 100644 index 000000000..e202b472d --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr @@ -0,0 +1,38 @@ +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:10:1 + | +LL | #[proc_macro_derive()] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:18:17 + | +LL | mod inner { #![proc_macro_derive()] } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:21:5 + | +LL | #[proc_macro_derive()] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:24:5 + | +LL | #[proc_macro_derive()] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:27:5 + | +LL | #[proc_macro_derive()] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:30:5 + | +LL | #[proc_macro_derive()] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-stable.rs b/tests/ui/feature-gates/issue-43106-gating-of-stable.rs new file mode 100644 index 000000000..621ec01bb --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-stable.rs @@ -0,0 +1,35 @@ +// Testing gating of `#[stable]` in "weird" places. +// +// This file sits on its own because these signal errors, making +// this test incompatible with the "warnings only" nature of +// issue-43106-gating-of-builtin-attrs.rs + +#![stable()] +//~^ ERROR stability attributes may not be used outside of the standard library + +#[stable()] +//~^ ERROR stability attributes may not be used outside of the standard library +mod stable { + mod inner { + #![stable()] + //~^ ERROR stability attributes may not be used outside of the standard library + } + + #[stable()] + //~^ ERROR stability attributes may not be used outside of the standard library + fn f() {} + + #[stable()] + //~^ ERROR stability attributes may not be used outside of the standard library + struct S; + + #[stable()] + //~^ ERROR stability attributes may not be used outside of the standard library + type T = S; + + #[stable()] + //~^ ERROR stability attributes may not be used outside of the standard library + impl S {} +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr b/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr new file mode 100644 index 000000000..677fef3a9 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-stable.stderr @@ -0,0 +1,45 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:14:9 + | +LL | #![stable()] + | ^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:18:5 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:22:5 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:26:5 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:30:5 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:10:1 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-stable.rs:7:1 + | +LL | #![stable()] + | ^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.rs b/tests/ui/feature-gates/issue-43106-gating-of-test.rs new file mode 100644 index 000000000..39835c926 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.rs @@ -0,0 +1,7 @@ +// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. + +#![allow(soft_unstable)] +#![test = "4200"] +//~^ ERROR cannot determine resolution for the attribute macro `test` +//~^^ ERROR `test` attribute cannot be used at crate level +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr new file mode 100644 index 000000000..300a9966d --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr @@ -0,0 +1,21 @@ +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-43106-gating-of-test.rs:4:4 + | +LL | #![test = "4200"] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: `test` attribute cannot be used at crate level + --> $DIR/issue-43106-gating-of-test.rs:4:1 + | +LL | #![test = "4200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[test = "4200"] + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-unstable.rs b/tests/ui/feature-gates/issue-43106-gating-of-unstable.rs new file mode 100644 index 000000000..d507bcd8f --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-unstable.rs @@ -0,0 +1,35 @@ +// Testing gating of `#[unstable]` in "weird" places. +// +// This file sits on its own because these signal errors, making +// this test incompatible with the "warnings only" nature of +// issue-43106-gating-of-builtin-attrs.rs + +#![unstable()] +//~^ ERROR stability attributes may not be used outside of the standard library + +#[unstable()] +//~^ ERROR stability attributes may not be used outside of the standard library +mod unstable { + mod inner { + #![unstable()] + //~^ ERROR stability attributes may not be used outside of the standard library + } + + #[unstable()] + //~^ ERROR stability attributes may not be used outside of the standard library + fn f() {} + + #[unstable()] + //~^ ERROR stability attributes may not be used outside of the standard library + struct S; + + #[unstable()] + //~^ ERROR stability attributes may not be used outside of the standard library + type T = S; + + #[unstable()] + //~^ ERROR stability attributes may not be used outside of the standard library + impl S {} +} + +fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr b/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr new file mode 100644 index 000000000..a2f361878 --- /dev/null +++ b/tests/ui/feature-gates/issue-43106-gating-of-unstable.stderr @@ -0,0 +1,45 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:14:9 + | +LL | #![unstable()] + | ^^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:18:5 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:22:5 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:26:5 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:30:5 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:10:1 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-43106-gating-of-unstable.rs:7:1 + | +LL | #![unstable()] + | ^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/feature-gates/issue-49983-see-issue-0.rs b/tests/ui/feature-gates/issue-49983-see-issue-0.rs new file mode 100644 index 000000000..eeb80d014 --- /dev/null +++ b/tests/ui/feature-gates/issue-49983-see-issue-0.rs @@ -0,0 +1,6 @@ +extern crate core; + +// error should not say "(see issue #0)" +#[allow(unused_imports)] use core::ptr::Unique; //~ ERROR use of unstable library feature + +fn main() {} diff --git a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr new file mode 100644 index 000000000..314238a34 --- /dev/null +++ b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'ptr_internals': use `NonNull` instead and consider `PhantomData` (if you also use `#[may_dangle]`), `Send`, and/or `Sync` + --> $DIR/issue-49983-see-issue-0.rs:4:30 + | +LL | #[allow(unused_imports)] use core::ptr::Unique; + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(ptr_internals)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/rustc-private.rs b/tests/ui/feature-gates/rustc-private.rs new file mode 100644 index 000000000..7b8944bb0 --- /dev/null +++ b/tests/ui/feature-gates/rustc-private.rs @@ -0,0 +1,5 @@ +// gate-test-rustc_private + +extern crate libc; //~ ERROR use of unstable library feature 'rustc_private' + +fn main() {} diff --git a/tests/ui/feature-gates/rustc-private.stderr b/tests/ui/feature-gates/rustc-private.stderr new file mode 100644 index 000000000..1a8536d37 --- /dev/null +++ b/tests/ui/feature-gates/rustc-private.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/rustc-private.rs:3:1 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27812 for more information + = help: add `#![feature(rustc_private)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs b/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs new file mode 100644 index 000000000..49f1cba71 --- /dev/null +++ b/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs @@ -0,0 +1,30 @@ +// check-fail +// This file is used to test the behavior of the early-pass syntax warnings. +// If macro syntax is stabilized, replace with a different unstable syntax. + +macro a() {} +//~^ ERROR: `macro` is experimental + +#[cfg(FALSE)] +macro b() {} + +macro_rules! identity { + ($($x:tt)*) => ($($x)*); +} + +identity! { + macro c() {} + //~^ ERROR: `macro` is experimental +} + +#[cfg(FALSE)] +identity! { + macro d() {} // No error +} + +identity! { + #[cfg(FALSE)] + macro e() {} +} + +fn main() {} diff --git a/tests/ui/feature-gates/soft-syntax-gates-with-errors.stderr b/tests/ui/feature-gates/soft-syntax-gates-with-errors.stderr new file mode 100644 index 000000000..49550d811 --- /dev/null +++ b/tests/ui/feature-gates/soft-syntax-gates-with-errors.stderr @@ -0,0 +1,21 @@ +error[E0658]: `macro` is experimental + --> $DIR/soft-syntax-gates-with-errors.rs:5:1 + | +LL | macro a() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + +error[E0658]: `macro` is experimental + --> $DIR/soft-syntax-gates-with-errors.rs:16:5 + | +LL | macro c() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs b/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs new file mode 100644 index 000000000..ca4ad2320 --- /dev/null +++ b/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs @@ -0,0 +1,26 @@ +// check-pass +// This file is used to test the behavior of the early-pass syntax warnings. +// If macro syntax is stabilized, replace with a different unstable syntax. + +#[cfg(FALSE)] +macro b() {} +//~^ WARN: `macro` is experimental +//~| WARN: unstable syntax + +macro_rules! identity { + ($($x:tt)*) => ($($x)*); +} + +#[cfg(FALSE)] +identity! { + macro d() {} // No error +} + +identity! { + #[cfg(FALSE)] + macro e() {} + //~^ WARN: `macro` is experimental + //~| WARN: unstable syntax +} + +fn main() {} diff --git a/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr b/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr new file mode 100644 index 000000000..3d9c22e54 --- /dev/null +++ b/tests/ui/feature-gates/soft-syntax-gates-without-errors.stderr @@ -0,0 +1,24 @@ +warning: `macro` is experimental + --> $DIR/soft-syntax-gates-without-errors.rs:6:1 + | +LL | macro b() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: `macro` is experimental + --> $DIR/soft-syntax-gates-without-errors.rs:21:5 + | +LL | macro e() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 2 warnings emitted + diff --git a/tests/ui/feature-gates/stability-attribute-consistency.rs b/tests/ui/feature-gates/stability-attribute-consistency.rs new file mode 100644 index 000000000..6ee7003c3 --- /dev/null +++ b/tests/ui/feature-gates/stability-attribute-consistency.rs @@ -0,0 +1,16 @@ +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#![feature(staged_api)] + +#[stable(feature = "foo", since = "1.0.0")] +fn foo_stable_1_0_0() {} + +#[stable(feature = "foo", since = "1.29.0")] +//~^ ERROR feature `foo` is declared stable since 1.29.0 +fn foo_stable_1_29_0() {} + +#[unstable(feature = "foo", issue = "none")] +//~^ ERROR feature `foo` is declared unstable +fn foo_unstable() {} + +fn main() {} diff --git a/tests/ui/feature-gates/stability-attribute-consistency.stderr b/tests/ui/feature-gates/stability-attribute-consistency.stderr new file mode 100644 index 000000000..1b93d3c96 --- /dev/null +++ b/tests/ui/feature-gates/stability-attribute-consistency.stderr @@ -0,0 +1,15 @@ +error[E0711]: feature `foo` is declared stable since 1.29.0, but was previously declared stable since 1.0.0 + --> $DIR/stability-attribute-consistency.rs:8:1 + | +LL | #[stable(feature = "foo", since = "1.29.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0711]: feature `foo` is declared unstable, but was previously declared stable + --> $DIR/stability-attribute-consistency.rs:12:1 + | +LL | #[unstable(feature = "foo", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0711`. diff --git a/tests/ui/feature-gates/stable-features.rs b/tests/ui/feature-gates/stable-features.rs new file mode 100644 index 000000000..ed7f0899d --- /dev/null +++ b/tests/ui/feature-gates/stable-features.rs @@ -0,0 +1,14 @@ +// Testing that the stable_features lint catches use of stable +// language and lib features. + +#![deny(stable_features)] + +#![feature(test_accepted_feature)] +//~^ ERROR the feature `test_accepted_feature` has been stable since 1.0.0 + +#![feature(rust1)] +//~^ ERROR the feature `rust1` has been stable since 1.0.0 + +fn main() { + let _foo: Vec<()> = Vec::new(); +} diff --git a/tests/ui/feature-gates/stable-features.stderr b/tests/ui/feature-gates/stable-features.stderr new file mode 100644 index 000000000..831b40b86 --- /dev/null +++ b/tests/ui/feature-gates/stable-features.stderr @@ -0,0 +1,20 @@ +error: the feature `test_accepted_feature` has been stable since 1.0.0 and no longer requires an attribute to enable + --> $DIR/stable-features.rs:6:12 + | +LL | #![feature(test_accepted_feature)] + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/stable-features.rs:4:9 + | +LL | #![deny(stable_features)] + | ^^^^^^^^^^^^^^^ + +error: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable + --> $DIR/stable-features.rs:9:12 + | +LL | #![feature(rust1)] + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/trace_macros-gate.rs b/tests/ui/feature-gates/trace_macros-gate.rs new file mode 100644 index 000000000..c9af04741 --- /dev/null +++ b/tests/ui/feature-gates/trace_macros-gate.rs @@ -0,0 +1,14 @@ +// Test that the trace_macros feature gate is on. + +fn main() { + trace_macros!(); //~ ERROR `trace_macros` is not stable + //~| ERROR trace_macros! accepts only `true` or `false` + trace_macros!(true); //~ ERROR `trace_macros` is not stable + trace_macros!(false); //~ ERROR `trace_macros` is not stable + + macro_rules! expando { + ($x: ident) => { trace_macros!($x) } //~ ERROR `trace_macros` is not stable + } + + expando!(true); +} diff --git a/tests/ui/feature-gates/trace_macros-gate.stderr b/tests/ui/feature-gates/trace_macros-gate.stderr new file mode 100644 index 000000000..1ca10aeec --- /dev/null +++ b/tests/ui/feature-gates/trace_macros-gate.stderr @@ -0,0 +1,49 @@ +error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change + --> $DIR/trace_macros-gate.rs:4:5 + | +LL | trace_macros!(); + | ^^^^^^^^^^^^ + | + = note: see issue #29598 for more information + = help: add `#![feature(trace_macros)]` to the crate attributes to enable + +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-gate.rs:4:5 + | +LL | trace_macros!(); + | ^^^^^^^^^^^^^^^ + +error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change + --> $DIR/trace_macros-gate.rs:6:5 + | +LL | trace_macros!(true); + | ^^^^^^^^^^^^ + | + = note: see issue #29598 for more information + = help: add `#![feature(trace_macros)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change + --> $DIR/trace_macros-gate.rs:7:5 + | +LL | trace_macros!(false); + | ^^^^^^^^^^^^ + | + = note: see issue #29598 for more information + = help: add `#![feature(trace_macros)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change + --> $DIR/trace_macros-gate.rs:10:26 + | +LL | ($x: ident) => { trace_macros!($x) } + | ^^^^^^^^^^^^ +... +LL | expando!(true); + | -------------- in this macro invocation + | + = note: see issue #29598 for more information + = help: add `#![feature(trace_macros)]` to the crate attributes to enable + = note: this error originates in the macro `expando` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/unknown-feature.rs b/tests/ui/feature-gates/unknown-feature.rs new file mode 100644 index 000000000..20fd932d4 --- /dev/null +++ b/tests/ui/feature-gates/unknown-feature.rs @@ -0,0 +1,3 @@ +#![feature(unknown_rust_feature)] //~ ERROR unknown feature + +fn main() {} diff --git a/tests/ui/feature-gates/unknown-feature.stderr b/tests/ui/feature-gates/unknown-feature.stderr new file mode 100644 index 000000000..e5c05872d --- /dev/null +++ b/tests/ui/feature-gates/unknown-feature.stderr @@ -0,0 +1,9 @@ +error[E0635]: unknown feature `unknown_rust_feature` + --> $DIR/unknown-feature.rs:1:12 + | +LL | #![feature(unknown_rust_feature)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/feature-gates/unstable-attribute-allow-issue-0.rs b/tests/ui/feature-gates/unstable-attribute-allow-issue-0.rs new file mode 100644 index 000000000..bffe43262 --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-allow-issue-0.rs @@ -0,0 +1,13 @@ +// Check that an issue value can be explicitly set to "0" instead of "none" +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[unstable(feature = "unstable_test_feature", issue = "0")] +fn unstable_issue_0() {} //~^ ERROR `issue` must be a non-zero numeric string or "none" + +#[unstable(feature = "unstable_test_feature", issue = "none")] +fn unstable_issue_none() {} + +#[unstable(feature = "unstable_test_feature", issue = "something")] +fn unstable_issue_not_allowed() {} //~^ ERROR `issue` must be a non-zero numeric string or "none" diff --git a/tests/ui/feature-gates/unstable-attribute-allow-issue-0.stderr b/tests/ui/feature-gates/unstable-attribute-allow-issue-0.stderr new file mode 100644 index 000000000..4ed42101a --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-allow-issue-0.stderr @@ -0,0 +1,19 @@ +error[E0545]: `issue` must be a non-zero numeric string or "none" + --> $DIR/unstable-attribute-allow-issue-0.rs:6:47 + | +LL | #[unstable(feature = "unstable_test_feature", issue = "0")] + | ^^^^^^^^--- + | | + | `issue` must not be "0", use "none" instead + +error[E0545]: `issue` must be a non-zero numeric string or "none" + --> $DIR/unstable-attribute-allow-issue-0.rs:12:47 + | +LL | #[unstable(feature = "unstable_test_feature", issue = "something")] + | ^^^^^^^^----------- + | | + | invalid digit found in string + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0545`. diff --git a/tests/ui/ffi_const.rs b/tests/ui/ffi_const.rs new file mode 100644 index 000000000..7aeb5a49a --- /dev/null +++ b/tests/ui/ffi_const.rs @@ -0,0 +1,5 @@ +#![feature(ffi_const)] +#![crate_type = "lib"] + +#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions +pub fn foo() {} diff --git a/tests/ui/ffi_const.stderr b/tests/ui/ffi_const.stderr new file mode 100644 index 000000000..bc3c12eaf --- /dev/null +++ b/tests/ui/ffi_const.stderr @@ -0,0 +1,9 @@ +error[E0756]: `#[ffi_const]` may only be used on foreign functions + --> $DIR/ffi_const.rs:4:1 + | +LL | #[ffi_const] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0756`. diff --git a/tests/ui/ffi_const2.rs b/tests/ui/ffi_const2.rs new file mode 100644 index 000000000..82fe8a9c9 --- /dev/null +++ b/tests/ui/ffi_const2.rs @@ -0,0 +1,11 @@ +#![feature(ffi_const, ffi_pure)] + +extern "C" { + #[ffi_pure] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]` + #[ffi_const] + pub fn baz(); +} + +fn main() { + unsafe { baz() }; +} diff --git a/tests/ui/ffi_const2.stderr b/tests/ui/ffi_const2.stderr new file mode 100644 index 000000000..0c30c9dc5 --- /dev/null +++ b/tests/ui/ffi_const2.stderr @@ -0,0 +1,9 @@ +error[E0757]: `#[ffi_const]` function cannot be `#[ffi_pure]` + --> $DIR/ffi_const2.rs:4:5 + | +LL | #[ffi_pure] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0757`. diff --git a/tests/ui/ffi_pure.rs b/tests/ui/ffi_pure.rs new file mode 100644 index 000000000..c37d34c87 --- /dev/null +++ b/tests/ui/ffi_pure.rs @@ -0,0 +1,5 @@ +#![feature(ffi_pure)] +#![crate_type = "lib"] + +#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions +pub fn foo() {} diff --git a/tests/ui/ffi_pure.stderr b/tests/ui/ffi_pure.stderr new file mode 100644 index 000000000..bc911c85d --- /dev/null +++ b/tests/ui/ffi_pure.stderr @@ -0,0 +1,9 @@ +error[E0755]: `#[ffi_pure]` may only be used on foreign functions + --> $DIR/ffi_pure.rs:4:1 + | +LL | #[ffi_pure] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0755`. diff --git a/tests/ui/ffi_returns_twice.rs b/tests/ui/ffi_returns_twice.rs new file mode 100644 index 000000000..845e18df1 --- /dev/null +++ b/tests/ui/ffi_returns_twice.rs @@ -0,0 +1,5 @@ +#![feature(ffi_returns_twice)] +#![crate_type = "lib"] + +#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions +pub fn foo() {} diff --git a/tests/ui/ffi_returns_twice.stderr b/tests/ui/ffi_returns_twice.stderr new file mode 100644 index 000000000..2b7f5694f --- /dev/null +++ b/tests/ui/ffi_returns_twice.stderr @@ -0,0 +1,9 @@ +error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions + --> $DIR/ffi_returns_twice.rs:4:1 + | +LL | #[ffi_returns_twice] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0724`. diff --git a/tests/ui/filter-block-view-items.rs b/tests/ui/filter-block-view-items.rs new file mode 100644 index 000000000..e63aa9157 --- /dev/null +++ b/tests/ui/filter-block-view-items.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + // Make sure that this view item is filtered out because otherwise it would + // trigger a compilation error + #[cfg(not_present)] use bar as foo; +} diff --git a/tests/ui/fmt/auxiliary/format-string-proc-macro.rs b/tests/ui/fmt/auxiliary/format-string-proc-macro.rs new file mode 100644 index 000000000..1b7ef93f4 --- /dev/null +++ b/tests/ui/fmt/auxiliary/format-string-proc-macro.rs @@ -0,0 +1,52 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; + +#[proc_macro] +pub fn foo_with_input_span(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + + let mut lit = Literal::string("{foo}"); + lit.set_span(span); + + TokenStream::from(TokenTree::Literal(lit)) +} + +#[proc_macro] +pub fn err_with_input_span(input: TokenStream) -> TokenStream { + let span = input.into_iter().next().unwrap().span(); + + let mut lit = Literal::string(" }"); + lit.set_span(span); + + TokenStream::from(TokenTree::Literal(lit)) +} + + +#[proc_macro] +pub fn respan_to_invalid_format_literal(input: TokenStream) -> TokenStream { + let mut s = Literal::string("{"); + s.set_span(input.into_iter().next().unwrap().span()); + TokenStream::from_iter([ + TokenTree::from(Ident::new("format", Span::call_site())), + TokenTree::from(Punct::new('!', Spacing::Alone)), + TokenTree::from(Group::new(Delimiter::Parenthesis, TokenTree::from(s).into())), + ]) +} + +#[proc_macro] +pub fn capture_a_with_prepended_space_preserve_span(input: TokenStream) -> TokenStream { + let mut s = Literal::string(" {a}"); + s.set_span(input.into_iter().next().unwrap().span()); + TokenStream::from_iter([ + TokenTree::from(Ident::new("format", Span::call_site())), + TokenTree::from(Punct::new('!', Spacing::Alone)), + TokenTree::from(Group::new(Delimiter::Parenthesis, TokenTree::from(s).into())), + ]) +} diff --git a/tests/ui/fmt/format-args-capture-issue-102057.rs b/tests/ui/fmt/format-args-capture-issue-102057.rs new file mode 100644 index 000000000..b8089d49b --- /dev/null +++ b/tests/ui/fmt/format-args-capture-issue-102057.rs @@ -0,0 +1,19 @@ +fn main() { + format!("\x7Ba}"); + //~^ ERROR cannot find value `a` in this scope + format!("\x7Ba\x7D"); + //~^ ERROR cannot find value `a` in this scope + + let a = 0; + + format!("\x7Ba} {b}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba\x7D {b}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba} \x7Bb}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba\x7D \x7Bb}"); + //~^ ERROR cannot find value `b` in this scope + format!("\x7Ba\x7D \x7Bb\x7D"); + //~^ ERROR cannot find value `b` in this scope +} diff --git a/tests/ui/fmt/format-args-capture-issue-102057.stderr b/tests/ui/fmt/format-args-capture-issue-102057.stderr new file mode 100644 index 000000000..f2d625e7f --- /dev/null +++ b/tests/ui/fmt/format-args-capture-issue-102057.stderr @@ -0,0 +1,45 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/format-args-capture-issue-102057.rs:2:18 + | +LL | format!("\x7Ba}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/format-args-capture-issue-102057.rs:4:18 + | +LL | format!("\x7Ba\x7D"); + | ^ not found in this scope + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:9:22 + | +LL | format!("\x7Ba} {b}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:11:25 + | +LL | format!("\x7Ba\x7D {b}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:13:25 + | +LL | format!("\x7Ba} \x7Bb}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:15:28 + | +LL | format!("\x7Ba\x7D \x7Bb}"); + | ^ help: a local variable with a similar name exists: `a` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/format-args-capture-issue-102057.rs:17:28 + | +LL | format!("\x7Ba\x7D \x7Bb\x7D"); + | ^ help: a local variable with a similar name exists: `a` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/fmt/format-args-capture-issue-93378.rs b/tests/ui/fmt/format-args-capture-issue-93378.rs new file mode 100644 index 000000000..9d722a028 --- /dev/null +++ b/tests/ui/fmt/format-args-capture-issue-93378.rs @@ -0,0 +1,11 @@ +fn main() { + let a = "a"; + let b = "b"; + + println!("{a} {b} {} {} {c} {}", c = "c"); + //~^ ERROR: 3 positional arguments in format string, but there is 1 argument + + let n = 1; + println!("{a:.n$} {b:.*}"); + //~^ ERROR: 1 positional argument in format string, but no arguments were given +} diff --git a/tests/ui/fmt/format-args-capture-issue-93378.stderr b/tests/ui/fmt/format-args-capture-issue-93378.stderr new file mode 100644 index 000000000..6429b0d46 --- /dev/null +++ b/tests/ui/fmt/format-args-capture-issue-93378.stderr @@ -0,0 +1,17 @@ +error: 3 positional arguments in format string, but there is 1 argument + --> $DIR/format-args-capture-issue-93378.rs:5:23 + | +LL | println!("{a} {b} {} {} {c} {}", c = "c"); + | ^^ ^^ ^^ --- + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/format-args-capture-issue-93378.rs:9:26 + | +LL | println!("{a:.n$} {b:.*}"); + | ^^ this precision flag adds an extra required argument at position 0, which is why there is 1 argument expected + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: aborting due to 2 previous errors + diff --git a/tests/ui/fmt/format-args-capture-issue-94010.rs b/tests/ui/fmt/format-args-capture-issue-94010.rs new file mode 100644 index 000000000..bd03e9c93 --- /dev/null +++ b/tests/ui/fmt/format-args-capture-issue-94010.rs @@ -0,0 +1,7 @@ +fn main() { + const FOO: i32 = 123; + println!("{foo:X}"); + //~^ ERROR: cannot find value `foo` in this scope + println!("{:.foo$}", 0); + //~^ ERROR: cannot find value `foo` in this scope +} diff --git a/tests/ui/fmt/format-args-capture-issue-94010.stderr b/tests/ui/fmt/format-args-capture-issue-94010.stderr new file mode 100644 index 000000000..ed90dc855 --- /dev/null +++ b/tests/ui/fmt/format-args-capture-issue-94010.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-issue-94010.rs:3:16 + | +LL | const FOO: i32 = 123; + | --------------------- similarly named constant `FOO` defined here +LL | println!("{foo:X}"); + | ^^^ help: a constant with a similar name exists (notice the capitalization): `FOO` + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-issue-94010.rs:5:18 + | +LL | const FOO: i32 = 123; + | --------------------- similarly named constant `FOO` defined here +... +LL | println!("{:.foo$}", 0); + | ^^^ help: a constant with a similar name exists (notice the capitalization): `FOO` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/fmt/format-args-capture-macro-hygiene.rs b/tests/ui/fmt/format-args-capture-macro-hygiene.rs new file mode 100644 index 000000000..b04f80ba4 --- /dev/null +++ b/tests/ui/fmt/format-args-capture-macro-hygiene.rs @@ -0,0 +1,22 @@ +// aux-build:format-string-proc-macro.rs + +#[macro_use] +extern crate format_string_proc_macro; + +macro_rules! def_site { + () => { "{foo}" } //~ ERROR: there is no argument named `foo` +} + +macro_rules! call_site { + ($fmt:literal) => { $fmt } +} + +fn main() { + format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo` + format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar` + + format!(def_site!()); + format!(call_site!("{foo}")); //~ ERROR: there is no argument named `foo` + + format!(foo_with_input_span!("")); //~ ERROR: there is no argument named `foo` +} diff --git a/tests/ui/fmt/format-args-capture-macro-hygiene.stderr b/tests/ui/fmt/format-args-capture-macro-hygiene.stderr new file mode 100644 index 000000000..1b5fbd2af --- /dev/null +++ b/tests/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -0,0 +1,53 @@ +error: there is no argument named `foo` + --> $DIR/format-args-capture-macro-hygiene.rs:15: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 the macro `concat` (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:16: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 the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: there is no argument named `foo` + --> $DIR/format-args-capture-macro-hygiene.rs:7:13 + | +LL | () => { "{foo}" } + | ^^^^^^^ +... +LL | format!(def_site!()); + | ----------- in this macro invocation + | + = 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 the macro `def_site` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: there is no argument named `foo` + --> $DIR/format-args-capture-macro-hygiene.rs:19:24 + | +LL | format!(call_site!("{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 + +error: there is no argument named `foo` + --> $DIR/format-args-capture-macro-hygiene.rs:21:34 + | +LL | format!(foo_with_input_span!("")); + | ^^ + | + = 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 + +error: aborting due to 5 previous errors + diff --git a/tests/ui/fmt/format-args-capture-missing-variables.rs b/tests/ui/fmt/format-args-capture-missing-variables.rs new file mode 100644 index 000000000..46fc083cb --- /dev/null +++ b/tests/ui/fmt/format-args-capture-missing-variables.rs @@ -0,0 +1,20 @@ +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/tests/ui/fmt/format-args-capture-missing-variables.stderr b/tests/ui/fmt/format-args-capture-missing-variables.stderr new file mode 100644 index 000000000..d980e7be2 --- /dev/null +++ b/tests/ui/fmt/format-args-capture-missing-variables.stderr @@ -0,0 +1,47 @@ +error: named argument never used + --> $DIR/format-args-capture-missing-variables.rs:8: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:2:18 + | +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:2:27 + | +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:6:15 + | +LL | format!("{foo}"); + | ^^^ not found in this scope + +error[E0425]: cannot find value `valueb` in this scope + --> $DIR/format-args-capture-missing-variables.rs:8:24 + | +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:10 + | +LL | {foo} + | ^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-missing-variables.rs:19:14 + | +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/tests/ui/fmt/format-args-capture.rs b/tests/ui/fmt/format-args-capture.rs new file mode 100644 index 000000000..560352b5c --- /dev/null +++ b/tests/ui/fmt/format-args-capture.rs @@ -0,0 +1,89 @@ +// run-pass + +fn main() { + named_argument_takes_precedence_to_captured(); + formatting_parameters_can_be_captured(); + capture_raw_strings_and_idents(); + repeated_capture(); + + #[cfg(panic = "unwind")] + { + panic_with_single_argument_does_not_get_formatted(); + panic_with_multiple_arguments_is_formatted(); + } +} + +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 capture_raw_strings_and_idents() { + let r#type = "apple"; + let s = format!(r#"The fruit is an {type}"#); + assert_eq!(&s, "The fruit is an apple"); + + let r#type = "orange"; + let s = format!(r"The fruit is an {type}"); + assert_eq!(&s, "The fruit is an orange"); +} + +#[cfg(panic = "unwind")] +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. + + #[allow(non_fmt_panics)] + let msg = std::panic::catch_unwind(|| { + panic!("{foo}"); + }) + .unwrap_err(); + + assert_eq!(msg.downcast_ref::<&str>(), Some(&"{foo}")) +} + +#[cfg(panic = "unwind")] +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::(), 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: test.rs:2:17 +// | +// 2 | format!(concat!("abc}")); +// | ^ unmatched `}` in format string +// +// This test checks that this behavior has been fixed. + +fn main() { + format!(concat!("abc}")); + //~^ ERROR: invalid format string: unmatched `}` found + + format!(err_with_input_span!("")); + //~^ ERROR: invalid format string: unmatched `}` found +} diff --git a/tests/ui/fmt/format-expanded-string.stderr b/tests/ui/fmt/format-expanded-string.stderr new file mode 100644 index 000000000..26ce7f269 --- /dev/null +++ b/tests/ui/fmt/format-expanded-string.stderr @@ -0,0 +1,19 @@ +error: invalid format string: unmatched `}` found + --> $DIR/format-expanded-string.rs:19:13 + | +LL | format!(concat!("abc}")); + | ^^^^^^^^^^^^^^^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: invalid format string: unmatched `}` found + --> $DIR/format-expanded-string.rs:22:34 + | +LL | format!(err_with_input_span!("")); + | ^^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/fmt/format-raw-string-error.rs b/tests/ui/fmt/format-raw-string-error.rs new file mode 100644 index 000000000..9f0bc01a7 --- /dev/null +++ b/tests/ui/fmt/format-raw-string-error.rs @@ -0,0 +1,3 @@ +fn main() { + println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#); //~ ERROR invalid format string: unmatched `}` found +} diff --git a/tests/ui/fmt/format-raw-string-error.stderr b/tests/ui/fmt/format-raw-string-error.stderr new file mode 100644 index 000000000..8d61950d8 --- /dev/null +++ b/tests/ui/fmt/format-raw-string-error.stderr @@ -0,0 +1,10 @@ +error: invalid format string: unmatched `}` found + --> $DIR/format-raw-string-error.rs:2:45 + | +LL | println!(r#"\'\'\'\'\'\'\'\'\'\'\'\'\'\'}"#); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to previous error + diff --git a/tests/ui/fmt/format-string-error-2.rs b/tests/ui/fmt/format-string-error-2.rs new file mode 100644 index 000000000..1f7f0d8f6 --- /dev/null +++ b/tests/ui/fmt/format-string-error-2.rs @@ -0,0 +1,86 @@ +// ignore-tidy-tab + +fn main() { + format!("{ + a"); + //~^ ERROR invalid format string + format!("{ \ + \ + b"); + //~^ ERROR invalid format string + format!(r#"{ \ + + rawc"#); + //~^^^ ERROR invalid format string + format!(r#"{ \n +\n + rawd"#); + //~^^^ ERROR invalid format string + format!("{ \n +\n + e"); + //~^ ERROR invalid format string + format!(" + { + a"); + //~^ ERROR invalid format string + format!(" + { + a + "); + //~^^ ERROR invalid format string + format!(" \ + { \ + \ + b"); + //~^ ERROR invalid format string + format!(" \ + { \ + \ + b \ + \ + "); + //~^^^ ERROR invalid format string + format!(r#" +raw { \ + \ + c"#); + //~^^^ ERROR invalid format string + format!(r#" +raw { \n +\n + d"#); + //~^^^ ERROR invalid format string + format!(" + { \n +\n + e"); + //~^ ERROR invalid format string + + format!(" + {asdf + } + ", asdf=1); + // ok - this is supported + format!(" + { + asdf} + ", asdf=1); + //~^^ ERROR invalid format string + println!("\t{}"); + //~^ ERROR 1 positional argument in format string + + // note: `\x7B` is `{` + println!("\x7B}\u{8} {", 1); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + + println!("\x7B}\u8 {", 1); + //~^ ERROR incorrect unicode escape sequence + + // note: raw strings don't escape `\xFF` and `\u{FF}` sequences + println!(r#"\x7B}\u{8} {"#, 1); + //~^ ERROR invalid format string: unmatched `}` found + + println!(r#"\x7B}\u8 {"#, 1); + //~^ ERROR invalid format string: unmatched `}` found +} diff --git a/tests/ui/fmt/format-string-error-2.stderr b/tests/ui/fmt/format-string-error-2.stderr new file mode 100644 index 000000000..76cdfbb93 --- /dev/null +++ b/tests/ui/fmt/format-string-error-2.stderr @@ -0,0 +1,175 @@ +error: incorrect unicode escape sequence + --> $DIR/format-string-error-2.rs:77:20 + | +LL | println!("\x7B}\u8 {", 1); + | ^^^ help: format of unicode escape sequences uses braces: `\u{8}` + +error: invalid format string: expected `'}'`, found `'a'` + --> $DIR/format-string-error-2.rs:5:5 + | +LL | format!("{ + | - because of this opening brace +LL | a"); + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'b'` + --> $DIR/format-string-error-2.rs:9:5 + | +LL | format!("{ \ + | - because of this opening brace +LL | \ +LL | b"); + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'\'` + --> $DIR/format-string-error-2.rs:11:18 + | +LL | format!(r#"{ \ + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'\'` + --> $DIR/format-string-error-2.rs:15:18 + | +LL | format!(r#"{ \n + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'e'` + --> $DIR/format-string-error-2.rs:21:5 + | +LL | format!("{ \n + | - because of this opening brace +LL | \n +LL | e"); + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'a'` + --> $DIR/format-string-error-2.rs:25:5 + | +LL | { + | - because of this opening brace +LL | a"); + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'a'` + --> $DIR/format-string-error-2.rs:29:5 + | +LL | { + | - because of this opening brace +LL | a + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'b'` + --> $DIR/format-string-error-2.rs:35:5 + | +LL | { \ + | - because of this opening brace +LL | \ +LL | b"); + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'b'` + --> $DIR/format-string-error-2.rs:40:5 + | +LL | { \ + | - because of this opening brace +LL | \ +LL | b \ + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'\'` + --> $DIR/format-string-error-2.rs:45:8 + | +LL | raw { \ + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'\'` + --> $DIR/format-string-error-2.rs:50:8 + | +LL | raw { \n + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'e'` + --> $DIR/format-string-error-2.rs:57:5 + | +LL | { \n + | - because of this opening brace +LL | \n +LL | e"); + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'`, found `'a'` + --> $DIR/format-string-error-2.rs:67:5 + | +LL | { + | - because of this opening brace +LL | asdf} + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/format-string-error-2.rs:70:17 + | +LL | println!("\t{}"); + | ^^ + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error-2.rs:74:27 + | +LL | println!("\x7B}\u{8} {", 1); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error-2.rs:81:21 + | +LL | println!(r#"\x7B}\u{8} {"#, 1); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error-2.rs:84:21 + | +LL | println!(r#"\x7B}\u8 {"#, 1); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to 18 previous errors + diff --git a/tests/ui/fmt/format-string-error.rs b/tests/ui/fmt/format-string-error.rs new file mode 100644 index 000000000..eae4f3cb5 --- /dev/null +++ b/tests/ui/fmt/format-string-error.rs @@ -0,0 +1,55 @@ +// ignore-tidy-tab + +fn main() { + println!("{"); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + println!("{{}}"); + println!("}"); + //~^ ERROR invalid format string: unmatched `}` found + let _ = format!("{_}", _ = 6usize); + //~^ ERROR invalid format string: invalid argument name `_` + let _ = format!("{a:_}", a = "", _ = 0); + //~^ ERROR invalid format string: invalid argument name `_` + let _ = format!("{a:._$}", a = "", _ = 0); + //~^ ERROR invalid format string: invalid argument name `_` + let _ = format!("{"); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + let _ = format!("}"); + //~^ ERROR invalid format string: unmatched `}` found + let _ = format!("{\\}"); + //~^ ERROR invalid format string: expected `'}'`, found `'\\'` + let _ = format!("\n\n\n{\n\n\n"); + //~^ ERROR invalid format string + let _ = format!(r###" + + + + {"###); + //~^ ERROR invalid format string + let _ = format!(r###" + + + + { + +"###); + //~^ ERROR invalid format string + let _ = format!(r###" + + + + } + +"###); + //~^^^ ERROR invalid format string + let _ = format!(r###" + + + + } + +"###); + //~^^^ ERROR invalid format string: unmatched `}` found + println!("{} {} {}", 1, 2); + //~^ ERROR 3 positional arguments in format string, but there are 2 arguments +} diff --git a/tests/ui/fmt/format-string-error.stderr b/tests/ui/fmt/format-string-error.stderr new file mode 100644 index 000000000..8a32c2254 --- /dev/null +++ b/tests/ui/fmt/format-string-error.stderr @@ -0,0 +1,125 @@ +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:4:16 + | +LL | println!("{"); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error.rs:7:15 + | +LL | println!("}"); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: invalid argument name `_` + --> $DIR/format-string-error.rs:9:23 + | +LL | let _ = format!("{_}", _ = 6usize); + | ^ invalid argument name in format string + | + = note: argument name cannot be a single underscore + +error: invalid format string: invalid argument name `_` + --> $DIR/format-string-error.rs:11:25 + | +LL | let _ = format!("{a:_}", a = "", _ = 0); + | ^ invalid argument name in format string + | + = note: argument name cannot be a single underscore + +error: invalid format string: invalid argument name `_` + --> $DIR/format-string-error.rs:13:26 + | +LL | let _ = format!("{a:._$}", a = "", _ = 0); + | ^ invalid argument name in format string + | + = note: argument name cannot be a single underscore + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:15:23 + | +LL | let _ = format!("{"); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error.rs:17:22 + | +LL | let _ = format!("}"); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: expected `'}'`, found `'\'` + --> $DIR/format-string-error.rs:19:23 + | +LL | let _ = format!("{\}"); + | -^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:21:35 + | +LL | let _ = format!("\n\n\n{\n\n\n"); + | - ^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:27:3 + | +LL | {"###); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/format-string-error.rs:35:1 + | +LL | { + | - because of this opening brace +LL | +LL | "###); + | ^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error.rs:41:2 + | +LL | } + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: unmatched `}` found + --> $DIR/format-string-error.rs:49:9 + | +LL | } + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: 3 positional arguments in format string, but there are 2 arguments + --> $DIR/format-string-error.rs:53:15 + | +LL | println!("{} {} {}", 1, 2); + | ^^ ^^ ^^ - - + +error: aborting due to 14 previous errors + diff --git a/tests/ui/fmt/format-with-yield-point.rs b/tests/ui/fmt/format-with-yield-point.rs new file mode 100644 index 000000000..e484074cc --- /dev/null +++ b/tests/ui/fmt/format-with-yield-point.rs @@ -0,0 +1,33 @@ +// check-pass +// edition:2021 + +macro_rules! m { + () => { + async {}.await + }; +} + +async fn with_await() { + println!("{} {:?}", "", async {}.await); +} + +async fn with_macro_call_expr() { + println!("{} {:?}", "", m!()); +} + +async fn with_macro_call_stmt_semi() { + println!("{} {:?}", "", { m!(); }); +} + +async fn with_macro_call_stmt_braced() { + println!("{} {:?}", "", { m!{} }); +} + +fn assert_send(_: impl Send) {} + +fn main() { + assert_send(with_await()); + assert_send(with_macro_call_expr()); + assert_send(with_macro_call_stmt_semi()); + assert_send(with_macro_call_stmt_braced()); +} diff --git a/tests/ui/fmt/ifmt-bad-arg.rs b/tests/ui/fmt/ifmt-bad-arg.rs new file mode 100644 index 000000000..68861d7bf --- /dev/null +++ b/tests/ui/fmt/ifmt-bad-arg.rs @@ -0,0 +1,99 @@ +fn main() { + // bad arguments to the format! call + + // bad number of arguments, see #44954 (originally #15780) + + format!("{}"); + //~^ ERROR: 1 positional argument in format string, but no arguments were given + + format!("{1}", 1); + //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument) + //~^^ ERROR: argument never used + + format!("{} {}"); + //~^ ERROR: 2 positional arguments in format string, but no arguments were given + + format!("{0} {1}", 1); + //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument) + + format!("{0} {1} {2}", 1, 2); + //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments) + + format!("{} {value} {} {}", 1, value=2); + //~^ ERROR: 3 positional arguments in format string, but there are 2 arguments + format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2); + //~^ ERROR: 6 positional arguments in format string, but there are 3 arguments + + 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!("", 1, 2); //~ ERROR: multiple unused formatting arguments + format!("{}", 1, 2); //~ ERROR: argument never used + format!("{1}", 1, 2); //~ ERROR: argument never used + format!("{}", 1, foo=2); //~ ERROR: named argument never used + format!("{foo}", 1, foo=2); //~ ERROR: argument never used + format!("", foo=2); //~ ERROR: named argument never used + format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments + + format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument + format!("{foo} {} {}", foo=1, 2); //~ ERROR: positional arguments cannot follow + + // bad named arguments, #35082 + + format!("{valuea} {valueb}", valuea=5, valuec=7); + //~^ ERROR cannot find value `valueb` in this scope + //~^^ ERROR named argument never used + + // bad syntax of the format string + + format!("{"); //~ ERROR: expected `'}'` but string was terminated + + format!("foo } bar"); //~ ERROR: unmatched `}` found + format!("foo }"); //~ ERROR: unmatched `}` found + + format!("foo %s baz", "bar"); //~ ERROR: argument never used + + format!(r##" + + {foo} + + "##); + //~^^^ ERROR: cannot find value `foo` in this scope + + // bad syntax in format string with multiple newlines, #53836 + format!("first number: {} +second number: {} +third number: {} +fourth number: {} +fifth number: {} +sixth number: {} +seventh number: {} +eighth number: {} +ninth number: { +tenth number: {}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + //~^^ ERROR: invalid format string + println!("{} {:.*} {}", 1, 3.2, 4); + //~^ ERROR 4 positional arguments in format string, but there are 3 arguments + //~| ERROR mismatched types + println!("{} {:07$.*} {}", 1, 3.2, 4); + //~^ ERROR invalid reference to positional arguments 3 and 7 (there are 3 arguments) + //~| ERROR mismatched types + println!("{} {:07$} {}", 1, 3.2, 4); + //~^ ERROR invalid reference to positional argument 7 (there are 3 arguments) + println!("{:foo}", 1); //~ ERROR unknown format trait `foo` + println!("{5} {:4$} {6:7$}", 1); + //~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument) + let foo = 1; + println!("{foo:0$}"); + //~^ ERROR invalid reference to positional argument 0 (no arguments were given) + + // We used to ICE here because we tried to unconditionally access the first argument, which + // doesn't exist. + println!("{:.*}"); + //~^ ERROR 2 positional arguments in format string, but no arguments were given + println!("{:.0$}"); + //~^ ERROR invalid reference to positional argument 0 (no arguments were given) +} diff --git a/tests/ui/fmt/ifmt-bad-arg.stderr b/tests/ui/fmt/ifmt-bad-arg.stderr new file mode 100644 index 000000000..c2619d6df --- /dev/null +++ b/tests/ui/fmt/ifmt-bad-arg.stderr @@ -0,0 +1,332 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/ifmt-bad-arg.rs:6:14 + | +LL | format!("{}"); + | ^^ + +error: invalid reference to positional argument 1 (there is 1 argument) + --> $DIR/ifmt-bad-arg.rs:9:15 + | +LL | format!("{1}", 1); + | ^ + | + = note: positional arguments are zero-based + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:9:20 + | +LL | format!("{1}", 1); + | ----- ^ argument never used + | | + | formatting specifier missing + +error: 2 positional arguments in format string, but no arguments were given + --> $DIR/ifmt-bad-arg.rs:13:14 + | +LL | format!("{} {}"); + | ^^ ^^ + +error: invalid reference to positional argument 1 (there is 1 argument) + --> $DIR/ifmt-bad-arg.rs:16:19 + | +LL | format!("{0} {1}", 1); + | ^ + | + = note: positional arguments are zero-based + +error: invalid reference to positional argument 2 (there are 2 arguments) + --> $DIR/ifmt-bad-arg.rs:19:23 + | +LL | format!("{0} {1} {2}", 1, 2); + | ^ + | + = note: positional arguments are zero-based + +error: 3 positional arguments in format string, but there are 2 arguments + --> $DIR/ifmt-bad-arg.rs:22:14 + | +LL | format!("{} {value} {} {}", 1, value=2); + | ^^ ^^ ^^ - - + +error: 6 positional arguments in format string, but there are 3 arguments + --> $DIR/ifmt-bad-arg.rs:24:29 + | +LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2); + | ^^ ^^ ^^ ^^ ^^ ^^ - - - + +error: multiple unused formatting arguments + --> $DIR/ifmt-bad-arg.rs:32:17 + | +LL | format!("", 1, 2); + | -- ^ ^ argument never used + | | | + | | argument never used + | multiple missing formatting specifiers + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:33:22 + | +LL | format!("{}", 1, 2); + | ---- ^ argument never used + | | + | formatting specifier missing + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:34:20 + | +LL | format!("{1}", 1, 2); + | ----- ^ argument never used + | | + | formatting specifier missing + +error: named argument never used + --> $DIR/ifmt-bad-arg.rs:35:26 + | +LL | format!("{}", 1, foo=2); + | ---- ^ named argument never used + | | + | formatting specifier missing + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:36:22 + | +LL | format!("{foo}", 1, foo=2); + | ------- ^ argument never used + | | + | formatting specifier missing + +error: named argument never used + --> $DIR/ifmt-bad-arg.rs:37:21 + | +LL | format!("", foo=2); + | -- ^ named argument never used + | | + | formatting specifier missing + +error: multiple unused formatting arguments + --> $DIR/ifmt-bad-arg.rs:38:32 + | +LL | format!("{} {}", 1, 2, foo=1, bar=2); + | ------- ^ ^ named argument never used + | | | + | | named argument never used + | multiple missing formatting specifiers + +error: duplicate argument named `foo` + --> $DIR/ifmt-bad-arg.rs:40:29 + | +LL | format!("{foo}", foo=1, foo=2); + | --- ^^^ duplicate argument + | | + | previously here + +error: positional arguments cannot follow named arguments + --> $DIR/ifmt-bad-arg.rs:41:35 + | +LL | format!("{foo} {} {}", foo=1, 2); + | ----- ^ positional arguments must be before named arguments + | | + | named argument + +error: named argument never used + --> $DIR/ifmt-bad-arg.rs:45:51 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ------------------- ^ named argument never used + | | + | formatting specifier missing + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/ifmt-bad-arg.rs:51:15 + | +LL | format!("{"); + | -^ expected `'}'` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: unmatched `}` found + --> $DIR/ifmt-bad-arg.rs:53:18 + | +LL | format!("foo } bar"); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: invalid format string: unmatched `}` found + --> $DIR/ifmt-bad-arg.rs:54:18 + | +LL | format!("foo }"); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: argument never used + --> $DIR/ifmt-bad-arg.rs:56:27 + | +LL | format!("foo %s baz", "bar"); + | -- ^^^^^ argument never used + | | + | help: format specifiers use curly braces: `{}` + | + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: invalid format string: expected `'}'`, found `'t'` + --> $DIR/ifmt-bad-arg.rs:75:1 + | +LL | ninth number: { + | - because of this opening brace +LL | tenth number: {}", + | ^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: 4 positional arguments in format string, but there are 3 arguments + --> $DIR/ifmt-bad-arg.rs:78:15 + | +LL | println!("{} {:.*} {}", 1, 3.2, 4); + | ^^ ^^--^ ^^ - --- - + | | + | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: invalid reference to positional arguments 3 and 7 (there are 3 arguments) + --> $DIR/ifmt-bad-arg.rs:81:21 + | +LL | println!("{} {:07$.*} {}", 1, 3.2, 4); + | ^^ ^ + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: invalid reference to positional argument 7 (there are 3 arguments) + --> $DIR/ifmt-bad-arg.rs:84:21 + | +LL | println!("{} {:07$} {}", 1, 3.2, 4); + | ^^ + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: unknown format trait `foo` + --> $DIR/ifmt-bad-arg.rs:86:17 + | +LL | println!("{:foo}", 1); + | ^^^ + | + = note: the only appropriate formatting traits are: + - ``, which uses the `Display` trait + - `?`, which uses the `Debug` trait + - `e`, which uses the `LowerExp` trait + - `E`, which uses the `UpperExp` trait + - `o`, which uses the `Octal` trait + - `p`, which uses the `Pointer` trait + - `b`, which uses the `Binary` trait + - `x`, which uses the `LowerHex` trait + - `X`, which uses the `UpperHex` trait + +error: invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument) + --> $DIR/ifmt-bad-arg.rs:87:16 + | +LL | println!("{5} {:4$} {6:7$}", 1); + | ^ ^^ ^ ^^ + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: invalid reference to positional argument 0 (no arguments were given) + --> $DIR/ifmt-bad-arg.rs:90:20 + | +LL | println!("{foo:0$}"); + | ^^ + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: 2 positional arguments in format string, but no arguments were given + --> $DIR/ifmt-bad-arg.rs:95:15 + | +LL | println!("{:.*}"); + | ^^--^ + | | + | this precision flag adds an extra required argument at position 0, which is why there are 2 arguments expected + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error: invalid reference to positional argument 0 (no arguments were given) + --> $DIR/ifmt-bad-arg.rs:97:16 + | +LL | println!("{:.0$}"); + | ^^^^ + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/ifmt-bad-arg.rs:27:18 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^ not found in this scope + +error[E0425]: cannot find value `bar` in this scope + --> $DIR/ifmt-bad-arg.rs:27:27 + | +LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); + | ^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/ifmt-bad-arg.rs:31:15 + | +LL | format!("{foo}"); + | ^^^ not found in this scope + +error[E0425]: cannot find value `valueb` in this scope + --> $DIR/ifmt-bad-arg.rs:45:24 + | +LL | format!("{valuea} {valueb}", valuea=5, valuec=7); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/ifmt-bad-arg.rs:60:10 + | +LL | {foo} + | ^^^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/ifmt-bad-arg.rs:78:32 + | +LL | println!("{} {:.*} {}", 1, 3.2, 4); + | ^^^ + | | + | expected `usize`, found floating-point number + | arguments to this function are incorrect + | + = note: expected reference `&usize` + found reference `&{float}` +note: associated function defined here + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/ifmt-bad-arg.rs:81:35 + | +LL | println!("{} {:07$.*} {}", 1, 3.2, 4); + | ^^^ + | | + | expected `usize`, found floating-point number + | arguments to this function are incorrect + | + = note: expected reference `&usize` + found reference `&{float}` +note: associated function defined here + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 38 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/fmt/ifmt-bad-format-args.rs b/tests/ui/fmt/ifmt-bad-format-args.rs new file mode 100644 index 000000000..ba7301561 --- /dev/null +++ b/tests/ui/fmt/ifmt-bad-format-args.rs @@ -0,0 +1,4 @@ +fn main() { + format_args!(); //~ ERROR: requires at least a format string argument + format_args!(|| {}); //~ ERROR: must be a string literal +} diff --git a/tests/ui/fmt/ifmt-bad-format-args.stderr b/tests/ui/fmt/ifmt-bad-format-args.stderr new file mode 100644 index 000000000..2db280c5e --- /dev/null +++ b/tests/ui/fmt/ifmt-bad-format-args.stderr @@ -0,0 +1,21 @@ +error: requires at least a format string argument + --> $DIR/ifmt-bad-format-args.rs:2:5 + | +LL | format_args!(); + | ^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: format argument must be a string literal + --> $DIR/ifmt-bad-format-args.rs:3:18 + | +LL | format_args!(|| {}); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | format_args!("{}", || {}); + | +++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/fmt/ifmt-unimpl.rs b/tests/ui/fmt/ifmt-unimpl.rs new file mode 100644 index 000000000..258f4eea5 --- /dev/null +++ b/tests/ui/fmt/ifmt-unimpl.rs @@ -0,0 +1,4 @@ +fn main() { + format!("{:X}", "3"); + //~^ ERROR: `str: UpperHex` is not satisfied +} diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr new file mode 100644 index 000000000..be321c3c5 --- /dev/null +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `str: UpperHex` is not satisfied + --> $DIR/ifmt-unimpl.rs:2:21 + | +LL | format!("{:X}", "3"); + | ^^^ the trait `UpperHex` is not implemented for `str` + | + = help: the following other types implement trait `UpperHex`: + &T + &mut T + NonZeroI128 + NonZeroI16 + NonZeroI32 + NonZeroI64 + NonZeroI8 + NonZeroIsize + and 21 others + = note: required for `&str` to implement `UpperHex` +note: required by a bound in `ArgumentV1::<'a>::new_upper_hex` + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/fmt/ifmt-unknown-trait.rs b/tests/ui/fmt/ifmt-unknown-trait.rs new file mode 100644 index 000000000..158152c89 --- /dev/null +++ b/tests/ui/fmt/ifmt-unknown-trait.rs @@ -0,0 +1,4 @@ +fn main() { + format!("{:notimplemented}", "3"); + //~^ ERROR: unknown format trait `notimplemented` +} diff --git a/tests/ui/fmt/ifmt-unknown-trait.stderr b/tests/ui/fmt/ifmt-unknown-trait.stderr new file mode 100644 index 000000000..459432bf4 --- /dev/null +++ b/tests/ui/fmt/ifmt-unknown-trait.stderr @@ -0,0 +1,19 @@ +error: unknown format trait `notimplemented` + --> $DIR/ifmt-unknown-trait.rs:2:16 + | +LL | format!("{:notimplemented}", "3"); + | ^^^^^^^^^^^^^^ + | + = note: the only appropriate formatting traits are: + - ``, which uses the `Display` trait + - `?`, which uses the `Debug` trait + - `e`, which uses the `LowerExp` trait + - `E`, which uses the `UpperExp` trait + - `o`, which uses the `Octal` trait + - `p`, which uses the `Pointer` trait + - `b`, which uses the `Binary` trait + - `x`, which uses the `LowerHex` trait + - `X`, which uses the `UpperHex` trait + +error: aborting due to previous error + diff --git a/tests/ui/fmt/incorrect-separator.rs b/tests/ui/fmt/incorrect-separator.rs new file mode 100644 index 000000000..b8d2e4a34 --- /dev/null +++ b/tests/ui/fmt/incorrect-separator.rs @@ -0,0 +1,29 @@ +// Allows to track issue #75492: +// https://github.com/rust-lang/rust/issues/75492 + +use std::iter; + +fn main() { + format!("A number: {}". iter::once(42).next().unwrap()); + //~^ ERROR expected `,`, found `.` + + // Other kind of types are also checked: + + format!("A number: {}" / iter::once(42).next().unwrap()); + //~^ ERROR expected `,`, found `/` + + format!("A number: {}"; iter::once(42).next().unwrap()); + //~^ ERROR expected `,`, found `;` + + // Note: this character is an COMBINING COMMA BELOW unicode char + format!("A number: {}" ̦ iter::once(42).next().unwrap()); + //~^ ERROR expected `,`, found `iter` + //~^^ ERROR unknown start of token: \u{326} + + // Here recovery is tested. + // If the `compile_error!` is emitted, then the parser is able to recover + // from the incorrect first separator. + format!("{}". compile_error!("fail")); + //~^ ERROR expected `,`, found `.` + //~^^ ERROR fail +} diff --git a/tests/ui/fmt/incorrect-separator.stderr b/tests/ui/fmt/incorrect-separator.stderr new file mode 100644 index 000000000..5a3e5515b --- /dev/null +++ b/tests/ui/fmt/incorrect-separator.stderr @@ -0,0 +1,44 @@ +error: unknown start of token: \u{326} + --> $DIR/incorrect-separator.rs:19:28 + | +LL | format!("A number: {}" ̦ iter::once(42).next().unwrap()); + | ^ + +error: expected `,`, found `.` + --> $DIR/incorrect-separator.rs:7:27 + | +LL | format!("A number: {}". iter::once(42).next().unwrap()); + | ^ expected `,` + +error: expected `,`, found `/` + --> $DIR/incorrect-separator.rs:12:28 + | +LL | format!("A number: {}" / iter::once(42).next().unwrap()); + | ^ expected `,` + +error: expected `,`, found `;` + --> $DIR/incorrect-separator.rs:15:27 + | +LL | format!("A number: {}"; iter::once(42).next().unwrap()); + | ^ expected `,` + +error: expected `,`, found `iter` + --> $DIR/incorrect-separator.rs:19:30 + | +LL | format!("A number: {}" ̦ iter::once(42).next().unwrap()); + | ^^^^ expected `,` + +error: expected `,`, found `.` + --> $DIR/incorrect-separator.rs:26:17 + | +LL | format!("{}". compile_error!("fail")); + | ^ expected `,` + +error: fail + --> $DIR/incorrect-separator.rs:26:19 + | +LL | format!("{}". compile_error!("fail")); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/fmt/indoc-issue-106408.rs b/tests/ui/fmt/indoc-issue-106408.rs new file mode 100644 index 000000000..e4e3093b5 --- /dev/null +++ b/tests/ui/fmt/indoc-issue-106408.rs @@ -0,0 +1,9 @@ +// aux-build:format-string-proc-macro.rs +// check-pass + +extern crate format_string_proc_macro; + +fn main() { + let a = 0; + format_string_proc_macro::capture_a_with_prepended_space_preserve_span!("{a}"); +} diff --git a/tests/ui/fmt/issue-103826.rs b/tests/ui/fmt/issue-103826.rs new file mode 100644 index 000000000..a11ec37a0 --- /dev/null +++ b/tests/ui/fmt/issue-103826.rs @@ -0,0 +1,8 @@ +fn main() { + format!("{\x7D"); + //~^ ERROR 1 positional argument in format string, but no arguments were given + format!("\x7B\x7D"); + //~^ ERROR 1 positional argument in format string, but no arguments were given + format!("{\x7D {\x7D"); + //~^ ERROR 2 positional arguments in format string, but no arguments were given +} diff --git a/tests/ui/fmt/issue-103826.stderr b/tests/ui/fmt/issue-103826.stderr new file mode 100644 index 000000000..0f27e1930 --- /dev/null +++ b/tests/ui/fmt/issue-103826.stderr @@ -0,0 +1,20 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-103826.rs:2:14 + | +LL | format!("{\x7D"); + | ^^^^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-103826.rs:4:14 + | +LL | format!("\x7B\x7D"); + | ^^^^^^^^ + +error: 2 positional arguments in format string, but no arguments were given + --> $DIR/issue-103826.rs:6:14 + | +LL | format!("{\x7D {\x7D"); + | ^^^^^ ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/fmt/issue-104142.rs b/tests/ui/fmt/issue-104142.rs new file mode 100644 index 000000000..8d7283a71 --- /dev/null +++ b/tests/ui/fmt/issue-104142.rs @@ -0,0 +1,6 @@ +fn main() { + println!( + r#" + \"\'}、"# //~ ERROR invalid format string: unmatched `}` found + ); +} diff --git a/tests/ui/fmt/issue-104142.stderr b/tests/ui/fmt/issue-104142.stderr new file mode 100644 index 000000000..d41644faa --- /dev/null +++ b/tests/ui/fmt/issue-104142.stderr @@ -0,0 +1,10 @@ +error: invalid format string: unmatched `}` found + --> $DIR/issue-104142.rs:4:9 + | +LL | \"\'}、"# + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to previous error + diff --git a/tests/ui/fmt/issue-86085.rs b/tests/ui/fmt/issue-86085.rs new file mode 100644 index 000000000..63d42b769 --- /dev/null +++ b/tests/ui/fmt/issue-86085.rs @@ -0,0 +1,6 @@ +// Tests for an ICE with the fuzzed input below. + +fn main ( ) { +format ! ( concat ! ( r#"lJð¿Ã†ï¿½.ð¿ï¿½"# , "r} {}" ) ) ; +//~^ ERROR: invalid format string: unmatched `}` found +} diff --git a/tests/ui/fmt/issue-86085.stderr b/tests/ui/fmt/issue-86085.stderr new file mode 100644 index 000000000..ee7d8a5cc --- /dev/null +++ b/tests/ui/fmt/issue-86085.stderr @@ -0,0 +1,11 @@ +error: invalid format string: unmatched `}` found + --> $DIR/issue-86085.rs:4:12 + | +LL | format ! ( concat ! ( r#"lJð¿Ã†ï¿½.ð¿ï¿½"# , "r} {}" ) ) ; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/fmt/issue-89173.rs b/tests/ui/fmt/issue-89173.rs new file mode 100644 index 000000000..fc99af408 --- /dev/null +++ b/tests/ui/fmt/issue-89173.rs @@ -0,0 +1,14 @@ +// Regression test for #89173: Make sure a helpful note is issued for +// printf-style format strings using `*` to specify the width. + +fn main() { + let num = 0x0abcde; + let width = 6; + print!("%0*x", width, num); + //~^ ERROR: multiple unused formatting arguments + //~| NOTE: multiple missing formatting specifiers + //~| NOTE: argument never used + //~| NOTE: argument never used + //~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width + //~| NOTE: printf formatting is not supported +} diff --git a/tests/ui/fmt/issue-89173.stderr b/tests/ui/fmt/issue-89173.stderr new file mode 100644 index 000000000..ddeb769ea --- /dev/null +++ b/tests/ui/fmt/issue-89173.stderr @@ -0,0 +1,18 @@ +error: multiple unused formatting arguments + --> $DIR/issue-89173.rs:7:20 + | +LL | print!("%0*x", width, num); + | ------ ^^^^^ ^^^ argument never used + | | | + | | argument never used + | multiple missing formatting specifiers + | +note: format specifiers use curly braces, and you have to use a positional or named parameter for the width + --> $DIR/issue-89173.rs:7:13 + | +LL | print!("%0*x", width, num); + | ^^^^ + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: aborting due to previous error + diff --git a/tests/ui/fmt/issue-91556.rs b/tests/ui/fmt/issue-91556.rs new file mode 100644 index 000000000..e782e6f90 --- /dev/null +++ b/tests/ui/fmt/issue-91556.rs @@ -0,0 +1,8 @@ +fn main() { + let _ = format!(concat!("{0}ð–³ð–¾ð—Œð—{"), i); + //~^ ERROR: invalid format string: expected `'}'` but string was terminated + //~| NOTE: if you intended to print `{`, you can escape it using `{{` + //~| NOTE: in this expansion of concat! + //~| NOTE: in this expansion of concat! + //~| NOTE: expected `'}'` in format string +} diff --git a/tests/ui/fmt/issue-91556.stderr b/tests/ui/fmt/issue-91556.stderr new file mode 100644 index 000000000..dbd5aef45 --- /dev/null +++ b/tests/ui/fmt/issue-91556.stderr @@ -0,0 +1,11 @@ +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/issue-91556.rs:2:19 + | +LL | let _ = format!(concat!("{0}ð–³ð–¾ð—Œð—{"), i); + | ^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/fmt/respanned-literal-issue-106191.rs b/tests/ui/fmt/respanned-literal-issue-106191.rs new file mode 100644 index 000000000..bb741c0ef --- /dev/null +++ b/tests/ui/fmt/respanned-literal-issue-106191.rs @@ -0,0 +1,15 @@ +// aux-build:format-string-proc-macro.rs +// check-fail +// known-bug: #106191 +// unset-rustc-env:RUST_BACKTRACE +// had to be reverted +// error-pattern:internal compiler error +// failure-status:101 +// dont-check-compiler-stderr + +extern crate format_string_proc_macro; + +fn main() { + format_string_proc_macro::respan_to_invalid_format_literal!("¡"); + format_args!(r#concat!("¡ {")); +} diff --git a/tests/ui/fmt/respanned-literal-issue-106191.stderr b/tests/ui/fmt/respanned-literal-issue-106191.stderr new file mode 100644 index 000000000..16717f422 --- /dev/null +++ b/tests/ui/fmt/respanned-literal-issue-106191.stderr @@ -0,0 +1,2 @@ + query stack during panic: +end of query stack diff --git a/tests/ui/fmt/send-sync.rs b/tests/ui/fmt/send-sync.rs new file mode 100644 index 000000000..95ec68d1d --- /dev/null +++ b/tests/ui/fmt/send-sync.rs @@ -0,0 +1,10 @@ +fn send(_: T) {} +fn sync(_: T) {} + +fn main() { + // `Cell` is not `Sync`, so `&Cell` is neither `Sync` nor `Send`, + // `std::fmt::Arguments` used to forget this... + let c = std::cell::Cell::new(42); + send(format_args!("{:?}", c)); //~ ERROR E0277 + sync(format_args!("{:?}", c)); //~ ERROR E0277 +} diff --git a/tests/ui/fmt/send-sync.stderr b/tests/ui/fmt/send-sync.stderr new file mode 100644 index 000000000..3ed040c3a --- /dev/null +++ b/tests/ui/fmt/send-sync.stderr @@ -0,0 +1,43 @@ +error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely + --> $DIR/send-sync.rs:8:10 + | +LL | send(format_args!("{:?}", c)); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `[ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque` + = note: required because it appears within the type `&core::fmt::Opaque` + = note: required because it appears within the type `ArgumentV1<'_>` + = note: required because it appears within the type `[ArgumentV1<'_>]` + = note: required for `&[ArgumentV1<'_>]` to implement `Send` + = note: required because it appears within the type `Arguments<'_>` +note: required by a bound in `send` + --> $DIR/send-sync.rs:1:12 + | +LL | fn send(_: T) {} + | ^^^^ required by this bound in `send` + +error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely + --> $DIR/send-sync.rs:9:10 + | +LL | sync(format_args!("{:?}", c)); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::Opaque` + = note: required because it appears within the type `&core::fmt::Opaque` + = note: required because it appears within the type `ArgumentV1<'_>` + = note: required because it appears within the type `[ArgumentV1<'_>]` + = note: required because it appears within the type `&[ArgumentV1<'_>]` + = note: required because it appears within the type `Arguments<'_>` +note: required by a bound in `sync` + --> $DIR/send-sync.rs:2:12 + | +LL | fn sync(_: T) {} + | ^^^^ required by this bound in `sync` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/fmt/struct-field-as-captured-argument.fixed b/tests/ui/fmt/struct-field-as-captured-argument.fixed new file mode 100644 index 000000000..f7244f674 --- /dev/null +++ b/tests/ui/fmt/struct-field-as-captured-argument.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +#[derive(Debug)] +struct Foo { + field: usize, +} + +fn main() { + let foo = Foo { field: 0 }; + let bar = 3; + format!("{0}", foo.field); //~ ERROR invalid format string: field access isn't supported + format!("{1} {} {bar}", "aa", foo.field); //~ ERROR invalid format string: field access isn't supported + format!("{2} {} {1} {bar}", "aa", "bb", foo.field); //~ ERROR invalid format string: field access isn't supported + format!("{1} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported + format!("{1:?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported + format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported + format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported +} diff --git a/tests/ui/fmt/struct-field-as-captured-argument.rs b/tests/ui/fmt/struct-field-as-captured-argument.rs new file mode 100644 index 000000000..ab5f2552b --- /dev/null +++ b/tests/ui/fmt/struct-field-as-captured-argument.rs @@ -0,0 +1,18 @@ +// run-rustfix + +#[derive(Debug)] +struct Foo { + field: usize, +} + +fn main() { + let foo = Foo { field: 0 }; + let bar = 3; + format!("{foo.field}"); //~ ERROR invalid format string: field access isn't supported + format!("{foo.field} {} {bar}", "aa"); //~ ERROR invalid format string: field access isn't supported + format!("{foo.field} {} {1} {bar}", "aa", "bb"); //~ ERROR invalid format string: field access isn't supported + format!("{foo.field} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported + format!("{foo.field:?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported + format!("{foo.field:#?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported + format!("{foo.field:.3} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported +} diff --git a/tests/ui/fmt/struct-field-as-captured-argument.stderr b/tests/ui/fmt/struct-field-as-captured-argument.stderr new file mode 100644 index 000000000..7ea8b4068 --- /dev/null +++ b/tests/ui/fmt/struct-field-as-captured-argument.stderr @@ -0,0 +1,79 @@ +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:11:15 + | +LL | format!("{foo.field}"); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{0}", foo.field); + | ~ +++++++++++ + +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:12:15 + | +LL | format!("{foo.field} {} {bar}", "aa"); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{1} {} {bar}", "aa", foo.field); + | ~ +++++++++++ + +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:13:15 + | +LL | format!("{foo.field} {} {1} {bar}", "aa", "bb"); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{2} {} {1} {bar}", "aa", "bb", foo.field); + | ~ +++++++++++ + +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:14:15 + | +LL | format!("{foo.field} {} {baz}", "aa", baz = 3); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{1} {} {baz}", "aa", foo.field, baz = 3); + | ~ +++++++++++ + +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:15:15 + | +LL | format!("{foo.field:?} {} {baz}", "aa", baz = 3); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{1:?} {} {baz}", "aa", foo.field, baz = 3); + | ~ +++++++++++ + +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:16:15 + | +LL | format!("{foo.field:#?} {} {baz}", "aa", baz = 3); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3); + | ~ +++++++++++ + +error: invalid format string: field access isn't supported + --> $DIR/struct-field-as-captured-argument.rs:17:15 + | +LL | format!("{foo.field:.3} {} {baz}", "aa", baz = 3); + | ^^^^^^^^^ not supported in format string + | +help: consider using a positional formatting argument instead + | +LL | format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3); + | ~ +++++++++++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/fmt/unicode-escape-spans.rs b/tests/ui/fmt/unicode-escape-spans.rs new file mode 100644 index 000000000..753d91ce5 --- /dev/null +++ b/tests/ui/fmt/unicode-escape-spans.rs @@ -0,0 +1,19 @@ +fn main() { + // 1 byte in UTF-8 + format!("\u{000041}{a}"); //~ ERROR cannot find value + format!("\u{0041}{a}"); //~ ERROR cannot find value + format!("\u{41}{a}"); //~ ERROR cannot find value + format!("\u{0}{a}"); //~ ERROR cannot find value + + // 2 bytes + format!("\u{0df}{a}"); //~ ERROR cannot find value + format!("\u{df}{a}"); //~ ERROR cannot find value + + // 3 bytes + format!("\u{00211d}{a}"); //~ ERROR cannot find value + format!("\u{211d}{a}"); //~ ERROR cannot find value + + // 4 bytes + format!("\u{1f4a3}{a}"); //~ ERROR cannot find value + format!("\u{10ffff}{a}"); //~ ERROR cannot find value +} diff --git a/tests/ui/fmt/unicode-escape-spans.stderr b/tests/ui/fmt/unicode-escape-spans.stderr new file mode 100644 index 000000000..1d8473f01 --- /dev/null +++ b/tests/ui/fmt/unicode-escape-spans.stderr @@ -0,0 +1,63 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:3:25 + | +LL | format!("\u{000041}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:4:23 + | +LL | format!("\u{0041}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:5:21 + | +LL | format!("\u{41}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:6:20 + | +LL | format!("\u{0}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:9:22 + | +LL | format!("\u{0df}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:10:21 + | +LL | format!("\u{df}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:13:25 + | +LL | format!("\u{00211d}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:14:23 + | +LL | format!("\u{211d}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:17:24 + | +LL | format!("\u{1f4a3}{a}"); + | ^ not found in this scope + +error[E0425]: cannot find value `a` in this scope + --> $DIR/unicode-escape-spans.rs:18:25 + | +LL | format!("\u{10ffff}{a}"); + | ^ not found in this scope + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/fn-in-pat.rs b/tests/ui/fn-in-pat.rs new file mode 100644 index 000000000..2d7c86b86 --- /dev/null +++ b/tests/ui/fn-in-pat.rs @@ -0,0 +1,16 @@ +struct A {} + +impl A { + fn new() {} +} + +fn hof(_: F) where F: FnMut(()) {} + +fn ice() { + hof(|c| match c { + A::new() => (), //~ ERROR expected tuple struct or tuple variant, found associated function + _ => () + }) +} + +fn main() {} diff --git a/tests/ui/fn-in-pat.stderr b/tests/ui/fn-in-pat.stderr new file mode 100644 index 000000000..2482d6326 --- /dev/null +++ b/tests/ui/fn-in-pat.stderr @@ -0,0 +1,11 @@ +error[E0164]: expected tuple struct or tuple variant, found associated function `A::new` + --> $DIR/fn-in-pat.rs:11:9 + | +LL | A::new() => (), + | ^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/fn/bad-main.rs b/tests/ui/fn/bad-main.rs new file mode 100644 index 000000000..751159961 --- /dev/null +++ b/tests/ui/fn/bad-main.rs @@ -0,0 +1 @@ +fn main(x: isize) { } //~ ERROR: `main` function has wrong type [E0580] diff --git a/tests/ui/fn/bad-main.stderr b/tests/ui/fn/bad-main.stderr new file mode 100644 index 000000000..675b66d05 --- /dev/null +++ b/tests/ui/fn/bad-main.stderr @@ -0,0 +1,12 @@ +error[E0580]: `main` function has wrong type + --> $DIR/bad-main.rs:1:1 + | +LL | fn main(x: isize) { } + | ^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `fn()` + found fn pointer `fn(isize)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/fn/dyn-fn-alignment.rs b/tests/ui/fn/dyn-fn-alignment.rs new file mode 100644 index 000000000..cedfd1cf2 --- /dev/null +++ b/tests/ui/fn/dyn-fn-alignment.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(dead_code)] +#[repr(align(256))] +struct A { + v: u8, +} + +impl A { + fn f(&self) -> *const A { + self + } +} + +fn f2(v: u8) -> Box *const A> { + let a = A { v }; + Box::new(move || a.f()) +} + +fn main() { + let addr = f2(0)(); + assert_eq!(addr as usize % 256, 0, "addr: {:?}", addr); +} diff --git a/tests/ui/fn/expr-fn-panic.rs b/tests/ui/fn/expr-fn-panic.rs new file mode 100644 index 000000000..123b57f97 --- /dev/null +++ b/tests/ui/fn/expr-fn-panic.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn f() -> ! { + panic!() +} + +fn main() { + f(); +} diff --git a/tests/ui/fn/expr-fn.rs b/tests/ui/fn/expr-fn.rs new file mode 100644 index 000000000..253cbfd5d --- /dev/null +++ b/tests/ui/fn/expr-fn.rs @@ -0,0 +1,62 @@ +// run-pass +#![allow(unused_braces)] + +fn test_int() { + fn f() -> isize { 10 } + assert_eq!(f(), 10); +} + +fn test_vec() { + fn f() -> Vec { vec![10, 11] } + let vect = f(); + assert_eq!(vect[1], 11); +} + +fn test_generic() { + fn f(t: T) -> T { t } + assert_eq!(f(10), 10); +} + +fn test_alt() { + fn f() -> isize { match true { false => { 10 } true => { 20 } } } + assert_eq!(f(), 20); +} + +fn test_if() { + fn f() -> isize { if true { 10 } else { 20 } } + assert_eq!(f(), 10); +} + +fn test_block() { + fn f() -> isize { { 10 } } + assert_eq!(f(), 10); +} + +fn test_ret() { + fn f() -> isize { + return 10 // no semi + + } + assert_eq!(f(), 10); +} + + +// From issue #372 +fn test_372() { + fn f() -> isize { let x = { 3 }; x } + assert_eq!(f(), 3); +} + +fn test_nil() { () } + +pub fn main() { + test_int(); + test_vec(); + test_generic(); + test_alt(); + test_if(); + test_block(); + test_ret(); + test_372(); + test_nil(); +} diff --git a/tests/ui/fn/fn-bad-block-type.rs b/tests/ui/fn/fn-bad-block-type.rs new file mode 100644 index 000000000..01dcff058 --- /dev/null +++ b/tests/ui/fn/fn-bad-block-type.rs @@ -0,0 +1,5 @@ +// error-pattern:mismatched types + +fn f() -> isize { true } + +fn main() { } diff --git a/tests/ui/fn/fn-bad-block-type.stderr b/tests/ui/fn/fn-bad-block-type.stderr new file mode 100644 index 000000000..13ebfd1e2 --- /dev/null +++ b/tests/ui/fn/fn-bad-block-type.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/fn-bad-block-type.rs:3:19 + | +LL | fn f() -> isize { true } + | ----- ^^^^ expected `isize`, found `bool` + | | + | expected `isize` because of return type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fn/fn-closure-mutable-capture.rs b/tests/ui/fn/fn-closure-mutable-capture.rs new file mode 100644 index 000000000..97141886f --- /dev/null +++ b/tests/ui/fn/fn-closure-mutable-capture.rs @@ -0,0 +1,12 @@ +pub fn bar(_f: F) {} //~ NOTE change this to accept `FnMut` instead of `Fn` + +pub fn foo() { + let mut x = 0; + bar(move || x = 1); + //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure + //~| NOTE cannot assign + //~| NOTE expects `Fn` instead of `FnMut` + //~| NOTE in this closure +} + +fn main() {} diff --git a/tests/ui/fn/fn-closure-mutable-capture.stderr b/tests/ui/fn/fn-closure-mutable-capture.stderr new file mode 100644 index 000000000..03e3d545a --- /dev/null +++ b/tests/ui/fn/fn-closure-mutable-capture.stderr @@ -0,0 +1,15 @@ +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/fn-closure-mutable-capture.rs:5:17 + | +LL | pub fn bar(_f: F) {} + | - change this to accept `FnMut` instead of `Fn` +... +LL | bar(move || x = 1); + | --- ------- ^^^^^ cannot assign + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/fn/fn-compare-mismatch.rs b/tests/ui/fn/fn-compare-mismatch.rs new file mode 100644 index 000000000..d734d54e8 --- /dev/null +++ b/tests/ui/fn/fn-compare-mismatch.rs @@ -0,0 +1,7 @@ +fn main() { + fn f() { } + fn g() { } + let x = f == g; + //~^ ERROR binary operation `==` cannot be applied + //~| ERROR mismatched types +} diff --git a/tests/ui/fn/fn-compare-mismatch.stderr b/tests/ui/fn/fn-compare-mismatch.stderr new file mode 100644 index 000000000..df838cb11 --- /dev/null +++ b/tests/ui/fn/fn-compare-mismatch.stderr @@ -0,0 +1,26 @@ +error[E0369]: binary operation `==` cannot be applied to type `fn() {f}` + --> $DIR/fn-compare-mismatch.rs:4:15 + | +LL | let x = f == g; + | - ^^ - fn() {g} + | | + | fn() {f} + | +help: use parentheses to call these + | +LL | let x = f() == g(); + | ++ ++ + +error[E0308]: mismatched types + --> $DIR/fn-compare-mismatch.rs:4:18 + | +LL | let x = f == g; + | ^ expected fn item, found a different fn item + | + = note: expected fn item `fn() {f}` + found fn item `fn() {g}` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/fn/fn-item-type.rs b/tests/ui/fn/fn-item-type.rs new file mode 100644 index 000000000..1831e6cbf --- /dev/null +++ b/tests/ui/fn/fn-item-type.rs @@ -0,0 +1,53 @@ +// Test that the types of distinct fn items are not compatible by +// default. See also `run-pass/fn-item-type-*.rs`. + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } + +fn eq(x: T, y: T) { } + +trait Foo { fn foo() { /* this is a default fn */ } } +impl Foo for T { /* `foo` is still default here */ } + +fn main() { + eq(foo::, bar::); + //~^ ERROR mismatched types + //~| expected fn item `fn(_) -> _ {foo::}` + //~| found fn item `fn(_) -> _ {bar::}` + //~| expected fn item, found a different fn item + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + eq(foo::, foo::); + //~^ ERROR mismatched types + //~| expected `u8`, found `i8` + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + eq(bar::, bar::>); + //~^ ERROR mismatched types + //~| found fn item `fn(_) -> _ {bar::>}` + //~| expected struct `String`, found struct `Vec` + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + // Make sure we distinguish between trait methods correctly. + eq(::foo, ::foo); + //~^ ERROR mismatched types + //~| expected `u8`, found `u16` + //~| different `fn` items always have unique types, even if their signatures are the same + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + eq(foo::, bar:: as fn(isize) -> isize); + //~^ ERROR mismatched types + //~| found fn pointer `fn(_) -> _` + //~| expected fn item, found fn pointer + //~| change the expected type to be function pointer + //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer + + eq(foo:: as fn(isize) -> isize, bar::); // ok! +} diff --git a/tests/ui/fn/fn-item-type.stderr b/tests/ui/fn/fn-item-type.stderr new file mode 100644 index 000000000..f03a47d5c --- /dev/null +++ b/tests/ui/fn/fn-item-type.stderr @@ -0,0 +1,97 @@ +error[E0308]: mismatched types + --> $DIR/fn-item-type.rs:13:19 + | +LL | eq(foo::, bar::); + | -- ^^^^^^^^^ expected fn item, found a different fn item + | | + | arguments to this function are incorrect + | + = note: expected fn item `fn(_) -> _ {foo::}` + found fn item `fn(_) -> _ {bar::}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo:: as fn(isize) -> isize` +note: function defined here + --> $DIR/fn-item-type.rs:7:4 + | +LL | fn eq(x: T, y: T) { } + | ^^ ---- + +error[E0308]: mismatched types + --> $DIR/fn-item-type.rs:22:19 + | +LL | eq(foo::, foo::); + | -- ^^^^^^^^^ expected `u8`, found `i8` + | | + | arguments to this function are incorrect + | + = note: expected fn item `fn(_) -> _ {foo::}` + found fn item `fn(_) -> _ {foo::}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo:: as fn(isize) -> isize` +note: function defined here + --> $DIR/fn-item-type.rs:7:4 + | +LL | fn eq(x: T, y: T) { } + | ^^ ---- + +error[E0308]: mismatched types + --> $DIR/fn-item-type.rs:29:23 + | +LL | eq(bar::, bar::>); + | -- ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec` + | | + | arguments to this function are incorrect + | + = note: expected fn item `fn(_) -> _ {bar::}` + found fn item `fn(_) -> _ {bar::>}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar:: as fn(isize) -> isize` +note: function defined here + --> $DIR/fn-item-type.rs:7:4 + | +LL | fn eq(x: T, y: T) { } + | ^^ ---- + +error[E0308]: mismatched types + --> $DIR/fn-item-type.rs:38:26 + | +LL | eq(::foo, ::foo); + | -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16` + | | + | arguments to this function are incorrect + | + = note: expected fn item `fn() {::foo}` + found fn item `fn() {::foo}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `fn()` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `::foo as fn()` +note: function defined here + --> $DIR/fn-item-type.rs:7:4 + | +LL | fn eq(x: T, y: T) { } + | ^^ ---- + +error[E0308]: mismatched types + --> $DIR/fn-item-type.rs:45:19 + | +LL | eq(foo::, bar:: as fn(isize) -> isize); + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer + | | + | arguments to this function are incorrect + | + = note: expected fn item `fn(_) -> _ {foo::}` + found fn pointer `fn(_) -> _` + = help: change the expected type to be function pointer `fn(isize) -> isize` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo:: as fn(isize) -> isize` +note: function defined here + --> $DIR/fn-item-type.rs:7:4 + | +LL | fn eq(x: T, y: T) { } + | ^^ ---- + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fn/fn-recover-return-sign.fixed b/tests/ui/fn/fn-recover-return-sign.fixed new file mode 100644 index 000000000..076be6a35 --- /dev/null +++ b/tests/ui/fn/fn-recover-return-sign.fixed @@ -0,0 +1,28 @@ +// run-rustfix +#![allow(unused)] +fn a() -> usize { 0 } +//~^ ERROR return types are denoted using `->` + +fn b()-> usize { 0 } +//~^ ERROR return types are denoted using `->` + +fn bar(_: u32) {} + +fn baz() -> *const dyn Fn(u32) { unimplemented!() } + +fn foo() { + match () { + _ if baz() == &bar as &dyn Fn(u32) => (), + () => (), + } +} + +fn main() { + let foo = |a: bool| -> bool { a }; + //~^ ERROR return types are denoted using `->` + dbg!(foo(false)); + + let bar = |a: bool|-> bool { a }; + //~^ ERROR return types are denoted using `->` + dbg!(bar(false)); +} diff --git a/tests/ui/fn/fn-recover-return-sign.rs b/tests/ui/fn/fn-recover-return-sign.rs new file mode 100644 index 000000000..0656023c0 --- /dev/null +++ b/tests/ui/fn/fn-recover-return-sign.rs @@ -0,0 +1,28 @@ +// run-rustfix +#![allow(unused)] +fn a() => usize { 0 } +//~^ ERROR return types are denoted using `->` + +fn b(): usize { 0 } +//~^ ERROR return types are denoted using `->` + +fn bar(_: u32) {} + +fn baz() -> *const dyn Fn(u32) { unimplemented!() } + +fn foo() { + match () { + _ if baz() == &bar as &dyn Fn(u32) => (), + () => (), + } +} + +fn main() { + let foo = |a: bool| => bool { a }; + //~^ ERROR return types are denoted using `->` + dbg!(foo(false)); + + let bar = |a: bool|: bool { a }; + //~^ ERROR return types are denoted using `->` + dbg!(bar(false)); +} diff --git a/tests/ui/fn/fn-recover-return-sign.stderr b/tests/ui/fn/fn-recover-return-sign.stderr new file mode 100644 index 000000000..983109730 --- /dev/null +++ b/tests/ui/fn/fn-recover-return-sign.stderr @@ -0,0 +1,26 @@ +error: return types are denoted using `->` + --> $DIR/fn-recover-return-sign.rs:3:8 + | +LL | fn a() => usize { 0 } + | ^^ help: use `->` instead + +error: return types are denoted using `->` + --> $DIR/fn-recover-return-sign.rs:6:7 + | +LL | fn b(): usize { 0 } + | ^ help: use `->` instead + +error: return types are denoted using `->` + --> $DIR/fn-recover-return-sign.rs:21:25 + | +LL | let foo = |a: bool| => bool { a }; + | ^^ help: use `->` instead + +error: return types are denoted using `->` + --> $DIR/fn-recover-return-sign.rs:25:24 + | +LL | let bar = |a: bool|: bool { a }; + | ^ help: use `->` instead + +error: aborting due to 4 previous errors + diff --git a/tests/ui/fn/fn-recover-return-sign2.rs b/tests/ui/fn/fn-recover-return-sign2.rs new file mode 100644 index 000000000..31f56565c --- /dev/null +++ b/tests/ui/fn/fn-recover-return-sign2.rs @@ -0,0 +1,8 @@ +// Separate test file because `Fn() => bool` isn't getting fixed and rustfix complained that +// even though a fix was applied the code was still incorrect + +fn foo() => impl Fn() => bool { + //~^ ERROR return types are denoted using `->` + //~| ERROR expected one of `+`, `->`, `::`, `where`, or `{`, found `=>` + unimplemented!() +} diff --git a/tests/ui/fn/fn-recover-return-sign2.stderr b/tests/ui/fn/fn-recover-return-sign2.stderr new file mode 100644 index 000000000..25ee8dd0c --- /dev/null +++ b/tests/ui/fn/fn-recover-return-sign2.stderr @@ -0,0 +1,14 @@ +error: return types are denoted using `->` + --> $DIR/fn-recover-return-sign2.rs:4:10 + | +LL | fn foo() => impl Fn() => bool { + | ^^ help: use `->` instead + +error: expected one of `+`, `->`, `::`, `where`, or `{`, found `=>` + --> $DIR/fn-recover-return-sign2.rs:4:23 + | +LL | fn foo() => impl Fn() => bool { + | ^^ expected one of `+`, `->`, `::`, `where`, or `{` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/fn/fn-trait-formatting.rs b/tests/ui/fn/fn-trait-formatting.rs new file mode 100644 index 000000000..636ac7107 --- /dev/null +++ b/tests/ui/fn/fn-trait-formatting.rs @@ -0,0 +1,21 @@ +fn needs_fn(x: F) where F: Fn(isize) -> isize {} + + + +fn main() { + let _: () = Box::new(|_: isize| {}) as Box; + //~^ ERROR mismatched types + //~| expected unit type `()` + //~| found struct `Box` + let _: () = Box::new(|_: isize, isize| {}) as Box; + //~^ ERROR mismatched types + //~| expected unit type `()` + //~| found struct `Box` + let _: () = Box::new(|| -> isize { unimplemented!() }) as Box isize>; + //~^ ERROR mismatched types + //~| expected unit type `()` + //~| found struct `Box isize>` + + needs_fn(1); + //~^ ERROR expected a `Fn<(isize,)>` closure, found `{integer}` +} diff --git a/tests/ui/fn/fn-trait-formatting.stderr b/tests/ui/fn/fn-trait-formatting.stderr new file mode 100644 index 000000000..2a674d3c1 --- /dev/null +++ b/tests/ui/fn/fn-trait-formatting.stderr @@ -0,0 +1,60 @@ +error[E0308]: mismatched types + --> $DIR/fn-trait-formatting.rs:6:17 + | +LL | let _: () = Box::new(|_: isize| {}) as Box; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` + | | + | expected due to this + | + = note: expected unit type `()` + found struct `Box` +help: use parentheses to call this trait object + | +LL | let _: () = (Box::new(|_: isize| {}) as Box)(/* isize */); + | + ++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-trait-formatting.rs:10:17 + | +LL | let _: () = Box::new(|_: isize, isize| {}) as Box; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` + | | + | expected due to this + | + = note: expected unit type `()` + found struct `Box` +help: use parentheses to call this trait object + | +LL | let _: () = (Box::new(|_: isize, isize| {}) as Box)(/* isize */, /* isize */); + | + +++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-trait-formatting.rs:14:17 + | +LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box isize>; + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box` + | | + | expected due to this + | + = note: expected unit type `()` + found struct `Box isize>` + +error[E0277]: expected a `Fn<(isize,)>` closure, found `{integer}` + --> $DIR/fn-trait-formatting.rs:19:14 + | +LL | needs_fn(1); + | -------- ^ expected an `Fn<(isize,)>` closure, found `{integer}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(isize,)>` is not implemented for `{integer}` +note: required by a bound in `needs_fn` + --> $DIR/fn-trait-formatting.rs:1:31 + | +LL | fn needs_fn(x: F) where F: Fn(isize) -> isize {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `needs_fn` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/fn/fun-call-variants.rs b/tests/ui/fn/fun-call-variants.rs new file mode 100644 index 000000000..5b83e2620 --- /dev/null +++ b/tests/ui/fn/fun-call-variants.rs @@ -0,0 +1,12 @@ +// run-pass + +fn ho(f: F) -> isize where F: FnOnce(isize) -> isize { let n: isize = f(3); return n; } + +fn direct(x: isize) -> isize { return x + 1; } + +pub fn main() { + let a: isize = direct(3); // direct + let b: isize = ho(direct); // indirect unbound + + assert_eq!(a, b); +} diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs new file mode 100644 index 000000000..5d9245556 --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs @@ -0,0 +1,23 @@ +// check-fail + +trait Trait { + type Type; +} + +impl Trait for T { + type Type = (); +} + +fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type) +where + 'a: 'a, + 'b: 'b, +{ +} + +fn g<'a, 'b>() { + f::<'a, 'b>(()); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr new file mode 100644 index 000000000..0c3df04ea --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type-2.rs:19:5 + | +LL | fn g<'a, 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | f::<'a, 'b>(()); + | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `f` + = note: the function `f` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs new file mode 100644 index 000000000..888f74cf6 --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs @@ -0,0 +1,22 @@ +// check-pass + +pub trait Yokeable<'a>: 'static { + type Output: 'a; +} + +impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T { + type Output = &'a T; +} + +pub trait ZeroCopyFrom: for<'a> Yokeable<'a> { + /// Clone the cart `C` into a [`Yokeable`] struct, which may retain references into `C`. + fn zero_copy_from<'b>(cart: &'b C) -> >::Output; +} + +impl ZeroCopyFrom<[T]> for &'static [T] { + fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] { + cart + } +} + +fn main() {} diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs new file mode 100644 index 000000000..12859252c --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs @@ -0,0 +1,24 @@ +// A regression test for #98543 + +trait Trait { + type Type; +} + +impl Trait for T { + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str +where + &'a &'b (): Trait, // <- adding this bound is the change from #91068 +{ + s +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + //~^ ERROR cannot move out of `x` because it is borrowed + println!("{}", y); +} diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr new file mode 100644 index 000000000..fcbaa91d1 --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr @@ -0,0 +1,14 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/implied-bounds-unnorm-associated-type-4.rs:21:10 + | +LL | let y = f(&x, ()); + | -- borrow of `x` occurs here +LL | drop(x); + | ^ move out of `x` occurs here +LL | +LL | println!("{}", y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs new file mode 100644 index 000000000..2a9a6a8cc --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs @@ -0,0 +1,23 @@ +trait Trait<'a>: 'a { + type Type; +} + +// if the `T: 'a` bound gets implied we would probably get ub here again +impl<'a, T> Trait<'a> for T { + //~^ ERROR the parameter type `T` may not live long enough + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'b () as Trait<'a>>::Type) -> &'a str +where + &'b (): Trait<'a>, +{ + s +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + println!("{}", y); +} diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr new file mode 100644 index 000000000..458756a3d --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -0,0 +1,19 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:13 + | +LL | impl<'a, T> Trait<'a> for T { + | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:1:18 + | +LL | trait Trait<'a>: 'a { + | ^^ +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a> for T { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type.rs new file mode 100644 index 000000000..d58d25036 --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.rs @@ -0,0 +1,23 @@ +// check-fail +// See issue #91068. We check that the unnormalized associated types in +// function signatures are implied + +trait Trait { + type Type; +} + +impl Trait for T { + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { + s +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + //~^ ERROR cannot move out of `x` because it is borrowed + println!("{}", y); +} diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr new file mode 100644 index 000000000..e35f46e44 --- /dev/null +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr @@ -0,0 +1,14 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/implied-bounds-unnorm-associated-type.rs:20:10 + | +LL | let y = f(&x, ()); + | -- borrow of `x` occurs here +LL | drop(x); + | ^ move out of `x` occurs here +LL | +LL | println!("{}", y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/fn/issue-3044.rs b/tests/ui/fn/issue-3044.rs new file mode 100644 index 000000000..19bee733e --- /dev/null +++ b/tests/ui/fn/issue-3044.rs @@ -0,0 +1,6 @@ +fn main() { + let needlesArr: Vec = vec!['a', 'f']; + needlesArr.iter().fold(|x, y| { + //~^ ERROR this method takes 2 arguments but 1 argument was supplied + }); +} diff --git a/tests/ui/fn/issue-3044.stderr b/tests/ui/fn/issue-3044.stderr new file mode 100644 index 000000000..2690ad711 --- /dev/null +++ b/tests/ui/fn/issue-3044.stderr @@ -0,0 +1,21 @@ +error[E0061]: this method takes 2 arguments but 1 argument was supplied + --> $DIR/issue-3044.rs:3:23 + | +LL | needlesArr.iter().fold(|x, y| { + | _______________________^^^^- +LL | | +LL | | }); + | |______- an argument is missing + | +note: associated function defined here + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: provide the argument + | +LL ~ needlesArr.iter().fold(|x, y| { +LL + +LL ~ }, /* f */); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/fn/issue-3904.rs b/tests/ui/fn/issue-3904.rs new file mode 100644 index 000000000..7beb91a28 --- /dev/null +++ b/tests/ui/fn/issue-3904.rs @@ -0,0 +1,25 @@ +// run-pass +fn example_err(prog: &str, arg: &str) { + println!("{}: {}", prog, arg) +} + +fn exit(print: F, prog: &str, arg: &str) where F: FnOnce(&str, &str) { + print(prog, arg); +} + +struct X where F: FnOnce(&str, &str) { + err: F, +} + +impl X where F: FnOnce(&str, &str) { + pub fn boom(self) { + exit(self.err, "prog", "arg"); + } +} + +pub fn main(){ + let val = X { + err: example_err, + }; + val.boom(); +} diff --git a/tests/ui/fn/issue-80179.rs b/tests/ui/fn/issue-80179.rs new file mode 100644 index 000000000..35e39bebb --- /dev/null +++ b/tests/ui/fn/issue-80179.rs @@ -0,0 +1,27 @@ +// Functions with a type placeholder `_` as the return type should +// show a function pointer suggestion when given a function item +// and suggest how to return closures correctly from a function. +// This is a regression test of #80179 + +fn returns_i32() -> i32 { + 0 +} + +fn returns_fn_ptr() -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] +//~| NOTE not allowed in type signatures +//~| HELP replace with the correct return type +//~| SUGGESTION fn() -> i32 + returns_i32 +} + +fn returns_closure() -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] +//~| NOTE not allowed in type signatures +//~| HELP replace with an appropriate return type +//~| SUGGESTION impl Fn() -> i32 +//~| NOTE for more information on `Fn` traits and closure types + || 0 +} + +fn main() {} diff --git a/tests/ui/fn/issue-80179.stderr b/tests/ui/fn/issue-80179.stderr new file mode 100644 index 000000000..f5d6c44db --- /dev/null +++ b/tests/ui/fn/issue-80179.stderr @@ -0,0 +1,23 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-80179.rs:10:24 + | +LL | fn returns_fn_ptr() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `fn() -> i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-80179.rs:18:25 + | +LL | fn returns_closure() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Fn() -> i32` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/fn/keyword-order.rs b/tests/ui/fn/keyword-order.rs new file mode 100644 index 000000000..8a21db673 --- /dev/null +++ b/tests/ui/fn/keyword-order.rs @@ -0,0 +1,6 @@ +// edition:2018 + +default pub const async unsafe extern fn err() {} //~ ERROR `default` is not followed by an item +//~^ ERROR expected item, found keyword `pub` + +pub default const async unsafe extern fn ok() {} diff --git a/tests/ui/fn/keyword-order.stderr b/tests/ui/fn/keyword-order.stderr new file mode 100644 index 000000000..d3b140c85 --- /dev/null +++ b/tests/ui/fn/keyword-order.stderr @@ -0,0 +1,16 @@ +error: `default` is not followed by an item + --> $DIR/keyword-order.rs:3:1 + | +LL | default pub const async unsafe extern fn err() {} + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: expected item, found keyword `pub` + --> $DIR/keyword-order.rs:3:9 + | +LL | default pub const async unsafe extern fn err() {} + | ^^^ expected item + +error: aborting due to 2 previous errors + diff --git a/tests/ui/fn/nested-function-names-issue-8587.rs b/tests/ui/fn/nested-function-names-issue-8587.rs new file mode 100644 index 000000000..8fafd41d9 --- /dev/null +++ b/tests/ui/fn/nested-function-names-issue-8587.rs @@ -0,0 +1,42 @@ +// run-pass +// Make sure nested functions are separate, even if they have +// equal name. +// +// Issue #8587 + + +pub struct X; + +impl X { + fn f(&self) -> isize { + #[inline(never)] + fn inner() -> isize { + 0 + } + inner() + } + + fn g(&self) -> isize { + #[inline(never)] + fn inner_2() -> isize { + 1 + } + inner_2() + } + + fn h(&self) -> isize { + #[inline(never)] + fn inner() -> isize { + 2 + } + inner() + } +} + +pub fn main() { + let n = X; + assert_eq!(n.f(), 0); + assert_eq!(n.g(), 1); + // This test `h` used to fail. + assert_eq!(n.h(), 2); +} diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.rs b/tests/ui/fn/signature-error-reporting-under-verbose.rs new file mode 100644 index 000000000..d7a8c95e8 --- /dev/null +++ b/tests/ui/fn/signature-error-reporting-under-verbose.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zverbose + +fn foo(_: i32, _: i32) {} + +fn needs_ptr(_: fn(i32, u32)) {} +//~^ NOTE function defined here +//~| NOTE + +fn main() { + needs_ptr(foo); + //~^ ERROR mismatched types + //~| NOTE expected `u32`, found `i32` + //~| NOTE expected fn pointer `fn(i32, u32)` + //~| NOTE arguments to this function are incorrect +} diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.stderr b/tests/ui/fn/signature-error-reporting-under-verbose.stderr new file mode 100644 index 000000000..6260fc8dc --- /dev/null +++ b/tests/ui/fn/signature-error-reporting-under-verbose.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/signature-error-reporting-under-verbose.rs:10:15 + | +LL | needs_ptr(foo); + | --------- ^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `fn(i32, u32)` + found fn item `fn(i32, i32) {foo}` +note: function defined here + --> $DIR/signature-error-reporting-under-verbose.rs:5:4 + | +LL | fn needs_ptr(_: fn(i32, u32)) {} + | ^^^^^^^^^ --------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs new file mode 100644 index 000000000..33daa1ea0 --- /dev/null +++ b/tests/ui/fn/suggest-return-closure.rs @@ -0,0 +1,34 @@ +fn fn_once() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl FnOnce() + //~| NOTE for more information on `Fn` traits and closure types + let x = String::new(); + || { + drop(x); + } +} + +fn fn_mut() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl FnMut(char) + //~| NOTE for more information on `Fn` traits and closure types + let x = String::new(); + |c| { + x.push(c); + } +} + +fn fun() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Fn() -> i32 + //~| NOTE for more information on `Fn` traits and closure types + || 1i32 +} + +fn main() {} diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr new file mode 100644 index 000000000..341044469 --- /dev/null +++ b/tests/ui/fn/suggest-return-closure.stderr @@ -0,0 +1,36 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:1:17 + | +LL | fn fn_once() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl FnOnce()` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:13:16 + | +LL | fn fn_mut() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl FnMut(char)` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:25:13 + | +LL | fn fun() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Fn() -> i32` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/fn/suggest-return-future.rs b/tests/ui/fn/suggest-return-future.rs new file mode 100644 index 000000000..750740d94 --- /dev/null +++ b/tests/ui/fn/suggest-return-future.rs @@ -0,0 +1,23 @@ +// edition: 2021 + +async fn a() -> i32 { + 0 +} + +fn foo() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Future + a() +} + +fn bar() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Future + async { a().await } +} + +fn main() {} diff --git a/tests/ui/fn/suggest-return-future.stderr b/tests/ui/fn/suggest-return-future.stderr new file mode 100644 index 000000000..a4c8b5d8c --- /dev/null +++ b/tests/ui/fn/suggest-return-future.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-future.rs:7:13 + | +LL | fn foo() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Future` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-future.rs:15:13 + | +LL | fn bar() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Future` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/for-loop-while/auto-loop.rs b/tests/ui/for-loop-while/auto-loop.rs new file mode 100644 index 000000000..f02ac43c7 --- /dev/null +++ b/tests/ui/for-loop-while/auto-loop.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let mut sum = 0; + let xs = vec![1, 2, 3, 4, 5]; + for x in &xs { + sum += *x; + } + assert_eq!(sum, 15); +} diff --git a/tests/ui/for-loop-while/break-outside-loop.rs b/tests/ui/for-loop-while/break-outside-loop.rs new file mode 100644 index 000000000..26769b30d --- /dev/null +++ b/tests/ui/for-loop-while/break-outside-loop.rs @@ -0,0 +1,35 @@ +struct Foo { + t: String +} + +fn cond() -> bool { true } + +fn foo(_: F) where F: FnOnce() {} + +fn main() { + let pth = break; //~ ERROR: `break` outside of a loop + if cond() { continue } //~ ERROR: `continue` outside of a loop + + while cond() { + if cond() { break } + if cond() { continue } + foo(|| { + if cond() { break } //~ ERROR: `break` inside of a closure + if cond() { continue } //~ ERROR: `continue` inside of a closure + }) + } + + let rs: Foo = Foo{t: pth}; + + let unconstrained = break; //~ ERROR: `break` outside of a loop + + // This used to ICE because `target_id` passed to `check_expr_break` would be the closure and + // not the `loop`, which failed in the call to `find_breakable`. (#65383) + 'lab: loop { + || { + break 'lab; + //~^ ERROR use of unreachable label `'lab` + //~| ERROR `break` inside of a closure + }; + } +} diff --git a/tests/ui/for-loop-while/break-outside-loop.stderr b/tests/ui/for-loop-while/break-outside-loop.stderr new file mode 100644 index 000000000..9092f34df --- /dev/null +++ b/tests/ui/for-loop-while/break-outside-loop.stderr @@ -0,0 +1,58 @@ +error[E0767]: use of unreachable label `'lab` + --> $DIR/break-outside-loop.rs:30:19 + | +LL | 'lab: loop { + | ---- unreachable label defined here +LL | || { +LL | break 'lab; + | ^^^^ unreachable label `'lab` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-outside-loop.rs:10:15 + | +LL | let pth = break; + | ^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `continue` outside of a loop + --> $DIR/break-outside-loop.rs:11:17 + | +LL | if cond() { continue } + | ^^^^^^^^ cannot `continue` outside of a loop + +error[E0267]: `break` inside of a closure + --> $DIR/break-outside-loop.rs:17:25 + | +LL | foo(|| { + | -- enclosing closure +LL | if cond() { break } + | ^^^^^ cannot `break` inside of a closure + +error[E0267]: `continue` inside of a closure + --> $DIR/break-outside-loop.rs:18:25 + | +LL | foo(|| { + | -- enclosing closure +LL | if cond() { break } +LL | if cond() { continue } + | ^^^^^^^^ cannot `continue` inside of a closure + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-outside-loop.rs:24:25 + | +LL | let unconstrained = break; + | ^^^^^ cannot `break` outside of a loop or labeled block + +error[E0267]: `break` inside of a closure + --> $DIR/break-outside-loop.rs:30:13 + | +LL | || { + | -- enclosing closure +LL | break 'lab; + | ^^^^^^^^^^ cannot `break` inside of a closure + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0267, E0268, E0767. +For more information about an error, try `rustc --explain E0267`. diff --git a/tests/ui/for-loop-while/break-value.rs b/tests/ui/for-loop-while/break-value.rs new file mode 100644 index 000000000..9fc49fa81 --- /dev/null +++ b/tests/ui/for-loop-while/break-value.rs @@ -0,0 +1,7 @@ +// run-pass +#![allow(unreachable_code)] +// pretty-expanded FIXME #23616 + +fn int_id(x: isize) -> isize { return x; } + +pub fn main() { loop { int_id(break); } } diff --git a/tests/ui/for-loop-while/break-while-condition.rs b/tests/ui/for-loop-while/break-while-condition.rs new file mode 100644 index 000000000..6064e6ab0 --- /dev/null +++ b/tests/ui/for-loop-while/break-while-condition.rs @@ -0,0 +1,29 @@ +#![feature(never_type)] + +fn main() { + // The `if false` expressions are simply to + // make sure we don't avoid checking everything + // simply because a few expressions are unreachable. + + if false { + let _: ! = { //~ ERROR mismatched types + 'a: while break 'a {}; + }; + } + + if false { + let _: ! = { + while false { //~ ERROR mismatched types + break + } + }; + } + + if false { + let _: ! = { + while false { //~ ERROR mismatched types + return + } + }; + } +} diff --git a/tests/ui/for-loop-while/break-while-condition.stderr b/tests/ui/for-loop-while/break-while-condition.stderr new file mode 100644 index 000000000..e79f6a75f --- /dev/null +++ b/tests/ui/for-loop-while/break-while-condition.stderr @@ -0,0 +1,45 @@ +error[E0308]: mismatched types + --> $DIR/break-while-condition.rs:9:20 + | +LL | let _: ! = { + | ____________________^ +LL | | 'a: while break 'a {}; +LL | | }; + | |_________^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/break-while-condition.rs:16:13 + | +LL | / while false { +LL | | break +LL | | } + | |_____________^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/break-while-condition.rs:24:13 + | +LL | / while false { +LL | | return +LL | | } + | |_____________^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` +note: the function expects a value to always be returned, but loops might run zero times + --> $DIR/break-while-condition.rs:24:13 + | +LL | while false { + | ^^^^^^^^^^^ this might have zero elements to iterate on +LL | return + | ------ if the loop doesn't execute, this value would never get returned + = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/for-loop-while/break.rs b/tests/ui/for-loop-while/break.rs new file mode 100644 index 000000000..427b1b7a0 --- /dev/null +++ b/tests/ui/for-loop-while/break.rs @@ -0,0 +1,25 @@ +// run-pass + +pub fn main() { + let mut i = 0; + while i < 20 { i += 1; if i == 10 { break; } } + assert_eq!(i, 10); + loop { i += 1; if i == 20 { break; } } + assert_eq!(i, 20); + let xs = [1, 2, 3, 4, 5, 6]; + for x in &xs { + if *x == 3 { break; } assert!((*x <= 3)); + } + i = 0; + while i < 10 { i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); } + i = 0; + loop { + i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); + if i >= 10 { break; } + } + let ys = vec![1, 2, 3, 4, 5, 6]; + for x in &ys { + if *x % 2 == 0 { continue; } + assert!((*x % 2 != 0)); + } +} diff --git a/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs b/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs new file mode 100644 index 000000000..afc77355a --- /dev/null +++ b/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs @@ -0,0 +1,41 @@ +// run-pass +// This test verifies that temporaries created for `while`'s and `if` +// conditions are dropped after the condition is evaluated. + +struct Temporary; + +static mut DROPPED: isize = 0; + +impl Drop for Temporary { + fn drop(&mut self) { + unsafe { DROPPED += 1; } + } +} + +impl Temporary { + fn do_stuff(&self) -> bool {true} +} + +fn borrow() -> Box { Box::new(Temporary) } + + +pub fn main() { + let mut i = 0; + + // This loop's condition + // should call `Temporary`'s + // `drop` 6 times. + while borrow().do_stuff() { + i += 1; + unsafe { assert_eq!(DROPPED, i) } + if i > 5 { + break; + } + } + + // This if condition should + // call it 1 time + if borrow().do_stuff() { + unsafe { assert_eq!(DROPPED, i + 1) } + } +} diff --git a/tests/ui/for-loop-while/for-destruct.rs b/tests/ui/for-loop-while/for-destruct.rs new file mode 100644 index 000000000..7ca8d4ded --- /dev/null +++ b/tests/ui/for-loop-while/for-destruct.rs @@ -0,0 +1,9 @@ +// run-pass + +struct Pair { x: isize, y: isize } + +pub fn main() { + for elt in &(vec![Pair {x: 10, y: 20}, Pair {x: 30, y: 0}]) { + assert_eq!(elt.x + elt.y, 30); + } +} diff --git a/tests/ui/for-loop-while/for-loop-goofiness.rs b/tests/ui/for-loop-while/for-loop-goofiness.rs new file mode 100644 index 000000000..872ab168b --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-goofiness.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +enum BogusOption { + None, + Some(T), +} + +type Iterator = isize; + +pub fn main() { + let x = [ 3, 3, 3 ]; + for i in &x { + assert_eq!(*i, 3); + } +} diff --git a/tests/ui/for-loop-while/for-loop-has-unit-body.rs b/tests/ui/for-loop-while/for-loop-has-unit-body.rs new file mode 100644 index 000000000..eba385461 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-has-unit-body.rs @@ -0,0 +1,13 @@ +// run-pass +fn main() { + // Check that the tail statement in the body unifies with something + for _ in 0..3 { + // `()` is fine to zero-initialize as it is zero sized and inhabited. + unsafe { std::mem::zeroed() } + } + + // Check that the tail statement in the body can be unit + for _ in 0..3 { + () + } +} diff --git a/tests/ui/for-loop-while/for-loop-into-iterator.rs b/tests/ui/for-loop-while/for-loop-into-iterator.rs new file mode 100644 index 000000000..199d4ddb2 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-into-iterator.rs @@ -0,0 +1,19 @@ +// run-pass +// Test that for loops can do what RFC #235 claims + + +fn main() { + let mut v = vec![1]; + + for x in &v { + assert_eq!(x, &1); + } + + for x in &mut v { + assert_eq!(x, &mut 1); + } + + for x in v { + assert_eq!(x, 1); + } +} diff --git a/tests/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs b/tests/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs new file mode 100644 index 000000000..6a38764a1 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-lifetime-of-unbound-values.rs @@ -0,0 +1,34 @@ +// run-pass +// Test when destructors run in a for loop. The intention is +// that the value for each iteration is dropped *after* the loop +// body has executed. This is true even when the value is assigned +// to a `_` pattern (and hence ignored). + +use std::cell::Cell; + +struct Flag<'a>(&'a Cell); + +impl<'a> Drop for Flag<'a> { + fn drop(&mut self) { + self.0.set(false) + } +} + +fn main() { + let alive2 = Cell::new(true); + for _i in std::iter::once(Flag(&alive2)) { + // The Flag value should be alive in the for loop body + assert_eq!(alive2.get(), true); + } + // The Flag value should be dead outside of the loop + assert_eq!(alive2.get(), false); + + let alive = Cell::new(true); + for _ in std::iter::once(Flag(&alive)) { + // The Flag value should be alive in the for loop body even if it wasn't + // bound by the for loop + assert_eq!(alive.get(), true); + } + // The Flag value should be dead outside of the loop + assert_eq!(alive.get(), false); +} diff --git a/tests/ui/for-loop-while/for-loop-macro.rs b/tests/ui/for-loop-while/for-loop-macro.rs new file mode 100644 index 000000000..5abccd2a1 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-macro.rs @@ -0,0 +1,11 @@ +// run-pass +macro_rules! var { + ( $name:ident ) => ( $name ); +} + +pub fn main() { + let x = [ 3, 3, 3 ]; + for var!(i) in &x { + assert_eq!(*i, 3); + } +} diff --git a/tests/ui/for-loop-while/for-loop-mut-ref-element.rs b/tests/ui/for-loop-while/for-loop-mut-ref-element.rs new file mode 100644 index 000000000..a3d82ace9 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-mut-ref-element.rs @@ -0,0 +1,6 @@ +// run-pass +// Tests that for loops can bind elements as mutable references + +fn main() { + for ref mut _a in std::iter::once(true) {} +} diff --git a/tests/ui/for-loop-while/for-loop-no-std.rs b/tests/ui/for-loop-while/for-loop-no-std.rs new file mode 100644 index 000000000..65a33c5f1 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-no-std.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_imports)] +#![feature(lang_items, start)] +#![no_std] + +extern crate std as other; + +#[macro_use] extern crate alloc; + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + for _ in [1,2,3].iter() { } + 0 +} diff --git a/tests/ui/for-loop-while/for-loop-panic.rs b/tests/ui/for-loop-while/for-loop-panic.rs new file mode 100644 index 000000000..ac607d6d7 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-panic.rs @@ -0,0 +1,4 @@ +// run-pass + + +pub fn main() { let x: Vec = Vec::new(); for _ in &x { panic!("moop"); } } diff --git a/tests/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs b/tests/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs new file mode 100644 index 000000000..a1e9b1ed8 --- /dev/null +++ b/tests/ui/for-loop-while/for-loop-unconstrained-element-type-i32-fallback.rs @@ -0,0 +1,11 @@ +// run-pass +// Test that the type of `sum` falls back to `i32` here, +// and that the for loop desugaring doesn't interfere with +// that. + +fn main() { + let mut sum = 0; + for i in Vec::new() { + sum += &i; + } +} diff --git a/tests/ui/for-loop-while/foreach-external-iterators-break.rs b/tests/ui/for-loop-while/foreach-external-iterators-break.rs new file mode 100644 index 000000000..7de6a4f8a --- /dev/null +++ b/tests/ui/for-loop-while/foreach-external-iterators-break.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let mut y = 0; + for i in &x[..] { + if y > 10 { + break; + } + y += *i; + } + assert_eq!(y, 11); +} diff --git a/tests/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs b/tests/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs new file mode 100644 index 000000000..5d690807e --- /dev/null +++ b/tests/ui/for-loop-while/foreach-external-iterators-hashmap-break-restart.rs @@ -0,0 +1,33 @@ +// run-pass + +use std::collections::HashMap; + +// This is a fancy one: it uses an external iterator established +// outside the loop, breaks, then _picks back up_ and continues +// iterating with it. + +pub fn main() { + let mut h = HashMap::new(); + let kvs = [(1, 10), (2, 20), (3, 30)]; + for &(k,v) in &kvs { + h.insert(k,v); + } + let mut x = 0; + let mut y = 0; + + let mut i = h.iter(); + + for (&k,&v) in i.by_ref() { + x += k; + y += v; + break; + } + + for (&k,&v) in i { + x += k; + y += v; + } + + assert_eq!(x, 6); + assert_eq!(y, 60); +} diff --git a/tests/ui/for-loop-while/foreach-external-iterators-hashmap.rs b/tests/ui/for-loop-while/foreach-external-iterators-hashmap.rs new file mode 100644 index 000000000..9f2ca05cd --- /dev/null +++ b/tests/ui/for-loop-while/foreach-external-iterators-hashmap.rs @@ -0,0 +1,19 @@ +// run-pass + +use std::collections::HashMap; + +pub fn main() { + let mut h = HashMap::new(); + let kvs = [(1, 10), (2, 20), (3, 30)]; + for &(k,v) in &kvs { + h.insert(k,v); + } + let mut x = 0; + let mut y = 0; + for (&k,&v) in &h { + x += k; + y += v; + } + assert_eq!(x, 6); + assert_eq!(y, 60); +} diff --git a/tests/ui/for-loop-while/foreach-external-iterators-loop.rs b/tests/ui/for-loop-while/foreach-external-iterators-loop.rs new file mode 100644 index 000000000..78af195bc --- /dev/null +++ b/tests/ui/for-loop-while/foreach-external-iterators-loop.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let mut y = 0; + for (n,i) in x.iter().enumerate() { + if n < 10 { + continue; + } + y += *i; + } + assert_eq!(y, 90); +} diff --git a/tests/ui/for-loop-while/foreach-external-iterators-nested.rs b/tests/ui/for-loop-while/foreach-external-iterators-nested.rs new file mode 100644 index 000000000..8a95f160a --- /dev/null +++ b/tests/ui/for-loop-while/foreach-external-iterators-nested.rs @@ -0,0 +1,15 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let y = [2; 100]; + let mut p = 0; + let mut q = 0; + for i in &x[..] { + for j in &y[..] { + p += *j; + } + q += *i + p; + } + assert_eq!(q, 1010100); +} diff --git a/tests/ui/for-loop-while/foreach-external-iterators.rs b/tests/ui/for-loop-while/foreach-external-iterators.rs new file mode 100644 index 000000000..24ecfe9b6 --- /dev/null +++ b/tests/ui/for-loop-while/foreach-external-iterators.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let x = [1; 100]; + let mut y = 0; + for i in &x[..] { + y += *i + } + assert_eq!(y, 100); +} diff --git a/tests/ui/for-loop-while/foreach-nested.rs b/tests/ui/for-loop-while/foreach-nested.rs new file mode 100644 index 000000000..bb6edbc07 --- /dev/null +++ b/tests/ui/for-loop-while/foreach-nested.rs @@ -0,0 +1,16 @@ +// run-pass + + +fn two(mut it: F) where F: FnMut(isize) { it(0); it(1); } + +pub fn main() { + let mut a: Vec = vec![-1, -1, -1, -1]; + let mut p: isize = 0; + two(|i| { + two(|j| { a[p as usize] = 10 * i + j; p += 1; }) + }); + assert_eq!(a[0], 0); + assert_eq!(a[1], 1); + assert_eq!(a[2], 10); + assert_eq!(a[3], 11); +} diff --git a/tests/ui/for-loop-while/foreach-put-structured.rs b/tests/ui/for-loop-while/foreach-put-structured.rs new file mode 100644 index 000000000..3a47fcf34 --- /dev/null +++ b/tests/ui/for-loop-while/foreach-put-structured.rs @@ -0,0 +1,22 @@ +// run-pass + + +fn pairs(mut it: F) where F: FnMut((isize, isize)) { + let mut i: isize = 0; + let mut j: isize = 0; + while i < 10 { it((i, j)); i += 1; j += i; } +} + +pub fn main() { + let mut i: isize = 10; + let mut j: isize = 0; + pairs(|p| { + let (_0, _1) = p; + println!("{}", _0); + println!("{}", _1); + assert_eq!(_0 + 10, i); + i += 1; + j = _1; + }); + assert_eq!(j, 45); +} diff --git a/tests/ui/for-loop-while/foreach-simple-outer-slot.rs b/tests/ui/for-loop-while/foreach-simple-outer-slot.rs new file mode 100644 index 000000000..a8d42a789 --- /dev/null +++ b/tests/ui/for-loop-while/foreach-simple-outer-slot.rs @@ -0,0 +1,16 @@ +// run-pass + + + +pub fn main() { + let mut sum: isize = 0; + first_ten(|i| { println!("main"); println!("{}", i); sum = sum + i; }); + println!("sum"); + println!("{}", sum); + assert_eq!(sum, 45); +} + +fn first_ten(mut it: F) where F: FnMut(isize) { + let mut i: isize = 0; + while i < 10 { println!("first_ten"); it(i); i = i + 1; } +} diff --git a/tests/ui/for-loop-while/issue-2216.rs b/tests/ui/for-loop-while/issue-2216.rs new file mode 100644 index 000000000..ad5410742 --- /dev/null +++ b/tests/ui/for-loop-while/issue-2216.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(unreachable_code)] +pub fn main() { + let mut x = 0; + + 'foo: loop { + 'bar: loop { + loop { + if 1 == 2 { + break 'foo; + } + else { + break 'bar; + } + } + continue 'foo; + } + x = 42; + break; + } + + println!("{}", x); + assert_eq!(x, 42); +} diff --git a/tests/ui/for-loop-while/issue-51345.rs b/tests/ui/for-loop-while/issue-51345.rs new file mode 100644 index 000000000..15571e8bf --- /dev/null +++ b/tests/ui/for-loop-while/issue-51345.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unreachable_code)] + +fn main() { + let mut v = Vec::new(); + + loop { v.push(break) } +} diff --git a/tests/ui/for-loop-while/issue-69841.rs b/tests/ui/for-loop-while/issue-69841.rs new file mode 100644 index 000000000..1aca16ca8 --- /dev/null +++ b/tests/ui/for-loop-while/issue-69841.rs @@ -0,0 +1,31 @@ +// This is a regression test for issue rust-lang/rust#69841, which exposed an +// LLVM bug which needed a fix to be backported. + +// run-pass +// no-system-llvm + +fn main() { + let buffer = [49u8, 10]; + let mut a : u64 = 0; + 'read: loop { + for c in &buffer { + match c { + 48..=57 => { + a*= 10; + a+= *c as u64 - 48; + } + 10 => { + break 'read; + } + _ => { + unsafe { std::hint::unreachable_unchecked() }; + } + } + } + } + if a == 1 { + println!("What did you expect?"); + } else { + panic!("this should be unreachable."); + } +} diff --git a/tests/ui/for-loop-while/label_break_value.rs b/tests/ui/for-loop-while/label_break_value.rs new file mode 100644 index 000000000..10992c505 --- /dev/null +++ b/tests/ui/for-loop-while/label_break_value.rs @@ -0,0 +1,166 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] + +// Test control flow to follow label_break_value semantics +fn label_break(a: bool, b: bool) -> u32 { + let mut v = 0; + 'b: { + v = 1; + if a { + break 'b; + } + v = 2; + if b { + break 'b; + } + v = 3; + } + return v; +} + +// Test that values can be returned +fn break_value(a: bool, b: bool) -> u32 { + let result = 'block: { + if a { break 'block 1; } + if b { break 'block 2; } + 3 + }; + result +} + +// Test nesting of labeled blocks +// here we only check that it compiles +fn label_break_nested() { + 'b: { + println!("hi"); + if false { + break 'b; + } + 'c: { + if false { + break 'b; + } + break 'c; + } + println!("hello"); + if true { + break 'b; + } + } +} + +// Tests for mixing labeled blocks with loop constructs +// This function should be the identity function +fn label_break_mixed(v: u32) -> u32 { + let mut r = 0; + 'b: { + // Unlabeled break still works + // (only crossing boundaries is an error) + loop { + break; + } + if v == 0 { + break 'b; + } + // Labeled breaking an inner loop still works + 'c: loop { + if r == 1 { + break 'c; + } + r += 1; + } + assert_eq!(r, 1); + if v == 1 { + break 'b; + } + // Labeled breaking an outer loop still works + 'd: loop { + { + if v == r { + break 'b; + } + if r == 5 { + break 'd; + } + r += 1; + } + } + assert_eq!(r, 5); + assert!(v > r); + // Here we test return from inside a labeled block + return v; + } + r +} + +fn label_break_match(c: u8, xe: u8, ye: i8) { + let mut x = 0; + let y = 'a: { + match c { + 0 => break 'a 0, + v if { if v % 2 == 0 { break 'a 1; }; v % 3 == 0 } => { x += 1; }, + v if { 'b: { break 'b v == 5; } } => { x = 41; }, + _ => 'b: { + break 'b (); + }, + } + x += 1; + -1 + }; + + assert_eq!(x, xe); + assert_eq!(y, ye); +} + +#[allow(unused_labels)] +fn label_break_macro() { + macro_rules! mac1 { + ($target:lifetime, $val:expr) => { + break $target $val; + }; + } + let x: u8 = 'a: { + 'b: { + mac1!('b, 1); + }; + 0 + }; + assert_eq!(x, 0); + let x: u8 = 'a: { + 'b: { + if true { + mac1!('a, 1); + } + }; + 0 + }; + assert_eq!(x, 1); +} + +pub fn main() { + assert_eq!(label_break(true, false), 1); + assert_eq!(label_break(false, true), 2); + assert_eq!(label_break(false, false), 3); + + assert_eq!(break_value(true, false), 1); + assert_eq!(break_value(false, true), 2); + assert_eq!(break_value(false, false), 3); + + assert_eq!(label_break_mixed(0), 0); + assert_eq!(label_break_mixed(1), 1); + assert_eq!(label_break_mixed(2), 2); + assert_eq!(label_break_mixed(3), 3); + assert_eq!(label_break_mixed(4), 4); + assert_eq!(label_break_mixed(5), 5); + assert_eq!(label_break_mixed(6), 6); + + label_break_match(0, 0, 0); + label_break_match(1, 1, -1); + label_break_match(2, 0, 1); + label_break_match(3, 2, -1); + label_break_match(5, 42, -1); + label_break_match(7, 1, -1); + + label_break_macro(); +} diff --git a/tests/ui/for-loop-while/label_break_value_invalid.rs b/tests/ui/for-loop-while/label_break_value_invalid.rs new file mode 100644 index 000000000..fcf2e0f29 --- /dev/null +++ b/tests/ui/for-loop-while/label_break_value_invalid.rs @@ -0,0 +1,35 @@ +#![crate_type = "lib"] + +fn lbv_macro_test_hygiene_respected() { + macro_rules! mac2 { + ($val:expr) => { + break 'a $val; //~ ERROR undeclared label `'a` [E0426] + }; + } + let x: u8 = 'a: { + 'b: { + if true { + mac2!(2); + } + }; + 0 + }; + assert_eq!(x, 2); + + macro_rules! mac3 { + ($val:expr) => { + 'a: { + $val + } + }; + } + let x: u8 = mac3!('b: { + if true { + break 'a 3; //~ ERROR undeclared label `'a` [E0426] + } + 0 + }); + assert_eq!(x, 3); + let x: u8 = mac3!(break 'a 4); //~ ERROR undeclared label `'a` [E0426] + assert_eq!(x, 4); +} diff --git a/tests/ui/for-loop-while/label_break_value_invalid.stderr b/tests/ui/for-loop-while/label_break_value_invalid.stderr new file mode 100644 index 000000000..f6999c4ab --- /dev/null +++ b/tests/ui/for-loop-while/label_break_value_invalid.stderr @@ -0,0 +1,32 @@ +error[E0426]: use of undeclared label `'a` + --> $DIR/label_break_value_invalid.rs:6:19 + | +LL | break 'a $val; + | ^^ undeclared label `'a` +... +LL | mac2!(2); + | -------- in this macro invocation + | + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0426]: use of undeclared label `'a` + --> $DIR/label_break_value_invalid.rs:28:19 + | +LL | let x: u8 = mac3!('b: { + | -- a label with a similar name is reachable +LL | if true { +LL | break 'a 3; + | ^^ + | | + | undeclared label `'a` + | help: try using similarly named label: `'b` + +error[E0426]: use of undeclared label `'a` + --> $DIR/label_break_value_invalid.rs:33:29 + | +LL | let x: u8 = mac3!(break 'a 4); + | ^^ undeclared label `'a` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/for-loop-while/labeled-break.rs b/tests/ui/for-loop-while/labeled-break.rs new file mode 100644 index 000000000..4dacc5757 --- /dev/null +++ b/tests/ui/for-loop-while/labeled-break.rs @@ -0,0 +1,22 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + 'foo: loop { + loop { + break 'foo; + } + } + + 'bar: for _ in 0..100 { + loop { + break 'bar; + } + } + + 'foobar: while 1 + 1 == 2 { + loop { + break 'foobar; + } + } +} diff --git a/tests/ui/for-loop-while/linear-for-loop.rs b/tests/ui/for-loop-while/linear-for-loop.rs new file mode 100644 index 000000000..3c573db1d --- /dev/null +++ b/tests/ui/for-loop-while/linear-for-loop.rs @@ -0,0 +1,23 @@ +// run-pass +pub fn main() { + let x = vec![1, 2, 3]; + let mut y = 0; + for i in &x { println!("{}", *i); y += *i; } + println!("{}", y); + assert_eq!(y, 6); + let s = "hello there".to_string(); + let mut i: isize = 0; + for c in s.bytes() { + if i == 0 { assert_eq!(c, 'h' as u8); } + if i == 1 { assert_eq!(c, 'e' as u8); } + if i == 2 { assert_eq!(c, 'l' as u8); } + if i == 3 { assert_eq!(c, 'l' as u8); } + if i == 4 { assert_eq!(c, 'o' as u8); } + // ... + + i += 1; + println!("{}", i); + println!("{}", c); + } + assert_eq!(i, 11); +} diff --git a/tests/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs b/tests/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs new file mode 100644 index 000000000..11b697165 --- /dev/null +++ b/tests/ui/for-loop-while/liveness-assign-imm-local-after-loop.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 + +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn test(_cond: bool) { + let v: isize; + v = 1; + loop { } // loop never terminates, so no error is reported + v = 2; +} + +pub fn main() { + // note: don't call test()... :) +} diff --git a/tests/ui/for-loop-while/liveness-loop-break.rs b/tests/ui/for-loop-while/liveness-loop-break.rs new file mode 100644 index 000000000..60a63bccb --- /dev/null +++ b/tests/ui/for-loop-while/liveness-loop-break.rs @@ -0,0 +1,13 @@ +// run-pass +fn test() { + let v; + loop { + v = 3; + break; + } + println!("{}", v); +} + +pub fn main() { + test(); +} diff --git a/tests/ui/for-loop-while/liveness-move-in-loop.rs b/tests/ui/for-loop-while/liveness-move-in-loop.rs new file mode 100644 index 000000000..ce73d6335 --- /dev/null +++ b/tests/ui/for-loop-while/liveness-move-in-loop.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +fn take(x: isize) -> isize {x} + +fn the_loop() { + let mut list = Vec::new(); + loop { + let x = 5; + if x > 3 { + list.push(take(x)); + } else { + break; + } + } +} + +pub fn main() {} diff --git a/tests/ui/for-loop-while/long-while.rs b/tests/ui/for-loop-while/long-while.rs new file mode 100644 index 000000000..529cca7b7 --- /dev/null +++ b/tests/ui/for-loop-while/long-while.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +pub fn main() { + let mut i: isize = 0; + while i < 1000000 { + i += 1; + let x = 3; + } +} diff --git a/tests/ui/for-loop-while/loop-break-cont-1.rs b/tests/ui/for-loop-while/loop-break-cont-1.rs new file mode 100644 index 000000000..f207746f0 --- /dev/null +++ b/tests/ui/for-loop-while/loop-break-cont-1.rs @@ -0,0 +1,9 @@ +// run-pass + +pub fn main() { + let _i = 0_usize; + loop { + break; + } + assert!(true); +} diff --git a/tests/ui/for-loop-while/loop-break-cont.rs b/tests/ui/for-loop-while/loop-break-cont.rs new file mode 100644 index 000000000..92d5a32c6 --- /dev/null +++ b/tests/ui/for-loop-while/loop-break-cont.rs @@ -0,0 +1,39 @@ +// run-pass +pub fn main() { + let mut i = 0_usize; + loop { + println!("a"); + i += 1_usize; + if i == 10_usize { + break; + } + } + assert_eq!(i, 10_usize); + let mut is_even = false; + loop { + if i == 21_usize { + break; + } + println!("b"); + is_even = false; + i += 1_usize; + if i % 2_usize != 0_usize { + continue; + } + is_even = true; + } + assert!(!is_even); + loop { + println!("c"); + if i == 22_usize { + break; + } + is_even = false; + i += 1_usize; + if i % 2_usize != 0_usize { + continue; + } + is_even = true; + } + assert!(is_even); +} diff --git a/tests/ui/for-loop-while/loop-break-value.rs b/tests/ui/for-loop-while/loop-break-value.rs new file mode 100644 index 000000000..d7209fc4d --- /dev/null +++ b/tests/ui/for-loop-while/loop-break-value.rs @@ -0,0 +1,139 @@ +// run-pass + +#![allow(unreachable_code)] +#![feature(never_type)] + +#[allow(unused)] +fn never_returns() { + loop { + break loop {}; + } +} + +pub fn main() { + let value = 'outer: loop { + if 1 == 1 { + break 13; + } else { + let _never: ! = loop { + break loop { + break 'outer panic!(); + } + }; + } + }; + assert_eq!(value, 13); + + let x = [1, 3u32, 5]; + let y = [17]; + let z = []; + let coerced: &[_] = loop { + match 2 { + 1 => break &x, + 2 => break &y, + 3 => break &z, + _ => (), + } + }; + assert_eq!(coerced, &[17u32]); + + let trait_unified = loop { + break if true { + break Default::default() + } else { + break [13, 14] + }; + }; + assert_eq!(trait_unified, [0, 0]); + + let trait_unified_2 = loop { + if false { + break [String::from("Hello")] + } else { + break Default::default() + }; + }; + assert_eq!(trait_unified_2, [""]); + + let trait_unified_3 = loop { + break if false { + break [String::from("Hello")] + } else { + ["Yes".into()] + }; + }; + assert_eq!(trait_unified_3, ["Yes"]); + + let regular_break = loop { + if true { + break; + } else { + break break Default::default(); + } + }; + assert_eq!(regular_break, ()); + + let regular_break_2 = loop { + if true { + break Default::default(); + } else { + break; + } + }; + assert_eq!(regular_break_2, ()); + + let regular_break_3 = loop { + break if true { + Default::default() + } else { + break; + } + }; + assert_eq!(regular_break_3, ()); + + let regular_break_4 = loop { + break (); + break; + }; + assert_eq!(regular_break_4, ()); + + let regular_break_5 = loop { + break; + break (); + }; + assert_eq!(regular_break_5, ()); + + let nested_break_value = 'outer2: loop { + let _a: u32 = 'inner: loop { + if true { + break 'outer2 "hello"; + } else { + break 'inner 17; + } + }; + panic!(); + }; + assert_eq!(nested_break_value, "hello"); + + let break_from_while_cond = loop { + 'inner_loop: while break 'inner_loop { + panic!(); + } + break 123; + }; + assert_eq!(break_from_while_cond, 123); + + let break_from_while_to_outer = 'outer_loop: loop { + while break 'outer_loop 567 { + panic!("from_inner"); + } + panic!("from outer"); + }; + assert_eq!(break_from_while_to_outer, 567); + + let rust = true; + let value = loop { + break rust; + }; + assert!(value); +} diff --git a/tests/ui/for-loop-while/loop-diverges.rs b/tests/ui/for-loop-while/loop-diverges.rs new file mode 100644 index 000000000..f657bf9e0 --- /dev/null +++ b/tests/ui/for-loop-while/loop-diverges.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_parens)] +// pretty-expanded FIXME #23616 + +/* Make sure a loop{} can be the tailexpr in the body +of a diverging function */ + +fn forever() -> ! { + loop{} +} + +pub fn main() { + if (1 == 2) { forever(); } +} diff --git a/tests/ui/for-loop-while/loop-label-shadowing.rs b/tests/ui/for-loop-while/loop-label-shadowing.rs new file mode 100644 index 000000000..9bedde67b --- /dev/null +++ b/tests/ui/for-loop-while/loop-label-shadowing.rs @@ -0,0 +1,12 @@ +// run-pass +// Issue #12512. + +// pretty-expanded FIXME #23616 + +fn main() { + let mut foo = Vec::new(); + #[allow(unused_labels)] + 'foo: for i in &[1, 2, 3] { + foo.push(*i); + } +} diff --git a/tests/ui/for-loop-while/loop-labeled-break-value.rs b/tests/ui/for-loop-while/loop-labeled-break-value.rs new file mode 100644 index 000000000..cc8f82698 --- /dev/null +++ b/tests/ui/for-loop-while/loop-labeled-break-value.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + 'outer: loop { + let _: i32 = loop { break 'outer }; + } + 'outer2: loop { + let _: i32 = loop { loop { break 'outer2 } }; + } +} diff --git a/tests/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs b/tests/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs new file mode 100644 index 000000000..1b5db2012 --- /dev/null +++ b/tests/ui/for-loop-while/loop-no-reinit-needed-post-bot.rs @@ -0,0 +1,34 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct S; +// Ensure S is moved, not copied, on assignment. +impl Drop for S { fn drop(&mut self) { } } + +// user-defined function "returning" bottom (i.e., no return at all). +fn my_panic() -> ! { loop {} } + +pub fn step(f: bool) { + let mut g = S; + let mut i = 0; + loop + { + if i > 10 { break; } else { i += 1; } + + let _g = g; + + if f { + // re-initialize g, but only before restarting loop. + g = S; + continue; + } + + my_panic(); + + // we never get here, so we do not need to re-initialize g. + } +} + +pub fn main() { + step(true); +} diff --git a/tests/ui/for-loop-while/loop-scope.rs b/tests/ui/for-loop-while/loop-scope.rs new file mode 100644 index 000000000..73324a3e1 --- /dev/null +++ b/tests/ui/for-loop-while/loop-scope.rs @@ -0,0 +1,8 @@ +// run-pass + +pub fn main() { + let x = vec![10, 20, 30]; + let mut sum = 0; + for x in &x { sum += *x; } + assert_eq!(sum, 60); +} diff --git a/tests/ui/for-loop-while/while-cont.rs b/tests/ui/for-loop-while/while-cont.rs new file mode 100644 index 000000000..a864e8ef7 --- /dev/null +++ b/tests/ui/for-loop-while/while-cont.rs @@ -0,0 +1,11 @@ +// run-pass +// Issue #825: Should recheck the loop condition after continuing +pub fn main() { + let mut i = 1; + while i > 0 { + assert!((i > 0)); + println!("{}", i); + i -= 1; + continue; + } +} diff --git a/tests/ui/for-loop-while/while-flow-graph.rs b/tests/ui/for-loop-while/while-flow-graph.rs new file mode 100644 index 000000000..1748964a7 --- /dev/null +++ b/tests/ui/for-loop-while/while-flow-graph.rs @@ -0,0 +1,6 @@ +// run-pass + + +// pretty-expanded FIXME #23616 + +pub fn main() { let x: isize = 10; while x == 10 && x == 11 { let _y = 0xf00_usize; } } diff --git a/tests/ui/for-loop-while/while-label.rs b/tests/ui/for-loop-while/while-label.rs new file mode 100644 index 000000000..5abc41daf --- /dev/null +++ b/tests/ui/for-loop-while/while-label.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unreachable_code)] + + +pub fn main() { + let mut i = 100; + 'w: while 1 + 1 == 2 { + i -= 1; + if i == 95 { + break 'w; + panic!("Should have broken out of loop"); + } + } + assert_eq!(i, 95); +} diff --git a/tests/ui/for-loop-while/while-let-2.rs b/tests/ui/for-loop-while/while-let-2.rs new file mode 100644 index 000000000..b9a49b47c --- /dev/null +++ b/tests/ui/for-loop-while/while-let-2.rs @@ -0,0 +1,31 @@ +// run-pass + +#[allow(dead_code)] +fn macros() { + macro_rules! foo{ + ($p:pat, $e:expr, $b:block) => {{ + while let $p = $e $b + //~^ WARN irrefutable `while let` + //~| WARN irrefutable `while let` + }} + } + macro_rules! bar{ + ($p:pat, $e:expr, $b:block) => {{ + foo!($p, $e, $b) + }} + } + + foo!(_a, 1, { + println!("irrefutable pattern"); + }); + bar!(_a, 1, { + println!("irrefutable pattern"); + }); +} + +pub fn main() { + while let _a = 1 { //~ WARN irrefutable `while let` + println!("irrefutable pattern"); + break; + } +} diff --git a/tests/ui/for-loop-while/while-let-2.stderr b/tests/ui/for-loop-while/while-let-2.stderr new file mode 100644 index 000000000..1b1cf6792 --- /dev/null +++ b/tests/ui/for-loop-while/while-let-2.stderr @@ -0,0 +1,42 @@ +warning: irrefutable `while let` pattern + --> $DIR/while-let-2.rs:7:19 + | +LL | while let $p = $e $b + | ^^^ +... +LL | / foo!(_a, 1, { +LL | | println!("irrefutable pattern"); +LL | | }); + | |______- in this macro invocation + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + = note: `#[warn(irrefutable_let_patterns)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `while let` pattern + --> $DIR/while-let-2.rs:7:19 + | +LL | while let $p = $e $b + | ^^^ +... +LL | / bar!(_a, 1, { +LL | | println!("irrefutable pattern"); +LL | | }); + | |______- in this macro invocation + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + = note: this warning originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `while let` pattern + --> $DIR/while-let-2.rs:27:11 + | +LL | while let _a = 1 { + | ^^^^^^^^^^ + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + +warning: 3 warnings emitted + diff --git a/tests/ui/for-loop-while/while-let.rs b/tests/ui/for-loop-while/while-let.rs new file mode 100644 index 000000000..b9d70ff0b --- /dev/null +++ b/tests/ui/for-loop-while/while-let.rs @@ -0,0 +1,46 @@ +// run-pass + +use std::collections::BinaryHeap; + +fn make_pq() -> BinaryHeap { + BinaryHeap::from(vec![1,2,3]) +} + +pub fn main() { + let mut pq = make_pq(); + let mut sum = 0; + while let Some(x) = pq.pop() { + sum += x; + } + assert_eq!(sum, 6); + + pq = make_pq(); + sum = 0; + 'a: while let Some(x) = pq.pop() { + sum += x; + if x == 2 { + break 'a; + } + } + assert_eq!(sum, 5); + + pq = make_pq(); + sum = 0; + 'a2: while let Some(x) = pq.pop() { + if x == 3 { + continue 'a2; + } + sum += x; + } + assert_eq!(sum, 3); + + let mut pq1 = make_pq(); + sum = 0; + while let Some(x) = pq1.pop() { + let mut pq2 = make_pq(); + while let Some(y) = pq2.pop() { + sum += x * y; + } + } + assert_eq!(sum, 6 + 12 + 18); +} diff --git a/tests/ui/for-loop-while/while-loop-constraints-2.rs b/tests/ui/for-loop-while/while-loop-constraints-2.rs new file mode 100644 index 000000000..3c5cdf06c --- /dev/null +++ b/tests/ui/for-loop-while/while-loop-constraints-2.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] + +pub fn main() { + let mut y: isize = 42; + let mut z: isize = 42; + let mut x: isize; + while z < 50 { + z += 1; + while false { x = y; y = z; } + println!("{}", y); + } + assert!((y == 42 && z == 50)); +} diff --git a/tests/ui/for-loop-while/while-prelude-drop.rs b/tests/ui/for-loop-while/while-prelude-drop.rs new file mode 100644 index 000000000..196b9daf6 --- /dev/null +++ b/tests/ui/for-loop-while/while-prelude-drop.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::string::String; + +#[derive(PartialEq)] +enum t { a, b(String), } + +fn make(i: isize) -> t { + if i > 10 { return t::a; } + let mut s = String::from("hello"); + // Ensure s is non-const. + + s.push_str("there"); + return t::b(s); +} + +pub fn main() { + let mut i = 0; + + + // The auto slot for the result of make(i) should not leak. + while make(i) != t::a { i += 1; } +} diff --git a/tests/ui/for-loop-while/while-with-break.rs b/tests/ui/for-loop-while/while-with-break.rs new file mode 100644 index 000000000..a9d52dda5 --- /dev/null +++ b/tests/ui/for-loop-while/while-with-break.rs @@ -0,0 +1,17 @@ +// run-pass + +pub fn main() { + let mut i: isize = 90; + while i < 100 { + println!("{}", i); + i = i + 1; + if i == 95 { + let _v: Vec = + vec![1, 2, 3, 4, 5]; // we check that it is freed by break + + println!("breaking"); + break; + } + } + assert_eq!(i, 95); +} diff --git a/tests/ui/for-loop-while/while.rs b/tests/ui/for-loop-while/while.rs new file mode 100644 index 000000000..90f718a34 --- /dev/null +++ b/tests/ui/for-loop-while/while.rs @@ -0,0 +1,13 @@ +// run-pass + + +pub fn main() { + let mut x: isize = 10; + let mut y: isize = 0; + while y < x { println!("{}", y); println!("hello"); y = y + 1; } + while x > 0 { + println!("goodbye"); + x = x - 1; + println!("{}", x); + } +} diff --git a/tests/ui/for/for-c-in-str.rs b/tests/ui/for/for-c-in-str.rs new file mode 100644 index 000000000..b086128d2 --- /dev/null +++ b/tests/ui/for/for-c-in-str.rs @@ -0,0 +1,14 @@ +// E0277 should point exclusively at line 6, not the entire for loop span + +fn main() { + for c in "asdf" { + //~^ ERROR `&str` is not an iterator + //~| NOTE `&str` is not an iterator + //~| HELP the trait `Iterator` is not implemented for `&str` + //~| NOTE required for `&str` to implement `IntoIterator` + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + println!(); + } +} diff --git a/tests/ui/for/for-c-in-str.stderr b/tests/ui/for/for-c-in-str.stderr new file mode 100644 index 000000000..959a7c43f --- /dev/null +++ b/tests/ui/for/for-c-in-str.stderr @@ -0,0 +1,12 @@ +error[E0277]: `&str` is not an iterator + --> $DIR/for-c-in-str.rs:4:14 + | +LL | for c in "asdf" { + | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` + | + = help: the trait `Iterator` is not implemented for `&str` + = note: required for `&str` to implement `IntoIterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/for/for-expn.rs b/tests/ui/for/for-expn.rs new file mode 100644 index 000000000..b9c4bbeda --- /dev/null +++ b/tests/ui/for/for-expn.rs @@ -0,0 +1,9 @@ +// Test that an error on a sub-expresson in a for loop has the correct span. + +fn main() { + // Odd formatting to make sure we get the right span. + for t in & + foo //~ ERROR cannot find value `foo` in this scope + { + } +} diff --git a/tests/ui/for/for-expn.stderr b/tests/ui/for/for-expn.stderr new file mode 100644 index 000000000..cdb211555 --- /dev/null +++ b/tests/ui/for/for-expn.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/for-expn.rs:6:7 + | +LL | foo + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/for/for-loop-bogosity.rs b/tests/ui/for/for-loop-bogosity.rs new file mode 100644 index 000000000..9341dea09 --- /dev/null +++ b/tests/ui/for/for-loop-bogosity.rs @@ -0,0 +1,21 @@ +struct MyStruct { + x: isize, + y: isize, +} + +impl MyStruct { + fn next(&mut self) -> Option { + Some(self.x) + } +} + +pub fn main() { + let mut bogus = MyStruct { + x: 1, + y: 2, + }; + for x in bogus { + //~^ ERROR `MyStruct` is not an iterator + drop(x); + } +} diff --git a/tests/ui/for/for-loop-bogosity.stderr b/tests/ui/for/for-loop-bogosity.stderr new file mode 100644 index 000000000..9bf8056e8 --- /dev/null +++ b/tests/ui/for/for-loop-bogosity.stderr @@ -0,0 +1,12 @@ +error[E0277]: `MyStruct` is not an iterator + --> $DIR/for-loop-bogosity.rs:17:14 + | +LL | for x in bogus { + | ^^^^^ `MyStruct` is not an iterator + | + = help: the trait `Iterator` is not implemented for `MyStruct` + = note: required for `MyStruct` to implement `IntoIterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/for/for-loop-refutable-pattern-error-message.rs b/tests/ui/for/for-loop-refutable-pattern-error-message.rs new file mode 100644 index 000000000..221951c87 --- /dev/null +++ b/tests/ui/for/for-loop-refutable-pattern-error-message.rs @@ -0,0 +1,3 @@ +fn main() { + for &1 in [1].iter() {} //~ ERROR refutable pattern in `for` loop binding +} diff --git a/tests/ui/for/for-loop-refutable-pattern-error-message.stderr b/tests/ui/for/for-loop-refutable-pattern-error-message.stderr new file mode 100644 index 000000000..49a82a676 --- /dev/null +++ b/tests/ui/for/for-loop-refutable-pattern-error-message.stderr @@ -0,0 +1,11 @@ +error[E0005]: refutable pattern in `for` loop binding + --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9 + | +LL | for &1 in [1].iter() {} + | ^^ patterns `&i32::MIN..=0_i32` and `&2_i32..=i32::MAX` not covered + | + = note: the matched value is of type `&i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/for/for-loop-type-error.rs b/tests/ui/for/for-loop-type-error.rs new file mode 100644 index 000000000..8d9fc20f0 --- /dev/null +++ b/tests/ui/for/for-loop-type-error.rs @@ -0,0 +1,6 @@ +pub fn main() { + let x = () + (); //~ ERROR cannot add `()` to `()` + + // this shouldn't have a flow-on error: + for _ in x {} +} diff --git a/tests/ui/for/for-loop-type-error.stderr b/tests/ui/for/for-loop-type-error.stderr new file mode 100644 index 000000000..c93a3b9b2 --- /dev/null +++ b/tests/ui/for/for-loop-type-error.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot add `()` to `()` + --> $DIR/for-loop-type-error.rs:2:16 + | +LL | let x = () + (); + | -- ^ -- () + | | + | () + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/for/for-loop-unconstrained-element-type.rs b/tests/ui/for/for-loop-unconstrained-element-type.rs new file mode 100644 index 000000000..0c7a3516a --- /dev/null +++ b/tests/ui/for/for-loop-unconstrained-element-type.rs @@ -0,0 +1,9 @@ +// Test that `for` loops don't introduce artificial +// constraints on the type of the binding (`i`). +// Subtle changes in the desugaring can cause the +// type of elements in the vector to (incorrectly) +// fallback to `!` or `()`. + +fn main() { + for i in Vec::new() { } //~ ERROR type annotations needed +} diff --git a/tests/ui/for/for-loop-unconstrained-element-type.stderr b/tests/ui/for/for-loop-unconstrained-element-type.stderr new file mode 100644 index 000000000..b1b38f6b9 --- /dev/null +++ b/tests/ui/for/for-loop-unconstrained-element-type.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/for-loop-unconstrained-element-type.rs:8:14 + | +LL | for i in Vec::new() { } + | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` + | +help: consider specifying the generic argument + | +LL | for i in Vec::::new() { } + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/foreign-fn-return-lifetime.fixed b/tests/ui/foreign-fn-return-lifetime.fixed new file mode 100644 index 000000000..143d6343d --- /dev/null +++ b/tests/ui/foreign-fn-return-lifetime.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +extern "C" { + pub fn g(_: &u8) -> &u8; // OK + pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/foreign-fn-return-lifetime.rs b/tests/ui/foreign-fn-return-lifetime.rs new file mode 100644 index 000000000..76fe50a34 --- /dev/null +++ b/tests/ui/foreign-fn-return-lifetime.rs @@ -0,0 +1,8 @@ +// run-rustfix + +extern "C" { + pub fn g(_: &u8) -> &u8; // OK + pub fn f() -> &u8; //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/foreign-fn-return-lifetime.stderr b/tests/ui/foreign-fn-return-lifetime.stderr new file mode 100644 index 000000000..df1a23a19 --- /dev/null +++ b/tests/ui/foreign-fn-return-lifetime.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/foreign-fn-return-lifetime.rs:5:19 + | +LL | pub fn f() -> &u8; + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | pub fn f() -> &'static u8; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/foreign-unsafe-fn-called.mir.stderr b/tests/ui/foreign-unsafe-fn-called.mir.stderr new file mode 100644 index 000000000..d3cf5d84f --- /dev/null +++ b/tests/ui/foreign-unsafe-fn-called.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/foreign-unsafe-fn-called.rs:11:5 + | +LL | test::free(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/foreign-unsafe-fn-called.rs b/tests/ui/foreign-unsafe-fn-called.rs new file mode 100644 index 000000000..67302ea1b --- /dev/null +++ b/tests/ui/foreign-unsafe-fn-called.rs @@ -0,0 +1,14 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +mod test { + extern "C" { + pub fn free(); + } +} + +fn main() { + test::free(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `test::free` is unsafe +} diff --git a/tests/ui/foreign-unsafe-fn-called.thir.stderr b/tests/ui/foreign-unsafe-fn-called.thir.stderr new file mode 100644 index 000000000..00ba0f7a6 --- /dev/null +++ b/tests/ui/foreign-unsafe-fn-called.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `test::free` is unsafe and requires unsafe function or block + --> $DIR/foreign-unsafe-fn-called.rs:11:5 + | +LL | test::free(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/foreign/auxiliary/fn-abi.rs b/tests/ui/foreign/auxiliary/fn-abi.rs new file mode 100644 index 000000000..25c9e1b4c --- /dev/null +++ b/tests/ui/foreign/auxiliary/fn-abi.rs @@ -0,0 +1,2 @@ +#[no_mangle] +pub extern fn foo() {} diff --git a/tests/ui/foreign/foreign-fn-linkname.rs b/tests/ui/foreign/foreign-fn-linkname.rs new file mode 100644 index 000000000..f6d820594 --- /dev/null +++ b/tests/ui/foreign/foreign-fn-linkname.rs @@ -0,0 +1,28 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with +// ignore-sgx no libc + +#![feature(rustc_private)] + +extern crate libc; +use std::ffi::CString; + +mod mlibc { + use libc::{c_char, size_t}; + + extern "C" { + #[link_name = "strlen"] + pub fn my_strlen(str: *const c_char) -> size_t; + } +} + +fn strlen(str: String) -> usize { + // C string is terminated with a zero + let s = CString::new(str).unwrap(); + unsafe { mlibc::my_strlen(s.as_ptr()) as usize } +} + +pub fn main() { + let len = strlen("Rust".to_string()); + assert_eq!(len, 4); +} diff --git a/tests/ui/foreign/foreign-int-types.rs b/tests/ui/foreign/foreign-int-types.rs new file mode 100644 index 000000000..2d01d3204 --- /dev/null +++ b/tests/ui/foreign/foreign-int-types.rs @@ -0,0 +1,12 @@ +// run-pass +#![forbid(improper_ctypes)] +#![allow(dead_code)] + +mod xx { + extern "C" { + pub fn strlen(str: *const u8) -> usize; + pub fn foo(x: isize, y: usize); + } +} + +fn main() {} diff --git a/tests/ui/foreign/foreign-mod-src/compiletest-ignore-dir b/tests/ui/foreign/foreign-mod-src/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/foreign/foreign-mod-src/inner.rs b/tests/ui/foreign/foreign-mod-src/inner.rs new file mode 100644 index 000000000..cf484878b --- /dev/null +++ b/tests/ui/foreign/foreign-mod-src/inner.rs @@ -0,0 +1,14 @@ +// run-pass + + + +pub fn main() { + let f = "Makefile"; + let s = rustrt.str_buf(f); + let buf = libc.malloc(1024); + let fd = libc.open(s, 0, 0); + libc.read(fd, buf, 1024); + libc.write(1, buf, 1024); + libc.close(fd); + libc.free(buf); +} diff --git a/tests/ui/foreign/foreign-mod-unused-const.rs b/tests/ui/foreign/foreign-mod-unused-const.rs new file mode 100644 index 000000000..7d79c30f4 --- /dev/null +++ b/tests/ui/foreign/foreign-mod-unused-const.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +mod foo { + extern "C" { + pub static errno: u32; + } +} + +pub fn main() {} diff --git a/tests/ui/foreign/foreign-pub-super.rs b/tests/ui/foreign/foreign-pub-super.rs new file mode 100644 index 000000000..19f9e4e33 --- /dev/null +++ b/tests/ui/foreign/foreign-pub-super.rs @@ -0,0 +1,12 @@ +// Test for #79487 +// check-pass + +#![allow(dead_code)] + +mod sha2 { + extern "C" { + pub(super) fn GFp_sha512_block_data_order(); + } +} + +fn main() {} diff --git a/tests/ui/foreign/foreign-src/compiletest-ignore-dir b/tests/ui/foreign/foreign-src/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/foreign/foreign-src/foreign.rs b/tests/ui/foreign/foreign-src/foreign.rs new file mode 100644 index 000000000..47016ad6c --- /dev/null +++ b/tests/ui/foreign/foreign-src/foreign.rs @@ -0,0 +1,9 @@ +// run-pass + + + +pub fn main() { + libc.puts(rustrt.str_buf("hello, extern world 1")); + libc.puts(rustrt.str_buf("hello, extern world 2")); + libc.puts(rustrt.str_buf("hello, extern world 3")); +} diff --git a/tests/ui/foreign/foreign-truncated-arguments.rs b/tests/ui/foreign/foreign-truncated-arguments.rs new file mode 100644 index 000000000..c61c2b587 --- /dev/null +++ b/tests/ui/foreign/foreign-truncated-arguments.rs @@ -0,0 +1,20 @@ +// run-pass +// compile-flags: -O +// Regression test for https://github.com/rust-lang/rust/issues/33868 + +#[repr(C)] +pub struct S { + a: u32, + b: f32, + c: u32 +} + +#[no_mangle] +#[inline(never)] +pub extern "C" fn test(s: S) -> u32 { + s.c +} + +fn main() { + assert_eq!(test(S{a: 0, b: 0.0, c: 42}), 42); +} diff --git a/tests/ui/foreign/foreign2.rs b/tests/ui/foreign/foreign2.rs new file mode 100644 index 000000000..df431f299 --- /dev/null +++ b/tests/ui/foreign/foreign2.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +// ignore-wasm32-bare no libc to test ffi with +// pretty-expanded FIXME #23616 +#![feature(rustc_private)] + +extern crate libc; + +mod bar { + extern "C" {} +} + +mod zed { + extern "C" {} +} + +mod mlibc { + use libc::{c_int, c_void, size_t, ssize_t}; + + extern "C" { + pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; + } +} + +mod baz { + extern "C" {} +} + +pub fn main() {} diff --git a/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs new file mode 100644 index 000000000..a84065e02 --- /dev/null +++ b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs @@ -0,0 +1,11 @@ +// Previously this ICE'd because `fn g()` would be lowered, but the block associated with `fn f()` +// wasn't. + +// compile-flags: --crate-type=lib + +extern "C" { + fn f() { + //~^ incorrect function inside `extern` block + fn g() {} + } +} diff --git a/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr new file mode 100644 index 000000000..d4a9ca3e7 --- /dev/null +++ b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr @@ -0,0 +1,19 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-74120-lowering-of-ffi-block-bodies.rs:7:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn f() { + | ________^___- + | | | + | | cannot have a body +LL | | +LL | | fn g() {} +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs new file mode 100644 index 000000000..2ac3ca293 --- /dev/null +++ b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs @@ -0,0 +1,12 @@ +// Regression test for issue #91370. + +extern { + //~^ `extern` blocks define existing foreign functions + fn f() { + //~^ incorrect function inside `extern` block + //~| cannot have a body + impl Copy for u8 {} + } +} + +fn main() {} diff --git a/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr new file mode 100644 index 000000000..4fb2f8c65 --- /dev/null +++ b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.stderr @@ -0,0 +1,21 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-91370-foreign-fn-block-impl.rs:5:8 + | +LL | extern { + | ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | +LL | fn f() { + | ________^___- + | | | + | | cannot have a body +LL | | +LL | | +LL | | impl Copy for u8 {} +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/tests/ui/foreign/issue-99276-same-type-lifetimes.rs b/tests/ui/foreign/issue-99276-same-type-lifetimes.rs new file mode 100644 index 000000000..fce603c80 --- /dev/null +++ b/tests/ui/foreign/issue-99276-same-type-lifetimes.rs @@ -0,0 +1,24 @@ +// Check that we do not ICE when structurally comparing types with lifetimes present. +// check-pass + +pub struct Record<'a> { + pub args: &'a [(usize, &'a str)], +} + +mod a { + extern "Rust" { + fn foo<'a, 'b>(record: &'a super::Record<'b>); + + fn bar<'a, 'b>(record: &'a super::Record<'b>); + } +} + +mod b { + extern "Rust" { + fn foo<'a, 'b>(record: &'a super::Record<'b>); + + fn bar<'a, 'b>(record: &'a super::Record<'b>); + } +} + +fn main() {} diff --git a/tests/ui/foreign/nil-decl-in-foreign.rs b/tests/ui/foreign/nil-decl-in-foreign.rs new file mode 100644 index 000000000..f3be94878 --- /dev/null +++ b/tests/ui/foreign/nil-decl-in-foreign.rs @@ -0,0 +1,14 @@ +// run-pass + +#![allow(improper_ctypes)] +#![allow(dead_code)] +// Issue #901 +// pretty-expanded FIXME #23616 + +mod libc { + extern "C" { + pub fn printf(x: ()); + } +} + +pub fn main() {} diff --git a/tests/ui/format-no-std.rs b/tests/ui/format-no-std.rs new file mode 100644 index 000000000..c9b7651bf --- /dev/null +++ b/tests/ui/format-no-std.rs @@ -0,0 +1,28 @@ +// run-pass +// ignore-emscripten no no_std executables + +#![feature(lang_items, start)] +#![no_std] + +extern crate std as other; + +#[macro_use] extern crate alloc; + +use alloc::string::ToString; + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + let s = format!("{}", 1_isize); + assert_eq!(s, "1".to_string()); + + let s = format!("test"); + assert_eq!(s, "test".to_string()); + + let s = format!("{test}", test=3_isize); + assert_eq!(s, "3".to_string()); + + let s = format!("hello {}", "world"); + assert_eq!(s, "hello world".to_string()); + + 0 +} diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs b/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs new file mode 100644 index 000000000..229c174da --- /dev/null +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs @@ -0,0 +1,10 @@ +// Test that we use fully-qualified type names in error messages. + +fn main() { + let x: //~ NOTE expected due to the type of this binding + Option; //~ NOTE expected due to this type + x = 5; + //~^ ERROR mismatched types + //~| NOTE expected enum `Option` + //~| NOTE expected enum `Option`, found integer +} diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr new file mode 100644 index 000000000..4750c5ccd --- /dev/null +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/fully-qualified-type-name1.rs:6:9 + | +LL | let x: + | - expected due to the type of this binding +LL | Option; + | ------------- expected due to this type +LL | x = 5; + | ^ expected enum `Option`, found integer + | + = note: expected enum `Option` + found type `{integer}` +help: try wrapping the expression in `Some` + | +LL | x = Some(5); + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs b/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs new file mode 100644 index 000000000..94a9f4e56 --- /dev/null +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs @@ -0,0 +1,18 @@ +// Test that we use fully-qualified type names in error messages. + +mod x { + pub enum Foo { } +} + +mod y { + pub enum Foo { } +} + +fn bar(x: x::Foo) -> y::Foo { + return x; + //~^ ERROR mismatched types + //~| expected enum `y::Foo`, found enum `x::Foo` +} + +fn main() { +} diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr new file mode 100644 index 000000000..a8f23f81d --- /dev/null +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/fully-qualified-type-name2.rs:12:12 + | +LL | fn bar(x: x::Foo) -> y::Foo { + | ------ expected `y::Foo` because of return type +LL | return x; + | ^ expected enum `y::Foo`, found enum `x::Foo` + | + = note: enum `x::Foo` and enum `y::Foo` have similar names, but are actually distinct types +note: enum `x::Foo` is defined in module `crate::x` of the current crate + --> $DIR/fully-qualified-type-name2.rs:4:5 + | +LL | pub enum Foo { } + | ^^^^^^^^^^^^ +note: enum `y::Foo` is defined in module `crate::y` of the current crate + --> $DIR/fully-qualified-type-name2.rs:8:5 + | +LL | pub enum Foo { } + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs b/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs new file mode 100644 index 000000000..2486ae009 --- /dev/null +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs @@ -0,0 +1,14 @@ +// Test that we use fully-qualified type names in error messages. + +use std::option::Option; + +fn bar(x: usize) -> Option { + return x; + //~^ ERROR mismatched types + //~| expected enum `Option` + //~| found type `usize` + //~| expected enum `Option`, found `usize` +} + +fn main() { +} diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr new file mode 100644 index 000000000..778b13f24 --- /dev/null +++ b/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/fully-qualified-type-name4.rs:6:12 + | +LL | fn bar(x: usize) -> Option { + | ------------- expected `Option` because of return type +LL | return x; + | ^ expected enum `Option`, found `usize` + | + = note: expected enum `Option` + found type `usize` +help: try wrapping the expression in `Some` + | +LL | return Some(x); + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/fun-indirect-call.rs b/tests/ui/fun-indirect-call.rs new file mode 100644 index 000000000..49da3d83f --- /dev/null +++ b/tests/ui/fun-indirect-call.rs @@ -0,0 +1,9 @@ +// run-pass + +fn f() -> isize { return 42; } + +pub fn main() { + let g: fn() -> isize = f; + let i: isize = g(); + assert_eq!(i, 42); +} diff --git a/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs new file mode 100644 index 000000000..855749c14 --- /dev/null +++ b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs @@ -0,0 +1,30 @@ +// compile-flags: -C opt-level=3 +// run-pass + +fn foo(_i: i32) -> i32 { + 1 +} +fn bar(_i: i32) -> i32 { + 1 +} + +fn main() { + let x: fn(i32) -> i32 = foo; + let y: fn(i32) -> i32 = bar; + + let s1; + if x == y { + s1 = "same".to_string(); + } else { + s1 = format!("{:?}, {:?}", x, y); + } + + let s2; + if x == y { + s2 = "same".to_string(); + } else { + s2 = format!("{:?}, {:?}", x, y); + } + + assert_eq!(s1, s2); +} diff --git a/tests/ui/function-pointer/issue-102289.rs b/tests/ui/function-pointer/issue-102289.rs new file mode 100644 index 000000000..de394ca9a --- /dev/null +++ b/tests/ui/function-pointer/issue-102289.rs @@ -0,0 +1,54 @@ +// check-pass + +pub(crate) trait Parser: Sized { + type Output; + fn parse(&mut self, _input: &str) -> Result<(), ()> { + loop {} + } + fn map(self, _f: F) -> Map + where + F: FnMut(Self::Output) -> B, + { + todo!() + } +} + +pub(crate) struct Chainl1(P, Op); +impl Parser for Chainl1 +where + P: Parser, + Op: Parser, + Op::Output: FnOnce(P::Output, P::Output) -> P::Output, +{ + type Output = P::Output; +} +pub(crate) fn chainl1(_parser: P, _op: Op) -> Chainl1 +where + P: Parser, + Op: Parser, + Op::Output: FnOnce(P::Output, P::Output) -> P::Output, +{ + loop {} +} + +pub(crate) struct Map(P, F); +impl Parser for Map +where + P: Parser, + F: FnMut(A) -> B, +{ + type Output = B; +} + +impl Parser for u32 { + type Output = (); +} + +pub fn chainl1_error_consume() { + fn first(t: T, _: U) -> T { + t + } + let _ = chainl1(1, 1.map(|_| first)).parse(""); +} + +fn main() {} diff --git a/tests/ui/function-pointer/sized-ret-with-binder.rs b/tests/ui/function-pointer/sized-ret-with-binder.rs new file mode 100644 index 000000000..104ac4d22 --- /dev/null +++ b/tests/ui/function-pointer/sized-ret-with-binder.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(unboxed_closures)] + +fn is_fn Fn<(&'a (),)>>() {} +fn is_fn2 Fn<(&'a &'b (),)>>() {} + +struct Outlives<'a, 'b>(std::marker::PhantomData<&'a &'b ()>); + +fn main() { + is_fn:: fn(&'a ()) -> &'a ()>(); + is_fn:: fn(&'a ()) -> &'a dyn std::fmt::Debug>(); + is_fn2:: fn(&'a &'b ()) -> Outlives<'a, 'b>>(); + is_fn2:: fn(&'a &'b ()) -> (&'a (), &'a ())>(); +} diff --git a/tests/ui/function-pointer/unsized-ret.rs b/tests/ui/function-pointer/unsized-ret.rs new file mode 100644 index 000000000..79009c5cb --- /dev/null +++ b/tests/ui/function-pointer/unsized-ret.rs @@ -0,0 +1,15 @@ +#![feature(fn_traits)] +#![feature(unboxed_closures)] +#![feature(tuple_trait)] + +fn foo, T:std::marker::Tuple>(f: Option, t: T) { + let y = (f.unwrap()).call(t); +} + +fn main() { + foo:: str, _>(None, ()); + //~^ ERROR the size for values of type `str` cannot be known at compilation time + + foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); + //~^ ERROR the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time +} diff --git a/tests/ui/function-pointer/unsized-ret.stderr b/tests/ui/function-pointer/unsized-ret.stderr new file mode 100644 index 000000000..6f430687e --- /dev/null +++ b/tests/ui/function-pointer/unsized-ret.stderr @@ -0,0 +1,35 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-ret.rs:10:27 + | +LL | foo:: str, _>(None, ()); + | --------------------- ^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: within `fn() -> str`, the trait `Sized` is not implemented for `str` + = note: required because it appears within the type `fn() -> str` +note: required by a bound in `foo` + --> $DIR/unsized-ret.rs:5:11 + | +LL | fn foo, T:std::marker::Tuple>(f: Option, t: T) { + | ^^^^^ required by this bound in `foo` + +error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time + --> $DIR/unsized-ret.rs:13:66 + | +LL | foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); + | ------------------------------------------------------------ ^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` + = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn Display + 'a)` +note: required by a bound in `foo` + --> $DIR/unsized-ret.rs:5:11 + | +LL | fn foo, T:std::marker::Tuple>(f: Option, t: T) { + | ^^^^^ required by this bound in `foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/functional-struct-update/functional-struct-update-noncopyable.rs b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.rs new file mode 100644 index 000000000..a9d7d9c8a --- /dev/null +++ b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.rs @@ -0,0 +1,14 @@ +// issue 7327 + +use std::sync::Arc; + +struct A { y: Arc, x: Arc } + +impl Drop for A { + fn drop(&mut self) { println!("x={}", *self.x); } +} +fn main() { + let a = A { y: Arc::new(1), x: Arc::new(2) }; + let _b = A { y: Arc::new(3), ..a }; //~ ERROR cannot move out of type `A` + let _c = a; +} diff --git a/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr new file mode 100644 index 000000000..45cdd3d2d --- /dev/null +++ b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr @@ -0,0 +1,12 @@ +error[E0509]: cannot move out of type `A`, which implements the `Drop` trait + --> $DIR/functional-struct-update-noncopyable.rs:12:14 + | +LL | let _b = A { y: Arc::new(3), ..a }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `a.x` has type `Arc`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0509`. diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs new file mode 100644 index 000000000..500633edf --- /dev/null +++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs @@ -0,0 +1,32 @@ +// RFC 736 (and Issue 21407): functional struct update should respect privacy. + +// The `foo` module attempts to maintains an invariant that each `S` +// has a unique `u64` id. +use self::foo::S; +mod foo { + use std::cell::{UnsafeCell}; + + static mut COUNT : UnsafeCell = UnsafeCell::new(1); + + pub struct S { pub a: u8, pub b: String, secret_uid: u64 } + + pub fn make_secrets(a: u8, b: String) -> S { + let val = unsafe { let p = COUNT.get(); let val = *p; *p = val + 1; val }; + println!("creating {}, uid {}", b, val); + S { a: a, b: b, secret_uid: val } + } + + impl Drop for S { + fn drop(&mut self) { + println!("dropping {}, uid {}", self.b, self.secret_uid); + } + } +} + +fn main() { + let s_1 = foo::make_secrets(3, format!("ess one")); + let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... + //~^ ERROR field `secret_uid` of struct `S` is private + println!("main forged an S named: {}", s_2.b); + // at end of scope, ... both s_1 *and* s_2 get dropped. Boom! +} diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr new file mode 100644 index 000000000..0b8af90b4 --- /dev/null +++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `secret_uid` of struct `S` is private + --> $DIR/functional-struct-update-respects-privacy.rs:28:49 + | +LL | let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... + | ^^^ field `secret_uid` is private + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/functions-closures/auxiliary/fn-abi.rs b/tests/ui/functions-closures/auxiliary/fn-abi.rs new file mode 100644 index 000000000..ace9fbdfd --- /dev/null +++ b/tests/ui/functions-closures/auxiliary/fn-abi.rs @@ -0,0 +1,2 @@ +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/tests/ui/functions-closures/call-closure-from-overloaded-op.rs b/tests/ui/functions-closures/call-closure-from-overloaded-op.rs new file mode 100644 index 000000000..8e1c68fd7 --- /dev/null +++ b/tests/ui/functions-closures/call-closure-from-overloaded-op.rs @@ -0,0 +1,9 @@ +// run-pass + +fn foo() -> isize { 22 } + +pub fn main() { + let mut x: Vec isize> = Vec::new(); + x.push(foo); + assert_eq!((x[0])(), 22); +} diff --git a/tests/ui/functions-closures/capture-clauses-boxed-closures.rs b/tests/ui/functions-closures/capture-clauses-boxed-closures.rs new file mode 100644 index 000000000..bcde50463 --- /dev/null +++ b/tests/ui/functions-closures/capture-clauses-boxed-closures.rs @@ -0,0 +1,14 @@ +// run-pass + +fn each(x: &[T], mut f: F) where F: FnMut(&T) { + for val in x { + f(val) + } +} + +fn main() { + let mut sum = 0_usize; + let elems = [ 1_usize, 2, 3, 4, 5 ]; + each(&elems, |val| sum += *val); + assert_eq!(sum, 15); +} diff --git a/tests/ui/functions-closures/capture-clauses-unboxed-closures.rs b/tests/ui/functions-closures/capture-clauses-unboxed-closures.rs new file mode 100644 index 000000000..206b3d7b6 --- /dev/null +++ b/tests/ui/functions-closures/capture-clauses-unboxed-closures.rs @@ -0,0 +1,13 @@ +// run-pass +fn each<'a,T,F:FnMut(&'a T)>(x: &'a [T], mut f: F) { + for val in x { + f(val) + } +} + +fn main() { + let mut sum = 0; + let elems = [ 1, 2, 3, 4, 5 ]; + each(&elems, |val: &usize| sum += *val); + assert_eq!(sum, 15); +} diff --git a/tests/ui/functions-closures/clone-closure.rs b/tests/ui/functions-closures/clone-closure.rs new file mode 100644 index 000000000..1e725d805 --- /dev/null +++ b/tests/ui/functions-closures/clone-closure.rs @@ -0,0 +1,18 @@ +// run-pass +// Check that closures implement `Clone`. + +#[derive(Clone)] +struct S(i32); + +fn main() { + let mut a = S(5); + let mut hello = move || { + a.0 += 1; + println!("Hello {}", a.0); + a.0 + }; + + let mut hello2 = hello.clone(); + assert_eq!(6, hello2()); + assert_eq!(6, hello()); +} diff --git a/tests/ui/functions-closures/closure-bounds-can-capture-chan.rs b/tests/ui/functions-closures/closure-bounds-can-capture-chan.rs new file mode 100644 index 000000000..ccb2e201d --- /dev/null +++ b/tests/ui/functions-closures/closure-bounds-can-capture-chan.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::channel; + +fn foo(blk: F) { + blk(); +} + +pub fn main() { + let (tx, rx) = channel(); + foo(move || { + tx.send(()).unwrap(); + }); + rx.recv().unwrap(); +} diff --git a/tests/ui/functions-closures/closure-expected-type/README.md b/tests/ui/functions-closures/closure-expected-type/README.md new file mode 100644 index 000000000..0b749040a --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/README.md @@ -0,0 +1,8 @@ +Some tests targeted at how we deduce the types of closure arguments. +This process is a result of some heuristics aimed at combining the +*expected type* we have with the *actual types* that we get from +inputs. This investigation was kicked off by #38714, which revealed +some pretty deep flaws in the ad-hoc way that we were doing things +before. + +See also `tests/ui/closure-expected-type`. diff --git a/tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs b/tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs new file mode 100644 index 000000000..6d5a9876c --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/expect-infer-supply-two-infers.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +fn with_closure(_: F) + where F: FnOnce(Vec, A) +{ +} + +fn expect_free_supply_free<'x>(x: &'x u32) { + with_closure(|mut x: Vec<_>, y| { + // Shows that the call to `x.push()` is influencing type of `y`... + x.push(22_u32); + + // ...since we now know the type of `y` and can resolve the method call. + let _ = y.wrapping_add(1); + }); +} + +fn main() { } diff --git a/tests/ui/functions-closures/closure-expected-type/issue-38714.rs b/tests/ui/functions-closures/closure-expected-type/issue-38714.rs new file mode 100644 index 000000000..e97785b5c --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/issue-38714.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +struct UsizeRef<'a> { + a: &'a usize +} + +type RefTo = Box Fn(&'r Vec) -> UsizeRef<'r>>; + +fn ref_to<'a>(vec: &'a Vec) -> UsizeRef<'a> { + UsizeRef{ a: &vec[0]} +} + +fn main() { + // Regression test: this was causing ICEs; it should compile. + let a: RefTo = Box::new(|vec: &Vec| { + UsizeRef{ a: &vec[0] } + }); +} diff --git a/tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs b/tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs new file mode 100644 index 000000000..e9964531c --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/supply-just-return-type.rs @@ -0,0 +1,26 @@ +// run-pass +fn with_closure(f: F) -> Result + where F: FnOnce(&char) -> Result, +{ + f(&'a') +} + +fn main() { + // Test that supplying the `-> Result` manually here + // (which is needed to constrain `R`) still allows us to figure + // out that the type of `x` is `&'a char` where `'a` is bound in + // the closure (if we didn't, we'd get a type-error because + // `with_closure` requires a bound region). + // + // This pattern was found in the wild. + let z = with_closure(|x| -> Result { Ok(*x) }); + assert_eq!(z.unwrap(), 'a'); + + // It also works with `_`: + let z = with_closure(|x: _| -> Result { Ok(*x) }); + assert_eq!(z.unwrap(), 'a'); + + // It also works with `&_`: + let z = with_closure(|x: &_| -> Result { Ok(*x) }); + assert_eq!(z.unwrap(), 'a'); +} diff --git a/tests/ui/functions-closures/closure-expected-type/supply-nothing.rs b/tests/ui/functions-closures/closure-expected-type/supply-nothing.rs new file mode 100644 index 000000000..8665cfc21 --- /dev/null +++ b/tests/ui/functions-closures/closure-expected-type/supply-nothing.rs @@ -0,0 +1,11 @@ +// run-pass +fn with_closure(f: F) -> u32 + where F: FnOnce(&u32, &u32) -> u32 +{ + f(&22, &44) +} + +fn main() { + let z = with_closure(|x, y| x + y).wrapping_add(1); + assert_eq!(z, 22 + 44 + 1); +} diff --git a/tests/ui/functions-closures/closure-immediate.rs b/tests/ui/functions-closures/closure-immediate.rs new file mode 100644 index 000000000..428fc6bde --- /dev/null +++ b/tests/ui/functions-closures/closure-immediate.rs @@ -0,0 +1,13 @@ +// run-pass + +// After the work to reoptimize structs, it became possible for immediate logic to fail. +// This test verifies that it actually works. + +fn main() { + let c = |a: u8, b: u16, c: u8| { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + }; + c(1, 2, 3); +} diff --git a/tests/ui/functions-closures/closure-inference.rs b/tests/ui/functions-closures/closure-inference.rs new file mode 100644 index 000000000..1877414f0 --- /dev/null +++ b/tests/ui/functions-closures/closure-inference.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_braces)] + +fn foo(i: isize) -> isize { i + 1 } + +fn apply(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) } + +pub fn main() { + let f = {|i| foo(i)}; + assert_eq!(apply(f, 2), 3); +} diff --git a/tests/ui/functions-closures/closure-inference2.rs b/tests/ui/functions-closures/closure-inference2.rs new file mode 100644 index 000000000..4ce132e86 --- /dev/null +++ b/tests/ui/functions-closures/closure-inference2.rs @@ -0,0 +1,9 @@ +// run-pass +// Test a rather underspecified example: +#![allow(unused_braces)] + +pub fn main() { + let f = {|i| i}; + assert_eq!(f(2), 2); + assert_eq!(f(5), 5); +} diff --git a/tests/ui/functions-closures/closure-reform.rs b/tests/ui/functions-closures/closure-reform.rs new file mode 100644 index 000000000..0bb6159ff --- /dev/null +++ b/tests/ui/functions-closures/closure-reform.rs @@ -0,0 +1,56 @@ +// run-pass +#![allow(unused_variables)] +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +fn call_it(f: F) + where F : FnOnce(String) -> String +{ + println!("{}", f("Fred".to_string())) +} + +fn call_a_thunk(f: F) where F: FnOnce() { + f(); +} + +fn call_this(f: F) where F: FnOnce(&str) + Send { + f("Hello!"); +} + +fn call_bare(f: fn(&str)) { + f("Hello world!") +} + +fn call_bare_again(f: extern "Rust" fn(&str)) { + f("Goodbye world!") +} + +pub fn main() { + // Procs + + let greeting = "Hello ".to_string(); + call_it(|s| { + format!("{}{}", greeting, s) + }); + + let greeting = "Goodbye ".to_string(); + call_it(|s| format!("{}{}", greeting, s)); + + let greeting = "How's life, ".to_string(); + call_it(|s: String| -> String { + format!("{}{}", greeting, s) + }); + + // Closures + + call_a_thunk(|| println!("Hello world!")); + + call_this(|s| println!("{}", s)); + + // External functions + + fn foo(s: &str) {} + call_bare(foo); + + call_bare_again(foo); +} diff --git a/tests/ui/functions-closures/closure-returning-closure.rs b/tests/ui/functions-closures/closure-returning-closure.rs new file mode 100644 index 000000000..17db81687 --- /dev/null +++ b/tests/ui/functions-closures/closure-returning-closure.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + let f = |_||x, y| x+y; + assert_eq!(f(())(1, 2), 3); +} diff --git a/tests/ui/functions-closures/closure-to-fn-coercion.rs b/tests/ui/functions-closures/closure-to-fn-coercion.rs new file mode 100644 index 000000000..87ba488b5 --- /dev/null +++ b/tests/ui/functions-closures/closure-to-fn-coercion.rs @@ -0,0 +1,35 @@ +// run-pass +use std::mem; + +const FOO: fn(u8) -> u8 = |v: u8| { v }; + +const BAR: [fn(&mut u32); 5] = [ + |_: &mut u32| {}, + |v: &mut u32| *v += 1, + |v: &mut u32| *v += 2, + |v: &mut u32| *v += 3, + |v: &mut u32| *v += 4, +]; +fn func_specific() -> fn() -> u32 { + || return 42 +} + +fn generic(_: T) -> fn() -> usize { + || mem::size_of::() +} + +fn main() { + // Items + assert_eq!(func_specific()(), 42); + let foo: fn(u8) -> u8 = |v: u8| { v }; + assert_eq!(foo(31), 31); + // Constants + assert_eq!(FOO(31), 31); + let mut a: u32 = 0; + assert_eq!({ BAR[0](&mut a); a }, 0); + assert_eq!({ BAR[1](&mut a); a }, 1); + assert_eq!({ BAR[2](&mut a); a }, 3); + assert_eq!({ BAR[3](&mut a); a }, 6); + assert_eq!({ BAR[4](&mut a); a }, 10); + assert_eq!(generic(0i8)(), 1); +} diff --git a/tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs b/tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs new file mode 100644 index 000000000..e7a938395 --- /dev/null +++ b/tests/ui/functions-closures/closure_to_fn_coercion-expected-types.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_variables)] +// Ensure that we deduce expected argument types when a `fn()` type is expected (#41755) + +fn foo(f: fn(Vec) -> usize) { } + +fn main() { + foo(|x| x.len()) +} diff --git a/tests/ui/functions-closures/copy-closure.rs b/tests/ui/functions-closures/copy-closure.rs new file mode 100644 index 000000000..72da02421 --- /dev/null +++ b/tests/ui/functions-closures/copy-closure.rs @@ -0,0 +1,16 @@ +// run-pass +// Check that closures implement `Copy`. + +fn call T>(f: F) -> T { f() } + +fn main() { + let a = 5; + let hello = || { + println!("Hello {}", a); + a + }; + + assert_eq!(5, call(hello.clone())); + assert_eq!(5, call(hello)); + assert_eq!(5, call(hello)); +} diff --git a/tests/ui/functions-closures/fn-abi.rs b/tests/ui/functions-closures/fn-abi.rs new file mode 100644 index 000000000..ac3a4be33 --- /dev/null +++ b/tests/ui/functions-closures/fn-abi.rs @@ -0,0 +1,18 @@ +// run-pass +// Ensure that declarations and types which use `extern fn` both have the same +// ABI (#9309). + +// pretty-expanded FIXME #23616 +// aux-build:fn-abi.rs + +extern crate fn_abi; + +extern "C" { + fn foo(); +} + +pub fn main() { + // Will only type check if the type of _p and the decl of foo use the + // same ABI + let _p: unsafe extern "C" fn() = foo; +} diff --git a/tests/ui/functions-closures/fn-bare-assign.rs b/tests/ui/functions-closures/fn-bare-assign.rs new file mode 100644 index 000000000..f5dab3c84 --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-assign.rs @@ -0,0 +1,17 @@ +// run-pass + +fn f(i: isize, called: &mut bool) { + assert_eq!(i, 10); + *called = true; +} + +fn g(f: fn(isize, v: &mut bool), called: &mut bool) { + f(10, called); +} + +pub fn main() { + let mut called = false; + let h = f; + g(h, &mut called); + assert_eq!(called, true); +} diff --git a/tests/ui/functions-closures/fn-bare-coerce-to-block.rs b/tests/ui/functions-closures/fn-bare-coerce-to-block.rs new file mode 100644 index 000000000..922e016dd --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-coerce-to-block.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn bare() {} + +fn likes_block(f: F) where F: FnOnce() { f() } + +pub fn main() { + likes_block(bare); +} diff --git a/tests/ui/functions-closures/fn-bare-item.rs b/tests/ui/functions-closures/fn-bare-item.rs new file mode 100644 index 000000000..a6e6495a4 --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-item.rs @@ -0,0 +1,8 @@ +// run-pass +fn f() { + println!("This is a bare function"); +} + +pub fn main() { + f(); +} diff --git a/tests/ui/functions-closures/fn-bare-size.rs b/tests/ui/functions-closures/fn-bare-size.rs new file mode 100644 index 000000000..2ba56eaae --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-size.rs @@ -0,0 +1,8 @@ +// run-pass + +use std::mem; + +pub fn main() { + // Bare functions should just be a pointer + assert_eq!(mem::size_of::(), mem::size_of::()); +} diff --git a/tests/ui/functions-closures/fn-bare-spawn.rs b/tests/ui/functions-closures/fn-bare-spawn.rs new file mode 100644 index 000000000..0d46fe220 --- /dev/null +++ b/tests/ui/functions-closures/fn-bare-spawn.rs @@ -0,0 +1,15 @@ +// run-pass +// This is what the signature to spawn should look like with bare functions + + +fn spawn(val: T, f: fn(T)) { + f(val); +} + +fn f(i: isize) { + assert_eq!(i, 100); +} + +pub fn main() { + spawn(100, f); +} diff --git a/tests/ui/functions-closures/fn-coerce-field.rs b/tests/ui/functions-closures/fn-coerce-field.rs new file mode 100644 index 000000000..38bde7b9e --- /dev/null +++ b/tests/ui/functions-closures/fn-coerce-field.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +struct r where F: FnOnce() { + field: F, +} + +pub fn main() { + fn f() {} + let _i: r = r {field: f as fn()}; +} diff --git a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs new file mode 100644 index 000000000..e48ab4aa9 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs @@ -0,0 +1,14 @@ +struct Struct(T); +impl Struct +//~^ ERROR cannot find type `T` in this scope +//~| NOTE not found in this scope +//~| HELP you might be missing a type parameter +where + T: Copy, + //~^ ERROR cannot find type `T` in this scope + //~| NOTE not found in this scope +{ + fn method(v: Vec) { v.len(); } +} + +fn main() {} diff --git a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr new file mode 100644 index 000000000..9d4ea0115 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr @@ -0,0 +1,20 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:2:13 + | +LL | impl Struct + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl Struct + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:7:5 + | +LL | T: Copy, + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/functions-closures/fn-help-with-err.rs b/tests/ui/functions-closures/fn-help-with-err.rs new file mode 100644 index 000000000..612fe1b84 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err.rs @@ -0,0 +1,24 @@ +// This test case checks the behavior of typeck::check::method::suggest::is_fn on Ty::Error. + +struct Foo; + +trait Bar { + //~^ NOTE `Bar` defines an item `bar`, perhaps you need to implement it + fn bar(&self) {} +} + +impl Bar for Foo {} + +fn main() { + let arc = std::sync::Arc::new(oops); + //~^ ERROR cannot find value `oops` in this scope + //~| NOTE not found + arc.bar(); + + let arc2 = std::sync::Arc::new(|| Foo); + arc2.bar(); + //~^ ERROR no method named `bar` + //~| NOTE method not found + //~| HELP items from traits can only be used if the trait is implemented and in scope + //~| HELP use parentheses to call this closure +} diff --git a/tests/ui/functions-closures/fn-help-with-err.stderr b/tests/ui/functions-closures/fn-help-with-err.stderr new file mode 100644 index 000000000..83a2b1f58 --- /dev/null +++ b/tests/ui/functions-closures/fn-help-with-err.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `oops` in this scope + --> $DIR/fn-help-with-err.rs:13:35 + | +LL | let arc = std::sync::Arc::new(oops); + | ^^^^ not found in this scope + +error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:18:36]>` in the current scope + --> $DIR/fn-help-with-err.rs:19:10 + | +LL | arc2.bar(); + | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:18:36]>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `bar`, perhaps you need to implement it + --> $DIR/fn-help-with-err.rs:5:1 + | +LL | trait Bar { + | ^^^^^^^^^ +help: use parentheses to call this closure + | +LL | arc2().bar(); + | ++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/functions-closures/fn-item-type-cast.rs b/tests/ui/functions-closures/fn-item-type-cast.rs new file mode 100644 index 000000000..4d50ea97b --- /dev/null +++ b/tests/ui/functions-closures/fn-item-type-cast.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test explicit coercions from a fn item type to a fn pointer type. + + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } +type IntMap = fn(isize) -> isize; + +fn eq(x: T, y: T) { } + +static TEST: Option = Some(foo as IntMap); + +fn main() { + let f = foo as IntMap; + + let f = if true { foo as IntMap } else { bar as IntMap }; + assert_eq!(f(4), 8); + + eq(foo as IntMap, bar as IntMap); +} diff --git a/tests/ui/functions-closures/fn-item-type-coerce.rs b/tests/ui/functions-closures/fn-item-type-coerce.rs new file mode 100644 index 000000000..7a096764e --- /dev/null +++ b/tests/ui/functions-closures/fn-item-type-coerce.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_variables)] +// Test implicit coercions from a fn item type to a fn pointer type. + +// pretty-expanded FIXME #23616 + +fn foo(x: isize) -> isize { x * 2 } +fn bar(x: isize) -> isize { x * 4 } +type IntMap = fn(isize) -> isize; + +fn eq(x: T, y: T) { } + +fn main() { + let f: IntMap = foo; + + eq::(foo, bar); +} diff --git a/tests/ui/functions-closures/fn-item-type-zero-sized.rs b/tests/ui/functions-closures/fn-item-type-zero-sized.rs new file mode 100644 index 000000000..bd9f1ed66 --- /dev/null +++ b/tests/ui/functions-closures/fn-item-type-zero-sized.rs @@ -0,0 +1,13 @@ +// run-pass +// Test that fn item types are zero-sized. + +use std::mem::{size_of, size_of_val}; + +fn main() { + assert_eq!(size_of_val(&main), 0); + + let (a, b) = (size_of::, size_of::); + assert_eq!(size_of_val(&a), 0); + assert_eq!(size_of_val(&b), 0); + assert_eq!((a(), b()), (1, 2)); +} diff --git a/tests/ui/functions-closures/fn-lval.rs b/tests/ui/functions-closures/fn-lval.rs new file mode 100644 index 000000000..01079eea4 --- /dev/null +++ b/tests/ui/functions-closures/fn-lval.rs @@ -0,0 +1,11 @@ +// run-pass + + + +// pretty-expanded FIXME #23616 + +fn foo(_f: fn(isize) -> isize) { } + +fn id(x: isize) -> isize { return x; } + +pub fn main() { foo(id); } diff --git a/tests/ui/functions-closures/fn-type-infer.rs b/tests/ui/functions-closures/fn-type-infer.rs new file mode 100644 index 000000000..fe6567f22 --- /dev/null +++ b/tests/ui/functions-closures/fn-type-infer.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +pub fn main() { + // We should be able to type infer inside of ||s. + let _f = || { + let i = 10; + }; +} diff --git a/tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs b/tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs new file mode 100644 index 000000000..4ac07123d --- /dev/null +++ b/tests/ui/functions-closures/implied-bounds-closure-arg-outlives.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that we are able to handle the relationships between free +// regions bound in a closure callback. + +#[derive(Copy, Clone)] +struct MyCx<'short, 'long: 'short> { + short: &'short u32, + long: &'long u32, +} + +impl<'short, 'long> MyCx<'short, 'long> { + fn short(self) -> &'short u32 { self.short } + fn long(self) -> &'long u32 { self.long } + fn set_short(&mut self, v: &'short u32) { self.short = v; } +} + +fn with(op: F) -> R +where + F: for<'short, 'long> FnOnce(MyCx<'short, 'long>) -> R, +{ + op(MyCx { + short: &22, + long: &22, + }) +} + +fn main() { + with(|mut cx| { + // For this to type-check, we need to be able to deduce that + // the lifetime of `l` can be `'short`, even though it has + // input from `'long`. + let l = if true { cx.long() } else { cx.short() }; + cx.set_short(l); + }); +} diff --git a/tests/ui/functions-closures/nullable-pointer-opt-closures.rs b/tests/ui/functions-closures/nullable-pointer-opt-closures.rs new file mode 100644 index 000000000..87dacfba2 --- /dev/null +++ b/tests/ui/functions-closures/nullable-pointer-opt-closures.rs @@ -0,0 +1,34 @@ +// run-pass + +use std::mem; + +pub fn main() { + // By Ref Capture + let a = 10i32; + let b = Some(|| println!("{}", a)); + // When we capture by reference we can use any of the + // captures as the discriminant since they're all + // behind a pointer. + assert_eq!(mem::size_of_val(&b), mem::size_of::()); + + // By Value Capture + let a = Box::new(12i32); + let b = Some(move || println!("{}", a)); + // We captured `a` by value and since it's a `Box` we can use it + // as the discriminant. + assert_eq!(mem::size_of_val(&b), mem::size_of::>()); + + // By Value Capture - Transitive case + let a = "Hello".to_string(); // String -> Vec -> Unique -> NonZero + let b = Some(move || println!("{}", a)); + // We captured `a` by value and since down the chain it contains + // a `NonZero` field, we can use it as the discriminant. + assert_eq!(mem::size_of_val(&b), mem::size_of::()); + + // By Value - No Optimization + let a = 14i32; + let b = Some(move || println!("{}", a)); + // We captured `a` by value but we can't use it as the discriminant + // thus we end up with an extra field for the discriminant + assert_eq!(mem::size_of_val(&b), mem::size_of::<(i32, i32)>()); +} diff --git a/tests/ui/functions-closures/parallel-codegen-closures.rs b/tests/ui/functions-closures/parallel-codegen-closures.rs new file mode 100644 index 000000000..79759daba --- /dev/null +++ b/tests/ui/functions-closures/parallel-codegen-closures.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(stable_features)] + +// Tests parallel codegen - this can fail if the symbol for the anonymous +// closure in `sum` pollutes the second codegen unit from the first. + +// compile-flags: -C codegen_units=2 + +#![feature(iter_arith)] + +mod a { + fn foo() { + let x = ["a", "bob", "c"]; + let len: usize = x.iter().map(|s| s.len()).sum(); + } +} + +mod b { + fn bar() { + let x = ["a", "bob", "c"]; + let len: usize = x.iter().map(|s| s.len()).sum(); + } +} + +fn main() { +} diff --git a/tests/ui/functions-closures/return-from-closure.rs b/tests/ui/functions-closures/return-from-closure.rs new file mode 100644 index 000000000..656a95f12 --- /dev/null +++ b/tests/ui/functions-closures/return-from-closure.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(non_upper_case_globals)] +// just to make sure that `return` is only returning from the closure, +// not the surrounding function. + +static mut calls: usize = 0; + +fn surrounding() { + let return_works = |n: isize| { + unsafe { calls += 1 } + + if n >= 0 { return; } + panic!() + }; + + return_works(10); + return_works(20); + + let return_works_proc = |n: isize| { + unsafe { calls += 1 } + + if n >= 0 { return; } + panic!() + }; + + return_works_proc(10); +} + +pub fn main() { + surrounding(); + + assert_eq!(unsafe {calls}, 3); +} diff --git a/tests/ui/future-incompatible-lint-group.rs b/tests/ui/future-incompatible-lint-group.rs new file mode 100644 index 000000000..bbd0e33d7 --- /dev/null +++ b/tests/ui/future-incompatible-lint-group.rs @@ -0,0 +1,18 @@ +// Ensure that the future_incompatible lint group only includes +// lints for changes that are not tied to an edition +#![deny(future_incompatible)] + +trait Tr { + // Warn only since this is not a `future_incompatible` lint + fn f(u8) {} //~ WARN anonymous parameters are deprecated + //~| WARN this is accepted in the current edition +} + +pub mod submodule { + // Error since this is a `future_incompatible` lint + #![doc(test(some_test))] + //~^ ERROR this attribute can only be applied at the crate level + //~| WARN this was previously accepted by the compiler +} + +fn main() {} diff --git a/tests/ui/future-incompatible-lint-group.stderr b/tests/ui/future-incompatible-lint-group.stderr new file mode 100644 index 000000000..a8fb100a7 --- /dev/null +++ b/tests/ui/future-incompatible-lint-group.stderr @@ -0,0 +1,28 @@ +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/future-incompatible-lint-group.rs:7:10 + | +LL | fn f(u8) {} + | ^^ help: try naming the parameter or explicitly ignoring it: `_: u8` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + = note: `#[warn(anonymous_parameters)]` on by default + +error: this attribute can only be applied at the crate level + --> $DIR/future-incompatible-lint-group.rs:13:12 + | +LL | #![doc(test(some_test))] + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: read for more information +note: the lint level is defined here + --> $DIR/future-incompatible-lint-group.rs:3:9 + | +LL | #![deny(future_incompatible)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(future_incompatible)]` + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/generator/addassign-yield.rs b/tests/ui/generator/addassign-yield.rs new file mode 100644 index 000000000..66f22bf31 --- /dev/null +++ b/tests/ui/generator/addassign-yield.rs @@ -0,0 +1,35 @@ +// run-pass +// Regression test for broken MIR error (#61442) +// Due to the two possible evaluation orders for +// a '+=' expression (depending on whether or not the 'AddAssign' trait +// is being used), we were failing to account for all types that might +// possibly be live across a yield point. + +#![feature(generators)] + +fn foo() { + let _x = static || { + let mut s = String::new(); + s += { yield; "" }; + }; + + let _y = static || { + let x = &mut 0; + *{ yield; x } += match String::new() { _ => 0 }; + }; + + // Please don't ever actually write something like this + let _z = static || { + let x = &mut 0; + *{ + let inner = &mut 1; + *{ yield (); inner } += match String::new() { _ => 1}; + yield; + x + } += match String::new() { _ => 2 }; + }; +} + +fn main() { + foo() +} diff --git a/tests/ui/generator/async-generator-issue-67158.rs b/tests/ui/generator/async-generator-issue-67158.rs new file mode 100644 index 000000000..8125a7a9b --- /dev/null +++ b/tests/ui/generator/async-generator-issue-67158.rs @@ -0,0 +1,6 @@ +#![feature(generators)] +// edition:2018 +// Regression test for #67158. +fn main() { + async { yield print!(":C") }; //~ ERROR `async` generators are not yet supported +} diff --git a/tests/ui/generator/async-generator-issue-67158.stderr b/tests/ui/generator/async-generator-issue-67158.stderr new file mode 100644 index 000000000..7270d188e --- /dev/null +++ b/tests/ui/generator/async-generator-issue-67158.stderr @@ -0,0 +1,9 @@ +error[E0727]: `async` generators are not yet supported + --> $DIR/async-generator-issue-67158.rs:5:13 + | +LL | async { yield print!(":C") }; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0727`. diff --git a/tests/ui/generator/auto-trait-regions.rs b/tests/ui/generator/auto-trait-regions.rs new file mode 100644 index 000000000..ea4b0d554 --- /dev/null +++ b/tests/ui/generator/auto-trait-regions.rs @@ -0,0 +1,53 @@ +#![feature(generators)] +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Foo {} + +struct No; + +impl !Foo for No {} + +struct A<'a, 'b>(&'a mut bool, &'b mut bool, No); + +impl<'a, 'b: 'a> Foo for A<'a, 'b> {} + +struct OnlyFooIfStaticRef(No); +impl Foo for &'static OnlyFooIfStaticRef {} + +struct OnlyFooIfRef(No); +impl<'a> Foo for &'a OnlyFooIfRef {} + +fn assert_foo(f: T) {} + +fn main() { + // Make sure 'static is erased for generator interiors so we can't match it in trait selection + let x: &'static _ = &OnlyFooIfStaticRef(No); + let gen = || { + let x = x; + yield; + assert_foo(x); + }; + assert_foo(gen); + //~^ ERROR implementation of `Foo` is not general enough + + // Allow impls which matches any lifetime + let x = &OnlyFooIfRef(No); + let gen = || { + let x = x; + yield; + assert_foo(x); + }; + assert_foo(gen); // ok + + // Disallow impls which relates lifetimes in the generator interior + let gen = || { + let a = A(&mut true, &mut true, No); + //~^ temporary value dropped while borrowed + //~| temporary value dropped while borrowed + yield; + assert_foo(a); + }; + assert_foo(gen); + //~^ ERROR not general enough +} diff --git a/tests/ui/generator/auto-trait-regions.stderr b/tests/ui/generator/auto-trait-regions.stderr new file mode 100644 index 000000000..0b1f34aeb --- /dev/null +++ b/tests/ui/generator/auto-trait-regions.stderr @@ -0,0 +1,47 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/auto-trait-regions.rs:45:24 + | +LL | let a = A(&mut true, &mut true, No); + | ^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | assert_foo(a); + | - borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error[E0716]: temporary value dropped while borrowed + --> $DIR/auto-trait-regions.rs:45:35 + | +LL | let a = A(&mut true, &mut true, No); + | ^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | assert_foo(a); + | - borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error: implementation of `Foo` is not general enough + --> $DIR/auto-trait-regions.rs:31:5 + | +LL | assert_foo(gen); + | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` + +error: implementation of `Foo` is not general enough + --> $DIR/auto-trait-regions.rs:51:5 + | +LL | assert_foo(gen); + | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs b/tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs new file mode 100644 index 000000000..207c2735f --- /dev/null +++ b/tests/ui/generator/auxiliary/metadata-sufficient-for-layout.rs @@ -0,0 +1,11 @@ +// compile-flags: --emit metadata +#![feature(generators, generator_trait)] + +use std::marker::Unpin; +use std::ops::Generator; + +pub fn g() -> impl Generator<(), Yield = (), Return = ()> { + || { + yield; + } +} diff --git a/tests/ui/generator/auxiliary/xcrate-reachable.rs b/tests/ui/generator/auxiliary/xcrate-reachable.rs new file mode 100644 index 000000000..2dd5ea675 --- /dev/null +++ b/tests/ui/generator/auxiliary/xcrate-reachable.rs @@ -0,0 +1,14 @@ +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn msg() -> u32 { + 0 +} + +pub fn foo() -> impl Generator<(), Yield=(), Return=u32> { + || { + yield; + return msg(); + } +} diff --git a/tests/ui/generator/auxiliary/xcrate.rs b/tests/ui/generator/auxiliary/xcrate.rs new file mode 100644 index 000000000..d07abd091 --- /dev/null +++ b/tests/ui/generator/auxiliary/xcrate.rs @@ -0,0 +1,18 @@ +#![feature(generators, generator_trait)] + +use std::marker::Unpin; +use std::ops::Generator; + +pub fn foo() -> impl Generator<(), Yield = (), Return = ()> { + || { + if false { + yield; + } + } +} + +pub fn bar(t: T) -> Box + Unpin> { + Box::new(|| { + yield t; + }) +} diff --git a/tests/ui/generator/borrow-in-tail-expr.rs b/tests/ui/generator/borrow-in-tail-expr.rs new file mode 100644 index 000000000..540f5e3e1 --- /dev/null +++ b/tests/ui/generator/borrow-in-tail-expr.rs @@ -0,0 +1,11 @@ +// run-pass + +#![feature(generators)] + +fn main() { + let _a = || { + yield; + let a = String::new(); + a.len() + }; +} diff --git a/tests/ui/generator/borrowing.rs b/tests/ui/generator/borrowing.rs new file mode 100644 index 000000000..d36592583 --- /dev/null +++ b/tests/ui/generator/borrowing.rs @@ -0,0 +1,20 @@ +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let _b = { + let a = 3; + Pin::new(&mut || yield &a).resume(()) + //~^ ERROR: `a` does not live long enough + }; + + let _b = { + let a = 3; + || { + yield &a + //~^ ERROR: `a` does not live long enough + } + }; +} diff --git a/tests/ui/generator/borrowing.stderr b/tests/ui/generator/borrowing.stderr new file mode 100644 index 000000000..38e1ace8c --- /dev/null +++ b/tests/ui/generator/borrowing.stderr @@ -0,0 +1,31 @@ +error[E0597]: `a` does not live long enough + --> $DIR/borrowing.rs:9:33 + | +LL | let _b = { + | -- borrow later stored here +LL | let a = 3; +LL | Pin::new(&mut || yield &a).resume(()) + | -- ^ borrowed value does not live long enough + | | + | value captured here by generator +LL | +LL | }; + | - `a` dropped here while still borrowed + +error[E0597]: `a` does not live long enough + --> $DIR/borrowing.rs:16:20 + | +LL | let _b = { + | -- borrow later stored here +LL | let a = 3; +LL | || { + | -- value captured here by generator +LL | yield &a + | ^ borrowed value does not live long enough +... +LL | }; + | - `a` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generator/clone-impl-async.rs b/tests/ui/generator/clone-impl-async.rs new file mode 100644 index 000000000..9e9b59d36 --- /dev/null +++ b/tests/ui/generator/clone-impl-async.rs @@ -0,0 +1,70 @@ +// edition:2021 +// gate-test-generator_clone +// Verifies that feature(generator_clone) doesn't allow async blocks to be cloned/copied. + +#![feature(generators, generator_clone)] + +use std::future::ready; + +struct NonClone; + +fn main() { + let inner_non_clone = async { + let non_clone = NonClone; + let () = ready(()).await; + drop(non_clone); + }; + check_copy(&inner_non_clone); + //~^ ERROR : Copy` is not satisfied + check_clone(&inner_non_clone); + //~^ ERROR : Clone` is not satisfied + + let non_clone = NonClone; + let outer_non_clone = async move { + drop(non_clone); + }; + check_copy(&outer_non_clone); + //~^ ERROR : Copy` is not satisfied + check_clone(&outer_non_clone); + //~^ ERROR : Clone` is not satisfied + + let maybe_copy_clone = async move {}; + check_copy(&maybe_copy_clone); + //~^ ERROR : Copy` is not satisfied + check_clone(&maybe_copy_clone); + //~^ ERROR : Clone` is not satisfied + + let inner_non_clone_fn = the_inner_non_clone_fn(); + check_copy(&inner_non_clone_fn); + //~^ ERROR : Copy` is not satisfied + check_clone(&inner_non_clone_fn); + //~^ ERROR : Clone` is not satisfied + + let outer_non_clone_fn = the_outer_non_clone_fn(NonClone); + check_copy(&outer_non_clone_fn); + //~^ ERROR : Copy` is not satisfied + check_clone(&outer_non_clone_fn); + //~^ ERROR : Clone` is not satisfied + + let maybe_copy_clone_fn = the_maybe_copy_clone_fn(); + check_copy(&maybe_copy_clone_fn); + //~^ ERROR : Copy` is not satisfied + check_clone(&maybe_copy_clone_fn); + //~^ ERROR : Clone` is not satisfied +} + +async fn the_inner_non_clone_fn() { + let non_clone = NonClone; + let () = ready(()).await; + drop(non_clone); +} + +async fn the_outer_non_clone_fn(non_clone: NonClone) { + let () = ready(()).await; + drop(non_clone); +} + +async fn the_maybe_copy_clone_fn() {} + +fn check_copy(_x: &T) {} +fn check_clone(_x: &T) {} diff --git a/tests/ui/generator/clone-impl-async.stderr b/tests/ui/generator/clone-impl-async.stderr new file mode 100644 index 000000000..985472887 --- /dev/null +++ b/tests/ui/generator/clone-impl-async.stderr @@ -0,0 +1,171 @@ +error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:17:16 + | +LL | check_copy(&inner_non_clone); + | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-async.rs:69:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:19:17 + | +LL | check_clone(&inner_non_clone); + | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-async.rs:70:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:26:16 + | +LL | check_copy(&outer_non_clone); + | ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-async.rs:69:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:28:17 + | +LL | check_clone(&outer_non_clone); + | ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-async.rs:70:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:32:16 + | +LL | check_copy(&maybe_copy_clone); + | ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-async.rs:69:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:34:17 + | +LL | check_clone(&maybe_copy_clone); + | ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-async.rs:70:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:38:16 + | +LL | check_copy(&inner_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-async.rs:69:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:40:17 + | +LL | check_clone(&inner_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-async.rs:70:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:44:16 + | +LL | check_copy(&outer_non_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-async.rs:69:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:46:17 + | +LL | check_clone(&outer_non_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-async.rs:70:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error[E0277]: the trait bound `impl Future: Copy` is not satisfied + --> $DIR/clone-impl-async.rs:50:16 + | +LL | check_copy(&maybe_copy_clone_fn); + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-async.rs:69:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `impl Future: Clone` is not satisfied + --> $DIR/clone-impl-async.rs:52:17 + | +LL | check_clone(&maybe_copy_clone_fn); + | ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-async.rs:70:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/clone-impl-static.rs b/tests/ui/generator/clone-impl-static.rs new file mode 100644 index 000000000..55ed0f281 --- /dev/null +++ b/tests/ui/generator/clone-impl-static.rs @@ -0,0 +1,17 @@ +// gate-test-generator_clone +// Verifies that static generators cannot be cloned/copied. + +#![feature(generators, generator_clone)] + +fn main() { + let gen = static move || { + yield; + }; + check_copy(&gen); + //~^ ERROR Copy` is not satisfied + check_clone(&gen); + //~^ ERROR Clone` is not satisfied +} + +fn check_copy(_x: &T) {} +fn check_clone(_x: &T) {} diff --git a/tests/ui/generator/clone-impl-static.stderr b/tests/ui/generator/clone-impl-static.stderr new file mode 100644 index 000000000..cbadf6f15 --- /dev/null +++ b/tests/ui/generator/clone-impl-static.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]: Copy` is not satisfied + --> $DIR/clone-impl-static.rs:10:16 + | +LL | check_copy(&gen); + | ---------- ^^^^ the trait `Copy` is not implemented for `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_copy` + --> $DIR/clone-impl-static.rs:16:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]: Clone` is not satisfied + --> $DIR/clone-impl-static.rs:12:17 + | +LL | check_clone(&gen); + | ----------- ^^^^ the trait `Clone` is not implemented for `[static generator@$DIR/clone-impl-static.rs:7:15: 7:29]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check_clone` + --> $DIR/clone-impl-static.rs:17:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/clone-impl.rs b/tests/ui/generator/clone-impl.rs new file mode 100644 index 000000000..cbfd65a53 --- /dev/null +++ b/tests/ui/generator/clone-impl.rs @@ -0,0 +1,73 @@ +// gate-test-generator_clone +// Verifies that non-static generators can be cloned/copied if all their upvars and locals held +// across awaits can be cloned/copied. + +#![feature(generators, generator_clone)] + +struct NonClone; + +fn main() { + let copyable: u32 = 123; + let clonable_0: Vec = Vec::new(); + let clonable_1: Vec = Vec::new(); + let non_clonable: NonClone = NonClone; + + let gen_copy_0 = move || { + yield; + drop(copyable); + }; + check_copy(&gen_copy_0); + check_clone(&gen_copy_0); + let gen_copy_1 = move || { + /* + let v = vec!['a']; + let n = NonClone; + drop(v); + drop(n); + */ + yield; + let v = vec!['a']; + let n = NonClone; + drop(n); + drop(copyable); + }; + check_copy(&gen_copy_1); + check_clone(&gen_copy_1); + let gen_clone_0 = move || { + let v = vec!['a']; + yield; + drop(v); + drop(clonable_0); + }; + check_copy(&gen_clone_0); + //~^ ERROR the trait bound `Vec: Copy` is not satisfied + //~| ERROR the trait bound `Vec: Copy` is not satisfied + check_clone(&gen_clone_0); + let gen_clone_1 = move || { + let v = vec!['a']; + /* + let n = NonClone; + drop(n); + */ + yield; + let n = NonClone; + drop(n); + drop(v); + drop(clonable_1); + }; + check_copy(&gen_clone_1); + //~^ ERROR the trait bound `Vec: Copy` is not satisfied + //~| ERROR the trait bound `Vec: Copy` is not satisfied + check_clone(&gen_clone_1); + let gen_non_clone = move || { + yield; + drop(non_clonable); + }; + check_copy(&gen_non_clone); + //~^ ERROR the trait bound `NonClone: Copy` is not satisfied + check_clone(&gen_non_clone); + //~^ ERROR the trait bound `NonClone: Clone` is not satisfied +} + +fn check_copy(_x: &T) {} +fn check_clone(_x: &T) {} diff --git a/tests/ui/generator/clone-impl.stderr b/tests/ui/generator/clone-impl.stderr new file mode 100644 index 000000000..a92646b19 --- /dev/null +++ b/tests/ui/generator/clone-impl.stderr @@ -0,0 +1,142 @@ +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:36:23: 36:30]` + --> $DIR/clone-impl.rs:42:16 + | +LL | let gen_clone_0 = move || { + | ------- within this `[generator@$DIR/clone-impl.rs:36:23: 36:30]` +... +LL | check_copy(&gen_clone_0); + | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:36:23: 36:30]`, the trait `Copy` is not implemented for `Vec` + | +note: captured value does not implement `Copy` + --> $DIR/clone-impl.rs:40:14 + | +LL | drop(clonable_0); + | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:72:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:36:23: 36:30]` + --> $DIR/clone-impl.rs:42:16 + | +LL | let gen_clone_0 = move || { + | ------- within this `[generator@$DIR/clone-impl.rs:36:23: 36:30]` +... +LL | check_copy(&gen_clone_0); + | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:36:23: 36:30]`, the trait `Copy` is not implemented for `Vec` + | +note: generator does not implement `Copy` as this value is used across a yield + --> $DIR/clone-impl.rs:38:9 + | +LL | let v = vec!['a']; + | - has type `Vec` which does not implement `Copy` +LL | yield; + | ^^^^^ yield occurs here, with `v` maybe used later +... +LL | }; + | - `v` is later dropped here +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:72:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:46:23: 46:30]` + --> $DIR/clone-impl.rs:58:16 + | +LL | let gen_clone_1 = move || { + | ------- within this `[generator@$DIR/clone-impl.rs:46:23: 46:30]` +... +LL | check_copy(&gen_clone_1); + | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:46:23: 46:30]`, the trait `Copy` is not implemented for `Vec` + | +note: captured value does not implement `Copy` + --> $DIR/clone-impl.rs:56:14 + | +LL | drop(clonable_1); + | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:72:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:46:23: 46:30]` + --> $DIR/clone-impl.rs:58:16 + | +LL | let gen_clone_1 = move || { + | ------- within this `[generator@$DIR/clone-impl.rs:46:23: 46:30]` +... +LL | check_copy(&gen_clone_1); + | ^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:46:23: 46:30]`, the trait `Copy` is not implemented for `Vec` + | +note: generator does not implement `Copy` as this value is used across a yield + --> $DIR/clone-impl.rs:52:9 + | +LL | let v = vec!['a']; + | - has type `Vec` which does not implement `Copy` +... +LL | yield; + | ^^^^^ yield occurs here, with `v` maybe used later +... +LL | }; + | - `v` is later dropped here +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:72:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` + +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `[generator@$DIR/clone-impl.rs:62:25: 62:32]` + --> $DIR/clone-impl.rs:66:16 + | +LL | let gen_non_clone = move || { + | ------- within this `[generator@$DIR/clone-impl.rs:62:25: 62:32]` +... +LL | check_copy(&gen_non_clone); + | ^^^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:62:25: 62:32]`, the trait `Copy` is not implemented for `NonClone` + | +note: captured value does not implement `Copy` + --> $DIR/clone-impl.rs:64:14 + | +LL | drop(non_clonable); + | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy` +note: required by a bound in `check_copy` + --> $DIR/clone-impl.rs:72:18 + | +LL | fn check_copy(_x: &T) {} + | ^^^^ required by this bound in `check_copy` +help: consider annotating `NonClone` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `[generator@$DIR/clone-impl.rs:62:25: 62:32]` + --> $DIR/clone-impl.rs:68:17 + | +LL | let gen_non_clone = move || { + | ------- within this `[generator@$DIR/clone-impl.rs:62:25: 62:32]` +... +LL | check_clone(&gen_non_clone); + | ^^^^^^^^^^^^^^ within `[generator@$DIR/clone-impl.rs:62:25: 62:32]`, the trait `Clone` is not implemented for `NonClone` + | +note: captured value does not implement `Clone` + --> $DIR/clone-impl.rs:64:14 + | +LL | drop(non_clonable); + | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone` +note: required by a bound in `check_clone` + --> $DIR/clone-impl.rs:73:19 + | +LL | fn check_clone(_x: &T) {} + | ^^^^^ required by this bound in `check_clone` +help: consider annotating `NonClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/conditional-drop.rs b/tests/ui/generator/conditional-drop.rs new file mode 100644 index 000000000..0927df869 --- /dev/null +++ b/tests/ui/generator/conditional-drop.rs @@ -0,0 +1,61 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static A: AtomicUsize = AtomicUsize::new(0); + +struct B; + +impl Drop for B { + fn drop(&mut self) { + A.fetch_add(1, Ordering::SeqCst); + } +} + + +fn test() -> bool { true } +fn test2() -> bool { false } + +fn main() { + t1(); + t2(); +} + +fn t1() { + let mut a = || { + let b = B; + if test() { + drop(b); + } + yield; + }; + + let n = A.load(Ordering::SeqCst); + Pin::new(&mut a).resume(()); + assert_eq!(A.load(Ordering::SeqCst), n + 1); + Pin::new(&mut a).resume(()); + assert_eq!(A.load(Ordering::SeqCst), n + 1); +} + +fn t2() { + let mut a = || { + let b = B; + if test2() { + drop(b); + } + yield; + }; + + let n = A.load(Ordering::SeqCst); + Pin::new(&mut a).resume(()); + assert_eq!(A.load(Ordering::SeqCst), n); + Pin::new(&mut a).resume(()); + assert_eq!(A.load(Ordering::SeqCst), n + 1); +} diff --git a/tests/ui/generator/control-flow.rs b/tests/ui/generator/control-flow.rs new file mode 100644 index 000000000..4f69c7855 --- /dev/null +++ b/tests/ui/generator/control-flow.rs @@ -0,0 +1,53 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +#![feature(generators, generator_trait)] + +use std::marker::Unpin; +use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; + +fn finish(mut amt: usize, mut t: T) -> T::Return + where T: Generator<(), Yield = ()> + Unpin, +{ + loop { + match Pin::new(&mut t).resume(()) { + GeneratorState::Yielded(()) => amt = amt.checked_sub(1).unwrap(), + GeneratorState::Complete(ret) => { + assert_eq!(amt, 0); + return ret + } + } + } + +} + +fn main() { + finish(1, || yield); + finish(8, || { + for _ in 0..8 { + yield; + } + }); + finish(1, || { + if true { + yield; + } else { + } + }); + finish(1, || { + if false { + } else { + yield; + } + }); + finish(2, || { + if { yield; false } { + yield; + panic!() + } + yield + }); +} diff --git a/tests/ui/generator/derived-drop-parent-expr.rs b/tests/ui/generator/derived-drop-parent-expr.rs new file mode 100644 index 000000000..4bd34346a --- /dev/null +++ b/tests/ui/generator/derived-drop-parent-expr.rs @@ -0,0 +1,17 @@ +// build-pass +// compile-flags:-Zdrop-tracking + +//! Like drop-tracking-parent-expression, but also tests that this doesn't ICE when building MIR +#![feature(generators)] + +fn assert_send(_thing: T) {} + +#[derive(Default)] +pub struct Client { pub nickname: String } + +fn main() { + let g = move || match drop(Client { ..Client::default() }) { + _status => yield, + }; + assert_send(g); +} diff --git a/tests/ui/generator/discriminant.rs b/tests/ui/generator/discriminant.rs new file mode 100644 index 000000000..195e77022 --- /dev/null +++ b/tests/ui/generator/discriminant.rs @@ -0,0 +1,137 @@ +//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are +//! reflected in the output of `mem::discriminant`. + +// run-pass + +#![feature(generators, generator_trait, core_intrinsics, discriminant_kind)] + +use std::intrinsics::discriminant_value; +use std::marker::{Unpin, DiscriminantKind}; +use std::mem::size_of_val; +use std::{cmp, ops::*}; + +macro_rules! yield25 { + ($e:expr) => { + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + }; +} + +/// Yields 250 times. +macro_rules! yield250 { + () => { + yield250!(()) + }; + + ($e:expr) => { + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + }; +} + +fn cycle( + gen: impl Generator<()> + Unpin + DiscriminantKind, + expected_max_discr: u32 +) { + let mut gen = Box::pin(gen); + let mut max_discr = 0; + loop { + max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut())); + match gen.as_mut().resume(()) { + GeneratorState::Yielded(_) => {} + GeneratorState::Complete(_) => { + assert_eq!(max_discr, expected_max_discr); + return; + } + } + } +} + +fn main() { + // Has only one invalid discr. value. + let gen_u8_tiny_niche = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + } + }; + + // Uses all values in the u8 discriminant. + let gen_u8_full = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + yield; // 256 + } + }; + + // Barely needs a u16 discriminant. + let gen_u16 = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + yield; // 256 + yield; // 257 + } + }; + + assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1); + assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche + assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore + assert_eq!(size_of_val(&gen_u8_full()), 1); + assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche + assert_eq!(size_of_val(&gen_u16()), 2); + assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche + + cycle(gen_u8_tiny_niche(), 254); + cycle(gen_u8_full(), 255); + cycle(gen_u16(), 256); +} diff --git a/tests/ui/generator/drop-and-replace.rs b/tests/ui/generator/drop-and-replace.rs new file mode 100644 index 000000000..a9a50a122 --- /dev/null +++ b/tests/ui/generator/drop-and-replace.rs @@ -0,0 +1,45 @@ +// run-pass +// Regression test for incorrect DropAndReplace behavior introduced in #60840 +// and fixed in #61373. When combined with the optimization implemented in +// #60187, this produced incorrect code for generators when a saved local was +// re-assigned. + +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +#[derive(Debug, PartialEq)] +struct Foo(i32); + +impl Drop for Foo { + fn drop(&mut self) { } +} + +fn main() { + let mut a = || { + let mut x = Foo(4); + yield; + assert_eq!(x.0, 4); + + // At one point this tricked our dataflow analysis into thinking `x` was + // StorageDead after the assignment. + x = Foo(5); + assert_eq!(x.0, 5); + + { + let y = Foo(6); + yield; + assert_eq!(y.0, 6); + } + + assert_eq!(x.0, 5); + }; + + loop { + match Pin::new(&mut a).resume(()) { + GeneratorState::Complete(()) => break, + _ => (), + } + } +} diff --git a/tests/ui/generator/drop-control-flow.rs b/tests/ui/generator/drop-control-flow.rs new file mode 100644 index 000000000..c6efda954 --- /dev/null +++ b/tests/ui/generator/drop-control-flow.rs @@ -0,0 +1,139 @@ +// build-pass +// compile-flags: -Zdrop-tracking + +// A test to ensure generators capture values that were conditionally dropped, +// and also that values that are dropped along all paths to a yield do not get +// included in the generator type. + +#![feature(generators, negative_impls)] +#![allow(unused_assignments, dead_code)] + +struct Ptr; +impl<'a> Drop for Ptr { + fn drop(&mut self) {} +} + +struct NonSend; +impl !Send for NonSend {} + +fn assert_send(_: T) {} + +// This test case is reduced from tests/ui/drop/dynamic-drop-async.rs +fn one_armed_if(arg: bool) { + let _ = || { + let arr = [Ptr]; + if arg { + drop(arr); + } + yield; + }; +} + +fn two_armed_if(arg: bool) { + assert_send(|| { + let arr = [Ptr]; + if arg { + drop(arr); + } else { + drop(arr); + } + yield; + }) +} + +fn if_let(arg: Option) { + let _ = || { + let arr = [Ptr]; + if let Some(_) = arg { + drop(arr); + } + yield; + }; +} + +fn init_in_if(arg: bool) { + assert_send(|| { + let mut x = NonSend; + drop(x); + if arg { + x = NonSend; + } else { + yield; + } + }) +} + +fn init_in_match_arm(arg: Option) { + assert_send(|| { + let mut x = NonSend; + drop(x); + match arg { + Some(_) => x = NonSend, + None => yield, + } + }) +} + +fn reinit() { + let _ = || { + let mut arr = [Ptr]; + drop(arr); + arr = [Ptr]; + yield; + }; +} + +fn loop_uninit() { + let _ = || { + let mut arr = [Ptr]; + let mut count = 0; + drop(arr); + while count < 3 { + yield; + arr = [Ptr]; + count += 1; + } + }; +} + +fn nested_loop() { + let _ = || { + let mut arr = [Ptr]; + let mut count = 0; + drop(arr); + while count < 3 { + for _ in 0..3 { + yield; + } + arr = [Ptr]; + count += 1; + } + }; +} + +fn loop_continue(b: bool) { + let _ = || { + let mut arr = [Ptr]; + let mut count = 0; + drop(arr); + while count < 3 { + count += 1; + yield; + if b { + arr = [Ptr]; + continue; + } + } + }; +} + +fn main() { + one_armed_if(true); + if_let(Some(41)); + init_in_if(true); + init_in_match_arm(Some(41)); + reinit(); + loop_uninit(); + nested_loop(); + loop_continue(true); +} diff --git a/tests/ui/generator/drop-env.rs b/tests/ui/generator/drop-env.rs new file mode 100644 index 000000000..66dfb8c2c --- /dev/null +++ b/tests/ui/generator/drop-env.rs @@ -0,0 +1,66 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static A: AtomicUsize = AtomicUsize::new(0); + +struct B; + +impl Drop for B { + fn drop(&mut self) { + A.fetch_add(1, Ordering::SeqCst); + } +} + +fn main() { + t1(); + t2(); + t3(); +} + +fn t1() { + let b = B; + let mut foo = || { + yield; + drop(b); + }; + + let n = A.load(Ordering::SeqCst); + drop(Pin::new(&mut foo).resume(())); + assert_eq!(A.load(Ordering::SeqCst), n); + drop(foo); + assert_eq!(A.load(Ordering::SeqCst), n + 1); +} + +fn t2() { + let b = B; + let mut foo = || { + yield b; + }; + + let n = A.load(Ordering::SeqCst); + drop(Pin::new(&mut foo).resume(())); + assert_eq!(A.load(Ordering::SeqCst), n + 1); + drop(foo); + assert_eq!(A.load(Ordering::SeqCst), n + 1); +} + +fn t3() { + let b = B; + let foo = || { + yield; + drop(b); + }; + + let n = A.load(Ordering::SeqCst); + assert_eq!(A.load(Ordering::SeqCst), n); + drop(foo); + assert_eq!(A.load(Ordering::SeqCst), n + 1); +} diff --git a/tests/ui/generator/drop-track-addassign-yield.rs b/tests/ui/generator/drop-track-addassign-yield.rs new file mode 100644 index 000000000..71cfb170b --- /dev/null +++ b/tests/ui/generator/drop-track-addassign-yield.rs @@ -0,0 +1,41 @@ +// run-pass +// compile-flags: -Zdrop-tracking + +// Based on addassign-yield.rs, but with drop tracking enabled. Originally we did not implement +// the fake_read callback on ExprUseVisitor which caused this case to break. + +#![feature(generators)] + +fn foo() { + let _y = static || { + let x = &mut 0; + *{ + yield; + x + } += match String::new() { + _ => 0, + }; + }; + + // Please don't ever actually write something like this + let _z = static || { + let x = &mut 0; + *{ + let inner = &mut 1; + *{ + yield (); + inner + } += match String::new() { + _ => 1, + }; + yield; + x + } += match String::new() { + _ => 2, + }; + }; +} + +fn main() { + foo() +} diff --git a/tests/ui/generator/drop-tracking-parent-expression.rs b/tests/ui/generator/drop-tracking-parent-expression.rs new file mode 100644 index 000000000..d40f1b8f6 --- /dev/null +++ b/tests/ui/generator/drop-tracking-parent-expression.rs @@ -0,0 +1,69 @@ +// compile-flags: -Zdrop-tracking +#![feature(generators, negative_impls, rustc_attrs)] + +macro_rules! type_combinations { + ( + $( $name:ident => { $( $tt:tt )* } );* $(;)? + ) => { $( + mod $name { + $( $tt )* + + impl !Sync for Client {} + impl !Send for Client {} + } + + // Struct update syntax. This fails because the Client used in the update is considered + // dropped *after* the yield. + { + let g = move || match drop($name::Client { ..$name::Client::default() }) { + //~^ `significant_drop::Client` which is not `Send` + //~| `insignificant_dtor::Client` which is not `Send` + //~| `derived_drop::Client` which is not `Send` + _ => yield, + }; + assert_send(g); + //~^ ERROR cannot be sent between threads + //~| ERROR cannot be sent between threads + //~| ERROR cannot be sent between threads + } + + // Simple owned value. This works because the Client is considered moved into `drop`, + // even though the temporary expression doesn't end until after the yield. + { + let g = move || match drop($name::Client::default()) { + _ => yield, + }; + assert_send(g); + } + )* } +} + +fn assert_send(_thing: T) {} + +fn main() { + type_combinations!( + // OK + copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; + // NOT OK: MIR borrowck thinks that this is used after the yield, even though + // this has no `Drop` impl and only the drops of the fields are observable. + // FIXME: this should compile. + derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; + // NOT OK + significant_drop => { + #[derive(Default)] + pub struct Client; + impl Drop for Client { + fn drop(&mut self) {} + } + }; + // NOT OK (we need to agree with MIR borrowck) + insignificant_dtor => { + #[derive(Default)] + #[rustc_insignificant_dtor] + pub struct Client; + impl Drop for Client { + fn drop(&mut self) {} + } + }; + ); +} diff --git a/tests/ui/generator/drop-tracking-parent-expression.stderr b/tests/ui/generator/drop-tracking-parent-expression.stderr new file mode 100644 index 000000000..fbf5d6e07 --- /dev/null +++ b/tests/ui/generator/drop-tracking-parent-expression.stderr @@ -0,0 +1,128 @@ +error: generator cannot be sent between threads safely + --> $DIR/drop-tracking-parent-expression.rs:24:25 + | +LL | assert_send(g); + | ^ generator is not `Send` +... +LL | / type_combinations!( +LL | | // OK +LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; +LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though +... | +LL | | }; +LL | | ); + | |_____- in this macro invocation + | + = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:18:21: 18:28]`, the trait `Send` is not implemented for `derived_drop::Client` +note: generator is not `Send` as this value is used across a yield + --> $DIR/drop-tracking-parent-expression.rs:22:22 + | +LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `derived_drop::Client` which is not `Send` +... +LL | _ => yield, + | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later +LL | }; + | - `$name::Client::default()` is later dropped here +... +LL | / type_combinations!( +LL | | // OK +LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; +LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though +... | +LL | | }; +LL | | ); + | |_____- in this macro invocation +note: required by a bound in `assert_send` + --> $DIR/drop-tracking-parent-expression.rs:41:19 + | +LL | fn assert_send(_thing: T) {} + | ^^^^ required by this bound in `assert_send` + = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generator cannot be sent between threads safely + --> $DIR/drop-tracking-parent-expression.rs:24:25 + | +LL | assert_send(g); + | ^ generator is not `Send` +... +LL | / type_combinations!( +LL | | // OK +LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; +LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though +... | +LL | | }; +LL | | ); + | |_____- in this macro invocation + | + = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:18:21: 18:28]`, the trait `Send` is not implemented for `significant_drop::Client` +note: generator is not `Send` as this value is used across a yield + --> $DIR/drop-tracking-parent-expression.rs:22:22 + | +LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `significant_drop::Client` which is not `Send` +... +LL | _ => yield, + | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later +LL | }; + | - `$name::Client::default()` is later dropped here +... +LL | / type_combinations!( +LL | | // OK +LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; +LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though +... | +LL | | }; +LL | | ); + | |_____- in this macro invocation +note: required by a bound in `assert_send` + --> $DIR/drop-tracking-parent-expression.rs:41:19 + | +LL | fn assert_send(_thing: T) {} + | ^^^^ required by this bound in `assert_send` + = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generator cannot be sent between threads safely + --> $DIR/drop-tracking-parent-expression.rs:24:25 + | +LL | assert_send(g); + | ^ generator is not `Send` +... +LL | / type_combinations!( +LL | | // OK +LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; +LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though +... | +LL | | }; +LL | | ); + | |_____- in this macro invocation + | + = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:18:21: 18:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client` +note: generator is not `Send` as this value is used across a yield + --> $DIR/drop-tracking-parent-expression.rs:22:22 + | +LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `insignificant_dtor::Client` which is not `Send` +... +LL | _ => yield, + | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later +LL | }; + | - `$name::Client::default()` is later dropped here +... +LL | / type_combinations!( +LL | | // OK +LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; +LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though +... | +LL | | }; +LL | | ); + | |_____- in this macro invocation +note: required by a bound in `assert_send` + --> $DIR/drop-tracking-parent-expression.rs:41:19 + | +LL | fn assert_send(_thing: T) {} + | ^^^^ required by this bound in `assert_send` + = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs b/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs new file mode 100644 index 000000000..646365e43 --- /dev/null +++ b/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs @@ -0,0 +1,12 @@ +// build-pass +// edition:2018 +// compile-flags: -Zdrop-tracking + +#![feature(generators)] + +fn main() { + let _ = static |x: u8| match x { + y if { yield } == y + 1 => (), + _ => (), + }; +} diff --git a/tests/ui/generator/drop-yield-twice.rs b/tests/ui/generator/drop-yield-twice.rs new file mode 100644 index 000000000..f484cbb8d --- /dev/null +++ b/tests/ui/generator/drop-yield-twice.rs @@ -0,0 +1,15 @@ +#![feature(negative_impls, generators)] + +struct Foo(i32); +impl !Send for Foo {} + +fn main() { + assert_send(|| { //~ ERROR generator cannot be sent between threads safely + let guard = Foo(42); + yield; + drop(guard); + yield; + }) +} + +fn assert_send(_: T) {} diff --git a/tests/ui/generator/drop-yield-twice.stderr b/tests/ui/generator/drop-yield-twice.stderr new file mode 100644 index 000000000..0808a2c85 --- /dev/null +++ b/tests/ui/generator/drop-yield-twice.stderr @@ -0,0 +1,31 @@ +error: generator cannot be sent between threads safely + --> $DIR/drop-yield-twice.rs:7:17 + | +LL | assert_send(|| { + | _________________^ +LL | | let guard = Foo(42); +LL | | yield; +LL | | drop(guard); +LL | | yield; +LL | | }) + | |_____^ generator is not `Send` + | + = help: within `[generator@$DIR/drop-yield-twice.rs:7:17: 7:19]`, the trait `Send` is not implemented for `Foo` +note: generator is not `Send` as this value is used across a yield + --> $DIR/drop-yield-twice.rs:9:9 + | +LL | let guard = Foo(42); + | ----- has type `Foo` which is not `Send` +LL | yield; + | ^^^^^ yield occurs here, with `guard` maybe used later +... +LL | }) + | - `guard` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/drop-yield-twice.rs:15:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + diff --git a/tests/ui/generator/dropck-resume.rs b/tests/ui/generator/dropck-resume.rs new file mode 100644 index 000000000..4c18077f3 --- /dev/null +++ b/tests/ui/generator/dropck-resume.rs @@ -0,0 +1,33 @@ +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +struct SetToNone<'a: 'b, 'b>(&'b mut Option<&'a i32>); + +impl<'a, 'b> Drop for SetToNone<'a, 'b> { + fn drop(&mut self) { + *self.0 = None; + } +} + +fn drop_using_generator() -> i32 { + let mut y = Some(&0); + let z = &mut y; + let r; + { + let mut g = move |r| { + let _s = SetToNone(r); + yield; + }; + let mut g = Pin::new(&mut g); + g.as_mut().resume(z); + r = y.as_ref().unwrap(); + //~^ ERROR cannot borrow `y` as immutable because it is also borrowed as mutable + } + **r +} + +fn main() { + println!("{}", drop_using_generator()); +} diff --git a/tests/ui/generator/dropck-resume.stderr b/tests/ui/generator/dropck-resume.stderr new file mode 100644 index 000000000..b0756eb55 --- /dev/null +++ b/tests/ui/generator/dropck-resume.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable + --> $DIR/dropck-resume.rs:25:13 + | +LL | let z = &mut y; + | ------ mutable borrow occurs here +... +LL | r = y.as_ref().unwrap(); + | ^^^^^^^^^^ immutable borrow occurs here +LL | +LL | } + | - mutable borrow might be used here, when `g` is dropped and runs the destructor for generator + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/generator/dropck.rs b/tests/ui/generator/dropck.rs new file mode 100644 index 000000000..f82111a76 --- /dev/null +++ b/tests/ui/generator/dropck.rs @@ -0,0 +1,20 @@ +#![feature(generators, generator_trait)] + +use std::cell::RefCell; +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let (mut gen, cell); + cell = Box::new(RefCell::new(0)); + let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); + //~^ ERROR `*cell` does not live long enough [E0597] + // the upvar is the non-dropck `&mut Option>`. + gen = || { + // but the generator can use it to drop a `Ref<'a, i32>`. + let _d = ref_.take(); //~ ERROR `ref_` does not live long enough + yield; + }; + Pin::new(&mut gen).resume(()); + // drops the RefCell and then the Ref, leading to use-after-free +} diff --git a/tests/ui/generator/dropck.stderr b/tests/ui/generator/dropck.stderr new file mode 100644 index 000000000..7bb188352 --- /dev/null +++ b/tests/ui/generator/dropck.stderr @@ -0,0 +1,34 @@ +error[E0597]: `*cell` does not live long enough + --> $DIR/dropck.rs:10:40 + | +LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); + | ^^^^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `*cell` dropped here while still borrowed + | borrow might be used here, when `gen` is dropped and runs the destructor for generator + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `ref_` does not live long enough + --> $DIR/dropck.rs:15:18 + | +LL | gen = || { + | -- value captured here by generator +LL | // but the generator can use it to drop a `Ref<'a, i32>`. +LL | let _d = ref_.take(); + | ^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `ref_` dropped here while still borrowed + | borrow might be used here, when `gen` is dropped and runs the destructor for generator + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generator/generator-region-requirements.migrate.stderr b/tests/ui/generator/generator-region-requirements.migrate.stderr new file mode 100644 index 000000000..8a96d187f --- /dev/null +++ b/tests/ui/generator/generator-region-requirements.migrate.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/generator-region-requirements.rs:16:51 + | +LL | fn dangle(x: &mut i32) -> &'static mut i32 { + | -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32` +... +LL | GeneratorState::Complete(c) => return c, + | ^ lifetime `'static` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/generator/generator-region-requirements.rs b/tests/ui/generator/generator-region-requirements.rs new file mode 100644 index 000000000..7269a79ca --- /dev/null +++ b/tests/ui/generator/generator-region-requirements.rs @@ -0,0 +1,19 @@ +#![feature(generators, generator_trait)] +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +fn dangle(x: &mut i32) -> &'static mut i32 { + let mut g = || { + yield; + x + }; + loop { + match Pin::new(&mut g).resume(()) { + GeneratorState::Complete(c) => return c, + //~^ ERROR lifetime may not live long enough + GeneratorState::Yielded(_) => (), + } + } +} + +fn main() {} diff --git a/tests/ui/generator/generator-region-requirements.stderr b/tests/ui/generator/generator-region-requirements.stderr new file mode 100644 index 000000000..87f604672 --- /dev/null +++ b/tests/ui/generator/generator-region-requirements.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/generator-region-requirements.rs:12:51 + | +LL | fn dangle(x: &mut i32) -> &'static mut i32 { + | - let's call the lifetime of this reference `'1` +... +LL | GeneratorState::Complete(c) => return c, + | ^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/generator/generator-resume-after-panic.rs b/tests/ui/generator/generator-resume-after-panic.rs new file mode 100644 index 000000000..f2e67f1f7 --- /dev/null +++ b/tests/ui/generator/generator-resume-after-panic.rs @@ -0,0 +1,25 @@ +// run-fail +// needs-unwind +// error-pattern:generator resumed after panicking +// ignore-emscripten no processes + +// Test that we get the correct message for resuming a panicked generator. + +#![feature(generators, generator_trait)] + +use std::{ + ops::Generator, + pin::Pin, + panic, +}; + +fn main() { + let mut g = || { + panic!(); + yield; + }; + panic::catch_unwind(panic::AssertUnwindSafe(|| { + let x = Pin::new(&mut g).resume(()); + })); + Pin::new(&mut g).resume(()); +} diff --git a/tests/ui/generator/generator-with-nll.rs b/tests/ui/generator/generator-with-nll.rs new file mode 100644 index 000000000..cee3e6d22 --- /dev/null +++ b/tests/ui/generator/generator-with-nll.rs @@ -0,0 +1,12 @@ +#![feature(generators)] + +fn main() { + || { + // The reference in `_a` is a Legal with NLL since it ends before the yield + let _a = &mut true; + let b = &mut true; + //~^ borrow may still be in use when generator yields + yield (); + println!("{}", b); + }; +} diff --git a/tests/ui/generator/generator-with-nll.stderr b/tests/ui/generator/generator-with-nll.stderr new file mode 100644 index 000000000..14199aeb9 --- /dev/null +++ b/tests/ui/generator/generator-with-nll.stderr @@ -0,0 +1,12 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/generator-with-nll.rs:7:17 + | +LL | let b = &mut true; + | ^^^^^^^^^ +LL | +LL | yield (); + | -------- possible yield occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/generator/generator-yielding-or-returning-itself.rs b/tests/ui/generator/generator-yielding-or-returning-itself.rs new file mode 100644 index 000000000..30788e3c1 --- /dev/null +++ b/tests/ui/generator/generator-yielding-or-returning-itself.rs @@ -0,0 +1,35 @@ +#![feature(generator_trait)] +#![feature(generators)] + +// Test that we cannot create a generator that returns a value of its +// own type. + +use std::ops::Generator; + +pub fn want_cyclic_generator_return(_: T) + where T: Generator +{ +} + +fn supply_cyclic_generator_return() { + want_cyclic_generator_return(|| { + //~^ ERROR type mismatch + if false { yield None.unwrap(); } + None.unwrap() + }) +} + +pub fn want_cyclic_generator_yield(_: T) + where T: Generator +{ +} + +fn supply_cyclic_generator_yield() { + want_cyclic_generator_yield(|| { + //~^ ERROR type mismatch + if false { yield None.unwrap(); } + None.unwrap() + }) +} + +fn main() { } diff --git a/tests/ui/generator/generator-yielding-or-returning-itself.stderr b/tests/ui/generator/generator-yielding-or-returning-itself.stderr new file mode 100644 index 000000000..8f5d2429a --- /dev/null +++ b/tests/ui/generator/generator-yielding-or-returning-itself.stderr @@ -0,0 +1,53 @@ +error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36]` + --> $DIR/generator-yielding-or-returning-itself.rs:15:34 + | +LL | want_cyclic_generator_return(|| { + | _____----------------------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | if false { yield None.unwrap(); } +LL | | None.unwrap() +LL | | }) + | |_____^ cyclic type of infinite size + | + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see issue #46062 + for more information +note: required by a bound in `want_cyclic_generator_return` + --> $DIR/generator-yielding-or-returning-itself.rs:10:36 + | +LL | pub fn want_cyclic_generator_return(_: T) + | ---------------------------- required by a bound in this +LL | where T: Generator + | ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return` + +error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35]` + --> $DIR/generator-yielding-or-returning-itself.rs:28:33 + | +LL | want_cyclic_generator_yield(|| { + | _____---------------------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | if false { yield None.unwrap(); } +LL | | None.unwrap() +LL | | }) + | |_____^ cyclic type of infinite size + | + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see issue #46062 + for more information +note: required by a bound in `want_cyclic_generator_yield` + --> $DIR/generator-yielding-or-returning-itself.rs:23:24 + | +LL | pub fn want_cyclic_generator_yield(_: T) + | --------------------------- required by a bound in this +LL | where T: Generator + | ^^^^^^^^^ required by this bound in `want_cyclic_generator_yield` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generator/issue-102645.rs b/tests/ui/generator/issue-102645.rs new file mode 100644 index 000000000..35acd5cd7 --- /dev/null +++ b/tests/ui/generator/issue-102645.rs @@ -0,0 +1,23 @@ +// compile-flags: -Zdrop-tracking + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let mut a = 5; + let mut b = || { + let d = 6; + yield; + _zzz(); // #break + a = d; + }; + Pin::new(&mut b).resume(); + //~^ ERROR this method takes 1 argument but 0 arguments were supplied + // This type error is required to reproduce the ICE... +} + +fn _zzz() { + () +} diff --git a/tests/ui/generator/issue-102645.stderr b/tests/ui/generator/issue-102645.stderr new file mode 100644 index 000000000..f6d244029 --- /dev/null +++ b/tests/ui/generator/issue-102645.stderr @@ -0,0 +1,16 @@ +error[E0061]: this method takes 1 argument but 0 arguments were supplied + --> $DIR/issue-102645.rs:16:22 + | +LL | Pin::new(&mut b).resume(); + | ^^^^^^-- an argument of type `()` is missing + | +note: associated function defined here + --> $SRC_DIR/core/src/ops/generator.rs:LL:COL +help: provide the argument + | +LL | Pin::new(&mut b).resume(()); + | ~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/generator/issue-44197.rs b/tests/ui/generator/issue-44197.rs new file mode 100644 index 000000000..389b9d139 --- /dev/null +++ b/tests/ui/generator/issue-44197.rs @@ -0,0 +1,36 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +fn foo(_: &str) -> String { + String::new() +} + +fn bar(baz: String) -> impl Generator<(), Yield = String, Return = ()> { + move || { + yield foo(&baz); + } +} + +fn foo2(_: &str) -> Result { + Err(()) +} + +fn bar2(baz: String) -> impl Generator<(), Yield = String, Return = ()> { + move || { + if let Ok(quux) = foo2(&baz) { + yield quux; + } + } +} + +fn main() { + assert_eq!( + Pin::new(&mut bar(String::new())).resume(()), + GeneratorState::Yielded(String::new()) + ); + assert_eq!(Pin::new(&mut bar2(String::new())).resume(()), GeneratorState::Complete(())); +} diff --git a/tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr b/tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr new file mode 100644 index 000000000..3afbea079 --- /dev/null +++ b/tests/ui/generator/issue-45729-unsafe-in-generator.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45729-unsafe-in-generator.rs:8:9 + | +LL | *(1 as *mut u32) = 42; + | ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/generator/issue-45729-unsafe-in-generator.rs b/tests/ui/generator/issue-45729-unsafe-in-generator.rs new file mode 100644 index 000000000..379c36d2c --- /dev/null +++ b/tests/ui/generator/issue-45729-unsafe-in-generator.rs @@ -0,0 +1,12 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(generators)] + +fn main() { + let _ = || { + *(1 as *mut u32) = 42; + //~^ ERROR dereference of raw pointer is unsafe + yield; + }; +} diff --git a/tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr b/tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr new file mode 100644 index 000000000..10d768f19 --- /dev/null +++ b/tests/ui/generator/issue-45729-unsafe-in-generator.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45729-unsafe-in-generator.rs:8:9 + | +LL | *(1 as *mut u32) = 42; + | ^^^^^^^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/generator/issue-48048.rs b/tests/ui/generator/issue-48048.rs new file mode 100644 index 000000000..992bbc97a --- /dev/null +++ b/tests/ui/generator/issue-48048.rs @@ -0,0 +1,13 @@ +#![feature(generators)] + +fn main() { + let x = (|_| {},); + + || { + let x = x; + + x.0({ //~ ERROR borrow may still be in use when generator yields + yield; + }); + }; +} diff --git a/tests/ui/generator/issue-48048.stderr b/tests/ui/generator/issue-48048.stderr new file mode 100644 index 000000000..234235839 --- /dev/null +++ b/tests/ui/generator/issue-48048.stderr @@ -0,0 +1,11 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/issue-48048.rs:9:9 + | +LL | x.0({ + | ^^^ +LL | yield; + | ----- possible yield occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/generator/issue-52304.rs b/tests/ui/generator/issue-52304.rs new file mode 100644 index 000000000..3e9de765b --- /dev/null +++ b/tests/ui/generator/issue-52304.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +pub fn example() -> impl Generator { + || yield &1 +} + +fn main() {} diff --git a/tests/ui/generator/issue-52398.rs b/tests/ui/generator/issue-52398.rs new file mode 100644 index 000000000..ada380d11 --- /dev/null +++ b/tests/ui/generator/issue-52398.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_variables)] + +#![feature(generators)] + +use std::cell::RefCell; + +struct A; + +impl A { + fn test(&self, a: ()) {} +} + +fn main() { + // Test that the MIR local with type &A created for the auto-borrow adjustment + // is caught by typeck + move || { //~ WARN unused generator that must be used + A.test(yield); + }; + + // Test that the std::cell::Ref temporary returned from the `borrow` call + // is caught by typeck + let y = RefCell::new(true); + static move || { //~ WARN unused generator that must be used + yield *y.borrow(); + return "Done"; + }; +} diff --git a/tests/ui/generator/issue-52398.stderr b/tests/ui/generator/issue-52398.stderr new file mode 100644 index 000000000..539343275 --- /dev/null +++ b/tests/ui/generator/issue-52398.stderr @@ -0,0 +1,24 @@ +warning: unused generator that must be used + --> $DIR/issue-52398.rs:17:5 + | +LL | / move || { +LL | | A.test(yield); +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: unused generator that must be used + --> $DIR/issue-52398.rs:24:5 + | +LL | / static move || { +LL | | yield *y.borrow(); +LL | | return "Done"; +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + +warning: 2 warnings emitted + diff --git a/tests/ui/generator/issue-53548-1.rs b/tests/ui/generator/issue-53548-1.rs new file mode 100644 index 000000000..173ae3c6f --- /dev/null +++ b/tests/ui/generator/issue-53548-1.rs @@ -0,0 +1,20 @@ +// A variant of #53548 that does not actually require generators, +// but which encountered the same ICE/error. See `issue-53548.rs` +// for details. +// +// check-pass + +use std::cell::RefCell; +use std::rc::Rc; + +trait Trait: 'static {} + +struct Store { + inner: Rc>>, +} + +fn main() { + let store = Store:: fn(&(dyn Trait + 'a))>> { + inner: Default::default(), + }; +} diff --git a/tests/ui/generator/issue-53548.rs b/tests/ui/generator/issue-53548.rs new file mode 100644 index 000000000..3ebabb914 --- /dev/null +++ b/tests/ui/generator/issue-53548.rs @@ -0,0 +1,38 @@ +// Regression test for #53548. The `Box` type below is +// expanded to `Box`, but the generator "witness" +// that results is `for<'r> { Box }`. The WF code was +// encountering an ICE (when debug-assertions were enabled) and an +// unexpected compilation error (without debug-asserions) when trying +// to process this `'r` region bound. In particular, to be WF, the +// region bound must meet the requirements of the trait, and hence we +// got `for<'r> { 'r: 'static }`. This would ICE because the `Binder` +// constructor we were using was assering that no higher-ranked +// regions were involved (because the WF code is supposed to skip +// those). The error (if debug-asserions were disabled) came because +// we obviously cannot prove that `'r: 'static` for any region `'r`. +// Pursuant with our "lazy WF" strategy for higher-ranked regions, the +// fix is not to require that `for<'r> { 'r: 'static }` holds (this is +// also analogous to what we would do for higher-ranked regions +// appearing within the trait in other positions). +// +// check-pass + +#![feature(generators)] + +use std::cell::RefCell; +use std::rc::Rc; + +trait Trait: 'static {} + +struct Store { + inner: Rc>>, +} + +fn main() { + Box::new(static move || { + let store = Store::> { + inner: Default::default(), + }; + yield (); + }); +} diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/generator/issue-57017.rs new file mode 100644 index 000000000..c0bde3b44 --- /dev/null +++ b/tests/ui/generator/issue-57017.rs @@ -0,0 +1,55 @@ +// build-pass +// compile-flags: -Zdrop-tracking +#![feature(generators, negative_impls)] + +macro_rules! type_combinations { + ( + $( $name:ident => { $( $tt:tt )* } );* + ) => { $( + mod $name { + pub mod unsync { + $( $tt )* + + impl !Sync for Client {} + } + pub mod unsend { + $( $tt )* + + impl !Send for Client {} + } + } + + // This is the same bug as issue 57017, but using yield instead of await + { + let g = move || match drop(&$name::unsync::Client::default()) { + _status => yield, + }; + assert_send(g); + } + + // This tests that `Client` is properly considered to be dropped after moving it into the + // function. + { + let g = move || match drop($name::unsend::Client::default()) { + _status => yield, + }; + assert_send(g); + } + )* } +} + +fn assert_send(_thing: T) {} + +fn main() { + type_combinations!( + copy => { #[derive(Copy, Clone, Default)] pub struct Client; }; + derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } }; + significant_drop => { + #[derive(Default)] + pub struct Client; + impl Drop for Client { + fn drop(&mut self) {} + } + } + ); +} diff --git a/tests/ui/generator/issue-57084.rs b/tests/ui/generator/issue-57084.rs new file mode 100644 index 000000000..2a5c3dd05 --- /dev/null +++ b/tests/ui/generator/issue-57084.rs @@ -0,0 +1,28 @@ +// This issue reproduces an ICE on compile (E.g. fails on 2018-12-19 nightly). +// "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '_#1r" +// run-pass +// edition:2018 +#![feature(generators,generator_trait)] +use std::ops::Generator; + +fn with(f: F) -> impl Generator +where F: Fn() -> () +{ + move || { + loop { + match f() { + _ => yield, + } + } + } +} + +fn main() { + let data = &vec![1]; + || { //~ WARN unused generator that must be used + let _to_pin = with(move || println!("{:p}", data)); + loop { + yield + } + }; +} diff --git a/tests/ui/generator/issue-57084.stderr b/tests/ui/generator/issue-57084.stderr new file mode 100644 index 000000000..8f1fc5e80 --- /dev/null +++ b/tests/ui/generator/issue-57084.stderr @@ -0,0 +1,16 @@ +warning: unused generator that must be used + --> $DIR/issue-57084.rs:22:5 + | +LL | / || { +LL | | let _to_pin = with(move || println!("{:p}", data)); +LL | | loop { +LL | | yield +LL | | } +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/issue-57478.rs b/tests/ui/generator/issue-57478.rs new file mode 100644 index 000000000..91407ea18 --- /dev/null +++ b/tests/ui/generator/issue-57478.rs @@ -0,0 +1,17 @@ +// check-pass +// compile-flags: -Zdrop-tracking + +#![feature(negative_impls, generators)] + +struct Foo; +impl !Send for Foo {} + +fn main() { + assert_send(|| { + let guard = Foo; + drop(guard); + yield; + }) +} + +fn assert_send(_: T) {} diff --git a/tests/ui/generator/issue-58888.rs b/tests/ui/generator/issue-58888.rs new file mode 100644 index 000000000..d42d09d40 --- /dev/null +++ b/tests/ui/generator/issue-58888.rs @@ -0,0 +1,28 @@ +// run-pass +// compile-flags: -g +// ignore-asmjs wasm2js does not support source maps yet + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +struct Database; + +impl Database { + fn get_connection(&self) -> impl Iterator { + Some(()).into_iter() + } + + fn check_connection(&self) -> impl Generator + '_ { + move || { + let iter = self.get_connection(); + for i in iter { + yield i + } + } + } +} + +fn main() { + Database.check_connection(); +} diff --git a/tests/ui/generator/issue-61442-stmt-expr-with-drop.rs b/tests/ui/generator/issue-61442-stmt-expr-with-drop.rs new file mode 100644 index 000000000..187c37402 --- /dev/null +++ b/tests/ui/generator/issue-61442-stmt-expr-with-drop.rs @@ -0,0 +1,32 @@ +// Test that we don't consider temporaries for statement expressions as live +// across yields + +// check-pass +// edition:2018 + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +async fn drop_and_await() { + async {}; + async {}.await; +} + +fn drop_and_yield() { + let x = || { + String::new(); + yield; + }; + Box::pin(x).as_mut().resume(()); + let y = static || { + String::new(); + yield; + }; + Box::pin(y).as_mut().resume(()); +} + +fn main() { + drop_and_await(); + drop_and_yield(); +} diff --git a/tests/ui/generator/issue-62506-two_awaits.rs b/tests/ui/generator/issue-62506-two_awaits.rs new file mode 100644 index 000000000..672e16b78 --- /dev/null +++ b/tests/ui/generator/issue-62506-two_awaits.rs @@ -0,0 +1,17 @@ +// Output = String caused an ICE whereas Output = &'static str compiled successfully. +// Broken MIR: generator contains type std::string::String in MIR, +// but typeck only knows about {::Future, ()} +// check-pass +// edition:2018 + +use std::future::Future; + +pub trait T { + type Future: Future; + fn bar() -> Self::Future; +} +pub async fn foo() where S: T { + S::bar().await; + S::bar().await; +} +pub fn main() {} diff --git a/tests/ui/generator/issue-64620-yield-array-element.rs b/tests/ui/generator/issue-64620-yield-array-element.rs new file mode 100644 index 000000000..2cbe8f516 --- /dev/null +++ b/tests/ui/generator/issue-64620-yield-array-element.rs @@ -0,0 +1,9 @@ +// Regression test for #64620 + +#![feature(generators)] + +pub fn crash(arr: [usize; 1]) { + yield arr[0]; //~ ERROR: yield expression outside of generator literal +} + +fn main() {} diff --git a/tests/ui/generator/issue-64620-yield-array-element.stderr b/tests/ui/generator/issue-64620-yield-array-element.stderr new file mode 100644 index 000000000..48383c2ed --- /dev/null +++ b/tests/ui/generator/issue-64620-yield-array-element.stderr @@ -0,0 +1,9 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/issue-64620-yield-array-element.rs:6:5 + | +LL | yield arr[0]; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/generator/issue-68112.rs b/tests/ui/generator/issue-68112.rs new file mode 100644 index 000000000..21026f45c --- /dev/null +++ b/tests/ui/generator/issue-68112.rs @@ -0,0 +1,71 @@ +#![feature(generators, generator_trait)] + +use std::{ + cell::RefCell, + sync::Arc, + pin::Pin, + ops::{Generator, GeneratorState}, +}; + +pub struct Ready(Option); +impl Generator<()> for Ready { + type Return = T; + type Yield = (); + fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> { + GeneratorState::Complete(self.0.take().unwrap()) + } +} +pub fn make_gen1(t: T) -> Ready { + Ready(Some(t)) +} + +fn require_send(_: impl Send) {} +//~^ NOTE required by a bound +//~| NOTE required by a bound +//~| NOTE required by this bound +//~| NOTE required by this bound + +fn make_non_send_generator() -> impl Generator>> { + make_gen1(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_gen = || { + let _non_send_gen = make_non_send_generator(); + //~^ NOTE not `Send` + yield; + //~^ NOTE yield occurs here + //~| NOTE value is used across a yield + }; //~ NOTE later dropped here + require_send(send_gen); + //~^ ERROR generator cannot be sent between threads + //~| NOTE not `Send` +} + +pub fn make_gen2(t: T) -> impl Generator { +//~^ NOTE appears within the type +//~| NOTE expansion of desugaring + || { //~ NOTE used within this generator + yield; + t + } +} +fn make_non_send_generator2() -> impl Generator>> { //~ NOTE appears within the type +//~^ NOTE expansion of desugaring + make_gen2(Arc::new(RefCell::new(0))) +} + +fn test2() { + let send_gen = || { //~ NOTE used within this generator + let _non_send_gen = make_non_send_generator2(); + yield; + }; + require_send(send_gen); + //~^ ERROR `RefCell` cannot be shared between threads safely + //~| NOTE `RefCell` cannot be shared between threads safely + //~| NOTE required for + //~| NOTE required by a bound introduced by this call + //~| NOTE captures the following types +} + +fn main() {} diff --git a/tests/ui/generator/issue-68112.stderr b/tests/ui/generator/issue-68112.stderr new file mode 100644 index 000000000..eb99d42c9 --- /dev/null +++ b/tests/ui/generator/issue-68112.stderr @@ -0,0 +1,64 @@ +error: generator cannot be sent between threads safely + --> $DIR/issue-68112.rs:40:18 + | +LL | require_send(send_gen); + | ^^^^^^^^ generator is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell` +note: generator is not `Send` as this value is used across a yield + --> $DIR/issue-68112.rs:36:9 + | +LL | let _non_send_gen = make_non_send_generator(); + | ------------- has type `impl Generator>>` which is not `Send` +LL | +LL | yield; + | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later +... +LL | }; + | - `_non_send_gen` is later dropped here +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:22:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `RefCell` cannot be shared between threads safely + --> $DIR/issue-68112.rs:63:18 + | +LL | require_send(send_gen); + | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `RefCell` + = note: required for `Arc>` to implement `Send` +note: required because it's used within this generator + --> $DIR/issue-68112.rs:48:5 + | +LL | || { + | ^^ +note: required because it appears within the type `impl Generator>>` + --> $DIR/issue-68112.rs:45:30 + | +LL | pub fn make_gen2(t: T) -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `impl Generator>>` + --> $DIR/issue-68112.rs:53:34 + | +LL | fn make_non_send_generator2() -> impl Generator>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `impl Generator>>`, `()` +note: required because it's used within this generator + --> $DIR/issue-68112.rs:59:20 + | +LL | let send_gen = || { + | ^^ +note: required by a bound in `require_send` + --> $DIR/issue-68112.rs:22:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/issue-69017.rs b/tests/ui/generator/issue-69017.rs new file mode 100644 index 000000000..511deb60e --- /dev/null +++ b/tests/ui/generator/issue-69017.rs @@ -0,0 +1,18 @@ +// This issue reproduces an ICE on compile +// Fails on 2020-02-08 nightly +// regressed commit: https://github.com/rust-lang/rust/commit/f8fd4624474a68bd26694eff3536b9f3a127b2d3 +// +// check-pass + +#![feature(generator_trait)] +#![feature(generators)] + +use std::ops::Generator; + +fn gen() -> impl Generator { + |_: usize| { + println!("-> {}", yield); + } +} + +fn main() {} diff --git a/tests/ui/generator/issue-69039.rs b/tests/ui/generator/issue-69039.rs new file mode 100644 index 000000000..ccc141860 --- /dev/null +++ b/tests/ui/generator/issue-69039.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; + +fn mkstr(my_name: String, my_mood: String) -> String { + format!("{} is {}", my_name.trim(), my_mood.trim()) +} + +fn my_scenario() -> impl Generator { + |_arg: String| { + let my_name = yield "What is your name?"; + let my_mood = yield "How are you feeling?"; + mkstr(my_name, my_mood) + } +} + +fn main() { + let mut my_session = Box::pin(my_scenario()); + + assert_eq!( + my_session.as_mut().resume("_arg".to_string()), + GeneratorState::Yielded("What is your name?") + ); + assert_eq!( + my_session.as_mut().resume("Your Name".to_string()), + GeneratorState::Yielded("How are you feeling?") + ); + assert_eq!( + my_session.as_mut().resume("Sensory Organs".to_string()), + GeneratorState::Complete("Your Name is Sensory Organs".to_string()) + ); +} diff --git a/tests/ui/generator/issue-87142.rs b/tests/ui/generator/issue-87142.rs new file mode 100644 index 000000000..fc10d04d4 --- /dev/null +++ b/tests/ui/generator/issue-87142.rs @@ -0,0 +1,32 @@ +// compile-flags: -Cdebuginfo=2 +// build-pass + +// Regression test for #87142 +// This test needs the above flags and the "lib" crate type. + +#![feature(type_alias_impl_trait, generator_trait, generators)] +#![crate_type = "lib"] + +use std::ops::Generator; + +pub trait GeneratorProviderAlt: Sized { + type Gen: Generator<(), Return = (), Yield = ()>; + + fn start(ctx: Context) -> Self::Gen; +} + +pub struct Context { + pub link: Box, +} + +impl GeneratorProviderAlt for () { + type Gen = impl Generator<(), Return = (), Yield = ()>; + fn start(ctx: Context) -> Self::Gen { + move || { + match ctx { + _ => (), + } + yield (); + } + } +} diff --git a/tests/ui/generator/issue-88653.rs b/tests/ui/generator/issue-88653.rs new file mode 100644 index 000000000..1d9377bce --- /dev/null +++ b/tests/ui/generator/issue-88653.rs @@ -0,0 +1,22 @@ +// Regression test for #88653, where a confusing warning about a +// type mismatch in generator arguments was issued. + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn foo(bar: bool) -> impl Generator<(bool,)> { + //~^ ERROR: type mismatch in generator arguments [E0631] + //~| NOTE: expected due to this + //~| NOTE: expected generator signature `fn((bool,)) -> _` + //~| NOTE: in this expansion of desugaring of `impl Trait` + //~| NOTE: in this expansion of desugaring of `impl Trait` + |bar| { + //~^ NOTE: found signature defined here + if bar { + yield bar; + } + } +} + +fn main() {} diff --git a/tests/ui/generator/issue-88653.stderr b/tests/ui/generator/issue-88653.stderr new file mode 100644 index 000000000..b742c6e2f --- /dev/null +++ b/tests/ui/generator/issue-88653.stderr @@ -0,0 +1,15 @@ +error[E0631]: type mismatch in generator arguments + --> $DIR/issue-88653.rs:8:22 + | +LL | fn foo(bar: bool) -> impl Generator<(bool,)> { + | ^^^^^^^^^^^^^^^^^^^^^^^ expected due to this +... +LL | |bar| { + | ----- found signature defined here + | + = note: expected generator signature `fn((bool,)) -> _` + found generator signature `fn(bool) -> _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/generator/issue-91477.rs b/tests/ui/generator/issue-91477.rs new file mode 100644 index 000000000..6c027feb4 --- /dev/null +++ b/tests/ui/generator/issue-91477.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +fn foo() -> impl Sized { + yield 1; //~ ERROR E0627 +} + +fn main() {} diff --git a/tests/ui/generator/issue-91477.stderr b/tests/ui/generator/issue-91477.stderr new file mode 100644 index 000000000..4597dc1bc --- /dev/null +++ b/tests/ui/generator/issue-91477.stderr @@ -0,0 +1,9 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/issue-91477.rs:4:5 + | +LL | yield 1; + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/generator/issue-93161.rs b/tests/ui/generator/issue-93161.rs new file mode 100644 index 000000000..92305609c --- /dev/null +++ b/tests/ui/generator/issue-93161.rs @@ -0,0 +1,94 @@ +// edition:2021 +// run-pass +// compile-flags: -Zdrop-tracking + +#![feature(never_type)] + +use std::future::Future; + +// See if we can run a basic `async fn` +pub async fn foo(x: &u32, y: u32) -> u32 { + let y = &y; + let z = 9; + let z = &z; + let y = async { *y + *z }.await; + let a = 10; + let a = &a; + *x + y + *a +} + +async fn add(x: u32, y: u32) -> u32 { + let a = async { x + y }; + a.await +} + +async fn build_aggregate(a: u32, b: u32, c: u32, d: u32) -> u32 { + let x = (add(a, b).await, add(c, d).await); + x.0 + x.1 +} + +enum Never {} +fn never() -> Never { + panic!() +} + +async fn includes_never(crash: bool, x: u32) -> u32 { + let result = async { x * x }.await; + if !crash { + return result; + } + #[allow(unused)] + let bad = never(); + result *= async { x + x }.await; + drop(bad); + result +} + +async fn partial_init(x: u32) -> u32 { + #[allow(unreachable_code)] + let _x: (String, !) = (String::new(), return async { x + x }.await); +} + +async fn read_exact(_from: &mut &[u8], _to: &mut [u8]) -> Option<()> { + Some(()) +} + +async fn hello_world() { + let data = [0u8; 1]; + let mut reader = &data[..]; + + let mut marker = [0u8; 1]; + read_exact(&mut reader, &mut marker).await.unwrap(); +} + +fn run_fut(fut: impl Future) -> T { + use std::sync::Arc; + use std::task::{Context, Poll, Wake, Waker}; + + struct MyWaker; + impl Wake for MyWaker { + fn wake(self: Arc) { + unimplemented!() + } + } + + let waker = Waker::from(Arc::new(MyWaker)); + let mut context = Context::from_waker(&waker); + + let mut pinned = Box::pin(fut); + loop { + match pinned.as_mut().poll(&mut context) { + Poll::Pending => continue, + Poll::Ready(v) => return v, + } + } +} + +fn main() { + let x = 5; + assert_eq!(run_fut(foo(&x, 7)), 31); + assert_eq!(run_fut(build_aggregate(1, 2, 3, 4)), 10); + assert_eq!(run_fut(includes_never(false, 4)), 16); + assert_eq!(run_fut(partial_init(4)), 8); + run_fut(hello_world()); +} diff --git a/tests/ui/generator/iterator-count.rs b/tests/ui/generator/iterator-count.rs new file mode 100644 index 000000000..90eefe02f --- /dev/null +++ b/tests/ui/generator/iterator-count.rs @@ -0,0 +1,44 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::marker::Unpin; +use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; + +struct W(T); + +// This impl isn't safe in general, but the generator used in this test is movable +// so it won't cause problems. +impl + Unpin> Iterator for W { + type Item = T::Yield; + + fn next(&mut self) -> Option { + match Pin::new(&mut self.0).resume(()) { + GeneratorState::Complete(..) => None, + GeneratorState::Yielded(v) => Some(v), + } + } +} + +fn test() -> impl Generator<(), Return=(), Yield=u8> + Unpin { + || { + for i in 1..6 { + yield i + } + } +} + +fn main() { + let end = 11; + + let closure_test = |start| { + move || { + for i in start..end { + yield i + } + } + }; + + assert!(W(test()).chain(W(closure_test(6))).eq(1..11)); +} diff --git a/tests/ui/generator/layout-error.rs b/tests/ui/generator/layout-error.rs new file mode 100644 index 000000000..7c3d18740 --- /dev/null +++ b/tests/ui/generator/layout-error.rs @@ -0,0 +1,28 @@ +// Verifies that computing a layout of a generator tainted by type errors +// doesn't ICE. Regression test for #80998. +// +// edition:2018 + +#![feature(type_alias_impl_trait)] +use std::future::Future; + +pub struct Task(F); +impl Task { + const fn new() -> Self { + todo!() + } + fn spawn(&self, _: impl FnOnce() -> F) { + todo!() + } +} + +fn main() { + async fn cb() { + let a = Foo; //~ ERROR cannot find value `Foo` in this scope + } + + type F = impl Future; + // Check that statics are inhabited computes they layout. + static POOL: Task = Task::new(); + Task::spawn(&POOL, || cb()); +} diff --git a/tests/ui/generator/layout-error.stderr b/tests/ui/generator/layout-error.stderr new file mode 100644 index 000000000..b1a258f4f --- /dev/null +++ b/tests/ui/generator/layout-error.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/layout-error.rs:21:17 + | +LL | let a = Foo; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/generator/live-upvar-across-yield.rs b/tests/ui/generator/live-upvar-across-yield.rs new file mode 100644 index 000000000..6a2e42a55 --- /dev/null +++ b/tests/ui/generator/live-upvar-across-yield.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let b = |_| 3; + let mut a = || { + b(yield); + }; + Pin::new(&mut a).resume(()); +} diff --git a/tests/ui/generator/match-bindings.rs b/tests/ui/generator/match-bindings.rs new file mode 100644 index 000000000..865904a57 --- /dev/null +++ b/tests/ui/generator/match-bindings.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +#![feature(generators)] + +enum Enum { + A(String), + B +} + +fn main() { + || { //~ WARN unused generator that must be used + loop { + if let true = true { + match Enum::A(String::new()) { + Enum::A(_var) => {} + Enum::B => {} + } + } + yield; + } + }; +} diff --git a/tests/ui/generator/match-bindings.stderr b/tests/ui/generator/match-bindings.stderr new file mode 100644 index 000000000..3dd2d5954 --- /dev/null +++ b/tests/ui/generator/match-bindings.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/match-bindings.rs:12:5 + | +LL | / || { +LL | | loop { +LL | | if let true = true { +LL | | match Enum::A(String::new()) { +... | +LL | | } +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/metadata-sufficient-for-layout.rs b/tests/ui/generator/metadata-sufficient-for-layout.rs new file mode 100644 index 000000000..d0e648ee7 --- /dev/null +++ b/tests/ui/generator/metadata-sufficient-for-layout.rs @@ -0,0 +1,25 @@ +// Check that the layout of a generator is available when auxiliary crate +// is compiled with --emit metadata. +// +// Regression test for #80998. +// +// aux-build:metadata-sufficient-for-layout.rs + +#![feature(type_alias_impl_trait, rustc_attrs)] +#![feature(generator_trait)] + +extern crate metadata_sufficient_for_layout; + +use std::ops::Generator; + +type F = impl Generator<(), Yield = (), Return = ()>; + +// Static queries the layout of the generator. +static A: Option = None; + +fn f() -> F { + metadata_sufficient_for_layout::g() +} + +#[rustc_error] +fn main() {} //~ ERROR diff --git a/tests/ui/generator/metadata-sufficient-for-layout.stderr b/tests/ui/generator/metadata-sufficient-for-layout.stderr new file mode 100644 index 000000000..3488b04f2 --- /dev/null +++ b/tests/ui/generator/metadata-sufficient-for-layout.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/metadata-sufficient-for-layout.rs:25:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/generator/nested_generators.rs b/tests/ui/generator/nested_generators.rs new file mode 100644 index 000000000..45519150e --- /dev/null +++ b/tests/ui/generator/nested_generators.rs @@ -0,0 +1,21 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +fn main() { + let _generator = || { + let mut sub_generator = || { + yield 2; + }; + + match Pin::new(&mut sub_generator).resume(()) { + GeneratorState::Yielded(x) => { + yield x; + } + _ => panic!(), + }; + }; +} diff --git a/tests/ui/generator/niche-in-generator.rs b/tests/ui/generator/niche-in-generator.rs new file mode 100644 index 000000000..42bee81f5 --- /dev/null +++ b/tests/ui/generator/niche-in-generator.rs @@ -0,0 +1,19 @@ +// Test that niche finding works with captured generator upvars. + +// run-pass + +#![feature(generators)] + +use std::mem::size_of_val; + +fn take(_: T) {} + +fn main() { + let x = false; + let gen1 = || { + yield; + take(x); + }; + + assert_eq!(size_of_val(&gen1), size_of_val(&Some(gen1))); +} diff --git a/tests/ui/generator/non-static-is-unpin.rs b/tests/ui/generator/non-static-is-unpin.rs new file mode 100644 index 000000000..96d0a8e28 --- /dev/null +++ b/tests/ui/generator/non-static-is-unpin.rs @@ -0,0 +1,18 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::marker::{PhantomPinned, Unpin}; + +fn assert_unpin(_: G) { +} + +fn main() { + // Even though this generator holds a `PhantomPinned` in its environment, it + // remains `Unpin`. + assert_unpin(|| { + let pinned = PhantomPinned; + yield; + drop(pinned); + }); +} diff --git a/tests/ui/generator/not-send-sync.rs b/tests/ui/generator/not-send-sync.rs new file mode 100644 index 000000000..8ca5565fb --- /dev/null +++ b/tests/ui/generator/not-send-sync.rs @@ -0,0 +1,21 @@ +#![feature(generators)] + +use std::cell::Cell; + +fn main() { + fn assert_sync(_: T) {} + fn assert_send(_: T) {} + + assert_sync(|| { + //~^ ERROR: generator cannot be shared between threads safely + let a = Cell::new(2); + yield; + }); + + let a = Cell::new(2); + assert_send(|| { + //~^ ERROR: E0277 + drop(&a); + yield; + }); +} diff --git a/tests/ui/generator/not-send-sync.stderr b/tests/ui/generator/not-send-sync.stderr new file mode 100644 index 000000000..a821c57b9 --- /dev/null +++ b/tests/ui/generator/not-send-sync.stderr @@ -0,0 +1,56 @@ +error[E0277]: `Cell` cannot be shared between threads safely + --> $DIR/not-send-sync.rs:16:17 + | +LL | assert_send(|| { + | _____-----------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | drop(&a); +LL | | yield; +LL | | }); + | |_____^ `Cell` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Cell` + = note: required for `&Cell` to implement `Send` +note: required because it's used within this generator + --> $DIR/not-send-sync.rs:16:17 + | +LL | assert_send(|| { + | ^^ +note: required by a bound in `assert_send` + --> $DIR/not-send-sync.rs:7:23 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: generator cannot be shared between threads safely + --> $DIR/not-send-sync.rs:9:17 + | +LL | assert_sync(|| { + | _________________^ +LL | | +LL | | let a = Cell::new(2); +LL | | yield; +LL | | }); + | |_____^ generator is not `Sync` + | + = help: within `[generator@$DIR/not-send-sync.rs:9:17: 9:19]`, the trait `Sync` is not implemented for `Cell` +note: generator is not `Sync` as this value is used across a yield + --> $DIR/not-send-sync.rs:12:9 + | +LL | let a = Cell::new(2); + | - has type `Cell` which is not `Sync` +LL | yield; + | ^^^^^ yield occurs here, with `a` maybe used later +LL | }); + | - `a` is later dropped here +note: required by a bound in `assert_sync` + --> $DIR/not-send-sync.rs:6:23 + | +LL | fn assert_sync(_: T) {} + | ^^^^ required by this bound in `assert_sync` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/overlap-locals.rs b/tests/ui/generator/overlap-locals.rs new file mode 100644 index 000000000..101c8714f --- /dev/null +++ b/tests/ui/generator/overlap-locals.rs @@ -0,0 +1,29 @@ +// run-pass + +#![feature(generators)] + +fn main() { + let a = || { + { + let w: i32 = 4; + yield; + println!("{:?}", w); + } + { + let x: i32 = 5; + yield; + println!("{:?}", x); + } + { + let y: i32 = 6; + yield; + println!("{:?}", y); + } + { + let z: i32 = 7; + yield; + println!("{:?}", z); + } + }; + assert_eq!(8, std::mem::size_of_val(&a)); +} diff --git a/tests/ui/generator/panic-drops-resume.rs b/tests/ui/generator/panic-drops-resume.rs new file mode 100644 index 000000000..4c3caeb14 --- /dev/null +++ b/tests/ui/generator/panic-drops-resume.rs @@ -0,0 +1,36 @@ +//! Tests that panics inside a generator will correctly drop the initial resume argument. + +// run-pass +// needs-unwind + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static DROP: AtomicUsize = AtomicUsize::new(0); + +struct Dropper {} + +impl Drop for Dropper { + fn drop(&mut self) { + DROP.fetch_add(1, Ordering::SeqCst); + } +} + +fn main() { + let mut gen = |_arg| { + if true { + panic!(); + } + yield (); + }; + let mut gen = Pin::new(&mut gen); + + assert_eq!(DROP.load(Ordering::Acquire), 0); + let res = catch_unwind(AssertUnwindSafe(|| gen.as_mut().resume(Dropper {}))); + assert!(res.is_err()); + assert_eq!(DROP.load(Ordering::Acquire), 1); +} diff --git a/tests/ui/generator/panic-drops.rs b/tests/ui/generator/panic-drops.rs new file mode 100644 index 000000000..65001fd87 --- /dev/null +++ b/tests/ui/generator/panic-drops.rs @@ -0,0 +1,57 @@ +// run-pass +// needs-unwind + + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::panic; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static A: AtomicUsize = AtomicUsize::new(0); + +struct B; + +impl Drop for B { + fn drop(&mut self) { + A.fetch_add(1, Ordering::SeqCst); + } +} + +fn bool_true() -> bool { + true +} + +fn main() { + let b = B; + let mut foo = || { + if bool_true() { + panic!(); + } + drop(b); + yield; + }; + + assert_eq!(A.load(Ordering::SeqCst), 0); + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + Pin::new(&mut foo).resume(()) + })); + assert!(res.is_err()); + assert_eq!(A.load(Ordering::SeqCst), 1); + + let mut foo = || { + if bool_true() { + panic!(); + } + drop(B); + yield; + }; + + assert_eq!(A.load(Ordering::SeqCst), 1); + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + Pin::new(&mut foo).resume(()) + })); + assert!(res.is_err()); + assert_eq!(A.load(Ordering::SeqCst), 1); +} diff --git a/tests/ui/generator/panic-safe.rs b/tests/ui/generator/panic-safe.rs new file mode 100644 index 000000000..3db80bb58 --- /dev/null +++ b/tests/ui/generator/panic-safe.rs @@ -0,0 +1,30 @@ +// run-pass +// needs-unwind + + +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; +use std::panic; + +fn main() { + let mut foo = || { + if true { + panic!(); + } + yield; + }; + + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + Pin::new(&mut foo).resume(()) + })); + assert!(res.is_err()); + + for _ in 0..10 { + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + Pin::new(&mut foo).resume(()) + })); + assert!(res.is_err()); + } +} diff --git a/tests/ui/generator/partial-drop.rs b/tests/ui/generator/partial-drop.rs new file mode 100644 index 000000000..c872fb7f3 --- /dev/null +++ b/tests/ui/generator/partial-drop.rs @@ -0,0 +1,42 @@ +// compile-flags: -Zdrop-tracking + +#![feature(negative_impls, generators)] + +struct Foo; +impl !Send for Foo {} + +struct Bar { + foo: Foo, + x: i32, +} + +fn main() { + assert_send(|| { + //~^ ERROR generator cannot be sent between threads safely + // FIXME: it would be nice to make this work. + let guard = Bar { foo: Foo, x: 42 }; + drop(guard.foo); + yield; + }); + + assert_send(|| { + //~^ ERROR generator cannot be sent between threads safely + // FIXME: it would be nice to make this work. + let guard = Bar { foo: Foo, x: 42 }; + drop(guard); + guard.foo = Foo; + guard.x = 23; + yield; + }); + + assert_send(|| { + //~^ ERROR generator cannot be sent between threads safely + // FIXME: it would be nice to make this work. + let guard = Bar { foo: Foo, x: 42 }; + let Bar { foo, x } = guard; + drop(foo); + yield; + }); +} + +fn assert_send(_: T) {} diff --git a/tests/ui/generator/partial-drop.stderr b/tests/ui/generator/partial-drop.stderr new file mode 100644 index 000000000..9baafe54e --- /dev/null +++ b/tests/ui/generator/partial-drop.stderr @@ -0,0 +1,92 @@ +error: generator cannot be sent between threads safely + --> $DIR/partial-drop.rs:14:17 + | +LL | assert_send(|| { + | _________________^ +LL | | +LL | | // FIXME: it would be nice to make this work. +LL | | let guard = Bar { foo: Foo, x: 42 }; +LL | | drop(guard.foo); +LL | | yield; +LL | | }); + | |_____^ generator is not `Send` + | + = help: within `[generator@$DIR/partial-drop.rs:14:17: 14:19]`, the trait `Send` is not implemented for `Foo` +note: generator is not `Send` as this value is used across a yield + --> $DIR/partial-drop.rs:19:9 + | +LL | let guard = Bar { foo: Foo, x: 42 }; + | ----- has type `Bar` which is not `Send` +LL | drop(guard.foo); +LL | yield; + | ^^^^^ yield occurs here, with `guard` maybe used later +LL | }); + | - `guard` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/partial-drop.rs:42:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: generator cannot be sent between threads safely + --> $DIR/partial-drop.rs:22:17 + | +LL | assert_send(|| { + | _________________^ +LL | | +LL | | // FIXME: it would be nice to make this work. +LL | | let guard = Bar { foo: Foo, x: 42 }; +... | +LL | | yield; +LL | | }); + | |_____^ generator is not `Send` + | + = help: within `[generator@$DIR/partial-drop.rs:22:17: 22:19]`, the trait `Send` is not implemented for `Foo` +note: generator is not `Send` as this value is used across a yield + --> $DIR/partial-drop.rs:29:9 + | +LL | let guard = Bar { foo: Foo, x: 42 }; + | ----- has type `Bar` which is not `Send` +... +LL | yield; + | ^^^^^ yield occurs here, with `guard` maybe used later +LL | }); + | - `guard` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/partial-drop.rs:42:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: generator cannot be sent between threads safely + --> $DIR/partial-drop.rs:32:17 + | +LL | assert_send(|| { + | _________________^ +LL | | +LL | | // FIXME: it would be nice to make this work. +LL | | let guard = Bar { foo: Foo, x: 42 }; +... | +LL | | yield; +LL | | }); + | |_____^ generator is not `Send` + | + = help: within `[generator@$DIR/partial-drop.rs:32:17: 32:19]`, the trait `Send` is not implemented for `Foo` +note: generator is not `Send` as this value is used across a yield + --> $DIR/partial-drop.rs:38:9 + | +LL | let guard = Bar { foo: Foo, x: 42 }; + | ----- has type `Bar` which is not `Send` +... +LL | yield; + | ^^^^^ yield occurs here, with `guard` maybe used later +LL | }); + | - `guard` is later dropped here +note: required by a bound in `assert_send` + --> $DIR/partial-drop.rs:42:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generator/partial-initialization-across-yield.rs b/tests/ui/generator/partial-initialization-across-yield.rs new file mode 100644 index 000000000..65d9e6d39 --- /dev/null +++ b/tests/ui/generator/partial-initialization-across-yield.rs @@ -0,0 +1,43 @@ +// Test that we don't allow yielding from a generator while a local is partially +// initialized. + +#![feature(generators)] + +struct S { x: i32, y: i32 } +struct T(i32, i32); + +fn test_tuple() { + let _ = || { + let mut t: (i32, i32); + t.0 = 42; //~ ERROR E0381 + yield; + t.1 = 88; + let _ = t; + }; +} + +fn test_tuple_struct() { + let _ = || { + let mut t: T; + t.0 = 42; //~ ERROR E0381 + yield; + t.1 = 88; + let _ = t; + }; +} + +fn test_struct() { + let _ = || { + let mut t: S; + t.x = 42; //~ ERROR E0381 + yield; + t.y = 88; + let _ = t; + }; +} + +fn main() { + test_tuple(); + test_tuple_struct(); + test_struct(); +} diff --git a/tests/ui/generator/partial-initialization-across-yield.stderr b/tests/ui/generator/partial-initialization-across-yield.stderr new file mode 100644 index 000000000..3f9f1c046 --- /dev/null +++ b/tests/ui/generator/partial-initialization-across-yield.stderr @@ -0,0 +1,33 @@ +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-yield.rs:12:9 + | +LL | let mut t: (i32, i32); + | ----- binding declared here but left uninitialized +LL | t.0 = 42; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-yield.rs:22:9 + | +LL | let mut t: T; + | ----- binding declared here but left uninitialized +LL | t.0 = 42; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/partial-initialization-across-yield.rs:32:9 + | +LL | let mut t: S; + | ----- binding declared here but left uninitialized +LL | t.x = 42; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/generator/pattern-borrow.rs b/tests/ui/generator/pattern-borrow.rs new file mode 100644 index 000000000..d19363708 --- /dev/null +++ b/tests/ui/generator/pattern-borrow.rs @@ -0,0 +1,17 @@ +#![feature(generators)] + +enum Test { A(i32), B, } + +fn main() { } + +fn fun(test: Test) { + move || { + if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields + yield (); + _a.use_ref(); + } + }; +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/generator/pattern-borrow.stderr b/tests/ui/generator/pattern-borrow.stderr new file mode 100644 index 000000000..d78da5104 --- /dev/null +++ b/tests/ui/generator/pattern-borrow.stderr @@ -0,0 +1,11 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/pattern-borrow.rs:9:24 + | +LL | if let Test::A(ref _a) = test { + | ^^^^^^ +LL | yield (); + | -------- possible yield occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/generator/pin-box-generator.rs b/tests/ui/generator/pin-box-generator.rs new file mode 100644 index 000000000..c3136f5c0 --- /dev/null +++ b/tests/ui/generator/pin-box-generator.rs @@ -0,0 +1,13 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn assert_generator(_: G) { +} + +fn main() { + assert_generator(static || yield); + assert_generator(Box::pin(static || yield)); +} diff --git a/tests/ui/generator/print/generator-print-verbose-1.rs b/tests/ui/generator/print/generator-print-verbose-1.rs new file mode 100644 index 000000000..89124ad72 --- /dev/null +++ b/tests/ui/generator/print/generator-print-verbose-1.rs @@ -0,0 +1,60 @@ +// compile-flags: -Zverbose + +// Same as: tests/ui/generator/issue-68112.stderr + +#![feature(generators, generator_trait)] + +use std::{ + cell::RefCell, + sync::Arc, + pin::Pin, + ops::{Generator, GeneratorState}, +}; + +pub struct Ready(Option); +impl Generator<()> for Ready { + type Return = T; + type Yield = (); + fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> { + GeneratorState::Complete(self.0.take().unwrap()) + } +} +pub fn make_gen1(t: T) -> Ready { + Ready(Some(t)) +} + +fn require_send(_: impl Send) {} + +fn make_non_send_generator() -> impl Generator>> { + make_gen1(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_gen = || { + let _non_send_gen = make_non_send_generator(); + yield; + }; + require_send(send_gen); + //~^ ERROR generator cannot be sent between threads +} + +pub fn make_gen2(t: T) -> impl Generator { + || { + yield; + t + } +} +fn make_non_send_generator2() -> impl Generator>> { + make_gen2(Arc::new(RefCell::new(0))) +} + +fn test2() { + let send_gen = || { + let _non_send_gen = make_non_send_generator2(); + yield; + }; + require_send(send_gen); + //~^ ERROR `RefCell` cannot be shared between threads safely +} + +fn main() {} diff --git a/tests/ui/generator/print/generator-print-verbose-1.stderr b/tests/ui/generator/print/generator-print-verbose-1.stderr new file mode 100644 index 000000000..ebf35be58 --- /dev/null +++ b/tests/ui/generator/print/generator-print-verbose-1.stderr @@ -0,0 +1,62 @@ +error: generator cannot be sent between threads safely + --> $DIR/generator-print-verbose-1.rs:37:18 + | +LL | require_send(send_gen); + | ^^^^^^^^ generator is not `Send` + | + = help: the trait `Sync` is not implemented for `RefCell` +note: generator is not `Send` as this value is used across a yield + --> $DIR/generator-print-verbose-1.rs:35:9 + | +LL | let _non_send_gen = make_non_send_generator(); + | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send` +LL | yield; + | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later +LL | }; + | - `_non_send_gen` is later dropped here +note: required by a bound in `require_send` + --> $DIR/generator-print-verbose-1.rs:26:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `RefCell` cannot be shared between threads safely + --> $DIR/generator-print-verbose-1.rs:56:18 + | +LL | require_send(send_gen); + | ------------ ^^^^^^^^ `RefCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `RefCell` + = note: required for `Arc>` to implement `Send` +note: required because it's used within this generator + --> $DIR/generator-print-verbose-1.rs:42:5 + | +LL | || { + | ^^ +note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc>])` + --> $DIR/generator-print-verbose-1.rs:41:30 + | +LL | pub fn make_gen2(t: T) -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` + --> $DIR/generator-print-verbose-1.rs:47:34 + | +LL | fn make_non_send_generator2() -> impl Generator>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()` +note: required because it's used within this generator + --> $DIR/generator-print-verbose-1.rs:52:20 + | +LL | let send_gen = || { + | ^^ +note: required by a bound in `require_send` + --> $DIR/generator-print-verbose-1.rs:26:25 + | +LL | fn require_send(_: impl Send) {} + | ^^^^ required by this bound in `require_send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/print/generator-print-verbose-2.rs b/tests/ui/generator/print/generator-print-verbose-2.rs new file mode 100644 index 000000000..d914719cb --- /dev/null +++ b/tests/ui/generator/print/generator-print-verbose-2.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zverbose + +// Same as test/ui/generator/not-send-sync.rs +#![feature(generators)] + +use std::cell::Cell; + +fn main() { + fn assert_sync(_: T) {} + fn assert_send(_: T) {} + + assert_sync(|| { + //~^ ERROR: generator cannot be shared between threads safely + let a = Cell::new(2); + yield; + }); + + let a = Cell::new(2); + assert_send(|| { + //~^ ERROR: E0277 + drop(&a); + yield; + }); +} diff --git a/tests/ui/generator/print/generator-print-verbose-2.stderr b/tests/ui/generator/print/generator-print-verbose-2.stderr new file mode 100644 index 000000000..909e49c38 --- /dev/null +++ b/tests/ui/generator/print/generator-print-verbose-2.stderr @@ -0,0 +1,56 @@ +error[E0277]: `Cell` cannot be shared between threads safely + --> $DIR/generator-print-verbose-2.rs:19:17 + | +LL | assert_send(|| { + | _____-----------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | drop(&a); +LL | | yield; +LL | | }); + | |_____^ `Cell` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Cell` + = note: required for `&'_#4r Cell` to implement `Send` +note: required because it's used within this generator + --> $DIR/generator-print-verbose-2.rs:19:17 + | +LL | assert_send(|| { + | ^^ +note: required by a bound in `assert_send` + --> $DIR/generator-print-verbose-2.rs:10:23 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: generator cannot be shared between threads safely + --> $DIR/generator-print-verbose-2.rs:12:17 + | +LL | assert_sync(|| { + | _________________^ +LL | | +LL | | let a = Cell::new(2); +LL | | yield; +LL | | }); + | |_____^ generator is not `Sync` + | + = help: within `[main::{closure#0} upvar_tys=() {Cell, ()}]`, the trait `Sync` is not implemented for `Cell` +note: generator is not `Sync` as this value is used across a yield + --> $DIR/generator-print-verbose-2.rs:15:9 + | +LL | let a = Cell::new(2); + | - has type `Cell` which is not `Sync` +LL | yield; + | ^^^^^ yield occurs here, with `a` maybe used later +LL | }); + | - `a` is later dropped here +note: required by a bound in `assert_sync` + --> $DIR/generator-print-verbose-2.rs:9:23 + | +LL | fn assert_sync(_: T) {} + | ^^^^ required by this bound in `assert_sync` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/print/generator-print-verbose-3.rs b/tests/ui/generator/print/generator-print-verbose-3.rs new file mode 100644 index 000000000..8689539ec --- /dev/null +++ b/tests/ui/generator/print/generator-print-verbose-3.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zverbose + +#![feature(generators, generator_trait)] + +fn main() { + let x = "Type mismatch test"; + let generator :() = || { + //~^ ERROR mismatched types + yield 1i32; + return x + }; +} diff --git a/tests/ui/generator/print/generator-print-verbose-3.stderr b/tests/ui/generator/print/generator-print-verbose-3.stderr new file mode 100644 index 000000000..d15646259 --- /dev/null +++ b/tests/ui/generator/print/generator-print-verbose-3.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/generator-print-verbose-3.rs:7:25 + | +LL | let generator :() = || { + | ____________________--___^ + | | | + | | expected due to this +LL | | +LL | | yield 1i32; +LL | | return x +LL | | }; + | |_____^ expected `()`, found generator + | + = note: expected unit type `()` + found generator `[main::{closure#0} upvar_tys=(unavailable)]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generator/reborrow-mut-upvar.rs b/tests/ui/generator/reborrow-mut-upvar.rs new file mode 100644 index 000000000..dbd9e24e2 --- /dev/null +++ b/tests/ui/generator/reborrow-mut-upvar.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(generators)] + +fn _run(bar: &mut i32) { + || { //~ WARN unused generator that must be used + { + let _baz = &*bar; + yield; + } + + *bar = 2; + }; +} + +fn main() {} diff --git a/tests/ui/generator/reborrow-mut-upvar.stderr b/tests/ui/generator/reborrow-mut-upvar.stderr new file mode 100644 index 000000000..2e1fec35e --- /dev/null +++ b/tests/ui/generator/reborrow-mut-upvar.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/reborrow-mut-upvar.rs:6:5 + | +LL | / || { +LL | | { +LL | | let _baz = &*bar; +LL | | yield; +... | +LL | | *bar = 2; +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/ref-escapes-but-not-over-yield.rs b/tests/ui/generator/ref-escapes-but-not-over-yield.rs new file mode 100644 index 000000000..3856d8233 --- /dev/null +++ b/tests/ui/generator/ref-escapes-but-not-over-yield.rs @@ -0,0 +1,16 @@ +#![feature(generators)] + +fn foo(x: &i32) { + // In this case, a reference to `b` escapes the generator, but not + // because of a yield. We see that there is no yield in the scope of + // `b` and give the more generic error message. + let mut a = &3; + let mut b = move || { + yield(); + let b = 5; + a = &b; + //~^ ERROR borrowed data escapes outside of generator + }; +} + +fn main() { } diff --git a/tests/ui/generator/ref-escapes-but-not-over-yield.stderr b/tests/ui/generator/ref-escapes-but-not-over-yield.stderr new file mode 100644 index 000000000..5fc810040 --- /dev/null +++ b/tests/ui/generator/ref-escapes-but-not-over-yield.stderr @@ -0,0 +1,15 @@ +error[E0521]: borrowed data escapes outside of generator + --> $DIR/ref-escapes-but-not-over-yield.rs:11:9 + | +LL | let mut a = &3; + | ----- `a` declared here, outside of the generator body +... +LL | a = &b; + | ^^^^-- + | | | + | | borrow is only valid in the generator body + | reference to `b` escapes the generator body here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generator/ref-upvar-not-send.rs b/tests/ui/generator/ref-upvar-not-send.rs new file mode 100644 index 000000000..eb9ef63ec --- /dev/null +++ b/tests/ui/generator/ref-upvar-not-send.rs @@ -0,0 +1,31 @@ +// For `Send` generators, suggest a `T: Sync` requirement for `&T` upvars, +// and suggest a `T: Send` requirement for `&mut T` upvars. + +#![feature(generators)] + +fn assert_send(_: T) {} +//~^ NOTE required by a bound in `assert_send` +//~| NOTE required by this bound in `assert_send` +//~| NOTE required by a bound in `assert_send` +//~| NOTE required by this bound in `assert_send` + +fn main() { + let x: &*mut () = &std::ptr::null_mut(); + let y: &mut *mut () = &mut std::ptr::null_mut(); + assert_send(move || { + //~^ ERROR generator cannot be sent between threads safely + //~| NOTE generator is not `Send` + yield; + let _x = x; + }); + //~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` + //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync` + assert_send(move || { + //~^ ERROR generator cannot be sent between threads safely + //~| NOTE generator is not `Send` + yield; + let _y = y; + }); + //~^^ NOTE captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` + //~| NOTE has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send` +} diff --git a/tests/ui/generator/ref-upvar-not-send.stderr b/tests/ui/generator/ref-upvar-not-send.stderr new file mode 100644 index 000000000..689ace67e --- /dev/null +++ b/tests/ui/generator/ref-upvar-not-send.stderr @@ -0,0 +1,50 @@ +error: generator cannot be sent between threads safely + --> $DIR/ref-upvar-not-send.rs:15:17 + | +LL | assert_send(move || { + | _________________^ +LL | | +LL | | +LL | | yield; +LL | | let _x = x; +LL | | }); + | |_____^ generator is not `Send` + | + = help: the trait `Sync` is not implemented for `*mut ()` +note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` + --> $DIR/ref-upvar-not-send.rs:19:18 + | +LL | let _x = x; + | ^ has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync` +note: required by a bound in `assert_send` + --> $DIR/ref-upvar-not-send.rs:6:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: generator cannot be sent between threads safely + --> $DIR/ref-upvar-not-send.rs:23:17 + | +LL | assert_send(move || { + | _________________^ +LL | | +LL | | +LL | | yield; +LL | | let _y = y; +LL | | }); + | |_____^ generator is not `Send` + | + = help: within `[generator@$DIR/ref-upvar-not-send.rs:23:17: 23:24]`, the trait `Send` is not implemented for `*mut ()` +note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` + --> $DIR/ref-upvar-not-send.rs:27:18 + | +LL | let _y = y; + | ^ has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send` +note: required by a bound in `assert_send` + --> $DIR/ref-upvar-not-send.rs:6:19 + | +LL | fn assert_send(_: T) {} + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generator/reinit-in-match-guard.rs b/tests/ui/generator/reinit-in-match-guard.rs new file mode 100644 index 000000000..260b341a5 --- /dev/null +++ b/tests/ui/generator/reinit-in-match-guard.rs @@ -0,0 +1,25 @@ +// build-pass + +#![feature(generators)] + +#![allow(unused_assignments, dead_code)] + +fn main() { + let _ = || { + let mut x = vec![22_usize]; + std::mem::drop(x); + match y() { + true if { + x = vec![]; + false + } => {} + _ => { + yield; + } + } + }; +} + +fn y() -> bool { + true +} diff --git a/tests/ui/generator/resume-after-return.rs b/tests/ui/generator/resume-after-return.rs new file mode 100644 index 000000000..01a059a16 --- /dev/null +++ b/tests/ui/generator/resume-after-return.rs @@ -0,0 +1,28 @@ +// run-pass +// needs-unwind + + +#![feature(generators, generator_trait)] + +use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; +use std::panic; + +fn main() { + let mut foo = || { + if true { + return + } + yield; + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } + + match panic::catch_unwind(move || Pin::new(&mut foo).resume(())) { + Ok(_) => panic!("generator successfully resumed"), + Err(_) => {} + } +} diff --git a/tests/ui/generator/resume-arg-late-bound.rs b/tests/ui/generator/resume-arg-late-bound.rs new file mode 100644 index 000000000..1c35ba80d --- /dev/null +++ b/tests/ui/generator/resume-arg-late-bound.rs @@ -0,0 +1,17 @@ +//! Tests that we cannot produce a generator that accepts a resume argument +//! with any lifetime and then stores it across a `yield`. + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn test(a: impl for<'a> Generator<&'a mut bool>) {} + +fn main() { + let gen = |arg: &mut bool| { + yield (); + *arg = true; + }; + test(gen); + //~^ ERROR mismatched types +} diff --git a/tests/ui/generator/resume-arg-late-bound.stderr b/tests/ui/generator/resume-arg-late-bound.stderr new file mode 100644 index 000000000..34ee4036c --- /dev/null +++ b/tests/ui/generator/resume-arg-late-bound.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/resume-arg-late-bound.rs:15:5 + | +LL | test(gen); + | ^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Generator<&'a mut bool>` + found trait `Generator<&mut bool>` +note: the lifetime requirement is introduced here + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generator/resume-arg-size.rs b/tests/ui/generator/resume-arg-size.rs new file mode 100644 index 000000000..b93dc54f7 --- /dev/null +++ b/tests/ui/generator/resume-arg-size.rs @@ -0,0 +1,28 @@ +#![feature(generators)] + +// run-pass + +use std::mem::size_of_val; + +fn main() { + // Generator taking a `Copy`able resume arg. + let gen_copy = |mut x: usize| { + loop { + drop(x); + x = yield; + } + }; + + // Generator taking a non-`Copy` resume arg. + let gen_move = |mut x: Box| { + loop { + drop(x); + x = yield; + } + }; + + // Neither of these generators have the resume arg live across the `yield`, so they should be + // 1 Byte in size (only storing the discriminant) + assert_eq!(size_of_val(&gen_copy), 1); + assert_eq!(size_of_val(&gen_move), 1); +} diff --git a/tests/ui/generator/resume-live-across-yield.rs b/tests/ui/generator/resume-live-across-yield.rs new file mode 100644 index 000000000..4c4cf117a --- /dev/null +++ b/tests/ui/generator/resume-live-across-yield.rs @@ -0,0 +1,45 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static DROP: AtomicUsize = AtomicUsize::new(0); + +#[derive(PartialEq, Eq, Debug)] +struct Dropper(String); + +impl Drop for Dropper { + fn drop(&mut self) { + DROP.fetch_add(1, Ordering::SeqCst); + } +} + +fn main() { + let mut g = |mut _d| { + _d = yield; + _d + }; + + let mut g = Pin::new(&mut g); + + assert_eq!( + g.as_mut().resume(Dropper(String::from("Hello world!"))), + GeneratorState::Yielded(()) + ); + assert_eq!(DROP.load(Ordering::Acquire), 0); + match g.as_mut().resume(Dropper(String::from("Number Two"))) { + GeneratorState::Complete(dropper) => { + assert_eq!(DROP.load(Ordering::Acquire), 1); + assert_eq!(dropper.0, "Number Two"); + drop(dropper); + assert_eq!(DROP.load(Ordering::Acquire), 2); + } + _ => unreachable!(), + } + + drop(g); + assert_eq!(DROP.load(Ordering::Acquire), 2); +} diff --git a/tests/ui/generator/retain-resume-ref.rs b/tests/ui/generator/retain-resume-ref.rs new file mode 100644 index 000000000..0606ea71c --- /dev/null +++ b/tests/ui/generator/retain-resume-ref.rs @@ -0,0 +1,25 @@ +//! This test ensures that a mutable reference cannot be passed as a resume argument twice. + +#![feature(generators, generator_trait)] + +use std::marker::Unpin; +use std::ops::{ + Generator, + GeneratorState::{self, *}, +}; +use std::pin::Pin; + +fn main() { + let mut thing = String::from("hello"); + + let mut gen = |r| { + if false { + yield r; + } + }; + + let mut gen = Pin::new(&mut gen); + gen.as_mut().resume(&mut thing); + gen.as_mut().resume(&mut thing); + //~^ cannot borrow `thing` as mutable more than once at a time +} diff --git a/tests/ui/generator/retain-resume-ref.stderr b/tests/ui/generator/retain-resume-ref.stderr new file mode 100644 index 000000000..e33310d12 --- /dev/null +++ b/tests/ui/generator/retain-resume-ref.stderr @@ -0,0 +1,13 @@ +error[E0499]: cannot borrow `thing` as mutable more than once at a time + --> $DIR/retain-resume-ref.rs:23:25 + | +LL | gen.as_mut().resume(&mut thing); + | ---------- first mutable borrow occurs here +LL | gen.as_mut().resume(&mut thing); + | ------ ^^^^^^^^^^ second mutable borrow occurs here + | | + | first borrow later used by call + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/generator/size-moved-locals.rs b/tests/ui/generator/size-moved-locals.rs new file mode 100644 index 000000000..601a31418 --- /dev/null +++ b/tests/ui/generator/size-moved-locals.rs @@ -0,0 +1,78 @@ +// run-pass +// Test that we don't duplicate storage for a variable that is moved to another +// binding. This used to happen in the presence of unwind and drop edges (see +// `complex` below.) +// +// The exact sizes here can change (we'd like to know when they do). What we +// don't want to see is the `complex` generator size being upwards of 2048 bytes +// (which would indicate it is reserving space for two copies of Foo.) +// +// See issue #59123 for a full explanation. + +// edition:2018 +// ignore-wasm32 issue #62807 +// ignore-asmjs issue #62807 +// needs-unwind Size of Closures change on panic=abort + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +const FOO_SIZE: usize = 1024; +struct Foo(#[allow(unused_tuple_struct_fields)] [u8; FOO_SIZE]); + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn move_before_yield() -> impl Generator { + static || { + let first = Foo([0; FOO_SIZE]); + let _second = first; + yield; + // _second dropped here + } +} + +fn noop() {} + +fn move_before_yield_with_noop() -> impl Generator { + static || { + let first = Foo([0; FOO_SIZE]); + noop(); + let _second = first; + yield; + // _second dropped here + } +} + +// Today we don't have NRVO (we allocate space for both `first` and `second`,) +// but we can overlap `first` with `_third`. +fn overlap_move_points() -> impl Generator { + static || { + let first = Foo([0; FOO_SIZE]); + yield; + let second = first; + yield; + let _third = second; + yield; + } +} + +fn overlap_x_and_y() -> impl Generator { + static || { + let x = Foo([0; FOO_SIZE]); + yield; + drop(x); + let y = Foo([0; FOO_SIZE]); + yield; + drop(y); + } +} + +fn main() { + assert_eq!(1025, std::mem::size_of_val(&move_before_yield())); + assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop())); + assert_eq!(2051, std::mem::size_of_val(&overlap_move_points())); + assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y())); +} diff --git a/tests/ui/generator/sized-yield.rs b/tests/ui/generator/sized-yield.rs new file mode 100644 index 000000000..c6dd738d6 --- /dev/null +++ b/tests/ui/generator/sized-yield.rs @@ -0,0 +1,14 @@ +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let s = String::from("foo"); + let mut gen = move || { + //~^ ERROR the size for values of type + yield s[..]; + }; + Pin::new(&mut gen).resume(()); + //~^ ERROR the size for values of type +} diff --git a/tests/ui/generator/sized-yield.stderr b/tests/ui/generator/sized-yield.stderr new file mode 100644 index 000000000..fb34540d9 --- /dev/null +++ b/tests/ui/generator/sized-yield.stderr @@ -0,0 +1,26 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/sized-yield.rs:8:26 + | +LL | let mut gen = move || { + | __________________________^ +LL | | +LL | | yield s[..]; +LL | | }; + | |____^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the yield type of a generator must have a statically known size + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/sized-yield.rs:12:23 + | +LL | Pin::new(&mut gen).resume(()); + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `GeneratorState` + --> $SRC_DIR/core/src/ops/generator.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/smoke-resume-args.rs b/tests/ui/generator/smoke-resume-args.rs new file mode 100644 index 000000000..fa9271c53 --- /dev/null +++ b/tests/ui/generator/smoke-resume-args.rs @@ -0,0 +1,100 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +#![feature(generators, generator_trait)] + +use std::fmt::Debug; +use std::marker::Unpin; +use std::ops::{ + Generator, + GeneratorState::{self, *}, +}; +use std::pin::Pin; +use std::sync::atomic::{AtomicUsize, Ordering}; + +fn drain + Unpin, R, Y>( + gen: &mut G, + inout: Vec<(R, GeneratorState)>, +) where + Y: Debug + PartialEq, + G::Return: Debug + PartialEq, +{ + let mut gen = Pin::new(gen); + + for (input, out) in inout { + assert_eq!(gen.as_mut().resume(input), out); + } +} + +static DROPS: AtomicUsize = AtomicUsize::new(0); + +#[derive(Debug, PartialEq)] +struct DropMe; + +impl Drop for DropMe { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::SeqCst); + } +} + +fn expect_drops(expected_drops: usize, f: impl FnOnce() -> T) -> T { + DROPS.store(0, Ordering::SeqCst); + + let res = f(); + + let actual_drops = DROPS.load(Ordering::SeqCst); + assert_eq!(actual_drops, expected_drops); + res +} + +fn main() { + drain( + &mut |mut b| { + while b != 0 { + b = yield (b + 1); + } + -1 + }, + vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))], + ); + + expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))])); + + expect_drops(6, || { + drain( + &mut |a| yield yield a, + vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))], + ) + }); + + #[allow(unreachable_code)] + expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))])); + + expect_drops(2, || { + drain( + &mut |a: DropMe| { + if false { yield () } else { a } + }, + vec![(DropMe, Complete(DropMe))], + ) + }); + + expect_drops(4, || { + drain( + #[allow(unused_assignments, unused_variables)] + &mut |mut a: DropMe| { + a = yield; + a = yield; + a = yield; + }, + vec![ + (DropMe, Yielded(())), + (DropMe, Yielded(())), + (DropMe, Yielded(())), + (DropMe, Complete(())), + ], + ) + }); +} diff --git a/tests/ui/generator/smoke.rs b/tests/ui/generator/smoke.rs new file mode 100644 index 000000000..7a917a05d --- /dev/null +++ b/tests/ui/generator/smoke.rs @@ -0,0 +1,177 @@ +// run-pass + +// revisions: default nomiropt +//[nomiropt]compile-flags: -Z mir-opt-level=0 + +// ignore-emscripten no threads support +// compile-flags: --test + +#![feature(generators, generator_trait)] + +use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; +use std::thread; + +#[test] +fn simple() { + let mut foo = || { + if false { + yield; + } + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } +} + +#[test] +fn return_capture() { + let a = String::from("foo"); + let mut foo = || { + if false { + yield; + } + a + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(ref s) if *s == "foo" => {} + s => panic!("bad state: {:?}", s), + } +} + +#[test] +fn simple_yield() { + let mut foo = || { + yield; + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(()) => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } +} + +#[test] +fn yield_capture() { + let b = String::from("foo"); + let mut foo = || { + yield b; + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(ref s) if *s == "foo" => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } +} + +#[test] +fn simple_yield_value() { + let mut foo = || { + yield String::from("bar"); + return String::from("foo") + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(ref s) if *s == "bar" => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(ref s) if *s == "foo" => {} + s => panic!("bad state: {:?}", s), + } +} + +#[test] +fn return_after_yield() { + let a = String::from("foo"); + let mut foo = || { + yield; + return a + }; + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(()) => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(ref s) if *s == "foo" => {} + s => panic!("bad state: {:?}", s), + } +} + +#[test] +fn send_and_sync() { + assert_send_sync(|| { + yield + }); + assert_send_sync(|| { + yield String::from("foo"); + }); + assert_send_sync(|| { + yield; + return String::from("foo"); + }); + let a = 3; + assert_send_sync(|| { + yield a; + return + }); + let a = 3; + assert_send_sync(move || { + yield a; + return + }); + let a = String::from("a"); + assert_send_sync(|| { + yield ; + drop(a); + return + }); + let a = String::from("a"); + assert_send_sync(move || { + yield ; + drop(a); + return + }); + + fn assert_send_sync(_: T) {} +} + +#[test] +fn send_over_threads() { + let mut foo = || { yield }; + thread::spawn(move || { + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(()) => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } + }).join().unwrap(); + + let a = String::from("a"); + let mut foo = || { yield a }; + thread::spawn(move || { + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(ref s) if *s == "a" => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } + }).join().unwrap(); +} diff --git a/tests/ui/generator/static-generators.rs b/tests/ui/generator/static-generators.rs new file mode 100644 index 000000000..d098bf1e6 --- /dev/null +++ b/tests/ui/generator/static-generators.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::pin::Pin; +use std::ops::{Generator, GeneratorState}; + +fn main() { + let mut generator = static || { + let a = true; + let b = &a; + yield; + assert_eq!(b as *const _, &a as *const _); + }; + // SAFETY: We shadow the original generator variable so have no safe API to + // move it after this point. + let mut generator = unsafe { Pin::new_unchecked(&mut generator) }; + assert_eq!(generator.as_mut().resume(()), GeneratorState::Yielded(())); + assert_eq!(generator.as_mut().resume(()), GeneratorState::Complete(())); +} diff --git a/tests/ui/generator/static-mut-reference-across-yield.rs b/tests/ui/generator/static-mut-reference-across-yield.rs new file mode 100644 index 000000000..0fa6d9cdc --- /dev/null +++ b/tests/ui/generator/static-mut-reference-across-yield.rs @@ -0,0 +1,32 @@ +// build-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![feature(generators)] + +static mut A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn is_send_sync(_: T) {} + +fn main() { + unsafe { + let gen_index = static || { + let u = A[{ + yield; + 1 + }]; + }; + let gen_match = static || match A { + i if { + yield; + true + } => + { + () + } + _ => (), + }; + is_send_sync(gen_index); + is_send_sync(gen_match); + } +} diff --git a/tests/ui/generator/static-not-unpin.rs b/tests/ui/generator/static-not-unpin.rs new file mode 100644 index 000000000..cfcb94737 --- /dev/null +++ b/tests/ui/generator/static-not-unpin.rs @@ -0,0 +1,15 @@ +#![feature(generators)] + +// normalize-stderr-test "std::pin::Unpin" -> "std::marker::Unpin" + +use std::marker::Unpin; + +fn assert_unpin(_: T) { +} + +fn main() { + let mut generator = static || { + yield; + }; + assert_unpin(generator); //~ ERROR E0277 +} diff --git a/tests/ui/generator/static-not-unpin.stderr b/tests/ui/generator/static-not-unpin.stderr new file mode 100644 index 000000000..e3859595f --- /dev/null +++ b/tests/ui/generator/static-not-unpin.stderr @@ -0,0 +1,18 @@ +error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 11:34]` cannot be unpinned + --> $DIR/static-not-unpin.rs:14:18 + | +LL | assert_unpin(generator); + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 11:34]` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `assert_unpin` + --> $DIR/static-not-unpin.rs:7:20 + | +LL | fn assert_unpin(_: T) { + | ^^^^^ required by this bound in `assert_unpin` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/static-reference-across-yield.rs b/tests/ui/generator/static-reference-across-yield.rs new file mode 100644 index 000000000..23b11593b --- /dev/null +++ b/tests/ui/generator/static-reference-across-yield.rs @@ -0,0 +1,16 @@ +// build-pass +#![feature(generators)] + +static A: [i32; 5] = [1, 2, 3, 4, 5]; + +fn main() { + static || { + let u = A[{yield; 1}]; + }; + static || { + match A { + i if { yield; true } => (), + _ => (), + } + }; +} diff --git a/tests/ui/generator/too-live-local-in-immovable-gen.rs b/tests/ui/generator/too-live-local-in-immovable-gen.rs new file mode 100644 index 000000000..e0b856db7 --- /dev/null +++ b/tests/ui/generator/too-live-local-in-immovable-gen.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_unsafe)] + +#![feature(generators)] + +fn main() { + unsafe { + static move || { //~ WARN unused generator that must be used + // Tests that the generator transformation finds out that `a` is not live + // during the yield expression. Type checking will also compute liveness + // and it should also find out that `a` is not live. + // The compiler will panic if the generator transformation finds that + // `a` is live and type checking finds it dead. + let a = { + yield (); + 4i32 + }; + let _ = &a; + }; + } +} diff --git a/tests/ui/generator/too-live-local-in-immovable-gen.stderr b/tests/ui/generator/too-live-local-in-immovable-gen.stderr new file mode 100644 index 000000000..e262f213f --- /dev/null +++ b/tests/ui/generator/too-live-local-in-immovable-gen.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/too-live-local-in-immovable-gen.rs:8:9 + | +LL | / static move || { +LL | | // Tests that the generator transformation finds out that `a` is not live +LL | | // during the yield expression. Type checking will also compute liveness +LL | | // and it should also find out that `a` is not live. +... | +LL | | let _ = &a; +LL | | }; + | |_________^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/too-many-parameters.rs b/tests/ui/generator/too-many-parameters.rs new file mode 100644 index 000000000..7a353ea29 --- /dev/null +++ b/tests/ui/generator/too-many-parameters.rs @@ -0,0 +1,8 @@ +#![feature(generators)] + +fn main() { + |(), ()| { + //~^ error: too many parameters for a generator + yield; + }; +} diff --git a/tests/ui/generator/too-many-parameters.stderr b/tests/ui/generator/too-many-parameters.stderr new file mode 100644 index 000000000..22d40db3f --- /dev/null +++ b/tests/ui/generator/too-many-parameters.stderr @@ -0,0 +1,9 @@ +error[E0628]: too many parameters for a generator (expected 0 or 1 parameters) + --> $DIR/too-many-parameters.rs:4:5 + | +LL | |(), ()| { + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0628`. diff --git a/tests/ui/generator/type-mismatch-error.rs b/tests/ui/generator/type-mismatch-error.rs new file mode 100644 index 000000000..d39c788a8 --- /dev/null +++ b/tests/ui/generator/type-mismatch-error.rs @@ -0,0 +1,22 @@ +//! Test that we get the expected type mismatch error instead of "closure is expected to take 0 +//! arguments" (which got introduced after implementing resume arguments). + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn f(_: G, _: G::Return) {} + +fn main() { + f( + |a: u8| { + if false { + yield (); + } else { + a + //~^ error: `if` and `else` have incompatible types + } + }, + 0u8, + ); +} diff --git a/tests/ui/generator/type-mismatch-error.stderr b/tests/ui/generator/type-mismatch-error.stderr new file mode 100644 index 000000000..8f5949533 --- /dev/null +++ b/tests/ui/generator/type-mismatch-error.stderr @@ -0,0 +1,19 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/type-mismatch-error.rs:16:17 + | +LL | / if false { +LL | | yield (); + | | --------- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | } else { +LL | | a + | | ^ expected `()`, found `u8` +LL | | +LL | | } + | |_____________- `if` and `else` have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generator/type-mismatch-signature-deduction.rs b/tests/ui/generator/type-mismatch-signature-deduction.rs new file mode 100644 index 000000000..8d1ce6c7a --- /dev/null +++ b/tests/ui/generator/type-mismatch-signature-deduction.rs @@ -0,0 +1,18 @@ +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn foo() -> impl Generator { + //~^ ERROR type mismatch + || { + if false { + return Ok(6); + } + + yield (); + + 5 //~ ERROR mismatched types [E0308] + } +} + +fn main() {} diff --git a/tests/ui/generator/type-mismatch-signature-deduction.stderr b/tests/ui/generator/type-mismatch-signature-deduction.stderr new file mode 100644 index 000000000..b98da1ed8 --- /dev/null +++ b/tests/ui/generator/type-mismatch-signature-deduction.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-signature-deduction.rs:14:9 + | +LL | 5 + | ^ expected enum `Result`, found integer + | + = note: expected enum `Result<{integer}, _>` + found type `{integer}` +note: return type inferred to be `Result<{integer}, _>` here + --> $DIR/type-mismatch-signature-deduction.rs:9:20 + | +LL | return Ok(6); + | ^^^^^ +help: try wrapping the expression in a variant of `Result` + | +LL | Ok(5) + | +++ + +LL | Err(5) + | ++++ + + +error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7] as Generator>::Return == i32` + --> $DIR/type-mismatch-signature-deduction.rs:5:13 + | +LL | fn foo() -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32` + | + = note: expected enum `Result<{integer}, _>` + found type `i32` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/generator/unresolved-ct-var-drop-tracking.rs b/tests/ui/generator/unresolved-ct-var-drop-tracking.rs new file mode 100644 index 000000000..a6589348d --- /dev/null +++ b/tests/ui/generator/unresolved-ct-var-drop-tracking.rs @@ -0,0 +1,15 @@ +// incremental +// edition:2021 +// compile-flags: -Zdrop-tracking + +fn main() { + let _ = async { + let s = std::array::from_fn(|_| ()).await; + //~^ ERROR `[(); _]` is not a future + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + }; +} diff --git a/tests/ui/generator/unresolved-ct-var-drop-tracking.stderr b/tests/ui/generator/unresolved-ct-var-drop-tracking.stderr new file mode 100644 index 000000000..9e1fed54c --- /dev/null +++ b/tests/ui/generator/unresolved-ct-var-drop-tracking.stderr @@ -0,0 +1,78 @@ +error[E0277]: `[(); _]` is not a future + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ---------------------------^^^^^^ + | | | + | | `[(); _]` is not a future + | | help: remove the `.await` + | this call returns `[(); _]` + | + = help: the trait `Future` is not implemented for `[(); _]` + = note: [(); _] must be a future or must implement `IntoFuture` to be awaited + = note: required for `[(); _]` to implement `IntoFuture` + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var-drop-tracking.rs:7:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0698. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/unresolved-ct-var.rs b/tests/ui/generator/unresolved-ct-var.rs new file mode 100644 index 000000000..0a1570fc2 --- /dev/null +++ b/tests/ui/generator/unresolved-ct-var.rs @@ -0,0 +1,14 @@ +// incremental +// edition:2021 + +fn main() { + let _ = async { + let s = std::array::from_fn(|_| ()).await; + //~^ ERROR `[(); _]` is not a future + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + //~| ERROR type inside `async` block must be known in this context + }; +} diff --git a/tests/ui/generator/unresolved-ct-var.stderr b/tests/ui/generator/unresolved-ct-var.stderr new file mode 100644 index 000000000..fdf00dfad --- /dev/null +++ b/tests/ui/generator/unresolved-ct-var.stderr @@ -0,0 +1,78 @@ +error[E0277]: `[(); _]` is not a future + --> $DIR/unresolved-ct-var.rs:6:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ---------------------------^^^^^^ + | | | + | | `[(); _]` is not a future + | | help: remove the `.await` + | this call returns `[(); _]` + | + = help: the trait `Future` is not implemented for `[(); _]` + = note: [(); _] must be a future or must implement `IntoFuture` to be awaited + = note: required for `[(); _]` to implement `IntoFuture` + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var.rs:6:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var.rs:6:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var.rs:6:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var.rs:6:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var.rs:6:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var.rs:6:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var.rs:6:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var.rs:6:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/unresolved-ct-var.rs:6:17 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `from_fn` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/unresolved-ct-var.rs:6:44 + | +LL | let s = std::array::from_fn(|_| ()).await; + | ^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0698. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/xcrate-reachable.rs b/tests/ui/generator/xcrate-reachable.rs new file mode 100644 index 000000000..1b1cff338 --- /dev/null +++ b/tests/ui/generator/xcrate-reachable.rs @@ -0,0 +1,14 @@ +// run-pass + +// aux-build:xcrate-reachable.rs + +#![feature(generator_trait)] + +extern crate xcrate_reachable as foo; + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + Pin::new(&mut foo::foo()).resume(()); +} diff --git a/tests/ui/generator/xcrate.rs b/tests/ui/generator/xcrate.rs new file mode 100644 index 000000000..40986bbeb --- /dev/null +++ b/tests/ui/generator/xcrate.rs @@ -0,0 +1,30 @@ +// run-pass + +// aux-build:xcrate.rs + +#![feature(generators, generator_trait)] + +extern crate xcrate; + +use std::ops::{GeneratorState, Generator}; +use std::pin::Pin; + +fn main() { + let mut foo = xcrate::foo(); + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } + + let mut foo = xcrate::bar(3); + + match Pin::new(&mut foo).resume(()) { + GeneratorState::Yielded(3) => {} + s => panic!("bad state: {:?}", s), + } + match Pin::new(&mut foo).resume(()) { + GeneratorState::Complete(()) => {} + s => panic!("bad state: {:?}", s), + } +} diff --git a/tests/ui/generator/yield-in-args-rev.rs b/tests/ui/generator/yield-in-args-rev.rs new file mode 100644 index 000000000..4c99bb3ef --- /dev/null +++ b/tests/ui/generator/yield-in-args-rev.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] + +// Test that a borrow that occurs after a yield in the same +// argument list is not treated as live across the yield by +// type-checking. + +#![feature(generators)] + +fn foo(_a: (), _b: &bool) {} + +fn bar() { + || { //~ WARN unused generator that must be used + let b = true; + foo(yield, &b); + }; +} + +fn main() { } diff --git a/tests/ui/generator/yield-in-args-rev.stderr b/tests/ui/generator/yield-in-args-rev.stderr new file mode 100644 index 000000000..a87248f66 --- /dev/null +++ b/tests/ui/generator/yield-in-args-rev.stderr @@ -0,0 +1,14 @@ +warning: unused generator that must be used + --> $DIR/yield-in-args-rev.rs:13:5 + | +LL | / || { +LL | | let b = true; +LL | | foo(yield, &b); +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/yield-in-args.rs b/tests/ui/generator/yield-in-args.rs new file mode 100644 index 000000000..80110af55 --- /dev/null +++ b/tests/ui/generator/yield-in-args.rs @@ -0,0 +1,10 @@ +#![feature(generators)] + +fn foo(_b: &bool, _a: ()) {} + +fn main() { + || { + let b = true; + foo(&b, yield); //~ ERROR + }; +} diff --git a/tests/ui/generator/yield-in-args.stderr b/tests/ui/generator/yield-in-args.stderr new file mode 100644 index 000000000..ee6d22c27 --- /dev/null +++ b/tests/ui/generator/yield-in-args.stderr @@ -0,0 +1,9 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/yield-in-args.rs:8:13 + | +LL | foo(&b, yield); + | ^^ ----- possible yield occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/generator/yield-in-box.rs b/tests/ui/generator/yield-in-box.rs new file mode 100644 index 000000000..dd6fa7c15 --- /dev/null +++ b/tests/ui/generator/yield-in-box.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that box-statements with yields in them work. + +#![feature(generators, box_syntax, generator_trait)] +use std::pin::Pin; +use std::ops::Generator; +use std::ops::GeneratorState; + +fn main() { + let x = 0i32; + || { //~ WARN unused generator that must be used + let y = 2u32; + { + let _t = box (&x, yield 0, &y); + } + match box (&x, yield 0, &y) { + _t => {} + } + }; + + let mut g = |_| box yield; + assert_eq!(Pin::new(&mut g).resume(1), GeneratorState::Yielded(())); + assert_eq!(Pin::new(&mut g).resume(2), GeneratorState::Complete(box 2)); +} diff --git a/tests/ui/generator/yield-in-box.stderr b/tests/ui/generator/yield-in-box.stderr new file mode 100644 index 000000000..9d03ee008 --- /dev/null +++ b/tests/ui/generator/yield-in-box.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/yield-in-box.rs:11:5 + | +LL | / || { +LL | | let y = 2u32; +LL | | { +LL | | let _t = box (&x, yield 0, &y); +... | +LL | | } +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/yield-in-const.rs b/tests/ui/generator/yield-in-const.rs new file mode 100644 index 000000000..fe5ca822c --- /dev/null +++ b/tests/ui/generator/yield-in-const.rs @@ -0,0 +1,6 @@ +#![feature(generators)] + +const A: u8 = { yield 3u8; 3u8}; +//~^ ERROR yield expression outside + +fn main() {} diff --git a/tests/ui/generator/yield-in-const.stderr b/tests/ui/generator/yield-in-const.stderr new file mode 100644 index 000000000..dcf4fe63e --- /dev/null +++ b/tests/ui/generator/yield-in-const.stderr @@ -0,0 +1,9 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/yield-in-const.rs:3:17 + | +LL | const A: u8 = { yield 3u8; 3u8}; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/generator/yield-in-function.rs b/tests/ui/generator/yield-in-function.rs new file mode 100644 index 000000000..29b811621 --- /dev/null +++ b/tests/ui/generator/yield-in-function.rs @@ -0,0 +1,4 @@ +#![feature(generators)] + +fn main() { yield; } +//~^ ERROR yield expression outside diff --git a/tests/ui/generator/yield-in-function.stderr b/tests/ui/generator/yield-in-function.stderr new file mode 100644 index 000000000..51cce198c --- /dev/null +++ b/tests/ui/generator/yield-in-function.stderr @@ -0,0 +1,9 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/yield-in-function.rs:3:13 + | +LL | fn main() { yield; } + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/generator/yield-in-initializer.rs b/tests/ui/generator/yield-in-initializer.rs new file mode 100644 index 000000000..0cab36e5f --- /dev/null +++ b/tests/ui/generator/yield-in-initializer.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(generators)] + +fn main() { + static || { //~ WARN unused generator that must be used + loop { + // Test that `opt` is not live across the yield, even when borrowed in a loop + // See https://github.com/rust-lang/rust/issues/52792 + let opt = { + yield; + true + }; + let _ = &opt; + } + }; +} diff --git a/tests/ui/generator/yield-in-initializer.stderr b/tests/ui/generator/yield-in-initializer.stderr new file mode 100644 index 000000000..ed14a2e32 --- /dev/null +++ b/tests/ui/generator/yield-in-initializer.stderr @@ -0,0 +1,17 @@ +warning: unused generator that must be used + --> $DIR/yield-in-initializer.rs:6:5 + | +LL | / static || { +LL | | loop { +LL | | // Test that `opt` is not live across the yield, even when borrowed in a loop +LL | | // See https://github.com/rust-lang/rust/issues/52792 +... | +LL | | } +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/yield-in-static.rs b/tests/ui/generator/yield-in-static.rs new file mode 100644 index 000000000..d27fbb33b --- /dev/null +++ b/tests/ui/generator/yield-in-static.rs @@ -0,0 +1,6 @@ +#![feature(generators)] + +static B: u8 = { yield 3u8; 3u8}; +//~^ ERROR yield expression outside + +fn main() {} diff --git a/tests/ui/generator/yield-in-static.stderr b/tests/ui/generator/yield-in-static.stderr new file mode 100644 index 000000000..d867f3ad3 --- /dev/null +++ b/tests/ui/generator/yield-in-static.stderr @@ -0,0 +1,9 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/yield-in-static.rs:3:18 + | +LL | static B: u8 = { yield 3u8; 3u8}; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/generator/yield-outside-generator-issue-78653.rs b/tests/ui/generator/yield-outside-generator-issue-78653.rs new file mode 100644 index 000000000..4e8050c81 --- /dev/null +++ b/tests/ui/generator/yield-outside-generator-issue-78653.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +fn main() { + yield || for i in 0 { } + //~^ ERROR yield expression outside of generator literal + //~| ERROR `{integer}` is not an iterator +} diff --git a/tests/ui/generator/yield-outside-generator-issue-78653.stderr b/tests/ui/generator/yield-outside-generator-issue-78653.stderr new file mode 100644 index 000000000..dcfb21174 --- /dev/null +++ b/tests/ui/generator/yield-outside-generator-issue-78653.stderr @@ -0,0 +1,20 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/yield-outside-generator-issue-78653.rs:4:5 + | +LL | yield || for i in 0 { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `{integer}` is not an iterator + --> $DIR/yield-outside-generator-issue-78653.rs:4:23 + | +LL | yield || for i in 0 { } + | ^ `{integer}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{integer}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{integer}` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0627. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/generator/yield-subtype.rs b/tests/ui/generator/yield-subtype.rs new file mode 100644 index 000000000..cb3fc9091 --- /dev/null +++ b/tests/ui/generator/yield-subtype.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(dead_code)] + +#![feature(generators)] + +fn bar<'a>() { + let a: &'static str = "hi"; + let b: &'a str = a; + + || { //~ WARN unused generator that must be used + yield a; + yield b; + }; +} + +fn main() {} diff --git a/tests/ui/generator/yield-subtype.stderr b/tests/ui/generator/yield-subtype.stderr new file mode 100644 index 000000000..97862e91c --- /dev/null +++ b/tests/ui/generator/yield-subtype.stderr @@ -0,0 +1,14 @@ +warning: unused generator that must be used + --> $DIR/yield-subtype.rs:11:5 + | +LL | / || { +LL | | yield a; +LL | | yield b; +LL | | }; + | |_____^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/generator/yield-while-iterating.rs b/tests/ui/generator/yield-while-iterating.rs new file mode 100644 index 000000000..985e5d8bd --- /dev/null +++ b/tests/ui/generator/yield-while-iterating.rs @@ -0,0 +1,75 @@ +#![feature(generators, generator_trait)] + +use std::ops::{GeneratorState, Generator}; +use std::cell::Cell; +use std::pin::Pin; + +fn yield_during_iter_owned_data(x: Vec) { + // The generator owns `x`, so we error out when yielding with a + // reference to it. This winds up becoming a rather confusing + // regionck error -- in particular, we would freeze with the + // reference in scope, and it doesn't live long enough. + let _b = move || { + for p in &x { //~ ERROR + yield(); + } + }; +} + +fn yield_during_iter_borrowed_slice(x: &[i32]) { + let _b = move || { + for p in x { + yield(); + } + }; +} + +fn yield_during_iter_borrowed_slice_2() { + let mut x = vec![22_i32]; + let _b = || { + for p in &x { + yield(); + } + }; + println!("{:?}", x); +} + +fn yield_during_iter_borrowed_slice_3() { + // OK to take a mutable ref to `x` and yield + // up pointers from it: + let mut x = vec![22_i32]; + let mut b = || { + for p in &mut x { + yield p; + } + }; + Pin::new(&mut b).resume(()); +} + +fn yield_during_iter_borrowed_slice_4() { + // ...but not OK to do that while reading + // from `x` too + let mut x = vec![22_i32]; + let mut b = || { + for p in &mut x { + yield p; + } + }; + println!("{}", x[0]); //~ ERROR + Pin::new(&mut b).resume(()); +} + +fn yield_during_range_iter() { + // Should be OK. + let mut b = || { + let v = vec![1,2,3]; + let len = v.len(); + for i in 0..len { + let x = v[i]; + yield x; + } + }; + Pin::new(&mut b).resume(()); +} + +fn main() { } diff --git a/tests/ui/generator/yield-while-iterating.stderr b/tests/ui/generator/yield-while-iterating.stderr new file mode 100644 index 000000000..b65634752 --- /dev/null +++ b/tests/ui/generator/yield-while-iterating.stderr @@ -0,0 +1,25 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/yield-while-iterating.rs:13:18 + | +LL | for p in &x { + | ^^ +LL | yield(); + | ------- possible yield occurs here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/yield-while-iterating.rs:58:20 + | +LL | let mut b = || { + | -- mutable borrow occurs here +LL | for p in &mut x { + | - first borrow occurs due to use of `x` in generator +... +LL | println!("{}", x[0]); + | ^ immutable borrow occurs here +LL | Pin::new(&mut b).resume(()); + | ------ mutable borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0502, E0626. +For more information about an error, try `rustc --explain E0502`. diff --git a/tests/ui/generator/yield-while-local-borrowed.rs b/tests/ui/generator/yield-while-local-borrowed.rs new file mode 100644 index 000000000..061a64dbc --- /dev/null +++ b/tests/ui/generator/yield-while-local-borrowed.rs @@ -0,0 +1,49 @@ +#![feature(generators, generator_trait)] + +use std::ops::{GeneratorState, Generator}; +use std::cell::Cell; +use std::pin::Pin; + +fn borrow_local_inline() { + // Not OK to yield with a borrow of a temporary. + // + // (This error occurs because the region shows up in the type of + // `b` and gets extended by region inference.) + let mut b = move || { + let a = &mut 3; + //~^ ERROR borrow may still be in use when generator yields + yield(); + println!("{}", a); + }; + Pin::new(&mut b).resume(()); +} + +fn borrow_local_inline_done() { + // No error here -- `a` is not in scope at the point of `yield`. + let mut b = move || { + { + let a = &mut 3; + } + yield(); + }; + Pin::new(&mut b).resume(()); +} + +fn borrow_local() { + // Not OK to yield with a borrow of a temporary. + // + // (This error occurs because the region shows up in the type of + // `b` and gets extended by region inference.) + let mut b = move || { + let a = 3; + { + let b = &a; + //~^ ERROR borrow may still be in use when generator yields + yield(); + println!("{}", b); + } + }; + Pin::new(&mut b).resume(()); +} + +fn main() { } diff --git a/tests/ui/generator/yield-while-local-borrowed.stderr b/tests/ui/generator/yield-while-local-borrowed.stderr new file mode 100644 index 000000000..c1513ef9b --- /dev/null +++ b/tests/ui/generator/yield-while-local-borrowed.stderr @@ -0,0 +1,21 @@ +error[E0626]: borrow may still be in use when generator yields + --> $DIR/yield-while-local-borrowed.rs:13:17 + | +LL | let a = &mut 3; + | ^^^^^^ +LL | +LL | yield(); + | ------- possible yield occurs here + +error[E0626]: borrow may still be in use when generator yields + --> $DIR/yield-while-local-borrowed.rs:40:21 + | +LL | let b = &a; + | ^^ +LL | +LL | yield(); + | ------- possible yield occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/generator/yield-while-ref-reborrowed.rs b/tests/ui/generator/yield-while-ref-reborrowed.rs new file mode 100644 index 000000000..a03ef945d --- /dev/null +++ b/tests/ui/generator/yield-while-ref-reborrowed.rs @@ -0,0 +1,40 @@ +#![feature(generators, generator_trait)] + +use std::ops::{GeneratorState, Generator}; +use std::cell::Cell; +use std::pin::Pin; + +fn reborrow_shared_ref(x: &i32) { + // This is OK -- we have a borrow live over the yield, but it's of + // data that outlives the generator. + let mut b = move || { + let a = &*x; + yield(); + println!("{}", a); + }; + Pin::new(&mut b).resume(()); +} + +fn reborrow_mutable_ref(x: &mut i32) { + // This is OK -- we have a borrow live over the yield, but it's of + // data that outlives the generator. + let mut b = move || { + let a = &mut *x; + yield(); + println!("{}", a); + }; + Pin::new(&mut b).resume(()); +} + +fn reborrow_mutable_ref_2(x: &mut i32) { + // ...but not OK to go on using `x`. + let mut b = || { + let a = &mut *x; + yield(); + println!("{}", a); + }; + println!("{}", x); //~ ERROR + Pin::new(&mut b).resume(()); +} + +fn main() { } diff --git a/tests/ui/generator/yield-while-ref-reborrowed.stderr b/tests/ui/generator/yield-while-ref-reborrowed.stderr new file mode 100644 index 000000000..47147f9c0 --- /dev/null +++ b/tests/ui/generator/yield-while-ref-reborrowed.stderr @@ -0,0 +1,18 @@ +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/yield-while-ref-reborrowed.rs:36:20 + | +LL | let mut b = || { + | -- generator construction occurs here +LL | let a = &mut *x; + | -- first borrow occurs due to use of `x` in generator +... +LL | println!("{}", x); + | ^ second borrow occurs here +LL | Pin::new(&mut b).resume(()); + | ------ first borrow later used here + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0501`. diff --git a/tests/ui/generator/yielding-in-match-guards.rs b/tests/ui/generator/yielding-in-match-guards.rs new file mode 100644 index 000000000..4e89fc975 --- /dev/null +++ b/tests/ui/generator/yielding-in-match-guards.rs @@ -0,0 +1,53 @@ +// build-pass +// edition:2018 + +// This test is derived from +// https://github.com/rust-lang/rust/issues/72651#issuecomment-668720468 + +// This test demonstrates that, in `async fn g()`, +// indeed a temporary borrow `y` from `x` is live +// while `f().await` is being evaluated. +// Thus, `&'_ u8` should be included in type signature +// of the underlying generator. + +#![feature(if_let_guard)] + +async fn f() -> u8 { 1 } +async fn foo() -> [bool; 10] { [false; 10] } + +pub async fn g(x: u8) { + match x { + y if f().await == y => (), + _ => (), + } +} + +// #78366: check the reference to the binding is recorded even if the binding is not autorefed + +async fn h(x: usize) { + match x { + y if foo().await[y] => (), + _ => (), + } +} + +async fn i(x: u8) { + match x { + y if f().await == y + 1 => (), + _ => (), + } +} + +async fn j(x: u8) { + match x { + y if let (1, 42) = (f().await, y) => (), + _ => (), + } +} + +fn main() { + let _ = g(10); + let _ = h(9); + let _ = i(8); + let _ = j(7); +} diff --git a/tests/ui/generic-associated-types/anonymize-bound-vars.rs b/tests/ui/generic-associated-types/anonymize-bound-vars.rs new file mode 100644 index 000000000..eb7a12412 --- /dev/null +++ b/tests/ui/generic-associated-types/anonymize-bound-vars.rs @@ -0,0 +1,13 @@ +// check-pass +// +// regression test for #98702 + +trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = [T; 2*2]; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/auxiliary/foo_defn.rs b/tests/ui/generic-associated-types/auxiliary/foo_defn.rs new file mode 100644 index 000000000..21a9b3b89 --- /dev/null +++ b/tests/ui/generic-associated-types/auxiliary/foo_defn.rs @@ -0,0 +1,6 @@ +use std::{future::Future, pin::Pin}; + +pub trait Foo { + type Bar: AsRef<()>; + fn foo(&self) -> Pin + '_>>; +} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs new file mode 100644 index 000000000..5101de19d --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.rs @@ -0,0 +1,34 @@ +// check-fail +// known-bug: unknown + +// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for +// all 'a where I::Item<'a> is WF", but really means "for all 'a possible" + +use std::fmt::Debug; + +pub trait LendingIterator { + type Item<'this> + where + Self: 'this; +} + +pub struct WindowsMut<'x> { + slice: &'x (), +} + +impl<'y> LendingIterator for WindowsMut<'y> { + type Item<'this> = &'this mut () where 'y: 'this; +} + +fn print_items(_iter: I) +where + I: LendingIterator, + for<'a> I::Item<'a>: Debug, +{ +} + +fn main() { + let slice = &mut (); + let windows = WindowsMut { slice }; + print_items::>(windows); +} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr new file mode 100644 index 000000000..362aeae23 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/hrtb-implied-1.rs:31:22 + | +LL | let slice = &mut (); + | ^^ creates a temporary value which is freed while still in use +LL | let windows = WindowsMut { slice }; +LL | print_items::>(windows); + | -------------------------------------- argument requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-implied-1.rs:26:26 + | +LL | for<'a> I::Item<'a>: Debug, + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs new file mode 100644 index 000000000..3174227a7 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.rs @@ -0,0 +1,39 @@ +// check-fail +// known-bug: unknown + +// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for +// all 'a where I::Item<'a> is WF", but really means "for all 'a possible" + +trait LendingIterator: Sized { + type Item<'a> + where + Self: 'a; + fn next(&mut self) -> Self::Item<'_>; +} +fn fails(iter: &mut I, f: F) -> bool +where + F: FnMut(I::Item<'_>), +{ + let mut iter2 = Eat(iter, f); + let _next = iter2.next(); + true +} +impl LendingIterator for &mut I { + type Item<'a> = I::Item<'a> where Self:'a; + fn next(&mut self) -> Self::Item<'_> { + (**self).next() + } +} + +struct Eat(I, F); +impl Iterator for Eat +where + F: FnMut(I::Item<'_>), +{ + type Item = (); + fn next(&mut self) -> Option { + None + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr new file mode 100644 index 000000000..1ee270398 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/hrtb-implied-2.rs:18:17 + | +LL | fn fails(iter: &mut I, f: F) -> bool + | ---- - let's call the lifetime of this reference `'1` + | | + | `iter` is a reference that is only valid in the function body +... +LL | let _next = iter2.next(); + | ^^^^^^^^^^^^ + | | + | `iter` escapes the function body here + | argument requires that `'1` must outlive `'static` + | + = note: requirement occurs because of a mutable reference to `Eat<&mut I, F>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + = note: due to current limitations in the borrow checker, this implies a `'static` lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs new file mode 100644 index 000000000..bc9e6c8ae --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs @@ -0,0 +1,23 @@ +trait LendingIterator { + type Item<'a> + where + Self: 'a; +} + +impl LendingIterator for &str { + type Item<'a> = () where Self:'a; +} + +fn trivial_bound(_: I) +where + I: LendingIterator, + for<'a> I::Item<'a>: Sized, +{ +} + +fn fails(iter: &str) { + trivial_bound(iter); + //~^ borrowed data escapes +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr new file mode 100644 index 000000000..c67e02437 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/hrtb-implied-3.rs:19:5 + | +LL | fn fails(iter: &str) { + | ---- - let's call the lifetime of this reference `'1` + | | + | `iter` is a reference that is only valid in the function body +LL | trivial_bound(iter); + | ^^^^^^^^^^^^^^^^^^^ + | | + | `iter` escapes the function body here + | argument requires that `'1` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-implied-3.rs:14:26 + | +LL | for<'a> I::Item<'a>: Sized, + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.rs b/tests/ui/generic-associated-types/bugs/issue-100013.rs new file mode 100644 index 000000000..973c548d7 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-100013.rs @@ -0,0 +1,35 @@ +// check-fail +// known-bug: unknown +// edition: 2021 + +// We really should accept this, but we need implied bounds between the regions +// in a generator interior. + +pub trait FutureIterator { + type Future<'s, 'cx>: Send + where + 's: 'cx; +} + +fn call() -> impl Send { + async { // a generator checked for autotrait impl `Send` + let x = None::>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + let x = None::>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + async { // a generator checked for autotrait impl `Send` + let x = None::>; // a type referencing GAT + async {}.await; // a yield point + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-100013.stderr b/tests/ui/generic-associated-types/bugs/issue-100013.stderr new file mode 100644 index 000000000..9db124a81 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-100013.stderr @@ -0,0 +1,78 @@ +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:15:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:16:38 + | +LL | let x = None::>; // a type referencing GAT + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:16:34 + | +LL | let x = None::>; // a type referencing GAT + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:22:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:21:14 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:21:10 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime may not live long enough + --> $DIR/issue-100013.rs:23:17 + | +LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | async { // a generator checked for autotrait impl `Send` +LL | let x = None::>; // a type referencing GAT + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime bound not satisfied + --> $DIR/issue-100013.rs:29:5 + | +LL | / async { // a generator checked for autotrait impl `Send` +LL | | let x = None::>; // a type referencing GAT +LL | | async {}.await; // a yield point +LL | | } + | |_____^ + | +note: the lifetime defined here... + --> $DIR/issue-100013.rs:28:18 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ +note: ...must outlive the lifetime defined here + --> $DIR/issue-100013.rs:28:10 + | +LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send { + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: aborting due to 4 previous errors + diff --git a/tests/ui/generic-associated-types/bugs/issue-80626.rs b/tests/ui/generic-associated-types/bugs/issue-80626.rs new file mode 100644 index 000000000..d6e18010f --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-80626.rs @@ -0,0 +1,12 @@ +// check-pass + +trait Allocator { + type Allocated; +} + +enum LinkedList { + Head, + Next(A::Allocated), +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.rs b/tests/ui/generic-associated-types/bugs/issue-87735.rs new file mode 100644 index 000000000..80737a798 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87735.rs @@ -0,0 +1,44 @@ +// check-fail +// known-bug: #87735, #88526 + +// This should pass, but we need an extension of implied bounds (probably). + +pub trait AsRef2 { + type Output<'a> where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a>; +} + +impl AsRef2 for Vec { + type Output<'a> = &'a [T] where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + &self[..] + } +} + +#[derive(Debug)] +struct Foo(T); +#[derive(Debug)] +struct FooRef<'a, U>(&'a [U]); + +impl<'b, T, U> AsRef2 for Foo +where + // * `for<'b, 'c> T: AsRef2 = &'c [U]>>` does not work + // + // * `U` is unconstrained but should be allowed in this context because `Output` is + // an associated type + T: AsRef2 = &'b [U]>, + U: 'b +{ + type Output<'a> = FooRef<'a, U> where Self: 'a; + + fn as_ref2<'a>(&'a self) -> Self::Output<'a> { + FooRef(self.0.as_ref2()) + } +} + +fn main() { + let foo = Foo(vec![1, 2, 3]); + dbg!(foo.as_ref2()); +} diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr new file mode 100644 index 000000000..ebe2054ce --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-87735.rs:25:13 + | +LL | impl<'b, T, U> AsRef2 for Foo + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87755.rs b/tests/ui/generic-associated-types/bugs/issue-87755.rs new file mode 100644 index 000000000..cda722d2f --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87755.rs @@ -0,0 +1,19 @@ +// check-fail +// known-bug: #87755 + +// This should pass. + +use std::fmt::Debug; + +trait Foo { + type Ass where Self::Ass: Debug; +} + +#[derive(Debug)] +struct Bar; + +impl Foo for Bar { + type Ass = Bar; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-87755.stderr b/tests/ui/generic-associated-types/bugs/issue-87755.stderr new file mode 100644 index 000000000..5e94db9b0 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87755.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Ass == _` + --> $DIR/issue-87755.rs:16:16 + | +LL | type Ass = Bar; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/bugs/issue-87803.rs b/tests/ui/generic-associated-types/bugs/issue-87803.rs new file mode 100644 index 000000000..56237e387 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87803.rs @@ -0,0 +1,25 @@ +// check-fail +// known-bug: #87803 + +// This should pass, but using a type alias vs a reference directly +// changes late-bound -> early-bound. + +trait Scanner { + type Input<'a>; + type Token<'a>; + + fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; +} + +struct IdScanner(); + +impl Scanner for IdScanner { + type Input<'a> = &'a str; + type Token<'a> = &'a str; + + fn scan<'a>(&mut self, s : &'a str) -> &'a str { + s + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-87803.stderr b/tests/ui/generic-associated-types/bugs/issue-87803.stderr new file mode 100644 index 000000000..fe2abdedb --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-87803.stderr @@ -0,0 +1,12 @@ +error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration + --> $DIR/issue-87803.rs:20:12 + | +LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; + | ---- lifetimes in impl do not match this method in trait +... +LL | fn scan<'a>(&mut self, s : &'a str) -> &'a str { + | ^^^^ lifetimes do not match method in trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.rs b/tests/ui/generic-associated-types/bugs/issue-88382.rs new file mode 100644 index 000000000..8f8cc4523 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88382.rs @@ -0,0 +1,29 @@ +// check-fail +// known-bug: #88382 + +// This should pass, but has a missed normalization due to HRTB. + +trait Iterable { + type Iterator<'a> where Self: 'a; + fn iter(&self) -> Self::Iterator<'_>; +} + +struct SomeImplementation(); + +impl Iterable for SomeImplementation { + type Iterator<'a> = std::iter::Empty; + fn iter(&self) -> Self::Iterator<'_> { + std::iter::empty() + } +} + +fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + f(&mut i.iter()); +} + +fn main() { + do_something(SomeImplementation(), |_| ()); + do_something(SomeImplementation(), test); +} + +fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} diff --git a/tests/ui/generic-associated-types/bugs/issue-88382.stderr b/tests/ui/generic-associated-types/bugs/issue-88382.stderr new file mode 100644 index 000000000..a9a70bb71 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88382.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/issue-88382.rs:26:40 + | +LL | do_something(SomeImplementation(), test); + | ------------ ^^^^ expected due to this + | | + | required by a bound introduced by this call +... +LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} + | ------------------------------------------------- found signature defined here + | + = note: expected function signature `for<'a> fn(&'a mut std::iter::Empty) -> _` + found function signature `for<'a, 'b> fn(&'b mut <_ as Iterable>::Iterator<'a>) -> _` +note: required by a bound in `do_something` + --> $DIR/issue-88382.rs:20:48 + | +LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.rs b/tests/ui/generic-associated-types/bugs/issue-88460.rs new file mode 100644 index 000000000..224e696ad --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88460.rs @@ -0,0 +1,29 @@ +// check-fail +// known-bug: #88460 + +// This should pass, but has a missed normalization due to HRTB. + +pub trait Marker {} + +pub trait Trait { + type Assoc<'a>; +} + +fn test(value: T) +where + T: Trait, + for<'a> T::Assoc<'a>: Marker, +{ +} + +impl Marker for () {} + +struct Foo; + +impl Trait for Foo { + type Assoc<'a> = (); +} + +fn main() { + test(Foo); +} diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.stderr b/tests/ui/generic-associated-types/bugs/issue-88460.stderr new file mode 100644 index 000000000..6612c4b49 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88460.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied + --> $DIR/issue-88460.rs:28:10 + | +LL | test(Foo); + | ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` + | | + | required by a bound introduced by this call + | + = help: the trait `Marker` is implemented for `()` +note: required by a bound in `test` + --> $DIR/issue-88460.rs:15:27 + | +LL | fn test(value: T) + | ---- required by a bound in this +... +LL | for<'a> T::Assoc<'a>: Marker, + | ^^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.rs b/tests/ui/generic-associated-types/bugs/issue-88526.rs new file mode 100644 index 000000000..99397744f --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88526.rs @@ -0,0 +1,33 @@ +// check-fail +// known-bug: #88526 + +// This should pass, but requires more logic. + +trait A { + type I<'a>; +} + +pub struct TestA +{ + f: F, +} + +impl A for TestA { + type I<'a> = &'a F; +} + +struct TestB +{ + q: Q, + f: F, +} + +impl<'q, Q, I, F> A for TestB +where + Q: A = &'q I>, + F: Fn(I), +{ + type I<'a> = (); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr new file mode 100644 index 000000000..56857c655 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-88526.rs:25:13 + | +LL | impl<'q, Q, I, F> A for TestB + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.rs b/tests/ui/generic-associated-types/bugs/issue-91762.rs new file mode 100644 index 000000000..8f2cc4550 --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-91762.rs @@ -0,0 +1,28 @@ +// check-fail +// known-bug: unknown + +// We almost certainly want this to pass, but +// it's particularly difficult currently, because we need a way of specifying +// that `::With = Self` without using that when we have +// a `U`. See `https://github.com/rust-lang/rust/pull/92728` for a (hacky) +// solution. This might be better to just wait for Chalk. + +pub trait Functor { + type With; + + fn fmap(this: Self::With) -> Self::With; +} + +pub trait FunctorExt: Sized { + type Base: Functor = Self>; + + fn fmap(self) { + let arg: ::With; + let ret: ::With; + + arg = self; + ret = ::fmap(arg); + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/bugs/issue-91762.stderr b/tests/ui/generic-associated-types/bugs/issue-91762.stderr new file mode 100644 index 000000000..1272c8b8a --- /dev/null +++ b/tests/ui/generic-associated-types/bugs/issue-91762.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-91762.rs:24:15 + | +LL | ret = ::fmap(arg); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `fmap` + | +help: consider specifying the generic arguments + | +LL | ret = ::fmap::(arg); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/generic-associated-types/collections-project-default.rs b/tests/ui/generic-associated-types/collections-project-default.rs new file mode 100644 index 000000000..e08aa18cf --- /dev/null +++ b/tests/ui/generic-associated-types/collections-project-default.rs @@ -0,0 +1,70 @@ +#![feature(associated_type_defaults)] + +// A Collection trait and collection families. Based on +// https://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// associated-type-constructors-part-2-family-traits/ + +// check that we don't normalize with trait defaults. + +trait Collection { + type Iter<'iter>: Iterator where T: 'iter, Self: 'iter; + type Family: CollectionFamily; + // Test associated type defaults with parameters + type Sibling: Collection = + <>::Family as CollectionFamily>::Member; + + fn empty() -> Self; + + fn add(&mut self, value: T); + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; +} + +trait CollectionFamily { + type Member: Collection; +} + +struct VecFamily; + +impl CollectionFamily for VecFamily { + type Member = Vec; +} + +impl Collection for Vec { + type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter; + type Family = VecFamily; + + fn empty() -> Self { + Vec::new() + } + + fn add(&mut self, value: T) { + self.push(value) + } + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { + self.iter() + } +} + +fn floatify_sibling(ints: &C) -> >::Sibling +where + C: Collection, +{ + let mut res = ::Member::::empty(); + for &v in ints.iterate() { + res.add(v as f32); + } + res + //~^ ERROR mismatched types +} + +fn use_floatify() { + let a = vec![1i32, 2, 3]; + let c = floatify_sibling(&a); + assert_eq!(Some(&1.0), c.iterate().next()); +} + +fn main() { + use_floatify(); +} diff --git a/tests/ui/generic-associated-types/collections-project-default.stderr b/tests/ui/generic-associated-types/collections-project-default.stderr new file mode 100644 index 000000000..5701017dc --- /dev/null +++ b/tests/ui/generic-associated-types/collections-project-default.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/collections-project-default.rs:58:5 + | +LL | fn floatify_sibling(ints: &C) -> >::Sibling + | ------------------------------------ expected `>::Sibling` because of return type +... +LL | res + | ^^^ expected Collection::Sibling, found CollectionFamily::Member + | + = note: expected associated type `>::Sibling` + found associated type `<>::Family as CollectionFamily>::Member` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/collections.rs b/tests/ui/generic-associated-types/collections.rs new file mode 100644 index 000000000..15f429afb --- /dev/null +++ b/tests/ui/generic-associated-types/collections.rs @@ -0,0 +1,69 @@ +#![feature(associated_type_defaults)] + +// A Collection trait and collection families. Based on +// https://smallcultfollowing.com/babysteps/blog/2016/11/03/ +// associated-type-constructors-part-2-family-traits/ + +// run-pass + +trait Collection { + type Iter<'iter>: Iterator where T: 'iter, Self: 'iter; + type Family: CollectionFamily; + // Test associated type defaults with parameters + type Sibling: Collection = + <>::Family as CollectionFamily>::Member; + + fn empty() -> Self; + + fn add(&mut self, value: T); + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; +} + +trait CollectionFamily { + type Member: Collection; +} + +struct VecFamily; + +impl CollectionFamily for VecFamily { + type Member = Vec; +} + +impl Collection for Vec { + type Iter<'iter> = std::slice::Iter<'iter, T> where T: 'iter; + type Family = VecFamily; + + fn empty() -> Self { + Vec::new() + } + + fn add(&mut self, value: T) { + self.push(value) + } + + fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { + self.iter() + } +} + +fn floatify(ints: &C) -> <>::Family as CollectionFamily>::Member +where + C: Collection, +{ + let mut res = ::Member::::empty(); + for &v in ints.iterate() { + res.add(v as f32); + } + res +} + +fn use_floatify() { + let a = vec![1, 2, 3]; + let b = floatify(&a); + assert_eq!(Some(&1.0), b.iterate().next()); +} + +fn main() { + use_floatify(); +} diff --git a/tests/ui/generic-associated-types/collectivity-regression.rs b/tests/ui/generic-associated-types/collectivity-regression.rs new file mode 100644 index 000000000..54154f9d1 --- /dev/null +++ b/tests/ui/generic-associated-types/collectivity-regression.rs @@ -0,0 +1,22 @@ +// Regression test from https://github.com/rust-lang/rust/pull/98109 + +pub trait Get { + type Value<'a> + where + Self: 'a; +} + +fn multiply_at(x: T) +where + for<'a> T: Get = ()>, +{ + || { + //~^ `T` does not live long enough + // + // FIXME(#98437). This regressed at some point and + // probably should work. + let _x = x; + }; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/collectivity-regression.stderr b/tests/ui/generic-associated-types/collectivity-regression.stderr new file mode 100644 index 000000000..a085096e1 --- /dev/null +++ b/tests/ui/generic-associated-types/collectivity-regression.stderr @@ -0,0 +1,24 @@ +error: `T` does not live long enough + --> $DIR/collectivity-regression.rs:13:5 + | +LL | / || { +LL | | +LL | | // +LL | | // FIXME(#98437). This regressed at some point and +LL | | // probably should work. +LL | | let _x = x; +LL | | }; + | |_____^ + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/collectivity-regression.rs:11:16 + | +LL | for<'a> T: Get = ()>, + | ^^^^^^^^^^^^^^^^^^^ +help: consider restricting the type parameter to the `'static` lifetime + | +LL | for<'a> T: Get = ()> + 'static, + | +++++++++ + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs new file mode 100644 index 000000000..c5f9a25a6 --- /dev/null +++ b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-1.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test unsures that with_opt_const_param returns the +// def_id of the N param in the Foo::Assoc GAT. + +trait Foo { + type Assoc; + fn foo(&self) -> Self::Assoc<3>; +} + +impl Foo for () { + type Assoc = [(); N]; + fn foo(&self) -> Self::Assoc<3> { + [(); 3] + } +} + +fn main() { + assert_eq!(().foo(), [(); 3]); +} diff --git a/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs new file mode 100644 index 000000000..cd7941ed9 --- /dev/null +++ b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-2.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test unsures that with_opt_const_param returns the +// def_id of the N param in the Foo::Assoc GAT. + +trait Foo { + type Assoc; + fn foo(&self) -> Self::Assoc; +} + +impl Foo for () { + type Assoc = [(); N]; + fn foo(&self) -> Self::Assoc { + [(); N] + } +} + +fn main() { + assert_eq!(().foo::<10>(), [(); 10]); +} diff --git a/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs new file mode 100644 index 000000000..db61fc080 --- /dev/null +++ b/tests/ui/generic-associated-types/const-generics-gat-in-trait-return-type-3.rs @@ -0,0 +1,25 @@ +// run-pass + +// This test unsures that with_opt_const_param returns the +// def_id of the N param in the Bar::Assoc GAT. + +trait Bar { + type Assoc; +} +trait Foo: Bar { + fn foo(&self) -> Self::Assoc<3>; +} + +impl Bar for () { + type Assoc = [(); N]; +} + +impl Foo for () { + fn foo(&self) -> Self::Assoc<3> { + [(); 3] + } +} + +fn main() { + assert_eq!(().foo(), [(); 3]); +} diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.rs b/tests/ui/generic-associated-types/const_params_have_right_type.rs new file mode 100644 index 000000000..d2cb12697 --- /dev/null +++ b/tests/ui/generic-associated-types/const_params_have_right_type.rs @@ -0,0 +1,10 @@ +trait Trait { + type Foo; +} + +impl Trait for () { + type Foo = u32; + //~^ error: type `Foo` has an incompatible generic parameter for trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.stderr b/tests/ui/generic-associated-types/const_params_have_right_type.stderr new file mode 100644 index 000000000..fdedd3bf5 --- /dev/null +++ b/tests/ui/generic-associated-types/const_params_have_right_type.stderr @@ -0,0 +1,16 @@ +error[E0053]: type `Foo` has an incompatible generic parameter for trait `Trait` + --> $DIR/const_params_have_right_type.rs:6:14 + | +LL | trait Trait { + | ----- +LL | type Foo; + | ----------- expected const parameter of type `u8` +... +LL | impl Trait for () { + | ----------------- +LL | type Foo = u32; + | ^^^^^^^^^^^^ found const parameter of type `u64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs new file mode 100644 index 000000000..c78a54997 --- /dev/null +++ b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.rs @@ -0,0 +1,14 @@ +// Test that correct syntax is used in suggestion to constrain associated type + +trait X { + type Y; +} + +fn f(a: T::Y) { + //~^ HELP consider constraining the associated type `::Y` to `Vec` + //~| SUGGESTION Y = Vec> + let b: Vec = a; + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr new file mode 100644 index 000000000..96c4330fe --- /dev/null +++ b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/constraint-assoc-type-suggestion.rs:10:23 + | +LL | let b: Vec = a; + | -------- ^ expected struct `Vec`, found associated type + | | + | expected due to this + | + = note: expected struct `Vec` + found associated type `::Y` +help: consider constraining the associated type `::Y` to `Vec` + | +LL | fn f = Vec>>(a: T::Y) { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/construct_with_other_type.rs b/tests/ui/generic-associated-types/construct_with_other_type.rs new file mode 100644 index 000000000..5cb07f558 --- /dev/null +++ b/tests/ui/generic-associated-types/construct_with_other_type.rs @@ -0,0 +1,22 @@ +// check-pass + +use std::ops::Deref; + +trait Foo { + type Bar<'a, 'b>; +} + +trait Baz { + type Quux<'a>: Foo where Self: 'a; + + // This weird type tests that we can use universal function call syntax to access the Item on + type Baa<'a>: Deref as Foo>::Bar<'a, 'static>> where Self: 'a; +} + +impl Baz for T where T: Foo { + type Quux<'a> = T where T: 'a; + + type Baa<'a> = &'a ::Bar<'a, 'static> where T: 'a; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/cross-crate-bounds.rs b/tests/ui/generic-associated-types/cross-crate-bounds.rs new file mode 100644 index 000000000..8934a07fd --- /dev/null +++ b/tests/ui/generic-associated-types/cross-crate-bounds.rs @@ -0,0 +1,32 @@ +// regression test for #73816 +// We handled bounds differently when `feature(generic_associated_types)` was enabled + +// edition:2018 +// aux-build:foo_defn.rs + +extern crate foo_defn; + +use foo_defn::Foo; +use std::{future::Future, pin::Pin}; + +pub struct FooImpl; + +impl Foo for FooImpl { + type Bar = (); + //~^ ERROR the trait bound `(): AsRef<()>` is not satisfied + fn foo(&self) -> Pin + '_>> { + panic!() + } +} + +async fn foo() { + bar(&FooImpl).await; +} + +async fn bar(foo: &F) { + foo.foo().await.as_ref(); +} + +fn main() { + // futures::executor::block_on(foo()); +} diff --git a/tests/ui/generic-associated-types/cross-crate-bounds.stderr b/tests/ui/generic-associated-types/cross-crate-bounds.stderr new file mode 100644 index 000000000..83ee04d5a --- /dev/null +++ b/tests/ui/generic-associated-types/cross-crate-bounds.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): AsRef<()>` is not satisfied + --> $DIR/cross-crate-bounds.rs:15:16 + | +LL | type Bar = (); + | ^^ the trait `AsRef<()>` is not implemented for `()` + | +note: required by a bound in `foo_defn::Foo::Bar` + --> $DIR/auxiliary/foo_defn.rs:4:15 + | +LL | type Bar: AsRef<()>; + | ^^^^^^^^^ required by this bound in `Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/elided-in-expr-position.rs b/tests/ui/generic-associated-types/elided-in-expr-position.rs new file mode 100644 index 000000000..e40093305 --- /dev/null +++ b/tests/ui/generic-associated-types/elided-in-expr-position.rs @@ -0,0 +1,37 @@ +#![allow(unused)] + +pub trait Trait { + type Assoc<'a> where Self: 'a; + + fn f(&self) -> Self::Assoc<'_>; + + // Disallow elision in return position, for now + fn g(&self) -> Self::Assoc; + //~^ ERROR missing generics for associated type `Trait::Assoc` +} + +pub struct Struct { + item: f32 +} + +pub struct GenericStruct<'a> { + ref_item: &'a f32 +} + +impl Trait for Struct { + type Assoc<'a> = GenericStruct<'a>; + + fn f(&self) -> Self::Assoc<'_> { + Self::Assoc { + ref_item: &self.item + } + } + + // Disallow elision in return position, for now + fn g(&self) -> Self::Assoc { + //~^ ERROR missing generics for associated type `Trait::Assoc` + todo!() + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/elided-in-expr-position.stderr b/tests/ui/generic-associated-types/elided-in-expr-position.stderr new file mode 100644 index 000000000..842b23bd4 --- /dev/null +++ b/tests/ui/generic-associated-types/elided-in-expr-position.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `Trait::Assoc` + --> $DIR/elided-in-expr-position.rs:9:26 + | +LL | fn g(&self) -> Self::Assoc; + | ^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/elided-in-expr-position.rs:4:10 + | +LL | type Assoc<'a> where Self: 'a; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | fn g(&self) -> Self::Assoc<'_>; + | ++++ + +error[E0107]: missing generics for associated type `Trait::Assoc` + --> $DIR/elided-in-expr-position.rs:31:26 + | +LL | fn g(&self) -> Self::Assoc { + | ^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/elided-in-expr-position.rs:4:10 + | +LL | type Assoc<'a> where Self: 'a; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | fn g(&self) -> Self::Assoc<'_> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/empty_generics.rs b/tests/ui/generic-associated-types/empty_generics.rs new file mode 100644 index 000000000..964c2972d --- /dev/null +++ b/tests/ui/generic-associated-types/empty_generics.rs @@ -0,0 +1,6 @@ +trait Foo { + type Bar<,>; + //~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/empty_generics.stderr b/tests/ui/generic-associated-types/empty_generics.stderr new file mode 100644 index 000000000..b753181cf --- /dev/null +++ b/tests/ui/generic-associated-types/empty_generics.stderr @@ -0,0 +1,13 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + --> $DIR/empty_generics.rs:2:14 + | +LL | trait Foo { + | - while parsing this item list starting here +LL | type Bar<,>; + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime +LL | +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/equality-bound.rs b/tests/ui/generic-associated-types/equality-bound.rs new file mode 100644 index 000000000..fcc2da801 --- /dev/null +++ b/tests/ui/generic-associated-types/equality-bound.rs @@ -0,0 +1,15 @@ +fn sum>(i: I) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses + panic!() +} +fn sum2(i: I) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses + panic!() +} +fn sum3(i: J) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses +//~| ERROR failed to resolve: use of undeclared type `I` + panic!() +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr new file mode 100644 index 000000000..d78f7a7fb --- /dev/null +++ b/tests/ui/generic-associated-types/equality-bound.stderr @@ -0,0 +1,43 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:1:51 + | +LL | fn sum>(i: I) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn sum>(i: I) -> i32 where I::Item = i32 { +LL + fn sum>(i: I) -> i32 where { + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:5:41 + | +LL | fn sum2(i: I) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn sum2(i: I) -> i32 where I::Item = i32 { +LL + fn sum2>(i: I) -> i32 where { + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:9:41 + | +LL | fn sum3(i: J) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information + +error[E0433]: failed to resolve: use of undeclared type `I` + --> $DIR/equality-bound.rs:9:41 + | +LL | fn sum3(i: J) -> i32 where I::Item = i32 { + | ^ use of undeclared type `I` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr new file mode 100644 index 000000000..614c4a34c --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator.rs:13:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs new file mode 100644 index 000000000..247761dd0 --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -0,0 +1,38 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait FromLendingIterator: Sized { + fn from_iter LendingIterator = A>>(iter: T) -> Self; +} + +impl FromLendingIterator for Vec { + fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + //[base]~^ impl has stricter + let mut v = vec![]; + while let Some(item) = iter.next() { + v.push(item); + } + v + } +} + +pub trait LendingIterator { + type Item<'z> + where + Self: 'z; + fn next(&mut self) -> Option>; + + fn collect>(self) -> B + where + Self: Sized, + Self: for<'q> LendingIterator = A>, + { + >::from_iter(self) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr new file mode 100644 index 000000000..f6b0b644e --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/lending_iterator_2.rs:13:45 + | +LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; + | ------------------------------------------------------------------------ definition of `from_iter` from trait +... +LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs new file mode 100644 index 000000000..eb9c0456a --- /dev/null +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -0,0 +1,30 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait FromLendingIterator: Sized { + fn from_iter LendingIterator = A>>(iter: T) -> Self; +} + +impl FromLendingIterator for Vec { + fn from_iter LendingIterator = A>>(mut iter: I) -> Self { + //[base]~^ impl has stricter + let mut v = vec![]; + while let Some(item) = iter.next() { + v.push(item); + } + v + } +} + +pub trait LendingIterator { + type Item<'a> + where + Self: 'a; + fn next(&mut self) -> Option>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs new file mode 100644 index 000000000..86b164ba7 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs @@ -0,0 +1,9 @@ +trait X { + type Y<'x>; +} + +fn main() { + fn _f(arg : Box X = &'a [u32]>>) {} + //~^ ERROR: use of undeclared lifetime name `'x` + //~| ERROR: binding for associated type `Y` references lifetime +} diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr new file mode 100644 index 000000000..b77f10084 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr @@ -0,0 +1,26 @@ +error[E0261]: use of undeclared lifetime name `'x` + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:6:35 + | +LL | fn _f(arg : Box X = &'a [u32]>>) {} + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'x` lifetime + | +LL | fn _f(arg : Box X = &'a [u32]>>) {} + | +++ +help: consider introducing lifetime `'x` here + | +LL | fn _f<'x>(arg : Box X = &'a [u32]>>) {} + | ++++ + +error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:6:33 + | +LL | fn _f(arg : Box X = &'a [u32]>>) {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0582. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr new file mode 100644 index 000000000..fd54faaf3 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:26:17 + | +LL | fn f(_arg : Box Foo = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/gat-in-trait-path.rs:10:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs new file mode 100644 index 000000000..c55f5a726 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -0,0 +1,33 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![feature(associated_type_defaults)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait Foo { + type A<'a> where Self: 'a; +} + +struct Fooy; + +impl Foo for Fooy { + type A<'a> = &'a (); +} + +#[derive(Clone)] +struct Fooer(T); + +impl Foo for Fooer { + type A<'x> = &'x () where T: 'x; +} + +fn f(_arg : Box Foo = &'a ()>>) {} +//[base]~^ the trait `Foo` cannot be made into an object + + +fn main() { + let foo = Fooer(5); + f(Box::new(foo)); +} diff --git a/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs new file mode 100644 index 000000000..d00c036fb --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs @@ -0,0 +1,14 @@ +trait Foo { + type F<'a>; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl Foo for T { + //~^ ERROR: the type parameter `T1` is not constrained + type F = &[u8]; + //~^ ERROR: the name `T1` is already used for + //~| ERROR: `&` without an explicit lifetime name cannot be used here +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr new file mode 100644 index 000000000..cb2b9f32b --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -0,0 +1,25 @@ +error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters + --> $DIR/gat-trait-path-generic-type-arg.rs:9:12 + | +LL | impl Foo for T { + | -- first use of `T1` +LL | +LL | type F = &[u8]; + | ^^ already used + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/gat-trait-path-generic-type-arg.rs:9:18 + | +LL | type F = &[u8]; + | ^ explicit lifetime name needed here + +error[E0207]: the type parameter `T1` is not constrained by the impl trait, self type, or predicates + --> $DIR/gat-trait-path-generic-type-arg.rs:7:10 + | +LL | impl Foo for T { + | ^^ unconstrained type parameter + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0207, E0403, E0637. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs new file mode 100644 index 000000000..83b86f04a --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs @@ -0,0 +1,15 @@ +trait X { + type Y<'a>; + + fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t } +} + +impl X for T { + fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { + //~^ ERROR missing generics for associated type + //~^^ ERROR missing generics for associated type + t + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr new file mode 100644 index 000000000..499221637 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:8:20 + | +LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-missing-lifetime.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { + | ++++ + +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/gat-trait-path-missing-lifetime.rs:8:20 + | +LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-missing-lifetime.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs new file mode 100644 index 000000000..9eb069637 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -0,0 +1,16 @@ +trait X { + type Y<'a>; +} + +fn foo<'a>(arg: Box>) {} + //~^ ERROR: lifetime in trait object type must be followed by `+` + //~| ERROR: parenthesized generic arguments cannot be used + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument + //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + + +fn bar<'a>(arg: Box>) {} + //~^ ERROR: parenthesized generic arguments cannot be used + //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr new file mode 100644 index 000000000..165779796 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -0,0 +1,74 @@ +error: lifetime in trait object type must be followed by `+` + --> $DIR/gat-trait-path-parenthesised-args.rs:5:29 + | +LL | fn foo<'a>(arg: Box>) {} + | ^^ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 + | +LL | fn foo<'a>(arg: Box>) {} + | ^^^^^ + | +help: use angle brackets instead + | +LL | fn foo<'a>(arg: Box = &'a ()>>) {} + | ~ ~ + +error: parenthesized generic arguments cannot be used in associated type constraints + --> $DIR/gat-trait-path-parenthesised-args.rs:12:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^-- + | | + | help: remove these parentheses + +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 + | +LL | fn foo<'a>(arg: Box>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn foo<'a>(arg: Box>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 + | +LL | fn foo<'a>(arg: Box>) {} + | ^---- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ + +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/gat-trait-path-parenthesised-args.rs:12:27 + | +LL | fn bar<'a>(arg: Box>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn bar<'a>(arg: Box>) {} + | ++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/generic-associated-type-bounds.rs b/tests/ui/generic-associated-types/generic-associated-type-bounds.rs new file mode 100644 index 000000000..fdc5a7267 --- /dev/null +++ b/tests/ui/generic-associated-types/generic-associated-type-bounds.rs @@ -0,0 +1,32 @@ +// run-pass + +pub trait X { + type Y<'a> where Self: 'a; + fn m(&self) -> Self::Y<'_>; +} + +impl X for () { + type Y<'a> = &'a (); + + fn m(&self) -> Self::Y<'_> { + self + } +} + +fn f(x: &impl for<'a> X = &'a ()>) -> &() { + x.m() +} + +fn g X = &'a ()>>(x: &T) -> &() { + x.m() +} + +fn h(x: &()) -> &() { + x.m() +} + +fn main() { + f(&()); + g(&()); + h(&()); +} diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.rs b/tests/ui/generic-associated-types/generic-associated-types-where.rs new file mode 100644 index 000000000..bbdfffafe --- /dev/null +++ b/tests/ui/generic-associated-types/generic-associated-types-where.rs @@ -0,0 +1,26 @@ +// Checking the interaction with this other feature +#![feature(associated_type_defaults)] + +use std::fmt::{Display, Debug}; + +trait Foo { + type Assoc where Self: Sized; + type Assoc2 where T: Display; + type Assoc3; + type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator; + type NoGenerics; +} + +struct Bar; + +impl Foo for Bar { + type Assoc = usize; + type Assoc2 = Vec; + //~^ ERROR `T` doesn't implement `std::fmt::Display` + type Assoc3 = Vec where T: Iterator; + //~^ ERROR impl has stricter requirements than trait + type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator; + type NoGenerics = ::std::cell::Cell; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.stderr b/tests/ui/generic-associated-types/generic-associated-types-where.stderr new file mode 100644 index 000000000..9a745c099 --- /dev/null +++ b/tests/ui/generic-associated-types/generic-associated-types-where.stderr @@ -0,0 +1,25 @@ +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/generic-associated-types-where.rs:18:22 + | +LL | type Assoc2 = Vec; + | ^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting type parameter `T` + | +LL | type Assoc2 = Vec; + | +++++++++++++++++++ + +error[E0276]: impl has stricter requirements than trait + --> $DIR/generic-associated-types-where.rs:20:38 + | +LL | type Assoc3; + | -------------- definition of `Assoc3` from trait +... +LL | type Assoc3 = Vec where T: Iterator; + | ^^^^^^^^ impl has extra requirement `T: Iterator` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs new file mode 100644 index 000000000..2cb218bf8 --- /dev/null +++ b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.rs @@ -0,0 +1,13 @@ +use std::ops::Deref; + +trait Iterable { + type Item<'a>; + type Iter<'a>: Iterator> + + Deref>; + //~^ ERROR undeclared lifetime + + fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; + //~^ ERROR undeclared lifetime +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr new file mode 100644 index 000000000..396ff15ab --- /dev/null +++ b/tests/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -0,0 +1,38 @@ +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/generic_associated_type_undeclared_lifetimes.rs:6:37 + | +LL | + Deref>; + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | + for<'b> Deref>; + | +++++++ +help: consider introducing lifetime `'b` here + | +LL | type Iter<'b, 'a>: Iterator> + | +++ +help: consider introducing lifetime `'b` here + | +LL | trait Iterable<'b> { + | ++++ + +error[E0261]: use of undeclared lifetime name `'undeclared` + --> $DIR/generic_associated_type_undeclared_lifetimes.rs:9:41 + | +LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; + | ^^^^^^^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'undeclared` here + | +LL | fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>; + | ++++++++++++ +help: consider introducing lifetime `'undeclared` here + | +LL | trait Iterable<'undeclared> { + | +++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/generic-associated-types/impl_bounds.rs b/tests/ui/generic-associated-types/impl_bounds.rs new file mode 100644 index 000000000..e45bdcf92 --- /dev/null +++ b/tests/ui/generic-associated-types/impl_bounds.rs @@ -0,0 +1,24 @@ +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a> where Self: 'a; + type B<'a, 'b> where 'a: 'b; + type C where Self: Clone; + fn d() where Self: Clone; +} + +#[derive(Copy, Clone)] +struct Fooy(T); + +impl Foo for Fooy { + type A<'a> = (&'a ()) where Self: 'static; + //~^ ERROR impl has stricter requirements than trait + type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + //~^ ERROR impl has stricter requirements than trait + type C = String where Self: Copy; + //~^ ERROR the trait bound `T: Copy` is not satisfied + fn d() where Self: Copy {} + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr new file mode 100644 index 000000000..261070d1d --- /dev/null +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -0,0 +1,77 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/impl_bounds.rs:14:39 + | +LL | type A<'a> where Self: 'a; + | ---------- definition of `A` from trait +... +LL | type A<'a> = (&'a ()) where Self: 'static; + | ^^^^^^^ impl has extra requirement `T: 'static` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/impl_bounds.rs:16:48 + | +LL | type B<'a, 'b> where 'a: 'b; + | -------------- definition of `B` from trait +... +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; + | ^^ impl has extra requirement `'b: 'a` + | +help: copy the `where` clause predicates from the trait + | +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'a: 'b; + | ~~~~~~~~~~~~ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/impl_bounds.rs:18:33 + | +LL | type C = String where Self: Copy; + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required for `Fooy` to implement `Copy` + --> $DIR/impl_bounds.rs:10:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro +note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type + --> $DIR/impl_bounds.rs:6:10 + | +LL | trait Foo { + | --- in this trait +... +LL | type C where Self: Clone; + | ^ this trait's associated type doesn't have the requirement `Fooy: Copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | impl Foo for Fooy { + | +++++++++++++++++++ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/impl_bounds.rs:20:24 + | +LL | fn d() where Self: Copy {} + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required for `Fooy` to implement `Copy` + --> $DIR/impl_bounds.rs:10:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ unsatisfied trait bound introduced in this `derive` macro +note: the requirement `Fooy: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method + --> $DIR/impl_bounds.rs:7:8 + | +LL | trait Foo { + | --- in this trait +... +LL | fn d() where Self: Clone; + | ^ this trait's method doesn't have the requirement `Fooy: Copy` + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | impl Foo for Fooy { + | +++++++++++++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/impl_bounds_ok.rs b/tests/ui/generic-associated-types/impl_bounds_ok.rs new file mode 100644 index 000000000..88f829ea2 --- /dev/null +++ b/tests/ui/generic-associated-types/impl_bounds_ok.rs @@ -0,0 +1,29 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a> where Self: 'a; + type B<'a, 'b> where 'a: 'b; + type C where Self: Clone; +} + +#[derive(Clone)] +struct Fooy; + +impl Foo for Fooy { + type A<'a> = (&'a ()); + type B<'a: 'b, 'b> = (&'a(), &'b ()); + type C = String; +} + +#[derive(Clone)] +struct Fooer(T); + +impl Foo for Fooer { + type A<'x> = (&'x ()) where T: 'x; + type B<'u, 'v> = (&'v &'u ()) where 'u: 'v; + type C = String where Self: Clone + ToOwned; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-101020.rs b/tests/ui/generic-associated-types/issue-101020.rs new file mode 100644 index 000000000..80d0fa5ad --- /dev/null +++ b/tests/ui/generic-associated-types/issue-101020.rs @@ -0,0 +1,35 @@ +pub trait LendingIterator { + type Item<'a> + where + Self: 'a; + + fn consume(self, _f: F) + where + Self: Sized, + for<'a> Self::Item<'a>: FuncInput<'a, Self::Item<'a>>, + { + } +} + +impl LendingIterator for &mut I { + type Item<'a> = I::Item<'a> where Self: 'a; +} +struct EmptyIter; +impl LendingIterator for EmptyIter { + type Item<'a> = &'a mut () where Self:'a; +} +pub trait FuncInput<'a, F> +where + F: Foo, + Self: Sized, +{ +} +impl<'a, T, F: 'a> FuncInput<'a, F> for T where F: Foo {} +trait Foo {} + +fn map_test() { + (&mut EmptyIter).consume(()); + //~^ ERROR the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr new file mode 100644 index 000000000..1f9273a8c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-101020.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satisfied + --> $DIR/issue-101020.rs:31:22 + | +LL | (&mut EmptyIter).consume(()); + | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()` + | +note: required for `&'a mut ()` to implement `for<'a> FuncInput<'a, &'a mut ()>` + --> $DIR/issue-101020.rs:27:20 + | +LL | impl<'a, T, F: 'a> FuncInput<'a, F> for T where F: Foo {} + | ^^^^^^^^^^^^^^^^ ^ ------ unsatisfied trait bound introduced here +note: required by a bound in `LendingIterator::consume` + --> $DIR/issue-101020.rs:9:33 + | +LL | fn consume(self, _f: F) + | ------- required by a bound in this +... +LL | for<'a> Self::Item<'a>: FuncInput<'a, Self::Item<'a>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `LendingIterator::consume` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-102114.rs b/tests/ui/generic-associated-types/issue-102114.rs new file mode 100644 index 000000000..de31737ef --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102114.rs @@ -0,0 +1,16 @@ +trait A { + type B<'b>; + fn a() -> Self::B<'static>; +} + +struct C; + +struct Wrapper(T); + +impl A for C { + type B = Wrapper; + //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters + fn a() -> Self::B<'static> {} +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-102114.stderr b/tests/ui/generic-associated-types/issue-102114.stderr new file mode 100644 index 000000000..8e41dee54 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102114.stderr @@ -0,0 +1,12 @@ +error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/issue-102114.rs:11:12 + | +LL | type B<'b>; + | -- expected 0 type parameters +... +LL | type B = Wrapper; + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/generic-associated-types/issue-102333.rs b/tests/ui/generic-associated-types/issue-102333.rs new file mode 100644 index 000000000..6c7256332 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102333.rs @@ -0,0 +1,15 @@ +// check-pass + +trait A { + type T: B = ()>; +} + +trait B { + type U; +} + +fn f() { + let _: <::T as B>::U<1i32> = (); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.rs b/tests/ui/generic-associated-types/issue-102335-gat.rs new file mode 100644 index 000000000..a7255fdcb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102335-gat.rs @@ -0,0 +1,12 @@ +trait T { + type A: S = ()>; + //~^ ERROR associated type bindings are not allowed here +} + +trait Q {} + +trait S { + type C: Q; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr new file mode 100644 index 000000000..7a7900a1e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-gat.rs:2:21 + | +LL | type A: S = ()>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/generic-associated-types/issue-47206-where-clause.rs b/tests/ui/generic-associated-types/issue-47206-where-clause.rs new file mode 100644 index 000000000..3d1b88ddf --- /dev/null +++ b/tests/ui/generic-associated-types/issue-47206-where-clause.rs @@ -0,0 +1,14 @@ +// Check that this program doesn't cause the compiler to error without output. + +trait Foo { + type Assoc3; +} + +struct Bar; + +impl Foo for Bar { + type Assoc3 = Vec where T: Iterator; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-47206-where-clause.stderr b/tests/ui/generic-associated-types/issue-47206-where-clause.stderr new file mode 100644 index 000000000..7006744df --- /dev/null +++ b/tests/ui/generic-associated-types/issue-47206-where-clause.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-47206-where-clause.rs:10:38 + | +LL | type Assoc3; + | -------------- definition of `Assoc3` from trait +... +LL | type Assoc3 = Vec where T: Iterator; + | ^^^^^^^^ impl has extra requirement `T: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs b/tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs new file mode 100644 index 000000000..625ccfe89 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-58694-parameter-out-of-range.rs @@ -0,0 +1,7 @@ +// check-pass + +trait Cert { + type PublicKey<'a>: From<&'a [u8]>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs b/tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs new file mode 100644 index 000000000..c1140bff8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-62326-parameter-out-of-range.rs @@ -0,0 +1,11 @@ +// check-pass + +trait Iterator { + type Item<'a>: 'a; +} + +impl Iterator for () { + type Item<'a> = &'a (); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67424.rs b/tests/ui/generic-associated-types/issue-67424.rs new file mode 100644 index 000000000..b6c7c70cd --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67424.rs @@ -0,0 +1,12 @@ +// check-pass +// Fixed by #67160 + +trait Trait1 { + type A; +} + +trait Trait2 { + type Type1: Trait1; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510-pass.base.stderr b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr new file mode 100644 index 000000000..4cc68530e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510-pass.rs:12:23 + | +LL | fn _func1<'a>(_x: Box=&'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-67510-pass.rs:9:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-67510-pass.rs b/tests/ui/generic-associated-types/issue-67510-pass.rs new file mode 100644 index 000000000..66ce3e807 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510-pass.rs @@ -0,0 +1,15 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait X { + type Y<'a>; +} + +fn _func1<'a>(_x: Box=&'a ()>>) {} +//[base]~^ ERROR the trait `X` cannot be made into an object + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510.rs b/tests/ui/generic-associated-types/issue-67510.rs new file mode 100644 index 000000000..ab5c25d74 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510.rs @@ -0,0 +1,10 @@ +trait X { + type Y<'a>; +} + +fn f(x: Box = &'a ()>>) {} +//~^ ERROR: use of undeclared lifetime name `'a` +//~| ERROR: use of undeclared lifetime name `'a` +//~| ERROR: the trait `X` cannot be made into an object [E0038] + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510.stderr b/tests/ui/generic-associated-types/issue-67510.stderr new file mode 100644 index 000000000..d25c5b0f3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510.stderr @@ -0,0 +1,50 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:5:21 + | +LL | fn f(x: Box = &'a ()>>) {} + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn f(x: Box X = &'a ()>>) {} + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn f<'a>(x: Box = &'a ()>>) {} + | ++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-67510.rs:5:28 + | +LL | fn f(x: Box = &'a ()>>) {} + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn f(x: Box X = &'a ()>>) {} + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn f<'a>(x: Box = &'a ()>>) {} + | ++++ + +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510.rs:5:13 + | +LL | fn f(x: Box = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-67510.rs:2:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0261. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs new file mode 100644 index 000000000..f1e779fcb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.rs @@ -0,0 +1,29 @@ +// Regression test for #68641 + +trait UnsafeCopy { + type Item<'a>: Copy; + + fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> { + *item + } +} + +impl UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() { + let mut s = String::from("Hello world!"); + + let copy = String::copy(&s); + + // Do we indeed point to the samme memory? + assert!(s.as_ptr() == copy.as_ptr()); + + // Any use of `copy` is certeinly UB after this + drop(s); + + // UB UB UB UB UB!! + println!("{}", copy); +} diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr new file mode 100644 index 000000000..6bb7492af --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-68641-check-gat-bounds.rs:12:21 + | +LL | type Item<'a> = T; + | ^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `UnsafeCopy::Item` + --> $DIR/issue-68641-check-gat-bounds.rs:4:20 + | +LL | type Item<'a>: Copy; + | ^^^^ required by this bound in `UnsafeCopy::Item` +help: consider restricting type parameter `T` + | +LL | impl UnsafeCopy for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs new file mode 100644 index 000000000..f5502adee --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -0,0 +1,18 @@ +// Regression test for #68642 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +fn main() { + usize>::callme(|| 1); +} diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr new file mode 100644 index 000000000..07452137b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68642-broken-llvm-ir.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68642-broken-llvm-ir.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.rs b/tests/ui/generic-associated-types/issue-68643-broken-mir.rs new file mode 100644 index 000000000..6050a8bf5 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -0,0 +1,18 @@ +// Regression test for #68643 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +pub fn main() { + ::callme(|| {}); +} diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr new file mode 100644 index 000000000..31ded5dab --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68643-broken-mir.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68643-broken-mir.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs b/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs new file mode 100644 index 000000000..898cfa1e7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -0,0 +1,18 @@ +// Regression test for #68644 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +fn main() { + ::callme(0); +} diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr new file mode 100644 index 000000000..e2f9930cc --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68644-codegen-selection.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68644-codegen-selection.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs new file mode 100644 index 000000000..60b065bfc --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -0,0 +1,18 @@ +// Regression test for #68645 + +trait Fun { + type F<'a>: Fn() -> u32; + + fn callme<'a>(f: Self::F<'a>) -> u32 { + f() + } +} + +impl Fun for T { + type F<'a> = Self; + //~^ ERROR expected a `Fn<()>` closure, found `T` +} + +fn main() { + <&dyn Iterator>::callme(&std::iter::once(1)); +} diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr new file mode 100644 index 000000000..0065368ad --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<()>` closure, found `T` + --> $DIR/issue-68645-codegen-fulfillment.rs:12:18 + | +LL | type F<'a> = Self; + | ^^^^ expected an `Fn<()>` closure, found `T` + | + = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `Fun::F` + --> $DIR/issue-68645-codegen-fulfillment.rs:4:17 + | +LL | type F<'a>: Fn() -> u32; + | ^^^^^^^^^^^ required by this bound in `Fun::F` +help: consider restricting type parameter `T` + | +LL | impl> Fun for T { + | ++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-68648-1.rs b/tests/ui/generic-associated-types/issue-68648-1.rs new file mode 100644 index 000000000..0df41bab3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68648-1.rs @@ -0,0 +1,22 @@ +// check-pass + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: for<'b> Fun = T>>(t: T) -> T::F<'a> { + T::identity(t) +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/tests/ui/generic-associated-types/issue-68648-2.rs b/tests/ui/generic-associated-types/issue-68648-2.rs new file mode 100644 index 000000000..0f963d58f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68648-2.rs @@ -0,0 +1,21 @@ +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: Fun = T>>(t: T) -> T::F<'a> { + T::identity(()) + //~^ ERROR: mismatched types +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/tests/ui/generic-associated-types/issue-68648-2.stderr b/tests/ui/generic-associated-types/issue-68648-2.stderr new file mode 100644 index 000000000..b2bef19eb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68648-2.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-68648-2.rs:12:17 + | +LL | fn bug<'a, T: Fun = T>>(t: T) -> T::F<'a> { + | - this type parameter +LL | T::identity(()) + | ----------- ^^ expected type parameter `T`, found `()` + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found unit type `()` +note: associated function defined here + --> $DIR/issue-68648-2.rs:4:8 + | +LL | fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } + | ^^^^^^^^ -------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-68649-pass.rs b/tests/ui/generic-associated-types/issue-68649-pass.rs new file mode 100644 index 000000000..772743877 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68649-pass.rs @@ -0,0 +1,22 @@ +// check-pass + +trait Fun { + type F<'a>; + + fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t } +} + +impl Fun for T { + type F<'a> = Self; +} + +fn bug<'a, T: Fun = T>>(t: T) -> T::F<'a> { + T::identity(t) +} + + +fn main() { + let x = 10; + + bug(x); +} diff --git a/tests/ui/generic-associated-types/issue-68653.rs b/tests/ui/generic-associated-types/issue-68653.rs new file mode 100644 index 000000000..170b87cf2 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68653.rs @@ -0,0 +1,13 @@ +// A regression test for #68653, which was fixed by #68938. + +// check-pass + +trait Fun { + type F<'a: 'a>; +} + +impl Fun for T { + type F<'a> = Self; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.rs b/tests/ui/generic-associated-types/issue-68656-unsized-values.rs new file mode 100644 index 000000000..607cfed0b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.rs @@ -0,0 +1,19 @@ +// Regression test for #68656 + +trait UnsafeCopy { + type Item<'a>: std::ops::Deref; + + fn bug<'a>(item: &Self::Item<'a>) -> () { + let x: T = **item; + &x as *const _; + } +} + +impl UnsafeCopy for T { + type Item<'a> = T; + //~^ ERROR type mismatch resolving `::Target == T` +} + +fn main() { + <&'static str>::bug(&""); +} diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr new file mode 100644 index 000000000..e8770aedf --- /dev/null +++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr @@ -0,0 +1,23 @@ +error[E0271]: type mismatch resolving `::Target == T` + --> $DIR/issue-68656-unsized-values.rs:13:21 + | +LL | impl UnsafeCopy for T { + | - this type parameter +LL | type Item<'a> = T; + | ^ expected type parameter `T`, found associated type + | + = note: expected type parameter `T` + found associated type `::Target` +note: required by a bound in `UnsafeCopy::Item` + --> $DIR/issue-68656-unsized-values.rs:4:36 + | +LL | type Item<'a>: std::ops::Deref; + | ^^^^^^^^^^ required by this bound in `UnsafeCopy::Item` +help: consider further restricting this bound + | +LL | impl> UnsafeCopy for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-70303.rs b/tests/ui/generic-associated-types/issue-70303.rs new file mode 100644 index 000000000..0edff5e4e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-70303.rs @@ -0,0 +1,57 @@ +// check-pass + +trait Document { + type Cursor<'a>: DocCursor<'a> where Self: 'a; + + fn cursor(&self) -> Self::Cursor<'_>; +} + +struct DocumentImpl {} + +impl Document for DocumentImpl { + type Cursor<'a> = DocCursorImpl<'a>; + + fn cursor(&self) -> Self::Cursor<'_> { + DocCursorImpl { + document: &self, + } + } +} + + +trait DocCursor<'a> {} + +struct DocCursorImpl<'a> { + document: &'a DocumentImpl, +} + +impl<'a> DocCursor<'a> for DocCursorImpl<'a> {} + +struct Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + cursor: Cursor, + _phantom: std::marker::PhantomData<&'d ()>, +} + + +impl<'d, Cursor> Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + pub fn from(document: &'d Doc) -> Lexer<'d, Cursor> + where + Doc: Document = Cursor>, + { + Lexer { + cursor: document.cursor(), + _phantom: std::marker::PhantomData, + } + } +} + +pub fn main() { + let doc = DocumentImpl {}; + let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); +} diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs new file mode 100644 index 000000000..8898d4c7d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-70304.rs @@ -0,0 +1,55 @@ +trait Document { + type Cursor<'a>: DocCursor<'a>; + //~^ ERROR: missing required bound on `Cursor` + + fn cursor(&self) -> Self::Cursor<'_>; +} + +struct DocumentImpl {} + +impl Document for DocumentImpl { + type Cursor<'a> = DocCursorImpl<'a>; + + fn cursor(&self) -> Self::Cursor<'_> { + DocCursorImpl { document: &self } + } +} + +trait DocCursor<'a> {} + +struct DocCursorImpl<'a> { + document: &'a DocumentImpl, +} + +impl<'a> DocCursor<'a> for DocCursorImpl<'a> {} + +struct Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + cursor: Cursor, + _phantom: std::marker::PhantomData<&'d ()>, +} + +impl<'d, Cursor> Lexer<'d, Cursor> +where + Cursor: DocCursor<'d>, +{ + pub fn from(document: &'d Doc) -> Lexer<'d, Cursor> + where + Doc: Document = Cursor>, + { + Lexer { cursor: document.cursor(), _phantom: std::marker::PhantomData } + } +} + +fn create_doc() -> impl Document = DocCursorImpl<'_>> { + //~^ ERROR `'_` cannot be used here [E0637] + //~| ERROR: missing lifetime specifier + DocumentImpl {} +} + +pub fn main() { + let doc = create_doc(); + let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); +} diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr new file mode 100644 index 000000000..99339e968 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -0,0 +1,33 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/issue-70304.rs:46:41 + | +LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { + | ^^ `'_` is a reserved lifetime name + +error[E0106]: missing lifetime specifier + --> $DIR/issue-70304.rs:46:61 + | +LL | fn create_doc() -> impl Document = DocCursorImpl<'_>> { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn create_doc() -> impl Document = DocCursorImpl<'static>> { + | ~~~~~~~ + +error: missing required bound on `Cursor` + --> $DIR/issue-70304.rs:2:5 + | +LL | type Cursor<'a>: DocCursor<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs new file mode 100644 index 000000000..f0e162d82 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -0,0 +1,18 @@ +trait Provider { + type A<'a>; +} + +impl Provider for () { + type A<'a> = (); +} + +struct Holder { + inner: Box>, + //~^ ERROR: missing generics for associated type +} + +fn main() { + Holder { + inner: Box::new(()), + }; +} diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr new file mode 100644 index 000000000..4b4fe43e8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Provider::A` + --> $DIR/issue-71176.rs:10:27 + | +LL | inner: Box>, + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-71176.rs:2:10 + | +LL | type A<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | inner: Box = B>>, + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-74684-1.rs b/tests/ui/generic-associated-types/issue-74684-1.rs new file mode 100644 index 000000000..e9ec80074 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-1.rs @@ -0,0 +1,23 @@ +trait Fun { + type F<'a>: ?Sized; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl Fun for T { + type F<'a> = [u8]; +} + +fn bug<'a, T: ?Sized + Fun = [u8]>>(_ : Box) -> &'static T::F<'a> { + let a = [0; 1]; + let _x = T::identity(&a); + //~^ ERROR: `a` does not live long enough + todo!() +} + + +fn main() { + let x = 10; + + bug(Box::new(x)); +} diff --git a/tests/ui/generic-associated-types/issue-74684-1.stderr b/tests/ui/generic-associated-types/issue-74684-1.stderr new file mode 100644 index 000000000..cacc97307 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-1.stderr @@ -0,0 +1,18 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-1.rs:13:26 + | +LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(_ : Box) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; +LL | let _x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/generic-associated-types/issue-74684-2.rs b/tests/ui/generic-associated-types/issue-74684-2.rs new file mode 100644 index 000000000..ff243af2c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-2.rs @@ -0,0 +1,23 @@ +trait Fun { + type F<'a>: ?Sized; + + fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t } +} + +impl Fun for T { + type F<'a> = i32; +} + +fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { + let a = [0; 1]; + let x = T::identity(&a); + todo!() +} + + +fn main() { + let x = 10; + + bug(Box::new(x)); + //~^ ERROR: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` +} diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr new file mode 100644 index 000000000..59b85abf5 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + --> $DIR/issue-74684-2.rs:21:9 + | +LL | bug(Box::new(x)); + | --- ^^^^^^^^^^^ type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` + | | + | required by a bound introduced by this call + | +note: expected this to be `[u8]` + --> $DIR/issue-74684-2.rs:8:18 + | +LL | type F<'a> = i32; + | ^^^ +note: required by a bound in `bug` + --> $DIR/issue-74684-2.rs:11:28 + | +LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { + | ^^^^^^^^^^^^ required by this bound in `bug` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-74816.rs b/tests/ui/generic-associated-types/issue-74816.rs new file mode 100644 index 000000000..344afb87f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74816.rs @@ -0,0 +1,21 @@ +#![feature(associated_type_defaults)] + +trait Trait1 { + fn foo(); +} + +trait Trait2 { + type Associated: Trait1 = Self; + //~^ ERROR: the trait bound `Self: Trait1` is not satisfied + //~| the size for values of type `Self` cannot be known +} + +impl Trait2 for () {} + +fn call_foo() { + T::Associated::foo() +} + +fn main() { + call_foo::<()>() +} diff --git a/tests/ui/generic-associated-types/issue-74816.stderr b/tests/ui/generic-associated-types/issue-74816.stderr new file mode 100644 index 000000000..45018e697 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74816.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `Self: Trait1` is not satisfied + --> $DIR/issue-74816.rs:8:31 + | +LL | type Associated: Trait1 = Self; + | ^^^^ the trait `Trait1` is not implemented for `Self` + | +note: required by a bound in `Trait2::Associated` + --> $DIR/issue-74816.rs:8:22 + | +LL | type Associated: Trait1 = Self; + | ^^^^^^ required by this bound in `Trait2::Associated` +help: consider further restricting `Self` + | +LL | trait Trait2: Trait1 { + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-74816.rs:8:31 + | +LL | type Associated: Trait1 = Self; + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Trait2::Associated` + --> $DIR/issue-74816.rs:8:5 + | +LL | type Associated: Trait1 = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait2::Associated` +help: consider further restricting `Self` + | +LL | trait Trait2: Sized { + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-74824.rs b/tests/ui/generic-associated-types/issue-74824.rs new file mode 100644 index 000000000..10c45d133 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74824.rs @@ -0,0 +1,25 @@ +#![feature(associated_type_defaults)] + +use std::ops::Deref; + +trait UnsafeCopy { + type Copy: Copy = Box; + //~^ ERROR the trait bound `Box: Copy` is not satisfied + //~^^ ERROR the trait bound `T: Clone` is not satisfied + fn copy(x: &Self::Copy) -> Self::Copy { + *x + } +} + +impl UnsafeCopy for T {} + +fn main() { + let b = Box::new(42usize); + let copy = <()>::copy(&b); + + let raw_b = Box::deref(&b) as *const _; + let raw_copy = Box::deref(©) as *const _; + + // assert the addresses. + assert_eq!(raw_b, raw_copy); +} diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr new file mode 100644 index 000000000..e5638d90e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74824.stderr @@ -0,0 +1,33 @@ +error[E0277]: the trait bound `Box: Copy` is not satisfied + --> $DIR/issue-74824.rs:6:26 + | +LL | type Copy: Copy = Box; + | ^^^^^^ the trait `Copy` is not implemented for `Box` + | +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:6:19 + | +LL | type Copy: Copy = Box; + | ^^^^ required by this bound in `UnsafeCopy::Copy` + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/issue-74824.rs:6:26 + | +LL | type Copy: Copy = Box; + | ^^^^^^ the trait `Clone` is not implemented for `T` + | + = note: required for `Box` to implement `Clone` + = note: required for `::Copy` to implement `Copy` +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:6:19 + | +LL | type Copy: Copy = Box; + | ^^^^ required by this bound in `UnsafeCopy::Copy` +help: consider restricting type parameter `T` + | +LL | type Copy: Copy = Box; + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-76407.rs b/tests/ui/generic-associated-types/issue-76407.rs new file mode 100644 index 000000000..9556ec6da --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76407.rs @@ -0,0 +1,25 @@ +// check-pass + +trait Marker {} + +impl Marker for u32 {} + +trait MyTrait { + type Item<'a>; +} + +struct MyStruct; + +impl MyTrait for MyStruct { + type Item<'a> = u32; +} + +fn ty_check() +where + T: MyTrait, + for<'a> T::Item<'a>: Marker +{} + +fn main() { + ty_check::(); +} diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr new file mode 100644 index 000000000..52c6e3eec --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.base.stderr @@ -0,0 +1,52 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:39:33 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:9:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); + | ++++ + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:39:14 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-76535.rs:9:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:39:57 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-76535.rs:9:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + = note: required for `Box` to implement `CoerceUnsized>>>` + = note: required by cast to type `Box>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-76535.extended.stderr b/tests/ui/generic-associated-types/issue-76535.extended.stderr new file mode 100644 index 000000000..369b86d29 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.extended.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:39:33 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:9:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs new file mode 100644 index 000000000..2457a05a0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.rs @@ -0,0 +1,43 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +pub trait SubTrait {} + +pub trait SuperTrait { + type SubType<'a>: SubTrait where Self: 'a; + + fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>; +} + +pub struct SubStruct<'a> { + sup: &'a mut SuperStruct, +} + +impl<'a> SubTrait for SubStruct<'a> {} + +pub struct SuperStruct { + value: u8, +} + +impl SuperStruct { + pub fn new(value: u8) -> SuperStruct { + SuperStruct { value } + } +} + +impl SuperTrait for SuperStruct { + type SubType<'a> = SubStruct<'a>; + + fn get_sub<'a>(&'a mut self) -> Self::SubType<'a> { + SubStruct { sup: self } + } +} + +fn main() { + let sub: Box> = Box::new(SuperStruct::new(0)); + //~^ ERROR missing generics for associated type + //[base]~^^ ERROR the trait + //[base]~| ERROR the trait +} diff --git a/tests/ui/generic-associated-types/issue-76826.rs b/tests/ui/generic-associated-types/issue-76826.rs new file mode 100644 index 000000000..ead78453e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76826.rs @@ -0,0 +1,42 @@ +// run-pass + +pub trait Iter { + type Item<'a> where Self: 'a; + + fn next<'a>(&'a mut self) -> Option>; + + fn for_each(mut self, mut f: F) + where Self: Sized, F: for<'a> FnMut(Self::Item<'a>) + { + while let Some(item) = self.next() { + f(item); + } + } +} + +pub struct Windows { + items: Vec, + start: usize, + len: usize, +} + +impl Windows { + pub fn new(items: Vec, len: usize) -> Self { + Self { items, start: 0, len } + } +} + +impl Iter for Windows { + type Item<'a> = &'a mut [T] where T: 'a; + + fn next<'a>(&'a mut self) -> Option> { + let slice = self.items.get_mut(self.start..self.start + self.len)?; + self.start += 1; + Some(slice) + } +} + +fn main() { + Windows::new(vec![1, 2, 3, 4, 5], 3) + .for_each(|slice| println!("{:?}", slice)); +} diff --git a/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs new file mode 100644 index 000000000..fd3b967d9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs @@ -0,0 +1,38 @@ +// Test for diagnostics when we have mismatched lifetime due to implicit 'static lifetime in GATs + +// check-fail + +pub trait A {} +impl A for &dyn A {} +impl A for Box {} + +pub trait B { + type T<'a>: A; +} + +impl B for () { + // `'a` doesn't match implicit `'static`: suggest `'_` + type T<'a> = Box; //~ incompatible lifetime on type +} + +trait C {} +impl C for Box {} +pub trait D { + type T<'a>: C; +} +impl D for () { + // `'a` doesn't match explicit `'static`: we *should* suggest removing `'static` + type T<'a> = Box; //~ incompatible lifetime on type +} + +trait E {} +impl E for (Box, Box) {} +pub trait F { + type T<'a>: E; +} +impl F for () { + // `'a` doesn't match explicit `'static`: suggest `'_` + type T<'a> = (Box, Box); //~ incompatible lifetime on type +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr new file mode 100644 index 000000000..86e0f5745 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.stderr @@ -0,0 +1,87 @@ +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:15:18 + | +LL | type T<'a> = Box; + | ^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:10:17 + | +LL | type T<'a>: A; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined here... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:15:12 + | +LL | type T<'a> = Box; + | ^^ + = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:7:20 + | +LL | impl A for Box {} + | ^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl A for Box {} + | ++++ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:25:18 + | +LL | type T<'a> = Box; + | ^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:21:17 + | +LL | type T<'a>: C; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined here... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:25:12 + | +LL | type T<'a> = Box; + | ^^ +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:19:1 + | +LL | impl C for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incompatible lifetime on type + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:35:18 + | +LL | type T<'a> = (Box, Box); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:31:17 + | +LL | type T<'a>: E; + | ^ introduces a `'static` lifetime requirement +note: the lifetime `'a` as defined here... + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:35:12 + | +LL | type T<'a> = (Box, Box); + | ^^ + = note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:29:21 + | +LL | impl E for (Box, Box) {} + | ^ +note: this has an implicit `'static` lifetime requirement + --> $DIR/issue-78113-lifetime-mismatch-dyn-trait-box.rs:29:33 + | +LL | impl E for (Box, Box) {} + | ^ +help: consider relaxing the implicit `'static` requirement + | +LL | impl E for (Box, Box) {} + | ++++ +help: consider relaxing the implicit `'static` requirement + | +LL | impl E for (Box, Box) {} + | ++++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/issue-78671.base.stderr b/tests/ui/generic-associated-types/issue-78671.base.stderr new file mode 100644 index 000000000..bad8c1c9d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.base.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:10:47 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:7:10 + | +LL | type Member; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily=usize> + | +++ + +error[E0038]: the trait `CollectionFamily` cannot be made into an object + --> $DIR/issue-78671.rs:10:25 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-78671.rs:7:10 + | +LL | trait CollectionFamily { + | ---------------- this trait cannot be made into an object... +LL | type Member; + | ^^^^^^ ...because it contains the generic associated type `Member` + = help: consider moving `Member` to another trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-78671.extended.stderr b/tests/ui/generic-associated-types/issue-78671.extended.stderr new file mode 100644 index 000000000..1d8a3d410 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.extended.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:10:47 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:7:10 + | +LL | type Member; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily=usize> + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-78671.rs b/tests/ui/generic-associated-types/issue-78671.rs new file mode 100644 index 000000000..327b0c14a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.rs @@ -0,0 +1,17 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait CollectionFamily { + type Member; +} +fn floatify() { + Box::new(Family) as &dyn CollectionFamily + //~^ ERROR: missing generics for associated type + //[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object +} + +struct Family; + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr new file mode 100644 index 000000000..f1de77bc3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.base.stderr @@ -0,0 +1,52 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:47:36 + | +LL | as Box>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:23:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box = dyn RefCont<'_, u8>>>; + | ++++ + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:47:12 + | +LL | as Box>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-79422.rs:23:10 + | +LL | trait MapLike { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:44:13 + | +LL | let m = Box::new(std::collections::BTreeMap::::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-79422.rs:23:10 + | +LL | trait MapLike { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + = note: required for `Box>` to implement `CoerceUnsized + 'static)>>>` + = note: required by cast to type `Box + 'static)>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr new file mode 100644 index 000000000..d79de0ca6 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:47:36 + | +LL | as Box>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:23:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box = dyn RefCont<'_, u8>>>; + | ++++ + +error[E0271]: type mismatch resolving ` as MapLike>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` + --> $DIR/issue-79422.rs:44:13 + | +LL | let m = Box::new(std::collections::BTreeMap::::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as MapLike>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` + | +note: expected this to be `(dyn RefCont<'_, u8> + 'static)` + --> $DIR/issue-79422.rs:28:25 + | +LL | type VRefCont<'a> = &'a V where Self: 'a; + | ^^^^^ + = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` + found reference `&u8` + = note: required for the cast from `BTreeMap` to the object type `dyn MapLike + 'static)>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0271. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs new file mode 100644 index 000000000..a52dd792d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.rs @@ -0,0 +1,50 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait RefCont<'a, T> { + fn t(&'a self) -> &'a T; +} + +impl<'a, T> RefCont<'a, T> for &'a T { + fn t(&'a self) -> &'a T { + self + } +} + +impl<'a, T> RefCont<'a, T> for Box { + fn t(&'a self) -> &'a T { + self.as_ref() + } +} + +trait MapLike { + type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + fn get<'a>(&'a self, key: &K) -> Option>; +} + +impl MapLike for std::collections::BTreeMap { + type VRefCont<'a> = &'a V where Self: 'a; + fn get<'a>(&'a self, key: &K) -> Option<&'a V> { + std::collections::BTreeMap::get(self, key) + } +} + +struct Source; + +impl MapLike for Source { + type VRefCont<'a> = Box; + fn get<'a>(&self, _: &K) -> Option> { + Some(Box::new(V::default())) + } +} + +fn main() { + let m = Box::new(std::collections::BTreeMap::::new()) + //[base]~^ ERROR the trait + //[extended]~^^ type mismatch + as Box>>; + //~^ ERROR missing generics for associated type + //[base]~^^ ERROR the trait +} diff --git a/tests/ui/generic-associated-types/issue-79636-1.rs b/tests/ui/generic-associated-types/issue-79636-1.rs new file mode 100644 index 000000000..a89039b5c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-1.rs @@ -0,0 +1,21 @@ +trait Monad { + type Unwrapped; + type Wrapped; + + fn bind(self, f: F) -> Self::Wrapped { + todo!() + } +} + +fn join(outer: MOuter) -> MOuter::Wrapped +where + MOuter: Monad, + MInner: Monad>, + //~^ ERROR: missing generics for associated type `Monad::Wrapped` +{ + outer.bind(|inner| inner) +} + +fn main() { + assert_eq!(join(Some(Some(true))), Some(true)); +} diff --git a/tests/ui/generic-associated-types/issue-79636-1.stderr b/tests/ui/generic-associated-types/issue-79636-1.stderr new file mode 100644 index 000000000..6e0d2ff4d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-1.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `Monad::Wrapped` + --> $DIR/issue-79636-1.rs:13:34 + | +LL | MInner: Monad>, + | ^^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `B` + --> $DIR/issue-79636-1.rs:3:10 + | +LL | type Wrapped; + | ^^^^^^^ - +help: add missing generic argument + | +LL | MInner: Monad = MOuter::Wrapped>, + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79636-2.rs b/tests/ui/generic-associated-types/issue-79636-2.rs new file mode 100644 index 000000000..ff5ff38c9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-2.rs @@ -0,0 +1,15 @@ +trait SomeTrait { + type Wrapped: SomeTrait; + + fn f() -> (); +} + +fn program() -> () +where + W: SomeTrait, + //~^ ERROR: missing generics for associated type `SomeTrait::Wrapped` +{ + return W::f(); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-79636-2.stderr b/tests/ui/generic-associated-types/issue-79636-2.stderr new file mode 100644 index 000000000..162873239 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79636-2.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `SomeTrait::Wrapped` + --> $DIR/issue-79636-2.rs:9:18 + | +LL | W: SomeTrait, + | ^^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `A` + --> $DIR/issue-79636-2.rs:2:10 + | +LL | type Wrapped: SomeTrait; + | ^^^^^^^ - +help: add missing generic argument + | +LL | W: SomeTrait = W>, + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-80433-reduced.rs b/tests/ui/generic-associated-types/issue-80433-reduced.rs new file mode 100644 index 000000000..44831a995 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-80433-reduced.rs @@ -0,0 +1,21 @@ +// check-pass + +struct E {} + +trait TestMut { + type Output<'a>; + fn test_mut(&mut self) -> Self::Output<'static>; +} + +impl TestMut for E { + type Output<'a> = usize; + fn test_mut(&mut self) -> Self::Output<'static> { + todo!() + } +} + +fn test_simpler<'a>(_: impl TestMut = usize>) {} + +fn main() { + test_simpler(E {}); +} diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs new file mode 100644 index 000000000..05ff82fa7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-80433.rs @@ -0,0 +1,32 @@ +#[derive(Default)] +struct E { + data: T, +} + +trait TestMut { + type Output<'a>; + fn test_mut<'a>(&'a mut self) -> Self::Output<'a>; +} + +impl TestMut for E +where + T: 'static, +{ + type Output<'a> = &'a mut T; + fn test_mut<'a>(&'a mut self) -> Self::Output<'a> { + &mut self.data + } +} + +fn test_simpler<'a>(dst: &'a mut impl TestMut) + //~^ ERROR missing generics for associated type +{ + for n in 0i16..100 { + *dst.test_mut() = n.into(); + } +} + +fn main() { + let mut t1: E = Default::default(); + test_simpler(&mut t1); +} diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr new file mode 100644 index 000000000..4f4f96a4b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `TestMut::Output` + --> $DIR/issue-80433.rs:21:47 + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut) + | ^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-80433.rs:7:10 + | +LL | type Output<'a>; + | ^^^^^^ -- +help: add missing lifetime argument + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut = &'a mut f32>) + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-81487.rs b/tests/ui/generic-associated-types/issue-81487.rs new file mode 100644 index 000000000..0d19a75bb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81487.rs @@ -0,0 +1,17 @@ +// build-pass + +trait Trait { + type Ref<'a>; +} + +impl Trait for () { + type Ref<'a> = &'a i8; +} + +struct RefRef<'a, T: Trait>(&'a ::Ref<'a>); + +fn wrap<'a, T: Trait>(reff: &'a ::Ref<'a>) -> RefRef<'a, T> { + RefRef(reff) +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs new file mode 100644 index 000000000..a7cc9a605 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.rs @@ -0,0 +1,18 @@ +// Regression test for #81712. + +trait A { + type BType: B; +} + +trait B { + type AType: A; +} +trait C { + type DType: D; +} +trait D { + type CType: C; + //~^ ERROR missing generics for associated type +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr new file mode 100644 index 000000000..e0fc225f4 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81712-cyclic-traits.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `C::DType` + --> $DIR/issue-81712-cyclic-traits.rs:14:19 + | +LL | type CType: C; + | ^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-81712-cyclic-traits.rs:11:10 + | +LL | type DType: D; + | ^^^^^ - +help: add missing generic argument + | +LL | type CType: C = Self>; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-81862.rs b/tests/ui/generic-associated-types/issue-81862.rs new file mode 100644 index 000000000..bde828b77 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81862.rs @@ -0,0 +1,10 @@ +trait StreamingIterator { + type Item<'a>; + fn next(&mut self) -> Option; + //~^ ERROR missing generics for associated type +} + +fn main() {} + +// call stack from back to front: +// create_substs_for_assoc_ty -> qpath_to_ty -> res_to_ty -> ast_ty_to_ty -> ty_of_fn diff --git a/tests/ui/generic-associated-types/issue-81862.stderr b/tests/ui/generic-associated-types/issue-81862.stderr new file mode 100644 index 000000000..df30be65e --- /dev/null +++ b/tests/ui/generic-associated-types/issue-81862.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `StreamingIterator::Item` + --> $DIR/issue-81862.rs:3:40 + | +LL | fn next(&mut self) -> Option; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-81862.rs:2:10 + | +LL | type Item<'a>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn next(&mut self) -> Option>; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-84931.rs b/tests/ui/generic-associated-types/issue-84931.rs new file mode 100644 index 000000000..4123ce9d4 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-84931.rs @@ -0,0 +1,21 @@ +// check-fail + +trait StreamingIter { + type Item<'a> where Self: 'a; + fn next<'a>(&'a mut self) -> Option>; +} + +struct StreamingSliceIter<'a, T> { + idx: usize, + data: &'a mut [T], +} + +impl<'b, T: 'b> StreamingIter for StreamingSliceIter<'b, T> { + type Item<'a> = &'a mut T; + //~^ the parameter type + fn next(&mut self) -> Option<&mut T> { + loop {} + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-84931.stderr b/tests/ui/generic-associated-types/issue-84931.stderr new file mode 100644 index 000000000..fffea98a4 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-84931.stderr @@ -0,0 +1,11 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-84931.rs:14:21 + | +LL | type Item<'a> = &'a mut T; + | ^^^^^^^^^- help: consider adding a where clause: `where T: 'a` + | | + | ...so that the reference type `&'a mut T` does not outlive the data it points at + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/generic-associated-types/issue-85921.rs b/tests/ui/generic-associated-types/issue-85921.rs new file mode 100644 index 000000000..d281ed9ee --- /dev/null +++ b/tests/ui/generic-associated-types/issue-85921.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Trait { + type Assoc<'a>; + + fn with_assoc(f: impl FnOnce(Self::Assoc<'_>)); +} + +impl Trait for () { + type Assoc<'a> = i32; + + fn with_assoc(f: impl FnOnce(Self::Assoc<'_>)) { + f(5i32) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86218-2.rs b/tests/ui/generic-associated-types/issue-86218-2.rs new file mode 100644 index 000000000..63c839ea8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86218-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay { + type InnerStream<'s>: Stream + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl Yay for () { + type InnerStream<'s> = impl Stream + 's; + fn foo<'s>() -> Self::InnerStream<'s> { () } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86218.rs b/tests/ui/generic-associated-types/issue-86218.rs new file mode 100644 index 000000000..b2c3071f0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86218.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait Stream { + type Item; +} + +impl Stream for () { + type Item = i32; +} + +trait Yay { + type InnerStream<'s>: Stream + 's; + fn foo<'s>() -> Self::InnerStream<'s>; +} + +impl<'a> Yay<&'a ()> for () { + type InnerStream<'s> = impl Stream + 's; + //^ ERROR does not fulfill the required lifetime + fn foo<'s>() -> Self::InnerStream<'s> { () } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86483.rs b/tests/ui/generic-associated-types/issue-86483.rs new file mode 100644 index 000000000..70267637a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86483.rs @@ -0,0 +1,14 @@ +// Regression test of #86483. +// +// Made to pass as part of fixing #98095. +// +// check-pass + +pub trait IceIce +where + for<'a> T: 'a, +{ + type Ice<'v>: IntoIterator; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86787.rs b/tests/ui/generic-associated-types/issue-86787.rs new file mode 100644 index 000000000..96075ca50 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86787.rs @@ -0,0 +1,37 @@ +// check-fail + +enum Either { + Left(L), + Right(R), +} + +pub trait HasChildrenOf { + type T; + type TRef<'a>; + //~^ missing required + + fn ref_children<'a>(&'a self) -> Vec>; + fn take_children(self) -> Vec; +} + +impl HasChildrenOf for Either +where + Left: HasChildrenOf, + Right: HasChildrenOf, +{ + type T = Either; + type TRef<'a> = Either<&'a Left::T, &'a Right::T> + where + ::T: 'a, + ::T: 'a; + + fn ref_children<'a>(&'a self) -> Vec> { + todo!() + } + + fn take_children(self) -> Vec { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86787.stderr b/tests/ui/generic-associated-types/issue-86787.stderr new file mode 100644 index 000000000..f34c63cf7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-86787.stderr @@ -0,0 +1,13 @@ +error: missing required bound on `TRef` + --> $DIR/issue-86787.rs:10:5 + | +LL | type TRef<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-87258_a.rs b/tests/ui/generic-associated-types/issue-87258_a.rs new file mode 100644 index 000000000..9ab683d3d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_a.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = impl Trait1; + //~^ ERROR unconstrained opaque type + fn foo<'a>() -> Self::FooFuture<'a> { + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87258_a.stderr b/tests/ui/generic-associated-types/issue-87258_a.stderr new file mode 100644 index 000000000..eae9bd9b1 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_a.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-87258_a.rs:17:26 + | +LL | type FooFuture<'a> = impl Trait1; + | ^^^^^^^^^^^ + | + = note: `FooFuture` must be used in combination with a concrete type within the same impl + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-87258_b.rs b/tests/ui/generic-associated-types/issue-87258_b.rs new file mode 100644 index 000000000..7b7610b21 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_b.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; +//~^ ERROR unconstrained opaque type + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = Helper<'c, 'a, S>; + fn foo<'a>() -> Self::FooFuture<'a> { + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87258_b.stderr b/tests/ui/generic-associated-types/issue-87258_b.stderr new file mode 100644 index 000000000..0ee665f38 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87258_b.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-87258_b.rs:16:49 + | +LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; + | ^^^^^^^^^^^ + | + = note: `Helper` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-87429-2.rs b/tests/ui/generic-associated-types/issue-87429-2.rs new file mode 100644 index 000000000..feb43ee5a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-2.rs @@ -0,0 +1,18 @@ +// Derived from `issue-87429`. A test that ensures that using bound vars in the +// predicates in the param env when checking that an associated type satisfies +// its bounds does not cause us to not be able to use the bounds on the parameters. + +// check-pass + +trait Family { + type Member<'a, C: Eq>: for<'b> MyBound<'b, C>; +} + +trait MyBound<'a, C> { } +impl<'a, C: Eq> MyBound<'a, C> for i32 { } + +impl Family for () { + type Member<'a, C: Eq> = i32; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87429-associated-type-default.rs b/tests/ui/generic-associated-types/issue-87429-associated-type-default.rs new file mode 100644 index 000000000..2006f9bc7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-associated-type-default.rs @@ -0,0 +1,17 @@ +// check-fail + +#![feature(associated_type_defaults)] + +trait Family { + // Fine, i32: PartialEq + type Member<'a>: for<'b> PartialEq> = i32; +} + +struct Foo; +trait Family2 { + // Not fine, not Foo: PartialEq + type Member<'a>: for<'b> PartialEq> = Foo; + //~^ ERROR can't compare +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr new file mode 100644 index 000000000..b1abe012b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr @@ -0,0 +1,20 @@ +error[E0277]: can't compare `Foo` with `Foo` + --> $DIR/issue-87429-associated-type-default.rs:13:60 + | +LL | type Member<'a>: for<'b> PartialEq> = Foo; + | ^^^ no implementation for `Foo == Foo` + | + = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `Family2::Member` + --> $DIR/issue-87429-associated-type-default.rs:13:22 + | +LL | type Member<'a>: for<'b> PartialEq> = Foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member` +help: consider annotating `Foo` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.rs b/tests/ui/generic-associated-types/issue-87429-specialization.rs new file mode 100644 index 000000000..6e31f1b21 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-specialization.rs @@ -0,0 +1,24 @@ +// check-fail + +#![feature(specialization)] +//~^ WARN incomplete + +trait Family { + type Member<'a>: for<'b> PartialEq>; +} + +struct I32Family; + +impl Family for I32Family { + default type Member<'a> = i32; +} + +struct Foo; +struct FooFamily; + +impl Family for FooFamily { + default type Member<'a> = Foo; + //~^ ERROR can't compare +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.stderr b/tests/ui/generic-associated-types/issue-87429-specialization.stderr new file mode 100644 index 000000000..11c4ebf60 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429-specialization.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-87429-specialization.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `Foo` with `Foo` + --> $DIR/issue-87429-specialization.rs:20:31 + | +LL | default type Member<'a> = Foo; + | ^^^ no implementation for `Foo == Foo` + | + = help: the trait `PartialEq` is not implemented for `Foo` +note: required by a bound in `Family::Member` + --> $DIR/issue-87429-specialization.rs:7:22 + | +LL | type Member<'a>: for<'b> PartialEq>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member` +help: consider annotating `Foo` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-87429.rs b/tests/ui/generic-associated-types/issue-87429.rs new file mode 100644 index 000000000..56394823c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87429.rs @@ -0,0 +1,13 @@ +// check-pass + +trait Family { + type Member<'a>: for<'b> PartialEq>; +} + +struct I32; + +impl Family for I32 { + type Member<'a> = i32; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87748.rs b/tests/ui/generic-associated-types/issue-87748.rs new file mode 100644 index 000000000..6cbe3d902 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87748.rs @@ -0,0 +1,21 @@ +// Checks that we properly add implied bounds from unnormalized projections in +// inputs when typechecking functions. + +// check-pass + +trait MyTrait { + type Assoc<'a, 'b> where 'b: 'a; + fn do_sth(arg: Self::Assoc<'_, '_>); + fn do_sth2(arg: Self::Assoc<'_, '_>) {} +} + +struct Foo; + +impl MyTrait for Foo { + type Assoc<'a, 'b> = u32 where 'b: 'a; + + fn do_sth(_: u32) {} + fn do_sth2(_: Self::Assoc<'static, 'static>) {} +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-87750.rs b/tests/ui/generic-associated-types/issue-87750.rs new file mode 100644 index 000000000..b35657989 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-87750.rs @@ -0,0 +1,24 @@ +// check-pass + +trait PointerFamily { + type Pointer; +} + +struct Rc(Box); +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer = Rc; +} + +#[allow(dead_code)] +enum Node +where + P::Pointer>: Sized, +{ + Cons(P::Pointer>), +} + +fn main() { + let _list: ::Pointer>; +} diff --git a/tests/ui/generic-associated-types/issue-88287.rs b/tests/ui/generic-associated-types/issue-88287.rs new file mode 100644 index 000000000..82188493d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88287.rs @@ -0,0 +1,39 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +trait SearchableResource { + type SearchResult; +} + +trait SearchableResourceExt: SearchableResource { + type Future<'f, A: 'f + ?Sized, B: 'f>: Future, ()>> + 'f + where + A: SearchableResource, + Self: 'f; + + fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>; +} + +type SearchFutureTy<'f, A, B: 'f> +where + A: SearchableResource + ?Sized + 'f, += impl Future, ()>> + 'f; +impl SearchableResourceExt for T +where + T: SearchableResource, +{ + type Future<'f, A, B: 'f> = SearchFutureTy<'f, A, B> + where + A: SearchableResource + ?Sized + 'f, + Self: 'f; + + fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> { + async move { todo!() } + //~^ ERROR: the size for values of type `A` cannot be known at compilation time + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr new file mode 100644 index 000000000..1b84cce62 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88287.stderr @@ -0,0 +1,27 @@ +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/issue-88287.rs:34:9 + | +LL | type SearchFutureTy<'f, A, B: 'f> + | - this type parameter needs to be `std::marker::Sized` +... +LL | async move { todo!() } + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `>` + --> $DIR/issue-88287.rs:24:6 + | +LL | impl SearchableResourceExt for T + | ^ required by this bound in `>` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - A: SearchableResource + ?Sized + 'f, +LL + A: SearchableResource + 'f, + | +help: consider relaxing the implicit `Sized` restriction + | +LL | T: SearchableResource + ?Sized, + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs new file mode 100644 index 000000000..c02690618 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88360.rs @@ -0,0 +1,18 @@ +trait GatTrait { + type Gat<'a> where Self: 'a; + + fn test(&self) -> Self::Gat<'_>; +} + +trait SuperTrait +where + Self: 'static, + for<'a> Self: GatTrait = &'a T>, +{ + fn copy(&self) -> Self::Gat<'_> where T: Copy { + *self.test() + //~^ mismatched types + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr new file mode 100644 index 000000000..cd3750344 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-88360.rs:13:9 + | +LL | trait SuperTrait + | - this type parameter +... +LL | fn copy(&self) -> Self::Gat<'_> where T: Copy { + | ------------- expected `&T` because of return type +LL | *self.test() + | ^^^^^^^^^^^^ + | | + | expected `&T`, found type parameter `T` + | help: consider borrowing here: `&*self.test()` + | + = note: expected reference `&T` + found type parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-88405.rs b/tests/ui/generic-associated-types/issue-88405.rs new file mode 100644 index 000000000..8dad6a89f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88405.rs @@ -0,0 +1,14 @@ +// check-pass + +trait SomeTrait {} +trait OtherTrait { + type Item; +} + +trait ErrorSimpleExample { + type AssociatedType: SomeTrait; + type GatBounded; + type ErrorMinimal: OtherTrait>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-88459.rs b/tests/ui/generic-associated-types/issue-88459.rs new file mode 100644 index 000000000..07d7bc06d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88459.rs @@ -0,0 +1,17 @@ +// check-pass + +trait Trait { + type Assoc<'a>; +} + +fn f(_: T, _: impl Fn(T::Assoc<'_>)) {} + +struct Type; + +impl Trait for Type { + type Assoc<'a> = (); +} + +fn main() { + f(Type, |_|()); +} diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs new file mode 100644 index 000000000..24641ee1f --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88595.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait A<'a> { + type B<'b>: Clone + // FIXME(generic_associated_types): Remove one of the below bounds + // https://github.com/rust-lang/rust/pull/90678#discussion_r744976085 + where + Self: 'a, Self: 'b; + + fn a(&'a self) -> Self::B<'a>; +} + +struct C; + +impl<'a> A<'a> for C { + type B<'b> = impl Clone; + + fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope +} diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr new file mode 100644 index 000000000..bcefc8066 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-88595.stderr @@ -0,0 +1,16 @@ +error: non-defining opaque type use in defining scope + --> $DIR/issue-88595.rs:20:35 + | +LL | fn a(&'a self) -> Self::B<'a> {} + | ^^ + | +note: lifetime used multiple times + --> $DIR/issue-88595.rs:17:6 + | +LL | impl<'a> A<'a> for C { + | ^^ +LL | type B<'b> = impl Clone; + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-89008.rs b/tests/ui/generic-associated-types/issue-89008.rs new file mode 100644 index 000000000..669dbafb5 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-89008.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2021 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; +use std::marker::PhantomData; + +trait Stream { + type Item; +} + +struct Empty { + _phantom: PhantomData, +} + +impl Stream for Empty { + type Item = T; +} + +trait X { + type LineStream<'a, Repr>: Stream where Self: 'a; + type LineStreamFut<'a, Repr>: Future> where Self: 'a; + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr>; +} + +struct Y; + +impl X for Y { + type LineStream<'a, Repr> = impl Stream; + type LineStreamFut<'a, Repr> = impl Future>; + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { + async { Empty { _phantom: PhantomData } } + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-89352.rs b/tests/ui/generic-associated-types/issue-89352.rs new file mode 100644 index 000000000..1896d0c87 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-89352.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait GenAssoc { + type Iter<'at>; + fn iter(&self) -> Self::Iter<'_>; + fn reborrow<'longt: 'shortt, 'shortt>(iter: Self::Iter<'longt>) -> Self::Iter<'shortt>; +} + +pub struct Wrapper<'a, T: 'a, A: GenAssoc> { + a: A::Iter<'a>, + _p: PhantomData, +} + +impl<'ai, T: 'ai, A: GenAssoc> GenAssoc for Wrapper<'ai, T, A> +where + A::Iter<'ai>: Clone, +{ + type Iter<'b> = (); + fn iter<'s>(&'s self) -> Self::Iter<'s> { + let a = A::reborrow::<'ai, 's>(self.a.clone()); + } + + fn reborrow<'long: 'short, 'short>(iter: Self::Iter<'long>) -> Self::Iter<'short> { + () + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-90014.rs b/tests/ui/generic-associated-types/issue-90014.rs new file mode 100644 index 000000000..55db95a6d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014.rs @@ -0,0 +1,21 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +trait MakeFut { + type Fut<'a> where Self: 'a; + fn make_fut<'a>(&'a self) -> Self::Fut<'a>; +} + +impl MakeFut for &'_ mut () { + type Fut<'a> = impl Future; + //~^ ERROR: the type `&mut ()` does not fulfill the required lifetime + + fn make_fut<'a>(&'a self) -> Self::Fut<'a> { + async { () } + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-90014.stderr b/tests/ui/generic-associated-types/issue-90014.stderr new file mode 100644 index 000000000..b4b1bc7da --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90014.stderr @@ -0,0 +1,22 @@ +error[E0477]: the type `&mut ()` does not fulfill the required lifetime + --> $DIR/issue-90014.rs:13:20 + | +LL | type Fut<'a> where Self: 'a; + | ------------ definition of `Fut` from trait +... +LL | type Fut<'a> = impl Future; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-90014.rs:13:14 + | +LL | type Fut<'a> = impl Future; + | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type Fut<'a> = impl Future where Self: 'a; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/issue-90729.rs b/tests/ui/generic-associated-types/issue-90729.rs new file mode 100644 index 000000000..bcec2e321 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-90729.rs @@ -0,0 +1,36 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait Type { + type Ref<'a>; +} + +pub trait AsBytes {} + +impl AsBytes for &str {} + +pub struct Utf8; + +impl Type for Utf8 { + type Ref<'a> = &'a str; +} + +pub struct Bytes { + _marker: PhantomData, +} + +impl Bytes +where + for<'a> T::Ref<'a>: AsBytes, +{ + pub fn new() -> Self { + Self { + _marker: PhantomData, + } + } +} + +fn main() { + let _b = Bytes::::new(); +} diff --git a/tests/ui/generic-associated-types/issue-91139.migrate.stderr b/tests/ui/generic-associated-types/issue-91139.migrate.stderr new file mode 100644 index 000000000..690160577 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91139.migrate.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `<<` + --> $DIR/issue-91139.rs:1:1 + | +LL | <<<<<<< HEAD + | ^^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-91139.rs b/tests/ui/generic-associated-types/issue-91139.rs new file mode 100644 index 000000000..adc0cb4e0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91139.rs @@ -0,0 +1,27 @@ +trait Foo { + type Type<'a> + where + T: 'a; +} + +impl Foo for () { + type Type<'a> = () + where + T: 'a; +} + +fn foo() { + let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); + //~^ ERROR `T` does not live long enough + //~| ERROR `T` does not live long enough + // + // FIXME: This error is bogus, but it arises because we try to validate + // that `<() as Foo>::Type<'a>` is valid, which requires proving + // that `T: 'a`. Since `'a` is higher-ranked, this becomes + // `for<'a> T: 'a`, which is not true. Of course, the error is bogus + // because there *ought* to be an implied bound stating that `'a` is + // not any lifetime but specifically + // "some `'a` such that `<() as Foo>::Type<'a>" is valid". +} + +pub fn main() {} diff --git a/tests/ui/generic-associated-types/issue-91139.stderr b/tests/ui/generic-associated-types/issue-91139.stderr new file mode 100644 index 000000000..d9d76adfb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91139.stderr @@ -0,0 +1,14 @@ +error: `T` does not live long enough + --> $DIR/issue-91139.rs:14:12 + | +LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `T` does not live long enough + --> $DIR/issue-91139.rs:14:12 + | +LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/issue-91883.rs b/tests/ui/generic-associated-types/issue-91883.rs new file mode 100644 index 000000000..e870e08a3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91883.rs @@ -0,0 +1,40 @@ +use std::fmt::Debug; +use std::marker::PhantomData; + +#[derive(Debug)] +pub struct TransactionImpl<'db> { + _marker: PhantomData<&'db ()>, +} + +#[derive(Debug)] +pub struct CursorImpl<'txn> { + _marker: PhantomData<&'txn ()>, +} + +pub trait Cursor<'txn> {} + +pub trait Transaction<'db>: Send + Sync + Debug + Sized { + type Cursor<'tx>: Cursor<'tx> + where + 'db: 'tx, + Self: 'tx; + + fn cursor<'tx>(&'tx self) -> Result, ()> + where + 'db: 'tx; +} + +impl<'tx> Cursor<'tx> for CursorImpl<'tx> {} + +impl<'db> Transaction<'db> for TransactionImpl<'db> { + type Cursor<'tx> = CursorImpl<'tx>; //~ ERROR lifetime bound not satisfied + + fn cursor<'tx>(&'tx self) -> Result, ()> + where + 'db: 'tx, + { + loop {} + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-91883.stderr b/tests/ui/generic-associated-types/issue-91883.stderr new file mode 100644 index 000000000..d5db96209 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-91883.stderr @@ -0,0 +1,27 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/issue-91883.rs:30:24 + | +LL | type Cursor<'tx>: Cursor<'tx> + | ----------------------------- definition of `Cursor` from trait +... +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'db` as defined here + --> $DIR/issue-91883.rs:29:6 + | +LL | impl<'db> Transaction<'db> for TransactionImpl<'db> { + | ^^^ +note: but lifetime parameter must outlive the lifetime `'tx` as defined here + --> $DIR/issue-91883.rs:30:17 + | +LL | type Cursor<'tx> = CursorImpl<'tx>; + | ^^^ +help: copy the `where` clause predicates from the trait + | +LL | type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx; + | +++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/generic-associated-types/issue-92033.rs b/tests/ui/generic-associated-types/issue-92033.rs new file mode 100644 index 000000000..d111580b8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92033.rs @@ -0,0 +1,37 @@ +struct Texture; + +trait Surface { + type TextureIter<'a>: Iterator + where + Self: 'a; + + fn get_texture(&self) -> Self::TextureIter<'_>; +} + +trait Swapchain { + type Surface<'a>: Surface + where + Self: 'a; + + fn get_surface(&self) -> Self::Surface<'_>; +} + +impl<'s> Surface for &'s Texture { + type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + //~^ ERROR the type + + fn get_texture(&self) -> Self::TextureIter<'_> { + let option: Option<&Texture> = Some(self); + option.into_iter() + } +} + +impl Swapchain for Texture { + type Surface<'a> = &'a Texture; + + fn get_surface(&self) -> Self::Surface<'_> { + self + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-92033.stderr b/tests/ui/generic-associated-types/issue-92033.stderr new file mode 100644 index 000000000..ddc420a7b --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92033.stderr @@ -0,0 +1,22 @@ +error[E0477]: the type `&'s Texture` does not fulfill the required lifetime + --> $DIR/issue-92033.rs:20:28 + | +LL | type TextureIter<'a>: Iterator + | -------------------------------------------------- definition of `TextureIter` from trait +... +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here + --> $DIR/issue-92033.rs:20:22 + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; + | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture> where Self: 'a; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/issue-92096.migrate.stderr b/tests/ui/generic-associated-types/issue-92096.migrate.stderr new file mode 100644 index 000000000..ce1fd6dd9 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92096.migrate.stderr @@ -0,0 +1,24 @@ +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:19:33 + | +LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send + | ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | C: Client + Send + Sync + 'a, + | ++++ + +error[E0311]: the parameter type `C` may not live long enough + --> $DIR/issue-92096.rs:19:33 + | +LL | fn call_connect(c: &'_ C) -> impl '_ + Future + Send + | ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | C: Client + Send + Sync + 'a, + | ++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/issue-92096.rs b/tests/ui/generic-associated-types/issue-92096.rs new file mode 100644 index 000000000..e285af666 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92096.rs @@ -0,0 +1,28 @@ +// edition:2018 + +use std::future::Future; + +trait Client { + type Connecting<'a>: Future + Send + where + Self: 'a; + + fn connect(&'_ self) -> Self::Connecting<'_>; +} + +fn call_connect(c: &'_ C) -> impl '_ + Future + Send +where + C: Client + Send + Sync, +{ + async move { c.connect().await } + //~^ ERROR `C` does not live long enough + // + // FIXME(#71723). This is because we infer at some point a value of + // + // impl Future::Connection<'_>> + // + // and then we somehow fail the WF check because `where C: 'a` is not known, + // but I'm not entirely sure how that comes about. +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-92096.stderr b/tests/ui/generic-associated-types/issue-92096.stderr new file mode 100644 index 000000000..91a06d5ac --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92096.stderr @@ -0,0 +1,8 @@ +error: `C` does not live long enough + --> $DIR/issue-92096.rs:17:5 + | +LL | async move { c.connect().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/issue-92280.rs b/tests/ui/generic-associated-types/issue-92280.rs new file mode 100644 index 000000000..9284beea3 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92280.rs @@ -0,0 +1,24 @@ +// check-pass + +#![allow(non_camel_case_types)] + +trait HasAssoc { + type Assoc; +} + +trait Iterate { + type Iter<'a> + where + Self: 'a; +} + +struct KeySegment_Broken { + key: T, +} +impl Iterate for KeySegment_Broken { + type Iter<'a> = () + where + Self: 'a; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-92954.rs b/tests/ui/generic-associated-types/issue-92954.rs new file mode 100644 index 000000000..22ce8f9fe --- /dev/null +++ b/tests/ui/generic-associated-types/issue-92954.rs @@ -0,0 +1,8 @@ +// check-pass + +pub trait Foo { + type Assoc<'c>; + fn function() -> for<'x> fn(Self::Assoc<'x>); +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93141.rs b/tests/ui/generic-associated-types/issue-93141.rs new file mode 100644 index 000000000..48c78b9c0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93141.rs @@ -0,0 +1,23 @@ +// check-pass + +pub trait Fooey: Sized { + type Context<'c> where Self: 'c; +} + +pub struct Handle(Option Fn(&mut E::Context<'c>)>>); + +fn tuple() -> (Option,) { (Option::None,) } + +pub struct FooImpl {} +impl Fooey for FooImpl { + type Context<'c> = &'c (); +} + +impl FooImpl { + pub fn fail1() -> Handle { + let (tx,) = tuple(); + Handle(tx) + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93262.rs b/tests/ui/generic-associated-types/issue-93262.rs new file mode 100644 index 000000000..a7bcd111d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93262.rs @@ -0,0 +1,19 @@ +// check-pass + +pub trait Trait { + type Assoc<'a> where Self: 'a; +} + +pub trait Foo +where + for<'a> T::Assoc<'a>: Clone +{} + +pub struct Type; + +impl Foo for Type +where + for<'a> T::Assoc<'a>: Clone +{} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93340.rs b/tests/ui/generic-associated-types/issue-93340.rs new file mode 100644 index 000000000..4662fda53 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93340.rs @@ -0,0 +1,18 @@ +// check-pass + +pub trait Scalar: 'static { + type RefType<'a>: ScalarRef<'a>; +} + +pub trait ScalarRef<'a>: 'a {} + +fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O { + todo!() +} + +fn build_expression( +) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { + cmp_eq +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93341.rs b/tests/ui/generic-associated-types/issue-93341.rs new file mode 100644 index 000000000..737b2bbdb --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93341.rs @@ -0,0 +1,54 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct Id<'id>(PhantomData &'id ()>); + +fn new_id() -> Id<'static> { + Id(PhantomData) +} + +pub trait HasLifetime where { + type AtLifetime<'a>; +} + +pub struct ExistentialLifetime(S::AtLifetime<'static>); + +impl ExistentialLifetime { + pub fn new(f: F) -> ExistentialLifetime + where for<'id> F: FnOnce(Id<'id>) -> S::AtLifetime<'id> { + ExistentialLifetime(f(new_id())) + } +} + + +struct ExampleS<'id>(Id<'id>); + +struct ExampleMarker; + +impl HasLifetime for ExampleMarker { + type AtLifetime<'id> = ExampleS<'id>; +} + + +fn broken0() -> ExistentialLifetime { + fn new_helper<'id>(id: Id<'id>) -> ExampleS<'id> { + ExampleS(id) + } + + ExistentialLifetime::::new(new_helper) +} + +fn broken1() -> ExistentialLifetime { + fn new_helper<'id>(id: Id<'id>) -> ::AtLifetime<'id> { + ExampleS(id) + } + + ExistentialLifetime::::new(new_helper) +} + +fn broken2() -> ExistentialLifetime { + ExistentialLifetime::::new(|id| ExampleS(id)) +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-93342.rs b/tests/ui/generic-associated-types/issue-93342.rs new file mode 100644 index 000000000..d4422d5d1 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93342.rs @@ -0,0 +1,55 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait Scalar: 'static { + type RefType<'a>: ScalarRef<'a>; +} + +pub trait ScalarRef<'a>: 'a {} + +impl Scalar for i32 { + type RefType<'a> = i32; +} + +impl Scalar for String { + type RefType<'a> = &'a str; +} + +impl Scalar for bool { + type RefType<'a> = i32; +} + +impl<'a> ScalarRef<'a> for bool {} + +impl<'a> ScalarRef<'a> for i32 {} + +impl<'a> ScalarRef<'a> for &'a str {} + +fn str_contains(a: &str, b: &str) -> bool { + a.contains(b) +} + +pub struct BinaryExpression +where + F: Fn(A::RefType<'_>, B::RefType<'_>) -> O, +{ + f: F, + _phantom: PhantomData<(A, B, O)>, +} + +impl BinaryExpression +where + F: Fn(A::RefType<'_>, B::RefType<'_>) -> O, +{ + pub fn new(f: F) -> Self { + Self { + f, + _phantom: PhantomData, + } + } +} + +fn main() { + BinaryExpression::::new(str_contains); +} diff --git a/tests/ui/generic-associated-types/issue-93874.rs b/tests/ui/generic-associated-types/issue-93874.rs new file mode 100644 index 000000000..30956655a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93874.rs @@ -0,0 +1,33 @@ +// check-pass + +pub trait Build { + type Output; + fn build(self, input: O) -> Self::Output; +} + +pub struct IdentityBuild; +impl Build for IdentityBuild { + type Output = O; + fn build(self, input: O) -> Self::Output { + input + } +} + +fn a() { + let _x: u8 = IdentityBuild.build(10); +} + +fn b() { + let _x: Vec = IdentityBuild.build(Vec::new()); +} + +fn c() { + let mut f = IdentityBuild.build(|| ()); + (f)(); +} + +pub fn main() { + a(); + b(); + c(); +} diff --git a/tests/ui/generic-associated-types/issue-95305.rs b/tests/ui/generic-associated-types/issue-95305.rs new file mode 100644 index 000000000..6c3ec20e7 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-95305.rs @@ -0,0 +1,19 @@ +// It's not yet clear how '_ and GATs should interact. +// Forbid it for now but proper support might be added +// at some point in the future. + +#![feature(anonymous_lifetime_in_impl_trait)] +trait Foo { + type Item<'a>; +} + +fn foo(x: &impl Foo = u32>) { } + //~^ ERROR `'_` cannot be used here [E0637] + +// Ok: the anonymous lifetime is bound to the function. +fn bar(x: &impl for<'a> Foo = &'_ u32>) { } + +// Ok: the anonymous lifetime is bound to the function. +fn baz(x: &impl for<'a> Foo = &u32>) { } + +fn main() {} diff --git a/tests/ui/generic-associated-types/issue-95305.stderr b/tests/ui/generic-associated-types/issue-95305.stderr new file mode 100644 index 000000000..eb15cbc62 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-95305.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/issue-95305.rs:10:26 + | +LL | fn foo(x: &impl Foo = u32>) { } + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/generic-associated-types/iterable.rs b/tests/ui/generic-associated-types/iterable.rs new file mode 100644 index 000000000..8ad351bd3 --- /dev/null +++ b/tests/ui/generic-associated-types/iterable.rs @@ -0,0 +1,44 @@ +// run-pass + +trait Iterable { + type Item<'a> where Self: 'a; + type Iter<'a>: Iterator> where Self: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a>; +} + +// Impl for struct type +impl Iterable for Vec { + type Item<'a> = as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a> { + self[..].iter() + } +} + +// Impl for a primitive type +impl Iterable for [T] { + type Item<'a> = as Iterator>::Item where T: 'a; + type Iter<'a> = std::slice::Iter<'a, T> where T: 'a; + + fn iter<'a>(&'a self) -> Self::Iter<'a> { + self.iter() + } +} + +fn make_iter<'a, I: Iterable + ?Sized>(it: &'a I) -> I::Iter<'a> { + it.iter() +} + +fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option> { + it.iter().next() +} + +fn main() { + let v = vec![1, 2, 3]; + assert_eq!(v, make_iter(&v).copied().collect::>()); + assert_eq!(v, make_iter(&*v).copied().collect::>()); + assert_eq!(Some(&1), get_first(&v)); + assert_eq!(Some(&1), get_first(&*v)); +} diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs new file mode 100644 index 000000000..83655341d --- /dev/null +++ b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -0,0 +1,33 @@ +// Test that the predicate printed in an unresolved method error prints the +// generics for a generic associated type. + +trait X { + type Y; +} + +trait M { + fn f(&self) {} +} + +impl = i32>> M for T {} +//~^ NOTE trait bound `::Y = i32` was not satisfied +//~| NOTE +//~| NOTE +//~| NOTE + +struct S; +//~^ NOTE method `f` not found for this +//~| NOTE doesn't satisfy `::Y = i32` +//~| NOTE doesn't satisfy `S: M` + +impl X for S { + type Y = bool; +} + +fn f(a: S) { + a.f(); + //~^ ERROR the method `f` exists for struct `S`, but its trait bounds were not satisfied + //~| NOTE method cannot be called on `S` due to unsatisfied trait bounds +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr new file mode 100644 index 000000000..baef38f6b --- /dev/null +++ b/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -0,0 +1,24 @@ +error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied + --> $DIR/method-unsatified-assoc-type-predicate.rs:28:7 + | +LL | struct S; + | -------- + | | + | method `f` not found for this struct + | doesn't satisfy `::Y = i32` + | doesn't satisfy `S: M` +... +LL | a.f(); + | ^ method cannot be called on `S` due to unsatisfied trait bounds + | +note: trait bound `::Y = i32` was not satisfied + --> $DIR/method-unsatified-assoc-type-predicate.rs:12:11 + | +LL | impl = i32>> M for T {} + | ^^^^^^^^^^^^ - - + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/generic-associated-types/mismatched-where-clause-regions.rs b/tests/ui/generic-associated-types/mismatched-where-clause-regions.rs new file mode 100644 index 000000000..8caf53176 --- /dev/null +++ b/tests/ui/generic-associated-types/mismatched-where-clause-regions.rs @@ -0,0 +1,12 @@ +trait Foo { + type T<'a1, 'b1> + where + 'a1: 'b1; +} + +impl Foo for () { + type T<'a2, 'b2> = () where 'b2: 'a2; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr b/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr new file mode 100644 index 000000000..91a030076 --- /dev/null +++ b/tests/ui/generic-associated-types/mismatched-where-clause-regions.stderr @@ -0,0 +1,17 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/mismatched-where-clause-regions.rs:8:38 + | +LL | type T<'a1, 'b1> + | ---------------- definition of `T` from trait +... +LL | type T<'a2, 'b2> = () where 'b2: 'a2; + | ^^^ impl has extra requirement `'b2: 'a2` + | +help: copy the `where` clause predicates from the trait + | +LL | type T<'a2, 'b2> = () where 'a2: 'b2; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed new file mode 100644 index 000000000..ee758f19e --- /dev/null +++ b/tests/ui/generic-associated-types/missing-bounds.fixed @@ -0,0 +1,46 @@ +// run-rustfix + +use std::ops::Add; + +struct A(B); + +impl Add for A where B: Add + Add { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + A(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct C(B); + +impl> Add for C { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct D(B); + +impl> Add for D { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B` + } +} + +struct E(B); + +impl> Add for E where B: Add { + //~^ ERROR equality constraints are not yet supported in `where` clauses + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs new file mode 100644 index 000000000..ffafff5e9 --- /dev/null +++ b/tests/ui/generic-associated-types/missing-bounds.rs @@ -0,0 +1,46 @@ +// run-rustfix + +use std::ops::Add; + +struct A(B); + +impl Add for A where B: Add { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + A(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct C(B); + +impl Add for C { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +struct D(B); + +impl Add for D { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B` + } +} + +struct E(B); + +impl Add for E where ::Output = B { + //~^ ERROR equality constraints are not yet supported in `where` clauses + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self(self.0 + rhs.0) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr new file mode 100644 index 000000000..9f669b9a5 --- /dev/null +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -0,0 +1,105 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/missing-bounds.rs:37:33 + | +LL | impl Add for E where ::Output = B { + | ^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Output` is an associated type you're trying to set, use the associated type binding syntax + | +LL | impl Add for E where B: Add { + | ~~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:11:11 + | +LL | impl Add for A where B: Add { + | - this type parameter +... +LL | A(self.0 + rhs.0) + | - ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | | + | arguments to this struct are incorrect + | + = note: expected type parameter `B` + found associated type `::Output` +help: the type constructed contains `::Output` due to the type of the argument passed + --> $DIR/missing-bounds.rs:11:9 + | +LL | A(self.0 + rhs.0) + | ^^--------------^ + | | + | this argument influences the type of `A` +note: tuple struct defined here + --> $DIR/missing-bounds.rs:5:8 + | +LL | struct A(B); + | ^ +help: consider further restricting this bound + | +LL | impl Add for A where B: Add + Add { + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:21:14 + | +LL | impl Add for C { + | - this type parameter +... +LL | Self(self.0 + rhs.0) + | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type parameter `B` + found associated type `::Output` +note: tuple struct defined here + --> $DIR/missing-bounds.rs:15:8 + | +LL | struct C(B); + | ^ +help: consider further restricting this bound + | +LL | impl> Add for C { + | +++++++++++++++++ + +error[E0369]: cannot add `B` to `B` + --> $DIR/missing-bounds.rs:31:21 + | +LL | Self(self.0 + rhs.0) + | ------ ^ ----- B + | | + | B + | +help: consider restricting type parameter `B` + | +LL | impl> Add for D { + | +++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:42:14 + | +LL | impl Add for E where ::Output = B { + | - this type parameter +... +LL | Self(self.0 + rhs.0) + | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type parameter `B` + found associated type `::Output` +note: tuple struct defined here + --> $DIR/missing-bounds.rs:35:8 + | +LL | struct E(B); + | ^ +help: consider further restricting this bound + | +LL | impl> Add for E where ::Output = B { + | +++++++++++++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs b/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs new file mode 100644 index 000000000..de9cad308 --- /dev/null +++ b/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -0,0 +1,11 @@ +// check-fail + +trait Foo { + type Assoc<'a, 'b>; +} +impl Foo for () { + type Assoc<'a, 'b> = () where 'a: 'b; + //~^ impl has stricter requirements than trait +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr new file mode 100644 index 000000000..8a71fc73a --- /dev/null +++ b/tests/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -0,0 +1,18 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/missing-where-clause-on-trait.rs:7:39 + | +LL | type Assoc<'a, 'b>; + | ------------------ definition of `Assoc` from trait +... +LL | type Assoc<'a, 'b> = () where 'a: 'b; + | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - type Assoc<'a, 'b> = () where 'a: 'b; +LL + type Assoc<'a, 'b> = () ; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.rs b/tests/ui/generic-associated-types/missing_lifetime_args.rs new file mode 100644 index 000000000..78def8092 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_args.rs @@ -0,0 +1,20 @@ +trait X { + type Y<'a, 'b>; +} + +struct Foo<'a, 'b, 'c> { + a: &'a u32, + b: &'b str, + c: &'c str, +} + +fn foo<'c, 'd>(_arg: Box>) {} +//~^ ERROR missing generics for associated type + +fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} +//~^ ERROR this struct takes 3 lifetime arguments but 2 lifetime + +fn f<'a>(_arg: Foo<'a>) {} +//~^ ERROR this struct takes 3 lifetime arguments but 1 lifetime + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr new file mode 100644 index 000000000..8f74b12c0 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr @@ -0,0 +1,55 @@ +error[E0107]: missing generics for associated type `X::Y` + --> $DIR/missing_lifetime_args.rs:11:32 + | +LL | fn foo<'c, 'd>(_arg: Box>) {} + | ^ expected 2 lifetime arguments + | +note: associated type defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/missing_lifetime_args.rs:2:10 + | +LL | type Y<'a, 'b>; + | ^ -- -- +help: add missing lifetime arguments + | +LL | fn foo<'c, 'd>(_arg: Box = (&'c u32, &'d u32)>>) {} + | ++++++++ + +error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/missing_lifetime_args.rs:14:26 + | +LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} + | ^^^ -- -- supplied 2 lifetime arguments + | | + | expected 3 lifetime arguments + | +note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` + --> $DIR/missing_lifetime_args.rs:5:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime argument + | +LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {} + | ++++ + +error[E0107]: this struct takes 3 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing_lifetime_args.rs:17:16 + | +LL | fn f<'a>(_arg: Foo<'a>) {} + | ^^^ -- supplied 1 lifetime argument + | | + | expected 3 lifetime arguments + | +note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c` + --> $DIR/missing_lifetime_args.rs:5:8 + | +LL | struct Foo<'a, 'b, 'c> { + | ^^^ -- -- -- +help: add missing lifetime arguments + | +LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {} + | ++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.rs b/tests/ui/generic-associated-types/missing_lifetime_const.rs new file mode 100644 index 000000000..8b174b9e9 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_const.rs @@ -0,0 +1,10 @@ +trait Foo { + type Assoc<'a, const N: usize>; +} + +fn foo() { + let _: ::Assoc<3>; + //~^ ERROR this associated type +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.stderr b/tests/ui/generic-associated-types/missing_lifetime_const.stderr new file mode 100644 index 000000000..62d2e9f49 --- /dev/null +++ b/tests/ui/generic-associated-types/missing_lifetime_const.stderr @@ -0,0 +1,19 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/missing_lifetime_const.rs:6:24 + | +LL | let _: ::Assoc<3>; + | ^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/missing_lifetime_const.rs:2:10 + | +LL | type Assoc<'a, const N: usize>; + | ^^^^^ -- +help: add missing lifetime argument + | +LL | let _: ::Assoc<'a, 3>; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/own-bound-span.rs b/tests/ui/generic-associated-types/own-bound-span.rs new file mode 100644 index 000000000..3699f7296 --- /dev/null +++ b/tests/ui/generic-associated-types/own-bound-span.rs @@ -0,0 +1,17 @@ +struct S; + +trait D { + type P; + //~^ NOTE required by this bound in `D::P` + //~| NOTE required by a bound in `D::P` +} + +impl D for S { + type P = (); +} + +fn main() { + let _: ::P; + //~^ ERROR the trait bound `String: Copy` is not satisfied + //~| NOTE the trait `Copy` is not implemented for `String` +} diff --git a/tests/ui/generic-associated-types/own-bound-span.stderr b/tests/ui/generic-associated-types/own-bound-span.stderr new file mode 100644 index 000000000..8ab8ea623 --- /dev/null +++ b/tests/ui/generic-associated-types/own-bound-span.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/own-bound-span.rs:14:12 + | +LL | let _: ::P; + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `D::P` + --> $DIR/own-bound-span.rs:4:15 + | +LL | type P; + | ^^^^ required by this bound in `D::P` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind.rs b/tests/ui/generic-associated-types/parameter_number_and_kind.rs new file mode 100644 index 000000000..8428e7763 --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind.rs @@ -0,0 +1,18 @@ +#![feature(associated_type_defaults)] + +trait Foo { + type A<'a>; + type B<'a, 'b>; + type C; + type D; + type E<'a, T>; + // Test parameters in default values + type FOk = Self::E<'static, T>; + type FErr1 = Self::E<'static, 'static>; + //~^ ERROR this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| ERROR this associated type takes 1 + type FErr2 = Self::E<'static, T, u32>; + //~^ ERROR this associated type takes 1 +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind.stderr new file mode 100644 index 000000000..c20b9669e --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind.stderr @@ -0,0 +1,47 @@ +error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/parameter_number_and_kind.rs:11:24 + | +LL | type FErr1 = Self::E<'static, 'static>; + | ^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/parameter_number_and_kind.rs:8:10 + | +LL | type E<'a, T>; + | ^ -- + +error[E0107]: this associated type takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/parameter_number_and_kind.rs:11:24 + | +LL | type FErr1 = Self::E<'static, 'static>; + | ^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/parameter_number_and_kind.rs:8:10 + | +LL | type E<'a, T>; + | ^ - +help: add missing generic argument + | +LL | type FErr1 = Self::E<'static, 'static, T>; + | +++ + +error[E0107]: this associated type takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/parameter_number_and_kind.rs:14:27 + | +LL | type FErr2 = Self::E<'static, T, u32>; + | ^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/parameter_number_and_kind.rs:8:10 + | +LL | type E<'a, T>; + | ^ - + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs new file mode 100644 index 000000000..c1381025a --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs @@ -0,0 +1,33 @@ +#![feature(associated_type_defaults)] + +// FIXME(#44265) add tests for type-generic and const-genertic associated types. + +trait Foo { + type A<'a>; + type B<'a, 'b>; + type C; +} + +struct Fooy; + +impl Foo for Fooy { + type A = u32; + //~^ ERROR lifetime parameters or bounds on type `A` do not match the trait declaration + type B<'a, T> = Vec; + //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters + type C<'a> = u32; + //~^ ERROR lifetime parameters or bounds on type `C` do not match the trait declaration +} + +struct Fooer; + +impl Foo for Fooer { + type A = u32; + //~^ ERROR type `A` has 1 type parameter but its trait declaration has 0 type parameters + type B<'a> = u32; + //~^ ERROR lifetime parameters or bounds on type `B` do not match the trait declaration + type C = T; + //~^ ERROR type `C` has 1 type parameter but its trait declaration has 0 type parameters +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr new file mode 100644 index 000000000..fdd6d305a --- /dev/null +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr @@ -0,0 +1,62 @@ +error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration + --> $DIR/parameter_number_and_kind_impl.rs:14:11 + | +LL | type A<'a>; + | ---- lifetimes in impl do not match this type in trait +... +LL | type A = u32; + | ^ lifetimes do not match type in trait + +error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/parameter_number_and_kind_impl.rs:16:12 + | +LL | type B<'a, 'b>; + | -- -- + | | + | expected 0 type parameters +... +LL | type B<'a, T> = Vec; + | ^^ ^ + | | + | found 1 type parameter + +error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration + --> $DIR/parameter_number_and_kind_impl.rs:18:11 + | +LL | type C; + | - lifetimes in impl do not match this type in trait +... +LL | type C<'a> = u32; + | ^^^^ lifetimes do not match type in trait + +error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/parameter_number_and_kind_impl.rs:25:12 + | +LL | type A<'a>; + | -- expected 0 type parameters +... +LL | type A = u32; + | ^ found 1 type parameter + +error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration + --> $DIR/parameter_number_and_kind_impl.rs:27:11 + | +LL | type B<'a, 'b>; + | -------- lifetimes in impl do not match this type in trait +... +LL | type B<'a> = u32; + | ^^^^ lifetimes do not match type in trait + +error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/parameter_number_and_kind_impl.rs:29:12 + | +LL | type C; + | - expected 0 type parameters +... +LL | type C = T; + | ^ found 1 type parameter + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0049, E0195. +For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/generic-associated-types/parse/in-trait-impl.rs b/tests/ui/generic-associated-types/parse/in-trait-impl.rs new file mode 100644 index 000000000..767098835 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/in-trait-impl.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: -Z parse-only + +impl Baz for T where T: Foo { + type Quux<'a> = ::Bar<'a, 'static>; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/in-trait.rs b/tests/ui/generic-associated-types/parse/in-trait.rs new file mode 100644 index 000000000..6628aac37 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/in-trait.rs @@ -0,0 +1,22 @@ +// check-pass +// compile-flags: -Z parse-only + +use std::ops::Deref; +use std::fmt::Debug; + +trait Foo { + type Bar<'a>; + type Bar<'a, 'b>; + type Bar<'a, 'b,>; + type Bar<'a, 'b, T>; + type Bar<'a, 'b, T, U>; + type Bar<'a, 'b, T, U,>; + type Bar<'a, 'b, T: Debug, U,>; + type Bar<'a, 'b, T: Debug, U,>: Debug; + type Bar<'a, 'b, T: Debug, U,>: Deref + Into; + type Bar<'a, 'b, T: Debug, U,> where T: Deref, U: Into; + type Bar<'a, 'b, T: Debug, U,>: Deref + Into + where T: Deref, U: Into; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs b/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs new file mode 100644 index 000000000..cbb051892 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.rs @@ -0,0 +1,8 @@ +trait X { + type Y<'a>; +} + +fn f1<'a>(arg : Box>) {} + //~^ ERROR: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr new file mode 100644 index 000000000..53d5f9de6 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expected-token.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` + --> $DIR/trait-path-expected-token.rs:5:33 + | +LL | fn f1<'a>(arg : Box>) {} + | - ^ expected one of 7 possible tokens + | | + | maybe try to close unmatched angle bracket + +error: aborting due to previous error + diff --git a/tests/ui/generic-associated-types/parse/trait-path-expressions.rs b/tests/ui/generic-associated-types/parse/trait-path-expressions.rs new file mode 100644 index 000000000..9183ec497 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expressions.rs @@ -0,0 +1,20 @@ +mod error1 { + trait X { + type Y<'a>; + } + + fn f1<'a>(arg : Box>) {} + //~^ ERROR: expected expression, found `)` +} + +mod error2 { + + trait X { + type Y<'a>; + } + + fn f2<'a>(arg : Box>) {} + //~^ ERROR: expected one of +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr new file mode 100644 index 000000000..cf2b1763f --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-expressions.stderr @@ -0,0 +1,23 @@ +error: expected expression, found `)` + --> $DIR/trait-path-expressions.rs:6:39 + | +LL | fn f1<'a>(arg : Box>) {} + | - ^ expected expression + | | + | while parsing a const generic argument starting here + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-expressions.rs:16:36 + | +LL | fn f2<'a>(arg : Box>) {} + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f2<'a>(arg : Box = 32 >>) {} + | + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs new file mode 100644 index 000000000..ecabf8943 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs @@ -0,0 +1,18 @@ +trait X { + type Y<'a>; +} + +const _: () = { + fn f1<'a>(arg : Box>) {} + //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `:` + //~| ERROR: expected parameter name, found `>` + //~| ERROR: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` + //~| ERROR: constant provided when a type was expected +}; + +const _: () = { + fn f1<'a>(arg : Box>) {} + //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `=` +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr new file mode 100644 index 000000000..10ceccedc --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr @@ -0,0 +1,43 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `:` + --> $DIR/trait-path-missing-gen_arg.rs:6:30 + | +LL | fn f1<'a>(arg : Box>) {} + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | fn f1<'a>(arg : Box<{ dyn X< : 32 } >>) {} + | + + + +error: expected parameter name, found `>` + --> $DIR/trait-path-missing-gen_arg.rs:6:36 + | +LL | fn f1<'a>(arg : Box>) {} + | ^ expected parameter name + +error: expected one of `!`, `)`, `+`, `,`, or `::`, found `>` + --> $DIR/trait-path-missing-gen_arg.rs:6:36 + | +LL | fn f1<'a>(arg : Box>) {} + | ^ + | | + | expected one of `!`, `)`, `+`, `,`, or `::` + | help: missing `,` + +error: expected one of `>`, a const expression, lifetime, or type, found `=` + --> $DIR/trait-path-missing-gen_arg.rs:14:30 + | +LL | fn f1<'a>(arg : Box>) {} + | - ^ expected one of `>`, a const expression, lifetime, or type + | | + | maybe try to close unmatched angle bracket + +error[E0747]: constant provided when a type was expected + --> $DIR/trait-path-missing-gen_arg.rs:6:23 + | +LL | fn f1<'a>(arg : Box>) {} + | ^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.rs b/tests/ui/generic-associated-types/parse/trait-path-segments.rs new file mode 100644 index 000000000..458e203eb --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.rs @@ -0,0 +1,32 @@ +const _: () = { + trait X { + type Y<'a>; + } + + fn f1<'a>(arg : Box>) {} + //~^ ERROR: expected one of + }; + +const _: () = { + trait X { + type Y<'a>; + } + + trait Z {} + + impl::Y<'a> = &'a u32>> Z for T {} + //~^ ERROR: expected one of +}; + +const _: () = { + trait X { + type Y<'a>; + } + + trait Z {} + + impl = &'a u32>> Z for T {} + //~^ ERROR: expected one of +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-segments.stderr b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr new file mode 100644 index 000000000..8bc737d67 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-segments.stderr @@ -0,0 +1,41 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:6:36 + | +LL | fn f1<'a>(arg : Box>) {} + | - ^ expected one of 8 possible tokens + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box = u32>>) {} + | + + +error: expected one of `,`, `::`, `:`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:17:35 + | +LL | impl::Y<'a> = &'a u32>> Z for T {} + | - ^ expected one of `,`, `::`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | impl::Y<'a>> = &'a u32>> Z for T {} + | + + +error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=` + --> $DIR/trait-path-segments.rs:28:25 + | +LL | impl = &'a u32>> Z for T {} + | - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | impl> = &'a u32>> Z for T {} + | + + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs new file mode 100644 index 000000000..1622b92aa --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs @@ -0,0 +1,11 @@ +trait X { + type Y<'a>; +} + +const _: () = { + fn f2<'a>(arg : Box = &'a ()>>) {} + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr new file mode 100644 index 000000000..0a09ec5dc --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr @@ -0,0 +1,33 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/trait-path-type-error-once-implemented.rs:6:29 + | +LL | fn f2<'a>(arg : Box = &'a ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/trait-path-type-error-once-implemented.rs:2:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg : Box = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/trait-path-type-error-once-implemented.rs:6:29 + | +LL | fn f2<'a>(arg : Box = &'a ()>>) {} + | ^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/trait-path-type-error-once-implemented.rs:2:10 + | +LL | type Y<'a>; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.rs b/tests/ui/generic-associated-types/parse/trait-path-types.rs new file mode 100644 index 000000000..74a00342f --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-types.rs @@ -0,0 +1,20 @@ +trait X { + type Y<'a>; +} + +const _: () = { + fn f<'a>(arg : Box>) {} + //~^ ERROR: expected one of +}; + +const _: () = { + fn f1<'a>(arg : Box) = &'a ()>>) {} + //~^ ERROR: expected one of +}; + +const _: () = { + fn f1<'a>(arg : Box>) {} + //~^ ERROR: expected one of +}; + +fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-types.stderr b/tests/ui/generic-associated-types/parse/trait-path-types.stderr new file mode 100644 index 000000000..8f7a73c95 --- /dev/null +++ b/tests/ui/generic-associated-types/parse/trait-path-types.stderr @@ -0,0 +1,41 @@ +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:6:37 + | +LL | fn f<'a>(arg : Box>) {} + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f<'a>(arg : Box = u32>>) {} + | + + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:11:37 + | +LL | fn f1<'a>(arg : Box) = &'a ()>>) {} + | - ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box)> = &'a ()>>) {} + | + + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/trait-path-types.rs:16:33 + | +LL | fn f1<'a>(arg : Box>) {} + | -- ^ expected one of `,`, `:`, or `>` + | | + | maybe try to close unmatched angle bracket + | +help: you might have meant to end the type parameters here + | +LL | fn f1<'a>(arg : Box = u32 >>) {} + | + + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/pointer_family.rs b/tests/ui/generic-associated-types/pointer_family.rs new file mode 100644 index 000000000..80827cd56 --- /dev/null +++ b/tests/ui/generic-associated-types/pointer_family.rs @@ -0,0 +1,34 @@ +// check-pass + +use std::rc::Rc; +use std::sync::Arc; +use std::ops::Deref; + +trait PointerFamily { + type Pointer: Deref; + fn new(value: T) -> Self::Pointer; +} + +struct ArcFamily; + +impl PointerFamily for ArcFamily { + type Pointer = Arc; + fn new(value: T) -> Self::Pointer { + Arc::new(value) + } +} + +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer = Rc; + fn new(value: T) -> Self::Pointer { + Rc::new(value) + } +} + +struct Foo { + bar: P::Pointer, +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/projection-bound-cycle-generic.rs b/tests/ui/generic-associated-types/projection-bound-cycle-generic.rs new file mode 100644 index 000000000..ecf6f69c9 --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle-generic.rs @@ -0,0 +1,59 @@ +// Like `projection-bound-cycle.rs` but this avoids using +// `feature(trivial_bounds)`. + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where ::Item: Sized; +} + +struct Number { t: T } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if ([T]: Sized) { # if the where clauses hold + // [T]: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item = [T] where [T]: Sized; + //~^ ERROR overflow evaluating the requirement ` as Foo>::Item == _` +} + +struct OnlySized where T: Sized { f: T } +impl Print for OnlySized { + fn print() { + println!("{}", std::mem::size_of::()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl Bar for T where T: Foo { + // This is not ok, we need to prove `wf(::Item)`, which requires + // knowing that `::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(::Item)`, which is an invalid cycle. + type Assoc = OnlySized<::Item>; +} + +fn foo() { + T::print() // oops, in fact `T = OnlySized` which is ill-formed +} + +fn bar() { + // we have `FromEnv(T: Bar)` hence + // `::Assoc` is well-formed and + // `Implemented(::Assoc: Print)` hold + foo::<::Assoc>() +} + +fn main() { + bar::>() +} diff --git a/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr b/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr new file mode 100644 index 000000000..aae9a56bb --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle-generic.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` as Foo>::Item == _` + --> $DIR/projection-bound-cycle-generic.rs:23:5 + | +LL | type Item = [T] where [T]: Sized; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/projection-bound-cycle.rs b/tests/ui/generic-associated-types/projection-bound-cycle.rs new file mode 100644 index 000000000..b51ae7ef2 --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle.rs @@ -0,0 +1,62 @@ +// Test case from Chalk. +// Make sure that we make sure that we don't allow arbitrary bounds to be +// proven when a bound and a where clause of an associated type are the same. + +#![feature(trivial_bounds)] + +trait Print { + fn print(); +} + +trait Foo { + type Item: Sized where ::Item: Sized; +} + +struct Number { } + +impl Foo for Number { + // Well-formedness checks require that the following + // goal is true: + // ``` + // if (str: Sized) { # if the where clauses hold + // str: Sized # then the bound on the associated type hold + // } + // ``` + // which it is :) + type Item = str where str: Sized; + //~^ ERROR overflow evaluating the requirement `::Item == _` +} + +struct OnlySized where T: Sized { f: T } +impl Print for OnlySized { + fn print() { + println!("{}", std::mem::size_of::()); + } +} + +trait Bar { + type Assoc: Print; +} + +impl Bar for T where T: Foo { + // This is not ok, we need to prove `wf(::Item)`, which requires + // knowing that `::Item: Sized` to satisfy the where clause. We + // can use the bound on `Foo::Item` for this, but that requires + // `wf(::Item)`, which is an invalid cycle. + type Assoc = OnlySized<::Item>; +} + +fn foo() { + T::print() // oops, in fact `T = OnlySized` which is ill-formed +} + +fn bar() { + // we have `FromEnv(T: Bar)` hence + // `::Assoc` is well-formed and + // `Implemented(::Assoc: Print)` hold + foo::<::Assoc>() +} + +fn main() { + bar::() +} diff --git a/tests/ui/generic-associated-types/projection-bound-cycle.stderr b/tests/ui/generic-associated-types/projection-bound-cycle.stderr new file mode 100644 index 000000000..b1b8afeec --- /dev/null +++ b/tests/ui/generic-associated-types/projection-bound-cycle.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Item == _` + --> $DIR/projection-bound-cycle.rs:26:5 + | +LL | type Item = str where str: Sized; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs new file mode 100644 index 000000000..8e4d5ca5e --- /dev/null +++ b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.rs @@ -0,0 +1,33 @@ +pub trait X { + type Y<'a> where Self: 'a; + fn m(&self) -> Self::Y<'_>; +} + +impl X for () { + type Y<'a> = &'a (); + + fn m(&self) -> Self::Y<'_> { + self + } +} + +fn f(x: &impl for<'a> X = &'a ()>) -> &'static () { + x.m() + //~^ ERROR lifetime may not live long enough +} + +fn g X = &'a ()>>(x: &T) -> &'static () { + x.m() + //~^ ERROR lifetime may not live long enough +} + +fn h(x: &()) -> &'static () { + x.m() + //~^ ERROR lifetime may not live long enough +} + +fn main() { + f(&()); + g(&()); + h(&()); +} diff --git a/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr new file mode 100644 index 000000000..753ead48b --- /dev/null +++ b/tests/ui/generic-associated-types/projection-type-lifetime-mismatch.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:15:5 + | +LL | fn f(x: &impl for<'a> X = &'a ()>) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:20:5 + | +LL | fn g X = &'a ()>>(x: &T) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/projection-type-lifetime-mismatch.rs:25:5 + | +LL | fn h(x: &()) -> &'static () { + | - let's call the lifetime of this reference `'1` +LL | x.m() + | ^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/self-outlives-lint.rs b/tests/ui/generic-associated-types/self-outlives-lint.rs new file mode 100644 index 000000000..673891fc3 --- /dev/null +++ b/tests/ui/generic-associated-types/self-outlives-lint.rs @@ -0,0 +1,224 @@ +// check-fail + +use std::fmt::Debug; + +// We have a `&'a self`, so we need a `Self: 'a` +trait Iterable { + type Item<'x>; + //~^ missing required + fn iter<'a>(&'a self) -> Self::Item<'a>; +} + +/* +impl Iterable for T { + type Item<'a> = &'a T; + fn iter<'a>(&'a self) -> Self::Item<'a> { + self + } +} +*/ + +// We have a `&'a T`, so we need a `T: 'x` +trait Deserializer { + type Out<'x>; + //~^ missing required + fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>; +} + +/* +impl Deserializer for () { + type Out<'a> = &'a T; + fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input } +} +*/ + +// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x` +trait Deserializer2 { + type Out<'x>; + //~^ missing required + fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>; +} + +// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y` +trait Deserializer3 { + type Out<'x, 'y>; + //~^ missing required + fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>; +} + +// `T` is a param on the function, so it can't be named by the associated type +trait Deserializer4 { + type Out<'x>; + fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>; +} + +struct Wrap(T); + +// We pass `Wrap` and we see `&'z Wrap`, so we require `D: 'x` +trait Des { + type Out<'x, D>; + //~^ missing required + fn des<'z, T>(&self, data: &'z Wrap) -> Self::Out<'z, Wrap>; +} +/* +impl Des for () { + type Out<'x, D> = &'x D; // Not okay + fn des<'a, T>(&self, data: &'a Wrap) -> Self::Out<'a, Wrap> { + data + } +} +*/ + +// We have `T` and `'z` as GAT substs. Because of `&'z Wrap`, there is an +// implied bound that `T: 'z`, so we require `D: 'x` +trait Des2 { + type Out<'x, D>; + //~^ missing required + fn des<'z, T>(&self, data: &'z Wrap) -> Self::Out<'z, T>; +} +/* +impl Des2 for () { + type Out<'x, D> = &'x D; + fn des<'a, T>(&self, data: &'a Wrap) -> Self::Out<'a, T> { + &data.0 + } +} +*/ + +// We see `&'z T`, so we require `D: 'x` +trait Des3 { + type Out<'x, D>; + //~^ missing required + fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>; +} +/* +impl Des3 for () { + type Out<'x, D> = &'x D; + fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> { + data + } +} +*/ + +// Similar case to before, except with GAT. +trait NoGat<'a> { + type Bar; + fn method(&'a self) -> Self::Bar; +} + +// Lifetime is not on function; except `Self: 'a` +// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one +trait TraitLifetime<'a> { + type Bar<'b>; + //~^ missing required + fn method(&'a self) -> Self::Bar<'a>; +} + +// Like above, but we have a where clause that can prove what we want +// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one +trait TraitLifetimeWhere<'a> where Self: 'a { + type Bar<'b>; + //~^ missing required + fn method(&'a self) -> Self::Bar<'a>; +} + +// Explicit bound instead of implicit; we want to still error +trait ExplicitBound { + type Bar<'b>; + //~^ missing required + fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b; +} + +// The use of the GAT here is not in the return, we don't want to error +trait NotInReturn { + type Bar<'b>; + fn method<'b>(&'b self) where Self::Bar<'b>: Debug; +} + +// We obviously error for `Iterator`, but we should also error for `Item` +trait IterableTwo { + type Item<'a>; + //~^ missing required + type Iterator<'a>: Iterator>; + //~^ missing required + fn iter<'a>(&'a self) -> Self::Iterator<'a>; +} + +trait IterableTwoWhere { + type Item<'a>; + //~^ missing required + type Iterator<'a>: Iterator> where Self: 'a; + fn iter<'a>(&'a self) -> Self::Iterator<'a>; +} + +// We also should report region outlives clauses. Here, we know that `'y: 'x`, +// because of `&'x &'y`, so we require that `'b: 'a`. +trait RegionOutlives { + type Bar<'a, 'b>; + //~^ missing required + fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>; +} + +/* +impl Foo for () { + type Bar<'a, 'b> = &'a &'b (); + fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> { + input + } +} +*/ + +// Similar to the above, except with explicit bounds +trait ExplicitRegionOutlives<'ctx> { + type Fut<'out>; + //~^ missing required + + fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out> + where + 'ctx: 'out; +} + + +// If there are multiple methods that return the GAT, require a set of clauses +// that can be satisfied by *all* methods +trait MultipleMethods { + type Bar<'me>; + + fn gimme<'a>(&'a self) -> Self::Bar<'a>; + fn gimme_default(&self) -> Self::Bar<'static>; +} + +// We would normally require `Self: 'a`, but we can prove that `Self: 'static` +// because of the the bounds on the trait, so the bound is proven +trait Trait: 'static { + type Assoc<'a>; + fn make_assoc(_: &u32) -> Self::Assoc<'_>; +} + +// We ignore `'static` lifetimes for any lints +trait StaticReturn<'a> { + type Y<'b>; + fn foo(&self) -> Self::Y<'static>; +} + +// Same as above, but with extra method that takes GAT - just make sure this works +trait StaticReturnAndTakes<'a> { + type Y<'b>; + fn foo(&self) -> Self::Y<'static>; + fn bar<'b>(&self, arg: Self::Y<'b>); +} + +// We require bounds when the GAT appears in the inputs +trait Input { + type Item<'a>; + //~^ missing required + fn takes_item<'a>(&'a self, item: Self::Item<'a>); +} + +// We don't require bounds when the GAT appears in the where clauses +trait WhereClause { + type Item<'a>; + fn takes_item<'a>(&'a self) where Self::Item<'a>: ; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/self-outlives-lint.stderr b/tests/ui/generic-associated-types/self-outlives-lint.stderr new file mode 100644 index 000000000..9e9b2e18a --- /dev/null +++ b/tests/ui/generic-associated-types/self-outlives-lint.stderr @@ -0,0 +1,178 @@ +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:7:5 + | +LL | type Item<'x>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:23:5 + | +LL | type Out<'x>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where T: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:37:5 + | +LL | type Out<'x>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where T: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bounds on `Out` + --> $DIR/self-outlives-lint.rs:44:5 + | +LL | type Out<'x, 'y>; + | ^^^^^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where T: 'x, U: 'y` + | + = note: these bounds are currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:59:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where D: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:75:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where D: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Out` + --> $DIR/self-outlives-lint.rs:90:5 + | +LL | type Out<'x, D>; + | ^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where D: 'x` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bounds on `Bar` + --> $DIR/self-outlives-lint.rs:112:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clauses: `where Self: 'a, Self: 'b` + | + = note: these bounds are currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Bar` + --> $DIR/self-outlives-lint.rs:120:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'b` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Bar` + --> $DIR/self-outlives-lint.rs:127:5 + | +LL | type Bar<'b>; + | ^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'b` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Iterator` + --> $DIR/self-outlives-lint.rs:142:5 + | +LL | type Iterator<'a>: Iterator>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:140:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:148:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Bar` + --> $DIR/self-outlives-lint.rs:157:5 + | +LL | type Bar<'a, 'b>; + | ^^^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where 'b: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Fut` + --> $DIR/self-outlives-lint.rs:173:5 + | +LL | type Fut<'out>; + | ^^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where 'ctx: 'out` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:213:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: aborting due to 16 previous errors + diff --git a/tests/ui/generic-associated-types/shadowing.rs b/tests/ui/generic-associated-types/shadowing.rs new file mode 100644 index 000000000..a05d6e143 --- /dev/null +++ b/tests/ui/generic-associated-types/shadowing.rs @@ -0,0 +1,29 @@ +trait Shadow<'a> { + type Bar<'a>; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope +} + +trait NoShadow<'a> { + type Bar<'b>; // OK +} + +impl<'a> NoShadow<'a> for &'a u32 { + type Bar<'a> = i32; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope +} + +trait ShadowT { + type Bar; + //~^ ERROR the name `T` is already used +} + +trait NoShadowT { + type Bar; // OK +} + +impl NoShadowT for Option { + type Bar = i32; + //~^ ERROR the name `T` is already used +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/shadowing.stderr b/tests/ui/generic-associated-types/shadowing.stderr new file mode 100644 index 000000000..bb32684bc --- /dev/null +++ b/tests/ui/generic-associated-types/shadowing.stderr @@ -0,0 +1,36 @@ +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:2:14 + | +LL | trait Shadow<'a> { + | -- first declared here +LL | type Bar<'a>; + | ^^ lifetime `'a` already in scope + +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:11:14 + | +LL | impl<'a> NoShadow<'a> for &'a u32 { + | -- first declared here +LL | type Bar<'a> = i32; + | ^^ lifetime `'a` already in scope + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:16:14 + | +LL | trait ShadowT { + | - first use of `T` +LL | type Bar; + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:25:14 + | +LL | impl NoShadowT for Option { + | - first use of `T` +LL | type Bar = i32; + | ^ already used + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0403, E0496. +For more information about an error, try `rustc --explain E0403`. diff --git a/tests/ui/generic-associated-types/streaming_iterator.rs b/tests/ui/generic-associated-types/streaming_iterator.rs new file mode 100644 index 000000000..408b8dc99 --- /dev/null +++ b/tests/ui/generic-associated-types/streaming_iterator.rs @@ -0,0 +1,74 @@ +// run-pass + +use std::fmt::Display; + +trait StreamingIterator { + type Item<'a> where Self: 'a; + // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. + fn next<'a>(&'a mut self) -> Option>; +} + +struct Foo { + // Applying a concrete lifetime to the constructor outside the trait. + bar: ::Item<'static>, +} + +// Users can bound parameters by the type constructed by that trait's associated type constructor +// of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid: +//FIXME(#44265): This next line should parse and be valid +//fn foo StreamingIterator=&'a [i32]>>(_iter: T) { /* ... */ } +fn _foo(_iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } + +// Full example of enumerate iterator + +#[must_use = "iterators are lazy and do nothing unless consumed"] +struct StreamEnumerate { + iter: I, + count: usize, +} + +impl StreamingIterator for StreamEnumerate { + type Item<'a> = (usize, I::Item<'a>) where Self: 'a; + fn next<'a>(&'a mut self) -> Option> { + match self.iter.next() { + None => None, + Some(val) => { + let r = Some((self.count, val)); + self.count += 1; + r + } + } + } +} + +impl StreamingIterator for I { + type Item<'a> = ::Item where Self: 'a; + fn next(&mut self) -> Option<::Item<'_>> { + Iterator::next(self) + } +} + +impl StreamEnumerate { + pub fn new(iter: I) -> Self { + StreamEnumerate { + count: 0, + iter, + } + } +} + +fn test_stream_enumerate() { + let v = vec!["a", "b", "c"]; + let mut se = StreamEnumerate::new(v.iter()); + while let Some(item) = se.next() { + assert_eq!(v[item.0], *item.1); + } + let x = Foo::> { + bar: &0u32, + }; + assert_eq!(*x.bar, 0u32); +} + +fn main() { + test_stream_enumerate(); +} diff --git a/tests/ui/generic-associated-types/trait-objects.base.stderr b/tests/ui/generic-associated-types/trait-objects.base.stderr new file mode 100644 index 000000000..556422c27 --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.base.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:13:21 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/trait-objects.rs:7:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/trait-objects.extended.stderr b/tests/ui/generic-associated-types/trait-objects.extended.stderr new file mode 100644 index 000000000..45b64d2b0 --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.extended.stderr @@ -0,0 +1,19 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/trait-objects.rs:15:5 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the function body +LL | +LL | x.size_hint().0 + | ^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'1` must outlive `'static` + | + = note: due to current limitations in the borrow checker, this implies a `'static` lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs new file mode 100644 index 000000000..17fed11ba --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -0,0 +1,19 @@ +// revisions: base extended + +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] + +trait StreamingIterator { + type Item<'a> where Self: 'a; + fn size_hint(&self) -> (usize, Option); + // Uncommenting makes `StreamingIterator` not object safe +// fn next(&mut self) -> Self::Item<'_>; +} + +fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + //[base]~^ the trait `StreamingIterator` cannot be made into an object + x.size_hint().0 + //[extended]~^ borrowed data escapes +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/type-param-defaults.rs b/tests/ui/generic-associated-types/type-param-defaults.rs new file mode 100644 index 000000000..f034076b0 --- /dev/null +++ b/tests/ui/generic-associated-types/type-param-defaults.rs @@ -0,0 +1,34 @@ +// Check that we disallow GAT param defaults, even with `invalid_type_param_default` allowed + +#![allow(invalid_type_param_default)] + +trait Trait { + type Assoc; + //~^ defaults for type parameters are only allowed +} + +impl Trait for () { + type Assoc = u64; + //~^ defaults for type parameters are only allowed +} + +impl Trait for u32 { + type Assoc = T; + //~^ defaults for type parameters are only allowed +} + +trait Other {} +impl Other for u32 {} + +fn foo() +where + T: Trait, + T::Assoc: Other { + } + +fn main() { + // errors + foo::<()>(); + // works + foo::(); +} diff --git a/tests/ui/generic-associated-types/type-param-defaults.stderr b/tests/ui/generic-associated-types/type-param-defaults.stderr new file mode 100644 index 000000000..85ccaba0e --- /dev/null +++ b/tests/ui/generic-associated-types/type-param-defaults.stderr @@ -0,0 +1,20 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/type-param-defaults.rs:6:16 + | +LL | type Assoc; + | ^^^^^^^ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/type-param-defaults.rs:11:16 + | +LL | type Assoc = u64; + | ^^^^^^^ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/type-param-defaults.rs:16:16 + | +LL | type Assoc = T; + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs new file mode 100644 index 000000000..1cc09aa6d --- /dev/null +++ b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs @@ -0,0 +1,25 @@ +pub trait X { + type Y<'a: 'static>; + //~^ WARNING unnecessary lifetime parameter +} + +impl X for () { + type Y<'a> = &'a (); +} + +struct B<'a, T: for<'r> X = &'r ()>> { + f: ::Y<'a>, + //~^ ERROR lifetime bound not satisfied +} + +struct C<'a, T: X> { + f: ::Y<'a>, + //~^ ERROR lifetime bound not satisfied +} + +struct D<'a> { + f: <() as X>::Y<'a>, + //~^ ERROR lifetime bound not satisfied +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr new file mode 100644 index 000000000..fbd79879d --- /dev/null +++ b/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr @@ -0,0 +1,50 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/unsatified-item-lifetime-bound.rs:2:12 + | +LL | type Y<'a: 'static>; + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error[E0478]: lifetime bound not satisfied + --> $DIR/unsatified-item-lifetime-bound.rs:11:8 + | +LL | f: ::Y<'a>, + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:10:10 + | +LL | struct B<'a, T: for<'r> X = &'r ()>> { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0478]: lifetime bound not satisfied + --> $DIR/unsatified-item-lifetime-bound.rs:16:8 + | +LL | f: ::Y<'a>, + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:15:10 + | +LL | struct C<'a, T: X> { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0478]: lifetime bound not satisfied + --> $DIR/unsatified-item-lifetime-bound.rs:21:8 + | +LL | f: <() as X>::Y<'a>, + | ^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/unsatified-item-lifetime-bound.rs:20:10 + | +LL | struct D<'a> { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs new file mode 100644 index 000000000..7137d9237 --- /dev/null +++ b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.rs @@ -0,0 +1,19 @@ +trait ATy { + type Item<'a>: 'a; +} + +impl<'b> ATy for &'b () { + type Item<'a> = &'b (); + //~^ ERROR the type `&'b ()` does not fulfill the required lifetime +} + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); + //~^ ERROR the type `&'a ()` does not fulfill the required lifetime +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr new file mode 100644 index 000000000..1c9ac01ec --- /dev/null +++ b/tests/ui/generic-associated-types/unsatisfied-outlives-bound.stderr @@ -0,0 +1,27 @@ +error[E0477]: the type `&'b ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:6:21 + | +LL | type Item<'a> = &'b (); + | ^^^^^^ + | +note: type must outlive the lifetime `'a` as defined here as required by this binding + --> $DIR/unsatisfied-outlives-bound.rs:6:15 + | +LL | type Item<'a> = &'b (); + | ^^ + +error[E0477]: the type `&'a ()` does not fulfill the required lifetime + --> $DIR/unsatisfied-outlives-bound.rs:15:21 + | +LL | type Item<'a> = &'a (); + | ^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/unsatisfied-outlives-bound.rs:11:20 + | +LL | type Item<'a>: 'static; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/generic-associated-types/variance_constraints.rs b/tests/ui/generic-associated-types/variance_constraints.rs new file mode 100644 index 000000000..0e9dbb8b1 --- /dev/null +++ b/tests/ui/generic-associated-types/variance_constraints.rs @@ -0,0 +1,22 @@ +// check-pass +// issue #69184 + +trait A { + type B<'a> where Self: 'a; + + fn make_b<'a>(&'a self) -> Self::B<'a>; +} + +struct S {} +impl A for S { + type B<'a> = &'a S; + fn make_b<'a>(&'a self) -> &'a Self { + self + } +} + +enum E<'a> { + S(::B<'a>), +} + +fn main() {} diff --git a/tests/ui/generics/autobind.rs b/tests/ui/generics/autobind.rs new file mode 100644 index 000000000..70606a2a2 --- /dev/null +++ b/tests/ui/generics/autobind.rs @@ -0,0 +1,12 @@ +// run-pass + +fn f(x: Vec) -> T { return x.into_iter().next().unwrap(); } + +fn g(act: F) -> isize where F: FnOnce(Vec) -> isize { return act(vec![1, 2, 3]); } + +pub fn main() { + assert_eq!(g(f), 1); + let f1 = f; + assert_eq!(f1(vec!["x".to_string(), "y".to_string(), "z".to_string()]), + "x".to_string()); +} diff --git a/tests/ui/generics/auxiliary/default_type_params_xc.rs b/tests/ui/generics/auxiliary/default_type_params_xc.rs new file mode 100644 index 000000000..aacbd672a --- /dev/null +++ b/tests/ui/generics/auxiliary/default_type_params_xc.rs @@ -0,0 +1,5 @@ +pub struct Heap; + +pub struct FakeHeap; + +pub struct FakeVec { pub f: Option<(T,A)> } diff --git a/tests/ui/generics/bad-mid-path-type-params.rs b/tests/ui/generics/bad-mid-path-type-params.rs new file mode 100644 index 000000000..23a5d1525 --- /dev/null +++ b/tests/ui/generics/bad-mid-path-type-params.rs @@ -0,0 +1,44 @@ +struct S { + contents: T, +} + +impl S { + fn new(x: T, _: U) -> S { + S { + contents: x, + } + } +} + +trait Trait { + fn new(x: T, y: U) -> Self; +} + +struct S2 { + contents: isize, +} + +impl Trait for S2 { + fn new(x: isize, _: U) -> S2 { + S2 { + contents: x, + } + } +} + +fn foo<'a>() { + let _ = S::new::(1, 1.0); + //~^ ERROR this associated function takes 1 + + let _ = S::<'a,isize>::new::(1, 1.0); + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + + let _: S2 = Trait::new::(1, 1.0); + //~^ ERROR this associated function takes 1 + + let _: S2 = Trait::<'a,isize>::new::(1, 1.0); + //~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this associated function takes 1 +} + +fn main() {} diff --git a/tests/ui/generics/bad-mid-path-type-params.stderr b/tests/ui/generics/bad-mid-path-type-params.stderr new file mode 100644 index 000000000..aee2b6015 --- /dev/null +++ b/tests/ui/generics/bad-mid-path-type-params.stderr @@ -0,0 +1,73 @@ +error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/bad-mid-path-type-params.rs:30:16 + | +LL | let _ = S::new::(1, 1.0); + | ^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated function defined here, with 1 generic parameter: `U` + --> $DIR/bad-mid-path-type-params.rs:6:8 + | +LL | fn new(x: T, _: U) -> S { + | ^^^ - + +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/bad-mid-path-type-params.rs:33:13 + | +LL | let _ = S::<'a,isize>::new::(1, 1.0); + | ^ -- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/bad-mid-path-type-params.rs:1:8 + | +LL | struct S { + | ^ + +error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/bad-mid-path-type-params.rs:36:24 + | +LL | let _: S2 = Trait::new::(1, 1.0); + | ^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated function defined here, with 1 generic parameter: `U` + --> $DIR/bad-mid-path-type-params.rs:14:8 + | +LL | fn new(x: T, y: U) -> Self; + | ^^^ - + +error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/bad-mid-path-type-params.rs:39:17 + | +LL | let _: S2 = Trait::<'a,isize>::new::(1, 1.0); + | ^^^^^ -- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + | +note: trait defined here, with 0 lifetime parameters + --> $DIR/bad-mid-path-type-params.rs:13:7 + | +LL | trait Trait { + | ^^^^^ + +error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/bad-mid-path-type-params.rs:39:36 + | +LL | let _: S2 = Trait::<'a,isize>::new::(1, 1.0); + | ^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated function defined here, with 1 generic parameter: `U` + --> $DIR/bad-mid-path-type-params.rs:14:8 + | +LL | fn new(x: T, y: U) -> Self; + | ^^^ - + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-alias-unique.rs b/tests/ui/generics/generic-alias-unique.rs new file mode 100644 index 000000000..fc1383986 --- /dev/null +++ b/tests/ui/generics/generic-alias-unique.rs @@ -0,0 +1,10 @@ +// run-pass + +fn id(t: T) -> T { return t; } + +pub fn main() { + let expected: Box<_> = Box::new(100); + let actual = id::>(expected.clone()); + println!("{}", *actual); + assert_eq!(*expected, *actual); +} diff --git a/tests/ui/generics/generic-arg-mismatch-recover.rs b/tests/ui/generics/generic-arg-mismatch-recover.rs new file mode 100644 index 000000000..2cf7f1d65 --- /dev/null +++ b/tests/ui/generics/generic-arg-mismatch-recover.rs @@ -0,0 +1,12 @@ +struct Foo<'a, T: 'a>(&'a T); + +struct Bar<'a>(&'a ()); + +fn main() { + Foo::<'static, 'static, ()>(&0); + //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + + Bar::<'static, 'static, ()>(&()); + //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| ERROR this struct takes 0 +} diff --git a/tests/ui/generics/generic-arg-mismatch-recover.stderr b/tests/ui/generics/generic-arg-mismatch-recover.stderr new file mode 100644 index 000000000..45fea925f --- /dev/null +++ b/tests/ui/generics/generic-arg-mismatch-recover.stderr @@ -0,0 +1,45 @@ +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/generic-arg-mismatch-recover.rs:6:5 + | +LL | Foo::<'static, 'static, ()>(&0); + | ^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/generic-arg-mismatch-recover.rs:1:8 + | +LL | struct Foo<'a, T: 'a>(&'a T); + | ^^^ -- + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/generic-arg-mismatch-recover.rs:9:5 + | +LL | Bar::<'static, 'static, ()>(&()); + | ^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/generic-arg-mismatch-recover.rs:3:8 + | +LL | struct Bar<'a>(&'a ()); + | ^^^ -- + +error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/generic-arg-mismatch-recover.rs:9:5 + | +LL | Bar::<'static, 'static, ()>(&()); + | ^^^ -- help: remove this generic argument + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/generic-arg-mismatch-recover.rs:3:8 + | +LL | struct Bar<'a>(&'a ()); + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-default-type-params-cross-crate.rs b/tests/ui/generics/generic-default-type-params-cross-crate.rs new file mode 100644 index 000000000..834b15be1 --- /dev/null +++ b/tests/ui/generics/generic-default-type-params-cross-crate.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:default_type_params_xc.rs + +// pretty-expanded FIXME #23616 + +extern crate default_type_params_xc; + +struct Vec(#[allow(unused_tuple_struct_fields)] Option<(T,A)>); + +struct Foo; + +fn main() { + let _a = Vec::(None); + let _b = Vec::(None); + let _c = default_type_params_xc::FakeVec:: { f: None }; + let _d = default_type_params_xc::FakeVec:: { f: None }; +} diff --git a/tests/ui/generics/generic-default-type-params.rs b/tests/ui/generics/generic-default-type-params.rs new file mode 100644 index 000000000..afdd301fd --- /dev/null +++ b/tests/ui/generics/generic-default-type-params.rs @@ -0,0 +1,53 @@ +// run-pass +struct Foo { + a: A +} + +impl Foo { + fn bar_int(&self) -> isize { + self.a + } +} + +impl Foo { + fn bar_char(&self) -> char { + self.a + } +} + +impl Foo { + fn bar(&self) { + let (i, c): (isize, char) = self.a; + assert_eq!(Foo { a: i }.bar_int(), i); + assert_eq!(Foo { a: c }.bar_char(), c); + } +} + +impl Foo { + fn baz(&self) -> A { + self.a.clone() + } +} + +fn default_foo(x: Foo) { + let (i, c): (isize, char) = x.a; + assert_eq!(i, 1); + assert_eq!(c, 'a'); + + x.bar(); + assert_eq!(x.baz(), (1, 'a')); +} + +#[derive(PartialEq, Debug)] +struct BazHelper(T); + +#[derive(PartialEq, Debug)] +// Ensure that we can use previous type parameters in defaults. +struct Baz, V = Option>(T, U, V); + +fn main() { + default_foo(Foo { a: (1, 'a') }); + + let x: Baz = Baz(true, BazHelper(false), Some(BazHelper(true))); + assert_eq!(x, Baz(true, BazHelper(false), Some(BazHelper(true)))); +} diff --git a/tests/ui/generics/generic-derived-type.rs b/tests/ui/generics/generic-derived-type.rs new file mode 100644 index 000000000..c643496fa --- /dev/null +++ b/tests/ui/generics/generic-derived-type.rs @@ -0,0 +1,21 @@ +// run-pass +fn g(x: X) -> X { return x; } + +#[derive(Clone)] +struct Pair { + a: T, + b: T +} + +fn f(t: T) -> Pair { + let x: Pair = Pair {a: t.clone(), b: t}; + return g::>(x); +} + +pub fn main() { + let b = f::(10); + println!("{}" ,b.a); + println!("{}", b.b); + assert_eq!(b.a, 10); + assert_eq!(b.b, 10); +} diff --git a/tests/ui/generics/generic-exterior-unique.rs b/tests/ui/generics/generic-exterior-unique.rs new file mode 100644 index 000000000..10d87f9f4 --- /dev/null +++ b/tests/ui/generics/generic-exterior-unique.rs @@ -0,0 +1,11 @@ +// run-pass + +struct Recbox {x: Box} + +fn reclift(t: T) -> Recbox { return Recbox { x: Box::new(t) }; } + +pub fn main() { + let foo: isize = 17; + let rbfoo: Recbox = reclift::(foo); + assert_eq!(*rbfoo.x, foo); +} diff --git a/tests/ui/generics/generic-extern-lifetime.rs b/tests/ui/generics/generic-extern-lifetime.rs new file mode 100644 index 000000000..c42744808 --- /dev/null +++ b/tests/ui/generics/generic-extern-lifetime.rs @@ -0,0 +1,15 @@ +// Test to make sure the names of the lifetimes are correctly resolved +// in extern blocks. + +extern "C" { + pub fn life<'a>(x: &'a i32); + pub fn life2<'b>(x: &'a i32, y: &'b i32); //~ ERROR use of undeclared lifetime name `'a` + pub fn life3<'a>(x: &'a i32, y: &i32) -> &'a i32; + pub fn life4<'b>(x: for<'c> fn(&'a i32)); //~ ERROR use of undeclared lifetime name `'a` + pub fn life5<'b>(x: for<'c> fn(&'b i32)); + pub fn life6<'b>(x: for<'c> fn(&'c i32)); + pub fn life7<'b>() -> for<'c> fn(&'a i32); //~ ERROR use of undeclared lifetime name `'a` + pub fn life8<'b>() -> for<'c> fn(&'b i32); + pub fn life9<'b>() -> for<'c> fn(&'c i32); +} +fn main() {} diff --git a/tests/ui/generics/generic-extern-lifetime.stderr b/tests/ui/generics/generic-extern-lifetime.stderr new file mode 100644 index 000000000..33332e760 --- /dev/null +++ b/tests/ui/generics/generic-extern-lifetime.stderr @@ -0,0 +1,42 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generic-extern-lifetime.rs:6:26 + | +LL | pub fn life2<'b>(x: &'a i32, y: &'b i32); + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generic-extern-lifetime.rs:8:37 + | +LL | pub fn life4<'b>(x: for<'c> fn(&'a i32)); + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | pub fn life4<'b>(x: for<'a, 'c> fn(&'a i32)); + | +++ +help: consider introducing lifetime `'a` here + | +LL | pub fn life4<'a, 'b>(x: for<'c> fn(&'a i32)); + | +++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generic-extern-lifetime.rs:11:39 + | +LL | pub fn life7<'b>() -> for<'c> fn(&'a i32); + | ^^ undeclared lifetime + | +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | pub fn life7<'b>() -> for<'a, 'c> fn(&'a i32); + | +++ +help: consider introducing lifetime `'a` here + | +LL | pub fn life7<'a, 'b>() -> for<'c> fn(&'a i32); + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/generics/generic-extern-mangle.rs b/tests/ui/generics/generic-extern-mangle.rs new file mode 100644 index 000000000..985a6f39c --- /dev/null +++ b/tests/ui/generics/generic-extern-mangle.rs @@ -0,0 +1,9 @@ +// run-pass +use std::ops::Add; + +extern "C" fn foo(a: T, b: T) -> T::Output { a + b } + +fn main() { + assert_eq!(100u8, foo(0u8, 100u8)); + assert_eq!(100u16, foo(0u16, 100u16)); +} diff --git a/tests/ui/generics/generic-extern.rs b/tests/ui/generics/generic-extern.rs new file mode 100644 index 000000000..3690d6fd0 --- /dev/null +++ b/tests/ui/generics/generic-extern.rs @@ -0,0 +1,7 @@ +extern "C" { + fn foo(); //~ ERROR foreign items may not have type parameters +} + +fn main() { + foo::(); +} diff --git a/tests/ui/generics/generic-extern.stderr b/tests/ui/generics/generic-extern.stderr new file mode 100644 index 000000000..c90215b61 --- /dev/null +++ b/tests/ui/generics/generic-extern.stderr @@ -0,0 +1,11 @@ +error[E0044]: foreign items may not have type parameters + --> $DIR/generic-extern.rs:2:5 + | +LL | fn foo(); + | ^^^^^^^^^^^^ can't have type parameters + | + = help: replace the type parameters with concrete types like `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/generics/generic-fn-infer.rs b/tests/ui/generics/generic-fn-infer.rs new file mode 100644 index 000000000..9ba422473 --- /dev/null +++ b/tests/ui/generics/generic-fn-infer.rs @@ -0,0 +1,10 @@ +// run-pass + + + + +// Issue #45: infer type parameters in function applications + +fn id(x: T) -> T { return x; } + +pub fn main() { let x: isize = 42; let y: isize = id(x); assert_eq!(x, y); } diff --git a/tests/ui/generics/generic-fn-twice.rs b/tests/ui/generics/generic-fn-twice.rs new file mode 100644 index 000000000..2f25fc24c --- /dev/null +++ b/tests/ui/generics/generic-fn-twice.rs @@ -0,0 +1,11 @@ +// run-pass + + + +// pretty-expanded FIXME #23616 + +mod foomod { + pub fn foo() { } +} + +pub fn main() { foomod::foo::(); foomod::foo::(); } diff --git a/tests/ui/generics/generic-fn-unique.rs b/tests/ui/generics/generic-fn-unique.rs new file mode 100644 index 000000000..7e246bce9 --- /dev/null +++ b/tests/ui/generics/generic-fn-unique.rs @@ -0,0 +1,8 @@ +// run-pass + +fn f(x: Box) -> Box { return x; } + +pub fn main() { + let x = f(Box::new(3)); + println!("{}", *x); +} diff --git a/tests/ui/generics/generic-fn.rs b/tests/ui/generics/generic-fn.rs new file mode 100644 index 000000000..8038fabc1 --- /dev/null +++ b/tests/ui/generics/generic-fn.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] + +fn id(x: T) -> T { return x; } + +#[derive(Copy, Clone)] +struct Triple {x: isize, y: isize, z: isize} + +pub fn main() { + let mut x = 62; + let mut y = 63; + let a = 'a'; + let mut b = 'b'; + let p: Triple = Triple {x: 65, y: 66, z: 67}; + let mut q: Triple = Triple {x: 68, y: 69, z: 70}; + y = id::(x); + println!("{}", y); + assert_eq!(x, y); + b = id::(a); + println!("{}", b); + assert_eq!(a, b); + q = id::(p); + x = p.z; + y = q.z; + println!("{}", y); + assert_eq!(x, y); +} diff --git a/tests/ui/generics/generic-function-item-where-type.rs b/tests/ui/generics/generic-function-item-where-type.rs new file mode 100644 index 000000000..e1b0578ca --- /dev/null +++ b/tests/ui/generics/generic-function-item-where-type.rs @@ -0,0 +1,6 @@ +fn foo() {} + +fn main() { + foo::

() + //~^ ERROR constant provided when a type was expected +} diff --git a/tests/ui/generics/generic-function-item-where-type.stderr b/tests/ui/generics/generic-function-item-where-type.stderr new file mode 100644 index 000000000..88594129c --- /dev/null +++ b/tests/ui/generics/generic-function-item-where-type.stderr @@ -0,0 +1,12 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/generic-function-item-where-type.rs:4:11 + | +LL | foo::
() + | ^^^^ + | + = help: `main` is a function item, not a type + = help: function item types cannot be named directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/generics/generic-impl-less-params-with-defaults.rs b/tests/ui/generics/generic-impl-less-params-with-defaults.rs new file mode 100644 index 000000000..66afbb58a --- /dev/null +++ b/tests/ui/generics/generic-impl-less-params-with-defaults.rs @@ -0,0 +1,13 @@ +use std::marker; + +struct Foo( + marker::PhantomData<(A,B,C)>); + +impl Foo { + fn new() -> Foo {Foo(marker::PhantomData)} +} + +fn main() { + Foo::::new(); + //~^ ERROR this struct takes at least 2 generic arguments but 1 generic argument +} diff --git a/tests/ui/generics/generic-impl-less-params-with-defaults.stderr b/tests/ui/generics/generic-impl-less-params-with-defaults.stderr new file mode 100644 index 000000000..cdbb57902 --- /dev/null +++ b/tests/ui/generics/generic-impl-less-params-with-defaults.stderr @@ -0,0 +1,21 @@ +error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied + --> $DIR/generic-impl-less-params-with-defaults.rs:11:5 + | +LL | Foo::::new(); + | ^^^ ----- supplied 1 generic argument + | | + | expected at least 2 generic arguments + | +note: struct defined here, with at least 2 generic parameters: `A`, `B` + --> $DIR/generic-impl-less-params-with-defaults.rs:3:8 + | +LL | struct Foo( + | ^^^ - - +help: add missing generic argument + | +LL | Foo::::new(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-impl-more-params-with-defaults.rs b/tests/ui/generics/generic-impl-more-params-with-defaults.rs new file mode 100644 index 000000000..a28332374 --- /dev/null +++ b/tests/ui/generics/generic-impl-more-params-with-defaults.rs @@ -0,0 +1,15 @@ +use std::marker; + +struct Heap; + +struct Vec( + marker::PhantomData<(T,A)>); + +impl Vec { + fn new() -> Vec {Vec(marker::PhantomData)} +} + +fn main() { + Vec::::new(); + //~^ ERROR this struct takes at most 2 generic arguments but 3 generic arguments were supplied +} diff --git a/tests/ui/generics/generic-impl-more-params-with-defaults.stderr b/tests/ui/generics/generic-impl-more-params-with-defaults.stderr new file mode 100644 index 000000000..fe9b670da --- /dev/null +++ b/tests/ui/generics/generic-impl-more-params-with-defaults.stderr @@ -0,0 +1,17 @@ +error[E0107]: this struct takes at most 2 generic arguments but 3 generic arguments were supplied + --> $DIR/generic-impl-more-params-with-defaults.rs:13:5 + | +LL | Vec::::new(); + | ^^^ ---- help: remove this generic argument + | | + | expected at most 2 generic arguments + | +note: struct defined here, with at most 2 generic parameters: `T`, `A` + --> $DIR/generic-impl-more-params-with-defaults.rs:5:8 + | +LL | struct Vec( + | ^^^ - -------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-ivec-leak.rs b/tests/ui/generics/generic-ivec-leak.rs new file mode 100644 index 000000000..9610bdcb3 --- /dev/null +++ b/tests/ui/generics/generic-ivec-leak.rs @@ -0,0 +1,5 @@ +// run-pass +#![allow(non_camel_case_types)] +enum wrapper { wrapped(#[allow(unused_tuple_struct_fields)] T), } + +pub fn main() { let _w = wrapper::wrapped(vec![1, 2, 3, 4, 5]); } diff --git a/tests/ui/generics/generic-lifetime-trait-impl.rs b/tests/ui/generics/generic-lifetime-trait-impl.rs new file mode 100644 index 000000000..6ffaba19d --- /dev/null +++ b/tests/ui/generics/generic-lifetime-trait-impl.rs @@ -0,0 +1,23 @@ +// This code used to produce an ICE on the definition of trait Bar +// with the following message: +// +// Type parameter out of range when substituting in region 'a (root +// type=fn(Self) -> 'astr) (space=FnSpace, index=0) +// +// Regression test for issue #16218. + +trait Bar<'a> { + fn dummy(&'a self); +} + +trait Foo<'a> { + fn dummy(&'a self) { } + fn bar<'b, T: Bar<'b>>(self) -> &'b str; +} + +impl<'a> Foo<'a> for &'a str { + fn bar>(self) -> &'a str { panic!() } //~ ERROR lifetime +} + +fn main() { +} diff --git a/tests/ui/generics/generic-lifetime-trait-impl.stderr b/tests/ui/generics/generic-lifetime-trait-impl.stderr new file mode 100644 index 000000000..4ae5098a1 --- /dev/null +++ b/tests/ui/generics/generic-lifetime-trait-impl.stderr @@ -0,0 +1,12 @@ +error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration + --> $DIR/generic-lifetime-trait-impl.rs:19:11 + | +LL | fn bar<'b, T: Bar<'b>>(self) -> &'b str; + | ---------------- lifetimes in impl do not match this method in trait +... +LL | fn bar>(self) -> &'a str { panic!() } + | ^^^^^^^^^^^^ lifetimes do not match method in trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/generics/generic-newtype-struct.rs b/tests/ui/generics/generic-newtype-struct.rs new file mode 100644 index 000000000..aa879f01a --- /dev/null +++ b/tests/ui/generics/generic-newtype-struct.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct S(#[allow(unused_tuple_struct_fields)] T); + +pub fn main() { + let _s = S(2); +} diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed new file mode 100644 index 000000000..501acb6e1 --- /dev/null +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -0,0 +1,159 @@ +// run-rustfix + +#![deny(no_mangle_generic_items)] + + +pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + +pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + +#[no_mangle] +pub fn baz(x: &i32) -> &i32 { x } + +#[no_mangle] +pub fn qux<'a>(x: &'a i32) -> &i32 { x } + +pub struct Foo; + +impl Foo { + + pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + + pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + pub fn baz(x: &i32) -> &i32 { x } + + #[no_mangle] + pub fn qux<'a>(x: &'a i32) -> &i32 { x } +} + +trait Trait1 { + fn foo(); + extern "C" fn bar(); + fn baz(x: &i32) -> &i32; + fn qux<'a>(x: &'a i32) -> &i32; +} + +impl Trait1 for Foo { + + fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + + extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + fn baz(x: &i32) -> &i32 { x } + + #[no_mangle] + fn qux<'a>(x: &'a i32) -> &i32 { x } +} + +trait Trait2 { + fn foo(); + fn foo2(); + extern "C" fn bar(); + fn baz(x: &i32) -> &i32; + fn qux<'a>(x: &'a i32) -> &i32; +} + +impl Trait2 for Foo { + + fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + + fn foo2() {} //~ ERROR functions generic over types or consts must be mangled + + + extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + + fn baz(x: &i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled + + + fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled +} + +pub struct Bar(#[allow(unused_tuple_struct_fields)] T); + +impl Bar { + + pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + + pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + + pub fn baz() {} //~ ERROR functions generic over types or consts must be mangled +} + +impl Bar { + #[no_mangle] + pub fn qux() {} +} + +trait Trait3 { + fn foo(); + extern "C" fn bar(); + fn baz(); +} + +impl Trait3 for Bar { + + fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + + extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + + fn baz() {} //~ ERROR functions generic over types or consts must be mangled +} + +pub struct Baz<'a>(#[allow(unused_tuple_struct_fields)] &'a i32); + +impl<'a> Baz<'a> { + #[no_mangle] + pub fn foo() {} + + #[no_mangle] + pub fn bar<'b>(x: &'b i32) -> &i32 { x } +} + +trait Trait4 { + fn foo(); + fn bar<'a>(x: &'a i32) -> &i32; +} + +impl Trait4 for Bar { + #[no_mangle] + fn foo() {} + + #[no_mangle] + fn bar<'b>(x: &'b i32) -> &i32 { x } +} + +impl<'a> Trait4 for Baz<'a> { + #[no_mangle] + fn foo() {} + + #[no_mangle] + fn bar<'b>(x: &'b i32) -> &i32 { x } +} + +trait Trait5 { + fn foo(); +} + +impl Trait5 for Foo { + #[no_mangle] + fn foo() {} +} + +impl Trait5 for Bar { + #[no_mangle] + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs new file mode 100644 index 000000000..74e407078 --- /dev/null +++ b/tests/ui/generics/generic-no-mangle.rs @@ -0,0 +1,159 @@ +// run-rustfix + +#![deny(no_mangle_generic_items)] + +#[no_mangle] +pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled + +#[no_mangle] +pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + +#[no_mangle] +pub fn baz(x: &i32) -> &i32 { x } + +#[no_mangle] +pub fn qux<'a>(x: &'a i32) -> &i32 { x } + +pub struct Foo; + +impl Foo { + #[no_mangle] + pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + pub fn baz(x: &i32) -> &i32 { x } + + #[no_mangle] + pub fn qux<'a>(x: &'a i32) -> &i32 { x } +} + +trait Trait1 { + fn foo(); + extern "C" fn bar(); + fn baz(x: &i32) -> &i32; + fn qux<'a>(x: &'a i32) -> &i32; +} + +impl Trait1 for Foo { + #[no_mangle] + fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + fn baz(x: &i32) -> &i32 { x } + + #[no_mangle] + fn qux<'a>(x: &'a i32) -> &i32 { x } +} + +trait Trait2 { + fn foo(); + fn foo2(); + extern "C" fn bar(); + fn baz(x: &i32) -> &i32; + fn qux<'a>(x: &'a i32) -> &i32; +} + +impl Trait2 for Foo { + #[no_mangle] + fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + fn foo2() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + fn baz(x: &i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled +} + +pub struct Bar(#[allow(unused_tuple_struct_fields)] T); + +impl Bar { + #[no_mangle] + pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + pub extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + pub fn baz() {} //~ ERROR functions generic over types or consts must be mangled +} + +impl Bar { + #[no_mangle] + pub fn qux() {} +} + +trait Trait3 { + fn foo(); + extern "C" fn bar(); + fn baz(); +} + +impl Trait3 for Bar { + #[no_mangle] + fn foo() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + extern "C" fn bar() {} //~ ERROR functions generic over types or consts must be mangled + + #[no_mangle] + fn baz() {} //~ ERROR functions generic over types or consts must be mangled +} + +pub struct Baz<'a>(#[allow(unused_tuple_struct_fields)] &'a i32); + +impl<'a> Baz<'a> { + #[no_mangle] + pub fn foo() {} + + #[no_mangle] + pub fn bar<'b>(x: &'b i32) -> &i32 { x } +} + +trait Trait4 { + fn foo(); + fn bar<'a>(x: &'a i32) -> &i32; +} + +impl Trait4 for Bar { + #[no_mangle] + fn foo() {} + + #[no_mangle] + fn bar<'b>(x: &'b i32) -> &i32 { x } +} + +impl<'a> Trait4 for Baz<'a> { + #[no_mangle] + fn foo() {} + + #[no_mangle] + fn bar<'b>(x: &'b i32) -> &i32 { x } +} + +trait Trait5 { + fn foo(); +} + +impl Trait5 for Foo { + #[no_mangle] + fn foo() {} +} + +impl Trait5 for Bar { + #[no_mangle] + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/generics/generic-no-mangle.stderr b/tests/ui/generics/generic-no-mangle.stderr new file mode 100644 index 000000000..adfddbe9c --- /dev/null +++ b/tests/ui/generics/generic-no-mangle.stderr @@ -0,0 +1,144 @@ +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:6:1 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub fn foo() {} + | ^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/generic-no-mangle.rs:3:9 + | +LL | #![deny(no_mangle_generic_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:9:1 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub extern "C" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:21:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub fn foo() {} + | ^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:24:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub extern "C" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:42:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn foo() {} + | ^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:45:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | extern "C" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:64:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn foo() {} + | ^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:67:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn foo2() {} + | ^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:70:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | extern "C" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:73:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn baz(x: &i32) -> &i32 { x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:76:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn qux<'a>(x: &'a i32) -> &i32 { x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:83:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub fn foo() {} + | ^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:86:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub extern "C" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:89:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | pub fn baz() {} + | ^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:105:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn foo() {} + | ^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:108:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | extern "C" fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: functions generic over types or consts must be mangled + --> $DIR/generic-no-mangle.rs:111:5 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | fn baz() {} + | ^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/generics/generic-non-trailing-defaults.rs b/tests/ui/generics/generic-non-trailing-defaults.rs new file mode 100644 index 000000000..16ea71d48 --- /dev/null +++ b/tests/ui/generics/generic-non-trailing-defaults.rs @@ -0,0 +1,10 @@ +struct Heap; + +struct Vec(A, T); +//~^ ERROR generic parameters with a default must be trailing + +struct Foo, C>(A, B, C); +//~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use + +fn main() {} diff --git a/tests/ui/generics/generic-non-trailing-defaults.stderr b/tests/ui/generics/generic-non-trailing-defaults.stderr new file mode 100644 index 000000000..713ba091b --- /dev/null +++ b/tests/ui/generics/generic-non-trailing-defaults.stderr @@ -0,0 +1,21 @@ +error: generic parameters with a default must be trailing + --> $DIR/generic-non-trailing-defaults.rs:3:12 + | +LL | struct Vec(A, T); + | ^ + +error: generic parameters with a default must be trailing + --> $DIR/generic-non-trailing-defaults.rs:6:15 + | +LL | struct Foo, C>(A, B, C); + | ^ + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/generic-non-trailing-defaults.rs:6:23 + | +LL | struct Foo, C>(A, B, C); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/generics/generic-object.rs b/tests/ui/generics/generic-object.rs new file mode 100644 index 000000000..851424a11 --- /dev/null +++ b/tests/ui/generics/generic-object.rs @@ -0,0 +1,21 @@ +// run-pass + +trait Foo { + fn get(&self) -> T; +} + +struct S { + x: isize +} + +impl Foo for S { + fn get(&self) -> isize { + self.x + } +} + +pub fn main() { + let x = Box::new(S { x: 1 }); + let y = x as Box>; + assert_eq!(y.get(), 1); +} diff --git a/tests/ui/generics/generic-param-attrs.rs b/tests/ui/generics/generic-param-attrs.rs new file mode 100644 index 000000000..3c5cc84c6 --- /dev/null +++ b/tests/ui/generics/generic-param-attrs.rs @@ -0,0 +1,38 @@ +// This test previously ensured that attributes on formals in generic parameter +// lists are rejected without a feature gate. + +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(rustc_attrs)] + +struct StLt<#[rustc_dummy] 'a>(&'a u32); +struct StTy<#[rustc_dummy] I>(I); +enum EnLt<#[rustc_dummy] 'b> { A(&'b u32), B } +enum EnTy<#[rustc_dummy] J> { A(J), B } +trait TrLt<#[rustc_dummy] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } +trait TrTy<#[rustc_dummy] K> { fn foo(&self, _: K); } +type TyLt<#[rustc_dummy] 'd> = &'d u32; +type TyTy<#[rustc_dummy] L> = (L, ); + +impl<#[rustc_dummy] 'e> StLt<'e> { } +impl<#[rustc_dummy] M> StTy { } +impl<#[rustc_dummy] 'f> TrLt<'f> for StLt<'f> { + fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } } +} +impl<#[rustc_dummy] N> TrTy for StTy { + fn foo(&self, _: N) { } +} + +fn f_lt<#[rustc_dummy] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } +fn f_ty<#[rustc_dummy] O>(_: O) { } + +impl StTy { + fn m_lt<#[rustc_dummy] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } + fn m_ty<#[rustc_dummy] P>(_: P) { } +} + +fn hof_lt(_: Q) + where Q: for <#[rustc_dummy] 'i> Fn(&'i [u32]) -> &'i u32 +{} + +fn main() {} diff --git a/tests/ui/generics/generic-recursive-tag.rs b/tests/ui/generics/generic-recursive-tag.rs new file mode 100644 index 000000000..b344da1c7 --- /dev/null +++ b/tests/ui/generics/generic-recursive-tag.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(non_camel_case_types)] + +enum list { #[allow(unused_tuple_struct_fields)] cons(Box, Box>), nil, } + +pub fn main() { + let _a: list = + list::cons::(Box::new(10), + Box::new(list::cons::(Box::new(12), + Box::new(list::cons::(Box::new(13), + Box::new(list::nil::)))))); +} diff --git a/tests/ui/generics/generic-static-methods.rs b/tests/ui/generics/generic-static-methods.rs new file mode 100644 index 000000000..b39fa081a --- /dev/null +++ b/tests/ui/generics/generic-static-methods.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(non_camel_case_types)] + + +trait vec_utils { + fn map_(x: &Self, f: F) -> Vec where F: FnMut(&T) -> U; +} + +impl vec_utils for Vec { + fn map_(x: &Vec , mut f: F) -> Vec where F: FnMut(&T) -> U { + let mut r = Vec::new(); + for elt in x { + r.push(f(elt)); + } + r + } +} + +pub fn main() { + assert_eq!(vec_utils::map_(&vec![1,2,3], |&x| x+1), [2,3,4]); +} diff --git a/tests/ui/generics/generic-tag-corruption.rs b/tests/ui/generics/generic-tag-corruption.rs new file mode 100644 index 000000000..35de3c1f7 --- /dev/null +++ b/tests/ui/generics/generic-tag-corruption.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(non_camel_case_types)] + + +// This used to cause memory corruption in stage 0. +// pretty-expanded FIXME #23616 + +enum thing { some(#[allow(unused_tuple_struct_fields)] K), } + +pub fn main() { let _x = thing::some("hi".to_string()); } diff --git a/tests/ui/generics/generic-tag-local.rs b/tests/ui/generics/generic-tag-local.rs new file mode 100644 index 000000000..c5772e841 --- /dev/null +++ b/tests/ui/generics/generic-tag-local.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum clam { a(#[allow(unused_tuple_struct_fields)] T), } + +pub fn main() { let _c = clam::a(3); } diff --git a/tests/ui/generics/generic-tag-match.rs b/tests/ui/generics/generic-tag-match.rs new file mode 100644 index 000000000..09ed6a808 --- /dev/null +++ b/tests/ui/generics/generic-tag-match.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(non_camel_case_types)] + +enum foo { arm(T), } + +fn altfoo(f: foo) { + let mut hit = false; + match f { foo::arm::(_x) => { println!("in arm"); hit = true; } } + assert!((hit)); +} + +pub fn main() { altfoo::(foo::arm::(10)); } diff --git a/tests/ui/generics/generic-tag-values.rs b/tests/ui/generics/generic-tag-values.rs new file mode 100644 index 000000000..230f477b6 --- /dev/null +++ b/tests/ui/generics/generic-tag-values.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(non_camel_case_types)] + +enum noption { some(T), } + +struct Pair { x: isize, y: isize } + +pub fn main() { + let nop: noption = noption::some::(5); + match nop { noption::some::(n) => { println!("{}", n); assert_eq!(n, 5); } } + let nop2: noption = noption::some(Pair{x: 17, y: 42}); + match nop2 { + noption::some(t) => { + println!("{}", t.x); + println!("{}", t.y); + assert_eq!(t.x, 17); + assert_eq!(t.y, 42); + } + } +} diff --git a/tests/ui/generics/generic-tag.rs b/tests/ui/generics/generic-tag.rs new file mode 100644 index 000000000..31fc2178d --- /dev/null +++ b/tests/ui/generics/generic-tag.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +enum option { some(#[allow(unused_tuple_struct_fields)] Box), none, } + +pub fn main() { + let mut a: option = option::some::(Box::new(10)); + a = option::none::; +} diff --git a/tests/ui/generics/generic-temporary.rs b/tests/ui/generics/generic-temporary.rs new file mode 100644 index 000000000..b63b534d0 --- /dev/null +++ b/tests/ui/generics/generic-temporary.rs @@ -0,0 +1,16 @@ +// run-pass + +fn mk() -> isize { return 1; } + +fn chk(a: isize) { println!("{}", a); assert_eq!(a, 1); } + +fn apply(produce: fn() -> T, + consume: fn(T)) { + consume(produce()); +} + +pub fn main() { + let produce: fn() -> isize = mk; + let consume: fn(v: isize) = chk; + apply::(produce, consume); +} diff --git a/tests/ui/generics/generic-tup.rs b/tests/ui/generics/generic-tup.rs new file mode 100644 index 000000000..79ebd648c --- /dev/null +++ b/tests/ui/generics/generic-tup.rs @@ -0,0 +1,8 @@ +// run-pass +fn get_third(t: (T, T, T)) -> T { let (_, _, x) = t; return x; } + +pub fn main() { + println!("{}", get_third((1, 2, 3))); + assert_eq!(get_third((1, 2, 3)), 3); + assert_eq!(get_third((5u8, 6u8, 7u8)), 7u8); +} diff --git a/tests/ui/generics/generic-type-less-params-with-defaults.rs b/tests/ui/generics/generic-type-less-params-with-defaults.rs new file mode 100644 index 000000000..6b877ab8a --- /dev/null +++ b/tests/ui/generics/generic-type-less-params-with-defaults.rs @@ -0,0 +1,11 @@ +use std::marker; + +struct Heap; + +struct Vec( + marker::PhantomData<(T,A)>); + +fn main() { + let _: Vec; + //~^ ERROR missing generics for struct `Vec` +} diff --git a/tests/ui/generics/generic-type-less-params-with-defaults.stderr b/tests/ui/generics/generic-type-less-params-with-defaults.stderr new file mode 100644 index 000000000..6450bbd8b --- /dev/null +++ b/tests/ui/generics/generic-type-less-params-with-defaults.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for struct `Vec` + --> $DIR/generic-type-less-params-with-defaults.rs:9:12 + | +LL | let _: Vec; + | ^^^ expected at least 1 generic argument + | +note: struct defined here, with at least 1 generic parameter: `T` + --> $DIR/generic-type-less-params-with-defaults.rs:5:8 + | +LL | struct Vec( + | ^^^ - +help: add missing generic argument + | +LL | let _: Vec; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-type-more-params-with-defaults.rs b/tests/ui/generics/generic-type-more-params-with-defaults.rs new file mode 100644 index 000000000..3dab03297 --- /dev/null +++ b/tests/ui/generics/generic-type-more-params-with-defaults.rs @@ -0,0 +1,11 @@ +use std::marker; + +struct Heap; + +struct Vec( + marker::PhantomData<(T,A)>); + +fn main() { + let _: Vec; + //~^ ERROR this struct takes at most 2 generic arguments but 3 generic arguments +} diff --git a/tests/ui/generics/generic-type-more-params-with-defaults.stderr b/tests/ui/generics/generic-type-more-params-with-defaults.stderr new file mode 100644 index 000000000..7f0198f0e --- /dev/null +++ b/tests/ui/generics/generic-type-more-params-with-defaults.stderr @@ -0,0 +1,17 @@ +error[E0107]: this struct takes at most 2 generic arguments but 3 generic arguments were supplied + --> $DIR/generic-type-more-params-with-defaults.rs:9:12 + | +LL | let _: Vec; + | ^^^ ---- help: remove this generic argument + | | + | expected at most 2 generic arguments + | +note: struct defined here, with at most 2 generic parameters: `T`, `A` + --> $DIR/generic-type-more-params-with-defaults.rs:5:8 + | +LL | struct Vec( + | ^^^ - -------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generics/generic-type-params-forward-mention.rs b/tests/ui/generics/generic-type-params-forward-mention.rs new file mode 100644 index 000000000..000c47095 --- /dev/null +++ b/tests/ui/generics/generic-type-params-forward-mention.rs @@ -0,0 +1,6 @@ +// Ensure that we get an error and not an ICE for this problematic case. +struct Foo, U = bool>(T, U); +//~^ ERROR generic parameters with a default cannot use forward declared identifiers +fn main() { + let x: Foo; +} diff --git a/tests/ui/generics/generic-type-params-forward-mention.stderr b/tests/ui/generics/generic-type-params-forward-mention.stderr new file mode 100644 index 000000000..fa661c274 --- /dev/null +++ b/tests/ui/generics/generic-type-params-forward-mention.stderr @@ -0,0 +1,9 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/generic-type-params-forward-mention.rs:2:23 + | +LL | struct Foo, U = bool>(T, U); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/generics/generic-type-params-name-repr.rs b/tests/ui/generics/generic-type-params-name-repr.rs new file mode 100644 index 000000000..6e0beec66 --- /dev/null +++ b/tests/ui/generics/generic-type-params-name-repr.rs @@ -0,0 +1,51 @@ +use std::marker; + +struct A; +struct B; +struct C; +struct Foo(marker::PhantomData<(T,U,V)>); + +struct Hash(marker::PhantomData); +struct HashMap>(marker::PhantomData<(K,V,H)>); + +fn main() { + // Ensure that the printed type doesn't include the default type params... + let _: Foo = (); + //~^ ERROR mismatched types + //~| expected struct `Foo`, found `()` + //~| expected struct `Foo` + //~| found unit type `()` + + // ...even when they're present, but the same types as the defaults. + let _: Foo = (); + //~^ ERROR mismatched types + //~| expected struct `Foo`, found `()` + //~| expected struct `Foo` + //~| found unit type `()` + + // Including cases where the default is using previous type params. + let _: HashMap = (); + //~^ ERROR mismatched types + //~| expected struct `HashMap`, found `()` + //~| expected struct `HashMap` + //~| found unit type `()` + let _: HashMap> = (); + //~^ ERROR mismatched types + //~| expected struct `HashMap`, found `()` + //~| expected struct `HashMap` + //~| found unit type `()` + + // But not when there's a different type in between. + let _: Foo = (); + //~^ ERROR mismatched types + //~| expected struct `Foo`, found `()` + //~| expected struct `Foo` + //~| found unit type `()` + + // And don't print <> at all when there's just defaults. + let _: Foo = (); + //~^ ERROR mismatched types + //~| expected struct `Foo`, found `()` + //~| expected struct `Foo` + //~| found unit type `()` +} diff --git a/tests/ui/generics/generic-type-params-name-repr.stderr b/tests/ui/generics/generic-type-params-name-repr.stderr new file mode 100644 index 000000000..4c3c00396 --- /dev/null +++ b/tests/ui/generics/generic-type-params-name-repr.stderr @@ -0,0 +1,69 @@ +error[E0308]: mismatched types + --> $DIR/generic-type-params-name-repr.rs:13:25 + | +LL | let _: Foo = (); + | ---------- ^^ expected struct `Foo`, found `()` + | | + | expected due to this + | + = note: expected struct `Foo` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/generic-type-params-name-repr.rs:20:31 + | +LL | let _: Foo = (); + | ---------------- ^^ expected struct `Foo`, found `()` + | | + | expected due to this + | + = note: expected struct `Foo` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/generic-type-params-name-repr.rs:27:37 + | +LL | let _: HashMap = (); + | ---------------------- ^^ expected struct `HashMap`, found `()` + | | + | expected due to this + | + = note: expected struct `HashMap` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/generic-type-params-name-repr.rs:32:51 + | +LL | let _: HashMap> = (); + | ------------------------------------ ^^ expected struct `HashMap`, found `()` + | | + | expected due to this + | + = note: expected struct `HashMap` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/generic-type-params-name-repr.rs:39:31 + | +LL | let _: Foo = (); + | ---------------- ^^ expected struct `Foo`, found `()` + | | + | expected due to this + | + = note: expected struct `Foo` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/generic-type-params-name-repr.rs:46:27 + | +LL | let _: Foo = (); + | ------------ ^^ expected struct `Foo`, found `()` + | | + | expected due to this + | + = note: expected struct `Foo` + found unit type `()` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generics/generic-type-synonym.rs b/tests/ui/generics/generic-type-synonym.rs new file mode 100644 index 000000000..4f181fbcc --- /dev/null +++ b/tests/ui/generics/generic-type-synonym.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + + +// pretty-expanded FIXME #23616 + +struct Foo { + a: T +} + +type Bar = Foo; + +fn takebar(_b: Bar) { } + +pub fn main() { } diff --git a/tests/ui/generics/generic-type.rs b/tests/ui/generics/generic-type.rs new file mode 100644 index 000000000..aa46db07e --- /dev/null +++ b/tests/ui/generics/generic-type.rs @@ -0,0 +1,11 @@ +// run-pass + + + +struct Pair {x: T, y: T} + +pub fn main() { + let x: Pair = Pair {x: 10, y: 12}; + assert_eq!(x.x, 10); + assert_eq!(x.y, 12); +} diff --git a/tests/ui/generics/generic-unique.rs b/tests/ui/generics/generic-unique.rs new file mode 100644 index 000000000..2f34712ec --- /dev/null +++ b/tests/ui/generics/generic-unique.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] + +struct Triple { x: T, y: T, z: T } + +fn box_it(x: Triple) -> Box> { return Box::new(x); } + +pub fn main() { + let x: Box> = box_it::(Triple{x: 1, y: 2, z: 3}); + assert_eq!(x.y, 2); +} diff --git a/tests/ui/generics/issue-106694.rs b/tests/ui/generics/issue-106694.rs new file mode 100644 index 000000000..c4b02ee81 --- /dev/null +++ b/tests/ui/generics/issue-106694.rs @@ -0,0 +1,24 @@ +trait Trait {} + +fn foo(_: impl &Trait) {} +//~^ ERROR expected a trait, found type + +fn bar(_: T) {} +//~^ ERROR expected a trait, found type + +fn partially_correct_impl(_: impl &*const &Trait + Copy) {} +//~^ ERROR expected a trait, found type + +fn foo_bad(_: impl &BadTrait) {} +//~^ ERROR expected a trait, found type +//~^^ ERROR cannot find trait `BadTrait` in this scope + +fn bar_bad(_: T) {} +//~^ ERROR expected a trait, found type +//~^^ ERROR cannot find trait `BadTrait` in this scope + +fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} +//~^ ERROR expected a trait, found type +//~^^ ERROR cannot find trait `BadTrait` in this scope + +fn main() {} diff --git a/tests/ui/generics/issue-106694.stderr b/tests/ui/generics/issue-106694.stderr new file mode 100644 index 000000000..235b8982a --- /dev/null +++ b/tests/ui/generics/issue-106694.stderr @@ -0,0 +1,93 @@ +error: expected a trait, found type + --> $DIR/issue-106694.rs:3:16 + | +LL | fn foo(_: impl &Trait) {} + | ^^^^^^ + | +help: consider removing the indirection + | +LL - fn foo(_: impl &Trait) {} +LL + fn foo(_: impl Trait) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:6:11 + | +LL | fn bar(_: T) {} + | ^^^^^^ + | +help: consider removing the indirection + | +LL - fn bar(_: T) {} +LL + fn bar(_: T) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:9:35 + | +LL | fn partially_correct_impl(_: impl &*const &Trait + Copy) {} + | ^^^^^^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn partially_correct_impl(_: impl &*const &Trait + Copy) {} +LL + fn partially_correct_impl(_: impl Trait + Copy) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:12:20 + | +LL | fn foo_bad(_: impl &BadTrait) {} + | ^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn foo_bad(_: impl &BadTrait) {} +LL + fn foo_bad(_: impl BadTrait) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:16:15 + | +LL | fn bar_bad(_: T) {} + | ^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn bar_bad(_: T) {} +LL + fn bar_bad(_: T) {} + | + +error: expected a trait, found type + --> $DIR/issue-106694.rs:20:39 + | +LL | fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} + | ^^^^^^^^^^^^^^^^^ + | +help: consider removing the indirection + | +LL - fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} +LL + fn partially_correct_impl_bad(_: impl BadTrait + Copy) {} + | + +error[E0405]: cannot find trait `BadTrait` in this scope + --> $DIR/issue-106694.rs:12:21 + | +LL | fn foo_bad(_: impl &BadTrait) {} + | ^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `BadTrait` in this scope + --> $DIR/issue-106694.rs:16:16 + | +LL | fn bar_bad(_: T) {} + | ^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `BadTrait` in this scope + --> $DIR/issue-106694.rs:20:48 + | +LL | fn partially_correct_impl_bad(_: impl &*const &BadTrait + Copy) {} + | ^^^^^^^^ not found in this scope + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/generics/issue-1112.rs b/tests/ui/generics/issue-1112.rs new file mode 100644 index 000000000..3ba7bb217 --- /dev/null +++ b/tests/ui/generics/issue-1112.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +// Issue #1112 +// Alignment of interior pointers to dynamic-size types + + +struct X { + a: T, + b: u8, + c: bool, + d: u8, + e: u16, + f: u8, + g: u8 +} + +pub fn main() { + let x: X = X { + a: 12345678, + b: 9, + c: true, + d: 10, + e: 11, + f: 12, + g: 13 + }; + bar(x); +} + +fn bar(x: X) { + assert_eq!(x.b, 9); + assert_eq!(x.c, true); + assert_eq!(x.d, 10); + assert_eq!(x.e, 11); + assert_eq!(x.f, 12); + assert_eq!(x.g, 13); +} diff --git a/tests/ui/generics/issue-2936.rs b/tests/ui/generics/issue-2936.rs new file mode 100644 index 000000000..6b932d01d --- /dev/null +++ b/tests/ui/generics/issue-2936.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait bar { + fn get_bar(&self) -> T; +} + +fn foo>(b: U) -> T { + b.get_bar() +} + +struct cbar { + x: isize, +} + +impl bar for cbar { + fn get_bar(&self) -> isize { + self.x + } +} + +fn cbar(x: isize) -> cbar { + cbar { + x: x + } +} + +pub fn main() { + let x: isize = foo::(cbar(5)); + assert_eq!(x, 5); +} diff --git a/tests/ui/generics/issue-32498.rs b/tests/ui/generics/issue-32498.rs new file mode 100644 index 000000000..1b5440109 --- /dev/null +++ b/tests/ui/generics/issue-32498.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +// Making sure that no overflow occurs. + +struct L { + n: Option, +} +type L8 = L>>>>>>>; +type L64 = L8>>>; + +fn main() { + use std::mem::size_of; + assert_eq!(size_of::>>(), 1); + assert_eq!(size_of::>>>(), 1); +} diff --git a/tests/ui/generics/issue-333.rs b/tests/ui/generics/issue-333.rs new file mode 100644 index 000000000..0753aaa07 --- /dev/null +++ b/tests/ui/generics/issue-333.rs @@ -0,0 +1,7 @@ +// run-pass + +fn quux(x: T) -> T { let f = id::; return f(x); } + +fn id(x: T) -> T { return x; } + +pub fn main() { assert_eq!(quux(10), 10); } diff --git a/tests/ui/generics/issue-59508-1.rs b/tests/ui/generics/issue-59508-1.rs new file mode 100644 index 000000000..8e27749e8 --- /dev/null +++ b/tests/ui/generics/issue-59508-1.rs @@ -0,0 +1,16 @@ +#![allow(dead_code)] + +// This test checks that generic parameter re-ordering diagnostic suggestions mention that +// consts come after types and lifetimes. +// We cannot run rustfix on this test because of the above const generics warning. + +struct A; + +impl A { + pub fn do_things() { + //~^ ERROR lifetime parameters must be declared prior to type and const parameters + println!("panic"); + } +} + +fn main() {} diff --git a/tests/ui/generics/issue-59508-1.stderr b/tests/ui/generics/issue-59508-1.stderr new file mode 100644 index 000000000..1c510044f --- /dev/null +++ b/tests/ui/generics/issue-59508-1.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-59508-1.rs:10:25 + | +LL | pub fn do_things() { + | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>` + +error: aborting due to previous error + diff --git a/tests/ui/generics/issue-59508.fixed b/tests/ui/generics/issue-59508.fixed new file mode 100644 index 000000000..de8f47d4c --- /dev/null +++ b/tests/ui/generics/issue-59508.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(dead_code)] + +// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds. + +struct A; + +impl A { + pub fn do_things<'a, 'b: 'a, T>() { + //~^ ERROR lifetime parameters must be declared prior to type and const parameters + println!("panic"); + } +} + +fn main() {} diff --git a/tests/ui/generics/issue-59508.rs b/tests/ui/generics/issue-59508.rs new file mode 100644 index 000000000..a4c7d4ff2 --- /dev/null +++ b/tests/ui/generics/issue-59508.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(dead_code)] + +// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds. + +struct A; + +impl A { + pub fn do_things() { + //~^ ERROR lifetime parameters must be declared prior to type and const parameters + println!("panic"); + } +} + +fn main() {} diff --git a/tests/ui/generics/issue-59508.stderr b/tests/ui/generics/issue-59508.stderr new file mode 100644 index 000000000..fd23b6276 --- /dev/null +++ b/tests/ui/generics/issue-59508.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-59508.rs:10:25 + | +LL | pub fn do_things() { + | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>` + +error: aborting due to previous error + diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs new file mode 100644 index 000000000..cc93794e8 --- /dev/null +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs @@ -0,0 +1,20 @@ +#![crate_type="lib"] + +// rust-lang/rust#61631: The use of `Self` in the defaults of generic +// types in a *trait* definition are allowed. +// +// It *must* be accepted; we have used this pattern extensively since +// Rust 1.0 (see e.g. `trait Add`). +trait Tnobound

(processor: P) -> Task +where P: Execute + 'static { + Task { + _processor: Box::new(move || { + let q = P::E::inject(&()); + processor.execute(q); + }) + } +} + +fn main() { + task(annotate( + Annotate::>::new(), + |value: &mut usize| { + *value = 2; + } + )); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs new file mode 100644 index 000000000..002054732 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs @@ -0,0 +1,33 @@ +// check-pass + +use std::marker::PhantomData; + +trait Lt<'a> { + type T; +} +struct Id(PhantomData); +impl<'a,T> Lt<'a> for Id { + type T = T; +} + +struct Ref(PhantomData) where T: ?Sized; +impl<'a,T> Lt<'a> for Ref +where T: 'a + Lt<'a> + ?Sized +{ + type T = &'a T; +} +struct Mut(PhantomData) where T: ?Sized; +impl<'a,T> Lt<'a> for Mut +where T: 'a + Lt<'a> + ?Sized +{ + type T = &'a mut T; +} + +struct C(for<'a> fn(>::T) -> O) where I: for<'a> Lt<'a>; + + +fn main() { + let c = C::,_>(|()| 3); + c.0(()); + +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs new file mode 100644 index 000000000..d84e30f49 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs @@ -0,0 +1,32 @@ +trait ATC<'a> { + type Type: Sized; +} + +trait WithDefault: for<'a> ATC<'a> { + fn with_default Fn(>::Type)>(f: F); +} + +fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( + f: F, + x: >::Type, +) { + f(x); +} + +impl<'a> ATC<'a> for () { + type Type = Self; +} + +impl WithDefault for () { + fn with_default Fn(>::Type)>(f: F) { + // Errors with a bogus type mismatch. + //f(()); + // Going through another generic function works fine. + call(f, ()); + //~^ expected a + } +} + +fn main() { + // <()>::with_default(|_| {}); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr new file mode 100644 index 000000000..b30dd36d2 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -0,0 +1,19 @@ +error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` + --> $DIR/issue-62529-3.rs:25:14 + | +LL | call(f, ()); + | ---- ^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F` + | | + | required by a bound introduced by this call + | + = note: expected a closure with arguments `((),)` + found a closure with arguments `(<_ as ATC<'a>>::Type,)` +note: required by a bound in `call` + --> $DIR/issue-62529-3.rs:9:36 + | +LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs new file mode 100644 index 000000000..8c2a59868 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs @@ -0,0 +1,39 @@ +// check-pass + +use std::marker::PhantomData; +use std::mem; + +trait Container<'a> { + type Root: 'a; +} + +type RootOf<'a, T> = >::Root; + +struct Test<'a, T> where T: Container<'a> { + pub root: T::Root, + marker: PhantomData<&'a mut &'a mut ()>, +} + +impl<'a, 'b> Container<'b> for &'a str { + type Root = &'b str; +} + +impl<'a, T> Test<'a, T> where T: for<'b> Container<'b> { + fn new(root: RootOf<'a, T>) -> Test<'a, T> { + Test { + root: root, + marker: PhantomData + } + } + + fn with_mut(&mut self, f: F) -> R where + F: for<'b> FnOnce(&'b mut RootOf<'b, T>) -> R { + f(unsafe { mem::transmute(&mut self.root) }) + } +} + +fn main() { + let val = "root"; + let mut test: Test<&str> = Test::new(val); + test.with_mut(|_| { }); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs new file mode 100644 index 000000000..03f257a02 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs @@ -0,0 +1,27 @@ +// check-pass + +pub struct Struct {} + +pub trait Trait<'a> { + type Assoc; + + fn method() -> Self::Assoc; +} + +impl<'a> Trait<'a> for Struct { + type Assoc = (); + + fn method() -> Self::Assoc {} +} + +pub fn function(f: F) +where + F: for<'a> FnOnce(>::Assoc), + T: for<'b> Trait<'b>, +{ + f(T::method()); +} + +fn main() { + function::<_, Struct>(|_| {}); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs new file mode 100644 index 000000000..74a4785e4 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs @@ -0,0 +1,77 @@ +// check-pass + +use std::cell::RefMut; + +fn main() { + StateMachine2::Init.resume(); +} + +enum StateMachine2<'a> { + Init, + #[allow(dead_code)] // match required for ICE + AfterTwoYields { + p: Backed<'a, *mut String>, + }, +} + +impl<'a> StateMachine2<'a> { + fn take(&self) -> Self { + StateMachine2::Init + } +} + +impl<'a> StateMachine2<'a> { + fn resume(&mut self) -> () { + use StateMachine2::*; + match self.take() { + AfterTwoYields { p } => { + p.with(|_| {}); + } + _ => panic!("Resume after completed."), + } + } +} + +unsafe trait Unpack<'a> { + type Unpacked: 'a; + + fn unpack(&self) -> Self::Unpacked { + unsafe { std::mem::transmute_copy(&self) } + } +} + +unsafe trait Pack { + type Packed; + + fn pack(&self) -> Self::Packed { + unsafe { std::mem::transmute_copy(&self) } + } +} + +unsafe impl<'a> Unpack<'a> for String { + type Unpacked = String; +} + +unsafe impl Pack for String { + type Packed = String; +} + +unsafe impl<'a> Unpack<'a> for *mut String { + type Unpacked = &'a mut String; +} + +unsafe impl<'a> Pack for &'a mut String { + type Packed = *mut String; +} + +struct Backed<'a, U>(RefMut<'a, Option>, U); + +impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> { + fn with(self, f: F) -> Backed<'a, ()> + where + F: for<'f> FnOnce(>::Unpacked) -> (), + { + let result = f(self.1.unpack()); + Backed(self.0, result) + } +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs new file mode 100644 index 000000000..3ced40230 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait MyTrait<'a> { + type Output: 'a; + fn gimme_value(&self) -> Self::Output; +} + +pub struct MyStruct; + +impl<'a> MyTrait<'a> for MyStruct { + type Output = &'a usize; + fn gimme_value(&self) -> Self::Output { + unimplemented!() + } +} + +fn meow(t: T, f: F) +where + T: for<'any> MyTrait<'any>, + F: for<'any2> Fn(>::Output), +{ + let v = t.gimme_value(); + f(v); +} + +fn main() { + let struc = MyStruct; + meow(struc, |foo| { + println!("{:?}", foo); + }) +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr new file mode 100644 index 000000000..0f38f8e32 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.migrate.stderr @@ -0,0 +1,79 @@ +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:54:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r, 's> FnOnce<(&'r &'s str,)>` + found type `for<'r> FnOnce<(&'r &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:54:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:9 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:54:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&&str,)>` + found type `for<'r> FnOnce<(&'r &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:54:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:44 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>` + found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:58:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:9 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:58:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `FnOnce<(&Wrapper<'_>,)>` + found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:58:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:34:44 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs new file mode 100644 index 000000000..1d90226a3 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.rs @@ -0,0 +1,51 @@ +// check-fail +#![feature(rustc_attrs)] + +trait Parser<'s> { + type Output; + + fn call(&self, input: &'s str) -> (&'s str, Self::Output); +} + +impl<'s, F, T> Parser<'s> for F +where F: Fn(&'s str) -> (&'s str, T) { + type Output = T; + fn call(&self, input: &'s str) -> (&'s str, T) { + self(input) + } +} + +fn foo( + f1: F1, + base: &'static str, + f2: F2 +) +where + F1: for<'a> Parser<'a>, + F2: FnOnce(&::Output) -> bool +{ + let s: String = base.to_owned(); + let str_ref = s.as_ref(); + let (remaining, produced) = f1.call(str_ref); + assert!(f2(&produced)); + assert_eq!(remaining.len(), 0); +} + +struct Wrapper<'a>(&'a str); + +fn main() { + fn bar<'a>(s: &'a str) -> (&'a str, &'a str) { + (&s[..1], &s[..]) + } + + fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) { + (&s[..1], Wrapper(&s[..])) + } + + foo(bar, "string", |s| s.len() == 5); + //~^ ERROR mismatched types + //~| ERROR mismatched types + foo(baz, "string", |s| s.0.len() == 5); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr new file mode 100644 index 000000000..4ef96cd95 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr @@ -0,0 +1,79 @@ +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:45:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` + found trait `for<'a> FnOnce<(&'a &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:45:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:9 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:45:5 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>` + found trait `for<'a> FnOnce<(&'a &str,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:45:24 + | +LL | foo(bar, "string", |s| s.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:44 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:48:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` + found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:48:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:9 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-71955.rs:48:5 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>` + found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-71955.rs:48:24 + | +LL | foo(baz, "string", |s| s.0.len() == 5); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-71955.rs:25:44 + | +LL | F2: FnOnce(&::Output) -> bool + | ^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs new file mode 100644 index 000000000..93ccb4268 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-74261.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +trait A<'a> { + type B; + fn b(self) -> Self::B; +} + +struct T; +struct S<'a>(PhantomData<&'a ()>); + +impl<'a> A<'a> for T { + type B = S<'a>; + fn b(self) -> Self::B { + S(PhantomData) + } +} + +fn s(t: TT, f: F) +where + TT: for<'a> A<'a>, + F: for<'a> FnOnce(>::B) +{ + f(t.b()); +} + +fn main() { + s(T, |_| {}); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs new file mode 100644 index 000000000..583470080 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-76956.rs @@ -0,0 +1,15 @@ +// check-pass + +use std::ops::Deref; + +struct Data { + boxed: Box<&'static i32> +} + +impl Data { + fn use_data(&self, user: impl for <'a> FnOnce( as Deref>::Target)) { + user(*self.boxed) + } +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs new file mode 100644 index 000000000..00a866f22 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs @@ -0,0 +1,71 @@ +// build-pass +// edition:2018 + +type BoxFuture = std::pin::Pin>>; + +fn main() { + f(); +} + +async fn f() { + run("dependency").await; +} + +struct InMemoryStorage; + +struct User<'dep> { + dep: &'dep str, +} + +impl<'a> StorageRequest for SaveUser<'a> { + fn execute(&self) -> BoxFuture> { + todo!() + } +} + +trait Storage { + type Error; +} + +impl Storage for InMemoryStorage { + type Error = String; +} + +trait StorageRequestReturnType { + type Output; +} + +trait StorageRequest: StorageRequestReturnType { + fn execute( + &self, + ) -> BoxFuture::Output, ::Error>>; +} + +struct SaveUser<'a> { + name: &'a str, +} + +impl<'a> StorageRequestReturnType for SaveUser<'a> { + type Output = (); +} + +impl<'dep> User<'dep> { + async fn save(self) + where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest, + { + SaveUser { name: "Joe" } + .execute() + .await; + } +} + +async fn run(dep: &str) +where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest, + for<'a> SaveUser<'a>: StorageRequestReturnType, +{ + User { dep }.save().await; +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs new file mode 100644 index 000000000..6316ceea1 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Bar { + type Type; +} +struct Foo<'a>(&'a ()); +impl<'a> Bar for Foo<'a> { + type Type = (); +} + +fn func<'a>(_: as Bar>::Type) {} +fn assert_is_func(_: fn(A)) {} + +fn test() +where + for<'a> as Bar>::Type: Sized, +{ + assert_is_func(func); +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs new file mode 100644 index 000000000..f6ab9c203 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Indexable { + type Idx; +} +impl Indexable for u8 { + type Idx = u8; +} +impl Indexable for u16 { + type Idx = u16; +} + +pub trait Indexer: std::ops::Index {} + +trait StoreIndex: Indexer + Indexer {} + +fn foo(st: &impl StoreIndex) -> &dyn StoreIndex { + st as &dyn StoreIndex +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs new file mode 100644 index 000000000..8aa29926d --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -0,0 +1,19 @@ +#![feature(unboxed_closures)] + +trait SomeTrait<'a> { + type Associated; +} + +fn give_me_ice() { + callee:: >::Associated>(); + //~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] + //~| ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277] +} + +fn callee>() { + println!("{}", std::any::type_name::<>::Output>()); +} + +fn main() { + give_me_ice::<()>(); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr new file mode 100644 index 000000000..3240518fb --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied + --> $DIR/issue-85455.rs:8:14 + | +LL | callee:: >::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice SomeTrait<'a>>() { + | +++++++++++++++++++++++ + +error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied + --> $DIR/issue-85455.rs:8:5 + | +LL | callee:: >::Associated>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn give_me_ice SomeTrait<'a>>() { + | +++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs new file mode 100644 index 000000000..fffb54f86 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.rs @@ -0,0 +1,32 @@ +trait BufferMut {} +struct Ctx(D); + +trait BufferUdpStateContext {} +impl BufferUdpStateContext for C {} + +trait StackContext +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, +{ + type Dispatcher; +} + +trait TimerContext { + type Handler; +} +impl TimerContext for C +where + C: StackContext, + //~^ ERROR: is not satisfied [E0277] +{ + type Handler = Ctx; + //~^ ERROR: is not satisfied [E0277] +} + +struct EthernetWorker(C) +where + Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; +impl EthernetWorker {} +//~^ ERROR: is not satisfied [E0277] + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr new file mode 100644 index 000000000..62d0128fd --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr @@ -0,0 +1,69 @@ +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:19:8 + | +LL | C: StackContext, + | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:29:9 + | +LL | impl EthernetWorker {} + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `EthernetWorker` + --> $DIR/issue-89118.rs:28:14 + | +LL | struct EthernetWorker(C) + | -------------- required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` + +error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied + --> $DIR/issue-89118.rs:22:20 + | +LL | type Handler = Ctx; + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | +note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>` + --> $DIR/issue-89118.rs:5:23 + | +LL | impl BufferUdpStateContext for C {} + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `StackContext` + --> $DIR/issue-89118.rs:9:14 + | +LL | trait StackContext + | ------------ required by a bound in this +LL | where +LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs new file mode 100644 index 000000000..f7e467b37 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89436.rs @@ -0,0 +1,44 @@ +// check-pass + +#![allow(unused)] + +trait MiniYokeable<'a> { + type Output; +} + +struct MiniYoke MiniYokeable<'a>> { + pub yokeable: Y, +} + +fn map_project_broken( + source: MiniYoke, + f: impl for<'a> FnOnce( + >::Output, + core::marker::PhantomData<&'a ()>, + ) ->

>::Output, +) -> MiniYoke

+where + Y: for<'a> MiniYokeable<'a>, + P: for<'a> MiniYokeable<'a> +{ + unimplemented!() +} + +struct Bar<'a> { + string_1: &'a str, + string_2: &'a str, +} + +impl<'a> MiniYokeable<'a> for Bar<'static> { + type Output = Bar<'a>; +} + +impl<'a> MiniYokeable<'a> for &'static str { + type Output = &'a str; +} + +fn demo_broken(bar: MiniYoke>) -> MiniYoke<&'static str> { + map_project_broken(bar, |bar, _| bar.string_1) +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs new file mode 100644 index 000000000..effc32945 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90612.rs @@ -0,0 +1,41 @@ +// check-pass + +use std::marker::PhantomData; + +trait Family: Sized { + type Item<'a>; + + fn apply_all(&self, f: F) + where + F: FamilyItemFn { } +} + +struct Array(PhantomData); + +impl Family for Array { + type Item<'a> = &'a T; +} + +trait FamilyItemFn { + fn apply(&self, item: T::Item<'_>); +} + +impl FamilyItemFn for F +where + T: Family, + for<'a> F: Fn(T::Item<'a>) +{ + fn apply(&self, item: T::Item<'_>) { + (*self)(item); + } +} + +fn process(array: Array) { + // Works + array.apply_all(|x: &T| { }); + + // ICE: NoSolution + array.apply_all(|x: as Family>::Item<'_>| { }); +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs new file mode 100644 index 000000000..628b5cba1 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90638.rs @@ -0,0 +1,35 @@ +//check-pass + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + +trait IsCovariant<'a> {} + +struct Yoke Yokeable<'a>> { + data: Y, +} + +impl Yokeable<'a>> Yoke { + fn project Yokeable<'a>>(&self, _f: for<'a> fn(>::Output, &'a ()) + -> >::Output) -> Yoke { + + unimplemented!() + } +} + +fn _upcast(x: Yoke) -> Yoke + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> >::Output: IsCovariant<'a> + { + x.project(|data, _| { + Box::new(data) + }) +} + + +impl<'a> Yokeable<'a> for Box + 'static> { + type Output = Box + 'a>; +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs new file mode 100644 index 000000000..ffd6857d8 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs @@ -0,0 +1,31 @@ +// check-pass + +trait Variable<'a> { + type Type; +} + +impl Variable<'_> for () { + type Type = (); +} + +fn check(_: F) +where + F: Fn(T), // <- if removed, all fn_* then require type annotations + F: for<'a> Fn(>::Type), + T: for<'a> Variable<'a>, +{ +} + +fn test(arg: impl Fn(())) { + fn fn_1(_: ()) {} + let fn_2 = |_: ()| (); + let fn_3 = |a| fn_1(a); + let fn_4 = arg; + + check(fn_1); // Error + check(fn_2); // Ok + check(fn_3); // Ok + check(fn_4); // Error +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs new file mode 100644 index 000000000..ab9d9a7ce --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.rs @@ -0,0 +1,53 @@ +// check-fail +// known-bug: #90950 + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + + +trait IsCovariant<'a> {} + +struct Yoke Yokeable<'a>> { + data: Y, +} + + +// impl Yokeable<'a>> Yoke { +// fn project Yokeable<'a>>( +// &self, +// f: for<'a> fn(>::Output, &'a (), +// ) -> >::Output) -> Yoke { +// unimplemented!() +// } +// } + +fn upcast(x: Yoke) -> Yoke + 'static>> where + Y: for<'a> Yokeable<'a>, + for<'a> >::Output: IsCovariant<'a> + { + // x.project(|data, _| { + // Box::new(data) + // }) + unimplemented!() +} + + +impl<'a> Yokeable<'a> for Box + 'static> { + type Output = Box + 'a>; +} + +// this impl is mostly an example and unnecessary for the pure repro +use std::borrow::*; +impl<'a, T: ToOwned + ?Sized> Yokeable<'a> for Cow<'static, T> { + type Output = Cow<'a, T>; +} +impl<'a, T: ToOwned + ?Sized> IsCovariant<'a> for Cow<'a, T> {} + + + +fn upcast_yoke(y: Yoke>) -> Yoke + 'static>> { + upcast(y) +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr new file mode 100644 index 000000000..6206b167b --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `for<'a> <_ as Yokeable<'a>>::Output: IsCovariant<'a>` is not satisfied + --> $DIR/issue-90950.rs:50:12 + | +LL | upcast(y) + | ------ ^ the trait `for<'a> IsCovariant<'a>` is not implemented for `<_ as Yokeable<'a>>::Output` + | | + | required by a bound introduced by this call + | + = help: the trait `IsCovariant<'a>` is implemented for `std::borrow::Cow<'a, T>` +note: required by a bound in `upcast` + --> $DIR/issue-90950.rs:27:42 + | +LL | fn upcast(x: Yoke) -> Yoke + 'static>> where + | ------ required by a bound in this +LL | Y: for<'a> Yokeable<'a>, +LL | for<'a> >::Output: IsCovariant<'a> + | ^^^^^^^^^^^^^^^ required by this bound in `upcast` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs new file mode 100644 index 000000000..7693b1182 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.rs @@ -0,0 +1,23 @@ +// check-fail +// known-bug: #89196 + +// Should pass, but we normalize and check bounds before we resolve the generics +// of the function (which we know because of the return type). + +trait Trait<'a> { + type Out; +} + +impl<'a, T> Trait<'a> for T { + type Out = T; +} + +fn weird_bound() -> X + where + for<'a> X: Trait<'a>, + for<'a> >::Out: Copy +{ todo!() } + +fn main() { + let _: () = weird_bound(); +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr new file mode 100644 index 000000000..51c964600 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'a> <_ as Trait<'a>>::Out: Copy` is not satisfied + --> $DIR/norm-before-method-resolution.rs:22:17 + | +LL | let _: () = weird_bound(); + | ^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out` + | +note: required by a bound in `weird_bound` + --> $DIR/norm-before-method-resolution.rs:18:40 + | +LL | fn weird_bound() -> X + | ----------- required by a bound in this +... +LL | for<'a> >::Out: Copy + | ^^^^ required by this bound in `weird_bound` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr new file mode 100644 index 000000000..b7264c7e9 --- /dev/null +++ b/tests/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:54:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +... +LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, +LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + | |_____________________________________________- in this macro invocation + | + = note: expected enum `Option fn(&'a u32, &'b u32) -> &'a u32>` + found enum `Option fn(&'a u32, &'a u32) -> &'a u32>` + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr new file mode 100644 index 000000000..2355979b0 --- /dev/null +++ b/tests/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:54:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +... +LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), +LL | | fn(&'x u32)) } + | |______________- in this macro invocation + | + = note: expected enum `Option fn(&'a u32)>` + found enum `Option` + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr new file mode 100644 index 000000000..a73c03feb --- /dev/null +++ b/tests/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:54:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` + found enum `Option fn(Inv<'a>, Inv<'a>)>` + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/hr-subtype.rs:54:13 + | +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other +... +LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } + | |__________________________________- in this macro invocation + | + = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` + found enum `Option fn(Inv<'a>, Inv<'a>)>` + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr new file mode 100644 index 000000000..31d36d716 --- /dev/null +++ b/tests/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -0,0 +1,42 @@ +error: lifetime may not live long enough + --> $DIR/hr-subtype.rs:48:13 + | +LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here + | | + | lifetime `'x` defined here +LL | gimme::<$t2>(None::<$t1>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` +... +LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation + | + = help: consider adding the following bound: `'x: 'y` + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/hr-subtype.rs:54:13 + | +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here + | | + | lifetime `'x` defined here +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` +... +LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), +LL | | fn(Inv<'y>)) } + | |______________- in this macro invocation + | + = help: consider adding the following bound: `'x: 'y` + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr new file mode 100644 index 000000000..269cde54c --- /dev/null +++ b/tests/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -0,0 +1,19 @@ +error: lifetime may not live long enough + --> $DIR/hr-subtype.rs:54:13 + | +LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { + | -- -- lifetime `'y` defined here + | | + | lifetime `'x` defined here +LL | gimme::<$t1>(None::<$t2>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y` +... +LL | / check! { free_x_vs_free_y: (fn(&'x u32), +LL | | fn(&'y u32)) } + | |______________- in this macro invocation + | + = help: consider adding the following bound: `'x: 'y` + = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/hr-subtype/hr-subtype.rs b/tests/ui/hr-subtype/hr-subtype.rs new file mode 100644 index 000000000..c770e0de8 --- /dev/null +++ b/tests/ui/hr-subtype/hr-subtype.rs @@ -0,0 +1,111 @@ +// Targeted tests for the higher-ranked subtyping code. + +#![allow(dead_code)] + +// revisions: bound_a_vs_bound_a +// revisions: bound_a_vs_bound_b +// revisions: bound_inv_a_vs_bound_inv_b +// revisions: bound_co_a_vs_bound_co_b +// revisions: bound_a_vs_free_x +// revisions: free_x_vs_free_x +// revisions: free_x_vs_free_y +// revisions: free_inv_x_vs_free_inv_y +// revisions: bound_a_b_vs_bound_a +// revisions: bound_co_a_b_vs_bound_co_a +// revisions: bound_contra_a_contra_b_ret_co_a +// revisions: bound_co_a_co_b_ret_contra_a +// revisions: bound_inv_a_b_vs_bound_inv_a +// revisions: bound_a_b_ret_a_vs_bound_a_ret_a + +//[bound_a_vs_bound_a] check-pass +//[bound_a_vs_bound_b] check-pass +//[bound_inv_a_vs_bound_inv_b] check-pass +//[bound_co_a_vs_bound_co_b] check-pass +//[free_x_vs_free_x] check-pass +//[bound_co_a_b_vs_bound_co_a] check-pass +//[bound_co_a_co_b_ret_contra_a] check-pass +//[bound_a_b_vs_bound_a] check-pass +//[bound_contra_a_contra_b_ret_co_a] check-pass + +fn gimme(_: Option) {} + +struct Inv<'a> { + x: *mut &'a u32, +} + +struct Co<'a> { + x: fn(&'a u32), +} + +struct Contra<'a> { + x: &'a u32, +} + +macro_rules! check { + ($rev:ident: ($t1:ty, $t2:ty)) => { + #[cfg($rev)] + fn subtype<'x, 'y: 'x, 'z: 'y>() { + gimme::<$t2>(None::<$t1>); + //[free_inv_x_vs_free_inv_y]~^ ERROR + } + + #[cfg($rev)] + fn supertype<'x, 'y: 'x, 'z: 'y>() { + gimme::<$t1>(None::<$t2>); + //[bound_a_vs_free_x]~^ ERROR + //[free_x_vs_free_y]~^^ ERROR + //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR + //[bound_inv_a_b_vs_bound_inv_a]~| ERROR + //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^^ ERROR + //[free_inv_x_vs_free_inv_y]~^^^^^^ ERROR + } + }; +} + +// If both have bound regions, they are equivalent, regardless of +// variant. +check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32), +for<'a> fn(&'a u32)) } +check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32), +for<'b> fn(&'b u32)) } +check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>), +for<'b> fn(Inv<'b>)) } +check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>), +for<'b> fn(Co<'b>)) } + +// Bound is a subtype of free. +check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), +fn(&'x u32)) } + +// Two free regions are relatable if subtyping holds. +check! { free_x_vs_free_x: (fn(&'x u32), +fn(&'x u32)) } +check! { free_x_vs_free_y: (fn(&'x u32), +fn(&'y u32)) } +check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), +fn(Inv<'y>)) } + +// Somewhat surprisingly, a fn taking two distinct bound lifetimes and +// a fn taking one bound lifetime can be interchangeable, but only if +// we are co- or contra-variant with respect to both lifetimes. +// +// The reason is: +// - if we are covariant, then 'a and 'b can be set to the call-site +// intersection; +// - if we are contravariant, then 'a can be inferred to 'static. +check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32), +for<'a> fn(&'a u32, &'a u32)) } +check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>), +for<'a> fn(Co<'a>, Co<'a>)) } +check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>, +for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) } +check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>, +for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) } + +// If we make those lifetimes invariant, then the two types are not interchangeable. +check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>), +for<'a> fn(Inv<'a>, Inv<'a>)) } +check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32, +for<'a> fn(&'a u32, &'a u32) -> &'a u32) } + +fn main() {} diff --git a/tests/ui/hr-subtype/placeholder-pattern-fail.rs b/tests/ui/hr-subtype/placeholder-pattern-fail.rs new file mode 100644 index 000000000..bd4533e04 --- /dev/null +++ b/tests/ui/hr-subtype/placeholder-pattern-fail.rs @@ -0,0 +1,25 @@ +// Check that incorrect higher ranked subtyping +// causes an error. +struct Inv<'a>(fn(&'a ()) -> &'a ()); +fn hr_subtype<'c>(f: for<'a, 'b> fn(Inv<'a>, Inv<'a>)) { + // ok + let _: for<'a> fn(Inv<'a>, Inv<'a>) = f; + let sub: for<'a> fn(Inv<'a>, Inv<'a>) = f; + // no + let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; + //~^ ERROR mismatched types +} + +fn simple1<'c>(x: (&'c i32,)) { + let _x: (&'static i32,) = x; +} + +fn simple2<'c>(x: (&'c i32,)) { + let _: (&'static i32,) = x; +} + +fn main() { + hr_subtype(|_, _| {}); + simple1((&3,)); + simple2((&3,)); +} diff --git a/tests/ui/hr-subtype/placeholder-pattern-fail.stderr b/tests/ui/hr-subtype/placeholder-pattern-fail.stderr new file mode 100644 index 000000000..73b0a3173 --- /dev/null +++ b/tests/ui/hr-subtype/placeholder-pattern-fail.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/placeholder-pattern-fail.rs:9:47 + | +LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; + | ^^^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)` + found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/hr-subtype/placeholder-pattern.rs b/tests/ui/hr-subtype/placeholder-pattern.rs new file mode 100644 index 000000000..061e66e54 --- /dev/null +++ b/tests/ui/hr-subtype/placeholder-pattern.rs @@ -0,0 +1,18 @@ +// check-pass +// Check that higher ranked subtyping correctly works when using +// placeholder patterns. +fn hr_subtype<'c>(f: for<'a, 'b> fn(&'a (), &'b ())) { + let _: for<'a> fn(&'a (), &'a ()) = f; + let _: for<'a, 'b> fn(&'a (), &'b ()) = f; + let _: for<'a> fn(&'a (), &'c ()) = f; + let _: fn(&'c (), &'c ()) = f; +} + +fn simple<'c>(x: (&'static i32,)) { + let _: (&'c i32,) = x; +} + +fn main() { + hr_subtype(|_, _| {}); + simple((&3,)); +} diff --git a/tests/ui/hr-subtype/return-static.rs b/tests/ui/hr-subtype/return-static.rs new file mode 100644 index 000000000..6455854f3 --- /dev/null +++ b/tests/ui/hr-subtype/return-static.rs @@ -0,0 +1,13 @@ +// check-pass + +fn make() -> T { + panic!() +} + +fn take(x: T) {} + +fn main() { + let x: for<'a> fn(&'a u32) -> _ = make(); + let y: &'static u32 = x(&22); + take:: fn(&'b u32) -> &'b u32>(x); +} diff --git a/tests/ui/hygiene/arguments.rs b/tests/ui/hygiene/arguments.rs new file mode 100644 index 000000000..f0f732f4c --- /dev/null +++ b/tests/ui/hygiene/arguments.rs @@ -0,0 +1,17 @@ +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +macro m($t:ty, $e:expr) { + mod foo { + #[allow(unused)] + struct S; + pub(super) fn f(_: $t) {} + } + foo::f($e); +} + +fn main() { + struct S; + m!(S, S); //~ ERROR cannot find type `S` in this scope +} diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr new file mode 100644 index 000000000..d072086e0 --- /dev/null +++ b/tests/ui/hygiene/arguments.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `S` in this scope + --> $DIR/arguments.rs:16:8 + | +LL | m!(S, S); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/hygiene/assoc_item_ctxt.rs b/tests/ui/hygiene/assoc_item_ctxt.rs new file mode 100644 index 000000000..65593d1d5 --- /dev/null +++ b/tests/ui/hygiene/assoc_item_ctxt.rs @@ -0,0 +1,42 @@ +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] +#![allow(unused)] + +mod ok { + macro mac_trait_item($method: ident) { + fn $method(); + } + + trait Tr { + mac_trait_item!(method); + } + + macro mac_trait_impl() { + impl Tr for u8 { // OK + fn method() {} // OK + } + } + + mac_trait_impl!(); +} + +mod error { + macro mac_trait_item() { + fn method(); + } + + trait Tr { + mac_trait_item!(); + } + + macro mac_trait_impl() { + impl Tr for u8 { //~ ERROR not all trait items implemented, missing: `method` + fn method() {} //~ ERROR method `method` is not a member of trait `Tr` + } + } + + mac_trait_impl!(); +} + +fn main() {} diff --git a/tests/ui/hygiene/assoc_item_ctxt.stderr b/tests/ui/hygiene/assoc_item_ctxt.stderr new file mode 100644 index 000000000..d65716ec2 --- /dev/null +++ b/tests/ui/hygiene/assoc_item_ctxt.stderr @@ -0,0 +1,32 @@ +error[E0407]: method `method` is not a member of trait `Tr` + --> $DIR/assoc_item_ctxt.rs:35:13 + | +LL | fn method() {} + | ^^^------^^^^^ + | | | + | | help: there is an associated function with a similar name: `method` + | not a member of trait `Tr` +... +LL | mac_trait_impl!(); + | ----------------- in this macro invocation + | + = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0046]: not all trait items implemented, missing: `method` + --> $DIR/assoc_item_ctxt.rs:34:9 + | +LL | fn method(); + | ------------ `method` from trait +... +LL | impl Tr for u8 { + | ^^^^^^^^^^^^^^ missing `method` in implementation +... +LL | mac_trait_impl!(); + | ----------------- in this macro invocation + | + = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0046, E0407. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/hygiene/assoc_ty_bindings.rs b/tests/ui/hygiene/assoc_ty_bindings.rs new file mode 100644 index 000000000..0567beab9 --- /dev/null +++ b/tests/ui/hygiene/assoc_ty_bindings.rs @@ -0,0 +1,38 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro, associated_type_defaults)] + +trait Base { + type AssocTy; + fn f(); +} +trait Derived: Base { + fn g(); +} + +macro mac() { + type A = dyn Base; + type B = dyn Derived; + + impl Base for u8 { + type AssocTy = u8; + fn f() { + let _: Self::AssocTy; + } + } + impl Derived for u8 { + fn g() { + let _: Self::AssocTy; + } + } + + fn h() { + let _: T::AssocTy; + let _: U::AssocTy; + } +} + +mac!(); + +fn main() {} diff --git a/tests/ui/hygiene/auxiliary/codegen-attrs.rs b/tests/ui/hygiene/auxiliary/codegen-attrs.rs new file mode 100644 index 000000000..74afedbeb --- /dev/null +++ b/tests/ui/hygiene/auxiliary/codegen-attrs.rs @@ -0,0 +1,10 @@ +#![feature(decl_macro)] + +macro m($f:ident) { + #[export_name = "export_function_name"] + pub fn $f() -> i32 { + 2 + } +} + +m!(rust_function_name); diff --git a/tests/ui/hygiene/auxiliary/def-site-async-await.rs b/tests/ui/hygiene/auxiliary/def-site-async-await.rs new file mode 100644 index 000000000..f7e9b8013 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/def-site-async-await.rs @@ -0,0 +1,7 @@ +// edition:2018 + +extern crate opaque_hygiene; + +pub async fn serve() { + opaque_hygiene::make_it!(); +} diff --git a/tests/ui/hygiene/auxiliary/fields.rs b/tests/ui/hygiene/auxiliary/fields.rs new file mode 100644 index 000000000..733d11a9e --- /dev/null +++ b/tests/ui/hygiene/auxiliary/fields.rs @@ -0,0 +1,73 @@ +#![feature(decl_macro)] + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Field { + RootCtxt, + MacroCtxt, +} + +#[rustfmt::skip] +macro x( + $macro_name:ident, + $macro2_name:ident, + $type_name:ident, + $field_name:ident, + $const_name:ident +) { + #[derive(Copy, Clone)] + pub struct $type_name { + pub field: Field, + pub $field_name: Field, + } + + pub const $const_name: $type_name = + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt }; + + #[macro_export] + macro_rules! $macro_name { + (check_fields_of $e:expr) => {{ + let e = $e; + assert_eq!(e.field, Field::MacroCtxt); + assert_eq!(e.$field_name, Field::RootCtxt); + }}; + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + assert_eq!($const_name.$field_name, Field::RootCtxt); + }}; + (construct) => { + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt } + }; + } + + pub macro $macro2_name { + (check_fields_of $e:expr) => {{ + let e = $e; + assert_eq!(e.field, Field::MacroCtxt); + assert_eq!(e.$field_name, Field::RootCtxt); + }}, + (check_fields) => {{ + assert_eq!($const_name.field, Field::MacroCtxt); + assert_eq!($const_name.$field_name, Field::RootCtxt); + }}, + (construct) => { + $type_name { field: Field::MacroCtxt, $field_name: Field::RootCtxt } + } + } +} + +x!(test_fields, test_fields2, MyStruct, field, MY_CONST); + +pub fn check_fields(s: MyStruct) { + test_fields!(check_fields_of s); +} + +pub fn check_fields_local() { + test_fields!(check_fields); + test_fields2!(check_fields); + + let s1 = test_fields!(construct); + test_fields!(check_fields_of s1); + + let s2 = test_fields2!(construct); + test_fields2!(check_fields_of s2); +} diff --git a/tests/ui/hygiene/auxiliary/intercrate.rs b/tests/ui/hygiene/auxiliary/intercrate.rs new file mode 100644 index 000000000..068535885 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/intercrate.rs @@ -0,0 +1,46 @@ +#![feature(decl_macro)] + +pub mod foo { + pub use self::bar::m; + mod bar { + fn f() -> u32 { 1 } + pub macro m() { + f() + } + } +} + +pub struct SomeType; + +// `$crate` +pub macro uses_dollar_crate_modern() { + type Alias = $crate::SomeType; +} + +pub macro define_uses_dollar_crate_modern_nested($uses_dollar_crate_modern_nested: ident) { + macro $uses_dollar_crate_modern_nested() { + type AliasCrateModernNested = $crate::SomeType; + } +} + +#[macro_export] +macro_rules! define_uses_dollar_crate_legacy_nested { + () => { + macro_rules! uses_dollar_crate_legacy_nested { + () => { + type AliasLegacyNested = $crate::SomeType; + } + } + } +} + +// `crate` +pub macro uses_crate_modern() { + type AliasCrate = crate::SomeType; +} + +pub macro define_uses_crate_modern_nested($uses_crate_modern_nested: ident) { + macro $uses_crate_modern_nested() { + type AliasCrateModernNested = crate::SomeType; + } +} diff --git a/tests/ui/hygiene/auxiliary/legacy_interaction.rs b/tests/ui/hygiene/auxiliary/legacy_interaction.rs new file mode 100644 index 000000000..90d5243b7 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/legacy_interaction.rs @@ -0,0 +1,9 @@ +// ignore-pretty pretty-printing is unhygienic + +#[macro_export] +macro_rules! m { + () => { + fn f() {} // (2) + g(); // (1) + } +} diff --git a/tests/ui/hygiene/auxiliary/local_inner_macros.rs b/tests/ui/hygiene/auxiliary/local_inner_macros.rs new file mode 100644 index 000000000..4296ae2fd --- /dev/null +++ b/tests/ui/hygiene/auxiliary/local_inner_macros.rs @@ -0,0 +1,19 @@ +#[macro_export] +macro_rules! helper1 { + () => ( struct S; ) +} + +#[macro_export(local_inner_macros)] +macro_rules! helper2 { + () => ( helper1!(); ) +} + +#[macro_export(local_inner_macros)] +macro_rules! public_macro { + () => ( helper2!(); ) +} + +#[macro_export(local_inner_macros)] +macro_rules! public_macro_dynamic { + ($helper: ident) => ( $helper!(); ) +} diff --git a/tests/ui/hygiene/auxiliary/methods.rs b/tests/ui/hygiene/auxiliary/methods.rs new file mode 100644 index 000000000..23b9c61cf --- /dev/null +++ b/tests/ui/hygiene/auxiliary/methods.rs @@ -0,0 +1,160 @@ +#![feature(decl_macro)] + +#[derive(PartialEq, Eq, Debug)] +pub enum Method { + DefaultMacroCtxt, + DefaultRootCtxt, + OverrideMacroCtxt, + OverrideRootCtxt, +} + +#[rustfmt::skip] +macro x($macro_name:ident, $macro2_name:ident, $trait_name:ident, $method_name:ident) { + pub trait $trait_name { + fn method(&self) -> Method { + Method::DefaultMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::DefaultRootCtxt + } + } + + impl $trait_name for () {} + impl $trait_name for bool { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + + #[macro_export] + macro_rules! $macro_name { + (check_resolutions) => { + assert_eq!(().method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); + assert_eq!(().$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); + + assert_eq!(false.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); + assert_eq!(false.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); + + assert_eq!('a'.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); + assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); + + assert_eq!(1i32.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); + assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); + + assert_eq!(1i64.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); + assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); + }; + (assert_no_override $v:expr) => { + assert_eq!($v.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); + assert_eq!($v.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); + }; + (assert_override $v:expr) => { + assert_eq!($v.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); + assert_eq!($v.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); + }; + (impl for $t:ty) => { + impl $trait_name for $t { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + }; + } + + pub macro $macro2_name { + (check_resolutions) => { + assert_eq!(().method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); + assert_eq!(().$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); + + assert_eq!(false.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); + assert_eq!(false.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); + + assert_eq!('a'.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); + assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); + + assert_eq!(1i32.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); + assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); + + assert_eq!(1i64.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); + assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); + }, + (assert_no_override $v:expr) => { + assert_eq!($v.method(), Method::DefaultMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); + assert_eq!($v.$method_name(), Method::DefaultRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); + }, + (assert_override $v:expr) => { + assert_eq!($v.method(), Method::OverrideMacroCtxt); + assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); + assert_eq!($v.$method_name(), Method::OverrideRootCtxt); + assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); + }, + (impl for $t:ty) => { + impl $trait_name for $t { + fn method(&self) -> Method { + Method::OverrideMacroCtxt + } + + fn $method_name(&self) -> Method { + Method::OverrideRootCtxt + } + } + } + } +} + +x!(test_trait, test_trait2, MyTrait, method); + +impl MyTrait for char {} +test_trait!(impl for i32); +test_trait2!(impl for i64); + +pub fn check_crate_local() { + test_trait!(check_resolutions); + test_trait2!(check_resolutions); +} + +// Check that any comparison of idents at monomorphization time is correct +pub fn check_crate_local_generic(t: T, u: U) { + test_trait!(check_resolutions); + test_trait2!(check_resolutions); + + test_trait!(assert_no_override t); + test_trait2!(assert_no_override t); + test_trait!(assert_override u); + test_trait2!(assert_override u); +} diff --git a/tests/ui/hygiene/auxiliary/my_crate.rs b/tests/ui/hygiene/auxiliary/my_crate.rs new file mode 100644 index 000000000..cdc6c27d8 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/my_crate.rs @@ -0,0 +1 @@ +pub fn f() {} diff --git a/tests/ui/hygiene/auxiliary/needs_hygiene.rs b/tests/ui/hygiene/auxiliary/needs_hygiene.rs new file mode 100644 index 000000000..3df6450fd --- /dev/null +++ b/tests/ui/hygiene/auxiliary/needs_hygiene.rs @@ -0,0 +1,5 @@ +#![feature(decl_macro)] +macro x() { struct MyStruct; } + +x!(); +x!(); diff --git a/tests/ui/hygiene/auxiliary/nested-dollar-crate.rs b/tests/ui/hygiene/auxiliary/nested-dollar-crate.rs new file mode 100644 index 000000000..e5caa0f9c --- /dev/null +++ b/tests/ui/hygiene/auxiliary/nested-dollar-crate.rs @@ -0,0 +1,14 @@ +pub const IN_DEF_CRATE: &str = "In def crate!"; + +macro_rules! make_it { + () => { + #[macro_export] + macro_rules! inner { + () => { + $crate::IN_DEF_CRATE + } + } + } +} + +make_it!(); diff --git a/tests/ui/hygiene/auxiliary/not-libstd.rs b/tests/ui/hygiene/auxiliary/not-libstd.rs new file mode 100644 index 000000000..babba293d --- /dev/null +++ b/tests/ui/hygiene/auxiliary/not-libstd.rs @@ -0,0 +1 @@ +pub fn not_in_lib_std() {} diff --git a/tests/ui/hygiene/auxiliary/opaque-hygiene.rs b/tests/ui/hygiene/auxiliary/opaque-hygiene.rs new file mode 100644 index 000000000..7730f91bd --- /dev/null +++ b/tests/ui/hygiene/auxiliary/opaque-hygiene.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, quote}; + +#[proc_macro] +pub fn make_it(input: TokenStream) -> TokenStream { + // `quote!` applies def-site hygiene + quote! { + trait Foo { + fn my_fn(&self) {} + } + + impl Foo for T {} + "a".my_fn(); + } +} diff --git a/tests/ui/hygiene/auxiliary/pub_hygiene.rs b/tests/ui/hygiene/auxiliary/pub_hygiene.rs new file mode 100644 index 000000000..47e76a629 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/pub_hygiene.rs @@ -0,0 +1,7 @@ +#![feature(decl_macro)] + +macro x() { + pub struct MyStruct; +} + +x!(); diff --git a/tests/ui/hygiene/auxiliary/stdlib-prelude.rs b/tests/ui/hygiene/auxiliary/stdlib-prelude.rs new file mode 100644 index 000000000..81b0b7faa --- /dev/null +++ b/tests/ui/hygiene/auxiliary/stdlib-prelude.rs @@ -0,0 +1,3 @@ +#![feature(decl_macro)] + +pub macro stdlib_macro() {} diff --git a/tests/ui/hygiene/auxiliary/transparent-basic.rs b/tests/ui/hygiene/auxiliary/transparent-basic.rs new file mode 100644 index 000000000..37de27ee8 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/transparent-basic.rs @@ -0,0 +1,6 @@ +#![feature(decl_macro, rustc_attrs)] + +#[rustc_macro_transparency = "transparent"] +pub macro dollar_crate() { + let s = $crate::S; +} diff --git a/tests/ui/hygiene/auxiliary/unhygienic_example.rs b/tests/ui/hygiene/auxiliary/unhygienic_example.rs new file mode 100644 index 000000000..8e6e8f9b3 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/unhygienic_example.rs @@ -0,0 +1,27 @@ +#![crate_type = "lib"] + +extern crate my_crate; + +pub fn g() {} // (a) + +#[macro_export] +macro_rules! unhygienic_macro { + () => { + // (1) unhygienic: depends on `my_crate` in the crate root at the invocation site. + ::my_crate::f(); + + // (2) unhygienic: defines `f` at the invocation site (in addition to the above point). + use my_crate::f; + f(); + + g(); // (3) unhygienic: `g` needs to be in scope at use site. + + $crate::g(); // (4) hygienic: this always resolves to (a) + } +} + +#[allow(unused)] +fn test_unhygienic() { + unhygienic_macro!(); + f(); // `f` was defined at the use site +} diff --git a/tests/ui/hygiene/auxiliary/use_by_macro.rs b/tests/ui/hygiene/auxiliary/use_by_macro.rs new file mode 100644 index 000000000..791cf0358 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/use_by_macro.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] + +macro x($macro_name:ident) { + #[macro_export] + macro_rules! $macro_name { + (define) => { + pub struct MyStruct; + }; + (create) => { + MyStruct {} + }; + } +} + +x!(my_struct); diff --git a/tests/ui/hygiene/auxiliary/variants.rs b/tests/ui/hygiene/auxiliary/variants.rs new file mode 100644 index 000000000..dbfcce17d --- /dev/null +++ b/tests/ui/hygiene/auxiliary/variants.rs @@ -0,0 +1,36 @@ +#![feature(decl_macro)] + +#[rustfmt::skip] +macro x($macro_name:ident, $macro2_name:ident, $type_name:ident, $variant_name:ident) { + #[repr(u8)] + pub enum $type_name { + Variant = 0, + $variant_name = 1, + } + + #[macro_export] + macro_rules! $macro_name { + () => {{ + assert_eq!($type_name::Variant as u8, 0); + assert_eq!($type_name::$variant_name as u8, 1); + assert_eq!(<$type_name>::Variant as u8, 0); + assert_eq!(<$type_name>::$variant_name as u8, 1); + }}; + } + + pub macro $macro2_name { + () => {{ + assert_eq!($type_name::Variant as u8, 0); + assert_eq!($type_name::$variant_name as u8, 1); + assert_eq!(<$type_name>::Variant as u8, 0); + assert_eq!(<$type_name>::$variant_name as u8, 1); + }}, + } +} + +x!(test_variants, test_variants2, MyEnum, Variant); + +pub fn check_variants() { + test_variants!(); + test_variants2!(); +} diff --git a/tests/ui/hygiene/auxiliary/xcrate.rs b/tests/ui/hygiene/auxiliary/xcrate.rs new file mode 100644 index 000000000..f5a911f57 --- /dev/null +++ b/tests/ui/hygiene/auxiliary/xcrate.rs @@ -0,0 +1,28 @@ +#![feature(decl_macro)] +#![allow(unused)] + +pub use bar::test; + +extern crate std as foo; + +pub fn f() {} +use f as f2; + +mod bar { + pub fn g() {} + use baz::h; + + pub macro test() { + use std::mem; + use foo::cell; + ::f(); + ::f2(); + g(); + h(); + ::bar::h(); + } +} + +mod baz { + pub fn h() {} +} diff --git a/tests/ui/hygiene/cross-crate-codegen-attrs.rs b/tests/ui/hygiene/cross-crate-codegen-attrs.rs new file mode 100644 index 000000000..af6b13343 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-codegen-attrs.rs @@ -0,0 +1,12 @@ +// Make sure that macro expanded codegen attributes work across crates. +// We used to gensym the identifiers in attributes, which stopped dependent +// crates from seeing them, resulting in linker errors in cases like this one. + +// run-pass +// aux-build:codegen-attrs.rs + +extern crate codegen_attrs; + +fn main() { + assert_eq!(codegen_attrs::rust_function_name(), 2); +} diff --git a/tests/ui/hygiene/cross-crate-define-and-use.rs b/tests/ui/hygiene/cross-crate-define-and-use.rs new file mode 100644 index 000000000..94f1adff6 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-define-and-use.rs @@ -0,0 +1,19 @@ +// Check that a marco from another crate can define an item in one expansion +// and use it from another, without it being visible to everyone. +// This requires that the definition of `my_struct` preserves the hygiene +// information for the tokens in its definition. + +// check-pass +// aux-build:use_by_macro.rs + +#![feature(type_name_of_val)] +extern crate use_by_macro; + +use use_by_macro::*; + +enum MyStruct {} +my_struct!(define); + +fn main() { + let x = my_struct!(create); +} diff --git a/tests/ui/hygiene/cross-crate-fields.rs b/tests/ui/hygiene/cross-crate-fields.rs new file mode 100644 index 000000000..1bcd64573 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-fields.rs @@ -0,0 +1,24 @@ +// Test that fields on a struct defined in another crate are resolved correctly +// their names differ only in `SyntaxContext`. + +// run-pass +// aux-build:fields.rs + +extern crate fields; + +use fields::*; + +fn main() { + check_fields_local(); + + test_fields!(check_fields); + test_fields2!(check_fields); + + let s1 = test_fields!(construct); + check_fields(s1); + test_fields!(check_fields_of s1); + + let s2 = test_fields2!(construct); + check_fields(s2); + test_fields2!(check_fields_of s2); +} diff --git a/tests/ui/hygiene/cross-crate-glob-hygiene.rs b/tests/ui/hygiene/cross-crate-glob-hygiene.rs new file mode 100644 index 000000000..de5576682 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-glob-hygiene.rs @@ -0,0 +1,23 @@ +// Check that globs cannot import hygienic identifiers from a macro expansion +// in another crate. `my_struct` is a `macro_rules` macro, so the struct it +// defines is only not imported because `my_struct` is defined by a macros 2.0 +// macro. + +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +mod m { + use use_by_macro::*; + + my_struct!(define); +} + +use m::*; + +fn main() { + let x = my_struct!(create); + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/tests/ui/hygiene/cross-crate-glob-hygiene.stderr b/tests/ui/hygiene/cross-crate-glob-hygiene.stderr new file mode 100644 index 000000000..7369e77d0 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-glob-hygiene.stderr @@ -0,0 +1,11 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-glob-hygiene.rs:21:13 + | +LL | let x = my_struct!(create); + | ^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/hygiene/cross-crate-methods.rs b/tests/ui/hygiene/cross-crate-methods.rs new file mode 100644 index 000000000..0e6f57c33 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-methods.rs @@ -0,0 +1,33 @@ +// Test that methods defined in another crate are resolved correctly their +// names differ only in `SyntaxContext`. This also checks that any name +// resolution done when monomorphizing is correct. + +// run-pass +// aux-build:methods.rs + +extern crate methods; + +use methods::*; + +struct A; +struct B; +struct C; + +impl MyTrait for A {} +test_trait!(impl for B); +test_trait2!(impl for C); + +fn main() { + check_crate_local(); + check_crate_local_generic(A, B); + check_crate_local_generic(A, C); + + test_trait!(check_resolutions); + test_trait2!(check_resolutions); + test_trait!(assert_no_override A); + test_trait2!(assert_no_override A); + test_trait!(assert_override B); + test_trait2!(assert_override B); + test_trait!(assert_override C); + test_trait2!(assert_override C); +} diff --git a/tests/ui/hygiene/cross-crate-name-collision.rs b/tests/ui/hygiene/cross-crate-name-collision.rs new file mode 100644 index 000000000..8f118782f --- /dev/null +++ b/tests/ui/hygiene/cross-crate-name-collision.rs @@ -0,0 +1,12 @@ +// Check that two items defined in another crate that have identifiers that +// only differ by `SyntaxContext` do not cause name collisions when imported +// in another crate. + +// check-pass +// aux-build:needs_hygiene.rs + +extern crate needs_hygiene; + +use needs_hygiene::*; + +fn main() {} diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.rs b/tests/ui/hygiene/cross-crate-name-hiding-2.rs new file mode 100644 index 000000000..3eacd775c --- /dev/null +++ b/tests/ui/hygiene/cross-crate-name-hiding-2.rs @@ -0,0 +1,15 @@ +// Check that an identifier from a 2.0 macro in another crate cannot be +// resolved with an identifier that's not from a macro expansion. + +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +my_struct!(define); + +fn main() { + let x = MyStruct {}; + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr new file mode 100644 index 000000000..46314cdd5 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-name-hiding-2.rs:13:13 + | +LL | let x = MyStruct {}; + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/hygiene/cross-crate-name-hiding.rs b/tests/ui/hygiene/cross-crate-name-hiding.rs new file mode 100644 index 000000000..dd76ecc57 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-name-hiding.rs @@ -0,0 +1,13 @@ +// Check that an item defined by a 2.0 macro in another crate cannot be used in +// another crate. + +// aux-build:pub_hygiene.rs + +extern crate pub_hygiene; + +use pub_hygiene::*; + +fn main() { + let x = MyStruct {}; + //~^ ERROR cannot find struct, variant or union type `MyStruct` in this scope +} diff --git a/tests/ui/hygiene/cross-crate-name-hiding.stderr b/tests/ui/hygiene/cross-crate-name-hiding.stderr new file mode 100644 index 000000000..f8840c8f8 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-name-hiding.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope + --> $DIR/cross-crate-name-hiding.rs:11:13 + | +LL | let x = MyStruct {}; + | ^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/hygiene/cross-crate-redefine.rs b/tests/ui/hygiene/cross-crate-redefine.rs new file mode 100644 index 000000000..3cb06b4ba --- /dev/null +++ b/tests/ui/hygiene/cross-crate-redefine.rs @@ -0,0 +1,14 @@ +// Check that items with identical `SyntaxContext` conflict even when that +// context involves a mark from another crate. + +// aux-build:use_by_macro.rs + +extern crate use_by_macro; + +use use_by_macro::*; + +my_struct!(define); +//~^ ERROR the name `MyStruct` is defined multiple times +my_struct!(define); + +fn main() {} diff --git a/tests/ui/hygiene/cross-crate-redefine.stderr b/tests/ui/hygiene/cross-crate-redefine.stderr new file mode 100644 index 000000000..4f1419de4 --- /dev/null +++ b/tests/ui/hygiene/cross-crate-redefine.stderr @@ -0,0 +1,15 @@ +error[E0428]: the name `MyStruct` is defined multiple times + --> $DIR/cross-crate-redefine.rs:10:1 + | +LL | my_struct!(define); + | ^^^^^^^^^^^^^^^^^^ `MyStruct` redefined here +LL | +LL | my_struct!(define); + | ------------------ previous definition of the type `MyStruct` here + | + = note: `MyStruct` must be defined only once in the type namespace of this module + = note: this error originates in the macro `my_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/hygiene/cross-crate-variants.rs b/tests/ui/hygiene/cross-crate-variants.rs new file mode 100644 index 000000000..efc73a21f --- /dev/null +++ b/tests/ui/hygiene/cross-crate-variants.rs @@ -0,0 +1,18 @@ +// Test that variants of an enum defined in another crate are resolved +// correctly when their names differ only in `SyntaxContext`. + +// run-pass +// aux-build:variants.rs + +extern crate variants; + +use variants::*; + +fn main() { + check_variants(); + + test_variants!(); + test_variants2!(); + + assert_eq!(MyEnum::Variant as u8, 1); +} diff --git a/tests/ui/hygiene/dollar-crate-modern.rs b/tests/ui/hygiene/dollar-crate-modern.rs new file mode 100644 index 000000000..eb176fed8 --- /dev/null +++ b/tests/ui/hygiene/dollar-crate-modern.rs @@ -0,0 +1,25 @@ +// Make sure `$crate` and `crate` work in for basic cases of nested macros. + +// check-pass +// aux-build:intercrate.rs + +#![feature(decl_macro)] + +extern crate intercrate; + +// `$crate` +intercrate::uses_dollar_crate_modern!(); + +intercrate::define_uses_dollar_crate_modern_nested!(uses_dollar_crate_modern_nested); +uses_dollar_crate_modern_nested!(); + +intercrate::define_uses_dollar_crate_legacy_nested!(); +uses_dollar_crate_legacy_nested!(); + +// `crate` +intercrate::uses_crate_modern!(); + +intercrate::define_uses_crate_modern_nested!(uses_crate_modern_nested); +uses_crate_modern_nested!(); + +fn main() {} diff --git a/tests/ui/hygiene/duplicate_lifetimes.rs b/tests/ui/hygiene/duplicate_lifetimes.rs new file mode 100644 index 000000000..8971fb626 --- /dev/null +++ b/tests/ui/hygiene/duplicate_lifetimes.rs @@ -0,0 +1,19 @@ +// Ensure that lifetime parameter names are modernized before we check for +// duplicates. + +#![feature(decl_macro, rustc_attrs)] + +#[rustc_macro_transparency = "semitransparent"] +macro m($a:lifetime) { + fn g<$a, 'a>() {} //~ ERROR the name `'a` is already used for a generic parameter +} + +#[rustc_macro_transparency = "transparent"] +macro n($a:lifetime) { + fn h<$a, 'a>() {} //~ ERROR the name `'a` is already used for a generic parameter +} + +m!('a); +n!('a); + +fn main() {} diff --git a/tests/ui/hygiene/duplicate_lifetimes.stderr b/tests/ui/hygiene/duplicate_lifetimes.stderr new file mode 100644 index 000000000..9f1a75147 --- /dev/null +++ b/tests/ui/hygiene/duplicate_lifetimes.stderr @@ -0,0 +1,31 @@ +error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate_lifetimes.rs:8:14 + | +LL | fn g<$a, 'a>() {} + | ^^ already used +... +LL | m!('a); + | ------ + | | | + | | first use of `'a` + | in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters + --> $DIR/duplicate_lifetimes.rs:13:14 + | +LL | fn h<$a, 'a>() {} + | ^^ already used +... +LL | n!('a); + | ------ + | | | + | | first use of `'a` + | in this macro invocation + | + = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/hygiene/eager-from-opaque-2.rs b/tests/ui/hygiene/eager-from-opaque-2.rs new file mode 100644 index 000000000..220e55267 --- /dev/null +++ b/tests/ui/hygiene/eager-from-opaque-2.rs @@ -0,0 +1,22 @@ +// Regression test for the issue #63460. + +// check-pass + +#[macro_export] +macro_rules! separator { + () => { "/" }; +} + +#[macro_export] +macro_rules! concat_separator { + ( $e:literal, $($other:literal),+ ) => { + concat!($e, $crate::separator!(), $crate::concat_separator!($($other),+)) + }; + ( $e:literal ) => { + $e + } +} + +fn main() { + println!("{}", concat_separator!(2, 3, 4)) +} diff --git a/tests/ui/hygiene/eager-from-opaque.rs b/tests/ui/hygiene/eager-from-opaque.rs new file mode 100644 index 000000000..6f3215dd6 --- /dev/null +++ b/tests/ui/hygiene/eager-from-opaque.rs @@ -0,0 +1,20 @@ +// Opaque macro can eagerly expand its input without breaking its resolution. +// Regression test for issue #63685. + +// check-pass + +macro_rules! foo { + () => { + "foo" + }; +} + +macro_rules! bar { + () => { + foo!() + }; +} + +fn main() { + format_args!(bar!()); +} diff --git a/tests/ui/hygiene/expansion-info-reset.rs b/tests/ui/hygiene/expansion-info-reset.rs new file mode 100644 index 000000000..fa5f71212 --- /dev/null +++ b/tests/ui/hygiene/expansion-info-reset.rs @@ -0,0 +1,4 @@ +fn main() { + format_args!({ #[derive(Clone)] struct S; }); + //~^ ERROR format argument must be a string literal +} diff --git a/tests/ui/hygiene/expansion-info-reset.stderr b/tests/ui/hygiene/expansion-info-reset.stderr new file mode 100644 index 000000000..64d27e064 --- /dev/null +++ b/tests/ui/hygiene/expansion-info-reset.stderr @@ -0,0 +1,13 @@ +error: format argument must be a string literal + --> $DIR/expansion-info-reset.rs:2:18 + | +LL | format_args!({ #[derive(Clone)] struct S; }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: you might be missing a string literal to format with + | +LL | format_args!("{}", { #[derive(Clone)] struct S; }); + | +++++ + +error: aborting due to previous error + diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs new file mode 100644 index 000000000..571017df4 --- /dev/null +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs @@ -0,0 +1,28 @@ +#![feature(decl_macro)] + +macro a() { + extern crate core as my_core; + mod v { + // Early resolution. + use my_core; //~ ERROR unresolved import `my_core` + } + mod u { + // Late resolution. + fn f() { my_core::mem::drop(0); } + //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + } +} + +a!(); + +mod v { + // Early resolution. + use my_core; //~ ERROR unresolved import `my_core` +} +mod u { + // Late resolution. + fn f() { my_core::mem::drop(0); } + //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` +} + +fn main() {} diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr new file mode 100644 index 000000000..f1f4caee3 --- /dev/null +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -0,0 +1,38 @@ +error[E0432]: unresolved import `my_core` + --> $DIR/extern-prelude-from-opaque-fail.rs:20:9 + | +LL | use my_core; + | ^^^^^^^ no `my_core` in the root + +error[E0432]: unresolved import `my_core` + --> $DIR/extern-prelude-from-opaque-fail.rs:7:13 + | +LL | use my_core; + | ^^^^^^^ no `my_core` in the root +... +LL | a!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: use of undeclared crate or module `my_core` + --> $DIR/extern-prelude-from-opaque-fail.rs:11:18 + | +LL | fn f() { my_core::mem::drop(0); } + | ^^^^^^^ use of undeclared crate or module `my_core` +... +LL | a!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: use of undeclared crate or module `my_core` + --> $DIR/extern-prelude-from-opaque-fail.rs:24:14 + | +LL | fn f() { my_core::mem::drop(0); } + | ^^^^^^^ use of undeclared crate or module `my_core` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/hygiene/fields-definition.rs b/tests/ui/hygiene/fields-definition.rs new file mode 100644 index 000000000..173c357bd --- /dev/null +++ b/tests/ui/hygiene/fields-definition.rs @@ -0,0 +1,22 @@ +#![feature(decl_macro)] + +macro modern($a: ident) { + struct Modern { + a: u8, + $a: u8, // OK + } +} + +macro_rules! legacy { + ($a: ident) => { + struct Legacy { + a: u8, + $a: u8, //~ ERROR field `a` is already declared + } + } +} + +modern!(a); +legacy!(a); + +fn main() {} diff --git a/tests/ui/hygiene/fields-definition.stderr b/tests/ui/hygiene/fields-definition.stderr new file mode 100644 index 000000000..9d091cedd --- /dev/null +++ b/tests/ui/hygiene/fields-definition.stderr @@ -0,0 +1,16 @@ +error[E0124]: field `a` is already declared + --> $DIR/fields-definition.rs:14:13 + | +LL | a: u8, + | ----- `a` first declared here +LL | $a: u8, + | ^^^^^^ field already declared +... +LL | legacy!(a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `legacy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/hygiene/fields-move.rs b/tests/ui/hygiene/fields-move.rs new file mode 100644 index 000000000..401ad97e3 --- /dev/null +++ b/tests/ui/hygiene/fields-move.rs @@ -0,0 +1,30 @@ +// issue #46314 + +#![feature(decl_macro)] + +#[derive(Debug)] +struct NonCopy(String); + +struct Foo { + x: NonCopy, +} + +macro copy_modern($foo: ident) { + $foo.x +} + +macro_rules! copy_legacy { + ($foo: ident) => { + $foo.x //~ ERROR use of moved value: `foo.x` + } +} + +fn assert_two_copies(a: NonCopy, b: NonCopy) { + println!("Got two copies: {:?}, {:?}", a, b); +} + +fn main() { + let foo = Foo { x: NonCopy("foo".into()) }; + assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` + assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x` +} diff --git a/tests/ui/hygiene/fields-move.stderr b/tests/ui/hygiene/fields-move.stderr new file mode 100644 index 000000000..b5b507c7d --- /dev/null +++ b/tests/ui/hygiene/fields-move.stderr @@ -0,0 +1,39 @@ +error[E0382]: use of moved value: `foo.x` + --> $DIR/fields-move.rs:18:9 + | +LL | $foo.x + | ^^^^^^ value used here after move +... +LL | assert_two_copies(copy_modern!(foo), foo.x); + | ----- value moved here +LL | assert_two_copies(copy_legacy!(foo), foo.x); + | ----------------- in this macro invocation + | + = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait + = note: this error originates in the macro `copy_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0382]: use of moved value: `foo.x` + --> $DIR/fields-move.rs:28:42 + | +LL | $foo.x + | ------ value moved here +... +LL | assert_two_copies(copy_modern!(foo), foo.x); + | ^^^^^ value used here after move + | + = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `foo.x` + --> $DIR/fields-move.rs:29:42 + | +LL | $foo.x + | ------ value moved here +... +LL | assert_two_copies(copy_legacy!(foo), foo.x); + | ^^^^^ value used here after move + | + = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/hygiene/fields-numeric-borrowck.rs b/tests/ui/hygiene/fields-numeric-borrowck.rs new file mode 100644 index 000000000..9536babc2 --- /dev/null +++ b/tests/ui/hygiene/fields-numeric-borrowck.rs @@ -0,0 +1,13 @@ +struct S(u8); + +fn main() { + let mut s = S(0); + let borrow1 = &mut s.0; + let S { 0: ref mut borrow2 } = s; + //~^ ERROR cannot borrow `s.0` as mutable more than once at a time + borrow2.use_mut(); + borrow1.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/hygiene/fields-numeric-borrowck.stderr b/tests/ui/hygiene/fields-numeric-borrowck.stderr new file mode 100644 index 000000000..bc13aa62f --- /dev/null +++ b/tests/ui/hygiene/fields-numeric-borrowck.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `s.0` as mutable more than once at a time + --> $DIR/fields-numeric-borrowck.rs:6:16 + | +LL | let borrow1 = &mut s.0; + | -------- first mutable borrow occurs here +LL | let S { 0: ref mut borrow2 } = s; + | ^^^^^^^^^^^^^^^ second mutable borrow occurs here +... +LL | borrow1.use_mut(); + | ----------------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/hygiene/fields.rs b/tests/ui/hygiene/fields.rs new file mode 100644 index 000000000..7a417b46f --- /dev/null +++ b/tests/ui/hygiene/fields.rs @@ -0,0 +1,30 @@ +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +mod foo { + struct S { x: u32 } + struct T(u32); + + pub macro m($S:ident, $x:ident) {{ + struct $S { + $x: u32, + x: i32, + } + + let s = S { x: 0 }; //~ ERROR type `foo::S` is private + let _ = s.x; //~ ERROR type `foo::S` is private + + let t = T(0); //~ ERROR type `T` is private + let _ = t.0; //~ ERROR type `T` is private + + let s = $S { $x: 0, x: 1 }; + assert_eq!((s.$x, s.x), (0, 1)); + s + }} +} + +fn main() { + let s = foo::m!(S, x); + assert_eq!(s.x, 0); +} diff --git a/tests/ui/hygiene/fields.stderr b/tests/ui/hygiene/fields.stderr new file mode 100644 index 000000000..978120b1f --- /dev/null +++ b/tests/ui/hygiene/fields.stderr @@ -0,0 +1,46 @@ +error: type `foo::S` is private + --> $DIR/fields.rs:15:17 + | +LL | let s = S { x: 0 }; + | ^^^^^^^^^^ private type +... +LL | let s = foo::m!(S, x); + | ------------- in this macro invocation + | + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `foo::S` is private + --> $DIR/fields.rs:16:17 + | +LL | let _ = s.x; + | ^ private type +... +LL | let s = foo::m!(S, x); + | ------------- in this macro invocation + | + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `T` is private + --> $DIR/fields.rs:18:17 + | +LL | let t = T(0); + | ^^^^ private type +... +LL | let s = foo::m!(S, x); + | ------------- in this macro invocation + | + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `T` is private + --> $DIR/fields.rs:19:17 + | +LL | let _ = t.0; + | ^ private type +... +LL | let s = foo::m!(S, x); + | ------------- in this macro invocation + | + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + diff --git a/tests/ui/hygiene/for-loop.rs b/tests/ui/hygiene/for-loop.rs new file mode 100644 index 000000000..2e5ae43a9 --- /dev/null +++ b/tests/ui/hygiene/for-loop.rs @@ -0,0 +1,8 @@ +// for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that +// `iter` is not accessible inside the for loop. + +fn main() { + for _ in 0..10 { + iter.next(); //~ ERROR cannot find value `iter` in this scope + } +} diff --git a/tests/ui/hygiene/for-loop.stderr b/tests/ui/hygiene/for-loop.stderr new file mode 100644 index 000000000..932c951e7 --- /dev/null +++ b/tests/ui/hygiene/for-loop.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `iter` in this scope + --> $DIR/for-loop.rs:6:9 + | +LL | iter.next(); + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/hygiene/format-args.rs b/tests/ui/hygiene/format-args.rs new file mode 100644 index 000000000..d74889b95 --- /dev/null +++ b/tests/ui/hygiene/format-args.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(non_upper_case_globals)] +#![feature(format_args_nl)] + +static arg0: () = (); + +fn main() { + static arg1: () = (); + format_args!("{} {:?}", 0, 1); + format_args_nl!("{} {:?}", 0, 1); +} diff --git a/tests/ui/hygiene/generate-mod.rs b/tests/ui/hygiene/generate-mod.rs new file mode 100644 index 000000000..882629354 --- /dev/null +++ b/tests/ui/hygiene/generate-mod.rs @@ -0,0 +1,49 @@ +// This is an equivalent of issue #50504, but for declarative macros. + +#![feature(decl_macro, rustc_attrs)] + +macro genmod($FromOutside: ident, $Outer: ident) { + type A = $FromOutside; + struct $Outer; + mod inner { + type A = $FromOutside; // `FromOutside` shouldn't be available from here + type Inner = $Outer; // `Outer` shouldn't be available from here + } +} + +#[rustc_macro_transparency = "transparent"] +macro genmod_transparent() { + type A = FromOutside; + struct Outer; + mod inner { + type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope + type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope + } +} + +macro_rules! genmod_legacy { () => { + type A = FromOutside; + struct Outer; + mod inner { + type A = FromOutside; //~ ERROR cannot find type `FromOutside` in this scope + type Inner = Outer; //~ ERROR cannot find type `Outer` in this scope + } +}} + +fn check() { + struct FromOutside; + genmod!(FromOutside, Outer); //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `Outer` in this scope +} + +fn check_transparent() { + struct FromOutside; + genmod_transparent!(); +} + +fn check_legacy() { + struct FromOutside; + genmod_legacy!(); +} + +fn main() {} diff --git a/tests/ui/hygiene/generate-mod.stderr b/tests/ui/hygiene/generate-mod.stderr new file mode 100644 index 000000000..32a2e145c --- /dev/null +++ b/tests/ui/hygiene/generate-mod.stderr @@ -0,0 +1,59 @@ +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:35:13 + | +LL | genmod!(FromOutside, Outer); + | ^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:35:26 + | +LL | genmod!(FromOutside, Outer); + | ^^^^^ not found in this scope + +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:19:18 + | +LL | type A = FromOutside; + | ^^^^^^^^^^^ not found in this scope +... +LL | genmod_transparent!(); + | --------------------- in this macro invocation + | + = note: this error originates in the macro `genmod_transparent` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:20:22 + | +LL | type Inner = Outer; + | ^^^^^ not found in this scope +... +LL | genmod_transparent!(); + | --------------------- in this macro invocation + | + = note: this error originates in the macro `genmod_transparent` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:28:18 + | +LL | type A = FromOutside; + | ^^^^^^^^^^^ not found in this scope +... +LL | genmod_legacy!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `genmod_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:29:22 + | +LL | type Inner = Outer; + | ^^^^^ not found in this scope +... +LL | genmod_legacy!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `genmod_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/hygiene/generic_params.rs b/tests/ui/hygiene/generic_params.rs new file mode 100644 index 000000000..3b6216c3e --- /dev/null +++ b/tests/ui/hygiene/generic_params.rs @@ -0,0 +1,104 @@ +// Ensure that generic parameters always have modern hygiene. + +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro, rustc_attrs)] + +mod type_params { + macro m($T:ident) { + fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) { + (t1.clone(), t2 == t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($T:ident) { + fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn h(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($T:ident) { + fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn k(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + m!(T); + n!(T); + p!(T); +} + +mod lifetime_params { + macro m($a:lifetime) { + fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($a:lifetime) { + fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($a:lifetime) { + fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + m!('a); + n!('a); + p!('a); +} + +mod const_params { + macro m($C:ident) { + fn f(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($C:ident) { + fn g(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn h(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($C:ident) { + fn j(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn k(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + m!(C); + n!(C); + p!(C); +} + +fn main() {} diff --git a/tests/ui/hygiene/globs.rs b/tests/ui/hygiene/globs.rs new file mode 100644 index 000000000..a3f466ef4 --- /dev/null +++ b/tests/ui/hygiene/globs.rs @@ -0,0 +1,72 @@ +#![feature(decl_macro)] + +mod foo { + pub fn f() {} +} + +mod bar { + pub fn g() {} +} + +macro m($($t:tt)*) { + $($t)* + use foo::*; + f(); + g(); //~ ERROR cannot find function `g` in this scope +} + +fn main() { + m! { + use bar::*; + g(); + f(); //~ ERROR cannot find function `f` in this scope + } +} + +n!(f); +macro n($i:ident) { + mod foo { + pub fn $i() -> u32 { 0 } + pub fn f() {} + + mod test { + use super::*; + fn g() { + let _: u32 = $i(); + let _: () = f(); + } + } + + macro n($j:ident) { + mod test { + use super::*; + fn g() { + let _: u32 = $i(); + let _: () = f(); + $j(); + } + } + } + macro n_with_super($j:ident) { + mod test { + use super::*; + fn g() { + let _: u32 = $i(); + let _: () = f(); + super::$j(); + } + } + } + + n!(f); //~ ERROR cannot find function `f` in this scope + n_with_super!(f); + mod test2 { + super::n! { + f //~ ERROR cannot find function `f` in this scope + } + super::n_with_super! { + f + } + } + } +} diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr new file mode 100644 index 000000000..c01901be5 --- /dev/null +++ b/tests/ui/hygiene/globs.stderr @@ -0,0 +1,73 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/globs.rs:22:9 + | +LL | pub fn g() {} + | ---------- similarly named function `g` defined here +... +LL | f(); + | ^ + | +help: a function with a similar name exists + | +LL | g(); + | ~ +help: consider importing this function + | +LL | use foo::f; + | + +error[E0425]: cannot find function `g` in this scope + --> $DIR/globs.rs:15:5 + | +LL | pub fn f() {} + | ---------- similarly named function `f` defined here +... +LL | g(); + | ^ +... +LL | / m! { +LL | | use bar::*; +LL | | g(); +LL | | f(); +LL | | } + | |_____- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: a function with a similar name exists + | +LL | f(); + | ~ +help: consider importing this function + | +LL | use bar::g; + | + +error[E0425]: cannot find function `f` in this scope + --> $DIR/globs.rs:61:12 + | +LL | n!(f); + | ----- in this macro invocation +... +LL | n!(f); + | ^ not found in this scope + | + = help: consider importing this function: + foo::f + = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `f` in this scope + --> $DIR/globs.rs:65:17 + | +LL | n!(f); + | ----- in this macro invocation +... +LL | f + | ^ not found in this scope + | + = help: consider importing this function: + foo::f + = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/hygiene/hir-res-hygiene.rs b/tests/ui/hygiene/hir-res-hygiene.rs new file mode 100644 index 000000000..c26cf5fdb --- /dev/null +++ b/tests/ui/hygiene/hir-res-hygiene.rs @@ -0,0 +1,18 @@ +// check-pass +// edition:2018 +// aux-build:not-libstd.rs + +// Check that paths created in HIR are not affected by in scope names. + +extern crate not_libstd as std; + +async fn the_future() { + async {}.await; +} + +fn main() -> Result<(), ()> { + for i in 0..10 {} + for j in 0..=10 {} + Ok(())?; + Ok(()) +} diff --git a/tests/ui/hygiene/hygiene-dodging-1.rs b/tests/ui/hygiene/hygiene-dodging-1.rs new file mode 100644 index 000000000..69e47e82b --- /dev/null +++ b/tests/ui/hygiene/hygiene-dodging-1.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_must_use)] + +mod x { + pub fn g() -> usize {14} +} + +pub fn main(){ + // should *not* shadow the module x: + let x = 9; + // use it to avoid warnings: + x+3; + assert_eq!(x::g(),14); +} diff --git a/tests/ui/hygiene/hygiene.rs b/tests/ui/hygiene/hygiene.rs new file mode 100644 index 000000000..fb351cf0f --- /dev/null +++ b/tests/ui/hygiene/hygiene.rs @@ -0,0 +1,114 @@ +// run-pass +#![allow(unused)] + +fn f() { + let x = 0; + macro_rules! foo { () => { + assert_eq!(x, 0); + } } + + let x = 1; + foo!(); +} + +fn g() { + let x = 0; + macro_rules! m { ($m1:ident, $m2:ident, $x:ident) => { + macro_rules! $m1 { () => { ($x, x) } } + let x = 1; + macro_rules! $m2 { () => { ($x, x) } } + } } + + let x = 2; + m!(m2, m3, x); + + let x = 3; + assert_eq!(m2!(), (2, 0)); + assert_eq!(m3!(), (2, 1)); + + let x = 4; + m!(m4, m5, x); + assert_eq!(m4!(), (4, 0)); + assert_eq!(m5!(), (4, 1)); +} + +mod foo { + macro_rules! m { + ($f:ident : |$x:ident| $e:expr) => { + pub fn $f() -> (i32, i32) { + let x = 0; + let $x = 1; + (x, $e) + } + } + } + + m!(f: |x| x + 10); +} + +fn interpolated_pattern() { + let x = 0; + macro_rules! m { + ($p:pat, $e:expr) => { + let $p = 1; + assert_eq!((x, $e), (0, 1)); + } + } + + m!(x, x); +} + +fn patterns_in_macro_generated_macros() { + let x = 0; + macro_rules! m { + ($a:expr, $b:expr) => { + assert_eq!(x, 0); + let x = $a; + macro_rules! n { + () => { + (x, $b) + } + } + } + } + + let x = 1; + m!(2, x); + + let x = 3; + assert_eq!(n!(), (2, 1)); +} + +fn match_hygiene() { + let x = 0; + + macro_rules! m { + ($p:pat, $e:expr) => { + for result in &[Ok(1), Err(1)] { + match *result { + $p => { assert_eq!(($e, x), (1, 0)); } + Err(x) => { assert_eq!(($e, x), (2, 1)); } + } + } + } + } + + let x = 2; + m!(Ok(x), x); +} + +fn label_hygiene() { + 'a: loop { + macro_rules! m { () => { break 'a; } } + m!(); + } +} + +fn main() { + f(); + g(); + assert_eq!(foo::f(), (0, 11)); + interpolated_pattern(); + patterns_in_macro_generated_macros(); + match_hygiene(); +} diff --git a/tests/ui/hygiene/hygienic-label-1.rs b/tests/ui/hygiene/hygienic-label-1.rs new file mode 100644 index 000000000..a06d9255a --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-1.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + () => { break 'x; } //~ ERROR use of undeclared label `'x` +} + +pub fn main() { + 'x: loop { foo!(); } +} diff --git a/tests/ui/hygiene/hygienic-label-1.stderr b/tests/ui/hygiene/hygienic-label-1.stderr new file mode 100644 index 000000000..deb6a2059 --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-1.stderr @@ -0,0 +1,14 @@ +error[E0426]: use of undeclared label `'x` + --> $DIR/hygienic-label-1.rs:2:19 + | +LL | () => { break 'x; } + | ^^ undeclared label `'x` +... +LL | 'x: loop { foo!(); } + | ------ in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-label-2.rs b/tests/ui/hygiene/hygienic-label-2.rs new file mode 100644 index 000000000..43e01a934 --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-2.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + ($e: expr) => { 'x: loop { $e } } +} + +pub fn main() { + foo!(break 'x); //~ ERROR use of undeclared label `'x` +} diff --git a/tests/ui/hygiene/hygienic-label-2.stderr b/tests/ui/hygiene/hygienic-label-2.stderr new file mode 100644 index 000000000..f23e741de --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-2.stderr @@ -0,0 +1,9 @@ +error[E0426]: use of undeclared label `'x` + --> $DIR/hygienic-label-2.rs:6:16 + | +LL | foo!(break 'x); + | ^^ undeclared label `'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-label-3.rs b/tests/ui/hygiene/hygienic-label-3.rs new file mode 100644 index 000000000..ab0559e1b --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-3.rs @@ -0,0 +1,9 @@ +macro_rules! foo { + () => { break 'x; } //~ ERROR use of undeclared label `'x` +} + +pub fn main() { + 'x: for _ in 0..1 { + foo!(); + }; +} diff --git a/tests/ui/hygiene/hygienic-label-3.stderr b/tests/ui/hygiene/hygienic-label-3.stderr new file mode 100644 index 000000000..cf7f78a99 --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-3.stderr @@ -0,0 +1,14 @@ +error[E0426]: use of undeclared label `'x` + --> $DIR/hygienic-label-3.rs:2:19 + | +LL | () => { break 'x; } + | ^^ undeclared label `'x` +... +LL | foo!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-label-4.rs b/tests/ui/hygiene/hygienic-label-4.rs new file mode 100644 index 000000000..a7e1f0e78 --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-4.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + ($e: expr) => { 'x: for _ in 0..1 { $e } } +} + +pub fn main() { + foo!(break 'x); //~ ERROR use of undeclared label `'x` +} diff --git a/tests/ui/hygiene/hygienic-label-4.stderr b/tests/ui/hygiene/hygienic-label-4.stderr new file mode 100644 index 000000000..1c93da02f --- /dev/null +++ b/tests/ui/hygiene/hygienic-label-4.stderr @@ -0,0 +1,9 @@ +error[E0426]: use of undeclared label `'x` + --> $DIR/hygienic-label-4.rs:6:16 + | +LL | foo!(break 'x); + | ^^ undeclared label `'x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/hygiene/hygienic-labels-in-let.rs b/tests/ui/hygiene/hygienic-labels-in-let.rs new file mode 100644 index 000000000..8cf66f31a --- /dev/null +++ b/tests/ui/hygiene/hygienic-labels-in-let.rs @@ -0,0 +1,82 @@ +// run-pass +#![allow(unreachable_code)] +#![allow(unused_labels)] + +// Test that labels injected by macros do not break hygiene. This +// checks cases where the macros invocations are under the rhs of a +// let statement. + +// Issue #24278: The label/lifetime shadowing checker from #24162 +// conservatively ignores hygiene, and thus issues warnings that are +// both true- and false-positives for this test. + +macro_rules! loop_x { + ($e: expr) => { + // $e shouldn't be able to interact with this 'x + 'x: loop { + $e + } + }; +} + +macro_rules! while_true { + ($e: expr) => { + // $e shouldn't be able to interact with this 'x + 'x: while 1 + 1 == 2 { + $e + } + }; +} + +macro_rules! run_once { + ($e: expr) => { + // ditto + 'x: for _ in 0..1 { + $e + } + }; +} + +pub fn main() { + let mut i = 0; + + let j: isize = { + 'x: loop { + // this 'x should refer to the outer loop, lexically + loop_x!(break 'x); + i += 1; + } + i + 1 + }; + assert_eq!(j, 1); + + let k: isize = { + 'x: for _ in 0..1 { + // ditto + loop_x!(break 'x); + i += 1; + } + i + 1 + }; + assert_eq!(k, 1); + + let l: isize = { + 'x: for _ in 0..1 { + // ditto + while_true!(break 'x); + i += 1; + } + i + 1 + }; + assert_eq!(l, 1); + + let n: isize = { + 'x: for _ in 0..1 { + // ditto + run_once!(continue 'x); + i += 1; + } + i + 1 + }; + assert_eq!(n, 1); +} diff --git a/tests/ui/hygiene/hygienic-labels.rs b/tests/ui/hygiene/hygienic-labels.rs new file mode 100644 index 000000000..6a7d81f04 --- /dev/null +++ b/tests/ui/hygiene/hygienic-labels.rs @@ -0,0 +1,60 @@ +// run-pass +#![allow(unreachable_code)] +#![allow(unused_labels)] +// Test that labels injected by macros do not break hygiene. + +// Issue #24278: The label/lifetime shadowing checker from #24162 +// conservatively ignores hygiene, and thus issues warnings that are +// both true- and false-positives for this test. + +macro_rules! loop_x { + ($e: expr) => { + // $e shouldn't be able to interact with this 'x + 'x: loop { + $e + } + }; +} + +macro_rules! run_once { + ($e: expr) => { + // ditto + 'x: for _ in 0..1 { + $e + } + }; +} + +macro_rules! while_x { + ($e: expr) => { + // ditto + 'x: while 1 + 1 == 2 { + $e + } + }; +} + +pub fn main() { + 'x: for _ in 0..1 { + // this 'x should refer to the outer loop, lexically + loop_x!(break 'x); + panic!("break doesn't act hygienically inside for loop"); + } + + 'x: loop { + // ditto + loop_x!(break 'x); + panic!("break doesn't act hygienically inside infinite loop"); + } + + 'x: while 1 + 1 == 2 { + while_x!(break 'x); + panic!("break doesn't act hygienically inside infinite while loop"); + } + + 'x: for _ in 0..1 { + // ditto + run_once!(continue 'x); + panic!("continue doesn't act hygienically inside for loop"); + } +} diff --git a/tests/ui/hygiene/impl_items-2.rs b/tests/ui/hygiene/impl_items-2.rs new file mode 100644 index 000000000..465e444ae --- /dev/null +++ b/tests/ui/hygiene/impl_items-2.rs @@ -0,0 +1,26 @@ +#![feature(decl_macro)] + +trait Trait { + fn foo() {} +} + +macro trait_impl() { + fn foo() {} +} + +// Check that we error on multiple impl items that resolve to the same trait item. +impl Trait for i32 { + trait_impl!(); + fn foo() {} + //~^ ERROR duplicate definitions with name `foo`: [E0201] +} + +struct Type; + +// Check that we do not error with inherent impls. +impl Type { + trait_impl!(); + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/hygiene/impl_items-2.stderr b/tests/ui/hygiene/impl_items-2.stderr new file mode 100644 index 000000000..3c0ffeb10 --- /dev/null +++ b/tests/ui/hygiene/impl_items-2.stderr @@ -0,0 +1,15 @@ +error[E0201]: duplicate definitions with name `foo`: + --> $DIR/impl_items-2.rs:14:5 + | +LL | fn foo() {} + | ----------- item in trait +... +LL | fn foo() {} + | ----------- previous definition here +... +LL | fn foo() {} + | ^^^^^^^^^^^ duplicate definition + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/hygiene/impl_items.rs b/tests/ui/hygiene/impl_items.rs new file mode 100644 index 000000000..ddb25c06b --- /dev/null +++ b/tests/ui/hygiene/impl_items.rs @@ -0,0 +1,34 @@ +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +mod foo { + struct S; + impl S { + fn f(&self) {} + } + + pub macro m() { + let _: () = S.f(); //~ ERROR type `for<'a> fn(&'a foo::S) {foo::S::f}` is private + } +} + +struct S; + +macro m($f:ident) { + impl S { + fn f(&self) -> u32 { 0 } + fn $f(&self) -> i32 { 0 } + } + fn f() { + let _: u32 = S.f(); + let _: i32 = S.$f(); + } +} + +m!(f); + +fn main() { + let _: i32 = S.f(); + foo::m!(); +} diff --git a/tests/ui/hygiene/impl_items.stderr b/tests/ui/hygiene/impl_items.stderr new file mode 100644 index 000000000..46a250038 --- /dev/null +++ b/tests/ui/hygiene/impl_items.stderr @@ -0,0 +1,13 @@ +error: type `for<'a> fn(&'a foo::S) {foo::S::f}` is private + --> $DIR/impl_items.rs:12:23 + | +LL | let _: () = S.f(); + | ^ private type +... +LL | foo::m!(); + | --------- in this macro invocation + | + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/hygiene/intercrate.rs b/tests/ui/hygiene/intercrate.rs new file mode 100644 index 000000000..d9b5b789e --- /dev/null +++ b/tests/ui/hygiene/intercrate.rs @@ -0,0 +1,12 @@ +// ignore-pretty pretty-printing is unhygienic + +// aux-build:intercrate.rs + +#![feature(decl_macro)] + +extern crate intercrate; + +fn main() { + assert_eq!(intercrate::foo::m!(), 1); + //~^ ERROR type `fn() -> u32 {foo::bar::f}` is private +} diff --git a/tests/ui/hygiene/intercrate.stderr b/tests/ui/hygiene/intercrate.stderr new file mode 100644 index 000000000..91358b279 --- /dev/null +++ b/tests/ui/hygiene/intercrate.stderr @@ -0,0 +1,10 @@ +error: type `fn() -> u32 {foo::bar::f}` is private + --> $DIR/intercrate.rs:10:16 + | +LL | assert_eq!(intercrate::foo::m!(), 1); + | ^^^^^^^^^^^^^^^^^^^^^ private type + | + = note: this error originates in the macro `intercrate::foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/hygiene/issue-15221.rs b/tests/ui/hygiene/issue-15221.rs new file mode 100644 index 000000000..4b8319a83 --- /dev/null +++ b/tests/ui/hygiene/issue-15221.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(path_statements)] +// pretty-expanded FIXME #23616 + +macro_rules! inner { + ($e:pat ) => ($e) +} + +macro_rules! outer { + ($e:pat ) => (inner!($e)) +} + +fn main() { + let outer!(g1) = 13; + g1; +} diff --git a/tests/ui/hygiene/issue-32922.rs b/tests/ui/hygiene/issue-32922.rs new file mode 100644 index 000000000..54ec44a1c --- /dev/null +++ b/tests/ui/hygiene/issue-32922.rs @@ -0,0 +1,29 @@ +// check-pass + +macro_rules! foo { () => { + let x = 1; + macro_rules! bar { () => {x} } + let _ = bar!(); +}} + +macro_rules! m { // test issue #31856 + ($n:ident) => ( + let a = 1; + let $n = a; + ) +} + +macro_rules! baz { + ($i:ident) => { + let mut $i = 2; + $i = $i + 1; + } +} + +fn main() { + foo! {}; + bar! {}; + + let mut a = true; + baz!(a); +} diff --git a/tests/ui/hygiene/issue-40847.rs b/tests/ui/hygiene/issue-40847.rs new file mode 100644 index 000000000..087b40ad6 --- /dev/null +++ b/tests/ui/hygiene/issue-40847.rs @@ -0,0 +1,17 @@ +// run-pass +macro_rules! gen { + ($name:ident ( $($dol:tt $var:ident)* ) $($body:tt)*) => { + macro_rules! $name { + ($($dol $var:ident)*) => { + $($body)* + } + } + } +} + +gen!(m($var) $var); + +fn main() { + let x = 1; + assert_eq!(m!(x), 1); +} diff --git a/tests/ui/hygiene/issue-44128.rs b/tests/ui/hygiene/issue-44128.rs new file mode 100644 index 000000000..5e03bdb8c --- /dev/null +++ b/tests/ui/hygiene/issue-44128.rs @@ -0,0 +1,17 @@ +// check-pass +#![allow(unused_must_use)] +#![feature(decl_macro)] + +pub macro create_struct($a:ident) { + struct $a; + impl Clone for $a { + fn clone(&self) -> Self { + $a + } + } +} + +fn main() { + create_struct!(Test); + Test.clone(); +} diff --git a/tests/ui/hygiene/issue-47311.rs b/tests/ui/hygiene/issue-47311.rs new file mode 100644 index 000000000..5c2379a8a --- /dev/null +++ b/tests/ui/hygiene/issue-47311.rs @@ -0,0 +1,17 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] +#![allow(unused)] + +macro m($S:ident, $x:ident) { + $S { $x: 0 } +} + +mod foo { + struct S { x: i32 } + + fn f() { ::m!(S, x); } +} + +fn main() {} diff --git a/tests/ui/hygiene/issue-47312.rs b/tests/ui/hygiene/issue-47312.rs new file mode 100644 index 000000000..bbcb3a7f3 --- /dev/null +++ b/tests/ui/hygiene/issue-47312.rs @@ -0,0 +1,21 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] +#![allow(unused)] + +mod foo { + pub macro m($s:tt, $i:tt) { + $s.$i + } +} + +mod bar { + struct S(i32); + fn f() { + let s = S(0); + ::foo::m!(s, 0); + } +} + +fn main() {} diff --git a/tests/ui/hygiene/issue-61574-const-parameters.rs b/tests/ui/hygiene/issue-61574-const-parameters.rs new file mode 100644 index 000000000..3634ee004 --- /dev/null +++ b/tests/ui/hygiene/issue-61574-const-parameters.rs @@ -0,0 +1,30 @@ +// A more comprehensive test that const parameters have correctly implemented +// hygiene + +// check-pass + +use std::ops::Add; + +struct VectorLike([T; {SIZE}]); + +macro_rules! impl_operator_overload { + ($trait_ident:ident, $method_ident:ident) => { + + impl $trait_ident for VectorLike + where + T: $trait_ident, + { + type Output = VectorLike; + + fn $method_ident(self, _: VectorLike) -> VectorLike { + let _ = SIZE; + unimplemented!() + } + } + + } +} + +impl_operator_overload!(Add, add); + +fn main() {} diff --git a/tests/ui/hygiene/issue-77523-def-site-async-await.rs b/tests/ui/hygiene/issue-77523-def-site-async-await.rs new file mode 100644 index 000000000..2af60ff6f --- /dev/null +++ b/tests/ui/hygiene/issue-77523-def-site-async-await.rs @@ -0,0 +1,19 @@ +// build-pass +// aux-build:opaque-hygiene.rs +// aux-build:def-site-async-await.rs + +// Regression test for issue #77523 +// Tests that we don't ICE when an unusual combination +// of def-site hygiene and cross-crate monomorphization occurs. + +extern crate def_site_async_await; + +use std::future::Future; + +fn mk_ctxt() -> std::task::Context<'static> { + panic!() +} + +fn main() { + Box::pin(def_site_async_await::serve()).as_mut().poll(&mut mk_ctxt()); +} diff --git a/tests/ui/hygiene/items.rs b/tests/ui/hygiene/items.rs new file mode 100644 index 000000000..1c625a972 --- /dev/null +++ b/tests/ui/hygiene/items.rs @@ -0,0 +1,27 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +pub macro m($foo:ident, $f:ident, $e:expr) { + mod foo { + pub fn f() -> u32 { 0 } + pub fn $f() -> u64 { 0 } + } + + mod $foo { + pub fn f() -> i32 { 0 } + pub fn $f() -> i64 { 0 } + } + + let _: u32 = foo::f(); + let _: u64 = foo::$f(); + let _: i32 = $foo::f(); + let _: i64 = $foo::$f(); + let _: i64 = $e; +} + +fn main() { + m!(foo, f, foo::f()); + let _: i64 = foo::f(); +} diff --git a/tests/ui/hygiene/lambda-var-hygiene.rs b/tests/ui/hygiene/lambda-var-hygiene.rs new file mode 100644 index 000000000..bf06765e5 --- /dev/null +++ b/tests/ui/hygiene/lambda-var-hygiene.rs @@ -0,0 +1,12 @@ +// run-pass +// shouldn't affect evaluation of $ex: +macro_rules! bad_macro { + ($ex:expr) => ({(|_x| { $ex }) (9) }) +} + +fn takes_x(_x : isize) { + assert_eq!(bad_macro!(_x),8); +} +fn main() { + takes_x(8); +} diff --git a/tests/ui/hygiene/legacy_interaction.rs b/tests/ui/hygiene/legacy_interaction.rs new file mode 100644 index 000000000..52008eed5 --- /dev/null +++ b/tests/ui/hygiene/legacy_interaction.rs @@ -0,0 +1,42 @@ +// check-pass +#![allow(dead_code)] +// ignore-pretty pretty-printing is unhygienic + +// aux-build:legacy_interaction.rs + +#![feature(decl_macro)] +#[allow(unused)] + +extern crate legacy_interaction; +// ^ defines +// ```rust +// macro_rules! m { +// () => { +// fn f() {} // (1) +// g() // (2) +// } +// } +// ```rust + +mod def_site { + // Unless this macro opts out of hygiene, it should resolve the same wherever it is invoked. + pub macro m2() { + ::legacy_interaction::m!(); + f(); // This should resolve to (1) + fn g() {} // We want (2) resolve to this, not to (4) + } +} + +mod use_site { + fn test() { + fn f() -> bool { true } // (3) + fn g() -> bool { true } // (4) + + ::def_site::m2!(); + + let _: bool = f(); // This should resolve to (3) + let _: bool = g(); // This should resolve to (4) + } +} + +fn main() {} diff --git a/tests/ui/hygiene/lexical.rs b/tests/ui/hygiene/lexical.rs new file mode 100644 index 000000000..3d25c7209 --- /dev/null +++ b/tests/ui/hygiene/lexical.rs @@ -0,0 +1,24 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +mod bar { + mod baz { + pub fn f() {} + } + + pub macro m($f:ident) { + baz::f(); + let _: i32 = $f(); + { + fn $f() -> u32 { 0 } + let _: u32 = $f(); + } + } +} + +fn main() { + fn f() -> i32 { 0 } + bar::m!(f); +} diff --git a/tests/ui/hygiene/local_inner_macros.rs b/tests/ui/hygiene/local_inner_macros.rs new file mode 100644 index 000000000..71ffcac40 --- /dev/null +++ b/tests/ui/hygiene/local_inner_macros.rs @@ -0,0 +1,19 @@ +// check-pass +// aux-build:local_inner_macros.rs + +extern crate local_inner_macros; + +use local_inner_macros::{public_macro, public_macro_dynamic}; + +public_macro!(); + +macro_rules! local_helper { + () => ( struct Z; ) +} + +public_macro_dynamic!(local_helper); + +fn main() { + let s = S; + let z = Z; +} diff --git a/tests/ui/hygiene/macro-metavars-legacy.rs b/tests/ui/hygiene/macro-metavars-legacy.rs new file mode 100644 index 000000000..09070f0f5 --- /dev/null +++ b/tests/ui/hygiene/macro-metavars-legacy.rs @@ -0,0 +1,29 @@ +// Ensure macro metavariables are compared with legacy hygiene + +#![feature(rustc_attrs)] + +// run-pass + +macro_rules! make_mac { + ( $($dollar:tt $arg:ident),+ ) => { + macro_rules! mac { + ( $($dollar $arg : ident),+ ) => { + $( $dollar $arg )-+ + } + } + } +} + +macro_rules! show_hygiene { + ( $dollar:tt $arg:ident ) => { + make_mac!($dollar $arg, $dollar arg); + } +} + +show_hygiene!( $arg ); + +fn main() { + let x = 5; + let y = 3; + assert_eq!(2, mac!(x, y)); +} diff --git a/tests/ui/hygiene/macro-metavars-transparent.rs b/tests/ui/hygiene/macro-metavars-transparent.rs new file mode 100644 index 000000000..e475b5728 --- /dev/null +++ b/tests/ui/hygiene/macro-metavars-transparent.rs @@ -0,0 +1,24 @@ +// Ensure macro metavariables are not compared without removing transparent +// marks. + +#![feature(rustc_attrs)] + +// run-pass + +#[rustc_macro_transparency = "transparent"] +macro_rules! k { + ($($s:tt)*) => { + macro_rules! m { + ($y:tt) => { + $($s)* + } + } + } +} + +k!(1 + $y); + +fn main() { + let x = 2; + assert_eq!(3, m!(x)); +} diff --git a/tests/ui/hygiene/missing-self-diag.rs b/tests/ui/hygiene/missing-self-diag.rs new file mode 100644 index 000000000..f934f793c --- /dev/null +++ b/tests/ui/hygiene/missing-self-diag.rs @@ -0,0 +1,23 @@ +// Regression test for issue #66898 +// Tests that we don't emit a nonsensical error message +// when a macro invocation tries to access `self` from a function +// that has a 'self' parameter + +pub struct Foo; + +macro_rules! call_bar { + () => { + self.bar(); //~ ERROR expected value + } +} + +impl Foo { + pub fn foo(&self) { + call_bar!(); + } + + pub fn bar(&self) { + } +} + +fn main() {} diff --git a/tests/ui/hygiene/missing-self-diag.stderr b/tests/ui/hygiene/missing-self-diag.stderr new file mode 100644 index 000000000..690bcd032 --- /dev/null +++ b/tests/ui/hygiene/missing-self-diag.stderr @@ -0,0 +1,17 @@ +error[E0424]: expected value, found module `self` + --> $DIR/missing-self-diag.rs:10:9 + | +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +... +LL | / pub fn foo(&self) { +LL | | call_bar!(); + | | ----------- in this macro invocation +LL | | } + | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters + | + = note: this error originates in the macro `call_bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0424`. diff --git a/tests/ui/hygiene/nested-dollar-crate.rs b/tests/ui/hygiene/nested-dollar-crate.rs new file mode 100644 index 000000000..e8703bc77 --- /dev/null +++ b/tests/ui/hygiene/nested-dollar-crate.rs @@ -0,0 +1,9 @@ +// aux-build:nested-dollar-crate.rs +// edition:2018 +// run-pass + +extern crate nested_dollar_crate; + +fn main() { + assert_eq!(nested_dollar_crate::inner!(), "In def crate!"); +} diff --git a/tests/ui/hygiene/nested_macro_privacy.rs b/tests/ui/hygiene/nested_macro_privacy.rs new file mode 100644 index 000000000..dea9101ee --- /dev/null +++ b/tests/ui/hygiene/nested_macro_privacy.rs @@ -0,0 +1,17 @@ +#![feature(decl_macro)] + +macro n($foo:ident, $S:ident, $i:ident, $m:ident) { + mod $foo { + #[derive(Default)] + pub struct $S { $i: u32 } + pub macro $m($e:expr) { $e.$i } + } +} + +n!(foo, S, i, m); + +fn main() { + use foo::{S, m}; + S::default().i; //~ ERROR field `i` of struct `S` is private + m!(S::default()); // ok +} diff --git a/tests/ui/hygiene/nested_macro_privacy.stderr b/tests/ui/hygiene/nested_macro_privacy.stderr new file mode 100644 index 000000000..1d11cd0f5 --- /dev/null +++ b/tests/ui/hygiene/nested_macro_privacy.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `i` of struct `S` is private + --> $DIR/nested_macro_privacy.rs:15:18 + | +LL | S::default().i; + | ^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/hygiene/no_implicit_prelude-2018.rs b/tests/ui/hygiene/no_implicit_prelude-2018.rs new file mode 100644 index 000000000..83ca28167 --- /dev/null +++ b/tests/ui/hygiene/no_implicit_prelude-2018.rs @@ -0,0 +1,11 @@ +// edition:2018 + +#[no_implicit_prelude] +mod bar { + fn f() { + ::std::print!(""); // OK + print!(); //~ ERROR cannot find macro `print` in this scope + } +} + +fn main() {} diff --git a/tests/ui/hygiene/no_implicit_prelude-2018.stderr b/tests/ui/hygiene/no_implicit_prelude-2018.stderr new file mode 100644 index 000000000..3f31b041b --- /dev/null +++ b/tests/ui/hygiene/no_implicit_prelude-2018.stderr @@ -0,0 +1,11 @@ +error: cannot find macro `print` in this scope + --> $DIR/no_implicit_prelude-2018.rs:7:9 + | +LL | print!(); + | ^^^^^ + | + = help: consider importing this macro: + std::print + +error: aborting due to previous error + diff --git a/tests/ui/hygiene/no_implicit_prelude-2021.rs b/tests/ui/hygiene/no_implicit_prelude-2021.rs new file mode 100644 index 000000000..0fe9ae56c --- /dev/null +++ b/tests/ui/hygiene/no_implicit_prelude-2021.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2021 + +#![no_implicit_prelude] + +fn main() { + assert!(true, "hoi"); + assert!(false, "hoi {}", 123); +} diff --git a/tests/ui/hygiene/no_implicit_prelude.rs b/tests/ui/hygiene/no_implicit_prelude.rs new file mode 100644 index 000000000..e23826e9d --- /dev/null +++ b/tests/ui/hygiene/no_implicit_prelude.rs @@ -0,0 +1,20 @@ +#![feature(decl_macro)] + +mod foo { + pub macro m() { Vec::::new(); ().clone() } + fn f() { ::bar::m!(); } +} + +#[no_implicit_prelude] +mod bar { + pub macro m() { + Vec::new(); //~ ERROR failed to resolve + ().clone() //~ ERROR no method named `clone` found + } + fn f() { + ::foo::m!(); + assert!(true); + } +} + +fn main() {} diff --git a/tests/ui/hygiene/no_implicit_prelude.stderr b/tests/ui/hygiene/no_implicit_prelude.stderr new file mode 100644 index 000000000..c48c84035 --- /dev/null +++ b/tests/ui/hygiene/no_implicit_prelude.stderr @@ -0,0 +1,35 @@ +error[E0433]: failed to resolve: use of undeclared type `Vec` + --> $DIR/no_implicit_prelude.rs:11:9 + | +LL | fn f() { ::bar::m!(); } + | ----------- in this macro invocation +... +LL | Vec::new(); + | ^^^ use of undeclared type `Vec` + | + = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider importing this struct + | +LL | use std::vec::Vec; + | + +error[E0599]: no method named `clone` found for unit type `()` in the current scope + --> $DIR/no_implicit_prelude.rs:12:12 + | +LL | fn f() { ::bar::m!(); } + | ----------- in this macro invocation +... +LL | ().clone() + | ^^^^^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope + = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::clone::Clone; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/hygiene/panic-location.rs b/tests/ui/hygiene/panic-location.rs new file mode 100644 index 000000000..5cf169dfb --- /dev/null +++ b/tests/ui/hygiene/panic-location.rs @@ -0,0 +1,10 @@ +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=0 +// +// Regression test for issue #70963 +// The captured stderr from this test reports a location +// inside `VecDeque::with_capacity`, instead of `<::core::macros::panic macros>` +fn main() { + std::collections::VecDeque::::with_capacity(!0); +} diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr new file mode 100644 index 000000000..0b23b1cc2 --- /dev/null +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'capacity overflow', library/alloc/src/raw_vec.rs:518:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/hygiene/pattern-macro.rs b/tests/ui/hygiene/pattern-macro.rs new file mode 100644 index 000000000..e5d6a3aa1 --- /dev/null +++ b/tests/ui/hygiene/pattern-macro.rs @@ -0,0 +1,6 @@ +macro_rules! foo { () => ( x ) } + +fn main() { + let foo!() = 2; + x + 1; //~ ERROR cannot find value `x` in this scope +} diff --git a/tests/ui/hygiene/pattern-macro.stderr b/tests/ui/hygiene/pattern-macro.stderr new file mode 100644 index 000000000..edd05916e --- /dev/null +++ b/tests/ui/hygiene/pattern-macro.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/pattern-macro.rs:5:5 + | +LL | x + 1; + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/hygiene/prelude-import-hygiene.rs b/tests/ui/hygiene/prelude-import-hygiene.rs new file mode 100644 index 000000000..51e7bed65 --- /dev/null +++ b/tests/ui/hygiene/prelude-import-hygiene.rs @@ -0,0 +1,29 @@ +// Make sure that attribute used when injecting the prelude are resolved +// hygienically. + +// check-pass +// aux-build:not-libstd.rs + +//revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +// The prelude import shouldn't see these as candidates for when it's trying to +// use the built-in macros. +extern crate core; +use core::prelude::v1::test as prelude_import; +use core::prelude::v1::test as macro_use; + +// Should not be used for the prelude import - not a concern in the 2015 edition +// because `std` is already declared in the crate root. +#[cfg(rust2018)] +extern crate not_libstd as std; + +#[cfg(rust2018)] +mod x { + // The extern crate item should override `std` in the extern prelude. + fn f() { + std::not_in_lib_std(); + } +} + +fn main() {} diff --git a/tests/ui/hygiene/privacy-early.rs b/tests/ui/hygiene/privacy-early.rs new file mode 100644 index 000000000..58fc74d65 --- /dev/null +++ b/tests/ui/hygiene/privacy-early.rs @@ -0,0 +1,17 @@ +// edition:2018 + +#![feature(decl_macro)] + +mod foo { + fn f() {} + macro f() {} + + pub macro m() { + use f as g; //~ ERROR `f` is private, and cannot be re-exported + f!(); + } +} + +fn main() { + foo::m!(); +} diff --git a/tests/ui/hygiene/privacy-early.stderr b/tests/ui/hygiene/privacy-early.stderr new file mode 100644 index 000000000..0375ed56d --- /dev/null +++ b/tests/ui/hygiene/privacy-early.stderr @@ -0,0 +1,22 @@ +error[E0364]: `f` is private, and cannot be re-exported + --> $DIR/privacy-early.rs:10:13 + | +LL | use f as g; + | ^^^^^^ +... +LL | foo::m!(); + | --------- in this macro invocation + | +note: consider marking `f` as `pub` in the imported module + --> $DIR/privacy-early.rs:10:13 + | +LL | use f as g; + | ^^^^^^ +... +LL | foo::m!(); + | --------- in this macro invocation + = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/hygiene/privacy.rs b/tests/ui/hygiene/privacy.rs new file mode 100644 index 000000000..78d255553 --- /dev/null +++ b/tests/ui/hygiene/privacy.rs @@ -0,0 +1,18 @@ +#![feature(decl_macro)] + +mod foo { + fn f() {} + + pub macro m($e:expr) { + f(); + self::f(); + ::foo::f(); + $e + } +} + +fn main() { + foo::m!( + foo::f() //~ ERROR `f` is private + ); +} diff --git a/tests/ui/hygiene/privacy.stderr b/tests/ui/hygiene/privacy.stderr new file mode 100644 index 000000000..70a24304d --- /dev/null +++ b/tests/ui/hygiene/privacy.stderr @@ -0,0 +1,15 @@ +error[E0603]: function `f` is private + --> $DIR/privacy.rs:16:14 + | +LL | foo::f() + | ^ private function + | +note: the function `f` is defined here + --> $DIR/privacy.rs:4:5 + | +LL | fn f() {} + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/hygiene/rustc-macro-transparency.rs b/tests/ui/hygiene/rustc-macro-transparency.rs new file mode 100644 index 000000000..5f36993af --- /dev/null +++ b/tests/ui/hygiene/rustc-macro-transparency.rs @@ -0,0 +1,31 @@ +#![feature(decl_macro, rustc_attrs)] + +#[rustc_macro_transparency = "transparent"] +macro transparent() { + struct Transparent; + let transparent = 0; +} +#[rustc_macro_transparency = "semitransparent"] +macro semitransparent() { + struct SemiTransparent; + let semitransparent = 0; +} +#[rustc_macro_transparency = "opaque"] +macro opaque() { + struct Opaque; + let opaque = 0; +} + +fn main() { + transparent!(); + semitransparent!(); + opaque!(); + + Transparent; // OK + SemiTransparent; // OK + Opaque; //~ ERROR cannot find value `Opaque` in this scope + + transparent; // OK + semitransparent; //~ ERROR expected value, found macro `semitransparent` + opaque; //~ ERROR expected value, found macro `opaque` +} diff --git a/tests/ui/hygiene/rustc-macro-transparency.stderr b/tests/ui/hygiene/rustc-macro-transparency.stderr new file mode 100644 index 000000000..1d2a1e124 --- /dev/null +++ b/tests/ui/hygiene/rustc-macro-transparency.stderr @@ -0,0 +1,28 @@ +error[E0425]: cannot find value `Opaque` in this scope + --> $DIR/rustc-macro-transparency.rs:26:5 + | +LL | Opaque; + | ^^^^^^ not found in this scope + +error[E0423]: expected value, found macro `semitransparent` + --> $DIR/rustc-macro-transparency.rs:29:5 + | +LL | struct SemiTransparent; + | ----------------------- similarly named unit struct `SemiTransparent` defined here +... +LL | semitransparent; + | ^^^^^^^^^^^^^^^ + | | + | not a value + | help: a unit struct with a similar name exists: `SemiTransparent` + +error[E0423]: expected value, found macro `opaque` + --> $DIR/rustc-macro-transparency.rs:30:5 + | +LL | opaque; + | ^^^^^^ not a value + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0423, E0425. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/hygiene/specialization.rs b/tests/ui/hygiene/specialization.rs new file mode 100644 index 000000000..656aa880a --- /dev/null +++ b/tests/ui/hygiene/specialization.rs @@ -0,0 +1,25 @@ +// run-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +trait Tr { + fn f(&self) -> &'static str { + "This shouldn't happen" + } +} + +pub macro m($t:ty) { + impl Tr for $t { + fn f(&self) -> &'static str { + "Run me" + } + } +} + +struct S; +m!(S); + +fn main() { + assert_eq!(S.f(), "Run me"); +} diff --git a/tests/ui/hygiene/stdlib-prelude-from-opaque-early.rs b/tests/ui/hygiene/stdlib-prelude-from-opaque-early.rs new file mode 100644 index 000000000..c8c5c72bf --- /dev/null +++ b/tests/ui/hygiene/stdlib-prelude-from-opaque-early.rs @@ -0,0 +1,21 @@ +// check-pass +// aux-build:stdlib-prelude.rs + +#![feature(decl_macro)] +#![feature(prelude_import)] + +extern crate stdlib_prelude; + +#[prelude_import] +use stdlib_prelude::*; + +macro mac() { + mod m { + use std::mem; // OK (extern prelude) + stdlib_macro!(); // OK (stdlib prelude) + } +} + +mac!(); + +fn main() {} diff --git a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs new file mode 100644 index 000000000..cf65de2bc --- /dev/null +++ b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(decl_macro)] + +macro mac() { + mod m { + fn f() { + std::mem::drop(0); // OK (extern prelude) + drop(0); // OK (stdlib prelude) + } + } +} + +mac!(); + +fn main() {} diff --git a/tests/ui/hygiene/thread-local-not-in-prelude.rs b/tests/ui/hygiene/thread-local-not-in-prelude.rs new file mode 100644 index 000000000..e5ed09c60 --- /dev/null +++ b/tests/ui/hygiene/thread-local-not-in-prelude.rs @@ -0,0 +1,9 @@ +// run-pass +#![no_std] + +extern crate std; + +std::thread_local!(static A: usize = 30); + +fn main() { +} diff --git a/tests/ui/hygiene/trait_items-2.rs b/tests/ui/hygiene/trait_items-2.rs new file mode 100644 index 000000000..39edfc37d --- /dev/null +++ b/tests/ui/hygiene/trait_items-2.rs @@ -0,0 +1,20 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +#![feature(decl_macro)] + +macro m($T:ident, $f:ident) { + pub trait $T { + fn f(&self) -> u32 { 0 } + fn $f(&self) -> i32 { 0 } + } + impl $T for () {} + + let _: u32 = ().f(); + let _: i32 = ().$f(); +} + +fn main() { + m!(T, f); + let _: i32 = ().f(); +} diff --git a/tests/ui/hygiene/trait_items.rs b/tests/ui/hygiene/trait_items.rs new file mode 100644 index 000000000..15c4acbc9 --- /dev/null +++ b/tests/ui/hygiene/trait_items.rs @@ -0,0 +1,21 @@ +#![feature(decl_macro)] + +mod foo { + pub trait T { + fn f(&self) {} + } + impl T for () {} +} + +mod bar { + use foo::*; + pub macro m() { ().f() } + fn f() { ::baz::m!(); } +} + +mod baz { + pub macro m() { ().f() } //~ ERROR no method named `f` found + fn f() { ::bar::m!(); } +} + +fn main() {} diff --git a/tests/ui/hygiene/trait_items.stderr b/tests/ui/hygiene/trait_items.stderr new file mode 100644 index 000000000..80bdbe0e2 --- /dev/null +++ b/tests/ui/hygiene/trait_items.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `f` found for unit type `()` in the current scope + --> $DIR/trait_items.rs:17:24 + | +LL | fn f(&self) {} + | - the method is available for `()` here +... +LL | fn f() { ::baz::m!(); } + | ----------- in this macro invocation +... +LL | pub macro m() { ().f() } + | ^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope + = note: this error originates in the macro `::baz::m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use foo::T; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/hygiene/traits-in-scope.rs b/tests/ui/hygiene/traits-in-scope.rs new file mode 100644 index 000000000..548bb226b --- /dev/null +++ b/tests/ui/hygiene/traits-in-scope.rs @@ -0,0 +1,53 @@ +// Macros with def-site hygiene still bring traits into scope. +// It is not clear whether this is desirable behavior or not. +// It is also not clear how to prevent it if it is not desirable. + +// check-pass + +#![feature(decl_macro)] +#![feature(trait_alias)] + +mod traits { + pub trait Trait1 { + fn simple_import(&self) {} + } + pub trait Trait2 { + fn renamed_import(&self) {} + } + pub trait Trait3 { + fn underscore_import(&self) {} + } + pub trait Trait4 { + fn trait_alias(&self) {} + } + + impl Trait1 for () {} + impl Trait2 for () {} + impl Trait3 for () {} + impl Trait4 for () {} +} + +macro m1() { + use traits::Trait1; +} +macro m2() { + use traits::Trait2 as Alias; +} +macro m3() { + use traits::Trait3 as _; +} +macro m4() { + trait Alias = traits::Trait4; +} + +fn main() { + m1!(); + m2!(); + m3!(); + m4!(); + + ().simple_import(); + ().renamed_import(); + ().underscore_import(); + ().trait_alias(); +} diff --git a/tests/ui/hygiene/transparent-basic.rs b/tests/ui/hygiene/transparent-basic.rs new file mode 100644 index 000000000..bfa1713e4 --- /dev/null +++ b/tests/ui/hygiene/transparent-basic.rs @@ -0,0 +1,43 @@ +// check-pass +// aux-build:transparent-basic.rs + +#![feature(decl_macro, rustc_attrs)] + +extern crate transparent_basic; + +#[rustc_macro_transparency = "transparent"] +macro binding() { + let x = 10; +} + +#[rustc_macro_transparency = "transparent"] +macro label() { + break 'label +} + +macro_rules! legacy { + () => { + binding!(); + let y = x; + } +} + +fn legacy_interaction1() { + legacy!(); +} + +struct S; + +fn check_dollar_crate() { + // `$crate::S` inside the macro resolves to `S` from this crate. + transparent_basic::dollar_crate!(); +} + +fn main() { + binding!(); + let y = x; + + 'label: loop { + label!(); + } +} diff --git a/tests/ui/hygiene/unpretty-debug.rs b/tests/ui/hygiene/unpretty-debug.rs new file mode 100644 index 000000000..6e936bb3d --- /dev/null +++ b/tests/ui/hygiene/unpretty-debug.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Zunpretty=expanded,hygiene + +// Don't break whenever Symbol numbering changes +// normalize-stdout-test "\d+#" -> "0#" + +// minimal junk +#![feature(no_core)] +#![no_core] + +macro_rules! foo { + ($x: ident) => { y + $x } +} + +fn bar() { + let x = 1; + foo!(x) +} + +fn y() {} diff --git a/tests/ui/hygiene/unpretty-debug.stdout b/tests/ui/hygiene/unpretty-debug.stdout new file mode 100644 index 000000000..51c21043d --- /dev/null +++ b/tests/ui/hygiene/unpretty-debug.stdout @@ -0,0 +1,28 @@ +// check-pass +// compile-flags: -Zunpretty=expanded,hygiene + +// Don't break whenever Symbol numbering changes +// normalize-stdout-test "\d+#" -> "0#" + +// minimal junk +#![feature /* 0#0 */(no_core)] +#![no_core /* 0#0 */] + +macro_rules! foo /* 0#0 */ { ($x : ident) => { y + $x } } + +fn bar /* 0#0 */() { + let x /* 0#0 */ = 1; + y /* 0#1 */ + x /* 0#0 */ +} + +fn y /* 0#0 */() {} + +/* +Expansions: +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "foo") + +SyntaxContexts: +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent) +*/ diff --git a/tests/ui/hygiene/wrap_unhygienic_example.rs b/tests/ui/hygiene/wrap_unhygienic_example.rs new file mode 100644 index 000000000..50c6b35ab --- /dev/null +++ b/tests/ui/hygiene/wrap_unhygienic_example.rs @@ -0,0 +1,34 @@ +// check-pass +// ignore-pretty pretty-printing is unhygienic + +// aux-build:my_crate.rs +// aux-build:unhygienic_example.rs + +#![feature(decl_macro)] + +extern crate unhygienic_example; +extern crate my_crate; // (b) + +// Hygienic version of `unhygienic_macro`. +pub macro hygienic_macro() { + fn g() {} // (c) + ::unhygienic_example::unhygienic_macro!(); + // ^ Even though we invoke an unhygienic macro, `hygienic_macro` remains hygienic. + // In the above expansion: + // (1) `my_crate` always resolves to (b) regardless of invocation site. + // (2) The defined function `f` is only usable inside this macro definition. + // (3) `g` always resolves to (c) regardless of invocation site. + // (4) `$crate::g` remains hygienic and continues to resolve to (a). + + f(); +} + +#[allow(unused)] +fn test_hygienic_macro() { + hygienic_macro!(); + + fn f() {} // (d) no conflict + f(); // resolves to (d) +} + +fn main() {} diff --git a/tests/ui/hygiene/xcrate.rs b/tests/ui/hygiene/xcrate.rs new file mode 100644 index 000000000..6981ce3f6 --- /dev/null +++ b/tests/ui/hygiene/xcrate.rs @@ -0,0 +1,12 @@ +// run-pass +// ignore-pretty pretty-printing is unhygienic + +// aux-build:xcrate.rs + +#![feature(decl_macro)] + +extern crate xcrate; + +fn main() { + xcrate::test!(); +} diff --git a/tests/ui/illegal-sized-bound/mutability-mismatch-arg.fixed b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.fixed new file mode 100644 index 000000000..74f3c887f --- /dev/null +++ b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.fixed @@ -0,0 +1,9 @@ +// run-rustfix +fn test(t: &mut dyn Iterator) -> u64 { + *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/tests/ui/illegal-sized-bound/mutability-mismatch-arg.rs b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.rs new file mode 100644 index 000000000..3b02c5a5a --- /dev/null +++ b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.rs @@ -0,0 +1,9 @@ +// run-rustfix +fn test(t: &dyn Iterator) -> u64 { + *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr new file mode 100644 index 000000000..89613bd5c --- /dev/null +++ b/tests/ui/illegal-sized-bound/mutability-mismatch-arg.stderr @@ -0,0 +1,13 @@ +error: the `min` method cannot be invoked on `&dyn Iterator` + --> $DIR/mutability-mismatch-arg.rs:3:9 + | +LL | *t.min().unwrap() + | ^^^ + | +help: you need `&mut dyn Iterator` instead of `&dyn Iterator` + | +LL | fn test(t: &mut dyn Iterator) -> u64 { + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/illegal-sized-bound/mutability-mismatch.rs b/tests/ui/illegal-sized-bound/mutability-mismatch.rs new file mode 100644 index 000000000..01bb3537c --- /dev/null +++ b/tests/ui/illegal-sized-bound/mutability-mismatch.rs @@ -0,0 +1,32 @@ +struct MutType; + +pub trait MutTrait { + fn function(&mut self) + where + Self: Sized; +} + +impl MutTrait for MutType { + fn function(&mut self) {} +} + +struct Type; + +pub trait Trait { + fn function(&self) + where + Self: Sized; +} + +impl Trait for Type { + fn function(&self) {} +} + +fn main() { + (&MutType as &dyn MutTrait).function(); + //~^ ERROR the `function` method cannot be invoked on `&dyn MutTrait` + //~| HELP you need `&mut dyn MutTrait` instead of `&dyn MutTrait` + (&mut Type as &mut dyn Trait).function(); + //~^ ERROR the `function` method cannot be invoked on `&mut dyn Trait` + //~| HELP you need `&dyn Trait` instead of `&mut dyn Trait` +} diff --git a/tests/ui/illegal-sized-bound/mutability-mismatch.stderr b/tests/ui/illegal-sized-bound/mutability-mismatch.stderr new file mode 100644 index 000000000..2ca571d9b --- /dev/null +++ b/tests/ui/illegal-sized-bound/mutability-mismatch.stderr @@ -0,0 +1,18 @@ +error: the `function` method cannot be invoked on `&dyn MutTrait` + --> $DIR/mutability-mismatch.rs:26:33 + | +LL | (&MutType as &dyn MutTrait).function(); + | ^^^^^^^^ + | + = help: you need `&mut dyn MutTrait` instead of `&dyn MutTrait` + +error: the `function` method cannot be invoked on `&mut dyn Trait` + --> $DIR/mutability-mismatch.rs:29:35 + | +LL | (&mut Type as &mut dyn Trait).function(); + | ^^^^^^^^ + | + = help: you need `&dyn Trait` instead of `&mut dyn Trait` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/illegal-sized-bound/regular.rs b/tests/ui/illegal-sized-bound/regular.rs new file mode 100644 index 000000000..7abd27ef9 --- /dev/null +++ b/tests/ui/illegal-sized-bound/regular.rs @@ -0,0 +1,32 @@ +struct MutType; + +pub trait MutTrait { + fn function(&mut self) + where + Self: Sized; + //~^ this has a `Sized` requirement +} + +impl MutTrait for MutType { + fn function(&mut self) {} +} + +struct Type; + +pub trait Trait { + fn function(&self) + where + Self: Sized; + //~^ this has a `Sized` requirement +} + +impl Trait for Type { + fn function(&self) {} +} + +fn main() { + (&mut MutType as &mut dyn MutTrait).function(); + //~^ ERROR the `function` method cannot be invoked on a trait object + (&Type as &dyn Trait).function(); + //~^ ERROR the `function` method cannot be invoked on a trait object +} diff --git a/tests/ui/illegal-sized-bound/regular.stderr b/tests/ui/illegal-sized-bound/regular.stderr new file mode 100644 index 000000000..7f3744145 --- /dev/null +++ b/tests/ui/illegal-sized-bound/regular.stderr @@ -0,0 +1,20 @@ +error: the `function` method cannot be invoked on a trait object + --> $DIR/regular.rs:28:41 + | +LL | Self: Sized; + | ----- this has a `Sized` requirement +... +LL | (&mut MutType as &mut dyn MutTrait).function(); + | ^^^^^^^^ + +error: the `function` method cannot be invoked on a trait object + --> $DIR/regular.rs:30:27 + | +LL | Self: Sized; + | ----- this has a `Sized` requirement +... +LL | (&Type as &dyn Trait).function(); + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/illegal-ufcs-drop.fixed b/tests/ui/illegal-ufcs-drop.fixed new file mode 100644 index 000000000..d73b391be --- /dev/null +++ b/tests/ui/illegal-ufcs-drop.fixed @@ -0,0 +1,10 @@ +// run-rustfix +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn main() { + drop(&mut Foo) //~ ERROR explicit use of destructor method +} diff --git a/tests/ui/illegal-ufcs-drop.rs b/tests/ui/illegal-ufcs-drop.rs new file mode 100644 index 000000000..11411f554 --- /dev/null +++ b/tests/ui/illegal-ufcs-drop.rs @@ -0,0 +1,10 @@ +// run-rustfix +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn main() { + Drop::drop(&mut Foo) //~ ERROR explicit use of destructor method +} diff --git a/tests/ui/illegal-ufcs-drop.stderr b/tests/ui/illegal-ufcs-drop.stderr new file mode 100644 index 000000000..91f47d5e4 --- /dev/null +++ b/tests/ui/illegal-ufcs-drop.stderr @@ -0,0 +1,12 @@ +error[E0040]: explicit use of destructor method + --> $DIR/illegal-ufcs-drop.rs:9:5 + | +LL | Drop::drop(&mut Foo) + | ^^^^^^^^^^ + | | + | explicit destructor calls not allowed + | help: consider using `drop` function: `drop` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0040`. diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.rs b/tests/ui/impl-header-lifetime-elision/assoc-type.rs new file mode 100644 index 000000000..b0089a37a --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/assoc-type.rs @@ -0,0 +1,25 @@ +// Test that we do not yet support elision in associated types, even +// when there is just one name we could take from the impl header. + +#![allow(warnings)] + +trait MyTrait { + type Output; +} + +impl MyTrait for &i32 { + type Output = &i32; + //~^ ERROR `&` without an explicit lifetime name cannot be used here +} + +impl MyTrait for &u32 { + type Output = &'_ i32; + //~^ ERROR `'_` cannot be used here +} + +// This is what you have to do: +impl<'a> MyTrait for &'a f32 { + type Output = &'a f32; +} + +fn main() { } diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr new file mode 100644 index 000000000..c4f27e0b8 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr @@ -0,0 +1,15 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/assoc-type.rs:11:19 + | +LL | type Output = &i32; + | ^ explicit lifetime name needed here + +error[E0637]: `'_` cannot be used here + --> $DIR/assoc-type.rs:16:20 + | +LL | type Output = &'_ i32; + | ^^ `'_` is a reserved lifetime name + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs b/tests/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs new file mode 100644 index 000000000..929b82bfc --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/constant-used-as-arraylen.rs @@ -0,0 +1,24 @@ +// check-pass +// Verify that we do not ICE when anonymous lifetimes appear inside an AnonConst. + +pub struct EntriesBuffer(Box<[[u8; HashesEntry::LEN]; 5]>); + +impl EntriesBuffer { + pub fn iter_child_buffers(&mut self) -> impl Iterator { + self.0.iter_mut() + } + + pub fn iter_child_buffers_explicit( + &mut self, + ) -> impl Iterator::LEN]> { + self.0.iter_mut() + } +} + +pub struct HashesEntry<'a>(&'a [u8]); + +impl HashesEntry<'_> { + pub const LEN: usize = 1; +} + +fn main() {} diff --git a/tests/ui/impl-header-lifetime-elision/dyn-trait.rs b/tests/ui/impl-header-lifetime-elision/dyn-trait.rs new file mode 100644 index 000000000..359c08c98 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/dyn-trait.rs @@ -0,0 +1,36 @@ +// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a, +// 'b> MyTrait<'a> for &'b i32`. + +#![allow(warnings)] + +use std::fmt::Debug; + +// Equivalent to `Box`: +trait StaticTrait { } +impl StaticTrait for Box { } + +// Equivalent to `Box`: +trait NotStaticTrait { } +impl NotStaticTrait for Box { } + +// Check that we don't err when the trait has a lifetime parameter. +trait TraitWithLifetime<'a> { } +impl NotStaticTrait for &dyn TraitWithLifetime<'_> { } + +fn static_val(_: T) { +} + +fn with_dyn_debug_static<'a>(x: Box) { + static_val(x); + //~^ ERROR borrowed data escapes outside of function +} + +fn not_static_val(_: T) { +} + +fn with_dyn_debug_not_static<'a>(x: Box) { + not_static_val(x); // OK +} + +fn main() { +} diff --git a/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr b/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr new file mode 100644 index 000000000..762698c4f --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -0,0 +1,16 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/dyn-trait.rs:24:5 + | +LL | fn with_dyn_debug_static<'a>(x: Box) { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | static_val(x); + | ^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs b/tests/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs new file mode 100644 index 000000000..6301ac4a3 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/explicit-and-elided-same-header.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(warnings)] + +// This works for functions... +fn foo<'a>(x: &str, y: &'a str) {} + +// ...so this should work for impls +impl<'a> Foo<&str> for &'a str {} +trait Foo {} + +fn main() { +} diff --git a/tests/ui/impl-header-lifetime-elision/inherent-impl.rs b/tests/ui/impl-header-lifetime-elision/inherent-impl.rs new file mode 100644 index 000000000..9d7b2f2d0 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/inherent-impl.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) + +struct Foo<'a>(&'a u8); + +impl Foo<'_> { + fn x() {} +} + +fn main() {} diff --git a/tests/ui/impl-header-lifetime-elision/path-elided.rs b/tests/ui/impl-header-lifetime-elision/path-elided.rs new file mode 100644 index 000000000..40a52efc7 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/path-elided.rs @@ -0,0 +1,11 @@ +#![allow(warnings)] + +trait MyTrait { } + +struct Foo<'a> { x: &'a u32 } + +impl MyTrait for Foo { + //~^ ERROR implicit elided lifetime not allowed here +} + +fn main() {} diff --git a/tests/ui/impl-header-lifetime-elision/path-elided.stderr b/tests/ui/impl-header-lifetime-elision/path-elided.stderr new file mode 100644 index 000000000..0b7d3f1e8 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/path-elided.stderr @@ -0,0 +1,15 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/path-elided.rs:7:18 + | +LL | impl MyTrait for Foo { + | ^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +LL | impl MyTrait for Foo<'_> { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/impl-header-lifetime-elision/path-underscore.rs b/tests/ui/impl-header-lifetime-elision/path-underscore.rs new file mode 100644 index 000000000..f39ba5733 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/path-underscore.rs @@ -0,0 +1,34 @@ +// Test that `impl MyTrait for Foo<'_>` works. + +// run-pass + +#![allow(warnings)] + +trait MyTrait { } + +struct Foo<'a> { x: &'a u32 } + +impl MyTrait for Foo<'_> { +} + +fn impls_my_trait() { } + +fn impls_my_trait_val(_: T) { + impls_my_trait::(); +} + +fn random_where_clause() +where for<'a> Foo<'a>: MyTrait { } + +fn main() { + let x = 22; + let f = Foo { x: &x }; + + // This type is `Foo<'x>` for a local lifetime `'x`; so the impl + // must apply to any lifetime to apply to this. + impls_my_trait_val(f); + + impls_my_trait::>(); + + random_where_clause(); +} diff --git a/tests/ui/impl-header-lifetime-elision/ref-underscore.rs b/tests/ui/impl-header-lifetime-elision/ref-underscore.rs new file mode 100644 index 000000000..5be04d08a --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/ref-underscore.rs @@ -0,0 +1,30 @@ +// Test that `impl MyTrait for &i32` works and is equivalent to any lifetime. + +// run-pass + +#![allow(warnings)] + +trait MyTrait { } + +impl MyTrait for &i32 { +} + +fn impls_my_trait() { } + +fn impls_my_trait_val(_: T) { + impls_my_trait::(); +} + +fn random_where_clause() +where for<'a> &'a i32: MyTrait { } + +fn main() { + let x = 22; + let f = &x; + + impls_my_trait_val(f); + + impls_my_trait::<&'static i32>(); + + random_where_clause(); +} diff --git a/tests/ui/impl-header-lifetime-elision/trait-elided.rs b/tests/ui/impl-header-lifetime-elision/trait-elided.rs new file mode 100644 index 000000000..c3e76d9cb --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/trait-elided.rs @@ -0,0 +1,8 @@ +#![allow(warnings)] + +trait MyTrait<'a> {} + +impl MyTrait for u32 {} +//~^ ERROR implicit elided lifetime not allowed here + +fn main() {} diff --git a/tests/ui/impl-header-lifetime-elision/trait-elided.stderr b/tests/ui/impl-header-lifetime-elision/trait-elided.stderr new file mode 100644 index 000000000..412bba6be --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/trait-elided.stderr @@ -0,0 +1,15 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/trait-elided.rs:5:6 + | +LL | impl MyTrait for u32 {} + | ^^^^^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +LL | impl MyTrait<'_> for u32 {} + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/impl-header-lifetime-elision/trait-underscore.rs b/tests/ui/impl-header-lifetime-elision/trait-underscore.rs new file mode 100644 index 000000000..3e13b0426 --- /dev/null +++ b/tests/ui/impl-header-lifetime-elision/trait-underscore.rs @@ -0,0 +1,35 @@ +// Test that `impl MyTrait<'_> for &i32` is equivalent to `impl<'a, +// 'b> MyTrait<'a> for &'b i32`. +// +// run-pass + +#![allow(warnings)] + +trait MyTrait<'a> { } + +// This is equivalent to `MyTrait<'a> for &'b i32`, which is proven by +// the code below. +impl MyTrait<'_> for &i32 { +} + +// When called, T will be `&'x i32` for some `'x`, so since we can +// prove that `&'x i32: for<'a> MyTrait<'a>, then we know that the +// lifetime parameter above is disconnected. +fn impls_my_trait MyTrait<'a>>() { } + +fn impls_my_trait_val MyTrait<'a>>(_: T) { + impls_my_trait::(); +} + +fn random_where_clause() +where for<'a, 'b> &'a i32: MyTrait<'b> { } + +fn main() { + let x = 22; + let f = &x; + impls_my_trait_val(f); + + impls_my_trait::<&'static i32>(); + + random_where_clause(); +} diff --git a/tests/ui/impl-inherent-non-conflict.rs b/tests/ui/impl-inherent-non-conflict.rs new file mode 100644 index 000000000..be524f87c --- /dev/null +++ b/tests/ui/impl-inherent-non-conflict.rs @@ -0,0 +1,23 @@ +// run-pass +// Ensure that a user-defined type admits multiple inherent methods +// with the same name, which can be called on values that have a +// precise enough type to allow distinguishing between the methods. + + +struct Foo(T); + +impl Foo { + fn bar(&self) -> i32 { self.0 as i32 } +} + +impl Foo { + fn bar(&self) -> i32 { -(self.0 as i32) } +} + +fn main() { + let foo_u = Foo::(5); + assert_eq!(foo_u.bar(), 5); + + let foo_i = Foo::(3); + assert_eq!(foo_i.bar(), -3); +} diff --git a/tests/ui/impl-not-adjacent-to-type.rs b/tests/ui/impl-not-adjacent-to-type.rs new file mode 100644 index 000000000..97caf9083 --- /dev/null +++ b/tests/ui/impl-not-adjacent-to-type.rs @@ -0,0 +1,16 @@ +// run-pass + +mod foo { + pub struct Point { + pub x: i32, + pub y: i32, + } +} + +impl foo::Point { + fn x(&self) -> i32 { self.x } +} + +fn main() { + assert_eq!((foo::Point { x: 1, y: 3}).x(), 1); +} diff --git a/tests/ui/impl-privacy-xc-1.rs b/tests/ui/impl-privacy-xc-1.rs new file mode 100644 index 000000000..c9f7f09c7 --- /dev/null +++ b/tests/ui/impl-privacy-xc-1.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:impl_privacy_xc_1.rs + +// pretty-expanded FIXME #23616 + +extern crate impl_privacy_xc_1; + +pub fn main() { + let fish = impl_privacy_xc_1::Fish { x: 1 }; + fish.swim(); +} diff --git a/tests/ui/impl-trait/associated-impl-trait-type-generic-trait.rs b/tests/ui/impl-trait/associated-impl-trait-type-generic-trait.rs new file mode 100644 index 000000000..6c7c46b0e --- /dev/null +++ b/tests/ui/impl-trait/associated-impl-trait-type-generic-trait.rs @@ -0,0 +1,30 @@ +#![feature(type_alias_impl_trait)] +// build-pass (FIXME(62277): could be check-pass?) + +trait Bar {} +struct Dummy(U); +impl Bar for Dummy {} + +trait Foo { + type Assoc: Bar; + fn foo(t: T) -> Self::Assoc; +} + +impl Foo for i32 { + type Assoc = impl Bar; + fn foo(w: W) -> Self::Assoc { + Dummy(w) + } +} + +struct NonGeneric; +impl Bar for NonGeneric {} + +impl Foo for u32 { + type Assoc = impl Bar; + fn foo(_: W) -> Self::Assoc { + NonGeneric + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/associated-impl-trait-type-trivial.rs b/tests/ui/impl-trait/associated-impl-trait-type-trivial.rs new file mode 100644 index 000000000..cdda341ca --- /dev/null +++ b/tests/ui/impl-trait/associated-impl-trait-type-trivial.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] +// build-pass (FIXME(62277): could be check-pass?) + +trait Bar {} +struct Dummy; +impl Bar for Dummy {} + +trait Foo { + type Assoc: Bar; + fn foo() -> Self::Assoc; +} + +impl Foo for i32 { + type Assoc = impl Bar; + fn foo() -> Self::Assoc { + Dummy + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/associated-impl-trait-type.rs b/tests/ui/impl-trait/associated-impl-trait-type.rs new file mode 100644 index 000000000..d0661d66f --- /dev/null +++ b/tests/ui/impl-trait/associated-impl-trait-type.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] +// build-pass (FIXME(62277): could be check-pass?) + +trait Bar {} +struct Dummy; +impl Bar for Dummy {} + +trait Foo { + type Assoc: Bar; + fn foo() -> Self::Assoc; + fn bar() -> Self::Assoc; +} + +impl Foo for i32 { + type Assoc = impl Bar; + fn foo() -> Self::Assoc { + Dummy + } + fn bar() -> Self::Assoc { + Dummy + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/async_scope_creep.rs b/tests/ui/impl-trait/async_scope_creep.rs new file mode 100644 index 000000000..7a9d64d33 --- /dev/null +++ b/tests/ui/impl-trait/async_scope_creep.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] +// edition:2021 +// check-pass + +struct Pending {} + +struct CantOpen {} + +trait AsyncRead {} + +impl AsyncRead for i32 {} + +type PendingReader<'a> = impl AsyncRead + 'a; + +type OpeningReadFuture<'a> = + impl std::future::Future, CantOpen>>; + +impl Pending { + async fn read(&mut self) -> Result { + Ok(42) + } + + fn read_fut(&mut self) -> OpeningReadFuture<'_> { + self.read() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-leak-rpass.rs b/tests/ui/impl-trait/auto-trait-leak-rpass.rs new file mode 100644 index 000000000..9976a018b --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leak-rpass.rs @@ -0,0 +1,21 @@ +// run-pass + +// Fast path, main can see the concrete type returned. +fn before() -> impl FnMut(i32) { + let mut p = Box::new(0); + move |x| *p = x +} + +fn send(_: T) {} + +fn main() { + send(before()); + send(after()); +} + +// Deferred path, main has to wait until typeck finishes, +// to check if the return type of after is Send. +fn after() -> impl FnMut(i32) { + let mut p = Box::new(0); + move |x| *p = x +} diff --git a/tests/ui/impl-trait/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leak.rs new file mode 100644 index 000000000..c2fbbf94f --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leak.rs @@ -0,0 +1,23 @@ +use std::cell::Cell; +use std::rc::Rc; + +fn send(_: T) {} + +fn main() { +} + +// Cycles should work as the deferred obligations are +// independently resolved and only require the concrete +// return type, which can't depend on the obligation. +fn cycle1() -> impl Clone { + //~^ ERROR cycle detected + send(cycle2().clone()); + + Rc::new(Cell::new(5)) +} + +fn cycle2() -> impl Clone { + send(cycle1().clone()); + + Rc::new(String::from("foo")) +} diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr new file mode 100644 index 000000000..feedfc40a --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leak.stderr @@ -0,0 +1,99 @@ +error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:12:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires preparing `cycle1` for borrow checking... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building THIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:14:5 + | +LL | send(cycle2().clone()); + | ^^^^ + = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... +note: ...which requires computing type of `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:19:16 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires preparing `cycle2` for borrow checking... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building THIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:19:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:20:5 + | +LL | send(cycle1().clone()); + | ^^^^ + = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`... + = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:1:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/auto-trait-leak2.rs b/tests/ui/impl-trait/auto-trait-leak2.rs new file mode 100644 index 000000000..09450089a --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leak2.rs @@ -0,0 +1,39 @@ +use std::cell::Cell; +use std::rc::Rc; + +// Fast path, main can see the concrete type returned. +fn before() -> impl Fn(i32) { +//~^ NOTE within this `impl Fn +//~| NOTE within the type `impl Fn +//~| NOTE expansion of desugaring + let p = Rc::new(Cell::new(0)); + move |x| p.set(x) //~ NOTE used within this closure +} + +fn send(_: T) {} +//~^ NOTE required by a bound +//~| NOTE required by a bound +//~| NOTE required by this bound +//~| NOTE required by this bound + +fn main() { + send(before()); + //~^ ERROR `Rc>` cannot be sent between threads safely + //~| NOTE `Rc>` cannot be sent between threads safely + //~| NOTE required by a bound + + send(after()); + //~^ ERROR `Rc>` cannot be sent between threads safely + //~| NOTE `Rc>` cannot be sent between threads safely + //~| NOTE required by a bound +} + +// Deferred path, main has to wait until typeck finishes, +// to check if the return type of after is Send. +fn after() -> impl Fn(i32) { +//~^ NOTE within this `impl Fn(i32)` +//~| NOTE in this expansion +//~| NOTE appears within the type + let p = Rc::new(Cell::new(0)); + move |x| p.set(x) //~ NOTE used within this closure +} diff --git a/tests/ui/impl-trait/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leak2.stderr new file mode 100644 index 000000000..52fa28145 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leak2.stderr @@ -0,0 +1,59 @@ +error[E0277]: `Rc>` cannot be sent between threads safely + --> $DIR/auto-trait-leak2.rs:20:10 + | +LL | fn before() -> impl Fn(i32) { + | ------------ within this `impl Fn(i32)` +... +LL | send(before()); + | ---- ^^^^^^^^ `Rc>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` +note: required because it's used within this closure + --> $DIR/auto-trait-leak2.rs:10:5 + | +LL | move |x| p.set(x) + | ^^^^^^^^ +note: required because it appears within the type `impl Fn(i32)` + --> $DIR/auto-trait-leak2.rs:5:16 + | +LL | fn before() -> impl Fn(i32) { + | ^^^^^^^^^^^^ +note: required by a bound in `send` + --> $DIR/auto-trait-leak2.rs:13:12 + | +LL | fn send(_: T) {} + | ^^^^ required by this bound in `send` + +error[E0277]: `Rc>` cannot be sent between threads safely + --> $DIR/auto-trait-leak2.rs:25:10 + | +LL | send(after()); + | ---- ^^^^^^^ `Rc>` cannot be sent between threads safely + | | + | required by a bound introduced by this call +... +LL | fn after() -> impl Fn(i32) { + | ------------ within this `impl Fn(i32)` + | + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` +note: required because it's used within this closure + --> $DIR/auto-trait-leak2.rs:38:5 + | +LL | move |x| p.set(x) + | ^^^^^^^^ +note: required because it appears within the type `impl Fn(i32)` + --> $DIR/auto-trait-leak2.rs:33:15 + | +LL | fn after() -> impl Fn(i32) { + | ^^^^^^^^^^^^ +note: required by a bound in `send` + --> $DIR/auto-trait-leak2.rs:13:12 + | +LL | fn send(_: T) {} + | ^^^^ required by this bound in `send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/auto-trait.rs b/tests/ui/impl-trait/auto-trait.rs new file mode 100644 index 000000000..35994e4a5 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait.rs @@ -0,0 +1,25 @@ +// Tests that type alias impls traits do not leak auto-traits for +// the purposes of coherence checking +#![feature(type_alias_impl_trait)] + +trait OpaqueTrait {} +impl OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + () +} + +#[derive(Debug)] +struct D(T); + +trait AnotherTrait {} +impl AnotherTrait for T {} + +// This is in error, because we cannot assume that `OpaqueType: !Send`. +// (We treat opaque types as "foreign types" that could grow more impls +// in the future.) +impl AnotherTrait for D { + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` +} + +fn main() {} diff --git a/tests/ui/impl-trait/auto-trait.stderr b/tests/ui/impl-trait/auto-trait.stderr new file mode 100644 index 000000000..81009413c --- /dev/null +++ b/tests/ui/impl-trait/auto-trait.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` + --> $DIR/auto-trait.rs:21:1 + | +LL | impl AnotherTrait for T {} + | -------------------------------- first implementation here +... +LL | impl AnotherTrait for D { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/autoderef.rs b/tests/ui/impl-trait/autoderef.rs new file mode 100644 index 000000000..5e4f49954 --- /dev/null +++ b/tests/ui/impl-trait/autoderef.rs @@ -0,0 +1,19 @@ +// check-pass + +use std::path::Path; +use std::ffi::OsStr; +use std::ops::Deref; + +fn frob(path: &str) -> impl Deref + '_ { + OsStr::new(path).as_ref() +} + +fn open_parent<'path>(_path: &'path Path) { + todo!() +} + +fn main() { + let old_path = frob("hello"); + + open_parent(&old_path); +} diff --git a/tests/ui/impl-trait/auxiliary/extra-item.rs b/tests/ui/impl-trait/auxiliary/extra-item.rs new file mode 100644 index 000000000..8eaeafa52 --- /dev/null +++ b/tests/ui/impl-trait/auxiliary/extra-item.rs @@ -0,0 +1 @@ +pub trait MyTrait {} diff --git a/tests/ui/impl-trait/auxiliary/no_method_suggested_traits.rs b/tests/ui/impl-trait/auxiliary/no_method_suggested_traits.rs new file mode 100644 index 000000000..cefb17e0f --- /dev/null +++ b/tests/ui/impl-trait/auxiliary/no_method_suggested_traits.rs @@ -0,0 +1,36 @@ +pub use reexport::Reexported; + +pub struct Foo; +pub enum Bar { X } + +pub mod foo { + pub trait PubPub { + fn method(&self) {} + + fn method3(&self) {} + } + + impl PubPub for u32 {} + impl PubPub for i32 {} +} +pub mod bar { + trait PubPriv { + fn method(&self); + } +} +mod qux { + pub trait PrivPub { + fn method(&self); + } +} +mod quz { + trait PrivPriv { + fn method(&self); + } +} + +mod reexport { + pub trait Reexported { + fn method(&self); + } +} diff --git a/tests/ui/impl-trait/auxiliary/xcrate.rs b/tests/ui/impl-trait/auxiliary/xcrate.rs new file mode 100644 index 000000000..ac016258b --- /dev/null +++ b/tests/ui/impl-trait/auxiliary/xcrate.rs @@ -0,0 +1,23 @@ +// NOTE commented out due to issue #45994 +//pub fn fourway_add(a: i32) -> impl Fn(i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 { +// move |b| move |c| move |d| a + b + c + d +//} + +fn some_internal_fn() -> u32 { + 1 +} + +fn other_internal_fn() -> u32 { + 1 +} + +// See #40839 +pub fn return_closure_accessing_internal_fn() -> impl Fn() -> u32 { + || { + some_internal_fn() + 1 + } +} + +pub fn return_internal_fn() -> impl Fn() -> u32 { + other_internal_fn +} diff --git a/tests/ui/impl-trait/bound-normalization-fail.rs b/tests/ui/impl-trait/bound-normalization-fail.rs new file mode 100644 index 000000000..332959247 --- /dev/null +++ b/tests/ui/impl-trait/bound-normalization-fail.rs @@ -0,0 +1,48 @@ +// edition:2018 + +// See issue 60414 + +// Reduction to `impl Trait` + +struct Foo(T); + +trait FooLike { + type Output; +} + +impl FooLike for Foo { + type Output = T; +} + +mod impl_trait { + use super::*; + + trait Trait { + type Assoc; + } + + /// `T::Assoc` can't be normalized any further here. + fn foo_fail() -> impl FooLike { + //~^ ERROR: type mismatch + Foo(()) + } +} + +// Same with lifetimes in the trait + +mod lifetimes { + use super::*; + + trait Trait<'a> { + type Assoc; + } + + /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. + fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + //~^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + //~| ERROR: type mismatch + Foo(()) + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/bound-normalization-fail.stderr b/tests/ui/impl-trait/bound-normalization-fail.stderr new file mode 100644 index 000000000..f04a753a0 --- /dev/null +++ b/tests/ui/impl-trait/bound-normalization-fail.stderr @@ -0,0 +1,55 @@ +error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` + --> $DIR/bound-normalization-fail.rs:25:32 + | +LL | fn foo_fail() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` +LL | +LL | Foo(()) + | ------- return type was inferred to be `Foo<()>` here + | +note: expected this to be `()` + --> $DIR/bound-normalization-fail.rs:14:19 + | +LL | type Output = T; + | ^ + = note: expected unit type `()` + found associated type `::Assoc` +help: consider constraining the associated type `::Assoc` to `()` + | +LL | fn foo_fail>() -> impl FooLike { + | ++++++++++++ + +error[E0658]: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/bound-normalization-fail.rs:41:41 + | +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #103532 for more information + = help: add `#![feature(impl_trait_projections)]` to the crate attributes to enable + +error[E0271]: type mismatch resolving ` as FooLike>::Output == >::Assoc` + --> $DIR/bound-normalization-fail.rs:41:41 + | +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` +... +LL | Foo(()) + | ------- return type was inferred to be `Foo<()>` here + | +note: expected this to be `()` + --> $DIR/bound-normalization-fail.rs:14:19 + | +LL | type Output = T; + | ^ + = note: expected unit type `()` + found associated type `>::Assoc` +help: consider constraining the associated type `>::Assoc` to `()` + | +LL | fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike { + | ++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0658. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/bound-normalization-pass.rs b/tests/ui/impl-trait/bound-normalization-pass.rs new file mode 100644 index 000000000..51718079d --- /dev/null +++ b/tests/ui/impl-trait/bound-normalization-pass.rs @@ -0,0 +1,87 @@ +// check-pass +// edition:2018 +// revisions: default sa +//[sa] compile-flags: -Z save-analysis +//-^ To make this the regression test for #75962. + +#![feature(type_alias_impl_trait)] + +// See issue 60414 + +// Reduction to `impl Trait` + +struct Foo(T); + +trait FooLike { + type Output; +} + +impl FooLike for Foo { + type Output = T; +} + +mod impl_trait { + use super::*; + + trait Trait { + type Assoc; + } + + /// `T::Assoc` should be normalized to `()` here. + fn foo_pass>() -> impl FooLike { + Foo(()) + } +} + +// Same with lifetimes in the trait + +mod lifetimes { + use super::*; + + trait Trait<'a> { + type Assoc; + } + + /// Like above. + /// + /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here + fn foo2_pass<'a, T: Trait<'a, Assoc = ()> + 'a>() + -> impl FooLike>::Assoc> + 'a { + Foo(()) + } + + /// Normalization to type containing bound region. + /// + /// FIXME(#51525) -- the shorter notation `T::Assoc` winds up referencing `'static` here + fn foo2_pass2<'a, T: Trait<'a, Assoc = &'a ()> + 'a>() + -> impl FooLike>::Assoc> + 'a { + Foo(&()) + } +} + +// The same applied to `type Foo = impl Bar`s + +mod opaque_types { + trait Implemented { + type Assoc; + } + impl Implemented for T { + type Assoc = u8; + } + + trait Trait { + type Out; + } + + impl Trait for () { + type Out = u8; + } + + type Ex = impl Trait::Assoc>; + + fn define() -> Ex { + () + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/bounds_regression.rs b/tests/ui/impl-trait/bounds_regression.rs new file mode 100644 index 000000000..31fc46203 --- /dev/null +++ b/tests/ui/impl-trait/bounds_regression.rs @@ -0,0 +1,24 @@ +// run-pass + +pub trait FakeGenerator { + type Yield; + type Return; +} + +pub trait FakeFuture { + type Output; +} + +pub fn future_from_generator< + T: FakeGenerator +>(x: T) -> impl FakeFuture { + GenFuture(x) +} + +struct GenFuture>(#[allow(unused_tuple_struct_fields)] T); + +impl> FakeFuture for GenFuture { + type Output = T::Return; +} + +fn main() {} diff --git a/tests/ui/impl-trait/can-return-unconstrained-closure.rs b/tests/ui/impl-trait/can-return-unconstrained-closure.rs new file mode 100644 index 000000000..7ae1ac4f5 --- /dev/null +++ b/tests/ui/impl-trait/can-return-unconstrained-closure.rs @@ -0,0 +1,23 @@ +// Test that we are special casing "outlives" for opaque types. +// +// The return type of a closure is not required to outlive the closure. As such +// the following code would not compile if we used a standard outlives check +// when checking the return type, because the return type of the closure would +// be `&ReEmpty i32`, and we don't allow `ReEmpty` to occur in the concrete +// type used for an opaque type. +// +// However, opaque types are special cased to include check all regions in the +// concrete type against the bound, which forces the return type to be +// `&'static i32` here. + +// build-pass (FIXME(62277): could be check-pass?) + +fn make_identity() -> impl Sized { + |x: &'static i32| x +} + +fn make_identity_static() -> impl Sized + 'static { + |x: &'static i32| x +} + +fn main() {} diff --git a/tests/ui/impl-trait/closure-calling-parent-fn.rs b/tests/ui/impl-trait/closure-calling-parent-fn.rs new file mode 100644 index 000000000..9dab334a2 --- /dev/null +++ b/tests/ui/impl-trait/closure-calling-parent-fn.rs @@ -0,0 +1,12 @@ +// Regression test for #54593: the MIR type checker was going wrong +// when a closure returns the `impl Copy` from its parent fn. It was +// (incorrectly) replacing the `impl Copy` in its return type with the +// hidden type (`()`) but that type resulted from a recursive call to +// `foo` and hence is treated opaquely within the closure body. This +// resulted in a failed subtype relationship. +// +// check-pass + +fn foo() -> impl Copy { || foo(); } +fn bar() -> impl Copy { || bar(); } +fn main() { } diff --git a/tests/ui/impl-trait/closure-in-impl-trait-arg.rs b/tests/ui/impl-trait/closure-in-impl-trait-arg.rs new file mode 100644 index 000000000..3cfce459e --- /dev/null +++ b/tests/ui/impl-trait/closure-in-impl-trait-arg.rs @@ -0,0 +1,7 @@ +// run-pass +#![allow(unused_must_use)] +fn bug(_: impl Iterator) {} + +fn main() { + bug(std::iter::empty()); +} diff --git a/tests/ui/impl-trait/closure-in-impl-trait.rs b/tests/ui/impl-trait/closure-in-impl-trait.rs new file mode 100644 index 000000000..3593a1d5c --- /dev/null +++ b/tests/ui/impl-trait/closure-in-impl-trait.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_must_use)] +fn bug() -> impl Iterator { + std::iter::empty() +} + +fn ok() -> Box> { + Box::new(std::iter::empty()) +} + +fn main() { + for _item in ok::() {} + for _item in bug::() {} +} diff --git a/tests/ui/impl-trait/cross-return-site-inference.rs b/tests/ui/impl-trait/cross-return-site-inference.rs new file mode 100644 index 000000000..00aed2ad9 --- /dev/null +++ b/tests/ui/impl-trait/cross-return-site-inference.rs @@ -0,0 +1,48 @@ +// edition:2021 + +fn foo(b: bool) -> impl std::fmt::Debug { + if b { + return vec![42] + } + [].into_iter().collect() +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return [].into_iter().collect() + } + vec![42] +} + +fn bak(b: bool) -> impl std::fmt::Debug { + if b { + return std::iter::empty().collect() + } + vec![42] +} + +fn baa(b: bool) -> impl std::fmt::Debug { + if b { + return [42].into_iter().collect() + } + vec![] +} + +fn muh() -> Result<(), impl std::fmt::Debug> { + Err("whoops")?; + Ok(()) + //~^ ERROR type annotations needed +} + +fn muh2() -> Result<(), impl std::fmt::Debug> { + return Err(From::from("foo")); + //~^ ERROR type annotations needed + Ok(()) +} + +fn muh3() -> Result<(), impl std::fmt::Debug> { + Err(From::from("foo")) + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/impl-trait/cross-return-site-inference.stderr b/tests/ui/impl-trait/cross-return-site-inference.stderr new file mode 100644 index 000000000..766614e9e --- /dev/null +++ b/tests/ui/impl-trait/cross-return-site-inference.stderr @@ -0,0 +1,36 @@ +error[E0282]: type annotations needed + --> $DIR/cross-return-site-inference.rs:33:5 + | +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Ok::<(), E>(()) + | +++++++++ + +error[E0282]: type annotations needed + --> $DIR/cross-return-site-inference.rs:38:12 + | +LL | return Err(From::from("foo")); + | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | return Err::<(), E>(From::from("foo")); + | +++++++++ + +error[E0282]: type annotations needed + --> $DIR/cross-return-site-inference.rs:44:5 + | +LL | Err(From::from("foo")) + | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Err::<(), E>(From::from("foo")) + | +++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs new file mode 100644 index 000000000..d2c347920 --- /dev/null +++ b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait SuperExpectation: Fn(i32) {} + +impl SuperExpectation for T {} + +type Foo = impl SuperExpectation; + +fn main() { + let _: Foo = |x| { + let _ = x.to_string(); + }; +} diff --git a/tests/ui/impl-trait/deprecated_annotation.rs b/tests/ui/impl-trait/deprecated_annotation.rs new file mode 100644 index 000000000..f76724c8a --- /dev/null +++ b/tests/ui/impl-trait/deprecated_annotation.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![deny(warnings)] + +#[deprecated] +trait Deprecated {} + +#[deprecated] +struct DeprecatedTy; + +#[allow(deprecated)] +impl Deprecated for DeprecatedTy {} + +#[allow(deprecated)] +fn foo() -> impl Deprecated { DeprecatedTy } + +fn main() { + foo(); +} diff --git a/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs b/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs new file mode 100644 index 000000000..3a47710d5 --- /dev/null +++ b/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs @@ -0,0 +1,15 @@ +trait Foo { + fn foo(self, f: impl FnOnce()); +} + +impl Foo for () { + fn foo(self, f: impl FnOnce()) { + f() + } +} + +fn main() { + // FIXME: This should ideally use a fully qualified path + // without mentioning the generic arguments of `foo`. + ().foo(|| ()) //~ ERROR type annotations needed +} diff --git a/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr b/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr new file mode 100644 index 000000000..a1a629bdd --- /dev/null +++ b/tests/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/fully-qualified-path-impl-trait.rs:14:8 + | +LL | ().foo(|| ()) + | ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/divergence.rs b/tests/ui/impl-trait/divergence.rs new file mode 100644 index 000000000..211f7972d --- /dev/null +++ b/tests/ui/impl-trait/divergence.rs @@ -0,0 +1,13 @@ +// check-pass + +fn foo() -> impl MyTrait { + panic!(); + MyStruct +} + +struct MyStruct; +trait MyTrait {} + +impl MyTrait for MyStruct {} + +fn main() {} diff --git a/tests/ui/impl-trait/does-not-live-long-enough.rs b/tests/ui/impl-trait/does-not-live-long-enough.rs new file mode 100644 index 000000000..d2a345231 --- /dev/null +++ b/tests/ui/impl-trait/does-not-live-long-enough.rs @@ -0,0 +1,11 @@ +struct List { + data: Vec, +} +impl List { + fn started_with<'a>(&'a self, prefix: &'a str) -> impl Iterator { + self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref()) + //~^ ERROR E0373 + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/does-not-live-long-enough.stderr b/tests/ui/impl-trait/does-not-live-long-enough.stderr new file mode 100644 index 000000000..750687e23 --- /dev/null +++ b/tests/ui/impl-trait/does-not-live-long-enough.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `prefix`, which is owned by the current function + --> $DIR/does-not-live-long-enough.rs:6:33 + | +LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref()) + | ^^^ ------ `prefix` is borrowed here + | | + | may outlive borrowed value `prefix` + | +note: closure is returned here + --> $DIR/does-not-live-long-enough.rs:6:9 + | +LL | self.data.iter().filter(|s| s.starts_with(prefix)).map(|s| s.as_ref()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `prefix` (and any other referenced variables), use the `move` keyword + | +LL | self.data.iter().filter(move |s| s.starts_with(prefix)).map(|s| s.as_ref()) + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs new file mode 100644 index 000000000..3b7141573 --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs @@ -0,0 +1,16 @@ +// Test that we don't get an error with `dyn Bar` in an impl Trait +// when there are multiple inputs. The `dyn Bar` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Foo { type Item: ?Sized; } +trait Bar { } + +impl Foo for T { + type Item = dyn Bar; +} + +fn foo(x: &str, y: &str) -> impl Foo { () } + +fn main() { } diff --git a/tests/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs new file mode 100644 index 000000000..e8da52aad --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs @@ -0,0 +1,11 @@ +// Test that we don't get an error with `dyn Object` in an impl Trait +// when there are multiple inputs. The `dyn Object` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Alpha {} +trait Object {} +impl Alpha for T {} +fn alpha(x: &str, y: &str) -> impl Alpha { () } +fn main() { } diff --git a/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs new file mode 100644 index 000000000..aad9d89fe --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs @@ -0,0 +1,27 @@ +// Test that we don't get an error with `dyn Bar` in an impl Trait +// when there are multiple inputs. The `dyn Bar` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +fn bar(x: &str) -> &impl Foo { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs new file mode 100644 index 000000000..8d34c1b6c --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs @@ -0,0 +1,23 @@ +// Test that `impl Alpha` resets the object-lifetime +// default to `'static`. +// +// check-pass + +trait Alpha { + fn item(&self) -> Box { + panic!() + } +} + +trait Object {} +impl Alpha for T {} +fn alpha(x: &str, y: &str) -> impl Alpha { () } +fn is_static(_: T) where T: 'static { } + +fn bar(x: &str) -> &impl Alpha { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs new file mode 100644 index 000000000..cbf1daabe --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs @@ -0,0 +1,74 @@ +#![allow(bare_trait_objects)] +struct Struct; +trait Trait {} +impl Trait for Struct {} +impl Trait for u32 {} + +fn fuz() -> (usize, Trait) { (42, Struct) } +//~^ ERROR E0277 +//~| ERROR E0308 +fn bar() -> (usize, dyn Trait) { (42, Struct) } +//~^ ERROR E0277 +//~| ERROR E0308 +fn bap() -> Trait { Struct } +//~^ ERROR E0746 +fn ban() -> dyn Trait { Struct } +//~^ ERROR E0746 +fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0746 +// Suggest using `Box` +fn bal() -> dyn Trait { //~ ERROR E0746 + if true { + return Struct; + } + 42 +} +fn bax() -> dyn Trait { //~ ERROR E0746 + if true { + Struct + } else { + 42 //~ ERROR `if` and `else` have incompatible types + } +} +fn bam() -> Box { + if true { + return Struct; //~ ERROR mismatched types + } + 42 //~ ERROR mismatched types +} +fn baq() -> Box { + if true { + return 0; //~ ERROR mismatched types + } + 42 //~ ERROR mismatched types +} +fn baz() -> Box { + if true { + Struct //~ ERROR mismatched types + } else { + 42 //~ ERROR mismatched types + } +} +fn baw() -> Box { + if true { + 0 //~ ERROR mismatched types + } else { + 42 //~ ERROR mismatched types + } +} + +// Suggest using `impl Trait` +fn bat() -> dyn Trait { //~ ERROR E0746 + if true { + return 0; + } + 42 +} +fn bay() -> dyn Trait { //~ ERROR E0746 + if true { + 0 + } else { + 42 + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr new file mode 100644 index 000000000..7f73d5e12 --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -0,0 +1,303 @@ +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35 + | +LL | fn fuz() -> (usize, Trait) { (42, Struct) } + | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct` + | + = note: expected trait object `(dyn Trait + 'static)` + found struct `Struct` + +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13 + | +LL | fn fuz() -> (usize, Trait) { (42, Struct) } + | ^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))` + | | + | doesn't have a size known at compile-time + | + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = note: required because it appears within the type `(usize, (dyn Trait + 'static))` + = note: the return type of a function must have a statically known size + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct` + | + = note: expected trait object `(dyn Trait + 'static)` + found struct `Struct` + +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))` + | | + | doesn't have a size known at compile-time + | + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = note: required because it appears within the type `(usize, (dyn Trait + 'static))` + = note: the return type of a function must have a statically known size + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13 + | +LL | fn bap() -> Trait { Struct } + | ^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait` + | +LL | fn bap() -> impl Trait { Struct } + | ~~~~~~~~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 + | +LL | fn ban() -> dyn Trait { Struct } + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait` + | +LL | fn ban() -> impl Trait { Struct } + | ~~~~~~~~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13 + | +LL | fn bak() -> dyn Trait { unimplemented!() } + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature + | +LL | fn bak() -> impl Trait { unimplemented!() } + | ~~~~~~~~~~ +help: use a boxed trait object if all return paths implement trait `Trait` + | +LL | fn bak() -> Box { unimplemented!() } + | ++++ + + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 + | +LL | fn bal() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl Trait` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn bal() -> Box { + | ++++ + +help: ... and box this value + | +LL | return Box::new(Struct); + | +++++++++ + +help: ... and box this value + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9 + | +LL | / if true { +LL | | Struct + | | ------ expected because of this +LL | | } else { +LL | | 42 + | | ^^ expected struct `Struct`, found integer +LL | | } + | |_____- `if` and `else` have incompatible types + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13 + | +LL | fn bax() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl Trait` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn bax() -> Box { + | ++++ + +help: ... and box this value + | +LL | Box::new(Struct) + | +++++++++ + +help: ... and box this value + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16 + | +LL | fn bam() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return Struct; + | ^^^^^^ expected struct `Box`, found struct `Struct` + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | return Box::new(Struct); + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:5 + | +LL | fn bam() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected struct `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:40:16 + | +LL | fn baq() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return 0; + | ^ expected struct `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | return Box::new(0); + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:5 + | +LL | fn baq() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected struct `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9 + | +LL | fn baz() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | Struct + | ^^^^^^ expected struct `Box`, found struct `Struct` + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(Struct) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 + | +LL | fn baz() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected struct `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9 + | +LL | fn baw() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | 0 + | ^ expected struct `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(0) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 + | +LL | fn baw() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected struct `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:13 + | +LL | fn bat() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait` + | +LL | fn bat() -> impl Trait { + | ~~~~~~~~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13 + | +LL | fn bay() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait` + | +LL | fn bay() -> impl Trait { + | ~~~~~~~~~~ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0277, E0308, E0746. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/equal-hidden-lifetimes.rs b/tests/ui/impl-trait/equal-hidden-lifetimes.rs new file mode 100644 index 000000000..79db88828 --- /dev/null +++ b/tests/ui/impl-trait/equal-hidden-lifetimes.rs @@ -0,0 +1,49 @@ +// Test that we consider equal regions when checking for hidden regions in +// opaque types + +// check-pass + +// `'a == 'static` so `&'a i32` is fine as the return type +fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized { + //~^ WARNING unnecessary lifetime parameter `'a` + x +} + +// `'a == 'b` so `&'b i32` is fine as the return type +fn equal_regions<'a: 'b, 'b: 'a>(x: &'b i32) -> impl Sized + 'a { + let y: &'a i32 = x; + let z: &'b i32 = y; + x +} + +// `'a == 'b` so `&'a i32` is fine as the return type +fn equal_regions_rev<'a: 'b, 'b: 'a>(x: &'a i32) -> impl Sized + 'b { + let y: &'a i32 = x; + let z: &'b i32 = y; + x +} + +// `'a == 'b` so `*mut &'b i32` is fine as the return type +fn equal_regions_inv<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { + let y: *mut &'a i32 = x; + let z: *mut &'b i32 = y; + x +} + +// `'a == 'b` so `*mut &'a i32` is fine as the return type +fn equal_regions_inv_rev<'a: 'b, 'b: 'a>(x: *mut &'a i32) -> impl Sized + 'b { + let y: *mut &'a i32 = x; + let z: *mut &'b i32 = y; + x +} + +// Should be able to infer `fn(&'static ())` as the return type. +fn contravariant_lub<'a, 'b: 'a, 'c: 'a, 'd: 'b + 'c>( + x: fn(&'b ()), + y: fn(&'c ()), + c: bool, +) -> impl Sized + 'a { + if c { x } else { y } +} + +fn main() {} diff --git a/tests/ui/impl-trait/equal-hidden-lifetimes.stderr b/tests/ui/impl-trait/equal-hidden-lifetimes.stderr new file mode 100644 index 000000000..3e48aef55 --- /dev/null +++ b/tests/ui/impl-trait/equal-hidden-lifetimes.stderr @@ -0,0 +1,10 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/equal-hidden-lifetimes.rs:7:25 + | +LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized { + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/equality-rpass.rs b/tests/ui/impl-trait/equality-rpass.rs new file mode 100644 index 000000000..607b4a496 --- /dev/null +++ b/tests/ui/impl-trait/equality-rpass.rs @@ -0,0 +1,48 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo: std::fmt::Debug + Eq {} + +impl Foo for T {} + +fn hide(x: T) -> impl Foo { + x +} + +trait Leak: Sized { + fn leak(self) -> T; +} +impl Leak for U { + default fn leak(self) -> T { panic!("type mismatch") } +} +impl Leak for T { + fn leak(self) -> T { self } +} + +trait CheckIfSend: Sized { + type T: Default; + fn check(self) -> Self::T { Default::default() } +} +impl CheckIfSend for T { + default type T = (); +} +impl CheckIfSend for T { + type T = bool; +} + +fn lucky_seven() -> impl Fn(usize) -> u8 { + let a = [1, 2, 3, 4, 5, 6, 7]; + move |i| a[i] +} + +fn main() { + assert_eq!(hide(42), hide(42)); + + assert_eq!(std::mem::size_of_val(&hide([0_u8; 5])), 5); + assert_eq!(std::mem::size_of_val(&lucky_seven()), 7); + + assert_eq!(Leak::::leak(hide(5_i32)), 5_i32); + + assert_eq!(CheckIfSend::check(hide(0_i32)), false); +} diff --git a/tests/ui/impl-trait/equality-rpass.stderr b/tests/ui/impl-trait/equality-rpass.stderr new file mode 100644 index 000000000..bde8362fd --- /dev/null +++ b/tests/ui/impl-trait/equality-rpass.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality-rpass.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/equality.rs b/tests/ui/impl-trait/equality.rs new file mode 100644 index 000000000..828b5aac8 --- /dev/null +++ b/tests/ui/impl-trait/equality.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo: Copy + ToString {} + +impl Foo for T {} + +fn hide(x: T) -> impl Foo { + x +} + +fn two(x: bool) -> impl Foo { + if x { + return 1_i32; + } + 0_u32 + //~^ ERROR mismatched types + //~| expected `i32`, found `u32` +} + +fn sum_to(n: u32) -> impl Foo { + if n == 0 { + 0 + } else { + n + sum_to(n - 1) + //~^ ERROR cannot add `impl Foo` to `u32` + } +} + +trait Leak: Sized { + type T; + fn leak(self) -> Self::T; +} +impl Leak for T { + default type T = (); + default fn leak(self) -> Self::T { panic!() } +} +impl Leak for i32 { + type T = i32; + fn leak(self) -> i32 { self } +} + +fn main() { +} diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr new file mode 100644 index 000000000..69f4cbbbf --- /dev/null +++ b/tests/ui/impl-trait/equality.stderr @@ -0,0 +1,41 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/equality.rs:15:5 + | +LL | fn two(x: bool) -> impl Foo { + | -------- expected `i32` because of return type +... +LL | 0_u32 + | ^^^^^ expected `i32`, found `u32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 0_i32 + | ~~~ + +error[E0277]: cannot add `impl Foo` to `u32` + --> $DIR/equality.rs:24:11 + | +LL | n + sum_to(n - 1) + | ^ no implementation for `u32 + impl Foo` + | + = help: the trait `Add` is not implemented for `u32` + = help: the following other types implement trait `Add`: + <&'a u32 as Add> + <&u32 as Add<&u32>> + > + + +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/equality2.rs b/tests/ui/impl-trait/equality2.rs new file mode 100644 index 000000000..2e325867d --- /dev/null +++ b/tests/ui/impl-trait/equality2.rs @@ -0,0 +1,44 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo: Copy + ToString {} + +impl Foo for T {} + +fn hide(x: T) -> impl Foo { + x +} + +trait Leak: Sized { + type T; + fn leak(self) -> Self::T; +} +impl Leak for T { + default type T = (); + default fn leak(self) -> Self::T { panic!() } +} +impl Leak for i32 { + type T = i32; + fn leak(self) -> i32 { self } +} + +fn main() { + let _: u32 = hide(0_u32); + //~^ ERROR mismatched types + //~| expected type `u32` + //~| found opaque type `impl Foo` + //~| expected `u32`, found opaque type + + let _: i32 = Leak::leak(hide(0_i32)); + //~^ ERROR mismatched types + //~| expected type `i32` + //~| found associated type `::T` + //~| expected `i32`, found associated type + + let mut x = (hide(0_u32), hide(0_i32)); + x = (x.1, + //~^ ERROR mismatched types + //~| expected `u32`, found `i32` + x.0); + //~^ ERROR mismatched types + //~| expected `i32`, found `u32` +} diff --git a/tests/ui/impl-trait/equality2.stderr b/tests/ui/impl-trait/equality2.stderr new file mode 100644 index 000000000..e399a6102 --- /dev/null +++ b/tests/ui/impl-trait/equality2.stderr @@ -0,0 +1,75 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/equality2.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/equality2.rs:25:18 + | +LL | fn hide(x: T) -> impl Foo { + | -------- the found opaque type +... +LL | let _: u32 = hide(0_u32); + | --- ^^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl Foo` + +error[E0308]: mismatched types + --> $DIR/equality2.rs:31:18 + | +LL | fn hide(x: T) -> impl Foo { + | -------- the found opaque type +... +LL | let _: i32 = Leak::leak(hide(0_i32)); + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found associated type + | | + | expected due to this + | + = note: expected type `i32` + found associated type `::T` +help: consider constraining the associated type `::T` to `i32` + | +LL | fn hide(x: T) -> impl Foo { + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/equality2.rs:38:10 + | +LL | fn hide(x: T) -> impl Foo { + | -------- + | | + | the expected opaque type + | the found opaque type +... +LL | x = (x.1, + | ^^^ expected `u32`, found `i32` + | + = note: expected opaque type `impl Foo` (`u32`) + found opaque type `impl Foo` (`i32`) + +error[E0308]: mismatched types + --> $DIR/equality2.rs:41:10 + | +LL | fn hide(x: T) -> impl Foo { + | -------- + | | + | the expected opaque type + | the found opaque type +... +LL | x.0); + | ^^^ expected `i32`, found `u32` + | + = note: expected opaque type `impl Foo` (`i32`) + found opaque type `impl Foo` (`u32`) + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/example-calendar.rs b/tests/ui/impl-trait/example-calendar.rs new file mode 100644 index 000000000..da45f0d13 --- /dev/null +++ b/tests/ui/impl-trait/example-calendar.rs @@ -0,0 +1,840 @@ +// run-pass + +#![feature(fn_traits, + step_trait, + unboxed_closures, +)] + +//! Derived from: . +//! +//! Originally converted to Rust by [Daniel Keep](https://github.com/DanielKeep). + +use std::fmt::Write; + +/// Date representation. +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +struct NaiveDate(i32, u32, u32); + +impl NaiveDate { + pub fn from_ymd(y: i32, m: u32, d: u32) -> NaiveDate { + assert!(1 <= m && m <= 12, "m = {:?}", m); + assert!(1 <= d && d <= NaiveDate(y, m, 1).days_in_month(), "d = {:?}", d); + NaiveDate(y, m, d) + } + + pub fn year(&self) -> i32 { + self.0 + } + + pub fn month(&self) -> u32 { + self.1 + } + + pub fn day(&self) -> u32 { + self.2 + } + + pub fn succ(&self) -> NaiveDate { + let (mut y, mut m, mut d, n) = ( + self.year(), self.month(), self.day()+1, self.days_in_month()); + if d > n { + d = 1; + m += 1; + } + if m > 12 { + m = 1; + y += 1; + } + NaiveDate::from_ymd(y, m, d) + } + + pub fn weekday(&self) -> Weekday { + use Weekday::*; + + // 0 = Sunday + let year = self.year(); + let dow_jan_1 = (year*365 + ((year-1) / 4) - ((year-1) / 100) + ((year-1) / 400)) % 7; + let dow = (dow_jan_1 + (self.day_of_year() as i32 - 1)) % 7; + [Sun, Mon, Tue, Wed, Thu, Fri, Sat][dow as usize] + } + + pub fn isoweekdate(&self) -> (i32, u32, Weekday) { + let first_dow_mon_0 = self.year_first_day_of_week().num_days_from_monday(); + + // Work out this date's DOtY and week number, not including year adjustment. + let doy_0 = self.day_of_year() - 1; + let mut week_mon_0: i32 = ((first_dow_mon_0 + doy_0) / 7) as i32; + + if self.first_week_in_prev_year() { + week_mon_0 -= 1; + } + + let weeks_in_year = self.last_week_number(); + + // Work out the final result. + // If the week is `-1` or `>= weeks_in_year`, we will need to adjust the year. + let year = self.year(); + let wd = self.weekday(); + + if week_mon_0 < 0 { + (year - 1, NaiveDate::from_ymd(year - 1, 1, 1).last_week_number(), wd) + } else if week_mon_0 >= weeks_in_year as i32 { + (year + 1, (week_mon_0 + 1 - weeks_in_year as i32) as u32, wd) + } else { + (year, (week_mon_0 + 1) as u32, wd) + } + } + + fn first_week_in_prev_year(&self) -> bool { + let first_dow_mon_0 = self.year_first_day_of_week().num_days_from_monday(); + + // Any day in the year *before* the first Monday of that year + // is considered to be in the last week of the previous year, + // assuming the first week has *less* than four days in it. + // Adjust the week appropriately. + ((7 - first_dow_mon_0) % 7) < 4 + } + + fn year_first_day_of_week(&self) -> Weekday { + NaiveDate::from_ymd(self.year(), 1, 1).weekday() + } + + fn weeks_in_year(&self) -> u32 { + let days_in_last_week = self.year_first_day_of_week().num_days_from_monday() + 1; + if days_in_last_week >= 4 { 53 } else { 52 } + } + + fn last_week_number(&self) -> u32 { + let wiy = self.weeks_in_year(); + if self.first_week_in_prev_year() { wiy - 1 } else { wiy } + } + + fn day_of_year(&self) -> u32 { + (1..self.1).map(|m| NaiveDate::from_ymd(self.year(), m, 1).days_in_month()) + .fold(0, |a,b| a+b) + self.day() + } + + fn is_leap_year(&self) -> bool { + let year = self.year(); + if year % 4 != 0 { + return false + } else if year % 100 != 0 { + return true + } else if year % 400 != 0 { + return false + } else { + return true + } + } + + fn days_in_month(&self) -> u32 { + match self.month() { + /* Jan */ 1 => 31, + /* Feb */ 2 => if self.is_leap_year() { 29 } else { 28 }, + /* Mar */ 3 => 31, + /* Apr */ 4 => 30, + /* May */ 5 => 31, + /* Jun */ 6 => 30, + /* Jul */ 7 => 31, + /* Aug */ 8 => 31, + /* Sep */ 9 => 30, + /* Oct */ 10 => 31, + /* Nov */ 11 => 30, + /* Dec */ 12 => 31, + _ => unreachable!() + } + } +} + +impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate { + type Output = NaiveDate; + + fn add(self, other: &'b NaiveDate) -> NaiveDate { + assert_eq!(*other, NaiveDate(0, 0, 1)); + self.succ() + } +} + +impl std::iter::Step for NaiveDate { + fn steps_between(_: &Self, _: &Self) -> Option { + unimplemented!() + } + + fn forward_checked(start: Self, n: usize) -> Option { + Some((0..n).fold(start, |x, _| x.succ())) + } + + fn backward_checked(_: Self, _: usize) -> Option { + unimplemented!() + } +} + +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum Weekday { + Mon, + Tue, + Wed, + Thu, + Fri, + Sat, + Sun, +} + +impl Weekday { + pub fn num_days_from_monday(&self) -> u32 { + use Weekday::*; + match *self { + Mon => 0, + Tue => 1, + Wed => 2, + Thu => 3, + Fri => 4, + Sat => 5, + Sun => 6, + } + } + + pub fn num_days_from_sunday(&self) -> u32 { + use Weekday::*; + match *self { + Sun => 0, + Mon => 1, + Tue => 2, + Wed => 3, + Thu => 4, + Fri => 5, + Sat => 6, + } + } +} + +/// `GroupBy` implementation. +struct GroupBy { + it: std::iter::Peekable, + f: F, +} + +impl Clone for GroupBy +where + It: Iterator + Clone, + It::Item: Clone, + F: Clone, +{ + fn clone(&self) -> Self { + GroupBy { + it: self.it.clone(), + f: self.f.clone(), + } + } +} + +impl<'a, G, It: 'a, F: 'a> Iterator for GroupBy +where It: Iterator + Clone, + It::Item: Clone, + F: Clone + FnMut(&It::Item) -> G, + G: Eq + Clone +{ + type Item = (G, InGroup, F, G>); + + fn next(&mut self) -> Option { + self.it.peek().map(&mut self.f).map(|key| { + let start = self.it.clone(); + while let Some(k) = self.it.peek().map(&mut self.f) { + if key != k { + break; + } + self.it.next(); + } + + (key.clone(), InGroup { + it: start, + f: self.f.clone(), + g: key + }) + }) + } +} + +#[derive(Copy, Clone)] +struct InGroup { + it: It, + f: F, + g: G +} + +impl G, G: Eq> Iterator for InGroup { + type Item = It::Item; + + fn next(&mut self) -> Option { + self.it.next().and_then(|x| { + if (self.f)(&x) == self.g { Some(x) } else { None } + }) + } +} + +trait IteratorExt: Iterator + Sized { + fn group_by(self, f: F) -> GroupBy + where F: Clone + FnMut(&Self::Item) -> G, + G: Eq + { + GroupBy { it: self.peekable(), f } + } + + fn join(mut self, sep: &str) -> String + where Self::Item: std::fmt::Display { + let mut s = String::new(); + if let Some(e) = self.next() { + write!(s, "{}", e).unwrap(); + for e in self { + s.push_str(sep); + write!(s, "{}", e).unwrap(); + } + } + s + } + + // HACK(eddyb): only needed because `impl Trait` can't be + // used with trait methods: `.foo()` becomes `.__(foo)`. + fn __(self, f: F) -> R + where F: FnOnce(Self) -> R { + f(self) + } +} + +impl IteratorExt for It where It: Iterator {} + +/// Generates an iterator that yields exactly `n` spaces. +fn spaces(n: usize) -> std::iter::Take> { + std::iter::repeat(' ').take(n) +} + +fn test_spaces() { + assert_eq!(spaces(0).collect::(), ""); + assert_eq!(spaces(10).collect::(), " ") +} + +/// Returns an iterator of dates in a given year. +fn dates_in_year(year: i32) -> impl Iterator+Clone { + InGroup { + it: NaiveDate::from_ymd(year, 1, 1).., + f: |d: &NaiveDate| d.year(), + g: year + } +} + +fn test_dates_in_year() { + { + let mut dates = dates_in_year(2013); + assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 1))); + + // Check increment. + assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 2))); + + // Check monthly roll-over. + for _ in 3..31 { + assert!(dates.next() != None); + } + + assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 31))); + assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 2, 1))); + } + + { + // Check length of year. + let mut dates = dates_in_year(2013); + for _ in 0..365 { + assert!(dates.next() != None); + } + assert_eq!(dates.next(), None); + } + + { + // Check length of leap year. + let mut dates = dates_in_year(1984); + for _ in 0..366 { + assert!(dates.next() != None); + } + assert_eq!(dates.next(), None); + } +} + +/// Convenience trait for verifying that a given type iterates over +/// `NaiveDate`s. +trait DateIterator: Iterator + Clone {} +impl DateIterator for It where It: Iterator + Clone {} + +fn test_group_by() { + let input = [ + [1, 1], + [1, 1], + [1, 2], + [2, 2], + [2, 3], + [2, 3], + [3, 3] + ]; + + let by_x = input.iter().cloned().group_by(|a| a[0]); + let expected_1: &[&[[i32; 2]]] = &[ + &[[1, 1], [1, 1], [1, 2]], + &[[2, 2], [2, 3], [2, 3]], + &[[3, 3]] + ]; + for ((_, a), b) in by_x.zip(expected_1.iter().cloned()) { + assert_eq!(&a.collect::>()[..], b); + } + + let by_y = input.iter().cloned().group_by(|a| a[1]); + let expected_2: &[&[[i32; 2]]] = &[ + &[[1, 1], [1, 1]], + &[[1, 2], [2, 2]], + &[[2, 3], [2, 3], [3, 3]] + ]; + for ((_, a), b) in by_y.zip(expected_2.iter().cloned()) { + assert_eq!(&a.collect::>()[..], b); + } +} + +/// Groups an iterator of dates by month. +fn by_month(it: impl Iterator + Clone) + -> impl Iterator + Clone)> + Clone +{ + it.group_by(|d| d.month()) +} + +fn test_by_month() { + let mut months = dates_in_year(2013).__(by_month); + for (month, (_, mut date)) in (1..13).zip(&mut months) { + assert_eq!(date.nth(0).unwrap(), NaiveDate::from_ymd(2013, month, 1)); + } + assert!(months.next().is_none()); +} + +/// Groups an iterator of dates by week. +fn by_week(it: impl DateIterator) + -> impl Iterator + Clone +{ + // We go forward one day because `isoweekdate` considers the week to start on a Monday. + it.group_by(|d| d.succ().isoweekdate().1) +} + +fn test_isoweekdate() { + fn weeks_uniq(year: i32) -> Vec<((i32, u32), u32)> { + let mut weeks = dates_in_year(year).map(|d| d.isoweekdate()) + .map(|(y,w,_)| (y,w)); + let mut result = vec![]; + let mut accum = (weeks.next().unwrap(), 1); + for yw in weeks { + if accum.0 == yw { + accum.1 += 1; + } else { + result.push(accum); + accum = (yw, 1); + } + } + result.push(accum); + result + } + + let wu_1984 = weeks_uniq(1984); + assert_eq!(&wu_1984[..2], &[((1983, 52), 1), ((1984, 1), 7)]); + assert_eq!(&wu_1984[wu_1984.len()-2..], &[((1984, 52), 7), ((1985, 1), 1)]); + + let wu_2013 = weeks_uniq(2013); + assert_eq!(&wu_2013[..2], &[((2013, 1), 6), ((2013, 2), 7)]); + assert_eq!(&wu_2013[wu_2013.len()-2..], &[((2013, 52), 7), ((2014, 1), 2)]); + + let wu_2015 = weeks_uniq(2015); + assert_eq!(&wu_2015[..2], &[((2015, 1), 4), ((2015, 2), 7)]); + assert_eq!(&wu_2015[wu_2015.len()-2..], &[((2015, 52), 7), ((2015, 53), 4)]); +} + +fn test_by_week() { + let mut weeks = dates_in_year(2013).__(by_week); + assert_eq!( + &*weeks.next().unwrap().1.collect::>(), + &[ + NaiveDate::from_ymd(2013, 1, 1), + NaiveDate::from_ymd(2013, 1, 2), + NaiveDate::from_ymd(2013, 1, 3), + NaiveDate::from_ymd(2013, 1, 4), + NaiveDate::from_ymd(2013, 1, 5), + ] + ); + assert_eq!( + &*weeks.next().unwrap().1.collect::>(), + &[ + NaiveDate::from_ymd(2013, 1, 6), + NaiveDate::from_ymd(2013, 1, 7), + NaiveDate::from_ymd(2013, 1, 8), + NaiveDate::from_ymd(2013, 1, 9), + NaiveDate::from_ymd(2013, 1, 10), + NaiveDate::from_ymd(2013, 1, 11), + NaiveDate::from_ymd(2013, 1, 12), + ] + ); + assert_eq!(weeks.next().unwrap().1.nth(0).unwrap(), NaiveDate::from_ymd(2013, 1, 13)); +} + +/// The number of columns per day in the formatted output. +const COLS_PER_DAY: u32 = 3; + +/// The number of columns per week in the formatted output. +const COLS_PER_WEEK: u32 = 7 * COLS_PER_DAY; + +/// Formats an iterator of weeks into an iterator of strings. +fn format_weeks(it: impl Iterator) -> impl Iterator { + it.map(|week| { + let mut buf = String::with_capacity((COLS_PER_DAY * COLS_PER_WEEK + 2) as usize); + + // Format each day into its own cell and append to target string. + let mut last_day = 0; + let mut first = true; + for d in week { + last_day = d.weekday().num_days_from_sunday(); + + // Insert enough filler to align the first day with its respective day-of-week. + if first { + buf.extend(spaces((COLS_PER_DAY * last_day) as usize)); + first = false; + } + + write!(buf, " {:>2}", d.day()).unwrap(); + } + + // Insert more filler at the end to fill up the remainder of the week, + // if its a short week (e.g., at the end of the month). + buf.extend(spaces((COLS_PER_DAY * (6 - last_day)) as usize)); + buf + }) +} + +fn test_format_weeks() { + let jan_2013 = dates_in_year(2013) + .__(by_month).next() // pick January 2013 for testing purposes + // NOTE: This `map` is because `next` returns an `Option<_>`. + .map(|(_, month)| + month.__(by_week) + .map(|(_, weeks)| weeks) + .__(format_weeks) + .join("\n")); + + assert_eq!( + jan_2013.as_ref().map(|s| &**s), + Some(" 1 2 3 4 5\n\ + \x20 6 7 8 9 10 11 12\n\ + \x2013 14 15 16 17 18 19\n\ + \x2020 21 22 23 24 25 26\n\ + \x2027 28 29 30 31 ") + ); +} + +/// Formats the name of a month, centered on `COLS_PER_WEEK`. +fn month_title(month: u32) -> String { + const MONTH_NAMES: &'static [&'static str] = &[ + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + ]; + assert_eq!(MONTH_NAMES.len(), 12); + + // Determine how many spaces before and after the month name + // we need to center it over the formatted weeks in the month. + let name = MONTH_NAMES[(month - 1) as usize]; + assert!(name.len() < COLS_PER_WEEK as usize); + let before = (COLS_PER_WEEK as usize - name.len()) / 2; + let after = COLS_PER_WEEK as usize - name.len() - before; + + // Note: being slightly more verbose to avoid extra allocations. + let mut result = String::with_capacity(COLS_PER_WEEK as usize); + result.extend(spaces(before)); + result.push_str(name); + result.extend(spaces(after)); + result +} + +fn test_month_title() { + assert_eq!(month_title(1).len(), COLS_PER_WEEK as usize); +} + +/// Formats a month. +fn format_month(it: impl DateIterator) -> impl Iterator { + let mut month_days = it.peekable(); + let title = month_title(month_days.peek().unwrap().month()); + + Some(title).into_iter() + .chain(month_days.__(by_week) + .map(|(_, week)| week) + .__(format_weeks)) +} + +fn test_format_month() { + let month_fmt = dates_in_year(2013) + .__(by_month).next() // Pick January as a test case + .map(|(_, days)| days.into_iter() + .__(format_month) + .join("\n")); + + assert_eq!( + month_fmt.as_ref().map(|s| &**s), + Some(" January \n\ + \x20 1 2 3 4 5\n\ + \x20 6 7 8 9 10 11 12\n\ + \x2013 14 15 16 17 18 19\n\ + \x2020 21 22 23 24 25 26\n\ + \x2027 28 29 30 31 ") + ); +} + +/// Formats an iterator of months. +fn format_months(it: impl Iterator) + -> impl Iterator> +{ + it.map(format_month) +} + +/// Takes an iterator of iterators of strings; the sub-iterators are consumed +/// in lock-step, with their elements joined together. +trait PasteBlocks: Iterator + Sized +where Self::Item: Iterator { + fn paste_blocks(self, sep_width: usize) -> PasteBlocksIter { + PasteBlocksIter { + iters: self.collect(), + cache: vec![], + col_widths: None, + sep_width: sep_width, + } + } +} + +impl PasteBlocks for It where It: Iterator, It::Item: Iterator {} + +struct PasteBlocksIter +where StrIt: Iterator { + iters: Vec, + cache: Vec>, + col_widths: Option>, + sep_width: usize, +} + +impl Iterator for PasteBlocksIter +where StrIt: Iterator { + type Item = String; + + fn next(&mut self) -> Option { + self.cache.clear(); + + // `cache` is now the next line from each iterator. + self.cache.extend(self.iters.iter_mut().map(|it| it.next())); + + // If every line in `cache` is `None`, we have nothing further to do. + if self.cache.iter().all(|e| e.is_none()) { return None } + + // Get the column widths if we haven't already. + let col_widths = match self.col_widths { + Some(ref v) => &**v, + None => { + self.col_widths = Some(self.cache.iter() + .map(|ms| ms.as_ref().map(|s| s.len()).unwrap_or(0)) + .collect()); + &**self.col_widths.as_ref().unwrap() + } + }; + + // Fill in any `None`s with spaces. + let mut parts = col_widths.iter().cloned().zip(self.cache.iter_mut()) + .map(|(w,ms)| ms.take().unwrap_or_else(|| spaces(w).collect())); + + // Join them all together. + let first = parts.next().unwrap_or(String::new()); + let sep_width = self.sep_width; + Some(parts.fold(first, |mut accum, next| { + accum.extend(spaces(sep_width)); + accum.push_str(&next); + accum + })) + } +} + +fn test_paste_blocks() { + let row = dates_in_year(2013) + .__(by_month).map(|(_, days)| days) + .take(3) + .__(format_months) + .paste_blocks(1) + .join("\n"); + assert_eq!( + &*row, + " January February March \n\ + \x20 1 2 3 4 5 1 2 1 2\n\ + \x20 6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9\n\ + \x2013 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16\n\ + \x2020 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23\n\ + \x2027 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30\n\ + \x20 31 " + ); +} + +/// Produces an iterator that yields `n` elements at a time. +trait Chunks: Iterator + Sized { + fn chunks(self, n: usize) -> ChunksIter { + assert!(n > 0); + ChunksIter { + it: self, + n: n, + } + } +} + +impl Chunks for It where It: Iterator {} + +struct ChunksIter +where It: Iterator { + it: It, + n: usize, +} + +// Note: `chunks` in Rust is more-or-less impossible without overhead of some kind. +// Aliasing rules mean you need to add dynamic borrow checking, and the design of +// `Iterator` means that you need to have the iterator's state kept in an allocation +// that is jointly owned by the iterator itself and the sub-iterator. +// As such, I've chosen to cop-out and just heap-allocate each chunk. + +impl Iterator for ChunksIter +where It: Iterator { + type Item = Vec; + + fn next(&mut self) -> Option> { + let first = self.it.next()?; + + let mut result = Vec::with_capacity(self.n); + result.push(first); + + Some((&mut self.it).take(self.n-1) + .fold(result, |mut acc, next| { acc.push(next); acc })) + } +} + +fn test_chunks() { + let r = &[1, 2, 3, 4, 5, 6, 7]; + let c = r.iter().cloned().chunks(3).collect::>(); + assert_eq!(&*c, &[vec![1, 2, 3], vec![4, 5, 6], vec![7]]); +} + +/// Formats a year. +fn format_year(year: i32, months_per_row: usize) -> String { + const COL_SPACING: usize = 1; + + // Start by generating all dates for the given year. + dates_in_year(year) + + // Group them by month and throw away month number. + .__(by_month).map(|(_, days)| days) + + // Group the months into horizontal rows. + .chunks(months_per_row) + + // Format each row... + .map(|r| r.into_iter() + // ... by formatting each month ... + .__(format_months) + + // ... and horizontally pasting each respective month's lines together. + .paste_blocks(COL_SPACING) + .join("\n") + ) + + // Insert a blank line between each row. + .join("\n\n") +} + +fn test_format_year() { + const MONTHS_PER_ROW: usize = 3; + + macro_rules! assert_eq_cal { + ($lhs:expr, $rhs:expr) => { + if $lhs != $rhs { + println!("got:\n```\n{}\n```\n", $lhs.replace(" ", ".")); + println!("expected:\n```\n{}\n```", $rhs.replace(" ", ".")); + panic!("calendars didn't match!"); + } + } + } + + assert_eq_cal!(&format_year(1984, MONTHS_PER_ROW), "\ +\x20 January February March \n\ +\x20 1 2 3 4 5 6 7 1 2 3 4 1 2 3\n\ +\x20 8 9 10 11 12 13 14 5 6 7 8 9 10 11 4 5 6 7 8 9 10\n\ +\x2015 16 17 18 19 20 21 12 13 14 15 16 17 18 11 12 13 14 15 16 17\n\ +\x2022 23 24 25 26 27 28 19 20 21 22 23 24 25 18 19 20 21 22 23 24\n\ +\x2029 30 31 26 27 28 29 25 26 27 28 29 30 31\n\ +\n\ +\x20 April May June \n\ +\x20 1 2 3 4 5 6 7 1 2 3 4 5 1 2\n\ +\x20 8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9\n\ +\x2015 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16\n\ +\x2022 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23\n\ +\x2029 30 27 28 29 30 31 24 25 26 27 28 29 30\n\ +\n\ +\x20 July August September \n\ +\x20 1 2 3 4 5 6 7 1 2 3 4 1\n\ +\x20 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8\n\ +\x2015 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15\n\ +\x2022 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22\n\ +\x2029 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29\n\ +\x20 30 \n\ +\n\ +\x20 October November December \n\ +\x20 1 2 3 4 5 6 1 2 3 1\n\ +\x20 7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8\n\ +\x2014 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15\n\ +\x2021 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22\n\ +\x2028 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29\n\ +\x20 30 31 "); + + assert_eq_cal!(&format_year(2015, MONTHS_PER_ROW), "\ +\x20 January February March \n\ +\x20 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7\n\ +\x20 4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14\n\ +\x2011 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21\n\ +\x2018 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28\n\ +\x2025 26 27 28 29 30 31 29 30 31 \n\ +\n\ +\x20 April May June \n\ +\x20 1 2 3 4 1 2 1 2 3 4 5 6\n\ +\x20 5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13\n\ +\x2012 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20\n\ +\x2019 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27\n\ +\x2026 27 28 29 30 24 25 26 27 28 29 30 28 29 30 \n\ +\x20 31 \n\ +\n\ +\x20 July August September \n\ +\x20 1 2 3 4 1 1 2 3 4 5\n\ +\x20 5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12\n\ +\x2012 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19\n\ +\x2019 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26\n\ +\x2026 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30 \n\ +\x20 30 31 \n\ +\n\ +\x20 October November December \n\ +\x20 1 2 3 1 2 3 4 5 6 7 1 2 3 4 5\n\ +\x20 4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12\n\ +\x2011 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19\n\ +\x2018 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26\n\ +\x2025 26 27 28 29 30 31 29 30 27 28 29 30 31 "); +} + +fn main() { + // Run tests. + test_spaces(); + test_dates_in_year(); + test_group_by(); + test_by_month(); + test_isoweekdate(); + test_by_week(); + test_format_weeks(); + test_month_title(); + test_format_month(); + test_paste_blocks(); + test_chunks(); + test_format_year(); +} diff --git a/tests/ui/impl-trait/example-st.rs b/tests/ui/impl-trait/example-st.rs new file mode 100644 index 000000000..4e1aa3a08 --- /dev/null +++ b/tests/ui/impl-trait/example-st.rs @@ -0,0 +1,30 @@ +// run-pass + +struct State; +type Error = (); + +trait Bind { + type Output; + fn bind(self, f: F) -> Self::Output; +} + +fn bind(mut a: A, mut f: F) + -> impl FnMut(&mut State) -> Result +where F: FnMut(T) -> B, + A: FnMut(&mut State) -> Result, + B: FnMut(&mut State) -> Result +{ + move |state | { + let r = a(state)?; + f(r)(state) + } +} + +fn atom(x: T) -> impl FnMut(&mut State) -> Result { + let mut x = Some(x); + move |_| x.take().map_or(Err(()), Ok) +} + +fn main() { + assert_eq!(bind(atom(5), |x| atom(x > 4))(&mut State), Ok(true)); +} diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs new file mode 100644 index 000000000..1aa23c608 --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/const-args.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Usizer { + fn m(self) -> usize; +} + +fn f(u: impl Usizer) -> usize { + N + u.m() +} + +struct Usizable; + +impl Usizer for Usizable { + fn m(self) -> usize { + 16 + } +} + +fn main() { + assert_eq!(f::<4usize>(Usizable), 20usize); +} diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs new file mode 100644 index 000000000..3b1024d61 --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.rs @@ -0,0 +1,5 @@ +fn foo(_f: impl AsRef) {} + +fn main() { + foo::("".to_string()); //~ ERROR E0107 +} diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr new file mode 100644 index 000000000..c8b82783e --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr @@ -0,0 +1,18 @@ +error[E0107]: this function takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/explicit-generic-args-for-impl.rs:4:5 + | +LL | foo::("".to_string()); + | ^^^ ------ help: remove this generic argument + | | + | expected 1 generic argument + | +note: function defined here, with 1 generic parameter: `T` + --> $DIR/explicit-generic-args-for-impl.rs:1:4 + | +LL | fn foo(_f: impl AsRef) {} + | ^^^ - + = note: `impl Trait` cannot be explicitly specified as a generic argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs new file mode 100644 index 000000000..99e0931ab --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args.rs @@ -0,0 +1,7 @@ +// check-pass + +fn foo(_f: impl AsRef) {} + +fn main() { + foo::("".to_string()); +} diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs new file mode 100644 index 000000000..987df4997 --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs @@ -0,0 +1,7 @@ +// check-pass + +fn f(_: impl AsRef, _: impl AsRef) {} + +fn main() { + f::<[u8]>("a", b"a"); +} diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs new file mode 100644 index 000000000..a93bdb178 --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.rs @@ -0,0 +1,6 @@ +fn f(_: impl AsRef, _: impl AsRef) {} + +fn main() { + f::<[u8]>("a", b"a"); + //~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied +} diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr new file mode 100644 index 000000000..9d6db88d3 --- /dev/null +++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/not-enough-args.rs:4:5 + | +LL | f::<[u8]>("a", b"a"); + | ^ ---- supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `T`, `U` + --> $DIR/not-enough-args.rs:1:4 + | +LL | fn f(_: impl AsRef, _: impl AsRef) {} + | ^ - - +help: add missing generic argument + | +LL | f::<[u8], U>("a", b"a"); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/extra-item.rs b/tests/ui/impl-trait/extra-item.rs new file mode 100644 index 000000000..d82237cce --- /dev/null +++ b/tests/ui/impl-trait/extra-item.rs @@ -0,0 +1,10 @@ +// aux-build:extra-item.rs +// compile-flags:--extern extra_item + +struct S; + +impl extra_item::MyTrait for S { + fn extra() {} //~ ERROR method `extra` is not a member of trait `extra_item::MyTrait` +} + +fn main() {} diff --git a/tests/ui/impl-trait/extra-item.stderr b/tests/ui/impl-trait/extra-item.stderr new file mode 100644 index 000000000..728bcc0aa --- /dev/null +++ b/tests/ui/impl-trait/extra-item.stderr @@ -0,0 +1,9 @@ +error[E0407]: method `extra` is not a member of trait `extra_item::MyTrait` + --> $DIR/extra-item.rs:7:5 + | +LL | fn extra() {} + | ^^^^^^^^^^^^^ not a member of trait `extra_item::MyTrait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0407`. diff --git a/tests/ui/impl-trait/fallback.rs b/tests/ui/impl-trait/fallback.rs new file mode 100644 index 000000000..1e6eb5bb3 --- /dev/null +++ b/tests/ui/impl-trait/fallback.rs @@ -0,0 +1,9 @@ +// check-pass + +fn take_edge_counters( + x: &mut Option>, +) -> Option> { + x.take().map_or(None, |m| Some(m.into_iter())) +} + +fn main() {} diff --git a/tests/ui/impl-trait/fallback_inference.rs b/tests/ui/impl-trait/fallback_inference.rs new file mode 100644 index 000000000..98f0bd1af --- /dev/null +++ b/tests/ui/impl-trait/fallback_inference.rs @@ -0,0 +1,7 @@ +use std::marker::PhantomData; + +fn weird() -> PhantomData { + PhantomData //~ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/impl-trait/fallback_inference.stderr b/tests/ui/impl-trait/fallback_inference.stderr new file mode 100644 index 000000000..4ac3c238f --- /dev/null +++ b/tests/ui/impl-trait/fallback_inference.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/fallback_inference.rs:4:5 + | +LL | PhantomData + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` + | +help: consider specifying the generic argument + | +LL | PhantomData:: + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/feature-self-return-type.rs b/tests/ui/impl-trait/feature-self-return-type.rs new file mode 100644 index 000000000..51877e9cc --- /dev/null +++ b/tests/ui/impl-trait/feature-self-return-type.rs @@ -0,0 +1,102 @@ +// edition:2018 +#![feature(impl_trait_projections)] + +// This test checks that we emit the correct borrowck error when `Self` or a projection is used as +// a return type. See #61949 for context. + +mod with_self { + pub struct Foo<'a> { + pub bar: &'a i32, + } + + impl<'a> Foo<'a> { + pub fn new(_bar: &'a i32) -> impl Into { + Foo { + bar: &22 + } + } + } + + fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).into() + //~^ ERROR `bar` does not live long enough + }; + drop(x); + } +} + +struct Foo(T); + +trait FooLike { + type Output; +} + +impl FooLike for Foo { + type Output = T; +} + +mod impl_trait { + use super::*; + + trait Trait { + type Assoc; + + fn make_assoc(self) -> Self::Assoc; + } + + /// `T::Assoc` can't be normalized any further here. + fn foo(x: T) -> impl FooLike { + Foo(x.make_assoc()) + } + + impl<'a> Trait for &'a () { + type Assoc = &'a (); + + fn make_assoc(self) -> &'a () { &() } + } + + fn usage() { + let x = { + let y = (); + foo(&y) + //~^ ERROR `y` does not live long enough + }; + drop(x); + } +} + +// Same with lifetimes in the trait + +mod lifetimes { + use super::*; + + trait Trait<'a> { + type Assoc; + + fn make_assoc(self) -> Self::Assoc; + } + + /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. + fn foo<'a, T: Trait<'a>>(x: T) -> impl FooLike { + Foo(x.make_assoc()) + } + + impl<'a> Trait<'a> for &'a () { + type Assoc = &'a (); + + fn make_assoc(self) -> &'a () { &() } + } + + fn usage() { + let x = { + let y = (); + foo(&y) + //~^ ERROR `y` does not live long enough + }; + drop(x); + } +} + +fn main() { } diff --git a/tests/ui/impl-trait/feature-self-return-type.stderr b/tests/ui/impl-trait/feature-self-return-type.stderr new file mode 100644 index 000000000..601e53b76 --- /dev/null +++ b/tests/ui/impl-trait/feature-self-return-type.stderr @@ -0,0 +1,39 @@ +error[E0597]: `bar` does not live long enough + --> $DIR/feature-self-return-type.rs:23:22 + | +LL | let x = { + | - borrow later stored here +LL | let bar = 22; +LL | Foo::new(&bar).into() + | ^^^^ borrowed value does not live long enough +LL | +LL | }; + | - `bar` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/feature-self-return-type.rs:63:17 + | +LL | let x = { + | - borrow later stored here +LL | let y = (); +LL | foo(&y) + | ^^ borrowed value does not live long enough +LL | +LL | }; + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/feature-self-return-type.rs:95:17 + | +LL | let x = { + | - borrow later stored here +LL | let y = (); +LL | foo(&y) + | ^^ borrowed value does not live long enough +LL | +LL | }; + | - `y` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr new file mode 100644 index 000000000..edf3911e2 --- /dev/null +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied + --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 + | +LL | fn ice() -> impl AsRef { + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr new file mode 100644 index 000000000..30fbba168 --- /dev/null +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -0,0 +1,14 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24 + | +LL | fn ice() -> impl AsRef { + | ^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | fn ice() -> impl AsRef { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs new file mode 100644 index 000000000..bed81c4bc --- /dev/null +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -0,0 +1,12 @@ +// revisions: edition2015 edition2021 +//[edition2021]edition:2021 + +#![allow(warnings)] + +fn ice() -> impl AsRef { + //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782] + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/hidden-lifetimes.rs b/tests/ui/impl-trait/hidden-lifetimes.rs new file mode 100644 index 000000000..ae07c8927 --- /dev/null +++ b/tests/ui/impl-trait/hidden-lifetimes.rs @@ -0,0 +1,63 @@ +// Test to show what happens if we were not careful and allowed invariant +// lifetimes to escape though an impl trait. +// +// Specifically we swap a long lived and short lived reference, giving us a +// dangling pointer. + +use std::cell::RefCell; +use std::rc::Rc; + +trait Swap: Sized { + fn swap(self, other: Self); +} + +impl Swap for &mut T { + fn swap(self, other: Self) { + std::mem::swap(self, other); + } +} + +impl Swap for Rc> { + fn swap(self, other: Self) { + >::swap(&self, &other); + } +} + +// Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and +// `&'a mut &'l T` are the same type. +fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { + x + //~^ ERROR hidden type +} + +fn dangle_ref() -> &'static [i32; 3] { + let mut res = &[4, 5, 6]; + let x = [1, 2, 3]; + hide_ref(&mut res).swap(hide_ref(&mut &x)); + res +} + +// Here we are hiding `'b` making the caller believe that `Rc>` +// and `Rc>` are the same type. +// +// This is different to the previous example because the concrete return type +// only has a single lifetime. +fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + x + //~^ ERROR hidden type +} + +fn dangle_rc_refcell() -> &'static [i32; 3] { + let long = Rc::new(RefCell::new(&[4, 5, 6])); + let x = [1, 2, 3]; + let short = Rc::new(RefCell::new(&x)); + hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short)); + let res: &'static [i32; 3] = *long.borrow(); + res +} + +fn main() { + // both will print nonsense values. + println!("{:?}", dangle_ref()); + println!("{:?}", dangle_rc_refcell()) +} diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.stderr new file mode 100644 index 000000000..3cc47e1e8 --- /dev/null +++ b/tests/ui/impl-trait/hidden-lifetimes.stderr @@ -0,0 +1,29 @@ +error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds + --> $DIR/hidden-lifetimes.rs:29:5 + | +LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { + | -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here +LL | x + | ^ + | +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b { + | ++++ + +error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds + --> $DIR/hidden-lifetimes.rs:46:5 + | +LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + | -- hidden type `Rc>` captures the lifetime `'b` as defined here +LL | x + | ^ + | +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.rs b/tests/ui/impl-trait/hidden-type-is-opaque-2.rs new file mode 100644 index 000000000..970d84120 --- /dev/null +++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.rs @@ -0,0 +1,45 @@ +// This doesn't work, because we don't flow information from opaque types +// into function arguments via the function's generic parameters +// FIXME(oli-obk): make `expected_inputs_for_expected_output` support this + +#![feature(type_alias_impl_trait)] + +fn reify_as() -> Thunk Continuation> { + Thunk::new(|mut cont| { + cont.reify_as(); //~ ERROR type annotations needed + cont + }) +} + +type Tait = impl FnOnce(Continuation) -> Continuation; + +fn reify_as_tait() -> Thunk { + Thunk::new(|mut cont| { + cont.reify_as(); //~ ERROR type annotations needed + cont + }) +} + +#[must_use] +struct Thunk(F); + +impl Thunk { + fn new(f: F) -> Self + where + F: ContFn, + { + Thunk(f) + } +} + +trait ContFn {} + +impl Continuation> ContFn for F {} + +struct Continuation; + +impl Continuation { + fn reify_as(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.stderr b/tests/ui/impl-trait/hidden-type-is-opaque-2.stderr new file mode 100644 index 000000000..957052feb --- /dev/null +++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.stderr @@ -0,0 +1,15 @@ +error[E0282]: type annotations needed + --> $DIR/hidden-type-is-opaque-2.rs:9:9 + | +LL | cont.reify_as(); + | ^^^^ cannot infer type + +error[E0282]: type annotations needed + --> $DIR/hidden-type-is-opaque-2.rs:18:9 + | +LL | cont.reify_as(); + | ^^^^ cannot infer type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/hidden-type-is-opaque.rs b/tests/ui/impl-trait/hidden-type-is-opaque.rs new file mode 100644 index 000000000..72b4028d8 --- /dev/null +++ b/tests/ui/impl-trait/hidden-type-is-opaque.rs @@ -0,0 +1,42 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +fn reify_as() -> Thunk { + Thunk::new(|mut cont| { + cont.reify_as(); + cont + }) +} + +type Tait = impl ContFn; + +fn reify_as_tait() -> Thunk { + Thunk::new(|mut cont| { + cont.reify_as(); + cont + }) +} + +#[must_use] +struct Thunk(F); + +impl Thunk { + fn new(f: F) -> Self + where + F: FnOnce(Continuation) -> Continuation, + { + Thunk(f) + } +} + +trait ContFn {} + +impl Continuation> ContFn for F {} + +struct Continuation; + +impl Continuation { + fn reify_as(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs new file mode 100644 index 000000000..b0aeded0e --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs @@ -0,0 +1,8 @@ +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> impl Debug { + |x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr new file mode 100644 index 000000000..433b76b7a --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds + --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 + | +LL | |x| x + | --- ^ + | | + | hidden type `&u8` captures the anonymous lifetime #1 defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs new file mode 100644 index 000000000..527a4586f --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -0,0 +1,24 @@ +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn d() -> impl Fn() -> (impl Debug + '_) { + //~^ ERROR missing lifetime specifier + || () +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr new file mode 100644 index 000000000..443ffeb55 --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -0,0 +1,51 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-fn-hrtb-bounds.rs:19:38 + | +LL | fn d() -> impl Fn() -> (impl Debug + '_) { + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn d() -> impl Fn() -> (impl Debug + 'static) { + | ~~~~~~~ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:4:41 + | +LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:4:19 + | +LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { + | ^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:9:52 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:9:20 + | +LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ^^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-hrtb-bounds.rs:14:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds.rs:14:20 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | ^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs new file mode 100644 index 000000000..61303a5b2 --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs @@ -0,0 +1,15 @@ +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +fn a() -> impl Fn(&u8) -> impl Debug + '_ { + //~^ ERROR ambiguous `+` in a type + //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + |x| x +} + +fn b() -> impl Fn() -> impl Debug + Send { + //~^ ERROR ambiguous `+` in a type + || () +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr new file mode 100644 index 000000000..cf6e5ef7b --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr @@ -0,0 +1,26 @@ +error: ambiguous `+` in a type + --> $DIR/impl-fn-parsing-ambiguities.rs:4:27 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)` + +error: ambiguous `+` in a type + --> $DIR/impl-fn-parsing-ambiguities.rs:10:24 + | +LL | fn b() -> impl Fn() -> impl Debug + Send { + | ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/impl-fn-parsing-ambiguities.rs:4:40 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^^ + | +note: lifetime declared here + --> $DIR/impl-fn-parsing-ambiguities.rs:4:19 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { + | ^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs new file mode 100644 index 000000000..157786623 --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -0,0 +1,15 @@ +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + //~^ ERROR cannot resolve opaque type + + |x| x + //~^ ERROR concrete type differs from previous defining opaque type use +} + +fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { + a() +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr new file mode 100644 index 000000000..c19420bbb --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -0,0 +1,21 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 + | +LL | |x| x + | ^ expected `impl Debug + '_`, got `&u8` + | +note: previous use here + --> $DIR/impl-fn-predefined-lifetimes.rs:7:5 + | +LL | |x| x + | ^^^^^ + +error[E0720]: cannot resolve opaque type + --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | ^^^^^^^^^^^^^^^ cannot resolve opaque type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/impl-generic-mismatch-ab.rs b/tests/ui/impl-trait/impl-generic-mismatch-ab.rs new file mode 100644 index 000000000..6c9b119de --- /dev/null +++ b/tests/ui/impl-trait/impl-generic-mismatch-ab.rs @@ -0,0 +1,12 @@ +use std::fmt::Debug; + +trait Foo { + fn foo(&self, a: &A, b: &impl Debug); +} + +impl Foo for () { + fn foo(&self, a: &impl Debug, b: &B) { } + //~^ ERROR method `foo` has an incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr b/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr new file mode 100644 index 000000000..db97fc2bd --- /dev/null +++ b/tests/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -0,0 +1,23 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/impl-generic-mismatch-ab.rs:8:32 + | +LL | fn foo(&self, a: &impl Debug, b: &B) { } + | - ^^^^^^^^^^^ + | | | + | | expected type parameter `B`, found type parameter `impl Debug` + | | help: change the parameter type to match the trait: `&B` + | expected type parameter + | +note: type in trait + --> $DIR/impl-generic-mismatch-ab.rs:4:32 + | +LL | fn foo(&self, a: &A, b: &impl Debug); + | ^^ + = note: expected signature `fn(&(), &B, &impl Debug)` + found signature `fn(&(), &impl Debug, &B)` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/impl-generic-mismatch.rs b/tests/ui/impl-trait/impl-generic-mismatch.rs new file mode 100644 index 000000000..fb8bde0d0 --- /dev/null +++ b/tests/ui/impl-trait/impl-generic-mismatch.rs @@ -0,0 +1,41 @@ +use std::fmt::Debug; + +trait Foo { + fn foo(&self, _: &impl Debug); +} + +impl Foo for () { + fn foo(&self, _: &U) { } + //~^ Error method `foo` has incompatible signature for trait +} + +trait Bar { + fn bar(&self, _: &U); +} + +impl Bar for () { + fn bar(&self, _: &impl Debug) { } + //~^ Error method `bar` has incompatible signature for trait +} + +trait Baz { + fn baz(&self, _: &U, _: &T); +} + +impl Baz for () { + fn baz(&self, _: &impl Debug, _: &T) { } + //~^ Error method `baz` has incompatible signature for trait +} + +// With non-local trait (#49841): + +use std::hash::{Hash, Hasher}; + +struct X; + +impl Hash for X { + fn hash(&self, hasher: &mut impl Hasher) {} + //~^ Error method `hash` has incompatible signature for trait +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-generic-mismatch.stderr b/tests/ui/impl-trait/impl-generic-mismatch.stderr new file mode 100644 index 000000000..973b65bfd --- /dev/null +++ b/tests/ui/impl-trait/impl-generic-mismatch.stderr @@ -0,0 +1,55 @@ +error[E0643]: method `foo` has incompatible signature for trait + --> $DIR/impl-generic-mismatch.rs:8:12 + | +LL | fn foo(&self, _: &impl Debug); + | ---------- declaration in trait here +... +LL | fn foo(&self, _: &U) { } + | ^ expected `impl Trait`, found generic parameter + | +help: try removing the generic parameter and using `impl Trait` instead + | +LL - fn foo(&self, _: &U) { } +LL + fn foo(&self, _: &impl Debug) { } + | + +error[E0643]: method `bar` has incompatible signature for trait + --> $DIR/impl-generic-mismatch.rs:17:23 + | +LL | fn bar(&self, _: &U); + | - declaration in trait here +... +LL | fn bar(&self, _: &impl Debug) { } + | ^^^^^^^^^^ expected generic parameter, found `impl Trait` + | +help: try changing the `impl Trait` argument to a generic parameter + | +LL | fn bar(&self, _: &U) { } + | ++++++++++ ~ + +error[E0643]: method `baz` has incompatible signature for trait + --> $DIR/impl-generic-mismatch.rs:26:33 + | +LL | fn baz(&self, _: &U, _: &T); + | - declaration in trait here +... +LL | fn baz(&self, _: &impl Debug, _: &T) { } + | ^^^^^^^^^^ expected generic parameter, found `impl Trait` + | +help: try changing the `impl Trait` argument to a generic parameter + | +LL | fn baz(&self, _: &T, _: &T) { } + | ~~~~~~~~~~~~~~~~~~~~ ~ + +error[E0643]: method `hash` has incompatible signature for trait + --> $DIR/impl-generic-mismatch.rs:37:33 + | +LL | fn hash(&self, hasher: &mut impl Hasher) {} + | ^^^^^^^^^^^ expected generic parameter, found `impl Trait` + --> $SRC_DIR/core/src/hash/mod.rs:LL:COL + | + = note: declaration in trait here + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0643`. diff --git a/tests/ui/impl-trait/impl-trait-in-macro.rs b/tests/ui/impl-trait/impl-trait-in-macro.rs new file mode 100644 index 000000000..3165c9b99 --- /dev/null +++ b/tests/ui/impl-trait/impl-trait-in-macro.rs @@ -0,0 +1,20 @@ +use std::fmt::Debug; + +macro_rules! i { + ($($tr:tt)*) => { impl $($tr)* }; +} + +fn foo(x: i!(Debug), y: i!(Debug)) -> String { + let mut a = x; + a = y; //~ ERROR mismatched + format!("{:?}", a) +} + +trait S {} + +fn much_universe, U: IntoIterator)>>( + _: i!(Debug + Clone), +) { +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-trait-in-macro.stderr b/tests/ui/impl-trait/impl-trait-in-macro.stderr new file mode 100644 index 000000000..7cfbe3447 --- /dev/null +++ b/tests/ui/impl-trait/impl-trait-in-macro.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/impl-trait-in-macro.rs:9:9 + | +LL | ($($tr:tt)*) => { impl $($tr)* }; + | ---- + | | + | expected type parameter + | found type parameter +... +LL | let mut a = x; + | - expected due to this value +LL | a = y; + | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` + | + = note: expected type parameter `impl Debug` (type parameter `impl Debug`) + found type parameter `impl Debug` (type parameter `impl Debug`) + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.rs b/tests/ui/impl-trait/impl-trait-plus-priority.rs new file mode 100644 index 000000000..dfac9c0f1 --- /dev/null +++ b/tests/ui/impl-trait/impl-trait-plus-priority.rs @@ -0,0 +1,49 @@ +// compile-flags: -Z parse-only + +fn f() -> impl A + {} // OK +fn f() -> impl A + B {} // OK +fn f() -> dyn A + B {} // OK +fn f() -> A + B {} // OK + +impl S { + fn f(self) -> impl A + { // OK + let _ = |a, b| -> impl A + {}; // OK + } + fn f(self) -> impl A + B { // OK + let _ = |a, b| -> impl A + B {}; // OK + } + fn f(self) -> dyn A + B { // OK + let _ = |a, b| -> dyn A + B {}; // OK + } + fn f(self) -> A + B { // OK + let _ = |a, b| -> A + B {}; // OK + } +} + +type A = fn() -> impl A +; +//~^ ERROR ambiguous `+` in a type +type A = fn() -> impl A + B; +//~^ ERROR ambiguous `+` in a type +type A = fn() -> dyn A + B; +//~^ ERROR ambiguous `+` in a type +type A = fn() -> A + B; +//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A` + +type A = Fn() -> impl A +; +//~^ ERROR ambiguous `+` in a type +type A = Fn() -> impl A + B; +//~^ ERROR ambiguous `+` in a type +type A = Fn() -> dyn A + B; +//~^ ERROR ambiguous `+` in a type +type A = Fn() -> A + B; // OK, interpreted as `(Fn() -> A) + B` for compatibility + +type A = &impl A +; +//~^ ERROR ambiguous `+` in a type +type A = &impl A + B; +//~^ ERROR ambiguous `+` in a type +type A = &dyn A + B; +//~^ ERROR ambiguous `+` in a type +type A = &A + B; +//~^ ERROR expected a path on the left-hand side of `+`, not `&A` + +fn main() {} diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.stderr b/tests/ui/impl-trait/impl-trait-plus-priority.stderr new file mode 100644 index 000000000..205d9b0b7 --- /dev/null +++ b/tests/ui/impl-trait/impl-trait-plus-priority.stderr @@ -0,0 +1,69 @@ +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:23:18 + | +LL | type A = fn() -> impl A +; + | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:25:18 + | +LL | type A = fn() -> impl A + B; + | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:27:18 + | +LL | type A = fn() -> dyn A + B; + | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)` + +error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A` + --> $DIR/impl-trait-plus-priority.rs:29:10 + | +LL | type A = fn() -> A + B; + | ^^^^^^^^^^^^^ perhaps you forgot parentheses? + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:32:18 + | +LL | type A = Fn() -> impl A +; + | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:34:18 + | +LL | type A = Fn() -> impl A + B; + | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:36:18 + | +LL | type A = Fn() -> dyn A + B; + | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:40:11 + | +LL | type A = &impl A +; + | ^^^^^^^^ help: use parentheses to disambiguate: `(impl A)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:42:11 + | +LL | type A = &impl A + B; + | ^^^^^^^^^^ help: use parentheses to disambiguate: `(impl A + B)` + +error: ambiguous `+` in a type + --> $DIR/impl-trait-plus-priority.rs:44:11 + | +LL | type A = &dyn A + B; + | ^^^^^^^^^ help: use parentheses to disambiguate: `(dyn A + B)` + +error[E0178]: expected a path on the left-hand side of `+`, not `&A` + --> $DIR/impl-trait-plus-priority.rs:46:10 + | +LL | type A = &A + B; + | ^^^^^^ help: try adding parentheses: `&(A + B)` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0178`. diff --git a/tests/ui/impl-trait/impl_fn_associativity.rs b/tests/ui/impl-trait/impl_fn_associativity.rs new file mode 100644 index 000000000..71a8f9c77 --- /dev/null +++ b/tests/ui/impl-trait/impl_fn_associativity.rs @@ -0,0 +1,26 @@ +// run-pass +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +fn f_debug() -> impl Fn() -> impl Debug { + || () +} + +fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { + || f_debug() +} + +fn multi() -> impl Fn() -> (impl Debug + Send) { + || () +} + +fn main() { + // Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug` + let debug = ff_debug()()(); + assert_eq!(format!("{:?}", debug), "()"); + + let x = multi()(); + assert_eq!(format!("{:?}", x), "()"); + fn assert_send(_: &impl Send) {} + assert_send(&x); +} diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs new file mode 100644 index 000000000..b3ff2ce5a --- /dev/null +++ b/tests/ui/impl-trait/impl_trait_projections.rs @@ -0,0 +1,39 @@ +use std::fmt::Debug; +use std::option; + +fn parametrized_type_is_allowed() -> Option { + Some(5i32) +} + +fn path_parametrized_type_is_allowed() -> option::Option { + Some(5i32) +} + +fn projection_is_disallowed(x: impl Iterator) -> ::Item { +//~^ ERROR `impl Trait` is not allowed in path parameters +//~| ERROR `impl Trait` is not allowed in path parameters + x.next().unwrap() +} + +fn projection_with_named_trait_is_disallowed(x: impl Iterator) + -> ::Item +//~^ ERROR `impl Trait` is not allowed in path parameters +{ + x.next().unwrap() +} + +fn projection_with_named_trait_inside_path_is_disallowed() + -> <::std::ops::Range as Iterator>::Item +//~^ ERROR `impl Trait` is not allowed in path parameters +{ + (1i32..100).next().unwrap() +} + +fn projection_from_impl_trait_inside_dyn_trait_is_disallowed() + -> as Iterator>::Item +//~^ ERROR `impl Trait` is not allowed in path parameters +{ + panic!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr new file mode 100644 index 000000000..4deb24731 --- /dev/null +++ b/tests/ui/impl-trait/impl_trait_projections.stderr @@ -0,0 +1,33 @@ +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:12:51 + | +LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { + | ^^^^^^^^^^^^^ + +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:19:9 + | +LL | -> ::Item + | ^^^^^^^^^^^^^ + +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:26:27 + | +LL | -> <::std::ops::Range as Iterator>::Item + | ^^^^^^^^^^ + +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:33:29 + | +LL | -> as Iterator>::Item + | ^^^^^^^^^^ + +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:12:51 + | +LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0667`. diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs new file mode 100644 index 000000000..74df300f8 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs @@ -0,0 +1,11 @@ +#![feature(return_position_impl_trait_in_trait)] + +pub trait Foo { + fn bar() -> impl Sized; +} + +pub struct Foreign; + +impl Foo for Foreign { + fn bar() {} +} diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs new file mode 100644 index 000000000..a4d483dee --- /dev/null +++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs @@ -0,0 +1,49 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete + +struct TestA {} +struct TestB {} + +impl TestTrait for TestA { + type Output = (); +} +impl TestTrait for TestB { + type Output = (); +} + +trait TestTrait { + type Output; +} + +impl TestTrait for GreeterOutput +where + A: TestTrait, + B: TestTrait, +{ + type Output = (); +} + +enum GreeterOutput +where + A: TestTrait, + B: TestTrait, +{ + SayHello(A), + SayGoodbye(B), +} + +trait Greeter { + fn test_func(&self, func: &str) -> impl TestTrait { + match func { + "SayHello" => GreeterOutput::SayHello(TestA {}), + "SayGoodbye" => GreeterOutput::SayGoodbye(TestB {}), + _ => GreeterOutput::SayHello(TestA {}), + } + } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr new file mode 100644 index 000000000..d681ecf25 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/box-coerce-span-in-default.rs:3:12 + | +LL | #![feature(return_position_impl_trait_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs new file mode 100644 index 000000000..772da845e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> Wrapper { Wrapper(0) } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/deep-match.rs b/tests/ui/impl-trait/in-trait/deep-match.rs new file mode 100644 index 000000000..a6385147c --- /dev/null +++ b/tests/ui/impl-trait/in-trait/deep-match.rs @@ -0,0 +1,15 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct Wrapper(T); + +trait Foo { + fn bar() -> Wrapper; +} + +impl Foo for () { + fn bar() -> i32 { 0 } + //~^ ERROR method `bar` has an incompatible return type for trait +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/deep-match.stderr b/tests/ui/impl-trait/in-trait/deep-match.stderr new file mode 100644 index 000000000..034ee5ea4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/deep-match.stderr @@ -0,0 +1,15 @@ +error[E0053]: method `bar` has an incompatible return type for trait + --> $DIR/deep-match.rs:11:17 + | +LL | fn bar() -> i32 { 0 } + | ^^^ + | | + | expected struct `Wrapper`, found `i32` + | return type in trait + | + = note: expected struct `Wrapper<_>` + found type `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs new file mode 100644 index 000000000..45ae2b8ad --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs @@ -0,0 +1,13 @@ +// edition:2021 + +#![allow(incomplete_features)] +#![feature(async_fn_in_trait)] + +pub trait Foo { + async fn woopsie_async(&self) -> String { + 42 + //~^ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr new file mode 100644 index 000000000..142b1bff1 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/default-body-type-err-2.rs:8:9 + | +LL | 42 + | ^^- help: try using a conversion method: `.to_string()` + | | + | expected struct `String`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs new file mode 100644 index 000000000..ac9baf91c --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs @@ -0,0 +1,13 @@ +#![allow(incomplete_features)] +#![feature(return_position_impl_trait_in_trait)] + +use std::ops::Deref; + +pub trait Foo { + fn lol(&self) -> impl Deref { + //~^ type mismatch resolving `<&i32 as Deref>::Target == String` + &1i32 + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr new file mode 100644 index 000000000..461247a3e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr @@ -0,0 +1,12 @@ +error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String` + --> $DIR/default-body-type-err.rs:7:22 + | +LL | fn lol(&self) -> impl Deref { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` +LL | +LL | &1i32 + | ----- return type was inferred to be `&i32` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs new file mode 100644 index 000000000..ad3cc7c25 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -0,0 +1,21 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + async fn baz(&self) -> impl Debug { + "" + } +} + +struct Bar; + +impl Foo for Bar {} + +fn main() { + let _ = Bar.baz(); +} diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs new file mode 100644 index 000000000..b0baf5bb1 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/default-body.rs @@ -0,0 +1,21 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + async fn baz(&self) -> &str { + "" + } +} + +struct Bar; + +impl Foo for Bar {} + +fn main() { + let _ = Bar.baz(); +} diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs new file mode 100644 index 000000000..bb4e0d44f --- /dev/null +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -0,0 +1,13 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar() -> impl std::fmt::Display; +} + +impl Foo for () { + fn bar() -> () {} + //~^ ERROR `()` doesn't implement `std::fmt::Display` +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr new file mode 100644 index 000000000..aa5492d28 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/doesnt-satisfy.rs:9:17 + | +LL | fn bar() -> () {} + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Foo::bar::{opaque#0}` + --> $DIR/doesnt-satisfy.rs:5:22 + | +LL | fn bar() -> impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs new file mode 100644 index 000000000..9c1c2b503 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/early.rs @@ -0,0 +1,23 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + async fn bar<'a: 'a>(&'a mut self); +} + +impl Foo for () { + async fn bar<'a: 'a>(&'a mut self) {} +} + +pub trait Foo2 { + fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a; +} + +impl Foo2 for () { + fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/encode.rs b/tests/ui/impl-trait/in-trait/encode.rs new file mode 100644 index 000000000..efb9f6498 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/encode.rs @@ -0,0 +1,9 @@ +// build-pass +// compile-flags: --crate-type=lib + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar() -> impl Sized; +} diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs new file mode 100644 index 000000000..6341f5b42 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/foreign.rs @@ -0,0 +1,9 @@ +// check-pass +// aux-build: rpitit.rs + +extern crate rpitit; + +fn main() { + // Witness an RPITIT from another crate + let () = ::bar(); +} diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.rs b/tests/ui/impl-trait/in-trait/generics-mismatch.rs new file mode 100644 index 000000000..cc0fc720e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.rs @@ -0,0 +1,17 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct U; + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U { + fn bar(&self) {} + //~^ ERROR method `bar` has 1 type parameter but its trait declaration has 0 type parameters +} + +fn main() { + U.bar(); +} diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr new file mode 100644 index 000000000..cd42683e0 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/generics-mismatch.rs:11:12 + | +LL | fn bar(&self) -> impl Sized; + | - expected 0 type parameters +... +LL | fn bar(&self) {} + | ^ found 1 type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/issue-102140.rs b/tests/ui/impl-trait/in-trait/issue-102140.rs new file mode 100644 index 000000000..be1e012ac --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102140.rs @@ -0,0 +1,30 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Marker {} +impl Marker for u32 {} + +trait MyTrait { + fn foo(&self) -> impl Marker + where + Self: Sized; +} + +struct Outer; + +impl MyTrait for Outer { + fn foo(&self) -> impl Marker { + 42 + } +} + +impl dyn MyTrait { + fn other(&self) -> impl Marker { + MyTrait::foo(&self) + //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr new file mode 100644 index 000000000..18bb63745 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr @@ -0,0 +1,33 @@ +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:22 + | +LL | MyTrait::foo(&self) + | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | | + | required by a bound introduced by this call + | +help: consider removing the leading `&`-reference + | +LL - MyTrait::foo(&self) +LL + MyTrait::foo(self) + | + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/issue-102140.rs:23:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/issue-102301.rs b/tests/ui/impl-trait/in-trait/issue-102301.rs new file mode 100644 index 000000000..a93714a65 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102301.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn foo>(self) -> impl Foo; +} + +struct Bar; + +impl Foo for Bar { + fn foo>(self) -> impl Foo { + self + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/issue-102571.rs b/tests/ui/impl-trait/in-trait/issue-102571.rs new file mode 100644 index 000000000..61c91e644 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102571.rs @@ -0,0 +1,24 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; +use std::ops::Deref; + +trait Foo { + fn bar(self) -> impl Deref; +} + +struct A; + +impl Foo for A { + fn bar(self) -> &'static str { + "Hello, world" + } +} + +fn foo(t: T) { + let () = t.bar(); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.stderr new file mode 100644 index 000000000..87219941d --- /dev/null +++ b/tests/ui/impl-trait/in-trait/issue-102571.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-102571.rs:20:9 + | +LL | let () = t.bar(); + | ^^ ------- this expression has type `impl Deref` + | | + | expected associated type, found `()` + | + = note: expected associated type `impl Deref` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.rs b/tests/ui/impl-trait/in-trait/method-signature-matches.rs new file mode 100644 index 000000000..c848ee3f6 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.rs @@ -0,0 +1,51 @@ +// edition: 2021 + +#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] +#![allow(incomplete_features)] + +trait Uwu { + fn owo(x: ()) -> impl Sized; +} + +impl Uwu for () { + fn owo(_: u8) {} + //~^ ERROR method `owo` has an incompatible type for trait +} + +trait AsyncUwu { + async fn owo(x: ()) {} +} + +impl AsyncUwu for () { + async fn owo(_: u8) {} + //~^ ERROR method `owo` has an incompatible type for trait +} + +trait TooMuch { + fn calm_down_please() -> impl Sized; +} + +impl TooMuch for () { + fn calm_down_please(_: (), _: (), _: ()) {} + //~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 +} + +trait TooLittle { + fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; +} + +impl TooLittle for () { + fn come_on_a_little_more_effort() {} + //~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 +} + +trait Lifetimes { + fn early<'early, T>(x: &'early T) -> impl Sized; +} + +impl Lifetimes for () { + fn early<'late, T>(_: &'late ()) {} + //~^ ERROR method `early` has an incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.stderr new file mode 100644 index 000000000..4dfd77222 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.stderr @@ -0,0 +1,84 @@ +error[E0053]: method `owo` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:11:15 + | +LL | fn owo(_: u8) {} + | ^^ + | | + | expected `()`, found `u8` + | help: change the parameter type to match the trait: `()` + | +note: type in trait + --> $DIR/method-signature-matches.rs:7:15 + | +LL | fn owo(x: ()) -> impl Sized; + | ^^ + = note: expected signature `fn(())` + found signature `fn(u8)` + +error[E0053]: method `owo` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:20:21 + | +LL | async fn owo(_: u8) {} + | ^^ + | | + | expected `()`, found `u8` + | help: change the parameter type to match the trait: `()` + | +note: while checking the return type of the `async fn` + --> $DIR/method-signature-matches.rs:20:25 + | +LL | async fn owo(_: u8) {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/method-signature-matches.rs:20:25 + | +LL | async fn owo(_: u8) {} + | ^ checked the `Output` of this `async fn`, found opaque type +note: type in trait + --> $DIR/method-signature-matches.rs:16:21 + | +LL | async fn owo(x: ()) {} + | ^^ + = note: expected signature `fn(()) -> _` + found signature `fn(u8) -> _` + +error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 + --> $DIR/method-signature-matches.rs:29:28 + | +LL | fn calm_down_please() -> impl Sized; + | ------------------------------------ trait requires 0 parameters +... +LL | fn calm_down_please(_: (), _: (), _: ()) {} + | ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3 + +error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 + --> $DIR/method-signature-matches.rs:38:5 + | +LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; + | ---------------- trait requires 3 parameters +... +LL | fn come_on_a_little_more_effort() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0 + +error[E0053]: method `early` has an incompatible type for trait + --> $DIR/method-signature-matches.rs:47:27 + | +LL | fn early<'late, T>(_: &'late ()) {} + | - ^^^^^^^^^ + | | | + | | expected type parameter `T`, found `()` + | | help: change the parameter type to match the trait: `&'early T` + | this type parameter + | +note: type in trait + --> $DIR/method-signature-matches.rs:43:28 + | +LL | fn early<'early, T>(x: &'early T) -> impl Sized; + | ^^^^^^^^^ + = note: expected signature `fn(&'early T)` + found signature `fn(&())` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0050, E0053. +For more information about an error, try `rustc --explain E0050`. diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs new file mode 100644 index 000000000..65285e3a3 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs @@ -0,0 +1,32 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; +use std::ops::Deref; + +trait Foo { + fn bar(self) -> impl Deref; +} + +struct A; + +impl Foo for A { + fn bar(self) -> &'static str { + "Hello, world" + } +} + +struct B; + +impl Foo for B { + fn bar(self) -> Box { + Box::new(42) + } +} + +fn main() { + println!("Message for you: {:?}", &*A.bar()); + println!("Another for you: {:?}", &*B.bar()); +} diff --git a/tests/ui/impl-trait/in-trait/object-safety.rs b/tests/ui/impl-trait/in-trait/object-safety.rs new file mode 100644 index 000000000..dd35b9a2d --- /dev/null +++ b/tests/ui/impl-trait/in-trait/object-safety.rs @@ -0,0 +1,22 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + fn baz(&self) -> impl Debug; +} + +impl Foo for u32 { + fn baz(&self) -> u32 { + 32 + } +} + +fn main() { + let i = Box::new(42_u32) as Box; + //~^ ERROR the trait `Foo` cannot be made into an object + //~| ERROR the trait `Foo` cannot be made into an object + let s = i.baz(); + //~^ ERROR the trait `Foo` cannot be made into an object +} diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr new file mode 100644 index 000000000..ca0e760ff --- /dev/null +++ b/tests/ui/impl-trait/in-trait/object-safety.stderr @@ -0,0 +1,50 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:17:33 + | +LL | let i = Box::new(42_u32) as Box; + | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:22 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> impl Debug; + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type + = help: consider moving `baz` to another trait + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:20:13 + | +LL | let s = i.baz(); + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:22 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> impl Debug; + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type + = help: consider moving `baz` to another trait + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:17:13 + | +LL | let i = Box::new(42_u32) as Box; + | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:22 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> impl Debug; + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type + = help: consider moving `baz` to another trait + = note: required for `Box` to implement `CoerceUnsized>` + = note: required by cast to type `Box` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs new file mode 100644 index 000000000..3ac264e8e --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs @@ -0,0 +1,19 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for () { + fn bar(&self) -> impl Display { + "Hello, world" + } +} + +fn main() { + let x: &str = ().bar(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr new file mode 100644 index 000000000..15edda483 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/opaque-in-impl-is-opaque.rs:17:19 + | +LL | fn bar(&self) -> impl Display { + | ------------ the found opaque type +... +LL | let x: &str = ().bar(); + | ---- ^^^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `impl std::fmt::Display` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs new file mode 100644 index 000000000..2e0662969 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -0,0 +1,48 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + fn foo(&self) -> impl Debug; +} + +impl Foo for () { + fn foo(&self) -> impl Debug { + "Hello, world" + } +} + +impl Foo for std::marker::PhantomData { + fn foo(&self) -> impl Debug { + T::default() + } +} + +trait Bar { + fn bar(&self) -> impl Debug; +} + +impl Bar for () { + fn bar(&self) -> impl Debug { + format!("Hello with generic {}", std::any::type_name::()) + } +} + +trait Baz { + fn baz(&self) -> impl Debug + '_; +} + +impl Baz for String { + fn baz(&self) -> impl Debug + '_ { + (self,) + } +} + +fn main() { + println!("{:?}", ().foo()); + println!("{:?}", ().bar::()); + println!("{:?}", "hi".to_string().baz()); +} diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs new file mode 100644 index 000000000..d6ede1cc4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/reveal.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn f() -> Box; +} + +impl Foo for () { + fn f() -> Box { + Box::new(String::new()) + } +} + +fn main() { + let x: Box = <() as Foo>::f(); +} diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs new file mode 100644 index 000000000..90682631a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -0,0 +1,21 @@ +// edition:2021 + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; + +pub trait AsyncTrait { + fn async_fn(&self, buff: &[u8]) -> impl Future>; +} + +pub struct Struct; + +impl AsyncTrait for Struct { + fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + async move { buff.to_vec() } + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr new file mode 100644 index 000000000..e10566017 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr @@ -0,0 +1,16 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/signature-mismatch.rs:15:5 + | +LL | fn async_fn(&self, buff: &[u8]) -> impl Future>; + | ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future> + 'static` +... +LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future> + '2` + | + = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future> + 'static` + found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future> + '2` + = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs new file mode 100644 index 000000000..9d27d3710 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs @@ -0,0 +1,26 @@ +// FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not. +// But we fixed an ICE anyways. + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +default impl Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + //~^ ERROR method `bar` has an incompatible type for trait + *self + } +} + +impl Foo for i32 {} + +fn main() { + 1i32.bar(); +} diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr new file mode 100644 index 000000000..37cfd7449 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr @@ -0,0 +1,23 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/specialization-broken.rs:16:22 + | +LL | default impl Foo for U + | - this type parameter +... +LL | fn bar(&self) -> U { + | ^ + | | + | expected associated type, found type parameter `U` + | help: change the output type to match the trait: `impl Sized` + | +note: type in trait + --> $DIR/specialization-broken.rs:9:22 + | +LL | fn bar(&self) -> impl Sized; + | ^^^^^^^^^^ + = note: expected signature `fn(&U) -> impl Sized` + found signature `fn(&U) -> U` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs new file mode 100644 index 000000000..c9ee877db --- /dev/null +++ b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(specialization)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn bar(&self) -> impl Sized; +} + +impl Foo for U +where + U: Copy, +{ + fn bar(&self) -> U { + *self + } +} + +impl Foo for i32 {} + +fn main() { + let _: i32 = 1i32.bar(); +} diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs new file mode 100644 index 000000000..4cbe682b4 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/success.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Display; + +trait Foo { + fn bar(&self) -> impl Display; +} + +impl Foo for i32 { + fn bar(&self) -> i32 { + *self + } +} + +impl Foo for &'static str { + fn bar(&self) -> &'static str { + *self + } +} + +struct Yay; + +impl Foo for Yay { + fn bar(&self) -> String { + String::from(":^)") + } +} + +fn foo_generically(t: T) { + println!("{}", t.bar()); +} + +fn main() { + println!("{}", "Hello, world.".bar()); + println!("The answer is {}!", 42.bar()); + foo_generically(Yay); +} diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs new file mode 100644 index 000000000..0bbe50ea6 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs @@ -0,0 +1,17 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +struct S; + +trait Foo { + fn bar() -> impl Sized; +} + +impl Foo for S { + fn bar() -> impl Sized {} + //~^ ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter +} + +fn main() { + S::bar(); +} diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr new file mode 100644 index 000000000..8ff54cad9 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr @@ -0,0 +1,12 @@ +error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/trait-more-generics-than-impl.rs:11:11 + | +LL | fn bar() -> impl Sized; + | - expected 1 type parameter +... +LL | fn bar() -> impl Sized {} + | ^ found 0 type parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs new file mode 100644 index 000000000..2c71583b3 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs @@ -0,0 +1,16 @@ +// issue #101663 + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Wf {} + +trait Uwu { + fn nya() -> impl Wf>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + + fn nya2() -> impl Wf<[u8]>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr new file mode 100644 index 000000000..03cc4c2b9 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -0,0 +1,30 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-bounds.rs:9:22 + | +LL | fn nya() -> impl Wf>; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-bounds.rs:12:23 + | +LL | fn nya2() -> impl Wf<[u8]>; + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Wf` + --> $DIR/wf-bounds.rs:6:10 + | +LL | trait Wf {} + | ^ required by this bound in `Wf` +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Wf {} + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/where-clause.rs b/tests/ui/impl-trait/in-trait/where-clause.rs new file mode 100644 index 000000000..87bac519c --- /dev/null +++ b/tests/ui/impl-trait/in-trait/where-clause.rs @@ -0,0 +1,24 @@ +// check-pass +// edition: 2021 + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::fmt::Debug; + +trait Foo { + fn foo<'a>(&'a self) -> impl Debug + where + Item: 'a; +} + +impl Foo for D { + fn foo<'a>(&'a self) -> impl Debug + where + Item: 'a, + { + self.clone() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-100075-2.rs b/tests/ui/impl-trait/issue-100075-2.rs new file mode 100644 index 000000000..cf059af19 --- /dev/null +++ b/tests/ui/impl-trait/issue-100075-2.rs @@ -0,0 +1,8 @@ +fn opaque(t: T) -> impl Sized { + //~^ ERROR cannot resolve opaque type + //~| WARNING function cannot return without recursing + opaque(Some(t)) +} + +#[allow(dead_code)] +fn main() {} diff --git a/tests/ui/impl-trait/issue-100075-2.stderr b/tests/ui/impl-trait/issue-100075-2.stderr new file mode 100644 index 000000000..d2dbd8c62 --- /dev/null +++ b/tests/ui/impl-trait/issue-100075-2.stderr @@ -0,0 +1,24 @@ +warning: function cannot return without recursing + --> $DIR/issue-100075-2.rs:1:1 + | +LL | fn opaque(t: T) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | opaque(Some(t)) + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0720]: cannot resolve opaque type + --> $DIR/issue-100075-2.rs:1:23 + | +LL | fn opaque(t: T) -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +... +LL | opaque(Some(t)) + | --------------- returning here with type `impl Sized` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issue-100075.rs b/tests/ui/impl-trait/issue-100075.rs new file mode 100644 index 000000000..ea30abb48 --- /dev/null +++ b/tests/ui/impl-trait/issue-100075.rs @@ -0,0 +1,21 @@ +trait Marker {} +impl Marker for T {} + +fn maybe( + _t: T, +) -> Option< + //removing the line below makes it compile + &'static T, +> { + None +} + +fn _g(t: &'static T) -> &'static impl Marker { + //~^ ERROR cannot resolve opaque type + if let Some(t) = maybe(t) { + return _g(t); + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-100075.stderr b/tests/ui/impl-trait/issue-100075.stderr new file mode 100644 index 000000000..267ecfdae --- /dev/null +++ b/tests/ui/impl-trait/issue-100075.stderr @@ -0,0 +1,12 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/issue-100075.rs:13:37 + | +LL | fn _g(t: &'static T) -> &'static impl Marker { + | ^^^^^^^^^^^ recursive opaque type +... +LL | return _g(t); + | ----- returning here with type `&impl Marker` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issue-100187.rs b/tests/ui/impl-trait/issue-100187.rs new file mode 100644 index 000000000..fc541c696 --- /dev/null +++ b/tests/ui/impl-trait/issue-100187.rs @@ -0,0 +1,12 @@ +// check-pass + +trait Trait { + type Ty; +} +impl Trait<&u8> for () { + type Ty = (); +} + +fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-102605.rs b/tests/ui/impl-trait/issue-102605.rs new file mode 100644 index 000000000..3bbdf35af --- /dev/null +++ b/tests/ui/impl-trait/issue-102605.rs @@ -0,0 +1,15 @@ +// edition:2021 + +async fn foo() -> Result<(), String> { + Ok(()) +} + +fn convert_result(r: Result) -> Option { + None +} + +fn main() -> Option<()> { + //~^ ERROR `main` has invalid return type `Option<()>` + convert_result(foo()) + //~^ ERROR mismatched types +} diff --git a/tests/ui/impl-trait/issue-102605.stderr b/tests/ui/impl-trait/issue-102605.stderr new file mode 100644 index 000000000..d4aba9149 --- /dev/null +++ b/tests/ui/impl-trait/issue-102605.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched types + --> $DIR/issue-102605.rs:13:20 + | +LL | convert_result(foo()) + | -------------- ^^^^^ expected enum `Result`, found opaque type + | | + | arguments to this function are incorrect + | +note: while checking the return type of the `async fn` + --> $DIR/issue-102605.rs:3:19 + | +LL | async fn foo() -> Result<(), String> { + | ^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type + = note: expected enum `Result<(), _>` + found opaque type `impl Future>` +note: function defined here + --> $DIR/issue-102605.rs:7:4 + | +LL | fn convert_result(r: Result) -> Option { + | ^^^^^^^^^^^^^^ --------------- +help: consider `await`ing on the `Future` + | +LL | convert_result(foo().await) + | ++++++ +help: try wrapping the expression in `Err` + | +LL | convert_result(Err(foo())) + | ++++ + + +error[E0277]: `main` has invalid return type `Option<()>` + --> $DIR/issue-102605.rs:11:14 + | +LL | fn main() -> Option<()> { + | ^^^^^^^^^^ `main` can only return types that implement `Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issue-103181-1.rs b/tests/ui/impl-trait/issue-103181-1.rs new file mode 100644 index 000000000..197aedf9d --- /dev/null +++ b/tests/ui/impl-trait/issue-103181-1.rs @@ -0,0 +1,85 @@ +// edition:2021 + +mod hyper { + use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task::Poll}; + + pub trait HttpBody { + type Error; + } + impl HttpBody for () { + //~^ ERROR not all trait items implemented, missing: `Error` + // don't implement `Error` here for the ICE + } + + pub struct Server(I, S); + + pub fn serve(_: S) -> Server { + todo!() + } + + impl Future for Server<(), S> + where + S: MakeServiceRef<(), (), ResBody = B>, + B: HttpBody, + B::Error: Debug, + { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll { + todo!() + } + } + + pub trait MakeServiceRef { + type ResBody; + } + + impl MakeServiceRef<(), ()> for T + where + T: for<'a> Service<&'a (), Response = S>, + S: Service<()>, + { + type ResBody = (); + } + + pub struct MakeServiceFn(pub F); + pub struct ServiceFn(pub PhantomData<(F, R)>); + + pub trait Service { + type Response; + } + + impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn + where + F: Fn() -> Ret, + Ret: Future>, + { + type Response = Svc; + } + + impl Service for ServiceFn + where + F: Fn() -> Ret, + Ret: Future>, + { + type Response = ResBody; + } +} + +async fn smarvice() -> Result<(), ()> { + Ok(()) +} + +fn service_fn(f: F) -> hyper::ServiceFn +where + F: Fn() -> S, +{ + hyper::ServiceFn(std::marker::PhantomData) +} + +async fn iceice() { + let service = hyper::MakeServiceFn(|| async { Ok::<_, ()>(service_fn(|| smarvice())) }); + hyper::serve::<(), _>(service).await; +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-103181-1.stderr b/tests/ui/impl-trait/issue-103181-1.stderr new file mode 100644 index 000000000..cd026607d --- /dev/null +++ b/tests/ui/impl-trait/issue-103181-1.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Error` + --> $DIR/issue-103181-1.rs:9:5 + | +LL | type Error; + | ---------- `Error` from trait +LL | } +LL | impl HttpBody for () { + | ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/issue-103181-2.rs b/tests/ui/impl-trait/issue-103181-2.rs new file mode 100644 index 000000000..b43ac4507 --- /dev/null +++ b/tests/ui/impl-trait/issue-103181-2.rs @@ -0,0 +1,29 @@ +// edition:2021 + +trait SendFuture: Send { + type Output; +} + +impl SendFuture for Fut { + type Output = (); +} + +async fn broken_fut() { + ident_error; + //~^ ERROR cannot find value `ident_error` in this scope +} + +// triggers normalization of `::Output`, +// which requires `Fut: Send`. +fn normalize(_: Fut, _: Fut::Output) {} + +async fn iceice() +// <- async fn is necessary +where + A: Send, + B: Send, // <- a second bound +{ + normalize(broken_fut(), ()); +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-103181-2.stderr b/tests/ui/impl-trait/issue-103181-2.stderr new file mode 100644 index 000000000..5eb2dd918 --- /dev/null +++ b/tests/ui/impl-trait/issue-103181-2.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `ident_error` in this scope + --> $DIR/issue-103181-2.rs:12:5 + | +LL | ident_error; + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/impl-trait/issue-103599.rs b/tests/ui/impl-trait/issue-103599.rs new file mode 100644 index 000000000..043ae67f2 --- /dev/null +++ b/tests/ui/impl-trait/issue-103599.rs @@ -0,0 +1,10 @@ +// check-pass + +trait T {} + +fn wrap(x: impl T) -> impl T { + //~^ WARN function cannot return without recursing + wrap(wrap(x)) +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-103599.stderr b/tests/ui/impl-trait/issue-103599.stderr new file mode 100644 index 000000000..82038c1dc --- /dev/null +++ b/tests/ui/impl-trait/issue-103599.stderr @@ -0,0 +1,14 @@ +warning: function cannot return without recursing + --> $DIR/issue-103599.rs:5:1 + | +LL | fn wrap(x: impl T) -> impl T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | wrap(wrap(x)) + | ------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/issue-35668.rs b/tests/ui/impl-trait/issue-35668.rs new file mode 100644 index 000000000..c970163fc --- /dev/null +++ b/tests/ui/impl-trait/issue-35668.rs @@ -0,0 +1,12 @@ +fn func<'a, T>(a: &'a [T]) -> impl Iterator { + a.iter().map(|a| a*a) + //~^ ERROR cannot multiply `&T` by `&T` +} + +fn main() { + let a = (0..30).collect::>(); + + for k in func(&a) { + println!("{}", k); + } +} diff --git a/tests/ui/impl-trait/issue-35668.stderr b/tests/ui/impl-trait/issue-35668.stderr new file mode 100644 index 000000000..84add5799 --- /dev/null +++ b/tests/ui/impl-trait/issue-35668.stderr @@ -0,0 +1,16 @@ +error[E0369]: cannot multiply `&T` by `&T` + --> $DIR/issue-35668.rs:2:23 + | +LL | a.iter().map(|a| a*a) + | -^- &T + | | + | &T + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn func<'a, T>(a: &'a [T]) -> impl Iterator where &T: Mul<&T> { + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/impl-trait/issue-46959.rs b/tests/ui/impl-trait/issue-46959.rs new file mode 100644 index 000000000..3611a9568 --- /dev/null +++ b/tests/ui/impl-trait/issue-46959.rs @@ -0,0 +1,9 @@ +// check-pass +#![deny(non_camel_case_types)] + +#[allow(dead_code)] +fn qqq(lol: impl Iterator) -> impl Iterator { + lol.map(|x|x as u64) +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-49556.rs b/tests/ui/impl-trait/issue-49556.rs new file mode 100644 index 000000000..c8c172f0e --- /dev/null +++ b/tests/ui/impl-trait/issue-49556.rs @@ -0,0 +1,13 @@ +// check-pass +fn iter<'a>(data: &'a [usize]) -> impl Iterator + 'a { + data.iter() + .map( + |x| x // fn(&'a usize) -> &'a usize + ) + .map( + |x| *x // fn(&'a usize) -> usize + ) +} + +fn main() { +} diff --git a/tests/ui/impl-trait/issue-49579.rs b/tests/ui/impl-trait/issue-49579.rs new file mode 100644 index 000000000..98de014e9 --- /dev/null +++ b/tests/ui/impl-trait/issue-49579.rs @@ -0,0 +1,14 @@ +// check-pass + +fn fibs(n: u32) -> impl Iterator { + (0 .. n) + .scan((0, 1), |st, _| { + *st = (st.1, st.0 + st.1); + Some(*st) + }) + .map(&|(f, _)| f) +} + +fn main() { + println!("{:?}", fibs(10).collect::>()); +} diff --git a/tests/ui/impl-trait/issue-49685.rs b/tests/ui/impl-trait/issue-49685.rs new file mode 100644 index 000000000..fb328d67b --- /dev/null +++ b/tests/ui/impl-trait/issue-49685.rs @@ -0,0 +1,13 @@ +// run-pass +// Regression test for #49685: drop elaboration was not revealing the +// value of `impl Trait` returns, leading to an ICE. + +fn main() { + let _ = Some(()) + .into_iter() + .flat_map(|_| Some(()).into_iter().flat_map(func)); +} + +fn func(_: ()) -> impl Iterator { + Some(()).into_iter().flat_map(|_| vec![]) +} diff --git a/tests/ui/impl-trait/issue-51185.rs b/tests/ui/impl-trait/issue-51185.rs new file mode 100644 index 000000000..52a2b2553 --- /dev/null +++ b/tests/ui/impl-trait/issue-51185.rs @@ -0,0 +1,8 @@ +// run-pass +fn foo() -> impl Into fn(&'a ())> { + (|_| {}) as for<'a> fn(&'a ()) +} + +fn main() { + foo().into()(&()); +} diff --git a/tests/ui/impl-trait/issue-54966.rs b/tests/ui/impl-trait/issue-54966.rs new file mode 100644 index 000000000..0ed3c4b3c --- /dev/null +++ b/tests/ui/impl-trait/issue-54966.rs @@ -0,0 +1,6 @@ +// issue-54966: ICE returning an unknown type with impl FnMut + +fn generate_duration() -> Oper {} +//~^ ERROR cannot find type `Oper` in this scope + +fn main() {} diff --git a/tests/ui/impl-trait/issue-54966.stderr b/tests/ui/impl-trait/issue-54966.stderr new file mode 100644 index 000000000..aa9a61cb5 --- /dev/null +++ b/tests/ui/impl-trait/issue-54966.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Oper` in this scope + --> $DIR/issue-54966.rs:3:27 + | +LL | fn generate_duration() -> Oper {} + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/impl-trait/issue-55872-1.rs b/tests/ui/impl-trait/issue-55872-1.rs new file mode 100644 index 000000000..22ff7ffa2 --- /dev/null +++ b/tests/ui/impl-trait/issue-55872-1.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type E: Copy; + + fn foo() -> Self::E; +} + +impl Bar for S { + type E = impl Copy; + + fn foo() -> Self::E { + //~^ ERROR impl has stricter requirements than trait + //~| ERROR the trait bound `S: Copy` is not satisfied in `(S, T)` [E0277] + //~| ERROR the trait bound `T: Copy` is not satisfied in `(S, T)` [E0277] + (S::default(), T::default()) + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr new file mode 100644 index 000000000..8912cce1b --- /dev/null +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -0,0 +1,37 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-55872-1.rs:12:15 + | +LL | fn foo() -> Self::E; + | ----------------------- definition of `foo` from trait +... +LL | fn foo() -> Self::E { + | ^^^^^^^ impl has extra requirement `T: Default` + +error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` + --> $DIR/issue-55872-1.rs:12:29 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` + | + = note: required because it appears within the type `(S, T)` +help: consider further restricting this bound + | +LL | impl Bar for S { + | +++++++++++++++++++ + +error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` + --> $DIR/issue-55872-1.rs:12:29 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` + | + = note: required because it appears within the type `(S, T)` +help: consider further restricting this bound + | +LL | fn foo() -> Self::E { + | +++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0276, E0277. +For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/impl-trait/issue-55872-2.rs b/tests/ui/impl-trait/issue-55872-2.rs new file mode 100644 index 000000000..4443d3c4d --- /dev/null +++ b/tests/ui/impl-trait/issue-55872-2.rs @@ -0,0 +1,19 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type E: Send; + + fn foo() -> Self::E; +} + +impl Bar for S { + type E = impl std::marker::Send; + fn foo() -> Self::E { + async {} + //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-55872-2.stderr b/tests/ui/impl-trait/issue-55872-2.stderr new file mode 100644 index 000000000..11b8485c8 --- /dev/null +++ b/tests/ui/impl-trait/issue-55872-2.stderr @@ -0,0 +1,8 @@ +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-55872-2.rs:14:9 + | +LL | async {} + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issue-55872-3.rs b/tests/ui/impl-trait/issue-55872-3.rs new file mode 100644 index 000000000..91811df93 --- /dev/null +++ b/tests/ui/impl-trait/issue-55872-3.rs @@ -0,0 +1,20 @@ +// edition:2018 +// ignore-compare-mode-chalk + +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type E: Copy; + + fn foo() -> Self::E; +} + +impl Bar for S { + type E = impl std::marker::Copy; + fn foo() -> Self::E { + //~^ ERROR : Copy` is not satisfied [E0277] + async {} + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr new file mode 100644 index 000000000..c6e10f0f3 --- /dev/null +++ b/tests/ui/impl-trait/issue-55872-3.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `[async block@$DIR/issue-55872-3.rs:16:9: 16:17]: Copy` is not satisfied + --> $DIR/issue-55872-3.rs:14:20 + | +LL | fn foo() -> Self::E { + | ^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/issue-55872-3.rs:16:9: 16:17]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issue-55872.rs b/tests/ui/impl-trait/issue-55872.rs new file mode 100644 index 000000000..c4e6f6436 --- /dev/null +++ b/tests/ui/impl-trait/issue-55872.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type E: Copy; + + fn foo() -> Self::E; +} + +impl Bar for S { + type E = impl Copy; + + fn foo() -> Self::E { + || () + //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-55872.stderr b/tests/ui/impl-trait/issue-55872.stderr new file mode 100644 index 000000000..cb370fbe1 --- /dev/null +++ b/tests/ui/impl-trait/issue-55872.stderr @@ -0,0 +1,8 @@ +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-55872.rs:13:9 + | +LL | || () + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issue-56445.rs b/tests/ui/impl-trait/issue-56445.rs new file mode 100644 index 000000000..6dd1648c9 --- /dev/null +++ b/tests/ui/impl-trait/issue-56445.rs @@ -0,0 +1,25 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-629426939 +// check-pass + +#![crate_type = "lib"] + +use std::marker::PhantomData; + +pub struct S<'a> { + pub m1: PhantomData<&'a u8>, + pub m2: [u8; S::size()], +} + +impl<'a> S<'a> +{ + pub const fn size() -> usize { 1 } + + pub fn new() -> Self + { + Self + { + m1: PhantomData, + m2: [0; Self::size()], + } + } +} diff --git a/tests/ui/impl-trait/issue-68532.rs b/tests/ui/impl-trait/issue-68532.rs new file mode 100644 index 000000000..01a7af0ae --- /dev/null +++ b/tests/ui/impl-trait/issue-68532.rs @@ -0,0 +1,13 @@ +// check-pass + +pub struct A<'a>(&'a ()); + +impl<'a> A<'a> { + const N: usize = 68; + + pub fn foo(&self) { + let _b = [0; Self::N]; + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-72911.rs b/tests/ui/impl-trait/issue-72911.rs new file mode 100644 index 000000000..63f4898f4 --- /dev/null +++ b/tests/ui/impl-trait/issue-72911.rs @@ -0,0 +1,21 @@ +// Regression test for #72911. + +pub struct Lint {} + +impl Lint {} + +pub fn gather_all() -> impl Iterator { + lint_files().flat_map(|f| gather_from_file(&f)) +} + +fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator { + //~^ ERROR: failed to resolve + unimplemented!() +} + +fn lint_files() -> impl Iterator { + //~^ ERROR: failed to resolve + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-72911.stderr b/tests/ui/impl-trait/issue-72911.stderr new file mode 100644 index 000000000..0e86561aa --- /dev/null +++ b/tests/ui/impl-trait/issue-72911.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `foo` + --> $DIR/issue-72911.rs:11:33 + | +LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator { + | ^^^ use of undeclared crate or module `foo` + +error[E0433]: failed to resolve: use of undeclared crate or module `foo` + --> $DIR/issue-72911.rs:16:41 + | +LL | fn lint_files() -> impl Iterator { + | ^^^ use of undeclared crate or module `foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/impl-trait/issue-86465.rs b/tests/ui/impl-trait/issue-86465.rs new file mode 100644 index 000000000..8c7b41d73 --- /dev/null +++ b/tests/ui/impl-trait/issue-86465.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type X<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) { + (a, a) + //~^ ERROR concrete type differs from previous defining opaque type use +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-86465.stderr b/tests/ui/impl-trait/issue-86465.stderr new file mode 100644 index 000000000..b949b2b42 --- /dev/null +++ b/tests/ui/impl-trait/issue-86465.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-86465.rs:10:5 + | +LL | (a, a) + | ^^^^^^ + | | + | expected `&'a u32`, got `&'b u32` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issue-87450.rs b/tests/ui/impl-trait/issue-87450.rs new file mode 100644 index 000000000..983ef7cfb --- /dev/null +++ b/tests/ui/impl-trait/issue-87450.rs @@ -0,0 +1,16 @@ +fn bar() -> impl Fn() { + wrap(wrap(wrap(wrap(foo())))) +} + +fn foo() -> impl Fn() { + //~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion] + //~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720] + wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) +} + +fn wrap(f: impl Fn()) -> impl Fn() { + move || f() +} + +fn main() { +} diff --git a/tests/ui/impl-trait/issue-87450.stderr b/tests/ui/impl-trait/issue-87450.stderr new file mode 100644 index 000000000..173fca63f --- /dev/null +++ b/tests/ui/impl-trait/issue-87450.stderr @@ -0,0 +1,27 @@ +warning: function cannot return without recursing + --> $DIR/issue-87450.rs:5:1 + | +LL | fn foo() -> impl Fn() { + | ^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0720]: cannot resolve opaque type + --> $DIR/issue-87450.rs:5:13 + | +LL | fn foo() -> impl Fn() { + | ^^^^^^^^^ recursive opaque type +... +LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) + | ----------------------------------------------- returning here with type `impl Fn()` +... +LL | fn wrap(f: impl Fn()) -> impl Fn() { + | --------- returning this opaque type `impl Fn()` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issue-99073-2.rs b/tests/ui/impl-trait/issue-99073-2.rs new file mode 100644 index 000000000..14ac68880 --- /dev/null +++ b/tests/ui/impl-trait/issue-99073-2.rs @@ -0,0 +1,17 @@ +use std::fmt::Display; + +fn main() { + test("hi", true); +} + +fn test(t: T, recurse: bool) -> impl Display { + let f = || { + let i: u32 = test::(-1, false); + //~^ ERROR concrete type differs from previous defining opaque type use + println!("{i}"); + }; + if recurse { + f(); + } + t +} diff --git a/tests/ui/impl-trait/issue-99073-2.stderr b/tests/ui/impl-trait/issue-99073-2.stderr new file mode 100644 index 000000000..913bc8f56 --- /dev/null +++ b/tests/ui/impl-trait/issue-99073-2.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-99073-2.rs:9:22 + | +LL | let i: u32 = test::(-1, false); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32` + | +note: previous use here + --> $DIR/issue-99073-2.rs:16:5 + | +LL | t + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issue-99073.rs b/tests/ui/impl-trait/issue-99073.rs new file mode 100644 index 000000000..7798e247d --- /dev/null +++ b/tests/ui/impl-trait/issue-99073.rs @@ -0,0 +1,8 @@ +fn main() { + let _ = fix(|_: &dyn Fn()| {}); +} + +fn fix(f: F) -> impl Fn() { + move || f(fix(&f)) + //~^ ERROR concrete type differs from previous defining opaque type use +} diff --git a/tests/ui/impl-trait/issue-99073.stderr b/tests/ui/impl-trait/issue-99073.stderr new file mode 100644 index 000000000..546367953 --- /dev/null +++ b/tests/ui/impl-trait/issue-99073.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-99073.rs:6:11 + | +LL | move || f(fix(&f)) + | ^^^^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G` + | +note: previous use here + --> $DIR/issue-99073.rs:6:3 + | +LL | move || f(fix(&f)) + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issue-99642-2.rs b/tests/ui/impl-trait/issue-99642-2.rs new file mode 100644 index 000000000..0e88b3633 --- /dev/null +++ b/tests/ui/impl-trait/issue-99642-2.rs @@ -0,0 +1,8 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +type Opq = impl Sized; +fn test() -> impl Iterator { + Box::new(0..) as Box> +} +fn main(){} diff --git a/tests/ui/impl-trait/issue-99642.rs b/tests/ui/impl-trait/issue-99642.rs new file mode 100644 index 000000000..75af60491 --- /dev/null +++ b/tests/ui/impl-trait/issue-99642.rs @@ -0,0 +1,7 @@ +// check-pass + +fn test() -> impl Iterator { + Box::new(0..) as Box> +} + +fn main() {} diff --git a/tests/ui/impl-trait/issue-99914.rs b/tests/ui/impl-trait/issue-99914.rs new file mode 100644 index 000000000..4324a0229 --- /dev/null +++ b/tests/ui/impl-trait/issue-99914.rs @@ -0,0 +1,13 @@ +// edition:2021 + +fn main() {} + +struct Error; +struct Okay; + +fn foo(t: Result) { + t.and_then(|t| -> _ { bar(t) }); + //~^ ERROR mismatched types +} + +async fn bar(t: Okay) {} diff --git a/tests/ui/impl-trait/issue-99914.stderr b/tests/ui/impl-trait/issue-99914.stderr new file mode 100644 index 000000000..074d5d58d --- /dev/null +++ b/tests/ui/impl-trait/issue-99914.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-99914.rs:9:27 + | +LL | t.and_then(|t| -> _ { bar(t) }); + | ^^^^^^ expected enum `Result`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-99914.rs:13:23 + | +LL | async fn bar(t: Okay) {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected enum `Result<_, Error>` + found opaque type `impl Future` +help: try wrapping the expression in `Ok` + | +LL | t.and_then(|t| -> _ { Ok(bar(t)) }); + | +++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs b/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs new file mode 100644 index 000000000..451ddb3cc --- /dev/null +++ b/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs @@ -0,0 +1,25 @@ +// Test that attempts to construct infinite types via impl trait fail +// in a graceful way. +// +// Regression test for #38064. + +trait Quux {} + +fn foo() -> impl Quux { //~ ERROR cannot resolve opaque type + struct Foo(T); + impl Quux for Foo {} + Foo(bar()) +} + +fn bar() -> impl Quux { //~ ERROR cannot resolve opaque type + struct Bar(T); + impl Quux for Bar {} + Bar(foo()) +} + +// effectively: +// struct Foo(Bar); +// struct Bar(Foo); +// should produce an error about infinite size + +fn main() { foo(); } diff --git a/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr b/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr new file mode 100644 index 000000000..16a1262ec --- /dev/null +++ b/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr @@ -0,0 +1,27 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/infinite-impl-trait-issue-38064.rs:8:13 + | +LL | fn foo() -> impl Quux { + | ^^^^^^^^^ recursive opaque type +... +LL | Foo(bar()) + | ---------- returning here with type `Foo` +... +LL | fn bar() -> impl Quux { + | --------- returning this opaque type `Foo` + +error[E0720]: cannot resolve opaque type + --> $DIR/infinite-impl-trait-issue-38064.rs:14:13 + | +LL | fn foo() -> impl Quux { + | --------- returning this opaque type `Bar` +... +LL | fn bar() -> impl Quux { + | ^^^^^^^^^ recursive opaque type +... +LL | Bar(foo()) + | ---------- returning here with type `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issues/issue-104815.rs b/tests/ui/impl-trait/issues/issue-104815.rs new file mode 100644 index 000000000..7a9826a8d --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-104815.rs @@ -0,0 +1,66 @@ +// check-pass + +struct It; + +struct Data { + items: Vec, +} + +impl Data { + fn new() -> Self { + Self { + items: vec![It, It], + } + } + + fn content(&self) -> impl Iterator { + self.items.iter() + } +} + +struct Container<'a> { + name: String, + resolver: Box, +} + +impl<'a> Container<'a> { + fn new(name: &str, resolver: R) -> Self { + Self { + name: name.to_owned(), + resolver: Box::new(resolver), + } + } +} + +trait Resolver {} + +impl Resolver for &R {} + +impl Resolver for It {} + +fn get<'a>(mut items: impl Iterator) -> impl Resolver + 'a { + items.next().unwrap() +} + +fn get2<'a, 'b: 'b>(mut items: impl Iterator) -> impl Resolver + 'a { + items.next().unwrap() +} + +fn main() { + let data = Data::new(); + let resolver = get(data.content()); + + let _ = ["a", "b"] + .iter() + .map(|&n| Container::new(n, &resolver)) + .map(|c| c.name) + .collect::>(); + + let resolver = get2(data.content()); + + let _ = ["a", "b"] + .iter() + .map(|&n| Container::new(n, &resolver)) + .map(|c| c.name) + .collect::>(); +} diff --git a/tests/ui/impl-trait/issues/issue-105826.rs b/tests/ui/impl-trait/issues/issue-105826.rs new file mode 100644 index 000000000..06dc2d4c8 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-105826.rs @@ -0,0 +1,39 @@ +// check-pass + +use std::io::Write; + +struct A(Vec); + +struct B<'a> { + one: &'a mut A, + two: &'a mut Vec, + three: Vec, +} + +impl<'a> B<'a> { + fn one(&mut self) -> &mut impl Write { + &mut self.one.0 + } + fn two(&mut self) -> &mut impl Write { + &mut *self.two + } + fn three(&mut self) -> &mut impl Write { + &mut self.three + } +} + +struct C<'a>(B<'a>); + +impl<'a> C<'a> { + fn one(&mut self) -> &mut impl Write { + self.0.one() + } + fn two(&mut self) -> &mut impl Write { + self.0.two() + } + fn three(&mut self) -> &mut impl Write { + self.0.three() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs b/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs new file mode 100644 index 000000000..41f48cb56 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs @@ -0,0 +1,22 @@ +trait Foo { + fn foo(&self, a: A) -> A { + a + } +} + +trait NotRelevant { + fn nr(&self, a: A) -> A { + a + } +} + +struct Bar; + +impl NotRelevant for Bar {} + +fn main() { + let f1 = Bar; + + f1.foo(1usize); + //~^ error: method named `foo` found for struct `Bar` in the current scope +} diff --git a/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr new file mode 100644 index 000000000..9150d957d --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `foo` found for struct `Bar` in the current scope + --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 + | +LL | struct Bar; + | ---------- method `foo` not found for this struct +... +LL | f1.foo(1usize); + | ^^^ method not found in `Bar` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo`, perhaps you need to implement it + --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/issues/issue-42479.rs b/tests/ui/impl-trait/issues/issue-42479.rs new file mode 100644 index 000000000..efc1f975d --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-42479.rs @@ -0,0 +1,17 @@ +// check-pass + +use std::iter::once; + +struct Foo { + x: i32, +} + +impl Foo { + fn inside(&self) -> impl Iterator { + once(&self.x) + } +} + +fn main() { + println!("hi"); +} diff --git a/tests/ui/impl-trait/issues/issue-49376.rs b/tests/ui/impl-trait/issues/issue-49376.rs new file mode 100644 index 000000000..e4472fcc1 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-49376.rs @@ -0,0 +1,23 @@ +// check-pass + +// Tests for nested self-reference which caused a stack overflow. + +use std::fmt::Debug; +use std::ops::*; + +fn gen() -> impl PartialOrd + PartialEq + Debug { } + +struct Bar {} +trait Foo {} +trait FooNested> {} +impl Foo for Bar {} +impl FooNested for Bar {} + +fn foo() -> impl Foo + FooNested { + Bar {} +} + +fn test_impl_ops() -> impl Add + Sub + Mul + Div { 1 } +fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign { 1 } + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-52128.rs b/tests/ui/impl-trait/issues/issue-52128.rs new file mode 100644 index 000000000..5afd380dd --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-52128.rs @@ -0,0 +1,25 @@ +// check-pass + +#![deny(warnings)] + +use std::collections::BTreeMap; + +pub struct RangeMap { + map: BTreeMap, +} + +#[derive(Eq, PartialEq, Ord, PartialOrd)] +struct Range; + +impl RangeMap { + fn iter_with_range<'a>(&'a self) -> impl Iterator + 'a { + self.map.range(Range..Range) + } + + pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + self.iter_with_range().map(|(_, data)| data) + } + +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-53457.rs b/tests/ui/impl-trait/issues/issue-53457.rs new file mode 100644 index 000000000..7b9c2c53a --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-53457.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +type X = impl Clone; + +fn bar(f: F) -> F { + f +} + +fn foo() -> X { + bar(|_| ()) +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-54600.rs b/tests/ui/impl-trait/issues/issue-54600.rs new file mode 100644 index 000000000..3024fedf7 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54600.rs @@ -0,0 +1,7 @@ +use std::fmt::Debug; + +fn main() { + let x: Option = Some(44_u32); + //~^ `impl Trait` only allowed in function and inherent method return types + println!("{:?}", x); +} diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr new file mode 100644 index 000000000..316566a57 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54600.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-54600.rs:4:19 + | +LL | let x: Option = Some(44_u32); + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-54840.rs b/tests/ui/impl-trait/issues/issue-54840.rs new file mode 100644 index 000000000..8f1e0ece0 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54840.rs @@ -0,0 +1,7 @@ +use std::ops::Add; + +fn main() { + let i: i32 = 0; + let j: &impl Add = &i; + //~^ `impl Trait` only allowed in function and inherent method return types +} diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr new file mode 100644 index 000000000..8d82133ac --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54840.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-54840.rs:5:13 + | +LL | let j: &impl Add = &i; + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs new file mode 100644 index 000000000..8d7a1d56f --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54895.rs @@ -0,0 +1,22 @@ +trait Trait<'a> { + type Out; + fn call(&'a self) -> Self::Out; +} + +struct X(()); + +impl<'a> Trait<'a> for X { + type Out = (); + fn call(&'a self) -> Self::Out { + () + } +} + +fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + X(()) +} + +fn main() { + let _ = f(); +} diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.stderr new file mode 100644 index 000000000..7d22f027a --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54895.stderr @@ -0,0 +1,14 @@ +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/issue-54895.rs:15:53 + | +LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + | ^^ + | +note: lifetime declared here + --> $DIR/issue-54895.rs:15:20 + | +LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issues/issue-55608-captures-empty-region.rs b/tests/ui/impl-trait/issues/issue-55608-captures-empty-region.rs new file mode 100644 index 000000000..0c34c97e2 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-55608-captures-empty-region.rs @@ -0,0 +1,22 @@ +// This used to ICE because it creates an `impl Trait` that captures a +// hidden empty region. + +// check-pass + +fn server() -> impl FilterBase2 { + segment2(|| { loop { } }).map2(|| "") +} + +trait FilterBase2 { + fn map2(self, _fn: F) -> Map2 where Self: Sized { loop { } } +} + +struct Map2 { _func: F } + +impl FilterBase2 for Map2 { } + +fn segment2(_fn: F) -> Map2 where F: Fn() -> Result<(), ()> { + loop { } +} + +fn main() { server(); } diff --git a/tests/ui/impl-trait/issues/issue-57464-unexpected-regions.rs b/tests/ui/impl-trait/issues/issue-57464-unexpected-regions.rs new file mode 100644 index 000000000..c4f738a34 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57464-unexpected-regions.rs @@ -0,0 +1,29 @@ +// Regression test for issue 57464. +// +// Closure are (surprisingly) allowed to outlive their signature. As such it +// was possible to end up with `ReScope`s appearing in the concrete type of an +// opaque type. As all regions are now required to outlive the bound in an +// opaque type we avoid the issue here. + +// check-pass + +struct A(F); + +unsafe impl <'a, 'b, F: Fn(&'a i32) -> &'b i32> Send for A {} + +fn wrapped_closure() -> impl Sized { + let f = |x| x; + f(&0); + A(f) +} + +fn wrapped_closure_with_bound() -> impl Sized + 'static { + let f = |x| x; + f(&0); + A(f) +} + +fn main() { + let x: Box = Box::new(wrapped_closure()); + let y: Box = Box::new(wrapped_closure_with_bound()); +} diff --git a/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs b/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs new file mode 100644 index 000000000..0daec3305 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs @@ -0,0 +1,17 @@ +// rust-lang/rust#57979 : the initial support for `impl Trait` didn't +// properly check syntax hidden behind an associated type projection, +// but it did catch *some cases*. This is checking that we continue to +// properly emit errors for those. +// +// issue-57979-nested-impl-trait-in-assoc-proj.rs shows the main case +// that we were previously failing to catch. + +struct Deeper(T); + +pub trait Foo { } +pub trait Bar { } +pub trait Quux { type Assoc; } +pub fn demo(_: impl Quux>>) { } +//~^ ERROR nested `impl Trait` is not allowed + +fn main() { } diff --git a/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr b/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr new file mode 100644 index 000000000..6bebbc01f --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.stderr @@ -0,0 +1,12 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:14:48 + | +LL | pub fn demo(_: impl Quux>>) { } + | ---------^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0666`. diff --git a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs new file mode 100644 index 000000000..c5ecd1caa --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs @@ -0,0 +1,12 @@ +// rust-lang/rust#57979 : the initial support for `impl Trait` didn't +// properly check syntax hidden behind an associated type projection. +// Here we test behavior of occurrences of `impl Trait` within a path +// component in that context. + +pub trait Bar { } +pub trait Quux { type Assoc; } +pub fn demo(_: impl Quux<(), Assoc=<() as Quux>::Assoc>) { } +//~^ ERROR `impl Trait` is not allowed in path parameters +impl Quux for () { type Assoc = u32; } + +fn main() { } diff --git a/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr new file mode 100644 index 000000000..e31393181 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr @@ -0,0 +1,9 @@ +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/issue-57979-impl-trait-in-path.rs:8:48 + | +LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux>::Assoc>) { } + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0667`. diff --git a/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs b/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs new file mode 100644 index 000000000..5a444d3df --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs @@ -0,0 +1,12 @@ +// rust-lang/rust#57979 : the initial support for `impl Trait` didn't +// properly check syntax hidden behind an associated type projection. +// Here we test behavior of occurrences of `impl Trait` within an +// `impl Trait` in that context. + +pub trait Foo { } +pub trait Bar { } +pub trait Quux { type Assoc; } +pub fn demo(_: impl Quux>) { } +//~^ ERROR nested `impl Trait` is not allowed + +fn main() { } diff --git a/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr b/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr new file mode 100644 index 000000000..8d3d4b5e2 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.stderr @@ -0,0 +1,12 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:9:41 + | +LL | pub fn demo(_: impl Quux>) { } + | ---------^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0666`. diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs new file mode 100644 index 000000000..e5865d0df --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-58504.rs @@ -0,0 +1,12 @@ +#![feature(generators, generator_trait, never_type)] + +use std::ops::Generator; + +fn mk_gen() -> impl Generator { + || { loop { yield; } } +} + +fn main() { + let gens: [impl Generator;2] = [ mk_gen(), mk_gen() ]; + //~^ `impl Trait` only allowed in function and inherent method return types +} diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr new file mode 100644 index 000000000..6656e9fc3 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-58504.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-58504.rs:10:16 + | +LL | let gens: [impl Generator;2] = [ mk_gen(), mk_gen() ]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-58956.rs b/tests/ui/impl-trait/issues/issue-58956.rs new file mode 100644 index 000000000..68cfcd9ba --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-58956.rs @@ -0,0 +1,14 @@ +trait Lam {} + +pub struct B; +impl Lam for B {} +pub struct Wrap(T); + +const _A: impl Lam = { + //~^ `impl Trait` only allowed in function and inherent method return types + let x: Wrap = Wrap(B); + //~^ `impl Trait` only allowed in function and inherent method return types + x.0 +}; + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr new file mode 100644 index 000000000..123fb4df4 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-58956.stderr @@ -0,0 +1,15 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-58956.rs:7:11 + | +LL | const _A: impl Lam = { + | ^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-58956.rs:9:17 + | +LL | let x: Wrap = Wrap(B); + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs new file mode 100644 index 000000000..041bd0e38 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -0,0 +1,32 @@ +use std::marker::PhantomData; + +fn _alias_check() { + WrongImpl::foo(0i32); + //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied + WrongImpl::<()>::foo(0i32); + //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied + //~| ERROR trait bounds were not satisfied + CorrectImpl::foo(0i32); +} + +pub trait Raw { + type Value; +} + +pub type WrongImpl = SafeImpl>; + +pub type CorrectImpl = SafeImpl<[T], RawImpl>; + +pub struct RawImpl(PhantomData); + +impl Raw<[T]> for RawImpl { + type Value = T; +} + +pub struct SafeImpl>(PhantomData<(A, T)>); + +impl> SafeImpl { + pub fn foo(value: A::Value) {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr new file mode 100644 index 000000000..d872291c8 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -0,0 +1,55 @@ +error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied + --> $DIR/issue-62742.rs:4:5 + | +LL | WrongImpl::foo(0i32); + | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | + = help: the trait `Raw<[T]>` is implemented for `RawImpl` +note: required by a bound in `SafeImpl` + --> $DIR/issue-62742.rs:26:35 + | +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ^^^^^^ required by this bound in `SafeImpl` + +error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied + --> $DIR/issue-62742.rs:6:22 + | +LL | WrongImpl::<()>::foo(0i32); + | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds +... +LL | pub struct RawImpl(PhantomData); + | --------------------- doesn't satisfy `RawImpl<()>: Raw<()>` +... +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ----------------------------------------- function or associated item `foo` not found for this struct + | +note: trait bound `RawImpl<()>: Raw<()>` was not satisfied + --> $DIR/issue-62742.rs:28:20 + | +LL | impl> SafeImpl { + | ^^^^^^ -------------- + | | + | unsatisfied trait bound introduced here +note: the trait `Raw` must be implemented + --> $DIR/issue-62742.rs:12:1 + | +LL | pub trait Raw { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied + --> $DIR/issue-62742.rs:6:5 + | +LL | WrongImpl::<()>::foo(0i32); + | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` + | + = help: the trait `Raw<[T]>` is implemented for `RawImpl` +note: required by a bound in `SafeImpl` + --> $DIR/issue-62742.rs:26:35 + | +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ^^^^^^ required by this bound in `SafeImpl` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issues/issue-65581.rs b/tests/ui/impl-trait/issues/issue-65581.rs new file mode 100644 index 000000000..b947fc1d2 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-65581.rs @@ -0,0 +1,34 @@ +// check-pass +// ignore-compare-mode-chalk + +#![allow(dead_code)] + +trait Trait1 { + fn f1(self) -> U; +} + +trait Trait2 { + type T; + type U: Trait2; + fn f2(f: impl FnOnce(&Self::U)); +} + +fn f3() -> impl Trait1 { + Struct1 +} + +struct Struct1; + +impl Trait1 for Struct1 { + fn f1(self) -> T::T { + unimplemented!() + } +} + +fn f4() { + T::f2(|_| { + f3::().f1(); + }); +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs new file mode 100644 index 000000000..92f7e005d --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-67830.rs @@ -0,0 +1,26 @@ +trait MyFn { + type Output; + fn call(&self, arg: Arg) -> Self::Output; +} + +struct Wrap(F); + +impl MyFn for Wrap +where + F: Fn(A) -> B +{ + type Output = B; + + fn call(&self, arg: A) -> Self::Output { + (self.0)(arg) + } +} + + +struct A; +fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + Wrap(|a| Some(a).into_iter()) +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr new file mode 100644 index 000000000..d3ea8cb03 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-67830.stderr @@ -0,0 +1,14 @@ +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/issue-67830.rs:21:62 + | +LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { + | ^^ + | +note: lifetime declared here + --> $DIR/issue-67830.rs:21:23 + | +LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issues/issue-70877.rs b/tests/ui/impl-trait/issues/issue-70877.rs new file mode 100644 index 000000000..8169cfafa --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-70877.rs @@ -0,0 +1,36 @@ +#![feature(type_alias_impl_trait)] + +type FooArg<'a> = &'a dyn ToString; +type FooRet = impl std::fmt::Debug; + +type FooItem = Box FooRet>; +type Foo = impl Iterator; + +#[repr(C)] +struct Bar(u8); + +impl Iterator for Bar { + type Item = FooItem; + + fn next(&mut self) -> Option { + Some(Box::new(quux)) + } +} + +fn quux(st: FooArg) -> FooRet { + Some(st.to_string()) +} + +fn ham() -> Foo { + Bar(1) +} + +fn oof() -> impl std::fmt::Debug { + let mut bar = ham(); + let func = bar.next().unwrap(); + return func(&"oof"); //~ ERROR opaque type's hidden type cannot be another opaque type +} + +fn main() { + let _ = oof(); +} diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr new file mode 100644 index 000000000..8813bff3c --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-70877.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/issue-70877.rs:31:12 + | +LL | return func(&"oof"); + | ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/issue-70877.rs:28:13 + | +LL | fn oof() -> impl std::fmt::Debug { + | ^^^^^^^^^^^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/issue-70877.rs:4:15 + | +LL | type FooRet = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issues/issue-70971.rs b/tests/ui/impl-trait/issues/issue-70971.rs new file mode 100644 index 000000000..f8ae18bac --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-70971.rs @@ -0,0 +1,4 @@ +fn main() { + let x : (impl Copy,) = (true,); + //~^ `impl Trait` only allowed in function and inherent method return types +} diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr new file mode 100644 index 000000000..4dda4c22a --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-70971.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-70971.rs:2:14 + | +LL | let x : (impl Copy,) = (true,); + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-74282.rs b/tests/ui/impl-trait/issues/issue-74282.rs new file mode 100644 index 000000000..654de0cd0 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-74282.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +type Closure = impl Fn() -> u64; +struct Anonymous(Closure); + +fn main() { + let y = || -> Closure { || 3 }; + Anonymous(|| { //~ ERROR mismatched types + 3 //~^ ERROR mismatched types + }) +} diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr new file mode 100644 index 000000000..5b05fb281 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-74282.stderr @@ -0,0 +1,40 @@ +error[E0308]: mismatched types + --> $DIR/issue-74282.rs:8:15 + | +LL | type Closure = impl Fn() -> u64; + | ---------------- the expected opaque type +... +LL | Anonymous(|| { + | _____---------_^ + | | | + | | arguments to this struct are incorrect +LL | | 3 +LL | | }) + | |_____^ expected closure, found a different closure + | + = note: expected opaque type `Closure` + found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]` + = note: no two closures, even if identical, have the same type + = help: consider boxing your closure and/or using it as a trait object +note: tuple struct defined here + --> $DIR/issue-74282.rs:4:8 + | +LL | struct Anonymous(Closure); + | ^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-74282.rs:8:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | let y = || -> Closure { || 3 }; +LL | / Anonymous(|| { +LL | | 3 +LL | | }) + | | ^- help: consider using a semicolon here: `;` + | |______| + | expected `()`, found struct `Anonymous` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/issues/issue-77987.rs b/tests/ui/impl-trait/issues/issue-77987.rs new file mode 100644 index 000000000..d29710b6f --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-77987.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Foo {} +impl Foo for U {} + +type Scope = impl Foo<()>; + +#[allow(unused)] +fn infer_scope() -> Scope { + () +} + +#[allow(unused)] +fn ice() -> impl Foo +{ + loop {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-78722.rs b/tests/ui/impl-trait/issues/issue-78722.rs new file mode 100644 index 000000000..78233f300 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-78722.rs @@ -0,0 +1,20 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +type F = impl core::future::Future; + +struct Bug { + V1: [(); { + fn concrete_use() -> F { + //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()` + async {} + } + let f: F = async { 1 }; + //~^ ERROR `async` blocks are not allowed in constants + //~| ERROR destructor of + 1 + }], +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr new file mode 100644 index 000000000..c00df8087 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-78722.stderr @@ -0,0 +1,28 @@ +error[E0658]: `async` blocks are not allowed in constants + --> $DIR/issue-78722.rs:13:20 + | +LL | let f: F = async { 1 }; + | ^^^^^^^^^^^ + | + = note: see issue #85368 for more information + = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/issue-78722.rs:13:13 + | +LL | let f: F = async { 1 }; + | ^ the destructor for this type cannot be evaluated in constants +... +LL | }], + | - value is dropped here + +error[E0271]: expected `[async block@$DIR/issue-78722.rs:11:13: 11:21]` to be a future that resolves to `u8`, but it resolves to `()` + --> $DIR/issue-78722.rs:9:30 + | +LL | fn concrete_use() -> F { + | ^ expected `()`, found `u8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0271, E0493, E0658. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs new file mode 100644 index 000000000..da53594f3 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-79099.rs @@ -0,0 +1,10 @@ +struct Bug { + V1: [(); { + let f: impl core::future::Future = async { 1 }; + //~^ `impl Trait` only allowed in function and inherent method return types + //~| expected identifier + 1 + }], +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr new file mode 100644 index 000000000..362c67daf --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-79099.stderr @@ -0,0 +1,20 @@ +error: expected identifier, found `1` + --> $DIR/issue-79099.rs:3:65 + | +LL | let f: impl core::future::Future = async { 1 }; + | ----- ^ expected identifier + | | + | `async` blocks are only allowed in Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-79099.rs:3:16 + | +LL | let f: impl core::future::Future = async { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-82139.rs b/tests/ui/impl-trait/issues/issue-82139.rs new file mode 100644 index 000000000..cc9167b34 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-82139.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +trait Trait { + type Associated; + fn func() -> Self::Associated; +} + +trait Bound {} +pub struct Struct; + +impl Trait for Struct { + type Associated = impl Bound; + + fn func() -> Self::Associated { + Some(42).map(|_| j) //~ ERROR cannot find value `j` in this scope + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-82139.stderr b/tests/ui/impl-trait/issues/issue-82139.stderr new file mode 100644 index 000000000..0adcd4a7a --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-82139.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `j` in this scope + --> $DIR/issue-82139.rs:15:26 + | +LL | Some(42).map(|_| j) + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/impl-trait/issues/issue-83919.rs b/tests/ui/impl-trait/issues/issue-83919.rs new file mode 100644 index 000000000..e76443a65 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-83919.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] + +// edition:2021 + +use std::future::Future; + +trait Foo { + type T; + type Fut2: Future; // ICE got triggered with traits other than Future here + type Fut: Future; + fn get_fut(&self) -> Self::Fut; +} + +struct Implementor; + +impl Foo for Implementor { + type T = u64; + type Fut2 = impl Future; + type Fut = impl Future; + + fn get_fut(&self) -> Self::Fut { + //~^ ERROR `{integer}` is not a future + async move { + 42 + // 42 does not impl Future and rustc does actually point out the error, + // but rustc used to panic. + // Putting a valid Future here always worked fine. + } + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-83919.stderr b/tests/ui/impl-trait/issues/issue-83919.stderr new file mode 100644 index 000000000..d39dcf7fb --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-83919.stderr @@ -0,0 +1,12 @@ +error[E0277]: `{integer}` is not a future + --> $DIR/issue-83919.rs:21:26 + | +LL | fn get_fut(&self) -> Self::Fut { + | ^^^^^^^^^ `{integer}` is not a future + | + = help: the trait `Future` is not implemented for `{integer}` + = note: {integer} must be a future or must implement `IntoFuture` to be awaited + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs new file mode 100644 index 000000000..344f35952 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs @@ -0,0 +1,12 @@ +struct Foo(T); +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +type Result = std::result::Result; +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// should not cause ICE +fn x() -> Foo { + Foo(0) +} + +fn main() -> Result<()> {} diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr new file mode 100644 index 000000000..e635e554e --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr @@ -0,0 +1,15 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16 + | +LL | struct Foo(T); + | ^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20 + | +LL | type Result = std::result::Result; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs new file mode 100644 index 000000000..49a34ccfa --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-84073.rs @@ -0,0 +1,33 @@ +use std::marker::PhantomData; + +pub trait StatefulFuture {} +pub struct Never(PhantomData); +impl StatefulFuture for Never {} + +pub struct RaceBuilder { + future: F, + _phantom: PhantomData, +} + +impl RaceBuilder +where + F: StatefulFuture>, +{ + pub fn when(self) {} +} + +pub struct Race { + race: R, + _phantom: PhantomData, +} + +impl Race +where + R: Fn(RaceBuilder>), +{ + pub fn new(race: R) {} +} + +fn main() { + Race::new(|race| race.when()); //~ ERROR type annotations needed +} diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr new file mode 100644 index 000000000..3c39aa6ce --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `RaceBuilder>` + --> $DIR/issue-84073.rs:32:16 + | +LL | Race::new(|race| race.when()); + | ^^^^ + | +help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified + | +LL | Race::new(|race: RaceBuilder>| race.when()); + | ++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/issues/issue-84919.rs b/tests/ui/impl-trait/issues/issue-84919.rs new file mode 100644 index 000000000..a0b73743a --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-84919.rs @@ -0,0 +1,9 @@ +trait Trait {} +impl Trait for () {} + +fn foo<'a: 'a>() { + let _x: impl Trait = (); + //~^ `impl Trait` only allowed in function and inherent method return types +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr new file mode 100644 index 000000000..5abe1bd87 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-84919.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-84919.rs:5:13 + | +LL | let _x: impl Trait = (); + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-86201.rs b/tests/ui/impl-trait/issues/issue-86201.rs new file mode 100644 index 000000000..0786e66ca --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86201.rs @@ -0,0 +1,13 @@ +#![feature(unboxed_closures)] +#![feature(type_alias_impl_trait)] + +// check-pass + +type FunType = impl Fn<()>; +static STATIC_FN: FunType = some_fn; + +fn some_fn() {} + +fn main() { + let _: >::Output = STATIC_FN(); +} diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs new file mode 100644 index 000000000..e6e957714 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86642.rs @@ -0,0 +1,8 @@ +static x: impl Fn(&str) -> Result<&str, ()> = move |source| { + //~^ `impl Trait` only allowed in function and inherent method return types + let res = (move |source| Ok(source))(source); + let res = res.or((move |source| Ok(source))(source)); + res +}; + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr new file mode 100644 index 000000000..0ec118d5b --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86642.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-86642.rs:1:11 + | +LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-86719.rs b/tests/ui/impl-trait/issues/issue-86719.rs new file mode 100644 index 000000000..f4b0b3f33 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86719.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +trait Bar { + type E; +} +impl Bar for S { + type E = impl ; //~ ERROR at least one trait must be specified + fn foo() -> Self::E { //~ ERROR `foo` is not a member + |_| true //~ ERROR type annotations needed + } +} +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-86719.stderr b/tests/ui/impl-trait/issues/issue-86719.stderr new file mode 100644 index 000000000..7592418fd --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86719.stderr @@ -0,0 +1,29 @@ +error: at least one trait must be specified + --> $DIR/issue-86719.rs:7:14 + | +LL | type E = impl ; + | ^^^^ + +error[E0407]: method `foo` is not a member of trait `Bar` + --> $DIR/issue-86719.rs:8:5 + | +LL | / fn foo() -> Self::E { +LL | | |_| true +LL | | } + | |_____^ not a member of trait `Bar` + +error[E0282]: type annotations needed + --> $DIR/issue-86719.rs:9:10 + | +LL | |_| true + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | |_: /* Type */| true + | ++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0282, E0407. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs new file mode 100644 index 000000000..351243c67 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86800.rs @@ -0,0 +1,55 @@ +#![feature(type_alias_impl_trait)] + +// edition:2021 +// unset-rustc-env:RUST_BACKTRACE +// compile-flags:-Z treat-err-as-bug=1 +// error-pattern:stack backtrace: +// failure-status:101 +// normalize-stderr-test "note: .*" -> "" +// normalize-stderr-test "thread 'rustc' .*" -> "" +// normalize-stderr-test " +[0-9]+:.*\n" -> "" +// normalize-stderr-test " +at .*\n" -> "" + +use std::future::Future; + +struct Connection { +} + +trait Transaction { +} + +struct TestTransaction<'conn> { + conn: &'conn Connection +} + +impl<'conn> Transaction for TestTransaction<'conn> { +} + +struct Context { +} + +type TransactionResult = Result; + +type TransactionFuture<'__, O> = impl '__ + Future>; + +fn execute_transaction_fut<'f, F, O>( + f: F, +) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> +where + F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f +{ + f +} + +impl Context { + async fn do_transaction( + &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + ) -> TransactionResult + { + let mut conn = Connection {}; + let mut transaction = TestTransaction { conn: &mut conn }; + f(&mut transaction).await + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr new file mode 100644 index 000000000..6c4aa3567 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -0,0 +1,26 @@ +error: unconstrained opaque type + --> $DIR/issue-86800.rs:33:34 + | +LL | type TransactionFuture<'__, O> = impl '__ + Future>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = + + +stack backtrace: + +error: internal compiler error: unexpected panic + + + + + + + + + +query stack during panic: +#0 [type_of] computing type of `TransactionFuture::{opaque#0}` +#1 [check_mod_item_types] checking item types in top-level module +#2 [analysis] running analysis passes on this crate +end of query stack diff --git a/tests/ui/impl-trait/issues/issue-87295.rs b/tests/ui/impl-trait/issues/issue-87295.rs new file mode 100644 index 000000000..aeb8f8332 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-87295.rs @@ -0,0 +1,18 @@ +trait Trait { + type Output; +} +impl Trait for () { + type Output = i32; +} + +struct Struct(F); +impl Struct { + pub fn new(_: F) -> Self { + todo!() + } +} + +fn main() { + let _do_not_waste: Struct> = Struct::new(()); + //~^ `impl Trait` only allowed in function and inherent method return types +} diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr new file mode 100644 index 000000000..0b043056b --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-87295.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-87295.rs:16:31 + | +LL | let _do_not_waste: Struct> = Struct::new(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-87340.rs b/tests/ui/impl-trait/issues/issue-87340.rs new file mode 100644 index 000000000..f0f6d2bb6 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-87340.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +trait X { + type I; + fn f() -> Self::I; +} + +impl X for () { +//~^ ERROR `T` is not constrained by the impl trait, self type, or predicates + type I = impl Sized; + fn f() -> Self::I {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-87340.stderr b/tests/ui/impl-trait/issues/issue-87340.stderr new file mode 100644 index 000000000..2ab1e6a03 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-87340.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-87340.rs:8:6 + | +LL | impl X for () { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs new file mode 100644 index 000000000..fde8a6704 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-88236-2.rs @@ -0,0 +1,28 @@ +// this used to cause stack overflows + +trait Hrtb<'a> { + type Assoc; +} + +impl<'a> Hrtb<'a> for () { + type Assoc = (); +} + +impl<'a> Hrtb<'a> for &'a () { + type Assoc = (); +} + +fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} +//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + +fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + &() +} + +fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + x +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr new file mode 100644 index 000000000..8605d07ab --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr @@ -0,0 +1,38 @@ +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/issue-88236-2.rs:15:61 + | +LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} + | ^^ + | +note: lifetime declared here + --> $DIR/issue-88236-2.rs:15:28 + | +LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} + | ^^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/issue-88236-2.rs:18:80 + | +LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^ + | +note: lifetime declared here + --> $DIR/issue-88236-2.rs:18:47 + | +LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/issue-88236-2.rs:23:78 + | +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^ + | +note: lifetime declared here + --> $DIR/issue-88236-2.rs:23:45 + | +LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { + | ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/impl-trait/issues/issue-88236.rs b/tests/ui/impl-trait/issues/issue-88236.rs new file mode 100644 index 000000000..36d124173 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-88236.rs @@ -0,0 +1,18 @@ +// this used to cause stack overflows + +trait Hrtb<'a> { + type Assoc; +} + +impl<'a> Hrtb<'a> for () { + type Assoc = (); +} + +impl<'a> Hrtb<'a> for &'a () { + type Assoc = (); +} + +fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} +//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-88236.stderr b/tests/ui/impl-trait/issues/issue-88236.stderr new file mode 100644 index 000000000..7a4cc57b0 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-88236.stderr @@ -0,0 +1,14 @@ +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/issue-88236.rs:15:61 + | +LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} + | ^^ + | +note: lifetime declared here + --> $DIR/issue-88236.rs:15:28 + | +LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issues/issue-89312.rs b/tests/ui/impl-trait/issues/issue-89312.rs new file mode 100644 index 000000000..d685a6f12 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-89312.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait T { type Item; } + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} diff --git a/tests/ui/impl-trait/issues/issue-92305.rs b/tests/ui/impl-trait/issues/issue-92305.rs new file mode 100644 index 000000000..4a89238d0 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-92305.rs @@ -0,0 +1,14 @@ +// edition:2021 + +use std::iter; + +fn f(data: &[T]) -> impl Iterator { + //~^ ERROR: missing generics for struct `Vec` [E0107] + iter::empty() +} + +fn g(data: &[T], target: T) -> impl Iterator> { + f(data).filter(|x| x == target) +} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-92305.stderr b/tests/ui/impl-trait/issues/issue-92305.stderr new file mode 100644 index 000000000..86d7184da --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-92305.stderr @@ -0,0 +1,14 @@ +error[E0107]: missing generics for struct `Vec` + --> $DIR/issue-92305.rs:5:45 + | +LL | fn f(data: &[T]) -> impl Iterator { + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | fn f(data: &[T]) -> impl Iterator> { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/impl-trait/issues/issue-93788.rs b/tests/ui/impl-trait/issues/issue-93788.rs new file mode 100644 index 000000000..6924931cd --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-93788.rs @@ -0,0 +1,27 @@ +// check-pass + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { None } +} + +fn run(f: F) + where for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} diff --git a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs new file mode 100644 index 000000000..b05579f21 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +struct Concrete; + +type Tait = impl Sized; + +impl Foo for Concrete { + type Item = Concrete; + //~^ type mismatch resolving +} + +impl Bar for Concrete { + type Other = Tait; +} + +trait Foo { + type Item: Bar; +} + +trait Bar { + type Other; +} + +fn tait() -> Tait {} + +fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr new file mode 100644 index 000000000..f0dceb1b1 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr @@ -0,0 +1,25 @@ +error[E0271]: type mismatch resolving `::Other == Concrete` + --> $DIR/issue-99348-impl-compatibility.rs:8:17 + | +LL | type Tait = impl Sized; + | ---------- the found opaque type +... +LL | type Item = Concrete; + | ^^^^^^^^ type mismatch resolving `::Other == Concrete` + | +note: expected this to be `Concrete` + --> $DIR/issue-99348-impl-compatibility.rs:13:18 + | +LL | type Other = Tait; + | ^^^^ + = note: expected struct `Concrete` + found opaque type `Tait` +note: required by a bound in `Foo::Item` + --> $DIR/issue-99348-impl-compatibility.rs:17:20 + | +LL | type Item: Bar; + | ^^^^^^^^^^^^ required by this bound in `Foo::Item` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/lifetimes.rs b/tests/ui/impl-trait/lifetimes.rs new file mode 100644 index 000000000..9a9843375 --- /dev/null +++ b/tests/ui/impl-trait/lifetimes.rs @@ -0,0 +1,123 @@ +// run-pass + +#![allow(warnings)] +#![feature(generators)] + +use std::fmt::Debug; + +fn any_lifetime<'a>() -> &'a u32 { &5 } + +fn static_lifetime() -> &'static u32 { &5 } + +fn any_lifetime_as_static_impl_trait() -> impl Debug { + any_lifetime() +} + +fn lifetimes_as_static_impl_trait() -> impl Debug { + static_lifetime() +} + +fn no_params_or_lifetimes_is_static() -> impl Debug + 'static { + lifetimes_as_static_impl_trait() +} + +fn static_input_type_is_static(x: T) -> impl Debug + 'static { x } + +fn type_outlives_reference_lifetime<'a, T: Debug>(x: &'a T) -> impl Debug + 'a { x } +fn type_outlives_reference_lifetime_elided(x: &T) -> impl Debug + '_ { x } + +trait SingleRegionTrait<'a> {} +impl<'a> SingleRegionTrait<'a> for u32 {} +impl<'a> SingleRegionTrait<'a> for &'a u32 {} +struct SingleRegionStruct<'a>(&'a u32); + +fn simple_type_hrtb<'b>() -> impl for<'a> SingleRegionTrait<'a> { 5 } +fn elision_single_region_trait(x: &u32) -> impl SingleRegionTrait { x } +fn elision_single_region_struct(x: SingleRegionStruct) -> impl Into { x } + +fn closure_hrtb() -> impl for<'a> Fn(&'a u32) { |_| () } +fn closure_hr_elided() -> impl Fn(&u32) { |_| () } +fn closure_hr_elided_return() -> impl Fn(&u32) -> &u32 { |x| x } +fn closure_pass_through_elided_return(x: impl Fn(&u32) -> &u32) -> impl Fn(&u32) -> &u32 { x } +fn closure_pass_through_reference_elided(x: &impl Fn(&u32) -> &u32) -> &impl Fn(&u32) -> &u32 { x } + +fn nested_lifetime<'a>(input: &'a str) + -> impl Iterator + 'a> + 'a +{ + input.lines().map(|line| { + line.split_whitespace().map(|cell| cell.parse().unwrap()) + }) +} + +fn pass_through_elision(x: &u32) -> impl Into<&u32> { x } +fn pass_through_elision_with_fn_ptr(x: &fn(&u32) -> &u32) -> impl Into<&fn(&u32) -> &u32> { x } + +fn pass_through_elision_with_fn_path &u32>( + x: &T +) -> &impl Fn(&u32) -> &u32 { x } + +fn foo(x: &impl Debug) -> &impl Debug { x } +fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> &'a impl Debug { x } +fn foo_explicit_arg(x: &T) -> &impl Debug { x } + +fn mixed_lifetimes<'a>() -> impl for<'b> Fn(&'b &'a u32) { |_| () } +fn mixed_as_static() -> impl Fn(&'static &'static u32) { mixed_lifetimes() } + +trait MultiRegionTrait<'a, 'b>: Debug {} + +#[derive(Debug)] +struct MultiRegionStruct<'a, 'b>(&'a u32, &'b u32); +impl<'a, 'b> MultiRegionTrait<'a, 'b> for MultiRegionStruct<'a, 'b> {} + +#[derive(Debug)] +struct NoRegionStruct; +impl<'a, 'b> MultiRegionTrait<'a, 'b> for NoRegionStruct {} + +fn finds_least_region<'a: 'b, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> { + MultiRegionStruct(x, y) +} + +fn finds_explicit_bound<'a: 'b, 'b> + (x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> + 'b +{ + MultiRegionStruct(x, y) +} + +fn finds_explicit_bound_even_without_least_region<'a, 'b> + (x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> + 'b +{ + NoRegionStruct +} + +/* FIXME: `impl Trait<'a> + 'b` should live as long as 'b, even if 'b outlives 'a +fn outlives_bounds_even_with_contained_regions<'a, 'b> + (x: &'a u32, y: &'b u32) -> impl Debug + 'b +{ + finds_explicit_bound_even_without_least_region(x, y) +} +*/ + +fn unnamed_lifetimes_arent_contained_in_impl_trait_and_will_unify<'a, 'b> + (x: &'a u32, y: &'b u32) -> impl Debug +{ + fn deref<'lt>(x: &'lt u32) -> impl Debug { *x } + + if true { deref(x) } else { deref(y) } +} + +fn can_add_region_bound_to_static_type<'a, 'b>(_: &'a u32) -> impl Debug + 'a { 5 } + +struct MyVec(Vec>); + +impl<'unnecessary_lifetime> MyVec { + fn iter_doesnt_capture_unnecessary_lifetime<'s>(&'s self) -> impl Iterator { + self.0.iter().flat_map(|inner_vec| inner_vec.iter()) + } + + fn generator_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized { + || yield + } +} + + +fn main() {} diff --git a/tests/ui/impl-trait/lifetimes2.rs b/tests/ui/impl-trait/lifetimes2.rs new file mode 100644 index 000000000..834f2dc6c --- /dev/null +++ b/tests/ui/impl-trait/lifetimes2.rs @@ -0,0 +1,10 @@ +// check-pass + +pub fn keys<'a>(x: &'a Result) -> impl std::fmt::Debug + 'a { + match x { + Ok(map) => Ok(map), + Err(map) => Err(map), + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/method-suggestion-no-duplication.rs b/tests/ui/impl-trait/method-suggestion-no-duplication.rs new file mode 100644 index 000000000..c5c966a95 --- /dev/null +++ b/tests/ui/impl-trait/method-suggestion-no-duplication.rs @@ -0,0 +1,9 @@ +// issue #21405 +struct Foo; + +fn foo(f: F) where F: FnMut(Foo) {} + +fn main() { + foo(|s| s.is_empty()); + //~^ ERROR no method named `is_empty` found +} diff --git a/tests/ui/impl-trait/method-suggestion-no-duplication.stderr b/tests/ui/impl-trait/method-suggestion-no-duplication.stderr new file mode 100644 index 000000000..b727b2ca0 --- /dev/null +++ b/tests/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `is_empty` found for struct `Foo` in the current scope + --> $DIR/method-suggestion-no-duplication.rs:7:15 + | +LL | struct Foo; + | ---------- method `is_empty` not found for this struct +... +LL | foo(|s| s.is_empty()); + | ^^^^^^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `is_empty`, perhaps you need to implement it: + candidate #1: `ExactSizeIterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/multiple-lifetimes.rs b/tests/ui/impl-trait/multiple-lifetimes.rs new file mode 100644 index 000000000..5407fb6dd --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes.rs @@ -0,0 +1,12 @@ +// Test that multiple lifetimes are allowed in impl trait types. +// build-pass (FIXME(62277): could be check-pass?) + +trait X<'x>: Sized {} + +impl X<'_> for U {} + +fn multiple_lifeteimes<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl X<'b> + 'a { + x +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs new file mode 100644 index 000000000..2a2be6b74 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +#[derive(Clone)] +struct CopyIfEq(T, U); + +impl Copy for CopyIfEq {} + +type E<'a, 'b> = impl Sized; + +fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); + + // This assignment requires that `x` and `y` have the same type due to the + // `Copy` impl. The reason why we are using a copy to create a constraint + // is that only borrow checking (not regionck in type checking) enforces + // this bound. + let u = v; + let _: *mut &'a i32 = u.1; + unsafe { + let _: &'b i32 = *u.0; + } + u.0 + //~^ ERROR hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr new file mode 100644 index 000000000..908757080 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -0,0 +1,12 @@ +error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds + --> $DIR/error-handling-2.rs:22:5 + | +LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here +... +LL | u.0 + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr new file mode 100644 index 000000000..ccd004003 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/error-handling.rs:22:16 + | +LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'b i32 = *u.0; + | ^^^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs b/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs new file mode 100644 index 000000000..367e7f4e6 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +#[derive(Clone)] +struct CopyIfEq(T, U); + +impl Copy for CopyIfEq {} + +type E<'a, 'b> = impl Sized; + +fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); + + // This assignment requires that `x` and `y` have the same type due to the + // `Copy` impl. The reason why we are using a copy to create a constraint + // is that only borrow checking (not regionck in type checking) enforces + // this bound. + let u = v; + let _: *mut &'a i32 = u.1; + unsafe { + let _: &'b i32 = *u.0; + //~^ ERROR lifetime may not live long enough + } + u.0 +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr new file mode 100644 index 000000000..01d9f506a --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/error-handling.rs:20:16 + | +LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'b i32 = *u.0; + | ^^^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs b/tests/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs new file mode 100644 index 000000000..5251eeee8 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs @@ -0,0 +1,50 @@ +// edition:2018 +// check-pass + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Invert<'a> <: Invert<'b>` if `'b: 'a`, unlike most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Invert<'a>(fn(&'a u8)); + +fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e> +where + 'c: 'a, + 'c: 'b, + 'd: 'c, +{ + // Representing the where clauses as a graph, where `A: B` is an + // edge `B -> A`: + // + // ``` + // 'a -> 'c -> 'd + // ^ + // | + // 'b + // ``` + // + // Meanwhile we return a value &'0 u8 where we have the constraints: + // + // ``` + // '0: 'a + // '0: 'b + // '0 in ['d, 'e] + // ``` + // + // Here, ignoring the "in" constraint, the minimal choice for `'0` + // is `'c`, but that is not in the "in set". Still, that reduces + // the range of options in the "in set" to just `'d` (`'e: 'c` + // does not hold). + let p = if condition() { a } else { b }; + p +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs new file mode 100644 index 000000000..0bddce49b --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs @@ -0,0 +1,25 @@ +// edition:2018 +// build-pass (FIXME(62277): could be check-pass? + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// Test case where we have elision in the impl trait and we have to +// pick the right region. + +// Ultimately `Trait<'x, 'static>`. +fn upper_bounds1(a: &u8) -> impl Trait<'_, 'static> { + (a, a) +} + +// Ultimately `Trait<'x, 'x>`, so not really multiple bounds. +fn upper_bounds2(a: &u8) -> impl Trait<'_, '_> { + (a, a) +} + +// Kind of a weird annoying case. +fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> { + (a, a) +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs new file mode 100644 index 000000000..e363fdb36 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs @@ -0,0 +1,28 @@ +// edition:2018 +// check-pass + +#![feature(type_alias_impl_trait)] +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// Here we wind up selecting `'a` and `'b` in the hidden type because +// those are the types that appear in the original values. + +type Foo<'a, 'b> = impl Trait<'a, 'b>; + +fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> { + // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['a, 'b] + // '1 in ['a, 'b] + // ``` + // + // We use the fact that `'a: 0'` must hold (combined with the in + // constraint) to determine that `'0 = 'a` must be the answer. + (a, b) +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs new file mode 100644 index 000000000..0f21dd5ff --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs @@ -0,0 +1,25 @@ +// edition:2018 +// build-pass (FIXME(62277): could be check-pass?) + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// Here we wind up selecting `'a` and `'b` in the hidden type because +// those are the types that appear in the original values. + +fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { + // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['a, 'b] + // '1 in ['a, 'b] + // ``` + // + // We use the fact that `'a: 0'` must hold (combined with the in + // constraint) to determine that `'0 = 'a` must be the answer. + (a, b) +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs new file mode 100644 index 000000000..13ad1f721 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs @@ -0,0 +1,42 @@ +// edition:2018 +// build-pass (FIXME(62277): could be check-pass?) + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Ordinary<'a>(&'a u8); + +// Here we wind up selecting `'e` in the hidden type because +// we need something outlived by both `'a` and `'b` and only `'e` applies. + +fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> +where + 'a: 'e, + 'b: 'e, + 'a: 'd, +{ + // We return a value: + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['d, 'e] + // ``` + // + // but we don't have it. + // + // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. + let p = if condition() { a } else { b }; + p +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs new file mode 100644 index 000000000..c6eea5323 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs @@ -0,0 +1,36 @@ +// edition:2018 + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Ordinary<'a>(&'a u8); + +// Here we get an error because none of our choices (either `'d` nor `'e`) are outlived +// by both `'a` and `'b`. + +fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> +where + 'a: 'e, + 'b: 'd, +{ + // Hidden type `Ordinary<'0>` with constraints: + // + // ``` + // 'a: '0 + // 'b: '0 + // 'a in ['d, 'e] + // ``` + if condition() { a } else { b } + //~^ ERROR hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr new file mode 100644 index 000000000..ec49a6179 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -0,0 +1,17 @@ +error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds + --> $DIR/ordinary-bounds-unrelated.rs:28:33 + | +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ + | +help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs new file mode 100644 index 000000000..adcbca2a4 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs @@ -0,0 +1,39 @@ +// edition:2018 + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Ordinary<'a>(&'a u8); + +// Here we need something outlived by `'a` *and* outlived by `'b`, but +// we can only name `'a` and `'b` (and neither suits). So we get an +// error. Somewhat unfortunate, though, since the caller would have to +// consider the loans for both `'a` and `'b` alive. + +fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> +{ + // We return a value: + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['a, 'b] + // ``` + // + // but we don't have it. + // + // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. + if condition() { a } else { b } + //~^ ERROR hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr new file mode 100644 index 000000000..c36f9bc69 --- /dev/null +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -0,0 +1,17 @@ +error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds + --> $DIR/ordinary-bounds-unsuited.rs:31:33 + | +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ + | +help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs new file mode 100644 index 000000000..18404f986 --- /dev/null +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -0,0 +1,47 @@ +use std::fmt::Debug; + +fn elided(x: &i32) -> impl Copy { x } +//~^ ERROR: captures lifetime that does not appear in bounds + +fn explicit<'a>(x: &'a i32) -> impl Copy { x } +//~^ ERROR: captures lifetime that does not appear in bounds + +fn elided2(x: &i32) -> impl Copy + 'static { x } +//~^ ERROR lifetime may not live long enough + +fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } +//~^ ERROR lifetime may not live long enough + +fn foo<'a>(x: &i32) -> impl Copy + 'a { x } +//~^ ERROR explicit lifetime required in the type of `x` + +fn elided3(x: &i32) -> Box { Box::new(x) } + +fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + +fn elided4(x: &i32) -> Box { Box::new(x) } + +fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + +fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } +//~^ ERROR lifetime may not live long enough + +trait LifetimeTrait<'a> {} +impl<'a> LifetimeTrait<'a> for &'a i32 {} + +fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } +//~^ ERROR lifetime may not live long enough + +// Tests that a closure type containing 'b cannot be returned from a type where +// only 'a was expected. +fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { + move |_| println!("{}", y) + //~^ ERROR: captures lifetime that does not appear in bounds +} + +fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr new file mode 100644 index 000000000..9c81791fb --- /dev/null +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -0,0 +1,126 @@ +error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:3:35 + | +LL | fn elided(x: &i32) -> impl Copy { x } + | ---- ^ + | | + | hidden type `&i32` captures the anonymous lifetime defined here + | +help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | fn elided(x: &i32) -> impl Copy + '_ { x } + | ++++ + +error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:6:44 + | +LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } + | -- ^ + | | + | hidden type `&'a i32` captures the lifetime `'a` as defined here + | +help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound + | +LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:9:46 + | +LL | fn elided2(x: &i32) -> impl Copy + 'static { x } + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x` + | +LL | fn elided2(x: &i32) -> impl Copy + '_ { x } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x } + | ~~~~~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:12:55 + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } + | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x` + | +LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x } + | ~~~~~~~~~~~~ + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/must_outlive_least_region_or_bound.rs:15:41 + | +LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } + | ---- ^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:26:55 + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } + | ++++ +help: to declare that `impl Debug` captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:32:69 + | +LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } + | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing `impl LifetimeTrait<'a> + 'static`'s explicit `'static` bound to the lifetime of argument `x` + | +LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x } + | ~~~~~~~~~~~~ + +error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not appear in bounds + --> $DIR/must_outlive_least_region_or_bound.rs:38:5 + | +LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { + | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here +LL | move |_| println!("{}", y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b { + | ++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:43:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { + | +++++++++ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0310, E0621, E0700. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/needs_least_region_or_bound.rs b/tests/ui/impl-trait/needs_least_region_or_bound.rs new file mode 100644 index 000000000..c4bcfe5b2 --- /dev/null +++ b/tests/ui/impl-trait/needs_least_region_or_bound.rs @@ -0,0 +1,21 @@ +// check-pass + +trait MultiRegionTrait<'a, 'b> {} +impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {} + +fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> { + // Here we have a constraint that: + // + // (x, y) has type (&'0 u32, &'1 u32) + // + // where + // + // 'a: '0 + // + // then we require that `('0 u32, &'1 u32): MultiRegionTrait<'a, + // 'b>`, which winds up imposing a requirement that `'0 = 'a` and + // `'1 = 'b`. + (x, y) +} + +fn main() {} diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs new file mode 100644 index 000000000..70e24a3a9 --- /dev/null +++ b/tests/ui/impl-trait/negative-reasoning.rs @@ -0,0 +1,23 @@ +// Tests that we cannot assume that an opaque type does *not* implement some +// other trait +#![feature(type_alias_impl_trait)] + +trait OpaqueTrait {} +impl OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + () +} + +#[derive(Debug)] +struct D(T); + +trait AnotherTrait {} +impl AnotherTrait for T {} + +// This is in error, because we cannot assume that `OpaqueType: !Debug` +impl AnotherTrait for D { + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` +} + +fn main() {} diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr new file mode 100644 index 000000000..6b8cc9e73 --- /dev/null +++ b/tests/ui/impl-trait/negative-reasoning.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` + --> $DIR/negative-reasoning.rs:19:1 + | +LL | impl AnotherTrait for T {} + | ------------------------------------------- first implementation here +... +LL | impl AnotherTrait for D { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | + = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/nested-return-type.rs b/tests/ui/impl-trait/nested-return-type.rs new file mode 100644 index 000000000..7d7a084b8 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type.rs @@ -0,0 +1,16 @@ +// Check that nested impl Trait items work in functions with generic parameters. +// check-pass + +trait Captures<'a> {} + +impl Captures<'_> for T {} + +fn nested_assoc_type<'a: 'a, T>() -> impl Iterator { + [1].iter() +} + +fn nested_assoc_lifetime<'a: 'a, T>() -> impl Iterator> { + [1].iter() +} + +fn main() {} diff --git a/tests/ui/impl-trait/nested-return-type2-tait.rs b/tests/ui/impl-trait/nested-return-type2-tait.rs new file mode 100644 index 000000000..089018a1c --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2-tait.rs @@ -0,0 +1,34 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +type Sendable = impl Send; + +// The `Sendable` here is converted to an inference var and then later compared +// against the inference var created, causing the inference var to be set to +// the hidden type of `Sendable` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, but if its hidden type does. +fn foo() -> impl Trait { + //~^ WARN opaque type `impl Trait` does not satisfy its associated type bounds + || 42 +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type2-tait.stderr b/tests/ui/impl-trait/nested-return-type2-tait.stderr new file mode 100644 index 000000000..a8eb69cfc --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2-tait.stderr @@ -0,0 +1,17 @@ +warning: opaque type `impl Trait` does not satisfy its associated type bounds + --> $DIR/nested-return-type2-tait.rs:28:24 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `Sendable` +... +LL | fn foo() -> impl Trait { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default +help: add this bound + | +LL | type Sendable = impl Send + Duh; + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/nested-return-type2-tait2.rs b/tests/ui/impl-trait/nested-return-type2-tait2.rs new file mode 100644 index 000000000..af8e06630 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2-tait2.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +type Sendable = impl Send; +type Traitable = impl Trait; + +// The `impl Send` here is then later compared against the inference var +// created, causing the inference var to be set to `impl Send` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. So we error out. +fn foo() -> Traitable { + || 42 + //~^ ERROR `Sendable: Duh` is not satisfied +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type2-tait2.stderr b/tests/ui/impl-trait/nested-return-type2-tait2.stderr new file mode 100644 index 000000000..b85bb5efd --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2-tait2.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Sendable: Duh` is not satisfied + --> $DIR/nested-return-type2-tait2.rs:27:5 + | +LL | || 42 + | ^^^^^ the trait `Duh` is not implemented for `Sendable` + | + = help: the trait `Duh` is implemented for `i32` +note: required for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:7]` to implement `Trait` + --> $DIR/nested-return-type2-tait2.rs:14:31 + | +LL | impl R> Trait for F { + | --- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/nested-return-type2-tait3.rs b/tests/ui/impl-trait/nested-return-type2-tait3.rs new file mode 100644 index 000000000..74fd8a9dd --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2-tait3.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +type Traitable = impl Trait; + +// The `impl Send` here is then later compared against the inference var +// created, causing the inference var to be set to `impl Send` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. So we error out. +fn foo() -> Traitable { + || 42 + //~^ ERROR `impl Send: Duh` is not satisfied +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type2-tait3.stderr b/tests/ui/impl-trait/nested-return-type2-tait3.stderr new file mode 100644 index 000000000..19fd3c134 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2-tait3.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `impl Send: Duh` is not satisfied + --> $DIR/nested-return-type2-tait3.rs:26:5 + | +LL | || 42 + | ^^^^^ the trait `Duh` is not implemented for `impl Send` + | + = help: the trait `Duh` is implemented for `i32` +note: required for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:7]` to implement `Trait` + --> $DIR/nested-return-type2-tait3.rs:14:31 + | +LL | impl R> Trait for F { + | --- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/nested-return-type2.rs b/tests/ui/impl-trait/nested-return-type2.rs new file mode 100644 index 000000000..cc1f1f4ec --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2.rs @@ -0,0 +1,31 @@ +// check-pass + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +// the fact that `R` is the `::Output` projection on `F` causes +// an intermediate inference var to be generated which is then later +// compared against the actually found `Assoc` type. +impl R> Trait for F { + type Assoc = R; +} + +// The `impl Send` here is then later compared against the inference var +// created, causing the inference var to be set to `impl Send` instead of +// the hidden type. We already have obligations registered on the inference +// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque +// type does not implement `Duh`, even if its hidden type does. +// Lazy TAIT would error out, but we inserted a hack to make it work again, +// keeping backwards compatibility. +fn foo() -> impl Trait { + //~^ WARN opaque type `impl Trait` does not satisfy its associated type bounds + || 42 +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type2.stderr b/tests/ui/impl-trait/nested-return-type2.stderr new file mode 100644 index 000000000..3aed05ca1 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type2.stderr @@ -0,0 +1,17 @@ +warning: opaque type `impl Trait` does not satisfy its associated type bounds + --> $DIR/nested-return-type2.rs:25:24 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `impl Send` +... +LL | fn foo() -> impl Trait { + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default +help: add this bound + | +LL | fn foo() -> impl Trait { + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/nested-return-type3-tait.rs b/tests/ui/impl-trait/nested-return-type3-tait.rs new file mode 100644 index 000000000..3a97e35b4 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3-tait.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +type Sendable = impl Send; + +fn foo() -> impl Trait { + //~^ WARN opaque type `impl Trait` does not satisfy its associated type bounds + 42 +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type3-tait.stderr b/tests/ui/impl-trait/nested-return-type3-tait.stderr new file mode 100644 index 000000000..5f58c8dca --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3-tait.stderr @@ -0,0 +1,17 @@ +warning: opaque type `impl Trait` does not satisfy its associated type bounds + --> $DIR/nested-return-type3-tait.rs:19:24 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `Sendable` +... +LL | fn foo() -> impl Trait { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default +help: add this bound + | +LL | type Sendable = impl Send + Duh; + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.rs b/tests/ui/impl-trait/nested-return-type3-tait2.rs new file mode 100644 index 000000000..5b6f78a98 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3-tait2.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +type Sendable = impl Send; +type Traitable = impl Trait; +//~^ WARN opaque type `Traitable` does not satisfy its associated type bounds + +fn foo() -> Traitable { + 42 +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.stderr b/tests/ui/impl-trait/nested-return-type3-tait2.stderr new file mode 100644 index 000000000..c07f6ead7 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3-tait2.stderr @@ -0,0 +1,17 @@ +warning: opaque type `Traitable` does not satisfy its associated type bounds + --> $DIR/nested-return-type3-tait2.rs:18:29 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `Sendable` +... +LL | type Traitable = impl Trait; + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default +help: add this bound + | +LL | type Sendable = impl Send + Duh; + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/nested-return-type3-tait3.rs b/tests/ui/impl-trait/nested-return-type3-tait3.rs new file mode 100644 index 000000000..394d8f581 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3-tait3.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +type Traitable = impl Trait; +//~^ WARN opaque type `Traitable` does not satisfy its associated type bounds + +fn foo() -> Traitable { + 42 +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type3-tait3.stderr b/tests/ui/impl-trait/nested-return-type3-tait3.stderr new file mode 100644 index 000000000..d98ad8922 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3-tait3.stderr @@ -0,0 +1,17 @@ +warning: opaque type `Traitable` does not satisfy its associated type bounds + --> $DIR/nested-return-type3-tait3.rs:17:29 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `impl Send` +... +LL | type Traitable = impl Trait; + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default +help: add this bound + | +LL | type Traitable = impl Trait; + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/nested-return-type3.rs b/tests/ui/impl-trait/nested-return-type3.rs new file mode 100644 index 000000000..5a764fc4c --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl Trait for F { + type Assoc = F; +} + +fn foo() -> impl Trait { + //~^ WARN opaque type `impl Trait` does not satisfy its associated type bounds + 42 +} + +fn main() { +} diff --git a/tests/ui/impl-trait/nested-return-type3.stderr b/tests/ui/impl-trait/nested-return-type3.stderr new file mode 100644 index 000000000..632de71aa --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type3.stderr @@ -0,0 +1,17 @@ +warning: opaque type `impl Trait` does not satisfy its associated type bounds + --> $DIR/nested-return-type3.rs:15:24 + | +LL | type Assoc: Duh; + | --- this associated type bound is unsatisfied for `impl Send` +... +LL | fn foo() -> impl Trait { + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(opaque_hidden_inferred_bound)]` on by default +help: add this bound + | +LL | fn foo() -> impl Trait { + | +++++ + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/nested-return-type4.rs b/tests/ui/impl-trait/nested-return-type4.rs new file mode 100644 index 000000000..cec70bb1a --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type4.rs @@ -0,0 +1,8 @@ +// edition: 2021 + +fn test<'s: 's>(s: &'s str) -> impl std::future::Future { + async move { let _s = s; } + //~^ ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr new file mode 100644 index 000000000..e761a60e7 --- /dev/null +++ b/tests/ui/impl-trait/nested-return-type4.stderr @@ -0,0 +1,20 @@ +error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds + --> $DIR/nested-return-type4.rs:4:5 + | +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { + | -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here +LL | async move { let _s = s; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Future` captures `'s`, you can add an explicit `'s` lifetime bound + | +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future + 's { + | ++++ +help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` lifetime bound + | +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs new file mode 100644 index 000000000..a5db10d3a --- /dev/null +++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs @@ -0,0 +1,64 @@ +// Test the interaction between rested RPIT and HRTB. + +trait Foo<'a> { + type Assoc; +} + +impl Foo<'_> for () { + type Assoc = (); +} + +// Alternative version of `Foo` whose impl uses `'a`. +trait Bar<'a> { + type Assoc; +} + +impl<'a> Bar<'a> for () { + type Assoc = &'a (); +} + +trait Qux<'a> {} + +impl Qux<'_> for () {} + +// This is not supported. +fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} +//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + +// This is not supported. +fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} +//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + +fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} +//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + +fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} +//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet + +// This should resolve. +fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {} + +// This should resolve. +fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {} + +// This should resolve. +fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} + +// This should resolve. +fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {} + +// This should resolve. +fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {} + +// `'b` is not in scope for the outlives bound. +fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} +//~^ ERROR use of undeclared lifetime name `'b` [E0261] + +// This should resolve. +fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {} + +// `'b` is not in scope for the outlives bound. +fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} +//~^ ERROR use of undeclared lifetime name `'b` [E0261] + +fn main() {} diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr new file mode 100644 index 000000000..3dbe6ebad --- /dev/null +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -0,0 +1,82 @@ +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/nested-rpit-hrtb.rs:54:77 + | +LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | fn two_htrb_outlives() -> impl for<'b, 'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/nested-rpit-hrtb.rs:61:82 + | +LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | fn two_htrb_outlives_uses() -> impl for<'b, 'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} + | ++++ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/nested-rpit-hrtb.rs:25:69 + | +LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} + | ^^ + | +note: lifetime declared here + --> $DIR/nested-rpit-hrtb.rs:25:36 + | +LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {} + | ^^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/nested-rpit-hrtb.rs:29:68 + | +LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} + | ^^ + | +note: lifetime declared here + --> $DIR/nested-rpit-hrtb.rs:29:39 + | +LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} + | ^^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/nested-rpit-hrtb.rs:32:74 + | +LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} + | ^^ + | +note: lifetime declared here + --> $DIR/nested-rpit-hrtb.rs:32:41 + | +LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} + | ^^ + +error: higher kinded lifetime bounds on nested opaque types are not supported yet + --> $DIR/nested-rpit-hrtb.rs:35:73 + | +LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} + | ^^ + | +note: lifetime declared here + --> $DIR/nested-rpit-hrtb.rs:35:44 + | +LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} + | ^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/nested-rpit-with-anonymous-lifetimes.rs b/tests/ui/impl-trait/nested-rpit-with-anonymous-lifetimes.rs new file mode 100644 index 000000000..287a030cf --- /dev/null +++ b/tests/ui/impl-trait/nested-rpit-with-anonymous-lifetimes.rs @@ -0,0 +1,23 @@ +// check-pass + +pub struct VecNumber<'s> { + pub vec_number: Vec>, + pub auxiliary_object: &'s Vec, +} + +pub struct Number<'s> { + pub number: &'s usize, +} + +impl<'s> VecNumber<'s> { + pub fn vec_number_iterable_per_item_in_auxiliary_object( + &self, + ) -> impl Iterator>)> { + self.auxiliary_object.iter().map(move |n| { + let iter_number = self.vec_number.iter(); + (n, iter_number) + }) + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs new file mode 100644 index 000000000..e95fab3b6 --- /dev/null +++ b/tests/ui/impl-trait/nested_impl_trait.rs @@ -0,0 +1,32 @@ +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +fn fine(x: impl Into) -> impl Into { x } + +fn bad_in_ret_position(x: impl Into) -> impl Into { x } +//~^ ERROR nested `impl Trait` is not allowed +//~| ERROR the trait bound `impl Debug: From>` is not satisfied + +fn bad_in_fn_syntax(x: fn() -> impl Into) {} +//~^ ERROR nested `impl Trait` is not allowed +//~| `impl Trait` only allowed in function and inherent method return types + +fn bad_in_arg_position(_: impl Into) { } +//~^ ERROR nested `impl Trait` is not allowed + +struct X; +impl X { + fn bad(x: impl Into) -> impl Into { x } + //~^ ERROR nested `impl Trait` is not allowed + //~| ERROR the trait bound `impl Debug: From>` is not satisfied +} + +fn allowed_in_assoc_type() -> impl Iterator { + vec![|| println!("woot")].into_iter() +} + +fn allowed_in_ret_type() -> impl Fn() -> impl Into { + || 5u8 +} + +fn main() {} diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr new file mode 100644 index 000000000..9a8f5a340 --- /dev/null +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -0,0 +1,64 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:6:56 + | +LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } + | ----------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:10:42 + | +LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} + | ----------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:14:37 + | +LL | fn bad_in_arg_position(_: impl Into) { } + | ----------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/nested_impl_trait.rs:19:44 + | +LL | fn bad(x: impl Into) -> impl Into { x } + | ----------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return + --> $DIR/nested_impl_trait.rs:10:32 + | +LL | fn bad_in_fn_syntax(x: fn() -> impl Into) {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `impl Debug: From>` is not satisfied + --> $DIR/nested_impl_trait.rs:6:46 + | +LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | + = help: the trait `Into` is implemented for `T` + = note: required for `impl Into` to implement `Into` + +error[E0277]: the trait bound `impl Debug: From>` is not satisfied + --> $DIR/nested_impl_trait.rs:19:34 + | +LL | fn bad(x: impl Into) -> impl Into { x } + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | + = help: the trait `Into` is implemented for `T` + = note: required for `impl Into` to implement `Into` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0562, E0666. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/nesting.rs b/tests/ui/impl-trait/nesting.rs new file mode 100644 index 000000000..27bdd5fa4 --- /dev/null +++ b/tests/ui/impl-trait/nesting.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + +fn foo(t: T) -> impl Into<[T; { const FOO: usize = 1; FOO }]> { + [t] +} + +fn bar() -> impl Into<[u8; { const FOO: usize = 1; FOO }]> { + [99] +} + +fn main() { + println!("{:?}", foo(42).into()); + println!("{:?}", bar().into()); +} diff --git a/tests/ui/impl-trait/no-method-suggested-traits.rs b/tests/ui/impl-trait/no-method-suggested-traits.rs new file mode 100644 index 000000000..c8abc2d8f --- /dev/null +++ b/tests/ui/impl-trait/no-method-suggested-traits.rs @@ -0,0 +1,77 @@ +// aux-build:no_method_suggested_traits.rs +extern crate no_method_suggested_traits; + +struct Foo; +enum Bar { X } + +mod foo { + pub trait Bar { + fn method(&self) {} + + fn method2(&self) {} + } + + impl Bar for u32 {} + + impl Bar for char {} +} + +fn main() { + // test the values themselves, and autoderef. + + + 1u32.method(); + //~^ ERROR no method named + //~|items from traits can only be used if the trait is in scope + std::rc::Rc::new(&mut Box::new(&1u32)).method(); + //~^items from traits can only be used if the trait is in scope + //~| ERROR no method named `method` found for struct + + 'a'.method(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&'a')).method(); + //~^ ERROR no method named + + 1i32.method(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&1i32)).method(); + //~^ ERROR no method named + + Foo.method(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&Foo)).method(); + //~^ ERROR no method named + + 1u64.method2(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&1u64)).method2(); + //~^ ERROR no method named + + no_method_suggested_traits::Foo.method2(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); + //~^ ERROR no method named + no_method_suggested_traits::Bar::X.method2(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); + //~^ ERROR no method named + + Foo.method3(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&Foo)).method3(); + //~^ ERROR no method named + Bar::X.method3(); + //~^ ERROR no method named + std::rc::Rc::new(&mut Box::new(&Bar::X)).method3(); + //~^ ERROR no method named + + // should have no help: + 1_usize.method3(); //~ ERROR no method named + std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); //~ ERROR no method named + no_method_suggested_traits::Foo.method3(); //~ ERROR no method named + std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3(); + //~^ ERROR no method named + no_method_suggested_traits::Bar::X.method3(); //~ ERROR no method named + std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); + //~^ ERROR no method named +} diff --git a/tests/ui/impl-trait/no-method-suggested-traits.stderr b/tests/ui/impl-trait/no-method-suggested-traits.stderr new file mode 100644 index 000000000..548c89d0a --- /dev/null +++ b/tests/ui/impl-trait/no-method-suggested-traits.stderr @@ -0,0 +1,284 @@ +error[E0599]: no method named `method` found for type `u32` in the current scope + --> $DIR/no-method-suggested-traits.rs:23:10 + | +LL | 1u32.method(); + | ^^^^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use foo::Bar; + | +LL | use no_method_suggested_traits::Reexported; + | +LL | use no_method_suggested_traits::foo::PubPub; + | +LL | use no_method_suggested_traits::qux::PrivPub; + | + +error[E0599]: no method named `method` found for struct `Rc<&mut Box<&u32>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:26:44 + | +LL | std::rc::Rc::new(&mut Box::new(&1u32)).method(); + | ^^^^^^ method not found in `Rc<&mut Box<&u32>>` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use foo::Bar; + | +LL | use no_method_suggested_traits::Reexported; + | +LL | use no_method_suggested_traits::foo::PubPub; + | +LL | use no_method_suggested_traits::qux::PrivPub; + | + +error[E0599]: no method named `method` found for type `char` in the current scope + --> $DIR/no-method-suggested-traits.rs:30:9 + | +LL | fn method(&self) {} + | ------ the method is available for `char` here +... +LL | 'a'.method(); + | ^^^^^^ method not found in `char` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use foo::Bar; + | + +error[E0599]: no method named `method` found for struct `Rc<&mut Box<&char>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:32:43 + | +LL | std::rc::Rc::new(&mut Box::new(&'a')).method(); + | ^^^^^^ method not found in `Rc<&mut Box<&char>>` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use foo::Bar; + | + +error[E0599]: no method named `method` found for type `i32` in the current scope + --> $DIR/no-method-suggested-traits.rs:35:10 + | +LL | 1i32.method(); + | ^^^^^^ method not found in `i32` + | + ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12 + | +LL | fn method(&self) {} + | ------ the method is available for `i32` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use no_method_suggested_traits::foo::PubPub; + | + +error[E0599]: no method named `method` found for struct `Rc<&mut Box<&i32>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:37:44 + | +LL | std::rc::Rc::new(&mut Box::new(&1i32)).method(); + | ^^^^^^ method not found in `Rc<&mut Box<&i32>>` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use no_method_suggested_traits::foo::PubPub; + | + +error[E0599]: no method named `method` found for struct `Foo` in the current scope + --> $DIR/no-method-suggested-traits.rs:40:9 + | +LL | struct Foo; + | ---------- method `method` not found for this struct +... +LL | Foo.method(); + | ^^^^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `method`, perhaps you need to implement one of them: + candidate #1: `foo::Bar` + candidate #2: `PubPub` + candidate #3: `no_method_suggested_traits::qux::PrivPub` + candidate #4: `Reexported` + +error[E0599]: no method named `method` found for struct `Rc<&mut Box<&Foo>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:42:43 + | +LL | std::rc::Rc::new(&mut Box::new(&Foo)).method(); + | ^^^^^^ method not found in `Rc<&mut Box<&Foo>>` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `method`, perhaps you need to implement one of them: + candidate #1: `foo::Bar` + candidate #2: `PubPub` + candidate #3: `no_method_suggested_traits::qux::PrivPub` + candidate #4: `Reexported` + +error[E0599]: no method named `method2` found for type `u64` in the current scope + --> $DIR/no-method-suggested-traits.rs:45:10 + | +LL | 1u64.method2(); + | ^^^^^^^ method not found in `u64` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&u64>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:47:44 + | +LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); + | ^^^^^^^ method not found in `Rc<&mut Box<&u64>>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error[E0599]: no method named `method2` found for struct `Foo` in the current scope + --> $DIR/no-method-suggested-traits.rs:50:37 + | +LL | no_method_suggested_traits::Foo.method2(); + | ^^^^^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:52:71 + | +LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); + | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error[E0599]: no method named `method2` found for enum `Bar` in the current scope + --> $DIR/no-method-suggested-traits.rs:54:40 + | +LL | no_method_suggested_traits::Bar::X.method2(); + | ^^^^^^^ method not found in `Bar` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:56:74 + | +LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); + | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ + +error[E0599]: no method named `method3` found for struct `Foo` in the current scope + --> $DIR/no-method-suggested-traits.rs:59:9 + | +LL | struct Foo; + | ---------- method `method3` not found for this struct +... +LL | Foo.method3(); + | ^^^^^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `method3`, perhaps you need to implement it: + candidate #1: `PubPub` + +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:61:43 + | +LL | std::rc::Rc::new(&mut Box::new(&Foo)).method3(); + | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `method3`, perhaps you need to implement it: + candidate #1: `PubPub` + +error[E0599]: no method named `method3` found for enum `Bar` in the current scope + --> $DIR/no-method-suggested-traits.rs:63:12 + | +LL | enum Bar { X } + | -------- method `method3` not found for this enum +... +LL | Bar::X.method3(); + | ^^^^^^^ method not found in `Bar` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `method3`, perhaps you need to implement it: + candidate #1: `PubPub` + +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:65:46 + | +LL | std::rc::Rc::new(&mut Box::new(&Bar::X)).method3(); + | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `method3`, perhaps you need to implement it: + candidate #1: `PubPub` + +error[E0599]: no method named `method3` found for type `usize` in the current scope + --> $DIR/no-method-suggested-traits.rs:69:13 + | +LL | 1_usize.method3(); + | ^^^^^^^ method not found in `usize` + +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:70:47 + | +LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); + | ^^^^^^^ method not found in `Rc<&mut Box<&usize>>` + +error[E0599]: no method named `method3` found for struct `Foo` in the current scope + --> $DIR/no-method-suggested-traits.rs:71:37 + | +LL | no_method_suggested_traits::Foo.method3(); + | ^^^^^^^ method not found in `Foo` + +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:72:71 + | +LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3(); + | ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>` + +error[E0599]: no method named `method3` found for enum `Bar` in the current scope + --> $DIR/no-method-suggested-traits.rs:74:40 + | +LL | no_method_suggested_traits::Bar::X.method3(); + | ^^^^^^^ method not found in `Bar` + +error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope + --> $DIR/no-method-suggested-traits.rs:75:74 + | +LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); + | ^^^^^^^ method not found in `Rc<&mut Box<&Bar>>` + +error: aborting due to 24 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/impl-trait/no-trait.rs b/tests/ui/impl-trait/no-trait.rs new file mode 100644 index 000000000..9ce668f46 --- /dev/null +++ b/tests/ui/impl-trait/no-trait.rs @@ -0,0 +1,3 @@ +fn f() -> impl 'static {} //~ ERROR at least one trait must be specified + +fn main() {} diff --git a/tests/ui/impl-trait/no-trait.stderr b/tests/ui/impl-trait/no-trait.stderr new file mode 100644 index 000000000..3a636f252 --- /dev/null +++ b/tests/ui/impl-trait/no-trait.stderr @@ -0,0 +1,8 @@ +error: at least one trait must be specified + --> $DIR/no-trait.rs:1:11 + | +LL | fn f() -> impl 'static {} + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs new file mode 100644 index 000000000..020bcbb83 --- /dev/null +++ b/tests/ui/impl-trait/normalize-tait-in-const.rs @@ -0,0 +1,39 @@ +// known-bug: #103507 +// failure-status: 101 +// normalize-stderr-test "note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// rustc-env:RUST_BACKTRACE=0 + +#![feature(type_alias_impl_trait)] +#![feature(const_trait_impl)] +#![feature(const_refs_to_cell)] +#![feature(inline_const)] + +use std::marker::Destruct; + +trait T { + type Item; +} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +const fn filter_positive<'a>() -> &'a Alias<'a> { + &&S +} + +const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + fun(filter_positive()); +} + +const fn foo(_: &Alias<'_>) {} + +const BAR: () = { + with_positive(foo); +}; + +fn main() {} diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr new file mode 100644 index 000000000..b9fc8726f --- /dev/null +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -0,0 +1,8 @@ +error: internal compiler error: compiler/rustc_middle/src/ty/normalize_erasing_regions.rs:198:90: Failed to normalize fn(&'a Alias<'b>) {foo} as std::ops::FnOnce<(&&S,)>>::Output, maybe try to call `try_normalize_erasing_regions` instead + +query stack during panic: +#0 [eval_to_allocation_raw] const-evaluating + checking `BAR` +#1 [eval_to_const_value_raw] simplifying constant for the type system `BAR` +end of query stack +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs new file mode 100644 index 000000000..ab3086c78 --- /dev/null +++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs @@ -0,0 +1,35 @@ +#![allow(bare_trait_objects)] +trait NotObjectSafe { + fn foo() -> Self; +} + +struct A; +struct B; + +impl NotObjectSafe for A { + fn foo() -> Self { + A + } +} + +impl NotObjectSafe for B { + fn foo() -> Self { + B + } +} + +fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object + if true { + return A; + } + B +} + +fn cat() -> Box { //~ ERROR the trait `NotObjectSafe` cannot be made into an + if true { + return Box::new(A); + } + Box::new(B) +} + +fn main() {} diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr new file mode 100644 index 000000000..687dbe65e --- /dev/null +++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr @@ -0,0 +1,47 @@ +error[E0038]: the trait `NotObjectSafe` cannot be made into an object + --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:13 + | +LL | fn car() -> dyn NotObjectSafe { + | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + | +LL | trait NotObjectSafe { + | ------------- this trait cannot be made into an object... +LL | fn foo() -> Self; + | ^^^ ...because associated function `foo` has no `self` parameter +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) -> Self; + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | +++++++++++++++++ + +error[E0038]: the trait `NotObjectSafe` cannot be made into an object + --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:17 + | +LL | fn cat() -> Box { + | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + | +LL | trait NotObjectSafe { + | ------------- this trait cannot be made into an object... +LL | fn foo() -> Self; + | ^^^ ...because associated function `foo` has no `self` parameter +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) -> Self; + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs new file mode 100644 index 000000000..503515013 --- /dev/null +++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs @@ -0,0 +1,46 @@ +trait NotObjectSafe { + fn foo() -> Self; +} + +trait ObjectSafe { + fn bar(&self); +} + +struct A; +struct B; + +impl NotObjectSafe for A { + fn foo() -> Self { + A + } +} + +impl NotObjectSafe for B { + fn foo() -> Self { + B + } +} + +impl ObjectSafe for A { + fn bar(&self) {} +} + +impl ObjectSafe for B { + fn bar(&self) {} +} + +fn can() -> impl NotObjectSafe { + if true { + return A; + } + B //~ ERROR mismatched types +} + +fn cat() -> impl ObjectSafe { + if true { + return A; + } + B //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr new file mode 100644 index 000000000..d6f5a1ac2 --- /dev/null +++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5 + | +LL | fn can() -> impl NotObjectSafe { + | ------------------ expected `A` because of return type +... +LL | B + | ^ expected struct `A`, found struct `B` + +error[E0308]: mismatched types + --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5 + | +LL | fn cat() -> impl ObjectSafe { + | --------------- expected `A` because of return type +... +LL | B + | ^ expected struct `A`, found struct `B` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs new file mode 100644 index 000000000..fa7664a83 --- /dev/null +++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs @@ -0,0 +1,101 @@ +fn foo() -> impl std::fmt::Display { + if false { + return 0i32; + } + 1u32 //~ ERROR mismatched types +} + +fn bar() -> impl std::fmt::Display { + if false { + return 0i32; + } else { + return 1u32; //~ ERROR mismatched types + } +} + +fn baz() -> impl std::fmt::Display { + if false { + return 0i32; + } else { + 1u32 //~ ERROR mismatched types + } +} + +fn qux() -> impl std::fmt::Display { + if false { + 0i32 + } else { + 1u32 //~ ERROR `if` and `else` have incompatible types + } +} + +fn bat() -> impl std::fmt::Display { + match 13 { + 0 => return 0i32, + _ => 1u32, //~ ERROR mismatched types + } +} + +fn can() -> impl std::fmt::Display { + match 13 { //~ ERROR mismatched types + 0 => return 0i32, + 1 => 1u32, + _ => 2u32, + } +} + +fn cat() -> impl std::fmt::Display { + match 13 { + 0 => { + return 0i32; + } + _ => { + 1u32 //~ ERROR mismatched types + } + } +} + +fn dog() -> impl std::fmt::Display { + match 13 { + 0 => 0i32, + 1 => 1u32, //~ ERROR `match` arms have incompatible types + _ => 2u32, + } +} + +fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object + match 13 { + 0 => { + return 0i32; + } + _ => { + 1u32 + } + } +} + +fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object + match 13 { + 0 => 0i32, + 1 => 1u32, //~ ERROR `match` arms have incompatible types + _ => 2u32, + } +} + +fn man() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object + if false { + 0i32 + } else { + 1u32 //~ ERROR `if` and `else` have incompatible types + } +} + +fn apt() -> impl std::fmt::Display { + if let Some(42) = Some(42) { + 0i32 + } else { + 1u32 //~ ERROR `if` and `else` have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr new file mode 100644 index 000000000..3c65fd998 --- /dev/null +++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -0,0 +1,278 @@ +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5 + | +LL | fn foo() -> impl std::fmt::Display { + | ---------------------- expected `i32` because of return type +... +LL | 1u32 + | ^^^^ expected `i32`, found `u32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 1i32 + | ~~~ + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16 + | +LL | fn bar() -> impl std::fmt::Display { + | ---------------------- expected `i32` because of return type +... +LL | return 1u32; + | ^^^^ expected `i32`, found `u32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | return 1i32; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9 + | +LL | fn baz() -> impl std::fmt::Display { + | ---------------------- expected `i32` because of return type +... +LL | 1u32 + | ^^^^ expected `i32`, found `u32` + | +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | }.try_into().unwrap() + | ++++++++++++++++++++ + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9 + | +LL | / if false { +LL | | 0i32 + | | ---- expected because of this +LL | | } else { +LL | | 1u32 + | | ^^^^ expected `i32`, found `u32` +LL | | } + | |_____- `if` and `else` have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn qux() -> Box { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ Box::new(0i32) +LL | } else { +LL ~ Box::new(1u32) + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 1i32 + | ~~~ + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14 + | +LL | fn bat() -> impl std::fmt::Display { + | ---------------------- expected `i32` because of return type +... +LL | _ => 1u32, + | ^^^^ expected `i32`, found `u32` + | +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | }.try_into().unwrap() + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5 + | +LL | fn can() -> impl std::fmt::Display { + | ---------------------- expected `i32` because of return type +LL | / match 13 { +LL | | 0 => return 0i32, +LL | | 1 => 1u32, +LL | | _ => 2u32, +LL | | } + | |_____^ expected `i32`, found `u32` + | +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | }.try_into().unwrap() + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13 + | +LL | fn cat() -> impl std::fmt::Display { + | ---------------------- expected `i32` because of return type +... +LL | 1u32 + | ^^^^ expected `i32`, found `u32` + | +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | }.try_into().unwrap() + | ++++++++++++++++++++ + +error[E0308]: `match` arms have incompatible types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14 + | +LL | / match 13 { +LL | | 0 => 0i32, + | | ---- this is found to be of type `i32` +LL | | 1 => 1u32, + | | ^^^^ expected `i32`, found `u32` +LL | | _ => 2u32, +LL | | } + | |_____- `match` arms have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn dog() -> Box { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ 0 => Box::new(0i32), +LL ~ 1 => Box::new(1u32), + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 1 => 1i32, + | ~~~ + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9 + | +LL | / if let Some(42) = Some(42) { +LL | | 0i32 + | | ---- expected because of this +LL | | } else { +LL | | 1u32 + | | ^^^^ expected `i32`, found `u32` +LL | | } + | |_____- `if` and `else` have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn apt() -> Box { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ Box::new(0i32) +LL | } else { +LL ~ Box::new(1u32) + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 1i32 + | ~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13 + | +LL | fn hat() -> dyn std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn hat() -> Box { + | ++++ + +help: ... and box this value + | +LL | return Box::new(0i32); + | +++++++++ + +help: ... and box this value + | +LL | Box::new(1u32) + | +++++++++ + + +error[E0308]: `match` arms have incompatible types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14 + | +LL | / match 13 { +LL | | 0 => 0i32, + | | ---- this is found to be of type `i32` +LL | | 1 => 1u32, + | | ^^^^ expected `i32`, found `u32` +LL | | _ => 2u32, +LL | | } + | |_____- `match` arms have incompatible types + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 1 => 1i32, + | ~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13 + | +LL | fn pug() -> dyn std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn pug() -> Box { + | ++++ + +help: ... and box this value + | +LL | 0 => Box::new(0i32), + | +++++++++ + +help: ... and box this value + | +LL | 1 => Box::new(1u32), + | +++++++++ + +help: ... and box this value + | +LL | _ => Box::new(2u32), + | +++++++++ + + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9 + | +LL | / if false { +LL | | 0i32 + | | ---- expected because of this +LL | | } else { +LL | | 1u32 + | | ^^^^ expected `i32`, found `u32` +LL | | } + | |_____- `if` and `else` have incompatible types + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | 1i32 + | ~~~ + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13 + | +LL | fn man() -> dyn std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn man() -> Box { + | ++++ + +help: ... and box this value + | +LL | Box::new(0i32) + | +++++++++ + +help: ... and box this value + | +LL | Box::new(1u32) + | +++++++++ + + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0308, E0746. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/printing-binder.rs b/tests/ui/impl-trait/printing-binder.rs new file mode 100644 index 000000000..273b5dcdb --- /dev/null +++ b/tests/ui/impl-trait/printing-binder.rs @@ -0,0 +1,14 @@ +trait Trait<'a> {} +impl Trait<'_> for T {} +fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {} + +fn whatever2() -> impl for<'c> Fn(&'c ()) { + |_: &()| {} +} + +fn main() { + let x: u32 = whatever(); + //~^ ERROR mismatched types + let x2: u32 = whatever2(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/impl-trait/printing-binder.stderr b/tests/ui/impl-trait/printing-binder.stderr new file mode 100644 index 000000000..5ffec8af1 --- /dev/null +++ b/tests/ui/impl-trait/printing-binder.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/printing-binder.rs:10:18 + | +LL | fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {} + | ------------------------------------------ the found opaque type +... +LL | let x: u32 = whatever(); + | --- ^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl for<'a> Trait<'a> + for<'b> Trait<'b>` + +error[E0308]: mismatched types + --> $DIR/printing-binder.rs:12:19 + | +LL | fn whatever2() -> impl for<'c> Fn(&'c ()) { + | ----------------------- the found opaque type +... +LL | let x2: u32 = whatever2(); + | --- ^^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl for<'c> Fn(&'c ())` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/private_unused.rs b/tests/ui/impl-trait/private_unused.rs new file mode 100644 index 000000000..92268f186 --- /dev/null +++ b/tests/ui/impl-trait/private_unused.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#[deny(warnings)] + +enum Empty { } +trait Bar {} +impl Bar for () {} + +fn boo() -> impl Bar {} + +fn main() { + boo(); +} diff --git a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs new file mode 100644 index 000000000..b4fd6b3e7 --- /dev/null +++ b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.rs @@ -0,0 +1,20 @@ +pub trait Super { + type Assoc; +} + +impl Super for () { + type Assoc = u8; +} + +pub trait Test {} + +impl Test for T where T: Super {} + +fn test() -> impl Test { + //~^ERROR type mismatch resolving `<() as Super>::Assoc == ()` + () +} + +fn main() { + let a = test(); +} diff --git a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr new file mode 100644 index 000000000..a4ff51047 --- /dev/null +++ b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -0,0 +1,20 @@ +error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` + --> $DIR/projection-mismatch-in-impl-where-clause.rs:13:14 + | +LL | fn test() -> impl Test { + | ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()` + | +note: expected this to be `u8` + --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18 + | +LL | type Assoc = u8; + | ^^ +note: required for `()` to implement `Test` + --> $DIR/projection-mismatch-in-impl-where-clause.rs:11:9 + | +LL | impl Test for T where T: Super {} + | ^^^^ ^ ---------- unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/projection.rs b/tests/ui/impl-trait/projection.rs new file mode 100644 index 000000000..b33802e2b --- /dev/null +++ b/tests/ui/impl-trait/projection.rs @@ -0,0 +1,29 @@ +// build-pass +// needs to be build-pass, because it is a regression test for a mir validation failure +// that only happens during codegen. + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { None } +} + +fn run(f: F) + where for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} diff --git a/tests/ui/impl-trait/question_mark.rs b/tests/ui/impl-trait/question_mark.rs new file mode 100644 index 000000000..7bd5cff31 --- /dev/null +++ b/tests/ui/impl-trait/question_mark.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::fmt::Debug; + +#[derive(Debug)] +pub struct Target; + +#[derive(Debug)] +pub struct Source; +impl From for Target { + fn from(_: Source) -> Self { + Self + } +} + +fn maybe_source() -> Result<(), Source> { + todo!() +} + +pub fn typaram() -> Result<(), impl Debug> { + maybe_source()?; + Ok::<_, Target>(()) +} + +pub fn direct() -> Result<(), impl Debug> { + maybe_source()?; + Err(Target) +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-generator.rs b/tests/ui/impl-trait/recursive-generator.rs new file mode 100644 index 000000000..e876f0fb4 --- /dev/null +++ b/tests/ui/impl-trait/recursive-generator.rs @@ -0,0 +1,23 @@ +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; + +fn foo() -> impl Generator { + //~^ ERROR cannot resolve opaque type + //~| NOTE recursive opaque type + //~| NOTE in this expansion of desugaring of + || { + //~^ NOTE returning here + let mut gen = Box::pin(foo()); + //~^ NOTE generator captures itself here + let mut r = gen.as_mut().resume(()); + while let GeneratorState::Yielded(v) = r { + yield v; + r = gen.as_mut().resume(()); + } + } +} + +fn main() { + foo(); +} diff --git a/tests/ui/impl-trait/recursive-generator.stderr b/tests/ui/impl-trait/recursive-generator.stderr new file mode 100644 index 000000000..e23fd4b4a --- /dev/null +++ b/tests/ui/impl-trait/recursive-generator.stderr @@ -0,0 +1,19 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-generator.rs:5:13 + | +LL | fn foo() -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type +... +LL | / || { +LL | | +LL | | let mut gen = Box::pin(foo()); + | | ------- generator captures itself here +LL | | +... | +LL | | } +LL | | } + | |_____- returning here with type `[generator@$DIR/recursive-generator.rs:9:5: 9:7]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-direct.rs b/tests/ui/impl-trait/recursive-impl-trait-type-direct.rs new file mode 100644 index 000000000..540a280f0 --- /dev/null +++ b/tests/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -0,0 +1,9 @@ +// check-pass + +#![allow(unconditional_recursion)] + +fn test() -> impl Sized { + test() +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs new file mode 100644 index 000000000..ffc0cd9d1 --- /dev/null +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs @@ -0,0 +1,96 @@ +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden. + +#![feature(generators)] +#![allow(unconditional_recursion)] + +fn option(i: i32) -> impl Sized { + //~^ ERROR cannot resolve opaque type + if i < 0 { None } else { Some((option(i - 1), i)) } +} + +fn tuple() -> impl Sized { + //~^ ERROR + (tuple(),) +} + +fn array() -> impl Sized { + //~^ ERROR + [array()] +} + +fn ptr() -> impl Sized { + //~^ ERROR + &ptr() as *const _ +} + +fn fn_ptr() -> impl Sized { + //~^ ERROR + fn_ptr as fn() -> _ +} + +fn closure_capture() -> impl Sized { + //~^ ERROR + let x = closure_capture(); + move || { + x; + } +} + +fn closure_ref_capture() -> impl Sized { + //~^ ERROR + let x = closure_ref_capture(); + move || { + &x; + } +} + +fn closure_sig() -> impl Sized { + //~^ ERROR + || closure_sig() +} + +fn generator_sig() -> impl Sized { + //~^ ERROR + || generator_sig() +} + +fn generator_capture() -> impl Sized { + //~^ ERROR + let x = generator_capture(); + move || { + yield; + x; + } +} + +fn substs_change() -> impl Sized { + //~^ ERROR + (substs_change::<&T>(),) +} + +fn generator_hold() -> impl Sized { + //~^ ERROR + move || { + let x = generator_hold(); + yield; + x; + } +} + +fn use_fn_ptr() -> impl Sized { + // OK, error already reported + fn_ptr() +} + +fn mutual_recursion() -> impl Sync { + //~^ ERROR + mutual_recursion_b() +} + +fn mutual_recursion_b() -> impl Sized { + //~^ ERROR + mutual_recursion() +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr new file mode 100644 index 000000000..ebb231ae1 --- /dev/null +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -0,0 +1,152 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:7:22 + | +LL | fn option(i: i32) -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | if i < 0 { None } else { Some((option(i - 1), i)) } + | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>` + | | + | returning here with type `Option<(impl Sized, i32)>` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:12:15 + | +LL | fn tuple() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | (tuple(),) + | ---------- returning here with type `(impl Sized,)` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:17:15 + | +LL | fn array() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | [array()] + | --------- returning here with type `[impl Sized; 1]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:22:13 + | +LL | fn ptr() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | &ptr() as *const _ + | ------------------ returning here with type `*const impl Sized` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:27:16 + | +LL | fn fn_ptr() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | fn_ptr as fn() -> _ + | ------------------- returning here with type `fn() -> impl Sized` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:32:25 + | +LL | fn closure_capture() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +... +LL | / move || { +LL | | x; + | | - closure captures itself here +LL | | } + | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 35:12]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:40:29 + | +LL | fn closure_ref_capture() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +... +LL | / move || { +LL | | &x; + | | - closure captures itself here +LL | | } + | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 43:12]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:48:21 + | +LL | fn closure_sig() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | || closure_sig() + | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:7]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:53:23 + | +LL | fn generator_sig() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | || generator_sig() + | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:58:27 + | +LL | fn generator_capture() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +... +LL | / move || { +LL | | yield; +LL | | x; + | | - generator captures itself here +LL | | } + | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:67:35 + | +LL | fn substs_change() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | (substs_change::<&T>(),) + | ------------------------ returning here with type `(impl Sized,)` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:72:24 + | +LL | fn generator_hold() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | / move || { +LL | | let x = generator_hold(); + | | - generator captures itself here +LL | | yield; +LL | | x; +LL | | } + | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 74:12]` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:86:26 + | +LL | fn mutual_recursion() -> impl Sync { + | ^^^^^^^^^ recursive opaque type +LL | +LL | mutual_recursion_b() + | -------------------- returning here with type `impl Sized` +... +LL | fn mutual_recursion_b() -> impl Sized { + | ---------- returning this opaque type `impl Sized` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-indirect.rs:91:28 + | +LL | fn mutual_recursion() -> impl Sync { + | --------- returning this opaque type `impl Sync` +... +LL | fn mutual_recursion_b() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | +LL | mutual_recursion() + | ------------------ returning here with type `impl Sync` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs b/tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs new file mode 100644 index 000000000..818e40365 --- /dev/null +++ b/tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs @@ -0,0 +1,25 @@ +// Test that impl trait does not allow creating recursive types that are +// otherwise forbidden. Even when there's an opaque type in another crate +// hiding this. + +fn id(t: T) -> impl Sized { t } + +fn recursive_id() -> impl Sized { //~ ERROR cannot resolve opaque type + id(recursive_id2()) +} + +fn recursive_id2() -> impl Sized { //~ ERROR cannot resolve opaque type + id(recursive_id()) +} + +fn wrap(t: T) -> impl Sized { (t,) } + +fn recursive_wrap() -> impl Sized { //~ ERROR cannot resolve opaque type + wrap(recursive_wrap2()) +} + +fn recursive_wrap2() -> impl Sized { //~ ERROR cannot resolve opaque type + wrap(recursive_wrap()) +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr new file mode 100644 index 000000000..b514e9fef --- /dev/null +++ b/tests/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr @@ -0,0 +1,47 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22 + | +LL | fn id(t: T) -> impl Sized { t } + | ---------- returning this opaque type `impl Sized` +LL | +LL | fn recursive_id() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | id(recursive_id2()) + | ------------------- returning here with type `impl Sized` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23 + | +LL | fn id(t: T) -> impl Sized { t } + | ---------- returning this opaque type `impl Sized` +... +LL | fn recursive_id2() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | id(recursive_id()) + | ------------------ returning here with type `impl Sized` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24 + | +LL | fn wrap(t: T) -> impl Sized { (t,) } + | ---------- returning this opaque type `impl Sized` +LL | +LL | fn recursive_wrap() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | wrap(recursive_wrap2()) + | ----------------------- returning here with type `impl Sized` + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25 + | +LL | fn wrap(t: T) -> impl Sized { (t,) } + | ---------- returning this opaque type `impl Sized` +... +LL | fn recursive_wrap2() -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +LL | wrap(recursive_wrap()) + | ---------------------- returning here with type `impl Sized` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs new file mode 100644 index 000000000..af9dfe25b --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl PartialEq<(Foo, i32)>; + +struct Bar; + +impl PartialEq<(Foo, i32)> for Bar { + fn eq(&self, _other: &(Foo, i32)) -> bool { + true + } +} + +fn foo() -> Foo { + //~^ ERROR can't compare `Bar` with `(Bar, i32)` + Bar +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr new file mode 100644 index 000000000..7b63a3d0b --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: can't compare `Bar` with `(Bar, i32)` + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13 + | +LL | fn foo() -> Foo { + | ^^^ no implementation for `Bar == (Bar, i32)` +LL | +LL | Bar + | --- return type was inferred to be `Bar` here + | + = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` + = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs new file mode 100644 index 000000000..91f1ed481 --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +mod a { + type Foo = impl PartialEq<(Foo, i32)>; + //~^ ERROR: unconstrained opaque type + + struct Bar; + + impl PartialEq<(Bar, i32)> for Bar { + fn eq(&self, _other: &(Foo, i32)) -> bool { + //~^ ERROR: `eq` has an incompatible type for trait + true + } + } +} + +mod b { + type Foo = impl PartialEq<(Foo, i32)>; + //~^ ERROR: unconstrained opaque type + + struct Bar; + + impl PartialEq<(Foo, i32)> for Bar { + fn eq(&self, _other: &(Bar, i32)) -> bool { + //~^ ERROR: `eq` has an incompatible type for trait + true + } + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr new file mode 100644 index 000000000..c7c6ca440 --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -0,0 +1,49 @@ +error: unconstrained opaque type + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error[E0053]: method `eq` has an incompatible type for trait + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | -------------------------- the found opaque type +... +LL | fn eq(&self, _other: &(Foo, i32)) -> bool { + | ^^^^^^^^^^^ + | | + | expected struct `Bar`, found opaque type + | help: change the parameter type to match the trait: `&(a::Bar, i32)` + | + = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _` + found signature `fn(&a::Bar, &(a::Foo, i32)) -> _` + +error: unconstrained opaque type + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error[E0053]: method `eq` has an incompatible type for trait + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | -------------------------- the expected opaque type +... +LL | fn eq(&self, _other: &(Bar, i32)) -> bool { + | ^^^^^^^^^^^ + | | + | expected opaque type, found struct `Bar` + | help: change the parameter type to match the trait: `&(b::Foo, i32)` + | + = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _` + found signature `fn(&b::Bar, &(b::Bar, i32)) -> _` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs new file mode 100644 index 000000000..ad0a003e8 --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type Foo = impl PartialEq<(Foo, i32)>; + +struct Bar; + +impl PartialEq<(Bar, i32)> for Bar { + fn eq(&self, _other: &(Bar, i32)) -> bool { + true + } +} + +fn foo() -> Foo { + Bar +} + +fn main() {} diff --git a/tests/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs b/tests/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs new file mode 100644 index 000000000..9f63a8617 --- /dev/null +++ b/tests/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs @@ -0,0 +1,18 @@ +// In contrast to `region-escape-via-bound-invariant`, in this case we +// *can* return a value of type `&'x u32`, even though `'x` does not +// appear in the bounds. This is because `&` is contravariant, and so +// we are *actually* returning a `&'y u32`. +// +// See https://github.com/rust-lang/rust/issues/46541 for more details. + +// run-pass + +#![allow(dead_code)] + +fn foo<'x, 'y>(x: &'x u32) -> impl Fn() -> &'y u32 +where 'x: 'y +{ + move || x +} + +fn main() { } diff --git a/tests/ui/impl-trait/region-escape-via-bound-contravariant.rs b/tests/ui/impl-trait/region-escape-via-bound-contravariant.rs new file mode 100644 index 000000000..79319dfe7 --- /dev/null +++ b/tests/ui/impl-trait/region-escape-via-bound-contravariant.rs @@ -0,0 +1,22 @@ +// In contrast to `region-escape-via-bound-invariant`, in this case we +// *can* return a value of type `&'x u32`, even though `'x` does not +// appear in the bounds. This is because `&` is contravariant, and so +// we are *actually* returning a `&'y u32`. +// +// See https://github.com/rust-lang/rust/issues/46541 for more details. + +// run-pass + +#![allow(dead_code)] + +trait Trait<'a> { } + +impl<'a, 'b> Trait<'b> for &'a u32 { } + +fn foo<'x, 'y>(x: &'x u32) -> impl Trait<'y> +where 'x: 'y +{ + x +} + +fn main() { } diff --git a/tests/ui/impl-trait/region-escape-via-bound.rs b/tests/ui/impl-trait/region-escape-via-bound.rs new file mode 100644 index 000000000..fe60c76ca --- /dev/null +++ b/tests/ui/impl-trait/region-escape-via-bound.rs @@ -0,0 +1,21 @@ +// Test that we do not allow the region `'x` to escape in the impl +// trait **even though** `'y` escapes, which outlives `'x`. +// +// See https://github.com/rust-lang/rust/issues/46541 for more details. + +#![allow(dead_code)] + +use std::cell::Cell; + +trait Trait<'a> { } + +impl<'a, 'b> Trait<'b> for Cell<&'a u32> { } + +fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> +where 'x: 'y +{ + x + //~^ ERROR hidden type for `impl Trait<'y>` captures lifetime that does not appear in bounds [E0700] +} + +fn main() { } diff --git a/tests/ui/impl-trait/region-escape-via-bound.stderr b/tests/ui/impl-trait/region-escape-via-bound.stderr new file mode 100644 index 000000000..44a790cb1 --- /dev/null +++ b/tests/ui/impl-trait/region-escape-via-bound.stderr @@ -0,0 +1,17 @@ +error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not appear in bounds + --> $DIR/region-escape-via-bound.rs:17:5 + | +LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + | -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here +... +LL | x + | ^ + | +help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound + | +LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/return-position-impl-trait-minimal.rs b/tests/ui/impl-trait/return-position-impl-trait-minimal.rs new file mode 100644 index 000000000..6d3c06929 --- /dev/null +++ b/tests/ui/impl-trait/return-position-impl-trait-minimal.rs @@ -0,0 +1,5 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn main() {} + +fn foo() -> impl std::fmt::Debug { "cake" } diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs new file mode 100644 index 000000000..a4e603de1 --- /dev/null +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs @@ -0,0 +1,7 @@ +// check-pass + +pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + v.into_iter() +} + +fn main() {} diff --git a/tests/ui/impl-trait/rpit-not-sized.rs b/tests/ui/impl-trait/rpit-not-sized.rs new file mode 100644 index 000000000..bd2594078 --- /dev/null +++ b/tests/ui/impl-trait/rpit-not-sized.rs @@ -0,0 +1,6 @@ +fn foo() -> impl ?Sized { + //~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/rpit-not-sized.stderr b/tests/ui/impl-trait/rpit-not-sized.stderr new file mode 100644 index 000000000..608c94fc0 --- /dev/null +++ b/tests/ui/impl-trait/rpit-not-sized.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time + --> $DIR/rpit-not-sized.rs:1:13 + | +LL | fn foo() -> impl ?Sized { + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl ?Sized` + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.rs b/tests/ui/impl-trait/static-return-lifetime-infered.rs new file mode 100644 index 000000000..36ef9ea44 --- /dev/null +++ b/tests/ui/impl-trait/static-return-lifetime-infered.rs @@ -0,0 +1,16 @@ +struct A { + x: [(u32, u32); 10] +} + +impl A { + fn iter_values_anon(&self) -> impl Iterator { + self.x.iter().map(|a| a.0) + //~^ ERROR: captures lifetime that does not appear in bounds + } + fn iter_values<'a>(&'a self) -> impl Iterator { + self.x.iter().map(|a| a.0) + //~^ ERROR: captures lifetime that does not appear in bounds + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.stderr b/tests/ui/impl-trait/static-return-lifetime-infered.stderr new file mode 100644 index 000000000..c451f8e37 --- /dev/null +++ b/tests/ui/impl-trait/static-return-lifetime-infered.stderr @@ -0,0 +1,29 @@ +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/static-return-lifetime-infered.rs:7:9 + | +LL | fn iter_values_anon(&self) -> impl Iterator { + | ----- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here +LL | self.x.iter().map(|a| a.0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | fn iter_values_anon(&self) -> impl Iterator + '_ { + | ++++ + +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/static-return-lifetime-infered.rs:11:9 + | +LL | fn iter_values<'a>(&'a self) -> impl Iterator { + | -- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here +LL | self.x.iter().map(|a| a.0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound + | +LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/suggest-calling-rpit-closure.rs b/tests/ui/impl-trait/suggest-calling-rpit-closure.rs new file mode 100644 index 000000000..640156291 --- /dev/null +++ b/tests/ui/impl-trait/suggest-calling-rpit-closure.rs @@ -0,0 +1,12 @@ +fn whatever() -> i32 { + opaque() +//~^ ERROR mismatched types +} + +fn opaque() -> impl Fn() -> i32 { + || 0 +} + +fn main() { + let _ = whatever(); +} diff --git a/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr b/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr new file mode 100644 index 000000000..c10a856d8 --- /dev/null +++ b/tests/ui/impl-trait/suggest-calling-rpit-closure.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/suggest-calling-rpit-closure.rs:2:5 + | +LL | fn whatever() -> i32 { + | --- expected `i32` because of return type +LL | opaque() + | ^^^^^^^^ expected `i32`, found opaque type +... +LL | fn opaque() -> impl Fn() -> i32 { + | ---------------- the found opaque type + | + = note: expected type `i32` + found opaque type `impl Fn() -> i32` +help: use parentheses to call this opaque type + | +LL | opaque()() + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/trait_resolution.rs b/tests/ui/impl-trait/trait_resolution.rs new file mode 100644 index 000000000..8dcbbfd6e --- /dev/null +++ b/tests/ui/impl-trait/trait_resolution.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::fmt::Debug; + +pub struct EventStream { + stream: S, +} + +impl EventStream { + fn into_stream(self) -> impl Debug { + unimplemented!() + } + + pub fn into_reader(self) -> impl Debug { + ReaderStream::from(self.into_stream()) + } +} + +#[derive(Debug)] +pub struct ReaderStream { + stream: S, +} + +impl From for ReaderStream { + fn from(stream: S) -> Self { + ReaderStream { stream } + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/trait_type.rs b/tests/ui/impl-trait/trait_type.rs new file mode 100644 index 000000000..638fefc46 --- /dev/null +++ b/tests/ui/impl-trait/trait_type.rs @@ -0,0 +1,24 @@ +struct MyType; +struct MyType2; +struct MyType3; +struct MyType4; + +impl std::fmt::Display for MyType { + fn fmt(&self, x: &str) -> () { } + //~^ ERROR method `fmt` has an incompatible type +} + +impl std::fmt::Display for MyType2 { + fn fmt(&self) -> () { } + //~^ ERROR method `fmt` has 1 parameter +} + +impl std::fmt::Display for MyType3 { + fn fmt() -> () { } + //~^ ERROR method `fmt` has a `&self` declaration in the trait +} + +impl std::fmt::Display for MyType4 {} +//~^ ERROR not all trait items + +fn main() {} diff --git a/tests/ui/impl-trait/trait_type.stderr b/tests/ui/impl-trait/trait_type.stderr new file mode 100644 index 000000000..81e4c933e --- /dev/null +++ b/tests/ui/impl-trait/trait_type.stderr @@ -0,0 +1,40 @@ +error[E0053]: method `fmt` has an incompatible type for trait + --> $DIR/trait_type.rs:7:21 + | +LL | fn fmt(&self, x: &str) -> () { } + | ^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `&mut Formatter<'_>` + | + = note: expected signature `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` + found signature `fn(&MyType, &str)` + +error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2 + --> $DIR/trait_type.rs:12:11 + | +LL | fn fmt(&self) -> () { } + | ^^^^^ expected 2 parameters, found 1 + | + = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` + +error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in the impl + --> $DIR/trait_type.rs:17:4 + | +LL | fn fmt() -> () { } + | ^^^^^^^^^^^^^^ expected `&self` in impl + | + = note: `fmt` from trait: `fn(&Self, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` + +error[E0046]: not all trait items implemented, missing: `fmt` + --> $DIR/trait_type.rs:21:1 + | +LL | impl std::fmt::Display for MyType4 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation + | + = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0046, E0050, E0053, E0186. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.rs b/tests/ui/impl-trait/two_tait_defining_each_other.rs new file mode 100644 index 000000000..6eb2a11b2 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +type A = impl Foo; +type B = impl Foo; + +trait Foo {} + +fn muh(x: A) -> B { + if false { + return Bar; // B's hidden type is Bar + } + x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other + //~^ ERROR opaque type's hidden type cannot be another opaque type +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.stderr b/tests/ui/impl-trait/two_tait_defining_each_other.stderr new file mode 100644 index 000000000..1a42ac525 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/two_tait_defining_each_other.rs:12:5 + | +LL | x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other + | ^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/two_tait_defining_each_other.rs:4:10 + | +LL | type B = impl Foo; + | ^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/two_tait_defining_each_other.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs new file mode 100644 index 000000000..05b096680 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +type A = impl Foo; //~ ERROR unconstrained opaque type +type B = impl Foo; + +trait Foo {} + +fn muh(x: A) -> B { + x // B's hidden type is A (opaquely) + //~^ ERROR opaque type's hidden type cannot be another opaque type +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.stderr new file mode 100644 index 000000000..4d8f96de1 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other2.stderr @@ -0,0 +1,27 @@ +error: unconstrained opaque type + --> $DIR/two_tait_defining_each_other2.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + | + = note: `A` must be used in combination with a concrete type within the same module + +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/two_tait_defining_each_other2.rs:9:5 + | +LL | x // B's hidden type is A (opaquely) + | ^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/two_tait_defining_each_other2.rs:4:10 + | +LL | type B = impl Foo; + | ^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/two_tait_defining_each_other2.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.rs b/tests/ui/impl-trait/two_tait_defining_each_other3.rs new file mode 100644 index 000000000..37f8ae1b8 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other3.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +type A = impl Foo; +type B = impl Foo; + +trait Foo {} + +fn muh(x: A) -> B { + if false { + return x; // B's hidden type is A (opaquely) + //~^ ERROR opaque type's hidden type cannot be another opaque type + } + Bar // A's hidden type is `Bar`, because all the return types are compared with each other +} + +struct Bar; +impl Foo for Bar {} + +fn main() {} diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.stderr b/tests/ui/impl-trait/two_tait_defining_each_other3.stderr new file mode 100644 index 000000000..b06dc16d5 --- /dev/null +++ b/tests/ui/impl-trait/two_tait_defining_each_other3.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/two_tait_defining_each_other3.rs:10:16 + | +LL | return x; // B's hidden type is A (opaquely) + | ^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/two_tait_defining_each_other3.rs:4:10 + | +LL | type B = impl Foo; + | ^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/two_tait_defining_each_other3.rs:3:10 + | +LL | type A = impl Foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/type-alias-generic-param.rs b/tests/ui/impl-trait/type-alias-generic-param.rs new file mode 100644 index 000000000..3499b2859 --- /dev/null +++ b/tests/ui/impl-trait/type-alias-generic-param.rs @@ -0,0 +1,23 @@ +// Regression test for issue #59342 +// Checks that we properly detect defining uses of opaque +// types in 'item' position when generic parameters are involved +// +// run-pass +#![feature(type_alias_impl_trait)] + +trait Meow { + type MeowType; + fn meow(self) -> Self::MeowType; +} + +impl Meow for I +where + I: Iterator, +{ + type MeowType = impl Iterator; + fn meow(self) -> Self::MeowType { + self + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs b/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs new file mode 100644 index 000000000..91be4efd5 --- /dev/null +++ b/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() { + type Existential = impl Debug; + + fn f() -> Existential {} + println!("{:?}", f()); +} diff --git a/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs b/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs new file mode 100644 index 000000000..ecfa5c69e --- /dev/null +++ b/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs @@ -0,0 +1,16 @@ +trait Foo { + type T; + fn foo(&self, t: Self::T); +//~^ NOTE expected 0 type parameters +} + +impl Foo for u32 { + type T = (); + + fn foo(&self, t: impl Clone) {} +//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters +//~| NOTE found 1 type parameter +//~| NOTE `impl Trait` introduces an implicit type parameter +} + +fn main() {} diff --git a/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr b/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr new file mode 100644 index 000000000..30322f88c --- /dev/null +++ b/tests/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr @@ -0,0 +1,15 @@ +error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22 + | +LL | fn foo(&self, t: Self::T); + | - expected 0 type parameters +... +LL | fn foo(&self, t: impl Clone) {} + | ^^^^^^^^^^ + | | + | found 1 type parameter + | `impl Trait` introduces an implicit type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/type_parameters_captured.rs b/tests/ui/impl-trait/type_parameters_captured.rs new file mode 100644 index 000000000..81ee7d3f8 --- /dev/null +++ b/tests/ui/impl-trait/type_parameters_captured.rs @@ -0,0 +1,12 @@ +use std::fmt::Debug; + +trait Any {} +impl Any for T {} + +// Check that type parameters are captured and not considered 'static +fn foo(x: T) -> impl Any + 'static { + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/type_parameters_captured.stderr b/tests/ui/impl-trait/type_parameters_captured.stderr new file mode 100644 index 000000000..fb502cfdd --- /dev/null +++ b/tests/ui/impl-trait/type_parameters_captured.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/type_parameters_captured.rs:8:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo(x: T) -> impl Any + 'static { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/unactionable_diagnostic.fixed b/tests/ui/impl-trait/unactionable_diagnostic.fixed new file mode 100644 index 000000000..6c2505177 --- /dev/null +++ b/tests/ui/impl-trait/unactionable_diagnostic.fixed @@ -0,0 +1,25 @@ +// run-rustfix + +pub trait Trait {} + +pub struct Foo; + +impl Trait for Foo {} + +fn foo<'x, P>( + _post: P, + x: &'x Foo, +) -> &'x impl Trait { + x +} + +pub fn bar<'t, T: 't>( + //~^ HELP: consider adding an explicit lifetime bound... + post: T, + x: &'t Foo, +) -> &'t impl Trait { + foo(post, x) + //~^ ERROR: the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/unactionable_diagnostic.rs b/tests/ui/impl-trait/unactionable_diagnostic.rs new file mode 100644 index 000000000..bce35cbdd --- /dev/null +++ b/tests/ui/impl-trait/unactionable_diagnostic.rs @@ -0,0 +1,25 @@ +// run-rustfix + +pub trait Trait {} + +pub struct Foo; + +impl Trait for Foo {} + +fn foo<'x, P>( + _post: P, + x: &'x Foo, +) -> &'x impl Trait { + x +} + +pub fn bar<'t, T>( + //~^ HELP: consider adding an explicit lifetime bound... + post: T, + x: &'t Foo, +) -> &'t impl Trait { + foo(post, x) + //~^ ERROR: the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/unactionable_diagnostic.stderr b/tests/ui/impl-trait/unactionable_diagnostic.stderr new file mode 100644 index 000000000..a32004cda --- /dev/null +++ b/tests/ui/impl-trait/unactionable_diagnostic.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/unactionable_diagnostic.rs:21:5 + | +LL | foo(post, x) + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | pub fn bar<'t, T: 't>( + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/impl-trait/universal-mismatched-type.rs b/tests/ui/impl-trait/universal-mismatched-type.rs new file mode 100644 index 000000000..e9129bbd7 --- /dev/null +++ b/tests/ui/impl-trait/universal-mismatched-type.rs @@ -0,0 +1,7 @@ +use std::fmt::Debug; + +fn foo(x: impl Debug) -> String { + x //~ ERROR mismatched types +} + +fn main() { } diff --git a/tests/ui/impl-trait/universal-mismatched-type.stderr b/tests/ui/impl-trait/universal-mismatched-type.stderr new file mode 100644 index 000000000..817c573c0 --- /dev/null +++ b/tests/ui/impl-trait/universal-mismatched-type.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/universal-mismatched-type.rs:4:5 + | +LL | fn foo(x: impl Debug) -> String { + | ---------- ------ expected `String` because of return type + | | + | this type parameter +LL | x + | ^ expected struct `String`, found type parameter `impl Debug` + | + = note: expected struct `String` + found type parameter `impl Debug` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/universal-two-impl-traits.rs b/tests/ui/impl-trait/universal-two-impl-traits.rs new file mode 100644 index 000000000..689c24012 --- /dev/null +++ b/tests/ui/impl-trait/universal-two-impl-traits.rs @@ -0,0 +1,16 @@ +use std::fmt::Debug; + +fn foo(x: impl Debug, y: impl Debug) -> String { + let mut a = x; + a = y; //~ ERROR mismatched + format!("{:?}", a) +} + +trait S {} + +fn much_universe, U: IntoIterator>>( + _: impl Debug + Clone, +) { +} + +fn main() {} diff --git a/tests/ui/impl-trait/universal-two-impl-traits.stderr b/tests/ui/impl-trait/universal-two-impl-traits.stderr new file mode 100644 index 000000000..ab8a53d0d --- /dev/null +++ b/tests/ui/impl-trait/universal-two-impl-traits.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/universal-two-impl-traits.rs:5:9 + | +LL | fn foo(x: impl Debug, y: impl Debug) -> String { + | ---------- ---------- found type parameter + | | + | expected type parameter +LL | let mut a = x; + | - expected due to this value +LL | a = y; + | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` + | + = note: expected type parameter `impl Debug` (type parameter `impl Debug`) + found type parameter `impl Debug` (type parameter `impl Debug`) + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/universal_hrtb_anon.rs b/tests/ui/impl-trait/universal_hrtb_anon.rs new file mode 100644 index 000000000..30c8d291f --- /dev/null +++ b/tests/ui/impl-trait/universal_hrtb_anon.rs @@ -0,0 +1,10 @@ +// run-pass + +fn hrtb(f: impl Fn(&u32) -> u32) -> u32 { + f(&22) + f(&44) +} + +fn main() { + let sum = hrtb(|x| x * 2); + assert_eq!(sum, 22*2 + 44*2); +} diff --git a/tests/ui/impl-trait/universal_hrtb_named.rs b/tests/ui/impl-trait/universal_hrtb_named.rs new file mode 100644 index 000000000..07ff5d23e --- /dev/null +++ b/tests/ui/impl-trait/universal_hrtb_named.rs @@ -0,0 +1,10 @@ +// run-pass + +fn hrtb(f: impl for<'a> Fn(&'a u32) -> &'a u32) -> u32 { + f(&22) + f(&44) +} + +fn main() { + let sum = hrtb(|x| x); + assert_eq!(sum, 22 + 44); +} diff --git a/tests/ui/impl-trait/universal_in_adt_in_parameters.rs b/tests/ui/impl-trait/universal_in_adt_in_parameters.rs new file mode 100644 index 000000000..a3829133d --- /dev/null +++ b/tests/ui/impl-trait/universal_in_adt_in_parameters.rs @@ -0,0 +1,22 @@ +// run-pass + +use std::fmt::Display; + +fn check_display_eq(iter: &Vec) { + let mut collected = String::new(); + for it in iter { + let disp = format!("{} ", it); + collected.push_str(&disp); + } + assert_eq!("0 3 27 823 4891 1 0", collected.trim()); +} + +fn main() { + let i32_list_vec = vec![0i32, 3, 27, 823, 4891, 1, 0]; + let u32_list_vec = vec![0u32, 3, 27, 823, 4891, 1, 0]; + let str_list_vec = vec!["0", "3", "27", "823", "4891", "1", "0"]; + + check_display_eq(&i32_list_vec); + check_display_eq(&u32_list_vec); + check_display_eq(&str_list_vec); +} diff --git a/tests/ui/impl-trait/universal_in_impl_trait_in_parameters.rs b/tests/ui/impl-trait/universal_in_impl_trait_in_parameters.rs new file mode 100644 index 000000000..e98912d95 --- /dev/null +++ b/tests/ui/impl-trait/universal_in_impl_trait_in_parameters.rs @@ -0,0 +1,30 @@ +// run-pass + +use std::fmt::Display; + +fn check_display_eq(iter: impl IntoIterator) { + let mut collected = String::new(); + for it in iter { + let disp = format!("{} ", it); + collected.push_str(&disp); + } + assert_eq!("0 3 27 823 4891 1 0", collected.trim()); +} + +fn main() { + let i32_list = [0i32, 3, 27, 823, 4891, 1, 0]; + let i32_list_vec = vec![0i32, 3, 27, 823, 4891, 1, 0]; + let u32_list = [0u32, 3, 27, 823, 4891, 1, 0]; + let u32_list_vec = vec![0u32, 3, 27, 823, 4891, 1, 0]; + let u16_list = [0u16, 3, 27, 823, 4891, 1, 0]; + let str_list = ["0", "3", "27", "823", "4891", "1", "0"]; + let str_list_vec = vec!["0", "3", "27", "823", "4891", "1", "0"]; + + check_display_eq(&i32_list); + check_display_eq(i32_list_vec); + check_display_eq(&u32_list); + check_display_eq(u32_list_vec); + check_display_eq(&u16_list); + check_display_eq(&str_list); + check_display_eq(str_list_vec); +} diff --git a/tests/ui/impl-trait/universal_in_trait_defn_parameters.rs b/tests/ui/impl-trait/universal_in_trait_defn_parameters.rs new file mode 100644 index 000000000..23c217a8f --- /dev/null +++ b/tests/ui/impl-trait/universal_in_trait_defn_parameters.rs @@ -0,0 +1,18 @@ +// run-pass + +use std::fmt::Debug; + +trait InTraitDefnParameters { + fn in_parameters(_: impl Debug) -> String; +} + +impl InTraitDefnParameters for () { + fn in_parameters(v: impl Debug) -> String { + format!("() + {:?}", v) + } +} + +fn main() { + let s = <() as InTraitDefnParameters>::in_parameters(22); + assert_eq!(s, "() + 22"); +} diff --git a/tests/ui/impl-trait/universal_multiple_bounds.rs b/tests/ui/impl-trait/universal_multiple_bounds.rs new file mode 100644 index 000000000..40c1405c3 --- /dev/null +++ b/tests/ui/impl-trait/universal_multiple_bounds.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::fmt::Display; + +fn foo(f: impl Display + Clone) -> String { + let g = f.clone(); + format!("{} + {}", f, g) +} + +fn main() { + let sum = foo(format!("22")); + assert_eq!(sum, r"22 + 22"); +} diff --git a/tests/ui/impl-trait/universal_wrong_bounds.rs b/tests/ui/impl-trait/universal_wrong_bounds.rs new file mode 100644 index 000000000..2182506c7 --- /dev/null +++ b/tests/ui/impl-trait/universal_wrong_bounds.rs @@ -0,0 +1,13 @@ +use std::fmt::Display; + +fn foo(f: impl Display + Clone) -> String { + wants_debug(f); + wants_display(f); + wants_clone(f); +} + +fn wants_debug(g: impl Debug) { } //~ ERROR expected trait, found derive macro `Debug` +fn wants_display(g: impl Debug) { } //~ ERROR expected trait, found derive macro `Debug` +fn wants_clone(g: impl Clone) { } + +fn main() {} diff --git a/tests/ui/impl-trait/universal_wrong_bounds.stderr b/tests/ui/impl-trait/universal_wrong_bounds.stderr new file mode 100644 index 000000000..3b1a5e5f4 --- /dev/null +++ b/tests/ui/impl-trait/universal_wrong_bounds.stderr @@ -0,0 +1,25 @@ +error[E0404]: expected trait, found derive macro `Debug` + --> $DIR/universal_wrong_bounds.rs:9:24 + | +LL | fn wants_debug(g: impl Debug) { } + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::fmt::Debug; + | + +error[E0404]: expected trait, found derive macro `Debug` + --> $DIR/universal_wrong_bounds.rs:10:26 + | +LL | fn wants_display(g: impl Debug) { } + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::fmt::Debug; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.rs b/tests/ui/impl-trait/universal_wrong_hrtb.rs new file mode 100644 index 000000000..b9551c2ce --- /dev/null +++ b/tests/ui/impl-trait/universal_wrong_hrtb.rs @@ -0,0 +1,8 @@ +trait Trait<'a> { + type Assoc; +} + +fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {} +//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level + +fn main() {} diff --git a/tests/ui/impl-trait/universal_wrong_hrtb.stderr b/tests/ui/impl-trait/universal_wrong_hrtb.stderr new file mode 100644 index 000000000..37eb8dfa1 --- /dev/null +++ b/tests/ui/impl-trait/universal_wrong_hrtb.stderr @@ -0,0 +1,14 @@ +error: `impl Trait` can only mention lifetimes bound at the fn or impl level + --> $DIR/universal_wrong_hrtb.rs:5:73 + | +LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {} + | ^^ + | +note: lifetime declared here + --> $DIR/universal_wrong_hrtb.rs:5:39 + | +LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {} + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/unsafety-checking-cycle.rs b/tests/ui/impl-trait/unsafety-checking-cycle.rs new file mode 100644 index 000000000..4a5831c5b --- /dev/null +++ b/tests/ui/impl-trait/unsafety-checking-cycle.rs @@ -0,0 +1,32 @@ +// Ensure that we don't get a cycle error from trying to determine whether an +// opaque type implements `Freeze` in safety checking, when it doesn't matter. + +// check-pass + +#![feature(rustc_attrs)] + +struct AnyValue(T); + +// No need to check for `Freeze` here, there's no +// `rustc_layout_scalar_valid_range_start` involved. +fn not_restricted(c: bool) -> impl Sized { + if c { + let x = AnyValue(not_restricted(false)); + &x.0; + } + 2u32 +} + +#[rustc_layout_scalar_valid_range_start(1)] +struct NonZero(T); + +// No need to check for `Freeze` here, we're not borrowing the field. +fn not_field(c: bool) -> impl Sized { + if c { + let x = unsafe { NonZero(not_field(false)) }; + &x; + } + 5u32 +} + +fn main() {} diff --git a/tests/ui/impl-trait/wf-eval-order.rs b/tests/ui/impl-trait/wf-eval-order.rs new file mode 100644 index 000000000..c7d6bb870 --- /dev/null +++ b/tests/ui/impl-trait/wf-eval-order.rs @@ -0,0 +1,39 @@ +// Check that we handle evaluating `wf` predicates correctly. + +// check-pass + +struct X(T) +where + T::V: Clone; + +fn hide(t: T) -> impl Sized { + t +} + +trait A { + type U; +} + +impl A for T { + type U = T; +} + +trait B { + type V; +} + +impl, T> B for S { + type V = T; +} + +fn main() { + // Evaluating `typeof(x): Sized` requires + // + // - `wf(typeof(x))` because we use a projection candidate. + // - `::V: Clone` because that's a bound on the trait. + // - `::V` normalizes to `_#1` where `::U == _#1` + // + // This all works if we evaluate `::U == _#1` before + // `::V`, but we previously had the opposite order. + let x = hide(X(0)); +} diff --git a/tests/ui/impl-trait/where-allowed-2.rs b/tests/ui/impl-trait/where-allowed-2.rs new file mode 100644 index 000000000..1a1210d00 --- /dev/null +++ b/tests/ui/impl-trait/where-allowed-2.rs @@ -0,0 +1,6 @@ +use std::fmt::Debug; + +fn in_adt_in_return() -> Vec { panic!() } +//~^ ERROR type annotations needed + +fn main() {} diff --git a/tests/ui/impl-trait/where-allowed-2.stderr b/tests/ui/impl-trait/where-allowed-2.stderr new file mode 100644 index 000000000..2b328c01c --- /dev/null +++ b/tests/ui/impl-trait/where-allowed-2.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/where-allowed-2.rs:3:30 + | +LL | fn in_adt_in_return() -> Vec { panic!() } + | ^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs new file mode 100644 index 000000000..ff63b04c2 --- /dev/null +++ b/tests/ui/impl-trait/where-allowed.rs @@ -0,0 +1,250 @@ +//! A simple test for testing many permutations of allowedness of +//! impl Trait +#![feature(impl_trait_in_fn_trait_return)] +use std::fmt::Debug; + +// Allowed +fn in_parameters(_: impl Debug) { panic!() } + +// Allowed +fn in_return() -> impl Debug { panic!() } + +// Allowed +fn in_adt_in_parameters(_: Vec) { panic!() } + +// Disallowed +fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Allowed +fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } + +// Disallowed +fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~^^ ERROR nested `impl Trait` is not allowed + +// Disallowed +fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR nested `impl Trait` is not allowed + +// Allowed +fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } + +// Disallowed +fn in_Fn_parameter_in_generics (_: F) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + + +// Allowed +fn in_impl_Trait_in_parameters(_: impl Iterator) { panic!() } + +// Allowed +fn in_impl_Trait_in_return() -> impl IntoIterator { + vec![vec![0; 10], vec![12; 7], vec![8; 3]] +} + +// Disallowed +struct InBraceStructField { x: impl Debug } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +struct InAdtInBraceStructField { x: Vec } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +struct InTupleStructField(impl Debug); +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +enum InEnum { + InBraceVariant { x: impl Debug }, + //~^ ERROR `impl Trait` only allowed in function and inherent method return types + InTupleVariant(impl Debug), + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Allowed +trait InTraitDefnParameters { + fn in_parameters(_: impl Debug); +} + +// Disallowed +trait InTraitDefnReturn { + fn in_return() -> impl Debug; + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Allowed and disallowed in trait impls +trait DummyTrait { + type Out; + fn in_trait_impl_parameter(_: impl Debug); + fn in_trait_impl_return() -> Self::Out; +} +impl DummyTrait for () { + type Out = impl Debug; + //~^ ERROR `impl Trait` in type aliases is unstable + + fn in_trait_impl_parameter(_: impl Debug) { } + // Allowed + + fn in_trait_impl_return() -> impl Debug { () } + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Allowed +struct DummyType; +impl DummyType { + fn in_inherent_impl_parameters(_: impl Debug) { } + fn in_inherent_impl_return() -> impl Debug { () } +} + +// Disallowed +extern "C" { + fn in_foreign_parameters(_: impl Debug); + //~^ ERROR `impl Trait` only allowed in function and inherent method return types + + fn in_foreign_return() -> impl Debug; + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Allowed +extern "C" fn in_extern_fn_parameters(_: impl Debug) { +} + +// Allowed +extern "C" fn in_extern_fn_return() -> impl Debug { + 22 +} + +type InTypeAlias = impl Debug; +//~^ ERROR `impl Trait` in type aliases is unstable + +type InReturnInTypeAlias = fn() -> impl Debug; +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR `impl Trait` in type aliases is unstable + +// Disallowed in impl headers +impl PartialEq for () { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Disallowed in impl headers +impl PartialEq<()> for impl Debug { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Disallowed in inherent impls +impl impl Debug { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Disallowed in inherent impls +struct InInherentImplAdt { t: T } +impl InInherentImplAdt { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} + +// Disallowed in where clauses +fn in_fn_where_clause() + where impl Debug: Debug +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +{ +} + +// Disallowed in where clauses +fn in_adt_in_fn_where_clause() + where Vec: Debug +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +{ +} + +// Disallowed +fn in_trait_parameter_in_fn_where_clause() + where T: PartialEq +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +{ +} + +// Disallowed +fn in_Fn_parameter_in_fn_where_clause() + where T: Fn(impl Debug) +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +{ +} + +// Disallowed +fn in_Fn_return_in_fn_where_clause() + where T: Fn() -> impl Debug +//~^ ERROR `impl Trait` only allowed in function and inherent method return types +{ +} + +// Disallowed +struct InStructGenericParamDefault(T); +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +enum InEnumGenericParamDefault { Variant(T) } +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +trait InTraitGenericParamDefault {} +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +type InTypeAliasGenericParamDefault = T; +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +// Disallowed +impl T {} +//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +//~| WARNING this was previously accepted by the compiler but is being phased out +//~| ERROR `impl Trait` only allowed in function and inherent method return types +//~| ERROR no nominal type found + +// Disallowed +fn in_method_generic_param_default(_: T) {} +//~^ ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +//~| WARNING this was previously accepted by the compiler but is being phased out +//~| ERROR `impl Trait` only allowed in function and inherent method return types + +fn main() { + let _in_local_variable: impl Fn() = || {}; + //~^ ERROR `impl Trait` only allowed in function and inherent method return types + let _in_return_in_local_variable = || -> impl Fn() { || {} }; + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr new file mode 100644 index 000000000..3ad0a9f9d --- /dev/null +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -0,0 +1,316 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/where-allowed.rs:47:51 + | +LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } + | --------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/where-allowed.rs:56:57 + | +LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } + | --------^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/where-allowed.rs:118:16 + | +LL | type Out = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/where-allowed.rs:153:23 + | +LL | type InTypeAlias = impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/where-allowed.rs:156:39 + | +LL | type InReturnInTypeAlias = fn() -> impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param + --> $DIR/where-allowed.rs:16:40 + | +LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return + --> $DIR/where-allowed.rs:20:42 + | +LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param + --> $DIR/where-allowed.rs:24:38 + | +LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return + --> $DIR/where-allowed.rs:28:40 + | +LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param + --> $DIR/where-allowed.rs:32:49 + | +LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/where-allowed.rs:36:51 + | +LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param + --> $DIR/where-allowed.rs:40:55 + | +LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param + --> $DIR/where-allowed.rs:47:51 + | +LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/where-allowed.rs:52:53 + | +LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param + --> $DIR/where-allowed.rs:56:57 + | +LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param + --> $DIR/where-allowed.rs:64:38 + | +LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/where-allowed.rs:68:40 + | +LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:81:32 + | +LL | struct InBraceStructField { x: impl Debug } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path + --> $DIR/where-allowed.rs:85:41 + | +LL | struct InAdtInBraceStructField { x: Vec } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:89:27 + | +LL | struct InTupleStructField(impl Debug); + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:94:25 + | +LL | InBraceVariant { x: impl Debug }, + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:96:20 + | +LL | InTupleVariant(impl Debug), + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return + --> $DIR/where-allowed.rs:107:23 + | +LL | fn in_return() -> impl Debug; + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return + --> $DIR/where-allowed.rs:124:34 + | +LL | fn in_trait_impl_return() -> impl Debug { () } + | ^^^^^^^^^^ + | + = note: see issue #91611 for more information + = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param + --> $DIR/where-allowed.rs:137:33 + | +LL | fn in_foreign_parameters(_: impl Debug); + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return + --> $DIR/where-allowed.rs:140:31 + | +LL | fn in_foreign_return() -> impl Debug; + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return + --> $DIR/where-allowed.rs:156:39 + | +LL | type InReturnInTypeAlias = fn() -> impl Debug; + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait + --> $DIR/where-allowed.rs:161:16 + | +LL | impl PartialEq for () { + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:166:24 + | +LL | impl PartialEq<()> for impl Debug { + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:171:6 + | +LL | impl impl Debug { + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:177:24 + | +LL | impl InInherentImplAdt { + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:183:11 + | +LL | where impl Debug: Debug + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:190:15 + | +LL | where Vec: Debug + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound + --> $DIR/where-allowed.rs:197:24 + | +LL | where T: PartialEq + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param + --> $DIR/where-allowed.rs:204:17 + | +LL | where T: Fn(impl Debug) + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return + --> $DIR/where-allowed.rs:211:22 + | +LL | where T: Fn() -> impl Debug + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:217:40 + | +LL | struct InStructGenericParamDefault(T); + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:221:36 + | +LL | enum InEnumGenericParamDefault { Variant(T) } + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:225:38 + | +LL | trait InTraitGenericParamDefault {} + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:229:41 + | +LL | type InTypeAliasGenericParamDefault = T; + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:233:11 + | +LL | impl T {} + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/where-allowed.rs:240:40 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/where-allowed.rs:246:29 + | +LL | let _in_local_variable: impl Fn() = || {}; + | ^^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return + --> $DIR/where-allowed.rs:248:46 + | +LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; + | ^^^^^^^^^ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:233:7 + | +LL | impl T {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:240:36 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + +error[E0118]: no nominal type found for inherent implementation + --> $DIR/where-allowed.rs:233:23 + | +LL | impl T {} + | ^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + +error: aborting due to 47 previous errors + +Some errors have detailed explanations: E0118, E0562, E0658, E0666. +For more information about an error, try `rustc --explain E0118`. diff --git a/tests/ui/impl-trait/xcrate.rs b/tests/ui/impl-trait/xcrate.rs new file mode 100644 index 000000000..fe106ff05 --- /dev/null +++ b/tests/ui/impl-trait/xcrate.rs @@ -0,0 +1,11 @@ +// run-pass + +// aux-build:xcrate.rs + +extern crate xcrate; + +fn main() { +// NOTE line below commented out due to issue #45994 +// assert_eq!(xcrate::fourway_add(1)(2)(3)(4), 10); + xcrate::return_closure_accessing_internal_fn()(); +} diff --git a/tests/ui/impl-trait/xcrate_simple.rs b/tests/ui/impl-trait/xcrate_simple.rs new file mode 100644 index 000000000..2b1fc97e3 --- /dev/null +++ b/tests/ui/impl-trait/xcrate_simple.rs @@ -0,0 +1,9 @@ +// run-pass + +// aux-build:xcrate.rs + +extern crate xcrate; + +fn main() { + xcrate::return_internal_fn()(); +} diff --git a/tests/ui/impl-unused-rps-in-assoc-type.rs b/tests/ui/impl-unused-rps-in-assoc-type.rs new file mode 100644 index 000000000..ea41997a6 --- /dev/null +++ b/tests/ui/impl-unused-rps-in-assoc-type.rs @@ -0,0 +1,18 @@ +// Test that lifetime parameters must be constrained if they appear in +// an associated type def'n. Issue #22077. + +trait Fun { + type Output; + fn call<'x>(&'x self) -> Self::Output; +} + +struct Holder { x: String } + +impl<'a> Fun for Holder { //~ ERROR E0207 + type Output = &'a str; + fn call<'b>(&'b self) -> &'b str { + &self.x[..] + } +} + +fn main() { } diff --git a/tests/ui/impl-unused-rps-in-assoc-type.stderr b/tests/ui/impl-unused-rps-in-assoc-type.stderr new file mode 100644 index 000000000..c7ad1b4e6 --- /dev/null +++ b/tests/ui/impl-unused-rps-in-assoc-type.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-rps-in-assoc-type.rs:11:6 + | +LL | impl<'a> Fun for Holder { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-unused-tps-inherent.rs b/tests/ui/impl-unused-tps-inherent.rs new file mode 100644 index 000000000..83a228e55 --- /dev/null +++ b/tests/ui/impl-unused-tps-inherent.rs @@ -0,0 +1,25 @@ +struct MyType; + +struct MyType1(T); + +trait Bar { + type Out; +} + +impl MyType { + //~^ ERROR the type parameter `T` is not constrained +} + +impl MyType1 { + // OK, T is used in `Foo`. +} + +impl MyType1 { + //~^ ERROR the type parameter `U` is not constrained +} + +impl MyType1 where T: Bar { + // OK, T is used in `Foo`. +} + +fn main() { } diff --git a/tests/ui/impl-unused-tps-inherent.stderr b/tests/ui/impl-unused-tps-inherent.stderr new file mode 100644 index 000000000..43f63cf96 --- /dev/null +++ b/tests/ui/impl-unused-tps-inherent.stderr @@ -0,0 +1,15 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps-inherent.rs:9:6 + | +LL | impl MyType { + | ^ unconstrained type parameter + +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps-inherent.rs:17:8 + | +LL | impl MyType1 { + | ^ unconstrained type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/impl-unused-tps.rs b/tests/ui/impl-unused-tps.rs new file mode 100644 index 000000000..7cc1ae613 --- /dev/null +++ b/tests/ui/impl-unused-tps.rs @@ -0,0 +1,62 @@ +trait Foo { + fn get(&self, A: &A) { } +} + +trait Bar { + type Out; +} + +impl Foo for [isize;0] { + // OK, T is used in `Foo`. +} + +impl Foo for [isize;1] { + //~^ ERROR the type parameter `U` is not constrained +} + +impl Foo for [isize;2] where T : Bar { + // OK, `U` is now constrained by the output type parameter. +} + +impl,U> Foo for [isize;3] { + // OK, same as above but written differently. +} + +impl Foo for U { + // OK, T, U are used everywhere. Note that the coherence check + // hasn't executed yet, so no errors about overlap. +} + +impl Bar for T { + //~^ ERROR the type parameter `U` is not constrained + + type Out = U; + + // Using `U` in an associated type within the impl is not good enough! +} + +impl Bar for T + where T : Bar +{ + //~^^^ ERROR the type parameter `U` is not constrained + + // This crafty self-referential attempt is still no good. +} + +impl Foo for T + where (T,U): Bar +{ + //~^^^ ERROR the type parameter `U` is not constrained + //~| ERROR the type parameter `V` is not constrained + + // Here, `V` is bound by an output type parameter, but the inputs + // are not themselves constrained. +} + +impl Foo<(T,U)> for T + where (T,U): Bar +{ + // As above, but both T and U ARE constrained. +} + +fn main() { } diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr new file mode 100644 index 000000000..053ab91c8 --- /dev/null +++ b/tests/ui/impl-unused-tps.stderr @@ -0,0 +1,33 @@ +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps.rs:13:8 + | +LL | impl Foo for [isize;1] { + | ^ unconstrained type parameter + +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps.rs:30:8 + | +LL | impl Bar for T { + | ^ unconstrained type parameter + +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps.rs:38:8 + | +LL | impl Bar for T + | ^ unconstrained type parameter + +error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps.rs:46:8 + | +LL | impl Foo for T + | ^ unconstrained type parameter + +error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-unused-tps.rs:46:10 + | +LL | impl Foo for T + | ^ unconstrained type parameter + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/implicit-method-bind.rs b/tests/ui/implicit-method-bind.rs new file mode 100644 index 000000000..5e27516a8 --- /dev/null +++ b/tests/ui/implicit-method-bind.rs @@ -0,0 +1,3 @@ +fn main() { + let _f = 10i32.abs; //~ ERROR attempted to take value of method +} diff --git a/tests/ui/implicit-method-bind.stderr b/tests/ui/implicit-method-bind.stderr new file mode 100644 index 000000000..e0a968527 --- /dev/null +++ b/tests/ui/implicit-method-bind.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `abs` on type `i32` + --> $DIR/implicit-method-bind.rs:2:20 + | +LL | let _f = 10i32.abs; + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _f = 10i32.abs(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs new file mode 100644 index 000000000..33b746c5e --- /dev/null +++ b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs @@ -0,0 +1,27 @@ +// Test for a less than ideal interaction of implied bounds and normalization. +trait Tr { + type Ty; +} + +impl Tr for T { + type Ty = &'static T; +} + +// `<&'a u8 as Tr>::Ty` should cause an error because `&'a u8: Tr` doesn't hold for +// all possible 'a. However, we consider normalized types for implied bounds. +// +// We normalize this projection to `&'static &'a u8` and add a nested `&'a u8: 'static` +// bound. This bound is then proven using the implied bounds for `&'static &'a u8` which +// we only get by normalizing in the first place. +fn test<'a>(x: &'a u8, _wf: <&'a u8 as Tr>::Ty) -> &'static u8 { x } + +fn main() { + // This works as we have 'static references due to promotion. + let _: &'static u8 = test(&3, &&3); + // This causes an error because the projection requires 'a to be 'static. + // It would be unsound if this compiled. + let x: u8 = 3; + let _: &'static u8 = test(&x, &&3); + //~^ ERROR `x` does not live long enough + +} diff --git a/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr new file mode 100644 index 000000000..d0249e74f --- /dev/null +++ b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/assoc-ty-wf-used-to-get-assoc-ty.rs:24:31 + | +LL | let _: &'static u8 = test(&x, &&3); + | -----^^------ + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +... +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs b/tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs new file mode 100644 index 000000000..c177655c5 --- /dev/null +++ b/tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs @@ -0,0 +1,61 @@ +// A test exploiting the bug behind #25860 except with +// implied trait bounds which currently don't exist without `-Ztrait-solver=chalk`. +use std::marker::PhantomData; +struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) +where + T: Convert<'a, 'b>; + +trait Convert<'a, 'b>: Sized { + fn cast(&'a self) -> &'b Self; +} +impl<'long: 'short, 'short, T> Convert<'long, 'short> for T { + fn cast(&'long self) -> &'short T { + self + } +} + +// This function will compile once we add implied trait bounds. +// +// If we're not careful with our impl, the transformations +// in `bad` would succeed, which is unsound ✨ +// +// FIXME: the error is pretty bad, this should say +// +// `T: Convert<'in_, 'out>` is not implemented +// +// help: needed by `Foo<'in_, 'out, T>` +// +// Please ping @lcnr if your changes end up causing `badboi` to compile. +fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T { + //~^ ERROR lifetime mismatch + sadness.cast() +} + +fn badboi2<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) { + //~^ ERROR lifetime mismatch + let _: &'out T = sadness.cast(); +} + +fn badboi3<'in_, 'out, T>(a: Foo<'in_, 'out, (&'in_ T, &'out T)>, sadness: &'in_ T) { + //~^ ERROR lifetime mismatch + let _: &'out T = sadness.cast(); +} + +fn bad<'short, T>(value: &'short T) -> &'static T { + let x: for<'in_, 'out> fn(Foo<'in_, 'out, T>, &'in_ T) -> &'out T = badboi; + let x: for<'out> fn(Foo<'short, 'out, T>, &'short T) -> &'out T = x; + let x: for<'out> fn(Foo<'static, 'out, T>, &'short T) -> &'out T = x; + let x: fn(Foo<'static, 'static, T>, &'short T) -> &'static T = x; + x(Foo(PhantomData), value) +} + +// Use `bad` to cause a segfault. +fn main() { + let mut outer: Option<&'static u32> = Some(&3); + let static_ref: &'static &'static u32 = match outer { + Some(ref reference) => bad(reference), + None => unreachable!(), + }; + outer = None; + println!("{}", static_ref); +} diff --git a/tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr b/tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr new file mode 100644 index 000000000..0c00bbc38 --- /dev/null +++ b/tests/ui/implied-bounds/hrlt-implied-trait-bounds-guard.stderr @@ -0,0 +1,30 @@ +error[E0623]: lifetime mismatch + --> $DIR/hrlt-implied-trait-bounds-guard.rs:29:29 + | +LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) -> &'out T { + | ^^^^^^^^^^^^^^^^^^ ------- + | | + | this parameter and the return type are declared with different lifetimes... + | ...but data from `x` is returned here + +error[E0623]: lifetime mismatch + --> $DIR/hrlt-implied-trait-bounds-guard.rs:34:30 + | +LL | fn badboi2<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ T) { + | ^^^^^^^^^^^^^^^^^^ + | | + | this type is declared with multiple lifetimes... + | ...but data with one lifetime flows into the other here + +error[E0623]: lifetime mismatch + --> $DIR/hrlt-implied-trait-bounds-guard.rs:39:30 + | +LL | fn badboi3<'in_, 'out, T>(a: Foo<'in_, 'out, (&'in_ T, &'out T)>, sadness: &'in_ T) { + | ^^^^^^^^^^^^^^^^^-------^^-------^^ + | | | + | | these two types are declared with different lifetimes... + | ...but data from `a` flows into `a` here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0623`. diff --git a/tests/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs b/tests/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs new file mode 100644 index 000000000..69847d6a8 --- /dev/null +++ b/tests/ui/implied-bounds/hrlt-implied-trait-bounds-roundtrip.rs @@ -0,0 +1,35 @@ +// check-pass +struct Foo<'a>(&'a ()) +where + (): Trait<'a>; + +trait Trait<'a> { + fn id(value: &'a T) -> &'static T; +} + +impl Trait<'static> for () { + fn id(value: &'static T) -> &'static T { + value + } +} + +fn could_use_implied_bounds<'a, T>(_: Foo<'a>, x: &'a T) -> &'static T +where + (): Trait<'a>, // This could be an implied bound +{ + <()>::id(x) +} + +fn main() { + let bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = |_, _| {}; + + // If `could_use_implied_bounds` were to use implied bounds, + // keeping 'a late-bound, then we could assign that function + // to this variable. + let bar: for<'a> fn(Foo<'a>, &'a ()) = bar; + + // In this case, the subtyping relation here would be unsound, + // allowing us to transmute lifetimes. This currently compiles + // because we incorrectly deal with implied bounds inside of binders. + let _bar: for<'a, 'b> fn(Foo<'a>, &'b ()) = bar; +} diff --git a/tests/ui/implied-bounds/impl-header-unnormalized-types.rs b/tests/ui/implied-bounds/impl-header-unnormalized-types.rs new file mode 100644 index 000000000..d84539f8a --- /dev/null +++ b/tests/ui/implied-bounds/impl-header-unnormalized-types.rs @@ -0,0 +1,28 @@ +struct Foo(T); + +trait GoodBye { + type Forget; +} +impl GoodBye for T { + type Forget = (); +} + +trait NeedsWf<'a, 'b> { + type Assoc; +} + +impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { + type Assoc = &'a &'b (); + //~^ ERROR in type `&'a &'b ()`, reference has a longer lifetime than the data it references +} + +fn needs_wf<'a, 'b, T: NeedsWf<'a, 'b>>() {} + +fn foo<'a: 'a, 'b: 'b>(_: &'b String) { + needs_wf::<'a, 'b, Foo<()>>(); +} + +fn main() { + let x = String::from("hello"); + foo::<'static, '_>(&x); +} diff --git a/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr b/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr new file mode 100644 index 000000000..88abd5f54 --- /dev/null +++ b/tests/ui/implied-bounds/impl-header-unnormalized-types.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references + --> $DIR/impl-header-unnormalized-types.rs:15:18 + | +LL | type Assoc = &'a &'b (); + | ^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/impl-header-unnormalized-types.rs:14:6 + | +LL | impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/impl-header-unnormalized-types.rs:14:10 + | +LL | impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs new file mode 100644 index 000000000..6ccbb5bb2 --- /dev/null +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.rs @@ -0,0 +1,22 @@ +#![deny(implied_bounds_entailment)] + +trait Project { + type Ty; +} +impl Project for &'_ &'_ () { + type Ty = (); +} +trait Trait { + fn get<'s>(s: &'s str, _: ()) -> &'static str; +} +impl Trait for () { + fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + //~^ ERROR impl method assumes more implied bounds than the corresponding trait method + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + s + } +} +fn main() { + let val = <() as Trait>::get(&String::from("blah blah blah"), ()); + println!("{}", val); +} diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr new file mode 100644 index 000000000..ebe07027d --- /dev/null +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -0,0 +1,31 @@ +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs new file mode 100644 index 000000000..d097bc16a --- /dev/null +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs @@ -0,0 +1,21 @@ +#![deny(implied_bounds_entailment)] + +use std::cell::RefCell; + +pub struct MessageListeners<'a> { + listeners: RefCell>>, +} + +pub trait MessageListenersInterface { + fn listeners<'c>(&'c self) -> &'c MessageListeners<'c>; +} + +impl<'a> MessageListenersInterface for MessageListeners<'a> { + fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + //~^ ERROR impl method assumes more implied bounds than the corresponding trait method + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + self + } +} + +fn main() {} diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr new file mode 100644 index 000000000..43d3e058f --- /dev/null +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -0,0 +1,31 @@ +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility.rs:14:35 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility.rs:14:35 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/implied-bounds/issue-100690.rs b/tests/ui/implied-bounds/issue-100690.rs new file mode 100644 index 000000000..5599cd410 --- /dev/null +++ b/tests/ui/implied-bounds/issue-100690.rs @@ -0,0 +1,45 @@ +// This code (probably) _should_ compile, but it currently does not because we +// are not smart enough about implied bounds. + +use std::io; + +fn real_dispatch(f: F) -> Result<(), io::Error> +//~^ NOTE required by a bound in this +where + F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, + //~^ NOTE required by this bound in `real_dispatch` + //~| NOTE required by a bound in `real_dispatch` +{ + todo!() +} + +#[derive(Debug)] +struct UIView<'a, T: 'a> { + _phantom: std::marker::PhantomData<&'a mut T>, +} + +trait Handle<'a, T: 'a, V, R> { + fn dispatch(&self, f: F) -> Result<(), io::Error> + where + F: FnOnce(&mut V) -> R + Send + 'static; +} + +#[derive(Debug, Clone)] +struct TUIHandle { + _phantom: std::marker::PhantomData, +} + +impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle { + fn dispatch(&self, f: F) -> Result<(), io::Error> + where + F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static, + { + real_dispatch(f) + //~^ ERROR expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + //~| NOTE expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + //~| NOTE expected a closure with arguments + //~| NOTE required by a bound introduced by this call + } +} + +fn main() {} diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr new file mode 100644 index 000000000..3f6af70d8 --- /dev/null +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -0,0 +1,22 @@ +error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + --> $DIR/issue-100690.rs:37:23 + | +LL | real_dispatch(f) + | ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + | | + | required by a bound introduced by this call + | + = note: expected a closure with arguments `(&mut UIView<'a, T>,)` + found a closure with arguments `(&mut UIView<'_, T>,)` +note: required by a bound in `real_dispatch` + --> $DIR/issue-100690.rs:9:8 + | +LL | fn real_dispatch(f: F) -> Result<(), io::Error> + | ------------- required by a bound in this +... +LL | F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/implied-bounds/issue-101951.rs b/tests/ui/implied-bounds/issue-101951.rs new file mode 100644 index 000000000..108fef8a1 --- /dev/null +++ b/tests/ui/implied-bounds/issue-101951.rs @@ -0,0 +1,50 @@ +// Taken directly from that issue. +// +// This test detected that we didn't correctly resolve +// inference variables when computing implied bounds. +// +// check-pass +pub trait BuilderFn<'a> { + type Output; +} + +impl<'a, F, Out> BuilderFn<'a> for F +where + F: FnOnce(&'a mut ()) -> Out, +{ + type Output = Out; +} + +pub trait ConstructionFirm { + type Builder: for<'a> BuilderFn<'a>; +} + +pub trait Campus +where + T: ConstructionFirm, +{ + fn add_building( + &mut self, + building: &mut <::Builder as BuilderFn<'_>>::Output, + ); +} + +struct ArchitectsInc {} + +impl ConstructionFirm for ArchitectsInc { + type Builder = fn(&mut ()) -> PrettyCondo<'_>; +} + +struct PrettyCondo<'a> { + _marker: &'a mut (), +} + +struct CondoEstate {} + +impl Campus for CondoEstate { + fn add_building(&mut self, _building: &mut PrettyCondo<'_>) { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/imports/absolute-paths-in-nested-use-groups.rs b/tests/ui/imports/absolute-paths-in-nested-use-groups.rs new file mode 100644 index 000000000..96b513167 --- /dev/null +++ b/tests/ui/imports/absolute-paths-in-nested-use-groups.rs @@ -0,0 +1,11 @@ +#![allow(unused_imports)] + +mod foo {} + +use foo::{ + ::bar, //~ ERROR crate root in paths can only be used in start position + super::bar, //~ ERROR `super` in paths can only be used in start position + self::bar, //~ ERROR `self` in paths can only be used in start position +}; + +fn main() {} diff --git a/tests/ui/imports/absolute-paths-in-nested-use-groups.stderr b/tests/ui/imports/absolute-paths-in-nested-use-groups.stderr new file mode 100644 index 000000000..e41590ac4 --- /dev/null +++ b/tests/ui/imports/absolute-paths-in-nested-use-groups.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: crate root in paths can only be used in start position + --> $DIR/absolute-paths-in-nested-use-groups.rs:6:5 + | +LL | ::bar, + | ^ crate root in paths can only be used in start position + +error[E0433]: failed to resolve: `super` in paths can only be used in start position + --> $DIR/absolute-paths-in-nested-use-groups.rs:7:5 + | +LL | super::bar, + | ^^^^^ `super` in paths can only be used in start position + +error[E0433]: failed to resolve: `self` in paths can only be used in start position + --> $DIR/absolute-paths-in-nested-use-groups.rs:8:5 + | +LL | self::bar, + | ^^^^ `self` in paths can only be used in start position + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/imports/auxiliary/gensymed.rs b/tests/ui/imports/auxiliary/gensymed.rs new file mode 100644 index 000000000..bbb19f5ec --- /dev/null +++ b/tests/ui/imports/auxiliary/gensymed.rs @@ -0,0 +1,3 @@ +// edition:2018 + +mod std {} diff --git a/tests/ui/imports/auxiliary/glob-conflict.rs b/tests/ui/imports/auxiliary/glob-conflict.rs new file mode 100644 index 000000000..c83db64c6 --- /dev/null +++ b/tests/ui/imports/auxiliary/glob-conflict.rs @@ -0,0 +1,13 @@ +mod m1 { + pub fn f() {} +} +mod m2 { + pub fn f(_: u8) {} +} + +pub use m1::*; +pub use m2::*; + +pub mod glob { + pub use *; +} diff --git a/tests/ui/imports/auxiliary/import_crate_var.rs b/tests/ui/imports/auxiliary/import_crate_var.rs new file mode 100644 index 000000000..a273b103a --- /dev/null +++ b/tests/ui/imports/auxiliary/import_crate_var.rs @@ -0,0 +1,7 @@ +pub fn f() {} + +#[macro_export] +macro_rules! m { () => { + use $crate; + import_crate_var::f(); +} } diff --git a/tests/ui/imports/auxiliary/issue-36881-aux.rs b/tests/ui/imports/auxiliary/issue-36881-aux.rs new file mode 100644 index 000000000..e373b6438 --- /dev/null +++ b/tests/ui/imports/auxiliary/issue-36881-aux.rs @@ -0,0 +1 @@ +pub trait Foo {} diff --git a/tests/ui/imports/auxiliary/issue-52891.rs b/tests/ui/imports/auxiliary/issue-52891.rs new file mode 100644 index 000000000..075981183 --- /dev/null +++ b/tests/ui/imports/auxiliary/issue-52891.rs @@ -0,0 +1,33 @@ +pub mod a { + pub mod inner { + } +} + +pub mod b { + pub mod inner { + } +} + +pub mod c {} + +pub mod d {} + +pub mod e {} + +pub mod f {} + +pub mod g {} + +pub mod h {} + +pub mod i {} + +pub mod j {} + +pub mod k {} + +pub mod l {} + +pub mod m {} + +pub mod n {} diff --git a/tests/ui/imports/auxiliary/issue-55811.rs b/tests/ui/imports/auxiliary/issue-55811.rs new file mode 100644 index 000000000..877e4cdb0 --- /dev/null +++ b/tests/ui/imports/auxiliary/issue-55811.rs @@ -0,0 +1,5 @@ +mod m {} + +// These two imports should not conflict when this crate is loaded from some other crate. +use m::{}; +use m::{}; diff --git a/tests/ui/imports/auxiliary/issue-56125.rs b/tests/ui/imports/auxiliary/issue-56125.rs new file mode 100644 index 000000000..8e0797582 --- /dev/null +++ b/tests/ui/imports/auxiliary/issue-56125.rs @@ -0,0 +1,11 @@ +pub mod issue_56125 {} + +pub mod last_segment { + pub mod issue_56125 {} +} + +pub mod non_last_segment { + pub mod non_last_segment { + pub mod issue_56125 {} + } +} diff --git a/tests/ui/imports/auxiliary/issue-59764.rs b/tests/ui/imports/auxiliary/issue-59764.rs new file mode 100644 index 000000000..a92eed968 --- /dev/null +++ b/tests/ui/imports/auxiliary/issue-59764.rs @@ -0,0 +1,18 @@ +pub mod foo { + #[macro_export] + macro_rules! makro { + ($foo:ident) => { + fn $foo() { } + } + } + + pub fn baz() {} + + pub fn foobar() {} + + pub mod barbaz { + pub fn barfoo() {} + } +} + +pub fn foobaz() {} diff --git a/tests/ui/imports/auxiliary/overlapping_pub_trait_source.rs b/tests/ui/imports/auxiliary/overlapping_pub_trait_source.rs new file mode 100644 index 000000000..2a25d60ac --- /dev/null +++ b/tests/ui/imports/auxiliary/overlapping_pub_trait_source.rs @@ -0,0 +1,13 @@ +/* This crate declares an item as both `prelude::*` and `m::Tr`. + * The compiler should always suggest `m::Tr`. */ + +pub struct S; + +pub mod prelude { + pub use crate::m::Tr as _; +} + +pub mod m { + pub trait Tr { fn method(&self); } + impl Tr for crate::S { fn method(&self) {} } +} diff --git a/tests/ui/imports/auxiliary/two_macros.rs b/tests/ui/imports/auxiliary/two_macros.rs new file mode 100644 index 000000000..92c211467 --- /dev/null +++ b/tests/ui/imports/auxiliary/two_macros.rs @@ -0,0 +1,5 @@ +#[macro_export] +macro_rules! m { ($($t:tt)*) => { $($t)* } } + +#[macro_export] +macro_rules! n { ($($t:tt)*) => { $($t)* } } diff --git a/tests/ui/imports/auxiliary/unnamed_pub_trait_source.rs b/tests/ui/imports/auxiliary/unnamed_pub_trait_source.rs new file mode 100644 index 000000000..d73c9a795 --- /dev/null +++ b/tests/ui/imports/auxiliary/unnamed_pub_trait_source.rs @@ -0,0 +1,13 @@ +/* This crate declares an item that is unnamed. + * Its only public path is through `prelude::*`. */ + +pub struct S; + +mod m { + pub trait Tr { fn method(&self); } + impl Tr for crate::S { fn method(&self) {} } +} + +pub mod prelude { + pub use crate::m::Tr as _; +} diff --git a/tests/ui/imports/bad-import-in-nested.rs b/tests/ui/imports/bad-import-in-nested.rs new file mode 100644 index 000000000..2e95480ad --- /dev/null +++ b/tests/ui/imports/bad-import-in-nested.rs @@ -0,0 +1,27 @@ +// edition: 2021 + +#![allow(unused)] + +mod A { + pub(crate) type AA = (); + pub(crate) type BB = (); + + mod A2 { + use super::{super::C::D::AA, AA as _}; + //~^ ERROR unresolved import + } +} + +mod C { + pub mod D {} +} + +mod B { + use crate::C::{self, AA}; + //~^ ERROR unresolved import + + use crate::{A, C::BB}; + //~^ ERROR unresolved import +} + +fn main() {} diff --git a/tests/ui/imports/bad-import-in-nested.stderr b/tests/ui/imports/bad-import-in-nested.stderr new file mode 100644 index 000000000..b6b1bc5fc --- /dev/null +++ b/tests/ui/imports/bad-import-in-nested.stderr @@ -0,0 +1,30 @@ +error[E0432]: unresolved import `super::super::C::D::AA` + --> $DIR/bad-import-in-nested.rs:10:21 + | +LL | use super::{super::C::D::AA, AA as _}; + | ^^^^^^^^^^^^^^^ no `AA` in `C::D` + | + = help: consider importing this type alias instead: + crate::A::AA + +error[E0432]: unresolved import `crate::C::AA` + --> $DIR/bad-import-in-nested.rs:20:26 + | +LL | use crate::C::{self, AA}; + | ^^ no `AA` in `C` + | + = help: consider importing this type alias instead: + crate::A::AA + +error[E0432]: unresolved import `crate::C::BB` + --> $DIR/bad-import-in-nested.rs:23:20 + | +LL | use crate::{A, C::BB}; + | ^^^^^ no `BB` in `C` + | + = help: consider importing this type alias instead: + crate::A::BB + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/bad-import-with-rename.rs b/tests/ui/imports/bad-import-with-rename.rs new file mode 100644 index 000000000..ffe56916f --- /dev/null +++ b/tests/ui/imports/bad-import-with-rename.rs @@ -0,0 +1,16 @@ +mod A { + pub type B = (); + pub type B2 = (); +} + +mod C { + use crate::D::B as _; + //~^ ERROR unresolved import `crate::D::B` + + use crate::D::B2; + //~^ ERROR unresolved import `crate::D::B2` +} + +mod D {} + +fn main() {} diff --git a/tests/ui/imports/bad-import-with-rename.stderr b/tests/ui/imports/bad-import-with-rename.stderr new file mode 100644 index 000000000..f9c5cf920 --- /dev/null +++ b/tests/ui/imports/bad-import-with-rename.stderr @@ -0,0 +1,25 @@ +error[E0432]: unresolved import `crate::D::B` + --> $DIR/bad-import-with-rename.rs:7:9 + | +LL | use crate::D::B as _; + | ^^^^^^^^^^^^^^^^ no `B` in `D` + | +help: consider importing this type alias instead + | +LL | use A::B as _; + | ~~~~~~~~~ + +error[E0432]: unresolved import `crate::D::B2` + --> $DIR/bad-import-with-rename.rs:10:9 + | +LL | use crate::D::B2; + | ^^^^^^^^^^^^ no `B2` in `D` + | +help: consider importing this type alias instead + | +LL | use A::B2; + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/double-import.rs b/tests/ui/imports/double-import.rs new file mode 100644 index 000000000..e7325368b --- /dev/null +++ b/tests/ui/imports/double-import.rs @@ -0,0 +1,15 @@ +// This tests that conflicting imports shows both `use` lines +// when reporting the error. + +mod sub1 { + pub fn foo() {} // implementation 1 +} + +mod sub2 { + pub fn foo() {} // implementation 2 +} + +use sub1::foo; +use sub2::foo; //~ ERROR the name `foo` is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/double-import.stderr b/tests/ui/imports/double-import.stderr new file mode 100644 index 000000000..82f5eb83e --- /dev/null +++ b/tests/ui/imports/double-import.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `foo` is defined multiple times + --> $DIR/double-import.rs:13:5 + | +LL | use sub1::foo; + | --------- previous import of the value `foo` here +LL | use sub2::foo; + | ^^^^^^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the value namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use sub2::foo as other_foo; + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/duplicate.rs b/tests/ui/imports/duplicate.rs new file mode 100644 index 000000000..db6538969 --- /dev/null +++ b/tests/ui/imports/duplicate.rs @@ -0,0 +1,51 @@ +mod a { + pub fn foo() {} +} + +mod b { + pub fn foo() {} +} + +mod c { + pub use a::foo; +} + +mod d { + use a::foo; + use a::foo; //~ ERROR the name `foo` is defined multiple times +} + +mod e { + pub use a::*; + pub use c::*; // ok +} + +mod f { + pub use a::*; + pub use b::*; +} + +mod g { + pub use a::*; + pub use f::*; +} + +fn main() { + e::foo(); + f::foo(); //~ ERROR `foo` is ambiguous + g::foo(); +} + +mod ambiguous_module_errors { + pub mod m1 { pub use super::m1 as foo; pub fn bar() {} } + pub mod m2 { pub use super::m2 as foo; } + + use self::m1::*; + use self::m2::*; + + use self::foo::bar; //~ ERROR `foo` is ambiguous + + fn f() { + foo::bar(); //~ ERROR `foo` is ambiguous + } +} diff --git a/tests/ui/imports/duplicate.stderr b/tests/ui/imports/duplicate.stderr new file mode 100644 index 000000000..997a2741b --- /dev/null +++ b/tests/ui/imports/duplicate.stderr @@ -0,0 +1,74 @@ +error[E0252]: the name `foo` is defined multiple times + --> $DIR/duplicate.rs:15:9 + | +LL | use a::foo; + | ------ previous import of the value `foo` here +LL | use a::foo; + | ^^^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the value namespace of this module + +error[E0659]: `foo` is ambiguous + --> $DIR/duplicate.rs:46:15 + | +LL | use self::foo::bar; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `foo` could refer to the module imported here + --> $DIR/duplicate.rs:43:9 + | +LL | use self::m1::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `foo` to disambiguate +note: `foo` could also refer to the module imported here + --> $DIR/duplicate.rs:44:9 + | +LL | use self::m2::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `foo` to disambiguate + +error[E0659]: `foo` is ambiguous + --> $DIR/duplicate.rs:35:8 + | +LL | f::foo(); + | ^^^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `foo` could refer to the function imported here + --> $DIR/duplicate.rs:24:13 + | +LL | pub use a::*; + | ^^^^ + = help: consider adding an explicit import of `foo` to disambiguate +note: `foo` could also refer to the function imported here + --> $DIR/duplicate.rs:25:13 + | +LL | pub use b::*; + | ^^^^ + = help: consider adding an explicit import of `foo` to disambiguate + +error[E0659]: `foo` is ambiguous + --> $DIR/duplicate.rs:49:9 + | +LL | foo::bar(); + | ^^^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `foo` could refer to the module imported here + --> $DIR/duplicate.rs:43:9 + | +LL | use self::m1::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `foo` to disambiguate +note: `foo` could also refer to the module imported here + --> $DIR/duplicate.rs:44:9 + | +LL | use self::m2::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `foo` to disambiguate + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0252, E0659. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/export-glob-imports-target.rs b/tests/ui/imports/export-glob-imports-target.rs new file mode 100644 index 000000000..4df807ea4 --- /dev/null +++ b/tests/ui/imports/export-glob-imports-target.rs @@ -0,0 +1,22 @@ +// run-pass + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +// Test that a glob-export functions as an import +// when referenced within its own local scope. + +// Modified to not use export since it's going away. --pcw + +// pretty-expanded FIXME #23616 + +mod foo { + use foo::bar::*; + pub mod bar { + pub static a : isize = 10; + } + pub fn zum() { + let _b = a; + } +} + +pub fn main() { } diff --git a/tests/ui/imports/export-multi.rs b/tests/ui/imports/export-multi.rs new file mode 100644 index 000000000..02bdbe8af --- /dev/null +++ b/tests/ui/imports/export-multi.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use m::f; +use m::g; + +mod m { + pub fn f() { } + pub fn g() { } +} + +pub fn main() { f(); g(); m::f(); m::g(); } diff --git a/tests/ui/imports/extern-crate-self/extern-crate-self-fail.rs b/tests/ui/imports/extern-crate-self/extern-crate-self-fail.rs new file mode 100644 index 000000000..1c0d3b4b9 --- /dev/null +++ b/tests/ui/imports/extern-crate-self/extern-crate-self-fail.rs @@ -0,0 +1,6 @@ +extern crate self; //~ ERROR `extern crate self;` requires renaming + +#[macro_use] //~ ERROR `#[macro_use]` is not supported on `extern crate self` +extern crate self as foo; + +fn main() {} diff --git a/tests/ui/imports/extern-crate-self/extern-crate-self-fail.stderr b/tests/ui/imports/extern-crate-self/extern-crate-self-fail.stderr new file mode 100644 index 000000000..127765727 --- /dev/null +++ b/tests/ui/imports/extern-crate-self/extern-crate-self-fail.stderr @@ -0,0 +1,19 @@ +error: `extern crate self;` requires renaming + --> $DIR/extern-crate-self-fail.rs:1:1 + | +LL | extern crate self; + | ^^^^^^^^^^^^^^^^^^ + | +help: rename the `self` crate to be able to import it + | +LL | extern crate self as name; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: `#[macro_use]` is not supported on `extern crate self` + --> $DIR/extern-crate-self-fail.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs b/tests/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs new file mode 100644 index 000000000..796835228 --- /dev/null +++ b/tests/ui/imports/extern-crate-self/extern-crate-self-macro-alias.rs @@ -0,0 +1,16 @@ +// run-pass + +// Test that a macro can correctly expand the alias +// in an `extern crate self as ALIAS` item. + +fn the_answer() -> usize { 42 } + +macro_rules! alias_self { + ($alias:ident) => { extern crate self as $alias; } +} + +alias_self!(the_alias); + +fn main() { + assert_eq!(the_alias::the_answer(), 42); +} diff --git a/tests/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs b/tests/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs new file mode 100644 index 000000000..244293be7 --- /dev/null +++ b/tests/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Test that `extern crate self;` is accepted +// syntactically as an item for use in a macro. + +macro_rules! accept_item { ($x:item) => {} } + +accept_item! { + extern crate self; +} + +fn main() {} diff --git a/tests/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs b/tests/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs new file mode 100644 index 000000000..009a92e87 --- /dev/null +++ b/tests/ui/imports/extern-crate-self/extern-crate-self-macro-self.rs @@ -0,0 +1,16 @@ +// run-pass + +// Test that a macro can correctly expand `self` in +// an `extern crate self as ALIAS` item. + +fn the_answer() -> usize { 42 } + +macro_rules! extern_something { + ($alias:ident) => { extern crate $alias as the_alias; } +} + +extern_something!(self); + +fn main() { + assert_eq!(the_alias::the_answer(), 42); +} diff --git a/tests/ui/imports/extern-crate-self/extern-crate-self-pass.rs b/tests/ui/imports/extern-crate-self/extern-crate-self-pass.rs new file mode 100644 index 000000000..9cebb622e --- /dev/null +++ b/tests/ui/imports/extern-crate-self/extern-crate-self-pass.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) + +extern crate self as foo; + +struct S; + +mod m { + fn check() { + foo::S; // OK + } +} + +fn main() {} diff --git a/tests/ui/imports/extern-crate-used.rs b/tests/ui/imports/extern-crate-used.rs new file mode 100644 index 000000000..8198c1816 --- /dev/null +++ b/tests/ui/imports/extern-crate-used.rs @@ -0,0 +1,32 @@ +// Extern crate items are marked as used if they are used +// through extern prelude entries introduced by them. + +// edition:2018 + +#![deny(unused_extern_crates)] + +// Shouldn't suggest changing to `use`, as new name +// would no longer be added to the prelude which could cause +// compilation errors for imports that use the new name in +// other modules. See #57672. +extern crate core as iso1; +extern crate core as iso2; +extern crate core as iso3; +extern crate core as iso4; + +// Doesn't introduce its extern prelude entry, so it's still considered unused. +extern crate core; //~ ERROR unused extern crate + +mod m { + use iso1::any as are_you_okay1; + use ::iso2::any as are_you_okay2; + type AreYouOkay1 = dyn iso3::any::Any; + type AreYouOkay2 = dyn (::iso4::any::Any); + + use core::any as are_you_okay3; + use ::core::any as are_you_okay4; + type AreYouOkay3 = dyn core::any::Any; + type AreYouOkay4 = dyn (::core::any::Any); +} + +fn main() {} diff --git a/tests/ui/imports/extern-crate-used.stderr b/tests/ui/imports/extern-crate-used.stderr new file mode 100644 index 000000000..1b9a2e472 --- /dev/null +++ b/tests/ui/imports/extern-crate-used.stderr @@ -0,0 +1,14 @@ +error: unused extern crate + --> $DIR/extern-crate-used.rs:18:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/extern-crate-used.rs:6:9 + | +LL | #![deny(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs b/tests/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs new file mode 100644 index 000000000..30d87f90b --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs @@ -0,0 +1,16 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +macro_rules! define_iso { () => { + extern crate std as iso; +}} + +::iso::thread_local! { + static S: u8 = 0; +} + +define_iso!(); + +fn main() { + let s = S; +} diff --git a/tests/ui/imports/extern-prelude-extern-crate-cfg.rs b/tests/ui/imports/extern-prelude-extern-crate-cfg.rs new file mode 100644 index 000000000..cfae08fcc --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-cfg.rs @@ -0,0 +1,16 @@ +// build-pass (FIXME(62277): could be check-pass?) +// compile-flags:--cfg my_feature + +#![no_std] + +#[cfg(my_feature)] +extern crate std; + +mod m { + #[cfg(my_feature)] + fn conditional() { + std::vec::Vec::::new(); // OK + } +} + +fn main() {} diff --git a/tests/ui/imports/extern-prelude-extern-crate-fail.rs b/tests/ui/imports/extern-prelude-extern-crate-fail.rs new file mode 100644 index 000000000..feb1ab09d --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-fail.rs @@ -0,0 +1,22 @@ +// aux-build:two_macros.rs +// compile-flags:--extern non_existent + +mod n { + extern crate two_macros; +} + +mod m { + fn check() { + two_macros::m!(); //~ ERROR failed to resolve: use of undeclared crate or module `two_macros` + } +} + +macro_rules! define_std_as_non_existent { + () => { + extern crate std as non_existent; + //~^ ERROR `extern crate` items cannot shadow names passed with `--extern` + } +} +define_std_as_non_existent!(); + +fn main() {} diff --git a/tests/ui/imports/extern-prelude-extern-crate-fail.stderr b/tests/ui/imports/extern-prelude-extern-crate-fail.stderr new file mode 100644 index 000000000..f7e37449e --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-fail.stderr @@ -0,0 +1,20 @@ +error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` + --> $DIR/extern-prelude-extern-crate-fail.rs:16:9 + | +LL | extern crate std as non_existent; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_std_as_non_existent!(); + | ----------------------------- in this macro invocation + | + = note: this error originates in the macro `define_std_as_non_existent` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0433]: failed to resolve: use of undeclared crate or module `two_macros` + --> $DIR/extern-prelude-extern-crate-fail.rs:10:9 + | +LL | two_macros::m!(); + | ^^^^^^^^^^ use of undeclared crate or module `two_macros` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/imports/extern-prelude-extern-crate-pass.rs b/tests/ui/imports/extern-prelude-extern-crate-pass.rs new file mode 100644 index 000000000..c87d58f63 --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-pass.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:two_macros.rs + +extern crate two_macros; + +mod m { + fn check() { + two_macros::m!(); // OK + } +} + +fn main() {} diff --git a/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs b/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs new file mode 100644 index 000000000..6ff3ab736 --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs @@ -0,0 +1,26 @@ +// aux-build:two_macros.rs + +macro_rules! define_vec { + () => { + extern crate std as Vec; + } +} + +define_vec!(); + +mod m { + fn check() { + Vec::panic!(); //~ ERROR `Vec` is ambiguous + } +} + +macro_rules! define_other_core { + () => { + extern crate std as core; + //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern` + } +} + +define_other_core!(); + +fn main() {} diff --git a/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr new file mode 100644 index 000000000..ade479ed1 --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr @@ -0,0 +1,33 @@ +error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:19:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `Vec` is ambiguous + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9 + | +LL | Vec::panic!(); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `Vec` could refer to the crate imported here + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:5:9 + | +LL | extern crate std as Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_vec!(); + | ------------- in this macro invocation +note: `Vec` could also refer to a struct from prelude + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + = note: this error originates in the macro `define_vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/extern-prelude-extern-crate-shadowing.rs b/tests/ui/imports/extern-prelude-extern-crate-shadowing.rs new file mode 100644 index 000000000..9e69a27d7 --- /dev/null +++ b/tests/ui/imports/extern-prelude-extern-crate-shadowing.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:two_macros.rs + +extern crate two_macros as core; + +mod m { + fn check() { + core::m!(); // OK + } +} + +fn main() {} diff --git a/tests/ui/imports/gensymed.rs b/tests/ui/imports/gensymed.rs new file mode 100644 index 000000000..7b53f0c53 --- /dev/null +++ b/tests/ui/imports/gensymed.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2018 +// aux-build:gensymed.rs + +extern crate gensymed; + +use gensymed::*; + +fn main() {} diff --git a/tests/ui/imports/glob-conflict-cross-crate.rs b/tests/ui/imports/glob-conflict-cross-crate.rs new file mode 100644 index 000000000..d84c243f2 --- /dev/null +++ b/tests/ui/imports/glob-conflict-cross-crate.rs @@ -0,0 +1,8 @@ +// aux-build:glob-conflict.rs + +extern crate glob_conflict; + +fn main() { + glob_conflict::f(); //~ ERROR cannot find function `f` in crate `glob_conflict` + glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob` +} diff --git a/tests/ui/imports/glob-conflict-cross-crate.stderr b/tests/ui/imports/glob-conflict-cross-crate.stderr new file mode 100644 index 000000000..0e3b4222f --- /dev/null +++ b/tests/ui/imports/glob-conflict-cross-crate.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find function `f` in crate `glob_conflict` + --> $DIR/glob-conflict-cross-crate.rs:6:20 + | +LL | glob_conflict::f(); + | ^ not found in `glob_conflict` + +error[E0425]: cannot find function `f` in module `glob_conflict::glob` + --> $DIR/glob-conflict-cross-crate.rs:7:26 + | +LL | glob_conflict::glob::f(); + | ^ not found in `glob_conflict::glob` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/glob-cycles.rs b/tests/ui/imports/glob-cycles.rs new file mode 100644 index 000000000..f354cc885 --- /dev/null +++ b/tests/ui/imports/glob-cycles.rs @@ -0,0 +1,18 @@ +// check-pass + +mod foo { + pub use bar::*; + pub use main as f; +} + +mod bar { + pub use foo::*; +} + +pub use foo::*; +pub use baz::*; +mod baz { + pub use super::*; +} + +pub fn main() {} diff --git a/tests/ui/imports/glob-resolve1.rs b/tests/ui/imports/glob-resolve1.rs new file mode 100644 index 000000000..904b77117 --- /dev/null +++ b/tests/ui/imports/glob-resolve1.rs @@ -0,0 +1,39 @@ +// Make sure that globs only bring in public things. + +use bar::*; + +mod bar { + use self::fpriv as import; + fn fpriv() {} + extern "C" { + fn epriv(); + } + enum A { + A1, + } + pub enum B { + B1, + } + + struct C; + + type D = isize; +} + +fn foo() {} + +fn main() { + fpriv(); //~ ERROR cannot find function `fpriv` in this scope + epriv(); //~ ERROR cannot find function `epriv` in this scope + B; //~ ERROR expected value, found enum `B` + C; //~ ERROR cannot find value `C` in this scope + import(); //~ ERROR: cannot find function `import` in this scope + + foo::(); //~ ERROR: cannot find type `A` in this scope + foo::(); //~ ERROR: cannot find type `C` in this scope + foo::(); //~ ERROR: cannot find type `D` in this scope +} + +mod other { + pub fn import() {} +} diff --git a/tests/ui/imports/glob-resolve1.stderr b/tests/ui/imports/glob-resolve1.stderr new file mode 100644 index 000000000..3b66a5e31 --- /dev/null +++ b/tests/ui/imports/glob-resolve1.stderr @@ -0,0 +1,114 @@ +error[E0425]: cannot find function `fpriv` in this scope + --> $DIR/glob-resolve1.rs:26:5 + | +LL | fpriv(); + | ^^^^^ not found in this scope + | +note: function `bar::fpriv` exists but is inaccessible + --> $DIR/glob-resolve1.rs:7:5 + | +LL | fn fpriv() {} + | ^^^^^^^^^^ not accessible + +error[E0425]: cannot find function `epriv` in this scope + --> $DIR/glob-resolve1.rs:27:5 + | +LL | epriv(); + | ^^^^^ not found in this scope + | +note: function `bar::epriv` exists but is inaccessible + --> $DIR/glob-resolve1.rs:9:9 + | +LL | fn epriv(); + | ^^^^^^^^^^^ not accessible + +error[E0423]: expected value, found enum `B` + --> $DIR/glob-resolve1.rs:28:5 + | +LL | B; + | ^ + | +note: the enum is defined here + --> $DIR/glob-resolve1.rs:14:5 + | +LL | / pub enum B { +LL | | B1, +LL | | } + | |_____^ +help: you might have meant to use the following enum variant + | +LL | B::B1; + | ~~~~~ + +error[E0425]: cannot find value `C` in this scope + --> $DIR/glob-resolve1.rs:29:5 + | +LL | C; + | ^ not found in this scope + | +note: unit struct `bar::C` exists but is inaccessible + --> $DIR/glob-resolve1.rs:18:5 + | +LL | struct C; + | ^^^^^^^^^ not accessible + +error[E0425]: cannot find function `import` in this scope + --> $DIR/glob-resolve1.rs:30:5 + | +LL | import(); + | ^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use other::import; + | + +error[E0412]: cannot find type `A` in this scope + --> $DIR/glob-resolve1.rs:32:11 + | +LL | pub enum B { + | ---------- similarly named enum `B` defined here +... +LL | foo::(); + | ^ help: an enum with a similar name exists: `B` + | +note: enum `bar::A` exists but is inaccessible + --> $DIR/glob-resolve1.rs:11:5 + | +LL | enum A { + | ^^^^^^ not accessible + +error[E0412]: cannot find type `C` in this scope + --> $DIR/glob-resolve1.rs:33:11 + | +LL | pub enum B { + | ---------- similarly named enum `B` defined here +... +LL | foo::(); + | ^ help: an enum with a similar name exists: `B` + | +note: struct `bar::C` exists but is inaccessible + --> $DIR/glob-resolve1.rs:18:5 + | +LL | struct C; + | ^^^^^^^^^ not accessible + +error[E0412]: cannot find type `D` in this scope + --> $DIR/glob-resolve1.rs:34:11 + | +LL | pub enum B { + | ---------- similarly named enum `B` defined here +... +LL | foo::(); + | ^ help: an enum with a similar name exists: `B` + | +note: type alias `bar::D` exists but is inaccessible + --> $DIR/glob-resolve1.rs:20:5 + | +LL | type D = isize; + | ^^^^^^^^^^^^^^^ not accessible + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0412, E0423, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/imports/glob-shadowing.rs b/tests/ui/imports/glob-shadowing.rs new file mode 100644 index 000000000..3a33b592b --- /dev/null +++ b/tests/ui/imports/glob-shadowing.rs @@ -0,0 +1,34 @@ +#![feature(decl_macro)] + +mod m { + pub macro env($e: expr) { $e } + pub macro fenv() { 0 } +} + +mod glob_in_normal_module { + use m::*; + fn check() { + let x = env!("PATH"); //~ ERROR `env` is ambiguous + } +} + +mod glob_in_block_module { + fn block() { + use m::*; + fn check() { + let x = env!("PATH"); //~ ERROR `env` is ambiguous + } + } +} + +mod glob_shadows_item { + pub macro fenv($e: expr) { $e } + fn block() { + use m::*; + fn check() { + let x = fenv!(); //~ ERROR `fenv` is ambiguous + } + } +} + +fn main() {} diff --git a/tests/ui/imports/glob-shadowing.stderr b/tests/ui/imports/glob-shadowing.stderr new file mode 100644 index 000000000..aff2eff68 --- /dev/null +++ b/tests/ui/imports/glob-shadowing.stderr @@ -0,0 +1,54 @@ +error[E0659]: `env` is ambiguous + --> $DIR/glob-shadowing.rs:11:17 + | +LL | let x = env!("PATH"); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution + = note: `env` could refer to a macro from prelude +note: `env` could also refer to the macro imported here + --> $DIR/glob-shadowing.rs:9:9 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `env` to disambiguate + = help: or use `self::env` to refer to this macro unambiguously + +error[E0659]: `env` is ambiguous + --> $DIR/glob-shadowing.rs:19:21 + | +LL | let x = env!("PATH"); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution + = note: `env` could refer to a macro from prelude +note: `env` could also refer to the macro imported here + --> $DIR/glob-shadowing.rs:17:13 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `env` to disambiguate + +error[E0659]: `fenv` is ambiguous + --> $DIR/glob-shadowing.rs:29:21 + | +LL | let x = fenv!(); + | ^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution +note: `fenv` could refer to the macro imported here + --> $DIR/glob-shadowing.rs:27:13 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `fenv` to disambiguate +note: `fenv` could also refer to the macro defined here + --> $DIR/glob-shadowing.rs:25:5 + | +LL | pub macro fenv($e: expr) { $e } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::fenv` to refer to this macro unambiguously + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/glob-use-std.rs b/tests/ui/imports/glob-use-std.rs new file mode 100644 index 000000000..ef06cc570 --- /dev/null +++ b/tests/ui/imports/glob-use-std.rs @@ -0,0 +1,11 @@ +// Issue #7580 + +// run-fail +// error-pattern:panic works +// ignore-emscripten no processes + +use std::*; + +fn main() { + panic!("panic works") +} diff --git a/tests/ui/imports/import-crate-var.rs b/tests/ui/imports/import-crate-var.rs new file mode 100644 index 000000000..aac5a15d3 --- /dev/null +++ b/tests/ui/imports/import-crate-var.rs @@ -0,0 +1,8 @@ +// aux-build:import_crate_var.rs + +#[macro_use] extern crate import_crate_var; + +fn main() { + m!(); + //~^ ERROR `$crate` may not be imported +} diff --git a/tests/ui/imports/import-crate-var.stderr b/tests/ui/imports/import-crate-var.stderr new file mode 100644 index 000000000..f1f1dfbdb --- /dev/null +++ b/tests/ui/imports/import-crate-var.stderr @@ -0,0 +1,10 @@ +error: `$crate` may not be imported + --> $DIR/import-crate-var.rs:6:5 + | +LL | m!(); + | ^^^^ + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans.rs b/tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans.rs new file mode 100644 index 000000000..b76c1680b --- /dev/null +++ b/tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans.rs @@ -0,0 +1,20 @@ +#![crate_type = "rlib"] +// no-prefer-dynamic + +// compile-flags: -g + +#[macro_use] +mod crate_with_invalid_spans_macros; + +pub fn exported_generic(x: T, y: u32) -> (T, u32) { + // Using the add1 macro will produce an invalid span, because the `y` passed + // to the macro will have a span from this file, but the rest of the code + // generated from the macro will have spans from the macro-defining file. + // The AST node for the (1 + y) expression generated by the macro will then + // take it's `lo` span bound from the `1` literal in the macro-defining file + // and it's `hi` bound from `y` in this file, which should be lower than the + // `lo` and even lower than the lower bound of the SourceFile it is supposedly + // contained in because the SourceFile for this file was allocated earlier than + // the SourceFile of the macro-defining file. + return (x, add1!(y)); +} diff --git a/tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans_macros.rs b/tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans_macros.rs new file mode 100644 index 000000000..63611c242 --- /dev/null +++ b/tests/ui/imports/import-crate-with-invalid-spans/auxiliary/crate_with_invalid_spans_macros.rs @@ -0,0 +1,7 @@ +macro_rules! add1 { + ($e:expr) => ({ + let a = 1 + $e; + let b = $e + 1; + a + b - 1 + }) +} diff --git a/tests/ui/imports/import-crate-with-invalid-spans/main.rs b/tests/ui/imports/import-crate-with-invalid-spans/main.rs new file mode 100644 index 000000000..64a4deca8 --- /dev/null +++ b/tests/ui/imports/import-crate-with-invalid-spans/main.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:crate_with_invalid_spans.rs + +// pretty-expanded FIXME #23616 + +extern crate crate_with_invalid_spans; + +fn main() { + // The AST of `exported_generic` stored in crate_with_invalid_spans's + // metadata should contain an invalid span where span.lo() > span.hi(). + // Let's make sure the compiler doesn't crash when encountering this. + let _ = crate_with_invalid_spans::exported_generic(32u32, 7u32); +} diff --git a/tests/ui/imports/import-from-missing.rs b/tests/ui/imports/import-from-missing.rs new file mode 100644 index 000000000..8eae70020 --- /dev/null +++ b/tests/ui/imports/import-from-missing.rs @@ -0,0 +1,12 @@ +use spam::{ham, eggs}; //~ ERROR unresolved import `spam::eggs` [E0432] + //~^ no `eggs` in `spam` + +mod spam { + pub fn ham() { } +} + +fn main() { + ham(); + // Expect eggs to pass because the compiler inserts a fake name for it + eggs(); +} diff --git a/tests/ui/imports/import-from-missing.stderr b/tests/ui/imports/import-from-missing.stderr new file mode 100644 index 000000000..4254bfb5e --- /dev/null +++ b/tests/ui/imports/import-from-missing.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `spam::eggs` + --> $DIR/import-from-missing.rs:1:17 + | +LL | use spam::{ham, eggs}; + | ^^^^ no `eggs` in `spam` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-from.rs b/tests/ui/imports/import-from.rs new file mode 100644 index 000000000..2817977b3 --- /dev/null +++ b/tests/ui/imports/import-from.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use spam::{ham, eggs}; + +mod spam { + pub fn ham() { } + pub fn eggs() { } +} + +pub fn main() { ham(); eggs(); } diff --git a/tests/ui/imports/import-glob-0-rpass.rs b/tests/ui/imports/import-glob-0-rpass.rs new file mode 100644 index 000000000..9c6a87279 --- /dev/null +++ b/tests/ui/imports/import-glob-0-rpass.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +use module_of_many_things::*; +use dug::too::greedily::and::too::deep::*; + +mod module_of_many_things { + pub fn f1() { println!("f1"); } + pub fn f2() { println!("f2"); } + fn f3() { println!("f3"); } + pub fn f4() { println!("f4"); } +} + +mod dug { + pub mod too { + pub mod greedily { + pub mod and { + pub mod too { + pub mod deep { + pub fn nameless_fear() { println!("Boo!"); } + pub fn also_redstone() { println!("Whatever."); } + } + } + } + } + } +} + + +pub fn main() { f1(); f2(); f4(); nameless_fear(); also_redstone(); } diff --git a/tests/ui/imports/import-glob-0.rs b/tests/ui/imports/import-glob-0.rs new file mode 100644 index 000000000..37a0d1545 --- /dev/null +++ b/tests/ui/imports/import-glob-0.rs @@ -0,0 +1,16 @@ +use module_of_many_things::*; + +mod module_of_many_things { + pub fn f1() { println!("f1"); } + pub fn f2() { println!("f2"); } + fn f3() { println!("f3"); } + pub fn f4() { println!("f4"); } +} + + +fn main() { + f1(); + f2(); + f999(); //~ ERROR cannot find function `f999` in this scope + f4(); +} diff --git a/tests/ui/imports/import-glob-0.stderr b/tests/ui/imports/import-glob-0.stderr new file mode 100644 index 000000000..820ff1bb5 --- /dev/null +++ b/tests/ui/imports/import-glob-0.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `f999` in this scope + --> $DIR/import-glob-0.rs:14:5 + | +LL | f999(); + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/import-glob-1.rs b/tests/ui/imports/import-glob-1.rs new file mode 100644 index 000000000..fcc0b63f1 --- /dev/null +++ b/tests/ui/imports/import-glob-1.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +// This should resolve fine. Prior to fix, the last import +// was being tried too early, and marked as unrsolved before +// the glob import had a chance to be resolved. + +mod bar { + pub use self::middle::*; + + mod middle { + pub use self::baz::Baz; + + mod baz { + pub enum Baz { + Baz1, + Baz2 + } + } + } +} + +mod foo { + use bar::Baz::{Baz1, Baz2}; +} + +fn main() {} diff --git a/tests/ui/imports/import-glob-circular.rs b/tests/ui/imports/import-glob-circular.rs new file mode 100644 index 000000000..e47fa870c --- /dev/null +++ b/tests/ui/imports/import-glob-circular.rs @@ -0,0 +1,19 @@ +mod circ1 { + pub use circ2::f2; + pub fn f1() { println!("f1"); } + pub fn common() -> usize { return 0; } +} + +mod circ2 { + pub use circ1::f1; + pub fn f2() { println!("f2"); } + pub fn common() -> usize { return 1; } +} + +mod test { + use circ1::*; + + fn test() { f1066(); } //~ ERROR cannot find function `f1066` in this scope +} + +fn main() {} diff --git a/tests/ui/imports/import-glob-circular.stderr b/tests/ui/imports/import-glob-circular.stderr new file mode 100644 index 000000000..86bbea579 --- /dev/null +++ b/tests/ui/imports/import-glob-circular.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `f1066` in this scope + --> $DIR/import-glob-circular.rs:16:17 + | +LL | fn test() { f1066(); } + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/import-glob-crate.rs b/tests/ui/imports/import-glob-crate.rs new file mode 100644 index 000000000..501392b78 --- /dev/null +++ b/tests/ui/imports/import-glob-crate.rs @@ -0,0 +1,19 @@ +// run-pass +use std::mem::*; + +pub fn main() { + assert_eq!(size_of::(), 1); + let (mut x, mut y) = (1, 2); + swap(&mut x, &mut y); + assert_eq!(x, 2); + assert_eq!(y, 1); +} + +#[allow(unused)] +fn f() { + mod foo { pub use *; } + mod bar { pub use ::*; } + + foo::main(); + bar::main(); +} diff --git a/tests/ui/imports/import-in-block.rs b/tests/ui/imports/import-in-block.rs new file mode 100644 index 000000000..19703904e --- /dev/null +++ b/tests/ui/imports/import-in-block.rs @@ -0,0 +1,13 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + use std::mem::replace; + let mut x = 5; + let _ = replace(&mut x, 6); + { + use std::mem::*; + let mut y = 6; + swap(&mut x, &mut y); + } +} diff --git a/tests/ui/imports/import-loop-2.rs b/tests/ui/imports/import-loop-2.rs new file mode 100644 index 000000000..14a85dd08 --- /dev/null +++ b/tests/ui/imports/import-loop-2.rs @@ -0,0 +1,13 @@ +// error-pattern:import + +mod a { + pub use b::x; +} + +mod b { + pub use a::x; + + fn main() { let y = x; } +} + +fn main() {} diff --git a/tests/ui/imports/import-loop-2.stderr b/tests/ui/imports/import-loop-2.stderr new file mode 100644 index 000000000..1abfcde03 --- /dev/null +++ b/tests/ui/imports/import-loop-2.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `a::x` + --> $DIR/import-loop-2.rs:8:13 + | +LL | pub use a::x; + | ^^^^ no `x` in `a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-loop.rs b/tests/ui/imports/import-loop.rs new file mode 100644 index 000000000..b48783401 --- /dev/null +++ b/tests/ui/imports/import-loop.rs @@ -0,0 +1,9 @@ +// error-pattern:import + +use y::x; + +mod y { + pub use y::x; +} + +fn main() { } diff --git a/tests/ui/imports/import-loop.stderr b/tests/ui/imports/import-loop.stderr new file mode 100644 index 000000000..b87bfb1be --- /dev/null +++ b/tests/ui/imports/import-loop.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `y::x` + --> $DIR/import-loop.rs:6:13 + | +LL | pub use y::x; + | ^^^^ no `x` in `y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-prefix-macro-1.rs b/tests/ui/imports/import-prefix-macro-1.rs new file mode 100644 index 000000000..91cfd3768 --- /dev/null +++ b/tests/ui/imports/import-prefix-macro-1.rs @@ -0,0 +1,16 @@ +mod a { + pub mod b { + pub mod c { + pub struct S; + pub struct Z; + } + } +} + +macro_rules! import { + ($p: path) => (use $p {S, Z}); //~ERROR expected one of `::`, `;`, or `as`, found `{` +} + +import! { a::b::c } + +fn main() {} diff --git a/tests/ui/imports/import-prefix-macro-1.stderr b/tests/ui/imports/import-prefix-macro-1.stderr new file mode 100644 index 000000000..8868ee3ae --- /dev/null +++ b/tests/ui/imports/import-prefix-macro-1.stderr @@ -0,0 +1,13 @@ +error: expected one of `::`, `;`, or `as`, found `{` + --> $DIR/import-prefix-macro-1.rs:11:27 + | +LL | ($p: path) => (use $p {S, Z}); + | ^^^^^^ expected one of `::`, `;`, or `as` +... +LL | import! { a::b::c } + | ------------------- in this macro invocation + | + = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/imports/import-prefix-macro-2.rs b/tests/ui/imports/import-prefix-macro-2.rs new file mode 100644 index 000000000..952d161e8 --- /dev/null +++ b/tests/ui/imports/import-prefix-macro-2.rs @@ -0,0 +1,16 @@ +mod a { + pub mod b { + pub mod c { + pub struct S; + pub struct Z; + } + } +} + +macro_rules! import { + ($p: path) => (use ::$p {S, Z}); //~ERROR expected identifier, found `a::b::c` +} + +import! { a::b::c } + +fn main() {} diff --git a/tests/ui/imports/import-prefix-macro-2.stderr b/tests/ui/imports/import-prefix-macro-2.stderr new file mode 100644 index 000000000..23f8d5764 --- /dev/null +++ b/tests/ui/imports/import-prefix-macro-2.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found `a::b::c` + --> $DIR/import-prefix-macro-2.rs:11:26 + | +LL | ($p: path) => (use ::$p {S, Z}); + | ^^ expected identifier +... +LL | import! { a::b::c } + | ------------------- in this macro invocation + | + = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/imports/import-prefix-macro.rs b/tests/ui/imports/import-prefix-macro.rs new file mode 100644 index 000000000..d770bb0da --- /dev/null +++ b/tests/ui/imports/import-prefix-macro.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(unused_variables)] +mod a { + pub mod b { + pub mod c { + pub struct S; + pub struct Z; + } + pub struct W; + } +} + +macro_rules! import { + (1 $p: path) => (use $p;); + (2 $p: path) => (use $p::{Z};); + (3 $p: path) => (use $p::*;); +} + +import! { 1 a::b::c::S } +import! { 2 a::b::c } +import! { 3 a::b } + +fn main() { + let s = S; + let z = Z; + let w = W; +} diff --git a/tests/ui/imports/import-rename.rs b/tests/ui/imports/import-rename.rs new file mode 100644 index 000000000..9ad2b34b8 --- /dev/null +++ b/tests/ui/imports/import-rename.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(unused_variables)] +use foo::{x, y as fooy}; +use Maybe::{Yes as MaybeYes}; + +pub enum Maybe { Yes, No } +mod foo { + use super::Maybe::{self as MaybeFoo}; + pub fn x(a: MaybeFoo) {} + pub fn y(a: i32) { println!("{}", a); } +} + +pub fn main() { x(MaybeYes); fooy(10); } diff --git a/tests/ui/imports/import-rpass.rs b/tests/ui/imports/import-rpass.rs new file mode 100644 index 000000000..de8bf6261 --- /dev/null +++ b/tests/ui/imports/import-rpass.rs @@ -0,0 +1,12 @@ +// run-pass +mod foo { + pub fn x(y: isize) { println!("{}", y); } +} + +mod bar { + use foo::x; + use foo::x as z; + pub fn thing() { x(10); z(10); } +} + +pub fn main() { bar::thing(); } diff --git a/tests/ui/imports/import-trailing-comma.rs b/tests/ui/imports/import-trailing-comma.rs new file mode 100644 index 000000000..f65c5c866 --- /dev/null +++ b/tests/ui/imports/import-trailing-comma.rs @@ -0,0 +1,13 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use foo::bar::{baz, quux,}; + +mod foo { + pub mod bar { + pub fn baz() { } + pub fn quux() { } + } +} + +pub fn main() { baz(); quux(); } diff --git a/tests/ui/imports/import-trait-method.rs b/tests/ui/imports/import-trait-method.rs new file mode 100644 index 000000000..97dd68f1e --- /dev/null +++ b/tests/ui/imports/import-trait-method.rs @@ -0,0 +1,7 @@ +trait Foo { + fn foo(); +} + +use Foo::foo; //~ ERROR not directly importable + +fn main() { foo(); } diff --git a/tests/ui/imports/import-trait-method.stderr b/tests/ui/imports/import-trait-method.stderr new file mode 100644 index 000000000..3c26907d3 --- /dev/null +++ b/tests/ui/imports/import-trait-method.stderr @@ -0,0 +1,9 @@ +error[E0253]: `foo` is not directly importable + --> $DIR/import-trait-method.rs:5:5 + | +LL | use Foo::foo; + | ^^^^^^^^ cannot be imported directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0253`. diff --git a/tests/ui/imports/import.rs b/tests/ui/imports/import.rs new file mode 100644 index 000000000..3170dd2fa --- /dev/null +++ b/tests/ui/imports/import.rs @@ -0,0 +1,17 @@ +use zed::bar; +use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432] + //~| no `baz` in `zed` + //~| HELP a similar name exists in the module + //~| SUGGESTION bar + + +mod zed { + pub fn bar() { println!("bar"); } + use foo; //~ ERROR unresolved import `foo` [E0432] + //~^ no `foo` in the root +} + +fn main() { + zed::foo(); //~ ERROR `foo` is private + bar(); +} diff --git a/tests/ui/imports/import.stderr b/tests/ui/imports/import.stderr new file mode 100644 index 000000000..797712e2d --- /dev/null +++ b/tests/ui/imports/import.stderr @@ -0,0 +1,31 @@ +error[E0432]: unresolved import `zed::baz` + --> $DIR/import.rs:2:5 + | +LL | use zed::baz; + | ^^^^^--- + | | | + | | help: a similar name exists in the module: `bar` + | no `baz` in `zed` + +error[E0432]: unresolved import `foo` + --> $DIR/import.rs:10:9 + | +LL | use foo; + | ^^^ no `foo` in the root + +error[E0603]: unresolved item import `foo` is private + --> $DIR/import.rs:15:10 + | +LL | zed::foo(); + | ^^^ private unresolved item import + | +note: the unresolved item import `foo` is defined here + --> $DIR/import.rs:10:9 + | +LL | use foo; + | ^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0432, E0603. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import2-rpass.rs b/tests/ui/imports/import2-rpass.rs new file mode 100644 index 000000000..7b70f799e --- /dev/null +++ b/tests/ui/imports/import2-rpass.rs @@ -0,0 +1,9 @@ +// run-pass + +use zed::bar; + +mod zed { + pub fn bar() { println!("bar"); } +} + +pub fn main() { bar(); } diff --git a/tests/ui/imports/import2.rs b/tests/ui/imports/import2.rs new file mode 100644 index 000000000..036d6bc07 --- /dev/null +++ b/tests/ui/imports/import2.rs @@ -0,0 +1,10 @@ +use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432] + //~^ could not find `zed` in `baz` + +mod baz {} +mod zed { + pub fn bar() { println!("bar3"); } +} +fn main() { + bar(); +} diff --git a/tests/ui/imports/import2.stderr b/tests/ui/imports/import2.stderr new file mode 100644 index 000000000..da888979c --- /dev/null +++ b/tests/ui/imports/import2.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `baz::zed` + --> $DIR/import2.rs:1:10 + | +LL | use baz::zed::bar; + | ^^^ could not find `zed` in `baz` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import3-rpass.rs b/tests/ui/imports/import3-rpass.rs new file mode 100644 index 000000000..17797aed3 --- /dev/null +++ b/tests/ui/imports/import3-rpass.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(unused_imports)] + +use baz::zed; +use baz::zed::bar; + +mod baz { + pub mod zed { + pub fn bar() { println!("bar2"); } + } +} + +pub fn main() { bar(); } diff --git a/tests/ui/imports/import3.rs b/tests/ui/imports/import3.rs new file mode 100644 index 000000000..2c6ac9a00 --- /dev/null +++ b/tests/ui/imports/import3.rs @@ -0,0 +1,4 @@ +// error-pattern: unresolved +use main::bar; + +fn main() { println!("foo"); } diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr new file mode 100644 index 000000000..ca75c9c18 --- /dev/null +++ b/tests/ui/imports/import3.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `main` + --> $DIR/import3.rs:2:5 + | +LL | use main::bar; + | ^^^^ maybe a missing crate `main`? + | + = help: consider adding `extern crate main` to use the `main` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import4-rpass.rs b/tests/ui/imports/import4-rpass.rs new file mode 100644 index 000000000..4fda53861 --- /dev/null +++ b/tests/ui/imports/import4-rpass.rs @@ -0,0 +1,9 @@ +// run-pass + +use zed::bar; + +mod zed { + pub fn bar() { println!("bar"); } +} + +pub fn main() { let _zed = 42; bar(); } diff --git a/tests/ui/imports/import4.rs b/tests/ui/imports/import4.rs new file mode 100644 index 000000000..ba3b7fbf5 --- /dev/null +++ b/tests/ui/imports/import4.rs @@ -0,0 +1,7 @@ +// error-pattern: import + + +mod a { pub use b::foo; } +mod b { pub use a::foo; } + +fn main() { println!("loop"); } diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr new file mode 100644 index 000000000..e0b478f1a --- /dev/null +++ b/tests/ui/imports/import4.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `a::foo` + --> $DIR/import4.rs:5:17 + | +LL | mod b { pub use a::foo; } + | ^^^^^^ no `foo` in `a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import5.rs b/tests/ui/imports/import5.rs new file mode 100644 index 000000000..be2a55c2d --- /dev/null +++ b/tests/ui/imports/import5.rs @@ -0,0 +1,10 @@ +// run-pass +use foo::bar; +mod foo { + pub use foo::zed::bar; + pub mod zed { + pub fn bar() { println!("foo"); } + } +} + +pub fn main() { bar(); } diff --git a/tests/ui/imports/import6.rs b/tests/ui/imports/import6.rs new file mode 100644 index 000000000..e11b28531 --- /dev/null +++ b/tests/ui/imports/import6.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_imports)] + +use foo::zed; +use bar::baz; + +mod foo { + pub mod zed { + pub fn baz() { println!("baz"); } + } +} +mod bar { + pub use foo::zed::baz; +} +pub fn main() { baz(); } diff --git a/tests/ui/imports/import7.rs b/tests/ui/imports/import7.rs new file mode 100644 index 000000000..aca7fbdc4 --- /dev/null +++ b/tests/ui/imports/import7.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_imports)] + +use foo::zed; +use bar::baz; + +mod foo { + pub mod zed { + pub fn baz() { println!("baz"); } + } +} +mod bar { + pub use foo::zed::baz; + pub mod foo { + pub mod zed {} + } +} +pub fn main() { baz(); } diff --git a/tests/ui/imports/import8.rs b/tests/ui/imports/import8.rs new file mode 100644 index 000000000..87f0986ba --- /dev/null +++ b/tests/ui/imports/import8.rs @@ -0,0 +1,10 @@ +// run-pass + +use foo::x; +use foo::x as z; + +mod foo { + pub fn x(y: isize) { println!("{}", y); } +} + +pub fn main() { x(10); z(10); } diff --git a/tests/ui/imports/imports.rs b/tests/ui/imports/imports.rs new file mode 100644 index 000000000..acb2b32b5 --- /dev/null +++ b/tests/ui/imports/imports.rs @@ -0,0 +1,66 @@ +// run-pass +#![allow(unused)] + +// Like other items, private imports can be imported and used non-lexically in paths. +mod a { + use a as foo; + use self::foo::foo as bar; + + mod b { + use super::bar; + } +} + +mod foo { pub fn f() {} } +mod bar { pub fn f() {} } + +pub fn f() -> bool { true } + +// Items and explicit imports shadow globs. +fn g() { + use foo::*; + use bar::*; + fn f() -> bool { true } + let _: bool = f(); +} + +fn h() { + use foo::*; + use bar::*; + use f; + let _: bool = f(); +} + +// Here, there appears to be shadowing but isn't because of namespaces. +mod b { + use foo::*; // This imports `f` in the value namespace. + use super::b as f; // This imports `f` only in the type namespace, + fn test() { self::f(); } // so the glob isn't shadowed. +} + +// Here, there is shadowing in one namespace, but not the other. +mod c { + mod test { + pub fn f() {} + pub mod f {} + } + use self::test::*; // This glob-imports `f` in both namespaces. + mod f { pub fn f() {} } // This shadows the glob only in the value namespace. + + fn test() { + self::f(); // Check that the glob-imported value isn't shadowed. + self::f::f(); // Check that the glob-imported module is shadowed. + } +} + +// Unused names can be ambiguous. +mod d { + pub use foo::*; // This imports `f` in the value namespace. + pub use bar::*; // This also imports `f` in the value namespace. +} + +mod e { + pub use d::*; // n.b. Since `e::f` is not used, this is not considered to be a use of `d::f`. +} + +fn main() {} diff --git a/tests/ui/imports/inaccessible_type_aliases.rs b/tests/ui/imports/inaccessible_type_aliases.rs new file mode 100644 index 000000000..c3d4214e2 --- /dev/null +++ b/tests/ui/imports/inaccessible_type_aliases.rs @@ -0,0 +1,14 @@ +mod a { + type Foo = u64; + type Bar = u64; +} + +mod b { + type Foo = u64; +} + +fn main() { + let x: Foo = 100; //~ ERROR: cannot find type `Foo` in this scope + let y: Bar = 100; //~ ERROR: cannot find type `Bar` in this scope + println!("x: {}, y: {}", x, y); +} diff --git a/tests/ui/imports/inaccessible_type_aliases.stderr b/tests/ui/imports/inaccessible_type_aliases.stderr new file mode 100644 index 000000000..ef2242460 --- /dev/null +++ b/tests/ui/imports/inaccessible_type_aliases.stderr @@ -0,0 +1,30 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/inaccessible_type_aliases.rs:11:12 + | +LL | let x: Foo = 100; + | ^^^ not found in this scope + | +note: these type aliases exist but are inaccessible + --> $DIR/inaccessible_type_aliases.rs:2:5 + | +LL | type Foo = u64; + | ^^^^^^^^^^^^^^^ `a::Foo`: not accessible +... +LL | type Foo = u64; + | ^^^^^^^^^^^^^^^ `b::Foo`: not accessible + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/inaccessible_type_aliases.rs:12:12 + | +LL | let y: Bar = 100; + | ^^^ not found in this scope + | +note: type alias `a::Bar` exists but is inaccessible + --> $DIR/inaccessible_type_aliases.rs:3:5 + | +LL | type Bar = u64; + | ^^^^^^^^^^^^^^^ not accessible + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/imports/issue-13404.rs b/tests/ui/imports/issue-13404.rs new file mode 100644 index 000000000..c5af827d5 --- /dev/null +++ b/tests/ui/imports/issue-13404.rs @@ -0,0 +1,10 @@ +use a::f; +use b::f; //~ ERROR: unresolved import `b::f` [E0432] + //~^ no `f` in `b` + +mod a { pub fn f() {} } +mod b { } + +fn main() { + f(); +} diff --git a/tests/ui/imports/issue-13404.stderr b/tests/ui/imports/issue-13404.stderr new file mode 100644 index 000000000..1f50debb0 --- /dev/null +++ b/tests/ui/imports/issue-13404.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `b::f` + --> $DIR/issue-13404.rs:2:5 + | +LL | use b::f; + | ^^^^ no `f` in `b` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-1697.rs b/tests/ui/imports/issue-1697.rs new file mode 100644 index 000000000..5cd76d21f --- /dev/null +++ b/tests/ui/imports/issue-1697.rs @@ -0,0 +1,6 @@ +// Testing that we don't fail abnormally after hitting the errors + +use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432] + //~^ maybe a missing crate `unresolved`? + +fn main() {} diff --git a/tests/ui/imports/issue-1697.stderr b/tests/ui/imports/issue-1697.stderr new file mode 100644 index 000000000..019ef9ad5 --- /dev/null +++ b/tests/ui/imports/issue-1697.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `unresolved` + --> $DIR/issue-1697.rs:3:5 + | +LL | use unresolved::*; + | ^^^^^^^^^^ maybe a missing crate `unresolved`? + | + = help: consider adding `extern crate unresolved` to use the `unresolved` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-18083.rs b/tests/ui/imports/issue-18083.rs new file mode 100644 index 000000000..36420ec14 --- /dev/null +++ b/tests/ui/imports/issue-18083.rs @@ -0,0 +1,25 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_imports)] +// These crossed imports should resolve fine, and not block on +// each other and be reported as unresolved. + +mod a { + use b::{B}; + pub use self::inner::A; + + mod inner { + pub struct A; + } +} + +mod b { + use a::{A}; + pub use self::inner::B; + + mod inner { + pub struct B; + } +} + +fn main() {} diff --git a/tests/ui/imports/issue-19498.rs b/tests/ui/imports/issue-19498.rs new file mode 100644 index 000000000..5fe6742f5 --- /dev/null +++ b/tests/ui/imports/issue-19498.rs @@ -0,0 +1,13 @@ +use self::A; +use self::B; +mod A {} //~ ERROR the name `A` is defined multiple times +//~| `A` redefined here +pub mod B {} //~ ERROR the name `B` is defined multiple times +//~| `B` redefined here +mod C { + use C::D; + mod D {} //~ ERROR the name `D` is defined multiple times + //~| `D` redefined here +} + +fn main() {} diff --git a/tests/ui/imports/issue-19498.stderr b/tests/ui/imports/issue-19498.stderr new file mode 100644 index 000000000..9d2602209 --- /dev/null +++ b/tests/ui/imports/issue-19498.stderr @@ -0,0 +1,47 @@ +error[E0255]: the name `A` is defined multiple times + --> $DIR/issue-19498.rs:3:1 + | +LL | use self::A; + | ------- previous import of the module `A` here +LL | use self::B; +LL | mod A {} + | ^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use self::A as OtherA; + | ~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `B` is defined multiple times + --> $DIR/issue-19498.rs:5:1 + | +LL | use self::B; + | ------- previous import of the module `B` here +... +LL | pub mod B {} + | ^^^^^^^^^ `B` redefined here + | + = note: `B` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use self::B as OtherB; + | ~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `D` is defined multiple times + --> $DIR/issue-19498.rs:9:5 + | +LL | use C::D; + | ---- previous import of the module `D` here +LL | mod D {} + | ^^^^^ `D` redefined here + | + = note: `D` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use C::D as OtherD; + | ~~~~~~~~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/imports/issue-24081.rs b/tests/ui/imports/issue-24081.rs new file mode 100644 index 000000000..10983ce11 --- /dev/null +++ b/tests/ui/imports/issue-24081.rs @@ -0,0 +1,18 @@ +use std::ops::Add; +use std::ops::Sub; +use std::ops::Mul; +use std::ops::Div; +use std::ops::Rem; + +type Add = bool; //~ ERROR the name `Add` is defined multiple times +//~| `Add` redefined here +struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times +//~| `Sub` redefined here +enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times +//~| `Mul` redefined here +mod Div { } //~ ERROR the name `Div` is defined multiple times +//~| `Div` redefined here +trait Rem { } //~ ERROR the name `Rem` is defined multiple times +//~| `Rem` redefined here + +fn main() {} diff --git a/tests/ui/imports/issue-24081.stderr b/tests/ui/imports/issue-24081.stderr new file mode 100644 index 000000000..e5ed6b10a --- /dev/null +++ b/tests/ui/imports/issue-24081.stderr @@ -0,0 +1,78 @@ +error[E0255]: the name `Add` is defined multiple times + --> $DIR/issue-24081.rs:7:1 + | +LL | use std::ops::Add; + | ------------- previous import of the trait `Add` here +... +LL | type Add = bool; + | ^^^^^^^^^^^^^^^^ `Add` redefined here + | + = note: `Add` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Add as OtherAdd; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Sub` is defined multiple times + --> $DIR/issue-24081.rs:9:1 + | +LL | use std::ops::Sub; + | ------------- previous import of the trait `Sub` here +... +LL | struct Sub { x: f32 } + | ^^^^^^^^^^ `Sub` redefined here + | + = note: `Sub` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Sub as OtherSub; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Mul` is defined multiple times + --> $DIR/issue-24081.rs:11:1 + | +LL | use std::ops::Mul; + | ------------- previous import of the trait `Mul` here +... +LL | enum Mul { A, B } + | ^^^^^^^^ `Mul` redefined here + | + = note: `Mul` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Mul as OtherMul; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Div` is defined multiple times + --> $DIR/issue-24081.rs:13:1 + | +LL | use std::ops::Div; + | ------------- previous import of the trait `Div` here +... +LL | mod Div { } + | ^^^^^^^ `Div` redefined here + | + = note: `Div` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Div as OtherDiv; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Rem` is defined multiple times + --> $DIR/issue-24081.rs:15:1 + | +LL | use std::ops::Rem; + | ------------- previous import of the trait `Rem` here +... +LL | trait Rem { } + | ^^^^^^^^^ `Rem` redefined here + | + = note: `Rem` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::ops::Rem as OtherRem; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/imports/issue-24883.rs b/tests/ui/imports/issue-24883.rs new file mode 100644 index 000000000..819a20ddb --- /dev/null +++ b/tests/ui/imports/issue-24883.rs @@ -0,0 +1,17 @@ +// check-pass + +mod a { + pub mod b { pub struct Foo; } + + pub mod c { + use super::b; + pub struct Bar(pub b::Foo); + } + + pub use self::c::*; +} + +fn main() { + let _ = a::c::Bar(a::b::Foo); + let _ = a::Bar(a::b::Foo); +} diff --git a/tests/ui/imports/issue-25396.rs b/tests/ui/imports/issue-25396.rs new file mode 100644 index 000000000..301658d23 --- /dev/null +++ b/tests/ui/imports/issue-25396.rs @@ -0,0 +1,29 @@ +#![allow(non_camel_case_types)] + +use foo::baz; +use bar::baz; //~ ERROR the name `baz` is defined multiple times + +use foo::Quux; +use bar::Quux; //~ ERROR the name `Quux` is defined multiple times + +use foo::blah; +use bar::blah; //~ ERROR the name `blah` is defined multiple times + +use foo::WOMP; +use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times + +fn main() {} + +mod foo { + pub mod baz {} + pub trait Quux { } + pub type blah = (f64, u32); + pub const WOMP: u8 = 5; +} + +mod bar { + pub mod baz {} + pub type Quux = i32; + pub struct blah { x: i8 } + pub const WOMP: i8 = -5; +} diff --git a/tests/ui/imports/issue-25396.stderr b/tests/ui/imports/issue-25396.stderr new file mode 100644 index 000000000..518d2be78 --- /dev/null +++ b/tests/ui/imports/issue-25396.stderr @@ -0,0 +1,59 @@ +error[E0252]: the name `baz` is defined multiple times + --> $DIR/issue-25396.rs:4:5 + | +LL | use foo::baz; + | -------- previous import of the module `baz` here +LL | use bar::baz; + | ^^^^^^^^ `baz` reimported here + | + = note: `baz` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::baz as other_baz; + | ~~~~~~~~~~~~~~~~~~~~~ + +error[E0252]: the name `Quux` is defined multiple times + --> $DIR/issue-25396.rs:7:5 + | +LL | use foo::Quux; + | --------- previous import of the trait `Quux` here +LL | use bar::Quux; + | ^^^^^^^^^ `Quux` reimported here + | + = note: `Quux` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::Quux as OtherQuux; + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0252]: the name `blah` is defined multiple times + --> $DIR/issue-25396.rs:10:5 + | +LL | use foo::blah; + | --------- previous import of the type `blah` here +LL | use bar::blah; + | ^^^^^^^^^ `blah` reimported here + | + = note: `blah` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::blah as other_blah; + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0252]: the name `WOMP` is defined multiple times + --> $DIR/issue-25396.rs:13:5 + | +LL | use foo::WOMP; + | --------- previous import of the value `WOMP` here +LL | use bar::WOMP; + | ^^^^^^^^^ `WOMP` reimported here + | + = note: `WOMP` must be defined only once in the value namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use bar::WOMP as OtherWOMP; + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-26873-multifile/A/B.rs b/tests/ui/imports/issue-26873-multifile/A/B.rs new file mode 100644 index 000000000..ab7b0d816 --- /dev/null +++ b/tests/ui/imports/issue-26873-multifile/A/B.rs @@ -0,0 +1,4 @@ +// run-pass +use super::*; + +pub struct S; diff --git a/tests/ui/imports/issue-26873-multifile/A/C.rs b/tests/ui/imports/issue-26873-multifile/A/C.rs new file mode 100644 index 000000000..b287283df --- /dev/null +++ b/tests/ui/imports/issue-26873-multifile/A/C.rs @@ -0,0 +1,6 @@ +// run-pass +use super::*; + +use super::B::S; + +pub struct T { i: i32 } diff --git a/tests/ui/imports/issue-26873-multifile/A/mod.rs b/tests/ui/imports/issue-26873-multifile/A/mod.rs new file mode 100644 index 000000000..0f18772bf --- /dev/null +++ b/tests/ui/imports/issue-26873-multifile/A/mod.rs @@ -0,0 +1,5 @@ +// run-pass +pub mod B; +pub mod C; + +pub use self::C::T; diff --git a/tests/ui/imports/issue-26873-multifile/compiletest-ignore-dir b/tests/ui/imports/issue-26873-multifile/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs b/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs new file mode 100644 index 000000000..da2acf6c9 --- /dev/null +++ b/tests/ui/imports/issue-26873-multifile/issue-26873-multifile.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] + +// ignore-pretty issue #37195 + +#[path = "issue-26873-multifile/mod.rs"] +mod multifile; + +fn main() {} diff --git a/tests/ui/imports/issue-26873-multifile/issue-26873-onefile.rs b/tests/ui/imports/issue-26873-multifile/issue-26873-onefile.rs new file mode 100644 index 000000000..f06c6499e --- /dev/null +++ b/tests/ui/imports/issue-26873-multifile/issue-26873-onefile.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(non_snake_case)] + +mod A { + pub mod B { + use super::*; + + pub struct S; + } + + pub mod C { + use super::*; + use super::B::S; + + pub struct T; + } + + pub use self::C::T; +} + +use A::*; + +fn main() {} diff --git a/tests/ui/imports/issue-26873-multifile/mod.rs b/tests/ui/imports/issue-26873-multifile/mod.rs new file mode 100644 index 000000000..a1ba53f91 --- /dev/null +++ b/tests/ui/imports/issue-26873-multifile/mod.rs @@ -0,0 +1,4 @@ +// run-pass +mod A; + +use self::A::*; diff --git a/tests/ui/imports/issue-26886.rs b/tests/ui/imports/issue-26886.rs new file mode 100644 index 000000000..6e6d406c6 --- /dev/null +++ b/tests/ui/imports/issue-26886.rs @@ -0,0 +1,8 @@ +use std::sync::{self, Arc}; +use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times + //~| `Arc` must be defined only once in the type namespace of this module +use std::sync; //~ ERROR the name `sync` is defined multiple times + //~| `sync` must be defined only once in the type namespace of this module + +fn main() { +} diff --git a/tests/ui/imports/issue-26886.stderr b/tests/ui/imports/issue-26886.stderr new file mode 100644 index 000000000..e2b925ec5 --- /dev/null +++ b/tests/ui/imports/issue-26886.stderr @@ -0,0 +1,24 @@ +error[E0252]: the name `Arc` is defined multiple times + --> $DIR/issue-26886.rs:2:5 + | +LL | use std::sync::{self, Arc}; + | --- previous import of the type `Arc` here +LL | use std::sync::Arc; + | ^^^^^^^^^^^^^^ `Arc` reimported here + | + = note: `Arc` must be defined only once in the type namespace of this module + +error[E0252]: the name `sync` is defined multiple times + --> $DIR/issue-26886.rs:4:5 + | +LL | use std::sync::{self, Arc}; + | ---- previous import of the module `sync` here +... +LL | use std::sync; + | ^^^^^^^^^ `sync` reimported here + | + = note: `sync` must be defined only once in the type namespace of this module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-26930.rs b/tests/ui/imports/issue-26930.rs new file mode 100644 index 000000000..707e71b11 --- /dev/null +++ b/tests/ui/imports/issue-26930.rs @@ -0,0 +1,8 @@ +// check-pass + +extern crate core; +use core as core_export; +use self::x::*; +mod x {} + +fn main() {} diff --git a/tests/ui/imports/issue-28134.rs b/tests/ui/imports/issue-28134.rs new file mode 100644 index 000000000..ef2a5d634 --- /dev/null +++ b/tests/ui/imports/issue-28134.rs @@ -0,0 +1,5 @@ +// compile-flags: --test + +#![allow(soft_unstable)] +#![test] //~ ERROR cannot determine resolution for the attribute macro `test` +//~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level diff --git a/tests/ui/imports/issue-28134.stderr b/tests/ui/imports/issue-28134.stderr new file mode 100644 index 000000000..33cb53f20 --- /dev/null +++ b/tests/ui/imports/issue-28134.stderr @@ -0,0 +1,21 @@ +error: cannot determine resolution for the attribute macro `test` + --> $DIR/issue-28134.rs:4:4 + | +LL | #![test] + | ^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: `test` attribute cannot be used at crate level + --> $DIR/issue-28134.rs:4:1 + | +LL | #![test] + | ^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[test] + | ~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/imports/issue-28388-1.rs b/tests/ui/imports/issue-28388-1.rs new file mode 100644 index 000000000..14de62140 --- /dev/null +++ b/tests/ui/imports/issue-28388-1.rs @@ -0,0 +1,5 @@ +// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. + +use foo::{}; //~ ERROR unresolved import `foo` + +fn main() {} diff --git a/tests/ui/imports/issue-28388-1.stderr b/tests/ui/imports/issue-28388-1.stderr new file mode 100644 index 000000000..7f5e47aa8 --- /dev/null +++ b/tests/ui/imports/issue-28388-1.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `foo` + --> $DIR/issue-28388-1.rs:3:5 + | +LL | use foo::{}; + | ^^^^^^^ no `foo` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-28388-2.rs b/tests/ui/imports/issue-28388-2.rs new file mode 100644 index 000000000..024b0388b --- /dev/null +++ b/tests/ui/imports/issue-28388-2.rs @@ -0,0 +1,10 @@ +// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. + +mod m { + mod n {} +} + +use m::n::{}; +//~^ ERROR module `n` is private + +fn main() {} diff --git a/tests/ui/imports/issue-28388-2.stderr b/tests/ui/imports/issue-28388-2.stderr new file mode 100644 index 000000000..1afaf622b --- /dev/null +++ b/tests/ui/imports/issue-28388-2.stderr @@ -0,0 +1,15 @@ +error[E0603]: module `n` is private + --> $DIR/issue-28388-2.rs:7:8 + | +LL | use m::n::{}; + | ^ private module + | +note: the module `n` is defined here + --> $DIR/issue-28388-2.rs:4:5 + | +LL | mod n {} + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/issue-2937.rs b/tests/ui/imports/issue-2937.rs new file mode 100644 index 000000000..335df5c07 --- /dev/null +++ b/tests/ui/imports/issue-2937.rs @@ -0,0 +1,6 @@ +use m::f as x; //~ ERROR unresolved import `m::f` [E0432] + //~^ no `f` in `m` + +mod m {} + +fn main() {} diff --git a/tests/ui/imports/issue-2937.stderr b/tests/ui/imports/issue-2937.stderr new file mode 100644 index 000000000..428634828 --- /dev/null +++ b/tests/ui/imports/issue-2937.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `m::f` + --> $DIR/issue-2937.rs:1:5 + | +LL | use m::f as x; + | ^^^^^^^^^ no `f` in `m` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-30560.rs b/tests/ui/imports/issue-30560.rs new file mode 100644 index 000000000..d8d4ca608 --- /dev/null +++ b/tests/ui/imports/issue-30560.rs @@ -0,0 +1,9 @@ +type Alias = (); +use Alias::*; //~ ERROR unresolved import `Alias` [E0432] + +use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432] + +trait T {} +use T::*; //~ ERROR items in traits are not importable + +fn main() {} diff --git a/tests/ui/imports/issue-30560.stderr b/tests/ui/imports/issue-30560.stderr new file mode 100644 index 000000000..69cfd4c06 --- /dev/null +++ b/tests/ui/imports/issue-30560.stderr @@ -0,0 +1,21 @@ +error: items in traits are not importable + --> $DIR/issue-30560.rs:7:5 + | +LL | use T::*; + | ^^^^ + +error[E0432]: unresolved import `Alias` + --> $DIR/issue-30560.rs:2:5 + | +LL | use Alias::*; + | ^^^^^ `Alias` is a type alias, not a module + +error[E0432]: unresolved import `std::io::Result` + --> $DIR/issue-30560.rs:4:14 + | +LL | use std::io::Result::*; + | ^^^^^^ `Result` is a type alias, not a module + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-31212.rs b/tests/ui/imports/issue-31212.rs new file mode 100644 index 000000000..556f0d18f --- /dev/null +++ b/tests/ui/imports/issue-31212.rs @@ -0,0 +1,10 @@ +// This checks that a path that cannot be resolved because of an indeterminate import +// does not trigger an ICE. + +mod foo { + pub use self::*; //~ ERROR unresolved +} + +fn main() { + foo::f(); //~ ERROR cannot find function `f` in module `foo` +} diff --git a/tests/ui/imports/issue-31212.stderr b/tests/ui/imports/issue-31212.stderr new file mode 100644 index 000000000..0bb56b361 --- /dev/null +++ b/tests/ui/imports/issue-31212.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `self::*` + --> $DIR/issue-31212.rs:5:13 + | +LL | pub use self::*; + | ^^^^^^^ cannot glob-import a module into itself + +error[E0425]: cannot find function `f` in module `foo` + --> $DIR/issue-31212.rs:9:10 + | +LL | foo::f(); + | ^ not found in `foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0432. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/issue-32119.rs b/tests/ui/imports/issue-32119.rs new file mode 100644 index 000000000..36adb5289 --- /dev/null +++ b/tests/ui/imports/issue-32119.rs @@ -0,0 +1,17 @@ +// check-pass + +pub type T = (); +mod foo { pub use super::T; } +mod bar { pub use super::T; } + +pub use foo::*; +pub use bar::*; + +mod baz { + pub type T = (); + mod foo { pub use super::T as S; } + mod bar { pub use super::foo::S as T; } + pub use self::bar::*; +} + +fn main() {} diff --git a/tests/ui/imports/issue-32222.rs b/tests/ui/imports/issue-32222.rs new file mode 100644 index 000000000..4ed06bff8 --- /dev/null +++ b/tests/ui/imports/issue-32222.rs @@ -0,0 +1,22 @@ +// check-pass + +mod foo { + pub fn bar() {} +} + +pub use foo::*; +use b::bar; + +mod foobar { + use super::*; +} + +mod a { + pub mod bar {} +} + +mod b { + pub use a::bar; +} + +fn main() {} diff --git a/tests/ui/imports/issue-32354-suggest-import-rename.fixed b/tests/ui/imports/issue-32354-suggest-import-rename.fixed new file mode 100644 index 000000000..27f1b8964 --- /dev/null +++ b/tests/ui/imports/issue-32354-suggest-import-rename.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_imports)] + +pub mod extension1 { + pub trait ConstructorExtension {} +} + +pub mod extension2 { + pub trait ConstructorExtension {} +} + +use extension1::ConstructorExtension; +use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-32354-suggest-import-rename.rs b/tests/ui/imports/issue-32354-suggest-import-rename.rs new file mode 100644 index 000000000..5a7f234d5 --- /dev/null +++ b/tests/ui/imports/issue-32354-suggest-import-rename.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_imports)] + +pub mod extension1 { + pub trait ConstructorExtension {} +} + +pub mod extension2 { + pub trait ConstructorExtension {} +} + +use extension1::ConstructorExtension; +use extension2::ConstructorExtension; //~ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-32354-suggest-import-rename.stderr b/tests/ui/imports/issue-32354-suggest-import-rename.stderr new file mode 100644 index 000000000..4c5875ba7 --- /dev/null +++ b/tests/ui/imports/issue-32354-suggest-import-rename.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `ConstructorExtension` is defined multiple times + --> $DIR/issue-32354-suggest-import-rename.rs:14:5 + | +LL | use extension1::ConstructorExtension; + | -------------------------------- previous import of the trait `ConstructorExtension` here +LL | use extension2::ConstructorExtension; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ConstructorExtension` reimported here + | + = note: `ConstructorExtension` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use extension2::ConstructorExtension as OtherConstructorExtension; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-32833.rs b/tests/ui/imports/issue-32833.rs new file mode 100644 index 000000000..379eedde7 --- /dev/null +++ b/tests/ui/imports/issue-32833.rs @@ -0,0 +1,7 @@ +use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432] + //~^ no `Foo` in `bar` +mod bar { + use Foo; +} + +fn main() {} diff --git a/tests/ui/imports/issue-32833.stderr b/tests/ui/imports/issue-32833.stderr new file mode 100644 index 000000000..430cc0fda --- /dev/null +++ b/tests/ui/imports/issue-32833.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `bar::Foo` + --> $DIR/issue-32833.rs:1:5 + | +LL | use bar::Foo; + | ^^^^^^^^ no `Foo` in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-33464.rs b/tests/ui/imports/issue-33464.rs new file mode 100644 index 000000000..a0edb5fdb --- /dev/null +++ b/tests/ui/imports/issue-33464.rs @@ -0,0 +1,10 @@ +// Make sure that the spans of import errors are correct. + +use abc::one_el; +//~^ ERROR +use abc::{a, bbb, cccccc}; +//~^ ERROR +use a_very_long_name::{el, el2}; +//~^ ERROR + +fn main() {} diff --git a/tests/ui/imports/issue-33464.stderr b/tests/ui/imports/issue-33464.stderr new file mode 100644 index 000000000..c4e5c5558 --- /dev/null +++ b/tests/ui/imports/issue-33464.stderr @@ -0,0 +1,27 @@ +error[E0432]: unresolved import `abc` + --> $DIR/issue-33464.rs:3:5 + | +LL | use abc::one_el; + | ^^^ maybe a missing crate `abc`? + | + = help: consider adding `extern crate abc` to use the `abc` crate + +error[E0432]: unresolved import `abc` + --> $DIR/issue-33464.rs:5:5 + | +LL | use abc::{a, bbb, cccccc}; + | ^^^ maybe a missing crate `abc`? + | + = help: consider adding `extern crate abc` to use the `abc` crate + +error[E0432]: unresolved import `a_very_long_name` + --> $DIR/issue-33464.rs:7:5 + | +LL | use a_very_long_name::{el, el2}; + | ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`? + | + = help: consider adding `extern crate a_very_long_name` to use the `a_very_long_name` crate + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-36881.rs b/tests/ui/imports/issue-36881.rs new file mode 100644 index 000000000..04313872d --- /dev/null +++ b/tests/ui/imports/issue-36881.rs @@ -0,0 +1,6 @@ +// aux-build:issue-36881-aux.rs + +fn main() { + extern crate issue_36881_aux; + use issue_36881_aux::Foo; //~ ERROR unresolved import +} diff --git a/tests/ui/imports/issue-36881.stderr b/tests/ui/imports/issue-36881.stderr new file mode 100644 index 000000000..2e1b46860 --- /dev/null +++ b/tests/ui/imports/issue-36881.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `issue_36881_aux` + --> $DIR/issue-36881.rs:5:9 + | +LL | use issue_36881_aux::Foo; + | ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`? + | + = help: consider adding `extern crate issue_36881_aux` to use the `issue_36881_aux` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-37887.rs b/tests/ui/imports/issue-37887.rs new file mode 100644 index 000000000..58f0c6b65 --- /dev/null +++ b/tests/ui/imports/issue-37887.rs @@ -0,0 +1,4 @@ +fn main() { + extern crate libc; //~ ERROR use of unstable + use libc::*; //~ ERROR unresolved import +} diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr new file mode 100644 index 000000000..75185cad3 --- /dev/null +++ b/tests/ui/imports/issue-37887.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `libc` + --> $DIR/issue-37887.rs:3:9 + | +LL | use libc::*; + | ^^^^ maybe a missing crate `libc`? + | + = help: consider adding `extern crate libc` to use the `libc` crate + +error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/issue-37887.rs:2:5 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #27812 for more information + = help: add `#![feature(rustc_private)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0658. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-38293.rs b/tests/ui/imports/issue-38293.rs new file mode 100644 index 000000000..3b1393600 --- /dev/null +++ b/tests/ui/imports/issue-38293.rs @@ -0,0 +1,16 @@ +// Test that `fn foo::bar::{self}` only imports `bar` in the type namespace. + +mod foo { + pub fn f() { } +} +use foo::f::{self}; //~ ERROR unresolved import `foo::f` + +mod bar { + pub fn baz() {} + pub mod baz {} +} +use bar::baz::{self}; + +fn main() { + baz(); //~ ERROR expected function, found module `baz` +} diff --git a/tests/ui/imports/issue-38293.stderr b/tests/ui/imports/issue-38293.stderr new file mode 100644 index 000000000..d2450ab12 --- /dev/null +++ b/tests/ui/imports/issue-38293.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `foo::f` + --> $DIR/issue-38293.rs:6:14 + | +LL | use foo::f::{self}; + | ^^^^ no `f` in `foo` + +error[E0423]: expected function, found module `baz` + --> $DIR/issue-38293.rs:15:5 + | +LL | baz(); + | ^^^ not a function + | +help: consider importing this function instead + | +LL | use bar::baz; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0432. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/imports/issue-4366-2.rs b/tests/ui/imports/issue-4366-2.rs new file mode 100644 index 000000000..c777b7502 --- /dev/null +++ b/tests/ui/imports/issue-4366-2.rs @@ -0,0 +1,26 @@ +// ensures that 'use foo:*' doesn't import non-public item + +use m1::*; + +mod foo { + pub fn foo() {} +} +mod a { + pub mod b { + use foo::foo; + type Bar = isize; + } + pub mod sub { + use a::b::*; + fn sub() -> Bar { 1 } + //~^ ERROR cannot find type `Bar` in this scope + } +} + +mod m1 { + fn foo() {} +} + +fn main() { + foo(); //~ ERROR expected function, found module `foo` +} diff --git a/tests/ui/imports/issue-4366-2.stderr b/tests/ui/imports/issue-4366-2.stderr new file mode 100644 index 000000000..4c94634ee --- /dev/null +++ b/tests/ui/imports/issue-4366-2.stderr @@ -0,0 +1,27 @@ +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-4366-2.rs:15:21 + | +LL | fn sub() -> Bar { 1 } + | ^^^ not found in this scope + | +note: type alias `a::b::Bar` exists but is inaccessible + --> $DIR/issue-4366-2.rs:11:9 + | +LL | type Bar = isize; + | ^^^^^^^^^^^^^^^^^ not accessible + +error[E0423]: expected function, found module `foo` + --> $DIR/issue-4366-2.rs:25:5 + | +LL | foo(); + | ^^^ not a function + | +help: consider importing this function instead + | +LL | use foo::foo; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0423. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/imports/issue-4366.rs b/tests/ui/imports/issue-4366.rs new file mode 100644 index 000000000..9ec2e58ec --- /dev/null +++ b/tests/ui/imports/issue-4366.rs @@ -0,0 +1,26 @@ +// regression test for issue 4366 + +// ensures that 'use foo:*' doesn't import non-public 'use' statements in the +// module 'foo' + +use m1::*; + +mod foo { + pub fn foo() {} +} +mod a { + pub mod b { + use foo::foo; + type Bar = isize; + } + pub mod sub { + use a::b::*; + fn sub() -> isize { foo(); 1 } //~ ERROR cannot find function `foo` in this scope + } +} + +mod m1 { + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/imports/issue-4366.stderr b/tests/ui/imports/issue-4366.stderr new file mode 100644 index 000000000..469ea93e9 --- /dev/null +++ b/tests/ui/imports/issue-4366.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/issue-4366.rs:18:29 + | +LL | fn sub() -> isize { foo(); 1 } + | ^^^ not found in this scope + | +help: consider importing this function + | +LL | use foo::foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed new file mode 100644 index 000000000..b463848ae --- /dev/null +++ b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed @@ -0,0 +1,5 @@ +// run-rustfix + +extern crate std as other_std; +fn main() {} +//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs new file mode 100644 index 000000000..1b491ac7e --- /dev/null +++ b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs @@ -0,0 +1,5 @@ +// run-rustfix + +extern crate std; +fn main() {} +//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr new file mode 100644 index 000000000..25aca4cb7 --- /dev/null +++ b/tests/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr @@ -0,0 +1,15 @@ +error[E0259]: the name `std` is defined multiple times + --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:3:1 + | +LL | extern crate std; + | ^^^^^^^^^^^^^^^^^ `std` reimported here + | + = note: `std` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate std as other_std; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/issue-45829/auxiliary/issue-45829-a.rs b/tests/ui/imports/issue-45829/auxiliary/issue-45829-a.rs new file mode 100644 index 000000000..e9f7fefb6 --- /dev/null +++ b/tests/ui/imports/issue-45829/auxiliary/issue-45829-a.rs @@ -0,0 +1 @@ +pub const FOO: usize = *&0; diff --git a/tests/ui/imports/issue-45829/auxiliary/issue-45829-b.rs b/tests/ui/imports/issue-45829/auxiliary/issue-45829-b.rs new file mode 100644 index 000000000..e9f7fefb6 --- /dev/null +++ b/tests/ui/imports/issue-45829/auxiliary/issue-45829-b.rs @@ -0,0 +1 @@ +pub const FOO: usize = *&0; diff --git a/tests/ui/imports/issue-45829/import-self.rs b/tests/ui/imports/issue-45829/import-self.rs new file mode 100644 index 000000000..2dc4331ce --- /dev/null +++ b/tests/ui/imports/issue-45829/import-self.rs @@ -0,0 +1,19 @@ +mod foo { + pub struct A; + pub struct B; +} + +use foo::{self}; +//~^ ERROR is defined multiple times + +use foo as self; +//~^ ERROR expected identifier + +use foo::self; //~ ERROR is defined multiple times +//~^ ERROR `self` imports are only allowed within a { } list + +use foo::A; +use foo::{self as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/import-self.stderr b/tests/ui/imports/issue-45829/import-self.stderr new file mode 100644 index 000000000..0c9424f30 --- /dev/null +++ b/tests/ui/imports/issue-45829/import-self.stderr @@ -0,0 +1,70 @@ +error: expected identifier, found keyword `self` + --> $DIR/import-self.rs:9:12 + | +LL | use foo as self; + | ^^^^ expected identifier, found keyword + +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/import-self.rs:12:8 + | +LL | use foo::self; + | ^^^^^^ + | +help: consider importing the module directly + | +LL - use foo::self; +LL + use foo; + | +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use foo::{self}; + | + + + +error[E0255]: the name `foo` is defined multiple times + --> $DIR/import-self.rs:6:11 + | +LL | mod foo { + | ------- previous definition of the module `foo` here +... +LL | use foo::{self}; + | ^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{self as other_foo}; + | ~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `foo` is defined multiple times + --> $DIR/import-self.rs:12:5 + | +LL | mod foo { + | ------- previous definition of the module `foo` here +... +LL | use foo::self; + | ^^^^^^^^^ `foo` reimported here + | + = note: `foo` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo as other_foo; + | ~~~~~~~~~~~~~~~~ + +error[E0252]: the name `A` is defined multiple times + --> $DIR/import-self.rs:16:11 + | +LL | use foo::A; + | ------ previous import of the type `A` here +LL | use foo::{self as A}; + | ^^^^^^^^^ `A` reimported here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{self as OtherA}; + | ~~~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0252, E0255, E0429. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/import-twice.rs b/tests/ui/imports/issue-45829/import-twice.rs new file mode 100644 index 000000000..e5a8bb7ad --- /dev/null +++ b/tests/ui/imports/issue-45829/import-twice.rs @@ -0,0 +1,9 @@ +mod foo { + pub struct A; + pub struct B; +} + +use foo::{A, A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/import-twice.stderr b/tests/ui/imports/issue-45829/import-twice.stderr new file mode 100644 index 000000000..656b011bc --- /dev/null +++ b/tests/ui/imports/issue-45829/import-twice.stderr @@ -0,0 +1,13 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/import-twice.rs:6:14 + | +LL | use foo::{A, A}; + | - ^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/issue-45829.rs b/tests/ui/imports/issue-45829/issue-45829.rs new file mode 100644 index 000000000..1e76e4b14 --- /dev/null +++ b/tests/ui/imports/issue-45829/issue-45829.rs @@ -0,0 +1,9 @@ +mod foo { + pub struct A; + pub struct B; +} + +use foo::{A, B as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/issue-45829.stderr b/tests/ui/imports/issue-45829/issue-45829.stderr new file mode 100644 index 000000000..e9a9d47ce --- /dev/null +++ b/tests/ui/imports/issue-45829/issue-45829.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/issue-45829.rs:6:14 + | +LL | use foo::{A, B as A}; + | - ^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{A, B as OtherA}; + | ~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/rename-extern-vs-use.rs b/tests/ui/imports/issue-45829/rename-extern-vs-use.rs new file mode 100644 index 000000000..aef7aa35c --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-extern-vs-use.rs @@ -0,0 +1,11 @@ +// aux-build:issue-45829-b.rs + +mod foo { + pub mod bar {} +} + +use foo::bar; +extern crate issue_45829_b as bar; +//~^ ERROR the name `bar` is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr b/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr new file mode 100644 index 000000000..98fd8a623 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-extern-vs-use.stderr @@ -0,0 +1,17 @@ +error[E0254]: the name `bar` is defined multiple times + --> $DIR/rename-extern-vs-use.rs:8:1 + | +LL | use foo::bar; + | -------- previous import of the module `bar` here +LL | extern crate issue_45829_b as bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` reimported here + | + = note: `bar` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_bar; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/imports/issue-45829/rename-extern-with-tab.rs b/tests/ui/imports/issue-45829/rename-extern-with-tab.rs new file mode 100644 index 000000000..0da8b826c --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-extern-with-tab.rs @@ -0,0 +1,8 @@ +// aux-build:issue-45829-a.rs +// aux-build:issue-45829-b.rs + +extern crate issue_45829_a; +extern crate issue_45829_b as issue_45829_a; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr b/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr new file mode 100644 index 000000000..2c4e8ce99 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-extern-with-tab.stderr @@ -0,0 +1,17 @@ +error[E0259]: the name `issue_45829_a` is defined multiple times + --> $DIR/rename-extern-with-tab.rs:5:1 + | +LL | extern crate issue_45829_a; + | --------------------------- previous import of the extern crate `issue_45829_a` here +LL | extern crate issue_45829_b as issue_45829_a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here + | + = note: `issue_45829_a` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_issue_45829_a; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/issue-45829/rename-extern.rs b/tests/ui/imports/issue-45829/rename-extern.rs new file mode 100644 index 000000000..7dbda6932 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-extern.rs @@ -0,0 +1,8 @@ +// aux-build:issue-45829-a.rs +// aux-build:issue-45829-b.rs + +extern crate issue_45829_a; +extern crate issue_45829_b as issue_45829_a; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/rename-extern.stderr b/tests/ui/imports/issue-45829/rename-extern.stderr new file mode 100644 index 000000000..209ae2201 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-extern.stderr @@ -0,0 +1,17 @@ +error[E0259]: the name `issue_45829_a` is defined multiple times + --> $DIR/rename-extern.rs:5:1 + | +LL | extern crate issue_45829_a; + | --------------------------- previous import of the extern crate `issue_45829_a` here +LL | extern crate issue_45829_b as issue_45829_a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here + | + = note: `issue_45829_a` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate issue_45829_b as other_issue_45829_a; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/issue-45829/rename-use-vs-extern.rs b/tests/ui/imports/issue-45829/rename-use-vs-extern.rs new file mode 100644 index 000000000..0cf3a77fd --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-use-vs-extern.rs @@ -0,0 +1,7 @@ +// aux-build:issue-45829-b.rs + +extern crate issue_45829_b; +use std as issue_45829_b; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr b/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr new file mode 100644 index 000000000..dfb5810c4 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-use-vs-extern.stderr @@ -0,0 +1,17 @@ +error[E0254]: the name `issue_45829_b` is defined multiple times + --> $DIR/rename-use-vs-extern.rs:4:5 + | +LL | extern crate issue_45829_b; + | --------------------------- previous import of the extern crate `issue_45829_b` here +LL | use std as issue_45829_b; + | ^^^^^^^^^^^^^^^^^^^^ `issue_45829_b` reimported here + | + = note: `issue_45829_b` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std as other_issue_45829_b; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/imports/issue-45829/rename-use-with-tabs.rs b/tests/ui/imports/issue-45829/rename-use-with-tabs.rs new file mode 100644 index 000000000..86c5fa00f --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-use-with-tabs.rs @@ -0,0 +1,12 @@ +mod foo { + pub struct A; + + pub mod bar { + pub struct B; + } +} + +use foo::{A, bar::B as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr b/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr new file mode 100644 index 000000000..5a63af588 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-use-with-tabs.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/rename-use-with-tabs.rs:9:14 + | +LL | use foo::{A, bar::B as A}; + | - ^^^^^^^^^^^^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use foo::{A, bar::B as OtherA}; + | ~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/rename-with-path.rs b/tests/ui/imports/issue-45829/rename-with-path.rs new file mode 100644 index 000000000..e278a8789 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-with-path.rs @@ -0,0 +1,4 @@ +use std::{collections::HashMap as A, sync::Arc as A}; +//~^ ERROR is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-45829/rename-with-path.stderr b/tests/ui/imports/issue-45829/rename-with-path.stderr new file mode 100644 index 000000000..2d26b0838 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename-with-path.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `A` is defined multiple times + --> $DIR/rename-with-path.rs:1:38 + | +LL | use std::{collections::HashMap as A, sync::Arc as A}; + | ------------------------- ^^^^^^^^^^^^^^ `A` reimported here + | | + | previous import of the type `A` here + | + = note: `A` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::{collections::HashMap as A, sync::Arc as OtherA}; + | ~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-45829/rename.rs b/tests/ui/imports/issue-45829/rename.rs new file mode 100644 index 000000000..1c45956c6 --- /dev/null +++ b/tests/ui/imports/issue-45829/rename.rs @@ -0,0 +1,7 @@ +use core; +use std as core; +//~^ ERROR is defined multiple times + +fn main() { + 1 + 1; +} diff --git a/tests/ui/imports/issue-45829/rename.stderr b/tests/ui/imports/issue-45829/rename.stderr new file mode 100644 index 000000000..ed185ae2a --- /dev/null +++ b/tests/ui/imports/issue-45829/rename.stderr @@ -0,0 +1,17 @@ +error[E0252]: the name `core` is defined multiple times + --> $DIR/rename.rs:2:5 + | +LL | use core; + | ---- previous import of the module `core` here +LL | use std as core; + | ^^^^^^^^^^^ `core` reimported here + | + = note: `core` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std as other_core; + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-47623.rs b/tests/ui/imports/issue-47623.rs new file mode 100644 index 000000000..ad8aa4c1a --- /dev/null +++ b/tests/ui/imports/issue-47623.rs @@ -0,0 +1,3 @@ +use self; //~ERROR `self` imports are only allowed within a { } list + +fn main() {} diff --git a/tests/ui/imports/issue-47623.stderr b/tests/ui/imports/issue-47623.stderr new file mode 100644 index 000000000..53968a296 --- /dev/null +++ b/tests/ui/imports/issue-47623.stderr @@ -0,0 +1,9 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/issue-47623.rs:1:5 + | +LL | use self; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/imports/issue-4865-1.rs b/tests/ui/imports/issue-4865-1.rs new file mode 100644 index 000000000..68fbee37d --- /dev/null +++ b/tests/ui/imports/issue-4865-1.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_imports)] +// This should resolve fine. +// Prior to fix, the crossed imports between a and b +// would block on the glob import, itself never being resolved +// because these previous imports were not resolved. + +pub mod a { + use b::fn_b; + use c::*; + + pub fn fn_a(){ + } +} + +pub mod b { + use a::fn_a; + use c::*; + + pub fn fn_b(){ + } +} + +pub mod c{ + pub fn fn_c(){ + } +} + +use a::fn_a; +use b::fn_b; + +fn main() { +} diff --git a/tests/ui/imports/issue-4865-2.rs b/tests/ui/imports/issue-4865-2.rs new file mode 100644 index 000000000..cbe1d0d32 --- /dev/null +++ b/tests/ui/imports/issue-4865-2.rs @@ -0,0 +1,24 @@ +// run-pass +// Previously, this would have failed to resolve due to the circular +// block between `use say` and `pub use hello::*`. +// +// Now, as `use say` is not `pub`, the glob import can resolve +// without any problem and this resolves fine. + +pub use hello::*; + +pub mod say { + pub fn hello() { println!("hello"); } +} + +pub mod hello { + use say; + + pub fn hello() { + say::hello(); + } +} + +fn main() { + hello(); +} diff --git a/tests/ui/imports/issue-4865-3.rs b/tests/ui/imports/issue-4865-3.rs new file mode 100644 index 000000000..12f9bba18 --- /dev/null +++ b/tests/ui/imports/issue-4865-3.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_imports)] +// This should resolve fine even with the circular imports as +// they are not `pub`. + +pub mod a { + use b::*; +} + +pub mod b { + use a::*; +} + +use a::*; + +fn main() { +} diff --git a/tests/ui/imports/issue-52891.fixed b/tests/ui/imports/issue-52891.fixed new file mode 100644 index 000000000..e694b5c9b --- /dev/null +++ b/tests/ui/imports/issue-52891.fixed @@ -0,0 +1,37 @@ +// aux-build:issue-52891.rs +// run-rustfix + +#![allow(warnings)] + +extern crate issue_52891; + +// Check that we don't suggest renaming duplicate imports but instead +// suggest removing one. + +use issue_52891::a; + //~ ERROR `a` is defined multiple times + +use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times +use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times +use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times + +use issue_52891::{//~ ERROR `a` is defined multiple times + h, + i}; +use issue_52891::{j, + //~ ERROR `a` is defined multiple times + k}; +use issue_52891::{l, + m}; //~ ERROR `a` is defined multiple times + +use issue_52891::a::inner; +use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times + + +//~^ ERROR `issue_52891` is defined multiple times + + +#[macro_use] +use issue_52891::n; //~ ERROR `n` is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-52891.rs b/tests/ui/imports/issue-52891.rs new file mode 100644 index 000000000..cd4b40629 --- /dev/null +++ b/tests/ui/imports/issue-52891.rs @@ -0,0 +1,38 @@ +// aux-build:issue-52891.rs +// run-rustfix + +#![allow(warnings)] + +extern crate issue_52891; + +// Check that we don't suggest renaming duplicate imports but instead +// suggest removing one. + +use issue_52891::a; +use issue_52891::a; //~ ERROR `a` is defined multiple times + +use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times +use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times +use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times + +use issue_52891::{a, //~ ERROR `a` is defined multiple times + h, + i}; +use issue_52891::{j, + a, //~ ERROR `a` is defined multiple times + k}; +use issue_52891::{l, + m, + a}; //~ ERROR `a` is defined multiple times + +use issue_52891::a::inner; +use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times + +use issue_52891::{self}; +//~^ ERROR `issue_52891` is defined multiple times + +use issue_52891::n; +#[macro_use] +use issue_52891::n; //~ ERROR `n` is defined multiple times + +fn main() {} diff --git a/tests/ui/imports/issue-52891.stderr b/tests/ui/imports/issue-52891.stderr new file mode 100644 index 000000000..7bb1301ed --- /dev/null +++ b/tests/ui/imports/issue-52891.stderr @@ -0,0 +1,131 @@ +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:12:5 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +LL | use issue_52891::a; + | ^^^^^^^^^^^^^^ `a` reimported here + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:14:19 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{a, b, c}; + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:15:22 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{d, a, e}; + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:16:25 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{f, g, a}; + | ^ `a` reimported here + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:18:19 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | use issue_52891::{a, + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:22:5 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | a, + | ^-- + | | + | `a` reimported here + | help: remove unnecessary import + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `a` is defined multiple times + --> $DIR/issue-52891.rs:26:5 + | +LL | use issue_52891::a; + | -------------- previous import of the module `a` here +... +LL | a}; + | ^ `a` reimported here + | + = note: `a` must be defined only once in the type namespace of this module + +error[E0252]: the name `inner` is defined multiple times + --> $DIR/issue-52891.rs:29:5 + | +LL | use issue_52891::a::inner; + | --------------------- previous import of the module `inner` here +LL | use issue_52891::b::inner; + | ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here + | + = note: `inner` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use issue_52891::b::inner as other_inner; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0254]: the name `issue_52891` is defined multiple times + --> $DIR/issue-52891.rs:31:19 + | +LL | extern crate issue_52891; + | ------------------------- previous import of the extern crate `issue_52891` here +... +LL | use issue_52891::{self}; + | ------------------^^^^-- + | | | + | | `issue_52891` reimported here + | help: remove unnecessary import + | + = note: `issue_52891` must be defined only once in the type namespace of this module + +error[E0252]: the name `n` is defined multiple times + --> $DIR/issue-52891.rs:36:5 + | +LL | use issue_52891::n; + | -------------- previous import of the module `n` here +LL | #[macro_use] +LL | use issue_52891::n; + | ^^^^^^^^^^^^^^ `n` reimported here + | + = note: `n` must be defined only once in the type namespace of this module + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0252, E0254. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/issue-53140.rs b/tests/ui/imports/issue-53140.rs new file mode 100644 index 000000000..7b4cc1768 --- /dev/null +++ b/tests/ui/imports/issue-53140.rs @@ -0,0 +1,11 @@ +// check-pass + +mod m { + pub struct S(u8); + + use S as Z; +} + +use m::*; + +fn main() {} diff --git a/tests/ui/imports/issue-53269.rs b/tests/ui/imports/issue-53269.rs new file mode 100644 index 000000000..1031d5071 --- /dev/null +++ b/tests/ui/imports/issue-53269.rs @@ -0,0 +1,11 @@ +// Ambiguity between a `macro_rules` macro and a non-existent import recovered as `Res::Err` + +macro_rules! mac { () => () } + +mod m { + use nonexistent_module::mac; //~ ERROR unresolved import `nonexistent_module` + + mac!(); //~ ERROR `mac` is ambiguous +} + +fn main() {} diff --git a/tests/ui/imports/issue-53269.stderr b/tests/ui/imports/issue-53269.stderr new file mode 100644 index 000000000..29c7556da --- /dev/null +++ b/tests/ui/imports/issue-53269.stderr @@ -0,0 +1,31 @@ +error[E0432]: unresolved import `nonexistent_module` + --> $DIR/issue-53269.rs:6:9 + | +LL | use nonexistent_module::mac; + | ^^^^^^^^^^^^^^^^^^ maybe a missing crate `nonexistent_module`? + | + = help: consider adding `extern crate nonexistent_module` to use the `nonexistent_module` crate + +error[E0659]: `mac` is ambiguous + --> $DIR/issue-53269.rs:8:5 + | +LL | mac!(); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module +note: `mac` could refer to the macro defined here + --> $DIR/issue-53269.rs:3:1 + | +LL | macro_rules! mac { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `mac` could also refer to the unresolved item imported here + --> $DIR/issue-53269.rs:6:9 + | +LL | use nonexistent_module::mac; + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::mac` to refer to this unresolved item unambiguously + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0659. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-53512.rs b/tests/ui/imports/issue-53512.rs new file mode 100644 index 000000000..67470f854 --- /dev/null +++ b/tests/ui/imports/issue-53512.rs @@ -0,0 +1,8 @@ +// Macro from prelude is shadowed by non-existent import recovered as `Res::Err`. + +mod m {} +use m::assert; //~ ERROR unresolved import `m::assert` + +fn main() { + assert!(true); +} diff --git a/tests/ui/imports/issue-53512.stderr b/tests/ui/imports/issue-53512.stderr new file mode 100644 index 000000000..05fe111b3 --- /dev/null +++ b/tests/ui/imports/issue-53512.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `m::assert` + --> $DIR/issue-53512.rs:4:5 + | +LL | use m::assert; + | ^^^^^^^^^ no `assert` in `m` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-53565.rs b/tests/ui/imports/issue-53565.rs new file mode 100644 index 000000000..114a53a92 --- /dev/null +++ b/tests/ui/imports/issue-53565.rs @@ -0,0 +1,7 @@ +use std::time::{foo, bar, buzz}; +//~^ ERROR unresolved imports +use std::time::{abc, def}; +//~^ ERROR unresolved imports +fn main(){ + println!("Hello World!"); +} diff --git a/tests/ui/imports/issue-53565.stderr b/tests/ui/imports/issue-53565.stderr new file mode 100644 index 000000000..71c3b2aaa --- /dev/null +++ b/tests/ui/imports/issue-53565.stderr @@ -0,0 +1,20 @@ +error[E0432]: unresolved imports `std::time::foo`, `std::time::bar`, `std::time::buzz` + --> $DIR/issue-53565.rs:1:17 + | +LL | use std::time::{foo, bar, buzz}; + | ^^^ ^^^ ^^^^ no `buzz` in `time` + | | | + | | no `bar` in `time` + | no `foo` in `time` + +error[E0432]: unresolved imports `std::time::abc`, `std::time::def` + --> $DIR/issue-53565.rs:3:17 + | +LL | use std::time::{abc, def}; + | ^^^ ^^^ no `def` in `time` + | | + | no `abc` in `time` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-55457.rs b/tests/ui/imports/issue-55457.rs new file mode 100644 index 000000000..c1f048897 --- /dev/null +++ b/tests/ui/imports/issue-55457.rs @@ -0,0 +1,10 @@ +use NonExistent; //~ ERROR unresolved import `NonExistent` +use non_existent::non_existent; //~ ERROR unresolved import `non_existent` + +#[non_existent] //~ ERROR cannot determine resolution for the attribute macro `non_existent` +#[derive(NonExistent)] //~ ERROR cannot determine resolution for the derive macro `NonExistent` + //~| ERROR cannot determine resolution for the derive macro `NonExistent` + //~| ERROR cannot determine resolution for the derive macro `NonExistent` +struct S; + +fn main() {} diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr new file mode 100644 index 000000000..788fcc830 --- /dev/null +++ b/tests/ui/imports/issue-55457.stderr @@ -0,0 +1,52 @@ +error[E0432]: unresolved import `NonExistent` + --> $DIR/issue-55457.rs:1:5 + | +LL | use NonExistent; + | ^^^^^^^^^^^ + | | + | no `NonExistent` in the root + | help: a similar name exists in the module: `non_existent` + +error[E0432]: unresolved import `non_existent` + --> $DIR/issue-55457.rs:2:5 + | +LL | use non_existent::non_existent; + | ^^^^^^^^^^^^ maybe a missing crate `non_existent`? + | + = help: consider adding `extern crate non_existent` to use the `non_existent` crate + +error: cannot determine resolution for the derive macro `NonExistent` + --> $DIR/issue-55457.rs:5:10 + | +LL | #[derive(NonExistent)] + | ^^^^^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the attribute macro `non_existent` + --> $DIR/issue-55457.rs:4:3 + | +LL | #[non_existent] + | ^^^^^^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the derive macro `NonExistent` + --> $DIR/issue-55457.rs:5:10 + | +LL | #[derive(NonExistent)] + | ^^^^^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot determine resolution for the derive macro `NonExistent` + --> $DIR/issue-55457.rs:5:10 + | +LL | #[derive(NonExistent)] + | ^^^^^^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-55811.rs b/tests/ui/imports/issue-55811.rs new file mode 100644 index 000000000..2df328cca --- /dev/null +++ b/tests/ui/imports/issue-55811.rs @@ -0,0 +1,6 @@ +// check-pass +// aux-build:issue-55811.rs + +extern crate issue_55811; + +fn main() {} diff --git a/tests/ui/imports/issue-55884-1.rs b/tests/ui/imports/issue-55884-1.rs new file mode 100644 index 000000000..21744aa5d --- /dev/null +++ b/tests/ui/imports/issue-55884-1.rs @@ -0,0 +1,21 @@ +mod m { + mod m1 { + pub struct S {} + } + mod m2 { + // Note this derive, it makes this struct macro-expanded, + // so it doesn't appear in time to participate in the initial resolution of `use m::S`, + // only in the later validation pass. + #[derive(Default)] + pub struct S {} + } + + // Create a glob vs glob ambiguity + pub use self::m1::*; + pub use self::m2::*; +} + +fn main() { + use m::S; //~ ERROR `S` is ambiguous + let s = S {}; +} diff --git a/tests/ui/imports/issue-55884-1.stderr b/tests/ui/imports/issue-55884-1.stderr new file mode 100644 index 000000000..c38166dde --- /dev/null +++ b/tests/ui/imports/issue-55884-1.stderr @@ -0,0 +1,23 @@ +error[E0659]: `S` is ambiguous + --> $DIR/issue-55884-1.rs:19:12 + | +LL | use m::S; + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `S` could refer to the struct imported here + --> $DIR/issue-55884-1.rs:14:13 + | +LL | pub use self::m1::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate +note: `S` could also refer to the struct imported here + --> $DIR/issue-55884-1.rs:15:13 + | +LL | pub use self::m2::*; + | ^^^^^^^^^^^ + = help: consider adding an explicit import of `S` to disambiguate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/issue-55884-2.rs b/tests/ui/imports/issue-55884-2.rs new file mode 100644 index 000000000..75bb4206f --- /dev/null +++ b/tests/ui/imports/issue-55884-2.rs @@ -0,0 +1,14 @@ +mod options { + pub struct ParseOptions {} +} + +mod parser { + pub use options::*; + // Private single import shadows public glob import, but arrives too late for initial + // resolution of `use parser::ParseOptions` because it depends on that resolution itself. + use ParseOptions; +} + +pub use parser::ParseOptions; //~ ERROR struct import `ParseOptions` is private + +fn main() {} diff --git a/tests/ui/imports/issue-55884-2.stderr b/tests/ui/imports/issue-55884-2.stderr new file mode 100644 index 000000000..5adbc4b66 --- /dev/null +++ b/tests/ui/imports/issue-55884-2.stderr @@ -0,0 +1,30 @@ +error[E0603]: struct import `ParseOptions` is private + --> $DIR/issue-55884-2.rs:12:17 + | +LL | pub use parser::ParseOptions; + | ^^^^^^^^^^^^ private struct import + | +note: the struct import `ParseOptions` is defined here... + --> $DIR/issue-55884-2.rs:9:9 + | +LL | use ParseOptions; + | ^^^^^^^^^^^^ +note: ...and refers to the struct import `ParseOptions` which is defined here... + --> $DIR/issue-55884-2.rs:12:9 + | +LL | pub use parser::ParseOptions; + | ^^^^^^^^^^^^^^^^^^^^ consider importing it directly +note: ...and refers to the struct import `ParseOptions` which is defined here... + --> $DIR/issue-55884-2.rs:6:13 + | +LL | pub use options::*; + | ^^^^^^^^^^ consider importing it directly +note: ...and refers to the struct `ParseOptions` which is defined here + --> $DIR/issue-55884-2.rs:2:5 + | +LL | pub struct ParseOptions {} + | ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/issue-56125.rs b/tests/ui/imports/issue-56125.rs new file mode 100644 index 000000000..ec5747b4b --- /dev/null +++ b/tests/ui/imports/issue-56125.rs @@ -0,0 +1,21 @@ +// edition:2018 +// compile-flags:--extern issue_56125 +// aux-build:issue-56125.rs + +mod m1 { + use issue_56125::last_segment::*; + //~^ ERROR `issue_56125` is ambiguous +} + +mod m2 { + use issue_56125::non_last_segment::non_last_segment::*; + //~^ ERROR `issue_56125` is ambiguous +} + +mod m3 { + mod empty {} + use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` + use issue_56125::*; //~ ERROR `issue_56125` is ambiguous +} + +fn main() {} diff --git a/tests/ui/imports/issue-56125.stderr b/tests/ui/imports/issue-56125.stderr new file mode 100644 index 000000000..3448f3119 --- /dev/null +++ b/tests/ui/imports/issue-56125.stderr @@ -0,0 +1,70 @@ +error[E0432]: unresolved import `empty::issue_56125` + --> $DIR/issue-56125.rs:17:9 + | +LL | use empty::issue_56125; + | ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty` + | +help: consider importing one of these items instead + | +LL | use crate::m3::last_segment::issue_56125; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | use crate::m3::non_last_segment::non_last_segment::issue_56125; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | use issue_56125::issue_56125; + | ~~~~~~~~~~~~~~~~~~~~~~~~ +LL | use issue_56125::last_segment::issue_56125; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + and 1 other candidate + +error[E0659]: `issue_56125` is ambiguous + --> $DIR/issue-56125.rs:6:9 + | +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `issue_56125` could refer to a crate passed with `--extern` + = help: use `::issue_56125` to refer to this crate unambiguously +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:6:9 + | +LL | use issue_56125::last_segment::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously + +error[E0659]: `issue_56125` is ambiguous + --> $DIR/issue-56125.rs:11:9 + | +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `issue_56125` could refer to a crate passed with `--extern` + = help: use `::issue_56125` to refer to this crate unambiguously +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:11:9 + | +LL | use issue_56125::non_last_segment::non_last_segment::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously + +error[E0659]: `issue_56125` is ambiguous + --> $DIR/issue-56125.rs:18:9 + | +LL | use issue_56125::*; + | ^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `issue_56125` could refer to a crate passed with `--extern` + = help: use `::issue_56125` to refer to this crate unambiguously +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:18:9 + | +LL | use issue_56125::*; + | ^^^^^^^^^^^^^^ + = help: use `self::issue_56125` to refer to this module unambiguously + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0659. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-56263.rs b/tests/ui/imports/issue-56263.rs new file mode 100644 index 000000000..363781f2d --- /dev/null +++ b/tests/ui/imports/issue-56263.rs @@ -0,0 +1,8 @@ +// check-pass +// edition:2018 + +use ::std; + +fn main() { + let std = 10; +} diff --git a/tests/ui/imports/issue-57015.rs b/tests/ui/imports/issue-57015.rs new file mode 100644 index 000000000..27688fd34 --- /dev/null +++ b/tests/ui/imports/issue-57015.rs @@ -0,0 +1,13 @@ +mod glob_ok { + pub mod something { + pub mod something_else {} + } +} + +mod single_err {} + +use glob_ok::*; // glob_ok::something +use single_err::something; //~ ERROR unresolved import `single_err::something` +use something::something_else; + +fn main() {} diff --git a/tests/ui/imports/issue-57015.stderr b/tests/ui/imports/issue-57015.stderr new file mode 100644 index 000000000..5374ba3dc --- /dev/null +++ b/tests/ui/imports/issue-57015.stderr @@ -0,0 +1,14 @@ +error[E0432]: unresolved import `single_err::something` + --> $DIR/issue-57015.rs:10:5 + | +LL | use single_err::something; + | ^^^^^^^^^^^^^^^^^^^^^ no `something` in `single_err` + | +help: consider importing this module instead + | +LL | use glob_ok::something; + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-57539.rs b/tests/ui/imports/issue-57539.rs new file mode 100644 index 000000000..90b74eb46 --- /dev/null +++ b/tests/ui/imports/issue-57539.rs @@ -0,0 +1,8 @@ +// edition:2018 + +mod core { + use core; //~ ERROR `core` is ambiguous + use crate::*; +} + +fn main() {} diff --git a/tests/ui/imports/issue-57539.stderr b/tests/ui/imports/issue-57539.stderr new file mode 100644 index 000000000..1a3ca4eda --- /dev/null +++ b/tests/ui/imports/issue-57539.stderr @@ -0,0 +1,19 @@ +error[E0659]: `core` is ambiguous + --> $DIR/issue-57539.rs:4:9 + | +LL | use core; + | ^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `core` could refer to a built-in crate + = help: use `::core` to refer to this crate unambiguously +note: `core` could also refer to the module imported here + --> $DIR/issue-57539.rs:5:9 + | +LL | use crate::*; + | ^^^^^^^^ + = help: use `self::core` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/issue-59764.rs b/tests/ui/imports/issue-59764.rs new file mode 100644 index 000000000..09dee8c27 --- /dev/null +++ b/tests/ui/imports/issue-59764.rs @@ -0,0 +1,136 @@ +// aux-build:issue-59764.rs +// compile-flags:--extern issue_59764 +// edition:2018 + +#![allow(warnings)] + +// This tests the suggestion to import macros from the root of a crate. This aims to capture +// the case where a user attempts to import a macro from the definition location instead of the +// root of the crate and the macro is annotated with `#![macro_export]`. + +// Edge cases.. + +mod multiple_imports_same_line_at_end { + use issue_59764::foo::{baz, makro}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_at_end_trailing_comma { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }; +} + +mod multiple_imports_multiline_at_end { + use issue_59764::foo::{ + baz, + makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }; +} + +mod multiple_imports_same_line_in_middle { + use issue_59764::foo::{baz, makro, foobar}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod multiple_imports_multiline_in_middle_trailing_comma { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar, + }; +} + +mod multiple_imports_multiline_in_middle { + use issue_59764::foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + foobar + }; +} + +mod nested_imports { + use issue_59764::{foobaz, foo::makro}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiple_imports { + use issue_59764::{foobaz, foo::{baz, makro}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod nested_multiline_multiple_imports_trailing_comma { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + }, + }; +} + +mod nested_multiline_multiple_imports { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + } + }; +} + +mod doubly_nested_multiple_imports { + use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod doubly_multiline_nested_multiple_imports { + use issue_59764::{ + foobaz, + foo::{ + baz, + makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + barbaz::{ + barfoo, + } + } + }; +} + +mod renamed_import { + use issue_59764::foo::makro as baz; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod renamed_multiple_imports { + use issue_59764::foo::{baz, makro as foobar}; + //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] +} + +mod lots_of_whitespace { + use + issue_59764::{ + + foobaz, + + + foo::{baz, + + makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432] + + }; +} + +// Simple case.. + +use issue_59764::foo::makro; +//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] + +makro!(bar); +//~^ ERROR cannot determine resolution for the macro `makro` + +fn main() { + bar(); + //~^ ERROR cannot find function `bar` in this scope [E0425] +} diff --git a/tests/ui/imports/issue-59764.stderr b/tests/ui/imports/issue-59764.stderr new file mode 100644 index 000000000..b969515e2 --- /dev/null +++ b/tests/ui/imports/issue-59764.stderr @@ -0,0 +1,246 @@ +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:14:33 + | +LL | use issue_59764::foo::{baz, makro}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL - use issue_59764::foo::{baz, makro}; +LL + use issue_59764::{makro, foo::{baz}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:21:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, foo::{ +LL | baz, +LL ~ +LL ~ }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:28:9 + | +LL | makro + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, foo::{ +LL | baz, +LL ~ +LL ~ }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:33:33 + | +LL | use issue_59764::foo::{baz, makro, foobar}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL - use issue_59764::foo::{baz, makro, foobar}; +LL + use issue_59764::{makro, foo::{baz, foobar}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:40:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, foo::{ +LL | baz, +LL ~ +LL | foobar, +LL ~ }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:48:9 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, foo::{ +LL | baz, +LL ~ +LL | foobar +LL ~ }}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:54:31 + | +LL | use issue_59764::{foobaz, foo::makro}; + | ^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL - use issue_59764::{foobaz, foo::makro}; +LL + use issue_59764::{makro, foobaz}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:59:42 + | +LL | use issue_59764::{foobaz, foo::{baz, makro}}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL - use issue_59764::{foobaz, foo::{baz, makro}}; +LL + use issue_59764::{makro, foobaz, foo::{baz}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:68:13 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL ~ + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:78:13 + | +LL | makro + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL ~ + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:84:42 + | +LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL - use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}}; +LL + use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:93:13 + | +LL | makro, + | ^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use issue_59764::{makro, +LL | foobaz, +LL | foo::{ +LL | baz, +LL ~ + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:102:9 + | +LL | use issue_59764::foo::makro as baz; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::makro as baz; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:107:33 + | +LL | use issue_59764::foo::{baz, makro as foobar}; + | ^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL - use issue_59764::foo::{baz, makro as foobar}; +LL + use issue_59764::{makro as foobar, foo::{baz}}; + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:120:17 + | +LL | makro as foobar} + | ^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ issue_59764::{makro as foobar, +LL | + ... +LL | +LL ~ foo::{baz} + | + +error[E0432]: unresolved import `issue_59764::foo::makro` + --> $DIR/issue-59764.rs:127:5 + | +LL | use issue_59764::foo::makro; + | ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL | use issue_59764::makro; + | ~~~~~~~~~~~~~~~~~~ + +error: cannot determine resolution for the macro `makro` + --> $DIR/issue-59764.rs:130:1 + | +LL | makro!(bar); + | ^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/issue-59764.rs:134:5 + | +LL | bar(); + | ^^^ not found in this scope + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0425, E0432. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/issue-62767.rs b/tests/ui/imports/issue-62767.rs new file mode 100644 index 000000000..01184eea9 --- /dev/null +++ b/tests/ui/imports/issue-62767.rs @@ -0,0 +1,30 @@ +// check-pass + +// Minimized case from #62767. +mod m { + pub enum Same { + Same, + } +} + +use m::*; + +// The variant `Same` introduced by this import is also considered when resolving the prefix +// `Same::` during import validation to avoid effects similar to time travel (#74556). +use Same::Same; + +// Case from #74556. +mod foo { + pub mod bar { + pub mod bar { + pub fn foobar() {} + } + } +} + +use foo::*; +use bar::bar; + +use bar::foobar; + +fn main() {} diff --git a/tests/ui/imports/issue-68103.rs b/tests/ui/imports/issue-68103.rs new file mode 100644 index 000000000..e775678fc --- /dev/null +++ b/tests/ui/imports/issue-68103.rs @@ -0,0 +1,6 @@ +// check-pass + +pub extern crate self as name; +pub use name::name as bug; + +fn main() {} diff --git a/tests/ui/imports/issue-8208.rs b/tests/ui/imports/issue-8208.rs new file mode 100644 index 000000000..1c566938f --- /dev/null +++ b/tests/ui/imports/issue-8208.rs @@ -0,0 +1,17 @@ +use self::*; //~ ERROR: unresolved import `self::*` [E0432] + //~^ cannot glob-import a module into itself + +mod foo { + use foo::*; //~ ERROR: unresolved import `foo::*` [E0432] + //~^ cannot glob-import a module into itself + + mod bar { + use super::bar::*; + //~^ ERROR: unresolved import `super::bar::*` [E0432] + //~| cannot glob-import a module into itself + } + +} + +fn main() { +} diff --git a/tests/ui/imports/issue-8208.stderr b/tests/ui/imports/issue-8208.stderr new file mode 100644 index 000000000..e59aea12c --- /dev/null +++ b/tests/ui/imports/issue-8208.stderr @@ -0,0 +1,21 @@ +error[E0432]: unresolved import `self::*` + --> $DIR/issue-8208.rs:1:5 + | +LL | use self::*; + | ^^^^^^^ cannot glob-import a module into itself + +error[E0432]: unresolved import `foo::*` + --> $DIR/issue-8208.rs:5:9 + | +LL | use foo::*; + | ^^^^^^ cannot glob-import a module into itself + +error[E0432]: unresolved import `super::bar::*` + --> $DIR/issue-8208.rs:9:13 + | +LL | use super::bar::*; + | ^^^^^^^^^^^^^ cannot glob-import a module into itself + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-8640.rs b/tests/ui/imports/issue-8640.rs new file mode 100644 index 000000000..51a02a32e --- /dev/null +++ b/tests/ui/imports/issue-8640.rs @@ -0,0 +1,10 @@ +#[allow(unused_imports)] + +mod foo { + use baz::bar; + mod bar {} + //~^ ERROR the name `bar` is defined multiple times +} +mod baz { pub mod bar {} } + +fn main() {} diff --git a/tests/ui/imports/issue-8640.stderr b/tests/ui/imports/issue-8640.stderr new file mode 100644 index 000000000..ab44f067f --- /dev/null +++ b/tests/ui/imports/issue-8640.stderr @@ -0,0 +1,17 @@ +error[E0255]: the name `bar` is defined multiple times + --> $DIR/issue-8640.rs:5:5 + | +LL | use baz::bar; + | -------- previous import of the module `bar` here +LL | mod bar {} + | ^^^^^^^ `bar` redefined here + | + = note: `bar` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use baz::bar as other_bar; + | ~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed new file mode 100644 index 000000000..0e60c73b6 --- /dev/null +++ b/tests/ui/imports/issue-99695-b.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + + mod p { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + } + + use ::nu; +pub use self::p::{other_item as _}; + //~^ ERROR unresolved import `self::p::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695-b.rs b/tests/ui/imports/issue-99695-b.rs new file mode 100644 index 000000000..031443a1f --- /dev/null +++ b/tests/ui/imports/issue-99695-b.rs @@ -0,0 +1,19 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + + mod p { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + } + + pub use self::p::{nu, other_item as _}; + //~^ ERROR unresolved import `self::p::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695-b.stderr b/tests/ui/imports/issue-99695-b.stderr new file mode 100644 index 000000000..b6f5c726a --- /dev/null +++ b/tests/ui/imports/issue-99695-b.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `self::p::nu` + --> $DIR/issue-99695-b.rs:14:23 + | +LL | pub use self::p::{nu, other_item as _}; + | ^^ no `nu` in `m::p` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use ::nu; +LL ~ pub use self::p::{other_item as _}; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.fixed new file mode 100644 index 000000000..6bf228b23 --- /dev/null +++ b/tests/ui/imports/issue-99695.fixed @@ -0,0 +1,17 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + + use ::nu; +pub use self::{other_item as _}; + //~^ ERROR unresolved import `self::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs new file mode 100644 index 000000000..f7199f149 --- /dev/null +++ b/tests/ui/imports/issue-99695.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![allow(unused, nonstandard_style)] +mod m { + #[macro_export] + macro_rules! nu { + {} => {}; + } + + pub struct other_item; + + pub use self::{nu, other_item as _}; + //~^ ERROR unresolved import `self::nu` [E0432] + //~| HELP a macro with this name exists at the root of the crate +} + +fn main() {} diff --git a/tests/ui/imports/issue-99695.stderr b/tests/ui/imports/issue-99695.stderr new file mode 100644 index 000000000..0ef762e1c --- /dev/null +++ b/tests/ui/imports/issue-99695.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `self::nu` + --> $DIR/issue-99695.rs:11:20 + | +LL | pub use self::{nu, other_item as _}; + | ^^ no `nu` in `m` + | + = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined +help: a macro with this name exists at the root of the crate + | +LL ~ use ::nu; +LL ~ pub use self::{other_item as _}; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/local-modularized-tricky-fail-1.rs b/tests/ui/imports/local-modularized-tricky-fail-1.rs new file mode 100644 index 000000000..29e9b8ec8 --- /dev/null +++ b/tests/ui/imports/local-modularized-tricky-fail-1.rs @@ -0,0 +1,46 @@ +#![feature(decl_macro)] + +macro_rules! define_exported { () => { + #[macro_export] + macro_rules! exported { + () => () + } +}} +macro_rules! define_panic { () => { + #[macro_export] + macro_rules! panic { + () => () + } +}} +macro_rules! define_include { () => { + #[macro_export] + macro_rules! include { + () => () + } +}} + +use inner1::*; + +mod inner1 { + pub macro exported() {} +} + +exported!(); //~ ERROR `exported` is ambiguous + +mod inner2 { + define_exported!(); +} + +fn main() { + panic!(); //~ ERROR `panic` is ambiguous +} + +mod inner3 { + define_panic!(); +} + +mod inner4 { + define_include!(); +} + +include!(); //~ ERROR `include` is ambiguous diff --git a/tests/ui/imports/local-modularized-tricky-fail-1.stderr b/tests/ui/imports/local-modularized-tricky-fail-1.stderr new file mode 100644 index 000000000..20eadaaaa --- /dev/null +++ b/tests/ui/imports/local-modularized-tricky-fail-1.stderr @@ -0,0 +1,70 @@ +error[E0659]: `exported` is ambiguous + --> $DIR/local-modularized-tricky-fail-1.rs:28:1 + | +LL | exported!(); + | ^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution +note: `exported` could refer to the macro defined here + --> $DIR/local-modularized-tricky-fail-1.rs:5:5 + | +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_exported!(); + | ------------------ in this macro invocation +note: `exported` could also refer to the macro imported here + --> $DIR/local-modularized-tricky-fail-1.rs:22:5 + | +LL | use inner1::*; + | ^^^^^^^^^ + = help: consider adding an explicit import of `exported` to disambiguate + = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `panic` is ambiguous + --> $DIR/local-modularized-tricky-fail-1.rs:35:5 + | +LL | panic!(); + | ^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `panic` could refer to a macro from prelude +note: `panic` could also refer to the macro defined here + --> $DIR/local-modularized-tricky-fail-1.rs:11:5 + | +LL | / macro_rules! panic { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_panic!(); + | --------------- in this macro invocation + = help: use `crate::panic` to refer to this macro unambiguously + = note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `include` is ambiguous + --> $DIR/local-modularized-tricky-fail-1.rs:46:1 + | +LL | include!(); + | ^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `include` could refer to a macro from prelude +note: `include` could also refer to the macro defined here + --> $DIR/local-modularized-tricky-fail-1.rs:17:5 + | +LL | / macro_rules! include { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_include!(); + | ----------------- in this macro invocation + = help: use `crate::include` to refer to this macro unambiguously + = note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/local-modularized-tricky-fail-2.rs b/tests/ui/imports/local-modularized-tricky-fail-2.rs new file mode 100644 index 000000000..386de88bc --- /dev/null +++ b/tests/ui/imports/local-modularized-tricky-fail-2.rs @@ -0,0 +1,22 @@ +// Crate-local macro expanded `macro_export` macros cannot be accessed with module-relative paths. + +macro_rules! define_exported { () => { + #[macro_export] + macro_rules! exported { + () => () + } +}} + +define_exported!(); + +mod m { + use exported; + //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot + //~| WARN this was previously accepted +} + +fn main() { + ::exported!(); + //~^ ERROR macro-expanded `macro_export` macros from the current crate cannot + //~| WARN this was previously accepted +} diff --git a/tests/ui/imports/local-modularized-tricky-fail-2.stderr b/tests/ui/imports/local-modularized-tricky-fail-2.stderr new file mode 100644 index 000000000..2c1965ac0 --- /dev/null +++ b/tests/ui/imports/local-modularized-tricky-fail-2.stderr @@ -0,0 +1,43 @@ +error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths + --> $DIR/local-modularized-tricky-fail-2.rs:13:9 + | +LL | use exported; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #52234 +note: the macro is defined here + --> $DIR/local-modularized-tricky-fail-2.rs:5:5 + | +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_exported!(); + | ------------------ in this macro invocation + = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` on by default + = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths + --> $DIR/local-modularized-tricky-fail-2.rs:19:5 + | +LL | ::exported!(); + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #52234 +note: the macro is defined here + --> $DIR/local-modularized-tricky-fail-2.rs:5:5 + | +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_exported!(); + | ------------------ in this macro invocation + = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/imports/local-modularized-tricky-pass-1.rs b/tests/ui/imports/local-modularized-tricky-pass-1.rs new file mode 100644 index 000000000..b52ddaf89 --- /dev/null +++ b/tests/ui/imports/local-modularized-tricky-pass-1.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +macro_rules! define_exported { () => { + #[macro_export] + macro_rules! exported { + () => () + } +}} + +mod inner1 { + use super::*; + exported!(); +} + +mod inner2 { + define_exported!(); +} + +fn main() {} diff --git a/tests/ui/imports/local-modularized-tricky-pass-2.rs b/tests/ui/imports/local-modularized-tricky-pass-2.rs new file mode 100644 index 000000000..d5efbdf78 --- /dev/null +++ b/tests/ui/imports/local-modularized-tricky-pass-2.rs @@ -0,0 +1,50 @@ +// check-pass +// +// `#[macro_export] macro_rules` that doesn't originate from macro expansions can be placed +// into the root module soon enough to act as usual items and shadow globs and preludes. + +#![feature(decl_macro)] + +// `macro_export` shadows globs +use inner1::*; + +mod inner1 { + pub macro exported() {} +} + +exported!(); + +mod deep { + fn deep() { + type Deeper = [u8; { + #[macro_export] + macro_rules! exported { + () => ( struct Б; ) + } + + 0 + }]; + } +} + +// `macro_export` shadows std prelude +fn main() { + panic!(); +} + +mod inner3 { + #[macro_export] + macro_rules! panic { + () => ( struct Г; ) + } +} + +// `macro_export` shadows builtin macros +include!(); + +mod inner4 { + #[macro_export] + macro_rules! include { + () => ( struct Д; ) + } +} diff --git a/tests/ui/imports/local-modularized.rs b/tests/ui/imports/local-modularized.rs new file mode 100644 index 000000000..8eeb1cf07 --- /dev/null +++ b/tests/ui/imports/local-modularized.rs @@ -0,0 +1,35 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#[macro_export(local_inner_macros)] +macro_rules! dollar_crate_exported { + (1) => { $crate::exported!(); }; + (2) => { exported!(); }; +} + +// Before `exported` is defined +exported!(); + +mod inner { + + ::exported!(); + crate::exported!(); + dollar_crate_exported!(1); + dollar_crate_exported!(2); + + mod inner_inner { + #[macro_export] + macro_rules! exported { + () => () + } + } + + // After `exported` is defined + ::exported!(); + crate::exported!(); + dollar_crate_exported!(1); + dollar_crate_exported!(2); +} + +exported!(); + +fn main() {} diff --git a/tests/ui/imports/macro-paths.rs b/tests/ui/imports/macro-paths.rs new file mode 100644 index 000000000..cc584e05a --- /dev/null +++ b/tests/ui/imports/macro-paths.rs @@ -0,0 +1,28 @@ +// aux-build:two_macros.rs + +extern crate two_macros; + +mod foo { + pub mod bar { + pub use two_macros::m; + } +} + +fn f() { + use foo::*; + bar::m! { //~ ERROR ambiguous + mod bar { pub use two_macros::m; } + } +} + +pub mod baz { + pub use two_macros::m; +} + +fn g() { + baz::m! { //~ ERROR ambiguous + mod baz { pub use two_macros::m; } + } +} + +fn main() {} diff --git a/tests/ui/imports/macro-paths.stderr b/tests/ui/imports/macro-paths.stderr new file mode 100644 index 000000000..5f113ce2b --- /dev/null +++ b/tests/ui/imports/macro-paths.stderr @@ -0,0 +1,43 @@ +error[E0659]: `bar` is ambiguous + --> $DIR/macro-paths.rs:13:5 + | +LL | bar::m! { + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution +note: `bar` could refer to the module defined here + --> $DIR/macro-paths.rs:14:9 + | +LL | mod bar { pub use two_macros::m; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `bar` could also refer to the module imported here + --> $DIR/macro-paths.rs:12:9 + | +LL | use foo::*; + | ^^^^^^ + = help: consider adding an explicit import of `bar` to disambiguate + +error[E0659]: `baz` is ambiguous + --> $DIR/macro-paths.rs:23:5 + | +LL | baz::m! { + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `baz` could refer to the module defined here + --> $DIR/macro-paths.rs:24:9 + | +LL | mod baz { pub use two_macros::m; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `baz` could also refer to the module defined here + --> $DIR/macro-paths.rs:18:1 + | +LL | / pub mod baz { +LL | | pub use two_macros::m; +LL | | } + | |_^ + = help: use `crate::baz` to refer to this module unambiguously + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/macros.rs b/tests/ui/imports/macros.rs new file mode 100644 index 000000000..f2a22ad62 --- /dev/null +++ b/tests/ui/imports/macros.rs @@ -0,0 +1,41 @@ +// aux-build:two_macros.rs + +extern crate two_macros; // two identity macros `m` and `n` + +mod foo { + pub use two_macros::n as m; +} + +mod m1 { + m!(use two_macros::*;); + use foo::m; // This shadows the glob import +} + +mod m2 { + use two_macros::*; + m! { //~ ERROR ambiguous + use foo::m; + } +} + +mod m3 { + use two_macros::m; + fn f() { + use two_macros::n as m; // This shadows the above import + m!(); + } + + fn g() { + m! { //~ ERROR ambiguous + use two_macros::n as m; + } + } +} + +mod m4 { + macro_rules! m { () => {} } + use two_macros::m; + m!(); +} + +fn main() {} diff --git a/tests/ui/imports/macros.stderr b/tests/ui/imports/macros.stderr new file mode 100644 index 000000000..e34e5359b --- /dev/null +++ b/tests/ui/imports/macros.stderr @@ -0,0 +1,41 @@ +error[E0659]: `m` is ambiguous + --> $DIR/macros.rs:16:5 + | +LL | m! { + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution +note: `m` could refer to the macro imported here + --> $DIR/macros.rs:17:13 + | +LL | use foo::m; + | ^^^^^^ +note: `m` could also refer to the macro imported here + --> $DIR/macros.rs:15:9 + | +LL | use two_macros::*; + | ^^^^^^^^^^^^^ + = help: consider adding an explicit import of `m` to disambiguate + +error[E0659]: `m` is ambiguous + --> $DIR/macros.rs:29:9 + | +LL | m! { + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro imported here + --> $DIR/macros.rs:30:17 + | +LL | use two_macros::n as m; + | ^^^^^^^^^^^^^^^^^^ +note: `m` could also refer to the macro imported here + --> $DIR/macros.rs:22:9 + | +LL | use two_macros::m; + | ^^^^^^^^^^^^^ + = help: use `self::m` to refer to this macro unambiguously + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/no-std-inject.rs b/tests/ui/imports/no-std-inject.rs new file mode 100644 index 000000000..e9664a4dd --- /dev/null +++ b/tests/ui/imports/no-std-inject.rs @@ -0,0 +1,6 @@ +#![no_std] + +extern crate core; //~ ERROR: the name `core` is defined multiple times +extern crate std; + +fn main() {} diff --git a/tests/ui/imports/no-std-inject.stderr b/tests/ui/imports/no-std-inject.stderr new file mode 100644 index 000000000..8e2268048 --- /dev/null +++ b/tests/ui/imports/no-std-inject.stderr @@ -0,0 +1,15 @@ +error[E0259]: the name `core` is defined multiple times + --> $DIR/no-std-inject.rs:3:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ `core` reimported here + | + = note: `core` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate core as other_core; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/imports/overlapping_pub_trait.rs b/tests/ui/imports/overlapping_pub_trait.rs new file mode 100644 index 000000000..69aba3ae9 --- /dev/null +++ b/tests/ui/imports/overlapping_pub_trait.rs @@ -0,0 +1,15 @@ +// aux-build:overlapping_pub_trait_source.rs + +/* + * This crate declares two public paths, `m::Tr` and `prelude::_`. Make sure we prefer the former. + */ +extern crate overlapping_pub_trait_source; +//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: +//~| SUGGESTION overlapping_pub_trait_source::m::Tr + +fn main() { + use overlapping_pub_trait_source::S; + S.method(); + //~^ ERROR no method named `method` found for struct `S` in the current scope [E0599] + //~| HELP items from traits can only be used if the trait is in scope +} diff --git a/tests/ui/imports/overlapping_pub_trait.stderr b/tests/ui/imports/overlapping_pub_trait.stderr new file mode 100644 index 000000000..d0c845a5e --- /dev/null +++ b/tests/ui/imports/overlapping_pub_trait.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `method` found for struct `S` in the current scope + --> $DIR/overlapping_pub_trait.rs:12:7 + | +LL | S.method(); + | ^^^^^^ method not found in `S` + | + ::: $DIR/auxiliary/overlapping_pub_trait_source.rs:11:23 + | +LL | pub trait Tr { fn method(&self); } + | ------ the method is available for `S` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use overlapping_pub_trait_source::m::Tr; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/imports/reexport-star.rs b/tests/ui/imports/reexport-star.rs new file mode 100644 index 000000000..639ab1a0f --- /dev/null +++ b/tests/ui/imports/reexport-star.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +mod a { + pub fn f() {} + pub fn g() {} +} + +mod b { + pub use a::*; +} + +pub fn main() { + b::f(); + b::g(); +} diff --git a/tests/ui/imports/reexports.rs b/tests/ui/imports/reexports.rs new file mode 100644 index 000000000..d76cc41be --- /dev/null +++ b/tests/ui/imports/reexports.rs @@ -0,0 +1,37 @@ +#![warn(unused_imports)] + +mod a { + fn foo() {} + mod foo {} + + mod a { + pub use super::foo; //~ ERROR cannot be re-exported + pub use super::*; + //~^ WARNING glob import doesn't reexport anything because no candidate is public enough + } +} + +mod b { + pub fn foo() {} + mod foo { + pub struct S; + } + + pub mod a { + pub use super::foo; // This is OK since the value `foo` is visible enough. + fn f(_: foo::S) {} // `foo` is imported in the type namespace (but not `pub` re-exported). + } + + pub mod b { + pub use super::*; // This is also OK since the value `foo` is visible enough. + fn f(_: foo::S) {} // Again, the module `foo` is imported (but not `pub` re-exported). + } +} + +mod c { + // Test that `foo` is not re-exported. + use b::a::foo::S; //~ ERROR `foo` + use b::b::foo::S as T; //~ ERROR `foo` +} + +fn main() {} diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr new file mode 100644 index 000000000..8cbff0ac7 --- /dev/null +++ b/tests/ui/imports/reexports.stderr @@ -0,0 +1,62 @@ +error[E0364]: `foo` is private, and cannot be re-exported + --> $DIR/reexports.rs:8:17 + | +LL | pub use super::foo; + | ^^^^^^^^^^ + | +note: consider marking `foo` as `pub` in the imported module + --> $DIR/reexports.rs:8:17 + | +LL | pub use super::foo; + | ^^^^^^^^^^ + +error[E0603]: module import `foo` is private + --> $DIR/reexports.rs:33:15 + | +LL | use b::a::foo::S; + | ^^^ private module import + | +note: the module import `foo` is defined here... + --> $DIR/reexports.rs:21:17 + | +LL | pub use super::foo; // This is OK since the value `foo` is visible enough. + | ^^^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/reexports.rs:16:5 + | +LL | mod foo { + | ^^^^^^^ + +error[E0603]: module import `foo` is private + --> $DIR/reexports.rs:34:15 + | +LL | use b::b::foo::S as T; + | ^^^ private module import + | +note: the module import `foo` is defined here... + --> $DIR/reexports.rs:26:17 + | +LL | pub use super::*; // This is also OK since the value `foo` is visible enough. + | ^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/reexports.rs:16:5 + | +LL | mod foo { + | ^^^^^^^ + +warning: glob import doesn't reexport anything because no candidate is public enough + --> $DIR/reexports.rs:9:17 + | +LL | pub use super::*; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/reexports.rs:1:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0364, E0603. +For more information about an error, try `rustc --explain E0364`. diff --git a/tests/ui/imports/resolve_self_super_hint.rs b/tests/ui/imports/resolve_self_super_hint.rs new file mode 100644 index 000000000..a14ec5b72 --- /dev/null +++ b/tests/ui/imports/resolve_self_super_hint.rs @@ -0,0 +1,27 @@ +mod a { + extern crate alloc; + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::alloc + mod b { + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION super::alloc + mod c { + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION a::alloc + mod d { + use alloc::HashMap; + //~^ ERROR unresolved import `alloc` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION a::alloc + } + } + } +} + +fn main() {} diff --git a/tests/ui/imports/resolve_self_super_hint.stderr b/tests/ui/imports/resolve_self_super_hint.stderr new file mode 100644 index 000000000..bc862553b --- /dev/null +++ b/tests/ui/imports/resolve_self_super_hint.stderr @@ -0,0 +1,33 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:3:9 + | +LL | use alloc::HashMap; + | ^^^^^ help: a similar path exists: `self::alloc` + +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:8:13 + | +LL | use alloc::HashMap; + | ^^^^^ help: a similar path exists: `super::alloc` + +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:13:17 + | +LL | use alloc::HashMap; + | ^^^^^ + | | + | unresolved import + | help: a similar path exists: `a::alloc` + +error[E0432]: unresolved import `alloc` + --> $DIR/resolve_self_super_hint.rs:18:21 + | +LL | use alloc::HashMap; + | ^^^^^ + | | + | unresolved import + | help: a similar path exists: `a::alloc` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/rfc-1560-warning-cycle.rs b/tests/ui/imports/rfc-1560-warning-cycle.rs new file mode 100644 index 000000000..cfa7179fb --- /dev/null +++ b/tests/ui/imports/rfc-1560-warning-cycle.rs @@ -0,0 +1,13 @@ +pub struct Foo; + +mod bar { + struct Foo; + + mod baz { + use *; + use bar::*; + fn f(_: Foo) {} //~ ERROR `Foo` is ambiguous + } +} + +fn main() {} diff --git a/tests/ui/imports/rfc-1560-warning-cycle.stderr b/tests/ui/imports/rfc-1560-warning-cycle.stderr new file mode 100644 index 000000000..fd7e99165 --- /dev/null +++ b/tests/ui/imports/rfc-1560-warning-cycle.stderr @@ -0,0 +1,23 @@ +error[E0659]: `Foo` is ambiguous + --> $DIR/rfc-1560-warning-cycle.rs:9:17 + | +LL | fn f(_: Foo) {} + | ^^^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `Foo` could refer to the struct imported here + --> $DIR/rfc-1560-warning-cycle.rs:7:13 + | +LL | use *; + | ^ + = help: consider adding an explicit import of `Foo` to disambiguate +note: `Foo` could also refer to the struct imported here + --> $DIR/rfc-1560-warning-cycle.rs:8:13 + | +LL | use bar::*; + | ^^^^^^ + = help: consider adding an explicit import of `Foo` to disambiguate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/shadow_builtin_macros.rs b/tests/ui/imports/shadow_builtin_macros.rs new file mode 100644 index 000000000..02c27d5ce --- /dev/null +++ b/tests/ui/imports/shadow_builtin_macros.rs @@ -0,0 +1,52 @@ +// aux-build:two_macros.rs + +mod foo { + extern crate two_macros; + pub use self::two_macros::m as panic; +} + +mod m1 { + use foo::panic; // ok + fn f() { panic!(); } +} + +mod m2 { + use foo::*; + fn f() { panic!(); } //~ ERROR ambiguous +} + +mod m3 { + ::two_macros::m!(use foo::panic;); + fn f() { panic!(); } //~ ERROR ambiguous +} + +mod m4 { + macro_rules! panic { () => {} } // ok + panic!(); +} + +mod m5 { + macro_rules! m { () => { + macro_rules! panic { () => {} } + } } + m!(); + panic!(); //~ ERROR `panic` is ambiguous +} + +#[macro_use(n)] +extern crate two_macros; +mod bar { + pub use two_macros::m as n; +} + +mod m6 { + use bar::n; // ok + n!(); +} + +mod m7 { + use bar::*; + n!(); //~ ERROR ambiguous +} + +fn main() {} diff --git a/tests/ui/imports/shadow_builtin_macros.stderr b/tests/ui/imports/shadow_builtin_macros.stderr new file mode 100644 index 000000000..6ffb31c20 --- /dev/null +++ b/tests/ui/imports/shadow_builtin_macros.stderr @@ -0,0 +1,72 @@ +error[E0659]: `panic` is ambiguous + --> $DIR/shadow_builtin_macros.rs:15:14 + | +LL | fn f() { panic!(); } + | ^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution + = note: `panic` could refer to a macro from prelude +note: `panic` could also refer to the macro imported here + --> $DIR/shadow_builtin_macros.rs:14:9 + | +LL | use foo::*; + | ^^^^^^ + = help: consider adding an explicit import of `panic` to disambiguate + = help: or use `self::panic` to refer to this macro unambiguously + +error[E0659]: `panic` is ambiguous + --> $DIR/shadow_builtin_macros.rs:33:5 + | +LL | panic!(); + | ^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `panic` could refer to a macro from prelude +note: `panic` could also refer to the macro defined here + --> $DIR/shadow_builtin_macros.rs:30:9 + | +LL | macro_rules! panic { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | } } +LL | m!(); + | ---- in this macro invocation + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `n` is ambiguous + --> $DIR/shadow_builtin_macros.rs:49:5 + | +LL | n!(); + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution +note: `n` could refer to the macro imported here + --> $DIR/shadow_builtin_macros.rs:48:9 + | +LL | use bar::*; + | ^^^^^^ + = help: consider adding an explicit import of `n` to disambiguate + = help: or use `self::n` to refer to this macro unambiguously +note: `n` could also refer to the macro imported here + --> $DIR/shadow_builtin_macros.rs:36:13 + | +LL | #[macro_use(n)] + | ^ + +error[E0659]: `panic` is ambiguous + --> $DIR/shadow_builtin_macros.rs:20:14 + | +LL | fn f() { panic!(); } + | ^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `panic` could refer to a macro from prelude +note: `panic` could also refer to the macro imported here + --> $DIR/shadow_builtin_macros.rs:19:26 + | +LL | ::two_macros::m!(use foo::panic;); + | ^^^^^^^^^^ + = help: use `self::panic` to refer to this macro unambiguously + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/tool-mod-child.rs b/tests/ui/imports/tool-mod-child.rs new file mode 100644 index 000000000..4581dc2e2 --- /dev/null +++ b/tests/ui/imports/tool-mod-child.rs @@ -0,0 +1,7 @@ +use clippy::a; //~ ERROR unresolved import `clippy` +use clippy::a::b; //~ ERROR failed to resolve: maybe a missing crate `clippy`? + +use rustdoc::a; //~ ERROR unresolved import `rustdoc` +use rustdoc::a::b; //~ ERROR failed to resolve: maybe a missing crate `rustdoc`? + +fn main() {} diff --git a/tests/ui/imports/tool-mod-child.stderr b/tests/ui/imports/tool-mod-child.stderr new file mode 100644 index 000000000..6caf15bc7 --- /dev/null +++ b/tests/ui/imports/tool-mod-child.stderr @@ -0,0 +1,36 @@ +error[E0433]: failed to resolve: maybe a missing crate `clippy`? + --> $DIR/tool-mod-child.rs:2:5 + | +LL | use clippy::a::b; + | ^^^^^^ maybe a missing crate `clippy`? + | + = help: consider adding `extern crate clippy` to use the `clippy` crate + +error[E0432]: unresolved import `clippy` + --> $DIR/tool-mod-child.rs:1:5 + | +LL | use clippy::a; + | ^^^^^^ maybe a missing crate `clippy`? + | + = help: consider adding `extern crate clippy` to use the `clippy` crate + +error[E0433]: failed to resolve: maybe a missing crate `rustdoc`? + --> $DIR/tool-mod-child.rs:5:5 + | +LL | use rustdoc::a::b; + | ^^^^^^^ maybe a missing crate `rustdoc`? + | + = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate + +error[E0432]: unresolved import `rustdoc` + --> $DIR/tool-mod-child.rs:4:5 + | +LL | use rustdoc::a; + | ^^^^^^^ maybe a missing crate `rustdoc`? + | + = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/unnamed_pub_trait.rs b/tests/ui/imports/unnamed_pub_trait.rs new file mode 100644 index 000000000..c38fb17b9 --- /dev/null +++ b/tests/ui/imports/unnamed_pub_trait.rs @@ -0,0 +1,16 @@ +// aux-build:unnamed_pub_trait_source.rs + +/* + * This crate declares an unnameable public path for our item. Make sure we don't suggest + * importing it by name, and instead we suggest importing it by glob. + */ +extern crate unnamed_pub_trait_source; +//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: +//~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr + +fn main() { + use unnamed_pub_trait_source::S; + S.method(); + //~^ ERROR no method named `method` found for struct `S` in the current scope [E0599] + //~| HELP items from traits can only be used if the trait is in scope +} diff --git a/tests/ui/imports/unnamed_pub_trait.stderr b/tests/ui/imports/unnamed_pub_trait.stderr new file mode 100644 index 000000000..319dfd7e1 --- /dev/null +++ b/tests/ui/imports/unnamed_pub_trait.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `method` found for struct `S` in the current scope + --> $DIR/unnamed_pub_trait.rs:13:7 + | +LL | S.method(); + | ^^^^^^ method not found in `S` + | + ::: $DIR/auxiliary/unnamed_pub_trait_source.rs:7:23 + | +LL | pub trait Tr { fn method(&self); } + | ------ the method is available for `S` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use unnamed_pub_trait_source::prelude::*; // trait Tr + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/imports/unresolved-imports-used.rs b/tests/ui/imports/unresolved-imports-used.rs new file mode 100644 index 000000000..75cf88019 --- /dev/null +++ b/tests/ui/imports/unresolved-imports-used.rs @@ -0,0 +1,18 @@ +// There should be *one* unused import error. +#![deny(unused_imports)] + +mod qux { + fn quz() {} + pub fn quy() {} +} + +use qux::quz; //~ ERROR function `quz` is private +use qux::bar; //~ ERROR unresolved import `qux::bar` +use foo::bar; //~ ERROR unresolved import `foo` +use baz::*; //~ ERROR unresolved import `baz` +use qux::bar2; //~ ERROR unresolved import `qux::bar2` +use foo2::bar2;//~ ERROR unresolved import `foo2` +use baz2::*; //~ ERROR unresolved import `baz2` +use qux::quy; //~ ERROR unused import + +fn main() {} diff --git a/tests/ui/imports/unresolved-imports-used.stderr b/tests/ui/imports/unresolved-imports-used.stderr new file mode 100644 index 000000000..73f9d1bfb --- /dev/null +++ b/tests/ui/imports/unresolved-imports-used.stderr @@ -0,0 +1,72 @@ +error[E0432]: unresolved import `qux::bar` + --> $DIR/unresolved-imports-used.rs:10:5 + | +LL | use qux::bar; + | ^^^^^^^^ no `bar` in `qux` + +error[E0432]: unresolved import `qux::bar2` + --> $DIR/unresolved-imports-used.rs:13:5 + | +LL | use qux::bar2; + | ^^^^^^^^^ no `bar2` in `qux` + +error[E0432]: unresolved import `foo` + --> $DIR/unresolved-imports-used.rs:11:5 + | +LL | use foo::bar; + | ^^^ maybe a missing crate `foo`? + | + = help: consider adding `extern crate foo` to use the `foo` crate + +error[E0432]: unresolved import `baz` + --> $DIR/unresolved-imports-used.rs:12:5 + | +LL | use baz::*; + | ^^^ maybe a missing crate `baz`? + | + = help: consider adding `extern crate baz` to use the `baz` crate + +error[E0432]: unresolved import `foo2` + --> $DIR/unresolved-imports-used.rs:14:5 + | +LL | use foo2::bar2; + | ^^^^ maybe a missing crate `foo2`? + | + = help: consider adding `extern crate foo2` to use the `foo2` crate + +error[E0432]: unresolved import `baz2` + --> $DIR/unresolved-imports-used.rs:15:5 + | +LL | use baz2::*; + | ^^^^ maybe a missing crate `baz2`? + | + = help: consider adding `extern crate baz2` to use the `baz2` crate + +error[E0603]: function `quz` is private + --> $DIR/unresolved-imports-used.rs:9:10 + | +LL | use qux::quz; + | ^^^ private function + | +note: the function `quz` is defined here + --> $DIR/unresolved-imports-used.rs:5:4 + | +LL | fn quz() {} + | ^^^^^^^^ + +error: unused import: `qux::quy` + --> $DIR/unresolved-imports-used.rs:16:5 + | +LL | use qux::quy; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unresolved-imports-used.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0432, E0603. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/unused-import-issue-87973.fixed b/tests/ui/imports/unused-import-issue-87973.fixed new file mode 100644 index 000000000..5c194d18a --- /dev/null +++ b/tests/ui/imports/unused-import-issue-87973.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#![deny(unused_imports)] + +// Check that attributes get removed too. See #87973. + +//~^ ERROR unused import + +fn main() {} diff --git a/tests/ui/imports/unused-import-issue-87973.rs b/tests/ui/imports/unused-import-issue-87973.rs new file mode 100644 index 000000000..c31f0f979 --- /dev/null +++ b/tests/ui/imports/unused-import-issue-87973.rs @@ -0,0 +1,11 @@ +// run-rustfix +#![deny(unused_imports)] + +// Check that attributes get removed too. See #87973. +#[deprecated] +#[allow(unsafe_code)] +#[cfg(not(foo))] +use std::fs; +//~^ ERROR unused import + +fn main() {} diff --git a/tests/ui/imports/unused-import-issue-87973.stderr b/tests/ui/imports/unused-import-issue-87973.stderr new file mode 100644 index 000000000..81b7ea791 --- /dev/null +++ b/tests/ui/imports/unused-import-issue-87973.stderr @@ -0,0 +1,14 @@ +error: unused import: `std::fs` + --> $DIR/unused-import-issue-87973.rs:8:5 + | +LL | use std::fs; + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-import-issue-87973.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/imports/unused-imports-in-test-mode.rs b/tests/ui/imports/unused-imports-in-test-mode.rs new file mode 100644 index 000000000..039f59a88 --- /dev/null +++ b/tests/ui/imports/unused-imports-in-test-mode.rs @@ -0,0 +1,102 @@ +// compile-flags: --test + +#![deny(unused_imports)] + +use std::io::BufRead; //~ ERROR unused import: `std::io::BufRead` + +fn a() {} +fn b() {} + +mod test { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod tests { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod test_a { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod a_test { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod tests_a { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod a_tests { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod fastest_search { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +#[cfg(test)] +mod test_has_attr { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +mod test_has_no_attr { + #[cfg(test)] + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; //~ ERROR unused import: `crate::b` + } +} + +fn main() {} diff --git a/tests/ui/imports/unused-imports-in-test-mode.stderr b/tests/ui/imports/unused-imports-in-test-mode.stderr new file mode 100644 index 000000000..c5faaa114 --- /dev/null +++ b/tests/ui/imports/unused-imports-in-test-mode.stderr @@ -0,0 +1,68 @@ +error: unused import: `std::io::BufRead` + --> $DIR/unused-imports-in-test-mode.rs:5:5 + | +LL | use std::io::BufRead; + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-imports-in-test-mode.rs:3:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:16:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:26:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:36:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:46:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:56:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:66:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:76:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:87:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: unused import: `crate::b` + --> $DIR/unused-imports-in-test-mode.rs:98:13 + | +LL | use crate::b; + | ^^^^^^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/imports/unused-imports-in-test-module.rs b/tests/ui/imports/unused-imports-in-test-module.rs new file mode 100644 index 000000000..7849c3fcd --- /dev/null +++ b/tests/ui/imports/unused-imports-in-test-module.rs @@ -0,0 +1,89 @@ +#![deny(unused_imports)] + +use std::io::BufRead; //~ ERROR unused import: `std::io::BufRead` + +fn a() {} +fn b() {} + +mod test { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +mod tests { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +mod test_a { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +mod a_test { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +mod tests_a { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +mod a_tests { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +mod fastest_search { + use super::a; //~ ERROR unused import: `super::a` + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +#[cfg(test)] +mod test_has_attr { + use super::a; + + #[test] + fn foo() { + a(); + use crate::b; + } +} + +fn main() {} diff --git a/tests/ui/imports/unused-imports-in-test-module.stderr b/tests/ui/imports/unused-imports-in-test-module.stderr new file mode 100644 index 000000000..1598368eb --- /dev/null +++ b/tests/ui/imports/unused-imports-in-test-module.stderr @@ -0,0 +1,92 @@ +error: unused import: `std::io::BufRead` + --> $DIR/unused-imports-in-test-module.rs:3:5 + | +LL | use std::io::BufRead; + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-imports-in-test-module.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:9:9 + | +LL | use super::a; + | ^^^^^^^^ + | +help: consider adding a `#[cfg(test)]` to the containing module + --> $DIR/unused-imports-in-test-module.rs:8:1 + | +LL | mod test { + | ^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:19:9 + | +LL | use super::a; + | ^^^^^^^^ + | +help: consider adding a `#[cfg(test)]` to the containing module + --> $DIR/unused-imports-in-test-module.rs:18:1 + | +LL | mod tests { + | ^^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:29:9 + | +LL | use super::a; + | ^^^^^^^^ + | +help: consider adding a `#[cfg(test)]` to the containing module + --> $DIR/unused-imports-in-test-module.rs:28:1 + | +LL | mod test_a { + | ^^^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:39:9 + | +LL | use super::a; + | ^^^^^^^^ + | +help: consider adding a `#[cfg(test)]` to the containing module + --> $DIR/unused-imports-in-test-module.rs:38:1 + | +LL | mod a_test { + | ^^^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:49:9 + | +LL | use super::a; + | ^^^^^^^^ + | +help: consider adding a `#[cfg(test)]` to the containing module + --> $DIR/unused-imports-in-test-module.rs:48:1 + | +LL | mod tests_a { + | ^^^^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:59:9 + | +LL | use super::a; + | ^^^^^^^^ + | +help: consider adding a `#[cfg(test)]` to the containing module + --> $DIR/unused-imports-in-test-module.rs:58:1 + | +LL | mod a_tests { + | ^^^^^^^^^^^ + +error: unused import: `super::a` + --> $DIR/unused-imports-in-test-module.rs:69:9 + | +LL | use super::a; + | ^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/imports/unused-macro-use.rs b/tests/ui/imports/unused-macro-use.rs new file mode 100644 index 000000000..9f63eb4b4 --- /dev/null +++ b/tests/ui/imports/unused-macro-use.rs @@ -0,0 +1,11 @@ +#![deny(unused)] + +#[macro_use] //~ ERROR unused `#[macro_use]` import +extern crate core; + +#[macro_use( + panic //~ ERROR unused `#[macro_use]` import +)] +extern crate core as core_2; + +fn main() {} diff --git a/tests/ui/imports/unused-macro-use.stderr b/tests/ui/imports/unused-macro-use.stderr new file mode 100644 index 000000000..7137a90e4 --- /dev/null +++ b/tests/ui/imports/unused-macro-use.stderr @@ -0,0 +1,21 @@ +error: unused `#[macro_use]` import + --> $DIR/unused-macro-use.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-use.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(unused)]` + +error: unused `#[macro_use]` import + --> $DIR/unused-macro-use.rs:7:5 + | +LL | panic + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/imports/unused.rs b/tests/ui/imports/unused.rs new file mode 100644 index 000000000..c22e95ec3 --- /dev/null +++ b/tests/ui/imports/unused.rs @@ -0,0 +1,27 @@ +#![deny(unused)] + +mod foo { + fn f() {} + + mod m1 { + pub(super) use super::f; //~ ERROR unused + } + + mod m2 { + #[allow(unused)] + use super::m1::*; // (despite this glob import) + } + + mod m3 { + pub(super) use super::f; // Check that this is counted as used (cf. issue #36249). + } + + pub mod m4 { + use super::m3::*; + pub fn g() { f(); } + } +} + +fn main() { + foo::m4::g(); +} diff --git a/tests/ui/imports/unused.stderr b/tests/ui/imports/unused.stderr new file mode 100644 index 000000000..08128d794 --- /dev/null +++ b/tests/ui/imports/unused.stderr @@ -0,0 +1,15 @@ +error: unused import: `super::f` + --> $DIR/unused.rs:7:24 + | +LL | pub(super) use super::f; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/imports/use-mod.rs b/tests/ui/imports/use-mod.rs new file mode 100644 index 000000000..84da2e708 --- /dev/null +++ b/tests/ui/imports/use-mod.rs @@ -0,0 +1,33 @@ +// run-pass + +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 + +pub use foo::bar::{self, First}; +use self::bar::Second; + +mod foo { + pub use self::bar::baz::{self}; + + pub mod bar { + pub mod baz { + pub struct Fourth; + } + pub struct First; + pub struct Second; + } + + pub struct Third; +} + +mod baz { + use super::foo::{bar, self}; + pub use foo::Third; +} + +fn main() { + let _ = First; + let _ = Second; + let _ = baz::Third; + let _ = foo::baz::Fourth; +} diff --git a/tests/ui/impossible_range.fixed b/tests/ui/impossible_range.fixed new file mode 100644 index 000000000..3fd950e0d --- /dev/null +++ b/tests/ui/impossible_range.fixed @@ -0,0 +1,20 @@ +// run-rustfix +// Make sure that invalid ranges generate an error during parsing, not an ICE + +#![allow(path_statements)] + +pub fn main() { + ..; + 0..; + ..1; + 0..1; + ..; //~ERROR inclusive range with no end + //~^HELP use `..` instead +} + +fn _foo1() { + ..=1; + 0..=1; + 0..; //~ERROR inclusive range with no end + //~^HELP use `..` instead +} diff --git a/tests/ui/impossible_range.rs b/tests/ui/impossible_range.rs new file mode 100644 index 000000000..0fe0e17be --- /dev/null +++ b/tests/ui/impossible_range.rs @@ -0,0 +1,20 @@ +// run-rustfix +// Make sure that invalid ranges generate an error during parsing, not an ICE + +#![allow(path_statements)] + +pub fn main() { + ..; + 0..; + ..1; + 0..1; + ..=; //~ERROR inclusive range with no end + //~^HELP use `..` instead +} + +fn _foo1() { + ..=1; + 0..=1; + 0..=; //~ERROR inclusive range with no end + //~^HELP use `..` instead +} diff --git a/tests/ui/impossible_range.stderr b/tests/ui/impossible_range.stderr new file mode 100644 index 000000000..53c56065c --- /dev/null +++ b/tests/ui/impossible_range.stderr @@ -0,0 +1,19 @@ +error[E0586]: inclusive range with no end + --> $DIR/impossible_range.rs:11:5 + | +LL | ..=; + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/impossible_range.rs:18:6 + | +LL | 0..=; + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/inc-range-pat.rs b/tests/ui/inc-range-pat.rs new file mode 100644 index 000000000..1eb7dd0aa --- /dev/null +++ b/tests/ui/inc-range-pat.rs @@ -0,0 +1,12 @@ +// run-pass +// Test old and new syntax for inclusive range patterns. + +#![allow(ellipsis_inclusive_range_patterns)] + +fn main() { + assert!(match 42 { 0 ... 100 => true, _ => false }); + assert!(match 42 { 0 ..= 100 => true, _ => false }); + + assert!(match 'x' { 'a' ... 'z' => true, _ => false }); + assert!(match 'x' { 'a' ..= 'z' => true, _ => false }); +} diff --git a/tests/ui/include-macros/auxiliary/same-file-in-two-crates-aux.rs b/tests/ui/include-macros/auxiliary/same-file-in-two-crates-aux.rs new file mode 100644 index 000000000..7b680bce4 --- /dev/null +++ b/tests/ui/include-macros/auxiliary/same-file-in-two-crates-aux.rs @@ -0,0 +1,4 @@ +#[inline] +pub fn some_function() -> u32 { + 1 +} diff --git a/tests/ui/include-macros/data.bin b/tests/ui/include-macros/data.bin new file mode 100644 index 000000000..ce4e0b831 --- /dev/null +++ b/tests/ui/include-macros/data.bin @@ -0,0 +1,2 @@ +This file starts with BOM. +Lines are separated by \r\n. diff --git a/tests/ui/include-macros/file.txt b/tests/ui/include-macros/file.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/include-macros/mismatched-types.rs b/tests/ui/include-macros/mismatched-types.rs new file mode 100644 index 000000000..83fa378a3 --- /dev/null +++ b/tests/ui/include-macros/mismatched-types.rs @@ -0,0 +1,4 @@ +fn main() { + let b: &[u8] = include_str!("file.txt"); //~ ERROR mismatched types + let s: &str = include_bytes!("file.txt"); //~ ERROR mismatched types +} diff --git a/tests/ui/include-macros/mismatched-types.stderr b/tests/ui/include-macros/mismatched-types.stderr new file mode 100644 index 000000000..a408877af --- /dev/null +++ b/tests/ui/include-macros/mismatched-types.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/mismatched-types.rs:2:20 + | +LL | let b: &[u8] = include_str!("file.txt"); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str` + | | + | expected due to this + | + = note: expected reference `&[u8]` + found reference `&'static str` + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/mismatched-types.rs:3:19 + | +LL | let s: &str = include_bytes!("file.txt"); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `str`, found array `[u8; 0]` + | | + | expected due to this + | + = note: expected reference `&str` + found reference `&'static [u8; 0]` + = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/include-macros/normalization.rs b/tests/ui/include-macros/normalization.rs new file mode 100644 index 000000000..889f08e60 --- /dev/null +++ b/tests/ui/include-macros/normalization.rs @@ -0,0 +1,12 @@ +// run-pass + +fn main() { + assert_eq!( + &include_bytes!("data.bin")[..], + &b"\xEF\xBB\xBFThis file starts with BOM.\r\nLines are separated by \\r\\n.\r\n"[..], + ); + assert_eq!( + include_str!("data.bin"), + "\u{FEFF}This file starts with BOM.\r\nLines are separated by \\r\\n.\r\n", + ); +} diff --git a/tests/ui/include-macros/same-file-in-two-crates.rs b/tests/ui/include-macros/same-file-in-two-crates.rs new file mode 100644 index 000000000..f49efa2cf --- /dev/null +++ b/tests/ui/include-macros/same-file-in-two-crates.rs @@ -0,0 +1,21 @@ +// This test makes sure that the compiler can handle the same source file to be +// part of the local crate *and* an upstream crate. This can happen, for example, +// when there is some auto-generated code that is part of both a library and an +// accompanying integration test. +// +// The test uses include!() to include a source file that is also part of +// an upstream crate. +// +// This is a regression test for https://github.com/rust-lang/rust/issues/85955. + +// check-pass +// compile-flags: --crate-type=rlib +// aux-build:same-file-in-two-crates-aux.rs +extern crate same_file_in_two_crates_aux; + +pub fn foo() -> u32 { + same_file_in_two_crates_aux::some_function() + + some_function() +} + +include!("./auxiliary/same-file-in-two-crates-aux.rs"); diff --git a/tests/ui/incoherent-inherent-impls/auxiliary/extern-crate.rs b/tests/ui/incoherent-inherent-impls/auxiliary/extern-crate.rs new file mode 100644 index 000000000..22f0d912c --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/auxiliary/extern-crate.rs @@ -0,0 +1,9 @@ +#![feature(rustc_attrs)] + +#[rustc_has_incoherent_inherent_impls] +pub struct StructWithAttr; +pub struct StructNoAttr; + +#[rustc_has_incoherent_inherent_impls] +pub enum EnumWithAttr {} +pub enum EnumNoAttr {} diff --git a/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.rs b/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.rs new file mode 100644 index 000000000..0f7282bec --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.rs @@ -0,0 +1,40 @@ +// aux-build:extern-crate.rs +#![feature(rustc_attrs)] +extern crate extern_crate; + +impl extern_crate::StructWithAttr { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate + fn foo() {} +} +impl extern_crate::StructWithAttr { + #[rustc_allow_incoherent_impl] + fn bar() {} +} +impl extern_crate::StructNoAttr { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate + fn foo() {} +} +impl extern_crate::StructNoAttr { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate + #[rustc_allow_incoherent_impl] + fn bar() {} +} +impl extern_crate::EnumWithAttr { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate + fn foo() {} +} +impl extern_crate::EnumWithAttr { + #[rustc_allow_incoherent_impl] + fn bar() {} +} +impl extern_crate::EnumNoAttr { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate + fn foo() {} +} +impl extern_crate::EnumNoAttr { + //~^ ERROR cannot define inherent `impl` for a type outside of the crate + #[rustc_allow_incoherent_impl] + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr b/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr new file mode 100644 index 000000000..8f7082511 --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr @@ -0,0 +1,115 @@ +error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/needs-has-incoherent-impls.rs:5:1 + | +LL | / impl extern_crate::StructWithAttr { +LL | | +LL | | fn foo() {} +LL | | } + | |_^ + | + = help: consider moving this inherent impl into the crate defining the type if possible +help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items + --> $DIR/needs-has-incoherent-impls.rs:7:5 + | +LL | fn foo() {} + | ^^^^^^^^^^^ + +error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/needs-has-incoherent-impls.rs:13:1 + | +LL | / impl extern_crate::StructNoAttr { +LL | | +LL | | fn foo() {} +LL | | } + | |_^ + | + = help: consider moving this inherent impl into the crate defining the type if possible +help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items + --> $DIR/needs-has-incoherent-impls.rs:13:1 + | +LL | / impl extern_crate::StructNoAttr { +LL | | +LL | | fn foo() {} +LL | | } + | |_^ + +error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/needs-has-incoherent-impls.rs:17:1 + | +LL | / impl extern_crate::StructNoAttr { +LL | | +LL | | #[rustc_allow_incoherent_impl] +LL | | fn bar() {} +LL | | } + | |_^ + | + = help: consider moving this inherent impl into the crate defining the type if possible +help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items + --> $DIR/needs-has-incoherent-impls.rs:17:1 + | +LL | / impl extern_crate::StructNoAttr { +LL | | +LL | | #[rustc_allow_incoherent_impl] +LL | | fn bar() {} +LL | | } + | |_^ + +error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/needs-has-incoherent-impls.rs:22:1 + | +LL | / impl extern_crate::EnumWithAttr { +LL | | +LL | | fn foo() {} +LL | | } + | |_^ + | + = help: consider moving this inherent impl into the crate defining the type if possible +help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items + --> $DIR/needs-has-incoherent-impls.rs:24:5 + | +LL | fn foo() {} + | ^^^^^^^^^^^ + +error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/needs-has-incoherent-impls.rs:30:1 + | +LL | / impl extern_crate::EnumNoAttr { +LL | | +LL | | fn foo() {} +LL | | } + | |_^ + | + = help: consider moving this inherent impl into the crate defining the type if possible +help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items + --> $DIR/needs-has-incoherent-impls.rs:30:1 + | +LL | / impl extern_crate::EnumNoAttr { +LL | | +LL | | fn foo() {} +LL | | } + | |_^ + +error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/needs-has-incoherent-impls.rs:34:1 + | +LL | / impl extern_crate::EnumNoAttr { +LL | | +LL | | #[rustc_allow_incoherent_impl] +LL | | fn bar() {} +LL | | } + | |_^ + | + = help: consider moving this inherent impl into the crate defining the type if possible +help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items + --> $DIR/needs-has-incoherent-impls.rs:34:1 + | +LL | / impl extern_crate::EnumNoAttr { +LL | | +LL | | #[rustc_allow_incoherent_impl] +LL | | fn bar() {} +LL | | } + | |_^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0390`. diff --git a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.rs b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.rs new file mode 100644 index 000000000..62c249e58 --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.rs @@ -0,0 +1,18 @@ +// aux-build:extern-crate.rs +extern crate extern_crate; + +impl extern_crate::StructWithAttr {} +//~^ ERROR cannot define inherent `impl` for a type outside of the crate + +impl extern_crate::StructNoAttr {} +//~^ ERROR cannot define inherent `impl` for a type outside of the crate + +impl extern_crate::EnumWithAttr {} +//~^ ERROR cannot define inherent `impl` for a type outside of the crate + +impl extern_crate::EnumNoAttr {} +//~^ ERROR cannot define inherent `impl` for a type outside of the crate + +impl f32 {} //~ ERROR cannot define inherent `impl` for primitive types + +fn main() {} diff --git a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr new file mode 100644 index 000000000..b3f8b51d0 --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr @@ -0,0 +1,44 @@ +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/no-attr-empty-impl.rs:4:1 + | +LL | impl extern_crate::StructWithAttr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/no-attr-empty-impl.rs:7:1 + | +LL | impl extern_crate::StructNoAttr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/no-attr-empty-impl.rs:10:1 + | +LL | impl extern_crate::EnumWithAttr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/no-attr-empty-impl.rs:13:1 + | +LL | impl extern_crate::EnumNoAttr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/no-attr-empty-impl.rs:16:6 + | +LL | impl f32 {} + | ^^^ + | + = help: consider using an extension trait instead + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0116, E0390. +For more information about an error, try `rustc --explain E0116`. diff --git a/tests/ui/index-bot.rs b/tests/ui/index-bot.rs new file mode 100644 index 000000000..e69c4019f --- /dev/null +++ b/tests/ui/index-bot.rs @@ -0,0 +1,3 @@ +fn main() { + (return)[0]; //~ ERROR cannot index into a value of type `!` +} diff --git a/tests/ui/index-bot.stderr b/tests/ui/index-bot.stderr new file mode 100644 index 000000000..b5d782975 --- /dev/null +++ b/tests/ui/index-bot.stderr @@ -0,0 +1,9 @@ +error[E0608]: cannot index into a value of type `!` + --> $DIR/index-bot.rs:2:5 + | +LL | (return)[0]; + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/index-help.rs b/tests/ui/index-help.rs new file mode 100644 index 000000000..66571ec41 --- /dev/null +++ b/tests/ui/index-help.rs @@ -0,0 +1,4 @@ +fn main() { + let x = vec![1]; + x[0i32]; //~ ERROR E0277 +} diff --git a/tests/ui/index-help.stderr b/tests/ui/index-help.stderr new file mode 100644 index 000000000..e020d0298 --- /dev/null +++ b/tests/ui/index-help.stderr @@ -0,0 +1,13 @@ +error[E0277]: the type `[{integer}]` cannot be indexed by `i32` + --> $DIR/index-help.rs:3:7 + | +LL | x[0i32]; + | ^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `Vec<{integer}>` to implement `Index` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/index_message.rs b/tests/ui/index_message.rs new file mode 100644 index 000000000..87e0cde59 --- /dev/null +++ b/tests/ui/index_message.rs @@ -0,0 +1,4 @@ +fn main() { + let z = (); + let _ = z[0]; //~ ERROR cannot index into a value of type `()` +} diff --git a/tests/ui/index_message.stderr b/tests/ui/index_message.stderr new file mode 100644 index 000000000..6c2b12673 --- /dev/null +++ b/tests/ui/index_message.stderr @@ -0,0 +1,9 @@ +error[E0608]: cannot index into a value of type `()` + --> $DIR/index_message.rs:3:13 + | +LL | let _ = z[0]; + | ^^^^ help: to access tuple elements, use: `z.0` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/indexing-requires-a-uint.rs b/tests/ui/indexing-requires-a-uint.rs new file mode 100644 index 000000000..dbe9b44a1 --- /dev/null +++ b/tests/ui/indexing-requires-a-uint.rs @@ -0,0 +1,14 @@ +// Make sure that indexing an array is only valid with a `usize`, not any other +// integral type. + +fn main() { + fn bar(_: T) {} + [0][0u8]; //~ ERROR: the type `[{integer}]` cannot be indexed by `u8` + + [0][0]; // should infer to be a usize + + let i = 0; // i is an IntVar + [0][i]; // i should be locked to usize + bar::(i); // i should not be re-coerced back to an isize + //~^ ERROR: mismatched types +} diff --git a/tests/ui/indexing-requires-a-uint.stderr b/tests/ui/indexing-requires-a-uint.stderr new file mode 100644 index 000000000..7a741cfc7 --- /dev/null +++ b/tests/ui/indexing-requires-a-uint.stderr @@ -0,0 +1,32 @@ +error[E0277]: the type `[{integer}]` cannot be indexed by `u8` + --> $DIR/indexing-requires-a-uint.rs:6:9 + | +LL | [0][0u8]; + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[{integer}]` to implement `Index` + +error[E0308]: mismatched types + --> $DIR/indexing-requires-a-uint.rs:12:18 + | +LL | bar::(i); // i should not be re-coerced back to an isize + | ------------ ^ expected `isize`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/indexing-requires-a-uint.rs:5:8 + | +LL | fn bar(_: T) {} + | ^^^ ---- +help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit + | +LL | bar::(i.try_into().unwrap()); // i should not be re-coerced back to an isize + | ++++++++++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/infer-fn-tail-expr.rs b/tests/ui/infer-fn-tail-expr.rs new file mode 100644 index 000000000..413b1877a --- /dev/null +++ b/tests/ui/infer-fn-tail-expr.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(dead_code)] +// issue #680 + + +// pretty-expanded FIXME #23616 + +fn f() -> Vec { Vec::new() } + +pub fn main() { } diff --git a/tests/ui/inference/ambiguous_type_parameter.rs b/tests/ui/inference/ambiguous_type_parameter.rs new file mode 100644 index 000000000..dc70ed661 --- /dev/null +++ b/tests/ui/inference/ambiguous_type_parameter.rs @@ -0,0 +1,17 @@ +use std::collections::HashMap; + +trait Store { + fn get_raw(&self, key: &K) -> Option<()>; +} + +struct InMemoryStore; + +impl Store> for InMemoryStore { + fn get_raw(&self, key: &String) -> Option<()> { + None + } +} + +fn main() { + InMemoryStore.get_raw(&String::default()); //~ ERROR type annotations needed +} diff --git a/tests/ui/inference/ambiguous_type_parameter.stderr b/tests/ui/inference/ambiguous_type_parameter.stderr new file mode 100644 index 000000000..9cbe221de --- /dev/null +++ b/tests/ui/inference/ambiguous_type_parameter.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/ambiguous_type_parameter.rs:16:19 + | +LL | InMemoryStore.get_raw(&String::default()); + | ^^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >>::get_raw(&InMemoryStore, &String::default()); + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs new file mode 100644 index 000000000..04bc0b1a8 --- /dev/null +++ b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs @@ -0,0 +1,35 @@ +#![feature(staged_api)] +#![feature(arbitrary_self_types)] + +#![stable(feature = "ipu_iterator", since = "1.0.0")] + +#[stable(feature = "ipu_iterator", since = "1.0.0")] +pub trait IpuIterator { + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_flatten(&self) -> u32 { + 0 + } + + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_by_value_vs_by_ref(self) -> u32 where Self: Sized { + 0 + } + + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_by_ref_vs_by_ref_mut(&self) -> u32 { + 0 + } + + #[unstable(feature = "ipu_flatten", issue = "99999")] + fn ipu_by_mut_ptr_vs_by_const_ptr(self: *mut Self) -> u32 { + 0 + } + + #[unstable(feature = "assoc_const_ipu_iter", issue = "99999")] + const C: i32; +} + +#[stable(feature = "ipu_iterator", since = "1.0.0")] +impl IpuIterator for char { + const C: i32 = 42; +} diff --git a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs new file mode 100644 index 000000000..fa1efbcfe --- /dev/null +++ b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs @@ -0,0 +1,25 @@ +#![feature(arbitrary_self_types)] + +pub trait IpuItertools { + fn ipu_flatten(&self) -> u32 { + 1 + } + + fn ipu_by_value_vs_by_ref(&self) -> u32 { + 1 + } + + fn ipu_by_ref_vs_by_ref_mut(&mut self) -> u32 { + 1 + } + + fn ipu_by_mut_ptr_vs_by_const_ptr(self: *const Self) -> u32 { + 1 + } + + const C: i32; +} + +impl IpuItertools for char { + const C: i32 = 1; +} diff --git a/tests/ui/inference/cannot-infer-async.rs b/tests/ui/inference/cannot-infer-async.rs new file mode 100644 index 000000000..b5152d04f --- /dev/null +++ b/tests/ui/inference/cannot-infer-async.rs @@ -0,0 +1,16 @@ +// edition:2018 + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; + + Ok(()) + //~^ ERROR type annotations needed + }; +} diff --git a/tests/ui/inference/cannot-infer-async.stderr b/tests/ui/inference/cannot-infer-async.stderr new file mode 100644 index 000000000..0579cf238 --- /dev/null +++ b/tests/ui/inference/cannot-infer-async.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-async.rs:13:9 + | +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Ok::<(), E>(()) + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-closure-circular.rs b/tests/ui/inference/cannot-infer-closure-circular.rs new file mode 100644 index 000000000..affb48149 --- /dev/null +++ b/tests/ui/inference/cannot-infer-closure-circular.rs @@ -0,0 +1,13 @@ +fn main() { + // Below we call the closure with its own return as the argument, unifying + // its inferred input and return types. We want to make sure that the generated + // error handles this gracefully, and in particular doesn't generate an extra + // note about the `?` operator in the closure body, which isn't relevant to + // the inference. + let x = |r| { //~ ERROR type annotations needed for `Result<(), E>` + let v = r?; + Ok(v) + }; + + let _ = x(x(Ok(()))); +} diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr new file mode 100644 index 000000000..b706cd2bc --- /dev/null +++ b/tests/ui/inference/cannot-infer-closure-circular.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Result<(), E>` + --> $DIR/cannot-infer-closure-circular.rs:7:14 + | +LL | let x = |r| { + | ^ + | +help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified + | +LL | let x = |r: Result<(), E>| { + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-closure.rs b/tests/ui/inference/cannot-infer-closure.rs new file mode 100644 index 000000000..bd5d10b41 --- /dev/null +++ b/tests/ui/inference/cannot-infer-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let x = |a: (), b: ()| { + Err(a)?; + Ok(b) + //~^ ERROR type annotations needed + }; +} diff --git a/tests/ui/inference/cannot-infer-closure.stderr b/tests/ui/inference/cannot-infer-closure.stderr new file mode 100644 index 000000000..a4b818e6e --- /dev/null +++ b/tests/ui/inference/cannot-infer-closure.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-closure.rs:4:9 + | +LL | Ok(b) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Ok::<(), E>(b) + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/cannot-infer-partial-try-return.rs b/tests/ui/inference/cannot-infer-partial-try-return.rs new file mode 100644 index 000000000..b555697dc --- /dev/null +++ b/tests/ui/inference/cannot-infer-partial-try-return.rs @@ -0,0 +1,23 @@ +struct QualifiedError(E); + +impl From for QualifiedError +where + E: std::error::Error, + T: From, +{ + fn from(e: E) -> QualifiedError { + QualifiedError(e.into()) + } +} + +fn infallible() -> Result<(), std::convert::Infallible> { + Ok(()) +} + +fn main() { + let x = || -> Result<_, QualifiedError<_>> { + infallible()?; + Ok(()) + //~^ ERROR type annotations needed + }; +} diff --git a/tests/ui/inference/cannot-infer-partial-try-return.stderr b/tests/ui/inference/cannot-infer-partial-try-return.stderr new file mode 100644 index 000000000..888c321bc --- /dev/null +++ b/tests/ui/inference/cannot-infer-partial-try-return.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-partial-try-return.rs:20:9 + | +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Ok::<(), QualifiedError<_>>(()) + | +++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/char-as-str-multi.rs b/tests/ui/inference/char-as-str-multi.rs new file mode 100644 index 000000000..c29a15025 --- /dev/null +++ b/tests/ui/inference/char-as-str-multi.rs @@ -0,0 +1,7 @@ +// When a MULTI/NO-character string literal is used where a char should be, +// DO NOT suggest changing to single quotes. + +fn main() { + let _: char = "foo"; //~ ERROR mismatched types + let _: char = ""; //~ ERROR mismatched types +} diff --git a/tests/ui/inference/char-as-str-multi.stderr b/tests/ui/inference/char-as-str-multi.stderr new file mode 100644 index 000000000..297ca2b54 --- /dev/null +++ b/tests/ui/inference/char-as-str-multi.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/char-as-str-multi.rs:5:19 + | +LL | let _: char = "foo"; + | ---- ^^^^^ expected `char`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/char-as-str-multi.rs:6:19 + | +LL | let _: char = ""; + | ---- ^^ expected `char`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/char-as-str-single.fixed b/tests/ui/inference/char-as-str-single.fixed new file mode 100644 index 000000000..bab1854dc --- /dev/null +++ b/tests/ui/inference/char-as-str-single.fixed @@ -0,0 +1,12 @@ +// When a SINGLE-character string literal is used where a char should be, +// suggest changing to single quotes. + +// Testing both single-byte and multi-byte characters, as we should handle both. + +// run-rustfix + +fn main() { + let _: char = 'a'; //~ ERROR mismatched types + let _: char = '人'; //~ ERROR mismatched types + let _: char = '\''; //~ ERROR mismatched types +} diff --git a/tests/ui/inference/char-as-str-single.rs b/tests/ui/inference/char-as-str-single.rs new file mode 100644 index 000000000..736920643 --- /dev/null +++ b/tests/ui/inference/char-as-str-single.rs @@ -0,0 +1,12 @@ +// When a SINGLE-character string literal is used where a char should be, +// suggest changing to single quotes. + +// Testing both single-byte and multi-byte characters, as we should handle both. + +// run-rustfix + +fn main() { + let _: char = "a"; //~ ERROR mismatched types + let _: char = "人"; //~ ERROR mismatched types + let _: char = "'"; //~ ERROR mismatched types +} diff --git a/tests/ui/inference/char-as-str-single.stderr b/tests/ui/inference/char-as-str-single.stderr new file mode 100644 index 000000000..3375ec6ac --- /dev/null +++ b/tests/ui/inference/char-as-str-single.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/char-as-str-single.rs:9:19 + | +LL | let _: char = "a"; + | ---- ^^^ expected `char`, found `&str` + | | + | expected due to this + | +help: if you meant to write a `char` literal, use single quotes + | +LL | let _: char = 'a'; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/char-as-str-single.rs:10:19 + | +LL | let _: char = "人"; + | ---- ^^^^ expected `char`, found `&str` + | | + | expected due to this + | +help: if you meant to write a `char` literal, use single quotes + | +LL | let _: char = '人'; + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/char-as-str-single.rs:11:19 + | +LL | let _: char = "'"; + | ---- ^^^ expected `char`, found `&str` + | | + | expected due to this + | +help: if you meant to write a `char` literal, use single quotes + | +LL | let _: char = '\''; + | ~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/deref-suggestion.rs b/tests/ui/inference/deref-suggestion.rs new file mode 100644 index 000000000..0d8e7289d --- /dev/null +++ b/tests/ui/inference/deref-suggestion.rs @@ -0,0 +1,75 @@ +macro_rules! borrow { + ($x:expr) => { &$x } +} + +fn foo(_: String) {} + +fn foo2(s: &String) { + foo(s); + //~^ ERROR mismatched types +} + +fn foo3(_: u32) {} +fn foo4(u: &u32) { + foo3(u); + //~^ ERROR mismatched types +} + +struct S<'a> { + u: &'a u32, +} + +struct R { + i: u32, +} + +fn main() { + let s = String::new(); + let r_s = &s; + foo2(r_s); + foo(&"aaa".to_owned()); + //~^ ERROR mismatched types + foo(&mut "aaa".to_owned()); + //~^ ERROR mismatched types + foo3(borrow!(0)); + //~^ ERROR mismatched types + foo4(&0); + assert_eq!(3i32, &3i32); + //~^ ERROR mismatched types + let u = 3; + let s = S { u }; + //~^ ERROR mismatched types + let s = S { u: u }; + //~^ ERROR mismatched types + let i = &4; + let r = R { i }; + //~^ ERROR mismatched types + let r = R { i: i }; + //~^ ERROR mismatched types + + + let a = &1; + let b = &2; + let val: i32 = if true { + a + 1 + } else { + b + //~^ ERROR mismatched types + }; + let val: i32 = if true { + let _ = 2; + a + 1 + } else { + let _ = 2; + b + //~^ ERROR mismatched types + }; + let val = if true { + *a + } else if true { + //~^ ERROR incompatible types + b + } else { + &0 + }; +} diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr new file mode 100644 index 000000000..3db67cdb5 --- /dev/null +++ b/tests/ui/inference/deref-suggestion.stderr @@ -0,0 +1,180 @@ +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:8:9 + | +LL | foo(s); + | --- ^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found `&String` + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/deref-suggestion.rs:5:4 + | +LL | fn foo(_: String) {} + | ^^^ --------- + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:14:10 + | +LL | foo3(u); + | ---- ^ expected `u32`, found `&u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/deref-suggestion.rs:12:4 + | +LL | fn foo3(_: u32) {} + | ^^^^ ------ +help: consider dereferencing the borrow + | +LL | foo3(*u); + | + + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:30:9 + | +LL | foo(&"aaa".to_owned()); + | --- ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/deref-suggestion.rs:5:4 + | +LL | fn foo(_: String) {} + | ^^^ --------- +help: consider removing the borrow + | +LL - foo(&"aaa".to_owned()); +LL + foo("aaa".to_owned()); + | + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:32:9 + | +LL | foo(&mut "aaa".to_owned()); + | --- ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/deref-suggestion.rs:5:4 + | +LL | fn foo(_: String) {} + | ^^^ --------- +help: consider removing the borrow + | +LL - foo(&mut "aaa".to_owned()); +LL + foo("aaa".to_owned()); + | + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:34:10 + | +LL | foo3(borrow!(0)); + | ---- ^^^^^^^^^^ expected `u32`, found `&{integer}` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/deref-suggestion.rs:12:4 + | +LL | fn foo3(_: u32) {} + | ^^^^ ------ + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:37:5 + | +LL | assert_eq!(3i32, &3i32); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected `i32`, found `&i32` + | expected because this is `i32` + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:40:17 + | +LL | let s = S { u }; + | ^ + | | + | expected `&u32`, found integer + | help: consider borrowing here: `u: &u` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:42:20 + | +LL | let s = S { u: u }; + | ^ + | | + | expected `&u32`, found integer + | help: consider borrowing here: `&u` + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:45:17 + | +LL | let r = R { i }; + | ^ expected `u32`, found `&{integer}` + | +help: consider dereferencing the borrow + | +LL | let r = R { i: *i }; + | ++++ + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:47:20 + | +LL | let r = R { i: i }; + | ^ expected `u32`, found `&{integer}` + | +help: consider dereferencing the borrow + | +LL | let r = R { i: *i }; + | + + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:56:9 + | +LL | b + | ^ expected `i32`, found `&{integer}` + | +help: consider dereferencing the borrow + | +LL | *b + | + + +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:64:9 + | +LL | b + | ^ expected `i32`, found `&{integer}` + | +help: consider dereferencing the borrow + | +LL | *b + | + + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/deref-suggestion.rs:69:12 + | +LL | let val = if true { + | ________________- +LL | | *a + | | -- expected because of this +LL | | } else if true { + | | ____________^ +LL | || +LL | || b +LL | || } else { +LL | || &0 +LL | || }; + | || ^ + | ||_____| + | |_____`if` and `else` have incompatible types + | expected `i32`, found `&{integer}` + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/erase-type-params-in-label.rs b/tests/ui/inference/erase-type-params-in-label.rs new file mode 100644 index 000000000..1fea2da92 --- /dev/null +++ b/tests/ui/inference/erase-type-params-in-label.rs @@ -0,0 +1,27 @@ +fn main() { + let foo = foo(1, ""); //~ ERROR E0283 +} +fn baz() { + let bar = bar(1, ""); //~ ERROR E0283 +} + +struct Bar { + t: T, + k: K, + n: N, +} + +fn bar(t: T, k: K) -> Bar { + Bar { t, k, n: Default::default() } +} + +struct Foo { + t: T, + k: K, + n: N, + m: M, +} + +fn foo(t: T, k: K) -> Foo { + Foo { t, k, n: Default::default(), m: Default::default() } +} diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr new file mode 100644 index 000000000..9be182864 --- /dev/null +++ b/tests/ui/inference/erase-type-params-in-label.stderr @@ -0,0 +1,37 @@ +error[E0283]: type annotations needed for `Foo` + --> $DIR/erase-type-params-in-label.rs:2:9 + | +LL | let foo = foo(1, ""); + | ^^^ --- type must be known at this point + | + = note: cannot satisfy `_: Default` +note: required by a bound in `foo` + --> $DIR/erase-type-params-in-label.rs:25:17 + | +LL | fn foo(t: T, k: K) -> Foo { + | ^^^^^^^ required by this bound in `foo` +help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified + | +LL | let foo: Foo = foo(1, ""); + | ++++++++++++++++++++++ + +error[E0283]: type annotations needed for `Bar` + --> $DIR/erase-type-params-in-label.rs:5:9 + | +LL | let bar = bar(1, ""); + | ^^^ --- type must be known at this point + | + = note: cannot satisfy `_: Default` +note: required by a bound in `bar` + --> $DIR/erase-type-params-in-label.rs:14:17 + | +LL | fn bar(t: T, k: K) -> Bar { + | ^^^^^^^ required by this bound in `bar` +help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified + | +LL | let bar: Bar = bar(1, ""); + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/infer-binary-operand-behind-reference.rs b/tests/ui/inference/infer-binary-operand-behind-reference.rs new file mode 100644 index 000000000..0c0a3171e --- /dev/null +++ b/tests/ui/inference/infer-binary-operand-behind-reference.rs @@ -0,0 +1,30 @@ +// check-pass + +fn main() { + // Test that we can infer the type of binary operands when + // references are involved, on various types and operators. + let _: u8 = 0 + 0; + let _: u8 = 0 + &0; + let _: u8 = &0 + 0; + let _: u8 = &0 + &0; + + let _: f32 = 0.0 + 0.0; + let _: f32 = 0.0 + &0.0; + let _: f32 = &0.0 + 0.0; + let _: f32 = &0.0 + &0.0; + + let _: u8 = 0 << 0; + let _: u8 = 0 << &0; + let _: u8 = &0 << 0; + let _: u8 = &0 << &0; + + // Test type inference when variable types are indirectly inferred. + let a = 22; + let _: usize = a + &44; + + // When we have no expected type, the types of the operands is the default type. + let _ = 0 + 0; + let _ = 0 + &0; + let _ = &0 + 0; + let _ = &0 + &0; +} diff --git a/tests/ui/inference/inference-variable-behind-raw-pointer.rs b/tests/ui/inference/inference-variable-behind-raw-pointer.rs new file mode 100644 index 000000000..6662e46b1 --- /dev/null +++ b/tests/ui/inference/inference-variable-behind-raw-pointer.rs @@ -0,0 +1,11 @@ +// check-pass + +// tests that the following code compiles, but produces a future-compatibility warning + +fn main() { + let data = std::ptr::null(); + let _ = &data as *const *const (); + if data.is_null() {} + //~^ WARNING type annotations needed + //~| WARNING this is accepted in the current edition +} diff --git a/tests/ui/inference/inference-variable-behind-raw-pointer.stderr b/tests/ui/inference/inference-variable-behind-raw-pointer.stderr new file mode 100644 index 000000000..3dea09e7f --- /dev/null +++ b/tests/ui/inference/inference-variable-behind-raw-pointer.stderr @@ -0,0 +1,12 @@ +warning: type annotations needed + --> $DIR/inference-variable-behind-raw-pointer.rs:8:13 + | +LL | if data.is_null() {} + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #46906 + = note: `#[warn(tyvar_behind_raw_pointer)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/inference/inference_unstable.rs b/tests/ui/inference/inference_unstable.rs new file mode 100644 index 000000000..daf0cf042 --- /dev/null +++ b/tests/ui/inference/inference_unstable.rs @@ -0,0 +1,31 @@ +// Ensures #[unstable] functions without opting in the corresponding #![feature] +// will not break inference. + +// aux-build:inference_unstable_iterator.rs +// aux-build:inference_unstable_itertools.rs +// run-pass + +extern crate inference_unstable_iterator; +extern crate inference_unstable_itertools; + +#[allow(unused_imports)] +use inference_unstable_iterator::IpuIterator; +use inference_unstable_itertools::IpuItertools; + +fn main() { + assert_eq!('x'.ipu_flatten(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!('x'.ipu_by_value_vs_by_ref(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1); +//~^ WARN an associated function with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an + assert_eq!(char::C, 1); +//~^ WARN an associated constant with this name may be added to the standard library in the future +//~| WARN once this associated item is added to the standard library, the ambiguity may cause an +} diff --git a/tests/ui/inference/inference_unstable.stderr b/tests/ui/inference/inference_unstable.stderr new file mode 100644 index 000000000..ecbf2641b --- /dev/null +++ b/tests/ui/inference/inference_unstable.stderr @@ -0,0 +1,57 @@ +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:16:20 + | +LL | assert_eq!('x'.ipu_flatten(), 1); + | ^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten` + = note: `#[warn(unstable_name_collisions)]` on by default + +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:19:20 + | +LL | assert_eq!('x'.ipu_by_value_vs_by_ref(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_value_vs_by_ref(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_value_vs_by_ref` + +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:22:20 + | +LL | assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_ref_vs_by_ref_mut(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_ref_vs_by_ref_mut` + +warning: an associated function with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:25:40 + | +LL | assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 + = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_mut_ptr_vs_by_const_ptr(...)` to keep using the current method + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_mut_ptr_vs_by_const_ptr` + +warning: an associated constant with this name may be added to the standard library in the future + --> $DIR/inference_unstable.rs:28:16 + | +LL | assert_eq!(char::C, 1); + | ^^^^^^^ help: use the fully qualified path to the associated const: `::C` + | + = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! + = note: for more information, see issue #48919 + = help: add `#![feature(assoc_const_ipu_iter)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::C` + +warning: 5 warnings emitted + diff --git a/tests/ui/inference/inference_unstable_featured.rs b/tests/ui/inference/inference_unstable_featured.rs new file mode 100644 index 000000000..792b29aaa --- /dev/null +++ b/tests/ui/inference/inference_unstable_featured.rs @@ -0,0 +1,17 @@ +// There should be E0034 "multiple applicable items in scope" if we opt-in for +// the feature. + +// aux-build:inference_unstable_iterator.rs +// aux-build:inference_unstable_itertools.rs + +#![feature(ipu_flatten)] + +extern crate inference_unstable_iterator; +extern crate inference_unstable_itertools; + +use inference_unstable_iterator::IpuIterator; +use inference_unstable_itertools::IpuItertools; + +fn main() { + assert_eq!('x'.ipu_flatten(), 0); //~ ERROR E0034 +} diff --git a/tests/ui/inference/inference_unstable_featured.stderr b/tests/ui/inference/inference_unstable_featured.stderr new file mode 100644 index 000000000..4ddede29c --- /dev/null +++ b/tests/ui/inference/inference_unstable_featured.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/inference_unstable_featured.rs:16:20 + | +LL | assert_eq!('x'.ipu_flatten(), 0); + | ^^^^^^^^^^^ multiple `ipu_flatten` found + | + = note: candidate #1 is defined in an impl of the trait `IpuIterator` for the type `char` + = note: candidate #2 is defined in an impl of the trait `IpuItertools` for the type `char` +help: disambiguate the associated function for candidate #1 + | +LL | assert_eq!(IpuIterator::ipu_flatten(&'x'), 0); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | assert_eq!(IpuItertools::ipu_flatten(&'x'), 0); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/inference/inference_unstable_forced.rs b/tests/ui/inference/inference_unstable_forced.rs new file mode 100644 index 000000000..649b3ed2a --- /dev/null +++ b/tests/ui/inference/inference_unstable_forced.rs @@ -0,0 +1,12 @@ +// If the unstable API is the only possible solution, +// still emit E0658 "use of unstable library feature". + +// aux-build:inference_unstable_iterator.rs + +extern crate inference_unstable_iterator; + +use inference_unstable_iterator::IpuIterator; + +fn main() { + assert_eq!('x'.ipu_flatten(), 0); //~ ERROR E0658 +} diff --git a/tests/ui/inference/inference_unstable_forced.stderr b/tests/ui/inference/inference_unstable_forced.stderr new file mode 100644 index 000000000..a1c4cd851 --- /dev/null +++ b/tests/ui/inference/inference_unstable_forced.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'ipu_flatten' + --> $DIR/inference_unstable_forced.rs:11:20 + | +LL | assert_eq!('x'.ipu_flatten(), 0); + | ^^^^^^^^^^^ + | + = note: see issue #99999 for more information + = help: add `#![feature(ipu_flatten)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/inference/issue-103587.rs b/tests/ui/inference/issue-103587.rs new file mode 100644 index 000000000..11536f9f4 --- /dev/null +++ b/tests/ui/inference/issue-103587.rs @@ -0,0 +1,12 @@ +fn main() { + let x = Some(123); + + if let Some(_) == x {} + //~^ ERROR expected `=`, found `==` + + if Some(_) = x {} + //~^ ERROR mismatched types + + if None = x { } + //~^ ERROR mismatched types +} diff --git a/tests/ui/inference/issue-103587.stderr b/tests/ui/inference/issue-103587.stderr new file mode 100644 index 000000000..b373fbfbb --- /dev/null +++ b/tests/ui/inference/issue-103587.stderr @@ -0,0 +1,40 @@ +error: expected `=`, found `==` + --> $DIR/issue-103587.rs:4:20 + | +LL | if let Some(_) == x {} + | ^^ + | +help: consider using `=` here + | +LL | if let Some(_) = x {} + | ~ + +error[E0308]: mismatched types + --> $DIR/issue-103587.rs:7:8 + | +LL | if Some(_) = x {} + | ^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(_) = x {} + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-103587.rs:10:8 + | +LL | if None = x { } + | ^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to use pattern matching + | +LL | if let None = x { } + | +++ +help: you might have meant to compare for equality + | +LL | if None == x { } + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/issue-104649.rs b/tests/ui/inference/issue-104649.rs new file mode 100644 index 000000000..4637b884d --- /dev/null +++ b/tests/ui/inference/issue-104649.rs @@ -0,0 +1,32 @@ +type Result = ::std::result::Result; +struct Error; + +trait ForEach { + type Input; + fn for_each(self, f: F) + where + F: FnOnce(Self::Input) -> U; +} + +impl ForEach for A { + type Input = T; + fn for_each(self, f: F) + where + F: FnOnce(Self::Input) -> U, + { + todo!() + } +} + +struct A(T); + +fn main() { + let a = A(Result::Ok(Result::Ok(()))); //~ ERROR type annotations needed + a.for_each(|a: Result<_>| { + let f = || match a { + Ok(Ok(a)) => {} + Ok(Err(a)) => {} + Err(a) => {} + }; + }); +} diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr new file mode 100644 index 000000000..4962b21f9 --- /dev/null +++ b/tests/ui/inference/issue-104649.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `A, Error>>` + --> $DIR/issue-104649.rs:24:9 + | +LL | let a = A(Result::Ok(Result::Ok(()))); + | ^ + | +help: consider giving `a` an explicit type, where the type for type parameter `E` is specified + | +LL | let a: A, Error>> = A(Result::Ok(Result::Ok(()))); + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/issue-28935.rs b/tests/ui/inference/issue-28935.rs new file mode 100644 index 000000000..872822dbd --- /dev/null +++ b/tests/ui/inference/issue-28935.rs @@ -0,0 +1,9 @@ +// check-pass + +use std::cell::RefCell; + +pub fn f(v: Vec>) { + let _t = &mut *v[0].borrow_mut(); +} + +fn main() {} diff --git a/tests/ui/inference/issue-36053.rs b/tests/ui/inference/issue-36053.rs new file mode 100644 index 000000000..5c6d07804 --- /dev/null +++ b/tests/ui/inference/issue-36053.rs @@ -0,0 +1,22 @@ +// run-pass +// Regression test for #36053. ICE was caused due to obligations being +// added to a special, dedicated fulfillment cx during a +// probe. Problem seems to be related to the particular definition of +// `FusedIterator` in std but I was not able to isolate that into an +// external crate. + +use std::iter::FusedIterator; + +struct Thing<'a>(#[allow(unused_tuple_struct_fields)] &'a str); +impl<'a> Iterator for Thing<'a> { + type Item = &'a str; + fn next(&mut self) -> Option<&'a str> { + None + } +} + +impl<'a> FusedIterator for Thing<'a> {} + +fn main() { + Thing("test").fuse().filter(|_| true).count(); +} diff --git a/tests/ui/inference/issue-70703.rs b/tests/ui/inference/issue-70703.rs new file mode 100644 index 000000000..d90498e96 --- /dev/null +++ b/tests/ui/inference/issue-70703.rs @@ -0,0 +1,26 @@ +// check-pass + +trait Factory { + type Product; +} + +impl Factory for () { + type Product = (); +} + +trait ProductConsumer

{ + fn consume(self, product: P); +} + +impl

ProductConsumer

for () { + fn consume(self, _: P) {} +} + +fn make_product_consumer(_: F) -> impl ProductConsumer { + () +} + +fn main() { + let consumer = make_product_consumer(()); + consumer.consume(()); +} diff --git a/tests/ui/inference/issue-71309.rs b/tests/ui/inference/issue-71309.rs new file mode 100644 index 000000000..c31107d8f --- /dev/null +++ b/tests/ui/inference/issue-71309.rs @@ -0,0 +1,7 @@ +fn foo(x: Result) -> Result<(), ()> { + let y: u32 = x?; + //~^ ERROR: `?` operator has incompatible types + Ok(()) +} + +fn main() {} diff --git a/tests/ui/inference/issue-71309.stderr b/tests/ui/inference/issue-71309.stderr new file mode 100644 index 000000000..af8714f1c --- /dev/null +++ b/tests/ui/inference/issue-71309.stderr @@ -0,0 +1,15 @@ +error[E0308]: `?` operator has incompatible types + --> $DIR/issue-71309.rs:2:18 + | +LL | let y: u32 = x?; + | ^^ expected `u32`, found `i32` + | + = note: `?` operator cannot convert from `i32` to `u32` +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | let y: u32 = x?.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/issue-71732.rs b/tests/ui/inference/issue-71732.rs new file mode 100644 index 000000000..8a9d2b235 --- /dev/null +++ b/tests/ui/inference/issue-71732.rs @@ -0,0 +1,24 @@ +// Regression test for #71732, it used to emit incorrect diagnostics, like: +// error[E0283]: type annotations needed +// --> src/main.rs:5:10 +// | +// 5 | .get(&"key".into()) +// | ^^^ cannot infer type for struct `String` +// | +// = note: cannot satisfy `String: Borrow<_>` +// help: consider specifying the type argument in the method call +// | +// 5 | .get::(&"key".into()) +// | + +use std::collections::hash_map::HashMap; + +fn foo(parameters: &HashMap) -> bool { + parameters + .get(&"key".into()) + //~^ ERROR type annotations needed + .and_then(|found: &String| Some(false)) + .unwrap_or(false) +} + +fn main() {} diff --git a/tests/ui/inference/issue-71732.stderr b/tests/ui/inference/issue-71732.stderr new file mode 100644 index 000000000..01b37f2ac --- /dev/null +++ b/tests/ui/inference/issue-71732.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed + --> $DIR/issue-71732.rs:18:10 + | +LL | .get(&"key".into()) + | ^^^ ------------- type must be known at this point + | | + | cannot infer type of the type parameter `Q` declared on the associated function `get` + | + = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: + - impl Borrow for String; + - impl Borrow for T + where T: ?Sized; +note: required by a bound in `HashMap::::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL +help: consider specifying the generic argument + | +LL | .get::(&"key".into()) + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-72616.rs b/tests/ui/inference/issue-72616.rs new file mode 100644 index 000000000..69ade1a75 --- /dev/null +++ b/tests/ui/inference/issue-72616.rs @@ -0,0 +1,32 @@ +// ignore-wasm32 FIXME: ignoring wasm as it suggests slightly different impls + +// Regression test for #72616, it used to emit incorrect diagnostics, like: +// error[E0283]: type annotations needed for `String` +// --> src/main.rs:8:30 +// | +// 5 | let _: String = "".to_owned().try_into().unwrap(); +// | - consider giving this pattern a type +// ... +// 8 | if String::from("a") == "a".try_into().unwrap() {} +// | ^^ cannot infer type for struct `String` +// | +// = note: cannot satisfy `String: PartialEq<_>` + +use std::convert::TryInto; + +pub fn main() { + { + let _: String = "".to_owned().try_into().unwrap(); + } + { + if String::from("a") == "a".try_into().unwrap() {} + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + } + { + let _: String = match "_".try_into() { + Ok(a) => a, + Err(_) => "".into(), + }; + } +} diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr new file mode 100644 index 000000000..6ee0626ca --- /dev/null +++ b/tests/ui/inference/issue-72616.stderr @@ -0,0 +1,37 @@ +error[E0283]: type annotations needed + --> $DIR/issue-72616.rs:22:37 + | +LL | if String::from("a") == "a".try_into().unwrap() {} + | -- ^^^^^^^^ + | | + | type must be known at this point + | + = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate: + - impl PartialEq for String; + - impl<'a, 'b> PartialEq<&'a str> for String; + - impl<'a, 'b> PartialEq> for String; + - impl<'a, 'b> PartialEq for String; +help: try using a fully qualified path to specify the expected types + | +LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} + | +++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-72616.rs:22:37 + | +LL | if String::from("a") == "a".try_into().unwrap() {} + | ^^^^^^^^ + | + = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`: + - impl<> TryFrom<&str> for std::sys_common::net::LookupHost; + - impl TryFrom for T + where U: Into; + = note: required for `&str` to implement `TryInto<_>` +help: try using a fully qualified path to specify the expected types + | +LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} + | +++++++++++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-72690.rs b/tests/ui/inference/issue-72690.rs new file mode 100644 index 000000000..8c0a0f51a --- /dev/null +++ b/tests/ui/inference/issue-72690.rs @@ -0,0 +1,70 @@ +fn no_err() { + |x: String| x; + let _ = String::from("x"); +} + +fn err() { + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed +} + +fn arg_pat_closure_err() { + |x| String::from("x".as_ref()); //~ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn local_pat_closure_err() { + let _ = "x".as_ref(); //~ ERROR type annotations needed +} + +fn err_first_arg_pat() { + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed + |x: String| x; +} + +fn err_second_arg_pat() { + |x: String| x; + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed +} + +fn err_mid_arg_pat() { + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed + |x: String| x; + |x: String| x; + |x: String| x; + |x: String| x; +} + +fn err_first_local_pat() { + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed + let _ = String::from("x"); +} + +fn err_second_local_pat() { + let _ = String::from("x"); + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed +} + +fn err_mid_local_pat() { + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + String::from("x".as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); + let _ = String::from("x"); +} + +fn main() {} diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr new file mode 100644 index 000000000..8eda71ec0 --- /dev/null +++ b/tests/ui/inference/issue-72690.stderr @@ -0,0 +1,229 @@ +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:7:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:7:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0282]: type annotations needed + --> $DIR/issue-72690.rs:12:6 + | +LL | |x| String::from("x".as_ref()); + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | |x: /* Type */| String::from("x".as_ref()); + | ++++++++++++ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:12:26 + | +LL | |x| String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | |x| String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed for `&T` + --> $DIR/issue-72690.rs:17:9 + | +LL | let _ = "x".as_ref(); + | ^ ------ type must be known at this point + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: &T = "x".as_ref(); + | ++++ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:21:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:21:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:28:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:28:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:37:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:37:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:46:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:46:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:53:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:53:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:62:5 + | +LL | String::from("x".as_ref()); + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate: + - impl<> From<&String> for String; + - impl<> From<&str> for String; + +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:62:22 + | +LL | String::from("x".as_ref()); + | ^^^^^^ + | + = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef for str; + - impl AsRef for str; + - impl AsRef<[u8]> for str; + - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/issue-80816.rs b/tests/ui/inference/issue-80816.rs new file mode 100644 index 000000000..4d319b449 --- /dev/null +++ b/tests/ui/inference/issue-80816.rs @@ -0,0 +1,55 @@ +#![allow(unreachable_code)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::sync::Arc; + +pub struct Guard { + _phantom: PhantomData, +} +impl Deref for Guard { + type Target = T; + fn deref(&self) -> &T { + unimplemented!() + } +} + +pub struct DirectDeref(T); +impl Deref for DirectDeref> { + type Target = T; + fn deref(&self) -> &T { + unimplemented!() + } +} + +pub trait Access { + type Guard: Deref; + fn load(&self) -> Self::Guard { + unimplemented!() + } +} +impl, P: Deref> Access for P { + //~^ NOTE: required for `Arc>>` to implement `Access<_>` + //~| NOTE unsatisfied trait bound introduced here + type Guard = A::Guard; +} +impl Access for ArcSwapAny { + //~^ NOTE: multiple `impl`s satisfying `ArcSwapAny>: Access<_>` found + type Guard = Guard; +} +impl Access for ArcSwapAny> { + type Guard = DirectDeref>; +} + +pub struct ArcSwapAny { + _phantom_arc: PhantomData, +} + +pub fn foo() { + let s: Arc>> = unimplemented!(); + let guard: Guard> = s.load(); + //~^ ERROR: type annotations needed + //~| HELP: try using a fully qualified path to specify the expected types +} + +fn main() {} diff --git a/tests/ui/inference/issue-80816.stderr b/tests/ui/inference/issue-80816.stderr new file mode 100644 index 000000000..80c0c8abe --- /dev/null +++ b/tests/ui/inference/issue-80816.stderr @@ -0,0 +1,29 @@ +error[E0283]: type annotations needed + --> $DIR/issue-80816.rs:50:38 + | +LL | let guard: Guard> = s.load(); + | ^^^^ + | +note: multiple `impl`s satisfying `ArcSwapAny>: Access<_>` found + --> $DIR/issue-80816.rs:36:1 + | +LL | impl Access for ArcSwapAny { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Access for ArcSwapAny> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required for `Arc>>` to implement `Access<_>` + --> $DIR/issue-80816.rs:31:45 + | +LL | impl, P: Deref> Access for P { + | --------- ^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +help: try using a fully qualified path to specify the expected types + | +LL | let guard: Guard> = >> as Access>::load(&s); + | ++++++++++++++++++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-81522.rs b/tests/ui/inference/issue-81522.rs new file mode 100644 index 000000000..902f8fdde --- /dev/null +++ b/tests/ui/inference/issue-81522.rs @@ -0,0 +1,31 @@ +// Regression test for #81522. +// Ensures that `#[allow(unstable_name_collisions)]` appended to things other than function +// suppresses the corresponding diagnostics emitted from inside them. +// But note that this attribute doesn't work for macro invocations if it is appended directly. + +// aux-build:inference_unstable_iterator.rs +// aux-build:inference_unstable_itertools.rs +// run-pass + +extern crate inference_unstable_iterator; +extern crate inference_unstable_itertools; + +#[allow(unused_imports)] +use inference_unstable_iterator::IpuIterator; +use inference_unstable_itertools::IpuItertools; + +fn main() { + // expression statement + #[allow(unstable_name_collisions)] + 'x'.ipu_flatten(); + + // let statement + #[allow(unstable_name_collisions)] + let _ = 'x'.ipu_flatten(); + + // block expression + #[allow(unstable_name_collisions)] + { + 'x'.ipu_flatten(); + } +} diff --git a/tests/ui/inference/issue-83606.rs b/tests/ui/inference/issue-83606.rs new file mode 100644 index 000000000..c387046e9 --- /dev/null +++ b/tests/ui/inference/issue-83606.rs @@ -0,0 +1,10 @@ +// Regression test for #83606. + +fn foo(_: impl std::fmt::Display) -> [usize; N] { + [0; N] +} + +fn main() { + let _ = foo("foo"); + //~^ ERROR: type annotations needed for `[usize; N]` +} diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr new file mode 100644 index 000000000..f2ee8692e --- /dev/null +++ b/tests/ui/inference/issue-83606.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[usize; N]` + --> $DIR/issue-83606.rs:8:9 + | +LL | let _ = foo("foo"); + | ^ + | +help: consider giving this pattern a type, where the the value of const parameter `N` is specified + | +LL | let _: [usize; N] = foo("foo"); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/issue-86162-1.rs b/tests/ui/inference/issue-86162-1.rs new file mode 100644 index 000000000..5a547eb38 --- /dev/null +++ b/tests/ui/inference/issue-86162-1.rs @@ -0,0 +1,9 @@ +// Regression test of #86162. + +fn foo(x: impl Clone) {} +fn gen() -> T { todo!() } + +fn main() { + foo(gen()); //<- Do not suggest `foo::()`! + //~^ ERROR: type annotations needed +} diff --git a/tests/ui/inference/issue-86162-1.stderr b/tests/ui/inference/issue-86162-1.stderr new file mode 100644 index 000000000..4f621b82d --- /dev/null +++ b/tests/ui/inference/issue-86162-1.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed + --> $DIR/issue-86162-1.rs:7:9 + | +LL | foo(gen()); //<- Do not suggest `foo::()`! + | --- ^^^ cannot infer type of the type parameter `T` declared on the function `gen` + | | + | required by a bound introduced by this call + | + = note: cannot satisfy `_: Clone` +note: required by a bound in `foo` + --> $DIR/issue-86162-1.rs:3:16 + | +LL | fn foo(x: impl Clone) {} + | ^^^^^ required by this bound in `foo` +help: consider specifying the generic argument + | +LL | foo(gen::()); //<- Do not suggest `foo::()`! + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/issue-86162-2.rs b/tests/ui/inference/issue-86162-2.rs new file mode 100644 index 000000000..b8c75dd77 --- /dev/null +++ b/tests/ui/inference/issue-86162-2.rs @@ -0,0 +1,14 @@ +// Regression test of #86162. + +fn gen() -> T { todo!() } + +struct Foo; + +impl Foo { + fn bar(x: impl Clone) {} +} + +fn main() { + Foo::bar(gen()); //<- Do not suggest `Foo::bar::()`! + //~^ ERROR: type annotations needed +} diff --git a/tests/ui/inference/issue-86162-2.stderr b/tests/ui/inference/issue-86162-2.stderr new file mode 100644 index 000000000..9aff2cec1 --- /dev/null +++ b/tests/ui/inference/issue-86162-2.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed + --> $DIR/issue-86162-2.rs:12:14 + | +LL | Foo::bar(gen()); //<- Do not suggest `Foo::bar::()`! + | -------- ^^^ cannot infer type of the type parameter `T` declared on the function `gen` + | | + | required by a bound introduced by this call + | + = note: cannot satisfy `_: Clone` +note: required by a bound in `Foo::bar` + --> $DIR/issue-86162-2.rs:8:20 + | +LL | fn bar(x: impl Clone) {} + | ^^^^^ required by this bound in `Foo::bar` +help: consider specifying the generic argument + | +LL | Foo::bar(gen::()); //<- Do not suggest `Foo::bar::()`! + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/inference/lub-glb-with-unbound-infer-var.rs b/tests/ui/inference/lub-glb-with-unbound-infer-var.rs new file mode 100644 index 000000000..c9e117089 --- /dev/null +++ b/tests/ui/inference/lub-glb-with-unbound-infer-var.rs @@ -0,0 +1,15 @@ +// run-pass +// Test for a specific corner case: when we compute the LUB of two fn +// types and their parameters have unbound variables. In that case, we +// wind up relating those two variables. This was causing an ICE in an +// in-progress PR. + +fn main() { + let a_f: fn(_) = |_| (); + let b_f: fn(_) = |_| (); + let c_f = match 22 { + 0 => a_f, + _ => b_f, + }; + c_f(4); +} diff --git a/tests/ui/inference/need_type_info/channel.rs b/tests/ui/inference/need_type_info/channel.rs new file mode 100644 index 000000000..e2ba5a941 --- /dev/null +++ b/tests/ui/inference/need_type_info/channel.rs @@ -0,0 +1,19 @@ +// Test that we suggest specifying the generic argument of `channel` +// instead of the return type of that function, which is a lot more +// complex. +use std::sync::mpsc::channel; + +fn no_tuple() { + let _data = + channel(); //~ ERROR type annotations needed +} + +fn tuple() { + let (_sender, _receiver) = + channel(); //~ ERROR type annotations needed +} + +fn main() { + no_tuple(); + tuple(); +} diff --git a/tests/ui/inference/need_type_info/channel.stderr b/tests/ui/inference/need_type_info/channel.stderr new file mode 100644 index 000000000..e33ace033 --- /dev/null +++ b/tests/ui/inference/need_type_info/channel.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/channel.rs:8:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::(); + | +++++ + +error[E0282]: type annotations needed + --> $DIR/channel.rs:13:9 + | +LL | channel(); + | ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `channel` + | +help: consider specifying the generic argument + | +LL | channel::(); + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs new file mode 100644 index 000000000..72e0e74f3 --- /dev/null +++ b/tests/ui/inference/need_type_info/concrete-impl.rs @@ -0,0 +1,16 @@ +trait Ambiguous { + fn method() {} +} + +struct One; +struct Two; +struct Struct; + +impl Ambiguous for Struct {} +impl Ambiguous for Struct {} + +fn main() { + >::method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr new file mode 100644 index 000000000..aa3296995 --- /dev/null +++ b/tests/ui/inference/need_type_info/concrete-impl.stderr @@ -0,0 +1,24 @@ +error[E0282]: type annotations needed + --> $DIR/concrete-impl.rs:13:5 + | +LL | >::method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous` + +error[E0283]: type annotations needed + --> $DIR/concrete-impl.rs:13:5 + | +LL | >::method(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous` + | +note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found + --> $DIR/concrete-impl.rs:9:1 + | +LL | impl Ambiguous for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Ambiguous for Struct {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs new file mode 100644 index 000000000..3084f6eac --- /dev/null +++ b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs @@ -0,0 +1,11 @@ +enum OhNo { + A(T), + B(U), + C, +} + +fn uwu() { + OhNo::C::; //~ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr new file mode 100644 index 000000000..2ad35ab03 --- /dev/null +++ b/tests/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/do-not-suggest-generic-arguments-for-turbofish.rs:8:5 + | +LL | OhNo::C::; + | ^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the enum `OhNo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs new file mode 100644 index 000000000..42af9fa8d --- /dev/null +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.rs @@ -0,0 +1,21 @@ +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer() {} + +enum Bar { + Variant {} +} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output::Variant {} + } +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr new file mode 100644 index 000000000..68ecb3813 --- /dev/null +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-enum.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-enum.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs new file mode 100644 index 000000000..b0c0d3397 --- /dev/null +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.rs @@ -0,0 +1,19 @@ +trait Foo { + type Output; + + fn baz(); +} + +enum Bar { + Simple {}, + Generic(T), +} + +impl Foo for u8 { + type Output = Bar; + fn baz() { + Self::Output::Simple {}; //~ ERROR type annotations needed + } +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr new file mode 100644 index 000000000..cbc2477de --- /dev/null +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative-gat.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative-gat.rs:15:9 + | +LL | Self::Output::Simple {}; + | ^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated type `Output` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative.rs b/tests/ui/inference/need_type_info/expr-struct-type-relative.rs new file mode 100644 index 000000000..c3ece2b16 --- /dev/null +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative.rs @@ -0,0 +1,21 @@ +// regression test for #98598 + +trait Foo { + type Output; + + fn baz() -> Self::Output; +} + +fn needs_infer() {} + +struct Bar {} + +impl Foo for u8 { + type Output = Bar; + fn baz() -> Self::Output { + needs_infer(); //~ ERROR type annotations needed + Self::Output {} + } +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr b/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr new file mode 100644 index 000000000..397d8e7be --- /dev/null +++ b/tests/ui/inference/need_type_info/expr-struct-type-relative.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expr-struct-type-relative.rs:16:9 + | +LL | needs_infer(); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `needs_infer` + | +help: consider specifying the generic argument + | +LL | needs_infer::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/issue-103053.rs b/tests/ui/inference/need_type_info/issue-103053.rs new file mode 100644 index 000000000..05169666f --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-103053.rs @@ -0,0 +1,18 @@ +trait TypeMapper { + type MapType; +} + +type Mapped = ::MapType; + +struct Test {} + +impl TypeMapper for () { + type MapType = Test; +} + +fn test() { + Mapped::<()> {}; + None; //~ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/issue-103053.stderr b/tests/ui/inference/need_type_info/issue-103053.stderr new file mode 100644 index 000000000..84f0475d8 --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-103053.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-103053.rs:15:5 + | +LL | None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | None::; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/self-ty-in-path.rs b/tests/ui/inference/need_type_info/self-ty-in-path.rs new file mode 100644 index 000000000..768a8cc37 --- /dev/null +++ b/tests/ui/inference/need_type_info/self-ty-in-path.rs @@ -0,0 +1,13 @@ +// Test that we don't ICE when encountering a `Self` in a path. +struct TestErr(T); + +impl TestErr { + fn func_a() {} + + fn func_b() { + Self::func_a(); + //~^ ERROR type annotations needed + } +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/self-ty-in-path.stderr b/tests/ui/inference/need_type_info/self-ty-in-path.stderr new file mode 100644 index 000000000..04b521dbd --- /dev/null +++ b/tests/ui/inference/need_type_info/self-ty-in-path.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/self-ty-in-path.rs:8:9 + | +LL | Self::func_a(); + | ^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the associated function `func_a` + | +help: consider specifying the generic argument + | +LL | Self::func_a::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.rs b/tests/ui/inference/need_type_info/type-alias-indirect.rs new file mode 100644 index 000000000..0ed02ddc5 --- /dev/null +++ b/tests/ui/inference/need_type_info/type-alias-indirect.rs @@ -0,0 +1,18 @@ +// An addition to the `type-alias.rs` test, +// see the FIXME in that file for why this test +// exists. +// +// If there is none, feel free to remove this test +// again. +struct Ty(T); +impl Ty { + fn new() {} +} + +type IndirectAlias = Ty>; +fn indirect_alias() { + IndirectAlias::new(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/type-alias-indirect.stderr b/tests/ui/inference/need_type_info/type-alias-indirect.stderr new file mode 100644 index 000000000..6161690df --- /dev/null +++ b/tests/ui/inference/need_type_info/type-alias-indirect.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/type-alias-indirect.rs:14:5 + | +LL | IndirectAlias::new(); + | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/need_type_info/type-alias.rs b/tests/ui/inference/need_type_info/type-alias.rs new file mode 100644 index 000000000..f921b046b --- /dev/null +++ b/tests/ui/inference/need_type_info/type-alias.rs @@ -0,0 +1,36 @@ +// Test the inference errors in case the relevant path +// uses a type alias. +// +// Regression test for #97698. +struct Ty(T); +impl Ty { + fn new() {} +} + +type DirectAlias = Ty; +fn direct_alias() { + DirectAlias::new() + //~^ ERROR type annotations needed +} + +type IndirectAlias = Ty>; +fn indirect_alias() { + IndirectAlias::new(); + // FIXME: This should also emit an error. + // + // Added it separately as `type-alias-indirect.rs` + // where it does error. +} + +struct TyDefault(T, U); +impl TyDefault { + fn new() {} +} + +type DirectButWithDefaultAlias = TyDefault; +fn direct_but_with_default_alias() { + DirectButWithDefaultAlias::new(); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr new file mode 100644 index 000000000..a33f49baf --- /dev/null +++ b/tests/ui/inference/need_type_info/type-alias.stderr @@ -0,0 +1,15 @@ +error[E0282]: type annotations needed + --> $DIR/type-alias.rs:12:5 + | +LL | DirectAlias::new() + | ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/type-alias.rs:32:5 + | +LL | DirectButWithDefaultAlias::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/newlambdas-ret-infer.rs b/tests/ui/inference/newlambdas-ret-infer.rs new file mode 100644 index 000000000..9b629838f --- /dev/null +++ b/tests/ui/inference/newlambdas-ret-infer.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(dead_code)] +// Test that the lambda kind is inferred correctly as a return +// expression + +// pretty-expanded FIXME #23616 + +fn unique() -> Box { return Box::new(|| ()); } + +pub fn main() { +} diff --git a/tests/ui/inference/newlambdas-ret-infer2.rs b/tests/ui/inference/newlambdas-ret-infer2.rs new file mode 100644 index 000000000..abe31a05f --- /dev/null +++ b/tests/ui/inference/newlambdas-ret-infer2.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(dead_code)] +// Test that the lambda kind is inferred correctly as a return +// expression + +// pretty-expanded FIXME #23616 + +fn unique() -> Box { Box::new(|| ()) } + +pub fn main() { +} diff --git a/tests/ui/inference/question-mark-type-infer.rs b/tests/ui/inference/question-mark-type-infer.rs new file mode 100644 index 000000000..10560f85e --- /dev/null +++ b/tests/ui/inference/question-mark-type-infer.rs @@ -0,0 +1,16 @@ +// Test that type inference fails where there are multiple possible return types +// for the `?` operator. + +fn f(x: &i32) -> Result { + Ok(*x) +} + +fn g() -> Result, ()> { + let l = [1, 2, 3, 4]; + l.iter().map(f).collect()? + //~^ ERROR type annotations needed +} + +fn main() { + g(); +} diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr new file mode 100644 index 000000000..a9cb7e525 --- /dev/null +++ b/tests/ui/inference/question-mark-type-infer.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/question-mark-type-infer.rs:10:21 + | +LL | l.iter().map(f).collect()? + | ^^^^^^^ cannot infer type of the type parameter `B` declared on the associated function `collect` + | +help: consider specifying the generic argument + | +LL | l.iter().map(f).collect::>()? + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/inference/range-type-infer.rs b/tests/ui/inference/range-type-infer.rs new file mode 100644 index 000000000..f07c04171 --- /dev/null +++ b/tests/ui/inference/range-type-infer.rs @@ -0,0 +1,22 @@ +// run-pass + +#![allow(unused_must_use)] +// Make sure the type inference for the new range expression work as +// good as the old one. Check out issue #21672, #21595 and #21649 for +// more details. + + +fn main() { + let xs = (0..8).map(|i| i == 1u64).collect::>(); + assert_eq!(xs[1], true); + let xs = (0..8).map(|i| 1u64 == i).collect::>(); + assert_eq!(xs[1], true); + let xs: Vec = (0..10).collect(); + assert_eq!(xs.len(), 10); + + for x in 0..10 { x % 2; } + for x in 0..100 { x as f32; } + + let array = [true, false]; + for i in 0..1 { array[i]; } +} diff --git a/tests/ui/inference/simple-infer.rs b/tests/ui/inference/simple-infer.rs new file mode 100644 index 000000000..561e4fdec --- /dev/null +++ b/tests/ui/inference/simple-infer.rs @@ -0,0 +1,6 @@ +// run-pass + +#![allow(unused_mut)] + + +pub fn main() { let mut n; n = 1; println!("{}", n); } diff --git a/tests/ui/inference/str-as-char.fixed b/tests/ui/inference/str-as-char.fixed new file mode 100644 index 000000000..6aea809cb --- /dev/null +++ b/tests/ui/inference/str-as-char.fixed @@ -0,0 +1,10 @@ +// When a char literal is used where a str should be, +// suggest changing to double quotes. + +// run-rustfix + +fn main() { + let _: &str = "a"; //~ ERROR mismatched types + let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint + let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint +} diff --git a/tests/ui/inference/str-as-char.rs b/tests/ui/inference/str-as-char.rs new file mode 100644 index 000000000..eaa8d788c --- /dev/null +++ b/tests/ui/inference/str-as-char.rs @@ -0,0 +1,10 @@ +// When a char literal is used where a str should be, +// suggest changing to double quotes. + +// run-rustfix + +fn main() { + let _: &str = 'a'; //~ ERROR mismatched types + let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint + let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint +} diff --git a/tests/ui/inference/str-as-char.stderr b/tests/ui/inference/str-as-char.stderr new file mode 100644 index 000000000..2c84dac8e --- /dev/null +++ b/tests/ui/inference/str-as-char.stderr @@ -0,0 +1,38 @@ +error: character literal may only contain one codepoint + --> $DIR/str-as-char.rs:8:19 + | +LL | let _: &str = '"""'; + | ^^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let _: &str = "\"\"\""; + | ~~~~~~~~ + +error: character literal may only contain one codepoint + --> $DIR/str-as-char.rs:9:19 + | +LL | let _: &str = '\"\"\"'; + | ^^^^^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let _: &str = "\"\"\""; + | ~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/str-as-char.rs:7:19 + | +LL | let _: &str = 'a'; + | ---- ^^^ expected `&str`, found `char` + | | + | expected due to this + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let _: &str = "a"; + | ~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/tutorial-suffix-inference-test.rs b/tests/ui/inference/tutorial-suffix-inference-test.rs new file mode 100644 index 000000000..849adfd53 --- /dev/null +++ b/tests/ui/inference/tutorial-suffix-inference-test.rs @@ -0,0 +1,24 @@ +fn main() { + let x = 3; + let y: i32 = 3; + + fn identity_u8(n: u8) -> u8 { n } + fn identity_u16(n: u16) -> u16 { n } + + identity_u8(x); // after this, `x` is assumed to have type `u8` + identity_u16(x); + //~^ ERROR mismatched types + //~| expected `u16`, found `u8` + identity_u16(y); + //~^ ERROR mismatched types + //~| expected `u16`, found `i32` + + let a = 3; + + fn identity_i(n: isize) -> isize { n } + + identity_i(a); // ok + identity_u16(a); + //~^ ERROR mismatched types + //~| expected `u16`, found `isize` +} diff --git a/tests/ui/inference/tutorial-suffix-inference-test.stderr b/tests/ui/inference/tutorial-suffix-inference-test.stderr new file mode 100644 index 000000000..d83a1367d --- /dev/null +++ b/tests/ui/inference/tutorial-suffix-inference-test.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/tutorial-suffix-inference-test.rs:9:18 + | +LL | identity_u16(x); + | ------------ ^ expected `u16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/tutorial-suffix-inference-test.rs:6:8 + | +LL | fn identity_u16(n: u16) -> u16 { n } + | ^^^^^^^^^^^^ ------ +help: you can convert a `u8` to a `u16` + | +LL | identity_u16(x.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/tutorial-suffix-inference-test.rs:12:18 + | +LL | identity_u16(y); + | ------------ ^ expected `u16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/tutorial-suffix-inference-test.rs:6:8 + | +LL | fn identity_u16(n: u16) -> u16 { n } + | ^^^^^^^^^^^^ ------ +help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit + | +LL | identity_u16(y.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/tutorial-suffix-inference-test.rs:21:18 + | +LL | identity_u16(a); + | ------------ ^ expected `u16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/tutorial-suffix-inference-test.rs:6:8 + | +LL | fn identity_u16(n: u16) -> u16 { n } + | ^^^^^^^^^^^^ ------ +help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit + | +LL | identity_u16(a.try_into().unwrap()); + | ++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/type-infer-generalize-ty-var.rs b/tests/ui/inference/type-infer-generalize-ty-var.rs new file mode 100644 index 000000000..a3d6916cb --- /dev/null +++ b/tests/ui/inference/type-infer-generalize-ty-var.rs @@ -0,0 +1,56 @@ +// run-pass + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +// Test a scenario where we generate a constraint like `?1 <: &?2`. +// In such a case, it is important that we instantiate `?1` with `&?3` +// where `?3 <: ?2`, and not with `&?2`. This is a regression test for +// #18653. The important thing is that we build. + +use std::cell::RefCell; + +enum Wrap { + WrapSome(A), + WrapNone +} + +use Wrap::*; + +struct T; +struct U; + +trait Get { + fn get(&self) -> &T; +} + +impl Get for Wrap { + fn get(&self) -> &(dyn MyShow + 'static) { + static x: usize = 42; + &x + } +} + +impl Get for Wrap { + fn get(&self) -> &usize { + static x: usize = 55; + &x + } +} + +trait MyShow { fn dummy(&self) { } } +impl<'a> MyShow for &'a (dyn MyShow + 'a) { } +impl MyShow for usize { } +fn constrain<'a>(rc: RefCell<&'a (dyn MyShow + 'a)>) { } + +fn main() { + let mut collection: Wrap<_> = WrapNone; + + { + let __arg0 = Get::get(&collection); + let __args_cell = RefCell::new(__arg0); + constrain(__args_cell); + } + collection = WrapSome(T); +} diff --git a/tests/ui/infinite/infinite-autoderef.rs b/tests/ui/infinite/infinite-autoderef.rs new file mode 100644 index 000000000..cbbe1f81d --- /dev/null +++ b/tests/ui/infinite/infinite-autoderef.rs @@ -0,0 +1,26 @@ +// error-pattern: reached the recursion limit while auto-dereferencing +// compile-flags: -Zdeduplicate-diagnostics=yes + +use std::ops::Deref; + +struct Foo; + +impl Deref for Foo { + type Target = Foo; + + fn deref(&self) -> &Foo { + self + } +} + +pub fn main() { + let mut x; + loop { + x = Box::new(x); + x.foo; + x.bar(); + } + + Foo.foo; + Foo.bar(); +} diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr new file mode 100644 index 000000000..51b61e3a6 --- /dev/null +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -0,0 +1,54 @@ +error[E0308]: mismatched types + --> $DIR/infinite-autoderef.rs:19:13 + | +LL | x = Box::new(x); + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | x = *Box::new(x); + | + + +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` + --> $DIR/infinite-autoderef.rs:24:5 + | +LL | Foo.foo; + | ^^^^^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) + +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` + --> $DIR/infinite-autoderef.rs:24:9 + | +LL | Foo.foo; + | ^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) + +error[E0609]: no field `foo` on type `Foo` + --> $DIR/infinite-autoderef.rs:24:9 + | +LL | Foo.foo; + | ^^^ unknown field + +error[E0055]: reached the recursion limit while auto-dereferencing `Foo` + --> $DIR/infinite-autoderef.rs:25:9 + | +LL | Foo.bar(); + | ^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`) + +error[E0599]: no method named `bar` found for struct `Foo` in the current scope + --> $DIR/infinite-autoderef.rs:25:9 + | +LL | struct Foo; + | ---------- method `bar` not found for this struct +... +LL | Foo.bar(); + | ^^^ method not found in `Foo` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0055, E0308, E0599, E0609. +For more information about an error, try `rustc --explain E0055`. diff --git a/tests/ui/infinite/infinite-instantiation.polonius.stderr b/tests/ui/infinite/infinite-instantiation.polonius.stderr new file mode 100644 index 000000000..29eb8c481 --- /dev/null +++ b/tests/ui/infinite/infinite-instantiation.polonius.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `function::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/infinite-instantiation.rs:22:9 + | +LL | function(counter - 1, t.to_option()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `function` defined here + --> $DIR/infinite-instantiation.rs:20:1 + | +LL | fn function(counter: usize, t: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation.polonius/infinite-instantiation.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/infinite/infinite-instantiation.rs b/tests/ui/infinite/infinite-instantiation.rs new file mode 100644 index 000000000..9b9f332ca --- /dev/null +++ b/tests/ui/infinite/infinite-instantiation.rs @@ -0,0 +1,29 @@ +// build-fail +// normalize-stderr-test: ".nll/" -> "/" + +trait ToOpt: Sized { + fn to_option(&self) -> Option; +} + +impl ToOpt for usize { + fn to_option(&self) -> Option { + Some(*self) + } +} + +impl ToOpt for Option { + fn to_option(&self) -> Option> { + Some((*self).clone()) + } +} + +fn function(counter: usize, t: T) { + if counter > 0 { + function(counter - 1, t.to_option()); + //~^ ERROR reached the recursion limit while instantiating `function::>>>>>` + --> $DIR/infinite-instantiation.rs:22:9 + | +LL | function(counter - 1, t.to_option()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `function` defined here + --> $DIR/infinite-instantiation.rs:20:1 + | +LL | fn function(counter: usize, t: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation/infinite-instantiation.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/infinite/infinite-macro-expansion.rs b/tests/ui/infinite/infinite-macro-expansion.rs new file mode 100644 index 000000000..6ea0bc73d --- /dev/null +++ b/tests/ui/infinite/infinite-macro-expansion.rs @@ -0,0 +1,7 @@ +macro_rules! recursive { + () => (recursive!()) //~ ERROR recursion limit reached while expanding `recursive!` +} + +fn main() { + recursive!() +} diff --git a/tests/ui/infinite/infinite-macro-expansion.stderr b/tests/ui/infinite/infinite-macro-expansion.stderr new file mode 100644 index 000000000..15654dfaf --- /dev/null +++ b/tests/ui/infinite/infinite-macro-expansion.stderr @@ -0,0 +1,14 @@ +error: recursion limit reached while expanding `recursive!` + --> $DIR/infinite-macro-expansion.rs:2:12 + | +LL | () => (recursive!()) + | ^^^^^^^^^^^^ +... +LL | recursive!() + | ------------ in this macro invocation + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_macro_expansion`) + = note: this error originates in the macro `recursive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/infinite/infinite-recursion-const-fn.rs b/tests/ui/infinite/infinite-recursion-const-fn.rs new file mode 100644 index 000000000..420915311 --- /dev/null +++ b/tests/ui/infinite/infinite-recursion-const-fn.rs @@ -0,0 +1,11 @@ +//https://github.com/rust-lang/rust/issues/31364 + +const fn a() -> usize { + b() //~ ERROR evaluation of constant value failed [E0080] +} +const fn b() -> usize { + a() +} +const ARR: [i32; a()] = [5; 6]; + +fn main() {} diff --git a/tests/ui/infinite/infinite-recursion-const-fn.stderr b/tests/ui/infinite/infinite-recursion-const-fn.stderr new file mode 100644 index 000000000..53b603a47 --- /dev/null +++ b/tests/ui/infinite/infinite-recursion-const-fn.stderr @@ -0,0 +1,650 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ reached the configured maximum number of stack frames + | +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `b` + --> $DIR/infinite-recursion-const-fn.rs:7:5 + | +LL | a() + | ^^^ +note: inside `a` + --> $DIR/infinite-recursion-const-fn.rs:4:5 + | +LL | b() + | ^^^ +note: inside `ARR::{constant#0}` + --> $DIR/infinite-recursion-const-fn.rs:9:18 + | +LL | const ARR: [i32; a()] = [5; 6]; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/infinite/infinite-struct.rs b/tests/ui/infinite/infinite-struct.rs new file mode 100644 index 000000000..f08e10f6b --- /dev/null +++ b/tests/ui/infinite/infinite-struct.rs @@ -0,0 +1,16 @@ +struct Take(Take); +//~^ ERROR has infinite size + +// check that we don't hang trying to find the tail of a recursive struct (#79437) +fn foo() -> Take { + Take(loop {}) +} + +// mutually infinite structs +struct Foo { //~ ERROR has infinite size + x: Bar, +} + +struct Bar([T; 1]); + +fn main() {} diff --git a/tests/ui/infinite/infinite-struct.stderr b/tests/ui/infinite/infinite-struct.stderr new file mode 100644 index 000000000..b6c72b1de --- /dev/null +++ b/tests/ui/infinite/infinite-struct.stderr @@ -0,0 +1,27 @@ +error[E0072]: recursive type `Take` has infinite size + --> $DIR/infinite-struct.rs:1:1 + | +LL | struct Take(Take); + | ^^^^^^^^^^^ ---- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Take(Box); + | ++++ + + +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/infinite-struct.rs:10:1 + | +LL | struct Foo { + | ^^^^^^^^^^ +LL | x: Bar, + | --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | x: Bar>, + | ++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/infinite/infinite-tag-type-recursion.rs b/tests/ui/infinite/infinite-tag-type-recursion.rs new file mode 100644 index 000000000..87a9e08dd --- /dev/null +++ b/tests/ui/infinite/infinite-tag-type-recursion.rs @@ -0,0 +1,4 @@ +enum MList { Cons(isize, MList), Nil } +//~^ ERROR recursive type `MList` has infinite size + +fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/tests/ui/infinite/infinite-tag-type-recursion.stderr b/tests/ui/infinite/infinite-tag-type-recursion.stderr new file mode 100644 index 000000000..513bbfc1b --- /dev/null +++ b/tests/ui/infinite/infinite-tag-type-recursion.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `MList` has infinite size + --> $DIR/infinite-tag-type-recursion.rs:1:1 + | +LL | enum MList { Cons(isize, MList), Nil } + | ^^^^^^^^^^ ----- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum MList { Cons(isize, Box), Nil } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/infinite/infinite-trait-alias-recursion.rs b/tests/ui/infinite/infinite-trait-alias-recursion.rs new file mode 100644 index 000000000..ec86744e6 --- /dev/null +++ b/tests/ui/infinite/infinite-trait-alias-recursion.rs @@ -0,0 +1,10 @@ +#![feature(trait_alias)] + +trait T1 = T2; +//~^ ERROR cycle detected when computing the super predicates of `T1` + +trait T2 = T3; + +trait T3 = T1 + T3; + +fn main() {} diff --git a/tests/ui/infinite/infinite-trait-alias-recursion.stderr b/tests/ui/infinite/infinite-trait-alias-recursion.stderr new file mode 100644 index 000000000..b925b3b01 --- /dev/null +++ b/tests/ui/infinite/infinite-trait-alias-recursion.stderr @@ -0,0 +1,42 @@ +error[E0391]: cycle detected when computing the super predicates of `T1` + --> $DIR/infinite-trait-alias-recursion.rs:3:1 + | +LL | trait T1 = T2; + | ^^^^^^^^ + | +note: ...which requires computing the super traits of `T1`... + --> $DIR/infinite-trait-alias-recursion.rs:3:12 + | +LL | trait T1 = T2; + | ^^ +note: ...which requires computing the super predicates of `T2`... + --> $DIR/infinite-trait-alias-recursion.rs:6:1 + | +LL | trait T2 = T3; + | ^^^^^^^^ +note: ...which requires computing the super traits of `T2`... + --> $DIR/infinite-trait-alias-recursion.rs:6:12 + | +LL | trait T2 = T3; + | ^^ +note: ...which requires computing the super predicates of `T3`... + --> $DIR/infinite-trait-alias-recursion.rs:8:1 + | +LL | trait T3 = T1 + T3; + | ^^^^^^^^ +note: ...which requires computing the super traits of `T3`... + --> $DIR/infinite-trait-alias-recursion.rs:8:12 + | +LL | trait T3 = T1 + T3; + | ^^ + = note: ...which again requires computing the super predicates of `T1`, completing the cycle + = note: trait aliases cannot be recursive +note: cycle used when collecting item types in top-level module + --> $DIR/infinite-trait-alias-recursion.rs:3:1 + | +LL | trait T1 = T2; + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs new file mode 100644 index 000000000..5381eedcf --- /dev/null +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs @@ -0,0 +1,6 @@ +type X1 = X2; +//~^ ERROR cycle detected when expanding type alias `X1` +type X2 = X3; +type X3 = X1; + +fn main() {} diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.stderr new file mode 100644 index 000000000..7f82b2944 --- /dev/null +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.stderr @@ -0,0 +1,34 @@ +error[E0391]: cycle detected when expanding type alias `X1` + --> $DIR/infinite-type-alias-mutual-recursion.rs:1:11 + | +LL | type X1 = X2; + | ^^ + | +note: ...which requires expanding type alias `X2`... + --> $DIR/infinite-type-alias-mutual-recursion.rs:3:11 + | +LL | type X2 = X3; + | ^^ +note: ...which requires expanding type alias `X3`... + --> $DIR/infinite-type-alias-mutual-recursion.rs:4:11 + | +LL | type X3 = X1; + | ^^ + = note: ...which again requires expanding type alias `X1`, completing the cycle + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when collecting item types in top-level module + --> $DIR/infinite-type-alias-mutual-recursion.rs:1:1 + | +LL | / type X1 = X2; +LL | | +LL | | type X2 = X3; +LL | | type X3 = X1; +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/infinite/infinite-vec-type-recursion.rs b/tests/ui/infinite/infinite-vec-type-recursion.rs new file mode 100644 index 000000000..356818225 --- /dev/null +++ b/tests/ui/infinite/infinite-vec-type-recursion.rs @@ -0,0 +1,4 @@ +type X = Vec; +//~^ ERROR cycle detected + +fn main() { let b: X = Vec::new(); } diff --git a/tests/ui/infinite/infinite-vec-type-recursion.stderr b/tests/ui/infinite/infinite-vec-type-recursion.stderr new file mode 100644 index 000000000..1e487a5b1 --- /dev/null +++ b/tests/ui/infinite/infinite-vec-type-recursion.stderr @@ -0,0 +1,22 @@ +error[E0391]: cycle detected when expanding type alias `X` + --> $DIR/infinite-vec-type-recursion.rs:1:14 + | +LL | type X = Vec; + | ^ + | + = note: ...which immediately requires expanding type alias `X` again + = note: type aliases cannot be recursive + = help: consider using a struct, enum, or union instead to break the cycle + = help: see for more information +note: cycle used when collecting item types in top-level module + --> $DIR/infinite-vec-type-recursion.rs:1:1 + | +LL | / type X = Vec; +LL | | +LL | | +LL | | fn main() { let b: X = Vec::new(); } + | |____________________________________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/infinite/issue-41731-infinite-macro-print.rs b/tests/ui/infinite/issue-41731-infinite-macro-print.rs new file mode 100644 index 000000000..d52e6e7e9 --- /dev/null +++ b/tests/ui/infinite/issue-41731-infinite-macro-print.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z trace-macros + +#![recursion_limit = "5"] + +fn main() { + macro_rules! stack { + ($overflow:expr) => { + print!(stack!($overflow)); + //~^ ERROR recursion limit reached while expanding + //~| ERROR format argument must be a string literal + }; + } + + stack!("overflow"); +} diff --git a/tests/ui/infinite/issue-41731-infinite-macro-print.stderr b/tests/ui/infinite/issue-41731-infinite-macro-print.stderr new file mode 100644 index 000000000..e30b2039d --- /dev/null +++ b/tests/ui/infinite/issue-41731-infinite-macro-print.stderr @@ -0,0 +1,38 @@ +error: recursion limit reached while expanding `$crate::format_args!` + --> $DIR/issue-41731-infinite-macro-print.rs:14:5 + | +LL | stack!("overflow"); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "10"]` attribute to your crate (`issue_41731_infinite_macro_print`) + = note: this error originates in the macro `print` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: trace_macro + --> $DIR/issue-41731-infinite-macro-print.rs:14:5 + | +LL | stack!("overflow"); + | ^^^^^^^^^^^^^^^^^^ + | + = note: expanding `stack! { "overflow" }` + = note: to `print! (stack! ("overflow")) ;` + = note: expanding `print! { stack! ("overflow") }` + = note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))) ; }` + = note: expanding `stack! { "overflow" }` + = note: to `print! (stack! ("overflow")) ;` + = note: expanding `print! { stack! ("overflow") }` + = note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))) ; }` + +error: format argument must be a string literal + --> $DIR/issue-41731-infinite-macro-print.rs:14:5 + | +LL | stack!("overflow"); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `print` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might be missing a string literal to format with + | +LL | print!("{}", stack!($overflow)); + | +++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/infinite/issue-41731-infinite-macro-println.rs b/tests/ui/infinite/issue-41731-infinite-macro-println.rs new file mode 100644 index 000000000..3c2b7ee02 --- /dev/null +++ b/tests/ui/infinite/issue-41731-infinite-macro-println.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z trace-macros + +#![recursion_limit = "5"] + +fn main() { + macro_rules! stack { + ($overflow:expr) => { + println!(stack!($overflow)); + //~^ ERROR recursion limit reached while expanding + //~| ERROR format argument must be a string literal + }; + } + + stack!("overflow"); +} diff --git a/tests/ui/infinite/issue-41731-infinite-macro-println.stderr b/tests/ui/infinite/issue-41731-infinite-macro-println.stderr new file mode 100644 index 000000000..66b466daf --- /dev/null +++ b/tests/ui/infinite/issue-41731-infinite-macro-println.stderr @@ -0,0 +1,38 @@ +error: recursion limit reached while expanding `$crate::format_args_nl!` + --> $DIR/issue-41731-infinite-macro-println.rs:14:5 + | +LL | stack!("overflow"); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "10"]` attribute to your crate (`issue_41731_infinite_macro_println`) + = note: this error originates in the macro `println` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: trace_macro + --> $DIR/issue-41731-infinite-macro-println.rs:14:5 + | +LL | stack!("overflow"); + | ^^^^^^^^^^^^^^^^^^ + | + = note: expanding `stack! { "overflow" }` + = note: to `println! (stack! ("overflow")) ;` + = note: expanding `println! { stack! ("overflow") }` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))) ; }` + = note: expanding `stack! { "overflow" }` + = note: to `println! (stack! ("overflow")) ;` + = note: expanding `println! { stack! ("overflow") }` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))) ; }` + +error: format argument must be a string literal + --> $DIR/issue-41731-infinite-macro-println.rs:14:5 + | +LL | stack!("overflow"); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `println` which comes from the expansion of the macro `stack` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might be missing a string literal to format with + | +LL | println!("{}", stack!($overflow)); + | +++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs b/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs new file mode 100644 index 000000000..42ed5d19d --- /dev/null +++ b/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs @@ -0,0 +1,54 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt}; + +// This constant has to be above the ALLOCATING_ALGO_THRESHOLD +// constant in inherent_impls_overlap.rs +const REPEAT_COUNT: u32 = 501; + +#[proc_macro] +/// Repeats the input many times, while replacing idents +/// named "IDENT" with "id_$v", where v is a counter. +pub fn repeat_with_idents(input: TokenStream) -> TokenStream { + let mut res = Vec::new(); + fn visit_stream(res: &mut Vec, stream :TokenStream, v: u32) { + let mut stream_iter = stream.into_iter(); + while let Some(tt) = stream_iter.next() { + match tt { + Tt::Group(group) => { + let tt = Tt::Group(visit_group(group, v)); + res.push(tt); + }, + Tt::Ident(id) => { + let id = if &id.to_string() == "IDENT" { + Ident::new(&format!("id_{}", v), id.span()) + } else { + id + }; + res.push(Tt::Ident(id)); + }, + Tt::Punct(p) => { + res.push(Tt::Punct(p)); + }, + Tt::Literal(lit) => { + res.push(Tt::Literal(lit)); + }, + } + } + } + fn visit_group(group :Group, v: u32) -> Group { + let mut res = Vec::new(); + visit_stream(&mut res, group.stream(), v); + let stream = res.into_iter().collect(); + let delim = group.delimiter(); + Group::new(delim, stream) + } + for v in 0 .. REPEAT_COUNT { + visit_stream(&mut res, input.clone(), v) + } + res.into_iter().collect() +} diff --git a/tests/ui/inherent-impls-overlap-check/no-overlap.rs b/tests/ui/inherent-impls-overlap-check/no-overlap.rs new file mode 100644 index 000000000..450e6d420 --- /dev/null +++ b/tests/ui/inherent-impls-overlap-check/no-overlap.rs @@ -0,0 +1,53 @@ +// run-pass +// aux-build:repeat.rs + +// This tests the allocating algo branch of the +// inherent impls overlap checker. +// This branch was added by PR: +// https://github.com/rust-lang/rust/pull/78317 +// In this test, we repeat many impl blocks +// to trigger the allocating branch. + +#![allow(unused)] + +extern crate repeat; + +// Simple case where each impl block is distinct + +struct Foo {} + +repeat::repeat_with_idents!(impl Foo { fn IDENT() {} }); + +// There are overlapping impl blocks but due to generics, +// they may overlap. + +struct Bar(T); + +struct A; +struct B; + +repeat::repeat_with_idents!(impl Bar { fn IDENT() {} }); + +impl Bar { fn foo() {} } +impl Bar { fn foo() {} } + +// Regression test for issue #89820: + +impl Bar { + pub fn a() {} + pub fn aa() {} +} + +impl Bar { + pub fn b() {} + pub fn bb() {} +} + +impl Bar { + pub fn a() {} + pub fn aa() {} + pub fn bb() {} + pub fn b() {} +} + +fn main() {} diff --git a/tests/ui/inherent-impls-overlap-check/overlap.rs b/tests/ui/inherent-impls-overlap-check/overlap.rs new file mode 100644 index 000000000..6f2801197 --- /dev/null +++ b/tests/ui/inherent-impls-overlap-check/overlap.rs @@ -0,0 +1,71 @@ +// aux-build:repeat.rs + +#![allow(unused)] + +// This tests the allocating algo branch of the +// inherent impls overlap checker. +// This branch was added by PR: +// https://github.com/rust-lang/rust/pull/78317 +// In this test, we repeat many impl blocks +// to trigger the allocating branch. + +// Simple overlap + +extern crate repeat; + +struct Foo {} + +repeat::repeat_with_idents!(impl Foo { fn IDENT() {} }); + +impl Foo { fn hello() {} } //~ERROR duplicate definitions with name `hello` +impl Foo { fn hello() {} } + +// Transitive overlap + +struct Foo2 {} + +repeat::repeat_with_idents!(impl Foo2 { fn IDENT() {} }); + +impl Foo2 { + fn bar() {} + fn hello2() {} //~ERROR duplicate definitions with name `hello2` +} + +impl Foo2 { + fn baz() {} + fn hello2() {} +} + +// Slightly stronger transitive overlap + +struct Foo3 {} + +repeat::repeat_with_idents!(impl Foo3 { fn IDENT() {} }); + +impl Foo3 { + fn bar() {} //~ERROR duplicate definitions with name `bar` + fn hello3() {} //~ERROR duplicate definitions with name `hello3` +} + +impl Foo3 { + fn bar() {} + fn hello3() {} +} + +// Generic overlap + +struct Bar(T); + +struct A; +struct B; + +repeat::repeat_with_idents!(impl Bar { fn IDENT() {} }); + +impl Bar { fn foo() {} fn bar2() {} } +impl Bar { + fn foo() {} + fn bar2() {} //~ERROR duplicate definitions with name `bar2` +} +impl Bar { fn bar2() {} } + +fn main() {} diff --git a/tests/ui/inherent-impls-overlap-check/overlap.stderr b/tests/ui/inherent-impls-overlap-check/overlap.stderr new file mode 100644 index 000000000..3dd279371 --- /dev/null +++ b/tests/ui/inherent-impls-overlap-check/overlap.stderr @@ -0,0 +1,47 @@ +error[E0592]: duplicate definitions with name `hello` + --> $DIR/overlap.rs:20:12 + | +LL | impl Foo { fn hello() {} } + | ^^^^^^^^^^ duplicate definitions for `hello` +LL | impl Foo { fn hello() {} } + | ---------- other definition for `hello` + +error[E0592]: duplicate definitions with name `hello2` + --> $DIR/overlap.rs:31:5 + | +LL | fn hello2() {} + | ^^^^^^^^^^^ duplicate definitions for `hello2` +... +LL | fn hello2() {} + | ----------- other definition for `hello2` + +error[E0592]: duplicate definitions with name `bar` + --> $DIR/overlap.rs:46:5 + | +LL | fn bar() {} + | ^^^^^^^^ duplicate definitions for `bar` +... +LL | fn bar() {} + | -------- other definition for `bar` + +error[E0592]: duplicate definitions with name `hello3` + --> $DIR/overlap.rs:47:5 + | +LL | fn hello3() {} + | ^^^^^^^^^^^ duplicate definitions for `hello3` +... +LL | fn hello3() {} + | ----------- other definition for `hello3` + +error[E0592]: duplicate definitions with name `bar2` + --> $DIR/overlap.rs:67:5 + | +LL | fn bar2() {} + | ^^^^^^^^^ duplicate definitions for `bar2` +LL | } +LL | impl Bar { fn bar2() {} } + | --------- other definition for `bar2` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/inherit-env.rs b/tests/ui/inherit-env.rs new file mode 100644 index 000000000..e29fa04bb --- /dev/null +++ b/tests/ui/inherit-env.rs @@ -0,0 +1,26 @@ +// run-pass +// ignore-emscripten +// ignore-wasm32 +// ignore-sgx no processes + +use std::env; +use std::process::Command; + +fn main() { + if env::args().nth(1).map(|s| s == "print").unwrap_or(false) { + for (k, v) in env::vars() { + println!("{}={}", k, v); + } + return + } + + let me = env::current_exe().unwrap(); + let result = Command::new(me).arg("print").output().unwrap(); + let output = String::from_utf8(result.stdout).unwrap(); + + for (k, v) in env::vars() { + assert!(output.contains(&format!("{}={}", k, v)), + "output doesn't contain `{}={}`\n{}", + k, v, output); + } +} diff --git a/tests/ui/inline-const/const-expr-array-init.rs b/tests/ui/inline-const/const-expr-array-init.rs new file mode 100644 index 000000000..8a92cdbc0 --- /dev/null +++ b/tests/ui/inline-const/const-expr-array-init.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(inline_const)] + +use std::cell::Cell; + +fn main() { + let _x = [const { Cell::new(0) }; 20]; +} diff --git a/tests/ui/inline-const/const-expr-basic.rs b/tests/ui/inline-const/const-expr-basic.rs new file mode 100644 index 000000000..dac46fe25 --- /dev/null +++ b/tests/ui/inline-const/const-expr-basic.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(inline_const)] + +fn foo() -> i32 { + const { + let x = 5 + 10; + x / 3 + } +} + +fn main() { + assert_eq!(5, foo()); +} diff --git a/tests/ui/inline-const/const-expr-generic-err.rs b/tests/ui/inline-const/const-expr-generic-err.rs new file mode 100644 index 000000000..4e8879af5 --- /dev/null +++ b/tests/ui/inline-const/const-expr-generic-err.rs @@ -0,0 +1,15 @@ +// build-fail +#![feature(inline_const)] + +fn foo() { + const { assert!(std::mem::size_of::() == 0); } //~ ERROR E0080 +} + +fn bar() -> usize { + const { N - 1 } //~ ERROR E0080 +} + +fn main() { + foo::(); + bar::<0>(); +} diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr new file mode 100644 index 000000000..fc0b6cc44 --- /dev/null +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -0,0 +1,29 @@ +error[E0080]: evaluation of `foo::::{constant#0}` failed + --> $DIR/const-expr-generic-err.rs:5:13 + | +LL | const { assert!(std::mem::size_of::() == 0); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:5:13 + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: the above error was encountered while instantiating `fn foo::` + --> $DIR/const-expr-generic-err.rs:13:5 + | +LL | foo::(); + | ^^^^^^^^^^^^ + +error[E0080]: evaluation of `bar::<0>::{constant#0}` failed + --> $DIR/const-expr-generic-err.rs:9:13 + | +LL | const { N - 1 } + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +note: the above error was encountered while instantiating `fn bar::<0>` + --> $DIR/const-expr-generic-err.rs:14:5 + | +LL | bar::<0>(); + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/inline-const/const-expr-generic-err2.rs b/tests/ui/inline-const/const-expr-generic-err2.rs new file mode 100644 index 000000000..e097cbe9d --- /dev/null +++ b/tests/ui/inline-const/const-expr-generic-err2.rs @@ -0,0 +1,10 @@ +#![feature(inline_const)] + +fn foo() { + let _ = [0u8; const { std::mem::size_of::() }]; + //~^ ERROR: constant expression depends on a generic parameter +} + +fn main() { + foo::(); +} diff --git a/tests/ui/inline-const/const-expr-generic-err2.stderr b/tests/ui/inline-const/const-expr-generic-err2.stderr new file mode 100644 index 000000000..00b716cd2 --- /dev/null +++ b/tests/ui/inline-const/const-expr-generic-err2.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/const-expr-generic-err2.rs:4:19 + | +LL | let _ = [0u8; const { std::mem::size_of::() }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/inline-const/const-expr-generic.rs b/tests/ui/inline-const/const-expr-generic.rs new file mode 100644 index 000000000..3207bfa0e --- /dev/null +++ b/tests/ui/inline-const/const-expr-generic.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(inline_const)] + +fn foo() -> usize { + const { std::mem::size_of::() } +} + +fn bar() -> usize { + const { N + 1 } +} + +fn main() { + foo::(); + bar::<1>(); +} diff --git a/tests/ui/inline-const/const-expr-inference.rs b/tests/ui/inline-const/const-expr-inference.rs new file mode 100644 index 000000000..0d5892a74 --- /dev/null +++ b/tests/ui/inline-const/const-expr-inference.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(inline_const)] + +pub fn todo() -> T { + const { todo!() } +} + +fn main() { + let _: usize = const { 0 }; +} diff --git a/tests/ui/inline-const/const-expr-lifetime-err.rs b/tests/ui/inline-const/const-expr-lifetime-err.rs new file mode 100644 index 000000000..0a032a733 --- /dev/null +++ b/tests/ui/inline-const/const-expr-lifetime-err.rs @@ -0,0 +1,29 @@ +#![feature(const_mut_refs)] +#![feature(inline_const)] + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +impl<'a> InvariantRef<'a, ()> { + pub const NEW: Self = InvariantRef::new(&()); +} + +fn equate(x: T, y: T){} + +fn foo<'a>() { + let y = (); + equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW }); + //~^ ERROR `y` does not live long enough [E0597] +} + +fn main() { + foo(); +} diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr new file mode 100644 index 000000000..a23f7c9a7 --- /dev/null +++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr @@ -0,0 +1,18 @@ +error[E0597]: `y` does not live long enough + --> $DIR/const-expr-lifetime-err.rs:23:30 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let y = (); +LL | equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW }); + | ------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `y` is borrowed for `'a` +LL | +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/inline-const/const-expr-lifetime.rs b/tests/ui/inline-const/const-expr-lifetime.rs new file mode 100644 index 000000000..d883deb28 --- /dev/null +++ b/tests/ui/inline-const/const-expr-lifetime.rs @@ -0,0 +1,35 @@ +// run-pass + +#![feature(const_mut_refs)] +#![feature(inline_const)] + +use std::marker::PhantomData; + +// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" +fn issue_78174() { + let foo = const { "foo" }; + assert_eq!(foo, "foo"); +} + +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +fn get_invariant_ref<'a>() -> InvariantRef<'a, ()> { + const { InvariantRef::<'a, ()>::new(&()) } +} + +fn get_invariant_ref2<'a>() -> InvariantRef<'a, ()> { + // Try some type inference + const { InvariantRef::new(&()) } +} + +fn main() { + issue_78174(); + get_invariant_ref(); + get_invariant_ref2(); +} diff --git a/tests/ui/inline-const/const-expr-macro.rs b/tests/ui/inline-const/const-expr-macro.rs new file mode 100644 index 000000000..041f3e15a --- /dev/null +++ b/tests/ui/inline-const/const-expr-macro.rs @@ -0,0 +1,12 @@ +// run-pass + +#![feature(inline_const)] + +macro_rules! do_const_block{ + ($val:block) => { const $val } +} + +fn main() { + let s = do_const_block!({ 22 }); + assert_eq!(s, 22); +} diff --git a/tests/ui/inline-const/const-expr-reference.rs b/tests/ui/inline-const/const-expr-reference.rs new file mode 100644 index 000000000..a54d879f6 --- /dev/null +++ b/tests/ui/inline-const/const-expr-reference.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(inline_const)] + +const fn bar() -> i32 { + const { + 2 + 3 + } +} + +fn main() { + let x: &'static i32 = &const{bar()}; + assert_eq!(&5, x); +} diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs new file mode 100644 index 000000000..7c0d83516 --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-generic.rs @@ -0,0 +1,31 @@ +#![allow(incomplete_features)] +#![feature(inline_const_pat)] + +// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter + +fn foo() { + match 0 { + const { V } => {}, + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter + _ => {}, + } +} + +const fn f(x: usize) -> usize { + x + 1 +} + +fn bar() { + match 0 { + const { f(V) } => {}, + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter + _ => {}, + } +} + +fn main() { + foo::<1>(); + bar::<1>(); +} diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr new file mode 100644 index 000000000..77267f12f --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -0,0 +1,26 @@ +error: constant pattern depends on a generic parameter + --> $DIR/const-match-pat-generic.rs:8:9 + | +LL | const { V } => {}, + | ^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/const-match-pat-generic.rs:21:9 + | +LL | const { f(V) } => {}, + | ^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/const-match-pat-generic.rs:8:9 + | +LL | const { V } => {}, + | ^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/const-match-pat-generic.rs:21:9 + | +LL | const { f(V) } => {}, + | ^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/inline-const/const-match-pat-inference.rs b/tests/ui/inline-const/const-match-pat-inference.rs new file mode 100644 index 000000000..d83ae6e98 --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-inference.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(inline_const_pat)] +#![allow(incomplete_features)] + +fn main() { + match 1u64 { + 0 => (), + const { 0 + 1 } => (), + const { 2 - 1 } ..= const { u64::MAX } => (), + } +} diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs new file mode 100644 index 000000000..436b8037f --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.rs @@ -0,0 +1,34 @@ +// ignore-test + +#![allow(incomplete_features)] +#![feature(const_mut_refs)] +#![feature(inline_const_pat)] + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +impl<'a> InvariantRef<'a, ()> { + pub const NEW: Self = InvariantRef::new(&()); +} + +fn match_invariant_ref<'a>() { + let y = (); + match InvariantRef::new(&y) { + //~^ ERROR `y` does not live long enough [E0597] + // FIXME(nbdd0121): This should give the same error as `InvariantRef::<'a>::NEW` (without + // const block) + const { InvariantRef::<'a>::NEW } => (), + } +} + +fn main() { + match_invariant_ref(); +} diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs new file mode 100644 index 000000000..6d943bbcc --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-lifetime.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(const_mut_refs)] +#![feature(inline_const)] +#![feature(inline_const_pat)] + +use std::marker::PhantomData; + +// rust-lang/rust#78174: ICE: "cannot convert ReErased to a region vid" +fn issue_78174() { + match "foo" { + const { concat!("fo", "o") } => (), + _ => unreachable!(), + } +} + +#[derive(PartialEq, Eq)] +pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>); + +impl<'a, T: ?Sized> InvariantRef<'a, T> { + pub const fn new(r: &'a T) -> Self { + InvariantRef(r, PhantomData) + } +} + +fn match_invariant_ref<'a>() { + match const { InvariantRef::<'a, _>::new(&()) } { + const { InvariantRef::<'a, ()>::new(&()) } => { + } + } +} + +fn main() { + issue_78174(); + match_invariant_ref(); +} diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs new file mode 100644 index 000000000..73d6334c3 --- /dev/null +++ b/tests/ui/inline-const/const-match-pat-range.rs @@ -0,0 +1,39 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(inline_const_pat, exclusive_range_pattern)] + +fn main() { + const N: u32 = 10; + let x: u32 = 3; + + match x { + 1 ..= const { N + 1 } => {}, + _ => {}, + } + + match x { + const { N - 1 } ..= 10 => {}, + _ => {}, + } + + match x { + const { N - 1 } ..= const { N + 1 } => {}, + _ => {}, + } + + match x { + .. const { N + 1 } => {}, + _ => {}, + } + + match x { + const { N - 1 } .. => {}, + _ => {}, + } + + match x { + ..= const { N + 1 } => {}, + _ => {} + } +} diff --git a/tests/ui/inline-const/const-match-pat.rs b/tests/ui/inline-const/const-match-pat.rs new file mode 100644 index 000000000..2f55e16b3 --- /dev/null +++ b/tests/ui/inline-const/const-match-pat.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(inline_const_pat)] +const MMIO_BIT1: u8 = 4; +const MMIO_BIT2: u8 = 5; + +fn main() { + let s = match read_mmio() { + 0 => "FOO", + const { 1 << MMIO_BIT1 } => "BAR", + const { 1 << MMIO_BIT2 } => "BAZ", + _ => unreachable!(), + }; + + assert_eq!("BAZ", s); +} + +fn read_mmio() -> i32 { + 1 << 5 +} diff --git a/tests/ui/inline-const/expr-unsafe-err.mir.stderr b/tests/ui/inline-const/expr-unsafe-err.mir.stderr new file mode 100644 index 000000000..1bec41e2e --- /dev/null +++ b/tests/ui/inline-const/expr-unsafe-err.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/expr-unsafe-err.rs:8:9 + | +LL | require_unsafe(); + | ^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/expr-unsafe-err.rs b/tests/ui/inline-const/expr-unsafe-err.rs new file mode 100644 index 000000000..adf05d352 --- /dev/null +++ b/tests/ui/inline-const/expr-unsafe-err.rs @@ -0,0 +1,11 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +#![feature(inline_const)] +const unsafe fn require_unsafe() -> usize { 1 } + +fn main() { + const { + require_unsafe(); + //~^ ERROR [E0133] + } +} diff --git a/tests/ui/inline-const/expr-unsafe-err.thir.stderr b/tests/ui/inline-const/expr-unsafe-err.thir.stderr new file mode 100644 index 000000000..c971e8afb --- /dev/null +++ b/tests/ui/inline-const/expr-unsafe-err.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block + --> $DIR/expr-unsafe-err.rs:8:9 + | +LL | require_unsafe(); + | ^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/expr-unsafe.mir.stderr b/tests/ui/inline-const/expr-unsafe.mir.stderr new file mode 100644 index 000000000..1ab6e42fb --- /dev/null +++ b/tests/ui/inline-const/expr-unsafe.mir.stderr @@ -0,0 +1,14 @@ +warning: unnecessary `unsafe` block + --> $DIR/expr-unsafe.rs:12:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/expr-unsafe.rs:4:9 + | +LL | #![warn(unused_unsafe)] + | ^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/inline-const/expr-unsafe.rs b/tests/ui/inline-const/expr-unsafe.rs new file mode 100644 index 000000000..d71efd33d --- /dev/null +++ b/tests/ui/inline-const/expr-unsafe.rs @@ -0,0 +1,16 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +#![warn(unused_unsafe)] +#![feature(inline_const)] +const unsafe fn require_unsafe() -> usize { 1 } + +fn main() { + unsafe { + const { + require_unsafe(); + unsafe {} + //~^ WARNING unnecessary `unsafe` block + } + } +} diff --git a/tests/ui/inline-const/expr-unsafe.thir.stderr b/tests/ui/inline-const/expr-unsafe.thir.stderr new file mode 100644 index 000000000..4737444fb --- /dev/null +++ b/tests/ui/inline-const/expr-unsafe.thir.stderr @@ -0,0 +1,17 @@ +warning: unnecessary `unsafe` block + --> $DIR/expr-unsafe.rs:12:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/expr-unsafe.rs:4:9 + | +LL | #![warn(unused_unsafe)] + | ^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/inline-const/expr-with-block-err.rs b/tests/ui/inline-const/expr-with-block-err.rs new file mode 100644 index 000000000..f7547742d --- /dev/null +++ b/tests/ui/inline-const/expr-with-block-err.rs @@ -0,0 +1,6 @@ +#![feature(inline_const)] + +fn main() { + const { 2 } - const { 1 }; + //~^ ERROR mismatched types +} diff --git a/tests/ui/inline-const/expr-with-block-err.stderr b/tests/ui/inline-const/expr-with-block-err.stderr new file mode 100644 index 000000000..6f7408f4e --- /dev/null +++ b/tests/ui/inline-const/expr-with-block-err.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/expr-with-block-err.rs:4:13 + | +LL | const { 2 } - const { 1 }; + | ^ expected `()`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inline-const/expr-with-block.rs b/tests/ui/inline-const/expr-with-block.rs new file mode 100644 index 000000000..391872476 --- /dev/null +++ b/tests/ui/inline-const/expr-with-block.rs @@ -0,0 +1,10 @@ +// check-pass +#![feature(inline_const)] +fn main() { + match true { + true => const {} + false => () + } + const {} + () +} diff --git a/tests/ui/inline-const/macro-with-const.rs b/tests/ui/inline-const/macro-with-const.rs new file mode 100644 index 000000000..e7393166d --- /dev/null +++ b/tests/ui/inline-const/macro-with-const.rs @@ -0,0 +1,20 @@ +// check-pass + +macro_rules! exp { + (const $n:expr) => { + $n + }; +} + +macro_rules! stmt { + (exp $e:expr) => { + $e + }; + (exp $($t:tt)+) => { + exp!($($t)+) + }; +} + +fn main() { + stmt!(exp const 1); +} diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs new file mode 100644 index 000000000..e290b438c --- /dev/null +++ b/tests/ui/inline-const/pat-unsafe-err.rs @@ -0,0 +1,17 @@ +// ignore-test This is currently broken +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![allow(incomplete_features)] +#![feature(inline_const_pat)] + +const unsafe fn require_unsafe() -> usize { 1 } + +fn main() { + match () { + const { + require_unsafe(); + //~^ ERROR [E0133] + } => (), + } +} diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs new file mode 100644 index 000000000..bcf7f6e01 --- /dev/null +++ b/tests/ui/inline-const/pat-unsafe.rs @@ -0,0 +1,22 @@ +// ignore-test This is currently broken +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![allow(incomplete_features)] +#![warn(unused_unsafe)] +#![feature(inline_const_pat)] + +const unsafe fn require_unsafe() -> usize { 1 } + +fn main() { + unsafe { + match () { + const { + require_unsafe(); + unsafe {} + //~^ WARNING unnecessary `unsafe` block + } => (), + } + } +} diff --git a/tests/ui/inline-disallow-on-variant.rs b/tests/ui/inline-disallow-on-variant.rs new file mode 100644 index 000000000..d92a4e8cc --- /dev/null +++ b/tests/ui/inline-disallow-on-variant.rs @@ -0,0 +1,7 @@ +enum Foo { + #[inline] + //~^ ERROR attribute should be applied + Variant, +} + +fn main() {} diff --git a/tests/ui/inline-disallow-on-variant.stderr b/tests/ui/inline-disallow-on-variant.stderr new file mode 100644 index 000000000..1b176579b --- /dev/null +++ b/tests/ui/inline-disallow-on-variant.stderr @@ -0,0 +1,12 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-disallow-on-variant.rs:2:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | +LL | Variant, + | ------- not a function or closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/inlined-main.rs b/tests/ui/inlined-main.rs new file mode 100644 index 000000000..75ff4c87d --- /dev/null +++ b/tests/ui/inlined-main.rs @@ -0,0 +1,4 @@ +// run-pass + +#[inline(always)] +fn main() {} diff --git a/tests/ui/inner-attrs-on-impl.rs b/tests/ui/inner-attrs-on-impl.rs new file mode 100644 index 000000000..636e8c488 --- /dev/null +++ b/tests/ui/inner-attrs-on-impl.rs @@ -0,0 +1,24 @@ +// run-pass + +struct Foo; + +impl Foo { + #![cfg(cfg_that_surely_doesnt_exist)] + + fn method(&self) -> bool { false } +} + +impl Foo { + #![cfg(not(cfg_that_surely_doesnt_exist))] + + // check that we don't eat attributes too eagerly. + #[cfg(cfg_that_surely_doesnt_exist)] + fn method(&self) -> bool { false } + + fn method(&self) -> bool { true } +} + + +pub fn main() { + assert!(Foo.method()); +} diff --git a/tests/ui/inner-module.rs b/tests/ui/inner-module.rs new file mode 100644 index 000000000..363f753e2 --- /dev/null +++ b/tests/ui/inner-module.rs @@ -0,0 +1,10 @@ +// run-pass + +mod inner { + pub mod inner2 { + pub fn hello() { println!("hello, modular world"); } + } + pub fn hello() { inner2::hello(); } +} + +pub fn main() { inner::hello(); inner::inner2::hello(); } diff --git a/tests/ui/inner-static-type-parameter.rs b/tests/ui/inner-static-type-parameter.rs new file mode 100644 index 000000000..c08ccd29d --- /dev/null +++ b/tests/ui/inner-static-type-parameter.rs @@ -0,0 +1,11 @@ +// see #9186 + +enum Bar { What } //~ ERROR parameter `T` is never used + +fn foo() { + static a: Bar = Bar::What; +//~^ ERROR can't use generic parameters from outer function +} + +fn main() { +} diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/inner-static-type-parameter.stderr new file mode 100644 index 000000000..e4e449e41 --- /dev/null +++ b/tests/ui/inner-static-type-parameter.stderr @@ -0,0 +1,21 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/inner-static-type-parameter.rs:6:19 + | +LL | fn foo() { + | - type parameter from outer function +LL | static a: Bar = Bar::What; + | ^ use of generic parameter from outer function + +error[E0392]: parameter `T` is never used + --> $DIR/inner-static-type-parameter.rs:3:10 + | +LL | enum Bar { What } + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0401. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/inner-static.rs b/tests/ui/inner-static.rs new file mode 100644 index 000000000..adba299eb --- /dev/null +++ b/tests/ui/inner-static.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:inner_static.rs + + +extern crate inner_static; + +pub fn main() { + let a = inner_static::A::<()> { v: () }; + let b = inner_static::B::<()> { v: () }; + let c = inner_static::test::A::<()> { v: () }; + assert_eq!(a.bar(), 2); + assert_eq!(b.bar(), 4); + assert_eq!(c.bar(), 6); +} diff --git a/tests/ui/integral-indexing.rs b/tests/ui/integral-indexing.rs new file mode 100644 index 000000000..f076dfcb0 --- /dev/null +++ b/tests/ui/integral-indexing.rs @@ -0,0 +1,16 @@ +pub fn main() { + let v: Vec = vec![0, 1, 2, 3, 4, 5]; + let s: String = "abcdef".to_string(); + v[3_usize]; + v[3]; + v[3u8]; //~ERROR : the type `[isize]` cannot be indexed by `u8` + v[3i8]; //~ERROR : the type `[isize]` cannot be indexed by `i8` + v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32` + v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32` + s.as_bytes()[3_usize]; + s.as_bytes()[3]; + s.as_bytes()[3u8]; //~ERROR : the type `[u8]` cannot be indexed by `u8` + s.as_bytes()[3i8]; //~ERROR : the type `[u8]` cannot be indexed by `i8` + s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32` + s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32` +} diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr new file mode 100644 index 000000000..bbbb2a86a --- /dev/null +++ b/tests/ui/integral-indexing.stderr @@ -0,0 +1,83 @@ +error[E0277]: the type `[isize]` cannot be indexed by `u8` + --> $DIR/integral-indexing.rs:6:7 + | +LL | v[3u8]; + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `Vec` to implement `Index` + +error[E0277]: the type `[isize]` cannot be indexed by `i8` + --> $DIR/integral-indexing.rs:7:7 + | +LL | v[3i8]; + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `Vec` to implement `Index` + +error[E0277]: the type `[isize]` cannot be indexed by `u32` + --> $DIR/integral-indexing.rs:8:7 + | +LL | v[3u32]; + | ^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `Vec` to implement `Index` + +error[E0277]: the type `[isize]` cannot be indexed by `i32` + --> $DIR/integral-indexing.rs:9:7 + | +LL | v[3i32]; + | ^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `Vec` to implement `Index` + +error[E0277]: the type `[u8]` cannot be indexed by `u8` + --> $DIR/integral-indexing.rs:12:18 + | +LL | s.as_bytes()[3u8]; + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[u8]` to implement `Index` + +error[E0277]: the type `[u8]` cannot be indexed by `i8` + --> $DIR/integral-indexing.rs:13:18 + | +LL | s.as_bytes()[3i8]; + | ^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[u8]` to implement `Index` + +error[E0277]: the type `[u8]` cannot be indexed by `u32` + --> $DIR/integral-indexing.rs:14:18 + | +LL | s.as_bytes()[3u32]; + | ^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[u8]` to implement `Index` + +error[E0277]: the type `[u8]` cannot be indexed by `i32` + --> $DIR/integral-indexing.rs:15:18 + | +LL | s.as_bytes()[3i32]; + | ^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[u8]` to implement `Index` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/integral-variable-unification-error.rs b/tests/ui/integral-variable-unification-error.rs new file mode 100644 index 000000000..8d1621321 --- /dev/null +++ b/tests/ui/integral-variable-unification-error.rs @@ -0,0 +1,8 @@ +fn main() { + let mut x //~ NOTE expected due to the type of this binding + = + 2; //~ NOTE expected due to this value + x = 5.0; + //~^ ERROR mismatched types + //~| NOTE expected integer, found floating-point number +} diff --git a/tests/ui/integral-variable-unification-error.stderr b/tests/ui/integral-variable-unification-error.stderr new file mode 100644 index 000000000..f77c265a2 --- /dev/null +++ b/tests/ui/integral-variable-unification-error.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/integral-variable-unification-error.rs:5:9 + | +LL | let mut x + | ----- expected due to the type of this binding +LL | = +LL | 2; + | - expected due to this value +LL | x = 5.0; + | ^^^ expected integer, found floating-point number + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/interior-mutability/interior-mutability.rs b/tests/ui/interior-mutability/interior-mutability.rs new file mode 100644 index 000000000..c704acc22 --- /dev/null +++ b/tests/ui/interior-mutability/interior-mutability.rs @@ -0,0 +1,7 @@ +use std::cell::Cell; +use std::panic::catch_unwind; +fn main() { + let mut x = Cell::new(22); + catch_unwind(|| { x.set(23); }); + //~^ ERROR the type `UnsafeCell` may contain interior mutability and a +} diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr new file mode 100644 index 000000000..034d22591 --- /dev/null +++ b/tests/ui/interior-mutability/interior-mutability.stderr @@ -0,0 +1,22 @@ +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/interior-mutability.rs:5:18 + | +LL | catch_unwind(|| { x.set(23); }); + | ------------ ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | | + | required by a bound introduced by this call + | + = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `Cell` + = note: required for `&Cell` to implement `UnwindSafe` +note: required because it's used within this closure + --> $DIR/interior-mutability.rs:5:18 + | +LL | catch_unwind(|| { x.set(23); }); + | ^^ +note: required by a bound in `catch_unwind` + --> $SRC_DIR/std/src/panic.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/internal/auxiliary/internal_unstable.rs b/tests/ui/internal/auxiliary/internal_unstable.rs new file mode 100644 index 000000000..eb4d6cb38 --- /dev/null +++ b/tests/ui/internal/auxiliary/internal_unstable.rs @@ -0,0 +1,101 @@ +#![feature(staged_api, allow_internal_unstable)] +#![stable(feature = "stable", since = "1.0.0")] + +#[unstable(feature = "function", issue = "none")] +pub fn unstable() {} + + +#[stable(feature = "stable", since = "1.0.0")] +pub struct Foo { + #[unstable(feature = "struct_field", issue = "none")] + pub x: u8 +} + +impl Foo { + #[unstable(feature = "method", issue = "none")] + pub fn method(&self) {} +} + +#[stable(feature = "stable", since = "1.0.0")] +pub struct Bar { + #[unstable(feature = "struct2_field", issue = "none")] + pub x: u8 +} + +#[stable(feature = "stable", since = "1.0.0")] +#[allow_internal_unstable(function)] +#[macro_export] +macro_rules! call_unstable_allow { + () => { $crate::unstable() } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[allow_internal_unstable(struct_field)] +#[macro_export] +macro_rules! construct_unstable_allow { + ($e: expr) => { + $crate::Foo { x: $e } + } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[allow_internal_unstable(method)] +#[macro_export] +macro_rules! call_method_allow { + ($e: expr) => { $e.method() } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[allow_internal_unstable(struct_field, struct2_field)] +#[macro_export] +macro_rules! access_field_allow { + ($e: expr) => { $e.x } +} + +// regression test for #77088 +#[stable(feature = "stable", since = "1.0.0")] +#[allow_internal_unstable(struct_field)] +#[allow_internal_unstable(struct2_field)] +#[macro_export] +macro_rules! access_field_allow2 { + ($e: expr) => { $e.x } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[allow_internal_unstable()] +#[macro_export] +macro_rules! pass_through_allow { + ($e: expr) => { $e } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[macro_export] +macro_rules! call_unstable_noallow { + () => { $crate::unstable() } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[macro_export] +macro_rules! construct_unstable_noallow { + ($e: expr) => { + $crate::Foo { x: $e } + } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[macro_export] +macro_rules! call_method_noallow { + ($e: expr) => { $e.method() } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[macro_export] +macro_rules! access_field_noallow { + ($e: expr) => { $e.x } +} + +#[stable(feature = "stable", since = "1.0.0")] +#[macro_export] +macro_rules! pass_through_noallow { + ($e: expr) => { $e } +} diff --git a/tests/ui/internal/internal-unstable-const.rs b/tests/ui/internal/internal-unstable-const.rs new file mode 100644 index 000000000..4ec2426df --- /dev/null +++ b/tests/ui/internal/internal-unstable-const.rs @@ -0,0 +1,13 @@ +// Don't allow unstable features in stable functions without `allow_internal_unstable`. + +#![stable(feature = "rust1", since = "1.0.0")] +#![feature(staged_api)] +#![feature(const_fn_floating_point_arithmetic)] + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +pub const fn foo() -> f32 { + 1.0 + 1.0 //~ ERROR const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` +} + +fn main() {} diff --git a/tests/ui/internal/internal-unstable-const.stderr b/tests/ui/internal/internal-unstable-const.stderr new file mode 100644 index 000000000..37d2ea6d2 --- /dev/null +++ b/tests/ui/internal/internal-unstable-const.stderr @@ -0,0 +1,17 @@ +error: const-stable function cannot use `#[feature(const_fn_floating_point_arithmetic)]` + --> $DIR/internal-unstable-const.rs:10:5 + | +LL | 1.0 + 1.0 + | ^^^^^^^^^ + | +help: if it is not part of the public API, make this function unstably const + | +LL | #[rustc_const_unstable(feature = "...", issue = "...")] + | +help: otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks + | +LL | #[rustc_allow_const_fn_unstable(const_fn_floating_point_arithmetic)] + | + +error: aborting due to previous error + diff --git a/tests/ui/internal/internal-unstable-noallow.rs b/tests/ui/internal/internal-unstable-noallow.rs new file mode 100644 index 000000000..616f6668d --- /dev/null +++ b/tests/ui/internal/internal-unstable-noallow.rs @@ -0,0 +1,23 @@ +// this has to be separate to internal-unstable.rs because these tests +// have error messages pointing deep into the internals of the +// cross-crate macros, and hence need to use error-pattern instead of +// the // ~ form. + +// aux-build:internal_unstable.rs +// error-pattern:use of unstable library feature 'function' +// error-pattern:use of unstable library feature 'struct_field' +// error-pattern:use of unstable library feature 'method' +// error-pattern:use of unstable library feature 'struct2_field' + +#[macro_use] +extern crate internal_unstable; + +fn main() { + call_unstable_noallow!(); + + construct_unstable_noallow!(0); + + |x: internal_unstable::Foo| { call_method_noallow!(x) }; + + |x: internal_unstable::Bar| { access_field_noallow!(x) }; +} diff --git a/tests/ui/internal/internal-unstable-noallow.stderr b/tests/ui/internal/internal-unstable-noallow.stderr new file mode 100644 index 000000000..b0ceae62a --- /dev/null +++ b/tests/ui/internal/internal-unstable-noallow.stderr @@ -0,0 +1,39 @@ +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable-noallow.rs:16:5 + | +LL | call_unstable_noallow!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(function)]` to the crate attributes to enable + = note: this error originates in the macro `call_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: use of unstable library feature 'struct_field' + --> $DIR/internal-unstable-noallow.rs:18:5 + | +LL | construct_unstable_noallow!(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(struct_field)]` to the crate attributes to enable + = note: this error originates in the macro `construct_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: use of unstable library feature 'method' + --> $DIR/internal-unstable-noallow.rs:20:35 + | +LL | |x: internal_unstable::Foo| { call_method_noallow!(x) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(method)]` to the crate attributes to enable + = note: this error originates in the macro `call_method_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: use of unstable library feature 'struct2_field' + --> $DIR/internal-unstable-noallow.rs:22:35 + | +LL | |x: internal_unstable::Bar| { access_field_noallow!(x) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(struct2_field)]` to the crate attributes to enable + = note: this error originates in the macro `access_field_noallow` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/internal/internal-unstable-thread-local.rs b/tests/ui/internal/internal-unstable-thread-local.rs new file mode 100644 index 000000000..b9194c6b3 --- /dev/null +++ b/tests/ui/internal/internal-unstable-thread-local.rs @@ -0,0 +1,11 @@ +// aux-build:internal_unstable.rs + +#![allow(dead_code)] + +extern crate internal_unstable; + + +thread_local!(static FOO: () = ()); +thread_local!(static BAR: () = internal_unstable::unstable()); //~ ERROR use of unstable + +fn main() {} diff --git a/tests/ui/internal/internal-unstable-thread-local.stderr b/tests/ui/internal/internal-unstable-thread-local.stderr new file mode 100644 index 000000000..558e3dbb7 --- /dev/null +++ b/tests/ui/internal/internal-unstable-thread-local.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable-thread-local.rs:9:32 + | +LL | thread_local!(static BAR: () = internal_unstable::unstable()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(function)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/internal/internal-unstable.rs b/tests/ui/internal/internal-unstable.rs new file mode 100644 index 000000000..b8987d3e1 --- /dev/null +++ b/tests/ui/internal/internal-unstable.rs @@ -0,0 +1,56 @@ +// aux-build:internal_unstable.rs + +#![feature(allow_internal_unstable)] +#[allow(dead_code)] + +#[macro_use] +extern crate internal_unstable; + +struct Baz { + #[allow_internal_unstable] + //^ WARN `#[allow_internal_unstable]` is ignored on struct fields and match arms + baz: u8, +} + +macro_rules! foo { + ($e: expr, $f: expr) => {{ + $e; + $f; + internal_unstable::unstable(); //~ ERROR use of unstable + }} +} + +#[allow_internal_unstable(function)] +macro_rules! bar { + ($e: expr) => {{ + foo!($e, + internal_unstable::unstable()); + internal_unstable::unstable(); + }} +} + +fn main() { + // ok, the instability is contained. + call_unstable_allow!(); + construct_unstable_allow!(0); + |x: internal_unstable::Foo| { call_method_allow!(x) }; + |x: internal_unstable::Bar| { access_field_allow!(x) }; + |x: internal_unstable::Bar| { access_field_allow2!(x) }; // regression test for #77088 + + // bad. + pass_through_allow!(internal_unstable::unstable()); //~ ERROR use of unstable + + pass_through_noallow!(internal_unstable::unstable()); //~ ERROR use of unstable + + + + println!("{:?}", internal_unstable::unstable()); //~ ERROR use of unstable + + bar!(internal_unstable::unstable()); //~ ERROR use of unstable + + match true { + #[allow_internal_unstable] + //^ WARN `#[allow_internal_unstable]` is ignored on struct fields and match arms + _ => {} + } +} diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr new file mode 100644 index 000000000..f0f9bfb8d --- /dev/null +++ b/tests/ui/internal/internal-unstable.stderr @@ -0,0 +1,47 @@ +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable.rs:41:25 + | +LL | pass_through_allow!(internal_unstable::unstable()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(function)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable.rs:43:27 + | +LL | pass_through_noallow!(internal_unstable::unstable()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(function)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable.rs:47:22 + | +LL | println!("{:?}", internal_unstable::unstable()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(function)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable.rs:49:10 + | +LL | bar!(internal_unstable::unstable()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(function)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'function' + --> $DIR/internal-unstable.rs:19:9 + | +LL | internal_unstable::unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | bar!(internal_unstable::unstable()); + | ----------------------------------- in this macro invocation + | + = help: add `#![feature(function)]` to the crate attributes to enable + = note: this error originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/intrinsics-always-extern.rs b/tests/ui/intrinsics-always-extern.rs new file mode 100644 index 000000000..22951147d --- /dev/null +++ b/tests/ui/intrinsics-always-extern.rs @@ -0,0 +1,16 @@ +#![feature(intrinsics)] + +trait Foo { + extern "rust-intrinsic" fn foo(&self); //~ ERROR intrinsic must +} + +impl Foo for () { + extern "rust-intrinsic" fn foo(&self) { //~ ERROR intrinsic must + } +} + +extern "rust-intrinsic" fn hello() {//~ ERROR intrinsic must +} + +fn main() { +} diff --git a/tests/ui/intrinsics-always-extern.stderr b/tests/ui/intrinsics-always-extern.stderr new file mode 100644 index 000000000..24b6da160 --- /dev/null +++ b/tests/ui/intrinsics-always-extern.stderr @@ -0,0 +1,24 @@ +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/intrinsics-always-extern.rs:4:32 + | +LL | extern "rust-intrinsic" fn foo(&self); + | ^^^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/intrinsics-always-extern.rs:8:43 + | +LL | extern "rust-intrinsic" fn foo(&self) { + | ___________________________________________^ +LL | | } + | |_____^ + +error: intrinsic must be in `extern "rust-intrinsic" { ... }` block + --> $DIR/intrinsics-always-extern.rs:12:36 + | +LL | extern "rust-intrinsic" fn hello() { + | ____________________________________^ +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs b/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs new file mode 100644 index 000000000..f3b9d569c --- /dev/null +++ b/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs @@ -0,0 +1,14 @@ +#![feature(intrinsics)] + +pub mod rusti { + extern "rust-intrinsic" { + pub fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; + } +} + +#[inline(always)] +pub fn atomic_xchg_seqcst(dst: *mut isize, src: isize) -> isize { + unsafe { + rusti::atomic_xchg_seqcst(dst, src) + } +} diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs b/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs new file mode 100644 index 000000000..f36a5f1ac --- /dev/null +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs @@ -0,0 +1,32 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics, core_intrinsics)] +#![allow(warnings)] +#![crate_type = "rlib"] + +// Bad monomorphizations could previously cause LLVM asserts even though the +// error was caught in the compiler. + +extern "platform-intrinsic" { + fn simd_add(x: T, y: T) -> T; +} + +use std::intrinsics; + +#[derive(Copy, Clone)] +pub struct Foo(i64); + +pub fn test_cttz(v: Foo) -> Foo { + intrinsics::cttz(v) + //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo` +} + +pub unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo { + intrinsics::fadd_fast(a, b) + //~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo` +} + +pub unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo { + simd_add(a, b) + //~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` +} diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr b/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr new file mode 100644 index 000000000..c070f0181 --- /dev/null +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr @@ -0,0 +1,21 @@ +error[E0511]: invalid monomorphization of `cttz` intrinsic: expected basic integer type, found `Foo` + --> $DIR/bad-intrinsic-monomorphization.rs:20:5 + | +LL | intrinsics::cttz(v) + | ^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `fadd_fast` intrinsic: expected basic float type, found `Foo` + --> $DIR/bad-intrinsic-monomorphization.rs:25:5 + | +LL | intrinsics::fadd_fast(a, b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` + --> $DIR/bad-intrinsic-monomorphization.rs:30:5 + | +LL | simd_add(a, b) + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/intrinsics/const-eval-select-backtrace-std.rs b/tests/ui/intrinsics/const-eval-select-backtrace-std.rs new file mode 100644 index 000000000..1164a3a5b --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-backtrace-std.rs @@ -0,0 +1,7 @@ +// See issue #100696. +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=0 +fn main() { + &""[1..]; +} diff --git a/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr b/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr new file mode 100644 index 000000000..463cd52c5 --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'byte index 1 is out of bounds of ``', $DIR/const-eval-select-backtrace-std.rs:6:6 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/intrinsics/const-eval-select-backtrace.rs b/tests/ui/intrinsics/const-eval-select-backtrace.rs new file mode 100644 index 000000000..ef1c7c419 --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-backtrace.rs @@ -0,0 +1,19 @@ +#![feature(core_intrinsics)] +// See issue #100696. +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=0 + +#[track_caller] +fn uhoh() { + panic!("Aaah!") +} + +const fn c() {} + +fn main() { + // safety: this is unsound and just used to test + unsafe { + std::intrinsics::const_eval_select((), c, uhoh); + } +} diff --git a/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr b/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr new file mode 100644 index 000000000..54e28db5e --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'Aaah!', $DIR/const-eval-select-backtrace.rs:17:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/intrinsics/const-eval-select-bad.rs b/tests/ui/intrinsics/const-eval-select-bad.rs new file mode 100644 index 000000000..fa14efad7 --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-bad.rs @@ -0,0 +1,46 @@ +#![feature(const_eval_select)] +#![feature(core_intrinsics)] + +use std::intrinsics::const_eval_select; + +const fn not_fn_items() { + const_eval_select((), || {}, || {}); + //~^ ERROR this argument must be a function item + //~| ERROR this argument must be a function item + const_eval_select((), 42, 0xDEADBEEF); + //~^ ERROR expected a `FnOnce<()>` closure + //~| ERROR expected a `FnOnce<()>` closure + //~| ERROR this argument must be a function item + //~| ERROR this argument must be a function item +} + +const fn foo(n: i32) -> i32 { + n +} + +fn bar(n: i32) -> bool { + assert_eq!(n, 0, "{} must be equal to {}", n, 0); + n == 0 +} + +fn baz(n: bool) -> i32 { + assert!(n, "{} must be true", n); + n as i32 +} + +const fn return_ty_mismatch() { + const_eval_select((1,), foo, bar); + //~^ ERROR expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool` +} + +const fn args_ty_mismatch() { + const_eval_select((true,), foo, baz); + //~^ ERROR type mismatch +} + +const fn non_const_fn() { + const_eval_select((1,), bar, bar); + //~^ ERROR this argument must be a `const fn` +} + +fn main() {} diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr new file mode 100644 index 000000000..fd7d061b6 --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -0,0 +1,101 @@ +error: this argument must be a function item + --> $DIR/const-eval-select-bad.rs:7:27 + | +LL | const_eval_select((), || {}, || {}); + | ^^^^^ + | + = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:27: 7:29] + = help: consult the documentation on `const_eval_select` for more information + +error: this argument must be a function item + --> $DIR/const-eval-select-bad.rs:7:34 + | +LL | const_eval_select((), || {}, || {}); + | ^^^^^ + | + = note: expected a function item, found [closure@$DIR/const-eval-select-bad.rs:7:34: 7:36] + = help: consult the documentation on `const_eval_select` for more information + +error: this argument must be a function item + --> $DIR/const-eval-select-bad.rs:10:27 + | +LL | const_eval_select((), 42, 0xDEADBEEF); + | ^^ + | + = note: expected a function item, found {integer} + = help: consult the documentation on `const_eval_select` for more information + +error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` + --> $DIR/const-eval-select-bad.rs:10:27 + | +LL | const_eval_select((), 42, 0xDEADBEEF); + | ----------------- ^^ expected an `FnOnce<()>` closure, found `{integer}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + +error: this argument must be a function item + --> $DIR/const-eval-select-bad.rs:10:31 + | +LL | const_eval_select((), 42, 0xDEADBEEF); + | ^^^^^^^^^^ + | + = note: expected a function item, found {integer} + = help: consult the documentation on `const_eval_select` for more information + +error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` + --> $DIR/const-eval-select-bad.rs:10:31 + | +LL | const_eval_select((), 42, 0xDEADBEEF); + | ----------------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + +error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool` + --> $DIR/const-eval-select-bad.rs:32:34 + | +LL | const_eval_select((1,), foo, bar); + | ----------------- ^^^ expected `i32`, found `bool` + | | + | required by a bound introduced by this call + | +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + +error[E0631]: type mismatch in function arguments + --> $DIR/const-eval-select-bad.rs:37:32 + | +LL | const fn foo(n: i32) -> i32 { + | --------------------------- found signature defined here +... +LL | const_eval_select((true,), foo, baz); + | ----------------- ^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(bool) -> _` + found function signature `fn(i32) -> _` +note: required by a bound in `const_eval_select` + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + +error: this argument must be a `const fn` + --> $DIR/const-eval-select-bad.rs:42:29 + | +LL | const_eval_select((1,), bar, bar); + | ^^^ + | + = help: consult the documentation on `const_eval_select` for more information + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0271, E0277, E0631. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/intrinsics/const-eval-select-stability.rs b/tests/ui/intrinsics/const-eval-select-stability.rs new file mode 100644 index 000000000..f9554dece --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-stability.rs @@ -0,0 +1,21 @@ +#![feature(staged_api)] +#![feature(const_eval_select)] +#![feature(core_intrinsics)] +#![stable(since = "1.0", feature = "ui_test")] + +use std::intrinsics::const_eval_select; + +fn log() { + println!("HEY HEY HEY") +} + +const fn nothing(){} + +#[stable(since = "1.0", feature = "hey")] +#[rustc_const_stable(since = "1.0", feature = "const_hey")] +pub const unsafe fn hey() { + const_eval_select((), nothing, log); + //~^ ERROR `const_eval_select` is not yet stable as a const fn +} + +fn main() {} diff --git a/tests/ui/intrinsics/const-eval-select-stability.stderr b/tests/ui/intrinsics/const-eval-select-stability.stderr new file mode 100644 index 000000000..65b507b88 --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-stability.stderr @@ -0,0 +1,10 @@ +error: `const_eval_select` is not yet stable as a const fn + --> $DIR/const-eval-select-stability.rs:17:5 + | +LL | const_eval_select((), nothing, log); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to previous error + diff --git a/tests/ui/intrinsics/const-eval-select-x86_64.rs b/tests/ui/intrinsics/const-eval-select-x86_64.rs new file mode 100644 index 000000000..f3924acf0 --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select-x86_64.rs @@ -0,0 +1,40 @@ +// run-pass +// only-x86_64 + +#![feature(const_eval_select)] +#![feature(core_intrinsics)] +use std::intrinsics::const_eval_select; +use std::arch::x86_64::*; +use std::mem::transmute; + +const fn eq_ct(x: [i32; 4], y: [i32; 4]) -> bool { + x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3] +} + +fn eq_rt(x: [i32; 4], y: [i32; 4]) -> bool { + unsafe { + let x = _mm_loadu_si128(&x as *const _ as *const _); + let y = _mm_loadu_si128(&y as *const _ as *const _); + let r = _mm_cmpeq_epi32(x, y); + let r = _mm_movemask_ps(transmute(r) ); + r == 0b1111 + } +} + +const fn eq(x: [i32; 4], y: [i32; 4]) -> bool { + unsafe { + const_eval_select((x, y), eq_ct, eq_rt) + } +} + +fn main() { + const X: bool = eq([0, 1, 2, 3], [0, 1, 2, 3]); + assert_eq!(X, true); + let x = eq([0, 1, 2, 3], [0, 1, 2, 3]); + assert_eq!(x, true); + + const Y: bool = eq([0, 1, 2, 3], [0, 1, 3, 2]); + assert_eq!(Y, false); + let y = eq([0, 1, 2, 3], [0, 1, 3, 2]); + assert_eq!(y, false); +} diff --git a/tests/ui/intrinsics/const-eval-select.rs b/tests/ui/intrinsics/const-eval-select.rs new file mode 100644 index 000000000..9ff20d3fb --- /dev/null +++ b/tests/ui/intrinsics/const-eval-select.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(const_eval_select)] +#![feature(core_intrinsics)] + +use std::intrinsics::const_eval_select; + +const fn yes() -> bool { + true +} + +fn no() -> bool { + false +} + +// not a sound use case; testing only +const fn is_const_eval() -> bool { + unsafe { const_eval_select((), yes, no) } +} + +fn main() { + const YES: bool = is_const_eval(); + let no = is_const_eval(); + + assert_eq!(true, YES); + assert_eq!(false, no); +} diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs new file mode 100644 index 000000000..c8b1ff1db --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -0,0 +1,67 @@ +// run-pass +// ignore-wasm32-bare seems not important to test here + +#![feature(intrinsics)] + +mod rusti { + extern "rust-intrinsic" { + pub fn pref_align_of() -> usize; + #[rustc_safe_intrinsic] + pub fn min_align_of() -> usize; + } +} + +#[cfg(any(target_os = "android", + target_os = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "illumos", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "vxworks"))] +mod m { + #[cfg(target_arch = "x86")] + pub fn main() { + unsafe { + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 4); + } + } + + #[cfg(not(target_arch = "x86"))] + pub fn main() { + unsafe { + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); + } + } +} + +#[cfg(target_env = "sgx")] +mod m { + #[cfg(target_arch = "x86_64")] + pub fn main() { + unsafe { + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); + } + } +} + +#[cfg(target_os = "windows")] +mod m { + pub fn main() { + unsafe { + assert_eq!(::rusti::pref_align_of::(), 8); + assert_eq!(::rusti::min_align_of::(), 8); + } + } +} + +fn main() { + m::main(); +} diff --git a/tests/ui/intrinsics/intrinsic-assume.rs b/tests/ui/intrinsics/intrinsic-assume.rs new file mode 100644 index 000000000..3c9d70cb5 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-assume.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::assume; + +unsafe fn f(x: i32) -> i32 { + assume(x == 34); + match x { + 34 => 42, + _ => 30 + } +} + +fn main() { + let x = unsafe { f(34) }; + assert_eq!(x, 42); +} diff --git a/tests/ui/intrinsics/intrinsic-atomics-cc.rs b/tests/ui/intrinsics/intrinsic-atomics-cc.rs new file mode 100644 index 000000000..ce3fa7b0c --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-atomics-cc.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:cci_intrinsic.rs + + +extern crate cci_intrinsic; +use cci_intrinsic::atomic_xchg_seqcst; + +pub fn main() { + let mut x = 1; + atomic_xchg_seqcst(&mut x, 5); + assert_eq!(x, 5); +} diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs new file mode 100644 index 000000000..b17f4347b --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-atomics.rs @@ -0,0 +1,102 @@ +// run-pass +#![feature(intrinsics)] + +mod rusti { + extern "rust-intrinsic" { + pub fn atomic_cxchg_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + + pub fn atomic_cxchgweak_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + + pub fn atomic_load_seqcst(src: *const T) -> T; + pub fn atomic_load_acquire(src: *const T) -> T; + + pub fn atomic_store_seqcst(dst: *mut T, val: T); + pub fn atomic_store_release(dst: *mut T, val: T); + + pub fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; + pub fn atomic_xchg_acquire(dst: *mut T, src: T) -> T; + pub fn atomic_xchg_release(dst: *mut T, src: T) -> T; + + pub fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; + pub fn atomic_xadd_acquire(dst: *mut T, src: T) -> T; + pub fn atomic_xadd_release(dst: *mut T, src: T) -> T; + + pub fn atomic_xsub_seqcst(dst: *mut T, src: T) -> T; + pub fn atomic_xsub_acquire(dst: *mut T, src: T) -> T; + pub fn atomic_xsub_release(dst: *mut T, src: T) -> T; + } +} + +pub fn main() { + unsafe { + let mut x: Box<_> = Box::new(1); + + assert_eq!(rusti::atomic_load_seqcst(&*x), 1); + *x = 5; + assert_eq!(rusti::atomic_load_acquire(&*x), 5); + + rusti::atomic_store_seqcst(&mut *x,3); + assert_eq!(*x, 3); + rusti::atomic_store_release(&mut *x,1); + assert_eq!(*x, 1); + + assert_eq!(rusti::atomic_cxchg_seqcst_seqcst(&mut *x, 1, 2), (1, true)); + assert_eq!(*x, 2); + + assert_eq!(rusti::atomic_cxchg_acquire_acquire(&mut *x, 1, 3), (2, false)); + assert_eq!(*x, 2); + + assert_eq!(rusti::atomic_cxchg_release_relaxed(&mut *x, 2, 1), (2, true)); + assert_eq!(*x, 1); + + assert_eq!(rusti::atomic_xchg_seqcst(&mut *x, 0), 1); + assert_eq!(*x, 0); + + assert_eq!(rusti::atomic_xchg_acquire(&mut *x, 1), 0); + assert_eq!(*x, 1); + + assert_eq!(rusti::atomic_xchg_release(&mut *x, 0), 1); + assert_eq!(*x, 0); + + assert_eq!(rusti::atomic_xadd_seqcst(&mut *x, 1), 0); + assert_eq!(rusti::atomic_xadd_acquire(&mut *x, 1), 1); + assert_eq!(rusti::atomic_xadd_release(&mut *x, 1), 2); + assert_eq!(*x, 3); + + assert_eq!(rusti::atomic_xsub_seqcst(&mut *x, 1), 3); + assert_eq!(rusti::atomic_xsub_acquire(&mut *x, 1), 2); + assert_eq!(rusti::atomic_xsub_release(&mut *x, 1), 1); + assert_eq!(*x, 0); + + loop { + let res = rusti::atomic_cxchgweak_seqcst_seqcst(&mut *x, 0, 1); + assert_eq!(res.0, 0); + if res.1 { + break; + } + } + assert_eq!(*x, 1); + + loop { + let res = rusti::atomic_cxchgweak_acquire_acquire(&mut *x, 1, 2); + assert_eq!(res.0, 1); + if res.1 { + break; + } + } + assert_eq!(*x, 2); + + loop { + let res = rusti::atomic_cxchgweak_release_relaxed(&mut *x, 2, 3); + assert_eq!(res.0, 2); + if res.1 { + break; + } + } + assert_eq!(*x, 3); + } +} diff --git a/tests/ui/intrinsics/intrinsic-nearby.rs b/tests/ui/intrinsics/intrinsic-nearby.rs new file mode 100644 index 000000000..7b1d1eeaa --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-nearby.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::*; + +fn main() { + unsafe { + assert_eq!(nearbyintf32(5.234f32), 5f32); + assert_eq!(nearbyintf64(6.777f64), 7f64); + } +} diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-padding.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-padding.rs new file mode 100644 index 000000000..a93d777d2 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-padding.rs @@ -0,0 +1,10 @@ +#![feature(core_intrinsics)] +#![feature(const_intrinsic_raw_eq)] + +const BAD_RAW_EQ_CALL: bool = unsafe { + std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) +//~^ ERROR evaluation of constant value failed +}; + +pub fn main() { +} diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr new file mode 100644 index 000000000..56d5a4857 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/intrinsic-raw_eq-const-padding.rs:5:5 + | +LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const.rs new file mode 100644 index 000000000..32841f531 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const.rs @@ -0,0 +1,26 @@ +// run-pass + +#![feature(core_intrinsics)] +#![feature(const_intrinsic_raw_eq)] + +pub fn main() { + use std::intrinsics::raw_eq; + + const RAW_EQ_I32_TRUE: bool = unsafe { raw_eq(&42_i32, &42) }; + assert!(RAW_EQ_I32_TRUE); + + const RAW_EQ_I32_FALSE: bool = unsafe { raw_eq(&4_i32, &2) }; + assert!(!RAW_EQ_I32_FALSE); + + const RAW_EQ_CHAR_TRUE: bool = unsafe { raw_eq(&'a', &'a') }; + assert!(RAW_EQ_CHAR_TRUE); + + const RAW_EQ_CHAR_FALSE: bool = unsafe { raw_eq(&'a', &'A') }; + assert!(!RAW_EQ_CHAR_FALSE); + + const RAW_EQ_ARRAY_TRUE: bool = unsafe { raw_eq(&[13_u8, 42], &[13, 42]) }; + assert!(RAW_EQ_ARRAY_TRUE); + + const RAW_EQ_ARRAY_FALSE: bool = unsafe { raw_eq(&[13_u8, 42], &[42, 13]) }; + assert!(!RAW_EQ_ARRAY_FALSE); +} diff --git a/tests/ui/intrinsics/intrinsic-unreachable.rs b/tests/ui/intrinsics/intrinsic-unreachable.rs new file mode 100644 index 000000000..73dd71d48 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-unreachable.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(core_intrinsics)] + +use std::intrinsics; + +// See also tests/run-make/intrinsic-unreachable. + +unsafe fn f(x: usize) -> usize { + match x { + 17 => 23, + _ => intrinsics::unreachable(), + } +} + +fn main() { + assert_eq!(unsafe { f(17) }, 23); +} diff --git a/tests/ui/intrinsics/intrinsic-volatile.rs b/tests/ui/intrinsics/intrinsic-volatile.rs new file mode 100644 index 000000000..7b2c825a2 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-volatile.rs @@ -0,0 +1,44 @@ +// run-pass + +#![feature(core_intrinsics)] + +use std::intrinsics::*; + +pub fn main() { + unsafe { + let mut x: Box = Box::new(0); + let mut y: Box = Box::new(0); + + // test volatile load + assert_eq!(volatile_load(&*x), 0); + *x = 1; + assert_eq!(volatile_load(&*x), 1); + + // test volatile store + volatile_store(&mut *x, 2); + assert_eq!(*x, 2); + + // test volatile copy memory + volatile_copy_memory(&mut *y, &*x, 1); + assert_eq!(*y, 2); + + // test volatile copy non-overlapping memory + *x = 3; + volatile_copy_nonoverlapping_memory(&mut *y, &*x, 1); + assert_eq!(*y, 3); + + // test volatile set memory + volatile_set_memory(&mut *x, 4, 1); + assert_eq!(*x, 4); + + // test unaligned volatile load + let arr: [u8; 3] = [1, 2, 3]; + let ptr = arr[1..].as_ptr() as *const u16; + assert_eq!(unaligned_volatile_load(ptr), u16::from_ne_bytes([arr[1], arr[2]])); + + // test unaligned volatile store + let ptr = arr[1..].as_ptr() as *mut u16; + unaligned_volatile_store(ptr, 0); + assert_eq!(arr, [1, 0, 0]); + } +} diff --git a/tests/ui/intrinsics/intrinsics-integer.rs b/tests/ui/intrinsics/intrinsics-integer.rs new file mode 100644 index 000000000..88bf42b68 --- /dev/null +++ b/tests/ui/intrinsics/intrinsics-integer.rs @@ -0,0 +1,177 @@ +// run-pass + +#![feature(intrinsics)] +#![feature(rustc_attrs)] + +mod rusti { + extern "rust-intrinsic" { + #[rustc_safe_intrinsic] + pub fn ctpop(x: T) -> T; + #[rustc_safe_intrinsic] + pub fn ctlz(x: T) -> T; + pub fn ctlz_nonzero(x: T) -> T; + #[rustc_safe_intrinsic] + pub fn cttz(x: T) -> T; + pub fn cttz_nonzero(x: T) -> T; + #[rustc_safe_intrinsic] + pub fn bswap(x: T) -> T; + #[rustc_safe_intrinsic] + pub fn bitreverse(x: T) -> T; + } +} + +pub fn main() { + use rusti::*; + + assert_eq!(ctpop(0u8), 0); assert_eq!(ctpop(0i8), 0); + assert_eq!(ctpop(0u16), 0); assert_eq!(ctpop(0i16), 0); + assert_eq!(ctpop(0u32), 0); assert_eq!(ctpop(0i32), 0); + assert_eq!(ctpop(0u64), 0); assert_eq!(ctpop(0i64), 0); + assert_eq!(ctpop(0u128), 0); assert_eq!(ctpop(0i128), 0); + + assert_eq!(ctpop(1u8), 1); assert_eq!(ctpop(1i8), 1); + assert_eq!(ctpop(1u16), 1); assert_eq!(ctpop(1i16), 1); + assert_eq!(ctpop(1u32), 1); assert_eq!(ctpop(1i32), 1); + assert_eq!(ctpop(1u64), 1); assert_eq!(ctpop(1i64), 1); + assert_eq!(ctpop(1u128), 1); assert_eq!(ctpop(1i128), 1); + + assert_eq!(ctpop(10u8), 2); assert_eq!(ctpop(10i8), 2); + assert_eq!(ctpop(10u16), 2); assert_eq!(ctpop(10i16), 2); + assert_eq!(ctpop(10u32), 2); assert_eq!(ctpop(10i32), 2); + assert_eq!(ctpop(10u64), 2); assert_eq!(ctpop(10i64), 2); + assert_eq!(ctpop(10u128), 2); assert_eq!(ctpop(10i128), 2); + + assert_eq!(ctpop(100u8), 3); assert_eq!(ctpop(100i8), 3); + assert_eq!(ctpop(100u16), 3); assert_eq!(ctpop(100i16), 3); + assert_eq!(ctpop(100u32), 3); assert_eq!(ctpop(100i32), 3); + assert_eq!(ctpop(100u64), 3); assert_eq!(ctpop(100i64), 3); + assert_eq!(ctpop(100u128), 3); assert_eq!(ctpop(100i128), 3); + + assert_eq!(ctpop(-1i8 as u8), 8); assert_eq!(ctpop(-1i8), 8); + assert_eq!(ctpop(-1i16 as u16), 16); assert_eq!(ctpop(-1i16), 16); + assert_eq!(ctpop(-1i32 as u32), 32); assert_eq!(ctpop(-1i32), 32); + assert_eq!(ctpop(-1i64 as u64), 64); assert_eq!(ctpop(-1i64), 64); + assert_eq!(ctpop(-1i128 as u128), 128); assert_eq!(ctpop(-1i128), 128); + + assert_eq!(ctlz(0u8), 8); assert_eq!(ctlz(0i8), 8); + assert_eq!(ctlz(0u16), 16); assert_eq!(ctlz(0i16), 16); + assert_eq!(ctlz(0u32), 32); assert_eq!(ctlz(0i32), 32); + assert_eq!(ctlz(0u64), 64); assert_eq!(ctlz(0i64), 64); + assert_eq!(ctlz(0u128), 128); assert_eq!(ctlz(0i128), 128); + + assert_eq!(ctlz(1u8), 7); assert_eq!(ctlz(1i8), 7); + assert_eq!(ctlz(1u16), 15); assert_eq!(ctlz(1i16), 15); + assert_eq!(ctlz(1u32), 31); assert_eq!(ctlz(1i32), 31); + assert_eq!(ctlz(1u64), 63); assert_eq!(ctlz(1i64), 63); + assert_eq!(ctlz(1u128), 127); assert_eq!(ctlz(1i128), 127); + + assert_eq!(ctlz(10u8), 4); assert_eq!(ctlz(10i8), 4); + assert_eq!(ctlz(10u16), 12); assert_eq!(ctlz(10i16), 12); + assert_eq!(ctlz(10u32), 28); assert_eq!(ctlz(10i32), 28); + assert_eq!(ctlz(10u64), 60); assert_eq!(ctlz(10i64), 60); + assert_eq!(ctlz(10u128), 124); assert_eq!(ctlz(10i128), 124); + + assert_eq!(ctlz(100u8), 1); assert_eq!(ctlz(100i8), 1); + assert_eq!(ctlz(100u16), 9); assert_eq!(ctlz(100i16), 9); + assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25); + assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57); + assert_eq!(ctlz(100u128), 121); assert_eq!(ctlz(100i128), 121); + + unsafe { + assert_eq!(ctlz_nonzero(1u8), 7); assert_eq!(ctlz_nonzero(1i8), 7); + assert_eq!(ctlz_nonzero(1u16), 15); assert_eq!(ctlz_nonzero(1i16), 15); + assert_eq!(ctlz_nonzero(1u32), 31); assert_eq!(ctlz_nonzero(1i32), 31); + assert_eq!(ctlz_nonzero(1u64), 63); assert_eq!(ctlz_nonzero(1i64), 63); + assert_eq!(ctlz_nonzero(1u128), 127); assert_eq!(ctlz_nonzero(1i128), 127); + + assert_eq!(ctlz_nonzero(10u8), 4); assert_eq!(ctlz_nonzero(10i8), 4); + assert_eq!(ctlz_nonzero(10u16), 12); assert_eq!(ctlz_nonzero(10i16), 12); + assert_eq!(ctlz_nonzero(10u32), 28); assert_eq!(ctlz_nonzero(10i32), 28); + assert_eq!(ctlz_nonzero(10u64), 60); assert_eq!(ctlz_nonzero(10i64), 60); + assert_eq!(ctlz_nonzero(10u128), 124); assert_eq!(ctlz_nonzero(10i128), 124); + + assert_eq!(ctlz_nonzero(100u8), 1); assert_eq!(ctlz_nonzero(100i8), 1); + assert_eq!(ctlz_nonzero(100u16), 9); assert_eq!(ctlz_nonzero(100i16), 9); + assert_eq!(ctlz_nonzero(100u32), 25); assert_eq!(ctlz_nonzero(100i32), 25); + assert_eq!(ctlz_nonzero(100u64), 57); assert_eq!(ctlz_nonzero(100i64), 57); + assert_eq!(ctlz_nonzero(100u128), 121); assert_eq!(ctlz_nonzero(100i128), 121); + } + + assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0); + assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0); + assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0); + assert_eq!(cttz(-1i64 as u64), 0); assert_eq!(cttz(-1i64), 0); + assert_eq!(cttz(-1i128 as u128), 0); assert_eq!(cttz(-1i128), 0); + + assert_eq!(cttz(0u8), 8); assert_eq!(cttz(0i8), 8); + assert_eq!(cttz(0u16), 16); assert_eq!(cttz(0i16), 16); + assert_eq!(cttz(0u32), 32); assert_eq!(cttz(0i32), 32); + assert_eq!(cttz(0u64), 64); assert_eq!(cttz(0i64), 64); + assert_eq!(cttz(0u128), 128); assert_eq!(cttz(0i128), 128); + + assert_eq!(cttz(1u8), 0); assert_eq!(cttz(1i8), 0); + assert_eq!(cttz(1u16), 0); assert_eq!(cttz(1i16), 0); + assert_eq!(cttz(1u32), 0); assert_eq!(cttz(1i32), 0); + assert_eq!(cttz(1u64), 0); assert_eq!(cttz(1i64), 0); + assert_eq!(cttz(1u128), 0); assert_eq!(cttz(1i128), 0); + + assert_eq!(cttz(10u8), 1); assert_eq!(cttz(10i8), 1); + assert_eq!(cttz(10u16), 1); assert_eq!(cttz(10i16), 1); + assert_eq!(cttz(10u32), 1); assert_eq!(cttz(10i32), 1); + assert_eq!(cttz(10u64), 1); assert_eq!(cttz(10i64), 1); + assert_eq!(cttz(10u128), 1); assert_eq!(cttz(10i128), 1); + + assert_eq!(cttz(100u8), 2); assert_eq!(cttz(100i8), 2); + assert_eq!(cttz(100u16), 2); assert_eq!(cttz(100i16), 2); + assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2); + assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2); + assert_eq!(cttz(100u128), 2); assert_eq!(cttz(100i128), 2); + + unsafe { + assert_eq!(cttz_nonzero(-1i8 as u8), 0); assert_eq!(cttz_nonzero(-1i8), 0); + assert_eq!(cttz_nonzero(-1i16 as u16), 0); assert_eq!(cttz_nonzero(-1i16), 0); + assert_eq!(cttz_nonzero(-1i32 as u32), 0); assert_eq!(cttz_nonzero(-1i32), 0); + assert_eq!(cttz_nonzero(-1i64 as u64), 0); assert_eq!(cttz_nonzero(-1i64), 0); + assert_eq!(cttz_nonzero(-1i128 as u128), 0); assert_eq!(cttz_nonzero(-1i128), 0); + + assert_eq!(cttz_nonzero(1u8), 0); assert_eq!(cttz_nonzero(1i8), 0); + assert_eq!(cttz_nonzero(1u16), 0); assert_eq!(cttz_nonzero(1i16), 0); + assert_eq!(cttz_nonzero(1u32), 0); assert_eq!(cttz_nonzero(1i32), 0); + assert_eq!(cttz_nonzero(1u64), 0); assert_eq!(cttz_nonzero(1i64), 0); + assert_eq!(cttz_nonzero(1u128), 0); assert_eq!(cttz_nonzero(1i128), 0); + + assert_eq!(cttz_nonzero(10u8), 1); assert_eq!(cttz_nonzero(10i8), 1); + assert_eq!(cttz_nonzero(10u16), 1); assert_eq!(cttz_nonzero(10i16), 1); + assert_eq!(cttz_nonzero(10u32), 1); assert_eq!(cttz_nonzero(10i32), 1); + assert_eq!(cttz_nonzero(10u64), 1); assert_eq!(cttz_nonzero(10i64), 1); + assert_eq!(cttz_nonzero(10u128), 1); assert_eq!(cttz_nonzero(10i128), 1); + + assert_eq!(cttz_nonzero(100u8), 2); assert_eq!(cttz_nonzero(100i8), 2); + assert_eq!(cttz_nonzero(100u16), 2); assert_eq!(cttz_nonzero(100i16), 2); + assert_eq!(cttz_nonzero(100u32), 2); assert_eq!(cttz_nonzero(100i32), 2); + assert_eq!(cttz_nonzero(100u64), 2); assert_eq!(cttz_nonzero(100i64), 2); + assert_eq!(cttz_nonzero(100u128), 2); assert_eq!(cttz_nonzero(100i128), 2); + } + + assert_eq!(bswap(0x0Au8), 0x0A); // no-op + assert_eq!(bswap(0x0Ai8), 0x0A); // no-op + assert_eq!(bswap(0x0A0Bu16), 0x0B0A); + assert_eq!(bswap(0x0A0Bi16), 0x0B0A); + assert_eq!(bswap(0x0ABBCC0Du32), 0x0DCCBB0A); + assert_eq!(bswap(0x0ABBCC0Di32), 0x0DCCBB0A); + assert_eq!(bswap(0x0122334455667708u64), 0x0877665544332201); + assert_eq!(bswap(0x0122334455667708i64), 0x0877665544332201); + assert_eq!(bswap(0x0122334455667708u128), 0x08776655443322010000000000000000); + assert_eq!(bswap(0x0122334455667708i128), 0x08776655443322010000000000000000); + + assert_eq!(bitreverse(0x0Au8), 0x50); + assert_eq!(bitreverse(0x0Ai8), 0x50); + assert_eq!(bitreverse(0x0A0Cu16), 0x3050); + assert_eq!(bitreverse(0x0A0Ci16), 0x3050); + assert_eq!(bitreverse(0x0ABBCC0Eu32), 0x7033DD50); + assert_eq!(bitreverse(0x0ABBCC0Ei32), 0x7033DD50); + assert_eq!(bitreverse(0x0122334455667708u64), 0x10EE66AA22CC4480); + assert_eq!(bitreverse(0x0122334455667708i64), 0x10EE66AA22CC4480); + assert_eq!(bitreverse(0x0122334455667708u128), 0x10EE66AA22CC44800000000000000000); + assert_eq!(bitreverse(0x0122334455667708i128), 0x10EE66AA22CC44800000000000000000); +} diff --git a/tests/ui/intrinsics/intrinsics-math.rs b/tests/ui/intrinsics/intrinsics-math.rs new file mode 100644 index 000000000..aea9fde69 --- /dev/null +++ b/tests/ui/intrinsics/intrinsics-math.rs @@ -0,0 +1,60 @@ +// run-pass +// ignore-emscripten fma not implemented in emscripten + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => ({ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", *a, *b); + }) +} + +pub fn main() { + use std::f32; + use std::f64; + + assert_approx_eq!(64f32.sqrt(), 8f32); + assert_approx_eq!(64f64.sqrt(), 8f64); + + assert_approx_eq!(25f32.powi(-2), 0.0016f32); + assert_approx_eq!(23.2f64.powi(2), 538.24f64); + + assert_approx_eq!(0f32.sin(), 0f32); + assert_approx_eq!((f64::consts::PI / 2f64).sin(), 1f64); + + assert_approx_eq!(0f32.cos(), 1f32); + assert_approx_eq!((f64::consts::PI * 2f64).cos(), 1f64); + + assert_approx_eq!(25f32.powf(-2f32), 0.0016f32); + assert_approx_eq!(400f64.powf(0.5f64), 20f64); + + assert_approx_eq!((1f32.exp() - f32::consts::E).abs(), 0f32); + assert_approx_eq!(1f64.exp(), f64::consts::E); + + assert_approx_eq!(10f32.exp2(), 1024f32); + assert_approx_eq!(50f64.exp2(), 1125899906842624f64); + + assert_approx_eq!((f32::consts::E.ln() - 1f32).abs(), 0f32); + assert_approx_eq!(1f64.ln(), 0f64); + + assert_approx_eq!(10f32.log10(), 1f32); + assert_approx_eq!(f64::consts::E.log10(), f64::consts::LOG10_E); + + assert_approx_eq!(8f32.log2(), 3f32); + assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E); + + assert_approx_eq!(1.0f32.mul_add(2.0f32, 5.0f32), 7.0f32); + assert_approx_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); + + assert_approx_eq!((-1.0f32).abs(), 1.0f32); + assert_approx_eq!(34.2f64.abs(), 34.2f64); + + assert_approx_eq!(3.8f32.floor(), 3.0f32); + assert_approx_eq!((-1.1f64).floor(), -2.0f64); + + assert_approx_eq!((-2.3f32).ceil(), -2.0f32); + assert_approx_eq!(3.8f64.ceil(), 4.0f64); + + assert_approx_eq!(0.1f32.trunc(), 0.0f32); + assert_approx_eq!((-0.1f64).trunc(), 0.0f64); +} diff --git a/tests/ui/intrinsics/issue-28575.mir.stderr b/tests/ui/intrinsics/issue-28575.mir.stderr new file mode 100644 index 000000000..c42498390 --- /dev/null +++ b/tests/ui/intrinsics/issue-28575.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-28575.rs:11:5 + | +LL | FOO() + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/issue-28575.rs b/tests/ui/intrinsics/issue-28575.rs new file mode 100644 index 000000000..410f664f8 --- /dev/null +++ b/tests/ui/intrinsics/issue-28575.rs @@ -0,0 +1,12 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(intrinsics)] + +extern "C" { + pub static FOO: extern "rust-intrinsic" fn(); +} + +fn main() { + FOO() //~ ERROR: use of extern static is unsafe +} diff --git a/tests/ui/intrinsics/issue-28575.thir.stderr b/tests/ui/intrinsics/issue-28575.thir.stderr new file mode 100644 index 000000000..c42498390 --- /dev/null +++ b/tests/ui/intrinsics/issue-28575.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-28575.rs:11:5 + | +LL | FOO() + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/issue-84297-reifying-copy.rs b/tests/ui/intrinsics/issue-84297-reifying-copy.rs new file mode 100644 index 000000000..08ba9ce7e --- /dev/null +++ b/tests/ui/intrinsics/issue-84297-reifying-copy.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + let _unused = if true { + core::ptr::copy:: + } else { + core::ptr::copy_nonoverlapping:: + }; +} diff --git a/tests/ui/intrinsics/non-integer-atomic.rs b/tests/ui/intrinsics/non-integer-atomic.rs new file mode 100644 index 000000000..85ea81ba6 --- /dev/null +++ b/tests/ui/intrinsics/non-integer-atomic.rs @@ -0,0 +1,92 @@ +// build-fail + +#![feature(core_intrinsics)] +#![allow(warnings)] +#![crate_type = "rlib"] + +use std::intrinsics; + +#[derive(Copy, Clone)] +pub struct Foo(i64); +pub type Bar = &'static Fn(); +pub type Quux = [u8; 100]; + +pub unsafe fn test_bool_load(p: &mut bool, v: bool) { + intrinsics::atomic_load_seqcst(p); + //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool` +} + +pub unsafe fn test_bool_store(p: &mut bool, v: bool) { + intrinsics::atomic_store_seqcst(p, v); + //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool` +} + +pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) { + intrinsics::atomic_xchg_seqcst(p, v); + //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `bool` +} + +pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) { + intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `bool` +} + +pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) { + intrinsics::atomic_load_seqcst(p); + //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo` +} + +pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) { + intrinsics::atomic_store_seqcst(p, v); + //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo` +} + +pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) { + intrinsics::atomic_xchg_seqcst(p, v); + //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `Foo` +} + +pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) { + intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `Foo` +} + +pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) { + intrinsics::atomic_load_seqcst(p); + //~^ ERROR expected basic integer type, found `&dyn Fn()` +} + +pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) { + intrinsics::atomic_store_seqcst(p, v); + //~^ ERROR expected basic integer type, found `&dyn Fn()` +} + +pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) { + intrinsics::atomic_xchg_seqcst(p, v); + //~^ ERROR expected basic integer type, found `&dyn Fn()` +} + +pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) { + intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + //~^ ERROR expected basic integer type, found `&dyn Fn()` +} + +pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) { + intrinsics::atomic_load_seqcst(p); + //~^ ERROR `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` +} + +pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) { + intrinsics::atomic_store_seqcst(p, v); + //~^ ERROR `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` +} + +pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) { + intrinsics::atomic_xchg_seqcst(p, v); + //~^ ERROR `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` +} + +pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) { + intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + //~^ ERROR `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` +} diff --git a/tests/ui/intrinsics/non-integer-atomic.stderr b/tests/ui/intrinsics/non-integer-atomic.stderr new file mode 100644 index 000000000..32791a8e8 --- /dev/null +++ b/tests/ui/intrinsics/non-integer-atomic.stderr @@ -0,0 +1,99 @@ +error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `bool` + --> $DIR/non-integer-atomic.rs:15:5 + | +LL | intrinsics::atomic_load_seqcst(p); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `bool` + --> $DIR/non-integer-atomic.rs:20:5 + | +LL | intrinsics::atomic_store_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `bool` + --> $DIR/non-integer-atomic.rs:25:5 + | +LL | intrinsics::atomic_xchg_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `bool` + --> $DIR/non-integer-atomic.rs:30:5 + | +LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `Foo` + --> $DIR/non-integer-atomic.rs:35:5 + | +LL | intrinsics::atomic_load_seqcst(p); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `Foo` + --> $DIR/non-integer-atomic.rs:40:5 + | +LL | intrinsics::atomic_store_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `Foo` + --> $DIR/non-integer-atomic.rs:45:5 + | +LL | intrinsics::atomic_xchg_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `Foo` + --> $DIR/non-integer-atomic.rs:50:5 + | +LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:55:5 + | +LL | intrinsics::atomic_load_seqcst(p); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:60:5 + | +LL | intrinsics::atomic_store_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:65:5 + | +LL | intrinsics::atomic_xchg_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:70:5 + | +LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_load_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:75:5 + | +LL | intrinsics::atomic_load_seqcst(p); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_store_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:80:5 + | +LL | intrinsics::atomic_store_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_xchg_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:85:5 + | +LL | intrinsics::atomic_xchg_seqcst(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_cxchg_seqcst_seqcst` intrinsic: expected basic integer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:90:5 + | +LL | intrinsics::atomic_cxchg_seqcst_seqcst(p, v, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/intrinsics/panic-uninitialized-zeroed.rs b/tests/ui/intrinsics/panic-uninitialized-zeroed.rs new file mode 100644 index 000000000..1a0104b85 --- /dev/null +++ b/tests/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -0,0 +1,397 @@ +// run-pass +// revisions: default strict +// [strict]compile-flags: -Zstrict-init-checks +// ignore-tidy-linelength +// ignore-emscripten spawning processes is not supported +// ignore-sgx no processes + +// This test checks panic emitted from `mem::{uninitialized,zeroed}`. + +#![feature(never_type)] +#![allow(deprecated, invalid_value)] + +use std::{ + mem::{self, MaybeUninit, ManuallyDrop}, + ptr::NonNull, + num, +}; + +#[allow(dead_code)] +struct Foo { + x: u8, + y: !, +} + +enum Bar {} + +#[allow(dead_code)] +enum OneVariant { Variant(i32) } + +#[allow(dead_code, non_camel_case_types)] +enum OneVariant_NonZero { + Variant(i32, i32, num::NonZeroI32), + DeadVariant(Bar), +} + +#[allow(dead_code, non_camel_case_types)] +enum OneVariant_Ref { + Variant(&'static i32), + DeadVariant(Bar), +} + +// An `Aggregate` abi enum where 0 is not a valid discriminant. +#[allow(dead_code)] +#[repr(i32)] +enum NoNullVariant { + Variant1(i32, i32) = 1, + Variant2(i32, i32) = 2, +} + +// An enum with ScalarPair layout +#[allow(dead_code)] +enum LR { + Left(i64), + Right(i64), +} +#[allow(dead_code, non_camel_case_types)] +enum LR_NonZero { + Left(num::NonZeroI64), + Right(num::NonZeroI64), +} + +struct ZeroSized; + +#[allow(dead_code)] +#[repr(i32)] +enum ZeroIsValid { + Zero(u8) = 0, + One(NonNull<()>) = 1, +} + +#[track_caller] +fn test_panic_msg T) + 'static>(op: F, msg: &str) { + use std::{panic, env, process}; + + // The tricky part is that we can't just run `op`, as that would *abort* the process. + // So instead, we reinvoke this process with the caller location as argument. + // For the purpose of this test, the line number is unique enough. + // If we are running in such a re-invocation, we skip all the tests *except* for the one with that type name. + let our_loc = panic::Location::caller().line().to_string(); + let mut args = env::args(); + let this = args.next().unwrap(); + if let Some(loc) = args.next() { + if loc == our_loc { + op(); + panic!("we did not abort"); + } else { + // Nothing, we are running another test. + } + } else { + // Invoke new process for actual test, and check result. + let mut cmd = process::Command::new(this); + cmd.arg(our_loc); + let res = cmd.output().unwrap(); + assert!(!res.status.success(), "test did not fail"); + let stderr = String::from_utf8_lossy(&res.stderr); + assert!(stderr.contains(msg), "test did not contain expected output: looking for {:?}, output:\n{}", msg, stderr); + } +} + +#[track_caller] +fn test_panic_msg_only_if_strict(op: impl (FnOnce() -> T) + 'static, msg: &str) { + if !cfg!(strict) { + // Just run it. + op(); + } else { + test_panic_msg(op, msg); + } +} + +fn main() { + unsafe { + // Uninhabited types + test_panic_msg( + || mem::uninitialized::(), + "attempted to instantiate uninhabited type `!`" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to instantiate uninhabited type `!`" + ); + test_panic_msg( + || MaybeUninit::::uninit().assume_init(), + "attempted to instantiate uninhabited type `!`" + ); + + test_panic_msg( + || mem::uninitialized::(), + "attempted to instantiate uninhabited type `Foo`" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to instantiate uninhabited type `Foo`" + ); + test_panic_msg( + || MaybeUninit::::uninit().assume_init(), + "attempted to instantiate uninhabited type `Foo`" + ); + + test_panic_msg( + || mem::uninitialized::(), + "attempted to instantiate uninhabited type `Bar`" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to instantiate uninhabited type `Bar`" + ); + test_panic_msg( + || MaybeUninit::::uninit().assume_init(), + "attempted to instantiate uninhabited type `Bar`" + ); + + test_panic_msg( + || mem::uninitialized::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Foo; 2]>(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Foo; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Foo; 2]`" + ); + + test_panic_msg( + || mem::uninitialized::<[Bar; 2]>(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + test_panic_msg( + || mem::zeroed::<[Bar; 2]>(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + test_panic_msg( + || MaybeUninit::<[Bar; 2]>::uninit().assume_init(), + "attempted to instantiate uninhabited type `[Bar; 2]`" + ); + + // Types that don't allow either. + test_panic_msg( + || mem::zeroed::<&i32>(), + "attempted to zero-initialize type `&i32`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&i32>(), + "attempted to leave type `&i32` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::>(), + "attempted to zero-initialize type `alloc::boxed::Box<[i32; 0]>`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::>(), + "attempted to leave type `alloc::boxed::Box<[i32; 0]>` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::>(), + "attempted to zero-initialize type `alloc::boxed::Box`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::>(), + "attempted to leave type `alloc::boxed::Box` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&[i32]>(), + "attempted to zero-initialize type `&[i32]`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&[i32]>(), + "attempted to leave type `&[i32]` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&(u8, [u8])>(), + "attempted to zero-initialize type `&(u8, [u8])`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&(u8, [u8])>(), + "attempted to leave type `&(u8, [u8])` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&dyn Send>(), + "attempted to zero-initialize type `&dyn core::marker::Send`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<&dyn Send>(), + "attempted to leave type `&dyn core::marker::Send` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<*const dyn Send>(), + "attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::<*const dyn Send>(), + "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `NoNullVariant` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to zero-initialize type `NoNullVariant`, \ + which is invalid" + ); + + test_panic_msg( + || mem::zeroed::(), + "attempted to zero-initialize type `OneVariant_Ref`, \ + which is invalid" + ); + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `OneVariant_Ref` uninitialized, which is invalid" + ); + + // Types where both are invalid, but we allow uninit since the 0x01-filling is not LLVM UB. + test_panic_msg( + || mem::zeroed::(), + "attempted to zero-initialize type `fn()`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::(), + "attempted to leave type `fn()` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&()>(), + "attempted to zero-initialize type `&()`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<&()>(), + "attempted to leave type `&()` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&[u8]>(), + "attempted to zero-initialize type `&[u8]`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<&[u8]>(), + "attempted to leave type `&[u8]` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<&str>(), + "attempted to zero-initialize type `&str`, which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<&str>(), + "attempted to leave type `&str` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::<(NonNull, u32, u32)>(), + "attempted to zero-initialize type `(core::ptr::non_null::NonNull, u32, u32)`, \ + which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::<(NonNull, u32, u32)>(), + "attempted to leave type `(core::ptr::non_null::NonNull, u32, u32)` uninitialized, which is invalid" + ); + + test_panic_msg( + || mem::zeroed::(), + "attempted to zero-initialize type `OneVariant_NonZero`, \ + which is invalid" + ); + test_panic_msg_only_if_strict( + || mem::uninitialized::(), + "attempted to leave type `OneVariant_NonZero` uninitialized, which is invalid" + ); + + // Types where both are invalid but we allow the zeroed form since it is not LLVM UB. + test_panic_msg_only_if_strict( + || mem::zeroed::(), + "attempted to zero-initialize type `LR_NonZero`, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `LR_NonZero` uninitialized, which is invalid" + ); + + test_panic_msg_only_if_strict( + || mem::zeroed::>(), + "attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop`, \ + which is invalid" + ); + test_panic_msg( + || mem::uninitialized::>(), + "attempted to leave type `core::mem::manually_drop::ManuallyDrop` uninitialized, \ + which is invalid" + ); + + // Some strict-only things + test_panic_msg_only_if_strict( + || mem::uninitialized::(), + "attempted to leave type `i32` uninitialized, which is invalid" + ); + + test_panic_msg_only_if_strict( + || mem::uninitialized::<*const ()>(), + "attempted to leave type `*const ()` uninitialized, which is invalid" + ); + + test_panic_msg_only_if_strict( + || mem::uninitialized::<[i32; 1]>(), + "attempted to leave type `[i32; 1]` uninitialized, which is invalid" + ); + + test_panic_msg_only_if_strict( + || mem::zeroed::<[NonNull<()>; 1]>(), + "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid" + ); + + // Types that can be zero, but not uninit (though some are mitigated). + let _val = mem::zeroed::(); + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `LR` uninitialized, which is invalid" + ); + + let _val = mem::zeroed::>(); + test_panic_msg( + || mem::uninitialized::>(), + "attempted to leave type `core::mem::manually_drop::ManuallyDrop` uninitialized, which is invalid" + ); + + let _val = mem::zeroed::(); + test_panic_msg_only_if_strict( + || mem::uninitialized::(), + "attempted to leave type `bool` uninitialized, which is invalid" + ); + + let _val = mem::zeroed::(); + test_panic_msg_only_if_strict( + || mem::uninitialized::(), + "attempted to leave type `OneVariant` uninitialized, which is invalid" + ); + + // Some things that are actually allowed. + let _val = mem::zeroed::>(); + let _val = mem::zeroed::>>(); + let _val = mem::zeroed::<[!; 0]>(); + let _val = mem::zeroed::(); + let _val = mem::uninitialized::>(); + let _val = mem::uninitialized::<[!; 0]>(); + let _val = mem::uninitialized::<()>(); + let _val = mem::uninitialized::(); + } +} diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs new file mode 100644 index 000000000..50e12eaeb --- /dev/null +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -0,0 +1,11 @@ +#![feature(intrinsics)] +#![feature(rustc_attrs)] + +extern "rust-intrinsic" { + fn size_of() -> usize; //~ ERROR intrinsic safety mismatch + + #[rustc_safe_intrinsic] + fn assume(b: bool); //~ ERROR intrinsic safety mismatch +} + +fn main() {} diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr new file mode 100644 index 000000000..0c2f3be49 --- /dev/null +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -0,0 +1,14 @@ +error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` + --> $DIR/safe-intrinsic-mismatch.rs:5:5 + | +LL | fn size_of() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` + --> $DIR/safe-intrinsic-mismatch.rs:8:5 + | +LL | fn assume(b: bool); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/intrinsics/unchecked_math_unsafe.mir.stderr b/tests/ui/intrinsics/unchecked_math_unsafe.mir.stderr new file mode 100644 index 000000000..26b2f9f27 --- /dev/null +++ b/tests/ui/intrinsics/unchecked_math_unsafe.mir.stderr @@ -0,0 +1,27 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unchecked_math_unsafe.rs:8:15 + | +LL | let add = std::intrinsics::unchecked_add(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unchecked_math_unsafe.rs:9:15 + | +LL | let sub = std::intrinsics::unchecked_sub(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unchecked_math_unsafe.rs:10:15 + | +LL | let mul = std::intrinsics::unchecked_mul(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/unchecked_math_unsafe.rs b/tests/ui/intrinsics/unchecked_math_unsafe.rs new file mode 100644 index 000000000..98d3a11ad --- /dev/null +++ b/tests/ui/intrinsics/unchecked_math_unsafe.rs @@ -0,0 +1,11 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(core_intrinsics)] + +fn main() { + let (x, y) = (1u32, 2u32); + let add = std::intrinsics::unchecked_add(x, y); //~ ERROR call to unsafe function + let sub = std::intrinsics::unchecked_sub(x, y); //~ ERROR call to unsafe function + let mul = std::intrinsics::unchecked_mul(x, y); //~ ERROR call to unsafe function +} diff --git a/tests/ui/intrinsics/unchecked_math_unsafe.thir.stderr b/tests/ui/intrinsics/unchecked_math_unsafe.thir.stderr new file mode 100644 index 000000000..5c3728ccd --- /dev/null +++ b/tests/ui/intrinsics/unchecked_math_unsafe.thir.stderr @@ -0,0 +1,27 @@ +error[E0133]: call to unsafe function `unchecked_add` is unsafe and requires unsafe function or block + --> $DIR/unchecked_math_unsafe.rs:8:15 + | +LL | let add = std::intrinsics::unchecked_add(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `unchecked_sub` is unsafe and requires unsafe function or block + --> $DIR/unchecked_math_unsafe.rs:9:15 + | +LL | let sub = std::intrinsics::unchecked_sub(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `unchecked_mul` is unsafe and requires unsafe function or block + --> $DIR/unchecked_math_unsafe.rs:10:15 + | +LL | let mul = std::intrinsics::unchecked_mul(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/unchecked_math_unstable.rs b/tests/ui/intrinsics/unchecked_math_unstable.rs new file mode 100644 index 000000000..8869063d1 --- /dev/null +++ b/tests/ui/intrinsics/unchecked_math_unstable.rs @@ -0,0 +1,8 @@ +fn main() { + let (x, y) = (1u32, 2u32); + unsafe { + let add = std::intrinsics::unchecked_add(x, y); //~ ERROR use of unstable library feature + let sub = std::intrinsics::unchecked_sub(x, y); //~ ERROR use of unstable library feature + let mul = std::intrinsics::unchecked_mul(x, y); //~ ERROR use of unstable library feature + } +} diff --git a/tests/ui/intrinsics/unchecked_math_unstable.stderr b/tests/ui/intrinsics/unchecked_math_unstable.stderr new file mode 100644 index 000000000..a43aa16ae --- /dev/null +++ b/tests/ui/intrinsics/unchecked_math_unstable.stderr @@ -0,0 +1,27 @@ +error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/unchecked_math_unstable.rs:4:19 + | +LL | let add = std::intrinsics::unchecked_add(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/unchecked_math_unstable.rs:5:19 + | +LL | let sub = std::intrinsics::unchecked_sub(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/unchecked_math_unstable.rs:6:19 + | +LL | let mul = std::intrinsics::unchecked_mul(x, y); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr new file mode 100644 index 000000000..d0e8d4719 --- /dev/null +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr @@ -0,0 +1,2 @@ +error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf` was expected + diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr new file mode 100644 index 000000000..52a591902 --- /dev/null +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADTARGET.stderr @@ -0,0 +1,4 @@ +error: `-Zbranch-protection` is only supported on aarch64 + +error: aborting due to previous error + diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs new file mode 100644 index 000000000..1d7ec5cba --- /dev/null +++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs @@ -0,0 +1,14 @@ +// revisions: BADFLAGS BADTARGET +// [BADFLAGS] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=leaf +// [BADFLAGS] check-fail +// [BADFLAGS] needs-llvm-components: aarch64 +// [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti +// [BADTARGET] check-fail +// [BADTARGET] needs-llvm-components: x86 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized { } diff --git a/tests/ui/invalid-compile-flags/codegen-option-without-group.rs b/tests/ui/invalid-compile-flags/codegen-option-without-group.rs new file mode 100644 index 000000000..7bbf47a38 --- /dev/null +++ b/tests/ui/invalid-compile-flags/codegen-option-without-group.rs @@ -0,0 +1 @@ +// compile-flags: --llvm-args diff --git a/tests/ui/invalid-compile-flags/codegen-option-without-group.stderr b/tests/ui/invalid-compile-flags/codegen-option-without-group.stderr new file mode 100644 index 000000000..c5a0c29ca --- /dev/null +++ b/tests/ui/invalid-compile-flags/codegen-option-without-group.stderr @@ -0,0 +1,2 @@ +error: Unrecognized option: 'llvm-args'. Did you mean `-C llvm-args`? + diff --git a/tests/ui/invalid-compile-flags/debug-option-without-group.rs b/tests/ui/invalid-compile-flags/debug-option-without-group.rs new file mode 100644 index 000000000..86e40c178 --- /dev/null +++ b/tests/ui/invalid-compile-flags/debug-option-without-group.rs @@ -0,0 +1 @@ +// compile-flags: --unpretty=hir diff --git a/tests/ui/invalid-compile-flags/debug-option-without-group.stderr b/tests/ui/invalid-compile-flags/debug-option-without-group.stderr new file mode 100644 index 000000000..0e57e31ad --- /dev/null +++ b/tests/ui/invalid-compile-flags/debug-option-without-group.stderr @@ -0,0 +1,2 @@ +error: Unrecognized option: 'unpretty'. Did you mean `-Z unpretty`? + diff --git a/tests/ui/invalid-module-declaration/auxiliary/foo/bar.rs b/tests/ui/invalid-module-declaration/auxiliary/foo/bar.rs new file mode 100644 index 000000000..bcfd7dc0a --- /dev/null +++ b/tests/ui/invalid-module-declaration/auxiliary/foo/bar.rs @@ -0,0 +1 @@ +pub mod baz; diff --git a/tests/ui/invalid-module-declaration/auxiliary/foo/mod.rs b/tests/ui/invalid-module-declaration/auxiliary/foo/mod.rs new file mode 100644 index 000000000..46f285ca4 --- /dev/null +++ b/tests/ui/invalid-module-declaration/auxiliary/foo/mod.rs @@ -0,0 +1 @@ +pub mod bar; diff --git a/tests/ui/invalid-module-declaration/invalid-module-declaration.rs b/tests/ui/invalid-module-declaration/invalid-module-declaration.rs new file mode 100644 index 000000000..254d810d7 --- /dev/null +++ b/tests/ui/invalid-module-declaration/invalid-module-declaration.rs @@ -0,0 +1,5 @@ +mod auxiliary { + mod foo; +} + +fn main() {} diff --git a/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr b/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr new file mode 100644 index 000000000..7bc8efd7e --- /dev/null +++ b/tests/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -0,0 +1,11 @@ +error[E0583]: file not found for module `baz` + --> $DIR/auxiliary/foo/bar.rs:1:1 + | +LL | pub mod baz; + | ^^^^^^^^^^^^ + | + = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs" or "$DIR/auxiliary/foo/bar/baz/mod.rs" + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/invalid-self-argument/bare-fn-start.rs b/tests/ui/invalid-self-argument/bare-fn-start.rs new file mode 100644 index 000000000..7c580bc5a --- /dev/null +++ b/tests/ui/invalid-self-argument/bare-fn-start.rs @@ -0,0 +1,6 @@ +fn a(&self) { } +//~^ ERROR `self` parameter is only allowed in associated functions +//~| NOTE not semantically valid as function parameter +//~| NOTE associated functions are those in `impl` or `trait` definitions + +fn main() { } diff --git a/tests/ui/invalid-self-argument/bare-fn-start.stderr b/tests/ui/invalid-self-argument/bare-fn-start.stderr new file mode 100644 index 000000000..37753e61f --- /dev/null +++ b/tests/ui/invalid-self-argument/bare-fn-start.stderr @@ -0,0 +1,10 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/bare-fn-start.rs:1:6 + | +LL | fn a(&self) { } + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: aborting due to previous error + diff --git a/tests/ui/invalid-self-argument/bare-fn.rs b/tests/ui/invalid-self-argument/bare-fn.rs new file mode 100644 index 000000000..342bdc31a --- /dev/null +++ b/tests/ui/invalid-self-argument/bare-fn.rs @@ -0,0 +1,5 @@ +fn b(foo: u32, &mut self) { } +//~^ ERROR unexpected `self` parameter in function +//~| NOTE must be the first parameter of an associated function + +fn main() { } diff --git a/tests/ui/invalid-self-argument/bare-fn.stderr b/tests/ui/invalid-self-argument/bare-fn.stderr new file mode 100644 index 000000000..ff2217b5e --- /dev/null +++ b/tests/ui/invalid-self-argument/bare-fn.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` parameter in function + --> $DIR/bare-fn.rs:1:16 + | +LL | fn b(foo: u32, &mut self) { } + | ^^^^^^^^^ must be the first parameter of an associated function + +error: aborting due to previous error + diff --git a/tests/ui/invalid-self-argument/trait-fn.rs b/tests/ui/invalid-self-argument/trait-fn.rs new file mode 100644 index 000000000..5ccea5895 --- /dev/null +++ b/tests/ui/invalid-self-argument/trait-fn.rs @@ -0,0 +1,11 @@ +struct Foo {} + +impl Foo { + fn c(foo: u32, self) {} + //~^ ERROR unexpected `self` parameter in function + //~| NOTE must be the first parameter of an associated function + + fn good(&mut self, foo: u32) {} +} + +fn main() { } diff --git a/tests/ui/invalid-self-argument/trait-fn.stderr b/tests/ui/invalid-self-argument/trait-fn.stderr new file mode 100644 index 000000000..b9887af96 --- /dev/null +++ b/tests/ui/invalid-self-argument/trait-fn.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` parameter in function + --> $DIR/trait-fn.rs:4:20 + | +LL | fn c(foo: u32, self) {} + | ^^^^ must be the first parameter of an associated function + +error: aborting due to previous error + diff --git a/tests/ui/invalid/invalid-crate-type-macro.rs b/tests/ui/invalid/invalid-crate-type-macro.rs new file mode 100644 index 000000000..9ba5e79ba --- /dev/null +++ b/tests/ui/invalid/invalid-crate-type-macro.rs @@ -0,0 +1,7 @@ +#![crate_type = foo!()] //~ ERROR malformed `crate_type` attribute + +macro_rules! foo { + () => {"rlib"}; +} + +fn main() {} diff --git a/tests/ui/invalid/invalid-crate-type-macro.stderr b/tests/ui/invalid/invalid-crate-type-macro.stderr new file mode 100644 index 000000000..c196d4278 --- /dev/null +++ b/tests/ui/invalid/invalid-crate-type-macro.stderr @@ -0,0 +1,8 @@ +error: malformed `crate_type` attribute input + --> $DIR/invalid-crate-type-macro.rs:1:1 + | +LL | #![crate_type = foo!()] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + +error: aborting due to previous error + diff --git a/tests/ui/invalid/invalid-crate-type.rs b/tests/ui/invalid/invalid-crate-type.rs new file mode 100644 index 000000000..6c44c3b4f --- /dev/null +++ b/tests/ui/invalid/invalid-crate-type.rs @@ -0,0 +1,48 @@ +// regression test for issue 11256 +#![crate_type="foo"] //~ ERROR invalid `crate_type` value + +// Tests for suggestions (#53958) + +#![crate_type="statoclib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION staticlib + +#![crate_type="procmacro"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION proc-macro + +#![crate_type="static-lib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION staticlib + +#![crate_type="drylib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION dylib + +#![crate_type="dlib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION rlib + +#![crate_type="lob"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION lib + +#![crate_type="bon"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION bin + +#![crate_type="cdalib"] +//~^ ERROR invalid `crate_type` value +//~| HELP did you mean +//~| SUGGESTION cdylib + +fn main() { + return +} diff --git a/tests/ui/invalid/invalid-crate-type.stderr b/tests/ui/invalid/invalid-crate-type.stderr new file mode 100644 index 000000000..59d5d7bc9 --- /dev/null +++ b/tests/ui/invalid/invalid-crate-type.stderr @@ -0,0 +1,58 @@ +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:2:15 + | +LL | #![crate_type="foo"] + | ^^^^^ + | + = note: `#[deny(unknown_crate_types)]` on by default + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:6:15 + | +LL | #![crate_type="statoclib"] + | ^^^^^^^^^^^ help: did you mean: `"staticlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:11:15 + | +LL | #![crate_type="procmacro"] + | ^^^^^^^^^^^ help: did you mean: `"proc-macro"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:16:15 + | +LL | #![crate_type="static-lib"] + | ^^^^^^^^^^^^ help: did you mean: `"staticlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:21:15 + | +LL | #![crate_type="drylib"] + | ^^^^^^^^ help: did you mean: `"dylib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:26:15 + | +LL | #![crate_type="dlib"] + | ^^^^^^ help: did you mean: `"rlib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:31:15 + | +LL | #![crate_type="lob"] + | ^^^^^ help: did you mean: `"lib"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:36:15 + | +LL | #![crate_type="bon"] + | ^^^^^ help: did you mean: `"bin"` + +error: invalid `crate_type` value + --> $DIR/invalid-crate-type.rs:41:15 + | +LL | #![crate_type="cdalib"] + | ^^^^^^^^ help: did you mean: `"cdylib"` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/invalid/invalid-debugger-visualizer-option.rs b/tests/ui/invalid/invalid-debugger-visualizer-option.rs new file mode 100644 index 000000000..5645a30cc --- /dev/null +++ b/tests/ui/invalid/invalid-debugger-visualizer-option.rs @@ -0,0 +1,7 @@ +// normalize-stderr-test: "foo.random:.*\(" -> "foo.random: $$FILE_NOT_FOUND_MSG (" +// normalize-stderr-test: "os error \d+" -> "os error $$FILE_NOT_FOUND_CODE" + +#![feature(debugger_visualizer)] +#![debugger_visualizer(random_file = "../foo.random")] //~ ERROR invalid argument +#![debugger_visualizer(natvis_file = "../foo.random")] //~ ERROR +fn main() {} diff --git a/tests/ui/invalid/invalid-debugger-visualizer-option.stderr b/tests/ui/invalid/invalid-debugger-visualizer-option.stderr new file mode 100644 index 000000000..afb8d16ee --- /dev/null +++ b/tests/ui/invalid/invalid-debugger-visualizer-option.stderr @@ -0,0 +1,18 @@ +error: invalid argument + --> $DIR/invalid-debugger-visualizer-option.rs:5:24 + | +LL | #![debugger_visualizer(random_file = "../foo.random")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected: `natvis_file = "..."` + = note: OR + = note: expected: `gdb_script_file = "..."` + +error: couldn't read $DIR/../foo.random: $FILE_NOT_FOUND_MSG (os error $FILE_NOT_FOUND_CODE) + --> $DIR/invalid-debugger-visualizer-option.rs:6:24 + | +LL | #![debugger_visualizer(natvis_file = "../foo.random")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs new file mode 100644 index 000000000..f0aba6a75 --- /dev/null +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs @@ -0,0 +1,4 @@ +#![feature(debugger_visualizer)] + +#[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module +fn main() {} diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr new file mode 100644 index 000000000..3555bbb16 --- /dev/null +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr @@ -0,0 +1,8 @@ +error: attribute should be applied to a module + --> $DIR/invalid-debugger-visualizer-target.rs:3:1 + | +LL | #[debugger_visualizer(natvis_file = "../foo.natvis")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/invalid/invalid-inline.rs b/tests/ui/invalid/invalid-inline.rs new file mode 100644 index 000000000..2501b1e23 --- /dev/null +++ b/tests/ui/invalid/invalid-inline.rs @@ -0,0 +1,14 @@ +#![allow(dead_code)] + +#[inline(please,no)] //~ ERROR expected one argument +fn a() { +} + +#[inline()] //~ ERROR expected one argument +fn b() { +} + +fn main() { + a(); + b(); +} diff --git a/tests/ui/invalid/invalid-inline.stderr b/tests/ui/invalid/invalid-inline.stderr new file mode 100644 index 000000000..7edbf936b --- /dev/null +++ b/tests/ui/invalid/invalid-inline.stderr @@ -0,0 +1,15 @@ +error[E0534]: expected one argument + --> $DIR/invalid-inline.rs:3:1 + | +LL | #[inline(please,no)] + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0534]: expected one argument + --> $DIR/invalid-inline.rs:7:1 + | +LL | #[inline()] + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0534`. diff --git a/tests/ui/invalid/invalid-llvm-passes.rs b/tests/ui/invalid/invalid-llvm-passes.rs new file mode 100644 index 000000000..ee28f5eb6 --- /dev/null +++ b/tests/ui/invalid/invalid-llvm-passes.rs @@ -0,0 +1,4 @@ +// build-fail +// compile-flags: -Cpasses=unknown-pass + +fn main() {} diff --git a/tests/ui/invalid/invalid-llvm-passes.stderr b/tests/ui/invalid/invalid-llvm-passes.stderr new file mode 100644 index 000000000..ae1f85e41 --- /dev/null +++ b/tests/ui/invalid/invalid-llvm-passes.stderr @@ -0,0 +1,4 @@ +error: failed to run LLVM passes: unknown pass name 'unknown-pass' + +error: aborting due to previous error + diff --git a/tests/ui/invalid/invalid-macro-matcher.rs b/tests/ui/invalid/invalid-macro-matcher.rs new file mode 100644 index 000000000..ff79d4e1a --- /dev/null +++ b/tests/ui/invalid/invalid-macro-matcher.rs @@ -0,0 +1,8 @@ +#![allow(unused_macros)] + +macro_rules! invalid { + _ => (); //~ ERROR invalid macro matcher +} + +fn main() { +} diff --git a/tests/ui/invalid/invalid-macro-matcher.stderr b/tests/ui/invalid/invalid-macro-matcher.stderr new file mode 100644 index 000000000..dbe025b73 --- /dev/null +++ b/tests/ui/invalid/invalid-macro-matcher.stderr @@ -0,0 +1,8 @@ +error: invalid macro matcher; matchers must be contained in balanced delimiters + --> $DIR/invalid-macro-matcher.rs:4:5 + | +LL | _ => (); + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/invalid/invalid-no-sanitize.rs b/tests/ui/invalid/invalid-no-sanitize.rs new file mode 100644 index 000000000..b52e3cc83 --- /dev/null +++ b/tests/ui/invalid/invalid-no-sanitize.rs @@ -0,0 +1,5 @@ +#![feature(no_sanitize)] + +#[no_sanitize(brontosaurus)] //~ ERROR invalid argument +fn main() { +} diff --git a/tests/ui/invalid/invalid-no-sanitize.stderr b/tests/ui/invalid/invalid-no-sanitize.stderr new file mode 100644 index 000000000..460003495 --- /dev/null +++ b/tests/ui/invalid/invalid-no-sanitize.stderr @@ -0,0 +1,10 @@ +error: invalid argument for `no_sanitize` + --> $DIR/invalid-no-sanitize.rs:3:15 + | +LL | #[no_sanitize(brontosaurus)] + | ^^^^^^^^^^^^ + | + = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` + +error: aborting due to previous error + diff --git a/tests/ui/invalid/invalid-path-in-const.rs b/tests/ui/invalid/invalid-path-in-const.rs new file mode 100644 index 000000000..51eb86072 --- /dev/null +++ b/tests/ui/invalid/invalid-path-in-const.rs @@ -0,0 +1,4 @@ +fn main() { + fn f(a: [u8; u32::DOESNOTEXIST]) {} + //~^ ERROR no associated item named `DOESNOTEXIST` found for type `u32` +} diff --git a/tests/ui/invalid/invalid-path-in-const.stderr b/tests/ui/invalid/invalid-path-in-const.stderr new file mode 100644 index 000000000..a14ab7d85 --- /dev/null +++ b/tests/ui/invalid/invalid-path-in-const.stderr @@ -0,0 +1,9 @@ +error[E0599]: no associated item named `DOESNOTEXIST` found for type `u32` in the current scope + --> $DIR/invalid-path-in-const.rs:2:23 + | +LL | fn f(a: [u8; u32::DOESNOTEXIST]) {} + | ^^^^^^^^^^^^ associated item not found in `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/invalid/invalid-plugin-attr.rs b/tests/ui/invalid/invalid-plugin-attr.rs new file mode 100644 index 000000000..3080af245 --- /dev/null +++ b/tests/ui/invalid/invalid-plugin-attr.rs @@ -0,0 +1,7 @@ +#![deny(unused_attributes)] +#![feature(plugin)] + +#[plugin(bla)] //~ ERROR should be an inner attribute +//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated + +fn main() {} diff --git a/tests/ui/invalid/invalid-plugin-attr.stderr b/tests/ui/invalid/invalid-plugin-attr.stderr new file mode 100644 index 000000000..d3882d33f --- /dev/null +++ b/tests/ui/invalid/invalid-plugin-attr.stderr @@ -0,0 +1,22 @@ +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 + --> $DIR/invalid-plugin-attr.rs:4:1 + | +LL | #[plugin(bla)] + | ^^^^^^^^^^^^^^ help: may be removed in a future compiler version + | + = note: `#[warn(deprecated)]` on by default + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/invalid-plugin-attr.rs:4:1 + | +LL | #[plugin(bla)] + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/invalid-plugin-attr.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs new file mode 100644 index 000000000..6eabd9b10 --- /dev/null +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs @@ -0,0 +1,43 @@ +#![feature(rustc_attrs)] + +#[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] must have one index for +fn foo1() {} + +#[rustc_legacy_const_generics(1)] //~ ERROR index exceeds number of arguments +fn foo2() {} + +#[rustc_legacy_const_generics(2)] //~ ERROR index exceeds number of arguments +fn foo3(_: u8) {} + +#[rustc_legacy_const_generics(a)] //~ ERROR arguments should be non-negative integers +fn foo4() {} + +#[rustc_legacy_const_generics(1, a, 2, b)] //~ ERROR arguments should be non-negative integers +fn foo5() {} + +#[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function +struct S; + +#[rustc_legacy_const_generics(0usize)] //~ ERROR suffixed literals are not allowed in attributes +fn foo6() {} + +extern { + #[rustc_legacy_const_generics(1)] //~ ERROR attribute should be applied to a function + fn foo7(); //~ ERROR foreign items may not have const parameters +} + +#[rustc_legacy_const_generics(0)] //~ ERROR #[rustc_legacy_const_generics] functions must only have +fn foo8() {} + +impl S { + #[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function + fn foo9() {} +} + +#[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute +fn bar1() {} + +#[rustc_legacy_const_generics = 1] //~ ERROR malformed `rustc_legacy_const_generics` attribute +fn bar2() {} + +fn main() {} diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr new file mode 100644 index 000000000..1ced1433f --- /dev/null +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr @@ -0,0 +1,95 @@ +error: suffixed literals are not allowed in attributes + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:21:31 + | +LL | #[rustc_legacy_const_generics(0usize)] + | ^^^^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:37:1 + | +LL | #[rustc_legacy_const_generics] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` + +error: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:40:1 + | +LL | #[rustc_legacy_const_generics = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` + +error: #[rustc_legacy_const_generics] must have one index for each generic parameter + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:1 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo1() {} + | - generic parameters + +error: index exceeds number of arguments + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:6:31 + | +LL | #[rustc_legacy_const_generics(1)] + | ^ there is only 1 argument + +error: index exceeds number of arguments + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:9:31 + | +LL | #[rustc_legacy_const_generics(2)] + | ^ there are only 2 arguments + +error: arguments should be non-negative integers + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:12:31 + | +LL | #[rustc_legacy_const_generics(a)] + | ^ + +error: arguments should be non-negative integers + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:15:34 + | +LL | #[rustc_legacy_const_generics(1, a, 2, b)] + | ^ ^ + +error: attribute should be applied to a function definition + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:18:1 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | struct S; + | --------- not a function definition + +error: #[rustc_legacy_const_generics] functions must only have const generics + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:1 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo8() {} + | - non-const generic parameter + +error: attribute should be applied to a function definition + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:5 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo9() {} + | ---------------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5 + | +LL | #[rustc_legacy_const_generics(1)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo7(); + | -------------------------- not a function definition + +error[E0044]: foreign items may not have const parameters + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:26:5 + | +LL | fn foo7(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters + | + = help: replace the const parameters with concrete consts + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs new file mode 100644 index 000000000..06cf8c0f0 --- /dev/null +++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs @@ -0,0 +1,30 @@ +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(u32::MAX)] //~ ERROR +pub struct A(u32); + +#[rustc_layout_scalar_valid_range_end(1, 2)] //~ ERROR +pub struct B(u8); + +#[rustc_layout_scalar_valid_range_end(a = "a")] //~ ERROR +pub struct C(i32); + +#[rustc_layout_scalar_valid_range_end(1)] //~ ERROR +enum E { + X = 1, + Y = 14, +} + +#[rustc_layout_scalar_valid_range_start(rustc_layout_scalar_valid_range_start)] //~ ERROR +struct NonZero(T); + +fn not_field() -> impl Send { + NonZero(false) +} + +fn main() { + let _ = A(0); + let _ = B(0); + let _ = C(0); + let _ = E::X; +} diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr new file mode 100644 index 000000000..7879e7358 --- /dev/null +++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr @@ -0,0 +1,37 @@ +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:3:1 + | +LL | #[rustc_layout_scalar_valid_range_start(u32::MAX)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:6:1 + | +LL | #[rustc_layout_scalar_valid_range_end(1, 2)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:9:1 + | +LL | #[rustc_layout_scalar_valid_range_end(a = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute should be applied to a struct + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1 + | +LL | #[rustc_layout_scalar_valid_range_end(1)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / enum E { +LL | | X = 1, +LL | | Y = 14, +LL | | } + | |_- not a struct + +error: expected exactly one integer literal argument + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:18:1 + | +LL | #[rustc_layout_scalar_valid_range_start(rustc_layout_scalar_valid_range_start)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/invalid_crate_type_syntax.rs b/tests/ui/invalid_crate_type_syntax.rs new file mode 100644 index 000000000..621587af3 --- /dev/null +++ b/tests/ui/invalid_crate_type_syntax.rs @@ -0,0 +1,6 @@ +// regression test for issue 16974 +#![crate_type(lib)] //~ ERROR malformed `crate_type` attribute input + +fn my_lib_fn() {} + +fn main() {} diff --git a/tests/ui/invalid_crate_type_syntax.stderr b/tests/ui/invalid_crate_type_syntax.stderr new file mode 100644 index 000000000..4072a2fa1 --- /dev/null +++ b/tests/ui/invalid_crate_type_syntax.stderr @@ -0,0 +1,8 @@ +error: malformed `crate_type` attribute input + --> $DIR/invalid_crate_type_syntax.rs:2:1 + | +LL | #![crate_type(lib)] + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + +error: aborting due to previous error + diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.rs b/tests/ui/invalid_dispatch_from_dyn_impls.rs new file mode 100644 index 000000000..b7bc766fb --- /dev/null +++ b/tests/ui/invalid_dispatch_from_dyn_impls.rs @@ -0,0 +1,51 @@ +#![feature(unsize, dispatch_from_dyn)] + +use std::{ + ops::DispatchFromDyn, + marker::{Unsize, PhantomData}, +}; + +struct WrapperWithExtraField(T, i32); + +impl DispatchFromDyn> for WrapperWithExtraField +where + T: DispatchFromDyn, +{} //~^^^ ERROR [E0378] + + +struct MultiplePointers{ + ptr1: *const T, + ptr2: *const T, +} + +impl DispatchFromDyn> for MultiplePointers +where + T: Unsize, +{} //~^^^ ERROR [E0378] + + +struct NothingToCoerce { + data: PhantomData, +} + +impl DispatchFromDyn> for NothingToCoerce {} +//~^ ERROR [E0378] + +#[repr(C)] +struct HasReprC(Box); + +impl DispatchFromDyn> for HasReprC +where + T: Unsize, +{} //~^^^ ERROR [E0378] + +#[repr(align(64))] +struct OverAlignedZst; +struct OverAligned(Box, OverAlignedZst); + +impl DispatchFromDyn> for OverAligned + where + T: Unsize, +{} //~^^^ ERROR [E0378] + +fn main() {} diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.stderr b/tests/ui/invalid_dispatch_from_dyn_impls.stderr new file mode 100644 index 000000000..b5b32d2f0 --- /dev/null +++ b/tests/ui/invalid_dispatch_from_dyn_impls.stderr @@ -0,0 +1,40 @@ +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 + | +LL | impl DispatchFromDyn> for WrapperWithExtraField + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: extra field `1` of type `i32` is not allowed + +error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions + --> $DIR/invalid_dispatch_from_dyn_impls.rs:21:1 + | +LL | impl DispatchFromDyn> for MultiplePointers + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced + = note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`) + +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found + --> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1 + | +LL | impl DispatchFromDyn> for NothingToCoerce {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` + --> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1 + | +LL | impl DispatchFromDyn> for HasReprC + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 + | +LL | impl DispatchFromDyn> for OverAligned + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: extra field `1` of type `OverAlignedZst` is not allowed + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0378`. diff --git a/tests/ui/issue-76387-llvm-miscompile.rs b/tests/ui/issue-76387-llvm-miscompile.rs new file mode 100644 index 000000000..a9b4686c9 --- /dev/null +++ b/tests/ui/issue-76387-llvm-miscompile.rs @@ -0,0 +1,22 @@ +// no-system-llvm +// compile-flags: -C opt-level=3 +// aux-build: issue-76387.rs +// run-pass + +// Regression test for issue #76387 +// Tests that LLVM doesn't miscompile this + +extern crate issue_76387; + +use issue_76387::FatPtr; + +fn print(data: &[u8]) { + println!("{:#?}", data); +} + +fn main() { + let ptr = FatPtr::new(20); + let data = unsafe { std::slice::from_raw_parts(ptr.as_ptr(), ptr.len()) }; + + print(data); +} diff --git a/tests/ui/issue-94866.rs b/tests/ui/issue-94866.rs new file mode 100644 index 000000000..c42034879 --- /dev/null +++ b/tests/ui/issue-94866.rs @@ -0,0 +1,14 @@ +macro_rules! m { + () => { + {} + }; +} + +enum Enum { A, B } + +fn main() { + match Enum::A { + //~^ ERROR non-exhaustive patterns + Enum::A => m!() + } +} diff --git a/tests/ui/issue-94866.stderr b/tests/ui/issue-94866.stderr new file mode 100644 index 000000000..b3c17ce89 --- /dev/null +++ b/tests/ui/issue-94866.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Enum::B` not covered + --> $DIR/issue-94866.rs:10:11 + | +LL | match Enum::A { + | ^^^^^^^ pattern `Enum::B` not covered + | +note: `Enum` defined here + --> $DIR/issue-94866.rs:7:16 + | +LL | enum Enum { A, B } + | ---- ^ not covered + = note: the matched value is of type `Enum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Enum::A => m!(), +LL + Enum::B => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/issues-71798.rs b/tests/ui/issues-71798.rs new file mode 100644 index 000000000..14b6c0f35 --- /dev/null +++ b/tests/ui/issues-71798.rs @@ -0,0 +1,8 @@ +fn test_ref(x: &u32) -> impl std::future::Future + '_ { + //~^ ERROR `u32` is not a future + *x +} + +fn main() { + let _ = test_ref & u; //~ ERROR cannot find value `u` in this scope +} diff --git a/tests/ui/issues-71798.stderr b/tests/ui/issues-71798.stderr new file mode 100644 index 000000000..829d0a02e --- /dev/null +++ b/tests/ui/issues-71798.stderr @@ -0,0 +1,22 @@ +error[E0425]: cannot find value `u` in this scope + --> $DIR/issues-71798.rs:7:24 + | +LL | let _ = test_ref & u; + | ^ not found in this scope + +error[E0277]: `u32` is not a future + --> $DIR/issues-71798.rs:1:25 + | +LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future +LL | +LL | *x + | -- return type was inferred to be `u32` here + | + = help: the trait `Future` is not implemented for `u32` + = note: u32 must be a future or must implement `IntoFuture` to be awaited + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/auxiliary/cgu_test.rs b/tests/ui/issues/auxiliary/cgu_test.rs new file mode 100644 index 000000000..5ed973164 --- /dev/null +++ b/tests/ui/issues/auxiliary/cgu_test.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic +// compile-flags: --crate-type=lib + +pub fn id(t: T) -> T { + t +} diff --git a/tests/ui/issues/auxiliary/cgu_test_a.rs b/tests/ui/issues/auxiliary/cgu_test_a.rs new file mode 100644 index 000000000..a3dcd9201 --- /dev/null +++ b/tests/ui/issues/auxiliary/cgu_test_a.rs @@ -0,0 +1,15 @@ +// no-prefer-dynamic +// compile-flags: -Ccodegen-units=2 --crate-type=lib + +extern crate cgu_test; + +pub mod a { + pub fn a() { + ::cgu_test::id(0); + } +} +pub mod b { + pub fn a() { + ::cgu_test::id(0); + } +} diff --git a/tests/ui/issues/auxiliary/cgu_test_b.rs b/tests/ui/issues/auxiliary/cgu_test_b.rs new file mode 100644 index 000000000..a3dcd9201 --- /dev/null +++ b/tests/ui/issues/auxiliary/cgu_test_b.rs @@ -0,0 +1,15 @@ +// no-prefer-dynamic +// compile-flags: -Ccodegen-units=2 --crate-type=lib + +extern crate cgu_test; + +pub mod a { + pub fn a() { + ::cgu_test::id(0); + } +} +pub mod b { + pub fn a() { + ::cgu_test::id(0); + } +} diff --git a/tests/ui/issues/auxiliary/i8.rs b/tests/ui/issues/auxiliary/i8.rs new file mode 100644 index 000000000..889a9c4eb --- /dev/null +++ b/tests/ui/issues/auxiliary/i8.rs @@ -0,0 +1,3 @@ +// A crate named after a built-in type. + +pub struct Test; diff --git a/tests/ui/issues/auxiliary/iss.rs b/tests/ui/issues/auxiliary/iss.rs new file mode 100644 index 000000000..cf32f6c2d --- /dev/null +++ b/tests/ui/issues/auxiliary/iss.rs @@ -0,0 +1,12 @@ +#![crate_name="issue6919_3"] + +// part of issue-6919.rs + +pub struct C where K: FnOnce() { + pub k: K, +} + +fn no_op() { } +pub const D : C = C { + k: no_op as fn() +}; diff --git a/tests/ui/issues/auxiliary/issue-11224.rs b/tests/ui/issues/auxiliary/issue-11224.rs new file mode 100644 index 000000000..63543621a --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-11224.rs @@ -0,0 +1,16 @@ +#![deny(dead_code)] + +mod inner { + pub trait Trait { + fn f(&self) { f(); } + } + + impl Trait for isize {} + + fn f() {} +} + +pub fn foo() { + let a = &1isize as &inner::Trait; + a.f(); +} diff --git a/tests/ui/issues/auxiliary/issue-11508.rs b/tests/ui/issues/auxiliary/issue-11508.rs new file mode 100644 index 000000000..16bfc65c2 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-11508.rs @@ -0,0 +1,10 @@ +pub struct Closed01(pub F); + +pub trait Bar { fn new() -> Self; } + +impl Bar for Closed01 { + fn new() -> Closed01 { Closed01(Bar::new()) } +} +impl Bar for f32 { fn new() -> f32 { 1.0 } } + +pub fn random() -> T { Bar::new() } diff --git a/tests/ui/issues/auxiliary/issue-11529.rs b/tests/ui/issues/auxiliary/issue-11529.rs new file mode 100644 index 000000000..dd3ef4387 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-11529.rs @@ -0,0 +1 @@ +pub struct A<'a>(pub &'a isize); diff --git a/tests/ui/issues/auxiliary/issue-11680.rs b/tests/ui/issues/auxiliary/issue-11680.rs new file mode 100644 index 000000000..74abbf0bf --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-11680.rs @@ -0,0 +1,9 @@ +enum Foo { + Bar(isize) +} + +pub mod test { + enum Foo { + Bar(isize) + } +} diff --git a/tests/ui/issues/auxiliary/issue-12133-dylib.rs b/tests/ui/issues/auxiliary/issue-12133-dylib.rs new file mode 100644 index 000000000..8bd2b3353 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-12133-dylib.rs @@ -0,0 +1 @@ +#![crate_type = "dylib"] diff --git a/tests/ui/issues/auxiliary/issue-12133-dylib2.rs b/tests/ui/issues/auxiliary/issue-12133-dylib2.rs new file mode 100644 index 000000000..30de74006 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-12133-dylib2.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "dylib"] + +extern crate issue_12133_rlib as a; +extern crate issue_12133_dylib as b; diff --git a/tests/ui/issues/auxiliary/issue-12133-rlib.rs b/tests/ui/issues/auxiliary/issue-12133-rlib.rs new file mode 100644 index 000000000..39c261e11 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-12133-rlib.rs @@ -0,0 +1,3 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] diff --git a/tests/ui/issues/auxiliary/issue-12612-1.rs b/tests/ui/issues/auxiliary/issue-12612-1.rs new file mode 100644 index 000000000..01f5a784b --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-12612-1.rs @@ -0,0 +1,3 @@ +pub mod bar { + pub fn foo() {} +} diff --git a/tests/ui/issues/auxiliary/issue-12612-2.rs b/tests/ui/issues/auxiliary/issue-12612-2.rs new file mode 100644 index 000000000..2c7247871 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-12612-2.rs @@ -0,0 +1 @@ +pub fn baz() {} diff --git a/tests/ui/issues/auxiliary/issue-12660-aux.rs b/tests/ui/issues/auxiliary/issue-12660-aux.rs new file mode 100644 index 000000000..6dea8662d --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-12660-aux.rs @@ -0,0 +1,11 @@ +#![crate_type="lib"] +#![crate_name="issue12660aux"] + +pub use my_mod::{MyStruct, my_fn}; + +mod my_mod { + pub struct MyStruct; + + pub fn my_fn(my_struct: MyStruct) { + } +} diff --git a/tests/ui/issues/auxiliary/issue-13507.rs b/tests/ui/issues/auxiliary/issue-13507.rs new file mode 100644 index 000000000..c91013043 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-13507.rs @@ -0,0 +1,87 @@ +pub mod testtypes { + use std::any::TypeId; + + pub fn type_ids() -> Vec { + vec![ + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::() + ] + } + + // Tests Bool + pub type FooBool = bool; + + // Tests Char + pub type FooChar = char; + + // Tests Int (does not test all variants of IntTy) + pub type FooInt = isize; + + // Tests Uint (does not test all variants of UintTy) + pub type FooUint = usize; + + // Tests Float (does not test all variants of FloatTy) + pub type FooFloat = f64; + + // Tests Str + pub type FooStr = str; + + // Tests Array + pub type FooArray = [u8; 1]; + + // Tests Slice + pub type FooSlice = [u8]; + + // Tests Box (of u8) + pub type FooBox = Box; + + // Tests RawPtr + pub type FooPtr = *const u8; + + // Tests Ref + pub type FooRef = &'static u8; + + // Tests FnPtr + pub type FooFnPtr = fn(u8) -> bool; + + // Tests Dynamic + pub trait FooTrait { + fn foo_method(&self) -> usize; + } + + // Tests struct + pub struct FooStruct { + pub pub_foo_field: usize, + foo_field: usize + } + + // Tests enum + pub enum FooEnum { + VarA(usize), + VarB(usize, usize) + } + + // Tests Tuple + pub type FooNil = (); + pub type FooTuple = (u8, i8, bool); + + // Skipping Param + + // Skipping Infer + + // Skipping Error +} diff --git a/tests/ui/issues/auxiliary/issue-13620-1.rs b/tests/ui/issues/auxiliary/issue-13620-1.rs new file mode 100644 index 000000000..a77aa5a71 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-13620-1.rs @@ -0,0 +1,9 @@ +pub struct Foo { + pub foo: extern "C" fn() +} + +extern "C" fn the_foo() {} + +pub const FOO: Foo = Foo { + foo: the_foo +}; diff --git a/tests/ui/issues/auxiliary/issue-13620-2.rs b/tests/ui/issues/auxiliary/issue-13620-2.rs new file mode 100644 index 000000000..7efd24407 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-13620-2.rs @@ -0,0 +1,3 @@ +extern crate issue_13620_1 as crate1; + +pub static FOO2: crate1::Foo = crate1::FOO; diff --git a/tests/ui/issues/auxiliary/issue-13872-1.rs b/tests/ui/issues/auxiliary/issue-13872-1.rs new file mode 100644 index 000000000..fa9258834 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-13872-1.rs @@ -0,0 +1 @@ +pub enum A { B } diff --git a/tests/ui/issues/auxiliary/issue-13872-2.rs b/tests/ui/issues/auxiliary/issue-13872-2.rs new file mode 100644 index 000000000..8c64f16e3 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-13872-2.rs @@ -0,0 +1,3 @@ +extern crate issue_13872_1 as foo; + +pub use foo::A::B; diff --git a/tests/ui/issues/auxiliary/issue-13872-3.rs b/tests/ui/issues/auxiliary/issue-13872-3.rs new file mode 100644 index 000000000..d31d52eb8 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-13872-3.rs @@ -0,0 +1,9 @@ +extern crate issue_13872_2 as bar; + +use bar::B; + +pub fn foo() { + match B { + B => {} + } +} diff --git a/tests/ui/issues/auxiliary/issue-14344-1.rs b/tests/ui/issues/auxiliary/issue-14344-1.rs new file mode 100644 index 000000000..954a1e554 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-14344-1.rs @@ -0,0 +1,5 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/tests/ui/issues/auxiliary/issue-14344-2.rs b/tests/ui/issues/auxiliary/issue-14344-2.rs new file mode 100644 index 000000000..c47b8c0ea --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-14344-2.rs @@ -0,0 +1,3 @@ +extern crate issue_14344_1; + +pub fn bar() {} diff --git a/tests/ui/issues/auxiliary/issue-14421.rs b/tests/ui/issues/auxiliary/issue-14421.rs new file mode 100644 index 000000000..5fe4b24cf --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-14421.rs @@ -0,0 +1,25 @@ +#![crate_type="lib"] +#![deny(warnings)] +#![allow(dead_code)] + +pub use src::aliases::B; +pub use src::hidden_core::make; + +mod src { + pub mod aliases { + use super::hidden_core::A; + pub type B = A; + } + + pub mod hidden_core { + use super::aliases::B; + + pub struct A { t: T } + + pub fn make() -> B { A { t: 1.0 } } + + impl A { + pub fn foo(&mut self) { println!("called foo"); } + } + } +} diff --git a/tests/ui/issues/auxiliary/issue-14422.rs b/tests/ui/issues/auxiliary/issue-14422.rs new file mode 100644 index 000000000..a6026c1d0 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-14422.rs @@ -0,0 +1,25 @@ +#![crate_type="lib"] +#![deny(warnings)] + +pub use src::aliases::B; +pub use src::hidden_core::make; + +mod src { + pub mod aliases { + use super::hidden_core::A; + pub type B = A; + } + + pub mod hidden_core { + use super::aliases::B; + + #[derive(Copy, Clone)] + pub struct A; + + pub fn make() -> B { A } + + impl A { + pub fn foo(&mut self) { println!("called foo"); } + } + } +} diff --git a/tests/ui/issues/auxiliary/issue-15562.rs b/tests/ui/issues/auxiliary/issue-15562.rs new file mode 100644 index 000000000..6ff26b47e --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-15562.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] + +extern "C" { + pub fn transmute(); +} diff --git a/tests/ui/issues/auxiliary/issue-16643.rs b/tests/ui/issues/auxiliary/issue-16643.rs new file mode 100644 index 000000000..7808e0119 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-16643.rs @@ -0,0 +1,19 @@ +#![crate_type = "lib"] + +pub struct TreeBuilder { pub h: H } + +impl TreeBuilder { + pub fn process_token(&mut self) { + match self { + _ => for _y in self.by_ref() {} + } + } +} + +impl Iterator for TreeBuilder { + type Item = H; + + fn next(&mut self) -> Option { + None + } +} diff --git a/tests/ui/issues/auxiliary/issue-16725.rs b/tests/ui/issues/auxiliary/issue-16725.rs new file mode 100644 index 000000000..9f9abd575 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-16725.rs @@ -0,0 +1,3 @@ +extern "C" { + fn bar(); +} diff --git a/tests/ui/issues/auxiliary/issue-17662.rs b/tests/ui/issues/auxiliary/issue-17662.rs new file mode 100644 index 000000000..75efe110c --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-17662.rs @@ -0,0 +1,12 @@ +#![crate_type = "lib"] + +pub trait Foo<'a, T> { + fn foo(&'a self) -> T; +} + +pub fn foo<'a, T>(x: &'a Foo<'a, T>) -> T { + let x: &'a Foo = x; + // ^ the lifetime parameter of Foo is left to be inferred. + x.foo() + // ^ encoding this method call in metadata triggers an ICE. +} diff --git a/tests/ui/issues/auxiliary/issue-18501.rs b/tests/ui/issues/auxiliary/issue-18501.rs new file mode 100644 index 000000000..dd914b464 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-18501.rs @@ -0,0 +1,17 @@ +#![crate_type = "rlib"] +struct Foo; + +trait Tr { + fn tr(&self); +} + +impl Tr for Foo { + fn tr(&self) {} +} + +fn take_method(f: fn(&T), t: &T) {} + +#[inline] +pub fn pass_method() { + take_method(Tr::tr, &Foo); +} diff --git a/tests/ui/issues/auxiliary/issue-18514.rs b/tests/ui/issues/auxiliary/issue-18514.rs new file mode 100644 index 000000000..20c8e60ee --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-18514.rs @@ -0,0 +1,17 @@ +#![crate_type = "rlib"] + +pub trait Tr { + fn tr(&self); +} + +pub struct St(pub Vec); + +impl Tr for St { + fn tr(&self) { + match self { + &St(ref v) => { + v.iter(); + } + } + } +} diff --git a/tests/ui/issues/auxiliary/issue-18711.rs b/tests/ui/issues/auxiliary/issue-18711.rs new file mode 100644 index 000000000..5cb1f9c43 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-18711.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] + +pub fn inner(f: F) -> F { + (move || f)() +} diff --git a/tests/ui/issues/auxiliary/issue-18913-1.rs b/tests/ui/issues/auxiliary/issue-18913-1.rs new file mode 100644 index 000000000..053c5ada5 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-18913-1.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![crate_name = "foo"] + +pub fn foo() -> i32 { 0 } diff --git a/tests/ui/issues/auxiliary/issue-18913-2.rs b/tests/ui/issues/auxiliary/issue-18913-2.rs new file mode 100644 index 000000000..54747b45f --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-18913-2.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![crate_name = "foo"] + +pub fn foo() -> i32 { 1 } diff --git a/tests/ui/issues/auxiliary/issue-1920.rs b/tests/ui/issues/auxiliary/issue-1920.rs new file mode 100644 index 000000000..1548cb995 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-1920.rs @@ -0,0 +1,4 @@ +// Just exporting some type to test for correct diagnostics when this +// crate is pulled in at a non-root location in client crate. + +pub struct S; diff --git a/tests/ui/issues/auxiliary/issue-19293.rs b/tests/ui/issues/auxiliary/issue-19293.rs new file mode 100644 index 000000000..31359e865 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-19293.rs @@ -0,0 +1,4 @@ +pub struct Foo (pub isize); +pub enum MyEnum { + Foo(Foo), +} diff --git a/tests/ui/issues/auxiliary/issue-19340-1.rs b/tests/ui/issues/auxiliary/issue-19340-1.rs new file mode 100644 index 000000000..39ee36b8b --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-19340-1.rs @@ -0,0 +1,3 @@ +pub enum Homura { + Madoka { name: String }, +} diff --git a/tests/ui/issues/auxiliary/issue-20389.rs b/tests/ui/issues/auxiliary/issue-20389.rs new file mode 100644 index 000000000..ae6d44eeb --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-20389.rs @@ -0,0 +1,4 @@ +pub trait T { + type C; + fn dummy(&self) { } +} diff --git a/tests/ui/issues/auxiliary/issue-21202.rs b/tests/ui/issues/auxiliary/issue-21202.rs new file mode 100644 index 000000000..e3daa1ba0 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-21202.rs @@ -0,0 +1,6 @@ +pub mod A { + pub struct Foo; + impl Foo { + fn foo(&self) { } + } +} diff --git a/tests/ui/issues/auxiliary/issue-2170-lib.rs b/tests/ui/issues/auxiliary/issue-2170-lib.rs new file mode 100644 index 000000000..a99385a83 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2170-lib.rs @@ -0,0 +1,18 @@ +fn foo(_x: i32) { +} + +pub struct rsrc { + x: i32, +} + +impl Drop for rsrc { + fn drop(&mut self) { + foo(self.x); + } +} + +pub fn rsrc(x: i32) -> rsrc { + rsrc { + x: x + } +} diff --git a/tests/ui/issues/auxiliary/issue-2316-a.rs b/tests/ui/issues/auxiliary/issue-2316-a.rs new file mode 100644 index 000000000..418ddc0b0 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2316-a.rs @@ -0,0 +1,3 @@ +enum cat { + tabby, calico, tortoiseshell +} diff --git a/tests/ui/issues/auxiliary/issue-2316-b.rs b/tests/ui/issues/auxiliary/issue-2316-b.rs new file mode 100644 index 000000000..550c2d6eb --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2316-b.rs @@ -0,0 +1,11 @@ +#![allow(unused_imports)] + +extern crate issue_2316_a; + +pub mod cloth { + use issue_2316_a::*; + + pub enum fabric { + gingham, flannel, calico + } +} diff --git a/tests/ui/issues/auxiliary/issue-2380.rs b/tests/ui/issues/auxiliary/issue-2380.rs new file mode 100644 index 000000000..79fd62d16 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2380.rs @@ -0,0 +1,13 @@ +#![crate_name="a"] +#![crate_type = "lib"] + +pub trait i +{ + fn dummy(&self, t: T) -> T { panic!() } +} + +pub fn f() -> Box+'static> { + impl i for () { } + + Box::new(()) as Box+'static> +} diff --git a/tests/ui/issues/auxiliary/issue-2414-a.rs b/tests/ui/issues/auxiliary/issue-2414-a.rs new file mode 100644 index 000000000..b90ab32dd --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2414-a.rs @@ -0,0 +1,12 @@ +#![crate_name="a"] +#![crate_type = "lib"] + +type t1 = usize; + +trait foo { + fn foo(&self); +} + +impl foo for String { + fn foo(&self) {} +} diff --git a/tests/ui/issues/auxiliary/issue-2414-b.rs b/tests/ui/issues/auxiliary/issue-2414-b.rs new file mode 100644 index 000000000..fc018349d --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2414-b.rs @@ -0,0 +1,4 @@ +#![crate_name="b"] +#![crate_type = "lib"] + +extern crate a; diff --git a/tests/ui/issues/auxiliary/issue-2472-b.rs b/tests/ui/issues/auxiliary/issue-2472-b.rs new file mode 100644 index 000000000..0d151520f --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2472-b.rs @@ -0,0 +1,13 @@ +pub struct S(pub ()); + +impl S { + pub fn foo(&self) { } +} + +pub trait T { + fn bar(&self); +} + +impl T for S { + fn bar(&self) { } +} diff --git a/tests/ui/issues/auxiliary/issue-25185-1.rs b/tests/ui/issues/auxiliary/issue-25185-1.rs new file mode 100644 index 000000000..e957be9c1 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-25185-1.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + pub fn rust_dbg_extern_identity_u32(u: u32) -> u32; +} diff --git a/tests/ui/issues/auxiliary/issue-25185-2.rs b/tests/ui/issues/auxiliary/issue-25185-2.rs new file mode 100644 index 000000000..7ce3df255 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-25185-2.rs @@ -0,0 +1,3 @@ +extern crate issue_25185_1; + +pub use issue_25185_1::rust_dbg_extern_identity_u32; diff --git a/tests/ui/issues/auxiliary/issue-2526.rs b/tests/ui/issues/auxiliary/issue-2526.rs new file mode 100644 index 000000000..3b27f658c --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2526.rs @@ -0,0 +1,44 @@ +#![crate_name="issue_2526"] +#![crate_type = "lib"] + +use std::marker; + +pub struct arc_destruct { + _data: isize, + _marker: marker::PhantomData +} + +impl Drop for arc_destruct { + fn drop(&mut self) {} +} + +fn arc_destruct(data: isize) -> arc_destruct { + arc_destruct { + _data: data, + _marker: marker::PhantomData + } +} + +fn arc(_data: T) -> arc_destruct { + arc_destruct(0) +} + +fn init() -> arc_destruct { + arc(context_res()) +} + +pub struct context_res { + ctx : isize, +} + +impl Drop for context_res { + fn drop(&mut self) {} +} + +fn context_res() -> context_res { + context_res { + ctx: 0 + } +} + +pub type context = arc_destruct; diff --git a/tests/ui/issues/auxiliary/issue-25467.rs b/tests/ui/issues/auxiliary/issue-25467.rs new file mode 100644 index 000000000..ca9b3097c --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-25467.rs @@ -0,0 +1,10 @@ +#![crate_type="lib"] + +pub trait Trait { + // the issue is sensitive to interning order - so use names + // unlikely to appear in libstd. + type Issue25467FooT; + type Issue25467BarT; +} + +pub type Object = Option>>; diff --git a/tests/ui/issues/auxiliary/issue-2631-a.rs b/tests/ui/issues/auxiliary/issue-2631-a.rs new file mode 100644 index 000000000..1e8211bfa --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2631-a.rs @@ -0,0 +1,14 @@ +#![crate_name="req"] +#![crate_type = "lib"] + +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + +pub type header_map = HashMap>>>>; + +// the unused ty param is necessary so this gets monomorphized +pub fn request(req: &header_map) { + let data = req[&"METHOD".to_string()].clone(); + let _x = data.borrow().clone()[0].clone(); +} diff --git a/tests/ui/issues/auxiliary/issue-2723-a.rs b/tests/ui/issues/auxiliary/issue-2723-a.rs new file mode 100644 index 000000000..661b46d82 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-2723-a.rs @@ -0,0 +1,3 @@ +pub unsafe fn f(xs: Vec ) { + xs.iter().map(|_x| { unsafe fn q() { panic!(); } }).collect::>(); +} diff --git a/tests/ui/issues/auxiliary/issue-29181.rs b/tests/ui/issues/auxiliary/issue-29181.rs new file mode 100644 index 000000000..bd1a9be4e --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-29181.rs @@ -0,0 +1,5 @@ +#![crate_type="lib"] + +pub mod foo { + pub use super::*; +} diff --git a/tests/ui/issues/auxiliary/issue-29265.rs b/tests/ui/issues/auxiliary/issue-29265.rs new file mode 100644 index 000000000..6d26002a2 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-29265.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] + +pub struct SomeType { + pub some_member: usize, +} + +pub static SOME_VALUE: SomeType = SomeType { + some_member: 1, +}; diff --git a/tests/ui/issues/auxiliary/issue-29485.rs b/tests/ui/issues/auxiliary/issue-29485.rs new file mode 100644 index 000000000..1e8891c51 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-29485.rs @@ -0,0 +1,16 @@ +#![crate_name="a"] +#![crate_type = "lib"] + +pub struct X(pub u8); + +impl Drop for X { + fn drop(&mut self) { + assert_eq!(self.0, 1) + } +} + +pub fn f(x: &mut X, g: fn()) { + x.0 = 1; + g(); + x.0 = 0; +} diff --git a/tests/ui/issues/auxiliary/issue-3012-1.rs b/tests/ui/issues/auxiliary/issue-3012-1.rs new file mode 100644 index 000000000..509af2a8d --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-3012-1.rs @@ -0,0 +1,20 @@ +#![crate_name="socketlib"] +#![crate_type = "lib"] + +pub mod socket { + pub struct socket_handle { + sockfd: u32, + } + + impl Drop for socket_handle { + fn drop(&mut self) { + /* c::close(self.sockfd); */ + } + } + + pub fn socket_handle(x: u32) -> socket_handle { + socket_handle { + sockfd: x + } + } +} diff --git a/tests/ui/issues/auxiliary/issue-30123-aux.rs b/tests/ui/issues/auxiliary/issue-30123-aux.rs new file mode 100644 index 000000000..07c743eb2 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-30123-aux.rs @@ -0,0 +1,23 @@ +use std::marker::PhantomData; + +pub struct Directed; +pub struct Undirected; + +pub struct Graph { + nodes: Vec>, + edges: Vec>, + ty: PhantomData, +} + + +impl Graph { + pub fn new() -> Self { + Graph{nodes: Vec::new(), edges: Vec::new(), ty: PhantomData} + } +} + +impl Graph { + pub fn new_undirected() -> Self { + Graph{nodes: Vec::new(), edges: Vec::new(), ty: PhantomData} + } +} diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rc b/tests/ui/issues/auxiliary/issue-3136-a.rc new file mode 100644 index 000000000..cd5fd3145 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-3136-a.rc @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +#[path = "issue-3136-a.rs"] +pub mod issue_3136_a; diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rs b/tests/ui/issues/auxiliary/issue-3136-a.rs new file mode 100644 index 000000000..9bb546ab3 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-3136-a.rs @@ -0,0 +1,14 @@ +trait x { + fn use_x(&self); +} +struct y(()); +impl x for y { + fn use_x(&self) { + struct foo { //~ ERROR quux + i: () + } + fn new_foo(i: ()) -> foo { + foo { i: i } + } + } +} diff --git a/tests/ui/issues/auxiliary/issue-31702-1.rs b/tests/ui/issues/auxiliary/issue-31702-1.rs new file mode 100644 index 000000000..a48d0dc2c --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-31702-1.rs @@ -0,0 +1,16 @@ +#[derive(Copy)] +pub struct U256(pub [u64; 4]); + +impl Clone for U256 { + fn clone(&self) -> U256 { + *self + } +} + +impl U256 { + pub fn new(value: u64) -> U256 { + let mut ret = [0; 4]; + ret[0] = value; + U256(ret) + } +} diff --git a/tests/ui/issues/auxiliary/issue-31702-2.rs b/tests/ui/issues/auxiliary/issue-31702-2.rs new file mode 100644 index 000000000..d360ae0ca --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-31702-2.rs @@ -0,0 +1,20 @@ +// compile-flags: -g + +extern crate issue_31702_1; + +use std::collections::HashMap; +use issue_31702_1::U256; + +pub struct Ethash { + engine_params: fn() -> Option<&'static Vec>, + u256_params: HashMap, +} + +impl Ethash { + pub fn u256_param(&mut self, name: &str) -> U256 { + let engine = self.engine_params; + *self.u256_params.entry(name.to_owned()).or_insert_with(|| { + engine().map_or(U256::new(0u64), |_a| loop {}) + }) + } +} diff --git a/tests/ui/issues/auxiliary/issue-34796-aux.rs b/tests/ui/issues/auxiliary/issue-34796-aux.rs new file mode 100644 index 000000000..09c69b903 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-34796-aux.rs @@ -0,0 +1,20 @@ +#![crate_type = "lib"] +pub trait Future { + type Item; + type Error; +} + +impl Future for u32 { + type Item = (); + type Error = Box<()>; +} + +fn foo() -> Box>> { + Box::new(0u32) +} + +pub fn bar(_s: F) + where F: Fn(A) -> B, +{ + foo(); +} diff --git a/tests/ui/issues/auxiliary/issue-36954.rs b/tests/ui/issues/auxiliary/issue-36954.rs new file mode 100644 index 000000000..bc444a381 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-36954.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] + +const fn foo(i: i32) -> i32 { + i +} + +pub const FOO: i32 = foo(1); diff --git a/tests/ui/issues/auxiliary/issue-38190.rs b/tests/ui/issues/auxiliary/issue-38190.rs new file mode 100644 index 000000000..373e646ba --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-38190.rs @@ -0,0 +1,2 @@ +#[macro_export] +macro_rules! m { ([$i:item]) => {} } diff --git a/tests/ui/issues/auxiliary/issue-38226-aux.rs b/tests/ui/issues/auxiliary/issue-38226-aux.rs new file mode 100644 index 000000000..f96801719 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-38226-aux.rs @@ -0,0 +1,23 @@ +#![crate_type="rlib"] + +#[inline(never)] +pub fn foo() { + let _: Box = Box::new(SomeTraitImpl); +} + +pub fn bar() { + SomeTraitImpl.bar(); +} + +mod submod { + pub trait SomeTrait { + fn bar(&self) { + panic!("NO") + } + } +} + +use self::submod::SomeTrait; + +pub struct SomeTraitImpl; +impl SomeTrait for SomeTraitImpl {} diff --git a/tests/ui/issues/auxiliary/issue-3979-traits.rs b/tests/ui/issues/auxiliary/issue-3979-traits.rs new file mode 100644 index 000000000..5d03a0e9e --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-3979-traits.rs @@ -0,0 +1,15 @@ +#![crate_name="issue_3979_traits"] + +#![crate_type = "lib"] + +pub trait Positioned { + fn SetX(&mut self, _: isize); + fn X(&self) -> isize; +} + +pub trait Movable: Positioned { + fn translate(&mut self, dx: isize) { + let x = self.X() + dx; + self.SetX(x); + } +} diff --git a/tests/ui/issues/auxiliary/issue-41053.rs b/tests/ui/issues/auxiliary/issue-41053.rs new file mode 100644 index 000000000..ae73c3e78 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-41053.rs @@ -0,0 +1 @@ +pub struct Test; diff --git a/tests/ui/issues/auxiliary/issue-41394.rs b/tests/ui/issues/auxiliary/issue-41394.rs new file mode 100644 index 000000000..2e650efc7 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-41394.rs @@ -0,0 +1,16 @@ +#![crate_type = "lib"] + +#[repr(u32)] +pub enum Foo { + Foo = Private::Variant as u32 +} + +#[repr(u8)] +enum Private { + Variant = 42 +} + +#[inline(always)] +pub fn foo() -> Foo { + Foo::Foo +} diff --git a/tests/ui/issues/auxiliary/issue-41549.rs b/tests/ui/issues/auxiliary/issue-41549.rs new file mode 100644 index 000000000..b7bd37525 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-41549.rs @@ -0,0 +1,3 @@ +pub trait Trait { + const CONST: u32; +} diff --git a/tests/ui/issues/auxiliary/issue-42007-s.rs b/tests/ui/issues/auxiliary/issue-42007-s.rs new file mode 100644 index 000000000..95119a589 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-42007-s.rs @@ -0,0 +1,4 @@ +#[repr(u8)] +pub enum E { + B = 1 as u8, +} diff --git a/tests/ui/issues/auxiliary/issue-4208-cc.rs b/tests/ui/issues/auxiliary/issue-4208-cc.rs new file mode 100644 index 000000000..7b4c8b01a --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-4208-cc.rs @@ -0,0 +1,10 @@ +#![crate_name="numeric"] +#![crate_type = "lib"] + +pub trait Trig { + fn sin(&self) -> T; +} + +pub fn sin, R>(theta: &T) -> R { theta.sin() } + +pub trait Angle: Trig {} diff --git a/tests/ui/issues/auxiliary/issue-4545.rs b/tests/ui/issues/auxiliary/issue-4545.rs new file mode 100644 index 000000000..2f6094750 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-4545.rs @@ -0,0 +1,2 @@ +pub struct S(Option); +pub fn mk() -> S { S(None) } diff --git a/tests/ui/issues/auxiliary/issue-48984-aux.rs b/tests/ui/issues/auxiliary/issue-48984-aux.rs new file mode 100644 index 000000000..7cc888cd4 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-48984-aux.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] +#![crate_name = "issue48984aux"] + +pub trait Foo { type Item; } + +pub trait Bar: Foo { } diff --git a/tests/ui/issues/auxiliary/issue-49544.rs b/tests/ui/issues/auxiliary/issue-49544.rs new file mode 100644 index 000000000..f8b3a3fba --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-49544.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] + +pub fn foo() -> Vec { + std::env::args() + .skip(1) + .collect() +} diff --git a/tests/ui/issues/auxiliary/issue-51798.rs b/tests/ui/issues/auxiliary/issue-51798.rs new file mode 100644 index 000000000..fef5213db --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-51798.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +pub fn vec() -> Vec { vec![] } diff --git a/tests/ui/issues/auxiliary/issue-52489.rs b/tests/ui/issues/auxiliary/issue-52489.rs new file mode 100644 index 000000000..f53bf7db5 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-52489.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] +#![unstable(feature = "issue_52489_unstable", issue = "none")] +#![feature(staged_api)] diff --git a/tests/ui/issues/auxiliary/issue-5518.rs b/tests/ui/issues/auxiliary/issue-5518.rs new file mode 100644 index 000000000..bfe96552a --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-5518.rs @@ -0,0 +1,4 @@ +trait A<'a, T> { + fn f(&mut self) -> &'a mut T; + fn p() -> T; +} diff --git a/tests/ui/issues/auxiliary/issue-5521.rs b/tests/ui/issues/auxiliary/issue-5521.rs new file mode 100644 index 000000000..c2f81779b --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-5521.rs @@ -0,0 +1,3 @@ +use std::collections::HashMap; + +pub type map = Box>; diff --git a/tests/ui/issues/auxiliary/issue-56943.rs b/tests/ui/issues/auxiliary/issue-56943.rs new file mode 100644 index 000000000..65b9beb91 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-56943.rs @@ -0,0 +1,3 @@ +pub struct S; +mod m { pub struct S; } +pub use crate::m::S as S2; diff --git a/tests/ui/issues/auxiliary/issue-57271-lib.rs b/tests/ui/issues/auxiliary/issue-57271-lib.rs new file mode 100644 index 000000000..ff625668a --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-57271-lib.rs @@ -0,0 +1,11 @@ +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum BaseType { + Byte, + Char, + Double, + Float, + Int, + Long, + Short, + Boolean, +} diff --git a/tests/ui/issues/auxiliary/issue-5844-aux.rs b/tests/ui/issues/auxiliary/issue-5844-aux.rs new file mode 100644 index 000000000..ea83378ca --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-5844-aux.rs @@ -0,0 +1,3 @@ +extern "C" { + pub fn rand() -> u32; +} diff --git a/tests/ui/issues/auxiliary/issue-7178.rs b/tests/ui/issues/auxiliary/issue-7178.rs new file mode 100644 index 000000000..56ae5139a --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-7178.rs @@ -0,0 +1,7 @@ +pub struct Foo<'a, A:'a>(&'a A); + +impl<'a, A> Foo<'a, A> { + pub fn new(a: &'a A) -> Foo<'a, A> { + Foo(a) + } +} diff --git a/tests/ui/issues/auxiliary/issue-73112.rs b/tests/ui/issues/auxiliary/issue-73112.rs new file mode 100644 index 000000000..6210c29bb --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-73112.rs @@ -0,0 +1,10 @@ +#[repr(transparent)] +pub struct PageTableEntry { + entry: u64, +} + +#[repr(align(4096))] +#[repr(C)] +pub struct PageTable { + entries: [PageTableEntry; 512], +} diff --git a/tests/ui/issues/auxiliary/issue-7899.rs b/tests/ui/issues/auxiliary/issue-7899.rs new file mode 100644 index 000000000..3af6e8716 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-7899.rs @@ -0,0 +1 @@ +pub struct V2(pub T, pub T); diff --git a/tests/ui/issues/auxiliary/issue-8044.rs b/tests/ui/issues/auxiliary/issue-8044.rs new file mode 100644 index 000000000..2ec25f51c --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-8044.rs @@ -0,0 +1,15 @@ +pub struct BTree { + pub node: TreeItem, +} + +pub enum TreeItem { + TreeLeaf { value: V }, +} + +pub fn leaf(value: V) -> TreeItem { + TreeItem::TreeLeaf { value: value } +} + +fn main() { + BTree:: { node: leaf(1) }; +} diff --git a/tests/ui/issues/auxiliary/issue-8259.rs b/tests/ui/issues/auxiliary/issue-8259.rs new file mode 100644 index 000000000..891aee099 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-8259.rs @@ -0,0 +1,4 @@ +pub enum Foo<'a> { + A, + B(&'a str), +} diff --git a/tests/ui/issues/auxiliary/issue-8401.rs b/tests/ui/issues/auxiliary/issue-8401.rs new file mode 100644 index 000000000..e35dbbfab --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-8401.rs @@ -0,0 +1,16 @@ +// for this issue, this code must be built in a library + +use std::mem; + +trait A { + fn dummy(&self) { } +} +struct B; +impl A for B {} + +fn bar(_: &mut A, _: &T) {} + +fn foo(t: &T) { + let mut b = B; + bar(&mut b as &mut A, t) +} diff --git a/tests/ui/issues/auxiliary/issue-9123.rs b/tests/ui/issues/auxiliary/issue-9123.rs new file mode 100644 index 000000000..60af53359 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-9123.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] + +pub trait X { + fn x() { + fn f() { } + f(); + } + fn dummy(&self) { } +} diff --git a/tests/ui/issues/auxiliary/issue-9155.rs b/tests/ui/issues/auxiliary/issue-9155.rs new file mode 100644 index 000000000..049a96a65 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-9155.rs @@ -0,0 +1,7 @@ +pub struct Foo(T); + +impl Foo { + pub fn new(t: T) -> Foo { + Foo(t) + } +} diff --git a/tests/ui/issues/auxiliary/issue-9188.rs b/tests/ui/issues/auxiliary/issue-9188.rs new file mode 100644 index 000000000..3bc5697a1 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-9188.rs @@ -0,0 +1,13 @@ +pub fn foo() -> &'static isize { + if false { + static a: isize = 4; + return &a; + } else { + static a: isize = 5; + return &a; + } +} + +pub fn bar() -> &'static isize { + foo::() +} diff --git a/tests/ui/issues/auxiliary/issue-9906.rs b/tests/ui/issues/auxiliary/issue-9906.rs new file mode 100644 index 000000000..8a3eea790 --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-9906.rs @@ -0,0 +1,15 @@ +pub use other::FooBar; +pub use other::foo; + +mod other { + pub struct FooBar{value: isize} + impl FooBar{ + pub fn new(val: isize) -> FooBar { + FooBar{value: val} + } + } + + pub fn foo(){ + 1+1; + } +} diff --git a/tests/ui/issues/auxiliary/issue-9968.rs b/tests/ui/issues/auxiliary/issue-9968.rs new file mode 100644 index 000000000..8d795b59e --- /dev/null +++ b/tests/ui/issues/auxiliary/issue-9968.rs @@ -0,0 +1,22 @@ +pub use internal::core::{Trait, Struct}; + +mod internal { + pub mod core { + pub struct Struct; + impl Struct { + pub fn init() -> Struct { + Struct + } + } + + pub trait Trait { + fn test(&self) { + private(); + } + } + + impl Trait for Struct {} + + fn private() { } + } +} diff --git a/tests/ui/issues/auxiliary/private-trait-xc.rs b/tests/ui/issues/auxiliary/private-trait-xc.rs new file mode 100644 index 000000000..481a48a7c --- /dev/null +++ b/tests/ui/issues/auxiliary/private-trait-xc.rs @@ -0,0 +1 @@ +trait Foo {} diff --git a/tests/ui/issues/auxiliary/reexported-trait.rs b/tests/ui/issues/auxiliary/reexported-trait.rs new file mode 100644 index 000000000..51a991bef --- /dev/null +++ b/tests/ui/issues/auxiliary/reexported-trait.rs @@ -0,0 +1,17 @@ +mod private { + pub trait Trait { + fn trait_method(&self) { + } + } + pub trait TraitB { + fn trait_method_b(&self) { + } + } +} + +pub struct FooStruct; +pub use crate::private::Trait; +impl crate::private::Trait for FooStruct {} + +pub use crate::private::TraitB as TraitBRename; +impl crate::private::TraitB for FooStruct {} diff --git a/tests/ui/issues/issue-100605.rs b/tests/ui/issues/issue-100605.rs new file mode 100644 index 000000000..917a45c15 --- /dev/null +++ b/tests/ui/issues/issue-100605.rs @@ -0,0 +1,9 @@ +fn takes_option(_arg: Option<&String>) {} + +fn main() { + takes_option(&None); //~ ERROR 4:18: 4:23: mismatched types [E0308] + + let x = String::from("x"); + let res = Some(x); + takes_option(&res); //~ ERROR 8:18: 8:22: mismatched types [E0308] +} diff --git a/tests/ui/issues/issue-100605.stderr b/tests/ui/issues/issue-100605.stderr new file mode 100644 index 000000000..886e3cd6b --- /dev/null +++ b/tests/ui/issues/issue-100605.stderr @@ -0,0 +1,46 @@ +error[E0308]: mismatched types + --> $DIR/issue-100605.rs:4:18 + | +LL | takes_option(&None); + | ------------ ^^^^^ expected enum `Option`, found `&Option<_>` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&String>` + found reference `&Option<_>` +note: function defined here + --> $DIR/issue-100605.rs:1:4 + | +LL | fn takes_option(_arg: Option<&String>) {} + | ^^^^^^^^^^^^ --------------------- +help: you can convert from `&Option` to `Option<&T>` using `.as_ref()` + | +LL | takes_option(None.as_ref()); + | ~~~~~~~~~~~~~ +help: consider removing the borrow + | +LL - takes_option(&None); +LL + takes_option(None); + | + +error[E0308]: mismatched types + --> $DIR/issue-100605.rs:8:18 + | +LL | takes_option(&res); + | ------------ ^^^^ + | | | + | | expected enum `Option`, found `&Option` + | | help: you can convert from `&Option` to `Option<&T>` using `.as_ref()`: `res.as_ref()` + | arguments to this function are incorrect + | + = note: expected enum `Option<&String>` + found reference `&Option` +note: function defined here + --> $DIR/issue-100605.rs:1:4 + | +LL | fn takes_option(_arg: Option<&String>) {} + | ^^^^^^^^^^^^ --------------------- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-10228.rs b/tests/ui/issues/issue-10228.rs new file mode 100644 index 000000000..ebf8b436f --- /dev/null +++ b/tests/ui/issues/issue-10228.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +enum StdioContainer { + CreatePipe(bool) +} + +struct Test<'a> { + args: &'a [String], + io: &'a [StdioContainer] +} + +pub fn main() { + let test = Test { + args: &[], + io: &[StdioContainer::CreatePipe(true)] + }; +} diff --git a/tests/ui/issues/issue-10291.rs b/tests/ui/issues/issue-10291.rs new file mode 100644 index 000000000..31b9e1240 --- /dev/null +++ b/tests/ui/issues/issue-10291.rs @@ -0,0 +1,8 @@ +fn test<'x>(x: &'x isize) { + drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { + x + //~^ ERROR lifetime may not live long enough + })); +} + +fn main() {} diff --git a/tests/ui/issues/issue-10291.stderr b/tests/ui/issues/issue-10291.stderr new file mode 100644 index 000000000..a7b827d27 --- /dev/null +++ b/tests/ui/issues/issue-10291.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-10291.rs:3:9 + | +LL | fn test<'x>(x: &'x isize) { + | -- lifetime `'x` defined here +LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { +LL | x + | ^ returning this value requires that `'x` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-102964.rs b/tests/ui/issues/issue-102964.rs new file mode 100644 index 000000000..43ff23600 --- /dev/null +++ b/tests/ui/issues/issue-102964.rs @@ -0,0 +1,10 @@ +use std::rc::Rc; +type Foo<'a, T> = &'a dyn Fn(&T); +type RcFoo<'a, T> = Rc>; + +fn bar_function(function: Foo) -> RcFoo { + //~^ ERROR mismatched types + let rc = Rc::new(function); +} + +fn main() {} diff --git a/tests/ui/issues/issue-102964.stderr b/tests/ui/issues/issue-102964.stderr new file mode 100644 index 000000000..450403909 --- /dev/null +++ b/tests/ui/issues/issue-102964.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-102964.rs:5:41 + | +LL | fn bar_function(function: Foo) -> RcFoo { + | ------------ ^^^^^^^^ expected struct `Rc`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Rc<&dyn for<'a> Fn(&'a T)>` + found unit type `()` +help: consider returning the local binding `rc` + | +LL ~ let rc = Rc::new(function); +LL + rc + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-10396.rs b/tests/ui/issues/issue-10396.rs new file mode 100644 index 000000000..d16ea3dc3 --- /dev/null +++ b/tests/ui/issues/issue-10396.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +#[derive(Debug)] +enum Foo<'s> { + V(&'s str) +} + +fn f(arr: &[&Foo]) { + for &f in arr { + println!("{:?}", f); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-10412.rs b/tests/ui/issues/issue-10412.rs new file mode 100644 index 000000000..0de170161 --- /dev/null +++ b/tests/ui/issues/issue-10412.rs @@ -0,0 +1,27 @@ +trait Serializable<'self, T> { + //~^ ERROR lifetimes cannot use keyword names + fn serialize(val: &'self T) -> Vec; //~ ERROR lifetimes cannot use keyword names + fn deserialize(repr: &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names +} + +impl<'self> Serializable for &'self str { + //~^ ERROR lifetimes cannot use keyword names + //~| ERROR lifetimes cannot use keyword names + //~| ERROR implicit elided lifetime not allowed here + //~| ERROR the size for values of type `str` cannot be known at compilation time [E0277] + fn serialize(val: &'self str) -> Vec { + //~^ ERROR lifetimes cannot use keyword names + vec![1] + } + fn deserialize(repr: &[u8]) -> &'self str { + //~^ ERROR lifetimes cannot use keyword names + "hi" + } +} + +fn main() { + println!("hello"); + let x = "foo".to_string(); + let y = x; + println!("{}", y); +} diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr new file mode 100644 index 000000000..46b9fd541 --- /dev/null +++ b/tests/ui/issues/issue-10412.stderr @@ -0,0 +1,75 @@ +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:1:20 + | +LL | trait Serializable<'self, T> { + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:3:24 + | +LL | fn serialize(val: &'self T) -> Vec; + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:4:37 + | +LL | fn deserialize(repr: &[u8]) -> &'self T; + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:7:6 + | +LL | impl<'self> Serializable for &'self str { + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:7:36 + | +LL | impl<'self> Serializable for &'self str { + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:12:24 + | +LL | fn serialize(val: &'self str) -> Vec { + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/issue-10412.rs:16:37 + | +LL | fn deserialize(repr: &[u8]) -> &'self str { + | ^^^^^ + +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/issue-10412.rs:7:13 + | +LL | impl<'self> Serializable for &'self str { + | ^^^^^^^^^^^^^^^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +LL | impl<'self> Serializable<'_, str> for &'self str { + | +++ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-10412.rs:7:13 + | +LL | impl<'self> Serializable for &'self str { + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `Serializable` + --> $DIR/issue-10412.rs:1:27 + | +LL | trait Serializable<'self, T> { + | ^ required by this bound in `Serializable` +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Serializable<'self, T: ?Sized> { + | ++++++++ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0277, E0726. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-10436.rs b/tests/ui/issues/issue-10436.rs new file mode 100644 index 000000000..a7a20bad5 --- /dev/null +++ b/tests/ui/issues/issue-10436.rs @@ -0,0 +1,11 @@ +// run-pass +fn works(x: T) -> Vec { vec![x] } + +fn also_works(x: T) -> Vec { vec![x] } + +fn main() { + let _: Vec = works(0); + let _: Vec = also_works(0); + let _ = works(0); + let _ = also_works(0); +} diff --git a/tests/ui/issues/issue-10456.rs b/tests/ui/issues/issue-10456.rs new file mode 100644 index 000000000..9f8d25955 --- /dev/null +++ b/tests/ui/issues/issue-10456.rs @@ -0,0 +1,25 @@ +// check-pass +// pretty-expanded FIXME #23616 + +pub struct Foo; + +pub trait Bar { + fn bar(&self); +} + +pub trait Baz { + fn baz(&self) { } +} + +impl Bar for T { + fn bar(&self) {} +} + +impl Baz for Foo {} + +pub fn foo(t: Box) { + t.bar(); // ~Foo doesn't implement Baz + (*t).bar(); // ok b/c Foo implements Baz +} + +fn main() {} diff --git a/tests/ui/issues/issue-10465.rs b/tests/ui/issues/issue-10465.rs new file mode 100644 index 000000000..d899c3ffa --- /dev/null +++ b/tests/ui/issues/issue-10465.rs @@ -0,0 +1,23 @@ +pub mod a { + pub trait A { + fn foo(&self); + } + +} +pub mod b { + use a::A; + + pub struct B; + impl A for B { fn foo(&self) {} } + + pub mod c { + use b::B; + + fn foo(b: &B) { + b.foo(); //~ ERROR: no method named `foo` found + } + } + +} + +fn main() {} diff --git a/tests/ui/issues/issue-10465.stderr b/tests/ui/issues/issue-10465.stderr new file mode 100644 index 000000000..0ccf69dc0 --- /dev/null +++ b/tests/ui/issues/issue-10465.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `foo` found for reference `&B` in the current scope + --> $DIR/issue-10465.rs:17:15 + | +LL | b.foo(); + | ^^^ method not found in `&B` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use a::A; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-10545.rs b/tests/ui/issues/issue-10545.rs new file mode 100644 index 000000000..acd071496 --- /dev/null +++ b/tests/ui/issues/issue-10545.rs @@ -0,0 +1,9 @@ +mod a { + struct S; + impl S { } +} + +fn foo(_: a::S) { //~ ERROR: struct `S` is private +} + +fn main() {} diff --git a/tests/ui/issues/issue-10545.stderr b/tests/ui/issues/issue-10545.stderr new file mode 100644 index 000000000..f1da33eab --- /dev/null +++ b/tests/ui/issues/issue-10545.stderr @@ -0,0 +1,15 @@ +error[E0603]: struct `S` is private + --> $DIR/issue-10545.rs:6:14 + | +LL | fn foo(_: a::S) { + | ^ private struct + | +note: the struct `S` is defined here + --> $DIR/issue-10545.rs:2:5 + | +LL | struct S; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-10638.rs b/tests/ui/issues/issue-10638.rs new file mode 100644 index 000000000..e359669c0 --- /dev/null +++ b/tests/ui/issues/issue-10638.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + //// I am not a doc comment! + ////////////////// still not a doc comment + /////**** nope, me neither */ + /*** And neither am I! */ + 5; + /*****! certainly not I */ +} diff --git a/tests/ui/issues/issue-10656.rs b/tests/ui/issues/issue-10656.rs new file mode 100644 index 000000000..250c4bc44 --- /dev/null +++ b/tests/ui/issues/issue-10656.rs @@ -0,0 +1,3 @@ +#![deny(missing_docs)] +#![crate_type="lib"] +//~^^ ERROR missing documentation for the crate diff --git a/tests/ui/issues/issue-10656.stderr b/tests/ui/issues/issue-10656.stderr new file mode 100644 index 000000000..2e4365f1e --- /dev/null +++ b/tests/ui/issues/issue-10656.stderr @@ -0,0 +1,15 @@ +error: missing documentation for the crate + --> $DIR/issue-10656.rs:1:1 + | +LL | / #![deny(missing_docs)] +LL | | #![crate_type="lib"] + | |____________________^ + | +note: the lint level is defined here + --> $DIR/issue-10656.rs:1:9 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-10682.rs b/tests/ui/issues/issue-10682.rs new file mode 100644 index 000000000..72e4559d3 --- /dev/null +++ b/tests/ui/issues/issue-10682.rs @@ -0,0 +1,13 @@ +// run-pass +// Regression test for issue #10682 +// Nested `proc` usage can't use outer owned data + +// pretty-expanded FIXME #23616 + +fn work(_: Box) {} +fn foo(_: F) {} + +pub fn main() { + let a = Box::new(1); + foo(move|| { foo(move|| { work(a) }) }) +} diff --git a/tests/ui/issues/issue-10683.rs b/tests/ui/issues/issue-10683.rs new file mode 100644 index 000000000..dcb221f8c --- /dev/null +++ b/tests/ui/issues/issue-10683.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +static NAME: &'static str = "hello world"; + +fn main() { + match &*NAME.to_ascii_lowercase() { + "foo" => {} + _ => {} + } +} diff --git a/tests/ui/issues/issue-10718.rs b/tests/ui/issues/issue-10718.rs new file mode 100644 index 000000000..a1de0cfe6 --- /dev/null +++ b/tests/ui/issues/issue-10718.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f(p: F) { + p(); +} + +pub fn main() { + let p = || (); + f(p); +} diff --git a/tests/ui/issues/issue-10734.rs b/tests/ui/issues/issue-10734.rs new file mode 100644 index 000000000..723e6ed22 --- /dev/null +++ b/tests/ui/issues/issue-10734.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(non_upper_case_globals)] + +static mut drop_count: usize = 0; + +struct Foo { + dropped: bool +} + +impl Drop for Foo { + fn drop(&mut self) { + // Test to make sure we haven't dropped already + assert!(!self.dropped); + self.dropped = true; + // And record the fact that we dropped for verification later + unsafe { drop_count += 1; } + } +} + +pub fn main() { + // An `if true { expr }` statement should compile the same as `{ expr }`. + if true { + let _a = Foo{ dropped: false }; + } + // Check that we dropped already (as expected from a `{ expr }`). + unsafe { assert_eq!(drop_count, 1); } + + // An `if false {} else { expr }` statement should compile the same as `{ expr }`. + if false { + panic!(); + } else { + let _a = Foo{ dropped: false }; + } + // Check that we dropped already (as expected from a `{ expr }`). + unsafe { assert_eq!(drop_count, 2); } +} diff --git a/tests/ui/issues/issue-10764.rs b/tests/ui/issues/issue-10764.rs new file mode 100644 index 000000000..bb915f58d --- /dev/null +++ b/tests/ui/issues/issue-10764.rs @@ -0,0 +1,5 @@ +fn f(_: extern "Rust" fn()) {} +extern "C" fn bar() {} + +fn main() { f(bar) } +//~^ ERROR mismatched types diff --git a/tests/ui/issues/issue-10764.stderr b/tests/ui/issues/issue-10764.stderr new file mode 100644 index 000000000..4d8a85a13 --- /dev/null +++ b/tests/ui/issues/issue-10764.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-10764.rs:4:15 + | +LL | fn main() { f(bar) } + | - ^^^ expected "Rust" fn, found "C" fn + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `fn()` + found fn item `extern "C" fn() {bar}` +note: function defined here + --> $DIR/issue-10764.rs:1:4 + | +LL | fn f(_: extern "Rust" fn()) {} + | ^ --------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-10767.rs b/tests/ui/issues/issue-10767.rs new file mode 100644 index 000000000..5670cd458 --- /dev/null +++ b/tests/ui/issues/issue-10767.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + fn f() { + } + let _: Box = Box::new(f as fn()); +} diff --git a/tests/ui/issues/issue-10802.rs b/tests/ui/issues/issue-10802.rs new file mode 100644 index 000000000..99e1a92df --- /dev/null +++ b/tests/ui/issues/issue-10802.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(dead_code)] + +struct DroppableStruct; +enum DroppableEnum { + DroppableVariant1, DroppableVariant2 +} + +static mut DROPPED: bool = false; + +impl Drop for DroppableStruct { + fn drop(&mut self) { + unsafe { DROPPED = true; } + } +} +impl Drop for DroppableEnum { + fn drop(&mut self) { + unsafe { DROPPED = true; } + } +} + +trait MyTrait { fn dummy(&self) { } } +impl MyTrait for Box {} +impl MyTrait for Box {} + +struct Whatever { w: Box } +impl Whatever { + fn new(w: Box) -> Whatever { + Whatever { w: w } + } +} + +fn main() { + { + let f: Box<_> = Box::new(DroppableStruct); + let _a = Whatever::new(Box::new(f) as Box); + } + assert!(unsafe { DROPPED }); + unsafe { DROPPED = false; } + { + let f: Box<_> = Box::new(DroppableEnum::DroppableVariant1); + let _a = Whatever::new(Box::new(f) as Box); + } + assert!(unsafe { DROPPED }); +} diff --git a/tests/ui/issues/issue-10806.rs b/tests/ui/issues/issue-10806.rs new file mode 100644 index 000000000..2f1d7bb5a --- /dev/null +++ b/tests/ui/issues/issue-10806.rs @@ -0,0 +1,38 @@ +// run-pass +#![allow(unused_imports)] + +// pretty-expanded FIXME #23616 + +pub fn foo() -> isize { + 3 +} +pub fn bar() -> isize { + 4 +} + +pub mod baz { + use {foo, bar}; + pub fn quux() -> isize { + foo() + bar() + } +} + +pub mod grault { + use {foo}; + pub fn garply() -> isize { + foo() + } +} + +pub mod waldo { + use {}; + pub fn plugh() -> isize { + 0 + } +} + +pub fn main() { + let _x = baz::quux(); + let _y = grault::garply(); + let _z = waldo::plugh(); +} diff --git a/tests/ui/issues/issue-10853.rs b/tests/ui/issues/issue-10853.rs new file mode 100644 index 000000000..3dcabf9b1 --- /dev/null +++ b/tests/ui/issues/issue-10853.rs @@ -0,0 +1,15 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#![deny(missing_docs)] +#![doc="module"] + +#[doc="struct"] +pub struct Foo; + +pub fn foo() { + #![doc="fn"] +} + +#[doc="main"] +pub fn main() {} diff --git a/tests/ui/issues/issue-10877.rs b/tests/ui/issues/issue-10877.rs new file mode 100644 index 000000000..15a383175 --- /dev/null +++ b/tests/ui/issues/issue-10877.rs @@ -0,0 +1,16 @@ +struct Foo { + x: isize, +} +extern "C" { + fn foo(1: ()); + //~^ ERROR: patterns aren't allowed in foreign function declarations + fn bar((): isize); + //~^ ERROR: patterns aren't allowed in foreign function declarations + fn baz(Foo { x }: isize); + //~^ ERROR: patterns aren't allowed in foreign function declarations + fn qux((x, y): ()); + //~^ ERROR: patterns aren't allowed in foreign function declarations + fn this_is_actually_ok(a: usize); + fn and_so_is_this(_: usize); +} +fn main() {} diff --git a/tests/ui/issues/issue-10877.stderr b/tests/ui/issues/issue-10877.stderr new file mode 100644 index 000000000..bd3797cba --- /dev/null +++ b/tests/ui/issues/issue-10877.stderr @@ -0,0 +1,27 @@ +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/issue-10877.rs:5:12 + | +LL | fn foo(1: ()); + | ^ pattern not allowed in foreign function + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/issue-10877.rs:7:12 + | +LL | fn bar((): isize); + | ^^ pattern not allowed in foreign function + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/issue-10877.rs:9:12 + | +LL | fn baz(Foo { x }: isize); + | ^^^^^^^^^ pattern not allowed in foreign function + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/issue-10877.rs:11:12 + | +LL | fn qux((x, y): ()); + | ^^^^^^ pattern not allowed in foreign function + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0130`. diff --git a/tests/ui/issues/issue-10902.rs b/tests/ui/issues/issue-10902.rs new file mode 100644 index 000000000..162482d49 --- /dev/null +++ b/tests/ui/issues/issue-10902.rs @@ -0,0 +1,21 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub mod two_tuple { + pub trait T { fn dummy(&self) { } } + pub struct P<'a>(&'a (dyn T + 'a), &'a (dyn T + 'a)); + pub fn f<'a>(car: &'a dyn T, cdr: &'a dyn T) -> P<'a> { + P(car, cdr) + } +} + +pub mod two_fields { + pub trait T { fn dummy(&self) { } } + pub struct P<'a> { car: &'a (dyn T + 'a), cdr: &'a (dyn T + 'a) } + pub fn f<'a>(car: &'a dyn T, cdr: &'a dyn T) -> P<'a> { + P{ car: car, cdr: cdr } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-11004.rs b/tests/ui/issues/issue-11004.rs new file mode 100644 index 000000000..10ef1f5e3 --- /dev/null +++ b/tests/ui/issues/issue-11004.rs @@ -0,0 +1,27 @@ +use std::mem; + +struct A { x: i32, y: f64 } + +#[cfg(not(works))] +unsafe fn access(n:*mut A) -> (i32, f64) { + let x : i32 = n.x; //~ no field `x` on type `*mut A` + let y : f64 = n.y; //~ no field `y` on type `*mut A` + (x, y) +} + +#[cfg(works)] +unsafe fn access(n:*mut A) -> (i32, f64) { + let x : i32 = (*n).x; + let y : f64 = (*n).y; + (x, y) +} + +fn main() { + let a : A = A { x: 3, y: 3.14 }; + let p : &A = &a; + let (x,y) = unsafe { + let n : *mut A = mem::transmute(p); + access(n) + }; + println!("x: {}, y: {}", x, y); +} diff --git a/tests/ui/issues/issue-11004.stderr b/tests/ui/issues/issue-11004.stderr new file mode 100644 index 000000000..b5831e42e --- /dev/null +++ b/tests/ui/issues/issue-11004.stderr @@ -0,0 +1,19 @@ +error[E0609]: no field `x` on type `*mut A` + --> $DIR/issue-11004.rs:7:21 + | +LL | let x : i32 = n.x; + | --^ + | | + | help: `n` is a raw pointer; try dereferencing it: `(*n).x` + +error[E0609]: no field `y` on type `*mut A` + --> $DIR/issue-11004.rs:8:21 + | +LL | let y : f64 = n.y; + | --^ + | | + | help: `n` is a raw pointer; try dereferencing it: `(*n).y` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-11047.rs b/tests/ui/issues/issue-11047.rs new file mode 100644 index 000000000..1fb2b5bb3 --- /dev/null +++ b/tests/ui/issues/issue-11047.rs @@ -0,0 +1,26 @@ +// run-pass +// Test that static methods can be invoked on `type` aliases + +#![allow(unused_variables)] + +pub mod foo { + pub mod bar { + pub mod baz { + pub struct Qux; + + impl Qux { + pub fn new() {} + } + } + } +} + +fn main() { + + type Ham = foo::bar::baz::Qux; + let foo = foo::bar::baz::Qux::new(); // invoke directly + let bar = Ham::new(); // invoke via type alias + + type StringVec = Vec; + let sv = StringVec::new(); +} diff --git a/tests/ui/issues/issue-11085.rs b/tests/ui/issues/issue-11085.rs new file mode 100644 index 000000000..47c03238b --- /dev/null +++ b/tests/ui/issues/issue-11085.rs @@ -0,0 +1,46 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: --cfg foo + +// pretty-expanded FIXME #23616 + +struct Foo { + #[cfg(fail)] + bar: baz, + foo: isize, +} + +struct Foo2 { + #[cfg(foo)] + foo: isize, +} + +enum Bar1 { + Bar1_1, + #[cfg(fail)] + Bar1_2(NotAType), +} + +enum Bar2 { + #[cfg(fail)] + Bar2_1(NotAType), +} + +enum Bar3 { + Bar3_1 { + #[cfg(fail)] + foo: isize, + bar: isize, + } +} + +pub fn main() { + let _f = Foo { foo: 3 }; + let _f = Foo2 { foo: 3 }; + + match Bar1::Bar1_1 { + Bar1::Bar1_1 => {} + } + + let _f = Bar3::Bar3_1 { bar: 3 }; +} diff --git a/tests/ui/issues/issue-11192.rs b/tests/ui/issues/issue-11192.rs new file mode 100644 index 000000000..1a3d8c9fe --- /dev/null +++ b/tests/ui/issues/issue-11192.rs @@ -0,0 +1,22 @@ +struct Foo { + x: isize +} + + +impl Drop for Foo { + fn drop(&mut self) { + println!("drop {}", self.x); + } +} + + +fn main() { + let mut ptr: Box<_> = Box::new(Foo { x: 0 }); + let mut test = |foo: &Foo| { + println!("access {}", foo.x); + ptr = Box::new(Foo { x: ptr.x + 1 }); + println!("access {}", foo.x); + }; + test(&*ptr); + //~^ ERROR: cannot borrow `*ptr` as immutable +} diff --git a/tests/ui/issues/issue-11192.stderr b/tests/ui/issues/issue-11192.stderr new file mode 100644 index 000000000..fc1548013 --- /dev/null +++ b/tests/ui/issues/issue-11192.stderr @@ -0,0 +1,17 @@ +error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as mutable + --> $DIR/issue-11192.rs:20:10 + | +LL | let mut test = |foo: &Foo| { + | ----------- mutable borrow occurs here +LL | println!("access {}", foo.x); +LL | ptr = Box::new(Foo { x: ptr.x + 1 }); + | --- first borrow occurs due to use of `ptr` in closure +... +LL | test(&*ptr); + | ---- ^^^^^ immutable borrow occurs here + | | + | mutable borrow later used by call + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/issues/issue-11205.rs b/tests/ui/issues/issue-11205.rs new file mode 100644 index 000000000..ce0951eaf --- /dev/null +++ b/tests/ui/issues/issue-11205.rs @@ -0,0 +1,85 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Foo { fn dummy(&self) { } } +impl Foo for isize {} +fn foo(_: [&dyn Foo; 2]) {} +fn foos(_: &[&dyn Foo]) {} +fn foog(_: &[T], _: &[T]) {} + +fn bar(_: [Box; 2]) {} +fn bars(_: &[Box]) {} + +fn main() { + let x: [&dyn Foo; 2] = [&1, &2]; + foo(x); + foo([&1, &2]); + + let r = &1; + let x: [&dyn Foo; 2] = [r; 2]; + foo(x); + foo([&1; 2]); + + let x: &[&dyn Foo] = &[&1, &2]; + foos(x); + foos(&[&1, &2]); + + let x: &[&dyn Foo] = &[&1, &2]; + let r = &1; + foog(x, &[r]); + + let x: [Box; 2] = [Box::new(1), Box::new(2)]; + bar(x); + bar([Box::new(1), Box::new(2)]); + + let x: &[Box] = &[Box::new(1), Box::new(2)]; + bars(x); + bars(&[Box::new(1), Box::new(2)]); + + let x: &[Box] = &[Box::new(1), Box::new(2)]; + foog(x, &[Box::new(1)]); + + struct T<'a> { + t: [&'a (dyn Foo+'a); 2] + } + let _n = T { + t: [&1, &2] + }; + let r = &1; + let _n = T { + t: [r; 2] + }; + let x: [&dyn Foo; 2] = [&1, &2]; + let _n = T { + t: x + }; + + struct F<'b> { + t: &'b [&'b (dyn Foo+'b)] + } + let _n = F { + t: &[&1, &2] + }; + let r = &1; + let r: [&dyn Foo; 2] = [r; 2]; + let _n = F { + t: &r + }; + let x: [&dyn Foo; 2] = [&1, &2]; + let _n = F { + t: &x + }; + + struct M<'a> { + t: &'a [Box] + } + let _n = M { + t: &[Box::new(1), Box::new(2)] + }; + let x: [Box; 2] = [Box::new(1), Box::new(2)]; + let _n = M { + t: &x + }; +} diff --git a/tests/ui/issues/issue-11224.rs b/tests/ui/issues/issue-11224.rs new file mode 100644 index 000000000..e1c1df99a --- /dev/null +++ b/tests/ui/issues/issue-11224.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-11224.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_11224 as unused; + +pub fn main() {} diff --git a/tests/ui/issues/issue-11267.rs b/tests/ui/issues/issue-11267.rs new file mode 100644 index 000000000..848ed6ac7 --- /dev/null +++ b/tests/ui/issues/issue-11267.rs @@ -0,0 +1,19 @@ +// run-pass +// Tests that unary structs can be mutably borrowed. + +struct Empty; + +trait T { + fn next(&mut self) -> Option; +} +impl T for Empty { + fn next(&mut self) -> Option { None } +} + +fn do_something_with(a : &mut dyn T) { + println!("{:?}", a.next()) +} + +pub fn main() { + do_something_with(&mut Empty); +} diff --git a/tests/ui/issues/issue-11374.rs b/tests/ui/issues/issue-11374.rs new file mode 100644 index 000000000..7519ba282 --- /dev/null +++ b/tests/ui/issues/issue-11374.rs @@ -0,0 +1,27 @@ +use std::io::{self, Read}; +use std::vec; + +pub struct Container<'a> { + reader: &'a mut dyn Read +} + +impl<'a> Container<'a> { + pub fn wrap<'s>(reader: &'s mut dyn io::Read) -> Container<'s> { + Container { reader: reader } + } + + pub fn read_to(&mut self, vec: &mut [u8]) { + self.reader.read(vec); + } +} + +pub fn for_stdin<'a>() -> Container<'a> { + let mut r = io::stdin(); + Container::wrap(&mut r as &mut dyn io::Read) +} + +fn main() { + let mut c = for_stdin(); + let mut v = Vec::new(); + c.read_to(v); //~ ERROR E0308 +} diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr new file mode 100644 index 000000000..ace77814a --- /dev/null +++ b/tests/ui/issues/issue-11374.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-11374.rs:26:15 + | +LL | c.read_to(v); + | ------- ^ + | | | + | | expected `&mut [u8]`, found struct `Vec` + | | help: consider mutably borrowing here: `&mut v` + | arguments to this method are incorrect + | + = note: expected mutable reference `&mut [u8]` + found struct `Vec<_>` +note: associated function defined here + --> $DIR/issue-11374.rs:13:12 + | +LL | pub fn read_to(&mut self, vec: &mut [u8]) { + | ^^^^^^^ -------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-11382.rs b/tests/ui/issues/issue-11382.rs new file mode 100644 index 000000000..42a7a0d04 --- /dev/null +++ b/tests/ui/issues/issue-11382.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() { + println!("{}", 1.2); +} diff --git a/tests/ui/issues/issue-11384.rs b/tests/ui/issues/issue-11384.rs new file mode 100644 index 000000000..0105b4d22 --- /dev/null +++ b/tests/ui/issues/issue-11384.rs @@ -0,0 +1,10 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait Common { fn dummy(&self) { } } + +impl<'t, T> Common for (T, &'t T) {} + +impl<'t, T> Common for (&'t T, T) {} + +fn main() {} diff --git a/tests/ui/issues/issue-11508.rs b/tests/ui/issues/issue-11508.rs new file mode 100644 index 000000000..49868b73e --- /dev/null +++ b/tests/ui/issues/issue-11508.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-11508.rs + +extern crate issue_11508 as rand; + +use rand::{Closed01, random}; + +fn main() { + let Closed01(val) = random::>(); + println!("{}", val); +} diff --git a/tests/ui/issues/issue-11515.rs b/tests/ui/issues/issue-11515.rs new file mode 100644 index 000000000..b5c942f96 --- /dev/null +++ b/tests/ui/issues/issue-11515.rs @@ -0,0 +1,10 @@ +struct Test { + func: Box, +} + + + +fn main() { + let closure: Box = Box::new(|| ()); + let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658] +} diff --git a/tests/ui/issues/issue-11515.stderr b/tests/ui/issues/issue-11515.stderr new file mode 100644 index 000000000..accd47f0f --- /dev/null +++ b/tests/ui/issues/issue-11515.stderr @@ -0,0 +1,13 @@ +error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental + --> $DIR/issue-11515.rs:9:38 + | +LL | let test = Box::new(Test { func: closure }); + | ^^^^^^^ + | + = note: see issue #65991 for more information + = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable + = note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-11529.rs b/tests/ui/issues/issue-11529.rs new file mode 100644 index 000000000..9a6cc8e9f --- /dev/null +++ b/tests/ui/issues/issue-11529.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-11529.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_11529 as a; + +fn main() { + let one = 1; + let _a = a::A(&one); +} diff --git a/tests/ui/issues/issue-11552.rs b/tests/ui/issues/issue-11552.rs new file mode 100644 index 000000000..9fb9f3d2e --- /dev/null +++ b/tests/ui/issues/issue-11552.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(box_patterns)] + +#[derive(Clone)] +enum Noun +{ + Atom(isize), + Cell(Box, Box) +} + +fn fas(n: &Noun) -> Noun +{ + match n { + &Noun::Cell(box Noun::Atom(2), box Noun::Cell(ref a, _)) => (**a).clone(), + _ => panic!("Invalid fas pattern") + } +} + +pub fn main() { + fas( + &Noun::Cell(Box::new(Noun::Atom(2)), + Box::new(Noun::Cell(Box::new(Noun::Atom(2)), Box::new(Noun::Atom(3))))) + ); +} diff --git a/tests/ui/issues/issue-11592.rs b/tests/ui/issues/issue-11592.rs new file mode 100644 index 000000000..a4611f2f9 --- /dev/null +++ b/tests/ui/issues/issue-11592.rs @@ -0,0 +1,11 @@ +// check-pass +//! Ensure the private trait Bar isn't complained about. + +#![deny(missing_docs)] + +mod foo { + trait Bar { fn bar(&self) { } } + impl Bar for i8 { fn bar(&self) { } } +} + +fn main() { } diff --git a/tests/ui/issues/issue-11593.rs b/tests/ui/issues/issue-11593.rs new file mode 100644 index 000000000..8bf034e82 --- /dev/null +++ b/tests/ui/issues/issue-11593.rs @@ -0,0 +1,10 @@ +// aux-build:private-trait-xc.rs + +extern crate private_trait_xc; + +struct Bar; + +impl private_trait_xc::Foo for Bar {} +//~^ ERROR: trait `Foo` is private + +fn main() {} diff --git a/tests/ui/issues/issue-11593.stderr b/tests/ui/issues/issue-11593.stderr new file mode 100644 index 000000000..aa9768b18 --- /dev/null +++ b/tests/ui/issues/issue-11593.stderr @@ -0,0 +1,15 @@ +error[E0603]: trait `Foo` is private + --> $DIR/issue-11593.rs:7:24 + | +LL | impl private_trait_xc::Foo for Bar {} + | ^^^ private trait + | +note: the trait `Foo` is defined here + --> $DIR/auxiliary/private-trait-xc.rs:1:1 + | +LL | trait Foo {} + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-11677.rs b/tests/ui/issues/issue-11677.rs new file mode 100644 index 000000000..be18c736f --- /dev/null +++ b/tests/ui/issues/issue-11677.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_imports)] + +#![allow(dead_code)] + +// this code used to cause an ICE + +use std::marker; + +trait X { + fn dummy(&self) -> T { panic!() } +} + +struct S {f: Box+'static>, + g: Box+'static>} + +struct F; +impl X for F { +} + +fn main() { + S {f: Box::new(F), g: Box::new(F) }; +} diff --git a/tests/ui/issues/issue-11680.rs b/tests/ui/issues/issue-11680.rs new file mode 100644 index 000000000..bfa8f5c5a --- /dev/null +++ b/tests/ui/issues/issue-11680.rs @@ -0,0 +1,11 @@ +// aux-build:issue-11680.rs + +extern crate issue_11680 as other; + +fn main() { + let _b = other::Foo::Bar(1); + //~^ ERROR: enum `Foo` is private + + let _b = other::test::Foo::Bar(1); + //~^ ERROR: enum `Foo` is private +} diff --git a/tests/ui/issues/issue-11680.stderr b/tests/ui/issues/issue-11680.stderr new file mode 100644 index 000000000..ea224af8e --- /dev/null +++ b/tests/ui/issues/issue-11680.stderr @@ -0,0 +1,27 @@ +error[E0603]: enum `Foo` is private + --> $DIR/issue-11680.rs:6:21 + | +LL | let _b = other::Foo::Bar(1); + | ^^^ private enum + | +note: the enum `Foo` is defined here + --> $DIR/auxiliary/issue-11680.rs:1:1 + | +LL | enum Foo { + | ^^^^^^^^ + +error[E0603]: enum `Foo` is private + --> $DIR/issue-11680.rs:9:27 + | +LL | let _b = other::test::Foo::Bar(1); + | ^^^ private enum + | +note: the enum `Foo` is defined here + --> $DIR/auxiliary/issue-11680.rs:6:5 + | +LL | enum Foo { + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-11681.rs b/tests/ui/issues/issue-11681.rs new file mode 100644 index 000000000..6d8810d80 --- /dev/null +++ b/tests/ui/issues/issue-11681.rs @@ -0,0 +1,19 @@ +// This tests verifies that unary structs and enum variants +// are treated as rvalues and their lifetime is not bounded to +// the static scope. + +struct Test; + +impl Drop for Test { + fn drop (&mut self) {} +} + +fn createTest<'a>() -> &'a Test { + let testValue = &Test; + return testValue; //~ ERROR cannot return value referencing temporary value +} + + +pub fn main() { + createTest(); +} diff --git a/tests/ui/issues/issue-11681.stderr b/tests/ui/issues/issue-11681.stderr new file mode 100644 index 000000000..f2f930766 --- /dev/null +++ b/tests/ui/issues/issue-11681.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/issue-11681.rs:13:10 + | +LL | let testValue = &Test; + | ---- temporary value created here +LL | return testValue; + | ^^^^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-11692-1.rs b/tests/ui/issues/issue-11692-1.rs new file mode 100644 index 000000000..b6f3bb8ef --- /dev/null +++ b/tests/ui/issues/issue-11692-1.rs @@ -0,0 +1,3 @@ +fn main() { + print!(testo!()); //~ ERROR cannot find macro `testo` in this scope +} diff --git a/tests/ui/issues/issue-11692-1.stderr b/tests/ui/issues/issue-11692-1.stderr new file mode 100644 index 000000000..386463436 --- /dev/null +++ b/tests/ui/issues/issue-11692-1.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `testo` in this scope + --> $DIR/issue-11692-1.rs:2:12 + | +LL | print!(testo!()); + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-11692-2.rs b/tests/ui/issues/issue-11692-2.rs new file mode 100644 index 000000000..5957ed338 --- /dev/null +++ b/tests/ui/issues/issue-11692-2.rs @@ -0,0 +1,3 @@ +fn main() { + concat!(test!()); //~ ERROR cannot find macro `test` in this scope +} diff --git a/tests/ui/issues/issue-11692-2.stderr b/tests/ui/issues/issue-11692-2.stderr new file mode 100644 index 000000000..84746ca2c --- /dev/null +++ b/tests/ui/issues/issue-11692-2.stderr @@ -0,0 +1,10 @@ +error: cannot find macro `test` in this scope + --> $DIR/issue-11692-2.rs:2:13 + | +LL | concat!(test!()); + | ^^^^ + | + = note: `test` is in scope, but it is an attribute: `#[test]` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-11709.rs b/tests/ui/issues/issue-11709.rs new file mode 100644 index 000000000..cb5e3dff3 --- /dev/null +++ b/tests/ui/issues/issue-11709.rs @@ -0,0 +1,38 @@ +// run-pass +#![allow(dead_code)] +// ignore-pretty issue #37199 + +// Don't panic on blocks without results +// There are several tests in this run-pass that raised +// when this bug was opened. The cases where the compiler +// panics before the fix have a comment. + +struct S {x:()} + +fn test(slot: &mut Option Box>>) -> () { + let a = slot.take(); + let _a = match a { + // `{let .. a(); }` would break + Some(mut a) => { let _a = a(); }, + None => (), + }; +} + +fn not(b: bool) -> bool { + if b { + !b + } else { + // `panic!(...)` would break + panic!("Break the compiler"); + } +} + +pub fn main() { + // {} would break + let _r = {}; + let mut slot = None; + // `{ test(...); }` would break + let _s : S = S{ x: { test(&mut slot); } }; + + let _b = not(true); +} diff --git a/tests/ui/issues/issue-11740.rs b/tests/ui/issues/issue-11740.rs new file mode 100644 index 000000000..9faeb7770 --- /dev/null +++ b/tests/ui/issues/issue-11740.rs @@ -0,0 +1,28 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +struct Attr { + name: String, + value: String, +} + +struct Element { + attrs: Vec>, +} + +impl Element { + pub unsafe fn get_attr<'a>(&'a self, name: &str) { + self.attrs + .iter() + .find(|attr| { + let attr: &&Box = std::mem::transmute(attr); + true + }); + } +} + +fn main() { + let element = Element { attrs: Vec::new() }; + let _ = unsafe { element.get_attr("foo") }; +} diff --git a/tests/ui/issues/issue-11771.rs b/tests/ui/issues/issue-11771.rs new file mode 100644 index 000000000..c69cd1e79 --- /dev/null +++ b/tests/ui/issues/issue-11771.rs @@ -0,0 +1,11 @@ +fn main() { + let x = (); + 1 + + x //~^ ERROR E0277 + ; + + let x: () = (); + 1 + + x //~^ ERROR E0277 + ; +} diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr new file mode 100644 index 000000000..161fce4b0 --- /dev/null +++ b/tests/ui/issues/issue-11771.stderr @@ -0,0 +1,39 @@ +error[E0277]: cannot add `()` to `{integer}` + --> $DIR/issue-11771.rs:3:7 + | +LL | 1 + + | ^ no implementation for `{integer} + ()` + | + = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others + +error[E0277]: cannot add `()` to `{integer}` + --> $DIR/issue-11771.rs:8:7 + | +LL | 1 + + | ^ no implementation for `{integer} + ()` + | + = help: the trait `Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-11820.rs b/tests/ui/issues/issue-11820.rs new file mode 100644 index 000000000..7ffe96527 --- /dev/null +++ b/tests/ui/issues/issue-11820.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct NoClone; + +fn main() { + let rnc = &NoClone; + let rsnc = &Some(NoClone); + + let _: &NoClone = rnc.clone(); + let _: &Option = rsnc.clone(); +} diff --git a/tests/ui/issues/issue-11844.rs b/tests/ui/issues/issue-11844.rs new file mode 100644 index 000000000..f974a4702 --- /dev/null +++ b/tests/ui/issues/issue-11844.rs @@ -0,0 +1,8 @@ +fn main() { + let a = Some(Box::new(1)); + match a { + Ok(a) => //~ ERROR: mismatched types + println!("{}",a), + None => panic!() + } +} diff --git a/tests/ui/issues/issue-11844.stderr b/tests/ui/issues/issue-11844.stderr new file mode 100644 index 000000000..81cf918a1 --- /dev/null +++ b/tests/ui/issues/issue-11844.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-11844.rs:4:9 + | +LL | match a { + | - this expression has type `Option>` +LL | Ok(a) => + | ^^^^^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option>` + found enum `Result<_, _>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-11869.rs b/tests/ui/issues/issue-11869.rs new file mode 100644 index 000000000..b300f4593 --- /dev/null +++ b/tests/ui/issues/issue-11869.rs @@ -0,0 +1,17 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct A { + a: String +} + +fn borrow<'a>(binding: &'a A) -> &'a str { + match &*binding.a { + "in" => "in_", + "ref" => "ref_", + ident => ident + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-11873.rs b/tests/ui/issues/issue-11873.rs new file mode 100644 index 000000000..d3bd05caf --- /dev/null +++ b/tests/ui/issues/issue-11873.rs @@ -0,0 +1,7 @@ +fn main() { + let mut v = vec![1]; + let mut f = || v.push(2); + let _w = v; //~ ERROR: cannot move out of `v` + + f(); +} diff --git a/tests/ui/issues/issue-11873.stderr b/tests/ui/issues/issue-11873.stderr new file mode 100644 index 000000000..c814eedd2 --- /dev/null +++ b/tests/ui/issues/issue-11873.stderr @@ -0,0 +1,16 @@ +error[E0505]: cannot move out of `v` because it is borrowed + --> $DIR/issue-11873.rs:4:14 + | +LL | let mut f = || v.push(2); + | -- - borrow occurs due to use in closure + | | + | borrow of `v` occurs here +LL | let _w = v; + | ^ move out of `v` occurs here +LL | +LL | f(); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/issues/issue-11958.rs b/tests/ui/issues/issue-11958.rs new file mode 100644 index 000000000..a7af01e25 --- /dev/null +++ b/tests/ui/issues/issue-11958.rs @@ -0,0 +1,11 @@ +// run-pass + +// We shouldn't need to rebind a moved upvar as mut if it's already +// marked as mut + +pub fn main() { + let mut x = 1; + let _thunk = Box::new(move|| { x = 2; }); + //~^ WARN value assigned to `x` is never read + //~| WARN unused variable: `x` +} diff --git a/tests/ui/issues/issue-11958.stderr b/tests/ui/issues/issue-11958.stderr new file mode 100644 index 000000000..5dca4c2f0 --- /dev/null +++ b/tests/ui/issues/issue-11958.stderr @@ -0,0 +1,20 @@ +warning: value assigned to `x` is never read + --> $DIR/issue-11958.rs:8:36 + | +LL | let _thunk = Box::new(move|| { x = 2; }); + | ^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` on by default + +warning: unused variable: `x` + --> $DIR/issue-11958.rs:8:36 + | +LL | let _thunk = Box::new(move|| { x = 2; }); + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` on by default + +warning: 2 warnings emitted + diff --git a/tests/ui/issues/issue-12028.rs b/tests/ui/issues/issue-12028.rs new file mode 100644 index 000000000..7503766ff --- /dev/null +++ b/tests/ui/issues/issue-12028.rs @@ -0,0 +1,38 @@ +// Test an example where we fail to infer the type parameter H. This +// is because there is really nothing constraining it. At one time, we +// would infer based on the where clauses in scope, but that no longer +// works. + +trait Hash { + fn hash2(&self, hasher: &H) -> u64; +} + +trait Stream { + fn input(&mut self, bytes: &[u8]); + fn result(&self) -> u64; +} + +trait StreamHasher { + type S : Stream; + fn stream(&self) -> Self::S; +} + +trait StreamHash: Hash { + fn input_stream(&self, stream: &mut H::S); +} + +impl Hash for u8 { + fn hash2(&self, hasher: &H) -> u64 { + let mut stream = hasher.stream(); + self.input_stream(&mut stream); //~ ERROR type annotations needed + Stream::result(&stream) + } +} + +impl StreamHash for u8 { + fn input_stream(&self, stream: &mut H::S) { + Stream::input(stream, &[*self]); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-12028.stderr b/tests/ui/issues/issue-12028.stderr new file mode 100644 index 000000000..8d6b81c24 --- /dev/null +++ b/tests/ui/issues/issue-12028.stderr @@ -0,0 +1,15 @@ +error[E0284]: type annotations needed + --> $DIR/issue-12028.rs:27:14 + | +LL | self.input_stream(&mut stream); + | ^^^^^^^^^^^^ + | + = note: cannot satisfy `<_ as StreamHasher>::S == ::S` +help: try using a fully qualified path to specify the expected types + | +LL | >::input_stream(self, &mut stream); + | ++++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/issues/issue-12033.rs b/tests/ui/issues/issue-12033.rs new file mode 100644 index 000000000..9dc7573c9 --- /dev/null +++ b/tests/ui/issues/issue-12033.rs @@ -0,0 +1,7 @@ +// run-pass +use std::cell::RefCell; + +fn main() { + let x = RefCell::new(0); + if *x.borrow() == 0 {} else {} +} diff --git a/tests/ui/issues/issue-12041.rs b/tests/ui/issues/issue-12041.rs new file mode 100644 index 000000000..091e8fe8b --- /dev/null +++ b/tests/ui/issues/issue-12041.rs @@ -0,0 +1,13 @@ +use std::sync::mpsc::channel; +use std::thread; + +fn main() { + let (tx, rx) = channel(); + let _t = thread::spawn(move|| -> () { + loop { + let tx = tx; + //~^ ERROR: use of moved value: `tx` + tx.send(1); + } + }); +} diff --git a/tests/ui/issues/issue-12041.stderr b/tests/ui/issues/issue-12041.stderr new file mode 100644 index 000000000..b9ffa499a --- /dev/null +++ b/tests/ui/issues/issue-12041.stderr @@ -0,0 +1,11 @@ +error[E0382]: use of moved value: `tx` + --> $DIR/issue-12041.rs:8:22 + | +LL | let tx = tx; + | ^^ value moved here, in previous iteration of loop + | + = note: move occurs because `tx` has type `Sender`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-12127.rs b/tests/ui/issues/issue-12127.rs new file mode 100644 index 000000000..199d542e8 --- /dev/null +++ b/tests/ui/issues/issue-12127.rs @@ -0,0 +1,14 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_once>(f: F) -> F { f } +fn do_it(x: &isize) { } + +fn main() { + let x: Box<_> = Box::new(22); + let f = to_fn_once(move|| do_it(&*x)); + to_fn_once(move|| { + f(); + f(); + //~^ ERROR: use of moved value: `f` + })() +} diff --git a/tests/ui/issues/issue-12127.stderr b/tests/ui/issues/issue-12127.stderr new file mode 100644 index 000000000..2c451b07f --- /dev/null +++ b/tests/ui/issues/issue-12127.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `f` + --> $DIR/issue-12127.rs:11:9 + | +LL | f(); + | --- `f` moved due to this call +LL | f(); + | ^ value used here after move + | +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/issue-12127.rs:10:9 + | +LL | f(); + | ^ + = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:30]`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-12133-1.rs b/tests/ui/issues/issue-12133-1.rs new file mode 100644 index 000000000..96ad5abd5 --- /dev/null +++ b/tests/ui/issues/issue-12133-1.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:issue-12133-rlib.rs +// aux-build:issue-12133-dylib.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_12133_rlib as a; +extern crate issue_12133_dylib as b; + +fn main() {} diff --git a/tests/ui/issues/issue-12133-2.rs b/tests/ui/issues/issue-12133-2.rs new file mode 100644 index 000000000..02fec65c2 --- /dev/null +++ b/tests/ui/issues/issue-12133-2.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-12133-rlib.rs +// aux-build:issue-12133-dylib.rs +// no-prefer-dynamic + +// pretty-expanded FIXME #23616 + +extern crate issue_12133_rlib as a; +extern crate issue_12133_dylib as b; + +fn main() {} diff --git a/tests/ui/issues/issue-12133-3.rs b/tests/ui/issues/issue-12133-3.rs new file mode 100644 index 000000000..e6b16e2da --- /dev/null +++ b/tests/ui/issues/issue-12133-3.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:issue-12133-rlib.rs +// aux-build:issue-12133-dylib.rs +// aux-build:issue-12133-dylib2.rs +// ignore-emscripten no dylib support +// ignore-musl +// ignore-sgx no dylib support + +// pretty-expanded FIXME #23616 + +extern crate issue_12133_dylib2 as other; + +fn main() {} diff --git a/tests/ui/issues/issue-12187-1.rs b/tests/ui/issues/issue-12187-1.rs new file mode 100644 index 000000000..86128ed94 --- /dev/null +++ b/tests/ui/issues/issue-12187-1.rs @@ -0,0 +1,8 @@ +fn new() -> &'static T { + panic!() +} + +fn main() { + let &v = new(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr new file mode 100644 index 000000000..806b7f0ac --- /dev/null +++ b/tests/ui/issues/issue-12187-1.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `&T` + --> $DIR/issue-12187-1.rs:6:9 + | +LL | let &v = new(); + | ^^ + | +help: consider giving this pattern a type, where the placeholders `_` are specified + | +LL | let &v: &T = new(); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-12187-2.rs b/tests/ui/issues/issue-12187-2.rs new file mode 100644 index 000000000..080a6206b --- /dev/null +++ b/tests/ui/issues/issue-12187-2.rs @@ -0,0 +1,8 @@ +fn new<'r, T>() -> &'r T { + panic!() +} + +fn main() { + let &v = new(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr new file mode 100644 index 000000000..a1fa0a2b0 --- /dev/null +++ b/tests/ui/issues/issue-12187-2.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `&T` + --> $DIR/issue-12187-2.rs:6:9 + | +LL | let &v = new(); + | ^^ + | +help: consider giving this pattern a type, where the placeholders `_` are specified + | +LL | let &v: &T = new(); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-12285.rs b/tests/ui/issues/issue-12285.rs new file mode 100644 index 000000000..24ac5d2fb --- /dev/null +++ b/tests/ui/issues/issue-12285.rs @@ -0,0 +1,14 @@ +// run-pass + +struct S; + +fn main() { + match Some(&S) { + Some(&S) => {}, + _x => unreachable!() + } + match Some(&S) { + Some(&S) => {}, + None => unreachable!() + } +} diff --git a/tests/ui/issues/issue-1251.rs b/tests/ui/issues/issue-1251.rs new file mode 100644 index 000000000..c2c047c79 --- /dev/null +++ b/tests/ui/issues/issue-1251.rs @@ -0,0 +1,16 @@ +// build-pass +#![allow(unused_attributes)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test ffi with +#![feature(rustc_private)] + +mod rustrt { + extern crate libc; + + extern "C" { + pub fn rust_get_test_int() -> libc::intptr_t; + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-12511.rs b/tests/ui/issues/issue-12511.rs new file mode 100644 index 000000000..ea83e3fd9 --- /dev/null +++ b/tests/ui/issues/issue-12511.rs @@ -0,0 +1,8 @@ +trait T1 : T2 { +//~^ ERROR cycle detected +} + +trait T2 : T1 { +} + +fn main() { } diff --git a/tests/ui/issues/issue-12511.stderr b/tests/ui/issues/issue-12511.stderr new file mode 100644 index 000000000..789a1141c --- /dev/null +++ b/tests/ui/issues/issue-12511.stderr @@ -0,0 +1,33 @@ +error[E0391]: cycle detected when computing the super predicates of `T1` + --> $DIR/issue-12511.rs:1:1 + | +LL | trait T1 : T2 { + | ^^^^^^^^^^^^^ + | +note: ...which requires computing the super traits of `T1`... + --> $DIR/issue-12511.rs:1:12 + | +LL | trait T1 : T2 { + | ^^ +note: ...which requires computing the super predicates of `T2`... + --> $DIR/issue-12511.rs:5:1 + | +LL | trait T2 : T1 { + | ^^^^^^^^^^^^^ +note: ...which requires computing the super traits of `T2`... + --> $DIR/issue-12511.rs:5:12 + | +LL | trait T2 : T1 { + | ^^ + = note: ...which again requires computing the super predicates of `T1`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-12511.rs:1:1 + | +LL | / trait T1 : T2 { +LL | | +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-12567.rs b/tests/ui/issues/issue-12567.rs new file mode 100644 index 000000000..1b2a37de4 --- /dev/null +++ b/tests/ui/issues/issue-12567.rs @@ -0,0 +1,13 @@ +fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { + match (l1, l2) { + //~^ ERROR: cannot move out of type `[T]`, a non-copy slice + //~| ERROR: cannot move out of type `[T]`, a non-copy slice + (&[], &[]) => println!("both empty"), + (&[], &[hd, ..]) | (&[hd, ..], &[]) + => println!("one empty"), + (&[hd1, ..], &[hd2, ..]) + => println!("both nonempty"), + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-12567.stderr b/tests/ui/issues/issue-12567.stderr new file mode 100644 index 000000000..7fa06825f --- /dev/null +++ b/tests/ui/issues/issue-12567.stderr @@ -0,0 +1,47 @@ +error[E0508]: cannot move out of type `[T]`, a non-copy slice + --> $DIR/issue-12567.rs:2:11 + | +LL | match (l1, l2) { + | ^^^^^^^^ cannot move out of here +... +LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) + | -- data moved here +LL | => println!("one empty"), +LL | (&[hd1, ..], &[hd2, ..]) + | --- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) + | +++ +help: consider borrowing the pattern binding + | +LL | (&[ref hd1, ..], &[hd2, ..]) + | +++ + +error[E0508]: cannot move out of type `[T]`, a non-copy slice + --> $DIR/issue-12567.rs:2:11 + | +LL | match (l1, l2) { + | ^^^^^^^^ cannot move out of here +... +LL | (&[], &[hd, ..]) | (&[hd, ..], &[]) + | -- data moved here +LL | => println!("one empty"), +LL | (&[hd1, ..], &[hd2, ..]) + | --- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) + | +++ +help: consider borrowing the pattern binding + | +LL | (&[hd1, ..], &[ref hd2, ..]) + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/issues/issue-1257.rs b/tests/ui/issues/issue-1257.rs new file mode 100644 index 000000000..de5a6d359 --- /dev/null +++ b/tests/ui/issues/issue-1257.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main () { + let mut line = "".to_string(); + let mut i = 0; + while line != "exit".to_string() { + line = if i == 9 { "exit".to_string() } else { "notexit".to_string() }; + i += 1; + } +} diff --git a/tests/ui/issues/issue-12612.rs b/tests/ui/issues/issue-12612.rs new file mode 100644 index 000000000..d254f6941 --- /dev/null +++ b/tests/ui/issues/issue-12612.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_imports)] +// aux-build:issue-12612-1.rs +// aux-build:issue-12612-2.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_12612_1 as foo; +extern crate issue_12612_2 as bar; + +mod test { + use bar::baz; +} + +fn main() {} diff --git a/tests/ui/issues/issue-12660.rs b/tests/ui/issues/issue-12660.rs new file mode 100644 index 000000000..44c492b43 --- /dev/null +++ b/tests/ui/issues/issue-12660.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:issue-12660-aux.rs + +// pretty-expanded FIXME #23616 + +extern crate issue12660aux; + +use issue12660aux::{my_fn, MyStruct}; + +#[allow(path_statements)] +fn main() { + my_fn(MyStruct); + MyStruct; +} diff --git a/tests/ui/issues/issue-12677.rs b/tests/ui/issues/issue-12677.rs new file mode 100644 index 000000000..d0e4c17d4 --- /dev/null +++ b/tests/ui/issues/issue-12677.rs @@ -0,0 +1,9 @@ +// run-pass + +fn main() { + let s = "Hello"; + let first = s.bytes(); + let second = first.clone(); + + assert_eq!(first.collect::>(), second.collect::>()) +} diff --git a/tests/ui/issues/issue-12699.rs b/tests/ui/issues/issue-12699.rs new file mode 100644 index 000000000..e26c2d7cd --- /dev/null +++ b/tests/ui/issues/issue-12699.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-wasm32-bare can't block the thread +// ignore-sgx not supported +#![allow(deprecated)] + +use std::thread; + +fn main() { + thread::sleep_ms(250); +} diff --git a/tests/ui/issues/issue-12729.rs b/tests/ui/issues/issue-12729.rs new file mode 100644 index 000000000..aa0b04af2 --- /dev/null +++ b/tests/ui/issues/issue-12729.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub struct Foo; + +mod bar { + use Foo; + + impl Foo { + fn baz(&self) {} + } +} +fn main() {} diff --git a/tests/ui/issues/issue-12744.rs b/tests/ui/issues/issue-12744.rs new file mode 100644 index 000000000..e2756ec97 --- /dev/null +++ b/tests/ui/issues/issue-12744.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + fn test() -> Box { Box::new(1) } + println!("{:?}", test()) +} diff --git a/tests/ui/issues/issue-12860.rs b/tests/ui/issues/issue-12860.rs new file mode 100644 index 000000000..01b642cdf --- /dev/null +++ b/tests/ui/issues/issue-12860.rs @@ -0,0 +1,49 @@ +// run-pass +use std::collections::HashSet; + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct XYZ { + x: isize, + y: isize, + z: isize +} + +fn main() { + let mut connected = HashSet::new(); + let mut border = HashSet::new(); + + let middle = XYZ{x: 0, y: 0, z: 0}; + border.insert(middle); + + while !border.is_empty() && connected.len() < 10000 { + let choice = *(border.iter().next().unwrap()); + border.remove(&choice); + connected.insert(choice); + + let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z}; + let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z}; + let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z}; + let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z}; + let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1}; + let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1}; + + if !connected.contains(&cxp) { + border.insert(cxp); + } + if !connected.contains(&cxm){ + border.insert(cxm); + } + if !connected.contains(&cyp){ + border.insert(cyp); + } + if !connected.contains(&cym) { + border.insert(cym); + } + if !connected.contains(&czp){ + border.insert(czp); + } + if !connected.contains(&czm) { + border.insert(czm); + } + } +} diff --git a/tests/ui/issues/issue-12863.rs b/tests/ui/issues/issue-12863.rs new file mode 100644 index 000000000..1ac1c3d81 --- /dev/null +++ b/tests/ui/issues/issue-12863.rs @@ -0,0 +1,8 @@ +mod foo { pub fn bar() {} } + +fn main() { + match () { + foo::bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found function `foo::bar` + } +} diff --git a/tests/ui/issues/issue-12863.stderr b/tests/ui/issues/issue-12863.stderr new file mode 100644 index 000000000..9c29a37cb --- /dev/null +++ b/tests/ui/issues/issue-12863.stderr @@ -0,0 +1,9 @@ +error[E0532]: expected unit struct, unit variant or constant, found function `foo::bar` + --> $DIR/issue-12863.rs:5:9 + | +LL | foo::bar => {} + | ^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-12909.rs b/tests/ui/issues/issue-12909.rs new file mode 100644 index 000000000..a68d73a00 --- /dev/null +++ b/tests/ui/issues/issue-12909.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +use std::collections::HashMap; + +fn copy(&x: &T) -> T { + x +} + +fn main() { + let arr = [(1, 1), (2, 2), (3, 3)]; + + let v1: Vec<&_> = arr.iter().collect(); + let v2: Vec<_> = arr.iter().map(copy).collect(); + + let m1: HashMap<_, _> = arr.iter().map(copy).collect(); + let m2: HashMap = arr.iter().map(copy).collect(); + let m3: HashMap<_, usize> = arr.iter().map(copy).collect(); +} diff --git a/tests/ui/issues/issue-12920.rs b/tests/ui/issues/issue-12920.rs new file mode 100644 index 000000000..a0cfea055 --- /dev/null +++ b/tests/ui/issues/issue-12920.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +pub fn main() { + panic!(); + println!("{}", 1); +} diff --git a/tests/ui/issues/issue-12997-1.rs b/tests/ui/issues/issue-12997-1.rs new file mode 100644 index 000000000..9f808dac3 --- /dev/null +++ b/tests/ui/issues/issue-12997-1.rs @@ -0,0 +1,11 @@ +// compile-flags: --test + +//! Test that makes sure wrongly-typed bench functions aren't ignored + +#![feature(test)] + +#[bench] +fn foo() { } //~ ERROR functions used as benches + +#[bench] +fn bar(x: isize, y: isize) { } //~ ERROR functions used as benches diff --git a/tests/ui/issues/issue-12997-1.stderr b/tests/ui/issues/issue-12997-1.stderr new file mode 100644 index 000000000..00c605174 --- /dev/null +++ b/tests/ui/issues/issue-12997-1.stderr @@ -0,0 +1,14 @@ +error: functions used as benches must have signature `fn(&mut Bencher) -> impl Termination` + --> $DIR/issue-12997-1.rs:8:1 + | +LL | fn foo() { } + | ^^^^^^^^^^^^ + +error: functions used as benches must have signature `fn(&mut Bencher) -> impl Termination` + --> $DIR/issue-12997-1.rs:11:1 + | +LL | fn bar(x: isize, y: isize) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-12997-2.rs b/tests/ui/issues/issue-12997-2.rs new file mode 100644 index 000000000..9df965315 --- /dev/null +++ b/tests/ui/issues/issue-12997-2.rs @@ -0,0 +1,9 @@ +// compile-flags: --test + +//! Test that makes sure wrongly-typed bench functions are rejected + +#![feature(test)] + +#[bench] +fn bar(x: isize) { } +//~^ ERROR mismatched types diff --git a/tests/ui/issues/issue-12997-2.stderr b/tests/ui/issues/issue-12997-2.stderr new file mode 100644 index 000000000..2a3d0e345 --- /dev/null +++ b/tests/ui/issues/issue-12997-2.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-12997-2.rs:8:1 + | +LL | #[bench] + | -------- in this procedural macro expansion +LL | fn bar(x: isize) { } + | ^^^^^^^^^^^^^^^^^^^^ + | | + | expected `isize`, found `&mut Bencher` + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-12997-2.rs:8:4 + | +LL | fn bar(x: isize) { } + | ^^^ -------- + = note: this error originates in the attribute macro `bench` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13027.rs b/tests/ui/issues/issue-13027.rs new file mode 100644 index 000000000..64bf2a11d --- /dev/null +++ b/tests/ui/issues/issue-13027.rs @@ -0,0 +1,178 @@ +// run-pass + +// Tests that match expression handles overlapped literal and range +// properly in the presence of guard function. + +fn val() -> usize { 1 } + +static CONST: usize = 1; + +pub fn main() { + lit_shadow_range(); + range_shadow_lit(); + range_shadow_range(); + multi_pats_shadow_lit(); + multi_pats_shadow_range(); + lit_shadow_multi_pats(); + range_shadow_multi_pats(); + misc(); +} + +fn lit_shadow_range() { + assert_eq!(2, match 1 { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + let x = 0; + assert_eq!(2, match x+1 { + 0 => 0, + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + assert_eq!(2, match val() { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + assert_eq!(2, match CONST { + 0 => 0, + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); + + // value is out of the range of second arm, should match wildcard pattern + assert_eq!(3, match 3 { + 1 if false => 1, + 1..=2 => 2, + _ => 3 + }); +} + +fn range_shadow_lit() { + assert_eq!(2, match 1 { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + let x = 0; + assert_eq!(2, match x+1 { + 0 => 0, + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + assert_eq!(2, match val() { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + assert_eq!(2, match CONST { + 0 => 0, + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); + + // ditto + assert_eq!(3, match 3 { + 1..=2 if false => 1, + 1 => 2, + _ => 3 + }); +} + +fn range_shadow_range() { + assert_eq!(2, match 1 { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + let x = 0; + assert_eq!(2, match x+1 { + 100 => 0, + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + assert_eq!(2, match val() { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + assert_eq!(2, match CONST { + 100 => 0, + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); + + // ditto + assert_eq!(3, match 5 { + 0..=2 if false => 1, + 1..=3 => 2, + _ => 3, + }); +} + +fn multi_pats_shadow_lit() { + assert_eq!(2, match 1 { + 100 => 0, + 0 | 1..=10 if false => 1, + 1 => 2, + _ => 3, + }); +} + +fn multi_pats_shadow_range() { + assert_eq!(2, match 1 { + 100 => 0, + 0 | 1..=10 if false => 1, + 1..=3 => 2, + _ => 3, + }); +} + +fn lit_shadow_multi_pats() { + assert_eq!(2, match 1 { + 100 => 0, + 1 if false => 1, + 0 | 1..=10 => 2, + _ => 3, + }); +} + +fn range_shadow_multi_pats() { + assert_eq!(2, match 1 { + 100 => 0, + 1..=3 if false => 1, + 0 | 1..=10 => 2, + _ => 3, + }); +} + +fn misc() { + enum Foo { + Bar(#[allow(unused_tuple_struct_fields)] usize, bool) + } + // This test basically mimics how trace_macros! macro is implemented, + // which is a rare combination of vector patterns, multiple wild-card + // patterns and guard functions. + let r = match [Foo::Bar(0, false)] { + [Foo::Bar(_, pred)] if pred => 1, + [Foo::Bar(_, pred)] if !pred => 2, + _ => 0, + }; + assert_eq!(2, r); +} diff --git a/tests/ui/issues/issue-13033.rs b/tests/ui/issues/issue-13033.rs new file mode 100644 index 000000000..fdb356e70 --- /dev/null +++ b/tests/ui/issues/issue-13033.rs @@ -0,0 +1,14 @@ +trait Foo { + fn bar(&mut self, other: &mut dyn Foo); +} + +struct Baz; + +impl Foo for Baz { + fn bar(&mut self, other: &dyn Foo) {} + //~^ ERROR method `bar` has an incompatible type for trait + //~| expected signature `fn(&mut Baz, &mut dyn Foo)` + //~| found signature `fn(&mut Baz, &dyn Foo)` +} + +fn main() {} diff --git a/tests/ui/issues/issue-13033.stderr b/tests/ui/issues/issue-13033.stderr new file mode 100644 index 000000000..db2c1189e --- /dev/null +++ b/tests/ui/issues/issue-13033.stderr @@ -0,0 +1,20 @@ +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/issue-13033.rs:8:30 + | +LL | fn bar(&mut self, other: &dyn Foo) {} + | ^^^^^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `&mut dyn Foo` + | +note: type in trait + --> $DIR/issue-13033.rs:2:30 + | +LL | fn bar(&mut self, other: &mut dyn Foo); + | ^^^^^^^^^^^^ + = note: expected signature `fn(&mut Baz, &mut dyn Foo)` + found signature `fn(&mut Baz, &dyn Foo)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-13058.rs b/tests/ui/issues/issue-13058.rs new file mode 100644 index 000000000..a5806feb7 --- /dev/null +++ b/tests/ui/issues/issue-13058.rs @@ -0,0 +1,27 @@ +use std::ops::Range; + +trait Itble<'r, T, I: Iterator> { fn iter(&'r self) -> I; } + +impl<'r> Itble<'r, usize, Range> for (usize, usize) { + fn iter(&'r self) -> Range { + let &(min, max) = self; + min..max + } +} + +fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool +{ + let cont_iter = cont.iter(); +//~^ ERROR explicit lifetime required in the type of `cont` [E0621] + let result = cont_iter.fold(Some(0), |state, val| { + state.map_or(None, |mask| { + let bit = 1 << val; + if mask & bit == 0 {Some(mask|bit)} else {None} + }) + }); + result.is_some() +} + +fn main() { + check(&(3, 5)); +} diff --git a/tests/ui/issues/issue-13058.stderr b/tests/ui/issues/issue-13058.stderr new file mode 100644 index 000000000..8368978de --- /dev/null +++ b/tests/ui/issues/issue-13058.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `cont` + --> $DIR/issue-13058.rs:14:21 + | +LL | fn check<'r, I: Iterator, T: Itble<'r, usize, I>>(cont: &T) -> bool + | -- help: add explicit lifetime `'r` to the type of `cont`: `&'r T` +LL | { +LL | let cont_iter = cont.iter(); + | ^^^^^^^^^^^ lifetime `'r` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-13105.rs b/tests/ui/issues/issue-13105.rs new file mode 100644 index 000000000..15a98c779 --- /dev/null +++ b/tests/ui/issues/issue-13105.rs @@ -0,0 +1,9 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait Foo { + #[allow(anonymous_parameters)] + fn quux(u8) {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-13167.rs b/tests/ui/issues/issue-13167.rs new file mode 100644 index 000000000..8584c98de --- /dev/null +++ b/tests/ui/issues/issue-13167.rs @@ -0,0 +1,22 @@ +// check-pass +// pretty-expanded FIXME #23616 + +use std::slice; + +pub struct PhfMapEntries<'a, T: 'a> { + iter: slice::Iter<'a, (&'static str, T)>, +} + +impl<'a, T> Iterator for PhfMapEntries<'a, T> { + type Item = (&'static str, &'a T); + + fn next(&mut self) -> Option<(&'static str, &'a T)> { + self.iter.by_ref().map(|&(key, ref value)| (key, value)).next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-13202.rs b/tests/ui/issues/issue-13202.rs new file mode 100644 index 000000000..16debb5b6 --- /dev/null +++ b/tests/ui/issues/issue-13202.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:bad input +// ignore-emscripten no processes + +fn main() { + Some("foo").unwrap_or(panic!("bad input")).to_string(); +} diff --git a/tests/ui/issues/issue-13204.rs b/tests/ui/issues/issue-13204.rs new file mode 100644 index 000000000..3d6aba845 --- /dev/null +++ b/tests/ui/issues/issue-13204.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_mut)] +// Test that when instantiating trait default methods, typeck handles +// lifetime parameters defined on the method bound correctly. + + +pub trait Foo { + fn bar<'a, I: Iterator>(&self, it: I) -> usize { + let mut xs = it.filter(|_| true); + xs.count() + } +} + +pub struct Baz; + +impl Foo for Baz { + // When instantiating `Foo::bar` for `Baz` here, typeck used to + // ICE due to the lifetime parameter of `bar`. +} + +fn main() { + let x = Baz; + let y = vec![(), (), ()]; + assert_eq!(x.bar(y.iter()), 3); +} diff --git a/tests/ui/issues/issue-13214.rs b/tests/ui/issues/issue-13214.rs new file mode 100644 index 000000000..0cf8d0675 --- /dev/null +++ b/tests/ui/issues/issue-13214.rs @@ -0,0 +1,23 @@ +// build-pass +#![allow(dead_code)] +// defining static with struct that contains enum +// with &'static str variant used to cause ICE + +// pretty-expanded FIXME #23616 + +pub enum Foo { + Bar, + Baz(&'static str), +} + +pub static TEST: Test = Test { + foo: Foo::Bar, + c: 'a' +}; + +pub struct Test { + foo: Foo, + c: char, +} + +fn main() {} diff --git a/tests/ui/issues/issue-13259-windows-tcb-trash.rs b/tests/ui/issues/issue-13259-windows-tcb-trash.rs new file mode 100644 index 000000000..740e7780d --- /dev/null +++ b/tests/ui/issues/issue-13259-windows-tcb-trash.rs @@ -0,0 +1,42 @@ +// run-pass +#![feature(rustc_private)] + +extern crate libc; + +#[cfg(windows)] +mod imp { + type LPVOID = *mut u8; + type DWORD = u32; + type LPWSTR = *mut u16; + + extern "system" { + fn FormatMessageW(flags: DWORD, + lpSrc: LPVOID, + msgId: DWORD, + langId: DWORD, + buf: LPWSTR, + nsize: DWORD, + args: *const u8) + -> DWORD; + } + + pub fn test() { + let mut buf: [u16; 50] = [0; 50]; + let ret = unsafe { + FormatMessageW(0x1000, core::ptr::null_mut(), 1, 0x400, + buf.as_mut_ptr(), buf.len() as u32, core::ptr::null()) + }; + // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented + // stacks taking control of pvArbitrary + assert!(ret != 0); + } +} + +#[cfg(not(windows))] +mod imp { + pub fn test() { } +} + +fn main() { + imp::test() +} diff --git a/tests/ui/issues/issue-13264.rs b/tests/ui/issues/issue-13264.rs new file mode 100644 index 000000000..691bb63a2 --- /dev/null +++ b/tests/ui/issues/issue-13264.rs @@ -0,0 +1,74 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::ops::Deref; + +struct Root { + jsref: JSRef +} + +impl Deref for Root { + type Target = JSRef; + + fn deref<'a>(&'a self) -> &'a JSRef { + &self.jsref + } +} + +#[derive(Copy, Clone)] +struct JSRef { + node: *const Node +} + +impl Deref for JSRef { + type Target = Node; + + fn deref<'a>(&'a self) -> &'a Node { + self.get() + } +} + +trait INode { + fn RemoveChild(&self); +} + +impl INode for JSRef { + fn RemoveChild(&self) { + self.get().RemoveChild(0) + } +} + +impl JSRef { + fn AddChild(&self) { + self.get().AddChild(0); + } + + fn get<'a>(&'a self) -> &'a Node { + unsafe { + &*self.node + } + } +} + +struct Node; + +impl Node { + fn RemoveChild(&self, _a: usize) { + } + + fn AddChild(&self, _a: usize) { + } +} + +fn main() { + let n = Node; + let jsref = JSRef { node: &n }; + let root = Root { jsref: jsref }; + + root.AddChild(); + jsref.AddChild(); + + root.RemoveChild(); + jsref.RemoveChild(); +} diff --git a/tests/ui/issues/issue-13323.rs b/tests/ui/issues/issue-13323.rs new file mode 100644 index 000000000..71e14d4da --- /dev/null +++ b/tests/ui/issues/issue-13323.rs @@ -0,0 +1,58 @@ +// run-pass + +struct StrWrap { + s: String +} + +impl StrWrap { + fn new(s: &str) -> StrWrap { + StrWrap { s: s.to_string() } + } + + fn get_s<'a>(&'a self) -> &'a str { + &self.s + } +} + +struct MyStruct { + s: StrWrap +} + +impl MyStruct { + fn new(s: &str) -> MyStruct { + MyStruct { s: StrWrap::new(s) } + } + + fn get_str_wrap<'a>(&'a self) -> &'a StrWrap { + &self.s + } +} + +trait Matcher { + fn matches(&self, actual: T) -> bool; +} + +fn assert_that>(actual: T, matcher: &U) { + assert!(matcher.matches(actual)); +} + +struct EqualTo { + expected: T +} + +impl Matcher for EqualTo { + fn matches(&self, actual: T) -> bool { + self.expected.eq(&actual) + } +} + +fn equal_to(expected: T) -> Box> { + Box::new(EqualTo { expected: expected }) +} + +pub fn main() { + let my_struct = MyStruct::new("zomg"); + let s = my_struct.get_str_wrap(); + + assert_that(s.get_s(), &*equal_to("zomg")); +} diff --git a/tests/ui/issues/issue-13359.rs b/tests/ui/issues/issue-13359.rs new file mode 100644 index 000000000..9129790c5 --- /dev/null +++ b/tests/ui/issues/issue-13359.rs @@ -0,0 +1,13 @@ +fn foo(_s: i16) { } + +fn bar(_s: u32) { } + +fn main() { + foo(1*(1 as isize)); + //~^ ERROR mismatched types + //~| expected `i16`, found `isize` + + bar(1*(1 as usize)); + //~^ ERROR mismatched types + //~| expected `u32`, found `usize` +} diff --git a/tests/ui/issues/issue-13359.stderr b/tests/ui/issues/issue-13359.stderr new file mode 100644 index 000000000..fef63680a --- /dev/null +++ b/tests/ui/issues/issue-13359.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/issue-13359.rs:6:9 + | +LL | foo(1*(1 as isize)); + | --- ^^^^^^^^^^^^^^ expected `i16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-13359.rs:1:4 + | +LL | fn foo(_s: i16) { } + | ^^^ ------- +help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit + | +LL | foo((1*(1 as isize)).try_into().unwrap()); + | + +++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-13359.rs:10:9 + | +LL | bar(1*(1 as usize)); + | --- ^^^^^^^^^^^^^^ expected `u32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-13359.rs:3:4 + | +LL | fn bar(_s: u32) { } + | ^^^ ------- +help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit + | +LL | bar((1*(1 as usize)).try_into().unwrap()); + | + +++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13405.rs b/tests/ui/issues/issue-13405.rs new file mode 100644 index 000000000..732172b23 --- /dev/null +++ b/tests/ui/issues/issue-13405.rs @@ -0,0 +1,20 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct Foo<'a> { + i: &'a bool, + j: Option<&'a isize>, +} + +impl<'a> Foo<'a> { + fn bar(&mut self, j: &isize) { + let child = Foo { + i: self.i, + j: Some(j) + }; + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-13407.rs b/tests/ui/issues/issue-13407.rs new file mode 100644 index 000000000..7ea81ffb5 --- /dev/null +++ b/tests/ui/issues/issue-13407.rs @@ -0,0 +1,9 @@ +mod A { + struct C; +} + +fn main() { + A::C = 1; + //~^ ERROR: invalid left-hand side of assignment + //~| ERROR: struct `C` is private +} diff --git a/tests/ui/issues/issue-13407.stderr b/tests/ui/issues/issue-13407.stderr new file mode 100644 index 000000000..54b6c640d --- /dev/null +++ b/tests/ui/issues/issue-13407.stderr @@ -0,0 +1,24 @@ +error[E0603]: unit struct `C` is private + --> $DIR/issue-13407.rs:6:8 + | +LL | A::C = 1; + | ^ private unit struct + | +note: the unit struct `C` is defined here + --> $DIR/issue-13407.rs:2:5 + | +LL | struct C; + | ^^^^^^^^^ + +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-13407.rs:6:10 + | +LL | A::C = 1; + | ---- ^ + | | + | cannot assign to this expression + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0070, E0603. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/issues/issue-13434.rs b/tests/ui/issues/issue-13434.rs new file mode 100644 index 000000000..1b7d3e201 --- /dev/null +++ b/tests/ui/issues/issue-13434.rs @@ -0,0 +1,21 @@ +// run-pass +#[derive(Debug)] +struct MyStruct; + +trait Repro { + fn repro(self, s: MyStruct) -> String; +} + +impl Repro for F where F: FnOnce(MyStruct) -> String { + fn repro(self, s: MyStruct) -> String { + self(s) + } +} + +fn do_stuff(r: R) -> String { + r.repro(MyStruct) +} + +pub fn main() { + assert_eq!("MyStruct".to_string(), do_stuff(|s: MyStruct| format!("{:?}", s))); +} diff --git a/tests/ui/issues/issue-13446.rs b/tests/ui/issues/issue-13446.rs new file mode 100644 index 000000000..9f1fc4277 --- /dev/null +++ b/tests/ui/issues/issue-13446.rs @@ -0,0 +1,6 @@ +// Used to cause ICE + +static VEC: [u32; 256] = vec![]; +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/issues/issue-13446.stderr b/tests/ui/issues/issue-13446.stderr new file mode 100644 index 000000000..30fb73dd3 --- /dev/null +++ b/tests/ui/issues/issue-13446.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/issue-13446.rs:3:26 + | +LL | static VEC: [u32; 256] = vec![]; + | ^^^^^^ expected array `[u32; 256]`, found struct `Vec` + | + = note: expected array `[u32; 256]` + found struct `Vec<_>` + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13466.rs b/tests/ui/issues/issue-13466.rs new file mode 100644 index 000000000..a420c7704 --- /dev/null +++ b/tests/ui/issues/issue-13466.rs @@ -0,0 +1,20 @@ +// Regression test for #13466 + +pub fn main() { + // The expected arm type `Option` has one type parameter, while + // the actual arm `Result` has two. typeck should not be + // tricked into looking up a non-existing second type parameter. + let _x: usize = match Some(1) { + Ok(u) => u, + //~^ ERROR mismatched types + //~| expected enum `Option<{integer}>` + //~| found enum `Result<_, _>` + //~| expected enum `Option`, found enum `Result` + + Err(e) => panic!(e) + //~^ ERROR mismatched types + //~| expected enum `Option<{integer}>` + //~| found enum `Result<_, _>` + //~| expected enum `Option`, found enum `Result` + }; +} diff --git a/tests/ui/issues/issue-13466.stderr b/tests/ui/issues/issue-13466.stderr new file mode 100644 index 000000000..c78466f4e --- /dev/null +++ b/tests/ui/issues/issue-13466.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-13466.rs:8:9 + | +LL | let _x: usize = match Some(1) { + | ------- this expression has type `Option<{integer}>` +LL | Ok(u) => u, + | ^^^^^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option<{integer}>` + found enum `Result<_, _>` + +error[E0308]: mismatched types + --> $DIR/issue-13466.rs:14:9 + | +LL | let _x: usize = match Some(1) { + | ------- this expression has type `Option<{integer}>` +... +LL | Err(e) => panic!(e) + | ^^^^^^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option<{integer}>` + found enum `Result<_, _>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13482-2.rs b/tests/ui/issues/issue-13482-2.rs new file mode 100644 index 000000000..bbcb954af --- /dev/null +++ b/tests/ui/issues/issue-13482-2.rs @@ -0,0 +1,9 @@ +// compile-flags:-Z verbose + +fn main() { + let x = [1,2]; + let y = match x { + [] => None, //~ ERROR pattern requires 0 elements but array has 2 + [a,_] => Some(a) + }; +} diff --git a/tests/ui/issues/issue-13482-2.stderr b/tests/ui/issues/issue-13482-2.stderr new file mode 100644 index 000000000..ccab95878 --- /dev/null +++ b/tests/ui/issues/issue-13482-2.stderr @@ -0,0 +1,9 @@ +error[E0527]: pattern requires 0 elements but array has 2 + --> $DIR/issue-13482-2.rs:6:9 + | +LL | [] => None, + | ^^ expected 2 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/issues/issue-13482.rs b/tests/ui/issues/issue-13482.rs new file mode 100644 index 000000000..244b3237e --- /dev/null +++ b/tests/ui/issues/issue-13482.rs @@ -0,0 +1,7 @@ +fn main() { + let x = [1,2]; + let y = match x { + [] => None, //~ ERROR pattern requires 0 elements but array has 2 + [a,_] => Some(a) + }; +} diff --git a/tests/ui/issues/issue-13482.stderr b/tests/ui/issues/issue-13482.stderr new file mode 100644 index 000000000..3eb05f504 --- /dev/null +++ b/tests/ui/issues/issue-13482.stderr @@ -0,0 +1,9 @@ +error[E0527]: pattern requires 0 elements but array has 2 + --> $DIR/issue-13482.rs:4:5 + | +LL | [] => None, + | ^^ expected 2 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/issues/issue-13497-2.rs b/tests/ui/issues/issue-13497-2.rs new file mode 100644 index 000000000..c82da0f00 --- /dev/null +++ b/tests/ui/issues/issue-13497-2.rs @@ -0,0 +1,7 @@ +fn read_lines_borrowed<'a>() -> Vec<&'a str> { + let rawLines: Vec = vec!["foo ".to_string(), " bar".to_string()]; + rawLines //~ ERROR cannot return value referencing local variable `rawLines` + .iter().map(|l| l.trim()).collect() +} + +fn main() {} diff --git a/tests/ui/issues/issue-13497-2.stderr b/tests/ui/issues/issue-13497-2.stderr new file mode 100644 index 000000000..a365e24e2 --- /dev/null +++ b/tests/ui/issues/issue-13497-2.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `rawLines` + --> $DIR/issue-13497-2.rs:3:5 + | +LL | // rawLines +LL | || .iter().map(|l| l.trim()).collect() + | ||_______________-___________________________^ returns a value referencing data owned by the current function + | |_______________| + | `rawLines` is borrowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-13497.rs b/tests/ui/issues/issue-13497.rs new file mode 100644 index 000000000..4b2795aa8 --- /dev/null +++ b/tests/ui/issues/issue-13497.rs @@ -0,0 +1,8 @@ +fn read_lines_borrowed1() -> Vec< + &str //~ ERROR missing lifetime specifier +> { + let rawLines: Vec = vec!["foo ".to_string(), " bar".to_string()]; + rawLines.iter().map(|l| l.trim()).collect() +} + +fn main() {} diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr new file mode 100644 index 000000000..4b1d979da --- /dev/null +++ b/tests/ui/issues/issue-13497.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-13497.rs:2:5 + | +LL | &str + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | &'static str + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-13507-2.rs b/tests/ui/issues/issue-13507-2.rs new file mode 100644 index 000000000..63f3589c6 --- /dev/null +++ b/tests/ui/issues/issue-13507-2.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(unused_imports)] +// aux-build:issue-13507.rs + +extern crate issue_13507; +use issue_13507::testtypes; + +use std::any::TypeId; + +pub fn type_ids() -> Vec { + use issue_13507::testtypes::*; + vec![ + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::() + ] +} + +pub fn main() { + let othercrate = issue_13507::testtypes::type_ids(); + let thiscrate = type_ids(); + assert_eq!(thiscrate, othercrate); +} diff --git a/tests/ui/issues/issue-1362.rs b/tests/ui/issues/issue-1362.rs new file mode 100644 index 000000000..6fd43f50e --- /dev/null +++ b/tests/ui/issues/issue-1362.rs @@ -0,0 +1,8 @@ +// Regression test for issue #1362 - without that fix the span will be bogus +// no-reformat +fn main() { + let x: u32 = 20i32; //~ ERROR mismatched types +} +// NOTE: Do not add any extra lines as the line number the error is +// on is significant; an error later in the source file might not +// trigger the bug. diff --git a/tests/ui/issues/issue-1362.stderr b/tests/ui/issues/issue-1362.stderr new file mode 100644 index 000000000..babbb6e51 --- /dev/null +++ b/tests/ui/issues/issue-1362.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-1362.rs:4:16 + | +LL | let x: u32 = 20i32; + | --- ^^^^^ expected `u32`, found `i32` + | | + | expected due to this + | +help: change the type of the numeric literal from `i32` to `u32` + | +LL | let x: u32 = 20u32; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13620.rs b/tests/ui/issues/issue-13620.rs new file mode 100644 index 000000000..3c3c19df7 --- /dev/null +++ b/tests/ui/issues/issue-13620.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-13620-1.rs +// aux-build:issue-13620-2.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_13620_2 as crate2; + +fn main() { + (crate2::FOO2.foo)(); +} diff --git a/tests/ui/issues/issue-13665.rs b/tests/ui/issues/issue-13665.rs new file mode 100644 index 000000000..a3843c650 --- /dev/null +++ b/tests/ui/issues/issue-13665.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn foo<'r>() { + let maybe_value_ref: Option<&'r u8> = None; + + let _ = maybe_value_ref.map(|& ref v| v); + let _ = maybe_value_ref.map(|& ref v| -> &'r u8 {v}); + let _ = maybe_value_ref.map(|& ref v: &'r u8| -> &'r u8 {v}); + let _ = maybe_value_ref.map(|& ref v: &'r u8| {v}); +} + +fn main() { + foo(); +} diff --git a/tests/ui/issues/issue-13703.rs b/tests/ui/issues/issue-13703.rs new file mode 100644 index 000000000..424c99974 --- /dev/null +++ b/tests/ui/issues/issue-13703.rs @@ -0,0 +1,6 @@ +// check-pass +// pretty-expanded FIXME #23616 + +pub struct Foo<'a, 'b: 'a> { foo: &'a &'b isize } +pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<& & ()>) { let _y = x.foo; } +fn main() {} diff --git a/tests/ui/issues/issue-13763.rs b/tests/ui/issues/issue-13763.rs new file mode 100644 index 000000000..dd5f6dbc9 --- /dev/null +++ b/tests/ui/issues/issue-13763.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +mod u8 { + pub const BITS: usize = 8; +} + +const NUM: usize = u8::BITS; + +struct MyStruct { nums: [usize; 8] } + +fn main() { + let _s = MyStruct { nums: [0; NUM] }; +} diff --git a/tests/ui/issues/issue-13775.rs b/tests/ui/issues/issue-13775.rs new file mode 100644 index 000000000..f5977effc --- /dev/null +++ b/tests/ui/issues/issue-13775.rs @@ -0,0 +1,9 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait Foo { + #[allow(anonymous_parameters)] + fn bar(&self, isize) {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-13808.rs b/tests/ui/issues/issue-13808.rs new file mode 100644 index 000000000..9f9db067b --- /dev/null +++ b/tests/ui/issues/issue-13808.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct Foo<'a> { + listener: Box, +} + +impl<'a> Foo<'a> { + fn new(listener: F) -> Foo<'a> where F: FnMut() + 'a { + Foo { listener: Box::new(listener) } + } +} + +fn main() { + let a = Foo::new(|| {}); +} diff --git a/tests/ui/issues/issue-13847.rs b/tests/ui/issues/issue-13847.rs new file mode 100644 index 000000000..06a0304ae --- /dev/null +++ b/tests/ui/issues/issue-13847.rs @@ -0,0 +1,3 @@ +fn main() { + return.is_failure //~ ERROR no field `is_failure` on type `!` +} diff --git a/tests/ui/issues/issue-13847.stderr b/tests/ui/issues/issue-13847.stderr new file mode 100644 index 000000000..52b8dc049 --- /dev/null +++ b/tests/ui/issues/issue-13847.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `is_failure` on type `!` + --> $DIR/issue-13847.rs:2:12 + | +LL | return.is_failure + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-13867.rs b/tests/ui/issues/issue-13867.rs new file mode 100644 index 000000000..9510aae77 --- /dev/null +++ b/tests/ui/issues/issue-13867.rs @@ -0,0 +1,48 @@ +// run-pass +// Test that codegen works correctly when there are multiple refutable +// patterns in match expression. + +enum Foo { + FooUint(usize), + FooNullary, +} + +fn main() { + let r = match (Foo::FooNullary, 'a') { + (Foo::FooUint(..), 'a'..='z') => 1, + (Foo::FooNullary, 'x') => 2, + _ => 0 + }; + assert_eq!(r, 0); + + let r = match (Foo::FooUint(0), 'a') { + (Foo::FooUint(1), 'a'..='z') => 1, + (Foo::FooUint(..), 'x') => 2, + (Foo::FooNullary, 'a') => 3, + _ => 0 + }; + assert_eq!(r, 0); + + let r = match ('a', Foo::FooUint(0)) { + ('a'..='z', Foo::FooUint(1)) => 1, + ('x', Foo::FooUint(..)) => 2, + ('a', Foo::FooNullary) => 3, + _ => 0 + }; + assert_eq!(r, 0); + + let r = match ('a', 'a') { + ('a'..='z', 'b') => 1, + ('x', 'a'..='z') => 2, + _ => 0 + }; + assert_eq!(r, 0); + + let r = match ('a', 'a') { + ('a'..='z', 'b') => 1, + ('x', 'a'..='z') => 2, + ('a', 'a') => 3, + _ => 0 + }; + assert_eq!(r, 3); +} diff --git a/tests/ui/issues/issue-13872.rs b/tests/ui/issues/issue-13872.rs new file mode 100644 index 000000000..aade6b836 --- /dev/null +++ b/tests/ui/issues/issue-13872.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:issue-13872-1.rs +// aux-build:issue-13872-2.rs +// aux-build:issue-13872-3.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_13872_3 as other; + +fn main() { + other::foo(); +} diff --git a/tests/ui/issues/issue-14082.rs b/tests/ui/issues/issue-14082.rs new file mode 100644 index 000000000..52b8c8680 --- /dev/null +++ b/tests/ui/issues/issue-14082.rs @@ -0,0 +1,20 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#![allow(unused_imports, dead_code)] + +use foo::Foo; + +mod foo { + pub use m::Foo; // this should shadow d::Foo +} + +mod m { + pub struct Foo; +} + +mod d { + pub struct Foo; +} + +fn main() {} diff --git a/tests/ui/issues/issue-14091-2.rs b/tests/ui/issues/issue-14091-2.rs new file mode 100644 index 000000000..e2f6b1833 --- /dev/null +++ b/tests/ui/issues/issue-14091-2.rs @@ -0,0 +1,17 @@ +// + +// Very + +// sensitive +pub struct BytePos(pub u32); + +// to particular + +// line numberings / offsets + +fn main() { + let x = BytePos(1); + + assert!(x, x); + //~^ ERROR cannot apply unary operator `!` to type `BytePos` +} diff --git a/tests/ui/issues/issue-14091-2.stderr b/tests/ui/issues/issue-14091-2.stderr new file mode 100644 index 000000000..f8375d4ef --- /dev/null +++ b/tests/ui/issues/issue-14091-2.stderr @@ -0,0 +1,18 @@ +error[E0600]: cannot apply unary operator `!` to type `BytePos` + --> $DIR/issue-14091-2.rs:15:5 + | +LL | assert!(x, x); + | ^^^^^^^^^^^^^ cannot apply unary operator `!` + | +note: an implementation of `Not` might be missing for `BytePos` + --> $DIR/issue-14091-2.rs:6:1 + | +LL | pub struct BytePos(pub u32); + | ^^^^^^^^^^^^^^^^^^ must implement `Not` +note: the trait `Not` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/issues/issue-14091.rs b/tests/ui/issues/issue-14091.rs new file mode 100644 index 000000000..0ee20de90 --- /dev/null +++ b/tests/ui/issues/issue-14091.rs @@ -0,0 +1,4 @@ +fn main(){ + assert!(1,1); + //~^ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-14091.stderr b/tests/ui/issues/issue-14091.stderr new file mode 100644 index 000000000..0a9640a9e --- /dev/null +++ b/tests/ui/issues/issue-14091.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-14091.rs:2:5 + | +LL | assert!(1,1); + | ^^^^^^^^^^^^ expected `bool`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-14092.rs b/tests/ui/issues/issue-14092.rs new file mode 100644 index 000000000..67c2a42ea --- /dev/null +++ b/tests/ui/issues/issue-14092.rs @@ -0,0 +1,4 @@ +fn fn1(0: Box) {} +//~^ ERROR missing generics for struct `Box` + +fn main() {} diff --git a/tests/ui/issues/issue-14092.stderr b/tests/ui/issues/issue-14092.stderr new file mode 100644 index 000000000..3a43627e6 --- /dev/null +++ b/tests/ui/issues/issue-14092.stderr @@ -0,0 +1,14 @@ +error[E0107]: missing generics for struct `Box` + --> $DIR/issue-14092.rs:1:11 + | +LL | fn fn1(0: Box) {} + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | fn fn1(0: Box) {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-14229.rs b/tests/ui/issues/issue-14229.rs new file mode 100644 index 000000000..477a2c650 --- /dev/null +++ b/tests/ui/issues/issue-14229.rs @@ -0,0 +1,21 @@ +// run-pass +trait Foo: Sized { + fn foo(self) {} +} + +trait Bar: Sized { + fn bar(self) {} +} + +struct S; + +impl<'l> Foo for &'l S {} + +impl Bar for T {} + +fn main() { + let s = S; + s.foo(); + (&s).bar(); + s.bar(); +} diff --git a/tests/ui/issues/issue-14254.rs b/tests/ui/issues/issue-14254.rs new file mode 100644 index 000000000..6f9308376 --- /dev/null +++ b/tests/ui/issues/issue-14254.rs @@ -0,0 +1,93 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait Foo: Sized { + fn bar(&self); + fn baz(&self) { } + fn bah(_: Option) { } +} + +struct BarTy { + x : isize, + y : f64, +} + +impl BarTy { + fn a() {} + fn b(&self) {} +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl Foo for *const BarTy { + fn bar(&self) { + self.baz(); + BarTy::a(); + Foo::bah(None::<*const BarTy>); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl<'a> Foo for &'a BarTy { + fn bar(&self) { + self.baz(); + self.x; + self.y; + BarTy::a(); + Foo::bah(None::<&BarTy>); + self.b(); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl<'a> Foo for &'a mut BarTy { + fn bar(&self) { + self.baz(); + self.x; + self.y; + BarTy::a(); + Foo::bah(None::<&mut BarTy>); + self.b(); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl Foo for Box { + fn bar(&self) { + self.baz(); + Foo::bah(None::>); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl Foo for *const isize { + fn bar(&self) { + self.baz(); + Foo::bah(None::<*const isize>); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl<'a> Foo for &'a isize { + fn bar(&self) { + self.baz(); + Foo::bah(None::<&isize>); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl<'a> Foo for &'a mut isize { + fn bar(&self) { + self.baz(); + Foo::bah(None::<&mut isize>); + } +} + +// If these fail, it's necessary to update rustc_resolve and the cfail tests. +impl Foo for Box { + fn bar(&self) { + self.baz(); + Foo::bah(None::>); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-14285.rs b/tests/ui/issues/issue-14285.rs new file mode 100644 index 000000000..2ba9ff717 --- /dev/null +++ b/tests/ui/issues/issue-14285.rs @@ -0,0 +1,17 @@ +trait Foo { + fn dummy(&self) { } +} + +struct A; + +impl Foo for A {} + +struct B<'a>(&'a (dyn Foo + 'a)); + +fn foo<'a>(a: &dyn Foo) -> B<'a> { + B(a) //~ ERROR explicit lifetime required in the type of `a` [E0621] +} + +fn main() { + let _test = foo(&A); +} diff --git a/tests/ui/issues/issue-14285.stderr b/tests/ui/issues/issue-14285.stderr new file mode 100644 index 000000000..5c0706601 --- /dev/null +++ b/tests/ui/issues/issue-14285.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `a` + --> $DIR/issue-14285.rs:12:5 + | +LL | fn foo<'a>(a: &dyn Foo) -> B<'a> { + | -------- help: add explicit lifetime `'a` to the type of `a`: `&'a (dyn Foo + 'a)` +LL | B(a) + | ^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-14308.rs b/tests/ui/issues/issue-14308.rs new file mode 100644 index 000000000..e067bcdf3 --- /dev/null +++ b/tests/ui/issues/issue-14308.rs @@ -0,0 +1,15 @@ +// run-pass + +struct A(isize); + +fn main() { + let x = match A(3) { + A(..) => 1 + }; + assert_eq!(x, 1); + let x = match A(4) { + A(1) => 1, + A(..) => 2 + }; + assert_eq!(x, 2); +} diff --git a/tests/ui/issues/issue-14330.rs b/tests/ui/issues/issue-14330.rs new file mode 100644 index 000000000..0844fc720 --- /dev/null +++ b/tests/ui/issues/issue-14330.rs @@ -0,0 +1,7 @@ +// check-pass +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 + +#[macro_use] extern crate std as std2; + +fn main() {} diff --git a/tests/ui/issues/issue-14344.rs b/tests/ui/issues/issue-14344.rs new file mode 100644 index 000000000..33b1df827 --- /dev/null +++ b/tests/ui/issues/issue-14344.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-14344-1.rs +// aux-build:issue-14344-2.rs + +extern crate issue_14344_1; +extern crate issue_14344_2; + +fn main() { + issue_14344_1::foo(); + issue_14344_2::bar(); +} diff --git a/tests/ui/issues/issue-14366.rs b/tests/ui/issues/issue-14366.rs new file mode 100644 index 000000000..bb338860d --- /dev/null +++ b/tests/ui/issues/issue-14366.rs @@ -0,0 +1,4 @@ +fn main() { + let _x = "test" as &dyn (::std::any::Any); + //~^ ERROR the size for values of type +} diff --git a/tests/ui/issues/issue-14366.stderr b/tests/ui/issues/issue-14366.stderr new file mode 100644 index 000000000..10a73b245 --- /dev/null +++ b/tests/ui/issues/issue-14366.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-14366.rs:2:14 + | +LL | let _x = "test" as &dyn (::std::any::Any); + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn Any` +help: consider borrowing the value, since `&str` can be coerced into `dyn Any` + | +LL | let _x = &"test" as &dyn (::std::any::Any); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-14382.rs b/tests/ui/issues/issue-14382.rs new file mode 100644 index 000000000..dca24d0be --- /dev/null +++ b/tests/ui/issues/issue-14382.rs @@ -0,0 +1,15 @@ +// run-pass +#[derive(Debug)] +struct Matrix4(#[allow(unused_tuple_struct_fields)] S); +trait POrd {} + +fn translate>(s: S) -> Matrix4 { Matrix4(s) } + +impl POrd for f32 {} +impl POrd for f64 {} + +fn main() { + let x = 1.0; + let m : Matrix4 = translate(x); + println!("m: {:?}", m); +} diff --git a/tests/ui/issues/issue-14393.rs b/tests/ui/issues/issue-14393.rs new file mode 100644 index 000000000..df635407a --- /dev/null +++ b/tests/ui/issues/issue-14393.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + match ("", 1_usize) { + (_, 42_usize) => (), + ("", _) => (), + _ => () + } +} diff --git a/tests/ui/issues/issue-14399.rs b/tests/ui/issues/issue-14399.rs new file mode 100644 index 000000000..7b32bf8e4 --- /dev/null +++ b/tests/ui/issues/issue-14399.rs @@ -0,0 +1,18 @@ +// run-pass +// #14399 +// We'd previously ICE if we had a method call whose return +// value was coerced to a trait object. (v.clone() returns Box +// which is coerced to Box). + +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +struct B1; + +trait A { fn foo(&self) {} } +impl A for B1 {} + +fn main() { + let v: Box<_> = Box::new(B1); + let _c: Box = v.clone(); +} diff --git a/tests/ui/issues/issue-14421.rs b/tests/ui/issues/issue-14421.rs new file mode 100644 index 000000000..c59bd8706 --- /dev/null +++ b/tests/ui/issues/issue-14421.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_snake_case)] + +// aux-build:issue-14421.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_14421 as bug_lib; + +use bug_lib::B; +use bug_lib::make; + +pub fn main() { + let mut an_A: B = make(); + an_A.foo(); +} diff --git a/tests/ui/issues/issue-14422.rs b/tests/ui/issues/issue-14422.rs new file mode 100644 index 000000000..b9e2065d0 --- /dev/null +++ b/tests/ui/issues/issue-14422.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_snake_case)] + +// aux-build:issue-14422.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_14422 as bug_lib; + +use bug_lib::B; +use bug_lib::make; + +pub fn main() { + let mut an_A: B = make(); + an_A.foo(); +} diff --git a/tests/ui/issues/issue-1448-2.rs b/tests/ui/issues/issue-1448-2.rs new file mode 100644 index 000000000..829e81b9c --- /dev/null +++ b/tests/ui/issues/issue-1448-2.rs @@ -0,0 +1,7 @@ +// Regression test for issue #1448 and #1386 + +fn foo(a: u32) -> u32 { a } + +fn main() { + println!("{}", foo(10i32)); //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-1448-2.stderr b/tests/ui/issues/issue-1448-2.stderr new file mode 100644 index 000000000..203dd92c9 --- /dev/null +++ b/tests/ui/issues/issue-1448-2.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-1448-2.rs:6:24 + | +LL | println!("{}", foo(10i32)); + | --- ^^^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-1448-2.rs:3:4 + | +LL | fn foo(a: u32) -> u32 { a } + | ^^^ ------ +help: change the type of the numeric literal from `i32` to `u32` + | +LL | println!("{}", foo(10u32)); + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-1451.rs b/tests/ui/issues/issue-1451.rs new file mode 100644 index 000000000..ad8928b20 --- /dev/null +++ b/tests/ui/issues/issue-1451.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![allow(non_snake_case)] +#![allow(unused_variables)] + +struct T { f: extern "Rust" fn() } +struct S { f: extern "Rust" fn() } + +fn fooS(t: S) { +} + +fn fooT(t: T) { +} + +fn bar() { +} + +pub fn main() { + let x: extern "Rust" fn() = bar; + fooS(S {f: x}); + fooS(S {f: bar}); + + let x: extern "Rust" fn() = bar; + fooT(T {f: x}); + fooT(T {f: bar}); +} diff --git a/tests/ui/issues/issue-14541.rs b/tests/ui/issues/issue-14541.rs new file mode 100644 index 000000000..555ec9f98 --- /dev/null +++ b/tests/ui/issues/issue-14541.rs @@ -0,0 +1,10 @@ +struct Vec2 { y: f32 } +struct Vec3 { y: f32, z: f32 } + +fn make(v: Vec2) { + let Vec3 { y: _, z: _ } = v; + //~^ ERROR mismatched types + //~| expected struct `Vec2`, found struct `Vec3` +} + +fn main() { } diff --git a/tests/ui/issues/issue-14541.stderr b/tests/ui/issues/issue-14541.stderr new file mode 100644 index 000000000..cf155f428 --- /dev/null +++ b/tests/ui/issues/issue-14541.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-14541.rs:5:9 + | +LL | let Vec3 { y: _, z: _ } = v; + | ^^^^^^^^^^^^^^^^^^^ - this expression has type `Vec2` + | | + | expected struct `Vec2`, found struct `Vec3` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-1460.rs b/tests/ui/issues/issue-1460.rs new file mode 100644 index 000000000..e663f7fd4 --- /dev/null +++ b/tests/ui/issues/issue-1460.rs @@ -0,0 +1,7 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +pub fn main() { + {|i: u32| if 1 == i { }}; //~ WARN unused closure that must be used +} diff --git a/tests/ui/issues/issue-1460.stderr b/tests/ui/issues/issue-1460.stderr new file mode 100644 index 000000000..eb7661fad --- /dev/null +++ b/tests/ui/issues/issue-1460.stderr @@ -0,0 +1,11 @@ +warning: unused closure that must be used + --> $DIR/issue-1460.rs:6:5 + | +LL | {|i: u32| if 1 == i { }}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-14721.rs b/tests/ui/issues/issue-14721.rs new file mode 100644 index 000000000..a5c47dd8c --- /dev/null +++ b/tests/ui/issues/issue-14721.rs @@ -0,0 +1,4 @@ +fn main() { + let foo = "str"; + println!("{}", foo.desc); //~ no field `desc` on type `&str` +} diff --git a/tests/ui/issues/issue-14721.stderr b/tests/ui/issues/issue-14721.stderr new file mode 100644 index 000000000..49ebb2976 --- /dev/null +++ b/tests/ui/issues/issue-14721.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `desc` on type `&str` + --> $DIR/issue-14721.rs:3:24 + | +LL | println!("{}", foo.desc); + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-1476.rs b/tests/ui/issues/issue-1476.rs new file mode 100644 index 000000000..138570a93 --- /dev/null +++ b/tests/ui/issues/issue-1476.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", x); //~ ERROR cannot find value `x` in this scope +} diff --git a/tests/ui/issues/issue-1476.stderr b/tests/ui/issues/issue-1476.stderr new file mode 100644 index 000000000..670bd5463 --- /dev/null +++ b/tests/ui/issues/issue-1476.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-1476.rs:2:20 + | +LL | println!("{}", x); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-14821.rs b/tests/ui/issues/issue-14821.rs new file mode 100644 index 000000000..00b2e3607 --- /dev/null +++ b/tests/ui/issues/issue-14821.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +trait SomeTrait {} +struct Meow; +impl SomeTrait for Meow {} + +struct Foo<'a> { + x: &'a dyn SomeTrait, + y: &'a dyn SomeTrait, +} + +impl<'a> Foo<'a> { + pub fn new<'b>(x: &'b dyn SomeTrait, y: &'b dyn SomeTrait) -> Foo<'b> { Foo { x: x, y: y } } +} + +fn main() { + let r = Meow; + let s = Meow; + let q = Foo::new(&r as &dyn SomeTrait, &s as &dyn SomeTrait); +} diff --git a/tests/ui/issues/issue-14845.rs b/tests/ui/issues/issue-14845.rs new file mode 100644 index 000000000..d9b20e1f6 --- /dev/null +++ b/tests/ui/issues/issue-14845.rs @@ -0,0 +1,11 @@ +struct X { + a: [u8; 1] +} + +fn main() { + let x = X { a: [0] }; + let _f = &x.a as *mut u8; //~ ERROR casting + + let local: [u8; 1] = [0]; + let _v = &local as *mut u8; //~ ERROR casting +} diff --git a/tests/ui/issues/issue-14845.stderr b/tests/ui/issues/issue-14845.stderr new file mode 100644 index 000000000..2fa9fbaa8 --- /dev/null +++ b/tests/ui/issues/issue-14845.stderr @@ -0,0 +1,15 @@ +error[E0606]: casting `&[u8; 1]` as `*mut u8` is invalid + --> $DIR/issue-14845.rs:7:14 + | +LL | let _f = &x.a as *mut u8; + | ^^^^^^^^^^^^^^^ + +error[E0606]: casting `&[u8; 1]` as `*mut u8` is invalid + --> $DIR/issue-14845.rs:10:14 + | +LL | let _v = &local as *mut u8; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/issues/issue-14853.rs b/tests/ui/issues/issue-14853.rs new file mode 100644 index 000000000..4ce6e3174 --- /dev/null +++ b/tests/ui/issues/issue-14853.rs @@ -0,0 +1,20 @@ +use std::fmt::Debug; + +trait Str {} + +trait Something: Sized { + fn yay(_: Option, thing: &[T]); +} + +struct X { data: u32 } + +impl Something for X { + fn yay(_:Option, thing: &[T]) { + //~^ ERROR E0276 + } +} + +fn main() { + let arr = &["one", "two", "three"]; + println!("{:?}", Something::yay(None::, arr)); +} diff --git a/tests/ui/issues/issue-14853.stderr b/tests/ui/issues/issue-14853.stderr new file mode 100644 index 000000000..2adcf55ec --- /dev/null +++ b/tests/ui/issues/issue-14853.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-14853.rs:12:15 + | +LL | fn yay(_: Option, thing: &[T]); + | ----------------------------------------------- definition of `yay` from trait +... +LL | fn yay(_:Option, thing: &[T]) { + | ^^^ impl has extra requirement `T: Str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/issues/issue-14865.rs b/tests/ui/issues/issue-14865.rs new file mode 100644 index 000000000..56e78e78f --- /dev/null +++ b/tests/ui/issues/issue-14865.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +enum X { + Foo(usize), + Bar(bool) +} + +fn main() { + let x = match X::Foo(42) { + X::Foo(..) => 1, + _ if true => 0, + X::Bar(..) => panic!("Oh dear") + }; + assert_eq!(x, 1); + + let x = match X::Foo(42) { + _ if true => 0, + X::Foo(..) => 1, + X::Bar(..) => panic!("Oh dear") + }; + assert_eq!(x, 0); +} diff --git a/tests/ui/issues/issue-14875.rs b/tests/ui/issues/issue-14875.rs new file mode 100644 index 000000000..fca330915 --- /dev/null +++ b/tests/ui/issues/issue-14875.rs @@ -0,0 +1,35 @@ +// run-pass +// needs-unwind + +// Check that values are not leaked when a dtor panics (#14875) + +use std::panic::{self, UnwindSafe}; + +struct SetInnerOnDrop<'a>(&'a mut bool); + +impl<'a> UnwindSafe for SetInnerOnDrop<'a> {} + +impl<'a> Drop for SetInnerOnDrop<'a> { + fn drop(&mut self) { + *self.0 = true; + } +} + +struct PanicOnDrop; +impl Drop for PanicOnDrop { + fn drop(&mut self) { + panic!("test panic"); + } +} + +fn main() { + let mut set_on_drop = false; + { + let set_inner_on_drop = SetInnerOnDrop(&mut set_on_drop); + let _ = panic::catch_unwind(|| { + let _set_inner_on_drop = set_inner_on_drop; + let _panic_on_drop = PanicOnDrop; + }); + } + assert!(set_on_drop); +} diff --git a/tests/ui/issues/issue-14901.rs b/tests/ui/issues/issue-14901.rs new file mode 100644 index 000000000..5319abbdf --- /dev/null +++ b/tests/ui/issues/issue-14901.rs @@ -0,0 +1,18 @@ +// check-pass +pub trait Reader {} + +enum Wrapper<'a> { + WrapReader(&'a (dyn Reader + 'a)) +} + +trait Wrap<'a> { + fn wrap(self) -> Wrapper<'a>; +} + +impl<'a, R: Reader> Wrap<'a> for &'a mut R { + fn wrap(self) -> Wrapper<'a> { + Wrapper::WrapReader(self as &'a mut dyn Reader) + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-14915.rs b/tests/ui/issues/issue-14915.rs new file mode 100644 index 000000000..127b909dd --- /dev/null +++ b/tests/ui/issues/issue-14915.rs @@ -0,0 +1,6 @@ +fn main() { + let x: Box = Box::new(0); + + println!("{}", x + 1); + //~^ ERROR cannot add `{integer}` to `Box` +} diff --git a/tests/ui/issues/issue-14915.stderr b/tests/ui/issues/issue-14915.stderr new file mode 100644 index 000000000..6e6326929 --- /dev/null +++ b/tests/ui/issues/issue-14915.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot add `{integer}` to `Box` + --> $DIR/issue-14915.rs:4:22 + | +LL | println!("{}", x + 1); + | - ^ - {integer} + | | + | Box + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-14919.rs b/tests/ui/issues/issue-14919.rs new file mode 100644 index 000000000..943615433 --- /dev/null +++ b/tests/ui/issues/issue-14919.rs @@ -0,0 +1,55 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait Matcher { + fn next_match(&mut self) -> Option<(usize, usize)>; +} + +struct CharPredMatcher<'a, 'b> { + str: &'a str, + pred: Box bool + 'b>, +} + +impl<'a, 'b> Matcher for CharPredMatcher<'a, 'b> { + fn next_match(&mut self) -> Option<(usize, usize)> { + None + } +} + +trait IntoMatcher<'a, T> { + fn into_matcher(self, _: &'a str) -> T; +} + +impl<'a, 'b, F> IntoMatcher<'a, CharPredMatcher<'a, 'b>> for F where F: FnMut(char) -> bool + 'b { + fn into_matcher(self, s: &'a str) -> CharPredMatcher<'a, 'b> { + CharPredMatcher { + str: s, + pred: Box::new(self), + } + } +} + +struct MatchIndices { + matcher: M +} + +impl Iterator for MatchIndices { + type Item = (usize, usize); + + fn next(&mut self) -> Option<(usize, usize)> { + self.matcher.next_match() + } +} + +fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndices { + let string_matcher = from.into_matcher(s); + MatchIndices { matcher: string_matcher } +} + +fn main() { + let s = "abcbdef"; + match_indices(s, |c: char| c == 'b') + .collect::>(); +} diff --git a/tests/ui/issues/issue-14959.rs b/tests/ui/issues/issue-14959.rs new file mode 100644 index 000000000..e31a94315 --- /dev/null +++ b/tests/ui/issues/issue-14959.rs @@ -0,0 +1,55 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#![feature(fn_traits, unboxed_closures)] + +use std::ops::Fn; + +trait Response { fn dummy(&self) { } } +trait Request { fn dummy(&self) { } } +trait Ingot { + fn enter(&mut self, _: &mut R, _: &mut S, a: &mut Alloy) -> Status; +} + +#[allow(dead_code)] +struct HelloWorld; + +struct SendFile; +struct Alloy; +enum Status { + Continue +} + +impl Alloy { + fn find(&self) -> Option { + None + } +} + +impl<'b> Fn<(&'b mut (dyn Response + 'b),)> for SendFile { + extern "rust-call" fn call(&self, (_res,): (&'b mut (dyn Response + 'b),)) {} +} + +impl<'b> FnMut<(&'b mut (dyn Response + 'b),)> for SendFile { + extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (dyn Response+'b),)) { + self.call((_res,)) + } +} + +impl<'b> FnOnce<(&'b mut (dyn Response + 'b),)> for SendFile { + type Output = (); + + extern "rust-call" fn call_once(self, (_res,): (&'b mut (dyn Response+'b),)) { + self.call((_res,)) + } +} + +impl Ingot for HelloWorld { + fn enter(&mut self, _req: &mut Rq, res: &mut Rs, alloy: &mut Alloy) -> Status { + let send_file = alloy.find::().unwrap(); + send_file(res); + Status::Continue + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-15034.rs b/tests/ui/issues/issue-15034.rs new file mode 100644 index 000000000..9ea6ed89c --- /dev/null +++ b/tests/ui/issues/issue-15034.rs @@ -0,0 +1,22 @@ +pub struct Lexer<'a> { + input: &'a str, +} + +impl<'a> Lexer<'a> { + pub fn new(input: &'a str) -> Lexer<'a> { + Lexer { input: input } + } +} + +struct Parser<'a> { + lexer: &'a mut Lexer<'a>, +} + +impl<'a> Parser<'a> { + pub fn new(lexer: &'a mut Lexer) -> Parser<'a> { + Parser { lexer: lexer } + //~^ ERROR explicit lifetime required in the type of `lexer` [E0621] + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/issues/issue-15034.stderr new file mode 100644 index 000000000..f142e260a --- /dev/null +++ b/tests/ui/issues/issue-15034.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `lexer` + --> $DIR/issue-15034.rs:17:9 + | +LL | pub fn new(lexer: &'a mut Lexer) -> Parser<'a> { + | ------------- help: add explicit lifetime `'a` to the type of `lexer`: `&'a mut Lexer<'a>` +LL | Parser { lexer: lexer } + | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-15043.rs b/tests/ui/issues/issue-15043.rs new file mode 100644 index 000000000..53748be8a --- /dev/null +++ b/tests/ui/issues/issue-15043.rs @@ -0,0 +1,14 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(warnings)] + +struct S(T); + +static s1: S>=S(S(0)); +static s2: S=S(0); + +fn main() { + let foo: S>=S(S(0)); + let foo: S=S(0); +} diff --git a/tests/ui/issues/issue-15063.rs b/tests/ui/issues/issue-15063.rs new file mode 100644 index 000000000..408267512 --- /dev/null +++ b/tests/ui/issues/issue-15063.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +enum Two { A, B} +impl Drop for Two { + fn drop(&mut self) { + println!("Dropping!"); + } +} +fn main() { + let k = Two::A; +} diff --git a/tests/ui/issues/issue-15094.rs b/tests/ui/issues/issue-15094.rs new file mode 100644 index 000000000..cb27e2bcf --- /dev/null +++ b/tests/ui/issues/issue-15094.rs @@ -0,0 +1,26 @@ +#![feature(fn_traits, unboxed_closures)] + +use std::{fmt, ops}; + +struct Debuger { + x: T +} + +impl ops::FnOnce<(),> for Debuger { + type Output = (); + fn call_once(self, _args: ()) { + //~^ ERROR `call_once` has an incompatible type for trait + //~| expected signature `extern "rust-call" fn + //~| found signature `fn + println!("{:?}", self.x); + } +} + +fn make_shower(x: T) -> Debuger { + Debuger { x: x } +} + +pub fn main() { + let show3 = make_shower(3); + show3(); +} diff --git a/tests/ui/issues/issue-15094.stderr b/tests/ui/issues/issue-15094.stderr new file mode 100644 index 000000000..b7c950892 --- /dev/null +++ b/tests/ui/issues/issue-15094.stderr @@ -0,0 +1,12 @@ +error[E0053]: method `call_once` has an incompatible type for trait + --> $DIR/issue-15094.rs:11:5 + | +LL | fn call_once(self, _args: ()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn + | + = note: expected signature `extern "rust-call" fn(Debuger<_>, ())` + found signature `fn(Debuger<_>, ())` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-15104.rs b/tests/ui/issues/issue-15104.rs new file mode 100644 index 000000000..47b207ea9 --- /dev/null +++ b/tests/ui/issues/issue-15104.rs @@ -0,0 +1,13 @@ +// run-pass + +fn main() { + assert_eq!(count_members(&[1, 2, 3, 4]), 4); +} + +fn count_members(v: &[usize]) -> usize { + match *v { + [] => 0, + [_] => 1, + [_, ref xs @ ..] => 1 + count_members(xs) + } +} diff --git a/tests/ui/issues/issue-15129-rpass.rs b/tests/ui/issues/issue-15129-rpass.rs new file mode 100644 index 000000000..522d0209c --- /dev/null +++ b/tests/ui/issues/issue-15129-rpass.rs @@ -0,0 +1,25 @@ +// run-pass + +pub enum T { + T1(()), + T2(()) +} + +pub enum V { + V1(isize), + V2(bool) +} + +fn foo(x: (T, V)) -> String { + match x { + (T::T1(()), V::V1(i)) => format!("T1(()), V1({})", i), + (T::T2(()), V::V2(b)) => format!("T2(()), V2({})", b), + _ => String::new() + } +} + + +fn main() { + assert_eq!(foo((T::T1(()), V::V1(99))), "T1(()), V1(99)".to_string()); + assert_eq!(foo((T::T2(()), V::V2(true))), "T2(()), V2(true)".to_string()); +} diff --git a/tests/ui/issues/issue-15155.rs b/tests/ui/issues/issue-15155.rs new file mode 100644 index 000000000..7b137b4af --- /dev/null +++ b/tests/ui/issues/issue-15155.rs @@ -0,0 +1,21 @@ +// run-pass +trait TraitWithSend: Send {} +trait IndirectTraitWithSend: TraitWithSend {} + +// Check struct instantiation (Box will only have Send if TraitWithSend has Send) +#[allow(dead_code)] +struct Blah { x: Box } +impl TraitWithSend for Blah {} + +// Struct instantiation 2-levels deep +#[allow(dead_code)] +struct IndirectBlah { x: Box } +impl TraitWithSend for IndirectBlah {} +impl IndirectTraitWithSend for IndirectBlah {} + +fn test_trait() { println!("got here!") } + +fn main() { + test_trait::(); + test_trait::(); +} diff --git a/tests/ui/issues/issue-15167.rs b/tests/ui/issues/issue-15167.rs new file mode 100644 index 000000000..a2653c10e --- /dev/null +++ b/tests/ui/issues/issue-15167.rs @@ -0,0 +1,26 @@ +// macro f should not be able to inject a reference to 'n'. + +macro_rules! f { () => (n) } +//~^ ERROR cannot find value `n` in this scope +//~| ERROR cannot find value `n` in this scope +//~| ERROR cannot find value `n` in this scope +//~| ERROR cannot find value `n` in this scope + +fn main() -> (){ + for n in 0..1 { + println!("{}", f!()); + } + + if let Some(n) = None { + println!("{}", f!()); + } + + if false { + } else if let Some(n) = None { + println!("{}", f!()); + } + + while let Some(n) = None { + println!("{}", f!()); + } +} diff --git a/tests/ui/issues/issue-15167.stderr b/tests/ui/issues/issue-15167.stderr new file mode 100644 index 000000000..53082ea0e --- /dev/null +++ b/tests/ui/issues/issue-15167.stderr @@ -0,0 +1,47 @@ +error[E0425]: cannot find value `n` in this scope + --> $DIR/issue-15167.rs:3:25 + | +LL | macro_rules! f { () => (n) } + | ^ not found in this scope +... +LL | println!("{}", f!()); + | ---- in this macro invocation + | + = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `n` in this scope + --> $DIR/issue-15167.rs:3:25 + | +LL | macro_rules! f { () => (n) } + | ^ not found in this scope +... +LL | println!("{}", f!()); + | ---- in this macro invocation + | + = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `n` in this scope + --> $DIR/issue-15167.rs:3:25 + | +LL | macro_rules! f { () => (n) } + | ^ not found in this scope +... +LL | println!("{}", f!()); + | ---- in this macro invocation + | + = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `n` in this scope + --> $DIR/issue-15167.rs:3:25 + | +LL | macro_rules! f { () => (n) } + | ^ not found in this scope +... +LL | println!("{}", f!()); + | ---- in this macro invocation + | + = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-15189.rs b/tests/ui/issues/issue-15189.rs new file mode 100644 index 000000000..a9c884bdc --- /dev/null +++ b/tests/ui/issues/issue-15189.rs @@ -0,0 +1,10 @@ +// run-pass +macro_rules! third { + ($e:expr) => ({let x = 2; $e[x]}) +} + +fn main() { + let x = vec![10_usize,11_usize,12_usize,13_usize]; + let t = third!(x); + assert_eq!(t,12_usize); +} diff --git a/tests/ui/issues/issue-15207.rs b/tests/ui/issues/issue-15207.rs new file mode 100644 index 000000000..356e55ac9 --- /dev/null +++ b/tests/ui/issues/issue-15207.rs @@ -0,0 +1,6 @@ +fn main() { + loop { + break.push(1) //~ ERROR no method named `push` found for type `!` + ; + } +} diff --git a/tests/ui/issues/issue-15207.stderr b/tests/ui/issues/issue-15207.stderr new file mode 100644 index 000000000..25ce7cb5c --- /dev/null +++ b/tests/ui/issues/issue-15207.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `push` found for type `!` in the current scope + --> $DIR/issue-15207.rs:3:15 + | +LL | break.push(1) + | ^^^^ method not found in `!` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-15260.rs b/tests/ui/issues/issue-15260.rs new file mode 100644 index 000000000..64fc3df3d --- /dev/null +++ b/tests/ui/issues/issue-15260.rs @@ -0,0 +1,25 @@ +struct Foo { + a: usize, +} + +fn main() { + let Foo { + a: _, + a: _ + //~^ ERROR field `a` bound multiple times in the pattern + } = Foo { a: 29 }; + + let Foo { + a, + a: _ + //~^ ERROR field `a` bound multiple times in the pattern + } = Foo { a: 29 }; + + let Foo { + a, + a: _, + //~^ ERROR field `a` bound multiple times in the pattern + a: x + //~^ ERROR field `a` bound multiple times in the pattern + } = Foo { a: 29 }; +} diff --git a/tests/ui/issues/issue-15260.stderr b/tests/ui/issues/issue-15260.stderr new file mode 100644 index 000000000..4a3041122 --- /dev/null +++ b/tests/ui/issues/issue-15260.stderr @@ -0,0 +1,36 @@ +error[E0025]: field `a` bound multiple times in the pattern + --> $DIR/issue-15260.rs:8:9 + | +LL | a: _, + | ---- first use of `a` +LL | a: _ + | ^^^^ multiple uses of `a` in pattern + +error[E0025]: field `a` bound multiple times in the pattern + --> $DIR/issue-15260.rs:14:9 + | +LL | a, + | - first use of `a` +LL | a: _ + | ^^^^ multiple uses of `a` in pattern + +error[E0025]: field `a` bound multiple times in the pattern + --> $DIR/issue-15260.rs:20:9 + | +LL | a, + | - first use of `a` +LL | a: _, + | ^^^^ multiple uses of `a` in pattern + +error[E0025]: field `a` bound multiple times in the pattern + --> $DIR/issue-15260.rs:22:9 + | +LL | a, + | - first use of `a` +... +LL | a: x + | ^^^^ multiple uses of `a` in pattern + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0025`. diff --git a/tests/ui/issues/issue-15381.rs b/tests/ui/issues/issue-15381.rs new file mode 100644 index 000000000..23b266bef --- /dev/null +++ b/tests/ui/issues/issue-15381.rs @@ -0,0 +1,9 @@ +fn main() { + let values: Vec = vec![1,2,3,4,5,6,7,8]; + + for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { + //~^ ERROR refutable pattern in `for` loop binding + //~| patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered + println!("y={}", y); + } +} diff --git a/tests/ui/issues/issue-15381.stderr b/tests/ui/issues/issue-15381.stderr new file mode 100644 index 000000000..085958411 --- /dev/null +++ b/tests/ui/issues/issue-15381.stderr @@ -0,0 +1,11 @@ +error[E0005]: refutable pattern in `for` loop binding + --> $DIR/issue-15381.rs:4:9 + | +LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) { + | ^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered + | + = note: the matched value is of type `&[u8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/issues/issue-15444.rs b/tests/ui/issues/issue-15444.rs new file mode 100644 index 000000000..e94afee96 --- /dev/null +++ b/tests/ui/issues/issue-15444.rs @@ -0,0 +1,23 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait MyTrait { + fn foo(&self); +} + +impl MyTrait for fn(A, B) -> C { + fn foo(&self) {} +} + +fn bar(t: &T) { + t.foo() +} + +fn thing(a: isize, b: isize) -> isize { + a + b +} + +fn main() { + let thing: fn(isize, isize) -> isize = thing; // coerce to fn type + bar(&thing); +} diff --git a/tests/ui/issues/issue-15523-big.rs b/tests/ui/issues/issue-15523-big.rs new file mode 100644 index 000000000..05414f1db --- /dev/null +++ b/tests/ui/issues/issue-15523-big.rs @@ -0,0 +1,39 @@ +// run-pass +// Issue 15523: derive(PartialOrd) should use the provided +// discriminant values for the derived ordering. +// +// This test is checking corner cases that arise when you have +// 64-bit values in the variants. + +#[derive(PartialEq, PartialOrd)] +#[repr(u64)] +enum Eu64 { + Pos2 = 2, + PosMax = !0, + Pos1 = 1, +} + +#[derive(PartialEq, PartialOrd)] +#[repr(i64)] +enum Ei64 { + Pos2 = 2, + Neg1 = -1, + NegMin = 1 << 63, + PosMax = !(1 << 63), + Pos1 = 1, +} + +fn main() { + assert!(Eu64::Pos2 > Eu64::Pos1); + assert!(Eu64::Pos2 < Eu64::PosMax); + assert!(Eu64::Pos1 < Eu64::PosMax); + + + assert!(Ei64::Pos2 > Ei64::Pos1); + assert!(Ei64::Pos2 > Ei64::Neg1); + assert!(Ei64::Pos1 > Ei64::Neg1); + assert!(Ei64::Pos2 > Ei64::NegMin); + assert!(Ei64::Pos1 > Ei64::NegMin); + assert!(Ei64::Pos2 < Ei64::PosMax); + assert!(Ei64::Pos1 < Ei64::PosMax); +} diff --git a/tests/ui/issues/issue-15523.rs b/tests/ui/issues/issue-15523.rs new file mode 100644 index 000000000..220a34b9b --- /dev/null +++ b/tests/ui/issues/issue-15523.rs @@ -0,0 +1,42 @@ +// run-pass +// Issue 15523: derive(PartialOrd) should use the provided +// discriminant values for the derived ordering. +// +// This is checking the basic functionality. + +#[derive(PartialEq, PartialOrd)] +enum E1 { + Pos2 = 2, + Neg1 = -1, + Pos1 = 1, +} + +#[derive(PartialEq, PartialOrd)] +#[repr(u8)] +enum E2 { + Pos2 = 2, + PosMax = !0 as u8, + Pos1 = 1, +} + +#[derive(PartialEq, PartialOrd)] +#[repr(i8)] +enum E3 { + Pos2 = 2, + Neg1 = -1_i8, + Pos1 = 1, +} + +fn main() { + assert!(E1::Pos2 > E1::Pos1); + assert!(E1::Pos1 > E1::Neg1); + assert!(E1::Pos2 > E1::Neg1); + + assert!(E2::Pos2 > E2::Pos1); + assert!(E2::Pos1 < E2::PosMax); + assert!(E2::Pos2 < E2::PosMax); + + assert!(E3::Pos2 > E3::Pos1); + assert!(E3::Pos1 > E3::Neg1); + assert!(E3::Pos2 > E3::Neg1); +} diff --git a/tests/ui/issues/issue-15562.rs b/tests/ui/issues/issue-15562.rs new file mode 100644 index 000000000..dc0ecd365 --- /dev/null +++ b/tests/ui/issues/issue-15562.rs @@ -0,0 +1,19 @@ +// run-pass +// aux-build:issue-15562.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_15562 as i; + +pub fn main() { + unsafe { + transmute(); + i::transmute(); + } +} + +// We declare this so we don't run into unresolved symbol errors +// The above extern is NOT `extern "rust-intrinsic"` and thus +// means it'll try to find a corresponding symbol to link to. +#[no_mangle] +pub extern "C" fn transmute() {} diff --git a/tests/ui/issues/issue-15571.rs b/tests/ui/issues/issue-15571.rs new file mode 100644 index 000000000..5f228b286 --- /dev/null +++ b/tests/ui/issues/issue-15571.rs @@ -0,0 +1,57 @@ +// run-pass + +fn match_on_local() { + let mut foo: Option> = Some(Box::new(5)); + match foo { + None => {}, + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); +} + +fn match_on_arg(mut foo: Option>) { + match foo { + None => {} + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); +} + +fn match_on_binding() { + match Some(Box::new(7)) { + mut foo => { + match foo { + None => {}, + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); + } + } +} + +fn match_on_upvar() { + let mut foo: Option> = Some(Box::new(8)); + let f = move|| { + match foo { + None => {}, + Some(x) => { + foo = Some(x); + } + } + println!("'{}'", foo.unwrap()); + }; + f(); +} + +fn main() { + match_on_local(); + match_on_arg(Some(Box::new(6))); + match_on_binding(); + match_on_upvar(); +} diff --git a/tests/ui/issues/issue-15673.rs b/tests/ui/issues/issue-15673.rs new file mode 100644 index 000000000..a8733d7f1 --- /dev/null +++ b/tests/ui/issues/issue-15673.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(stable_features)] + +#![feature(iter_arith)] + +fn main() { + let x: [u64; 3] = [1, 2, 3]; + assert_eq!(6, (0..3).map(|i| x[i]).sum::()); +} diff --git a/tests/ui/issues/issue-15689-1.rs b/tests/ui/issues/issue-15689-1.rs new file mode 100644 index 000000000..d143926b2 --- /dev/null +++ b/tests/ui/issues/issue-15689-1.rs @@ -0,0 +1,10 @@ +// run-pass + +#[derive(PartialEq, Debug)] +enum Test<'a> { + Slice(&'a isize) +} + +fn main() { + assert_eq!(Test::Slice(&1), Test::Slice(&1)) +} diff --git a/tests/ui/issues/issue-15689-2.rs b/tests/ui/issues/issue-15689-2.rs new file mode 100644 index 000000000..83dcb1406 --- /dev/null +++ b/tests/ui/issues/issue-15689-2.rs @@ -0,0 +1,10 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Clone)] +enum Test<'a> { + Slice(&'a isize) +} + +fn main() {} diff --git a/tests/ui/issues/issue-15734.rs b/tests/ui/issues/issue-15734.rs new file mode 100644 index 000000000..be5820606 --- /dev/null +++ b/tests/ui/issues/issue-15734.rs @@ -0,0 +1,58 @@ +// run-pass +// If `Index` used an associated type for its output, this test would +// work more smoothly. + +use std::ops::Index; + +struct Mat { data: Vec, cols: usize, } + +impl Mat { + fn new(data: Vec, cols: usize) -> Mat { + Mat { data: data, cols: cols } + } + fn row<'a>(&'a self, row: usize) -> Row<&'a Mat> { + Row { mat: self, row: row, } + } +} + +impl Index<(usize, usize)> for Mat { + type Output = T; + + fn index<'a>(&'a self, (row, col): (usize, usize)) -> &'a T { + &self.data[row * self.cols + col] + } +} + +impl<'a, T> Index<(usize, usize)> for &'a Mat { + type Output = T; + + fn index<'b>(&'b self, index: (usize, usize)) -> &'b T { + (*self).index(index) + } +} + +struct Row { mat: M, row: usize, } + +impl> Index for Row { + type Output = T; + + fn index<'a>(&'a self, col: usize) -> &'a T { + &self.mat[(self.row, col)] + } +} + +fn main() { + let m = Mat::new(vec![1, 2, 3, 4, 5, 6], 3); + let r = m.row(1); + + assert_eq!(r.index(2), &6); + assert_eq!(r[2], 6); + assert_eq!(r[2], 6); + assert_eq!(6, r[2]); + + let e = r[2]; + assert_eq!(e, 6); + + let e: usize = r[2]; + assert_eq!(e, 6); +} diff --git a/tests/ui/issues/issue-15735.rs b/tests/ui/issues/issue-15735.rs new file mode 100644 index 000000000..f9ba34405 --- /dev/null +++ b/tests/ui/issues/issue-15735.rs @@ -0,0 +1,17 @@ +// check-pass +#![allow(dead_code)] +struct A<'a> { + a: &'a i32, + b: &'a i32, +} + +impl <'a> A<'a> { + fn foo<'b>(&'b self) { + A { + a: self.a, + b: self.b, + }; + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-15756.rs b/tests/ui/issues/issue-15756.rs new file mode 100644 index 000000000..e0861dee6 --- /dev/null +++ b/tests/ui/issues/issue-15756.rs @@ -0,0 +1,14 @@ +use std::slice::Chunks; +use std::slice::ChunksMut; + +fn dft_iter<'a, T>(arg1: Chunks<'a,T>, arg2: ChunksMut<'a,T>) +{ + for + &mut something + //~^ ERROR the size for values of type + in arg2 + { + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-15756.stderr b/tests/ui/issues/issue-15756.stderr new file mode 100644 index 000000000..d9bdc69ad --- /dev/null +++ b/tests/ui/issues/issue-15756.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[T]` cannot be known at compilation time + --> $DIR/issue-15756.rs:7:10 + | +LL | &mut something + | ^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[T]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-15763.rs b/tests/ui/issues/issue-15763.rs new file mode 100644 index 000000000..ae0863615 --- /dev/null +++ b/tests/ui/issues/issue-15763.rs @@ -0,0 +1,88 @@ +// run-pass +#![allow(unreachable_code)] + +#[derive(PartialEq, Debug)] +struct Bar { + x: isize +} +impl Drop for Bar { + fn drop(&mut self) { + assert_eq!(self.x, 22); + } +} + +#[derive(PartialEq, Debug)] +struct Foo { + x: Bar, + a: isize +} + +fn foo() -> Result { + return Ok(Foo { + x: Bar { x: 22 }, + a: return Err(32) + }); +} + +fn baz() -> Result { + Ok(Foo { + x: Bar { x: 22 }, + a: return Err(32) + }) +} + +// explicit immediate return +fn aa() -> isize { + return 3; +} + +// implicit immediate return +fn bb() -> isize { + 3 +} + +// implicit outptr return +fn cc() -> Result { + Ok(3) +} + +// explicit outptr return +fn dd() -> Result { + return Ok(3); +} + +trait A { + fn aaa(&self) -> isize { + 3 + } + fn bbb(&self) -> isize { + return 3; + } + fn ccc(&self) -> Result { + Ok(3) + } + fn ddd(&self) -> Result { + return Ok(3); + } +} + +impl A for isize {} + +fn main() { + assert_eq!(foo(), Err(32)); + assert_eq!(baz(), Err(32)); + + assert_eq!(aa(), 3); + assert_eq!(bb(), 3); + assert_eq!(cc().unwrap(), 3); + assert_eq!(dd().unwrap(), 3); + + let i = Box::new(32isize) as Box; + assert_eq!(i.aaa(), 3); + let i = Box::new(32isize) as Box; + assert_eq!(i.bbb(), 3); + let i = Box::new(32isize) as Box; + assert_eq!(i.ccc().unwrap(), 3); + let i = Box::new(32isize) as Box; + assert_eq!(i.ddd().unwrap(), 3); +} diff --git a/tests/ui/issues/issue-15774.rs b/tests/ui/issues/issue-15774.rs new file mode 100644 index 000000000..ed2235758 --- /dev/null +++ b/tests/ui/issues/issue-15774.rs @@ -0,0 +1,25 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![deny(warnings)] +#![allow(unused_imports)] + +pub enum Foo { A } +mod bar { + pub fn normal(x: ::Foo) { + use Foo::A; + match x { + A => {} + } + } + pub fn wrong(x: ::Foo) { + match x { + ::Foo::A => {} + } + } +} + +pub fn main() { + bar::normal(Foo::A); + bar::wrong(Foo::A); +} diff --git a/tests/ui/issues/issue-15783.rs b/tests/ui/issues/issue-15783.rs new file mode 100644 index 000000000..0b1f4545e --- /dev/null +++ b/tests/ui/issues/issue-15783.rs @@ -0,0 +1,14 @@ +pub fn foo(params: Option<&[&str]>) -> usize { + params.unwrap().first().unwrap().len() +} + +fn main() { + let name = "Foo"; + let x = Some(&[name]); + let msg = foo(x); + //~^ ERROR mismatched types + //~| expected enum `Option<&[&str]>` + //~| found enum `Option<&[&str; 1]>` + //~| expected slice `[&str]`, found array `[&str; 1]` + assert_eq!(msg, 3); +} diff --git a/tests/ui/issues/issue-15783.stderr b/tests/ui/issues/issue-15783.stderr new file mode 100644 index 000000000..660dfe9ed --- /dev/null +++ b/tests/ui/issues/issue-15783.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-15783.rs:8:19 + | +LL | let msg = foo(x); + | --- ^ expected slice `[&str]`, found array `[&str; 1]` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&[&str]>` + found enum `Option<&[&str; 1]>` +note: function defined here + --> $DIR/issue-15783.rs:1:8 + | +LL | pub fn foo(params: Option<&[&str]>) -> usize { + | ^^^ ----------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-15793.rs b/tests/ui/issues/issue-15793.rs new file mode 100644 index 000000000..769012b1b --- /dev/null +++ b/tests/ui/issues/issue-15793.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] + +enum NestedEnum { + First, + Second, + Third +} +enum Enum { + Variant1(bool), + Variant2(NestedEnum) +} + +#[inline(never)] +fn foo(x: Enum) -> isize { + match x { + Enum::Variant1(true) => 1, + Enum::Variant1(false) => 2, + Enum::Variant2(NestedEnum::Second) => 3, + Enum::Variant2(NestedEnum::Third) => 4, + Enum::Variant2(NestedEnum::First) => 5 + } +} + +fn main() { + assert_eq!(foo(Enum::Variant2(NestedEnum::Third)), 4); +} diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/issues/issue-15858.rs new file mode 100644 index 000000000..8d65afc48 --- /dev/null +++ b/tests/ui/issues/issue-15858.rs @@ -0,0 +1,33 @@ +// run-pass +static mut DROP_RAN: bool = false; + +trait Bar { + fn do_something(&mut self); +} + +struct BarImpl; + +impl Bar for BarImpl { + fn do_something(&mut self) {} +} + + +struct Foo(#[allow(unused_tuple_struct_fields)] B); + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { + DROP_RAN = true; + } + } +} + + +fn main() { + { + let _x: Foo = Foo(BarImpl); + } + unsafe { + assert_eq!(DROP_RAN, true); + } +} diff --git a/tests/ui/issues/issue-15896.rs b/tests/ui/issues/issue-15896.rs new file mode 100644 index 000000000..d3153b516 --- /dev/null +++ b/tests/ui/issues/issue-15896.rs @@ -0,0 +1,15 @@ +// Regression test for #15896. It used to ICE rustc. + +fn main() { + enum R { REB(()) } + struct Tau { t: usize } + enum E { B(R, Tau) } + + let e = E::B(R::REB(()), Tau { t: 3 }); + let u = match e { + E::B( + Tau{t: x}, + //~^ ERROR mismatched types + _) => x, + }; +} diff --git a/tests/ui/issues/issue-15896.stderr b/tests/ui/issues/issue-15896.stderr new file mode 100644 index 000000000..038337f5a --- /dev/null +++ b/tests/ui/issues/issue-15896.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-15896.rs:11:11 + | +LL | let u = match e { + | - this expression has type `E` +LL | E::B( +LL | Tau{t: x}, + | ^^^^^^^^^ expected enum `R`, found struct `Tau` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-15965.rs b/tests/ui/issues/issue-15965.rs new file mode 100644 index 000000000..eef4900d4 --- /dev/null +++ b/tests/ui/issues/issue-15965.rs @@ -0,0 +1,7 @@ +fn main() { + return + { return () } +//~^ ERROR type annotations needed [E0282] + () + ; +} diff --git a/tests/ui/issues/issue-15965.stderr b/tests/ui/issues/issue-15965.stderr new file mode 100644 index 000000000..fe06810b8 --- /dev/null +++ b/tests/ui/issues/issue-15965.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/issue-15965.rs:3:9 + | +LL | / { return () } +LL | | +LL | | () + | |______^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-16048.rs b/tests/ui/issues/issue-16048.rs new file mode 100644 index 000000000..eaf6acff2 --- /dev/null +++ b/tests/ui/issues/issue-16048.rs @@ -0,0 +1,30 @@ +trait NoLifetime { + fn get<'p, T : Test<'p>>(&self) -> T; + //~^ NOTE lifetimes in impl do not match this method in trait +} + +trait Test<'p> { + fn new(buf: &'p mut [u8]) -> Self; +} + +struct Foo<'a> { + buf: &'a mut [u8], +} + +impl<'a> Test<'a> for Foo<'a> { + fn new(buf: &'a mut [u8]) -> Foo<'a> { + Foo { buf: buf } + } +} + +impl<'a> NoLifetime for Foo<'a> { + fn get<'p, T: Test<'a> + From>>(&self) -> T { + //~^ ERROR E0195 + //~| NOTE lifetimes do not match method in trait + return *self as T; + //~^ ERROR non-primitive cast: `Foo<'a>` as `T` + //~| NOTE an `as` expression can only be used to convert between primitive types + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-16048.stderr b/tests/ui/issues/issue-16048.stderr new file mode 100644 index 000000000..73610942d --- /dev/null +++ b/tests/ui/issues/issue-16048.stderr @@ -0,0 +1,21 @@ +error[E0195]: lifetime parameters or bounds on method `get` do not match the trait declaration + --> $DIR/issue-16048.rs:21:11 + | +LL | fn get<'p, T : Test<'p>>(&self) -> T; + | ------------------ lifetimes in impl do not match this method in trait +... +LL | fn get<'p, T: Test<'a> + From>>(&self) -> T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait + +error[E0605]: non-primitive cast: `Foo<'a>` as `T` + --> $DIR/issue-16048.rs:24:16 + | +LL | return *self as T; + | ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)` + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0195, E0605. +For more information about an error, try `rustc --explain E0195`. diff --git a/tests/ui/issues/issue-16149.rs b/tests/ui/issues/issue-16149.rs new file mode 100644 index 000000000..51b60725c --- /dev/null +++ b/tests/ui/issues/issue-16149.rs @@ -0,0 +1,11 @@ +extern "C" { + static externalValue: isize; +} + +fn main() { + let boolValue = match 42 { + externalValue => true, + //~^ ERROR match bindings cannot shadow statics + _ => false, + }; +} diff --git a/tests/ui/issues/issue-16149.stderr b/tests/ui/issues/issue-16149.stderr new file mode 100644 index 000000000..bb809840b --- /dev/null +++ b/tests/ui/issues/issue-16149.stderr @@ -0,0 +1,12 @@ +error[E0530]: match bindings cannot shadow statics + --> $DIR/issue-16149.rs:7:9 + | +LL | static externalValue: isize; + | ---------------------------- the static `externalValue` is defined here +... +LL | externalValue => true, + | ^^^^^^^^^^^^^ cannot be named the same as a static + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/issues/issue-16151.rs b/tests/ui/issues/issue-16151.rs new file mode 100644 index 000000000..48a14b2af --- /dev/null +++ b/tests/ui/issues/issue-16151.rs @@ -0,0 +1,29 @@ +// run-pass + +use std::mem; + +static mut DROP_COUNT: usize = 0; + +struct Fragment; + +impl Drop for Fragment { + fn drop(&mut self) { + unsafe { + DROP_COUNT += 1; + } + } +} + +fn main() { + { + let mut fragments = vec![Fragment, Fragment, Fragment]; + let _new_fragments: Vec = mem::replace(&mut fragments, vec![]) + .into_iter() + .skip_while(|_fragment| { + true + }).collect(); + } + unsafe { + assert_eq!(DROP_COUNT, 3); + } +} diff --git a/tests/ui/issues/issue-16250.rs b/tests/ui/issues/issue-16250.rs new file mode 100644 index 000000000..436e2a6ce --- /dev/null +++ b/tests/ui/issues/issue-16250.rs @@ -0,0 +1,9 @@ +#![deny(warnings)] + +pub struct Foo; + +extern "C" { + pub fn foo(x: (Foo)); //~ ERROR `extern` block uses type `Foo` +} + +fn main() {} diff --git a/tests/ui/issues/issue-16250.stderr b/tests/ui/issues/issue-16250.stderr new file mode 100644 index 000000000..5eb5e0864 --- /dev/null +++ b/tests/ui/issues/issue-16250.stderr @@ -0,0 +1,22 @@ +error: `extern` block uses type `Foo`, which is not FFI-safe + --> $DIR/issue-16250.rs:6:20 + | +LL | pub fn foo(x: (Foo)); + | ^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-16250.rs:3:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/issue-16250.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-16256.rs b/tests/ui/issues/issue-16256.rs new file mode 100644 index 000000000..eec23437b --- /dev/null +++ b/tests/ui/issues/issue-16256.rs @@ -0,0 +1,7 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + let mut buf = Vec::new(); + |c: u8| buf.push(c); //~ WARN unused closure that must be used +} diff --git a/tests/ui/issues/issue-16256.stderr b/tests/ui/issues/issue-16256.stderr new file mode 100644 index 000000000..d920530b5 --- /dev/null +++ b/tests/ui/issues/issue-16256.stderr @@ -0,0 +1,11 @@ +warning: unused closure that must be used + --> $DIR/issue-16256.rs:6:5 + | +LL | |c: u8| buf.push(c); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-16278.rs b/tests/ui/issues/issue-16278.rs new file mode 100644 index 000000000..2f47b694a --- /dev/null +++ b/tests/ui/issues/issue-16278.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-tidy-cr + +// this file has some special \r\n endings (use xxd to see them) + +fn main() {assert_eq!(b"", b"\ + "); +assert_eq!(b"\n", b" +"); +} diff --git a/tests/ui/issues/issue-16338.rs b/tests/ui/issues/issue-16338.rs new file mode 100644 index 000000000..321b3576c --- /dev/null +++ b/tests/ui/issues/issue-16338.rs @@ -0,0 +1,10 @@ +struct Slice { + data: *const T, + len: usize, +} + +fn main() { + let Slice { data: data, len: len } = "foo"; + //~^ ERROR mismatched types + //~| found struct `Slice<_>` +} diff --git a/tests/ui/issues/issue-16338.stderr b/tests/ui/issues/issue-16338.stderr new file mode 100644 index 000000000..6878600b0 --- /dev/null +++ b/tests/ui/issues/issue-16338.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-16338.rs:7:9 + | +LL | let Slice { data: data, len: len } = "foo"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----- this expression has type `&str` + | | + | expected `str`, found struct `Slice` + | + = note: expected type `str` + found struct `Slice<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-16401.rs b/tests/ui/issues/issue-16401.rs new file mode 100644 index 000000000..332352ca7 --- /dev/null +++ b/tests/ui/issues/issue-16401.rs @@ -0,0 +1,15 @@ +struct Slice { + data: *const T, + len: usize, +} + +fn main() { + match () { + Slice { data: data, len: len } => (), + //~^ ERROR mismatched types + //~| expected unit type `()` + //~| found struct `Slice<_>` + //~| expected `()`, found struct `Slice` + _ => unreachable!() + } +} diff --git a/tests/ui/issues/issue-16401.stderr b/tests/ui/issues/issue-16401.stderr new file mode 100644 index 000000000..f8ea09070 --- /dev/null +++ b/tests/ui/issues/issue-16401.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-16401.rs:8:9 + | +LL | match () { + | -- this expression has type `()` +LL | Slice { data: data, len: len } => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Slice` + | + = note: expected unit type `()` + found struct `Slice<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-16441.rs b/tests/ui/issues/issue-16441.rs new file mode 100644 index 000000000..bafa204e0 --- /dev/null +++ b/tests/ui/issues/issue-16441.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Empty; + +// This used to cause an ICE +#[allow(improper_ctypes_definitions)] +extern "C" fn ice(_a: Empty) {} + +fn main() { +} diff --git a/tests/ui/issues/issue-16452.rs b/tests/ui/issues/issue-16452.rs new file mode 100644 index 000000000..faf9edd3b --- /dev/null +++ b/tests/ui/issues/issue-16452.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn main() { + if true { return } + match () { + () => { static MAGIC: usize = 0; } + } +} diff --git a/tests/ui/issues/issue-16492.rs b/tests/ui/issues/issue-16492.rs new file mode 100644 index 000000000..7fa808237 --- /dev/null +++ b/tests/ui/issues/issue-16492.rs @@ -0,0 +1,67 @@ +// run-pass +#![allow(non_snake_case)] + +use std::rc::Rc; +use std::cell::Cell; + +struct Field { + number: usize, + state: Rc> +} + +impl Field { + fn new(number: usize, state: Rc>) -> Field { + Field { + number: number, + state: state + } + } +} + +impl Drop for Field { + fn drop(&mut self) { + println!("Dropping field {}", self.number); + assert_eq!(self.state.get(), self.number); + self.state.set(self.state.get()+1); + } +} + +struct NoDropImpl { + _one: Field, + _two: Field, + _three: Field +} + +struct HasDropImpl { + _one: Field, + _two: Field, + _three: Field +} + +impl Drop for HasDropImpl { + fn drop(&mut self) { + println!("HasDropImpl.drop()"); + assert_eq!(self._one.state.get(), 0); + self._one.state.set(1); + } +} + +pub fn main() { + let state = Rc::new(Cell::new(1)); + let noImpl = NoDropImpl { + _one: Field::new(1, state.clone()), + _two: Field::new(2, state.clone()), + _three: Field::new(3, state.clone()) + }; + drop(noImpl); + assert_eq!(state.get(), 4); + + state.set(0); + let hasImpl = HasDropImpl { + _one: Field::new(1, state.clone()), + _two: Field::new(2, state.clone()), + _three: Field::new(3, state.clone()) + }; + drop(hasImpl); + assert_eq!(state.get(), 4); +} diff --git a/tests/ui/issues/issue-16530.rs b/tests/ui/issues/issue-16530.rs new file mode 100644 index 000000000..25817a2a6 --- /dev/null +++ b/tests/ui/issues/issue-16530.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(deprecated)] + +use std::hash::{SipHasher, Hasher, Hash}; + +#[derive(Hash)] +struct Empty; + +pub fn main() { + let mut s1 = SipHasher::new(); + Empty.hash(&mut s1); + let mut s2 = SipHasher::new(); + Empty.hash(&mut s2); + assert_eq!(s1.finish(), s2.finish()); +} diff --git a/tests/ui/issues/issue-16538.mir.stderr b/tests/ui/issues/issue-16538.mir.stderr new file mode 100644 index 000000000..e320df4b7 --- /dev/null +++ b/tests/ui/issues/issue-16538.mir.stderr @@ -0,0 +1,29 @@ +error[E0015]: cannot call non-const fn `Y::foo` in statics + --> $DIR/issue-16538.rs:14:23 + | +LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-16538.rs:14:30 + | +LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); + | ^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-16538.rs:14:21 + | +LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0133. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/issues/issue-16538.rs b/tests/ui/issues/issue-16538.rs new file mode 100644 index 000000000..270fa3014 --- /dev/null +++ b/tests/ui/issues/issue-16538.rs @@ -0,0 +1,19 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +mod Y { + pub type X = usize; + extern "C" { + pub static x: *const usize; + } + pub fn foo(value: *const X) -> *const X { + value + } +} + +static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); +//~^ ERROR dereference of raw pointer +//~| ERROR E0015 +//~| ERROR use of extern static is unsafe and requires + +fn main() {} diff --git a/tests/ui/issues/issue-16538.thir.stderr b/tests/ui/issues/issue-16538.thir.stderr new file mode 100644 index 000000000..4a8628692 --- /dev/null +++ b/tests/ui/issues/issue-16538.thir.stderr @@ -0,0 +1,29 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-16538.rs:14:22 + | +LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-16538.rs:14:30 + | +LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); + | ^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0015]: cannot call non-const fn `Y::foo` in statics + --> $DIR/issue-16538.rs:14:23 + | +LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0133. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/issues/issue-16560.rs b/tests/ui/issues/issue-16560.rs new file mode 100644 index 000000000..d5fffc7ef --- /dev/null +++ b/tests/ui/issues/issue-16560.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_variables)] +// ignore-emscripten no threads support + +use std::thread; +use std::mem; + +fn main() { + let y = 0u8; + let closure = move |x: u8| y + x; + + // Check that both closures are capturing by value + assert_eq!(1, mem::size_of_val(&closure)); + + thread::spawn(move|| { + let ok = closure; + }).join().ok().unwrap(); +} diff --git a/tests/ui/issues/issue-16562.rs b/tests/ui/issues/issue-16562.rs new file mode 100644 index 000000000..e16a35158 --- /dev/null +++ b/tests/ui/issues/issue-16562.rs @@ -0,0 +1,17 @@ +trait MatrixShape {} + +struct Col { + data: D, + col: C, +} + +trait Collection { fn len(&self) -> usize; } + +impl Collection for Col { +//~^ ERROR type parameter `T` is not constrained + fn len(&self) -> usize { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-16562.stderr b/tests/ui/issues/issue-16562.stderr new file mode 100644 index 000000000..3fe7507e8 --- /dev/null +++ b/tests/ui/issues/issue-16562.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-16562.rs:10:6 + | +LL | impl Collection for Col { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-16596.rs b/tests/ui/issues/issue-16596.rs new file mode 100644 index 000000000..e7a096302 --- /dev/null +++ b/tests/ui/issues/issue-16596.rs @@ -0,0 +1,22 @@ +// check-pass +#![allow(dead_code)] + +trait MatrixRow { fn dummy(&self) { }} + +struct Mat; + +impl<'a> MatrixRow for &'a Mat {} + +struct Rows { + mat: M, +} + +impl<'a> Iterator for Rows<&'a Mat> { + type Item = (); + + fn next(&mut self) -> Option<()> { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-1660.rs b/tests/ui/issues/issue-1660.rs new file mode 100644 index 000000000..aa60a8d8a --- /dev/null +++ b/tests/ui/issues/issue-1660.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// pretty-expanded FIXME #23616 + +pub fn main() { + static _x: isize = 1<<2; +} diff --git a/tests/ui/issues/issue-16643.rs b/tests/ui/issues/issue-16643.rs new file mode 100644 index 000000000..c74a554af --- /dev/null +++ b/tests/ui/issues/issue-16643.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:issue-16643.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_16643 as i; + +pub fn main() { + i::TreeBuilder { h: 3 }.process_token(); +} diff --git a/tests/ui/issues/issue-16648.rs b/tests/ui/issues/issue-16648.rs new file mode 100644 index 000000000..539f015fa --- /dev/null +++ b/tests/ui/issues/issue-16648.rs @@ -0,0 +1,11 @@ +// run-pass +fn main() { + let x: (isize, &[isize]) = (2, &[1, 2]); + assert_eq!(match x { + (0, &[_, _]) => 0, + (1, _) => 1, + (2, &[_, _]) => 2, + (2, _) => 3, + _ => 4 + }, 2); +} diff --git a/tests/ui/issues/issue-16668.rs b/tests/ui/issues/issue-16668.rs new file mode 100644 index 000000000..92efb42fe --- /dev/null +++ b/tests/ui/issues/issue-16668.rs @@ -0,0 +1,20 @@ +// check-pass +#![allow(dead_code)] +struct Parser<'a, I, O> { + parse: Box Result + 'a> +} + +impl<'a, I: 'a, O: 'a> Parser<'a, I, O> { + fn compose(mut self, mut rhs: Parser<'a, O, K>) -> Parser<'a, I, K> { + Parser { + parse: Box::new(move |x: I| { + match (self.parse)(x) { + Ok(r) => (rhs.parse)(r), + Err(e) => Err(e) + } + }) + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-16671.rs b/tests/ui/issues/issue-16671.rs new file mode 100644 index 000000000..eff8e275b --- /dev/null +++ b/tests/ui/issues/issue-16671.rs @@ -0,0 +1,12 @@ +// run-pass + +#![deny(warnings)] + +fn foo(_f: F) { } + +fn main() { + let mut var = Vec::new(); + foo(move|| { + var.push(1); + }); +} diff --git a/tests/ui/issues/issue-16683.rs b/tests/ui/issues/issue-16683.rs new file mode 100644 index 000000000..72fa21bdd --- /dev/null +++ b/tests/ui/issues/issue-16683.rs @@ -0,0 +1,9 @@ +trait T<'a> { + fn a(&'a self) -> &'a bool; + fn b(&self) { + self.a(); + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-16683.stderr b/tests/ui/issues/issue-16683.stderr new file mode 100644 index 000000000..fff681b2e --- /dev/null +++ b/tests/ui/issues/issue-16683.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/issue-16683.rs:4:9 + | +LL | trait T<'a> { + | -- lifetime `'a` defined here +LL | fn a(&'a self) -> &'a bool; +LL | fn b(&self) { + | - let's call the lifetime of this reference `'1` +LL | self.a(); + | ^^^^^^^^ argument requires that `'1` must outlive `'a` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-16725.rs b/tests/ui/issues/issue-16725.rs new file mode 100644 index 000000000..2cf8a6069 --- /dev/null +++ b/tests/ui/issues/issue-16725.rs @@ -0,0 +1,8 @@ +// aux-build:issue-16725.rs + +extern crate issue_16725 as foo; + +fn main() { + unsafe { foo::bar(); } + //~^ ERROR: function `bar` is private +} diff --git a/tests/ui/issues/issue-16725.stderr b/tests/ui/issues/issue-16725.stderr new file mode 100644 index 000000000..5f6eae73e --- /dev/null +++ b/tests/ui/issues/issue-16725.stderr @@ -0,0 +1,15 @@ +error[E0603]: function `bar` is private + --> $DIR/issue-16725.rs:6:19 + | +LL | unsafe { foo::bar(); } + | ^^^ private function + | +note: the function `bar` is defined here + --> $DIR/auxiliary/issue-16725.rs:2:5 + | +LL | fn bar(); + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-16739.rs b/tests/ui/issues/issue-16739.rs new file mode 100644 index 000000000..b21ea4bcd --- /dev/null +++ b/tests/ui/issues/issue-16739.rs @@ -0,0 +1,45 @@ +// run-pass +#![feature(unboxed_closures, fn_traits)] + +// Test that unboxing shim for calling rust-call ABI methods through a +// trait box works and does not cause an ICE. + +struct Foo { foo: u32 } + +impl FnMut<()> for Foo { + extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo } +} + +impl FnOnce<()> for Foo { + type Output = u32; + extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } +} + +impl FnMut<(u32,)> for Foo { + extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } +} + +impl FnOnce<(u32,)> for Foo { + type Output = u32; + extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } +} + +impl FnMut<(u32,u32)> for Foo { + extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } +} + +impl FnOnce<(u32,u32)> for Foo { + type Output = u32; + extern "rust-call" fn call_once(mut self, args: (u32,u32)) -> u32 { self.call_mut(args) } +} + +fn main() { + let mut f = Box::new(Foo { foo: 42 }) as Box u32>; + assert_eq!(f.call_mut(()), 42); + + let mut f = Box::new(Foo { foo: 40 }) as Box u32>; + assert_eq!(f.call_mut((2,)), 42); + + let mut f = Box::new(Foo { foo: 40 }) as Box u32>; + assert_eq!(f.call_mut((1, 1)), 42); +} diff --git a/tests/ui/issues/issue-16745.rs b/tests/ui/issues/issue-16745.rs new file mode 100644 index 000000000..e9137df0f --- /dev/null +++ b/tests/ui/issues/issue-16745.rs @@ -0,0 +1,11 @@ +// run-pass +fn main() { + const X: u8 = 0; + let out: u8 = match 0u8 { + X => 99, + b'\t' => 1, + 1u8 => 2, + _ => 3, + }; + assert_eq!(out, 99); +} diff --git a/tests/ui/issues/issue-16774.rs b/tests/ui/issues/issue-16774.rs new file mode 100644 index 000000000..2b308ef76 --- /dev/null +++ b/tests/ui/issues/issue-16774.rs @@ -0,0 +1,45 @@ +// run-pass +#![feature(box_patterns)] + +use std::ops::{Deref, DerefMut}; + +struct X(Box); + +static mut DESTRUCTOR_RAN: bool = false; + +impl Drop for X { + fn drop(&mut self) { + unsafe { + assert!(!DESTRUCTOR_RAN); + DESTRUCTOR_RAN = true; + } + } +} + +impl Deref for X { + type Target = isize; + + fn deref(&self) -> &isize { + let &X(box ref x) = self; + x + } +} + +impl DerefMut for X { + fn deref_mut(&mut self) -> &mut isize { + let &mut X(box ref mut x) = self; + x + } +} + +fn main() { + { + let mut test = X(Box::new(5)); + { + let mut change = || { *test = 10 }; + change(); + } + assert_eq!(*test, 10); + } + assert!(unsafe { DESTRUCTOR_RAN }); +} diff --git a/tests/ui/issues/issue-16783.rs b/tests/ui/issues/issue-16783.rs new file mode 100644 index 000000000..4af4031d2 --- /dev/null +++ b/tests/ui/issues/issue-16783.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +pub fn main() { + let x = [1, 2, 3]; + let y = x; +} diff --git a/tests/ui/issues/issue-16819.rs b/tests/ui/issues/issue-16819.rs new file mode 100644 index 000000000..cc0200904 --- /dev/null +++ b/tests/ui/issues/issue-16819.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(unused_variables)] +// `#[cfg]` on struct field permits empty unusable struct + +struct S { + #[cfg(untrue)] + a: int, +} + +fn main() { + let s = S {}; +} diff --git a/tests/ui/issues/issue-16922-rpass.rs b/tests/ui/issues/issue-16922-rpass.rs new file mode 100644 index 000000000..c3c6ff304 --- /dev/null +++ b/tests/ui/issues/issue-16922-rpass.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::any::Any; + +fn foo(_: &u8) { +} + +fn main() { + let _ = &foo as &dyn Any; +} diff --git a/tests/ui/issues/issue-16922.rs b/tests/ui/issues/issue-16922.rs new file mode 100644 index 000000000..bbbbf72db --- /dev/null +++ b/tests/ui/issues/issue-16922.rs @@ -0,0 +1,10 @@ +use std::any::Any; + +fn foo(value: &T) -> Box { + Box::new(value) as Box + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let _ = foo(&5); +} diff --git a/tests/ui/issues/issue-16922.stderr b/tests/ui/issues/issue-16922.stderr new file mode 100644 index 000000000..9d9f32a97 --- /dev/null +++ b/tests/ui/issues/issue-16922.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/issue-16922.rs:4:5 + | +LL | fn foo(value: &T) -> Box { + | - let's call the lifetime of this reference `'1` +LL | Box::new(value) as Box + | ^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound + | +LL | fn foo(value: &T) -> Box { + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-16939.rs b/tests/ui/issues/issue-16939.rs new file mode 100644 index 000000000..ad7248343 --- /dev/null +++ b/tests/ui/issues/issue-16939.rs @@ -0,0 +1,8 @@ +// Make sure we don't ICE when making an overloaded call with the +// wrong arity. + +fn _foo (f: F) { + |t| f(t); //~ ERROR E0057 +} + +fn main() {} diff --git a/tests/ui/issues/issue-16939.stderr b/tests/ui/issues/issue-16939.stderr new file mode 100644 index 000000000..766456454 --- /dev/null +++ b/tests/ui/issues/issue-16939.stderr @@ -0,0 +1,19 @@ +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/issue-16939.rs:5:9 + | +LL | |t| f(t); + | ^ - argument unexpected + | +note: callable defined here + --> $DIR/issue-16939.rs:4:12 + | +LL | fn _foo (f: F) { + | ^^^^ +help: remove the extra argument + | +LL | |t| f(); + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/issues/issue-1696.rs b/tests/ui/issues/issue-1696.rs new file mode 100644 index 000000000..b5d77df3a --- /dev/null +++ b/tests/ui/issues/issue-1696.rs @@ -0,0 +1,8 @@ +// run-pass +use std::collections::HashMap; + +pub fn main() { + let mut m = HashMap::new(); + m.insert(b"foo".to_vec(), b"bar".to_vec()); + println!("{:?}", m); +} diff --git a/tests/ui/issues/issue-16966.rs b/tests/ui/issues/issue-16966.rs new file mode 100644 index 000000000..9c6188350 --- /dev/null +++ b/tests/ui/issues/issue-16966.rs @@ -0,0 +1,4 @@ +fn main() { + panic!(std::default::Default::default()); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-16966.stderr b/tests/ui/issues/issue-16966.stderr new file mode 100644 index 000000000..60f5190db --- /dev/null +++ b/tests/ui/issues/issue-16966.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/issue-16966.rs:2:5 + | +LL | panic!(std::default::Default::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic` + | + = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-16994.rs b/tests/ui/issues/issue-16994.rs new file mode 100644 index 000000000..8d3074bce --- /dev/null +++ b/tests/ui/issues/issue-16994.rs @@ -0,0 +1,9 @@ +// check-pass + +fn cb<'a,T>(_x: Box, bool))) -> T>) -> T { + panic!() +} + +fn main() { + cb(Box::new(|(k, &(ref v, b))| (*k, v.clone(), b))); +} diff --git a/tests/ui/issues/issue-17001.rs b/tests/ui/issues/issue-17001.rs new file mode 100644 index 000000000..68cb2865f --- /dev/null +++ b/tests/ui/issues/issue-17001.rs @@ -0,0 +1,5 @@ +mod foo {} + +fn main() { + let p = foo { x: () }; //~ ERROR expected struct, variant or union type, found module `foo` +} diff --git a/tests/ui/issues/issue-17001.stderr b/tests/ui/issues/issue-17001.stderr new file mode 100644 index 000000000..d7e606997 --- /dev/null +++ b/tests/ui/issues/issue-17001.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found module `foo` + --> $DIR/issue-17001.rs:4:13 + | +LL | let p = foo { x: () }; + | ^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-17033.rs b/tests/ui/issues/issue-17033.rs new file mode 100644 index 000000000..72a8cd982 --- /dev/null +++ b/tests/ui/issues/issue-17033.rs @@ -0,0 +1,6 @@ +fn f<'r>(p: &'r mut fn(p: &mut ())) { + (*p)(()) //~ ERROR mismatched types + //~| expected `&mut ()`, found `()` +} + +fn main() {} diff --git a/tests/ui/issues/issue-17033.stderr b/tests/ui/issues/issue-17033.stderr new file mode 100644 index 000000000..f26bee5ff --- /dev/null +++ b/tests/ui/issues/issue-17033.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/issue-17033.rs:2:10 + | +LL | (*p)(()) + | ---- ^^ + | | | + | | expected `&mut ()`, found `()` + | | help: consider mutably borrowing here: `&mut ()` + | arguments to this function are incorrect + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-17068.rs b/tests/ui/issues/issue-17068.rs new file mode 100644 index 000000000..fe2c1a34b --- /dev/null +++ b/tests/ui/issues/issue-17068.rs @@ -0,0 +1,12 @@ +// run-pass +// Test that regionck creates the right region links in the pattern +// binding of a for loop + +fn foo<'a>(v: &'a [usize]) -> &'a usize { + for &ref x in v { return x; } + unreachable!() +} + +fn main() { + assert_eq!(foo(&[0]), &0); +} diff --git a/tests/ui/issues/issue-17121.rs b/tests/ui/issues/issue-17121.rs new file mode 100644 index 000000000..1e7b9f015 --- /dev/null +++ b/tests/ui/issues/issue-17121.rs @@ -0,0 +1,31 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::fs::File; +use std::io::{self, BufReader, Read}; + +struct Lexer +{ + reader: BufReader, +} + +impl Lexer +{ + pub fn new_from_reader(r: R) -> Lexer + { + Lexer{reader: BufReader::new(r)} + } + + pub fn new_from_file(p: &str) -> io::Result> + { + Ok(Lexer::new_from_reader(File::open(p)?)) + } + + pub fn new_from_str<'a>(s: &'a str) -> Lexer<&'a [u8]> + { + Lexer::new_from_reader(s.as_bytes()) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-17216.rs b/tests/ui/issues/issue-17216.rs new file mode 100644 index 000000000..05baa1bff --- /dev/null +++ b/tests/ui/issues/issue-17216.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_variables)] +struct Leak<'a> { + dropped: &'a mut bool +} + +impl<'a> Drop for Leak<'a> { + fn drop(&mut self) { + *self.dropped = true; + } +} + +fn main() { + let mut dropped = false; + { + let leak = Leak { dropped: &mut dropped }; + for ((), leaked) in Some(((), leak)).into_iter() {} + } + + assert!(dropped); +} diff --git a/tests/ui/issues/issue-17252.rs b/tests/ui/issues/issue-17252.rs new file mode 100644 index 000000000..7141e4874 --- /dev/null +++ b/tests/ui/issues/issue-17252.rs @@ -0,0 +1,10 @@ +const FOO: usize = FOO; //~ ERROR E0391 + +fn main() { + let _x: [u8; FOO]; // caused stack overflow prior to fix + let _y: usize = 1 + { + const BAR: usize = BAR; + let _z: [u8; BAR]; // caused stack overflow prior to fix + 1 + }; +} diff --git a/tests/ui/issues/issue-17252.stderr b/tests/ui/issues/issue-17252.stderr new file mode 100644 index 000000000..aca5242b2 --- /dev/null +++ b/tests/ui/issues/issue-17252.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when const-evaluating + checking `FOO` + --> $DIR/issue-17252.rs:1:20 + | +LL | const FOO: usize = FOO; + | ^^^ + | + = note: ...which immediately requires const-evaluating + checking `FOO` again +note: cycle used when const-evaluating + checking `main::{constant#0}` + --> $DIR/issue-17252.rs:4:18 + | +LL | let _x: [u8; FOO]; // caused stack overflow prior to fix + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-17302.rs b/tests/ui/issues/issue-17302.rs new file mode 100644 index 000000000..cf7a2f1b0 --- /dev/null +++ b/tests/ui/issues/issue-17302.rs @@ -0,0 +1,26 @@ +// run-pass + +static mut DROPPED: [bool; 2] = [false, false]; + +struct A(usize); +struct Foo { _a: A, _b: isize } + +impl Drop for A { + fn drop(&mut self) { + let A(i) = *self; + unsafe { DROPPED[i] = true; } + } +} + +fn main() { + { + Foo { + _a: A(0), + ..Foo { _a: A(1), _b: 2 } + }; + } + unsafe { + assert!(DROPPED[0]); + assert!(DROPPED[1]); + } +} diff --git a/tests/ui/issues/issue-17322.rs b/tests/ui/issues/issue-17322.rs new file mode 100644 index 000000000..b4fc40c3f --- /dev/null +++ b/tests/ui/issues/issue-17322.rs @@ -0,0 +1,13 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::io::{self, Write}; + +fn f(wr: &mut dyn Write) { + wr.write_all(b"hello").ok().expect("failed"); +} + +fn main() { + let mut wr = Box::new(io::stdout()) as Box; + f(&mut wr); +} diff --git a/tests/ui/issues/issue-17336.rs b/tests/ui/issues/issue-17336.rs new file mode 100644 index 000000000..89ce59b11 --- /dev/null +++ b/tests/ui/issues/issue-17336.rs @@ -0,0 +1,9 @@ +// build-pass +#![allow(unused_must_use)] +#[allow(dead_code)] +fn check(a: &str) { + let x = a as *const str; + x == x; +} + +fn main() {} diff --git a/tests/ui/issues/issue-17337.rs b/tests/ui/issues/issue-17337.rs new file mode 100644 index 000000000..193f89f83 --- /dev/null +++ b/tests/ui/issues/issue-17337.rs @@ -0,0 +1,17 @@ +#![feature(staged_api)] +#![deny(deprecated)] + +#![unstable(feature = "unstable_test_feature", issue = "none")] + +struct Foo; + +impl Foo { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn foo(self) {} +} + +fn main() { + Foo + .foo(); //~ ERROR use of deprecated +} diff --git a/tests/ui/issues/issue-17337.stderr b/tests/ui/issues/issue-17337.stderr new file mode 100644 index 000000000..34c2eb05f --- /dev/null +++ b/tests/ui/issues/issue-17337.stderr @@ -0,0 +1,14 @@ +error: use of deprecated associated function `Foo::foo`: text + --> $DIR/issue-17337.rs:16:6 + | +LL | .foo(); + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-17337.rs:2:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-17351.rs b/tests/ui/issues/issue-17351.rs new file mode 100644 index 000000000..62f6bcf15 --- /dev/null +++ b/tests/ui/issues/issue-17351.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Str { fn foo(&self) {} } +impl Str for str {} +impl<'a, S: ?Sized> Str for &'a S where S: Str {} + +fn main() { + let _: &dyn Str = &"x"; +} diff --git a/tests/ui/issues/issue-17361.rs b/tests/ui/issues/issue-17361.rs new file mode 100644 index 000000000..e97fc3afd --- /dev/null +++ b/tests/ui/issues/issue-17361.rs @@ -0,0 +1,9 @@ +// run-pass +// Test that astconv doesn't forget about mutability of &mut str + +// pretty-expanded FIXME #23616 + +fn main() { + fn foo(_: &mut T) {} + let _f: fn(&mut str) = foo; +} diff --git a/tests/ui/issues/issue-17373.rs b/tests/ui/issues/issue-17373.rs new file mode 100644 index 000000000..dc3be48a7 --- /dev/null +++ b/tests/ui/issues/issue-17373.rs @@ -0,0 +1,4 @@ +fn main() { + *return //~ ERROR type `!` cannot be dereferenced + ; +} diff --git a/tests/ui/issues/issue-17373.stderr b/tests/ui/issues/issue-17373.stderr new file mode 100644 index 000000000..5c429d111 --- /dev/null +++ b/tests/ui/issues/issue-17373.stderr @@ -0,0 +1,9 @@ +error[E0614]: type `!` cannot be dereferenced + --> $DIR/issue-17373.rs:2:5 + | +LL | *return + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/issues/issue-17385.rs b/tests/ui/issues/issue-17385.rs new file mode 100644 index 000000000..7400aadb0 --- /dev/null +++ b/tests/ui/issues/issue-17385.rs @@ -0,0 +1,29 @@ +struct X(isize); + +enum Enum { + Variant1, + Variant2 +} + +impl Drop for X { + fn drop(&mut self) {} +} +impl Drop for Enum { + fn drop(&mut self) {} +} + +fn main() { + let foo = X(1); + drop(foo); + match foo { //~ ERROR use of moved value + X(1) => (), + _ => unreachable!() + } + + let e = Enum::Variant2; + drop(e); + match e { //~ ERROR use of moved value + Enum::Variant1 => unreachable!(), + Enum::Variant2 => () + } +} diff --git a/tests/ui/issues/issue-17385.stderr b/tests/ui/issues/issue-17385.stderr new file mode 100644 index 000000000..77aa201b3 --- /dev/null +++ b/tests/ui/issues/issue-17385.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/issue-17385.rs:18:5 + | +LL | let foo = X(1); + | --- move occurs because `foo` has type `X`, which does not implement the `Copy` trait +LL | drop(foo); + | --- value moved here +LL | match foo { + | ^^^^^^^^^ value used here after move + +error[E0382]: use of moved value: `e` + --> $DIR/issue-17385.rs:25:11 + | +LL | let e = Enum::Variant2; + | - move occurs because `e` has type `Enum`, which does not implement the `Copy` trait +LL | drop(e); + | - value moved here +LL | match e { + | ^ value used here after move + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-17405.rs b/tests/ui/issues/issue-17405.rs new file mode 100644 index 000000000..14781a7d3 --- /dev/null +++ b/tests/ui/issues/issue-17405.rs @@ -0,0 +1,9 @@ +enum Foo { + Bar(isize) +} + +fn main() { + match Foo::Bar(1) { + Foo { i } => () //~ ERROR expected struct, variant or union type, found enum `Foo` + } +} diff --git a/tests/ui/issues/issue-17405.stderr b/tests/ui/issues/issue-17405.stderr new file mode 100644 index 000000000..37274e239 --- /dev/null +++ b/tests/ui/issues/issue-17405.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found enum `Foo` + --> $DIR/issue-17405.rs:7:9 + | +LL | Foo { i } => () + | ^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-17431-1.rs b/tests/ui/issues/issue-17431-1.rs new file mode 100644 index 000000000..3b692cc0e --- /dev/null +++ b/tests/ui/issues/issue-17431-1.rs @@ -0,0 +1,6 @@ +struct Foo { foo: Option> } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/issues/issue-17431-1.stderr b/tests/ui/issues/issue-17431-1.stderr new file mode 100644 index 000000000..e3af8976c --- /dev/null +++ b/tests/ui/issues/issue-17431-1.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-1.rs:1:1 + | +LL | struct Foo { foo: Option> } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo { foo: Option>> } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-2.rs b/tests/ui/issues/issue-17431-2.rs new file mode 100644 index 000000000..f7b9c6a55 --- /dev/null +++ b/tests/ui/issues/issue-17431-2.rs @@ -0,0 +1,8 @@ +struct Baz { q: Option } +//~^ ERROR recursive types `Baz` and `Foo` have infinite size + +struct Foo { q: Option } + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/issues/issue-17431-2.stderr b/tests/ui/issues/issue-17431-2.stderr new file mode 100644 index 000000000..39a99ec1e --- /dev/null +++ b/tests/ui/issues/issue-17431-2.stderr @@ -0,0 +1,20 @@ +error[E0072]: recursive types `Baz` and `Foo` have infinite size + --> $DIR/issue-17431-2.rs:1:1 + | +LL | struct Baz { q: Option } + | ^^^^^^^^^^ --- recursive without indirection +... +LL | struct Foo { q: Option } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ struct Baz { q: Option> } +LL | +LL | +LL ~ struct Foo { q: Option> } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-3.rs b/tests/ui/issues/issue-17431-3.rs new file mode 100644 index 000000000..83a63a88b --- /dev/null +++ b/tests/ui/issues/issue-17431-3.rs @@ -0,0 +1,8 @@ +use std::sync::Mutex; + +struct Foo { foo: Mutex> } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/issues/issue-17431-3.stderr b/tests/ui/issues/issue-17431-3.stderr new file mode 100644 index 000000000..394134c78 --- /dev/null +++ b/tests/ui/issues/issue-17431-3.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-3.rs:3:1 + | +LL | struct Foo { foo: Mutex> } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo { foo: Mutex>> } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-4.rs b/tests/ui/issues/issue-17431-4.rs new file mode 100644 index 000000000..48f0dba2a --- /dev/null +++ b/tests/ui/issues/issue-17431-4.rs @@ -0,0 +1,8 @@ +use std::marker; + +struct Foo { foo: Option>>, marker: marker::PhantomData } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/issues/issue-17431-4.stderr b/tests/ui/issues/issue-17431-4.stderr new file mode 100644 index 000000000..3d141e44b --- /dev/null +++ b/tests/ui/issues/issue-17431-4.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-4.rs:3:1 + | +LL | struct Foo { foo: Option>>, marker: marker::PhantomData } + | ^^^^^^^^^^^^^ ------ recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo { foo: Option>>>, marker: marker::PhantomData } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-5.rs b/tests/ui/issues/issue-17431-5.rs new file mode 100644 index 000000000..0fd6ee611 --- /dev/null +++ b/tests/ui/issues/issue-17431-5.rs @@ -0,0 +1,11 @@ +use std::marker; + +struct Foo { foo: Bar } + +struct Bar { x: Bar , marker: marker::PhantomData } +//~^ ERROR recursive type `Bar` has infinite size + +impl Foo { fn foo(&self) {} } + +fn main() { +} diff --git a/tests/ui/issues/issue-17431-5.stderr b/tests/ui/issues/issue-17431-5.stderr new file mode 100644 index 000000000..44a90a6fe --- /dev/null +++ b/tests/ui/issues/issue-17431-5.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Bar` has infinite size + --> $DIR/issue-17431-5.rs:5:1 + | +LL | struct Bar { x: Bar , marker: marker::PhantomData } + | ^^^^^^^^^^^^^ -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Bar { x: Box> , marker: marker::PhantomData } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-6.rs b/tests/ui/issues/issue-17431-6.rs new file mode 100644 index 000000000..b7e49873d --- /dev/null +++ b/tests/ui/issues/issue-17431-6.rs @@ -0,0 +1,8 @@ +use std::sync::Mutex; + +enum Foo { X(Mutex>) } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(self) {} } + +fn main() {} diff --git a/tests/ui/issues/issue-17431-6.stderr b/tests/ui/issues/issue-17431-6.stderr new file mode 100644 index 000000000..e0a822550 --- /dev/null +++ b/tests/ui/issues/issue-17431-6.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-6.rs:3:1 + | +LL | enum Foo { X(Mutex>) } + | ^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum Foo { X(Mutex>>) } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17431-7.rs b/tests/ui/issues/issue-17431-7.rs new file mode 100644 index 000000000..4fd786278 --- /dev/null +++ b/tests/ui/issues/issue-17431-7.rs @@ -0,0 +1,6 @@ +enum Foo { Voo(Option>) } +//~^ ERROR recursive type `Foo` has infinite size + +impl Foo { fn bar(&self) {} } + +fn main() { } diff --git a/tests/ui/issues/issue-17431-7.stderr b/tests/ui/issues/issue-17431-7.stderr new file mode 100644 index 000000000..ecf072b8e --- /dev/null +++ b/tests/ui/issues/issue-17431-7.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-17431-7.rs:1:1 + | +LL | enum Foo { Voo(Option>) } + | ^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum Foo { Voo(Option>>) } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-17441.rs b/tests/ui/issues/issue-17441.rs new file mode 100644 index 000000000..e5f83c4eb --- /dev/null +++ b/tests/ui/issues/issue-17441.rs @@ -0,0 +1,13 @@ +fn main() { + let _foo = &[1_usize, 2] as [usize]; + //~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]` + + let _bar = Box::new(1_usize) as dyn std::fmt::Debug; + //~^ ERROR cast to unsized type: `Box` as `dyn Debug` + + let _baz = 1_usize as dyn std::fmt::Debug; + //~^ ERROR cast to unsized type: `usize` as `dyn Debug` + + let _quux = [1_usize, 2] as [usize]; + //~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]` +} diff --git a/tests/ui/issues/issue-17441.stderr b/tests/ui/issues/issue-17441.stderr new file mode 100644 index 000000000..4dbe50178 --- /dev/null +++ b/tests/ui/issues/issue-17441.stderr @@ -0,0 +1,47 @@ +error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]` + --> $DIR/issue-17441.rs:2:16 + | +LL | let _foo = &[1_usize, 2] as [usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using an implicit coercion to `&[usize]` instead + --> $DIR/issue-17441.rs:2:16 + | +LL | let _foo = &[1_usize, 2] as [usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0620]: cast to unsized type: `Box` as `dyn Debug` + --> $DIR/issue-17441.rs:5:16 + | +LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^^------------------- + | | + | help: you can cast to a `Box` instead: `Box` + +error[E0620]: cast to unsized type: `usize` as `dyn Debug` + --> $DIR/issue-17441.rs:8:16 + | +LL | let _baz = 1_usize as dyn std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a box or reference as appropriate + --> $DIR/issue-17441.rs:8:16 + | +LL | let _baz = 1_usize as dyn std::fmt::Debug; + | ^^^^^^^ + +error[E0620]: cast to unsized type: `[usize; 2]` as `[usize]` + --> $DIR/issue-17441.rs:11:17 + | +LL | let _quux = [1_usize, 2] as [usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using a box or reference as appropriate + --> $DIR/issue-17441.rs:11:17 + | +LL | let _quux = [1_usize, 2] as [usize]; + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0620`. diff --git a/tests/ui/issues/issue-17450.rs b/tests/ui/issues/issue-17450.rs new file mode 100644 index 000000000..1ac0af175 --- /dev/null +++ b/tests/ui/issues/issue-17450.rs @@ -0,0 +1,7 @@ +// build-pass +#![allow(dead_code, warnings)] + +static mut x: isize = 3; +static mut y: isize = unsafe { x }; + +fn main() {} diff --git a/tests/ui/issues/issue-17503.rs b/tests/ui/issues/issue-17503.rs new file mode 100644 index 000000000..9a92c06e1 --- /dev/null +++ b/tests/ui/issues/issue-17503.rs @@ -0,0 +1,10 @@ +// run-pass +fn main() { + let s: &[isize] = &[0, 1, 2, 3, 4]; + let ss: &&[isize] = &s; + let sss: &&&[isize] = &ss; + + println!("{:?}", &s[..3]); + println!("{:?}", &ss[3..]); + println!("{:?}", &sss[2..4]); +} diff --git a/tests/ui/issues/issue-17546.rs b/tests/ui/issues/issue-17546.rs new file mode 100644 index 000000000..6c62010f1 --- /dev/null +++ b/tests/ui/issues/issue-17546.rs @@ -0,0 +1,42 @@ +// ignore-sgx std::os::fortanix_sgx::usercalls::raw::Result changes compiler suggestions + +use foo::MyEnum::Result; +use foo::NoResult; // Through a re-export + +mod foo { + pub use self::MyEnum::NoResult; + + pub enum MyEnum { + Result, + NoResult + } + + fn new() -> NoResult { + //~^ ERROR expected type, found variant `NoResult` + unimplemented!() + } +} + +mod bar { + use foo::MyEnum::Result; + use foo; + + fn new() -> Result { + //~^ ERROR expected type, found variant `Result` + unimplemented!() + } +} + +fn new() -> Result { + //~^ ERROR expected type, found variant `Result` + unimplemented!() +} + +fn newer() -> NoResult { + //~^ ERROR expected type, found variant `NoResult` + unimplemented!() +} + +fn main() { + let _ = new(); +} diff --git a/tests/ui/issues/issue-17546.stderr b/tests/ui/issues/issue-17546.stderr new file mode 100644 index 000000000..81592320a --- /dev/null +++ b/tests/ui/issues/issue-17546.stderr @@ -0,0 +1,73 @@ +error[E0573]: expected type, found variant `NoResult` + --> $DIR/issue-17546.rs:14:17 + | +LL | fn new() -> NoResult { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: similarly named enum `Result` defined here + | +help: try using the variant's enum + | +LL | fn new() -> foo::MyEnum { + | ~~~~~~~~~~~ +help: an enum with a similar name exists + | +LL | fn new() -> Result { + | ~~~~~~ + +error[E0573]: expected type, found variant `Result` + --> $DIR/issue-17546.rs:24:17 + | +LL | fn new() -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type + | +help: consider importing one of these items instead + | +LL | use std::fmt::Result; + | +LL | use std::io::Result; + | +LL | use std::result::Result; + | +LL | use std::thread::Result; + | + +error[E0573]: expected type, found variant `Result` + --> $DIR/issue-17546.rs:30:13 + | +LL | fn new() -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a type + | +help: consider importing one of these items instead + | +LL | use std::fmt::Result; + | +LL | use std::io::Result; + | +LL | use std::result::Result; + | +LL | use std::thread::Result; + | + +error[E0573]: expected type, found variant `NoResult` + --> $DIR/issue-17546.rs:35:15 + | +LL | fn newer() -> NoResult { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: similarly named enum `Result` defined here + | +help: try using the variant's enum + | +LL | fn newer() -> foo::MyEnum { + | ~~~~~~~~~~~ +help: an enum with a similar name exists + | +LL | fn newer() -> Result { + | ~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/issues/issue-17551.rs b/tests/ui/issues/issue-17551.rs new file mode 100644 index 000000000..a65957ce0 --- /dev/null +++ b/tests/ui/issues/issue-17551.rs @@ -0,0 +1,8 @@ +use std::marker; + +struct B(marker::PhantomData); + +fn main() { + let foo = B(marker::PhantomData); //~ ERROR type annotations needed + let closure = || foo; +} diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr new file mode 100644 index 000000000..5f45a2f84 --- /dev/null +++ b/tests/ui/issues/issue-17551.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `B` + --> $DIR/issue-17551.rs:6:9 + | +LL | let foo = B(marker::PhantomData); + | ^^^ + | +help: consider giving `foo` an explicit type, where the type for type parameter `T` is specified + | +LL | let foo: B = B(marker::PhantomData); + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-17651.rs b/tests/ui/issues/issue-17651.rs new file mode 100644 index 000000000..7629a5a3b --- /dev/null +++ b/tests/ui/issues/issue-17651.rs @@ -0,0 +1,7 @@ +// Test that moves of unsized values within closures are caught +// and rejected. + +fn main() { + (|| Box::new(*(&[0][..])))(); + //~^ ERROR the size for values of type +} diff --git a/tests/ui/issues/issue-17651.stderr b/tests/ui/issues/issue-17651.stderr new file mode 100644 index 000000000..b37811e19 --- /dev/null +++ b/tests/ui/issues/issue-17651.stderr @@ -0,0 +1,15 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/issue-17651.rs:5:18 + | +LL | (|| Box::new(*(&[0][..])))(); + | -------- ^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by a bound in `Box::::new` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-17662.rs b/tests/ui/issues/issue-17662.rs new file mode 100644 index 000000000..a2683808b --- /dev/null +++ b/tests/ui/issues/issue-17662.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:issue-17662.rs + + +extern crate issue_17662 as i; + +use std::marker; + +struct Bar<'a> { m: marker::PhantomData<&'a ()> } + +impl<'a> i::Foo<'a, usize> for Bar<'a> { + fn foo(&self) -> usize { 5 } +} + +pub fn main() { + assert_eq!(i::foo(&Bar { m: marker::PhantomData }), 5); +} diff --git a/tests/ui/issues/issue-17732.rs b/tests/ui/issues/issue-17732.rs new file mode 100644 index 000000000..8f63d5bae --- /dev/null +++ b/tests/ui/issues/issue-17732.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +// pretty-expanded FIXME #23616 + +trait Person { + type string; + fn dummy(&self) { } +} + +struct Someone(std::marker::PhantomData

); + +fn main() {} diff --git a/tests/ui/issues/issue-17734.rs b/tests/ui/issues/issue-17734.rs new file mode 100644 index 000000000..ba8d6c21c --- /dev/null +++ b/tests/ui/issues/issue-17734.rs @@ -0,0 +1,15 @@ +// run-pass +// Test that generating drop glue for Box doesn't ICE + + +fn f(s: Box) -> Box { + s +} + +fn main() { + // There is currently no safe way to construct a `Box`, so improvise + let box_arr: Box<[u8]> = Box::new(['h' as u8, 'e' as u8, 'l' as u8, 'l' as u8, 'o' as u8]); + let box_str: Box = unsafe { std::mem::transmute(box_arr) }; + assert_eq!(&*box_str, "hello"); + f(box_str); +} diff --git a/tests/ui/issues/issue-17740.rs b/tests/ui/issues/issue-17740.rs new file mode 100644 index 000000000..3b868555f --- /dev/null +++ b/tests/ui/issues/issue-17740.rs @@ -0,0 +1,18 @@ +struct Foo<'a> { + data: &'a[u8], +} + +impl <'a> Foo<'a>{ + fn bar(self: &mut Foo) { + //~^ mismatched `self` parameter type + //~| expected struct `Foo<'a>` + //~| found struct `Foo<'_>` + //~| lifetime mismatch + //~| mismatched `self` parameter type + //~| expected struct `Foo<'a>` + //~| found struct `Foo<'_>` + //~| lifetime mismatch + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-17740.stderr b/tests/ui/issues/issue-17740.stderr new file mode 100644 index 000000000..d17738041 --- /dev/null +++ b/tests/ui/issues/issue-17740.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched `self` parameter type + --> $DIR/issue-17740.rs:6:18 + | +LL | fn bar(self: &mut Foo) { + | ^^^^^^^^ lifetime mismatch + | + = note: expected struct `Foo<'a>` + found struct `Foo<'_>` +note: the anonymous lifetime defined here... + --> $DIR/issue-17740.rs:6:23 + | +LL | fn bar(self: &mut Foo) { + | ^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/issue-17740.rs:5:7 + | +LL | impl <'a> Foo<'a>{ + | ^^ + +error[E0308]: mismatched `self` parameter type + --> $DIR/issue-17740.rs:6:18 + | +LL | fn bar(self: &mut Foo) { + | ^^^^^^^^ lifetime mismatch + | + = note: expected struct `Foo<'a>` + found struct `Foo<'_>` +note: the lifetime `'a` as defined here... + --> $DIR/issue-17740.rs:5:7 + | +LL | impl <'a> Foo<'a>{ + | ^^ +note: ...does not necessarily outlive the anonymous lifetime defined here + --> $DIR/issue-17740.rs:6:23 + | +LL | fn bar(self: &mut Foo) { + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-17746.rs b/tests/ui/issues/issue-17746.rs new file mode 100644 index 000000000..bab64a4b5 --- /dev/null +++ b/tests/ui/issues/issue-17746.rs @@ -0,0 +1,25 @@ +// check-pass +#![allow(dead_code)] +// Regression test for #17746 + +fn main() {} + +struct A; + +impl A { + fn b(&mut self) { + self.a() + } +} + +trait Foo { + fn dummy(&self) {} +} +trait Bar { + fn a(&self); +} + +impl Foo for A {} +impl Bar for T where T: Foo { + fn a(&self) {} +} diff --git a/tests/ui/issues/issue-17758.rs b/tests/ui/issues/issue-17758.rs new file mode 100644 index 000000000..e2ee84694 --- /dev/null +++ b/tests/ui/issues/issue-17758.rs @@ -0,0 +1,12 @@ +// Test that regionck suggestions in a provided method of a trait +// don't ICE + +trait Foo<'a> { + fn foo(&'a self); + fn bar(&self) { + self.foo(); + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-17758.stderr b/tests/ui/issues/issue-17758.stderr new file mode 100644 index 000000000..613ef6b90 --- /dev/null +++ b/tests/ui/issues/issue-17758.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/issue-17758.rs:7:9 + | +LL | trait Foo<'a> { + | -- lifetime `'a` defined here +LL | fn foo(&'a self); +LL | fn bar(&self) { + | - let's call the lifetime of this reference `'1` +LL | self.foo(); + | ^^^^^^^^^^ argument requires that `'1` must outlive `'a` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-17771.rs b/tests/ui/issues/issue-17771.rs new file mode 100644 index 000000000..2f6464668 --- /dev/null +++ b/tests/ui/issues/issue-17771.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait Aaa { fn dummy(&self) { } } + +impl<'a> Aaa for &'a mut (dyn Aaa + 'a) {} + +struct Bar<'a> { + writer: &'a mut (dyn Aaa + 'a), +} + +fn baz(_: &mut dyn Aaa) { +} + +fn foo<'a>(mut bar: Bar<'a>) { + baz(&mut bar.writer); +} + +fn main() { +} diff --git a/tests/ui/issues/issue-17800.rs b/tests/ui/issues/issue-17800.rs new file mode 100644 index 000000000..5254f45d7 --- /dev/null +++ b/tests/ui/issues/issue-17800.rs @@ -0,0 +1,12 @@ +enum MyOption { + MySome(T), + MyNone, +} + +fn main() { + match MyOption::MySome(42) { + MyOption::MySome { x: 42 } => (), + //~^ ERROR tuple variant `MyOption::MySome` written as struct variant + _ => (), + } +} diff --git a/tests/ui/issues/issue-17800.stderr b/tests/ui/issues/issue-17800.stderr new file mode 100644 index 000000000..baab67583 --- /dev/null +++ b/tests/ui/issues/issue-17800.stderr @@ -0,0 +1,14 @@ +error[E0769]: tuple variant `MyOption::MySome` written as struct variant + --> $DIR/issue-17800.rs:8:9 + | +LL | MyOption::MySome { x: 42 } => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | MyOption::MySome(42) => (), + | ~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/issues/issue-17816.rs b/tests/ui/issues/issue-17816.rs new file mode 100644 index 000000000..7ca47d503 --- /dev/null +++ b/tests/ui/issues/issue-17816.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_variables)] +use std::marker::PhantomData; + +fn main() { + struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F, marker: PhantomData<&'a ()> } + let f = |x: Vec<&str>| -> &str { "foobar" }; + let sym = Symbol { function: f, marker: PhantomData }; + (sym.function)(vec![]); +} diff --git a/tests/ui/issues/issue-17877.rs b/tests/ui/issues/issue-17877.rs new file mode 100644 index 000000000..126e01de5 --- /dev/null +++ b/tests/ui/issues/issue-17877.rs @@ -0,0 +1,13 @@ +// run-pass + +fn main() { + assert_eq!(match [0u8; 1024] { + _ => 42_usize, + }, 42_usize); + + assert_eq!(match [0u8; 1024] { + [1, ..] => 0_usize, + [0, ..] => 1_usize, + _ => 2_usize + }, 1_usize); +} diff --git a/tests/ui/issues/issue-17897.rs b/tests/ui/issues/issue-17897.rs new file mode 100644 index 000000000..6873c7ccb --- /dev/null +++ b/tests/ui/issues/issue-17897.rs @@ -0,0 +1,8 @@ +// run-pass +fn action(mut cb: Box usize>) -> usize { + cb(1) +} + +pub fn main() { + println!("num: {}", action(Box::new(move |u| u))); +} diff --git a/tests/ui/issues/issue-17904-2.rs b/tests/ui/issues/issue-17904-2.rs new file mode 100644 index 000000000..9603da097 --- /dev/null +++ b/tests/ui/issues/issue-17904-2.rs @@ -0,0 +1,6 @@ +// Test that we can parse a unit struct with a where clause, even if +// it leads to an error later on since `T` is unused. + +struct Foo where T: Copy; //~ ERROR parameter `T` is never used + +fn main() {} diff --git a/tests/ui/issues/issue-17904-2.stderr b/tests/ui/issues/issue-17904-2.stderr new file mode 100644 index 000000000..62b7b7953 --- /dev/null +++ b/tests/ui/issues/issue-17904-2.stderr @@ -0,0 +1,11 @@ +error[E0392]: parameter `T` is never used + --> $DIR/issue-17904-2.rs:4:12 + | +LL | struct Foo where T: Copy; + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/issues/issue-17904.rs b/tests/ui/issues/issue-17904.rs new file mode 100644 index 000000000..c3f504ac1 --- /dev/null +++ b/tests/ui/issues/issue-17904.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +// Test that we can parse where clauses on various forms of tuple +// structs. + +// pretty-expanded FIXME #23616 + +struct Bar(T) where T: Copy; +struct Bleh(T, U) where T: Copy, U: Sized; +struct Baz where T: Copy { + field: T +} + +fn main() {} diff --git a/tests/ui/issues/issue-17905-2.rs b/tests/ui/issues/issue-17905-2.rs new file mode 100644 index 000000000..44279cc86 --- /dev/null +++ b/tests/ui/issues/issue-17905-2.rs @@ -0,0 +1,18 @@ +#[derive(Debug)] +struct Pair (T, V); + +impl Pair< + &str, + isize +> { + fn say(self: &Pair<&str, isize>) { +//~^ ERROR mismatched `self` parameter type +//~| ERROR mismatched `self` parameter type + println!("{:?}", self); + } +} + +fn main() { + let result = &Pair("shane", 1); + result.say(); +} diff --git a/tests/ui/issues/issue-17905-2.stderr b/tests/ui/issues/issue-17905-2.stderr new file mode 100644 index 000000000..88b5fbec6 --- /dev/null +++ b/tests/ui/issues/issue-17905-2.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched `self` parameter type + --> $DIR/issue-17905-2.rs:8:18 + | +LL | fn say(self: &Pair<&str, isize>) { + | ^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected struct `Pair<&str, _>` + found struct `Pair<&str, _>` +note: the anonymous lifetime defined here... + --> $DIR/issue-17905-2.rs:8:24 + | +LL | fn say(self: &Pair<&str, isize>) { + | ^^^^ +note: ...does not necessarily outlive the anonymous lifetime as defined here + --> $DIR/issue-17905-2.rs:5:5 + | +LL | &str, + | ^ + +error[E0308]: mismatched `self` parameter type + --> $DIR/issue-17905-2.rs:8:18 + | +LL | fn say(self: &Pair<&str, isize>) { + | ^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected struct `Pair<&str, _>` + found struct `Pair<&str, _>` +note: the anonymous lifetime as defined here... + --> $DIR/issue-17905-2.rs:5:5 + | +LL | &str, + | ^ +note: ...does not necessarily outlive the anonymous lifetime defined here + --> $DIR/issue-17905-2.rs:8:24 + | +LL | fn say(self: &Pair<&str, isize>) { + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-17905.rs b/tests/ui/issues/issue-17905.rs new file mode 100644 index 000000000..dae9648b9 --- /dev/null +++ b/tests/ui/issues/issue-17905.rs @@ -0,0 +1,19 @@ +// run-pass + +#[derive(Debug)] +#[allow(unused_tuple_struct_fields)] +struct Pair (T, V); + +impl Pair< + &str, + isize +> { + fn say(&self) { + println!("{:?}", self); + } +} + +fn main() { + let result = &Pair("shane", 1); + result.say(); +} diff --git a/tests/ui/issues/issue-17933.rs b/tests/ui/issues/issue-17933.rs new file mode 100644 index 000000000..6da4e6e15 --- /dev/null +++ b/tests/ui/issues/issue-17933.rs @@ -0,0 +1,9 @@ +pub static X: usize = 1; + +fn main() { + match 1 { + self::X => { }, + //~^ ERROR expected unit struct, unit variant or constant, found static `self::X` + _ => { }, + } +} diff --git a/tests/ui/issues/issue-17933.stderr b/tests/ui/issues/issue-17933.stderr new file mode 100644 index 000000000..33534d3f8 --- /dev/null +++ b/tests/ui/issues/issue-17933.stderr @@ -0,0 +1,9 @@ +error[E0532]: expected unit struct, unit variant or constant, found static `self::X` + --> $DIR/issue-17933.rs:5:9 + | +LL | self::X => { }, + | ^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-17954.rs b/tests/ui/issues/issue-17954.rs new file mode 100644 index 000000000..eb6a3d70f --- /dev/null +++ b/tests/ui/issues/issue-17954.rs @@ -0,0 +1,15 @@ +#![feature(thread_local)] + +#[thread_local] +static FOO: u8 = 3; + +fn main() { + let a = &FOO; + //~^ ERROR thread-local variable borrowed past end of function + //~| NOTE thread-local variables cannot be borrowed beyond the end of the function + + std::thread::spawn(move || { + println!("{}", a); + }); +} +//~^ NOTE end of enclosing function is here diff --git a/tests/ui/issues/issue-17954.stderr b/tests/ui/issues/issue-17954.stderr new file mode 100644 index 000000000..e08375fee --- /dev/null +++ b/tests/ui/issues/issue-17954.stderr @@ -0,0 +1,12 @@ +error[E0712]: thread-local variable borrowed past end of function + --> $DIR/issue-17954.rs:7:13 + | +LL | let a = &FOO; + | ^^^^ thread-local variables cannot be borrowed beyond the end of the function +... +LL | } + | - end of enclosing function is here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0712`. diff --git a/tests/ui/issues/issue-17959.rs b/tests/ui/issues/issue-17959.rs new file mode 100644 index 000000000..8bf9e6236 --- /dev/null +++ b/tests/ui/issues/issue-17959.rs @@ -0,0 +1,21 @@ +extern crate core; + +use core::ops::Drop; + +trait Bar {} + +struct G { + _ptr: *const T +} + +impl Drop for G { +//~^ ERROR `Drop` impl requires `T: Sized` + fn drop(&mut self) { + if !self._ptr.is_null() { + } + } +} + +fn main() { + let x:G; +} diff --git a/tests/ui/issues/issue-17959.stderr b/tests/ui/issues/issue-17959.stderr new file mode 100644 index 000000000..fb795febf --- /dev/null +++ b/tests/ui/issues/issue-17959.stderr @@ -0,0 +1,15 @@ +error[E0367]: `Drop` impl requires `T: Sized` but the struct it is implemented for does not + --> $DIR/issue-17959.rs:11:6 + | +LL | impl Drop for G { + | ^ + | +note: the implementor must specify the same requirement + --> $DIR/issue-17959.rs:7:1 + | +LL | struct G { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0367`. diff --git a/tests/ui/issues/issue-17994.rs b/tests/ui/issues/issue-17994.rs new file mode 100644 index 000000000..39b0a7ebe --- /dev/null +++ b/tests/ui/issues/issue-17994.rs @@ -0,0 +1,3 @@ +trait Tr {} +type Huh where T: Tr = isize; //~ ERROR type parameter `T` is unused +fn main() {} diff --git a/tests/ui/issues/issue-17994.stderr b/tests/ui/issues/issue-17994.stderr new file mode 100644 index 000000000..61e1e496f --- /dev/null +++ b/tests/ui/issues/issue-17994.stderr @@ -0,0 +1,9 @@ +error[E0091]: type parameter `T` is unused + --> $DIR/issue-17994.rs:2:10 + | +LL | type Huh where T: Tr = isize; + | ^ unused type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0091`. diff --git a/tests/ui/issues/issue-17999.rs b/tests/ui/issues/issue-17999.rs new file mode 100644 index 000000000..941f1e775 --- /dev/null +++ b/tests/ui/issues/issue-17999.rs @@ -0,0 +1,10 @@ +#![deny(unused_variables)] + +fn main() { + for _ in 1..101 { + let x = (); //~ ERROR: unused variable: `x` + match () { + a => {} //~ ERROR: unused variable: `a` + } + } +} diff --git a/tests/ui/issues/issue-17999.stderr b/tests/ui/issues/issue-17999.stderr new file mode 100644 index 000000000..4a1ef7350 --- /dev/null +++ b/tests/ui/issues/issue-17999.stderr @@ -0,0 +1,20 @@ +error: unused variable: `x` + --> $DIR/issue-17999.rs:5:13 + | +LL | let x = (); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/issue-17999.rs:1:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `a` + --> $DIR/issue-17999.rs:7:13 + | +LL | a => {} + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-18058.rs b/tests/ui/issues/issue-18058.rs new file mode 100644 index 000000000..cced66717 --- /dev/null +++ b/tests/ui/issues/issue-18058.rs @@ -0,0 +1,4 @@ +impl Undefined {} +//~^ ERROR cannot find type `Undefined` in this scope + +fn main() {} diff --git a/tests/ui/issues/issue-18058.stderr b/tests/ui/issues/issue-18058.stderr new file mode 100644 index 000000000..18159ffc2 --- /dev/null +++ b/tests/ui/issues/issue-18058.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Undefined` in this scope + --> $DIR/issue-18058.rs:1:6 + | +LL | impl Undefined {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-18088.rs b/tests/ui/issues/issue-18088.rs new file mode 100644 index 000000000..c557b5a65 --- /dev/null +++ b/tests/ui/issues/issue-18088.rs @@ -0,0 +1,8 @@ +// check-pass + +pub trait Indexable: std::ops::Index { + fn index2(&self, i: usize) -> &T { + &self[i] + } +} +fn main() {} diff --git a/tests/ui/issues/issue-18107.rs b/tests/ui/issues/issue-18107.rs new file mode 100644 index 000000000..4bf5b6c0f --- /dev/null +++ b/tests/ui/issues/issue-18107.rs @@ -0,0 +1,13 @@ +pub trait AbstractRenderer {} + +fn _create_render(_: &()) -> + dyn AbstractRenderer +//~^ ERROR return type cannot have an unboxed trait object +{ + match 0 { + _ => unimplemented!() + } +} + +fn main() { +} diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/issues/issue-18107.stderr new file mode 100644 index 000000000..1669b550a --- /dev/null +++ b/tests/ui/issues/issue-18107.stderr @@ -0,0 +1,18 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-18107.rs:4:5 + | +LL | dyn AbstractRenderer + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature + | +LL | impl AbstractRenderer + | +help: use a boxed trait object if all return paths implement trait `AbstractRenderer` + | +LL | Box + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/issues/issue-18110.rs b/tests/ui/issues/issue-18110.rs new file mode 100644 index 000000000..41c29e77d --- /dev/null +++ b/tests/ui/issues/issue-18110.rs @@ -0,0 +1,7 @@ +// run-pass +#![allow(unreachable_code)] +// pretty-expanded FIXME #23616 + +fn main() { + ({return},); +} diff --git a/tests/ui/issues/issue-18119.rs b/tests/ui/issues/issue-18119.rs new file mode 100644 index 000000000..e48dc51a2 --- /dev/null +++ b/tests/ui/issues/issue-18119.rs @@ -0,0 +1,12 @@ +const X: u8 = 1; +static Y: u8 = 1; +fn foo() {} + +impl X {} +//~^ ERROR expected type, found constant `X` +impl Y {} +//~^ ERROR expected type, found static `Y` +impl foo {} +//~^ ERROR expected type, found function `foo` + +fn main() {} diff --git a/tests/ui/issues/issue-18119.stderr b/tests/ui/issues/issue-18119.stderr new file mode 100644 index 000000000..ddee5a9da --- /dev/null +++ b/tests/ui/issues/issue-18119.stderr @@ -0,0 +1,21 @@ +error[E0573]: expected type, found constant `X` + --> $DIR/issue-18119.rs:5:6 + | +LL | impl X {} + | ^ not a type + +error[E0573]: expected type, found static `Y` + --> $DIR/issue-18119.rs:7:6 + | +LL | impl Y {} + | ^ not a type + +error[E0573]: expected type, found function `foo` + --> $DIR/issue-18119.rs:9:6 + | +LL | impl foo {} + | ^^^ not a type + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/issues/issue-18159.rs b/tests/ui/issues/issue-18159.rs new file mode 100644 index 000000000..bd347d632 --- /dev/null +++ b/tests/ui/issues/issue-18159.rs @@ -0,0 +1,3 @@ +fn main() { + let x; //~ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-18159.stderr b/tests/ui/issues/issue-18159.stderr new file mode 100644 index 000000000..5e0589eed --- /dev/null +++ b/tests/ui/issues/issue-18159.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-18159.rs:2:9 + | +LL | let x; + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: /* Type */; + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-18173.rs b/tests/ui/issues/issue-18173.rs new file mode 100644 index 000000000..11468040e --- /dev/null +++ b/tests/ui/issues/issue-18173.rs @@ -0,0 +1,12 @@ +// run-pass +trait Foo { + type T; +} + +// should be able to use a trait with an associated type without specifying it as an argument +trait Bar { + fn bar(foo: &F); +} + +pub fn main() { +} diff --git a/tests/ui/issues/issue-18183.rs b/tests/ui/issues/issue-18183.rs new file mode 100644 index 000000000..64476d1c1 --- /dev/null +++ b/tests/ui/issues/issue-18183.rs @@ -0,0 +1,3 @@ +pub struct Foo(Bar); //~ ERROR E0128 +pub struct Baz(Foo); +fn main() {} diff --git a/tests/ui/issues/issue-18183.stderr b/tests/ui/issues/issue-18183.stderr new file mode 100644 index 000000000..a7dc64708 --- /dev/null +++ b/tests/ui/issues/issue-18183.stderr @@ -0,0 +1,9 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/issue-18183.rs:1:20 + | +LL | pub struct Foo(Bar); + | ^^^ defaulted generic parameters cannot be forward declared + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/issues/issue-18188.rs b/tests/ui/issues/issue-18188.rs new file mode 100644 index 000000000..ce166724a --- /dev/null +++ b/tests/ui/issues/issue-18188.rs @@ -0,0 +1,22 @@ +// check-pass +// pretty-expanded FIXME #23616 + +pub trait Promisable: Send + Sync {} +impl Promisable for T {} + +pub fn propagate<'a, T, E, F, G>(mut action: F) + -> Box) -> Result + 'a> + where + T: Promisable + Clone + 'a, + E: Promisable + Clone + 'a, + F: FnMut(&T) -> Result + Send + 'a, + G: FnMut(Result) -> Result + 'a { + Box::new(move |result: Result| { + match result { + Ok(ref t) => action(t), + Err(ref e) => Err(e.clone()), + } + }) +} + +fn main() {} diff --git a/tests/ui/issues/issue-1821.rs b/tests/ui/issues/issue-1821.rs new file mode 100644 index 000000000..76ee9c3ed --- /dev/null +++ b/tests/ui/issues/issue-1821.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// Issue #1821 - Don't recurse trying to typecheck this + + +// pretty-expanded FIXME #23616 + +enum t { + foo(Vec) +} +pub fn main() {} diff --git a/tests/ui/issues/issue-18232.rs b/tests/ui/issues/issue-18232.rs new file mode 100644 index 000000000..7e6f6ef0f --- /dev/null +++ b/tests/ui/issues/issue-18232.rs @@ -0,0 +1,22 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct Cursor<'a>(::std::marker::PhantomData<&'a ()>); + +trait CursorNavigator { + fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool; +} + +struct SimpleNavigator; + +impl CursorNavigator for SimpleNavigator { + fn init_cursor<'a, 'b: 'a>(&'a self, _cursor: &mut Cursor<'b>) -> bool { + false + } +} + +fn main() { + let mut c = Cursor(::std::marker::PhantomData); + let n = SimpleNavigator; + n.init_cursor(&mut c); +} diff --git a/tests/ui/issues/issue-18352.rs b/tests/ui/issues/issue-18352.rs new file mode 100644 index 000000000..5d93ed064 --- /dev/null +++ b/tests/ui/issues/issue-18352.rs @@ -0,0 +1,14 @@ +// run-pass + +const X: &'static str = "12345"; + +fn test(s: String) -> bool { + match &*s { + X => true, + _ => false + } +} + +fn main() { + assert!(test("12345".to_string())); +} diff --git a/tests/ui/issues/issue-18353.rs b/tests/ui/issues/issue-18353.rs new file mode 100644 index 000000000..3d15c9980 --- /dev/null +++ b/tests/ui/issues/issue-18353.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// Test that wrapping an unsized struct in an enum which gets optimised does +// not ICE. + +// pretty-expanded FIXME #23616 + +struct Str { + f: [u8] +} + +fn main() { + let str: Option<&Str> = None; + let _ = str.is_some(); +} diff --git a/tests/ui/issues/issue-18389.rs b/tests/ui/issues/issue-18389.rs new file mode 100644 index 000000000..654dfb63b --- /dev/null +++ b/tests/ui/issues/issue-18389.rs @@ -0,0 +1,18 @@ +use std::any::Any; +use std::any::TypeId; + +trait Private { + fn call(&self, p: P, r: R); +} +pub trait Public: Private< +//~^ ERROR private trait `Private<::P, ::R>` in public interface + ::P, + ::R +> { + type P; + type R; + + fn call_inner(&self); +} + +fn main() {} diff --git a/tests/ui/issues/issue-18389.stderr b/tests/ui/issues/issue-18389.stderr new file mode 100644 index 000000000..6ce78c45d --- /dev/null +++ b/tests/ui/issues/issue-18389.stderr @@ -0,0 +1,16 @@ +error[E0445]: private trait `Private<::P, ::R>` in public interface + --> $DIR/issue-18389.rs:7:1 + | +LL | trait Private { + | ------------------- `Private<::P, ::R>` declared as private +... +LL | / pub trait Public: Private< +LL | | +LL | | ::P, +LL | | ::R +LL | | > { + | |_^ can't leak private trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0445`. diff --git a/tests/ui/issues/issue-18423.rs b/tests/ui/issues/issue-18423.rs new file mode 100644 index 000000000..a81b32f05 --- /dev/null +++ b/tests/ui/issues/issue-18423.rs @@ -0,0 +1,8 @@ +// Test that `Box` cannot be used with a lifetime argument. + +struct Foo<'a> { + x: Box<'a, isize> + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied +} + +fn main() { } diff --git a/tests/ui/issues/issue-18423.stderr b/tests/ui/issues/issue-18423.stderr new file mode 100644 index 000000000..bbf793662 --- /dev/null +++ b/tests/ui/issues/issue-18423.stderr @@ -0,0 +1,11 @@ +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/issue-18423.rs:4:8 + | +LL | x: Box<'a, isize> + | ^^^ -- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-18446-2.rs b/tests/ui/issues/issue-18446-2.rs new file mode 100644 index 000000000..85422d4d2 --- /dev/null +++ b/tests/ui/issues/issue-18446-2.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(dead_code)] +// Test that methods in trait impls should override default methods. + +trait T { + fn foo(&self) -> i32 { 0 } +} + +impl<'a> dyn T + 'a { + fn foo(&self) -> i32 { 1 } +} + +fn main() {} diff --git a/tests/ui/issues/issue-18446.rs b/tests/ui/issues/issue-18446.rs new file mode 100644 index 000000000..a2e238da0 --- /dev/null +++ b/tests/ui/issues/issue-18446.rs @@ -0,0 +1,19 @@ +// Test that name clashes between the method in an impl for the type +// and the method in the trait when both are in the same scope. + +trait T { + fn foo(&self); +} + +impl<'a> dyn T + 'a { + fn foo(&self) {} +} + +impl T for i32 { + fn foo(&self) {} +} + +fn main() { + let x: &dyn T = &0i32; + x.foo(); //~ ERROR multiple applicable items in scope [E0034] +} diff --git a/tests/ui/issues/issue-18446.stderr b/tests/ui/issues/issue-18446.stderr new file mode 100644 index 000000000..939cf0292 --- /dev/null +++ b/tests/ui/issues/issue-18446.stderr @@ -0,0 +1,24 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/issue-18446.rs:18:7 + | +LL | x.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl for the type `(dyn T + 'a)` + --> $DIR/issue-18446.rs:9:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `T` + --> $DIR/issue-18446.rs:5:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #2 + | +LL | T::foo(&x); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-18464.rs b/tests/ui/issues/issue-18464.rs new file mode 100644 index 000000000..14d2d0a6c --- /dev/null +++ b/tests/ui/issues/issue-18464.rs @@ -0,0 +1,12 @@ +// run-pass +#![deny(dead_code)] + +const LOW_RANGE: char = '0'; +const HIGH_RANGE: char = '9'; + +fn main() { + match '5' { + LOW_RANGE..=HIGH_RANGE => (), + _ => () + }; +} diff --git a/tests/ui/issues/issue-18501.rs b/tests/ui/issues/issue-18501.rs new file mode 100644 index 000000000..0ca23074c --- /dev/null +++ b/tests/ui/issues/issue-18501.rs @@ -0,0 +1,13 @@ +// run-pass +// Test that we don't ICE when inlining a function from another +// crate that uses a trait method as a value due to incorrectly +// translating the def ID of the trait during AST decoding. + +// aux-build:issue-18501.rs +// pretty-expanded FIXME #23616 + +extern crate issue_18501 as issue; + +fn main() { + issue::pass_method(); +} diff --git a/tests/ui/issues/issue-18514.rs b/tests/ui/issues/issue-18514.rs new file mode 100644 index 000000000..48e7f0741 --- /dev/null +++ b/tests/ui/issues/issue-18514.rs @@ -0,0 +1,16 @@ +// run-pass +// Test that we don't ICE when codegenning a generic impl method from +// an extern crate that contains a match expression on a local +// variable place where one of the match case bodies contains an +// expression that autoderefs through an overloaded generic deref +// impl. + +// aux-build:issue-18514.rs + +extern crate issue_18514 as ice; +use ice::{Tr, St}; + +fn main() { + let st: St<()> = St(vec![]); + st.tr(); +} diff --git a/tests/ui/issues/issue-18532.rs b/tests/ui/issues/issue-18532.rs new file mode 100644 index 000000000..31fd87961 --- /dev/null +++ b/tests/ui/issues/issue-18532.rs @@ -0,0 +1,7 @@ +// Test that overloaded call parameter checking does not ICE +// when a type error or unconstrained type variable propagates +// into it. + +fn main() { + (return)((),()); //~ ERROR expected function, found `!` +} diff --git a/tests/ui/issues/issue-18532.stderr b/tests/ui/issues/issue-18532.stderr new file mode 100644 index 000000000..4c224eb2d --- /dev/null +++ b/tests/ui/issues/issue-18532.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `!` + --> $DIR/issue-18532.rs:6:5 + | +LL | (return)((),()); + | ^^^^^^^^------- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-18539.rs b/tests/ui/issues/issue-18539.rs new file mode 100644 index 000000000..745df26e3 --- /dev/null +++ b/tests/ui/issues/issue-18539.rs @@ -0,0 +1,16 @@ +// run-pass +// Test that coercing bare fn's that return a zero sized type to +// a closure doesn't cause an LLVM ERROR + +// pretty-expanded FIXME #23616 + +struct Foo; + +fn uint_to_foo(_: usize) -> Foo { + Foo +} + +#[allow(unused_must_use)] +fn main() { + (0..10).map(uint_to_foo); +} diff --git a/tests/ui/issues/issue-18566.rs b/tests/ui/issues/issue-18566.rs new file mode 100644 index 000000000..9da904acf --- /dev/null +++ b/tests/ui/issues/issue-18566.rs @@ -0,0 +1,25 @@ +use std::ops::Deref; + +struct MyPtr<'a>(&'a mut usize); +impl<'a> Deref for MyPtr<'a> { + type Target = usize; + + fn deref<'b>(&'b self) -> &'b usize { self.0 } +} + +trait Tr { + fn poke(&self, s: &mut usize); +} + +impl Tr for usize { + fn poke(&self, s: &mut usize) { + *s = 2; + } +} + +fn main() { + let s = &mut 1; + + MyPtr(s).poke(s); + //~^ ERROR cannot borrow `*s` as mutable more than once at a time +} diff --git a/tests/ui/issues/issue-18566.stderr b/tests/ui/issues/issue-18566.stderr new file mode 100644 index 000000000..8db78935f --- /dev/null +++ b/tests/ui/issues/issue-18566.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `*s` as mutable more than once at a time + --> $DIR/issue-18566.rs:23:19 + | +LL | MyPtr(s).poke(s); + | - ---- ^ second mutable borrow occurs here + | | | + | | first borrow later used by call + | first mutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-18576.rs b/tests/ui/issues/issue-18576.rs new file mode 100644 index 000000000..389cf108b --- /dev/null +++ b/tests/ui/issues/issue-18576.rs @@ -0,0 +1,16 @@ +// run-fail +// error-pattern:stop +// ignore-emscripten no processes + +// #18576 +// Make sure that calling an extern function pointer in an unreachable +// context doesn't cause an LLVM assertion + +#[allow(unreachable_code)] +fn main() { + panic!("stop"); + let pointer = other; + pointer(); +} + +extern "C" fn other() {} diff --git a/tests/ui/issues/issue-18611.rs b/tests/ui/issues/issue-18611.rs new file mode 100644 index 000000000..91a765f34 --- /dev/null +++ b/tests/ui/issues/issue-18611.rs @@ -0,0 +1,9 @@ +fn add_state(op: ::State) { +//~^ ERROR `isize: HasState` is not satisfied +} + +trait HasState { + type State; +} + +fn main() {} diff --git a/tests/ui/issues/issue-18611.stderr b/tests/ui/issues/issue-18611.stderr new file mode 100644 index 000000000..bd18d4622 --- /dev/null +++ b/tests/ui/issues/issue-18611.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `isize: HasState` is not satisfied + --> $DIR/issue-18611.rs:1:18 + | +LL | fn add_state(op: ::State) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-18685.rs b/tests/ui/issues/issue-18685.rs new file mode 100644 index 000000000..bfe24b663 --- /dev/null +++ b/tests/ui/issues/issue-18685.rs @@ -0,0 +1,21 @@ +// run-pass +// Test that the self param space is not used in a conflicting +// manner by unboxed closures within a default method on a trait + +// pretty-expanded FIXME #23616 + +trait Tr { + fn foo(&self); + + fn bar(&self) { + (|| { self.foo() })() + } +} + +impl Tr for () { + fn foo(&self) {} +} + +fn main() { + ().bar(); +} diff --git a/tests/ui/issues/issue-1871.rs b/tests/ui/issues/issue-1871.rs new file mode 100644 index 000000000..f7a2bdd56 --- /dev/null +++ b/tests/ui/issues/issue-1871.rs @@ -0,0 +1,12 @@ +// Tests that we don't generate a spurious error about f.honk's type +// being undeterminable +fn main() { + let f = 42; + + let _g = if f < 5 { + f.honk() //~ ERROR no method named `honk` found + } + else { + () + }; +} diff --git a/tests/ui/issues/issue-1871.stderr b/tests/ui/issues/issue-1871.stderr new file mode 100644 index 000000000..b774ca22d --- /dev/null +++ b/tests/ui/issues/issue-1871.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `honk` found for type `{integer}` in the current scope + --> $DIR/issue-1871.rs:7:9 + | +LL | f.honk() + | ^^^^ method not found in `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-18711.rs b/tests/ui/issues/issue-18711.rs new file mode 100644 index 000000000..435841877 --- /dev/null +++ b/tests/ui/issues/issue-18711.rs @@ -0,0 +1,12 @@ +// run-pass +// Test that we don't panic on a RefCell borrow conflict in certain +// code paths involving unboxed closures. + +// pretty-expanded FIXME #23616 + +// aux-build:issue-18711.rs +extern crate issue_18711 as issue; + +fn main() { + (|| issue::inner(()))(); +} diff --git a/tests/ui/issues/issue-18738.rs b/tests/ui/issues/issue-18738.rs new file mode 100644 index 000000000..bcc1ec03f --- /dev/null +++ b/tests/ui/issues/issue-18738.rs @@ -0,0 +1,17 @@ +// check-pass +#![allow(dead_code)] +#[derive(Eq, PartialEq, PartialOrd, Ord)] +enum Test<'a> { + Int(&'a isize), + Slice(&'a [u8]), +} + +#[derive(Eq, PartialEq, PartialOrd, Ord)] +struct Version { + vendor_info: &'static str +} + +#[derive(Eq, PartialEq, PartialOrd, Ord)] +struct Foo(&'static str); + +fn main() {} diff --git a/tests/ui/issues/issue-18767.rs b/tests/ui/issues/issue-18767.rs new file mode 100644 index 000000000..2a5721b72 --- /dev/null +++ b/tests/ui/issues/issue-18767.rs @@ -0,0 +1,10 @@ +// run-pass +// Test that regionck uses the right memcat for patterns in for loops +// and doesn't ICE. + + +fn main() { + for &&x in Some(&0_usize).iter() { + assert_eq!(x, 0) + } +} diff --git a/tests/ui/issues/issue-18783.rs b/tests/ui/issues/issue-18783.rs new file mode 100644 index 000000000..d4851ac14 --- /dev/null +++ b/tests/ui/issues/issue-18783.rs @@ -0,0 +1,28 @@ +use std::cell::RefCell; + +fn main() { + let mut y = 1; + let c = RefCell::new(vec![]); + c.push(Box::new(|| y = 0)); + c.push(Box::new(|| y = 0)); +//~^ ERROR cannot borrow `y` as mutable more than once at a time +} + +fn ufcs() { + let mut y = 1; + let c = RefCell::new(vec![]); + + Push::push(&c, Box::new(|| y = 0)); + Push::push(&c, Box::new(|| y = 0)); +//~^ ERROR cannot borrow `y` as mutable more than once at a time +} + +trait Push<'c> { + fn push<'f: 'c>(&self, push: Box); +} + +impl<'c> Push<'c> for RefCell>> { + fn push<'f: 'c>(&self, fun: Box) { + self.borrow_mut().push(fun) + } +} diff --git a/tests/ui/issues/issue-18783.stderr b/tests/ui/issues/issue-18783.stderr new file mode 100644 index 000000000..cc223ac46 --- /dev/null +++ b/tests/ui/issues/issue-18783.stderr @@ -0,0 +1,33 @@ +error[E0499]: cannot borrow `y` as mutable more than once at a time + --> $DIR/issue-18783.rs:7:21 + | +LL | c.push(Box::new(|| y = 0)); + | -- - first borrow occurs due to use of `y` in closure + | | + | first mutable borrow occurs here +LL | c.push(Box::new(|| y = 0)); + | ^^ - second borrow occurs due to use of `y` in closure + | | + | second mutable borrow occurs here +LL | +LL | } + | - first borrow might be used here, when `c` is dropped and runs the destructor for type `RefCell>>` + +error[E0499]: cannot borrow `y` as mutable more than once at a time + --> $DIR/issue-18783.rs:16:29 + | +LL | Push::push(&c, Box::new(|| y = 0)); + | -- - first borrow occurs due to use of `y` in closure + | | + | first mutable borrow occurs here +LL | Push::push(&c, Box::new(|| y = 0)); + | ^^ - second borrow occurs due to use of `y` in closure + | | + | second mutable borrow occurs here +LL | +LL | } + | - first borrow might be used here, when `c` is dropped and runs the destructor for type `RefCell>>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-18804/auxiliary/lib.rs b/tests/ui/issues/issue-18804/auxiliary/lib.rs new file mode 100644 index 000000000..e29d48285 --- /dev/null +++ b/tests/ui/issues/issue-18804/auxiliary/lib.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] +#![feature(linkage)] + +pub fn foo() -> *const () { + extern "C" { + #[linkage = "extern_weak"] + static FOO: *const (); + } + unsafe { FOO } +} diff --git a/tests/ui/issues/issue-18804/main.rs b/tests/ui/issues/issue-18804/main.rs new file mode 100644 index 000000000..c36048ea5 --- /dev/null +++ b/tests/ui/issues/issue-18804/main.rs @@ -0,0 +1,19 @@ +// run-pass +// Test for issue #18804, #[linkage] does not propagate through generic +// functions. Failure results in a linker error. + +// ignore-asmjs no weak symbol support +// ignore-emscripten no weak symbol support +// ignore-windows no extern_weak linkage +// ignore-macos no extern_weak linkage + +// aux-build:lib.rs + +// rust-lang/rust#56772: nikic says we need this to be proper test. +// compile-flags: -C no-prepopulate-passes -C passes=name-anon-globals + +extern crate lib; + +fn main() { + lib::foo::(); +} diff --git a/tests/ui/issues/issue-18809.rs b/tests/ui/issues/issue-18809.rs new file mode 100644 index 000000000..cc5b4a64c --- /dev/null +++ b/tests/ui/issues/issue-18809.rs @@ -0,0 +1,12 @@ +// check-pass +trait Tup { + type T0; + type T1; +} + +impl Tup for isize { + type T0 = f32; + type T1 = (); +} + +fn main() {} diff --git a/tests/ui/issues/issue-18819.rs b/tests/ui/issues/issue-18819.rs new file mode 100644 index 000000000..e634c55f8 --- /dev/null +++ b/tests/ui/issues/issue-18819.rs @@ -0,0 +1,18 @@ +trait Foo { + type Item; +} + +struct X; + +impl Foo for X { + type Item = bool; +} + +fn print_x(_: &dyn Foo, extra: &str) { + println!("{}", extra); +} + +fn main() { + print_x(X); + //~^ ERROR E0061 +} diff --git a/tests/ui/issues/issue-18819.stderr b/tests/ui/issues/issue-18819.stderr new file mode 100644 index 000000000..767fdd5ca --- /dev/null +++ b/tests/ui/issues/issue-18819.stderr @@ -0,0 +1,30 @@ +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/issue-18819.rs:16:5 + | +LL | print_x(X); + | ^^^^^^^--- an argument of type `&str` is missing + | +note: expected reference, found struct `X` + --> $DIR/issue-18819.rs:16:13 + | +LL | print_x(X); + | ^ + = note: expected reference `&dyn Foo` + found struct `X` +note: function defined here + --> $DIR/issue-18819.rs:11:4 + | +LL | fn print_x(_: &dyn Foo, extra: &str) { + | ^^^^^^^ ---------------------- ----------- +help: consider borrowing here + | +LL | print_x(&X); + | ~~ +help: provide the argument + | +LL | print_x(/* &dyn Foo */, /* &str */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/issues/issue-18845.rs b/tests/ui/issues/issue-18845.rs new file mode 100644 index 000000000..83fab4b5e --- /dev/null +++ b/tests/ui/issues/issue-18845.rs @@ -0,0 +1,16 @@ +// run-pass +// This used to generate invalid IR in that even if we took the +// `false` branch we'd still try to free the Box from the other +// arm. This was due to treating `*Box::new(9)` as an rvalue datum +// instead of as a place. + +fn test(foo: bool) -> u8 { + match foo { + true => *Box::new(9), + false => 0 + } +} + +fn main() { + assert_eq!(9, test(true)); +} diff --git a/tests/ui/issues/issue-18859.rs b/tests/ui/issues/issue-18859.rs new file mode 100644 index 000000000..c4575bce9 --- /dev/null +++ b/tests/ui/issues/issue-18859.rs @@ -0,0 +1,16 @@ +// run-pass + +mod foo { + pub mod bar { + pub mod baz { + pub fn name() -> &'static str { + module_path!() + } + } + } +} + +fn main() { + assert_eq!(module_path!(), "issue_18859"); + assert_eq!(foo::bar::baz::name(), "issue_18859::foo::bar::baz"); +} diff --git a/tests/ui/issues/issue-18906.rs b/tests/ui/issues/issue-18906.rs new file mode 100644 index 000000000..976a9f49b --- /dev/null +++ b/tests/ui/issues/issue-18906.rs @@ -0,0 +1,30 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub trait Borrow { + fn borrow(&self) -> &Borrowed; +} + +impl Borrow for T { + fn borrow(&self) -> &T { self } +} + +trait Foo { + fn foo(&self, other: &Self); +} + +fn bar(k: &K, q: &Q) where K: Borrow, Q: Foo { + q.foo(k.borrow()) +} + +struct MyTree(K); + +impl MyTree { + // This caused a failure in #18906 + fn bar(k: &K, q: &Q) where K: Borrow, Q: Foo { + q.foo(k.borrow()) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-18913.rs b/tests/ui/issues/issue-18913.rs new file mode 100644 index 000000000..27fae6d77 --- /dev/null +++ b/tests/ui/issues/issue-18913.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:issue-18913-1.rs +// aux-build:issue-18913-2.rs + +extern crate foo; + +fn main() { + assert_eq!(foo::foo(), 1); +} diff --git a/tests/ui/issues/issue-18919.rs b/tests/ui/issues/issue-18919.rs new file mode 100644 index 000000000..f06771e9e --- /dev/null +++ b/tests/ui/issues/issue-18919.rs @@ -0,0 +1,12 @@ +type FuncType<'f> = dyn Fn(&isize) -> isize + 'f; + +fn ho_func(f: Option) { + //~^ ERROR the size for values of type +} + +enum Option { + Some(T), + None, +} + +fn main() {} diff --git a/tests/ui/issues/issue-18919.stderr b/tests/ui/issues/issue-18919.stderr new file mode 100644 index 000000000..b0b03a0ee --- /dev/null +++ b/tests/ui/issues/issue-18919.stderr @@ -0,0 +1,23 @@ +error[E0277]: the size for values of type `dyn for<'a> Fn(&'a isize) -> isize` cannot be known at compilation time + --> $DIR/issue-18919.rs:3:15 + | +LL | fn ho_func(f: Option) { + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn for<'a> Fn(&'a isize) -> isize` +note: required by a bound in `Option` + --> $DIR/issue-18919.rs:7:13 + | +LL | enum Option { + | ^ required by this bound in `Option` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/issue-18919.rs:7:13 + | +LL | enum Option { + | ^ this could be changed to `T: ?Sized`... +LL | Some(T), + | - ...if indirection were used here: `Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-18952.rs b/tests/ui/issues/issue-18952.rs new file mode 100644 index 000000000..56378b59e --- /dev/null +++ b/tests/ui/issues/issue-18952.rs @@ -0,0 +1,56 @@ +// This issue tests fn_traits overloading on arity. +// run-pass + +#![feature(fn_traits)] +#![feature(unboxed_closures)] + +struct Foo; + +impl Fn<(isize, isize)> for Foo { + extern "rust-call" fn call(&self, args: (isize, isize)) -> Self::Output { + println!("{:?}", args); + (args.0 + 1, args.1 + 1) + } +} + +impl FnMut<(isize, isize)> for Foo { + extern "rust-call" fn call_mut(&mut self, args: (isize, isize)) -> Self::Output { + println!("{:?}", args); + (args.0 + 1, args.1 + 1) + } +} + +impl FnOnce<(isize, isize)> for Foo { + type Output = (isize, isize); + extern "rust-call" fn call_once(self, args: (isize, isize)) -> Self::Output { + println!("{:?}", args); + (args.0 + 1, args.1 + 1) + } +} + +impl Fn<(isize, isize, isize)> for Foo { + extern "rust-call" fn call(&self, args: (isize, isize, isize)) -> Self::Output { + println!("{:?}", args); + (args.0 + 3, args.1 + 3, args.2 + 3) + } +} + +impl FnMut<(isize, isize, isize)> for Foo { + extern "rust-call" fn call_mut(&mut self, args: (isize, isize, isize)) -> Self::Output { + println!("{:?}", args); + (args.0 + 3, args.1 + 3, args.2 + 3) + } +} +impl FnOnce<(isize, isize, isize)> for Foo { + type Output = (isize, isize, isize); + extern "rust-call" fn call_once(self, args: (isize, isize, isize)) -> Self::Output { + println!("{:?}", args); + (args.0 + 3, args.1 + 3, args.2 + 3) + } +} + +fn main() { + let foo = Foo; + assert_eq!(foo(1, 1), (2, 2)); + assert_eq!(foo(1, 1, 1), (4, 4, 4)); +} diff --git a/tests/ui/issues/issue-18959.rs b/tests/ui/issues/issue-18959.rs new file mode 100644 index 000000000..4b6f04e25 --- /dev/null +++ b/tests/ui/issues/issue-18959.rs @@ -0,0 +1,20 @@ +pub trait Foo { fn foo(&self, ext_thing: &T); } +pub trait Bar: Foo { } +impl Bar for T { } + +pub struct Thing; +impl Foo for Thing { + fn foo(&self, _: &T) {} +} + +#[inline(never)] +fn foo(b: &dyn Bar) { + //~^ ERROR E0038 + b.foo(&0) +} + +fn main() { + let mut thing = Thing; + let test: &dyn Bar = &mut thing; + foo(test); +} diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr new file mode 100644 index 000000000..b9e278736 --- /dev/null +++ b/tests/ui/issues/issue-18959.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-18959.rs:11:12 + | +LL | fn foo(b: &dyn Bar) { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-18959.rs:1:20 + | +LL | pub trait Foo { fn foo(&self, ext_thing: &T); } + | ^^^ ...because method `foo` has generic type parameters +LL | pub trait Bar: Foo { } + | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-18988.rs b/tests/ui/issues/issue-18988.rs new file mode 100644 index 000000000..708965d81 --- /dev/null +++ b/tests/ui/issues/issue-18988.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] +pub trait Foo : Send { } + +pub struct MyFoo { + children: Vec>, +} + +impl Foo for MyFoo { } + +pub fn main() { } diff --git a/tests/ui/issues/issue-1900.rs b/tests/ui/issues/issue-1900.rs new file mode 100644 index 000000000..761bd3170 --- /dev/null +++ b/tests/ui/issues/issue-1900.rs @@ -0,0 +1,2 @@ +fn main() { } +//~^ ERROR `main` function is not allowed to have generic parameters diff --git a/tests/ui/issues/issue-1900.stderr b/tests/ui/issues/issue-1900.stderr new file mode 100644 index 000000000..ce413662f --- /dev/null +++ b/tests/ui/issues/issue-1900.stderr @@ -0,0 +1,9 @@ +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-1900.rs:1:8 + | +LL | fn main() { } + | ^^^ `main` cannot have generic parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/issues/issue-19001.rs b/tests/ui/issues/issue-19001.rs new file mode 100644 index 000000000..76c380c2f --- /dev/null +++ b/tests/ui/issues/issue-19001.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// check that we handle recursive arrays correctly in `type_of` + +struct Loopy { + ptr: *mut [Loopy; 1] +} + +fn main() { + let _t = Loopy { ptr: core::ptr::null_mut() }; +} diff --git a/tests/ui/issues/issue-19037.rs b/tests/ui/issues/issue-19037.rs new file mode 100644 index 000000000..74623da14 --- /dev/null +++ b/tests/ui/issues/issue-19037.rs @@ -0,0 +1,20 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Str([u8]); + +#[derive(Clone)] +struct CharSplits<'a, Sep> { + string: &'a Str, + sep: Sep, + allow_trailing_empty: bool, + only_ascii: bool, + finished: bool, +} + +fn clone(s: &Str) -> &Str { + Clone::clone(&s) +} + +fn main() {} diff --git a/tests/ui/issues/issue-19086.rs b/tests/ui/issues/issue-19086.rs new file mode 100644 index 000000000..42148c5f5 --- /dev/null +++ b/tests/ui/issues/issue-19086.rs @@ -0,0 +1,13 @@ +use Foo::FooB; + +enum Foo { + FooB { x: i32, y: i32 } +} + +fn main() { + let f = FooB { x: 3, y: 4 }; + match f { + FooB(a, b) => println!("{} {}", a, b), + //~^ ERROR expected tuple struct or tuple variant, found variant `FooB` + } +} diff --git a/tests/ui/issues/issue-19086.stderr b/tests/ui/issues/issue-19086.stderr new file mode 100644 index 000000000..a3c06a725 --- /dev/null +++ b/tests/ui/issues/issue-19086.stderr @@ -0,0 +1,12 @@ +error[E0532]: expected tuple struct or tuple variant, found variant `FooB` + --> $DIR/issue-19086.rs:10:9 + | +LL | FooB { x: i32, y: i32 } + | ----------------------- `FooB` defined here +... +LL | FooB(a, b) => println!("{} {}", a, b), + | ^^^^^^^^^^ help: use struct pattern syntax instead: `FooB { x, y }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-19097.rs b/tests/ui/issues/issue-19097.rs new file mode 100644 index 000000000..2f4b0d575 --- /dev/null +++ b/tests/ui/issues/issue-19097.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +// regression test for #19097 + +struct Foo(T); + +impl<'a, T> Foo<&'a T> { + fn foo(&self) {} +} +impl<'a, T> Foo<&'a mut T> { + fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-19098.rs b/tests/ui/issues/issue-19098.rs new file mode 100644 index 000000000..3d05f11b6 --- /dev/null +++ b/tests/ui/issues/issue-19098.rs @@ -0,0 +1,12 @@ +// check-pass +pub trait Handler { + fn handle(&self, _: &mut String); +} + +impl Handler for F where F: for<'a, 'b> Fn(&'a mut String) { + fn handle(&self, st: &mut String) { + self(st) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-19100.fixed b/tests/ui/issues/issue-19100.fixed new file mode 100644 index 000000000..029855de2 --- /dev/null +++ b/tests/ui/issues/issue-19100.fixed @@ -0,0 +1,29 @@ +// run-rustfix + +#![allow(non_snake_case)] +#![allow(dead_code)] +#![allow(unused_variables)] + +#[derive(Copy, Clone)] +enum Foo { + Bar, + Baz +} + +impl Foo { + fn foo(&self) { + match self { + & +Foo::Bar if true +//~^ ERROR pattern binding `Bar` is named the same as one of the variants of the type `Foo` +=> println!("bar"), + & +Foo::Baz if false +//~^ ERROR pattern binding `Baz` is named the same as one of the variants of the type `Foo` +=> println!("baz"), +_ => () + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-19100.rs b/tests/ui/issues/issue-19100.rs new file mode 100644 index 000000000..bd9e4ea5b --- /dev/null +++ b/tests/ui/issues/issue-19100.rs @@ -0,0 +1,29 @@ +// run-rustfix + +#![allow(non_snake_case)] +#![allow(dead_code)] +#![allow(unused_variables)] + +#[derive(Copy, Clone)] +enum Foo { + Bar, + Baz +} + +impl Foo { + fn foo(&self) { + match self { + & +Bar if true +//~^ ERROR pattern binding `Bar` is named the same as one of the variants of the type `Foo` +=> println!("bar"), + & +Baz if false +//~^ ERROR pattern binding `Baz` is named the same as one of the variants of the type `Foo` +=> println!("baz"), +_ => () + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-19100.stderr b/tests/ui/issues/issue-19100.stderr new file mode 100644 index 000000000..ebbf083b7 --- /dev/null +++ b/tests/ui/issues/issue-19100.stderr @@ -0,0 +1,17 @@ +error[E0170]: pattern binding `Bar` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-19100.rs:17:1 + | +LL | Bar if true + | ^^^ help: to match on the variant, qualify the path: `Foo::Bar` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-19100.rs:21:1 + | +LL | Baz if false + | ^^^ help: to match on the variant, qualify the path: `Foo::Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/issues/issue-19102.rs b/tests/ui/issues/issue-19102.rs new file mode 100644 index 000000000..1f32d10b6 --- /dev/null +++ b/tests/ui/issues/issue-19102.rs @@ -0,0 +1,12 @@ +// check-pass +#![allow(unused_imports)] +#![deny(unused_qualifications)] + +use self::A::B; + +#[derive(PartialEq)] +pub enum A { + B, +} + +fn main() {} diff --git a/tests/ui/issues/issue-19127.rs b/tests/ui/issues/issue-19127.rs new file mode 100644 index 000000000..c847ac9e4 --- /dev/null +++ b/tests/ui/issues/issue-19127.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +fn foo T>(f: F) {} +fn id<'a>(input: &'a u8) -> &'a u8 { input } + +fn main() { + foo(id); +} diff --git a/tests/ui/issues/issue-19129-1.rs b/tests/ui/issues/issue-19129-1.rs new file mode 100644 index 000000000..03a969101 --- /dev/null +++ b/tests/ui/issues/issue-19129-1.rs @@ -0,0 +1,16 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait Trait { + type Output; + + fn method() -> >::Output; +} + +impl Trait for () { + type Output = (); + + fn method() {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-19129-2.rs b/tests/ui/issues/issue-19129-2.rs new file mode 100644 index 000000000..991d79d41 --- /dev/null +++ b/tests/ui/issues/issue-19129-2.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +trait Trait { + type Output; + + fn method(&self, i: Input) -> bool { false } +} + +fn main() {} diff --git a/tests/ui/issues/issue-19135.rs b/tests/ui/issues/issue-19135.rs new file mode 100644 index 000000000..84540a3ff --- /dev/null +++ b/tests/ui/issues/issue-19135.rs @@ -0,0 +1,13 @@ +// run-pass +use std::marker::PhantomData; + +#[derive(Debug)] +struct LifetimeStruct<'a>(PhantomData<&'a ()>); + +fn main() { + takes_hrtb_closure(|lts| println!("{:?}", lts)); +} + +fn takes_hrtb_closureFnMut(LifetimeStruct<'a>)>(mut f: F) { + f(LifetimeStruct(PhantomData)); +} diff --git a/tests/ui/issues/issue-1920-1.rs b/tests/ui/issues/issue-1920-1.rs new file mode 100644 index 000000000..26553f56b --- /dev/null +++ b/tests/ui/issues/issue-1920-1.rs @@ -0,0 +1,14 @@ +//! Test that absolute path names are correct when a crate is not linked into the root namespace + +// aux-build:issue-1920.rs + +mod foo { + pub extern crate issue_1920; +} + +fn assert_clone() where T : Clone { } + +fn main() { + assert_clone::(); + //~^ ERROR `S: Clone` is not satisfied +} diff --git a/tests/ui/issues/issue-1920-1.stderr b/tests/ui/issues/issue-1920-1.stderr new file mode 100644 index 000000000..a54692425 --- /dev/null +++ b/tests/ui/issues/issue-1920-1.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `S: Clone` is not satisfied + --> $DIR/issue-1920-1.rs:12:20 + | +LL | assert_clone::(); + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `S` + | +note: required by a bound in `assert_clone` + --> $DIR/issue-1920-1.rs:9:32 + | +LL | fn assert_clone() where T : Clone { } + | ^^^^^ required by this bound in `assert_clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-1920-2.rs b/tests/ui/issues/issue-1920-2.rs new file mode 100644 index 000000000..8d4a5f663 --- /dev/null +++ b/tests/ui/issues/issue-1920-2.rs @@ -0,0 +1,12 @@ +//! Test that when a crate is linked under another name that name is used in global paths + +// aux-build:issue-1920.rs + +extern crate issue_1920 as bar; + +fn assert_clone() where T : Clone { } + +fn main() { + assert_clone::(); + //~^ ERROR `S: Clone` is not satisfied +} diff --git a/tests/ui/issues/issue-1920-2.stderr b/tests/ui/issues/issue-1920-2.stderr new file mode 100644 index 000000000..1083b0112 --- /dev/null +++ b/tests/ui/issues/issue-1920-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `S: Clone` is not satisfied + --> $DIR/issue-1920-2.rs:10:20 + | +LL | assert_clone::(); + | ^^^^^^ the trait `Clone` is not implemented for `S` + | +note: required by a bound in `assert_clone` + --> $DIR/issue-1920-2.rs:7:32 + | +LL | fn assert_clone() where T : Clone { } + | ^^^^^ required by this bound in `assert_clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-1920-3.rs b/tests/ui/issues/issue-1920-3.rs new file mode 100644 index 000000000..520db50f9 --- /dev/null +++ b/tests/ui/issues/issue-1920-3.rs @@ -0,0 +1,16 @@ +//! Test that when a crate is linked multiple times that the shortest absolute path name is used + +// aux-build:issue-1920.rs + +mod foo { + pub extern crate issue_1920; +} + +extern crate issue_1920; + +fn assert_clone() where T : Clone { } + +fn main() { + assert_clone::(); + //~^ ERROR `S: Clone` is not satisfied +} diff --git a/tests/ui/issues/issue-1920-3.stderr b/tests/ui/issues/issue-1920-3.stderr new file mode 100644 index 000000000..3f0787c88 --- /dev/null +++ b/tests/ui/issues/issue-1920-3.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `S: Clone` is not satisfied + --> $DIR/issue-1920-3.rs:14:20 + | +LL | assert_clone::(); + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `S` + | +note: required by a bound in `assert_clone` + --> $DIR/issue-1920-3.rs:11:32 + | +LL | fn assert_clone() where T : Clone { } + | ^^^^^ required by this bound in `assert_clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-19244-1.rs b/tests/ui/issues/issue-19244-1.rs new file mode 100644 index 000000000..77fab7cfa --- /dev/null +++ b/tests/ui/issues/issue-19244-1.rs @@ -0,0 +1,6 @@ +const TUP: (usize,) = (42,); + +fn main() { + let a: [isize; TUP.1]; + //~^ ERROR no field `1` on type `(usize,)` +} diff --git a/tests/ui/issues/issue-19244-1.stderr b/tests/ui/issues/issue-19244-1.stderr new file mode 100644 index 000000000..1eb530542 --- /dev/null +++ b/tests/ui/issues/issue-19244-1.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `1` on type `(usize,)` + --> $DIR/issue-19244-1.rs:4:24 + | +LL | let a: [isize; TUP.1]; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-19244-2.rs b/tests/ui/issues/issue-19244-2.rs new file mode 100644 index 000000000..c9a68b05c --- /dev/null +++ b/tests/ui/issues/issue-19244-2.rs @@ -0,0 +1,7 @@ +struct MyStruct { field: usize } +const STRUCT: MyStruct = MyStruct { field: 42 }; + +fn main() { + let a: [isize; STRUCT.nonexistent_field]; + //~^ no field `nonexistent_field` on type `MyStruct` +} diff --git a/tests/ui/issues/issue-19244-2.stderr b/tests/ui/issues/issue-19244-2.stderr new file mode 100644 index 000000000..54529fdf5 --- /dev/null +++ b/tests/ui/issues/issue-19244-2.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `nonexistent_field` on type `MyStruct` + --> $DIR/issue-19244-2.rs:5:27 + | +LL | let a: [isize; STRUCT.nonexistent_field]; + | ^^^^^^^^^^^^^^^^^ unknown field + | + = note: available fields are: `field` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-19293.rs b/tests/ui/issues/issue-19293.rs new file mode 100644 index 000000000..b6e9e3d06 --- /dev/null +++ b/tests/ui/issues/issue-19293.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:issue-19293.rs +// pretty-expanded FIXME #23616 + +extern crate issue_19293; +use issue_19293::{Foo, MyEnum}; + +fn main() { + MyEnum::Foo(Foo(5)); +} diff --git a/tests/ui/issues/issue-19340-1.rs b/tests/ui/issues/issue-19340-1.rs new file mode 100644 index 000000000..e3cc2daae --- /dev/null +++ b/tests/ui/issues/issue-19340-1.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_variables)] +// aux-build:issue-19340-1.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_19340_1 as lib; + +use lib::Homura; + +fn main() { + let homura = Homura::Madoka { name: "Kaname".to_string() }; + + match homura { + Homura::Madoka { name } => (), + }; +} diff --git a/tests/ui/issues/issue-19340-2.rs b/tests/ui/issues/issue-19340-2.rs new file mode 100644 index 000000000..a222e9e46 --- /dev/null +++ b/tests/ui/issues/issue-19340-2.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +enum Homura { + Madoka { + name: String, + age: u32, + }, +} + +fn main() { + let homura = Homura::Madoka { + name: "Akemi".to_string(), + age: 14, + }; + + match homura { + Homura::Madoka { + name, + age, + } => (), + }; +} diff --git a/tests/ui/issues/issue-19367.rs b/tests/ui/issues/issue-19367.rs new file mode 100644 index 000000000..0699533e7 --- /dev/null +++ b/tests/ui/issues/issue-19367.rs @@ -0,0 +1,32 @@ +// run-pass +struct S { + o: Option +} + +// Make sure we don't reuse the same alloca when matching +// on field of struct or tuple which we reassign in the match body. + +fn main() { + let mut a = (0, Some("right".to_string())); + let b = match a.1 { + Some(v) => { + a.1 = Some("wrong".to_string()); + v + } + None => String::new() + }; + println!("{}", b); + assert_eq!(b, "right"); + + + let mut s = S{ o: Some("right".to_string()) }; + let b = match s.o { + Some(v) => { + s.o = Some("wrong".to_string()); + v + } + None => String::new(), + }; + println!("{}", b); + assert_eq!(b, "right"); +} diff --git a/tests/ui/issues/issue-19380.rs b/tests/ui/issues/issue-19380.rs new file mode 100644 index 000000000..5c10e2067 --- /dev/null +++ b/tests/ui/issues/issue-19380.rs @@ -0,0 +1,18 @@ +trait Qiz { + fn qiz(); +} + +struct Foo; +impl Qiz for Foo { + fn qiz() {} +} + +struct Bar { + foos: &'static [&'static (dyn Qiz + 'static)] +//~^ ERROR E0038 +} + +const FOO : Foo = Foo; +const BAR : Bar = Bar { foos: &[&FOO]}; + +fn main() { } diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr new file mode 100644 index 000000000..b2aeb5edf --- /dev/null +++ b/tests/ui/issues/issue-19380.stderr @@ -0,0 +1,25 @@ +error[E0038]: the trait `Qiz` cannot be made into an object + --> $DIR/issue-19380.rs:11:29 + | +LL | foos: &'static [&'static (dyn Qiz + 'static)] + | ^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-19380.rs:2:6 + | +LL | trait Qiz { + | --- this trait cannot be made into an object... +LL | fn qiz(); + | ^^^ ...because associated function `qiz` has no `self` parameter +help: consider turning `qiz` into a method by giving it a `&self` argument + | +LL | fn qiz(&self); + | +++++ +help: alternatively, consider constraining `qiz` so it does not apply to trait objects + | +LL | fn qiz() where Self: Sized; + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-19398.rs b/tests/ui/issues/issue-19398.rs new file mode 100644 index 000000000..a9d0acaa2 --- /dev/null +++ b/tests/ui/issues/issue-19398.rs @@ -0,0 +1,12 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait T { + unsafe extern "Rust" fn foo(&self); +} + +impl T for () { + unsafe extern "Rust" fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-19404.rs b/tests/ui/issues/issue-19404.rs new file mode 100644 index 000000000..f1cf1feb0 --- /dev/null +++ b/tests/ui/issues/issue-19404.rs @@ -0,0 +1,37 @@ +// build-pass +#![allow(dead_code)] +#![allow(unused_variables)] +use std::any::TypeId; +use std::rc::Rc; + +type Fp = Rc; + +struct Engine; + +trait Component: 'static {} +impl Component for Engine {} + +trait Env { + fn get_component_type_id(&self, type_id: TypeId) -> Option>; +} + +impl<'a> dyn Env + 'a { + fn get_component(&self) -> Option> { + let x = self.get_component_type_id(TypeId::of::()); + None + } +} + +trait Figment { + fn init(&mut self, env: &dyn Env); +} + +struct MyFigment; + +impl Figment for MyFigment { + fn init(&mut self, env: &dyn Env) { + let engine = env.get_component::(); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-19479.rs b/tests/ui/issues/issue-19479.rs new file mode 100644 index 000000000..70bfe7213 --- /dev/null +++ b/tests/ui/issues/issue-19479.rs @@ -0,0 +1,19 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait Base { + fn dummy(&self) { } +} +trait AssocA { + type X: Base; + fn dummy(&self) { } +} +trait AssocB { + type Y: Base; + fn dummy(&self) { } +} +impl AssocB for T { + type Y = ::X; +} + +fn main() {} diff --git a/tests/ui/issues/issue-19482.rs b/tests/ui/issues/issue-19482.rs new file mode 100644 index 000000000..3f3c5de9b --- /dev/null +++ b/tests/ui/issues/issue-19482.rs @@ -0,0 +1,13 @@ +// Test that a partially specified trait object with unspecified associated +// type does not type-check. + +trait Foo { + type A; + + fn dummy(&self) { } +} + +fn bar(x: &dyn Foo) {} +//~^ ERROR the associated type `A` (from trait `Foo`) must be specified + +pub fn main() {} diff --git a/tests/ui/issues/issue-19482.stderr b/tests/ui/issues/issue-19482.stderr new file mode 100644 index 000000000..d51cc1f08 --- /dev/null +++ b/tests/ui/issues/issue-19482.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `A` (from trait `Foo`) must be specified + --> $DIR/issue-19482.rs:10:16 + | +LL | type A; + | ------ `A` defined here +... +LL | fn bar(x: &dyn Foo) {} + | ^^^ help: specify the associated type: `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-19499.rs b/tests/ui/issues/issue-19499.rs new file mode 100644 index 000000000..d09056ce3 --- /dev/null +++ b/tests/ui/issues/issue-19499.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(path_statements)] +#![allow(unused_variables)] +// Regression test for issue #19499. Due to incorrect caching of trait +// results for closures with upvars whose types were not fully +// computed, this rather bizarre little program (along with many more +// reasonable examples) let to ambiguity errors about not being able +// to infer sufficient type information. + +// pretty-expanded FIXME #23616 + +fn main() { + let n = 0; + let it = Some(1_usize).into_iter().inspect(|_| {n;}); +} diff --git a/tests/ui/issues/issue-19521.rs b/tests/ui/issues/issue-19521.rs new file mode 100644 index 000000000..a2a32a21a --- /dev/null +++ b/tests/ui/issues/issue-19521.rs @@ -0,0 +1,3 @@ +fn main() { + "".homura()(); //~ ERROR no method named `homura` found +} diff --git a/tests/ui/issues/issue-19521.stderr b/tests/ui/issues/issue-19521.stderr new file mode 100644 index 000000000..b6847cd75 --- /dev/null +++ b/tests/ui/issues/issue-19521.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `homura` found for reference `&'static str` in the current scope + --> $DIR/issue-19521.rs:2:8 + | +LL | "".homura()(); + | ^^^^^^ method not found in `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-19601.rs b/tests/ui/issues/issue-19601.rs new file mode 100644 index 000000000..176e6ba41 --- /dev/null +++ b/tests/ui/issues/issue-19601.rs @@ -0,0 +1,6 @@ +// check-pass + +trait A {} +struct B where B: A> { t: T } + +fn main() {} diff --git a/tests/ui/issues/issue-1962.fixed b/tests/ui/issues/issue-1962.fixed new file mode 100644 index 000000000..897fd172b --- /dev/null +++ b/tests/ui/issues/issue-1962.fixed @@ -0,0 +1,10 @@ +// compile-flags: -D while-true +// run-rustfix + +fn main() { + let mut i = 0; + 'a: loop { //~ ERROR denote infinite loops with `loop + i += 1; + if i == 5 { break 'a; } + } +} diff --git a/tests/ui/issues/issue-1962.rs b/tests/ui/issues/issue-1962.rs new file mode 100644 index 000000000..71e874100 --- /dev/null +++ b/tests/ui/issues/issue-1962.rs @@ -0,0 +1,10 @@ +// compile-flags: -D while-true +// run-rustfix + +fn main() { + let mut i = 0; + 'a: while true { //~ ERROR denote infinite loops with `loop + i += 1; + if i == 5 { break 'a; } + } +} diff --git a/tests/ui/issues/issue-1962.stderr b/tests/ui/issues/issue-1962.stderr new file mode 100644 index 000000000..4c32a4cf3 --- /dev/null +++ b/tests/ui/issues/issue-1962.stderr @@ -0,0 +1,10 @@ +error: denote infinite loops with `loop { ... }` + --> $DIR/issue-1962.rs:6:5 + | +LL | 'a: while true { + | ^^^^^^^^^^^^^^ help: use `loop` + | + = note: requested on the command line with `-D while-true` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-19631.rs b/tests/ui/issues/issue-19631.rs new file mode 100644 index 000000000..694e6dcd1 --- /dev/null +++ b/tests/ui/issues/issue-19631.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait PoolManager { + type C; + fn dummy(&self) { } +} + +struct InnerPool { + manager: M, +} + +impl InnerPool where M: PoolManager {} + +fn main() {} diff --git a/tests/ui/issues/issue-19632.rs b/tests/ui/issues/issue-19632.rs new file mode 100644 index 000000000..203976079 --- /dev/null +++ b/tests/ui/issues/issue-19632.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait PoolManager { + type C; + fn dummy(&self) { } +} + +struct InnerPool { + manager: M, +} + +fn main() {} diff --git a/tests/ui/issues/issue-19692.rs b/tests/ui/issues/issue-19692.rs new file mode 100644 index 000000000..99eccc8a8 --- /dev/null +++ b/tests/ui/issues/issue-19692.rs @@ -0,0 +1,8 @@ +struct Homura; + +fn akemi(homura: Homura) { + let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found + madoka.clone(); +} + +fn main() { } diff --git a/tests/ui/issues/issue-19692.stderr b/tests/ui/issues/issue-19692.stderr new file mode 100644 index 000000000..9e888ed75 --- /dev/null +++ b/tests/ui/issues/issue-19692.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `kaname` found for struct `Homura` in the current scope + --> $DIR/issue-19692.rs:4:40 + | +LL | struct Homura; + | ------------- method `kaname` not found for this struct +... +LL | let Some(ref madoka) = Some(homura.kaname()); + | ^^^^^^ method not found in `Homura` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-19707.rs b/tests/ui/issues/issue-19707.rs new file mode 100644 index 000000000..6bc7132af --- /dev/null +++ b/tests/ui/issues/issue-19707.rs @@ -0,0 +1,7 @@ +#![allow(dead_code)] + +type Foo = fn(&u8, &u8) -> &u8; //~ ERROR missing lifetime specifier + +fn bar &u8>(f: &F) {} //~ ERROR missing lifetime specifier + +fn main() {} diff --git a/tests/ui/issues/issue-19707.stderr b/tests/ui/issues/issue-19707.stderr new file mode 100644 index 000000000..3e1bb32c1 --- /dev/null +++ b/tests/ui/issues/issue-19707.stderr @@ -0,0 +1,36 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-19707.rs:3:28 + | +LL | type Foo = fn(&u8, &u8) -> &u8; + | --- --- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8; + | +++++++ ++ ++ ++ +help: consider introducing a named lifetime parameter + | +LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8; + | ++++ ++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-19707.rs:5:27 + | +LL | fn bar &u8>(f: &F) {} + | --- --- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | fn bar Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} + | +++++++ ++ ++ ++ +help: consider introducing a named lifetime parameter + | +LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} + | +++ ++ ++ ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-19734.rs b/tests/ui/issues/issue-19734.rs new file mode 100644 index 000000000..fe4a327ae --- /dev/null +++ b/tests/ui/issues/issue-19734.rs @@ -0,0 +1,8 @@ +fn main() {} + +struct Type; + +impl Type { + undef!(); + //~^ ERROR cannot find macro `undef` in this scope +} diff --git a/tests/ui/issues/issue-19734.stderr b/tests/ui/issues/issue-19734.stderr new file mode 100644 index 000000000..81757974d --- /dev/null +++ b/tests/ui/issues/issue-19734.stderr @@ -0,0 +1,8 @@ +error: cannot find macro `undef` in this scope + --> $DIR/issue-19734.rs:6:5 + | +LL | undef!(); + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-1974.rs b/tests/ui/issues/issue-1974.rs new file mode 100644 index 000000000..74a54a602 --- /dev/null +++ b/tests/ui/issues/issue-1974.rs @@ -0,0 +1,11 @@ +// run-pass +// Issue 1974 +// Don't double free the condition allocation +// pretty-expanded FIXME #23616 + +pub fn main() { + let s = "hej".to_string(); + while s != "".to_string() { + return; + } +} diff --git a/tests/ui/issues/issue-19811-escape-unicode.rs b/tests/ui/issues/issue-19811-escape-unicode.rs new file mode 100644 index 000000000..a2c50bc02 --- /dev/null +++ b/tests/ui/issues/issue-19811-escape-unicode.rs @@ -0,0 +1,9 @@ +// run-pass + +fn main() { + let mut escaped = String::from(""); + for c in '\u{10401}'.escape_unicode() { + escaped.push(c); + } + assert_eq!("\\u{10401}", escaped); +} diff --git a/tests/ui/issues/issue-19850.rs b/tests/ui/issues/issue-19850.rs new file mode 100644 index 000000000..4a578c398 --- /dev/null +++ b/tests/ui/issues/issue-19850.rs @@ -0,0 +1,22 @@ +// check-pass +#![allow(unused_variables)] +// Test that `::Output` and `Self::Output` are accepted as type annotations in let +// bindings + +// pretty-expanded FIXME #23616 + +trait Int { + fn one() -> Self; + fn leading_zeros(self) -> usize; +} + +trait Foo { + type T : Int; + + fn test(&self) { + let r: ::T = Int::one(); + let r: Self::T = Int::one(); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-19922.rs b/tests/ui/issues/issue-19922.rs new file mode 100644 index 000000000..fede86f22 --- /dev/null +++ b/tests/ui/issues/issue-19922.rs @@ -0,0 +1,8 @@ +enum Homura { + Akemi { madoka: () } +} + +fn main() { + let homura = Homura::Akemi { kaname: () }; + //~^ ERROR variant `Homura::Akemi` has no field named `kaname` +} diff --git a/tests/ui/issues/issue-19922.stderr b/tests/ui/issues/issue-19922.stderr new file mode 100644 index 000000000..826b2ac04 --- /dev/null +++ b/tests/ui/issues/issue-19922.stderr @@ -0,0 +1,11 @@ +error[E0559]: variant `Homura::Akemi` has no field named `kaname` + --> $DIR/issue-19922.rs:6:34 + | +LL | let homura = Homura::Akemi { kaname: () }; + | ^^^^^^ `Homura::Akemi` does not have this field + | + = note: available fields are: `madoka` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0559`. diff --git a/tests/ui/issues/issue-19982.rs b/tests/ui/issues/issue-19982.rs new file mode 100644 index 000000000..12419c109 --- /dev/null +++ b/tests/ui/issues/issue-19982.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(fn_traits, unboxed_closures)] + +#[allow(dead_code)] +struct Foo; + +impl Fn<(&(),)> for Foo { + extern "rust-call" fn call(&self, (_,): (&(),)) {} +} + +impl FnMut<(&(),)> for Foo { + extern "rust-call" fn call_mut(&mut self, (_,): (&(),)) {} +} + +impl FnOnce<(&(),)> for Foo { + type Output = (); + + extern "rust-call" fn call_once(self, (_,): (&(),)) {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-19991.rs b/tests/ui/issues/issue-19991.rs new file mode 100644 index 000000000..dd0efa972 --- /dev/null +++ b/tests/ui/issues/issue-19991.rs @@ -0,0 +1,9 @@ +// Test if the sugared `if let` construct correctly prints "missing an else clause" when an else +// clause does not exist, instead of the unsympathetic "`match` arms have incompatible types" + +fn main() { + if let Some(homura) = Some("madoka") { //~ ERROR missing an `else` clause + //~| expected integer, found `()` + 765 + }; +} diff --git a/tests/ui/issues/issue-19991.stderr b/tests/ui/issues/issue-19991.stderr new file mode 100644 index 000000000..57b0882b6 --- /dev/null +++ b/tests/ui/issues/issue-19991.stderr @@ -0,0 +1,16 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/issue-19991.rs:5:5 + | +LL | / if let Some(homura) = Some("madoka") { +LL | | +LL | | 765 + | | --- found here +LL | | }; + | |_____^ expected integer, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/issues/issue-20009.rs b/tests/ui/issues/issue-20009.rs new file mode 100644 index 000000000..f289e58c5 --- /dev/null +++ b/tests/ui/issues/issue-20009.rs @@ -0,0 +1,13 @@ +// check-pass +// Check that associated types are `Sized` + +// pretty-expanded FIXME #23616 + +trait Trait { + type Output; + + fn is_sized(&self) -> Self::Output; + fn wasnt_sized(&self) -> Self::Output { loop {} } +} + +fn main() {} diff --git a/tests/ui/issues/issue-20055-box-trait.rs b/tests/ui/issues/issue-20055-box-trait.rs new file mode 100644 index 000000000..772cd9d7e --- /dev/null +++ b/tests/ui/issues/issue-20055-box-trait.rs @@ -0,0 +1,41 @@ +// run-pass +// See Issues #20055 and #21695. + +// We are checking here that the temporaries `Box<[i8, k]>`, for `k` +// in 1, 2, 3, 4, that are induced by the match expression are +// properly handled, in that only *one* will be initialized by +// whichever arm is run, and subsequently dropped at the end of the +// statement surrounding the `match`. + +trait Boo { + fn dummy(&self) { } +} + +impl Boo for [i8; 1] { } +impl Boo for [i8; 2] { } +impl Boo for [i8; 3] { } +impl Boo for [i8; 4] { } + +pub fn foo(box_1: fn () -> Box<[i8; 1]>, + box_2: fn () -> Box<[i8; 2]>, + box_3: fn () -> Box<[i8; 3]>, + box_4: fn () -> Box<[i8; 4]>, + ) { + println!("Hello World 1"); + let _: Box = match 3 { + 1 => box_1(), + 2 => box_2(), + 3 => box_3(), + _ => box_4(), + }; + println!("Hello World 2"); +} + +pub fn main() { + fn box_1() -> Box<[i8; 1]> { Box::new( [1; 1] ) } + fn box_2() -> Box<[i8; 2]> { Box::new( [1; 2] ) } + fn box_3() -> Box<[i8; 3]> { Box::new( [1; 3] ) } + fn box_4() -> Box<[i8; 4]> { Box::new( [1; 4] ) } + + foo(box_1, box_2, box_3, box_4); +} diff --git a/tests/ui/issues/issue-20055-box-unsized-array.rs b/tests/ui/issues/issue-20055-box-unsized-array.rs new file mode 100644 index 000000000..1246c8065 --- /dev/null +++ b/tests/ui/issues/issue-20055-box-unsized-array.rs @@ -0,0 +1,29 @@ +// run-pass +// Issue #2005: Check that boxed fixed-size arrays are properly +// accounted for (namely, only deallocated if they were actually +// created) when they appear as temporaries in unused arms of a match +// expression. + +pub fn foo(box_1: fn () -> Box<[i8; 1]>, + box_2: fn () -> Box<[i8; 20]>, + box_3: fn () -> Box<[i8; 300]>, + box_4: fn () -> Box<[i8; 4000]>, + ) { + println!("Hello World 1"); + let _: Box<[i8]> = match 3 { + 1 => box_1(), + 2 => box_2(), + 3 => box_3(), + _ => box_4(), + }; + println!("Hello World 2"); +} + +pub fn main() { + fn box_1() -> Box<[i8; 1]> { Box::new( [1] ) } + fn box_2() -> Box<[i8; 20]> { Box::new( [1; 20] ) } + fn box_3() -> Box<[i8; 300]> { Box::new( [1; 300] ) } + fn box_4() -> Box<[i8; 4000]> { Box::new( [1; 4000] ) } + + foo(box_1, box_2, box_3, box_4); +} diff --git a/tests/ui/issues/issue-20162.rs b/tests/ui/issues/issue-20162.rs new file mode 100644 index 000000000..b491bc37f --- /dev/null +++ b/tests/ui/issues/issue-20162.rs @@ -0,0 +1,7 @@ +struct X { x: i32 } + +fn main() { + let mut b: Vec = vec![]; + b.sort(); + //~^ ERROR `X: Ord` is not satisfied +} diff --git a/tests/ui/issues/issue-20162.stderr b/tests/ui/issues/issue-20162.stderr new file mode 100644 index 000000000..1c5b76fbf --- /dev/null +++ b/tests/ui/issues/issue-20162.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `X: Ord` is not satisfied + --> $DIR/issue-20162.rs:5:7 + | +LL | b.sort(); + | ^^^^ the trait `Ord` is not implemented for `X` + | +note: required by a bound in `slice::::sort` + --> $SRC_DIR/alloc/src/slice.rs:LL:COL +help: consider annotating `X` with `#[derive(Ord)]` + | +LL | #[derive(Ord)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-20174.rs b/tests/ui/issues/issue-20174.rs new file mode 100644 index 000000000..4ed5a97c1 --- /dev/null +++ b/tests/ui/issues/issue-20174.rs @@ -0,0 +1,7 @@ +// run-pass +struct GradFn usize>(F); + +fn main() { + let GradFn(x_squared) : GradFn<_> = GradFn(|| -> usize { 2 }); + let _ = x_squared(); +} diff --git a/tests/ui/issues/issue-20186.rs b/tests/ui/issues/issue-20186.rs new file mode 100644 index 000000000..54d68f100 --- /dev/null +++ b/tests/ui/issues/issue-20186.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] +struct Foo; + +impl Foo { + fn putc(&self, b: u8) { } + + fn puts(&self, s: &str) { + for byte in s.bytes() { + self.putc(byte) + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-20225.rs b/tests/ui/issues/issue-20225.rs new file mode 100644 index 000000000..0c8e6e402 --- /dev/null +++ b/tests/ui/issues/issue-20225.rs @@ -0,0 +1,22 @@ +#![feature(fn_traits, unboxed_closures)] + +struct Foo; + +impl<'a, T> Fn<(&'a T,)> for Foo { + extern "rust-call" fn call(&self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait +} + +impl<'a, T> FnMut<(&'a T,)> for Foo { + extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait +} + +impl<'a, T> FnOnce<(&'a T,)> for Foo { + type Output = (); + + extern "rust-call" fn call_once(self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr new file mode 100644 index 000000000..582216010 --- /dev/null +++ b/tests/ui/issues/issue-20225.stderr @@ -0,0 +1,46 @@ +error[E0053]: method `call` has an incompatible type for trait + --> $DIR/issue-20225.rs:6:43 + | +LL | impl<'a, T> Fn<(&'a T,)> for Foo { + | - this type parameter +LL | extern "rust-call" fn call(&self, (_,): (T,)) {} + | ^^^^ + | | + | expected `&T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` + | + = note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))` + found signature `extern "rust-call" fn(&Foo, (T,))` + +error[E0053]: method `call_mut` has an incompatible type for trait + --> $DIR/issue-20225.rs:11:51 + | +LL | impl<'a, T> FnMut<(&'a T,)> for Foo { + | - this type parameter +LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} + | ^^^^ + | | + | expected `&T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` + | + = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))` + found signature `extern "rust-call" fn(&mut Foo, (T,))` + +error[E0053]: method `call_once` has an incompatible type for trait + --> $DIR/issue-20225.rs:18:47 + | +LL | impl<'a, T> FnOnce<(&'a T,)> for Foo { + | - this type parameter +... +LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} + | ^^^^ + | | + | expected `&T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` + | + = note: expected signature `extern "rust-call" fn(Foo, (&'a T,))` + found signature `extern "rust-call" fn(Foo, (T,))` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-20261.rs b/tests/ui/issues/issue-20261.rs new file mode 100644 index 000000000..528393606 --- /dev/null +++ b/tests/ui/issues/issue-20261.rs @@ -0,0 +1,7 @@ +fn main() { + // N.B., this (almost) typechecks when default binding modes are enabled. + for (ref i,) in [].iter() { + i.clone(); + //~^ ERROR type annotations needed + } +} diff --git a/tests/ui/issues/issue-20261.stderr b/tests/ui/issues/issue-20261.stderr new file mode 100644 index 000000000..9ac751e4d --- /dev/null +++ b/tests/ui/issues/issue-20261.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/issue-20261.rs:4:11 + | +LL | i.clone(); + | ^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-20313-rpass.rs b/tests/ui/issues/issue-20313-rpass.rs new file mode 100644 index 000000000..591f3659e --- /dev/null +++ b/tests/ui/issues/issue-20313-rpass.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![feature(link_llvm_intrinsics)] + +extern "C" { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; +} + +fn main() {} diff --git a/tests/ui/issues/issue-20313.rs b/tests/ui/issues/issue-20313.rs new file mode 100644 index 000000000..a72af650c --- /dev/null +++ b/tests/ui/issues/issue-20313.rs @@ -0,0 +1,6 @@ +extern "C" { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; //~ ERROR linking to LLVM intrinsics is experimental +} + +fn main() {} diff --git a/tests/ui/issues/issue-20313.stderr b/tests/ui/issues/issue-20313.stderr new file mode 100644 index 000000000..7a0b344a5 --- /dev/null +++ b/tests/ui/issues/issue-20313.stderr @@ -0,0 +1,12 @@ +error[E0658]: linking to LLVM intrinsics is experimental + --> $DIR/issue-20313.rs:3:5 + | +LL | fn sqrt(x: f32) -> f32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29602 for more information + = help: add `#![feature(link_llvm_intrinsics)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-20389.rs b/tests/ui/issues/issue-20389.rs new file mode 100644 index 000000000..9bc3efcc1 --- /dev/null +++ b/tests/ui/issues/issue-20389.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-20389.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_20389; + +struct Foo; + +impl issue_20389::T for Foo { + type C = (); +} + +fn main() {} diff --git a/tests/ui/issues/issue-20396.rs b/tests/ui/issues/issue-20396.rs new file mode 100644 index 000000000..4a34f8b38 --- /dev/null +++ b/tests/ui/issues/issue-20396.rs @@ -0,0 +1,16 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Foo { + fn noop(&self, _: T); +} + +enum Bar { Bla(T) } + +struct Baz<'a> { + inner: dyn for<'b> Foo> + 'a, +} + +fn main() {} diff --git a/tests/ui/issues/issue-20413.rs b/tests/ui/issues/issue-20413.rs new file mode 100644 index 000000000..4de22f0c9 --- /dev/null +++ b/tests/ui/issues/issue-20413.rs @@ -0,0 +1,42 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" +trait Foo { + fn answer(self); +} + +struct NoData; +//~^ ERROR: parameter `T` is never used + +impl Foo for T where NoData: Foo { + //~^ ERROR: overflow evaluating the requirement + fn answer(self) { + let val: NoData = NoData; + } +} + +trait Bar { + fn answer(self); +} + +trait Baz { + fn answer(self); +} + +struct AlmostNoData(Option); + +struct EvenLessData(Option); + +impl Bar for T where EvenLessData: Baz { +//~^ ERROR: overflow evaluating the requirement + fn answer(self) { + let val: EvenLessData = EvenLessData(None); + } +} + +impl Baz for T where AlmostNoData: Bar { +//~^ ERROR: overflow evaluating the requirement + fn answer(self) { + let val: NoData = AlmostNoData(None); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-20413.stderr b/tests/ui/issues/issue-20413.stderr new file mode 100644 index 000000000..202e84631 --- /dev/null +++ b/tests/ui/issues/issue-20413.stderr @@ -0,0 +1,73 @@ +error[E0392]: parameter `T` is never used + --> $DIR/issue-20413.rs:6:15 + | +LL | struct NoData; + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error[E0275]: overflow evaluating the requirement `NoData>>>>>>: Foo` + --> $DIR/issue-20413.rs:9:36 + | +LL | impl Foo for T where NoData: Foo { + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) +note: required for `NoData>>>>>>>>>>>>` to implement `Foo` + --> $DIR/issue-20413.rs:9:9 + | +LL | impl Foo for T where NoData: Foo { + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' + = note: 127 redundant requirements hidden + = note: required for `NoData` to implement `Foo` + +error[E0275]: overflow evaluating the requirement `EvenLessData>>>>>>: Baz` + --> $DIR/issue-20413.rs:28:42 + | +LL | impl Bar for T where EvenLessData: Baz { + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) +note: required for `AlmostNoData>>>>>>` to implement `Bar` + --> $DIR/issue-20413.rs:28:9 + | +LL | impl Bar for T where EvenLessData: Baz { + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' +note: required for `EvenLessData>>>>>>` to implement `Baz` + --> $DIR/issue-20413.rs:35:9 + | +LL | impl Baz for T where AlmostNoData: Bar { + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' + = note: 126 redundant requirements hidden + = note: required for `EvenLessData` to implement `Baz` + +error[E0275]: overflow evaluating the requirement `AlmostNoData>>>>>>: Bar` + --> $DIR/issue-20413.rs:35:42 + | +LL | impl Baz for T where AlmostNoData: Bar { + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) +note: required for `EvenLessData>>>>>>` to implement `Baz` + --> $DIR/issue-20413.rs:35:9 + | +LL | impl Baz for T where AlmostNoData: Bar { + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' +note: required for `AlmostNoData>>>>>>` to implement `Bar` + --> $DIR/issue-20413.rs:28:9 + | +LL | impl Bar for T where EvenLessData: Baz { + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' + = note: 126 redundant requirements hidden + = note: required for `AlmostNoData` to implement `Bar` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0275, E0392. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-20414.rs b/tests/ui/issues/issue-20414.rs new file mode 100644 index 000000000..2496e342a --- /dev/null +++ b/tests/ui/issues/issue-20414.rs @@ -0,0 +1,21 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait Trait { + fn method(self) -> isize; +} + +struct Wrapper { + field: T +} + +impl<'a, T> Trait for &'a Wrapper where &'a T: Trait { + fn method(self) -> isize { + let r: &'a T = &self.field; + Trait::method(r); // these should both work + r.method() + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-20427.rs b/tests/ui/issues/issue-20427.rs new file mode 100644 index 000000000..cfd8b2191 --- /dev/null +++ b/tests/ui/issues/issue-20427.rs @@ -0,0 +1,88 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(deprecated, deprecated_in_future)] + +// aux-build:i8.rs + +extern crate i8; +use std::string as i16; +static i32: i32 = 0; +const i64: i64 = 0; +fn u8(f32: f32) {} +fn f(f64: f64) {} +enum u32 {} +struct u64; +trait bool {} + +mod char { + extern crate i8; + static i32_: i32 = 0; + const i64_: i64 = 0; + fn u8_(f32: f32) {} + fn f_(f64: f64_) {} + type u16_ = u16; + enum u32_ {} + struct u64_; + trait bool_ {} + mod char_ {} + + mod str { + use super::i8 as i8; + use super::i32_ as i32; + use super::i64_ as i64; + use super::u8_ as u8; + use super::f_ as f64; + use super::u16_ as u16; + use super::u32_ as u32; + use super::u64_ as u64; + use super::bool_ as bool; + use super::{bool_ as str}; + use super::char_ as char; + } +} + +trait isize_ { + type isize; +} + +fn usize<'usize>(usize: &'usize usize) -> &'usize usize { usize } + +mod reuse { + use std::mem::size_of; + + type u8 = u64; + use std::string::String as i16; + + pub fn check() { + assert_eq!(size_of::(), 8); + assert_eq!(size_of::<::u64>(), 0); + assert_eq!(size_of::(), 3 * size_of::<*const ()>()); + assert_eq!(size_of::(), 0); + } +} + +mod guard { + pub fn check() { + use std::u8; // bring module u8 in scope + fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8 + u8::max_value() // OK, resolves to associated function ::max_value, + // not to non-existent std::u8::max_value + } + assert_eq!(f(), u8::MAX); // OK, resolves to std::u8::MAX + } +} + +fn main() { + let bool = true; + let _ = match bool { + str @ true => if str { i32 as i64 } else { i64 }, + false => i64, + }; + + reuse::check::(); + guard::check(); +} diff --git a/tests/ui/issues/issue-20433.rs b/tests/ui/issues/issue-20433.rs new file mode 100644 index 000000000..a663239cc --- /dev/null +++ b/tests/ui/issues/issue-20433.rs @@ -0,0 +1,8 @@ +fn main() {} + +struct The; + +impl The { + fn iceman(c: Vec<[i32]>) {} + //~^ ERROR the size for values of type +} diff --git a/tests/ui/issues/issue-20433.stderr b/tests/ui/issues/issue-20433.stderr new file mode 100644 index 000000000..3ae952546 --- /dev/null +++ b/tests/ui/issues/issue-20433.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-20433.rs:6:18 + | +LL | fn iceman(c: Vec<[i32]>) {} + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-20454.rs b/tests/ui/issues/issue-20454.rs new file mode 100644 index 000000000..46cae33f1 --- /dev/null +++ b/tests/ui/issues/issue-20454.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(unused_must_use)] +use std::thread; + +fn _foo() { + thread::spawn(move || { // no need for -> () + loop { + println!("hello"); + } + }).join(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-20544.rs b/tests/ui/issues/issue-20544.rs new file mode 100644 index 000000000..0f4d314f1 --- /dev/null +++ b/tests/ui/issues/issue-20544.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(unboxed_closures)] +#![feature(fn_traits)] + +struct Fun(F); + +impl FnOnce<(T,)> for Fun where F: Fn(T) -> T { + type Output = T; + + extern "rust-call" fn call_once(self, (t,): (T,)) -> T { + (self.0)(t) + } +} + +fn main() { + let fun = Fun(|i: isize| i * 2); + println!("{}", fun(3)); +} diff --git a/tests/ui/issues/issue-20575.rs b/tests/ui/issues/issue-20575.rs new file mode 100644 index 000000000..0ca67d9dc --- /dev/null +++ b/tests/ui/issues/issue-20575.rs @@ -0,0 +1,10 @@ +// run-pass +// Test that overloaded calls work with zero arity closures + +// pretty-expanded FIXME #23616 + +fn main() { + let functions: [Box Option<()>>; 1] = [Box::new(|| None)]; + + let _: Option> = functions.iter().map(|f| (*f)()).collect(); +} diff --git a/tests/ui/issues/issue-20605.rs b/tests/ui/issues/issue-20605.rs new file mode 100644 index 000000000..17b7d32eb --- /dev/null +++ b/tests/ui/issues/issue-20605.rs @@ -0,0 +1,6 @@ +fn changer<'a>(mut things: Box>) { + for item in *things { *item = 0 } +//~^ ERROR the size for values of type +} + +fn main() {} diff --git a/tests/ui/issues/issue-20605.stderr b/tests/ui/issues/issue-20605.stderr new file mode 100644 index 000000000..e1858b639 --- /dev/null +++ b/tests/ui/issues/issue-20605.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `dyn Iterator` cannot be known at compilation time + --> $DIR/issue-20605.rs:2:17 + | +LL | for item in *things { *item = 0 } + | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | + = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied + = note: required for `dyn Iterator` to implement `IntoIterator` +help: consider mutably borrowing here + | +LL | for item in &mut *things { *item = 0 } + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-20616.rs b/tests/ui/issues/issue-20616.rs new file mode 100644 index 000000000..6c24d4372 --- /dev/null +++ b/tests/ui/issues/issue-20616.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code)] +type MyType<'a, T> = &'a T; + +// combine lifetime bounds and type arguments in usual way +type TypeA<'a> = MyType<'a, ()>; + +// ensure token `>>` works fine +type TypeB = Box>; +type TypeB_ = Box>; + +// trailing comma when combine lifetime bounds and type arguments +type TypeC<'a> = MyType<'a, (),>; + +// normal lifetime bounds +type TypeD = TypeA<'static>; + +// trailing comma on lifetime bounds +type TypeE = TypeA<'static,>; + +// normal type argument +type TypeF = Box; + +// type argument with trailing comma +type TypeG = Box; + +// trailing comma on lifetime defs +type TypeH<'a,> = &'a (); + +// trailing comma on type argument +type TypeI = T; + +static STATIC: () = (); + +fn main() { + + // ensure token `>=` works fine + let _: TypeA<'static>= &STATIC; + let _: TypeA<'static,>= &STATIC; + + // ensure token `>>=` works fine + let _: Box>= Box::new(&STATIC); + let _: Box>= Box::new(&STATIC); +} diff --git a/tests/ui/issues/issue-2063-resource.rs b/tests/ui/issues/issue-2063-resource.rs new file mode 100644 index 000000000..1d0527447 --- /dev/null +++ b/tests/ui/issues/issue-2063-resource.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +// test that autoderef of a type like this does not +// cause compiler to loop. Note that no instances +// of such a type could ever be constructed. + +struct S { + x: X, + to_str: (), +} + +struct X(Box); + +fn main() {} diff --git a/tests/ui/issues/issue-2063.rs b/tests/ui/issues/issue-2063.rs new file mode 100644 index 000000000..f08f9d4cf --- /dev/null +++ b/tests/ui/issues/issue-2063.rs @@ -0,0 +1,22 @@ +// run-pass +// test that autoderef of a type like this does not +// cause compiler to loop. Note that no instances +// of such a type could ever be constructed. + +struct T(#[allow(unused_tuple_struct_fields)] Box); + +trait ToStr2 { + fn my_to_string(&self) -> String; +} + +impl ToStr2 for T { + fn my_to_string(&self) -> String { "t".to_string() } +} + +#[allow(dead_code)] +fn new_t(x: T) { + x.my_to_string(); +} + +fn main() { +} diff --git a/tests/ui/issues/issue-20644.rs b/tests/ui/issues/issue-20644.rs new file mode 100644 index 000000000..1b90727fb --- /dev/null +++ b/tests/ui/issues/issue-20644.rs @@ -0,0 +1,32 @@ +// build-pass +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(stable_features)] + +// A reduced version of the rustbook ice. The problem this encountered +// had to do with codegen ignoring binders. + +// pretty-expanded FIXME #23616 + +#![feature(os)] + +use std::iter; +use std::os; +use std::fs::File; +use std::io::prelude::*; +use std::env; +use std::path::Path; + +pub fn parse_summary(_: R, _: &Path) { + let path_from_root = Path::new(""); + Path::new(&"../".repeat(path_from_root.components().count() - 1)); + } + +fn foo() { + let cwd = env::current_dir().unwrap(); + let src = cwd.clone(); + let summary = File::open(&src.join("SUMMARY.md")).unwrap(); + let _ = parse_summary(summary, &src); +} + +fn main() {} diff --git a/tests/ui/issues/issue-20676.rs b/tests/ui/issues/issue-20676.rs new file mode 100644 index 000000000..2bc503496 --- /dev/null +++ b/tests/ui/issues/issue-20676.rs @@ -0,0 +1,12 @@ +// run-pass +// Regression test for #20676. Error was that we didn't support +// UFCS-style calls to a method in `Trait` where `Self` was bound to a +// trait object of type `Trait`. See also `ufcs-trait-object.rs`. + + +use std::fmt; + +fn main() { + let a: &dyn fmt::Debug = &1; + format!("{:?}", a); +} diff --git a/tests/ui/issues/issue-20714.rs b/tests/ui/issues/issue-20714.rs new file mode 100644 index 000000000..3aa39bb73 --- /dev/null +++ b/tests/ui/issues/issue-20714.rs @@ -0,0 +1,5 @@ +struct G; + +fn main() { + let g = G(); //~ ERROR: expected function, found struct `G` +} diff --git a/tests/ui/issues/issue-20714.stderr b/tests/ui/issues/issue-20714.stderr new file mode 100644 index 000000000..a3447aa68 --- /dev/null +++ b/tests/ui/issues/issue-20714.stderr @@ -0,0 +1,20 @@ +error[E0618]: expected function, found struct `G` + --> $DIR/issue-20714.rs:4:13 + | +LL | struct G; + | -------- struct `G` defined here +... +LL | let g = G(); + | ^-- + | | + | call expression requires function + | +help: `G` is a unit struct, and does not take parentheses to be constructed + | +LL - let g = G(); +LL + let g = G; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-2074.rs b/tests/ui/issues/issue-2074.rs new file mode 100644 index 000000000..a6bea3858 --- /dev/null +++ b/tests/ui/issues/issue-2074.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(non_camel_case_types)] + +pub fn main() { + let one = || { + enum r { a } + r::a as usize + }; + let two = || { + enum r { a } + r::a as usize + }; + one(); two(); +} diff --git a/tests/ui/issues/issue-20763-1.rs b/tests/ui/issues/issue-20763-1.rs new file mode 100644 index 000000000..858d313fc --- /dev/null +++ b/tests/ui/issues/issue-20763-1.rs @@ -0,0 +1,29 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait T0 { + type O; + fn dummy(&self) { } +} + +struct S(A); +impl T0 for S { type O = A; } + +trait T1: T0 { + // this looks okay but as we see below, `f` is unusable + fn m0::O) -> bool>(self, f: F) -> bool; +} + +// complains about the bounds on F here not being required by the trait +impl T1 for S { + fn m0 bool>(self, f: F) -> bool { f(self.0) } +} + +// // complains about mismatched types: as T0>::O vs. A +// impl T1 for S +// { +// fn m0::O) -> bool>(self, f: F) -> bool { f(self.0) } +// } + +fn main() { } diff --git a/tests/ui/issues/issue-20763-2.rs b/tests/ui/issues/issue-20763-2.rs new file mode 100644 index 000000000..aa5bed209 --- /dev/null +++ b/tests/ui/issues/issue-20763-2.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait T0 { + type O; + fn dummy(&self) { } +} + +struct S(A); +impl T0 for S { type O = A; } + +trait T1: T0 { + // this looks okay but as we see below, `f` is unusable + fn m0::O) -> bool>(self, f: F) -> bool; +} + +// complains about mismatched types: as T0>::O vs. A +impl T1 for S +{ + fn m0::O) -> bool>(self, f: F) -> bool { f(self.0) } +} + +fn main() { } diff --git a/tests/ui/issues/issue-20772.rs b/tests/ui/issues/issue-20772.rs new file mode 100644 index 000000000..1500bc831 --- /dev/null +++ b/tests/ui/issues/issue-20772.rs @@ -0,0 +1,5 @@ +trait T : Iterator +//~^ ERROR cycle detected +{} + +fn main() {} diff --git a/tests/ui/issues/issue-20772.stderr b/tests/ui/issues/issue-20772.stderr new file mode 100644 index 000000000..22b9f5bd4 --- /dev/null +++ b/tests/ui/issues/issue-20772.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the super traits of `T` with associated type name `Item` + --> $DIR/issue-20772.rs:1:1 + | +LL | trait T : Iterator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing the super traits of `T` with associated type name `Item` again +note: cycle used when computing the super traits of `T` + --> $DIR/issue-20772.rs:1:1 + | +LL | trait T : Iterator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-20797.rs b/tests/ui/issues/issue-20797.rs new file mode 100644 index 000000000..ef0e72571 --- /dev/null +++ b/tests/ui/issues/issue-20797.rs @@ -0,0 +1,93 @@ +// build-pass + +// Regression test for #20797. + +use std::default::Default; +use std::io; +use std::fs; +use std::path::PathBuf; + +pub trait PathExtensions { + fn is_dir(&self) -> bool { false } +} + +impl PathExtensions for PathBuf {} + +/// A strategy for acquiring more subpaths to walk. +pub trait Strategy { + type P: PathExtensions; + /// Gets additional subpaths from a given path. + fn get_more(&self, item: &Self::P) -> io::Result>; + /// Determine whether a path should be walked further. + /// This is run against each item from `get_more()`. + fn prune(&self, p: &Self::P) -> bool; +} + +/// The basic fully-recursive strategy. Nothing is pruned. +#[derive(Copy, Clone, Default)] +pub struct Recursive; + +impl Strategy for Recursive { + type P = PathBuf; + fn get_more(&self, p: &PathBuf) -> io::Result> { + Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect()) + } + + fn prune(&self, _: &PathBuf) -> bool { false } +} + +/// A directory walker of `P` using strategy `S`. +pub struct Subpaths { + stack: Vec, + strategy: S, +} + +impl Subpaths { + /// Creates a directory walker with a root path and strategy. + pub fn new(p: &S::P, strategy: S) -> io::Result> { + let stack = strategy.get_more(p)?; + Ok(Subpaths { stack: stack, strategy: strategy }) + } +} + +impl Subpaths { + /// Creates a directory walker with a root path and a default strategy. + pub fn walk(p: &S::P) -> io::Result> { + Subpaths::new(p, Default::default()) + } +} + +impl Default for Subpaths { + fn default() -> Subpaths { + Subpaths { stack: Vec::new(), strategy: Default::default() } + } +} + +impl Iterator for Subpaths { + type Item = S::P; + fn next (&mut self) -> Option { + let mut opt_path = self.stack.pop(); + while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { + opt_path = self.stack.pop(); + } + match opt_path { + Some(path) => { + if path.is_dir() { + let result = self.strategy.get_more(&path); + match result { + Ok(dirs) => { self.stack.extend(dirs); }, + Err(..) => { } + } + } + Some(path) + } + None => None, + } + } +} + +fn _foo() { + let _walker: Subpaths = Subpaths::walk(&PathBuf::from("/home")).unwrap(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-20803.rs b/tests/ui/issues/issue-20803.rs new file mode 100644 index 000000000..f657cf6cd --- /dev/null +++ b/tests/ui/issues/issue-20803.rs @@ -0,0 +1,10 @@ +// run-pass +use std::ops::Add; + +fn foo(x: T) -> >::Output where i32: Add { + 42i32 + x +} + +fn main() { + println!("{}", foo(0i32)); +} diff --git a/tests/ui/issues/issue-20831-debruijn.rs b/tests/ui/issues/issue-20831-debruijn.rs new file mode 100644 index 000000000..20d980763 --- /dev/null +++ b/tests/ui/issues/issue-20831-debruijn.rs @@ -0,0 +1,39 @@ +// Regression test for #20831: debruijn index account was thrown off +// by the (anonymous) lifetime in `::Output` +// below. Note that changing to a named lifetime made the problem go +// away. + +use std::cell::RefCell; +use std::ops::{Shl, Shr}; + +pub trait Subscriber { + type Input; +} + +pub trait Publisher<'a> { + type Output; + fn subscribe(&mut self, _: Box + 'a>); +} + +pub trait Processor<'a> : Subscriber + Publisher<'a> { } + +impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { } + +struct MyStruct<'a> { + sub: Box + 'a> +} + +impl<'a> Publisher<'a> for MyStruct<'a> { + type Output = u64; + fn subscribe(&mut self, t : Box::Output> + 'a>) { + // Not obvious, but there is an implicit lifetime here -------^ + //~^^ ERROR cannot infer + // + // The fact that `Publisher` is using an implicit lifetime is + // what was causing the debruijn accounting to be off, so + // leave it that way! + self.sub = t; + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr new file mode 100644 index 000000000..c3af1f678 --- /dev/null +++ b/tests/ui/issues/issue-20831-debruijn.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/issue-20831-debruijn.rs:28:33 + | +LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime defined here... + --> $DIR/issue-20831-debruijn.rs:28:58 + | +LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... + --> $DIR/issue-20831-debruijn.rs:26:6 + | +LL | impl<'a> Publisher<'a> for MyStruct<'a> { + | ^^ +note: ...so that the types are compatible + --> $DIR/issue-20831-debruijn.rs:28:33 + | +LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected ` as Publisher<'_>>` + found ` as Publisher<'_>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/issues/issue-20847.rs b/tests/ui/issues/issue-20847.rs new file mode 100644 index 000000000..0cd7edf89 --- /dev/null +++ b/tests/ui/issues/issue-20847.rs @@ -0,0 +1,12 @@ +// run-pass +#![feature(fn_traits)] + +use std::ops::Fn; + +fn say(x: u32, y: u32) { + println!("{} {}", x, y); +} + +fn main() { + Fn::call(&say, (1, 2)); +} diff --git a/tests/ui/issues/issue-20939.rs b/tests/ui/issues/issue-20939.rs new file mode 100644 index 000000000..c0c222978 --- /dev/null +++ b/tests/ui/issues/issue-20939.rs @@ -0,0 +1,6 @@ +trait Foo {} + +impl<'a> Foo for dyn Foo + 'a {} +//~^ ERROR the object type `(dyn Foo + 'a)` automatically implements the trait `Foo` + +fn main() {} diff --git a/tests/ui/issues/issue-20939.stderr b/tests/ui/issues/issue-20939.stderr new file mode 100644 index 000000000..3819a21a2 --- /dev/null +++ b/tests/ui/issues/issue-20939.stderr @@ -0,0 +1,9 @@ +error[E0371]: the object type `(dyn Foo + 'a)` automatically implements the trait `Foo` + --> $DIR/issue-20939.rs:3:1 + | +LL | impl<'a> Foo for dyn Foo + 'a {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Foo + 'a)` automatically implements trait `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0371`. diff --git a/tests/ui/issues/issue-20953.rs b/tests/ui/issues/issue-20953.rs new file mode 100644 index 000000000..4ec7e3195 --- /dev/null +++ b/tests/ui/issues/issue-20953.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +fn main() { + let mut shrinker: Box> = Box::new(vec![1].into_iter()); + println!("{:?}", shrinker.next()); + for v in shrinker { assert!(false); } + + let mut shrinker: &mut dyn Iterator = &mut vec![1].into_iter(); + println!("{:?}", shrinker.next()); + for v in shrinker { assert!(false); } +} diff --git a/tests/ui/issues/issue-20971.rs b/tests/ui/issues/issue-20971.rs new file mode 100644 index 000000000..2e1041817 --- /dev/null +++ b/tests/ui/issues/issue-20971.rs @@ -0,0 +1,23 @@ +// Regression test for Issue #20971. + +// run-fail +// error-pattern:Hello, world! +// ignore-emscripten no processes + +pub trait Parser { + type Input; + fn parse(&mut self, input: ::Input); +} + +impl Parser for () { + type Input = (); + fn parse(&mut self, input: ()) {} +} + +pub fn many() -> Box::Input> + 'static> { + panic!("Hello, world!") +} + +fn main() { + many().parse(()); +} diff --git a/tests/ui/issues/issue-21033.rs b/tests/ui/issues/issue-21033.rs new file mode 100644 index 000000000..91f72eb36 --- /dev/null +++ b/tests/ui/issues/issue-21033.rs @@ -0,0 +1,48 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +#![feature(box_patterns)] + +enum E { + StructVar { boxed: Box } +} + +fn main() { + + // Test matching each shorthand notation for field patterns. + let mut a = E::StructVar { boxed: Box::new(3) }; + match a { + E::StructVar { box boxed } => { } + } + match a { + E::StructVar { box ref boxed } => { } + } + match a { + E::StructVar { box mut boxed } => { } + } + match a { + E::StructVar { box ref mut boxed } => { } + } + match a { + E::StructVar { ref boxed } => { } + } + match a { + E::StructVar { ref mut boxed } => { } + } + match a { + E::StructVar { mut boxed } => { } + } + + // Test matching non shorthand notation. Recreate a since last test + // moved `boxed` + let mut a = E::StructVar { boxed: Box::new(3) }; + match a { + E::StructVar { boxed: box ref mut num } => { } + } + match a { + E::StructVar { boxed: ref mut num } => { } + } + +} diff --git a/tests/ui/issues/issue-21140.rs b/tests/ui/issues/issue-21140.rs new file mode 100644 index 000000000..01de90111 --- /dev/null +++ b/tests/ui/issues/issue-21140.rs @@ -0,0 +1,6 @@ +// check-pass +pub trait Trait where Self::Out: std::fmt::Display { + type Out; +} + +fn main() {} diff --git a/tests/ui/issues/issue-21160.rs b/tests/ui/issues/issue-21160.rs new file mode 100644 index 000000000..10136ba11 --- /dev/null +++ b/tests/ui/issues/issue-21160.rs @@ -0,0 +1,11 @@ +struct Bar; + +impl Bar { + fn hash(&self, _: T) {} +} + +#[derive(Hash)] +struct Foo(Bar); +//~^ error: `Bar: Hash` is not satisfied + +fn main() {} diff --git a/tests/ui/issues/issue-21160.stderr b/tests/ui/issues/issue-21160.stderr new file mode 100644 index 000000000..266749376 --- /dev/null +++ b/tests/ui/issues/issue-21160.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Bar: Hash` is not satisfied + --> $DIR/issue-21160.rs:8:12 + | +LL | #[derive(Hash)] + | ---- in this derive macro expansion +LL | struct Foo(Bar); + | ^^^ the trait `Hash` is not implemented for `Bar` + | + = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Bar` with `#[derive(Hash)]` + | +LL | #[derive(Hash)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-21174-2.rs b/tests/ui/issues/issue-21174-2.rs new file mode 100644 index 000000000..c90f91f6a --- /dev/null +++ b/tests/ui/issues/issue-21174-2.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] +trait Trait<'a> { + type A; + type B; +} + +fn foo<'a, T: Trait<'a>>(value: T::A) { + let new: T::B = unsafe { std::mem::transmute_copy(&value) }; +} + +fn main() { } diff --git a/tests/ui/issues/issue-21174.rs b/tests/ui/issues/issue-21174.rs new file mode 100644 index 000000000..078274251 --- /dev/null +++ b/tests/ui/issues/issue-21174.rs @@ -0,0 +1,11 @@ +trait Trait<'a> { + type A; + type B; +} + +fn foo<'a, T: Trait<'a>>(value: T::A) { + let new: T::B = unsafe { std::mem::transmute(value) }; +//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types +} + +fn main() { } diff --git a/tests/ui/issues/issue-21174.stderr b/tests/ui/issues/issue-21174.stderr new file mode 100644 index 000000000..5981d9dc7 --- /dev/null +++ b/tests/ui/issues/issue-21174.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/issue-21174.rs:7:30 + | +LL | let new: T::B = unsafe { std::mem::transmute(value) }; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `>::A` (this type does not have a fixed size) + = note: target type: `>::B` (this type does not have a fixed size) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/issues/issue-21177.rs b/tests/ui/issues/issue-21177.rs new file mode 100644 index 000000000..258e362d1 --- /dev/null +++ b/tests/ui/issues/issue-21177.rs @@ -0,0 +1,9 @@ +trait Trait { + type A; + type B; +} + +fn foo>() { } +//~^ ERROR cycle detected + +fn main() { } diff --git a/tests/ui/issues/issue-21177.stderr b/tests/ui/issues/issue-21177.stderr new file mode 100644 index 000000000..6877a1846 --- /dev/null +++ b/tests/ui/issues/issue-21177.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing the bounds for type parameter `T` + --> $DIR/issue-21177.rs:6:21 + | +LL | fn foo>() { } + | ^^^^ + | + = note: ...which immediately requires computing the bounds for type parameter `T` again +note: cycle used when computing explicit predicates of `foo` + --> $DIR/issue-21177.rs:6:21 + | +LL | fn foo>() { } + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-21202.rs b/tests/ui/issues/issue-21202.rs new file mode 100644 index 000000000..f62de7ce7 --- /dev/null +++ b/tests/ui/issues/issue-21202.rs @@ -0,0 +1,15 @@ +// aux-build:issue-21202.rs + +extern crate issue_21202 as crate1; + +use crate1::A; + +mod B { + use crate1::A::Foo; + fn bar(f: Foo) { + Foo::foo(&f); + //~^ ERROR: associated function `foo` is private + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-21202.stderr b/tests/ui/issues/issue-21202.stderr new file mode 100644 index 000000000..1d2816fed --- /dev/null +++ b/tests/ui/issues/issue-21202.stderr @@ -0,0 +1,14 @@ +error[E0624]: associated function `foo` is private + --> $DIR/issue-21202.rs:10:14 + | +LL | Foo::foo(&f); + | ^^^ private associated function + | + ::: $DIR/auxiliary/issue-21202.rs:4:9 + | +LL | fn foo(&self) { } + | ------------- private associated function defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/issues/issue-21245.rs b/tests/ui/issues/issue-21245.rs new file mode 100644 index 000000000..c8e55a0cc --- /dev/null +++ b/tests/ui/issues/issue-21245.rs @@ -0,0 +1,56 @@ +// check-pass +#![allow(dead_code)] +// Regression test for issue #21245. Check that we are able to infer +// the types in these examples correctly. It used to be that +// insufficient type propagation caused the type of the iterator to be +// incorrectly unified with the `*const` type to which it is coerced. + +// pretty-expanded FIXME #23616 + +use std::ptr; + +trait IntoIterator { + type Iter: Iterator; + + fn into_iter2(self) -> Self::Iter; +} + +impl IntoIterator for I where I: Iterator { + type Iter = I; + + fn into_iter2(self) -> I { + self + } +} + +fn desugared_for_loop_bad(v: Vec) { + match IntoIterator::into_iter2(v.iter()) { + mut iter => { + loop { + match ::std::iter::Iterator::next(&mut iter) { + ::std::option::Option::Some(x) => { + unsafe { ptr::read(x); } + }, + ::std::option::Option::None => break + } + } + } + } +} + +fn desugared_for_loop_good(v: Vec) { + match v.iter().into_iter() { + mut iter => { + loop { + match ::std::iter::Iterator::next(&mut iter) { + ::std::option::Option::Some(x) => { + unsafe { ptr::read(x); } + }, + ::std::option::Option::None => break + } + } + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-21291.rs b/tests/ui/issues/issue-21291.rs new file mode 100644 index 000000000..b351e22d8 --- /dev/null +++ b/tests/ui/issues/issue-21291.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-emscripten no threads support + +// Regression test for unwrapping the result of `join`, issue #21291 + +use std::thread; + +fn main() { + thread::spawn(|| {}).join().unwrap() +} diff --git a/tests/ui/issues/issue-21306.rs b/tests/ui/issues/issue-21306.rs new file mode 100644 index 000000000..b06a475e4 --- /dev/null +++ b/tests/ui/issues/issue-21306.rs @@ -0,0 +1,9 @@ +// run-pass + +use std::sync::Arc; + +fn main() { + let x = 5; + let command = Arc::new(Box::new(|| { x*2 })); + assert_eq!(command(), 10); +} diff --git a/tests/ui/issues/issue-21332.rs b/tests/ui/issues/issue-21332.rs new file mode 100644 index 000000000..6547f3a9b --- /dev/null +++ b/tests/ui/issues/issue-21332.rs @@ -0,0 +1,10 @@ +struct S; + +impl Iterator for S { + type Item = i32; + fn next(&mut self) -> Result { Ok(7) } + //~^ ERROR method `next` has an incompatible type for trait + //~| expected enum `Option`, found enum `Result` +} + +fn main() {} diff --git a/tests/ui/issues/issue-21332.stderr b/tests/ui/issues/issue-21332.stderr new file mode 100644 index 000000000..0e1beebf2 --- /dev/null +++ b/tests/ui/issues/issue-21332.stderr @@ -0,0 +1,15 @@ +error[E0053]: method `next` has an incompatible type for trait + --> $DIR/issue-21332.rs:5:27 + | +LL | fn next(&mut self) -> Result { Ok(7) } + | ^^^^^^^^^^^^^^^^ + | | + | expected enum `Option`, found enum `Result` + | help: change the output type to match the trait: `Option` + | + = note: expected signature `fn(&mut S) -> Option` + found signature `fn(&mut S) -> Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-21361.rs b/tests/ui/issues/issue-21361.rs new file mode 100644 index 000000000..c970e77ab --- /dev/null +++ b/tests/ui/issues/issue-21361.rs @@ -0,0 +1,11 @@ +// run-pass + +fn main() { + let v = vec![1, 2, 3]; + let boxed: Box> = Box::new(v.into_iter()); + assert_eq!(boxed.max(), Some(3)); + + let v = vec![1, 2, 3]; + let boxed: &mut dyn Iterator = &mut v.into_iter(); + assert_eq!(boxed.max(), Some(3)); +} diff --git a/tests/ui/issues/issue-21384.rs b/tests/ui/issues/issue-21384.rs new file mode 100644 index 000000000..caa99a159 --- /dev/null +++ b/tests/ui/issues/issue-21384.rs @@ -0,0 +1,21 @@ +// run-pass + +use ::std::ops::RangeFull; + +fn test(arg: T) -> T { + arg.clone() +} + +#[derive(PartialEq, Debug)] +struct Test(isize); + +fn main() { + // Check that ranges implement clone + assert_eq!(test(1..5), (1..5)); + assert_eq!(test(..5), (..5)); + assert_eq!(test(1..), (1..)); + assert_eq!(test(RangeFull), (RangeFull)); + + // Check that ranges can still be used with non-clone limits + assert_eq!((Test(1)..Test(5)), (Test(1)..Test(5))); +} diff --git a/tests/ui/issues/issue-21400.rs b/tests/ui/issues/issue-21400.rs new file mode 100644 index 000000000..4a85158d9 --- /dev/null +++ b/tests/ui/issues/issue-21400.rs @@ -0,0 +1,56 @@ +// run-pass +// Regression test for #21400 which itself was extracted from +// stackoverflow.com/questions/28031155/is-my-borrow-checker-drunk/28031580 + +fn main() { + let mut t = Test; + assert_eq!(t.method1("one"), Ok(1)); + assert_eq!(t.method2("two"), Ok(2)); + assert_eq!(t.test(), Ok(2)); +} + +struct Test; + +impl Test { + fn method1(&mut self, _arg: &str) -> Result { + Ok(1) + } + + fn method2(self: &mut Test, _arg: &str) -> Result { + Ok(2) + } + + fn test(self: &mut Test) -> Result { + let s = format!("abcde"); + // (Originally, this invocation of method2 was saying that `s` + // does not live long enough.) + let data = match self.method2(&*s) { + Ok(r) => r, + Err(e) => return Err(e) + }; + Ok(data) + } +} + +// Below is a closer match for the original test that was failing to compile + +pub struct GitConnect; + +impl GitConnect { + fn command(self: &mut GitConnect, _s: &str) -> Result>, &str> { + unimplemented!() + } + + pub fn git_upload_pack(self: &mut GitConnect) -> Result { + let c = format!("git-upload-pack"); + + let mut out = String::new(); + let data = self.command(&c)?; + + for line in data.iter() { + out.push_str(&format!("{:?}", line)); + } + + Ok(out) + } +} diff --git a/tests/ui/issues/issue-21402.rs b/tests/ui/issues/issue-21402.rs new file mode 100644 index 000000000..d140b6162 --- /dev/null +++ b/tests/ui/issues/issue-21402.rs @@ -0,0 +1,12 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#[derive(Hash)] +struct Foo { + a: Vec, + b: (bool, bool), + c: [bool; 2], +} + +fn main() {} diff --git a/tests/ui/issues/issue-21449.rs b/tests/ui/issues/issue-21449.rs new file mode 100644 index 000000000..00ce2b7ff --- /dev/null +++ b/tests/ui/issues/issue-21449.rs @@ -0,0 +1,6 @@ +mod MyMod {} + +fn main() { + let myVar = MyMod { T: 0 }; + //~^ ERROR expected struct, variant or union type, found module `MyMod` +} diff --git a/tests/ui/issues/issue-21449.stderr b/tests/ui/issues/issue-21449.stderr new file mode 100644 index 000000000..ecaf6faba --- /dev/null +++ b/tests/ui/issues/issue-21449.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found module `MyMod` + --> $DIR/issue-21449.rs:4:17 + | +LL | let myVar = MyMod { T: 0 }; + | ^^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-2150.rs b/tests/ui/issues/issue-2150.rs new file mode 100644 index 000000000..baa1dde0f --- /dev/null +++ b/tests/ui/issues/issue-2150.rs @@ -0,0 +1,12 @@ +#![deny(unreachable_code)] +#![allow(unused_variables)] +#![allow(dead_code)] + +fn fail_len(v: Vec ) -> usize { + let mut i = 3; + panic!(); + for x in &v { i += 1; } + //~^ ERROR: unreachable statement + return i; +} +fn main() {} diff --git a/tests/ui/issues/issue-2150.stderr b/tests/ui/issues/issue-2150.stderr new file mode 100644 index 000000000..26874faa2 --- /dev/null +++ b/tests/ui/issues/issue-2150.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/issue-2150.rs:8:5 + | +LL | panic!(); + | -------- any code following this expression is unreachable +LL | for x in &v { i += 1; } + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/issue-2150.rs:1:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-2151.rs b/tests/ui/issues/issue-2151.rs new file mode 100644 index 000000000..82cf49de8 --- /dev/null +++ b/tests/ui/issues/issue-2151.rs @@ -0,0 +1,4 @@ +fn main() { + let x = panic!(); //~ ERROR type annotations needed + x.clone(); +} diff --git a/tests/ui/issues/issue-2151.stderr b/tests/ui/issues/issue-2151.stderr new file mode 100644 index 000000000..c75038b61 --- /dev/null +++ b/tests/ui/issues/issue-2151.stderr @@ -0,0 +1,16 @@ +error[E0282]: type annotations needed + --> $DIR/issue-2151.rs:2:9 + | +LL | let x = panic!(); + | ^ +LL | x.clone(); + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let x: /* Type */ = panic!(); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-21546.rs b/tests/ui/issues/issue-21546.rs new file mode 100644 index 000000000..9f3974b43 --- /dev/null +++ b/tests/ui/issues/issue-21546.rs @@ -0,0 +1,49 @@ +// Also works as a test for #14564 + +#[allow(non_snake_case)] +mod Foo { } + +#[allow(dead_code)] +struct Foo; +//~^ ERROR the name `Foo` is defined multiple times + +#[allow(non_snake_case)] +mod Bar { } + +#[allow(dead_code)] +struct Bar(i32); +//~^ ERROR the name `Bar` is defined multiple times + + +#[allow(dead_code)] +struct Baz(i32); + +#[allow(non_snake_case)] +mod Baz { } +//~^ ERROR the name `Baz` is defined multiple times + + +#[allow(dead_code)] +struct Qux { x: bool } + +#[allow(non_snake_case)] +mod Qux { } +//~^ ERROR the name `Qux` is defined multiple times + + +#[allow(dead_code)] +struct Quux; + +#[allow(non_snake_case)] +mod Quux { } +//~^ ERROR the name `Quux` is defined multiple times + + +#[allow(dead_code)] +enum Corge { A, B } + +#[allow(non_snake_case)] +mod Corge { } +//~^ ERROR the name `Corge` is defined multiple times + +fn main() { } diff --git a/tests/ui/issues/issue-21546.stderr b/tests/ui/issues/issue-21546.stderr new file mode 100644 index 000000000..5fd06fc67 --- /dev/null +++ b/tests/ui/issues/issue-21546.stderr @@ -0,0 +1,69 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-21546.rs:7:1 + | +LL | mod Foo { } + | ------- previous definition of the module `Foo` here +... +LL | struct Foo; + | ^^^^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0428]: the name `Bar` is defined multiple times + --> $DIR/issue-21546.rs:14:1 + | +LL | mod Bar { } + | ------- previous definition of the module `Bar` here +... +LL | struct Bar(i32); + | ^^^^^^^^^^^^^^^^ `Bar` redefined here + | + = note: `Bar` must be defined only once in the type namespace of this module + +error[E0428]: the name `Baz` is defined multiple times + --> $DIR/issue-21546.rs:22:1 + | +LL | struct Baz(i32); + | ---------------- previous definition of the type `Baz` here +... +LL | mod Baz { } + | ^^^^^^^ `Baz` redefined here + | + = note: `Baz` must be defined only once in the type namespace of this module + +error[E0428]: the name `Qux` is defined multiple times + --> $DIR/issue-21546.rs:30:1 + | +LL | struct Qux { x: bool } + | ---------- previous definition of the type `Qux` here +... +LL | mod Qux { } + | ^^^^^^^ `Qux` redefined here + | + = note: `Qux` must be defined only once in the type namespace of this module + +error[E0428]: the name `Quux` is defined multiple times + --> $DIR/issue-21546.rs:38:1 + | +LL | struct Quux; + | ------------ previous definition of the type `Quux` here +... +LL | mod Quux { } + | ^^^^^^^^ `Quux` redefined here + | + = note: `Quux` must be defined only once in the type namespace of this module + +error[E0428]: the name `Corge` is defined multiple times + --> $DIR/issue-21546.rs:46:1 + | +LL | enum Corge { A, B } + | ---------- previous definition of the type `Corge` here +... +LL | mod Corge { } + | ^^^^^^^^^ `Corge` redefined here + | + = note: `Corge` must be defined only once in the type namespace of this module + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-21554.rs b/tests/ui/issues/issue-21554.rs new file mode 100644 index 000000000..c176b1247 --- /dev/null +++ b/tests/ui/issues/issue-21554.rs @@ -0,0 +1,6 @@ +struct Inches(i32); + +fn main() { + Inches as f32; + //~^ ERROR casting +} diff --git a/tests/ui/issues/issue-21554.stderr b/tests/ui/issues/issue-21554.stderr new file mode 100644 index 000000000..6ea552a26 --- /dev/null +++ b/tests/ui/issues/issue-21554.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `fn(i32) -> Inches {Inches}` as `f32` is invalid + --> $DIR/issue-21554.rs:4:5 + | +LL | Inches as f32; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/issues/issue-21596.rs b/tests/ui/issues/issue-21596.rs new file mode 100644 index 000000000..79f6c91d9 --- /dev/null +++ b/tests/ui/issues/issue-21596.rs @@ -0,0 +1,5 @@ +fn main() { + let x = 8u8; + let z: *const u8 = &x; + println!("{}", z.to_string()); //~ ERROR E0599 +} diff --git a/tests/ui/issues/issue-21596.stderr b/tests/ui/issues/issue-21596.stderr new file mode 100644 index 000000000..a336d1b0e --- /dev/null +++ b/tests/ui/issues/issue-21596.stderr @@ -0,0 +1,15 @@ +error[E0599]: `*const u8` doesn't implement `std::fmt::Display` + --> $DIR/issue-21596.rs:4:22 + | +LL | println!("{}", z.to_string()); + | ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter + | + = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref + = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior + = note: the following trait bounds were not satisfied: + `*const u8: std::fmt::Display` + which is required by `*const u8: ToString` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-21600.rs b/tests/ui/issues/issue-21600.rs new file mode 100644 index 000000000..2e22e5e6f --- /dev/null +++ b/tests/ui/issues/issue-21600.rs @@ -0,0 +1,18 @@ +fn call_it(f: F) where F: Fn() { f(); } + +struct A; + +impl A { + fn gen(&self) {} + fn gen_mut(&mut self) {} +} + +fn main() { + let mut x = A; + call_it(|| { + call_it(|| x.gen()); + call_it(|| x.gen_mut()); + //~^ ERROR cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + //~| ERROR cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + }); +} diff --git a/tests/ui/issues/issue-21600.stderr b/tests/ui/issues/issue-21600.stderr new file mode 100644 index 000000000..ea304f936 --- /dev/null +++ b/tests/ui/issues/issue-21600.stderr @@ -0,0 +1,31 @@ +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/issue-21600.rs:14:20 + | +LL | fn call_it(f: F) where F: Fn() { f(); } + | - change this to accept `FnMut` instead of `Fn` +... +LL | call_it(|| x.gen_mut()); + | ------- -- ^^^^^^^^^^^ cannot borrow as mutable + | | | + | | in this closure + | expects `Fn` instead of `FnMut` + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/issue-21600.rs:14:17 + | +LL | fn call_it(f: F) where F: Fn() { f(); } + | - change this to accept `FnMut` instead of `Fn` +... +LL | call_it(|| { + | ------- -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | call_it(|| x.gen()); +LL | call_it(|| x.gen_mut()); + | ^^ - mutable borrow occurs due to use of `x` in closure + | | + | cannot borrow as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-21622.rs b/tests/ui/issues/issue-21622.rs new file mode 100644 index 000000000..2d4cddac9 --- /dev/null +++ b/tests/ui/issues/issue-21622.rs @@ -0,0 +1,21 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Index; + +impl Index { + fn new() -> Self { Index } +} + +fn user() { + let new = Index::new; + + fn inner() { + let index = Index::new(); + } + + let index2 = new(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-21634.rs b/tests/ui/issues/issue-21634.rs new file mode 100644 index 000000000..2731bfd76 --- /dev/null +++ b/tests/ui/issues/issue-21634.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(stable_features)] + +#![feature(cfg_target_feature)] + +#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] +fn main() { + if let Ok(x) = "3.1415".parse::() { + assert_eq!(false, x <= 0.0); + } + if let Ok(x) = "3.1415".parse::() { + assert_eq!(3.1415, x + 0.0); + } + if let Ok(mut x) = "3.1415".parse::() { + assert_eq!(8.1415, { x += 5.0; x }); + } +} + +#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] +fn main() {} diff --git a/tests/ui/issues/issue-21655.rs b/tests/ui/issues/issue-21655.rs new file mode 100644 index 000000000..d1cd4ec7b --- /dev/null +++ b/tests/ui/issues/issue-21655.rs @@ -0,0 +1,12 @@ +// run-pass + +fn test(it: &mut dyn Iterator) { + for x in it { + assert_eq!(x, 1) + } +} + +fn main() { + let v = vec![1]; + test(&mut v.into_iter()) +} diff --git a/tests/ui/issues/issue-2170-exe.rs b/tests/ui/issues/issue-2170-exe.rs new file mode 100644 index 000000000..a89579706 --- /dev/null +++ b/tests/ui/issues/issue-2170-exe.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:issue-2170-lib.rs +// pretty-expanded FIXME #23616 + +extern crate issue_2170_lib; + +pub fn main() { + // let _ = issue_2170_lib::rsrc(2); +} diff --git a/tests/ui/issues/issue-21701.rs b/tests/ui/issues/issue-21701.rs new file mode 100644 index 000000000..bfa03c5e4 --- /dev/null +++ b/tests/ui/issues/issue-21701.rs @@ -0,0 +1,15 @@ +fn foo(t: U) { + let y = t(); +//~^ ERROR: expected function, found `U` +} + +struct Bar; + +pub fn some_func() { + let f = Bar(); +//~^ ERROR: expected function, found struct `Bar` +} + +fn main() { + foo(|| { 1 }); +} diff --git a/tests/ui/issues/issue-21701.stderr b/tests/ui/issues/issue-21701.stderr new file mode 100644 index 000000000..9f1fe7dde --- /dev/null +++ b/tests/ui/issues/issue-21701.stderr @@ -0,0 +1,30 @@ +error[E0618]: expected function, found `U` + --> $DIR/issue-21701.rs:2:13 + | +LL | fn foo(t: U) { + | - `t` has type `U` +LL | let y = t(); + | ^-- + | | + | call expression requires function + +error[E0618]: expected function, found struct `Bar` + --> $DIR/issue-21701.rs:9:13 + | +LL | struct Bar; + | ---------- struct `Bar` defined here +... +LL | let f = Bar(); + | ^^^-- + | | + | call expression requires function + | +help: `Bar` is a unit struct, and does not take parentheses to be constructed + | +LL - let f = Bar(); +LL + let f = Bar; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-21763.rs b/tests/ui/issues/issue-21763.rs new file mode 100644 index 000000000..5beb1d8b8 --- /dev/null +++ b/tests/ui/issues/issue-21763.rs @@ -0,0 +1,11 @@ +// Regression test for HashMap only impl'ing Send/Sync if its contents do + +use std::collections::HashMap; +use std::rc::Rc; + +fn foo() {} + +fn main() { + foo::, Rc<()>>>(); + //~^ ERROR `Rc<()>` cannot be sent between threads safely +} diff --git a/tests/ui/issues/issue-21763.stderr b/tests/ui/issues/issue-21763.stderr new file mode 100644 index 000000000..04379f07b --- /dev/null +++ b/tests/ui/issues/issue-21763.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Rc<()>` cannot be sent between threads safely + --> $DIR/issue-21763.rs:9:11 + | +LL | foo::, Rc<()>>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely + | + = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>` + = note: required because it appears within the type `(Rc<()>, Rc<()>)` + = note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send` + = note: required because it appears within the type `HashMap, Rc<()>, RandomState>` + = note: required because it appears within the type `HashMap, Rc<()>>` +note: required by a bound in `foo` + --> $DIR/issue-21763.rs:6:11 + | +LL | fn foo() {} + | ^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-21837.rs b/tests/ui/issues/issue-21837.rs new file mode 100644 index 000000000..213119bd2 --- /dev/null +++ b/tests/ui/issues/issue-21837.rs @@ -0,0 +1,10 @@ +pub trait Bound {} +pub struct Foo(T); + +pub trait Trait1 {} +impl Trait1 for Foo {} + +pub trait Trait2 {} +impl Trait2 for Foo {} //~ ERROR the trait bound `T: Bound` is not satisfied + +fn main() {} diff --git a/tests/ui/issues/issue-21837.stderr b/tests/ui/issues/issue-21837.stderr new file mode 100644 index 000000000..3d3852664 --- /dev/null +++ b/tests/ui/issues/issue-21837.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Bound` is not satisfied + --> $DIR/issue-21837.rs:8:20 + | +LL | impl Trait2 for Foo {} + | ^^^^^^ the trait `Bound` is not implemented for `T` + | +note: required by a bound in `Foo` + --> $DIR/issue-21837.rs:2:19 + | +LL | pub struct Foo(T); + | ^^^^^ required by this bound in `Foo` +help: consider restricting type parameter `T` + | +LL | impl Trait2 for Foo {} + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-21891.rs b/tests/ui/issues/issue-21891.rs new file mode 100644 index 000000000..576f0253e --- /dev/null +++ b/tests/ui/issues/issue-21891.rs @@ -0,0 +1,12 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +// pretty-expanded FIXME #23616 + +static foo: [usize; 3] = [1, 2, 3]; + +static slice_1: &'static [usize] = &foo; +static slice_2: &'static [usize] = &foo; + +fn main() {} diff --git a/tests/ui/issues/issue-2190-1.rs b/tests/ui/issues/issue-2190-1.rs new file mode 100644 index 000000000..e67a924b9 --- /dev/null +++ b/tests/ui/issues/issue-2190-1.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(non_upper_case_globals)] + +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads + +use std::thread::Builder; + +static generations: usize = 1024+256+128+49; + +fn spawn(mut f: Box) { + Builder::new().stack_size(32 * 1024).spawn(move|| f()); +} + +fn child_no(x: usize) -> Box { + Box::new(move|| { + if x < generations { + spawn(child_no(x+1)); + } + }) +} + +pub fn main() { + spawn(child_no(0)); +} diff --git a/tests/ui/issues/issue-21909.rs b/tests/ui/issues/issue-21909.rs new file mode 100644 index 000000000..7cb558d9a --- /dev/null +++ b/tests/ui/issues/issue-21909.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait A { + fn dummy(&self, arg: X); +} + +trait B { + type X; + type Y: A; + + fn dummy(&self); +} + +fn main () { } diff --git a/tests/ui/issues/issue-21922.rs b/tests/ui/issues/issue-21922.rs new file mode 100644 index 000000000..9727b2efe --- /dev/null +++ b/tests/ui/issues/issue-21922.rs @@ -0,0 +1,17 @@ +// run-pass +use std::ops::Add; +fn show(z: i32) { + println!("{}", z) +} +fn main() { + let x = 23; + let y = 42; + show(Add::add( x, y)); + show(Add::add( x, &y)); + show(Add::add(&x, y)); + show(Add::add(&x, &y)); + show( x + y); + show( x + &y); + show(&x + y); + show(&x + &y); +} diff --git a/tests/ui/issues/issue-21946.rs b/tests/ui/issues/issue-21946.rs new file mode 100644 index 000000000..d0c052cb2 --- /dev/null +++ b/tests/ui/issues/issue-21946.rs @@ -0,0 +1,12 @@ +trait Foo { + type A; +} + +struct FooStruct; + +impl Foo for FooStruct { + type A = ::A; + //~^ ERROR overflow evaluating the requirement `::A == _` +} + +fn main() {} diff --git a/tests/ui/issues/issue-21946.stderr b/tests/ui/issues/issue-21946.stderr new file mode 100644 index 000000000..67f6b3081 --- /dev/null +++ b/tests/ui/issues/issue-21946.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::A == _` + --> $DIR/issue-21946.rs:8:14 + | +LL | type A = ::A; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-21950.rs b/tests/ui/issues/issue-21950.rs new file mode 100644 index 000000000..72a98bd8d --- /dev/null +++ b/tests/ui/issues/issue-21950.rs @@ -0,0 +1,13 @@ +trait Add { + type Output; +} + +impl Add for i32 { + type Output = i32; +} + +fn main() { + let x = &10 as &dyn Add; + //~^ ERROR E0393 + //~| ERROR E0191 +} diff --git a/tests/ui/issues/issue-21950.stderr b/tests/ui/issues/issue-21950.stderr new file mode 100644 index 000000000..731615a6b --- /dev/null +++ b/tests/ui/issues/issue-21950.stderr @@ -0,0 +1,24 @@ +error[E0191]: the value of the associated type `Output` (from trait `Add`) must be specified + --> $DIR/issue-21950.rs:10:25 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let x = &10 as &dyn Add; + | ^^^ help: specify the associated type: `Add` + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/issue-21950.rs:10:25 + | +LL | trait Add { + | ------------------- type parameter `Rhs` must be specified for this +... +LL | let x = &10 as &dyn Add; + | ^^^ help: set the type parameter to the desired type: `Add` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0191, E0393. +For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-21974.rs b/tests/ui/issues/issue-21974.rs new file mode 100644 index 000000000..f7c659be1 --- /dev/null +++ b/tests/ui/issues/issue-21974.rs @@ -0,0 +1,18 @@ +// Test that (for now) we report an ambiguity error here, because +// specific trait relationships are ignored for the purposes of trait +// matching. This behavior should likely be improved such that this +// test passes. See #21974 for more details. + +trait Foo { + fn foo(self); +} + +fn foo<'a,'b,T>(x: &'a T, y: &'b T) + where &'a T : Foo, //~ ERROR type annotations needed + &'b T : Foo +{ + x.foo(); + y.foo(); +} + +fn main() { } diff --git a/tests/ui/issues/issue-21974.stderr b/tests/ui/issues/issue-21974.stderr new file mode 100644 index 000000000..2d60b18b1 --- /dev/null +++ b/tests/ui/issues/issue-21974.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo` + --> $DIR/issue-21974.rs:11:19 + | +LL | where &'a T : Foo, + | ^^^ + | +note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found + --> $DIR/issue-21974.rs:11:19 + | +LL | where &'a T : Foo, + | ^^^ +LL | &'b T : Foo + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-22008.rs b/tests/ui/issues/issue-22008.rs new file mode 100644 index 000000000..004255822 --- /dev/null +++ b/tests/ui/issues/issue-22008.rs @@ -0,0 +1,9 @@ +// run-pass +pub fn main() { + let command = "a"; + + match command { + "foo" => println!("foo"), + _ => println!("{}", command), + } +} diff --git a/tests/ui/issues/issue-22034.rs b/tests/ui/issues/issue-22034.rs new file mode 100644 index 000000000..405ffd089 --- /dev/null +++ b/tests/ui/issues/issue-22034.rs @@ -0,0 +1,11 @@ +#![feature(rustc_private)] + +extern crate libc; + +fn main() { + let ptr: *mut () = core::ptr::null_mut(); + let _: &mut dyn Fn() = unsafe { + &mut *(ptr as *mut dyn Fn()) + //~^ ERROR expected a `Fn<()>` closure, found `()` + }; +} diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/issues/issue-22034.stderr new file mode 100644 index 000000000..b32de5b24 --- /dev/null +++ b/tests/ui/issues/issue-22034.stderr @@ -0,0 +1,13 @@ +error[E0277]: expected a `Fn<()>` closure, found `()` + --> $DIR/issue-22034.rs:8:16 + | +LL | &mut *(ptr as *mut dyn Fn()) + | ^^^ expected an `Fn<()>` closure, found `()` + | + = help: the trait `Fn<()>` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + = note: required for the cast from `()` to the object type `dyn Fn()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-22036.rs b/tests/ui/issues/issue-22036.rs new file mode 100644 index 000000000..30da2130a --- /dev/null +++ b/tests/ui/issues/issue-22036.rs @@ -0,0 +1,25 @@ +// run-pass + +trait DigitCollection: Sized { + type Iter: Iterator; + fn digit_iter(self) -> Self::Iter; + + fn digit_sum(self) -> u32 { + self.digit_iter() + .map(|digit: u8| digit as u32) + .fold(0, |sum, digit| sum + digit) + } +} + +impl DigitCollection for I where I: Iterator { + type Iter = I; + + fn digit_iter(self) -> I { + self + } +} + +fn main() { + let xs = vec![1, 2, 3, 4, 5]; + assert_eq!(xs.into_iter().digit_sum(), 15); +} diff --git a/tests/ui/issues/issue-2214.rs b/tests/ui/issues/issue-2214.rs new file mode 100644 index 000000000..1994c3515 --- /dev/null +++ b/tests/ui/issues/issue-2214.rs @@ -0,0 +1,41 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with +// ignore-sgx no libc +#![feature(rustc_private)] + +extern crate libc; + +use libc::{c_double, c_int}; +use std::mem; + +fn to_c_int(v: &mut isize) -> &mut c_int { + unsafe { mem::transmute_copy(&v) } +} + +fn lgamma(n: c_double, value: &mut isize) -> c_double { + unsafe { + return m::lgamma(n, to_c_int(value)); + } +} + +mod m { + use libc::{c_double, c_int}; + + extern "C" { + #[cfg(all(unix, not(target_os = "vxworks")))] + #[link_name="lgamma_r"] + pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double; + #[cfg(windows)] + #[link_name = "lgamma"] + pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double; + #[cfg(target_os = "vxworks")] + #[link_name = "lgamma"] + pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double; + } +} + +pub fn main() { + let mut y: isize = 5; + let x: &mut isize = &mut y; + assert_eq!(lgamma(1.0 as c_double, x), 0.0 as c_double); +} diff --git a/tests/ui/issues/issue-22258.rs b/tests/ui/issues/issue-22258.rs new file mode 100644 index 000000000..93ead5818 --- /dev/null +++ b/tests/ui/issues/issue-22258.rs @@ -0,0 +1,10 @@ +// run-pass +use std::ops::Add; + +fn f(a: T, b: T) -> ::Output { + a + b +} + +fn main() { + println!("a + b is {}", f::(100f32, 200f32)); +} diff --git a/tests/ui/issues/issue-22289.rs b/tests/ui/issues/issue-22289.rs new file mode 100644 index 000000000..e1b3dfe5b --- /dev/null +++ b/tests/ui/issues/issue-22289.rs @@ -0,0 +1,3 @@ +fn main() { + 0 as &dyn std::any::Any; //~ ERROR non-primitive cast +} diff --git a/tests/ui/issues/issue-22289.stderr b/tests/ui/issues/issue-22289.stderr new file mode 100644 index 000000000..b594e8b7a --- /dev/null +++ b/tests/ui/issues/issue-22289.stderr @@ -0,0 +1,14 @@ +error[E0605]: non-primitive cast: `i32` as `&(dyn Any + 'static)` + --> $DIR/issue-22289.rs:2:5 + | +LL | 0 as &dyn std::any::Any; + | ^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | &0 as &dyn std::any::Any; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/issues/issue-22312.rs b/tests/ui/issues/issue-22312.rs new file mode 100644 index 000000000..4e359b341 --- /dev/null +++ b/tests/ui/issues/issue-22312.rs @@ -0,0 +1,17 @@ +use std::ops::Index; + +pub trait Array2D: Index + Sized { + fn rows(&self) -> usize; + fn columns(&self) -> usize; + fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a >::Output> { + if y >= self.rows() || x >= self.columns() { + return None; + } + let i = y * self.columns() + x; + let indexer = &(*self as &dyn Index>::Output>); + //~^ERROR non-primitive cast + Some(indexer.index(i)) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-22312.stderr b/tests/ui/issues/issue-22312.stderr new file mode 100644 index 000000000..da15c092f --- /dev/null +++ b/tests/ui/issues/issue-22312.stderr @@ -0,0 +1,14 @@ +error[E0605]: non-primitive cast: `Self` as `&dyn Index>::Output>` + --> $DIR/issue-22312.rs:11:24 + | +LL | let indexer = &(*self as &dyn Index>::Output>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let indexer = &(&*self as &dyn Index>::Output>); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/issues/issue-22346.rs b/tests/ui/issues/issue-22346.rs new file mode 100644 index 000000000..5f6d9dcc9 --- /dev/null +++ b/tests/ui/issues/issue-22346.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +// This used to cause an ICE because the retslot for the "return" had the wrong type +fn testcase<'a>() -> Box + 'a> { + return Box::new((0..3).map(|i| { return i; })); +} + +fn main() { +} diff --git a/tests/ui/issues/issue-22356.rs b/tests/ui/issues/issue-22356.rs new file mode 100644 index 000000000..47fad3bb9 --- /dev/null +++ b/tests/ui/issues/issue-22356.rs @@ -0,0 +1,34 @@ +// check-pass +#![allow(type_alias_bounds)] + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomData; + +pub struct Handle(T, I); + +impl Handle { + pub fn get_info(&self) -> &I { + let Handle(_, ref info) = *self; + info + } +} + +pub struct BufferHandle { + raw: RawBufferHandle, + _marker: PhantomData, +} + +impl BufferHandle { + pub fn get_info(&self) -> &String { + self.raw.get_info() + } +} + +pub type RawBufferHandle = Handle<::Buffer, String>; + +pub trait Device { + type Buffer; +} + +fn main() {} diff --git a/tests/ui/issues/issue-22370.rs b/tests/ui/issues/issue-22370.rs new file mode 100644 index 000000000..bab0469c0 --- /dev/null +++ b/tests/ui/issues/issue-22370.rs @@ -0,0 +1,6 @@ +trait A {} + +fn f(a: &dyn A) {} +//~^ ERROR E0393 + +fn main() {} diff --git a/tests/ui/issues/issue-22370.stderr b/tests/ui/issues/issue-22370.stderr new file mode 100644 index 000000000..cd27c4e4e --- /dev/null +++ b/tests/ui/issues/issue-22370.stderr @@ -0,0 +1,14 @@ +error[E0393]: the type parameter `T` must be explicitly specified + --> $DIR/issue-22370.rs:3:14 + | +LL | trait A {} + | --------------- type parameter `T` must be specified for this +LL | +LL | fn f(a: &dyn A) {} + | ^ help: set the type parameter to the desired type: `A` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/issues/issue-22384.rs b/tests/ui/issues/issue-22384.rs new file mode 100644 index 000000000..98988f27e --- /dev/null +++ b/tests/ui/issues/issue-22384.rs @@ -0,0 +1,8 @@ +trait Trait { + fn foo(); +} + +fn main() { + <::foobar as Trait>::foo(); + //~^ ERROR cannot find associated type `foobar` in trait `Copy` +} diff --git a/tests/ui/issues/issue-22384.stderr b/tests/ui/issues/issue-22384.stderr new file mode 100644 index 000000000..1f767a443 --- /dev/null +++ b/tests/ui/issues/issue-22384.stderr @@ -0,0 +1,9 @@ +error[E0576]: cannot find associated type `foobar` in trait `Copy` + --> $DIR/issue-22384.rs:6:21 + | +LL | <::foobar as Trait>::foo(); + | ^^^^^^ not found in `Copy` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0576`. diff --git a/tests/ui/issues/issue-22403.rs b/tests/ui/issues/issue-22403.rs new file mode 100644 index 000000000..8d8559094 --- /dev/null +++ b/tests/ui/issues/issue-22403.rs @@ -0,0 +1,6 @@ +// run-pass +fn main() { + let x = Box::new([1, 2, 3]); + let y = x as Box<[i32]>; + println!("y: {:?}", y); +} diff --git a/tests/ui/issues/issue-22426.rs b/tests/ui/issues/issue-22426.rs new file mode 100644 index 000000000..adf060a82 --- /dev/null +++ b/tests/ui/issues/issue-22426.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + match 42 { + x if x < 7 => (), + _ => () + } +} diff --git a/tests/ui/issues/issue-22434.rs b/tests/ui/issues/issue-22434.rs new file mode 100644 index 000000000..34057b46e --- /dev/null +++ b/tests/ui/issues/issue-22434.rs @@ -0,0 +1,8 @@ +pub trait Foo { + type A; +} + +type I<'a> = &'a (dyn Foo + 'a); +//~^ ERROR the value of the associated type `A` (from trait `Foo`) must be specified + +fn main() {} diff --git a/tests/ui/issues/issue-22434.stderr b/tests/ui/issues/issue-22434.stderr new file mode 100644 index 000000000..b97fa2503 --- /dev/null +++ b/tests/ui/issues/issue-22434.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `A` (from trait `Foo`) must be specified + --> $DIR/issue-22434.rs:5:23 + | +LL | type A; + | ------ `A` defined here +... +LL | type I<'a> = &'a (dyn Foo + 'a); + | ^^^ help: specify the associated type: `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-22468.rs b/tests/ui/issues/issue-22468.rs new file mode 100644 index 000000000..197a19c03 --- /dev/null +++ b/tests/ui/issues/issue-22468.rs @@ -0,0 +1,9 @@ +fn main() { + let foo = "bar"; + let x = foo("baz"); + //~^ ERROR: expected function, found `&str` +} + +fn foo(file: &str) -> bool { + true +} diff --git a/tests/ui/issues/issue-22468.stderr b/tests/ui/issues/issue-22468.stderr new file mode 100644 index 000000000..3fff91acb --- /dev/null +++ b/tests/ui/issues/issue-22468.stderr @@ -0,0 +1,13 @@ +error[E0618]: expected function, found `&str` + --> $DIR/issue-22468.rs:3:13 + | +LL | let foo = "bar"; + | --- `foo` has type `&str` +LL | let x = foo("baz"); + | ^^^------- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-22471.rs b/tests/ui/issues/issue-22471.rs new file mode 100644 index 000000000..69879ab7f --- /dev/null +++ b/tests/ui/issues/issue-22471.rs @@ -0,0 +1,7 @@ +// check-pass +#![allow(dead_code)] +#![allow(type_alias_bounds)] + +type Foo where T: Copy = Box; + +fn main(){} diff --git a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs b/tests/ui/issues/issue-22536-copy-mustnt-zero.rs new file mode 100644 index 000000000..017f36484 --- /dev/null +++ b/tests/ui/issues/issue-22536-copy-mustnt-zero.rs @@ -0,0 +1,28 @@ +// run-pass +// Regression test for Issue #22536: If a type implements Copy, then +// moving it must not zero the original memory. + + +trait Resources { + type Buffer: Copy; + fn foo(&self) {} +} + +struct BufferHandle { + raw: ::Buffer, +} +impl Copy for BufferHandle {} +impl Clone for BufferHandle { + fn clone(&self) -> BufferHandle { *self } +} + +enum Res {} +impl Resources for Res { + type Buffer = u32; +} + +fn main() { + let b: BufferHandle = BufferHandle { raw: 1 }; + let c = b; + assert_eq!(c.raw, b.raw) +} diff --git a/tests/ui/issues/issue-22577.rs b/tests/ui/issues/issue-22577.rs new file mode 100644 index 000000000..8aca21bf1 --- /dev/null +++ b/tests/ui/issues/issue-22577.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::{fs, net}; + +fn assert_both() {} +fn assert_send() {} + +fn main() { + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); +} diff --git a/tests/ui/issues/issue-22599.rs b/tests/ui/issues/issue-22599.rs new file mode 100644 index 000000000..05096e5c1 --- /dev/null +++ b/tests/ui/issues/issue-22599.rs @@ -0,0 +1,10 @@ +#![deny(unused_variables)] + +fn f(_: i32) {} + +fn main() { + let mut v = 0; + f(v); + v = match 0 { a => 0 }; //~ ERROR: unused variable: `a` + f(v); +} diff --git a/tests/ui/issues/issue-22599.stderr b/tests/ui/issues/issue-22599.stderr new file mode 100644 index 000000000..2b34830d0 --- /dev/null +++ b/tests/ui/issues/issue-22599.stderr @@ -0,0 +1,14 @@ +error: unused variable: `a` + --> $DIR/issue-22599.rs:8:19 + | +LL | v = match 0 { a => 0 }; + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/issue-22599.rs:1:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-22603.rs b/tests/ui/issues/issue-22603.rs new file mode 100644 index 000000000..a83e291f9 --- /dev/null +++ b/tests/ui/issues/issue-22603.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(unboxed_closures, fn_traits)] + +struct Foo; + +impl FnOnce<(A,)> for Foo { + type Output = (); + extern "rust-call" fn call_once(self, (_,): (A,)) { + } +} + +fn main() { + println!("{:?}", Foo("bar")); +} diff --git a/tests/ui/issues/issue-22629.rs b/tests/ui/issues/issue-22629.rs new file mode 100644 index 000000000..7beeb126e --- /dev/null +++ b/tests/ui/issues/issue-22629.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_imports)] +// Test transitive analysis for associated types. Collected types +// should be normalized and new obligations generated. + +// pretty-expanded FIXME #23616 + +use std::borrow::{ToOwned, Cow}; + +fn assert_send(_: T) {} + +fn main() { + assert_send(Cow::Borrowed("foo")); +} diff --git a/tests/ui/issues/issue-22638.polonius.stderr b/tests/ui/issues/issue-22638.polonius.stderr new file mode 100644 index 000000000..87a7c00e4 --- /dev/null +++ b/tests/ui/issues/issue-22638.polonius.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `A::matches::$CLOSURE` + --> $DIR/issue-22638.rs:56:9 + | +LL | a.matches(f) + | ^^^^^^^^^^^^ + | +note: `A::matches` defined here + --> $DIR/issue-22638.rs:15:5 + | +LL | pub fn matches(&self, f: &F) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-22638.polonius/issue-22638.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-22638.rs b/tests/ui/issues/issue-22638.rs new file mode 100644 index 000000000..198ceccc2 --- /dev/null +++ b/tests/ui/issues/issue-22638.rs @@ -0,0 +1,63 @@ +// build-fail +// normalize-stderr-test: "<\[closure@.+`" -> "$$CLOSURE`" +// normalize-stderr-test: ".nll/" -> "/" + +#![allow(unused)] + +#![recursion_limit = "20"] +#![type_length_limit = "20000000"] +#![crate_type = "rlib"] + +#[derive(Clone)] +struct A (B); + +impl A { + pub fn matches(&self, f: &F) { + let &A(ref term) = self; + term.matches(f); + } +} + +#[derive(Clone)] +enum B { + Variant1, + Variant2(C), +} + +impl B { + pub fn matches(&self, f: &F) { + match self { + &B::Variant2(ref factor) => { + factor.matches(&|| ()) + } + _ => unreachable!("") + } + } +} + +#[derive(Clone)] +struct C (D); + +impl C { + pub fn matches(&self, f: &F) { + let &C(ref base) = self; + base.matches(&|| { + C(base.clone()).matches(f) + }) + } +} + +#[derive(Clone)] +struct D (Box); + +impl D { + pub fn matches(&self, f: &F) { + let &D(ref a) = self; + a.matches(f) + //~^ ERROR reached the recursion limit while instantiating `A::matches::<[closure + } +} + +pub fn matches() { + A(B::Variant1).matches(&(|| ())) +} diff --git a/tests/ui/issues/issue-22638.stderr b/tests/ui/issues/issue-22638.stderr new file mode 100644 index 000000000..1caa4221f --- /dev/null +++ b/tests/ui/issues/issue-22638.stderr @@ -0,0 +1,14 @@ +error: reached the recursion limit while instantiating `A::matches::$CLOSURE` + --> $DIR/issue-22638.rs:56:9 + | +LL | a.matches(f) + | ^^^^^^^^^^^^ + | +note: `A::matches` defined here + --> $DIR/issue-22638.rs:15:5 + | +LL | pub fn matches(&self, f: &F) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-22644.rs b/tests/ui/issues/issue-22644.rs new file mode 100644 index 000000000..b1d69dcd8 --- /dev/null +++ b/tests/ui/issues/issue-22644.rs @@ -0,0 +1,35 @@ +#![feature(type_ascription)] + +fn main() { + let a : usize = 0; + let long_name : usize = 0; + + println!("{}", a as usize > long_name); + println!("{}", a as usize < long_name); //~ ERROR `<` is interpreted as a start of generic + println!("{}{}", a as usize < long_name, long_name); + //~^ ERROR `<` is interpreted as a start of generic + println!("{}", a as usize < 4); //~ ERROR `<` is interpreted as a start of generic + println!("{}", a: usize > long_name); + println!("{}{}", a: usize < long_name, long_name); + //~^ ERROR `<` is interpreted as a start of generic + println!("{}", a: usize < 4); //~ ERROR `<` is interpreted as a start of generic + + println!("{}", a + as + usize + < //~ ERROR `<` is interpreted as a start of generic + 4); + println!("{}", a + + + as + + + usize + < //~ ERROR `<` is interpreted as a start of generic + 5); + + println!("{}", a as usize << long_name); //~ ERROR `<<` is interpreted as a start of generic + + println!("{}", a: &mut 4); //~ ERROR expected type, found `4` +} diff --git a/tests/ui/issues/issue-22644.stderr b/tests/ui/issues/issue-22644.stderr new file mode 100644 index 000000000..45027afa7 --- /dev/null +++ b/tests/ui/issues/issue-22644.stderr @@ -0,0 +1,123 @@ +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:8:31 + | +LL | println!("{}", a as usize < long_name); + | ^ --------- interpreted as generic arguments + | | + | not interpreted as comparison + | +help: try comparing the cast value + | +LL | println!("{}", (a as usize) < long_name); + | + + + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:9:33 + | +LL | println!("{}{}", a as usize < long_name, long_name); + | ^ -------------------- interpreted as generic arguments + | | + | not interpreted as comparison + | +help: try comparing the cast value + | +LL | println!("{}{}", (a as usize) < long_name, long_name); + | + + + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:11:31 + | +LL | println!("{}", a as usize < 4); + | ^ - interpreted as generic arguments + | | + | not interpreted as comparison + | +help: try comparing the cast value + | +LL | println!("{}", (a as usize) < 4); + | + + + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:13:31 + | +LL | println!("{}{}", a: usize < long_name, long_name); + | ^ -------------------- interpreted as generic arguments + | | + | not interpreted as comparison + | +help: try comparing the cast value + | +LL | println!("{}{}", (a: usize) < long_name, long_name); + | + + + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:15:29 + | +LL | println!("{}", a: usize < 4); + | ^ - interpreted as generic arguments + | | + | not interpreted as comparison + | +help: try comparing the cast value + | +LL | println!("{}", (a: usize) < 4); + | + + + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:20:20 + | +LL | < + | ^ not interpreted as comparison +LL | 4); + | - interpreted as generic arguments + | +help: try comparing the cast value + | +LL ~ println!("{}", (a +LL | as +LL ~ usize) + | + +error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison + --> $DIR/issue-22644.rs:29:20 + | +LL | < + | ^ not interpreted as comparison +LL | 5); + | - interpreted as generic arguments + | +help: try comparing the cast value + | +LL ~ println!("{}", (a +LL | + ... +LL | +LL ~ usize) + | + +error: `<<` is interpreted as a start of generic arguments for `usize`, not a shift + --> $DIR/issue-22644.rs:32:31 + | +LL | println!("{}", a as usize << long_name); + | ^^ --------- interpreted as generic arguments + | | + | not interpreted as shift + | +help: try shifting the cast value + | +LL | println!("{}", (a as usize) << long_name); + | + + + +error: expected type, found `4` + --> $DIR/issue-22644.rs:34:28 + | +LL | println!("{}", a: &mut 4); + | - ^ expected type + | | + | tried to parse a type due to this type ascription + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: see issue #23416 for more information + +error: aborting due to 9 previous errors + diff --git a/tests/ui/issues/issue-22673.rs b/tests/ui/issues/issue-22673.rs new file mode 100644 index 000000000..4b9b4d6b2 --- /dev/null +++ b/tests/ui/issues/issue-22673.rs @@ -0,0 +1,7 @@ +// check-pass + +trait Expr: PartialEq { + type Item; +} + +fn main() {} diff --git a/tests/ui/issues/issue-22684.rs b/tests/ui/issues/issue-22684.rs new file mode 100644 index 000000000..a5b042706 --- /dev/null +++ b/tests/ui/issues/issue-22684.rs @@ -0,0 +1,18 @@ +mod foo { + pub struct Foo; + impl Foo { + fn bar(&self) {} + } + + pub trait Baz { + fn bar(&self) -> bool { true } + } + impl Baz for Foo {} +} + +fn main() { + use foo::Baz; + + // Check that `bar` resolves to the trait method, not the inherent impl method. + let _: () = foo::Foo.bar(); //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-22684.stderr b/tests/ui/issues/issue-22684.stderr new file mode 100644 index 000000000..2407ece5e --- /dev/null +++ b/tests/ui/issues/issue-22684.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-22684.rs:17:17 + | +LL | let _: () = foo::Foo.bar(); + | -- ^^^^^^^^^^^^^^ expected `()`, found `bool` + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-22706.rs b/tests/ui/issues/issue-22706.rs new file mode 100644 index 000000000..bb8a58d3d --- /dev/null +++ b/tests/ui/issues/issue-22706.rs @@ -0,0 +1,3 @@ +fn is_copy::Copy>() {} +//~^ ERROR type arguments are not allowed on module `marker` [E0109] +fn main() {} diff --git a/tests/ui/issues/issue-22706.stderr b/tests/ui/issues/issue-22706.stderr new file mode 100644 index 000000000..5366a36b1 --- /dev/null +++ b/tests/ui/issues/issue-22706.stderr @@ -0,0 +1,11 @@ +error[E0109]: type arguments are not allowed on module `marker` + --> $DIR/issue-22706.rs:1:29 + | +LL | fn is_copy::Copy>() {} + | ------ ^^^ type argument not allowed + | | + | not allowed on module `marker` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/issues/issue-22777.rs b/tests/ui/issues/issue-22777.rs new file mode 100644 index 000000000..486683d12 --- /dev/null +++ b/tests/ui/issues/issue-22777.rs @@ -0,0 +1,48 @@ +// check-pass +// This test is reduced from librustc_ast. It is just checking that we +// can successfully deal with a "deep" structure, which the drop-check +// was hitting a recursion limit on at one point. + +// pretty-expanded FIXME #23616 + +#![allow(non_camel_case_types)] + +pub fn noop_fold_impl_item() -> SmallVector { + loop { } +} + +pub struct SmallVector(P); +pub struct ImplItem(P); + +struct P(Box); + +struct S01_Method(P); +struct S02_Generics(P); +struct S03_TyParam(P); +struct S04_TyParamBound(S05_PolyTraitRef); +struct S05_PolyTraitRef(S06_TraitRef); +struct S06_TraitRef(S07_Path); +struct S07_Path(Vec); +struct S08_PathSegment(S09_GenericArgs); +struct S09_GenericArgs(P); +struct S10_ParenthesizedParameterData(Option>); +struct S11_Ty(P); +struct S12_Expr(P); +struct S13_Block(Vec>); +struct S14_Stmt(P); +struct S15_Decl(P); +struct S16_Local(P); +struct S17_Pat(P); +struct S18_Mac(Vec>); +struct S19_TokenTree(P); +struct S20_Token(P); +struct S21_Nonterminal(P); +struct S22_Item(P); +struct S23_EnumDef(Vec>); +struct S24_Variant(P); +struct S25_VariantKind(P); +struct S26_StructDef(Vec>); +struct S27_StructField(P); +struct S28_StructFieldKind; + +pub fn main() {} diff --git a/tests/ui/issues/issue-22781.rs b/tests/ui/issues/issue-22781.rs new file mode 100644 index 000000000..d644cec4d --- /dev/null +++ b/tests/ui/issues/issue-22781.rs @@ -0,0 +1,15 @@ +// check-pass +#![allow(unused_variables)] +use std::collections::HashMap; +use std::collections::hash_map::Entry::Vacant; + +pub fn foo() { + type F = Box; + let mut map: HashMap<(), F> = HashMap::new(); + let x: &mut F = match map.entry(()) { + Vacant(_) => unimplemented!(), + _ => unimplemented!() + }; +} + +fn main() {} diff --git a/tests/ui/issues/issue-22789.rs b/tests/ui/issues/issue-22789.rs new file mode 100644 index 000000000..cef407537 --- /dev/null +++ b/tests/ui/issues/issue-22789.rs @@ -0,0 +1,8 @@ +// check-pass + +#![feature(unboxed_closures, fn_traits)] + +fn main() { + let k = |x: i32| { x + 1 }; + Fn::call(&k, (0,)); +} diff --git a/tests/ui/issues/issue-2281-part1.rs b/tests/ui/issues/issue-2281-part1.rs new file mode 100644 index 000000000..8340ade22 --- /dev/null +++ b/tests/ui/issues/issue-2281-part1.rs @@ -0,0 +1 @@ +fn main() { println!("{}", foobar); } //~ ERROR cannot find value `foobar` in this scope diff --git a/tests/ui/issues/issue-2281-part1.stderr b/tests/ui/issues/issue-2281-part1.stderr new file mode 100644 index 000000000..c2391a7c0 --- /dev/null +++ b/tests/ui/issues/issue-2281-part1.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `foobar` in this scope + --> $DIR/issue-2281-part1.rs:1:28 + | +LL | fn main() { println!("{}", foobar); } + | ^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-22814.rs b/tests/ui/issues/issue-22814.rs new file mode 100644 index 000000000..4079adfc8 --- /dev/null +++ b/tests/ui/issues/issue-22814.rs @@ -0,0 +1,13 @@ +// check-pass +trait Test {} + +macro_rules! test { +( $($name:ident)+) => ( + impl<$($name: Test),+> Test for ($($name,)+) { + } +) +} + +test!(A B C); + +fn main() {} diff --git a/tests/ui/issues/issue-2284.rs b/tests/ui/issues/issue-2284.rs new file mode 100644 index 000000000..6f2c95834 --- /dev/null +++ b/tests/ui/issues/issue-2284.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait Send { + fn f(&self); +} + +fn f(t: T) { + t.f(); +} + +pub fn main() { +} diff --git a/tests/ui/issues/issue-22864-1.rs b/tests/ui/issues/issue-22864-1.rs new file mode 100644 index 000000000..0fad5433d --- /dev/null +++ b/tests/ui/issues/issue-22864-1.rs @@ -0,0 +1,7 @@ +// run-pass +pub fn main() { + struct Fun(F); + let f = Fun(|x| 3*x); + let Fun(g) = f; + println!("{:?}",g(4)); +} diff --git a/tests/ui/issues/issue-22864-2.rs b/tests/ui/issues/issue-22864-2.rs new file mode 100644 index 000000000..4aa9e3e08 --- /dev/null +++ b/tests/ui/issues/issue-22864-2.rs @@ -0,0 +1,7 @@ +// run-pass +// ignore-emscripten no threads support + +pub fn main() { + let f = || || 0; + std::thread::spawn(f()); +} diff --git a/tests/ui/issues/issue-22872.rs b/tests/ui/issues/issue-22872.rs new file mode 100644 index 000000000..5db2891e6 --- /dev/null +++ b/tests/ui/issues/issue-22872.rs @@ -0,0 +1,24 @@ +trait Wrap<'b> { + fn foo(&'b mut self); +} + +struct Wrapper

(P); + +impl<'b, P> Wrap<'b> for Wrapper

+where P: Process<'b>, +

>::Item: Iterator { + fn foo(&mut self) {} +} + + +pub trait Process<'a> { + type Item; + fn bar(&'a self); +} + +fn push_process

(process: P) where P: Process<'static> { + let _: Box Wrap<'b>> = Box::new(Wrapper(process)); +//~^ ERROR is not an iterator +} + +fn main() {} diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/issues/issue-22872.stderr new file mode 100644 index 000000000..951019719 --- /dev/null +++ b/tests/ui/issues/issue-22872.stderr @@ -0,0 +1,24 @@ +error[E0277]: `

>::Item` is not an iterator + --> $DIR/issue-22872.rs:20:40 + | +LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator + | + = help: the trait `Iterator` is not implemented for `

>::Item` +note: required for `Wrapper

` to implement `for<'b> Wrap<'b>` + --> $DIR/issue-22872.rs:7:13 + | +LL | impl<'b, P> Wrap<'b> for Wrapper

+ | ^^^^^^^^ ^^^^^^^^^^ +LL | where P: Process<'b>, +LL |

>::Item: Iterator { + | -------- unsatisfied trait bound introduced here + = note: required for the cast from `Wrapper

` to the object type `dyn for<'b> Wrap<'b>` +help: consider further restricting the associated type + | +LL | fn push_process

(process: P) where P: Process<'static>,

>::Item: Iterator { + | ++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-22874.rs b/tests/ui/issues/issue-22874.rs new file mode 100644 index 000000000..37c6c8143 --- /dev/null +++ b/tests/ui/issues/issue-22874.rs @@ -0,0 +1,10 @@ +struct Table { + rows: [[String]], + //~^ ERROR the size for values of type +} + +fn f(table: &Table) -> &[String] { + &table.rows[0] +} + +fn main() {} diff --git a/tests/ui/issues/issue-22874.stderr b/tests/ui/issues/issue-22874.stderr new file mode 100644 index 000000000..d64899080 --- /dev/null +++ b/tests/ui/issues/issue-22874.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[String]` cannot be known at compilation time + --> $DIR/issue-22874.rs:2:11 + | +LL | rows: [[String]], + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[String]` + = note: slice and array elements must have `Sized` type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-2288.rs b/tests/ui/issues/issue-2288.rs new file mode 100644 index 000000000..6fd690a4d --- /dev/null +++ b/tests/ui/issues/issue-2288.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait clam { + fn chowder(&self, y: A); +} + +#[derive(Copy, Clone)] +struct foo { + x: A, +} + +impl clam for foo { + fn chowder(&self, _y: A) { + } +} + +fn foo(b: A) -> foo { + foo { + x: b + } +} + +fn f(x: Box>, a: A) { + x.chowder(a); +} + +pub fn main() { + + let c = foo(42); + let d: Box> = Box::new(c) as Box>; + f(d, c.x); +} diff --git a/tests/ui/issues/issue-22886.rs b/tests/ui/issues/issue-22886.rs new file mode 100644 index 000000000..f8b576e09 --- /dev/null +++ b/tests/ui/issues/issue-22886.rs @@ -0,0 +1,21 @@ +// Regression test for #22886. + +fn crash_please() { + let mut iter = Newtype(Some(Box::new(0))); + let saved = iter.next().unwrap(); + println!("{}", saved); + iter.0 = None; + println!("{}", saved); +} + +struct Newtype(Option>); + +impl<'a> Iterator for Newtype { //~ ERROR E0207 + type Item = &'a Box; + + fn next(&mut self) -> Option<&Box> { + self.0.as_ref() + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-22886.stderr b/tests/ui/issues/issue-22886.stderr new file mode 100644 index 000000000..c4b396559 --- /dev/null +++ b/tests/ui/issues/issue-22886.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-22886.rs:13:6 + | +LL | impl<'a> Iterator for Newtype { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-22894.rs b/tests/ui/issues/issue-22894.rs new file mode 100644 index 000000000..93c1db914 --- /dev/null +++ b/tests/ui/issues/issue-22894.rs @@ -0,0 +1,4 @@ +// build-pass +#[allow(dead_code)] +static X: &'static str = &*""; +fn main() {} diff --git a/tests/ui/issues/issue-22933-1.rs b/tests/ui/issues/issue-22933-1.rs new file mode 100644 index 000000000..3c9aa2669 --- /dev/null +++ b/tests/ui/issues/issue-22933-1.rs @@ -0,0 +1,23 @@ +// check-pass + +struct CNFParser { + token: char, +} + +impl CNFParser { + fn is_whitespace(c: char) -> bool { + c == ' ' || c == '\n' + } + + fn consume_whitespace(&mut self) { + self.consume_while(&(CNFParser::is_whitespace)) + } + + fn consume_while(&mut self, p: &dyn Fn(char) -> bool) { + while p(self.token) { + return + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-22933-2.rs b/tests/ui/issues/issue-22933-2.rs new file mode 100644 index 000000000..dfd84b9a7 --- /dev/null +++ b/tests/ui/issues/issue-22933-2.rs @@ -0,0 +1,8 @@ +enum Delicious { + Pie = 0x1, + Apple = 0x2, + ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, + //~^ ERROR no variant or associated item named `PIE` found +} + +fn main() {} diff --git a/tests/ui/issues/issue-22933-2.stderr b/tests/ui/issues/issue-22933-2.stderr new file mode 100644 index 000000000..1a0e87e15 --- /dev/null +++ b/tests/ui/issues/issue-22933-2.stderr @@ -0,0 +1,15 @@ +error[E0599]: no variant or associated item named `PIE` found for enum `Delicious` in the current scope + --> $DIR/issue-22933-2.rs:4:55 + | +LL | enum Delicious { + | -------------- variant or associated item `PIE` not found for this enum +... +LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, + | ^^^ + | | + | variant or associated item not found in `Delicious` + | help: there is a variant with a similar name: `Pie` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-22992-2.rs b/tests/ui/issues/issue-22992-2.rs new file mode 100644 index 000000000..042af40ed --- /dev/null +++ b/tests/ui/issues/issue-22992-2.rs @@ -0,0 +1,18 @@ +// run-pass +struct A(B); +struct B; + +use std::ops::Deref; + +impl Deref for A { + type Target = B; + fn deref(&self) -> &B { &self.0 } +} + +impl B { + fn foo(&self) {} +} + +fn main() { + A(B).foo(); +} diff --git a/tests/ui/issues/issue-22992.rs b/tests/ui/issues/issue-22992.rs new file mode 100644 index 000000000..292a0ae29 --- /dev/null +++ b/tests/ui/issues/issue-22992.rs @@ -0,0 +1,75 @@ +// run-pass + +struct X { val: i32 } +impl std::ops::Deref for X { + type Target = i32; + fn deref(&self) -> &i32 { &self.val } +} + + +trait M { fn m(self); } +impl M for i32 { fn m(self) { println!("i32::m()"); } } +impl M for X { fn m(self) { println!("X::m()"); } } +impl<'a> M for &'a X { fn m(self) { println!("&X::m()"); } } +impl<'a, 'b> M for &'a &'b X { fn m(self) { println!("&&X::m()"); } } +impl<'a, 'b, 'c> M for &'a &'b &'c X { fn m(self) { println!("&&&X::m()"); } } + +trait RefM { fn refm(&self); } +impl RefM for i32 { fn refm(&self) { println!("i32::refm()"); } } +impl RefM for X { fn refm(&self) { println!("X::refm()"); } } +impl<'a> RefM for &'a X { fn refm(&self) { println!("&X::refm()"); } } +impl<'a, 'b> RefM for &'a &'b X { fn refm(&self) { println!("&&X::refm()"); } } +impl<'a, 'b, 'c> RefM for &'a &'b &'c X { fn refm(&self) { println!("&&&X::refm()"); } } + +struct Y { val: i32 } +impl std::ops::Deref for Y { + type Target = i32; + fn deref(&self) -> &i32 { &self.val } +} + +struct Z { val: Y } +impl std::ops::Deref for Z { + type Target = Y; + fn deref(&self) -> &Y { &self.val } +} + +struct A; +impl std::marker::Copy for A {} +impl Clone for A { fn clone(&self) -> Self { *self } } +impl M for A { fn m(self) { println!("A::m()"); } } +impl<'a, 'b, 'c> M for &'a &'b &'c A { fn m(self) { println!("&&&A::m()"); } } +impl RefM for A { fn refm(&self) { println!("A::refm()"); } } +impl<'a, 'b, 'c> RefM for &'a &'b &'c A { fn refm(&self) { println!("&&&A::refm()"); } } + +fn main() { + // I'll use @ to denote left side of the dot operator + (*X{val:42}).m(); // i32::refm() , self == @ + X{val:42}.m(); // X::m() , self == @ + (&X{val:42}).m(); // &X::m() , self == @ + (&&X{val:42}).m(); // &&X::m() , self == @ + (&&&X{val:42}).m(); // &&&X:m() , self == @ + (&&&&X{val:42}).m(); // &&&X::m() , self == *@ + (&&&&&X{val:42}).m(); // &&&X::m() , self == **@ + + (*X{val:42}).refm(); // i32::refm() , self == @ + X{val:42}.refm(); // X::refm() , self == @ + (&X{val:42}).refm(); // X::refm() , self == *@ + (&&X{val:42}).refm(); // &X::refm() , self == *@ + (&&&X{val:42}).refm(); // &&X::refm() , self == *@ + (&&&&X{val:42}).refm(); // &&&X::refm(), self == *@ + (&&&&&X{val:42}).refm(); // &&&X::refm(), self == **@ + + Y{val:42}.refm(); // i32::refm() , self == *@ + Z{val:Y{val:42}}.refm(); // i32::refm() , self == **@ + + A.m(); // A::m() , self == @ + // without the Copy trait, (&A).m() would be a compilation error: + // cannot move out of borrowed content + (&A).m(); // A::m() , self == *@ + (&&A).m(); // &&&A::m() , self == &@ + (&&&A).m(); // &&&A::m() , self == @ + A.refm(); // A::refm() , self == @ + (&A).refm(); // A::refm() , self == *@ + (&&A).refm(); // A::refm() , self == **@ + (&&&A).refm(); // &&&A::refm(), self == @ +} diff --git a/tests/ui/issues/issue-23024.rs b/tests/ui/issues/issue-23024.rs new file mode 100644 index 000000000..010281ee3 --- /dev/null +++ b/tests/ui/issues/issue-23024.rs @@ -0,0 +1,12 @@ +use std::any::Any; + +fn main() +{ + fn h(x:i32) -> i32 {3*x} + let mut vfnfer:Vec> = vec![]; + vfnfer.push(Box::new(h)); + println!("{:?}",(vfnfer[0] as dyn Fn)(3)); + //~^ ERROR the precise format of `Fn`-family traits' + //~| ERROR missing generics for trait `Fn` + //~| ERROR the value of the associated type `Output` (from trait `FnOnce`) +} diff --git a/tests/ui/issues/issue-23024.stderr b/tests/ui/issues/issue-23024.stderr new file mode 100644 index 000000000..2c325ffcc --- /dev/null +++ b/tests/ui/issues/issue-23024.stderr @@ -0,0 +1,30 @@ +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/issue-23024.rs:8:39 + | +LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); + | ^^ help: use parenthetical notation instead: `Fn() -> ()` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0107]: missing generics for trait `Fn` + --> $DIR/issue-23024.rs:8:39 + | +LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); + | ^^ expected 1 generic argument + | +help: add missing generic argument + | +LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); + | ++++++ + +error[E0191]: the value of the associated type `Output` (from trait `FnOnce`) must be specified + --> $DIR/issue-23024.rs:8:39 + | +LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); + | ^^ help: specify the associated type: `Fn` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0191, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-23036.rs b/tests/ui/issues/issue-23036.rs new file mode 100644 index 000000000..d67f18472 --- /dev/null +++ b/tests/ui/issues/issue-23036.rs @@ -0,0 +1,10 @@ +// run-pass + +use std::collections::HashMap; +use std::path::Path; + +fn main() { + let mut map = HashMap::new(); + map.insert(Path::new("a"), 0); + map.get(Path::new("a")); +} diff --git a/tests/ui/issues/issue-23041.rs b/tests/ui/issues/issue-23041.rs new file mode 100644 index 000000000..a1371521a --- /dev/null +++ b/tests/ui/issues/issue-23041.rs @@ -0,0 +1,7 @@ +use std::any::Any; +fn main() +{ + fn bar(x:i32) ->i32 { 3*x }; + let b:Box = Box::new(bar as fn(_)->_); + b.downcast_ref::_>(); //~ ERROR E0282 +} diff --git a/tests/ui/issues/issue-23041.stderr b/tests/ui/issues/issue-23041.stderr new file mode 100644 index 000000000..6592b76a3 --- /dev/null +++ b/tests/ui/issues/issue-23041.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-23041.rs:6:7 + | +LL | b.downcast_ref::_>(); + | ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref` + | +help: consider specifying the generic argument + | +LL | b.downcast_ref:: _>(); + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-23046.rs b/tests/ui/issues/issue-23046.rs new file mode 100644 index 000000000..a68369616 --- /dev/null +++ b/tests/ui/issues/issue-23046.rs @@ -0,0 +1,20 @@ +pub enum Expr<'var, VAR> { + Let(Box>, + Box Fn(Expr<'v, VAR>) -> Expr<'v, VAR> + 'var>) +} + +pub fn add<'var, VAR> + (a: Expr<'var, VAR>, b: Expr<'var, VAR>) -> Expr<'var, VAR> { + loop {} +} + +pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> + (a: Expr<'var, VAR>, b: F) -> Expr<'var, VAR> { + loop {} +} + +fn main() { + let ex = |x| { //~ ERROR type annotations needed + let_(add(x,x), |y| { + let_(add(x, x), |x|x)})}; +} diff --git a/tests/ui/issues/issue-23046.stderr b/tests/ui/issues/issue-23046.stderr new file mode 100644 index 000000000..1403ecbd9 --- /dev/null +++ b/tests/ui/issues/issue-23046.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Expr<'_, VAR>` + --> $DIR/issue-23046.rs:17:15 + | +LL | let ex = |x| { + | ^ + | +help: consider giving this closure parameter an explicit type, where the type for type parameter `VAR` is specified + | +LL | let ex = |x: Expr<'_, VAR>| { + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-23073.rs b/tests/ui/issues/issue-23073.rs new file mode 100644 index 000000000..a0ca91336 --- /dev/null +++ b/tests/ui/issues/issue-23073.rs @@ -0,0 +1,9 @@ +#![feature(associated_type_defaults)] + +trait Foo { type T; } +trait Bar { + type Foo: Foo; + type FooT = <::Foo>::T; //~ ERROR ambiguous associated type +} + +fn main() {} diff --git a/tests/ui/issues/issue-23073.stderr b/tests/ui/issues/issue-23073.stderr new file mode 100644 index 000000000..3a9f49ef1 --- /dev/null +++ b/tests/ui/issues/issue-23073.stderr @@ -0,0 +1,14 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-23073.rs:6:17 + | +LL | type FooT = <::Foo>::T; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `T` implemented for `::Foo`, you could use the fully-qualified path + | +LL | type FooT = <::Foo as Example>::T; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/issues/issue-2311-2.rs b/tests/ui/issues/issue-2311-2.rs new file mode 100644 index 000000000..760d4edaa --- /dev/null +++ b/tests/ui/issues/issue-2311-2.rs @@ -0,0 +1,26 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +trait clam { + fn get(self) -> A; +} + +struct foo { + x: A, +} + +impl foo { + pub fn bar>(&self, _c: C) -> B { + panic!(); + } +} + +fn foo(b: A) -> foo { + foo { + x: b + } +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-2311.rs b/tests/ui/issues/issue-2311.rs new file mode 100644 index 000000000..21ff19f7f --- /dev/null +++ b/tests/ui/issues/issue-2311.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +trait clam { fn get(self) -> A; } +trait foo { + fn bar>(&self, c: C) -> B; +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-2312.rs b/tests/ui/issues/issue-2312.rs new file mode 100644 index 000000000..8a94bcbd4 --- /dev/null +++ b/tests/ui/issues/issue-2312.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// Testing that the B's are resolved + + +trait clam { fn get(self) -> A; } + +struct foo(isize); + +impl foo { + pub fn bar>(&self, _c: C) -> B { panic!(); } +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-23122-1.rs b/tests/ui/issues/issue-23122-1.rs new file mode 100644 index 000000000..7fe0900ed --- /dev/null +++ b/tests/ui/issues/issue-23122-1.rs @@ -0,0 +1,14 @@ +trait Next { + type Next: Next; +} + +struct GetNext { + t: T, +} + +impl Next for GetNext { + type Next = as Next>::Next; + //~^ ERROR overflow evaluating the requirement +} + +fn main() {} diff --git a/tests/ui/issues/issue-23122-1.stderr b/tests/ui/issues/issue-23122-1.stderr new file mode 100644 index 000000000..0b568b30e --- /dev/null +++ b/tests/ui/issues/issue-23122-1.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement ` as Next>::Next == _` + --> $DIR/issue-23122-1.rs:10:17 + | +LL | type Next = as Next>::Next; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-23122-2.rs b/tests/ui/issues/issue-23122-2.rs new file mode 100644 index 000000000..338789c2e --- /dev/null +++ b/tests/ui/issues/issue-23122-2.rs @@ -0,0 +1,15 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" +trait Next { + type Next: Next; +} + +struct GetNext { + t: T, +} + +impl Next for GetNext { + type Next = as Next>::Next; + //~^ ERROR overflow evaluating the requirement +} + +fn main() {} diff --git a/tests/ui/issues/issue-23122-2.stderr b/tests/ui/issues/issue-23122-2.stderr new file mode 100644 index 000000000..06e5b711a --- /dev/null +++ b/tests/ui/issues/issue-23122-2.stderr @@ -0,0 +1,19 @@ +error[E0275]: overflow evaluating the requirement `<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` + --> $DIR/issue-23122-2.rs:11:17 + | +LL | type Next = as Next>::Next; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`) +note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next` + --> $DIR/issue-23122-2.rs:10:15 + | +LL | impl Next for GetNext { + | - ^^^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-23122-2/issue-23122-2.long-type-hash.txt' + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/issues/issue-2316-c.rs b/tests/ui/issues/issue-2316-c.rs new file mode 100644 index 000000000..d975aa695 --- /dev/null +++ b/tests/ui/issues/issue-2316-c.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:issue-2316-a.rs +// aux-build:issue-2316-b.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_2316_b; +use issue_2316_b::cloth; + +pub fn main() { + let _c: cloth::fabric = cloth::fabric::calico; +} diff --git a/tests/ui/issues/issue-23173.rs b/tests/ui/issues/issue-23173.rs new file mode 100644 index 000000000..92f4c5464 --- /dev/null +++ b/tests/ui/issues/issue-23173.rs @@ -0,0 +1,13 @@ +enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ } +struct Struct { + a: usize, +} + +fn use_token(token: &Token) { unimplemented!() } + +fn main() { + use_token(&Token::Homura); //~ ERROR no variant or associated item named `Homura` + Struct::method(); //~ ERROR no function or associated item named `method` found + Struct::method; //~ ERROR no function or associated item named `method` found + Struct::Assoc; //~ ERROR no associated item named `Assoc` found +} diff --git a/tests/ui/issues/issue-23173.stderr b/tests/ui/issues/issue-23173.stderr new file mode 100644 index 000000000..d07d1a7ca --- /dev/null +++ b/tests/ui/issues/issue-23173.stderr @@ -0,0 +1,39 @@ +error[E0599]: no variant or associated item named `Homura` found for enum `Token` in the current scope + --> $DIR/issue-23173.rs:9:23 + | +LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ } + | ---------- variant or associated item `Homura` not found for this enum +... +LL | use_token(&Token::Homura); + | ^^^^^^ variant or associated item not found in `Token` + +error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope + --> $DIR/issue-23173.rs:10:13 + | +LL | struct Struct { + | ------------- function or associated item `method` not found for this struct +... +LL | Struct::method(); + | ^^^^^^ function or associated item not found in `Struct` + +error[E0599]: no function or associated item named `method` found for struct `Struct` in the current scope + --> $DIR/issue-23173.rs:11:13 + | +LL | struct Struct { + | ------------- function or associated item `method` not found for this struct +... +LL | Struct::method; + | ^^^^^^ function or associated item not found in `Struct` + +error[E0599]: no associated item named `Assoc` found for struct `Struct` in the current scope + --> $DIR/issue-23173.rs:12:13 + | +LL | struct Struct { + | ------------- associated item `Assoc` not found for this struct +... +LL | Struct::Assoc; + | ^^^^^ associated item not found in `Struct` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-23189.rs b/tests/ui/issues/issue-23189.rs new file mode 100644 index 000000000..e5526357c --- /dev/null +++ b/tests/ui/issues/issue-23189.rs @@ -0,0 +1,5 @@ +mod module {} + +fn main() { + let _ = module { x: 0 }; //~ERROR expected struct +} diff --git a/tests/ui/issues/issue-23189.stderr b/tests/ui/issues/issue-23189.stderr new file mode 100644 index 000000000..ed065212c --- /dev/null +++ b/tests/ui/issues/issue-23189.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found module `module` + --> $DIR/issue-23189.rs:4:13 + | +LL | let _ = module { x: 0 }; + | ^^^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-23217.rs b/tests/ui/issues/issue-23217.rs new file mode 100644 index 000000000..09f9ebccf --- /dev/null +++ b/tests/ui/issues/issue-23217.rs @@ -0,0 +1,5 @@ +pub enum SomeEnum { + B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found +} + +fn main() {} diff --git a/tests/ui/issues/issue-23217.stderr b/tests/ui/issues/issue-23217.stderr new file mode 100644 index 000000000..5d3d8a4f8 --- /dev/null +++ b/tests/ui/issues/issue-23217.stderr @@ -0,0 +1,14 @@ +error[E0599]: no variant or associated item named `A` found for enum `SomeEnum` in the current scope + --> $DIR/issue-23217.rs:2:19 + | +LL | pub enum SomeEnum { + | ----------------- variant or associated item `A` not found for this enum +LL | B = SomeEnum::A, + | ^ + | | + | variant or associated item not found in `SomeEnum` + | help: there is a variant with a similar name: `B` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-23253.rs b/tests/ui/issues/issue-23253.rs new file mode 100644 index 000000000..22b55c285 --- /dev/null +++ b/tests/ui/issues/issue-23253.rs @@ -0,0 +1,6 @@ +enum Foo { Bar } + +fn main() { + Foo::Bar.a; + //~^ no field `a` on type `Foo` +} diff --git a/tests/ui/issues/issue-23253.stderr b/tests/ui/issues/issue-23253.stderr new file mode 100644 index 000000000..be5714cd9 --- /dev/null +++ b/tests/ui/issues/issue-23253.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `a` on type `Foo` + --> $DIR/issue-23253.rs:4:14 + | +LL | Foo::Bar.a; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-23261.rs b/tests/ui/issues/issue-23261.rs new file mode 100644 index 000000000..e21f86351 --- /dev/null +++ b/tests/ui/issues/issue-23261.rs @@ -0,0 +1,61 @@ +// run-pass +// Matching on a DST struct should not trigger an LLVM assertion. + +struct Foo { + a: i32, + inner: T +} + +trait Get { + fn get(&self) -> i32; +} + +impl Get for i32 { + fn get(&self) -> i32 { + *self + } +} + +fn check_val(val: &Foo<[u8]>) { + match *val { + Foo { a, .. } => { + assert_eq!(a, 32); + } + } +} + +fn check_dst_val(val: &Foo<[u8]>) { + match *val { + Foo { ref inner, .. } => { + assert_eq!(inner, [1, 2, 3]); + } + } +} + +fn check_both(val: &Foo<[u8]>) { + match *val { + Foo { a, ref inner } => { + assert_eq!(a, 32); + assert_eq!(inner, [1, 2, 3]); + } + } +} + +fn check_trait_obj(val: &Foo) { + match *val { + Foo { a, ref inner } => { + assert_eq!(a, 32); + assert_eq!(inner.get(), 32); + } + } +} + +fn main() { + let foo: &Foo<[u8]> = &Foo { a: 32, inner: [1, 2, 3] }; + check_val(foo); + check_dst_val(foo); + check_both(foo); + + let foo: &Foo = &Foo { a: 32, inner: 32 }; + check_trait_obj(foo); +} diff --git a/tests/ui/issues/issue-23281.rs b/tests/ui/issues/issue-23281.rs new file mode 100644 index 000000000..727168964 --- /dev/null +++ b/tests/ui/issues/issue-23281.rs @@ -0,0 +1,12 @@ +pub struct Struct; + +impl Struct { + pub fn function(funs: Vec ()>) {} + //~^ ERROR the size for values of type +} + +struct Vec { + t: T, +} + +fn main() {} diff --git a/tests/ui/issues/issue-23281.stderr b/tests/ui/issues/issue-23281.stderr new file mode 100644 index 000000000..804334c9b --- /dev/null +++ b/tests/ui/issues/issue-23281.stderr @@ -0,0 +1,23 @@ +error[E0277]: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + --> $DIR/issue-23281.rs:4:27 + | +LL | pub fn function(funs: Vec ()>) {} + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` +note: required by a bound in `Vec` + --> $DIR/issue-23281.rs:8:12 + | +LL | struct Vec { + | ^ required by this bound in `Vec` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/issue-23281.rs:8:12 + | +LL | struct Vec { + | ^ this could be changed to `T: ?Sized`... +LL | t: T, + | - ...if indirection were used here: `Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-23302-1.rs b/tests/ui/issues/issue-23302-1.rs new file mode 100644 index 000000000..24e79dc58 --- /dev/null +++ b/tests/ui/issues/issue-23302-1.rs @@ -0,0 +1,7 @@ +// Check that an enum with recursion in the discriminant throws +// the appropriate error (rather than, say, blowing the stack). +enum X { + A = X::A as isize, //~ ERROR E0391 +} + +fn main() { } diff --git a/tests/ui/issues/issue-23302-1.stderr b/tests/ui/issues/issue-23302-1.stderr new file mode 100644 index 000000000..9366050d7 --- /dev/null +++ b/tests/ui/issues/issue-23302-1.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when const-evaluating + checking `X::A::{constant#0}` + --> $DIR/issue-23302-1.rs:4:9 + | +LL | A = X::A as isize, + | ^^^^^^^^^^^^^ + | + = note: ...which immediately requires const-evaluating + checking `X::A::{constant#0}` again +note: cycle used when simplifying constant for the type system `X::A::{constant#0}` + --> $DIR/issue-23302-1.rs:4:9 + | +LL | A = X::A as isize, + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-23302-2.rs b/tests/ui/issues/issue-23302-2.rs new file mode 100644 index 000000000..e89c7eab5 --- /dev/null +++ b/tests/ui/issues/issue-23302-2.rs @@ -0,0 +1,8 @@ +// Since `Y::B` here defaults to `Y::A+1`, this is also a +// recursive definition. +enum Y { + A = Y::B as isize, //~ ERROR E0391 + B, +} + +fn main() { } diff --git a/tests/ui/issues/issue-23302-2.stderr b/tests/ui/issues/issue-23302-2.stderr new file mode 100644 index 000000000..b97ae287a --- /dev/null +++ b/tests/ui/issues/issue-23302-2.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when const-evaluating + checking `Y::A::{constant#0}` + --> $DIR/issue-23302-2.rs:4:9 + | +LL | A = Y::B as isize, + | ^^^^^^^^^^^^^ + | + = note: ...which immediately requires const-evaluating + checking `Y::A::{constant#0}` again +note: cycle used when simplifying constant for the type system `Y::A::{constant#0}` + --> $DIR/issue-23302-2.rs:4:9 + | +LL | A = Y::B as isize, + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-23302-3.rs b/tests/ui/issues/issue-23302-3.rs new file mode 100644 index 000000000..da75f3307 --- /dev/null +++ b/tests/ui/issues/issue-23302-3.rs @@ -0,0 +1,5 @@ +const A: i32 = B; //~ ERROR cycle detected + +const B: i32 = A; + +fn main() { } diff --git a/tests/ui/issues/issue-23302-3.stderr b/tests/ui/issues/issue-23302-3.stderr new file mode 100644 index 000000000..c6cafe575 --- /dev/null +++ b/tests/ui/issues/issue-23302-3.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating + checking `A` + --> $DIR/issue-23302-3.rs:1:16 + | +LL | const A: i32 = B; + | ^ + | +note: ...which requires const-evaluating + checking `B`... + --> $DIR/issue-23302-3.rs:3:16 + | +LL | const B: i32 = A; + | ^ + = note: ...which again requires const-evaluating + checking `A`, completing the cycle +note: cycle used when simplifying constant for the type system `A` + --> $DIR/issue-23302-3.rs:1:1 + | +LL | const A: i32 = B; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-23304-1.rs b/tests/ui/issues/issue-23304-1.rs new file mode 100644 index 000000000..1805c1c19 --- /dev/null +++ b/tests/ui/issues/issue-23304-1.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] + +#[repr(u8)] +#[allow(dead_code)] +enum ValueType { + DOUBLE = 0x00, + INT32 = 0x01, +} + +#[repr(u32)] +enum ValueTag { + INT32 = 0x1FFF0u32 | (ValueType::INT32 as u32), + X, +} + +#[repr(u64)] +enum ValueShiftedTag { + INT32 = ValueTag::INT32 as u64, + X, +} + +fn main() { + println!("{}", ValueTag::INT32 as u32); +} diff --git a/tests/ui/issues/issue-23304-2.rs b/tests/ui/issues/issue-23304-2.rs new file mode 100644 index 000000000..6376fdb65 --- /dev/null +++ b/tests/ui/issues/issue-23304-2.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] + +enum X { A = 42 as isize } + +enum Y { A = X::A as isize } + +fn main() { + let x = X::A; + let x = x as isize; + assert_eq!(x, 42); + assert_eq!(Y::A as isize, 42); +} diff --git a/tests/ui/issues/issue-23311.rs b/tests/ui/issues/issue-23311.rs new file mode 100644 index 000000000..62c96840b --- /dev/null +++ b/tests/ui/issues/issue-23311.rs @@ -0,0 +1,11 @@ +// run-pass + +// Test that we do not ICE when pattern matching an array against a slice. + +fn main() { + match "foo".as_bytes() { + b"food" => (), + &[b'f', ..] => (), + _ => () + } +} diff --git a/tests/ui/issues/issue-23336.rs b/tests/ui/issues/issue-23336.rs new file mode 100644 index 000000000..cd71d7eed --- /dev/null +++ b/tests/ui/issues/issue-23336.rs @@ -0,0 +1,11 @@ +// run-pass +pub trait Data { fn doit(&self) {} } +impl Data for T {} +pub trait UnaryLogic { type D: Data; } +impl UnaryLogic for () { type D = i32; } + +pub fn crashes(t: T::D) { + t.doit(); +} + +fn main() { crashes::<()>(0); } diff --git a/tests/ui/issues/issue-23354-2.rs b/tests/ui/issues/issue-23354-2.rs new file mode 100644 index 000000000..c291d8a5e --- /dev/null +++ b/tests/ui/issues/issue-23354-2.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panic evaluated +// ignore-emscripten no processes + +#[allow(unused_variables)] +fn main() { + // This used to trigger an LLVM assertion during compilation + let x = [panic!("panic evaluated"); 2]; +} diff --git a/tests/ui/issues/issue-23354.rs b/tests/ui/issues/issue-23354.rs new file mode 100644 index 000000000..8b7c2eef2 --- /dev/null +++ b/tests/ui/issues/issue-23354.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern:panic evaluated +// ignore-emscripten no processes + +#[allow(unused_variables)] +fn main() { + let x = [panic!("panic evaluated"); 0]; +} diff --git a/tests/ui/issues/issue-23406.rs b/tests/ui/issues/issue-23406.rs new file mode 100644 index 000000000..d00d5d6f9 --- /dev/null +++ b/tests/ui/issues/issue-23406.rs @@ -0,0 +1,15 @@ +// build-pass +#![allow(dead_code)] +trait Inner { + type T; +} + +impl<'a> Inner for &'a i32 { + type T = i32; +} + +fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T { + *x +} + +fn main() {} diff --git a/tests/ui/issues/issue-23433.rs b/tests/ui/issues/issue-23433.rs new file mode 100644 index 000000000..d4fbbde62 --- /dev/null +++ b/tests/ui/issues/issue-23433.rs @@ -0,0 +1,13 @@ +// run-pass +// Don't fail if we encounter a NonNull where T is an unsized type + +use std::ptr::NonNull; + +fn main() { + let mut a = [0u8; 5]; + let b: Option> = Some(NonNull::from(&mut a)); + match b { + Some(_) => println!("Got `Some`"), + None => panic!("Unexpected `None`"), + } +} diff --git a/tests/ui/issues/issue-23442.rs b/tests/ui/issues/issue-23442.rs new file mode 100644 index 000000000..d1e4317e5 --- /dev/null +++ b/tests/ui/issues/issue-23442.rs @@ -0,0 +1,23 @@ +// check-pass +#![allow(dead_code)] +use std::marker::PhantomData; + +pub struct UnionedKeys<'a,K> + where K: UnifyKey + 'a +{ + table: &'a mut UnificationTable, + root_key: K, + stack: Vec, +} + +pub trait UnifyKey { + type Value; +} + +pub struct UnificationTable { + values: Delegate, +} + +pub struct Delegate(PhantomData); + +fn main() {} diff --git a/tests/ui/issues/issue-23477.rs b/tests/ui/issues/issue-23477.rs new file mode 100644 index 000000000..988ebe03c --- /dev/null +++ b/tests/ui/issues/issue-23477.rs @@ -0,0 +1,16 @@ +// build-pass +// ignore-asmjs wasm2js does not support source maps yet +// compile-flags: -g + +pub struct Dst { + pub a: (), + pub b: (), + pub data: [u8], +} + +pub unsafe fn borrow(bytes: &[u8]) -> &Dst { + let dst: &Dst = std::mem::transmute((bytes.as_ptr(), bytes.len())); + dst +} + +fn main() {} diff --git a/tests/ui/issues/issue-23485.rs b/tests/ui/issues/issue-23485.rs new file mode 100644 index 000000000..1dd3d9293 --- /dev/null +++ b/tests/ui/issues/issue-23485.rs @@ -0,0 +1,50 @@ +// run-pass +#![allow(unused_imports)] +// Test for an ICE that occurred when a default method implementation +// was applied to a type that did not meet the prerequisites. The +// problem occurred specifically because normalizing +// `Self::Item::Target` was impossible in this case. + +use std::boxed::Box; +use std::marker::Sized; +use std::clone::Clone; +use std::ops::Deref; +use std::option::Option; +use std::option::Option::{Some,None}; + +trait Iterator { + type Item; + + fn next(&mut self) -> Option; + + fn clone_first(mut self) -> Option<::Target> where + Self: Sized, + Self::Item: Deref, + ::Target: Clone, + { + self.next().map(|x| x.clone()) + } +} + +struct Counter { + value: i32 +} + +struct Token { + value: i32 +} + +impl Iterator for Counter { + type Item = Token; + + fn next(&mut self) -> Option { + let x = self.value; + self.value += 1; + Some(Token { value: x }) + } +} + +fn main() { + let mut x: Box> = Box::new(Counter { value: 22 }); + assert_eq!(x.next().unwrap().value, 22); +} diff --git a/tests/ui/issues/issue-23491.rs b/tests/ui/issues/issue-23491.rs new file mode 100644 index 000000000..e5f9dd3ef --- /dev/null +++ b/tests/ui/issues/issue-23491.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_variables)] + +struct Node(#[allow(unused_tuple_struct_fields)] T); + +fn main() { + let x: Box> = Box::new(Node([])); +} diff --git a/tests/ui/issues/issue-23543.rs b/tests/ui/issues/issue-23543.rs new file mode 100644 index 000000000..843e1a8a8 --- /dev/null +++ b/tests/ui/issues/issue-23543.rs @@ -0,0 +1,11 @@ +pub trait A: Copy {} + +struct Foo; + +pub trait D { + fn f(self) + where T: A; + //~^ ERROR associated type bindings are not allowed here [E0229] +} + +fn main() {} diff --git a/tests/ui/issues/issue-23543.stderr b/tests/ui/issues/issue-23543.stderr new file mode 100644 index 000000000..ebb70afe3 --- /dev/null +++ b/tests/ui/issues/issue-23543.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-23543.rs:7:17 + | +LL | where T: A; + | ^^^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-23544.rs b/tests/ui/issues/issue-23544.rs new file mode 100644 index 000000000..6ad00b2fb --- /dev/null +++ b/tests/ui/issues/issue-23544.rs @@ -0,0 +1,9 @@ +pub trait A: Copy {} + +pub trait D { + fn f(self) + where T: A; + //~^ ERROR associated type bindings are not allowed here [E0229] +} + +fn main() {} diff --git a/tests/ui/issues/issue-23544.stderr b/tests/ui/issues/issue-23544.stderr new file mode 100644 index 000000000..c912baccb --- /dev/null +++ b/tests/ui/issues/issue-23544.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-23544.rs:5:17 + | +LL | where T: A; + | ^^^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-23550.rs b/tests/ui/issues/issue-23550.rs new file mode 100644 index 000000000..9cce9a0a9 --- /dev/null +++ b/tests/ui/issues/issue-23550.rs @@ -0,0 +1,22 @@ +// build-pass +#![feature(core_intrinsics)] +#![allow(warnings)] + +use std::intrinsics; + +#[derive(Copy, Clone)] +struct Wrap(i64); + +// These volatile intrinsics used to cause an ICE + +unsafe fn test_bool(p: &mut bool, v: bool) { + intrinsics::volatile_load(p); + intrinsics::volatile_store(p, v); +} + +unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) { + intrinsics::volatile_load(p); + intrinsics::volatile_store(p, v); +} + +fn main() {} diff --git a/tests/ui/issues/issue-23589.rs b/tests/ui/issues/issue-23589.rs new file mode 100644 index 000000000..1c640af8d --- /dev/null +++ b/tests/ui/issues/issue-23589.rs @@ -0,0 +1,5 @@ +fn main() { + let v: Vec(&str) = vec!['1', '2']; + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR mismatched types +} diff --git a/tests/ui/issues/issue-23589.stderr b/tests/ui/issues/issue-23589.stderr new file mode 100644 index 000000000..1a91f5e04 --- /dev/null +++ b/tests/ui/issues/issue-23589.stderr @@ -0,0 +1,26 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-23589.rs:2:12 + | +LL | let v: Vec(&str) = vec!['1', '2']; + | ^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | let v: Vec<&str> = vec!['1', '2']; + | ~ ~ + +error[E0308]: mismatched types + --> $DIR/issue-23589.rs:2:29 + | +LL | let v: Vec(&str) = vec!['1', '2']; + | ^^^ expected `&str`, found `char` + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let v: Vec(&str) = vec!["1", '2']; + | ~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0214, E0308. +For more information about an error, try `rustc --explain E0214`. diff --git a/tests/ui/issues/issue-23611-enum-swap-in-drop.rs b/tests/ui/issues/issue-23611-enum-swap-in-drop.rs new file mode 100644 index 000000000..cdb130d60 --- /dev/null +++ b/tests/ui/issues/issue-23611-enum-swap-in-drop.rs @@ -0,0 +1,259 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// Issue 23611: this test is ensuring that, for an instance `X` of the +// enum `E`, if you swap in a different variant during the execution +// of the `::drop`, then the appropriate substructure will +// be torn down after the `::drop` method returns. + +use std::cell::RefCell; +use std::mem; + +use self::d::D; + +pub fn main() { + let log = RefCell::new(vec![]); + d::println("created empty log"); + test(&log); + + // println!("log: {:?}", &log.borrow()[..]); + assert_eq!( + &log.borrow()[..], + [ + // created empty log + // +-- Make D(test_1, 10000000) + // | +-- Make D(g_b_5, 50000001) + // | | in g_B(b2b0) from E::drop, b=b4b0 + // | +-- Drop D(g_b_5, 50000001) + 50000001, + // | + // | +-- Make D(drop_6, 60000002) + // | | +-- Make D(g_b_5, 50000003) + // | | | in g_B(b2b0) from E::drop, b=b4b1 + // | | +-- Drop D(g_b_5, 50000003) + 50000003, + // | | + // | | +-- Make D(GaspB::drop_3, 30000004) + // | | | +-- Make D(g_b_5, 50000005) + // | | | | in g_B(b4b2) from GaspB::drop + // | | | +-- Drop D(g_b_5, 50000005) + 50000005, + // | | | + // | | +-- Drop D(GaspB::drop_3, 30000004) + 30000004, + // | | + // +-- Drop D(test_1, 10000000) + 10000000, + // | + // +-- Make D(GaspA::drop_2, 20000006) + // | | +-- Make D(f_a_4, 40000007) + // | | | in f_A(a3a0) from GaspA::drop + // | | +-- Drop D(f_a_4, 40000007) + 40000007, + // | | + // +-- Drop D(GaspA::drop_2, 20000006) + 20000006, + // | + // +-- Drop D(drop_6, 60000002) + 60000002 + // + ]); + + // For reference purposes, the old (incorrect) behavior would produce the following + // output, which you can compare to the above: + // + // created empty log + // +-- Make D(test_1, 10000000) + // | +-- Make D(g_b_5, 50000001) + // | | in g_B(b2b0) from E::drop, b=b4b0 + // | +-- Drop D(g_b_5, 50000001) + // | + // | +-- Make D(drop_6, 60000002) + // | | +-- Make D(g_b_5, 50000003) + // | | | in g_B(b2b0) from E::drop, b=b4b1 + // | | +-- Drop D(g_b_5, 50000003) + // | | + // | | +-- Make D(GaspB::drop_3, 30000004) + // | | | +-- Make D(g_b_5, 50000005) + // | | | | in g_B(b4b2) from GaspB::drop + // | | | +-- Drop D(g_b_5, 50000005) + // | | | + // | | +-- Drop D(GaspB::drop_3, 30000004) + // | | + // +-- Drop D(test_1, 10000000) + // | + // +-- Make D(GaspB::drop_3, 30000006) + // | | +-- Make D(f_a_4, 40000007) + // | | | in f_A(a3a0) from GaspB::drop + // | | +-- Drop D(f_a_4, 40000007) + // | | + // +-- Drop D(GaspB::drop_3, 30000006) + // | + // +-- Drop D(drop_6, 60000002) + + // Note that this calls f_A from GaspB::drop (and thus creates a D + // with a uid incorporating the origin of GaspB's drop that + // surrounds the f_A invocation), but the code as written only + // ever hands f_A off to instances of GaspA, and thus one should + // be able to prove the invariant that f_A is *only* invoked from + // from an instance of GaspA (either via the GaspA drop + // implementation or the E drop implementation). Yet the old (bad) + // behavior allowed a call to f_A to leak in while we are tearing + // down a value of type GaspB. +} + +fn test<'a>(log: d::Log<'a>) { + let _e = E::B(GaspB(g_b, 0xB4B0, log, D::new("test", 1, log)), true); +} + +struct GaspA<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>); +struct GaspB<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>); + +impl<'a> Drop for GaspA<'a> { + fn drop(&mut self) { + let _d = d::D::new("GaspA::drop", 2, self.2); + (self.0)(self.1, "GaspA::drop", self.2); + } +} + +impl<'a> Drop for GaspB<'a> { + fn drop(&mut self) { + let _d = d::D::new("GaspB::drop", 3, self.2); + (self.0)(self.1, "GaspB::drop", self.2); + } +} + +enum E<'a> { + A(GaspA<'a>, bool), B(GaspB<'a>, bool), +} + +fn f_a(x: u32, ctxt: &str, log: d::Log) { + let _d = d::D::new("f_a", 4, log); + d::println(&format!("in f_A({:x}) from {}", x, ctxt)); +} +fn g_b(y: u32, ctxt: &str, log: d::Log) { + let _d = d::D::new("g_b", 5, log); + d::println(&format!("in g_B({:x}) from {}", y, ctxt)); +} + +impl<'a> Drop for E<'a> { + fn drop(&mut self) { + let (do_drop, log) = match *self { + E::A(GaspA(ref f, ref mut val_a, log, ref _d_a), ref mut do_drop) => { + f(0xA1A0, &format!("E::drop, a={:x}", val_a), log); + *val_a += 1; + // swap in do_drop := false to avoid infinite dtor regress + (mem::replace(do_drop, false), log) + } + E::B(GaspB(ref g, ref mut val_b, log, ref _d_b), ref mut do_drop) => { + g(0xB2B0, &format!("E::drop, b={:x}", val_b), log); + *val_b += 1; + // swap in do_drop := false to avoid infinite dtor regress + (mem::replace(do_drop, false), log) + } + }; + + #[allow(unused_must_use)] + if do_drop { + mem::replace(self, E::A(GaspA(f_a, 0xA3A0, log, D::new("drop", 6, log)), true)); + } + } +} + +// This module provides simultaneous printouts of the dynamic extents +// of all of the D values, in addition to logging the order that each +// is dropped. +// +// This code is similar to a support code module embedded within +// test/run-pass/issue-123338-ensure-param-drop-order.rs; however, +// that (slightly simpler) code only identifies objects in the log via +// (creation) time-stamps; this incorporates both timestamping and the +// point of origin within the source code into the unique ID (uid). + +const PREF_INDENT: u32 = 20; + +pub mod d { + #![allow(unused_parens)] + use std::fmt; + use std::mem; + use std::cell::RefCell; + + static mut counter: u16 = 0; + static mut trails: u64 = 0; + + pub type Log<'a> = &'a RefCell>; + + pub fn current_width() -> u32 { + unsafe { max_width() - trails.leading_zeros() } + } + + pub fn max_width() -> u32 { + unsafe { + (mem::size_of_val(&trails)*8) as u32 + } + } + + pub fn indent_println(my_trails: u32, s: &str) { + let mut indent: String = String::new(); + for i in 0..my_trails { + unsafe { + if trails & (1 << i) != 0 { + indent = indent + "| "; + } else { + indent = indent + " "; + } + } + } + println!("{}{}", indent, s); + } + + pub fn println(s: &str) { + indent_println(super::PREF_INDENT, s); + } + + fn first_avail() -> u32 { + unsafe { + for i in 0..64 { + if trails & (1 << i) == 0 { + return i; + } + } + } + panic!("exhausted trails"); + } + + pub struct D<'a> { + name: &'static str, i: u8, uid: u32, trail: u32, log: Log<'a> + } + + impl<'a> fmt::Display for D<'a> { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + write!(w, "D({}_{}, {})", self.name, self.i, self.uid) + } + } + + impl<'a> D<'a> { + pub fn new(name: &'static str, i: u8, log: Log<'a>) -> D<'a> { + unsafe { + let trail = first_avail(); + let ctr = ((i as u32) * 10_000_000) + (counter as u32); + counter += 1; + trails |= (1 << trail); + let ret = D { + name: name, i: i, log: log, uid: ctr, trail: trail + }; + indent_println(trail, &format!("+-- Make {}", ret)); + ret + } + } + } + + impl<'a> Drop for D<'a> { + fn drop(&mut self) { + unsafe { trails &= !(1 << self.trail); }; + self.log.borrow_mut().push(self.uid); + indent_println(self.trail, &format!("+-- Drop {}", self)); + indent_println(::PREF_INDENT, ""); + } + } +} diff --git a/tests/ui/issues/issue-23649-1.rs b/tests/ui/issues/issue-23649-1.rs new file mode 100644 index 000000000..fc0c9a605 --- /dev/null +++ b/tests/ui/issues/issue-23649-1.rs @@ -0,0 +1,12 @@ +// run-pass +use std::mem; + +pub struct X([u8]); + +fn _f(x: &X) -> usize { match *x { X(ref x) => { x.len() } } } + +fn main() { + let b: &[u8] = &[11; 42]; + let v: &X = unsafe { mem::transmute(b) }; + assert_eq!(_f(v), 42); +} diff --git a/tests/ui/issues/issue-23649-2.rs b/tests/ui/issues/issue-23649-2.rs new file mode 100644 index 000000000..ce7d8e3a7 --- /dev/null +++ b/tests/ui/issues/issue-23649-2.rs @@ -0,0 +1,10 @@ +// run-pass + +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +fn main() { + let m: HashMap = HashMap::new(); + let k = Path::new("foo"); + println!("{:?}", m.get(k)); +} diff --git a/tests/ui/issues/issue-23649-3.rs b/tests/ui/issues/issue-23649-3.rs new file mode 100644 index 000000000..8f61c71d6 --- /dev/null +++ b/tests/ui/issues/issue-23649-3.rs @@ -0,0 +1,5 @@ +// build-pass +#[derive(PartialEq)] +struct Slice { slice: [u8] } + +fn main() {} diff --git a/tests/ui/issues/issue-23699.rs b/tests/ui/issues/issue-23699.rs new file mode 100644 index 000000000..952548837 --- /dev/null +++ b/tests/ui/issues/issue-23699.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_variables)] +fn gimme_a_raw_pointer(_: *const T) { } + +fn test(t: T) { } + +fn main() { + // Clearly `pointer` must be of type `*const ()`. + let pointer = &() as *const _; + gimme_a_raw_pointer(pointer); + + let t = test as fn (i32); + t(0i32); +} diff --git a/tests/ui/issues/issue-23781.rs b/tests/ui/issues/issue-23781.rs new file mode 100644 index 000000000..220ebdb18 --- /dev/null +++ b/tests/ui/issues/issue-23781.rs @@ -0,0 +1,29 @@ +// run-pass +use std::fmt; + +struct Foo; +impl fmt::Debug for Foo { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + println!("::fmt()"); + + write!(fmt, "") + } +} + +fn test1() { + let foo_str = format!("{:?}", Foo); + + println!("{}", foo_str); +} + +fn test2() { + println!("{:?}", Foo); +} + +fn main() { + // This works fine + test1(); + + // This fails + test2(); +} diff --git a/tests/ui/issues/issue-2380-b.rs b/tests/ui/issues/issue-2380-b.rs new file mode 100644 index 000000000..d708c7b42 --- /dev/null +++ b/tests/ui/issues/issue-2380-b.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:issue-2380.rs + +// pretty-expanded FIXME #23616 + +extern crate a; + +pub fn main() { + a::f::<()>(); +} diff --git a/tests/ui/issues/issue-23808.rs b/tests/ui/issues/issue-23808.rs new file mode 100644 index 000000000..0988b09fc --- /dev/null +++ b/tests/ui/issues/issue-23808.rs @@ -0,0 +1,59 @@ +// run-pass + +#![deny(dead_code)] + +// use different types / traits to test all combinations + +trait Const { + const C: (); +} + +trait StaticFn { + fn sfn(); +} + +struct ConstStruct; +struct StaticFnStruct; + +enum ConstEnum {} +enum StaticFnEnum {} + +struct AliasedConstStruct; +struct AliasedStaticFnStruct; + +enum AliasedConstEnum {} +enum AliasedStaticFnEnum {} + +type AliasConstStruct = AliasedConstStruct; +type AliasStaticFnStruct = AliasedStaticFnStruct; +type AliasConstEnum = AliasedConstEnum; +type AliasStaticFnEnum = AliasedStaticFnEnum; + +macro_rules! impl_Const {($($T:ident),*) => {$( + impl Const for $T { + const C: () = (); + } +)*}} + +macro_rules! impl_StaticFn {($($T:ident),*) => {$( + impl StaticFn for $T { + fn sfn() {} + } +)*}} + +impl_Const!(ConstStruct, ConstEnum, AliasedConstStruct, AliasedConstEnum); +impl_StaticFn!(StaticFnStruct, StaticFnEnum, AliasedStaticFnStruct, AliasedStaticFnEnum); + +fn main() { + let _ = ConstStruct::C; + let _ = ConstEnum::C; + + StaticFnStruct::sfn(); + StaticFnEnum::sfn(); + + let _ = AliasConstStruct::C; + let _ = AliasConstEnum::C; + + AliasStaticFnStruct::sfn(); + AliasStaticFnEnum::sfn(); +} diff --git a/tests/ui/issues/issue-2383.rs b/tests/ui/issues/issue-2383.rs new file mode 100644 index 000000000..06e61ce68 --- /dev/null +++ b/tests/ui/issues/issue-2383.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::collections::VecDeque; + +pub fn main() { + let mut q = VecDeque::new(); + q.push_front(10); +} diff --git a/tests/ui/issues/issue-23891.rs b/tests/ui/issues/issue-23891.rs new file mode 100644 index 000000000..73467f715 --- /dev/null +++ b/tests/ui/issues/issue-23891.rs @@ -0,0 +1,11 @@ +// run-pass +macro_rules! id { + ($s: pat) => ($s); +} + +fn main() { + match (Some(123), Some(456)) { + (id!(Some(a)), _) | (_, id!(Some(a))) => println!("{}", a), + _ => (), + } +} diff --git a/tests/ui/issues/issue-23898.rs b/tests/ui/issues/issue-23898.rs new file mode 100644 index 000000000..3de365675 --- /dev/null +++ b/tests/ui/issues/issue-23898.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_parens)] +#![allow(non_camel_case_types)] + +// Note: This test was used to demonstrate #5873 (now #23898). + +enum State { ST_NULL, ST_WHITESPACE } + +fn main() { + [State::ST_NULL; (State::ST_WHITESPACE as usize)]; +} diff --git a/tests/ui/issues/issue-23958.rs b/tests/ui/issues/issue-23958.rs new file mode 100644 index 000000000..7e90d7586 --- /dev/null +++ b/tests/ui/issues/issue-23958.rs @@ -0,0 +1,13 @@ +// run-pass +trait Collection where for<'a> &'a Self: IntoIterator { + fn my_iter(&self) -> <&Self as IntoIterator>::IntoIter { + self.into_iter() + } +} + +impl Collection for [T] { } + +fn main() { + let v = [0usize]; + let _ = v.my_iter(); +} diff --git a/tests/ui/issues/issue-23966.rs b/tests/ui/issues/issue-23966.rs new file mode 100644 index 000000000..5fdec28ac --- /dev/null +++ b/tests/ui/issues/issue-23966.rs @@ -0,0 +1,4 @@ +fn main() { + "".chars().fold(|_, _| (), ()); + //~^ ERROR E0277 +} diff --git a/tests/ui/issues/issue-23966.stderr b/tests/ui/issues/issue-23966.stderr new file mode 100644 index 000000000..8f934481d --- /dev/null +++ b/tests/ui/issues/issue-23966.stderr @@ -0,0 +1,15 @@ +error[E0277]: expected a `FnMut<(_, char)>` closure, found `()` + --> $DIR/issue-23966.rs:2:32 + | +LL | "".chars().fold(|_, _| (), ()); + | ---- ^^ expected an `FnMut<(_, char)>` closure, found `()` + | | + | required by a bound introduced by this call + | + = help: the trait `FnMut<(_, char)>` is not implemented for `()` +note: required by a bound in `fold` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-23992.rs b/tests/ui/issues/issue-23992.rs new file mode 100644 index 000000000..1ff44bd7f --- /dev/null +++ b/tests/ui/issues/issue-23992.rs @@ -0,0 +1,19 @@ +// run-pass +pub struct Outer(T); +pub struct Inner<'a> { value: &'a bool } + +pub trait Trait { + type Error; + fn ready(self) -> Self::Error; +} + +impl<'a> Trait for Inner<'a> { + type Error = Outer>; + fn ready(self) -> Outer> { Outer(self) } +} + +fn main() { + let value = true; + let inner = Inner { value: &value }; + assert_eq!(inner.ready().0.value, &value); +} diff --git a/tests/ui/issues/issue-24013.rs b/tests/ui/issues/issue-24013.rs new file mode 100644 index 000000000..c6d301671 --- /dev/null +++ b/tests/ui/issues/issue-24013.rs @@ -0,0 +1,7 @@ +fn main() { + use std::mem::{transmute, swap}; + let a = 1; + let b = 2; + unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; + //~^ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-24013.stderr b/tests/ui/issues/issue-24013.stderr new file mode 100644 index 000000000..72102f460 --- /dev/null +++ b/tests/ui/issues/issue-24013.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/issue-24013.rs:5:13 + | +LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))}; + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-24036.rs b/tests/ui/issues/issue-24036.rs new file mode 100644 index 000000000..7df036c8e --- /dev/null +++ b/tests/ui/issues/issue-24036.rs @@ -0,0 +1,16 @@ +fn closure_to_loc() { + let mut x = |c| c + 1; + x = |c| c + 1; + //~^ ERROR mismatched types +} + +fn closure_from_match() { + let x = match 1usize { + 1 => |c| c + 1, + 2 => |c| c - 1, + _ => |c| c - 1 + }; + //~^^^^ ERROR type annotations needed +} + +fn main() { } diff --git a/tests/ui/issues/issue-24036.stderr b/tests/ui/issues/issue-24036.stderr new file mode 100644 index 000000000..0e73a51fa --- /dev/null +++ b/tests/ui/issues/issue-24036.stderr @@ -0,0 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/issue-24036.rs:3:9 + | +LL | let mut x = |c| c + 1; + | --- the expected closure +LL | x = |c| c + 1; + | ^^^^^^^^^ expected closure, found a different closure + | + = note: expected closure `[closure@$DIR/issue-24036.rs:2:17: 2:20]` + found closure `[closure@$DIR/issue-24036.rs:3:9: 3:12]` + = note: no two closures, even if identical, have the same type + = help: consider boxing your closure and/or using it as a trait object + +error[E0282]: type annotations needed + --> $DIR/issue-24036.rs:9:15 + | +LL | 1 => |c| c + 1, + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | 1 => |c: /* Type */| c + 1, + | ++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-24086.rs b/tests/ui/issues/issue-24086.rs new file mode 100644 index 000000000..54622afbc --- /dev/null +++ b/tests/ui/issues/issue-24086.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] +pub struct Registry<'a> { + listener: &'a mut (), +} + +pub struct Listener<'a> { + pub announce: Option>, + pub remove: Option>, +} + +impl<'a> Drop for Registry<'a> { + fn drop(&mut self) {} +} + +fn main() { + let mut registry_listener = Listener { + announce: None, + remove: None, + }; +} diff --git a/tests/ui/issues/issue-2414-c.rs b/tests/ui/issues/issue-2414-c.rs new file mode 100644 index 000000000..f6fe97980 --- /dev/null +++ b/tests/ui/issues/issue-2414-c.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:issue-2414-a.rs +// aux-build:issue-2414-b.rs + +// pretty-expanded FIXME #23616 + +extern crate b; + +pub fn main() {} diff --git a/tests/ui/issues/issue-24161.rs b/tests/ui/issues/issue-24161.rs new file mode 100644 index 000000000..f4cdd982a --- /dev/null +++ b/tests/ui/issues/issue-24161.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] +#[derive(Copy,Clone)] +struct Functions { + a: fn(u32) -> u32, + b: extern "C" fn(u32) -> u32, + c: unsafe fn(u32) -> u32, + d: unsafe extern "C" fn(u32) -> u32 +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-24227.rs b/tests/ui/issues/issue-24227.rs new file mode 100644 index 000000000..12816c235 --- /dev/null +++ b/tests/ui/issues/issue-24227.rs @@ -0,0 +1,18 @@ +// check-pass +// This resulted in an ICE. Test for future-proofing +// Issue #24227 + +#![allow(unused)] + +struct Foo<'a> { + x: &'a u8 +} + +impl<'a> Foo<'a> { + fn foo() { + let mut tmp: Self; + } + +} + +fn main() {} diff --git a/tests/ui/issues/issue-2428.rs b/tests/ui/issues/issue-2428.rs new file mode 100644 index 000000000..94b830de3 --- /dev/null +++ b/tests/ui/issues/issue-2428.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(non_upper_case_globals)] + + +pub fn main() { + let _foo = 100; + const quux: isize = 5; + + enum Stuff { + Bar = quux + } + + assert_eq!(Stuff::Bar as isize, quux); +} diff --git a/tests/ui/issues/issue-24308.rs b/tests/ui/issues/issue-24308.rs new file mode 100644 index 000000000..4a582c68e --- /dev/null +++ b/tests/ui/issues/issue-24308.rs @@ -0,0 +1,17 @@ +// run-pass +pub trait Foo { + fn method1() {} + fn method2(); +} + +struct Slice<'a, T: 'a>(#[allow(unused_tuple_struct_fields)] &'a [T]); + +impl<'a, T: 'a> Foo for Slice<'a, T> { + fn method2() { + ::method1(); + } +} + +fn main() { + as Foo>::method2(); +} diff --git a/tests/ui/issues/issue-24322.rs b/tests/ui/issues/issue-24322.rs new file mode 100644 index 000000000..6567fcab4 --- /dev/null +++ b/tests/ui/issues/issue-24322.rs @@ -0,0 +1,9 @@ +struct B; + +impl B { + fn func(&self) -> u32 { 42 } +} + +fn main() { + let x: &fn(&B) -> u32 = &B::func; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-24322.stderr b/tests/ui/issues/issue-24322.stderr new file mode 100644 index 000000000..1e4c8ac7c --- /dev/null +++ b/tests/ui/issues/issue-24322.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-24322.rs:8:29 + | +LL | let x: &fn(&B) -> u32 = &B::func; + | -------------- ^^^^^^^^ expected fn pointer, found fn item + | | + | expected due to this + | + = note: expected reference `&for<'a> fn(&'a B) -> u32` + found reference `&for<'a> fn(&'a B) -> u32 {B::func}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-24352.rs b/tests/ui/issues/issue-24352.rs new file mode 100644 index 000000000..5c8246d17 --- /dev/null +++ b/tests/ui/issues/issue-24352.rs @@ -0,0 +1,4 @@ +fn main() { + 1.0f64 - 1.0; + 1.0f64 - 1 //~ ERROR E0277 +} diff --git a/tests/ui/issues/issue-24352.stderr b/tests/ui/issues/issue-24352.stderr new file mode 100644 index 000000000..1f51b6e29 --- /dev/null +++ b/tests/ui/issues/issue-24352.stderr @@ -0,0 +1,20 @@ +error[E0277]: cannot subtract `{integer}` from `f64` + --> $DIR/issue-24352.rs:3:12 + | +LL | 1.0f64 - 1 + | ^ no implementation for `f64 - {integer}` + | + = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Sub`: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | 1.0f64 - 1.0 + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-24353.rs b/tests/ui/issues/issue-24353.rs new file mode 100644 index 000000000..f78255b7e --- /dev/null +++ b/tests/ui/issues/issue-24353.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unreachable_code)] +fn main() { + return (); + + let x = (); + x +} diff --git a/tests/ui/issues/issue-24357.rs b/tests/ui/issues/issue-24357.rs new file mode 100644 index 000000000..152e69ebc --- /dev/null +++ b/tests/ui/issues/issue-24357.rs @@ -0,0 +1,11 @@ +struct NoCopy; +fn main() { + let x = NoCopy; + //~^ NOTE move occurs because `x` has type `NoCopy` + let f = move || { let y = x; }; + //~^ NOTE value moved into closure here + //~| NOTE variable moved due to use in closure + let z = x; + //~^ ERROR use of moved value: `x` + //~| NOTE value used here after move +} diff --git a/tests/ui/issues/issue-24357.stderr b/tests/ui/issues/issue-24357.stderr new file mode 100644 index 000000000..b9e15f5e2 --- /dev/null +++ b/tests/ui/issues/issue-24357.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of moved value: `x` + --> $DIR/issue-24357.rs:8:12 + | +LL | let x = NoCopy; + | - move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait +LL | +LL | let f = move || { let y = x; }; + | ------- - variable moved due to use in closure + | | + | value moved into closure here +... +LL | let z = x; + | ^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-24363.rs b/tests/ui/issues/issue-24363.rs new file mode 100644 index 000000000..34726fba9 --- /dev/null +++ b/tests/ui/issues/issue-24363.rs @@ -0,0 +1,6 @@ +fn main() { + 1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields + ()+() //~ ERROR cannot add + // ^ ensure that we typeck the inner expression ^ + ]; +} diff --git a/tests/ui/issues/issue-24363.stderr b/tests/ui/issues/issue-24363.stderr new file mode 100644 index 000000000..16537e21a --- /dev/null +++ b/tests/ui/issues/issue-24363.stderr @@ -0,0 +1,18 @@ +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/issue-24363.rs:2:7 + | +LL | 1.create_a_type_error[ + | ^^^^^^^^^^^^^^^^^^^ + +error[E0369]: cannot add `()` to `()` + --> $DIR/issue-24363.rs:3:11 + | +LL | ()+() + | --^-- () + | | + | () + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0369, E0610. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-24365.rs b/tests/ui/issues/issue-24365.rs new file mode 100644 index 000000000..eca104b6f --- /dev/null +++ b/tests/ui/issues/issue-24365.rs @@ -0,0 +1,19 @@ +pub enum Attribute { + Code {attr_name_idx: u16}, +} + +pub enum Foo { + Bar +} + +fn test(a: Foo) { + println!("{}", a.b); //~ no field `b` on type `Foo` +} + +fn main() { + let x = Attribute::Code { + attr_name_idx: 42, + }; + let z = (&x).attr_name_idx; //~ no field `attr_name_idx` on type `&Attribute` + let y = x.attr_name_idx; //~ no field `attr_name_idx` on type `Attribute` +} diff --git a/tests/ui/issues/issue-24365.stderr b/tests/ui/issues/issue-24365.stderr new file mode 100644 index 000000000..f9eead8a4 --- /dev/null +++ b/tests/ui/issues/issue-24365.stderr @@ -0,0 +1,21 @@ +error[E0609]: no field `b` on type `Foo` + --> $DIR/issue-24365.rs:10:22 + | +LL | println!("{}", a.b); + | ^ + +error[E0609]: no field `attr_name_idx` on type `&Attribute` + --> $DIR/issue-24365.rs:17:18 + | +LL | let z = (&x).attr_name_idx; + | ^^^^^^^^^^^^^ + +error[E0609]: no field `attr_name_idx` on type `Attribute` + --> $DIR/issue-24365.rs:18:15 + | +LL | let y = x.attr_name_idx; + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-24389.rs b/tests/ui/issues/issue-24389.rs new file mode 100644 index 000000000..7cc761176 --- /dev/null +++ b/tests/ui/issues/issue-24389.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] + +struct Foo; + +impl Foo { + fn new() -> Self { Foo } + fn bar() { Self::new(); } +} + +fn main() {} diff --git a/tests/ui/issues/issue-24424.rs b/tests/ui/issues/issue-24424.rs new file mode 100644 index 000000000..22bf513af --- /dev/null +++ b/tests/ui/issues/issue-24424.rs @@ -0,0 +1,7 @@ +trait Trait1<'l0, T0> {} +trait Trait0<'l0> {} + +impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} +//~^ ERROR type annotations needed + +fn main() {} diff --git a/tests/ui/issues/issue-24424.stderr b/tests/ui/issues/issue-24424.stderr new file mode 100644 index 000000000..50d7f988e --- /dev/null +++ b/tests/ui/issues/issue-24424.stderr @@ -0,0 +1,15 @@ +error[E0283]: type annotations needed: cannot satisfy `T0: Trait0<'l0>` + --> $DIR/issue-24424.rs:4:57 + | +LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} + | ^^^^^^^^^^^ + | +note: multiple `impl`s or `where` clauses satisfying `T0: Trait0<'l0>` found + --> $DIR/issue-24424.rs:4:57 + | +LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} + | ^^^^^^^^^^^ ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-24434.rs b/tests/ui/issues/issue-24434.rs new file mode 100644 index 000000000..4c1bfc03c --- /dev/null +++ b/tests/ui/issues/issue-24434.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags:--cfg set1 + +#![cfg_attr(set1, feature(rustc_attrs))] +#![rustc_dummy] + +fn main() {} diff --git a/tests/ui/issues/issue-24446.rs b/tests/ui/issues/issue-24446.rs new file mode 100644 index 000000000..9ab952ade --- /dev/null +++ b/tests/ui/issues/issue-24446.rs @@ -0,0 +1,7 @@ +fn main() { + static foo: dyn Fn() -> u32 = || -> u32 { + //~^ ERROR the size for values of type + //~| ERROR cannot be shared between threads safely + 0 + }; +} diff --git a/tests/ui/issues/issue-24446.stderr b/tests/ui/issues/issue-24446.stderr new file mode 100644 index 000000000..4afb87c48 --- /dev/null +++ b/tests/ui/issues/issue-24446.stderr @@ -0,0 +1,20 @@ +error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time + --> $DIR/issue-24446.rs:2:17 + | +LL | static foo: dyn Fn() -> u32 = || -> u32 { + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` + +error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely + --> $DIR/issue-24446.rs:2:17 + | +LL | static foo: dyn Fn() -> u32 = || -> u32 { + | ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)` + = note: shared static variables must have a type that implements `Sync` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-2445-b.rs b/tests/ui/issues/issue-2445-b.rs new file mode 100644 index 000000000..f369eae3a --- /dev/null +++ b/tests/ui/issues/issue-2445-b.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct c1 { + x: T, +} + +impl c1 { + pub fn f1(&self, _x: isize) { + } +} + +fn c1(x: T) -> c1 { + c1 { + x: x + } +} + +impl c1 { + pub fn f2(&self, _x: isize) { + } +} + + +pub fn main() { + c1::(3).f1(4); + c1::(3).f2(4); +} diff --git a/tests/ui/issues/issue-2445.rs b/tests/ui/issues/issue-2445.rs new file mode 100644 index 000000000..5730ce165 --- /dev/null +++ b/tests/ui/issues/issue-2445.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct c1 { + x: T, +} + +impl c1 { + pub fn f1(&self, _x: T) {} +} + +fn c1(x: T) -> c1 { + c1 { + x: x + } +} + +impl c1 { + pub fn f2(&self, _x: T) {} +} + + +pub fn main() { + c1::(3).f1(4); + c1::(3).f2(4); +} diff --git a/tests/ui/issues/issue-24533.rs b/tests/ui/issues/issue-24533.rs new file mode 100644 index 000000000..8592bf430 --- /dev/null +++ b/tests/ui/issues/issue-24533.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(unused_must_use)] +use std::slice::Iter; +use std::io::{Error, ErrorKind, Result}; +use std::vec::*; + +fn foo(it: &mut Iter) -> Result { + Ok(*it.next().unwrap()) +} + +fn bar() -> Result { + let data: Vec = Vec::new(); + + if true { + return Err(Error::new(ErrorKind::NotFound, "msg")); + } + + let mut it = data.iter(); + foo(&mut it) +} + +fn main() { + bar(); +} diff --git a/tests/ui/issues/issue-24589.rs b/tests/ui/issues/issue-24589.rs new file mode 100644 index 000000000..6b03e14f9 --- /dev/null +++ b/tests/ui/issues/issue-24589.rs @@ -0,0 +1,17 @@ +// run-pass +pub struct _X([u8]); + +impl std::ops::Deref for _X { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + &self.0 + } +} + +pub fn _g(x: &_X) -> &[u8] { + x +} + +fn main() { +} diff --git a/tests/ui/issues/issue-2463.rs b/tests/ui/issues/issue-2463.rs new file mode 100644 index 000000000..d24a47c53 --- /dev/null +++ b/tests/ui/issues/issue-2463.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Pair { f: isize, g: isize } + +pub fn main() { + + let x = Pair { + f: 0, + g: 0, + }; + + let _y = Pair { + f: 1, + g: 1, + .. x + }; + + let _z = Pair { + f: 1, + .. x + }; + +} diff --git a/tests/ui/issues/issue-24682.rs b/tests/ui/issues/issue-24682.rs new file mode 100644 index 000000000..0d1ab7341 --- /dev/null +++ b/tests/ui/issues/issue-24682.rs @@ -0,0 +1,21 @@ +trait A: Sized { + type N; + fn x() -> + Self< + N= //~ ERROR associated type bindings are not allowed here + Self::N> { + loop {} + } + fn y(&self) -> + std + //~ ERROR associated type bindings are not allowed here + ::option::Option<()> + { None } + fn z(&self) -> + u32 //~ ERROR associated type bindings are not allowed here + { 42 } + +} + +fn main() { +} diff --git a/tests/ui/issues/issue-24682.stderr b/tests/ui/issues/issue-24682.stderr new file mode 100644 index 000000000..e1943bf4d --- /dev/null +++ b/tests/ui/issues/issue-24682.stderr @@ -0,0 +1,22 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-24682.rs:5:11 + | +LL | / N= +LL | | Self::N> { + | |_________________^ associated type not allowed here + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-24682.rs:11:13 + | +LL | + | ^^^^ associated type not allowed here + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-24682.rs:15:13 + | +LL | u32 + | ^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs b/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs new file mode 100644 index 000000000..5b1b1389c --- /dev/null +++ b/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs @@ -0,0 +1,10 @@ +#![crate_type="lib"] + +// This is a file that pulls in a separate file as a submodule, where +// that separate file has many multi-byte characters, to try to +// encourage the compiler to trip on them. + +#[path = "issue-24687-mbcs-in-comments.rs"] +mod issue_24687_mbcs_in_comments; + +pub use issue_24687_mbcs_in_comments::D; diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs b/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs new file mode 100644 index 000000000..215145a64 --- /dev/null +++ b/tests/ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs @@ -0,0 +1,27 @@ +use std::fmt; + +// This ia file with many multi-byte characters, to try to encourage +// the compiler to trip on them. The Drop implementation below will +// need to have its source location embedded into the debug info for +// the output file. + +// αααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααααα +// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ +// γγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγγ +// δδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδδ +// εεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεεε + +// ζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζζ +// ηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηηη +// θθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθθ +// ιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιιι +// κκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκκ + +pub struct D(pub X); + +impl Drop for D { + fn drop(&mut self) { + // λλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλλ + println!("Dropping D({:?})", self.0); + } +} diff --git a/tests/ui/issues/issue-24687-embed-debuginfo/main.rs b/tests/ui/issues/issue-24687-embed-debuginfo/main.rs new file mode 100644 index 000000000..f08bcdfe6 --- /dev/null +++ b/tests/ui/issues/issue-24687-embed-debuginfo/main.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:issue-24687-lib.rs +// compile-flags:-g +// ignore-asmjs wasm2js does not support source maps yet + +extern crate issue_24687_lib as d; + +fn main() { + // Create a `D`, which has a destructor whose body will be codegen'ed + // into the generated code here, and thus the local debuginfo will + // need references into the original source locations from + // `importer` above. + let _d = d::D("Hi"); +} diff --git a/tests/ui/issues/issue-2470-bounds-check-overflow.rs b/tests/ui/issues/issue-2470-bounds-check-overflow.rs new file mode 100644 index 000000000..f0e8e185e --- /dev/null +++ b/tests/ui/issues/issue-2470-bounds-check-overflow.rs @@ -0,0 +1,27 @@ +// run-fail +// error-pattern:index out of bounds +// ignore-emscripten no processes + +use std::mem; + +fn main() { + + // This should cause a bounds-check panic, but may not if we do our + // bounds checking by comparing the scaled index to the vector's + // address-bounds, since we've scaled the index to wrap around to the + // address of the 0th cell in the array (even though the index is + // huge). + + let x = vec![1_usize, 2_usize, 3_usize]; + + let base = x.as_ptr() as usize; + let idx = base / mem::size_of::(); + println!("ov1 base = 0x{:x}", base); + println!("ov1 idx = 0x{:x}", idx); + println!("ov1 sizeof::() = 0x{:x}", mem::size_of::()); + println!("ov1 idx * sizeof::() = 0x{:x}", + idx * mem::size_of::()); + + // This should panic. + println!("ov1 0x{:x}", x[idx]); +} diff --git a/tests/ui/issues/issue-2472.rs b/tests/ui/issues/issue-2472.rs new file mode 100644 index 000000000..c790bc2d0 --- /dev/null +++ b/tests/ui/issues/issue-2472.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:issue-2472-b.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_2472_b; + +use issue_2472_b::{S, T}; + +pub fn main() { + let s = S(()); + s.foo(); + s.bar(); +} diff --git a/tests/ui/issues/issue-24779.rs b/tests/ui/issues/issue-24779.rs new file mode 100644 index 000000000..f1283d0dc --- /dev/null +++ b/tests/ui/issues/issue-24779.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() { + assert_eq!((||||42)()(), 42); +} diff --git a/tests/ui/issues/issue-24819.rs b/tests/ui/issues/issue-24819.rs new file mode 100644 index 000000000..59c3f2cd1 --- /dev/null +++ b/tests/ui/issues/issue-24819.rs @@ -0,0 +1,11 @@ +use std::collections::HashSet; + +fn main() { + let mut v = Vec::new(); + foo(&mut v); + //~^ ERROR mismatched types + //~| expected struct `HashSet`, found struct `Vec` +} + +fn foo(h: &mut HashSet) { +} diff --git a/tests/ui/issues/issue-24819.stderr b/tests/ui/issues/issue-24819.stderr new file mode 100644 index 000000000..982a11fef --- /dev/null +++ b/tests/ui/issues/issue-24819.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-24819.rs:5:9 + | +LL | foo(&mut v); + | --- ^^^^^^ expected struct `HashSet`, found struct `Vec` + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut HashSet` + found mutable reference `&mut Vec<_>` +note: function defined here + --> $DIR/issue-24819.rs:10:4 + | +LL | fn foo(h: &mut HashSet) { + | ^^^ -------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-2487-a.rs b/tests/ui/issues/issue-2487-a.rs new file mode 100644 index 000000000..fe12dad74 --- /dev/null +++ b/tests/ui/issues/issue-2487-a.rs @@ -0,0 +1,32 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct socket { + sock: isize, + +} + +impl Drop for socket { + fn drop(&mut self) {} +} + +impl socket { + pub fn set_identity(&self) { + closure(|| setsockopt_bytes(self.sock.clone())) + } +} + +fn socket() -> socket { + socket { + sock: 1 + } +} + +fn closure(f: F) where F: FnOnce() { f() } + +fn setsockopt_bytes(_sock: isize) { } + +pub fn main() {} diff --git a/tests/ui/issues/issue-24945-repeat-dash-opts.rs b/tests/ui/issues/issue-24945-repeat-dash-opts.rs new file mode 100644 index 000000000..0f92fc2f7 --- /dev/null +++ b/tests/ui/issues/issue-24945-repeat-dash-opts.rs @@ -0,0 +1,10 @@ +// run-pass +// This test is just checking that we continue to accept `-g -g -O -O` +// as options to the compiler. + +// compile-flags:-g -g -O -O +// ignore-asmjs wasm2js does not support source maps yet + +fn main() { + assert_eq!(1, 1); +} diff --git a/tests/ui/issues/issue-24947.rs b/tests/ui/issues/issue-24947.rs new file mode 100644 index 000000000..23705b4c9 --- /dev/null +++ b/tests/ui/issues/issue-24947.rs @@ -0,0 +1,25 @@ +// run-pass +// #24947 ICE using a trait-associated const in an array size + + +struct Foo; + +impl Foo { + const SIZE: usize = 8; +} + +trait Bar { + const BAR_SIZE: usize; +} + +impl Bar for Foo { + const BAR_SIZE: usize = 12; +} + +#[allow(unused_variables)] +fn main() { + let w: [u8; 12] = [0u8; ::BAR_SIZE]; + let x: [u8; 12] = [0u8; ::BAR_SIZE]; + let y: [u8; 8] = [0u8; ::SIZE]; + let z: [u8; 8] = [0u8; Foo::SIZE]; +} diff --git a/tests/ui/issues/issue-24954.rs b/tests/ui/issues/issue-24954.rs new file mode 100644 index 000000000..0177dd4ea --- /dev/null +++ b/tests/ui/issues/issue-24954.rs @@ -0,0 +1,13 @@ +// run-pass +macro_rules! foo { + ($y:expr) => ({ + $y = 2; + }) +} + +#[allow(unused_variables)] +#[allow(unused_assignments)] +fn main() { + let mut x = 1; + foo!(x); +} diff --git a/tests/ui/issues/issue-2502.rs b/tests/ui/issues/issue-2502.rs new file mode 100644 index 000000000..631510024 --- /dev/null +++ b/tests/ui/issues/issue-2502.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +// pretty-expanded FIXME #23616 + +struct font<'a> { + fontbuf: &'a Vec , +} + +impl<'a> font<'a> { + pub fn buf(&self) -> &'a Vec { + self.fontbuf + } +} + +fn font(fontbuf: &Vec ) -> font { + font { + fontbuf: fontbuf + } +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-25076.rs b/tests/ui/issues/issue-25076.rs new file mode 100644 index 000000000..6c5a55392 --- /dev/null +++ b/tests/ui/issues/issue-25076.rs @@ -0,0 +1,11 @@ +struct S; + +trait InOut { type Out; } + +fn do_fold>(init: B, f: F) {} + +fn bot() -> T { loop {} } + +fn main() { + do_fold(bot(), ()); //~ ERROR `(): InOut<_>` is not satisfied +} diff --git a/tests/ui/issues/issue-25076.stderr b/tests/ui/issues/issue-25076.stderr new file mode 100644 index 000000000..159cc484c --- /dev/null +++ b/tests/ui/issues/issue-25076.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `(): InOut<_>` is not satisfied + --> $DIR/issue-25076.rs:10:20 + | +LL | do_fold(bot(), ()); + | ------- ^^ the trait `InOut<_>` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_fold` + --> $DIR/issue-25076.rs:5:18 + | +LL | fn do_fold>(init: B, f: F) {} + | ^^^^^^^^^^^^^^^ required by this bound in `do_fold` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-25089.rs b/tests/ui/issues/issue-25089.rs new file mode 100644 index 000000000..c988f8f55 --- /dev/null +++ b/tests/ui/issues/issue-25089.rs @@ -0,0 +1,34 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +use std::thread; + +struct Foo(#[allow(unused_tuple_struct_fields)] i32); + +impl Drop for Foo { + fn drop(&mut self) { + static mut DROPPED: bool = false; + unsafe { + assert!(!DROPPED); + DROPPED = true; + } + } +} + +struct Empty; + +fn empty() -> Empty { Empty } + +fn should_panic(_: Foo, _: Empty) { + panic!("test panic"); +} + +fn test() { + should_panic(Foo(1), empty()); +} + +fn main() { + let ret = thread::spawn(test).join(); + assert!(ret.is_err()); +} diff --git a/tests/ui/issues/issue-25145.rs b/tests/ui/issues/issue-25145.rs new file mode 100644 index 000000000..f5ae28fbb --- /dev/null +++ b/tests/ui/issues/issue-25145.rs @@ -0,0 +1,13 @@ +// run-pass + +struct S; + +impl S { + const N: usize = 3; +} + +static STUFF: [u8; S::N] = [0; S::N]; + +fn main() { + assert_eq!(STUFF, [0; 3]); +} diff --git a/tests/ui/issues/issue-25180.rs b/tests/ui/issues/issue-25180.rs new file mode 100644 index 000000000..29dc07f49 --- /dev/null +++ b/tests/ui/issues/issue-25180.rs @@ -0,0 +1,7 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +const x: &'static dyn Fn() = &|| println!("ICE here"); + +fn main() {} diff --git a/tests/ui/issues/issue-25185.rs b/tests/ui/issues/issue-25185.rs new file mode 100644 index 000000000..383c9a1e9 --- /dev/null +++ b/tests/ui/issues/issue-25185.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:issue-25185-1.rs +// aux-build:issue-25185-2.rs +// ignore-wasm32-bare no libc for ffi testing + +extern crate issue_25185_2; + +fn main() { + let x = unsafe { + issue_25185_2::rust_dbg_extern_identity_u32(1) + }; + assert_eq!(x, 1); +} diff --git a/tests/ui/issues/issue-2526-a.rs b/tests/ui/issues/issue-2526-a.rs new file mode 100644 index 000000000..f3fdc0bd3 --- /dev/null +++ b/tests/ui/issues/issue-2526-a.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-2526.rs + +// pretty-expanded FIXME #23616 + +#![allow(unused_imports)] + +extern crate issue_2526; +use issue_2526::*; + +pub fn main() {} diff --git a/tests/ui/issues/issue-25279.rs b/tests/ui/issues/issue-25279.rs new file mode 100644 index 000000000..fdc516d37 --- /dev/null +++ b/tests/ui/issues/issue-25279.rs @@ -0,0 +1,16 @@ +// run-pass +struct S<'a>(&'a ()); + +impl<'a> S<'a> { + fn foo(self) -> &'a () { + ::bar(self) + } + + fn bar(self) -> &'a () { + self.0 + } +} + +fn main() { + S(&()).foo(); +} diff --git a/tests/ui/issues/issue-25343.rs b/tests/ui/issues/issue-25343.rs new file mode 100644 index 000000000..95a0bd915 --- /dev/null +++ b/tests/ui/issues/issue-25343.rs @@ -0,0 +1,22 @@ +// run-pass +#[allow(unused)] +fn main() { + || { + 'label: loop { + } + }; + + // More cases added from issue 31754 + + 'label2: loop { + break; + } + + let closure = || { + 'label2: loop {} + }; + + fn inner_fn() { + 'label2: loop {} + } +} diff --git a/tests/ui/issues/issue-25368.rs b/tests/ui/issues/issue-25368.rs new file mode 100644 index 000000000..4be83457f --- /dev/null +++ b/tests/ui/issues/issue-25368.rs @@ -0,0 +1,14 @@ +use std::sync::mpsc::channel; +use std::thread::spawn; +use std::marker::PhantomData; + +struct Foo {foo: PhantomData} + +fn main() { + let (tx, rx) = + channel(); + spawn(move || { + tx.send(Foo{ foo: PhantomData }); + //~^ ERROR type annotations needed + }); +} diff --git a/tests/ui/issues/issue-25368.stderr b/tests/ui/issues/issue-25368.stderr new file mode 100644 index 000000000..e6ed3aac7 --- /dev/null +++ b/tests/ui/issues/issue-25368.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-25368.rs:11:27 + | +LL | tx.send(Foo{ foo: PhantomData }); + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` + | +help: consider specifying the generic argument + | +LL | tx.send(Foo{ foo: PhantomData:: }); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-25386.rs b/tests/ui/issues/issue-25386.rs new file mode 100644 index 000000000..b26cc7768 --- /dev/null +++ b/tests/ui/issues/issue-25386.rs @@ -0,0 +1,27 @@ +mod stuff { + pub struct Item { + c_object: Box, + } + pub struct CObj { + name: Option, + } + impl Item { + pub fn new() -> Item { + Item { + c_object: Box::new(CObj { name: None }), + } + } + } +} + +macro_rules! check_ptr_exist { + ($var:expr, $member:ident) => ( + (*$var.c_object).$member.is_some() + //~^ ERROR field `c_object` of struct `Item` is private + ); +} + +fn main() { + let item = stuff::Item::new(); + println!("{}", check_ptr_exist!(item, name)); +} diff --git a/tests/ui/issues/issue-25386.stderr b/tests/ui/issues/issue-25386.stderr new file mode 100644 index 000000000..727b96908 --- /dev/null +++ b/tests/ui/issues/issue-25386.stderr @@ -0,0 +1,14 @@ +error[E0616]: field `c_object` of struct `Item` is private + --> $DIR/issue-25386.rs:19:16 + | +LL | (*$var.c_object).$member.is_some() + | ^^^^^^^^ private field +... +LL | println!("{}", check_ptr_exist!(item, name)); + | ---------------------------- in this macro invocation + | + = note: this error originates in the macro `check_ptr_exist` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/issues/issue-25394.rs b/tests/ui/issues/issue-25394.rs new file mode 100644 index 000000000..2f0ae19fc --- /dev/null +++ b/tests/ui/issues/issue-25394.rs @@ -0,0 +1,6 @@ +// check-pass +#![allow(dead_code)] +#[derive(Debug)] +struct Row([T]); + +fn main() {} diff --git a/tests/ui/issues/issue-25439.rs b/tests/ui/issues/issue-25439.rs new file mode 100644 index 000000000..4f73ff3e3 --- /dev/null +++ b/tests/ui/issues/issue-25439.rs @@ -0,0 +1,9 @@ +struct Helper<'a, F: 'a>(&'a F); + +fn fix(f: F) -> i32 where F: Fn(Helper, i32) -> i32 { + f(Helper(&f), 8) +} + +fn main() { + fix(|_, x| x); //~ ERROR closure/generator type that references itself [E0644] +} diff --git a/tests/ui/issues/issue-25439.stderr b/tests/ui/issues/issue-25439.stderr new file mode 100644 index 000000000..dadae23fd --- /dev/null +++ b/tests/ui/issues/issue-25439.stderr @@ -0,0 +1,19 @@ +error[E0644]: closure/generator type that references itself + --> $DIR/issue-25439.rs:8:9 + | +LL | fix(|_, x| x); + | ^^^^^^ cyclic type of infinite size + | + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see issue #46062 + for more information +note: required by a bound in `fix` + --> $DIR/issue-25439.rs:3:33 + | +LL | fn fix(f: F) -> i32 where F: Fn(Helper, i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fix` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0644`. diff --git a/tests/ui/issues/issue-25467.rs b/tests/ui/issues/issue-25467.rs new file mode 100644 index 000000000..31ac5f0f3 --- /dev/null +++ b/tests/ui/issues/issue-25467.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(unused_variables)] +// aux-build:issue-25467.rs + +pub type Issue25467BarT = (); +pub type Issue25467FooT = (); + +extern crate issue_25467 as aux; + +fn main() { + let o: aux::Object = None; +} diff --git a/tests/ui/issues/issue-25497.rs b/tests/ui/issues/issue-25497.rs new file mode 100644 index 000000000..25f5ab90f --- /dev/null +++ b/tests/ui/issues/issue-25497.rs @@ -0,0 +1,19 @@ +// run-pass +#[derive(Clone, Debug, PartialEq)] +enum Expression { + Dummy, + Add(Box), +} + +use Expression::*; + +fn simplify(exp: Expression) -> Expression { + match exp { + Add(n) => *n.clone(), + _ => Dummy + } +} + +fn main() { + assert_eq!(simplify(Add(Box::new(Dummy))), Dummy); +} diff --git a/tests/ui/issues/issue-2550.rs b/tests/ui/issues/issue-2550.rs new file mode 100644 index 000000000..04ec66b80 --- /dev/null +++ b/tests/ui/issues/issue-2550.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// pretty-expanded FIXME #23616 + +struct C { + x: usize, +} + +fn C(x: usize) -> C { + C { + x: x + } +} + +fn f(_x: T) { +} + +pub fn main() { + f(C(1)); +} diff --git a/tests/ui/issues/issue-25515.rs b/tests/ui/issues/issue-25515.rs new file mode 100644 index 000000000..e7b9ea3ac --- /dev/null +++ b/tests/ui/issues/issue-25515.rs @@ -0,0 +1,20 @@ +// run-pass +use std::rc::Rc; + +struct Foo<'r>(&'r mut i32); + +impl<'r> Drop for Foo<'r> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +fn main() { + let mut drops = 0; + + { + let _: Rc = Rc::new(Foo(&mut drops)); + } + + assert_eq!(1, drops); +} diff --git a/tests/ui/issues/issue-25549-multiple-drop.rs b/tests/ui/issues/issue-25549-multiple-drop.rs new file mode 100644 index 000000000..25a2da707 --- /dev/null +++ b/tests/ui/issues/issue-25549-multiple-drop.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_variables)] +struct Foo<'r>(&'r mut i32); + +impl<'r> Drop for Foo<'r> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +trait Trait {} +impl<'r> Trait for Foo<'r> {} + +struct Holder(T); + +fn main() { + let mut drops = 0; + + { + let y = &Holder([Foo(&mut drops)]) as &Holder<[Foo]>; + // this used to cause an extra drop of the Foo instance + let x = &y.0; + } + assert_eq!(1, drops); + + drops = 0; + { + let y = &Holder(Foo(&mut drops)) as &Holder; + // this used to cause an extra drop of the Foo instance + let x = &y.0; + } + assert_eq!(1, drops); +} diff --git a/tests/ui/issues/issue-25579.rs b/tests/ui/issues/issue-25579.rs new file mode 100644 index 000000000..5f5a0f4d2 --- /dev/null +++ b/tests/ui/issues/issue-25579.rs @@ -0,0 +1,20 @@ +// check-pass + +enum Sexpression { + Num(()), + Cons(&'static mut Sexpression) +} + +fn causes_error_in_ast(mut l: &mut Sexpression) { + loop { match l { + &mut Sexpression::Num(ref mut n) => {}, + &mut Sexpression::Cons(ref mut expr) => { + l = &mut **expr; + } + }} +} + + +fn main() { + causes_error_in_ast(&mut Sexpression::Num(())); +} diff --git a/tests/ui/issues/issue-25679.rs b/tests/ui/issues/issue-25679.rs new file mode 100644 index 000000000..b548da988 --- /dev/null +++ b/tests/ui/issues/issue-25679.rs @@ -0,0 +1,20 @@ +// run-pass +trait Device { + type Resources; +} +#[allow(unused_tuple_struct_fields)] +struct Foo(D, R); + +impl Foo { + fn present(&self) {} +} + +struct Res; +struct Dev; + +impl Device for Dev { type Resources = Res; } + +fn main() { + let foo = Foo(Dev, Res); + foo.present(); +} diff --git a/tests/ui/issues/issue-25693.rs b/tests/ui/issues/issue-25693.rs new file mode 100644 index 000000000..9af0ba100 --- /dev/null +++ b/tests/ui/issues/issue-25693.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_variables)] +pub trait Parameters { type SelfRef; } + +struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> } +struct BP; + +impl<'a> Parameters for RP<'a> { type SelfRef = &'a X>; } +impl Parameters for BP { type SelfRef = Box>; } + +pub struct Y; +pub enum X { + Nothing, + SameAgain(P::SelfRef, Y) +} + +fn main() { + let bnil: Box> = Box::new(X::Nothing); + let bx: Box> = Box::new(X::SameAgain(bnil, Y)); + let rnil: X = X::Nothing; + let rx: X = X::SameAgain(&rnil, Y); +} diff --git a/tests/ui/issues/issue-25746-bool-transmute.rs b/tests/ui/issues/issue-25746-bool-transmute.rs new file mode 100644 index 000000000..bc2f4a7c1 --- /dev/null +++ b/tests/ui/issues/issue-25746-bool-transmute.rs @@ -0,0 +1,11 @@ +// run-pass +use std::mem::transmute; + +fn main() { + unsafe { + let _: i8 = transmute(false); + let _: i8 = transmute(true); + let _: bool = transmute(0u8); + let _: bool = transmute(1u8); + } +} diff --git a/tests/ui/issues/issue-25757.rs b/tests/ui/issues/issue-25757.rs new file mode 100644 index 000000000..ec1864d7d --- /dev/null +++ b/tests/ui/issues/issue-25757.rs @@ -0,0 +1,18 @@ +// run-pass +struct Foo { + a: u32 +} + +impl Foo { + fn x(&mut self) { + self.a = 5; + } +} + +const FUNC: &'static dyn Fn(&mut Foo) -> () = &Foo::x; + +fn main() { + let mut foo = Foo { a: 137 }; + FUNC(&mut foo); + assert_eq!(foo.a, 5); +} diff --git a/tests/ui/issues/issue-25810.rs b/tests/ui/issues/issue-25810.rs new file mode 100644 index 000000000..f32216f32 --- /dev/null +++ b/tests/ui/issues/issue-25810.rs @@ -0,0 +1,28 @@ +// run-pass +fn main() { + let x = X(15); + let y = x.foo(); + println!("{:?}",y); +} + +trait Foo + where for<'a> &'a Self: Bar +{ + fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output; +} + +trait Bar { + type Output; +} + +struct X(i32); + +impl<'a> Bar for &'a X { + type Output = &'a i32; +} + +impl Foo for X { + fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output { + &self.0 + } +} diff --git a/tests/ui/issues/issue-2590.rs b/tests/ui/issues/issue-2590.rs new file mode 100644 index 000000000..a9a0e5ca4 --- /dev/null +++ b/tests/ui/issues/issue-2590.rs @@ -0,0 +1,15 @@ +struct Parser { + tokens: Vec , +} + +trait Parse { + fn parse(&self) -> Vec ; +} + +impl Parse for Parser { + fn parse(&self) -> Vec { + self.tokens //~ ERROR cannot move out + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-2590.stderr b/tests/ui/issues/issue-2590.stderr new file mode 100644 index 000000000..6aacd563a --- /dev/null +++ b/tests/ui/issues/issue-2590.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `self.tokens` which is behind a shared reference + --> $DIR/issue-2590.rs:11:9 + | +LL | self.tokens + | ^^^^^^^^^^^ move occurs because `self.tokens` has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-25901.rs b/tests/ui/issues/issue-25901.rs new file mode 100644 index 000000000..1f7b341a9 --- /dev/null +++ b/tests/ui/issues/issue-25901.rs @@ -0,0 +1,14 @@ +struct A; +struct B; + +static S: &'static B = &A; +//~^ ERROR the trait bound + +use std::ops::Deref; + +impl Deref for A { + type Target = B; + fn deref(&self)->&B { static B_: B = B; &B_ } +} + +fn main(){} diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/issues/issue-25901.stderr new file mode 100644 index 000000000..b9cac3222 --- /dev/null +++ b/tests/ui/issues/issue-25901.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `A: Deref` is not satisfied + --> $DIR/issue-25901.rs:4:24 + | +LL | static S: &'static B = &A; + | ^^ the trait `~const Deref` is not implemented for `A` + | +note: the trait `Deref` is implemented for `A`, but that implementation is not `const` + --> $DIR/issue-25901.rs:4:24 + | +LL | static S: &'static B = &A; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-26056.rs b/tests/ui/issues/issue-26056.rs new file mode 100644 index 000000000..99d43ec79 --- /dev/null +++ b/tests/ui/issues/issue-26056.rs @@ -0,0 +1,22 @@ +trait MapLookup { + type MapValue; +} + +impl MapLookup for K { + type MapValue = K; +} + +trait Map: MapLookup<::Key> { + type Key; +} + +impl Map for K { + type Key = K; +} + + +fn main() { + let _ = &() + as &dyn Map; + //~^ ERROR E0038 +} diff --git a/tests/ui/issues/issue-26056.stderr b/tests/ui/issues/issue-26056.stderr new file mode 100644 index 000000000..2c873243f --- /dev/null +++ b/tests/ui/issues/issue-26056.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Map` cannot be made into an object + --> $DIR/issue-26056.rs:20:13 + | +LL | as &dyn Map; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-26056.rs:9:12 + | +LL | trait Map: MapLookup<::Key> { + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-26093.rs b/tests/ui/issues/issue-26093.rs new file mode 100644 index 000000000..c838515ca --- /dev/null +++ b/tests/ui/issues/issue-26093.rs @@ -0,0 +1,12 @@ +macro_rules! not_a_place { + ($thing:expr) => { + $thing = 42; + //~^ ERROR invalid left-hand side of assignment + $thing += 42; + //~^ ERROR invalid left-hand side of assignment + } +} + +fn main() { + not_a_place!(99); +} diff --git a/tests/ui/issues/issue-26093.stderr b/tests/ui/issues/issue-26093.stderr new file mode 100644 index 000000000..1a08d0fef --- /dev/null +++ b/tests/ui/issues/issue-26093.stderr @@ -0,0 +1,32 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-26093.rs:3:16 + | +LL | $thing = 42; + | ^ +... +LL | not_a_place!(99); + | ---------------- + | | | + | | cannot assign to this expression + | in this macro invocation + | + = note: this error originates in the macro `not_a_place` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0067]: invalid left-hand side of assignment + --> $DIR/issue-26093.rs:5:16 + | +LL | $thing += 42; + | ^^ +... +LL | not_a_place!(99); + | ---------------- + | | | + | | cannot assign to this expression + | in this macro invocation + | + = note: this error originates in the macro `not_a_place` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0067, E0070. +For more information about an error, try `rustc --explain E0067`. diff --git a/tests/ui/issues/issue-26094.rs b/tests/ui/issues/issue-26094.rs new file mode 100644 index 000000000..d3d670aa9 --- /dev/null +++ b/tests/ui/issues/issue-26094.rs @@ -0,0 +1,13 @@ +macro_rules! some_macro { + ($other: expr) => ({ + $other(None) //~ NOTE argument of type `Option<_>` unexpected + }) +} + +fn some_function() {} //~ NOTE defined here + +fn main() { + some_macro!(some_function); + //~^ ERROR function takes 0 arguments but 1 argument was supplied + //~| NOTE in this expansion of some_macro! +} diff --git a/tests/ui/issues/issue-26094.stderr b/tests/ui/issues/issue-26094.stderr new file mode 100644 index 000000000..881a6e538 --- /dev/null +++ b/tests/ui/issues/issue-26094.stderr @@ -0,0 +1,22 @@ +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/issue-26094.rs:10:17 + | +LL | $other(None) + | ---- argument of type `Option<_>` unexpected +... +LL | some_macro!(some_function); + | ^^^^^^^^^^^^^ + | +note: function defined here + --> $DIR/issue-26094.rs:7:4 + | +LL | fn some_function() {} + | ^^^^^^^^^^^^^ +help: remove the extra argument + | +LL | some_function() + | ~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/issues/issue-26095.rs b/tests/ui/issues/issue-26095.rs new file mode 100644 index 000000000..638f8f571 --- /dev/null +++ b/tests/ui/issues/issue-26095.rs @@ -0,0 +1,23 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + + +trait HasNumber { + const Number: usize; +} + +enum One {} +enum Two {} + +enum Foo {} + +impl HasNumber for One { + const Number: usize = 1; +} + +impl HasNumber for Two { + const Number: usize = 2; +} + +fn main() {} diff --git a/tests/ui/issues/issue-2611-3.rs b/tests/ui/issues/issue-2611-3.rs new file mode 100644 index 000000000..a95a748e0 --- /dev/null +++ b/tests/ui/issues/issue-2611-3.rs @@ -0,0 +1,19 @@ +// check-pass +#![allow(dead_code)] +// Tests that impls are allowed to have looser, more permissive bounds +// than the traits require. + + +trait A { + fn b(&self, x: C) -> C; +} + +struct E { + f: isize +} + +impl A for E { + fn b(&self, _x: F) -> F { panic!() } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-26127.rs b/tests/ui/issues/issue-26127.rs new file mode 100644 index 000000000..f3f9c1d9a --- /dev/null +++ b/tests/ui/issues/issue-26127.rs @@ -0,0 +1,12 @@ +// run-pass +trait Tr { type T; } +impl Tr for u8 { type T=(); } +struct S(#[allow(unused_tuple_struct_fields)] I::T); + +fn foo(i: I::T) { + S::(i); +} + +fn main() { + foo::(()); +} diff --git a/tests/ui/issues/issue-26186.rs b/tests/ui/issues/issue-26186.rs new file mode 100644 index 000000000..f93869352 --- /dev/null +++ b/tests/ui/issues/issue-26186.rs @@ -0,0 +1,62 @@ +// check-pass +use std::sync::Mutex; +use std::cell::RefCell; +use std::rc::Rc; +use std::ops::*; + +//eefriedman example +struct S<'a, T:FnMut() + 'static + ?Sized>(&'a mut T); +impl<'a, T:?Sized + FnMut() + 'static> DerefMut for S<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } +} +impl<'a, T:?Sized + FnMut() + 'static> Deref for S<'a, T> { + type Target = dyn FnMut() + 'a; + fn deref(&self) -> &Self::Target { &self.0 } +} + +//Ossipal example +struct FunctionIcon { + get_icon: Mutex u32>>, +} + +impl FunctionIcon { + fn get_icon(&self) -> impl '_ + std::ops::DerefMut u32>> { + self.get_icon.lock().unwrap() + } + + fn load_icon(&self) { + let mut get_icon = self.get_icon(); + let _rgba_icon = (*get_icon)(); + } +} + +//shepmaster example +struct Foo; + +impl Deref for Foo { + type Target = dyn FnMut() + 'static; + fn deref(&self) -> &Self::Target { + unimplemented!() + } +} + +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + unimplemented!() + } +} + +fn main() { + //eefriedman example + let mut f = ||{}; + let mut s = S(&mut f); + s(); + + //Diggsey/Mark-Simulacrum example + let a: Rc> = Rc::new(RefCell::new(||{})); + a.borrow_mut()(); + + //shepmaster example + let mut t = Foo; + t(); +} diff --git a/tests/ui/issues/issue-26205.rs b/tests/ui/issues/issue-26205.rs new file mode 100644 index 000000000..f5f39ded0 --- /dev/null +++ b/tests/ui/issues/issue-26205.rs @@ -0,0 +1,31 @@ +// check-pass +#![allow(dead_code)] +use std::ops::{Deref, DerefMut}; + +struct Foo; + +impl Foo { + fn foo_mut(&mut self) {} +} + +struct Bar(Foo); + +impl Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &self.0 + } +} + +impl DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Foo { + &mut self.0 + } +} + +fn test(mut bar: Box) { + bar.foo_mut(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-26217.rs b/tests/ui/issues/issue-26217.rs new file mode 100644 index 000000000..422625e73 --- /dev/null +++ b/tests/ui/issues/issue-26217.rs @@ -0,0 +1,10 @@ +fn foo() where for<'a> T: 'a {} + +fn bar<'a>() { + foo::<&'a i32>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { + bar(); +} diff --git a/tests/ui/issues/issue-26217.stderr b/tests/ui/issues/issue-26217.stderr new file mode 100644 index 000000000..73c772205 --- /dev/null +++ b/tests/ui/issues/issue-26217.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/issue-26217.rs:4:5 + | +LL | fn bar<'a>() { + | -- lifetime `'a` defined here +LL | foo::<&'a i32>(); + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/issue-26217.rs:1:30 + | +LL | fn foo() where for<'a> T: 'a {} + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-26237.rs b/tests/ui/issues/issue-26237.rs new file mode 100644 index 000000000..71e96677d --- /dev/null +++ b/tests/ui/issues/issue-26237.rs @@ -0,0 +1,12 @@ +macro_rules! macro_panic { + ($not_a_function:expr, $some_argument:ident) => { + $not_a_function($some_argument) + } +} + +fn main() { + let mut value_a = 0; + let mut value_b = 0; + macro_panic!(value_a, value_b); + //~^ ERROR expected function, found `{integer}` +} diff --git a/tests/ui/issues/issue-26237.stderr b/tests/ui/issues/issue-26237.stderr new file mode 100644 index 000000000..91d28a5e1 --- /dev/null +++ b/tests/ui/issues/issue-26237.stderr @@ -0,0 +1,15 @@ +error[E0618]: expected function, found `{integer}` + --> $DIR/issue-26237.rs:10:18 + | +LL | $not_a_function($some_argument) + | ------------------------------- call expression requires function +... +LL | let mut value_a = 0; + | ----------- `value_a` has type `{integer}` +LL | let mut value_b = 0; +LL | macro_panic!(value_a, value_b); + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-26262.rs b/tests/ui/issues/issue-26262.rs new file mode 100644 index 000000000..41135db91 --- /dev/null +++ b/tests/ui/issues/issue-26262.rs @@ -0,0 +1,22 @@ +// Check that projections don't count as constraining type parameters. + +struct S(T); + +trait Tr { type Assoc; fn test(); } + +impl S { +//~^ ERROR the type parameter `T` is not constrained + fn foo(self, _: T) { + T::test(); + } +} + +trait Trait1 { type Bar; } +trait Trait2<'x> { type Foo; } + +impl<'a,T: Trait2<'a>> Trait1<>::Foo> for T { +//~^ ERROR the lifetime parameter `'a` is not constrained + type Bar = &'a (); +} + +fn main() {} diff --git a/tests/ui/issues/issue-26262.stderr b/tests/ui/issues/issue-26262.stderr new file mode 100644 index 000000000..90e2d0d93 --- /dev/null +++ b/tests/ui/issues/issue-26262.stderr @@ -0,0 +1,15 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-26262.rs:7:6 + | +LL | impl S { + | ^ unconstrained type parameter + +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-26262.rs:17:6 + | +LL | impl<'a,T: Trait2<'a>> Trait1<>::Foo> for T { + | ^^ unconstrained lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-2631-b.rs b/tests/ui/issues/issue-2631-b.rs new file mode 100644 index 000000000..c7f6728e3 --- /dev/null +++ b/tests/ui/issues/issue-2631-b.rs @@ -0,0 +1,17 @@ +// run-pass + +// aux-build:issue-2631-a.rs + +extern crate req; + +use req::request; +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + +pub fn main() { + let v = vec![Rc::new("hi".to_string())]; + let mut m: req::header_map = HashMap::new(); + m.insert("METHOD".to_string(), Rc::new(RefCell::new(v))); + request::(&m); +} diff --git a/tests/ui/issues/issue-2642.rs b/tests/ui/issues/issue-2642.rs new file mode 100644 index 000000000..95c563225 --- /dev/null +++ b/tests/ui/issues/issue-2642.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn f() { + let _x: usize = loop { loop { break; } }; +} + +pub fn main() { +} diff --git a/tests/ui/issues/issue-26468.rs b/tests/ui/issues/issue-26468.rs new file mode 100644 index 000000000..71cc90e8b --- /dev/null +++ b/tests/ui/issues/issue-26468.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] + +enum FooMode { + Check = 0x1001, +} + +enum BarMode { + Check = 0x2001, +} + +enum Mode { + Foo(FooMode), + Bar(BarMode), +} + +#[inline(never)] +fn broken(mode: &Mode) -> u32 { + for _ in 0..1 { + if let Mode::Foo(FooMode::Check) = *mode { return 17 } + if let Mode::Bar(BarMode::Check) = *mode { return 19 } + } + return 42; +} + +fn main() { + let mode = Mode::Bar(BarMode::Check); + assert_eq!(broken(&mode), 19); +} diff --git a/tests/ui/issues/issue-26472.rs b/tests/ui/issues/issue-26472.rs new file mode 100644 index 000000000..b100c59ad --- /dev/null +++ b/tests/ui/issues/issue-26472.rs @@ -0,0 +1,13 @@ +mod sub { + pub struct S { len: usize } + impl S { + pub fn new() -> S { S { len: 0 } } + pub fn len(&self) -> usize { self.len } + } +} + +fn main() { + let s = sub::S::new(); + let v = s.len; //~ ERROR field `len` of struct `S` is private + s.len = v; //~ ERROR field `len` of struct `S` is private +} diff --git a/tests/ui/issues/issue-26472.stderr b/tests/ui/issues/issue-26472.stderr new file mode 100644 index 000000000..d7134bff1 --- /dev/null +++ b/tests/ui/issues/issue-26472.stderr @@ -0,0 +1,20 @@ +error[E0616]: field `len` of struct `S` is private + --> $DIR/issue-26472.rs:11:15 + | +LL | let v = s.len; + | ^^^ private field + | +help: a method `len` also exists, call it with parentheses + | +LL | let v = s.len(); + | ++ + +error[E0616]: field `len` of struct `S` is private + --> $DIR/issue-26472.rs:12:7 + | +LL | s.len = v; + | ^^^ private field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/issues/issue-26484.rs b/tests/ui/issues/issue-26484.rs new file mode 100644 index 000000000..2a8750d3e --- /dev/null +++ b/tests/ui/issues/issue-26484.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags:-g +// ignore-asmjs wasm2js does not support source maps yet + +fn helper bool>(_f: F) { + print!(""); +} + +fn main() { + let cond = 0; + helper(|v| v == cond) +} diff --git a/tests/ui/issues/issue-26614.rs b/tests/ui/issues/issue-26614.rs new file mode 100644 index 000000000..b8ebbdc5a --- /dev/null +++ b/tests/ui/issues/issue-26614.rs @@ -0,0 +1,14 @@ +// check-pass + +trait Mirror { + type It; +} + +impl Mirror for T { + type It = Self; +} + +fn main() { + let c: ::It = 5; + const CCCC: ::It = 5; +} diff --git a/tests/ui/issues/issue-26619.rs b/tests/ui/issues/issue-26619.rs new file mode 100644 index 000000000..b9d34b055 --- /dev/null +++ b/tests/ui/issues/issue-26619.rs @@ -0,0 +1,22 @@ +pub struct History<'a> { pub _s: &'a str } + +impl<'a> History<'a> { + pub fn get_page(&self) { + for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) { + //~^ ERROR cannot return value referencing function parameter + println!("{:?}", s); + } + } + + fn make_entry(&self, s: &'a String) -> Option<&str> { + let parts: Vec<_> = s.split('|').collect(); + println!("{:?} -> {:?}", s, parts); + + if let [commit, ..] = &parts[..] { Some(commit) } else { None } + } +} + +fn main() { + let h = History{ _s: "" }; + h.get_page(); +} diff --git a/tests/ui/issues/issue-26619.stderr b/tests/ui/issues/issue-26619.stderr new file mode 100644 index 000000000..1282fd7d3 --- /dev/null +++ b/tests/ui/issues/issue-26619.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing function parameter + --> $DIR/issue-26619.rs:5:76 + | +LL | for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) { + | -------- ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function + | | + | function parameter borrowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-26641.rs b/tests/ui/issues/issue-26641.rs new file mode 100644 index 000000000..e08edd0b5 --- /dev/null +++ b/tests/ui/issues/issue-26641.rs @@ -0,0 +1,6 @@ +// run-pass +struct Parser<'a>(#[allow(unused_tuple_struct_fields)] Box); + +fn main() { + let _x = Parser(Box::new(|_|{})); +} diff --git a/tests/ui/issues/issue-26646.rs b/tests/ui/issues/issue-26646.rs new file mode 100644 index 000000000..86e4bd7e8 --- /dev/null +++ b/tests/ui/issues/issue-26646.rs @@ -0,0 +1,12 @@ +// check-pass +#![deny(unused_attributes)] + +#[repr(C)] +#[repr(packed)] +pub struct Foo; + +#[repr(packed)] +#[repr(C)] +pub struct Bar; + +fn main() { } diff --git a/tests/ui/issues/issue-26655.rs b/tests/ui/issues/issue-26655.rs new file mode 100644 index 000000000..cb386c908 --- /dev/null +++ b/tests/ui/issues/issue-26655.rs @@ -0,0 +1,26 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +// Check that the destructors of simple enums are run on unwinding + +use std::sync::atomic::{Ordering, AtomicUsize}; +use std::thread; + +static LOG: AtomicUsize = AtomicUsize::new(0); + +enum WithDtor { Val } +impl Drop for WithDtor { + fn drop(&mut self) { + LOG.store(LOG.load(Ordering::SeqCst)+1,Ordering::SeqCst); + } +} + +pub fn main() { + thread::spawn(move|| { + let _e: WithDtor = WithDtor::Val; + panic!("fail"); + }).join().unwrap_err(); + + assert_eq!(LOG.load(Ordering::SeqCst), 1); +} diff --git a/tests/ui/issues/issue-26709.rs b/tests/ui/issues/issue-26709.rs new file mode 100644 index 000000000..1bd2651dd --- /dev/null +++ b/tests/ui/issues/issue-26709.rs @@ -0,0 +1,17 @@ +// run-pass +struct Wrapper<'a, T: ?Sized>(&'a mut i32, #[allow(unused_tuple_struct_fields)] T); + +impl<'a, T: ?Sized> Drop for Wrapper<'a, T> { + fn drop(&mut self) { + *self.0 = 432; + } +} + +fn main() { + let mut x = 0; + { + let wrapper = Box::new(Wrapper(&mut x, 123)); + let _: Box> = wrapper; + } + assert_eq!(432, x) +} diff --git a/tests/ui/issues/issue-26802.rs b/tests/ui/issues/issue-26802.rs new file mode 100644 index 000000000..307a67160 --- /dev/null +++ b/tests/ui/issues/issue-26802.rs @@ -0,0 +1,14 @@ +// run-pass +trait Foo<'a> { + fn bar<'b>(&self, x: &'b u8) -> u8 where 'a: 'b { *x+7 } +} + +pub struct FooBar; +impl Foo<'static> for FooBar {} +fn test(foobar: FooBar) -> Box> { + Box::new(foobar) +} + +fn main() { + assert_eq!(test(FooBar).bar(&4), 11); +} diff --git a/tests/ui/issues/issue-26805.rs b/tests/ui/issues/issue-26805.rs new file mode 100644 index 000000000..bcf8a6731 --- /dev/null +++ b/tests/ui/issues/issue-26805.rs @@ -0,0 +1,6 @@ +// run-pass +struct NonOrd; + +fn main() { + let _: Box> = Box::new(vec![NonOrd].into_iter()); +} diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs new file mode 100644 index 000000000..3391ea4b3 --- /dev/null +++ b/tests/ui/issues/issue-26812.rs @@ -0,0 +1,6 @@ +#![feature(default_type_parameter_fallback)] + +fn avg(_: T) {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +fn main() {} diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr new file mode 100644 index 000000000..fd1bbb9c5 --- /dev/null +++ b/tests/ui/issues/issue-26812.stderr @@ -0,0 +1,9 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/issue-26812.rs:3:10 + | +LL | fn avg(_: T) {} + | ^^^^^^^ defaulted generic parameters cannot be forward declared + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/issues/issue-26905-rpass.rs b/tests/ui/issues/issue-26905-rpass.rs new file mode 100644 index 000000000..2d5827f47 --- /dev/null +++ b/tests/ui/issues/issue-26905-rpass.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(unsize, coerce_unsized)] + +// Verfies that PhantomData is ignored for DST coercions + +use std::marker::{Unsize, PhantomData}; +use std::ops::CoerceUnsized; + +struct MyRc { + _ptr: *const T, + _boo: PhantomData, +} + +impl, U: ?Sized> CoerceUnsized> for MyRc{ } + +fn main() { + let data = [1, 2, 3]; + let iter = data.iter(); + let x = MyRc { _ptr: &iter, _boo: PhantomData }; + let _y: MyRc> = x; +} diff --git a/tests/ui/issues/issue-26905.rs b/tests/ui/issues/issue-26905.rs new file mode 100644 index 000000000..4c5c67d58 --- /dev/null +++ b/tests/ui/issues/issue-26905.rs @@ -0,0 +1,23 @@ +#![feature(unsize, coerce_unsized)] + +// Verfies that non-PhantomData ZSTs still cause coercions to fail. +// They might have additional semantics that we don't want to bulldoze. + +use std::marker::{Unsize, PhantomData}; +use std::ops::CoerceUnsized; + +struct NotPhantomData(PhantomData); + +struct MyRc { + _ptr: *const T, + _boo: NotPhantomData, +} + +impl, U: ?Sized> CoerceUnsized> for MyRc{ } //~ERROR + +fn main() { + let data = [1, 2, 3]; + let iter = data.iter(); + let x = MyRc { _ptr: &iter, _boo: NotPhantomData(PhantomData) }; + let _y: MyRc> = x; +} diff --git a/tests/ui/issues/issue-26905.stderr b/tests/ui/issues/issue-26905.stderr new file mode 100644 index 000000000..10dbb7325 --- /dev/null +++ b/tests/ui/issues/issue-26905.stderr @@ -0,0 +1,12 @@ +error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions + --> $DIR/issue-26905.rs:16:40 + | +LL | impl, U: ?Sized> CoerceUnsized> for MyRc{ } + | ^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions + | + = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced + = note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData` to `NotPhantomData`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0375`. diff --git a/tests/ui/issues/issue-26948.rs b/tests/ui/issues/issue-26948.rs new file mode 100644 index 000000000..832c9641d --- /dev/null +++ b/tests/ui/issues/issue-26948.rs @@ -0,0 +1,6 @@ +fn main() { + enum Foo { A { x: u32 } } + let orig = Foo::A { x: 5 }; + Foo::A { x: 6, ..orig }; + //~^ ERROR functional record update syntax requires a struct +} diff --git a/tests/ui/issues/issue-26948.stderr b/tests/ui/issues/issue-26948.stderr new file mode 100644 index 000000000..faede1687 --- /dev/null +++ b/tests/ui/issues/issue-26948.stderr @@ -0,0 +1,9 @@ +error[E0436]: functional record update syntax requires a struct + --> $DIR/issue-26948.rs:4:22 + | +LL | Foo::A { x: 6, ..orig }; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0436`. diff --git a/tests/ui/issues/issue-26997.rs b/tests/ui/issues/issue-26997.rs new file mode 100644 index 000000000..3653e6273 --- /dev/null +++ b/tests/ui/issues/issue-26997.rs @@ -0,0 +1,15 @@ +// build-pass +#![allow(dead_code)] +pub struct Foo { + x: isize, + y: isize +} + +impl Foo { + #[allow(improper_ctypes_definitions)] + pub extern "C" fn foo_new() -> Foo { + Foo { x: 21, y: 33 } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-27008.rs b/tests/ui/issues/issue-27008.rs new file mode 100644 index 000000000..e04de33f6 --- /dev/null +++ b/tests/ui/issues/issue-27008.rs @@ -0,0 +1,7 @@ +struct S; + +fn main() { + let b = [0; S]; + //~^ ERROR mismatched types + //~| expected `usize`, found struct `S` +} diff --git a/tests/ui/issues/issue-27008.stderr b/tests/ui/issues/issue-27008.stderr new file mode 100644 index 000000000..5b7e74c1c --- /dev/null +++ b/tests/ui/issues/issue-27008.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-27008.rs:4:17 + | +LL | let b = [0; S]; + | ^ expected `usize`, found struct `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-27033.rs b/tests/ui/issues/issue-27033.rs new file mode 100644 index 000000000..a23819a20 --- /dev/null +++ b/tests/ui/issues/issue-27033.rs @@ -0,0 +1,12 @@ +fn main() { + match Some(1) { + None @ _ => {} //~ ERROR match bindings cannot shadow unit variants + }; + const C: u8 = 1; + match 1 { + C @ 2 => { //~ ERROR match bindings cannot shadow constant + println!("{}", C); + } + _ => {} + }; +} diff --git a/tests/ui/issues/issue-27033.stderr b/tests/ui/issues/issue-27033.stderr new file mode 100644 index 000000000..7a0ca888d --- /dev/null +++ b/tests/ui/issues/issue-27033.stderr @@ -0,0 +1,21 @@ +error[E0530]: match bindings cannot shadow unit variants + --> $DIR/issue-27033.rs:3:9 + | +LL | None @ _ => {} + | ^^^^ cannot be named the same as a unit variant + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the unit variant `None` is defined here + +error[E0530]: match bindings cannot shadow constants + --> $DIR/issue-27033.rs:7:9 + | +LL | const C: u8 = 1; + | ---------------- the constant `C` is defined here +LL | match 1 { +LL | C @ 2 => { + | ^ cannot be named the same as a constant + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/issues/issue-27042.rs b/tests/ui/issues/issue-27042.rs new file mode 100644 index 000000000..517c1f2e6 --- /dev/null +++ b/tests/ui/issues/issue-27042.rs @@ -0,0 +1,17 @@ +// Regression test for #27042. Test that a loop's label is included in its span. + +fn main() { + let _: i32 = + 'a: // in this case, the citation is just the `break`: + loop { break }; //~ ERROR mismatched types + let _: i32 = + 'b: //~ ERROR mismatched types + //~^ WARN denote infinite loops with + while true { break }; // but here we cite the whole loop + let _: i32 = + 'c: //~ ERROR mismatched types + for _ in None { break }; // but here we cite the whole loop + let _: i32 = + 'd: //~ ERROR mismatched types + while let Some(_) = None { break }; +} diff --git a/tests/ui/issues/issue-27042.stderr b/tests/ui/issues/issue-27042.stderr new file mode 100644 index 000000000..59ef28481 --- /dev/null +++ b/tests/ui/issues/issue-27042.stderr @@ -0,0 +1,48 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/issue-27042.rs:8:9 + | +LL | / 'b: +LL | | +LL | | while true { break }; // but here we cite the whole loop + | |__________________^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0308]: mismatched types + --> $DIR/issue-27042.rs:6:16 + | +LL | loop { break }; + | ^^^^^ + | | + | expected `i32`, found `()` + | help: give it a value of the expected type: `break 42` + +error[E0308]: mismatched types + --> $DIR/issue-27042.rs:8:9 + | +LL | let _: i32 = + | --- expected due to this +LL | / 'b: +LL | | +LL | | while true { break }; // but here we cite the whole loop + | |____________________________^ expected `i32`, found `()` + +error[E0308]: mismatched types + --> $DIR/issue-27042.rs:12:9 + | +LL | / 'c: +LL | | for _ in None { break }; // but here we cite the whole loop + | |_______________________________^ expected `i32`, found `()` + +error[E0308]: mismatched types + --> $DIR/issue-27042.rs:15:9 + | +LL | let _: i32 = + | --- expected due to this +LL | / 'd: +LL | | while let Some(_) = None { break }; + | |__________________________________________^ expected `i32`, found `()` + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-27054-primitive-binary-ops.rs b/tests/ui/issues/issue-27054-primitive-binary-ops.rs new file mode 100644 index 000000000..c6f925de5 --- /dev/null +++ b/tests/ui/issues/issue-27054-primitive-binary-ops.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + let x = &mut 1; + assert_eq!(*x + { *x=2; 1 }, 2); +} diff --git a/tests/ui/issues/issue-27078.rs b/tests/ui/issues/issue-27078.rs new file mode 100644 index 000000000..5f09b9587 --- /dev/null +++ b/tests/ui/issues/issue-27078.rs @@ -0,0 +1,9 @@ +trait Foo { + const BAR: i32; + fn foo(self) -> &'static i32 { + //~^ ERROR the size for values of type + &::BAR + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-27078.stderr b/tests/ui/issues/issue-27078.stderr new file mode 100644 index 000000000..ced92bbd4 --- /dev/null +++ b/tests/ui/issues/issue-27078.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-27078.rs:3:12 + | +LL | fn foo(self) -> &'static i32 { + | ^^^^ doesn't have a size known at compile-time + | + = help: unsized fn params are gated as an unstable feature +help: consider further restricting `Self` + | +LL | fn foo(self) -> &'static i32 where Self: Sized { + | +++++++++++++++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(&self) -> &'static i32 { + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-2708.rs b/tests/ui/issues/issue-2708.rs new file mode 100644 index 000000000..4e53b9d14 --- /dev/null +++ b/tests/ui/issues/issue-2708.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// pretty-expanded FIXME #23616 + + + +struct Font { + fontbuf: usize, + cairo_font: usize, + font_dtor: usize, + +} + +impl Drop for Font { + fn drop(&mut self) {} +} + +fn Font() -> Font { + Font { + fontbuf: 0, + cairo_font: 0, + font_dtor: 0 + } +} + +pub fn main() { + let _f: Box<_> = Box::new(Font()); +} diff --git a/tests/ui/issues/issue-27105.rs b/tests/ui/issues/issue-27105.rs new file mode 100644 index 000000000..3339af364 --- /dev/null +++ b/tests/ui/issues/issue-27105.rs @@ -0,0 +1,15 @@ +// check-pass +use std::cell::RefCell; +use std::rc::Rc; + +pub struct Callbacks { + callbacks: Vec>>, +} + +impl Callbacks { + pub fn register(&mut self, callback: F) { + self.callbacks.push(Rc::new(RefCell::new(callback))); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-2723-b.rs b/tests/ui/issues/issue-2723-b.rs new file mode 100644 index 000000000..1910561d0 --- /dev/null +++ b/tests/ui/issues/issue-2723-b.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-2723-a.rs + +extern crate issue_2723_a; +use issue_2723_a::f; + +pub fn main() { + unsafe { + f(vec![2]); + } +} diff --git a/tests/ui/issues/issue-27240.rs b/tests/ui/issues/issue-27240.rs new file mode 100644 index 000000000..eaf254f33 --- /dev/null +++ b/tests/ui/issues/issue-27240.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] +use std::fmt; +struct NoisyDrop(#[allow(unused_tuple_struct_fields)] T); +impl Drop for NoisyDrop { + fn drop(&mut self) {} +} + +struct Bar(#[allow(unused_tuple_struct_fields)] [*const NoisyDrop; 2]); + +fn fine() { + let (u,b); + u = vec![43]; + b = Bar([&NoisyDrop(&u), &NoisyDrop(&u)]); +} + +#[allow(unused_tuple_struct_fields)] +struct Bar2(*const NoisyDrop, *const NoisyDrop); + +fn lolwut() { + let (u,v); + u = vec![43]; + v = Bar2(&NoisyDrop(&u), &NoisyDrop(&u)); +} + +fn main() { fine(); lolwut() } diff --git a/tests/ui/issues/issue-27268.rs b/tests/ui/issues/issue-27268.rs new file mode 100644 index 000000000..161e2d4d2 --- /dev/null +++ b/tests/ui/issues/issue-27268.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() { + const _C: &'static dyn Fn() = &||{}; +} diff --git a/tests/ui/issues/issue-27281.rs b/tests/ui/issues/issue-27281.rs new file mode 100644 index 000000000..717d8b2c2 --- /dev/null +++ b/tests/ui/issues/issue-27281.rs @@ -0,0 +1,17 @@ +// check-pass +pub trait Trait<'a> { + type T; + type U; + fn foo(&self, s: &'a ()) -> &'a (); +} + +impl<'a> Trait<'a> for () { + type T = &'a (); + type U = Self::T; + + fn foo(&self, s: &'a ()) -> &'a () { + let t: Self::T = s; t + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/issues/issue-27340.rs new file mode 100644 index 000000000..61c77cc1f --- /dev/null +++ b/tests/ui/issues/issue-27340.rs @@ -0,0 +1,6 @@ +struct Foo; +#[derive(Copy, Clone)] +//~^ ERROR the trait `Copy` may not be implemented for this type +struct Bar(Foo); + +fn main() {} diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr new file mode 100644 index 000000000..40889b866 --- /dev/null +++ b/tests/ui/issues/issue-27340.stderr @@ -0,0 +1,14 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/issue-27340.rs:2:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ +LL | +LL | struct Bar(Foo); + | --- this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/issues/issue-2735-2.rs b/tests/ui/issues/issue-2735-2.rs new file mode 100644 index 000000000..70ebce9d3 --- /dev/null +++ b/tests/ui/issues/issue-2735-2.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::cell::Cell; + +// This test should behave exactly like issue-2735-3 +struct defer<'a> { + b: &'a Cell, +} + +impl<'a> Drop for defer<'a> { + fn drop(&mut self) { + self.b.set(true); + } +} + +fn defer(b: &Cell) -> defer { + defer { + b: b + } +} + +pub fn main() { + let dtor_ran = &Cell::new(false); + let _ = defer(dtor_ran); + assert!(dtor_ran.get()); +} diff --git a/tests/ui/issues/issue-2735-3.rs b/tests/ui/issues/issue-2735-3.rs new file mode 100644 index 000000000..233015378 --- /dev/null +++ b/tests/ui/issues/issue-2735-3.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::cell::Cell; + +// This test should behave exactly like issue-2735-2 +struct defer<'a> { + b: &'a Cell, +} + +impl<'a> Drop for defer<'a> { + fn drop(&mut self) { + self.b.set(true); + } +} + +fn defer(b: &Cell) -> defer { + defer { + b: b + } +} + +pub fn main() { + let dtor_ran = &Cell::new(false); + defer(dtor_ran); + assert!(dtor_ran.get()); +} diff --git a/tests/ui/issues/issue-2735.rs b/tests/ui/issues/issue-2735.rs new file mode 100644 index 000000000..20d3949a9 --- /dev/null +++ b/tests/ui/issues/issue-2735.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +trait hax { + fn dummy(&self) { } +} +impl hax for A { } + +fn perform_hax(x: Box) -> Box { + Box::new(x) as Box +} + +fn deadcode() { + perform_hax(Box::new("deadcode".to_string())); +} + +pub fn main() { + perform_hax(Box::new(42)); +} diff --git a/tests/ui/issues/issue-27401-dropflag-reinit.rs b/tests/ui/issues/issue-27401-dropflag-reinit.rs new file mode 100644 index 000000000..ab54af29b --- /dev/null +++ b/tests/ui/issues/issue-27401-dropflag-reinit.rs @@ -0,0 +1,26 @@ +// run-pass + +// Check that when a `let`-binding occurs in a loop, its associated +// drop-flag is reinitialized (to indicate "needs-drop" at the end of +// the owning variable's scope). + +struct A<'a>(&'a mut i32); + +impl<'a> Drop for A<'a> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +fn main() { + let mut cnt = 0; + for i in 0..2 { + let a = A(&mut cnt); + if i == 1 { // Note that + break; // both this break + } // and also + drop(a); // this move of `a` + // are necessary to expose the bug + } + assert_eq!(cnt, 2); +} diff --git a/tests/ui/issues/issue-27433.fixed b/tests/ui/issues/issue-27433.fixed new file mode 100644 index 000000000..ce31f6bea --- /dev/null +++ b/tests/ui/issues/issue-27433.fixed @@ -0,0 +1,7 @@ +// run-rustfix +fn main() { + let foo = 42u32; + #[allow(unused_variables, non_snake_case)] + let FOO : u32 = foo; + //~^ ERROR attempt to use a non-constant value in a constant +} diff --git a/tests/ui/issues/issue-27433.rs b/tests/ui/issues/issue-27433.rs new file mode 100644 index 000000000..01411a51c --- /dev/null +++ b/tests/ui/issues/issue-27433.rs @@ -0,0 +1,7 @@ +// run-rustfix +fn main() { + let foo = 42u32; + #[allow(unused_variables, non_snake_case)] + const FOO : u32 = foo; + //~^ ERROR attempt to use a non-constant value in a constant +} diff --git a/tests/ui/issues/issue-27433.stderr b/tests/ui/issues/issue-27433.stderr new file mode 100644 index 000000000..da751a649 --- /dev/null +++ b/tests/ui/issues/issue-27433.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-27433.rs:5:23 + | +LL | const FOO : u32 = foo; + | --------- ^^^ non-constant value + | | + | help: consider using `let` instead of `const`: `let FOO` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-2748-a.rs b/tests/ui/issues/issue-2748-a.rs new file mode 100644 index 000000000..cbb9bcc28 --- /dev/null +++ b/tests/ui/issues/issue-2748-a.rs @@ -0,0 +1,17 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// pretty-expanded FIXME #23616 + +struct CMap<'a> { + buf: &'a [u8], +} + +fn CMap(buf: &[u8]) -> CMap { + CMap { + buf: buf + } +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-27583.rs b/tests/ui/issues/issue-27583.rs new file mode 100644 index 000000000..84c94c7c9 --- /dev/null +++ b/tests/ui/issues/issue-27583.rs @@ -0,0 +1,47 @@ +// check-pass +// Regression test for issue #27583. Unclear how useful this will be +// going forward, since the issue in question was EXTREMELY sensitive +// to compiler internals (like the precise numbering of nodes), but +// what the hey. + +#![allow(warnings)] + +use std::cell::Cell; +use std::marker::PhantomData; + +pub trait Delegate<'tcx> { } + +pub struct InferCtxt<'a, 'tcx: 'a> { + x: PhantomData<&'a Cell<&'tcx ()>> +} + +pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> { + x: &'t InferCtxt<'a, 'tcx>, +} + +pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> { + typer: &'t InferCtxt<'a, 'tcx>, + mc: MemCategorizationContext<'t, 'a, 'tcx>, + delegate: &'d mut (Delegate<'tcx>+'d), +} + +impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { + pub fn new(delegate: &'d mut Delegate<'tcx>, + typer: &'t InferCtxt<'a, 'tcx>) + -> ExprUseVisitor<'d,'t,'a,'tcx> + { + ExprUseVisitor { + typer: typer, + mc: MemCategorizationContext::new(typer), + delegate: delegate, + } + } +} + +impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { + pub fn new(typer: &'t InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> { + MemCategorizationContext { x: typer } + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-27592.rs b/tests/ui/issues/issue-27592.rs new file mode 100644 index 000000000..88f70f584 --- /dev/null +++ b/tests/ui/issues/issue-27592.rs @@ -0,0 +1,19 @@ +// Regression test for issue #27592. + +fn write<'a, F: ::std::ops::FnOnce()->::std::fmt::Arguments<'a> + 'a>(fcn: F) { + use std::fmt::Write; + let _ = match fcn() { a => write!(&mut Stream, "{}", a), }; +} + +struct Stream; +impl ::std::fmt::Write for Stream { + fn write_str(&mut self, _s: &str) -> ::std::fmt::Result { + Ok( () ) + } +} + +fn main() { + write(|| format_args!("{}", String::from("Hello world"))); + //~^ ERROR cannot return value referencing temporary value + //~| ERROR cannot return reference to temporary value +} diff --git a/tests/ui/issues/issue-27592.stderr b/tests/ui/issues/issue-27592.stderr new file mode 100644 index 000000000..1205a8b65 --- /dev/null +++ b/tests/ui/issues/issue-27592.stderr @@ -0,0 +1,22 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/issue-27592.rs:16:14 + | +LL | write(|| format_args!("{}", String::from("Hello world"))); + | ^^^^^^^^^^^^^^^^^^^---------------------------^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + | + = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0515]: cannot return reference to temporary value + --> $DIR/issue-27592.rs:16:14 + | +LL | write(|| format_args!("{}", String::from("Hello world"))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a reference to data owned by the current function + | + = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-2761.rs b/tests/ui/issues/issue-2761.rs new file mode 100644 index 000000000..3ba098abb --- /dev/null +++ b/tests/ui/issues/issue-2761.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:custom message +// ignore-emscripten no processes + +fn main() { + assert!(false, "custom message"); +} diff --git a/tests/ui/issues/issue-27639.rs b/tests/ui/issues/issue-27639.rs new file mode 100644 index 000000000..945fbad91 --- /dev/null +++ b/tests/ui/issues/issue-27639.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +fn main() { + const iter: i32 = 0; + + for i in 1..10 { + println!("{}", i); + } +} diff --git a/tests/ui/issues/issue-27697.rs b/tests/ui/issues/issue-27697.rs new file mode 100644 index 000000000..12af8a8e8 --- /dev/null +++ b/tests/ui/issues/issue-27697.rs @@ -0,0 +1,21 @@ +// check-pass + +use std::ops::Deref; + +trait MyTrait { + fn do_something(&self); + fn as_str(&self) -> &str; +} + +impl Deref for dyn MyTrait { + type Target = str; + fn deref(&self) -> &Self::Target { + self.as_str() + } +} + +fn trait_object_does_something(t: &dyn MyTrait) { + t.do_something() +} + +fn main() {} diff --git a/tests/ui/issues/issue-27815.rs b/tests/ui/issues/issue-27815.rs new file mode 100644 index 000000000..9e53014f4 --- /dev/null +++ b/tests/ui/issues/issue-27815.rs @@ -0,0 +1,12 @@ +mod A {} + +fn main() { + let u = A { x: 1 }; //~ ERROR expected struct, variant or union type, found module `A` + let v = u32 { x: 1 }; //~ ERROR expected struct, variant or union type, found builtin type `u32` + match () { + A { x: 1 } => {} + //~^ ERROR expected struct, variant or union type, found module `A` + u32 { x: 1 } => {} + //~^ ERROR expected struct, variant or union type, found builtin type `u32` + } +} diff --git a/tests/ui/issues/issue-27815.stderr b/tests/ui/issues/issue-27815.stderr new file mode 100644 index 000000000..43f78ccf6 --- /dev/null +++ b/tests/ui/issues/issue-27815.stderr @@ -0,0 +1,27 @@ +error[E0574]: expected struct, variant or union type, found module `A` + --> $DIR/issue-27815.rs:4:13 + | +LL | let u = A { x: 1 }; + | ^ not a struct, variant or union type + +error[E0574]: expected struct, variant or union type, found builtin type `u32` + --> $DIR/issue-27815.rs:5:13 + | +LL | let v = u32 { x: 1 }; + | ^^^ not a struct, variant or union type + +error[E0574]: expected struct, variant or union type, found module `A` + --> $DIR/issue-27815.rs:7:9 + | +LL | A { x: 1 } => {} + | ^ not a struct, variant or union type + +error[E0574]: expected struct, variant or union type, found builtin type `u32` + --> $DIR/issue-27815.rs:9:9 + | +LL | u32 { x: 1 } => {} + | ^^^ not a struct, variant or union type + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/issues/issue-27842.rs b/tests/ui/issues/issue-27842.rs new file mode 100644 index 000000000..3bcfa1330 --- /dev/null +++ b/tests/ui/issues/issue-27842.rs @@ -0,0 +1,11 @@ +fn main() { + let tup = (0, 1, 2); + // the case where we show a suggestion + let _ = tup[0]; + //~^ ERROR cannot index into a value of type + + // the case where we show just a general hint + let i = 0_usize; + let _ = tup[i]; + //~^ ERROR cannot index into a value of type +} diff --git a/tests/ui/issues/issue-27842.stderr b/tests/ui/issues/issue-27842.stderr new file mode 100644 index 000000000..784666a63 --- /dev/null +++ b/tests/ui/issues/issue-27842.stderr @@ -0,0 +1,17 @@ +error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer})` + --> $DIR/issue-27842.rs:4:13 + | +LL | let _ = tup[0]; + | ^^^^^^ help: to access tuple elements, use: `tup.0` + +error[E0608]: cannot index into a value of type `({integer}, {integer}, {integer})` + --> $DIR/issue-27842.rs:9:13 + | +LL | let _ = tup[i]; + | ^^^^^^ + | + = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/issues/issue-27859.rs b/tests/ui/issues/issue-27859.rs new file mode 100644 index 000000000..233670681 --- /dev/null +++ b/tests/ui/issues/issue-27859.rs @@ -0,0 +1,20 @@ +// run-pass +// ignore-wasm32 issue 42629 + +#[inline(never)] +fn foo(a: f32, b: f32) -> f32 { + a % b +} + +#[inline(never)] +fn bar(a: f32, b: f32) -> f32 { + ((a as f64) % (b as f64)) as f32 +} + +fn main() { + let unknown_float = std::env::args().len(); + println!("{}", foo(4.0, unknown_float as f32)); + println!("{}", foo(5.0, (unknown_float as f32) + 1.0)); + println!("{}", bar(6.0, (unknown_float as f32) + 2.0)); + println!("{}", bar(7.0, (unknown_float as f32) + 3.0)); +} diff --git a/tests/ui/issues/issue-27889.rs b/tests/ui/issues/issue-27889.rs new file mode 100644 index 000000000..623416a5d --- /dev/null +++ b/tests/ui/issues/issue-27889.rs @@ -0,0 +1,23 @@ +// check-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] +// Test that a field can have the same name in different variants +// of an enum + +pub enum Foo { + X { foo: u32 }, + Y { foo: u32 } +} + +pub fn foo(mut x: Foo) { + let mut y = None; + let mut z = None; + if let Foo::X { ref foo } = x { + z = Some(foo); + } + if let Foo::Y { ref mut foo } = x { + y = Some(foo); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-27901.rs b/tests/ui/issues/issue-27901.rs new file mode 100644 index 000000000..ffd90b689 --- /dev/null +++ b/tests/ui/issues/issue-27901.rs @@ -0,0 +1,11 @@ +// run-pass +trait Stream { type Item; } +impl<'a> Stream for &'a str { type Item = u8; } +fn f<'s>(s: &'s str) -> (&'s str, <&'s str as Stream>::Item) { + (s, 42) +} + +fn main() { + let fx = f as for<'t> fn(&'t str) -> (&'t str, <&'t str as Stream>::Item); + assert_eq!(fx("hi"), ("hi", 42)); +} diff --git a/tests/ui/issues/issue-27942.rs b/tests/ui/issues/issue-27942.rs new file mode 100644 index 000000000..34b34de38 --- /dev/null +++ b/tests/ui/issues/issue-27942.rs @@ -0,0 +1,14 @@ +pub trait Resources<'a> {} + +pub trait Buffer<'a, R: Resources<'a>> { + + fn select(&self) -> BufferViewHandle; + //~^ ERROR mismatched types + //~| lifetime mismatch + //~| ERROR mismatched types + //~| lifetime mismatch +} + +pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R); + +fn main() {} diff --git a/tests/ui/issues/issue-27942.stderr b/tests/ui/issues/issue-27942.stderr new file mode 100644 index 000000000..7ea9345a6 --- /dev/null +++ b/tests/ui/issues/issue-27942.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched types + --> $DIR/issue-27942.rs:5:25 + | +LL | fn select(&self) -> BufferViewHandle; + | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `Resources<'_>` + found trait `Resources<'a>` +note: the anonymous lifetime defined here... + --> $DIR/issue-27942.rs:5:15 + | +LL | fn select(&self) -> BufferViewHandle; + | ^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/issue-27942.rs:3:18 + | +LL | pub trait Buffer<'a, R: Resources<'a>> { + | ^^ + +error[E0308]: mismatched types + --> $DIR/issue-27942.rs:5:25 + | +LL | fn select(&self) -> BufferViewHandle; + | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `Resources<'_>` + found trait `Resources<'a>` +note: the lifetime `'a` as defined here... + --> $DIR/issue-27942.rs:3:18 + | +LL | pub trait Buffer<'a, R: Resources<'a>> { + | ^^ +note: ...does not necessarily outlive the anonymous lifetime defined here + --> $DIR/issue-27942.rs:5:15 + | +LL | fn select(&self) -> BufferViewHandle; + | ^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-27949.rs b/tests/ui/issues/issue-27949.rs new file mode 100644 index 000000000..e905da72a --- /dev/null +++ b/tests/ui/issues/issue-27949.rs @@ -0,0 +1,41 @@ +// run-pass +// +// At one time, the `==` operator (and other binary operators) did not +// support subtyping during type checking, and would therefore require +// LHS and RHS to be exactly identical--i.e. to have the same lifetimes. +// +// This was fixed in 1a7fb7dc78439a704f024609ce3dc0beb1386552. + +#[derive(Copy, Clone)] +struct Input<'a> { + foo: &'a u32 +} + +impl <'a> std::cmp::PartialEq> for Input<'a> { + fn eq(&self, other: &Input<'a>) -> bool { + self.foo == other.foo + } + + fn ne(&self, other: &Input<'a>) -> bool { + self.foo != other.foo + } +} + + +fn check_equal<'a, 'b>(x: Input<'a>, y: Input<'b>) -> bool { + // Type checking error due to 'a != 'b prior to 1a7fb7dc78 + x == y +} + +fn main() { + let i = 1u32; + let j = 1u32; + let k = 2u32; + + let input_i = Input { foo: &i }; + let input_j = Input { foo: &j }; + let input_k = Input { foo: &k }; + assert!(check_equal(input_i, input_i)); + assert!(check_equal(input_i, input_j)); + assert!(!check_equal(input_i, input_k)); +} diff --git a/tests/ui/issues/issue-27997.rs b/tests/ui/issues/issue-27997.rs new file mode 100644 index 000000000..dd74cf752 --- /dev/null +++ b/tests/ui/issues/issue-27997.rs @@ -0,0 +1,37 @@ +// run-pass +use std::sync::atomic::{Ordering, AtomicUsize}; + +use std::mem; +struct S { + _u: U, + size_of_u: usize, + _v: V, + size_of_v: usize +} + +impl S { + fn new(u: U, v: V) -> Self { + S { + _u: u, + size_of_u: mem::size_of::(), + _v: v, + size_of_v: mem::size_of::() + } + } +} + +static COUNT: AtomicUsize = AtomicUsize::new(0); + +impl Drop for S { + fn drop(&mut self) { + assert_eq!(mem::size_of::(), self.size_of_u); + assert_eq!(mem::size_of::(), self.size_of_v); + COUNT.store(COUNT.load(Ordering::SeqCst)+1, Ordering::SeqCst); + } +} + +fn main() { + assert_eq!(COUNT.load(Ordering::SeqCst), 0); + { S::new(0u8, 1u16); } + assert_eq!(COUNT.load(Ordering::SeqCst), 1); +} diff --git a/tests/ui/issues/issue-2804-2.rs b/tests/ui/issues/issue-2804-2.rs new file mode 100644 index 000000000..d02725505 --- /dev/null +++ b/tests/ui/issues/issue-2804-2.rs @@ -0,0 +1,12 @@ +// check-pass +#![allow(dead_code)] +// Minimized version of issue-2804.rs. Both check that callee IDs don't +// clobber the previous node ID in a macro expr + +use std::collections::HashMap; + +fn add_interfaces(managed_ip: String, device: HashMap) { + println!("{}, {}", managed_ip, device["interfaces"]); +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-28105.rs b/tests/ui/issues/issue-28105.rs new file mode 100644 index 000000000..1e8d2d6cc --- /dev/null +++ b/tests/ui/issues/issue-28105.rs @@ -0,0 +1,8 @@ +// Make sure that a continue span actually contains the keyword. + +fn main() { + continue //~ ERROR `continue` outside of a loop + ; + break //~ ERROR `break` outside of a loop + ; +} diff --git a/tests/ui/issues/issue-28105.stderr b/tests/ui/issues/issue-28105.stderr new file mode 100644 index 000000000..f450256f3 --- /dev/null +++ b/tests/ui/issues/issue-28105.stderr @@ -0,0 +1,15 @@ +error[E0268]: `continue` outside of a loop + --> $DIR/issue-28105.rs:4:5 + | +LL | continue + | ^^^^^^^^ cannot `continue` outside of a loop + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-28105.rs:6:5 + | +LL | break + | ^^^^^ cannot `break` outside of a loop or labeled block + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-28109.rs b/tests/ui/issues/issue-28109.rs new file mode 100644 index 000000000..755a539b5 --- /dev/null +++ b/tests/ui/issues/issue-28109.rs @@ -0,0 +1,12 @@ +// Make sure that label for continue and break is spanned correctly + +fn main() { + loop { + continue + 'b //~ ERROR use of undeclared label + ; + break + 'c //~ ERROR use of undeclared label + ; + } +} diff --git a/tests/ui/issues/issue-28109.stderr b/tests/ui/issues/issue-28109.stderr new file mode 100644 index 000000000..0f918d3b6 --- /dev/null +++ b/tests/ui/issues/issue-28109.stderr @@ -0,0 +1,15 @@ +error[E0426]: use of undeclared label `'b` + --> $DIR/issue-28109.rs:6:9 + | +LL | 'b + | ^^ undeclared label `'b` + +error[E0426]: use of undeclared label `'c` + --> $DIR/issue-28109.rs:9:9 + | +LL | 'c + | ^^ undeclared label `'c` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/issues/issue-28181.rs b/tests/ui/issues/issue-28181.rs new file mode 100644 index 000000000..c46e131c6 --- /dev/null +++ b/tests/ui/issues/issue-28181.rs @@ -0,0 +1,6 @@ +// run-pass +fn bar(f: F) -> usize where F: Fn([usize; 1]) -> usize { f([2]) } + +fn main() { + bar(|u| { u[0] }); +} diff --git a/tests/ui/issues/issue-2823.rs b/tests/ui/issues/issue-2823.rs new file mode 100644 index 000000000..7b443b415 --- /dev/null +++ b/tests/ui/issues/issue-2823.rs @@ -0,0 +1,14 @@ +struct C { + x: isize, +} + +impl Drop for C { + fn drop(&mut self) { + println!("dropping: {}", self.x); + } +} + +fn main() { + let c = C{ x: 2}; + let _d = c.clone(); //~ ERROR no method named `clone` found +} diff --git a/tests/ui/issues/issue-2823.stderr b/tests/ui/issues/issue-2823.stderr new file mode 100644 index 000000000..b5a2b2f55 --- /dev/null +++ b/tests/ui/issues/issue-2823.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `clone` found for struct `C` in the current scope + --> $DIR/issue-2823.rs:13:16 + | +LL | struct C { + | -------- method `clone` not found for this struct +... +LL | let _d = c.clone(); + | ^^^^^ method not found in `C` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-28279.rs b/tests/ui/issues/issue-28279.rs new file mode 100644 index 000000000..bab5df122 --- /dev/null +++ b/tests/ui/issues/issue-28279.rs @@ -0,0 +1,21 @@ +// check-pass +#![allow(dead_code)] +use std::rc::Rc; + +fn test1() -> Rc Fn(&'a usize) + 'static> { + if let Some(_) = Some(1) { + loop{} + } else { + loop{} + } +} + +fn test2() -> *mut (dyn for<'a> Fn(&'a usize) + 'static) { + if let Some(_) = Some(1) { + loop{} + } else { + loop{} + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-28344.rs b/tests/ui/issues/issue-28344.rs new file mode 100644 index 000000000..1a6a7f46b --- /dev/null +++ b/tests/ui/issues/issue-28344.rs @@ -0,0 +1,15 @@ +use std::ops::BitXor; + +fn main() { + let x: u8 = BitXor::bitor(0 as u8, 0 as u8); + //~^ ERROR must be specified + //~| no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + + let g = BitXor::bitor; + //~^ ERROR must be specified + //~| no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr new file mode 100644 index 000000000..f398a5da3 --- /dev/null +++ b/tests/ui/issues/issue-28344.stderr @@ -0,0 +1,61 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-28344.rs:4:17 + | +LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); + | ^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | let x: u8 = ::bitor(0 as u8, 0 as u8); + | ++++ + + +error[E0191]: the value of the associated type `Output` (from trait `BitXor`) must be specified + --> $DIR/issue-28344.rs:4:17 + | +LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); + | ^^^^^^ help: specify the associated type: `BitXor` + +error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope + --> $DIR/issue-28344.rs:4:25 + | +LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); + | ^^^^^ + | | + | function or associated item not found in `dyn BitXor<_>` + | help: there is a method with a similar name: `bitxor` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-28344.rs:10:13 + | +LL | let g = BitXor::bitor; + | ^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let g = ::bitor; + | ++++ + + +error[E0191]: the value of the associated type `Output` (from trait `BitXor`) must be specified + --> $DIR/issue-28344.rs:10:13 + | +LL | let g = BitXor::bitor; + | ^^^^^^ help: specify the associated type: `BitXor` + +error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope + --> $DIR/issue-28344.rs:10:21 + | +LL | let g = BitXor::bitor; + | ^^^^^ + | | + | function or associated item not found in `dyn BitXor<_>` + | help: there is a method with a similar name: `bitxor` + +error: aborting due to 4 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0191, E0599. +For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-28433.rs b/tests/ui/issues/issue-28433.rs new file mode 100644 index 000000000..8d05c32d5 --- /dev/null +++ b/tests/ui/issues/issue-28433.rs @@ -0,0 +1,12 @@ +enum Bird { + pub Duck, + //~^ ERROR unnecessary visibility qualifier + Goose, + pub(crate) Dove + //~^ ERROR unnecessary visibility qualifier +} + + +fn main() { + let y = Bird::Goose; +} diff --git a/tests/ui/issues/issue-28433.stderr b/tests/ui/issues/issue-28433.stderr new file mode 100644 index 000000000..9f5f63336 --- /dev/null +++ b/tests/ui/issues/issue-28433.stderr @@ -0,0 +1,15 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/issue-28433.rs:2:5 + | +LL | pub Duck, + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/issue-28433.rs:5:5 + | +LL | pub(crate) Dove + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/issues/issue-28472.rs b/tests/ui/issues/issue-28472.rs new file mode 100644 index 000000000..6db1f9a5b --- /dev/null +++ b/tests/ui/issues/issue-28472.rs @@ -0,0 +1,14 @@ +// Check that the visibility modifier is included in the span of foreign items. + +extern "C" { + fn foo(); + + pub //~ ERROR the name `foo` is defined multiple times + fn foo(); + + pub //~ ERROR the name `foo` is defined multiple times + static mut foo: u32; +} + +fn main() { +} diff --git a/tests/ui/issues/issue-28472.stderr b/tests/ui/issues/issue-28472.stderr new file mode 100644 index 000000000..051ed25b6 --- /dev/null +++ b/tests/ui/issues/issue-28472.stderr @@ -0,0 +1,27 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/issue-28472.rs:6:3 + | +LL | fn foo(); + | --------- previous definition of the value `foo` here +LL | +LL | / pub +LL | | fn foo(); + | |___________^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this module + +error[E0428]: the name `foo` is defined multiple times + --> $DIR/issue-28472.rs:9:3 + | +LL | fn foo(); + | --------- previous definition of the value `foo` here +... +LL | / pub +LL | | static mut foo: u32; + | |______________________^ `foo` redefined here + | + = note: `foo` must be defined only once in the value namespace of this module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-2848.rs b/tests/ui/issues/issue-2848.rs new file mode 100644 index 000000000..e0049bf8f --- /dev/null +++ b/tests/ui/issues/issue-2848.rs @@ -0,0 +1,17 @@ +#[allow(non_camel_case_types)] + +mod bar { + pub enum foo { + alpha, + beta, + charlie + } +} + +fn main() { + use bar::foo::{alpha, charlie}; + match alpha { + alpha | beta => {} //~ ERROR variable `beta` is not bound in all patterns + charlie => {} + } +} diff --git a/tests/ui/issues/issue-2848.stderr b/tests/ui/issues/issue-2848.stderr new file mode 100644 index 000000000..71ed7d70b --- /dev/null +++ b/tests/ui/issues/issue-2848.stderr @@ -0,0 +1,11 @@ +error[E0408]: variable `beta` is not bound in all patterns + --> $DIR/issue-2848.rs:14:7 + | +LL | alpha | beta => {} + | ^^^^^ ---- variable not in all patterns + | | + | pattern doesn't bind `beta` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/issues/issue-2849.rs b/tests/ui/issues/issue-2849.rs new file mode 100644 index 000000000..787ab0e28 --- /dev/null +++ b/tests/ui/issues/issue-2849.rs @@ -0,0 +1,8 @@ +enum Foo { Alpha, Beta(isize) } + +fn main() { + match Foo::Alpha { + Foo::Alpha | Foo::Beta(i) => {} + //~^ ERROR variable `i` is not bound in all patterns + } +} diff --git a/tests/ui/issues/issue-2849.stderr b/tests/ui/issues/issue-2849.stderr new file mode 100644 index 000000000..9027098d2 --- /dev/null +++ b/tests/ui/issues/issue-2849.stderr @@ -0,0 +1,11 @@ +error[E0408]: variable `i` is not bound in all patterns + --> $DIR/issue-2849.rs:5:7 + | +LL | Foo::Alpha | Foo::Beta(i) => {} + | ^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `i` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/issues/issue-28498-must-work-ex1.rs b/tests/ui/issues/issue-28498-must-work-ex1.rs new file mode 100644 index 000000000..ab6d190e0 --- /dev/null +++ b/tests/ui/issues/issue-28498-must-work-ex1.rs @@ -0,0 +1,18 @@ +// run-pass +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #examples-of-code-that-must-continue-to-work + +use std::cell::Cell; + +struct Concrete<'a>(#[allow(unused_tuple_struct_fields)] u32, Cell>>); + +fn main() { + let mut data = Vec::new(); + data.push(Concrete(0, Cell::new(None))); + data.push(Concrete(0, Cell::new(None))); + + data[0].1.set(Some(&data[1])); + data[1].1.set(Some(&data[0])); +} diff --git a/tests/ui/issues/issue-28498-must-work-ex2.rs b/tests/ui/issues/issue-28498-must-work-ex2.rs new file mode 100644 index 000000000..378d736ee --- /dev/null +++ b/tests/ui/issues/issue-28498-must-work-ex2.rs @@ -0,0 +1,20 @@ +// run-pass +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #examples-of-code-that-must-continue-to-work + +use std::cell::Cell; + +struct Concrete<'a>(#[allow(unused_tuple_struct_fields)] u32, Cell>>); + +struct Foo { data: Vec } + +fn main() { + let mut foo = Foo { data: Vec::new() }; + foo.data.push(Concrete(0, Cell::new(None))); + foo.data.push(Concrete(0, Cell::new(None))); + + foo.data[0].1.set(Some(&foo.data[1])); + foo.data[1].1.set(Some(&foo.data[0])); +} diff --git a/tests/ui/issues/issue-28498-ugeh-ex1.rs b/tests/ui/issues/issue-28498-ugeh-ex1.rs new file mode 100644 index 000000000..24bf706ce --- /dev/null +++ b/tests/ui/issues/issue-28498-ugeh-ex1.rs @@ -0,0 +1,27 @@ +// run-pass + +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #example-of-the-unguarded-escape-hatch + +#![feature(dropck_eyepatch)] +use std::cell::Cell; + +struct Concrete<'a>(#[allow(unused_tuple_struct_fields)] u32, Cell>>); + +struct Foo { data: Vec } + +// Below is the UGEH attribute +unsafe impl<#[may_dangle] T> Drop for Foo { + fn drop(&mut self) { } +} + +fn main() { + let mut foo = Foo { data: Vec::new() }; + foo.data.push(Concrete(0, Cell::new(None))); + foo.data.push(Concrete(0, Cell::new(None))); + + foo.data[0].1.set(Some(&foo.data[1])); + foo.data[1].1.set(Some(&foo.data[0])); +} diff --git a/tests/ui/issues/issue-28550.rs b/tests/ui/issues/issue-28550.rs new file mode 100644 index 000000000..95583f805 --- /dev/null +++ b/tests/ui/issues/issue-28550.rs @@ -0,0 +1,16 @@ +// run-pass +struct AT,T>(F::Output); +struct BT,T>(A); + +// Removing Option causes it to compile. +fn fooT>(f: F) -> Option> { + Some(B(A(f()))) +} + +fn main() { + let v = (|| foo(||4))(); + match v { + Some(B(A(4))) => {}, + _ => unreachable!() + } +} diff --git a/tests/ui/issues/issue-28561.rs b/tests/ui/issues/issue-28561.rs new file mode 100644 index 000000000..beb12c36d --- /dev/null +++ b/tests/ui/issues/issue-28561.rs @@ -0,0 +1,73 @@ +// check-pass +#[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Clone, Copy)] +struct Array { + f00: [T; 00], + f01: [T; 01], + f02: [T; 02], + f03: [T; 03], + f04: [T; 04], + f05: [T; 05], + f06: [T; 06], + f07: [T; 07], + f08: [T; 08], + f09: [T; 09], + f10: [T; 10], + f11: [T; 11], + f12: [T; 12], + f13: [T; 13], + f14: [T; 14], + f15: [T; 15], + f16: [T; 16], + f17: [T; 17], + f18: [T; 18], + f19: [T; 19], + f20: [T; 20], + f21: [T; 21], + f22: [T; 22], + f23: [T; 23], + f24: [T; 24], + f25: [T; 25], + f26: [T; 26], + f27: [T; 27], + f28: [T; 28], + f29: [T; 29], + f30: [T; 30], + f31: [T; 31], + f32: [T; 32], +} + +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +struct Fn { + f00: fn(), + f01: fn(A), + f02: fn(A, B), + f03: fn(A, B, C), + f04: fn(A, B, C, D), + f05: fn(A, B, C, D, E), + f06: fn(A, B, C, D, E, F), + f07: fn(A, B, C, D, E, F, G), + f08: fn(A, B, C, D, E, F, G, H), + f09: fn(A, B, C, D, E, F, G, H, I), + f10: fn(A, B, C, D, E, F, G, H, I, J), + f11: fn(A, B, C, D, E, F, G, H, I, J, K), + f12: fn(A, B, C, D, E, F, G, H, I, J, K, L), +} + +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +struct Tuple { + f00: (), + f01: (A), + f02: (A, B), + f03: (A, B, C), + f04: (A, B, C, D), + f05: (A, B, C, D, E), + f06: (A, B, C, D, E, F), + f07: (A, B, C, D, E, F, G), + f08: (A, B, C, D, E, F, G, H), + f09: (A, B, C, D, E, F, G, H, I), + f10: (A, B, C, D, E, F, G, H, I, J), + f11: (A, B, C, D, E, F, G, H, I, J, K), + f12: (A, B, C, D, E, F, G, H, I, J, K, L), +} + +fn main() {} diff --git a/tests/ui/issues/issue-28568.rs b/tests/ui/issues/issue-28568.rs new file mode 100644 index 000000000..ce511158f --- /dev/null +++ b/tests/ui/issues/issue-28568.rs @@ -0,0 +1,12 @@ +struct MyStruct; + +impl Drop for MyStruct { + fn drop(&mut self) { } +} + +impl Drop for MyStruct { +//~^ ERROR conflicting implementations of trait + fn drop(&mut self) { } +} + +fn main() {} diff --git a/tests/ui/issues/issue-28568.stderr b/tests/ui/issues/issue-28568.stderr new file mode 100644 index 000000000..960259080 --- /dev/null +++ b/tests/ui/issues/issue-28568.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Drop` for type `MyStruct` + --> $DIR/issue-28568.rs:7:1 + | +LL | impl Drop for MyStruct { + | ---------------------- first implementation here +... +LL | impl Drop for MyStruct { + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-28586.rs b/tests/ui/issues/issue-28586.rs new file mode 100644 index 000000000..c543ef9b0 --- /dev/null +++ b/tests/ui/issues/issue-28586.rs @@ -0,0 +1,7 @@ +// Regression test for issue #28586 + +pub trait Foo {} +impl Foo for [u8; usize::BYTES] {} +//~^ ERROR no associated item named `BYTES` found + +fn main() { } diff --git a/tests/ui/issues/issue-28586.stderr b/tests/ui/issues/issue-28586.stderr new file mode 100644 index 000000000..d19c4af2d --- /dev/null +++ b/tests/ui/issues/issue-28586.stderr @@ -0,0 +1,9 @@ +error[E0599]: no associated item named `BYTES` found for type `usize` in the current scope + --> $DIR/issue-28586.rs:4:26 + | +LL | impl Foo for [u8; usize::BYTES] {} + | ^^^^^ associated item not found in `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-28600.rs b/tests/ui/issues/issue-28600.rs new file mode 100644 index 000000000..52db0d5fd --- /dev/null +++ b/tests/ui/issues/issue-28600.rs @@ -0,0 +1,15 @@ +// build-pass +// #28600 ICE: pub extern fn with parameter type &str inside struct impl + +struct Test; + +impl Test { + #[allow(dead_code)] + #[allow(unused_variables)] + #[allow(improper_ctypes_definitions)] + pub extern "C" fn test(val: &str) { + + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-28625.rs b/tests/ui/issues/issue-28625.rs new file mode 100644 index 000000000..15a6a63d5 --- /dev/null +++ b/tests/ui/issues/issue-28625.rs @@ -0,0 +1,22 @@ +// normalize-stderr-test "\d+ bits" -> "N bits" + +trait Bar { + type Bar; +} + +struct ArrayPeano { + data: T::Bar, +} + +fn foo(a: &ArrayPeano) -> &[T] where T: Bar { + unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes +} + +impl Bar for () { + type Bar = (); +} + +fn main() { + let x: ArrayPeano<()> = ArrayPeano { data: () }; + foo(&x); +} diff --git a/tests/ui/issues/issue-28625.stderr b/tests/ui/issues/issue-28625.stderr new file mode 100644 index 000000000..7ee0cd486 --- /dev/null +++ b/tests/ui/issues/issue-28625.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/issue-28625.rs:12:14 + | +LL | unsafe { std::mem::transmute(a) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `&ArrayPeano` (N bits) + = note: target type: `&[T]` (N bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/issues/issue-28776.mir.stderr b/tests/ui/issues/issue-28776.mir.stderr new file mode 100644 index 000000000..1d470fb5e --- /dev/null +++ b/tests/ui/issues/issue-28776.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-28776.rs:7:5 + | +LL | (&ptr::write)(1 as *mut _, 42); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-28776.rs b/tests/ui/issues/issue-28776.rs new file mode 100644 index 000000000..19df3c4a4 --- /dev/null +++ b/tests/ui/issues/issue-28776.rs @@ -0,0 +1,9 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +use std::ptr; + +fn main() { + (&ptr::write)(1 as *mut _, 42); + //~^ ERROR E0133 +} diff --git a/tests/ui/issues/issue-28776.thir.stderr b/tests/ui/issues/issue-28776.thir.stderr new file mode 100644 index 000000000..e3562810b --- /dev/null +++ b/tests/ui/issues/issue-28776.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `std::ptr::write` is unsafe and requires unsafe function or block + --> $DIR/issue-28776.rs:7:5 + | +LL | (&ptr::write)(1 as *mut _, 42); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-28777.rs b/tests/ui/issues/issue-28777.rs new file mode 100644 index 000000000..1f426b718 --- /dev/null +++ b/tests/ui/issues/issue-28777.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_braces)] +fn main() { + let v1 = { 1 + {2} * {3} }; + let v2 = 1 + {2} * {3} ; + + assert_eq!(7, v1); + assert_eq!(7, v2); + + let v3; + v3 = { 1 + {2} * {3} }; + let v4; + v4 = 1 + {2} * {3}; + assert_eq!(7, v3); + assert_eq!(7, v4); + + let v5 = { 1 + {2} * 3 }; + assert_eq!(7, v5); + + let v9 = { 1 + if 1 > 2 {1} else {2} * {3} }; + assert_eq!(7, v9); +} diff --git a/tests/ui/issues/issue-28822.rs b/tests/ui/issues/issue-28822.rs new file mode 100644 index 000000000..10e5d1dd0 --- /dev/null +++ b/tests/ui/issues/issue-28822.rs @@ -0,0 +1,7 @@ +// check-pass +#![allow(dead_code)] + +fn main() {} + +const fn size_ofs(_: usize) {} +const fn size_ofs2(_foo: usize) {} diff --git a/tests/ui/issues/issue-28828.rs b/tests/ui/issues/issue-28828.rs new file mode 100644 index 000000000..03968809e --- /dev/null +++ b/tests/ui/issues/issue-28828.rs @@ -0,0 +1,18 @@ +// run-pass +pub trait Foo { + type Out; +} + +impl Foo for () { + type Out = bool; +} + +fn main() { + type Bool = <() as Foo>::Out; + + let x: Bool = true; + assert!(x); + + let y: Option = None; + assert_eq!(y, None); +} diff --git a/tests/ui/issues/issue-28839.rs b/tests/ui/issues/issue-28839.rs new file mode 100644 index 000000000..73be87a0c --- /dev/null +++ b/tests/ui/issues/issue-28839.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-pretty issue #37199 + +pub struct Foo; + +pub fn get_foo2<'a>(foo: &'a mut Option<&'a mut Foo>) -> &'a mut Foo { + match foo { + // Ensure that this is not considered a move, but rather a reborrow. + &mut Some(ref mut x) => *x, + &mut None => panic!(), + } +} + +fn main() { +} diff --git a/tests/ui/issues/issue-28936.rs b/tests/ui/issues/issue-28936.rs new file mode 100644 index 000000000..da9e92c0c --- /dev/null +++ b/tests/ui/issues/issue-28936.rs @@ -0,0 +1,27 @@ +// check-pass +pub type Session = i32; +pub struct StreamParser<'a, T> { + _tokens: T, + _session: &'a mut Session, +} + +impl<'a, T> StreamParser<'a, T> { + pub fn thing(&mut self) -> bool { true } +} + +pub fn parse_stream, U, F>( + _session: &mut Session, _tokens: T, _f: F) -> U + where F: Fn(&mut StreamParser) -> U { panic!(); } + +pub fn thing(session: &mut Session) { + let mut stream = vec![1, 2, 3].into_iter(); + + let _b = parse_stream(session, + stream.by_ref(), + // replacing the above with the following fixes it + //&mut stream, + |p| p.thing()); + +} + +fn main() {} diff --git a/tests/ui/issues/issue-2895.rs b/tests/ui/issues/issue-2895.rs new file mode 100644 index 000000000..d8c08996b --- /dev/null +++ b/tests/ui/issues/issue-2895.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] + +use std::mem; + +struct Cat { + x: isize +} + +struct Kitty { + x: isize, +} + +impl Drop for Kitty { + fn drop(&mut self) {} +} + +#[cfg(target_pointer_width = "64")] +pub fn main() { + assert_eq!(mem::size_of::(), 8 as usize); + assert_eq!(mem::size_of::(), 8 as usize); +} + +#[cfg(target_pointer_width = "32")] +pub fn main() { + assert_eq!(mem::size_of::(), 4 as usize); + assert_eq!(mem::size_of::(), 4 as usize); +} diff --git a/tests/ui/issues/issue-28971.rs b/tests/ui/issues/issue-28971.rs new file mode 100644 index 000000000..f0a1e2d00 --- /dev/null +++ b/tests/ui/issues/issue-28971.rs @@ -0,0 +1,16 @@ +enum Foo { + Bar(u8) +} +fn main(){ + foo(|| { + match Foo::Bar(1) { + Foo::Baz(..) => (), + //~^ ERROR no variant or associated item named `Baz` found + _ => (), + } + }); +} + +fn foo(f: F) where F: FnMut() { + f(); +} diff --git a/tests/ui/issues/issue-28971.stderr b/tests/ui/issues/issue-28971.stderr new file mode 100644 index 000000000..2eb8a1c26 --- /dev/null +++ b/tests/ui/issues/issue-28971.stderr @@ -0,0 +1,15 @@ +error[E0599]: no variant or associated item named `Baz` found for enum `Foo` in the current scope + --> $DIR/issue-28971.rs:7:18 + | +LL | enum Foo { + | -------- variant or associated item `Baz` not found for this enum +... +LL | Foo::Baz(..) => (), + | ^^^ + | | + | variant or associated item not found in `Foo` + | help: there is a variant with a similar name: `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-28983.rs b/tests/ui/issues/issue-28983.rs new file mode 100644 index 000000000..3db26a1ee --- /dev/null +++ b/tests/ui/issues/issue-28983.rs @@ -0,0 +1,22 @@ +// run-pass +pub trait Test { type T; } + +impl Test for u32 { + type T = i32; +} + +pub mod export { + #[no_mangle] + pub extern "C" fn issue_28983(t: ::T) -> i32 { t*3 } +} + +// to test both exporting and importing functions, import +// a function from ourselves. +extern "C" { + fn issue_28983(t: ::T) -> i32; +} + +fn main() { + assert_eq!(export::issue_28983(2), 6); + assert_eq!(unsafe { issue_28983(3) }, 9); +} diff --git a/tests/ui/issues/issue-28992-empty.rs b/tests/ui/issues/issue-28992-empty.rs new file mode 100644 index 000000000..74cfeb6db --- /dev/null +++ b/tests/ui/issues/issue-28992-empty.rs @@ -0,0 +1,16 @@ +// Can't use constants as tuple struct patterns + + +const C1: i32 = 0; + +struct S; + +impl S { + const C2: i32 = 0; +} + +fn main() { + if let C1(..) = 0 {} //~ ERROR expected tuple struct or tuple variant, found constant `C1` + if let S::C2(..) = 0 {} + //~^ ERROR expected tuple struct or tuple variant, found associated constant `S::C2` +} diff --git a/tests/ui/issues/issue-28992-empty.stderr b/tests/ui/issues/issue-28992-empty.stderr new file mode 100644 index 000000000..f69773b8c --- /dev/null +++ b/tests/ui/issues/issue-28992-empty.stderr @@ -0,0 +1,16 @@ +error[E0532]: expected tuple struct or tuple variant, found constant `C1` + --> $DIR/issue-28992-empty.rs:13:12 + | +LL | if let C1(..) = 0 {} + | ^^ not a tuple struct or tuple variant + +error[E0164]: expected tuple struct or tuple variant, found associated constant `S::C2` + --> $DIR/issue-28992-empty.rs:14:12 + | +LL | if let S::C2(..) = 0 {} + | ^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0164, E0532. +For more information about an error, try `rustc --explain E0164`. diff --git a/tests/ui/issues/issue-28999.rs b/tests/ui/issues/issue-28999.rs new file mode 100644 index 000000000..cec3e25da --- /dev/null +++ b/tests/ui/issues/issue-28999.rs @@ -0,0 +1,11 @@ +// check-pass +pub struct Xyz<'a, V> { + pub v: (V, &'a u32), +} + +pub fn eq<'a, 's, 't, V>(this: &'s Xyz<'a, V>, other: &'t Xyz<'a, V>) -> bool + where V: PartialEq { + this.v == other.v +} + +fn main() {} diff --git a/tests/ui/issues/issue-29030.rs b/tests/ui/issues/issue-29030.rs new file mode 100644 index 000000000..723e35840 --- /dev/null +++ b/tests/ui/issues/issue-29030.rs @@ -0,0 +1,9 @@ +// check-pass +#![allow(dead_code)] +#[derive(Debug)] +struct Message<'a, P: 'a = &'a [u8]> { + header: &'a [u8], + payload: P, +} + +fn main() {} diff --git a/tests/ui/issues/issue-29037.rs b/tests/ui/issues/issue-29037.rs new file mode 100644 index 000000000..155ed144b --- /dev/null +++ b/tests/ui/issues/issue-29037.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(dead_code)] +// This test ensures that each pointer type `P` is covariant in `X`. + +use std::rc::Rc; +use std::sync::Arc; + +fn a<'r>(x: Box<&'static str>) -> Box<&'r str> { + x +} + +fn b<'r, 'w>(x: &'w &'static str) -> &'w &'r str { + x +} + +fn c<'r>(x: Arc<&'static str>) -> Arc<&'r str> { + x +} + +fn d<'r>(x: Rc<&'static str>) -> Rc<&'r str> { + x +} + +fn main() {} diff --git a/tests/ui/issues/issue-2904.rs b/tests/ui/issues/issue-2904.rs new file mode 100644 index 000000000..73aa78f09 --- /dev/null +++ b/tests/ui/issues/issue-2904.rs @@ -0,0 +1,79 @@ +// build-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + +// Map representation + +use std::fmt; +use std::io::prelude::*; +use square::{bot, wall, rock, lambda, closed_lift, open_lift, earth, empty}; + +enum square { + bot, + wall, + rock, + lambda, + closed_lift, + open_lift, + earth, + empty +} + +impl fmt::Debug for square { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", match *self { + bot => { "R".to_string() } + wall => { "#".to_string() } + rock => { "*".to_string() } + lambda => { "\\".to_string() } + closed_lift => { "L".to_string() } + open_lift => { "O".to_string() } + earth => { ".".to_string() } + empty => { " ".to_string() } + }) + } +} + +fn square_from_char(c: char) -> square { + match c { + 'R' => { bot } + '#' => { wall } + '*' => { rock } + '\\' => { lambda } + 'L' => { closed_lift } + 'O' => { open_lift } + '.' => { earth } + ' ' => { empty } + _ => { + println!("invalid square: {}", c); + panic!() + } + } +} + +fn read_board_grid(mut input: rdr) + -> Vec> { + let mut input: &mut dyn Read = &mut input; + let mut grid = Vec::new(); + let mut line = [0; 10]; + input.read(&mut line); + let mut row = Vec::new(); + for c in &line { + row.push(square_from_char(*c as char)) + } + grid.push(row); + let width = grid[0].len(); + for row in &grid { assert_eq!(row.len(), width) } + grid +} + +mod test { + #[test] + pub fn trivial_to_string() { + assert_eq!(lambda.to_string(), "\\") + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-29048.rs b/tests/ui/issues/issue-29048.rs new file mode 100644 index 000000000..039f072f1 --- /dev/null +++ b/tests/ui/issues/issue-29048.rs @@ -0,0 +1,12 @@ +// check-pass +pub struct Chan; +pub struct ChanSelect<'c, T> { + chans: Vec<(&'c Chan, T)>, +} +impl<'c, T> ChanSelect<'c, T> { + pub fn add_recv_ret(&mut self, chan: &'c Chan, ret: T) + { + self.chans.push((chan, ret)); + } +} +fn main() {} diff --git a/tests/ui/issues/issue-29053.rs b/tests/ui/issues/issue-29053.rs new file mode 100644 index 000000000..34c4a0f8f --- /dev/null +++ b/tests/ui/issues/issue-29053.rs @@ -0,0 +1,12 @@ +// run-pass +fn main() { + let x: &'static str = "x"; + + { + let y = "y".to_string(); + let ref mut x = &*x; + *x = &*y; + } + + assert_eq!(x, "x"); +} diff --git a/tests/ui/issues/issue-29071-2.rs b/tests/ui/issues/issue-29071-2.rs new file mode 100644 index 000000000..f27bf0261 --- /dev/null +++ b/tests/ui/issues/issue-29071-2.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(dead_code)] +fn t1() -> u32 { + let x; + x = if true { [1, 2, 3] } else { [2, 3, 4] }[0]; + x +} + +fn t2() -> [u32; 1] { + if true { [1, 2, 3]; } else { [2, 3, 4]; } + [0] +} + +fn t3() -> u32 { + let x; + x = if true { i1 as F } else { i2 as F }(); + x +} + +fn t4() -> () { + if true { i1 as F; } else { i2 as F; } + () +} + +type F = fn() -> u32; +fn i1() -> u32 { 1 } +fn i2() -> u32 { 2 } + +fn main() { + assert_eq!(t1(), 1); + assert_eq!(t3(), 1); +} diff --git a/tests/ui/issues/issue-29071.rs b/tests/ui/issues/issue-29071.rs new file mode 100644 index 000000000..8bdacf2ce --- /dev/null +++ b/tests/ui/issues/issue-29071.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +fn ret() -> u32 { + static x: u32 = 10; + x & if true { 10u32 } else { 20u32 } & x +} + +fn ret2() -> &'static u32 { + static x: u32 = 10; + if true { 10u32; } else { 20u32; } + &x +} + +fn main() {} diff --git a/tests/ui/issues/issue-29092.rs b/tests/ui/issues/issue-29092.rs new file mode 100644 index 000000000..f20d2a424 --- /dev/null +++ b/tests/ui/issues/issue-29092.rs @@ -0,0 +1,26 @@ +// run-pass +// Regression test for Issue #29092. +// +// (Possibly redundant with regression test run-pass/issue-30530.rs) + +use self::Term::*; + +#[derive(Clone)] +pub enum Term { + Dummy, + A(Box), + B(Box), +} + +// a small-step evaluator +pub fn small_eval(v: Term) -> Term { + match v { + A(t) => *t.clone(), + B(t) => *t.clone(), + _ => Dummy, + } +} + +fn main() { + small_eval(Dummy); +} diff --git a/tests/ui/issues/issue-29147-rpass.rs b/tests/ui/issues/issue-29147-rpass.rs new file mode 100644 index 000000000..439f8bb53 --- /dev/null +++ b/tests/ui/issues/issue-29147-rpass.rs @@ -0,0 +1,28 @@ +// run-pass +#![recursion_limit="1024"] +#![allow(dead_code)] + +use std::mem; + +pub struct S0(T,T); +pub struct S1(Option>>>,Option>>>); +pub struct S2(Option>>>,Option>>>); +pub struct S3(Option>>>,Option>>>); +pub struct S4(Option>>>,Option>>>); +pub struct S5(Option>>>,Option>>>,Option); + +trait Foo { fn xxx(&self); } +/// some local of #[fundamental] trait +trait Bar {} + +impl Foo for T where T: Bar, T: Sync { + fn xxx(&self) {} +} + +impl Foo for S5 { fn xxx(&self) {} } + +fn main() { + let s = S5(None,None,None); + s.xxx(); + assert_eq!(mem::size_of_val(&s.2), mem::size_of::>()); +} diff --git a/tests/ui/issues/issue-29147.rs b/tests/ui/issues/issue-29147.rs new file mode 100644 index 000000000..190ecf460 --- /dev/null +++ b/tests/ui/issues/issue-29147.rs @@ -0,0 +1,23 @@ +#![recursion_limit="1024"] +#![allow(dead_code)] + +pub struct S0(T,T); +pub struct S1(Option>>>,Option>>>); +pub struct S2(Option>>>,Option>>>); +pub struct S3(Option>>>,Option>>>); +pub struct S4(Option>>>,Option>>>); +pub struct S5(Option>>>,Option>>>,Option); + +trait Foo { fn xxx(&self); } +trait Bar {} // anything local or #[fundamental] + +impl Foo for T where T: Bar, T: Sync { + fn xxx(&self) {} +} + +impl Foo for S5 { fn xxx(&self) {} } +impl Foo for S5 { fn xxx(&self) {} } + +fn main() { + let _ = >::xxx; //~ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-29147.stderr b/tests/ui/issues/issue-29147.stderr new file mode 100644 index 000000000..138d477dc --- /dev/null +++ b/tests/ui/issues/issue-29147.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed + --> $DIR/issue-29147.rs:22:13 + | +LL | let _ = >::xxx; + | ^^^^^^^^^^^^ cannot infer type for struct `S5<_>` + | +note: multiple `impl`s satisfying `S5<_>: Foo` found + --> $DIR/issue-29147.rs:18:1 + | +LL | impl Foo for S5 { fn xxx(&self) {} } + | ^^^^^^^^^^^^^^^^^^^^ +LL | impl Foo for S5 { fn xxx(&self) {} } + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-29181.rs b/tests/ui/issues/issue-29181.rs new file mode 100644 index 000000000..70e5bc019 --- /dev/null +++ b/tests/ui/issues/issue-29181.rs @@ -0,0 +1,9 @@ +// aux-build:issue-29181.rs + +extern crate issue_29181 as foo; + +fn main() { + 0.homura(); //~ ERROR no method named `homura` found + // Issue #47759, detect existing method on the fundamental impl: + let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type +} diff --git a/tests/ui/issues/issue-29181.stderr b/tests/ui/issues/issue-29181.stderr new file mode 100644 index 000000000..53addf2fe --- /dev/null +++ b/tests/ui/issues/issue-29181.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `homura` found for type `{integer}` in the current scope + --> $DIR/issue-29181.rs:6:7 + | +LL | 0.homura(); + | ^^^^^^ method not found in `{integer}` + +error[E0689]: can't call method `exp` on ambiguous numeric type `{float}` + --> $DIR/issue-29181.rs:8:30 + | +LL | let _ = |x: f64| x * 2.0.exp(); + | ^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | let _ = |x: f64| x * 2.0_f32.exp(); + | ~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0689. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-29265.rs b/tests/ui/issues/issue-29265.rs new file mode 100644 index 000000000..f554c4d16 --- /dev/null +++ b/tests/ui/issues/issue-29265.rs @@ -0,0 +1,10 @@ +// aux-build:issue-29265.rs +// check-pass + +extern crate issue_29265 as lib; + +static _UNUSED: &'static lib::SomeType = &lib::SOME_VALUE; + +fn main() { + vec![0u8; lib::SOME_VALUE.some_member]; +} diff --git a/tests/ui/issues/issue-29276.rs b/tests/ui/issues/issue-29276.rs new file mode 100644 index 000000000..02b695659 --- /dev/null +++ b/tests/ui/issues/issue-29276.rs @@ -0,0 +1,5 @@ +// check-pass +#![allow(dead_code)] +struct S([u8; { struct Z; 0 }]); + +fn main() {} diff --git a/tests/ui/issues/issue-2935.rs b/tests/ui/issues/issue-2935.rs new file mode 100644 index 000000000..37f818199 --- /dev/null +++ b/tests/ui/issues/issue-2935.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +//type t = { a: isize }; +// type t = { a: bool }; +type t = bool; + +trait it { + fn f(&self); +} + +impl it for t { + fn f(&self) { } +} + +pub fn main() { + // let x = ({a: 4} as it); + // let y = box ({a: 4}); + // let z = box ({a: 4} as it); + // let z = box ({a: true} as it); + let z: Box<_> = Box::new(Box::new(true) as Box); + // x.f(); + // y.f(); + // (*z).f(); + println!("ok so far..."); + z.f(); //segfault +} diff --git a/tests/ui/issues/issue-29466.rs b/tests/ui/issues/issue-29466.rs new file mode 100644 index 000000000..f8785a632 --- /dev/null +++ b/tests/ui/issues/issue-29466.rs @@ -0,0 +1,3603 @@ +// ignore-tidy-filelength +// +// run-pass + +#![allow(unused_variables)] + +macro_rules! m( + ($e1:expr => $e2:expr) => ({ $e1 }) +); + +fn main() { + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + let x = m!(1 => 2); + + println!("{}", x); +} diff --git a/tests/ui/issues/issue-29485.rs b/tests/ui/issues/issue-29485.rs new file mode 100644 index 000000000..8d58ee6d9 --- /dev/null +++ b/tests/ui/issues/issue-29485.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_attributes)] +// aux-build:issue-29485.rs +// needs-unwind +// ignore-emscripten no threads + +#[feature(recover)] + +extern crate a; + +fn main() { + let _ = std::thread::spawn(move || { + a::f(&mut a::X(0), g); + }).join(); +} + +fn g() { + panic!(); +} diff --git a/tests/ui/issues/issue-2951.rs b/tests/ui/issues/issue-2951.rs new file mode 100644 index 000000000..1798e3e75 --- /dev/null +++ b/tests/ui/issues/issue-2951.rs @@ -0,0 +1,11 @@ +fn foo(x: T, y: U) { + let mut xx = x; + xx = y; + //~^ ERROR mismatched types + //~| expected type parameter `T`, found type parameter `U` + //~| expected type parameter `T` + //~| found type parameter `U` +} + +fn main() { +} diff --git a/tests/ui/issues/issue-2951.stderr b/tests/ui/issues/issue-2951.stderr new file mode 100644 index 000000000..538bbe2f5 --- /dev/null +++ b/tests/ui/issues/issue-2951.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-2951.rs:3:10 + | +LL | fn foo(x: T, y: U) { + | - - found type parameter + | | + | expected type parameter +LL | let mut xx = x; + | - expected due to this value +LL | xx = y; + | ^ expected type parameter `T`, found type parameter `U` + | + = note: expected type parameter `T` + found type parameter `U` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-29516.rs b/tests/ui/issues/issue-29516.rs new file mode 100644 index 000000000..6779d508d --- /dev/null +++ b/tests/ui/issues/issue-29516.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait NotSame {} + +impl !NotSame for (A, A) {} + +trait OneOfEach {} + +impl OneOfEach for (A,) {} + +impl OneOfEach for (A, B) +where + (B,): OneOfEach, + (A, B): NotSame, +{ +} + +fn main() {} diff --git a/tests/ui/issues/issue-29522.rs b/tests/ui/issues/issue-29522.rs new file mode 100644 index 000000000..3d2de5ef6 --- /dev/null +++ b/tests/ui/issues/issue-29522.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_variables)] +// check that we don't accidentally capture upvars just because their name +// occurs in a path + +fn assert_static(_t: T) {} + +mod foo { + pub fn scope() {} +} + +fn main() { + let scope = &mut 0; + assert_static(|| { + foo::scope(); + }); +} diff --git a/tests/ui/issues/issue-29540.rs b/tests/ui/issues/issue-29540.rs new file mode 100644 index 000000000..c0de20822 --- /dev/null +++ b/tests/ui/issues/issue-29540.rs @@ -0,0 +1,492 @@ +// build-pass +#[derive(Debug)] +pub struct Config { + pub name: String, + pub cluster: String, + pub debug_none: String, + pub debug_lockdep: String, + pub debug_context: String, + pub debug_crush: String, + pub debug_mds: String, + pub debug_mds_balancer: String, + pub debug_mds_locker: String, + pub debug_mds_log: String, + pub debug_mds_log_expire: String, + pub debug_mds_migrator: String, + pub debug_buffer: String, + pub debug_timer: String, + pub debug_filer: String, + pub debug_striper: String, + pub debug_objecter: String, + pub debug_rados: String, + pub debug_rbd: String, + pub debug_journaler: String, + pub debug_objectcacher: String, + pub debug_client: String, + pub debug_osd: String, + pub debug_optracker: String, + pub debug_objclass: String, + pub debug_filestore: String, + pub debug_keyvaluestore: String, + pub debug_journal: String, + pub debug_ms: String, + pub debug_mon: String, + pub debug_monc: String, + pub debug_paxos: String, + pub debug_tp: String, + pub debug_auth: String, + pub debug_crypto: String, + pub debug_finisher: String, + pub debug_heartbeatmap: String, + pub debug_perfcounter: String, + pub debug_rgw: String, + pub debug_civetweb: String, + pub debug_javaclient: String, + pub debug_asok: String, + pub debug_throttle: String, + pub host: String, + pub fsid: String, + pub public_addr: String, + pub cluster_addr: String, + pub public_network: String, + pub cluster_network: String, + pub num_client: String, + pub monmap: String, + pub mon_host: String, + pub lockdep: String, + pub run_dir: String, + pub admin_socket: String, + pub daemonize: String, + pub pid_file: String, + pub chdir: String, + pub max_open_files: String, + pub restapi_log_level: String, + pub restapi_base_url: String, + pub fatal_signal_handlers: String, + pub log_file: String, + pub log_max_new: String, + pub log_max_recent: String, + pub log_to_stderr: String, + pub err_to_stderr: String, + pub log_to_syslog: String, + pub err_to_syslog: String, + pub log_flush_on_exit: String, + pub log_stop_at_utilization: String, + pub clog_to_monitors: String, + pub clog_to_syslog: String, + pub clog_to_syslog_level: String, + pub clog_to_syslog_facility: String, + pub mon_cluster_log_to_syslog: String, + pub mon_cluster_log_to_syslog_level: String, + pub mon_cluster_log_to_syslog_facility: String, + pub mon_cluster_log_file: String, + pub mon_cluster_log_file_level: String, + pub key: String, + pub keyfile: String, + pub keyring: String, + pub heartbeat_interval: String, + pub heartbeat_file: String, + pub heartbeat_inject_failure: String, + pub perf: String, + pub ms_tcp_nodelay: String, + pub ms_tcp_rcvbuf: String, + pub ms_initial_backoff: String, + pub ms_max_backoff: String, + pub ms_nocrc: String, + pub ms_die_on_bad_msg: String, + pub ms_die_on_unhandled_msg: String, + pub ms_die_on_old_message: String, + pub ms_dispatch_throttle_bytes: String, + pub ms_bind_ipv6: String, + pub ms_bind_port_min: String, + pub ms_bind_port_max: String, + pub ms_rwthread_stack_bytes: String, + pub ms_tcp_read_timeout: String, + pub ms_pq_max_tokens_per_priority: String, + pub ms_pq_min_cost: String, + pub ms_inject_socket_failures: String, + pub ms_inject_delay_type: String, + pub ms_inject_delay_msg_type: String, + pub ms_inject_delay_max: String, + pub ms_inject_delay_probability: String, + pub ms_inject_internal_delays: String, + pub ms_dump_on_send: String, + pub inject_early_sigterm: String, + pub mon_data: String, + pub mon_initial_members: String, + pub mon_sync_fs_threshold: String, + pub mon_compact_on_start: String, + pub mon_compact_on_bootstrap: String, + pub mon_compact_on_trim: String, + pub mon_tick_interval: String, + pub mon_subscribe_interval: String, + pub mon_delta_reset_interval: String, + pub mon_osd_laggy_halflife: String, + pub mon_osd_laggy_weight: String, + pub mon_osd_adjust_heartbeat_grace: String, + pub mon_osd_adjust_down_out_interval: String, + pub mon_osd_auto_mark_in: String, + pub mon_osd_auto_mark_auto_out_in: String, + pub mon_osd_auto_mark_new_in: String, + pub mon_osd_down_out_interval: String, + pub mon_osd_down_out_subtree_limit: String, + pub mon_osd_min_up_ratio: String, + pub mon_osd_min_in_ratio: String, + pub mon_osd_max_op_age: String, + pub mon_osd_max_split_count: String, + pub mon_osd_allow_primary_temp: String, + pub mon_osd_allow_primary_affinity: String, + pub mon_stat_smooth_intervals: String, + pub mon_lease: String, + pub mon_lease_renew_interval: String, + pub mon_lease_ack_timeout: String, + pub mon_clock_drift_allowed: String, + pub mon_clock_drift_warn_backoff: String, + pub mon_timecheck_interval: String, + pub mon_accept_timeout: String, + pub mon_pg_create_interval: String, + pub mon_pg_stuck_threshold: String, + pub mon_pg_warn_min_per_osd: String, + pub mon_pg_warn_max_object_skew: String, + pub mon_pg_warn_min_objects: String, + pub mon_pg_warn_min_pool_objects: String, + pub mon_cache_target_full_warn_ratio: String, + pub mon_osd_full_ratio: String, + pub mon_osd_nearfull_ratio: String, + pub mon_globalid_prealloc: String, + pub mon_osd_report_timeout: String, + pub mon_force_standby_active: String, + pub mon_warn_on_old_mons: String, + pub mon_warn_on_legacy_crush_tunables: String, + pub mon_warn_on_osd_down_out_interval_zero: String, + pub mon_warn_on_cache_pools_without_hit_sets: String, + pub mon_min_osdmap_epochs: String, + pub mon_max_pgmap_epochs: String, + pub mon_max_log_epochs: String, + pub mon_max_mdsmap_epochs: String, + pub mon_max_osd: String, + pub mon_probe_timeout: String, + pub mon_slurp_timeout: String, + pub mon_slurp_bytes: String, + pub mon_client_bytes: String, + pub mon_daemon_bytes: String, + pub mon_max_log_entries_per_event: String, + pub mon_health_data_update_interval: String, + pub mon_data_avail_crit: String, + pub mon_data_avail_warn: String, + pub mon_config_key_max_entry_size: String, + pub mon_sync_timeout: String, + pub mon_sync_max_payload_size: String, + pub mon_sync_debug: String, + pub mon_sync_debug_leader: String, + pub mon_sync_debug_provider: String, + pub mon_sync_debug_provider_fallback: String, + pub mon_inject_sync_get_chunk_delay: String, + pub mon_osd_min_down_reporters: String, + pub mon_osd_min_down_reports: String, + pub mon_osd_force_trim_to: String, + pub mon_mds_force_trim_to: String, + pub mon_advanced_debug_mode: String, + pub mon_debug_dump_transactions: String, + pub mon_debug_dump_location: String, + pub mon_sync_provider_kill_at: String, + pub mon_sync_requester_kill_at: String, + pub mon_leveldb_write_buffer_size: String, + pub mon_leveldb_cache_size: String, + pub mon_leveldb_block_size: String, + pub mon_leveldb_bloom_size: String, + pub mon_leveldb_max_open_files: String, + pub mon_leveldb_compression: String, + pub mon_leveldb_paranoid: String, + pub mon_leveldb_log: String, + pub mon_leveldb_size_warn: String, + pub mon_force_quorum_join: String, + pub paxos_stash_full_interval: String, + pub paxos_max_join_drift: String, + pub paxos_propose_interval: String, + pub paxos_min_wait: String, + pub paxos_min: String, + pub paxos_trim_min: String, + pub paxos_trim_max: String, + pub paxos_service_trim_min: String, + pub paxos_service_trim_max: String, + pub paxos_kill_at: String, + pub clock_offset: String, + pub auth_cluster_required: String, + pub auth_service_required: String, + pub auth_client_required: String, + pub auth_supported: String, + pub cephx_require_signatures: String, + pub cephx_cluster_require_signatures: String, + pub cephx_service_require_signatures: String, + pub cephx_sign_messages: String, + pub auth_mon_ticket_ttl: String, + pub auth_service_ticket_ttl: String, + pub auth_debug: String, + pub mon_client_hunt_interval: String, + pub mon_client_ping_interval: String, + pub mon_client_ping_timeout: String, + pub mon_client_hunt_interval_backoff: String, + pub mon_client_hunt_interval_max_multiple: String, + pub mon_client_max_log_entries_per_message: String, + pub mon_max_pool_pg_num: String, + pub mon_pool_quota_warn_threshold: String, + pub mon_pool_quota_crit_threshold: String, + pub client_cache_size: String, + pub client_cache_mid: String, + pub client_use_random_mds: String, + pub client_mount_timeout: String, + pub client_tick_interval: String, + pub client_trace: String, + pub client_readahead_min: String, + pub client_readahead_max_bytes: String, + pub client_readahead_max_periods: String, + pub client_snapdir: String, + pub client_mountpoint: String, + pub client_notify_timeout: String, + pub osd_client_watch_timeout: String, + pub client_caps_release_delay: String, + pub client_oc: String, + pub client_oc_size: String, + pub client_oc_max_dirty: String, + pub client_oc_target_dirty: String, + pub client_oc_max_dirty_age: String, + pub client_oc_max_objects: String, + pub client_debug_force_sync_read: String, + pub client_debug_inject_tick_delay: String, + pub client_max_inline_size: String, + pub fuse_use_invalidate_cb: String, + pub fuse_allow_other: String, + pub fuse_default_permissions: String, + pub fuse_big_writes: String, + pub fuse_atomic_o_trunc: String, + pub fuse_debug: String, + pub fuse_multithreaded: String, + pub crush_location: String, + pub objecter_tick_interval: String, + pub objecter_timeout: String, + pub objecter_inflight_op_bytes: String, + pub objecter_inflight_ops: String, + pub journaler_allow_split_entries: String, + pub journaler_write_head_interval: String, + pub journaler_prefetch_periods: String, + pub journaler_prezero_periods: String, + pub journaler_batch_interval: String, + pub journaler_batch_max: String, + pub mds_data: String, + pub mds_max_file_size: String, + pub mds_cache_size: String, + pub mds_cache_mid: String, + pub mds_mem_max: String, + pub mds_dir_max_commit_size: String, + pub mds_decay_halflife: String, + pub mds_beacon_interval: String, + pub mds_beacon_grace: String, + pub mds_enforce_unique_name: String, + pub mds_interval: String, + pub mds_session_timeout: String, + pub mds_freeze_tree_timeout: String, + pub mds_session_autoclose: String, + pub mds_reconnect_timeout: String, + pub mds_tick_interval: String, + pub mds_dirstat_min_interval: String, + pub mds_scatter_nudge_interval: String, + pub mds_client_prealloc_inos: String, + pub mds_early_reply: String, + pub mds_default_dir_hash: String, + pub mds_log: String, + pub mds_log_skip_corrupt_events: String, + pub mds_log_max_events: String, + pub mds_log_segment_size: String, + pub mds_log_max_segments: String, + pub mds_log_max_expiring: String, + pub mds_bal_sample_interval: String, + pub mds_bal_replicate_threshold: String, + pub mds_bal_unreplicate_threshold: String, + pub mds_bal_frag: String, + pub mds_bal_split_size: String, + pub mds_bal_split_rd: String, + pub mds_bal_split_wr: String, + pub mds_bal_split_bits: String, + pub mds_bal_merge_size: String, + pub mds_bal_merge_rd: String, + pub mds_bal_merge_wr: String, + pub mds_bal_interval: String, + pub mds_bal_fragment_interval: String, + pub mds_bal_idle_threshold: String, + pub mds_bal_max: String, + pub mds_bal_max_until: String, + pub mds_bal_mode: String, + pub mds_bal_min_rebalance: String, + pub mds_bal_min_start: String, + pub mds_bal_need_min: String, + pub mds_bal_need_max: String, + pub mds_bal_midchunk: String, + pub mds_bal_minchunk: String, + pub mds_bal_target_removal_min: String, + pub mds_bal_target_removal_max: String, + pub mds_replay_interval: String, + pub mds_shutdown_check: String, + pub mds_thrash_exports: String, + pub mds_thrash_fragments: String, + pub mds_dump_cache_on_map: String, + pub mds_dump_cache_after_rejoin: String, + pub mds_verify_scatter: String, + pub mds_debug_scatterstat: String, + pub mds_debug_frag: String, + pub mds_debug_auth_pins: String, + pub mds_debug_subtrees: String, + pub mds_kill_mdstable_at: String, + pub mds_kill_export_at: String, + pub mds_kill_import_at: String, + pub mds_kill_link_at: String, + pub mds_kill_rename_at: String, + pub mds_kill_openc_at: String, + pub mds_kill_journal_at: String, + pub mds_kill_journal_expire_at: String, + pub mds_kill_journal_replay_at: String, + pub mds_kill_create_at: String, + pub mds_open_remote_link_mode: String, + pub mds_inject_traceless_reply_probability: String, + pub mds_wipe_sessions: String, + pub mds_wipe_ino_prealloc: String, + pub mds_skip_ino: String, + pub max_mds: String, + pub mds_standby_for_name: String, + pub mds_standby_for_rank: String, + pub mds_standby_replay: String, + pub osd_compact_leveldb_on_mount: String, + pub osd_max_backfills: String, + pub osd_backfill_full_ratio: String, + pub osd_backfill_retry_interval: String, + pub osd_agent_max_ops: String, + pub osd_agent_min_evict_effort: String, + pub osd_agent_quantize_effort: String, + pub osd_agent_delay_time: String, + pub osd_agent_hist_halflife: String, + pub osd_agent_slop: String, + pub osd_uuid: String, + pub osd_data: String, + pub osd_journal: String, + pub osd_journal_size: String, + pub osd_max_write_size: String, + pub osd_max_pgls: String, + pub osd_client_message_size_cap: String, + pub osd_client_message_cap: String, + pub osd_pg_bits: String, + pub osd_pgp_bits: String, + pub osd_crush_chooseleaf_type: String, + pub osd_pool_default_crush_rule: String, + pub osd_pool_default_crush_replicated_ruleset: String, + pub osd_pool_erasure_code_stripe_width: String, + pub osd_pool_default_size: String, + pub osd_pool_default_min_size: String, + pub osd_pool_default_pg_num: String, + pub osd_pool_default_pgp_num: String, + pub osd_pool_default_erasure_code_directory: String, + pub osd_pool_default_erasure_code_profile: String, + pub osd_erasure_code_plugins: String, + pub osd_pool_default_flags: String, + pub osd_pool_default_flag_hashpspool: String, + pub osd_pool_default_hit_set_bloom_fpp: String, + pub osd_pool_default_cache_target_dirty_ratio: String, + pub osd_pool_default_cache_target_full_ratio: String, + pub osd_pool_default_cache_min_flush_age: String, + pub osd_pool_default_cache_min_evict_age: String, + pub osd_hit_set_min_size: String, + pub osd_hit_set_max_size: String, + pub osd_hit_set_namespace: String, + pub osd_tier_default_cache_mode: String, + pub osd_tier_default_cache_hit_set_count: String, + pub osd_tier_default_cache_hit_set_period: String, + pub osd_tier_default_cache_hit_set_type: String, + pub osd_map_dedup: String, + pub osd_map_max_advance: String, + pub osd_map_cache_size: String, + pub osd_map_message_max: String, + pub osd_map_share_max_epochs: String, + pub osd_op_threads: String, + pub osd_peering_wq_batch_size: String, + pub osd_op_pq_max_tokens_per_priority: String, + pub osd_op_pq_min_cost: String, + pub osd_disk_threads: String, + pub osd_disk_thread_ioprio_class: String, + pub osd_disk_thread_ioprio_priority: String, + pub osd_recovery_threads: String, + pub osd_recover_clone_overlap: String, + pub osd_recover_clone_overlap_limit: String, + pub osd_backfill_scan_min: String, + pub osd_backfill_scan_max: String, + pub osd_op_thread_timeout: String, + pub osd_recovery_thread_timeout: String, + pub osd_snap_trim_thread_timeout: String, + pub osd_snap_trim_sleep: String, + pub osd_scrub_thread_timeout: String, + pub osd_scrub_finalize_thread_timeout: String, + pub osd_scrub_invalid_stats: String, + pub osd_remove_thread_timeout: String, + pub osd_command_thread_timeout: String, + pub osd_age: String, + pub osd_age_time: String, + pub osd_heartbeat_addr: String, + pub osd_heartbeat_interval: String, + pub osd_heartbeat_grace: String, + pub osd_heartbeat_min_peers: String, + pub osd_pg_max_concurrent_snap_trims: String, + pub osd_heartbeat_min_healthy_ratio: String, + pub osd_mon_heartbeat_interval: String, + pub osd_mon_report_interval_max: String, + pub osd_mon_report_interval_min: String, + pub osd_pg_stat_report_interval_max: String, + pub osd_mon_ack_timeout: String, + pub osd_default_data_pool_replay_window: String, + pub osd_preserve_trimmed_log: String, + pub osd_auto_mark_unfound_lost: String, + pub osd_recovery_delay_start: String, + pub osd_recovery_max_active: String, + pub osd_recovery_max_single_start: String, + pub osd_recovery_max_chunk: String, + pub osd_copyfrom_max_chunk: String, + pub osd_push_per_object_cost: String, + pub osd_max_push_cost: String, + pub osd_max_push_objects: String, + pub osd_recovery_forget_lost_objects: String, + pub osd_max_scrubs: String, + pub osd_scrub_load_threshold: String, + pub osd_scrub_min_interval: String, + pub osd_scrub_max_interval: String, + pub osd_scrub_chunk_min: String, + pub osd_scrub_chunk_max: String, + pub osd_scrub_sleep: String, + pub osd_deep_scrub_interval: String, + pub osd_deep_scrub_stride: String, + pub osd_scan_list_ping_tp_interval: String, + pub osd_auto_weight: String, + pub osd_class_dir: String, + pub osd_open_classes_on_start: String, + pub osd_check_for_log_corruption: String, + pub osd_use_stale_snap: String, + pub osd_rollback_to_cluster_snap: String, + pub osd_default_notify_timeout: String, + pub osd_kill_backfill_at: String, + pub osd_pg_epoch_persisted_max_stale: String, + pub osd_min_pg_log_entries: String, + pub osd_max_pg_log_entries: String, + pub osd_op_complaint_time: String, + pub osd_command_max_records: String, + pub osd_op_log_threshold: String, + pub osd_verify_sparse_read_holes: String, + pub osd_debug_drop_ping_probability: String, + pub osd_debug_drop_ping_duration: String, + pub osd_debug_drop_pg_create_probability: String, + pub osd_debug_drop_pg_create_duration: String, + pub osd_debug_drop_op_probability: String, + pub osd_debug_op_order: String, + pub osd_debug_verify_snaps_on_info: String, + pub osd_debug_verify_stray_on_activate: String, + pub osd_debug_skip_full_check_in_backfill_reservation: String, + pub osd_debug_reject_backfill_probability: String, + pub osd_enable_op_tracker: String, +} + +fn main() {} diff --git a/tests/ui/issues/issue-29663.rs b/tests/ui/issues/issue-29663.rs new file mode 100644 index 000000000..e2e89a8bf --- /dev/null +++ b/tests/ui/issues/issue-29663.rs @@ -0,0 +1,56 @@ +// run-pass +#![allow(stable_features)] +// write_volatile causes an LLVM assert with composite types + +#![feature(volatile)] +use std::ptr::{read_volatile, write_volatile}; + +#[derive(Debug, Eq, PartialEq)] +struct A(u32); +#[derive(Debug, Eq, PartialEq)] +struct B(u64); +#[derive(Debug, Eq, PartialEq)] +struct C(u32, u32); +#[derive(Debug, Eq, PartialEq)] +struct D(u64, u64); +#[derive(Debug, Eq, PartialEq)] +struct E([u64; 32]); + +fn main() { + unsafe { + let mut x: u32 = 0; + write_volatile(&mut x, 1); + assert_eq!(read_volatile(&x), 1); + assert_eq!(x, 1); + + let mut x: u64 = 0; + write_volatile(&mut x, 1); + assert_eq!(read_volatile(&x), 1); + assert_eq!(x, 1); + + let mut x = A(0); + write_volatile(&mut x, A(1)); + assert_eq!(read_volatile(&x), A(1)); + assert_eq!(x, A(1)); + + let mut x = B(0); + write_volatile(&mut x, B(1)); + assert_eq!(read_volatile(&x), B(1)); + assert_eq!(x, B(1)); + + let mut x = C(0, 0); + write_volatile(&mut x, C(1, 1)); + assert_eq!(read_volatile(&x), C(1, 1)); + assert_eq!(x, C(1, 1)); + + let mut x = D(0, 0); + write_volatile(&mut x, D(1, 1)); + assert_eq!(read_volatile(&x), D(1, 1)); + assert_eq!(x, D(1, 1)); + + let mut x = E([0; 32]); + write_volatile(&mut x, E([1; 32])); + assert_eq!(read_volatile(&x), E([1; 32])); + assert_eq!(x, E([1; 32])); + } +} diff --git a/tests/ui/issues/issue-29668.rs b/tests/ui/issues/issue-29668.rs new file mode 100644 index 000000000..3d6c27bcd --- /dev/null +++ b/tests/ui/issues/issue-29668.rs @@ -0,0 +1,16 @@ +// run-pass +// Functions can return unnameable types + +mod m1 { + mod m2 { + #[derive(Debug)] + pub struct A; + } + use self::m2::A; + pub fn x() -> A { A } +} + +fn main() { + let x = m1::x(); + println!("{:?}", x); +} diff --git a/tests/ui/issues/issue-29710.rs b/tests/ui/issues/issue-29710.rs new file mode 100644 index 000000000..bc98d389c --- /dev/null +++ b/tests/ui/issues/issue-29710.rs @@ -0,0 +1,11 @@ +// check-pass +#![deny(unused_results)] +#![allow(dead_code)] + +#[derive(Debug)] +struct A(usize); + +#[derive(Debug)] +struct B { a: usize } + +fn main() {} diff --git a/tests/ui/issues/issue-29723.rs b/tests/ui/issues/issue-29723.rs new file mode 100644 index 000000000..399e9ba0d --- /dev/null +++ b/tests/ui/issues/issue-29723.rs @@ -0,0 +1,22 @@ +// test for https://github.com/rust-lang/rust/issues/29723 + +#![feature(if_let_guard)] + +fn main() { + let s = String::new(); + let _s = match 0 { + 0 if { drop(s); false } => String::from("oops"), + _ => { + // This should trigger an error, + // s could have been moved from. + s + //~^ ERROR use of moved value: `s` + } + }; + + let s = String::new(); + let _s = match 0 { + 0 if let Some(()) = { drop(s); None } => String::from("oops"), + _ => s //~ ERROR use of moved value: `s` + }; +} diff --git a/tests/ui/issues/issue-29723.stderr b/tests/ui/issues/issue-29723.stderr new file mode 100644 index 000000000..044d8a9b5 --- /dev/null +++ b/tests/ui/issues/issue-29723.stderr @@ -0,0 +1,36 @@ +error[E0382]: use of moved value: `s` + --> $DIR/issue-29723.rs:12:13 + | +LL | let s = String::new(); + | - move occurs because `s` has type `String`, which does not implement the `Copy` trait +LL | let _s = match 0 { +LL | 0 if { drop(s); false } => String::from("oops"), + | - value moved here +... +LL | s + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | 0 if { drop(s.clone()); false } => String::from("oops"), + | ++++++++ + +error[E0382]: use of moved value: `s` + --> $DIR/issue-29723.rs:20:14 + | +LL | let s = String::new(); + | - move occurs because `s` has type `String`, which does not implement the `Copy` trait +LL | let _s = match 0 { +LL | 0 if let Some(()) = { drop(s); None } => String::from("oops"), + | - value moved here +LL | _ => s + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | 0 if let Some(()) = { drop(s.clone()); None } => String::from("oops"), + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-29740.rs b/tests/ui/issues/issue-29740.rs new file mode 100644 index 000000000..20398890b --- /dev/null +++ b/tests/ui/issues/issue-29740.rs @@ -0,0 +1,317 @@ +// check-pass +#![allow(dead_code)] +// Regression test for #29740. Inefficient MIR matching algorithms +// generated way too much code for this sort of case, leading to OOM. +#![allow(non_snake_case)] + +pub mod KeyboardEventConstants { + pub const DOM_KEY_LOCATION_STANDARD: u32 = 0; + pub const DOM_KEY_LOCATION_LEFT: u32 = 1; + pub const DOM_KEY_LOCATION_RIGHT: u32 = 2; + pub const DOM_KEY_LOCATION_NUMPAD: u32 = 3; +} // mod KeyboardEventConstants + +pub enum Key { + Space, + Apostrophe, + Comma, + Minus, + Period, + Slash, + Num0, + Num1, + Num2, + Num3, + Num4, + Num5, + Num6, + Num7, + Num8, + Num9, + Semicolon, + Equal, + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + LeftBracket, + Backslash, + RightBracket, + GraveAccent, + World1, + World2, + + Escape, + Enter, + Tab, + Backspace, + Insert, + Delete, + Right, + Left, + Down, + Up, + PageUp, + PageDown, + Home, + End, + CapsLock, + ScrollLock, + NumLock, + PrintScreen, + Pause, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + F25, + Kp0, + Kp1, + Kp2, + Kp3, + Kp4, + Kp5, + Kp6, + Kp7, + Kp8, + Kp9, + KpDecimal, + KpDivide, + KpMultiply, + KpSubtract, + KpAdd, + KpEnter, + KpEqual, + LeftShift, + LeftControl, + LeftAlt, + LeftSuper, + RightShift, + RightControl, + RightAlt, + RightSuper, + Menu, +} + +fn key_from_string(key_string: &str, location: u32) -> Option { + match key_string { + " " => Some(Key::Space), + "\"" => Some(Key::Apostrophe), + "'" => Some(Key::Apostrophe), + "<" => Some(Key::Comma), + "," => Some(Key::Comma), + "_" => Some(Key::Minus), + "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Minus), + ">" => Some(Key::Period), + "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Period), + "?" => Some(Key::Slash), + "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Slash), + "~" => Some(Key::GraveAccent), + "`" => Some(Key::GraveAccent), + ")" => Some(Key::Num0), + "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num0), + "!" => Some(Key::Num1), + "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num1), + "@" => Some(Key::Num2), + "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num2), + "#" => Some(Key::Num3), + "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num3), + "$" => Some(Key::Num4), + "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num4), + "%" => Some(Key::Num5), + "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num5), + "^" => Some(Key::Num6), + "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num6), + "&" => Some(Key::Num7), + "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num7), + "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8), + "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num8), + "(" => Some(Key::Num9), + "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Num9), + ":" => Some(Key::Semicolon), + ";" => Some(Key::Semicolon), + "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal), + "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD => Some(Key::Equal), + "A" => Some(Key::A), + "a" => Some(Key::A), + "B" => Some(Key::B), + "b" => Some(Key::B), + "C" => Some(Key::C), + "c" => Some(Key::C), + "D" => Some(Key::D), + "d" => Some(Key::D), + "E" => Some(Key::E), + "e" => Some(Key::E), + "F" => Some(Key::F), + "f" => Some(Key::F), + "G" => Some(Key::G), + "g" => Some(Key::G), + "H" => Some(Key::H), + "h" => Some(Key::H), + "I" => Some(Key::I), + "i" => Some(Key::I), + "J" => Some(Key::J), + "j" => Some(Key::J), + "K" => Some(Key::K), + "k" => Some(Key::K), + "L" => Some(Key::L), + "l" => Some(Key::L), + "M" => Some(Key::M), + "m" => Some(Key::M), + "N" => Some(Key::N), + "n" => Some(Key::N), + "O" => Some(Key::O), + "o" => Some(Key::O), + "P" => Some(Key::P), + "p" => Some(Key::P), + "Q" => Some(Key::Q), + "q" => Some(Key::Q), + "R" => Some(Key::R), + "r" => Some(Key::R), + "S" => Some(Key::S), + "s" => Some(Key::S), + "T" => Some(Key::T), + "t" => Some(Key::T), + "U" => Some(Key::U), + "u" => Some(Key::U), + "V" => Some(Key::V), + "v" => Some(Key::V), + "W" => Some(Key::W), + "w" => Some(Key::W), + "X" => Some(Key::X), + "x" => Some(Key::X), + "Y" => Some(Key::Y), + "y" => Some(Key::Y), + "Z" => Some(Key::Z), + "z" => Some(Key::Z), + "{" => Some(Key::LeftBracket), + "[" => Some(Key::LeftBracket), + "|" => Some(Key::Backslash), + "\\" => Some(Key::Backslash), + "}" => Some(Key::RightBracket), + "]" => Some(Key::RightBracket), + "Escape" => Some(Key::Escape), + "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_STANDARD + => Some(Key::Enter), + "Tab" => Some(Key::Tab), + "Backspace" => Some(Key::Backspace), + "Insert" => Some(Key::Insert), + "Delete" => Some(Key::Delete), + "ArrowRight" => Some(Key::Right), + "ArrowLeft" => Some(Key::Left), + "ArrowDown" => Some(Key::Down), + "ArrowUp" => Some(Key::Up), + "PageUp" => Some(Key::PageUp), + "PageDown" => Some(Key::PageDown), + "Home" => Some(Key::Home), + "End" => Some(Key::End), + "CapsLock" => Some(Key::CapsLock), + "ScrollLock" => Some(Key::ScrollLock), + "NumLock" => Some(Key::NumLock), + "PrintScreen" => Some(Key::PrintScreen), + "Pause" => Some(Key::Pause), + "F1" => Some(Key::F1), + "F2" => Some(Key::F2), + "F3" => Some(Key::F3), + "F4" => Some(Key::F4), + "F5" => Some(Key::F5), + "F6" => Some(Key::F6), + "F7" => Some(Key::F7), + "F8" => Some(Key::F8), + "F9" => Some(Key::F9), + "F10" => Some(Key::F10), + "F11" => Some(Key::F11), + "F12" => Some(Key::F12), + "F13" => Some(Key::F13), + "F14" => Some(Key::F14), + "F15" => Some(Key::F15), + "F16" => Some(Key::F16), + "F17" => Some(Key::F17), + "F18" => Some(Key::F18), + "F19" => Some(Key::F19), + "F20" => Some(Key::F20), + "F21" => Some(Key::F21), + "F22" => Some(Key::F22), + "F23" => Some(Key::F23), + "F24" => Some(Key::F24), + "F25" => Some(Key::F25), + "0" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp0), + "1" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp1), + "2" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp2), + "3" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp3), + "4" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp4), + "5" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp5), + "6" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp6), + "7" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp7), + "8" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp8), + "9" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::Kp9), + "." if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDecimal), + "/" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpDivide), + "*" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpMultiply), + "-" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpSubtract), + "+" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpAdd), + "Enter" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD + => Some(Key::KpEnter), + "=" if location == KeyboardEventConstants::DOM_KEY_LOCATION_NUMPAD => Some(Key::KpEqual), + "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT + => Some(Key::LeftShift), + "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT + => Some(Key::LeftControl), + "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT => Some(Key::LeftAlt), + "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_LEFT + => Some(Key::LeftSuper), + "Shift" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT + => Some(Key::RightShift), + "Control" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT + => Some(Key::RightControl), + "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightAlt), + "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT + => Some(Key::RightSuper), + "ContextMenu" => Some(Key::Menu), + _ => None + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-29743.rs b/tests/ui/issues/issue-29743.rs new file mode 100644 index 000000000..250cd7e1b --- /dev/null +++ b/tests/ui/issues/issue-29743.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() { + let mut i = [1, 2, 3]; + i[i[0]] = 0; + i[i[0] - 1] = 0; +} diff --git a/tests/ui/issues/issue-29746.rs b/tests/ui/issues/issue-29746.rs new file mode 100644 index 000000000..3470a7e09 --- /dev/null +++ b/tests/ui/issues/issue-29746.rs @@ -0,0 +1,36 @@ +// run-pass +// zip!(a1,a2,a3,a4) is equivalent to: +// a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4)) +macro_rules! zip { + // Entry point + ([$a:expr, $b:expr, $($rest:expr),*]) => { + zip!([$($rest),*], $a.zip($b), (x,y), [x,y]) + }; + + // Intermediate steps to build the zipped expression, the match pattern + // and the output tuple of the closure, using macro hygiene to repeatedly + // introduce new variables named 'x'. + ([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => { + zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x]) + }; + + // Final step + ([], $zip:expr, $pat:pat, [$($flat:expr),+]) => { + $zip.map(|$pat| ($($flat),+)) + }; + + // Comma + ([$a:expr], $zip:expr, $pat:pat, [$($flat:expr),*]) => { + zip!([$a,], $zip, $pat, [$($flat),*]) + }; +} + +fn main() { + let p1 = vec![1i32, 2].into_iter(); + let p2 = vec!["10", "20"].into_iter(); + let p3 = vec![100u16, 200].into_iter(); + let p4 = vec![1000i64, 2000].into_iter(); + + let e = zip!([p1,p2,p3,p4]).collect::>(); + assert_eq!(e[0], (1i32,"10",100u16,1000i64)); +} diff --git a/tests/ui/issues/issue-29798.rs b/tests/ui/issues/issue-29798.rs new file mode 100644 index 000000000..5eff5d191 --- /dev/null +++ b/tests/ui/issues/issue-29798.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 5 +// ignore-emscripten no processes + +const fn test(x: usize) -> i32 { + [42;5][x] +} + +fn main () { + let _ = test(5); +} diff --git a/tests/ui/issues/issue-29821.rs b/tests/ui/issues/issue-29821.rs new file mode 100644 index 000000000..54be3afb5 --- /dev/null +++ b/tests/ui/issues/issue-29821.rs @@ -0,0 +1,19 @@ +// build-pass + +pub trait Foo { + type FooAssoc; +} + +pub struct Bar { + id: F::FooAssoc +} + +pub struct Baz; + +impl Foo for Baz { + type FooAssoc = usize; +} + +static mut MY_FOO: Bar = Bar { id: 0 }; + +fn main() {} diff --git a/tests/ui/issues/issue-29857.rs b/tests/ui/issues/issue-29857.rs new file mode 100644 index 000000000..6f4c5f45d --- /dev/null +++ b/tests/ui/issues/issue-29857.rs @@ -0,0 +1,19 @@ +// check-pass + +use std::marker::PhantomData; + +pub trait Foo

{} + +impl > Foo

for Option {} + +pub struct Qux (PhantomData<*mut T>); + +impl Foo<*mut T> for Option> {} + +pub trait Bar { + type Output: 'static; +} + +impl> Foo<*mut T> for W {} + +fn main() {} diff --git a/tests/ui/issues/issue-29861.rs b/tests/ui/issues/issue-29861.rs new file mode 100644 index 000000000..58f8eb536 --- /dev/null +++ b/tests/ui/issues/issue-29861.rs @@ -0,0 +1,20 @@ +pub trait MakeRef<'a> { + type Ref; +} +impl<'a, T: 'a> MakeRef<'a> for T { + type Ref = &'a T; +} + +pub trait MakeRef2 { + type Ref2; +} +impl<'a, T: 'a> MakeRef2 for T { +//~^ ERROR the lifetime parameter `'a` is not constrained + type Ref2 = >::Ref; +} + +fn foo() -> ::Ref2 { &String::from("foo") } + +fn main() { + println!("{}", foo()); +} diff --git a/tests/ui/issues/issue-29861.stderr b/tests/ui/issues/issue-29861.stderr new file mode 100644 index 000000000..d9d3cf360 --- /dev/null +++ b/tests/ui/issues/issue-29861.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-29861.rs:11:6 + | +LL | impl<'a, T: 'a> MakeRef2 for T { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-2989.rs b/tests/ui/issues/issue-2989.rs new file mode 100644 index 000000000..c0b673743 --- /dev/null +++ b/tests/ui/issues/issue-2989.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(non_camel_case_types)] + +trait methods { + fn to_bytes(&self) -> Vec ; +} + +impl methods for () { + fn to_bytes(&self) -> Vec { + Vec::new() + } +} + +// the position of this function is significant! - if it comes before methods +// then it works, if it comes after it then it doesn't! +fn to_bools(bitv: Storage) -> Vec { + (0..8).map(|i| { + let w = i / 64; + let b = i % 64; + let x = 1 & (bitv.storage[w] >> b); + x == 1 + }).collect() +} + +struct Storage { storage: Vec } + +pub fn main() { + let bools = vec![false, false, true, false, false, true, true, false]; + let bools2 = to_bools(Storage{storage: vec![0b01100100]}); + + for i in 0..8 { + println!("{} => {} vs {}", i, bools[i], bools2[i]); + } + + assert_eq!(bools, bools2); +} diff --git a/tests/ui/issues/issue-29948.rs b/tests/ui/issues/issue-29948.rs new file mode 100644 index 000000000..3ed701480 --- /dev/null +++ b/tests/ui/issues/issue-29948.rs @@ -0,0 +1,40 @@ +// run-pass +// needs-unwind + +use std::panic; + +impl<'a> panic::UnwindSafe for Foo<'a> {} +impl<'a> panic::RefUnwindSafe for Foo<'a> {} + +struct Foo<'a>(&'a mut bool); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + *self.0 = true; + } +} + +fn f(t: T) { + t() +} + +fn main() { + let mut ran_drop = false; + { + let x = Foo(&mut ran_drop); + let x = move || { let _ = x; }; + f(x); + } + assert!(ran_drop); + + let mut ran_drop = false; + { + let x = Foo(&mut ran_drop); + let result = panic::catch_unwind(move || { + let x = move || { let _ = x; panic!() }; + f(x); + }); + assert!(result.is_err()); + } + assert!(ran_drop); +} diff --git a/tests/ui/issues/issue-2995.rs b/tests/ui/issues/issue-2995.rs new file mode 100644 index 000000000..0da790948 --- /dev/null +++ b/tests/ui/issues/issue-2995.rs @@ -0,0 +1,5 @@ +fn bad (p: *const isize) { + let _q: &isize = p as &isize; //~ ERROR non-primitive cast +} + +fn main() { } diff --git a/tests/ui/issues/issue-2995.stderr b/tests/ui/issues/issue-2995.stderr new file mode 100644 index 000000000..0d09612c6 --- /dev/null +++ b/tests/ui/issues/issue-2995.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `*const isize` as `&isize` + --> $DIR/issue-2995.rs:2:22 + | +LL | let _q: &isize = p as &isize; + | ^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL - let _q: &isize = p as &isize; +LL + let _q: &isize = &*p; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/issues/issue-30007.rs b/tests/ui/issues/issue-30007.rs new file mode 100644 index 000000000..918a821ba --- /dev/null +++ b/tests/ui/issues/issue-30007.rs @@ -0,0 +1,7 @@ +macro_rules! t { + () => ( String ; ); //~ ERROR macro expansion ignores token `;` +} + +fn main() { + let i: Vec; +} diff --git a/tests/ui/issues/issue-30007.stderr b/tests/ui/issues/issue-30007.stderr new file mode 100644 index 000000000..87e770e15 --- /dev/null +++ b/tests/ui/issues/issue-30007.stderr @@ -0,0 +1,13 @@ +error: macro expansion ignores token `;` and any following + --> $DIR/issue-30007.rs:2:20 + | +LL | () => ( String ; ); + | ^ +... +LL | let i: Vec; + | ---- caused by the macro expansion here + | + = note: the usage of `t!` is likely invalid in type context + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-30018-panic.rs b/tests/ui/issues/issue-30018-panic.rs new file mode 100644 index 000000000..cba3055a2 --- /dev/null +++ b/tests/ui/issues/issue-30018-panic.rs @@ -0,0 +1,26 @@ +// run-pass +// Regression test for Issue #30018. This is very similar to the +// original reported test, except that the panic is wrapped in a +// spawned thread to isolate the expected error result from the +// SIGTRAP injected by the drop-flag consistency checking. + +// needs-unwind +// ignore-emscripten no threads support + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn foo() -> Foo { + panic!(); +} + +fn main() { + use std::thread; + let handle = thread::spawn(|| { + let _ = &[foo()]; + }); + let _ = handle.join(); +} diff --git a/tests/ui/issues/issue-3008-1.rs b/tests/ui/issues/issue-3008-1.rs new file mode 100644 index 000000000..1124969e6 --- /dev/null +++ b/tests/ui/issues/issue-3008-1.rs @@ -0,0 +1,12 @@ +enum Foo { + Foo_(Bar) +} + +enum Bar { + //~^ ERROR recursive type `Bar` has infinite size + BarNone, + BarSome(Bar) +} + +fn main() { +} diff --git a/tests/ui/issues/issue-3008-1.stderr b/tests/ui/issues/issue-3008-1.stderr new file mode 100644 index 000000000..be25b9091 --- /dev/null +++ b/tests/ui/issues/issue-3008-1.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `Bar` has infinite size + --> $DIR/issue-3008-1.rs:5:1 + | +LL | enum Bar { + | ^^^^^^^^ +... +LL | BarSome(Bar) + | --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | BarSome(Box) + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-3008-2.rs b/tests/ui/issues/issue-3008-2.rs new file mode 100644 index 000000000..5846c69da --- /dev/null +++ b/tests/ui/issues/issue-3008-2.rs @@ -0,0 +1,6 @@ +enum Foo { Foo_(Bar) } +struct Bar { x: Bar } +//~^ ERROR E0072 + +fn main() { +} diff --git a/tests/ui/issues/issue-3008-2.stderr b/tests/ui/issues/issue-3008-2.stderr new file mode 100644 index 000000000..858a8fd6a --- /dev/null +++ b/tests/ui/issues/issue-3008-2.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Bar` has infinite size + --> $DIR/issue-3008-2.rs:2:1 + | +LL | struct Bar { x: Bar } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Bar { x: Box } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-3008-3.rs b/tests/ui/issues/issue-3008-3.rs new file mode 100644 index 000000000..212eb2eb8 --- /dev/null +++ b/tests/ui/issues/issue-3008-3.rs @@ -0,0 +1,10 @@ +use std::marker; + +enum E1 { V1(E2), } +enum E2 { V2(E2, marker::PhantomData), } +//~^ ERROR recursive type `E2` has infinite size + +impl E1 { fn foo(&self) {} } + +fn main() { +} diff --git a/tests/ui/issues/issue-3008-3.stderr b/tests/ui/issues/issue-3008-3.stderr new file mode 100644 index 000000000..a1a81e293 --- /dev/null +++ b/tests/ui/issues/issue-3008-3.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `E2` has infinite size + --> $DIR/issue-3008-3.rs:4:1 + | +LL | enum E2 { V2(E2, marker::PhantomData), } + | ^^^^^^^^^^ ------ recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum E2 { V2(Box>, marker::PhantomData), } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-30081.rs b/tests/ui/issues/issue-30081.rs new file mode 100644 index 000000000..e7fca96ed --- /dev/null +++ b/tests/ui/issues/issue-30081.rs @@ -0,0 +1,15 @@ +// run-pass +// This used to segfault #30081 + +pub enum Instruction { + Increment(i8), + Loop(Box>), +} + +fn main() { + let instrs: Option<(u8, Box)> = None; + instrs.into_iter() + .map(|(_, instr)| instr) + .map(|instr| match *instr { _other => {} }) + .last(); +} diff --git a/tests/ui/issues/issue-3012-2.rs b/tests/ui/issues/issue-3012-2.rs new file mode 100644 index 000000000..7d32c51f5 --- /dev/null +++ b/tests/ui/issues/issue-3012-2.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:issue-3012-1.rs + +// pretty-expanded FIXME #23616 + +extern crate socketlib; + +use socketlib::socket; + +pub fn main() { + let fd: u32 = 1 as u32; + let _sock: Box<_> = Box::new(socket::socket_handle(fd)); +} diff --git a/tests/ui/issues/issue-30123.rs b/tests/ui/issues/issue-30123.rs new file mode 100644 index 000000000..705355d91 --- /dev/null +++ b/tests/ui/issues/issue-30123.rs @@ -0,0 +1,9 @@ +// aux-build:issue-30123-aux.rs + +extern crate issue_30123_aux; +use issue_30123_aux::*; + +fn main() { + let ug = Graph::::new_undirected(); + //~^ ERROR no function or associated item named `new_undirected` found +} diff --git a/tests/ui/issues/issue-30123.stderr b/tests/ui/issues/issue-30123.stderr new file mode 100644 index 000000000..7808cbf8a --- /dev/null +++ b/tests/ui/issues/issue-30123.stderr @@ -0,0 +1,12 @@ +error[E0599]: no function or associated item named `new_undirected` found for struct `Graph` in the current scope + --> $DIR/issue-30123.rs:7:33 + | +LL | let ug = Graph::::new_undirected(); + | ^^^^^^^^^^^^^^ function or associated item not found in `Graph` + | + = note: the function or associated item was found for + - `issue_30123_aux::Graph` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-3021-b.rs b/tests/ui/issues/issue-3021-b.rs new file mode 100644 index 000000000..f1630afe1 --- /dev/null +++ b/tests/ui/issues/issue-3021-b.rs @@ -0,0 +1,14 @@ +fn siphash(k0 : u64) { + + struct SipHash { + v0: u64, + } + + impl SipHash { + pub fn reset(&mut self) { + self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment + } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-3021-b.stderr b/tests/ui/issues/issue-3021-b.stderr new file mode 100644 index 000000000..72289c5f9 --- /dev/null +++ b/tests/ui/issues/issue-3021-b.stderr @@ -0,0 +1,11 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/issue-3021-b.rs:9:22 + | +LL | self.v0 = k0 ^ 0x736f6d6570736575; + | ^^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/issues/issue-3021-d.rs b/tests/ui/issues/issue-3021-d.rs new file mode 100644 index 000000000..1fb0002b2 --- /dev/null +++ b/tests/ui/issues/issue-3021-d.rs @@ -0,0 +1,28 @@ +trait SipHash { + fn result(&self) -> u64; + fn reset(&self); +} + +fn siphash(k0 : u64, k1 : u64) { + struct SipState { + v0: u64, + v1: u64, + } + + fn mk_result(st : &SipState) -> u64 { + + let v0 = st.v0; + let v1 = st.v1; + return v0 ^ v1; + } + + impl SipHash for SipState { + fn reset(&self) { + self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment + self.v1 = k1 ^ 0x646f72616e646f6d; //~ ERROR can't capture dynamic environment + } + fn result(&self) -> u64 { return mk_result(self); } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-3021-d.stderr b/tests/ui/issues/issue-3021-d.stderr new file mode 100644 index 000000000..39e6e8c43 --- /dev/null +++ b/tests/ui/issues/issue-3021-d.stderr @@ -0,0 +1,19 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/issue-3021-d.rs:21:23 + | +LL | self.v0 = k0 ^ 0x736f6d6570736575; + | ^^ + | + = help: use the `|| { ... }` closure form instead + +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/issue-3021-d.rs:22:23 + | +LL | self.v1 = k1 ^ 0x646f72616e646f6d; + | ^^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/issues/issue-30236.rs b/tests/ui/issues/issue-30236.rs new file mode 100644 index 000000000..9c2d85507 --- /dev/null +++ b/tests/ui/issues/issue-30236.rs @@ -0,0 +1,7 @@ +type Foo< + Unused //~ ERROR type parameter `Unused` is unused + > = u8; + +fn main() { + +} diff --git a/tests/ui/issues/issue-30236.stderr b/tests/ui/issues/issue-30236.stderr new file mode 100644 index 000000000..64cbd58d6 --- /dev/null +++ b/tests/ui/issues/issue-30236.stderr @@ -0,0 +1,9 @@ +error[E0091]: type parameter `Unused` is unused + --> $DIR/issue-30236.rs:2:5 + | +LL | Unused + | ^^^^^^ unused type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0091`. diff --git a/tests/ui/issues/issue-30255.rs b/tests/ui/issues/issue-30255.rs new file mode 100644 index 000000000..6970a122b --- /dev/null +++ b/tests/ui/issues/issue-30255.rs @@ -0,0 +1,24 @@ +// +// Test that lifetime elision error messages correctly omit parameters +// with no elided lifetimes + +struct S<'a> { + field: &'a i32, +} + +fn f(a: &S, b: i32) -> &i32 { +//~^ ERROR missing lifetime specifier [E0106] + panic!(); +} + +fn g(a: &S, b: bool, c: &i32) -> &i32 { +//~^ ERROR missing lifetime specifier [E0106] + panic!(); +} + +fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { +//~^ ERROR missing lifetime specifier [E0106] + panic!(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-30255.stderr b/tests/ui/issues/issue-30255.stderr new file mode 100644 index 000000000..adb721a1c --- /dev/null +++ b/tests/ui/issues/issue-30255.stderr @@ -0,0 +1,39 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-30255.rs:9:24 + | +LL | fn f(a: &S, b: i32) -> &i32 { + | -- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(a: &'a S<'a>, b: i32) -> &'a i32 { + | ++++ ++ ++++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-30255.rs:14:34 + | +LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { + | -- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c` +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(a: &'a S<'a>, b: bool, c: &'a i32) -> &'a i32 { + | ++++ ++ ++++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-30255.rs:19:44 + | +LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { + | ----- -- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d` +help: consider introducing a named lifetime parameter + | +LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S<'a>, d: &'a i32) -> &'a i32 { + | ++++ ++ ++ ++++ ++ ++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-3026.rs b/tests/ui/issues/issue-3026.rs new file mode 100644 index 000000000..4619a3fe7 --- /dev/null +++ b/tests/ui/issues/issue-3026.rs @@ -0,0 +1,11 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::collections::HashMap; + +pub fn main() { + let x: Box<_>; + let mut buggy_map: HashMap = HashMap::new(); + x = Box::new(1); + buggy_map.insert(42, &*x); +} diff --git a/tests/ui/issues/issue-3029.rs b/tests/ui/issues/issue-3029.rs new file mode 100644 index 000000000..a5d30960a --- /dev/null +++ b/tests/ui/issues/issue-3029.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:so long +// ignore-emscripten no processes + +#![allow(unused_allocation)] +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn main() { + let mut x = Vec::new(); + let y = vec![3]; + panic!("so long"); + x.extend(y.into_iter()); +} diff --git a/tests/ui/issues/issue-3037.rs b/tests/ui/issues/issue-3037.rs new file mode 100644 index 000000000..ff4d32c28 --- /dev/null +++ b/tests/ui/issues/issue-3037.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] + +enum what { } + +fn what_to_string(x: what) -> String +{ + match x { + } +} + +pub fn main() +{ +} diff --git a/tests/ui/issues/issue-30371.rs b/tests/ui/issues/issue-30371.rs new file mode 100644 index 000000000..eea548c48 --- /dev/null +++ b/tests/ui/issues/issue-30371.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unreachable_code)] +#![allow(for_loops_over_fallibles)] +#![deny(unused_variables)] + +fn main() { + for _ in match return () { + () => Some(0), + } {} +} diff --git a/tests/ui/issues/issue-3038.rs b/tests/ui/issues/issue-3038.rs new file mode 100644 index 000000000..cf3ba009f --- /dev/null +++ b/tests/ui/issues/issue-3038.rs @@ -0,0 +1,26 @@ +enum F { G(isize, isize) } + +enum H { I(J, K) } + +enum J { L(isize, isize) } +enum K { M(isize, isize) } + +fn main() +{ + + let _z = match F::G(1, 2) { + F::G(x, x) => { println!("{}", x + x); } + //~^ ERROR identifier `x` is bound more than once in the same pattern + }; + + let _z = match H::I(J::L(1, 2), K::M(3, 4)) { + H::I(J::L(x, _), K::M(_, x)) + //~^ ERROR identifier `x` is bound more than once in the same pattern + => { println!("{}", x + x); } + }; + + let _z = match (1, 2) { + (x, x) => { x } //~ ERROR identifier `x` is bound more than once in the same pattern + }; + +} diff --git a/tests/ui/issues/issue-3038.stderr b/tests/ui/issues/issue-3038.stderr new file mode 100644 index 000000000..210da2cef --- /dev/null +++ b/tests/ui/issues/issue-3038.stderr @@ -0,0 +1,21 @@ +error[E0416]: identifier `x` is bound more than once in the same pattern + --> $DIR/issue-3038.rs:12:15 + | +LL | F::G(x, x) => { println!("{}", x + x); } + | ^ used in a pattern more than once + +error[E0416]: identifier `x` is bound more than once in the same pattern + --> $DIR/issue-3038.rs:17:32 + | +LL | H::I(J::L(x, _), K::M(_, x)) + | ^ used in a pattern more than once + +error[E0416]: identifier `x` is bound more than once in the same pattern + --> $DIR/issue-3038.rs:23:13 + | +LL | (x, x) => { x } + | ^ used in a pattern more than once + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0416`. diff --git a/tests/ui/issues/issue-30380.rs b/tests/ui/issues/issue-30380.rs new file mode 100644 index 000000000..48b329c5d --- /dev/null +++ b/tests/ui/issues/issue-30380.rs @@ -0,0 +1,36 @@ +// check that panics in destructors during assignment do not leave +// destroyed values lying around for other destructors to observe. + +// run-fail +// error-pattern:panicking destructors ftw! +// ignore-emscripten no processes + +struct Observer<'a>(&'a mut FilledOnDrop); + +struct FilledOnDrop(u32); +impl Drop for FilledOnDrop { + fn drop(&mut self) { + if self.0 == 0 { + // this is only set during the destructor - safe + // code should not be able to observe this. + self.0 = 0x1c1c1c1c; + panic!("panicking destructors ftw!"); + } + } +} + +impl<'a> Drop for Observer<'a> { + fn drop(&mut self) { + assert_eq!(self.0 .0, 1); + } +} + +fn foo(b: &mut Observer) { + *b.0 = FilledOnDrop(1); +} + +fn main() { + let mut bomb = FilledOnDrop(0); + let mut observer = Observer(&mut bomb); + foo(&mut observer); +} diff --git a/tests/ui/issues/issue-30438-a.rs b/tests/ui/issues/issue-30438-a.rs new file mode 100644 index 000000000..0d4eb796a --- /dev/null +++ b/tests/ui/issues/issue-30438-a.rs @@ -0,0 +1,23 @@ +// Original regression test for Issue #30438. + +use std::ops::Index; + +struct Test<'a> { + s: &'a String +} + +impl <'a> Index for Test<'a> { + type Output = Test<'a>; + fn index(&self, _: usize) -> &Self::Output { + return &Test { s: &self.s}; + //~^ ERROR: cannot return reference to temporary value + } +} + +fn main() { + let s = "Hello World".to_string(); + let test = Test{s: &s}; + let r = &test[0]; + println!("{}", test.s); // OK since test is valid + println!("{}", r.s); // Segfault since value pointed by r has already been dropped +} diff --git a/tests/ui/issues/issue-30438-a.stderr b/tests/ui/issues/issue-30438-a.stderr new file mode 100644 index 000000000..53845af82 --- /dev/null +++ b/tests/ui/issues/issue-30438-a.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/issue-30438-a.rs:12:16 + | +LL | return &Test { s: &self.s}; + | ^------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-30438-b.rs b/tests/ui/issues/issue-30438-b.rs new file mode 100644 index 000000000..79510cdb6 --- /dev/null +++ b/tests/ui/issues/issue-30438-b.rs @@ -0,0 +1,24 @@ +// Modified regression test for Issue #30438 that exposed an +// independent issue (see discussion on ticket). + +use std::ops::Index; + +struct Test<'a> { + s: &'a String +} + +impl <'a> Index for Test<'a> { + type Output = Test<'a>; + fn index(&self, _: usize) -> &Self::Output { + &Test { s: &self.s} + //~^ ERROR: cannot return reference to temporary value + } +} + +fn main() { + let s = "Hello World".to_string(); + let test = Test{s: &s}; + let r = &test[0]; + println!("{}", test.s); // OK since test is valid + println!("{}", r.s); // Segfault since value pointed by r has already been dropped +} diff --git a/tests/ui/issues/issue-30438-b.stderr b/tests/ui/issues/issue-30438-b.stderr new file mode 100644 index 000000000..fd6bd25b1 --- /dev/null +++ b/tests/ui/issues/issue-30438-b.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/issue-30438-b.rs:13:9 + | +LL | &Test { s: &self.s} + | ^------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-30438-c.rs b/tests/ui/issues/issue-30438-c.rs new file mode 100644 index 000000000..4cf634245 --- /dev/null +++ b/tests/ui/issues/issue-30438-c.rs @@ -0,0 +1,21 @@ +// Simplified regression test for #30438, inspired by arielb1. + +trait Trait { type Out; } + +struct Test<'a> { s: &'a str } + +fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y as Trait>::Out where 'z: 'static { + //~^ WARN unnecessary lifetime parameter `'z` + let x = Test { s: "this cannot last" }; + &x + //~^ ERROR: cannot return reference to local variable `x` +} + +impl<'b> Trait for Test<'b> { type Out = Test<'b>; } + +fn main() { + let orig = Test { s: "Hello World" }; + let r = silly(&orig); + println!("{}", orig.s); // OK since `orig` is valid + println!("{}", r.s); // Segfault (method does not return a sane value) +} diff --git a/tests/ui/issues/issue-30438-c.stderr b/tests/ui/issues/issue-30438-c.stderr new file mode 100644 index 000000000..a7a5c0500 --- /dev/null +++ b/tests/ui/issues/issue-30438-c.stderr @@ -0,0 +1,17 @@ +warning: unnecessary lifetime parameter `'z` + --> $DIR/issue-30438-c.rs:7:74 + | +LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y as Trait>::Out where 'z: 'static { + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'z` + +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-30438-c.rs:10:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-30490.rs b/tests/ui/issues/issue-30490.rs new file mode 100644 index 000000000..4f0eeac8f --- /dev/null +++ b/tests/ui/issues/issue-30490.rs @@ -0,0 +1,102 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia Child I/O swaps not privileged + +// Previously libstd would set stdio descriptors of a child process +// by `dup`ing the requested descriptors to inherit directly into the +// stdio descriptors. This, however, would incorrectly handle cases +// where the descriptors to inherit were already stdio descriptors. +// This test checks to avoid that regression. + +#![cfg_attr(unix, feature(rustc_private))] +#![cfg_attr(not(unix), allow(unused_imports))] + +#[cfg(unix)] +extern crate libc; + +use std::fs::File; +use std::io::{Read, Write}; +use std::io::{stdout, stderr}; +use std::process::{Command, Stdio}; + +#[cfg(unix)] +use std::os::unix::io::FromRawFd; + +#[cfg(not(unix))] +fn main() { + // Bug not present in Windows +} + +#[cfg(unix)] +fn main() { + let mut args = std::env::args(); + let name = args.next().unwrap(); + let args: Vec = args.collect(); + if let Some("--child") = args.get(0).map(|s| &**s) { + return child(); + } else if !args.is_empty() { + panic!("unknown options"); + } + + let stdout_backup = unsafe { libc::dup(libc::STDOUT_FILENO) }; + let stderr_backup = unsafe { libc::dup(libc::STDERR_FILENO) }; + assert!(stdout_backup > -1); + assert!(stderr_backup > -1); + + let (stdout_reader, stdout_writer) = pipe(); + let (stderr_reader, stderr_writer) = pipe(); + assert!(unsafe { libc::dup2(stdout_writer, libc::STDOUT_FILENO) } > -1); + assert!(unsafe { libc::dup2(stderr_writer, libc::STDERR_FILENO) } > -1); + + // Make sure we close any duplicates of the writer end of the pipe, + // otherwise we can get stuck reading from the pipe which has open + // writers but no one supplying any input + assert_eq!(unsafe { libc::close(stdout_writer) }, 0); + assert_eq!(unsafe { libc::close(stderr_writer) }, 0); + + stdout().write_all("parent stdout\n".as_bytes()).expect("failed to write to stdout"); + stderr().write_all("parent stderr\n".as_bytes()).expect("failed to write to stderr"); + + let child = { + Command::new(name) + .arg("--child") + .stdin(Stdio::inherit()) + .stdout(unsafe { Stdio::from_raw_fd(libc::STDERR_FILENO) }) + .stderr(unsafe { Stdio::from_raw_fd(libc::STDOUT_FILENO) }) + .spawn() + }; + + // The Stdio passed into the Command took over (and closed) std{out, err} + // so we should restore them as they were. + assert!(unsafe { libc::dup2(stdout_backup, libc::STDOUT_FILENO) } > -1); + assert!(unsafe { libc::dup2(stderr_backup, libc::STDERR_FILENO) } > -1); + + // Using File as a shim around the descriptor + let mut read = String::new(); + let mut f: File = unsafe { FromRawFd::from_raw_fd(stdout_reader) }; + f.read_to_string(&mut read).expect("failed to read from stdout file"); + assert_eq!(read, "parent stdout\nchild stderr\n"); + + // Using File as a shim around the descriptor + read.clear(); + let mut f: File = unsafe { FromRawFd::from_raw_fd(stderr_reader) }; + f.read_to_string(&mut read).expect("failed to read from stderr file"); + assert_eq!(read, "parent stderr\nchild stdout\n"); + + assert!(child.expect("failed to execute child process").wait().unwrap().success()); +} + +#[cfg(unix)] +fn child() { + stdout().write_all("child stdout\n".as_bytes()).expect("child failed to write to stdout"); + stderr().write_all("child stderr\n".as_bytes()).expect("child failed to write to stderr"); +} + +#[cfg(unix)] +/// Returns a pipe (reader, writer combo) +fn pipe() -> (i32, i32) { + let mut fds = [0; 2]; + assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0); + (fds[0], fds[1]) +} diff --git a/tests/ui/issues/issue-3052.rs b/tests/ui/issues/issue-3052.rs new file mode 100644 index 000000000..ee2456da3 --- /dev/null +++ b/tests/ui/issues/issue-3052.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +type Connection = Box) + 'static>; + +fn f() -> Option { + let mock_connection: Connection = Box::new(|_| {}); + Some(mock_connection) +} + +pub fn main() { +} diff --git a/tests/ui/issues/issue-30530.rs b/tests/ui/issues/issue-30530.rs new file mode 100644 index 000000000..111fb8aa5 --- /dev/null +++ b/tests/ui/issues/issue-30530.rs @@ -0,0 +1,28 @@ +// run-pass +// Regression test for Issue #30530: alloca's created for storing +// intermediate scratch values during brace-less match arms need to be +// initialized with their drop-flag set to "dropped" (or else we end +// up running the destructors on garbage data at the end of the +// function). + +pub enum Handler { + Default, + #[allow(dead_code)] + Custom(*mut Box), +} + +fn main() { + #[allow(unused_must_use)] { + take(Handler::Default, Box::new(main)); + } +} + +#[inline(never)] +pub fn take(h: Handler, f: Box) -> Box { + unsafe { + match h { + Handler::Custom(ptr) => *Box::from_raw(ptr), + Handler::Default => f, + } + } +} diff --git a/tests/ui/issues/issue-30589.rs b/tests/ui/issues/issue-30589.rs new file mode 100644 index 000000000..94eb58399 --- /dev/null +++ b/tests/ui/issues/issue-30589.rs @@ -0,0 +1,9 @@ +use std::fmt; + +impl fmt::Display for DecoderError { //~ ERROR cannot find type `DecoderError` in this scope + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Missing data: {}", self.0) + } +} +fn main() { +} diff --git a/tests/ui/issues/issue-30589.stderr b/tests/ui/issues/issue-30589.stderr new file mode 100644 index 000000000..4b88547a1 --- /dev/null +++ b/tests/ui/issues/issue-30589.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `DecoderError` in this scope + --> $DIR/issue-30589.rs:3:23 + | +LL | impl fmt::Display for DecoderError { + | ^^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-30615.rs b/tests/ui/issues/issue-30615.rs new file mode 100644 index 000000000..c718449d8 --- /dev/null +++ b/tests/ui/issues/issue-30615.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + &0u8 as *const u8 as *const dyn PartialEq; + &[0u8] as *const [u8; 1] as *const [u8]; +} diff --git a/tests/ui/issues/issue-30756.rs b/tests/ui/issues/issue-30756.rs new file mode 100644 index 000000000..836db951b --- /dev/null +++ b/tests/ui/issues/issue-30756.rs @@ -0,0 +1,7 @@ +// run-pass +#![forbid(unsafe_code)] + +thread_local!(static FOO: u8 = 1); + +fn main() { +} diff --git a/tests/ui/issues/issue-30891.rs b/tests/ui/issues/issue-30891.rs new file mode 100644 index 000000000..30f55e0bd --- /dev/null +++ b/tests/ui/issues/issue-30891.rs @@ -0,0 +1,10 @@ +// run-pass +const ERROR_CONST: bool = true; + +fn get() -> bool { + false || ERROR_CONST +} + +pub fn main() { + assert_eq!(get(), true); +} diff --git a/tests/ui/issues/issue-3091.rs b/tests/ui/issues/issue-3091.rs new file mode 100644 index 000000000..0c0a41242 --- /dev/null +++ b/tests/ui/issues/issue-3091.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let x = 1; + let y = 1; + assert_eq!(&x, &y); +} diff --git a/tests/ui/issues/issue-3099-a.rs b/tests/ui/issues/issue-3099-a.rs new file mode 100644 index 000000000..9c3d8cf5a --- /dev/null +++ b/tests/ui/issues/issue-3099-a.rs @@ -0,0 +1,5 @@ +enum A { B, C } + +enum A { D, E } //~ ERROR the name `A` is defined multiple times + +fn main() {} diff --git a/tests/ui/issues/issue-3099-a.stderr b/tests/ui/issues/issue-3099-a.stderr new file mode 100644 index 000000000..e3733cebb --- /dev/null +++ b/tests/ui/issues/issue-3099-a.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/issue-3099-a.rs:3:1 + | +LL | enum A { B, C } + | ------ previous definition of the type `A` here +LL | +LL | enum A { D, E } + | ^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-3099-b.rs b/tests/ui/issues/issue-3099-b.rs new file mode 100644 index 000000000..71952c3b0 --- /dev/null +++ b/tests/ui/issues/issue-3099-b.rs @@ -0,0 +1,5 @@ +pub mod a {} + +pub mod a {} //~ ERROR the name `a` is defined multiple times + +fn main() {} diff --git a/tests/ui/issues/issue-3099-b.stderr b/tests/ui/issues/issue-3099-b.stderr new file mode 100644 index 000000000..c0cfefeb9 --- /dev/null +++ b/tests/ui/issues/issue-3099-b.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `a` is defined multiple times + --> $DIR/issue-3099-b.rs:3:1 + | +LL | pub mod a {} + | --------- previous definition of the module `a` here +LL | +LL | pub mod a {} + | ^^^^^^^^^ `a` redefined here + | + = note: `a` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-3099.rs b/tests/ui/issues/issue-3099.rs new file mode 100644 index 000000000..ee75b3593 --- /dev/null +++ b/tests/ui/issues/issue-3099.rs @@ -0,0 +1,11 @@ +fn a(x: String) -> String { + format!("First function with {}", x) +} + +fn a(x: String, y: String) -> String { //~ ERROR the name `a` is defined multiple times + format!("Second function with {} and {}", x, y) +} + +fn main() { + println!("Result: "); +} diff --git a/tests/ui/issues/issue-3099.stderr b/tests/ui/issues/issue-3099.stderr new file mode 100644 index 000000000..32ee2e1d2 --- /dev/null +++ b/tests/ui/issues/issue-3099.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `a` is defined multiple times + --> $DIR/issue-3099.rs:5:1 + | +LL | fn a(x: String) -> String { + | ------------------------- previous definition of the value `a` here +... +LL | fn a(x: String, y: String) -> String { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `a` redefined here + | + = note: `a` must be defined only once in the value namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-31011.rs b/tests/ui/issues/issue-31011.rs new file mode 100644 index 000000000..4dead04c2 --- /dev/null +++ b/tests/ui/issues/issue-31011.rs @@ -0,0 +1,29 @@ +macro_rules! log { + ( $ctx:expr, $( $args:expr),* ) => { + if $ctx.trace { + //~^ no field `trace` on type `&T` + println!( $( $args, )* ); + } + } +} + +// Create a structure. +struct Foo { + trace: bool, +} + +// Generic wrapper calls log! with a structure. +fn wrap(context: &T) -> () +{ + log!(context, "entered wrapper"); + //~^ in this expansion of log! +} + +fn main() { + // Create a structure. + let x = Foo { trace: true }; + log!(x, "run started"); + // Apply a closure which accesses internal fields. + wrap(&x); + log!(x, "run finished"); +} diff --git a/tests/ui/issues/issue-31011.stderr b/tests/ui/issues/issue-31011.stderr new file mode 100644 index 000000000..58c170409 --- /dev/null +++ b/tests/ui/issues/issue-31011.stderr @@ -0,0 +1,17 @@ +error[E0609]: no field `trace` on type `&T` + --> $DIR/issue-31011.rs:3:17 + | +LL | if $ctx.trace { + | ^^^^^ +... +LL | fn wrap(context: &T) -> () + | - type parameter 'T' declared here +LL | { +LL | log!(context, "entered wrapper"); + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `log` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-3109.rs b/tests/ui/issues/issue-3109.rs new file mode 100644 index 000000000..bd807cad7 --- /dev/null +++ b/tests/ui/issues/issue-3109.rs @@ -0,0 +1,4 @@ +// run-pass +pub fn main() { + println!("{:?}", ("hi there!", "you")); +} diff --git a/tests/ui/issues/issue-3121.rs b/tests/ui/issues/issue-3121.rs new file mode 100644 index 000000000..4bf5b9b60 --- /dev/null +++ b/tests/ui/issues/issue-3121.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +#[derive(Copy, Clone)] +enum side { mayo, catsup, vinegar } +#[derive(Copy, Clone)] +enum order { hamburger, fries(side), shake } +#[derive(Copy, Clone)] +enum meal { to_go(order), for_here(order) } + +fn foo(m: Box, cond: bool) { + match *m { + meal::to_go(_) => { } + meal::for_here(_) if cond => {} + meal::for_here(order::hamburger) => {} + meal::for_here(order::fries(_s)) => {} + meal::for_here(order::shake) => {} + } +} + +pub fn main() { + foo(Box::new(meal::for_here(order::hamburger)), true) +} diff --git a/tests/ui/issues/issue-31260.rs b/tests/ui/issues/issue-31260.rs new file mode 100644 index 000000000..4db7445b0 --- /dev/null +++ b/tests/ui/issues/issue-31260.rs @@ -0,0 +1,15 @@ +// check-pass +#![allow(dead_code)] +pub struct Struct { + pub field: K, +} + +static STRUCT: Struct<&'static [u8]> = Struct { + field: {&[1]} +}; + +static STRUCT2: Struct<&'static [u8]> = Struct { + field: &[1] +}; + +fn main() {} diff --git a/tests/ui/issues/issue-31267-additional.rs b/tests/ui/issues/issue-31267-additional.rs new file mode 100644 index 000000000..7f0cbd658 --- /dev/null +++ b/tests/ui/issues/issue-31267-additional.rs @@ -0,0 +1,20 @@ +// run-pass + +#[derive(Clone, Copy, Debug)] +struct Bar; + +const BAZ: Bar = Bar; + +#[derive(Debug)] +struct Foo(#[allow(unused_tuple_struct_fields)] [Bar; 1]); + +struct Biz; + +impl Biz { + const BAZ: Foo = Foo([BAZ; 1]); +} + +fn main() { + let foo = Biz::BAZ; + println!("{:?}", foo); +} diff --git a/tests/ui/issues/issue-31267.rs b/tests/ui/issues/issue-31267.rs new file mode 100644 index 000000000..50843c89e --- /dev/null +++ b/tests/ui/issues/issue-31267.rs @@ -0,0 +1,14 @@ +// run-pass +// Regression test for issue #31267 + + +struct Foo; + +impl Foo { + const FOO: [i32; 3] = [0; 3]; +} + +pub fn main() { + let foo = Foo::FOO; + assert_eq!(foo, [0i32, 0, 0]); +} diff --git a/tests/ui/issues/issue-31299.rs b/tests/ui/issues/issue-31299.rs new file mode 100644 index 000000000..78c3252d3 --- /dev/null +++ b/tests/ui/issues/issue-31299.rs @@ -0,0 +1,35 @@ +// run-pass +// Regression test for #31299. This was generating an overflow error +// because of eager normalization: +// +// proving `M: Sized` requires +// - proving `PtrBack>: Sized` requires +// - normalizing `Vec< as Front>::Back>>: Sized` requires +// - proving `Vec: Front` requires +// - `M: Sized` <-- cycle! +// +// If we skip the normalization step, though, everything goes fine. +// +// This could be fixed by implementing lazy normalization everywhere. +// +// However, we want this to work before then. For that, when checking +// whether a type is Sized we only check that the tails are Sized. As +// PtrBack does not have a tail, we don't need to normalize anything +// and this compiles + +trait Front { + type Back; +} + +impl Front for Vec { + type Back = Vec; +} + +struct PtrBack(#[allow(unused_tuple_struct_fields)] Vec); + +struct M(#[allow(unused_tuple_struct_fields)] PtrBack>); + +#[allow(unused_must_use)] +fn main() { + std::mem::size_of::(); +} diff --git a/tests/ui/issues/issue-3136-b.rs b/tests/ui/issues/issue-3136-b.rs new file mode 100644 index 000000000..c4ca7236e --- /dev/null +++ b/tests/ui/issues/issue-3136-b.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-3136-a.rc + +// pretty-expanded FIXME #23616 + +extern crate issue_3136_a; + +pub fn main() {} diff --git a/tests/ui/issues/issue-3149.rs b/tests/ui/issues/issue-3149.rs new file mode 100644 index 000000000..6ab3bc846 --- /dev/null +++ b/tests/ui/issues/issue-3149.rs @@ -0,0 +1,26 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_snake_case)] +// pretty-expanded FIXME #23616 + +fn Matrix4(m11: T, m12: T, m13: T, m14: T, + m21: T, m22: T, m23: T, m24: T, + m31: T, m32: T, m33: T, m34: T, + m41: T, m42: T, m43: T, m44: T) + -> Matrix4 { + Matrix4 { + m11: m11, m12: m12, m13: m13, m14: m14, + m21: m21, m22: m22, m23: m23, m24: m24, + m31: m31, m32: m32, m33: m33, m34: m34, + m41: m41, m42: m42, m43: m43, m44: m44 + } +} + +struct Matrix4 { + m11: T, m12: T, m13: T, m14: T, + m21: T, m22: T, m23: T, m24: T, + m31: T, m32: T, m33: T, m34: T, + m41: T, m42: T, m43: T, m44: T, +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-31511.rs b/tests/ui/issues/issue-31511.rs new file mode 100644 index 000000000..53fecb016 --- /dev/null +++ b/tests/ui/issues/issue-31511.rs @@ -0,0 +1,6 @@ +fn cast_thin_to_fat(x: *const ()) { + x as *const [u8]; + //~^ ERROR: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]` +} + +fn main() {} diff --git a/tests/ui/issues/issue-31511.stderr b/tests/ui/issues/issue-31511.stderr new file mode 100644 index 000000000..cb2991809 --- /dev/null +++ b/tests/ui/issues/issue-31511.stderr @@ -0,0 +1,9 @@ +error[E0607]: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]` + --> $DIR/issue-31511.rs:2:5 + | +LL | x as *const [u8]; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0607`. diff --git a/tests/ui/issues/issue-3154.rs b/tests/ui/issues/issue-3154.rs new file mode 100644 index 000000000..91c7203c1 --- /dev/null +++ b/tests/ui/issues/issue-3154.rs @@ -0,0 +1,11 @@ +struct Thing<'a, Q:'a> { + x: &'a Q +} + +fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> { + Thing { x: x } //~ ERROR explicit lifetime required in the type of `x` [E0621] +} + +fn main() { + thing(&()); +} diff --git a/tests/ui/issues/issue-3154.stderr b/tests/ui/issues/issue-3154.stderr new file mode 100644 index 000000000..da2af83ff --- /dev/null +++ b/tests/ui/issues/issue-3154.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/issue-3154.rs:6:5 + | +LL | fn thing<'a,Q>(x: &Q) -> Thing<'a,Q> { + | -- help: add explicit lifetime `'a` to the type of `x`: `&'a Q` +LL | Thing { x: x } + | ^^^^^^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-31702.rs b/tests/ui/issues/issue-31702.rs new file mode 100644 index 000000000..5b24eead3 --- /dev/null +++ b/tests/ui/issues/issue-31702.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:issue-31702-1.rs +// aux-build:issue-31702-2.rs + +// this test is actually entirely in the linked library crates + +extern crate issue_31702_1; +extern crate issue_31702_2; + +fn main() {} diff --git a/tests/ui/issues/issue-31769.rs b/tests/ui/issues/issue-31769.rs new file mode 100644 index 000000000..f56c6ea56 --- /dev/null +++ b/tests/ui/issues/issue-31769.rs @@ -0,0 +1,4 @@ +fn main() { + #[inline] struct Foo; //~ ERROR attribute should be applied to function or closure + #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to a struct, enum, or union +} diff --git a/tests/ui/issues/issue-31769.stderr b/tests/ui/issues/issue-31769.stderr new file mode 100644 index 000000000..03e2f931c --- /dev/null +++ b/tests/ui/issues/issue-31769.stderr @@ -0,0 +1,16 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-31769.rs:2:5 + | +LL | #[inline] struct Foo; + | ^^^^^^^^^ ----------- not a function or closure + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-31769.rs:3:12 + | +LL | #[repr(C)] fn foo() {} + | ^ ----------- not a struct, enum, or union + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0517, E0518. +For more information about an error, try `rustc --explain E0517`. diff --git a/tests/ui/issues/issue-31776.rs b/tests/ui/issues/issue-31776.rs new file mode 100644 index 000000000..c86623ce2 --- /dev/null +++ b/tests/ui/issues/issue-31776.rs @@ -0,0 +1,55 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Various scenarios in which `pub` is required in blocks + +struct S; + +mod m { + fn f() { + impl ::S { + pub fn s(&self) {} + } + } +} + +// Scenario 1 + +pub trait Tr { + type A; +} +pub struct S1; + +fn f() { + pub struct Z; + + impl ::Tr for ::S1 { + type A = Z; // Private-in-public error unless `struct Z` is pub + } +} + +// Scenario 2 + +trait Tr1 { + type A; + fn pull(&self) -> Self::A; +} +struct S2; + +mod m1 { + fn f() { + pub struct Z { + pub field: u8 + } + + impl ::Tr1 for ::S2 { + type A = Z; + fn pull(&self) -> Self::A { Z{field: 10} } + } + } +} + +fn main() { + S.s(); // Privacy error, unless `fn s` is pub + let a = S2.pull().field; // Privacy error unless `field: u8` is pub +} diff --git a/tests/ui/issues/issue-31910.rs b/tests/ui/issues/issue-31910.rs new file mode 100644 index 000000000..e0655d3f6 --- /dev/null +++ b/tests/ui/issues/issue-31910.rs @@ -0,0 +1,11 @@ +enum Enum { + X = Trait::Number, + //~^ ERROR mismatched types + //~| expected `isize`, found `i32` +} + +trait Trait { + const Number: i32 = 1; +} + +fn main() {} diff --git a/tests/ui/issues/issue-31910.stderr b/tests/ui/issues/issue-31910.stderr new file mode 100644 index 000000000..2603c9442 --- /dev/null +++ b/tests/ui/issues/issue-31910.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-31910.rs:2:9 + | +LL | X = Trait::Number, + | ^^^^^^^^^^^^^ expected `isize`, found `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-32004.rs b/tests/ui/issues/issue-32004.rs new file mode 100644 index 000000000..b3493508c --- /dev/null +++ b/tests/ui/issues/issue-32004.rs @@ -0,0 +1,19 @@ +enum Foo { + Bar(i32), + Baz +} + +struct S; + +fn main() { + match Foo::Baz { + Foo::Bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `Foo::Bar` + _ => {} + } + + match S { + S(()) => {} + //~^ ERROR expected tuple struct or tuple variant, found unit struct `S` + } +} diff --git a/tests/ui/issues/issue-32004.stderr b/tests/ui/issues/issue-32004.stderr new file mode 100644 index 000000000..2d2ed5a63 --- /dev/null +++ b/tests/ui/issues/issue-32004.stderr @@ -0,0 +1,32 @@ +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `Foo::Bar` + --> $DIR/issue-32004.rs:10:9 + | +LL | Bar(i32), + | -------- `Foo::Bar` defined here +LL | Baz + | --- similarly named unit variant `Baz` defined here +... +LL | Foo::Bar => {} + | ^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | Foo::Bar(_) => {} + | ~~~~~~~~~~~ +help: a unit variant with a similar name exists + | +LL | Foo::Baz => {} + | ~~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `S` + --> $DIR/issue-32004.rs:16:9 + | +LL | struct S; + | --------- `S` defined here +... +LL | S(()) => {} + | ^^^^^ help: use this syntax instead: `S` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-32008.rs b/tests/ui/issues/issue-32008.rs new file mode 100644 index 000000000..6c2e20679 --- /dev/null +++ b/tests/ui/issues/issue-32008.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Tests that binary operators allow subtyping on both the LHS and RHS, +// and as such do not introduce unnecessarily strict lifetime constraints. + +use std::ops::Add; + +struct Foo; + +impl<'a> Add<&'a Foo> for &'a Foo { + type Output = (); + fn add(self, rhs: &'a Foo) {} +} + +fn try_to_add(input: &Foo) { + let local = Foo; + + // Manual reborrow worked even with invariant trait search. + &*input + &local; + + // Direct use of the reference on the LHS requires additional + // subtyping before searching (invariantly) for `LHS: Add`. + input + &local; +} + +fn main() { +} diff --git a/tests/ui/issues/issue-32086.rs b/tests/ui/issues/issue-32086.rs new file mode 100644 index 000000000..d595d1dd7 --- /dev/null +++ b/tests/ui/issues/issue-32086.rs @@ -0,0 +1,7 @@ +struct S(u8); +const C: S = S(10); + +fn main() { + let C(a) = S(11); //~ ERROR expected tuple struct or tuple variant, found constant `C` + let C(..) = S(11); //~ ERROR expected tuple struct or tuple variant, found constant `C` +} diff --git a/tests/ui/issues/issue-32086.stderr b/tests/ui/issues/issue-32086.stderr new file mode 100644 index 000000000..e566dea89 --- /dev/null +++ b/tests/ui/issues/issue-32086.stderr @@ -0,0 +1,21 @@ +error[E0532]: expected tuple struct or tuple variant, found constant `C` + --> $DIR/issue-32086.rs:5:9 + | +LL | struct S(u8); + | ------------- similarly named tuple struct `S` defined here +... +LL | let C(a) = S(11); + | ^ help: a tuple struct with a similar name exists: `S` + +error[E0532]: expected tuple struct or tuple variant, found constant `C` + --> $DIR/issue-32086.rs:6:9 + | +LL | struct S(u8); + | ------------- similarly named tuple struct `S` defined here +... +LL | let C(..) = S(11); + | ^ help: a tuple struct with a similar name exists: `S` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-32122-1.fixed b/tests/ui/issues/issue-32122-1.fixed new file mode 100644 index 000000000..4fc5f64ff --- /dev/null +++ b/tests/ui/issues/issue-32122-1.fixed @@ -0,0 +1,17 @@ +// run-rustfix +use std::ops::Deref; + +struct Foo(u8); + +impl Deref for Foo { + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let a = Foo(0); + // Should suggest `&*` when coercing &ty to *const ty + let _: *const u8 = &*a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-32122-1.rs b/tests/ui/issues/issue-32122-1.rs new file mode 100644 index 000000000..3c4859f07 --- /dev/null +++ b/tests/ui/issues/issue-32122-1.rs @@ -0,0 +1,17 @@ +// run-rustfix +use std::ops::Deref; + +struct Foo(u8); + +impl Deref for Foo { + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let a = Foo(0); + // Should suggest `&*` when coercing &ty to *const ty + let _: *const u8 = &a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-32122-1.stderr b/tests/ui/issues/issue-32122-1.stderr new file mode 100644 index 000000000..10b0c0967 --- /dev/null +++ b/tests/ui/issues/issue-32122-1.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-32122-1.rs:16:24 + | +LL | let _: *const u8 = &a; + | --------- ^^ expected `u8`, found struct `Foo` + | | + | expected due to this + | + = note: expected raw pointer `*const u8` + found reference `&Foo` +help: consider dereferencing + | +LL | let _: *const u8 = &*a; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-32122-2.fixed b/tests/ui/issues/issue-32122-2.fixed new file mode 100644 index 000000000..cee0e5929 --- /dev/null +++ b/tests/ui/issues/issue-32122-2.fixed @@ -0,0 +1,28 @@ +// run-rustfix +use std::ops::Deref; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +fn main() { + let a = Emm(Foo(Bar(0))); + // Should suggest `&***` even when deref is pretty deep + let _: *const u8 = &***a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-32122-2.rs b/tests/ui/issues/issue-32122-2.rs new file mode 100644 index 000000000..39e9df422 --- /dev/null +++ b/tests/ui/issues/issue-32122-2.rs @@ -0,0 +1,28 @@ +// run-rustfix +use std::ops::Deref; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +fn main() { + let a = Emm(Foo(Bar(0))); + // Should suggest `&***` even when deref is pretty deep + let _: *const u8 = &a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-32122-2.stderr b/tests/ui/issues/issue-32122-2.stderr new file mode 100644 index 000000000..5c3dade8e --- /dev/null +++ b/tests/ui/issues/issue-32122-2.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-32122-2.rs:27:24 + | +LL | let _: *const u8 = &a; + | --------- ^^ expected `u8`, found struct `Emm` + | | + | expected due to this + | + = note: expected raw pointer `*const u8` + found reference `&Emm` +help: consider dereferencing + | +LL | let _: *const u8 = &***a; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-3214.rs b/tests/ui/issues/issue-3214.rs new file mode 100644 index 000000000..928a65938 --- /dev/null +++ b/tests/ui/issues/issue-3214.rs @@ -0,0 +1,11 @@ +fn foo() { + struct Foo { + x: T, //~ ERROR can't use generic parameters from outer function + } + + impl Drop for Foo { + //~^ ERROR this struct takes 0 generic arguments but 1 generic argument + fn drop(&mut self) {} + } +} +fn main() {} diff --git a/tests/ui/issues/issue-3214.stderr b/tests/ui/issues/issue-3214.stderr new file mode 100644 index 000000000..aa0b5ce64 --- /dev/null +++ b/tests/ui/issues/issue-3214.stderr @@ -0,0 +1,28 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-3214.rs:3:12 + | +LL | fn foo() { + | - type parameter from outer function +LL | struct Foo { + | - help: try using a local generic parameter instead: `` +LL | x: T, + | ^ use of generic parameter from outer function + +error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-3214.rs:6:22 + | +LL | impl Drop for Foo { + | ^^^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/issue-3214.rs:2:12 + | +LL | struct Foo { + | ^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0401. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-3220.rs b/tests/ui/issues/issue-3220.rs new file mode 100644 index 000000000..7dc672edb --- /dev/null +++ b/tests/ui/issues/issue-3220.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +// pretty-expanded FIXME #23616 + +struct thing { x: isize, } + +impl Drop for thing { + fn drop(&mut self) {} +} + +fn thing() -> thing { + thing { + x: 0 + } +} + +impl thing { + pub fn f(self) {} +} + +pub fn main() { + let z = thing(); + (z).f(); +} diff --git a/tests/ui/issues/issue-32292.rs b/tests/ui/issues/issue-32292.rs new file mode 100644 index 000000000..99b865391 --- /dev/null +++ b/tests/ui/issues/issue-32292.rs @@ -0,0 +1,9 @@ +// run-pass +#![deny(warnings)] + +#[derive(Hash, Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Copy)] +struct Foo; + +fn main() { + let _ = Foo; +} diff --git a/tests/ui/issues/issue-32323.rs b/tests/ui/issues/issue-32323.rs new file mode 100644 index 000000000..5078f5523 --- /dev/null +++ b/tests/ui/issues/issue-32323.rs @@ -0,0 +1,8 @@ +pub trait Tr<'a> { + type Out; +} + +pub fn f<'a, T: Tr<'a>>() -> >::Out {} +//~^ ERROR mismatched types + +pub fn main() {} diff --git a/tests/ui/issues/issue-32323.stderr b/tests/ui/issues/issue-32323.stderr new file mode 100644 index 000000000..8212c607e --- /dev/null +++ b/tests/ui/issues/issue-32323.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-32323.rs:5:30 + | +LL | pub fn f<'a, T: Tr<'a>>() -> >::Out {} + | - ^^^^^^^^^^^^^^^^^^ expected associated type, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected associated type `>::Out` + found unit type `()` +help: consider constraining the associated type `>::Out` to `()` + | +LL | pub fn f<'a, T: Tr<'a, Out = ()>>() -> >::Out {} + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-32324.rs b/tests/ui/issues/issue-32324.rs new file mode 100644 index 000000000..2df547b2e --- /dev/null +++ b/tests/ui/issues/issue-32324.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(dead_code)] + +trait Resources { + type Buffer: Copy; +} + +#[derive(Copy, Clone)] +struct ConstantBufferSet( + pub R::Buffer +); + +#[derive(Copy, Clone)] +enum It {} +impl Resources for It { + type Buffer = u8; +} + +#[derive(Copy, Clone)] +enum Command { + BindConstantBuffers(ConstantBufferSet) +} + +fn main() {} diff --git a/tests/ui/issues/issue-32326.rs b/tests/ui/issues/issue-32326.rs new file mode 100644 index 000000000..e928c66e2 --- /dev/null +++ b/tests/ui/issues/issue-32326.rs @@ -0,0 +1,10 @@ +// Regression test for #32326. We ran out of memory because we +// attempted to expand this case up to the recursion limit, and 2^N is +// too big. + +enum Expr { //~ ERROR E0072 + Plus(Expr, Expr), + Literal(i64), +} + +fn main() { } diff --git a/tests/ui/issues/issue-32326.stderr b/tests/ui/issues/issue-32326.stderr new file mode 100644 index 000000000..dc51198d9 --- /dev/null +++ b/tests/ui/issues/issue-32326.stderr @@ -0,0 +1,16 @@ +error[E0072]: recursive type `Expr` has infinite size + --> $DIR/issue-32326.rs:5:1 + | +LL | enum Expr { + | ^^^^^^^^^ +LL | Plus(Expr, Expr), + | ---- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | Plus(Box, Expr), + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-32377.rs b/tests/ui/issues/issue-32377.rs new file mode 100644 index 000000000..555f6abd7 --- /dev/null +++ b/tests/ui/issues/issue-32377.rs @@ -0,0 +1,19 @@ +// normalize-stderr-test "\d+ bits" -> "N bits" + +use std::mem; +use std::marker::PhantomData; + +trait Foo { + type Error; +} + +struct Bar { + stream: PhantomData, +} + +fn foo(x: [usize; 2]) -> Bar { + unsafe { mem::transmute(x) } + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +fn main() {} diff --git a/tests/ui/issues/issue-32377.stderr b/tests/ui/issues/issue-32377.stderr new file mode 100644 index 000000000..5e870eb3e --- /dev/null +++ b/tests/ui/issues/issue-32377.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/issue-32377.rs:15:14 + | +LL | unsafe { mem::transmute(x) } + | ^^^^^^^^^^^^^^ + | + = note: source type: `[usize; 2]` (N bits) + = note: target type: `Bar` (N bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/issues/issue-32389.rs b/tests/ui/issues/issue-32389.rs new file mode 100644 index 000000000..cc94cc819 --- /dev/null +++ b/tests/ui/issues/issue-32389.rs @@ -0,0 +1,11 @@ +// run-pass +fn foo() -> T { loop {} } + +fn test() { + let ref mut a: &mut dyn FnMut((i8,), i16) = foo(); + a((0,), 0); +} + +fn main() { + let _ = test; +} diff --git a/tests/ui/issues/issue-32518.rs b/tests/ui/issues/issue-32518.rs new file mode 100644 index 000000000..808b40f71 --- /dev/null +++ b/tests/ui/issues/issue-32518.rs @@ -0,0 +1,13 @@ +// run-pass +// no-prefer-dynamic +// aux-build:cgu_test.rs +// aux-build:cgu_test_a.rs +// aux-build:cgu_test_b.rs + +extern crate cgu_test_a; +extern crate cgu_test_b; + +fn main() { + cgu_test_a::a::a(); + cgu_test_b::a::a(); +} diff --git a/tests/ui/issues/issue-32655.rs b/tests/ui/issues/issue-32655.rs new file mode 100644 index 000000000..f52e09231 --- /dev/null +++ b/tests/ui/issues/issue-32655.rs @@ -0,0 +1,19 @@ +macro_rules! foo ( + () => ( + #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope + struct T; + ); +); + +macro_rules! bar ( + ($e:item) => ($e) +); + +foo!(); + +bar!( + #[derive_Clone] //~ ERROR cannot find attribute `derive_Clone` in this scope + struct S; +); + +fn main() {} diff --git a/tests/ui/issues/issue-32655.stderr b/tests/ui/issues/issue-32655.stderr new file mode 100644 index 000000000..b8362499b --- /dev/null +++ b/tests/ui/issues/issue-32655.stderr @@ -0,0 +1,25 @@ +error: cannot find attribute `derive_Clone` in this scope + --> $DIR/issue-32655.rs:3:11 + | +LL | #[derive_Clone] + | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const` +... +LL | foo!(); + | ------ in this macro invocation + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: similarly named attribute macro `derive_const` defined here + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find attribute `derive_Clone` in this scope + --> $DIR/issue-32655.rs:15:7 + | +LL | #[derive_Clone] + | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: similarly named attribute macro `derive_const` defined here + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-32709.rs b/tests/ui/issues/issue-32709.rs new file mode 100644 index 000000000..c05bfdc4c --- /dev/null +++ b/tests/ui/issues/issue-32709.rs @@ -0,0 +1,8 @@ +// Make sure that the span of try shorthand does not include the trailing +// semicolon; +fn a() -> Result { + Err(5)?; //~ ERROR + Ok(1) +} + +fn main() {} diff --git a/tests/ui/issues/issue-32709.stderr b/tests/ui/issues/issue-32709.stderr new file mode 100644 index 000000000..1d595ca56 --- /dev/null +++ b/tests/ui/issues/issue-32709.stderr @@ -0,0 +1,17 @@ +error[E0277]: `?` couldn't convert the error to `()` + --> $DIR/issue-32709.rs:4:11 + | +LL | fn a() -> Result { + | --------------- expected `()` because of this +LL | Err(5)?; + | ^ the trait `From<{integer}>` is not implemented for `()` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual>> + = note: required for `Result` to implement `FromResidual>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-32782.rs b/tests/ui/issues/issue-32782.rs new file mode 100644 index 000000000..e3aa9f3bf --- /dev/null +++ b/tests/ui/issues/issue-32782.rs @@ -0,0 +1,13 @@ +macro_rules! bar ( + () => () +); + +macro_rules! foo ( + () => ( + #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps + bar!(); + ); +); + +foo!(); +fn main() {} diff --git a/tests/ui/issues/issue-32782.stderr b/tests/ui/issues/issue-32782.stderr new file mode 100644 index 000000000..a6c55ba03 --- /dev/null +++ b/tests/ui/issues/issue-32782.stderr @@ -0,0 +1,15 @@ +error[E0658]: allow_internal_unstable side-steps feature gating and stability checks + --> $DIR/issue-32782.rs:7:9 + | +LL | #[allow_internal_unstable] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | foo!(); + | ------ in this macro invocation + | + = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-32797.rs b/tests/ui/issues/issue-32797.rs new file mode 100644 index 000000000..b12b929f8 --- /dev/null +++ b/tests/ui/issues/issue-32797.rs @@ -0,0 +1,13 @@ +// check-pass + +pub use bar::*; +mod bar { + pub use super::*; +} + +pub use baz::*; +mod baz { + pub use main as f; +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-32805.rs b/tests/ui/issues/issue-32805.rs new file mode 100644 index 000000000..23c194739 --- /dev/null +++ b/tests/ui/issues/issue-32805.rs @@ -0,0 +1,10 @@ +// run-pass +fn const_mir() -> f32 { 9007199791611905.0 } + +fn main() { + let original = "9007199791611905.0"; // (1<<53)+(1<<29)+1 + let expected = "9007200000000000"; + + assert_eq!(const_mir().to_string(), expected); + assert_eq!(original.parse::().unwrap().to_string(), expected); +} diff --git a/tests/ui/issues/issue-3290.rs b/tests/ui/issues/issue-3290.rs new file mode 100644 index 000000000..7014d517f --- /dev/null +++ b/tests/ui/issues/issue-3290.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + let mut x: Box<_> = Box::new(3); + x = x; + assert_eq!(*x, 3); +} diff --git a/tests/ui/issues/issue-32950.rs b/tests/ui/issues/issue-32950.rs new file mode 100644 index 000000000..27d68a11c --- /dev/null +++ b/tests/ui/issues/issue-32950.rs @@ -0,0 +1,9 @@ +#![feature(concat_idents)] + +#[derive(Debug)] +struct Baz( + concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros + //~^ ERROR cannot find type `FooBar` in this scope +); + +fn main() {} diff --git a/tests/ui/issues/issue-32950.stderr b/tests/ui/issues/issue-32950.stderr new file mode 100644 index 000000000..f6635d982 --- /dev/null +++ b/tests/ui/issues/issue-32950.stderr @@ -0,0 +1,17 @@ +error: `derive` cannot be used on items with type macros + --> $DIR/issue-32950.rs:5:5 + | +LL | concat_idents!(Foo, Bar) + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0412]: cannot find type `FooBar` in this scope + --> $DIR/issue-32950.rs:5:5 + | +LL | concat_idents!(Foo, Bar) + | ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `concat_idents` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-32995-2.rs b/tests/ui/issues/issue-32995-2.rs new file mode 100644 index 000000000..e713a64d3 --- /dev/null +++ b/tests/ui/issues/issue-32995-2.rs @@ -0,0 +1,13 @@ +fn main() { + { fn f() {} } + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + { fn f() -> impl ::std::marker()::Send { } } + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait +} + +#[derive(Clone)] +struct X; + +impl ::std::marker()::Copy for X {} +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait diff --git a/tests/ui/issues/issue-32995-2.stderr b/tests/ui/issues/issue-32995-2.stderr new file mode 100644 index 000000000..6c2d772a2 --- /dev/null +++ b/tests/ui/issues/issue-32995-2.stderr @@ -0,0 +1,21 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995-2.rs:2:22 + | +LL | { fn f() {} } + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995-2.rs:5:29 + | +LL | { fn f() -> impl ::std::marker()::Send { } } + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995-2.rs:12:13 + | +LL | impl ::std::marker()::Copy for X {} + | ^^^^^^^^ only `Fn` traits may use parentheses + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/issues/issue-32995.rs b/tests/ui/issues/issue-32995.rs new file mode 100644 index 000000000..0d07a7693 --- /dev/null +++ b/tests/ui/issues/issue-32995.rs @@ -0,0 +1,24 @@ +fn main() { + let x: usize() = 1; + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + let b: ::std::boxed()::Box<_> = Box::new(1); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + let p = ::std::str::()::from_utf8(b"foo").unwrap(); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + let p = ::std::str::from_utf8::()(b"foo").unwrap(); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + let o : Box = Box::new(1); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + + let o : Box = Box::new(1); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait +} + +fn foo() { + let d : X() = Default::default(); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait +} diff --git a/tests/ui/issues/issue-32995.stderr b/tests/ui/issues/issue-32995.stderr new file mode 100644 index 000000000..b868011b9 --- /dev/null +++ b/tests/ui/issues/issue-32995.stderr @@ -0,0 +1,45 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:2:12 + | +LL | let x: usize() = 1; + | ^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:5:19 + | +LL | let b: ::std::boxed()::Box<_> = Box::new(1); + | ^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:8:20 + | +LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); + | ^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:11:25 + | +LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); + | ^^^^^^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:14:29 + | +LL | let o : Box = Box::new(1); + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:17:35 + | +LL | let o : Box = Box::new(1); + | ^^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-32995.rs:22:13 + | +LL | let d : X() = Default::default(); + | ^^^ only `Fn` traits may use parentheses + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/issues/issue-33096.rs b/tests/ui/issues/issue-33096.rs new file mode 100644 index 000000000..2501e1430 --- /dev/null +++ b/tests/ui/issues/issue-33096.rs @@ -0,0 +1,19 @@ +// run-pass +// compile-flags: -g +// ignore-asmjs wasm2js does not support source maps yet + +use std::ops::Deref; + +trait Foo { + fn foo() {} +} + +impl Foo for u8 {} + +fn bar() where T::Target: Foo { + <::Target as Foo>::foo() +} + +fn main() { + bar::<&u8>(); +} diff --git a/tests/ui/issues/issue-33187.rs b/tests/ui/issues/issue-33187.rs new file mode 100644 index 000000000..8db9e0058 --- /dev/null +++ b/tests/ui/issues/issue-33187.rs @@ -0,0 +1,23 @@ +// run-pass + +struct Foo(::Data); + +impl Copy for Foo where ::Data: Copy {} +impl Clone for Foo +where + ::Data: Clone, +{ + fn clone(&self) -> Self { + Foo(self.0.clone()) + } +} + +trait Repr { + type Data; +} + +impl Repr for A { + type Data = u32; +} + +fn main() {} diff --git a/tests/ui/issues/issue-33202.rs b/tests/ui/issues/issue-33202.rs new file mode 100644 index 000000000..11b89ae1b --- /dev/null +++ b/tests/ui/issues/issue-33202.rs @@ -0,0 +1,9 @@ +// run-pass +#[repr(C)] +pub enum CPOption { + PSome(T), +} + +fn main() { + println!("sizeof CPOption {}", std::mem::size_of::>()); +} diff --git a/tests/ui/issues/issue-33241.rs b/tests/ui/issues/issue-33241.rs new file mode 100644 index 000000000..5f9f1e4a7 --- /dev/null +++ b/tests/ui/issues/issue-33241.rs @@ -0,0 +1,12 @@ +// check-pass + +use std::fmt; + +// CoerceUnsized is not implemented for tuples. You can still create +// an unsized tuple by transmuting a trait object. +fn any() -> T { unreachable!() } + +fn main() { + let t: &(u8, dyn fmt::Debug) = any(); + println!("{:?}", &t.1); +} diff --git a/tests/ui/issues/issue-33287.rs b/tests/ui/issues/issue-33287.rs new file mode 100644 index 000000000..770eb7c02 --- /dev/null +++ b/tests/ui/issues/issue-33287.rs @@ -0,0 +1,10 @@ +// build-pass +#![allow(dead_code)] +#![allow(unused_variables)] +const A: [u32; 1] = [0]; + +fn test() { + let range = A[1]..; +} + +fn main() { } diff --git a/tests/ui/issues/issue-33293.rs b/tests/ui/issues/issue-33293.rs new file mode 100644 index 000000000..a6ef007d5 --- /dev/null +++ b/tests/ui/issues/issue-33293.rs @@ -0,0 +1,6 @@ +fn main() { + match 0 { + aaa::bbb(_) => () + //~^ ERROR failed to resolve: use of undeclared crate or module `aaa` + }; +} diff --git a/tests/ui/issues/issue-33293.stderr b/tests/ui/issues/issue-33293.stderr new file mode 100644 index 000000000..c8450f400 --- /dev/null +++ b/tests/ui/issues/issue-33293.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `aaa` + --> $DIR/issue-33293.rs:3:9 + | +LL | aaa::bbb(_) => () + | ^^^ use of undeclared crate or module `aaa` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/issues/issue-33387.rs b/tests/ui/issues/issue-33387.rs new file mode 100644 index 000000000..499fa7c1f --- /dev/null +++ b/tests/ui/issues/issue-33387.rs @@ -0,0 +1,32 @@ +// run-pass +#![feature(rustc_attrs)] + +use std::sync::Arc; + +trait Foo { + fn get(&self) -> [u8; 2]; +} + +impl Foo for [u8; 2] { + fn get(&self) -> [u8; 2] { + *self + } +} + +struct Bar(T); + +fn unsize_fat_ptr<'a>(x: &'a Bar) -> &'a Bar { + x +} + +fn unsize_nested_fat_ptr(x: Arc) -> Arc { + x +} + +fn main() { + let x: Box> = Box::new(Bar([1,2])); + assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]); + + let x: Arc = Arc::new([3, 4]); + assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]); +} diff --git a/tests/ui/issues/issue-3344.rs b/tests/ui/issues/issue-3344.rs new file mode 100644 index 000000000..de764b3d0 --- /dev/null +++ b/tests/ui/issues/issue-3344.rs @@ -0,0 +1,7 @@ +#[derive(PartialEq)] +struct Thing(usize); +impl PartialOrd for Thing { //~ ERROR not all trait items implemented, missing: `partial_cmp` + fn le(&self, other: &Thing) -> bool { true } + fn ge(&self, other: &Thing) -> bool { true } +} +fn main() {} diff --git a/tests/ui/issues/issue-3344.stderr b/tests/ui/issues/issue-3344.stderr new file mode 100644 index 000000000..11d599967 --- /dev/null +++ b/tests/ui/issues/issue-3344.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `partial_cmp` + --> $DIR/issue-3344.rs:3:1 + | +LL | impl PartialOrd for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `partial_cmp` in implementation + | + = help: implement the missing item: `fn partial_cmp(&self, _: &Rhs) -> Option { todo!() }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/issues/issue-33461.rs b/tests/ui/issues/issue-33461.rs new file mode 100644 index 000000000..4e01d4d30 --- /dev/null +++ b/tests/ui/issues/issue-33461.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_variables)] +use std::marker::PhantomData; + +struct TheType { + t: PhantomData +} + +pub trait TheTrait { + type TheAssociatedType; +} + +impl TheTrait for () { + type TheAssociatedType = (); +} + +pub trait Shape { + fn doit(&self) { + } +} + +impl Shape

for TheType { +} + +fn main() { + let ball = TheType { t: PhantomData }; + let handle: &dyn Shape<()> = &ball; +} diff --git a/tests/ui/issues/issue-33504.rs b/tests/ui/issues/issue-33504.rs new file mode 100644 index 000000000..89cc06ede --- /dev/null +++ b/tests/ui/issues/issue-33504.rs @@ -0,0 +1,9 @@ +// Shadowing a unit-like enum in a closure + +struct Test; + +fn main() { + || { + let Test = 1; //~ ERROR mismatched types + }; +} diff --git a/tests/ui/issues/issue-33504.stderr b/tests/ui/issues/issue-33504.stderr new file mode 100644 index 000000000..d9e7c3b16 --- /dev/null +++ b/tests/ui/issues/issue-33504.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-33504.rs:7:13 + | +LL | struct Test; + | ----------- unit struct defined here +... +LL | let Test = 1; + | ^^^^ - this expression has type `{integer}` + | | + | expected integer, found struct `Test` + | `Test` is interpreted as a unit struct, not a new binding + | help: introduce a new binding instead: `other_test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-33525.rs b/tests/ui/issues/issue-33525.rs new file mode 100644 index 000000000..74f21eff2 --- /dev/null +++ b/tests/ui/issues/issue-33525.rs @@ -0,0 +1,5 @@ +fn main() { + a; //~ ERROR cannot find value `a` + "".lorem; //~ ERROR no field + "".ipsum; //~ ERROR no field +} diff --git a/tests/ui/issues/issue-33525.stderr b/tests/ui/issues/issue-33525.stderr new file mode 100644 index 000000000..f8d703dc3 --- /dev/null +++ b/tests/ui/issues/issue-33525.stderr @@ -0,0 +1,22 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-33525.rs:2:5 + | +LL | a; + | ^ not found in this scope + +error[E0609]: no field `lorem` on type `&'static str` + --> $DIR/issue-33525.rs:3:8 + | +LL | "".lorem; + | ^^^^^ + +error[E0609]: no field `ipsum` on type `&'static str` + --> $DIR/issue-33525.rs:4:8 + | +LL | "".ipsum; + | ^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0609. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-33571.rs b/tests/ui/issues/issue-33571.rs new file mode 100644 index 000000000..2713f47ad --- /dev/null +++ b/tests/ui/issues/issue-33571.rs @@ -0,0 +1,7 @@ +#[derive(Clone, + Sync, //~ ERROR cannot find derive macro `Sync` in this scope + //~| ERROR cannot find derive macro `Sync` in this scope + Copy)] +enum Foo {} + +fn main() {} diff --git a/tests/ui/issues/issue-33571.stderr b/tests/ui/issues/issue-33571.stderr new file mode 100644 index 000000000..2a9ba5ba7 --- /dev/null +++ b/tests/ui/issues/issue-33571.stderr @@ -0,0 +1,26 @@ +error: cannot find derive macro `Sync` in this scope + --> $DIR/issue-33571.rs:2:10 + | +LL | Sync, + | ^^^^ + | +note: unsafe traits like `Sync` should be implemented explicitly + --> $DIR/issue-33571.rs:2:10 + | +LL | Sync, + | ^^^^ + +error: cannot find derive macro `Sync` in this scope + --> $DIR/issue-33571.rs:2:10 + | +LL | Sync, + | ^^^^ + | +note: unsafe traits like `Sync` should be implemented explicitly + --> $DIR/issue-33571.rs:2:10 + | +LL | Sync, + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-33687.rs b/tests/ui/issues/issue-33687.rs new file mode 100644 index 000000000..ac802ed86 --- /dev/null +++ b/tests/ui/issues/issue-33687.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(unboxed_closures)] +#![feature(fn_traits)] + +struct Test; + +impl FnOnce<(u32, u32)> for Test { + type Output = u32; + + extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { + a + b + } +} + +fn main() { + assert_eq!(Test(1u32, 2u32), 3u32); +} diff --git a/tests/ui/issues/issue-33770.rs b/tests/ui/issues/issue-33770.rs new file mode 100644 index 000000000..f3c99015b --- /dev/null +++ b/tests/ui/issues/issue-33770.rs @@ -0,0 +1,94 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::process::{Command, Stdio}; +use std::env; +use std::sync::{Mutex, RwLock}; +use std::time::Duration; +use std::thread; + +fn test_mutex() { + let m = Mutex::new(0); + let _g = m.lock().unwrap(); + let _g2 = m.lock().unwrap(); +} + +fn test_try_mutex() { + let m = Mutex::new(0); + let _g = m.lock().unwrap(); + let _g2 = m.try_lock().unwrap(); +} + +fn test_rwlock_ww() { + let m = RwLock::new(0); + let _g = m.write().unwrap(); + let _g2 = m.write().unwrap(); +} + +fn test_try_rwlock_ww() { + let m = RwLock::new(0); + let _g = m.write().unwrap(); + let _g2 = m.try_write().unwrap(); +} + +fn test_rwlock_rw() { + let m = RwLock::new(0); + let _g = m.read().unwrap(); + let _g2 = m.write().unwrap(); +} + +fn test_try_rwlock_rw() { + let m = RwLock::new(0); + let _g = m.read().unwrap(); + let _g2 = m.try_write().unwrap(); +} + +fn test_rwlock_wr() { + let m = RwLock::new(0); + let _g = m.write().unwrap(); + let _g2 = m.read().unwrap(); +} + +fn test_try_rwlock_wr() { + let m = RwLock::new(0); + let _g = m.write().unwrap(); + let _g2 = m.try_read().unwrap(); +} + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 { + match &*args[1] { + "mutex" => test_mutex(), + "try_mutex" => test_try_mutex(), + "rwlock_ww" => test_rwlock_ww(), + "try_rwlock_ww" => test_try_rwlock_ww(), + "rwlock_rw" => test_rwlock_rw(), + "try_rwlock_rw" => test_try_rwlock_rw(), + "rwlock_wr" => test_rwlock_wr(), + "try_rwlock_wr" => test_try_rwlock_wr(), + _ => unreachable!(), + } + // If we reach this point then the test failed + println!("TEST FAILED: {}", args[1]); + } else { + let mut v = vec![]; + v.push(Command::new(&args[0]).arg("mutex").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("try_mutex").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("rwlock_ww").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("try_rwlock_ww").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("rwlock_rw").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("try_rwlock_rw").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("rwlock_wr").stderr(Stdio::null()).spawn().unwrap()); + v.push(Command::new(&args[0]).arg("try_rwlock_wr").stderr(Stdio::null()).spawn().unwrap()); + + thread::sleep(Duration::new(1, 0)); + + // Make sure all subprocesses either panicked or were killed because they deadlocked + for mut c in v { + c.kill().ok(); + assert!(!c.wait().unwrap().success()); + } + } +} diff --git a/tests/ui/issues/issue-3389.rs b/tests/ui/issues/issue-3389.rs new file mode 100644 index 000000000..294a07229 --- /dev/null +++ b/tests/ui/issues/issue-3389.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +struct trie_node { + content: Vec , + children: Vec , +} + +fn print_str_vector(vector: Vec ) { + for string in &vector { + println!("{}", *string); + } +} + +pub fn main() { + let mut node: trie_node = trie_node { + content: Vec::new(), + children: Vec::new() + }; + let v = vec!["123".to_string(), "abc".to_string()]; + node.content = vec!["123".to_string(), "abc".to_string()]; + print_str_vector(v); + print_str_vector(node.content.clone()); + +} diff --git a/tests/ui/issues/issue-33903.rs b/tests/ui/issues/issue-33903.rs new file mode 100644 index 000000000..613aa121a --- /dev/null +++ b/tests/ui/issues/issue-33903.rs @@ -0,0 +1,10 @@ +// check-pass +#![allow(dead_code)] +// Issue 33903: +// Built-in indexing should be used even when the index is not +// trivially an integer +// Only built-in indexing can be used in constant expressions + +const FOO: i32 = [12, 34][0 + 1]; + +fn main() {} diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs new file mode 100644 index 000000000..e3b6dcf55 --- /dev/null +++ b/tests/ui/issues/issue-33941.rs @@ -0,0 +1,9 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes + +use std::collections::HashMap; + +fn main() { + for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` +} diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr new file mode 100644 index 000000000..668eaabca --- /dev/null +++ b/tests/ui/issues/issue-33941.stderr @@ -0,0 +1,42 @@ +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + --> $DIR/issue-33941.rs:6:36 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^ expected reference, found tuple + | + = note: expected reference `&_` + found tuple `(&_, &_)` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-33941.rs:6:29 + | +LL | for _ in HashMap::new().iter().cloned() {} + | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here + | | + | this expression has type `HashMap<_, _>` +note: required by a bound in `cloned` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + --> $DIR/issue-33941.rs:6:14 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | + = note: expected tuple `(&_, &_)` + found reference `&_` + = note: required for `Cloned>` to implement `Iterator` + = note: required for `Cloned>` to implement `IntoIterator` + +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + --> $DIR/issue-33941.rs:6:14 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | + = note: expected tuple `(&_, &_)` + found reference `&_` + = note: required for `Cloned>` to implement `Iterator` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-33992.rs b/tests/ui/issues/issue-33992.rs new file mode 100644 index 000000000..a6b137ba6 --- /dev/null +++ b/tests/ui/issues/issue-33992.rs @@ -0,0 +1,32 @@ +// run-pass +// ignore-windows +// ignore-macos +// ignore-emscripten common linkage not implemented right now + +#![feature(linkage)] + +#[linkage = "common"] +pub static mut TEST1: u32 = 0u32; + +#[linkage = "external"] +pub static TEST2: bool = true; + +#[linkage = "internal"] +pub static TEST3: bool = true; + +#[linkage = "linkonce"] +pub static TEST4: bool = true; + +#[linkage = "linkonce_odr"] +pub static TEST5: bool = true; + +#[linkage = "private"] +pub static TEST6: bool = true; + +#[linkage = "weak"] +pub static TEST7: bool = true; + +#[linkage = "weak_odr"] +pub static TEST8: bool = true; + +fn main() {} diff --git a/tests/ui/issues/issue-34047.rs b/tests/ui/issues/issue-34047.rs new file mode 100644 index 000000000..55196177f --- /dev/null +++ b/tests/ui/issues/issue-34047.rs @@ -0,0 +1,8 @@ +const C: u8 = 0; + +fn main() { + match 1u8 { + mut C => {} //~ ERROR match bindings cannot shadow constants + _ => {} + } +} diff --git a/tests/ui/issues/issue-34047.stderr b/tests/ui/issues/issue-34047.stderr new file mode 100644 index 000000000..f770ded50 --- /dev/null +++ b/tests/ui/issues/issue-34047.stderr @@ -0,0 +1,12 @@ +error[E0530]: match bindings cannot shadow constants + --> $DIR/issue-34047.rs:5:13 + | +LL | const C: u8 = 0; + | ---------------- the constant `C` is defined here +... +LL | mut C => {} + | ^ cannot be named the same as a constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/issues/issue-34074.rs b/tests/ui/issues/issue-34074.rs new file mode 100644 index 000000000..0600d3937 --- /dev/null +++ b/tests/ui/issues/issue-34074.rs @@ -0,0 +1,10 @@ +// run-pass +// Make sure several unnamed function parameters don't conflict with each other + +trait Tr { + #[allow(anonymous_parameters)] + fn f(u8, u8) {} +} + +fn main() { +} diff --git a/tests/ui/issues/issue-34209.rs b/tests/ui/issues/issue-34209.rs new file mode 100644 index 000000000..632ddb91b --- /dev/null +++ b/tests/ui/issues/issue-34209.rs @@ -0,0 +1,11 @@ +enum S { + A, +} + +fn bug(l: S) { + match l { + S::B {} => {}, //~ ERROR no variant named `B` found for enum `S` + } +} + +fn main () {} diff --git a/tests/ui/issues/issue-34209.stderr b/tests/ui/issues/issue-34209.stderr new file mode 100644 index 000000000..f9a25b69f --- /dev/null +++ b/tests/ui/issues/issue-34209.stderr @@ -0,0 +1,12 @@ +error[E0599]: no variant named `B` found for enum `S` + --> $DIR/issue-34209.rs:7:12 + | +LL | enum S { + | ------ variant `B` not found here +... +LL | S::B {} => {}, + | ^ help: there is a variant with a similar name: `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-34229.rs b/tests/ui/issues/issue-34229.rs new file mode 100644 index 000000000..13e627a49 --- /dev/null +++ b/tests/ui/issues/issue-34229.rs @@ -0,0 +1,5 @@ +#[derive(PartialEq)] struct Comparable; +#[derive(PartialEq, PartialOrd)] struct Nope(Comparable); +//~^ ERROR can't compare `Comparable` + +fn main() {} diff --git a/tests/ui/issues/issue-34229.stderr b/tests/ui/issues/issue-34229.stderr new file mode 100644 index 000000000..69ef876d2 --- /dev/null +++ b/tests/ui/issues/issue-34229.stderr @@ -0,0 +1,18 @@ +error[E0277]: can't compare `Comparable` with `Comparable` + --> $DIR/issue-34229.rs:2:46 + | +LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable); + | ---------- ^^^^^^^^^^ no implementation for `Comparable < Comparable` and `Comparable > Comparable` + | | + | in this derive macro expansion + | + = help: the trait `PartialOrd` is not implemented for `Comparable` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Comparable` with `#[derive(PartialOrd)]` + | +LL | #[derive(PartialEq)] #[derive(PartialOrd)] + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-3424.rs b/tests/ui/issues/issue-3424.rs new file mode 100644 index 000000000..43d75a652 --- /dev/null +++ b/tests/ui/issues/issue-3424.rs @@ -0,0 +1,20 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +// rustc --test ignores2.rs && ./ignores2 + +pub struct Path; + +type rsrc_loader = Box Result>; + +fn tester() +{ + let mut loader: rsrc_loader = Box::new(move |_path| { + Ok("more blah".to_string()) + }); + + let path = Path; + assert!(loader(&path).is_ok()); +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-3429.rs b/tests/ui/issues/issue-3429.rs new file mode 100644 index 000000000..9d94c3ff6 --- /dev/null +++ b/tests/ui/issues/issue-3429.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let x = 1_usize; + let y = || x; + let _z = y(); +} diff --git a/tests/ui/issues/issue-34334.rs b/tests/ui/issues/issue-34334.rs new file mode 100644 index 000000000..51486bc40 --- /dev/null +++ b/tests/ui/issues/issue-34334.rs @@ -0,0 +1,8 @@ +fn main () { + let sr: Vec<(u32, _, _) = vec![]; + //~^ ERROR expected one of + + let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); + //~^ ERROR a value of type `Vec<(u32, _, _)>` cannot be built + +} diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr new file mode 100644 index 000000000..9d2c315e4 --- /dev/null +++ b/tests/ui/issues/issue-34334.stderr @@ -0,0 +1,38 @@ +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/issue-34334.rs:2:29 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | -- - ^ expected one of `,`, `:`, or `>` + | | | + | | maybe try to close unmatched angle bracket + | while parsing the type for `sr` + | +help: you might have meant to end the type parameters here + | +LL | let sr: Vec<(u32, _, _)> = vec![]; + | + + +error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()` + --> $DIR/issue-34334.rs:5:87 + | +LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); + | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-34334.rs:5:43 + | +LL | let sr: Vec<(u32, _, _) = vec![]; + | ------ this expression has type `Vec<(_, _, _)>` +... +LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here + | | + | `Iterator::Item` is `&(_, _, _)` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-34349.rs b/tests/ui/issues/issue-34349.rs new file mode 100644 index 000000000..d86180261 --- /dev/null +++ b/tests/ui/issues/issue-34349.rs @@ -0,0 +1,22 @@ +// This is a regression test for a problem encountered around upvar +// inference and trait caching: in particular, we were entering a +// temporary closure kind during inference, and then caching results +// based on that temporary kind, which led to no error being reported +// in this particular test. + +fn main() { + let inc = || {}; + inc(); + + fn apply(f: F) where F: Fn() { + f() + } + + let mut farewell = "goodbye".to_owned(); + let diary = || { //~ ERROR E0525 + farewell.push_str("!!!"); + println!("Then I screamed {}.", farewell); + }; + + apply(diary); +} diff --git a/tests/ui/issues/issue-34349.stderr b/tests/ui/issues/issue-34349.stderr new file mode 100644 index 000000000..8e9a16619 --- /dev/null +++ b/tests/ui/issues/issue-34349.stderr @@ -0,0 +1,22 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/issue-34349.rs:16:17 + | +LL | let diary = || { + | ^^ this closure implements `FnMut`, not `Fn` +LL | farewell.push_str("!!!"); + | -------- closure is `FnMut` because it mutates the variable `farewell` here +... +LL | apply(diary); + | ----- ----- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `apply` + --> $DIR/issue-34349.rs:11:32 + | +LL | fn apply(f: F) where F: Fn() { + | ^^^^ required by this bound in `apply` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/issues/issue-34373.rs b/tests/ui/issues/issue-34373.rs new file mode 100644 index 000000000..ca24e37d9 --- /dev/null +++ b/tests/ui/issues/issue-34373.rs @@ -0,0 +1,11 @@ +#![allow(warnings)] + +trait Trait { + fn foo(_: T) {} +} + +pub struct Foo>>; //~ ERROR cycle detected +type DefaultFoo = Foo; + +fn main() { +} diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr new file mode 100644 index 000000000..8be3cfa72 --- /dev/null +++ b/tests/ui/issues/issue-34373.stderr @@ -0,0 +1,27 @@ +error[E0391]: cycle detected when computing type of `Foo::T` + --> $DIR/issue-34373.rs:7:30 + | +LL | pub struct Foo>>; + | ^^^^^^^^^^ + | +note: ...which requires expanding type alias `DefaultFoo`... + --> $DIR/issue-34373.rs:8:19 + | +LL | type DefaultFoo = Foo; + | ^^^ + = note: ...which again requires computing type of `Foo::T`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-34373.rs:1:1 + | +LL | / #![allow(warnings)] +LL | | +LL | | trait Trait { +LL | | fn foo(_: T) {} +... | +LL | | fn main() { +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/issues/issue-34418.rs b/tests/ui/issues/issue-34418.rs new file mode 100644 index 000000000..6132f744b --- /dev/null +++ b/tests/ui/issues/issue-34418.rs @@ -0,0 +1,19 @@ +// check-pass + +macro_rules! make_item { + () => { fn f() {} } +} + +macro_rules! make_stmt { + () => { let x = 0; } +} + +fn f() { + make_item! {} +} + +fn g() { + make_stmt! {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-34427.rs b/tests/ui/issues/issue-34427.rs new file mode 100644 index 000000000..a14b5b9e2 --- /dev/null +++ b/tests/ui/issues/issue-34427.rs @@ -0,0 +1,17 @@ +// run-pass +// Issue #34427: On ARM, the code in `foo` at one time was generating +// a machine code instruction of the form: `str r0, [r0, rN]!` (for +// some N), which is not legal because the source register and base +// register cannot be identical in the preindexed form signalled by +// the `!`. +// +// See LLVM bug: https://llvm.org/bugs/show_bug.cgi?id=28809 + +#[inline(never)] +fn foo(n: usize) -> Vec> { + (0..n).map(|_| None).collect() +} + +fn main() { + let _ = (foo(10), foo(32)); +} diff --git a/tests/ui/issues/issue-3447.rs b/tests/ui/issues/issue-3447.rs new file mode 100644 index 000000000..ee5b22778 --- /dev/null +++ b/tests/ui/issues/issue-3447.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] +#![allow(non_camel_case_types)] + +use std::cell::RefCell; + +static S: &'static str = "str"; + +struct list { + element: T, + next: Option>>> +} + +impl list { + pub fn addEnd(&mut self, element: T) { + let newList = list { + element: element, + next: None + }; + + self.next = Some(Box::new(RefCell::new(newList))); + } +} + +pub fn main() { + let ls = list { + element: S, + next: None + }; + println!("{}", ls.element); +} diff --git a/tests/ui/issues/issue-34503.rs b/tests/ui/issues/issue-34503.rs new file mode 100644 index 000000000..26e735840 --- /dev/null +++ b/tests/ui/issues/issue-34503.rs @@ -0,0 +1,11 @@ +// run-pass +fn main() { + struct X; + trait Foo { + fn foo(&self) where (T, Option): Ord {} + fn bar(&self, x: &Option) -> bool + where Option: Ord { *x < *x } + } + impl Foo for () {} + let _ = &() as &dyn Foo; +} diff --git a/tests/ui/issues/issue-34569.rs b/tests/ui/issues/issue-34569.rs new file mode 100644 index 000000000..88dcdd411 --- /dev/null +++ b/tests/ui/issues/issue-34569.rs @@ -0,0 +1,18 @@ +// run-pass +// compile-flags:-g +// ignore-asmjs wasm2js does not support source maps yet + +// In this test we just want to make sure that the code below does not lead to +// a debuginfo verification assertion during compilation. This was caused by the +// closure in the guard being codegened twice due to how match expressions are +// handled. +// +// See https://github.com/rust-lang/rust/issues/34569 for details. + +fn main() { + match 0 { + e if (|| { e == 0 })() => {}, + 1 => {}, + _ => {} + } +} diff --git a/tests/ui/issues/issue-34571.rs b/tests/ui/issues/issue-34571.rs new file mode 100644 index 000000000..5498091da --- /dev/null +++ b/tests/ui/issues/issue-34571.rs @@ -0,0 +1,11 @@ +// run-pass +#[repr(u8)] +enum Foo { + Foo(#[allow(unused_tuple_struct_fields)] u8), +} + +fn main() { + match Foo::Foo(1) { + _ => () + } +} diff --git a/tests/ui/issues/issue-34721.fixed b/tests/ui/issues/issue-34721.fixed new file mode 100644 index 000000000..f135ad383 --- /dev/null +++ b/tests/ui/issues/issue-34721.fixed @@ -0,0 +1,34 @@ +// run-rustfix + +pub trait Foo { + fn zero(self) -> Self; +} + +impl Foo for u32 { + fn zero(self) -> u32 { 0u32 } +} + +pub mod bar { + pub use Foo; + pub fn bar(x: T) -> T { + x.zero() + } +} + +mod baz { + use bar; + use Foo; + pub fn baz(x: T) -> T { + if 0 == 1 { + bar::bar(x.zero()) + } else { + x.zero() + }; + x.zero() + //~^ ERROR use of moved value + } +} + +fn main() { + let _ = baz::baz(0u32); +} diff --git a/tests/ui/issues/issue-34721.rs b/tests/ui/issues/issue-34721.rs new file mode 100644 index 000000000..14dd01766 --- /dev/null +++ b/tests/ui/issues/issue-34721.rs @@ -0,0 +1,34 @@ +// run-rustfix + +pub trait Foo { + fn zero(self) -> Self; +} + +impl Foo for u32 { + fn zero(self) -> u32 { 0u32 } +} + +pub mod bar { + pub use Foo; + pub fn bar(x: T) -> T { + x.zero() + } +} + +mod baz { + use bar; + use Foo; + pub fn baz(x: T) -> T { + if 0 == 1 { + bar::bar(x.zero()) + } else { + x.zero() + }; + x.zero() + //~^ ERROR use of moved value + } +} + +fn main() { + let _ = baz::baz(0u32); +} diff --git a/tests/ui/issues/issue-34721.stderr b/tests/ui/issues/issue-34721.stderr new file mode 100644 index 000000000..f2bf22227 --- /dev/null +++ b/tests/ui/issues/issue-34721.stderr @@ -0,0 +1,28 @@ +error[E0382]: use of moved value: `x` + --> $DIR/issue-34721.rs:27:9 + | +LL | pub fn baz(x: T) -> T { + | - move occurs because `x` has type `T`, which does not implement the `Copy` trait +LL | if 0 == 1 { +LL | bar::bar(x.zero()) + | ------ `x` moved due to this method call +LL | } else { +LL | x.zero() + | ------ `x` moved due to this method call +LL | }; +LL | x.zero() + | ^ value used here after move + | +note: `Foo::zero` takes ownership of the receiver `self`, which moves `x` + --> $DIR/issue-34721.rs:4:13 + | +LL | fn zero(self) -> Self; + | ^^^^ +help: consider further restricting this bound + | +LL | pub fn baz(x: T) -> T { + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-34751.rs b/tests/ui/issues/issue-34751.rs new file mode 100644 index 000000000..6309c0a02 --- /dev/null +++ b/tests/ui/issues/issue-34751.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] +// #34751 ICE: 'rustc' panicked at 'assertion failed: !substs.has_regions_escaping_depth(0)' + +#[allow(dead_code)] + +use std::marker::PhantomData; + +fn f<'a>(PhantomData::<&'a u8>: PhantomData<&'a u8>) {} + +fn main() {} diff --git a/tests/ui/issues/issue-3477.rs b/tests/ui/issues/issue-3477.rs new file mode 100644 index 000000000..3817d0e6a --- /dev/null +++ b/tests/ui/issues/issue-3477.rs @@ -0,0 +1,5 @@ +fn main() { + let _p: char = 100; + //~^ ERROR mismatched types + //~| expected `char`, found `u8` +} diff --git a/tests/ui/issues/issue-3477.stderr b/tests/ui/issues/issue-3477.stderr new file mode 100644 index 000000000..fd5f7dcf6 --- /dev/null +++ b/tests/ui/issues/issue-3477.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-3477.rs:2:20 + | +LL | let _p: char = 100; + | ---- ^^^ expected `char`, found `u8` + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-34780.rs b/tests/ui/issues/issue-34780.rs new file mode 100644 index 000000000..fbedad35b --- /dev/null +++ b/tests/ui/issues/issue-34780.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(stable_features)] +#![feature(associated_consts)] + +use std::marker::PhantomData; + +trait Tr<'a> { + const C: PhantomData<&'a u8> = PhantomData::<&'a u8>; +} + +fn main() {} diff --git a/tests/ui/issues/issue-34796.rs b/tests/ui/issues/issue-34796.rs new file mode 100644 index 000000000..88d5c50a2 --- /dev/null +++ b/tests/ui/issues/issue-34796.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +// This test case exposes conditions where the encoding of a trait object type +// with projection predicates would differ between this crate and the upstream +// crate, because the predicates were encoded in different order within each +// crate. This led to different symbol hashes of functions using these type, +// which in turn led to linker errors because the two crates would not agree on +// the symbol name. +// The fix was to make the order in which predicates get encoded stable. + +// aux-build:issue-34796-aux.rs +extern crate issue_34796_aux; + +fn mk() -> T { loop {} } + +struct Data { + data: T, + error: E, +} + +fn main() { + issue_34796_aux::bar(|()| { + Data::<(), std::io::Error> { + data: mk(), + error: mk(), + } + }) +} diff --git a/tests/ui/issues/issue-34839.rs b/tests/ui/issues/issue-34839.rs new file mode 100644 index 000000000..8ffed827e --- /dev/null +++ b/tests/ui/issues/issue-34839.rs @@ -0,0 +1,19 @@ +// check-pass + +trait RegularExpression: Sized { + type Text; +} + +struct ExecNoSyncStr<'a>(&'a u8); + +impl<'c> RegularExpression for ExecNoSyncStr<'c> { + type Text = u8; +} + +struct FindCaptures<'t, R>(&'t R::Text) where R: RegularExpression, R::Text: 't; + +enum FindCapturesInner<'r, 't> { + Dynamic(FindCaptures<'t, ExecNoSyncStr<'r>>), +} + +fn main() {} diff --git a/tests/ui/issues/issue-34932.rs b/tests/ui/issues/issue-34932.rs new file mode 100644 index 000000000..ab568fd01 --- /dev/null +++ b/tests/ui/issues/issue-34932.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags:--test +#![cfg(any())] // This test should be configured away +#![feature(rustc_attrs)] // Test that this is allowed on stable/beta +#![feature(iter_arith_traits)] // Test that this is not unused +#![deny(unused_features)] + +#[test] +fn dummy() { + let () = "this should not reach type-checking"; +} diff --git a/tests/ui/issues/issue-3500.rs b/tests/ui/issues/issue-3500.rs new file mode 100644 index 000000000..7b39cc16c --- /dev/null +++ b/tests/ui/issues/issue-3500.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let x = &Some(1); + match x { + &Some(_) => (), + &None => (), + } +} diff --git a/tests/ui/issues/issue-35139.rs b/tests/ui/issues/issue-35139.rs new file mode 100644 index 000000000..e462f3543 --- /dev/null +++ b/tests/ui/issues/issue-35139.rs @@ -0,0 +1,26 @@ +use std::fmt; + +pub trait MethodType { + type GetProp: ?Sized; +} + +pub struct MTFn; + +impl<'a> MethodType for MTFn { //~ ERROR E0207 + type GetProp = dyn fmt::Debug + 'a; +} + +fn bad(a: Box<::GetProp>) -> Box { + a +} + +fn dangling(a: &str) -> Box { + bad(Box::new(a)) +} + +fn main() { + let mut s = "hello".to_string(); + let x = dangling(&s); + s = String::new(); + println!("{:?}", x); +} diff --git a/tests/ui/issues/issue-35139.stderr b/tests/ui/issues/issue-35139.stderr new file mode 100644 index 000000000..79e889b7e --- /dev/null +++ b/tests/ui/issues/issue-35139.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-35139.rs:9:6 + | +LL | impl<'a> MethodType for MTFn { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/issues/issue-3521-2.fixed b/tests/ui/issues/issue-3521-2.fixed new file mode 100644 index 000000000..140c24b93 --- /dev/null +++ b/tests/ui/issues/issue-3521-2.fixed @@ -0,0 +1,9 @@ +// run-rustfix +fn main() { + let foo = 100; + + let y: isize = foo + 1; + //~^ ERROR attempt to use a non-constant value in a constant + + println!("{}", y); +} diff --git a/tests/ui/issues/issue-3521-2.rs b/tests/ui/issues/issue-3521-2.rs new file mode 100644 index 000000000..f66efec45 --- /dev/null +++ b/tests/ui/issues/issue-3521-2.rs @@ -0,0 +1,9 @@ +// run-rustfix +fn main() { + let foo = 100; + + static y: isize = foo + 1; + //~^ ERROR attempt to use a non-constant value in a constant + + println!("{}", y); +} diff --git a/tests/ui/issues/issue-3521-2.stderr b/tests/ui/issues/issue-3521-2.stderr new file mode 100644 index 000000000..84c7a9efa --- /dev/null +++ b/tests/ui/issues/issue-3521-2.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-3521-2.rs:5:23 + | +LL | static y: isize = foo + 1; + | -------- ^^^ non-constant value + | | + | help: consider using `let` instead of `static`: `let y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-35241.rs b/tests/ui/issues/issue-35241.rs new file mode 100644 index 000000000..2fa762475 --- /dev/null +++ b/tests/ui/issues/issue-35241.rs @@ -0,0 +1,5 @@ +struct Foo(u32); + +fn test() -> Foo { Foo } //~ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/issues/issue-35241.stderr b/tests/ui/issues/issue-35241.stderr new file mode 100644 index 000000000..d600e934b --- /dev/null +++ b/tests/ui/issues/issue-35241.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-35241.rs:3:20 + | +LL | struct Foo(u32); + | ---------- `Foo` defines a struct constructor here, which should be called +LL | +LL | fn test() -> Foo { Foo } + | --- ^^^ expected struct `Foo`, found struct constructor + | | + | expected `Foo` because of return type + | + = note: expected struct `Foo` + found struct constructor `fn(u32) -> Foo {Foo}` +help: use parentheses to construct this tuple struct + | +LL | fn test() -> Foo { Foo(/* u32 */) } + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-35423.rs b/tests/ui/issues/issue-35423.rs new file mode 100644 index 000000000..202ffcc1d --- /dev/null +++ b/tests/ui/issues/issue-35423.rs @@ -0,0 +1,9 @@ +// run-pass +fn main () { + let x = 4; + match x { + ref r if *r < 0 => println!("got negative num {} < 0", r), + e @ 1 ..= 100 => println!("got number within range [1,100] {}", e), + _ => println!("no"), + } +} diff --git a/tests/ui/issues/issue-3556.rs b/tests/ui/issues/issue-3556.rs new file mode 100644 index 000000000..3c1934ade --- /dev/null +++ b/tests/ui/issues/issue-3556.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(dead_code)] + +#[derive(Debug)] +enum Token { + Text(String), + ETag(Vec, String), + UTag(Vec, String), + Section(Vec, bool, Vec, String, + String, String, String, String), + IncompleteSection(Vec, bool, String, bool), + Partial(String, String, String), +} + +fn check_strs(actual: &str, expected: &str) -> bool +{ + if actual != expected + { + println!("Found {}, but expected {}", actual, expected); + return false; + } + return true; +} + +pub fn main() +{ + let t = Token::Text("foo".to_string()); + let u = Token::Section(vec!["alpha".to_string()], + true, + vec![t], + "foo".to_string(), + "foo".to_string(), "foo".to_string(), "foo".to_string(), + "foo".to_string()); + let v = format!("{:?}", u); // this is the line that causes the seg fault + assert!(!v.is_empty()); +} diff --git a/tests/ui/issues/issue-35570.rs b/tests/ui/issues/issue-35570.rs new file mode 100644 index 000000000..a2b0222d4 --- /dev/null +++ b/tests/ui/issues/issue-35570.rs @@ -0,0 +1,29 @@ +use std::mem; + +trait Trait1 {} +trait Trait2<'a> { + type Ty; +} + +fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { + //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied + //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied + let _e: (usize, usize) = unsafe{mem::transmute(param)}; +} + +trait Lifetime<'a> { + type Out; +} +impl<'a> Lifetime<'a> for () { + type Out = &'a (); +} +fn foo<'a>(x: &'a ()) -> <() as Lifetime<'a>>::Out { + x +} + +fn takes_lifetime(_f: for<'a> fn(&'a ()) -> <() as Lifetime<'a>>::Out) { +} + +fn main() { + takes_lifetime(foo); +} diff --git a/tests/ui/issues/issue-35570.stderr b/tests/ui/issues/issue-35570.stderr new file mode 100644 index 000000000..3dc33729d --- /dev/null +++ b/tests/ui/issues/issue-35570.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied + --> $DIR/issue-35570.rs:8:40 + | +LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + +error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied + --> $DIR/issue-35570.rs:8:1 + | +LL | / fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { +LL | | +LL | | +LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)}; +LL | | } + | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-3559.rs b/tests/ui/issues/issue-3559.rs new file mode 100644 index 000000000..9d498584a --- /dev/null +++ b/tests/ui/issues/issue-3559.rs @@ -0,0 +1,18 @@ +// run-pass +use std::collections::HashMap; + +fn check_strs(actual: &str, expected: &str) -> bool { + if actual != expected { + println!("Found {}, but expected {}", actual, expected); + return false; + } + return true; +} + +pub fn main() { + let mut table = HashMap::new(); + table.insert("one".to_string(), 1); + table.insert("two".to_string(), 2); + assert!(check_strs(&format!("{:?}", table), "{\"one\": 1, \"two\": 2}") || + check_strs(&format!("{:?}", table), "{\"two\": 2, \"one\": 1}")); +} diff --git a/tests/ui/issues/issue-35600.rs b/tests/ui/issues/issue-35600.rs new file mode 100644 index 000000000..f0bab6010 --- /dev/null +++ b/tests/ui/issues/issue-35600.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(unused_variables)] + +trait Foo { + type bar; + fn bar(); +} + +impl Foo for () { + type bar = (); + fn bar() {} +} + +fn main() { + let x: <() as Foo>::bar = (); + <()>::bar(); +} diff --git a/tests/ui/issues/issue-3563-3.rs b/tests/ui/issues/issue-3563-3.rs new file mode 100644 index 000000000..bedfdab97 --- /dev/null +++ b/tests/ui/issues/issue-3563-3.rs @@ -0,0 +1,180 @@ +// run-pass +#![allow(unused_imports)] +#![allow(non_snake_case)] + +// ASCII art shape renderer. Demonstrates traits, impls, operator overloading, +// non-copyable struct, unit testing. To run execute: rustc --test shapes.rs && +// ./shapes + +// Rust's std library is tightly bound to the language itself so it is +// automatically linked in. However the extra library is designed to be +// optional (for code that must run on constrained environments like embedded +// devices or special environments like kernel code) so it must be explicitly +// linked in. + +// Extern mod controls linkage. Use controls the visibility of names to modules +// that are already linked in. Using WriterUtil allows us to use the write_line +// method. + +use std::fmt; +use std::iter::repeat; +use std::slice; + +// Represents a position on a canvas. +#[derive(Copy, Clone)] +struct Point { + x: isize, + y: isize, +} + +// Represents an offset on a canvas. (This has the same structure as a Point. +// but different semantics). +#[derive(Copy, Clone)] +struct Size { + width: isize, + height: isize, +} + +#[derive(Copy, Clone)] +struct Rect { + top_left: Point, + size: Size, +} + +// Contains the information needed to do shape rendering via ASCII art. +struct AsciiArt { + width: usize, + height: usize, + fill: char, + lines: Vec > , + + // This struct can be quite large so we'll disable copying: developers need + // to either pass these structs around via references or move them. +} + +impl Drop for AsciiArt { + fn drop(&mut self) {} +} + +// It's common to define a constructor sort of function to create struct instances. +// If there is a canonical constructor it is typically named the same as the type. +// Other constructor sort of functions are typically named from_foo, from_bar, etc. +fn AsciiArt(width: usize, height: usize, fill: char) -> AsciiArt { + // Build a vector of vectors containing blank characters for each position in + // our canvas. + let lines = vec![vec!['.'; width]; height]; + + // Rust code often returns values by omitting the trailing semi-colon + // instead of using an explicit return statement. + AsciiArt {width: width, height: height, fill: fill, lines: lines} +} + +// Methods particular to the AsciiArt struct. +impl AsciiArt { + fn add_pt(&mut self, x: isize, y: isize) { + if x >= 0 && x < self.width as isize { + if y >= 0 && y < self.height as isize { + // Note that numeric types don't implicitly convert to each other. + let v = y as usize; + let h = x as usize; + + // Vector subscripting will normally copy the element, but &v[i] + // will return a reference which is what we need because the + // element is: + // 1) potentially large + // 2) needs to be modified + let row = &mut self.lines[v]; + row[h] = self.fill; + } + } + } +} + +// Allows AsciiArt to be converted to a string using the libcore ToString trait. +// Note that the %s fmt! specifier will not call this automatically. +impl fmt::Display for AsciiArt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Convert each line into a string. + let lines = self.lines.iter() + .map(|line| line.iter().cloned().collect()) + .collect::>(); + + // Concatenate the lines together using a new-line. + write!(f, "{}", lines.join("\n")) + } +} + +// This is similar to an interface in other languages: it defines a protocol which +// developers can implement for arbitrary concrete types. +trait Canvas { + fn add_point(&mut self, shape: Point); + fn add_rect(&mut self, shape: Rect); + + // Unlike interfaces traits support default implementations. + // Got an ICE as soon as I added this method. + fn add_points(&mut self, shapes: &[Point]) { + for pt in shapes {self.add_point(*pt)}; + } +} + +// Here we provide an implementation of the Canvas methods for AsciiArt. +// Other implementations could also be provided (e.g., for PDF or Apple's Quartz) +// and code can use them polymorphically via the Canvas trait. +impl Canvas for AsciiArt { + fn add_point(&mut self, shape: Point) { + self.add_pt(shape.x, shape.y); + } + + fn add_rect(&mut self, shape: Rect) { + // Add the top and bottom lines. + for x in shape.top_left.x..shape.top_left.x + shape.size.width { + self.add_pt(x, shape.top_left.y); + self.add_pt(x, shape.top_left.y + shape.size.height - 1); + } + + // Add the left and right lines. + for y in shape.top_left.y..shape.top_left.y + shape.size.height { + self.add_pt(shape.top_left.x, y); + self.add_pt(shape.top_left.x + shape.size.width - 1, y); + } + } +} + +// Rust's unit testing framework is currently a bit under-developed so we'll use +// this little helper. +pub fn check_strs(actual: &str, expected: &str) -> bool { + if actual != expected { + println!("Found:\n{}\nbut expected\n{}", actual, expected); + return false; + } + return true; +} + + +fn test_ascii_art_ctor() { + let art = AsciiArt(3, 3, '*'); + assert!(check_strs(&art.to_string(), "...\n...\n...")); +} + + +fn test_add_pt() { + let mut art = AsciiArt(3, 3, '*'); + art.add_pt(0, 0); + art.add_pt(0, -10); + art.add_pt(1, 2); + assert!(check_strs(&art.to_string(), "*..\n...\n.*.")); +} + + +fn test_shapes() { + let mut art = AsciiArt(4, 4, '*'); + art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}}); + art.add_point(Point {x: 2, y: 2}); + assert!(check_strs(&art.to_string(), "****\n*..*\n*.**\n****")); +} + +pub fn main() { + test_ascii_art_ctor(); + test_add_pt(); + test_shapes(); +} diff --git a/tests/ui/issues/issue-3574.rs b/tests/ui/issues/issue-3574.rs new file mode 100644 index 000000000..eb967577f --- /dev/null +++ b/tests/ui/issues/issue-3574.rs @@ -0,0 +1,14 @@ +// run-pass +// rustc --test match_borrowed_str.rs.rs && ./match_borrowed_str.rs + + +fn compare(x: &str, y: &str) -> bool { + match x { + "foo" => y == "foo", + _ => y == "bar", + } +} + +pub fn main() { + assert!(compare("foo", "foo")); +} diff --git a/tests/ui/issues/issue-35815.rs b/tests/ui/issues/issue-35815.rs new file mode 100644 index 000000000..05fd1b15d --- /dev/null +++ b/tests/ui/issues/issue-35815.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +use std::mem; + +struct Foo { + a: i64, + b: bool, + c: T, +} + +fn main() { + let foo: &Foo = &Foo { a: 1, b: false, c: 2i32 }; + let foo_unsized: &Foo = foo; + assert_eq!(mem::size_of_val(foo), mem::size_of_val(foo_unsized)); +} diff --git a/tests/ui/issues/issue-35976.rs b/tests/ui/issues/issue-35976.rs new file mode 100644 index 000000000..aa6f74cb5 --- /dev/null +++ b/tests/ui/issues/issue-35976.rs @@ -0,0 +1,24 @@ +// revisions: imported unimported +//[imported] check-pass + +mod private { + pub trait Future { + //[unimported]~^^ HELP perhaps add a `use` for it + fn wait(&self) where Self: Sized; + } + + impl Future for Box { + fn wait(&self) { } + } +} + +#[cfg(imported)] +use private::Future; + +fn bar(arg: Box) { + // Importing the trait means that we don't autoderef `Box` + arg.wait(); + //[unimported]~^ ERROR the `wait` method cannot be invoked on a trait object +} + +fn main() {} diff --git a/tests/ui/issues/issue-35976.unimported.stderr b/tests/ui/issues/issue-35976.unimported.stderr new file mode 100644 index 000000000..5d61bb8ea --- /dev/null +++ b/tests/ui/issues/issue-35976.unimported.stderr @@ -0,0 +1,16 @@ +error: the `wait` method cannot be invoked on a trait object + --> $DIR/issue-35976.rs:20:9 + | +LL | fn wait(&self) where Self: Sized; + | ----- this has a `Sized` requirement +... +LL | arg.wait(); + | ^^^^ + | +help: another candidate was found in the following trait, perhaps add a `use` for it: + | +LL | use private::Future; + | + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-35988.rs b/tests/ui/issues/issue-35988.rs new file mode 100644 index 000000000..5cf2f8e52 --- /dev/null +++ b/tests/ui/issues/issue-35988.rs @@ -0,0 +1,6 @@ +enum E { + V([Box]), + //~^ ERROR the size for values of type +} + +fn main() {} diff --git a/tests/ui/issues/issue-35988.stderr b/tests/ui/issues/issue-35988.stderr new file mode 100644 index 000000000..55988844c --- /dev/null +++ b/tests/ui/issues/issue-35988.stderr @@ -0,0 +1,21 @@ +error[E0277]: the size for values of type `[Box]` cannot be known at compilation time + --> $DIR/issue-35988.rs:2:7 + | +LL | V([Box]), + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[Box]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | V(&[Box]), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | V(Box<[Box]>), + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-36023.rs b/tests/ui/issues/issue-36023.rs new file mode 100644 index 000000000..64d92bf8c --- /dev/null +++ b/tests/ui/issues/issue-36023.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(unused_variables)] +use std::ops::Deref; + +fn main() { + if env_var("FOOBAR").as_ref().map(Deref::deref).ok() == Some("yes") { + panic!() + } + + let env_home: Result = Ok("foo-bar-baz".to_string()); + let env_home = env_home.as_ref().map(Deref::deref).ok(); + + if env_home == Some("") { panic!() } +} + +#[inline(never)] +fn env_var(s: &str) -> Result { + Err(VarError::NotPresent) +} + +pub enum VarError { + NotPresent, + NotUnicode(String), +} diff --git a/tests/ui/issues/issue-36036-associated-type-layout.rs b/tests/ui/issues/issue-36036-associated-type-layout.rs new file mode 100644 index 000000000..022f9a5d5 --- /dev/null +++ b/tests/ui/issues/issue-36036-associated-type-layout.rs @@ -0,0 +1,27 @@ +// run-pass +// Issue 36036: computing the layout of a type composed from another +// trait's associated type caused compiler to ICE when the associated +// type was allowed to be unsized, even though the known instantiated +// type is itself sized. + +#![allow(dead_code)] + +trait Context { + type Container: ?Sized; +} + +impl Context for u16 { + type Container = u8; +} + +struct Wrapper { + container: &'static C::Container +} + +fn foobar(_: Wrapper) {} + +static VALUE: u8 = 0; + +fn main() { + foobar(Wrapper { container: &VALUE }); +} diff --git a/tests/ui/issues/issue-36075.rs b/tests/ui/issues/issue-36075.rs new file mode 100644 index 000000000..bc5bdc3ff --- /dev/null +++ b/tests/ui/issues/issue-36075.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +trait DeclarationParser { + type Declaration; +} + +struct DeclarationListParser<'i, I, P> + where P: DeclarationParser +{ + input: &'i (), + parser: P +} + +fn main() {} diff --git a/tests/ui/issues/issue-3609.rs b/tests/ui/issues/issue-3609.rs new file mode 100644 index 000000000..57ff12a08 --- /dev/null +++ b/tests/ui/issues/issue-3609.rs @@ -0,0 +1,30 @@ +// check-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_mut)] +use std::thread; +use std::sync::mpsc::Sender; + +type RingBuffer = Vec ; +type SamplesFn = Box; + +enum Msg +{ + GetSamples(String, SamplesFn), // sample set name, callback which receives samples +} + +fn foo(name: String, samples_chan: Sender) { + thread::spawn(move|| { + let mut samples_chan = samples_chan; + + let callback: SamplesFn = Box::new(move |buffer| { + for i in 0..buffer.len() { + println!("{}: {}", i, buffer[i]) + } + }); + + samples_chan.send(Msg::GetSamples(name.clone(), callback)); + }).join(); +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-36116.rs b/tests/ui/issues/issue-36116.rs new file mode 100644 index 000000000..c7c70c7af --- /dev/null +++ b/tests/ui/issues/issue-36116.rs @@ -0,0 +1,25 @@ +// Unnecessary path disambiguator is ok + +// check-pass + +macro_rules! m { + ($p: path) => { + let _ = $p(0); + let _: $p; + } +} + +struct Foo { + _a: T, +} + +struct S(T); + +fn f() { + let f = Some(Foo { _a: 42 }).map(|a| a as Foo::); + let g: Foo:: = Foo { _a: 42 }; + + m!(S::); +} + +fn main() {} diff --git a/tests/ui/issues/issue-36260.rs b/tests/ui/issues/issue-36260.rs new file mode 100644 index 000000000..d96dc80ea --- /dev/null +++ b/tests/ui/issues/issue-36260.rs @@ -0,0 +1,13 @@ +// run-pass +// Make sure this compiles without getting a linker error because of missing +// drop-glue because the collector missed adding drop-glue for the closure: + +fn create_fn() -> Box { + let text = String::new(); + + Box::new(move || { let _ = &text; }) +} + +fn main() { + let _ = create_fn(); +} diff --git a/tests/ui/issues/issue-36278-prefix-nesting.rs b/tests/ui/issues/issue-36278-prefix-nesting.rs new file mode 100644 index 000000000..a809f7f13 --- /dev/null +++ b/tests/ui/issues/issue-36278-prefix-nesting.rs @@ -0,0 +1,20 @@ +// run-pass +// Issue 36278: On an unsized struct with >1 level of nontrivial +// nesting, ensure we are computing dynamic size of prefix correctly. + +use std::mem; + +const SZ: usize = 100; +#[allow(unused_tuple_struct_fields)] +struct P([u8; SZ], T); + +type Ack = P>; + +fn main() { + let size_of_sized; let size_of_unsized; + let x: Box> = Box::new(P([0; SZ], P([0; SZ], [0; 0]))); + size_of_sized = mem::size_of_val::>(&x); + let y: Box> = x; + size_of_unsized = mem::size_of_val::>(&y); + assert_eq!(size_of_sized, size_of_unsized); +} diff --git a/tests/ui/issues/issue-36299.rs b/tests/ui/issues/issue-36299.rs new file mode 100644 index 000000000..7b68420b7 --- /dev/null +++ b/tests/ui/issues/issue-36299.rs @@ -0,0 +1,5 @@ +struct Foo<'a, A> {} +//~^ ERROR parameter `'a` is never used +//~| ERROR parameter `A` is never used + +fn main() {} diff --git a/tests/ui/issues/issue-36299.stderr b/tests/ui/issues/issue-36299.stderr new file mode 100644 index 000000000..dc24fb353 --- /dev/null +++ b/tests/ui/issues/issue-36299.stderr @@ -0,0 +1,20 @@ +error[E0392]: parameter `'a` is never used + --> $DIR/issue-36299.rs:1:12 + | +LL | struct Foo<'a, A> {} + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `A` is never used + --> $DIR/issue-36299.rs:1:16 + | +LL | struct Foo<'a, A> {} + | ^ unused parameter + | + = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `A` to be a const parameter, use `const A: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/issues/issue-36379.rs b/tests/ui/issues/issue-36379.rs new file mode 100644 index 000000000..3a3e6f470 --- /dev/null +++ b/tests/ui/issues/issue-36379.rs @@ -0,0 +1,5 @@ +// check-pass + +fn _test() -> impl Default { } + +fn main() {} diff --git a/tests/ui/issues/issue-36400.rs b/tests/ui/issues/issue-36400.rs new file mode 100644 index 000000000..a405f9b11 --- /dev/null +++ b/tests/ui/issues/issue-36400.rs @@ -0,0 +1,6 @@ +fn f(x: &mut u32) {} + +fn main() { + let x = Box::new(3); + f(&mut *x); //~ ERROR cannot borrow `*x` as mutable, as `x` is not declared as mutable +} diff --git a/tests/ui/issues/issue-36400.stderr b/tests/ui/issues/issue-36400.stderr new file mode 100644 index 000000000..5b753c69d --- /dev/null +++ b/tests/ui/issues/issue-36400.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable + --> $DIR/issue-36400.rs:5:7 + | +LL | f(&mut *x); + | ^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = Box::new(3); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-36401.rs b/tests/ui/issues/issue-36401.rs new file mode 100644 index 000000000..f51197b01 --- /dev/null +++ b/tests/ui/issues/issue-36401.rs @@ -0,0 +1,16 @@ +// run-pass +#[derive(Debug)] +pub enum Event { + Key(u8), + Resize, + Unknown(u16), +} + +static XTERM_SINGLE_BYTES : [(u8, Event); 1] = [(1, Event::Resize)]; + +fn main() { + match XTERM_SINGLE_BYTES[0] { + (1, Event::Resize) => {}, + ref bad => panic!("unexpected {:?}", bad) + } +} diff --git a/tests/ui/issues/issue-36474.rs b/tests/ui/issues/issue-36474.rs new file mode 100644 index 000000000..90ee5b3cd --- /dev/null +++ b/tests/ui/issues/issue-36474.rs @@ -0,0 +1,31 @@ +// run-pass +fn main() { + remove_axis(&3, 0); +} + +trait Dimension { + fn slice(&self) -> &[usize]; +} + +impl Dimension for () { + fn slice(&self) -> &[usize] { &[] } +} + +impl Dimension for usize { + fn slice(&self) -> &[usize] { + unsafe { + ::std::slice::from_raw_parts(self, 1) + } + } +} + +fn remove_axis(value: &usize, axis: usize) -> () { + let tup = (); + let mut it = tup.slice().iter(); + for (i, _) in value.slice().iter().enumerate() { + if i == axis { + continue; + } + it.next(); + } +} diff --git a/tests/ui/issues/issue-3656.rs b/tests/ui/issues/issue-3656.rs new file mode 100644 index 000000000..4a9f94306 --- /dev/null +++ b/tests/ui/issues/issue-3656.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +#![allow(improper_ctypes)] +// Issue #3656 +// Incorrect struct size computation in the FFI, because of not taking +// the alignment of elements into account. + +// pretty-expanded FIXME #23616 +// ignore-wasm32-bare no libc to test with +#![feature(rustc_private)] + +extern crate libc; +use libc::{c_uint, c_void}; + +pub struct KEYGEN { + hash_algorithm: [c_uint; 2], + count: u32, + salt: *const c_void, + salt_size: u32, +} + +extern "C" { + // Bogus signature, just need to test if it compiles. + pub fn malloc(data: KEYGEN); +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-3668-2.fixed b/tests/ui/issues/issue-3668-2.fixed new file mode 100644 index 000000000..a95781c6e --- /dev/null +++ b/tests/ui/issues/issue-3668-2.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] +fn f(x:isize) { + let child: isize = x + 1; + //~^ ERROR attempt to use a non-constant value in a constant +} + +fn main() {} diff --git a/tests/ui/issues/issue-3668-2.rs b/tests/ui/issues/issue-3668-2.rs new file mode 100644 index 000000000..8aa0897ec --- /dev/null +++ b/tests/ui/issues/issue-3668-2.rs @@ -0,0 +1,8 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] +fn f(x:isize) { + static child: isize = x + 1; + //~^ ERROR attempt to use a non-constant value in a constant +} + +fn main() {} diff --git a/tests/ui/issues/issue-3668-2.stderr b/tests/ui/issues/issue-3668-2.stderr new file mode 100644 index 000000000..ba9651041 --- /dev/null +++ b/tests/ui/issues/issue-3668-2.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-3668-2.rs:4:27 + | +LL | static child: isize = x + 1; + | ------------ ^ non-constant value + | | + | help: consider using `let` instead of `static`: `let child` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-3668.rs b/tests/ui/issues/issue-3668.rs new file mode 100644 index 000000000..0e1f19a75 --- /dev/null +++ b/tests/ui/issues/issue-3668.rs @@ -0,0 +1,14 @@ +struct P { child: Option> } +trait PTrait { + fn getChildOption(&self) -> Option>; +} + +impl PTrait for P { + fn getChildOption(&self) -> Option> { + static childVal: Box

= self.child.get(); + //~^ ERROR attempt to use a non-constant value in a constant + panic!(); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-3668.stderr b/tests/ui/issues/issue-3668.stderr new file mode 100644 index 000000000..edc49979c --- /dev/null +++ b/tests/ui/issues/issue-3668.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-3668.rs:8:34 + | +LL | static childVal: Box

= self.child.get(); + | --------------- ^^^^ non-constant value + | | + | help: consider using `let` instead of `static`: `let childVal` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-36744-bitcast-args-if-needed.rs b/tests/ui/issues/issue-36744-bitcast-args-if-needed.rs new file mode 100644 index 000000000..34bbb66d9 --- /dev/null +++ b/tests/ui/issues/issue-36744-bitcast-args-if-needed.rs @@ -0,0 +1,23 @@ +// run-pass +// This tests for an ICE (and, if ignored, subsequent LLVM abort) when +// a lifetime-parametric fn is passed into a context whose expected +// type has a differing lifetime parameterization. + +struct A<'a> { + _a: &'a i32, +} + +fn call(s: T, functions: &Vec fn(&'n T)>) { + for function in functions { + function(&s); + } +} + +fn f(a: &A) { println!("a holds {}", a._a); } + +fn main() { + let a = A { _a: &10 }; + + let vec: Vec fn(&'u A<'v>)> = vec![f]; + call(a, &vec); +} diff --git a/tests/ui/issues/issue-36744-without-calls.rs b/tests/ui/issues/issue-36744-without-calls.rs new file mode 100644 index 000000000..dc5dc4f13 --- /dev/null +++ b/tests/ui/issues/issue-36744-without-calls.rs @@ -0,0 +1,13 @@ +// build-pass +// Tests for an LLVM abort when storing a lifetime-parametric fn into +// context that is expecting one that is not lifetime-parametric +// (i.e., has no `for <'_>`). + +pub struct A<'a>(&'a ()); +pub struct S(T); + +pub fn bad<'s>(v: &mut S)>, y: S fn(A<'b>)>) { + *v = y; +} + +fn main() {} diff --git a/tests/ui/issues/issue-36786-resolve-call.rs b/tests/ui/issues/issue-36786-resolve-call.rs new file mode 100644 index 000000000..e5341ba7d --- /dev/null +++ b/tests/ui/issues/issue-36786-resolve-call.rs @@ -0,0 +1,8 @@ +// run-pass +// Ensure that types that rely on obligations are autoderefed +// correctly + +fn main() { + let x : Vec> = vec![Box::new(|| ())]; + x[0]() +} diff --git a/tests/ui/issues/issue-36792.rs b/tests/ui/issues/issue-36792.rs new file mode 100644 index 000000000..99ae633dd --- /dev/null +++ b/tests/ui/issues/issue-36792.rs @@ -0,0 +1,7 @@ +// run-pass +fn foo() -> impl Copy { + foo +} +fn main() { + foo(); +} diff --git a/tests/ui/issues/issue-3680.rs b/tests/ui/issues/issue-3680.rs new file mode 100644 index 000000000..37c9000c0 --- /dev/null +++ b/tests/ui/issues/issue-3680.rs @@ -0,0 +1,9 @@ +fn main() { + match None { + Err(_) => () + //~^ ERROR mismatched types + //~| expected enum `Option<_>` + //~| found enum `Result<_, _>` + //~| expected enum `Option`, found enum `Result` + } +} diff --git a/tests/ui/issues/issue-3680.stderr b/tests/ui/issues/issue-3680.stderr new file mode 100644 index 000000000..29ba44f13 --- /dev/null +++ b/tests/ui/issues/issue-3680.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-3680.rs:3:9 + | +LL | match None { + | ---- this expression has type `Option<_>` +LL | Err(_) => () + | ^^^^^^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option<_>` + found enum `Result<_, _>` +help: try wrapping the pattern in `Some` + | +LL | Some(Err(_)) => () + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-36816.rs b/tests/ui/issues/issue-36816.rs new file mode 100644 index 000000000..54690b43c --- /dev/null +++ b/tests/ui/issues/issue-36816.rs @@ -0,0 +1,7 @@ +// run-pass +macro_rules! m { () => { 1 } } +macro_rules! n { () => { 1 + m!() } } + +fn main() { + let _: [u32; n!()] = [0, 0]; +} diff --git a/tests/ui/issues/issue-36836.rs b/tests/ui/issues/issue-36836.rs new file mode 100644 index 000000000..99c562131 --- /dev/null +++ b/tests/ui/issues/issue-36836.rs @@ -0,0 +1,15 @@ +// Previously, in addition to the real cause of the problem as seen below, +// the compiler would tell the user: +// +// ``` +// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or +// predicates +// ``` +// +// With this test, we check that only the relevant error is emitted. + +trait Foo {} + +impl Foo for Bar {} //~ ERROR cannot find type `Bar` in this scope + +fn main() {} diff --git a/tests/ui/issues/issue-36836.stderr b/tests/ui/issues/issue-36836.stderr new file mode 100644 index 000000000..418194fac --- /dev/null +++ b/tests/ui/issues/issue-36836.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-36836.rs:13:17 + | +LL | impl Foo for Bar {} + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-36839.rs b/tests/ui/issues/issue-36839.rs new file mode 100644 index 000000000..ca3d66b1c --- /dev/null +++ b/tests/ui/issues/issue-36839.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Foo { + type Bar; +} + +pub trait Broken { + type Assoc; + fn broken(&self) where Self::Assoc: Foo; +} + +impl Broken for T { + type Assoc = (); + fn broken(&self) where Self::Assoc: Foo { + let _x: ::Bar; + } +} + +fn main() { + let _m: &dyn Broken = &(); +} diff --git a/tests/ui/issues/issue-36856.rs b/tests/ui/issues/issue-36856.rs new file mode 100644 index 000000000..5657ba69f --- /dev/null +++ b/tests/ui/issues/issue-36856.rs @@ -0,0 +1,16 @@ +// run-pass +// Regression test for #36856. + +// compile-flags:-g +// ignore-asmjs wasm2js does not support source maps yet + +fn g() -> bool { + false +} + +pub fn main() { + let a = !g(); + if a != !g() { + panic!(); + } +} diff --git a/tests/ui/issues/issue-36936.rs b/tests/ui/issues/issue-36936.rs new file mode 100644 index 000000000..486a422b7 --- /dev/null +++ b/tests/ui/issues/issue-36936.rs @@ -0,0 +1,26 @@ +// run-pass +// check that casts are not being treated as lexprs. + +fn main() { + let mut a = 0i32; + let b = &(a as i32); + a = 1; + assert_ne!(&a as *const i32, b as *const i32); + assert_eq!(*b, 0); + + assert_eq!(issue_36936(), 1); +} + + +struct A(u32); + +impl Drop for A { + fn drop(&mut self) { + self.0 = 0; + } +} + +fn issue_36936() -> u32 { + let a = &(A(1) as A); + a.0 +} diff --git a/tests/ui/issues/issue-36954.rs b/tests/ui/issues/issue-36954.rs new file mode 100644 index 000000000..56ff9926e --- /dev/null +++ b/tests/ui/issues/issue-36954.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-36954.rs + +extern crate issue_36954 as lib; + +fn main() { + let _ = lib::FOO; +} diff --git a/tests/ui/issues/issue-3702-2.rs b/tests/ui/issues/issue-3702-2.rs new file mode 100644 index 000000000..d47f6d248 --- /dev/null +++ b/tests/ui/issues/issue-3702-2.rs @@ -0,0 +1,20 @@ +pub trait ToPrimitive { + fn to_int(&self) -> isize { 0 } +} + +impl ToPrimitive for i32 {} +impl ToPrimitive for isize {} + +trait Add { + fn to_int(&self) -> isize; + fn add_dynamic(&self, other: &dyn Add) -> isize; +} + +impl Add for isize { + fn to_int(&self) -> isize { *self } + fn add_dynamic(&self, other: &dyn Add) -> isize { + self.to_int() + other.to_int() //~ ERROR multiple applicable items in scope + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-3702-2.stderr b/tests/ui/issues/issue-3702-2.stderr new file mode 100644 index 000000000..1fd64ca90 --- /dev/null +++ b/tests/ui/issues/issue-3702-2.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/issue-3702-2.rs:16:14 + | +LL | self.to_int() + other.to_int() + | ^^^^^^ multiple `to_int` found + | +note: candidate #1 is defined in an impl of the trait `ToPrimitive` for the type `isize` + --> $DIR/issue-3702-2.rs:2:5 + | +LL | fn to_int(&self) -> isize { 0 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `Add` for the type `isize` + --> $DIR/issue-3702-2.rs:14:5 + | +LL | fn to_int(&self) -> isize { *self } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | ToPrimitive::to_int(&self) + other.to_int() + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | Add::to_int(&self) + other.to_int() + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-3702.rs b/tests/ui/issues/issue-3702.rs new file mode 100644 index 000000000..f48d549b3 --- /dev/null +++ b/tests/ui/issues/issue-3702.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + trait Text { + fn to_string(&self) -> String; + } + + fn to_string(t: Box) { + println!("{}", (*t).to_string()); + } + +} diff --git a/tests/ui/issues/issue-37051.rs b/tests/ui/issues/issue-37051.rs new file mode 100644 index 000000000..9cae6cf5e --- /dev/null +++ b/tests/ui/issues/issue-37051.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait State: Sized { + type NextState: State = StateMachineEnded; + fn execute(self) -> Option; +} + +struct StateMachineEnded; + +impl State for StateMachineEnded { + fn execute(self) -> Option { + None + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-3707.rs b/tests/ui/issues/issue-3707.rs new file mode 100644 index 000000000..0817c51ee --- /dev/null +++ b/tests/ui/issues/issue-3707.rs @@ -0,0 +1,18 @@ +struct Obj { + member: usize +} + +impl Obj { + pub fn boom() -> bool { + return 1+1 == 2 + } + pub fn chirp(&self) { + self.boom(); //~ ERROR no method named `boom` found + } +} + +fn main() { + let o = Obj { member: 0 }; + o.chirp(); + 1 + 1; +} diff --git a/tests/ui/issues/issue-3707.stderr b/tests/ui/issues/issue-3707.stderr new file mode 100644 index 000000000..07c8101cb --- /dev/null +++ b/tests/ui/issues/issue-3707.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `boom` found for reference `&Obj` in the current scope + --> $DIR/issue-3707.rs:10:14 + | +LL | self.boom(); + | -----^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `Obj::boom()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `Obj` + --> $DIR/issue-3707.rs:6:5 + | +LL | pub fn boom() -> bool { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-37109.rs b/tests/ui/issues/issue-37109.rs new file mode 100644 index 000000000..1e57d5f95 --- /dev/null +++ b/tests/ui/issues/issue-37109.rs @@ -0,0 +1,16 @@ +// run-pass +trait ToRef<'a> { + type Ref: 'a; +} + +impl<'a, U: 'a> ToRef<'a> for U { + type Ref = &'a U; +} + +fn example<'a, T>(value: &'a T) -> (>::Ref, u32) { + (value, 0) +} + +fn main() { + example(&0); +} diff --git a/tests/ui/issues/issue-37131.rs b/tests/ui/issues/issue-37131.rs new file mode 100644 index 000000000..ac2d1d1ed --- /dev/null +++ b/tests/ui/issues/issue-37131.rs @@ -0,0 +1,9 @@ +// Tests that compiling for a target which is not installed will result in a helpful +// error message. + +// compile-flags: --target=thumbv6m-none-eabi +// ignore-arm +// needs-llvm-components: arm + +// error-pattern:target may not be installed +fn main() { } diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/issues/issue-37131.stderr new file mode 100644 index 000000000..9ecae3e7a --- /dev/null +++ b/tests/ui/issues/issue-37131.stderr @@ -0,0 +1,11 @@ +error[E0463]: can't find crate for `std` + | + = note: the `thumbv6m-none-eabi` target may not be installed + = help: consider downloading the target with `rustup target add thumbv6m-none-eabi` + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error: requires `sized` lang_item + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-37291/auxiliary/lib.rs b/tests/ui/issues/issue-37291/auxiliary/lib.rs new file mode 100644 index 000000000..1b163ee13 --- /dev/null +++ b/tests/ui/issues/issue-37291/auxiliary/lib.rs @@ -0,0 +1,42 @@ +#![crate_type = "lib"] + +use std::ops::Mul; + +pub trait A {} +pub trait B { + type AT: A; +} +pub trait C { + type BT: B; +} + +pub struct AV; +impl A for AV {} + +pub struct BV; +impl B for BV { + type AT = AV; +} + +pub struct CV; +impl C for CV { + type BT = BV; +} + +pub struct WrapperB(pub T); +pub struct WrapperC(pub T); + +impl Mul::AT>> for WrapperC + where C1: C +{ + type Output = u8; + fn mul(self, _: WrapperB<::AT>) -> Self::Output { + loop {} + } +} +impl Mul> for WrapperC { + type Output = u8; + fn mul(self, _: WrapperC) -> Self::Output { + loop {} + } +} diff --git a/tests/ui/issues/issue-37291/main.rs b/tests/ui/issues/issue-37291/main.rs new file mode 100644 index 000000000..6fb6b50da --- /dev/null +++ b/tests/ui/issues/issue-37291/main.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_imports)] +// aux-build:lib.rs + +// Regression test for #37291. The problem was that the starting +// environment for a specialization check was not including the +// where-clauses from the impl when attempting to normalize the impl's +// trait-ref, so things like `::Item` could not resolve, +// since the `C: Foo` trait bound was not included in the environment. + +extern crate lib; + +use lib::{CV, WrapperB, WrapperC}; + +fn main() { + let a = WrapperC(CV); + let b = WrapperC(CV); + if false { + let _ = a * b; + } +} diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr new file mode 100644 index 000000000..3a1c0b82c --- /dev/null +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(.....), ...), ...) as Foo>::recurse` + --> $DIR/issue-37311.rs:17:9 + | +LL | (self, self).recurse(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `::recurse` defined here + --> $DIR/issue-37311.rs:16:5 + | +LL | fn recurse(&self) { + | ^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311.polonius/issue-37311.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs new file mode 100644 index 000000000..50d1f166c --- /dev/null +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.rs @@ -0,0 +1,23 @@ +// build-fail +// normalize-stderr-test: ".nll/" -> "/" + +trait Mirror { + type Image; +} + +impl Mirror for T { type Image = T; } + +trait Foo { + fn recurse(&self); +} + +impl Foo for T { + #[allow(unconditional_recursion)] + fn recurse(&self) { + (self, self).recurse(); //~ ERROR reached the recursion limit + } +} + +fn main() { + ().recurse(); +} diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr new file mode 100644 index 000000000..5b8299fe8 --- /dev/null +++ b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `<(&(&(..., ...), ...), ...) as Foo>::recurse` + --> $DIR/issue-37311.rs:17:9 + | +LL | (self, self).recurse(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `::recurse` defined here + --> $DIR/issue-37311.rs:16:5 + | +LL | fn recurse(&self) { + | ^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311/issue-37311.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-3743.rs b/tests/ui/issues/issue-3743.rs new file mode 100644 index 000000000..07741914f --- /dev/null +++ b/tests/ui/issues/issue-3743.rs @@ -0,0 +1,55 @@ +// run-pass +// If `Mul` used an associated type for its output, this test would +// work more smoothly. + +use std::ops::Mul; + +#[derive(Copy, Clone)] +struct Vec2 { + x: f64, + y: f64 +} + +// methods we want to export as methods as well as operators +impl Vec2 { +#[inline(always)] + fn vmul(self, other: f64) -> Vec2 { + Vec2 { x: self.x * other, y: self.y * other } + } +} + +// Right-hand-side operator visitor pattern +trait RhsOfVec2Mul { + type Result; + + fn mul_vec2_by(&self, lhs: &Vec2) -> Self::Result; +} + +// Vec2's implementation of Mul "from the other side" using the above trait +impl> Mul for Vec2 { + type Output = Res; + + fn mul(self, rhs: Rhs) -> Res { rhs.mul_vec2_by(&self) } +} + +// Implementation of 'f64 as right-hand-side of Vec2::Mul' +impl RhsOfVec2Mul for f64 { + type Result = Vec2; + + fn mul_vec2_by(&self, lhs: &Vec2) -> Vec2 { lhs.vmul(*self) } +} + +// Usage with failing inference +pub fn main() { + let a = Vec2 { x: 3.0f64, y: 4.0f64 }; + + // the following compiles and works properly + let v1: Vec2 = a * 3.0f64; + println!("{} {}", v1.x, v1.y); + + // the following compiles but v2 will not be Vec2 yet and + // using it later will cause an error that the type of v2 + // must be known + let v2 = a * 3.0f64; + println!("{} {}", v2.x, v2.y); // error regarding v2's type +} diff --git a/tests/ui/issues/issue-37510.rs b/tests/ui/issues/issue-37510.rs new file mode 100644 index 000000000..2081c9f7e --- /dev/null +++ b/tests/ui/issues/issue-37510.rs @@ -0,0 +1,14 @@ +// check-pass + +fn foo(_: &mut i32) -> bool { true } + +fn main() { + let opt = Some(92); + let mut x = 62; + + if let Some(_) = opt { + + } else if foo(&mut x) { + + } +} diff --git a/tests/ui/issues/issue-3753.rs b/tests/ui/issues/issue-3753.rs new file mode 100644 index 000000000..dc9e42bad --- /dev/null +++ b/tests/ui/issues/issue-3753.rs @@ -0,0 +1,32 @@ +// run-pass +// Issue #3656 +// Issue Name: pub method preceded by attribute can't be parsed +// Abstract: Visibility parsing failed when compiler parsing + +use std::f64; + +#[derive(Copy, Clone)] +pub struct Point { + x: f64, + y: f64 +} + +#[derive(Copy, Clone)] +pub enum Shape { + Circle(Point, f64), + Rectangle(Point, Point) +} + +impl Shape { + pub fn area(&self, sh: Shape) -> f64 { + match sh { + Shape::Circle(_, size) => f64::consts::PI * size * size, + Shape::Rectangle(Point {x, y}, Point {x: x2, y: y2}) => (x2 - x) * (y2 - y) + } + } +} + +pub fn main(){ + let s = Shape::Circle(Point { x: 1.0, y: 2.0 }, 3.0); + println!("{}", s.area(s)); +} diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs new file mode 100644 index 000000000..1e67e9a81 --- /dev/null +++ b/tests/ui/issues/issue-37534.rs @@ -0,0 +1,6 @@ +struct Foo { } +//~^ ERROR expected trait, found derive macro `Hash` +//~^^ ERROR parameter `T` is never used +//~^^^ WARN default bound relaxed for a type parameter, but this does nothing + +fn main() { } diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr new file mode 100644 index 000000000..895479986 --- /dev/null +++ b/tests/ui/issues/issue-37534.stderr @@ -0,0 +1,29 @@ +error[E0404]: expected trait, found derive macro `Hash` + --> $DIR/issue-37534.rs:1:16 + | +LL | struct Foo { } + | ^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::hash::Hash; + | + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-37534.rs:1:12 + | +LL | struct Foo { } + | ^ + +error[E0392]: parameter `T` is never used + --> $DIR/issue-37534.rs:1:12 + | +LL | struct Foo { } + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0392, E0404. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/issues/issue-37576.rs b/tests/ui/issues/issue-37576.rs new file mode 100644 index 000000000..e7f933ab2 --- /dev/null +++ b/tests/ui/issues/issue-37576.rs @@ -0,0 +1,45 @@ +fn main() { + 'test_1: while break 'test_1 {} + while break {} + //~^ ERROR `break` or `continue` with no label + + 'test_2: while let true = break 'test_2 {} + while let true = break {} + //~^ ERROR `break` or `continue` with no label + + loop { 'test_3: while break 'test_3 {} } + loop { while break {} } + //~^ ERROR `break` or `continue` with no label + + loop { + 'test_4: while break 'test_4 {} + break; + } + loop { + while break {} + //~^ ERROR `break` or `continue` with no label + break; + } + + 'test_5: while continue 'test_5 {} + while continue {} + //~^ ERROR `break` or `continue` with no label + + 'test_6: while let true = continue 'test_6 {} + while let true = continue {} + //~^ ERROR `break` or `continue` with no label + + loop { 'test_7: while continue 'test_7 {} } + loop { while continue {} } + //~^ ERROR `break` or `continue` with no label + + loop { + 'test_8: while continue 'test_8 {} + continue; + } + loop { + while continue {} + //~^ ERROR `break` or `continue` with no label + continue; + } +} diff --git a/tests/ui/issues/issue-37576.stderr b/tests/ui/issues/issue-37576.stderr new file mode 100644 index 000000000..d19e1f453 --- /dev/null +++ b/tests/ui/issues/issue-37576.stderr @@ -0,0 +1,51 @@ +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:3:11 + | +LL | while break {} + | ^^^^^ unlabeled `break` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:7:22 + | +LL | while let true = break {} + | ^^^^^ unlabeled `break` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:11:18 + | +LL | loop { while break {} } + | ^^^^^ unlabeled `break` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:19:15 + | +LL | while break {} + | ^^^^^ unlabeled `break` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:25:11 + | +LL | while continue {} + | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:29:22 + | +LL | while let true = continue {} + | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:33:18 + | +LL | loop { while continue {} } + | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-37576.rs:41:15 + | +LL | while continue {} + | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0590`. diff --git a/tests/ui/issues/issue-37598.rs b/tests/ui/issues/issue-37598.rs new file mode 100644 index 000000000..458e999c3 --- /dev/null +++ b/tests/ui/issues/issue-37598.rs @@ -0,0 +1,11 @@ +// check-pass + +fn check(list: &[u8]) { + match list { + &[] => {}, + &[_u1, _u2, ref _next @ ..] => {}, + &[_u1] => {}, + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-3763.rs b/tests/ui/issues/issue-3763.rs new file mode 100644 index 000000000..25ad6b319 --- /dev/null +++ b/tests/ui/issues/issue-3763.rs @@ -0,0 +1,29 @@ +// compile-flags: -Zsave-analysis +// Also regression test for #69416 + +mod my_mod { + pub struct MyStruct { + priv_field: isize + } + pub fn MyStruct () -> MyStruct { + MyStruct {priv_field: 4} + } + impl MyStruct { + fn happyfun(&self) {} + } +} + +fn main() { + let my_struct = my_mod::MyStruct(); + let _woohoo = (&my_struct).priv_field; + //~^ ERROR field `priv_field` of struct `MyStruct` is private + + let _woohoo = (Box::new(my_struct)).priv_field; + //~^ ERROR field `priv_field` of struct `MyStruct` is private + + (&my_struct).happyfun(); //~ ERROR associated function `happyfun` is private + + (Box::new(my_struct)).happyfun(); //~ ERROR associated function `happyfun` is private + let nope = my_struct.priv_field; + //~^ ERROR field `priv_field` of struct `MyStruct` is private +} diff --git a/tests/ui/issues/issue-3763.stderr b/tests/ui/issues/issue-3763.stderr new file mode 100644 index 000000000..6f4567546 --- /dev/null +++ b/tests/ui/issues/issue-3763.stderr @@ -0,0 +1,40 @@ +error[E0616]: field `priv_field` of struct `MyStruct` is private + --> $DIR/issue-3763.rs:18:32 + | +LL | let _woohoo = (&my_struct).priv_field; + | ^^^^^^^^^^ private field + +error[E0616]: field `priv_field` of struct `MyStruct` is private + --> $DIR/issue-3763.rs:21:41 + | +LL | let _woohoo = (Box::new(my_struct)).priv_field; + | ^^^^^^^^^^ private field + +error[E0624]: associated function `happyfun` is private + --> $DIR/issue-3763.rs:24:18 + | +LL | fn happyfun(&self) {} + | ------------------ private associated function defined here +... +LL | (&my_struct).happyfun(); + | ^^^^^^^^ private associated function + +error[E0624]: associated function `happyfun` is private + --> $DIR/issue-3763.rs:26:27 + | +LL | fn happyfun(&self) {} + | ------------------ private associated function defined here +... +LL | (Box::new(my_struct)).happyfun(); + | ^^^^^^^^ private associated function + +error[E0616]: field `priv_field` of struct `MyStruct` is private + --> $DIR/issue-3763.rs:27:26 + | +LL | let nope = my_struct.priv_field; + | ^^^^^^^^^^ private field + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0616, E0624. +For more information about an error, try `rustc --explain E0616`. diff --git a/tests/ui/issues/issue-37665.rs b/tests/ui/issues/issue-37665.rs new file mode 100644 index 000000000..81ff478aa --- /dev/null +++ b/tests/ui/issues/issue-37665.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z unpretty=mir + +use std::path::MAIN_SEPARATOR; + +fn main() { + let mut foo : String = "hello".to_string(); + foo.push(MAIN_SEPARATOR); + println!("{}", foo); + let x: () = 0; //~ ERROR: mismatched types +} diff --git a/tests/ui/issues/issue-37665.stderr b/tests/ui/issues/issue-37665.stderr new file mode 100644 index 000000000..1e1f451b4 --- /dev/null +++ b/tests/ui/issues/issue-37665.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-37665.rs:9:17 + | +LL | let x: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-37686.rs b/tests/ui/issues/issue-37686.rs new file mode 100644 index 000000000..ba58e9e9d --- /dev/null +++ b/tests/ui/issues/issue-37686.rs @@ -0,0 +1,7 @@ +// run-pass +fn main() { + match (0, 0) { + (usize::MIN, usize::MAX) => {} + _ => {} + } +} diff --git a/tests/ui/issues/issue-37725.rs b/tests/ui/issues/issue-37725.rs new file mode 100644 index 000000000..1c6df0da6 --- /dev/null +++ b/tests/ui/issues/issue-37725.rs @@ -0,0 +1,12 @@ +// build-pass +// compiler-opts: -Zmir-opt-level=2 + +#![allow(dead_code)] +trait Foo { + fn foo(&self); +} + +fn foo<'a>(s: &'a mut ()) where &'a mut (): Foo { + s.foo(); +} +fn main() {} diff --git a/tests/ui/issues/issue-37733.rs b/tests/ui/issues/issue-37733.rs new file mode 100644 index 000000000..e211e2c33 --- /dev/null +++ b/tests/ui/issues/issue-37733.rs @@ -0,0 +1,7 @@ +// build-pass +#![allow(dead_code)] +type A = for<> fn(); + +type B = for<'a,> fn(); + +pub fn main() {} diff --git a/tests/ui/issues/issue-3779.rs b/tests/ui/issues/issue-3779.rs new file mode 100644 index 000000000..901c1be80 --- /dev/null +++ b/tests/ui/issues/issue-3779.rs @@ -0,0 +1,8 @@ +struct S { + //~^ ERROR E0072 + element: Option +} + +fn main() { + let x = S { element: None }; +} diff --git a/tests/ui/issues/issue-3779.stderr b/tests/ui/issues/issue-3779.stderr new file mode 100644 index 000000000..a0dbcc920 --- /dev/null +++ b/tests/ui/issues/issue-3779.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `S` has infinite size + --> $DIR/issue-3779.rs:1:1 + | +LL | struct S { + | ^^^^^^^^ +LL | +LL | element: Option + | - recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | element: Option> + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-37884.rs b/tests/ui/issues/issue-37884.rs new file mode 100644 index 000000000..ee37481b2 --- /dev/null +++ b/tests/ui/issues/issue-37884.rs @@ -0,0 +1,14 @@ +struct RepeatMut<'a, T>(T, &'a ()); + +impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { + + type Item = &'a mut T; + fn next(&'a mut self) -> Option + //~^ ERROR method not compatible with trait + //~| lifetime mismatch + { + Some(&mut self.0) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr new file mode 100644 index 000000000..7ddb36c8e --- /dev/null +++ b/tests/ui/issues/issue-37884.stderr @@ -0,0 +1,22 @@ +error[E0308]: method not compatible with trait + --> $DIR/issue-37884.rs:6:5 + | +LL | fn next(&'a mut self) -> Option + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&mut RepeatMut<'a, T>) -> Option<_>` + found signature `fn(&'a mut RepeatMut<'a, T>) -> Option<_>` +note: the anonymous lifetime as defined here... + --> $DIR/issue-37884.rs:6:5 + | +LL | fn next(&'a mut self) -> Option + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/issue-37884.rs:3:6 + | +LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-3794.rs b/tests/ui/issues/issue-3794.rs new file mode 100644 index 000000000..b1f028fbc --- /dev/null +++ b/tests/ui/issues/issue-3794.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(dead_code)] + +trait T { + fn print(&self); +} + +#[derive(Debug)] +struct S { + s: isize, +} + +impl T for S { + fn print(&self) { + println!("{:?}", self); + } +} + +fn print_t(t: &dyn T) { + t.print(); +} + +fn print_s(s: &S) { + s.print(); +} + +pub fn main() { + let s: Box = Box::new(S { s: 5 }); + print_s(&*s); + let t: Box = s as Box; + print_t(&*t); +} diff --git a/tests/ui/issues/issue-38160.rs b/tests/ui/issues/issue-38160.rs new file mode 100644 index 000000000..0da8b7900 --- /dev/null +++ b/tests/ui/issues/issue-38160.rs @@ -0,0 +1,19 @@ +// check-pass + +trait MyTrait { + const MY_CONST: &'static str; +} + +macro_rules! my_macro { + () => { + struct MyStruct; + + impl MyTrait for MyStruct { + const MY_CONST: &'static str = stringify!(abc); + } + } +} + +my_macro!(); + +fn main() {} diff --git a/tests/ui/issues/issue-38190.rs b/tests/ui/issues/issue-38190.rs new file mode 100644 index 000000000..cfa0420c8 --- /dev/null +++ b/tests/ui/issues/issue-38190.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:issue-38190.rs +// ignore-pretty issue #37195 + +#[macro_use] +extern crate issue_38190; + +mod auxiliary { + m!([ + #[path = "issue-38190.rs"] + mod issue_38190; + ]); +} + +fn main() {} diff --git a/tests/ui/issues/issue-38226.rs b/tests/ui/issues/issue-38226.rs new file mode 100644 index 000000000..3213e3618 --- /dev/null +++ b/tests/ui/issues/issue-38226.rs @@ -0,0 +1,15 @@ +// run-pass +// This test makes sure that we don't run into a linker error because of the +// middle::reachable pass missing trait methods with default impls. + +// aux-build:issue-38226-aux.rs + +// Need -Cno-prepopulate-passes to really disable inlining, otherwise the faulty +// code gets optimized out: +// compile-flags: -Cno-prepopulate-passes -Cpasses=name-anon-globals + +extern crate issue_38226_aux; + +fn main() { + issue_38226_aux::foo::<()>(); +} diff --git a/tests/ui/issues/issue-38381.rs b/tests/ui/issues/issue-38381.rs new file mode 100644 index 000000000..82d4a4e32 --- /dev/null +++ b/tests/ui/issues/issue-38381.rs @@ -0,0 +1,7 @@ +// check-pass + +use std::ops::Deref; + +fn main() { + let _x: fn(&i32) -> <&i32 as Deref>::Target = unimplemented!(); +} diff --git a/tests/ui/issues/issue-38412.rs b/tests/ui/issues/issue-38412.rs new file mode 100644 index 000000000..96bd93af5 --- /dev/null +++ b/tests/ui/issues/issue-38412.rs @@ -0,0 +1,10 @@ +fn main() { + let Box(a) = loop { }; + //~^ ERROR cannot match against a tuple struct which contains private fields + + // (The below is a trick to allow compiler to infer a type for + // variable `a` without attempting to ascribe a type to the + // pattern or otherwise attempting to name the Box type, which + // would run afoul of issue #22207) + let _b: *mut i32 = *a; +} diff --git a/tests/ui/issues/issue-38412.stderr b/tests/ui/issues/issue-38412.stderr new file mode 100644 index 000000000..610696f84 --- /dev/null +++ b/tests/ui/issues/issue-38412.stderr @@ -0,0 +1,9 @@ +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/issue-38412.rs:2:9 + | +LL | let Box(a) = loop { }; + | ^^^ constructor is not visible here due to private fields + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-38437.rs b/tests/ui/issues/issue-38437.rs new file mode 100644 index 000000000..e14121690 --- /dev/null +++ b/tests/ui/issues/issue-38437.rs @@ -0,0 +1,46 @@ +// run-pass +#![allow(dead_code)] +// Check that drop elaboration clears the "master" discriminant +// drop flag even if it protects no fields. + +struct Good(usize); +impl Drop for Good { + #[inline(never)] + fn drop(&mut self) { + println!("dropping Good({})", self.0); + } +} + +struct Void; +impl Drop for Void { + #[inline(never)] + fn drop(&mut self) { + panic!("Suddenly, a Void appears."); + } +} + +enum E { + Never(Void), + Fine(Good) +} + +fn main() { + let mut go = true; + + loop { + let next; + match go { + true => next = E::Fine(Good(123)), + false => return, + } + + match next { + E::Never(_) => return, + E::Fine(_good) => go = false, + } + + // `next` is dropped and StorageDead'd here. We must reset the + // discriminant's drop flag to avoid random variants being + // dropped. + } +} diff --git a/tests/ui/issues/issue-38458.rs b/tests/ui/issues/issue-38458.rs new file mode 100644 index 000000000..665a8fdf8 --- /dev/null +++ b/tests/ui/issues/issue-38458.rs @@ -0,0 +1,5 @@ +const x: () = { + return; //~ ERROR return statement outside of function body +}; + +fn main() {} diff --git a/tests/ui/issues/issue-38458.stderr b/tests/ui/issues/issue-38458.stderr new file mode 100644 index 000000000..c04a01118 --- /dev/null +++ b/tests/ui/issues/issue-38458.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-38458.rs:2:5 + | +LL | return; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/issues/issue-3847.rs b/tests/ui/issues/issue-3847.rs new file mode 100644 index 000000000..16e0b00b3 --- /dev/null +++ b/tests/ui/issues/issue-3847.rs @@ -0,0 +1,13 @@ +// run-pass +mod buildings { + pub struct Tower { pub height: usize } +} + +pub fn main() { + let sears = buildings::Tower { height: 1451 }; + let h: usize = match sears { + buildings::Tower { height: h } => { h } + }; + + println!("{}", h); +} diff --git a/tests/ui/issues/issue-38556.rs b/tests/ui/issues/issue-38556.rs new file mode 100644 index 000000000..63fd9db08 --- /dev/null +++ b/tests/ui/issues/issue-38556.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +pub struct Foo; + +macro_rules! reexport { + () => { use Foo as Bar; } +} + +reexport!(); + +fn main() { + fn f(_: Bar) {} +} diff --git a/tests/ui/issues/issue-38727.rs b/tests/ui/issues/issue-38727.rs new file mode 100644 index 000000000..2d418b652 --- /dev/null +++ b/tests/ui/issues/issue-38727.rs @@ -0,0 +1,13 @@ +// build-pass +#![allow(dead_code)] +#[repr(u64)] +enum A { + A = 0u64, + B = !0u64, +} + +fn cmp() -> A { + A::B +} + +fn main() {} diff --git a/tests/ui/issues/issue-3874.rs b/tests/ui/issues/issue-3874.rs new file mode 100644 index 000000000..f9553d88d --- /dev/null +++ b/tests/ui/issues/issue-3874.rs @@ -0,0 +1,12 @@ +// build-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +enum PureCounter { PureCounterVariant(usize) } + +fn each(thing: PureCounter, blk: F) where F: FnOnce(&usize) { + let PureCounter::PureCounterVariant(ref x) = thing; + blk(x); +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-38763.rs b/tests/ui/issues/issue-38763.rs new file mode 100644 index 000000000..a966cf217 --- /dev/null +++ b/tests/ui/issues/issue-38763.rs @@ -0,0 +1,13 @@ +// run-pass +// ignore-emscripten + +#[repr(C)] +pub struct Foo(i128); + +#[no_mangle] +#[allow(improper_ctypes_definitions)] +pub extern "C" fn foo(x: Foo) -> Foo { x } + +fn main() { + foo(Foo(1)); +} diff --git a/tests/ui/issues/issue-3878.rs b/tests/ui/issues/issue-3878.rs new file mode 100644 index 000000000..6de3405af --- /dev/null +++ b/tests/ui/issues/issue-3878.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(path_statements)] + +pub fn main() { + let y: Box<_> = Box::new(1); + y; +} diff --git a/tests/ui/issues/issue-38821.rs b/tests/ui/issues/issue-38821.rs new file mode 100644 index 000000000..6753860e9 --- /dev/null +++ b/tests/ui/issues/issue-38821.rs @@ -0,0 +1,33 @@ +pub struct Nullable(T); + +pub trait NotNull {} + +pub trait IntoNullable { + type Nullable; +} + +impl IntoNullable for T { + type Nullable = Nullable; +} + +impl IntoNullable for Nullable { + type Nullable = Nullable; +} + +pub trait Expression { + type SqlType; +} + +pub trait Column: Expression {} + +#[derive(Debug, Copy, Clone)] +//~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied +pub enum ColumnInsertValue where + Col: Column, + Expr: Expression::Nullable>, +{ + Expression(Col, Expr), + Default(Col), +} + +fn main() {} diff --git a/tests/ui/issues/issue-38821.stderr b/tests/ui/issues/issue-38821.stderr new file mode 100644 index 000000000..a52a9c138 --- /dev/null +++ b/tests/ui/issues/issue-38821.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied + --> $DIR/issue-38821.rs:23:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | +note: required for `::SqlType` to implement `IntoNullable` + --> $DIR/issue-38821.rs:9:18 + | +LL | impl IntoNullable for T { + | ------- ^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting the associated type + | +LL | Expr: Expression::Nullable>, ::SqlType: NotNull, + | +++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-38857.rs b/tests/ui/issues/issue-38857.rs new file mode 100644 index 000000000..81d881c10 --- /dev/null +++ b/tests/ui/issues/issue-38857.rs @@ -0,0 +1,5 @@ +fn main() { + let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; + //~^ ERROR failed to resolve: could not find `imp` in `sys` [E0433] + //~^^ ERROR module `sys` is private [E0603] +} diff --git a/tests/ui/issues/issue-38857.stderr b/tests/ui/issues/issue-38857.stderr new file mode 100644 index 000000000..4d505784b --- /dev/null +++ b/tests/ui/issues/issue-38857.stderr @@ -0,0 +1,19 @@ +error[E0433]: failed to resolve: could not find `imp` in `sys` + --> $DIR/issue-38857.rs:2:23 + | +LL | let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; + | ^^^ could not find `imp` in `sys` + +error[E0603]: module `sys` is private + --> $DIR/issue-38857.rs:2:18 + | +LL | let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() }; + | ^^^ private module + | +note: the module `sys` is defined here + --> $SRC_DIR/std/src/lib.rs:LL:COL + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0603. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/issues/issue-38875/auxiliary/issue-38875-b.rs b/tests/ui/issues/issue-38875/auxiliary/issue-38875-b.rs new file mode 100644 index 000000000..e9f7fefb6 --- /dev/null +++ b/tests/ui/issues/issue-38875/auxiliary/issue-38875-b.rs @@ -0,0 +1 @@ +pub const FOO: usize = *&0; diff --git a/tests/ui/issues/issue-38875/issue-38875.rs b/tests/ui/issues/issue-38875/issue-38875.rs new file mode 100644 index 000000000..124e4d6fd --- /dev/null +++ b/tests/ui/issues/issue-38875/issue-38875.rs @@ -0,0 +1,8 @@ +// aux-build:issue-38875-b.rs +// check-pass + +extern crate issue_38875_b; + +fn main() { + let test_x = [0; issue_38875_b::FOO]; +} diff --git a/tests/ui/issues/issue-3888-2.rs b/tests/ui/issues/issue-3888-2.rs new file mode 100644 index 000000000..d1ef914bd --- /dev/null +++ b/tests/ui/issues/issue-3888-2.rs @@ -0,0 +1,9 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn vec_peek<'r, T>(v: &'r [T]) -> &'r [T] { + &v[1..5] +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-38919.rs b/tests/ui/issues/issue-38919.rs new file mode 100644 index 000000000..3d28f1936 --- /dev/null +++ b/tests/ui/issues/issue-38919.rs @@ -0,0 +1,5 @@ +fn foo() { + T::Item; //~ ERROR no associated item named `Item` found +} + +fn main() { } diff --git a/tests/ui/issues/issue-38919.stderr b/tests/ui/issues/issue-38919.stderr new file mode 100644 index 000000000..f9ab8a515 --- /dev/null +++ b/tests/ui/issues/issue-38919.stderr @@ -0,0 +1,11 @@ +error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope + --> $DIR/issue-38919.rs:2:8 + | +LL | fn foo() { + | - associated item `Item` not found for this type parameter +LL | T::Item; + | ^^^^ associated item not found in `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-38942.rs b/tests/ui/issues/issue-38942.rs new file mode 100644 index 000000000..308bdd6e2 --- /dev/null +++ b/tests/ui/issues/issue-38942.rs @@ -0,0 +1,17 @@ +// run-pass +// See https://github.com/rust-lang/rust/issues/38942 + +#[repr(u64)] +pub enum NSEventType { + NSEventTypePressure, +} + +pub const A: u64 = NSEventType::NSEventTypePressure as u64; + +fn banana() -> u64 { + A +} + +fn main() { + println!("banana! {}", banana()); +} diff --git a/tests/ui/issues/issue-3895.rs b/tests/ui/issues/issue-3895.rs new file mode 100644 index 000000000..c560ca60d --- /dev/null +++ b/tests/ui/issues/issue-3895.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + enum State { BadChar, BadSyntax } + + match State::BadChar { + _ if true => State::BadChar, + State::BadChar | State::BadSyntax => panic!() , + }; +} diff --git a/tests/ui/issues/issue-38954.rs b/tests/ui/issues/issue-38954.rs new file mode 100644 index 000000000..61df411b1 --- /dev/null +++ b/tests/ui/issues/issue-38954.rs @@ -0,0 +1,4 @@ +fn _test(ref _p: str) {} +//~^ ERROR the size for values of type + +fn main() { } diff --git a/tests/ui/issues/issue-38954.stderr b/tests/ui/issues/issue-38954.stderr new file mode 100644 index 000000000..ab15bb1af --- /dev/null +++ b/tests/ui/issues/issue-38954.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-38954.rs:1:10 + | +LL | fn _test(ref _p: str) {} + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn _test(ref _p: &str) {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-38987.rs b/tests/ui/issues/issue-38987.rs new file mode 100644 index 000000000..cb4e1b0d4 --- /dev/null +++ b/tests/ui/issues/issue-38987.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() { + let _ = -0x8000_0000_0000_0000_0000_0000_0000_0000i128; +} diff --git a/tests/ui/issues/issue-39089.rs b/tests/ui/issues/issue-39089.rs new file mode 100644 index 000000000..c7d4f8bd3 --- /dev/null +++ b/tests/ui/issues/issue-39089.rs @@ -0,0 +1,5 @@ +// check-pass +#![allow(dead_code)] +fn f Sized>() {} + +fn main() {} diff --git a/tests/ui/issues/issue-39175.rs b/tests/ui/issues/issue-39175.rs new file mode 100644 index 000000000..3866e0651 --- /dev/null +++ b/tests/ui/issues/issue-39175.rs @@ -0,0 +1,16 @@ +// This test ignores some platforms as the particular extension trait used +// to demonstrate the issue is only available on unix. This is fine as +// the fix to suggested paths is not platform-dependent and will apply on +// these platforms also. + +// ignore-windows +// ignore-emscripten +// ignore-sgx no processes + +use std::process::Command; +// use std::os::unix::process::CommandExt; + +fn main() { + Command::new("echo").arg("hello").exec(); +//~^ ERROR no method named `exec` +} diff --git a/tests/ui/issues/issue-39175.stderr b/tests/ui/issues/issue-39175.stderr new file mode 100644 index 000000000..afceae82e --- /dev/null +++ b/tests/ui/issues/issue-39175.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `exec` found for mutable reference `&mut Command` in the current scope + --> $DIR/issue-39175.rs:14:39 + | +LL | Command::new("echo").arg("hello").exec(); + | ^^^^ method not found in `&mut Command` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::os::unix::process::CommandExt; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-39211.rs b/tests/ui/issues/issue-39211.rs new file mode 100644 index 000000000..6f3834d51 --- /dev/null +++ b/tests/ui/issues/issue-39211.rs @@ -0,0 +1,13 @@ +trait VecN { + const DIM: usize; +} +trait Mat { + type Row: VecN; +} + +fn m() { + let a = [3; M::Row::DIM]; + //~^ ERROR constant expression depends on a generic parameter +} +fn main() { +} diff --git a/tests/ui/issues/issue-39211.stderr b/tests/ui/issues/issue-39211.stderr new file mode 100644 index 000000000..cd2a014bb --- /dev/null +++ b/tests/ui/issues/issue-39211.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-39211.rs:9:17 + | +LL | let a = [3; M::Row::DIM]; + | ^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-39292.rs b/tests/ui/issues/issue-39292.rs new file mode 100644 index 000000000..968cf0891 --- /dev/null +++ b/tests/ui/issues/issue-39292.rs @@ -0,0 +1,17 @@ +// run-pass +// Regression test for issue #39292. The object vtable was being +// incorrectly left with a null pointer. + +trait Foo { + fn print<'a>(&'a self) where T: 'a { println!("foo"); } +} + +impl<'a> Foo<&'a ()> for () { } + +trait Bar: for<'a> Foo<&'a ()> { } + +impl Bar for () {} + +fn main() { + (&() as &dyn Bar).print(); // Segfault +} diff --git a/tests/ui/issues/issue-39367.rs b/tests/ui/issues/issue-39367.rs new file mode 100644 index 000000000..e7beb8a03 --- /dev/null +++ b/tests/ui/issues/issue-39367.rs @@ -0,0 +1,42 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +use std::ops::Deref; + +struct ArenaSet::Target>(U, &'static V) + where V: 'static + ?Sized; + +static Z: [u8; 4] = [1,2,3,4]; + +fn arena() -> &'static ArenaSet> { + fn __static_ref_initialize() -> ArenaSet> { + ArenaSet(vec![], &Z) + } + unsafe { + use std::sync::Once; + fn require_sync(_: &T) { } + unsafe fn __stability() -> &'static ArenaSet> { + use std::mem::transmute; + static mut DATA: *const ArenaSet> = std::ptr::null_mut(); + + static mut ONCE: Once = Once::new(); + ONCE.call_once(|| { + DATA = transmute + ::>>, *const ArenaSet>> + (Box::new(__static_ref_initialize())); + }); + + &*DATA + } + let static_ref = __stability(); + require_sync(static_ref); + static_ref + } +} + +fn main() { + let &ArenaSet(ref u, v) = arena(); + assert!(u.is_empty()); + assert_eq!(v, Z); +} diff --git a/tests/ui/issues/issue-39467.rs b/tests/ui/issues/issue-39467.rs new file mode 100644 index 000000000..397751e4e --- /dev/null +++ b/tests/ui/issues/issue-39467.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] +macro_rules! expr { () => { () } } + +enum A {} + +impl A { + const A: () = expr!(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-39548.rs b/tests/ui/issues/issue-39548.rs new file mode 100644 index 000000000..304e37bf3 --- /dev/null +++ b/tests/ui/issues/issue-39548.rs @@ -0,0 +1,6 @@ +// run-pass +type Array = [(); ((1 < 2) == false) as usize]; + +fn main() { + let _: Array = []; +} diff --git a/tests/ui/issues/issue-39687.rs b/tests/ui/issues/issue-39687.rs new file mode 100644 index 000000000..cbb721fbb --- /dev/null +++ b/tests/ui/issues/issue-39687.rs @@ -0,0 +1,6 @@ +#![feature(fn_traits)] + +fn main() { + ::call; + //~^ ERROR associated type bindings are not allowed here [E0229] +} diff --git a/tests/ui/issues/issue-39687.stderr b/tests/ui/issues/issue-39687.stderr new file mode 100644 index 000000000..b1b3041ea --- /dev/null +++ b/tests/ui/issues/issue-39687.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-39687.rs:4:14 + | +LL | ::call; + | ^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-39709.rs b/tests/ui/issues/issue-39709.rs new file mode 100644 index 000000000..69ef2700e --- /dev/null +++ b/tests/ui/issues/issue-39709.rs @@ -0,0 +1,5 @@ +// run-pass +#![allow(unused_macros)] +fn main() { + println!("{}", { macro_rules! x { ($(t:tt)*) => {} } 33 }); +} diff --git a/tests/ui/issues/issue-3979-2.rs b/tests/ui/issues/issue-3979-2.rs new file mode 100644 index 000000000..4ec128a45 --- /dev/null +++ b/tests/ui/issues/issue-3979-2.rs @@ -0,0 +1,18 @@ +// check-pass +// pretty-expanded FIXME #23616 + +trait A { + fn a_method(&self); +} + +trait B: A { + fn b_method(&self); +} + +trait C: B { + fn c_method(&self) { + self.a_method(); + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-3979-generics.rs b/tests/ui/issues/issue-3979-generics.rs new file mode 100644 index 000000000..519de1cad --- /dev/null +++ b/tests/ui/issues/issue-3979-generics.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +use std::ops::Add; + +trait Positioned { + fn SetX(&mut self, _: S); + fn X(&self) -> S; +} + +trait Movable>: Positioned { + fn translate(&mut self, dx: S) { + let x = self.X() + dx; + self.SetX(x); + } +} + +struct Point { x: isize, y: isize } + +impl Positioned for Point { + fn SetX(&mut self, x: isize) { + self.x = x; + } + fn X(&self) -> isize { + self.x + } +} + +impl Movable for Point {} + +pub fn main() { + let mut p = Point{ x: 1, y: 2}; + p.translate(3); + assert_eq!(p.X(), 4); +} diff --git a/tests/ui/issues/issue-3979-xcrate.rs b/tests/ui/issues/issue-3979-xcrate.rs new file mode 100644 index 000000000..fcb1f55c3 --- /dev/null +++ b/tests/ui/issues/issue-3979-xcrate.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-3979-traits.rs + +extern crate issue_3979_traits; +use issue_3979_traits::{Positioned, Movable}; + +struct Point { x: isize, y: isize } + +impl Positioned for Point { + fn SetX(&mut self, x: isize) { + self.x = x; + } + fn X(&self) -> isize { + self.x + } +} + +impl Movable for Point {} + +pub fn main() { + let mut p = Point{ x: 1, y: 2}; + p.translate(3); + assert_eq!(p.X(), 4); +} diff --git a/tests/ui/issues/issue-3979.rs b/tests/ui/issues/issue-3979.rs new file mode 100644 index 000000000..72949d8c7 --- /dev/null +++ b/tests/ui/issues/issue-3979.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +trait Positioned { + fn SetX(&mut self, _: isize); + fn X(&self) -> isize; +} + +trait Movable: Positioned { + fn translate(&mut self, dx: isize) { + let x = self.X(); + self.SetX(x + dx); + } +} + +struct Point { x: isize, y: isize } + +impl Positioned for Point { + fn SetX(&mut self, x: isize) { + self.x = x; + } + fn X(&self) -> isize { + self.x + } +} + +impl Movable for Point {} + +pub fn main() { + let mut p = Point{ x: 1, y: 2}; + p.translate(3); + assert_eq!(p.X(), 4); +} diff --git a/tests/ui/issues/issue-39808.rs b/tests/ui/issues/issue-39808.rs new file mode 100644 index 000000000..a47013673 --- /dev/null +++ b/tests/ui/issues/issue-39808.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unreachable_code)] + +// Regression test for #39808. The type parameter of `Owned` was +// considered to be "unconstrained" because the type resulting from +// `format!` (`String`) was not being propagated upward, owing to the +// fact that the expression diverges. + +use std::borrow::Cow; + +fn main() { + let _ = if false { + Cow::Owned(format!("{:?}", panic!())) + } else { + Cow::Borrowed("") + }; +} diff --git a/tests/ui/issues/issue-39827.rs b/tests/ui/issues/issue-39827.rs new file mode 100644 index 000000000..782c668c8 --- /dev/null +++ b/tests/ui/issues/issue-39827.rs @@ -0,0 +1,34 @@ +// run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::{ volatile_copy_memory, volatile_store, volatile_load, + volatile_copy_nonoverlapping_memory, + volatile_set_memory }; + +// +// This test ensures that volatile intrinsics can be specialised with +// zero-sized types and, in case of copy/set functions, can accept +// number of elements equal to zero. +// +fn main () { + let mut dst_pair = (1, 2); + let src_pair = (3, 4); + let mut dst_empty = (); + let src_empty = (); + + const COUNT_0: usize = 0; + const COUNT_100: usize = 100; + + unsafe { + volatile_copy_memory(&mut dst_pair, &dst_pair, COUNT_0); + volatile_copy_nonoverlapping_memory(&mut dst_pair, &src_pair, 0); + volatile_copy_memory(&mut dst_empty, &dst_empty, 100); + volatile_copy_nonoverlapping_memory(&mut dst_empty, &src_empty, + COUNT_100); + volatile_set_memory(&mut dst_empty, 0, COUNT_100); + volatile_set_memory(&mut dst_pair, 0, COUNT_0); + volatile_store(&mut dst_empty, ()); + volatile_store(&mut dst_empty, src_empty); + volatile_load(&src_empty); + } +} diff --git a/tests/ui/issues/issue-39848.rs b/tests/ui/issues/issue-39848.rs new file mode 100644 index 000000000..1964d7399 --- /dev/null +++ b/tests/ui/issues/issue-39848.rs @@ -0,0 +1,9 @@ +macro_rules! get_opt { + ($tgt:expr, $field:ident) => { + if $tgt.has_$field() {} //~ ERROR expected `{`, found `foo` + } +} + +fn main() { + get_opt!(bar, foo); +} diff --git a/tests/ui/issues/issue-39848.stderr b/tests/ui/issues/issue-39848.stderr new file mode 100644 index 000000000..387ef0776 --- /dev/null +++ b/tests/ui/issues/issue-39848.stderr @@ -0,0 +1,25 @@ +error: expected `{`, found `foo` + --> $DIR/issue-39848.rs:3:21 + | +LL | if $tgt.has_$field() {} + | ^^^^^^ expected `{` +... +LL | get_opt!(bar, foo); + | ------------------ in this macro invocation + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-39848.rs:3:12 + | +LL | if $tgt.has_$field() {} + | ^^^^^^^^^ +... +LL | get_opt!(bar, foo); + | ------------------ in this macro invocation + = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) +help: try placing this code inside a block + | +LL | if $tgt.has_{ $field() } {} + | + + + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-3991.rs b/tests/ui/issues/issue-3991.rs new file mode 100644 index 000000000..4851eddf5 --- /dev/null +++ b/tests/ui/issues/issue-3991.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +struct HasNested { + nest: Vec > , +} + +impl HasNested { + fn method_push_local(&mut self) { + self.nest[0].push(0); + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-3993.rs b/tests/ui/issues/issue-3993.rs new file mode 100644 index 000000000..9dea54ea7 --- /dev/null +++ b/tests/ui/issues/issue-3993.rs @@ -0,0 +1,10 @@ +use zoo::fly; //~ ERROR: function `fly` is private + +mod zoo { + fn fly() {} +} + + +fn main() { + fly(); +} diff --git a/tests/ui/issues/issue-3993.stderr b/tests/ui/issues/issue-3993.stderr new file mode 100644 index 000000000..deecf7a9d --- /dev/null +++ b/tests/ui/issues/issue-3993.stderr @@ -0,0 +1,15 @@ +error[E0603]: function `fly` is private + --> $DIR/issue-3993.rs:1:10 + | +LL | use zoo::fly; + | ^^^ private function + | +note: the function `fly` is defined here + --> $DIR/issue-3993.rs:4:5 + | +LL | fn fly() {} + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/issues/issue-39970.rs b/tests/ui/issues/issue-39970.rs new file mode 100644 index 000000000..f51e3b522 --- /dev/null +++ b/tests/ui/issues/issue-39970.rs @@ -0,0 +1,21 @@ +trait Array<'a> { + type Element: 'a; +} + +trait Visit { + fn visit() {} +} + +impl<'a> Array<'a> for () { + type Element = &'a (); +} + +impl Visit for () where + //(): for<'a> Array<'a, Element=&'a ()>, // No ICE + (): for<'a> Array<'a, Element=()>, // ICE +{} + +fn main() { + <() as Visit>::visit(); + //~^ ERROR type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` +} diff --git a/tests/ui/issues/issue-39970.stderr b/tests/ui/issues/issue-39970.stderr new file mode 100644 index 000000000..0cabdf7f2 --- /dev/null +++ b/tests/ui/issues/issue-39970.stderr @@ -0,0 +1,23 @@ +error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` + --> $DIR/issue-39970.rs:19:5 + | +LL | <() as Visit>::visit(); + | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()` + | +note: expected this to be `()` + --> $DIR/issue-39970.rs:10:20 + | +LL | type Element = &'a (); + | ^^^^^^ +note: required for `()` to implement `Visit` + --> $DIR/issue-39970.rs:13:6 + | +LL | impl Visit for () where + | ^^^^^ ^^ +LL | //(): for<'a> Array<'a, Element=&'a ()>, // No ICE +LL | (): for<'a> Array<'a, Element=()>, // ICE + | ---------- unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-39984.rs b/tests/ui/issues/issue-39984.rs new file mode 100644 index 000000000..1c9ae26ca --- /dev/null +++ b/tests/ui/issues/issue-39984.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] +#![allow(unreachable_code)] +// Regression test for issue #39984. +// +// The key here is that the error type of the `Ok` call ought to be +// constrained to `String`, even though it is dead-code. + +fn main() {} + +fn t() -> Result<(), String> { + return Err("".into()); + Ok(()) +} diff --git a/tests/ui/issues/issue-40000.rs b/tests/ui/issues/issue-40000.rs new file mode 100644 index 000000000..a6e05e7ba --- /dev/null +++ b/tests/ui/issues/issue-40000.rs @@ -0,0 +1,9 @@ +fn main() { + let bar: fn(&mut u32) = |_| {}; + + fn foo(x: Box) {} + let bar = Box::new(|x: &i32| {}) as Box; + foo(bar); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/issues/issue-40000.stderr b/tests/ui/issues/issue-40000.stderr new file mode 100644 index 000000000..c41fbb9d2 --- /dev/null +++ b/tests/ui/issues/issue-40000.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-40000.rs:6:9 + | +LL | foo(bar); + | ^^^ one type is more general than the other + | + = note: expected trait object `dyn for<'a> Fn(&'a i32)` + found trait object `dyn Fn(&i32)` + +error[E0308]: mismatched types + --> $DIR/issue-40000.rs:6:9 + | +LL | foo(bar); + | ^^^ one type is more general than the other + | + = note: expected trait object `dyn for<'a> Fn(&'a i32)` + found trait object `dyn Fn(&i32)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-40003.rs b/tests/ui/issues/issue-40003.rs new file mode 100644 index 000000000..5e61361f9 --- /dev/null +++ b/tests/ui/issues/issue-40003.rs @@ -0,0 +1,178 @@ +// run-pass +#![allow(unused_must_use)] +fn main() { + if false { test(); } +} + +fn test() { + let rx = Err::, u32>(1).into_future(); + + rx.map(|l: Vec| stream::iter(l.into_iter().map(|i| Ok(i)))) + .flatten_stream() + .chunks(50) + .buffer_unordered(5); +} + +use future::{Future, IntoFuture}; +mod future { + use std::result; + + use {stream, Stream}; + + pub trait Future { + type Item; + type Error; + + fn map(self, _: F) -> Map + where F: FnOnce(Self::Item) -> U, + Self: Sized, + { + panic!() + } + + fn flatten_stream(self) -> FlattenStream + where ::Item: stream::Stream, + Self: Sized + { + panic!() + } + } + + pub trait IntoFuture { + type Future: Future; + type Item; + type Error; + fn into_future(self) -> Self::Future; + } + + impl IntoFuture for F { + type Future = F; + type Item = F::Item; + type Error = F::Error; + + fn into_future(self) -> F { + panic!() + } + } + + impl IntoFuture for result::Result { + type Future = FutureResult; + type Item = T; + type Error = E; + + fn into_future(self) -> FutureResult { + panic!() + } + } + + pub struct Map { + _a: (A, F), + } + + impl Future for Map + where A: Future, + F: FnOnce(A::Item) -> U, + { + type Item = U; + type Error = A::Error; + } + + pub struct FlattenStream { + _f: F, + } + + impl Stream for FlattenStream + where F: Future, + ::Item: Stream, + { + type Item = ::Item; + type Error = ::Error; + } + + pub struct FutureResult { + _inner: (T, E), + } + + impl Future for FutureResult { + type Item = T; + type Error = E; + } +} + +mod stream { + use IntoFuture; + + pub trait Stream { + type Item; + type Error; + + fn buffer_unordered(self, amt: usize) -> BufferUnordered + where Self::Item: IntoFuture::Error>, + Self: Sized + { + new(self, amt) + } + + fn chunks(self, _capacity: usize) -> Chunks + where Self: Sized + { + panic!() + } + } + + pub struct IterStream { + _iter: I, + } + + pub fn iter(_: J) -> IterStream + where J: IntoIterator>, + { + panic!() + } + + impl Stream for IterStream + where I: Iterator>, + { + type Item = T; + type Error = E; + } + + pub struct Chunks { + _stream: S + } + + impl Stream for Chunks + where S: Stream + { + type Item = Result::Item>, u32>; + type Error = ::Error; + } + + pub struct BufferUnordered { + _stream: S, + } + + enum Slot { + Next(#[allow(unused_tuple_struct_fields)] usize), + _Data { _a: T }, + } + + fn new(_s: S, _amt: usize) -> BufferUnordered + where S: Stream, + S::Item: IntoFuture::Error>, + { + (0..0).map(|_| { + Slot::Next::<::Future>(1) + }).collect::>(); + panic!() + } + + impl Stream for BufferUnordered + where S: Stream, + S::Item: IntoFuture::Error>, + { + type Item = ::Item; + type Error = ::Error; + } +} +use stream::Stream; diff --git a/tests/ui/issues/issue-40085.rs b/tests/ui/issues/issue-40085.rs new file mode 100644 index 000000000..132044cfd --- /dev/null +++ b/tests/ui/issues/issue-40085.rs @@ -0,0 +1,13 @@ +// run-pass +use std::ops::Index; +fn bar() {} +static UNIT: () = (); +struct S; +impl Index for S { + type Output = (); + fn index(&self, _: fn()) -> &() { &UNIT } +} +fn main() { + S.index(bar); + S[bar]; +} diff --git a/tests/ui/issues/issue-40136.rs b/tests/ui/issues/issue-40136.rs new file mode 100644 index 000000000..29d3fc2d5 --- /dev/null +++ b/tests/ui/issues/issue-40136.rs @@ -0,0 +1,15 @@ +// check-pass +#![allow(dead_code)] + +macro_rules! m { () => { 0 } } + +trait T { + const C: i32 = m!(); +} + +struct S; +impl S { + const C: i32 = m!(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-40235.rs b/tests/ui/issues/issue-40235.rs new file mode 100644 index 000000000..0f799c350 --- /dev/null +++ b/tests/ui/issues/issue-40235.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_variables)] +fn foo() {} + +fn main() { + while let Some(foo) = Some(1) { break } + foo(); +} diff --git a/tests/ui/issues/issue-4025.rs b/tests/ui/issues/issue-4025.rs new file mode 100644 index 000000000..dc534c64c --- /dev/null +++ b/tests/ui/issues/issue-4025.rs @@ -0,0 +1,25 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_mut)] +/* +# if b { x } else { y } requires identical types for x and y +*/ + +fn print1(b: bool, s1: &str, s2: &str) { + println!("{}", if b { s1 } else { s2 }); +} +fn print2<'a, 'b>(b: bool, s1: &'a str, s2: &'b str) { + println!("{}", if b { s1 } else { s2 }); +} +fn print3(b: bool, s1: &str, s2: &str) { + let mut s: &str; + if b { s = s1; } else { s = s2; } + println!("{}", s); +} +fn print4<'a, 'b>(b: bool, s1: &'a str, s2: &'b str) { + let mut s: &str; + if b { s = s1; } else { s = s2; } + println!("{}", s); +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-40288-2.rs b/tests/ui/issues/issue-40288-2.rs new file mode 100644 index 000000000..032a2e65f --- /dev/null +++ b/tests/ui/issues/issue-40288-2.rs @@ -0,0 +1,31 @@ +fn prove_static(_: &'static T) {} + +fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { + let mut out = [x]; + { + let slice: &mut [_] = &mut out; + slice[0] = y; + } + out[0] + //~^ ERROR explicit lifetime required in the type of `y` [E0621] +} + +struct Struct { + head: T, + _tail: U +} + +fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { + let mut out = Struct { head: x, _tail: [()] }; + { + let dst: &mut Struct<_, [()]> = &mut out; + dst.head = y; + } + out.head + //~^ ERROR explicit lifetime required in the type of `y` [E0621] +} + +fn main() { + prove_static(lifetime_transmute_slice("", &String::from("foo"))); + prove_static(lifetime_transmute_struct("", &String::from("bar"))); +} diff --git a/tests/ui/issues/issue-40288-2.stderr b/tests/ui/issues/issue-40288-2.stderr new file mode 100644 index 000000000..2c64856b0 --- /dev/null +++ b/tests/ui/issues/issue-40288-2.stderr @@ -0,0 +1,21 @@ +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/issue-40288-2.rs:9:5 + | +LL | fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { + | -- help: add explicit lifetime `'a` to the type of `y`: `&'a T` +... +LL | out[0] + | ^^^^^^ lifetime `'a` required + +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/issue-40288-2.rs:24:5 + | +LL | fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T { + | -- help: add explicit lifetime `'a` to the type of `y`: `&'a T` +... +LL | out.head + | ^^^^^^^^ lifetime `'a` required + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/issues/issue-40288.rs b/tests/ui/issues/issue-40288.rs new file mode 100644 index 000000000..60204c117 --- /dev/null +++ b/tests/ui/issues/issue-40288.rs @@ -0,0 +1,20 @@ +fn save_ref<'a>(refr: &'a i32, to: &mut [&'a i32]) { + for val in &mut *to { + *val = refr; + } +} + +fn main() { + let ref init = 0i32; + let ref mut refr = 1i32; + + let mut out = [init]; + + save_ref(&*refr, &mut out); + + // This shouldn't be allowed as `refr` is borrowed + *refr = 3; //~ ERROR cannot assign to `*refr` because it is borrowed + + // Prints 3?! + println!("{:?}", out[0]); +} diff --git a/tests/ui/issues/issue-40288.stderr b/tests/ui/issues/issue-40288.stderr new file mode 100644 index 000000000..fb4ecab36 --- /dev/null +++ b/tests/ui/issues/issue-40288.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `*refr` because it is borrowed + --> $DIR/issue-40288.rs:16:5 + | +LL | save_ref(&*refr, &mut out); + | ------ borrow of `*refr` occurs here +... +LL | *refr = 3; + | ^^^^^^^^^ assignment to borrowed `*refr` occurs here +... +LL | println!("{:?}", out[0]); + | ------ borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/issues/issue-40350.rs b/tests/ui/issues/issue-40350.rs new file mode 100644 index 000000000..a39a8519a --- /dev/null +++ b/tests/ui/issues/issue-40350.rs @@ -0,0 +1,10 @@ +// check-pass + +enum E { + A = { + enum F { B } + 0 + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.rs b/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.rs new file mode 100644 index 000000000..254956ae3 --- /dev/null +++ b/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.rs @@ -0,0 +1,10 @@ +// Check that we do not suggest `ref f` here in the `main()` function. +struct Foo { + pub v: Vec, +} + +fn main() { + let mut f = Foo { v: Vec::new() }; + f.v.push("hello".to_string()); + let e = f.v[0]; //~ ERROR cannot move out of index +} diff --git a/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr b/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr new file mode 100644 index 000000000..e15eed656 --- /dev/null +++ b/tests/ui/issues/issue-40402-ref-hints/issue-40402-1.stderr @@ -0,0 +1,14 @@ +error[E0507]: cannot move out of index of `Vec` + --> $DIR/issue-40402-1.rs:9:13 + | +LL | let e = f.v[0]; + | ^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let e = &f.v[0]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.rs b/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.rs new file mode 100644 index 000000000..1fb6e31e9 --- /dev/null +++ b/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.rs @@ -0,0 +1,6 @@ +// Check that we do suggest `(ref a, ref b)` here, since `a` and `b` +// are nested within a pattern +fn main() { + let x = vec![(String::new(), String::new())]; + let (a, b) = x[0]; //~ ERROR cannot move out of index +} diff --git a/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr b/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr new file mode 100644 index 000000000..1bc554efb --- /dev/null +++ b/tests/ui/issues/issue-40402-ref-hints/issue-40402-2.stderr @@ -0,0 +1,18 @@ +error[E0507]: cannot move out of index of `Vec<(String, String)>` + --> $DIR/issue-40402-2.rs:5:18 + | +LL | let (a, b) = x[0]; + | - - ^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing here + | +LL | let (a, b) = &x[0]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-40408.rs b/tests/ui/issues/issue-40408.rs new file mode 100644 index 000000000..81acc41cb --- /dev/null +++ b/tests/ui/issues/issue-40408.rs @@ -0,0 +1,7 @@ +// run-pass +fn main() { + println!("{}", 0E+10); + println!("{}", 0e+10); + println!("{}", 00e+10); + println!("{}", 00E+10); +} diff --git a/tests/ui/issues/issue-40510-1.migrate.stderr b/tests/ui/issues/issue-40510-1.migrate.stderr new file mode 100644 index 000000000..776a724d3 --- /dev/null +++ b/tests/ui/issues/issue-40510-1.migrate.stderr @@ -0,0 +1,13 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-40510-1.rs:11:9 + | +LL | || { + | - inferred to be a `FnMut` closure +LL | &mut x + | ^^^^^^ returns a reference to a captured variable which escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-40510-1.rs b/tests/ui/issues/issue-40510-1.rs new file mode 100644 index 000000000..ca53dcd9b --- /dev/null +++ b/tests/ui/issues/issue-40510-1.rs @@ -0,0 +1,12 @@ +#![allow(unused)] + +fn f() { + let mut x: Box<()> = Box::new(()); + + || { + &mut x + }; + //~^^ ERROR captured variable cannot escape `FnMut` closure body +} + +fn main() {} diff --git a/tests/ui/issues/issue-40510-1.stderr b/tests/ui/issues/issue-40510-1.stderr new file mode 100644 index 000000000..e88f31ea1 --- /dev/null +++ b/tests/ui/issues/issue-40510-1.stderr @@ -0,0 +1,19 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-40510-1.rs:7:9 + | +LL | let mut x: Box<()> = Box::new(()); + | ----- variable defined here +LL | +LL | || { + | - inferred to be a `FnMut` closure +LL | &mut x + | ^^^^^- + | | | + | | variable captured here + | returns a reference to a captured variable which escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-40510-2.rs b/tests/ui/issues/issue-40510-2.rs new file mode 100644 index 000000000..3ae84be05 --- /dev/null +++ b/tests/ui/issues/issue-40510-2.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(unused)] + +fn f() { + let x: Box<()> = Box::new(()); + + || { + &x + }; +} + + +fn main() {} diff --git a/tests/ui/issues/issue-40510-3.migrate.stderr b/tests/ui/issues/issue-40510-3.migrate.stderr new file mode 100644 index 000000000..a49475a85 --- /dev/null +++ b/tests/ui/issues/issue-40510-3.migrate.stderr @@ -0,0 +1,15 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-40510-3.rs:11:9 + | +LL | || { + | - inferred to be a `FnMut` closure +LL | / || { +LL | | x.push(()) +LL | | } + | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-40510-3.rs b/tests/ui/issues/issue-40510-3.rs new file mode 100644 index 000000000..181263adc --- /dev/null +++ b/tests/ui/issues/issue-40510-3.rs @@ -0,0 +1,14 @@ +#![allow(unused)] + +fn f() { + let mut x: Vec<()> = Vec::new(); + + || { + || { + x.push(()) + } + //~^^^ ERROR captured variable cannot escape `FnMut` closure body + }; +} + +fn main() {} diff --git a/tests/ui/issues/issue-40510-3.stderr b/tests/ui/issues/issue-40510-3.stderr new file mode 100644 index 000000000..eb077415e --- /dev/null +++ b/tests/ui/issues/issue-40510-3.stderr @@ -0,0 +1,23 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-40510-3.rs:7:9 + | +LL | let mut x: Vec<()> = Vec::new(); + | ----- variable defined here +LL | +LL | || { + | - inferred to be a `FnMut` closure +LL | / || { +LL | | x.push(()) + | | - variable captured here +LL | | } + | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape +help: consider adding 'move' keyword before the nested closure + | +LL | move || { + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-40510-4.rs b/tests/ui/issues/issue-40510-4.rs new file mode 100644 index 000000000..48bb8d36f --- /dev/null +++ b/tests/ui/issues/issue-40510-4.rs @@ -0,0 +1,15 @@ +// check-pass +#![allow(unused)] + +fn f() { + let x: Vec<()> = Vec::new(); + + || { + || { + x.len() + } + }; +} + + +fn main() {} diff --git a/tests/ui/issues/issue-40610.rs b/tests/ui/issues/issue-40610.rs new file mode 100644 index 000000000..c01233605 --- /dev/null +++ b/tests/ui/issues/issue-40610.rs @@ -0,0 +1,6 @@ +fn f(_: &[f32]) {} + +fn main() { + () + f(&[1.0]); + //~^ ERROR cannot add `()` to `()` +} diff --git a/tests/ui/issues/issue-40610.stderr b/tests/ui/issues/issue-40610.stderr new file mode 100644 index 000000000..b4e302dff --- /dev/null +++ b/tests/ui/issues/issue-40610.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot add `()` to `()` + --> $DIR/issue-40610.rs:4:8 + | +LL | () + f(&[1.0]); + | -- ^ --------- () + | | + | () + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-40749.rs b/tests/ui/issues/issue-40749.rs new file mode 100644 index 000000000..0a847853b --- /dev/null +++ b/tests/ui/issues/issue-40749.rs @@ -0,0 +1,6 @@ +fn main() { + [0; ..10]; + //~^ ERROR mismatched types + //~| expected type `usize` + //~| found struct `RangeTo<{integer}>` +} diff --git a/tests/ui/issues/issue-40749.stderr b/tests/ui/issues/issue-40749.stderr new file mode 100644 index 000000000..fa239f744 --- /dev/null +++ b/tests/ui/issues/issue-40749.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-40749.rs:2:9 + | +LL | [0; ..10]; + | ^^^^ expected `usize`, found struct `RangeTo` + | + = note: expected type `usize` + found struct `RangeTo<{integer}>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-40782.fixed b/tests/ui/issues/issue-40782.fixed new file mode 100644 index 000000000..305a9c329 --- /dev/null +++ b/tests/ui/issues/issue-40782.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + for _i in 0..2 { //~ ERROR missing `in` + } + for _i in 0..2 { //~ ERROR missing `in` + } +} diff --git a/tests/ui/issues/issue-40782.rs b/tests/ui/issues/issue-40782.rs new file mode 100644 index 000000000..43460ec15 --- /dev/null +++ b/tests/ui/issues/issue-40782.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + for _i 0..2 { //~ ERROR missing `in` + } + for _i of 0..2 { //~ ERROR missing `in` + } +} diff --git a/tests/ui/issues/issue-40782.stderr b/tests/ui/issues/issue-40782.stderr new file mode 100644 index 000000000..81f419bf6 --- /dev/null +++ b/tests/ui/issues/issue-40782.stderr @@ -0,0 +1,14 @@ +error: missing `in` in `for` loop + --> $DIR/issue-40782.rs:4:11 + | +LL | for _i 0..2 { + | ^ help: try adding `in` here + +error: missing `in` in `for` loop + --> $DIR/issue-40782.rs:6:12 + | +LL | for _i of 0..2 { + | ^^ help: try using `in` here instead + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-40827.rs b/tests/ui/issues/issue-40827.rs new file mode 100644 index 000000000..6e42c5061 --- /dev/null +++ b/tests/ui/issues/issue-40827.rs @@ -0,0 +1,17 @@ +use std::rc::Rc; +use std::sync::Arc; + +struct Foo(Arc); + +enum Bar { + A(Rc), + B(Option), +} + +fn f(_: T) {} + +fn main() { + f(Foo(Arc::new(Bar::B(None)))); + //~^ ERROR E0277 + //~| ERROR E0277 +} diff --git a/tests/ui/issues/issue-40827.stderr b/tests/ui/issues/issue-40827.stderr new file mode 100644 index 000000000..7f5c578ae --- /dev/null +++ b/tests/ui/issues/issue-40827.stderr @@ -0,0 +1,55 @@ +error[E0277]: `Rc` cannot be shared between threads safely + --> $DIR/issue-40827.rs:14:7 + | +LL | f(Foo(Arc::new(Bar::B(None)))); + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Bar`, the trait `Sync` is not implemented for `Rc` +note: required because it appears within the type `Bar` + --> $DIR/issue-40827.rs:6:6 + | +LL | enum Bar { + | ^^^ + = note: required for `Arc` to implement `Send` +note: required because it appears within the type `Foo` + --> $DIR/issue-40827.rs:4:8 + | +LL | struct Foo(Arc); + | ^^^ +note: required by a bound in `f` + --> $DIR/issue-40827.rs:11:9 + | +LL | fn f(_: T) {} + | ^^^^ required by this bound in `f` + +error[E0277]: `Rc` cannot be sent between threads safely + --> $DIR/issue-40827.rs:14:7 + | +LL | f(Foo(Arc::new(Bar::B(None)))); + | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Bar`, the trait `Send` is not implemented for `Rc` +note: required because it appears within the type `Bar` + --> $DIR/issue-40827.rs:6:6 + | +LL | enum Bar { + | ^^^ + = note: required for `Arc` to implement `Send` +note: required because it appears within the type `Foo` + --> $DIR/issue-40827.rs:4:8 + | +LL | struct Foo(Arc); + | ^^^ +note: required by a bound in `f` + --> $DIR/issue-40827.rs:11:9 + | +LL | fn f(_: T) {} + | ^^^^ required by this bound in `f` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-40845.rs b/tests/ui/issues/issue-40845.rs new file mode 100644 index 000000000..a4ede6adf --- /dev/null +++ b/tests/ui/issues/issue-40845.rs @@ -0,0 +1,6 @@ +trait T { m!(); } //~ ERROR cannot find macro `m` in this scope + +struct S; +impl S { m!(); } //~ ERROR cannot find macro `m` in this scope + +fn main() {} diff --git a/tests/ui/issues/issue-40845.stderr b/tests/ui/issues/issue-40845.stderr new file mode 100644 index 000000000..66bf05320 --- /dev/null +++ b/tests/ui/issues/issue-40845.stderr @@ -0,0 +1,14 @@ +error: cannot find macro `m` in this scope + --> $DIR/issue-40845.rs:1:11 + | +LL | trait T { m!(); } + | ^ + +error: cannot find macro `m` in this scope + --> $DIR/issue-40845.rs:4:10 + | +LL | impl S { m!(); } + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-40861.rs b/tests/ui/issues/issue-40861.rs new file mode 100644 index 000000000..d8a8384a5 --- /dev/null +++ b/tests/ui/issues/issue-40861.rs @@ -0,0 +1,6 @@ +fn f(_: &[f32]) {} + +fn main() { + ()[f(&[1.0])]; + //~^ ERROR cannot index into a value of type `()` +} diff --git a/tests/ui/issues/issue-40861.stderr b/tests/ui/issues/issue-40861.stderr new file mode 100644 index 000000000..84e38b9bb --- /dev/null +++ b/tests/ui/issues/issue-40861.stderr @@ -0,0 +1,11 @@ +error[E0608]: cannot index into a value of type `()` + --> $DIR/issue-40861.rs:4:5 + | +LL | ()[f(&[1.0])]; + | ^^^^^^^^^^^^^ + | + = help: to access tuple elements, use tuple indexing syntax (e.g., `tuple.0`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/issues/issue-40883.rs b/tests/ui/issues/issue-40883.rs new file mode 100644 index 000000000..8a4aef46d --- /dev/null +++ b/tests/ui/issues/issue-40883.rs @@ -0,0 +1,94 @@ +// run-pass +#![allow(dead_code)] +// check that we don't have linear stack usage with multiple calls to `push` + +#![feature(test)] + +extern crate test; +use std::mem; + +fn meal() -> Big { + if test::black_box(false) { + panic!() + } + Big { drop_me: [ + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, + ]} +} + +pub struct Big { + drop_me: [Option>; 48], +} + +#[inline] +fn push(out: &mut Vec) { + out.push(meal()); +} + +#[inline(never)] +pub fn supersize_me(out: &mut Vec) { + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); // 16 calls to `push` + + verify_stack_usage(out); + + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); + push(out); // 16 calls to `push` +} + +#[inline(never)] +fn verify_stack_usage(before_ptr: *mut Vec) { + // To check stack usage, create locals before and after + // and check the difference in addresses between them. + let mut stack_var: Vec = vec![]; + test::black_box(&mut stack_var); + let stack_usage = isize::abs( + (&mut stack_var as *mut _ as isize) - + (before_ptr as isize)) as usize; + // Give space for 2 copies of `Big` + 272 "misc" bytes + // (value observed on x86_64-pc-windows-gnu). + if stack_usage > mem::size_of::() * 2 + 272 { + panic!("used {} bytes of stack, but `struct Big` is only {} bytes", + stack_usage, mem::size_of::()); + } + +} + +pub fn main() { + let mut v = vec![]; + test::black_box(&mut v); + supersize_me(&mut v); +} diff --git a/tests/ui/issues/issue-40951.rs b/tests/ui/issues/issue-40951.rs new file mode 100644 index 000000000..49171eba6 --- /dev/null +++ b/tests/ui/issues/issue-40951.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(unused_variables)] +// Regression test for #40951. + +const FOO: [&'static str; 1] = ["foo"]; + +fn find(t: &[T], element: &T) { } + +fn main() { + let x = format!("hi"); + find(&FOO, &&*x); +} diff --git a/tests/ui/issues/issue-41053.rs b/tests/ui/issues/issue-41053.rs new file mode 100644 index 000000000..967edfd44 --- /dev/null +++ b/tests/ui/issues/issue-41053.rs @@ -0,0 +1,21 @@ +// run-pass +// aux-build:issue-41053.rs + +pub trait Trait { fn foo(&self) {} } + +pub struct Foo; + +impl Iterator for Foo { + type Item = Box; + fn next(&mut self) -> Option> { + extern crate issue_41053; + impl ::Trait for issue_41053::Test { + fn foo(&self) {} + } + Some(Box::new(issue_41053::Test)) + } +} + +fn main() { + Foo.next().unwrap().foo(); +} diff --git a/tests/ui/issues/issue-41139.rs b/tests/ui/issues/issue-41139.rs new file mode 100644 index 000000000..94c53216f --- /dev/null +++ b/tests/ui/issues/issue-41139.rs @@ -0,0 +1,12 @@ +trait Trait {} + +fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { + panic!("") +} + +fn main() { + // This isn't great. The issue here is that `dyn Trait` is not sized, so + // `dyn Fn() -> dyn Trait` is not well-formed. + let t: &dyn Trait = &get_function()(); + //~^ ERROR expected function, found `&dyn Fn() -> (dyn Trait + 'static)` +} diff --git a/tests/ui/issues/issue-41139.stderr b/tests/ui/issues/issue-41139.stderr new file mode 100644 index 000000000..97492e6e0 --- /dev/null +++ b/tests/ui/issues/issue-41139.stderr @@ -0,0 +1,12 @@ +error[E0618]: expected function, found `&dyn Fn() -> (dyn Trait + 'static)` + --> $DIR/issue-41139.rs:10:26 + | +LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { + | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)` +... +LL | let t: &dyn Trait = &get_function()(); + | ^^^^^^^^^^^^^^ this trait object returns an unsized value `(dyn Trait + 'static)`, so it cannot be called + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-41213.rs b/tests/ui/issues/issue-41213.rs new file mode 100644 index 000000000..5c91bf711 --- /dev/null +++ b/tests/ui/issues/issue-41213.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +enum A { + A1, + A2, + A3, +} + +enum B { + B1(String, String), + B2(String, String), +} + +fn main() { + let a = A::A1; + loop { + let _ctor = match a { + A::A3 => break, + A::A1 => B::B1, + A::A2 => B::B2, + }; + break; + } +} diff --git a/tests/ui/issues/issue-41229-ref-str.rs b/tests/ui/issues/issue-41229-ref-str.rs new file mode 100644 index 000000000..fe5e6cd6e --- /dev/null +++ b/tests/ui/issues/issue-41229-ref-str.rs @@ -0,0 +1,4 @@ +pub fn example(ref s: str) {} +//~^ ERROR the size for values of type + +fn main() {} diff --git a/tests/ui/issues/issue-41229-ref-str.stderr b/tests/ui/issues/issue-41229-ref-str.stderr new file mode 100644 index 000000000..31fdf3b72 --- /dev/null +++ b/tests/ui/issues/issue-41229-ref-str.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-41229-ref-str.rs:1:16 + | +LL | pub fn example(ref s: str) {} + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | pub fn example(ref s: &str) {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-41272.rs b/tests/ui/issues/issue-41272.rs new file mode 100644 index 000000000..1f4da46f8 --- /dev/null +++ b/tests/ui/issues/issue-41272.rs @@ -0,0 +1,21 @@ +// check-pass +#![allow(dead_code)] +struct Foo; + +impl Foo { + fn bar(&mut self) -> bool { true } +} + +fn error(foo: &mut Foo) { + if let Some(_) = Some(true) { + } else if foo.bar() {} +} + +fn ok(foo: &mut Foo) { + if let Some(_) = Some(true) { + } else { + if foo.bar() {} + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-41298.rs b/tests/ui/issues/issue-41298.rs new file mode 100644 index 000000000..a1b4de39b --- /dev/null +++ b/tests/ui/issues/issue-41298.rs @@ -0,0 +1,8 @@ +// check-pass +#![allow(dead_code)] +struct Function { t: T, f: F } + +impl Function R> { fn foo() { } } +impl Function R> { fn bar() { } } + +fn main() { } diff --git a/tests/ui/issues/issue-41394-rpass.rs b/tests/ui/issues/issue-41394-rpass.rs new file mode 100644 index 000000000..37c652523 --- /dev/null +++ b/tests/ui/issues/issue-41394-rpass.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-41394.rs + +extern crate issue_41394 as lib; + +fn main() { + assert_eq!(lib::foo() as u32, 42); +} diff --git a/tests/ui/issues/issue-41394.rs b/tests/ui/issues/issue-41394.rs new file mode 100644 index 000000000..07cad8796 --- /dev/null +++ b/tests/ui/issues/issue-41394.rs @@ -0,0 +1,11 @@ +enum Foo { + A = "" + 1 + //~^ ERROR cannot add `{integer}` to `&str` +} + +enum Bar { + A = Foo::A as isize + //~^ const +} + +fn main() {} diff --git a/tests/ui/issues/issue-41394.stderr b/tests/ui/issues/issue-41394.stderr new file mode 100644 index 000000000..1b5c64628 --- /dev/null +++ b/tests/ui/issues/issue-41394.stderr @@ -0,0 +1,17 @@ +error[E0369]: cannot add `{integer}` to `&str` + --> $DIR/issue-41394.rs:2:12 + | +LL | A = "" + 1 + | -- ^ - {integer} + | | + | &str + +note: erroneous constant used + --> $DIR/issue-41394.rs:7:9 + | +LL | A = Foo::A as isize + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-41479.rs b/tests/ui/issues/issue-41479.rs new file mode 100644 index 000000000..6daaf440e --- /dev/null +++ b/tests/ui/issues/issue-41479.rs @@ -0,0 +1,9 @@ +// run-pass +fn split(pair: (A, B)) { + let _a = pair.0; + let _b = pair.1; +} + +fn main() { + split(((), ((), ()))); +} diff --git a/tests/ui/issues/issue-41498.rs b/tests/ui/issues/issue-41498.rs new file mode 100644 index 000000000..ad918ecdd --- /dev/null +++ b/tests/ui/issues/issue-41498.rs @@ -0,0 +1,17 @@ +// run-pass +// regression test for issue #41498. + +struct S; +impl S { + fn mutate(&mut self) {} +} + +fn call_and_ref T>(x: &mut Option, f: F) -> &mut T { + *x = Some(f()); + x.as_mut().unwrap() +} + +fn main() { + let mut n = None; + call_and_ref(&mut n, || [S])[0].mutate(); +} diff --git a/tests/ui/issues/issue-41549.rs b/tests/ui/issues/issue-41549.rs new file mode 100644 index 000000000..d19926a54 --- /dev/null +++ b/tests/ui/issues/issue-41549.rs @@ -0,0 +1,12 @@ +// aux-build:issue-41549.rs + + +extern crate issue_41549; + +struct S; + +impl issue_41549::Trait for S { + const CONST: () = (); //~ ERROR incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/issues/issue-41549.stderr b/tests/ui/issues/issue-41549.stderr new file mode 100644 index 000000000..62307d387 --- /dev/null +++ b/tests/ui/issues/issue-41549.stderr @@ -0,0 +1,9 @@ +error[E0326]: implemented const `CONST` has an incompatible type for trait + --> $DIR/issue-41549.rs:9:18 + | +LL | const CONST: () = (); + | ^^ expected `u32`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/issues/issue-41604.rs b/tests/ui/issues/issue-41604.rs new file mode 100644 index 000000000..11a1cc25b --- /dev/null +++ b/tests/ui/issues/issue-41604.rs @@ -0,0 +1,11 @@ +// run-pass +struct B; + +impl B { + fn init(&mut self) {} +} + +fn main() { + let mut b = [B]; + b[1-1].init(); +} diff --git a/tests/ui/issues/issue-41628.rs b/tests/ui/issues/issue-41628.rs new file mode 100644 index 000000000..92159824e --- /dev/null +++ b/tests/ui/issues/issue-41628.rs @@ -0,0 +1,7 @@ +// check-pass +#![deny(dead_code)] + +#[used] +static FOO: u32 = 0; + +fn main() {} diff --git a/tests/ui/issues/issue-41652/auxiliary/issue-41652-b.rs b/tests/ui/issues/issue-41652/auxiliary/issue-41652-b.rs new file mode 100644 index 000000000..2ce21b036 --- /dev/null +++ b/tests/ui/issues/issue-41652/auxiliary/issue-41652-b.rs @@ -0,0 +1,6 @@ +pub trait Tr { + // Note: The function needs to be declared over multiple lines to reproduce + // the crash. DO NOT reformat. + fn f() + where Self: Sized; +} diff --git a/tests/ui/issues/issue-41652/issue-41652.rs b/tests/ui/issues/issue-41652/issue-41652.rs new file mode 100644 index 000000000..d8a6f4c8d --- /dev/null +++ b/tests/ui/issues/issue-41652/issue-41652.rs @@ -0,0 +1,14 @@ +// aux-build:issue-41652-b.rs + +extern crate issue_41652_b; + +struct S; + +impl issue_41652_b::Tr for S { + fn f() { + 3.f() + //~^ ERROR can't call method `f` on ambiguous numeric type `{integer}` + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-41652/issue-41652.stderr b/tests/ui/issues/issue-41652/issue-41652.stderr new file mode 100644 index 000000000..1618f0f5a --- /dev/null +++ b/tests/ui/issues/issue-41652/issue-41652.stderr @@ -0,0 +1,14 @@ +error[E0689]: can't call method `f` on ambiguous numeric type `{integer}` + --> $DIR/issue-41652.rs:9:11 + | +LL | 3.f() + | ^ + | +help: you must specify a concrete type for this numeric value, like `i32` + | +LL | 3_i32.f() + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/issues/issue-41677.rs b/tests/ui/issues/issue-41677.rs new file mode 100644 index 000000000..afddbc799 --- /dev/null +++ b/tests/ui/issues/issue-41677.rs @@ -0,0 +1,28 @@ +// run-pass +// Regression test for #41677. The local variable was winding up with +// a type `Receiver` where `?T` was unconstrained, because we +// failed to enforce the WF obligations and `?T` is a bivariant type +// parameter position. + +#![allow(unused_variables, dead_code)] + +use std::marker::PhantomData; + +trait Handle { + type Inner; +} + +struct ResizingHandle(PhantomData); +impl Handle for ResizingHandle { + type Inner = H; +} + +struct Receiver>(PhantomData); + +fn channel(size: usize) -> Receiver> { + let rx = Receiver(PhantomData); + rx +} + +fn main() { +} diff --git a/tests/ui/issues/issue-41696.rs b/tests/ui/issues/issue-41696.rs new file mode 100644 index 000000000..d094f7194 --- /dev/null +++ b/tests/ui/issues/issue-41696.rs @@ -0,0 +1,54 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![recursion_limit = "128"] +// this used to cause exponential code-size blowup during LLVM passes. + +#![feature(test)] + +extern crate test; + +struct MayUnwind; + +impl Drop for MayUnwind { + fn drop(&mut self) { + if test::black_box(false) { + panic!() + } + } +} + +struct DS { + may_unwind: MayUnwind, + name: String, + next: U, +} + +fn add(ds: DS, name: String) -> DS> { + DS { + may_unwind: MayUnwind, + name: "?".to_owned(), + next: ds, + } +} + +fn main() { + let deserializers = DS { may_unwind: MayUnwind, name: "?".to_owned(), next: () }; + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); + let deserializers = add(deserializers, "?".to_owned()); // 0.7s + let deserializers = add(deserializers, "?".to_owned()); // 1.3s + let deserializers = add(deserializers, "?".to_owned()); // 2.4s + let deserializers = add(deserializers, "?".to_owned()); // 6.7s + let deserializers = add(deserializers, "?".to_owned()); // 26.0s + let deserializers = add(deserializers, "?".to_owned()); // 114.0s + let deserializers = add(deserializers, "?".to_owned()); // 228.0s + let deserializers = add(deserializers, "?".to_owned()); // 400.0s + let deserializers = add(deserializers, "?".to_owned()); // 800.0s + let deserializers = add(deserializers, "?".to_owned()); // 1600.0s + let deserializers = add(deserializers, "?".to_owned()); // 3200.0s +} diff --git a/tests/ui/issues/issue-41726.rs b/tests/ui/issues/issue-41726.rs new file mode 100644 index 000000000..39631912c --- /dev/null +++ b/tests/ui/issues/issue-41726.rs @@ -0,0 +1,7 @@ +use std::collections::HashMap; +fn main() { + let things: HashMap> = HashMap::new(); + for src in things.keys() { + things[src.as_str()].sort(); //~ ERROR cannot borrow data in an index of + } +} diff --git a/tests/ui/issues/issue-41726.stderr b/tests/ui/issues/issue-41726.stderr new file mode 100644 index 000000000..b05c1fb14 --- /dev/null +++ b/tests/ui/issues/issue-41726.stderr @@ -0,0 +1,15 @@ +error[E0596]: cannot borrow data in an index of `HashMap>` as mutable + --> $DIR/issue-41726.rs:5:9 + | +LL | things[src.as_str()].sort(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap>` +help: to modify a `HashMap>` use `.get_mut()` + | +LL | things.get_mut(src.as_str()).map(|val| val.sort()); + | ~~~~~~~~~ ~~~~~~~~~~~~~~~ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-41742.rs b/tests/ui/issues/issue-41742.rs new file mode 100644 index 000000000..afe311b4d --- /dev/null +++ b/tests/ui/issues/issue-41742.rs @@ -0,0 +1,25 @@ +use std::ops::{Index, IndexMut}; + +struct S; +struct H; + +impl S { + fn f(&mut self) {} +} + +impl Index for H { + type Output = S; + fn index(&self, index: u32) -> &S { + unimplemented!() + } +} + +impl IndexMut for H { + fn index_mut(&mut self, index: u32) -> &mut S { + unimplemented!() + } +} + +fn main() { + H["?"].f(); //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-41742.stderr b/tests/ui/issues/issue-41742.stderr new file mode 100644 index 000000000..61a0ae5fa --- /dev/null +++ b/tests/ui/issues/issue-41742.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-41742.rs:24:7 + | +LL | H["?"].f(); + | ^^^ expected `u32`, found `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-41744.rs b/tests/ui/issues/issue-41744.rs new file mode 100644 index 000000000..dcdd1c21e --- /dev/null +++ b/tests/ui/issues/issue-41744.rs @@ -0,0 +1,7 @@ +// run-pass +trait Tc {} +impl Tc for bool {} + +fn main() { + let _: &[&dyn Tc] = &[&true]; +} diff --git a/tests/ui/issues/issue-41849-variance-req.rs b/tests/ui/issues/issue-41849-variance-req.rs new file mode 100644 index 000000000..af081083a --- /dev/null +++ b/tests/ui/issues/issue-41849-variance-req.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +// Regression test for #41849. + +use std::ops::Mul; + +const C: usize = 1; +const CAPACITY: usize = 1 * C; + +struct A { + f: [X; CAPACITY], +} + +struct B { + f: T, +} + +impl Mul for B { + type Output = Self; + fn mul(self, _rhs: B) -> Self::Output { + self + } +} + +impl Mul for B { + type Output = Self; + fn mul(self, _rhs: usize) -> Self::Output { + self + } +} + +fn main() { + let a = A { f: [1] }; + let _ = B { f: a }; +} diff --git a/tests/ui/issues/issue-41880.rs b/tests/ui/issues/issue-41880.rs new file mode 100644 index 000000000..977c43b71 --- /dev/null +++ b/tests/ui/issues/issue-41880.rs @@ -0,0 +1,29 @@ +fn iterate(initial: T, f: F) -> Iterate { + Iterate { + state: initial, + f: f, + } +} + +pub struct Iterate { + state: T, + f: F +} + +impl Iterator for Iterate where F: Fn(&T) -> T { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.state = (self.f)(&self.state); + Some(self.state.clone()) + } + #[inline] + fn size_hint(&self) -> (usize, Option) { (usize::MAX, None) } +} + +fn main() { + let a = iterate(0, |x| x+1); + println!("{:?}", a.iter().take(10).collect::>()); + //~^ ERROR no method named `iter` found +} diff --git a/tests/ui/issues/issue-41880.stderr b/tests/ui/issues/issue-41880.stderr new file mode 100644 index 000000000..00c375f8d --- /dev/null +++ b/tests/ui/issues/issue-41880.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `iter` found for struct `Iterate` in the current scope + --> $DIR/issue-41880.rs:27:24 + | +LL | pub struct Iterate { + | ------------------------ method `iter` not found for this struct +... +LL | println!("{:?}", a.iter().take(10).collect::>()); + | ^^^^ method not found in `Iterate<{integer}, [closure@issue-41880.rs:26:24]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-41888.rs b/tests/ui/issues/issue-41888.rs new file mode 100644 index 000000000..32df520f2 --- /dev/null +++ b/tests/ui/issues/issue-41888.rs @@ -0,0 +1,34 @@ +// run-pass +fn main() { let _ = g(Some(E::F(K))); } + +type R = Result<(), ()>; +struct K; + +enum E { + F(K), // must not be built-in type + #[allow(dead_code)] + G(Box, Box), +} + +fn translate(x: R) -> R { x } + +fn g(mut status: Option) -> R { + loop { + match status { + Some(infix_or_postfix) => match infix_or_postfix { + E::F(_op) => { // <- must be captured by value + match Ok(()) { + Err(err) => return Err(err), + Ok(_) => {}, + }; + } + _ => (), + }, + _ => match translate(Err(())) { + Err(err) => return Err(err), + Ok(_) => {}, + } + } + status = None; + } +} diff --git a/tests/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs b/tests/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs new file mode 100644 index 000000000..3d678ba04 --- /dev/null +++ b/tests/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs @@ -0,0 +1,30 @@ +// check-pass +#![allow(dead_code)] +// Regression test for #41936. The coerce-unsized trait check in +// coherence was using subtyping, which triggered variance +// computation, which failed because it required type info for fields +// that had not (yet) been computed. + +#![feature(unsize)] +#![feature(coerce_unsized)] + +use std::{marker,ops}; + +// Change the array to a non-array, and error disappears +// Adding a new field to the end keeps the error +struct LogDataBuf([u8;8]); + +struct Aref +{ + // Inner structure triggers the error, removing the inner removes the message. + ptr: Box>, +} +impl, U: ?Sized> ops::CoerceUnsized> for Aref {} + +struct ArefInner +{ + // Even with this field commented out, the error is raised. + data: T, +} + +fn main(){} diff --git a/tests/ui/issues/issue-41974.rs b/tests/ui/issues/issue-41974.rs new file mode 100644 index 000000000..10c363479 --- /dev/null +++ b/tests/ui/issues/issue-41974.rs @@ -0,0 +1,14 @@ +#[derive(Copy, Clone)] +struct Flags; + +trait A { +} + +impl Drop for T where T: A { + //~^ ERROR E0120 + //~| ERROR E0210 + fn drop(&mut self) { + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-41974.stderr b/tests/ui/issues/issue-41974.stderr new file mode 100644 index 000000000..e249db9df --- /dev/null +++ b/tests/ui/issues/issue-41974.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/issue-41974.rs:7:6 + | +LL | impl Drop for T where T: A { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/issue-41974.rs:7:18 + | +LL | impl Drop for T where T: A { + | ^ must be a struct, enum, or union in the current crate + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0120, E0210. +For more information about an error, try `rustc --explain E0120`. diff --git a/tests/ui/issues/issue-41998.rs b/tests/ui/issues/issue-41998.rs new file mode 100644 index 000000000..7696a3108 --- /dev/null +++ b/tests/ui/issues/issue-41998.rs @@ -0,0 +1,10 @@ +// check-pass + + +fn main() { + if ('x' as char) < ('y' as char) { + print!("x"); + } else { + print!("y"); + } +} diff --git a/tests/ui/issues/issue-42007.rs b/tests/ui/issues/issue-42007.rs new file mode 100644 index 000000000..a477e476e --- /dev/null +++ b/tests/ui/issues/issue-42007.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-42007-s.rs + +extern crate issue_42007_s; + +enum I { + E(issue_42007_s::E), +} + +fn main() {} diff --git a/tests/ui/issues/issue-4208.rs b/tests/ui/issues/issue-4208.rs new file mode 100644 index 000000000..3b01811a9 --- /dev/null +++ b/tests/ui/issues/issue-4208.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-4208-cc.rs + +// pretty-expanded FIXME #23616 + +extern crate numeric; +use numeric::{sin, Angle}; + +fn foo>(theta: A) -> T { sin(&theta) } + +pub fn main() {} diff --git a/tests/ui/issues/issue-42106.rs b/tests/ui/issues/issue-42106.rs new file mode 100644 index 000000000..5e688693b --- /dev/null +++ b/tests/ui/issues/issue-42106.rs @@ -0,0 +1,10 @@ +fn do_something(collection: &mut Vec) { + let _a = &collection; + collection.swap(1, 2); //~ ERROR also borrowed as immutable + _a.use_ref(); +} + +fn main() { } + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/issues/issue-42106.stderr b/tests/ui/issues/issue-42106.stderr new file mode 100644 index 000000000..73cf8652f --- /dev/null +++ b/tests/ui/issues/issue-42106.stderr @@ -0,0 +1,13 @@ +error[E0502]: cannot borrow `*collection` as mutable because it is also borrowed as immutable + --> $DIR/issue-42106.rs:3:5 + | +LL | let _a = &collection; + | ----------- immutable borrow occurs here +LL | collection.swap(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | _a.use_ref(); + | ------------ immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/issues/issue-42148.rs b/tests/ui/issues/issue-42148.rs new file mode 100644 index 000000000..cb8c0d6ed --- /dev/null +++ b/tests/ui/issues/issue-42148.rs @@ -0,0 +1,6 @@ +// run-pass +struct Zst; + +fn main() { + unsafe { ::std::ptr::write_volatile(1 as *mut Zst, Zst) } +} diff --git a/tests/ui/issues/issue-42210.rs b/tests/ui/issues/issue-42210.rs new file mode 100644 index 000000000..01a5d5636 --- /dev/null +++ b/tests/ui/issues/issue-42210.rs @@ -0,0 +1,21 @@ +// run-pass +// Regression test for #42210. + +// compile-flags: -g +// ignore-asmjs wasm2js does not support source maps yet + +trait Foo { + fn foo() { } +} + +struct Bar; + +trait Baz { +} + +impl Foo for (Bar, dyn Baz) { } + + +fn main() { + <(Bar, dyn Baz) as Foo>::foo() +} diff --git a/tests/ui/issues/issue-4228.rs b/tests/ui/issues/issue-4228.rs new file mode 100644 index 000000000..491000b65 --- /dev/null +++ b/tests/ui/issues/issue-4228.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct Foo; + +impl Foo { + fn first() {} +} +impl Foo { + fn second() {} +} + +pub fn main() { + Foo::first(); + Foo::second(); +} diff --git a/tests/ui/issues/issue-42312.rs b/tests/ui/issues/issue-42312.rs new file mode 100644 index 000000000..426efcbf9 --- /dev/null +++ b/tests/ui/issues/issue-42312.rs @@ -0,0 +1,11 @@ +use std::ops::Deref; + +pub trait Foo { + fn baz(_: Self::Target) where Self: Deref {} + //~^ ERROR the size for values of type +} + +pub fn f(_: dyn ToString) {} +//~^ ERROR the size for values of type + +fn main() { } diff --git a/tests/ui/issues/issue-42312.stderr b/tests/ui/issues/issue-42312.stderr new file mode 100644 index 000000000..3ca6a2957 --- /dev/null +++ b/tests/ui/issues/issue-42312.stderr @@ -0,0 +1,37 @@ +error[E0277]: the size for values of type `::Target` cannot be known at compilation time + --> $DIR/issue-42312.rs:4:12 + | +LL | fn baz(_: Self::Target) where Self: Deref {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `::Target` + = help: unsized fn params are gated as an unstable feature +help: consider further restricting the associated type + | +LL | fn baz(_: Self::Target) where Self: Deref, ::Target: Sized {} + | ++++++++++++++++++++++++++++++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn baz(_: &Self::Target) where Self: Deref {} + | + + +error[E0277]: the size for values of type `(dyn ToString + 'static)` cannot be known at compilation time + --> $DIR/issue-42312.rs:8:10 + | +LL | pub fn f(_: dyn ToString) {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn ToString + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | pub fn f(_: impl ToString) {} + | ~~~~ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | pub fn f(_: &dyn ToString) {} + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-42453.rs b/tests/ui/issues/issue-42453.rs new file mode 100644 index 000000000..92fefceab --- /dev/null +++ b/tests/ui/issues/issue-42453.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +#[derive(Debug)] +struct builder; + +fn main() { + +} diff --git a/tests/ui/issues/issue-42467.rs b/tests/ui/issues/issue-42467.rs new file mode 100644 index 000000000..afa1bcd13 --- /dev/null +++ b/tests/ui/issues/issue-42467.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(dead_code)] +struct Foo(T); + +struct IntoIter(T); + +impl<'a, T: 'a> Iterator for IntoIter { + type Item = (); + + fn next(&mut self) -> Option<()> { + None + } +} + +impl IntoIterator for Foo { + type Item = (); + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + IntoIter(self.0) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-4252.rs b/tests/ui/issues/issue-4252.rs new file mode 100644 index 000000000..0d47a7f0c --- /dev/null +++ b/tests/ui/issues/issue-4252.rs @@ -0,0 +1,33 @@ +// run-pass +trait X { + fn call(&self, x: &T); + fn default_method(&self, x: &T) { + println!("X::default_method {:?}", x); + } +} + +#[derive(Debug)] +struct Y(#[allow(unused_tuple_struct_fields)] isize); + +#[derive(Debug)] +struct Z { + x: T +} + +impl X for Y { + fn call(&self, x: &T) { + println!("X::call {:?} {:?}", self, x); + } +} + +impl Drop for Z { + fn drop(&mut self) { + // These statements used to cause an ICE. + self.x.call(self); + self.x.default_method(self); + } +} + +pub fn main() { + let _z = Z {x: Y(42)}; +} diff --git a/tests/ui/issues/issue-42552.rs b/tests/ui/issues/issue-42552.rs new file mode 100644 index 000000000..50d28a2f0 --- /dev/null +++ b/tests/ui/issues/issue-42552.rs @@ -0,0 +1,31 @@ +// run-pass +// Regression test for an obscure issue with the projection cache. + +fn into_iter(a: &I) -> Groups { + Groups { _a: a } +} + +pub struct Groups<'a, I: 'a> { + _a: &'a I, +} + +impl<'a, I: Iterator> Iterator for Groups<'a, I> { + type Item = Group<'a, I>; + fn next(&mut self) -> Option { + None + } +} + +pub struct Group<'a, I: Iterator + 'a> + where I::Item: 'a // <-- needed to trigger ICE! +{ + _phantom: &'a (), + _ice_trigger: I::Item, // <-- needed to trigger ICE! +} + + +fn main() { + let _ = into_iter(&[0].iter().map(|_| 0)).map(|grp| { + let _g = grp; + }); +} diff --git a/tests/ui/issues/issue-4265.rs b/tests/ui/issues/issue-4265.rs new file mode 100644 index 000000000..2596079d3 --- /dev/null +++ b/tests/ui/issues/issue-4265.rs @@ -0,0 +1,14 @@ +struct Foo { + baz: usize +} + +impl Foo { + fn bar() { + Foo { baz: 0 }.bar(); + } + + fn bar() { //~ ERROR duplicate definitions + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-4265.stderr b/tests/ui/issues/issue-4265.stderr new file mode 100644 index 000000000..8c7303f3c --- /dev/null +++ b/tests/ui/issues/issue-4265.stderr @@ -0,0 +1,12 @@ +error[E0592]: duplicate definitions with name `bar` + --> $DIR/issue-4265.rs:10:5 + | +LL | fn bar() { + | -------- other definition for `bar` +... +LL | fn bar() { + | ^^^^^^^^ duplicate definitions for `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/issues/issue-42755.rs b/tests/ui/issues/issue-42755.rs new file mode 100644 index 000000000..65796fc24 --- /dev/null +++ b/tests/ui/issues/issue-42755.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + ($($p:vis)*) => {} //~ ERROR repetition matches empty token tree +} + +foo!(a); + +fn main() {} diff --git a/tests/ui/issues/issue-42755.stderr b/tests/ui/issues/issue-42755.stderr new file mode 100644 index 000000000..12047e22f --- /dev/null +++ b/tests/ui/issues/issue-42755.stderr @@ -0,0 +1,8 @@ +error: repetition matches empty token tree + --> $DIR/issue-42755.rs:2:7 + | +LL | ($($p:vis)*) => {} + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-42796.rs b/tests/ui/issues/issue-42796.rs new file mode 100644 index 000000000..5e83a1cd6 --- /dev/null +++ b/tests/ui/issues/issue-42796.rs @@ -0,0 +1,19 @@ +pub trait Mirror { + type Image; +} + +impl Mirror for T { + type Image = T; +} + +pub fn poison(victim: String) where >::Image: Copy { + loop { drop(victim); } +} + +fn main() { + let s = "Hello!".to_owned(); + let mut s_copy = s; + s_copy.push_str("World!"); + "0wned!".to_owned(); + println!("{}", s); //~ ERROR borrow of moved value +} diff --git a/tests/ui/issues/issue-42796.stderr b/tests/ui/issues/issue-42796.stderr new file mode 100644 index 000000000..f2971df5d --- /dev/null +++ b/tests/ui/issues/issue-42796.stderr @@ -0,0 +1,20 @@ +error[E0382]: borrow of moved value: `s` + --> $DIR/issue-42796.rs:18:20 + | +LL | let s = "Hello!".to_owned(); + | - move occurs because `s` has type `String`, which does not implement the `Copy` trait +LL | let mut s_copy = s; + | - value moved here +... +LL | println!("{}", s); + | ^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut s_copy = s.clone(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-42880.rs b/tests/ui/issues/issue-42880.rs new file mode 100644 index 000000000..b61ba80e2 --- /dev/null +++ b/tests/ui/issues/issue-42880.rs @@ -0,0 +1,8 @@ +type Value = String; + +fn main() { + let f = |&Value::String(_)| (); //~ ERROR no associated item named + + let vec: Vec = Vec::new(); + vec.last().map(f); +} diff --git a/tests/ui/issues/issue-42880.stderr b/tests/ui/issues/issue-42880.stderr new file mode 100644 index 000000000..bec14429d --- /dev/null +++ b/tests/ui/issues/issue-42880.stderr @@ -0,0 +1,9 @@ +error[E0599]: no associated item named `String` found for struct `String` in the current scope + --> $DIR/issue-42880.rs:4:22 + | +LL | let f = |&Value::String(_)| (); + | ^^^^^^ associated item not found in `String` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-42956.rs b/tests/ui/issues/issue-42956.rs new file mode 100644 index 000000000..e6b3f9ffa --- /dev/null +++ b/tests/ui/issues/issue-42956.rs @@ -0,0 +1,26 @@ +// check-pass +#![allow(dead_code)] +#![allow(stable_features)] +#![feature(associated_consts)] + +impl A for i32 { + type Foo = u32; +} +impl B for u32 { + const BAR: i32 = 0; +} + +trait A { + type Foo: B; +} + +trait B { + const BAR: i32; +} + +fn generic() { + // This panics if the universal function call syntax is used as well + println!("{}", T::Foo::BAR); +} + +fn main() {} diff --git a/tests/ui/issues/issue-43057.rs b/tests/ui/issues/issue-43057.rs new file mode 100644 index 000000000..4ce52af43 --- /dev/null +++ b/tests/ui/issues/issue-43057.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(unused)] + +macro_rules! column { + ($i:ident) => { + $i + }; +} + +fn foo() -> ! { + panic!(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-43162.rs b/tests/ui/issues/issue-43162.rs new file mode 100644 index 000000000..782eb4229 --- /dev/null +++ b/tests/ui/issues/issue-43162.rs @@ -0,0 +1,8 @@ +fn foo() -> bool { + //~^ ERROR E0308 + break true; //~ ERROR E0268 +} + +fn main() { + break {}; //~ ERROR E0268 +} diff --git a/tests/ui/issues/issue-43162.stderr b/tests/ui/issues/issue-43162.stderr new file mode 100644 index 000000000..40d920005 --- /dev/null +++ b/tests/ui/issues/issue-43162.stderr @@ -0,0 +1,24 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-43162.rs:3:5 + | +LL | break true; + | ^^^^^^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-43162.rs:7:5 + | +LL | break {}; + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + +error[E0308]: mismatched types + --> $DIR/issue-43162.rs:1:13 + | +LL | fn foo() -> bool { + | --- ^^^^ expected `bool`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0268, E0308. +For more information about an error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-43205.rs b/tests/ui/issues/issue-43205.rs new file mode 100644 index 000000000..f47d5a347 --- /dev/null +++ b/tests/ui/issues/issue-43205.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + let _ = &&[()][0]; + println!("{:?}", &[(),()][1]); +} diff --git a/tests/ui/issues/issue-43250.rs b/tests/ui/issues/issue-43250.rs new file mode 100644 index 000000000..24d70d296 --- /dev/null +++ b/tests/ui/issues/issue-43250.rs @@ -0,0 +1,13 @@ +fn main() { + let mut y; + const C: u32 = 0; + macro_rules! m { + ($a:expr) => { + let $a = 0; + } + } + m!(y); + //~^ ERROR arbitrary expressions aren't allowed in patterns + m!(C); + //~^ ERROR arbitrary expressions aren't allowed in patterns +} diff --git a/tests/ui/issues/issue-43250.stderr b/tests/ui/issues/issue-43250.stderr new file mode 100644 index 000000000..f729c5cf1 --- /dev/null +++ b/tests/ui/issues/issue-43250.stderr @@ -0,0 +1,14 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/issue-43250.rs:9:8 + | +LL | m!(y); + | ^ + +error: arbitrary expressions aren't allowed in patterns + --> $DIR/issue-43250.rs:11:8 + | +LL | m!(C); + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-43291.rs b/tests/ui/issues/issue-43291.rs new file mode 100644 index 000000000..52b629e35 --- /dev/null +++ b/tests/ui/issues/issue-43291.rs @@ -0,0 +1,9 @@ +// run-pass +pub fn main() { + assert_eq!(!0usize as *const (), foo(0, 1)); + assert_eq!(!0usize as *const (), (0i8 - 1) as *const ()); +} + +pub fn foo(a: i8, b: i8) -> *const () { + (a - b) as *const () +} diff --git a/tests/ui/issues/issue-4333.rs b/tests/ui/issues/issue-4333.rs new file mode 100644 index 000000000..3df319b68 --- /dev/null +++ b/tests/ui/issues/issue-4333.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_must_use)] +// pretty-expanded FIXME #23616 + +use std::io; + +pub fn main() { + let stdout = &mut io::stdout() as &mut dyn io::Write; + stdout.write(b"Hello!"); +} diff --git a/tests/ui/issues/issue-4335.rs b/tests/ui/issues/issue-4335.rs new file mode 100644 index 000000000..c5914a17c --- /dev/null +++ b/tests/ui/issues/issue-4335.rs @@ -0,0 +1,13 @@ +#![feature(fn_traits)] + +fn id(t: T) -> T { t } + +fn f<'r, T>(v: &'r T) -> Box T + 'r> { + id(Box::new(|| *v)) + //~^ ERROR E0507 +} + +fn main() { + let v = &5; + println!("{}", f(v).call_mut(())); +} diff --git a/tests/ui/issues/issue-4335.stderr b/tests/ui/issues/issue-4335.stderr new file mode 100644 index 000000000..ecc1fa523 --- /dev/null +++ b/tests/ui/issues/issue-4335.stderr @@ -0,0 +1,13 @@ +error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMut` closure + --> $DIR/issue-4335.rs:6:20 + | +LL | fn f<'r, T>(v: &'r T) -> Box T + 'r> { + | - captured outer variable +LL | id(Box::new(|| *v)) + | -- ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait + | | + | captured by this `FnMut` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-43355.rs b/tests/ui/issues/issue-43355.rs new file mode 100644 index 000000000..bf819af79 --- /dev/null +++ b/tests/ui/issues/issue-43355.rs @@ -0,0 +1,19 @@ +pub trait Trait1 { + type Output; +} + +pub trait Trait2 {} + +pub struct A; + +impl Trait1 for T where T: Trait2 { + type Output = (); +} + +impl Trait1> for A { +//~^ ERROR conflicting implementations of trait +//~| downstream crates may implement trait `Trait2>` for type `A` + type Output = i32; +} + +fn main() {} diff --git a/tests/ui/issues/issue-43355.stderr b/tests/ui/issues/issue-43355.stderr new file mode 100644 index 000000000..57adc8ad5 --- /dev/null +++ b/tests/ui/issues/issue-43355.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `Trait1>` for type `A` + --> $DIR/issue-43355.rs:13:1 + | +LL | impl Trait1 for T where T: Trait2 { + | -------------------------- first implementation here +... +LL | impl Trait1> for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A` + | + = note: downstream crates may implement trait `Trait2>` for type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-43357.rs b/tests/ui/issues/issue-43357.rs new file mode 100644 index 000000000..474c97655 --- /dev/null +++ b/tests/ui/issues/issue-43357.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] +trait Trait { + type Output; +} + +fn f() { + std::mem::size_of::(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-43420-no-over-suggest.rs b/tests/ui/issues/issue-43420-no-over-suggest.rs new file mode 100644 index 000000000..4365bff5a --- /dev/null +++ b/tests/ui/issues/issue-43420-no-over-suggest.rs @@ -0,0 +1,9 @@ +// check that we substitute type parameters before we suggest anything - otherwise +// we would suggest function such as `as_slice` for the `&[u16]`. + +fn foo(b: &[u16]) {} + +fn main() { + let a: Vec = Vec::new(); + foo(&a); //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-43420-no-over-suggest.stderr b/tests/ui/issues/issue-43420-no-over-suggest.stderr new file mode 100644 index 000000000..58fd1121a --- /dev/null +++ b/tests/ui/issues/issue-43420-no-over-suggest.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-43420-no-over-suggest.rs:8:9 + | +LL | foo(&a); + | --- ^^ expected slice `[u16]`, found struct `Vec` + | | + | arguments to this function are incorrect + | + = note: expected reference `&[u16]` + found reference `&Vec` +note: function defined here + --> $DIR/issue-43420-no-over-suggest.rs:4:4 + | +LL | fn foo(b: &[u16]) {} + | ^^^ --------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-43424.rs b/tests/ui/issues/issue-43424.rs new file mode 100644 index 000000000..b3f76d8b0 --- /dev/null +++ b/tests/ui/issues/issue-43424.rs @@ -0,0 +1,12 @@ +#![allow(unused)] + +macro_rules! m { + ($attr_path: path) => { + #[$attr_path] + fn f() {} + } +} + +m!(inline); //~ ERROR: unexpected generic arguments in path + +fn main() {} diff --git a/tests/ui/issues/issue-43424.stderr b/tests/ui/issues/issue-43424.stderr new file mode 100644 index 000000000..8f59d7cc3 --- /dev/null +++ b/tests/ui/issues/issue-43424.stderr @@ -0,0 +1,8 @@ +error: unexpected generic arguments in path + --> $DIR/issue-43424.rs:10:10 + | +LL | m!(inline); + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-43431.rs b/tests/ui/issues/issue-43431.rs new file mode 100644 index 000000000..e7ec35105 --- /dev/null +++ b/tests/ui/issues/issue-43431.rs @@ -0,0 +1,14 @@ +#![feature(fn_traits)] + +trait CallSingle { + fn call(&self, a: A) -> B where Self: Sized, Self: Fn(A) -> B; +} + +impl B> CallSingle for F { + fn call(&self, a: A) -> B { + B>::call(self, (a,)) + //~^ ERROR associated type bindings are not allowed here + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-43431.stderr b/tests/ui/issues/issue-43431.stderr new file mode 100644 index 000000000..4edb52869 --- /dev/null +++ b/tests/ui/issues/issue-43431.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-43431.rs:9:27 + | +LL | B>::call(self, (a,)) + | ^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/issues/issue-43483.rs b/tests/ui/issues/issue-43483.rs new file mode 100644 index 000000000..76dd1c2eb --- /dev/null +++ b/tests/ui/issues/issue-43483.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] +trait VecN { + const DIM: usize; +} + +trait Mat { + type Row: VecN; +} + +fn m() { + let x = M::Row::DIM; +} + +fn main() {} diff --git a/tests/ui/issues/issue-43692.rs b/tests/ui/issues/issue-43692.rs new file mode 100644 index 000000000..a9999c226 --- /dev/null +++ b/tests/ui/issues/issue-43692.rs @@ -0,0 +1,5 @@ +// run-pass +fn main() { + assert_eq!('\u{10__FFFF}', '\u{10FFFF}'); + assert_eq!("\u{10_F0FF__}foo\u{1_0_0_0__}", "\u{10F0FF}foo\u{1000}"); +} diff --git a/tests/ui/issues/issue-43806.rs b/tests/ui/issues/issue-43806.rs new file mode 100644 index 000000000..8c8cccfb2 --- /dev/null +++ b/tests/ui/issues/issue-43806.rs @@ -0,0 +1,23 @@ +// check-pass + +#![deny(unused_results)] + +enum Void {} + +fn foo() {} + +fn bar() -> ! { + loop {} +} + +fn baz() -> Void { + loop {} +} + +fn qux() { + foo(); + bar(); + baz(); +} + +fn main() {} diff --git a/tests/ui/issues/issue-43853.rs b/tests/ui/issues/issue-43853.rs new file mode 100644 index 000000000..dd42c1e3c --- /dev/null +++ b/tests/ui/issues/issue-43853.rs @@ -0,0 +1,17 @@ +// run-pass +// needs-unwind + +use std::panic; + +fn test() { + wait(|| panic!()); +} + +fn wait T>(f: F) -> F::Output { + From::from(f()) +} + +fn main() { + let result = panic::catch_unwind(move || test()); + assert!(result.is_err()); +} diff --git a/tests/ui/issues/issue-4387.rs b/tests/ui/issues/issue-4387.rs new file mode 100644 index 000000000..84592f16a --- /dev/null +++ b/tests/ui/issues/issue-4387.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let _foo = [0; 2*4]; +} diff --git a/tests/ui/issues/issue-43910.rs b/tests/ui/issues/issue-43910.rs new file mode 100644 index 000000000..d8c877329 --- /dev/null +++ b/tests/ui/issues/issue-43910.rs @@ -0,0 +1,7 @@ +// run-pass +#![deny(unused_variables)] + +fn main() { + #[allow(unused_variables)] + let x = 12; +} diff --git a/tests/ui/issues/issue-43923.rs b/tests/ui/issues/issue-43923.rs new file mode 100644 index 000000000..ad35a6685 --- /dev/null +++ b/tests/ui/issues/issue-43923.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +struct A { ptr: T } + +fn foo(x: &A<[T]>) {} + +fn main() { + let a = foo; + let b = A { ptr: [a, a, a] }; + a(&A { ptr: [()] }); +} diff --git a/tests/ui/issues/issue-43925.rs b/tests/ui/issues/issue-43925.rs new file mode 100644 index 000000000..1a2108871 --- /dev/null +++ b/tests/ui/issues/issue-43925.rs @@ -0,0 +1,4 @@ +#[link(name = "foo", cfg("rlib"))] //~ ERROR link cfg must have a single predicate argument +extern "C" {} + +fn main() {} diff --git a/tests/ui/issues/issue-43925.stderr b/tests/ui/issues/issue-43925.stderr new file mode 100644 index 000000000..b0ad25063 --- /dev/null +++ b/tests/ui/issues/issue-43925.stderr @@ -0,0 +1,8 @@ +error: link cfg must have a single predicate argument + --> $DIR/issue-43925.rs:1:22 + | +LL | #[link(name = "foo", cfg("rlib"))] + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-43926.rs b/tests/ui/issues/issue-43926.rs new file mode 100644 index 000000000..6d3003552 --- /dev/null +++ b/tests/ui/issues/issue-43926.rs @@ -0,0 +1,4 @@ +#[link(name = "foo", cfg())] //~ ERROR link cfg must have a single predicate argument +extern "C" {} + +fn main() {} diff --git a/tests/ui/issues/issue-43926.stderr b/tests/ui/issues/issue-43926.stderr new file mode 100644 index 000000000..f67f91a6b --- /dev/null +++ b/tests/ui/issues/issue-43926.stderr @@ -0,0 +1,8 @@ +error: link cfg must have a single predicate argument + --> $DIR/issue-43926.rs:1:22 + | +LL | #[link(name = "foo", cfg())] + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-43988.rs b/tests/ui/issues/issue-43988.rs new file mode 100644 index 000000000..b114e8e03 --- /dev/null +++ b/tests/ui/issues/issue-43988.rs @@ -0,0 +1,36 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + + #[inline] + let _a = 4; + //~^^ ERROR attribute should be applied to function or closure + + + #[inline(XYZ)] + let _b = 4; + //~^^ ERROR attribute should be applied to function or closure + + #[repr(nothing)] + let _x = 0; + //~^^ ERROR E0552 + + #[repr(something_not_real)] + loop { + () + }; + //~^^^^ ERROR E0552 + + #[repr] + let _y = "123"; + //~^^ ERROR malformed `repr` attribute + + fn foo() {} + + #[inline(ABC)] + foo(); + //~^^ ERROR attribute should be applied to function or closure + + let _z = #[repr] 1; + //~^ ERROR malformed `repr` attribute +} diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr new file mode 100644 index 000000000..02c5dd5bf --- /dev/null +++ b/tests/ui/issues/issue-43988.stderr @@ -0,0 +1,56 @@ +error: malformed `repr` attribute input + --> $DIR/issue-43988.rs:24:5 + | +LL | #[repr] + | ^^^^^^^ help: must be of the form: `#[repr(C)]` + +error: malformed `repr` attribute input + --> $DIR/issue-43988.rs:34:14 + | +LL | let _z = #[repr] 1; + | ^^^^^^^ help: must be of the form: `#[repr(C)]` + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43988.rs:5:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | let _a = 4; + | ----------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43988.rs:10:5 + | +LL | #[inline(XYZ)] + | ^^^^^^^^^^^^^^ +LL | let _b = 4; + | ----------- not a function or closure + +error[E0552]: unrecognized representation hint + --> $DIR/issue-43988.rs:14:12 + | +LL | #[repr(nothing)] + | ^^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/issue-43988.rs:18:12 + | +LL | #[repr(something_not_real)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-43988.rs:30:5 + | +LL | #[inline(ABC)] + | ^^^^^^^^^^^^^^ +LL | foo(); + | ----- not a function or closure + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0518, E0552. +For more information about an error, try `rustc --explain E0518`. diff --git a/tests/ui/issues/issue-44023.rs b/tests/ui/issues/issue-44023.rs new file mode 100644 index 000000000..e4320b7da --- /dev/null +++ b/tests/ui/issues/issue-44023.rs @@ -0,0 +1,4 @@ +pub fn main () {} + +fn სáƒáƒ­áƒ›áƒ”ლáƒáƒ“_გემრიელი_სáƒáƒ“ილი ( ) -> isize { //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-44023.stderr b/tests/ui/issues/issue-44023.stderr new file mode 100644 index 000000000..9e9701241 --- /dev/null +++ b/tests/ui/issues/issue-44023.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-44023.rs:3:36 + | +LL | fn სáƒáƒ­áƒ›áƒ”ლáƒáƒ“_გემრიელი_სáƒáƒ“ილი ( ) -> isize { + | ------------------------ ^^^^^ expected `isize`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-44056.rs b/tests/ui/issues/issue-44056.rs new file mode 100644 index 000000000..a4903ed2c --- /dev/null +++ b/tests/ui/issues/issue-44056.rs @@ -0,0 +1,6 @@ +// build-pass (FIXME(55996): should be run on targets supporting avx) +// only-x86_64 +// no-prefer-dynamic +// compile-flags: -Ctarget-feature=+avx -Clto + +fn main() {} diff --git a/tests/ui/issues/issue-44078.rs b/tests/ui/issues/issue-44078.rs new file mode 100644 index 000000000..b8c0e285f --- /dev/null +++ b/tests/ui/issues/issue-44078.rs @@ -0,0 +1,3 @@ +fn main() { + "😊""; //~ ERROR unterminated double quote +} diff --git a/tests/ui/issues/issue-44078.stderr b/tests/ui/issues/issue-44078.stderr new file mode 100644 index 000000000..daf67219f --- /dev/null +++ b/tests/ui/issues/issue-44078.stderr @@ -0,0 +1,11 @@ +error[E0765]: unterminated double quote string + --> $DIR/issue-44078.rs:2:8 + | +LL | "😊""; + | _________^ +LL | | } + | |__^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0765`. diff --git a/tests/ui/issues/issue-44216-add-instant.rs b/tests/ui/issues/issue-44216-add-instant.rs new file mode 100644 index 000000000..78cfecf2f --- /dev/null +++ b/tests/ui/issues/issue-44216-add-instant.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:overflow +// ignore-emscripten no processes + +use std::time::{Instant, Duration}; + +fn main() { + let now = Instant::now(); + let _ = now + Duration::from_secs(u64::MAX); +} diff --git a/tests/ui/issues/issue-44216-add-system-time.rs b/tests/ui/issues/issue-44216-add-system-time.rs new file mode 100644 index 000000000..7e9a3f802 --- /dev/null +++ b/tests/ui/issues/issue-44216-add-system-time.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:overflow +// ignore-emscripten no processes + +use std::time::{Duration, SystemTime}; + +fn main() { + let now = SystemTime::now(); + let _ = now + Duration::from_secs(u64::MAX); +} diff --git a/tests/ui/issues/issue-44216-sub-instant.rs b/tests/ui/issues/issue-44216-sub-instant.rs new file mode 100644 index 000000000..e40f80d44 --- /dev/null +++ b/tests/ui/issues/issue-44216-sub-instant.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:overflow +// ignore-emscripten no processes + +use std::time::{Instant, Duration}; + +fn main() { + let now = Instant::now(); + let _ = now - Duration::from_secs(u64::MAX); +} diff --git a/tests/ui/issues/issue-44216-sub-system-time.rs b/tests/ui/issues/issue-44216-sub-system-time.rs new file mode 100644 index 000000000..2c5a000fa --- /dev/null +++ b/tests/ui/issues/issue-44216-sub-system-time.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:overflow +// ignore-emscripten no processes + +use std::time::{Duration, SystemTime}; + +fn main() { + let now = SystemTime::now(); + let _ = now - Duration::from_secs(u64::MAX); +} diff --git a/tests/ui/issues/issue-44239.fixed b/tests/ui/issues/issue-44239.fixed new file mode 100644 index 000000000..e6c29cee9 --- /dev/null +++ b/tests/ui/issues/issue-44239.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code, non_upper_case_globals)] +fn main() { + const n: usize = 0; + + struct Foo; + impl Foo { + const N: usize = n; + //~^ ERROR attempt to use a non-constant value + } +} diff --git a/tests/ui/issues/issue-44239.rs b/tests/ui/issues/issue-44239.rs new file mode 100644 index 000000000..482ed194c --- /dev/null +++ b/tests/ui/issues/issue-44239.rs @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code, non_upper_case_globals)] +fn main() { + let n: usize = 0; + + struct Foo; + impl Foo { + const N: usize = n; + //~^ ERROR attempt to use a non-constant value + } +} diff --git a/tests/ui/issues/issue-44239.stderr b/tests/ui/issues/issue-44239.stderr new file mode 100644 index 000000000..2a245c92c --- /dev/null +++ b/tests/ui/issues/issue-44239.stderr @@ -0,0 +1,12 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-44239.rs:8:26 + | +LL | let n: usize = 0; + | ----- help: consider using `const` instead of `let`: `const n` +... +LL | const N: usize = n; + | ^ non-constant value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/issues/issue-44247.rs b/tests/ui/issues/issue-44247.rs new file mode 100644 index 000000000..3544880fa --- /dev/null +++ b/tests/ui/issues/issue-44247.rs @@ -0,0 +1,19 @@ +// check-pass +#![allow(dead_code)] +trait T { + type X; + const X: Self::X; +} +fn foo() { + let _: X::X = X::X; +} + +trait S { + const X: Self::X; + type X; +} +fn bar() { + let _: X::X = X::X; +} + +fn main() {} diff --git a/tests/ui/issues/issue-44255.rs b/tests/ui/issues/issue-44255.rs new file mode 100644 index 000000000..224503204 --- /dev/null +++ b/tests/ui/issues/issue-44255.rs @@ -0,0 +1,29 @@ +// run-pass + +use std::marker::PhantomData; + +fn main() { + let _arr = [1; >::VAL]; +} + +trait TypeVal { + const VAL: T; +} + +struct Five; + +impl TypeVal for Five { + const VAL: usize = 5; +} + +struct Multiply { + _n: PhantomData, + _m: PhantomData, +} + +impl TypeVal for Multiply + where N: TypeVal, + M: TypeVal, +{ + const VAL: usize = N::VAL * M::VAL; +} diff --git a/tests/ui/issues/issue-44405.rs b/tests/ui/issues/issue-44405.rs new file mode 100644 index 000000000..d404b9044 --- /dev/null +++ b/tests/ui/issues/issue-44405.rs @@ -0,0 +1,22 @@ +use std::ops::Index; + +struct Test; +struct Container(Test); + +impl Test { + fn test(&mut self) {} +} + +impl<'a> Index<&'a bool> for Container { + type Output = Test; + + fn index(&self, _index: &'a bool) -> &Test { + &self.0 + } +} + +fn main() { + let container = Container(Test); + let mut val = true; + container[&mut val].test(); //~ ERROR: cannot borrow data +} diff --git a/tests/ui/issues/issue-44405.stderr b/tests/ui/issues/issue-44405.stderr new file mode 100644 index 000000000..626cb2999 --- /dev/null +++ b/tests/ui/issues/issue-44405.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow data in an index of `Container` as mutable + --> $DIR/issue-44405.rs:21:5 + | +LL | container[&mut val].test(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Container` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-4464.rs b/tests/ui/issues/issue-4464.rs new file mode 100644 index 000000000..7ac107150 --- /dev/null +++ b/tests/ui/issues/issue-4464.rs @@ -0,0 +1,7 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn broken(v: &[u8], i: usize, j: usize) -> &[u8] { &v[i..j] } + +pub fn main() {} diff --git a/tests/ui/issues/issue-44730.rs b/tests/ui/issues/issue-44730.rs new file mode 100644 index 000000000..0493811b2 --- /dev/null +++ b/tests/ui/issues/issue-44730.rs @@ -0,0 +1,15 @@ +// check-pass +//! dox + +#![deny(missing_docs)] + +macro_rules! doc { + ($e:expr) => ( + #[doc = $e] + pub struct Foo; + ) +} + +doc!("a"); + +fn main() {} diff --git a/tests/ui/issues/issue-44851.rs b/tests/ui/issues/issue-44851.rs new file mode 100644 index 000000000..23daaeb0f --- /dev/null +++ b/tests/ui/issues/issue-44851.rs @@ -0,0 +1,15 @@ +// check-pass +macro_rules! a { + () => { "a" } +} + +macro_rules! b { + ($doc:expr) => { + #[doc = $doc] + pub struct B; + } +} + +b!(a!()); + +fn main() {} diff --git a/tests/ui/issues/issue-4517.rs b/tests/ui/issues/issue-4517.rs new file mode 100644 index 000000000..caf85d44a --- /dev/null +++ b/tests/ui/issues/issue-4517.rs @@ -0,0 +1,8 @@ +fn bar(int_param: usize) {} + +fn main() { + let foo: [u8; 4] = [1; 4]; + bar(foo); + //~^ ERROR mismatched types + //~| expected `usize`, found array `[u8; 4]` +} diff --git a/tests/ui/issues/issue-4517.stderr b/tests/ui/issues/issue-4517.stderr new file mode 100644 index 000000000..70b4ca5ec --- /dev/null +++ b/tests/ui/issues/issue-4517.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-4517.rs:5:9 + | +LL | bar(foo); + | --- ^^^ expected `usize`, found array `[u8; 4]` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-4517.rs:1:4 + | +LL | fn bar(int_param: usize) {} + | ^^^ ---------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-4541.rs b/tests/ui/issues/issue-4541.rs new file mode 100644 index 000000000..e7f26d021 --- /dev/null +++ b/tests/ui/issues/issue-4541.rs @@ -0,0 +1,22 @@ +// run-pass + +fn parse_args() -> String { + let args: Vec<_> = ::std::env::args().collect(); + let mut n = 0; + + while n < args.len() { + match &*args[n] { + "-v" => (), + s => { + return s.to_string(); + } + } + n += 1; + } + + return "".to_string() +} + +pub fn main() { + println!("{}", parse_args()); +} diff --git a/tests/ui/issues/issue-4542.rs b/tests/ui/issues/issue-4542.rs new file mode 100644 index 000000000..2386561c3 --- /dev/null +++ b/tests/ui/issues/issue-4542.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::env; + +pub fn main() { + for arg in env::args() { + match arg.clone() { + _s => { } + } + } +} diff --git a/tests/ui/issues/issue-45425.rs b/tests/ui/issues/issue-45425.rs new file mode 100644 index 000000000..10ce374ea --- /dev/null +++ b/tests/ui/issues/issue-45425.rs @@ -0,0 +1,12 @@ +// check-pass +#![allow(dead_code)] +use std::ops::Add; + +fn ref_add(a: &T, b: &T) -> T +where + for<'x> &'x T: Add<&'x T, Output = T>, +{ + a + b +} + +fn main() {} diff --git a/tests/ui/issues/issue-4545.rs b/tests/ui/issues/issue-4545.rs new file mode 100644 index 000000000..86fcf9af2 --- /dev/null +++ b/tests/ui/issues/issue-4545.rs @@ -0,0 +1,7 @@ +// run-pass +// aux-build:issue-4545.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_4545 as somelib; +pub fn main() { somelib::mk::(); } diff --git a/tests/ui/issues/issue-45510.rs b/tests/ui/issues/issue-45510.rs new file mode 100644 index 000000000..9e104ce6c --- /dev/null +++ b/tests/ui/issues/issue-45510.rs @@ -0,0 +1,32 @@ +// Test overloaded resolution of fn_traits. +// run-pass + +#![feature(fn_traits)] +#![feature(unboxed_closures)] + +#[derive(Debug, PartialEq, Eq)] +struct Ishmael; +#[derive(Debug, PartialEq, Eq)] +struct Maybe; +struct CallMe; + +impl FnOnce<(Ishmael,)> for CallMe { + type Output = Ishmael; + extern "rust-call" fn call_once(self, _args: (Ishmael,)) -> Ishmael { + println!("Split your lungs with blood and thunder!"); + Ishmael + } +} + +impl FnOnce<(Maybe,)> for CallMe { + type Output = Maybe; + extern "rust-call" fn call_once(self, _args: (Maybe,)) -> Maybe { + println!("So we just met, and this is crazy"); + Maybe + } +} + +fn main() { + assert_eq!(CallMe(Ishmael), Ishmael); + assert_eq!(CallMe(Maybe), Maybe); +} diff --git a/tests/ui/issues/issue-45562.fixed b/tests/ui/issues/issue-45562.fixed new file mode 100644 index 000000000..ac700fbd0 --- /dev/null +++ b/tests/ui/issues/issue-45562.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +#[no_mangle] pub static RAH: usize = 5; +//~^ ERROR const items should never be `#[no_mangle]` + +fn main() {} diff --git a/tests/ui/issues/issue-45562.rs b/tests/ui/issues/issue-45562.rs new file mode 100644 index 000000000..eabb5a5ce --- /dev/null +++ b/tests/ui/issues/issue-45562.rs @@ -0,0 +1,6 @@ +// run-rustfix + +#[no_mangle] pub const RAH: usize = 5; +//~^ ERROR const items should never be `#[no_mangle]` + +fn main() {} diff --git a/tests/ui/issues/issue-45562.stderr b/tests/ui/issues/issue-45562.stderr new file mode 100644 index 000000000..be259d3f8 --- /dev/null +++ b/tests/ui/issues/issue-45562.stderr @@ -0,0 +1,12 @@ +error: const items should never be `#[no_mangle]` + --> $DIR/issue-45562.rs:3:14 + | +LL | #[no_mangle] pub const RAH: usize = 5; + | ---------^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | + = note: `#[deny(no_mangle_const_items)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-45697-1.rs b/tests/ui/issues/issue-45697-1.rs new file mode 100644 index 000000000..b45f1170b --- /dev/null +++ b/tests/ui/issues/issue-45697-1.rs @@ -0,0 +1,25 @@ +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +// compile-flags: -C overflow-checks=on + +struct S<'a> { + pointer: &'a mut isize +} + +fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> { + S { pointer: &mut *p.pointer } +} + +fn main() { + let mut x = 1; + + { + let mut y = S { pointer: &mut x }; + let z = copy_borrowed_ptr(&mut y); + *y.pointer += 1; + //~^ ERROR cannot use `*y.pointer` because it was mutably borrowed [E0503] + //~| ERROR cannot assign to `*y.pointer` because it is borrowed [E0506] + *z.pointer += 1; + } +} diff --git a/tests/ui/issues/issue-45697-1.stderr b/tests/ui/issues/issue-45697-1.stderr new file mode 100644 index 000000000..30c69f196 --- /dev/null +++ b/tests/ui/issues/issue-45697-1.stderr @@ -0,0 +1,26 @@ +error[E0503]: cannot use `*y.pointer` because it was mutably borrowed + --> $DIR/issue-45697-1.rs:20:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `y` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ use of borrowed `y` +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error[E0506]: cannot assign to `*y.pointer` because it is borrowed + --> $DIR/issue-45697-1.rs:20:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `*y.pointer` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0503, E0506. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/issues/issue-45697.rs b/tests/ui/issues/issue-45697.rs new file mode 100644 index 000000000..db6d1d8fa --- /dev/null +++ b/tests/ui/issues/issue-45697.rs @@ -0,0 +1,25 @@ +// Test that assignments to an `&mut` pointer which is found in a +// borrowed (but otherwise non-aliasable) location is illegal. + +// compile-flags: -C overflow-checks=off + +struct S<'a> { + pointer: &'a mut isize +} + +fn copy_borrowed_ptr<'a>(p: &'a mut S<'a>) -> S<'a> { + S { pointer: &mut *p.pointer } +} + +fn main() { + let mut x = 1; + + { + let mut y = S { pointer: &mut x }; + let z = copy_borrowed_ptr(&mut y); + *y.pointer += 1; + //~^ ERROR cannot use `*y.pointer` because it was mutably borrowed [E0503] + //~| ERROR cannot assign to `*y.pointer` because it is borrowed [E0506] + *z.pointer += 1; + } +} diff --git a/tests/ui/issues/issue-45697.stderr b/tests/ui/issues/issue-45697.stderr new file mode 100644 index 000000000..26749d36f --- /dev/null +++ b/tests/ui/issues/issue-45697.stderr @@ -0,0 +1,26 @@ +error[E0503]: cannot use `*y.pointer` because it was mutably borrowed + --> $DIR/issue-45697.rs:20:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `y` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ use of borrowed `y` +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error[E0506]: cannot assign to `*y.pointer` because it is borrowed + --> $DIR/issue-45697.rs:20:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `*y.pointer` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0503, E0506. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/issues/issue-45730.rs b/tests/ui/issues/issue-45730.rs new file mode 100644 index 000000000..3776759fe --- /dev/null +++ b/tests/ui/issues/issue-45730.rs @@ -0,0 +1,9 @@ +use std::fmt; +fn main() { + let x: *const _ = 0 as _; //~ ERROR cannot cast + + let x: *const _ = 0 as *const _; //~ ERROR cannot cast + let y: Option<*const dyn fmt::Debug> = Some(x) as _; + + let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast +} diff --git a/tests/ui/issues/issue-45730.stderr b/tests/ui/issues/issue-45730.stderr new file mode 100644 index 000000000..d00f3d91b --- /dev/null +++ b/tests/ui/issues/issue-45730.stderr @@ -0,0 +1,27 @@ +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/issue-45730.rs:3:28 + | +LL | let x: *const _ = 0 as _; + | ^ needs more type information + | + = note: the type information given here is insufficient to check whether the pointer cast is valid + +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/issue-45730.rs:5:28 + | +LL | let x: *const _ = 0 as *const _; + | ^^^^^^^^ needs more type information + | + = note: the type information given here is insufficient to check whether the pointer cast is valid + +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/issue-45730.rs:8:44 + | +LL | let x = 0 as *const i32 as *const _ as *mut _; + | ^^^^^^ needs more type information + | + = note: the type information given here is insufficient to check whether the pointer cast is valid + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0641`. diff --git a/tests/ui/issues/issue-45731.rs b/tests/ui/issues/issue-45731.rs new file mode 100644 index 000000000..5c5ac5987 --- /dev/null +++ b/tests/ui/issues/issue-45731.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(unused_variables)] +// compile-flags:--test -g +// ignore-asmjs wasm2js does not support source maps yet + +#[cfg(target_os = "macos")] +#[test] +fn simple_test() { + use std::{env, panic, fs}; + + // Find our dSYM and replace the DWARF binary with an empty file + let mut dsym_path = env::current_exe().unwrap(); + let executable_name = dsym_path.file_name().unwrap().to_str().unwrap().to_string(); + assert!(dsym_path.pop()); // Pop executable + dsym_path.push(format!("{}.dSYM/Contents/Resources/DWARF/{0}", executable_name)); + { + let file = fs::OpenOptions::new().read(false).write(true).truncate(true).create(false) + .open(&dsym_path).unwrap(); + } + + env::set_var("RUST_BACKTRACE", "1"); + + // We don't need to die of panic, just trigger a backtrace + let _ = panic::catch_unwind(|| { + assert!(false); + }); +} diff --git a/tests/ui/issues/issue-45801.rs b/tests/ui/issues/issue-45801.rs new file mode 100644 index 000000000..780baa896 --- /dev/null +++ b/tests/ui/issues/issue-45801.rs @@ -0,0 +1,25 @@ +struct Params; + +pub trait Plugin { + type Error; +} + +pub trait Pluggable { + fn get_ref>(&mut self) -> Option { + None + } +} + +struct Foo; +impl Plugin for Params { + type Error = (); +} + +impl Pluggable for T {} + +fn handle(req: &mut i32) { + req.get_ref::(); + //~^ ERROR the trait bound `Params: Plugin` is not satisfied +} + +fn main() {} diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr new file mode 100644 index 000000000..8967f49df --- /dev/null +++ b/tests/ui/issues/issue-45801.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `Params: Plugin` is not satisfied + --> $DIR/issue-45801.rs:21:9 + | +LL | req.get_ref::(); + | ^^^^^^^ the trait `Plugin` is not implemented for `Params` + | + = help: the trait `Plugin` is implemented for `Params` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-45965.rs b/tests/ui/issues/issue-45965.rs new file mode 100644 index 000000000..15649f777 --- /dev/null +++ b/tests/ui/issues/issue-45965.rs @@ -0,0 +1,4 @@ +fn main() { + let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 }; + //~^ ERROR expected function, found `{float}` +} diff --git a/tests/ui/issues/issue-45965.stderr b/tests/ui/issues/issue-45965.stderr new file mode 100644 index 000000000..f3eaa9176 --- /dev/null +++ b/tests/ui/issues/issue-45965.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `{float}` + --> $DIR/issue-45965.rs:2:30 + | +LL | let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 }; + | ^^^---------- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-46069.rs b/tests/ui/issues/issue-46069.rs new file mode 100644 index 000000000..c418128c1 --- /dev/null +++ b/tests/ui/issues/issue-46069.rs @@ -0,0 +1,23 @@ +// run-pass +use std::iter::{Fuse, Cloned}; +use std::slice::Iter; + +struct Foo<'a, T: 'a>(#[allow(unused_tuple_struct_fields)] &'a T); +impl<'a, T: 'a> Copy for Foo<'a, T> {} +impl<'a, T: 'a> Clone for Foo<'a, T> { + fn clone(&self) -> Self { *self } +} + +fn copy_ex() { + let s = 2; + let k1 = || s; + let upvar = Foo(&k1); + let k = || upvar; + k(); +} + +fn main() { + let _f: *mut >> as Iterator>::Item = std::ptr::null_mut(); + + copy_ex(); +} diff --git a/tests/ui/issues/issue-46101.rs b/tests/ui/issues/issue-46101.rs new file mode 100644 index 000000000..ab3d30d40 --- /dev/null +++ b/tests/ui/issues/issue-46101.rs @@ -0,0 +1,6 @@ +trait Foo {} +#[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro + //~| ERROR failed to resolve: partially resolved path in a derive macro +struct S; + +fn main() {} diff --git a/tests/ui/issues/issue-46101.stderr b/tests/ui/issues/issue-46101.stderr new file mode 100644 index 000000000..40295b8a1 --- /dev/null +++ b/tests/ui/issues/issue-46101.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: partially resolved path in a derive macro + --> $DIR/issue-46101.rs:2:10 + | +LL | #[derive(Foo::Anything)] + | ^^^^^^^^^^^^^ partially resolved path in a derive macro + +error[E0433]: failed to resolve: partially resolved path in a derive macro + --> $DIR/issue-46101.rs:2:10 + | +LL | #[derive(Foo::Anything)] + | ^^^^^^^^^^^^^ partially resolved path in a derive macro + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/issues/issue-46302.rs b/tests/ui/issues/issue-46302.rs new file mode 100644 index 000000000..ba681d84e --- /dev/null +++ b/tests/ui/issues/issue-46302.rs @@ -0,0 +1,9 @@ +fn foo() { + let s = "abc"; + let u: &str = if true { s[..2] } else { s }; + //~^ ERROR mismatched types +} + +fn main() { + foo(); +} diff --git a/tests/ui/issues/issue-46302.stderr b/tests/ui/issues/issue-46302.stderr new file mode 100644 index 000000000..a6f97c3c9 --- /dev/null +++ b/tests/ui/issues/issue-46302.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-46302.rs:3:27 + | +LL | let u: &str = if true { s[..2] } else { s }; + | ^^^^^^ + | | + | expected `&str`, found `str` + | help: consider borrowing here: `&s[..2]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-46311.rs b/tests/ui/issues/issue-46311.rs new file mode 100644 index 000000000..1233a49c5 --- /dev/null +++ b/tests/ui/issues/issue-46311.rs @@ -0,0 +1,4 @@ +fn main() { + 'break: loop { //~ ERROR invalid label name `'break` + } +} diff --git a/tests/ui/issues/issue-46311.stderr b/tests/ui/issues/issue-46311.stderr new file mode 100644 index 000000000..d72d6477d --- /dev/null +++ b/tests/ui/issues/issue-46311.stderr @@ -0,0 +1,8 @@ +error: invalid label name `'break` + --> $DIR/issue-46311.rs:2:5 + | +LL | 'break: loop { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-46332.rs b/tests/ui/issues/issue-46332.rs new file mode 100644 index 000000000..bed74e313 --- /dev/null +++ b/tests/ui/issues/issue-46332.rs @@ -0,0 +1,11 @@ +// Original Levenshtein distance for both of this is 1. We improved accuracy with +// additional case insensitive comparison. + +struct TyUint {} + +struct TyInt {} + +fn main() { + TyUInt {}; + //~^ ERROR cannot find struct, variant or union type `TyUInt` in this scope +} diff --git a/tests/ui/issues/issue-46332.stderr b/tests/ui/issues/issue-46332.stderr new file mode 100644 index 000000000..890ef8014 --- /dev/null +++ b/tests/ui/issues/issue-46332.stderr @@ -0,0 +1,12 @@ +error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope + --> $DIR/issue-46332.rs:9:5 + | +LL | struct TyUint {} + | ------------- similarly named struct `TyUint` defined here +... +LL | TyUInt {}; + | ^^^^^^ help: a struct with a similar name exists (notice the capitalization): `TyUint` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/issues/issue-46438.rs b/tests/ui/issues/issue-46438.rs new file mode 100644 index 000000000..d78b95846 --- /dev/null +++ b/tests/ui/issues/issue-46438.rs @@ -0,0 +1,13 @@ +macro_rules! m { + ($my_type: ty) => { + impl $my_type for u8 {} + } +} + +trait Tr {} + +m!(Tr); + +m!(&'static u8); //~ ERROR expected a trait, found type + +fn main() {} diff --git a/tests/ui/issues/issue-46438.stderr b/tests/ui/issues/issue-46438.stderr new file mode 100644 index 000000000..c1fad44b8 --- /dev/null +++ b/tests/ui/issues/issue-46438.stderr @@ -0,0 +1,8 @@ +error: expected a trait, found type + --> $DIR/issue-46438.rs:11:4 + | +LL | m!(&'static u8); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-46471-1.rs b/tests/ui/issues/issue-46471-1.rs new file mode 100644 index 000000000..aa161d40f --- /dev/null +++ b/tests/ui/issues/issue-46471-1.rs @@ -0,0 +1,8 @@ +fn main() { + let y = { + let mut z = 0; + &mut z + }; + //~^^ ERROR `z` does not live long enough [E0597] + println!("{}", y); +} diff --git a/tests/ui/issues/issue-46471-1.stderr b/tests/ui/issues/issue-46471-1.stderr new file mode 100644 index 000000000..b09f31729 --- /dev/null +++ b/tests/ui/issues/issue-46471-1.stderr @@ -0,0 +1,14 @@ +error[E0597]: `z` does not live long enough + --> $DIR/issue-46471-1.rs:4:9 + | +LL | &mut z + | ^^^^^^ + | | + | borrowed value does not live long enough + | borrow later used here +LL | }; + | - `z` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/issues/issue-46472.rs b/tests/ui/issues/issue-46472.rs new file mode 100644 index 000000000..b9e20e8db --- /dev/null +++ b/tests/ui/issues/issue-46472.rs @@ -0,0 +1,6 @@ +fn bar<'a>() -> &'a mut u32 { + &mut 4 + //~^ ERROR cannot return reference to temporary value [E0515] +} + +fn main() { } diff --git a/tests/ui/issues/issue-46472.stderr b/tests/ui/issues/issue-46472.stderr new file mode 100644 index 000000000..6e561e03a --- /dev/null +++ b/tests/ui/issues/issue-46472.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/issue-46472.rs:2:5 + | +LL | &mut 4 + | ^^^^^- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-46604.rs b/tests/ui/issues/issue-46604.rs new file mode 100644 index 000000000..6ec6e7bdc --- /dev/null +++ b/tests/ui/issues/issue-46604.rs @@ -0,0 +1,7 @@ +static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //~ ERROR mutable references are not allowed +fn write>(buffer: T) { } + +fn main() { + write(&buf); + buf[0]=2; //~ ERROR E0594 +} diff --git a/tests/ui/issues/issue-46604.stderr b/tests/ui/issues/issue-46604.stderr new file mode 100644 index 000000000..7faa2d79b --- /dev/null +++ b/tests/ui/issues/issue-46604.stderr @@ -0,0 +1,16 @@ +error[E0764]: mutable references are not allowed in the final value of statics + --> $DIR/issue-46604.rs:1:25 + | +LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item + --> $DIR/issue-46604.rs:6:5 + | +LL | buf[0]=2; + | ^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0594, E0764. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed new file mode 100644 index 000000000..8668d8acd --- /dev/null +++ b/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused)] + +fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + and_yet + 1 +} + +fn main() { + let behold: isize = 2; + let with_tears: usize = 3; + light_flows_our_war_of_mocking_words(&(behold as usize)); + //~^ ERROR mismatched types [E0308] + light_flows_our_war_of_mocking_words(&(with_tears + 4)); + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs b/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs new file mode 100644 index 000000000..c8494612c --- /dev/null +++ b/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused)] + +fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + and_yet + 1 +} + +fn main() { + let behold: isize = 2; + let with_tears: usize = 3; + light_flows_our_war_of_mocking_words(behold as usize); + //~^ ERROR mismatched types [E0308] + light_flows_our_war_of_mocking_words(with_tears + 4); + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr new file mode 100644 index 000000000..e874ded8e --- /dev/null +++ b/tests/ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:12:42 + | +LL | light_flows_our_war_of_mocking_words(behold as usize); + | ------------------------------------ ^^^^^^^^^^^^^^^ + | | | + | | expected `&usize`, found `usize` + | | help: consider borrowing here: `&(behold as usize)` + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4 + | +LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- + +error[E0308]: mismatched types + --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:14:42 + | +LL | light_flows_our_war_of_mocking_words(with_tears + 4); + | ------------------------------------ ^^^^^^^^^^^^^^ + | | | + | | expected `&usize`, found `usize` + | | help: consider borrowing here: `&(with_tears + 4)` + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:5:4 + | +LL | fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-46771.rs b/tests/ui/issues/issue-46771.rs new file mode 100644 index 000000000..22be8d6af --- /dev/null +++ b/tests/ui/issues/issue-46771.rs @@ -0,0 +1,4 @@ +fn main() { + struct Foo; + (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `Foo` +} diff --git a/tests/ui/issues/issue-46771.stderr b/tests/ui/issues/issue-46771.stderr new file mode 100644 index 000000000..512827b2d --- /dev/null +++ b/tests/ui/issues/issue-46771.stderr @@ -0,0 +1,13 @@ +error[E0618]: expected function, found `Foo` + --> $DIR/issue-46771.rs:3:23 + | +LL | struct Foo; + | ---------- `Foo` defined here +LL | (1 .. 2).find(|_| Foo(0) == 0); + | ^^^--- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/issues/issue-46855.rs b/tests/ui/issues/issue-46855.rs new file mode 100644 index 000000000..aa6378f85 --- /dev/null +++ b/tests/ui/issues/issue-46855.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: -Zmir-opt-level=1 + +use std::mem; + +#[derive(Copy, Clone)] +enum Never {} + +union Foo { + a: u64, + b: Never +} + +fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 } + +fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x } + +fn main() { + println!("{}", mem::size_of::()); + + let f = [Foo { a: 42 }, Foo { a: 10 }]; + println!("{:?}", unsafe { f[0].a }); +} diff --git a/tests/ui/issues/issue-46964.rs b/tests/ui/issues/issue-46964.rs new file mode 100644 index 000000000..28fa92f20 --- /dev/null +++ b/tests/ui/issues/issue-46964.rs @@ -0,0 +1,19 @@ +// check-pass +mod my_mod { + #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)] + pub struct Name<'a> { + source: &'a str, + } + + pub const JSON: Name = Name { source: "JSON" }; +} + +pub fn crash() -> bool { + match (my_mod::JSON, None) { + (_, Some(my_mod::JSON)) => true, + (my_mod::JSON, None) => true, + _ => false, + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-46983.rs b/tests/ui/issues/issue-46983.rs new file mode 100644 index 000000000..4bd49a879 --- /dev/null +++ b/tests/ui/issues/issue-46983.rs @@ -0,0 +1,6 @@ +fn foo(x: &u32) -> &'static u32 { + &*x + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/issues/issue-46983.stderr b/tests/ui/issues/issue-46983.stderr new file mode 100644 index 000000000..38a219bbd --- /dev/null +++ b/tests/ui/issues/issue-46983.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-46983.rs:2:5 + | +LL | fn foo(x: &u32) -> &'static u32 { + | - let's call the lifetime of this reference `'1` +LL | &*x + | ^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs new file mode 100644 index 000000000..6cd1f1443 --- /dev/null +++ b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs @@ -0,0 +1,12 @@ +type Guilty = bool; +type FineDollars = u32; + +struct Verdict(Guilty, Option); + +fn main() { + let justice = Verdict(true, Some(2718)); + let _condemned = justice.00; + //~^ ERROR no field `00` on type `Verdict` + let _punishment = justice.001; + //~^ ERROR no field `001` on type `Verdict` +} diff --git a/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr new file mode 100644 index 000000000..5e1b816de --- /dev/null +++ b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr @@ -0,0 +1,17 @@ +error[E0609]: no field `00` on type `Verdict` + --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30 + | +LL | let _condemned = justice.00; + | ^^ help: a field with a similar name exists: `0` + +error[E0609]: no field `001` on type `Verdict` + --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 + | +LL | let _punishment = justice.001; + | ^^^ unknown field + | + = note: available fields are: `0`, `1` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-47094.rs b/tests/ui/issues/issue-47094.rs new file mode 100644 index 000000000..c5d37feb1 --- /dev/null +++ b/tests/ui/issues/issue-47094.rs @@ -0,0 +1,16 @@ +#[repr(C, u8)] //~ ERROR conflicting representation hints +//~^ WARN this was previously accepted +enum Foo { + A, + B, +} + +#[repr(C)] //~ ERROR conflicting representation hints +//~^ WARN this was previously accepted +#[repr(u8)] +enum Bar { + A, + B, +} + +fn main() {} diff --git a/tests/ui/issues/issue-47094.stderr b/tests/ui/issues/issue-47094.stderr new file mode 100644 index 000000000..970e31847 --- /dev/null +++ b/tests/ui/issues/issue-47094.stderr @@ -0,0 +1,25 @@ +error[E0566]: conflicting representation hints + --> $DIR/issue-47094.rs:1:8 + | +LL | #[repr(C, u8)] + | ^ ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + +error[E0566]: conflicting representation hints + --> $DIR/issue-47094.rs:8:8 + | +LL | #[repr(C)] + | ^ +LL | +LL | #[repr(u8)] + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0566`. diff --git a/tests/ui/issues/issue-47184.rs b/tests/ui/issues/issue-47184.rs new file mode 100644 index 000000000..2f78ce000 --- /dev/null +++ b/tests/ui/issues/issue-47184.rs @@ -0,0 +1,4 @@ +fn main() { + let _vec: Vec<&'static String> = vec![&String::new()]; + //~^ ERROR temporary value dropped while borrowed [E0716] +} diff --git a/tests/ui/issues/issue-47184.stderr b/tests/ui/issues/issue-47184.stderr new file mode 100644 index 000000000..c2c7df7a3 --- /dev/null +++ b/tests/ui/issues/issue-47184.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-47184.rs:2:44 + | +LL | let _vec: Vec<&'static String> = vec![&String::new()]; + | -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/issues/issue-47309.rs b/tests/ui/issues/issue-47309.rs new file mode 100644 index 000000000..abed9687b --- /dev/null +++ b/tests/ui/issues/issue-47309.rs @@ -0,0 +1,21 @@ +// Make sure that the mono-item collector does not crash when trying to +// instantiate a default impl of a method with lifetime parameters. +// See https://github.com/rust-lang/rust/issues/47309 + +// compile-flags:-Clink-dead-code +// build-pass + +#![crate_type="rlib"] + +pub trait EnvFuture { + type Item; + + fn boxed_result<'a>(self) where Self: Sized, Self::Item: 'a, { + } +} + +struct Foo; + +impl<'a> EnvFuture for &'a Foo { + type Item = (); +} diff --git a/tests/ui/issues/issue-4734.rs b/tests/ui/issues/issue-4734.rs new file mode 100644 index 000000000..29c965d7f --- /dev/null +++ b/tests/ui/issues/issue-4734.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +// Ensures that destructors are run for expressions of the form "e;" where +// `e` is a type which requires a destructor. + + +#![allow(path_statements)] + +struct A { n: isize } +struct B; + +static mut NUM_DROPS: usize = 0; + +impl Drop for A { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} + +impl Drop for B { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} + +fn main() { + assert_eq!(unsafe { NUM_DROPS }, 0); + { let _a = A { n: 1 }; } + assert_eq!(unsafe { NUM_DROPS }, 1); + { A { n: 3 }; } + assert_eq!(unsafe { NUM_DROPS }, 2); + + { let _b = B; } + assert_eq!(unsafe { NUM_DROPS }, 3); + { B; } + assert_eq!(unsafe { NUM_DROPS }, 4); +} diff --git a/tests/ui/issues/issue-4735.rs b/tests/ui/issues/issue-4735.rs new file mode 100644 index 000000000..3ea4b01cd --- /dev/null +++ b/tests/ui/issues/issue-4735.rs @@ -0,0 +1,19 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::mem::transmute; + +struct NonCopyable(*const u8); + +impl Drop for NonCopyable { + fn drop(&mut self) { + let NonCopyable(p) = *self; + let _v = unsafe { transmute::<*const u8, Box>(p) }; + } +} + +pub fn main() { + let t = Box::new(0); + let p = unsafe { transmute::, *const u8>(t) }; + let _z = NonCopyable(p); +} diff --git a/tests/ui/issues/issue-4736.rs b/tests/ui/issues/issue-4736.rs new file mode 100644 index 000000000..799d2d480 --- /dev/null +++ b/tests/ui/issues/issue-4736.rs @@ -0,0 +1,5 @@ +struct NonCopyable(()); + +fn main() { + let z = NonCopyable{ p: () }; //~ ERROR struct `NonCopyable` has no field named `p` +} diff --git a/tests/ui/issues/issue-4736.stderr b/tests/ui/issues/issue-4736.stderr new file mode 100644 index 000000000..2a1f1819c --- /dev/null +++ b/tests/ui/issues/issue-4736.stderr @@ -0,0 +1,17 @@ +error[E0560]: struct `NonCopyable` has no field named `p` + --> $DIR/issue-4736.rs:4:26 + | +LL | struct NonCopyable(()); + | ----------- `NonCopyable` defined here +... +LL | let z = NonCopyable{ p: () }; + | ^ field does not exist + | +help: `NonCopyable` is a tuple struct, use the appropriate syntax + | +LL | let z = NonCopyable(/* fields */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/issues/issue-47364.rs b/tests/ui/issues/issue-47364.rs new file mode 100644 index 000000000..b524354d9 --- /dev/null +++ b/tests/ui/issues/issue-47364.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(unused_variables)] +// compile-flags: -C codegen-units=8 -O +#![allow(non_snake_case)] + +fn main() { + nom_sql::selection(b"x "); +} + +pub enum Err

{ + Position(P), + NodePosition(u32), +} + +pub enum IResult { + Done(I,O), + Error(Err), + Incomplete(u32, u64) +} + +pub fn multispace(input: T) -> ::IResult { + ::IResult::Done(0, 0) +} + +mod nom_sql { + fn where_clause(i: &[u8]) -> ::IResult<&[u8], Option> { + let X = match ::multispace(i) { + ::IResult::Done(..) => ::IResult::Done(i, None::), + _ => ::IResult::Error(::Err::NodePosition(0)), + }; + match X { + ::IResult::Done(_, _) => ::IResult::Done(i, None), + _ => X + } + } + + pub fn selection(i: &[u8]) { + let Y = match { + match { + where_clause(i) + } { + ::IResult::Done(_, o) => ::IResult::Done(i, Some(o)), + ::IResult::Error(_) => ::IResult::Done(i, None), + _ => ::IResult::Incomplete(0, 0), + } + } { + ::IResult::Done(z, _) => ::IResult::Done(z, None::), + _ => return () + }; + match Y { + ::IResult::Done(x, _) => { + let bytes = b"; "; + let len = x.len(); + bytes[len]; + } + _ => () + } + } +} diff --git a/tests/ui/issues/issue-47377.rs b/tests/ui/issues/issue-47377.rs new file mode 100644 index 000000000..7a2e0fe6d --- /dev/null +++ b/tests/ui/issues/issue-47377.rs @@ -0,0 +1,6 @@ +// ignore-tidy-tab +fn main() { + let b = "hello"; + let _a = b + ", World!"; + //~^ ERROR E0369 +} diff --git a/tests/ui/issues/issue-47377.stderr b/tests/ui/issues/issue-47377.stderr new file mode 100644 index 000000000..4f0fd948e --- /dev/null +++ b/tests/ui/issues/issue-47377.stderr @@ -0,0 +1,18 @@ +error[E0369]: cannot add `&str` to `&str` + --> $DIR/issue-47377.rs:4:14 + | +LL | let _a = b + ", World!"; + | - ^ ---------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _a = b.to_owned() + ", World!"; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-47380.rs b/tests/ui/issues/issue-47380.rs new file mode 100644 index 000000000..61e096622 --- /dev/null +++ b/tests/ui/issues/issue-47380.rs @@ -0,0 +1,5 @@ +fn main() { + let b = "hello"; + println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; + //~^ ERROR E0369 +} diff --git a/tests/ui/issues/issue-47380.stderr b/tests/ui/issues/issue-47380.stderr new file mode 100644 index 000000000..b04ac5536 --- /dev/null +++ b/tests/ui/issues/issue-47380.stderr @@ -0,0 +1,18 @@ +error[E0369]: cannot add `&str` to `&str` + --> $DIR/issue-47380.rs:3:35 + | +LL | println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!"; + | - ^ ---------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | println!("🦀🦀🦀🦀🦀"); let _a = b.to_owned() + ", World!"; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-47486.rs b/tests/ui/issues/issue-47486.rs new file mode 100644 index 000000000..d686f02a9 --- /dev/null +++ b/tests/ui/issues/issue-47486.rs @@ -0,0 +1,4 @@ +fn main() { + () < std::mem::size_of::<_>(); //~ ERROR: mismatched types + [0u8; std::mem::size_of::<_>()]; //~ ERROR: type annotations needed +} diff --git a/tests/ui/issues/issue-47486.stderr b/tests/ui/issues/issue-47486.stderr new file mode 100644 index 000000000..c7e9af70e --- /dev/null +++ b/tests/ui/issues/issue-47486.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-47486.rs:2:10 + | +LL | () < std::mem::size_of::<_>(); + | -- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize` + | | + | expected because this is `()` + +error[E0282]: type annotations needed + --> $DIR/issue-47486.rs:3:11 + | +LL | [0u8; std::mem::size_of::<_>()]; + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `size_of` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-4759-1.rs b/tests/ui/issues/issue-4759-1.rs new file mode 100644 index 000000000..96fae0fec --- /dev/null +++ b/tests/ui/issues/issue-4759-1.rs @@ -0,0 +1,4 @@ +// run-pass +trait U { fn f(self); } +impl U for isize { fn f(self) {} } +pub fn main() { 4.f(); } diff --git a/tests/ui/issues/issue-4759.rs b/tests/ui/issues/issue-4759.rs new file mode 100644 index 000000000..e5b9e2ed5 --- /dev/null +++ b/tests/ui/issues/issue-4759.rs @@ -0,0 +1,18 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_shorthand_field_patterns)] + +struct T { a: Box } + +trait U { + fn f(self); +} + +impl U for Box { + fn f(self) { } +} + +pub fn main() { + let T { a: a } = T { a: Box::new(0) }; + a.f(); +} diff --git a/tests/ui/issues/issue-47638.rs b/tests/ui/issues/issue-47638.rs new file mode 100644 index 000000000..a1ed3c365 --- /dev/null +++ b/tests/ui/issues/issue-47638.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_variables)] +fn id<'c, 'b>(f: &'c &'b dyn Fn(&i32)) -> &'c &'b dyn Fn(&'static i32) { + f +} + +fn main() { + let f: &dyn Fn(&i32) = &|x| {}; + id(&f); +} diff --git a/tests/ui/issues/issue-47646.rs b/tests/ui/issues/issue-47646.rs new file mode 100644 index 000000000..ace6cdce8 --- /dev/null +++ b/tests/ui/issues/issue-47646.rs @@ -0,0 +1,13 @@ +use std::collections::BinaryHeap; + +fn main() { + let mut heap: BinaryHeap = BinaryHeap::new(); + let borrow = heap.peek_mut(); + + match (borrow, ()) { + (Some(_), ()) => { + println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable + } + _ => {} + }; +} diff --git a/tests/ui/issues/issue-47646.stderr b/tests/ui/issues/issue-47646.stderr new file mode 100644 index 000000000..84cf9237a --- /dev/null +++ b/tests/ui/issues/issue-47646.stderr @@ -0,0 +1,20 @@ +error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as mutable + --> $DIR/issue-47646.rs:9:30 + | +LL | let borrow = heap.peek_mut(); + | --------------- mutable borrow occurs here +LL | +LL | match (borrow, ()) { + | ------------ a temporary with access to the mutable borrow is created here ... +LL | (Some(_), ()) => { +LL | println!("{:?}", heap); + | ^^^^ immutable borrow occurs here +... +LL | }; + | - ... and the mutable borrow might be used here, when that temporary is dropped and runs the destructor for type `(Option>, ())` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/issues/issue-47673.rs b/tests/ui/issues/issue-47673.rs new file mode 100644 index 000000000..b5f0febfb --- /dev/null +++ b/tests/ui/issues/issue-47673.rs @@ -0,0 +1,6 @@ +// check-pass +#![allow(unused_imports)] + +use {{}, {}}; + +fn main() {} diff --git a/tests/ui/issues/issue-47703-1.rs b/tests/ui/issues/issue-47703-1.rs new file mode 100644 index 000000000..61d684c2a --- /dev/null +++ b/tests/ui/issues/issue-47703-1.rs @@ -0,0 +1,23 @@ +// check-pass + +struct AtomicRefMut<'a> { + value: &'a mut i32, + borrow: AtomicBorrowRefMut, +} + +struct AtomicBorrowRefMut { +} + +impl Drop for AtomicBorrowRefMut { + fn drop(&mut self) { + } +} + +fn map(orig: AtomicRefMut) -> AtomicRefMut { + AtomicRefMut { + value: orig.value, + borrow: orig.borrow, + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-47703-tuple.rs b/tests/ui/issues/issue-47703-tuple.rs new file mode 100644 index 000000000..bad187ead --- /dev/null +++ b/tests/ui/issues/issue-47703-tuple.rs @@ -0,0 +1,11 @@ +// check-pass + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +fn consume(x: (&mut (), WithDrop)) -> &mut () { x.0 } + +fn main() {} diff --git a/tests/ui/issues/issue-47703.rs b/tests/ui/issues/issue-47703.rs new file mode 100644 index 000000000..38be6f5d2 --- /dev/null +++ b/tests/ui/issues/issue-47703.rs @@ -0,0 +1,18 @@ +// check-pass + +struct MyStruct<'a> { + field: &'a mut (), + field2: WithDrop +} + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +impl<'a> MyStruct<'a> { + fn consume(self) -> &'a mut () { self.field } +} + +fn main() {} diff --git a/tests/ui/issues/issue-47715.rs b/tests/ui/issues/issue-47715.rs new file mode 100644 index 000000000..b8088c18d --- /dev/null +++ b/tests/ui/issues/issue-47715.rs @@ -0,0 +1,28 @@ +trait Foo {} + +trait Bar {} + +trait Iterable { + type Item; +} + +struct Container> { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types + field: T +} + +enum Enum> { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types + A(T), +} + +union Union + Copy> { + //~^ ERROR `impl Trait` only allowed in function and inherent method return types + x: T, +} + +type Type> = T; +//~^ ERROR `impl Trait` only allowed in function and inherent method return types + +fn main() { +} diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/issues/issue-47715.stderr new file mode 100644 index 000000000..0ee9388bf --- /dev/null +++ b/tests/ui/issues/issue-47715.stderr @@ -0,0 +1,27 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic + --> $DIR/issue-47715.rs:9:37 + | +LL | struct Container> { + | ^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic + --> $DIR/issue-47715.rs:14:30 + | +LL | enum Enum> { + | ^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic + --> $DIR/issue-47715.rs:19:32 + | +LL | union Union + Copy> { + | ^^^^^^^^ + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic + --> $DIR/issue-47715.rs:24:30 + | +LL | type Type> = T; + | ^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/issues/issue-47722.rs b/tests/ui/issues/issue-47722.rs new file mode 100644 index 000000000..5645a6343 --- /dev/null +++ b/tests/ui/issues/issue-47722.rs @@ -0,0 +1,17 @@ +// check-pass + +// Tests that automatic coercions from &mut T to *mut T +// allow borrows of T to expire immediately - essentially, that +// they work identically to 'foo as *mut T' + +struct SelfReference { + self_reference: *mut SelfReference, +} + +impl SelfReference { + fn set_self_ref(&mut self) { + self.self_reference = self; + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-47725.rs b/tests/ui/issues/issue-47725.rs new file mode 100644 index 000000000..9ec55be58 --- /dev/null +++ b/tests/ui/issues/issue-47725.rs @@ -0,0 +1,28 @@ +#![warn(unused_attributes)] //~ NOTE lint level is defined here + +#[link_name = "foo"] +//~^ WARN attribute should be applied to a foreign function or static [unused_attributes] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +struct Foo; //~ NOTE not a foreign function or static + +#[link_name = "foobar"] +//~^ WARN attribute should be applied to a foreign function or static [unused_attributes] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~| HELP try `#[link(name = "foobar")]` instead +extern "C" { + fn foo() -> u32; +} +//~^^^ NOTE not a foreign function or static + +#[link_name] +//~^ ERROR malformed `link_name` attribute input +//~| HELP must be of the form +//~| WARN attribute should be applied to a foreign function or static [unused_attributes] +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~| HELP try `#[link(name = "...")]` instead +extern "C" { + fn bar() -> u32; +} +//~^^^ NOTE not a foreign function or static + +fn main() {} diff --git a/tests/ui/issues/issue-47725.stderr b/tests/ui/issues/issue-47725.stderr new file mode 100644 index 000000000..7143fb4d6 --- /dev/null +++ b/tests/ui/issues/issue-47725.stderr @@ -0,0 +1,60 @@ +error: malformed `link_name` attribute input + --> $DIR/issue-47725.rs:17:1 + | +LL | #[link_name] + | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-47725.rs:3:1 + | +LL | #[link_name = "foo"] + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | struct Foo; + | ----------- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/issue-47725.rs:1:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-47725.rs:8:1 + | +LL | #[link_name = "foobar"] + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | / extern "C" { +LL | | fn foo() -> u32; +LL | | } + | |_- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +help: try `#[link(name = "foobar")]` instead + --> $DIR/issue-47725.rs:8:1 + | +LL | #[link_name = "foobar"] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attribute should be applied to a foreign function or static + --> $DIR/issue-47725.rs:17:1 + | +LL | #[link_name] + | ^^^^^^^^^^^^ +... +LL | / extern "C" { +LL | | fn bar() -> u32; +LL | | } + | |_- not a foreign function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +help: try `#[link(name = "...")]` instead + --> $DIR/issue-47725.rs:17:1 + | +LL | #[link_name] + | ^^^^^^^^^^^^ + +error: aborting due to previous error; 3 warnings emitted + diff --git a/tests/ui/issues/issue-48006.rs b/tests/ui/issues/issue-48006.rs new file mode 100644 index 000000000..cfef270e5 --- /dev/null +++ b/tests/ui/issues/issue-48006.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(step_trait)] + +use std::iter::Step; + +#[cfg(target_pointer_width = "16")] +fn main() { + assert!(Step::steps_between(&0u32, &u32::MAX).is_none()); +} + +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] +fn main() { + assert!(Step::steps_between(&0u32, &u32::MAX).is_some()); +} diff --git a/tests/ui/issues/issue-48131.mir.stderr b/tests/ui/issues/issue-48131.mir.stderr new file mode 100644 index 000000000..6817e8830 --- /dev/null +++ b/tests/ui/issues/issue-48131.mir.stderr @@ -0,0 +1,20 @@ +error: unnecessary `unsafe` block + --> $DIR/issue-48131.rs:12:9 + | +LL | unsafe { /* unnecessary */ } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/issue-48131.rs:6:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/issue-48131.rs:23:13 + | +LL | unsafe { /* unnecessary */ } + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-48131.rs b/tests/ui/issues/issue-48131.rs new file mode 100644 index 000000000..df9854708 --- /dev/null +++ b/tests/ui/issues/issue-48131.rs @@ -0,0 +1,33 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +// This note is annotated because the purpose of the test +// is to ensure that certain other notes are not generated. +#![deny(unused_unsafe)] //~ NOTE + + +// (test that no note is generated on this unsafe fn) +pub unsafe fn a() { + fn inner() { + unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe` + //~^ NOTE + } + + inner() +} + +pub fn b() { + // (test that no note is generated on this unsafe block) + unsafe { + fn inner() { + unsafe { /* unnecessary */ } //~ ERROR unnecessary `unsafe` + //~^ NOTE + } + // `()` is fine to zero-initialize as it is zero sized and inhabited. + let () = ::std::mem::zeroed(); + + inner() + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-48131.thir.stderr b/tests/ui/issues/issue-48131.thir.stderr new file mode 100644 index 000000000..6817e8830 --- /dev/null +++ b/tests/ui/issues/issue-48131.thir.stderr @@ -0,0 +1,20 @@ +error: unnecessary `unsafe` block + --> $DIR/issue-48131.rs:12:9 + | +LL | unsafe { /* unnecessary */ } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/issue-48131.rs:6:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/issue-48131.rs:23:13 + | +LL | unsafe { /* unnecessary */ } + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-48132.rs b/tests/ui/issues/issue-48132.rs new file mode 100644 index 000000000..f564aefe7 --- /dev/null +++ b/tests/ui/issues/issue-48132.rs @@ -0,0 +1,31 @@ +// Regression test for #48132. This was failing due to problems around +// the projection caching and dropck type enumeration. + +// run-pass + +#![allow(dead_code)] + +struct Inner { + iterator: I, + item: V, +} + +struct Outer { + inner: Inner, +} + +fn outer(iterator: I) -> Outer +where I: Iterator, + I::Item: Default, +{ + Outer { + inner: Inner { + iterator: iterator, + item: Default::default(), + } + } +} + +fn main() { + outer(std::iter::once(&1).cloned()); +} diff --git a/tests/ui/issues/issue-48159.rs b/tests/ui/issues/issue-48159.rs new file mode 100644 index 000000000..fc8f31fb1 --- /dev/null +++ b/tests/ui/issues/issue-48159.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::mem; + +pub enum c_void {} + +type uintptr_t = usize; +type int16_t = u16; +type uint16_t = int16_t; +type uint32_t = u32; +type intptr_t = uintptr_t; + +#[repr(C)] +#[repr(packed(4))] +pub struct kevent { + pub ident: uintptr_t, + pub filter: int16_t, + pub flags: uint16_t, + pub fflags: uint32_t, + pub data: intptr_t, + pub udata: *mut c_void, +} + +fn main() { + assert_eq!(mem::align_of::(), 4); +} diff --git a/tests/ui/issues/issue-48179.rs b/tests/ui/issues/issue-48179.rs new file mode 100644 index 000000000..f81203dc4 --- /dev/null +++ b/tests/ui/issues/issue-48179.rs @@ -0,0 +1,38 @@ +// Regression test for #48132. This was failing due to problems around +// the projection caching and dropck type enumeration. + +// check-pass + +pub struct Container { + value: Option, +} + +impl Container { + pub fn new(iter: T) -> Self { + panic!() + } +} + +pub struct Wrapper<'a> { + content: &'a Content, +} + +impl<'a, 'de> Wrapper<'a> { + pub fn new(content: &'a Content) -> Self { + Wrapper { + content: content, + } + } +} + +pub struct Content; + +fn crash_it(content: Content) { + let items = vec![content]; + let map = items.iter().map(|ref o| Wrapper::new(o)); + + let mut map_visitor = Container::new(map); + +} + +fn main() {} diff --git a/tests/ui/issues/issue-48276.rs b/tests/ui/issues/issue-48276.rs new file mode 100644 index 000000000..f55c056fa --- /dev/null +++ b/tests/ui/issues/issue-48276.rs @@ -0,0 +1,33 @@ +// Regression test for issue #48276 - ICE when self type does not match what is +// required by a trait and regions are involved. + +trait MyFrom { + fn from(a: A) -> Self; +} + +struct A; + +impl<'a, 'b> MyFrom for &'a str { + fn from(self: &'a Self) -> &'b str { + //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait + "asdf" + } +} + +struct B; + +impl From for B { + fn from(&self) -> B { + //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait + B + } +} + +impl From for &'static str { + fn from(&self) -> &'static str { + //~^ ERROR: method `from` has a `&self` declaration in the impl, but not in the trait + "" + } +} + +fn main(){} diff --git a/tests/ui/issues/issue-48276.stderr b/tests/ui/issues/issue-48276.stderr new file mode 100644 index 000000000..370905ee0 --- /dev/null +++ b/tests/ui/issues/issue-48276.stderr @@ -0,0 +1,28 @@ +error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait + --> $DIR/issue-48276.rs:11:5 + | +LL | fn from(a: A) -> Self; + | ---------------------- trait method declared without `&self` +... +LL | fn from(self: &'a Self) -> &'b str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl + +error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait + --> $DIR/issue-48276.rs:20:5 + | +LL | fn from(&self) -> B { + | ^^^^^^^^^^^^^^^^^^^ `&self` used in impl + | + = note: `from` from trait: `fn(T) -> Self` + +error[E0185]: method `from` has a `&self` declaration in the impl, but not in the trait + --> $DIR/issue-48276.rs:27:5 + | +LL | fn from(&self) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&self` used in impl + | + = note: `from` from trait: `fn(T) -> Self` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0185`. diff --git a/tests/ui/issues/issue-4830.rs b/tests/ui/issues/issue-4830.rs new file mode 100644 index 000000000..a8553bd6b --- /dev/null +++ b/tests/ui/issues/issue-4830.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +pub struct Scheduler { + /// The event loop used to drive the scheduler and perform I/O + event_loop: Box +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-48364.rs b/tests/ui/issues/issue-48364.rs new file mode 100644 index 000000000..14ee75e7c --- /dev/null +++ b/tests/ui/issues/issue-48364.rs @@ -0,0 +1,6 @@ +fn foo() -> bool { + b"".starts_with(stringify!(foo)) + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/issues/issue-48364.stderr b/tests/ui/issues/issue-48364.stderr new file mode 100644 index 000000000..60bbfc0c6 --- /dev/null +++ b/tests/ui/issues/issue-48364.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-48364.rs:2:21 + | +LL | b"".starts_with(stringify!(foo)) + | ----------- ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str` + | | + | arguments to this method are incorrect + | + = note: expected reference `&[u8]` + found reference `&'static str` +note: associated function defined here + --> $SRC_DIR/core/src/slice/mod.rs:LL:COL + = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs new file mode 100644 index 000000000..cbdc10bd2 --- /dev/null +++ b/tests/ui/issues/issue-48728.rs @@ -0,0 +1,13 @@ +// Regression test for #48728, an ICE that occurred computing +// coherence "help" information. + +#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone` +struct Node(Box); + +impl Clone for Node<[T]> { + fn clone(&self) -> Self { + Node(Box::clone(&self.0)) + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-48728.stderr b/tests/ui/issues/issue-48728.stderr new file mode 100644 index 000000000..0bb46724f --- /dev/null +++ b/tests/ui/issues/issue-48728.stderr @@ -0,0 +1,15 @@ +error[E0119]: conflicting implementations of trait `Clone` for type `Node<[_]>` + --> $DIR/issue-48728.rs:4:10 + | +LL | #[derive(Clone)] + | ^^^^^ conflicting implementation for `Node<[_]>` +... +LL | impl Clone for Node<[T]> { + | ------------------------------------------- first implementation here + | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `[_]` in future versions + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-4875.rs b/tests/ui/issues/issue-4875.rs new file mode 100644 index 000000000..8d361314f --- /dev/null +++ b/tests/ui/issues/issue-4875.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// regression test for issue 4875 + +// pretty-expanded FIXME #23616 + +pub struct Foo { + data: T, +} + +fn foo(Foo{..}: Foo) { +} + +pub fn main() { +} diff --git a/tests/ui/issues/issue-48838.rs b/tests/ui/issues/issue-48838.rs new file mode 100644 index 000000000..057a424df --- /dev/null +++ b/tests/ui/issues/issue-48838.rs @@ -0,0 +1,5 @@ +enum Functions { + Square = |x| x, //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/issues/issue-48838.stderr b/tests/ui/issues/issue-48838.stderr new file mode 100644 index 000000000..3502af702 --- /dev/null +++ b/tests/ui/issues/issue-48838.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-48838.rs:2:14 + | +LL | Square = |x| x, + | ^^^^^ expected `isize`, found closure + | + = note: expected type `isize` + found closure `[closure@$DIR/issue-48838.rs:2:14: 2:17]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-48984.rs b/tests/ui/issues/issue-48984.rs new file mode 100644 index 000000000..cb340f848 --- /dev/null +++ b/tests/ui/issues/issue-48984.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-48984-aux.rs +extern crate issue48984aux; +use issue48984aux::Bar; + +fn do_thing() { } + +fn main() { } diff --git a/tests/ui/issues/issue-49298.rs b/tests/ui/issues/issue-49298.rs new file mode 100644 index 000000000..e3ffa8e7c --- /dev/null +++ b/tests/ui/issues/issue-49298.rs @@ -0,0 +1,42 @@ +// run-pass +#![feature(test)] +#![allow(unused_mut)] // under NLL we get warning about `x` below: rust-lang/rust#54499 + +// This test is bogus (i.e., should be check-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it +// +// ignore-test + +// This test is checking that the space allocated for `x.1` does not +// overlap with `y`. (The reason why such a thing happened at one +// point was because `x.0: Void` and thus the whole type of `x` was +// uninhabited, and so the compiler thought it was safe to use the +// space of `x.1` to hold `y`.) +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + +extern crate test; + +enum Void {} + +fn main() { + let mut x: (Void, usize); + let mut y = 42; + x.1 = 13; + + // Make sure `y` stays on the stack. + test::black_box(&mut y); + + // Check that the write to `x.1` did not overwrite `y`. + // Note that this doesn't fail with optimizations enabled, + // because we can't keep `x.1` on the stack, like we can `y`, + // as we can't borrow partially initialized variables. + assert_eq!(y.to_string(), "42"); + + // Check that `(Void, usize)` has space for the `usize` field. + assert_eq!(std::mem::size_of::<(Void, usize)>(), + std::mem::size_of::()); +} diff --git a/tests/ui/issues/issue-4935.rs b/tests/ui/issues/issue-4935.rs new file mode 100644 index 000000000..c95020a0c --- /dev/null +++ b/tests/ui/issues/issue-4935.rs @@ -0,0 +1,6 @@ +// Regression test for issue #4935 + +fn foo(a: usize) {} +//~^ defined here +fn main() { foo(5, 6) } +//~^ ERROR function takes 1 argument but 2 arguments were supplied diff --git a/tests/ui/issues/issue-4935.stderr b/tests/ui/issues/issue-4935.stderr new file mode 100644 index 000000000..bb45fa083 --- /dev/null +++ b/tests/ui/issues/issue-4935.stderr @@ -0,0 +1,19 @@ +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/issue-4935.rs:5:13 + | +LL | fn main() { foo(5, 6) } + | ^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/issue-4935.rs:3:4 + | +LL | fn foo(a: usize) {} + | ^^^ -------- +help: remove the extra argument + | +LL | fn main() { foo(5) } + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/issues/issue-49544.rs b/tests/ui/issues/issue-49544.rs new file mode 100644 index 000000000..ed356275f --- /dev/null +++ b/tests/ui/issues/issue-49544.rs @@ -0,0 +1,9 @@ +// aux-build:issue-49544.rs +// check-pass + +extern crate issue_49544; +use issue_49544::foo; + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/issues/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs b/tests/ui/issues/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs new file mode 100644 index 000000000..f30d7e2ed --- /dev/null +++ b/tests/ui/issues/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_variables)] +#![deny(non_shorthand_field_patterns)] + +pub struct Value { pub value: A } + +#[macro_export] +macro_rules! pat { + ($a:pat) => { + Value { value: $a } + }; +} + +fn main() { + let pat!(value) = Value { value: () }; +} diff --git a/tests/ui/issues/issue-49632.rs b/tests/ui/issues/issue-49632.rs new file mode 100644 index 000000000..155fd0d24 --- /dev/null +++ b/tests/ui/issues/issue-49632.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(stmt_expr_attributes)] + +pub fn main() { + let _x = #[inline(always)] || {}; + let _y = #[inline(never)] || {}; + let _z = #[inline] || {}; +} diff --git a/tests/ui/issues/issue-4968.rs b/tests/ui/issues/issue-4968.rs new file mode 100644 index 000000000..634bd698d --- /dev/null +++ b/tests/ui/issues/issue-4968.rs @@ -0,0 +1,10 @@ +// Regression test for issue #4968 + +const A: (isize,isize) = (4,2); +fn main() { + match 42 { A => () } + //~^ ERROR mismatched types + //~| expected type `{integer}` + //~| found tuple `(isize, isize)` + //~| expected integer, found tuple +} diff --git a/tests/ui/issues/issue-4968.stderr b/tests/ui/issues/issue-4968.stderr new file mode 100644 index 000000000..bbaca4ed2 --- /dev/null +++ b/tests/ui/issues/issue-4968.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-4968.rs:5:16 + | +LL | const A: (isize,isize) = (4,2); + | ---------------------- constant defined here +LL | fn main() { +LL | match 42 { A => () } + | -- ^ + | | | + | | expected integer, found tuple + | | `A` is interpreted as a constant, not a new binding + | | help: introduce a new binding instead: `other_a` + | this expression has type `{integer}` + | + = note: expected type `{integer}` + found tuple `(isize, isize)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-4972.rs b/tests/ui/issues/issue-4972.rs new file mode 100644 index 000000000..3f1c6f855 --- /dev/null +++ b/tests/ui/issues/issue-4972.rs @@ -0,0 +1,17 @@ +#![feature(box_patterns)] + +trait MyTrait { + fn dummy(&self) {} +} + +pub enum TraitWrapper { + A(Box), +} + +fn get_tw_map(tw: &TraitWrapper) -> &dyn MyTrait { + match *tw { + TraitWrapper::A(box ref map) => map, //~ ERROR cannot be dereferenced + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-4972.stderr b/tests/ui/issues/issue-4972.stderr new file mode 100644 index 000000000..83daded7e --- /dev/null +++ b/tests/ui/issues/issue-4972.stderr @@ -0,0 +1,9 @@ +error[E0033]: type `Box<(dyn MyTrait + 'static)>` cannot be dereferenced + --> $DIR/issue-4972.rs:13:25 + | +LL | TraitWrapper::A(box ref map) => map, + | ^^^^^^^^^^^ type `Box<(dyn MyTrait + 'static)>` cannot be dereferenced + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0033`. diff --git a/tests/ui/issues/issue-49824.rs b/tests/ui/issues/issue-49824.rs new file mode 100644 index 000000000..bc1cd6856 --- /dev/null +++ b/tests/ui/issues/issue-49824.rs @@ -0,0 +1,9 @@ +fn main() { + let mut x = 0; + || { + || { + //~^ ERROR captured variable cannot escape `FnMut` closure body + let _y = &mut x; + } + }; +} diff --git a/tests/ui/issues/issue-49824.stderr b/tests/ui/issues/issue-49824.stderr new file mode 100644 index 000000000..14beadece --- /dev/null +++ b/tests/ui/issues/issue-49824.stderr @@ -0,0 +1,23 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-49824.rs:4:9 + | +LL | let mut x = 0; + | ----- variable defined here +LL | || { + | - inferred to be a `FnMut` closure +LL | / || { +LL | | +LL | | let _y = &mut x; + | | - variable captured here +LL | | } + | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape +help: consider adding 'move' keyword before the nested closure + | +LL | move || { + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.rs b/tests/ui/issues/issue-49851/compiler-builtins-error.rs new file mode 100644 index 000000000..4e56cca33 --- /dev/null +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.rs @@ -0,0 +1,13 @@ +//~ ERROR can't find crate for `core` +//~^ ERROR can't find crate for `compiler_builtins` + +// compile-flags: --target thumbv7em-none-eabihf +// needs-llvm-components: arm +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_std] + +extern crate cortex_m; +//~^ ERROR can't find crate for `cortex_m` + +fn main() {} diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr new file mode 100644 index 000000000..fcfa2bf11 --- /dev/null +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr @@ -0,0 +1,19 @@ +error[E0463]: can't find crate for `core` + | + = note: the `thumbv7em-none-eabihf` target may not be installed + = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error[E0463]: can't find crate for `compiler_builtins` + +error[E0463]: can't find crate for `cortex_m` + --> $DIR/compiler-builtins-error.rs:10:1 + | +LL | extern crate cortex_m; + | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate + +error: requires `sized` lang_item + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-49854.rs b/tests/ui/issues/issue-49854.rs new file mode 100644 index 000000000..0e1db00a3 --- /dev/null +++ b/tests/ui/issues/issue-49854.rs @@ -0,0 +1,9 @@ +// run-pass +use std::ffi::OsString; + +fn main() { + let os_str = OsString::from("Hello Rust!"); + + assert_eq!(os_str, "Hello Rust!"); + assert_eq!("Hello Rust!", os_str); +} diff --git a/tests/ui/issues/issue-49919.rs b/tests/ui/issues/issue-49919.rs new file mode 100644 index 000000000..780f33868 --- /dev/null +++ b/tests/ui/issues/issue-49919.rs @@ -0,0 +1,7 @@ +fn foo<'a, T: 'a>(t: T) -> Box &'a T + 'a> { + let foo: Box Fn() -> &'c T> = Box::new(move || &t); + //~^ ERROR: binding for associated type + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/issues/issue-49919.stderr b/tests/ui/issues/issue-49919.stderr new file mode 100644 index 000000000..8098be5cc --- /dev/null +++ b/tests/ui/issues/issue-49919.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'c`, which does not appear in the trait input types + --> $DIR/issue-49919.rs:2:39 + | +LL | let foo: Box Fn() -> &'c T> = Box::new(move || &t); + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/issues/issue-49934-errors.rs b/tests/ui/issues/issue-49934-errors.rs new file mode 100644 index 000000000..dd14bac5e --- /dev/null +++ b/tests/ui/issues/issue-49934-errors.rs @@ -0,0 +1,8 @@ +fn foo<#[derive(Debug)] T>() { //~ ERROR expected non-macro attribute, found attribute macro + match 0 { + #[derive(Debug)] //~ ERROR expected non-macro attribute, found attribute macro + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-49934-errors.stderr b/tests/ui/issues/issue-49934-errors.stderr new file mode 100644 index 000000000..8c4c54170 --- /dev/null +++ b/tests/ui/issues/issue-49934-errors.stderr @@ -0,0 +1,14 @@ +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/issue-49934-errors.rs:1:10 + | +LL | fn foo<#[derive(Debug)] T>() { + | ^^^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/issue-49934-errors.rs:3:11 + | +LL | #[derive(Debug)] + | ^^^^^^ not a non-macro attribute + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-49934.rs b/tests/ui/issues/issue-49934.rs new file mode 100644 index 000000000..119d84a06 --- /dev/null +++ b/tests/ui/issues/issue-49934.rs @@ -0,0 +1,30 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + // fold_stmt (Item) + #[allow(dead_code)] + #[derive(Debug)] // should not warn + struct Foo; + + // fold_stmt (Mac) + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + println!("Hello, world!"); + + // fold_stmt (Semi) + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + "Hello, world!"; + + // fold_stmt (Local) + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + let _ = "Hello, world!"; + + // visit_expr + let _ = #[derive(Debug)] "Hello, world!"; + //~^ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + + let _ = [ + // filter_map_expr + #[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + "Hello, world!", + ]; +} diff --git a/tests/ui/issues/issue-49934.stderr b/tests/ui/issues/issue-49934.stderr new file mode 100644 index 000000000..f2ff541bb --- /dev/null +++ b/tests/ui/issues/issue-49934.stderr @@ -0,0 +1,43 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-49934.rs:10:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | println!("Hello, world!"); + | -------------------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-49934.rs:14:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | "Hello, world!"; + | ---------------- not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-49934.rs:18:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | let _ = "Hello, world!"; + | ------------------------ not a `struct`, `enum` or `union` + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-49934.rs:22:13 + | +LL | let _ = #[derive(Debug)] "Hello, world!"; + | ^^^^^^^^^^^^^^^^ --------------- not a `struct`, `enum` or `union` + | | + | not applicable here + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/issue-49934.rs:27:9 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | "Hello, world!", + | --------------- not a `struct`, `enum` or `union` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/issues/issue-49955.rs b/tests/ui/issues/issue-49955.rs new file mode 100644 index 000000000..f2f3ebff2 --- /dev/null +++ b/tests/ui/issues/issue-49955.rs @@ -0,0 +1,20 @@ +// run-pass + +const ALL_THE_NUMS: [u32; 1] = [ + 1 +]; + +#[inline(never)] +fn array(i: usize) -> &'static u32 { + return &ALL_THE_NUMS[i]; +} + +#[inline(never)] +fn tuple_field() -> &'static u32 { + &(42,).0 +} + +fn main() { + assert_eq!(tuple_field().to_string(), "42"); + assert_eq!(array(0).to_string(), "1"); +} diff --git a/tests/ui/issues/issue-49973.rs b/tests/ui/issues/issue-49973.rs new file mode 100644 index 000000000..af421c52f --- /dev/null +++ b/tests/ui/issues/issue-49973.rs @@ -0,0 +1,11 @@ +// run-pass +#[derive(Debug)] +#[repr(i32)] +enum E { + Min = -2147483648i32, + _Max = 2147483647i32, +} + +fn main() { + assert_eq!(Some(E::Min).unwrap() as i32, -2147483648i32); +} diff --git a/tests/ui/issues/issue-5008-borrowed-traitobject-method-call.rs b/tests/ui/issues/issue-5008-borrowed-traitobject-method-call.rs new file mode 100644 index 000000000..fc869ae4f --- /dev/null +++ b/tests/ui/issues/issue-5008-borrowed-traitobject-method-call.rs @@ -0,0 +1,34 @@ +// run-pass +/* + +#5008 cast to &Trait causes code to segfault on method call + +It fixes itself if the &Trait is changed to @Trait. +*/ + +trait Debuggable { + fn debug_name(&self) -> String; +} + +#[derive(Clone)] +struct Thing { + name: String, +} + +impl Thing { + fn new() -> Thing { Thing { name: "dummy".to_string() } } +} + +impl Debuggable for Thing { + fn debug_name(&self) -> String { self.name.clone() } +} + +fn print_name(x: &dyn Debuggable) +{ + println!("debug_name = {}", x.debug_name()); +} + +pub fn main() { + let thing = Thing::new(); + print_name(&thing as &dyn Debuggable); +} diff --git a/tests/ui/issues/issue-50187.rs b/tests/ui/issues/issue-50187.rs new file mode 100644 index 000000000..4b0aeaab4 --- /dev/null +++ b/tests/ui/issues/issue-50187.rs @@ -0,0 +1,39 @@ +// check-pass + +#![feature(decl_macro)] + +mod type_ns { + pub type A = u8; +} +mod value_ns { + pub const A: u8 = 0; +} +mod macro_ns { + pub macro A() {} +} + +mod merge2 { + pub use type_ns::A; + pub use value_ns::A; +} +mod merge3 { + pub use type_ns::A; + pub use value_ns::A; + pub use macro_ns::A; +} + +mod use2 { + pub use merge2::A; +} +mod use3 { + pub use merge3::A; +} + +fn main() { + type B2 = use2::A; + let a2 = use2::A; + + type B3 = use3::A; + let a3 = use3::A; + use3::A!(); +} diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs new file mode 100644 index 000000000..160cfc3d4 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs @@ -0,0 +1,4 @@ +fn main() { + let _result = &Some(42).as_deref(); +//~^ ERROR the method +} diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr new file mode 100644 index 000000000..ce8173169 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -0,0 +1,12 @@ +error[E0599]: the method `as_deref` exists for enum `Option<{integer}>`, but its trait bounds were not satisfied + --> $DIR/option-as_deref.rs:2:29 + | +LL | let _result = &Some(42).as_deref(); + | ^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `{integer}: Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs new file mode 100644 index 000000000..ff5095ce3 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs @@ -0,0 +1,4 @@ +fn main() { + let _result = &mut Some(42).as_deref_mut(); +//~^ ERROR the method +} diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr new file mode 100644 index 000000000..943f77486 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -0,0 +1,12 @@ +error[E0599]: the method `as_deref_mut` exists for enum `Option<{integer}>`, but its trait bounds were not satisfied + --> $DIR/option-as_deref_mut.rs:2:33 + | +LL | let _result = &mut Some(42).as_deref_mut(); + | ^^^^^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `{integer}: Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs new file mode 100644 index 000000000..4232f14d2 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs @@ -0,0 +1,4 @@ +fn main() { + let _result = &Ok(42).as_deref(); +//~^ ERROR the method +} diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr new file mode 100644 index 000000000..a3b9ac677 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -0,0 +1,12 @@ +error[E0599]: the method `as_deref` exists for enum `Result<{integer}, _>`, but its trait bounds were not satisfied + --> $DIR/result-as_deref.rs:2:27 + | +LL | let _result = &Ok(42).as_deref(); + | ^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `{integer}: Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs new file mode 100644 index 000000000..3507d1d8e --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs @@ -0,0 +1,4 @@ +fn main() { + let _result = &mut Ok(42).as_deref_mut(); +//~^ ERROR the method +} diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr new file mode 100644 index 000000000..aa771e4c0 --- /dev/null +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -0,0 +1,12 @@ +error[E0599]: the method `as_deref_mut` exists for enum `Result<{integer}, _>`, but its trait bounds were not satisfied + --> $DIR/result-as_deref_mut.rs:2:31 + | +LL | let _result = &mut Ok(42).as_deref_mut(); + | ^^^^^^^^^^^^ + | + = note: the following trait bounds were not satisfied: + `{integer}: Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50403.rs b/tests/ui/issues/issue-50403.rs new file mode 100644 index 000000000..012057fc2 --- /dev/null +++ b/tests/ui/issues/issue-50403.rs @@ -0,0 +1,5 @@ +#![feature(concat_idents)] + +fn main() { + let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments +} diff --git a/tests/ui/issues/issue-50403.stderr b/tests/ui/issues/issue-50403.stderr new file mode 100644 index 000000000..a3a2ed044 --- /dev/null +++ b/tests/ui/issues/issue-50403.stderr @@ -0,0 +1,8 @@ +error: concat_idents! takes 1 or more arguments + --> $DIR/issue-50403.rs:4:13 + | +LL | let x = concat_idents!(); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-50411.rs b/tests/ui/issues/issue-50411.rs new file mode 100644 index 000000000..cd728b152 --- /dev/null +++ b/tests/ui/issues/issue-50411.rs @@ -0,0 +1,11 @@ +// Regression test for #50411: the MIR inliner was causing problems +// here because it would inline promoted code (which had already had +// elaborate-drops invoked on it) and then try to elaboate drops a +// second time. Uncool. + +// compile-flags:-Zmir-opt-level=4 +// build-pass + +fn main() { + let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count(); +} diff --git a/tests/ui/issues/issue-50415.rs b/tests/ui/issues/issue-50415.rs new file mode 100644 index 000000000..151b9fe44 --- /dev/null +++ b/tests/ui/issues/issue-50415.rs @@ -0,0 +1,16 @@ +// run-pass +fn main() { + // Simplified test case + let _ = || 0..=1; + + // Original test case + let full_length = 1024; + let range = { + // do some stuff, omit here + None + }; + + let range = range.map(|(s, t)| s..=t).unwrap_or(0..=(full_length-1)); + + assert_eq!(range, 0..=1023); +} diff --git a/tests/ui/issues/issue-50442.rs b/tests/ui/issues/issue-50442.rs new file mode 100644 index 000000000..25c7dde7a --- /dev/null +++ b/tests/ui/issues/issue-50442.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +enum Void {} + +enum Foo { + A(i32), + B(Void), + C(i32) +} + +fn main() { + let _foo = Foo::A(0); +} diff --git a/tests/ui/issues/issue-50471.rs b/tests/ui/issues/issue-50471.rs new file mode 100644 index 000000000..7278c392d --- /dev/null +++ b/tests/ui/issues/issue-50471.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + assert!({false}); + + assert!(r"\u{41}" == "A"); + + assert!(r"\u{".is_empty()); +} diff --git a/tests/ui/issues/issue-50518.rs b/tests/ui/issues/issue-50518.rs new file mode 100644 index 000000000..1e7b77949 --- /dev/null +++ b/tests/ui/issues/issue-50518.rs @@ -0,0 +1,40 @@ +// check-pass +use std::marker::PhantomData; + +struct Meta { + value: i32, + type_: PhantomData +} + +trait MetaTrait { + fn get_value(&self) -> i32; +} + +impl MetaTrait for Meta { + fn get_value(&self) -> i32 { self.value } +} + +trait Bar { + fn get_const(&self) -> &dyn MetaTrait; +} + +struct Foo { + _value: A +} + +impl Foo { + const CONST: &'static dyn MetaTrait = &Meta:: { + value: 10, + type_: PhantomData + }; +} + +impl Bar for Foo { + fn get_const(&self) -> &dyn MetaTrait { Self::CONST } +} + +fn main() { + let foo = Foo:: { _value: 10 }; + let bar: &dyn Bar = &foo; + println!("const {}", bar.get_const().get_value()); +} diff --git a/tests/ui/issues/issue-50571.fixed b/tests/ui/issues/issue-50571.fixed new file mode 100644 index 000000000..2f8c925b8 --- /dev/null +++ b/tests/ui/issues/issue-50571.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +trait Foo { + fn foo(_: [i32; 2]) {} + //~^ ERROR: patterns aren't allowed in methods without bodies +} + +fn main() {} diff --git a/tests/ui/issues/issue-50571.rs b/tests/ui/issues/issue-50571.rs new file mode 100644 index 000000000..56f422e7d --- /dev/null +++ b/tests/ui/issues/issue-50571.rs @@ -0,0 +1,8 @@ +// run-rustfix + +trait Foo { + fn foo([a, b]: [i32; 2]) {} + //~^ ERROR: patterns aren't allowed in methods without bodies +} + +fn main() {} diff --git a/tests/ui/issues/issue-50571.stderr b/tests/ui/issues/issue-50571.stderr new file mode 100644 index 000000000..f69963bb7 --- /dev/null +++ b/tests/ui/issues/issue-50571.stderr @@ -0,0 +1,14 @@ +error[E0642]: patterns aren't allowed in methods without bodies + --> $DIR/issue-50571.rs:4:12 + | +LL | fn foo([a, b]: [i32; 2]) {} + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL | fn foo(_: [i32; 2]) {} + | ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/issues/issue-50576.rs b/tests/ui/issues/issue-50576.rs new file mode 100644 index 000000000..e0c36b827 --- /dev/null +++ b/tests/ui/issues/issue-50576.rs @@ -0,0 +1,6 @@ +fn main() { + |bool: [u8; break 'L]| 0; + //~^ ERROR [E0426] + //~| ERROR [E0268] + Vec::<[u8; break]>::new(); //~ ERROR [E0268] +} diff --git a/tests/ui/issues/issue-50576.stderr b/tests/ui/issues/issue-50576.stderr new file mode 100644 index 000000000..4ec22fde9 --- /dev/null +++ b/tests/ui/issues/issue-50576.stderr @@ -0,0 +1,22 @@ +error[E0426]: use of undeclared label `'L` + --> $DIR/issue-50576.rs:2:23 + | +LL | |bool: [u8; break 'L]| 0; + | ^^ undeclared label `'L` + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-50576.rs:2:17 + | +LL | |bool: [u8; break 'L]| 0; + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-50576.rs:5:16 + | +LL | Vec::<[u8; break]>::new(); + | ^^^^^ cannot `break` outside of a loop or labeled block + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0268, E0426. +For more information about an error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-50581.rs b/tests/ui/issues/issue-50581.rs new file mode 100644 index 000000000..12bb9930e --- /dev/null +++ b/tests/ui/issues/issue-50581.rs @@ -0,0 +1,3 @@ +fn main() { + |_: [u8; break]| (); //~ ERROR [E0268] +} diff --git a/tests/ui/issues/issue-50581.stderr b/tests/ui/issues/issue-50581.stderr new file mode 100644 index 000000000..07b6df072 --- /dev/null +++ b/tests/ui/issues/issue-50581.stderr @@ -0,0 +1,9 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-50581.rs:2:14 + | +LL | |_: [u8; break]| (); + | ^^^^^ cannot `break` outside of a loop or labeled block + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-50582.rs b/tests/ui/issues/issue-50582.rs new file mode 100644 index 000000000..2d5c93587 --- /dev/null +++ b/tests/ui/issues/issue-50582.rs @@ -0,0 +1,5 @@ +fn main() { + Vec::<[(); 1 + for x in 0..1 {}]>::new(); + //~^ ERROR cannot add + //~| ERROR `for` is not allowed in a `const` +} diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr new file mode 100644 index 000000000..53ecc6112 --- /dev/null +++ b/tests/ui/issues/issue-50582.stderr @@ -0,0 +1,31 @@ +error[E0658]: `for` is not allowed in a `const` + --> $DIR/issue-50582.rs:2:20 + | +LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error[E0277]: cannot add `()` to `{integer}` in const contexts + --> $DIR/issue-50582.rs:2:18 + | +LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); + | ^ no implementation for `{integer} + ()` + | + = help: the trait `~const Add<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-50585.rs b/tests/ui/issues/issue-50585.rs new file mode 100644 index 000000000..a2f11c98d --- /dev/null +++ b/tests/ui/issues/issue-50585.rs @@ -0,0 +1,5 @@ +fn main() { + |y: Vec<[(); for x in 0..2 {}]>| {}; + //~^ ERROR mismatched types + //~| ERROR `for` is not allowed in a `const` +} diff --git a/tests/ui/issues/issue-50585.stderr b/tests/ui/issues/issue-50585.stderr new file mode 100644 index 000000000..e43cc20cb --- /dev/null +++ b/tests/ui/issues/issue-50585.stderr @@ -0,0 +1,19 @@ +error[E0658]: `for` is not allowed in a `const` + --> $DIR/issue-50585.rs:2:18 + | +LL | |y: Vec<[(); for x in 0..2 {}]>| {}; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-50585.rs:2:18 + | +LL | |y: Vec<[(); for x in 0..2 {}]>| {}; + | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-50600.rs b/tests/ui/issues/issue-50600.rs new file mode 100644 index 000000000..963e607af --- /dev/null +++ b/tests/ui/issues/issue-50600.rs @@ -0,0 +1,5 @@ +struct Foo ( + fn([u8; |x: u8| {}]), //~ ERROR mismatched types +); + +fn main() {} diff --git a/tests/ui/issues/issue-50600.stderr b/tests/ui/issues/issue-50600.stderr new file mode 100644 index 000000000..7fea7e5c0 --- /dev/null +++ b/tests/ui/issues/issue-50600.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-50600.rs:2:13 + | +LL | fn([u8; |x: u8| {}]), + | ^^^^^^^^^^ expected `usize`, found closure + | + = note: expected type `usize` + found closure `[closure@$DIR/issue-50600.rs:2:13: 2:20]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-50618.rs b/tests/ui/issues/issue-50618.rs new file mode 100644 index 000000000..5f762bc43 --- /dev/null +++ b/tests/ui/issues/issue-50618.rs @@ -0,0 +1,19 @@ +struct Point { + pub x: u64, + pub y: u64, +} + +const TEMPLATE: Point = Point { + x: 0, + y: 0 +}; + +fn main() { + let _ = || { + Point { + nonexistent: 0, + //~^ ERROR struct `Point` has no field named `nonexistent` + ..TEMPLATE + } + }; +} diff --git a/tests/ui/issues/issue-50618.stderr b/tests/ui/issues/issue-50618.stderr new file mode 100644 index 000000000..1ac5dde66 --- /dev/null +++ b/tests/ui/issues/issue-50618.stderr @@ -0,0 +1,11 @@ +error[E0560]: struct `Point` has no field named `nonexistent` + --> $DIR/issue-50618.rs:14:13 + | +LL | nonexistent: 0, + | ^^^^^^^^^^^ `Point` does not have this field + | + = note: available fields are: `x`, `y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/issues/issue-5062.rs b/tests/ui/issues/issue-5062.rs new file mode 100644 index 000000000..2db0a8e25 --- /dev/null +++ b/tests/ui/issues/issue-5062.rs @@ -0,0 +1,2 @@ +fn main() { format!("{:?}", None); } + //~^ ERROR type annotations needed [E0282] diff --git a/tests/ui/issues/issue-5062.stderr b/tests/ui/issues/issue-5062.stderr new file mode 100644 index 000000000..3191bd3de --- /dev/null +++ b/tests/ui/issues/issue-5062.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-5062.rs:1:29 + | +LL | fn main() { format!("{:?}", None); } + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | fn main() { format!("{:?}", None::); } + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-5067.rs b/tests/ui/issues/issue-5067.rs new file mode 100644 index 000000000..5857a0815 --- /dev/null +++ b/tests/ui/issues/issue-5067.rs @@ -0,0 +1,75 @@ +#![allow(unused_macros)] + +// Tests that repetition matchers cannot match the empty token tree (since that would be +// ambiguous). + +// edition:2018 + +macro_rules! foo { + ( $()* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $()+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $()? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(),* ) => {}; // PASS + ( $(),+ ) => {}; // PASS + // `?` cannot have a separator... + ( [$()*] ) => {}; + //~^ ERROR repetition matches empty token tree + ( [$()+] ) => {}; + //~^ ERROR repetition matches empty token tree + ( [$()?] ) => {}; + //~^ ERROR repetition matches empty token tree + ( [$(),*] ) => {}; // PASS + ( [$(),+] ) => {}; // PASS + // `?` cannot have a separator... + ( $($()* $(),* $(a)* $(a),* )* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()* $(),* $(a)* $(a),* )+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()* $(),* $(a)* $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS + ( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS + + ( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS + + ( $(a $()+)* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $()*)+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $()+)? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $()?)+ ) => {}; + //~^ ERROR repetition matches empty token tree +} + +// Original Issue + +macro_rules! make_vec { + (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); + //~^ ERROR repetition matches empty token tree +} + +fn main() { + let _ = make_vec![a 1, a 2, a 3]; +} + +// Minified Issue + +macro_rules! m { + ( $()* ) => {}; + //~^ ERROR repetition matches empty token tree +} + +m!(); diff --git a/tests/ui/issues/issue-5067.stderr b/tests/ui/issues/issue-5067.stderr new file mode 100644 index 000000000..7ffc60714 --- /dev/null +++ b/tests/ui/issues/issue-5067.stderr @@ -0,0 +1,110 @@ +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:9:8 + | +LL | ( $()* ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:11:8 + | +LL | ( $()+ ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:13:8 + | +LL | ( $()? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:18:9 + | +LL | ( [$()*] ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:20:9 + | +LL | ( [$()+] ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:22:9 + | +LL | ( [$()?] ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:27:8 + | +LL | ( $($()* $(),* $(a)* $(a),* )* ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:29:8 + | +LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:31:8 + | +LL | ( $($()* $(),* $(a)* $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:33:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )* ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:35:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:37:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:47:12 + | +LL | ( $(a $()+)* ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:49:12 + | +LL | ( $(a $()*)+ ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:51:12 + | +LL | ( $(a $()+)? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:53:12 + | +LL | ( $(a $()?)+ ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:60:18 + | +LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:71:8 + | +LL | ( $()* ) => {}; + | ^^ + +error: aborting due to 18 previous errors + diff --git a/tests/ui/issues/issue-50688.rs b/tests/ui/issues/issue-50688.rs new file mode 100644 index 000000000..88f898b86 --- /dev/null +++ b/tests/ui/issues/issue-50688.rs @@ -0,0 +1,3 @@ +fn main() { + [1; || {}]; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-50688.stderr b/tests/ui/issues/issue-50688.stderr new file mode 100644 index 000000000..6973ad271 --- /dev/null +++ b/tests/ui/issues/issue-50688.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-50688.rs:2:9 + | +LL | [1; || {}]; + | ^^^^^ expected `usize`, found closure + | + = note: expected type `usize` + found closure `[closure@$DIR/issue-50688.rs:2:9: 2:11]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-50689.rs b/tests/ui/issues/issue-50689.rs new file mode 100644 index 000000000..b49f29500 --- /dev/null +++ b/tests/ui/issues/issue-50689.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_variables)] +enum Foo { + Bar = (|x: i32| { }, 42).1, +} + +fn main() { + assert_eq!(Foo::Bar as usize, 42); +} diff --git a/tests/ui/issues/issue-50714-1.rs b/tests/ui/issues/issue-50714-1.rs new file mode 100644 index 000000000..a25940ce1 --- /dev/null +++ b/tests/ui/issues/issue-50714-1.rs @@ -0,0 +1,11 @@ +// Regression test for issue 50714, make sure that this isn't a linker error. + +#![no_std] +#![feature(start)] + +extern crate std; + +#[start] +fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { //~ ERROR [E0647] + 0 +} diff --git a/tests/ui/issues/issue-50714-1.stderr b/tests/ui/issues/issue-50714-1.stderr new file mode 100644 index 000000000..28469bee0 --- /dev/null +++ b/tests/ui/issues/issue-50714-1.stderr @@ -0,0 +1,9 @@ +error[E0647]: start function is not allowed to have a `where` clause + --> $DIR/issue-50714-1.rs:9:50 + | +LL | fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { + | ^^^^^^^^^^^^^^^^^ start function cannot have a `where` clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0647`. diff --git a/tests/ui/issues/issue-50714.rs b/tests/ui/issues/issue-50714.rs new file mode 100644 index 000000000..c571a470c --- /dev/null +++ b/tests/ui/issues/issue-50714.rs @@ -0,0 +1,3 @@ +// Regression test for issue 50714, make sure that this isn't a linker error. + +fn main() where fn(&()): Eq {} //~ ERROR [E0646] diff --git a/tests/ui/issues/issue-50714.stderr b/tests/ui/issues/issue-50714.stderr new file mode 100644 index 000000000..a11aceb62 --- /dev/null +++ b/tests/ui/issues/issue-50714.stderr @@ -0,0 +1,9 @@ +error[E0646]: `main` function is not allowed to have a `where` clause + --> $DIR/issue-50714.rs:3:11 + | +LL | fn main() where fn(&()): Eq {} + | ^^^^^^^^^^^^^^^^^ `main` cannot have a `where` clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0646`. diff --git a/tests/ui/issues/issue-50761.rs b/tests/ui/issues/issue-50761.rs new file mode 100644 index 000000000..1bf494ba8 --- /dev/null +++ b/tests/ui/issues/issue-50761.rs @@ -0,0 +1,23 @@ +// Confirm that we don't accidentally divide or mod by zero in llvm_type + +// build-pass + +mod a { + pub trait A {} +} + +mod b { + pub struct Builder {} + + pub fn new() -> Builder { + Builder {} + } + + impl Builder { + pub fn with_a(&mut self, _a: fn() -> dyn (::a::A)) {} + } +} + +pub use self::b::new; + +fn main() {} diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/issues/issue-50781.rs new file mode 100644 index 000000000..3c5e5a9f6 --- /dev/null +++ b/tests/ui/issues/issue-50781.rs @@ -0,0 +1,19 @@ +#![deny(where_clauses_object_safety)] + +trait Trait {} + +trait X { + fn foo(&self) where Self: Trait; //~ ERROR the trait `X` cannot be made into an object + //~^ WARN this was previously accepted by the compiler but is being phased out +} + +impl X for () { + fn foo(&self) {} +} + +impl Trait for dyn X {} + +pub fn main() { + // Check that this does not segfault. + ::foo(&()); +} diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr new file mode 100644 index 000000000..e185ecdda --- /dev/null +++ b/tests/ui/issues/issue-50781.stderr @@ -0,0 +1,24 @@ +error: the trait `X` cannot be made into an object + --> $DIR/issue-50781.rs:6:8 + | +LL | fn foo(&self) where Self: Trait; + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #51443 +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-50781.rs:6:8 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | fn foo(&self) where Self: Trait; + | ^^^ ...because method `foo` references the `Self` type in its `where` clause + = help: consider moving `foo` to another trait +note: the lint level is defined here + --> $DIR/issue-50781.rs:1:9 + | +LL | #![deny(where_clauses_object_safety)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-50802.rs b/tests/ui/issues/issue-50802.rs new file mode 100644 index 000000000..dece55968 --- /dev/null +++ b/tests/ui/issues/issue-50802.rs @@ -0,0 +1,8 @@ +#[allow(unreachable_code)] + +fn main() { + loop { + break while continue { //~ ERROR E0590 + } + } +} diff --git a/tests/ui/issues/issue-50802.stderr b/tests/ui/issues/issue-50802.stderr new file mode 100644 index 000000000..e064fabcc --- /dev/null +++ b/tests/ui/issues/issue-50802.stderr @@ -0,0 +1,9 @@ +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/issue-50802.rs:5:21 + | +LL | break while continue { + | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0590`. diff --git a/tests/ui/issues/issue-50811.rs b/tests/ui/issues/issue-50811.rs new file mode 100644 index 000000000..683c85604 --- /dev/null +++ b/tests/ui/issues/issue-50811.rs @@ -0,0 +1,55 @@ +// run-pass +#![feature(test)] + +extern crate test; + +use std::mem::size_of; +use test::black_box; + +// Ensure the const-eval result and runtime result of float comparison are equivalent. + +macro_rules! compare { + ($op:tt) => { + compare!( + [f64::NEG_INFINITY, -f64::MAX, -1.0, -0.0, 0.0, 1.0, f64::MAX, f64::INFINITY, f64::NAN], + $op + ); + }; + ([$($lhs:expr),+], $op:tt) => { + $(compare!( + $lhs, + $op, + [f64::NEG_INFINITY, -f64::MAX, -1.0, -0.0, 0.0, 1.0, f64::MAX, f64::INFINITY, f64::NAN] + );)+ + }; + ($lhs:expr, $op:tt, [$($rhs:expr),+]) => { + $({ + // Wrap the check in its own function to reduce time needed to borrowck. + fn check() { + static CONST_EVAL: bool = $lhs $op $rhs; + let runtime_eval = black_box($lhs) $op black_box($rhs); + assert_eq!(CONST_EVAL, runtime_eval, stringify!($lhs $op $rhs)); + assert_eq!( + size_of::<[u8; ($lhs $op $rhs) as usize]>(), + runtime_eval as usize, + stringify!($lhs $op $rhs (forced const eval)) + ); + } + check(); + })+ + }; +} + +fn main() { + assert_eq!(0.0/0.0 < 0.0/0.0, false); + assert_eq!(0.0/0.0 > 0.0/0.0, false); + assert_eq!(f64::NAN < f64::NAN, false); + assert_eq!(f64::NAN > f64::NAN, false); + + compare!(==); + compare!(!=); + compare!(<); + compare!(<=); + compare!(>); + compare!(>=); +} diff --git a/tests/ui/issues/issue-50825-1.rs b/tests/ui/issues/issue-50825-1.rs new file mode 100644 index 000000000..ee4316029 --- /dev/null +++ b/tests/ui/issues/issue-50825-1.rs @@ -0,0 +1,22 @@ +// run-pass +// regression test for issue #50825 +// Make sure that the `impl` bound (): X is preferred over +// the (): X bound in the where clause. + +trait X { + type T; +} + +trait Y: X { + fn foo(x: &Self::T); +} + +impl X for () { + type T = (); +} + +impl Y> for () where (): Y { + fn foo(_x: &()) {} +} + +fn main () {} diff --git a/tests/ui/issues/issue-50825.rs b/tests/ui/issues/issue-50825.rs new file mode 100644 index 000000000..1ece2e9fc --- /dev/null +++ b/tests/ui/issues/issue-50825.rs @@ -0,0 +1,15 @@ +// run-pass +// regression test for issue #50825 +// Make sure that the built-in bound {integer}: Sized is preferred over +// the u64: Sized bound in the where clause. + +fn foo(y: &[()]) +where + u64: Sized, +{ + y[0] +} + +fn main () { + foo(&[()]); +} diff --git a/tests/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs b/tests/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs new file mode 100644 index 000000000..1e20a5460 --- /dev/null +++ b/tests/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs @@ -0,0 +1,18 @@ +// revisions: default miropt +//[miropt]compile-flags: -Z mir-opt-level=3 +// ~^ This flag is for #77668, it used to be ICE. + +#![crate_type = "lib"] + +pub fn bar

( // Error won't happen if "bar" is not generic + _baz: P, +) { + hide_foo()(); +} + +fn hide_foo() -> impl Fn() { // Error won't happen if "iterate" hasn't impl Trait or has generics + foo +} + +fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics +} diff --git a/tests/ui/issues/issue-50865-private-impl-trait/main.rs b/tests/ui/issues/issue-50865-private-impl-trait/main.rs new file mode 100644 index 000000000..16dfac53a --- /dev/null +++ b/tests/ui/issues/issue-50865-private-impl-trait/main.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:lib.rs + +// Regression test for #50865. +// When using generics or specifying the type directly, this example +// codegens `foo` internally. However, when using a private `impl Trait` +// function which references another private item, `foo` (in this case) +// wouldn't be codegenned until main.rs used `bar`, as with impl Trait +// it is not cast to `fn()` automatically to satisfy e.g. +// `fn foo() -> fn() { ... }`. + +extern crate lib; + +fn main() { + lib::bar(()); // Error won't happen if bar is called from same crate +} diff --git a/tests/ui/issues/issue-5100.rs b/tests/ui/issues/issue-5100.rs new file mode 100644 index 000000000..69ed4b0e4 --- /dev/null +++ b/tests/ui/issues/issue-5100.rs @@ -0,0 +1,57 @@ +#![feature(box_patterns)] + + +enum A { B, C } + +fn main() { + match (true, false) { + A::B => (), +//~^ ERROR mismatched types +//~| expected tuple, found enum `A` +//~| expected tuple `(bool, bool)` +//~| found enum `A` + _ => () + } + + match (true, false) { + (true, false, false) => () +//~^ ERROR mismatched types +//~| expected a tuple with 2 elements, found one with 3 elements +//~| expected tuple `(bool, bool)` +//~| found tuple `(_, _, _)` + } + + match (true, false) { + (true, false, false) => () +//~^ ERROR mismatched types +//~| expected a tuple with 2 elements, found one with 3 elements +//~| expected tuple `(bool, bool)` +//~| found tuple `(_, _, _)` + } + + match (true, false) { + box (true, false) => () +//~^ ERROR mismatched types +//~| expected tuple `(bool, bool)` +//~| found struct `Box<_>` + } + + match (true, false) { + &(true, false) => () +//~^ ERROR mismatched types +//~| expected tuple, found reference +//~| expected tuple `(bool, bool)` +//~| found reference `&_` + } + + + let v = [('a', 'b') //~ ERROR expected function, found `(char, char)` + ('c', 'd'), + ('e', 'f')]; + + for &(x,y) in &v {} // should be OK + + // Make sure none of the errors above were fatal + let x: char = true; //~ ERROR mismatched types + //~| expected `char`, found `bool` +} diff --git a/tests/ui/issues/issue-5100.stderr b/tests/ui/issues/issue-5100.stderr new file mode 100644 index 000000000..c87a3e348 --- /dev/null +++ b/tests/ui/issues/issue-5100.stderr @@ -0,0 +1,76 @@ +error[E0308]: mismatched types + --> $DIR/issue-5100.rs:8:9 + | +LL | enum A { B, C } + | - unit variant defined here +... +LL | match (true, false) { + | ------------- this expression has type `(bool, bool)` +LL | A::B => (), + | ^^^^ expected tuple, found enum `A` + | + = note: expected tuple `(bool, bool)` + found enum `A` + +error[E0308]: mismatched types + --> $DIR/issue-5100.rs:17:9 + | +LL | match (true, false) { + | ------------- this expression has type `(bool, bool)` +LL | (true, false, false) => () + | ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `(bool, bool)` + found tuple `(_, _, _)` + +error[E0308]: mismatched types + --> $DIR/issue-5100.rs:25:9 + | +LL | match (true, false) { + | ------------- this expression has type `(bool, bool)` +LL | (true, false, false) => () + | ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `(bool, bool)` + found tuple `(_, _, _)` + +error[E0308]: mismatched types + --> $DIR/issue-5100.rs:33:9 + | +LL | match (true, false) { + | ------------- this expression has type `(bool, bool)` +LL | box (true, false) => () + | ^^^^^^^^^^^^^^^^^ expected tuple, found struct `Box` + | + = note: expected tuple `(bool, bool)` + found struct `Box<_>` + +error[E0308]: mismatched types + --> $DIR/issue-5100.rs:40:9 + | +LL | match (true, false) { + | ------------- this expression has type `(bool, bool)` +LL | &(true, false) => () + | ^^^^^^^^^^^^^^ expected tuple, found reference + | + = note: expected tuple `(bool, bool)` + found reference `&_` + +error[E0618]: expected function, found `(char, char)` + --> $DIR/issue-5100.rs:48:14 + | +LL | let v = [('a', 'b') + | ^^^^^^^^^^- help: consider separating array elements with a comma: `,` + +error[E0308]: mismatched types + --> $DIR/issue-5100.rs:55:19 + | +LL | let x: char = true; + | ---- ^^^^ expected `char`, found `bool` + | | + | expected due to this + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0308, E0618. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-51022.rs b/tests/ui/issues/issue-51022.rs new file mode 100644 index 000000000..cebdfe00c --- /dev/null +++ b/tests/ui/issues/issue-51022.rs @@ -0,0 +1,2 @@ +fn main<'a>() { } + //~^ ERROR `main` function is not allowed to have generic parameters [E0131] diff --git a/tests/ui/issues/issue-51022.stderr b/tests/ui/issues/issue-51022.stderr new file mode 100644 index 000000000..5e196bd4e --- /dev/null +++ b/tests/ui/issues/issue-51022.stderr @@ -0,0 +1,9 @@ +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-51022.rs:1:8 + | +LL | fn main<'a>() { } + | ^^^^ `main` cannot have generic parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0131`. diff --git a/tests/ui/issues/issue-51044.rs b/tests/ui/issues/issue-51044.rs new file mode 100644 index 000000000..628d78769 --- /dev/null +++ b/tests/ui/issues/issue-51044.rs @@ -0,0 +1,30 @@ +// run-pass +// regression test for issue #50825 +// Check that the feature gate normalizes associated types. + +#![allow(dead_code)] +struct Foo(T); +struct Duck; +struct Quack; + +trait Hello where A: Animal { +} + +trait Animal { + type Noise; +} + +trait Loud { +} + +impl Loud for f32 { +} + +impl Animal for Duck { + type Noise = Quack; +} + +impl Hello for Foo where f32: Loud<::Noise> { +} + +fn main() {} diff --git a/tests/ui/issues/issue-51102.rs b/tests/ui/issues/issue-51102.rs new file mode 100644 index 000000000..41446cd29 --- /dev/null +++ b/tests/ui/issues/issue-51102.rs @@ -0,0 +1,38 @@ +enum SimpleEnum { + NoState, +} + +struct SimpleStruct { + no_state_here: u64, +} + +fn main() { + let _ = |simple| { + match simple { + SimpleStruct { + state: 0, + //~^ struct `SimpleStruct` does not have a field named `state` [E0026] + .. + } => (), + } + }; + + let _ = |simple| { + match simple { + SimpleStruct { + no_state_here: 0, + no_state_here: 1 + //~^ ERROR field `no_state_here` bound multiple times in the pattern [E0025] + } => (), + } + }; + + let _ = |simple| { + match simple { + SimpleEnum::NoState { + state: 0 + //~^ ERROR variant `SimpleEnum::NoState` does not have a field named `state` [E0026] + } => (), + } + }; +} diff --git a/tests/ui/issues/issue-51102.stderr b/tests/ui/issues/issue-51102.stderr new file mode 100644 index 000000000..09c52292d --- /dev/null +++ b/tests/ui/issues/issue-51102.stderr @@ -0,0 +1,27 @@ +error[E0026]: struct `SimpleStruct` does not have a field named `state` + --> $DIR/issue-51102.rs:13:17 + | +LL | state: 0, + | ^^^^^ + | | + | struct `SimpleStruct` does not have this field + | help: `SimpleStruct` has a field named `no_state_here` + +error[E0025]: field `no_state_here` bound multiple times in the pattern + --> $DIR/issue-51102.rs:24:17 + | +LL | no_state_here: 0, + | ---------------- first use of `no_state_here` +LL | no_state_here: 1 + | ^^^^^^^^^^^^^^^^ multiple uses of `no_state_here` in pattern + +error[E0026]: variant `SimpleEnum::NoState` does not have a field named `state` + --> $DIR/issue-51102.rs:33:17 + | +LL | state: 0 + | ^^^^^ variant `SimpleEnum::NoState` does not have this field + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0025, E0026. +For more information about an error, try `rustc --explain E0025`. diff --git a/tests/ui/issues/issue-51116.rs b/tests/ui/issues/issue-51116.rs new file mode 100644 index 000000000..4c21cbfc6 --- /dev/null +++ b/tests/ui/issues/issue-51116.rs @@ -0,0 +1,12 @@ +fn main() { + let tiles = Default::default(); + for row in &mut tiles { + for tile in row { + *tile = 0; + //~^ ERROR type annotations needed + //~| NOTE cannot infer type + } + } + + let tiles: [[usize; 3]; 3] = tiles; +} diff --git a/tests/ui/issues/issue-51116.stderr b/tests/ui/issues/issue-51116.stderr new file mode 100644 index 000000000..c07f8735e --- /dev/null +++ b/tests/ui/issues/issue-51116.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/issue-51116.rs:5:13 + | +LL | *tile = 0; + | ^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-51154.rs b/tests/ui/issues/issue-51154.rs new file mode 100644 index 000000000..12903f790 --- /dev/null +++ b/tests/ui/issues/issue-51154.rs @@ -0,0 +1,6 @@ +fn foo() { + let _: Box = Box::new(|| ()); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/issues/issue-51154.stderr b/tests/ui/issues/issue-51154.stderr new file mode 100644 index 000000000..d8a833a86 --- /dev/null +++ b/tests/ui/issues/issue-51154.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-51154.rs:2:30 + | +LL | fn foo() { + | - this type parameter +LL | let _: Box = Box::new(|| ()); + | -------- ^^^^^ expected type parameter `F`, found closure + | | + | arguments to this function are incorrect + | + = note: expected type parameter `F` + found closure `[closure@$DIR/issue-51154.rs:2:30: 2:32]` + = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F` +note: associated function defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-51515.rs b/tests/ui/issues/issue-51515.rs new file mode 100644 index 000000000..797c1085d --- /dev/null +++ b/tests/ui/issues/issue-51515.rs @@ -0,0 +1,10 @@ +fn main() { + let foo = &16; + //~^ HELP consider changing this to be a mutable reference + //~| SUGGESTION &mut 16 + *foo = 32; + //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference + let bar = foo; + *bar = 64; + //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference +} diff --git a/tests/ui/issues/issue-51515.stderr b/tests/ui/issues/issue-51515.stderr new file mode 100644 index 000000000..c4e61e719 --- /dev/null +++ b/tests/ui/issues/issue-51515.stderr @@ -0,0 +1,22 @@ +error[E0594]: cannot assign to `*foo`, which is behind a `&` reference + --> $DIR/issue-51515.rs:5:5 + | +LL | *foo = 32; + | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let foo = &mut 16; + | ~~~~~~~ + +error[E0594]: cannot assign to `*bar`, which is behind a `&` reference + --> $DIR/issue-51515.rs:8:5 + | +LL | let bar = foo; + | --- consider changing this binding's type to be: `&mut i32` +LL | *bar = 64; + | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/issues/issue-5153.rs b/tests/ui/issues/issue-5153.rs new file mode 100644 index 000000000..5bf057903 --- /dev/null +++ b/tests/ui/issues/issue-5153.rs @@ -0,0 +1,12 @@ +trait Foo { + fn foo(self: Box); +} + +impl Foo for isize { + fn foo(self: Box) { } +} + +fn main() { + (&5isize as &dyn Foo).foo(); + //~^ ERROR: no method named `foo` found for reference `&dyn Foo` in the current scope +} diff --git a/tests/ui/issues/issue-5153.stderr b/tests/ui/issues/issue-5153.stderr new file mode 100644 index 000000000..93aaf4b9d --- /dev/null +++ b/tests/ui/issues/issue-5153.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope + --> $DIR/issue-5153.rs:10:27 + | +LL | fn foo(self: Box); + | --------- the method might not be found because of this arbitrary self type +... +LL | (&5isize as &dyn Foo).foo(); + | ^^^ method not found in `&dyn Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.rs b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.rs new file mode 100644 index 000000000..35402dff6 --- /dev/null +++ b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] + +fn missing_discourses() -> Result { + Ok(1) +} + +fn forbidden_narratives() -> Result { + missing_discourses()? + //~^ ERROR: `?` operator has incompatible types +} + +fn main() {} diff --git a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr new file mode 100644 index 000000000..cc0726bca --- /dev/null +++ b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr @@ -0,0 +1,22 @@ +error[E0308]: `?` operator has incompatible types + --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5 + | +LL | missing_discourses()? + | ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize` + | + = note: `?` operator cannot convert from `isize` to `Result` + = note: expected enum `Result` + found type `isize` +help: try removing this `?` + | +LL - missing_discourses()? +LL + missing_discourses() + | +help: try wrapping the expression in `Ok` + | +LL | Ok(missing_discourses()?) + | +++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-51655.rs b/tests/ui/issues/issue-51655.rs new file mode 100644 index 000000000..36fd90dab --- /dev/null +++ b/tests/ui/issues/issue-51655.rs @@ -0,0 +1,14 @@ +// check-pass +#![allow(dead_code)] + +const PATH_DOT: &[u8] = &[b'.']; + +fn match_slice(element: &[u8]) { + match element { + &[] => {} + PATH_DOT => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-51714.rs b/tests/ui/issues/issue-51714.rs new file mode 100644 index 000000000..8716524d6 --- /dev/null +++ b/tests/ui/issues/issue-51714.rs @@ -0,0 +1,21 @@ +fn main() { +//~^ NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body + |_: [_; return || {}] | {}; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + + [(); return || {}]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + + [(); return |ice| {}]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + + [(); return while let Some(n) = Some(0) {}]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... +} diff --git a/tests/ui/issues/issue-51714.stderr b/tests/ui/issues/issue-51714.stderr new file mode 100644 index 000000000..514d69c1c --- /dev/null +++ b/tests/ui/issues/issue-51714.stderr @@ -0,0 +1,63 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-51714.rs:6:14 + | +LL | / fn main() { +LL | | +LL | | +LL | | +LL | | +LL | | |_: [_; return || {}] | {}; + | | ^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-51714.rs:10:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return || {}]; + | | ^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-51714.rs:14:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return |ice| {}]; + | | ^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-51714.rs:18:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return while let Some(n) = Some(0) {}]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/issues/issue-51798.rs b/tests/ui/issues/issue-51798.rs new file mode 100644 index 000000000..b075809e9 --- /dev/null +++ b/tests/ui/issues/issue-51798.rs @@ -0,0 +1,14 @@ +// edition:2018 +// aux-build:issue-51798.rs +// check-pass + +extern crate issue_51798; + +mod server { + fn f() { + let mut v = issue_51798::vec(); + v.clear(); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-51874.rs b/tests/ui/issues/issue-51874.rs new file mode 100644 index 000000000..d9d7e36b5 --- /dev/null +++ b/tests/ui/issues/issue-51874.rs @@ -0,0 +1,3 @@ +fn main() { + let a = (1.0).pow(1.0); //~ ERROR can't call method `pow` on ambiguous numeric type +} diff --git a/tests/ui/issues/issue-51874.stderr b/tests/ui/issues/issue-51874.stderr new file mode 100644 index 000000000..b39159a65 --- /dev/null +++ b/tests/ui/issues/issue-51874.stderr @@ -0,0 +1,14 @@ +error[E0689]: can't call method `pow` on ambiguous numeric type `{float}` + --> $DIR/issue-51874.rs:2:19 + | +LL | let a = (1.0).pow(1.0); + | ^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | let a = (1.0_f32).pow(1.0); + | ~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/issues/issue-51907.rs b/tests/ui/issues/issue-51907.rs new file mode 100644 index 000000000..9378f4357 --- /dev/null +++ b/tests/ui/issues/issue-51907.rs @@ -0,0 +1,19 @@ +// run-pass +trait Foo { + extern "C" fn borrow(&self); + extern "C" fn take(self: Box); +} + +struct Bar; +impl Foo for Bar { + #[allow(improper_ctypes_definitions)] + extern "C" fn borrow(&self) {} + #[allow(improper_ctypes_definitions)] + extern "C" fn take(self: Box) {} +} + +fn main() { + let foo: Box = Box::new(Bar); + foo.borrow(); + foo.take() +} diff --git a/tests/ui/issues/issue-5192.rs b/tests/ui/issues/issue-5192.rs new file mode 100644 index 000000000..e2f835c19 --- /dev/null +++ b/tests/ui/issues/issue-5192.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub trait EventLoop { + fn dummy(&self) { } +} + +pub struct UvEventLoop { + uvio: isize +} + +impl UvEventLoop { + pub fn new() -> UvEventLoop { + UvEventLoop { + uvio: 0 + } + } +} + +impl EventLoop for UvEventLoop { +} + +pub struct Scheduler { + event_loop: Box, +} + +impl Scheduler { + + pub fn new(event_loop: Box) -> Scheduler { + Scheduler { + event_loop: event_loop, + } + } +} + +pub fn main() { + let _sched = Scheduler::new(Box::new(UvEventLoop::new()) as Box); +} diff --git a/tests/ui/issues/issue-51947.rs b/tests/ui/issues/issue-51947.rs new file mode 100644 index 000000000..c877fb8ae --- /dev/null +++ b/tests/ui/issues/issue-51947.rs @@ -0,0 +1,17 @@ +// build-pass + +#![crate_type = "lib"] +#![feature(linkage)] + +// MergeFunctions will merge these via an anonymous internal +// backing function, which must be named if ThinLTO buffers are used + +#[linkage = "weak"] +pub fn fn1(a: u32, b: u32, c: u32) -> u32 { + a + b + c +} + +#[linkage = "weak"] +pub fn fn2(a: u32, b: u32, c: u32) -> u32 { + a + b + c +} diff --git a/tests/ui/issues/issue-52049.rs b/tests/ui/issues/issue-52049.rs new file mode 100644 index 000000000..efdcc4493 --- /dev/null +++ b/tests/ui/issues/issue-52049.rs @@ -0,0 +1,8 @@ +fn foo(_: &'static u32) {} + +fn unpromotable(t: T) -> T { t } + +fn main() { + foo(&unpromotable(5u32)); +} +//~^^ ERROR temporary value dropped while borrowed diff --git a/tests/ui/issues/issue-52049.stderr b/tests/ui/issues/issue-52049.stderr new file mode 100644 index 000000000..b25dbd1cb --- /dev/null +++ b/tests/ui/issues/issue-52049.stderr @@ -0,0 +1,14 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-52049.rs:6:10 + | +LL | foo(&unpromotable(5u32)); + | -----^^^^^^^^^^^^^^^^^^- + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/issues/issue-52126-assign-op-invariance.rs b/tests/ui/issues/issue-52126-assign-op-invariance.rs new file mode 100644 index 000000000..c96cfdf3c --- /dev/null +++ b/tests/ui/issues/issue-52126-assign-op-invariance.rs @@ -0,0 +1,49 @@ +// Issue 52126: With respect to variance, the assign-op's like += were +// accidentally lumped together with other binary op's. In both cases +// we were coercing the LHS of the op to the expected supertype. +// +// The problem is that since the LHS of += is modified, we need the +// parameter to be invariant with respect to the overall type, not +// covariant. + +use std::collections::HashMap; +use std::ops::AddAssign; + +pub fn main() { + panics(); +} + +pub struct Counter<'l> { + map: HashMap<&'l str, usize>, +} + +impl<'l> AddAssign for Counter<'l> +{ + fn add_assign(&mut self, rhs: Counter<'l>) { + rhs.map.into_iter().for_each(|(key, val)| { + let count = self.map.entry(key).or_insert(0); + *count += val; + }); + } +} + +/// Often crashes, if not prints invalid strings. +pub fn panics() { + let mut acc = Counter{map: HashMap::new()}; + for line in vec!["123456789".to_string(), "12345678".to_string()] { + let v: Vec<&str> = line.split_whitespace().collect(); + //~^ ERROR `line` does not live long enough + // println!("accumulator before add_assign {:?}", acc.map); + let mut map = HashMap::new(); + for str_ref in v { + let e = map.entry(str_ref); + println!("entry: {:?}", e); + let count = e.or_insert(0); + *count += 1; + } + let cnt2 = Counter{map}; + acc += cnt2; + // println!("accumulator after add_assign {:?}", acc.map); + // line gets dropped here but references are kept in acc.map + } +} diff --git a/tests/ui/issues/issue-52126-assign-op-invariance.stderr b/tests/ui/issues/issue-52126-assign-op-invariance.stderr new file mode 100644 index 000000000..d45067577 --- /dev/null +++ b/tests/ui/issues/issue-52126-assign-op-invariance.stderr @@ -0,0 +1,15 @@ +error[E0597]: `line` does not live long enough + --> $DIR/issue-52126-assign-op-invariance.rs:34:28 + | +LL | let v: Vec<&str> = line.split_whitespace().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | acc += cnt2; + | --- borrow later used here +... +LL | } + | - `line` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/issues/issue-52140/auxiliary/some_crate.rs b/tests/ui/issues/issue-52140/auxiliary/some_crate.rs new file mode 100644 index 000000000..087005849 --- /dev/null +++ b/tests/ui/issues/issue-52140/auxiliary/some_crate.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] + +pub fn hello() { + println!("Hello, world!"); +} diff --git a/tests/ui/issues/issue-52140/main.rs b/tests/ui/issues/issue-52140/main.rs new file mode 100644 index 000000000..aeac43404 --- /dev/null +++ b/tests/ui/issues/issue-52140/main.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:some_crate.rs +// compile-flags:--extern some_crate +// edition:2018 + +mod foo { + pub use some_crate; +} + +fn main() { + ::some_crate::hello(); + foo::some_crate::hello(); +} diff --git a/tests/ui/issues/issue-52141/auxiliary/some_crate.rs b/tests/ui/issues/issue-52141/auxiliary/some_crate.rs new file mode 100644 index 000000000..087005849 --- /dev/null +++ b/tests/ui/issues/issue-52141/auxiliary/some_crate.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] + +pub fn hello() { + println!("Hello, world!"); +} diff --git a/tests/ui/issues/issue-52141/main.rs b/tests/ui/issues/issue-52141/main.rs new file mode 100644 index 000000000..7eea1726c --- /dev/null +++ b/tests/ui/issues/issue-52141/main.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:some_crate.rs +// compile-flags:--extern some_crate +// edition:2018 + +use some_crate as some_name; + +mod foo { + pub use crate::some_name::*; +} + +fn main() { + ::some_crate::hello(); + some_name::hello(); + foo::hello(); +} diff --git a/tests/ui/issues/issue-52262.rs b/tests/ui/issues/issue-52262.rs new file mode 100644 index 000000000..547643f0d --- /dev/null +++ b/tests/ui/issues/issue-52262.rs @@ -0,0 +1,24 @@ +#[derive(Debug)] +enum MyError { + NotFound { key: Vec }, + Err41, +} + +impl std::error::Error for MyError {} + +impl std::fmt::Display for MyError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MyError::NotFound { key } => write!( + f, + "unknown error with code {}.", + String::from_utf8(*key).unwrap() + //~^ ERROR cannot move out of `*key` which is behind a shared reference + ), + MyError::Err41 => write!(f, "Sit by a lake"), + } + } +} +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/issues/issue-52262.stderr b/tests/ui/issues/issue-52262.stderr new file mode 100644 index 000000000..ef41f078b --- /dev/null +++ b/tests/ui/issues/issue-52262.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*key` which is behind a shared reference + --> $DIR/issue-52262.rs:15:35 + | +LL | String::from_utf8(*key).unwrap() + | ^^^^ move occurs because `*key` has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/issues/issue-5239-1.rs b/tests/ui/issues/issue-5239-1.rs new file mode 100644 index 000000000..708ae34c6 --- /dev/null +++ b/tests/ui/issues/issue-5239-1.rs @@ -0,0 +1,6 @@ +// Regression test for issue #5239 + +fn main() { + let x = |ref x: isize| { x += 1; }; + //~^ ERROR E0368 +} diff --git a/tests/ui/issues/issue-5239-1.stderr b/tests/ui/issues/issue-5239-1.stderr new file mode 100644 index 000000000..f53ddb954 --- /dev/null +++ b/tests/ui/issues/issue-5239-1.stderr @@ -0,0 +1,11 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `&isize` + --> $DIR/issue-5239-1.rs:4:30 + | +LL | let x = |ref x: isize| { x += 1; }; + | -^^^^^ + | | + | cannot use `+=` on type `&isize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/issues/issue-5239-2.rs b/tests/ui/issues/issue-5239-2.rs new file mode 100644 index 000000000..b501c6e18 --- /dev/null +++ b/tests/ui/issues/issue-5239-2.rs @@ -0,0 +1,9 @@ +// run-pass +// Regression test for issue #5239 + + +pub fn main() { + let _f = |ref x: isize| { *x }; + let foo = 10; + assert_eq!(_f(foo), 10); +} diff --git a/tests/ui/issues/issue-52489.rs b/tests/ui/issues/issue-52489.rs new file mode 100644 index 000000000..8efe21698 --- /dev/null +++ b/tests/ui/issues/issue-52489.rs @@ -0,0 +1,8 @@ +// edition:2018 +// aux-build:issue-52489.rs +// compile-flags:--extern issue_52489 + +use issue_52489; +//~^ ERROR use of unstable library feature 'issue_52489_unstable' + +fn main() {} diff --git a/tests/ui/issues/issue-52489.stderr b/tests/ui/issues/issue-52489.stderr new file mode 100644 index 000000000..842ebd196 --- /dev/null +++ b/tests/ui/issues/issue-52489.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'issue_52489_unstable' + --> $DIR/issue-52489.rs:5:5 + | +LL | use issue_52489; + | ^^^^^^^^^^^ + | + = help: add `#![feature(issue_52489_unstable)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/issues/issue-52533.rs b/tests/ui/issues/issue-52533.rs new file mode 100644 index 000000000..bb9a1911f --- /dev/null +++ b/tests/ui/issues/issue-52533.rs @@ -0,0 +1,7 @@ +fn foo(_: impl for<'a> FnOnce(&'a u32, &u32) -> &'a u32) { +} + +fn main() { + foo(|a, b| b) + //~^ ERROR lifetime may not live long enough +} diff --git a/tests/ui/issues/issue-52533.stderr b/tests/ui/issues/issue-52533.stderr new file mode 100644 index 000000000..c764736d7 --- /dev/null +++ b/tests/ui/issues/issue-52533.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-52533.rs:5:16 + | +LL | foo(|a, b| b) + | - - ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | has type `&'1 u32` + | has type `&'2 u32` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-52705/auxiliary/png2.rs b/tests/ui/issues/issue-52705/auxiliary/png2.rs new file mode 100644 index 000000000..fa9956e44 --- /dev/null +++ b/tests/ui/issues/issue-52705/auxiliary/png2.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +pub struct DecodingError; diff --git a/tests/ui/issues/issue-52705/main.rs b/tests/ui/issues/issue-52705/main.rs new file mode 100644 index 000000000..90bb8ca75 --- /dev/null +++ b/tests/ui/issues/issue-52705/main.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// aux-build:png2.rs +// compile-flags:--extern png2 +// edition:2018 + +mod png { + use png2 as png_ext; + + fn foo() -> png_ext::DecodingError { unimplemented!() } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/issues/issue-52717.rs b/tests/ui/issues/issue-52717.rs new file mode 100644 index 000000000..f83232a4a --- /dev/null +++ b/tests/ui/issues/issue-52717.rs @@ -0,0 +1,13 @@ +enum A { + A { + foo: usize, + } +} + +fn main() { + let x = A::A { foo: 3 }; + match x { + A::A { fob } => { println!("{}", fob); } +//~^ ERROR does not have a field named `fob` + } +} diff --git a/tests/ui/issues/issue-52717.stderr b/tests/ui/issues/issue-52717.stderr new file mode 100644 index 000000000..468cdf2dc --- /dev/null +++ b/tests/ui/issues/issue-52717.stderr @@ -0,0 +1,12 @@ +error[E0026]: variant `A::A` does not have a field named `fob` + --> $DIR/issue-52717.rs:10:12 + | +LL | A::A { fob } => { println!("{}", fob); } + | ^^^ + | | + | variant `A::A` does not have this field + | help: a field with a similar name exists: `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0026`. diff --git a/tests/ui/issues/issue-5280.rs b/tests/ui/issues/issue-5280.rs new file mode 100644 index 000000000..5c5ce6c98 --- /dev/null +++ b/tests/ui/issues/issue-5280.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] + +type FontTableTag = u32; + +trait FontTableTagConversions { + fn tag_to_string(self); +} + +impl FontTableTagConversions for FontTableTag { + fn tag_to_string(self) { + let _ = &self; + } +} + +pub fn main() { + 5.tag_to_string(); +} diff --git a/tests/ui/issues/issue-5315.rs b/tests/ui/issues/issue-5315.rs new file mode 100644 index 000000000..0c121a5ee --- /dev/null +++ b/tests/ui/issues/issue-5315.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct A(#[allow(unused_tuple_struct_fields)] bool); + +pub fn main() { + let f = A; + f(true); +} diff --git a/tests/ui/issues/issue-5321-immediates-with-bare-self.rs b/tests/ui/issues/issue-5321-immediates-with-bare-self.rs new file mode 100644 index 000000000..64aa2836a --- /dev/null +++ b/tests/ui/issues/issue-5321-immediates-with-bare-self.rs @@ -0,0 +1,15 @@ +// run-pass + +trait Fooable { + fn yes(self); +} + +impl Fooable for usize { + fn yes(self) { + for _ in 0..self { println!("yes"); } + } +} + +pub fn main() { + 2.yes(); +} diff --git a/tests/ui/issues/issue-53251.rs b/tests/ui/issues/issue-53251.rs new file mode 100644 index 000000000..240826a16 --- /dev/null +++ b/tests/ui/issues/issue-53251.rs @@ -0,0 +1,21 @@ +struct S; + +impl S { + fn f() {} +} + +macro_rules! impl_add { + ($($n:ident)*) => { + $( + fn $n() { + S::f::(); + //~^ ERROR this associated function takes 0 generic + //~| ERROR this associated function takes 0 generic + } + )* + } +} + +impl_add!(a b); + +fn main() { } diff --git a/tests/ui/issues/issue-53251.stderr b/tests/ui/issues/issue-53251.stderr new file mode 100644 index 000000000..cee9a5deb --- /dev/null +++ b/tests/ui/issues/issue-53251.stderr @@ -0,0 +1,39 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-53251.rs:11:20 + | +LL | S::f::(); + | ^------- help: remove these generics + | | + | expected 0 generic arguments +... +LL | impl_add!(a b); + | -------------- in this macro invocation + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-53251.rs:4:8 + | +LL | fn f() {} + | ^ + = note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-53251.rs:11:20 + | +LL | S::f::(); + | ^------- help: remove these generics + | | + | expected 0 generic arguments +... +LL | impl_add!(a b); + | -------------- in this macro invocation + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-53251.rs:4:8 + | +LL | fn f() {} + | ^ + = note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-53275.rs b/tests/ui/issues/issue-53275.rs new file mode 100644 index 000000000..5ae6fb2d4 --- /dev/null +++ b/tests/ui/issues/issue-53275.rs @@ -0,0 +1,9 @@ +// build-pass + +#![crate_type = "lib"] +#![allow(unconditional_panic)] +struct S(u8); + +pub fn ice() { + S([][0]); +} diff --git a/tests/ui/issues/issue-53300.rs b/tests/ui/issues/issue-53300.rs new file mode 100644 index 000000000..09f0fe9d9 --- /dev/null +++ b/tests/ui/issues/issue-53300.rs @@ -0,0 +1,12 @@ +// issue 53300 + +pub trait A { + fn add(&self, b: i32) -> i32; +} + +fn addition() -> Wrapper {} +//~^ ERROR cannot find type `Wrapper` in this scope [E0412] + +fn main() { + let res = addition(); +} diff --git a/tests/ui/issues/issue-53300.stderr b/tests/ui/issues/issue-53300.stderr new file mode 100644 index 000000000..2fedef7d2 --- /dev/null +++ b/tests/ui/issues/issue-53300.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Wrapper` in this scope + --> $DIR/issue-53300.rs:7:18 + | +LL | fn addition() -> Wrapper {} + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-53333.rs b/tests/ui/issues/issue-53333.rs new file mode 100644 index 000000000..ccc9971f9 --- /dev/null +++ b/tests/ui/issues/issue-53333.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_imports)] +// edition:2018 + +fn main() { + use std; + let std = "std"; + println!("{}", std); +} diff --git a/tests/ui/issues/issue-53348.rs b/tests/ui/issues/issue-53348.rs new file mode 100644 index 000000000..d2f8c77c0 --- /dev/null +++ b/tests/ui/issues/issue-53348.rs @@ -0,0 +1,15 @@ +fn main() { + let mut v = vec!["hello", "this", "is", "a", "test"]; + + let v2 = Vec::new(); + + v.into_iter().map(|s|s.to_owned()).collect::>(); + + let mut a = String::new(); //~ NOTE expected due to this value + for i in v { + a = *i.to_string(); + //~^ ERROR mismatched types + //~| NOTE expected struct `String`, found `str` + v2.push(a); + } +} diff --git a/tests/ui/issues/issue-53348.stderr b/tests/ui/issues/issue-53348.stderr new file mode 100644 index 000000000..71d9f5b3d --- /dev/null +++ b/tests/ui/issues/issue-53348.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-53348.rs:10:13 + | +LL | let mut a = String::new(); + | ------------- expected due to this value +LL | for i in v { +LL | a = *i.to_string(); + | ^^^^^^^^^^^^^^ expected struct `String`, found `str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-53419.rs b/tests/ui/issues/issue-53419.rs new file mode 100644 index 000000000..892ec66af --- /dev/null +++ b/tests/ui/issues/issue-53419.rs @@ -0,0 +1,8 @@ +// check-pass + +struct Foo { + bar: dyn for<'r> Fn(usize, &'r dyn FnMut()) +} + +fn main() { +} diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/issues/issue-53498.rs new file mode 100644 index 000000000..9e0437c46 --- /dev/null +++ b/tests/ui/issues/issue-53498.rs @@ -0,0 +1,17 @@ +pub mod test { + pub struct A; + pub struct B; + pub struct Foo(T); + + impl Foo { + fn foo() {} + } + + impl Foo { + fn foo() {} + } +} + +fn main() { + test::Foo::::foo(); //~ ERROR associated function `foo` is private +} diff --git a/tests/ui/issues/issue-53498.stderr b/tests/ui/issues/issue-53498.stderr new file mode 100644 index 000000000..b28fbff62 --- /dev/null +++ b/tests/ui/issues/issue-53498.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `foo` is private + --> $DIR/issue-53498.rs:16:27 + | +LL | fn foo() {} + | -------- private associated function defined here +... +LL | test::Foo::::foo(); + | ^^^ private associated function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/issues/issue-53568.rs b/tests/ui/issues/issue-53568.rs new file mode 100644 index 000000000..49ae444f9 --- /dev/null +++ b/tests/ui/issues/issue-53568.rs @@ -0,0 +1,47 @@ +// Regression test for an NLL-related ICE (#53568) -- we failed to +// resolve inference variables in "custom type-ops". +// +// check-pass + +trait Future { + type Item; +} + +impl Future for F +where F: Fn() -> T +{ + type Item = T; +} + +trait Connect {} + +struct Connector { + handler: H, +} + +impl Connect for Connector +where + T: 'static, + H: Future +{ +} + +struct Client { + connector: C, +} + +fn build(_connector: C) -> Client { + unimplemented!() +} + +fn client(handler: H) -> Client +where H: Fn() + Copy +{ + let connector = Connector { + handler, + }; + let client = build(connector); + client +} + +fn main() { } diff --git a/tests/ui/issues/issue-5358-1.rs b/tests/ui/issues/issue-5358-1.rs new file mode 100644 index 000000000..f5e32e78d --- /dev/null +++ b/tests/ui/issues/issue-5358-1.rs @@ -0,0 +1,13 @@ +enum Either { Left(T), Right(U) } +struct S(Either); + +fn main() { + match S(Either::Left(5)) { + Either::Right(_) => {} + //~^ ERROR mismatched types + //~| expected struct `S`, found enum `Either` + //~| expected struct `S` + //~| found enum `Either<_, _>` + _ => {} + } +} diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/issues/issue-5358-1.stderr new file mode 100644 index 000000000..9d5b8d9d3 --- /dev/null +++ b/tests/ui/issues/issue-5358-1.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-5358-1.rs:6:9 + | +LL | match S(Either::Left(5)) { + | ------------------ this expression has type `S` +LL | Either::Right(_) => {} + | ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either` + | + = note: expected struct `S` + found enum `Either<_, _>` +help: try wrapping the pattern in `S` + | +LL | S(Either::Right(_)) => {} + | ++ + +help: you might have meant to use field `0` whose type is `Either` + | +LL | match S(Either::Left(5)).0 { + | ~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-53712.rs b/tests/ui/issues/issue-53712.rs new file mode 100644 index 000000000..2353904d7 --- /dev/null +++ b/tests/ui/issues/issue-53712.rs @@ -0,0 +1,9 @@ +// issue #53712: make the error generated by using tuple indexing on an array more specific + +fn main() { + let arr = [10, 20, 30, 40, 50]; + arr.0; + //~^ ERROR no field `0` on type `[{integer}; 5]` [E0609] + //~| HELP instead of using tuple indexing, use array indexing + //~| SUGGESTION arr[0] +} diff --git a/tests/ui/issues/issue-53712.stderr b/tests/ui/issues/issue-53712.stderr new file mode 100644 index 000000000..db85919af --- /dev/null +++ b/tests/ui/issues/issue-53712.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `0` on type `[{integer}; 5]` + --> $DIR/issue-53712.rs:5:9 + | +LL | arr.0; + | ----^ + | | + | help: instead of using tuple indexing, use array indexing: `arr[0]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/issues/issue-53728.rs b/tests/ui/issues/issue-53728.rs new file mode 100644 index 000000000..77b5010f7 --- /dev/null +++ b/tests/ui/issues/issue-53728.rs @@ -0,0 +1,19 @@ +// run-pass + +#![allow(dead_code)] +#[repr(u16)] +enum DeviceKind { + Nil = 0, +} + +#[repr(packed)] +struct DeviceInfo { + endianness: u8, + device_kind: DeviceKind, +} + +fn main() { + let _x = None::<(DeviceInfo, u8)>; + let _y = None::<(DeviceInfo, u16)>; + let _z = None::<(DeviceInfo, u64)>; +} diff --git a/tests/ui/issues/issue-53843.rs b/tests/ui/issues/issue-53843.rs new file mode 100644 index 000000000..f305b370c --- /dev/null +++ b/tests/ui/issues/issue-53843.rs @@ -0,0 +1,26 @@ +// run-pass + +use std::ops::Deref; + +pub struct Pin

(P); + +impl Deref for Pin

+where + P: Deref, +{ + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl

Pin

{ + fn poll(self) {} +} + +fn main() { + let mut unit = (); + let pin = Pin(&mut unit); + pin.poll(); +} diff --git a/tests/ui/issues/issue-54044.rs b/tests/ui/issues/issue-54044.rs new file mode 100644 index 000000000..809ea7a87 --- /dev/null +++ b/tests/ui/issues/issue-54044.rs @@ -0,0 +1,13 @@ +#![deny(unused_attributes)] //~ NOTE lint level is defined here + +#[cold] +//~^ ERROR attribute should be applied to a function +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +struct Foo; //~ NOTE not a function + +fn main() { + #[cold] + //~^ ERROR attribute should be applied to a function + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + 5; //~ NOTE not a function +} diff --git a/tests/ui/issues/issue-54044.stderr b/tests/ui/issues/issue-54044.stderr new file mode 100644 index 000000000..8bd94a041 --- /dev/null +++ b/tests/ui/issues/issue-54044.stderr @@ -0,0 +1,29 @@ +error: attribute should be applied to a function definition + --> $DIR/issue-54044.rs:3:1 + | +LL | #[cold] + | ^^^^^^^ +... +LL | struct Foo; + | ----------- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/issue-54044.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: attribute should be applied to a function definition + --> $DIR/issue-54044.rs:9:5 + | +LL | #[cold] + | ^^^^^^^ +... +LL | 5; + | - not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-54062.rs b/tests/ui/issues/issue-54062.rs new file mode 100644 index 000000000..093d6601d --- /dev/null +++ b/tests/ui/issues/issue-54062.rs @@ -0,0 +1,12 @@ +use std::sync::Mutex; + +struct Test { + comps: Mutex, +} + +fn main() {} + +fn testing(test: Test) { + let _ = test.comps.inner.try_lock(); + //~^ ERROR: field `inner` of struct `Mutex` is private +} diff --git a/tests/ui/issues/issue-54062.stderr b/tests/ui/issues/issue-54062.stderr new file mode 100644 index 000000000..5361ee1d3 --- /dev/null +++ b/tests/ui/issues/issue-54062.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `inner` of struct `Mutex` is private + --> $DIR/issue-54062.rs:10:24 + | +LL | let _ = test.comps.inner.try_lock(); + | ^^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/issues/issue-54094.rs b/tests/ui/issues/issue-54094.rs new file mode 100644 index 000000000..ec38dc40e --- /dev/null +++ b/tests/ui/issues/issue-54094.rs @@ -0,0 +1,14 @@ +// check-pass +trait Zoo { + type X; +} + +impl Zoo for u16 { + type X = usize; +} + +fn foo(abc: ::X) {} + +fn main() { + let x: *const u8 = foo as _; +} diff --git a/tests/ui/issues/issue-54302-cases.rs b/tests/ui/issues/issue-54302-cases.rs new file mode 100644 index 000000000..faa116269 --- /dev/null +++ b/tests/ui/issues/issue-54302-cases.rs @@ -0,0 +1,85 @@ +trait Mirror { + type Image; + fn coerce(self) -> Self::Image; +} + +impl Mirror for T { + type Image = T; + fn coerce(self) -> Self { self } +} + +trait Foo<'x, T> { + fn foo(self) -> &'x T; +} + +impl<'s, 'x, T: 'x> Foo<'x, T> for &'s T where &'s T: Foo2<'x, T> { + fn foo(self) -> &'x T { self.foo2() } +} + +trait Foo2<'x, T> { + fn foo2(self) -> &'x T; +} + +// example 1 - fails leak check +impl<'x> Foo2<'x, u32> for &'x u32 +{ + fn foo2(self) -> &'x u32 { self } +} + +// example 2 - OK with this issue +impl<'x, 'a: 'x> Foo2<'x, i32> for &'a i32 +{ + fn foo2(self) -> &'x i32 { self } +} + +// example 3 - fails due to issue #XYZ + Leak-check +impl<'x, T> Foo2<'x, u64> for T + where T: Mirror +{ + fn foo2(self) -> &'x u64 { self.coerce() } +} + +// example 4 - fails due to issue #XYZ +impl<'x, 'a: 'x, T> Foo2<'x, i64> for T + where T: Mirror +{ + fn foo2(self) -> &'x i64 { self.coerce() } +} + + +trait RefFoo { + fn ref_foo(&self) -> &'static T; +} + +impl RefFoo for T where for<'a> &'a T: Foo<'static, T> { + fn ref_foo(&self) -> &'static T { + self.foo() + } +} + + +fn coerce_lifetime1(a: &u32) -> &'static u32 +{ + >::ref_foo(a) + //~^ ERROR not general enough +} + +fn coerce_lifetime2(a: &i32) -> &'static i32 +{ + >::ref_foo(a) + //~^ ERROR not general enough +} + +fn coerce_lifetime3(a: &u64) -> &'static u64 +{ + >::ref_foo(a) + //~^ ERROR not general enough +} + +fn coerce_lifetime4(a: &i64) -> &'static i64 +{ + >::ref_foo(a) + //~^ ERROR not general enough +} + +fn main() {} diff --git a/tests/ui/issues/issue-54302-cases.stderr b/tests/ui/issues/issue-54302-cases.stderr new file mode 100644 index 000000000..6e8b69c4b --- /dev/null +++ b/tests/ui/issues/issue-54302-cases.stderr @@ -0,0 +1,38 @@ +error: implementation of `Foo` is not general enough + --> $DIR/issue-54302-cases.rs:63:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` + +error: implementation of `Foo` is not general enough + --> $DIR/issue-54302-cases.rs:69:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... + = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` + +error: implementation of `Foo` is not general enough + --> $DIR/issue-54302-cases.rs:75:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... + = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` + +error: implementation of `Foo` is not general enough + --> $DIR/issue-54302-cases.rs:81:5 + | +LL | >::ref_foo(a) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... + = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/issues/issue-54302.rs b/tests/ui/issues/issue-54302.rs new file mode 100644 index 000000000..1bfaebc38 --- /dev/null +++ b/tests/ui/issues/issue-54302.rs @@ -0,0 +1,19 @@ +trait Deserialize<'de> {} + +trait DeserializeOwned: for<'de> Deserialize<'de> {} +impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} + +// Based on this impl, `&'static str` only implements Deserialize<'static>. +// It does not implement for<'de> Deserialize<'de>. +impl<'de: 'a, 'a> Deserialize<'de> for &'a str {} + +fn main() { + // Then why does it implement DeserializeOwned? This compiles. + fn assert_deserialize_owned() {} + assert_deserialize_owned::<&'static str>(); + //~^ ERROR not general enough + + // It correctly does not implement for<'de> Deserialize<'de>. + //fn assert_hrtb Deserialize<'de>>() {} + //assert_hrtb::<&'static str>(); +} diff --git a/tests/ui/issues/issue-54302.stderr b/tests/ui/issues/issue-54302.stderr new file mode 100644 index 000000000..26c46571f --- /dev/null +++ b/tests/ui/issues/issue-54302.stderr @@ -0,0 +1,11 @@ +error: implementation of `Deserialize` is not general enough + --> $DIR/issue-54302.rs:13:5 + | +LL | assert_deserialize_owned::<&'static str>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough + | + = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... + = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-5439.rs b/tests/ui/issues/issue-5439.rs new file mode 100644 index 000000000..852b264dc --- /dev/null +++ b/tests/ui/issues/issue-5439.rs @@ -0,0 +1,19 @@ +struct Foo { + foo: isize, +} + +struct Bar { + bar: isize, +} + +impl Bar { + fn make_foo (&self, i: isize) -> Box { + return Box::new(Foo { nonexistent: self, foo: i }); //~ ERROR: no field named + } +} + +fn main () { + let bar = Bar { bar: 1 }; + let foo = bar.make_foo(2); + println!("{}", foo.foo); +} diff --git a/tests/ui/issues/issue-5439.stderr b/tests/ui/issues/issue-5439.stderr new file mode 100644 index 000000000..dc8f8b878 --- /dev/null +++ b/tests/ui/issues/issue-5439.stderr @@ -0,0 +1,11 @@ +error[E0560]: struct `Foo` has no field named `nonexistent` + --> $DIR/issue-5439.rs:11:31 + | +LL | return Box::new(Foo { nonexistent: self, foo: i }); + | ^^^^^^^^^^^ `Foo` does not have this field + | + = note: available fields are: `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/issues/issue-54410.rs b/tests/ui/issues/issue-54410.rs new file mode 100644 index 000000000..e3e8ca985 --- /dev/null +++ b/tests/ui/issues/issue-54410.rs @@ -0,0 +1,8 @@ +extern "C" { + pub static mut symbol: [i8]; + //~^ ERROR the size for values of type `[i8]` cannot be known at compilation time +} + +fn main() { + println!("{:p}", unsafe { &symbol }); +} diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr new file mode 100644 index 000000000..516c59afb --- /dev/null +++ b/tests/ui/issues/issue-54410.stderr @@ -0,0 +1,11 @@ +error[E0277]: the size for values of type `[i8]` cannot be known at compilation time + --> $DIR/issue-54410.rs:2:28 + | +LL | pub static mut symbol: [i8]; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i8]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs b/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs new file mode 100644 index 000000000..412028bdc --- /dev/null +++ b/tests/ui/issues/issue-54462-mutable-noalias-correctness.rs @@ -0,0 +1,25 @@ +// run-pass +// +// compile-flags: -Ccodegen-units=1 -O + +fn linidx(row: usize, col: usize) -> usize { + row * 1 + col * 3 +} + +fn main() { + let mut mat = [1.0f32, 5.0, 9.0, 2.0, 6.0, 10.0, 3.0, 7.0, 11.0, 4.0, 8.0, 12.0]; + + for i in 0..2 { + for j in i+1..3 { + if mat[linidx(j, 3)] > mat[linidx(i, 3)] { + for k in 0..4 { + let (x, rest) = mat.split_at_mut(linidx(i, k) + 1); + let a = x.last_mut().unwrap(); + let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); + ::std::mem::swap(a, b); + } + } + } + } + assert_eq!([9.0, 5.0, 1.0, 10.0, 6.0, 2.0, 11.0, 7.0, 3.0, 12.0, 8.0, 4.0], mat); +} diff --git a/tests/ui/issues/issue-54477-reduced-2.rs b/tests/ui/issues/issue-54477-reduced-2.rs new file mode 100644 index 000000000..199d69b45 --- /dev/null +++ b/tests/ui/issues/issue-54477-reduced-2.rs @@ -0,0 +1,26 @@ +// run-pass +// rust-lang/rust#54477: runtime bug in the VecDeque library that was +// exposed by this test case, derived from test suite of crates.io +// `collection` crate. + +use std::collections::VecDeque; + +fn main() { + let mut vecdeque_13 = VecDeque::from(vec![ ]); + let mut vecdeque_29 = VecDeque::from(vec![ 0 ]); + vecdeque_29.insert(0, 30 ); + vecdeque_29.insert(1, 31 ); + vecdeque_29.insert(2, 32 ); + vecdeque_29.insert(3, 33 ); + vecdeque_29.insert(4, 34 ); + vecdeque_29.insert(5, 35 ); + // println!("vecdeque_13: {:?}", vecdeque_13); + // println!("vecdeque_29: {:?}", vecdeque_29); + + // println!("Invoking: `vecdeque_13.append(&mut vecdeque_29)`"); + vecdeque_13.append(&mut vecdeque_29); + + // println!("vecdeque_13: {:?}", vecdeque_13); + + assert_eq!(vecdeque_13, VecDeque::from(vec![30, 31, 32, 33, 34, 35, 0])); +} diff --git a/tests/ui/issues/issue-54582.rs b/tests/ui/issues/issue-54582.rs new file mode 100644 index 000000000..8c50cac67 --- /dev/null +++ b/tests/ui/issues/issue-54582.rs @@ -0,0 +1,16 @@ +// run-pass + +pub trait Stage: Sync {} + +pub enum Enum { + A, + B, +} + +impl Stage for Enum {} + +pub static ARRAY: [(&dyn Stage, &str); 1] = [ + (&Enum::A, ""), +]; + +fn main() {} diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/issues/issue-54696.rs new file mode 100644 index 000000000..15355d30d --- /dev/null +++ b/tests/ui/issues/issue-54696.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + // We shouldn't promote this + let _ = &(main as fn() == main as fn()); + // Also check nested case + let _ = &(&(main as fn()) == &(main as fn())); +} diff --git a/tests/ui/issues/issue-5518.rs b/tests/ui/issues/issue-5518.rs new file mode 100644 index 000000000..97ed9ef30 --- /dev/null +++ b/tests/ui/issues/issue-5518.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-5518.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_5518 as other; + +fn main() {} diff --git a/tests/ui/issues/issue-5521.rs b/tests/ui/issues/issue-5521.rs new file mode 100644 index 000000000..cafdbc399 --- /dev/null +++ b/tests/ui/issues/issue-5521.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// aux-build:issue-5521.rs + + + +extern crate issue_5521 as foo; + +fn bar(a: foo::map) { + if false { + panic!(); + } else { + let _b = &(*a)[&2]; + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-55376.rs b/tests/ui/issues/issue-55376.rs new file mode 100644 index 000000000..4adff2b45 --- /dev/null +++ b/tests/ui/issues/issue-55376.rs @@ -0,0 +1,16 @@ +// run-pass +// Tests that paths in `pub(...)` don't fail HIR verification. + +#![allow(unused_imports)] +#![allow(dead_code)] + +pub(self) use self::my_mod::Foo; + +mod my_mod { + pub(super) use self::Foo as Bar; + pub(in super::my_mod) use self::Foo as Baz; + + pub struct Foo; +} + +fn main() {} diff --git a/tests/ui/issues/issue-55380.rs b/tests/ui/issues/issue-55380.rs new file mode 100644 index 000000000..f7cb296d3 --- /dev/null +++ b/tests/ui/issues/issue-55380.rs @@ -0,0 +1,28 @@ +// run-pass +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +pub trait Foo { + fn abc() -> u32; + fn def() -> u32; +} + +pub trait Marker {} + +impl Marker for () {} + +impl Foo for T { + default fn abc() -> u32 { 16 } + default fn def() -> u32 { 42 } +} + +impl Foo for T { + fn def() -> u32 { + Self::abc() + } +} + +fn main() { + assert_eq!(<()>::def(), 16); + assert_eq!(::def(), 42); +} diff --git a/tests/ui/issues/issue-55380.stderr b/tests/ui/issues/issue-55380.stderr new file mode 100644 index 000000000..403844c72 --- /dev/null +++ b/tests/ui/issues/issue-55380.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-55380.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-5550.rs b/tests/ui/issues/issue-5550.rs new file mode 100644 index 000000000..6ea24747b --- /dev/null +++ b/tests/ui/issues/issue-5550.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 + +pub fn main() { + let s: String = "foobar".to_string(); + let mut t: &str = &s; + t = &t[0..3]; // for master: str::view(t, 0, 3) maybe +} diff --git a/tests/ui/issues/issue-5554.rs b/tests/ui/issues/issue-5554.rs new file mode 100644 index 000000000..7737536f4 --- /dev/null +++ b/tests/ui/issues/issue-5554.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::default::Default; + +pub struct X { + a: T, +} + +// reordering these bounds stops the ICE +// +// nmatsakis: This test used to have the bounds Default + PartialEq + +// Default, but having duplicate bounds became illegal. +impl Default for X { + fn default() -> X { + X { a: Default::default() } + } +} + +macro_rules! constants { + () => { + let _ : X = Default::default(); + } +} + +pub fn main() { + constants!(); +} diff --git a/tests/ui/issues/issue-55587.rs b/tests/ui/issues/issue-55587.rs new file mode 100644 index 000000000..d9100cf55 --- /dev/null +++ b/tests/ui/issues/issue-55587.rs @@ -0,0 +1,5 @@ +use std::path::Path; + +fn main() { + let Path::new(); //~ ERROR expected tuple struct or tuple variant +} diff --git a/tests/ui/issues/issue-55587.stderr b/tests/ui/issues/issue-55587.stderr new file mode 100644 index 000000000..faf78cfe8 --- /dev/null +++ b/tests/ui/issues/issue-55587.stderr @@ -0,0 +1,11 @@ +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/issue-55587.rs:4:9 + | +LL | let Path::new(); + | ^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/issues/issue-5572.rs b/tests/ui/issues/issue-5572.rs new file mode 100644 index 000000000..175dc879d --- /dev/null +++ b/tests/ui/issues/issue-5572.rs @@ -0,0 +1,7 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn foo(_t: T) { } + +pub fn main() { } diff --git a/tests/ui/issues/issue-55731.rs b/tests/ui/issues/issue-55731.rs new file mode 100644 index 000000000..7b4f4e2cd --- /dev/null +++ b/tests/ui/issues/issue-55731.rs @@ -0,0 +1,52 @@ +use std::marker::PhantomData; + +trait DistributedIterator { + fn reduce(self) + where + Self: Sized, + { + unreachable!() + } +} + +trait DistributedIteratorMulti { + type Item; +} + +struct Connect(PhantomData); +impl DistributedIteratorMulti<&'a ()>> DistributedIterator for Connect where {} + +struct Cloned(PhantomData); +impl<'a, Source> DistributedIteratorMulti<&'a Source> for Cloned<&'a Source> { + type Item = (); +} + +struct Map { + i: I, + f: F, +} +impl, F, Source> DistributedIteratorMulti for Map +where + F: A<>::Item>, +{ + type Item = (); +} + +trait A {} + +struct X; +impl A<()> for X {} + +fn multi(_reducer: I) +where + I: for<'a> DistributedIteratorMulti<&'a ()>, +{ + DistributedIterator::reduce(Connect::(PhantomData)) +} + +fn main() { + multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough + i: Cloned(PhantomData), + f: X, + }); +} diff --git a/tests/ui/issues/issue-55731.stderr b/tests/ui/issues/issue-55731.stderr new file mode 100644 index 000000000..97fd6678c --- /dev/null +++ b/tests/ui/issues/issue-55731.stderr @@ -0,0 +1,14 @@ +error: implementation of `DistributedIteratorMulti` is not general enough + --> $DIR/issue-55731.rs:48:5 + | +LL | / multi(Map { +LL | | i: Cloned(PhantomData), +LL | | f: X, +LL | | }); + | |______^ implementation of `DistributedIteratorMulti` is not general enough + | + = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... + = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-56128.rs b/tests/ui/issues/issue-56128.rs new file mode 100644 index 000000000..10b50943c --- /dev/null +++ b/tests/ui/issues/issue-56128.rs @@ -0,0 +1,15 @@ +// Regression test for #56128. When this `pub(super) use...` gets +// exploded in the HIR, we were not handling ids correctly. +// +// check-pass + +mod bar { + pub(super) use self::baz::{x, y}; + + mod baz { + pub fn x() { } + pub fn y() { } + } +} + +fn main() { } diff --git a/tests/ui/issues/issue-56175.rs b/tests/ui/issues/issue-56175.rs new file mode 100644 index 000000000..ca1d0d431 --- /dev/null +++ b/tests/ui/issues/issue-56175.rs @@ -0,0 +1,9 @@ +// edition:2018 +// aux-crate:reexported_trait=reexported-trait.rs + +fn main() { + reexported_trait::FooStruct.trait_method(); + //~^ ERROR + reexported_trait::FooStruct.trait_method_b(); + //~^ ERROR +} diff --git a/tests/ui/issues/issue-56175.stderr b/tests/ui/issues/issue-56175.stderr new file mode 100644 index 000000000..013a440ed --- /dev/null +++ b/tests/ui/issues/issue-56175.stderr @@ -0,0 +1,37 @@ +error[E0599]: no method named `trait_method` found for struct `FooStruct` in the current scope + --> $DIR/issue-56175.rs:5:33 + | +LL | reexported_trait::FooStruct.trait_method(); + | ^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:3:12 + | +LL | fn trait_method(&self) { + | ------------ the method is available for `FooStruct` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use reexported_trait::Trait; + | + +error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in the current scope + --> $DIR/issue-56175.rs:7:33 + | +LL | reexported_trait::FooStruct.trait_method_b(); + | ^^^^^^^^^^^^^^ method not found in `FooStruct` + | + ::: $DIR/auxiliary/reexported-trait.rs:7:12 + | +LL | fn trait_method_b(&self) { + | -------------- the method is available for `FooStruct` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use reexported_trait::TraitBRename; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-56199.rs b/tests/ui/issues/issue-56199.rs new file mode 100644 index 000000000..ba11582a9 --- /dev/null +++ b/tests/ui/issues/issue-56199.rs @@ -0,0 +1,22 @@ +enum Foo {} +struct Bar {} + +impl Foo { + fn foo() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } +} + +impl Bar { + fn bar() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-56199.stderr b/tests/ui/issues/issue-56199.stderr new file mode 100644 index 000000000..7aaf8e4ac --- /dev/null +++ b/tests/ui/issues/issue-56199.stderr @@ -0,0 +1,30 @@ +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:6:17 + | +LL | let _ = Self; + | ^^^^ + | + = help: did you mean to use one of the enum's variants? + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:8:17 + | +LL | let _ = Self(); + | ^^^^ + | + = help: did you mean to use one of the enum's variants? + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:15:17 + | +LL | let _ = Self; + | ^^^^ help: use curly brackets: `Self { /* fields */ }` + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56199.rs:17:17 + | +LL | let _ = Self(); + | ^^^^ help: use curly brackets: `Self { /* fields */ }` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/issues/issue-56229.rs b/tests/ui/issues/issue-56229.rs new file mode 100644 index 000000000..9e5897b98 --- /dev/null +++ b/tests/ui/issues/issue-56229.rs @@ -0,0 +1,35 @@ +// check-pass + +trait Mirror { + type Other; +} + +#[derive(Debug)] +struct Even(usize); +struct Odd; + +impl Mirror for Even { + type Other = Odd; +} + +impl Mirror for Odd { + type Other = Even; +} + +trait Dyn: AsRef<::Other> {} + +impl Dyn for Even {} + +impl AsRef for Even { + fn as_ref(&self) -> &Even { + self + } +} + +fn code(d: &dyn Dyn) -> &T::Other { + d.as_ref() +} + +fn main() { + println!("{:?}", code(&Even(22))); +} diff --git a/tests/ui/issues/issue-56237.rs b/tests/ui/issues/issue-56237.rs new file mode 100644 index 000000000..534b85ace --- /dev/null +++ b/tests/ui/issues/issue-56237.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::ops::Deref; + +fn foo

(_value:

::Target) +where + P: Deref, +

::Target: Sized, +{} + +fn main() { + foo::>(2); +} diff --git a/tests/ui/issues/issue-5666.rs b/tests/ui/issues/issue-5666.rs new file mode 100644 index 000000000..810895b1b --- /dev/null +++ b/tests/ui/issues/issue-5666.rs @@ -0,0 +1,26 @@ +// run-pass + +struct Dog { + name : String +} + +trait Barks { + fn bark(&self) -> String; +} + +impl Barks for Dog { + fn bark(&self) -> String { + return format!("woof! (I'm {})", self.name); + } +} + + +pub fn main() { + let snoopy = Box::new(Dog{name: "snoopy".to_string()}); + let bubbles = Box::new(Dog{name: "bubbles".to_string()}); + let barker = [snoopy as Box, bubbles as Box]; + + for pup in &barker { + println!("{}", pup.bark()); + } +} diff --git a/tests/ui/issues/issue-56806.rs b/tests/ui/issues/issue-56806.rs new file mode 100644 index 000000000..b1dac26d6 --- /dev/null +++ b/tests/ui/issues/issue-56806.rs @@ -0,0 +1,6 @@ +pub trait Trait { + fn dyn_instead_of_self(self: Box); + //~^ ERROR invalid `self` parameter type +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr new file mode 100644 index 000000000..f164fd0c5 --- /dev/null +++ b/tests/ui/issues/issue-56806.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid `self` parameter type: Box<(dyn Trait + 'static)> + --> $DIR/issue-56806.rs:2:34 + | +LL | fn dyn_instead_of_self(self: Box); + | ^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/issues/issue-56835.rs b/tests/ui/issues/issue-56835.rs new file mode 100644 index 000000000..7132d15ee --- /dev/null +++ b/tests/ui/issues/issue-56835.rs @@ -0,0 +1,9 @@ +pub struct Foo {} + +impl Foo { + fn bar(Self(foo): Self) {} + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + //~^^ ERROR expected tuple struct or tuple variant, found self constructor `Self` [E0164] +} + +fn main() {} diff --git a/tests/ui/issues/issue-56835.stderr b/tests/ui/issues/issue-56835.stderr new file mode 100644 index 000000000..e949ae7b3 --- /dev/null +++ b/tests/ui/issues/issue-56835.stderr @@ -0,0 +1,15 @@ +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-56835.rs:4:12 + | +LL | fn bar(Self(foo): Self) {} + | ^^^^^^^^^ help: use curly brackets: `Self { /* fields */ }` + +error[E0164]: expected tuple struct or tuple variant, found self constructor `Self` + --> $DIR/issue-56835.rs:4:12 + | +LL | fn bar(Self(foo): Self) {} + | ^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/issues/issue-56870.rs b/tests/ui/issues/issue-56870.rs new file mode 100644 index 000000000..137a0ede0 --- /dev/null +++ b/tests/ui/issues/issue-56870.rs @@ -0,0 +1,38 @@ +// build-pass +// Regression test for #56870: Internal compiler error (traits & associated consts) + +use std::fmt::Debug; + +pub trait Foo { + const FOO: *const u8; +} + +impl Foo for dyn Debug { + const FOO: *const u8 = ::fmt as *const u8; +} + +pub trait Bar { + const BAR: *const u8; +} + +pub trait Baz { + type Data: Debug; +} + +pub struct BarStruct(S); + +impl Bar for BarStruct { + const BAR: *const u8 = ::Data>>::FOO; +} + +struct AnotherStruct; +#[derive(Debug)] +struct SomeStruct; + +impl Baz for AnotherStruct { + type Data = SomeStruct; +} + +fn main() { + let _x = as Bar>::BAR; +} diff --git a/tests/ui/issues/issue-5688.rs b/tests/ui/issues/issue-5688.rs new file mode 100644 index 000000000..b6e364c2f --- /dev/null +++ b/tests/ui/issues/issue-5688.rs @@ -0,0 +1,20 @@ +// run-pass +/* +# Corrupted initialization in the static struct + +...should print &[1, 2, 3] but instead prints something like +&[4492532864, 24]. It is pretty evident that the compiler messed up +with the representation of [isize; n] and [isize] somehow, or at least +failed to typecheck correctly. +*/ + +#[derive(Copy, Clone)] +struct X { vec: &'static [isize] } + +static V: &'static [X] = &[X { vec: &[1, 2, 3] }]; + +pub fn main() { + for &v in V { + println!("{:?}", v.vec); + } +} diff --git a/tests/ui/issues/issue-56943.rs b/tests/ui/issues/issue-56943.rs new file mode 100644 index 000000000..8fc77abdb --- /dev/null +++ b/tests/ui/issues/issue-56943.rs @@ -0,0 +1,8 @@ +// aux-build:issue-56943.rs + +extern crate issue_56943; + +fn main() { + let _: issue_56943::S = issue_56943::S2; + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/issues/issue-56943.stderr b/tests/ui/issues/issue-56943.stderr new file mode 100644 index 000000000..74ed5ec0f --- /dev/null +++ b/tests/ui/issues/issue-56943.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-56943.rs:6:29 + | +LL | let _: issue_56943::S = issue_56943::S2; + | -------------- ^^^^^^^^^^^^^^^ expected struct `S`, found struct `S2` + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/issues/issue-5708.rs new file mode 100644 index 000000000..6fe9943d3 --- /dev/null +++ b/tests/ui/issues/issue-5708.rs @@ -0,0 +1,55 @@ +// run-pass +#![allow(unused_variables)] +/* +# ICE when returning struct with reference to trait + +A function which takes a reference to a trait and returns a +struct with that reference results in an ICE. + +This does not occur with concrete types, only with references +to traits. +*/ + + +// original +trait Inner { + fn print(&self); +} + +impl Inner for isize { + fn print(&self) { print!("Inner: {}\n", *self); } +} + +struct Outer<'a> { + inner: &'a (dyn Inner+'a) +} + +impl<'a> Outer<'a> { + fn new(inner: &dyn Inner) -> Outer { + Outer { + inner: inner + } + } +} + +pub fn main() { + let inner: isize = 5; + let outer = Outer::new(&inner as &dyn Inner); + outer.inner.print(); +} + + +// minimal +pub trait MyTrait { + fn dummy(&self, t: T) -> T { panic!() } +} + +pub struct MyContainer<'a, T:'a> { + foos: Vec<&'a (dyn MyTrait+'a)> , +} + +impl<'a, T> MyContainer<'a, T> { + pub fn add (&mut self, foo: &'a dyn MyTrait) { + self.foos.push(foo); + } +} diff --git a/tests/ui/issues/issue-57156.rs b/tests/ui/issues/issue-57156.rs new file mode 100644 index 000000000..9f5ec9f27 --- /dev/null +++ b/tests/ui/issues/issue-57156.rs @@ -0,0 +1,23 @@ +// check-pass + +trait Foo { + type Output; +} + +trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> { + fn cb(&self) -> Box>; +} + +impl<'s> Foo<&'s ()> for () { + type Output = bool; +} + +impl<'a> Bar<'a, ()> for () { + fn cb(&self) -> Box> { + Box::new(*self) + } +} + +fn main() { + let _t = ().cb(); +} diff --git a/tests/ui/issues/issue-57162.rs b/tests/ui/issues/issue-57162.rs new file mode 100644 index 000000000..650700602 --- /dev/null +++ b/tests/ui/issues/issue-57162.rs @@ -0,0 +1,7 @@ +// check-pass + +trait Foo {} +impl Foo for dyn Send {} + +impl Foo for T {} +fn main() {} diff --git a/tests/ui/issues/issue-5718.rs b/tests/ui/issues/issue-5718.rs new file mode 100644 index 000000000..f29a1e2a0 --- /dev/null +++ b/tests/ui/issues/issue-5718.rs @@ -0,0 +1,24 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct Element; + +macro_rules! foo { + ($tag: expr, $string: expr) => { + if $tag == $string { + let element: Box<_> = Box::new(Element); + unsafe { + return std::mem::transmute::<_, usize>(element); + } + } + } +} + +fn bar() -> usize { + foo!("a", "b"); + 0 +} + +fn main() { + bar(); +} diff --git a/tests/ui/issues/issue-57198-pass.rs b/tests/ui/issues/issue-57198-pass.rs new file mode 100644 index 000000000..3857def98 --- /dev/null +++ b/tests/ui/issues/issue-57198-pass.rs @@ -0,0 +1,9 @@ +// run-pass + +mod m { + pub fn r#for() {} +} + +fn main() { + m::r#for(); +} diff --git a/tests/ui/issues/issue-57271.rs b/tests/ui/issues/issue-57271.rs new file mode 100644 index 000000000..f74222e3e --- /dev/null +++ b/tests/ui/issues/issue-57271.rs @@ -0,0 +1,24 @@ +// aux-build:issue-57271-lib.rs + +extern crate issue_57271_lib; + +use issue_57271_lib::BaseType; + +pub enum ObjectType { //~ ERROR recursive types `ObjectType` and `TypeSignature` have infinite size + Class(ClassTypeSignature), + Array(TypeSignature), + TypeVariable(()), +} + +pub struct ClassTypeSignature { + pub package: (), + pub class: (), + pub inner: (), +} + +pub enum TypeSignature { + Base(BaseType), + Object(ObjectType), +} + +fn main() {} diff --git a/tests/ui/issues/issue-57271.stderr b/tests/ui/issues/issue-57271.stderr new file mode 100644 index 000000000..391e69c91 --- /dev/null +++ b/tests/ui/issues/issue-57271.stderr @@ -0,0 +1,27 @@ +error[E0072]: recursive types `ObjectType` and `TypeSignature` have infinite size + --> $DIR/issue-57271.rs:7:1 + | +LL | pub enum ObjectType { + | ^^^^^^^^^^^^^^^^^^^ +LL | Class(ClassTypeSignature), +LL | Array(TypeSignature), + | ------------- recursive without indirection +... +LL | pub enum TypeSignature { + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | Base(BaseType), +LL | Object(ObjectType), + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ Array(Box), +LL | TypeVariable(()), + ... +LL | Base(BaseType), +LL ~ Object(Box), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/issues/issue-57362-1.rs b/tests/ui/issues/issue-57362-1.rs new file mode 100644 index 000000000..1fa417fe9 --- /dev/null +++ b/tests/ui/issues/issue-57362-1.rs @@ -0,0 +1,23 @@ +// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes +// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading +// to confusing notes such as: +// = note: expected type `Trait` +// found type `Trait` + +// from issue #57362 +trait Trait { + fn f(self); +} + +impl Trait for fn(&T) { + fn f(self) { + println!("f"); + } +} + +fn f() { + let a: fn(_) = |_: &u8| {}; + a.f(); //~ ERROR no method named `f` +} + +fn main() {} diff --git a/tests/ui/issues/issue-57362-1.stderr b/tests/ui/issues/issue-57362-1.stderr new file mode 100644 index 000000000..b10273f14 --- /dev/null +++ b/tests/ui/issues/issue-57362-1.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope + --> $DIR/issue-57362-1.rs:20:7 + | +LL | a.f(); + | ^ method not found in `fn(&u8)` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Trait` defines an item `f`, perhaps you need to implement it + --> $DIR/issue-57362-1.rs:8:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-57362-2.rs b/tests/ui/issues/issue-57362-2.rs new file mode 100644 index 000000000..a0b0ea1d0 --- /dev/null +++ b/tests/ui/issues/issue-57362-2.rs @@ -0,0 +1,25 @@ +// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes +// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading +// to confusing notes such as: +// = note: expected type `Trait` +// found type `Trait` + +// extracted from a similar issue: #57642 +trait X { + type G; + fn make_g() -> Self::G; +} + +impl<'a> X for fn(&'a ()) { + type G = &'a (); + + fn make_g() -> Self::G { + &() + } +} + +fn g() { + let x = ::make_g(); //~ ERROR the function +} + +fn main() {} diff --git a/tests/ui/issues/issue-57362-2.stderr b/tests/ui/issues/issue-57362-2.stderr new file mode 100644 index 000000000..7d08c4643 --- /dev/null +++ b/tests/ui/issues/issue-57362-2.stderr @@ -0,0 +1,18 @@ +error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied + --> $DIR/issue-57362-2.rs:22:25 + | +LL | let x = ::make_g(); + | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `for<'a> fn(&'a ()): X` + = help: items from traits can only be used if the trait is implemented and in scope +note: `X` defines an item `make_g`, perhaps you need to implement it + --> $DIR/issue-57362-2.rs:8:1 + | +LL | trait X { + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-57399-self-return-impl-trait.rs b/tests/ui/issues/issue-57399-self-return-impl-trait.rs new file mode 100644 index 000000000..c7fe40e7b --- /dev/null +++ b/tests/ui/issues/issue-57399-self-return-impl-trait.rs @@ -0,0 +1,22 @@ +// check-pass + +trait T { + type T; +} + +impl T for i32 { + type T = u32; +} + +struct S { + a: A, +} + + +impl From for S<::T> { + fn from(a: u32) -> Self { + Self { a } + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-5741.rs b/tests/ui/issues/issue-5741.rs new file mode 100644 index 000000000..b9eaf0be7 --- /dev/null +++ b/tests/ui/issues/issue-5741.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(while_true)] +#![allow(unreachable_code)] + +pub fn main() { + return; + while true {}; +} diff --git a/tests/ui/issues/issue-5754.rs b/tests/ui/issues/issue-5754.rs new file mode 100644 index 000000000..d90816635 --- /dev/null +++ b/tests/ui/issues/issue-5754.rs @@ -0,0 +1,16 @@ +// build-pass +#![allow(dead_code)] +#![allow(improper_ctypes)] + +// pretty-expanded FIXME #23616 + +struct TwoDoubles { + r: f64, + i: f64 +} + +extern "C" { + fn rust_dbg_extern_identity_TwoDoubles(arg1: TwoDoubles) -> TwoDoubles; +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-57741-1.rs b/tests/ui/issues/issue-57741-1.rs new file mode 100644 index 000000000..d0aae23b2 --- /dev/null +++ b/tests/ui/issues/issue-57741-1.rs @@ -0,0 +1,18 @@ +#![allow(warnings)] + +// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made +// because the box doesn't deref to the type of the arm. + +enum S { + A { a: usize }, + B { b: usize }, +} + +fn main() { + let x = Box::new(3u32); + let y = match x { + S::A { a } | S::B { b: a } => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; +} diff --git a/tests/ui/issues/issue-57741-1.stderr b/tests/ui/issues/issue-57741-1.stderr new file mode 100644 index 000000000..789a1f44d --- /dev/null +++ b/tests/ui/issues/issue-57741-1.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/issue-57741-1.rs:14:9 + | +LL | let y = match x { + | - this expression has type `Box` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^ expected struct `Box`, found enum `S` + | + = note: expected struct `Box` + found enum `S` + +error[E0308]: mismatched types + --> $DIR/issue-57741-1.rs:14:22 + | +LL | let y = match x { + | - this expression has type `Box` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^^^^ expected struct `Box`, found enum `S` + | + = note: expected struct `Box` + found enum `S` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-57741.fixed b/tests/ui/issues/issue-57741.fixed new file mode 100644 index 000000000..4cae08003 --- /dev/null +++ b/tests/ui/issues/issue-57741.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +#![allow(warnings)] + +// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works. + +enum S { + A { a: usize }, + B { b: usize }, +} + +enum T { + A(usize), + B(usize), +} + +fn main() { + let x = Box::new(T::A(3)); + let y = match *x { + T::A(a) | T::B(a) => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; + + let x = Box::new(S::A { a: 3 }); + let y = match *x { + S::A { a } | S::B { b: a } => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; +} diff --git a/tests/ui/issues/issue-57741.rs b/tests/ui/issues/issue-57741.rs new file mode 100644 index 000000000..e2658295a --- /dev/null +++ b/tests/ui/issues/issue-57741.rs @@ -0,0 +1,31 @@ +// run-rustfix + +#![allow(warnings)] + +// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works. + +enum S { + A { a: usize }, + B { b: usize }, +} + +enum T { + A(usize), + B(usize), +} + +fn main() { + let x = Box::new(T::A(3)); + let y = match x { + T::A(a) | T::B(a) => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; + + let x = Box::new(S::A { a: 3 }); + let y = match x { + S::A { a } | S::B { b: a } => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; +} diff --git a/tests/ui/issues/issue-57741.stderr b/tests/ui/issues/issue-57741.stderr new file mode 100644 index 000000000..cd277f20e --- /dev/null +++ b/tests/ui/issues/issue-57741.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:20:9 + | +LL | let y = match x { + | - + | | + | this expression has type `Box` + | help: consider dereferencing the boxed value: `*x` +LL | T::A(a) | T::B(a) => a, + | ^^^^^^^ expected struct `Box`, found enum `T` + | + = note: expected struct `Box` + found enum `T` + +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:20:19 + | +LL | let y = match x { + | - + | | + | this expression has type `Box` + | help: consider dereferencing the boxed value: `*x` +LL | T::A(a) | T::B(a) => a, + | ^^^^^^^ expected struct `Box`, found enum `T` + | + = note: expected struct `Box` + found enum `T` + +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:27:9 + | +LL | let y = match x { + | - + | | + | this expression has type `Box` + | help: consider dereferencing the boxed value: `*x` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^ expected struct `Box`, found enum `S` + | + = note: expected struct `Box` + found enum `S` + +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:27:22 + | +LL | let y = match x { + | - + | | + | this expression has type `Box` + | help: consider dereferencing the boxed value: `*x` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^^^^ expected struct `Box`, found enum `S` + | + = note: expected struct `Box` + found enum `S` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-57781.rs b/tests/ui/issues/issue-57781.rs new file mode 100644 index 000000000..f5015aaf5 --- /dev/null +++ b/tests/ui/issues/issue-57781.rs @@ -0,0 +1,20 @@ +// run-pass + +use std::cell::UnsafeCell; +use std::collections::HashMap; + +struct OnceCell { + _value: UnsafeCell>, +} + +impl OnceCell { + const INIT: OnceCell = OnceCell { + _value: UnsafeCell::new(None), + }; +} + +pub fn crash() { + let _ = OnceCell::>::INIT; +} + +fn main() {} diff --git a/tests/ui/issues/issue-57924.rs b/tests/ui/issues/issue-57924.rs new file mode 100644 index 000000000..8846912a8 --- /dev/null +++ b/tests/ui/issues/issue-57924.rs @@ -0,0 +1,10 @@ +pub struct Gcm(E); + +impl Gcm { + pub fn crash(e: E) -> Self { + Self::(e) + //~^ ERROR type arguments are not allowed on self constructor + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-57924.stderr b/tests/ui/issues/issue-57924.stderr new file mode 100644 index 000000000..0323a4dfb --- /dev/null +++ b/tests/ui/issues/issue-57924.stderr @@ -0,0 +1,11 @@ +error[E0109]: type arguments are not allowed on self constructor + --> $DIR/issue-57924.rs:5:16 + | +LL | Self::(e) + | ---- ^ type argument not allowed + | | + | not allowed on self constructor + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/issues/issue-58212.rs b/tests/ui/issues/issue-58212.rs new file mode 100644 index 000000000..4695497c3 --- /dev/null +++ b/tests/ui/issues/issue-58212.rs @@ -0,0 +1,15 @@ +// check-pass + +trait FromUnchecked { + fn from_unchecked(); +} + +impl FromUnchecked for [u8; 1] { + fn from_unchecked() { + let mut array: Self = [0; 1]; + let _ptr = &mut array as *mut [u8] as *mut u8; + } +} + +fn main() { +} diff --git a/tests/ui/issues/issue-58344.rs b/tests/ui/issues/issue-58344.rs new file mode 100644 index 000000000..0cb04dcb2 --- /dev/null +++ b/tests/ui/issues/issue-58344.rs @@ -0,0 +1,50 @@ +// check-pass + +use std::ops::Add; + +trait Trait { + fn get(self) -> T; +} + +struct Holder(T); + +impl Trait for Holder { + fn get(self) -> T { + self.0 + } +} + +enum Either { + Left(L), + Right(R), +} + +impl Either { + fn converge(self) -> T + where + L: Trait, + R: Trait, + { + match self { + Either::Left(val) => val.get(), + Either::Right(val) => val.get(), + } + } +} + +fn add_generic, B>( + lhs: A, + rhs: B, +) -> Either>::Output>, impl Trait<>::Output>> { + if true { Either::Left(Holder(lhs + rhs)) } else { Either::Right(Holder(lhs + rhs)) } +} + +fn add_one( + value: u32, +) -> Either>::Output>, impl Trait<>::Output>> { + add_generic(value, 1u32) +} + +pub fn main() { + add_one(3).converge(); +} diff --git a/tests/ui/issues/issue-58375-monomorphize-default-impls.rs b/tests/ui/issues/issue-58375-monomorphize-default-impls.rs new file mode 100644 index 000000000..6da6f398d --- /dev/null +++ b/tests/ui/issues/issue-58375-monomorphize-default-impls.rs @@ -0,0 +1,24 @@ +// Make sure that the mono-item collector does not crash when trying to +// instantiate a default impl for DecodeUtf16<::Item> +// See https://github.com/rust-lang/rust/issues/58375 + +// build-pass +// compile-flags:-C link-dead-code + +#![crate_type = "rlib"] + +pub struct DecodeUtf16(I); + +pub trait Arbitrary { + fn arbitrary() {} +} + +pub trait A { + type Item; +} + +impl A for u8 { + type Item = char; +} + +impl Arbitrary for DecodeUtf16<::Item> {} diff --git a/tests/ui/issues/issue-5844.mir.stderr b/tests/ui/issues/issue-5844.mir.stderr new file mode 100644 index 000000000..6134d6889 --- /dev/null +++ b/tests/ui/issues/issue-5844.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-5844.rs:8:5 + | +LL | issue_5844_aux::rand(); + | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-5844.rs b/tests/ui/issues/issue-5844.rs new file mode 100644 index 000000000..4f90a9c66 --- /dev/null +++ b/tests/ui/issues/issue-5844.rs @@ -0,0 +1,9 @@ +//aux-build:issue-5844-aux.rs +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +extern crate issue_5844_aux; + +fn main () { + issue_5844_aux::rand(); //~ ERROR: requires unsafe +} diff --git a/tests/ui/issues/issue-5844.thir.stderr b/tests/ui/issues/issue-5844.thir.stderr new file mode 100644 index 000000000..310a2b593 --- /dev/null +++ b/tests/ui/issues/issue-5844.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `rand` is unsafe and requires unsafe function or block + --> $DIR/issue-5844.rs:8:5 + | +LL | issue_5844_aux::rand(); + | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/issues/issue-58463.rs b/tests/ui/issues/issue-58463.rs new file mode 100644 index 000000000..af93f7622 --- /dev/null +++ b/tests/ui/issues/issue-58463.rs @@ -0,0 +1,10 @@ +// run-pass +// compile-flags:-C debuginfo=2 +// ignore-asmjs wasm2js does not support source maps yet + +fn foo() -> impl Copy { + foo +} +fn main() { + foo(); +} diff --git a/tests/ui/issues/issue-58712.rs b/tests/ui/issues/issue-58712.rs new file mode 100644 index 000000000..930bec688 --- /dev/null +++ b/tests/ui/issues/issue-58712.rs @@ -0,0 +1,14 @@ +struct AddrVec { + h: H, + a: A, +} + +impl AddrVec { + //~^ ERROR cannot find type `DeviceId` in this scope + pub fn device(&self) -> DeviceId { + //~^ ERROR cannot find type `DeviceId` in this scope + self.tail() + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-58712.stderr b/tests/ui/issues/issue-58712.stderr new file mode 100644 index 000000000..f4bd4d1e8 --- /dev/null +++ b/tests/ui/issues/issue-58712.stderr @@ -0,0 +1,20 @@ +error[E0412]: cannot find type `DeviceId` in this scope + --> $DIR/issue-58712.rs:6:20 + | +LL | impl AddrVec { + | ^^^^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl AddrVec { + | ++++++++++ + +error[E0412]: cannot find type `DeviceId` in this scope + --> $DIR/issue-58712.rs:8:29 + | +LL | pub fn device(&self) -> DeviceId { + | ^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-58734.rs b/tests/ui/issues/issue-58734.rs new file mode 100644 index 000000000..c838fde5d --- /dev/null +++ b/tests/ui/issues/issue-58734.rs @@ -0,0 +1,24 @@ +trait Trait { + fn exists(self) -> (); + + fn not_object_safe() -> Self; +} + +impl Trait for () { + fn exists(self) -> () { + } + + fn not_object_safe() -> Self { + () + } +} + +fn main() { + // object-safe or not, this call is OK + Trait::exists(()); + // no object safety error + Trait::nonexistent(()); + //~^ ERROR no function or associated item named `nonexistent` found + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/issues/issue-58734.stderr b/tests/ui/issues/issue-58734.stderr new file mode 100644 index 000000000..d2314626d --- /dev/null +++ b/tests/ui/issues/issue-58734.stderr @@ -0,0 +1,23 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-58734.rs:20:5 + | +LL | Trait::nonexistent(()); + | ^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | ::nonexistent(()); + | ++++ + + +error[E0599]: no function or associated item named `nonexistent` found for trait object `dyn Trait` in the current scope + --> $DIR/issue-58734.rs:20:12 + | +LL | Trait::nonexistent(()); + | ^^^^^^^^^^^ function or associated item not found in `dyn Trait` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/issues/issue-5883.rs new file mode 100644 index 000000000..82866b355 --- /dev/null +++ b/tests/ui/issues/issue-5883.rs @@ -0,0 +1,13 @@ +trait A {} + +struct Struct { + r: dyn A + 'static +} + +fn new_struct( + r: dyn A + 'static //~ ERROR the size for values of type +) -> Struct { //~ ERROR the size for values of type + Struct { r: r } +} + +fn main() {} diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/issues/issue-5883.stderr new file mode 100644 index 000000000..ffff403e0 --- /dev/null +++ b/tests/ui/issues/issue-5883.stderr @@ -0,0 +1,36 @@ +error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time + --> $DIR/issue-5883.rs:8:5 + | +LL | r: dyn A + 'static + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn A + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | r: impl A + 'static + | ~~~~ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | r: &dyn A + 'static + | + + +error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time + --> $DIR/issue-5883.rs:9:6 + | +LL | ) -> Struct { + | ^^^^^^ doesn't have a size known at compile-time +LL | Struct { r: r } + | --------------- this returned value is of type `Struct` + | + = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` +note: required because it appears within the type `Struct` + --> $DIR/issue-5883.rs:3:8 + | +LL | struct Struct { + | ^^^^^^ + = note: the return type of a function must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-5884.rs b/tests/ui/issues/issue-5884.rs new file mode 100644 index 000000000..991c52321 --- /dev/null +++ b/tests/ui/issues/issue-5884.rs @@ -0,0 +1,18 @@ +// build-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub struct Foo { + a: isize, +} + +struct Bar<'a> { + a: Box>, + b: &'a Foo, +} + +fn check(a: Box) { + let _ic = Bar{ b: &*a, a: Box::new(None) }; +} + +pub fn main(){} diff --git a/tests/ui/issues/issue-58857.rs b/tests/ui/issues/issue-58857.rs new file mode 100644 index 000000000..4350d7e5b --- /dev/null +++ b/tests/ui/issues/issue-58857.rs @@ -0,0 +1,7 @@ +struct Conj {a : A} +trait Valid {} + +impl Conj{} +//~^ ERROR negative bounds are not supported + +fn main() {} diff --git a/tests/ui/issues/issue-58857.stderr b/tests/ui/issues/issue-58857.stderr new file mode 100644 index 000000000..e2acec47e --- /dev/null +++ b/tests/ui/issues/issue-58857.stderr @@ -0,0 +1,8 @@ +error: negative bounds are not supported + --> $DIR/issue-58857.rs:4:7 + | +LL | impl Conj{} + | ^^^^^^^^ negative bounds are not supported + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-5900.rs b/tests/ui/issues/issue-5900.rs new file mode 100644 index 000000000..a7dc0eff4 --- /dev/null +++ b/tests/ui/issues/issue-5900.rs @@ -0,0 +1,15 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub mod foo { + use super::Bar; + + pub struct FooStruct { bar : Bar } +} + +pub enum Bar { + Bar0 = 0 as isize +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-59020.rs b/tests/ui/issues/issue-59020.rs new file mode 100644 index 000000000..a2b11764a --- /dev/null +++ b/tests/ui/issues/issue-59020.rs @@ -0,0 +1,27 @@ +// edition:2018 +// run-pass +// ignore-emscripten no threads support + +use std::thread; +use std::time::Duration; + +fn main() { + let t1 = thread::spawn(|| { + let sleep = Duration::new(0,100_000); + for _ in 0..100 { + println!("Parking1"); + thread::park_timeout(sleep); + } + }); + + let t2 = thread::spawn(|| { + let sleep = Duration::new(0,100_000); + for _ in 0..100 { + println!("Parking2"); + thread::park_timeout(sleep); + } + }); + + t1.join().expect("Couldn't join thread 1"); + t2.join().expect("Couldn't join thread 2"); +} diff --git a/tests/ui/issues/issue-5917.rs b/tests/ui/issues/issue-5917.rs new file mode 100644 index 000000000..6ab7081cf --- /dev/null +++ b/tests/ui/issues/issue-5917.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(non_upper_case_globals)] + +struct T (&'static [isize]); +static t : T = T (&[5, 4, 3]); +pub fn main () { + let T(ref v) = t; + assert_eq!(v[0], 5); +} diff --git a/tests/ui/issues/issue-59326.rs b/tests/ui/issues/issue-59326.rs new file mode 100644 index 000000000..c0e883774 --- /dev/null +++ b/tests/ui/issues/issue-59326.rs @@ -0,0 +1,26 @@ +// check-pass +trait Service { + type S; +} + +trait Framing { + type F; +} + +impl Framing for () { + type F = (); +} + +trait HttpService: Service {} + +type BoxService = Box>; + +fn build_server BoxService>(_: F) {} + +fn make_server() -> Box> { + unimplemented!() +} + +fn main() { + build_server(|| make_server()) +} diff --git a/tests/ui/issues/issue-59488.rs b/tests/ui/issues/issue-59488.rs new file mode 100644 index 000000000..384501e3e --- /dev/null +++ b/tests/ui/issues/issue-59488.rs @@ -0,0 +1,34 @@ +fn foo() -> i32 { + 42 +} + +fn bar(a: i64) -> i64 { + 43 +} + +enum Foo { + Bar(usize), +} + +fn main() { + foo > 12; + //~^ ERROR binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] + //~| ERROR mismatched types [E0308] + + bar > 13; + //~^ ERROR binary operation `>` cannot be applied to type `fn(i64) -> i64 {bar}` [E0369] + //~| ERROR mismatched types [E0308] + + foo > foo; + //~^ ERROR binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] + + foo > bar; + //~^ ERROR binary operation `>` cannot be applied to type `fn() -> i32 {foo}` [E0369] + //~| ERROR mismatched types [E0308] + + let i = Foo::Bar; + assert_eq!(Foo::Bar, i); + //~^ ERROR binary operation `==` cannot be applied to type `fn(usize) -> Foo {Foo::Bar}` [E0369] + //~| ERROR `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` [E0277] + //~| ERROR `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` [E0277] +} diff --git a/tests/ui/issues/issue-59488.stderr b/tests/ui/issues/issue-59488.stderr new file mode 100644 index 000000000..f9846b62a --- /dev/null +++ b/tests/ui/issues/issue-59488.stderr @@ -0,0 +1,127 @@ +error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:14:9 + | +LL | foo > 12; + | --- ^ -- {integer} + | | + | fn() -> i32 {foo} + | +help: use parentheses to call this function + | +LL | foo() > 12; + | ++ + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:14:11 + | +LL | foo > 12; + | ^^ expected fn item, found integer + | + = note: expected fn item `fn() -> i32 {foo}` + found type `i32` + +error[E0369]: binary operation `>` cannot be applied to type `fn(i64) -> i64 {bar}` + --> $DIR/issue-59488.rs:18:9 + | +LL | bar > 13; + | --- ^ -- {integer} + | | + | fn(i64) -> i64 {bar} + | +help: use parentheses to call this function + | +LL | bar(/* i64 */) > 13; + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:18:11 + | +LL | bar > 13; + | ^^ expected fn item, found integer + | + = note: expected fn item `fn(i64) -> i64 {bar}` + found type `i64` + +error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:22:9 + | +LL | foo > foo; + | --- ^ --- fn() -> i32 {foo} + | | + | fn() -> i32 {foo} + | +help: use parentheses to call these + | +LL | foo() > foo(); + | ++ ++ + +error[E0369]: binary operation `>` cannot be applied to type `fn() -> i32 {foo}` + --> $DIR/issue-59488.rs:25:9 + | +LL | foo > bar; + | --- ^ --- fn(i64) -> i64 {bar} + | | + | fn() -> i32 {foo} + +error[E0308]: mismatched types + --> $DIR/issue-59488.rs:25:11 + | +LL | foo > bar; + | ^^^ expected fn item, found a different fn item + | + = note: expected fn item `fn() -> i32 {foo}` + found fn item `fn(i64) -> i64 {bar}` + +error[E0369]: binary operation `==` cannot be applied to type `fn(usize) -> Foo {Foo::Bar}` + --> $DIR/issue-59488.rs:30:5 + | +LL | assert_eq!(Foo::Bar, i); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | fn(usize) -> Foo {Foo::Bar} + | fn(usize) -> Foo {Foo::Bar} + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` + --> $DIR/issue-59488.rs:30:5 + | +LL | assert_eq!(Foo::Bar, i); + | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` + = help: the following other types implement trait `Debug`: + extern "C" fn() -> Ret + extern "C" fn(A, B) -> Ret + extern "C" fn(A, B, ...) -> Ret + extern "C" fn(A, B, C) -> Ret + extern "C" fn(A, B, C, ...) -> Ret + extern "C" fn(A, B, C, D) -> Ret + extern "C" fn(A, B, C, D, ...) -> Ret + extern "C" fn(A, B, C, D, E) -> Ret + and 118 others + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` + --> $DIR/issue-59488.rs:30:5 + | +LL | assert_eq!(Foo::Bar, i); + | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` + = help: the following other types implement trait `Debug`: + extern "C" fn() -> Ret + extern "C" fn(A, B) -> Ret + extern "C" fn(A, B, ...) -> Ret + extern "C" fn(A, B, C) -> Ret + extern "C" fn(A, B, C, ...) -> Ret + extern "C" fn(A, B, C, D) -> Ret + extern "C" fn(A, B, C, D, ...) -> Ret + extern "C" fn(A, B, C, D, E) -> Ret + and 118 others + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0277, E0308, E0369. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-59494.rs b/tests/ui/issues/issue-59494.rs new file mode 100644 index 000000000..a53e28f72 --- /dev/null +++ b/tests/ui/issues/issue-59494.rs @@ -0,0 +1,23 @@ +fn t7p(f: impl Fn(B) -> C, g: impl Fn(A) -> B) -> impl Fn(A) -> C { + move |a: A| -> C { f(g(a)) } +} + +fn t8n(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C) +where + A: Copy, +{ + move |a: A| -> (B, C) { + let b = a; + let fa = f(a); + let ga = g(b); + (fa, ga) + } +} + +fn main() { + let f = |(_, _)| {}; + let g = |(a, _)| a; + let t7 = |env| |a| |b| t7p(f, g)(((env, a), b)); + let t8 = t8n(t7, t7p(f, g)); + //~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` [E0277] +} diff --git a/tests/ui/issues/issue-59494.stderr b/tests/ui/issues/issue-59494.stderr new file mode 100644 index 000000000..a9284535e --- /dev/null +++ b/tests/ui/issues/issue-59494.stderr @@ -0,0 +1,18 @@ +error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` + --> $DIR/issue-59494.rs:21:22 + | +LL | let t8 = t8n(t7, t7p(f, g)); + | --- ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn(((_, _), _))` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))` +note: required by a bound in `t8n` + --> $DIR/issue-59494.rs:5:45 + | +LL | fn t8n(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C) + | ^^^^^^^^^^ required by this bound in `t8n` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-5950.rs b/tests/ui/issues/issue-5950.rs new file mode 100644 index 000000000..492a9d572 --- /dev/null +++ b/tests/ui/issues/issue-5950.rs @@ -0,0 +1,9 @@ +// check-pass + +// pretty-expanded FIXME #23616 + +pub use local as local_alias; + +pub mod local { } + +pub fn main() {} diff --git a/tests/ui/issues/issue-59756.fixed b/tests/ui/issues/issue-59756.fixed new file mode 100644 index 000000000..7b55d0f17 --- /dev/null +++ b/tests/ui/issues/issue-59756.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +#![allow(warnings)] + +struct A; +struct B; + +fn foo() -> Result { + Ok(A) +} + +fn bar() -> Result { + foo() + //~^ ERROR try expression alternatives have incompatible types [E0308] +} + +fn main() {} diff --git a/tests/ui/issues/issue-59756.rs b/tests/ui/issues/issue-59756.rs new file mode 100644 index 000000000..d6df0592b --- /dev/null +++ b/tests/ui/issues/issue-59756.rs @@ -0,0 +1,21 @@ +// run-rustfix +// ignore-test +// +// FIXME: Re-enable this test once we support choosing +// between multiple mutually exclusive suggestions for the same span + +#![allow(warnings)] + +struct A; +struct B; + +fn foo() -> Result { + Ok(A) +} + +fn bar() -> Result { + foo()? + //~^ ERROR try expression alternatives have incompatible types [E0308] +} + +fn main() {} diff --git a/tests/ui/issues/issue-59756.stderr b/tests/ui/issues/issue-59756.stderr new file mode 100644 index 000000000..9066e57aa --- /dev/null +++ b/tests/ui/issues/issue-59756.stderr @@ -0,0 +1,20 @@ +error[E0308]: try expression alternatives have incompatible types + --> $DIR/issue-59756.rs:13:5 + | +LL | foo()? + | ^^^^^^ expected enum `std::result::Result`, found struct `A` + | + = note: expected enum `std::result::Result` + found struct `A` +help: try removing this `?` + | +LL | foo() + | -- +help: try using a variant of the expected enum + | +LL | Ok(foo()?) + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-5988.rs b/tests/ui/issues/issue-5988.rs new file mode 100644 index 000000000..303fb4fbc --- /dev/null +++ b/tests/ui/issues/issue-5988.rs @@ -0,0 +1,24 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait B { + fn f(&self); +} + +trait T : B { +} + +struct A; + +impl B for U { + fn f(&self) { } +} + +impl T for A { +} + +fn main() { + let a = A; + let br = &a as &dyn B; + br.f(); +} diff --git a/tests/ui/issues/issue-5997-enum.rs b/tests/ui/issues/issue-5997-enum.rs new file mode 100644 index 000000000..3ff4e036c --- /dev/null +++ b/tests/ui/issues/issue-5997-enum.rs @@ -0,0 +1,10 @@ +fn f() -> bool { + enum E { V(Z) } + //~^ ERROR can't use generic parameters from outer function + true +} + +fn main() { + let b = f::(); + assert!(b); +} diff --git a/tests/ui/issues/issue-5997-enum.stderr b/tests/ui/issues/issue-5997-enum.stderr new file mode 100644 index 000000000..3a79215d3 --- /dev/null +++ b/tests/ui/issues/issue-5997-enum.stderr @@ -0,0 +1,13 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-5997-enum.rs:2:16 + | +LL | fn f() -> bool { + | - type parameter from outer function +LL | enum E { V(Z) } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/issues/issue-5997-struct.rs b/tests/ui/issues/issue-5997-struct.rs new file mode 100644 index 000000000..6cf510b0a --- /dev/null +++ b/tests/ui/issues/issue-5997-struct.rs @@ -0,0 +1,10 @@ +fn f() -> bool { + struct S(T); //~ ERROR can't use generic parameters from outer function + + true +} + +fn main() { + let b = f::(); + assert!(b); +} diff --git a/tests/ui/issues/issue-5997-struct.stderr b/tests/ui/issues/issue-5997-struct.stderr new file mode 100644 index 000000000..d2e97f767 --- /dev/null +++ b/tests/ui/issues/issue-5997-struct.stderr @@ -0,0 +1,13 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-5997-struct.rs:2:14 + | +LL | fn f() -> bool { + | - type parameter from outer function +LL | struct S(T); + | -^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/issues/issue-5997.rs b/tests/ui/issues/issue-5997.rs new file mode 100644 index 000000000..145e3a792 --- /dev/null +++ b/tests/ui/issues/issue-5997.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + +fn f() -> bool { + enum E { V(T) } + + struct S(T); + + true +} + +fn main() { + let b = f::(); + assert!(b); +} diff --git a/tests/ui/issues/issue-60218.rs b/tests/ui/issues/issue-60218.rs new file mode 100644 index 000000000..4926691f3 --- /dev/null +++ b/tests/ui/issues/issue-60218.rs @@ -0,0 +1,19 @@ +// Regression test for #60218 +// +// This was reported to cause ICEs. + +use std::iter::Map; + +pub trait Foo {} + +pub fn trigger_error(iterable: I, functor: F) +where + for<'t> &'t I: IntoIterator, +for<'t> Map<<&'t I as IntoIterator>::IntoIter, F>: Iterator, +for<'t> ::IntoIter, F> as Iterator>::Item: Foo, +{ +} + +fn main() { + trigger_error(vec![], |x: &u32| x) //~ ERROR E0277 +} diff --git a/tests/ui/issues/issue-60218.stderr b/tests/ui/issues/issue-60218.stderr new file mode 100644 index 000000000..dd72b6515 --- /dev/null +++ b/tests/ui/issues/issue-60218.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `&u32: Foo` is not satisfied + --> $DIR/issue-60218.rs:18:19 + | +LL | trigger_error(vec![], |x: &u32| x) + | ------------- ^^^^^^ the trait `Foo` is not implemented for `&u32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `trigger_error` + --> $DIR/issue-60218.rs:13:72 + | +LL | pub fn trigger_error(iterable: I, functor: F) + | ------------- required by a bound in this +... +LL | for<'t> ::IntoIter, F> as Iterator>::Item: Foo, + | ^^^ required by this bound in `trigger_error` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-60622.rs b/tests/ui/issues/issue-60622.rs new file mode 100644 index 000000000..8e230c615 --- /dev/null +++ b/tests/ui/issues/issue-60622.rs @@ -0,0 +1,16 @@ +#![deny(warnings)] + +struct Borked {} + +impl Borked { + fn a(&self) {} +} + +fn run_wild(b: &Borked) { + b.a::<'_, T>(); + //~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + //~| ERROR this associated function takes 0 generic arguments but 1 generic argument + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +} + +fn main() {} diff --git a/tests/ui/issues/issue-60622.stderr b/tests/ui/issues/issue-60622.stderr new file mode 100644 index 000000000..ecf1ae758 --- /dev/null +++ b/tests/ui/issues/issue-60622.stderr @@ -0,0 +1,35 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/issue-60622.rs:10:11 + | +LL | fn a(&self) {} + | - the late bound lifetime parameter is introduced here +... +LL | b.a::<'_, T>(); + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 +note: the lint level is defined here + --> $DIR/issue-60622.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(late_bound_lifetime_arguments)]` implied by `#[deny(warnings)]` + +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-60622.rs:10:7 + | +LL | b.a::<'_, T>(); + | ^ - help: remove this generic argument + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-60622.rs:6:8 + | +LL | fn a(&self) {} + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-60989.rs b/tests/ui/issues/issue-60989.rs new file mode 100644 index 000000000..29db3fdb4 --- /dev/null +++ b/tests/ui/issues/issue-60989.rs @@ -0,0 +1,18 @@ +struct A {} +struct B {} + +impl From for B { + fn from(a: A) -> B { + B{} + } +} + +fn main() { + let c1 = (); + c1::<()>; + //~^ ERROR type arguments are not allowed on local variable + + let c1 = A {}; + c1::>; + //~^ ERROR type arguments are not allowed on local variable +} diff --git a/tests/ui/issues/issue-60989.stderr b/tests/ui/issues/issue-60989.stderr new file mode 100644 index 000000000..e0236567b --- /dev/null +++ b/tests/ui/issues/issue-60989.stderr @@ -0,0 +1,19 @@ +error[E0109]: type arguments are not allowed on local variable + --> $DIR/issue-60989.rs:12:10 + | +LL | c1::<()>; + | -- ^^ type argument not allowed + | | + | not allowed on local variable + +error[E0109]: type arguments are not allowed on local variable + --> $DIR/issue-60989.rs:16:10 + | +LL | c1::>; + | -- ^^^^^^^^^^^ type argument not allowed + | | + | not allowed on local variable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/issues/issue-61106.rs b/tests/ui/issues/issue-61106.rs new file mode 100644 index 000000000..308ef1de3 --- /dev/null +++ b/tests/ui/issues/issue-61106.rs @@ -0,0 +1,6 @@ +fn main() { + let x = String::new(); + foo(x.clone()); //~ ERROR mismatched types +} + +fn foo(_: &str) {} diff --git a/tests/ui/issues/issue-61106.stderr b/tests/ui/issues/issue-61106.stderr new file mode 100644 index 000000000..2bc092341 --- /dev/null +++ b/tests/ui/issues/issue-61106.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-61106.rs:3:9 + | +LL | foo(x.clone()); + | --- ^^^^^^^^^ + | | | + | | expected `&str`, found struct `String` + | | help: consider borrowing here: `&x` + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-61106.rs:6:4 + | +LL | fn foo(_: &str) {} + | ^^^ ------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-61108.rs b/tests/ui/issues/issue-61108.rs new file mode 100644 index 000000000..0a883b958 --- /dev/null +++ b/tests/ui/issues/issue-61108.rs @@ -0,0 +1,7 @@ +fn main() { + let mut bad_letters = vec!['e', 't', 'o', 'i']; + for l in bad_letters { + // something here + } + bad_letters.push('s'); //~ ERROR borrow of moved value: `bad_letters` +} diff --git a/tests/ui/issues/issue-61108.stderr b/tests/ui/issues/issue-61108.stderr new file mode 100644 index 000000000..3aaf5fb3f --- /dev/null +++ b/tests/ui/issues/issue-61108.stderr @@ -0,0 +1,21 @@ +error[E0382]: borrow of moved value: `bad_letters` + --> $DIR/issue-61108.rs:6:5 + | +LL | let mut bad_letters = vec!['e', 't', 'o', 'i']; + | --------------- move occurs because `bad_letters` has type `Vec`, which does not implement the `Copy` trait +LL | for l in bad_letters { + | ----------- `bad_letters` moved due to this implicit call to `.into_iter()` +... +LL | bad_letters.push('s'); + | ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `bad_letters` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider iterating over a slice of the `Vec`'s content to avoid moving into the `for` loop + | +LL | for l in &bad_letters { + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-6117.rs b/tests/ui/issues/issue-6117.rs new file mode 100644 index 000000000..5235d53d8 --- /dev/null +++ b/tests/ui/issues/issue-6117.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +enum Either { Left(T), Right(U) } + +pub fn main() { + match Either::Left(Box::new(17)) { + Either::Right(()) => {} + _ => {} + } +} diff --git a/tests/ui/issues/issue-6130.rs b/tests/ui/issues/issue-6130.rs new file mode 100644 index 000000000..a33ea6869 --- /dev/null +++ b/tests/ui/issues/issue-6130.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let i: usize = 0; + assert!(i <= 0xFFFF_FFFF); + + let i: isize = 0; + assert!(i >= -0x8000_0000); + assert!(i <= 0x7FFF_FFFF); +} diff --git a/tests/ui/issues/issue-61475.rs b/tests/ui/issues/issue-61475.rs new file mode 100644 index 000000000..680449c9e --- /dev/null +++ b/tests/ui/issues/issue-61475.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] + +enum E { + A, B +} + +fn main() { + match &&E::A { + &&E::A => { + } + &&E::B => { + } + }; +} diff --git a/tests/ui/issues/issue-6153.rs b/tests/ui/issues/issue-6153.rs new file mode 100644 index 000000000..25f026f21 --- /dev/null +++ b/tests/ui/issues/issue-6153.rs @@ -0,0 +1,13 @@ +// run-pass + + +fn swap(f: F) -> Vec where F: FnOnce(Vec) -> Vec { + let x = vec![1, 2, 3]; + f(x) +} + +pub fn main() { + let v = swap(|mut x| { x.push(4); x }); + let w = swap(|mut x| { x.push(4); x }); + assert_eq!(v, w); +} diff --git a/tests/ui/issues/issue-61623.rs b/tests/ui/issues/issue-61623.rs new file mode 100644 index 000000000..82df50d9d --- /dev/null +++ b/tests/ui/issues/issue-61623.rs @@ -0,0 +1,10 @@ +fn f1<'a>(_: &'a mut ()) {} + +fn f2

(_: P, _: ()) {} + +fn f3<'a>(x: &'a ((), &'a mut ())) { + f2(|| x.0, f1(x.1)) +//~^ ERROR cannot borrow `*x.1` as mutable, as it is behind a `&` reference +} + +fn main() {} diff --git a/tests/ui/issues/issue-61623.stderr b/tests/ui/issues/issue-61623.stderr new file mode 100644 index 000000000..5fcc33855 --- /dev/null +++ b/tests/ui/issues/issue-61623.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x.1` as mutable, as it is behind a `&` reference + --> $DIR/issue-61623.rs:6:19 + | +LL | f2(|| x.0, f1(x.1)) + | ^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f3<'a>(x: &'a mut ((), &'a mut ())) { + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-61696.rs b/tests/ui/issues/issue-61696.rs new file mode 100644 index 000000000..dca52927f --- /dev/null +++ b/tests/ui/issues/issue-61696.rs @@ -0,0 +1,66 @@ +// run-pass + +pub enum Infallible {} + +// The check that the `bool` field of `V1` is encoding a "niche variant" +// (i.e. not `V1`, so `V3` or `V4`) used to be mathematically incorrect, +// causing valid `V1` values to be interpreted as other variants. +pub enum E1 { + V1 { f: bool }, + V2 { f: Infallible }, + V3, + V4, +} + +// Computing the discriminant used to be done using the niche type (here `u8`, +// from the `bool` field of `V1`), overflowing for variants with large enough +// indices (`V3` and `V4`), causing them to be interpreted as other variants. +pub enum E2 { + V1 { f: bool }, + + /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X), + _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X), + _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X), + _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X), + _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X), + _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X), + _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X), + _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X), + _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X), + _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X), + _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X), + _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X), + _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X), + _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X), + _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X), + _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X), + _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X), + _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X), + _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X), + _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X), + _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X), + _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X), + _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X), + _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X), + _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X), + _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X), + _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X), + _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X), + _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X), + _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X), + _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X), + _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X), + + V3, + V4, +} + +fn main() { + if let E1::V2 { .. } = (E1::V1 { f: true }) { + unreachable!() + } + + if let E2::V1 { .. } = E2::V3:: { + unreachable!() + } +} diff --git a/tests/ui/issues/issue-61894.rs b/tests/ui/issues/issue-61894.rs new file mode 100644 index 000000000..776fdbb74 --- /dev/null +++ b/tests/ui/issues/issue-61894.rs @@ -0,0 +1,21 @@ +// run-pass + +#![feature(core_intrinsics)] + +use std::any::type_name; + +struct Bar(#[allow(unused_tuple_struct_fields)] M); + +impl Bar { + fn foo(&self) -> &'static str { + fn f() {} + fn type_name_of(_: T) -> &'static str { + type_name::() + } + type_name_of(f) + } +} + +fn main() { + assert_eq!(Bar(()).foo(), "issue_61894::Bar<_>::foo::f"); +} diff --git a/tests/ui/issues/issue-62375.rs b/tests/ui/issues/issue-62375.rs new file mode 100644 index 000000000..a2c8fe551 --- /dev/null +++ b/tests/ui/issues/issue-62375.rs @@ -0,0 +1,9 @@ +enum A { + Value(()) +} + +fn main() { + let a = A::Value(()); + a == A::Value; + //~^ ERROR binary operation `==` cannot be applied to type `A` +} diff --git a/tests/ui/issues/issue-62375.stderr b/tests/ui/issues/issue-62375.stderr new file mode 100644 index 000000000..478e025be --- /dev/null +++ b/tests/ui/issues/issue-62375.stderr @@ -0,0 +1,21 @@ +error[E0369]: binary operation `==` cannot be applied to type `A` + --> $DIR/issue-62375.rs:7:7 + | +LL | a == A::Value; + | - ^^ -------- fn(()) -> A {A::Value} + | | + | A + | +note: an implementation of `PartialEq<_>` might be missing for `A` + --> $DIR/issue-62375.rs:1:1 + | +LL | enum A { + | ^^^^^^ must implement `PartialEq<_>` +help: consider annotating `A` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/issues/issue-62480.rs b/tests/ui/issues/issue-62480.rs new file mode 100644 index 000000000..94a9c2ab8 --- /dev/null +++ b/tests/ui/issues/issue-62480.rs @@ -0,0 +1,10 @@ +fn main() { + // This used to ICE during liveness check because `target_id` passed to + // `propagate_through_expr` would be the closure and not the `loop`, which wouldn't be found in + // `self.break_ln`. (#62480) + 'a: { + || break 'a + //~^ ERROR use of unreachable label `'a` + //~| ERROR `break` inside of a closure + } +} diff --git a/tests/ui/issues/issue-62480.stderr b/tests/ui/issues/issue-62480.stderr new file mode 100644 index 000000000..db2305370 --- /dev/null +++ b/tests/ui/issues/issue-62480.stderr @@ -0,0 +1,22 @@ +error[E0767]: use of unreachable label `'a` + --> $DIR/issue-62480.rs:6:18 + | +LL | 'a: { + | -- unreachable label defined here +LL | || break 'a + | ^^ unreachable label `'a` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error[E0267]: `break` inside of a closure + --> $DIR/issue-62480.rs:6:12 + | +LL | || break 'a + | -- ^^^^^^^^ cannot `break` inside of a closure + | | + | enclosing closure + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0267, E0767. +For more information about an error, try `rustc --explain E0267`. diff --git a/tests/ui/issues/issue-6318.rs b/tests/ui/issues/issue-6318.rs new file mode 100644 index 000000000..e5f245f6f --- /dev/null +++ b/tests/ui/issues/issue-6318.rs @@ -0,0 +1,20 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub enum Thing { + A(Box) +} + +pub trait Foo { + fn dummy(&self) { } +} + +pub struct Struct; + +impl Foo for Struct {} + +pub fn main() { + match Thing::A(Box::new(Struct) as Box) { + Thing::A(_a) => 0, + }; +} diff --git a/tests/ui/issues/issue-6344-let.rs b/tests/ui/issues/issue-6344-let.rs new file mode 100644 index 000000000..a7b6a2e2d --- /dev/null +++ b/tests/ui/issues/issue-6344-let.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct A { x: usize } + +impl Drop for A { + fn drop(&mut self) {} +} + +pub fn main() { + let a = A { x: 0 }; + + let A { x: ref x } = a; + println!("{}", x) +} diff --git a/tests/ui/issues/issue-6344-match.rs b/tests/ui/issues/issue-6344-match.rs new file mode 100644 index 000000000..4505a34c7 --- /dev/null +++ b/tests/ui/issues/issue-6344-match.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct A { x: usize } + +impl Drop for A { + fn drop(&mut self) {} +} + +pub fn main() { + let a = A { x: 0 }; + + match a { + A { x : ref x } => { + println!("{}", x) + } + } +} diff --git a/tests/ui/issues/issue-63983.rs b/tests/ui/issues/issue-63983.rs new file mode 100644 index 000000000..ab952666f --- /dev/null +++ b/tests/ui/issues/issue-63983.rs @@ -0,0 +1,15 @@ +enum MyEnum { + Tuple(i32), + Struct{ s: i32 }, +} + +fn foo(en: MyEnum) { + match en { + MyEnum::Tuple => "", +//~^ ERROR expected unit struct, unit variant or constant, found tuple variant `MyEnum::Tuple` + MyEnum::Struct => "", +//~^ ERROR expected unit struct, unit variant or constant, found struct variant `MyEnum::Struct` + }; +} + +fn main() {} diff --git a/tests/ui/issues/issue-63983.stderr b/tests/ui/issues/issue-63983.stderr new file mode 100644 index 000000000..f90c81116 --- /dev/null +++ b/tests/ui/issues/issue-63983.stderr @@ -0,0 +1,19 @@ +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `MyEnum::Tuple` + --> $DIR/issue-63983.rs:8:9 + | +LL | Tuple(i32), + | ---------- `MyEnum::Tuple` defined here +... +LL | MyEnum::Tuple => "", + | ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyEnum::Tuple(_)` + +error[E0533]: expected unit struct, unit variant or constant, found struct variant `MyEnum::Struct` + --> $DIR/issue-63983.rs:10:9 + | +LL | MyEnum::Struct => "", + | ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0532, E0533. +For more information about an error, try `rustc --explain E0532`. diff --git a/tests/ui/issues/issue-64430.rs b/tests/ui/issues/issue-64430.rs new file mode 100644 index 000000000..0bc66e06e --- /dev/null +++ b/tests/ui/issues/issue-64430.rs @@ -0,0 +1,14 @@ +// compile-flags:-C panic=abort + +#![no_std] +pub struct Foo; + +fn main() { + Foo.bar() + //~^ ERROR E0599 +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop{} +} diff --git a/tests/ui/issues/issue-64430.stderr b/tests/ui/issues/issue-64430.stderr new file mode 100644 index 000000000..b6b1f3a66 --- /dev/null +++ b/tests/ui/issues/issue-64430.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `bar` found for struct `Foo` in the current scope + --> $DIR/issue-64430.rs:7:9 + | +LL | pub struct Foo; + | -------------- method `bar` not found for this struct +... +LL | Foo.bar() + | ^^^ method not found in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-64559.rs b/tests/ui/issues/issue-64559.rs new file mode 100644 index 000000000..71e054b5d --- /dev/null +++ b/tests/ui/issues/issue-64559.rs @@ -0,0 +1,6 @@ +fn main() { + let orig = vec![true]; + for _val in orig {} + let _closure = || orig; + //~^ ERROR use of moved value: `orig` +} diff --git a/tests/ui/issues/issue-64559.stderr b/tests/ui/issues/issue-64559.stderr new file mode 100644 index 000000000..386ac794d --- /dev/null +++ b/tests/ui/issues/issue-64559.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `orig` + --> $DIR/issue-64559.rs:4:20 + | +LL | let orig = vec![true]; + | ---- move occurs because `orig` has type `Vec`, which does not implement the `Copy` trait +LL | for _val in orig {} + | ---- `orig` moved due to this implicit call to `.into_iter()` +LL | let _closure = || orig; + | ^^ ---- use occurs due to use in closure + | | + | value used here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `orig` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider iterating over a slice of the `Vec`'s content to avoid moving into the `for` loop + | +LL | for _val in &orig {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-6458-1.rs b/tests/ui/issues/issue-6458-1.rs new file mode 100644 index 000000000..184e4832b --- /dev/null +++ b/tests/ui/issues/issue-6458-1.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn foo(t: T) {} +fn main() { + foo(panic!()) +} diff --git a/tests/ui/issues/issue-6458-2.rs b/tests/ui/issues/issue-6458-2.rs new file mode 100644 index 000000000..b18cae3ed --- /dev/null +++ b/tests/ui/issues/issue-6458-2.rs @@ -0,0 +1,5 @@ +fn main() { + // Unconstrained type: + format!("{:?}", None); + //~^ ERROR type annotations needed [E0282] +} diff --git a/tests/ui/issues/issue-6458-2.stderr b/tests/ui/issues/issue-6458-2.stderr new file mode 100644 index 000000000..8dbdd9a27 --- /dev/null +++ b/tests/ui/issues/issue-6458-2.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-6458-2.rs:3:21 + | +LL | format!("{:?}", None); + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | format!("{:?}", None::); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-6458-3.rs b/tests/ui/issues/issue-6458-3.rs new file mode 100644 index 000000000..d4f8886e9 --- /dev/null +++ b/tests/ui/issues/issue-6458-3.rs @@ -0,0 +1,6 @@ +use std::mem; + +fn main() { + mem::transmute(0); + //~^ ERROR type annotations needed [E0282] +} diff --git a/tests/ui/issues/issue-6458-3.stderr b/tests/ui/issues/issue-6458-3.stderr new file mode 100644 index 000000000..520efccae --- /dev/null +++ b/tests/ui/issues/issue-6458-3.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-6458-3.rs:4:5 + | +LL | mem::transmute(0); + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `Dst` declared on the function `transmute` + | +help: consider specifying the generic arguments + | +LL | mem::transmute::(0); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-6458-4.rs b/tests/ui/issues/issue-6458-4.rs new file mode 100644 index 000000000..054a5c15c --- /dev/null +++ b/tests/ui/issues/issue-6458-4.rs @@ -0,0 +1,7 @@ +fn foo(b: bool) -> Result { //~ ERROR mismatched types + Err("bar".to_string()); +} + +fn main() { + foo(false); +} diff --git a/tests/ui/issues/issue-6458-4.stderr b/tests/ui/issues/issue-6458-4.stderr new file mode 100644 index 000000000..168ececac --- /dev/null +++ b/tests/ui/issues/issue-6458-4.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-6458-4.rs:1:20 + | +LL | fn foo(b: bool) -> Result { + | --- ^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | Err("bar".to_string()); + | - help: remove this semicolon to return this value + | + = note: expected enum `Result` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-6458.rs b/tests/ui/issues/issue-6458.rs new file mode 100644 index 000000000..16718e90d --- /dev/null +++ b/tests/ui/issues/issue-6458.rs @@ -0,0 +1,14 @@ +use std::marker; + +pub struct TypeWithState(marker::PhantomData); +pub struct MyState; + +pub fn foo(_: TypeWithState) {} + +pub fn bar() { + foo(TypeWithState(marker::PhantomData)); + //~^ ERROR type annotations needed [E0282] +} + +fn main() { +} diff --git a/tests/ui/issues/issue-6458.stderr b/tests/ui/issues/issue-6458.stderr new file mode 100644 index 000000000..2e93c1385 --- /dev/null +++ b/tests/ui/issues/issue-6458.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-6458.rs:9:22 + | +LL | foo(TypeWithState(marker::PhantomData)); + | ^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` + | +help: consider specifying the generic argument + | +LL | foo(TypeWithState(marker::PhantomData::)); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-64593.rs b/tests/ui/issues/issue-64593.rs new file mode 100644 index 000000000..9e787f638 --- /dev/null +++ b/tests/ui/issues/issue-64593.rs @@ -0,0 +1,12 @@ +// check-pass +#![deny(improper_ctypes)] + +pub struct Error(std::num::NonZeroU32); + +extern "Rust" { + fn foo(dest: &mut [u8]) -> Result<(), Error>; +} + +fn main() { + let _ = unsafe { foo(&mut []) }; +} diff --git a/tests/ui/issues/issue-64792-bad-unicode-ctor.rs b/tests/ui/issues/issue-64792-bad-unicode-ctor.rs new file mode 100644 index 000000000..f1427ef46 --- /dev/null +++ b/tests/ui/issues/issue-64792-bad-unicode-ctor.rs @@ -0,0 +1,5 @@ +struct X {} + +const Y: X = X("ö"); //~ ERROR expected function, tuple struct or tuple variant, found struct `X` + +fn main() {} diff --git a/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr b/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr new file mode 100644 index 000000000..2ec151d24 --- /dev/null +++ b/tests/ui/issues/issue-64792-bad-unicode-ctor.stderr @@ -0,0 +1,12 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `X` + --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14 + | +LL | struct X {} + | ----------- `X` defined here +LL | +LL | const Y: X = X("ö"); + | ^^^^^^ help: use struct literal syntax instead: `X {}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/issues/issue-65131.rs b/tests/ui/issues/issue-65131.rs new file mode 100644 index 000000000..8b5345da9 --- /dev/null +++ b/tests/ui/issues/issue-65131.rs @@ -0,0 +1,18 @@ +fn get_pair(_a: &mut u32, _b: &mut u32) {} + +macro_rules! x10 { + ($($t:tt)*) => { + $($t)* $($t)* $($t)* $($t)* $($t)* + $($t)* $($t)* $($t)* $($t)* $($t)* + } +} + +#[allow(unused_assignments)] +fn main() { + let mut x = 1; + + get_pair(&mut x, &mut x); + //~^ ERROR: cannot borrow `x` as mutable more than once at a time + + x10! { x10!{ x10!{ if x > 0 { x += 2 } else { x += 1 } } } } +} diff --git a/tests/ui/issues/issue-65131.stderr b/tests/ui/issues/issue-65131.stderr new file mode 100644 index 000000000..e234e6da5 --- /dev/null +++ b/tests/ui/issues/issue-65131.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/issue-65131.rs:14:22 + | +LL | get_pair(&mut x, &mut x); + | -------- ------ ^^^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-65230.rs b/tests/ui/issues/issue-65230.rs new file mode 100644 index 000000000..54141d221 --- /dev/null +++ b/tests/ui/issues/issue-65230.rs @@ -0,0 +1,11 @@ +trait T0 {} +trait T1: T0 {} + +trait T2 {} + +impl<'a> T0 for &'a (dyn T2 + 'static) {} + +impl T1 for &dyn T2 {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/issues/issue-65230.stderr b/tests/ui/issues/issue-65230.stderr new file mode 100644 index 000000000..7ccab8894 --- /dev/null +++ b/tests/ui/issues/issue-65230.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-65230.rs:8:13 + | +LL | impl T1 for &dyn T2 {} + | ^^^^^^^ lifetime mismatch + | + = note: expected trait `<&dyn T2 as T0>` + found trait `<&(dyn T2 + 'static) as T0>` +note: the anonymous lifetime as defined here... + --> $DIR/issue-65230.rs:8:13 + | +LL | impl T1 for &dyn T2 {} + | ^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-65462.rs b/tests/ui/issues/issue-65462.rs new file mode 100644 index 000000000..8c39ea531 --- /dev/null +++ b/tests/ui/issues/issue-65462.rs @@ -0,0 +1,15 @@ +// build-pass + +enum Empty {} +enum Enum { + Empty( Empty ) +} + +fn foobar() -> Option< Enum > { + let value: Option< Empty > = None; + Some( Enum::Empty( value? ) ) +} + +fn main() { + foobar(); +} diff --git a/tests/ui/issues/issue-6557.rs b/tests/ui/issues/issue-6557.rs new file mode 100644 index 000000000..757e9608f --- /dev/null +++ b/tests/ui/issues/issue-6557.rs @@ -0,0 +1,9 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#![feature(box_patterns)] + +fn foo(box (_x, _y): Box<(isize, isize)>) {} + +pub fn main() {} diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr new file mode 100644 index 000000000..d0cb16995 --- /dev/null +++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/issue-65634-raw-ident-suggestion.rs:24:13 + | +LL | r#fn {}.r#struct(); + | ^^^^^^^^ multiple `r#struct` found + | +note: candidate #1 is defined in an impl of the trait `async` for the type `r#fn` + --> $DIR/issue-65634-raw-ident-suggestion.rs:7:5 + | +LL | fn r#struct(&self) { + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn` + --> $DIR/issue-65634-raw-ident-suggestion.rs:13:5 + | +LL | fn r#struct(&self) { + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | async::r#struct(&r#fn {}); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | await::r#struct(&r#fn {}); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr new file mode 100644 index 000000000..a75c1c413 --- /dev/null +++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/issue-65634-raw-ident-suggestion.rs:24:13 + | +LL | r#fn {}.r#struct(); + | ^^^^^^^^ multiple `r#struct` found + | +note: candidate #1 is defined in an impl of the trait `r#async` for the type `r#fn` + --> $DIR/issue-65634-raw-ident-suggestion.rs:7:5 + | +LL | fn r#struct(&self) { + | ^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `r#await` for the type `r#fn` + --> $DIR/issue-65634-raw-ident-suggestion.rs:13:5 + | +LL | fn r#struct(&self) { + | ^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | r#async::r#struct(&r#fn {}); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | r#await::r#struct(&r#fn {}); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.rs b/tests/ui/issues/issue-65634-raw-ident-suggestion.rs new file mode 100644 index 000000000..03dd0340c --- /dev/null +++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.rs @@ -0,0 +1,25 @@ +// revisions: edition2015 edition2018 +//[edition2018]edition:2018 + +#![allow(non_camel_case_types)] + +trait r#async { + fn r#struct(&self) { + println!("async"); + } +} + +trait r#await { + fn r#struct(&self) { + println!("await"); + } +} + +struct r#fn {} + +impl r#async for r#fn {} +impl r#await for r#fn {} + +fn main() { + r#fn {}.r#struct(); //~ ERROR multiple applicable items in scope +} diff --git a/tests/ui/issues/issue-6596-2.rs b/tests/ui/issues/issue-6596-2.rs new file mode 100644 index 000000000..8401c4a9d --- /dev/null +++ b/tests/ui/issues/issue-6596-2.rs @@ -0,0 +1,11 @@ +macro_rules! g { + ($inp:ident) => ( + { $inp $nonexistent } + //~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$` + ); +} + +fn main() { + let foo = 0; + g!(foo); +} diff --git a/tests/ui/issues/issue-6596-2.stderr b/tests/ui/issues/issue-6596-2.stderr new file mode 100644 index 000000000..4fa73a464 --- /dev/null +++ b/tests/ui/issues/issue-6596-2.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$` + --> $DIR/issue-6596-2.rs:3:16 + | +LL | { $inp $nonexistent } + | ^^^^^^^^^^^^ expected one of 8 possible tokens +... +LL | g!(foo); + | ------- in this macro invocation + | + = note: this error originates in the macro `g` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-66308.rs b/tests/ui/issues/issue-66308.rs new file mode 100644 index 000000000..8460b359a --- /dev/null +++ b/tests/ui/issues/issue-66308.rs @@ -0,0 +1,8 @@ +// build-pass +// compile-flags: --crate-type lib -C opt-level=0 + +// Regression test for LLVM crash affecting Emscripten targets + +pub fn foo() { + (0..0).rev().next(); +} diff --git a/tests/ui/issues/issue-66353.rs b/tests/ui/issues/issue-66353.rs new file mode 100644 index 000000000..d8abdd520 --- /dev/null +++ b/tests/ui/issues/issue-66353.rs @@ -0,0 +1,15 @@ +// #66353: ICE when trying to recover from incorrect associated type + +trait _Func { + fn func(_: Self); +} + +trait _A { + type AssocT; +} + +fn main() { + _Func::< <() as _A>::AssocT >::func(()); + //~^ ERROR the trait bound `(): _A` is not satisfied + //~| ERROR the trait bound `(): _Func<_>` is not satisfied +} diff --git a/tests/ui/issues/issue-66353.stderr b/tests/ui/issues/issue-66353.stderr new file mode 100644 index 000000000..335618097 --- /dev/null +++ b/tests/ui/issues/issue-66353.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `(): _A` is not satisfied + --> $DIR/issue-66353.rs:12:14 + | +LL | _Func::< <() as _A>::AssocT >::func(()); + | ^^^^^^^^^^^^^^^^^^ the trait `_A` is not implemented for `()` + +error[E0277]: the trait bound `(): _Func<_>` is not satisfied + --> $DIR/issue-66353.rs:12:41 + | +LL | _Func::< <() as _A>::AssocT >::func(()); + | ----------------------------------- ^^ the trait `_Func<_>` is not implemented for `()` + | | + | required by a bound introduced by this call + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-6642.rs b/tests/ui/issues/issue-6642.rs new file mode 100644 index 000000000..f80f6fffe --- /dev/null +++ b/tests/ui/issues/issue-6642.rs @@ -0,0 +1,9 @@ +struct A; +impl A { + fn m(&self) { + fn x() { + self.m() //~ ERROR can't capture dynamic environment in a fn item + } + } +} +fn main() {} diff --git a/tests/ui/issues/issue-6642.stderr b/tests/ui/issues/issue-6642.stderr new file mode 100644 index 000000000..6668108d0 --- /dev/null +++ b/tests/ui/issues/issue-6642.stderr @@ -0,0 +1,11 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/issue-6642.rs:5:13 + | +LL | self.m() + | ^^^^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.rs b/tests/ui/issues/issue-66667-function-cmp-cycle.rs new file mode 100644 index 000000000..7b025be11 --- /dev/null +++ b/tests/ui/issues/issue-66667-function-cmp-cycle.rs @@ -0,0 +1,16 @@ +fn first() { + second == 1 //~ ERROR binary operation + //~^ ERROR mismatched types +} + +fn second() { + first == 1 //~ ERROR binary operation + //~^ ERROR mismatched types +} + +fn bar() { + bar == 1 //~ ERROR binary operation + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr new file mode 100644 index 000000000..887699ef5 --- /dev/null +++ b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr @@ -0,0 +1,55 @@ +error[E0369]: binary operation `==` cannot be applied to type `fn() {second}` + --> $DIR/issue-66667-function-cmp-cycle.rs:2:12 + | +LL | second == 1 + | ------ ^^ - {integer} + | | + | fn() {second} + +error[E0308]: mismatched types + --> $DIR/issue-66667-function-cmp-cycle.rs:2:15 + | +LL | second == 1 + | ^ expected fn item, found integer + | + = note: expected fn item `fn() {second}` + found type `{integer}` + +error[E0369]: binary operation `==` cannot be applied to type `fn() {first}` + --> $DIR/issue-66667-function-cmp-cycle.rs:7:11 + | +LL | first == 1 + | ----- ^^ - {integer} + | | + | fn() {first} + +error[E0308]: mismatched types + --> $DIR/issue-66667-function-cmp-cycle.rs:7:14 + | +LL | first == 1 + | ^ expected fn item, found integer + | + = note: expected fn item `fn() {first}` + found type `{integer}` + +error[E0369]: binary operation `==` cannot be applied to type `fn() {bar}` + --> $DIR/issue-66667-function-cmp-cycle.rs:12:9 + | +LL | bar == 1 + | --- ^^ - {integer} + | | + | fn() {bar} + +error[E0308]: mismatched types + --> $DIR/issue-66667-function-cmp-cycle.rs:12:12 + | +LL | bar == 1 + | ^ expected fn item, found integer + | + = note: expected fn item `fn() {bar}` + found type `{integer}` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-66702-break-outside-loop-val.rs b/tests/ui/issues/issue-66702-break-outside-loop-val.rs new file mode 100644 index 000000000..05b86cbbf --- /dev/null +++ b/tests/ui/issues/issue-66702-break-outside-loop-val.rs @@ -0,0 +1,9 @@ +// Breaks with values inside closures used to ICE (#66863) + +fn main() { + 'some_label: loop { + || break 'some_label (); + //~^ ERROR: use of unreachable label `'some_label` + //~| ERROR: `break` inside of a closure + } +} diff --git a/tests/ui/issues/issue-66702-break-outside-loop-val.stderr b/tests/ui/issues/issue-66702-break-outside-loop-val.stderr new file mode 100644 index 000000000..f92ede311 --- /dev/null +++ b/tests/ui/issues/issue-66702-break-outside-loop-val.stderr @@ -0,0 +1,22 @@ +error[E0767]: use of unreachable label `'some_label` + --> $DIR/issue-66702-break-outside-loop-val.rs:5:18 + | +LL | 'some_label: loop { + | ----------- unreachable label defined here +LL | || break 'some_label (); + | ^^^^^^^^^^^ unreachable label `'some_label` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error[E0267]: `break` inside of a closure + --> $DIR/issue-66702-break-outside-loop-val.rs:5:12 + | +LL | || break 'some_label (); + | -- ^^^^^^^^^^^^^^^^^^^^ cannot `break` inside of a closure + | | + | enclosing closure + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0267, E0767. +For more information about an error, try `rustc --explain E0267`. diff --git a/tests/ui/issues/issue-66706.rs b/tests/ui/issues/issue-66706.rs new file mode 100644 index 000000000..835fdfae8 --- /dev/null +++ b/tests/ui/issues/issue-66706.rs @@ -0,0 +1,22 @@ +fn a() { + [0; [|_: _ &_| ()].len()] + //~^ ERROR expected `,`, found `&` + //~| ERROR type annotations needed +} + +fn b() { + [0; [|f @ &ref _| {} ; 0 ].len() ]; + //~^ ERROR expected identifier, found reserved identifier `_` +} + +fn c() { + [0; [|&_: _ &_| {}; 0 ].len()] + //~^ ERROR expected `,`, found `&` +} + +fn d() { + [0; match [|f @ &ref _| () ] {} ] + //~^ ERROR expected identifier, found reserved identifier `_` +} + +fn main() {} diff --git a/tests/ui/issues/issue-66706.stderr b/tests/ui/issues/issue-66706.stderr new file mode 100644 index 000000000..8a30c0cad --- /dev/null +++ b/tests/ui/issues/issue-66706.stderr @@ -0,0 +1,37 @@ +error: expected `,`, found `&` + --> $DIR/issue-66706.rs:2:16 + | +LL | [0; [|_: _ &_| ()].len()] + | -^ expected `,` + | | + | help: missing `,` + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-66706.rs:8:20 + | +LL | [0; [|f @ &ref _| {} ; 0 ].len() ]; + | ^ expected identifier, found reserved identifier + +error: expected `,`, found `&` + --> $DIR/issue-66706.rs:13:17 + | +LL | [0; [|&_: _ &_| {}; 0 ].len()] + | -^ expected `,` + | | + | help: missing `,` + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-66706.rs:18:26 + | +LL | [0; match [|f @ &ref _| () ] {} ] + | ^ expected identifier, found reserved identifier + +error[E0282]: type annotations needed + --> $DIR/issue-66706.rs:2:11 + | +LL | [0; [|_: _ &_| ()].len()] + | ^ cannot infer type + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-66768.rs b/tests/ui/issues/issue-66768.rs new file mode 100644 index 000000000..ce42c8b01 --- /dev/null +++ b/tests/ui/issues/issue-66768.rs @@ -0,0 +1,205 @@ +// Regression test for #66768. +// check-pass +#![allow(dead_code)] +//-^ "dead code" is needed to reproduce the issue. + +use std::marker::PhantomData; +use std::ops::{Add, Mul}; + +fn problematic_function(material_surface_element: Edge2dElement) +where + DefaultAllocator: FiniteElementAllocator, +{ + let _: Point2 = material_surface_element.map_reference_coords().into(); +} + +impl ArrayLength for UTerm { + type ArrayType = (); +} +impl> ArrayLength for UInt { + type ArrayType = GenericArrayImplEven; +} +impl> ArrayLength for UInt { + type ArrayType = GenericArrayImplOdd; +} +impl Add for UTerm { + type Output = U; + fn add(self, _: U) -> Self::Output { + unimplemented!() + } +} +impl Add> for UInt +where + Ul: Add, +{ + type Output = UInt, B1>; + fn add(self, _: UInt) -> Self::Output { + unimplemented!() + } +} +impl Mul for UTerm { + type Output = UTerm; + fn mul(self, _: U) -> Self { + unimplemented!() + } +} +impl Mul> for UInt +where + Ul: Mul>, +{ + type Output = UInt>, B0>; + fn mul(self, _: UInt) -> Self::Output { + unimplemented!() + } +} +impl Mul> for UInt +where + Ul: Mul>, + UInt>, B0>: Add>, +{ + type Output = Sum>, B0>, UInt>; + fn mul(self, _: UInt) -> Self::Output { + unimplemented!() + } +} +impl Allocator for DefaultAllocator +where + R: DimName, + C: DimName, + R::Value: Mul, + Prod: ArrayLength, +{ + type Buffer = ArrayStorage; + fn allocate_uninitialized(_: R, _: C) -> Self::Buffer { + unimplemented!() + } + fn allocate_from_iterator(_: R, _: C, _: I) -> Self::Buffer { + unimplemented!() + } +} +impl Allocator for DefaultAllocator { + type Buffer = VecStorage; + fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer { + unimplemented!() + } + fn allocate_from_iterator(_: Dynamic, _: C, _: I) -> Self::Buffer { + unimplemented!() + } +} +impl DimName for DimU1 { + type Value = U1; + fn name() -> Self { + unimplemented!() + } +} +impl DimName for DimU2 { + type Value = U2; + fn name() -> Self { + unimplemented!() + } +} +impl From> for Point +where + DefaultAllocator: Allocator, +{ + fn from(_: VectorN) -> Self { + unimplemented!() + } +} +impl FiniteElementAllocator for DefaultAllocator where + DefaultAllocator: Allocator + Allocator +{ +} +impl ReferenceFiniteElement for Edge2dElement { + type NodalDim = DimU1; +} +impl FiniteElement for Edge2dElement { + fn map_reference_coords(&self) -> Vector2 { + unimplemented!() + } +} + +type Owned = >::Buffer; +type MatrixMN = Matrix>; +type VectorN = MatrixMN; +type Vector2 = VectorN; +type Point2 = Point; +type U1 = UInt; +type U2 = UInt, B0>; +type Sum = >::Output; +type Prod = >::Output; + +struct GenericArray> { + _data: U::ArrayType, +} +struct GenericArrayImplEven { + _parent2: U, + _marker: T, +} +struct GenericArrayImplOdd { + _parent2: U, + _data: T, +} +struct B0; +struct B1; +struct UTerm; +struct UInt { + _marker: PhantomData<(U, B)>, +} +struct DefaultAllocator; +struct Dynamic; +struct DimU1; +struct DimU2; +struct Matrix { + _data: S, + _phantoms: PhantomData<(N, R, C)>, +} +struct ArrayStorage +where + R: DimName, + C: DimName, + R::Value: Mul, + Prod: ArrayLength, +{ + _data: GenericArray>, +} +struct VecStorage { + _data: N, + _nrows: R, + _ncols: C, +} +struct Point +where + DefaultAllocator: Allocator, +{ + _coords: VectorN, +} +struct Edge2dElement; + +trait ArrayLength { + type ArrayType; +} +trait Allocator { + type Buffer; + fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer; + fn allocate_from_iterator(nrows: R, ncols: C, iter: I) -> Self::Buffer; +} +trait DimName { + type Value; + fn name() -> Self; +} +trait FiniteElementAllocator: + Allocator + Allocator +{ +} +trait ReferenceFiniteElement { + type NodalDim; +} +trait FiniteElement: ReferenceFiniteElement +where + DefaultAllocator: FiniteElementAllocator, +{ + fn map_reference_coords(&self) -> VectorN; +} + +fn main() {} diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.rs b/tests/ui/issues/issue-66923-show-error-for-correct-call.rs new file mode 100644 index 000000000..833280739 --- /dev/null +++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.rs @@ -0,0 +1,15 @@ +// This test checks that errors are showed for lines with `collect` rather than `push` method. + +fn main() { + let v = vec![1_f64, 2.2_f64]; + let mut fft: Vec> = vec![]; + + let x1: &[f64] = &v; + let x2: Vec = x1.into_iter().collect(); + //~^ ERROR a value of type + fft.push(x2); + + let x3 = x1.into_iter().collect::>(); + //~^ ERROR a value of type + fft.push(x3); +} diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr new file mode 100644 index 000000000..cec482a53 --- /dev/null +++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -0,0 +1,40 @@ +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39 + | +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&f64>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 + | +LL | let x1: &[f64] = &v; + | -- this expression has type `&Vec` +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^^^^^ `Iterator::Item` is `&f64` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 + | +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&f64>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 + | +LL | let x1: &[f64] = &v; + | -- this expression has type `&Vec` +... +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^^^^^ `Iterator::Item` is `&f64` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.rs b/tests/ui/issues/issue-67039-unsound-pin-partialeq.rs new file mode 100644 index 000000000..a496e58a7 --- /dev/null +++ b/tests/ui/issues/issue-67039-unsound-pin-partialeq.rs @@ -0,0 +1,27 @@ +// Pin's PartialEq implementation allowed to access the pointer allowing for +// unsoundness by using Rc::get_mut to move value within Rc. +// See https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73 for more details. + +use std::ops::Deref; +use std::pin::Pin; +use std::rc::Rc; + +struct Apple; + +impl Deref for Apple { + type Target = Apple; + fn deref(&self) -> &Apple { + &Apple + } +} + +impl PartialEq> for Apple { + fn eq(&self, _rc: &Rc) -> bool { + unreachable!() + } +} + +fn main() { + let _ = Pin::new(Apple) == Rc::pin(Apple); + //~^ ERROR type mismatch resolving +} diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr new file mode 100644 index 000000000..37e2c3bdd --- /dev/null +++ b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr @@ -0,0 +1,13 @@ +error[E0271]: type mismatch resolving ` as Deref>::Target == Rc` + --> $DIR/issue-67039-unsound-pin-partialeq.rs:25:29 + | +LL | let _ = Pin::new(Apple) == Rc::pin(Apple); + | ^^ expected struct `Apple`, found struct `Rc` + | + = note: expected struct `Apple` + found struct `Rc` + = note: required for `Pin` to implement `PartialEq>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-6738.rs b/tests/ui/issues/issue-6738.rs new file mode 100644 index 000000000..a2f8dfe9c --- /dev/null +++ b/tests/ui/issues/issue-6738.rs @@ -0,0 +1,10 @@ +struct Foo { + x: T, +} +impl Foo { + fn add(&mut self, v: Foo){ + self.x += v.x; + //~^ ERROR: binary assignment operation `+=` cannot be applied + } +} +fn main() {} diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/issues/issue-6738.stderr new file mode 100644 index 000000000..f97d899c2 --- /dev/null +++ b/tests/ui/issues/issue-6738.stderr @@ -0,0 +1,16 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `T` + --> $DIR/issue-6738.rs:6:9 + | +LL | self.x += v.x; + | ------^^^^^^^ + | | + | cannot use `+=` on type `T` + | +help: consider restricting type parameter `T` + | +LL | impl Foo { + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/issues/issue-67535.rs b/tests/ui/issues/issue-67535.rs new file mode 100644 index 000000000..24f506213 --- /dev/null +++ b/tests/ui/issues/issue-67535.rs @@ -0,0 +1,22 @@ +fn main() {} + +impl std::ops::AddAssign for () { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: ()) -> () { + () + } +} + +impl std::ops::AddAssign for [(); 1] { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: [(); 1]) -> [(); 1] { + [()] + } +} + +impl std::ops::AddAssign for &[u8] { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: &[u8]) -> &[u8] { + self + } +} diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr new file mode 100644 index 000000000..4d7a02a50 --- /dev/null +++ b/tests/ui/issues/issue-67535.stderr @@ -0,0 +1,39 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:3:1 + | +LL | impl std::ops::AddAssign for () { + | ^^^^^-------------------^^^^^-- + | | | | + | | | this is not defined in the current crate because tuples are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:10:1 + | +LL | impl std::ops::AddAssign for [(); 1] { + | ^^^^^-------------------^^^^^------- + | | | | + | | | this is not defined in the current crate because arrays are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:17:1 + | +LL | impl std::ops::AddAssign for &[u8] { + | ^^^^^-------------------^^^^^----- + | | | | + | | | this is not defined in the current crate because slices are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/issues/issue-67552.polonius.stderr b/tests/ui/issues/issue-67552.polonius.stderr new file mode 100644 index 000000000..9ab77d344 --- /dev/null +++ b/tests/ui/issues/issue-67552.polonius.stderr @@ -0,0 +1,17 @@ +error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>` + --> $DIR/issue-67552.rs:28:9 + | +LL | rec(identity(&mut it)) + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `rec` defined here + --> $DIR/issue-67552.rs:21:1 + | +LL | / fn rec(mut it: T) +LL | | where +LL | | T: Iterator, + | |________________^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552.polonius/issue-67552.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-67552.rs b/tests/ui/issues/issue-67552.rs new file mode 100644 index 000000000..ec1997ccd --- /dev/null +++ b/tests/ui/issues/issue-67552.rs @@ -0,0 +1,32 @@ +// build-fail +// compile-flags: -Copt-level=0 +// normalize-stderr-test: ".nll/" -> "/" + +fn main() { + rec(Empty); +} + +struct Empty; + +impl Iterator for Empty { + type Item = (); + fn next<'a>(&'a mut self) -> core::option::Option<()> { + None + } +} + +fn identity(x: T) -> T { + x +} + +fn rec(mut it: T) +where + T: Iterator, +{ + if () == () { + T::count(it); + } else { + rec(identity(&mut it)) + //~^ ERROR reached the recursion limit while instantiating + } +} diff --git a/tests/ui/issues/issue-67552.stderr b/tests/ui/issues/issue-67552.stderr new file mode 100644 index 000000000..4746f918b --- /dev/null +++ b/tests/ui/issues/issue-67552.stderr @@ -0,0 +1,17 @@ +error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut ...>` + --> $DIR/issue-67552.rs:29:9 + | +LL | rec(identity(&mut it)) + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `rec` defined here + --> $DIR/issue-67552.rs:22:1 + | +LL | / fn rec(mut it: T) +LL | | where +LL | | T: Iterator, + | |________________^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552/issue-67552.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-68010-large-zst-consts.rs b/tests/ui/issues/issue-68010-large-zst-consts.rs new file mode 100644 index 000000000..3277df69c --- /dev/null +++ b/tests/ui/issues/issue-68010-large-zst-consts.rs @@ -0,0 +1,5 @@ +// build-pass + +fn main() { + println!("{}", [(); usize::MAX].len()); +} diff --git a/tests/ui/issues/issue-68696-catch-during-unwind.rs b/tests/ui/issues/issue-68696-catch-during-unwind.rs new file mode 100644 index 000000000..2b12a62d0 --- /dev/null +++ b/tests/ui/issues/issue-68696-catch-during-unwind.rs @@ -0,0 +1,25 @@ +// Checks that catch_unwind can be used if unwinding is already in progress. +// Used to fail when standard library had been compiled with debug assertions, +// due to incorrect assumption that a current thread is not panicking when +// entering the catch_unwind. +// +// run-pass + +use std::panic::catch_unwind; + +#[derive(Default)] +struct Guard; + +impl Drop for Guard { + fn drop(&mut self) { + let _ = catch_unwind(|| {}); + } +} + +fn main() { + #[cfg(panic = "unwind")] + let _ = catch_unwind(|| { + let _guard = Guard::default(); + panic!(); + }); +} diff --git a/tests/ui/issues/issue-6892.rs b/tests/ui/issues/issue-6892.rs new file mode 100644 index 000000000..a361461a4 --- /dev/null +++ b/tests/ui/issues/issue-6892.rs @@ -0,0 +1,58 @@ +// run-pass +#![allow(dead_code)] +// Ensures that destructors are run for expressions of the form "let _ = e;" +// where `e` is a type which requires a destructor. + + +struct Foo; +struct Bar { x: isize } +struct Baz(isize); +enum FooBar { _Foo(Foo), _Bar(usize) } + +static mut NUM_DROPS: usize = 0; + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} +impl Drop for Bar { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} +impl Drop for Baz { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} +impl Drop for FooBar { + fn drop(&mut self) { + unsafe { NUM_DROPS += 1; } + } +} + +fn main() { + assert_eq!(unsafe { NUM_DROPS }, 0); + { let _x = Foo; } + assert_eq!(unsafe { NUM_DROPS }, 1); + { let _x = Bar { x: 21 }; } + assert_eq!(unsafe { NUM_DROPS }, 2); + { let _x = Baz(21); } + assert_eq!(unsafe { NUM_DROPS }, 3); + { let _x = FooBar::_Foo(Foo); } + assert_eq!(unsafe { NUM_DROPS }, 5); + { let _x = FooBar::_Bar(42); } + assert_eq!(unsafe { NUM_DROPS }, 6); + + { let _ = Foo; } + assert_eq!(unsafe { NUM_DROPS }, 7); + { let _ = Bar { x: 21 }; } + assert_eq!(unsafe { NUM_DROPS }, 8); + { let _ = Baz(21); } + assert_eq!(unsafe { NUM_DROPS }, 9); + { let _ = FooBar::_Foo(Foo); } + assert_eq!(unsafe { NUM_DROPS }, 11); + { let _ = FooBar::_Bar(42); } + assert_eq!(unsafe { NUM_DROPS }, 12); +} diff --git a/tests/ui/issues/issue-68951.rs b/tests/ui/issues/issue-68951.rs new file mode 100644 index 000000000..1c1e92c5b --- /dev/null +++ b/tests/ui/issues/issue-68951.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + let array = [0x42u8; 10]; + for b in &array { + let lo = b & 0xf; + let hi = (b >> 4) & 0xf; + } +} diff --git a/tests/ui/issues/issue-6898.rs b/tests/ui/issues/issue-6898.rs new file mode 100644 index 000000000..44fd4bd07 --- /dev/null +++ b/tests/ui/issues/issue-6898.rs @@ -0,0 +1,33 @@ +// check-pass +// pretty-expanded FIXME #23616 + +use std::mem; + +/// Returns the size of a type +pub fn size_of() -> usize { + TypeInfo::size_of(None::) +} + +/// Returns the size of the type that `val` points to +pub fn size_of_val(val: &T) -> usize { + val.size_of_val() +} + +pub trait TypeInfo: Sized { + fn size_of(_lame_type_hint: Option) -> usize; + fn size_of_val(&self) -> usize; +} + +impl TypeInfo for T { + /// The size of the type in bytes. + fn size_of(_lame_type_hint: Option) -> usize { + mem::size_of::() + } + + /// Returns the size of the type of `self` in bytes. + fn size_of_val(&self) -> usize { + TypeInfo::size_of(None::) + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-69130.rs b/tests/ui/issues/issue-69130.rs new file mode 100644 index 000000000..9552e8ec2 --- /dev/null +++ b/tests/ui/issues/issue-69130.rs @@ -0,0 +1,7 @@ +// Issue 69130: character indexing bug in rustc_errors::CodeSuggestion::splice_lines(). + +enum F { +M (§& u8)} +//~^ ERROR unknown start of token +//~| missing lifetime specifier +fn main() {} diff --git a/tests/ui/issues/issue-69130.stderr b/tests/ui/issues/issue-69130.stderr new file mode 100644 index 000000000..e67cc295d --- /dev/null +++ b/tests/ui/issues/issue-69130.stderr @@ -0,0 +1,21 @@ +error: unknown start of token: \u{a7} + --> $DIR/issue-69130.rs:4:4 + | +LL | M (§& u8)} + | ^ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-69130.rs:4:5 + | +LL | M (§& u8)} + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ enum F<'a> { +LL ~ M (§&'a u8)} + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-6919.rs b/tests/ui/issues/issue-6919.rs new file mode 100644 index 000000000..6f1e1f977 --- /dev/null +++ b/tests/ui/issues/issue-6919.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_attributes)] +// aux-build:iss.rs + +// pretty-expanded FIXME #23616 + +extern crate issue6919_3; + +pub fn main() { + let _ = issue6919_3::D.k; +} diff --git a/tests/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs b/tests/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs new file mode 100644 index 000000000..6e030f1cc --- /dev/null +++ b/tests/ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs @@ -0,0 +1,33 @@ +// run-fail +// compile-flags: -C opt-level=3 +// error-pattern: index out of bounds: the len is 0 but the index is 16777216 +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +fn do_test(x: usize) { + let mut arr = vec![vec![0u8; 3]]; + + let mut z = vec![0]; + for arr_ref in arr.iter_mut() { + for y in 0..x { + for _ in 0..1 { + z.reserve_exact(x); + let iterator = std::iter::repeat(0).take(x); + let mut cnt = 0; + iterator.for_each(|_| { + z[0] = 0; + cnt += 1; + }); + let a = y * x; + let b = (y + 1) * x - 1; + let slice = &mut arr_ref[a..b]; + slice[1 << 24] += 1; + } + } + } +} + +fn main() { + do_test(1); + do_test(2); +} diff --git a/tests/ui/issues/issue-69225-layout-repeated-checked-add.rs b/tests/ui/issues/issue-69225-layout-repeated-checked-add.rs new file mode 100644 index 000000000..7f43e4d1a --- /dev/null +++ b/tests/ui/issues/issue-69225-layout-repeated-checked-add.rs @@ -0,0 +1,31 @@ +// Ensure we appropriately error instead of overflowing a calculation when creating a new Alloc +// Layout + +// run-fail +// compile-flags: -C opt-level=3 +// error-pattern: index out of bounds: the len is 0 but the index is 16777216 +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +fn do_test(x: usize) { + let arr = vec![vec![0u8; 3]]; + + let mut z = Vec::new(); + for arr_ref in arr { + for y in 0..x { + for _ in 0..1 { + z.extend(std::iter::repeat(0).take(x)); + let a = y * x; + let b = (y + 1) * x - 1; + let slice = &arr_ref[a..b]; + eprintln!("{} {} {} {}", a, b, arr_ref.len(), slice.len()); + eprintln!("{:?}", slice[1 << 24]); + } + } + } +} + +fn main() { + do_test(1); + do_test(2); +} diff --git a/tests/ui/issues/issue-69306.rs b/tests/ui/issues/issue-69306.rs new file mode 100644 index 000000000..85d60952a --- /dev/null +++ b/tests/ui/issues/issue-69306.rs @@ -0,0 +1,45 @@ +fn main() {} + +struct S0(T); +impl S0 { + const C: S0 = Self(0); + //~^ ERROR mismatched types + //~| ERROR mismatched types + + fn foo() { + Self(0); + //~^ ERROR mismatched types + } +} + +// Testing normalization. +trait Fun { + type Out; +} +impl Fun for S0 { + type Out = Self; +} +trait Foo { + fn foo(); +} +impl Foo for as Fun>::Out { + fn foo() { + Self(0); //~ ERROR mismatched types + } +} + +struct S1(T, U); +impl S1 { + const C: S1 = Self(0, 1); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +struct S2(T); +impl S2 { + fn map(x: U) -> S2 { + Self(x) + //~^ ERROR mismatched types + //~| ERROR mismatched types + } +} diff --git a/tests/ui/issues/issue-69306.stderr b/tests/ui/issues/issue-69306.stderr new file mode 100644 index 000000000..61ec5d318 --- /dev/null +++ b/tests/ui/issues/issue-69306.stderr @@ -0,0 +1,138 @@ +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:5:28 + | +LL | impl S0 { + | - this type parameter +LL | const C: S0 = Self(0); + | ---- ^ expected type parameter `T`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found type `{integer}` +note: tuple struct defined here + --> $DIR/issue-69306.rs:3:8 + | +LL | struct S0(T); + | ^^ + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:5:23 + | +LL | impl S0 { + | - this type parameter +LL | const C: S0 = Self(0); + | ^^^^^^^ expected `u8`, found type parameter `T` + | + = note: expected struct `S0` + found struct `S0` + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:10:14 + | +LL | impl S0 { + | - this type parameter +... +LL | Self(0); + | ---- ^ expected type parameter `T`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found type `{integer}` +note: tuple struct defined here + --> $DIR/issue-69306.rs:3:8 + | +LL | struct S0(T); + | ^^ + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:27:14 + | +LL | impl Foo for as Fun>::Out { + | - this type parameter +LL | fn foo() { +LL | Self(0); + | ---- ^ expected type parameter `T`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found type `{integer}` +note: tuple struct defined here + --> $DIR/issue-69306.rs:3:8 + | +LL | struct S0(T); + | ^^ + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:33:32 + | +LL | impl S1 { + | - this type parameter +LL | const C: S1 = Self(0, 1); + | ---- ^ expected type parameter `T`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found type `{integer}` +note: tuple struct defined here + --> $DIR/issue-69306.rs:31:8 + | +LL | struct S1(T, U); + | ^^ + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:33:27 + | +LL | impl S1 { + | - this type parameter +LL | const C: S1 = Self(0, 1); + | ^^^^^^^^^^ expected `u8`, found type parameter `T` + | + = note: expected struct `S1` + found struct `S1` + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:41:14 + | +LL | impl S2 { + | - expected type parameter +LL | fn map(x: U) -> S2 { + | - found type parameter +LL | Self(x) + | ---- ^ expected type parameter `T`, found type parameter `U` + | | + | arguments to this function are incorrect + | + = note: expected type parameter `T` + found type parameter `U` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: tuple struct defined here + --> $DIR/issue-69306.rs:38:8 + | +LL | struct S2(T); + | ^^ + +error[E0308]: mismatched types + --> $DIR/issue-69306.rs:41:9 + | +LL | impl S2 { + | - found type parameter +LL | fn map(x: U) -> S2 { + | - ----- expected `S2` because of return type + | | + | expected type parameter +LL | Self(x) + | ^^^^^^^ expected type parameter `U`, found type parameter `T` + | + = note: expected struct `S2` + found struct `S2` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-6936.rs b/tests/ui/issues/issue-6936.rs new file mode 100644 index 000000000..26531bba9 --- /dev/null +++ b/tests/ui/issues/issue-6936.rs @@ -0,0 +1,34 @@ +struct T; + +mod t1 { + type Foo = ::T; + mod Foo {} //~ ERROR the name `Foo` is defined multiple times +} + +mod t2 { + type Foo = ::T; + struct Foo; //~ ERROR the name `Foo` is defined multiple times +} + +mod t3 { + type Foo = ::T; + enum Foo {} //~ ERROR the name `Foo` is defined multiple times +} + +mod t4 { + type Foo = ::T; + fn Foo() {} // ok +} + +mod t5 { + type Bar = T; + mod Bar {} //~ ERROR the name `Bar` is defined multiple times +} + +mod t6 { + type Foo = ::T; + impl Foo {} // ok +} + + +fn main() {} diff --git a/tests/ui/issues/issue-6936.stderr b/tests/ui/issues/issue-6936.stderr new file mode 100644 index 000000000..9292d60ca --- /dev/null +++ b/tests/ui/issues/issue-6936.stderr @@ -0,0 +1,43 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-6936.rs:5:5 + | +LL | type Foo = ::T; + | --------------- previous definition of the type `Foo` here +LL | mod Foo {} + | ^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-6936.rs:10:5 + | +LL | type Foo = ::T; + | --------------- previous definition of the type `Foo` here +LL | struct Foo; + | ^^^^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-6936.rs:15:5 + | +LL | type Foo = ::T; + | --------------- previous definition of the type `Foo` here +LL | enum Foo {} + | ^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0428]: the name `Bar` is defined multiple times + --> $DIR/issue-6936.rs:25:5 + | +LL | type Bar = T; + | ---------------- previous definition of the type `Bar` here +LL | mod Bar {} + | ^^^^^^^ `Bar` redefined here + | + = note: `Bar` must be defined only once in the type namespace of this module + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-69396-const-no-type-in-macro.rs b/tests/ui/issues/issue-69396-const-no-type-in-macro.rs new file mode 100644 index 000000000..45a308574 --- /dev/null +++ b/tests/ui/issues/issue-69396-const-no-type-in-macro.rs @@ -0,0 +1,17 @@ +macro_rules! suite { + ( $( $fn:ident; )* ) => { + $( + const A = "A".$fn(); + //~^ ERROR the name `A` is defined multiple times + //~| ERROR missing type for `const` item + //~| ERROR the placeholder `_` is not allowed within types on item signatures for constants + )* + } +} + +suite! { + len; + is_empty; +} + +fn main() {} diff --git a/tests/ui/issues/issue-69396-const-no-type-in-macro.stderr b/tests/ui/issues/issue-69396-const-no-type-in-macro.stderr new file mode 100644 index 000000000..89aeafeba --- /dev/null +++ b/tests/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -0,0 +1,50 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13 + | +LL | const A = "A".$fn(); + | ^^^^^^^^^^^^^^^^^^^^ `A` redefined here +... +LL | / suite! { +LL | | len; +LL | | is_empty; +LL | | } + | |_- in this macro invocation + | + = note: `A` must be defined only once in the value namespace of this module + = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: missing type for `const` item + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20 + | +LL | const A = "A".$fn(); + | ^ help: provide a type for the constant: `: usize` +... +LL | / suite! { +LL | | len; +LL | | is_empty; +LL | | } + | |_- in this macro invocation + | + = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:20 + | +LL | const A = "A".$fn(); + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `bool` +... +LL | / suite! { +LL | | len; +LL | | is_empty; +LL | | } + | |_- in this macro invocation + | + = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0121, E0428. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/issues/issue-69455.rs b/tests/ui/issues/issue-69455.rs new file mode 100644 index 000000000..a53aadcfa --- /dev/null +++ b/tests/ui/issues/issue-69455.rs @@ -0,0 +1,31 @@ +// Regression test for #69455: projection predicate was not satisfied. +// Compiler should indicate the correct location of the +// unsatisfied projection predicate + +pub trait Test { + type Output; + + fn test(self, rhs: Rhs) -> Self::Output; +} + +impl Test for u64 { + type Output = u64; + + fn test(self, other: u32) -> u64 { + self + (other as u64) + } +} + +impl Test for u64 { + type Output = u64; + + fn test(self, other: u64) -> u64 { + (self + other) as u64 + } +} + +fn main() { + let xs: Vec = vec![1, 2, 3]; + println!("{}", 23u64.test(xs.iter().sum())); //~ ERROR: type annotations needed + //~^ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-69455.stderr b/tests/ui/issues/issue-69455.stderr new file mode 100644 index 000000000..fc343bb54 --- /dev/null +++ b/tests/ui/issues/issue-69455.stderr @@ -0,0 +1,39 @@ +error[E0284]: type annotations needed + --> $DIR/issue-69455.rs:29:41 + | +LL | println!("{}", 23u64.test(xs.iter().sum())); + | ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | | + | type must be known at this point + | + = note: cannot satisfy `>::Output == _` +help: consider specifying the generic argument + | +LL | println!("{}", 23u64.test(xs.iter().sum::())); + | +++++ + +error[E0283]: type annotations needed + --> $DIR/issue-69455.rs:29:41 + | +LL | println!("{}", 23u64.test(xs.iter().sum())); + | ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | | + | required by a bound introduced by this call + | +note: multiple `impl`s satisfying `u64: Test<_>` found + --> $DIR/issue-69455.rs:11:1 + | +LL | impl Test for u64 { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Test for u64 { + | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying the generic argument + | +LL | println!("{}", 23u64.test(xs.iter().sum::())); + | +++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0283, E0284. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs new file mode 100644 index 000000000..e98affc5c --- /dev/null +++ b/tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -0,0 +1,23 @@ +trait TraitA { + const VALUE: usize; +} + +struct A; +impl TraitA for A { + const VALUE: usize = 0; +} + +trait TraitB { + type MyA: TraitA; + const VALUE: usize = Self::MyA::VALUE; +} + +struct B; +impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` + type M = A; //~ ERROR type `M` is not a member of trait `TraitB` +} + +fn main() { + let _ = [0; B::VALUE]; + //~^ constant +} diff --git a/tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr new file mode 100644 index 000000000..ba385d887 --- /dev/null +++ b/tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -0,0 +1,25 @@ +error[E0437]: type `M` is not a member of trait `TraitB` + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:17:5 + | +LL | type M = A; + | ^^^^^^^^^^^^^ not a member of trait `TraitB` + +error[E0046]: not all trait items implemented, missing: `MyA` + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:16:1 + | +LL | type MyA: TraitA; + | ---------------- `MyA` from trait +... +LL | impl TraitB for B { + | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation + +note: erroneous constant used + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17 + | +LL | let _ = [0; B::VALUE]; + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0046, E0437. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/issues/issue-69683.rs b/tests/ui/issues/issue-69683.rs new file mode 100644 index 000000000..7a76e9ef2 --- /dev/null +++ b/tests/ui/issues/issue-69683.rs @@ -0,0 +1,33 @@ +pub trait Element { + type Array; +} + +impl Element<()> for T { + type Array = T; +} + +impl, S> Element<[S; 3]> for T { + type Array = [T::Array; 3]; +} + +trait Foo +where + u8: Element, +{ + fn foo(self, x: >::Array); +} + +impl Foo for u16 +where + u8: Element, +{ + fn foo(self, _: >::Array) {} +} + +fn main() { + let b: [u8; 3] = [0u8; 3]; + + 0u16.foo(b); //~ ERROR type annotations needed + //~^ ERROR type annotations needed + //>::foo(0u16, b); +} diff --git a/tests/ui/issues/issue-69683.stderr b/tests/ui/issues/issue-69683.stderr new file mode 100644 index 000000000..193de1a35 --- /dev/null +++ b/tests/ui/issues/issue-69683.stderr @@ -0,0 +1,43 @@ +error[E0284]: type annotations needed + --> $DIR/issue-69683.rs:30:10 + | +LL | 0u16.foo(b); + | ^^^ + | + = note: cannot satisfy `>::Array == [u8; 3]` +help: try using a fully qualified path to specify the expected types + | +LL | >::foo(0u16, b); + | +++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/issue-69683.rs:30:10 + | +LL | 0u16.foo(b); + | ^^^ + | +note: multiple `impl`s satisfying `u8: Element<_>` found + --> $DIR/issue-69683.rs:5:1 + | +LL | impl Element<()> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl, S> Element<[S; 3]> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Foo::foo` + --> $DIR/issue-69683.rs:15:9 + | +LL | u8: Element, + | ^^^^^^^^^^ required by this bound in `Foo::foo` +LL | { +LL | fn foo(self, x: >::Array); + | --- required by a bound in this +help: try using a fully qualified path to specify the expected types + | +LL | >::foo(0u16, b); + | +++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0283, E0284. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/issues/issue-70093.rs b/tests/ui/issues/issue-70093.rs new file mode 100644 index 000000000..86459dc90 --- /dev/null +++ b/tests/ui/issues/issue-70093.rs @@ -0,0 +1,10 @@ +// run-pass +// compile-flags: -Zlink-native-libraries=no -Cdefault-linker-libraries=yes +// ignore-windows - this will probably only work on unixish systems +// ignore-fuchsia - missing __libc_start_main for some reason (#84733) +// ignore-cross-compile - default-linker-libraries=yes doesn't play well with cross compiling + +#[link(name = "some-random-non-existent-library", kind = "static")] +extern "C" {} + +fn main() {} diff --git a/tests/ui/issues/issue-7012.rs b/tests/ui/issues/issue-7012.rs new file mode 100644 index 000000000..90eba1706 --- /dev/null +++ b/tests/ui/issues/issue-7012.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +/* +# Comparison of static arrays + +The expected behaviour would be that `test == test1`, therefore 'true' +would be printed, however the below prints false. +*/ + +struct signature<'a> { pattern : &'a [u32] } + +static test1: signature<'static> = signature { + pattern: &[0x243f6a88,0x85a308d3,0x13198a2e,0x03707344,0xa4093822,0x299f31d0] +}; + +pub fn main() { + let test: &[u32] = &[0x243f6a88,0x85a308d3,0x13198a2e, + 0x03707344,0xa4093822,0x299f31d0]; + println!("{}",test==test1.pattern); +} diff --git a/tests/ui/issues/issue-70381.rs b/tests/ui/issues/issue-70381.rs new file mode 100644 index 000000000..3df8277b8 --- /dev/null +++ b/tests/ui/issues/issue-70381.rs @@ -0,0 +1,6 @@ +// Test that multi-byte unicode characters with missing parameters do not ICE. + +fn main() { + println!("\r¡{}") + //~^ ERROR 1 positional argument in format string +} diff --git a/tests/ui/issues/issue-70381.stderr b/tests/ui/issues/issue-70381.stderr new file mode 100644 index 000000000..96b8e6569 --- /dev/null +++ b/tests/ui/issues/issue-70381.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-70381.rs:4:16 + | +LL | println!("\r¡{}") + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-7044.rs b/tests/ui/issues/issue-7044.rs new file mode 100644 index 000000000..a6e22bc52 --- /dev/null +++ b/tests/ui/issues/issue-7044.rs @@ -0,0 +1,4 @@ +static X: isize = 0; +struct X; //~ ERROR the name `X` is defined multiple times + +fn main() {} diff --git a/tests/ui/issues/issue-7044.stderr b/tests/ui/issues/issue-7044.stderr new file mode 100644 index 000000000..2ad67ec23 --- /dev/null +++ b/tests/ui/issues/issue-7044.stderr @@ -0,0 +1,13 @@ +error[E0428]: the name `X` is defined multiple times + --> $DIR/issue-7044.rs:2:1 + | +LL | static X: isize = 0; + | -------------------- previous definition of the value `X` here +LL | struct X; + | ^^^^^^^^^ `X` redefined here + | + = note: `X` must be defined only once in the value namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/issues/issue-7061.rs b/tests/ui/issues/issue-7061.rs new file mode 100644 index 000000000..8a6ee920a --- /dev/null +++ b/tests/ui/issues/issue-7061.rs @@ -0,0 +1,10 @@ +struct BarStruct; + +impl<'a> BarStruct { + fn foo(&'a mut self) -> Box { self } + //~^ ERROR mismatched types + //~| expected struct `Box` + //~| found mutable reference `&'a mut BarStruct` +} + +fn main() {} diff --git a/tests/ui/issues/issue-7061.stderr b/tests/ui/issues/issue-7061.stderr new file mode 100644 index 000000000..27034378d --- /dev/null +++ b/tests/ui/issues/issue-7061.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-7061.rs:4:46 + | +LL | fn foo(&'a mut self) -> Box { self } + | -------------- ^^^^ expected struct `Box`, found `&mut BarStruct` + | | + | expected `Box` because of return type + | + = note: expected struct `Box` + found mutable reference `&'a mut BarStruct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-70673.rs b/tests/ui/issues/issue-70673.rs new file mode 100644 index 000000000..3561f4012 --- /dev/null +++ b/tests/ui/issues/issue-70673.rs @@ -0,0 +1,12 @@ +// Regression test for https://github.com/rust-lang/rust/issues/70673. + +// run-pass + +#![feature(thread_local)] + +#[thread_local] +static A: &u8 = &42; + +fn main() { + dbg!(*A); +} diff --git a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs b/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs new file mode 100644 index 000000000..c2683157f --- /dev/null +++ b/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs @@ -0,0 +1,10 @@ +fn a() -> i32 { + 3 +} + +pub fn main() { + assert_eq!(a, 0); + //~^ ERROR binary operation `==` cannot + //~| ERROR mismatched types + //~| ERROR doesn't implement +} diff --git a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr new file mode 100644 index 000000000..b30bcfb77 --- /dev/null +++ b/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr @@ -0,0 +1,38 @@ +error[E0369]: binary operation `==` cannot be applied to type `fn() -> i32 {a}` + --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 + | +LL | assert_eq!(a, 0); + | ^^^^^^^^^^^^^^^^ + | | + | fn() -> i32 {a} + | {integer} + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 + | +LL | assert_eq!(a, 0); + | ^^^^^^^^^^^^^^^^ expected fn item, found integer + | + = note: expected fn item `fn() -> i32 {a}` + found type `{integer}` + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `fn() -> i32 {a}` doesn't implement `Debug` + --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 + | +LL | fn a() -> i32 { + | - consider calling this function +... +LL | assert_eq!(a, 0); + | ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}` + = help: use parentheses to call this function: `a()` + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308, E0369. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-70746.rs b/tests/ui/issues/issue-70746.rs new file mode 100644 index 000000000..8930c15f5 --- /dev/null +++ b/tests/ui/issues/issue-70746.rs @@ -0,0 +1,29 @@ +// check-pass + +pub trait Trait1 { + type C; +} + +struct T1; +impl Trait1 for T1 { + type C = usize; +} +pub trait Callback: FnMut(::C) {} +impl::C)> Callback for F {} + +pub struct State { + callback: Option>>, +} +impl State { + fn new() -> Self { + Self { callback: None } + } + fn test_cb(&mut self, d: ::C) { + (self.callback.as_mut().unwrap())(d) + } +} + +fn main() { + let mut s = State::::new(); + s.test_cb(1); +} diff --git a/tests/ui/issues/issue-7092.rs b/tests/ui/issues/issue-7092.rs new file mode 100644 index 000000000..85bfbf90d --- /dev/null +++ b/tests/ui/issues/issue-7092.rs @@ -0,0 +1,15 @@ +enum Whatever { +} + +fn foo(x: Whatever) { + match x { + Some(field) => +//~^ ERROR mismatched types +//~| expected enum `Whatever`, found enum `Option` +//~| expected enum `Whatever` +//~| found enum `Option<_>` + field.access(), + } +} + +fn main(){} diff --git a/tests/ui/issues/issue-7092.stderr b/tests/ui/issues/issue-7092.stderr new file mode 100644 index 000000000..59e8d75e2 --- /dev/null +++ b/tests/ui/issues/issue-7092.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-7092.rs:6:9 + | +LL | match x { + | - this expression has type `Whatever` +LL | Some(field) => + | ^^^^^^^^^^^ expected enum `Whatever`, found enum `Option` + | + = note: expected enum `Whatever` + found enum `Option<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-71406.rs b/tests/ui/issues/issue-71406.rs new file mode 100644 index 000000000..6266112c3 --- /dev/null +++ b/tests/ui/issues/issue-71406.rs @@ -0,0 +1,6 @@ +use std::sync::mpsc; + +fn main() { + let (tx, rx) = mpsc::channel::new(1); + //~^ ERROR expected type, found function `channel` in `mpsc` +} diff --git a/tests/ui/issues/issue-71406.stderr b/tests/ui/issues/issue-71406.stderr new file mode 100644 index 000000000..918163b60 --- /dev/null +++ b/tests/ui/issues/issue-71406.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: expected type, found function `channel` in `mpsc` + --> $DIR/issue-71406.rs:4:26 + | +LL | let (tx, rx) = mpsc::channel::new(1); + | ^^^^^^^ expected type, found function `channel` in `mpsc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/issues/issue-71584.rs b/tests/ui/issues/issue-71584.rs new file mode 100644 index 000000000..7bf3ed60e --- /dev/null +++ b/tests/ui/issues/issue-71584.rs @@ -0,0 +1,6 @@ +fn main() { + let n: u32 = 1; + let mut d: u64 = 2; + d = d % n.into(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/issues/issue-71584.stderr b/tests/ui/issues/issue-71584.stderr new file mode 100644 index 000000000..6ddb76573 --- /dev/null +++ b/tests/ui/issues/issue-71584.stderr @@ -0,0 +1,17 @@ +error[E0284]: type annotations needed + --> $DIR/issue-71584.rs:4:15 + | +LL | d = d % n.into(); + | - ^^^^ + | | + | type must be known at this point + | + = note: cannot satisfy `>::Output == u64` +help: try using a fully qualified path to specify the expected types + | +LL | d = d % >::into(n); + | +++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/issues/issue-71676-1.fixed b/tests/ui/issues/issue-71676-1.fixed new file mode 100644 index 000000000..cbc0e8c06 --- /dev/null +++ b/tests/ui/issues/issue-71676-1.fixed @@ -0,0 +1,53 @@ +// run-rustfix +use std::ops::Deref; +use std::ops::DerefMut; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Bar{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Emm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +fn main() { + // Suggest dereference with arbitrary mutability + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &***a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &mut ***a; //~ ERROR mismatched types + + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &***a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &mut ***a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-71676-1.rs b/tests/ui/issues/issue-71676-1.rs new file mode 100644 index 000000000..6e87c7174 --- /dev/null +++ b/tests/ui/issues/issue-71676-1.rs @@ -0,0 +1,53 @@ +// run-rustfix +use std::ops::Deref; +use std::ops::DerefMut; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Bar{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Emm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +fn main() { + // Suggest dereference with arbitrary mutability + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &a; //~ ERROR mismatched types + + let a = Emm(Foo(Bar(0))); + let _: *const u8 = &mut a; //~ ERROR mismatched types + + let mut a = Emm(Foo(Bar(0))); + let _: *mut u8 = &mut a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-71676-1.stderr b/tests/ui/issues/issue-71676-1.stderr new file mode 100644 index 000000000..2104634eb --- /dev/null +++ b/tests/ui/issues/issue-71676-1.stderr @@ -0,0 +1,63 @@ +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:43:24 + | +LL | let _: *const u8 = &a; + | --------- ^^ expected `u8`, found struct `Emm` + | | + | expected due to this + | + = note: expected raw pointer `*const u8` + found reference `&Emm` +help: consider dereferencing + | +LL | let _: *const u8 = &***a; + | +++ + +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:46:22 + | +LL | let _: *mut u8 = &a; + | ------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut u8` + found reference `&Emm` +help: consider dereferencing + | +LL | let _: *mut u8 = &mut ***a; + | +++++++ + +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:49:24 + | +LL | let _: *const u8 = &mut a; + | --------- ^^^^^^ expected `u8`, found struct `Emm` + | | + | expected due to this + | + = note: expected raw pointer `*const u8` + found mutable reference `&mut Emm` +help: consider dereferencing + | +LL | let _: *const u8 = &***a; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/issue-71676-1.rs:52:22 + | +LL | let _: *mut u8 = &mut a; + | ------- ^^^^^^ expected `u8`, found struct `Emm` + | | + | expected due to this + | + = note: expected raw pointer `*mut u8` + found mutable reference `&mut Emm` +help: consider dereferencing + | +LL | let _: *mut u8 = &mut ***a; + | +++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-71676-2.rs b/tests/ui/issues/issue-71676-2.rs new file mode 100644 index 000000000..f3183899d --- /dev/null +++ b/tests/ui/issues/issue-71676-2.rs @@ -0,0 +1,42 @@ +use std::ops::Deref; +use std::ops::DerefMut; +struct Bar(u8); +struct Foo(Bar); +struct Emm(Foo); +impl Deref for Bar{ + type Target = u8; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Emm { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Bar{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Emm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +fn main() { + let a = Emm(Foo(Bar(0))); + let _: *mut u8 = &a; //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-71676-2.stderr b/tests/ui/issues/issue-71676-2.stderr new file mode 100644 index 000000000..80fb4aed1 --- /dev/null +++ b/tests/ui/issues/issue-71676-2.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-71676-2.rs:41:22 + | +LL | let _: *mut u8 = &a; + | ------- ^^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut u8` + found reference `&Emm` +help: consider dereferencing + | +LL | let _: *mut u8 = &mut ***a; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-7178.rs b/tests/ui/issues/issue-7178.rs new file mode 100644 index 000000000..30aa736cd --- /dev/null +++ b/tests/ui/issues/issue-7178.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:issue-7178.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_7178 as cross_crate_self; + +pub fn main() { + let _ = cross_crate_self::Foo::new(&1); +} diff --git a/tests/ui/issues/issue-72002.rs b/tests/ui/issues/issue-72002.rs new file mode 100644 index 000000000..54ff89355 --- /dev/null +++ b/tests/ui/issues/issue-72002.rs @@ -0,0 +1,29 @@ +// check-pass +struct Indexable; + +impl Indexable { + fn boo(&mut self) {} +} + +impl std::ops::Index<&str> for Indexable { + type Output = Indexable; + + fn index(&self, field: &str) -> &Indexable { + self + } +} + +impl std::ops::IndexMut<&str> for Indexable { + fn index_mut(&mut self, field: &str) -> &mut Indexable { + self + } +} + +fn main() { + let mut v = Indexable; + let field = "hello".to_string(); + + v[field.as_str()].boo(); + + v[&field].boo(); // < This should work +} diff --git a/tests/ui/issues/issue-72076.rs b/tests/ui/issues/issue-72076.rs new file mode 100644 index 000000000..1659044a6 --- /dev/null +++ b/tests/ui/issues/issue-72076.rs @@ -0,0 +1,6 @@ +trait X { + type S; + fn f() -> Self::S {} //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/issues/issue-72076.stderr b/tests/ui/issues/issue-72076.stderr new file mode 100644 index 000000000..b942cf75b --- /dev/null +++ b/tests/ui/issues/issue-72076.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-72076.rs:3:23 + | +LL | fn f() -> Self::S {} + | ^^ expected associated type, found `()` + | + = note: expected associated type `::S` + found unit type `()` + = help: consider constraining the associated type `::S` to `()` or calling a method that returns `::S` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-72278.rs b/tests/ui/issues/issue-72278.rs new file mode 100644 index 000000000..92fd1f73a --- /dev/null +++ b/tests/ui/issues/issue-72278.rs @@ -0,0 +1,19 @@ +// run-pass + +#![allow(unused)] + +struct S; + +impl S { + fn func<'a, U>(&'a self) -> U { + todo!() + } +} + +fn dont_crash<'a, U>() -> U { + S.func::<'a, U>() + //~^ WARN cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/tests/ui/issues/issue-72278.stderr b/tests/ui/issues/issue-72278.stderr new file mode 100644 index 000000000..5468837a3 --- /dev/null +++ b/tests/ui/issues/issue-72278.stderr @@ -0,0 +1,15 @@ +warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/issue-72278.rs:14:14 + | +LL | fn func<'a, U>(&'a self) -> U { + | -- the late bound lifetime parameter is introduced here +... +LL | S.func::<'a, U>() + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + = note: `#[warn(late_bound_lifetime_arguments)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-7246.rs b/tests/ui/issues/issue-7246.rs new file mode 100644 index 000000000..7b16fa024 --- /dev/null +++ b/tests/ui/issues/issue-7246.rs @@ -0,0 +1,11 @@ +#![deny(unreachable_code)] +#![allow(dead_code)] + +use std::ptr; +pub unsafe fn g() { + return; + if *ptr::null() {}; //~ ERROR unreachable + //~| WARNING dereferencing a null pointer +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-7246.stderr b/tests/ui/issues/issue-7246.stderr new file mode 100644 index 000000000..a9bf2bf76 --- /dev/null +++ b/tests/ui/issues/issue-7246.stderr @@ -0,0 +1,24 @@ +error: unreachable statement + --> $DIR/issue-7246.rs:7:5 + | +LL | return; + | ------ any code following this expression is unreachable +LL | if *ptr::null() {}; + | ^^^^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/issue-7246.rs:1:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: dereferencing a null pointer + --> $DIR/issue-7246.rs:7:8 + | +LL | if *ptr::null() {}; + | ^^^^^^^^^^^^ this code causes undefined behavior when executed + | + = note: `#[warn(deref_nullptr)]` on by default + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/issues/issue-7268.rs b/tests/ui/issues/issue-7268.rs new file mode 100644 index 000000000..309176fb0 --- /dev/null +++ b/tests/ui/issues/issue-7268.rs @@ -0,0 +1,10 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn foo(_: T) {} + +fn bar(x: &'static T) { + foo(x); +} +fn main() {} diff --git a/tests/ui/issues/issue-72839-error-overflow.rs b/tests/ui/issues/issue-72839-error-overflow.rs new file mode 100644 index 000000000..6562d2284 --- /dev/null +++ b/tests/ui/issues/issue-72839-error-overflow.rs @@ -0,0 +1,19 @@ +// Regression test for issue #72839 +// Tests that we do not overflow during trait selection after +// a type error occurs +use std::ops::Rem; +trait Foo {} +struct MyStruct(T); + +impl Rem> for MyStruct where MyStruct: Rem> { + type Output = u8; + fn rem(self, _: MyStruct) -> Self::Output { + panic!() + } +} + +fn main() {} + +fn foo() { + if missing_var % 8 == 0 {} //~ ERROR cannot find +} diff --git a/tests/ui/issues/issue-72839-error-overflow.stderr b/tests/ui/issues/issue-72839-error-overflow.stderr new file mode 100644 index 000000000..c4b6f90ca --- /dev/null +++ b/tests/ui/issues/issue-72839-error-overflow.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `missing_var` in this scope + --> $DIR/issue-72839-error-overflow.rs:18:8 + | +LL | if missing_var % 8 == 0 {} + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/issues/issue-72933-match-stack-overflow.rs b/tests/ui/issues/issue-72933-match-stack-overflow.rs new file mode 100644 index 000000000..aa796bcf5 --- /dev/null +++ b/tests/ui/issues/issue-72933-match-stack-overflow.rs @@ -0,0 +1,5208 @@ +// build-pass +// ignore-tidy-filelength +#![crate_type="rlib"] + +fn banana(v: &str) -> u32 { + match v { + "0" => 0, + "1" => 1, + "2" => 2, + "3" => 3, + "4" => 4, + "5" => 5, + "6" => 6, + "7" => 7, + "8" => 8, + "9" => 9, + "10" => 10, + "11" => 11, + "12" => 12, + "13" => 13, + "14" => 14, + "15" => 15, + "16" => 16, + "17" => 17, + "18" => 18, + "19" => 19, + "20" => 20, + "21" => 21, + "22" => 22, + "23" => 23, + "24" => 24, + "25" => 25, + "26" => 26, + "27" => 27, + "28" => 28, + "29" => 29, + "30" => 30, + "31" => 31, + "32" => 32, + "33" => 33, + "34" => 34, + "35" => 35, + "36" => 36, + "37" => 37, + "38" => 38, + "39" => 39, + "40" => 40, + "41" => 41, + "42" => 42, + "43" => 43, + "44" => 44, + "45" => 45, + "46" => 46, + "47" => 47, + "48" => 48, + "49" => 49, + "50" => 50, + "51" => 51, + "52" => 52, + "53" => 53, + "54" => 54, + "55" => 55, + "56" => 56, + "57" => 57, + "58" => 58, + "59" => 59, + "60" => 60, + "61" => 61, + "62" => 62, + "63" => 63, + "64" => 64, + "65" => 65, + "66" => 66, + "67" => 67, + "68" => 68, + "69" => 69, + "70" => 70, + "71" => 71, + "72" => 72, + "73" => 73, + "74" => 74, + "75" => 75, + "76" => 76, + "77" => 77, + "78" => 78, + "79" => 79, + "80" => 80, + "81" => 81, + "82" => 82, + "83" => 83, + "84" => 84, + "85" => 85, + "86" => 86, + "87" => 87, + "88" => 88, + "89" => 89, + "90" => 90, + "91" => 91, + "92" => 92, + "93" => 93, + "94" => 94, + "95" => 95, + "96" => 96, + "97" => 97, + "98" => 98, + "99" => 99, + "100" => 100, + "101" => 101, + "102" => 102, + "103" => 103, + "104" => 104, + "105" => 105, + "106" => 106, + "107" => 107, + "108" => 108, + "109" => 109, + "110" => 110, + "111" => 111, + "112" => 112, + "113" => 113, + "114" => 114, + "115" => 115, + "116" => 116, + "117" => 117, + "118" => 118, + "119" => 119, + "120" => 120, + "121" => 121, + "122" => 122, + "123" => 123, + "124" => 124, + "125" => 125, + "126" => 126, + "127" => 127, + "128" => 128, + "129" => 129, + "130" => 130, + "131" => 131, + "132" => 132, + "133" => 133, + "134" => 134, + "135" => 135, + "136" => 136, + "137" => 137, + "138" => 138, + "139" => 139, + "140" => 140, + "141" => 141, + "142" => 142, + "143" => 143, + "144" => 144, + "145" => 145, + "146" => 146, + "147" => 147, + "148" => 148, + "149" => 149, + "150" => 150, + "151" => 151, + "152" => 152, + "153" => 153, + "154" => 154, + "155" => 155, + "156" => 156, + "157" => 157, + "158" => 158, + "159" => 159, + "160" => 160, + "161" => 161, + "162" => 162, + "163" => 163, + "164" => 164, + "165" => 165, + "166" => 166, + "167" => 167, + "168" => 168, + "169" => 169, + "170" => 170, + "171" => 171, + "172" => 172, + "173" => 173, + "174" => 174, + "175" => 175, + "176" => 176, + "177" => 177, + "178" => 178, + "179" => 179, + "180" => 180, + "181" => 181, + "182" => 182, + "183" => 183, + "184" => 184, + "185" => 185, + "186" => 186, + "187" => 187, + "188" => 188, + "189" => 189, + "190" => 190, + "191" => 191, + "192" => 192, + "193" => 193, + "194" => 194, + "195" => 195, + "196" => 196, + "197" => 197, + "198" => 198, + "199" => 199, + "200" => 200, + "201" => 201, + "202" => 202, + "203" => 203, + "204" => 204, + "205" => 205, + "206" => 206, + "207" => 207, + "208" => 208, + "209" => 209, + "210" => 210, + "211" => 211, + "212" => 212, + "213" => 213, + "214" => 214, + "215" => 215, + "216" => 216, + "217" => 217, + "218" => 218, + "219" => 219, + "220" => 220, + "221" => 221, + "222" => 222, + "223" => 223, + "224" => 224, + "225" => 225, + "226" => 226, + "227" => 227, + "228" => 228, + "229" => 229, + "230" => 230, + "231" => 231, + "232" => 232, + "233" => 233, + "234" => 234, + "235" => 235, + "236" => 236, + "237" => 237, + "238" => 238, + "239" => 239, + "240" => 240, + "241" => 241, + "242" => 242, + "243" => 243, + "244" => 244, + "245" => 245, + "246" => 246, + "247" => 247, + "248" => 248, + "249" => 249, + "250" => 250, + "251" => 251, + "252" => 252, + "253" => 253, + "254" => 254, + "255" => 255, + "256" => 256, + "257" => 257, + "258" => 258, + "259" => 259, + "260" => 260, + "261" => 261, + "262" => 262, + "263" => 263, + "264" => 264, + "265" => 265, + "266" => 266, + "267" => 267, + "268" => 268, + "269" => 269, + "270" => 270, + "271" => 271, + "272" => 272, + "273" => 273, + "274" => 274, + "275" => 275, + "276" => 276, + "277" => 277, + "278" => 278, + "279" => 279, + "280" => 280, + "281" => 281, + "282" => 282, + "283" => 283, + "284" => 284, + "285" => 285, + "286" => 286, + "287" => 287, + "288" => 288, + "289" => 289, + "290" => 290, + "291" => 291, + "292" => 292, + "293" => 293, + "294" => 294, + "295" => 295, + "296" => 296, + "297" => 297, + "298" => 298, + "299" => 299, + "300" => 300, + "301" => 301, + "302" => 302, + "303" => 303, + "304" => 304, + "305" => 305, + "306" => 306, + "307" => 307, + "308" => 308, + "309" => 309, + "310" => 310, + "311" => 311, + "312" => 312, + "313" => 313, + "314" => 314, + "315" => 315, + "316" => 316, + "317" => 317, + "318" => 318, + "319" => 319, + "320" => 320, + "321" => 321, + "322" => 322, + "323" => 323, + "324" => 324, + "325" => 325, + "326" => 326, + "327" => 327, + "328" => 328, + "329" => 329, + "330" => 330, + "331" => 331, + "332" => 332, + "333" => 333, + "334" => 334, + "335" => 335, + "336" => 336, + "337" => 337, + "338" => 338, + "339" => 339, + "340" => 340, + "341" => 341, + "342" => 342, + "343" => 343, + "344" => 344, + "345" => 345, + "346" => 346, + "347" => 347, + "348" => 348, + "349" => 349, + "350" => 350, + "351" => 351, + "352" => 352, + "353" => 353, + "354" => 354, + "355" => 355, + "356" => 356, + "357" => 357, + "358" => 358, + "359" => 359, + "360" => 360, + "361" => 361, + "362" => 362, + "363" => 363, + "364" => 364, + "365" => 365, + "366" => 366, + "367" => 367, + "368" => 368, + "369" => 369, + "370" => 370, + "371" => 371, + "372" => 372, + "373" => 373, + "374" => 374, + "375" => 375, + "376" => 376, + "377" => 377, + "378" => 378, + "379" => 379, + "380" => 380, + "381" => 381, + "382" => 382, + "383" => 383, + "384" => 384, + "385" => 385, + "386" => 386, + "387" => 387, + "388" => 388, + "389" => 389, + "390" => 390, + "391" => 391, + "392" => 392, + "393" => 393, + "394" => 394, + "395" => 395, + "396" => 396, + "397" => 397, + "398" => 398, + "399" => 399, + "400" => 400, + "401" => 401, + "402" => 402, + "403" => 403, + "404" => 404, + "405" => 405, + "406" => 406, + "407" => 407, + "408" => 408, + "409" => 409, + "410" => 410, + "411" => 411, + "412" => 412, + "413" => 413, + "414" => 414, + "415" => 415, + "416" => 416, + "417" => 417, + "418" => 418, + "419" => 419, + "420" => 420, + "421" => 421, + "422" => 422, + "423" => 423, + "424" => 424, + "425" => 425, + "426" => 426, + "427" => 427, + "428" => 428, + "429" => 429, + "430" => 430, + "431" => 431, + "432" => 432, + "433" => 433, + "434" => 434, + "435" => 435, + "436" => 436, + "437" => 437, + "438" => 438, + "439" => 439, + "440" => 440, + "441" => 441, + "442" => 442, + "443" => 443, + "444" => 444, + "445" => 445, + "446" => 446, + "447" => 447, + "448" => 448, + "449" => 449, + "450" => 450, + "451" => 451, + "452" => 452, + "453" => 453, + "454" => 454, + "455" => 455, + "456" => 456, + "457" => 457, + "458" => 458, + "459" => 459, + "460" => 460, + "461" => 461, + "462" => 462, + "463" => 463, + "464" => 464, + "465" => 465, + "466" => 466, + "467" => 467, + "468" => 468, + "469" => 469, + "470" => 470, + "471" => 471, + "472" => 472, + "473" => 473, + "474" => 474, + "475" => 475, + "476" => 476, + "477" => 477, + "478" => 478, + "479" => 479, + "480" => 480, + "481" => 481, + "482" => 482, + "483" => 483, + "484" => 484, + "485" => 485, + "486" => 486, + "487" => 487, + "488" => 488, + "489" => 489, + "490" => 490, + "491" => 491, + "492" => 492, + "493" => 493, + "494" => 494, + "495" => 495, + "496" => 496, + "497" => 497, + "498" => 498, + "499" => 499, + "500" => 500, + "501" => 501, + "502" => 502, + "503" => 503, + "504" => 504, + "505" => 505, + "506" => 506, + "507" => 507, + "508" => 508, + "509" => 509, + "510" => 510, + "511" => 511, + "512" => 512, + "513" => 513, + "514" => 514, + "515" => 515, + "516" => 516, + "517" => 517, + "518" => 518, + "519" => 519, + "520" => 520, + "521" => 521, + "522" => 522, + "523" => 523, + "524" => 524, + "525" => 525, + "526" => 526, + "527" => 527, + "528" => 528, + "529" => 529, + "530" => 530, + "531" => 531, + "532" => 532, + "533" => 533, + "534" => 534, + "535" => 535, + "536" => 536, + "537" => 537, + "538" => 538, + "539" => 539, + "540" => 540, + "541" => 541, + "542" => 542, + "543" => 543, + "544" => 544, + "545" => 545, + "546" => 546, + "547" => 547, + "548" => 548, + "549" => 549, + "550" => 550, + "551" => 551, + "552" => 552, + "553" => 553, + "554" => 554, + "555" => 555, + "556" => 556, + "557" => 557, + "558" => 558, + "559" => 559, + "560" => 560, + "561" => 561, + "562" => 562, + "563" => 563, + "564" => 564, + "565" => 565, + "566" => 566, + "567" => 567, + "568" => 568, + "569" => 569, + "570" => 570, + "571" => 571, + "572" => 572, + "573" => 573, + "574" => 574, + "575" => 575, + "576" => 576, + "577" => 577, + "578" => 578, + "579" => 579, + "580" => 580, + "581" => 581, + "582" => 582, + "583" => 583, + "584" => 584, + "585" => 585, + "586" => 586, + "587" => 587, + "588" => 588, + "589" => 589, + "590" => 590, + "591" => 591, + "592" => 592, + "593" => 593, + "594" => 594, + "595" => 595, + "596" => 596, + "597" => 597, + "598" => 598, + "599" => 599, + "600" => 600, + "601" => 601, + "602" => 602, + "603" => 603, + "604" => 604, + "605" => 605, + "606" => 606, + "607" => 607, + "608" => 608, + "609" => 609, + "610" => 610, + "611" => 611, + "612" => 612, + "613" => 613, + "614" => 614, + "615" => 615, + "616" => 616, + "617" => 617, + "618" => 618, + "619" => 619, + "620" => 620, + "621" => 621, + "622" => 622, + "623" => 623, + "624" => 624, + "625" => 625, + "626" => 626, + "627" => 627, + "628" => 628, + "629" => 629, + "630" => 630, + "631" => 631, + "632" => 632, + "633" => 633, + "634" => 634, + "635" => 635, + "636" => 636, + "637" => 637, + "638" => 638, + "639" => 639, + "640" => 640, + "641" => 641, + "642" => 642, + "643" => 643, + "644" => 644, + "645" => 645, + "646" => 646, + "647" => 647, + "648" => 648, + "649" => 649, + "650" => 650, + "651" => 651, + "652" => 652, + "653" => 653, + "654" => 654, + "655" => 655, + "656" => 656, + "657" => 657, + "658" => 658, + "659" => 659, + "660" => 660, + "661" => 661, + "662" => 662, + "663" => 663, + "664" => 664, + "665" => 665, + "666" => 666, + "667" => 667, + "668" => 668, + "669" => 669, + "670" => 670, + "671" => 671, + "672" => 672, + "673" => 673, + "674" => 674, + "675" => 675, + "676" => 676, + "677" => 677, + "678" => 678, + "679" => 679, + "680" => 680, + "681" => 681, + "682" => 682, + "683" => 683, + "684" => 684, + "685" => 685, + "686" => 686, + "687" => 687, + "688" => 688, + "689" => 689, + "690" => 690, + "691" => 691, + "692" => 692, + "693" => 693, + "694" => 694, + "695" => 695, + "696" => 696, + "697" => 697, + "698" => 698, + "699" => 699, + "700" => 700, + "701" => 701, + "702" => 702, + "703" => 703, + "704" => 704, + "705" => 705, + "706" => 706, + "707" => 707, + "708" => 708, + "709" => 709, + "710" => 710, + "711" => 711, + "712" => 712, + "713" => 713, + "714" => 714, + "715" => 715, + "716" => 716, + "717" => 717, + "718" => 718, + "719" => 719, + "720" => 720, + "721" => 721, + "722" => 722, + "723" => 723, + "724" => 724, + "725" => 725, + "726" => 726, + "727" => 727, + "728" => 728, + "729" => 729, + "730" => 730, + "731" => 731, + "732" => 732, + "733" => 733, + "734" => 734, + "735" => 735, + "736" => 736, + "737" => 737, + "738" => 738, + "739" => 739, + "740" => 740, + "741" => 741, + "742" => 742, + "743" => 743, + "744" => 744, + "745" => 745, + "746" => 746, + "747" => 747, + "748" => 748, + "749" => 749, + "750" => 750, + "751" => 751, + "752" => 752, + "753" => 753, + "754" => 754, + "755" => 755, + "756" => 756, + "757" => 757, + "758" => 758, + "759" => 759, + "760" => 760, + "761" => 761, + "762" => 762, + "763" => 763, + "764" => 764, + "765" => 765, + "766" => 766, + "767" => 767, + "768" => 768, + "769" => 769, + "770" => 770, + "771" => 771, + "772" => 772, + "773" => 773, + "774" => 774, + "775" => 775, + "776" => 776, + "777" => 777, + "778" => 778, + "779" => 779, + "780" => 780, + "781" => 781, + "782" => 782, + "783" => 783, + "784" => 784, + "785" => 785, + "786" => 786, + "787" => 787, + "788" => 788, + "789" => 789, + "790" => 790, + "791" => 791, + "792" => 792, + "793" => 793, + "794" => 794, + "795" => 795, + "796" => 796, + "797" => 797, + "798" => 798, + "799" => 799, + "800" => 800, + "801" => 801, + "802" => 802, + "803" => 803, + "804" => 804, + "805" => 805, + "806" => 806, + "807" => 807, + "808" => 808, + "809" => 809, + "810" => 810, + "811" => 811, + "812" => 812, + "813" => 813, + "814" => 814, + "815" => 815, + "816" => 816, + "817" => 817, + "818" => 818, + "819" => 819, + "820" => 820, + "821" => 821, + "822" => 822, + "823" => 823, + "824" => 824, + "825" => 825, + "826" => 826, + "827" => 827, + "828" => 828, + "829" => 829, + "830" => 830, + "831" => 831, + "832" => 832, + "833" => 833, + "834" => 834, + "835" => 835, + "836" => 836, + "837" => 837, + "838" => 838, + "839" => 839, + "840" => 840, + "841" => 841, + "842" => 842, + "843" => 843, + "844" => 844, + "845" => 845, + "846" => 846, + "847" => 847, + "848" => 848, + "849" => 849, + "850" => 850, + "851" => 851, + "852" => 852, + "853" => 853, + "854" => 854, + "855" => 855, + "856" => 856, + "857" => 857, + "858" => 858, + "859" => 859, + "860" => 860, + "861" => 861, + "862" => 862, + "863" => 863, + "864" => 864, + "865" => 865, + "866" => 866, + "867" => 867, + "868" => 868, + "869" => 869, + "870" => 870, + "871" => 871, + "872" => 872, + "873" => 873, + "874" => 874, + "875" => 875, + "876" => 876, + "877" => 877, + "878" => 878, + "879" => 879, + "880" => 880, + "881" => 881, + "882" => 882, + "883" => 883, + "884" => 884, + "885" => 885, + "886" => 886, + "887" => 887, + "888" => 888, + "889" => 889, + "890" => 890, + "891" => 891, + "892" => 892, + "893" => 893, + "894" => 894, + "895" => 895, + "896" => 896, + "897" => 897, + "898" => 898, + "899" => 899, + "900" => 900, + "901" => 901, + "902" => 902, + "903" => 903, + "904" => 904, + "905" => 905, + "906" => 906, + "907" => 907, + "908" => 908, + "909" => 909, + "910" => 910, + "911" => 911, + "912" => 912, + "913" => 913, + "914" => 914, + "915" => 915, + "916" => 916, + "917" => 917, + "918" => 918, + "919" => 919, + "920" => 920, + "921" => 921, + "922" => 922, + "923" => 923, + "924" => 924, + "925" => 925, + "926" => 926, + "927" => 927, + "928" => 928, + "929" => 929, + "930" => 930, + "931" => 931, + "932" => 932, + "933" => 933, + "934" => 934, + "935" => 935, + "936" => 936, + "937" => 937, + "938" => 938, + "939" => 939, + "940" => 940, + "941" => 941, + "942" => 942, + "943" => 943, + "944" => 944, + "945" => 945, + "946" => 946, + "947" => 947, + "948" => 948, + "949" => 949, + "950" => 950, + "951" => 951, + "952" => 952, + "953" => 953, + "954" => 954, + "955" => 955, + "956" => 956, + "957" => 957, + "958" => 958, + "959" => 959, + "960" => 960, + "961" => 961, + "962" => 962, + "963" => 963, + "964" => 964, + "965" => 965, + "966" => 966, + "967" => 967, + "968" => 968, + "969" => 969, + "970" => 970, + "971" => 971, + "972" => 972, + "973" => 973, + "974" => 974, + "975" => 975, + "976" => 976, + "977" => 977, + "978" => 978, + "979" => 979, + "980" => 980, + "981" => 981, + "982" => 982, + "983" => 983, + "984" => 984, + "985" => 985, + "986" => 986, + "987" => 987, + "988" => 988, + "989" => 989, + "990" => 990, + "991" => 991, + "992" => 992, + "993" => 993, + "994" => 994, + "995" => 995, + "996" => 996, + "997" => 997, + "998" => 998, + "999" => 999, + "1000" => 1000, + "1001" => 1001, + "1002" => 1002, + "1003" => 1003, + "1004" => 1004, + "1005" => 1005, + "1006" => 1006, + "1007" => 1007, + "1008" => 1008, + "1009" => 1009, + "1010" => 1010, + "1011" => 1011, + "1012" => 1012, + "1013" => 1013, + "1014" => 1014, + "1015" => 1015, + "1016" => 1016, + "1017" => 1017, + "1018" => 1018, + "1019" => 1019, + "1020" => 1020, + "1021" => 1021, + "1022" => 1022, + "1023" => 1023, + "1024" => 1024, + "1025" => 1025, + "1026" => 1026, + "1027" => 1027, + "1028" => 1028, + "1029" => 1029, + "1030" => 1030, + "1031" => 1031, + "1032" => 1032, + "1033" => 1033, + "1034" => 1034, + "1035" => 1035, + "1036" => 1036, + "1037" => 1037, + "1038" => 1038, + "1039" => 1039, + "1040" => 1040, + "1041" => 1041, + "1042" => 1042, + "1043" => 1043, + "1044" => 1044, + "1045" => 1045, + "1046" => 1046, + "1047" => 1047, + "1048" => 1048, + "1049" => 1049, + "1050" => 1050, + "1051" => 1051, + "1052" => 1052, + "1053" => 1053, + "1054" => 1054, + "1055" => 1055, + "1056" => 1056, + "1057" => 1057, + "1058" => 1058, + "1059" => 1059, + "1060" => 1060, + "1061" => 1061, + "1062" => 1062, + "1063" => 1063, + "1064" => 1064, + "1065" => 1065, + "1066" => 1066, + "1067" => 1067, + "1068" => 1068, + "1069" => 1069, + "1070" => 1070, + "1071" => 1071, + "1072" => 1072, + "1073" => 1073, + "1074" => 1074, + "1075" => 1075, + "1076" => 1076, + "1077" => 1077, + "1078" => 1078, + "1079" => 1079, + "1080" => 1080, + "1081" => 1081, + "1082" => 1082, + "1083" => 1083, + "1084" => 1084, + "1085" => 1085, + "1086" => 1086, + "1087" => 1087, + "1088" => 1088, + "1089" => 1089, + "1090" => 1090, + "1091" => 1091, + "1092" => 1092, + "1093" => 1093, + "1094" => 1094, + "1095" => 1095, + "1096" => 1096, + "1097" => 1097, + "1098" => 1098, + "1099" => 1099, + "1100" => 1100, + "1101" => 1101, + "1102" => 1102, + "1103" => 1103, + "1104" => 1104, + "1105" => 1105, + "1106" => 1106, + "1107" => 1107, + "1108" => 1108, + "1109" => 1109, + "1110" => 1110, + "1111" => 1111, + "1112" => 1112, + "1113" => 1113, + "1114" => 1114, + "1115" => 1115, + "1116" => 1116, + "1117" => 1117, + "1118" => 1118, + "1119" => 1119, + "1120" => 1120, + "1121" => 1121, + "1122" => 1122, + "1123" => 1123, + "1124" => 1124, + "1125" => 1125, + "1126" => 1126, + "1127" => 1127, + "1128" => 1128, + "1129" => 1129, + "1130" => 1130, + "1131" => 1131, + "1132" => 1132, + "1133" => 1133, + "1134" => 1134, + "1135" => 1135, + "1136" => 1136, + "1137" => 1137, + "1138" => 1138, + "1139" => 1139, + "1140" => 1140, + "1141" => 1141, + "1142" => 1142, + "1143" => 1143, + "1144" => 1144, + "1145" => 1145, + "1146" => 1146, + "1147" => 1147, + "1148" => 1148, + "1149" => 1149, + "1150" => 1150, + "1151" => 1151, + "1152" => 1152, + "1153" => 1153, + "1154" => 1154, + "1155" => 1155, + "1156" => 1156, + "1157" => 1157, + "1158" => 1158, + "1159" => 1159, + "1160" => 1160, + "1161" => 1161, + "1162" => 1162, + "1163" => 1163, + "1164" => 1164, + "1165" => 1165, + "1166" => 1166, + "1167" => 1167, + "1168" => 1168, + "1169" => 1169, + "1170" => 1170, + "1171" => 1171, + "1172" => 1172, + "1173" => 1173, + "1174" => 1174, + "1175" => 1175, + "1176" => 1176, + "1177" => 1177, + "1178" => 1178, + "1179" => 1179, + "1180" => 1180, + "1181" => 1181, + "1182" => 1182, + "1183" => 1183, + "1184" => 1184, + "1185" => 1185, + "1186" => 1186, + "1187" => 1187, + "1188" => 1188, + "1189" => 1189, + "1190" => 1190, + "1191" => 1191, + "1192" => 1192, + "1193" => 1193, + "1194" => 1194, + "1195" => 1195, + "1196" => 1196, + "1197" => 1197, + "1198" => 1198, + "1199" => 1199, + "1200" => 1200, + "1201" => 1201, + "1202" => 1202, + "1203" => 1203, + "1204" => 1204, + "1205" => 1205, + "1206" => 1206, + "1207" => 1207, + "1208" => 1208, + "1209" => 1209, + "1210" => 1210, + "1211" => 1211, + "1212" => 1212, + "1213" => 1213, + "1214" => 1214, + "1215" => 1215, + "1216" => 1216, + "1217" => 1217, + "1218" => 1218, + "1219" => 1219, + "1220" => 1220, + "1221" => 1221, + "1222" => 1222, + "1223" => 1223, + "1224" => 1224, + "1225" => 1225, + "1226" => 1226, + "1227" => 1227, + "1228" => 1228, + "1229" => 1229, + "1230" => 1230, + "1231" => 1231, + "1232" => 1232, + "1233" => 1233, + "1234" => 1234, + "1235" => 1235, + "1236" => 1236, + "1237" => 1237, + "1238" => 1238, + "1239" => 1239, + "1240" => 1240, + "1241" => 1241, + "1242" => 1242, + "1243" => 1243, + "1244" => 1244, + "1245" => 1245, + "1246" => 1246, + "1247" => 1247, + "1248" => 1248, + "1249" => 1249, + "1250" => 1250, + "1251" => 1251, + "1252" => 1252, + "1253" => 1253, + "1254" => 1254, + "1255" => 1255, + "1256" => 1256, + "1257" => 1257, + "1258" => 1258, + "1259" => 1259, + "1260" => 1260, + "1261" => 1261, + "1262" => 1262, + "1263" => 1263, + "1264" => 1264, + "1265" => 1265, + "1266" => 1266, + "1267" => 1267, + "1268" => 1268, + "1269" => 1269, + "1270" => 1270, + "1271" => 1271, + "1272" => 1272, + "1273" => 1273, + "1274" => 1274, + "1275" => 1275, + "1276" => 1276, + "1277" => 1277, + "1278" => 1278, + "1279" => 1279, + "1280" => 1280, + "1281" => 1281, + "1282" => 1282, + "1283" => 1283, + "1284" => 1284, + "1285" => 1285, + "1286" => 1286, + "1287" => 1287, + "1288" => 1288, + "1289" => 1289, + "1290" => 1290, + "1291" => 1291, + "1292" => 1292, + "1293" => 1293, + "1294" => 1294, + "1295" => 1295, + "1296" => 1296, + "1297" => 1297, + "1298" => 1298, + "1299" => 1299, + "1300" => 1300, + "1301" => 1301, + "1302" => 1302, + "1303" => 1303, + "1304" => 1304, + "1305" => 1305, + "1306" => 1306, + "1307" => 1307, + "1308" => 1308, + "1309" => 1309, + "1310" => 1310, + "1311" => 1311, + "1312" => 1312, + "1313" => 1313, + "1314" => 1314, + "1315" => 1315, + "1316" => 1316, + "1317" => 1317, + "1318" => 1318, + "1319" => 1319, + "1320" => 1320, + "1321" => 1321, + "1322" => 1322, + "1323" => 1323, + "1324" => 1324, + "1325" => 1325, + "1326" => 1326, + "1327" => 1327, + "1328" => 1328, + "1329" => 1329, + "1330" => 1330, + "1331" => 1331, + "1332" => 1332, + "1333" => 1333, + "1334" => 1334, + "1335" => 1335, + "1336" => 1336, + "1337" => 1337, + "1338" => 1338, + "1339" => 1339, + "1340" => 1340, + "1341" => 1341, + "1342" => 1342, + "1343" => 1343, + "1344" => 1344, + "1345" => 1345, + "1346" => 1346, + "1347" => 1347, + "1348" => 1348, + "1349" => 1349, + "1350" => 1350, + "1351" => 1351, + "1352" => 1352, + "1353" => 1353, + "1354" => 1354, + "1355" => 1355, + "1356" => 1356, + "1357" => 1357, + "1358" => 1358, + "1359" => 1359, + "1360" => 1360, + "1361" => 1361, + "1362" => 1362, + "1363" => 1363, + "1364" => 1364, + "1365" => 1365, + "1366" => 1366, + "1367" => 1367, + "1368" => 1368, + "1369" => 1369, + "1370" => 1370, + "1371" => 1371, + "1372" => 1372, + "1373" => 1373, + "1374" => 1374, + "1375" => 1375, + "1376" => 1376, + "1377" => 1377, + "1378" => 1378, + "1379" => 1379, + "1380" => 1380, + "1381" => 1381, + "1382" => 1382, + "1383" => 1383, + "1384" => 1384, + "1385" => 1385, + "1386" => 1386, + "1387" => 1387, + "1388" => 1388, + "1389" => 1389, + "1390" => 1390, + "1391" => 1391, + "1392" => 1392, + "1393" => 1393, + "1394" => 1394, + "1395" => 1395, + "1396" => 1396, + "1397" => 1397, + "1398" => 1398, + "1399" => 1399, + "1400" => 1400, + "1401" => 1401, + "1402" => 1402, + "1403" => 1403, + "1404" => 1404, + "1405" => 1405, + "1406" => 1406, + "1407" => 1407, + "1408" => 1408, + "1409" => 1409, + "1410" => 1410, + "1411" => 1411, + "1412" => 1412, + "1413" => 1413, + "1414" => 1414, + "1415" => 1415, + "1416" => 1416, + "1417" => 1417, + "1418" => 1418, + "1419" => 1419, + "1420" => 1420, + "1421" => 1421, + "1422" => 1422, + "1423" => 1423, + "1424" => 1424, + "1425" => 1425, + "1426" => 1426, + "1427" => 1427, + "1428" => 1428, + "1429" => 1429, + "1430" => 1430, + "1431" => 1431, + "1432" => 1432, + "1433" => 1433, + "1434" => 1434, + "1435" => 1435, + "1436" => 1436, + "1437" => 1437, + "1438" => 1438, + "1439" => 1439, + "1440" => 1440, + "1441" => 1441, + "1442" => 1442, + "1443" => 1443, + "1444" => 1444, + "1445" => 1445, + "1446" => 1446, + "1447" => 1447, + "1448" => 1448, + "1449" => 1449, + "1450" => 1450, + "1451" => 1451, + "1452" => 1452, + "1453" => 1453, + "1454" => 1454, + "1455" => 1455, + "1456" => 1456, + "1457" => 1457, + "1458" => 1458, + "1459" => 1459, + "1460" => 1460, + "1461" => 1461, + "1462" => 1462, + "1463" => 1463, + "1464" => 1464, + "1465" => 1465, + "1466" => 1466, + "1467" => 1467, + "1468" => 1468, + "1469" => 1469, + "1470" => 1470, + "1471" => 1471, + "1472" => 1472, + "1473" => 1473, + "1474" => 1474, + "1475" => 1475, + "1476" => 1476, + "1477" => 1477, + "1478" => 1478, + "1479" => 1479, + "1480" => 1480, + "1481" => 1481, + "1482" => 1482, + "1483" => 1483, + "1484" => 1484, + "1485" => 1485, + "1486" => 1486, + "1487" => 1487, + "1488" => 1488, + "1489" => 1489, + "1490" => 1490, + "1491" => 1491, + "1492" => 1492, + "1493" => 1493, + "1494" => 1494, + "1495" => 1495, + "1496" => 1496, + "1497" => 1497, + "1498" => 1498, + "1499" => 1499, + "1500" => 1500, + "1501" => 1501, + "1502" => 1502, + "1503" => 1503, + "1504" => 1504, + "1505" => 1505, + "1506" => 1506, + "1507" => 1507, + "1508" => 1508, + "1509" => 1509, + "1510" => 1510, + "1511" => 1511, + "1512" => 1512, + "1513" => 1513, + "1514" => 1514, + "1515" => 1515, + "1516" => 1516, + "1517" => 1517, + "1518" => 1518, + "1519" => 1519, + "1520" => 1520, + "1521" => 1521, + "1522" => 1522, + "1523" => 1523, + "1524" => 1524, + "1525" => 1525, + "1526" => 1526, + "1527" => 1527, + "1528" => 1528, + "1529" => 1529, + "1530" => 1530, + "1531" => 1531, + "1532" => 1532, + "1533" => 1533, + "1534" => 1534, + "1535" => 1535, + "1536" => 1536, + "1537" => 1537, + "1538" => 1538, + "1539" => 1539, + "1540" => 1540, + "1541" => 1541, + "1542" => 1542, + "1543" => 1543, + "1544" => 1544, + "1545" => 1545, + "1546" => 1546, + "1547" => 1547, + "1548" => 1548, + "1549" => 1549, + "1550" => 1550, + "1551" => 1551, + "1552" => 1552, + "1553" => 1553, + "1554" => 1554, + "1555" => 1555, + "1556" => 1556, + "1557" => 1557, + "1558" => 1558, + "1559" => 1559, + "1560" => 1560, + "1561" => 1561, + "1562" => 1562, + "1563" => 1563, + "1564" => 1564, + "1565" => 1565, + "1566" => 1566, + "1567" => 1567, + "1568" => 1568, + "1569" => 1569, + "1570" => 1570, + "1571" => 1571, + "1572" => 1572, + "1573" => 1573, + "1574" => 1574, + "1575" => 1575, + "1576" => 1576, + "1577" => 1577, + "1578" => 1578, + "1579" => 1579, + "1580" => 1580, + "1581" => 1581, + "1582" => 1582, + "1583" => 1583, + "1584" => 1584, + "1585" => 1585, + "1586" => 1586, + "1587" => 1587, + "1588" => 1588, + "1589" => 1589, + "1590" => 1590, + "1591" => 1591, + "1592" => 1592, + "1593" => 1593, + "1594" => 1594, + "1595" => 1595, + "1596" => 1596, + "1597" => 1597, + "1598" => 1598, + "1599" => 1599, + "1600" => 1600, + "1601" => 1601, + "1602" => 1602, + "1603" => 1603, + "1604" => 1604, + "1605" => 1605, + "1606" => 1606, + "1607" => 1607, + "1608" => 1608, + "1609" => 1609, + "1610" => 1610, + "1611" => 1611, + "1612" => 1612, + "1613" => 1613, + "1614" => 1614, + "1615" => 1615, + "1616" => 1616, + "1617" => 1617, + "1618" => 1618, + "1619" => 1619, + "1620" => 1620, + "1621" => 1621, + "1622" => 1622, + "1623" => 1623, + "1624" => 1624, + "1625" => 1625, + "1626" => 1626, + "1627" => 1627, + "1628" => 1628, + "1629" => 1629, + "1630" => 1630, + "1631" => 1631, + "1632" => 1632, + "1633" => 1633, + "1634" => 1634, + "1635" => 1635, + "1636" => 1636, + "1637" => 1637, + "1638" => 1638, + "1639" => 1639, + "1640" => 1640, + "1641" => 1641, + "1642" => 1642, + "1643" => 1643, + "1644" => 1644, + "1645" => 1645, + "1646" => 1646, + "1647" => 1647, + "1648" => 1648, + "1649" => 1649, + "1650" => 1650, + "1651" => 1651, + "1652" => 1652, + "1653" => 1653, + "1654" => 1654, + "1655" => 1655, + "1656" => 1656, + "1657" => 1657, + "1658" => 1658, + "1659" => 1659, + "1660" => 1660, + "1661" => 1661, + "1662" => 1662, + "1663" => 1663, + "1664" => 1664, + "1665" => 1665, + "1666" => 1666, + "1667" => 1667, + "1668" => 1668, + "1669" => 1669, + "1670" => 1670, + "1671" => 1671, + "1672" => 1672, + "1673" => 1673, + "1674" => 1674, + "1675" => 1675, + "1676" => 1676, + "1677" => 1677, + "1678" => 1678, + "1679" => 1679, + "1680" => 1680, + "1681" => 1681, + "1682" => 1682, + "1683" => 1683, + "1684" => 1684, + "1685" => 1685, + "1686" => 1686, + "1687" => 1687, + "1688" => 1688, + "1689" => 1689, + "1690" => 1690, + "1691" => 1691, + "1692" => 1692, + "1693" => 1693, + "1694" => 1694, + "1695" => 1695, + "1696" => 1696, + "1697" => 1697, + "1698" => 1698, + "1699" => 1699, + "1700" => 1700, + "1701" => 1701, + "1702" => 1702, + "1703" => 1703, + "1704" => 1704, + "1705" => 1705, + "1706" => 1706, + "1707" => 1707, + "1708" => 1708, + "1709" => 1709, + "1710" => 1710, + "1711" => 1711, + "1712" => 1712, + "1713" => 1713, + "1714" => 1714, + "1715" => 1715, + "1716" => 1716, + "1717" => 1717, + "1718" => 1718, + "1719" => 1719, + "1720" => 1720, + "1721" => 1721, + "1722" => 1722, + "1723" => 1723, + "1724" => 1724, + "1725" => 1725, + "1726" => 1726, + "1727" => 1727, + "1728" => 1728, + "1729" => 1729, + "1730" => 1730, + "1731" => 1731, + "1732" => 1732, + "1733" => 1733, + "1734" => 1734, + "1735" => 1735, + "1736" => 1736, + "1737" => 1737, + "1738" => 1738, + "1739" => 1739, + "1740" => 1740, + "1741" => 1741, + "1742" => 1742, + "1743" => 1743, + "1744" => 1744, + "1745" => 1745, + "1746" => 1746, + "1747" => 1747, + "1748" => 1748, + "1749" => 1749, + "1750" => 1750, + "1751" => 1751, + "1752" => 1752, + "1753" => 1753, + "1754" => 1754, + "1755" => 1755, + "1756" => 1756, + "1757" => 1757, + "1758" => 1758, + "1759" => 1759, + "1760" => 1760, + "1761" => 1761, + "1762" => 1762, + "1763" => 1763, + "1764" => 1764, + "1765" => 1765, + "1766" => 1766, + "1767" => 1767, + "1768" => 1768, + "1769" => 1769, + "1770" => 1770, + "1771" => 1771, + "1772" => 1772, + "1773" => 1773, + "1774" => 1774, + "1775" => 1775, + "1776" => 1776, + "1777" => 1777, + "1778" => 1778, + "1779" => 1779, + "1780" => 1780, + "1781" => 1781, + "1782" => 1782, + "1783" => 1783, + "1784" => 1784, + "1785" => 1785, + "1786" => 1786, + "1787" => 1787, + "1788" => 1788, + "1789" => 1789, + "1790" => 1790, + "1791" => 1791, + "1792" => 1792, + "1793" => 1793, + "1794" => 1794, + "1795" => 1795, + "1796" => 1796, + "1797" => 1797, + "1798" => 1798, + "1799" => 1799, + "1800" => 1800, + "1801" => 1801, + "1802" => 1802, + "1803" => 1803, + "1804" => 1804, + "1805" => 1805, + "1806" => 1806, + "1807" => 1807, + "1808" => 1808, + "1809" => 1809, + "1810" => 1810, + "1811" => 1811, + "1812" => 1812, + "1813" => 1813, + "1814" => 1814, + "1815" => 1815, + "1816" => 1816, + "1817" => 1817, + "1818" => 1818, + "1819" => 1819, + "1820" => 1820, + "1821" => 1821, + "1822" => 1822, + "1823" => 1823, + "1824" => 1824, + "1825" => 1825, + "1826" => 1826, + "1827" => 1827, + "1828" => 1828, + "1829" => 1829, + "1830" => 1830, + "1831" => 1831, + "1832" => 1832, + "1833" => 1833, + "1834" => 1834, + "1835" => 1835, + "1836" => 1836, + "1837" => 1837, + "1838" => 1838, + "1839" => 1839, + "1840" => 1840, + "1841" => 1841, + "1842" => 1842, + "1843" => 1843, + "1844" => 1844, + "1845" => 1845, + "1846" => 1846, + "1847" => 1847, + "1848" => 1848, + "1849" => 1849, + "1850" => 1850, + "1851" => 1851, + "1852" => 1852, + "1853" => 1853, + "1854" => 1854, + "1855" => 1855, + "1856" => 1856, + "1857" => 1857, + "1858" => 1858, + "1859" => 1859, + "1860" => 1860, + "1861" => 1861, + "1862" => 1862, + "1863" => 1863, + "1864" => 1864, + "1865" => 1865, + "1866" => 1866, + "1867" => 1867, + "1868" => 1868, + "1869" => 1869, + "1870" => 1870, + "1871" => 1871, + "1872" => 1872, + "1873" => 1873, + "1874" => 1874, + "1875" => 1875, + "1876" => 1876, + "1877" => 1877, + "1878" => 1878, + "1879" => 1879, + "1880" => 1880, + "1881" => 1881, + "1882" => 1882, + "1883" => 1883, + "1884" => 1884, + "1885" => 1885, + "1886" => 1886, + "1887" => 1887, + "1888" => 1888, + "1889" => 1889, + "1890" => 1890, + "1891" => 1891, + "1892" => 1892, + "1893" => 1893, + "1894" => 1894, + "1895" => 1895, + "1896" => 1896, + "1897" => 1897, + "1898" => 1898, + "1899" => 1899, + "1900" => 1900, + "1901" => 1901, + "1902" => 1902, + "1903" => 1903, + "1904" => 1904, + "1905" => 1905, + "1906" => 1906, + "1907" => 1907, + "1908" => 1908, + "1909" => 1909, + "1910" => 1910, + "1911" => 1911, + "1912" => 1912, + "1913" => 1913, + "1914" => 1914, + "1915" => 1915, + "1916" => 1916, + "1917" => 1917, + "1918" => 1918, + "1919" => 1919, + "1920" => 1920, + "1921" => 1921, + "1922" => 1922, + "1923" => 1923, + "1924" => 1924, + "1925" => 1925, + "1926" => 1926, + "1927" => 1927, + "1928" => 1928, + "1929" => 1929, + "1930" => 1930, + "1931" => 1931, + "1932" => 1932, + "1933" => 1933, + "1934" => 1934, + "1935" => 1935, + "1936" => 1936, + "1937" => 1937, + "1938" => 1938, + "1939" => 1939, + "1940" => 1940, + "1941" => 1941, + "1942" => 1942, + "1943" => 1943, + "1944" => 1944, + "1945" => 1945, + "1946" => 1946, + "1947" => 1947, + "1948" => 1948, + "1949" => 1949, + "1950" => 1950, + "1951" => 1951, + "1952" => 1952, + "1953" => 1953, + "1954" => 1954, + "1955" => 1955, + "1956" => 1956, + "1957" => 1957, + "1958" => 1958, + "1959" => 1959, + "1960" => 1960, + "1961" => 1961, + "1962" => 1962, + "1963" => 1963, + "1964" => 1964, + "1965" => 1965, + "1966" => 1966, + "1967" => 1967, + "1968" => 1968, + "1969" => 1969, + "1970" => 1970, + "1971" => 1971, + "1972" => 1972, + "1973" => 1973, + "1974" => 1974, + "1975" => 1975, + "1976" => 1976, + "1977" => 1977, + "1978" => 1978, + "1979" => 1979, + "1980" => 1980, + "1981" => 1981, + "1982" => 1982, + "1983" => 1983, + "1984" => 1984, + "1985" => 1985, + "1986" => 1986, + "1987" => 1987, + "1988" => 1988, + "1989" => 1989, + "1990" => 1990, + "1991" => 1991, + "1992" => 1992, + "1993" => 1993, + "1994" => 1994, + "1995" => 1995, + "1996" => 1996, + "1997" => 1997, + "1998" => 1998, + "1999" => 1999, + "2000" => 2000, + "2001" => 2001, + "2002" => 2002, + "2003" => 2003, + "2004" => 2004, + "2005" => 2005, + "2006" => 2006, + "2007" => 2007, + "2008" => 2008, + "2009" => 2009, + "2010" => 2010, + "2011" => 2011, + "2012" => 2012, + "2013" => 2013, + "2014" => 2014, + "2015" => 2015, + "2016" => 2016, + "2017" => 2017, + "2018" => 2018, + "2019" => 2019, + "2020" => 2020, + "2021" => 2021, + "2022" => 2022, + "2023" => 2023, + "2024" => 2024, + "2025" => 2025, + "2026" => 2026, + "2027" => 2027, + "2028" => 2028, + "2029" => 2029, + "2030" => 2030, + "2031" => 2031, + "2032" => 2032, + "2033" => 2033, + "2034" => 2034, + "2035" => 2035, + "2036" => 2036, + "2037" => 2037, + "2038" => 2038, + "2039" => 2039, + "2040" => 2040, + "2041" => 2041, + "2042" => 2042, + "2043" => 2043, + "2044" => 2044, + "2045" => 2045, + "2046" => 2046, + "2047" => 2047, + "2048" => 2048, + "2049" => 2049, + "2050" => 2050, + "2051" => 2051, + "2052" => 2052, + "2053" => 2053, + "2054" => 2054, + "2055" => 2055, + "2056" => 2056, + "2057" => 2057, + "2058" => 2058, + "2059" => 2059, + "2060" => 2060, + "2061" => 2061, + "2062" => 2062, + "2063" => 2063, + "2064" => 2064, + "2065" => 2065, + "2066" => 2066, + "2067" => 2067, + "2068" => 2068, + "2069" => 2069, + "2070" => 2070, + "2071" => 2071, + "2072" => 2072, + "2073" => 2073, + "2074" => 2074, + "2075" => 2075, + "2076" => 2076, + "2077" => 2077, + "2078" => 2078, + "2079" => 2079, + "2080" => 2080, + "2081" => 2081, + "2082" => 2082, + "2083" => 2083, + "2084" => 2084, + "2085" => 2085, + "2086" => 2086, + "2087" => 2087, + "2088" => 2088, + "2089" => 2089, + "2090" => 2090, + "2091" => 2091, + "2092" => 2092, + "2093" => 2093, + "2094" => 2094, + "2095" => 2095, + "2096" => 2096, + "2097" => 2097, + "2098" => 2098, + "2099" => 2099, + "2100" => 2100, + "2101" => 2101, + "2102" => 2102, + "2103" => 2103, + "2104" => 2104, + "2105" => 2105, + "2106" => 2106, + "2107" => 2107, + "2108" => 2108, + "2109" => 2109, + "2110" => 2110, + "2111" => 2111, + "2112" => 2112, + "2113" => 2113, + "2114" => 2114, + "2115" => 2115, + "2116" => 2116, + "2117" => 2117, + "2118" => 2118, + "2119" => 2119, + "2120" => 2120, + "2121" => 2121, + "2122" => 2122, + "2123" => 2123, + "2124" => 2124, + "2125" => 2125, + "2126" => 2126, + "2127" => 2127, + "2128" => 2128, + "2129" => 2129, + "2130" => 2130, + "2131" => 2131, + "2132" => 2132, + "2133" => 2133, + "2134" => 2134, + "2135" => 2135, + "2136" => 2136, + "2137" => 2137, + "2138" => 2138, + "2139" => 2139, + "2140" => 2140, + "2141" => 2141, + "2142" => 2142, + "2143" => 2143, + "2144" => 2144, + "2145" => 2145, + "2146" => 2146, + "2147" => 2147, + "2148" => 2148, + "2149" => 2149, + "2150" => 2150, + "2151" => 2151, + "2152" => 2152, + "2153" => 2153, + "2154" => 2154, + "2155" => 2155, + "2156" => 2156, + "2157" => 2157, + "2158" => 2158, + "2159" => 2159, + "2160" => 2160, + "2161" => 2161, + "2162" => 2162, + "2163" => 2163, + "2164" => 2164, + "2165" => 2165, + "2166" => 2166, + "2167" => 2167, + "2168" => 2168, + "2169" => 2169, + "2170" => 2170, + "2171" => 2171, + "2172" => 2172, + "2173" => 2173, + "2174" => 2174, + "2175" => 2175, + "2176" => 2176, + "2177" => 2177, + "2178" => 2178, + "2179" => 2179, + "2180" => 2180, + "2181" => 2181, + "2182" => 2182, + "2183" => 2183, + "2184" => 2184, + "2185" => 2185, + "2186" => 2186, + "2187" => 2187, + "2188" => 2188, + "2189" => 2189, + "2190" => 2190, + "2191" => 2191, + "2192" => 2192, + "2193" => 2193, + "2194" => 2194, + "2195" => 2195, + "2196" => 2196, + "2197" => 2197, + "2198" => 2198, + "2199" => 2199, + "2200" => 2200, + "2201" => 2201, + "2202" => 2202, + "2203" => 2203, + "2204" => 2204, + "2205" => 2205, + "2206" => 2206, + "2207" => 2207, + "2208" => 2208, + "2209" => 2209, + "2210" => 2210, + "2211" => 2211, + "2212" => 2212, + "2213" => 2213, + "2214" => 2214, + "2215" => 2215, + "2216" => 2216, + "2217" => 2217, + "2218" => 2218, + "2219" => 2219, + "2220" => 2220, + "2221" => 2221, + "2222" => 2222, + "2223" => 2223, + "2224" => 2224, + "2225" => 2225, + "2226" => 2226, + "2227" => 2227, + "2228" => 2228, + "2229" => 2229, + "2230" => 2230, + "2231" => 2231, + "2232" => 2232, + "2233" => 2233, + "2234" => 2234, + "2235" => 2235, + "2236" => 2236, + "2237" => 2237, + "2238" => 2238, + "2239" => 2239, + "2240" => 2240, + "2241" => 2241, + "2242" => 2242, + "2243" => 2243, + "2244" => 2244, + "2245" => 2245, + "2246" => 2246, + "2247" => 2247, + "2248" => 2248, + "2249" => 2249, + "2250" => 2250, + "2251" => 2251, + "2252" => 2252, + "2253" => 2253, + "2254" => 2254, + "2255" => 2255, + "2256" => 2256, + "2257" => 2257, + "2258" => 2258, + "2259" => 2259, + "2260" => 2260, + "2261" => 2261, + "2262" => 2262, + "2263" => 2263, + "2264" => 2264, + "2265" => 2265, + "2266" => 2266, + "2267" => 2267, + "2268" => 2268, + "2269" => 2269, + "2270" => 2270, + "2271" => 2271, + "2272" => 2272, + "2273" => 2273, + "2274" => 2274, + "2275" => 2275, + "2276" => 2276, + "2277" => 2277, + "2278" => 2278, + "2279" => 2279, + "2280" => 2280, + "2281" => 2281, + "2282" => 2282, + "2283" => 2283, + "2284" => 2284, + "2285" => 2285, + "2286" => 2286, + "2287" => 2287, + "2288" => 2288, + "2289" => 2289, + "2290" => 2290, + "2291" => 2291, + "2292" => 2292, + "2293" => 2293, + "2294" => 2294, + "2295" => 2295, + "2296" => 2296, + "2297" => 2297, + "2298" => 2298, + "2299" => 2299, + "2300" => 2300, + "2301" => 2301, + "2302" => 2302, + "2303" => 2303, + "2304" => 2304, + "2305" => 2305, + "2306" => 2306, + "2307" => 2307, + "2308" => 2308, + "2309" => 2309, + "2310" => 2310, + "2311" => 2311, + "2312" => 2312, + "2313" => 2313, + "2314" => 2314, + "2315" => 2315, + "2316" => 2316, + "2317" => 2317, + "2318" => 2318, + "2319" => 2319, + "2320" => 2320, + "2321" => 2321, + "2322" => 2322, + "2323" => 2323, + "2324" => 2324, + "2325" => 2325, + "2326" => 2326, + "2327" => 2327, + "2328" => 2328, + "2329" => 2329, + "2330" => 2330, + "2331" => 2331, + "2332" => 2332, + "2333" => 2333, + "2334" => 2334, + "2335" => 2335, + "2336" => 2336, + "2337" => 2337, + "2338" => 2338, + "2339" => 2339, + "2340" => 2340, + "2341" => 2341, + "2342" => 2342, + "2343" => 2343, + "2344" => 2344, + "2345" => 2345, + "2346" => 2346, + "2347" => 2347, + "2348" => 2348, + "2349" => 2349, + "2350" => 2350, + "2351" => 2351, + "2352" => 2352, + "2353" => 2353, + "2354" => 2354, + "2355" => 2355, + "2356" => 2356, + "2357" => 2357, + "2358" => 2358, + "2359" => 2359, + "2360" => 2360, + "2361" => 2361, + "2362" => 2362, + "2363" => 2363, + "2364" => 2364, + "2365" => 2365, + "2366" => 2366, + "2367" => 2367, + "2368" => 2368, + "2369" => 2369, + "2370" => 2370, + "2371" => 2371, + "2372" => 2372, + "2373" => 2373, + "2374" => 2374, + "2375" => 2375, + "2376" => 2376, + "2377" => 2377, + "2378" => 2378, + "2379" => 2379, + "2380" => 2380, + "2381" => 2381, + "2382" => 2382, + "2383" => 2383, + "2384" => 2384, + "2385" => 2385, + "2386" => 2386, + "2387" => 2387, + "2388" => 2388, + "2389" => 2389, + "2390" => 2390, + "2391" => 2391, + "2392" => 2392, + "2393" => 2393, + "2394" => 2394, + "2395" => 2395, + "2396" => 2396, + "2397" => 2397, + "2398" => 2398, + "2399" => 2399, + "2400" => 2400, + "2401" => 2401, + "2402" => 2402, + "2403" => 2403, + "2404" => 2404, + "2405" => 2405, + "2406" => 2406, + "2407" => 2407, + "2408" => 2408, + "2409" => 2409, + "2410" => 2410, + "2411" => 2411, + "2412" => 2412, + "2413" => 2413, + "2414" => 2414, + "2415" => 2415, + "2416" => 2416, + "2417" => 2417, + "2418" => 2418, + "2419" => 2419, + "2420" => 2420, + "2421" => 2421, + "2422" => 2422, + "2423" => 2423, + "2424" => 2424, + "2425" => 2425, + "2426" => 2426, + "2427" => 2427, + "2428" => 2428, + "2429" => 2429, + "2430" => 2430, + "2431" => 2431, + "2432" => 2432, + "2433" => 2433, + "2434" => 2434, + "2435" => 2435, + "2436" => 2436, + "2437" => 2437, + "2438" => 2438, + "2439" => 2439, + "2440" => 2440, + "2441" => 2441, + "2442" => 2442, + "2443" => 2443, + "2444" => 2444, + "2445" => 2445, + "2446" => 2446, + "2447" => 2447, + "2448" => 2448, + "2449" => 2449, + "2450" => 2450, + "2451" => 2451, + "2452" => 2452, + "2453" => 2453, + "2454" => 2454, + "2455" => 2455, + "2456" => 2456, + "2457" => 2457, + "2458" => 2458, + "2459" => 2459, + "2460" => 2460, + "2461" => 2461, + "2462" => 2462, + "2463" => 2463, + "2464" => 2464, + "2465" => 2465, + "2466" => 2466, + "2467" => 2467, + "2468" => 2468, + "2469" => 2469, + "2470" => 2470, + "2471" => 2471, + "2472" => 2472, + "2473" => 2473, + "2474" => 2474, + "2475" => 2475, + "2476" => 2476, + "2477" => 2477, + "2478" => 2478, + "2479" => 2479, + "2480" => 2480, + "2481" => 2481, + "2482" => 2482, + "2483" => 2483, + "2484" => 2484, + "2485" => 2485, + "2486" => 2486, + "2487" => 2487, + "2488" => 2488, + "2489" => 2489, + "2490" => 2490, + "2491" => 2491, + "2492" => 2492, + "2493" => 2493, + "2494" => 2494, + "2495" => 2495, + "2496" => 2496, + "2497" => 2497, + "2498" => 2498, + "2499" => 2499, + "2500" => 2500, + "2501" => 2501, + "2502" => 2502, + "2503" => 2503, + "2504" => 2504, + "2505" => 2505, + "2506" => 2506, + "2507" => 2507, + "2508" => 2508, + "2509" => 2509, + "2510" => 2510, + "2511" => 2511, + "2512" => 2512, + "2513" => 2513, + "2514" => 2514, + "2515" => 2515, + "2516" => 2516, + "2517" => 2517, + "2518" => 2518, + "2519" => 2519, + "2520" => 2520, + "2521" => 2521, + "2522" => 2522, + "2523" => 2523, + "2524" => 2524, + "2525" => 2525, + "2526" => 2526, + "2527" => 2527, + "2528" => 2528, + "2529" => 2529, + "2530" => 2530, + "2531" => 2531, + "2532" => 2532, + "2533" => 2533, + "2534" => 2534, + "2535" => 2535, + "2536" => 2536, + "2537" => 2537, + "2538" => 2538, + "2539" => 2539, + "2540" => 2540, + "2541" => 2541, + "2542" => 2542, + "2543" => 2543, + "2544" => 2544, + "2545" => 2545, + "2546" => 2546, + "2547" => 2547, + "2548" => 2548, + "2549" => 2549, + "2550" => 2550, + "2551" => 2551, + "2552" => 2552, + "2553" => 2553, + "2554" => 2554, + "2555" => 2555, + "2556" => 2556, + "2557" => 2557, + "2558" => 2558, + "2559" => 2559, + "2560" => 2560, + "2561" => 2561, + "2562" => 2562, + "2563" => 2563, + "2564" => 2564, + "2565" => 2565, + "2566" => 2566, + "2567" => 2567, + "2568" => 2568, + "2569" => 2569, + "2570" => 2570, + "2571" => 2571, + "2572" => 2572, + "2573" => 2573, + "2574" => 2574, + "2575" => 2575, + "2576" => 2576, + "2577" => 2577, + "2578" => 2578, + "2579" => 2579, + "2580" => 2580, + "2581" => 2581, + "2582" => 2582, + "2583" => 2583, + "2584" => 2584, + "2585" => 2585, + "2586" => 2586, + "2587" => 2587, + "2588" => 2588, + "2589" => 2589, + "2590" => 2590, + "2591" => 2591, + "2592" => 2592, + "2593" => 2593, + "2594" => 2594, + "2595" => 2595, + "2596" => 2596, + "2597" => 2597, + "2598" => 2598, + "2599" => 2599, + "2600" => 2600, + "2601" => 2601, + "2602" => 2602, + "2603" => 2603, + "2604" => 2604, + "2605" => 2605, + "2606" => 2606, + "2607" => 2607, + "2608" => 2608, + "2609" => 2609, + "2610" => 2610, + "2611" => 2611, + "2612" => 2612, + "2613" => 2613, + "2614" => 2614, + "2615" => 2615, + "2616" => 2616, + "2617" => 2617, + "2618" => 2618, + "2619" => 2619, + "2620" => 2620, + "2621" => 2621, + "2622" => 2622, + "2623" => 2623, + "2624" => 2624, + "2625" => 2625, + "2626" => 2626, + "2627" => 2627, + "2628" => 2628, + "2629" => 2629, + "2630" => 2630, + "2631" => 2631, + "2632" => 2632, + "2633" => 2633, + "2634" => 2634, + "2635" => 2635, + "2636" => 2636, + "2637" => 2637, + "2638" => 2638, + "2639" => 2639, + "2640" => 2640, + "2641" => 2641, + "2642" => 2642, + "2643" => 2643, + "2644" => 2644, + "2645" => 2645, + "2646" => 2646, + "2647" => 2647, + "2648" => 2648, + "2649" => 2649, + "2650" => 2650, + "2651" => 2651, + "2652" => 2652, + "2653" => 2653, + "2654" => 2654, + "2655" => 2655, + "2656" => 2656, + "2657" => 2657, + "2658" => 2658, + "2659" => 2659, + "2660" => 2660, + "2661" => 2661, + "2662" => 2662, + "2663" => 2663, + "2664" => 2664, + "2665" => 2665, + "2666" => 2666, + "2667" => 2667, + "2668" => 2668, + "2669" => 2669, + "2670" => 2670, + "2671" => 2671, + "2672" => 2672, + "2673" => 2673, + "2674" => 2674, + "2675" => 2675, + "2676" => 2676, + "2677" => 2677, + "2678" => 2678, + "2679" => 2679, + "2680" => 2680, + "2681" => 2681, + "2682" => 2682, + "2683" => 2683, + "2684" => 2684, + "2685" => 2685, + "2686" => 2686, + "2687" => 2687, + "2688" => 2688, + "2689" => 2689, + "2690" => 2690, + "2691" => 2691, + "2692" => 2692, + "2693" => 2693, + "2694" => 2694, + "2695" => 2695, + "2696" => 2696, + "2697" => 2697, + "2698" => 2698, + "2699" => 2699, + "2700" => 2700, + "2701" => 2701, + "2702" => 2702, + "2703" => 2703, + "2704" => 2704, + "2705" => 2705, + "2706" => 2706, + "2707" => 2707, + "2708" => 2708, + "2709" => 2709, + "2710" => 2710, + "2711" => 2711, + "2712" => 2712, + "2713" => 2713, + "2714" => 2714, + "2715" => 2715, + "2716" => 2716, + "2717" => 2717, + "2718" => 2718, + "2719" => 2719, + "2720" => 2720, + "2721" => 2721, + "2722" => 2722, + "2723" => 2723, + "2724" => 2724, + "2725" => 2725, + "2726" => 2726, + "2727" => 2727, + "2728" => 2728, + "2729" => 2729, + "2730" => 2730, + "2731" => 2731, + "2732" => 2732, + "2733" => 2733, + "2734" => 2734, + "2735" => 2735, + "2736" => 2736, + "2737" => 2737, + "2738" => 2738, + "2739" => 2739, + "2740" => 2740, + "2741" => 2741, + "2742" => 2742, + "2743" => 2743, + "2744" => 2744, + "2745" => 2745, + "2746" => 2746, + "2747" => 2747, + "2748" => 2748, + "2749" => 2749, + "2750" => 2750, + "2751" => 2751, + "2752" => 2752, + "2753" => 2753, + "2754" => 2754, + "2755" => 2755, + "2756" => 2756, + "2757" => 2757, + "2758" => 2758, + "2759" => 2759, + "2760" => 2760, + "2761" => 2761, + "2762" => 2762, + "2763" => 2763, + "2764" => 2764, + "2765" => 2765, + "2766" => 2766, + "2767" => 2767, + "2768" => 2768, + "2769" => 2769, + "2770" => 2770, + "2771" => 2771, + "2772" => 2772, + "2773" => 2773, + "2774" => 2774, + "2775" => 2775, + "2776" => 2776, + "2777" => 2777, + "2778" => 2778, + "2779" => 2779, + "2780" => 2780, + "2781" => 2781, + "2782" => 2782, + "2783" => 2783, + "2784" => 2784, + "2785" => 2785, + "2786" => 2786, + "2787" => 2787, + "2788" => 2788, + "2789" => 2789, + "2790" => 2790, + "2791" => 2791, + "2792" => 2792, + "2793" => 2793, + "2794" => 2794, + "2795" => 2795, + "2796" => 2796, + "2797" => 2797, + "2798" => 2798, + "2799" => 2799, + "2800" => 2800, + "2801" => 2801, + "2802" => 2802, + "2803" => 2803, + "2804" => 2804, + "2805" => 2805, + "2806" => 2806, + "2807" => 2807, + "2808" => 2808, + "2809" => 2809, + "2810" => 2810, + "2811" => 2811, + "2812" => 2812, + "2813" => 2813, + "2814" => 2814, + "2815" => 2815, + "2816" => 2816, + "2817" => 2817, + "2818" => 2818, + "2819" => 2819, + "2820" => 2820, + "2821" => 2821, + "2822" => 2822, + "2823" => 2823, + "2824" => 2824, + "2825" => 2825, + "2826" => 2826, + "2827" => 2827, + "2828" => 2828, + "2829" => 2829, + "2830" => 2830, + "2831" => 2831, + "2832" => 2832, + "2833" => 2833, + "2834" => 2834, + "2835" => 2835, + "2836" => 2836, + "2837" => 2837, + "2838" => 2838, + "2839" => 2839, + "2840" => 2840, + "2841" => 2841, + "2842" => 2842, + "2843" => 2843, + "2844" => 2844, + "2845" => 2845, + "2846" => 2846, + "2847" => 2847, + "2848" => 2848, + "2849" => 2849, + "2850" => 2850, + "2851" => 2851, + "2852" => 2852, + "2853" => 2853, + "2854" => 2854, + "2855" => 2855, + "2856" => 2856, + "2857" => 2857, + "2858" => 2858, + "2859" => 2859, + "2860" => 2860, + "2861" => 2861, + "2862" => 2862, + "2863" => 2863, + "2864" => 2864, + "2865" => 2865, + "2866" => 2866, + "2867" => 2867, + "2868" => 2868, + "2869" => 2869, + "2870" => 2870, + "2871" => 2871, + "2872" => 2872, + "2873" => 2873, + "2874" => 2874, + "2875" => 2875, + "2876" => 2876, + "2877" => 2877, + "2878" => 2878, + "2879" => 2879, + "2880" => 2880, + "2881" => 2881, + "2882" => 2882, + "2883" => 2883, + "2884" => 2884, + "2885" => 2885, + "2886" => 2886, + "2887" => 2887, + "2888" => 2888, + "2889" => 2889, + "2890" => 2890, + "2891" => 2891, + "2892" => 2892, + "2893" => 2893, + "2894" => 2894, + "2895" => 2895, + "2896" => 2896, + "2897" => 2897, + "2898" => 2898, + "2899" => 2899, + "2900" => 2900, + "2901" => 2901, + "2902" => 2902, + "2903" => 2903, + "2904" => 2904, + "2905" => 2905, + "2906" => 2906, + "2907" => 2907, + "2908" => 2908, + "2909" => 2909, + "2910" => 2910, + "2911" => 2911, + "2912" => 2912, + "2913" => 2913, + "2914" => 2914, + "2915" => 2915, + "2916" => 2916, + "2917" => 2917, + "2918" => 2918, + "2919" => 2919, + "2920" => 2920, + "2921" => 2921, + "2922" => 2922, + "2923" => 2923, + "2924" => 2924, + "2925" => 2925, + "2926" => 2926, + "2927" => 2927, + "2928" => 2928, + "2929" => 2929, + "2930" => 2930, + "2931" => 2931, + "2932" => 2932, + "2933" => 2933, + "2934" => 2934, + "2935" => 2935, + "2936" => 2936, + "2937" => 2937, + "2938" => 2938, + "2939" => 2939, + "2940" => 2940, + "2941" => 2941, + "2942" => 2942, + "2943" => 2943, + "2944" => 2944, + "2945" => 2945, + "2946" => 2946, + "2947" => 2947, + "2948" => 2948, + "2949" => 2949, + "2950" => 2950, + "2951" => 2951, + "2952" => 2952, + "2953" => 2953, + "2954" => 2954, + "2955" => 2955, + "2956" => 2956, + "2957" => 2957, + "2958" => 2958, + "2959" => 2959, + "2960" => 2960, + "2961" => 2961, + "2962" => 2962, + "2963" => 2963, + "2964" => 2964, + "2965" => 2965, + "2966" => 2966, + "2967" => 2967, + "2968" => 2968, + "2969" => 2969, + "2970" => 2970, + "2971" => 2971, + "2972" => 2972, + "2973" => 2973, + "2974" => 2974, + "2975" => 2975, + "2976" => 2976, + "2977" => 2977, + "2978" => 2978, + "2979" => 2979, + "2980" => 2980, + "2981" => 2981, + "2982" => 2982, + "2983" => 2983, + "2984" => 2984, + "2985" => 2985, + "2986" => 2986, + "2987" => 2987, + "2988" => 2988, + "2989" => 2989, + "2990" => 2990, + "2991" => 2991, + "2992" => 2992, + "2993" => 2993, + "2994" => 2994, + "2995" => 2995, + "2996" => 2996, + "2997" => 2997, + "2998" => 2998, + "2999" => 2999, + "3000" => 3000, + "3001" => 3001, + "3002" => 3002, + "3003" => 3003, + "3004" => 3004, + "3005" => 3005, + "3006" => 3006, + "3007" => 3007, + "3008" => 3008, + "3009" => 3009, + "3010" => 3010, + "3011" => 3011, + "3012" => 3012, + "3013" => 3013, + "3014" => 3014, + "3015" => 3015, + "3016" => 3016, + "3017" => 3017, + "3018" => 3018, + "3019" => 3019, + "3020" => 3020, + "3021" => 3021, + "3022" => 3022, + "3023" => 3023, + "3024" => 3024, + "3025" => 3025, + "3026" => 3026, + "3027" => 3027, + "3028" => 3028, + "3029" => 3029, + "3030" => 3030, + "3031" => 3031, + "3032" => 3032, + "3033" => 3033, + "3034" => 3034, + "3035" => 3035, + "3036" => 3036, + "3037" => 3037, + "3038" => 3038, + "3039" => 3039, + "3040" => 3040, + "3041" => 3041, + "3042" => 3042, + "3043" => 3043, + "3044" => 3044, + "3045" => 3045, + "3046" => 3046, + "3047" => 3047, + "3048" => 3048, + "3049" => 3049, + "3050" => 3050, + "3051" => 3051, + "3052" => 3052, + "3053" => 3053, + "3054" => 3054, + "3055" => 3055, + "3056" => 3056, + "3057" => 3057, + "3058" => 3058, + "3059" => 3059, + "3060" => 3060, + "3061" => 3061, + "3062" => 3062, + "3063" => 3063, + "3064" => 3064, + "3065" => 3065, + "3066" => 3066, + "3067" => 3067, + "3068" => 3068, + "3069" => 3069, + "3070" => 3070, + "3071" => 3071, + "3072" => 3072, + "3073" => 3073, + "3074" => 3074, + "3075" => 3075, + "3076" => 3076, + "3077" => 3077, + "3078" => 3078, + "3079" => 3079, + "3080" => 3080, + "3081" => 3081, + "3082" => 3082, + "3083" => 3083, + "3084" => 3084, + "3085" => 3085, + "3086" => 3086, + "3087" => 3087, + "3088" => 3088, + "3089" => 3089, + "3090" => 3090, + "3091" => 3091, + "3092" => 3092, + "3093" => 3093, + "3094" => 3094, + "3095" => 3095, + "3096" => 3096, + "3097" => 3097, + "3098" => 3098, + "3099" => 3099, + "3100" => 3100, + "3101" => 3101, + "3102" => 3102, + "3103" => 3103, + "3104" => 3104, + "3105" => 3105, + "3106" => 3106, + "3107" => 3107, + "3108" => 3108, + "3109" => 3109, + "3110" => 3110, + "3111" => 3111, + "3112" => 3112, + "3113" => 3113, + "3114" => 3114, + "3115" => 3115, + "3116" => 3116, + "3117" => 3117, + "3118" => 3118, + "3119" => 3119, + "3120" => 3120, + "3121" => 3121, + "3122" => 3122, + "3123" => 3123, + "3124" => 3124, + "3125" => 3125, + "3126" => 3126, + "3127" => 3127, + "3128" => 3128, + "3129" => 3129, + "3130" => 3130, + "3131" => 3131, + "3132" => 3132, + "3133" => 3133, + "3134" => 3134, + "3135" => 3135, + "3136" => 3136, + "3137" => 3137, + "3138" => 3138, + "3139" => 3139, + "3140" => 3140, + "3141" => 3141, + "3142" => 3142, + "3143" => 3143, + "3144" => 3144, + "3145" => 3145, + "3146" => 3146, + "3147" => 3147, + "3148" => 3148, + "3149" => 3149, + "3150" => 3150, + "3151" => 3151, + "3152" => 3152, + "3153" => 3153, + "3154" => 3154, + "3155" => 3155, + "3156" => 3156, + "3157" => 3157, + "3158" => 3158, + "3159" => 3159, + "3160" => 3160, + "3161" => 3161, + "3162" => 3162, + "3163" => 3163, + "3164" => 3164, + "3165" => 3165, + "3166" => 3166, + "3167" => 3167, + "3168" => 3168, + "3169" => 3169, + "3170" => 3170, + "3171" => 3171, + "3172" => 3172, + "3173" => 3173, + "3174" => 3174, + "3175" => 3175, + "3176" => 3176, + "3177" => 3177, + "3178" => 3178, + "3179" => 3179, + "3180" => 3180, + "3181" => 3181, + "3182" => 3182, + "3183" => 3183, + "3184" => 3184, + "3185" => 3185, + "3186" => 3186, + "3187" => 3187, + "3188" => 3188, + "3189" => 3189, + "3190" => 3190, + "3191" => 3191, + "3192" => 3192, + "3193" => 3193, + "3194" => 3194, + "3195" => 3195, + "3196" => 3196, + "3197" => 3197, + "3198" => 3198, + "3199" => 3199, + "3200" => 3200, + "3201" => 3201, + "3202" => 3202, + "3203" => 3203, + "3204" => 3204, + "3205" => 3205, + "3206" => 3206, + "3207" => 3207, + "3208" => 3208, + "3209" => 3209, + "3210" => 3210, + "3211" => 3211, + "3212" => 3212, + "3213" => 3213, + "3214" => 3214, + "3215" => 3215, + "3216" => 3216, + "3217" => 3217, + "3218" => 3218, + "3219" => 3219, + "3220" => 3220, + "3221" => 3221, + "3222" => 3222, + "3223" => 3223, + "3224" => 3224, + "3225" => 3225, + "3226" => 3226, + "3227" => 3227, + "3228" => 3228, + "3229" => 3229, + "3230" => 3230, + "3231" => 3231, + "3232" => 3232, + "3233" => 3233, + "3234" => 3234, + "3235" => 3235, + "3236" => 3236, + "3237" => 3237, + "3238" => 3238, + "3239" => 3239, + "3240" => 3240, + "3241" => 3241, + "3242" => 3242, + "3243" => 3243, + "3244" => 3244, + "3245" => 3245, + "3246" => 3246, + "3247" => 3247, + "3248" => 3248, + "3249" => 3249, + "3250" => 3250, + "3251" => 3251, + "3252" => 3252, + "3253" => 3253, + "3254" => 3254, + "3255" => 3255, + "3256" => 3256, + "3257" => 3257, + "3258" => 3258, + "3259" => 3259, + "3260" => 3260, + "3261" => 3261, + "3262" => 3262, + "3263" => 3263, + "3264" => 3264, + "3265" => 3265, + "3266" => 3266, + "3267" => 3267, + "3268" => 3268, + "3269" => 3269, + "3270" => 3270, + "3271" => 3271, + "3272" => 3272, + "3273" => 3273, + "3274" => 3274, + "3275" => 3275, + "3276" => 3276, + "3277" => 3277, + "3278" => 3278, + "3279" => 3279, + "3280" => 3280, + "3281" => 3281, + "3282" => 3282, + "3283" => 3283, + "3284" => 3284, + "3285" => 3285, + "3286" => 3286, + "3287" => 3287, + "3288" => 3288, + "3289" => 3289, + "3290" => 3290, + "3291" => 3291, + "3292" => 3292, + "3293" => 3293, + "3294" => 3294, + "3295" => 3295, + "3296" => 3296, + "3297" => 3297, + "3298" => 3298, + "3299" => 3299, + "3300" => 3300, + "3301" => 3301, + "3302" => 3302, + "3303" => 3303, + "3304" => 3304, + "3305" => 3305, + "3306" => 3306, + "3307" => 3307, + "3308" => 3308, + "3309" => 3309, + "3310" => 3310, + "3311" => 3311, + "3312" => 3312, + "3313" => 3313, + "3314" => 3314, + "3315" => 3315, + "3316" => 3316, + "3317" => 3317, + "3318" => 3318, + "3319" => 3319, + "3320" => 3320, + "3321" => 3321, + "3322" => 3322, + "3323" => 3323, + "3324" => 3324, + "3325" => 3325, + "3326" => 3326, + "3327" => 3327, + "3328" => 3328, + "3329" => 3329, + "3330" => 3330, + "3331" => 3331, + "3332" => 3332, + "3333" => 3333, + "3334" => 3334, + "3335" => 3335, + "3336" => 3336, + "3337" => 3337, + "3338" => 3338, + "3339" => 3339, + "3340" => 3340, + "3341" => 3341, + "3342" => 3342, + "3343" => 3343, + "3344" => 3344, + "3345" => 3345, + "3346" => 3346, + "3347" => 3347, + "3348" => 3348, + "3349" => 3349, + "3350" => 3350, + "3351" => 3351, + "3352" => 3352, + "3353" => 3353, + "3354" => 3354, + "3355" => 3355, + "3356" => 3356, + "3357" => 3357, + "3358" => 3358, + "3359" => 3359, + "3360" => 3360, + "3361" => 3361, + "3362" => 3362, + "3363" => 3363, + "3364" => 3364, + "3365" => 3365, + "3366" => 3366, + "3367" => 3367, + "3368" => 3368, + "3369" => 3369, + "3370" => 3370, + "3371" => 3371, + "3372" => 3372, + "3373" => 3373, + "3374" => 3374, + "3375" => 3375, + "3376" => 3376, + "3377" => 3377, + "3378" => 3378, + "3379" => 3379, + "3380" => 3380, + "3381" => 3381, + "3382" => 3382, + "3383" => 3383, + "3384" => 3384, + "3385" => 3385, + "3386" => 3386, + "3387" => 3387, + "3388" => 3388, + "3389" => 3389, + "3390" => 3390, + "3391" => 3391, + "3392" => 3392, + "3393" => 3393, + "3394" => 3394, + "3395" => 3395, + "3396" => 3396, + "3397" => 3397, + "3398" => 3398, + "3399" => 3399, + "3400" => 3400, + "3401" => 3401, + "3402" => 3402, + "3403" => 3403, + "3404" => 3404, + "3405" => 3405, + "3406" => 3406, + "3407" => 3407, + "3408" => 3408, + "3409" => 3409, + "3410" => 3410, + "3411" => 3411, + "3412" => 3412, + "3413" => 3413, + "3414" => 3414, + "3415" => 3415, + "3416" => 3416, + "3417" => 3417, + "3418" => 3418, + "3419" => 3419, + "3420" => 3420, + "3421" => 3421, + "3422" => 3422, + "3423" => 3423, + "3424" => 3424, + "3425" => 3425, + "3426" => 3426, + "3427" => 3427, + "3428" => 3428, + "3429" => 3429, + "3430" => 3430, + "3431" => 3431, + "3432" => 3432, + "3433" => 3433, + "3434" => 3434, + "3435" => 3435, + "3436" => 3436, + "3437" => 3437, + "3438" => 3438, + "3439" => 3439, + "3440" => 3440, + "3441" => 3441, + "3442" => 3442, + "3443" => 3443, + "3444" => 3444, + "3445" => 3445, + "3446" => 3446, + "3447" => 3447, + "3448" => 3448, + "3449" => 3449, + "3450" => 3450, + "3451" => 3451, + "3452" => 3452, + "3453" => 3453, + "3454" => 3454, + "3455" => 3455, + "3456" => 3456, + "3457" => 3457, + "3458" => 3458, + "3459" => 3459, + "3460" => 3460, + "3461" => 3461, + "3462" => 3462, + "3463" => 3463, + "3464" => 3464, + "3465" => 3465, + "3466" => 3466, + "3467" => 3467, + "3468" => 3468, + "3469" => 3469, + "3470" => 3470, + "3471" => 3471, + "3472" => 3472, + "3473" => 3473, + "3474" => 3474, + "3475" => 3475, + "3476" => 3476, + "3477" => 3477, + "3478" => 3478, + "3479" => 3479, + "3480" => 3480, + "3481" => 3481, + "3482" => 3482, + "3483" => 3483, + "3484" => 3484, + "3485" => 3485, + "3486" => 3486, + "3487" => 3487, + "3488" => 3488, + "3489" => 3489, + "3490" => 3490, + "3491" => 3491, + "3492" => 3492, + "3493" => 3493, + "3494" => 3494, + "3495" => 3495, + "3496" => 3496, + "3497" => 3497, + "3498" => 3498, + "3499" => 3499, + "3500" => 3500, + "3501" => 3501, + "3502" => 3502, + "3503" => 3503, + "3504" => 3504, + "3505" => 3505, + "3506" => 3506, + "3507" => 3507, + "3508" => 3508, + "3509" => 3509, + "3510" => 3510, + "3511" => 3511, + "3512" => 3512, + "3513" => 3513, + "3514" => 3514, + "3515" => 3515, + "3516" => 3516, + "3517" => 3517, + "3518" => 3518, + "3519" => 3519, + "3520" => 3520, + "3521" => 3521, + "3522" => 3522, + "3523" => 3523, + "3524" => 3524, + "3525" => 3525, + "3526" => 3526, + "3527" => 3527, + "3528" => 3528, + "3529" => 3529, + "3530" => 3530, + "3531" => 3531, + "3532" => 3532, + "3533" => 3533, + "3534" => 3534, + "3535" => 3535, + "3536" => 3536, + "3537" => 3537, + "3538" => 3538, + "3539" => 3539, + "3540" => 3540, + "3541" => 3541, + "3542" => 3542, + "3543" => 3543, + "3544" => 3544, + "3545" => 3545, + "3546" => 3546, + "3547" => 3547, + "3548" => 3548, + "3549" => 3549, + "3550" => 3550, + "3551" => 3551, + "3552" => 3552, + "3553" => 3553, + "3554" => 3554, + "3555" => 3555, + "3556" => 3556, + "3557" => 3557, + "3558" => 3558, + "3559" => 3559, + "3560" => 3560, + "3561" => 3561, + "3562" => 3562, + "3563" => 3563, + "3564" => 3564, + "3565" => 3565, + "3566" => 3566, + "3567" => 3567, + "3568" => 3568, + "3569" => 3569, + "3570" => 3570, + "3571" => 3571, + "3572" => 3572, + "3573" => 3573, + "3574" => 3574, + "3575" => 3575, + "3576" => 3576, + "3577" => 3577, + "3578" => 3578, + "3579" => 3579, + "3580" => 3580, + "3581" => 3581, + "3582" => 3582, + "3583" => 3583, + "3584" => 3584, + "3585" => 3585, + "3586" => 3586, + "3587" => 3587, + "3588" => 3588, + "3589" => 3589, + "3590" => 3590, + "3591" => 3591, + "3592" => 3592, + "3593" => 3593, + "3594" => 3594, + "3595" => 3595, + "3596" => 3596, + "3597" => 3597, + "3598" => 3598, + "3599" => 3599, + "3600" => 3600, + "3601" => 3601, + "3602" => 3602, + "3603" => 3603, + "3604" => 3604, + "3605" => 3605, + "3606" => 3606, + "3607" => 3607, + "3608" => 3608, + "3609" => 3609, + "3610" => 3610, + "3611" => 3611, + "3612" => 3612, + "3613" => 3613, + "3614" => 3614, + "3615" => 3615, + "3616" => 3616, + "3617" => 3617, + "3618" => 3618, + "3619" => 3619, + "3620" => 3620, + "3621" => 3621, + "3622" => 3622, + "3623" => 3623, + "3624" => 3624, + "3625" => 3625, + "3626" => 3626, + "3627" => 3627, + "3628" => 3628, + "3629" => 3629, + "3630" => 3630, + "3631" => 3631, + "3632" => 3632, + "3633" => 3633, + "3634" => 3634, + "3635" => 3635, + "3636" => 3636, + "3637" => 3637, + "3638" => 3638, + "3639" => 3639, + "3640" => 3640, + "3641" => 3641, + "3642" => 3642, + "3643" => 3643, + "3644" => 3644, + "3645" => 3645, + "3646" => 3646, + "3647" => 3647, + "3648" => 3648, + "3649" => 3649, + "3650" => 3650, + "3651" => 3651, + "3652" => 3652, + "3653" => 3653, + "3654" => 3654, + "3655" => 3655, + "3656" => 3656, + "3657" => 3657, + "3658" => 3658, + "3659" => 3659, + "3660" => 3660, + "3661" => 3661, + "3662" => 3662, + "3663" => 3663, + "3664" => 3664, + "3665" => 3665, + "3666" => 3666, + "3667" => 3667, + "3668" => 3668, + "3669" => 3669, + "3670" => 3670, + "3671" => 3671, + "3672" => 3672, + "3673" => 3673, + "3674" => 3674, + "3675" => 3675, + "3676" => 3676, + "3677" => 3677, + "3678" => 3678, + "3679" => 3679, + "3680" => 3680, + "3681" => 3681, + "3682" => 3682, + "3683" => 3683, + "3684" => 3684, + "3685" => 3685, + "3686" => 3686, + "3687" => 3687, + "3688" => 3688, + "3689" => 3689, + "3690" => 3690, + "3691" => 3691, + "3692" => 3692, + "3693" => 3693, + "3694" => 3694, + "3695" => 3695, + "3696" => 3696, + "3697" => 3697, + "3698" => 3698, + "3699" => 3699, + "3700" => 3700, + "3701" => 3701, + "3702" => 3702, + "3703" => 3703, + "3704" => 3704, + "3705" => 3705, + "3706" => 3706, + "3707" => 3707, + "3708" => 3708, + "3709" => 3709, + "3710" => 3710, + "3711" => 3711, + "3712" => 3712, + "3713" => 3713, + "3714" => 3714, + "3715" => 3715, + "3716" => 3716, + "3717" => 3717, + "3718" => 3718, + "3719" => 3719, + "3720" => 3720, + "3721" => 3721, + "3722" => 3722, + "3723" => 3723, + "3724" => 3724, + "3725" => 3725, + "3726" => 3726, + "3727" => 3727, + "3728" => 3728, + "3729" => 3729, + "3730" => 3730, + "3731" => 3731, + "3732" => 3732, + "3733" => 3733, + "3734" => 3734, + "3735" => 3735, + "3736" => 3736, + "3737" => 3737, + "3738" => 3738, + "3739" => 3739, + "3740" => 3740, + "3741" => 3741, + "3742" => 3742, + "3743" => 3743, + "3744" => 3744, + "3745" => 3745, + "3746" => 3746, + "3747" => 3747, + "3748" => 3748, + "3749" => 3749, + "3750" => 3750, + "3751" => 3751, + "3752" => 3752, + "3753" => 3753, + "3754" => 3754, + "3755" => 3755, + "3756" => 3756, + "3757" => 3757, + "3758" => 3758, + "3759" => 3759, + "3760" => 3760, + "3761" => 3761, + "3762" => 3762, + "3763" => 3763, + "3764" => 3764, + "3765" => 3765, + "3766" => 3766, + "3767" => 3767, + "3768" => 3768, + "3769" => 3769, + "3770" => 3770, + "3771" => 3771, + "3772" => 3772, + "3773" => 3773, + "3774" => 3774, + "3775" => 3775, + "3776" => 3776, + "3777" => 3777, + "3778" => 3778, + "3779" => 3779, + "3780" => 3780, + "3781" => 3781, + "3782" => 3782, + "3783" => 3783, + "3784" => 3784, + "3785" => 3785, + "3786" => 3786, + "3787" => 3787, + "3788" => 3788, + "3789" => 3789, + "3790" => 3790, + "3791" => 3791, + "3792" => 3792, + "3793" => 3793, + "3794" => 3794, + "3795" => 3795, + "3796" => 3796, + "3797" => 3797, + "3798" => 3798, + "3799" => 3799, + "3800" => 3800, + "3801" => 3801, + "3802" => 3802, + "3803" => 3803, + "3804" => 3804, + "3805" => 3805, + "3806" => 3806, + "3807" => 3807, + "3808" => 3808, + "3809" => 3809, + "3810" => 3810, + "3811" => 3811, + "3812" => 3812, + "3813" => 3813, + "3814" => 3814, + "3815" => 3815, + "3816" => 3816, + "3817" => 3817, + "3818" => 3818, + "3819" => 3819, + "3820" => 3820, + "3821" => 3821, + "3822" => 3822, + "3823" => 3823, + "3824" => 3824, + "3825" => 3825, + "3826" => 3826, + "3827" => 3827, + "3828" => 3828, + "3829" => 3829, + "3830" => 3830, + "3831" => 3831, + "3832" => 3832, + "3833" => 3833, + "3834" => 3834, + "3835" => 3835, + "3836" => 3836, + "3837" => 3837, + "3838" => 3838, + "3839" => 3839, + "3840" => 3840, + "3841" => 3841, + "3842" => 3842, + "3843" => 3843, + "3844" => 3844, + "3845" => 3845, + "3846" => 3846, + "3847" => 3847, + "3848" => 3848, + "3849" => 3849, + "3850" => 3850, + "3851" => 3851, + "3852" => 3852, + "3853" => 3853, + "3854" => 3854, + "3855" => 3855, + "3856" => 3856, + "3857" => 3857, + "3858" => 3858, + "3859" => 3859, + "3860" => 3860, + "3861" => 3861, + "3862" => 3862, + "3863" => 3863, + "3864" => 3864, + "3865" => 3865, + "3866" => 3866, + "3867" => 3867, + "3868" => 3868, + "3869" => 3869, + "3870" => 3870, + "3871" => 3871, + "3872" => 3872, + "3873" => 3873, + "3874" => 3874, + "3875" => 3875, + "3876" => 3876, + "3877" => 3877, + "3878" => 3878, + "3879" => 3879, + "3880" => 3880, + "3881" => 3881, + "3882" => 3882, + "3883" => 3883, + "3884" => 3884, + "3885" => 3885, + "3886" => 3886, + "3887" => 3887, + "3888" => 3888, + "3889" => 3889, + "3890" => 3890, + "3891" => 3891, + "3892" => 3892, + "3893" => 3893, + "3894" => 3894, + "3895" => 3895, + "3896" => 3896, + "3897" => 3897, + "3898" => 3898, + "3899" => 3899, + "3900" => 3900, + "3901" => 3901, + "3902" => 3902, + "3903" => 3903, + "3904" => 3904, + "3905" => 3905, + "3906" => 3906, + "3907" => 3907, + "3908" => 3908, + "3909" => 3909, + "3910" => 3910, + "3911" => 3911, + "3912" => 3912, + "3913" => 3913, + "3914" => 3914, + "3915" => 3915, + "3916" => 3916, + "3917" => 3917, + "3918" => 3918, + "3919" => 3919, + "3920" => 3920, + "3921" => 3921, + "3922" => 3922, + "3923" => 3923, + "3924" => 3924, + "3925" => 3925, + "3926" => 3926, + "3927" => 3927, + "3928" => 3928, + "3929" => 3929, + "3930" => 3930, + "3931" => 3931, + "3932" => 3932, + "3933" => 3933, + "3934" => 3934, + "3935" => 3935, + "3936" => 3936, + "3937" => 3937, + "3938" => 3938, + "3939" => 3939, + "3940" => 3940, + "3941" => 3941, + "3942" => 3942, + "3943" => 3943, + "3944" => 3944, + "3945" => 3945, + "3946" => 3946, + "3947" => 3947, + "3948" => 3948, + "3949" => 3949, + "3950" => 3950, + "3951" => 3951, + "3952" => 3952, + "3953" => 3953, + "3954" => 3954, + "3955" => 3955, + "3956" => 3956, + "3957" => 3957, + "3958" => 3958, + "3959" => 3959, + "3960" => 3960, + "3961" => 3961, + "3962" => 3962, + "3963" => 3963, + "3964" => 3964, + "3965" => 3965, + "3966" => 3966, + "3967" => 3967, + "3968" => 3968, + "3969" => 3969, + "3970" => 3970, + "3971" => 3971, + "3972" => 3972, + "3973" => 3973, + "3974" => 3974, + "3975" => 3975, + "3976" => 3976, + "3977" => 3977, + "3978" => 3978, + "3979" => 3979, + "3980" => 3980, + "3981" => 3981, + "3982" => 3982, + "3983" => 3983, + "3984" => 3984, + "3985" => 3985, + "3986" => 3986, + "3987" => 3987, + "3988" => 3988, + "3989" => 3989, + "3990" => 3990, + "3991" => 3991, + "3992" => 3992, + "3993" => 3993, + "3994" => 3994, + "3995" => 3995, + "3996" => 3996, + "3997" => 3997, + "3998" => 3998, + "3999" => 3999, + "4000" => 4000, + "4001" => 4001, + "4002" => 4002, + "4003" => 4003, + "4004" => 4004, + "4005" => 4005, + "4006" => 4006, + "4007" => 4007, + "4008" => 4008, + "4009" => 4009, + "4010" => 4010, + "4011" => 4011, + "4012" => 4012, + "4013" => 4013, + "4014" => 4014, + "4015" => 4015, + "4016" => 4016, + "4017" => 4017, + "4018" => 4018, + "4019" => 4019, + "4020" => 4020, + "4021" => 4021, + "4022" => 4022, + "4023" => 4023, + "4024" => 4024, + "4025" => 4025, + "4026" => 4026, + "4027" => 4027, + "4028" => 4028, + "4029" => 4029, + "4030" => 4030, + "4031" => 4031, + "4032" => 4032, + "4033" => 4033, + "4034" => 4034, + "4035" => 4035, + "4036" => 4036, + "4037" => 4037, + "4038" => 4038, + "4039" => 4039, + "4040" => 4040, + "4041" => 4041, + "4042" => 4042, + "4043" => 4043, + "4044" => 4044, + "4045" => 4045, + "4046" => 4046, + "4047" => 4047, + "4048" => 4048, + "4049" => 4049, + "4050" => 4050, + "4051" => 4051, + "4052" => 4052, + "4053" => 4053, + "4054" => 4054, + "4055" => 4055, + "4056" => 4056, + "4057" => 4057, + "4058" => 4058, + "4059" => 4059, + "4060" => 4060, + "4061" => 4061, + "4062" => 4062, + "4063" => 4063, + "4064" => 4064, + "4065" => 4065, + "4066" => 4066, + "4067" => 4067, + "4068" => 4068, + "4069" => 4069, + "4070" => 4070, + "4071" => 4071, + "4072" => 4072, + "4073" => 4073, + "4074" => 4074, + "4075" => 4075, + "4076" => 4076, + "4077" => 4077, + "4078" => 4078, + "4079" => 4079, + "4080" => 4080, + "4081" => 4081, + "4082" => 4082, + "4083" => 4083, + "4084" => 4084, + "4085" => 4085, + "4086" => 4086, + "4087" => 4087, + "4088" => 4088, + "4089" => 4089, + "4090" => 4090, + "4091" => 4091, + "4092" => 4092, + "4093" => 4093, + "4094" => 4094, + "4095" => 4095, + "4096" => 4096, + "4097" => 4097, + "4098" => 4098, + "4099" => 4099, + "4100" => 4100, + "4101" => 4101, + "4102" => 4102, + "4103" => 4103, + "4104" => 4104, + "4105" => 4105, + "4106" => 4106, + "4107" => 4107, + "4108" => 4108, + "4109" => 4109, + "4110" => 4110, + "4111" => 4111, + "4112" => 4112, + "4113" => 4113, + "4114" => 4114, + "4115" => 4115, + "4116" => 4116, + "4117" => 4117, + "4118" => 4118, + "4119" => 4119, + "4120" => 4120, + "4121" => 4121, + "4122" => 4122, + "4123" => 4123, + "4124" => 4124, + "4125" => 4125, + "4126" => 4126, + "4127" => 4127, + "4128" => 4128, + "4129" => 4129, + "4130" => 4130, + "4131" => 4131, + "4132" => 4132, + "4133" => 4133, + "4134" => 4134, + "4135" => 4135, + "4136" => 4136, + "4137" => 4137, + "4138" => 4138, + "4139" => 4139, + "4140" => 4140, + "4141" => 4141, + "4142" => 4142, + "4143" => 4143, + "4144" => 4144, + "4145" => 4145, + "4146" => 4146, + "4147" => 4147, + "4148" => 4148, + "4149" => 4149, + "4150" => 4150, + "4151" => 4151, + "4152" => 4152, + "4153" => 4153, + "4154" => 4154, + "4155" => 4155, + "4156" => 4156, + "4157" => 4157, + "4158" => 4158, + "4159" => 4159, + "4160" => 4160, + "4161" => 4161, + "4162" => 4162, + "4163" => 4163, + "4164" => 4164, + "4165" => 4165, + "4166" => 4166, + "4167" => 4167, + "4168" => 4168, + "4169" => 4169, + "4170" => 4170, + "4171" => 4171, + "4172" => 4172, + "4173" => 4173, + "4174" => 4174, + "4175" => 4175, + "4176" => 4176, + "4177" => 4177, + "4178" => 4178, + "4179" => 4179, + "4180" => 4180, + "4181" => 4181, + "4182" => 4182, + "4183" => 4183, + "4184" => 4184, + "4185" => 4185, + "4186" => 4186, + "4187" => 4187, + "4188" => 4188, + "4189" => 4189, + "4190" => 4190, + "4191" => 4191, + "4192" => 4192, + "4193" => 4193, + "4194" => 4194, + "4195" => 4195, + "4196" => 4196, + "4197" => 4197, + "4198" => 4198, + "4199" => 4199, + "4200" => 4200, + "4201" => 4201, + "4202" => 4202, + "4203" => 4203, + "4204" => 4204, + "4205" => 4205, + "4206" => 4206, + "4207" => 4207, + "4208" => 4208, + "4209" => 4209, + "4210" => 4210, + "4211" => 4211, + "4212" => 4212, + "4213" => 4213, + "4214" => 4214, + "4215" => 4215, + "4216" => 4216, + "4217" => 4217, + "4218" => 4218, + "4219" => 4219, + "4220" => 4220, + "4221" => 4221, + "4222" => 4222, + "4223" => 4223, + "4224" => 4224, + "4225" => 4225, + "4226" => 4226, + "4227" => 4227, + "4228" => 4228, + "4229" => 4229, + "4230" => 4230, + "4231" => 4231, + "4232" => 4232, + "4233" => 4233, + "4234" => 4234, + "4235" => 4235, + "4236" => 4236, + "4237" => 4237, + "4238" => 4238, + "4239" => 4239, + "4240" => 4240, + "4241" => 4241, + "4242" => 4242, + "4243" => 4243, + "4244" => 4244, + "4245" => 4245, + "4246" => 4246, + "4247" => 4247, + "4248" => 4248, + "4249" => 4249, + "4250" => 4250, + "4251" => 4251, + "4252" => 4252, + "4253" => 4253, + "4254" => 4254, + "4255" => 4255, + "4256" => 4256, + "4257" => 4257, + "4258" => 4258, + "4259" => 4259, + "4260" => 4260, + "4261" => 4261, + "4262" => 4262, + "4263" => 4263, + "4264" => 4264, + "4265" => 4265, + "4266" => 4266, + "4267" => 4267, + "4268" => 4268, + "4269" => 4269, + "4270" => 4270, + "4271" => 4271, + "4272" => 4272, + "4273" => 4273, + "4274" => 4274, + "4275" => 4275, + "4276" => 4276, + "4277" => 4277, + "4278" => 4278, + "4279" => 4279, + "4280" => 4280, + "4281" => 4281, + "4282" => 4282, + "4283" => 4283, + "4284" => 4284, + "4285" => 4285, + "4286" => 4286, + "4287" => 4287, + "4288" => 4288, + "4289" => 4289, + "4290" => 4290, + "4291" => 4291, + "4292" => 4292, + "4293" => 4293, + "4294" => 4294, + "4295" => 4295, + "4296" => 4296, + "4297" => 4297, + "4298" => 4298, + "4299" => 4299, + "4300" => 4300, + "4301" => 4301, + "4302" => 4302, + "4303" => 4303, + "4304" => 4304, + "4305" => 4305, + "4306" => 4306, + "4307" => 4307, + "4308" => 4308, + "4309" => 4309, + "4310" => 4310, + "4311" => 4311, + "4312" => 4312, + "4313" => 4313, + "4314" => 4314, + "4315" => 4315, + "4316" => 4316, + "4317" => 4317, + "4318" => 4318, + "4319" => 4319, + "4320" => 4320, + "4321" => 4321, + "4322" => 4322, + "4323" => 4323, + "4324" => 4324, + "4325" => 4325, + "4326" => 4326, + "4327" => 4327, + "4328" => 4328, + "4329" => 4329, + "4330" => 4330, + "4331" => 4331, + "4332" => 4332, + "4333" => 4333, + "4334" => 4334, + "4335" => 4335, + "4336" => 4336, + "4337" => 4337, + "4338" => 4338, + "4339" => 4339, + "4340" => 4340, + "4341" => 4341, + "4342" => 4342, + "4343" => 4343, + "4344" => 4344, + "4345" => 4345, + "4346" => 4346, + "4347" => 4347, + "4348" => 4348, + "4349" => 4349, + "4350" => 4350, + "4351" => 4351, + "4352" => 4352, + "4353" => 4353, + "4354" => 4354, + "4355" => 4355, + "4356" => 4356, + "4357" => 4357, + "4358" => 4358, + "4359" => 4359, + "4360" => 4360, + "4361" => 4361, + "4362" => 4362, + "4363" => 4363, + "4364" => 4364, + "4365" => 4365, + "4366" => 4366, + "4367" => 4367, + "4368" => 4368, + "4369" => 4369, + "4370" => 4370, + "4371" => 4371, + "4372" => 4372, + "4373" => 4373, + "4374" => 4374, + "4375" => 4375, + "4376" => 4376, + "4377" => 4377, + "4378" => 4378, + "4379" => 4379, + "4380" => 4380, + "4381" => 4381, + "4382" => 4382, + "4383" => 4383, + "4384" => 4384, + "4385" => 4385, + "4386" => 4386, + "4387" => 4387, + "4388" => 4388, + "4389" => 4389, + "4390" => 4390, + "4391" => 4391, + "4392" => 4392, + "4393" => 4393, + "4394" => 4394, + "4395" => 4395, + "4396" => 4396, + "4397" => 4397, + "4398" => 4398, + "4399" => 4399, + "4400" => 4400, + "4401" => 4401, + "4402" => 4402, + "4403" => 4403, + "4404" => 4404, + "4405" => 4405, + "4406" => 4406, + "4407" => 4407, + "4408" => 4408, + "4409" => 4409, + "4410" => 4410, + "4411" => 4411, + "4412" => 4412, + "4413" => 4413, + "4414" => 4414, + "4415" => 4415, + "4416" => 4416, + "4417" => 4417, + "4418" => 4418, + "4419" => 4419, + "4420" => 4420, + "4421" => 4421, + "4422" => 4422, + "4423" => 4423, + "4424" => 4424, + "4425" => 4425, + "4426" => 4426, + "4427" => 4427, + "4428" => 4428, + "4429" => 4429, + "4430" => 4430, + "4431" => 4431, + "4432" => 4432, + "4433" => 4433, + "4434" => 4434, + "4435" => 4435, + "4436" => 4436, + "4437" => 4437, + "4438" => 4438, + "4439" => 4439, + "4440" => 4440, + "4441" => 4441, + "4442" => 4442, + "4443" => 4443, + "4444" => 4444, + "4445" => 4445, + "4446" => 4446, + "4447" => 4447, + "4448" => 4448, + "4449" => 4449, + "4450" => 4450, + "4451" => 4451, + "4452" => 4452, + "4453" => 4453, + "4454" => 4454, + "4455" => 4455, + "4456" => 4456, + "4457" => 4457, + "4458" => 4458, + "4459" => 4459, + "4460" => 4460, + "4461" => 4461, + "4462" => 4462, + "4463" => 4463, + "4464" => 4464, + "4465" => 4465, + "4466" => 4466, + "4467" => 4467, + "4468" => 4468, + "4469" => 4469, + "4470" => 4470, + "4471" => 4471, + "4472" => 4472, + "4473" => 4473, + "4474" => 4474, + "4475" => 4475, + "4476" => 4476, + "4477" => 4477, + "4478" => 4478, + "4479" => 4479, + "4480" => 4480, + "4481" => 4481, + "4482" => 4482, + "4483" => 4483, + "4484" => 4484, + "4485" => 4485, + "4486" => 4486, + "4487" => 4487, + "4488" => 4488, + "4489" => 4489, + "4490" => 4490, + "4491" => 4491, + "4492" => 4492, + "4493" => 4493, + "4494" => 4494, + "4495" => 4495, + "4496" => 4496, + "4497" => 4497, + "4498" => 4498, + "4499" => 4499, + "4500" => 4500, + "4501" => 4501, + "4502" => 4502, + "4503" => 4503, + "4504" => 4504, + "4505" => 4505, + "4506" => 4506, + "4507" => 4507, + "4508" => 4508, + "4509" => 4509, + "4510" => 4510, + "4511" => 4511, + "4512" => 4512, + "4513" => 4513, + "4514" => 4514, + "4515" => 4515, + "4516" => 4516, + "4517" => 4517, + "4518" => 4518, + "4519" => 4519, + "4520" => 4520, + "4521" => 4521, + "4522" => 4522, + "4523" => 4523, + "4524" => 4524, + "4525" => 4525, + "4526" => 4526, + "4527" => 4527, + "4528" => 4528, + "4529" => 4529, + "4530" => 4530, + "4531" => 4531, + "4532" => 4532, + "4533" => 4533, + "4534" => 4534, + "4535" => 4535, + "4536" => 4536, + "4537" => 4537, + "4538" => 4538, + "4539" => 4539, + "4540" => 4540, + "4541" => 4541, + "4542" => 4542, + "4543" => 4543, + "4544" => 4544, + "4545" => 4545, + "4546" => 4546, + "4547" => 4547, + "4548" => 4548, + "4549" => 4549, + "4550" => 4550, + "4551" => 4551, + "4552" => 4552, + "4553" => 4553, + "4554" => 4554, + "4555" => 4555, + "4556" => 4556, + "4557" => 4557, + "4558" => 4558, + "4559" => 4559, + "4560" => 4560, + "4561" => 4561, + "4562" => 4562, + "4563" => 4563, + "4564" => 4564, + "4565" => 4565, + "4566" => 4566, + "4567" => 4567, + "4568" => 4568, + "4569" => 4569, + "4570" => 4570, + "4571" => 4571, + "4572" => 4572, + "4573" => 4573, + "4574" => 4574, + "4575" => 4575, + "4576" => 4576, + "4577" => 4577, + "4578" => 4578, + "4579" => 4579, + "4580" => 4580, + "4581" => 4581, + "4582" => 4582, + "4583" => 4583, + "4584" => 4584, + "4585" => 4585, + "4586" => 4586, + "4587" => 4587, + "4588" => 4588, + "4589" => 4589, + "4590" => 4590, + "4591" => 4591, + "4592" => 4592, + "4593" => 4593, + "4594" => 4594, + "4595" => 4595, + "4596" => 4596, + "4597" => 4597, + "4598" => 4598, + "4599" => 4599, + "4600" => 4600, + "4601" => 4601, + "4602" => 4602, + "4603" => 4603, + "4604" => 4604, + "4605" => 4605, + "4606" => 4606, + "4607" => 4607, + "4608" => 4608, + "4609" => 4609, + "4610" => 4610, + "4611" => 4611, + "4612" => 4612, + "4613" => 4613, + "4614" => 4614, + "4615" => 4615, + "4616" => 4616, + "4617" => 4617, + "4618" => 4618, + "4619" => 4619, + "4620" => 4620, + "4621" => 4621, + "4622" => 4622, + "4623" => 4623, + "4624" => 4624, + "4625" => 4625, + "4626" => 4626, + "4627" => 4627, + "4628" => 4628, + "4629" => 4629, + "4630" => 4630, + "4631" => 4631, + "4632" => 4632, + "4633" => 4633, + "4634" => 4634, + "4635" => 4635, + "4636" => 4636, + "4637" => 4637, + "4638" => 4638, + "4639" => 4639, + "4640" => 4640, + "4641" => 4641, + "4642" => 4642, + "4643" => 4643, + "4644" => 4644, + "4645" => 4645, + "4646" => 4646, + "4647" => 4647, + "4648" => 4648, + "4649" => 4649, + "4650" => 4650, + "4651" => 4651, + "4652" => 4652, + "4653" => 4653, + "4654" => 4654, + "4655" => 4655, + "4656" => 4656, + "4657" => 4657, + "4658" => 4658, + "4659" => 4659, + "4660" => 4660, + "4661" => 4661, + "4662" => 4662, + "4663" => 4663, + "4664" => 4664, + "4665" => 4665, + "4666" => 4666, + "4667" => 4667, + "4668" => 4668, + "4669" => 4669, + "4670" => 4670, + "4671" => 4671, + "4672" => 4672, + "4673" => 4673, + "4674" => 4674, + "4675" => 4675, + "4676" => 4676, + "4677" => 4677, + "4678" => 4678, + "4679" => 4679, + "4680" => 4680, + "4681" => 4681, + "4682" => 4682, + "4683" => 4683, + "4684" => 4684, + "4685" => 4685, + "4686" => 4686, + "4687" => 4687, + "4688" => 4688, + "4689" => 4689, + "4690" => 4690, + "4691" => 4691, + "4692" => 4692, + "4693" => 4693, + "4694" => 4694, + "4695" => 4695, + "4696" => 4696, + "4697" => 4697, + "4698" => 4698, + "4699" => 4699, + "4700" => 4700, + "4701" => 4701, + "4702" => 4702, + "4703" => 4703, + "4704" => 4704, + "4705" => 4705, + "4706" => 4706, + "4707" => 4707, + "4708" => 4708, + "4709" => 4709, + "4710" => 4710, + "4711" => 4711, + "4712" => 4712, + "4713" => 4713, + "4714" => 4714, + "4715" => 4715, + "4716" => 4716, + "4717" => 4717, + "4718" => 4718, + "4719" => 4719, + "4720" => 4720, + "4721" => 4721, + "4722" => 4722, + "4723" => 4723, + "4724" => 4724, + "4725" => 4725, + "4726" => 4726, + "4727" => 4727, + "4728" => 4728, + "4729" => 4729, + "4730" => 4730, + "4731" => 4731, + "4732" => 4732, + "4733" => 4733, + "4734" => 4734, + "4735" => 4735, + "4736" => 4736, + "4737" => 4737, + "4738" => 4738, + "4739" => 4739, + "4740" => 4740, + "4741" => 4741, + "4742" => 4742, + "4743" => 4743, + "4744" => 4744, + "4745" => 4745, + "4746" => 4746, + "4747" => 4747, + "4748" => 4748, + "4749" => 4749, + "4750" => 4750, + "4751" => 4751, + "4752" => 4752, + "4753" => 4753, + "4754" => 4754, + "4755" => 4755, + "4756" => 4756, + "4757" => 4757, + "4758" => 4758, + "4759" => 4759, + "4760" => 4760, + "4761" => 4761, + "4762" => 4762, + "4763" => 4763, + "4764" => 4764, + "4765" => 4765, + "4766" => 4766, + "4767" => 4767, + "4768" => 4768, + "4769" => 4769, + "4770" => 4770, + "4771" => 4771, + "4772" => 4772, + "4773" => 4773, + "4774" => 4774, + "4775" => 4775, + "4776" => 4776, + "4777" => 4777, + "4778" => 4778, + "4779" => 4779, + "4780" => 4780, + "4781" => 4781, + "4782" => 4782, + "4783" => 4783, + "4784" => 4784, + "4785" => 4785, + "4786" => 4786, + "4787" => 4787, + "4788" => 4788, + "4789" => 4789, + "4790" => 4790, + "4791" => 4791, + "4792" => 4792, + "4793" => 4793, + "4794" => 4794, + "4795" => 4795, + "4796" => 4796, + "4797" => 4797, + "4798" => 4798, + "4799" => 4799, + "4800" => 4800, + "4801" => 4801, + "4802" => 4802, + "4803" => 4803, + "4804" => 4804, + "4805" => 4805, + "4806" => 4806, + "4807" => 4807, + "4808" => 4808, + "4809" => 4809, + "4810" => 4810, + "4811" => 4811, + "4812" => 4812, + "4813" => 4813, + "4814" => 4814, + "4815" => 4815, + "4816" => 4816, + "4817" => 4817, + "4818" => 4818, + "4819" => 4819, + "4820" => 4820, + "4821" => 4821, + "4822" => 4822, + "4823" => 4823, + "4824" => 4824, + "4825" => 4825, + "4826" => 4826, + "4827" => 4827, + "4828" => 4828, + "4829" => 4829, + "4830" => 4830, + "4831" => 4831, + "4832" => 4832, + "4833" => 4833, + "4834" => 4834, + "4835" => 4835, + "4836" => 4836, + "4837" => 4837, + "4838" => 4838, + "4839" => 4839, + "4840" => 4840, + "4841" => 4841, + "4842" => 4842, + "4843" => 4843, + "4844" => 4844, + "4845" => 4845, + "4846" => 4846, + "4847" => 4847, + "4848" => 4848, + "4849" => 4849, + "4850" => 4850, + "4851" => 4851, + "4852" => 4852, + "4853" => 4853, + "4854" => 4854, + "4855" => 4855, + "4856" => 4856, + "4857" => 4857, + "4858" => 4858, + "4859" => 4859, + "4860" => 4860, + "4861" => 4861, + "4862" => 4862, + "4863" => 4863, + "4864" => 4864, + "4865" => 4865, + "4866" => 4866, + "4867" => 4867, + "4868" => 4868, + "4869" => 4869, + "4870" => 4870, + "4871" => 4871, + "4872" => 4872, + "4873" => 4873, + "4874" => 4874, + "4875" => 4875, + "4876" => 4876, + "4877" => 4877, + "4878" => 4878, + "4879" => 4879, + "4880" => 4880, + "4881" => 4881, + "4882" => 4882, + "4883" => 4883, + "4884" => 4884, + "4885" => 4885, + "4886" => 4886, + "4887" => 4887, + "4888" => 4888, + "4889" => 4889, + "4890" => 4890, + "4891" => 4891, + "4892" => 4892, + "4893" => 4893, + "4894" => 4894, + "4895" => 4895, + "4896" => 4896, + "4897" => 4897, + "4898" => 4898, + "4899" => 4899, + "4900" => 4900, + "4901" => 4901, + "4902" => 4902, + "4903" => 4903, + "4904" => 4904, + "4905" => 4905, + "4906" => 4906, + "4907" => 4907, + "4908" => 4908, + "4909" => 4909, + "4910" => 4910, + "4911" => 4911, + "4912" => 4912, + "4913" => 4913, + "4914" => 4914, + "4915" => 4915, + "4916" => 4916, + "4917" => 4917, + "4918" => 4918, + "4919" => 4919, + "4920" => 4920, + "4921" => 4921, + "4922" => 4922, + "4923" => 4923, + "4924" => 4924, + "4925" => 4925, + "4926" => 4926, + "4927" => 4927, + "4928" => 4928, + "4929" => 4929, + "4930" => 4930, + "4931" => 4931, + "4932" => 4932, + "4933" => 4933, + "4934" => 4934, + "4935" => 4935, + "4936" => 4936, + "4937" => 4937, + "4938" => 4938, + "4939" => 4939, + "4940" => 4940, + "4941" => 4941, + "4942" => 4942, + "4943" => 4943, + "4944" => 4944, + "4945" => 4945, + "4946" => 4946, + "4947" => 4947, + "4948" => 4948, + "4949" => 4949, + "4950" => 4950, + "4951" => 4951, + "4952" => 4952, + "4953" => 4953, + "4954" => 4954, + "4955" => 4955, + "4956" => 4956, + "4957" => 4957, + "4958" => 4958, + "4959" => 4959, + "4960" => 4960, + "4961" => 4961, + "4962" => 4962, + "4963" => 4963, + "4964" => 4964, + "4965" => 4965, + "4966" => 4966, + "4967" => 4967, + "4968" => 4968, + "4969" => 4969, + "4970" => 4970, + "4971" => 4971, + "4972" => 4972, + "4973" => 4973, + "4974" => 4974, + "4975" => 4975, + "4976" => 4976, + "4977" => 4977, + "4978" => 4978, + "4979" => 4979, + "4980" => 4980, + "4981" => 4981, + "4982" => 4982, + "4983" => 4983, + "4984" => 4984, + "4985" => 4985, + "4986" => 4986, + "4987" => 4987, + "4988" => 4988, + "4989" => 4989, + "4990" => 4990, + "4991" => 4991, + "4992" => 4992, + "4993" => 4993, + "4994" => 4994, + "4995" => 4995, + "4996" => 4996, + "4997" => 4997, + "4998" => 4998, + "4999" => 4999, + "5000" => 5000, + "5001" => 5001, + "5002" => 5002, + "5003" => 5003, + "5004" => 5004, + "5005" => 5005, + "5006" => 5006, + "5007" => 5007, + "5008" => 5008, + "5009" => 5009, + "5010" => 5010, + "5011" => 5011, + "5012" => 5012, + "5013" => 5013, + "5014" => 5014, + "5015" => 5015, + "5016" => 5016, + "5017" => 5017, + "5018" => 5018, + "5019" => 5019, + "5020" => 5020, + "5021" => 5021, + "5022" => 5022, + "5023" => 5023, + "5024" => 5024, + "5025" => 5025, + "5026" => 5026, + "5027" => 5027, + "5028" => 5028, + "5029" => 5029, + "5030" => 5030, + "5031" => 5031, + "5032" => 5032, + "5033" => 5033, + "5034" => 5034, + "5035" => 5035, + "5036" => 5036, + "5037" => 5037, + "5038" => 5038, + "5039" => 5039, + "5040" => 5040, + "5041" => 5041, + "5042" => 5042, + "5043" => 5043, + "5044" => 5044, + "5045" => 5045, + "5046" => 5046, + "5047" => 5047, + "5048" => 5048, + "5049" => 5049, + "5050" => 5050, + "5051" => 5051, + "5052" => 5052, + "5053" => 5053, + "5054" => 5054, + "5055" => 5055, + "5056" => 5056, + "5057" => 5057, + "5058" => 5058, + "5059" => 5059, + "5060" => 5060, + "5061" => 5061, + "5062" => 5062, + "5063" => 5063, + "5064" => 5064, + "5065" => 5065, + "5066" => 5066, + "5067" => 5067, + "5068" => 5068, + "5069" => 5069, + "5070" => 5070, + "5071" => 5071, + "5072" => 5072, + "5073" => 5073, + "5074" => 5074, + "5075" => 5075, + "5076" => 5076, + "5077" => 5077, + "5078" => 5078, + "5079" => 5079, + "5080" => 5080, + "5081" => 5081, + "5082" => 5082, + "5083" => 5083, + "5084" => 5084, + "5085" => 5085, + "5086" => 5086, + "5087" => 5087, + "5088" => 5088, + "5089" => 5089, + "5090" => 5090, + "5091" => 5091, + "5092" => 5092, + "5093" => 5093, + "5094" => 5094, + "5095" => 5095, + "5096" => 5096, + "5097" => 5097, + "5098" => 5098, + "5099" => 5099, + "5100" => 5100, + "5101" => 5101, + "5102" => 5102, + "5103" => 5103, + "5104" => 5104, + "5105" => 5105, + "5106" => 5106, + "5107" => 5107, + "5108" => 5108, + "5109" => 5109, + "5110" => 5110, + "5111" => 5111, + "5112" => 5112, + "5113" => 5113, + "5114" => 5114, + "5115" => 5115, + "5116" => 5116, + "5117" => 5117, + "5118" => 5118, + "5119" => 5119, + "5120" => 5120, + "5121" => 5121, + "5122" => 5122, + "5123" => 5123, + "5124" => 5124, + "5125" => 5125, + "5126" => 5126, + "5127" => 5127, + "5128" => 5128, + "5129" => 5129, + "5130" => 5130, + "5131" => 5131, + "5132" => 5132, + "5133" => 5133, + "5134" => 5134, + "5135" => 5135, + "5136" => 5136, + "5137" => 5137, + "5138" => 5138, + "5139" => 5139, + "5140" => 5140, + "5141" => 5141, + "5142" => 5142, + "5143" => 5143, + "5144" => 5144, + "5145" => 5145, + "5146" => 5146, + "5147" => 5147, + "5148" => 5148, + "5149" => 5149, + "5150" => 5150, + "5151" => 5151, + "5152" => 5152, + "5153" => 5153, + "5154" => 5154, + "5155" => 5155, + "5156" => 5156, + "5157" => 5157, + "5158" => 5158, + "5159" => 5159, + "5160" => 5160, + "5161" => 5161, + "5162" => 5162, + "5163" => 5163, + "5164" => 5164, + "5165" => 5165, + "5166" => 5166, + "5167" => 5167, + "5168" => 5168, + "5169" => 5169, + "5170" => 5170, + "5171" => 5171, + "5172" => 5172, + "5173" => 5173, + "5174" => 5174, + "5175" => 5175, + "5176" => 5176, + "5177" => 5177, + "5178" => 5178, + "5179" => 5179, + "5180" => 5180, + "5181" => 5181, + "5182" => 5182, + "5183" => 5183, + "5184" => 5184, + "5185" => 5185, + "5186" => 5186, + "5187" => 5187, + "5188" => 5188, + "5189" => 5189, + "5190" => 5190, + "5191" => 5191, + "5192" => 5192, + "5193" => 5193, + "5194" => 5194, + "5195" => 5195, + "5196" => 5196, + "5197" => 5197, + "5198" => 5198, + _ => 5199, + } +} diff --git a/tests/ui/issues/issue-73112.rs b/tests/ui/issues/issue-73112.rs new file mode 100644 index 000000000..cc7be9c95 --- /dev/null +++ b/tests/ui/issues/issue-73112.rs @@ -0,0 +1,13 @@ +// aux-build:issue-73112.rs + +extern crate issue_73112; + +fn main() { + use issue_73112::PageTable; + + #[repr(C, packed)] + struct SomeStruct { + //~^ ERROR packed type cannot transitively contain a `#[repr(align)]` type [E0588] + page_table: PageTable, + } +} diff --git a/tests/ui/issues/issue-73112.stderr b/tests/ui/issues/issue-73112.stderr new file mode 100644 index 000000000..4b8b97966 --- /dev/null +++ b/tests/ui/issues/issue-73112.stderr @@ -0,0 +1,15 @@ +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/issue-73112.rs:9:5 + | +LL | struct SomeStruct { + | ^^^^^^^^^^^^^^^^^ + | +note: `PageTable` has a `#[repr(align)]` attribute + --> $DIR/auxiliary/issue-73112.rs:8:1 + | +LL | pub struct PageTable { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0588`. diff --git a/tests/ui/issues/issue-73229.rs b/tests/ui/issues/issue-73229.rs new file mode 100644 index 000000000..35346199a --- /dev/null +++ b/tests/ui/issues/issue-73229.rs @@ -0,0 +1,33 @@ +// check-pass + +fn any() -> T { + loop {} +} + +trait Foo { + type V; +} + +trait Callback: Fn(&T, &T::V) {} +impl Callback for F {} + +struct Bar { + callback: Box>, +} + +impl Bar { + fn event(&self) { + (self.callback)(any(), any()); + } +} + +struct A; +struct B; +impl Foo for A { + type V = B; +} + +fn main() { + let foo = Bar:: { callback: Box::new(|_: &A, _: &B| ()) }; + foo.event(); +} diff --git a/tests/ui/issues/issue-7344.rs b/tests/ui/issues/issue-7344.rs new file mode 100644 index 000000000..f1727d0c1 --- /dev/null +++ b/tests/ui/issues/issue-7344.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_must_use)] +// pretty-expanded FIXME #23616 + +#![allow(unreachable_code)] + +fn foo() -> bool { false } + +fn bar() { + return; + !foo(); +} + +fn baz() { + return; + if "" == "" {} +} + +pub fn main() { + bar(); + baz(); +} diff --git a/tests/ui/issues/issue-7364.rs b/tests/ui/issues/issue-7364.rs new file mode 100644 index 000000000..79642bd41 --- /dev/null +++ b/tests/ui/issues/issue-7364.rs @@ -0,0 +1,7 @@ +use std::cell::RefCell; + +// Regression test for issue 7364 +static boxed: Box> = Box::new(RefCell::new(0)); +//~^ ERROR `RefCell` cannot be shared between threads safely [E0277] + +fn main() { } diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr new file mode 100644 index 000000000..5dc8c2b60 --- /dev/null +++ b/tests/ui/issues/issue-7364.stderr @@ -0,0 +1,14 @@ +error[E0277]: `RefCell` cannot be shared between threads safely + --> $DIR/issue-7364.rs:4:15 + | +LL | static boxed: Box> = Box::new(RefCell::new(0)); + | ^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `RefCell` + = note: required for `Unique>` to implement `Sync` + = note: required because it appears within the type `Box>` + = note: shared static variables must have a type that implements `Sync` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-74082.rs b/tests/ui/issues/issue-74082.rs new file mode 100644 index 000000000..e3e400c79 --- /dev/null +++ b/tests/ui/issues/issue-74082.rs @@ -0,0 +1,9 @@ +#![allow(dead_code)] + +#[repr(i128)] //~ ERROR: attribute should be applied to an enum +struct Foo; + +#[repr(u128)] //~ ERROR: attribute should be applied to an enum +struct Bar; + +fn main() {} diff --git a/tests/ui/issues/issue-74082.stderr b/tests/ui/issues/issue-74082.stderr new file mode 100644 index 000000000..12f5a3b27 --- /dev/null +++ b/tests/ui/issues/issue-74082.stderr @@ -0,0 +1,19 @@ +error[E0517]: attribute should be applied to an enum + --> $DIR/issue-74082.rs:3:8 + | +LL | #[repr(i128)] + | ^^^^ +LL | struct Foo; + | ----------- not an enum + +error[E0517]: attribute should be applied to an enum + --> $DIR/issue-74082.rs:6:8 + | +LL | #[repr(u128)] + | ^^^^ +LL | struct Bar; + | ----------- not an enum + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/issues/issue-74236/auxiliary/dep.rs b/tests/ui/issues/issue-74236/auxiliary/dep.rs new file mode 100644 index 000000000..45f2601d3 --- /dev/null +++ b/tests/ui/issues/issue-74236/auxiliary/dep.rs @@ -0,0 +1,8 @@ +// edition:2018 + +mod private { pub struct Pub; } + +// Reexport built-in attribute without a DefId (requires Rust 2018). +pub use cfg_attr as attr; +// This export needs to be after the built-in attribute to trigger the bug. +pub use private::Pub as Renamed; diff --git a/tests/ui/issues/issue-74236/main.rs b/tests/ui/issues/issue-74236/main.rs new file mode 100644 index 000000000..daa7cfcf9 --- /dev/null +++ b/tests/ui/issues/issue-74236/main.rs @@ -0,0 +1,9 @@ +// edition:2018 +// aux-build:dep.rs +// compile-flags:--extern dep + +fn main() { + // Trigger an error that will print the path of dep::private::Pub (as "dep::Renamed"). + let () = dep::Renamed; + //~^ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-74236/main.stderr b/tests/ui/issues/issue-74236/main.stderr new file mode 100644 index 000000000..55e94ae72 --- /dev/null +++ b/tests/ui/issues/issue-74236/main.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/main.rs:7:9 + | +LL | let () = dep::Renamed; + | ^^ ------------ this expression has type `Renamed` + | | + | expected struct `Renamed`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs b/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs new file mode 100644 index 000000000..36e993260 --- /dev/null +++ b/tests/ui/issues/issue-74564-if-expr-stack-overflow.rs @@ -0,0 +1,10419 @@ +// build-pass +// ignore-tidy-filelength +#![crate_type = "rlib"] + +fn banana(v: &str) -> u32 { + if v == "1" { + 1 + } else if v == "2" { + 2 + } else if v == "3" { + 3 + } else if v == "4" { + 4 + } else if v == "5" { + 5 + } else if v == "6" { + 6 + } else if v == "7" { + 7 + } else if v == "8" { + 8 + } else if v == "9" { + 9 + } else if v == "10" { + 10 + } else if v == "11" { + 11 + } else if v == "12" { + 12 + } else if v == "13" { + 13 + } else if v == "14" { + 14 + } else if v == "15" { + 15 + } else if v == "16" { + 16 + } else if v == "17" { + 17 + } else if v == "18" { + 18 + } else if v == "19" { + 19 + } else if v == "20" { + 20 + } else if v == "21" { + 21 + } else if v == "22" { + 22 + } else if v == "23" { + 23 + } else if v == "24" { + 24 + } else if v == "25" { + 25 + } else if v == "26" { + 26 + } else if v == "27" { + 27 + } else if v == "28" { + 28 + } else if v == "29" { + 29 + } else if v == "30" { + 30 + } else if v == "31" { + 31 + } else if v == "32" { + 32 + } else if v == "33" { + 33 + } else if v == "34" { + 34 + } else if v == "35" { + 35 + } else if v == "36" { + 36 + } else if v == "37" { + 37 + } else if v == "38" { + 38 + } else if v == "39" { + 39 + } else if v == "40" { + 40 + } else if v == "41" { + 41 + } else if v == "42" { + 42 + } else if v == "43" { + 43 + } else if v == "44" { + 44 + } else if v == "45" { + 45 + } else if v == "46" { + 46 + } else if v == "47" { + 47 + } else if v == "48" { + 48 + } else if v == "49" { + 49 + } else if v == "50" { + 50 + } else if v == "51" { + 51 + } else if v == "52" { + 52 + } else if v == "53" { + 53 + } else if v == "54" { + 54 + } else if v == "55" { + 55 + } else if v == "56" { + 56 + } else if v == "57" { + 57 + } else if v == "58" { + 58 + } else if v == "59" { + 59 + } else if v == "60" { + 60 + } else if v == "61" { + 61 + } else if v == "62" { + 62 + } else if v == "63" { + 63 + } else if v == "64" { + 64 + } else if v == "65" { + 65 + } else if v == "66" { + 66 + } else if v == "67" { + 67 + } else if v == "68" { + 68 + } else if v == "69" { + 69 + } else if v == "70" { + 70 + } else if v == "71" { + 71 + } else if v == "72" { + 72 + } else if v == "73" { + 73 + } else if v == "74" { + 74 + } else if v == "75" { + 75 + } else if v == "76" { + 76 + } else if v == "77" { + 77 + } else if v == "78" { + 78 + } else if v == "79" { + 79 + } else if v == "80" { + 80 + } else if v == "81" { + 81 + } else if v == "82" { + 82 + } else if v == "83" { + 83 + } else if v == "84" { + 84 + } else if v == "85" { + 85 + } else if v == "86" { + 86 + } else if v == "87" { + 87 + } else if v == "88" { + 88 + } else if v == "89" { + 89 + } else if v == "90" { + 90 + } else if v == "91" { + 91 + } else if v == "92" { + 92 + } else if v == "93" { + 93 + } else if v == "94" { + 94 + } else if v == "95" { + 95 + } else if v == "96" { + 96 + } else if v == "97" { + 97 + } else if v == "98" { + 98 + } else if v == "99" { + 99 + } else if v == "100" { + 100 + } else if v == "101" { + 101 + } else if v == "102" { + 102 + } else if v == "103" { + 103 + } else if v == "104" { + 104 + } else if v == "105" { + 105 + } else if v == "106" { + 106 + } else if v == "107" { + 107 + } else if v == "108" { + 108 + } else if v == "109" { + 109 + } else if v == "110" { + 110 + } else if v == "111" { + 111 + } else if v == "112" { + 112 + } else if v == "113" { + 113 + } else if v == "114" { + 114 + } else if v == "115" { + 115 + } else if v == "116" { + 116 + } else if v == "117" { + 117 + } else if v == "118" { + 118 + } else if v == "119" { + 119 + } else if v == "120" { + 120 + } else if v == "121" { + 121 + } else if v == "122" { + 122 + } else if v == "123" { + 123 + } else if v == "124" { + 124 + } else if v == "125" { + 125 + } else if v == "126" { + 126 + } else if v == "127" { + 127 + } else if v == "128" { + 128 + } else if v == "129" { + 129 + } else if v == "130" { + 130 + } else if v == "131" { + 131 + } else if v == "132" { + 132 + } else if v == "133" { + 133 + } else if v == "134" { + 134 + } else if v == "135" { + 135 + } else if v == "136" { + 136 + } else if v == "137" { + 137 + } else if v == "138" { + 138 + } else if v == "139" { + 139 + } else if v == "140" { + 140 + } else if v == "141" { + 141 + } else if v == "142" { + 142 + } else if v == "143" { + 143 + } else if v == "144" { + 144 + } else if v == "145" { + 145 + } else if v == "146" { + 146 + } else if v == "147" { + 147 + } else if v == "148" { + 148 + } else if v == "149" { + 149 + } else if v == "150" { + 150 + } else if v == "151" { + 151 + } else if v == "152" { + 152 + } else if v == "153" { + 153 + } else if v == "154" { + 154 + } else if v == "155" { + 155 + } else if v == "156" { + 156 + } else if v == "157" { + 157 + } else if v == "158" { + 158 + } else if v == "159" { + 159 + } else if v == "160" { + 160 + } else if v == "161" { + 161 + } else if v == "162" { + 162 + } else if v == "163" { + 163 + } else if v == "164" { + 164 + } else if v == "165" { + 165 + } else if v == "166" { + 166 + } else if v == "167" { + 167 + } else if v == "168" { + 168 + } else if v == "169" { + 169 + } else if v == "170" { + 170 + } else if v == "171" { + 171 + } else if v == "172" { + 172 + } else if v == "173" { + 173 + } else if v == "174" { + 174 + } else if v == "175" { + 175 + } else if v == "176" { + 176 + } else if v == "177" { + 177 + } else if v == "178" { + 178 + } else if v == "179" { + 179 + } else if v == "180" { + 180 + } else if v == "181" { + 181 + } else if v == "182" { + 182 + } else if v == "183" { + 183 + } else if v == "184" { + 184 + } else if v == "185" { + 185 + } else if v == "186" { + 186 + } else if v == "187" { + 187 + } else if v == "188" { + 188 + } else if v == "189" { + 189 + } else if v == "190" { + 190 + } else if v == "191" { + 191 + } else if v == "192" { + 192 + } else if v == "193" { + 193 + } else if v == "194" { + 194 + } else if v == "195" { + 195 + } else if v == "196" { + 196 + } else if v == "197" { + 197 + } else if v == "198" { + 198 + } else if v == "199" { + 199 + } else if v == "200" { + 200 + } else if v == "201" { + 201 + } else if v == "202" { + 202 + } else if v == "203" { + 203 + } else if v == "204" { + 204 + } else if v == "205" { + 205 + } else if v == "206" { + 206 + } else if v == "207" { + 207 + } else if v == "208" { + 208 + } else if v == "209" { + 209 + } else if v == "210" { + 210 + } else if v == "211" { + 211 + } else if v == "212" { + 212 + } else if v == "213" { + 213 + } else if v == "214" { + 214 + } else if v == "215" { + 215 + } else if v == "216" { + 216 + } else if v == "217" { + 217 + } else if v == "218" { + 218 + } else if v == "219" { + 219 + } else if v == "220" { + 220 + } else if v == "221" { + 221 + } else if v == "222" { + 222 + } else if v == "223" { + 223 + } else if v == "224" { + 224 + } else if v == "225" { + 225 + } else if v == "226" { + 226 + } else if v == "227" { + 227 + } else if v == "228" { + 228 + } else if v == "229" { + 229 + } else if v == "230" { + 230 + } else if v == "231" { + 231 + } else if v == "232" { + 232 + } else if v == "233" { + 233 + } else if v == "234" { + 234 + } else if v == "235" { + 235 + } else if v == "236" { + 236 + } else if v == "237" { + 237 + } else if v == "238" { + 238 + } else if v == "239" { + 239 + } else if v == "240" { + 240 + } else if v == "241" { + 241 + } else if v == "242" { + 242 + } else if v == "243" { + 243 + } else if v == "244" { + 244 + } else if v == "245" { + 245 + } else if v == "246" { + 246 + } else if v == "247" { + 247 + } else if v == "248" { + 248 + } else if v == "249" { + 249 + } else if v == "250" { + 250 + } else if v == "251" { + 251 + } else if v == "252" { + 252 + } else if v == "253" { + 253 + } else if v == "254" { + 254 + } else if v == "255" { + 255 + } else if v == "256" { + 256 + } else if v == "257" { + 257 + } else if v == "258" { + 258 + } else if v == "259" { + 259 + } else if v == "260" { + 260 + } else if v == "261" { + 261 + } else if v == "262" { + 262 + } else if v == "263" { + 263 + } else if v == "264" { + 264 + } else if v == "265" { + 265 + } else if v == "266" { + 266 + } else if v == "267" { + 267 + } else if v == "268" { + 268 + } else if v == "269" { + 269 + } else if v == "270" { + 270 + } else if v == "271" { + 271 + } else if v == "272" { + 272 + } else if v == "273" { + 273 + } else if v == "274" { + 274 + } else if v == "275" { + 275 + } else if v == "276" { + 276 + } else if v == "277" { + 277 + } else if v == "278" { + 278 + } else if v == "279" { + 279 + } else if v == "280" { + 280 + } else if v == "281" { + 281 + } else if v == "282" { + 282 + } else if v == "283" { + 283 + } else if v == "284" { + 284 + } else if v == "285" { + 285 + } else if v == "286" { + 286 + } else if v == "287" { + 287 + } else if v == "288" { + 288 + } else if v == "289" { + 289 + } else if v == "290" { + 290 + } else if v == "291" { + 291 + } else if v == "292" { + 292 + } else if v == "293" { + 293 + } else if v == "294" { + 294 + } else if v == "295" { + 295 + } else if v == "296" { + 296 + } else if v == "297" { + 297 + } else if v == "298" { + 298 + } else if v == "299" { + 299 + } else if v == "300" { + 300 + } else if v == "301" { + 301 + } else if v == "302" { + 302 + } else if v == "303" { + 303 + } else if v == "304" { + 304 + } else if v == "305" { + 305 + } else if v == "306" { + 306 + } else if v == "307" { + 307 + } else if v == "308" { + 308 + } else if v == "309" { + 309 + } else if v == "310" { + 310 + } else if v == "311" { + 311 + } else if v == "312" { + 312 + } else if v == "313" { + 313 + } else if v == "314" { + 314 + } else if v == "315" { + 315 + } else if v == "316" { + 316 + } else if v == "317" { + 317 + } else if v == "318" { + 318 + } else if v == "319" { + 319 + } else if v == "320" { + 320 + } else if v == "321" { + 321 + } else if v == "322" { + 322 + } else if v == "323" { + 323 + } else if v == "324" { + 324 + } else if v == "325" { + 325 + } else if v == "326" { + 326 + } else if v == "327" { + 327 + } else if v == "328" { + 328 + } else if v == "329" { + 329 + } else if v == "330" { + 330 + } else if v == "331" { + 331 + } else if v == "332" { + 332 + } else if v == "333" { + 333 + } else if v == "334" { + 334 + } else if v == "335" { + 335 + } else if v == "336" { + 336 + } else if v == "337" { + 337 + } else if v == "338" { + 338 + } else if v == "339" { + 339 + } else if v == "340" { + 340 + } else if v == "341" { + 341 + } else if v == "342" { + 342 + } else if v == "343" { + 343 + } else if v == "344" { + 344 + } else if v == "345" { + 345 + } else if v == "346" { + 346 + } else if v == "347" { + 347 + } else if v == "348" { + 348 + } else if v == "349" { + 349 + } else if v == "350" { + 350 + } else if v == "351" { + 351 + } else if v == "352" { + 352 + } else if v == "353" { + 353 + } else if v == "354" { + 354 + } else if v == "355" { + 355 + } else if v == "356" { + 356 + } else if v == "357" { + 357 + } else if v == "358" { + 358 + } else if v == "359" { + 359 + } else if v == "360" { + 360 + } else if v == "361" { + 361 + } else if v == "362" { + 362 + } else if v == "363" { + 363 + } else if v == "364" { + 364 + } else if v == "365" { + 365 + } else if v == "366" { + 366 + } else if v == "367" { + 367 + } else if v == "368" { + 368 + } else if v == "369" { + 369 + } else if v == "370" { + 370 + } else if v == "371" { + 371 + } else if v == "372" { + 372 + } else if v == "373" { + 373 + } else if v == "374" { + 374 + } else if v == "375" { + 375 + } else if v == "376" { + 376 + } else if v == "377" { + 377 + } else if v == "378" { + 378 + } else if v == "379" { + 379 + } else if v == "380" { + 380 + } else if v == "381" { + 381 + } else if v == "382" { + 382 + } else if v == "383" { + 383 + } else if v == "384" { + 384 + } else if v == "385" { + 385 + } else if v == "386" { + 386 + } else if v == "387" { + 387 + } else if v == "388" { + 388 + } else if v == "389" { + 389 + } else if v == "390" { + 390 + } else if v == "391" { + 391 + } else if v == "392" { + 392 + } else if v == "393" { + 393 + } else if v == "394" { + 394 + } else if v == "395" { + 395 + } else if v == "396" { + 396 + } else if v == "397" { + 397 + } else if v == "398" { + 398 + } else if v == "399" { + 399 + } else if v == "400" { + 400 + } else if v == "401" { + 401 + } else if v == "402" { + 402 + } else if v == "403" { + 403 + } else if v == "404" { + 404 + } else if v == "405" { + 405 + } else if v == "406" { + 406 + } else if v == "407" { + 407 + } else if v == "408" { + 408 + } else if v == "409" { + 409 + } else if v == "410" { + 410 + } else if v == "411" { + 411 + } else if v == "412" { + 412 + } else if v == "413" { + 413 + } else if v == "414" { + 414 + } else if v == "415" { + 415 + } else if v == "416" { + 416 + } else if v == "417" { + 417 + } else if v == "418" { + 418 + } else if v == "419" { + 419 + } else if v == "420" { + 420 + } else if v == "421" { + 421 + } else if v == "422" { + 422 + } else if v == "423" { + 423 + } else if v == "424" { + 424 + } else if v == "425" { + 425 + } else if v == "426" { + 426 + } else if v == "427" { + 427 + } else if v == "428" { + 428 + } else if v == "429" { + 429 + } else if v == "430" { + 430 + } else if v == "431" { + 431 + } else if v == "432" { + 432 + } else if v == "433" { + 433 + } else if v == "434" { + 434 + } else if v == "435" { + 435 + } else if v == "436" { + 436 + } else if v == "437" { + 437 + } else if v == "438" { + 438 + } else if v == "439" { + 439 + } else if v == "440" { + 440 + } else if v == "441" { + 441 + } else if v == "442" { + 442 + } else if v == "443" { + 443 + } else if v == "444" { + 444 + } else if v == "445" { + 445 + } else if v == "446" { + 446 + } else if v == "447" { + 447 + } else if v == "448" { + 448 + } else if v == "449" { + 449 + } else if v == "450" { + 450 + } else if v == "451" { + 451 + } else if v == "452" { + 452 + } else if v == "453" { + 453 + } else if v == "454" { + 454 + } else if v == "455" { + 455 + } else if v == "456" { + 456 + } else if v == "457" { + 457 + } else if v == "458" { + 458 + } else if v == "459" { + 459 + } else if v == "460" { + 460 + } else if v == "461" { + 461 + } else if v == "462" { + 462 + } else if v == "463" { + 463 + } else if v == "464" { + 464 + } else if v == "465" { + 465 + } else if v == "466" { + 466 + } else if v == "467" { + 467 + } else if v == "468" { + 468 + } else if v == "469" { + 469 + } else if v == "470" { + 470 + } else if v == "471" { + 471 + } else if v == "472" { + 472 + } else if v == "473" { + 473 + } else if v == "474" { + 474 + } else if v == "475" { + 475 + } else if v == "476" { + 476 + } else if v == "477" { + 477 + } else if v == "478" { + 478 + } else if v == "479" { + 479 + } else if v == "480" { + 480 + } else if v == "481" { + 481 + } else if v == "482" { + 482 + } else if v == "483" { + 483 + } else if v == "484" { + 484 + } else if v == "485" { + 485 + } else if v == "486" { + 486 + } else if v == "487" { + 487 + } else if v == "488" { + 488 + } else if v == "489" { + 489 + } else if v == "490" { + 490 + } else if v == "491" { + 491 + } else if v == "492" { + 492 + } else if v == "493" { + 493 + } else if v == "494" { + 494 + } else if v == "495" { + 495 + } else if v == "496" { + 496 + } else if v == "497" { + 497 + } else if v == "498" { + 498 + } else if v == "499" { + 499 + } else if v == "500" { + 500 + } else if v == "501" { + 501 + } else if v == "502" { + 502 + } else if v == "503" { + 503 + } else if v == "504" { + 504 + } else if v == "505" { + 505 + } else if v == "506" { + 506 + } else if v == "507" { + 507 + } else if v == "508" { + 508 + } else if v == "509" { + 509 + } else if v == "510" { + 510 + } else if v == "511" { + 511 + } else if v == "512" { + 512 + } else if v == "513" { + 513 + } else if v == "514" { + 514 + } else if v == "515" { + 515 + } else if v == "516" { + 516 + } else if v == "517" { + 517 + } else if v == "518" { + 518 + } else if v == "519" { + 519 + } else if v == "520" { + 520 + } else if v == "521" { + 521 + } else if v == "522" { + 522 + } else if v == "523" { + 523 + } else if v == "524" { + 524 + } else if v == "525" { + 525 + } else if v == "526" { + 526 + } else if v == "527" { + 527 + } else if v == "528" { + 528 + } else if v == "529" { + 529 + } else if v == "530" { + 530 + } else if v == "531" { + 531 + } else if v == "532" { + 532 + } else if v == "533" { + 533 + } else if v == "534" { + 534 + } else if v == "535" { + 535 + } else if v == "536" { + 536 + } else if v == "537" { + 537 + } else if v == "538" { + 538 + } else if v == "539" { + 539 + } else if v == "540" { + 540 + } else if v == "541" { + 541 + } else if v == "542" { + 542 + } else if v == "543" { + 543 + } else if v == "544" { + 544 + } else if v == "545" { + 545 + } else if v == "546" { + 546 + } else if v == "547" { + 547 + } else if v == "548" { + 548 + } else if v == "549" { + 549 + } else if v == "550" { + 550 + } else if v == "551" { + 551 + } else if v == "552" { + 552 + } else if v == "553" { + 553 + } else if v == "554" { + 554 + } else if v == "555" { + 555 + } else if v == "556" { + 556 + } else if v == "557" { + 557 + } else if v == "558" { + 558 + } else if v == "559" { + 559 + } else if v == "560" { + 560 + } else if v == "561" { + 561 + } else if v == "562" { + 562 + } else if v == "563" { + 563 + } else if v == "564" { + 564 + } else if v == "565" { + 565 + } else if v == "566" { + 566 + } else if v == "567" { + 567 + } else if v == "568" { + 568 + } else if v == "569" { + 569 + } else if v == "570" { + 570 + } else if v == "571" { + 571 + } else if v == "572" { + 572 + } else if v == "573" { + 573 + } else if v == "574" { + 574 + } else if v == "575" { + 575 + } else if v == "576" { + 576 + } else if v == "577" { + 577 + } else if v == "578" { + 578 + } else if v == "579" { + 579 + } else if v == "580" { + 580 + } else if v == "581" { + 581 + } else if v == "582" { + 582 + } else if v == "583" { + 583 + } else if v == "584" { + 584 + } else if v == "585" { + 585 + } else if v == "586" { + 586 + } else if v == "587" { + 587 + } else if v == "588" { + 588 + } else if v == "589" { + 589 + } else if v == "590" { + 590 + } else if v == "591" { + 591 + } else if v == "592" { + 592 + } else if v == "593" { + 593 + } else if v == "594" { + 594 + } else if v == "595" { + 595 + } else if v == "596" { + 596 + } else if v == "597" { + 597 + } else if v == "598" { + 598 + } else if v == "599" { + 599 + } else if v == "600" { + 600 + } else if v == "601" { + 601 + } else if v == "602" { + 602 + } else if v == "603" { + 603 + } else if v == "604" { + 604 + } else if v == "605" { + 605 + } else if v == "606" { + 606 + } else if v == "607" { + 607 + } else if v == "608" { + 608 + } else if v == "609" { + 609 + } else if v == "610" { + 610 + } else if v == "611" { + 611 + } else if v == "612" { + 612 + } else if v == "613" { + 613 + } else if v == "614" { + 614 + } else if v == "615" { + 615 + } else if v == "616" { + 616 + } else if v == "617" { + 617 + } else if v == "618" { + 618 + } else if v == "619" { + 619 + } else if v == "620" { + 620 + } else if v == "621" { + 621 + } else if v == "622" { + 622 + } else if v == "623" { + 623 + } else if v == "624" { + 624 + } else if v == "625" { + 625 + } else if v == "626" { + 626 + } else if v == "627" { + 627 + } else if v == "628" { + 628 + } else if v == "629" { + 629 + } else if v == "630" { + 630 + } else if v == "631" { + 631 + } else if v == "632" { + 632 + } else if v == "633" { + 633 + } else if v == "634" { + 634 + } else if v == "635" { + 635 + } else if v == "636" { + 636 + } else if v == "637" { + 637 + } else if v == "638" { + 638 + } else if v == "639" { + 639 + } else if v == "640" { + 640 + } else if v == "641" { + 641 + } else if v == "642" { + 642 + } else if v == "643" { + 643 + } else if v == "644" { + 644 + } else if v == "645" { + 645 + } else if v == "646" { + 646 + } else if v == "647" { + 647 + } else if v == "648" { + 648 + } else if v == "649" { + 649 + } else if v == "650" { + 650 + } else if v == "651" { + 651 + } else if v == "652" { + 652 + } else if v == "653" { + 653 + } else if v == "654" { + 654 + } else if v == "655" { + 655 + } else if v == "656" { + 656 + } else if v == "657" { + 657 + } else if v == "658" { + 658 + } else if v == "659" { + 659 + } else if v == "660" { + 660 + } else if v == "661" { + 661 + } else if v == "662" { + 662 + } else if v == "663" { + 663 + } else if v == "664" { + 664 + } else if v == "665" { + 665 + } else if v == "666" { + 666 + } else if v == "667" { + 667 + } else if v == "668" { + 668 + } else if v == "669" { + 669 + } else if v == "670" { + 670 + } else if v == "671" { + 671 + } else if v == "672" { + 672 + } else if v == "673" { + 673 + } else if v == "674" { + 674 + } else if v == "675" { + 675 + } else if v == "676" { + 676 + } else if v == "677" { + 677 + } else if v == "678" { + 678 + } else if v == "679" { + 679 + } else if v == "680" { + 680 + } else if v == "681" { + 681 + } else if v == "682" { + 682 + } else if v == "683" { + 683 + } else if v == "684" { + 684 + } else if v == "685" { + 685 + } else if v == "686" { + 686 + } else if v == "687" { + 687 + } else if v == "688" { + 688 + } else if v == "689" { + 689 + } else if v == "690" { + 690 + } else if v == "691" { + 691 + } else if v == "692" { + 692 + } else if v == "693" { + 693 + } else if v == "694" { + 694 + } else if v == "695" { + 695 + } else if v == "696" { + 696 + } else if v == "697" { + 697 + } else if v == "698" { + 698 + } else if v == "699" { + 699 + } else if v == "700" { + 700 + } else if v == "701" { + 701 + } else if v == "702" { + 702 + } else if v == "703" { + 703 + } else if v == "704" { + 704 + } else if v == "705" { + 705 + } else if v == "706" { + 706 + } else if v == "707" { + 707 + } else if v == "708" { + 708 + } else if v == "709" { + 709 + } else if v == "710" { + 710 + } else if v == "711" { + 711 + } else if v == "712" { + 712 + } else if v == "713" { + 713 + } else if v == "714" { + 714 + } else if v == "715" { + 715 + } else if v == "716" { + 716 + } else if v == "717" { + 717 + } else if v == "718" { + 718 + } else if v == "719" { + 719 + } else if v == "720" { + 720 + } else if v == "721" { + 721 + } else if v == "722" { + 722 + } else if v == "723" { + 723 + } else if v == "724" { + 724 + } else if v == "725" { + 725 + } else if v == "726" { + 726 + } else if v == "727" { + 727 + } else if v == "728" { + 728 + } else if v == "729" { + 729 + } else if v == "730" { + 730 + } else if v == "731" { + 731 + } else if v == "732" { + 732 + } else if v == "733" { + 733 + } else if v == "734" { + 734 + } else if v == "735" { + 735 + } else if v == "736" { + 736 + } else if v == "737" { + 737 + } else if v == "738" { + 738 + } else if v == "739" { + 739 + } else if v == "740" { + 740 + } else if v == "741" { + 741 + } else if v == "742" { + 742 + } else if v == "743" { + 743 + } else if v == "744" { + 744 + } else if v == "745" { + 745 + } else if v == "746" { + 746 + } else if v == "747" { + 747 + } else if v == "748" { + 748 + } else if v == "749" { + 749 + } else if v == "750" { + 750 + } else if v == "751" { + 751 + } else if v == "752" { + 752 + } else if v == "753" { + 753 + } else if v == "754" { + 754 + } else if v == "755" { + 755 + } else if v == "756" { + 756 + } else if v == "757" { + 757 + } else if v == "758" { + 758 + } else if v == "759" { + 759 + } else if v == "760" { + 760 + } else if v == "761" { + 761 + } else if v == "762" { + 762 + } else if v == "763" { + 763 + } else if v == "764" { + 764 + } else if v == "765" { + 765 + } else if v == "766" { + 766 + } else if v == "767" { + 767 + } else if v == "768" { + 768 + } else if v == "769" { + 769 + } else if v == "770" { + 770 + } else if v == "771" { + 771 + } else if v == "772" { + 772 + } else if v == "773" { + 773 + } else if v == "774" { + 774 + } else if v == "775" { + 775 + } else if v == "776" { + 776 + } else if v == "777" { + 777 + } else if v == "778" { + 778 + } else if v == "779" { + 779 + } else if v == "780" { + 780 + } else if v == "781" { + 781 + } else if v == "782" { + 782 + } else if v == "783" { + 783 + } else if v == "784" { + 784 + } else if v == "785" { + 785 + } else if v == "786" { + 786 + } else if v == "787" { + 787 + } else if v == "788" { + 788 + } else if v == "789" { + 789 + } else if v == "790" { + 790 + } else if v == "791" { + 791 + } else if v == "792" { + 792 + } else if v == "793" { + 793 + } else if v == "794" { + 794 + } else if v == "795" { + 795 + } else if v == "796" { + 796 + } else if v == "797" { + 797 + } else if v == "798" { + 798 + } else if v == "799" { + 799 + } else if v == "800" { + 800 + } else if v == "801" { + 801 + } else if v == "802" { + 802 + } else if v == "803" { + 803 + } else if v == "804" { + 804 + } else if v == "805" { + 805 + } else if v == "806" { + 806 + } else if v == "807" { + 807 + } else if v == "808" { + 808 + } else if v == "809" { + 809 + } else if v == "810" { + 810 + } else if v == "811" { + 811 + } else if v == "812" { + 812 + } else if v == "813" { + 813 + } else if v == "814" { + 814 + } else if v == "815" { + 815 + } else if v == "816" { + 816 + } else if v == "817" { + 817 + } else if v == "818" { + 818 + } else if v == "819" { + 819 + } else if v == "820" { + 820 + } else if v == "821" { + 821 + } else if v == "822" { + 822 + } else if v == "823" { + 823 + } else if v == "824" { + 824 + } else if v == "825" { + 825 + } else if v == "826" { + 826 + } else if v == "827" { + 827 + } else if v == "828" { + 828 + } else if v == "829" { + 829 + } else if v == "830" { + 830 + } else if v == "831" { + 831 + } else if v == "832" { + 832 + } else if v == "833" { + 833 + } else if v == "834" { + 834 + } else if v == "835" { + 835 + } else if v == "836" { + 836 + } else if v == "837" { + 837 + } else if v == "838" { + 838 + } else if v == "839" { + 839 + } else if v == "840" { + 840 + } else if v == "841" { + 841 + } else if v == "842" { + 842 + } else if v == "843" { + 843 + } else if v == "844" { + 844 + } else if v == "845" { + 845 + } else if v == "846" { + 846 + } else if v == "847" { + 847 + } else if v == "848" { + 848 + } else if v == "849" { + 849 + } else if v == "850" { + 850 + } else if v == "851" { + 851 + } else if v == "852" { + 852 + } else if v == "853" { + 853 + } else if v == "854" { + 854 + } else if v == "855" { + 855 + } else if v == "856" { + 856 + } else if v == "857" { + 857 + } else if v == "858" { + 858 + } else if v == "859" { + 859 + } else if v == "860" { + 860 + } else if v == "861" { + 861 + } else if v == "862" { + 862 + } else if v == "863" { + 863 + } else if v == "864" { + 864 + } else if v == "865" { + 865 + } else if v == "866" { + 866 + } else if v == "867" { + 867 + } else if v == "868" { + 868 + } else if v == "869" { + 869 + } else if v == "870" { + 870 + } else if v == "871" { + 871 + } else if v == "872" { + 872 + } else if v == "873" { + 873 + } else if v == "874" { + 874 + } else if v == "875" { + 875 + } else if v == "876" { + 876 + } else if v == "877" { + 877 + } else if v == "878" { + 878 + } else if v == "879" { + 879 + } else if v == "880" { + 880 + } else if v == "881" { + 881 + } else if v == "882" { + 882 + } else if v == "883" { + 883 + } else if v == "884" { + 884 + } else if v == "885" { + 885 + } else if v == "886" { + 886 + } else if v == "887" { + 887 + } else if v == "888" { + 888 + } else if v == "889" { + 889 + } else if v == "890" { + 890 + } else if v == "891" { + 891 + } else if v == "892" { + 892 + } else if v == "893" { + 893 + } else if v == "894" { + 894 + } else if v == "895" { + 895 + } else if v == "896" { + 896 + } else if v == "897" { + 897 + } else if v == "898" { + 898 + } else if v == "899" { + 899 + } else if v == "900" { + 900 + } else if v == "901" { + 901 + } else if v == "902" { + 902 + } else if v == "903" { + 903 + } else if v == "904" { + 904 + } else if v == "905" { + 905 + } else if v == "906" { + 906 + } else if v == "907" { + 907 + } else if v == "908" { + 908 + } else if v == "909" { + 909 + } else if v == "910" { + 910 + } else if v == "911" { + 911 + } else if v == "912" { + 912 + } else if v == "913" { + 913 + } else if v == "914" { + 914 + } else if v == "915" { + 915 + } else if v == "916" { + 916 + } else if v == "917" { + 917 + } else if v == "918" { + 918 + } else if v == "919" { + 919 + } else if v == "920" { + 920 + } else if v == "921" { + 921 + } else if v == "922" { + 922 + } else if v == "923" { + 923 + } else if v == "924" { + 924 + } else if v == "925" { + 925 + } else if v == "926" { + 926 + } else if v == "927" { + 927 + } else if v == "928" { + 928 + } else if v == "929" { + 929 + } else if v == "930" { + 930 + } else if v == "931" { + 931 + } else if v == "932" { + 932 + } else if v == "933" { + 933 + } else if v == "934" { + 934 + } else if v == "935" { + 935 + } else if v == "936" { + 936 + } else if v == "937" { + 937 + } else if v == "938" { + 938 + } else if v == "939" { + 939 + } else if v == "940" { + 940 + } else if v == "941" { + 941 + } else if v == "942" { + 942 + } else if v == "943" { + 943 + } else if v == "944" { + 944 + } else if v == "945" { + 945 + } else if v == "946" { + 946 + } else if v == "947" { + 947 + } else if v == "948" { + 948 + } else if v == "949" { + 949 + } else if v == "950" { + 950 + } else if v == "951" { + 951 + } else if v == "952" { + 952 + } else if v == "953" { + 953 + } else if v == "954" { + 954 + } else if v == "955" { + 955 + } else if v == "956" { + 956 + } else if v == "957" { + 957 + } else if v == "958" { + 958 + } else if v == "959" { + 959 + } else if v == "960" { + 960 + } else if v == "961" { + 961 + } else if v == "962" { + 962 + } else if v == "963" { + 963 + } else if v == "964" { + 964 + } else if v == "965" { + 965 + } else if v == "966" { + 966 + } else if v == "967" { + 967 + } else if v == "968" { + 968 + } else if v == "969" { + 969 + } else if v == "970" { + 970 + } else if v == "971" { + 971 + } else if v == "972" { + 972 + } else if v == "973" { + 973 + } else if v == "974" { + 974 + } else if v == "975" { + 975 + } else if v == "976" { + 976 + } else if v == "977" { + 977 + } else if v == "978" { + 978 + } else if v == "979" { + 979 + } else if v == "980" { + 980 + } else if v == "981" { + 981 + } else if v == "982" { + 982 + } else if v == "983" { + 983 + } else if v == "984" { + 984 + } else if v == "985" { + 985 + } else if v == "986" { + 986 + } else if v == "987" { + 987 + } else if v == "988" { + 988 + } else if v == "989" { + 989 + } else if v == "990" { + 990 + } else if v == "991" { + 991 + } else if v == "992" { + 992 + } else if v == "993" { + 993 + } else if v == "994" { + 994 + } else if v == "995" { + 995 + } else if v == "996" { + 996 + } else if v == "997" { + 997 + } else if v == "998" { + 998 + } else if v == "999" { + 999 + } else if v == "1000" { + 1000 + } else if v == "1001" { + 1001 + } else if v == "1002" { + 1002 + } else if v == "1003" { + 1003 + } else if v == "1004" { + 1004 + } else if v == "1005" { + 1005 + } else if v == "1006" { + 1006 + } else if v == "1007" { + 1007 + } else if v == "1008" { + 1008 + } else if v == "1009" { + 1009 + } else if v == "1010" { + 1010 + } else if v == "1011" { + 1011 + } else if v == "1012" { + 1012 + } else if v == "1013" { + 1013 + } else if v == "1014" { + 1014 + } else if v == "1015" { + 1015 + } else if v == "1016" { + 1016 + } else if v == "1017" { + 1017 + } else if v == "1018" { + 1018 + } else if v == "1019" { + 1019 + } else if v == "1020" { + 1020 + } else if v == "1021" { + 1021 + } else if v == "1022" { + 1022 + } else if v == "1023" { + 1023 + } else if v == "1024" { + 1024 + } else if v == "1025" { + 1025 + } else if v == "1026" { + 1026 + } else if v == "1027" { + 1027 + } else if v == "1028" { + 1028 + } else if v == "1029" { + 1029 + } else if v == "1030" { + 1030 + } else if v == "1031" { + 1031 + } else if v == "1032" { + 1032 + } else if v == "1033" { + 1033 + } else if v == "1034" { + 1034 + } else if v == "1035" { + 1035 + } else if v == "1036" { + 1036 + } else if v == "1037" { + 1037 + } else if v == "1038" { + 1038 + } else if v == "1039" { + 1039 + } else if v == "1040" { + 1040 + } else if v == "1041" { + 1041 + } else if v == "1042" { + 1042 + } else if v == "1043" { + 1043 + } else if v == "1044" { + 1044 + } else if v == "1045" { + 1045 + } else if v == "1046" { + 1046 + } else if v == "1047" { + 1047 + } else if v == "1048" { + 1048 + } else if v == "1049" { + 1049 + } else if v == "1050" { + 1050 + } else if v == "1051" { + 1051 + } else if v == "1052" { + 1052 + } else if v == "1053" { + 1053 + } else if v == "1054" { + 1054 + } else if v == "1055" { + 1055 + } else if v == "1056" { + 1056 + } else if v == "1057" { + 1057 + } else if v == "1058" { + 1058 + } else if v == "1059" { + 1059 + } else if v == "1060" { + 1060 + } else if v == "1061" { + 1061 + } else if v == "1062" { + 1062 + } else if v == "1063" { + 1063 + } else if v == "1064" { + 1064 + } else if v == "1065" { + 1065 + } else if v == "1066" { + 1066 + } else if v == "1067" { + 1067 + } else if v == "1068" { + 1068 + } else if v == "1069" { + 1069 + } else if v == "1070" { + 1070 + } else if v == "1071" { + 1071 + } else if v == "1072" { + 1072 + } else if v == "1073" { + 1073 + } else if v == "1074" { + 1074 + } else if v == "1075" { + 1075 + } else if v == "1076" { + 1076 + } else if v == "1077" { + 1077 + } else if v == "1078" { + 1078 + } else if v == "1079" { + 1079 + } else if v == "1080" { + 1080 + } else if v == "1081" { + 1081 + } else if v == "1082" { + 1082 + } else if v == "1083" { + 1083 + } else if v == "1084" { + 1084 + } else if v == "1085" { + 1085 + } else if v == "1086" { + 1086 + } else if v == "1087" { + 1087 + } else if v == "1088" { + 1088 + } else if v == "1089" { + 1089 + } else if v == "1090" { + 1090 + } else if v == "1091" { + 1091 + } else if v == "1092" { + 1092 + } else if v == "1093" { + 1093 + } else if v == "1094" { + 1094 + } else if v == "1095" { + 1095 + } else if v == "1096" { + 1096 + } else if v == "1097" { + 1097 + } else if v == "1098" { + 1098 + } else if v == "1099" { + 1099 + } else if v == "1100" { + 1100 + } else if v == "1101" { + 1101 + } else if v == "1102" { + 1102 + } else if v == "1103" { + 1103 + } else if v == "1104" { + 1104 + } else if v == "1105" { + 1105 + } else if v == "1106" { + 1106 + } else if v == "1107" { + 1107 + } else if v == "1108" { + 1108 + } else if v == "1109" { + 1109 + } else if v == "1110" { + 1110 + } else if v == "1111" { + 1111 + } else if v == "1112" { + 1112 + } else if v == "1113" { + 1113 + } else if v == "1114" { + 1114 + } else if v == "1115" { + 1115 + } else if v == "1116" { + 1116 + } else if v == "1117" { + 1117 + } else if v == "1118" { + 1118 + } else if v == "1119" { + 1119 + } else if v == "1120" { + 1120 + } else if v == "1121" { + 1121 + } else if v == "1122" { + 1122 + } else if v == "1123" { + 1123 + } else if v == "1124" { + 1124 + } else if v == "1125" { + 1125 + } else if v == "1126" { + 1126 + } else if v == "1127" { + 1127 + } else if v == "1128" { + 1128 + } else if v == "1129" { + 1129 + } else if v == "1130" { + 1130 + } else if v == "1131" { + 1131 + } else if v == "1132" { + 1132 + } else if v == "1133" { + 1133 + } else if v == "1134" { + 1134 + } else if v == "1135" { + 1135 + } else if v == "1136" { + 1136 + } else if v == "1137" { + 1137 + } else if v == "1138" { + 1138 + } else if v == "1139" { + 1139 + } else if v == "1140" { + 1140 + } else if v == "1141" { + 1141 + } else if v == "1142" { + 1142 + } else if v == "1143" { + 1143 + } else if v == "1144" { + 1144 + } else if v == "1145" { + 1145 + } else if v == "1146" { + 1146 + } else if v == "1147" { + 1147 + } else if v == "1148" { + 1148 + } else if v == "1149" { + 1149 + } else if v == "1150" { + 1150 + } else if v == "1151" { + 1151 + } else if v == "1152" { + 1152 + } else if v == "1153" { + 1153 + } else if v == "1154" { + 1154 + } else if v == "1155" { + 1155 + } else if v == "1156" { + 1156 + } else if v == "1157" { + 1157 + } else if v == "1158" { + 1158 + } else if v == "1159" { + 1159 + } else if v == "1160" { + 1160 + } else if v == "1161" { + 1161 + } else if v == "1162" { + 1162 + } else if v == "1163" { + 1163 + } else if v == "1164" { + 1164 + } else if v == "1165" { + 1165 + } else if v == "1166" { + 1166 + } else if v == "1167" { + 1167 + } else if v == "1168" { + 1168 + } else if v == "1169" { + 1169 + } else if v == "1170" { + 1170 + } else if v == "1171" { + 1171 + } else if v == "1172" { + 1172 + } else if v == "1173" { + 1173 + } else if v == "1174" { + 1174 + } else if v == "1175" { + 1175 + } else if v == "1176" { + 1176 + } else if v == "1177" { + 1177 + } else if v == "1178" { + 1178 + } else if v == "1179" { + 1179 + } else if v == "1180" { + 1180 + } else if v == "1181" { + 1181 + } else if v == "1182" { + 1182 + } else if v == "1183" { + 1183 + } else if v == "1184" { + 1184 + } else if v == "1185" { + 1185 + } else if v == "1186" { + 1186 + } else if v == "1187" { + 1187 + } else if v == "1188" { + 1188 + } else if v == "1189" { + 1189 + } else if v == "1190" { + 1190 + } else if v == "1191" { + 1191 + } else if v == "1192" { + 1192 + } else if v == "1193" { + 1193 + } else if v == "1194" { + 1194 + } else if v == "1195" { + 1195 + } else if v == "1196" { + 1196 + } else if v == "1197" { + 1197 + } else if v == "1198" { + 1198 + } else if v == "1199" { + 1199 + } else if v == "1200" { + 1200 + } else if v == "1201" { + 1201 + } else if v == "1202" { + 1202 + } else if v == "1203" { + 1203 + } else if v == "1204" { + 1204 + } else if v == "1205" { + 1205 + } else if v == "1206" { + 1206 + } else if v == "1207" { + 1207 + } else if v == "1208" { + 1208 + } else if v == "1209" { + 1209 + } else if v == "1210" { + 1210 + } else if v == "1211" { + 1211 + } else if v == "1212" { + 1212 + } else if v == "1213" { + 1213 + } else if v == "1214" { + 1214 + } else if v == "1215" { + 1215 + } else if v == "1216" { + 1216 + } else if v == "1217" { + 1217 + } else if v == "1218" { + 1218 + } else if v == "1219" { + 1219 + } else if v == "1220" { + 1220 + } else if v == "1221" { + 1221 + } else if v == "1222" { + 1222 + } else if v == "1223" { + 1223 + } else if v == "1224" { + 1224 + } else if v == "1225" { + 1225 + } else if v == "1226" { + 1226 + } else if v == "1227" { + 1227 + } else if v == "1228" { + 1228 + } else if v == "1229" { + 1229 + } else if v == "1230" { + 1230 + } else if v == "1231" { + 1231 + } else if v == "1232" { + 1232 + } else if v == "1233" { + 1233 + } else if v == "1234" { + 1234 + } else if v == "1235" { + 1235 + } else if v == "1236" { + 1236 + } else if v == "1237" { + 1237 + } else if v == "1238" { + 1238 + } else if v == "1239" { + 1239 + } else if v == "1240" { + 1240 + } else if v == "1241" { + 1241 + } else if v == "1242" { + 1242 + } else if v == "1243" { + 1243 + } else if v == "1244" { + 1244 + } else if v == "1245" { + 1245 + } else if v == "1246" { + 1246 + } else if v == "1247" { + 1247 + } else if v == "1248" { + 1248 + } else if v == "1249" { + 1249 + } else if v == "1250" { + 1250 + } else if v == "1251" { + 1251 + } else if v == "1252" { + 1252 + } else if v == "1253" { + 1253 + } else if v == "1254" { + 1254 + } else if v == "1255" { + 1255 + } else if v == "1256" { + 1256 + } else if v == "1257" { + 1257 + } else if v == "1258" { + 1258 + } else if v == "1259" { + 1259 + } else if v == "1260" { + 1260 + } else if v == "1261" { + 1261 + } else if v == "1262" { + 1262 + } else if v == "1263" { + 1263 + } else if v == "1264" { + 1264 + } else if v == "1265" { + 1265 + } else if v == "1266" { + 1266 + } else if v == "1267" { + 1267 + } else if v == "1268" { + 1268 + } else if v == "1269" { + 1269 + } else if v == "1270" { + 1270 + } else if v == "1271" { + 1271 + } else if v == "1272" { + 1272 + } else if v == "1273" { + 1273 + } else if v == "1274" { + 1274 + } else if v == "1275" { + 1275 + } else if v == "1276" { + 1276 + } else if v == "1277" { + 1277 + } else if v == "1278" { + 1278 + } else if v == "1279" { + 1279 + } else if v == "1280" { + 1280 + } else if v == "1281" { + 1281 + } else if v == "1282" { + 1282 + } else if v == "1283" { + 1283 + } else if v == "1284" { + 1284 + } else if v == "1285" { + 1285 + } else if v == "1286" { + 1286 + } else if v == "1287" { + 1287 + } else if v == "1288" { + 1288 + } else if v == "1289" { + 1289 + } else if v == "1290" { + 1290 + } else if v == "1291" { + 1291 + } else if v == "1292" { + 1292 + } else if v == "1293" { + 1293 + } else if v == "1294" { + 1294 + } else if v == "1295" { + 1295 + } else if v == "1296" { + 1296 + } else if v == "1297" { + 1297 + } else if v == "1298" { + 1298 + } else if v == "1299" { + 1299 + } else if v == "1300" { + 1300 + } else if v == "1301" { + 1301 + } else if v == "1302" { + 1302 + } else if v == "1303" { + 1303 + } else if v == "1304" { + 1304 + } else if v == "1305" { + 1305 + } else if v == "1306" { + 1306 + } else if v == "1307" { + 1307 + } else if v == "1308" { + 1308 + } else if v == "1309" { + 1309 + } else if v == "1310" { + 1310 + } else if v == "1311" { + 1311 + } else if v == "1312" { + 1312 + } else if v == "1313" { + 1313 + } else if v == "1314" { + 1314 + } else if v == "1315" { + 1315 + } else if v == "1316" { + 1316 + } else if v == "1317" { + 1317 + } else if v == "1318" { + 1318 + } else if v == "1319" { + 1319 + } else if v == "1320" { + 1320 + } else if v == "1321" { + 1321 + } else if v == "1322" { + 1322 + } else if v == "1323" { + 1323 + } else if v == "1324" { + 1324 + } else if v == "1325" { + 1325 + } else if v == "1326" { + 1326 + } else if v == "1327" { + 1327 + } else if v == "1328" { + 1328 + } else if v == "1329" { + 1329 + } else if v == "1330" { + 1330 + } else if v == "1331" { + 1331 + } else if v == "1332" { + 1332 + } else if v == "1333" { + 1333 + } else if v == "1334" { + 1334 + } else if v == "1335" { + 1335 + } else if v == "1336" { + 1336 + } else if v == "1337" { + 1337 + } else if v == "1338" { + 1338 + } else if v == "1339" { + 1339 + } else if v == "1340" { + 1340 + } else if v == "1341" { + 1341 + } else if v == "1342" { + 1342 + } else if v == "1343" { + 1343 + } else if v == "1344" { + 1344 + } else if v == "1345" { + 1345 + } else if v == "1346" { + 1346 + } else if v == "1347" { + 1347 + } else if v == "1348" { + 1348 + } else if v == "1349" { + 1349 + } else if v == "1350" { + 1350 + } else if v == "1351" { + 1351 + } else if v == "1352" { + 1352 + } else if v == "1353" { + 1353 + } else if v == "1354" { + 1354 + } else if v == "1355" { + 1355 + } else if v == "1356" { + 1356 + } else if v == "1357" { + 1357 + } else if v == "1358" { + 1358 + } else if v == "1359" { + 1359 + } else if v == "1360" { + 1360 + } else if v == "1361" { + 1361 + } else if v == "1362" { + 1362 + } else if v == "1363" { + 1363 + } else if v == "1364" { + 1364 + } else if v == "1365" { + 1365 + } else if v == "1366" { + 1366 + } else if v == "1367" { + 1367 + } else if v == "1368" { + 1368 + } else if v == "1369" { + 1369 + } else if v == "1370" { + 1370 + } else if v == "1371" { + 1371 + } else if v == "1372" { + 1372 + } else if v == "1373" { + 1373 + } else if v == "1374" { + 1374 + } else if v == "1375" { + 1375 + } else if v == "1376" { + 1376 + } else if v == "1377" { + 1377 + } else if v == "1378" { + 1378 + } else if v == "1379" { + 1379 + } else if v == "1380" { + 1380 + } else if v == "1381" { + 1381 + } else if v == "1382" { + 1382 + } else if v == "1383" { + 1383 + } else if v == "1384" { + 1384 + } else if v == "1385" { + 1385 + } else if v == "1386" { + 1386 + } else if v == "1387" { + 1387 + } else if v == "1388" { + 1388 + } else if v == "1389" { + 1389 + } else if v == "1390" { + 1390 + } else if v == "1391" { + 1391 + } else if v == "1392" { + 1392 + } else if v == "1393" { + 1393 + } else if v == "1394" { + 1394 + } else if v == "1395" { + 1395 + } else if v == "1396" { + 1396 + } else if v == "1397" { + 1397 + } else if v == "1398" { + 1398 + } else if v == "1399" { + 1399 + } else if v == "1400" { + 1400 + } else if v == "1401" { + 1401 + } else if v == "1402" { + 1402 + } else if v == "1403" { + 1403 + } else if v == "1404" { + 1404 + } else if v == "1405" { + 1405 + } else if v == "1406" { + 1406 + } else if v == "1407" { + 1407 + } else if v == "1408" { + 1408 + } else if v == "1409" { + 1409 + } else if v == "1410" { + 1410 + } else if v == "1411" { + 1411 + } else if v == "1412" { + 1412 + } else if v == "1413" { + 1413 + } else if v == "1414" { + 1414 + } else if v == "1415" { + 1415 + } else if v == "1416" { + 1416 + } else if v == "1417" { + 1417 + } else if v == "1418" { + 1418 + } else if v == "1419" { + 1419 + } else if v == "1420" { + 1420 + } else if v == "1421" { + 1421 + } else if v == "1422" { + 1422 + } else if v == "1423" { + 1423 + } else if v == "1424" { + 1424 + } else if v == "1425" { + 1425 + } else if v == "1426" { + 1426 + } else if v == "1427" { + 1427 + } else if v == "1428" { + 1428 + } else if v == "1429" { + 1429 + } else if v == "1430" { + 1430 + } else if v == "1431" { + 1431 + } else if v == "1432" { + 1432 + } else if v == "1433" { + 1433 + } else if v == "1434" { + 1434 + } else if v == "1435" { + 1435 + } else if v == "1436" { + 1436 + } else if v == "1437" { + 1437 + } else if v == "1438" { + 1438 + } else if v == "1439" { + 1439 + } else if v == "1440" { + 1440 + } else if v == "1441" { + 1441 + } else if v == "1442" { + 1442 + } else if v == "1443" { + 1443 + } else if v == "1444" { + 1444 + } else if v == "1445" { + 1445 + } else if v == "1446" { + 1446 + } else if v == "1447" { + 1447 + } else if v == "1448" { + 1448 + } else if v == "1449" { + 1449 + } else if v == "1450" { + 1450 + } else if v == "1451" { + 1451 + } else if v == "1452" { + 1452 + } else if v == "1453" { + 1453 + } else if v == "1454" { + 1454 + } else if v == "1455" { + 1455 + } else if v == "1456" { + 1456 + } else if v == "1457" { + 1457 + } else if v == "1458" { + 1458 + } else if v == "1459" { + 1459 + } else if v == "1460" { + 1460 + } else if v == "1461" { + 1461 + } else if v == "1462" { + 1462 + } else if v == "1463" { + 1463 + } else if v == "1464" { + 1464 + } else if v == "1465" { + 1465 + } else if v == "1466" { + 1466 + } else if v == "1467" { + 1467 + } else if v == "1468" { + 1468 + } else if v == "1469" { + 1469 + } else if v == "1470" { + 1470 + } else if v == "1471" { + 1471 + } else if v == "1472" { + 1472 + } else if v == "1473" { + 1473 + } else if v == "1474" { + 1474 + } else if v == "1475" { + 1475 + } else if v == "1476" { + 1476 + } else if v == "1477" { + 1477 + } else if v == "1478" { + 1478 + } else if v == "1479" { + 1479 + } else if v == "1480" { + 1480 + } else if v == "1481" { + 1481 + } else if v == "1482" { + 1482 + } else if v == "1483" { + 1483 + } else if v == "1484" { + 1484 + } else if v == "1485" { + 1485 + } else if v == "1486" { + 1486 + } else if v == "1487" { + 1487 + } else if v == "1488" { + 1488 + } else if v == "1489" { + 1489 + } else if v == "1490" { + 1490 + } else if v == "1491" { + 1491 + } else if v == "1492" { + 1492 + } else if v == "1493" { + 1493 + } else if v == "1494" { + 1494 + } else if v == "1495" { + 1495 + } else if v == "1496" { + 1496 + } else if v == "1497" { + 1497 + } else if v == "1498" { + 1498 + } else if v == "1499" { + 1499 + } else if v == "1500" { + 1500 + } else if v == "1501" { + 1501 + } else if v == "1502" { + 1502 + } else if v == "1503" { + 1503 + } else if v == "1504" { + 1504 + } else if v == "1505" { + 1505 + } else if v == "1506" { + 1506 + } else if v == "1507" { + 1507 + } else if v == "1508" { + 1508 + } else if v == "1509" { + 1509 + } else if v == "1510" { + 1510 + } else if v == "1511" { + 1511 + } else if v == "1512" { + 1512 + } else if v == "1513" { + 1513 + } else if v == "1514" { + 1514 + } else if v == "1515" { + 1515 + } else if v == "1516" { + 1516 + } else if v == "1517" { + 1517 + } else if v == "1518" { + 1518 + } else if v == "1519" { + 1519 + } else if v == "1520" { + 1520 + } else if v == "1521" { + 1521 + } else if v == "1522" { + 1522 + } else if v == "1523" { + 1523 + } else if v == "1524" { + 1524 + } else if v == "1525" { + 1525 + } else if v == "1526" { + 1526 + } else if v == "1527" { + 1527 + } else if v == "1528" { + 1528 + } else if v == "1529" { + 1529 + } else if v == "1530" { + 1530 + } else if v == "1531" { + 1531 + } else if v == "1532" { + 1532 + } else if v == "1533" { + 1533 + } else if v == "1534" { + 1534 + } else if v == "1535" { + 1535 + } else if v == "1536" { + 1536 + } else if v == "1537" { + 1537 + } else if v == "1538" { + 1538 + } else if v == "1539" { + 1539 + } else if v == "1540" { + 1540 + } else if v == "1541" { + 1541 + } else if v == "1542" { + 1542 + } else if v == "1543" { + 1543 + } else if v == "1544" { + 1544 + } else if v == "1545" { + 1545 + } else if v == "1546" { + 1546 + } else if v == "1547" { + 1547 + } else if v == "1548" { + 1548 + } else if v == "1549" { + 1549 + } else if v == "1550" { + 1550 + } else if v == "1551" { + 1551 + } else if v == "1552" { + 1552 + } else if v == "1553" { + 1553 + } else if v == "1554" { + 1554 + } else if v == "1555" { + 1555 + } else if v == "1556" { + 1556 + } else if v == "1557" { + 1557 + } else if v == "1558" { + 1558 + } else if v == "1559" { + 1559 + } else if v == "1560" { + 1560 + } else if v == "1561" { + 1561 + } else if v == "1562" { + 1562 + } else if v == "1563" { + 1563 + } else if v == "1564" { + 1564 + } else if v == "1565" { + 1565 + } else if v == "1566" { + 1566 + } else if v == "1567" { + 1567 + } else if v == "1568" { + 1568 + } else if v == "1569" { + 1569 + } else if v == "1570" { + 1570 + } else if v == "1571" { + 1571 + } else if v == "1572" { + 1572 + } else if v == "1573" { + 1573 + } else if v == "1574" { + 1574 + } else if v == "1575" { + 1575 + } else if v == "1576" { + 1576 + } else if v == "1577" { + 1577 + } else if v == "1578" { + 1578 + } else if v == "1579" { + 1579 + } else if v == "1580" { + 1580 + } else if v == "1581" { + 1581 + } else if v == "1582" { + 1582 + } else if v == "1583" { + 1583 + } else if v == "1584" { + 1584 + } else if v == "1585" { + 1585 + } else if v == "1586" { + 1586 + } else if v == "1587" { + 1587 + } else if v == "1588" { + 1588 + } else if v == "1589" { + 1589 + } else if v == "1590" { + 1590 + } else if v == "1591" { + 1591 + } else if v == "1592" { + 1592 + } else if v == "1593" { + 1593 + } else if v == "1594" { + 1594 + } else if v == "1595" { + 1595 + } else if v == "1596" { + 1596 + } else if v == "1597" { + 1597 + } else if v == "1598" { + 1598 + } else if v == "1599" { + 1599 + } else if v == "1600" { + 1600 + } else if v == "1601" { + 1601 + } else if v == "1602" { + 1602 + } else if v == "1603" { + 1603 + } else if v == "1604" { + 1604 + } else if v == "1605" { + 1605 + } else if v == "1606" { + 1606 + } else if v == "1607" { + 1607 + } else if v == "1608" { + 1608 + } else if v == "1609" { + 1609 + } else if v == "1610" { + 1610 + } else if v == "1611" { + 1611 + } else if v == "1612" { + 1612 + } else if v == "1613" { + 1613 + } else if v == "1614" { + 1614 + } else if v == "1615" { + 1615 + } else if v == "1616" { + 1616 + } else if v == "1617" { + 1617 + } else if v == "1618" { + 1618 + } else if v == "1619" { + 1619 + } else if v == "1620" { + 1620 + } else if v == "1621" { + 1621 + } else if v == "1622" { + 1622 + } else if v == "1623" { + 1623 + } else if v == "1624" { + 1624 + } else if v == "1625" { + 1625 + } else if v == "1626" { + 1626 + } else if v == "1627" { + 1627 + } else if v == "1628" { + 1628 + } else if v == "1629" { + 1629 + } else if v == "1630" { + 1630 + } else if v == "1631" { + 1631 + } else if v == "1632" { + 1632 + } else if v == "1633" { + 1633 + } else if v == "1634" { + 1634 + } else if v == "1635" { + 1635 + } else if v == "1636" { + 1636 + } else if v == "1637" { + 1637 + } else if v == "1638" { + 1638 + } else if v == "1639" { + 1639 + } else if v == "1640" { + 1640 + } else if v == "1641" { + 1641 + } else if v == "1642" { + 1642 + } else if v == "1643" { + 1643 + } else if v == "1644" { + 1644 + } else if v == "1645" { + 1645 + } else if v == "1646" { + 1646 + } else if v == "1647" { + 1647 + } else if v == "1648" { + 1648 + } else if v == "1649" { + 1649 + } else if v == "1650" { + 1650 + } else if v == "1651" { + 1651 + } else if v == "1652" { + 1652 + } else if v == "1653" { + 1653 + } else if v == "1654" { + 1654 + } else if v == "1655" { + 1655 + } else if v == "1656" { + 1656 + } else if v == "1657" { + 1657 + } else if v == "1658" { + 1658 + } else if v == "1659" { + 1659 + } else if v == "1660" { + 1660 + } else if v == "1661" { + 1661 + } else if v == "1662" { + 1662 + } else if v == "1663" { + 1663 + } else if v == "1664" { + 1664 + } else if v == "1665" { + 1665 + } else if v == "1666" { + 1666 + } else if v == "1667" { + 1667 + } else if v == "1668" { + 1668 + } else if v == "1669" { + 1669 + } else if v == "1670" { + 1670 + } else if v == "1671" { + 1671 + } else if v == "1672" { + 1672 + } else if v == "1673" { + 1673 + } else if v == "1674" { + 1674 + } else if v == "1675" { + 1675 + } else if v == "1676" { + 1676 + } else if v == "1677" { + 1677 + } else if v == "1678" { + 1678 + } else if v == "1679" { + 1679 + } else if v == "1680" { + 1680 + } else if v == "1681" { + 1681 + } else if v == "1682" { + 1682 + } else if v == "1683" { + 1683 + } else if v == "1684" { + 1684 + } else if v == "1685" { + 1685 + } else if v == "1686" { + 1686 + } else if v == "1687" { + 1687 + } else if v == "1688" { + 1688 + } else if v == "1689" { + 1689 + } else if v == "1690" { + 1690 + } else if v == "1691" { + 1691 + } else if v == "1692" { + 1692 + } else if v == "1693" { + 1693 + } else if v == "1694" { + 1694 + } else if v == "1695" { + 1695 + } else if v == "1696" { + 1696 + } else if v == "1697" { + 1697 + } else if v == "1698" { + 1698 + } else if v == "1699" { + 1699 + } else if v == "1700" { + 1700 + } else if v == "1701" { + 1701 + } else if v == "1702" { + 1702 + } else if v == "1703" { + 1703 + } else if v == "1704" { + 1704 + } else if v == "1705" { + 1705 + } else if v == "1706" { + 1706 + } else if v == "1707" { + 1707 + } else if v == "1708" { + 1708 + } else if v == "1709" { + 1709 + } else if v == "1710" { + 1710 + } else if v == "1711" { + 1711 + } else if v == "1712" { + 1712 + } else if v == "1713" { + 1713 + } else if v == "1714" { + 1714 + } else if v == "1715" { + 1715 + } else if v == "1716" { + 1716 + } else if v == "1717" { + 1717 + } else if v == "1718" { + 1718 + } else if v == "1719" { + 1719 + } else if v == "1720" { + 1720 + } else if v == "1721" { + 1721 + } else if v == "1722" { + 1722 + } else if v == "1723" { + 1723 + } else if v == "1724" { + 1724 + } else if v == "1725" { + 1725 + } else if v == "1726" { + 1726 + } else if v == "1727" { + 1727 + } else if v == "1728" { + 1728 + } else if v == "1729" { + 1729 + } else if v == "1730" { + 1730 + } else if v == "1731" { + 1731 + } else if v == "1732" { + 1732 + } else if v == "1733" { + 1733 + } else if v == "1734" { + 1734 + } else if v == "1735" { + 1735 + } else if v == "1736" { + 1736 + } else if v == "1737" { + 1737 + } else if v == "1738" { + 1738 + } else if v == "1739" { + 1739 + } else if v == "1740" { + 1740 + } else if v == "1741" { + 1741 + } else if v == "1742" { + 1742 + } else if v == "1743" { + 1743 + } else if v == "1744" { + 1744 + } else if v == "1745" { + 1745 + } else if v == "1746" { + 1746 + } else if v == "1747" { + 1747 + } else if v == "1748" { + 1748 + } else if v == "1749" { + 1749 + } else if v == "1750" { + 1750 + } else if v == "1751" { + 1751 + } else if v == "1752" { + 1752 + } else if v == "1753" { + 1753 + } else if v == "1754" { + 1754 + } else if v == "1755" { + 1755 + } else if v == "1756" { + 1756 + } else if v == "1757" { + 1757 + } else if v == "1758" { + 1758 + } else if v == "1759" { + 1759 + } else if v == "1760" { + 1760 + } else if v == "1761" { + 1761 + } else if v == "1762" { + 1762 + } else if v == "1763" { + 1763 + } else if v == "1764" { + 1764 + } else if v == "1765" { + 1765 + } else if v == "1766" { + 1766 + } else if v == "1767" { + 1767 + } else if v == "1768" { + 1768 + } else if v == "1769" { + 1769 + } else if v == "1770" { + 1770 + } else if v == "1771" { + 1771 + } else if v == "1772" { + 1772 + } else if v == "1773" { + 1773 + } else if v == "1774" { + 1774 + } else if v == "1775" { + 1775 + } else if v == "1776" { + 1776 + } else if v == "1777" { + 1777 + } else if v == "1778" { + 1778 + } else if v == "1779" { + 1779 + } else if v == "1780" { + 1780 + } else if v == "1781" { + 1781 + } else if v == "1782" { + 1782 + } else if v == "1783" { + 1783 + } else if v == "1784" { + 1784 + } else if v == "1785" { + 1785 + } else if v == "1786" { + 1786 + } else if v == "1787" { + 1787 + } else if v == "1788" { + 1788 + } else if v == "1789" { + 1789 + } else if v == "1790" { + 1790 + } else if v == "1791" { + 1791 + } else if v == "1792" { + 1792 + } else if v == "1793" { + 1793 + } else if v == "1794" { + 1794 + } else if v == "1795" { + 1795 + } else if v == "1796" { + 1796 + } else if v == "1797" { + 1797 + } else if v == "1798" { + 1798 + } else if v == "1799" { + 1799 + } else if v == "1800" { + 1800 + } else if v == "1801" { + 1801 + } else if v == "1802" { + 1802 + } else if v == "1803" { + 1803 + } else if v == "1804" { + 1804 + } else if v == "1805" { + 1805 + } else if v == "1806" { + 1806 + } else if v == "1807" { + 1807 + } else if v == "1808" { + 1808 + } else if v == "1809" { + 1809 + } else if v == "1810" { + 1810 + } else if v == "1811" { + 1811 + } else if v == "1812" { + 1812 + } else if v == "1813" { + 1813 + } else if v == "1814" { + 1814 + } else if v == "1815" { + 1815 + } else if v == "1816" { + 1816 + } else if v == "1817" { + 1817 + } else if v == "1818" { + 1818 + } else if v == "1819" { + 1819 + } else if v == "1820" { + 1820 + } else if v == "1821" { + 1821 + } else if v == "1822" { + 1822 + } else if v == "1823" { + 1823 + } else if v == "1824" { + 1824 + } else if v == "1825" { + 1825 + } else if v == "1826" { + 1826 + } else if v == "1827" { + 1827 + } else if v == "1828" { + 1828 + } else if v == "1829" { + 1829 + } else if v == "1830" { + 1830 + } else if v == "1831" { + 1831 + } else if v == "1832" { + 1832 + } else if v == "1833" { + 1833 + } else if v == "1834" { + 1834 + } else if v == "1835" { + 1835 + } else if v == "1836" { + 1836 + } else if v == "1837" { + 1837 + } else if v == "1838" { + 1838 + } else if v == "1839" { + 1839 + } else if v == "1840" { + 1840 + } else if v == "1841" { + 1841 + } else if v == "1842" { + 1842 + } else if v == "1843" { + 1843 + } else if v == "1844" { + 1844 + } else if v == "1845" { + 1845 + } else if v == "1846" { + 1846 + } else if v == "1847" { + 1847 + } else if v == "1848" { + 1848 + } else if v == "1849" { + 1849 + } else if v == "1850" { + 1850 + } else if v == "1851" { + 1851 + } else if v == "1852" { + 1852 + } else if v == "1853" { + 1853 + } else if v == "1854" { + 1854 + } else if v == "1855" { + 1855 + } else if v == "1856" { + 1856 + } else if v == "1857" { + 1857 + } else if v == "1858" { + 1858 + } else if v == "1859" { + 1859 + } else if v == "1860" { + 1860 + } else if v == "1861" { + 1861 + } else if v == "1862" { + 1862 + } else if v == "1863" { + 1863 + } else if v == "1864" { + 1864 + } else if v == "1865" { + 1865 + } else if v == "1866" { + 1866 + } else if v == "1867" { + 1867 + } else if v == "1868" { + 1868 + } else if v == "1869" { + 1869 + } else if v == "1870" { + 1870 + } else if v == "1871" { + 1871 + } else if v == "1872" { + 1872 + } else if v == "1873" { + 1873 + } else if v == "1874" { + 1874 + } else if v == "1875" { + 1875 + } else if v == "1876" { + 1876 + } else if v == "1877" { + 1877 + } else if v == "1878" { + 1878 + } else if v == "1879" { + 1879 + } else if v == "1880" { + 1880 + } else if v == "1881" { + 1881 + } else if v == "1882" { + 1882 + } else if v == "1883" { + 1883 + } else if v == "1884" { + 1884 + } else if v == "1885" { + 1885 + } else if v == "1886" { + 1886 + } else if v == "1887" { + 1887 + } else if v == "1888" { + 1888 + } else if v == "1889" { + 1889 + } else if v == "1890" { + 1890 + } else if v == "1891" { + 1891 + } else if v == "1892" { + 1892 + } else if v == "1893" { + 1893 + } else if v == "1894" { + 1894 + } else if v == "1895" { + 1895 + } else if v == "1896" { + 1896 + } else if v == "1897" { + 1897 + } else if v == "1898" { + 1898 + } else if v == "1899" { + 1899 + } else if v == "1900" { + 1900 + } else if v == "1901" { + 1901 + } else if v == "1902" { + 1902 + } else if v == "1903" { + 1903 + } else if v == "1904" { + 1904 + } else if v == "1905" { + 1905 + } else if v == "1906" { + 1906 + } else if v == "1907" { + 1907 + } else if v == "1908" { + 1908 + } else if v == "1909" { + 1909 + } else if v == "1910" { + 1910 + } else if v == "1911" { + 1911 + } else if v == "1912" { + 1912 + } else if v == "1913" { + 1913 + } else if v == "1914" { + 1914 + } else if v == "1915" { + 1915 + } else if v == "1916" { + 1916 + } else if v == "1917" { + 1917 + } else if v == "1918" { + 1918 + } else if v == "1919" { + 1919 + } else if v == "1920" { + 1920 + } else if v == "1921" { + 1921 + } else if v == "1922" { + 1922 + } else if v == "1923" { + 1923 + } else if v == "1924" { + 1924 + } else if v == "1925" { + 1925 + } else if v == "1926" { + 1926 + } else if v == "1927" { + 1927 + } else if v == "1928" { + 1928 + } else if v == "1929" { + 1929 + } else if v == "1930" { + 1930 + } else if v == "1931" { + 1931 + } else if v == "1932" { + 1932 + } else if v == "1933" { + 1933 + } else if v == "1934" { + 1934 + } else if v == "1935" { + 1935 + } else if v == "1936" { + 1936 + } else if v == "1937" { + 1937 + } else if v == "1938" { + 1938 + } else if v == "1939" { + 1939 + } else if v == "1940" { + 1940 + } else if v == "1941" { + 1941 + } else if v == "1942" { + 1942 + } else if v == "1943" { + 1943 + } else if v == "1944" { + 1944 + } else if v == "1945" { + 1945 + } else if v == "1946" { + 1946 + } else if v == "1947" { + 1947 + } else if v == "1948" { + 1948 + } else if v == "1949" { + 1949 + } else if v == "1950" { + 1950 + } else if v == "1951" { + 1951 + } else if v == "1952" { + 1952 + } else if v == "1953" { + 1953 + } else if v == "1954" { + 1954 + } else if v == "1955" { + 1955 + } else if v == "1956" { + 1956 + } else if v == "1957" { + 1957 + } else if v == "1958" { + 1958 + } else if v == "1959" { + 1959 + } else if v == "1960" { + 1960 + } else if v == "1961" { + 1961 + } else if v == "1962" { + 1962 + } else if v == "1963" { + 1963 + } else if v == "1964" { + 1964 + } else if v == "1965" { + 1965 + } else if v == "1966" { + 1966 + } else if v == "1967" { + 1967 + } else if v == "1968" { + 1968 + } else if v == "1969" { + 1969 + } else if v == "1970" { + 1970 + } else if v == "1971" { + 1971 + } else if v == "1972" { + 1972 + } else if v == "1973" { + 1973 + } else if v == "1974" { + 1974 + } else if v == "1975" { + 1975 + } else if v == "1976" { + 1976 + } else if v == "1977" { + 1977 + } else if v == "1978" { + 1978 + } else if v == "1979" { + 1979 + } else if v == "1980" { + 1980 + } else if v == "1981" { + 1981 + } else if v == "1982" { + 1982 + } else if v == "1983" { + 1983 + } else if v == "1984" { + 1984 + } else if v == "1985" { + 1985 + } else if v == "1986" { + 1986 + } else if v == "1987" { + 1987 + } else if v == "1988" { + 1988 + } else if v == "1989" { + 1989 + } else if v == "1990" { + 1990 + } else if v == "1991" { + 1991 + } else if v == "1992" { + 1992 + } else if v == "1993" { + 1993 + } else if v == "1994" { + 1994 + } else if v == "1995" { + 1995 + } else if v == "1996" { + 1996 + } else if v == "1997" { + 1997 + } else if v == "1998" { + 1998 + } else if v == "1999" { + 1999 + } else if v == "2000" { + 2000 + } else if v == "2001" { + 2001 + } else if v == "2002" { + 2002 + } else if v == "2003" { + 2003 + } else if v == "2004" { + 2004 + } else if v == "2005" { + 2005 + } else if v == "2006" { + 2006 + } else if v == "2007" { + 2007 + } else if v == "2008" { + 2008 + } else if v == "2009" { + 2009 + } else if v == "2010" { + 2010 + } else if v == "2011" { + 2011 + } else if v == "2012" { + 2012 + } else if v == "2013" { + 2013 + } else if v == "2014" { + 2014 + } else if v == "2015" { + 2015 + } else if v == "2016" { + 2016 + } else if v == "2017" { + 2017 + } else if v == "2018" { + 2018 + } else if v == "2019" { + 2019 + } else if v == "2020" { + 2020 + } else if v == "2021" { + 2021 + } else if v == "2022" { + 2022 + } else if v == "2023" { + 2023 + } else if v == "2024" { + 2024 + } else if v == "2025" { + 2025 + } else if v == "2026" { + 2026 + } else if v == "2027" { + 2027 + } else if v == "2028" { + 2028 + } else if v == "2029" { + 2029 + } else if v == "2030" { + 2030 + } else if v == "2031" { + 2031 + } else if v == "2032" { + 2032 + } else if v == "2033" { + 2033 + } else if v == "2034" { + 2034 + } else if v == "2035" { + 2035 + } else if v == "2036" { + 2036 + } else if v == "2037" { + 2037 + } else if v == "2038" { + 2038 + } else if v == "2039" { + 2039 + } else if v == "2040" { + 2040 + } else if v == "2041" { + 2041 + } else if v == "2042" { + 2042 + } else if v == "2043" { + 2043 + } else if v == "2044" { + 2044 + } else if v == "2045" { + 2045 + } else if v == "2046" { + 2046 + } else if v == "2047" { + 2047 + } else if v == "2048" { + 2048 + } else if v == "2049" { + 2049 + } else if v == "2050" { + 2050 + } else if v == "2051" { + 2051 + } else if v == "2052" { + 2052 + } else if v == "2053" { + 2053 + } else if v == "2054" { + 2054 + } else if v == "2055" { + 2055 + } else if v == "2056" { + 2056 + } else if v == "2057" { + 2057 + } else if v == "2058" { + 2058 + } else if v == "2059" { + 2059 + } else if v == "2060" { + 2060 + } else if v == "2061" { + 2061 + } else if v == "2062" { + 2062 + } else if v == "2063" { + 2063 + } else if v == "2064" { + 2064 + } else if v == "2065" { + 2065 + } else if v == "2066" { + 2066 + } else if v == "2067" { + 2067 + } else if v == "2068" { + 2068 + } else if v == "2069" { + 2069 + } else if v == "2070" { + 2070 + } else if v == "2071" { + 2071 + } else if v == "2072" { + 2072 + } else if v == "2073" { + 2073 + } else if v == "2074" { + 2074 + } else if v == "2075" { + 2075 + } else if v == "2076" { + 2076 + } else if v == "2077" { + 2077 + } else if v == "2078" { + 2078 + } else if v == "2079" { + 2079 + } else if v == "2080" { + 2080 + } else if v == "2081" { + 2081 + } else if v == "2082" { + 2082 + } else if v == "2083" { + 2083 + } else if v == "2084" { + 2084 + } else if v == "2085" { + 2085 + } else if v == "2086" { + 2086 + } else if v == "2087" { + 2087 + } else if v == "2088" { + 2088 + } else if v == "2089" { + 2089 + } else if v == "2090" { + 2090 + } else if v == "2091" { + 2091 + } else if v == "2092" { + 2092 + } else if v == "2093" { + 2093 + } else if v == "2094" { + 2094 + } else if v == "2095" { + 2095 + } else if v == "2096" { + 2096 + } else if v == "2097" { + 2097 + } else if v == "2098" { + 2098 + } else if v == "2099" { + 2099 + } else if v == "2100" { + 2100 + } else if v == "2101" { + 2101 + } else if v == "2102" { + 2102 + } else if v == "2103" { + 2103 + } else if v == "2104" { + 2104 + } else if v == "2105" { + 2105 + } else if v == "2106" { + 2106 + } else if v == "2107" { + 2107 + } else if v == "2108" { + 2108 + } else if v == "2109" { + 2109 + } else if v == "2110" { + 2110 + } else if v == "2111" { + 2111 + } else if v == "2112" { + 2112 + } else if v == "2113" { + 2113 + } else if v == "2114" { + 2114 + } else if v == "2115" { + 2115 + } else if v == "2116" { + 2116 + } else if v == "2117" { + 2117 + } else if v == "2118" { + 2118 + } else if v == "2119" { + 2119 + } else if v == "2120" { + 2120 + } else if v == "2121" { + 2121 + } else if v == "2122" { + 2122 + } else if v == "2123" { + 2123 + } else if v == "2124" { + 2124 + } else if v == "2125" { + 2125 + } else if v == "2126" { + 2126 + } else if v == "2127" { + 2127 + } else if v == "2128" { + 2128 + } else if v == "2129" { + 2129 + } else if v == "2130" { + 2130 + } else if v == "2131" { + 2131 + } else if v == "2132" { + 2132 + } else if v == "2133" { + 2133 + } else if v == "2134" { + 2134 + } else if v == "2135" { + 2135 + } else if v == "2136" { + 2136 + } else if v == "2137" { + 2137 + } else if v == "2138" { + 2138 + } else if v == "2139" { + 2139 + } else if v == "2140" { + 2140 + } else if v == "2141" { + 2141 + } else if v == "2142" { + 2142 + } else if v == "2143" { + 2143 + } else if v == "2144" { + 2144 + } else if v == "2145" { + 2145 + } else if v == "2146" { + 2146 + } else if v == "2147" { + 2147 + } else if v == "2148" { + 2148 + } else if v == "2149" { + 2149 + } else if v == "2150" { + 2150 + } else if v == "2151" { + 2151 + } else if v == "2152" { + 2152 + } else if v == "2153" { + 2153 + } else if v == "2154" { + 2154 + } else if v == "2155" { + 2155 + } else if v == "2156" { + 2156 + } else if v == "2157" { + 2157 + } else if v == "2158" { + 2158 + } else if v == "2159" { + 2159 + } else if v == "2160" { + 2160 + } else if v == "2161" { + 2161 + } else if v == "2162" { + 2162 + } else if v == "2163" { + 2163 + } else if v == "2164" { + 2164 + } else if v == "2165" { + 2165 + } else if v == "2166" { + 2166 + } else if v == "2167" { + 2167 + } else if v == "2168" { + 2168 + } else if v == "2169" { + 2169 + } else if v == "2170" { + 2170 + } else if v == "2171" { + 2171 + } else if v == "2172" { + 2172 + } else if v == "2173" { + 2173 + } else if v == "2174" { + 2174 + } else if v == "2175" { + 2175 + } else if v == "2176" { + 2176 + } else if v == "2177" { + 2177 + } else if v == "2178" { + 2178 + } else if v == "2179" { + 2179 + } else if v == "2180" { + 2180 + } else if v == "2181" { + 2181 + } else if v == "2182" { + 2182 + } else if v == "2183" { + 2183 + } else if v == "2184" { + 2184 + } else if v == "2185" { + 2185 + } else if v == "2186" { + 2186 + } else if v == "2187" { + 2187 + } else if v == "2188" { + 2188 + } else if v == "2189" { + 2189 + } else if v == "2190" { + 2190 + } else if v == "2191" { + 2191 + } else if v == "2192" { + 2192 + } else if v == "2193" { + 2193 + } else if v == "2194" { + 2194 + } else if v == "2195" { + 2195 + } else if v == "2196" { + 2196 + } else if v == "2197" { + 2197 + } else if v == "2198" { + 2198 + } else if v == "2199" { + 2199 + } else if v == "2200" { + 2200 + } else if v == "2201" { + 2201 + } else if v == "2202" { + 2202 + } else if v == "2203" { + 2203 + } else if v == "2204" { + 2204 + } else if v == "2205" { + 2205 + } else if v == "2206" { + 2206 + } else if v == "2207" { + 2207 + } else if v == "2208" { + 2208 + } else if v == "2209" { + 2209 + } else if v == "2210" { + 2210 + } else if v == "2211" { + 2211 + } else if v == "2212" { + 2212 + } else if v == "2213" { + 2213 + } else if v == "2214" { + 2214 + } else if v == "2215" { + 2215 + } else if v == "2216" { + 2216 + } else if v == "2217" { + 2217 + } else if v == "2218" { + 2218 + } else if v == "2219" { + 2219 + } else if v == "2220" { + 2220 + } else if v == "2221" { + 2221 + } else if v == "2222" { + 2222 + } else if v == "2223" { + 2223 + } else if v == "2224" { + 2224 + } else if v == "2225" { + 2225 + } else if v == "2226" { + 2226 + } else if v == "2227" { + 2227 + } else if v == "2228" { + 2228 + } else if v == "2229" { + 2229 + } else if v == "2230" { + 2230 + } else if v == "2231" { + 2231 + } else if v == "2232" { + 2232 + } else if v == "2233" { + 2233 + } else if v == "2234" { + 2234 + } else if v == "2235" { + 2235 + } else if v == "2236" { + 2236 + } else if v == "2237" { + 2237 + } else if v == "2238" { + 2238 + } else if v == "2239" { + 2239 + } else if v == "2240" { + 2240 + } else if v == "2241" { + 2241 + } else if v == "2242" { + 2242 + } else if v == "2243" { + 2243 + } else if v == "2244" { + 2244 + } else if v == "2245" { + 2245 + } else if v == "2246" { + 2246 + } else if v == "2247" { + 2247 + } else if v == "2248" { + 2248 + } else if v == "2249" { + 2249 + } else if v == "2250" { + 2250 + } else if v == "2251" { + 2251 + } else if v == "2252" { + 2252 + } else if v == "2253" { + 2253 + } else if v == "2254" { + 2254 + } else if v == "2255" { + 2255 + } else if v == "2256" { + 2256 + } else if v == "2257" { + 2257 + } else if v == "2258" { + 2258 + } else if v == "2259" { + 2259 + } else if v == "2260" { + 2260 + } else if v == "2261" { + 2261 + } else if v == "2262" { + 2262 + } else if v == "2263" { + 2263 + } else if v == "2264" { + 2264 + } else if v == "2265" { + 2265 + } else if v == "2266" { + 2266 + } else if v == "2267" { + 2267 + } else if v == "2268" { + 2268 + } else if v == "2269" { + 2269 + } else if v == "2270" { + 2270 + } else if v == "2271" { + 2271 + } else if v == "2272" { + 2272 + } else if v == "2273" { + 2273 + } else if v == "2274" { + 2274 + } else if v == "2275" { + 2275 + } else if v == "2276" { + 2276 + } else if v == "2277" { + 2277 + } else if v == "2278" { + 2278 + } else if v == "2279" { + 2279 + } else if v == "2280" { + 2280 + } else if v == "2281" { + 2281 + } else if v == "2282" { + 2282 + } else if v == "2283" { + 2283 + } else if v == "2284" { + 2284 + } else if v == "2285" { + 2285 + } else if v == "2286" { + 2286 + } else if v == "2287" { + 2287 + } else if v == "2288" { + 2288 + } else if v == "2289" { + 2289 + } else if v == "2290" { + 2290 + } else if v == "2291" { + 2291 + } else if v == "2292" { + 2292 + } else if v == "2293" { + 2293 + } else if v == "2294" { + 2294 + } else if v == "2295" { + 2295 + } else if v == "2296" { + 2296 + } else if v == "2297" { + 2297 + } else if v == "2298" { + 2298 + } else if v == "2299" { + 2299 + } else if v == "2300" { + 2300 + } else if v == "2301" { + 2301 + } else if v == "2302" { + 2302 + } else if v == "2303" { + 2303 + } else if v == "2304" { + 2304 + } else if v == "2305" { + 2305 + } else if v == "2306" { + 2306 + } else if v == "2307" { + 2307 + } else if v == "2308" { + 2308 + } else if v == "2309" { + 2309 + } else if v == "2310" { + 2310 + } else if v == "2311" { + 2311 + } else if v == "2312" { + 2312 + } else if v == "2313" { + 2313 + } else if v == "2314" { + 2314 + } else if v == "2315" { + 2315 + } else if v == "2316" { + 2316 + } else if v == "2317" { + 2317 + } else if v == "2318" { + 2318 + } else if v == "2319" { + 2319 + } else if v == "2320" { + 2320 + } else if v == "2321" { + 2321 + } else if v == "2322" { + 2322 + } else if v == "2323" { + 2323 + } else if v == "2324" { + 2324 + } else if v == "2325" { + 2325 + } else if v == "2326" { + 2326 + } else if v == "2327" { + 2327 + } else if v == "2328" { + 2328 + } else if v == "2329" { + 2329 + } else if v == "2330" { + 2330 + } else if v == "2331" { + 2331 + } else if v == "2332" { + 2332 + } else if v == "2333" { + 2333 + } else if v == "2334" { + 2334 + } else if v == "2335" { + 2335 + } else if v == "2336" { + 2336 + } else if v == "2337" { + 2337 + } else if v == "2338" { + 2338 + } else if v == "2339" { + 2339 + } else if v == "2340" { + 2340 + } else if v == "2341" { + 2341 + } else if v == "2342" { + 2342 + } else if v == "2343" { + 2343 + } else if v == "2344" { + 2344 + } else if v == "2345" { + 2345 + } else if v == "2346" { + 2346 + } else if v == "2347" { + 2347 + } else if v == "2348" { + 2348 + } else if v == "2349" { + 2349 + } else if v == "2350" { + 2350 + } else if v == "2351" { + 2351 + } else if v == "2352" { + 2352 + } else if v == "2353" { + 2353 + } else if v == "2354" { + 2354 + } else if v == "2355" { + 2355 + } else if v == "2356" { + 2356 + } else if v == "2357" { + 2357 + } else if v == "2358" { + 2358 + } else if v == "2359" { + 2359 + } else if v == "2360" { + 2360 + } else if v == "2361" { + 2361 + } else if v == "2362" { + 2362 + } else if v == "2363" { + 2363 + } else if v == "2364" { + 2364 + } else if v == "2365" { + 2365 + } else if v == "2366" { + 2366 + } else if v == "2367" { + 2367 + } else if v == "2368" { + 2368 + } else if v == "2369" { + 2369 + } else if v == "2370" { + 2370 + } else if v == "2371" { + 2371 + } else if v == "2372" { + 2372 + } else if v == "2373" { + 2373 + } else if v == "2374" { + 2374 + } else if v == "2375" { + 2375 + } else if v == "2376" { + 2376 + } else if v == "2377" { + 2377 + } else if v == "2378" { + 2378 + } else if v == "2379" { + 2379 + } else if v == "2380" { + 2380 + } else if v == "2381" { + 2381 + } else if v == "2382" { + 2382 + } else if v == "2383" { + 2383 + } else if v == "2384" { + 2384 + } else if v == "2385" { + 2385 + } else if v == "2386" { + 2386 + } else if v == "2387" { + 2387 + } else if v == "2388" { + 2388 + } else if v == "2389" { + 2389 + } else if v == "2390" { + 2390 + } else if v == "2391" { + 2391 + } else if v == "2392" { + 2392 + } else if v == "2393" { + 2393 + } else if v == "2394" { + 2394 + } else if v == "2395" { + 2395 + } else if v == "2396" { + 2396 + } else if v == "2397" { + 2397 + } else if v == "2398" { + 2398 + } else if v == "2399" { + 2399 + } else if v == "2400" { + 2400 + } else if v == "2401" { + 2401 + } else if v == "2402" { + 2402 + } else if v == "2403" { + 2403 + } else if v == "2404" { + 2404 + } else if v == "2405" { + 2405 + } else if v == "2406" { + 2406 + } else if v == "2407" { + 2407 + } else if v == "2408" { + 2408 + } else if v == "2409" { + 2409 + } else if v == "2410" { + 2410 + } else if v == "2411" { + 2411 + } else if v == "2412" { + 2412 + } else if v == "2413" { + 2413 + } else if v == "2414" { + 2414 + } else if v == "2415" { + 2415 + } else if v == "2416" { + 2416 + } else if v == "2417" { + 2417 + } else if v == "2418" { + 2418 + } else if v == "2419" { + 2419 + } else if v == "2420" { + 2420 + } else if v == "2421" { + 2421 + } else if v == "2422" { + 2422 + } else if v == "2423" { + 2423 + } else if v == "2424" { + 2424 + } else if v == "2425" { + 2425 + } else if v == "2426" { + 2426 + } else if v == "2427" { + 2427 + } else if v == "2428" { + 2428 + } else if v == "2429" { + 2429 + } else if v == "2430" { + 2430 + } else if v == "2431" { + 2431 + } else if v == "2432" { + 2432 + } else if v == "2433" { + 2433 + } else if v == "2434" { + 2434 + } else if v == "2435" { + 2435 + } else if v == "2436" { + 2436 + } else if v == "2437" { + 2437 + } else if v == "2438" { + 2438 + } else if v == "2439" { + 2439 + } else if v == "2440" { + 2440 + } else if v == "2441" { + 2441 + } else if v == "2442" { + 2442 + } else if v == "2443" { + 2443 + } else if v == "2444" { + 2444 + } else if v == "2445" { + 2445 + } else if v == "2446" { + 2446 + } else if v == "2447" { + 2447 + } else if v == "2448" { + 2448 + } else if v == "2449" { + 2449 + } else if v == "2450" { + 2450 + } else if v == "2451" { + 2451 + } else if v == "2452" { + 2452 + } else if v == "2453" { + 2453 + } else if v == "2454" { + 2454 + } else if v == "2455" { + 2455 + } else if v == "2456" { + 2456 + } else if v == "2457" { + 2457 + } else if v == "2458" { + 2458 + } else if v == "2459" { + 2459 + } else if v == "2460" { + 2460 + } else if v == "2461" { + 2461 + } else if v == "2462" { + 2462 + } else if v == "2463" { + 2463 + } else if v == "2464" { + 2464 + } else if v == "2465" { + 2465 + } else if v == "2466" { + 2466 + } else if v == "2467" { + 2467 + } else if v == "2468" { + 2468 + } else if v == "2469" { + 2469 + } else if v == "2470" { + 2470 + } else if v == "2471" { + 2471 + } else if v == "2472" { + 2472 + } else if v == "2473" { + 2473 + } else if v == "2474" { + 2474 + } else if v == "2475" { + 2475 + } else if v == "2476" { + 2476 + } else if v == "2477" { + 2477 + } else if v == "2478" { + 2478 + } else if v == "2479" { + 2479 + } else if v == "2480" { + 2480 + } else if v == "2481" { + 2481 + } else if v == "2482" { + 2482 + } else if v == "2483" { + 2483 + } else if v == "2484" { + 2484 + } else if v == "2485" { + 2485 + } else if v == "2486" { + 2486 + } else if v == "2487" { + 2487 + } else if v == "2488" { + 2488 + } else if v == "2489" { + 2489 + } else if v == "2490" { + 2490 + } else if v == "2491" { + 2491 + } else if v == "2492" { + 2492 + } else if v == "2493" { + 2493 + } else if v == "2494" { + 2494 + } else if v == "2495" { + 2495 + } else if v == "2496" { + 2496 + } else if v == "2497" { + 2497 + } else if v == "2498" { + 2498 + } else if v == "2499" { + 2499 + } else if v == "2500" { + 2500 + } else if v == "2501" { + 2501 + } else if v == "2502" { + 2502 + } else if v == "2503" { + 2503 + } else if v == "2504" { + 2504 + } else if v == "2505" { + 2505 + } else if v == "2506" { + 2506 + } else if v == "2507" { + 2507 + } else if v == "2508" { + 2508 + } else if v == "2509" { + 2509 + } else if v == "2510" { + 2510 + } else if v == "2511" { + 2511 + } else if v == "2512" { + 2512 + } else if v == "2513" { + 2513 + } else if v == "2514" { + 2514 + } else if v == "2515" { + 2515 + } else if v == "2516" { + 2516 + } else if v == "2517" { + 2517 + } else if v == "2518" { + 2518 + } else if v == "2519" { + 2519 + } else if v == "2520" { + 2520 + } else if v == "2521" { + 2521 + } else if v == "2522" { + 2522 + } else if v == "2523" { + 2523 + } else if v == "2524" { + 2524 + } else if v == "2525" { + 2525 + } else if v == "2526" { + 2526 + } else if v == "2527" { + 2527 + } else if v == "2528" { + 2528 + } else if v == "2529" { + 2529 + } else if v == "2530" { + 2530 + } else if v == "2531" { + 2531 + } else if v == "2532" { + 2532 + } else if v == "2533" { + 2533 + } else if v == "2534" { + 2534 + } else if v == "2535" { + 2535 + } else if v == "2536" { + 2536 + } else if v == "2537" { + 2537 + } else if v == "2538" { + 2538 + } else if v == "2539" { + 2539 + } else if v == "2540" { + 2540 + } else if v == "2541" { + 2541 + } else if v == "2542" { + 2542 + } else if v == "2543" { + 2543 + } else if v == "2544" { + 2544 + } else if v == "2545" { + 2545 + } else if v == "2546" { + 2546 + } else if v == "2547" { + 2547 + } else if v == "2548" { + 2548 + } else if v == "2549" { + 2549 + } else if v == "2550" { + 2550 + } else if v == "2551" { + 2551 + } else if v == "2552" { + 2552 + } else if v == "2553" { + 2553 + } else if v == "2554" { + 2554 + } else if v == "2555" { + 2555 + } else if v == "2556" { + 2556 + } else if v == "2557" { + 2557 + } else if v == "2558" { + 2558 + } else if v == "2559" { + 2559 + } else if v == "2560" { + 2560 + } else if v == "2561" { + 2561 + } else if v == "2562" { + 2562 + } else if v == "2563" { + 2563 + } else if v == "2564" { + 2564 + } else if v == "2565" { + 2565 + } else if v == "2566" { + 2566 + } else if v == "2567" { + 2567 + } else if v == "2568" { + 2568 + } else if v == "2569" { + 2569 + } else if v == "2570" { + 2570 + } else if v == "2571" { + 2571 + } else if v == "2572" { + 2572 + } else if v == "2573" { + 2573 + } else if v == "2574" { + 2574 + } else if v == "2575" { + 2575 + } else if v == "2576" { + 2576 + } else if v == "2577" { + 2577 + } else if v == "2578" { + 2578 + } else if v == "2579" { + 2579 + } else if v == "2580" { + 2580 + } else if v == "2581" { + 2581 + } else if v == "2582" { + 2582 + } else if v == "2583" { + 2583 + } else if v == "2584" { + 2584 + } else if v == "2585" { + 2585 + } else if v == "2586" { + 2586 + } else if v == "2587" { + 2587 + } else if v == "2588" { + 2588 + } else if v == "2589" { + 2589 + } else if v == "2590" { + 2590 + } else if v == "2591" { + 2591 + } else if v == "2592" { + 2592 + } else if v == "2593" { + 2593 + } else if v == "2594" { + 2594 + } else if v == "2595" { + 2595 + } else if v == "2596" { + 2596 + } else if v == "2597" { + 2597 + } else if v == "2598" { + 2598 + } else if v == "2599" { + 2599 + } else if v == "2600" { + 2600 + } else if v == "2601" { + 2601 + } else if v == "2602" { + 2602 + } else if v == "2603" { + 2603 + } else if v == "2604" { + 2604 + } else if v == "2605" { + 2605 + } else if v == "2606" { + 2606 + } else if v == "2607" { + 2607 + } else if v == "2608" { + 2608 + } else if v == "2609" { + 2609 + } else if v == "2610" { + 2610 + } else if v == "2611" { + 2611 + } else if v == "2612" { + 2612 + } else if v == "2613" { + 2613 + } else if v == "2614" { + 2614 + } else if v == "2615" { + 2615 + } else if v == "2616" { + 2616 + } else if v == "2617" { + 2617 + } else if v == "2618" { + 2618 + } else if v == "2619" { + 2619 + } else if v == "2620" { + 2620 + } else if v == "2621" { + 2621 + } else if v == "2622" { + 2622 + } else if v == "2623" { + 2623 + } else if v == "2624" { + 2624 + } else if v == "2625" { + 2625 + } else if v == "2626" { + 2626 + } else if v == "2627" { + 2627 + } else if v == "2628" { + 2628 + } else if v == "2629" { + 2629 + } else if v == "2630" { + 2630 + } else if v == "2631" { + 2631 + } else if v == "2632" { + 2632 + } else if v == "2633" { + 2633 + } else if v == "2634" { + 2634 + } else if v == "2635" { + 2635 + } else if v == "2636" { + 2636 + } else if v == "2637" { + 2637 + } else if v == "2638" { + 2638 + } else if v == "2639" { + 2639 + } else if v == "2640" { + 2640 + } else if v == "2641" { + 2641 + } else if v == "2642" { + 2642 + } else if v == "2643" { + 2643 + } else if v == "2644" { + 2644 + } else if v == "2645" { + 2645 + } else if v == "2646" { + 2646 + } else if v == "2647" { + 2647 + } else if v == "2648" { + 2648 + } else if v == "2649" { + 2649 + } else if v == "2650" { + 2650 + } else if v == "2651" { + 2651 + } else if v == "2652" { + 2652 + } else if v == "2653" { + 2653 + } else if v == "2654" { + 2654 + } else if v == "2655" { + 2655 + } else if v == "2656" { + 2656 + } else if v == "2657" { + 2657 + } else if v == "2658" { + 2658 + } else if v == "2659" { + 2659 + } else if v == "2660" { + 2660 + } else if v == "2661" { + 2661 + } else if v == "2662" { + 2662 + } else if v == "2663" { + 2663 + } else if v == "2664" { + 2664 + } else if v == "2665" { + 2665 + } else if v == "2666" { + 2666 + } else if v == "2667" { + 2667 + } else if v == "2668" { + 2668 + } else if v == "2669" { + 2669 + } else if v == "2670" { + 2670 + } else if v == "2671" { + 2671 + } else if v == "2672" { + 2672 + } else if v == "2673" { + 2673 + } else if v == "2674" { + 2674 + } else if v == "2675" { + 2675 + } else if v == "2676" { + 2676 + } else if v == "2677" { + 2677 + } else if v == "2678" { + 2678 + } else if v == "2679" { + 2679 + } else if v == "2680" { + 2680 + } else if v == "2681" { + 2681 + } else if v == "2682" { + 2682 + } else if v == "2683" { + 2683 + } else if v == "2684" { + 2684 + } else if v == "2685" { + 2685 + } else if v == "2686" { + 2686 + } else if v == "2687" { + 2687 + } else if v == "2688" { + 2688 + } else if v == "2689" { + 2689 + } else if v == "2690" { + 2690 + } else if v == "2691" { + 2691 + } else if v == "2692" { + 2692 + } else if v == "2693" { + 2693 + } else if v == "2694" { + 2694 + } else if v == "2695" { + 2695 + } else if v == "2696" { + 2696 + } else if v == "2697" { + 2697 + } else if v == "2698" { + 2698 + } else if v == "2699" { + 2699 + } else if v == "2700" { + 2700 + } else if v == "2701" { + 2701 + } else if v == "2702" { + 2702 + } else if v == "2703" { + 2703 + } else if v == "2704" { + 2704 + } else if v == "2705" { + 2705 + } else if v == "2706" { + 2706 + } else if v == "2707" { + 2707 + } else if v == "2708" { + 2708 + } else if v == "2709" { + 2709 + } else if v == "2710" { + 2710 + } else if v == "2711" { + 2711 + } else if v == "2712" { + 2712 + } else if v == "2713" { + 2713 + } else if v == "2714" { + 2714 + } else if v == "2715" { + 2715 + } else if v == "2716" { + 2716 + } else if v == "2717" { + 2717 + } else if v == "2718" { + 2718 + } else if v == "2719" { + 2719 + } else if v == "2720" { + 2720 + } else if v == "2721" { + 2721 + } else if v == "2722" { + 2722 + } else if v == "2723" { + 2723 + } else if v == "2724" { + 2724 + } else if v == "2725" { + 2725 + } else if v == "2726" { + 2726 + } else if v == "2727" { + 2727 + } else if v == "2728" { + 2728 + } else if v == "2729" { + 2729 + } else if v == "2730" { + 2730 + } else if v == "2731" { + 2731 + } else if v == "2732" { + 2732 + } else if v == "2733" { + 2733 + } else if v == "2734" { + 2734 + } else if v == "2735" { + 2735 + } else if v == "2736" { + 2736 + } else if v == "2737" { + 2737 + } else if v == "2738" { + 2738 + } else if v == "2739" { + 2739 + } else if v == "2740" { + 2740 + } else if v == "2741" { + 2741 + } else if v == "2742" { + 2742 + } else if v == "2743" { + 2743 + } else if v == "2744" { + 2744 + } else if v == "2745" { + 2745 + } else if v == "2746" { + 2746 + } else if v == "2747" { + 2747 + } else if v == "2748" { + 2748 + } else if v == "2749" { + 2749 + } else if v == "2750" { + 2750 + } else if v == "2751" { + 2751 + } else if v == "2752" { + 2752 + } else if v == "2753" { + 2753 + } else if v == "2754" { + 2754 + } else if v == "2755" { + 2755 + } else if v == "2756" { + 2756 + } else if v == "2757" { + 2757 + } else if v == "2758" { + 2758 + } else if v == "2759" { + 2759 + } else if v == "2760" { + 2760 + } else if v == "2761" { + 2761 + } else if v == "2762" { + 2762 + } else if v == "2763" { + 2763 + } else if v == "2764" { + 2764 + } else if v == "2765" { + 2765 + } else if v == "2766" { + 2766 + } else if v == "2767" { + 2767 + } else if v == "2768" { + 2768 + } else if v == "2769" { + 2769 + } else if v == "2770" { + 2770 + } else if v == "2771" { + 2771 + } else if v == "2772" { + 2772 + } else if v == "2773" { + 2773 + } else if v == "2774" { + 2774 + } else if v == "2775" { + 2775 + } else if v == "2776" { + 2776 + } else if v == "2777" { + 2777 + } else if v == "2778" { + 2778 + } else if v == "2779" { + 2779 + } else if v == "2780" { + 2780 + } else if v == "2781" { + 2781 + } else if v == "2782" { + 2782 + } else if v == "2783" { + 2783 + } else if v == "2784" { + 2784 + } else if v == "2785" { + 2785 + } else if v == "2786" { + 2786 + } else if v == "2787" { + 2787 + } else if v == "2788" { + 2788 + } else if v == "2789" { + 2789 + } else if v == "2790" { + 2790 + } else if v == "2791" { + 2791 + } else if v == "2792" { + 2792 + } else if v == "2793" { + 2793 + } else if v == "2794" { + 2794 + } else if v == "2795" { + 2795 + } else if v == "2796" { + 2796 + } else if v == "2797" { + 2797 + } else if v == "2798" { + 2798 + } else if v == "2799" { + 2799 + } else if v == "2800" { + 2800 + } else if v == "2801" { + 2801 + } else if v == "2802" { + 2802 + } else if v == "2803" { + 2803 + } else if v == "2804" { + 2804 + } else if v == "2805" { + 2805 + } else if v == "2806" { + 2806 + } else if v == "2807" { + 2807 + } else if v == "2808" { + 2808 + } else if v == "2809" { + 2809 + } else if v == "2810" { + 2810 + } else if v == "2811" { + 2811 + } else if v == "2812" { + 2812 + } else if v == "2813" { + 2813 + } else if v == "2814" { + 2814 + } else if v == "2815" { + 2815 + } else if v == "2816" { + 2816 + } else if v == "2817" { + 2817 + } else if v == "2818" { + 2818 + } else if v == "2819" { + 2819 + } else if v == "2820" { + 2820 + } else if v == "2821" { + 2821 + } else if v == "2822" { + 2822 + } else if v == "2823" { + 2823 + } else if v == "2824" { + 2824 + } else if v == "2825" { + 2825 + } else if v == "2826" { + 2826 + } else if v == "2827" { + 2827 + } else if v == "2828" { + 2828 + } else if v == "2829" { + 2829 + } else if v == "2830" { + 2830 + } else if v == "2831" { + 2831 + } else if v == "2832" { + 2832 + } else if v == "2833" { + 2833 + } else if v == "2834" { + 2834 + } else if v == "2835" { + 2835 + } else if v == "2836" { + 2836 + } else if v == "2837" { + 2837 + } else if v == "2838" { + 2838 + } else if v == "2839" { + 2839 + } else if v == "2840" { + 2840 + } else if v == "2841" { + 2841 + } else if v == "2842" { + 2842 + } else if v == "2843" { + 2843 + } else if v == "2844" { + 2844 + } else if v == "2845" { + 2845 + } else if v == "2846" { + 2846 + } else if v == "2847" { + 2847 + } else if v == "2848" { + 2848 + } else if v == "2849" { + 2849 + } else if v == "2850" { + 2850 + } else if v == "2851" { + 2851 + } else if v == "2852" { + 2852 + } else if v == "2853" { + 2853 + } else if v == "2854" { + 2854 + } else if v == "2855" { + 2855 + } else if v == "2856" { + 2856 + } else if v == "2857" { + 2857 + } else if v == "2858" { + 2858 + } else if v == "2859" { + 2859 + } else if v == "2860" { + 2860 + } else if v == "2861" { + 2861 + } else if v == "2862" { + 2862 + } else if v == "2863" { + 2863 + } else if v == "2864" { + 2864 + } else if v == "2865" { + 2865 + } else if v == "2866" { + 2866 + } else if v == "2867" { + 2867 + } else if v == "2868" { + 2868 + } else if v == "2869" { + 2869 + } else if v == "2870" { + 2870 + } else if v == "2871" { + 2871 + } else if v == "2872" { + 2872 + } else if v == "2873" { + 2873 + } else if v == "2874" { + 2874 + } else if v == "2875" { + 2875 + } else if v == "2876" { + 2876 + } else if v == "2877" { + 2877 + } else if v == "2878" { + 2878 + } else if v == "2879" { + 2879 + } else if v == "2880" { + 2880 + } else if v == "2881" { + 2881 + } else if v == "2882" { + 2882 + } else if v == "2883" { + 2883 + } else if v == "2884" { + 2884 + } else if v == "2885" { + 2885 + } else if v == "2886" { + 2886 + } else if v == "2887" { + 2887 + } else if v == "2888" { + 2888 + } else if v == "2889" { + 2889 + } else if v == "2890" { + 2890 + } else if v == "2891" { + 2891 + } else if v == "2892" { + 2892 + } else if v == "2893" { + 2893 + } else if v == "2894" { + 2894 + } else if v == "2895" { + 2895 + } else if v == "2896" { + 2896 + } else if v == "2897" { + 2897 + } else if v == "2898" { + 2898 + } else if v == "2899" { + 2899 + } else if v == "2900" { + 2900 + } else if v == "2901" { + 2901 + } else if v == "2902" { + 2902 + } else if v == "2903" { + 2903 + } else if v == "2904" { + 2904 + } else if v == "2905" { + 2905 + } else if v == "2906" { + 2906 + } else if v == "2907" { + 2907 + } else if v == "2908" { + 2908 + } else if v == "2909" { + 2909 + } else if v == "2910" { + 2910 + } else if v == "2911" { + 2911 + } else if v == "2912" { + 2912 + } else if v == "2913" { + 2913 + } else if v == "2914" { + 2914 + } else if v == "2915" { + 2915 + } else if v == "2916" { + 2916 + } else if v == "2917" { + 2917 + } else if v == "2918" { + 2918 + } else if v == "2919" { + 2919 + } else if v == "2920" { + 2920 + } else if v == "2921" { + 2921 + } else if v == "2922" { + 2922 + } else if v == "2923" { + 2923 + } else if v == "2924" { + 2924 + } else if v == "2925" { + 2925 + } else if v == "2926" { + 2926 + } else if v == "2927" { + 2927 + } else if v == "2928" { + 2928 + } else if v == "2929" { + 2929 + } else if v == "2930" { + 2930 + } else if v == "2931" { + 2931 + } else if v == "2932" { + 2932 + } else if v == "2933" { + 2933 + } else if v == "2934" { + 2934 + } else if v == "2935" { + 2935 + } else if v == "2936" { + 2936 + } else if v == "2937" { + 2937 + } else if v == "2938" { + 2938 + } else if v == "2939" { + 2939 + } else if v == "2940" { + 2940 + } else if v == "2941" { + 2941 + } else if v == "2942" { + 2942 + } else if v == "2943" { + 2943 + } else if v == "2944" { + 2944 + } else if v == "2945" { + 2945 + } else if v == "2946" { + 2946 + } else if v == "2947" { + 2947 + } else if v == "2948" { + 2948 + } else if v == "2949" { + 2949 + } else if v == "2950" { + 2950 + } else if v == "2951" { + 2951 + } else if v == "2952" { + 2952 + } else if v == "2953" { + 2953 + } else if v == "2954" { + 2954 + } else if v == "2955" { + 2955 + } else if v == "2956" { + 2956 + } else if v == "2957" { + 2957 + } else if v == "2958" { + 2958 + } else if v == "2959" { + 2959 + } else if v == "2960" { + 2960 + } else if v == "2961" { + 2961 + } else if v == "2962" { + 2962 + } else if v == "2963" { + 2963 + } else if v == "2964" { + 2964 + } else if v == "2965" { + 2965 + } else if v == "2966" { + 2966 + } else if v == "2967" { + 2967 + } else if v == "2968" { + 2968 + } else if v == "2969" { + 2969 + } else if v == "2970" { + 2970 + } else if v == "2971" { + 2971 + } else if v == "2972" { + 2972 + } else if v == "2973" { + 2973 + } else if v == "2974" { + 2974 + } else if v == "2975" { + 2975 + } else if v == "2976" { + 2976 + } else if v == "2977" { + 2977 + } else if v == "2978" { + 2978 + } else if v == "2979" { + 2979 + } else if v == "2980" { + 2980 + } else if v == "2981" { + 2981 + } else if v == "2982" { + 2982 + } else if v == "2983" { + 2983 + } else if v == "2984" { + 2984 + } else if v == "2985" { + 2985 + } else if v == "2986" { + 2986 + } else if v == "2987" { + 2987 + } else if v == "2988" { + 2988 + } else if v == "2989" { + 2989 + } else if v == "2990" { + 2990 + } else if v == "2991" { + 2991 + } else if v == "2992" { + 2992 + } else if v == "2993" { + 2993 + } else if v == "2994" { + 2994 + } else if v == "2995" { + 2995 + } else if v == "2996" { + 2996 + } else if v == "2997" { + 2997 + } else if v == "2998" { + 2998 + } else if v == "2999" { + 2999 + } else if v == "3000" { + 3000 + } else if v == "3001" { + 3001 + } else if v == "3002" { + 3002 + } else if v == "3003" { + 3003 + } else if v == "3004" { + 3004 + } else if v == "3005" { + 3005 + } else if v == "3006" { + 3006 + } else if v == "3007" { + 3007 + } else if v == "3008" { + 3008 + } else if v == "3009" { + 3009 + } else if v == "3010" { + 3010 + } else if v == "3011" { + 3011 + } else if v == "3012" { + 3012 + } else if v == "3013" { + 3013 + } else if v == "3014" { + 3014 + } else if v == "3015" { + 3015 + } else if v == "3016" { + 3016 + } else if v == "3017" { + 3017 + } else if v == "3018" { + 3018 + } else if v == "3019" { + 3019 + } else if v == "3020" { + 3020 + } else if v == "3021" { + 3021 + } else if v == "3022" { + 3022 + } else if v == "3023" { + 3023 + } else if v == "3024" { + 3024 + } else if v == "3025" { + 3025 + } else if v == "3026" { + 3026 + } else if v == "3027" { + 3027 + } else if v == "3028" { + 3028 + } else if v == "3029" { + 3029 + } else if v == "3030" { + 3030 + } else if v == "3031" { + 3031 + } else if v == "3032" { + 3032 + } else if v == "3033" { + 3033 + } else if v == "3034" { + 3034 + } else if v == "3035" { + 3035 + } else if v == "3036" { + 3036 + } else if v == "3037" { + 3037 + } else if v == "3038" { + 3038 + } else if v == "3039" { + 3039 + } else if v == "3040" { + 3040 + } else if v == "3041" { + 3041 + } else if v == "3042" { + 3042 + } else if v == "3043" { + 3043 + } else if v == "3044" { + 3044 + } else if v == "3045" { + 3045 + } else if v == "3046" { + 3046 + } else if v == "3047" { + 3047 + } else if v == "3048" { + 3048 + } else if v == "3049" { + 3049 + } else if v == "3050" { + 3050 + } else if v == "3051" { + 3051 + } else if v == "3052" { + 3052 + } else if v == "3053" { + 3053 + } else if v == "3054" { + 3054 + } else if v == "3055" { + 3055 + } else if v == "3056" { + 3056 + } else if v == "3057" { + 3057 + } else if v == "3058" { + 3058 + } else if v == "3059" { + 3059 + } else if v == "3060" { + 3060 + } else if v == "3061" { + 3061 + } else if v == "3062" { + 3062 + } else if v == "3063" { + 3063 + } else if v == "3064" { + 3064 + } else if v == "3065" { + 3065 + } else if v == "3066" { + 3066 + } else if v == "3067" { + 3067 + } else if v == "3068" { + 3068 + } else if v == "3069" { + 3069 + } else if v == "3070" { + 3070 + } else if v == "3071" { + 3071 + } else if v == "3072" { + 3072 + } else if v == "3073" { + 3073 + } else if v == "3074" { + 3074 + } else if v == "3075" { + 3075 + } else if v == "3076" { + 3076 + } else if v == "3077" { + 3077 + } else if v == "3078" { + 3078 + } else if v == "3079" { + 3079 + } else if v == "3080" { + 3080 + } else if v == "3081" { + 3081 + } else if v == "3082" { + 3082 + } else if v == "3083" { + 3083 + } else if v == "3084" { + 3084 + } else if v == "3085" { + 3085 + } else if v == "3086" { + 3086 + } else if v == "3087" { + 3087 + } else if v == "3088" { + 3088 + } else if v == "3089" { + 3089 + } else if v == "3090" { + 3090 + } else if v == "3091" { + 3091 + } else if v == "3092" { + 3092 + } else if v == "3093" { + 3093 + } else if v == "3094" { + 3094 + } else if v == "3095" { + 3095 + } else if v == "3096" { + 3096 + } else if v == "3097" { + 3097 + } else if v == "3098" { + 3098 + } else if v == "3099" { + 3099 + } else if v == "3100" { + 3100 + } else if v == "3101" { + 3101 + } else if v == "3102" { + 3102 + } else if v == "3103" { + 3103 + } else if v == "3104" { + 3104 + } else if v == "3105" { + 3105 + } else if v == "3106" { + 3106 + } else if v == "3107" { + 3107 + } else if v == "3108" { + 3108 + } else if v == "3109" { + 3109 + } else if v == "3110" { + 3110 + } else if v == "3111" { + 3111 + } else if v == "3112" { + 3112 + } else if v == "3113" { + 3113 + } else if v == "3114" { + 3114 + } else if v == "3115" { + 3115 + } else if v == "3116" { + 3116 + } else if v == "3117" { + 3117 + } else if v == "3118" { + 3118 + } else if v == "3119" { + 3119 + } else if v == "3120" { + 3120 + } else if v == "3121" { + 3121 + } else if v == "3122" { + 3122 + } else if v == "3123" { + 3123 + } else if v == "3124" { + 3124 + } else if v == "3125" { + 3125 + } else if v == "3126" { + 3126 + } else if v == "3127" { + 3127 + } else if v == "3128" { + 3128 + } else if v == "3129" { + 3129 + } else if v == "3130" { + 3130 + } else if v == "3131" { + 3131 + } else if v == "3132" { + 3132 + } else if v == "3133" { + 3133 + } else if v == "3134" { + 3134 + } else if v == "3135" { + 3135 + } else if v == "3136" { + 3136 + } else if v == "3137" { + 3137 + } else if v == "3138" { + 3138 + } else if v == "3139" { + 3139 + } else if v == "3140" { + 3140 + } else if v == "3141" { + 3141 + } else if v == "3142" { + 3142 + } else if v == "3143" { + 3143 + } else if v == "3144" { + 3144 + } else if v == "3145" { + 3145 + } else if v == "3146" { + 3146 + } else if v == "3147" { + 3147 + } else if v == "3148" { + 3148 + } else if v == "3149" { + 3149 + } else if v == "3150" { + 3150 + } else if v == "3151" { + 3151 + } else if v == "3152" { + 3152 + } else if v == "3153" { + 3153 + } else if v == "3154" { + 3154 + } else if v == "3155" { + 3155 + } else if v == "3156" { + 3156 + } else if v == "3157" { + 3157 + } else if v == "3158" { + 3158 + } else if v == "3159" { + 3159 + } else if v == "3160" { + 3160 + } else if v == "3161" { + 3161 + } else if v == "3162" { + 3162 + } else if v == "3163" { + 3163 + } else if v == "3164" { + 3164 + } else if v == "3165" { + 3165 + } else if v == "3166" { + 3166 + } else if v == "3167" { + 3167 + } else if v == "3168" { + 3168 + } else if v == "3169" { + 3169 + } else if v == "3170" { + 3170 + } else if v == "3171" { + 3171 + } else if v == "3172" { + 3172 + } else if v == "3173" { + 3173 + } else if v == "3174" { + 3174 + } else if v == "3175" { + 3175 + } else if v == "3176" { + 3176 + } else if v == "3177" { + 3177 + } else if v == "3178" { + 3178 + } else if v == "3179" { + 3179 + } else if v == "3180" { + 3180 + } else if v == "3181" { + 3181 + } else if v == "3182" { + 3182 + } else if v == "3183" { + 3183 + } else if v == "3184" { + 3184 + } else if v == "3185" { + 3185 + } else if v == "3186" { + 3186 + } else if v == "3187" { + 3187 + } else if v == "3188" { + 3188 + } else if v == "3189" { + 3189 + } else if v == "3190" { + 3190 + } else if v == "3191" { + 3191 + } else if v == "3192" { + 3192 + } else if v == "3193" { + 3193 + } else if v == "3194" { + 3194 + } else if v == "3195" { + 3195 + } else if v == "3196" { + 3196 + } else if v == "3197" { + 3197 + } else if v == "3198" { + 3198 + } else if v == "3199" { + 3199 + } else if v == "3200" { + 3200 + } else if v == "3201" { + 3201 + } else if v == "3202" { + 3202 + } else if v == "3203" { + 3203 + } else if v == "3204" { + 3204 + } else if v == "3205" { + 3205 + } else if v == "3206" { + 3206 + } else if v == "3207" { + 3207 + } else if v == "3208" { + 3208 + } else if v == "3209" { + 3209 + } else if v == "3210" { + 3210 + } else if v == "3211" { + 3211 + } else if v == "3212" { + 3212 + } else if v == "3213" { + 3213 + } else if v == "3214" { + 3214 + } else if v == "3215" { + 3215 + } else if v == "3216" { + 3216 + } else if v == "3217" { + 3217 + } else if v == "3218" { + 3218 + } else if v == "3219" { + 3219 + } else if v == "3220" { + 3220 + } else if v == "3221" { + 3221 + } else if v == "3222" { + 3222 + } else if v == "3223" { + 3223 + } else if v == "3224" { + 3224 + } else if v == "3225" { + 3225 + } else if v == "3226" { + 3226 + } else if v == "3227" { + 3227 + } else if v == "3228" { + 3228 + } else if v == "3229" { + 3229 + } else if v == "3230" { + 3230 + } else if v == "3231" { + 3231 + } else if v == "3232" { + 3232 + } else if v == "3233" { + 3233 + } else if v == "3234" { + 3234 + } else if v == "3235" { + 3235 + } else if v == "3236" { + 3236 + } else if v == "3237" { + 3237 + } else if v == "3238" { + 3238 + } else if v == "3239" { + 3239 + } else if v == "3240" { + 3240 + } else if v == "3241" { + 3241 + } else if v == "3242" { + 3242 + } else if v == "3243" { + 3243 + } else if v == "3244" { + 3244 + } else if v == "3245" { + 3245 + } else if v == "3246" { + 3246 + } else if v == "3247" { + 3247 + } else if v == "3248" { + 3248 + } else if v == "3249" { + 3249 + } else if v == "3250" { + 3250 + } else if v == "3251" { + 3251 + } else if v == "3252" { + 3252 + } else if v == "3253" { + 3253 + } else if v == "3254" { + 3254 + } else if v == "3255" { + 3255 + } else if v == "3256" { + 3256 + } else if v == "3257" { + 3257 + } else if v == "3258" { + 3258 + } else if v == "3259" { + 3259 + } else if v == "3260" { + 3260 + } else if v == "3261" { + 3261 + } else if v == "3262" { + 3262 + } else if v == "3263" { + 3263 + } else if v == "3264" { + 3264 + } else if v == "3265" { + 3265 + } else if v == "3266" { + 3266 + } else if v == "3267" { + 3267 + } else if v == "3268" { + 3268 + } else if v == "3269" { + 3269 + } else if v == "3270" { + 3270 + } else if v == "3271" { + 3271 + } else if v == "3272" { + 3272 + } else if v == "3273" { + 3273 + } else if v == "3274" { + 3274 + } else if v == "3275" { + 3275 + } else if v == "3276" { + 3276 + } else if v == "3277" { + 3277 + } else if v == "3278" { + 3278 + } else if v == "3279" { + 3279 + } else if v == "3280" { + 3280 + } else if v == "3281" { + 3281 + } else if v == "3282" { + 3282 + } else if v == "3283" { + 3283 + } else if v == "3284" { + 3284 + } else if v == "3285" { + 3285 + } else if v == "3286" { + 3286 + } else if v == "3287" { + 3287 + } else if v == "3288" { + 3288 + } else if v == "3289" { + 3289 + } else if v == "3290" { + 3290 + } else if v == "3291" { + 3291 + } else if v == "3292" { + 3292 + } else if v == "3293" { + 3293 + } else if v == "3294" { + 3294 + } else if v == "3295" { + 3295 + } else if v == "3296" { + 3296 + } else if v == "3297" { + 3297 + } else if v == "3298" { + 3298 + } else if v == "3299" { + 3299 + } else if v == "3300" { + 3300 + } else if v == "3301" { + 3301 + } else if v == "3302" { + 3302 + } else if v == "3303" { + 3303 + } else if v == "3304" { + 3304 + } else if v == "3305" { + 3305 + } else if v == "3306" { + 3306 + } else if v == "3307" { + 3307 + } else if v == "3308" { + 3308 + } else if v == "3309" { + 3309 + } else if v == "3310" { + 3310 + } else if v == "3311" { + 3311 + } else if v == "3312" { + 3312 + } else if v == "3313" { + 3313 + } else if v == "3314" { + 3314 + } else if v == "3315" { + 3315 + } else if v == "3316" { + 3316 + } else if v == "3317" { + 3317 + } else if v == "3318" { + 3318 + } else if v == "3319" { + 3319 + } else if v == "3320" { + 3320 + } else if v == "3321" { + 3321 + } else if v == "3322" { + 3322 + } else if v == "3323" { + 3323 + } else if v == "3324" { + 3324 + } else if v == "3325" { + 3325 + } else if v == "3326" { + 3326 + } else if v == "3327" { + 3327 + } else if v == "3328" { + 3328 + } else if v == "3329" { + 3329 + } else if v == "3330" { + 3330 + } else if v == "3331" { + 3331 + } else if v == "3332" { + 3332 + } else if v == "3333" { + 3333 + } else if v == "3334" { + 3334 + } else if v == "3335" { + 3335 + } else if v == "3336" { + 3336 + } else if v == "3337" { + 3337 + } else if v == "3338" { + 3338 + } else if v == "3339" { + 3339 + } else if v == "3340" { + 3340 + } else if v == "3341" { + 3341 + } else if v == "3342" { + 3342 + } else if v == "3343" { + 3343 + } else if v == "3344" { + 3344 + } else if v == "3345" { + 3345 + } else if v == "3346" { + 3346 + } else if v == "3347" { + 3347 + } else if v == "3348" { + 3348 + } else if v == "3349" { + 3349 + } else if v == "3350" { + 3350 + } else if v == "3351" { + 3351 + } else if v == "3352" { + 3352 + } else if v == "3353" { + 3353 + } else if v == "3354" { + 3354 + } else if v == "3355" { + 3355 + } else if v == "3356" { + 3356 + } else if v == "3357" { + 3357 + } else if v == "3358" { + 3358 + } else if v == "3359" { + 3359 + } else if v == "3360" { + 3360 + } else if v == "3361" { + 3361 + } else if v == "3362" { + 3362 + } else if v == "3363" { + 3363 + } else if v == "3364" { + 3364 + } else if v == "3365" { + 3365 + } else if v == "3366" { + 3366 + } else if v == "3367" { + 3367 + } else if v == "3368" { + 3368 + } else if v == "3369" { + 3369 + } else if v == "3370" { + 3370 + } else if v == "3371" { + 3371 + } else if v == "3372" { + 3372 + } else if v == "3373" { + 3373 + } else if v == "3374" { + 3374 + } else if v == "3375" { + 3375 + } else if v == "3376" { + 3376 + } else if v == "3377" { + 3377 + } else if v == "3378" { + 3378 + } else if v == "3379" { + 3379 + } else if v == "3380" { + 3380 + } else if v == "3381" { + 3381 + } else if v == "3382" { + 3382 + } else if v == "3383" { + 3383 + } else if v == "3384" { + 3384 + } else if v == "3385" { + 3385 + } else if v == "3386" { + 3386 + } else if v == "3387" { + 3387 + } else if v == "3388" { + 3388 + } else if v == "3389" { + 3389 + } else if v == "3390" { + 3390 + } else if v == "3391" { + 3391 + } else if v == "3392" { + 3392 + } else if v == "3393" { + 3393 + } else if v == "3394" { + 3394 + } else if v == "3395" { + 3395 + } else if v == "3396" { + 3396 + } else if v == "3397" { + 3397 + } else if v == "3398" { + 3398 + } else if v == "3399" { + 3399 + } else if v == "3400" { + 3400 + } else if v == "3401" { + 3401 + } else if v == "3402" { + 3402 + } else if v == "3403" { + 3403 + } else if v == "3404" { + 3404 + } else if v == "3405" { + 3405 + } else if v == "3406" { + 3406 + } else if v == "3407" { + 3407 + } else if v == "3408" { + 3408 + } else if v == "3409" { + 3409 + } else if v == "3410" { + 3410 + } else if v == "3411" { + 3411 + } else if v == "3412" { + 3412 + } else if v == "3413" { + 3413 + } else if v == "3414" { + 3414 + } else if v == "3415" { + 3415 + } else if v == "3416" { + 3416 + } else if v == "3417" { + 3417 + } else if v == "3418" { + 3418 + } else if v == "3419" { + 3419 + } else if v == "3420" { + 3420 + } else if v == "3421" { + 3421 + } else if v == "3422" { + 3422 + } else if v == "3423" { + 3423 + } else if v == "3424" { + 3424 + } else if v == "3425" { + 3425 + } else if v == "3426" { + 3426 + } else if v == "3427" { + 3427 + } else if v == "3428" { + 3428 + } else if v == "3429" { + 3429 + } else if v == "3430" { + 3430 + } else if v == "3431" { + 3431 + } else if v == "3432" { + 3432 + } else if v == "3433" { + 3433 + } else if v == "3434" { + 3434 + } else if v == "3435" { + 3435 + } else if v == "3436" { + 3436 + } else if v == "3437" { + 3437 + } else if v == "3438" { + 3438 + } else if v == "3439" { + 3439 + } else if v == "3440" { + 3440 + } else if v == "3441" { + 3441 + } else if v == "3442" { + 3442 + } else if v == "3443" { + 3443 + } else if v == "3444" { + 3444 + } else if v == "3445" { + 3445 + } else if v == "3446" { + 3446 + } else if v == "3447" { + 3447 + } else if v == "3448" { + 3448 + } else if v == "3449" { + 3449 + } else if v == "3450" { + 3450 + } else if v == "3451" { + 3451 + } else if v == "3452" { + 3452 + } else if v == "3453" { + 3453 + } else if v == "3454" { + 3454 + } else if v == "3455" { + 3455 + } else if v == "3456" { + 3456 + } else if v == "3457" { + 3457 + } else if v == "3458" { + 3458 + } else if v == "3459" { + 3459 + } else if v == "3460" { + 3460 + } else if v == "3461" { + 3461 + } else if v == "3462" { + 3462 + } else if v == "3463" { + 3463 + } else if v == "3464" { + 3464 + } else if v == "3465" { + 3465 + } else if v == "3466" { + 3466 + } else if v == "3467" { + 3467 + } else if v == "3468" { + 3468 + } else if v == "3469" { + 3469 + } else if v == "3470" { + 3470 + } else if v == "3471" { + 3471 + } else if v == "3472" { + 3472 + } else if v == "3473" { + 3473 + } else if v == "3474" { + 3474 + } else if v == "3475" { + 3475 + } else if v == "3476" { + 3476 + } else if v == "3477" { + 3477 + } else if v == "3478" { + 3478 + } else if v == "3479" { + 3479 + } else if v == "3480" { + 3480 + } else if v == "3481" { + 3481 + } else if v == "3482" { + 3482 + } else if v == "3483" { + 3483 + } else if v == "3484" { + 3484 + } else if v == "3485" { + 3485 + } else if v == "3486" { + 3486 + } else if v == "3487" { + 3487 + } else if v == "3488" { + 3488 + } else if v == "3489" { + 3489 + } else if v == "3490" { + 3490 + } else if v == "3491" { + 3491 + } else if v == "3492" { + 3492 + } else if v == "3493" { + 3493 + } else if v == "3494" { + 3494 + } else if v == "3495" { + 3495 + } else if v == "3496" { + 3496 + } else if v == "3497" { + 3497 + } else if v == "3498" { + 3498 + } else if v == "3499" { + 3499 + } else if v == "3500" { + 3500 + } else if v == "3501" { + 3501 + } else if v == "3502" { + 3502 + } else if v == "3503" { + 3503 + } else if v == "3504" { + 3504 + } else if v == "3505" { + 3505 + } else if v == "3506" { + 3506 + } else if v == "3507" { + 3507 + } else if v == "3508" { + 3508 + } else if v == "3509" { + 3509 + } else if v == "3510" { + 3510 + } else if v == "3511" { + 3511 + } else if v == "3512" { + 3512 + } else if v == "3513" { + 3513 + } else if v == "3514" { + 3514 + } else if v == "3515" { + 3515 + } else if v == "3516" { + 3516 + } else if v == "3517" { + 3517 + } else if v == "3518" { + 3518 + } else if v == "3519" { + 3519 + } else if v == "3520" { + 3520 + } else if v == "3521" { + 3521 + } else if v == "3522" { + 3522 + } else if v == "3523" { + 3523 + } else if v == "3524" { + 3524 + } else if v == "3525" { + 3525 + } else if v == "3526" { + 3526 + } else if v == "3527" { + 3527 + } else if v == "3528" { + 3528 + } else if v == "3529" { + 3529 + } else if v == "3530" { + 3530 + } else if v == "3531" { + 3531 + } else if v == "3532" { + 3532 + } else if v == "3533" { + 3533 + } else if v == "3534" { + 3534 + } else if v == "3535" { + 3535 + } else if v == "3536" { + 3536 + } else if v == "3537" { + 3537 + } else if v == "3538" { + 3538 + } else if v == "3539" { + 3539 + } else if v == "3540" { + 3540 + } else if v == "3541" { + 3541 + } else if v == "3542" { + 3542 + } else if v == "3543" { + 3543 + } else if v == "3544" { + 3544 + } else if v == "3545" { + 3545 + } else if v == "3546" { + 3546 + } else if v == "3547" { + 3547 + } else if v == "3548" { + 3548 + } else if v == "3549" { + 3549 + } else if v == "3550" { + 3550 + } else if v == "3551" { + 3551 + } else if v == "3552" { + 3552 + } else if v == "3553" { + 3553 + } else if v == "3554" { + 3554 + } else if v == "3555" { + 3555 + } else if v == "3556" { + 3556 + } else if v == "3557" { + 3557 + } else if v == "3558" { + 3558 + } else if v == "3559" { + 3559 + } else if v == "3560" { + 3560 + } else if v == "3561" { + 3561 + } else if v == "3562" { + 3562 + } else if v == "3563" { + 3563 + } else if v == "3564" { + 3564 + } else if v == "3565" { + 3565 + } else if v == "3566" { + 3566 + } else if v == "3567" { + 3567 + } else if v == "3568" { + 3568 + } else if v == "3569" { + 3569 + } else if v == "3570" { + 3570 + } else if v == "3571" { + 3571 + } else if v == "3572" { + 3572 + } else if v == "3573" { + 3573 + } else if v == "3574" { + 3574 + } else if v == "3575" { + 3575 + } else if v == "3576" { + 3576 + } else if v == "3577" { + 3577 + } else if v == "3578" { + 3578 + } else if v == "3579" { + 3579 + } else if v == "3580" { + 3580 + } else if v == "3581" { + 3581 + } else if v == "3582" { + 3582 + } else if v == "3583" { + 3583 + } else if v == "3584" { + 3584 + } else if v == "3585" { + 3585 + } else if v == "3586" { + 3586 + } else if v == "3587" { + 3587 + } else if v == "3588" { + 3588 + } else if v == "3589" { + 3589 + } else if v == "3590" { + 3590 + } else if v == "3591" { + 3591 + } else if v == "3592" { + 3592 + } else if v == "3593" { + 3593 + } else if v == "3594" { + 3594 + } else if v == "3595" { + 3595 + } else if v == "3596" { + 3596 + } else if v == "3597" { + 3597 + } else if v == "3598" { + 3598 + } else if v == "3599" { + 3599 + } else if v == "3600" { + 3600 + } else if v == "3601" { + 3601 + } else if v == "3602" { + 3602 + } else if v == "3603" { + 3603 + } else if v == "3604" { + 3604 + } else if v == "3605" { + 3605 + } else if v == "3606" { + 3606 + } else if v == "3607" { + 3607 + } else if v == "3608" { + 3608 + } else if v == "3609" { + 3609 + } else if v == "3610" { + 3610 + } else if v == "3611" { + 3611 + } else if v == "3612" { + 3612 + } else if v == "3613" { + 3613 + } else if v == "3614" { + 3614 + } else if v == "3615" { + 3615 + } else if v == "3616" { + 3616 + } else if v == "3617" { + 3617 + } else if v == "3618" { + 3618 + } else if v == "3619" { + 3619 + } else if v == "3620" { + 3620 + } else if v == "3621" { + 3621 + } else if v == "3622" { + 3622 + } else if v == "3623" { + 3623 + } else if v == "3624" { + 3624 + } else if v == "3625" { + 3625 + } else if v == "3626" { + 3626 + } else if v == "3627" { + 3627 + } else if v == "3628" { + 3628 + } else if v == "3629" { + 3629 + } else if v == "3630" { + 3630 + } else if v == "3631" { + 3631 + } else if v == "3632" { + 3632 + } else if v == "3633" { + 3633 + } else if v == "3634" { + 3634 + } else if v == "3635" { + 3635 + } else if v == "3636" { + 3636 + } else if v == "3637" { + 3637 + } else if v == "3638" { + 3638 + } else if v == "3639" { + 3639 + } else if v == "3640" { + 3640 + } else if v == "3641" { + 3641 + } else if v == "3642" { + 3642 + } else if v == "3643" { + 3643 + } else if v == "3644" { + 3644 + } else if v == "3645" { + 3645 + } else if v == "3646" { + 3646 + } else if v == "3647" { + 3647 + } else if v == "3648" { + 3648 + } else if v == "3649" { + 3649 + } else if v == "3650" { + 3650 + } else if v == "3651" { + 3651 + } else if v == "3652" { + 3652 + } else if v == "3653" { + 3653 + } else if v == "3654" { + 3654 + } else if v == "3655" { + 3655 + } else if v == "3656" { + 3656 + } else if v == "3657" { + 3657 + } else if v == "3658" { + 3658 + } else if v == "3659" { + 3659 + } else if v == "3660" { + 3660 + } else if v == "3661" { + 3661 + } else if v == "3662" { + 3662 + } else if v == "3663" { + 3663 + } else if v == "3664" { + 3664 + } else if v == "3665" { + 3665 + } else if v == "3666" { + 3666 + } else if v == "3667" { + 3667 + } else if v == "3668" { + 3668 + } else if v == "3669" { + 3669 + } else if v == "3670" { + 3670 + } else if v == "3671" { + 3671 + } else if v == "3672" { + 3672 + } else if v == "3673" { + 3673 + } else if v == "3674" { + 3674 + } else if v == "3675" { + 3675 + } else if v == "3676" { + 3676 + } else if v == "3677" { + 3677 + } else if v == "3678" { + 3678 + } else if v == "3679" { + 3679 + } else if v == "3680" { + 3680 + } else if v == "3681" { + 3681 + } else if v == "3682" { + 3682 + } else if v == "3683" { + 3683 + } else if v == "3684" { + 3684 + } else if v == "3685" { + 3685 + } else if v == "3686" { + 3686 + } else if v == "3687" { + 3687 + } else if v == "3688" { + 3688 + } else if v == "3689" { + 3689 + } else if v == "3690" { + 3690 + } else if v == "3691" { + 3691 + } else if v == "3692" { + 3692 + } else if v == "3693" { + 3693 + } else if v == "3694" { + 3694 + } else if v == "3695" { + 3695 + } else if v == "3696" { + 3696 + } else if v == "3697" { + 3697 + } else if v == "3698" { + 3698 + } else if v == "3699" { + 3699 + } else if v == "3700" { + 3700 + } else if v == "3701" { + 3701 + } else if v == "3702" { + 3702 + } else if v == "3703" { + 3703 + } else if v == "3704" { + 3704 + } else if v == "3705" { + 3705 + } else if v == "3706" { + 3706 + } else if v == "3707" { + 3707 + } else if v == "3708" { + 3708 + } else if v == "3709" { + 3709 + } else if v == "3710" { + 3710 + } else if v == "3711" { + 3711 + } else if v == "3712" { + 3712 + } else if v == "3713" { + 3713 + } else if v == "3714" { + 3714 + } else if v == "3715" { + 3715 + } else if v == "3716" { + 3716 + } else if v == "3717" { + 3717 + } else if v == "3718" { + 3718 + } else if v == "3719" { + 3719 + } else if v == "3720" { + 3720 + } else if v == "3721" { + 3721 + } else if v == "3722" { + 3722 + } else if v == "3723" { + 3723 + } else if v == "3724" { + 3724 + } else if v == "3725" { + 3725 + } else if v == "3726" { + 3726 + } else if v == "3727" { + 3727 + } else if v == "3728" { + 3728 + } else if v == "3729" { + 3729 + } else if v == "3730" { + 3730 + } else if v == "3731" { + 3731 + } else if v == "3732" { + 3732 + } else if v == "3733" { + 3733 + } else if v == "3734" { + 3734 + } else if v == "3735" { + 3735 + } else if v == "3736" { + 3736 + } else if v == "3737" { + 3737 + } else if v == "3738" { + 3738 + } else if v == "3739" { + 3739 + } else if v == "3740" { + 3740 + } else if v == "3741" { + 3741 + } else if v == "3742" { + 3742 + } else if v == "3743" { + 3743 + } else if v == "3744" { + 3744 + } else if v == "3745" { + 3745 + } else if v == "3746" { + 3746 + } else if v == "3747" { + 3747 + } else if v == "3748" { + 3748 + } else if v == "3749" { + 3749 + } else if v == "3750" { + 3750 + } else if v == "3751" { + 3751 + } else if v == "3752" { + 3752 + } else if v == "3753" { + 3753 + } else if v == "3754" { + 3754 + } else if v == "3755" { + 3755 + } else if v == "3756" { + 3756 + } else if v == "3757" { + 3757 + } else if v == "3758" { + 3758 + } else if v == "3759" { + 3759 + } else if v == "3760" { + 3760 + } else if v == "3761" { + 3761 + } else if v == "3762" { + 3762 + } else if v == "3763" { + 3763 + } else if v == "3764" { + 3764 + } else if v == "3765" { + 3765 + } else if v == "3766" { + 3766 + } else if v == "3767" { + 3767 + } else if v == "3768" { + 3768 + } else if v == "3769" { + 3769 + } else if v == "3770" { + 3770 + } else if v == "3771" { + 3771 + } else if v == "3772" { + 3772 + } else if v == "3773" { + 3773 + } else if v == "3774" { + 3774 + } else if v == "3775" { + 3775 + } else if v == "3776" { + 3776 + } else if v == "3777" { + 3777 + } else if v == "3778" { + 3778 + } else if v == "3779" { + 3779 + } else if v == "3780" { + 3780 + } else if v == "3781" { + 3781 + } else if v == "3782" { + 3782 + } else if v == "3783" { + 3783 + } else if v == "3784" { + 3784 + } else if v == "3785" { + 3785 + } else if v == "3786" { + 3786 + } else if v == "3787" { + 3787 + } else if v == "3788" { + 3788 + } else if v == "3789" { + 3789 + } else if v == "3790" { + 3790 + } else if v == "3791" { + 3791 + } else if v == "3792" { + 3792 + } else if v == "3793" { + 3793 + } else if v == "3794" { + 3794 + } else if v == "3795" { + 3795 + } else if v == "3796" { + 3796 + } else if v == "3797" { + 3797 + } else if v == "3798" { + 3798 + } else if v == "3799" { + 3799 + } else if v == "3800" { + 3800 + } else if v == "3801" { + 3801 + } else if v == "3802" { + 3802 + } else if v == "3803" { + 3803 + } else if v == "3804" { + 3804 + } else if v == "3805" { + 3805 + } else if v == "3806" { + 3806 + } else if v == "3807" { + 3807 + } else if v == "3808" { + 3808 + } else if v == "3809" { + 3809 + } else if v == "3810" { + 3810 + } else if v == "3811" { + 3811 + } else if v == "3812" { + 3812 + } else if v == "3813" { + 3813 + } else if v == "3814" { + 3814 + } else if v == "3815" { + 3815 + } else if v == "3816" { + 3816 + } else if v == "3817" { + 3817 + } else if v == "3818" { + 3818 + } else if v == "3819" { + 3819 + } else if v == "3820" { + 3820 + } else if v == "3821" { + 3821 + } else if v == "3822" { + 3822 + } else if v == "3823" { + 3823 + } else if v == "3824" { + 3824 + } else if v == "3825" { + 3825 + } else if v == "3826" { + 3826 + } else if v == "3827" { + 3827 + } else if v == "3828" { + 3828 + } else if v == "3829" { + 3829 + } else if v == "3830" { + 3830 + } else if v == "3831" { + 3831 + } else if v == "3832" { + 3832 + } else if v == "3833" { + 3833 + } else if v == "3834" { + 3834 + } else if v == "3835" { + 3835 + } else if v == "3836" { + 3836 + } else if v == "3837" { + 3837 + } else if v == "3838" { + 3838 + } else if v == "3839" { + 3839 + } else if v == "3840" { + 3840 + } else if v == "3841" { + 3841 + } else if v == "3842" { + 3842 + } else if v == "3843" { + 3843 + } else if v == "3844" { + 3844 + } else if v == "3845" { + 3845 + } else if v == "3846" { + 3846 + } else if v == "3847" { + 3847 + } else if v == "3848" { + 3848 + } else if v == "3849" { + 3849 + } else if v == "3850" { + 3850 + } else if v == "3851" { + 3851 + } else if v == "3852" { + 3852 + } else if v == "3853" { + 3853 + } else if v == "3854" { + 3854 + } else if v == "3855" { + 3855 + } else if v == "3856" { + 3856 + } else if v == "3857" { + 3857 + } else if v == "3858" { + 3858 + } else if v == "3859" { + 3859 + } else if v == "3860" { + 3860 + } else if v == "3861" { + 3861 + } else if v == "3862" { + 3862 + } else if v == "3863" { + 3863 + } else if v == "3864" { + 3864 + } else if v == "3865" { + 3865 + } else if v == "3866" { + 3866 + } else if v == "3867" { + 3867 + } else if v == "3868" { + 3868 + } else if v == "3869" { + 3869 + } else if v == "3870" { + 3870 + } else if v == "3871" { + 3871 + } else if v == "3872" { + 3872 + } else if v == "3873" { + 3873 + } else if v == "3874" { + 3874 + } else if v == "3875" { + 3875 + } else if v == "3876" { + 3876 + } else if v == "3877" { + 3877 + } else if v == "3878" { + 3878 + } else if v == "3879" { + 3879 + } else if v == "3880" { + 3880 + } else if v == "3881" { + 3881 + } else if v == "3882" { + 3882 + } else if v == "3883" { + 3883 + } else if v == "3884" { + 3884 + } else if v == "3885" { + 3885 + } else if v == "3886" { + 3886 + } else if v == "3887" { + 3887 + } else if v == "3888" { + 3888 + } else if v == "3889" { + 3889 + } else if v == "3890" { + 3890 + } else if v == "3891" { + 3891 + } else if v == "3892" { + 3892 + } else if v == "3893" { + 3893 + } else if v == "3894" { + 3894 + } else if v == "3895" { + 3895 + } else if v == "3896" { + 3896 + } else if v == "3897" { + 3897 + } else if v == "3898" { + 3898 + } else if v == "3899" { + 3899 + } else if v == "3900" { + 3900 + } else if v == "3901" { + 3901 + } else if v == "3902" { + 3902 + } else if v == "3903" { + 3903 + } else if v == "3904" { + 3904 + } else if v == "3905" { + 3905 + } else if v == "3906" { + 3906 + } else if v == "3907" { + 3907 + } else if v == "3908" { + 3908 + } else if v == "3909" { + 3909 + } else if v == "3910" { + 3910 + } else if v == "3911" { + 3911 + } else if v == "3912" { + 3912 + } else if v == "3913" { + 3913 + } else if v == "3914" { + 3914 + } else if v == "3915" { + 3915 + } else if v == "3916" { + 3916 + } else if v == "3917" { + 3917 + } else if v == "3918" { + 3918 + } else if v == "3919" { + 3919 + } else if v == "3920" { + 3920 + } else if v == "3921" { + 3921 + } else if v == "3922" { + 3922 + } else if v == "3923" { + 3923 + } else if v == "3924" { + 3924 + } else if v == "3925" { + 3925 + } else if v == "3926" { + 3926 + } else if v == "3927" { + 3927 + } else if v == "3928" { + 3928 + } else if v == "3929" { + 3929 + } else if v == "3930" { + 3930 + } else if v == "3931" { + 3931 + } else if v == "3932" { + 3932 + } else if v == "3933" { + 3933 + } else if v == "3934" { + 3934 + } else if v == "3935" { + 3935 + } else if v == "3936" { + 3936 + } else if v == "3937" { + 3937 + } else if v == "3938" { + 3938 + } else if v == "3939" { + 3939 + } else if v == "3940" { + 3940 + } else if v == "3941" { + 3941 + } else if v == "3942" { + 3942 + } else if v == "3943" { + 3943 + } else if v == "3944" { + 3944 + } else if v == "3945" { + 3945 + } else if v == "3946" { + 3946 + } else if v == "3947" { + 3947 + } else if v == "3948" { + 3948 + } else if v == "3949" { + 3949 + } else if v == "3950" { + 3950 + } else if v == "3951" { + 3951 + } else if v == "3952" { + 3952 + } else if v == "3953" { + 3953 + } else if v == "3954" { + 3954 + } else if v == "3955" { + 3955 + } else if v == "3956" { + 3956 + } else if v == "3957" { + 3957 + } else if v == "3958" { + 3958 + } else if v == "3959" { + 3959 + } else if v == "3960" { + 3960 + } else if v == "3961" { + 3961 + } else if v == "3962" { + 3962 + } else if v == "3963" { + 3963 + } else if v == "3964" { + 3964 + } else if v == "3965" { + 3965 + } else if v == "3966" { + 3966 + } else if v == "3967" { + 3967 + } else if v == "3968" { + 3968 + } else if v == "3969" { + 3969 + } else if v == "3970" { + 3970 + } else if v == "3971" { + 3971 + } else if v == "3972" { + 3972 + } else if v == "3973" { + 3973 + } else if v == "3974" { + 3974 + } else if v == "3975" { + 3975 + } else if v == "3976" { + 3976 + } else if v == "3977" { + 3977 + } else if v == "3978" { + 3978 + } else if v == "3979" { + 3979 + } else if v == "3980" { + 3980 + } else if v == "3981" { + 3981 + } else if v == "3982" { + 3982 + } else if v == "3983" { + 3983 + } else if v == "3984" { + 3984 + } else if v == "3985" { + 3985 + } else if v == "3986" { + 3986 + } else if v == "3987" { + 3987 + } else if v == "3988" { + 3988 + } else if v == "3989" { + 3989 + } else if v == "3990" { + 3990 + } else if v == "3991" { + 3991 + } else if v == "3992" { + 3992 + } else if v == "3993" { + 3993 + } else if v == "3994" { + 3994 + } else if v == "3995" { + 3995 + } else if v == "3996" { + 3996 + } else if v == "3997" { + 3997 + } else if v == "3998" { + 3998 + } else if v == "3999" { + 3999 + } else if v == "4000" { + 4000 + } else if v == "4001" { + 4001 + } else if v == "4002" { + 4002 + } else if v == "4003" { + 4003 + } else if v == "4004" { + 4004 + } else if v == "4005" { + 4005 + } else if v == "4006" { + 4006 + } else if v == "4007" { + 4007 + } else if v == "4008" { + 4008 + } else if v == "4009" { + 4009 + } else if v == "4010" { + 4010 + } else if v == "4011" { + 4011 + } else if v == "4012" { + 4012 + } else if v == "4013" { + 4013 + } else if v == "4014" { + 4014 + } else if v == "4015" { + 4015 + } else if v == "4016" { + 4016 + } else if v == "4017" { + 4017 + } else if v == "4018" { + 4018 + } else if v == "4019" { + 4019 + } else if v == "4020" { + 4020 + } else if v == "4021" { + 4021 + } else if v == "4022" { + 4022 + } else if v == "4023" { + 4023 + } else if v == "4024" { + 4024 + } else if v == "4025" { + 4025 + } else if v == "4026" { + 4026 + } else if v == "4027" { + 4027 + } else if v == "4028" { + 4028 + } else if v == "4029" { + 4029 + } else if v == "4030" { + 4030 + } else if v == "4031" { + 4031 + } else if v == "4032" { + 4032 + } else if v == "4033" { + 4033 + } else if v == "4034" { + 4034 + } else if v == "4035" { + 4035 + } else if v == "4036" { + 4036 + } else if v == "4037" { + 4037 + } else if v == "4038" { + 4038 + } else if v == "4039" { + 4039 + } else if v == "4040" { + 4040 + } else if v == "4041" { + 4041 + } else if v == "4042" { + 4042 + } else if v == "4043" { + 4043 + } else if v == "4044" { + 4044 + } else if v == "4045" { + 4045 + } else if v == "4046" { + 4046 + } else if v == "4047" { + 4047 + } else if v == "4048" { + 4048 + } else if v == "4049" { + 4049 + } else if v == "4050" { + 4050 + } else if v == "4051" { + 4051 + } else if v == "4052" { + 4052 + } else if v == "4053" { + 4053 + } else if v == "4054" { + 4054 + } else if v == "4055" { + 4055 + } else if v == "4056" { + 4056 + } else if v == "4057" { + 4057 + } else if v == "4058" { + 4058 + } else if v == "4059" { + 4059 + } else if v == "4060" { + 4060 + } else if v == "4061" { + 4061 + } else if v == "4062" { + 4062 + } else if v == "4063" { + 4063 + } else if v == "4064" { + 4064 + } else if v == "4065" { + 4065 + } else if v == "4066" { + 4066 + } else if v == "4067" { + 4067 + } else if v == "4068" { + 4068 + } else if v == "4069" { + 4069 + } else if v == "4070" { + 4070 + } else if v == "4071" { + 4071 + } else if v == "4072" { + 4072 + } else if v == "4073" { + 4073 + } else if v == "4074" { + 4074 + } else if v == "4075" { + 4075 + } else if v == "4076" { + 4076 + } else if v == "4077" { + 4077 + } else if v == "4078" { + 4078 + } else if v == "4079" { + 4079 + } else if v == "4080" { + 4080 + } else if v == "4081" { + 4081 + } else if v == "4082" { + 4082 + } else if v == "4083" { + 4083 + } else if v == "4084" { + 4084 + } else if v == "4085" { + 4085 + } else if v == "4086" { + 4086 + } else if v == "4087" { + 4087 + } else if v == "4088" { + 4088 + } else if v == "4089" { + 4089 + } else if v == "4090" { + 4090 + } else if v == "4091" { + 4091 + } else if v == "4092" { + 4092 + } else if v == "4093" { + 4093 + } else if v == "4094" { + 4094 + } else if v == "4095" { + 4095 + } else if v == "4096" { + 4096 + } else if v == "4097" { + 4097 + } else if v == "4098" { + 4098 + } else if v == "4099" { + 4099 + } else if v == "4100" { + 4100 + } else if v == "4101" { + 4101 + } else if v == "4102" { + 4102 + } else if v == "4103" { + 4103 + } else if v == "4104" { + 4104 + } else if v == "4105" { + 4105 + } else if v == "4106" { + 4106 + } else if v == "4107" { + 4107 + } else if v == "4108" { + 4108 + } else if v == "4109" { + 4109 + } else if v == "4110" { + 4110 + } else if v == "4111" { + 4111 + } else if v == "4112" { + 4112 + } else if v == "4113" { + 4113 + } else if v == "4114" { + 4114 + } else if v == "4115" { + 4115 + } else if v == "4116" { + 4116 + } else if v == "4117" { + 4117 + } else if v == "4118" { + 4118 + } else if v == "4119" { + 4119 + } else if v == "4120" { + 4120 + } else if v == "4121" { + 4121 + } else if v == "4122" { + 4122 + } else if v == "4123" { + 4123 + } else if v == "4124" { + 4124 + } else if v == "4125" { + 4125 + } else if v == "4126" { + 4126 + } else if v == "4127" { + 4127 + } else if v == "4128" { + 4128 + } else if v == "4129" { + 4129 + } else if v == "4130" { + 4130 + } else if v == "4131" { + 4131 + } else if v == "4132" { + 4132 + } else if v == "4133" { + 4133 + } else if v == "4134" { + 4134 + } else if v == "4135" { + 4135 + } else if v == "4136" { + 4136 + } else if v == "4137" { + 4137 + } else if v == "4138" { + 4138 + } else if v == "4139" { + 4139 + } else if v == "4140" { + 4140 + } else if v == "4141" { + 4141 + } else if v == "4142" { + 4142 + } else if v == "4143" { + 4143 + } else if v == "4144" { + 4144 + } else if v == "4145" { + 4145 + } else if v == "4146" { + 4146 + } else if v == "4147" { + 4147 + } else if v == "4148" { + 4148 + } else if v == "4149" { + 4149 + } else if v == "4150" { + 4150 + } else if v == "4151" { + 4151 + } else if v == "4152" { + 4152 + } else if v == "4153" { + 4153 + } else if v == "4154" { + 4154 + } else if v == "4155" { + 4155 + } else if v == "4156" { + 4156 + } else if v == "4157" { + 4157 + } else if v == "4158" { + 4158 + } else if v == "4159" { + 4159 + } else if v == "4160" { + 4160 + } else if v == "4161" { + 4161 + } else if v == "4162" { + 4162 + } else if v == "4163" { + 4163 + } else if v == "4164" { + 4164 + } else if v == "4165" { + 4165 + } else if v == "4166" { + 4166 + } else if v == "4167" { + 4167 + } else if v == "4168" { + 4168 + } else if v == "4169" { + 4169 + } else if v == "4170" { + 4170 + } else if v == "4171" { + 4171 + } else if v == "4172" { + 4172 + } else if v == "4173" { + 4173 + } else if v == "4174" { + 4174 + } else if v == "4175" { + 4175 + } else if v == "4176" { + 4176 + } else if v == "4177" { + 4177 + } else if v == "4178" { + 4178 + } else if v == "4179" { + 4179 + } else if v == "4180" { + 4180 + } else if v == "4181" { + 4181 + } else if v == "4182" { + 4182 + } else if v == "4183" { + 4183 + } else if v == "4184" { + 4184 + } else if v == "4185" { + 4185 + } else if v == "4186" { + 4186 + } else if v == "4187" { + 4187 + } else if v == "4188" { + 4188 + } else if v == "4189" { + 4189 + } else if v == "4190" { + 4190 + } else if v == "4191" { + 4191 + } else if v == "4192" { + 4192 + } else if v == "4193" { + 4193 + } else if v == "4194" { + 4194 + } else if v == "4195" { + 4195 + } else if v == "4196" { + 4196 + } else if v == "4197" { + 4197 + } else if v == "4198" { + 4198 + } else if v == "4199" { + 4199 + } else if v == "4200" { + 4200 + } else if v == "4201" { + 4201 + } else if v == "4202" { + 4202 + } else if v == "4203" { + 4203 + } else if v == "4204" { + 4204 + } else if v == "4205" { + 4205 + } else if v == "4206" { + 4206 + } else if v == "4207" { + 4207 + } else if v == "4208" { + 4208 + } else if v == "4209" { + 4209 + } else if v == "4210" { + 4210 + } else if v == "4211" { + 4211 + } else if v == "4212" { + 4212 + } else if v == "4213" { + 4213 + } else if v == "4214" { + 4214 + } else if v == "4215" { + 4215 + } else if v == "4216" { + 4216 + } else if v == "4217" { + 4217 + } else if v == "4218" { + 4218 + } else if v == "4219" { + 4219 + } else if v == "4220" { + 4220 + } else if v == "4221" { + 4221 + } else if v == "4222" { + 4222 + } else if v == "4223" { + 4223 + } else if v == "4224" { + 4224 + } else if v == "4225" { + 4225 + } else if v == "4226" { + 4226 + } else if v == "4227" { + 4227 + } else if v == "4228" { + 4228 + } else if v == "4229" { + 4229 + } else if v == "4230" { + 4230 + } else if v == "4231" { + 4231 + } else if v == "4232" { + 4232 + } else if v == "4233" { + 4233 + } else if v == "4234" { + 4234 + } else if v == "4235" { + 4235 + } else if v == "4236" { + 4236 + } else if v == "4237" { + 4237 + } else if v == "4238" { + 4238 + } else if v == "4239" { + 4239 + } else if v == "4240" { + 4240 + } else if v == "4241" { + 4241 + } else if v == "4242" { + 4242 + } else if v == "4243" { + 4243 + } else if v == "4244" { + 4244 + } else if v == "4245" { + 4245 + } else if v == "4246" { + 4246 + } else if v == "4247" { + 4247 + } else if v == "4248" { + 4248 + } else if v == "4249" { + 4249 + } else if v == "4250" { + 4250 + } else if v == "4251" { + 4251 + } else if v == "4252" { + 4252 + } else if v == "4253" { + 4253 + } else if v == "4254" { + 4254 + } else if v == "4255" { + 4255 + } else if v == "4256" { + 4256 + } else if v == "4257" { + 4257 + } else if v == "4258" { + 4258 + } else if v == "4259" { + 4259 + } else if v == "4260" { + 4260 + } else if v == "4261" { + 4261 + } else if v == "4262" { + 4262 + } else if v == "4263" { + 4263 + } else if v == "4264" { + 4264 + } else if v == "4265" { + 4265 + } else if v == "4266" { + 4266 + } else if v == "4267" { + 4267 + } else if v == "4268" { + 4268 + } else if v == "4269" { + 4269 + } else if v == "4270" { + 4270 + } else if v == "4271" { + 4271 + } else if v == "4272" { + 4272 + } else if v == "4273" { + 4273 + } else if v == "4274" { + 4274 + } else if v == "4275" { + 4275 + } else if v == "4276" { + 4276 + } else if v == "4277" { + 4277 + } else if v == "4278" { + 4278 + } else if v == "4279" { + 4279 + } else if v == "4280" { + 4280 + } else if v == "4281" { + 4281 + } else if v == "4282" { + 4282 + } else if v == "4283" { + 4283 + } else if v == "4284" { + 4284 + } else if v == "4285" { + 4285 + } else if v == "4286" { + 4286 + } else if v == "4287" { + 4287 + } else if v == "4288" { + 4288 + } else if v == "4289" { + 4289 + } else if v == "4290" { + 4290 + } else if v == "4291" { + 4291 + } else if v == "4292" { + 4292 + } else if v == "4293" { + 4293 + } else if v == "4294" { + 4294 + } else if v == "4295" { + 4295 + } else if v == "4296" { + 4296 + } else if v == "4297" { + 4297 + } else if v == "4298" { + 4298 + } else if v == "4299" { + 4299 + } else if v == "4300" { + 4300 + } else if v == "4301" { + 4301 + } else if v == "4302" { + 4302 + } else if v == "4303" { + 4303 + } else if v == "4304" { + 4304 + } else if v == "4305" { + 4305 + } else if v == "4306" { + 4306 + } else if v == "4307" { + 4307 + } else if v == "4308" { + 4308 + } else if v == "4309" { + 4309 + } else if v == "4310" { + 4310 + } else if v == "4311" { + 4311 + } else if v == "4312" { + 4312 + } else if v == "4313" { + 4313 + } else if v == "4314" { + 4314 + } else if v == "4315" { + 4315 + } else if v == "4316" { + 4316 + } else if v == "4317" { + 4317 + } else if v == "4318" { + 4318 + } else if v == "4319" { + 4319 + } else if v == "4320" { + 4320 + } else if v == "4321" { + 4321 + } else if v == "4322" { + 4322 + } else if v == "4323" { + 4323 + } else if v == "4324" { + 4324 + } else if v == "4325" { + 4325 + } else if v == "4326" { + 4326 + } else if v == "4327" { + 4327 + } else if v == "4328" { + 4328 + } else if v == "4329" { + 4329 + } else if v == "4330" { + 4330 + } else if v == "4331" { + 4331 + } else if v == "4332" { + 4332 + } else if v == "4333" { + 4333 + } else if v == "4334" { + 4334 + } else if v == "4335" { + 4335 + } else if v == "4336" { + 4336 + } else if v == "4337" { + 4337 + } else if v == "4338" { + 4338 + } else if v == "4339" { + 4339 + } else if v == "4340" { + 4340 + } else if v == "4341" { + 4341 + } else if v == "4342" { + 4342 + } else if v == "4343" { + 4343 + } else if v == "4344" { + 4344 + } else if v == "4345" { + 4345 + } else if v == "4346" { + 4346 + } else if v == "4347" { + 4347 + } else if v == "4348" { + 4348 + } else if v == "4349" { + 4349 + } else if v == "4350" { + 4350 + } else if v == "4351" { + 4351 + } else if v == "4352" { + 4352 + } else if v == "4353" { + 4353 + } else if v == "4354" { + 4354 + } else if v == "4355" { + 4355 + } else if v == "4356" { + 4356 + } else if v == "4357" { + 4357 + } else if v == "4358" { + 4358 + } else if v == "4359" { + 4359 + } else if v == "4360" { + 4360 + } else if v == "4361" { + 4361 + } else if v == "4362" { + 4362 + } else if v == "4363" { + 4363 + } else if v == "4364" { + 4364 + } else if v == "4365" { + 4365 + } else if v == "4366" { + 4366 + } else if v == "4367" { + 4367 + } else if v == "4368" { + 4368 + } else if v == "4369" { + 4369 + } else if v == "4370" { + 4370 + } else if v == "4371" { + 4371 + } else if v == "4372" { + 4372 + } else if v == "4373" { + 4373 + } else if v == "4374" { + 4374 + } else if v == "4375" { + 4375 + } else if v == "4376" { + 4376 + } else if v == "4377" { + 4377 + } else if v == "4378" { + 4378 + } else if v == "4379" { + 4379 + } else if v == "4380" { + 4380 + } else if v == "4381" { + 4381 + } else if v == "4382" { + 4382 + } else if v == "4383" { + 4383 + } else if v == "4384" { + 4384 + } else if v == "4385" { + 4385 + } else if v == "4386" { + 4386 + } else if v == "4387" { + 4387 + } else if v == "4388" { + 4388 + } else if v == "4389" { + 4389 + } else if v == "4390" { + 4390 + } else if v == "4391" { + 4391 + } else if v == "4392" { + 4392 + } else if v == "4393" { + 4393 + } else if v == "4394" { + 4394 + } else if v == "4395" { + 4395 + } else if v == "4396" { + 4396 + } else if v == "4397" { + 4397 + } else if v == "4398" { + 4398 + } else if v == "4399" { + 4399 + } else if v == "4400" { + 4400 + } else if v == "4401" { + 4401 + } else if v == "4402" { + 4402 + } else if v == "4403" { + 4403 + } else if v == "4404" { + 4404 + } else if v == "4405" { + 4405 + } else if v == "4406" { + 4406 + } else if v == "4407" { + 4407 + } else if v == "4408" { + 4408 + } else if v == "4409" { + 4409 + } else if v == "4410" { + 4410 + } else if v == "4411" { + 4411 + } else if v == "4412" { + 4412 + } else if v == "4413" { + 4413 + } else if v == "4414" { + 4414 + } else if v == "4415" { + 4415 + } else if v == "4416" { + 4416 + } else if v == "4417" { + 4417 + } else if v == "4418" { + 4418 + } else if v == "4419" { + 4419 + } else if v == "4420" { + 4420 + } else if v == "4421" { + 4421 + } else if v == "4422" { + 4422 + } else if v == "4423" { + 4423 + } else if v == "4424" { + 4424 + } else if v == "4425" { + 4425 + } else if v == "4426" { + 4426 + } else if v == "4427" { + 4427 + } else if v == "4428" { + 4428 + } else if v == "4429" { + 4429 + } else if v == "4430" { + 4430 + } else if v == "4431" { + 4431 + } else if v == "4432" { + 4432 + } else if v == "4433" { + 4433 + } else if v == "4434" { + 4434 + } else if v == "4435" { + 4435 + } else if v == "4436" { + 4436 + } else if v == "4437" { + 4437 + } else if v == "4438" { + 4438 + } else if v == "4439" { + 4439 + } else if v == "4440" { + 4440 + } else if v == "4441" { + 4441 + } else if v == "4442" { + 4442 + } else if v == "4443" { + 4443 + } else if v == "4444" { + 4444 + } else if v == "4445" { + 4445 + } else if v == "4446" { + 4446 + } else if v == "4447" { + 4447 + } else if v == "4448" { + 4448 + } else if v == "4449" { + 4449 + } else if v == "4450" { + 4450 + } else if v == "4451" { + 4451 + } else if v == "4452" { + 4452 + } else if v == "4453" { + 4453 + } else if v == "4454" { + 4454 + } else if v == "4455" { + 4455 + } else if v == "4456" { + 4456 + } else if v == "4457" { + 4457 + } else if v == "4458" { + 4458 + } else if v == "4459" { + 4459 + } else if v == "4460" { + 4460 + } else if v == "4461" { + 4461 + } else if v == "4462" { + 4462 + } else if v == "4463" { + 4463 + } else if v == "4464" { + 4464 + } else if v == "4465" { + 4465 + } else if v == "4466" { + 4466 + } else if v == "4467" { + 4467 + } else if v == "4468" { + 4468 + } else if v == "4469" { + 4469 + } else if v == "4470" { + 4470 + } else if v == "4471" { + 4471 + } else if v == "4472" { + 4472 + } else if v == "4473" { + 4473 + } else if v == "4474" { + 4474 + } else if v == "4475" { + 4475 + } else if v == "4476" { + 4476 + } else if v == "4477" { + 4477 + } else if v == "4478" { + 4478 + } else if v == "4479" { + 4479 + } else if v == "4480" { + 4480 + } else if v == "4481" { + 4481 + } else if v == "4482" { + 4482 + } else if v == "4483" { + 4483 + } else if v == "4484" { + 4484 + } else if v == "4485" { + 4485 + } else if v == "4486" { + 4486 + } else if v == "4487" { + 4487 + } else if v == "4488" { + 4488 + } else if v == "4489" { + 4489 + } else if v == "4490" { + 4490 + } else if v == "4491" { + 4491 + } else if v == "4492" { + 4492 + } else if v == "4493" { + 4493 + } else if v == "4494" { + 4494 + } else if v == "4495" { + 4495 + } else if v == "4496" { + 4496 + } else if v == "4497" { + 4497 + } else if v == "4498" { + 4498 + } else if v == "4499" { + 4499 + } else if v == "4500" { + 4500 + } else if v == "4501" { + 4501 + } else if v == "4502" { + 4502 + } else if v == "4503" { + 4503 + } else if v == "4504" { + 4504 + } else if v == "4505" { + 4505 + } else if v == "4506" { + 4506 + } else if v == "4507" { + 4507 + } else if v == "4508" { + 4508 + } else if v == "4509" { + 4509 + } else if v == "4510" { + 4510 + } else if v == "4511" { + 4511 + } else if v == "4512" { + 4512 + } else if v == "4513" { + 4513 + } else if v == "4514" { + 4514 + } else if v == "4515" { + 4515 + } else if v == "4516" { + 4516 + } else if v == "4517" { + 4517 + } else if v == "4518" { + 4518 + } else if v == "4519" { + 4519 + } else if v == "4520" { + 4520 + } else if v == "4521" { + 4521 + } else if v == "4522" { + 4522 + } else if v == "4523" { + 4523 + } else if v == "4524" { + 4524 + } else if v == "4525" { + 4525 + } else if v == "4526" { + 4526 + } else if v == "4527" { + 4527 + } else if v == "4528" { + 4528 + } else if v == "4529" { + 4529 + } else if v == "4530" { + 4530 + } else if v == "4531" { + 4531 + } else if v == "4532" { + 4532 + } else if v == "4533" { + 4533 + } else if v == "4534" { + 4534 + } else if v == "4535" { + 4535 + } else if v == "4536" { + 4536 + } else if v == "4537" { + 4537 + } else if v == "4538" { + 4538 + } else if v == "4539" { + 4539 + } else if v == "4540" { + 4540 + } else if v == "4541" { + 4541 + } else if v == "4542" { + 4542 + } else if v == "4543" { + 4543 + } else if v == "4544" { + 4544 + } else if v == "4545" { + 4545 + } else if v == "4546" { + 4546 + } else if v == "4547" { + 4547 + } else if v == "4548" { + 4548 + } else if v == "4549" { + 4549 + } else if v == "4550" { + 4550 + } else if v == "4551" { + 4551 + } else if v == "4552" { + 4552 + } else if v == "4553" { + 4553 + } else if v == "4554" { + 4554 + } else if v == "4555" { + 4555 + } else if v == "4556" { + 4556 + } else if v == "4557" { + 4557 + } else if v == "4558" { + 4558 + } else if v == "4559" { + 4559 + } else if v == "4560" { + 4560 + } else if v == "4561" { + 4561 + } else if v == "4562" { + 4562 + } else if v == "4563" { + 4563 + } else if v == "4564" { + 4564 + } else if v == "4565" { + 4565 + } else if v == "4566" { + 4566 + } else if v == "4567" { + 4567 + } else if v == "4568" { + 4568 + } else if v == "4569" { + 4569 + } else if v == "4570" { + 4570 + } else if v == "4571" { + 4571 + } else if v == "4572" { + 4572 + } else if v == "4573" { + 4573 + } else if v == "4574" { + 4574 + } else if v == "4575" { + 4575 + } else if v == "4576" { + 4576 + } else if v == "4577" { + 4577 + } else if v == "4578" { + 4578 + } else if v == "4579" { + 4579 + } else if v == "4580" { + 4580 + } else if v == "4581" { + 4581 + } else if v == "4582" { + 4582 + } else if v == "4583" { + 4583 + } else if v == "4584" { + 4584 + } else if v == "4585" { + 4585 + } else if v == "4586" { + 4586 + } else if v == "4587" { + 4587 + } else if v == "4588" { + 4588 + } else if v == "4589" { + 4589 + } else if v == "4590" { + 4590 + } else if v == "4591" { + 4591 + } else if v == "4592" { + 4592 + } else if v == "4593" { + 4593 + } else if v == "4594" { + 4594 + } else if v == "4595" { + 4595 + } else if v == "4596" { + 4596 + } else if v == "4597" { + 4597 + } else if v == "4598" { + 4598 + } else if v == "4599" { + 4599 + } else if v == "4600" { + 4600 + } else if v == "4601" { + 4601 + } else if v == "4602" { + 4602 + } else if v == "4603" { + 4603 + } else if v == "4604" { + 4604 + } else if v == "4605" { + 4605 + } else if v == "4606" { + 4606 + } else if v == "4607" { + 4607 + } else if v == "4608" { + 4608 + } else if v == "4609" { + 4609 + } else if v == "4610" { + 4610 + } else if v == "4611" { + 4611 + } else if v == "4612" { + 4612 + } else if v == "4613" { + 4613 + } else if v == "4614" { + 4614 + } else if v == "4615" { + 4615 + } else if v == "4616" { + 4616 + } else if v == "4617" { + 4617 + } else if v == "4618" { + 4618 + } else if v == "4619" { + 4619 + } else if v == "4620" { + 4620 + } else if v == "4621" { + 4621 + } else if v == "4622" { + 4622 + } else if v == "4623" { + 4623 + } else if v == "4624" { + 4624 + } else if v == "4625" { + 4625 + } else if v == "4626" { + 4626 + } else if v == "4627" { + 4627 + } else if v == "4628" { + 4628 + } else if v == "4629" { + 4629 + } else if v == "4630" { + 4630 + } else if v == "4631" { + 4631 + } else if v == "4632" { + 4632 + } else if v == "4633" { + 4633 + } else if v == "4634" { + 4634 + } else if v == "4635" { + 4635 + } else if v == "4636" { + 4636 + } else if v == "4637" { + 4637 + } else if v == "4638" { + 4638 + } else if v == "4639" { + 4639 + } else if v == "4640" { + 4640 + } else if v == "4641" { + 4641 + } else if v == "4642" { + 4642 + } else if v == "4643" { + 4643 + } else if v == "4644" { + 4644 + } else if v == "4645" { + 4645 + } else if v == "4646" { + 4646 + } else if v == "4647" { + 4647 + } else if v == "4648" { + 4648 + } else if v == "4649" { + 4649 + } else if v == "4650" { + 4650 + } else if v == "4651" { + 4651 + } else if v == "4652" { + 4652 + } else if v == "4653" { + 4653 + } else if v == "4654" { + 4654 + } else if v == "4655" { + 4655 + } else if v == "4656" { + 4656 + } else if v == "4657" { + 4657 + } else if v == "4658" { + 4658 + } else if v == "4659" { + 4659 + } else if v == "4660" { + 4660 + } else if v == "4661" { + 4661 + } else if v == "4662" { + 4662 + } else if v == "4663" { + 4663 + } else if v == "4664" { + 4664 + } else if v == "4665" { + 4665 + } else if v == "4666" { + 4666 + } else if v == "4667" { + 4667 + } else if v == "4668" { + 4668 + } else if v == "4669" { + 4669 + } else if v == "4670" { + 4670 + } else if v == "4671" { + 4671 + } else if v == "4672" { + 4672 + } else if v == "4673" { + 4673 + } else if v == "4674" { + 4674 + } else if v == "4675" { + 4675 + } else if v == "4676" { + 4676 + } else if v == "4677" { + 4677 + } else if v == "4678" { + 4678 + } else if v == "4679" { + 4679 + } else if v == "4680" { + 4680 + } else if v == "4681" { + 4681 + } else if v == "4682" { + 4682 + } else if v == "4683" { + 4683 + } else if v == "4684" { + 4684 + } else if v == "4685" { + 4685 + } else if v == "4686" { + 4686 + } else if v == "4687" { + 4687 + } else if v == "4688" { + 4688 + } else if v == "4689" { + 4689 + } else if v == "4690" { + 4690 + } else if v == "4691" { + 4691 + } else if v == "4692" { + 4692 + } else if v == "4693" { + 4693 + } else if v == "4694" { + 4694 + } else if v == "4695" { + 4695 + } else if v == "4696" { + 4696 + } else if v == "4697" { + 4697 + } else if v == "4698" { + 4698 + } else if v == "4699" { + 4699 + } else if v == "4700" { + 4700 + } else if v == "4701" { + 4701 + } else if v == "4702" { + 4702 + } else if v == "4703" { + 4703 + } else if v == "4704" { + 4704 + } else if v == "4705" { + 4705 + } else if v == "4706" { + 4706 + } else if v == "4707" { + 4707 + } else if v == "4708" { + 4708 + } else if v == "4709" { + 4709 + } else if v == "4710" { + 4710 + } else if v == "4711" { + 4711 + } else if v == "4712" { + 4712 + } else if v == "4713" { + 4713 + } else if v == "4714" { + 4714 + } else if v == "4715" { + 4715 + } else if v == "4716" { + 4716 + } else if v == "4717" { + 4717 + } else if v == "4718" { + 4718 + } else if v == "4719" { + 4719 + } else if v == "4720" { + 4720 + } else if v == "4721" { + 4721 + } else if v == "4722" { + 4722 + } else if v == "4723" { + 4723 + } else if v == "4724" { + 4724 + } else if v == "4725" { + 4725 + } else if v == "4726" { + 4726 + } else if v == "4727" { + 4727 + } else if v == "4728" { + 4728 + } else if v == "4729" { + 4729 + } else if v == "4730" { + 4730 + } else if v == "4731" { + 4731 + } else if v == "4732" { + 4732 + } else if v == "4733" { + 4733 + } else if v == "4734" { + 4734 + } else if v == "4735" { + 4735 + } else if v == "4736" { + 4736 + } else if v == "4737" { + 4737 + } else if v == "4738" { + 4738 + } else if v == "4739" { + 4739 + } else if v == "4740" { + 4740 + } else if v == "4741" { + 4741 + } else if v == "4742" { + 4742 + } else if v == "4743" { + 4743 + } else if v == "4744" { + 4744 + } else if v == "4745" { + 4745 + } else if v == "4746" { + 4746 + } else if v == "4747" { + 4747 + } else if v == "4748" { + 4748 + } else if v == "4749" { + 4749 + } else if v == "4750" { + 4750 + } else if v == "4751" { + 4751 + } else if v == "4752" { + 4752 + } else if v == "4753" { + 4753 + } else if v == "4754" { + 4754 + } else if v == "4755" { + 4755 + } else if v == "4756" { + 4756 + } else if v == "4757" { + 4757 + } else if v == "4758" { + 4758 + } else if v == "4759" { + 4759 + } else if v == "4760" { + 4760 + } else if v == "4761" { + 4761 + } else if v == "4762" { + 4762 + } else if v == "4763" { + 4763 + } else if v == "4764" { + 4764 + } else if v == "4765" { + 4765 + } else if v == "4766" { + 4766 + } else if v == "4767" { + 4767 + } else if v == "4768" { + 4768 + } else if v == "4769" { + 4769 + } else if v == "4770" { + 4770 + } else if v == "4771" { + 4771 + } else if v == "4772" { + 4772 + } else if v == "4773" { + 4773 + } else if v == "4774" { + 4774 + } else if v == "4775" { + 4775 + } else if v == "4776" { + 4776 + } else if v == "4777" { + 4777 + } else if v == "4778" { + 4778 + } else if v == "4779" { + 4779 + } else if v == "4780" { + 4780 + } else if v == "4781" { + 4781 + } else if v == "4782" { + 4782 + } else if v == "4783" { + 4783 + } else if v == "4784" { + 4784 + } else if v == "4785" { + 4785 + } else if v == "4786" { + 4786 + } else if v == "4787" { + 4787 + } else if v == "4788" { + 4788 + } else if v == "4789" { + 4789 + } else if v == "4790" { + 4790 + } else if v == "4791" { + 4791 + } else if v == "4792" { + 4792 + } else if v == "4793" { + 4793 + } else if v == "4794" { + 4794 + } else if v == "4795" { + 4795 + } else if v == "4796" { + 4796 + } else if v == "4797" { + 4797 + } else if v == "4798" { + 4798 + } else if v == "4799" { + 4799 + } else if v == "4800" { + 4800 + } else if v == "4801" { + 4801 + } else if v == "4802" { + 4802 + } else if v == "4803" { + 4803 + } else if v == "4804" { + 4804 + } else if v == "4805" { + 4805 + } else if v == "4806" { + 4806 + } else if v == "4807" { + 4807 + } else if v == "4808" { + 4808 + } else if v == "4809" { + 4809 + } else if v == "4810" { + 4810 + } else if v == "4811" { + 4811 + } else if v == "4812" { + 4812 + } else if v == "4813" { + 4813 + } else if v == "4814" { + 4814 + } else if v == "4815" { + 4815 + } else if v == "4816" { + 4816 + } else if v == "4817" { + 4817 + } else if v == "4818" { + 4818 + } else if v == "4819" { + 4819 + } else if v == "4820" { + 4820 + } else if v == "4821" { + 4821 + } else if v == "4822" { + 4822 + } else if v == "4823" { + 4823 + } else if v == "4824" { + 4824 + } else if v == "4825" { + 4825 + } else if v == "4826" { + 4826 + } else if v == "4827" { + 4827 + } else if v == "4828" { + 4828 + } else if v == "4829" { + 4829 + } else if v == "4830" { + 4830 + } else if v == "4831" { + 4831 + } else if v == "4832" { + 4832 + } else if v == "4833" { + 4833 + } else if v == "4834" { + 4834 + } else if v == "4835" { + 4835 + } else if v == "4836" { + 4836 + } else if v == "4837" { + 4837 + } else if v == "4838" { + 4838 + } else if v == "4839" { + 4839 + } else if v == "4840" { + 4840 + } else if v == "4841" { + 4841 + } else if v == "4842" { + 4842 + } else if v == "4843" { + 4843 + } else if v == "4844" { + 4844 + } else if v == "4845" { + 4845 + } else if v == "4846" { + 4846 + } else if v == "4847" { + 4847 + } else if v == "4848" { + 4848 + } else if v == "4849" { + 4849 + } else if v == "4850" { + 4850 + } else if v == "4851" { + 4851 + } else if v == "4852" { + 4852 + } else if v == "4853" { + 4853 + } else if v == "4854" { + 4854 + } else if v == "4855" { + 4855 + } else if v == "4856" { + 4856 + } else if v == "4857" { + 4857 + } else if v == "4858" { + 4858 + } else if v == "4859" { + 4859 + } else if v == "4860" { + 4860 + } else if v == "4861" { + 4861 + } else if v == "4862" { + 4862 + } else if v == "4863" { + 4863 + } else if v == "4864" { + 4864 + } else if v == "4865" { + 4865 + } else if v == "4866" { + 4866 + } else if v == "4867" { + 4867 + } else if v == "4868" { + 4868 + } else if v == "4869" { + 4869 + } else if v == "4870" { + 4870 + } else if v == "4871" { + 4871 + } else if v == "4872" { + 4872 + } else if v == "4873" { + 4873 + } else if v == "4874" { + 4874 + } else if v == "4875" { + 4875 + } else if v == "4876" { + 4876 + } else if v == "4877" { + 4877 + } else if v == "4878" { + 4878 + } else if v == "4879" { + 4879 + } else if v == "4880" { + 4880 + } else if v == "4881" { + 4881 + } else if v == "4882" { + 4882 + } else if v == "4883" { + 4883 + } else if v == "4884" { + 4884 + } else if v == "4885" { + 4885 + } else if v == "4886" { + 4886 + } else if v == "4887" { + 4887 + } else if v == "4888" { + 4888 + } else if v == "4889" { + 4889 + } else if v == "4890" { + 4890 + } else if v == "4891" { + 4891 + } else if v == "4892" { + 4892 + } else if v == "4893" { + 4893 + } else if v == "4894" { + 4894 + } else if v == "4895" { + 4895 + } else if v == "4896" { + 4896 + } else if v == "4897" { + 4897 + } else if v == "4898" { + 4898 + } else if v == "4899" { + 4899 + } else if v == "4900" { + 4900 + } else if v == "4901" { + 4901 + } else if v == "4902" { + 4902 + } else if v == "4903" { + 4903 + } else if v == "4904" { + 4904 + } else if v == "4905" { + 4905 + } else if v == "4906" { + 4906 + } else if v == "4907" { + 4907 + } else if v == "4908" { + 4908 + } else if v == "4909" { + 4909 + } else if v == "4910" { + 4910 + } else if v == "4911" { + 4911 + } else if v == "4912" { + 4912 + } else if v == "4913" { + 4913 + } else if v == "4914" { + 4914 + } else if v == "4915" { + 4915 + } else if v == "4916" { + 4916 + } else if v == "4917" { + 4917 + } else if v == "4918" { + 4918 + } else if v == "4919" { + 4919 + } else if v == "4920" { + 4920 + } else if v == "4921" { + 4921 + } else if v == "4922" { + 4922 + } else if v == "4923" { + 4923 + } else if v == "4924" { + 4924 + } else if v == "4925" { + 4925 + } else if v == "4926" { + 4926 + } else if v == "4927" { + 4927 + } else if v == "4928" { + 4928 + } else if v == "4929" { + 4929 + } else if v == "4930" { + 4930 + } else if v == "4931" { + 4931 + } else if v == "4932" { + 4932 + } else if v == "4933" { + 4933 + } else if v == "4934" { + 4934 + } else if v == "4935" { + 4935 + } else if v == "4936" { + 4936 + } else if v == "4937" { + 4937 + } else if v == "4938" { + 4938 + } else if v == "4939" { + 4939 + } else if v == "4940" { + 4940 + } else if v == "4941" { + 4941 + } else if v == "4942" { + 4942 + } else if v == "4943" { + 4943 + } else if v == "4944" { + 4944 + } else if v == "4945" { + 4945 + } else if v == "4946" { + 4946 + } else if v == "4947" { + 4947 + } else if v == "4948" { + 4948 + } else if v == "4949" { + 4949 + } else if v == "4950" { + 4950 + } else if v == "4951" { + 4951 + } else if v == "4952" { + 4952 + } else if v == "4953" { + 4953 + } else if v == "4954" { + 4954 + } else if v == "4955" { + 4955 + } else if v == "4956" { + 4956 + } else if v == "4957" { + 4957 + } else if v == "4958" { + 4958 + } else if v == "4959" { + 4959 + } else if v == "4960" { + 4960 + } else if v == "4961" { + 4961 + } else if v == "4962" { + 4962 + } else if v == "4963" { + 4963 + } else if v == "4964" { + 4964 + } else if v == "4965" { + 4965 + } else if v == "4966" { + 4966 + } else if v == "4967" { + 4967 + } else if v == "4968" { + 4968 + } else if v == "4969" { + 4969 + } else if v == "4970" { + 4970 + } else if v == "4971" { + 4971 + } else if v == "4972" { + 4972 + } else if v == "4973" { + 4973 + } else if v == "4974" { + 4974 + } else if v == "4975" { + 4975 + } else if v == "4976" { + 4976 + } else if v == "4977" { + 4977 + } else if v == "4978" { + 4978 + } else if v == "4979" { + 4979 + } else if v == "4980" { + 4980 + } else if v == "4981" { + 4981 + } else if v == "4982" { + 4982 + } else if v == "4983" { + 4983 + } else if v == "4984" { + 4984 + } else if v == "4985" { + 4985 + } else if v == "4986" { + 4986 + } else if v == "4987" { + 4987 + } else if v == "4988" { + 4988 + } else if v == "4989" { + 4989 + } else if v == "4990" { + 4990 + } else if v == "4991" { + 4991 + } else if v == "4992" { + 4992 + } else if v == "4993" { + 4993 + } else if v == "4994" { + 4994 + } else if v == "4995" { + 4995 + } else if v == "4996" { + 4996 + } else if v == "4997" { + 4997 + } else if v == "4998" { + 4998 + } else if v == "4999" { + 4999 + } else if v == "5000" { + 5000 + } else if v == "5001" { + 5001 + } else if v == "5002" { + 5002 + } else if v == "5003" { + 5003 + } else if v == "5004" { + 5004 + } else if v == "5005" { + 5005 + } else if v == "5006" { + 5006 + } else if v == "5007" { + 5007 + } else if v == "5008" { + 5008 + } else if v == "5009" { + 5009 + } else if v == "5010" { + 5010 + } else if v == "5011" { + 5011 + } else if v == "5012" { + 5012 + } else if v == "5013" { + 5013 + } else if v == "5014" { + 5014 + } else if v == "5015" { + 5015 + } else if v == "5016" { + 5016 + } else if v == "5017" { + 5017 + } else if v == "5018" { + 5018 + } else if v == "5019" { + 5019 + } else if v == "5020" { + 5020 + } else if v == "5021" { + 5021 + } else if v == "5022" { + 5022 + } else if v == "5023" { + 5023 + } else if v == "5024" { + 5024 + } else if v == "5025" { + 5025 + } else if v == "5026" { + 5026 + } else if v == "5027" { + 5027 + } else if v == "5028" { + 5028 + } else if v == "5029" { + 5029 + } else if v == "5030" { + 5030 + } else if v == "5031" { + 5031 + } else if v == "5032" { + 5032 + } else if v == "5033" { + 5033 + } else if v == "5034" { + 5034 + } else if v == "5035" { + 5035 + } else if v == "5036" { + 5036 + } else if v == "5037" { + 5037 + } else if v == "5038" { + 5038 + } else if v == "5039" { + 5039 + } else if v == "5040" { + 5040 + } else if v == "5041" { + 5041 + } else if v == "5042" { + 5042 + } else if v == "5043" { + 5043 + } else if v == "5044" { + 5044 + } else if v == "5045" { + 5045 + } else if v == "5046" { + 5046 + } else if v == "5047" { + 5047 + } else if v == "5048" { + 5048 + } else if v == "5049" { + 5049 + } else if v == "5050" { + 5050 + } else if v == "5051" { + 5051 + } else if v == "5052" { + 5052 + } else if v == "5053" { + 5053 + } else if v == "5054" { + 5054 + } else if v == "5055" { + 5055 + } else if v == "5056" { + 5056 + } else if v == "5057" { + 5057 + } else if v == "5058" { + 5058 + } else if v == "5059" { + 5059 + } else if v == "5060" { + 5060 + } else if v == "5061" { + 5061 + } else if v == "5062" { + 5062 + } else if v == "5063" { + 5063 + } else if v == "5064" { + 5064 + } else if v == "5065" { + 5065 + } else if v == "5066" { + 5066 + } else if v == "5067" { + 5067 + } else if v == "5068" { + 5068 + } else if v == "5069" { + 5069 + } else if v == "5070" { + 5070 + } else if v == "5071" { + 5071 + } else if v == "5072" { + 5072 + } else if v == "5073" { + 5073 + } else if v == "5074" { + 5074 + } else if v == "5075" { + 5075 + } else if v == "5076" { + 5076 + } else if v == "5077" { + 5077 + } else if v == "5078" { + 5078 + } else if v == "5079" { + 5079 + } else if v == "5080" { + 5080 + } else if v == "5081" { + 5081 + } else if v == "5082" { + 5082 + } else if v == "5083" { + 5083 + } else if v == "5084" { + 5084 + } else if v == "5085" { + 5085 + } else if v == "5086" { + 5086 + } else if v == "5087" { + 5087 + } else if v == "5088" { + 5088 + } else if v == "5089" { + 5089 + } else if v == "5090" { + 5090 + } else if v == "5091" { + 5091 + } else if v == "5092" { + 5092 + } else if v == "5093" { + 5093 + } else if v == "5094" { + 5094 + } else if v == "5095" { + 5095 + } else if v == "5096" { + 5096 + } else if v == "5097" { + 5097 + } else if v == "5098" { + 5098 + } else if v == "5099" { + 5099 + } else if v == "5100" { + 5100 + } else if v == "5101" { + 5101 + } else if v == "5102" { + 5102 + } else if v == "5103" { + 5103 + } else if v == "5104" { + 5104 + } else if v == "5105" { + 5105 + } else if v == "5106" { + 5106 + } else if v == "5107" { + 5107 + } else if v == "5108" { + 5108 + } else if v == "5109" { + 5109 + } else if v == "5110" { + 5110 + } else if v == "5111" { + 5111 + } else if v == "5112" { + 5112 + } else if v == "5113" { + 5113 + } else if v == "5114" { + 5114 + } else if v == "5115" { + 5115 + } else if v == "5116" { + 5116 + } else if v == "5117" { + 5117 + } else if v == "5118" { + 5118 + } else if v == "5119" { + 5119 + } else if v == "5120" { + 5120 + } else if v == "5121" { + 5121 + } else if v == "5122" { + 5122 + } else if v == "5123" { + 5123 + } else if v == "5124" { + 5124 + } else if v == "5125" { + 5125 + } else if v == "5126" { + 5126 + } else if v == "5127" { + 5127 + } else if v == "5128" { + 5128 + } else if v == "5129" { + 5129 + } else if v == "5130" { + 5130 + } else if v == "5131" { + 5131 + } else if v == "5132" { + 5132 + } else if v == "5133" { + 5133 + } else if v == "5134" { + 5134 + } else if v == "5135" { + 5135 + } else if v == "5136" { + 5136 + } else if v == "5137" { + 5137 + } else if v == "5138" { + 5138 + } else if v == "5139" { + 5139 + } else if v == "5140" { + 5140 + } else if v == "5141" { + 5141 + } else if v == "5142" { + 5142 + } else if v == "5143" { + 5143 + } else if v == "5144" { + 5144 + } else if v == "5145" { + 5145 + } else if v == "5146" { + 5146 + } else if v == "5147" { + 5147 + } else if v == "5148" { + 5148 + } else if v == "5149" { + 5149 + } else if v == "5150" { + 5150 + } else if v == "5151" { + 5151 + } else if v == "5152" { + 5152 + } else if v == "5153" { + 5153 + } else if v == "5154" { + 5154 + } else if v == "5155" { + 5155 + } else if v == "5156" { + 5156 + } else if v == "5157" { + 5157 + } else if v == "5158" { + 5158 + } else if v == "5159" { + 5159 + } else if v == "5160" { + 5160 + } else if v == "5161" { + 5161 + } else if v == "5162" { + 5162 + } else if v == "5163" { + 5163 + } else if v == "5164" { + 5164 + } else if v == "5165" { + 5165 + } else if v == "5166" { + 5166 + } else if v == "5167" { + 5167 + } else if v == "5168" { + 5168 + } else if v == "5169" { + 5169 + } else if v == "5170" { + 5170 + } else if v == "5171" { + 5171 + } else if v == "5172" { + 5172 + } else if v == "5173" { + 5173 + } else if v == "5174" { + 5174 + } else if v == "5175" { + 5175 + } else if v == "5176" { + 5176 + } else if v == "5177" { + 5177 + } else if v == "5178" { + 5178 + } else if v == "5179" { + 5179 + } else if v == "5180" { + 5180 + } else if v == "5181" { + 5181 + } else if v == "5182" { + 5182 + } else if v == "5183" { + 5183 + } else if v == "5184" { + 5184 + } else if v == "5185" { + 5185 + } else if v == "5186" { + 5186 + } else if v == "5187" { + 5187 + } else if v == "5188" { + 5188 + } else if v == "5189" { + 5189 + } else if v == "5190" { + 5190 + } else if v == "5191" { + 5191 + } else if v == "5192" { + 5192 + } else if v == "5193" { + 5193 + } else if v == "5194" { + 5194 + } else if v == "5195" { + 5195 + } else if v == "5196" { + 5196 + } else if v == "5197" { + 5197 + } else if v == "5198" { + 5198 + } else if v == "5199" { + 5199 + } else if v == "5200" { + 5200 + } else if v == "5201" { + 5201 + } else if v == "5202" { + 5202 + } else if v == "5203" { + 5203 + } else if v == "5204" { + 5204 + } else if v == "5205" { + 5205 + } else { + 5206 + } +} diff --git a/tests/ui/issues/issue-7519-match-unit-in-arg.rs b/tests/ui/issues/issue-7519-match-unit-in-arg.rs new file mode 100644 index 000000000..7d838cbb0 --- /dev/null +++ b/tests/ui/issues/issue-7519-match-unit-in-arg.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +/* +#7519 ICE pattern matching unit in function argument +*/ + +fn foo(():()) { } + +pub fn main() { + foo(()); +} diff --git a/tests/ui/issues/issue-75283.rs b/tests/ui/issues/issue-75283.rs new file mode 100644 index 000000000..d556132e4 --- /dev/null +++ b/tests/ui/issues/issue-75283.rs @@ -0,0 +1,6 @@ +extern "C" { + fn lol() { //~ ERROR incorrect function inside `extern` block + println!(""); + } +} +fn main() {} diff --git a/tests/ui/issues/issue-75283.stderr b/tests/ui/issues/issue-75283.stderr new file mode 100644 index 000000000..da3800aff --- /dev/null +++ b/tests/ui/issues/issue-75283.stderr @@ -0,0 +1,18 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-75283.rs:2:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn lol() { + | ________^^^___- + | | | + | | cannot have a body +LL | | println!(""); +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-75307.rs b/tests/ui/issues/issue-75307.rs new file mode 100644 index 000000000..cffa6bea8 --- /dev/null +++ b/tests/ui/issues/issue-75307.rs @@ -0,0 +1,3 @@ +fn main() { + format!(r"{}{}{}", named_arg=1); //~ ERROR 3 positional arguments in format string, but there is 1 argument +} diff --git a/tests/ui/issues/issue-75307.stderr b/tests/ui/issues/issue-75307.stderr new file mode 100644 index 000000000..c5b0b11e7 --- /dev/null +++ b/tests/ui/issues/issue-75307.stderr @@ -0,0 +1,8 @@ +error: 3 positional arguments in format string, but there is 1 argument + --> $DIR/issue-75307.rs:2:15 + | +LL | format!(r"{}{}{}", named_arg=1); + | ^^^^^^ - + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-7563.rs b/tests/ui/issues/issue-7563.rs new file mode 100644 index 000000000..c62405554 --- /dev/null +++ b/tests/ui/issues/issue-7563.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +trait IDummy { + fn do_nothing(&self); +} + +#[derive(Debug)] +struct A { a: isize } +#[derive(Debug)] +struct B<'a> { b: isize, pa: &'a A } + + impl IDummy for A { + fn do_nothing(&self) { + println!("A::do_nothing() is called"); + } + } + +impl<'a> B<'a> { + fn get_pa(&self) -> &'a dyn IDummy { self.pa as &'a dyn IDummy } +} + +pub fn main() { + let sa = A { a: 100 }; + let sb = B { b: 200, pa: &sa }; + + println!("sa is {:?}", sa); + println!("sb is {:?}", sb); +} diff --git a/tests/ui/issues/issue-75704.rs b/tests/ui/issues/issue-75704.rs new file mode 100644 index 000000000..aed7ddbcb --- /dev/null +++ b/tests/ui/issues/issue-75704.rs @@ -0,0 +1,7 @@ +// Caused an infinite loop during SimlifyCfg MIR transform previously. +// +// build-pass + +fn main() { + loop { continue; } +} diff --git a/tests/ui/issues/issue-7575.rs b/tests/ui/issues/issue-7575.rs new file mode 100644 index 000000000..ac69f2b1c --- /dev/null +++ b/tests/ui/issues/issue-7575.rs @@ -0,0 +1,17 @@ +// run-pass + +trait Foo { + fn new() -> bool { false } + fn dummy(&self) { } +} + +trait Bar { + fn new(&self) -> bool { true } +} + +impl Bar for isize {} +impl Foo for isize {} + +fn main() { + assert!(1.new()); +} diff --git a/tests/ui/issues/issue-75777.rs b/tests/ui/issues/issue-75777.rs new file mode 100644 index 000000000..a1e438bc6 --- /dev/null +++ b/tests/ui/issues/issue-75777.rs @@ -0,0 +1,15 @@ +// Regression test for #75777. +// Checks that a boxed future can be properly constructed. + +use std::future::{self, Future}; +use std::pin::Pin; + +type BoxFuture<'a, T> = Pin + 'a + Send>>; + +fn inject<'a, Env: 'a, A: 'a + Send>(v: A) -> Box BoxFuture<'a, A>> { + let fut: BoxFuture<'a, A> = Box::pin(future::ready(v)); + Box::new(move |_| fut) + //~^ ERROR: lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/issues/issue-75777.stderr b/tests/ui/issues/issue-75777.stderr new file mode 100644 index 000000000..370cd72fd --- /dev/null +++ b/tests/ui/issues/issue-75777.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-75777.rs:11:5 + | +LL | fn inject<'a, Env: 'a, A: 'a + Send>(v: A) -> Box BoxFuture<'a, A>> { + | -- lifetime `'a` defined here +LL | let fut: BoxFuture<'a, A> = Box::pin(future::ready(v)); +LL | Box::new(move |_| fut) + | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-76042.rs b/tests/ui/issues/issue-76042.rs new file mode 100644 index 000000000..34d529379 --- /dev/null +++ b/tests/ui/issues/issue-76042.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -Coverflow-checks=off -Ccodegen-units=1 -Copt-level=0 + +fn foo(a: i128, b: i128, s: u32) -> (i128, i128) { + if s == 128 { + (0, 0) + } else { + (b >> s, a >> s) + } +} +fn main() { + let r = foo(0, 8, 1); + if r.0 != 4 { + panic!(); + } +} diff --git a/tests/ui/issues/issue-7607-1.rs b/tests/ui/issues/issue-7607-1.rs new file mode 100644 index 000000000..5221f2c52 --- /dev/null +++ b/tests/ui/issues/issue-7607-1.rs @@ -0,0 +1,9 @@ +struct Foo { + x: isize +} + +impl Fo { //~ ERROR cannot find type `Fo` in this scope + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-7607-1.stderr b/tests/ui/issues/issue-7607-1.stderr new file mode 100644 index 000000000..c98302699 --- /dev/null +++ b/tests/ui/issues/issue-7607-1.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `Fo` in this scope + --> $DIR/issue-7607-1.rs:5:6 + | +LL | impl Fo { + | ^^ help: a trait with a similar name exists: `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-7607-2.rs b/tests/ui/issues/issue-7607-2.rs new file mode 100644 index 000000000..420a0ffd3 --- /dev/null +++ b/tests/ui/issues/issue-7607-2.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub mod a { + pub struct Foo { a: usize } +} + +pub mod b { + use a::Foo; + impl Foo { + fn bar(&self) { } + } +} + +pub fn main() { } diff --git a/tests/ui/issues/issue-76077-1.fixed b/tests/ui/issues/issue-76077-1.fixed new file mode 100644 index 000000000..8103a7ca4 --- /dev/null +++ b/tests/ui/issues/issue-76077-1.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +pub mod foo { + #[derive(Default)] + pub struct Foo { invisible: bool, } + + #[derive(Default)] + pub struct Bar { pub visible: bool, invisible: bool, } +} + +fn main() { + let foo::Foo { .. } = foo::Foo::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields + + let foo::Bar { visible, .. } = foo::Bar::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields +} diff --git a/tests/ui/issues/issue-76077-1.rs b/tests/ui/issues/issue-76077-1.rs new file mode 100644 index 000000000..730332853 --- /dev/null +++ b/tests/ui/issues/issue-76077-1.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +pub mod foo { + #[derive(Default)] + pub struct Foo { invisible: bool, } + + #[derive(Default)] + pub struct Bar { pub visible: bool, invisible: bool, } +} + +fn main() { + let foo::Foo {} = foo::Foo::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields + + let foo::Bar { visible } = foo::Bar::default(); + //~^ ERROR pattern requires `..` due to inaccessible fields +} diff --git a/tests/ui/issues/issue-76077-1.stderr b/tests/ui/issues/issue-76077-1.stderr new file mode 100644 index 000000000..8e77662b4 --- /dev/null +++ b/tests/ui/issues/issue-76077-1.stderr @@ -0,0 +1,24 @@ +error: pattern requires `..` due to inaccessible fields + --> $DIR/issue-76077-1.rs:13:9 + | +LL | let foo::Foo {} = foo::Foo::default(); + | ^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let foo::Foo { .. } = foo::Foo::default(); + | ~~~~~~ + +error: pattern requires `..` due to inaccessible fields + --> $DIR/issue-76077-1.rs:16:9 + | +LL | let foo::Bar { visible } = foo::Bar::default(); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let foo::Bar { visible, .. } = foo::Bar::default(); + | ++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/issues/issue-76077.rs b/tests/ui/issues/issue-76077.rs new file mode 100644 index 000000000..2d29093b0 --- /dev/null +++ b/tests/ui/issues/issue-76077.rs @@ -0,0 +1,10 @@ +pub mod foo { + pub struct Foo { + you_cant_use_this_field: bool, + } +} + +fn main() { + foo::Foo {}; + //~^ ERROR cannot construct `Foo` with struct literal syntax due to private fields +} diff --git a/tests/ui/issues/issue-76077.stderr b/tests/ui/issues/issue-76077.stderr new file mode 100644 index 000000000..197ca8d5a --- /dev/null +++ b/tests/ui/issues/issue-76077.stderr @@ -0,0 +1,10 @@ +error: cannot construct `Foo` with struct literal syntax due to private fields + --> $DIR/issue-76077.rs:8:5 + | +LL | foo::Foo {}; + | ^^^^^^^^ + | + = note: ... and other private field `you_cant_use_this_field` that was not provided + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-76191.rs b/tests/ui/issues/issue-76191.rs new file mode 100644 index 000000000..d9790d2b5 --- /dev/null +++ b/tests/ui/issues/issue-76191.rs @@ -0,0 +1,19 @@ +// Regression test for diagnostic issue #76191 +#![allow(non_snake_case)] + +use std::ops::RangeInclusive; + +const RANGE: RangeInclusive = 0..=255; + +const RANGE2: RangeInclusive = panic!(); + +fn main() { + let n: i32 = 1; + match n { + RANGE => {} + //~^ ERROR mismatched types + RANGE2 => {} + //~^ ERROR mismatched types + _ => {} + } +} diff --git a/tests/ui/issues/issue-76191.stderr b/tests/ui/issues/issue-76191.stderr new file mode 100644 index 000000000..137498047 --- /dev/null +++ b/tests/ui/issues/issue-76191.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/issue-76191.rs:13:9 + | +LL | const RANGE: RangeInclusive = 0..=255; + | -------------------------------- constant defined here +... +LL | match n { + | - this expression has type `i32` +LL | RANGE => {} + | ^^^^^ + | | + | expected `i32`, found struct `RangeInclusive` + | `RANGE` is interpreted as a constant, not a new binding + | + = note: expected type `i32` + found struct `RangeInclusive` +help: you may want to move the range into the match block + | +LL | 0..=255 => {} + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/issue-76191.rs:15:9 + | +LL | const RANGE2: RangeInclusive = panic!(); + | --------------------------------- constant defined here +... +LL | match n { + | - this expression has type `i32` +... +LL | RANGE2 => {} + | ^^^^^^ + | | + | expected `i32`, found struct `RangeInclusive` + | `RANGE2` is interpreted as a constant, not a new binding + | + = note: expected type `i32` + found struct `RangeInclusive` + = note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-7660.rs b/tests/ui/issues/issue-7660.rs new file mode 100644 index 000000000..ad0b8ecff --- /dev/null +++ b/tests/ui/issues/issue-7660.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_variables)] +// Regression test for issue 7660 +// rvalue lifetime too short when equivalent `match` works + +// pretty-expanded FIXME #23616 + +use std::collections::HashMap; + +struct A(isize, isize); + +pub fn main() { + let mut m: HashMap = HashMap::new(); + m.insert(1, A(0, 0)); + + let A(ref _a, ref _b) = m[&1]; + let (a, b) = match m[&1] { A(ref _a, ref _b) => (_a, _b) }; +} diff --git a/tests/ui/issues/issue-7663.rs b/tests/ui/issues/issue-7663.rs new file mode 100644 index 000000000..b15e215db --- /dev/null +++ b/tests/ui/issues/issue-7663.rs @@ -0,0 +1,32 @@ +// run-pass + +#![allow(unused_imports, dead_code)] + +mod test1 { + + mod foo { pub fn p() -> isize { 1 } } + mod bar { pub fn p() -> isize { 2 } } + + pub mod baz { + use test1::bar::p; + + pub fn my_main() { assert_eq!(p(), 2); } + } +} + +mod test2 { + + mod foo { pub fn p() -> isize { 1 } } + mod bar { pub fn p() -> isize { 2 } } + + pub mod baz { + use test2::bar::p; + + pub fn my_main() { assert_eq!(p(), 2); } + } +} + +fn main() { + test1::baz::my_main(); + test2::baz::my_main(); +} diff --git a/tests/ui/issues/issue-7673-cast-generically-implemented-trait.rs b/tests/ui/issues/issue-7673-cast-generically-implemented-trait.rs new file mode 100644 index 000000000..c089c3308 --- /dev/null +++ b/tests/ui/issues/issue-7673-cast-generically-implemented-trait.rs @@ -0,0 +1,20 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +/* + +#7673 Polymorphically creating traits barely works + +*/ + +pub fn main() {} + +trait A { + fn dummy(&self) { } +} + +impl A for T {} + +fn owned2(a: Box) { a as Box; } +fn owned3(a: Box) { Box::new(a) as Box; } diff --git a/tests/ui/issues/issue-77218/issue-77218-2.fixed b/tests/ui/issues/issue-77218/issue-77218-2.fixed new file mode 100644 index 000000000..0e835d49c --- /dev/null +++ b/tests/ui/issues/issue-77218/issue-77218-2.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/tests/ui/issues/issue-77218/issue-77218-2.rs b/tests/ui/issues/issue-77218/issue-77218-2.rs new file mode 100644 index 000000000..01dca1ae1 --- /dev/null +++ b/tests/ui/issues/issue-77218/issue-77218-2.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) { //~ ERROR invalid left-hand side of assignment + } +} diff --git a/tests/ui/issues/issue-77218/issue-77218-2.stderr b/tests/ui/issues/issue-77218/issue-77218-2.stderr new file mode 100644 index 000000000..58c1c18f9 --- /dev/null +++ b/tests/ui/issues/issue-77218/issue-77218-2.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218-2.rs:4:19 + | +LL | while Some(0) = value.get(0) { + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/issues/issue-77218/issue-77218.fixed b/tests/ui/issues/issue-77218/issue-77218.fixed new file mode 100644 index 000000000..4907b43b9 --- /dev/null +++ b/tests/ui/issues/issue-77218/issue-77218.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while let Some(0) = value.get(0) {} //~ ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/issues/issue-77218/issue-77218.rs b/tests/ui/issues/issue-77218/issue-77218.rs new file mode 100644 index 000000000..0ed154bf4 --- /dev/null +++ b/tests/ui/issues/issue-77218/issue-77218.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let value = [7u8]; + while Some(0) = value.get(0) {} //~ ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/issues/issue-77218/issue-77218.stderr b/tests/ui/issues/issue-77218/issue-77218.stderr new file mode 100644 index 000000000..eda635646 --- /dev/null +++ b/tests/ui/issues/issue-77218/issue-77218.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-77218.rs:4:19 + | +LL | while Some(0) = value.get(0) {} + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(0) = value.get(0) {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/issues/issue-7784.rs b/tests/ui/issues/issue-7784.rs new file mode 100644 index 000000000..b7323f09d --- /dev/null +++ b/tests/ui/issues/issue-7784.rs @@ -0,0 +1,30 @@ +// run-pass + +use std::ops::Add; + +fn foo + Clone>([x, y, z]: [T; 3]) -> (T, T, T) { + (x.clone(), x.clone() + y.clone(), x + y + z) +} +fn bar(a: &'static str, b: &'static str) -> [&'static str; 4] { + [a, b, b, a] +} + +fn main() { + assert_eq!(foo([1, 2, 3]), (1, 3, 6)); + + let [a, b, c, d] = bar("foo", "bar"); + assert_eq!(a, "foo"); + assert_eq!(b, "bar"); + assert_eq!(c, "bar"); + assert_eq!(d, "foo"); + + let [a, _, _, d] = bar("baz", "foo"); + assert_eq!(a, "baz"); + assert_eq!(d, "baz"); + + let out = bar("baz", "foo"); + let [a, xs @ .., d] = out; + assert_eq!(a, "baz"); + assert_eq!(xs, ["foo", "foo"]); + assert_eq!(d, "baz"); +} diff --git a/tests/ui/issues/issue-77919.rs b/tests/ui/issues/issue-77919.rs new file mode 100644 index 000000000..966d76d14 --- /dev/null +++ b/tests/ui/issues/issue-77919.rs @@ -0,0 +1,13 @@ +fn main() { + [1; >::VAL]; +} +trait TypeVal { + const VAL: T; +} +struct Five; +struct Multiply { + _n: PhantomData, //~ ERROR cannot find type `PhantomData` in this scope +} +impl TypeVal for Multiply where N: TypeVal {} +//~^ ERROR cannot find type `VAL` in this scope +//~| ERROR not all trait items implemented, missing: `VAL` diff --git a/tests/ui/issues/issue-77919.stderr b/tests/ui/issues/issue-77919.stderr new file mode 100644 index 000000000..d154bfe0c --- /dev/null +++ b/tests/ui/issues/issue-77919.stderr @@ -0,0 +1,35 @@ +error[E0412]: cannot find type `PhantomData` in this scope + --> $DIR/issue-77919.rs:9:9 + | +LL | _n: PhantomData, + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::marker::PhantomData; + | + +error[E0412]: cannot find type `VAL` in this scope + --> $DIR/issue-77919.rs:11:63 + | +LL | impl TypeVal for Multiply where N: TypeVal {} + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl TypeVal for Multiply where N: TypeVal {} + | +++++ + +error[E0046]: not all trait items implemented, missing: `VAL` + --> $DIR/issue-77919.rs:11:1 + | +LL | const VAL: T; + | ------------ `VAL` from trait +... +LL | impl TypeVal for Multiply where N: TypeVal {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `VAL` in implementation + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0412. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/issues/issue-78115.rs b/tests/ui/issues/issue-78115.rs new file mode 100644 index 000000000..ac18470c6 --- /dev/null +++ b/tests/ui/issues/issue-78115.rs @@ -0,0 +1,19 @@ +// Regression test for issue #78115: "ICE: variable should be placed in scope earlier" + +// check-pass +// edition:2018 + +#[allow(dead_code)] +struct Foo { + a: () +} + +async fn _bar() { + let foo = Foo { a: () }; + match foo { + Foo { a: _a } | Foo { a: _a } if true => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-7813.rs b/tests/ui/issues/issue-7813.rs new file mode 100644 index 000000000..ce549bde6 --- /dev/null +++ b/tests/ui/issues/issue-7813.rs @@ -0,0 +1,4 @@ +fn main() { + let v = &[]; //~ ERROR type annotations needed + let it = v.iter(); +} diff --git a/tests/ui/issues/issue-7813.stderr b/tests/ui/issues/issue-7813.stderr new file mode 100644 index 000000000..2a747f679 --- /dev/null +++ b/tests/ui/issues/issue-7813.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `&[_; 0]` + --> $DIR/issue-7813.rs:2:9 + | +LL | let v = &[]; + | ^ --- type must be known at this point + | +help: consider giving `v` an explicit type, where the placeholders `_` are specified + | +LL | let v: &[_; 0] = &[]; + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-78192.rs b/tests/ui/issues/issue-78192.rs new file mode 100644 index 000000000..b5c300159 --- /dev/null +++ b/tests/ui/issues/issue-78192.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(unused_assignments)] + +fn main() { + let a = 1u32; + let b = 2u32; + + let mut c: *const u32 = &a; + let d: &u32 = &b; + + let x = unsafe { &*c }; + c = d; + let z = *x; + + assert_eq!(1, z); +} diff --git a/tests/ui/issues/issue-78622.rs b/tests/ui/issues/issue-78622.rs new file mode 100644 index 000000000..c00fd2660 --- /dev/null +++ b/tests/ui/issues/issue-78622.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] + +struct S; +fn f() { + S::A:: {} + //~^ ERROR ambiguous associated type +} diff --git a/tests/ui/issues/issue-78622.stderr b/tests/ui/issues/issue-78622.stderr new file mode 100644 index 000000000..70daf8a2f --- /dev/null +++ b/tests/ui/issues/issue-78622.stderr @@ -0,0 +1,14 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-78622.rs:5:5 + | +LL | S::A:: {} + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | ::A:: {} + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/issues/issue-7867.rs b/tests/ui/issues/issue-7867.rs new file mode 100644 index 000000000..3074052f1 --- /dev/null +++ b/tests/ui/issues/issue-7867.rs @@ -0,0 +1,14 @@ +enum A { B, C } + +mod foo { pub fn bar() {} } + +fn main() { + match (true, false) { + A::B => (), + //~^ ERROR mismatched types + //~| expected tuple, found enum `A` + //~| expected tuple `(bool, bool)` + //~| found enum `A` + _ => () + } +} diff --git a/tests/ui/issues/issue-7867.stderr b/tests/ui/issues/issue-7867.stderr new file mode 100644 index 000000000..0d3121d60 --- /dev/null +++ b/tests/ui/issues/issue-7867.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-7867.rs:7:9 + | +LL | enum A { B, C } + | - unit variant defined here +... +LL | match (true, false) { + | ------------- this expression has type `(bool, bool)` +LL | A::B => (), + | ^^^^ expected tuple, found enum `A` + | + = note: expected tuple `(bool, bool)` + found enum `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-78957.rs b/tests/ui/issues/issue-78957.rs new file mode 100644 index 000000000..567c59fd5 --- /dev/null +++ b/tests/ui/issues/issue-78957.rs @@ -0,0 +1,29 @@ +#![deny(unused_attributes)] + +use std::marker::PhantomData; + +pub struct Foo<#[inline] const N: usize>; +//~^ ERROR attribute should be applied to function or closure +pub struct Bar<#[cold] const N: usize>; +//~^ ERROR attribute should be applied to a function +//~| WARN this was previously accepted +pub struct Baz<#[repr(C)] const N: usize>; +//~^ ERROR attribute should be applied to a struct, enum, or union +// +pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>); +//~^ ERROR attribute should be applied to function or closure +pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>); +//~^ ERROR attribute should be applied to a function +//~| WARN this was previously accepted +pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>); +//~^ ERROR attribute should be applied to a struct, enum, or union +// +pub struct Foo3<#[inline] T>(PhantomData); +//~^ ERROR attribute should be applied to function or closure +pub struct Bar3<#[cold] T>(PhantomData); +//~^ ERROR attribute should be applied to a function +//~| WARN this was previously accepted +pub struct Baz3<#[repr(C)] T>(PhantomData); +//~^ ERROR attribute should be applied to a struct, enum, or union + +fn main() {} diff --git a/tests/ui/issues/issue-78957.stderr b/tests/ui/issues/issue-78957.stderr new file mode 100644 index 000000000..6de22d6bf --- /dev/null +++ b/tests/ui/issues/issue-78957.stderr @@ -0,0 +1,69 @@ +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-78957.rs:5:16 + | +LL | pub struct Foo<#[inline] const N: usize>; + | ^^^^^^^^^ -------------- not a function or closure + +error: attribute should be applied to a function definition + --> $DIR/issue-78957.rs:7:16 + | +LL | pub struct Bar<#[cold] const N: usize>; + | ^^^^^^^ -------------- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/issue-78957.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-78957.rs:10:23 + | +LL | pub struct Baz<#[repr(C)] const N: usize>; + | ^ -------------- not a struct, enum, or union + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-78957.rs:13:17 + | +LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>); + | ^^^^^^^^^ -- not a function or closure + +error: attribute should be applied to a function definition + --> $DIR/issue-78957.rs:15:17 + | +LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>); + | ^^^^^^^ -- not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-78957.rs:18:24 + | +LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>); + | ^ -- not a struct, enum, or union + +error[E0518]: attribute should be applied to function or closure + --> $DIR/issue-78957.rs:21:17 + | +LL | pub struct Foo3<#[inline] T>(PhantomData); + | ^^^^^^^^^ - not a function or closure + +error: attribute should be applied to a function definition + --> $DIR/issue-78957.rs:23:17 + | +LL | pub struct Bar3<#[cold] T>(PhantomData); + | ^^^^^^^ - not a function definition + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-78957.rs:26:24 + | +LL | pub struct Baz3<#[repr(C)] T>(PhantomData); + | ^ - not a struct, enum, or union + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0517, E0518. +For more information about an error, try `rustc --explain E0517`. diff --git a/tests/ui/issues/issue-7899.rs b/tests/ui/issues/issue-7899.rs new file mode 100644 index 000000000..fb631f836 --- /dev/null +++ b/tests/ui/issues/issue-7899.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_variables)] +// aux-build:issue-7899.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_7899 as testcrate; + +fn main() { + let f = testcrate::V2(1.0f32, 2.0f32); +} diff --git a/tests/ui/issues/issue-7911.rs b/tests/ui/issues/issue-7911.rs new file mode 100644 index 000000000..f64887136 --- /dev/null +++ b/tests/ui/issues/issue-7911.rs @@ -0,0 +1,37 @@ +// run-pass +// (Closes #7911) Test that we can use the same self expression +// with different mutability in macro in two methods + +#![allow(unused_variables)] // unused foobar_immut + foobar_mut +trait FooBar { + fn dummy(&self) { } +} +struct Bar(#[allow(unused_tuple_struct_fields)] i32); +struct Foo { bar: Bar } + +impl FooBar for Bar {} + +trait Test { + fn get_immut(&self) -> &dyn FooBar; + fn get_mut(&mut self) -> &mut dyn FooBar; +} + +macro_rules! generate_test { ($type_:path, $slf:ident, $field:expr) => ( + impl Test for $type_ { + fn get_immut(&$slf) -> &dyn FooBar { + &$field as &dyn FooBar + } + + fn get_mut(&mut $slf) -> &mut dyn FooBar { + &mut $field as &mut dyn FooBar + } + } +)} + +generate_test!(Foo, self, self.bar); + +pub fn main() { + let mut foo: Foo = Foo { bar: Bar(42) }; + { let foobar_immut = foo.get_immut(); } + { let foobar_mut = foo.get_mut(); } +} diff --git a/tests/ui/issues/issue-7950.rs b/tests/ui/issues/issue-7950.rs new file mode 100644 index 000000000..d3dcb3380 --- /dev/null +++ b/tests/ui/issues/issue-7950.rs @@ -0,0 +1,8 @@ +// tests the good error message, not "missing module Foo" or something else unexpected + +struct Foo; + +fn main() { + Foo::bar(); + //~^ ERROR no function or associated item named `bar` found for struct `Foo` +} diff --git a/tests/ui/issues/issue-7950.stderr b/tests/ui/issues/issue-7950.stderr new file mode 100644 index 000000000..b8b0eb310 --- /dev/null +++ b/tests/ui/issues/issue-7950.stderr @@ -0,0 +1,12 @@ +error[E0599]: no function or associated item named `bar` found for struct `Foo` in the current scope + --> $DIR/issue-7950.rs:6:10 + | +LL | struct Foo; + | ---------- function or associated item `bar` not found for this struct +... +LL | Foo::bar(); + | ^^^ function or associated item not found in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-7970a.rs b/tests/ui/issues/issue-7970a.rs new file mode 100644 index 000000000..dae906410 --- /dev/null +++ b/tests/ui/issues/issue-7970a.rs @@ -0,0 +1,8 @@ +macro_rules! one_arg_macro { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); +} + +fn main() { + one_arg_macro!(); + //~^ ERROR unexpected end of macro invocation +} diff --git a/tests/ui/issues/issue-7970a.stderr b/tests/ui/issues/issue-7970a.stderr new file mode 100644 index 000000000..b04a0eef3 --- /dev/null +++ b/tests/ui/issues/issue-7970a.stderr @@ -0,0 +1,17 @@ +error: unexpected end of macro invocation + --> $DIR/issue-7970a.rs:6:5 + | +LL | macro_rules! one_arg_macro { + | -------------------------- when calling this macro +... +LL | one_arg_macro!(); + | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$fmt:expr` + --> $DIR/issue-7970a.rs:2:6 + | +LL | ($fmt:expr) => (print!(concat!($fmt, "\n"))); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/issues/issue-8044.rs b/tests/ui/issues/issue-8044.rs new file mode 100644 index 000000000..858f98b65 --- /dev/null +++ b/tests/ui/issues/issue-8044.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-8044.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_8044 as minimal; +use minimal::{BTree, leaf}; + +pub fn main() { + BTree:: { node: leaf(1) }; +} diff --git a/tests/ui/issues/issue-80607.rs b/tests/ui/issues/issue-80607.rs new file mode 100644 index 000000000..63f4df359 --- /dev/null +++ b/tests/ui/issues/issue-80607.rs @@ -0,0 +1,10 @@ +// This tests makes sure the diagnostics print the offending enum variant, not just the type. +pub enum Enum { + V1(i32), +} + +pub fn foo(x: i32) -> Enum { + Enum::V1 { x } //~ ERROR `Enum::V1` has no field named `x` +} + +fn main() {} diff --git a/tests/ui/issues/issue-80607.stderr b/tests/ui/issues/issue-80607.stderr new file mode 100644 index 000000000..38e46683b --- /dev/null +++ b/tests/ui/issues/issue-80607.stderr @@ -0,0 +1,17 @@ +error[E0559]: variant `Enum::V1` has no field named `x` + --> $DIR/issue-80607.rs:7:16 + | +LL | V1(i32), + | -- `Enum::V1` defined here +... +LL | Enum::V1 { x } + | ^ field does not exist + | +help: `Enum::V1` is a tuple variant, use the appropriate syntax + | +LL | Enum::V1(/* fields */) + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0559`. diff --git a/tests/ui/issues/issue-81584.fixed b/tests/ui/issues/issue-81584.fixed new file mode 100644 index 000000000..1cad59f10 --- /dev/null +++ b/tests/ui/issues/issue-81584.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let _ = vec![vec![0, 1], vec![2]] + .into_iter() + .map(|y| y.iter().map(|x| x + 1).collect::>()) + //~^ ERROR cannot return value referencing function parameter `y` + .collect::>(); +} diff --git a/tests/ui/issues/issue-81584.rs b/tests/ui/issues/issue-81584.rs new file mode 100644 index 000000000..452288db0 --- /dev/null +++ b/tests/ui/issues/issue-81584.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let _ = vec![vec![0, 1], vec![2]] + .into_iter() + .map(|y| y.iter().map(|x| x + 1)) + //~^ ERROR cannot return value referencing function parameter `y` + .collect::>(); +} diff --git a/tests/ui/issues/issue-81584.stderr b/tests/ui/issues/issue-81584.stderr new file mode 100644 index 000000000..54973cfa3 --- /dev/null +++ b/tests/ui/issues/issue-81584.stderr @@ -0,0 +1,14 @@ +error[E0515]: cannot return value referencing function parameter `y` + --> $DIR/issue-81584.rs:5:22 + | +LL | .map(|y| y.iter().map(|x| x + 1)) + | --------^^^^^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `y` is borrowed here + | + = help: use `.collect()` to allocate the iterator + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs b/tests/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs new file mode 100644 index 000000000..505e7b84b --- /dev/null +++ b/tests/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs @@ -0,0 +1,19 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +/* + +#8171 Self is not recognised as implementing kinds in default method implementations + +*/ + +fn require_send(_: T){} + +trait TragicallySelfIsNotSend: Send + Sized { + fn x(self) { + require_send(self); + } +} + +pub fn main(){} diff --git a/tests/ui/issues/issue-81918.rs b/tests/ui/issues/issue-81918.rs new file mode 100644 index 000000000..8938b8a6f --- /dev/null +++ b/tests/ui/issues/issue-81918.rs @@ -0,0 +1,11 @@ +// check-pass +// dont-check-compiler-stdout +// compile-flags: -Z unpretty=mir-cfg + +// This checks that unpretty=mir-cfg does not panic. See #81918. + +const TAG: &'static str = "ABCD"; + +fn main() { + if TAG == "" {} +} diff --git a/tests/ui/issues/issue-8248.rs b/tests/ui/issues/issue-8248.rs new file mode 100644 index 000000000..31a305c31 --- /dev/null +++ b/tests/ui/issues/issue-8248.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait A { + fn dummy(&self) { } +} +struct B; +impl A for B {} + +fn foo(_: &mut dyn A) {} + +pub fn main() { + let mut b = B; + foo(&mut b as &mut dyn A); +} diff --git a/tests/ui/issues/issue-8249.rs b/tests/ui/issues/issue-8249.rs new file mode 100644 index 000000000..d09dff3a6 --- /dev/null +++ b/tests/ui/issues/issue-8249.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait A { + fn dummy(&self) { } +} +struct B; +impl A for B {} + +struct C<'a> { + foo: &'a mut (dyn A+'a), +} + +fn foo(a: &mut dyn A) { + C{ foo: a }; +} + +pub fn main() { +} diff --git a/tests/ui/issues/issue-8259.rs b/tests/ui/issues/issue-8259.rs new file mode 100644 index 000000000..2802bea7f --- /dev/null +++ b/tests/ui/issues/issue-8259.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +// aux-build:issue-8259.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_8259 as other; +static a: other::Foo<'static> = other::Foo::A; + +pub fn main() {} diff --git a/tests/ui/issues/issue-82833-slice-miscompile.rs b/tests/ui/issues/issue-82833-slice-miscompile.rs new file mode 100644 index 000000000..8cf6a3137 --- /dev/null +++ b/tests/ui/issues/issue-82833-slice-miscompile.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Copt-level=0 -Cdebuginfo=2 + +// Make sure LLVM does not miscompile this. + +fn make_string(ch: char) -> String { + let mut bytes = [0u8; 4]; + ch.encode_utf8(&mut bytes).into() +} + +fn main() { + let ch = '😃'; + dbg!(ch); + let string = make_string(ch); + dbg!(string); +} diff --git a/tests/ui/issues/issue-83048.rs b/tests/ui/issues/issue-83048.rs new file mode 100644 index 000000000..8e4fb6eae --- /dev/null +++ b/tests/ui/issues/issue-83048.rs @@ -0,0 +1,5 @@ +// compile-flags: -Z unpretty=thir-tree + +pub fn main() { + break; //~ ERROR: `break` outside of a loop or labeled block [E0268] +} diff --git a/tests/ui/issues/issue-83048.stderr b/tests/ui/issues/issue-83048.stderr new file mode 100644 index 000000000..dade9e469 --- /dev/null +++ b/tests/ui/issues/issue-83048.stderr @@ -0,0 +1,9 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/issue-83048.rs:4:5 + | +LL | break; + | ^^^^^ cannot `break` outside of a loop or labeled block + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0268`. diff --git a/tests/ui/issues/issue-83190.rs b/tests/ui/issues/issue-83190.rs new file mode 100644 index 000000000..da931c3ed --- /dev/null +++ b/tests/ui/issues/issue-83190.rs @@ -0,0 +1,49 @@ +// check-pass + +// Regression test for issue #83190, triggering an ICE in borrowck. + +pub trait Any {} +impl Any for T {} + +pub trait StreamOnce { + type Range; +} + +pub trait Parser: Sized { + type Output; + type PartialState; + fn map(self) -> Map { + todo!() + } +} + +pub struct Map

(P); +impl> Parser for Map

{ + type Output = (); + type PartialState = P::PartialState; +} + +struct TakeWhile1(Input); +impl Parser for TakeWhile1 { + type Output = I::Range; + type PartialState = (); +} +impl TakeWhile1 { + fn new() -> Self { + todo!() + } +} + +impl> Parser for (A,) { + type Output = (); + type PartialState = Map; +} + +pub fn metric_stream_parser<'a, I>() -> impl Parser +where + I: StreamOnce, +{ + (TakeWhile1::new(),).map() +} + +fn main() {} diff --git a/tests/ui/issues/issue-8391.rs b/tests/ui/issues/issue-8391.rs new file mode 100644 index 000000000..1a9036965 --- /dev/null +++ b/tests/ui/issues/issue-8391.rs @@ -0,0 +1,9 @@ +// run-pass + +fn main() { + let x = match Some(1) { + ref _y @ Some(_) => 1, + None => 2, + }; + assert_eq!(x, 1); +} diff --git a/tests/ui/issues/issue-83924.fixed b/tests/ui/issues/issue-83924.fixed new file mode 100644 index 000000000..aa40da12b --- /dev/null +++ b/tests/ui/issues/issue-83924.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +fn main() { + let mut values = vec![10, 11, 12]; + let v = &mut values; + + let mut max = 0; + + for n in &mut *v { + max = std::cmp::max(max, *n); + } + + println!("max is {}", max); + println!("Converting to percentages of maximum value..."); + for n in v { + //~^ ERROR: use of moved value: `v` [E0382] + *n = 100 * (*n) / max; + } + println!("values: {:#?}", values); +} diff --git a/tests/ui/issues/issue-83924.rs b/tests/ui/issues/issue-83924.rs new file mode 100644 index 000000000..22b80fe2f --- /dev/null +++ b/tests/ui/issues/issue-83924.rs @@ -0,0 +1,20 @@ +// run-rustfix + +fn main() { + let mut values = vec![10, 11, 12]; + let v = &mut values; + + let mut max = 0; + + for n in v { + max = std::cmp::max(max, *n); + } + + println!("max is {}", max); + println!("Converting to percentages of maximum value..."); + for n in v { + //~^ ERROR: use of moved value: `v` [E0382] + *n = 100 * (*n) / max; + } + println!("values: {:#?}", values); +} diff --git a/tests/ui/issues/issue-83924.stderr b/tests/ui/issues/issue-83924.stderr new file mode 100644 index 000000000..572414df2 --- /dev/null +++ b/tests/ui/issues/issue-83924.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `v` + --> $DIR/issue-83924.rs:15:14 + | +LL | let v = &mut values; + | - move occurs because `v` has type `&mut Vec`, which does not implement the `Copy` trait +... +LL | for n in v { + | - `v` moved due to this implicit call to `.into_iter()` +... +LL | for n in v { + | ^ value used here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `v` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider creating a fresh reborrow of `v` here + | +LL | for n in &mut *v { + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/issues/issue-8398.rs b/tests/ui/issues/issue-8398.rs new file mode 100644 index 000000000..0ef39b6a6 --- /dev/null +++ b/tests/ui/issues/issue-8398.rs @@ -0,0 +1,13 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub trait Writer { + fn write(&mut self, b: &[u8]) -> Result<(), ()>; +} + +fn foo(a: &mut dyn Writer) { + a.write(&[]).unwrap(); +} + +pub fn main(){} diff --git a/tests/ui/issues/issue-8401.rs b/tests/ui/issues/issue-8401.rs new file mode 100644 index 000000000..1257bab6c --- /dev/null +++ b/tests/ui/issues/issue-8401.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-8401.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_8401; + +pub fn main() {} diff --git a/tests/ui/issues/issue-8498.rs b/tests/ui/issues/issue-8498.rs new file mode 100644 index 000000000..e6241b761 --- /dev/null +++ b/tests/ui/issues/issue-8498.rs @@ -0,0 +1,27 @@ +// run-pass + +pub fn main() { + match &[(Box::new(5),Box::new(7))] { + ps => { + let (ref y, _) = ps[0]; + assert_eq!(**y, 5); + } + } + + match Some(&[(Box::new(5),)]) { + Some(ps) => { + let (ref y,) = ps[0]; + assert_eq!(**y, 5); + } + None => () + } + + match Some(&[(Box::new(5),Box::new(7))]) { + Some(ps) => { + let (ref y, ref z) = ps[0]; + assert_eq!(**y, 5); + assert_eq!(**z, 7); + } + None => () + } +} diff --git a/tests/ui/issues/issue-8506.rs b/tests/ui/issues/issue-8506.rs new file mode 100644 index 000000000..cc32b8923 --- /dev/null +++ b/tests/ui/issues/issue-8506.rs @@ -0,0 +1,14 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_upper_case_globals)] + +#![allow(dead_code)] + +enum Either { + One, + Other(String,String) +} + +static one : Either = Either::One; + +pub fn main () { } diff --git a/tests/ui/issues/issue-8521.rs b/tests/ui/issues/issue-8521.rs new file mode 100644 index 000000000..15fbd4465 --- /dev/null +++ b/tests/ui/issues/issue-8521.rs @@ -0,0 +1,25 @@ +// check-pass +trait Foo1 {} + +trait A {} + +macro_rules! foo1(($t:path) => { + impl Foo1 for T {} +}); + +foo1!(A); + +trait Foo2 {} + +trait B {} + +#[allow(unused)] +struct C {} + +macro_rules! foo2(($t:path) => { + impl Foo2 for T {} +}); + +foo2!(B); + +fn main() {} diff --git a/tests/ui/issues/issue-85461.rs b/tests/ui/issues/issue-85461.rs new file mode 100644 index 000000000..965510887 --- /dev/null +++ b/tests/ui/issues/issue-85461.rs @@ -0,0 +1,27 @@ +// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 --crate-type dylib -Copt-level=0 +// build-pass +// needs-profiler-support + +// Regression test for #85461 where MSVC sometimes fails to link instrument-coverage binaries +// with dead code and #[inline(always)]. + +#![allow(dead_code)] + +mod foo { + #[inline(always)] + pub fn called() { } + + fn uncalled() { } +} + +pub mod bar { + pub fn call_me() { + super::foo::called(); + } +} + +pub mod baz { + pub fn call_me() { + super::foo::called(); + } +} diff --git a/tests/ui/issues/issue-8578.rs b/tests/ui/issues/issue-8578.rs new file mode 100644 index 000000000..2346ef5a9 --- /dev/null +++ b/tests/ui/issues/issue-8578.rs @@ -0,0 +1,20 @@ +// check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +// pretty-expanded FIXME #23616 + +pub struct UninterpretedOption_NamePart { + name_part: Option, +} + +impl<'a> UninterpretedOption_NamePart { + pub fn default_instance() -> &'static UninterpretedOption_NamePart { + static instance: UninterpretedOption_NamePart = UninterpretedOption_NamePart { + name_part: None, + }; + &instance + } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-86756.rs b/tests/ui/issues/issue-86756.rs new file mode 100644 index 000000000..7f864eb28 --- /dev/null +++ b/tests/ui/issues/issue-86756.rs @@ -0,0 +1,12 @@ +trait Foo {} +//~^ ERROR the name `T` is already used for a generic parameter in this item's generic parameters + +fn eq() { + eq:: + //~^ ERROR cannot find type `dyn` in this scope + //~| ERROR missing generics for trait `Foo` + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} + +fn main() {} diff --git a/tests/ui/issues/issue-86756.stderr b/tests/ui/issues/issue-86756.stderr new file mode 100644 index 000000000..bfa7459ab --- /dev/null +++ b/tests/ui/issues/issue-86756.stderr @@ -0,0 +1,48 @@ +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/issue-86756.rs:1:14 + | +LL | trait Foo {} + | - ^ already used + | | + | first use of `T` + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/issue-86756.rs:5:10 + | +LL | eq:: + | ^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-86756.rs:5:15 + | +LL | eq:: + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | eq:: + | +++ + +error[E0107]: missing generics for trait `Foo` + --> $DIR/issue-86756.rs:5:15 + | +LL | eq:: + | ^^^ expected at least 1 generic argument + | +note: trait defined here, with at least 1 generic parameter: `T` + --> $DIR/issue-86756.rs:1:7 + | +LL | trait Foo {} + | ^^^ - +help: add missing generic argument + | +LL | eq::> + | +++ + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0107, E0403, E0412. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/issues/issue-868.rs b/tests/ui/issues/issue-868.rs new file mode 100644 index 000000000..ce0a3c7ca --- /dev/null +++ b/tests/ui/issues/issue-868.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_parens)] +// pretty-expanded FIXME #23616 + +fn f(g: F) -> T where F: FnOnce() -> T { g() } + +pub fn main() { + let _x = f( | | { 10 }); + // used to be: cannot determine a type for this expression + f(| | { }); + // ditto + f( | | { ()}); + // always worked + let _: () = f(| | { }); + // empty block with no type info should compile too + let _ = f(||{}); + let _ = (||{}); +} diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs new file mode 100644 index 000000000..a80a64a2f --- /dev/null +++ b/tests/ui/issues/issue-87199.rs @@ -0,0 +1,20 @@ +// Regression test for issue #87199, where attempting to relax a bound +// other than the only supported `?Sized` would still cause the compiler +// to assume that the `Sized` bound was relaxed. + +// check-fail + +// Check that these function definitions only emit warnings, not errors +fn arg(_: T) {} +//~^ warning: default bound relaxed for a type parameter, but this does nothing +fn ref_arg(_: &T) {} +//~^ warning: default bound relaxed for a type parameter, but this does nothing +fn ret() -> impl Iterator + ?Send { std::iter::empty() } +//~^ warning: default bound relaxed for a type parameter, but this does nothing + +// Check that there's no `?Sized` relaxation! +fn main() { + ref_arg::(&5); + ref_arg::<[i32]>(&[5]); + //~^ the size for values of type `[i32]` cannot be known +} diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr new file mode 100644 index 000000000..0ec5e73f3 --- /dev/null +++ b/tests/ui/issues/issue-87199.stderr @@ -0,0 +1,40 @@ +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-87199.rs:8:8 + | +LL | fn arg(_: T) {} + | ^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-87199.rs:10:12 + | +LL | fn ref_arg(_: &T) {} + | ^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/issue-87199.rs:12:13 + | +LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-87199.rs:18:22 + | +LL | ref_arg::<[i32]>(&[5]); + | ---------------- ^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[i32]` +note: required by a bound in `ref_arg` + --> $DIR/issue-87199.rs:10:12 + | +LL | fn ref_arg(_: &T) {} + | ^ required by this bound in `ref_arg` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn ref_arg(_: &T) {} + | ++++++++ + +error: aborting due to previous error; 3 warnings emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-8727.polonius.stderr b/tests/ui/issues/issue-8727.polonius.stderr new file mode 100644 index 000000000..283c01b6b --- /dev/null +++ b/tests/ui/issues/issue-8727.polonius.stderr @@ -0,0 +1,26 @@ +warning: function cannot return without recursing + --> $DIR/issue-8727.rs:7:1 + | +LL | fn generic() { + | ^^^^^^^^^^^^^^^ cannot return without recursing +LL | generic::>(); + | ---------------------- recursive call site + | + = note: `#[warn(unconditional_recursion)]` on by default + = help: a `loop` may express intention better if this is on purpose + +error: reached the recursion limit while instantiating `generic::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-8727.rs:8:5 + | +LL | generic::>(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `generic` defined here + --> $DIR/issue-8727.rs:7:1 + | +LL | fn generic() { + | ^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727.polonius/issue-8727.long-type.txt' + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/issues/issue-8727.rs b/tests/ui/issues/issue-8727.rs new file mode 100644 index 000000000..a9b812661 --- /dev/null +++ b/tests/ui/issues/issue-8727.rs @@ -0,0 +1,16 @@ +// Verify the compiler fails with an error on infinite function +// recursions. + +// build-fail +// normalize-stderr-test: ".nll/" -> "/" + +fn generic() { //~ WARN function cannot return without recursing + generic::>(); +} +//~^^ ERROR reached the recursion limit while instantiating `generic:: at least once to trigger instantiation. + generic::(); +} diff --git a/tests/ui/issues/issue-8727.stderr b/tests/ui/issues/issue-8727.stderr new file mode 100644 index 000000000..22332b357 --- /dev/null +++ b/tests/ui/issues/issue-8727.stderr @@ -0,0 +1,26 @@ +warning: function cannot return without recursing + --> $DIR/issue-8727.rs:7:1 + | +LL | fn generic() { + | ^^^^^^^^^^^^^^^ cannot return without recursing +LL | generic::>(); + | ---------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: reached the recursion limit while instantiating `generic::>>>>>` + --> $DIR/issue-8727.rs:8:5 + | +LL | generic::>(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: `generic` defined here + --> $DIR/issue-8727.rs:7:1 + | +LL | fn generic() { + | ^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727/issue-8727.long-type.txt' + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/issues/issue-87490.rs b/tests/ui/issues/issue-87490.rs new file mode 100644 index 000000000..998f61a6b --- /dev/null +++ b/tests/ui/issues/issue-87490.rs @@ -0,0 +1,10 @@ +fn main() {} +trait StreamOnce { + type Position; +} +impl StreamOnce for &str { + type Position = usize; +} +fn follow(_: &str) -> <&str as StreamOnce>::Position { + String::new //~ ERROR mismatched types +} diff --git a/tests/ui/issues/issue-87490.stderr b/tests/ui/issues/issue-87490.stderr new file mode 100644 index 000000000..f359dd638 --- /dev/null +++ b/tests/ui/issues/issue-87490.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-87490.rs:9:5 + | +LL | fn follow(_: &str) -> <&str as StreamOnce>::Position { + | ------------------------------ expected `usize` because of return type +LL | String::new + | ^^^^^^^^^^^ expected `usize`, found fn item + | + = note: expected type `usize` + found fn item `fn() -> String {String::new}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-8761.rs b/tests/ui/issues/issue-8761.rs new file mode 100644 index 000000000..1453c3d75 --- /dev/null +++ b/tests/ui/issues/issue-8761.rs @@ -0,0 +1,10 @@ +enum Foo { + A = 1i64, + //~^ ERROR mismatched types + //~| expected `isize`, found `i64` + B = 2u8 + //~^ ERROR mismatched types + //~| expected `isize`, found `u8` +} + +fn main() {} diff --git a/tests/ui/issues/issue-8761.stderr b/tests/ui/issues/issue-8761.stderr new file mode 100644 index 000000000..c70093baf --- /dev/null +++ b/tests/ui/issues/issue-8761.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/issue-8761.rs:2:9 + | +LL | A = 1i64, + | ^^^^ expected `isize`, found `i64` + | +help: change the type of the numeric literal from `i64` to `isize` + | +LL | A = 1isize, + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/issue-8761.rs:5:9 + | +LL | B = 2u8 + | ^^^ expected `isize`, found `u8` + | +help: change the type of the numeric literal from `u8` to `isize` + | +LL | B = 2isize + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-8767.rs b/tests/ui/issues/issue-8767.rs new file mode 100644 index 000000000..972101a0b --- /dev/null +++ b/tests/ui/issues/issue-8767.rs @@ -0,0 +1,5 @@ +impl B { //~ ERROR cannot find type `B` in this scope +} + +fn main() { +} diff --git a/tests/ui/issues/issue-8767.stderr b/tests/ui/issues/issue-8767.stderr new file mode 100644 index 000000000..91d99f393 --- /dev/null +++ b/tests/ui/issues/issue-8767.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `B` in this scope + --> $DIR/issue-8767.rs:1:6 + | +LL | impl B { + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-87707.rs b/tests/ui/issues/issue-87707.rs new file mode 100644 index 000000000..c14e52dfe --- /dev/null +++ b/tests/ui/issues/issue-87707.rs @@ -0,0 +1,17 @@ +// test for #87707 +// edition:2018 +// run-fail +// exec-env:RUST_BACKTRACE=0 +// check-run-results +// needs-unwind uses catch_unwind + +use std::sync::Once; +use std::panic; + +fn main() { + let o = Once::new(); + let _ = panic::catch_unwind(|| { + o.call_once(|| panic!("Here Once instance is poisoned.")); + }); + o.call_once(|| {}); +} diff --git a/tests/ui/issues/issue-87707.run.stderr b/tests/ui/issues/issue-87707.run.stderr new file mode 100644 index 000000000..527c78ba8 --- /dev/null +++ b/tests/ui/issues/issue-87707.run.stderr @@ -0,0 +1,3 @@ +thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:14:24 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:16:7 diff --git a/tests/ui/issues/issue-8783.rs b/tests/ui/issues/issue-8783.rs new file mode 100644 index 000000000..4eb49c821 --- /dev/null +++ b/tests/ui/issues/issue-8783.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +use std::default::Default; + +struct X { pub x: usize } +impl Default for X { + fn default() -> X { + X { x: 42 } + } +} + +struct Y { pub y: T } +impl Default for Y { + fn default() -> Y { + Y { y: Default::default() } + } +} + +fn main() { + let X { x: _ } = Default::default(); + let Y { y: X { x } } = Default::default(); +} diff --git a/tests/ui/issues/issue-88150.rs b/tests/ui/issues/issue-88150.rs new file mode 100644 index 000000000..555a38637 --- /dev/null +++ b/tests/ui/issues/issue-88150.rs @@ -0,0 +1,21 @@ +// run-pass +// compile-flags:-C debuginfo=2 +// edition:2018 + +use core::marker::PhantomData; + +pub struct Foo( + PhantomData<(A, T)>, +); + +enum Never {} + +impl Foo { + fn new_foo() -> Foo { + Foo(PhantomData) + } +} + +fn main() { + let _ = Foo::<[()], Never>::new_foo(); +} diff --git a/tests/ui/issues/issue-8860.rs b/tests/ui/issues/issue-8860.rs new file mode 100644 index 000000000..b89a80c13 --- /dev/null +++ b/tests/ui/issues/issue-8860.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(dead_code)] + +static mut DROP: isize = 0; +static mut DROP_S: isize = 0; +static mut DROP_T: isize = 0; + +struct S; +impl Drop for S { + fn drop(&mut self) { + unsafe { + DROP_S += 1; + DROP += 1; + } + } +} +fn f(ref _s: S) {} + +struct T { i: isize } +impl Drop for T { + fn drop(&mut self) { + unsafe { + DROP_T += 1; + DROP += 1; + } + } +} +fn g(ref _t: T) {} + +fn do_test() { + let s = S; + f(s); + unsafe { + assert_eq!(1, DROP); + assert_eq!(1, DROP_S); + } + let t = T { i: 1 }; + g(t); + unsafe { assert_eq!(1, DROP_T); } +} + +fn main() { + do_test(); + unsafe { + assert_eq!(2, DROP); + assert_eq!(1, DROP_S); + assert_eq!(1, DROP_T); + } +} diff --git a/tests/ui/issues/issue-8898.rs b/tests/ui/issues/issue-8898.rs new file mode 100644 index 000000000..31d5ff86e --- /dev/null +++ b/tests/ui/issues/issue-8898.rs @@ -0,0 +1,18 @@ +// run-pass + +fn assert_repr_eq(obj : T, expected : String) { + assert_eq!(expected, format!("{:?}", obj)); +} + +pub fn main() { + let abc = [1, 2, 3]; + let tf = [true, false]; + let x = [(), ()]; + let slice = &x[..1]; + + assert_repr_eq(&abc[..], "[1, 2, 3]".to_string()); + assert_repr_eq(&tf[..], "[true, false]".to_string()); + assert_repr_eq(&x[..], "[(), ()]".to_string()); + assert_repr_eq(slice, "[()]".to_string()); + assert_repr_eq(&x[..], "[(), ()]".to_string()); +} diff --git a/tests/ui/issues/issue-9047.rs b/tests/ui/issues/issue-9047.rs new file mode 100644 index 000000000..fa8d75aec --- /dev/null +++ b/tests/ui/issues/issue-9047.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +fn decode() -> String { + 'outer: loop { + let mut ch_start: usize; + break 'outer; + } + "".to_string() +} + +pub fn main() { + println!("{}", decode()); +} diff --git a/tests/ui/issues/issue-9110.rs b/tests/ui/issues/issue-9110.rs new file mode 100644 index 000000000..cbf3c92d0 --- /dev/null +++ b/tests/ui/issues/issue-9110.rs @@ -0,0 +1,17 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 +#![allow(non_snake_case)] + +macro_rules! silly_macro { + () => ( + pub mod Qux { + pub struct Foo { x : u8 } + pub fn bar(_foo : Foo) {} + } + ); +} + +silly_macro!(); + +pub fn main() {} diff --git a/tests/ui/issues/issue-9123.rs b/tests/ui/issues/issue-9123.rs new file mode 100644 index 000000000..8c21d06c4 --- /dev/null +++ b/tests/ui/issues/issue-9123.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:issue-9123.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_9123; + +pub fn main() {} diff --git a/tests/ui/issues/issue-9129.rs b/tests/ui/issues/issue-9129.rs new file mode 100644 index 000000000..04110b3ae --- /dev/null +++ b/tests/ui/issues/issue-9129.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +// ignore-pretty unreported + +pub trait bomb { fn boom(&self, _: Ident); } +pub struct S; +impl bomb for S { fn boom(&self, _: Ident) { } } + +pub struct Ident { name: usize } + +macro_rules! int3 { () => ( { } ) } + +fn Ident_new() -> Ident { + int3!(); + Ident {name: 0x6789ABCD } +} + +pub fn light_fuse(fld: Box) { + int3!(); + let f = || { + int3!(); + fld.boom(Ident_new()); // *** 1 + }; + f(); +} + +pub fn main() { + let b = Box::new(S) as Box; + light_fuse(b); +} diff --git a/tests/ui/issues/issue-91489.rs b/tests/ui/issues/issue-91489.rs new file mode 100644 index 000000000..f028a4a3c --- /dev/null +++ b/tests/ui/issues/issue-91489.rs @@ -0,0 +1,40 @@ +// check-pass + +// regression test for #91489 + +use std::borrow::Borrow; +use std::borrow::Cow; + +pub struct VariantType {} +pub struct VariantTy {} + +impl Borrow for VariantType { + fn borrow(&self) -> &VariantTy { + unimplemented!() + } +} + +impl ToOwned for VariantTy { + type Owned = VariantType; + fn to_owned(&self) -> VariantType { + unimplemented!() + } +} + +impl VariantTy { + pub fn as_str(&self) -> () {} +} + +// the presence of this was causing all attempts to call `as_str` on +// `Cow<'_, VariantTy>, including in itself, to not find the method +static _TYP: () = { + let _ = || { + // should be found + Cow::Borrowed(&VariantTy {}).as_str(); + }; +}; + +fn main() { + // should be found + Cow::Borrowed(&VariantTy {}).as_str() +} diff --git a/tests/ui/issues/issue-9155.rs b/tests/ui/issues/issue-9155.rs new file mode 100644 index 000000000..4b5c451e8 --- /dev/null +++ b/tests/ui/issues/issue-9155.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:issue-9155.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_9155; + +struct Baz; + +pub fn main() { + issue_9155::Foo::new(Baz); +} diff --git a/tests/ui/issues/issue-9188.rs b/tests/ui/issues/issue-9188.rs new file mode 100644 index 000000000..34e61fdf6 --- /dev/null +++ b/tests/ui/issues/issue-9188.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-9188.rs + + +extern crate issue_9188; + +pub fn main() { + let a = issue_9188::bar(); + let b = issue_9188::foo::(); + assert_eq!(*a, *b); +} diff --git a/tests/ui/issues/issue-9243.rs b/tests/ui/issues/issue-9243.rs new file mode 100644 index 000000000..59fdb4662 --- /dev/null +++ b/tests/ui/issues/issue-9243.rs @@ -0,0 +1,16 @@ +// build-pass +#![allow(dead_code)] +// Regression test for issue 9243 +#![allow(non_upper_case_globals)] + +pub struct Test { + mem: isize, +} + +pub static g_test: Test = Test {mem: 0}; + +impl Drop for Test { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/issues/issue-9249.rs b/tests/ui/issues/issue-9249.rs new file mode 100644 index 000000000..caaba668a --- /dev/null +++ b/tests/ui/issues/issue-9249.rs @@ -0,0 +1,6 @@ +// check-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +static DATA:&'static [&'static str] = &["my string"]; +fn main() { } diff --git a/tests/ui/issues/issue-9259.rs b/tests/ui/issues/issue-9259.rs new file mode 100644 index 000000000..d838edbdd --- /dev/null +++ b/tests/ui/issues/issue-9259.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +struct A<'a> { + a: &'a [String], + b: Option<&'a [String]>, +} + +pub fn main() { + let b: &[String] = &["foo".to_string()]; + let a = A { + a: &["test".to_string()], + b: Some(b), + }; + assert_eq!(a.b.as_ref().unwrap()[0], "foo"); +} diff --git a/tests/ui/issues/issue-9382.rs b/tests/ui/issues/issue-9382.rs new file mode 100644 index 000000000..65718343f --- /dev/null +++ b/tests/ui/issues/issue-9382.rs @@ -0,0 +1,40 @@ +// pretty-expanded FIXME #23616 + + +// run-pass +#![allow(dead_code)] + +// Tests for a previous bug that occurred due to an interaction +// between struct field initialization and the auto-coercion +// from a vector to a slice. The drop glue was being invoked on +// the temporary slice with a wrong type, triggering an LLVM assert. + + +struct Thing1<'a> { + baz: &'a [Box], + bar: Box, +} + +struct Thing2<'a> { + baz: &'a [Box], + bar: u64, +} + +pub fn main() { + let _t1_fixed = Thing1 { + baz: &[], + bar: Box::new(32), + }; + Thing1 { + baz: &Vec::new(), + bar: Box::new(32), + }; + let _t2_fixed = Thing2 { + baz: &[], + bar: 32, + }; + Thing2 { + baz: &Vec::new(), + bar: 32, + }; +} diff --git a/tests/ui/issues/issue-9446.rs b/tests/ui/issues/issue-9446.rs new file mode 100644 index 000000000..e200840d2 --- /dev/null +++ b/tests/ui/issues/issue-9446.rs @@ -0,0 +1,30 @@ +// run-pass +struct Wrapper(String); + +impl Wrapper { + pub fn new(wrapped: String) -> Wrapper { + Wrapper(wrapped) + } + + pub fn say_hi(&self) { + let Wrapper(ref s) = *self; + println!("hello {}", *s); + } +} + +impl Drop for Wrapper { + fn drop(&mut self) {} +} + +pub fn main() { + { + // This runs without complaint. + let x = Wrapper::new("Bob".to_string()); + x.say_hi(); + } + { + // This fails to compile, circa 0.8-89-gc635fba. + // error: internal compiler error: drop_ty_immediate: non-box ty + Wrapper::new("Bob".to_string()).say_hi(); + } +} diff --git a/tests/ui/issues/issue-948.rs b/tests/ui/issues/issue-948.rs new file mode 100644 index 000000000..b9bbeb395 --- /dev/null +++ b/tests/ui/issues/issue-948.rs @@ -0,0 +1,15 @@ +// run-fail +// error-pattern:beep boop +// ignore-emscripten no processes + +#![allow(unused_variables)] + +struct Point { + x: isize, + y: isize, +} + +fn main() { + let origin = Point { x: 0, y: 0 }; + let f: Point = Point { x: (panic!("beep boop")), ..origin }; +} diff --git a/tests/ui/issues/issue-9575.rs b/tests/ui/issues/issue-9575.rs new file mode 100644 index 000000000..06b252990 --- /dev/null +++ b/tests/ui/issues/issue-9575.rs @@ -0,0 +1,7 @@ +#![feature(start)] + +#[start] +fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize { + //~^ `#[start]` function has wrong type + 0 +} diff --git a/tests/ui/issues/issue-9575.stderr b/tests/ui/issues/issue-9575.stderr new file mode 100644 index 000000000..5b8ce84a0 --- /dev/null +++ b/tests/ui/issues/issue-9575.stderr @@ -0,0 +1,12 @@ +error[E0308]: `#[start]` function has wrong type + --> $DIR/issue-9575.rs:4:1 + | +LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `fn(isize, *const *const u8) -> _` + found fn pointer `fn(isize, *const *const u8, *const u8) -> _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-9719.rs b/tests/ui/issues/issue-9719.rs new file mode 100644 index 000000000..e8c3c9c19 --- /dev/null +++ b/tests/ui/issues/issue-9719.rs @@ -0,0 +1,41 @@ +// build-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +mod a { + pub enum Enum { + A(T), + } + + pub trait X { + fn dummy(&self) { } + } + impl X for isize {} + + pub struct Z<'a>(Enum<&'a (dyn X + 'a)>); + fn foo() { let x: isize = 42; let z = Z(Enum::A(&x as &dyn X)); let _ = z; } +} + +mod b { + trait X { + fn dummy(&self) { } + } + impl X for isize {} + struct Y<'a>{ + x:Option<&'a (dyn X + 'a)>, + } + + fn bar() { + let x: isize = 42; + let _y = Y { x: Some(&x as &dyn X) }; + } +} + +mod c { + pub trait X { fn f(&self); } + impl X for isize { fn f(&self) {} } + pub struct Z<'a>(Option<&'a (dyn X + 'a)>); + fn main() { let x: isize = 42; let z = Z(Some(&x as &dyn X)); let _ = z; } +} + +pub fn main() {} diff --git a/tests/ui/issues/issue-9725.rs b/tests/ui/issues/issue-9725.rs new file mode 100644 index 000000000..360effbd1 --- /dev/null +++ b/tests/ui/issues/issue-9725.rs @@ -0,0 +1,7 @@ +struct A { foo: isize } + +fn main() { + let A { foo, foo } = A { foo: 3 }; + //~^ ERROR: identifier `foo` is bound more than once in the same pattern + //~^^ ERROR: field `foo` bound multiple times +} diff --git a/tests/ui/issues/issue-9725.stderr b/tests/ui/issues/issue-9725.stderr new file mode 100644 index 000000000..687e0cc0f --- /dev/null +++ b/tests/ui/issues/issue-9725.stderr @@ -0,0 +1,18 @@ +error[E0416]: identifier `foo` is bound more than once in the same pattern + --> $DIR/issue-9725.rs:4:18 + | +LL | let A { foo, foo } = A { foo: 3 }; + | ^^^ used in a pattern more than once + +error[E0025]: field `foo` bound multiple times in the pattern + --> $DIR/issue-9725.rs:4:18 + | +LL | let A { foo, foo } = A { foo: 3 }; + | --- ^^^ multiple uses of `foo` in pattern + | | + | first use of `foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0025, E0416. +For more information about an error, try `rustc --explain E0025`. diff --git a/tests/ui/issues/issue-9737.rs b/tests/ui/issues/issue-9737.rs new file mode 100644 index 000000000..7d3e05678 --- /dev/null +++ b/tests/ui/issues/issue-9737.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_variables)] +macro_rules! f { + (v: $x:expr) => ( println!("{}", $x) ) +} + +fn main () { + let v = 5; + f!(v: 3); +} diff --git a/tests/ui/issues/issue-979.rs b/tests/ui/issues/issue-979.rs new file mode 100644 index 000000000..57a99b325 --- /dev/null +++ b/tests/ui/issues/issue-979.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(non_camel_case_types)] + +use std::cell::Cell; + +struct r<'a> { + b: &'a Cell, +} + +impl<'a> Drop for r<'a> { + fn drop(&mut self) { + self.b.set(self.b.get() + 1); + } +} + +fn r(b: &Cell) -> r { + r { + b: b + } +} + +pub fn main() { + let b = &Cell::new(0); + { + let _p = Some(r(b)); + } + + assert_eq!(b.get(), 1); +} diff --git a/tests/ui/issues/issue-9814.rs b/tests/ui/issues/issue-9814.rs new file mode 100644 index 000000000..a87478e22 --- /dev/null +++ b/tests/ui/issues/issue-9814.rs @@ -0,0 +1,8 @@ +// Verify that single-variant enums can't be de-referenced +// Regression test for issue #9814 + +enum Foo { Bar(isize) } + +fn main() { + let _ = *Foo::Bar(2); //~ ERROR type `Foo` cannot be dereferenced +} diff --git a/tests/ui/issues/issue-9814.stderr b/tests/ui/issues/issue-9814.stderr new file mode 100644 index 000000000..bd9e7df49 --- /dev/null +++ b/tests/ui/issues/issue-9814.stderr @@ -0,0 +1,9 @@ +error[E0614]: type `Foo` cannot be dereferenced + --> $DIR/issue-9814.rs:7:13 + | +LL | let _ = *Foo::Bar(2); + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/issues/issue-98299.rs b/tests/ui/issues/issue-98299.rs new file mode 100644 index 000000000..63c058f91 --- /dev/null +++ b/tests/ui/issues/issue-98299.rs @@ -0,0 +1,18 @@ +use std::convert::TryFrom; + +pub fn test_usage(p: ()) { + SmallCString::try_from(p).map(|cstr| cstr); + //~^ ERROR: type annotations needed +} + +pub struct SmallCString {} + +impl TryFrom<()> for SmallCString { + type Error = (); + + fn try_from(path: ()) -> Result { + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr new file mode 100644 index 000000000..fd905392a --- /dev/null +++ b/tests/ui/issues/issue-98299.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `SmallCString` + --> $DIR/issue-98299.rs:4:36 + | +LL | SmallCString::try_from(p).map(|cstr| cstr); + | ^^^^ + | +help: consider giving this closure parameter an explicit type, where the the value of const parameter `N` is specified + | +LL | SmallCString::try_from(p).map(|cstr: SmallCString| cstr); + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-9837.rs b/tests/ui/issues/issue-9837.rs new file mode 100644 index 000000000..5d2c822a5 --- /dev/null +++ b/tests/ui/issues/issue-9837.rs @@ -0,0 +1,11 @@ +// run-pass +const C1: i32 = 0x12345678; +const C2: isize = C1 as i16 as isize; + +enum E { + V = C2 +} + +fn main() { + assert_eq!(C2 as u64, E::V as u64); +} diff --git a/tests/ui/issues/issue-9906.rs b/tests/ui/issues/issue-9906.rs new file mode 100644 index 000000000..a2870cf0f --- /dev/null +++ b/tests/ui/issues/issue-9906.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-9906.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_9906 as testmod; + +pub fn main() { + testmod::foo(); + testmod::FooBar::new(1); +} diff --git a/tests/ui/issues/issue-9918.rs b/tests/ui/issues/issue-9918.rs new file mode 100644 index 000000000..63ad7040d --- /dev/null +++ b/tests/ui/issues/issue-9918.rs @@ -0,0 +1,5 @@ +// run-pass + +pub fn main() { + assert_eq!((0 + 0u8) as char, '\0'); +} diff --git a/tests/ui/issues/issue-9942.rs b/tests/ui/issues/issue-9942.rs new file mode 100644 index 000000000..f48804465 --- /dev/null +++ b/tests/ui/issues/issue-9942.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + const S: usize = 23 as usize; [0; S]; () +} diff --git a/tests/ui/issues/issue-9951.rs b/tests/ui/issues/issue-9951.rs new file mode 100644 index 000000000..2698a3b17 --- /dev/null +++ b/tests/ui/issues/issue-9951.rs @@ -0,0 +1,21 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +trait Bar { + fn noop(&self); +} +impl Bar for u8 { + fn noop(&self) {} +} + +fn main() { + let (a, b) = (&5u8 as &dyn Bar, &9u8 as &dyn Bar); + let (c, d): (&dyn Bar, &dyn Bar) = (a, b); + + let (a, b) = (Box::new(5u8) as Box, Box::new(9u8) as Box); + let (c, d): (&dyn Bar, &dyn Bar) = (&*a, &*b); + + let (c, d): (&dyn Bar, &dyn Bar) = (&5, &9); +} diff --git a/tests/ui/issues/issue-9968.rs b/tests/ui/issues/issue-9968.rs new file mode 100644 index 000000000..3ab90d99a --- /dev/null +++ b/tests/ui/issues/issue-9968.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:issue-9968.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_9968 as lib; + +use lib::{Trait, Struct}; + +pub fn main() +{ + Struct::init().test(); +} diff --git a/tests/ui/issues/issue-99838.rs b/tests/ui/issues/issue-99838.rs new file mode 100644 index 000000000..2e81d5e82 --- /dev/null +++ b/tests/ui/issues/issue-99838.rs @@ -0,0 +1,40 @@ +// run-pass + +use std::hint; + +struct U16(u16); + +impl Drop for U16 { + fn drop(&mut self) { + // Prevent LLVM from optimizing away our alignment check. + assert!(hint::black_box(self as *mut U16 as usize) % 2 == 0); + } +} + +struct HasDrop; + +impl Drop for HasDrop { + fn drop(&mut self) {} +} + +struct Wrapper { + _a: U16, + b: HasDrop, +} + +#[repr(packed)] +struct Misalign(u8, Wrapper); + +fn main() { + let m = Misalign( + 0, + Wrapper { + _a: U16(10), + b: HasDrop, + }, + ); + // Put it somewhere definitely even (so the `a` field is definitely at an odd address). + let m: ([u16; 0], Misalign) = ([], m); + // Move out one field, so we run custom per-field drop logic below. + let _x = m.1.1.b; +} diff --git a/tests/ui/issues/issue-pr29383.rs b/tests/ui/issues/issue-pr29383.rs new file mode 100644 index 000000000..2bcc0aa27 --- /dev/null +++ b/tests/ui/issues/issue-pr29383.rs @@ -0,0 +1,14 @@ +enum E { + A, + B, +} + +fn main() { + match None { + None => {} + Some(E::A(..)) => {} + //~^ ERROR expected tuple struct or tuple variant, found unit variant `E::A` + Some(E::B(..)) => {} + //~^ ERROR expected tuple struct or tuple variant, found unit variant `E::B` + } +} diff --git a/tests/ui/issues/issue-pr29383.stderr b/tests/ui/issues/issue-pr29383.stderr new file mode 100644 index 000000000..57783d75b --- /dev/null +++ b/tests/ui/issues/issue-pr29383.stderr @@ -0,0 +1,21 @@ +error[E0532]: expected tuple struct or tuple variant, found unit variant `E::A` + --> $DIR/issue-pr29383.rs:9:14 + | +LL | A, + | - `E::A` defined here +... +LL | Some(E::A(..)) => {} + | ^^^^^^^^ help: use this syntax instead: `E::A` + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E::B` + --> $DIR/issue-pr29383.rs:11:14 + | +LL | B, + | - `E::B` defined here +... +LL | Some(E::B(..)) => {} + | ^^^^^^^^ help: use this syntax instead: `E::B` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/item-name-overload.rs b/tests/ui/item-name-overload.rs new file mode 100644 index 000000000..c8a302a2c --- /dev/null +++ b/tests/ui/item-name-overload.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(dead_code)] + + + +// pretty-expanded FIXME #23616 + +mod foo { + pub fn baz() { } +} + +mod bar { + pub fn baz() { } +} + +pub fn main() { } diff --git a/tests/ui/iterators/array-of-ranges.rs b/tests/ui/iterators/array-of-ranges.rs new file mode 100644 index 000000000..037540a3e --- /dev/null +++ b/tests/ui/iterators/array-of-ranges.rs @@ -0,0 +1,16 @@ +// check-pass + +fn main() { + for _ in [0..1] {} + for _ in [0..=1] {} + for _ in [0..] {} + for _ in [..1] {} + for _ in [..=1] {} + let start = 0; + let end = 0; + for _ in [start..end] {} + let array_of_range = [start..end]; + for _ in array_of_range {} + for _ in [0..1, 2..3] {} + for _ in [0..=1] {} +} diff --git a/tests/ui/iterators/array.rs b/tests/ui/iterators/array.rs new file mode 100644 index 000000000..5985c74e1 --- /dev/null +++ b/tests/ui/iterators/array.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() { + for _ in [1, 2] {} + let x = [1, 2]; + for _ in x {} + for _ in [1.0, 2.0] {} +} diff --git a/tests/ui/iterators/bound.rs b/tests/ui/iterators/bound.rs new file mode 100644 index 000000000..bdd99ef8d --- /dev/null +++ b/tests/ui/iterators/bound.rs @@ -0,0 +1,4 @@ +struct S(I); +struct T(S); +//~^ ERROR is not an iterator +fn main() {} diff --git a/tests/ui/iterators/bound.stderr b/tests/ui/iterators/bound.stderr new file mode 100644 index 000000000..cc7ded498 --- /dev/null +++ b/tests/ui/iterators/bound.stderr @@ -0,0 +1,17 @@ +error[E0277]: `u8` is not an iterator + --> $DIR/bound.rs:2:10 + | +LL | struct T(S); + | ^^^^^ `u8` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u8` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` +note: required by a bound in `S` + --> $DIR/bound.rs:1:13 + | +LL | struct S(I); + | ^^^^^^^^ required by this bound in `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/collect-into-array.rs b/tests/ui/iterators/collect-into-array.rs new file mode 100644 index 000000000..99d0d9bd7 --- /dev/null +++ b/tests/ui/iterators/collect-into-array.rs @@ -0,0 +1,6 @@ +fn main() { + let whatever: [u32; 10] = (0..10).collect(); + //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator + //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()` + //~| NOTE required by a bound in `collect` +} diff --git a/tests/ui/iterators/collect-into-array.stderr b/tests/ui/iterators/collect-into-array.stderr new file mode 100644 index 000000000..e38745cc1 --- /dev/null +++ b/tests/ui/iterators/collect-into-array.stderr @@ -0,0 +1,13 @@ +error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator + --> $DIR/collect-into-array.rs:2:39 + | +LL | let whatever: [u32; 10] = (0..10).collect(); + | ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs new file mode 100644 index 000000000..5a8aacb1a --- /dev/null +++ b/tests/ui/iterators/collect-into-slice.rs @@ -0,0 +1,17 @@ +fn process_slice(data: &[i32]) { + todo!() +} + +fn main() { + let some_generated_vec = (0..10).collect(); + //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time + //~| ERROR the size for values of type `[i32]` cannot be known at compilation time + //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size + //~| NOTE try explicitly collecting into a `Vec<{integer}>` + //~| NOTE required by a bound in `collect` + //~| NOTE required by a bound in `collect` + //~| NOTE all local variables must have a statically known size + //~| NOTE doesn't have a size known at compile-time + //~| NOTE doesn't have a size known at compile-time + process_slice(&some_generated_vec); +} diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr new file mode 100644 index 000000000..29fff8c51 --- /dev/null +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -0,0 +1,33 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/collect-into-slice.rs:6:9 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/collect-into-slice.rs:6:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size + --> $DIR/collect-into-slice.rs:6:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/float_iterator_hint.rs b/tests/ui/iterators/float_iterator_hint.rs new file mode 100644 index 000000000..a3335ca41 --- /dev/null +++ b/tests/ui/iterators/float_iterator_hint.rs @@ -0,0 +1,15 @@ +// #106728 + +fn main() { + for i in 0.2 { + //~^ ERROR `{float}` is not an iterator + //~| `{float}` is not an iterator + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + //~| NOTE required for `{float}` to implement `IntoIterator` + println!(); + } +} diff --git a/tests/ui/iterators/float_iterator_hint.stderr b/tests/ui/iterators/float_iterator_hint.stderr new file mode 100644 index 000000000..bae23a1f8 --- /dev/null +++ b/tests/ui/iterators/float_iterator_hint.stderr @@ -0,0 +1,13 @@ +error[E0277]: `{float}` is not an iterator + --> $DIR/float_iterator_hint.rs:4:14 + | +LL | for i in 0.2 { + | ^^^ `{float}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{float}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{float}` to implement `IntoIterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/integral.rs b/tests/ui/iterators/integral.rs new file mode 100644 index 000000000..7537c7904 --- /dev/null +++ b/tests/ui/iterators/integral.rs @@ -0,0 +1,26 @@ +fn main() { + for _ in 42 {} + //~^ ERROR `{integer}` is not an iterator + for _ in 42 as u8 {} + //~^ ERROR `u8` is not an iterator + for _ in 42 as i8 {} + //~^ ERROR `i8` is not an iterator + for _ in 42 as u16 {} + //~^ ERROR `u16` is not an iterator + for _ in 42 as i16 {} + //~^ ERROR `i16` is not an iterator + for _ in 42 as u32 {} + //~^ ERROR `u32` is not an iterator + for _ in 42 as i32 {} + //~^ ERROR `i32` is not an iterator + for _ in 42 as u64 {} + //~^ ERROR `u64` is not an iterator + for _ in 42 as i64 {} + //~^ ERROR `i64` is not an iterator + for _ in 42 as usize {} + //~^ ERROR `usize` is not an iterator + for _ in 42 as isize {} + //~^ ERROR `isize` is not an iterator + for _ in 42.0 {} + //~^ ERROR `{float}` is not an iterator +} diff --git a/tests/ui/iterators/integral.stderr b/tests/ui/iterators/integral.stderr new file mode 100644 index 000000000..c142fec8d --- /dev/null +++ b/tests/ui/iterators/integral.stderr @@ -0,0 +1,123 @@ +error[E0277]: `{integer}` is not an iterator + --> $DIR/integral.rs:2:14 + | +LL | for _ in 42 {} + | ^^ `{integer}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{integer}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{integer}` to implement `IntoIterator` + +error[E0277]: `u8` is not an iterator + --> $DIR/integral.rs:4:14 + | +LL | for _ in 42 as u8 {} + | ^^^^^^^^ `u8` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u8` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u8` to implement `IntoIterator` + +error[E0277]: `i8` is not an iterator + --> $DIR/integral.rs:6:14 + | +LL | for _ in 42 as i8 {} + | ^^^^^^^^ `i8` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i8` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i8` to implement `IntoIterator` + +error[E0277]: `u16` is not an iterator + --> $DIR/integral.rs:8:14 + | +LL | for _ in 42 as u16 {} + | ^^^^^^^^^ `u16` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u16` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u16` to implement `IntoIterator` + +error[E0277]: `i16` is not an iterator + --> $DIR/integral.rs:10:14 + | +LL | for _ in 42 as i16 {} + | ^^^^^^^^^ `i16` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i16` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i16` to implement `IntoIterator` + +error[E0277]: `u32` is not an iterator + --> $DIR/integral.rs:12:14 + | +LL | for _ in 42 as u32 {} + | ^^^^^^^^^ `u32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u32` to implement `IntoIterator` + +error[E0277]: `i32` is not an iterator + --> $DIR/integral.rs:14:14 + | +LL | for _ in 42 as i32 {} + | ^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i32` to implement `IntoIterator` + +error[E0277]: `u64` is not an iterator + --> $DIR/integral.rs:16:14 + | +LL | for _ in 42 as u64 {} + | ^^^^^^^^^ `u64` is not an iterator + | + = help: the trait `Iterator` is not implemented for `u64` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `u64` to implement `IntoIterator` + +error[E0277]: `i64` is not an iterator + --> $DIR/integral.rs:18:14 + | +LL | for _ in 42 as i64 {} + | ^^^^^^^^^ `i64` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i64` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i64` to implement `IntoIterator` + +error[E0277]: `usize` is not an iterator + --> $DIR/integral.rs:20:14 + | +LL | for _ in 42 as usize {} + | ^^^^^^^^^^^ `usize` is not an iterator + | + = help: the trait `Iterator` is not implemented for `usize` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `usize` to implement `IntoIterator` + +error[E0277]: `isize` is not an iterator + --> $DIR/integral.rs:22:14 + | +LL | for _ in 42 as isize {} + | ^^^^^^^^^^^ `isize` is not an iterator + | + = help: the trait `Iterator` is not implemented for `isize` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `isize` to implement `IntoIterator` + +error[E0277]: `{float}` is not an iterator + --> $DIR/integral.rs:24:14 + | +LL | for _ in 42.0 {} + | ^^^^ `{float}` is not an iterator + | + = help: the trait `Iterator` is not implemented for `{float}` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `{float}` to implement `IntoIterator` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.rs b/tests/ui/iterators/into-iter-on-arrays-2018.rs new file mode 100644 index 000000000..60995170a --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-2018.rs @@ -0,0 +1,46 @@ +// check-pass +// edition:2018 + +use std::array::IntoIter; +use std::ops::Deref; +use std::rc::Rc; +use std::slice::Iter; + +fn main() { + let array = [0; 10]; + + // Before 2021, the method dispatched to `IntoIterator for &[T; N]`, + // which we continue to support for compatibility. + let _: Iter<'_, i32> = array.into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + let _: Iter<'_, i32> = Box::new(array).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + let _: Iter<'_, i32> = Rc::new(array).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + let _: Iter<'_, i32> = Array(array).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + // But you can always use the trait method explicitly as an array. + let _: IntoIter = IntoIterator::into_iter(array); + + for _ in [1, 2, 3].into_iter() {} + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning +} + +/// User type that dereferences to an array. +struct Array([i32; 10]); + +impl Deref for Array { + type Target = [i32; 10]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/tests/ui/iterators/into-iter-on-arrays-2018.stderr b/tests/ui/iterators/into-iter-on-arrays-2018.stderr new file mode 100644 index 000000000..2378476e5 --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-2018.stderr @@ -0,0 +1,65 @@ +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-2018.rs:14:34 + | +LL | let _: Iter<'_, i32> = array.into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + = note: `#[warn(array_into_iter)]` on by default +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | let _: Iter<'_, i32> = array.iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | let _: Iter<'_, i32> = IntoIterator::into_iter(array); + | ++++++++++++++++++++++++ ~ + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-2018.rs:18:44 + | +LL | let _: Iter<'_, i32> = Box::new(array).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-2018.rs:22:43 + | +LL | let _: Iter<'_, i32> = Rc::new(array).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-2018.rs:25:41 + | +LL | let _: Iter<'_, i32> = Array(array).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-2018.rs:32:24 + | +LL | for _ in [1, 2, 3].into_iter() {} + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | for _ in [1, 2, 3].iter() {} + | ~~~~ +help: or remove `.into_iter()` to iterate by value + | +LL - for _ in [1, 2, 3].into_iter() {} +LL + for _ in [1, 2, 3] {} + | + +warning: 5 warnings emitted + diff --git a/tests/ui/iterators/into-iter-on-arrays-2021.rs b/tests/ui/iterators/into-iter-on-arrays-2021.rs new file mode 100644 index 000000000..158317efe --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-2021.rs @@ -0,0 +1,32 @@ +// check-pass +// edition:2021 + +use std::array::IntoIter; +use std::ops::Deref; +use std::rc::Rc; + +fn main() { + let array = [0; 10]; + + // In 2021, the method dispatches to `IntoIterator for [T; N]`. + let _: IntoIter = array.into_iter(); + let _: IntoIter = Box::new(array).into_iter(); + + // The `array_into_iter` lint doesn't cover other wrappers that deref to an array. + let _: IntoIter = Rc::new(array).into_iter(); + let _: IntoIter = Array(array).into_iter(); + + // You can always use the trait method explicitly as an array. + let _: IntoIter = IntoIterator::into_iter(array); +} + +/// User type that dereferences to an array. +struct Array([i32; 10]); + +impl Deref for Array { + type Target = [i32; 10]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.fixed b/tests/ui/iterators/into-iter-on-arrays-lint.fixed new file mode 100644 index 000000000..6e02a7024 --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-lint.fixed @@ -0,0 +1,63 @@ +// run-pass +// run-rustfix +// rustfix-only-machine-applicable + +#[allow(unused_must_use)] +fn main() { + let small = [1, 2]; + let big = [0u8; 33]; + + // Expressions that should trigger the lint + small.iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [1, 2].iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + big.iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [0u8; 33].iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + Box::new(small).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new([1, 2]).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(big).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new([0u8; 33]).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + Box::new(Box::new(small)).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(Box::new([1, 2])).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(Box::new(big)).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(Box::new([0u8; 33])).iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + // Expressions that should not + (&[1, 2]).into_iter(); + (&small).into_iter(); + (&[0u8; 33]).into_iter(); + (&big).into_iter(); + + for _ in &[1, 2] {} + (&small as &[_]).into_iter(); + small[..].into_iter(); + std::iter::IntoIterator::into_iter(&[1, 2]); + + #[allow(array_into_iter)] + [0, 1].into_iter(); +} diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.rs b/tests/ui/iterators/into-iter-on-arrays-lint.rs new file mode 100644 index 000000000..582d5cadd --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-lint.rs @@ -0,0 +1,63 @@ +// run-pass +// run-rustfix +// rustfix-only-machine-applicable + +#[allow(unused_must_use)] +fn main() { + let small = [1, 2]; + let big = [0u8; 33]; + + // Expressions that should trigger the lint + small.into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [1, 2].into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + big.into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + [0u8; 33].into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + Box::new(small).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new([1, 2]).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(big).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new([0u8; 33]).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + Box::new(Box::new(small)).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(Box::new([1, 2])).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(Box::new(big)).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + Box::new(Box::new([0u8; 33])).into_iter(); + //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter` + //~| WARNING this changes meaning + + // Expressions that should not + (&[1, 2]).into_iter(); + (&small).into_iter(); + (&[0u8; 33]).into_iter(); + (&big).into_iter(); + + for _ in &[1, 2] {} + (&small as &[_]).into_iter(); + small[..].into_iter(); + std::iter::IntoIterator::into_iter(&[1, 2]); + + #[allow(array_into_iter)] + [0, 1].into_iter(); +} diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.stderr b/tests/ui/iterators/into-iter-on-arrays-lint.stderr new file mode 100644 index 000000000..2fde276fa --- /dev/null +++ b/tests/ui/iterators/into-iter-on-arrays-lint.stderr @@ -0,0 +1,143 @@ +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:11:11 + | +LL | small.into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + = note: `#[warn(array_into_iter)]` on by default +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | small.iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(small); + | ++++++++++++++++++++++++ ~ + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:14:12 + | +LL | [1, 2].into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | [1, 2].iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter([1, 2]); + | ++++++++++++++++++++++++ ~ + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:17:9 + | +LL | big.into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | big.iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter(big); + | ++++++++++++++++++++++++ ~ + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:20:15 + | +LL | [0u8; 33].into_iter(); + | ^^^^^^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see +help: use `.iter()` instead of `.into_iter()` to avoid ambiguity + | +LL | [0u8; 33].iter(); + | ~~~~ +help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value + | +LL | IntoIterator::into_iter([0u8; 33]); + | ++++++++++++++++++++++++ ~ + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:24:21 + | +LL | Box::new(small).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:27:22 + | +LL | Box::new([1, 2]).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:30:19 + | +LL | Box::new(big).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:33:25 + | +LL | Box::new([0u8; 33]).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:37:31 + | +LL | Box::new(Box::new(small)).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:40:32 + | +LL | Box::new(Box::new([1, 2])).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:43:29 + | +LL | Box::new(Box::new(big)).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021 + --> $DIR/into-iter-on-arrays-lint.rs:46:35 + | +LL | Box::new(Box::new([0u8; 33])).into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see + +warning: 12 warnings emitted + diff --git a/tests/ui/iterators/into-iterator-type-inference-shift.rs b/tests/ui/iterators/into-iterator-type-inference-shift.rs new file mode 100644 index 000000000..9151172fd --- /dev/null +++ b/tests/ui/iterators/into-iterator-type-inference-shift.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] +// Regression test for type inference failure around shifting. In this +// case, the iteration yields an isize, but we hadn't run the full type +// propagation yet, and so we just saw a type variable, yielding an +// error. + +// pretty-expanded FIXME #23616 + +trait IntoIterator { + type Iter: Iterator; + + fn into_iter(self) -> Self::Iter; +} + +impl IntoIterator for I where I: Iterator { + type Iter = I; + + fn into_iter(self) -> I { + self + } +} + +fn desugared_for_loop_bad(byte: u8) -> u8 { + let mut result = 0; + let mut x = IntoIterator::into_iter(0..8); + let mut y = Iterator::next(&mut x); + let mut z = y.unwrap(); + byte >> z; + 1 +} + +fn main() {} diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs new file mode 100644 index 000000000..882a1d139 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.rs @@ -0,0 +1,4 @@ +fn main() { + let x = Some(()).iter().map(|()| 1).sum::(); + //~^ ERROR a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}` +} diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr new file mode 100644 index 000000000..3cb5e44c7 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr @@ -0,0 +1,24 @@ +error[E0277]: a value of type `f32` cannot be made by summing an iterator over elements of type `{integer}` + --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:41 + | +LL | let x = Some(()).iter().map(|()| 1).sum::(); + | ^^^ value of type `f32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-with-int-infer.rs:2:29 + | +LL | let x = Some(()).iter().map(|()| 1).sum::(); + | -------- ------ ^^^^^^^^^^^ `Iterator::Item` changed to `{integer}` here + | | | + | | `Iterator::Item` is `&()` here + | this expression has type `Option<()>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/invalid-iterator-chain.rs b/tests/ui/iterators/invalid-iterator-chain.rs new file mode 100644 index 000000000..ebdf33303 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain.rs @@ -0,0 +1,53 @@ +use std::collections::hash_set::Iter; +use std::collections::HashSet; + +fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + let i = i.map(|x| x.clone()); + i.collect() //~ ERROR E0277 +} + +fn main() { + let scores = vec![(0, 0)] + .iter() + .map(|(a, b)| { + a + b; + }); + println!("{}", scores.sum::()); //~ ERROR E0277 + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| x as f64) + .map(|x| x as i64) + .filter(|x| *x > 0) + .map(|x| { x + 1 }) + .map(|x| { x; }) + .sum::(), //~ ERROR E0277 + ); + println!( + "{}", + vec![0, 1] + .iter() + .map(|x| x * 2) + .map(|x| x as f64) + .filter(|x| *x > 0.0) + .map(|x| { x + 1.0 }) + .sum::(), //~ ERROR E0277 + ); + println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); //~ ERROR E0277 + println!("{}", vec![(), ()].iter().sum::()); //~ ERROR E0277 + let a = vec![0]; + let b = a.into_iter(); + let c = b.map(|x| x + 1); + let d = c.filter(|x| *x > 10 ); + let e = d.map(|x| { + x + 1; + }); + let f = e.filter(|_| false); + let g: Vec = f.collect(); //~ ERROR E0277 + + let mut s = HashSet::new(); + s.insert(1u8); + println!("{:?}", iter_to_vec(s.iter())); +} diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr new file mode 100644 index 000000000..f3dceca7e --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -0,0 +1,176 @@ +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&X` + --> $DIR/invalid-iterator-chain.rs:6:7 + | +LL | i.collect() + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<&X>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:4:26 + | +LL | fn iter_to_vec<'b, X>(i: Iter<'b, X>) -> Vec { + | ^^^^^^^^^^^ `Iterator::Item` is `&X` here +LL | let i = i.map(|x| x.clone()); + | ------------------ `Iterator::Item` remains `&X` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:15:27 + | +LL | println!("{}", scores.sum::()); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:12:10 + | +LL | let scores = vec![(0, 0)] + | ------------ this expression has type `Vec<({integer}, {integer})>` +LL | .iter() + | ------ `Iterator::Item` is `&({integer}, {integer})` here +LL | .map(|(a, b)| { + | __________^ +LL | | a + b; +LL | | }); + | |__________^ `Iterator::Item` changed to `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:26:14 + | +LL | .sum::(), + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:25:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- `Iterator::Item` changed to `{integer}` here +LL | .map(|x| x as f64) + | ----------------- `Iterator::Item` changed to `f64` here +LL | .map(|x| x as i64) + | ----------------- `Iterator::Item` changed to `i64` here +LL | .filter(|x| *x > 0) + | ------------------ `Iterator::Item` remains `i64` here +LL | .map(|x| { x + 1 }) + | ------------------ `Iterator::Item` remains `i64` here +LL | .map(|x| { x; }) + | ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `f64` + --> $DIR/invalid-iterator-chain.rs:36:14 + | +LL | .sum::(), + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:33:14 + | +LL | vec![0, 1] + | ---------- this expression has type `Vec<{integer}>` +LL | .iter() + | ------ `Iterator::Item` is `&{integer}` here +LL | .map(|x| x * 2) + | -------------- `Iterator::Item` changed to `{integer}` here +LL | .map(|x| x as f64) + | ^^^^^^^^^^^^^^^^^ `Iterator::Item` changed to `f64` here +LL | .filter(|x| *x > 0.0) + | -------------------- `Iterator::Item` remains `f64` here +LL | .map(|x| { x + 1.0 }) + | -------------------- `Iterator::Item` remains `f64` here +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:38:54 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:38:38 + | +LL | println!("{}", vec![0, 1].iter().map(|x| { x; }).sum::()); + | ---------- ------ ^^^^^^^^^^^^^^^ `Iterator::Item` changed to `()` here + | | | + | | `Iterator::Item` is `&{integer}` here + | this expression has type `Vec<{integer}>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` + --> $DIR/invalid-iterator-chain.rs:39:40 + | +LL | println!("{}", vec![(), ()].iter().sum::()); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<&()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:39:33 + | +LL | println!("{}", vec![(), ()].iter().sum::()); + | ------------ ^^^^^^ `Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `()` + --> $DIR/invalid-iterator-chain.rs:48:25 + | +LL | let g: Vec = f.collect(); + | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<()>` is not implemented for `Vec` + = help: the trait `FromIterator` is implemented for `Vec` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain.rs:44:15 + | +LL | let a = vec![0]; + | ------- this expression has type `Vec<{integer}>` +LL | let b = a.into_iter(); + | ----------- `Iterator::Item` is `{integer}` here +LL | let c = b.map(|x| x + 1); + | -------------- `Iterator::Item` remains `{integer}` here +LL | let d = c.filter(|x| *x > 10 ); + | -------------------- `Iterator::Item` remains `{integer}` here +LL | let e = d.map(|x| { + | _______________^ +LL | | x + 1; +LL | | }); + | |______^ `Iterator::Item` changed to `()` here +LL | let f = e.filter(|_| false); + | ----------------- `Iterator::Item` remains `()` here +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/issue-28098.rs b/tests/ui/iterators/issue-28098.rs new file mode 100644 index 000000000..80c77edae --- /dev/null +++ b/tests/ui/iterators/issue-28098.rs @@ -0,0 +1,31 @@ +fn main() { + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + for _ in false {} + //~^ ERROR `bool` is not an iterator + + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + other() +} + +pub fn other() { + // check errors are still reported globally + + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + let _ = Iterator::next(&mut ()); + //~^ ERROR `()` is not an iterator + //~| ERROR `()` is not an iterator + + for _ in false {} + //~^ ERROR `bool` is not an iterator +} diff --git a/tests/ui/iterators/issue-28098.stderr b/tests/ui/iterators/issue-28098.stderr new file mode 100644 index 000000000..3256e57d4 --- /dev/null +++ b/tests/ui/iterators/issue-28098.stderr @@ -0,0 +1,109 @@ +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `bool` is not an iterator + --> $DIR/issue-28098.rs:7:14 + | +LL | for _ in false {} + | ^^^^^ `bool` is not an iterator + | + = help: the trait `Iterator` is not implemented for `bool` + = note: required for `bool` to implement `IntoIterator` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:10:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:10:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:2:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:25:28 + | +LL | let _ = Iterator::next(&mut ()); + | -------------- ^^^^^^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:25:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error[E0277]: `bool` is not an iterator + --> $DIR/issue-28098.rs:29:14 + | +LL | for _ in false {} + | ^^^^^ `bool` is not an iterator + | + = help: the trait `Iterator` is not implemented for `bool` + = note: required for `bool` to implement `IntoIterator` + +error[E0277]: `()` is not an iterator + --> $DIR/issue-28098.rs:20:13 + | +LL | let _ = Iterator::next(&mut ()); + | ^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/issue-58952-filter-type-length.rs b/tests/ui/iterators/issue-58952-filter-type-length.rs new file mode 100644 index 000000000..6d12db8d1 --- /dev/null +++ b/tests/ui/iterators/issue-58952-filter-type-length.rs @@ -0,0 +1,32 @@ +// run-pass +//! This snippet causes the type length to blowup exponentially, +//! so check that we don't accidentally exceed the type length limit. +// FIXME: Once the size of iterator adaptors is further reduced, +// increase the complexity of this test. +use std::collections::VecDeque; + +fn main() { + let c = 2; + let bv = vec![2]; + let b = bv + .iter() + .filter(|a| **a == c); + + let _a = vec![1, 2, 3] + .into_iter() + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .filter(|a| b.clone().any(|b| *b == *a)) + .collect::>(); +} diff --git a/tests/ui/iterators/iter-cloned-type-inference.rs b/tests/ui/iterators/iter-cloned-type-inference.rs new file mode 100644 index 000000000..898e33719 --- /dev/null +++ b/tests/ui/iterators/iter-cloned-type-inference.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(stable_features)] + +// Test to see that the element type of .cloned() can be inferred +// properly. Previously this would fail to deduce the type of `sum`. + +#![feature(iter_arith)] + +fn square_sum(v: &[i64]) -> i64 { + let sum: i64 = v.iter().cloned().sum(); + sum * sum +} + +fn main() { + assert_eq!(36, square_sum(&[1,2,3])); +} diff --git a/tests/ui/iterators/iter-count-overflow-debug.rs b/tests/ui/iterators/iter-count-overflow-debug.rs new file mode 100644 index 000000000..8e59c11e9 --- /dev/null +++ b/tests/ui/iterators/iter-count-overflow-debug.rs @@ -0,0 +1,15 @@ +// run-pass +// only-32bit too impatient for 2â¶â´ items +// needs-unwind +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; + +fn main() { + assert_eq!((0..usize::MAX).by_ref().count(), usize::MAX); + + let r = panic::catch_unwind(|| { + (0..=usize::MAX).by_ref().count() + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-count-overflow-ndebug.rs b/tests/ui/iterators/iter-count-overflow-ndebug.rs new file mode 100644 index 000000000..dcaaff671 --- /dev/null +++ b/tests/ui/iterators/iter-count-overflow-ndebug.rs @@ -0,0 +1,8 @@ +// run-pass +// only-32bit too impatient for 2â¶â´ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +fn main() { + assert_eq!((0..usize::MAX).by_ref().count(), usize::MAX); + assert_eq!((0..=usize::MAX).by_ref().count(), 0); +} diff --git a/tests/ui/iterators/iter-map-fold-type-length.rs b/tests/ui/iterators/iter-map-fold-type-length.rs new file mode 100644 index 000000000..8ce4fcd87 --- /dev/null +++ b/tests/ui/iterators/iter-map-fold-type-length.rs @@ -0,0 +1,38 @@ +// run-pass +//! Check that type lengths don't explode with `Map` folds. +//! +//! The normal limit is a million, and this test used to exceed 1.5 million, but +//! now we can survive an even tighter limit. Still seems excessive though... +#![type_length_limit = "256000"] + +// Custom wrapper so Iterator methods aren't specialized. +struct Iter(I); + +impl Iterator for Iter +where + I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +fn main() { + let c = Iter(0i32..10) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .count(); + assert_eq!(c, 10); +} diff --git a/tests/ui/iterators/iter-position-overflow-debug.rs b/tests/ui/iterators/iter-position-overflow-debug.rs new file mode 100644 index 000000000..7a871e744 --- /dev/null +++ b/tests/ui/iterators/iter-position-overflow-debug.rs @@ -0,0 +1,21 @@ +// run-pass +// only-32bit too impatient for 2â¶â´ items +// needs-unwind +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; + +fn main() { + let n = usize::MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(usize::MAX)); + + let r = panic::catch_unwind(|| { + (0..).by_ref().position(|i| i > n) + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + (0..=n + 1).by_ref().position(|_| false) + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-position-overflow-ndebug.rs b/tests/ui/iterators/iter-position-overflow-ndebug.rs new file mode 100644 index 000000000..e610c3559 --- /dev/null +++ b/tests/ui/iterators/iter-position-overflow-ndebug.rs @@ -0,0 +1,10 @@ +// run-pass +// only-32bit too impatient for 2â¶â´ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +fn main() { + let n = usize::MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(usize::MAX)); + assert_eq!((0..).by_ref().position(|i| i > n), Some(0)); + assert_eq!((0..=n + 1).by_ref().position(|_| false), None); +} diff --git a/tests/ui/iterators/iter-range.rs b/tests/ui/iterators/iter-range.rs new file mode 100644 index 000000000..993d93790 --- /dev/null +++ b/tests/ui/iterators/iter-range.rs @@ -0,0 +1,14 @@ +// run-pass + + +fn range_(a: isize, b: isize, mut it: F) where F: FnMut(isize) { + assert!((a < b)); + let mut i: isize = a; + while i < b { it(i); i += 1; } +} + +pub fn main() { + let mut sum: isize = 0; + range_(0, 100, |x| sum += x ); + println!("{}", sum); +} diff --git a/tests/ui/iterators/iter-step-overflow-debug.rs b/tests/ui/iterators/iter-step-overflow-debug.rs new file mode 100644 index 000000000..6aa349ebe --- /dev/null +++ b/tests/ui/iterators/iter-step-overflow-debug.rs @@ -0,0 +1,21 @@ +// run-pass +// needs-unwind +// compile-flags: -C debug_assertions=yes + +use std::panic; + +fn main() { + let r = panic::catch_unwind(|| { + let mut it = u8::MAX..; + it.next().unwrap(); // 255 + it.next().unwrap(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + let mut it = i8::MAX..; + it.next().unwrap(); // 127 + it.next().unwrap(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-step-overflow-ndebug.rs b/tests/ui/iterators/iter-step-overflow-ndebug.rs new file mode 100644 index 000000000..33e708769 --- /dev/null +++ b/tests/ui/iterators/iter-step-overflow-ndebug.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: -C debug_assertions=no + +fn main() { + let mut it = u8::MAX..; + assert_eq!(it.next().unwrap(), 255); + assert_eq!(it.next().unwrap(), u8::MIN); + + let mut it = i8::MAX..; + assert_eq!(it.next().unwrap(), 127); + assert_eq!(it.next().unwrap(), i8::MIN); +} diff --git a/tests/ui/iterators/iter-sum-overflow-debug.rs b/tests/ui/iterators/iter-sum-overflow-debug.rs new file mode 100644 index 000000000..24c764ff9 --- /dev/null +++ b/tests/ui/iterators/iter-sum-overflow-debug.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind +// compile-flags: -C debug_assertions=yes + +use std::panic; + +fn main() { + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().sum::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().product::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().cloned().sum::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().cloned().product::(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/iter-sum-overflow-ndebug.rs b/tests/ui/iterators/iter-sum-overflow-ndebug.rs new file mode 100644 index 000000000..69f4744cc --- /dev/null +++ b/tests/ui/iterators/iter-sum-overflow-ndebug.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -C debug_assertions=no + +fn main() { + assert_eq!([1i32, i32::MAX].iter().sum::(), + 1i32.wrapping_add(i32::MAX)); + assert_eq!([2i32, i32::MAX].iter().product::(), + 2i32.wrapping_mul(i32::MAX)); + + assert_eq!([1i32, i32::MAX].iter().cloned().sum::(), + 1i32.wrapping_add(i32::MAX)); + assert_eq!([2i32, i32::MAX].iter().cloned().product::(), + 2i32.wrapping_mul(i32::MAX)); +} diff --git a/tests/ui/iterators/iter-sum-overflow-overflow-checks.rs b/tests/ui/iterators/iter-sum-overflow-overflow-checks.rs new file mode 100644 index 000000000..be45c075d --- /dev/null +++ b/tests/ui/iterators/iter-sum-overflow-overflow-checks.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind +// compile-flags: -C overflow-checks + +use std::panic; + +fn main() { + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().sum::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().product::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().cloned().sum::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::MAX].iter().cloned().product::(); + }); + assert!(r.is_err()); +} diff --git a/tests/ui/iterators/ranges.rs b/tests/ui/iterators/ranges.rs new file mode 100644 index 000000000..925d2d61a --- /dev/null +++ b/tests/ui/iterators/ranges.rs @@ -0,0 +1,9 @@ +fn main() { + for _ in ..10 {} + //~^ ERROR E0277 + for _ in ..=10 {} + //~^ ERROR E0277 + for _ in 0..10 {} + for _ in 0..=10 {} + for _ in 0.. {} +} diff --git a/tests/ui/iterators/ranges.stderr b/tests/ui/iterators/ranges.stderr new file mode 100644 index 000000000..b9fbcd530 --- /dev/null +++ b/tests/ui/iterators/ranges.stderr @@ -0,0 +1,23 @@ +error[E0277]: `RangeTo<{integer}>` is not an iterator + --> $DIR/ranges.rs:2:14 + | +LL | for _ in ..10 {} + | ^^^^ if you meant to iterate until a value, add a starting value + | + = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` + = note: required for `RangeTo<{integer}>` to implement `IntoIterator` + +error[E0277]: `RangeToInclusive<{integer}>` is not an iterator + --> $DIR/ranges.rs:4:14 + | +LL | for _ in ..=10 {} + | ^^^^^ if you meant to iterate until a value (including it), add a starting value + | + = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` + = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/rsplit-clone.rs b/tests/ui/iterators/rsplit-clone.rs new file mode 100644 index 000000000..911da7429 --- /dev/null +++ b/tests/ui/iterators/rsplit-clone.rs @@ -0,0 +1,11 @@ +// check-pass + +// RSplit previously required T: Clone in order to be Clone + +struct NotClone; + +fn main() { + let elements = [NotClone, NotClone, NotClone]; + let rsplit = elements.rsplit(|_| false); + rsplit.clone(); +} diff --git a/tests/ui/iterators/skip-count-overflow.rs b/tests/ui/iterators/skip-count-overflow.rs new file mode 100644 index 000000000..64dee3e3c --- /dev/null +++ b/tests/ui/iterators/skip-count-overflow.rs @@ -0,0 +1,8 @@ +// run-pass +// only-32bit too impatient for 2â¶â´ items +// compile-flags: -C overflow-checks -C opt-level=3 + +fn main() { + let i = (0..usize::MAX).chain(0..10).skip(usize::MAX); + assert_eq!(i.count(), 10); +} diff --git a/tests/ui/iterators/string.rs b/tests/ui/iterators/string.rs new file mode 100644 index 000000000..ad58a463e --- /dev/null +++ b/tests/ui/iterators/string.rs @@ -0,0 +1,6 @@ +fn main() { + for _ in "".to_owned() {} + //~^ ERROR `String` is not an iterator + for _ in "" {} + //~^ ERROR `&str` is not an iterator +} diff --git a/tests/ui/iterators/string.stderr b/tests/ui/iterators/string.stderr new file mode 100644 index 000000000..ddfe0169b --- /dev/null +++ b/tests/ui/iterators/string.stderr @@ -0,0 +1,21 @@ +error[E0277]: `String` is not an iterator + --> $DIR/string.rs:2:14 + | +LL | for _ in "".to_owned() {} + | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` + | + = help: the trait `Iterator` is not implemented for `String` + = note: required for `String` to implement `IntoIterator` + +error[E0277]: `&str` is not an iterator + --> $DIR/string.rs:4:14 + | +LL | for _ in "" {} + | ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` + | + = help: the trait `Iterator` is not implemented for `&str` + = note: required for `&str` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/vec-on-unimplemented.rs b/tests/ui/iterators/vec-on-unimplemented.rs new file mode 100644 index 000000000..42b5d36bf --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.rs @@ -0,0 +1,4 @@ +fn main() { + vec![true, false].map(|v| !v).collect::>(); + //~^ ERROR `Vec` is not an iterator +} diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr new file mode 100644 index 000000000..a7d9c481a --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -0,0 +1,18 @@ +error[E0599]: `Vec` is not an iterator + --> $DIR/vec-on-unimplemented.rs:2:23 + | +LL | vec![true, false].map(|v| !v).collect::>(); + | ^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | + = note: doesn't satisfy `Vec: Iterator` + | + = note: the following trait bounds were not satisfied: + `Vec: Iterator` + which is required by `&mut Vec: Iterator` + `[bool]: Iterator` + which is required by `&mut [bool]: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/json/json-and-color.rs b/tests/ui/json/json-and-color.rs new file mode 100644 index 000000000..6f8326fe2 --- /dev/null +++ b/tests/ui/json/json-and-color.rs @@ -0,0 +1,3 @@ +// compile-flags: --json=artifacts --error-format=json --color never + +fn main() {} diff --git a/tests/ui/json/json-and-color.stderr b/tests/ui/json/json-and-color.stderr new file mode 100644 index 000000000..1cda6af09 --- /dev/null +++ b/tests/ui/json/json-and-color.stderr @@ -0,0 +1,2 @@ +error: cannot specify the `--color` option with `--json` + diff --git a/tests/ui/json/json-and-error-format.rs b/tests/ui/json/json-and-error-format.rs new file mode 100644 index 000000000..6e2d73c76 --- /dev/null +++ b/tests/ui/json/json-and-error-format.rs @@ -0,0 +1,3 @@ +// compile-flags: --json=artifacts --error-format=short + +fn main() {} diff --git a/tests/ui/json/json-and-error-format.stderr b/tests/ui/json/json-and-error-format.stderr new file mode 100644 index 000000000..80e022137 --- /dev/null +++ b/tests/ui/json/json-and-error-format.stderr @@ -0,0 +1,2 @@ +error: using `--json` requires also using `--error-format=json` + diff --git a/tests/ui/json/json-bom-plus-crlf-multifile-aux.rs b/tests/ui/json/json-bom-plus-crlf-multifile-aux.rs new file mode 100644 index 000000000..991ea1d85 --- /dev/null +++ b/tests/ui/json/json-bom-plus-crlf-multifile-aux.rs @@ -0,0 +1,27 @@ +// (This line has BOM so it's ignored by compiletest for directives) +// +// ignore-test Not a test. Used by other tests +// ignore-tidy-cr + +// For easier verifying, the byte offsets in this file should match those +// in the json-bom-plus-crlf.rs - given the actual fn is identical (just with +// a different, but equally sized name), the easiest way to do this is to +// ensure the two files are of equal size on disk. +// Padding............................ + +// N.B., this file needs CRLF line endings. The .gitattributes file in +// this directory should enforce it. + +pub fn test() { + + let s : String = 1; // Error in the middle of line. + + let s : String = 1 + ; // Error before the newline. + + let s : String = +1; // Error after the newline. + + let s : String = ( + ); // Error spanning the newline. +} diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.rs b/tests/ui/json/json-bom-plus-crlf-multifile.rs new file mode 100644 index 000000000..9290e0104 --- /dev/null +++ b/tests/ui/json/json-bom-plus-crlf-multifile.rs @@ -0,0 +1,11 @@ +// (This line has BOM so it's ignored by compiletest for directives) +// +// compile-flags: --json=diagnostic-short --error-format=json +// ignore-tidy-cr + +#[path = "json-bom-plus-crlf-multifile-aux.rs"] +mod json_bom_plus_crlf_multifile_aux; + +fn main() { + json_bom_plus_crlf_multifile_aux::test(); +} diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.stderr b/tests/ui/json/json-bom-plus-crlf-multifile.stderr new file mode 100644 index 000000000..02f3bc687 --- /dev/null +++ b/tests/ui/json/json-bom-plus-crlf-multifile.stderr @@ -0,0 +1,114 @@ +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types +"} +{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors +"} diff --git a/tests/ui/json/json-bom-plus-crlf.rs b/tests/ui/json/json-bom-plus-crlf.rs new file mode 100644 index 000000000..be5b7dd2a --- /dev/null +++ b/tests/ui/json/json-bom-plus-crlf.rs @@ -0,0 +1,26 @@ +// (This line has BOM so it's ignored by compiletest for directives) +// +// compile-flags: --json=diagnostic-short --error-format=json +// ignore-tidy-cr + +// For easier verifying, the byte offsets in this file should match those +// in the json_bom_plus_crlf_multifile_aux.rs - given the actual fn is +// identical (just with a different, but equally sized name), the easiest way +// to do this is to ensure the two files are of equal size on disk. + +// N.B., this file needs CRLF line endings. The .gitattributes file in +// this directory should enforce it. + +fn main() { + + let s : String = 1; // Error in the middle of line. + + let s : String = 1 + ; // Error before the newline. + + let s : String = +1; // Error after the newline. + + let s : String = ( + ); // Error spanning the newline. +} diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr new file mode 100644 index 000000000..df6bd7286 --- /dev/null +++ b/tests/ui/json/json-bom-plus-crlf.stderr @@ -0,0 +1,114 @@ +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":607,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":667,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":731,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. + +Erroneous code examples: + +```compile_fail,E0308 +fn plus_one(x: i32) -> i32 { + x + 1 +} + +plus_one(\"Not a number\"); +// ^^^^^^^^^^^^^^ expected `i32`, found `&str` + +if \"Not a bool\" { +// ^^^^^^^^^^^^ expected `bool`, found `&str` +} + +let x: f32 = \"Not a float\"; +// --- ^^^^^^^^^^^^^ expected `f32`, found `&str` +// | +// expected due to this +``` + +This error occurs when an expression was used in a place where the compiler +expected an expression of a different type. It can occur in several cases, the +most common being when calling a function and passing an argument which has a +different type than the matching type in the function declaration. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types +"} +{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors +"} diff --git a/tests/ui/json/json-invalid.rs b/tests/ui/json/json-invalid.rs new file mode 100644 index 000000000..54d0dd184 --- /dev/null +++ b/tests/ui/json/json-invalid.rs @@ -0,0 +1,3 @@ +// compile-flags: --json=foo --error-format=json + +fn main() {} diff --git a/tests/ui/json/json-invalid.stderr b/tests/ui/json/json-invalid.stderr new file mode 100644 index 000000000..18bc76ab7 --- /dev/null +++ b/tests/ui/json/json-invalid.stderr @@ -0,0 +1,2 @@ +error: unknown `--json` option `foo` + diff --git a/tests/ui/json/json-multiple.polonius.stderr b/tests/ui/json/json-multiple.polonius.stderr new file mode 100644 index 000000000..0e4d442f2 --- /dev/null +++ b/tests/ui/json/json-multiple.polonius.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json-multiple.polonius/libjson_multiple.rlib","emit":"link"} diff --git a/tests/ui/json/json-multiple.rs b/tests/ui/json/json-multiple.rs new file mode 100644 index 000000000..fb126339d --- /dev/null +++ b/tests/ui/json/json-multiple.rs @@ -0,0 +1,5 @@ +// build-pass +// ignore-pass (different metadata emitted in different modes) +// compile-flags: --json=diagnostic-short --json artifacts --error-format=json + +#![crate_type = "lib"] diff --git a/tests/ui/json/json-multiple.stderr b/tests/ui/json/json-multiple.stderr new file mode 100644 index 000000000..55ccfd5fa --- /dev/null +++ b/tests/ui/json/json-multiple.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json/json-multiple/libjson_multiple.rlib","emit":"link"} diff --git a/tests/ui/json/json-options.polonius.stderr b/tests/ui/json/json-options.polonius.stderr new file mode 100644 index 000000000..e21f6f85d --- /dev/null +++ b/tests/ui/json/json-options.polonius.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json-options.polonius/libjson_options.rlib","emit":"link"} diff --git a/tests/ui/json/json-options.rs b/tests/ui/json/json-options.rs new file mode 100644 index 000000000..8b6ba131e --- /dev/null +++ b/tests/ui/json/json-options.rs @@ -0,0 +1,5 @@ +// build-pass +// ignore-pass (different metadata emitted in different modes) +// compile-flags: --json=diagnostic-short,artifacts --error-format=json + +#![crate_type = "lib"] diff --git a/tests/ui/json/json-options.stderr b/tests/ui/json/json-options.stderr new file mode 100644 index 000000000..645a26f5a --- /dev/null +++ b/tests/ui/json/json-options.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/json/json-options/libjson_options.rlib","emit":"link"} diff --git a/tests/ui/json/json-short.rs b/tests/ui/json/json-short.rs new file mode 100644 index 000000000..7414a5586 --- /dev/null +++ b/tests/ui/json/json-short.rs @@ -0,0 +1 @@ +// compile-flags: --json=diagnostic-short --error-format=json diff --git a/tests/ui/json/json-short.stderr b/tests/ui/json/json-short.stderr new file mode 100644 index 000000000..3bd85b083 --- /dev/null +++ b/tests/ui/json/json-short.stderr @@ -0,0 +1,19 @@ +{"message":"`main` function not found in crate `json_short`","code":{"code":"E0601","explanation":"No `main` function was found in a binary crate. + +To fix this error, add a `main` function: + +``` +fn main() { + // Your program will start here. + println!(\"Hello world!\"); +} +``` + +If you don't know the basics of Rust, you can look at the +[Rust Book][rust-book] to get started. + +[rust-book]: https://doc.rust-lang.org/book/ +"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:63: error[E0601]: `main` function not found in crate `json_short` +"} +{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error +"} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.rs b/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.rs new file mode 100644 index 000000000..b738eb4c7 --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let s = extern::foo::Bar; //~ ERROR expected expression, found keyword `extern` +} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr new file mode 100644 index 000000000..8bb89d2ee --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `extern` + --> $DIR/keyword-extern-as-identifier-expr.rs:2:13 + | +LL | let s = extern::foo::Bar; + | ^^^^^^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.rs b/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.rs new file mode 100644 index 000000000..8a420f720 --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.rs @@ -0,0 +1,3 @@ +fn main() { + let extern = 0; //~ ERROR expected identifier, found keyword `extern` +} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr new file mode 100644 index 000000000..9bf416341 --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `extern` + --> $DIR/keyword-extern-as-identifier-pat.rs:2:9 + | +LL | let extern = 0; + | ^^^^^^ expected identifier, found keyword + | +help: escape `extern` to use it as an identifier + | +LL | let r#extern = 0; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-type.rs b/tests/ui/keyword/extern/keyword-extern-as-identifier-type.rs new file mode 100644 index 000000000..12aa05976 --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-type.rs @@ -0,0 +1,3 @@ +type A = extern::foo::bar; //~ ERROR expected type, found keyword `extern` + +fn main() {} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr new file mode 100644 index 000000000..20ecf6bac --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-type.stderr @@ -0,0 +1,8 @@ +error: expected type, found keyword `extern` + --> $DIR/keyword-extern-as-identifier-type.rs:1:10 + | +LL | type A = extern::foo::bar; + | ^^^^^^ expected type + +error: aborting due to previous error + diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.rs new file mode 100644 index 000000000..a46ce67d4 --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.rs @@ -0,0 +1,4 @@ +use extern::foo; //~ ERROR expected identifier, found keyword `extern` + //~| ERROR unresolved import `r#extern` + +fn main() {} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr new file mode 100644 index 000000000..54ee45c28 --- /dev/null +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -0,0 +1,22 @@ +error: expected identifier, found keyword `extern` + --> $DIR/keyword-extern-as-identifier-use.rs:1:5 + | +LL | use extern::foo; + | ^^^^^^ expected identifier, found keyword + | +help: escape `extern` to use it as an identifier + | +LL | use r#extern::foo; + | ++ + +error[E0432]: unresolved import `r#extern` + --> $DIR/keyword-extern-as-identifier-use.rs:1:5 + | +LL | use extern::foo; + | ^^^^^^ maybe a missing crate `r#extern`? + | + = help: consider adding `extern crate r#extern` to use the `r#extern` crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/keyword/keyword-false-as-identifier.rs b/tests/ui/keyword/keyword-false-as-identifier.rs new file mode 100644 index 000000000..6382f841b --- /dev/null +++ b/tests/ui/keyword/keyword-false-as-identifier.rs @@ -0,0 +1,3 @@ +fn main() { + let false = 22; //~ error: mismatched types +} diff --git a/tests/ui/keyword/keyword-false-as-identifier.stderr b/tests/ui/keyword/keyword-false-as-identifier.stderr new file mode 100644 index 000000000..6dcfa3a48 --- /dev/null +++ b/tests/ui/keyword/keyword-false-as-identifier.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/keyword-false-as-identifier.rs:2:9 + | +LL | let false = 22; + | ^^^^^ -- this expression has type `{integer}` + | | + | expected integer, found `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/keyword/keyword-self-as-identifier.rs b/tests/ui/keyword/keyword-self-as-identifier.rs new file mode 100644 index 000000000..72e4f01e2 --- /dev/null +++ b/tests/ui/keyword/keyword-self-as-identifier.rs @@ -0,0 +1,3 @@ +fn main() { + let Self = 22; //~ ERROR cannot find unit struct, unit variant or constant `Self` in this scope +} diff --git a/tests/ui/keyword/keyword-self-as-identifier.stderr b/tests/ui/keyword/keyword-self-as-identifier.stderr new file mode 100644 index 000000000..060e7c3ea --- /dev/null +++ b/tests/ui/keyword/keyword-self-as-identifier.stderr @@ -0,0 +1,9 @@ +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/keyword-self-as-identifier.rs:2:9 + | +LL | let Self = 22; + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0531`. diff --git a/tests/ui/keyword/keyword-self-as-type-param.rs b/tests/ui/keyword/keyword-self-as-type-param.rs new file mode 100644 index 000000000..55c7ac128 --- /dev/null +++ b/tests/ui/keyword/keyword-self-as-type-param.rs @@ -0,0 +1,10 @@ +// Regression test of #36638. + +struct Foo(Self); +//~^ ERROR unexpected keyword `Self` in generic parameters +//~| ERROR recursive type `Foo` has infinite size + +trait Bar {} +//~^ ERROR unexpected keyword `Self` in generic parameters + +fn main() {} diff --git a/tests/ui/keyword/keyword-self-as-type-param.stderr b/tests/ui/keyword/keyword-self-as-type-param.stderr new file mode 100644 index 000000000..5aef94754 --- /dev/null +++ b/tests/ui/keyword/keyword-self-as-type-param.stderr @@ -0,0 +1,30 @@ +error: unexpected keyword `Self` in generic parameters + --> $DIR/keyword-self-as-type-param.rs:3:12 + | +LL | struct Foo(Self); + | ^^^^ + | + = note: you cannot use `Self` as a generic parameter because it is reserved for associated items + +error: unexpected keyword `Self` in generic parameters + --> $DIR/keyword-self-as-type-param.rs:7:11 + | +LL | trait Bar {} + | ^^^^ + | + = note: you cannot use `Self` as a generic parameter because it is reserved for associated items + +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/keyword-self-as-type-param.rs:3:1 + | +LL | struct Foo(Self); + | ^^^^^^^^^^^^^^^^ ---- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Foo(Box); + | ++++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/keyword/keyword-super-as-identifier.rs b/tests/ui/keyword/keyword-super-as-identifier.rs new file mode 100644 index 000000000..02c1b27b0 --- /dev/null +++ b/tests/ui/keyword/keyword-super-as-identifier.rs @@ -0,0 +1,3 @@ +fn main() { + let super = 22; //~ ERROR failed to resolve: there are too many leading `super` keywords +} diff --git a/tests/ui/keyword/keyword-super-as-identifier.stderr b/tests/ui/keyword/keyword-super-as-identifier.stderr new file mode 100644 index 000000000..1f64f3b73 --- /dev/null +++ b/tests/ui/keyword/keyword-super-as-identifier.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/keyword-super-as-identifier.rs:2:9 + | +LL | let super = 22; + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/keyword/keyword-super.rs b/tests/ui/keyword/keyword-super.rs new file mode 100644 index 000000000..c121a6c10 --- /dev/null +++ b/tests/ui/keyword/keyword-super.rs @@ -0,0 +1,3 @@ +fn main() { + let super: isize; //~ ERROR failed to resolve: there are too many leading `super` keywords +} diff --git a/tests/ui/keyword/keyword-super.stderr b/tests/ui/keyword/keyword-super.stderr new file mode 100644 index 000000000..0e0d67cb9 --- /dev/null +++ b/tests/ui/keyword/keyword-super.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/keyword-super.rs:2:9 + | +LL | let super: isize; + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/keyword/keyword-true-as-identifier.rs b/tests/ui/keyword/keyword-true-as-identifier.rs new file mode 100644 index 000000000..8c4ad7e2a --- /dev/null +++ b/tests/ui/keyword/keyword-true-as-identifier.rs @@ -0,0 +1,3 @@ +fn main() { + let true = 22; //~ error: mismatched types +} diff --git a/tests/ui/keyword/keyword-true-as-identifier.stderr b/tests/ui/keyword/keyword-true-as-identifier.stderr new file mode 100644 index 000000000..86f6e0006 --- /dev/null +++ b/tests/ui/keyword/keyword-true-as-identifier.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/keyword-true-as-identifier.rs:2:9 + | +LL | let true = 22; + | ^^^^ -- this expression has type `{integer}` + | | + | expected integer, found `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/kindck/kindck-copy.rs b/tests/ui/kindck/kindck-copy.rs new file mode 100644 index 000000000..6df98c230 --- /dev/null +++ b/tests/ui/kindck/kindck-copy.rs @@ -0,0 +1,71 @@ +// Test which of the builtin types are considered POD. + +use std::rc::Rc; + +fn assert_copy() { } + +trait Dummy { } + +#[derive(Copy, Clone)] +struct MyStruct { + x: isize, + y: isize, +} + +struct MyNoncopyStruct { + x: Box, +} + +fn test<'a,T,U:Copy>(_: &'a isize) { + // lifetime pointers are ok... + assert_copy::<&'static isize>(); + assert_copy::<&'a isize>(); + assert_copy::<&'a str>(); + assert_copy::<&'a [isize]>(); + + // ...unless they are mutable + assert_copy::<&'static mut isize>(); //~ ERROR : Copy` is not satisfied + assert_copy::<&'a mut isize>(); //~ ERROR : Copy` is not satisfied + + // boxes are not ok + assert_copy::>(); //~ ERROR : Copy` is not satisfied + assert_copy::(); //~ ERROR : Copy` is not satisfied + assert_copy:: >(); //~ ERROR : Copy` is not satisfied + assert_copy::>(); //~ ERROR : Copy` is not satisfied + + // borrowed object types are generally ok + assert_copy::<&'a dyn Dummy>(); + assert_copy::<&'a (dyn Dummy + Send)>(); + assert_copy::<&'static (dyn Dummy + Send)>(); + + // owned object types are not ok + assert_copy::>(); //~ ERROR : Copy` is not satisfied + assert_copy::>(); //~ ERROR : Copy` is not satisfied + + // mutable object types are not ok + assert_copy::<&'a mut (dyn Dummy + Send)>(); //~ ERROR : Copy` is not satisfied + + // unsafe ptrs are ok + assert_copy::<*const isize>(); + assert_copy::<*const &'a mut isize>(); + + // regular old ints and such are ok + assert_copy::(); + assert_copy::(); + assert_copy::<()>(); + + // tuples are ok + assert_copy::<(isize,isize)>(); + + // structs of POD are ok + assert_copy::(); + + // structs containing non-POD are not ok + assert_copy::(); //~ ERROR : Copy` is not satisfied + + // ref counted types are not ok + assert_copy::>(); //~ ERROR : Copy` is not satisfied +} + +pub fn main() { +} diff --git a/tests/ui/kindck/kindck-copy.stderr b/tests/ui/kindck/kindck-copy.stderr new file mode 100644 index 000000000..aee2aa98a --- /dev/null +++ b/tests/ui/kindck/kindck-copy.stderr @@ -0,0 +1,145 @@ +error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied + --> $DIR/kindck-copy.rs:27:19 + | +LL | assert_copy::<&'static mut isize>(); + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` +help: consider removing the leading `&`-reference + | +LL - assert_copy::<&'static mut isize>(); +LL + assert_copy::(); + | + +error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied + --> $DIR/kindck-copy.rs:28:19 + | +LL | assert_copy::<&'a mut isize>(); + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` +help: consider removing the leading `&`-reference + | +LL - assert_copy::<&'a mut isize>(); +LL + assert_copy::(); + | + +error[E0277]: the trait bound `Box: Copy` is not satisfied + --> $DIR/kindck-copy.rs:31:19 + | +LL | assert_copy::>(); + | ^^^^^^^^^^ the trait `Copy` is not implemented for `Box` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/kindck-copy.rs:32:19 + | +LL | assert_copy::(); + | ^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `Vec: Copy` is not satisfied + --> $DIR/kindck-copy.rs:33:19 + | +LL | assert_copy:: >(); + | ^^^^^^^^^^ the trait `Copy` is not implemented for `Vec` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `Box<&'a mut isize>: Copy` is not satisfied + --> $DIR/kindck-copy.rs:34:19 + | +LL | assert_copy::>(); + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box<&'a mut isize>` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `Box: Copy` is not satisfied + --> $DIR/kindck-copy.rs:42:19 + | +LL | assert_copy::>(); + | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `Box: Copy` is not satisfied + --> $DIR/kindck-copy.rs:43:19 + | +LL | assert_copy::>(); + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Box` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `&'a mut (dyn Dummy + Send + 'a): Copy` is not satisfied + --> $DIR/kindck-copy.rs:46:19 + | +LL | assert_copy::<&'a mut (dyn Dummy + Send)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut (dyn Dummy + Send + 'a)` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `MyNoncopyStruct: Copy` is not satisfied + --> $DIR/kindck-copy.rs:64:19 + | +LL | assert_copy::(); + | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `MyNoncopyStruct` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/kindck-copy.rs:67:19 + | +LL | assert_copy::>(); + | ^^^^^^^^^ the trait `Copy` is not implemented for `Rc` + | +note: required by a bound in `assert_copy` + --> $DIR/kindck-copy.rs:5:18 + | +LL | fn assert_copy() { } + | ^^^^ required by this bound in `assert_copy` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-impl-type-params-2.rs b/tests/ui/kindck/kindck-impl-type-params-2.rs new file mode 100644 index 000000000..8950fc51e --- /dev/null +++ b/tests/ui/kindck/kindck-impl-type-params-2.rs @@ -0,0 +1,15 @@ +trait Foo { +} + + + +impl Foo for T { +} + +fn take_param(foo: &T) { } + +fn main() { + let x: Box<_> = Box::new(3); + take_param(&x); + //~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied +} diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr new file mode 100644 index 000000000..1d26ae51f --- /dev/null +++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied + --> $DIR/kindck-impl-type-params-2.rs:13:16 + | +LL | take_param(&x); + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | | + | required by a bound introduced by this call + | +note: required for `Box<{integer}>` to implement `Foo` + --> $DIR/kindck-impl-type-params-2.rs:6:14 + | +LL | impl Foo for T { + | ---- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `take_param` + --> $DIR/kindck-impl-type-params-2.rs:9:17 + | +LL | fn take_param(foo: &T) { } + | ^^^ required by this bound in `take_param` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-impl-type-params.rs b/tests/ui/kindck/kindck-impl-type-params.rs new file mode 100644 index 000000000..72a6599c3 --- /dev/null +++ b/tests/ui/kindck/kindck-impl-type-params.rs @@ -0,0 +1,47 @@ +// Issue #14061: tests the interaction between generic implementation +// parameter bounds and trait objects. + +use std::marker; + +struct S(marker::PhantomData); + +trait Gettable { + fn get(&self) -> T { panic!() } +} + +impl Gettable for S {} + +fn f(val: T) { + let t: S = S(marker::PhantomData); + let a = &t as &dyn Gettable; + //~^ ERROR `T` cannot be sent between threads safely + //~| ERROR : Copy` is not satisfied +} + +fn g(val: T) { + let t: S = S(marker::PhantomData); + let a: &dyn Gettable = &t; + //~^ ERROR `T` cannot be sent between threads safely + //~| ERROR : Copy` is not satisfied +} + +fn foo<'a>() { + let t: S<&'a isize> = S(marker::PhantomData); + let a = &t as &dyn Gettable<&'a isize>; +} + +fn foo2<'a>() { + let t: Box> = Box::new(S(marker::PhantomData)); + let a = t as Box>; + //~^ ERROR : Copy` is not satisfied +} + +fn foo3<'a>() { + struct Foo; // does not impl Copy + + let t: Box> = Box::new(S(marker::PhantomData)); + let a: Box> = t; + //~^ ERROR : Copy` is not satisfied +} + +fn main() { } diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr new file mode 100644 index 000000000..6fd1fc3f7 --- /dev/null +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -0,0 +1,115 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/kindck-impl-type-params.rs:16:13 + | +LL | let a = &t as &dyn Gettable; + | ^^ `T` cannot be sent between threads safely + | +note: required for `S` to implement `Gettable` + --> $DIR/kindck-impl-type-params.rs:12:32 + | +LL | impl Gettable for S {} + | ---- ^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `S` to the object type `dyn Gettable` +help: consider restricting type parameter `T` + | +LL | fn f(val: T) { + | +++++++++++++++++++ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/kindck-impl-type-params.rs:16:13 + | +LL | let a = &t as &dyn Gettable; + | ^^ the trait `Copy` is not implemented for `T` + | +note: required for `S` to implement `Gettable` + --> $DIR/kindck-impl-type-params.rs:12:32 + | +LL | impl Gettable for S {} + | ---- ^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `S` to the object type `dyn Gettable` +help: consider restricting type parameter `T` + | +LL | fn f(val: T) { + | +++++++++++++++++++ + +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/kindck-impl-type-params.rs:23:31 + | +LL | let a: &dyn Gettable = &t; + | ^^ `T` cannot be sent between threads safely + | +note: required for `S` to implement `Gettable` + --> $DIR/kindck-impl-type-params.rs:12:32 + | +LL | impl Gettable for S {} + | ---- ^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `S` to the object type `dyn Gettable` +help: consider restricting type parameter `T` + | +LL | fn g(val: T) { + | +++++++++++++++++++ + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/kindck-impl-type-params.rs:23:31 + | +LL | let a: &dyn Gettable = &t; + | ^^ the trait `Copy` is not implemented for `T` + | +note: required for `S` to implement `Gettable` + --> $DIR/kindck-impl-type-params.rs:12:32 + | +LL | impl Gettable for S {} + | ---- ^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `S` to the object type `dyn Gettable` +help: consider restricting type parameter `T` + | +LL | fn g(val: T) { + | +++++++++++++++++++ + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/kindck-impl-type-params.rs:35:13 + | +LL | let a = t as Box>; + | ^ the trait `Copy` is not implemented for `String` + | + = help: the trait `Gettable` is implemented for `S` +note: required for `S` to implement `Gettable` + --> $DIR/kindck-impl-type-params.rs:12:32 + | +LL | impl Gettable for S {} + | ---- ^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `S` to the object type `dyn Gettable` + +error[E0277]: the trait bound `Foo: Copy` is not satisfied + --> $DIR/kindck-impl-type-params.rs:43:37 + | +LL | let a: Box> = t; + | ^ the trait `Copy` is not implemented for `Foo` + | + = help: the trait `Gettable` is implemented for `S` +note: required for `S` to implement `Gettable` + --> $DIR/kindck-impl-type-params.rs:12:32 + | +LL | impl Gettable for S {} + | ---- ^^^^^^^^^^^ ^^^^ + | | + | unsatisfied trait bound introduced here + = note: required for the cast from `S` to the object type `dyn Gettable` +help: consider annotating `Foo` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr new file mode 100644 index 000000000..8d45748a6 --- /dev/null +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -0,0 +1,55 @@ +error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied + --> $DIR/kindck-inherited-copy-bound.rs:21:16 + | +LL | take_param(&x); + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | | + | required by a bound introduced by this call + | +note: required for `Box<{integer}>` to implement `Foo` + --> $DIR/kindck-inherited-copy-bound.rs:14:14 + | +LL | impl Foo for T { + | ---- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `take_param` + --> $DIR/kindck-inherited-copy-bound.rs:17:17 + | +LL | fn take_param(foo: &T) { } + | ^^^ required by this bound in `take_param` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/kindck-inherited-copy-bound.rs:28:19 + | +LL | let z = &x as &dyn Foo; + | ^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/kindck-inherited-copy-bound.rs:10:13 + | +LL | trait Foo : Copy { + | --- ^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/kindck-inherited-copy-bound.rs:28:13 + | +LL | let z = &x as &dyn Foo; + | ^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/kindck-inherited-copy-bound.rs:10:13 + | +LL | trait Foo : Copy { + | --- ^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&Box<{integer}>` to implement `CoerceUnsized<&dyn Foo>` + = note: required by cast to type `&dyn Foo` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..2fbb5a98a --- /dev/null +++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied + --> $DIR/kindck-inherited-copy-bound.rs:21:16 + | +LL | take_param(&x); + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | | + | required by a bound introduced by this call + | +note: required for `Box<{integer}>` to implement `Foo` + --> $DIR/kindck-inherited-copy-bound.rs:14:14 + | +LL | impl Foo for T { + | ---- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `take_param` + --> $DIR/kindck-inherited-copy-bound.rs:17:17 + | +LL | fn take_param(foo: &T) { } + | ^^^ required by this bound in `take_param` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/kindck-inherited-copy-bound.rs:28:13 + | +LL | let z = &x as &dyn Foo; + | ^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/kindck-inherited-copy-bound.rs:10:13 + | +LL | trait Foo : Copy { + | --- ^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&Box` to implement `CoerceUnsized<&dyn Foo>` + = note: required by cast to type `&dyn Foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs new file mode 100644 index 000000000..87d47556b --- /dev/null +++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs @@ -0,0 +1,34 @@ +// Test that Copy bounds inherited by trait are checked. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + + +use std::any::Any; + +trait Foo : Copy { + fn foo(&self) {} +} + +impl Foo for T { +} + +fn take_param(foo: &T) { } + +fn a() { + let x: Box<_> = Box::new(3); + take_param(&x); //[curr]~ ERROR E0277 + //[object_safe_for_dispatch]~^ ERROR E0277 +} + +fn b() { + let x: Box<_> = Box::new(3); + let y = &x; + let z = &x as &dyn Foo; + //[curr]~^ ERROR E0038 + //[curr]~| ERROR E0038 + //[object_safe_for_dispatch]~^^^ ERROR E0038 +} + +fn main() { } diff --git a/tests/ui/kindck/kindck-nonsendable-1.rs b/tests/ui/kindck/kindck-nonsendable-1.rs new file mode 100644 index 000000000..b32fd7862 --- /dev/null +++ b/tests/ui/kindck/kindck-nonsendable-1.rs @@ -0,0 +1,11 @@ +use std::rc::Rc; + +fn foo(_x: Rc) {} + +fn bar(_: F) { } + +fn main() { + let x = Rc::new(3); + bar(move|| foo(x)); + //~^ ERROR `Rc` cannot be sent between threads safely +} diff --git a/tests/ui/kindck/kindck-nonsendable-1.stderr b/tests/ui/kindck/kindck-nonsendable-1.stderr new file mode 100644 index 000000000..cc6e1f59c --- /dev/null +++ b/tests/ui/kindck/kindck-nonsendable-1.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Rc` cannot be sent between threads safely + --> $DIR/kindck-nonsendable-1.rs:9:9 + | +LL | bar(move|| foo(x)); + | --- ------^^^^^^^ + | | | + | | `Rc` cannot be sent between threads safely + | | within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]` + | required by a bound introduced by this call + | + = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`, the trait `Send` is not implemented for `Rc` +note: required because it's used within this closure + --> $DIR/kindck-nonsendable-1.rs:9:9 + | +LL | bar(move|| foo(x)); + | ^^^^^^ +note: required by a bound in `bar` + --> $DIR/kindck-nonsendable-1.rs:5:21 + | +LL | fn bar(_: F) { } + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object.rs b/tests/ui/kindck/kindck-send-object.rs new file mode 100644 index 000000000..6411e688b --- /dev/null +++ b/tests/ui/kindck/kindck-send-object.rs @@ -0,0 +1,26 @@ +// Test which of the builtin types are considered sendable. The tests +// in this file all test the "kind" violates detected during kindck. +// See all `regions-bounded-by-send.rs` + +fn assert_send() { } +trait Dummy { } +trait Message : Send { } + +// careful with object types, who knows what they close over... + +fn object_ref_with_static_bound_not_ok() { + assert_send::<&'static (dyn Dummy + 'static)>(); + //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277] +} + +fn box_object_with_no_bound_not_ok<'a>() { + assert_send::>(); + //~^ ERROR `dyn Dummy` cannot be sent between threads safely +} + +fn object_with_send_bound_ok() { + assert_send::<&'static (dyn Dummy + Sync)>(); + assert_send::>(); +} + +fn main() { } diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr new file mode 100644 index 000000000..e9bbeeacd --- /dev/null +++ b/tests/ui/kindck/kindck-send-object.stderr @@ -0,0 +1,32 @@ +error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely + --> $DIR/kindck-send-object.rs:12:19 + | +LL | assert_send::<&'static (dyn Dummy + 'static)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)` + = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-object.rs:5:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error[E0277]: `dyn Dummy` cannot be sent between threads safely + --> $DIR/kindck-send-object.rs:17:19 + | +LL | assert_send::>(); + | ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `dyn Dummy` + = note: required for `Unique` to implement `Send` + = note: required because it appears within the type `Box` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-object.rs:5:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs new file mode 100644 index 000000000..787d0f8f6 --- /dev/null +++ b/tests/ui/kindck/kindck-send-object1.rs @@ -0,0 +1,32 @@ +// Test which object types are considered sendable. This test +// is broken into two parts because some errors occur in distinct +// phases in the compiler. See kindck-send-object2.rs as well! + +fn assert_send() { } +trait Dummy { } + +// careful with object types, who knows what they close over... +fn test51<'a>() { + assert_send::<&'a dyn Dummy>(); + //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277] +} +fn test52<'a>() { + assert_send::<&'a (dyn Dummy + Sync)>(); +} + +// ...unless they are properly bounded +fn test60() { + assert_send::<&'static (dyn Dummy + Sync)>(); +} +fn test61() { + assert_send::>(); +} + +// closure and object types can have lifetime bounds which make +// them not ok +fn test_71<'a>() { + assert_send::>(); + //~^ ERROR `(dyn Dummy + 'a)` cannot be sent between threads safely +} + +fn main() { } diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr new file mode 100644 index 000000000..11f597fee --- /dev/null +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -0,0 +1,32 @@ +error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely + --> $DIR/kindck-send-object1.rs:10:19 + | +LL | assert_send::<&'a dyn Dummy>(); + | ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)` + = note: required for `&'a (dyn Dummy + 'a)` to implement `Send` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-object1.rs:5:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely + --> $DIR/kindck-send-object1.rs:28:19 + | +LL | assert_send::>(); + | ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)` + = note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send` + = note: required because it appears within the type `Box<(dyn Dummy + 'a)>` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-object1.rs:5:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object2.rs b/tests/ui/kindck/kindck-send-object2.rs new file mode 100644 index 000000000..b797588e4 --- /dev/null +++ b/tests/ui/kindck/kindck-send-object2.rs @@ -0,0 +1,24 @@ +// Continue kindck-send-object1.rs. + +fn assert_send() { } +trait Dummy { } + +fn test50() { + assert_send::<&'static dyn Dummy>(); + //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277] +} + +fn test53() { + assert_send::>(); + //~^ ERROR `dyn Dummy` cannot be sent between threads safely +} + +// ...unless they are properly bounded +fn test60() { + assert_send::<&'static (dyn Dummy + Sync)>(); +} +fn test61() { + assert_send::>(); +} + +fn main() { } diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr new file mode 100644 index 000000000..b8af33d0d --- /dev/null +++ b/tests/ui/kindck/kindck-send-object2.stderr @@ -0,0 +1,32 @@ +error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely + --> $DIR/kindck-send-object2.rs:7:19 + | +LL | assert_send::<&'static dyn Dummy>(); + | ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)` + = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-object2.rs:3:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error[E0277]: `dyn Dummy` cannot be sent between threads safely + --> $DIR/kindck-send-object2.rs:12:19 + | +LL | assert_send::>(); + | ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `dyn Dummy` + = note: required for `Unique` to implement `Send` + = note: required because it appears within the type `Box` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-object2.rs:3:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-owned.rs b/tests/ui/kindck/kindck-send-owned.rs new file mode 100644 index 000000000..65efb6904 --- /dev/null +++ b/tests/ui/kindck/kindck-send-owned.rs @@ -0,0 +1,16 @@ +// Test which of the builtin types are considered sendable. + +fn assert_send() { } + +// owned content are ok +fn test30() { assert_send::>(); } +fn test31() { assert_send::(); } +fn test32() { assert_send:: >(); } + +// but not if they own a bad thing +fn test40() { + assert_send::>(); + //~^ ERROR `*mut u8` cannot be sent between threads safely +} + +fn main() { } diff --git a/tests/ui/kindck/kindck-send-owned.stderr b/tests/ui/kindck/kindck-send-owned.stderr new file mode 100644 index 000000000..b03f56465 --- /dev/null +++ b/tests/ui/kindck/kindck-send-owned.stderr @@ -0,0 +1,18 @@ +error[E0277]: `*mut u8` cannot be sent between threads safely + --> $DIR/kindck-send-owned.rs:12:19 + | +LL | assert_send::>(); + | ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `*mut u8` + = note: required for `Unique<*mut u8>` to implement `Send` + = note: required because it appears within the type `Box<*mut u8>` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-owned.rs:3:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-unsafe.rs b/tests/ui/kindck/kindck-send-unsafe.rs new file mode 100644 index 000000000..4ef30a71f --- /dev/null +++ b/tests/ui/kindck/kindck-send-unsafe.rs @@ -0,0 +1,11 @@ +extern crate core; + +fn assert_send() { } + +fn test71<'a>() { + assert_send::<*mut &'a isize>(); + //~^ ERROR `*mut &'a isize` cannot be sent between threads safely +} + +fn main() { +} diff --git a/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master b/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master new file mode 100644 index 000000000..3f0444ec9 --- /dev/null +++ b/tests/ui/kindck/kindck-send-unsafe.rs~rust-lang_master @@ -0,0 +1,12 @@ +fn assert_send() { } + +// unsafe ptrs are ok unless they point at unsendable things +fn test70() { + assert_send::<*mut int>(); +} +fn test71<'a>() { + assert_send::<*mut &'a int>(); //~ ERROR does not fulfill the required lifetime +} + +fn main() { +} diff --git a/tests/ui/kindck/kindck-send-unsafe.stderr b/tests/ui/kindck/kindck-send-unsafe.stderr new file mode 100644 index 000000000..ceed0053c --- /dev/null +++ b/tests/ui/kindck/kindck-send-unsafe.stderr @@ -0,0 +1,16 @@ +error[E0277]: `*mut &'a isize` cannot be sent between threads safely + --> $DIR/kindck-send-unsafe.rs:6:19 + | +LL | assert_send::<*mut &'a isize>(); + | ^^^^^^^^^^^^^^ `*mut &'a isize` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `*mut &'a isize` +note: required by a bound in `assert_send` + --> $DIR/kindck-send-unsafe.rs:3:18 + | +LL | fn assert_send() { } + | ^^^^ required by this bound in `assert_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kinds-in-metadata.rs b/tests/ui/kinds-in-metadata.rs new file mode 100644 index 000000000..136037a7a --- /dev/null +++ b/tests/ui/kinds-in-metadata.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:kinds_in_metadata.rs + +// pretty-expanded FIXME #23616 + +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests that metadata serialization works for the `Copy` kind. + +extern crate kinds_in_metadata; + +use kinds_in_metadata::f; + +pub fn main() { + f::(); +} diff --git a/tests/ui/kinds-of-primitive-impl.rs b/tests/ui/kinds-of-primitive-impl.rs new file mode 100644 index 000000000..6a067a9a3 --- /dev/null +++ b/tests/ui/kinds-of-primitive-impl.rs @@ -0,0 +1,26 @@ +impl u8 { +//~^ error: cannot define inherent `impl` for primitive types + pub const B: u8 = 0; +} + +impl str { +//~^ error: cannot define inherent `impl` for primitive types + fn foo() {} + fn bar(self) {} +} + +impl char { +//~^ error: cannot define inherent `impl` for primitive types + pub const B: u8 = 0; + pub const C: u8 = 0; + fn foo() {} + fn bar(self) {} +} + +struct MyType; +impl &MyType { +//~^ error: cannot define inherent `impl` for primitive types + pub fn for_ref(self) {} +} + +fn main() {} diff --git a/tests/ui/kinds-of-primitive-impl.stderr b/tests/ui/kinds-of-primitive-impl.stderr new file mode 100644 index 000000000..f4dbd1c40 --- /dev/null +++ b/tests/ui/kinds-of-primitive-impl.stderr @@ -0,0 +1,36 @@ +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:1:6 + | +LL | impl u8 { + | ^^ + | + = help: consider using an extension trait instead + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:6:6 + | +LL | impl str { + | ^^^ + | + = help: consider using an extension trait instead + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:12:6 + | +LL | impl char { + | ^^^^ + | + = help: consider using an extension trait instead + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:21:6 + | +LL | impl &MyType { + | ^^^^^^^ + | + = help: consider using an extension trait instead + = note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0390`. diff --git a/tests/ui/label/label-beginning-with-underscore.rs b/tests/ui/label/label-beginning-with-underscore.rs new file mode 100644 index 000000000..4b620864a --- /dev/null +++ b/tests/ui/label/label-beginning-with-underscore.rs @@ -0,0 +1,10 @@ +// check-pass + +#![deny(unused_labels)] + +fn main() { + // `unused_label` shouldn't warn labels beginning with `_` + '_unused: loop { + break; + } +} diff --git a/tests/ui/label/label-static.rs b/tests/ui/label/label-static.rs new file mode 100644 index 000000000..95e764d01 --- /dev/null +++ b/tests/ui/label/label-static.rs @@ -0,0 +1,5 @@ +fn main() { + 'static: loop { //~ ERROR invalid label name `'static` + break 'static //~ ERROR invalid label name `'static` + } +} diff --git a/tests/ui/label/label-static.stderr b/tests/ui/label/label-static.stderr new file mode 100644 index 000000000..1d3251d1b --- /dev/null +++ b/tests/ui/label/label-static.stderr @@ -0,0 +1,14 @@ +error: invalid label name `'static` + --> $DIR/label-static.rs:2:5 + | +LL | 'static: loop { + | ^^^^^^^ + +error: invalid label name `'static` + --> $DIR/label-static.rs:3:15 + | +LL | break 'static + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/label/label-underscore.rs b/tests/ui/label/label-underscore.rs new file mode 100644 index 000000000..de67f3d2c --- /dev/null +++ b/tests/ui/label/label-underscore.rs @@ -0,0 +1,5 @@ +fn main() { + '_: loop { //~ ERROR invalid label name `'_` + break '_ //~ ERROR invalid label name `'_` + } +} diff --git a/tests/ui/label/label-underscore.stderr b/tests/ui/label/label-underscore.stderr new file mode 100644 index 000000000..4558ec4cb --- /dev/null +++ b/tests/ui/label/label-underscore.stderr @@ -0,0 +1,14 @@ +error: invalid label name `'_` + --> $DIR/label-underscore.rs:2:5 + | +LL | '_: loop { + | ^^ + +error: invalid label name `'_` + --> $DIR/label-underscore.rs:3:15 + | +LL | break '_ + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/label/label_break_value_continue.rs b/tests/ui/label/label_break_value_continue.rs new file mode 100644 index 000000000..22172f4fd --- /dev/null +++ b/tests/ui/label/label_break_value_continue.rs @@ -0,0 +1,26 @@ +#![allow(unused_labels)] + +// Simple continue pointing to an unlabeled break should yield in an error +fn continue_simple() { + 'b: { + continue; //~ ERROR unlabeled `continue` inside of a labeled block + } +} + +// Labeled continue pointing to an unlabeled break should yield in an error +fn continue_labeled() { + 'b: { + continue 'b; //~ ERROR `continue` pointing to a labeled block + } +} + +// Simple continue that would cross a labeled block should yield in an error +fn continue_crossing() { + loop { + 'b: { + continue; //~ ERROR unlabeled `continue` inside of a labeled block + } + } +} + +pub fn main() {} diff --git a/tests/ui/label/label_break_value_continue.stderr b/tests/ui/label/label_break_value_continue.stderr new file mode 100644 index 000000000..284d213d6 --- /dev/null +++ b/tests/ui/label/label_break_value_continue.stderr @@ -0,0 +1,25 @@ +error[E0695]: unlabeled `continue` inside of a labeled block + --> $DIR/label_break_value_continue.rs:6:9 + | +LL | continue; + | ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label + +error[E0696]: `continue` pointing to a labeled block + --> $DIR/label_break_value_continue.rs:13:9 + | +LL | / 'b: { +LL | | continue 'b; + | | ^^^^^^^^^^^ labeled blocks cannot be `continue`'d +LL | | } + | |_____- labeled block the `continue` points to + +error[E0695]: unlabeled `continue` inside of a labeled block + --> $DIR/label_break_value_continue.rs:21:13 + | +LL | continue; + | ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0695, E0696. +For more information about an error, try `rustc --explain E0695`. diff --git a/tests/ui/label/label_break_value_desugared_break.rs b/tests/ui/label/label_break_value_desugared_break.rs new file mode 100644 index 000000000..70227d869 --- /dev/null +++ b/tests/ui/label/label_break_value_desugared_break.rs @@ -0,0 +1,19 @@ +// compile-flags: --edition 2018 +#![feature(try_blocks)] + +// run-pass +fn main() { + let _: Result<(), ()> = try { + 'foo: { + Err(())?; + break 'foo; + } + }; + + 'foo: { + let _: Result<(), ()> = try { + Err(())?; + break 'foo; + }; + } +} diff --git a/tests/ui/label/label_break_value_illegal_uses.fixed b/tests/ui/label/label_break_value_illegal_uses.fixed new file mode 100644 index 000000000..fb75276b4 --- /dev/null +++ b/tests/ui/label/label_break_value_illegal_uses.fixed @@ -0,0 +1,29 @@ +// run-rustfix + +// These are forbidden occurrences of label-break-value + +#[allow(unused_unsafe)] +fn labeled_unsafe() { + unsafe {} //~ ERROR block label not supported here +} + +fn labeled_if() { + if true {} //~ ERROR block label not supported here +} + +fn labeled_else() { + if true {} else {} //~ ERROR block label not supported here +} + +fn labeled_match() { + match false { //~ ERROR block label not supported here + _ => {} + } +} + +fn main() { + labeled_unsafe(); + labeled_if(); + labeled_else(); + labeled_match(); +} diff --git a/tests/ui/label/label_break_value_illegal_uses.rs b/tests/ui/label/label_break_value_illegal_uses.rs new file mode 100644 index 000000000..3cbf41380 --- /dev/null +++ b/tests/ui/label/label_break_value_illegal_uses.rs @@ -0,0 +1,29 @@ +// run-rustfix + +// These are forbidden occurrences of label-break-value + +#[allow(unused_unsafe)] +fn labeled_unsafe() { + unsafe 'b: {} //~ ERROR block label not supported here +} + +fn labeled_if() { + if true 'b: {} //~ ERROR block label not supported here +} + +fn labeled_else() { + if true {} else 'b: {} //~ ERROR block label not supported here +} + +fn labeled_match() { + match false 'b: { //~ ERROR block label not supported here + _ => {} + } +} + +fn main() { + labeled_unsafe(); + labeled_if(); + labeled_else(); + labeled_match(); +} diff --git a/tests/ui/label/label_break_value_illegal_uses.stderr b/tests/ui/label/label_break_value_illegal_uses.stderr new file mode 100644 index 000000000..15016ffd5 --- /dev/null +++ b/tests/ui/label/label_break_value_illegal_uses.stderr @@ -0,0 +1,26 @@ +error: block label not supported here + --> $DIR/label_break_value_illegal_uses.rs:7:12 + | +LL | unsafe 'b: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label_break_value_illegal_uses.rs:11:13 + | +LL | if true 'b: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label_break_value_illegal_uses.rs:15:21 + | +LL | if true {} else 'b: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label_break_value_illegal_uses.rs:19:17 + | +LL | match false 'b: { + | ^^^ not supported here + +error: aborting due to 4 previous errors + diff --git a/tests/ui/label/label_break_value_unlabeled_break.rs b/tests/ui/label/label_break_value_unlabeled_break.rs new file mode 100644 index 000000000..2a4f5d574 --- /dev/null +++ b/tests/ui/label/label_break_value_unlabeled_break.rs @@ -0,0 +1,19 @@ +#![allow(unused_labels)] + +// Simple unlabeled break should yield in an error +fn unlabeled_break_simple() { + 'b: { + break; //~ ERROR unlabeled `break` inside of a labeled block + } +} + +// Unlabeled break that would cross a labeled block should yield in an error +fn unlabeled_break_crossing() { + loop { + 'b: { + break; //~ ERROR unlabeled `break` inside of a labeled block + } + } +} + +pub fn main() {} diff --git a/tests/ui/label/label_break_value_unlabeled_break.stderr b/tests/ui/label/label_break_value_unlabeled_break.stderr new file mode 100644 index 000000000..a2ccd27b8 --- /dev/null +++ b/tests/ui/label/label_break_value_unlabeled_break.stderr @@ -0,0 +1,15 @@ +error[E0695]: unlabeled `break` inside of a labeled block + --> $DIR/label_break_value_unlabeled_break.rs:6:9 + | +LL | break; + | ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label + +error[E0695]: unlabeled `break` inside of a labeled block + --> $DIR/label_break_value_unlabeled_break.rs:14:13 + | +LL | break; + | ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0695`. diff --git a/tests/ui/label/label_misspelled.rs b/tests/ui/label/label_misspelled.rs new file mode 100644 index 000000000..e3180b06e --- /dev/null +++ b/tests/ui/label/label_misspelled.rs @@ -0,0 +1,62 @@ +#![warn(unused_labels)] + +fn main() { + 'while_loop: while true { //~ WARN denote infinite loops with + //~^ WARN unused label + while_loop; + //~^ ERROR cannot find value `while_loop` in this scope + }; + 'while_let: while let Some(_) = Some(()) { + //~^ WARN unused label + while_let; + //~^ ERROR cannot find value `while_let` in this scope + } + 'for_loop: for _ in 0..3 { + //~^ WARN unused label + for_loop; + //~^ ERROR cannot find value `for_loop` in this scope + }; + 'LOOP: loop { + //~^ WARN unused label + LOOP; + //~^ ERROR cannot find value `LOOP` in this scope + }; +} + +fn foo() { + 'LOOP: loop { + break LOOP; + //~^ ERROR cannot find value `LOOP` in this scope + }; + 'while_loop: while true { //~ WARN denote infinite loops with + break while_loop; + //~^ ERROR cannot find value `while_loop` in this scope + }; + 'while_let: while let Some(_) = Some(()) { + break while_let; + //~^ ERROR cannot find value `while_let` in this scope + } + 'for_loop: for _ in 0..3 { + break for_loop; + //~^ ERROR cannot find value `for_loop` in this scope + }; +} + +fn bar() { + let foo = (); + 'while_loop: while true { //~ WARN denote infinite loops with + //~^ WARN unused label + break foo; + //~^ ERROR `break` with value from a `while` loop + }; + 'while_let: while let Some(_) = Some(()) { + //~^ WARN unused label + break foo; + //~^ ERROR `break` with value from a `while` loop + } + 'for_loop: for _ in 0..3 { + //~^ WARN unused label + break foo; + //~^ ERROR `break` with value from a `for` loop + }; +} diff --git a/tests/ui/label/label_misspelled.stderr b/tests/ui/label/label_misspelled.stderr new file mode 100644 index 000000000..4b5b9e92c --- /dev/null +++ b/tests/ui/label/label_misspelled.stderr @@ -0,0 +1,206 @@ +error[E0425]: cannot find value `while_loop` in this scope + --> $DIR/label_misspelled.rs:6:9 + | +LL | 'while_loop: while true { + | ----------- a label with a similar name exists +LL | +LL | while_loop; + | ^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `while_let` in this scope + --> $DIR/label_misspelled.rs:11:9 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------- a label with a similar name exists +LL | +LL | while_let; + | ^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `for_loop` in this scope + --> $DIR/label_misspelled.rs:16:9 + | +LL | 'for_loop: for _ in 0..3 { + | --------- a label with a similar name exists +LL | +LL | for_loop; + | ^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `LOOP` in this scope + --> $DIR/label_misspelled.rs:21:9 + | +LL | 'LOOP: loop { + | ----- a label with a similar name exists +LL | +LL | LOOP; + | ^^^^ not found in this scope + +error[E0425]: cannot find value `LOOP` in this scope + --> $DIR/label_misspelled.rs:28:15 + | +LL | 'LOOP: loop { + | ----- a label with a similar name exists +LL | break LOOP; + | ^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'LOOP` + +error[E0425]: cannot find value `while_loop` in this scope + --> $DIR/label_misspelled.rs:32:15 + | +LL | 'while_loop: while true { + | ----------- a label with a similar name exists +LL | break while_loop; + | ^^^^^^^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'while_loop` + +error[E0425]: cannot find value `while_let` in this scope + --> $DIR/label_misspelled.rs:36:15 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------- a label with a similar name exists +LL | break while_let; + | ^^^^^^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'while_let` + +error[E0425]: cannot find value `for_loop` in this scope + --> $DIR/label_misspelled.rs:40:15 + | +LL | 'for_loop: for _ in 0..3 { + | --------- a label with a similar name exists +LL | break for_loop; + | ^^^^^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'for_loop` + +warning: unused label + --> $DIR/label_misspelled.rs:4:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/label_misspelled.rs:1:9 + | +LL | #![warn(unused_labels)] + | ^^^^^^^^^^^^^ + +warning: denote infinite loops with `loop { ... }` + --> $DIR/label_misspelled.rs:4:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: unused label + --> $DIR/label_misspelled.rs:9:5 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ^^^^^^^^^^ + +warning: unused label + --> $DIR/label_misspelled.rs:14:5 + | +LL | 'for_loop: for _ in 0..3 { + | ^^^^^^^^^ + +warning: unused label + --> $DIR/label_misspelled.rs:19:5 + | +LL | 'LOOP: loop { + | ^^^^^ + +warning: denote infinite loops with `loop { ... }` + --> $DIR/label_misspelled.rs:31:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + +warning: unused label + --> $DIR/label_misspelled.rs:47:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^ + +warning: denote infinite loops with `loop { ... }` + --> $DIR/label_misspelled.rs:47:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + +warning: unused label + --> $DIR/label_misspelled.rs:52:5 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ^^^^^^^^^^ + +warning: unused label + --> $DIR/label_misspelled.rs:57:5 + | +LL | 'for_loop: for _ in 0..3 { + | ^^^^^^^^^ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/label_misspelled.rs:49:9 + | +LL | 'while_loop: while true { + | ----------------------- you can't `break` with a value in a `while` loop +LL | +LL | break foo; + | ^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'while_loop; + | ~~~~~~~~~~~ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/label_misspelled.rs:54:9 + | +LL | 'while_let: while let Some(_) = Some(()) { + | ---------------------------------------- you can't `break` with a value in a `while` loop +LL | +LL | break foo; + | ^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'while_let; + | ~~~~~~~~~~ + +error[E0571]: `break` with value from a `for` loop + --> $DIR/label_misspelled.rs:59:9 + | +LL | 'for_loop: for _ in 0..3 { + | ------------------------ you can't `break` with a value in a `for` loop +LL | +LL | break foo; + | ^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `for` loop + | +LL | break; + | ~~~~~ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'for_loop; + | ~~~~~~~~~ + +error: aborting due to 11 previous errors; 10 warnings emitted + +Some errors have detailed explanations: E0425, E0571. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/label/label_misspelled_2.rs b/tests/ui/label/label_misspelled_2.rs new file mode 100644 index 000000000..55bbe6b30 --- /dev/null +++ b/tests/ui/label/label_misspelled_2.rs @@ -0,0 +1,16 @@ +#![warn(unused_labels)] + +fn main() { + 'a: for _ in 0..1 { + break 'a; + } + 'b: for _ in 0..1 { + break b; //~ ERROR cannot find value `b` in this scope + } + c: for _ in 0..1 { //~ ERROR malformed loop label + break 'c; + } + d: for _ in 0..1 { //~ ERROR malformed loop label + break d; //~ ERROR cannot find value `d` in this scope + } +} diff --git a/tests/ui/label/label_misspelled_2.stderr b/tests/ui/label/label_misspelled_2.stderr new file mode 100644 index 000000000..960646d98 --- /dev/null +++ b/tests/ui/label/label_misspelled_2.stderr @@ -0,0 +1,37 @@ +error: malformed loop label + --> $DIR/label_misspelled_2.rs:10:5 + | +LL | c: for _ in 0..1 { + | ^ help: use the correct loop label format: `'c` + +error: malformed loop label + --> $DIR/label_misspelled_2.rs:13:5 + | +LL | d: for _ in 0..1 { + | ^ help: use the correct loop label format: `'d` + +error[E0425]: cannot find value `b` in this scope + --> $DIR/label_misspelled_2.rs:8:15 + | +LL | 'b: for _ in 0..1 { + | -- a label with a similar name exists +LL | break b; + | ^ + | | + | not found in this scope + | help: use the similarly named label: `'b` + +error[E0425]: cannot find value `d` in this scope + --> $DIR/label_misspelled_2.rs:14:15 + | +LL | d: for _ in 0..1 { + | - a label with a similar name exists +LL | break d; + | ^ + | | + | not found in this scope + | help: use the similarly named label: `'d` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/lambda-infer-unresolved.rs b/tests/ui/lambda-infer-unresolved.rs new file mode 100644 index 000000000..9cc466b28 --- /dev/null +++ b/tests/ui/lambda-infer-unresolved.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(unused_mut)] +// This should typecheck even though the type of e is not fully +// resolved when we finish typechecking the ||. + + +struct Refs { refs: Vec , n: isize } + +pub fn main() { + let mut e = Refs{refs: vec![], n: 0}; + let _f = || println!("{}", e.n); + let x: &[isize] = &e.refs; + assert_eq!(x.len(), 0); +} diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs new file mode 100644 index 000000000..52bd8136d --- /dev/null +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs @@ -0,0 +1,27 @@ +// Make sure that an error is reported if the `call` function of the +// `fn`/`fn_mut` lang item is grossly ill-formed. + +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang = "fn"] +trait MyFn { + const call: i32 = 42; + //~^ ERROR: `call` trait item in `fn` lang item must be a function +} + +#[lang = "fn_mut"] +trait MyFnMut { + fn call(i: i32, j: i32) -> i32 { i + j } + //~^ ERROR: first argument of `call` in `fn_mut` lang item must be a reference +} + +fn main() { + let a = || 42; + a(); + + let mut i = 0; + let mut b = || { i += 1; }; + b(); +} diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr new file mode 100644 index 000000000..82bdae270 --- /dev/null +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr @@ -0,0 +1,14 @@ +error: `call` trait item in `fn` lang item must be a function + --> $DIR/fn-fn_mut-call-ill-formed.rs:10:5 + | +LL | const call: i32 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: first argument of `call` in `fn_mut` lang item must be a reference + --> $DIR/fn-fn_mut-call-ill-formed.rs:16:16 + | +LL | fn call(i: i32, j: i32) -> i32 { i + j } + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lang-items/issue-19660.rs b/tests/ui/lang-items/issue-19660.rs new file mode 100644 index 000000000..400ac310b --- /dev/null +++ b/tests/ui/lang-items/issue-19660.rs @@ -0,0 +1,15 @@ +// error-pattern: requires `copy` lang_item + +#![feature(lang_items, start, no_core)] +#![no_core] + +#[lang = "sized"] +trait Sized { } + +struct S; + +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + let _ = S; + 0 +} diff --git a/tests/ui/lang-items/issue-19660.stderr b/tests/ui/lang-items/issue-19660.stderr new file mode 100644 index 000000000..f5d903f38 --- /dev/null +++ b/tests/ui/lang-items/issue-19660.stderr @@ -0,0 +1,4 @@ +error: requires `copy` lang_item + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/issue-31076.rs b/tests/ui/lang-items/issue-31076.rs new file mode 100644 index 000000000..cdb196d4f --- /dev/null +++ b/tests/ui/lang-items/issue-31076.rs @@ -0,0 +1,17 @@ +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +#[lang="add"] +trait Add {} + +impl Add for i32 {} + +fn main() { + let x = 5 + 6; + //~^ ERROR cannot add `i32` to `{integer}` + let y = 5i32 + 6i32; + //~^ ERROR cannot add `i32` to `i32` +} diff --git a/tests/ui/lang-items/issue-31076.stderr b/tests/ui/lang-items/issue-31076.stderr new file mode 100644 index 000000000..ac0d9dc75 --- /dev/null +++ b/tests/ui/lang-items/issue-31076.stderr @@ -0,0 +1,19 @@ +error[E0369]: cannot add `i32` to `{integer}` + --> $DIR/issue-31076.rs:13:15 + | +LL | let x = 5 + 6; + | - ^ - i32 + | | + | {integer} + +error[E0369]: cannot add `i32` to `i32` + --> $DIR/issue-31076.rs:15:18 + | +LL | let y = 5i32 + 6i32; + | ---- ^ ---- i32 + | | + | i32 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lang-items/issue-83471.rs b/tests/ui/lang-items/issue-83471.rs new file mode 100644 index 000000000..b32aa0341 --- /dev/null +++ b/tests/ui/lang-items/issue-83471.rs @@ -0,0 +1,23 @@ +// Regression test for the ICE reported in issue #83471. + +#![crate_type="lib"] +#![feature(no_core)] +#![no_core] + +#[lang = "sized"] +//~^ ERROR: language items are subject to change [E0658] +trait Sized {} + +#[lang = "fn"] +//~^ ERROR: language items are subject to change [E0658] +//~| ERROR: `fn` language item must be applied to a trait with 1 generic argument +trait Fn { + fn call(export_name); + //~^ ERROR: expected type + //~| WARNING: anonymous parameters are deprecated + //~| WARNING: this is accepted in the current edition +} +fn call_through_fn_trait() { + a() + //~^ ERROR: cannot find function +} diff --git a/tests/ui/lang-items/issue-83471.stderr b/tests/ui/lang-items/issue-83471.stderr new file mode 100644 index 000000000..b315df179 --- /dev/null +++ b/tests/ui/lang-items/issue-83471.stderr @@ -0,0 +1,51 @@ +error[E0573]: expected type, found built-in attribute `export_name` + --> $DIR/issue-83471.rs:15:13 + | +LL | fn call(export_name); + | ^^^^^^^^^^^ not a type + +error[E0658]: language items are subject to change + --> $DIR/issue-83471.rs:7:1 + | +LL | #[lang = "sized"] + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(lang_items)]` to the crate attributes to enable + +error[E0658]: language items are subject to change + --> $DIR/issue-83471.rs:11:1 + | +LL | #[lang = "fn"] + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(lang_items)]` to the crate attributes to enable + +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/issue-83471.rs:15:13 + | +LL | fn call(export_name); + | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + = note: `#[warn(anonymous_parameters)]` on by default + +error[E0718]: `fn` language item must be applied to a trait with 1 generic argument + --> $DIR/issue-83471.rs:11:1 + | +LL | #[lang = "fn"] + | ^^^^^^^^^^^^^^ +... +LL | trait Fn { + | - this trait has 0 generic arguments + +error[E0425]: cannot find function `a` in this scope + --> $DIR/issue-83471.rs:21:5 + | +LL | a() + | ^ not found in this scope + +error: aborting due to 5 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0425, E0573, E0658, E0718. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/lang-items/issue-86238.rs b/tests/ui/lang-items/issue-86238.rs new file mode 100644 index 000000000..509f94f38 --- /dev/null +++ b/tests/ui/lang-items/issue-86238.rs @@ -0,0 +1,16 @@ +// Regression test for the ICE described in issue #86238. + +#![feature(lang_items)] +#![feature(no_core)] + +#![no_core] +fn main() { + let one = || {}; + one() + //~^ ERROR: failed to find an overloaded call trait for closure call + //~| HELP: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined +} +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} diff --git a/tests/ui/lang-items/issue-86238.stderr b/tests/ui/lang-items/issue-86238.stderr new file mode 100644 index 000000000..767e6de22 --- /dev/null +++ b/tests/ui/lang-items/issue-86238.stderr @@ -0,0 +1,10 @@ +error: failed to find an overloaded call trait for closure call + --> $DIR/issue-86238.rs:9:5 + | +LL | one() + | ^^^^^ + | + = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have associated `call`/`call_mut`/`call_once` functions + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/issue-87573.rs b/tests/ui/lang-items/issue-87573.rs new file mode 100644 index 000000000..aeb0c245a --- /dev/null +++ b/tests/ui/lang-items/issue-87573.rs @@ -0,0 +1,28 @@ +// Regression test for #87573, ensures that duplicate lang items or invalid generics +// for lang items doesn't cause ICE. + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "lib"] + +pub static STATIC_BOOL: bool = true; + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "sync"] +trait Sync {} +impl Sync for bool {} + +#[lang = "drop_in_place"] +//~^ ERROR: `drop_in_place` language item must be applied to a function with at least 1 generic argument +fn drop_fn() { + while false {} +} + +#[lang = "start"] +//~^ ERROR: `start` language item must be applied to a function with 1 generic argument +fn start(){} diff --git a/tests/ui/lang-items/issue-87573.stderr b/tests/ui/lang-items/issue-87573.stderr new file mode 100644 index 000000000..25560cfa0 --- /dev/null +++ b/tests/ui/lang-items/issue-87573.stderr @@ -0,0 +1,21 @@ +error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument + --> $DIR/issue-87573.rs:20:1 + | +LL | #[lang = "drop_in_place"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn drop_fn() { + | - this function has 0 generic arguments + +error[E0718]: `start` language item must be applied to a function with 1 generic argument + --> $DIR/issue-87573.rs:26:1 + | +LL | #[lang = "start"] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(){} + | - this function has 0 generic arguments + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/lang-items/lang-item-generic-requirements.rs b/tests/ui/lang-items/lang-item-generic-requirements.rs new file mode 100644 index 000000000..3d33adf68 --- /dev/null +++ b/tests/ui/lang-items/lang-item-generic-requirements.rs @@ -0,0 +1,59 @@ +// Checks that declaring a lang item with the wrong number of generic arguments errors rather than +// crashing (issue #83474, #83893, #87573, part of #9307, #79559). + +#![feature(lang_items, no_core)] +#![no_core] + +#[lang = "sized"] +trait MySized {} + +#[lang = "add"] +trait MyAdd<'a, T> {} +//~^^ ERROR: `add` language item must be applied to a trait with 1 generic argument [E0718] + +#[lang = "drop_in_place"] +//~^ ERROR `drop_in_place` language item must be applied to a function with at least 1 generic +fn my_ptr_drop() {} + +#[lang = "index"] +trait MyIndex<'a, T> {} +//~^^ ERROR: `index` language item must be applied to a trait with 1 generic argument [E0718] + +#[lang = "phantom_data"] +//~^ ERROR `phantom_data` language item must be applied to a struct with 1 generic argument +struct MyPhantomData; + +#[lang = "owned_box"] +//~^ ERROR `owned_box` language item must be applied to a struct with at least 1 generic argument +struct Foo; + +// When the `start` lang item is missing generics very odd things can happen, especially when +// it comes to cross-crate monomorphization +#[lang = "start"] +//~^ ERROR `start` language item must be applied to a function with 1 generic argument [E0718] +fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { + 0 +} + +fn ice() { + // Use add + let r = 5; + let a = 6; + r + a; + + // Use drop in place + my_ptr_drop(); + + // Use index + let arr = [0; 5]; + let _ = arr[2]; + + // Use phantomdata + let _ = MyPhantomData::<(), i32>; + + // Use Foo + let _: () = Foo; +} + +// use `start` +fn main() {} diff --git a/tests/ui/lang-items/lang-item-generic-requirements.stderr b/tests/ui/lang-items/lang-item-generic-requirements.stderr new file mode 100644 index 000000000..4d349a25f --- /dev/null +++ b/tests/ui/lang-items/lang-item-generic-requirements.stderr @@ -0,0 +1,55 @@ +error[E0718]: `add` language item must be applied to a trait with 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:10:1 + | +LL | #[lang = "add"] + | ^^^^^^^^^^^^^^^ +LL | trait MyAdd<'a, T> {} + | ------- this trait has 2 generic arguments + +error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:14:1 + | +LL | #[lang = "drop_in_place"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn my_ptr_drop() {} + | - this function has 0 generic arguments + +error[E0718]: `index` language item must be applied to a trait with 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:18:1 + | +LL | #[lang = "index"] + | ^^^^^^^^^^^^^^^^^ +LL | trait MyIndex<'a, T> {} + | ------- this trait has 2 generic arguments + +error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:22:1 + | +LL | #[lang = "phantom_data"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct MyPhantomData; + | ------ this struct has 2 generic arguments + +error[E0718]: `owned_box` language item must be applied to a struct with at least 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:26:1 + | +LL | #[lang = "owned_box"] + | ^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Foo; + | - this struct has 0 generic arguments + +error[E0718]: `start` language item must be applied to a function with 1 generic argument + --> $DIR/lang-item-generic-requirements.rs:32:1 + | +LL | #[lang = "start"] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { + | - this function has 0 generic arguments + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/lang-items/lang-item-missing-generator.rs b/tests/ui/lang-items/lang-item-missing-generator.rs new file mode 100644 index 000000000..9b9aff38e --- /dev/null +++ b/tests/ui/lang-items/lang-item-missing-generator.rs @@ -0,0 +1,21 @@ +// error-pattern: requires `generator` lang_item +#![feature(no_core, lang_items, unboxed_closures, tuple_trait)] +#![no_core] + +#[lang = "sized"] pub trait Sized { } + +#[lang = "tuple_trait"] pub trait Tuple { } + +#[lang = "fn_once"] +#[rustc_paren_sugar] +pub trait FnOnce { + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +pub fn abc() -> impl FnOnce(f32) { + |_| {} +} + +fn main() {} diff --git a/tests/ui/lang-items/lang-item-missing-generator.stderr b/tests/ui/lang-items/lang-item-missing-generator.stderr new file mode 100644 index 000000000..a24fdb5fb --- /dev/null +++ b/tests/ui/lang-items/lang-item-missing-generator.stderr @@ -0,0 +1,15 @@ +error[E0635]: unknown feature `tuple_trait` + --> $DIR/lang-item-missing-generator.rs:2:51 + | +LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)] + | ^^^^^^^^^^^ + +error: requires `generator` lang_item + --> $DIR/lang-item-missing-generator.rs:17:17 + | +LL | pub fn abc() -> impl FnOnce(f32) { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/lang-items/lang-item-missing.rs b/tests/ui/lang-items/lang-item-missing.rs new file mode 100644 index 000000000..4e2634324 --- /dev/null +++ b/tests/ui/lang-items/lang-item-missing.rs @@ -0,0 +1,12 @@ +// Test that a missing lang item (in this case `sized`) does not cause an ICE, +// see #17392. + +// error-pattern: requires `sized` lang_item + +#![feature(start, no_core)] +#![no_core] + +#[start] +fn start(argc: isize, argv: *const *const u8) -> isize { + 0 +} diff --git a/tests/ui/lang-items/lang-item-missing.stderr b/tests/ui/lang-items/lang-item-missing.stderr new file mode 100644 index 000000000..f7516c7d3 --- /dev/null +++ b/tests/ui/lang-items/lang-item-missing.stderr @@ -0,0 +1,4 @@ +error: requires `sized` lang_item + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.rs b/tests/ui/lang-items/missing-clone-for-suggestion.rs new file mode 100644 index 000000000..e8290c009 --- /dev/null +++ b/tests/ui/lang-items/missing-clone-for-suggestion.rs @@ -0,0 +1,20 @@ +// Avoid panicking if the Clone trait is not found while building error suggestions +// See #104870 + +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +fn g(x: T) {} + +fn f(x: *mut u8) { + g(x); + g(x); //~ ERROR use of moved value: `x` +} + +fn main() {} diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.stderr b/tests/ui/lang-items/missing-clone-for-suggestion.stderr new file mode 100644 index 000000000..35783a1be --- /dev/null +++ b/tests/ui/lang-items/missing-clone-for-suggestion.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `x` + --> $DIR/missing-clone-for-suggestion.rs:17:7 + | +LL | fn f(x: *mut u8) { + | - move occurs because `x` has type `*mut u8`, which does not implement the `Copy` trait +LL | g(x); + | - value moved here +LL | g(x); + | ^ value used here after move + | +note: consider changing this parameter type in function `g` to borrow instead if owning the value isn't necessary + --> $DIR/missing-clone-for-suggestion.rs:13:12 + | +LL | fn g(x: T) {} + | - ^ this parameter takes ownership of the value + | | + | in this function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/lang-items/no_owned_box_lang_item.rs b/tests/ui/lang-items/no_owned_box_lang_item.rs new file mode 100644 index 000000000..c22b44ffc --- /dev/null +++ b/tests/ui/lang-items/no_owned_box_lang_item.rs @@ -0,0 +1,16 @@ +// Test that we don't ICE when we are missing the owned_box lang item. + +// error-pattern: requires `owned_box` lang_item + +#![feature(lang_items, box_syntax)] +#![no_std] + +use core::panic::PanicInfo; + +fn main() { + let x = box 1i32; +} + +#[lang = "eh_personality"] extern "C" fn eh_personality() {} +#[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0; +#[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} } diff --git a/tests/ui/lang-items/no_owned_box_lang_item.stderr b/tests/ui/lang-items/no_owned_box_lang_item.stderr new file mode 100644 index 000000000..c55c246b5 --- /dev/null +++ b/tests/ui/lang-items/no_owned_box_lang_item.stderr @@ -0,0 +1,4 @@ +error: requires `owned_box` lang_item + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/required-lang-item.rs b/tests/ui/lang-items/required-lang-item.rs new file mode 100644 index 000000000..3b17c5b72 --- /dev/null +++ b/tests/ui/lang-items/required-lang-item.rs @@ -0,0 +1,11 @@ +// build-fail + +#![feature(lang_items, no_core)] +#![no_core] + +#[lang="copy"] pub trait Copy { } +#[lang="sized"] pub trait Sized { } + +// error-pattern:requires `start` lang_item + +fn main() {} diff --git a/tests/ui/lang-items/required-lang-item.stderr b/tests/ui/lang-items/required-lang-item.stderr new file mode 100644 index 000000000..83764a91a --- /dev/null +++ b/tests/ui/lang-items/required-lang-item.stderr @@ -0,0 +1,4 @@ +error: requires `start` lang_item + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.argc.stderr b/tests/ui/lang-items/start_lang_item_args.argc.stderr new file mode 100644 index 000000000..65c99a93c --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.argc.stderr @@ -0,0 +1,8 @@ +error: parameter 2 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:75:38 + | +LL | fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^ help: change the type from `i8` to `isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.argv.stderr b/tests/ui/lang-items/start_lang_item_args.argv.stderr new file mode 100644 index 000000000..f0947a9b3 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.argv.stderr @@ -0,0 +1,8 @@ +error: parameter 3 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:89:52 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize { + | ^^ help: change the type from `u8` to `*const *const u8` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr new file mode 100644 index 000000000..08efd5088 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr @@ -0,0 +1,13 @@ +error: parameter 3 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:82:52 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^ + | +help: change the type from `*const *const usize` to `*const *const u8` + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.main_args.stderr b/tests/ui/lang-items/start_lang_item_args.main_args.stderr new file mode 100644 index 000000000..c20a74466 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.main_args.stderr @@ -0,0 +1,13 @@ +error: parameter 1 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:61:20 + | +LL | fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^^^^^^^^^^^ + | +help: change the type from `fn(i32) -> T` to `fn() -> T` + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr new file mode 100644 index 000000000..8f967252f --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr @@ -0,0 +1,13 @@ +error: parameter 1 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:68:20 + | +LL | fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^^^^^^^^^^ + | +help: change the type from `fn() -> u16` to `fn() -> T` + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr new file mode 100644 index 000000000..deb37b868 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr @@ -0,0 +1,8 @@ +error: parameter 1 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:54:20 + | +LL | fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^^ help: change the type from `u64` to `fn() -> T` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr new file mode 100644 index 000000000..004c2a67f --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr @@ -0,0 +1,11 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/start_lang_item_args.rs:15:1 + | +LL | fn start() -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `start` lang item should have four parameters, but found 0 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr new file mode 100644 index 000000000..1d8285b59 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr @@ -0,0 +1,8 @@ +error: the return type of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:29:84 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} + | ^ help: change the type from `()` to `isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr new file mode 100644 index 000000000..e545a750f --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr @@ -0,0 +1,11 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/start_lang_item_args.rs:22:1 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `start` lang item should have four parameters, but found 3 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.rs b/tests/ui/lang-items/start_lang_item_args.rs new file mode 100644 index 000000000..0dbfba39c --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.rs @@ -0,0 +1,101 @@ +// check-fail +// revisions: missing_all_args missing_sigpipe_arg missing_ret start_ret too_many_args +// revisions: main_ty main_args main_ret argc argv_inner_ptr argv sigpipe + +#![feature(lang_items, no_core)] +#![no_core] + +#[lang = "copy"] +pub trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[cfg(missing_all_args)] +#[lang = "start"] +fn start() -> isize { + //[missing_all_args]~^ ERROR incorrect number of parameters + 100 +} + +#[cfg(missing_sigpipe_arg)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + //[missing_sigpipe_arg]~^ ERROR incorrect number of parameters + 100 +} + +#[cfg(missing_ret)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} +//[missing_ret]~^ ERROR the return type of the `start` lang item is incorrect + +#[cfg(start_ret)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 { + //[start_ret]~^ ERROR the return type of the `start` lang item is incorrect + 100 +} + +#[cfg(too_many_args)] +#[lang = "start"] +fn start( + //[too_many_args]~^ ERROR incorrect number of parameters + _main: fn() -> T, + _argc: isize, + _argv: *const *const u8, + _sigpipe: u8, + _extra_arg: (), +) -> isize { + 100 +} + +#[cfg(main_ty)] +#[lang = "start"] +fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[main_ty]~^ ERROR parameter 1 of the `start` lang item is incorrect + 100 +} + +#[cfg(main_args)] +#[lang = "start"] +fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[main_args]~^ ERROR parameter 1 of the `start` lang item is incorrect + 100 +} + +#[cfg(main_ret)] +#[lang = "start"] +fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[main_ret]~^ ERROR parameter 1 of the `start` lang item is incorrect + 100 +} + +#[cfg(argc)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[argc]~^ ERROR parameter 2 of the `start` lang item is incorrect + 100 +} + +#[cfg(argv_inner_ptr)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize { + //[argv_inner_ptr]~^ ERROR parameter 3 of the `start` lang item is incorrect + 100 +} + +#[cfg(argv)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize { + //[argv]~^ ERROR parameter 3 of the `start` lang item is incorrect + 100 +} + +#[cfg(sigpipe)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize { + //[sigpipe]~^ ERROR parameter 4 of the `start` lang item is incorrect + 100 +} + +fn main() {} diff --git a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr new file mode 100644 index 000000000..b20ae3128 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr @@ -0,0 +1,8 @@ +error: parameter 4 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:96:80 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize { + | ^^^ help: change the type from `i64` to `u8` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr new file mode 100644 index 000000000..935d5f3c8 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr @@ -0,0 +1,8 @@ +error: the return type of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:34:87 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 { + | ^^ help: change the type from `u8` to `isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr new file mode 100644 index 000000000..30a7ed18a --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr @@ -0,0 +1,17 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/start_lang_item_args.rs:41:1 + | +LL | / fn start( +LL | | +LL | | _main: fn() -> T, +LL | | _argc: isize, +... | +LL | | _extra_arg: (), +LL | | ) -> isize { + | |__________^ + | + = note: the `start` lang item should have four parameters, but found 5 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + diff --git a/tests/ui/last-use-in-block.rs b/tests/ui/last-use-in-block.rs new file mode 100644 index 000000000..1ab847dcd --- /dev/null +++ b/tests/ui/last-use-in-block.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_parens)] +// Issue #1818 + + +fn lp(s: String, mut f: F) -> T where F: FnMut(String) -> T { + while false { + let r = f(s); + return (r); + } + panic!(); +} + +fn apply(s: String, mut f: F) -> T where F: FnMut(String) -> T { + fn g(s: String, mut f: F) -> T where F: FnMut(String) -> T {f(s)} + g(s, |v| { let r = f(v); r }) +} + +pub fn main() {} diff --git a/tests/ui/last-use-in-cap-clause.rs b/tests/ui/last-use-in-cap-clause.rs new file mode 100644 index 000000000..98d434632 --- /dev/null +++ b/tests/ui/last-use-in-cap-clause.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(dead_code)] +// Make sure #1399 stays fixed + +struct A { a: Box } + +fn foo() -> Box isize + 'static> { + let k: Box<_> = Box::new(22); + let _u = A {a: k.clone()}; + let result = || 22; + Box::new(result) +} + +pub fn main() { + assert_eq!(foo()(), 22); +} diff --git a/tests/ui/last-use-is-capture.rs b/tests/ui/last-use-is-capture.rs new file mode 100644 index 000000000..1055fe799 --- /dev/null +++ b/tests/ui/last-use-is-capture.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(dead_code)] +// Make sure #1399 stays fixed + +struct A { a: Box } + +pub fn main() { + fn invoke(f: F) where F: FnOnce() { f(); } + let k: Box<_> = 22.into(); + let _u = A {a: k.clone()}; + invoke(|| println!("{}", k.clone()) ) +} diff --git a/tests/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs b/tests/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs new file mode 100644 index 000000000..5b9dc0e43 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/auxiliary/upstream_alias.rs @@ -0,0 +1,5 @@ +pub trait Trait<'a> { + type Assoc; +} + +pub type Alias<'a, T> = >::Assoc; diff --git a/tests/ui/late-bound-lifetimes/cross_crate_alias.rs b/tests/ui/late-bound-lifetimes/cross_crate_alias.rs new file mode 100644 index 000000000..4154c2792 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/cross_crate_alias.rs @@ -0,0 +1,10 @@ +// aux-build:upstream_alias.rs +// check-pass + +extern crate upstream_alias; + +fn foo<'a, T: for<'b> upstream_alias::Trait<'b>>(_: upstream_alias::Alias<'a, T>) -> &'a () { + todo!() +} + +fn main() {} diff --git a/tests/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs b/tests/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs new file mode 100644 index 000000000..e56a34218 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/downgraded_to_early_through_alias.rs @@ -0,0 +1,24 @@ +// check-pass + +trait Gats<'a> { + type Assoc; + type Assoc2; +} + +trait Trait: for<'a> Gats<'a> { + fn foo<'a>(_: &mut >::Assoc) -> >::Assoc2; +} + +impl<'a> Gats<'a> for () { + type Assoc = &'a u32; + type Assoc2 = (); +} + +type GatsAssoc<'a, T> = >::Assoc; +type GatsAssoc2<'a, T> = >::Assoc2; + +impl Trait for () { + fn foo<'a>(_: &mut GatsAssoc<'a, Self>) -> GatsAssoc2<'a, Self> {} +} + +fn main() {} diff --git a/tests/ui/late-bound-lifetimes/issue-36381.rs b/tests/ui/late-bound-lifetimes/issue-36381.rs new file mode 100644 index 000000000..7db56f1dc --- /dev/null +++ b/tests/ui/late-bound-lifetimes/issue-36381.rs @@ -0,0 +1,25 @@ +// run-pass +// Regression test for #36381. The monomorphization collector was asserting that +// there are no projection types, but the `<&str as +// StreamOnce>::Position` projection contained a late-bound region, +// and we don't currently normalize in that case until the function is +// actually invoked. + +pub trait StreamOnce { + type Position; +} + +impl<'a> StreamOnce for &'a str { + type Position = usize; +} + +pub fn parser(_: F) { +} + +fn follow(_: &str) -> <&str as StreamOnce>::Position { + panic!() +} + +fn main() { + parser(follow); +} diff --git a/tests/ui/late-bound-lifetimes/issue-47511.rs b/tests/ui/late-bound-lifetimes/issue-47511.rs new file mode 100644 index 000000000..789443515 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/issue-47511.rs @@ -0,0 +1,21 @@ +// check-pass + +fn f(_: X) -> X { + unimplemented!() +} + +fn g<'a>(_: X<'a>) -> X<'a> { + unimplemented!() +} + +type X<'a> = <&'a () as Trait>::Value; + +trait Trait { + type Value; +} + +impl<'a> Trait for &'a () { + type Value = (); +} + +fn main() {} diff --git a/tests/ui/late-bound-lifetimes/late_bound_through_alias.rs b/tests/ui/late-bound-lifetimes/late_bound_through_alias.rs new file mode 100644 index 000000000..91839673c --- /dev/null +++ b/tests/ui/late-bound-lifetimes/late_bound_through_alias.rs @@ -0,0 +1,16 @@ +// check-pass + +fn f(_: X) -> X { + unimplemented!() +} + +fn g<'a>(_: X<'a>) -> X<'a> { + unimplemented!() +} + +type X<'a> = &'a (); + +fn main() { + let _: for<'a> fn(X<'a>) -> X<'a> = g; + let _: for<'a> fn(X<'a>) -> X<'a> = f; +} diff --git a/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs b/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs new file mode 100644 index 000000000..0b331e203 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs @@ -0,0 +1,12 @@ +// ensures that we don't ICE when there are too many args supplied to the alias. + +trait Trait<'a> { + type Assoc; +} + +type Alias<'a, T> = >::Assoc; + +fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} +//~^ error: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + +fn main() {} diff --git a/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr new file mode 100644 index 000000000..3704d9bb9 --- /dev/null +++ b/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr @@ -0,0 +1,17 @@ +error[E0107]: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/mismatched_arg_count.rs:9:29 + | +LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {} + | ^^^^^ -- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: type alias defined here, with 1 lifetime parameter: `'a` + --> $DIR/mismatched_arg_count.rs:7:6 + | +LL | type Alias<'a, T> = >::Assoc; + | ^^^^^ -- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/layout/big-type-no-err.rs b/tests/ui/layout/big-type-no-err.rs new file mode 100644 index 000000000..af8191a9c --- /dev/null +++ b/tests/ui/layout/big-type-no-err.rs @@ -0,0 +1,13 @@ +// Enormous types are allowed if they are never actually instantiated. +// run-pass +trait Foo { + type Assoc; +} + +impl Foo for [u16; usize::MAX] { + type Assoc = u32; +} + +fn main() { + let _a: Option<<[u16; usize::MAX] as Foo>::Assoc> = None; +} diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs new file mode 100644 index 000000000..a282e7123 --- /dev/null +++ b/tests/ui/layout/debug.rs @@ -0,0 +1,22 @@ +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +#![feature(never_type, rustc_attrs, type_alias_impl_trait)] +#![crate_type = "lib"] + +#[rustc_layout(debug)] +enum E { Foo, Bar(!, i32, i32) } //~ ERROR: layout_of + +#[rustc_layout(debug)] +struct S { f1: i32, f2: (), f3: i32 } //~ ERROR: layout_of + +#[rustc_layout(debug)] +union U { f1: (i32, i32), f3: i32 } //~ ERROR: layout_of + +#[rustc_layout(debug)] +type Test = Result; //~ ERROR: layout_of + +#[rustc_layout(debug)] +type T = impl std::fmt::Debug; //~ ERROR: layout_of + +fn f() -> T { + 0i32 +} diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr new file mode 100644 index 000000000..c5e1c41d1 --- /dev/null +++ b/tests/ui/layout/debug.stderr @@ -0,0 +1,311 @@ +error: layout_of(E) = Layout { + size: Size(12 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(12 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Uninhabited, + fields: Arbitrary { + offsets: [ + Size(4 bytes), + Size(4 bytes), + Size(8 bytes), + ], + memory_index: [ + 0, + 1, + 2, + ], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/debug.rs:6:1 + | +LL | enum E { Foo, Bar(!, i32, i32) } + | ^^^^^^ + +error: layout_of(S) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + Size(0 bytes), + Size(4 bytes), + ], + memory_index: [ + 1, + 0, + 2, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + } + --> $DIR/debug.rs:9:1 + | +LL | struct S { f1: i32, f2: (), f3: i32 } + | ^^^^^^^^ + +error: layout_of(U) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Union( + 2, + ), + largest_niche: None, + variants: Single { + index: 0, + }, + } + --> $DIR/debug.rs:12:1 + | +LL | union U { f1: (i32, i32), f3: i32 } + | ^^^^^^^ + +error: layout_of(std::result::Result) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/debug.rs:15:1 + | +LL | type Test = Result; + | ^^^^^^^^^ + +error: layout_of(i32) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + variants: Single { + index: 0, + }, + } + --> $DIR/debug.rs:18:1 + | +LL | type T = impl std::fmt::Debug; + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/layout/hexagon-enum.rs b/tests/ui/layout/hexagon-enum.rs new file mode 100644 index 000000000..4c58537e3 --- /dev/null +++ b/tests/ui/layout/hexagon-enum.rs @@ -0,0 +1,34 @@ +// compile-flags: --target hexagon-unknown-linux-musl +// needs-llvm-components: hexagon +// +// Verify that the hexagon targets implement the repr(C) for enums correctly. +// +// See #82100 +#![feature(never_type, rustc_attrs, no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang="sized"] +trait Sized {} + +#[rustc_layout(debug)] +#[repr(C)] +enum A { Apple } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum B { Banana = 255, } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum C { Chaenomeles = 256, } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of + +const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator! + +#[rustc_layout(debug)] +#[repr(C)] +enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr new file mode 100644 index 000000000..d850dd69c --- /dev/null +++ b/tests/ui/layout/hexagon-enum.stderr @@ -0,0 +1,352 @@ +error: layout_of(A) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/hexagon-enum.rs:16:1 + | +LL | enum A { Apple } + | ^^^^^^ + +error: layout_of(B) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(1 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/hexagon-enum.rs:20:1 + | +LL | enum B { Banana = 255, } + | ^^^^^^ + +error: layout_of(C) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(2 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(2 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/hexagon-enum.rs:24:1 + | +LL | enum C { Chaenomeles = 256, } + | ^^^^^^ + +error: layout_of(P) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/hexagon-enum.rs:28:1 + | +LL | enum P { Peach = 0x1000_0000isize, } + | ^^^^^^ + +error: layout_of(T) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/hexagon-enum.rs:34:1 + | +LL | enum T { Tangerine = TANGERINE as isize } + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs b/tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs new file mode 100644 index 000000000..7eecd99dc --- /dev/null +++ b/tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.rs @@ -0,0 +1,36 @@ +#![feature(rustc_attrs)] + +// Show that `homogeneous_aggregate` code ignores zero-length C +// arrays. This matches the recent C standard, though not the +// behavior of all older compilers, which sometimes consider `T[0]` to +// be a "flexible array member" (see discussion on #56877 for +// details). + +#[repr(C)] +pub struct Foo { + x: u32 +} + +#[repr(C)] +pub struct Middle { + pub a: f32, + pub foo: [Foo; 0], + pub b: f32, +} + +#[rustc_layout(homogeneous_aggregate)] +pub type TestMiddle = Middle; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous + +#[repr(C)] +pub struct Final { + pub a: f32, + pub b: f32, + pub foo: [Foo; 0], +} + +#[rustc_layout(homogeneous_aggregate)] +pub type TestFinal = Final; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous + +fn main() { } diff --git a/tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr b/tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr new file mode 100644 index 000000000..e19216a99 --- /dev/null +++ b/tests/ui/layout/homogeneous-aggr-zero-sized-c-struct.stderr @@ -0,0 +1,14 @@ +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:22:1 + | +LL | pub type TestMiddle = Middle; + | ^^^^^^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-c-struct.rs:33:1 + | +LL | pub type TestFinal = Final; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs b/tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs new file mode 100644 index 000000000..a473c5c97 --- /dev/null +++ b/tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.rs @@ -0,0 +1,72 @@ +#![feature(rustc_attrs)] + +// Regression test for #56877. We want to ensure that the presence of +// `PhantomData` does not prevent `Bar` from being considered a +// homogeneous aggregate. + +#[repr(C)] +pub struct BaseCase { + pub a: f32, + pub b: f32, +} + +#[repr(C)] +pub struct WithPhantomData { + pub a: f32, + pub b: f32, + pub _unit: std::marker::PhantomData<()>, +} + +pub struct EmptyRustStruct {} + +#[repr(C)] +pub struct WithEmptyRustStruct { + pub a: f32, + pub b: f32, + pub _unit: EmptyRustStruct, +} + +pub struct TransitivelyEmptyRustStruct { + field: EmptyRustStruct, + array: [u32; 0], +} + +#[repr(C)] +pub struct WithTransitivelyEmptyRustStruct { + pub a: f32, + pub b: f32, + pub _unit: TransitivelyEmptyRustStruct, +} + +pub enum EmptyRustEnum { + Dummy, +} + +#[repr(C)] +pub struct WithEmptyRustEnum { + pub a: f32, + pub b: f32, + pub _unit: EmptyRustEnum, +} + +#[rustc_layout(homogeneous_aggregate)] +pub type Test1 = BaseCase; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test2 = WithPhantomData; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test3 = WithEmptyRustStruct; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test4 = WithTransitivelyEmptyRustStruct; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test5 = WithEmptyRustEnum; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +fn main() {} diff --git a/tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr b/tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr new file mode 100644 index 000000000..17d639da0 --- /dev/null +++ b/tests/ui/layout/homogeneous-aggr-zero-sized-repr-rust.stderr @@ -0,0 +1,32 @@ +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:53:1 + | +LL | pub type Test1 = BaseCase; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:57:1 + | +LL | pub type Test2 = WithPhantomData; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:61:1 + | +LL | pub type Test3 = WithEmptyRustStruct; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:65:1 + | +LL | pub type Test4 = WithTransitivelyEmptyRustStruct; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-zero-sized-repr-rust.rs:69:1 + | +LL | pub type Test5 = WithEmptyRustEnum; + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/layout/issue-60431-unsized-tail-behind-projection.rs b/tests/ui/layout/issue-60431-unsized-tail-behind-projection.rs new file mode 100644 index 000000000..65845d2c9 --- /dev/null +++ b/tests/ui/layout/issue-60431-unsized-tail-behind-projection.rs @@ -0,0 +1,35 @@ +// rust-lang/rust#60431: This is a scenario where to determine the size of +// `&Ref`, we need to know the concrete type of the last field in +// `Ref` (i.e. its "struct tail"), and determining that concrete type +// requires normalizing `Obstack::Dyn`. +// +// The old "struct tail" computation did not perform such normalization, and so +// the compiler would ICE when trying to figure out if `Ref` is a +// dynamically-sized type (DST). + +// run-pass + +use std::mem; + +pub trait Arena { + type Dyn : ?Sized; +} + +pub struct DynRef { + _dummy: [()], +} + +pub struct Ref { + _value: u8, + _dyn_arena: A::Dyn, +} + +pub struct Obstack; + +impl Arena for Obstack { + type Dyn = DynRef; +} + +fn main() { + assert_eq!(mem::size_of::<&Ref>(), mem::size_of::<&[()]>()); +} diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs new file mode 100644 index 000000000..dd025c9b4 --- /dev/null +++ b/tests/ui/layout/issue-84108.rs @@ -0,0 +1,14 @@ +// See issue #84108 -- this is a test to ensure we do not ICE +// on this invalid code. + +#![crate_type = "lib"] + +static FOO: (dyn AsRef, u8) = ("hello", 42); +//~^ ERROR cannot find type `OsStr` in this scope + +const BAR: (&Path, [u8], usize) = ("hello", [], 42); +//~^ ERROR cannot find type `Path` in this scope +//~| ERROR the size for values of type `[u8]` cannot be known at compilation time + +static BAZ: ([u8], usize) = ([], 0); +//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr new file mode 100644 index 000000000..36be64241 --- /dev/null +++ b/tests/ui/layout/issue-84108.stderr @@ -0,0 +1,44 @@ +error[E0412]: cannot find type `OsStr` in this scope + --> $DIR/issue-84108.rs:6:24 + | +LL | static FOO: (dyn AsRef, u8) = ("hello", 42); + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::ffi::OsStr; + | + +error[E0412]: cannot find type `Path` in this scope + --> $DIR/issue-84108.rs:9:14 + | +LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::path::Path; + | + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-84108.rs:9:12 + | +LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-84108.rs:13:13 + | +LL | static BAZ: ([u8], usize) = ([], 0); + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last element of a tuple may have a dynamically sized type + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0412. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs new file mode 100644 index 000000000..af5f5885d --- /dev/null +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs @@ -0,0 +1,54 @@ +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +#![crate_type = "lib"] +#![feature(rustc_attrs)] + +use std::mem::MaybeUninit; + +enum HasNiche { + A, + B, + C, +} + +// This should result in ScalarPair(Initialized, Union), +// since the u8 payload will be uninit for `None`. +#[rustc_layout(debug)] +pub enum MissingPayloadField { //~ ERROR: layout_of + Some(u8), + None +} + +// This should result in ScalarPair(Initialized, Initialized), +// since the u8 field is present in all variants, +// and hence will always be initialized. +#[rustc_layout(debug)] +pub enum CommonPayloadField { //~ ERROR: layout_of + A(u8), + B(u8), +} + +// This should result in ScalarPair(Initialized, Union), +// since, though a u8-sized field is present in all variants, it might be uninit. +#[rustc_layout(debug)] +pub enum CommonPayloadFieldIsMaybeUninit { //~ ERROR: layout_of + A(u8), + B(MaybeUninit), +} + +// This should result in ScalarPair(Initialized, Union), +// since only the niche field (used for the tag) is guaranteed to be initialized. +#[rustc_layout(debug)] +pub enum NicheFirst { //~ ERROR: layout_of + A(HasNiche, u8), + B, + C +} + +// This should result in ScalarPair(Union, Initialized), +// since only the niche field (used for the tag) is guaranteed to be initialized. +#[rustc_layout(debug)] +pub enum NicheSecond { //~ ERROR: layout_of + A(u8, HasNiche), + B, + C, +} diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr new file mode 100644 index 000000000..20d4c418e --- /dev/null +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -0,0 +1,655 @@ +error: layout_of(MissingPayloadField) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 + | +LL | pub enum MissingPayloadField { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(CommonPayloadField) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 + | +LL | pub enum CommonPayloadField { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 + | +LL | pub enum CommonPayloadFieldIsMaybeUninit { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(NicheFirst) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Union { + value: Int( + I8, + false, + ), + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + tag_encoding: Niche { + untagged_variant: 0, + niche_variants: 1..=2, + niche_start: 3, + }, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + Size(0 bytes), + ], + memory_index: [ + 1, + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + ), + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 2, + }, + }, + ], + }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 + | +LL | pub enum NicheFirst { + | ^^^^^^^^^^^^^^^^^^^ + +error: layout_of(NicheSecond) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Union { + value: Int( + I8, + false, + ), + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + ), + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=4, + }, + tag_encoding: Niche { + untagged_variant: 0, + niche_variants: 1..=2, + niche_start: 3, + }, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + Size(1 bytes), + ], + memory_index: [ + 0, + 1, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + ), + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 2, + }, + }, + ], + }, + } + --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 + | +LL | pub enum NicheSecond { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/layout/issue-96185-overaligned-enum.rs b/tests/ui/layout/issue-96185-overaligned-enum.rs new file mode 100644 index 000000000..ae1e6b012 --- /dev/null +++ b/tests/ui/layout/issue-96185-overaligned-enum.rs @@ -0,0 +1,19 @@ +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +#![crate_type = "lib"] +#![feature(rustc_attrs)] + +// This cannot use `Scalar` abi since there is padding. +#[rustc_layout(debug)] +#[repr(align(8))] +pub enum Aligned1 { //~ ERROR: layout_of + Zero = 0, + One = 1, +} + +// This should use `Scalar` abi. +#[rustc_layout(debug)] +#[repr(align(1))] +pub enum Aligned2 { //~ ERROR: layout_of + Zero = 0, + One = 1, +} diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr new file mode 100644 index 000000000..de6177c8d --- /dev/null +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -0,0 +1,172 @@ +error: layout_of(Aligned1) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/issue-96185-overaligned-enum.rs:8:1 + | +LL | pub enum Aligned1 { + | ^^^^^^^^^^^^^^^^^ + +error: layout_of(Aligned2) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/issue-96185-overaligned-enum.rs:16:1 + | +LL | pub enum Aligned2 { + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/layout/thin-meta-implies-thin-ptr.rs b/tests/ui/layout/thin-meta-implies-thin-ptr.rs new file mode 100644 index 000000000..972579ea8 --- /dev/null +++ b/tests/ui/layout/thin-meta-implies-thin-ptr.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(ptr_metadata)] + +use std::ptr::Thin; + +fn main() {} + +fn foo(t: *const T) -> *const () { + unsafe { std::mem::transmute(t) } +} diff --git a/tests/ui/layout/thumb-enum.rs b/tests/ui/layout/thumb-enum.rs new file mode 100644 index 000000000..3b43b1b83 --- /dev/null +++ b/tests/ui/layout/thumb-enum.rs @@ -0,0 +1,34 @@ +// compile-flags: --target thumbv8m.main-none-eabihf +// needs-llvm-components: arm +// +// Verify that thumb targets implement the repr(C) for enums correctly. +// +// See #87917 +#![feature(never_type, rustc_attrs, no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang="sized"] +trait Sized {} + +#[rustc_layout(debug)] +#[repr(C)] +enum A { Apple } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum B { Banana = 255, } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum C { Chaenomeles = 256, } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of + +const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator! + +#[rustc_layout(debug)] +#[repr(C)] +enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr new file mode 100644 index 000000000..227bd950b --- /dev/null +++ b/tests/ui/layout/thumb-enum.stderr @@ -0,0 +1,352 @@ +error: layout_of(A) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/thumb-enum.rs:16:1 + | +LL | enum A { Apple } + | ^^^^^^ + +error: layout_of(B) = Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(1 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/thumb-enum.rs:20:1 + | +LL | enum B { Banana = 255, } + | ^^^^^^ + +error: layout_of(C) = Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/thumb-enum.rs:24:1 + | +LL | enum C { Chaenomeles = 256, } + | ^^^^^^ + +error: layout_of(P) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/thumb-enum.rs:28:1 + | +LL | enum P { Peach = 0x1000_0000isize, } + | ^^^^^^ + +error: layout_of(T) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: Align(4 bytes), + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + ], + }, + } + --> $DIR/thumb-enum.rs:34:1 + | +LL | enum T { Tangerine = TANGERINE as isize } + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs new file mode 100644 index 000000000..68bcc3c1a --- /dev/null +++ b/tests/ui/layout/unsafe-cell-hides-niche.rs @@ -0,0 +1,82 @@ +// For rust-lang/rust#68303: the contents of `UnsafeCell` cannot +// participate in the niche-optimization for enum discriminants. This +// test checks that an `Option>` has the same +// size in memory as an `Option>` (namely, 8 bytes). + +// check-pass +// compile-flags: --crate-type=lib +// only-x86 + +#![feature(repr_simd)] + +use std::cell::{UnsafeCell, RefCell, Cell}; +use std::mem::size_of; +use std::num::NonZeroU32 as N32; +use std::sync::{Mutex, RwLock}; + +struct Wrapper(#[allow(unused_tuple_struct_fields)] T); + +#[repr(transparent)] +struct Transparent(#[allow(unused_tuple_struct_fields)] T); + +struct NoNiche(UnsafeCell); + +struct Size; + +macro_rules! check_sizes { + (check_one_specific_size: $ty:ty, $size:expr) => { + const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>; + }; + // Any tests run on `UnsafeCell` must be the same for `Cell` + (UnsafeCell<$ty:ty>: $size:expr => $optioned_size:expr) => { + check_sizes!(Cell<$ty>: $size => $optioned_size); + check_sizes!(@actual_check: UnsafeCell<$ty>: $size => $optioned_size); + }; + ($ty:ty: $size:expr => $optioned_size:expr) => { + check_sizes!(@actual_check: $ty: $size => $optioned_size); + }; + // This branch does the actual checking logic, the `@actual_check` prefix is here to distinguish + // it from other branches and not accidentally match any. + (@actual_check: $ty:ty: $size:expr => $optioned_size:expr) => { + check_sizes!(check_one_specific_size: $ty, $size); + check_sizes!(check_one_specific_size: Option<$ty>, $optioned_size); + check_sizes!(check_no_niche_opt: $size != $optioned_size, $ty); + }; + // only check that there is no niche (size goes up when wrapped in an option), + // don't check actual sizes + ($ty:ty) => { + check_sizes!(check_no_niche_opt: true, $ty); + }; + (check_no_niche_opt: $no_niche_opt:expr, $ty:ty) => { + const _: () = if $no_niche_opt { assert!(size_of::<$ty>() < size_of::>()); }; + }; +} + +const PTR_SIZE: usize = std::mem::size_of::<*const ()>(); + +check_sizes!(Wrapper: 4 => 8); +check_sizes!(Wrapper: 4 => 4); // (✓ niche opt) +check_sizes!(Transparent: 4 => 8); +check_sizes!(Transparent: 4 => 4); // (✓ niche opt) +check_sizes!(NoNiche: 4 => 8); +check_sizes!(NoNiche: 4 => 8); + +check_sizes!(UnsafeCell: 4 => 8); +check_sizes!(UnsafeCell: 4 => 8); + +check_sizes!(UnsafeCell<&()>: PTR_SIZE => PTR_SIZE * 2); +check_sizes!( RefCell<&()>: PTR_SIZE * 2 => PTR_SIZE * 3); + +check_sizes!(RwLock<&()>); +check_sizes!(Mutex<&()>); + +check_sizes!(UnsafeCell<&[i32]>: PTR_SIZE * 2 => PTR_SIZE * 3); +check_sizes!(UnsafeCell<(&(), &())>: PTR_SIZE * 2 => PTR_SIZE * 3); + +trait Trait {} +check_sizes!(UnsafeCell<&dyn Trait>: PTR_SIZE * 2 => PTR_SIZE * 3); + +#[repr(simd)] +pub struct Vec4([T; 4]); + +check_sizes!(UnsafeCell>: 16 => 32); diff --git a/tests/ui/layout/valid_range_oob.rs b/tests/ui/layout/valid_range_oob.rs new file mode 100644 index 000000000..74aa47fe4 --- /dev/null +++ b/tests/ui/layout/valid_range_oob.rs @@ -0,0 +1,15 @@ +// failure-status: 101 +// normalize-stderr-test "note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// rustc-env:RUST_BACKTRACE=0 + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_end(257)] +struct Foo(i8); + +// Need to do in a constant, as runtime codegen +// does not compute the layout of `Foo` in check builds. +const FOO: Foo = unsafe { Foo(1) }; + +fn main() {} diff --git a/tests/ui/layout/valid_range_oob.stderr b/tests/ui/layout/valid_range_oob.stderr new file mode 100644 index 000000000..7398f0164 --- /dev/null +++ b/tests/ui/layout/valid_range_oob.stderr @@ -0,0 +1,6 @@ +error: internal compiler error: unexpected panic + +query stack during panic: +#0 [layout_of] computing layout of `Foo` +#1 [eval_to_allocation_raw] const-evaluating + checking `FOO` +end of query stack diff --git a/tests/ui/layout/zero-sized-array-enum-niche.rs b/tests/ui/layout/zero-sized-array-enum-niche.rs new file mode 100644 index 000000000..23bbbfbfc --- /dev/null +++ b/tests/ui/layout/zero-sized-array-enum-niche.rs @@ -0,0 +1,45 @@ +// normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +#![feature(rustc_attrs)] +#![crate_type = "lib"] + +// Various tests around the behavior of zero-sized arrays and +// enum niches, especially that they have coherent size and alignment. + +// The original problem in #99836 came from ndarray's `TryFrom` for +// `SliceInfo<[SliceInfoElem; 0], Din, Dout>`, where that returns +// `Result` ~= `Result`. +// This is a close enough approximation: +#[rustc_layout(debug)] +type AlignedResult = Result<[u32; 0], bool>; //~ ERROR: layout_of +// The bug gave that size 1 with align 4, but the size should also be 4. +// It was also using the bool niche for the enum tag, which is fine, but +// after the fix, layout decides to use a direct tagged repr instead. + +// Here's another case with multiple ZST alignments, where we should +// get the maximal alignment and matching size. +#[rustc_layout(debug)] +enum MultipleAlignments { //~ ERROR: layout_of + Align2([u16; 0]), + Align4([u32; 0]), + Niche(bool), +} + +// Tagged repr is clever enough to grow tags to fill any padding, e.g.: +// 1. `T_FF` (one byte of Tag, one byte of padding, two bytes of align=2 Field) +// -> `TTFF` (Tag has expanded to two bytes, i.e. like `#[repr(u16)]`) +// 2. `TFF` (one byte of Tag, two bytes of align=1 Field) +// -> Tag has no room to expand! +// (this outcome can be forced onto 1. by wrapping Field in `Packed<...>`) +#[repr(packed)] +struct Packed(T); + +#[rustc_layout(debug)] +type NicheLosesToTagged = Result<[u32; 0], Packed>; //~ ERROR: layout_of +// Should get tag_encoding: Direct, size == align == 4. + +#[repr(u16)] +enum U16IsZero { _Zero = 0 } + +#[rustc_layout(debug)] +type NicheWinsOverTagged = Result<[u32; 0], Packed>; //~ ERROR: layout_of +// Should get tag_encoding: Niche, size == align == 4. diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr new file mode 100644 index 000000000..a3e82070e --- /dev/null +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -0,0 +1,424 @@ +error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/zero-sized-array-enum-niche.rs:13:1 + | +LL | type AlignedResult = Result<[u32; 0], bool>; + | ^^^^^^^^^^^^^^^^^^ + +error: layout_of(MultipleAlignments) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=2, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(2 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(2 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 1, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Single { + index: 2, + }, + }, + ], + }, + } + --> $DIR/zero-sized-array-enum-niche.rs:21:1 + | +LL | enum MultipleAlignments { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(4 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(3 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(1 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(1 bytes), + value: Int( + I16, + false, + ), + valid_range: 1..=65535, + }, + ), + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/zero-sized-array-enum-niche.rs:37:1 + | +LL | type NicheLosesToTagged = Result<[u32; 0], Packed>; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { + size: Size(4 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 0..=1, + }, + ), + variants: Multiple { + tag: Initialized { + value: Int( + I16, + false, + ), + valid_range: 0..=1, + }, + tag_encoding: Niche { + untagged_variant: 1, + niche_variants: 0..=0, + niche_start: 1, + }, + tag_field: 0, + variants: [ + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(4 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + variants: Single { + index: 0, + }, + }, + Layout { + size: Size(2 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: $PREF_ALIGN, + }, + abi: Aggregate { + sized: true, + }, + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Int( + I16, + false, + ), + valid_range: 0..=0, + }, + ), + variants: Single { + index: 1, + }, + }, + ], + }, + } + --> $DIR/zero-sized-array-enum-niche.rs:44:1 + | +LL | type NicheWinsOverTagged = Result<[u32; 0], Packed>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/layout/zero-sized-array-union.rs b/tests/ui/layout/zero-sized-array-union.rs new file mode 100644 index 000000000..1a662ba44 --- /dev/null +++ b/tests/ui/layout/zero-sized-array-union.rs @@ -0,0 +1,95 @@ +#![feature(rustc_attrs)] + +// Various tests around the behavior of zero-sized arrays and +// unions. This matches the behavior of modern C compilers, though +// older compilers (and sometimes clang) treat `T[0]` as a "flexible +// array member". See more +// details in #56877. + +#[derive(Copy, Clone)] +#[repr(C)] +struct Empty { } + +#[derive(Copy, Clone)] +#[repr(C)] +struct Empty2 { + e: Empty +} + +#[derive(Copy, Clone)] +#[repr(C)] +struct Empty3 { + z: [f32; 0], +} + +#[derive(Copy, Clone)] +#[repr(C)] +struct Empty4 { + e: Empty3 +} + +#[repr(C)] +union U1 { + s: Empty +} + +#[repr(C)] +union U2 { + s: Empty2 +} + +#[repr(C)] +union U3 { + s: Empty3 +} + +#[repr(C)] +union U4 { + s: Empty4 +} + +#[repr(C)] +struct Baz1 { + x: f32, + y: f32, + u: U1, +} + +#[rustc_layout(homogeneous_aggregate)] +type TestBaz1 = Baz1; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous + +#[repr(C)] +struct Baz2 { + x: f32, + y: f32, + u: U2, +} + +#[rustc_layout(homogeneous_aggregate)] +type TestBaz2 = Baz2; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous + +#[repr(C)] +struct Baz3 { + x: f32, + y: f32, + u: U3, +} + +#[rustc_layout(homogeneous_aggregate)] +type TestBaz3 = Baz3; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous + +#[repr(C)] +struct Baz4 { + x: f32, + y: f32, + u: U4, +} + +#[rustc_layout(homogeneous_aggregate)] +type TestBaz4 = Baz4; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous + +fn main() { } diff --git a/tests/ui/layout/zero-sized-array-union.stderr b/tests/ui/layout/zero-sized-array-union.stderr new file mode 100644 index 000000000..de2b863e4 --- /dev/null +++ b/tests/ui/layout/zero-sized-array-union.stderr @@ -0,0 +1,26 @@ +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/zero-sized-array-union.rs:59:1 + | +LL | type TestBaz1 = Baz1; + | ^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/zero-sized-array-union.rs:70:1 + | +LL | type TestBaz2 = Baz2; + | ^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/zero-sized-array-union.rs:81:1 + | +LL | type TestBaz3 = Baz3; + | ^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/zero-sized-array-union.rs:92:1 + | +LL | type TestBaz4 = Baz4; + | ^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lazy-and-or.rs b/tests/ui/lazy-and-or.rs new file mode 100644 index 000000000..0b44a70a5 --- /dev/null +++ b/tests/ui/lazy-and-or.rs @@ -0,0 +1,12 @@ +// run-pass + +fn incr(x: &mut isize) -> bool { *x += 1; assert!((false)); return false; } + +pub fn main() { + let x = 1 == 2 || 3 == 3; + assert!((x)); + let mut y: isize = 10; + println!("{}", x || incr(&mut y)); + assert_eq!(y, 10); + if true && x { assert!((true)); } else { assert!((false)); } +} diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.rs b/tests/ui/lazy-type-alias-impl-trait/branches.rs new file mode 100644 index 000000000..95239e2e3 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/branches.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + vec![42_i32] + } else { + std::iter::empty().collect() + } +} + +type Bar = impl std::fmt::Debug; + +fn bar(b: bool) -> Bar { + let x: Bar = if b { + vec![42_i32] + } else { + std::iter::empty().collect() + //~^ ERROR a value of type `Bar` cannot be built from an iterator over elements of type `_` + }; + x +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.stderr b/tests/ui/lazy-type-alias-impl-trait/branches.stderr new file mode 100644 index 000000000..0b206f31e --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/branches.stderr @@ -0,0 +1,13 @@ +error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_` + --> $DIR/branches.rs:19:28 + | +LL | std::iter::empty().collect() + | ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `Bar` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias-impl-trait/branches2.rs b/tests/ui/lazy-type-alias-impl-trait/branches2.rs new file mode 100644 index 000000000..04218f564 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/branches2.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type Foo = impl std::iter::FromIterator + PartialEq> + std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + vec![42_i32] + } else { + std::iter::empty().collect() + } +} + +fn bar(b: bool) -> impl PartialEq> + std::fmt::Debug { + if b { + vec![42_i32] + } else { + std::iter::empty().collect() + } +} + +fn main() { + assert_eq!(foo(true), vec![42]); + assert_eq!(foo(false), vec![]); + assert_eq!(bar(true), vec![42]); + assert_eq!(bar(false), vec![]); +} diff --git a/tests/ui/lazy-type-alias-impl-trait/branches3.rs b/tests/ui/lazy-type-alias-impl-trait/branches3.rs new file mode 100644 index 000000000..30c0af8a5 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/branches3.rs @@ -0,0 +1,36 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl for<'a> FnOnce(&'a str) -> usize; +type Bar = impl FnOnce(&'static str) -> usize; + +fn foo() -> Foo { + if true { + |s| s.len() //~ ERROR type annotations needed + } else { + panic!() + } +} +fn bar() -> Bar { + if true { + |s| s.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + +fn foo2() -> impl for<'a> FnOnce(&'a str) -> usize { + if true { + |s| s.len() //~ ERROR type annotations needed + } else { + panic!() + } +} +fn bar2() -> impl FnOnce(&'static str) -> usize { + if true { + |s| s.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias-impl-trait/branches3.stderr b/tests/ui/lazy-type-alias-impl-trait/branches3.stderr new file mode 100644 index 000000000..fe2631f94 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/branches3.stderr @@ -0,0 +1,47 @@ +error[E0282]: type annotations needed + --> $DIR/branches3.rs:8:10 + | +LL | |s| s.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |s: /* Type */| s.len() + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/branches3.rs:15:10 + | +LL | |s| s.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |s: /* Type */| s.len() + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/branches3.rs:23:10 + | +LL | |s| s.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |s: /* Type */| s.len() + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/branches3.rs:30:10 + | +LL | |s| s.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |s: /* Type */| s.len() + | ++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs b/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs new file mode 100644 index 000000000..f02a93ed4 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/freeze_cycle.rs @@ -0,0 +1,46 @@ +// check-pass + +#![feature(generator_trait, negative_impls)] + +use std::ops::{Generator, GeneratorState}; +use std::task::{Poll, Context}; +use std::future::{Future}; +use std::ptr::NonNull; +use std::pin::Pin; + +fn main() {} + +#[derive(Debug, Copy, Clone)] +pub struct ResumeTy(NonNull>); + +unsafe impl Send for ResumeTy {} + +unsafe impl Sync for ResumeTy {} + +pub const fn from_generator(gen: T) -> impl Future +where + T: Generator, +{ + struct GenFuture>(T); + + // We rely on the fact that async/await futures are immovable in order to create + // self-referential borrows in the underlying generator. + impl> !Unpin for GenFuture {} + + impl> Future for GenFuture { + type Output = T::Return; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. + let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; + + // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The + // `.await` lowering will safely cast that back to a `&mut Context`. + match gen.resume(ResumeTy(NonNull::from(cx).cast::>())) { + GeneratorState::Yielded(()) => Poll::Pending, + GeneratorState::Complete(x) => Poll::Ready(x), + } + } + } + + GenFuture(gen) +} diff --git a/tests/ui/lazy-type-alias-impl-trait/infer_cross_function.rs b/tests/ui/lazy-type-alias-impl-trait/infer_cross_function.rs new file mode 100644 index 000000000..d07d732c7 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/infer_cross_function.rs @@ -0,0 +1,27 @@ +// check-pass + +fn main() {} + +trait Reader {} + +struct Unit(R); +struct ResDwarf(R); + +struct Context { + dwarf: ResDwarf, +} + +struct Range; + +struct ResUnit(R); + +impl Context { + fn find_dwarf_unit(&self, probe: u64) -> Option<&Unit> { + let x = self.find_units(probe); + None + } + + fn find_units(&self, probe: u64) -> impl Iterator> { + std::iter::empty() + } +} diff --git a/tests/ui/lazy-type-alias-impl-trait/lifetime_inference.rs b/tests/ui/lazy-type-alias-impl-trait/lifetime_inference.rs new file mode 100644 index 000000000..f75a88aa8 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/lifetime_inference.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() {} + +fn nth(iter: &mut I, step: usize) -> impl FnMut() -> Option + '_ { + move || iter.nth(step) +} diff --git a/tests/ui/lazy-type-alias-impl-trait/nested.rs b/tests/ui/lazy-type-alias-impl-trait/nested.rs new file mode 100644 index 000000000..f82911127 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/nested.rs @@ -0,0 +1,23 @@ +// check-pass + +fn main() {} + +struct RawTableInner { + alloc: A, +} + +impl RawTableInner { + fn prepare_resize( + self, + ) -> ScopeGuard { + ScopeGuard { dropfn: move |self_| {}, value: self, } + } +} + +pub struct ScopeGuard +where + F: FnMut(&mut T), +{ + dropfn: F, + value: T, +} diff --git a/tests/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs b/tests/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs new file mode 100644 index 000000000..8d03b5158 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/opaque_vs_opaque.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() {} + +fn filter_fold bool, FOLD: FnMut(Acc, T) -> Acc>( + mut predicate: PRED, + mut fold: FOLD, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } +} diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion.rs b/tests/ui/lazy-type-alias-impl-trait/recursion.rs new file mode 100644 index 000000000..cf7cd5d26 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/recursion.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return 42 + } + let x: u32 = foo(false); + 99 +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return 42 + } + let x: u32 = bar(false); + 99 +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion2.rs b/tests/ui/lazy-type-alias-impl-trait/recursion2.rs new file mode 100644 index 000000000..6b3d9ff4c --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/recursion2.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return vec![]; + } + let x: Vec = foo(false); + std::iter::empty().collect() +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return vec![] + } + let x: Vec = bar(false); + std::iter::empty().collect() +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion3.rs b/tests/ui/lazy-type-alias-impl-trait/recursion3.rs new file mode 100644 index 000000000..7f1cedae0 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/recursion3.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return 42 + } + let x: u32 = foo(false) + 42; //~ ERROR cannot add + 99 +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return 42 + } + let x: u32 = bar(false) + 42; //~ ERROR cannot add + 99 +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr b/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr new file mode 100644 index 000000000..e1d5cafed --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr @@ -0,0 +1,19 @@ +error[E0369]: cannot add `{integer}` to `Foo` + --> $DIR/recursion3.rs:9:29 + | +LL | let x: u32 = foo(false) + 42; + | ---------- ^ -- {integer} + | | + | Foo + +error[E0369]: cannot add `{integer}` to `impl Debug` + --> $DIR/recursion3.rs:17:29 + | +LL | let x: u32 = bar(false) + 42; + | ---------- ^ -- {integer} + | | + | impl Debug + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion4.rs b/tests/ui/lazy-type-alias-impl-trait/recursion4.rs new file mode 100644 index 000000000..57dd7fb06 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/recursion4.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; + +fn foo(b: bool) -> Foo { + if b { + return vec![]; + } + let mut x = foo(false); + x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator + vec![] +} + +fn bar(b: bool) -> impl std::fmt::Debug { + if b { + return vec![]; + } + let mut x = bar(false); + x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator + vec![] +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr b/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr new file mode 100644 index 000000000..d8ac39a4f --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr @@ -0,0 +1,23 @@ +error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_` + --> $DIR/recursion4.rs:10:28 + | +LL | x = std::iter::empty().collect(); + | ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `Foo` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_` + --> $DIR/recursion4.rs:19:28 + | +LL | x = std::iter::empty().collect(); + | ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator<_>` is not implemented for `impl Debug` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs b/tests/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs new file mode 100644 index 000000000..007101498 --- /dev/null +++ b/tests/ui/lazy-type-alias-impl-trait/unsized_sized_opaque.rs @@ -0,0 +1,16 @@ +// check-pass + +fn main() {} + +pub struct PairSlices<'a, 'b, T> { + pub(crate) a0: &'a mut [T], + pub(crate) a1: &'a mut [T], + pub(crate) b0: &'b [T], + pub(crate) b1: &'b [T], +} + +impl<'a, 'b, T> PairSlices<'a, 'b, T> { + pub fn remainder(self) -> impl Iterator { + IntoIterator::into_iter([self.b0, self.b1]) + } +} diff --git a/tests/ui/let-else/const-fn.rs b/tests/ui/let-else/const-fn.rs new file mode 100644 index 000000000..a3921b803 --- /dev/null +++ b/tests/ui/let-else/const-fn.rs @@ -0,0 +1,18 @@ +// run-pass +// issue #101932 + + +const fn foo(a: Option) -> i32 { + let Some(a) = a else { + return 42 + }; + + a + 1 +} + +fn main() { + const A: i32 = foo(None); + const B: i32 = foo(Some(1)); + + println!("{} {}", A, B); +} diff --git a/tests/ui/let-else/issue-100103.rs b/tests/ui/let-else/issue-100103.rs new file mode 100644 index 000000000..f5f9b2f5f --- /dev/null +++ b/tests/ui/let-else/issue-100103.rs @@ -0,0 +1,15 @@ +// edition:2021 +// check-pass + +#![feature(try_blocks)] + + +fn main() { + let _: Result = try { + let Some(x) = Some(0) else { + Err(1)? + }; + + x + }; +} diff --git a/tests/ui/let-else/issue-102317.rs b/tests/ui/let-else/issue-102317.rs new file mode 100644 index 000000000..7369b4938 --- /dev/null +++ b/tests/ui/let-else/issue-102317.rs @@ -0,0 +1,20 @@ +// issue #102317 +// build-pass +// compile-flags: --edition 2021 -C opt-level=3 -Zvalidate-mir + +struct SegmentJob; + +impl Drop for SegmentJob { + fn drop(&mut self) {} +} + +pub async fn run() -> Result<(), ()> { + let jobs = Vec::::new(); + let Some(_job) = jobs.into_iter().next() else { + return Ok(()) + }; + + Ok(()) +} + +fn main() {} diff --git a/tests/ui/let-else/issue-94176.rs b/tests/ui/let-else/issue-94176.rs new file mode 100644 index 000000000..f76dfc15b --- /dev/null +++ b/tests/ui/let-else/issue-94176.rs @@ -0,0 +1,10 @@ +// Issue #94176: wrong span for the error message of a mismatched type error, +// if the function uses a `let else` construct. + + +pub fn test(a: Option) -> Option { //~ ERROR mismatched types + let Some(_) = a else { return None; }; + println!("Foo"); +} + +fn main() {} diff --git a/tests/ui/let-else/issue-94176.stderr b/tests/ui/let-else/issue-94176.stderr new file mode 100644 index 000000000..0cb97acee --- /dev/null +++ b/tests/ui/let-else/issue-94176.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-94176.rs:5:32 + | +LL | pub fn test(a: Option) -> Option { + | ---- ^^^^^^^^^^^ expected enum `Option`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Option` + found unit type `()` +help: consider returning the local binding `a` + | +LL ~ println!("Foo"); +LL + a + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/let-else/issue-99975.rs b/tests/ui/let-else/issue-99975.rs new file mode 100644 index 000000000..5b164f347 --- /dev/null +++ b/tests/ui/let-else/issue-99975.rs @@ -0,0 +1,20 @@ +// run-pass +// compile-flags: -C opt-level=3 -Zvalidate-mir + + + +fn return_result() -> Option { + Some("ok".to_string()) +} + +fn start() -> String { + let Some(content) = return_result() else { + return "none".to_string() + }; + + content +} + +fn main() { + start(); +} diff --git a/tests/ui/let-else/let-else-allow-in-expr.rs b/tests/ui/let-else/let-else-allow-in-expr.rs new file mode 100644 index 000000000..33acb6c6a --- /dev/null +++ b/tests/ui/let-else/let-else-allow-in-expr.rs @@ -0,0 +1,28 @@ +#![deny(unused_variables)] + +fn main() { + let Some(_): Option = ({ + let x = 1; //~ ERROR unused variable: `x` + Some(1) + }) else { + return; + }; + + #[allow(unused_variables)] + let Some(_): Option = ({ + let x = 1; + Some(1) + }) else { + return; + }; + + let Some(_): Option = ({ + #[allow(unused_variables)] + let x = 1; + Some(1) + }) else { + return; + }; + + let x = 1; //~ ERROR unused variable: `x` +} diff --git a/tests/ui/let-else/let-else-allow-in-expr.stderr b/tests/ui/let-else/let-else-allow-in-expr.stderr new file mode 100644 index 000000000..3b2b9066c --- /dev/null +++ b/tests/ui/let-else/let-else-allow-in-expr.stderr @@ -0,0 +1,20 @@ +error: unused variable: `x` + --> $DIR/let-else-allow-in-expr.rs:5:13 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/let-else-allow-in-expr.rs:1:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `x` + --> $DIR/let-else-allow-in-expr.rs:27:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/let-else/let-else-allow-unused.rs b/tests/ui/let-else/let-else-allow-unused.rs new file mode 100644 index 000000000..bbb1c7bea --- /dev/null +++ b/tests/ui/let-else/let-else-allow-unused.rs @@ -0,0 +1,15 @@ +// issue #89807 + + + +#[deny(unused_variables)] + +fn main() { + let value = Some(String::new()); + #[allow(unused)] + let banana = 1; + #[allow(unused)] + let Some(chaenomeles) = value.clone() else { return }; // OK + + let Some(chaenomeles) = value else { return }; //~ ERROR unused variable: `chaenomeles` +} diff --git a/tests/ui/let-else/let-else-allow-unused.stderr b/tests/ui/let-else/let-else-allow-unused.stderr new file mode 100644 index 000000000..05b8a9169 --- /dev/null +++ b/tests/ui/let-else/let-else-allow-unused.stderr @@ -0,0 +1,14 @@ +error: unused variable: `chaenomeles` + --> $DIR/let-else-allow-unused.rs:14:14 + | +LL | let Some(chaenomeles) = value else { return }; + | ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_chaenomeles` + | +note: the lint level is defined here + --> $DIR/let-else-allow-unused.rs:5:8 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-annotated.rs b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.rs new file mode 100644 index 000000000..955f33ee1 --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.rs @@ -0,0 +1,16 @@ +// from rfc2005 test suite + + + +// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the +// final default binding mode mutable. + +fn main() { + let Some(n): &mut Option = &&Some(5i32) else { return }; //~ ERROR mismatched types + *n += 1; + let _ = n; + + let Some(n): &mut Option = &&mut Some(5i32) else { return }; //~ ERROR mismatched types + *n += 1; + let _ = n; +} diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr new file mode 100644 index 000000000..065787cab --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/let-else-binding-explicit-mut-annotated.rs:9:37 + | +LL | let Some(n): &mut Option = &&Some(5i32) else { return }; + | ---------------- ^^^^^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Option` + found reference `&&Option` + +error[E0308]: mismatched types + --> $DIR/let-else-binding-explicit-mut-annotated.rs:13:37 + | +LL | let Some(n): &mut Option = &&mut Some(5i32) else { return }; + | ---------------- ^^^^^^^^^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Option` + found reference `&&mut Option` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-borrow.rs b/tests/ui/let-else/let-else-binding-explicit-mut-borrow.rs new file mode 100644 index 000000000..1524d0102 --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut-borrow.rs @@ -0,0 +1,13 @@ +// Slightly different from explicit-mut-annotated -- this won't show an error until borrowck. +// Should it show a type error instead? + + + +fn main() { + let Some(n): &mut Option = &mut &Some(5i32) else { + //~^ ERROR cannot borrow data in a `&` reference as mutable + return + }; + *n += 1; + let _ = n; +} diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr b/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr new file mode 100644 index 000000000..023fab8fe --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut-borrow.stderr @@ -0,0 +1,9 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/let-else-binding-explicit-mut-borrow.rs:7:37 + | +LL | let Some(n): &mut Option = &mut &Some(5i32) else { + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-pass.rs b/tests/ui/let-else/let-else-binding-explicit-mut-pass.rs new file mode 100644 index 000000000..b0a6264a1 --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut-pass.rs @@ -0,0 +1,13 @@ +// check-pass + + + +fn main() { + let Some(n) = &mut &mut Some(5i32) else { return; }; + *n += 1; // OK + let _ = n; + + let Some(n): &mut Option = &mut &mut Some(5i32) else { return; }; + *n += 1; // OK + let _ = n; +} diff --git a/tests/ui/let-else/let-else-binding-explicit-mut.rs b/tests/ui/let-else/let-else-binding-explicit-mut.rs new file mode 100644 index 000000000..a153b3af0 --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut.rs @@ -0,0 +1,20 @@ +// from rfc2005 test suite + + + +// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the +// final default binding mode mutable. + +fn main() { + let Some(n) = &&Some(5i32) else { return }; + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference + let _ = n; + + let Some(n) = &mut &Some(5i32) else { return }; + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference + let _ = n; + + let Some(n) = &&mut Some(5i32) else { return }; + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference + let _ = n; +} diff --git a/tests/ui/let-else/let-else-binding-explicit-mut.stderr b/tests/ui/let-else/let-else-binding-explicit-mut.stderr new file mode 100644 index 000000000..45f2b6b3b --- /dev/null +++ b/tests/ui/let-else/let-else-binding-explicit-mut.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `*n`, which is behind a `&` reference + --> $DIR/let-else-binding-explicit-mut.rs:10:5 + | +LL | *n += 1; + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*n`, which is behind a `&` reference + --> $DIR/let-else-binding-explicit-mut.rs:14:5 + | +LL | *n += 1; + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*n`, which is behind a `&` reference + --> $DIR/let-else-binding-explicit-mut.rs:18:5 + | +LL | *n += 1; + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/let-else/let-else-binding-immutable.rs b/tests/ui/let-else/let-else-binding-immutable.rs new file mode 100644 index 000000000..ff2d9f240 --- /dev/null +++ b/tests/ui/let-else/let-else-binding-immutable.rs @@ -0,0 +1,10 @@ +// from rfc2005 test suite + + + +pub fn main() { + let Some(x) = &Some(3) else { + panic!(); + }; + *x += 1; //~ ERROR: cannot assign to `*x`, which is behind a `&` reference +} diff --git a/tests/ui/let-else/let-else-binding-immutable.stderr b/tests/ui/let-else/let-else-binding-immutable.stderr new file mode 100644 index 000000000..dd1365a9e --- /dev/null +++ b/tests/ui/let-else/let-else-binding-immutable.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/let-else-binding-immutable.rs:9:5 + | +LL | *x += 1; + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/let-else/let-else-bindings.rs b/tests/ui/let-else/let-else-bindings.rs new file mode 100644 index 000000000..53ac398b8 --- /dev/null +++ b/tests/ui/let-else/let-else-bindings.rs @@ -0,0 +1,75 @@ +// run-pass +// adapted from tests/ui/binding/if-let.rs + +#![allow(dead_code)] + +fn none() -> bool { + let None = Some("test") else { + return true; + }; + false +} + +fn ok() -> bool { + let Ok(()) = Err::<(),&'static str>("test") else { + return true; + }; + false +} + +pub fn main() { + let x = Some(3); + let Some(y) = x else { + panic!("let-else panicked"); + }; + assert_eq!(y, 3); + let Some(_) = x else { + panic!("bad match"); + }; + assert!(none()); + assert!(ok()); + + assert!((|| { + let 1 = 2 else { + return true; + }; + false + })()); + + enum Foo { + One, + Two(usize), + Three(String, isize), + } + + let foo = Foo::Three("three".to_string(), 42); + let one = || { + let Foo::One = foo else { + return true; + }; + false + }; + assert!(one()); + let two = || { + let Foo::Two(_x) = foo else { + return true; + }; + false + }; + assert!(two()); + let three = || { + let Foo::Three(s, _x) = foo else { + return false; + }; + s == "three" + }; + assert!(three()); + + let a@Foo::Two(_) = Foo::Two(42_usize) else { + panic!("bad match") + }; + let Foo::Two(b) = a else { + panic!("panic in nested `if let`"); + }; + assert_eq!(b, 42_usize); +} diff --git a/tests/ui/let-else/let-else-bool-binop-init.fixed b/tests/ui/let-else/let-else-bool-binop-init.fixed new file mode 100644 index 000000000..20e558ca9 --- /dev/null +++ b/tests/ui/let-else/let-else-bool-binop-init.fixed @@ -0,0 +1,8 @@ +// run-rustfix + + + +fn main() { + let true = (true && false) else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else` + let true = (true || false) else { return }; //~ ERROR a `||` expression cannot be directly assigned in `let...else` +} diff --git a/tests/ui/let-else/let-else-bool-binop-init.rs b/tests/ui/let-else/let-else-bool-binop-init.rs new file mode 100644 index 000000000..f88179a94 --- /dev/null +++ b/tests/ui/let-else/let-else-bool-binop-init.rs @@ -0,0 +1,8 @@ +// run-rustfix + + + +fn main() { + let true = true && false else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else` + let true = true || false else { return }; //~ ERROR a `||` expression cannot be directly assigned in `let...else` +} diff --git a/tests/ui/let-else/let-else-bool-binop-init.stderr b/tests/ui/let-else/let-else-bool-binop-init.stderr new file mode 100644 index 000000000..edee65762 --- /dev/null +++ b/tests/ui/let-else/let-else-bool-binop-init.stderr @@ -0,0 +1,24 @@ +error: a `&&` expression cannot be directly assigned in `let...else` + --> $DIR/let-else-bool-binop-init.rs:6:16 + | +LL | let true = true && false else { return }; + | ^^^^^^^^^^^^^ + | +help: wrap the expression in parentheses + | +LL | let true = (true && false) else { return }; + | + + + +error: a `||` expression cannot be directly assigned in `let...else` + --> $DIR/let-else-bool-binop-init.rs:7:16 + | +LL | let true = true || false else { return }; + | ^^^^^^^^^^^^^ + | +help: wrap the expression in parentheses + | +LL | let true = (true || false) else { return }; + | + + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/let-else/let-else-brace-before-else.fixed b/tests/ui/let-else/let-else-brace-before-else.fixed new file mode 100644 index 000000000..a75c770dd --- /dev/null +++ b/tests/ui/let-else/let-else-brace-before-else.fixed @@ -0,0 +1,26 @@ +// run-rustfix + + + +fn main() { + let Some(1) = ({ Some(1) }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = (loop { break Some(1) }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let 2 = 1 + (match 1 { n => n }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = (unsafe { unsafe_fn() }) else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; +} + +unsafe fn unsafe_fn() -> T { + unimplemented!(); +} diff --git a/tests/ui/let-else/let-else-brace-before-else.rs b/tests/ui/let-else/let-else-brace-before-else.rs new file mode 100644 index 000000000..5603b946f --- /dev/null +++ b/tests/ui/let-else/let-else-brace-before-else.rs @@ -0,0 +1,26 @@ +// run-rustfix + + + +fn main() { + let Some(1) = { Some(1) } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = loop { break Some(1) } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let 2 = 1 + match 1 { n => n } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; + let Some(1) = unsafe { unsafe_fn() } else { + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + return; + }; +} + +unsafe fn unsafe_fn() -> T { + unimplemented!(); +} diff --git a/tests/ui/let-else/let-else-brace-before-else.stderr b/tests/ui/let-else/let-else-brace-before-else.stderr new file mode 100644 index 000000000..cb01e4c18 --- /dev/null +++ b/tests/ui/let-else/let-else-brace-before-else.stderr @@ -0,0 +1,46 @@ +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:6:29 + | +LL | let Some(1) = { Some(1) } else { + | ^ + | +help: wrap the expression in parentheses + | +LL | let Some(1) = ({ Some(1) }) else { + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:10:40 + | +LL | let Some(1) = loop { break Some(1) } else { + | ^ + | +help: wrap the expression in parentheses + | +LL | let Some(1) = (loop { break Some(1) }) else { + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:14:34 + | +LL | let 2 = 1 + match 1 { n => n } else { + | ^ + | +help: wrap the expression in parentheses + | +LL | let 2 = 1 + (match 1 { n => n }) else { + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-brace-before-else.rs:18:40 + | +LL | let Some(1) = unsafe { unsafe_fn() } else { + | ^ + | +help: wrap the expression in parentheses + | +LL | let Some(1) = (unsafe { unsafe_fn() }) else { + | + + + +error: aborting due to 4 previous errors + diff --git a/tests/ui/let-else/let-else-check.rs b/tests/ui/let-else/let-else-check.rs new file mode 100644 index 000000000..713fd986e --- /dev/null +++ b/tests/ui/let-else/let-else-check.rs @@ -0,0 +1,17 @@ +#![deny(unused_variables)] + +fn main() { + // type annotation, attributes + #[allow(unused_variables)] + let Some(_): Option = Some(Default::default()) else { + let x = 1; // OK + return; + }; + + let Some(_): Option = Some(Default::default()) else { + let x = 1; //~ ERROR unused variable: `x` + return; + }; + + let x = 1; //~ ERROR unused variable: `x` +} diff --git a/tests/ui/let-else/let-else-check.stderr b/tests/ui/let-else/let-else-check.stderr new file mode 100644 index 000000000..bdecbf708 --- /dev/null +++ b/tests/ui/let-else/let-else-check.stderr @@ -0,0 +1,20 @@ +error: unused variable: `x` + --> $DIR/let-else-check.rs:12:13 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/let-else-check.rs:1:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `x` + --> $DIR/let-else-check.rs:16:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/let-else/let-else-deref-coercion-annotated.rs b/tests/ui/let-else/let-else-deref-coercion-annotated.rs new file mode 100644 index 000000000..60fdf825a --- /dev/null +++ b/tests/ui/let-else/let-else-deref-coercion-annotated.rs @@ -0,0 +1,77 @@ +// check-pass +// +// Taken from https://github.com/rust-lang/rust/blob/6cc0a764e082d9c0abcf37a768d5889247ba13e2/compiler/rustc_typeck/src/check/_match.rs#L445-L462 +// +// We attempt to `let Bar::Present(_): &mut Bar = foo else { ... }` where foo is meant to +// Deref/DerefMut to Bar. You can do this with an irrefutable binding, so it should work with +// let-else too. + + +use std::ops::{Deref, DerefMut}; + +struct Foo(Bar); + +enum Bar { + Present(u32), + Absent, +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Bar { + &self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Bar { + &mut self.0 + } +} +impl Bar { + fn bar(&self) -> Option { + let Bar::Present(z): &Bar = self else { + return None; + }; + return Some(*z); + } +} +impl Foo { + fn set_bar_annotated(&mut self, value: u32) { + let Bar::Present(z): &mut Bar = self else { // OK + return; + }; + *z = value; + } +} + +fn main() { + let mut foo = Foo(Bar::Present(1)); + foo.set_bar_annotated(42); + assert_eq!(foo.bar(), Some(42)); + irrefutable::inner(); +} + +// The original, to show it works for irrefutable let decls +mod irrefutable { + use std::ops::{Deref, DerefMut}; + struct Foo(Bar); + struct Bar(u32); + impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Bar { + &self.0 + } + } + impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Bar { + &mut self.0 + } + } + fn foo(x: &mut Foo) { + let Bar(z): &mut Bar = x; // OK + *z = 42; + assert_eq!((x.0).0, 42); + } + pub fn inner() { + foo(&mut Foo(Bar(1))); + } +} diff --git a/tests/ui/let-else/let-else-deref-coercion.rs b/tests/ui/let-else/let-else-deref-coercion.rs new file mode 100644 index 000000000..052a5a8c7 --- /dev/null +++ b/tests/ui/let-else/let-else-deref-coercion.rs @@ -0,0 +1,75 @@ +// Taken from https://github.com/rust-lang/rust/blob/6cc0a764e082d9c0abcf37a768d5889247ba13e2/compiler/rustc_typeck/src/check/_match.rs#L445-L462 +// +// We attempt to `let Bar::Present(_) = foo else { ... }` where foo is meant to Deref/DerefMut to +// Bar. This fails, you must add a type annotation like `let _: &mut Bar = _ else { ... }` + + +use std::ops::{Deref, DerefMut}; + +struct Foo(Bar); + +enum Bar { + Present(u32), + Absent, +} +impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Bar { + &self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Bar { + &mut self.0 + } +} +impl Bar { + fn bar(&self) -> Option { + let Bar::Present(z): &Bar = self else { + return None; + }; + return Some(*z); + } +} +impl Foo { + // Try without the type annotation + fn set_bar_unannotated(&mut self, value: u32) { + let Bar::Present(z) = self else { //~ ERROR mismatched types + return; + }; + *z = value; + } +} + +fn main() { + let mut foo = Foo(Bar::Present(1)); + foo.set_bar_unannotated(54); + assert_eq!(foo.bar(), Some(54)); + irrefutable::inner(); +} + +// The original, to show it fails for irrefutable let decls +mod irrefutable { + use std::ops::{Deref, DerefMut}; + struct Foo(Bar); + struct Bar(u32); + impl Deref for Foo { + type Target = Bar; + fn deref(&self) -> &Bar { + &self.0 + } + } + impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Bar { + &mut self.0 + } + } + fn foo(x: &mut Foo) { + let Bar(z) = x; //~ ERROR mismatched types + *z = 54; + assert_eq!((x.0).0, 54); + } + pub fn inner() { + foo(&mut Foo(Bar(1))); + } +} diff --git a/tests/ui/let-else/let-else-deref-coercion.stderr b/tests/ui/let-else/let-else-deref-coercion.stderr new file mode 100644 index 000000000..bf78a079c --- /dev/null +++ b/tests/ui/let-else/let-else-deref-coercion.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/let-else-deref-coercion.rs:37:13 + | +LL | let Bar::Present(z) = self else { + | ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo` + | | + | expected struct `Foo`, found enum `Bar` + +error[E0308]: mismatched types + --> $DIR/let-else-deref-coercion.rs:68:13 + | +LL | let Bar(z) = x; + | ^^^^^^ - this expression has type `&mut irrefutable::Foo` + | | + | expected struct `Foo`, found struct `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/let-else/let-else-destructuring.rs b/tests/ui/let-else/let-else-destructuring.rs new file mode 100644 index 000000000..d1f1a69bf --- /dev/null +++ b/tests/ui/let-else/let-else-destructuring.rs @@ -0,0 +1,17 @@ +#[derive(Debug)] +enum Foo { + Done, + Nested(Option<&'static Foo>), +} + +fn walk(mut value: &Foo) { + loop { + println!("{:?}", value); + &Foo::Nested(Some(value)) = value else { break }; //~ ERROR invalid left-hand side of assignment + //~^ERROR ... else { ... } is not allowed + } +} + +fn main() { + walk(&Foo::Done); +} diff --git a/tests/ui/let-else/let-else-destructuring.stderr b/tests/ui/let-else/let-else-destructuring.stderr new file mode 100644 index 000000000..7d6cb2386 --- /dev/null +++ b/tests/ui/let-else/let-else-destructuring.stderr @@ -0,0 +1,17 @@ +error: ... else { ... } is not allowed + --> $DIR/let-else-destructuring.rs:10:9 + | +LL | &Foo::Nested(Some(value)) = value else { break }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0070]: invalid left-hand side of assignment + --> $DIR/let-else-destructuring.rs:10:35 + | +LL | &Foo::Nested(Some(value)) = value else { break }; + | ------------------------- ^ + | | + | cannot assign to this expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/let-else/let-else-drop-order.rs b/tests/ui/let-else/let-else-drop-order.rs new file mode 100644 index 000000000..e91e5de84 --- /dev/null +++ b/tests/ui/let-else/let-else-drop-order.rs @@ -0,0 +1,270 @@ +// run-pass +// edition:2021 +// check-run-results +// +// Drop order tests for let else +// +// Mostly this ensures two things: +// 1. That let and let else temporary drop order is the same. +// This is a specific design request: https://github.com/rust-lang/rust/pull/93628#issuecomment-1047140316 +// 2. That the else block truly only runs after the +// temporaries have dropped. +// +// We also print some nice tables for an overview by humans. +// Changes in those tables are considered breakages, but the +// important properties 1 and 2 are also enforced by the code. +// This is important as it's easy to update the stdout file +// with a --bless and miss the impact of that change. + + +#![allow(irrefutable_let_patterns)] + +use std::cell::RefCell; +use std::rc::Rc; + +#[derive(Clone)] +struct DropAccountant(Rc>>>); + +impl DropAccountant { + fn new() -> Self { + Self(Default::default()) + } + fn build_droppy(&self, v: u32) -> Droppy { + Droppy(self.clone(), v) + } + fn build_droppy_enum_none(&self, _v: u32) -> ((), DroppyEnum) { + ((), DroppyEnum::None(self.clone())) + } + fn new_list(&self, s: impl ToString) { + self.0.borrow_mut().push(vec![s.to_string()]); + } + fn push(&self, s: impl ToString) { + let s = s.to_string(); + let mut accounts = self.0.borrow_mut(); + accounts.last_mut().unwrap().push(s); + } + fn print_table(&self) { + println!(); + + let accounts = self.0.borrow(); + let before_last = &accounts[accounts.len() - 2]; + let last = &accounts[accounts.len() - 1]; + let before_last = get_comma_list(before_last); + let last = get_comma_list(last); + const LINES: &[&str] = &[ + "vanilla", + "&", + "&mut", + "move", + "fn(this)", + "tuple", + "array", + "ref &", + "ref mut &mut", + ]; + let max_len = LINES.iter().map(|v| v.len()).max().unwrap(); + let max_len_before = before_last.iter().map(|v| v.len()).max().unwrap(); + let max_len_last = last.iter().map(|v| v.len()).max().unwrap(); + + println!( + "| {: Vec { + std::iter::once(sl[0].clone()) + .chain(sl[1..].chunks(2).map(|c| c.join(","))) + .collect::>() +} + +struct Droppy(DropAccountant, T); + +impl Drop for Droppy { + fn drop(&mut self) { + self.0.push("drop"); + } +} + +#[allow(dead_code)] +enum DroppyEnum { + Some(DropAccountant, T), + None(DropAccountant), +} + +impl Drop for DroppyEnum { + fn drop(&mut self) { + match self { + DroppyEnum::Some(acc, _inner) => acc, + DroppyEnum::None(acc) => acc, + } + .push("drop"); + } +} + +macro_rules! nestings_with { + ($construct:ident, $binding:pat, $exp:expr) => { + // vanilla: + $construct!($binding, $exp.1); + + // &: + $construct!(&$binding, &$exp.1); + + // &mut: + $construct!(&mut $binding, &mut ($exp.1)); + + { + // move: + let w = $exp; + $construct!( + $binding, + { + let w = w; + w + } + .1 + ); + } + + // fn(this): + $construct!($binding, std::convert::identity($exp).1); + }; +} + +macro_rules! nestings { + ($construct:ident, $binding:pat, $exp:expr) => { + nestings_with!($construct, $binding, $exp); + + // tuple: + $construct!(($binding, 77), ($exp.1, 77)); + + // array: + $construct!([$binding], [$exp.1]); + }; +} + +macro_rules! let_else { + ($acc:expr, $v:expr, $binding:pat, $build:ident) => { + let acc = $acc; + let v = $v; + + macro_rules! let_else_construct { + ($arg:pat, $exp:expr) => { + loop { + let $arg = $exp else { + acc.push("else"); + break; + }; + acc.push("body"); + break; + } + }; + } + nestings!(let_else_construct, $binding, acc.$build(v)); + // ref &: + let_else_construct!($binding, &acc.$build(v).1); + + // ref mut &mut: + let_else_construct!($binding, &mut acc.$build(v).1); + }; +} + +macro_rules! let_ { + ($acc:expr, $binding:tt) => { + let acc = $acc; + + macro_rules! let_construct { + ($arg:pat, $exp:expr) => {{ + let $arg = $exp; + acc.push("body"); + }}; + } + let v = 0; + { + nestings_with!(let_construct, $binding, acc.build_droppy(v)); + } + acc.push("n/a"); + acc.push("n/a"); + acc.push("n/a"); + acc.push("n/a"); + + // ref &: + let_construct!($binding, &acc.build_droppy(v).1); + + // ref mut &mut: + let_construct!($binding, &mut acc.build_droppy(v).1); + }; +} + +fn main() { + let acc = DropAccountant::new(); + + println!(" --- matching cases ---"); + + // Ensure that let and let else have the same behaviour + acc.new_list("let _"); + let_!(&acc, _); + acc.new_list("let else _"); + let_else!(&acc, 0, _, build_droppy); + acc.assert_equality_last_two_lists(); + acc.print_table(); + + // Ensure that let and let else have the same behaviour + acc.new_list("let _v"); + let_!(&acc, _v); + acc.new_list("let else _v"); + let_else!(&acc, 0, _v, build_droppy); + acc.assert_equality_last_two_lists(); + acc.print_table(); + + println!(); + + println!(" --- mismatching cases ---"); + + acc.new_list("let else _ mismatch"); + let_else!(&acc, 1, DroppyEnum::Some(_, _), build_droppy_enum_none); + acc.new_list("let else _v mismatch"); + let_else!(&acc, 1, DroppyEnum::Some(_, _v), build_droppy_enum_none); + acc.print_table(); + // This ensures that we always drop before visiting the else case + acc.assert_all_equal_to("drop,else"); + + acc.new_list("let else 0 mismatch"); + let_else!(&acc, 1, 0, build_droppy); + acc.new_list("let else 0 mismatch"); + let_else!(&acc, 1, 0, build_droppy); + acc.print_table(); + // This ensures that we always drop before visiting the else case + acc.assert_all_equal_to("drop,else"); +} diff --git a/tests/ui/let-else/let-else-drop-order.run.stdout b/tests/ui/let-else/let-else-drop-order.run.stdout new file mode 100644 index 000000000..01cf2f73e --- /dev/null +++ b/tests/ui/let-else/let-else-drop-order.run.stdout @@ -0,0 +1,51 @@ + --- matching cases --- + +| construct | let _ | let else _ | +| ------------ | --------- | ---------- | +| vanilla | drop,body | drop,body | +| & | body,drop | body,drop | +| &mut | body,drop | body,drop | +| move | drop,body | drop,body | +| fn(this) | drop,body | drop,body | +| tuple | n/a,n/a | drop,body | +| array | n/a,n/a | drop,body | +| ref & | body,drop | body,drop | +| ref mut &mut | body,drop | body,drop | + +| construct | let _v | let else _v | +| ------------ | --------- | ----------- | +| vanilla | drop,body | drop,body | +| & | body,drop | body,drop | +| &mut | body,drop | body,drop | +| move | drop,body | drop,body | +| fn(this) | drop,body | drop,body | +| tuple | n/a,n/a | drop,body | +| array | n/a,n/a | drop,body | +| ref & | body,drop | body,drop | +| ref mut &mut | body,drop | body,drop | + + --- mismatching cases --- + +| construct | let else _ mismatch | let else _v mismatch | +| ------------ | ------------------- | -------------------- | +| vanilla | drop,else | drop,else | +| & | drop,else | drop,else | +| &mut | drop,else | drop,else | +| move | drop,else | drop,else | +| fn(this) | drop,else | drop,else | +| tuple | drop,else | drop,else | +| array | drop,else | drop,else | +| ref & | drop,else | drop,else | +| ref mut &mut | drop,else | drop,else | + +| construct | let else 0 mismatch | let else 0 mismatch | +| ------------ | ------------------- | ------------------- | +| vanilla | drop,else | drop,else | +| & | drop,else | drop,else | +| &mut | drop,else | drop,else | +| move | drop,else | drop,else | +| fn(this) | drop,else | drop,else | +| tuple | drop,else | drop,else | +| array | drop,else | drop,else | +| ref & | drop,else | drop,else | +| ref mut &mut | drop,else | drop,else | diff --git a/tests/ui/let-else/let-else-if.rs b/tests/ui/let-else/let-else-if.rs new file mode 100644 index 000000000..e8c54ca7a --- /dev/null +++ b/tests/ui/let-else/let-else-if.rs @@ -0,0 +1,8 @@ +fn main() { + let Some(_) = Some(()) else if true { + //~^ ERROR conditional `else if` is not supported for `let...else` + return; + } else { + return; + }; +} diff --git a/tests/ui/let-else/let-else-if.stderr b/tests/ui/let-else/let-else-if.stderr new file mode 100644 index 000000000..c63fd61c5 --- /dev/null +++ b/tests/ui/let-else/let-else-if.stderr @@ -0,0 +1,17 @@ +error: conditional `else if` is not supported for `let...else` + --> $DIR/let-else-if.rs:2:33 + | +LL | let Some(_) = Some(()) else if true { + | ^^ expected `{` + | +help: try placing this code inside a block + | +LL ~ let Some(_) = Some(()) else { if true { +LL | + ... +LL | return; +LL ~ } }; + | + +error: aborting due to previous error + diff --git a/tests/ui/let-else/let-else-irrefutable.rs b/tests/ui/let-else/let-else-irrefutable.rs new file mode 100644 index 000000000..f4b338eb0 --- /dev/null +++ b/tests/ui/let-else/let-else-irrefutable.rs @@ -0,0 +1,11 @@ +// check-pass + +fn main() { + let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern + + // Multiline else blocks should not get printed + let x = 1 else { //~ WARN irrefutable `let...else` pattern + eprintln!("problem case encountered"); + return + }; +} diff --git a/tests/ui/let-else/let-else-irrefutable.stderr b/tests/ui/let-else/let-else-irrefutable.stderr new file mode 100644 index 000000000..73d4e5f34 --- /dev/null +++ b/tests/ui/let-else/let-else-irrefutable.stderr @@ -0,0 +1,21 @@ +warning: irrefutable `let...else` pattern + --> $DIR/let-else-irrefutable.rs:4:5 + | +LL | let x = 1 else { return }; + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: irrefutable `let...else` pattern + --> $DIR/let-else-irrefutable.rs:7:5 + | +LL | let x = 1 else { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: 2 warnings emitted + diff --git a/tests/ui/let-else/let-else-missing-semicolon.rs b/tests/ui/let-else/let-else-missing-semicolon.rs new file mode 100644 index 000000000..d87ac90c1 --- /dev/null +++ b/tests/ui/let-else/let-else-missing-semicolon.rs @@ -0,0 +1,9 @@ +fn main() { + let Some(x) = Some(1) else { + return; + } //~ ERROR expected `;`, found keyword `let` + let _ = ""; + let Some(x) = Some(1) else { + panic!(); + } //~ ERROR expected `;`, found `}` +} diff --git a/tests/ui/let-else/let-else-missing-semicolon.stderr b/tests/ui/let-else/let-else-missing-semicolon.stderr new file mode 100644 index 000000000..99029ff33 --- /dev/null +++ b/tests/ui/let-else/let-else-missing-semicolon.stderr @@ -0,0 +1,18 @@ +error: expected `;`, found keyword `let` + --> $DIR/let-else-missing-semicolon.rs:4:6 + | +LL | } + | ^ help: add `;` here +LL | let _ = ""; + | --- unexpected token + +error: expected `;`, found `}` + --> $DIR/let-else-missing-semicolon.rs:8:6 + | +LL | } + | ^ help: add `;` here +LL | } + | - unexpected token + +error: aborting due to 2 previous errors + diff --git a/tests/ui/let-else/let-else-no-double-error.rs b/tests/ui/let-else/let-else-no-double-error.rs new file mode 100644 index 000000000..91fcc5d7e --- /dev/null +++ b/tests/ui/let-else/let-else-no-double-error.rs @@ -0,0 +1,12 @@ +// from rfc2005 test suite + + + +// Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs +// the error below would be reported twice (once when checking +// for a non-ref pattern, once when processing the pattern). + +fn main() { + let foo = 22; + let u32::XXX = foo else { return }; //~ ERROR: no associated item named `XXX` found for type `u32` in the current scope [E0599] +} diff --git a/tests/ui/let-else/let-else-no-double-error.stderr b/tests/ui/let-else/let-else-no-double-error.stderr new file mode 100644 index 000000000..941e588b1 --- /dev/null +++ b/tests/ui/let-else/let-else-no-double-error.stderr @@ -0,0 +1,9 @@ +error[E0599]: no associated item named `XXX` found for type `u32` in the current scope + --> $DIR/let-else-no-double-error.rs:11:14 + | +LL | let u32::XXX = foo else { return }; + | ^^^ associated item not found in `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/let-else/let-else-non-copy.rs b/tests/ui/let-else/let-else-non-copy.rs new file mode 100644 index 000000000..08c07dd1a --- /dev/null +++ b/tests/ui/let-else/let-else-non-copy.rs @@ -0,0 +1,45 @@ +// run-pass +// +// This is derived from a change to compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs, in +// preparation for adopting let-else within the compiler (thanks @est31): +// +// ``` +// - let place = if let mir::VarDebugInfoContents::Place(p) = var.value { p } else { continue }; +// + let mir::VarDebugInfoContents::Place(place) = var.value else { continue }; +// ``` +// +// The move was due to mir::Place being Copy, but mir::VarDebugInfoContents not being Copy. + + + +#[derive(Copy, Clone)] +struct Copyable; + +enum NonCopy { + Thing(Copyable), + #[allow(unused)] + Other, +} + +struct Wrapper { + field: NonCopy, +} + +fn let_else() { + let vec = vec![Wrapper { field: NonCopy::Thing(Copyable) }]; + for item in &vec { + let NonCopy::Thing(_copyable) = item.field else { continue }; + } +} + +fn if_let() { + let vec = vec![Wrapper { field: NonCopy::Thing(Copyable) }]; + for item in &vec { + let _copyable = if let NonCopy::Thing(copyable) = item.field { copyable } else { continue }; + } +} + +fn main() { + let_else(); + if_let(); +} diff --git a/tests/ui/let-else/let-else-non-diverging.rs b/tests/ui/let-else/let-else-non-diverging.rs new file mode 100644 index 000000000..a5442dd82 --- /dev/null +++ b/tests/ui/let-else/let-else-non-diverging.rs @@ -0,0 +1,22 @@ +fn main() { + let Some(x) = Some(1) else { //~ ERROR does not diverge + Some(2) + }; + let Some(x) = Some(1) else { //~ ERROR does not diverge + if 1 == 1 { + panic!(); + } + }; + let Some(x) = Some(1) else { Some(2) }; //~ ERROR does not diverge + + // Ensure that uninhabited types do not "diverge". + // This might be relaxed in the future, but when it is, + // it should be an explicitly wanted decision. + let Some(x) = Some(1) else { foo::() }; //~ ERROR does not diverge +} + +enum Uninhabited {} + +fn foo() -> T { + panic!() +} diff --git a/tests/ui/let-else/let-else-non-diverging.stderr b/tests/ui/let-else/let-else-non-diverging.stderr new file mode 100644 index 000000000..78551fcc4 --- /dev/null +++ b/tests/ui/let-else/let-else-non-diverging.stderr @@ -0,0 +1,55 @@ +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:2:32 + | +LL | let Some(x) = Some(1) else { + | ________________________________^ +LL | | Some(2) +LL | | }; + | |_____^ expected `!`, found enum `Option` + | + = note: expected type `!` + found enum `Option<{integer}>` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:5:32 + | +LL | let Some(x) = Some(1) else { + | ________________________________^ +LL | | if 1 == 1 { +LL | | panic!(); +LL | | } +LL | | }; + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:10:32 + | +LL | let Some(x) = Some(1) else { Some(2) }; + | ^^^^^^^^^^^ expected `!`, found enum `Option` + | + = note: expected type `!` + found enum `Option<{integer}>` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error[E0308]: `else` clause of `let...else` does not diverge + --> $DIR/let-else-non-diverging.rs:15:32 + | +LL | let Some(x) = Some(1) else { foo::() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found enum `Uninhabited` + | + = note: expected type `!` + found enum `Uninhabited` + = help: try adding a diverging expression, such as `return` or `panic!(..)` + = help: ...or use `match` instead of `let...else` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/let-else/let-else-ref-bindings-pass.rs b/tests/ui/let-else/let-else-ref-bindings-pass.rs new file mode 100644 index 000000000..62fc65731 --- /dev/null +++ b/tests/ui/let-else/let-else-ref-bindings-pass.rs @@ -0,0 +1,71 @@ +// check-pass + + +#![allow(unused_variables)] + +fn ref_() { + let bytes: Vec = b"Hello"[..].to_vec(); + let some = Some(bytes); + + let Some(ref a) = Some(()) else { return }; + + // | ref | type annotation | & | + // | --- | --------------- | - | + // | x | x | | error + // | x | x | x | error + // | | x | | error + // | | x | x | error + // | x | | | + let Some(ref a) = some else { return }; // OK + let b: &[u8] = a; + + // | x | | x | + let Some(ref a) = &some else { return }; // OK + let b: &[u8] = a; + + + // | | | x | + let Some(a) = &some else { return }; // OK + let b: &[u8] = a; + + let Some(a): Option<&[u8]> = some.as_deref() else { return }; // OK + let b: &[u8] = a; + let Some(ref a): Option<&[u8]> = some.as_deref() else { return }; // OK + let b: &[u8] = a; +} + +fn ref_mut() { + // This `ref mut` case had an ICE, see issue #89960 + let Some(ref mut a) = Some(()) else { return }; + + let bytes: Vec = b"Hello"[..].to_vec(); + let mut some = Some(bytes); + + // | ref mut | type annotation | &mut | + // | ------- | --------------- | ---- | + // | x | x | | error + // | x | x | x | error + // | | x | | error + // | | x | x | error + // | x | | | + let Some(ref mut a) = some else { return }; // OK + let b: &mut [u8] = a; + + // | x | | x | + let Some(ref mut a) = &mut some else { return }; // OK + let b: &mut [u8] = a; + + // | | | x | + let Some(a) = &mut some else { return }; // OK + let b: &mut [u8] = a; + + let Some(a): Option<&mut [u8]> = some.as_deref_mut() else { return }; // OK + let b: &mut [u8] = a; + let Some(ref mut a): Option<&mut [u8]> = some.as_deref_mut() else { return }; // OK + let b: &mut [u8] = a; +} + +fn main() { + ref_(); + ref_mut(); +} diff --git a/tests/ui/let-else/let-else-ref-bindings.rs b/tests/ui/let-else/let-else-ref-bindings.rs new file mode 100644 index 000000000..687e235d4 --- /dev/null +++ b/tests/ui/let-else/let-else-ref-bindings.rs @@ -0,0 +1,62 @@ +#![allow(unused_variables)] + + +fn ref_() { + let bytes: Vec = b"Hello"[..].to_vec(); + let some = Some(bytes); + + let Some(ref a) = Some(()) else { return }; + + // | ref | type annotation | & | + // | --- | --------------- | - | + // | x | | | OK + // | x | | x | OK + // | | | x | OK + // | x | x | | + let Some(ref a): Option<&[u8]> = some else { return }; //~ ERROR mismatched types + let b: & [u8] = a; + + // | x | x | x | + let Some(ref a): Option<&[u8]> = &some else { return }; //~ ERROR mismatched types + let b: & [u8] = a; + + // | | x | | + let Some(a): Option<&[u8]> = some else { return }; //~ ERROR mismatched types + let b: &[u8] = a; + // | | x | x | + let Some(a): Option<&[u8]> = &some else { return }; //~ ERROR mismatched types + let b: &[u8] = a; +} + +fn ref_mut() { + // This `ref mut` case had an ICE, see issue #89960 + let Some(ref mut a) = Some(()) else { return }; + + let bytes: Vec = b"Hello"[..].to_vec(); + let mut some = Some(bytes); + + // | ref mut | type annotation | &mut | + // | ------- | --------------- | ---- | + // | x | | | OK + // | x | | x | OK + // | | | x | OK + // | x | x | | + let Some(ref mut a): Option<&mut [u8]> = some else { return }; //~ ERROR mismatched types + let b: &mut [u8] = a; + + // | x | x | x | (nope) + let Some(ref mut a): Option<&mut [u8]> = &mut some else { return }; //~ ERROR mismatched types + let b: &mut [u8] = a; + + // | | x | | + let Some(a): Option<&mut [u8]> = some else { return }; //~ ERROR mismatched types + let b: &mut [u8] = a; + // | | x | x | + let Some(a): Option<&mut [u8]> = &mut some else { return }; //~ ERROR mismatched types + let b: &mut [u8] = a; +} + +fn main() { + ref_(); + ref_mut(); +} diff --git a/tests/ui/let-else/let-else-ref-bindings.stderr b/tests/ui/let-else/let-else-ref-bindings.stderr new file mode 100644 index 000000000..56b9e0733 --- /dev/null +++ b/tests/ui/let-else/let-else-ref-bindings.stderr @@ -0,0 +1,83 @@ +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:16:38 + | +LL | let Some(ref a): Option<&[u8]> = some else { return }; + | ^^^^ expected `&[u8]`, found struct `Vec` + | + = note: expected enum `Option<&[u8]>` + found enum `Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:20:38 + | +LL | let Some(ref a): Option<&[u8]> = &some else { return }; + | ^^^^^ expected enum `Option`, found `&Option>` + | + = note: expected enum `Option<&[u8]>` + found reference `&Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:24:34 + | +LL | let Some(a): Option<&[u8]> = some else { return }; + | ------------- ^^^^ expected `&[u8]`, found struct `Vec` + | | + | expected due to this + | + = note: expected enum `Option<&[u8]>` + found enum `Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:27:34 + | +LL | let Some(a): Option<&[u8]> = &some else { return }; + | ------------- ^^^^^ expected enum `Option`, found `&Option>` + | | + | expected due to this + | + = note: expected enum `Option<&[u8]>` + found reference `&Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:44:46 + | +LL | let Some(ref mut a): Option<&mut [u8]> = some else { return }; + | ^^^^ expected `&mut [u8]`, found struct `Vec` + | + = note: expected enum `Option<&mut [u8]>` + found enum `Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:48:46 + | +LL | let Some(ref mut a): Option<&mut [u8]> = &mut some else { return }; + | ^^^^^^^^^ expected enum `Option`, found mutable reference + | + = note: expected enum `Option<&mut [u8]>` + found mutable reference `&mut Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:52:38 + | +LL | let Some(a): Option<&mut [u8]> = some else { return }; + | ----------------- ^^^^ expected `&mut [u8]`, found struct `Vec` + | | + | expected due to this + | + = note: expected enum `Option<&mut [u8]>` + found enum `Option>` + +error[E0308]: mismatched types + --> $DIR/let-else-ref-bindings.rs:55:38 + | +LL | let Some(a): Option<&mut [u8]> = &mut some else { return }; + | ----------------- ^^^^^^^^^ expected enum `Option`, found mutable reference + | | + | expected due to this + | + = note: expected enum `Option<&mut [u8]>` + found mutable reference `&mut Option>` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/let-else/let-else-run-pass.rs b/tests/ui/let-else/let-else-run-pass.rs new file mode 100644 index 000000000..a0fb6c683 --- /dev/null +++ b/tests/ui/let-else/let-else-run-pass.rs @@ -0,0 +1,35 @@ +// run-pass + + + +fn main() { + #[allow(dead_code)] + enum MyEnum { + A(String), + B { f: String }, + C, + } + // ref binding to non-copy value and or-pattern + let (MyEnum::A(ref x) | MyEnum::B { f: ref x }) = (MyEnum::B { f: String::new() }) else { + panic!(); + }; + assert_eq!(x, ""); + + // nested let-else + let mut x = 1; + loop { + let 4 = x else { + let 3 = x else { + x += 1; + continue; + }; + break; + }; + panic!(); + } + assert_eq!(x, 3); + + // else return + let Some(1) = Some(2) else { return }; + panic!(); +} diff --git a/tests/ui/let-else/let-else-scope.rs b/tests/ui/let-else/let-else-scope.rs new file mode 100644 index 000000000..78a67769e --- /dev/null +++ b/tests/ui/let-else/let-else-scope.rs @@ -0,0 +1,5 @@ +fn main() { + let Some(x) = Some(2) else { + panic!("{}", x); //~ ERROR cannot find value `x` in this scope + }; +} diff --git a/tests/ui/let-else/let-else-scope.stderr b/tests/ui/let-else/let-else-scope.stderr new file mode 100644 index 000000000..3b4f09829 --- /dev/null +++ b/tests/ui/let-else/let-else-scope.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/let-else-scope.rs:3:22 + | +LL | panic!("{}", x); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/let-else/let-else-slicing-error.rs b/tests/ui/let-else/let-else-slicing-error.rs new file mode 100644 index 000000000..25770094b --- /dev/null +++ b/tests/ui/let-else/let-else-slicing-error.rs @@ -0,0 +1,9 @@ +// issue #92069 + + +fn main() { + let nums = vec![5, 4, 3, 2, 1]; + let [x, y] = nums else { //~ ERROR expected an array or slice + return; + }; +} diff --git a/tests/ui/let-else/let-else-slicing-error.stderr b/tests/ui/let-else/let-else-slicing-error.stderr new file mode 100644 index 000000000..064025e03 --- /dev/null +++ b/tests/ui/let-else/let-else-slicing-error.stderr @@ -0,0 +1,11 @@ +error[E0529]: expected an array or slice, found `Vec<{integer}>` + --> $DIR/let-else-slicing-error.rs:6:9 + | +LL | let [x, y] = nums else { + | ^^^^^^ ---- help: consider slicing here: `nums[..]` + | | + | pattern cannot match with input type `Vec<{integer}>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/let-else/let-else-source-expr-nomove-pass.rs b/tests/ui/let-else/let-else-source-expr-nomove-pass.rs new file mode 100644 index 000000000..ee378abcf --- /dev/null +++ b/tests/ui/let-else/let-else-source-expr-nomove-pass.rs @@ -0,0 +1,17 @@ +// run-pass +// issue #89688 + + + +fn example_let_else(value: Option) { + let Some(inner) = value else { + println!("other: {:?}", value); // OK + return; + }; + println!("inner: {}", inner); +} + +fn main() { + example_let_else(Some("foo".into())); + example_let_else(None); +} diff --git a/tests/ui/let-else/let-else-temp-borrowck.rs b/tests/ui/let-else/let-else-temp-borrowck.rs new file mode 100644 index 000000000..6b4642d2f --- /dev/null +++ b/tests/ui/let-else/let-else-temp-borrowck.rs @@ -0,0 +1,26 @@ +// run-pass +// +// from issue #93951, where borrowck complained the temporary that `foo(&x)` was stored in was to +// be dropped sometime after `x` was. It then suggested adding a semicolon that was already there. + + +use std::fmt::Debug; + +fn foo<'a>(x: &'a str) -> Result { + Ok(x) +} + +fn let_else() { + let x = String::from("Hey"); + let Ok(_) = foo(&x) else { return }; +} + +fn if_let() { + let x = String::from("Hey"); + let _ = if let Ok(s) = foo(&x) { s } else { return }; +} + +fn main() { + let_else(); + if_let(); +} diff --git a/tests/ui/let-else/let-else-temporary-lifetime.rs b/tests/ui/let-else/let-else-temporary-lifetime.rs new file mode 100644 index 000000000..c23eaa997 --- /dev/null +++ b/tests/ui/let-else/let-else-temporary-lifetime.rs @@ -0,0 +1,99 @@ +// run-pass +// compile-flags: -Zvalidate-mir + +use std::fmt::Display; +use std::rc::Rc; +use std::sync::atomic::{AtomicU8, Ordering}; + +static TRACKER: AtomicU8 = AtomicU8::new(0); + +#[derive(Default)] +struct Droppy { + inner: u32, +} + +impl Drop for Droppy { + fn drop(&mut self) { + TRACKER.store(1, Ordering::Release); + println!("I've been dropped"); + } +} + +fn foo<'a>(x: &'a str) -> Result { + Ok(x) +} + +fn main() { + assert_eq!(TRACKER.load(Ordering::Acquire), 0); + let 0 = Droppy::default().inner else { return }; + assert_eq!(TRACKER.load(Ordering::Acquire), 1); + println!("Should have dropped 👆"); + + { + // cf. https://github.com/rust-lang/rust/pull/99518#issuecomment-1191520030 + struct Foo<'a>(&'a mut u32); + + impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + *self.0 = 0; + } + } + let mut foo = 0; + let Foo(0) = Foo(&mut foo) else { + *&mut foo = 1; + todo!() + }; + } + { + let x = String::from("Hey"); + + let Ok(s) = foo(&x) else { panic!() }; + assert_eq!(s.to_string(), x); + } + { + // test let-else drops temps after statement + let rc = Rc::new(0); + let 0 = *rc.clone() else { unreachable!() }; + Rc::try_unwrap(rc).unwrap(); + } + { + let mut rc = Rc::new(0); + let mut i = 0; + loop { + if i > 3 { + break; + } + let 1 = *rc.clone() else { + if let Ok(v) = Rc::try_unwrap(rc) { + rc = Rc::new(v); + } else { + panic!() + } + i += 1; + continue + }; + } + } + { + fn must_pass() { + let rc = Rc::new(()); + let &None = &Some(Rc::clone(&rc)) else { + Rc::try_unwrap(rc).unwrap(); + return; + }; + unreachable!(); + } + must_pass(); + } + { + // test let-else drops temps before else block + // NOTE: this test has to be the last block in the `main` + // body. + let rc = Rc::new(0); + let 1 = *rc.clone() else { + Rc::try_unwrap(rc).unwrap(); + return; + }; + unreachable!(); + } +} diff --git a/tests/ui/let-else/let-else-then-diverge.rs b/tests/ui/let-else/let-else-then-diverge.rs new file mode 100644 index 000000000..1a75310c9 --- /dev/null +++ b/tests/ui/let-else/let-else-then-diverge.rs @@ -0,0 +1,17 @@ +// popped up in #94012, where an alternative desugaring was +// causing unreachable code errors + +#![deny(unused_variables)] +#![deny(unreachable_code)] + +fn let_else_diverge() -> bool { + let Some(_) = Some("test") else { + let x = 5; //~ ERROR unused variable: `x` + return false; + }; + return true; +} + +fn main() { + let_else_diverge(); +} diff --git a/tests/ui/let-else/let-else-then-diverge.stderr b/tests/ui/let-else/let-else-then-diverge.stderr new file mode 100644 index 000000000..470a11d47 --- /dev/null +++ b/tests/ui/let-else/let-else-then-diverge.stderr @@ -0,0 +1,14 @@ +error: unused variable: `x` + --> $DIR/let-else-then-diverge.rs:9:13 + | +LL | let x = 5; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/let-else-then-diverge.rs:4:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/let-else/let-else.rs b/tests/ui/let-else/let-else.rs new file mode 100644 index 000000000..3505533e6 --- /dev/null +++ b/tests/ui/let-else/let-else.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + let Some(x) = Some(1) else { + return; + }; + assert_eq!(x, 1); +} diff --git a/tests/ui/lexer/error-stage.rs b/tests/ui/lexer/error-stage.rs new file mode 100644 index 000000000..c8d88f745 --- /dev/null +++ b/tests/ui/lexer/error-stage.rs @@ -0,0 +1,80 @@ +// This test is about the treatment of invalid literals. In particular, some +// literals are only considered invalid if they survive to HIR lowering. +// +// Literals with bad suffixes +// -------------------------- +// Literals consist of a primary part and an optional suffix. +// https://doc.rust-lang.org/reference/tokens.html#suffixes says: +// +// Any kind of literal (string, integer, etc) with any suffix is valid as a +// token, and can be passed to a macro without producing an error. The macro +// itself will decide how to interpret such a token and whether to produce an +// error or not. +// +// ``` +// macro_rules! blackhole { ($tt:tt) => () } +// blackhole!("string"suffix); // OK +// ``` +// +// However, suffixes on literal tokens parsed as Rust code are restricted. +// Any suffixes are rejected on non-numeric literal tokens, and numeric +// literal tokens are accepted only with suffixes from the list below. +// +// Integer: u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize +// Floating-point: f32, f64 +// +// This means that something like `"string"any_suffix` is a token accepted by +// the lexer, but rejected later for being an invalid combination of primary +// part and suffix. +// +// `0b10f32` is a similar case. `0b10` is a valid primary part that is a valid +// *integer* literal when no suffix is present. It only causes an error later +// when combined with the `f32` float suffix. +// +// However, `0b10.0f32` is different. It is rejected by the lexer because +// `0b10.0` is not a valid token even on its own. +// +// This difference is unfortunate, but it's baked into the language now. +// +// Too-large integer literals +// -------------------------- +// https://doc.rust-lang.org/reference/tokens.html#integer-literals says that +// literals like `128_i8` and `256_u8` "are too big for their type, but are +// still valid tokens". + +macro_rules! sink { + ($($x:tt;)*) => {()} +} + +// The invalid literals are ignored because the macro consumes them. Except for +// `0b10.0f32` because it's a lexer error. +const _: () = sink! { + "string"any_suffix; // OK + 10u123; // OK + 10.0f123; // OK + 0b10f32; // OK + 0b10.0f32; //~ ERROR binary float literal is not supported + 999340282366920938463463374607431768211455999; // OK +}; + +// The invalid literals used to cause errors, but this was changed by #102944. +// Except for `0b010.0f32`, because it's a lexer error. +#[cfg(FALSE)] +fn configured_out() { + "string"any_suffix; // OK + 10u123; // OK + 10.0f123; // OK + 0b10f32; // OK + 0b10.0f32; //~ ERROR binary float literal is not supported + 999340282366920938463463374607431768211455999; // OK +} + +// All the invalid literals cause errors. +fn main() { + "string"any_suffix; //~ ERROR suffixes on string literals are invalid + 10u123; //~ ERROR invalid width `123` for integer literal + 10.0f123; //~ ERROR invalid width `123` for float literal + 0b10f32; //~ ERROR binary float literal is not supported + 0b10.0f32; //~ ERROR binary float literal is not supported + 999340282366920938463463374607431768211455999; //~ ERROR integer literal is too large +} diff --git a/tests/ui/lexer/error-stage.stderr b/tests/ui/lexer/error-stage.stderr new file mode 100644 index 000000000..ecbdb14dc --- /dev/null +++ b/tests/ui/lexer/error-stage.stderr @@ -0,0 +1,56 @@ +error: binary float literal is not supported + --> $DIR/error-stage.rs:56:5 + | +LL | 0b10.0f32; + | ^^^^^^ + +error: binary float literal is not supported + --> $DIR/error-stage.rs:68:5 + | +LL | 0b10.0f32; + | ^^^^^^ + +error: binary float literal is not supported + --> $DIR/error-stage.rs:78:5 + | +LL | 0b10.0f32; + | ^^^^^^ + +error: suffixes on string literals are invalid + --> $DIR/error-stage.rs:74:5 + | +LL | "string"any_suffix; + | ^^^^^^^^^^^^^^^^^^ invalid suffix `any_suffix` + +error: invalid width `123` for integer literal + --> $DIR/error-stage.rs:75:5 + | +LL | 10u123; + | ^^^^^^ + | + = help: valid widths are 8, 16, 32, 64 and 128 + +error: invalid width `123` for float literal + --> $DIR/error-stage.rs:76:5 + | +LL | 10.0f123; + | ^^^^^^^^ + | + = help: valid widths are 32 and 64 + +error: binary float literal is not supported + --> $DIR/error-stage.rs:77:5 + | +LL | 0b10f32; + | ^^^^^^^ not supported + +error: integer literal is too large + --> $DIR/error-stage.rs:79:5 + | +LL | 999340282366920938463463374607431768211455999; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lexer/lex-bad-binary-literal.rs b/tests/ui/lexer/lex-bad-binary-literal.rs new file mode 100644 index 000000000..7df98073e --- /dev/null +++ b/tests/ui/lexer/lex-bad-binary-literal.rs @@ -0,0 +1,11 @@ +fn main() { + 0b121; //~ ERROR invalid digit for a base 2 literal + 0b10_10301; //~ ERROR invalid digit for a base 2 literal + 0b30; //~ ERROR invalid digit for a base 2 literal + 0b41; //~ ERROR invalid digit for a base 2 literal + 0b5; //~ ERROR invalid digit for a base 2 literal + 0b6; //~ ERROR invalid digit for a base 2 literal + 0b7; //~ ERROR invalid digit for a base 2 literal + 0b8; //~ ERROR invalid digit for a base 2 literal + 0b9; //~ ERROR invalid digit for a base 2 literal +} diff --git a/tests/ui/lexer/lex-bad-binary-literal.stderr b/tests/ui/lexer/lex-bad-binary-literal.stderr new file mode 100644 index 000000000..992b3d248 --- /dev/null +++ b/tests/ui/lexer/lex-bad-binary-literal.stderr @@ -0,0 +1,56 @@ +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:2:8 + | +LL | 0b121; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:3:12 + | +LL | 0b10_10301; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:4:7 + | +LL | 0b30; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:5:7 + | +LL | 0b41; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:6:7 + | +LL | 0b5; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:7:7 + | +LL | 0b6; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:8:7 + | +LL | 0b7; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:9:7 + | +LL | 0b8; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/lex-bad-binary-literal.rs:10:7 + | +LL | 0b9; + | ^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lexer/lex-bad-char-literals-1.rs b/tests/ui/lexer/lex-bad-char-literals-1.rs new file mode 100644 index 000000000..e7951cfd2 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-1.rs @@ -0,0 +1,17 @@ +static c3: char = + '\x1' //~ ERROR: numeric character escape is too short +; + +static s3: &'static str = + "\x1" //~ ERROR: numeric character escape is too short +; + +static c: char = + '\â—' //~ ERROR: unknown character escape +; + +static s: &'static str = + "\â—" //~ ERROR: unknown character escape +; + +fn main() {} diff --git a/tests/ui/lexer/lex-bad-char-literals-1.stderr b/tests/ui/lexer/lex-bad-char-literals-1.stderr new file mode 100644 index 000000000..e6ff1f662 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-1.stderr @@ -0,0 +1,38 @@ +error: numeric character escape is too short + --> $DIR/lex-bad-char-literals-1.rs:2:6 + | +LL | '\x1' + | ^^^ + +error: numeric character escape is too short + --> $DIR/lex-bad-char-literals-1.rs:6:6 + | +LL | "\x1" + | ^^^ + +error: unknown character escape: `\u{25cf}` + --> $DIR/lex-bad-char-literals-1.rs:10:7 + | +LL | '\â—' + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL | r"\â—" + | ~~~~~ + +error: unknown character escape: `\u{25cf}` + --> $DIR/lex-bad-char-literals-1.rs:14:7 + | +LL | "\â—" + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL | r"\â—" + | ~~~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lexer/lex-bad-char-literals-2.rs b/tests/ui/lexer/lex-bad-char-literals-2.rs new file mode 100644 index 000000000..d35dafd9a --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-2.rs @@ -0,0 +1,6 @@ +// This test needs to the last one appearing in this file as it kills the parser +static c: char = + 'nope' //~ ERROR: character literal may only contain one codepoint +; + +fn main() {} diff --git a/tests/ui/lexer/lex-bad-char-literals-2.stderr b/tests/ui/lexer/lex-bad-char-literals-2.stderr new file mode 100644 index 000000000..c2b19a7ad --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-2.stderr @@ -0,0 +1,13 @@ +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-2.rs:3:5 + | +LL | 'nope' + | ^^^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | "nope" + | ~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lexer/lex-bad-char-literals-3.rs b/tests/ui/lexer/lex-bad-char-literals-3.rs new file mode 100644 index 000000000..5194ff4d9 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-3.rs @@ -0,0 +1,7 @@ +static c: char = 'â—â—'; +//~^ ERROR: character literal may only contain one codepoint + +fn main() { + let ch: &str = 'â—â—'; + //~^ ERROR: character literal may only contain one codepoint +} diff --git a/tests/ui/lexer/lex-bad-char-literals-3.stderr b/tests/ui/lexer/lex-bad-char-literals-3.stderr new file mode 100644 index 000000000..62a5e424c --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-3.stderr @@ -0,0 +1,24 @@ +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-3.rs:1:18 + | +LL | static c: char = 'â—â—'; + | ^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | static c: char = "â—â—"; + | ~~~~ + +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-3.rs:5:20 + | +LL | let ch: &str = 'â—â—'; + | ^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let ch: &str = "â—â—"; + | ~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lexer/lex-bad-char-literals-4.rs b/tests/ui/lexer/lex-bad-char-literals-4.rs new file mode 100644 index 000000000..de0a19df9 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-4.rs @@ -0,0 +1,5 @@ +// +// This test needs to the last one appearing in this file as it kills the parser +static c: char = + 'â— //~ ERROR: unterminated character literal +; diff --git a/tests/ui/lexer/lex-bad-char-literals-4.stderr b/tests/ui/lexer/lex-bad-char-literals-4.stderr new file mode 100644 index 000000000..fec4421c4 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-4.stderr @@ -0,0 +1,9 @@ +error[E0762]: unterminated character literal + --> $DIR/lex-bad-char-literals-4.rs:4:5 + | +LL | 'â— + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0762`. diff --git a/tests/ui/lexer/lex-bad-char-literals-5.rs b/tests/ui/lexer/lex-bad-char-literals-5.rs new file mode 100644 index 000000000..0c4339edc --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-5.rs @@ -0,0 +1,7 @@ +static c: char = '\x10\x10'; +//~^ ERROR: character literal may only contain one codepoint + +fn main() { + let ch: &str = '\x10\x10'; + //~^ ERROR: character literal may only contain one codepoint +} diff --git a/tests/ui/lexer/lex-bad-char-literals-5.stderr b/tests/ui/lexer/lex-bad-char-literals-5.stderr new file mode 100644 index 000000000..184817a65 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-5.stderr @@ -0,0 +1,24 @@ +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-5.rs:1:18 + | +LL | static c: char = '\x10\x10'; + | ^^^^^^^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | static c: char = "\x10\x10"; + | ~~~~~~~~~~ + +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-5.rs:5:20 + | +LL | let ch: &str = '\x10\x10'; + | ^^^^^^^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let ch: &str = "\x10\x10"; + | ~~~~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lexer/lex-bad-char-literals-6.rs b/tests/ui/lexer/lex-bad-char-literals-6.rs new file mode 100644 index 000000000..1b498c0fb --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-6.rs @@ -0,0 +1,15 @@ +fn main() { + let x: &str = 'ab'; + //~^ ERROR: character literal may only contain one codepoint + let y: char = 'cd'; + //~^ ERROR: character literal may only contain one codepoint + let z = 'ef'; + //~^ ERROR: character literal may only contain one codepoint + + if x == y {} + if y == z {} // no error here + if x == z {} + + let a: usize = ""; + //~^ ERROR: mismatched types +} diff --git a/tests/ui/lexer/lex-bad-char-literals-6.stderr b/tests/ui/lexer/lex-bad-char-literals-6.stderr new file mode 100644 index 000000000..2fe30304a --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-6.stderr @@ -0,0 +1,44 @@ +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-6.rs:2:19 + | +LL | let x: &str = 'ab'; + | ^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let x: &str = "ab"; + | ~~~~ + +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-6.rs:4:19 + | +LL | let y: char = 'cd'; + | ^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let y: char = "cd"; + | ~~~~ + +error: character literal may only contain one codepoint + --> $DIR/lex-bad-char-literals-6.rs:6:13 + | +LL | let z = 'ef'; + | ^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let z = "ef"; + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/lex-bad-char-literals-6.rs:13:20 + | +LL | let a: usize = ""; + | ----- ^^ expected `usize`, found `&str` + | | + | expected due to this + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lexer/lex-bad-char-literals-7.rs b/tests/ui/lexer/lex-bad-char-literals-7.rs new file mode 100644 index 000000000..c675df2f3 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-7.rs @@ -0,0 +1,13 @@ +fn main() { + let _: char = ''; + //~^ ERROR: empty character literal + let _: char = '\u{}'; + //~^ ERROR: empty unicode escape + + // Next two are OK, but may befool error recovery + let _ = '/'; + let _ = b'/'; + + let _ = ' hello // here's a comment + //~^ ERROR: unterminated character literal +} diff --git a/tests/ui/lexer/lex-bad-char-literals-7.stderr b/tests/ui/lexer/lex-bad-char-literals-7.stderr new file mode 100644 index 000000000..255b9c689 --- /dev/null +++ b/tests/ui/lexer/lex-bad-char-literals-7.stderr @@ -0,0 +1,21 @@ +error: empty character literal + --> $DIR/lex-bad-char-literals-7.rs:2:20 + | +LL | let _: char = ''; + | ^ empty character literal + +error: empty unicode escape + --> $DIR/lex-bad-char-literals-7.rs:4:20 + | +LL | let _: char = '\u{}'; + | ^^^^ this escape must have at least 1 hex digit + +error[E0762]: unterminated character literal + --> $DIR/lex-bad-char-literals-7.rs:11:13 + | +LL | let _ = ' hello // here's a comment + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0762`. diff --git a/tests/ui/lexer/lex-bad-numeric-literals.rs b/tests/ui/lexer/lex-bad-numeric-literals.rs new file mode 100644 index 000000000..56bdc50e4 --- /dev/null +++ b/tests/ui/lexer/lex-bad-numeric-literals.rs @@ -0,0 +1,35 @@ +// ignore-tidy-linelength + +fn main() { + 0o1.0; //~ ERROR: octal float literal is not supported + 0o2f32; //~ ERROR: octal float literal is not supported + 0o3.0f32; //~ ERROR: octal float literal is not supported + 0o4e4; //~ ERROR: octal float literal is not supported + 0o5.0e5; //~ ERROR: octal float literal is not supported + 0o6e6f32; //~ ERROR: octal float literal is not supported + 0o7.0e7f64; //~ ERROR: octal float literal is not supported + 0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported + 0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported + 0o; //~ ERROR: no valid digits + 1e+; //~ ERROR: expected at least one digit in exponent + 0x539.0; //~ ERROR: hexadecimal float literal is not supported + 9900000000000000000000000000999999999999999999999999999999; + //~^ ERROR: integer literal is too large + 9900000000000000000000000000999999999999999999999999999999; + //~^ ERROR: integer literal is too large + 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; + //~^ ERROR: integer literal is too large + 0o37777777777777777777777777777777777777777770; + //~^ ERROR: integer literal is too large + 0xffffffffffffffffffffffffffffffff0; + //~^ ERROR: integer literal is too large + 0x; //~ ERROR: no valid digits + 0xu32; //~ ERROR: no valid digits + 0ou32; //~ ERROR: no valid digits + 0bu32; //~ ERROR: no valid digits + 0b; //~ ERROR: no valid digits + 0o123f64; //~ ERROR: octal float literal is not supported + 0o123.456; //~ ERROR: octal float literal is not supported + 0b101f64; //~ ERROR: binary float literal is not supported + 0b111.101; //~ ERROR: binary float literal is not supported +} diff --git a/tests/ui/lexer/lex-bad-numeric-literals.stderr b/tests/ui/lexer/lex-bad-numeric-literals.stderr new file mode 100644 index 000000000..145754197 --- /dev/null +++ b/tests/ui/lexer/lex-bad-numeric-literals.stderr @@ -0,0 +1,169 @@ +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:4:5 + | +LL | 0o1.0; + | ^^^^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:6:5 + | +LL | 0o3.0f32; + | ^^^^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:7:5 + | +LL | 0o4e4; + | ^^^^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:8:5 + | +LL | 0o5.0e5; + | ^^^^^^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:9:5 + | +LL | 0o6e6f32; + | ^^^^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:10:5 + | +LL | 0o7.0e7f64; + | ^^^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:11:5 + | +LL | 0x8.0e+9; + | ^^^^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:12:5 + | +LL | 0x9.0e-9; + | ^^^^^^^^ + +error[E0768]: no valid digits found for number + --> $DIR/lex-bad-numeric-literals.rs:13:5 + | +LL | 0o; + | ^^ + +error: expected at least one digit in exponent + --> $DIR/lex-bad-numeric-literals.rs:14:5 + | +LL | 1e+; + | ^^^ + +error: hexadecimal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:15:5 + | +LL | 0x539.0; + | ^^^^^^^ + +error[E0768]: no valid digits found for number + --> $DIR/lex-bad-numeric-literals.rs:26:5 + | +LL | 0x; + | ^^ + +error[E0768]: no valid digits found for number + --> $DIR/lex-bad-numeric-literals.rs:27:5 + | +LL | 0xu32; + | ^^ + +error[E0768]: no valid digits found for number + --> $DIR/lex-bad-numeric-literals.rs:28:5 + | +LL | 0ou32; + | ^^ + +error[E0768]: no valid digits found for number + --> $DIR/lex-bad-numeric-literals.rs:29:5 + | +LL | 0bu32; + | ^^ + +error[E0768]: no valid digits found for number + --> $DIR/lex-bad-numeric-literals.rs:30:5 + | +LL | 0b; + | ^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:32:5 + | +LL | 0o123.456; + | ^^^^^^^^^ + +error: binary float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:34:5 + | +LL | 0b111.101; + | ^^^^^^^^^ + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:5:5 + | +LL | 0o2f32; + | ^^^^^^ not supported + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:16:5 + | +LL | 9900000000000000000000000000999999999999999999999999999999; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:18:5 + | +LL | 9900000000000000000000000000999999999999999999999999999999; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:20:5 + | +LL | 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:22:5 + | +LL | 0o37777777777777777777777777777777777777777770; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0o3777777777777777777777777777777777777777777` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:24:5 + | +LL | 0xffffffffffffffffffffffffffffffff0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` + +error: octal float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:31:5 + | +LL | 0o123f64; + | ^^^^^^^^ not supported + +error: binary float literal is not supported + --> $DIR/lex-bad-numeric-literals.rs:33:5 + | +LL | 0b101f64; + | ^^^^^^^^ not supported + +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0768`. diff --git a/tests/ui/lexer/lex-bad-octal-literal.rs b/tests/ui/lexer/lex-bad-octal-literal.rs new file mode 100644 index 000000000..49631f16b --- /dev/null +++ b/tests/ui/lexer/lex-bad-octal-literal.rs @@ -0,0 +1,4 @@ +fn main() { + 0o18; //~ ERROR invalid digit for a base 8 literal + 0o1234_9_5670; //~ ERROR invalid digit for a base 8 literal +} diff --git a/tests/ui/lexer/lex-bad-octal-literal.stderr b/tests/ui/lexer/lex-bad-octal-literal.stderr new file mode 100644 index 000000000..2cb8ca5de --- /dev/null +++ b/tests/ui/lexer/lex-bad-octal-literal.stderr @@ -0,0 +1,14 @@ +error: invalid digit for a base 8 literal + --> $DIR/lex-bad-octal-literal.rs:2:8 + | +LL | 0o18; + | ^ + +error: invalid digit for a base 8 literal + --> $DIR/lex-bad-octal-literal.rs:3:12 + | +LL | 0o1234_9_5670; + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lexer/lex-bad-token.rs b/tests/ui/lexer/lex-bad-token.rs new file mode 100644 index 000000000..9e4824611 --- /dev/null +++ b/tests/ui/lexer/lex-bad-token.rs @@ -0,0 +1,3 @@ +â— //~ ERROR: unknown start of token + +fn main() {} diff --git a/tests/ui/lexer/lex-bad-token.stderr b/tests/ui/lexer/lex-bad-token.stderr new file mode 100644 index 000000000..43c43721b --- /dev/null +++ b/tests/ui/lexer/lex-bad-token.stderr @@ -0,0 +1,8 @@ +error: unknown start of token: \u{25cf} + --> $DIR/lex-bad-token.rs:1:1 + | +LL | â— + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/lexer/lex-bare-cr-nondoc-comment.rs b/tests/ui/lexer/lex-bare-cr-nondoc-comment.rs new file mode 100644 index 000000000..5b528d6e1 --- /dev/null +++ b/tests/ui/lexer/lex-bare-cr-nondoc-comment.rs @@ -0,0 +1,9 @@ +// run-pass +// ignore-tidy-cr + +// nondoc comment with bare CR: ' ' +//// nondoc comment with bare CR: ' ' +/* block nondoc comment with bare CR: ' ' */ + +fn main() { +} diff --git a/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs new file mode 100644 index 000000000..b7752e1f0 --- /dev/null +++ b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.rs @@ -0,0 +1,26 @@ +// ignore-tidy-cr + +/// doc comment with bare CR: ' ' +pub fn foo() {} +//~^^ ERROR: bare CR not allowed in doc-comment + +/** block doc comment with bare CR: ' ' */ +pub fn bar() {} +//~^^ ERROR: bare CR not allowed in block doc-comment + +fn main() { + //! doc comment with bare CR: ' ' + //~^ ERROR: bare CR not allowed in doc-comment + + /*! block doc comment with bare CR: ' ' */ + //~^ ERROR: bare CR not allowed in block doc-comment + + // the following string literal has a bare CR in it + let _s = "foo bar"; //~ ERROR: bare CR not allowed in string + + // the following string literal has a bare CR in it + let _s = r"bar foo"; //~ ERROR: bare CR not allowed in raw string + + // the following string literal has a bare CR in it + let _s = "foo\ bar"; //~ ERROR: unknown character escape: `\r` +} diff --git a/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr new file mode 100644 index 000000000..1a21fed63 --- /dev/null +++ b/tests/ui/lexer/lex-bare-cr-string-literal-doc-comment.stderr @@ -0,0 +1,46 @@ +error: bare CR not allowed in doc-comment + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:3:32 + | +LL | /// doc comment with bare CR: ' ' + | ^ + +error: bare CR not allowed in block doc-comment + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:7:38 + | +LL | /** block doc comment with bare CR: ' ' */ + | ^ + +error: bare CR not allowed in doc-comment + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:12:36 + | +LL | //! doc comment with bare CR: ' ' + | ^ + +error: bare CR not allowed in block doc-comment + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:15:42 + | +LL | /*! block doc comment with bare CR: ' ' */ + | ^ + +error: bare CR not allowed in string, use `\r` instead + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:19:18 + | +LL | let _s = "foo bar"; + | ^ help: escape the character: `\r` + +error: bare CR not allowed in raw string + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:22:19 + | +LL | let _s = r"bar foo"; + | ^ + +error: unknown character escape: `\r` + --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:25:19 + | +LL | let _s = "foo\ bar"; + | ^ unknown character escape + | + = help: this is an isolated carriage return; consider checking your editor and version control settings + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lexer/lex-emoji-identifiers.rs b/tests/ui/lexer/lex-emoji-identifiers.rs new file mode 100644 index 000000000..91b5929c0 --- /dev/null +++ b/tests/ui/lexer/lex-emoji-identifiers.rs @@ -0,0 +1,17 @@ +fn invalid_emoji_usages() { + let arrowâ†”ï¸ = "basic emoji"; //~ ERROR: identifiers cannot contain emoji + // FIXME + let planet🪠= "basic emoji"; //~ ERROR: unknown start of token + // FIXME + let wireless🛜 = "basic emoji"; //~ ERROR: unknown start of token + // FIXME + let key1ï¸âƒ£ = "keycap sequence"; //~ ERROR: unknown start of token + //~^ WARN: identifier contains uncommon Unicode codepoints + let flag🇺🇳 = "flag sequence"; //~ ERROR: identifiers cannot contain emoji + let wales🴠= "tag sequence"; //~ ERROR: identifiers cannot contain emoji + let foldedðŸ™ðŸ¿ = "modifier sequence"; //~ ERROR: identifiers cannot contain emoji +} + +fn main() { + invalid_emoji_usages(); +} diff --git a/tests/ui/lexer/lex-emoji-identifiers.stderr b/tests/ui/lexer/lex-emoji-identifiers.stderr new file mode 100644 index 000000000..6237c5d02 --- /dev/null +++ b/tests/ui/lexer/lex-emoji-identifiers.stderr @@ -0,0 +1,52 @@ +error: unknown start of token: \u{1fa90} + --> $DIR/lex-emoji-identifiers.rs:4:15 + | +LL | let planet🪠= "basic emoji"; + | ^^ + +error: unknown start of token: \u{1f6dc} + --> $DIR/lex-emoji-identifiers.rs:6:17 + | +LL | let wireless🛜 = "basic emoji"; + | ^^ + +error: unknown start of token: \u{20e3} + --> $DIR/lex-emoji-identifiers.rs:8:14 + | +LL | let key1ï¸âƒ£ = "keycap sequence"; + | ^ + +error: identifiers cannot contain emoji: `arrow↔ï¸` + --> $DIR/lex-emoji-identifiers.rs:2:9 + | +LL | let arrowâ†”ï¸ = "basic emoji"; + | ^^^^^^ + +error: identifiers cannot contain emoji: `flag🇺🇳` + --> $DIR/lex-emoji-identifiers.rs:10:9 + | +LL | let flag🇺🇳 = "flag sequence"; + | ^^^^^^ + +error: identifiers cannot contain emoji: `walesðŸ´` + --> $DIR/lex-emoji-identifiers.rs:11:9 + | +LL | let wales🴠= "tag sequence"; + | ^^^^^^^ + +error: identifiers cannot contain emoji: `foldedðŸ™ðŸ¿` + --> $DIR/lex-emoji-identifiers.rs:12:9 + | +LL | let foldedðŸ™ðŸ¿ = "modifier sequence"; + | ^^^^^^^^^^ + +warning: identifier contains uncommon Unicode codepoints + --> $DIR/lex-emoji-identifiers.rs:8:9 + | +LL | let key1ï¸âƒ£ = "keycap sequence"; + | ^^^^ + | + = note: `#[warn(uncommon_codepoints)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted + diff --git a/tests/ui/lexer/lex-stray-backslash.rs b/tests/ui/lexer/lex-stray-backslash.rs new file mode 100644 index 000000000..bb27f44c2 --- /dev/null +++ b/tests/ui/lexer/lex-stray-backslash.rs @@ -0,0 +1,3 @@ +\ //~ ERROR: unknown start of token: \ + +fn main() {} diff --git a/tests/ui/lexer/lex-stray-backslash.stderr b/tests/ui/lexer/lex-stray-backslash.stderr new file mode 100644 index 000000000..06dc0f2b5 --- /dev/null +++ b/tests/ui/lexer/lex-stray-backslash.stderr @@ -0,0 +1,8 @@ +error: unknown start of token: \ + --> $DIR/lex-stray-backslash.rs:1:1 + | +LL | \ + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs b/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs new file mode 100644 index 000000000..802be7f5a --- /dev/null +++ b/tests/ui/lexer/lexer-crlf-line-endings-string-literal-doc-comment.rs @@ -0,0 +1,38 @@ +// run-pass +// ignore-tidy-cr +// ignore-tidy-cr (repeated again because of tidy bug) +// license is ignored because tidy can't handle the CRLF here properly. + +// N.B., this file needs CRLF line endings. The .gitattributes file in +// this directory should enforce it. + +// ignore-pretty issue #37195 + +/// Doc comment that ends in CRLF +pub fn foo() {} + +/** Block doc comment that + * contains CRLF characters + */ +pub fn bar() {} + +fn main() { + let s = "string +literal"; + assert_eq!(s, "string\nliteral"); + + let s = "literal with \ + escaped newline"; + assert_eq!(s, "literal with escaped newline"); + + let s = r"string +literal"; + assert_eq!(s, "string\nliteral"); + let s = br"byte string +literal"; + assert_eq!(s, "byte string\nliteral".as_bytes()); + + // validate that our source file has CRLF endings + let source = include_str!("lexer-crlf-line-endings-string-literal-doc-comment.rs"); + assert!(source.contains("string\r\nliteral")); +} diff --git a/tests/ui/lexical-scopes.rs b/tests/ui/lexical-scopes.rs new file mode 100644 index 000000000..46cfdf1ef --- /dev/null +++ b/tests/ui/lexical-scopes.rs @@ -0,0 +1,13 @@ +struct T { i: i32 } +fn f() { + let t = T { i: 0 }; //~ ERROR expected struct, variant or union type, found type parameter `T` +} + +mod Foo { + pub fn f() {} +} +fn g() { + Foo::f(); //~ ERROR no function or associated item named `f` +} + +fn main() {} diff --git a/tests/ui/lexical-scopes.stderr b/tests/ui/lexical-scopes.stderr new file mode 100644 index 000000000..f0eaa1a5c --- /dev/null +++ b/tests/ui/lexical-scopes.stderr @@ -0,0 +1,22 @@ +error[E0574]: expected struct, variant or union type, found type parameter `T` + --> $DIR/lexical-scopes.rs:3:13 + | +LL | struct T { i: i32 } + | - you might have meant to refer to this struct +LL | fn f() { + | - found this type parameter +LL | let t = T { i: 0 }; + | ^ not a struct, variant or union type + +error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope + --> $DIR/lexical-scopes.rs:10:10 + | +LL | fn g() { + | --- function or associated item `f` not found for this type parameter +LL | Foo::f(); + | ^ function or associated item not found in `Foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0574, E0599. +For more information about an error, try `rustc --explain E0574`. diff --git a/tests/ui/lexical-scoping.rs b/tests/ui/lexical-scoping.rs new file mode 100644 index 000000000..04904958a --- /dev/null +++ b/tests/ui/lexical-scoping.rs @@ -0,0 +1,19 @@ +// run-pass +// Tests that items in subscopes can shadow type parameters and local variables (see issue #23880). + +#![allow(unused)] +struct Foo { x: Box } +impl Foo { + fn foo(&self) { + type Bar = i32; + let _: Bar = 42; + } +} + +fn main() { + let f = 1; + { + fn f() {} + f(); + } +} diff --git a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs new file mode 100644 index 000000000..0335f72b7 --- /dev/null +++ b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs @@ -0,0 +1,47 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +//#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; + +#[proc_macro_attribute] +pub fn repro(_args: TokenStream, input: TokenStream) -> TokenStream { + let call_site = Span::call_site(); + let span = input.into_iter().nth(8).unwrap().span(); + + //fn f(_: &::std::fmt::Formatter) {} + TokenStream::from_iter([ + TokenTree::Ident(Ident::new("fn", call_site)), + TokenTree::Ident(Ident::new("f", call_site)), + TokenTree::Group(Group::new( + Delimiter::Parenthesis, + TokenStream::from_iter([ + TokenTree::Ident(Ident::new("_", call_site)), + TokenTree::Punct(punct(':', Spacing::Alone, call_site)), + TokenTree::Punct(punct('&', Spacing::Alone, call_site)), + TokenTree::Punct(punct(':', Spacing::Joint, span)), + TokenTree::Punct(punct(':', Spacing::Alone, span)), + TokenTree::Ident(Ident::new("std", span)), + TokenTree::Punct(punct(':', Spacing::Joint, span)), + TokenTree::Punct(punct(':', Spacing::Alone, span)), + TokenTree::Ident(Ident::new("fmt", span)), + TokenTree::Punct(punct(':', Spacing::Joint, span)), + TokenTree::Punct(punct(':', Spacing::Alone, span)), + TokenTree::Ident(Ident::new("Formatter", span)), + ]), + )), + TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), + ]) +} + +fn punct(ch: char, spacing: Spacing, span: Span) -> Punct { + let mut punct = Punct::new(ch, spacing); + punct.set_span(span); + punct +} diff --git a/tests/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs b/tests/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs new file mode 100644 index 000000000..58f1b81cf --- /dev/null +++ b/tests/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs @@ -0,0 +1,11 @@ +#![crate_type = "rlib"] + +// Helper for testing that we get suitable warnings when lifetime +// bound change will cause breakage. + +pub fn just_ref(x: &Fn()) { +} + +pub fn ref_obj(x: &Box) { + // this will change to &Box... +} diff --git a/tests/ui/lifetimes/bare-trait-object-borrowck.rs b/tests/ui/lifetimes/bare-trait-object-borrowck.rs new file mode 100644 index 000000000..45f5e4ae1 --- /dev/null +++ b/tests/ui/lifetimes/bare-trait-object-borrowck.rs @@ -0,0 +1,24 @@ +#![allow(bare_trait_objects)] +// check-pass +pub struct FormatWith<'a, I, F> { + sep: &'a str, + /// FormatWith uses interior mutability because Display::fmt takes &self. + inner: RefCell>, +} + +use std::cell::RefCell; +use std::fmt; + +struct Layout; + +pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F> +where + I: Iterator, + F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result, +{ + FormatWith { sep: separator, inner: RefCell::new(Some((iter, f))) } +} + +fn main() { + let _ = new_format(0..32, " | ", |i, f| f(&format_args!("0x{:x}", i))); +} diff --git a/tests/ui/lifetimes/bare-trait-object.rs b/tests/ui/lifetimes/bare-trait-object.rs new file mode 100644 index 000000000..9eff618c7 --- /dev/null +++ b/tests/ui/lifetimes/bare-trait-object.rs @@ -0,0 +1,25 @@ +// Verify that lifetime resolution correctly accounts for `Fn` bare trait objects. +// check-pass +#![allow(bare_trait_objects)] + +// This should work as: fn next_u32(fill_buf: &mut dyn FnMut(&mut [u8])) +fn next_u32(fill_buf: &mut FnMut(&mut [u8])) { + let mut buf: [u8; 4] = [0; 4]; + fill_buf(&mut buf); +} + +fn explicit(fill_buf: &mut dyn FnMut(&mut [u8])) { + let mut buf: [u8; 4] = [0; 4]; + fill_buf(&mut buf); +} + +fn main() { + let _: fn(&mut FnMut(&mut [u8])) = next_u32; + let _: &dyn Fn(&mut FnMut(&mut [u8])) = &next_u32; + let _: fn(&mut FnMut(&mut [u8])) = explicit; + let _: &dyn Fn(&mut FnMut(&mut [u8])) = &explicit; + let _: fn(&mut dyn FnMut(&mut [u8])) = next_u32; + let _: &dyn Fn(&mut dyn FnMut(&mut [u8])) = &next_u32; + let _: fn(&mut dyn FnMut(&mut [u8])) = explicit; + let _: &dyn Fn(&mut dyn FnMut(&mut [u8])) = &explicit; +} diff --git a/tests/ui/lifetimes/borrowck-let-suggestion.rs b/tests/ui/lifetimes/borrowck-let-suggestion.rs new file mode 100644 index 000000000..3d591a506 --- /dev/null +++ b/tests/ui/lifetimes/borrowck-let-suggestion.rs @@ -0,0 +1,12 @@ +fn f() { + let mut x = vec![1].iter(); + //~^ ERROR temporary value dropped while borrowed + x.use_mut(); +} + +fn main() { + f(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/lifetimes/borrowck-let-suggestion.stderr b/tests/ui/lifetimes/borrowck-let-suggestion.stderr new file mode 100644 index 000000000..987b051b1 --- /dev/null +++ b/tests/ui/lifetimes/borrowck-let-suggestion.stderr @@ -0,0 +1,17 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion.rs:2:17 + | +LL | let mut x = vec![1].iter(); + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | +LL | x.use_mut(); + | ----------- borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/lifetimes/conflicting-bounds.rs b/tests/ui/lifetimes/conflicting-bounds.rs new file mode 100644 index 000000000..f37f163db --- /dev/null +++ b/tests/ui/lifetimes/conflicting-bounds.rs @@ -0,0 +1,11 @@ +//~ type annotations needed: cannot satisfy `Self: Gen<'source>` + +pub trait Gen<'source> { + type Output; + + fn gen(&self) -> T + where + Self: for<'s> Gen<'s, Output = T>; +} + +fn main() {} diff --git a/tests/ui/lifetimes/conflicting-bounds.stderr b/tests/ui/lifetimes/conflicting-bounds.stderr new file mode 100644 index 000000000..42aa39366 --- /dev/null +++ b/tests/ui/lifetimes/conflicting-bounds.stderr @@ -0,0 +1,14 @@ +error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>` + | +note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found + --> $DIR/conflicting-bounds.rs:3:1 + | +LL | pub trait Gen<'source> { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | Self: for<'s> Gen<'s, Output = T>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/lifetimes/copy_modulo_regions.rs b/tests/ui/lifetimes/copy_modulo_regions.rs new file mode 100644 index 000000000..040fc4a00 --- /dev/null +++ b/tests/ui/lifetimes/copy_modulo_regions.rs @@ -0,0 +1,17 @@ +#[derive(Clone)] +struct Foo<'a>(fn(&'a ()) -> &'a ()); + +impl Copy for Foo<'static> {} + +fn mk_foo<'a>() -> Foo<'a> { + println!("mk_foo"); + Foo(|x| x) +} + +fn foo<'a>() -> [Foo<'a>; 100] { + [mk_foo::<'a>(); 100] //~ ERROR lifetime may not live long enough +} + +fn main() { + foo(); +} diff --git a/tests/ui/lifetimes/copy_modulo_regions.stderr b/tests/ui/lifetimes/copy_modulo_regions.stderr new file mode 100644 index 000000000..87dbb64ab --- /dev/null +++ b/tests/ui/lifetimes/copy_modulo_regions.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/copy_modulo_regions.rs:12:5 + | +LL | fn foo<'a>() -> [Foo<'a>; 100] { + | -- lifetime `'a` defined here +LL | [mk_foo::<'a>(); 100] + | ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/elided-lifetime-in-param-pat.rs b/tests/ui/lifetimes/elided-lifetime-in-param-pat.rs new file mode 100644 index 000000000..c1425fa42 --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-param-pat.rs @@ -0,0 +1,11 @@ +// check-pass + +struct S { + _t: T, +} + +fn f(S::<&i8> { .. }: S<&i8>) {} + +fn main() { + f(S { _t: &42_i8 }); +} diff --git a/tests/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs b/tests/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs new file mode 100644 index 000000000..9c9965d8f --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs @@ -0,0 +1,19 @@ +// check-pass + +struct Foo<'a>(&'a ()); + +fn with_fn() -> fn(Foo) { + |_| () +} + +fn with_impl_fn() -> impl Fn(Foo) { + |_| () +} + +fn with_where_fn() +where + T: Fn(Foo), +{ +} + +fn main() {} diff --git a/tests/ui/lifetimes/elided-lifetime-in-path-in-pat.rs b/tests/ui/lifetimes/elided-lifetime-in-path-in-pat.rs new file mode 100644 index 000000000..ff84d2511 --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-path-in-pat.rs @@ -0,0 +1,13 @@ +// check-pass + +struct Foo<'a> { + x: &'a (), +} + +// The lifetime in pattern-position `Foo` is elided. +// Verify that lowering does not create an independent lifetime parameter for it. +fn foo<'a>(Foo { x }: Foo<'a>) { + *x +} + +fn main() {} diff --git a/tests/ui/lifetimes/elided-lifetime-in-path-in-type-relative-expression.rs b/tests/ui/lifetimes/elided-lifetime-in-path-in-type-relative-expression.rs new file mode 100644 index 000000000..b9d2711fd --- /dev/null +++ b/tests/ui/lifetimes/elided-lifetime-in-path-in-type-relative-expression.rs @@ -0,0 +1,17 @@ +// check-pass + +struct Sqlite {} + +trait HasArguments<'q> { + type Arguments; +} + +impl<'q> HasArguments<'q> for Sqlite { + type Arguments = std::marker::PhantomData<&'q ()>; +} + +fn foo() { + let _ = ::Arguments::default(); +} + +fn main() {} diff --git a/tests/ui/lifetimes/fullwidth-ampersand.rs b/tests/ui/lifetimes/fullwidth-ampersand.rs new file mode 100644 index 000000000..7d8948bd8 --- /dev/null +++ b/tests/ui/lifetimes/fullwidth-ampersand.rs @@ -0,0 +1,7 @@ +// Verify that we do not ICE when the user uses a multubyte ampersand. + +fn f(_: &&()) -> &() { todo!() } +//~^ ERROR unknown start of token: \u{ff06} +//~| ERROR missing lifetime specifier [E0106] + +fn main() {} diff --git a/tests/ui/lifetimes/fullwidth-ampersand.stderr b/tests/ui/lifetimes/fullwidth-ampersand.stderr new file mode 100644 index 000000000..4645254f4 --- /dev/null +++ b/tests/ui/lifetimes/fullwidth-ampersand.stderr @@ -0,0 +1,26 @@ +error: unknown start of token: \u{ff06} + --> $DIR/fullwidth-ampersand.rs:3:10 + | +LL | fn f(_: &&()) -> &() { todo!() } + | ^^ + | +help: Unicode character '&' (Fullwidth Ampersand) looks like '&' (Ampersand), but it is not + | +LL | fn f(_: &&()) -> &() { todo!() } + | ~ + +error[E0106]: missing lifetime specifier + --> $DIR/fullwidth-ampersand.rs:3:18 + | +LL | fn f(_: &&()) -> &() { todo!() } + | ----- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(_: &'a &'a ()) -> &'a () { todo!() } + | ++++ ++ ++ ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/issue-105227.fixed b/tests/ui/lifetimes/issue-105227.fixed new file mode 100644 index 000000000..f6ed9c82e --- /dev/null +++ b/tests/ui/lifetimes/issue-105227.fixed @@ -0,0 +1,26 @@ +// Regression test for issue #105227. + +// run-rustfix +#![allow(warnings)] +fn chars0<'a>(v :(&'a str, &'a str)) -> impl Iterator + 'a { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v.0.chars().chain(v.1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bounds +} + +fn chars1<'a>(v0 : &'a str, v1 : &'a str) -> impl Iterator + 'a { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v0.chars().chain(v1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) -> +//~^ HELP to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` + (impl Iterator + 'b , &'b str) +{ + (v0.chars().chain(v1.chars()), v2) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn main() { +} diff --git a/tests/ui/lifetimes/issue-105227.rs b/tests/ui/lifetimes/issue-105227.rs new file mode 100644 index 000000000..6427a50bb --- /dev/null +++ b/tests/ui/lifetimes/issue-105227.rs @@ -0,0 +1,26 @@ +// Regression test for issue #105227. + +// run-rustfix +#![allow(warnings)] +fn chars0(v :(& str, &str)) -> impl Iterator { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v.0.chars().chain(v.1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bounds +} + +fn chars1(v0 : & str, v1 : &str) -> impl Iterator { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v0.chars().chain(v1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> +//~^ HELP to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` + (impl Iterator, &'b str) +{ + (v0.chars().chain(v1.chars()), v2) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn main() { +} diff --git a/tests/ui/lifetimes/issue-105227.stderr b/tests/ui/lifetimes/issue-105227.stderr new file mode 100644 index 000000000..d21145937 --- /dev/null +++ b/tests/ui/lifetimes/issue-105227.stderr @@ -0,0 +1,47 @@ +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-105227.rs:7:5 + | +LL | fn chars0(v :(& str, &str)) -> impl Iterator { + | ----- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +LL | +LL | v.0.chars().chain(v.1.chars()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + | +LL | fn chars0<'a>(v :(&'a str, &'a str)) -> impl Iterator + 'a { + | ++++ ++ ++ ++++ + +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-105227.rs:13:5 + | +LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator { + | ----- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +LL | +LL | v0.chars().chain(v1.chars()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + | +LL | fn chars1<'a>(v0 : &'a str, v1 : &'a str) -> impl Iterator + 'a { + | ++++ ++ ++ ++++ + +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-105227.rs:21:5 + | +LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> + | ---- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +... +LL | (v0.chars().chain(v1.chars()), v2) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` + | +LL ~ fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) -> +LL | +LL ~ (impl Iterator + 'b , &'b str) + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/lifetimes/issue-105507.fixed b/tests/ui/lifetimes/issue-105507.fixed new file mode 100644 index 000000000..277ce8a77 --- /dev/null +++ b/tests/ui/lifetimes/issue-105507.fixed @@ -0,0 +1,43 @@ +// run-rustfix +// +#![allow(warnings)] +struct Wrapper<'a, T: ?Sized>(&'a T); + +trait Project { + type Projected<'a> where Self: 'a; + fn project(this: Wrapper<'_, Self>) -> Self::Projected<'_>; +} +trait MyTrait {} +trait ProjectedMyTrait {} + +impl Project for Option { + type Projected<'a> = Option> where T: 'a; + fn project(this: Wrapper<'_, Self>) -> Self::Projected<'_> { + this.0.as_ref().map(Wrapper) + } +} + +impl MyTrait for Option> {} + +impl MyTrait for Wrapper<'_, T> {} + +impl ProjectedMyTrait for T + where + T: Project, + for<'a> T::Projected<'a>: MyTrait, + //~^ NOTE due to current limitations in the borrow checker, this implies a `'static` lifetime + //~| NOTE due to current limitations in the borrow checker, this implies a `'static` lifetime +{} + +fn require_trait(_: T) {} + +fn foo(wrap: Wrapper<'_, Option>, wrap1: Wrapper<'_, Option>) { + //~^ HELP consider restricting the type parameter to the `'static` lifetime + //~| HELP consider restricting the type parameter to the `'static` lifetime + require_trait(wrap); + //~^ ERROR `T` does not live long enough + require_trait(wrap1); + //~^ ERROR `U` does not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-105507.rs b/tests/ui/lifetimes/issue-105507.rs new file mode 100644 index 000000000..f46c6b6f2 --- /dev/null +++ b/tests/ui/lifetimes/issue-105507.rs @@ -0,0 +1,43 @@ +// run-rustfix +// +#![allow(warnings)] +struct Wrapper<'a, T: ?Sized>(&'a T); + +trait Project { + type Projected<'a> where Self: 'a; + fn project(this: Wrapper<'_, Self>) -> Self::Projected<'_>; +} +trait MyTrait {} +trait ProjectedMyTrait {} + +impl Project for Option { + type Projected<'a> = Option> where T: 'a; + fn project(this: Wrapper<'_, Self>) -> Self::Projected<'_> { + this.0.as_ref().map(Wrapper) + } +} + +impl MyTrait for Option> {} + +impl MyTrait for Wrapper<'_, T> {} + +impl ProjectedMyTrait for T + where + T: Project, + for<'a> T::Projected<'a>: MyTrait, + //~^ NOTE due to current limitations in the borrow checker, this implies a `'static` lifetime + //~| NOTE due to current limitations in the borrow checker, this implies a `'static` lifetime +{} + +fn require_trait(_: T) {} + +fn foo(wrap: Wrapper<'_, Option>, wrap1: Wrapper<'_, Option>) { + //~^ HELP consider restricting the type parameter to the `'static` lifetime + //~| HELP consider restricting the type parameter to the `'static` lifetime + require_trait(wrap); + //~^ ERROR `T` does not live long enough + require_trait(wrap1); + //~^ ERROR `U` does not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-105507.stderr b/tests/ui/lifetimes/issue-105507.stderr new file mode 100644 index 000000000..44d3a7eb9 --- /dev/null +++ b/tests/ui/lifetimes/issue-105507.stderr @@ -0,0 +1,34 @@ +error: `T` does not live long enough + --> $DIR/issue-105507.rs:37:5 + | +LL | require_trait(wrap); + | ^^^^^^^^^^^^^^^^^^^ + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/issue-105507.rs:27:35 + | +LL | for<'a> T::Projected<'a>: MyTrait, + | ^^^^^^^ +help: consider restricting the type parameter to the `'static` lifetime + | +LL | fn foo(wrap: Wrapper<'_, Option>, wrap1: Wrapper<'_, Option>) { + | +++++++++ +++++++++ + +error: `U` does not live long enough + --> $DIR/issue-105507.rs:39:5 + | +LL | require_trait(wrap1); + | ^^^^^^^^^^^^^^^^^^^^ + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/issue-105507.rs:27:35 + | +LL | for<'a> T::Projected<'a>: MyTrait, + | ^^^^^^^ +help: consider restricting the type parameter to the `'static` lifetime + | +LL | fn foo(wrap: Wrapper<'_, Option>, wrap1: Wrapper<'_, Option>) { + | +++++++++ +++++++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lifetimes/issue-17728.rs b/tests/ui/lifetimes/issue-17728.rs new file mode 100644 index 000000000..6aca159c4 --- /dev/null +++ b/tests/ui/lifetimes/issue-17728.rs @@ -0,0 +1,122 @@ +use std::fmt::{Debug, Formatter, Error}; +use std::collections::HashMap; + +trait HasInventory { + fn getInventory<'s>(&'s self) -> &'s mut Inventory; + fn addToInventory(&self, item: &Item); + fn removeFromInventory(&self, itemName: &str) -> bool; +} + +trait TraversesWorld { + fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { + let direction = str_to_direction(directionStr); + let maybe_room = room.direction_to_room.get(&direction); + match maybe_room { + Some(entry) => Ok(entry), + _ => Err("Direction does not exist in room.") + } + } +} + + +#[derive(Debug, Eq, PartialEq, Hash)] +enum RoomDirection { + West, + East, + North, + South, + Up, + Down, + In, + Out, + + None +} + +struct Room { + description: String, + items: Vec, + direction_to_room: HashMap, +} + +impl Room { + fn new(description: &'static str) -> Room { + Room { + description: description.to_string(), + items: Vec::new(), + direction_to_room: HashMap::new() + } + } + + fn add_direction(&mut self, direction: RoomDirection, room: Room) { + self.direction_to_room.insert(direction, room); + } +} + +struct Item { + name: String, +} + +struct Inventory { + items: Vec, +} + +impl Inventory { + fn new() -> Inventory { + Inventory { + items: Vec::new() + } + } +} + +struct Player { + name: String, + inventory: Inventory, +} + +impl Player { + fn new(name: &'static str) -> Player { + Player { + name: name.to_string(), + inventory: Inventory::new() + } + } +} + +impl TraversesWorld for Player { +} + +impl Debug for Player { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> { + formatter.write_str("Player{ name:"); + formatter.write_str(&self.name); + formatter.write_str(" }"); + Ok(()) + } +} + +fn str_to_direction(to_parse: &str) -> RoomDirection { + match to_parse { + "w" | "west" => RoomDirection::West, + "e" | "east" => RoomDirection::East, + "n" | "north" => RoomDirection::North, + "s" | "south" => RoomDirection::South, + "in" => RoomDirection::In, + "out" => RoomDirection::Out, + "up" => RoomDirection::Up, + "down" => RoomDirection::Down, + _ => None + } + //~^^ ERROR `match` arms have incompatible types +} + +fn main() { + let mut player = Player::new("Test player"); + let mut room = Room::new("A test room"); + println!("Made a player: {:?}", player); + println!("Direction parse: {:?}", str_to_direction("east")); + match player.attemptTraverse(&room, "west") { + Ok(_) => println!("Was able to move west"), + Err(msg) => println!("Not able to move west: {}", msg) + }; +} diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr new file mode 100644 index 000000000..3b25902d7 --- /dev/null +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -0,0 +1,21 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-17728.rs:108:14 + | +LL | / match to_parse { +LL | | "w" | "west" => RoomDirection::West, +LL | | "e" | "east" => RoomDirection::East, +LL | | "n" | "north" => RoomDirection::North, +... | +LL | | "down" => RoomDirection::Down, + | | ------------------- this and all prior arms are found to be of type `RoomDirection` +LL | | _ => None + | | ^^^^ expected enum `RoomDirection`, found enum `Option` +LL | | } + | |_____- `match` arms have incompatible types + | + = note: expected enum `RoomDirection` + found enum `Option<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/issue-26638.rs b/tests/ui/lifetimes/issue-26638.rs new file mode 100644 index 000000000..4bec3b341 --- /dev/null +++ b/tests/ui/lifetimes/issue-26638.rs @@ -0,0 +1,13 @@ +fn parse_type(iter: Box+'static>) -> &str { iter.next() } +//~^ ERROR missing lifetime specifier [E0106] +//~| ERROR mismatched types + +fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } +//~^ ERROR missing lifetime specifier [E0106] +//~| ERROR mismatched types +//~| ERROR function takes 1 argument but 0 arguments were supplied + +fn parse_type_3() -> &str { unimplemented!() } +//~^ ERROR missing lifetime specifier [E0106] + +fn main() {} diff --git a/tests/ui/lifetimes/issue-26638.stderr b/tests/ui/lifetimes/issue-26638.stderr new file mode 100644 index 000000000..98d39d614 --- /dev/null +++ b/tests/ui/lifetimes/issue-26638.stderr @@ -0,0 +1,73 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-26638.rs:1:62 + | +LL | fn parse_type(iter: Box+'static>) -> &str { iter.next() } + | ------------------------------------ ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn parse_type<'a>(iter: Box+'static>) -> &'a str { iter.next() } + | ++++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-26638.rs:5:40 + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() } + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-26638.rs:10:22 + | +LL | fn parse_type_3() -> &str { unimplemented!() } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn parse_type_3() -> &'static str { unimplemented!() } + | +++++++ + +error[E0308]: mismatched types + --> $DIR/issue-26638.rs:1:69 + | +LL | fn parse_type(iter: Box+'static>) -> &str { iter.next() } + | ---- ^^^^^^^^^^^ expected `&str`, found enum `Option` + | | + | expected `&'static str` because of return type + | + = note: expected reference `&'static str` + found enum `Option<&str>` + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/issue-26638.rs:5:47 + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } + | ^^^^-- an argument of type `&u8` is missing + | +help: provide the argument + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter(/* &u8 */) } + | ~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/issue-26638.rs:5:47 + | +LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } + | ---- ^^^^^^ expected `str`, found `u8` + | | + | expected `&'static str` because of return type + | + = note: expected reference `&'static str` + found reference `&u8` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0106, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/lifetimes/issue-34979.rs b/tests/ui/lifetimes/issue-34979.rs new file mode 100644 index 000000000..252486dd9 --- /dev/null +++ b/tests/ui/lifetimes/issue-34979.rs @@ -0,0 +1,9 @@ +trait Foo {} +impl<'a, T> Foo for &'a T {} + +struct Ctx<'a>(&'a ()) +where + &'a (): Foo, //~ ERROR: type annotations needed + &'static (): Foo; + +fn main() {} diff --git a/tests/ui/lifetimes/issue-34979.stderr b/tests/ui/lifetimes/issue-34979.stderr new file mode 100644 index 000000000..3d4208031 --- /dev/null +++ b/tests/ui/lifetimes/issue-34979.stderr @@ -0,0 +1,20 @@ +error[E0283]: type annotations needed: cannot satisfy `&'a (): Foo` + --> $DIR/issue-34979.rs:6:13 + | +LL | &'a (): Foo, + | ^^^ + | +note: multiple `impl`s or `where` clauses satisfying `&'a (): Foo` found + --> $DIR/issue-34979.rs:2:1 + | +LL | impl<'a, T> Foo for &'a T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | &'a (): Foo, + | ^^^ +LL | &'static (): Foo; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/lifetimes/issue-54378.rs b/tests/ui/lifetimes/issue-54378.rs new file mode 100644 index 000000000..aa42d4a7c --- /dev/null +++ b/tests/ui/lifetimes/issue-54378.rs @@ -0,0 +1,26 @@ +// check-pass + +// Regression test for #54378. + +#![feature(never_type)] + +use std::marker::PhantomData; + +pub trait Machine<'a, 'mir, 'tcx>: Sized { + type MemoryKinds: ::std::fmt::Debug + Copy + Eq; + const MUT_STATIC_KIND: Option; +} + +pub struct CompileTimeEvaluator<'a, 'mir, 'tcx: 'a+'mir> { + pub _data: PhantomData<(&'a (), &'mir (), &'tcx ())>, +} + +impl<'a, 'mir, 'tcx: 'a + 'mir> Machine<'a, 'mir, 'tcx> + for CompileTimeEvaluator<'a, 'mir, 'tcx> +{ + type MemoryKinds = !; + + const MUT_STATIC_KIND: Option = None; +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-55796.rs b/tests/ui/lifetimes/issue-55796.rs new file mode 100644 index 000000000..a7b27a999 --- /dev/null +++ b/tests/ui/lifetimes/issue-55796.rs @@ -0,0 +1,26 @@ +pub trait EdgeTrait { + fn target(&self) -> N; +} + +pub trait Graph<'a> { + type Node; + type Edge: EdgeTrait; + type NodesIter: Iterator + 'a; + type EdgesIter: Iterator + 'a; + + fn nodes(&'a self) -> Self::NodesIter; + fn out_edges(&'a self, u: &Self::Node) -> Self::EdgesIter; + fn in_edges(&'a self, u: &Self::Node) -> Self::EdgesIter; + + fn out_neighbors(&'a self, u: &Self::Node) -> Box> { + Box::new(self.out_edges(u).map(|e| e.target())) + //~^ ERROR lifetime may not live long enough + } + + fn in_neighbors(&'a self, u: &Self::Node) -> Box> { + Box::new(self.in_edges(u).map(|e| e.target())) + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-55796.stderr b/tests/ui/lifetimes/issue-55796.stderr new file mode 100644 index 000000000..5809a56cd --- /dev/null +++ b/tests/ui/lifetimes/issue-55796.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/issue-55796.rs:16:9 + | +LL | pub trait Graph<'a> { + | -- lifetime `'a` defined here +... +LL | Box::new(self.out_edges(u).map(|e| e.target())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-55796.rs:21:9 + | +LL | pub trait Graph<'a> { + | -- lifetime `'a` defined here +... +LL | Box::new(self.in_edges(u).map(|e| e.target())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.rs b/tests/ui/lifetimes/issue-64173-unused-lifetimes.rs new file mode 100644 index 000000000..8080dd7dc --- /dev/null +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.rs @@ -0,0 +1,19 @@ +use std::mem::size_of; + +struct Foo<'s> { //~ ERROR: parameter `'s` is never used + array: [(); size_of::<&Self>()], + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +// The below is taken from https://github.com/rust-lang/rust/issues/66152#issuecomment-550275017 +// as the root cause seems the same. + +const fn foo() -> usize { + 0 +} + +struct Bar<'a> { //~ ERROR: parameter `'a` is never used + beta: [(); foo::<&'a ()>()], //~ ERROR: a non-static lifetime is not allowed in a `const` +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr new file mode 100644 index 000000000..a487cbea5 --- /dev/null +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr @@ -0,0 +1,35 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-64173-unused-lifetimes.rs:16:23 + | +LL | beta: [(); foo::<&'a ()>()], + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-64173-unused-lifetimes.rs:4:28 + | +LL | array: [(); size_of::<&Self>()], + | ^^^^ + +error[E0392]: parameter `'s` is never used + --> $DIR/issue-64173-unused-lifetimes.rs:3:12 + | +LL | struct Foo<'s> { + | ^^ unused parameter + | + = help: consider removing `'s`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `'a` is never used + --> $DIR/issue-64173-unused-lifetimes.rs:15:12 + | +LL | struct Bar<'a> { + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0392, E0658. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/lifetimes/issue-67498.rs b/tests/ui/lifetimes/issue-67498.rs new file mode 100644 index 000000000..8d8826435 --- /dev/null +++ b/tests/ui/lifetimes/issue-67498.rs @@ -0,0 +1,21 @@ +// check-pass + +// Regression test for #67498. + +pub fn f<'a, 'b, 'd, 'e> ( + x: for<'c> fn( + fn(&'c fn(&'c ())), + fn(&'c fn(&'c ())), + fn(&'c fn(&'c ())), + fn(&'c fn(&'c ())), + ) +) -> fn( + fn(&'a fn(&'d ())), + fn(&'b fn(&'d ())), + fn(&'a fn(&'e ())), + fn(&'b fn(&'e ())), +) { + x +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs b/tests/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs new file mode 100644 index 000000000..b9aab2714 --- /dev/null +++ b/tests/ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs @@ -0,0 +1,13 @@ +// check-pass + +fn assert_static(_: T) {} + +// NOTE(eddyb) the `'a: 'a` may look a bit strange, but we *really* want +// `'a` to be an *early-bound* parameter, otherwise it doesn't matter anyway. +fn capture_lifetime<'a: 'a>() {} + +fn test_lifetime<'a>() { + assert_static(capture_lifetime::<'a>); +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-2.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-2.rs new file mode 100644 index 000000000..348586fa2 --- /dev/null +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-2.rs @@ -0,0 +1,22 @@ +// edition:2018 +// check-pass + +trait Trait { + type Output; +} + +async fn walk(filter: F) +where + for<'a> F: Trait<&'a u32> + 'a, + for<'a> >::Output: 'a, +{ +} + +async fn walk2(filter: F) +where + for<'a> F: Trait<&'a u32> + 'a, + for<'a> >::Output: 'a, +{ +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives.rs b/tests/ui/lifetimes/issue-76168-hr-outlives.rs new file mode 100644 index 000000000..9366e94c9 --- /dev/null +++ b/tests/ui/lifetimes/issue-76168-hr-outlives.rs @@ -0,0 +1,19 @@ +// edition:2018 +// check-pass + +#![feature(unboxed_closures)] +use std::future::Future; + +async fn wrapper(f: F) +where for<'a> F: FnOnce<(&'a mut i32,)>, + for<'a> >::Output: Future + 'a +{ + let mut i = 41; + f(&mut i).await; +} + +async fn add_one(i: &mut i32) { + *i = *i + 1; +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-77175.rs b/tests/ui/lifetimes/issue-77175.rs new file mode 100644 index 000000000..2282752b6 --- /dev/null +++ b/tests/ui/lifetimes/issue-77175.rs @@ -0,0 +1,19 @@ +#[deny(single_use_lifetimes)] +// edition:2018 +// check-pass + +// Prior to the fix, the compiler complained that the 'a lifetime was only used +// once. This was obviously wrong since the lifetime is used twice: For the s3 +// parameter and the return type. The issue was caused by the compiler +// desugaring the async function into a generator that uses only a single +// lifetime, which then the validator complained about becauase of the +// single_use_lifetimes constraints. +async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn foo<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str { + s3 +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-79187-2.rs b/tests/ui/lifetimes/issue-79187-2.rs new file mode 100644 index 000000000..fff92c30b --- /dev/null +++ b/tests/ui/lifetimes/issue-79187-2.rs @@ -0,0 +1,29 @@ +trait Foo {} + +impl Foo for F where F: Fn(&i32) -> &i32 {} + +fn take_foo(_: impl Foo) {} + +fn main() { + take_foo(|a| a); + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR mismatched types + take_foo(|a: &i32| a); + //~^ ERROR lifetime may not live long enough + //~| ERROR mismatched types + take_foo(|a: &i32| -> &i32 { a }); + //~^ ERROR lifetime may not live long enough + //~| ERROR mismatched types + + // OK + take_foo(identity(|a| a)); + take_foo(identity(|a: &i32| a)); + take_foo(identity(|a: &i32| -> &i32 { a })); + + fn identity(t: F) -> F + where + F: Fn(&i32) -> &i32, + { + t + } +} diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr new file mode 100644 index 000000000..c5f654b37 --- /dev/null +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/issue-79187-2.rs:11:24 + | +LL | take_foo(|a: &i32| a); + | - - ^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure is &'2 i32 + | let's call the lifetime of this reference `'1` + +error: lifetime may not live long enough + --> $DIR/issue-79187-2.rs:14:34 + | +LL | take_foo(|a: &i32| -> &i32 { a }); + | - - ^ returning this value requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'2` + | let's call the lifetime of this reference `'1` + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-79187-2.rs:8:5 + | +LL | take_foo(|a| a); + | ^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` + +error[E0308]: mismatched types + --> $DIR/issue-79187-2.rs:8:5 + | +LL | take_foo(|a| a); + | ^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Fn<(&'a i32,)>` + found trait `Fn<(&i32,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-79187-2.rs:8:14 + | +LL | take_foo(|a| a); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/issue-79187-2.rs:11:5 + | +LL | take_foo(|a: &i32| a); + | ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&i32` + found reference `&i32` +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/issue-79187-2.rs:14:5 + | +LL | take_foo(|a: &i32| -> &i32 { a }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&i32` + found reference `&i32` +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/issue-79187.rs b/tests/ui/lifetimes/issue-79187.rs new file mode 100644 index 000000000..8e1304562 --- /dev/null +++ b/tests/ui/lifetimes/issue-79187.rs @@ -0,0 +1,8 @@ +fn thing(x: impl FnOnce(&u32)) {} + +fn main() { + let f = |_| (); + thing(f); + //~^ ERROR mismatched types + //~^^ ERROR implementation of `FnOnce` is not general enough +} diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr new file mode 100644 index 000000000..ee6e7b89d --- /dev/null +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/issue-79187.rs:5:5 + | +LL | thing(f); + | ^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> FnOnce<(&'a u32,)>` + found trait `FnOnce<(&u32,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-79187.rs:4:13 + | +LL | let f = |_| (); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ^^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-79187.rs:5:5 + | +LL | thing(f); + | ^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/issue-83737-binders-across-types.rs b/tests/ui/lifetimes/issue-83737-binders-across-types.rs new file mode 100644 index 000000000..e130561e4 --- /dev/null +++ b/tests/ui/lifetimes/issue-83737-binders-across-types.rs @@ -0,0 +1,14 @@ +// build-pass +// compile-flags: --edition 2018 +// compile-flags: --crate-type rlib + +use std::future::Future; + +async fn handle(slf: &F) +where + F: Fn(&()) -> Box + Unpin>, +{ + (slf)(&()).await; +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs new file mode 100644 index 000000000..c496a3556 --- /dev/null +++ b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs @@ -0,0 +1,14 @@ +// build-pass +// compile-flags: --edition 2018 +// compile-flags: --crate-type rlib + +use std::future::Future; + +async fn handle(slf: &F) +where + F: Fn(&()) -> Box Future + Unpin>, +{ + (slf)(&()).await; +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs new file mode 100644 index 000000000..7f0ea730d --- /dev/null +++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs @@ -0,0 +1,8 @@ +// check-fail + +struct Foo {} +impl Foo { + fn bar(foo: Foo) {} + //~^ associated type bindings are not allowed here +} +fn main() {} diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr new file mode 100644 index 000000000..f7bdee633 --- /dev/null +++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-83753-invalid-associated-type-supertrait-hrtb.rs:5:21 + | +LL | fn bar(foo: Foo) {} + | ^^^^^^^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs b/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs new file mode 100644 index 000000000..604687ce7 --- /dev/null +++ b/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs @@ -0,0 +1,7 @@ +// check-fail + +static STATIC_VAR_FIVE: &One(); +//~^ cannot find type +//~| free static item without body + +fn main() {} diff --git a/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr b/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr new file mode 100644 index 000000000..e57933da5 --- /dev/null +++ b/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.stderr @@ -0,0 +1,17 @@ +error: free static item without body + --> $DIR/issue-83907-invalid-fn-like-path.rs:3:1 + | +LL | static STATIC_VAR_FIVE: &One(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error[E0412]: cannot find type `One` in this scope + --> $DIR/issue-83907-invalid-fn-like-path.rs:3:26 + | +LL | static STATIC_VAR_FIVE: &One(); + | ^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lifetimes/issue-84398.rs b/tests/ui/lifetimes/issue-84398.rs new file mode 100644 index 000000000..1912fa59b --- /dev/null +++ b/tests/ui/lifetimes/issue-84398.rs @@ -0,0 +1,20 @@ +// check-pass + +pub trait Deserialize<'de>: Sized {} +pub trait DeserializeOwned: for<'de> Deserialize<'de> {} + +pub trait Extensible { + type Config; +} + +// The `C` here generates a `C: Sized` candidate +pub trait Installer { + fn init>(&mut self) -> () + where + // This clause generates a `for<'de> C: Sized` candidate + B::Config: DeserializeOwned, + { + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-84604.rs b/tests/ui/lifetimes/issue-84604.rs new file mode 100644 index 000000000..b315ef051 --- /dev/null +++ b/tests/ui/lifetimes/issue-84604.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: -Csymbol-mangling-version=v0 + +pub fn f() {} +pub trait Frob {} +fn main() { + f::>(); + f:: Frob>(); +} diff --git a/tests/ui/lifetimes/issue-90170-elision-mismatch.fixed b/tests/ui/lifetimes/issue-90170-elision-mismatch.fixed new file mode 100644 index 000000000..bd85da1a7 --- /dev/null +++ b/tests/ui/lifetimes/issue-90170-elision-mismatch.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime may not live long enough + +pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime may not live long enough + +pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime may not live long enough + +fn main() {} diff --git a/tests/ui/lifetimes/issue-90170-elision-mismatch.rs b/tests/ui/lifetimes/issue-90170-elision-mismatch.rs new file mode 100644 index 000000000..3c495368b --- /dev/null +++ b/tests/ui/lifetimes/issue-90170-elision-mismatch.rs @@ -0,0 +1,9 @@ +// run-rustfix + +pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime may not live long enough + +pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime may not live long enough + +pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime may not live long enough + +fn main() {} diff --git a/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr b/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr new file mode 100644 index 000000000..48fb3fb4a --- /dev/null +++ b/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -0,0 +1,44 @@ +error: lifetime may not live long enough + --> $DIR/issue-90170-elision-mismatch.rs:3:40 + | +LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter + | +LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/issue-90170-elision-mismatch.rs:5:44 + | +LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter + | +LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ++ + +error: lifetime may not live long enough + --> $DIR/issue-90170-elision-mismatch.rs:7:63 + | +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter + | +LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++ ++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs new file mode 100644 index 000000000..ce4cddc9b --- /dev/null +++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs @@ -0,0 +1,15 @@ +use std::cell::RefCell; +use std::io::Read; + +fn main() {} + +fn inner(mut foo: &[u8]) { + let refcell = RefCell::new(&mut foo); + //~^ ERROR `foo` does not live long enough + let read = &refcell as &RefCell; + //~^ ERROR lifetime may not live long enough + + read_thing(read); +} + +fn read_thing(refcell: &RefCell) {} diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr new file mode 100644 index 000000000..99e1e7217 --- /dev/null +++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr @@ -0,0 +1,24 @@ +error[E0597]: `foo` does not live long enough + --> $DIR/issue-90600-expected-return-static-indirect.rs:7:32 + | +LL | let refcell = RefCell::new(&mut foo); + | ^^^^^^^^ borrowed value does not live long enough +LL | +LL | let read = &refcell as &RefCell; + | -------- cast requires that `foo` is borrowed for `'static` +... +LL | } + | - `foo` dropped here while still borrowed + +error: lifetime may not live long enough + --> $DIR/issue-90600-expected-return-static-indirect.rs:9:16 + | +LL | fn inner(mut foo: &[u8]) { + | - let's call the lifetime of this reference `'1` +... +LL | let read = &refcell as &RefCell; + | ^^^^^^^^ cast requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/lifetimes/issue-91763.rs b/tests/ui/lifetimes/issue-91763.rs new file mode 100644 index 000000000..2e8807fe6 --- /dev/null +++ b/tests/ui/lifetimes/issue-91763.rs @@ -0,0 +1,11 @@ +// aux-build:issue-91763-aux.rs + +#![deny(elided_lifetimes_in_paths)] + +extern crate issue_91763_aux; + +#[issue_91763_aux::repro] +fn f() -> Ptr; +//~^ ERROR hidden lifetime parameters in types are deprecated + +fn main() {} diff --git a/tests/ui/lifetimes/issue-91763.stderr b/tests/ui/lifetimes/issue-91763.stderr new file mode 100644 index 000000000..6ccf008c0 --- /dev/null +++ b/tests/ui/lifetimes/issue-91763.stderr @@ -0,0 +1,18 @@ +error: hidden lifetime parameters in types are deprecated + --> $DIR/issue-91763.rs:8:20 + | +LL | fn f() -> Ptr; + | ^ expected lifetime parameter + | +note: the lint level is defined here + --> $DIR/issue-91763.rs:3:9 + | +LL | #![deny(elided_lifetimes_in_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | fn f() -> Ptr<'_>; + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs new file mode 100644 index 000000000..3fba8c00c --- /dev/null +++ b/tests/ui/lifetimes/issue-95023.rs @@ -0,0 +1,11 @@ +struct ErrorKind; +struct Error(ErrorKind); +impl Fn(&isize) for Error { + //~^ ERROR manual implementations of `Fn` are experimental [E0183] + //~^^ ERROR associated type bindings are not allowed here [E0229] + fn foo(&self) -> Self::B<{N}>; + //~^ ERROR associated function in `impl` without body + //~^^ ERROR method `foo` is not a member of trait `Fn` [E0407] + //~^^^ ERROR associated type `B` not found for `Self` [E0220] +} +fn main() {} diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr new file mode 100644 index 000000000..35c3797c7 --- /dev/null +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -0,0 +1,38 @@ +error: associated function in `impl` without body + --> $DIR/issue-95023.rs:6:5 + | +LL | fn foo(&self) -> Self::B<{N}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error[E0407]: method `foo` is not a member of trait `Fn` + --> $DIR/issue-95023.rs:6:5 + | +LL | fn foo(&self) -> Self::B<{N}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Fn` + +error[E0183]: manual implementations of `Fn` are experimental + --> $DIR/issue-95023.rs:3:6 + | +LL | impl Fn(&isize) for Error { + | ^^^^^^^^^^ manual implementations of `Fn` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-95023.rs:3:6 + | +LL | impl Fn(&isize) for Error { + | ^^^^^^^^^^ associated type not allowed here + +error[E0220]: associated type `B` not found for `Self` + --> $DIR/issue-95023.rs:6:44 + | +LL | fn foo(&self) -> Self::B<{N}>; + | ^ associated type `B` not found + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0183, E0220, E0229, E0407. +For more information about an error, try `rustc --explain E0183`. diff --git a/tests/ui/lifetimes/issue-97193.rs b/tests/ui/lifetimes/issue-97193.rs new file mode 100644 index 000000000..6c82c29dd --- /dev/null +++ b/tests/ui/lifetimes/issue-97193.rs @@ -0,0 +1,9 @@ +extern "C" { + fn a(&mut self) { + //~^ ERROR incorrect function inside `extern` block + //~| ERROR `self` parameter is only allowed in associated functions + fn b(buf: &Self) {} + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-97193.stderr b/tests/ui/lifetimes/issue-97193.stderr new file mode 100644 index 000000000..21be543cc --- /dev/null +++ b/tests/ui/lifetimes/issue-97193.stderr @@ -0,0 +1,28 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-97193.rs:2:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn a(&mut self) { + | ________^____________- + | | | + | | cannot have a body +LL | | +LL | | +LL | | fn b(buf: &Self) {} +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `self` parameter is only allowed in associated functions + --> $DIR/issue-97193.rs:2:10 + | +LL | fn a(&mut self) { + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lifetimes/issue-97194.rs b/tests/ui/lifetimes/issue-97194.rs new file mode 100644 index 000000000..5f3560dbe --- /dev/null +++ b/tests/ui/lifetimes/issue-97194.rs @@ -0,0 +1,10 @@ +extern "C" { + fn bget(&self, index: [usize; Self::DIM]) -> bool { + //~^ ERROR incorrect function inside `extern` block + //~| ERROR `self` parameter is only allowed in associated functions + //~| ERROR failed to resolve: `Self` + type T<'a> = &'a str; + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/issue-97194.stderr b/tests/ui/lifetimes/issue-97194.stderr new file mode 100644 index 000000000..93bde285a --- /dev/null +++ b/tests/ui/lifetimes/issue-97194.stderr @@ -0,0 +1,36 @@ +error: incorrect function inside `extern` block + --> $DIR/issue-97194.rs:2:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn bget(&self, index: [usize; Self::DIM]) -> bool { + | ________^^^^___________________________________________- + | | | + | | cannot have a body +LL | | +LL | | +LL | | +LL | | type T<'a> = &'a str; +LL | | } + | |_____- help: remove the invalid body: `;` + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `self` parameter is only allowed in associated functions + --> $DIR/issue-97194.rs:2:13 + | +LL | fn bget(&self, index: [usize; Self::DIM]) -> bool { + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions + --> $DIR/issue-97194.rs:2:35 + | +LL | fn bget(&self, index: [usize; Self::DIM]) -> bool { + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/lifetimes/lifetime-bound-will-change-warning.rs b/tests/ui/lifetimes/lifetime-bound-will-change-warning.rs new file mode 100644 index 000000000..0d0303705 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-bound-will-change-warning.rs @@ -0,0 +1,56 @@ +// aux-build:lifetime_bound_will_change_warning_lib.rs + +// Test that various corner cases cause an error. These are tests +// that used to pass before we tweaked object defaults. + +#![allow(dead_code)] +#![allow(unused_variables)] + + +extern crate lifetime_bound_will_change_warning_lib as lib; + +fn just_ref(x: &dyn Fn()) { +} + +fn ref_obj(x: &Box) { + // this will change to &Box... + + // Note: no warning is issued here, because the type of `x` will change to 'static + if false { ref_obj(x); } +} + +fn test1<'a>(x: &'a Box) { + // just_ref will stay the same. + just_ref(&**x) +} + +fn test1cc<'a>(x: &'a Box) { + // same as test1, but cross-crate + lib::just_ref(&**x) +} + +fn test2<'a>(x: &'a Box) { + // but ref_obj will not, so warn. + ref_obj(x) + //~^ ERROR borrowed data escapes +} + +fn test2cc<'a>(x: &'a Box) { + // same as test2, but cross crate + lib::ref_obj(x) + //~^ ERROR borrowed data escapes +} + +fn test3<'a>(x: &'a Box) { + // here, we have a 'static bound, so even when ref_obj changes, no error results + ref_obj(x) +} + +fn test3cc<'a>(x: &'a Box) { + // same as test3, but cross crate + lib::ref_obj(x) +} + + +fn main() { +} diff --git a/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr b/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr new file mode 100644 index 000000000..c51580f28 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr @@ -0,0 +1,31 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/lifetime-bound-will-change-warning.rs:34:5 + | +LL | fn test2<'a>(x: &'a Box) { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | // but ref_obj will not, so warn. +LL | ref_obj(x) + | ^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/lifetime-bound-will-change-warning.rs:40:5 + | +LL | fn test2cc<'a>(x: &'a Box) { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | // same as test2, but cross crate +LL | lib::ref_obj(x) + | ^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.rs b/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.rs new file mode 100644 index 000000000..d2b782c92 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.rs @@ -0,0 +1,49 @@ +trait ListItem<'a> { + fn list_name() -> &'a str; +} + +trait Collection { fn len(&self) -> usize; } + +// is now well formed. RFC 2093 +struct List<'a, T: ListItem<'a>> { + slice: &'a [T] +} + +impl<'a, T: ListItem<'a>> Collection for List<'a, T> { + fn len(&self) -> usize { + 0 + } +} + +struct Foo { + foo: &'static T + //~^ ERROR may not live long enough +} + +trait X: Sized { + fn foo<'a, L: X<&'a Nested>>(); + //~^ ERROR may not live long enough + + // check that we give a sane error for `Self` + fn bar<'a, L: X<&'a Nested>>(); + //~^ ERROR may not live long enough + + // check that we give a sane error for nested generics + fn baz<'a, L, M: X<&'a Nested>>() { + //~^ ERROR may not live long enough + } +} + +trait TraitB {} + +struct Nested(K); +impl Nested { + fn generic_in_parent<'a, L: X<&'a Nested>>() { + //~^ ERROR may not live long enough + } + fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { + //~^ ERROR may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr new file mode 100644 index 000000000..affb4e8d0 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -0,0 +1,68 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:19:10 + | +LL | foo: &'static T + | ^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Foo { + | +++++++++ + +error[E0309]: the parameter type `K` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 + | +LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl Nested { + | ++++ + +error[E0309]: the parameter type `M` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 + | +LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b + 'a>() { + | ++++ + +error[E0309]: the parameter type `K` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 + | +LL | fn foo<'a, L: X<&'a Nested>>(); + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | trait X: Sized { + | ++++ + +error[E0309]: the parameter type `Self` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19 + | +LL | fn bar<'a, L: X<&'a Nested>>(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Self: 'a`... + = note: ...so that the reference type `&'a Nested` does not outlive the data it points at + +error[E0309]: the parameter type `L` may not live long enough + --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 + | +LL | fn baz<'a, L, M: X<&'a Nested>>() { + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | fn baz<'a, L: 'a, M: X<&'a Nested>>() { + | ++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0309, E0310. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs new file mode 100644 index 000000000..d0a8fe795 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -0,0 +1,51 @@ +// Lifetime annotation needed because we have no arguments. +fn f() -> &isize { //~ ERROR missing lifetime specifier + panic!() +} + +// Lifetime annotation needed because we have two by-reference parameters. +fn g(_x: &isize, _y: &isize) -> &isize { //~ ERROR missing lifetime specifier + panic!() +} + +struct Foo<'a> { + x: &'a isize, +} + +// Lifetime annotation needed because we have two lifetimes: one as a parameter +// and one on the reference. +fn h(_x: &Foo) -> &isize { //~ ERROR missing lifetime specifier + panic!() +} + +fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier + panic!() +} + +// Cases which used to work but now don't. + +type StaticStr = &'static str; // hides 'static +trait WithLifetime<'a> { + type Output; // can hide 'a +} + +// This worked because the type of the first argument contains +// 'static, although StaticStr doesn't even have parameters. +fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier + panic!() +} + +// This worked because the compiler resolved the argument type +// to >::Output which has the hidden 'a. +fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { +//~^ ERROR missing lifetime specifier + panic!() +} + +fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } +//~^ ERROR missing lifetime specifier + +// This is ok because both `'a` are for the same parameter. +fn m<'a>(_: &'a Foo<'a>) -> &str { "" } + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr new file mode 100644 index 000000000..5eee953ef --- /dev/null +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -0,0 +1,87 @@ +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:2:11 + | +LL | fn f() -> &isize { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f() -> &'static isize { + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33 + | +LL | fn g(_x: &isize, _y: &isize) -> &isize { + | ------ ------ ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y` +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize { + | ++++ ++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19 + | +LL | fn h(_x: &Foo) -> &isize { + | ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn h<'a>(_x: &'a Foo<'a>) -> &'a isize { + | ++++ ++ ++++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20 + | +LL | fn i(_x: isize) -> &isize { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn i(_x: isize) -> &'static isize { + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:34:24 + | +LL | fn j(_x: StaticStr) -> &isize { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn j(_x: StaticStr) -> &'static isize { + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:40:49 + | +LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'a` lifetime + | +LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &'a isize { + | ++ + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:45:37 + | +LL | fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } + | ------- ------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +help: consider using the `'a` lifetime + | +LL | fn l<'a>(_: &'a str, _: &'a str) -> &'a str { "" } + | ++ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-trait.rs b/tests/ui/lifetimes/lifetime-elision-return-type-trait.rs new file mode 100644 index 000000000..5168cb20d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -0,0 +1,13 @@ +trait Future { + type Item; + type Error; +} + +use std::error::Error; + +fn foo() -> impl Future> { + //~^ ERROR not satisfied + Ok(()) +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr new file mode 100644 index 000000000..ef1127c59 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied + --> $DIR/lifetime-elision-return-type-trait.rs:8:13 + | +LL | fn foo() -> impl Future> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs new file mode 100644 index 000000000..b0c09c751 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.rs @@ -0,0 +1,14 @@ +struct Foo { + field: i32, +} + +fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 { + if true { + let p: &i32 = &a.field; + &*p + } else { + &*x //~ ERROR explicit lifetime + } +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr new file mode 100644 index 000000000..63d00875d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/42701_one_named_and_one_anonymous.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/42701_one_named_and_one_anonymous.rs:10:9 + | +LL | fn foo2<'a>(a: &'a Foo, x: &i32) -> &'a i32 { + | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` +... +LL | &*x + | ^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs new file mode 100644 index 000000000..35f70dd19 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs @@ -0,0 +1,20 @@ +#[derive(Clone)] +enum Foo<'a> { + Bar(&'a str), +} + +impl<'a> Foo<'a> { + fn bar(&self, other: Foo) -> Foo<'a> { + match *self { + Foo::Bar(s) => { + if s == "test" { + other //~ ERROR explicit lifetime + } else { + self.clone() + } + } + } + } +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr new file mode 100644 index 000000000..64aa8361c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `other` + --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:11:21 + | +LL | fn bar(&self, other: Foo) -> Foo<'a> { + | --- help: add explicit lifetime `'a` to the type of `other`: `Foo<'a>` +... +LL | other + | ^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs new file mode 100644 index 000000000..9b15b378d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs @@ -0,0 +1,5 @@ +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } //~ ERROR explicit lifetime +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr new file mode 100644 index 000000000..b40481ecd --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-2.rs:2:16 + | +LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` +LL | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs new file mode 100644 index 000000000..6b062125c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs @@ -0,0 +1,5 @@ +fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + if x > y { x } else { y } //~ ERROR explicit lifetime +} + +fn main () { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr new file mode 100644 index 000000000..194fd9589 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in parameter type + --> $DIR/ex1-return-one-existing-name-if-else-3.rs:2:27 + | +LL | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 { + | --------------- help: add explicit lifetime `'a` to type: `(&'a i32, &'a i32)` +LL | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs new file mode 100644 index 000000000..7bc3fa623 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs @@ -0,0 +1,8 @@ +trait Foo { + +fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + if x > y { x } else { y } //~ ERROR explicit lifetime + } +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr new file mode 100644 index 000000000..64f4bd0fc --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:4:15 + | +LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` +LL | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs new file mode 100644 index 000000000..a1126d6bb --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -0,0 +1,14 @@ +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&'a self, x: &i32) -> &i32 { + + if true { &self.field } else { x } //~ ERROR explicit lifetime + + } + +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr new file mode 100644 index 000000000..961f9de66 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:8:36 + | +LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` +LL | +LL | if true { &self.field } else { x } + | ^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs new file mode 100644 index 000000000..f0d73deb3 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs @@ -0,0 +1,18 @@ +trait Foo { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; + +} + +impl Foo for () { + + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + + if x > y { x } else { y } + //~^ ERROR lifetime may not live long enough + + } + +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr new file mode 100644 index 000000000..5bb763813 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:11:20 + | +LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { + | -- - let's call the lifetime of this reference `'1` + | | + | lifetime `'a` defined here +LL | +LL | if x > y { x } else { y } + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs new file mode 100644 index 000000000..f72d567bb --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.rs @@ -0,0 +1,5 @@ +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + if x > y { x } else { y } //~ ERROR explicit lifetime +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr new file mode 100644 index 000000000..29a706957 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/ex1-return-one-existing-name-if-else.rs:2:27 + | +LL | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + | ---- help: add explicit lifetime `'a` to the type of `y`: `&'a i32` +LL | if x > y { x } else { y } + | ^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs new file mode 100644 index 000000000..49993aca3 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs @@ -0,0 +1,15 @@ +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&self, x: &'a i32) -> &i32 { + + x + //~^ ERROR lifetime may not live long enough + + } + +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr new file mode 100644 index 000000000..4bcd7cf95 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:8:5 + | +LL | fn foo<'a>(&self, x: &'a i32) -> &i32 { + | -- - let's call the lifetime of this reference `'1` + | | + | lifetime `'a` defined here +LL | +LL | x + | ^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs new file mode 100644 index 000000000..63d81a57d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs @@ -0,0 +1,14 @@ +struct Foo { + field: i32, +} + +impl Foo { + fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { + + if true { x } else { self } + //~^ ERROR lifetime may not live long enough + + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr new file mode 100644 index 000000000..34a64f8a6 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:8:30 + | +LL | fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { + | -- - let's call the lifetime of this reference `'1` + | | + | lifetime `'a` defined here +LL | +LL | if true { x } else { self } + | ^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs new file mode 100644 index 000000000..d6c918843 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs @@ -0,0 +1,5 @@ +fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime + if x > y { x } else { y } +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr new file mode 100644 index 000000000..bcc3e9510 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/ex1b-return-no-names-if-else.rs:1:29 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + | ++++ ++ ++ ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs new file mode 100644 index 000000000..998a48ce2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.rs @@ -0,0 +1,9 @@ +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a>(x: Ref, y: &mut Vec>) { + y.push(x); //~ ERROR explicit lifetime +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr new file mode 100644 index 000000000..90d4754eb --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-2.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/ex2a-push-one-existing-name-2.rs:6:5 + | +LL | fn foo<'a>(x: Ref, y: &mut Vec>) { + | -------- help: add explicit lifetime `'a` to the type of `x`: `Ref<'a, i32>` +LL | y.push(x); + | ^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs new file mode 100644 index 000000000..d18b50d0d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs @@ -0,0 +1,11 @@ +trait Foo<'a> {} +impl<'a, T> Foo<'a> for T {} + +fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T) + where i32: Foo<'a>, + u32: Foo<'b> +{ + x.push(y); //~ ERROR explicit lifetime required +} +fn main() { +} diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr new file mode 100644 index 000000000..a03e16b3b --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/ex2a-push-one-existing-name-early-bound.rs:8:5 + | +LL | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T) + | -- help: add explicit lifetime `'a` to the type of `y`: `&'a T` +... +LL | x.push(y); + | ^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs new file mode 100644 index 000000000..5188ea1cc --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.rs @@ -0,0 +1,9 @@ +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a>(x: &mut Vec>, y: Ref) { + x.push(y); //~ ERROR explicit lifetime +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr new file mode 100644 index 000000000..487b34e3d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/ex2a-push-one-existing-name.rs:6:5 + | +LL | fn foo<'a>(x: &mut Vec>, y: Ref) { + | -------- help: add explicit lifetime `'a` to the type of `y`: `Ref<'a, i32>` +LL | x.push(y); + | ^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs new file mode 100644 index 000000000..27424d79b --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.rs @@ -0,0 +1,10 @@ +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo(x: &mut Vec>, y: Ref) { + x.push(y); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr new file mode 100644 index 000000000..1622ce422 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/ex2b-push-no-existing-names.rs:6:5 + | +LL | fn foo(x: &mut Vec>, y: Ref) { + | - - has type `Ref<'1, i32>` + | | + | has type `&mut Vec>` +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs new file mode 100644 index 000000000..2236d78ef --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.rs @@ -0,0 +1,11 @@ +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + let z = Ref { data: y.data }; + x.push(z); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr new file mode 100644 index 000000000..99fab4631 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/ex2c-push-inference-variable.rs:7:5 + | +LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'b` defined here +LL | let z = Ref { data: y.data }; +LL | x.push(z); + | ^^^^^^^^^ argument requires that `'c` must outlive `'b` + | + = help: consider adding the following bound: `'c: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs new file mode 100644 index 000000000..f57323029 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs @@ -0,0 +1,12 @@ +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + let a: &mut Vec> = x; + let b = Ref { data: y.data }; + a.push(b); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr new file mode 100644 index 000000000..52c5752f6 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/ex2d-push-inference-variable-2.rs:8:5 + | +LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'b` defined here +... +LL | a.push(b); + | ^^^^^^^^^ argument requires that `'c` must outlive `'b` + | + = help: consider adding the following bound: `'c: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs new file mode 100644 index 000000000..4a934bbf0 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs @@ -0,0 +1,12 @@ +struct Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + let a: &mut Vec> = x; + let b = Ref { data: y.data }; + Vec::push(a, b); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr new file mode 100644 index 000000000..e90c81ee3 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/ex2e-push-inference-variable-3.rs:8:5 + | +LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'b` defined here +... +LL | Vec::push(a, b); + | ^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b` + | + = help: consider adding the following bound: `'c: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs new file mode 100644 index 000000000..09ee9accc --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs @@ -0,0 +1,6 @@ +fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { + *v = x; + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr new file mode 100644 index 000000000..5a23f1e0e --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-2.rs:2:5 + | +LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | *v = x; + | ^^^^^^ assignment requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { + | ++++ ++ ++ + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs new file mode 100644 index 000000000..b3106db77 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.rs @@ -0,0 +1,7 @@ +fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { + z.push((x,y)); + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr new file mode 100644 index 000000000..6ba130308 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -0,0 +1,32 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-3.rs:2:5 + | +LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | z.push((x,y)); + | ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-3.rs:2:5 + | +LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { + | - - let's call the lifetime of this reference `'3` + | | + | let's call the lifetime of this reference `'4` +LL | z.push((x,y)); + | ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { + | ++++ ++ ++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs new file mode 100644 index 000000000..5d0367783 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs @@ -0,0 +1,11 @@ +struct Ref<'a, 'b> { + a: &'a u32, + b: &'b u32, +} + +fn foo(mut x: Ref, y: Ref) { + x.b = y.b; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr new file mode 100644 index 000000000..4c0ffe5c0 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:7:5 + | +LL | fn foo(mut x: Ref, y: Ref) { + | ----- - has type `Ref<'_, '1>` + | | + | has type `Ref<'_, '2>` +LL | x.b = y.b; + | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs new file mode 100644 index 000000000..4a479f19c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs @@ -0,0 +1,11 @@ +struct Ref<'a, 'b> { + a: &'a u32, + b: &'b u32, +} + +fn foo(mut x: Ref) { + x.a = x.b; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr new file mode 100644 index 000000000..97c665347 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:7:5 + | +LL | fn foo(mut x: Ref) { + | ----- + | | + | has type `Ref<'_, '1>` + | has type `Ref<'2, '_>` +LL | x.a = x.b; + | ^^^^^^^^^ assignment requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs new file mode 100644 index 000000000..9b8cfe670 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs @@ -0,0 +1,13 @@ +struct Ref<'a> { + x: &'a u32, +} + +fn foo<'a, 'b>(mut x: Vec>, y: Ref<'b>) + where &'a (): Sized, + &'b u32: Sized +{ + x.push(y); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr new file mode 100644 index 000000000..b3d0bc2b8 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:9:5 + | +LL | fn foo<'a, 'b>(mut x: Vec>, y: Ref<'b>) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs new file mode 100644 index 000000000..db934a0be --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs @@ -0,0 +1,10 @@ +struct Ref<'a> { + x: &'a u32, +} + +fn foo<'a, 'b>(mut x: Vec>, y: Ref<'b>) { + x.push(y); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr new file mode 100644 index 000000000..fbe98a426 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:6:5 + | +LL | fn foo<'a, 'b>(mut x: Vec>, y: Ref<'b>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs new file mode 100644 index 000000000..4bf5db41f --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs @@ -0,0 +1,10 @@ +struct Ref<'a> { + x: &'a u32, +} + +fn foo(mut x: Vec, y: Ref) { + x.push(y); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr new file mode 100644 index 000000000..9630729d0 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-both-are-structs.rs:6:5 + | +LL | fn foo(mut x: Vec, y: Ref) { + | ----- - has type `Ref<'1>` + | | + | has type `Vec>` +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs new file mode 100644 index 000000000..8dcb814b2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.rs @@ -0,0 +1,6 @@ +fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) { + x.push(y); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr new file mode 100644 index 000000000..1e24032fc --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-latebound-regions.rs:2:5 + | +LL | fn foo<'a,'b>(x: &mut Vec<&'a u8>, y: &'b u8) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs new file mode 100644 index 000000000..e4df870bc --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs @@ -0,0 +1,9 @@ +struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 } + +fn foo(mut x: Ref, y: &u32) { + y = x.b; + //~^ ERROR lifetime may not live long enough + //~| ERROR cannot assign to immutable argument +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr new file mode 100644 index 000000000..bbd62902d --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr @@ -0,0 +1,21 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:4:5 + | +LL | fn foo(mut x: Ref, y: &u32) { + | ----- - let's call the lifetime of this reference `'2` + | | + | has type `Ref<'_, '1>` +LL | y = x.b; + | ^^^^^^^ assignment requires that `'1` must outlive `'2` + +error[E0384]: cannot assign to immutable argument `y` + --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:4:5 + | +LL | fn foo(mut x: Ref, y: &u32) { + | - help: consider making this binding mutable: `mut y` +LL | y = x.b; + | ^^^^^^^ cannot assign to immutable argument + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs new file mode 100644 index 000000000..00de48278 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs @@ -0,0 +1,8 @@ +struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 } + +fn foo(mut y: Ref, x: &u32) { + y.b = x; + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr new file mode 100644 index 000000000..79e7e8e15 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:4:5 + | +LL | fn foo(mut y: Ref, x: &u32) { + | ----- - let's call the lifetime of this reference `'1` + | | + | has type `Ref<'_, '2>` +LL | y.b = x; + | ^^^^^^^ assignment requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs new file mode 100644 index 000000000..00de48278 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.rs @@ -0,0 +1,8 @@ +struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 } + +fn foo(mut y: Ref, x: &u32) { + y.b = x; + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr new file mode 100644 index 000000000..53615fd1a --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct-4.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-one-is-struct-4.rs:4:5 + | +LL | fn foo(mut y: Ref, x: &u32) { + | ----- - let's call the lifetime of this reference `'1` + | | + | has type `Ref<'_, '2>` +LL | y.b = x; + | ^^^^^^^ assignment requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs new file mode 100644 index 000000000..5bb0e28d4 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs @@ -0,0 +1,11 @@ +struct Ref<'a, 'b> { + a: &'a u32, + b: &'b u32, +} + +fn foo(mut x: Ref, y: &u32) { + x.b = y; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr new file mode 100644 index 000000000..6ff441167 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-one-is-struct.rs:7:5 + | +LL | fn foo(mut x: Ref, y: &u32) { + | ----- - let's call the lifetime of this reference `'1` + | | + | has type `Ref<'_, '2>` +LL | x.b = y; + | ^^^^^^^ assignment requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs new file mode 100644 index 000000000..3ffd7be4e --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs @@ -0,0 +1,12 @@ +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&self, x: &i32) -> &i32 { + x + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr new file mode 100644 index 000000000..5601335d2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:7:5 + | +LL | fn foo<'a>(&self, x: &i32) -> &i32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | x + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn foo<'a>(&'a self, x: &'a i32) -> &i32 { + | ++ ++ + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs new file mode 100644 index 000000000..9b67a7742 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs @@ -0,0 +1,12 @@ +struct Foo { + field: i32, +} + +impl Foo { + fn foo<'a>(&self, x: &Foo) -> &Foo { + if true { x } else { self } + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr new file mode 100644 index 000000000..e221902c4 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-self-is-anon.rs:7:19 + | +LL | fn foo<'a>(&self, x: &Foo) -> &Foo { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | if true { x } else { self } + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn foo<'a>(&'a self, x: &'a Foo) -> &Foo { + | ++ ++ + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs new file mode 100644 index 000000000..2f67750d8 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.rs @@ -0,0 +1,7 @@ +fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { + y.push(z); + //~^ ERROR lifetime may not live long enough + //~| ERROR cannot borrow +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr new file mode 100644 index 000000000..cc2447b18 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 + | +LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | y.push(z); + | ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { + | ++++ ++ ++ + +error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable + --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 + | +LL | y.push(z); + | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(x:fn(&u8, &u8), mut y: Vec<&u8>, z: &u8) { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs new file mode 100644 index 000000000..73e1789f2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs @@ -0,0 +1,10 @@ +trait Foo { + fn foo<'a>(x: &mut Vec<&u8>, y: &u8); +} +impl Foo for () { + fn foo(x: &mut Vec<&u8>, y: &u8) { + x.push(y); + //~^ ERROR lifetime may not live long enough + } +} +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr new file mode 100644 index 000000000..9661f1e51 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-using-impl-items.rs:6:9 + | +LL | fn foo(x: &mut Vec<&u8>, y: &u8) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { + | ++++ ++ ++ + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs new file mode 100644 index 000000000..97fa9ef91 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.rs @@ -0,0 +1,7 @@ +fn foo(x:Box , y: Vec<&u8>, z: &u8) { + y.push(z); + //~^ ERROR lifetime may not live long enough + //~| ERROR cannot borrow +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr new file mode 100644 index 000000000..2ba5afa80 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 + | +LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | y.push(z); + | ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x:Box , y: Vec<&'a u8>, z: &'a u8) { + | ++++ ++ ++ + +error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable + --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 + | +LL | y.push(z); + | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(x:Box , mut y: Vec<&u8>, z: &u8) { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs new file mode 100644 index 000000000..ca0feaba8 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.rs @@ -0,0 +1,6 @@ +fn foo(x: &mut Vec<&u8>, y: &u8) { + x.push(y); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr new file mode 100644 index 000000000..ec9fac0c2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/ex3-both-anon-regions.rs:2:5 + | +LL | fn foo(x: &mut Vec<&u8>, y: &u8) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | x.push(y); + | ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { + | ++++ ++ ++ + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs new file mode 100644 index 000000000..ddb8bacce --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs @@ -0,0 +1,16 @@ +//! Regression test for #74400: Type mismatch in function arguments E0631, E0271 are falsely +//! recognized as E0308 mismatched types. + +use std::convert::identity; + +fn main() {} + +fn f(data: &[T], key: impl Fn(&T) -> S) { +} + +fn g(data: &[T]) { + f(data, identity) + //~^ ERROR the parameter type + //~| ERROR mismatched types + //~| ERROR implementation of `FnOnce` is not general +} diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr new file mode 100644 index 000000000..7049f28e2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -0,0 +1,38 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn g(data: &[T]) { + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Fn<(&'a T,)>` + found trait `Fn<(&T,)>` +note: the lifetime requirement is introduced here + --> $DIR/issue_74400.rs:8:34 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | ^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue_74400.rs:12:5 + | +LL | f(data, identity) + | ^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0310. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs b/tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs new file mode 100644 index 000000000..81a20c587 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.rs @@ -0,0 +1,37 @@ +// Check notes are placed on an assignment that can actually precede the current assignment +// Don't emit a first assignment for assignment in a loop. + +fn test() { + let x; + if true { + x = 1; + } else { + x = 2; + x = 3; //~ ERROR [E0384] + } +} + +fn test_in_loop() { + loop { + let x; + if true { + x = 1; + } else { + x = 2; + x = 3; //~ ERROR [E0384] + } + } +} + +fn test_using_loop() { + let x; + loop { + if true { + x = 1; //~ ERROR [E0384] + } else { + x = 2; //~ ERROR [E0384] + } + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr b/tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr new file mode 100644 index 000000000..b47a47d63 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/liveness-assign-imm-local-notes.stderr @@ -0,0 +1,46 @@ +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/liveness-assign-imm-local-notes.rs:10:9 + | +LL | let x; + | - help: consider making this binding mutable: `mut x` +... +LL | x = 2; + | ----- first assignment to `x` +LL | x = 3; + | ^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/liveness-assign-imm-local-notes.rs:21:13 + | +LL | let x; + | - help: consider making this binding mutable: `mut x` +... +LL | x = 2; + | ----- first assignment to `x` +LL | x = 3; + | ^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/liveness-assign-imm-local-notes.rs:30:13 + | +LL | let x; + | - help: consider making this binding mutable: `mut x` +... +LL | x = 1; + | ^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/liveness-assign-imm-local-notes.rs:32:13 + | +LL | let x; + | - help: consider making this binding mutable: `mut x` +... +LL | x = 1; + | ----- first assignment to `x` +LL | } else { +LL | x = 2; + | ^^^^^ cannot assign twice to immutable variable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs new file mode 100644 index 000000000..2ce1a0f45 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs @@ -0,0 +1,12 @@ +trait Foo { + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; +} + +impl Foo for () { + fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + if x > y { x } else { y } + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr new file mode 100644 index 000000000..9c61d5a0c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -0,0 +1,16 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 + | +LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; + | ------------------------------------------- expected `fn(&'1 i32, &'a i32) -> &'a i32` +... +LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'1 i32) -> &'1 i32` + | + = note: expected signature `fn(&'1 i32, &'a i32) -> &'a i32` + found signature `fn(&'1 i32, &'1 i32) -> &'1 i32` + = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/lifetime-no-keyword.rs b/tests/ui/lifetimes/lifetime-no-keyword.rs new file mode 100644 index 000000000..f466f44f5 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-no-keyword.rs @@ -0,0 +1,7 @@ +fn foo<'a>(a: &'a isize) { } +fn bar(a: &'static isize) { } +fn baz<'let>(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names +//~^ ERROR lifetimes cannot use keyword names +fn zab<'self>(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names +//~^ ERROR lifetimes cannot use keyword names +fn main() { } diff --git a/tests/ui/lifetimes/lifetime-no-keyword.stderr b/tests/ui/lifetimes/lifetime-no-keyword.stderr new file mode 100644 index 000000000..ba8ceb80f --- /dev/null +++ b/tests/ui/lifetimes/lifetime-no-keyword.stderr @@ -0,0 +1,26 @@ +error: lifetimes cannot use keyword names + --> $DIR/lifetime-no-keyword.rs:3:8 + | +LL | fn baz<'let>(a: &'let isize) { } + | ^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/lifetime-no-keyword.rs:3:18 + | +LL | fn baz<'let>(a: &'let isize) { } + | ^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/lifetime-no-keyword.rs:5:8 + | +LL | fn zab<'self>(a: &'self isize) { } + | ^^^^^ + +error: lifetimes cannot use keyword names + --> $DIR/lifetime-no-keyword.rs:5:19 + | +LL | fn zab<'self>(a: &'self isize) { } + | ^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lifetimes/missing-lifetime-in-alias.rs b/tests/ui/lifetimes/missing-lifetime-in-alias.rs new file mode 100644 index 000000000..51c564c01 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-alias.rs @@ -0,0 +1,31 @@ +trait Trait<'a> { + type Foo; + + type Bar<'b> + //~^ NOTE associated type defined here, with 1 lifetime parameter + //~| NOTE + where + Self: 'b; +} + +struct Impl<'a>(&'a ()); + +impl<'a> Trait<'a> for Impl<'a> { + type Foo = &'a (); + type Bar<'b> = &'b (); +} + +type A<'a> = Impl<'a>; + +type B<'a> = as Trait>::Foo; +//~^ ERROR missing lifetime specifier +//~| NOTE expected named lifetime parameter + +type C<'a, 'b> = as Trait>::Bar; +//~^ ERROR missing lifetime specifier +//~| ERROR missing generics for associated type +//~| NOTE expected named lifetime parameter +//~| NOTE these named lifetimes are available to use +//~| NOTE expected 1 lifetime argument + +fn main() {} diff --git a/tests/ui/lifetimes/missing-lifetime-in-alias.stderr b/tests/ui/lifetimes/missing-lifetime-in-alias.stderr new file mode 100644 index 000000000..20159e144 --- /dev/null +++ b/tests/ui/lifetimes/missing-lifetime-in-alias.stderr @@ -0,0 +1,47 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-alias.rs:20:24 + | +LL | type B<'a> = as Trait>::Foo; + | ^^^^^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | type B<'a> = as Trait<'a>>::Foo; + | ++++ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-alias.rs:24:28 + | +LL | type C<'a, 'b> = as Trait>::Bar; + | ^^^^^ expected named lifetime parameter + | +note: these named lifetimes are available to use + --> $DIR/missing-lifetime-in-alias.rs:24:8 + | +LL | type C<'a, 'b> = as Trait>::Bar; + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | type C<'a, 'b> = as Trait<'lifetime>>::Bar; + | +++++++++++ + +error[E0107]: missing generics for associated type `Trait::Bar` + --> $DIR/missing-lifetime-in-alias.rs:24:36 + | +LL | type C<'a, 'b> = as Trait>::Bar; + | ^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'b` + --> $DIR/missing-lifetime-in-alias.rs:4:10 + | +LL | type Bar<'b> + | ^^^ -- +help: add missing lifetime argument + | +LL | type C<'a, 'b> = as Trait>::Bar<'a>; + | ++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0107. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/nested-binder-print.rs b/tests/ui/lifetimes/nested-binder-print.rs new file mode 100644 index 000000000..f97f349fd --- /dev/null +++ b/tests/ui/lifetimes/nested-binder-print.rs @@ -0,0 +1,10 @@ +struct TwoLt<'a, 'b>(&'a (), &'b ()); +type Foo<'a> = fn(TwoLt<'_, 'a>); + +fn foo() { + let y: for<'a> fn(Foo<'a>); + let x: u32 = y; + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/lifetimes/nested-binder-print.stderr b/tests/ui/lifetimes/nested-binder-print.stderr new file mode 100644 index 000000000..32dd89693 --- /dev/null +++ b/tests/ui/lifetimes/nested-binder-print.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/nested-binder-print.rs:6:18 + | +LL | let x: u32 = y; + | --- ^ expected `u32`, found fn pointer + | | + | expected due to this + | + = note: expected type `u32` + found fn pointer `for<'a> fn(for<'b> fn(TwoLt<'b, 'a>))` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/nested.rs b/tests/ui/lifetimes/nested.rs new file mode 100644 index 000000000..f3f1f2016 --- /dev/null +++ b/tests/ui/lifetimes/nested.rs @@ -0,0 +1,7 @@ +// check-pass + +fn method<'a>(_i: &'a i32) { + fn inner<'a>(_j: &'a f32) {} +} + +fn main() {} diff --git a/tests/ui/lifetimes/re-empty-in-error.rs b/tests/ui/lifetimes/re-empty-in-error.rs new file mode 100644 index 000000000..554028a96 --- /dev/null +++ b/tests/ui/lifetimes/re-empty-in-error.rs @@ -0,0 +1,10 @@ +// We didn't have a single test mentioning +// `ReEmpty` and this test changes that. +fn foo<'a>(_a: &'a u32) where for<'b> &'b (): 'a { +} + +fn main() { + foo(&10); + //~^ ERROR higher-ranked lifetime error + //~| NOTE could not prove +} diff --git a/tests/ui/lifetimes/re-empty-in-error.stderr b/tests/ui/lifetimes/re-empty-in-error.stderr new file mode 100644 index 000000000..c35d8ecec --- /dev/null +++ b/tests/ui/lifetimes/re-empty-in-error.stderr @@ -0,0 +1,10 @@ +error: higher-ranked lifetime error + --> $DIR/re-empty-in-error.rs:7:5 + | +LL | foo(&10); + | ^^^^^^^^ + | + = note: could not prove `for<'b> &'b (): 'a` + +error: aborting due to previous error + diff --git a/tests/ui/lifetimes/shadow.rs b/tests/ui/lifetimes/shadow.rs new file mode 100644 index 000000000..e2124887e --- /dev/null +++ b/tests/ui/lifetimes/shadow.rs @@ -0,0 +1,8 @@ +struct Foo(T); + +impl<'s> Foo<&'s u8> { + fn bar<'s>(&self, x: &'s u8) {} //~ ERROR shadows a lifetime name + fn baz(x: for<'s> fn(&'s u32)) {} //~ ERROR shadows a lifetime name +} + +fn main() {} diff --git a/tests/ui/lifetimes/shadow.stderr b/tests/ui/lifetimes/shadow.stderr new file mode 100644 index 000000000..b834e90d8 --- /dev/null +++ b/tests/ui/lifetimes/shadow.stderr @@ -0,0 +1,20 @@ +error[E0496]: lifetime name `'s` shadows a lifetime name that is already in scope + --> $DIR/shadow.rs:4:12 + | +LL | impl<'s> Foo<&'s u8> { + | -- first declared here +LL | fn bar<'s>(&self, x: &'s u8) {} + | ^^ lifetime `'s` already in scope + +error[E0496]: lifetime name `'s` shadows a lifetime name that is already in scope + --> $DIR/shadow.rs:5:19 + | +LL | impl<'s> Foo<&'s u8> { + | -- first declared here +LL | fn bar<'s>(&self, x: &'s u8) {} +LL | fn baz(x: for<'s> fn(&'s u32)) {} + | ^^ lifetime `'s` already in scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0496`. diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed new file mode 100644 index 000000000..f977f0bd3 --- /dev/null +++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +#![allow(warnings)] + +fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { + with_restriction::(x) //~ ERROR the parameter type `T` may not live long enough +} + +fn with_restriction<'b, T: 'b>(x: &'b ()) -> &'b () { + x +} + +fn main() {} diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs new file mode 100644 index 000000000..d6ce112ec --- /dev/null +++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs @@ -0,0 +1,13 @@ +// run-rustfix + +#![allow(warnings)] + +fn no_restriction(x: &()) -> &() { + with_restriction::(x) //~ ERROR the parameter type `T` may not live long enough +} + +fn with_restriction<'b, T: 'b>(x: &'b ()) -> &'b () { + x +} + +fn main() {} diff --git a/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr new file mode 100644 index 000000000..2d58d3a02 --- /dev/null +++ b/tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr @@ -0,0 +1,24 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:6:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:5:25 + | +LL | fn no_restriction(x: &()) -> &() { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:6:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() { + | +++ ++++ ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.rs b/tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.rs new file mode 100644 index 000000000..cc29f9de7 --- /dev/null +++ b/tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.rs @@ -0,0 +1,16 @@ +#[derive(Eq, PartialEq)] +struct Test { + a: &'b str, + //~^ ERROR use of undeclared lifetime name `'b` + //~| ERROR use of undeclared lifetime name `'b` +} + +trait T { + fn foo(&'static self) {} +} + +impl T for Test { + fn foo(&'b self) {} //~ ERROR use of undeclared lifetime name `'b` +} + +fn main() {} diff --git a/tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr new file mode 100644 index 000000000..0d6ade415 --- /dev/null +++ b/tests/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr @@ -0,0 +1,36 @@ +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 + | +LL | struct Test { + | - help: consider introducing lifetime `'b` here: `<'b>` +LL | a: &'b str, + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 + | +LL | #[derive(Eq, PartialEq)] + | -- lifetime `'b` is missing in item created through this procedural macro +LL | struct Test { + | - help: consider introducing lifetime `'b` here: `<'b>` +LL | a: &'b str, + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13 + | +LL | fn foo(&'b self) {} + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | fn foo<'b>(&'b self) {} + | ++++ +help: consider introducing lifetime `'b` here + | +LL | impl<'b> T for Test { + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs b/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs new file mode 100644 index 000000000..8deb36551 --- /dev/null +++ b/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs @@ -0,0 +1,3 @@ +fn main() { + [0].iter().flat_map(|a| [0].iter().map(|_| &a)); //~ ERROR closure may outlive +} diff --git a/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr b/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr new file mode 100644 index 000000000..439904509 --- /dev/null +++ b/tests/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function + --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:44 + | +LL | [0].iter().flat_map(|a| [0].iter().map(|_| &a)); + | ^^^ - `a` is borrowed here + | | + | may outlive borrowed value `a` + | +note: closure is returned here + --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:29 + | +LL | [0].iter().flat_map(|a| [0].iter().map(|_| &a)); + | ^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword + | +LL | [0].iter().flat_map(|a| [0].iter().map(move |_| &a)); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs new file mode 100644 index 000000000..b4c86aab8 --- /dev/null +++ b/tests/ui/lifetimes/unusual-rib-combinations.rs @@ -0,0 +1,28 @@ +#![feature(inline_const)] + +struct S<'a>(&'a u8); +fn foo() {} + +// Paren generic args in AnonConst +fn a() -> [u8; foo::()] { +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait +//~| ERROR mismatched types + panic!() +} + +// Paren generic args in ConstGeneric +fn b() {} +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + +// Paren generic args in AnonymousReportError +fn c() {} +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait +//~| ERROR defaults for type parameters are only allowed in +//~| WARN this was previously accepted + +// Elided lifetime in path in ConstGeneric +fn d() {} +//~^ ERROR missing lifetime specifier +//~| ERROR `S<'static>` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr new file mode 100644 index 000000000..6d7b42506 --- /dev/null +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -0,0 +1,61 @@ +error[E0106]: missing lifetime specifier + --> $DIR/unusual-rib-combinations.rs:24:15 + | +LL | fn d() {} + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | fn d<'a, const C: S<'a>>() {} + | +++ ++++ + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/unusual-rib-combinations.rs:7:16 + | +LL | fn a() -> [u8; foo::()] { + | ^^^^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/unusual-rib-combinations.rs:14:15 + | +LL | fn b() {} + | ^^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/unusual-rib-combinations.rs:18:10 + | +LL | fn c() {} + | ^^^^ only `Fn` traits may use parentheses + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unusual-rib-combinations.rs:18:6 + | +LL | fn c() {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error[E0308]: mismatched types + --> $DIR/unusual-rib-combinations.rs:7:16 + | +LL | fn a() -> [u8; foo::()] { + | ^^^^^^^ expected `usize`, found fn item + | + = note: expected type `usize` + found fn item `fn() {foo}` + +error: `S<'static>` is forbidden as the type of a const generic parameter + --> $DIR/unusual-rib-combinations.rs:24:15 + | +LL | fn d() {} + | ^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0106, E0214, E0308. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/limits/huge-array-simple-32.rs b/tests/ui/limits/huge-array-simple-32.rs new file mode 100644 index 000000000..2290e3d5e --- /dev/null +++ b/tests/ui/limits/huge-array-simple-32.rs @@ -0,0 +1,12 @@ +// ignore-64bit +// build-fail + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +#![allow(arithmetic_overflow)] + +fn main() { + let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the current architecture + [0; (1u32<<31) as usize +(1u32<<15) as usize]; +} diff --git a/tests/ui/limits/huge-array-simple-32.stderr b/tests/ui/limits/huge-array-simple-32.stderr new file mode 100644 index 000000000..31e120df6 --- /dev/null +++ b/tests/ui/limits/huge-array-simple-32.stderr @@ -0,0 +1,8 @@ +error: values of the type `[u8; 2147516416]` are too big for the current architecture + --> $DIR/huge-array-simple-32.rs:10:9 + | +LL | let _fat: [u8; (1<<31)+(1<<15)] = + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/huge-array-simple-64.rs b/tests/ui/limits/huge-array-simple-64.rs new file mode 100644 index 000000000..02c961fc5 --- /dev/null +++ b/tests/ui/limits/huge-array-simple-64.rs @@ -0,0 +1,12 @@ +// build-fail +// ignore-32bit + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +#![allow(arithmetic_overflow)] + +fn main() { + let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the current architecture + [0; (1u64<<61) as usize +(1u64<<31) as usize]; +} diff --git a/tests/ui/limits/huge-array-simple-64.stderr b/tests/ui/limits/huge-array-simple-64.stderr new file mode 100644 index 000000000..c5d3fe85d --- /dev/null +++ b/tests/ui/limits/huge-array-simple-64.stderr @@ -0,0 +1,8 @@ +error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture + --> $DIR/huge-array-simple-64.rs:10:9 + | +LL | let _fat: [u8; (1<<61)+(1<<31)] = + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/huge-array.rs b/tests/ui/limits/huge-array.rs new file mode 100644 index 000000000..3070801f8 --- /dev/null +++ b/tests/ui/limits/huge-array.rs @@ -0,0 +1,15 @@ +// FIXME https://github.com/rust-lang/rust/issues/59774 + +// build-fail +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +fn generic(t: T) { + let s: [T; 1518600000] = [t; 1518600000]; + //~^ ERROR values of the type `[[u8; 1518599999]; 1518600000]` are too big +} + +fn main() { + let x: [u8; 1518599999] = [0; 1518599999]; + generic::<[u8; 1518599999]>(x); +} diff --git a/tests/ui/limits/huge-array.stderr b/tests/ui/limits/huge-array.stderr new file mode 100644 index 000000000..817458b73 --- /dev/null +++ b/tests/ui/limits/huge-array.stderr @@ -0,0 +1,8 @@ +error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the current architecture + --> $DIR/huge-array.rs:8:9 + | +LL | let s: [T; 1518600000] = [t; 1518600000]; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs new file mode 100644 index 000000000..39ea6e11b --- /dev/null +++ b/tests/ui/limits/huge-enum.rs @@ -0,0 +1,18 @@ +// build-fail +// normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE" +// normalize-stderr-test "\[u32; \d+\]" -> "TYPE" + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +#[cfg(target_pointer_width = "32")] +type BIG = Option<[u32; (1<<29)-1]>; + +#[cfg(target_pointer_width = "64")] +type BIG = Option<[u32; (1<<45)-1]>; + +fn main() { + let big: BIG = None; + //~^ ERROR are too big for the current architecture +} diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr new file mode 100644 index 000000000..a1456e1a8 --- /dev/null +++ b/tests/ui/limits/huge-enum.stderr @@ -0,0 +1,8 @@ +error: values of the type `Option` are too big for the current architecture + --> $DIR/huge-enum.rs:16:9 + | +LL | let big: BIG = None; + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/huge-struct.rs b/tests/ui/limits/huge-struct.rs new file mode 100644 index 000000000..02f38d860 --- /dev/null +++ b/tests/ui/limits/huge-struct.rs @@ -0,0 +1,53 @@ +// build-fail +// normalize-stderr-test "S32" -> "SXX" +// normalize-stderr-test "S1M" -> "SXX" +// error-pattern: too big for the current + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +struct S32 { + v0: T, + v1: T, + v2: T, + v3: T, + v4: T, + v5: T, + v6: T, + v7: T, + v8: T, + u9: T, + v10: T, + v11: T, + v12: T, + v13: T, + v14: T, + v15: T, + v16: T, + v17: T, + v18: T, + v19: T, + v20: T, + v21: T, + v22: T, + v23: T, + v24: T, + u25: T, + v26: T, + v27: T, + v28: T, + v29: T, + v30: T, + v31: T, +} + +struct S1k { val: S32> } + +struct S1M { val: S1k> } + +fn main() { + let fat: Option>>> = None; + //~^ ERROR are too big for the current architecture + +} diff --git a/tests/ui/limits/huge-struct.stderr b/tests/ui/limits/huge-struct.stderr new file mode 100644 index 000000000..f0ee88e59 --- /dev/null +++ b/tests/ui/limits/huge-struct.stderr @@ -0,0 +1,8 @@ +error: values of the type `SXX>>` are too big for the current architecture + --> $DIR/huge-struct.rs:50:9 + | +LL | let fat: Option>>> = None; + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/issue-15919-32.rs b/tests/ui/limits/issue-15919-32.rs new file mode 100644 index 000000000..3c93f14cc --- /dev/null +++ b/tests/ui/limits/issue-15919-32.rs @@ -0,0 +1,13 @@ +// ignore-64bit +// build-fail + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +fn main() { + let x = [0usize; 0xffff_ffff]; //~ ERROR too big +} + +// This and the -64 version of this test need to have different literals, as we can't rely on +// conditional compilation for them while retaining the same spans/lines. diff --git a/tests/ui/limits/issue-15919-32.stderr b/tests/ui/limits/issue-15919-32.stderr new file mode 100644 index 000000000..0d79fc0c7 --- /dev/null +++ b/tests/ui/limits/issue-15919-32.stderr @@ -0,0 +1,8 @@ +error: values of the type `[usize; usize::MAX]` are too big for the current architecture + --> $DIR/issue-15919-32.rs:9:9 + | +LL | let x = [0usize; 0xffff_ffff]; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/issue-15919-64.rs b/tests/ui/limits/issue-15919-64.rs new file mode 100644 index 000000000..3ecbd34ea --- /dev/null +++ b/tests/ui/limits/issue-15919-64.rs @@ -0,0 +1,13 @@ +// build-fail +// ignore-32bit + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +fn main() { + let x = [0usize; 0xffff_ffff_ffff_ffff]; //~ ERROR too big +} + +// This and the -32 version of this test need to have different literals, as we can't rely on +// conditional compilation for them while retaining the same spans/lines. diff --git a/tests/ui/limits/issue-15919-64.stderr b/tests/ui/limits/issue-15919-64.stderr new file mode 100644 index 000000000..3399d644e --- /dev/null +++ b/tests/ui/limits/issue-15919-64.stderr @@ -0,0 +1,8 @@ +error: values of the type `[usize; usize::MAX]` are too big for the current architecture + --> $DIR/issue-15919-64.rs:9:9 + | +LL | let x = [0usize; 0xffff_ffff_ffff_ffff]; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs new file mode 100644 index 000000000..56cf5d831 --- /dev/null +++ b/tests/ui/limits/issue-17913.rs @@ -0,0 +1,21 @@ +// build-fail +// normalize-stderr-test "\[&usize; \d+\]" -> "[&usize; usize::MAX]" +// error-pattern: too big for the current architecture + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +#[cfg(target_pointer_width = "64")] +fn main() { + let n = 0_usize; + let a: Box<_> = Box::new([&n; 0xF000000000000000_usize]); + println!("{}", a[0xFFFFFF_usize]); +} + +#[cfg(target_pointer_width = "32")] +fn main() { + let n = 0_usize; + let a: Box<_> = Box::new([&n; 0xFFFFFFFF_usize]); + println!("{}", a[0xFFFFFF_usize]); +} diff --git a/tests/ui/limits/issue-17913.stderr b/tests/ui/limits/issue-17913.stderr new file mode 100644 index 000000000..684db53a9 --- /dev/null +++ b/tests/ui/limits/issue-17913.stderr @@ -0,0 +1,4 @@ +error: values of the type `[&usize; usize::MAX]` are too big for the current architecture + +error: aborting due to previous error + diff --git a/tests/ui/limits/issue-55878.rs b/tests/ui/limits/issue-55878.rs new file mode 100644 index 000000000..c1c54646d --- /dev/null +++ b/tests/ui/limits/issue-55878.rs @@ -0,0 +1,8 @@ +// build-fail +// normalize-stderr-64bit "18446744073709551615" -> "SIZE" +// normalize-stderr-32bit "4294967295" -> "SIZE" + +// error-pattern: are too big for the current architecture +fn main() { + println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); +} diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr new file mode 100644 index 000000000..99f1fdf75 --- /dev/null +++ b/tests/ui/limits/issue-55878.stderr @@ -0,0 +1,38 @@ +error[E0080]: values of the type `[u8; usize::MAX]` are too big for the current architecture + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +note: inside `std::mem::size_of::<[u8; usize::MAX]>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `main` + --> $DIR/issue-55878.rs:7:26 + | +LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/issue-55878.rs:7:26 + | +LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-55878.rs:7:26 + | +LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/issue-55878.rs:7:26 + | +LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-56762.rs b/tests/ui/limits/issue-56762.rs new file mode 100644 index 000000000..fb0a270f1 --- /dev/null +++ b/tests/ui/limits/issue-56762.rs @@ -0,0 +1,24 @@ +// only-x86_64 + +// FIXME https://github.com/rust-lang/rust/issues/59774 +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +const HUGE_SIZE: usize = !0usize / 8; + + +pub struct TooBigArray { + arr: [u8; HUGE_SIZE], +} + +impl TooBigArray { + pub const fn new() -> Self { + TooBigArray { arr: [0x00; HUGE_SIZE], } + } +} + +static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); +//~^ ERROR values of the type `[u8; 2305843009213693951]` are too big +static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; +//~^ ERROR values of the type `[u8; 2305843009213693951]` are too big + +fn main() { } diff --git a/tests/ui/limits/issue-56762.stderr b/tests/ui/limits/issue-56762.stderr new file mode 100644 index 000000000..e6b9c6762 --- /dev/null +++ b/tests/ui/limits/issue-56762.stderr @@ -0,0 +1,15 @@ +error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture + --> $DIR/issue-56762.rs:19:1 + | +LL | static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: values of the type `[u8; 2305843009213693951]` are too big for the current architecture + --> $DIR/issue-56762.rs:21:1 + | +LL | static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs b/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs new file mode 100644 index 000000000..2560ffe16 --- /dev/null +++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs @@ -0,0 +1,11 @@ +// build-fail +// only-x86_64 +// compile-flags: -Zmir-opt-level=0 + +fn main() { + Bug::V([0; !0]); //~ ERROR are too big for the current +} + +enum Bug { + V([u8; !0]), +} diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr new file mode 100644 index 000000000..44b2be269 --- /dev/null +++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr @@ -0,0 +1,8 @@ +error: values of the type `[u8; usize::MAX]` are too big for the current architecture + --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5 + | +LL | Bug::V([0; !0]); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/limits/issue-75158-64.rs b/tests/ui/limits/issue-75158-64.rs new file mode 100644 index 000000000..06c209c07 --- /dev/null +++ b/tests/ui/limits/issue-75158-64.rs @@ -0,0 +1,16 @@ +//~ ERROR + +// build-fail +// ignore-32bit + +struct S { + x: [T; !0], +} + +pub fn f() -> usize { + std::mem::size_of::>() +} + +fn main() { + let x = f(); +} diff --git a/tests/ui/limits/issue-75158-64.stderr b/tests/ui/limits/issue-75158-64.stderr new file mode 100644 index 000000000..d5991bcf5 --- /dev/null +++ b/tests/ui/limits/issue-75158-64.stderr @@ -0,0 +1,4 @@ +error: values of the type `[u8; usize::MAX]` are too big for the current architecture + +error: aborting due to previous error + diff --git a/tests/ui/link-section.rs b/tests/ui/link-section.rs new file mode 100644 index 000000000..48efb07ff --- /dev/null +++ b/tests/ui/link-section.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(non_upper_case_globals)] +#[cfg(not(target_os = "macos"))] +#[link_section=".moretext"] +fn i_live_in_more_text() -> &'static str { + "knock knock" +} + +#[cfg(not(target_os = "macos"))] +#[link_section=".imm"] +static magic: usize = 42; + +#[cfg(not(target_os = "macos"))] +#[link_section=".mut"] +static mut frobulator: usize = 0xdeadbeef; + +#[cfg(target_os = "macos")] +#[link_section="__TEXT,__moretext"] +fn i_live_in_more_text() -> &'static str { + "knock knock" +} + +#[cfg(target_os = "macos")] +#[link_section="__RODATA,__imm"] +static magic: usize = 42; + +#[cfg(target_os = "macos")] +#[link_section="__DATA,__mut"] +static mut frobulator: usize = 0xdeadbeef; + +pub fn main() { + unsafe { + frobulator = 0x12345678; + println!("{} {} {}", i_live_in_more_text(), magic, frobulator); + } +} diff --git a/tests/ui/linkage-attr/auxiliary/def_colliding_external.rs b/tests/ui/linkage-attr/auxiliary/def_colliding_external.rs new file mode 100644 index 000000000..60b55b3e2 --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/def_colliding_external.rs @@ -0,0 +1,7 @@ +#![feature(linkage)] +#![crate_type = "lib"] + +extern "C" { + #[linkage = "external"] + pub static collision: *const i32; +} diff --git a/tests/ui/linkage-attr/auxiliary/def_external.rs b/tests/ui/linkage-attr/auxiliary/def_external.rs new file mode 100644 index 000000000..2300930e5 --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/def_external.rs @@ -0,0 +1,5 @@ +#![feature(linkage)] +#![crate_type = "lib"] + +#[linkage="external"] +pub static EXTERN: u32 = 0; diff --git a/tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-dylib.rs b/tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-dylib.rs new file mode 100644 index 000000000..0d927117d --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-dylib.rs @@ -0,0 +1,4 @@ +#![feature(link_cfg)] + +#[link(name = "foo", cfg(foo))] +extern "C" {} diff --git a/tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-rlib.rs b/tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-rlib.rs new file mode 100644 index 000000000..0a296f0b2 --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/link-cfg-works-transitive-rlib.rs @@ -0,0 +1,7 @@ +// no-prefer-dynamic + +#![feature(link_cfg)] +#![crate_type = "rlib"] + +#[link(name = "foo", cfg(foo))] +extern "C" {} diff --git a/tests/ui/linkage-attr/auxiliary/linkage1.rs b/tests/ui/linkage-attr/auxiliary/linkage1.rs new file mode 100644 index 000000000..e87ce5e4d --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/linkage1.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub static foo: isize = 3; + +pub fn bar() {} diff --git a/tests/ui/linkage-attr/issue-10755.rs b/tests/ui/linkage-attr/issue-10755.rs new file mode 100644 index 000000000..afd2dc46c --- /dev/null +++ b/tests/ui/linkage-attr/issue-10755.rs @@ -0,0 +1,10 @@ +// build-fail +// dont-check-compiler-stderr +// compile-flags: -C linker=llllll -C linker-flavor=ld +// error-pattern: `llllll` + +// Before, the error-pattern checked for "not found". On WSL with appendWindowsPath=true, running +// in invalid command returns a PermissionDenied instead. + +fn main() { +} diff --git a/tests/ui/linkage-attr/link-attr-validation-early.rs b/tests/ui/linkage-attr/link-attr-validation-early.rs new file mode 100644 index 000000000..b9a835fb5 --- /dev/null +++ b/tests/ui/linkage-attr/link-attr-validation-early.rs @@ -0,0 +1,8 @@ +// Top-level ill-formed +#[link] //~ ERROR attribute must be of the form + //~| WARN this was previously accepted +#[link = "foo"] //~ ERROR attribute must be of the form + //~| WARN this was previously accepted +extern "C" {} + +fn main() {} diff --git a/tests/ui/linkage-attr/link-attr-validation-early.stderr b/tests/ui/linkage-attr/link-attr-validation-early.stderr new file mode 100644 index 000000000..24ad9d825 --- /dev/null +++ b/tests/ui/linkage-attr/link-attr-validation-early.stderr @@ -0,0 +1,21 @@ +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/link-attr-validation-early.rs:2:1 + | +LL | #[link] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + = note: `#[deny(ill_formed_attribute_input)]` on by default + +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/link-attr-validation-early.rs:4:1 + | +LL | #[link = "foo"] + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/linkage-attr/link-attr-validation-late.rs b/tests/ui/linkage-attr/link-attr-validation-late.rs new file mode 100644 index 000000000..34f720dd2 --- /dev/null +++ b/tests/ui/linkage-attr/link-attr-validation-late.rs @@ -0,0 +1,39 @@ +#![feature(link_cfg)] + +// Top-level ill-formed +#[link(name = "...", "literal")] //~ ERROR unexpected `#[link]` argument +#[link(name = "...", unknown)] //~ ERROR unexpected `#[link]` argument +extern "C" {} + +// Duplicate arguments +#[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments +#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments +#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments +#[link(name = "...", cfg(FALSE), cfg(FALSE))] //~ ERROR multiple `cfg` arguments +#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments +extern "C" {} + +// Ill-formed arguments +#[link(name)] //~ ERROR link name must be of the form `name = "string"` + //~| ERROR `#[link]` attribute requires a `name = "string"` argument +#[link(name())] //~ ERROR link name must be of the form `name = "string"` + //~| ERROR `#[link]` attribute requires a `name = "string"` argument +#[link(name = "...", kind)] //~ ERROR link kind must be of the form `kind = "string"` +#[link(name = "...", kind())] //~ ERROR link kind must be of the form `kind = "string"` +#[link(name = "...", modifiers)] //~ ERROR link modifiers must be of the form `modifiers = "string"` +#[link(name = "...", modifiers())] //~ ERROR link modifiers must be of the form `modifiers = "string"` +#[link(name = "...", cfg)] //~ ERROR link cfg must be of the form `cfg(/* predicate */)` +#[link(name = "...", cfg = "literal")] //~ ERROR link cfg must be of the form `cfg(/* predicate */)` +#[link(name = "...", cfg("literal"))] //~ ERROR link cfg must have a single predicate argument +#[link(name = "...", wasm_import_module)] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"` +#[link(name = "...", wasm_import_module())] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"` +extern "C" {} + +// Basic modifier validation +#[link(name = "...", modifiers = "")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix +#[link(name = "...", modifiers = "no-plus-minus")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix +#[link(name = "...", modifiers = "+unknown")] //~ ERROR unknown linking modifier `unknown` +#[link(name = "...", modifiers = "+verbatim,+verbatim")] //~ ERROR multiple `verbatim` modifiers +extern "C" {} + +fn main() {} diff --git a/tests/ui/linkage-attr/link-attr-validation-late.stderr b/tests/ui/linkage-attr/link-attr-validation-late.stderr new file mode 100644 index 000000000..1ad5fbaf7 --- /dev/null +++ b/tests/ui/linkage-attr/link-attr-validation-late.stderr @@ -0,0 +1,147 @@ +error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type + --> $DIR/link-attr-validation-late.rs:4:22 + | +LL | #[link(name = "...", "literal")] + | ^^^^^^^^^ + +error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type + --> $DIR/link-attr-validation-late.rs:5:22 + | +LL | #[link(name = "...", unknown)] + | ^^^^^^^ + +error: multiple `name` arguments in a single `#[link]` attribute + --> $DIR/link-attr-validation-late.rs:9:22 + | +LL | #[link(name = "foo", name = "bar")] + | ^^^^^^^^^^^^ + +error: multiple `kind` arguments in a single `#[link]` attribute + --> $DIR/link-attr-validation-late.rs:10:38 + | +LL | #[link(name = "...", kind = "dylib", kind = "bar")] + | ^^^^^^^^^^^^ + +error: multiple `modifiers` arguments in a single `#[link]` attribute + --> $DIR/link-attr-validation-late.rs:11:47 + | +LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] + | ^^^^^^^^^^^^^^^^^ + +error: multiple `cfg` arguments in a single `#[link]` attribute + --> $DIR/link-attr-validation-late.rs:12:34 + | +LL | #[link(name = "...", cfg(FALSE), cfg(FALSE))] + | ^^^^^^^^^^ + +error: multiple `wasm_import_module` arguments in a single `#[link]` attribute + --> $DIR/link-attr-validation-late.rs:13:36 + | +LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: link name must be of the form `name = "string"` + --> $DIR/link-attr-validation-late.rs:17:8 + | +LL | #[link(name)] + | ^^^^ + +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/link-attr-validation-late.rs:17:1 + | +LL | #[link(name)] + | ^^^^^^^^^^^^^ missing `name` argument + +error: link name must be of the form `name = "string"` + --> $DIR/link-attr-validation-late.rs:19:8 + | +LL | #[link(name())] + | ^^^^^^ + +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/link-attr-validation-late.rs:19:1 + | +LL | #[link(name())] + | ^^^^^^^^^^^^^^^ missing `name` argument + +error: link kind must be of the form `kind = "string"` + --> $DIR/link-attr-validation-late.rs:21:22 + | +LL | #[link(name = "...", kind)] + | ^^^^ + +error: link kind must be of the form `kind = "string"` + --> $DIR/link-attr-validation-late.rs:22:22 + | +LL | #[link(name = "...", kind())] + | ^^^^^^ + +error: link modifiers must be of the form `modifiers = "string"` + --> $DIR/link-attr-validation-late.rs:23:22 + | +LL | #[link(name = "...", modifiers)] + | ^^^^^^^^^ + +error: link modifiers must be of the form `modifiers = "string"` + --> $DIR/link-attr-validation-late.rs:24:22 + | +LL | #[link(name = "...", modifiers())] + | ^^^^^^^^^^^ + +error: link cfg must be of the form `cfg(/* predicate */)` + --> $DIR/link-attr-validation-late.rs:25:22 + | +LL | #[link(name = "...", cfg)] + | ^^^ + +error: link cfg must be of the form `cfg(/* predicate */)` + --> $DIR/link-attr-validation-late.rs:26:22 + | +LL | #[link(name = "...", cfg = "literal")] + | ^^^^^^^^^^^^^^^ + +error: link cfg must have a single predicate argument + --> $DIR/link-attr-validation-late.rs:27:22 + | +LL | #[link(name = "...", cfg("literal"))] + | ^^^^^^^^^^^^^^ + +error: wasm import module must be of the form `wasm_import_module = "string"` + --> $DIR/link-attr-validation-late.rs:28:22 + | +LL | #[link(name = "...", wasm_import_module)] + | ^^^^^^^^^^^^^^^^^^ + +error: wasm import module must be of the form `wasm_import_module = "string"` + --> $DIR/link-attr-validation-late.rs:29:22 + | +LL | #[link(name = "...", wasm_import_module())] + | ^^^^^^^^^^^^^^^^^^^^ + +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + --> $DIR/link-attr-validation-late.rs:33:34 + | +LL | #[link(name = "...", modifiers = "")] + | ^^ + +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed + --> $DIR/link-attr-validation-late.rs:34:34 + | +LL | #[link(name = "...", modifiers = "no-plus-minus")] + | ^^^^^^^^^^^^^^^ + +error: unknown linking modifier `unknown`, expected one of: bundle, verbatim, whole-archive, as-needed + --> $DIR/link-attr-validation-late.rs:35:34 + | +LL | #[link(name = "...", modifiers = "+unknown")] + | ^^^^^^^^^^ + +error: multiple `verbatim` modifiers in a single `modifiers` argument + --> $DIR/link-attr-validation-late.rs:36:34 + | +LL | #[link(name = "...", modifiers = "+verbatim,+verbatim")] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 24 previous errors + +For more information about this error, try `rustc --explain E0459`. diff --git a/tests/ui/linkage-attr/link-cfg-works.rs b/tests/ui/linkage-attr/link-cfg-works.rs new file mode 100644 index 000000000..254091ff2 --- /dev/null +++ b/tests/ui/linkage-attr/link-cfg-works.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:link-cfg-works-transitive-rlib.rs +// aux-build:link-cfg-works-transitive-dylib.rs + +#![feature(link_cfg)] + +extern crate link_cfg_works_transitive_dylib; +extern crate link_cfg_works_transitive_rlib; + +#[link(name = "foo", cfg(foo))] +extern "C" {} + +fn main() {} diff --git a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs new file mode 100644 index 000000000..3a0910658 --- /dev/null +++ b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs @@ -0,0 +1,24 @@ +// rust-lang/rust#61232: We used to ICE when trying to detect a +// collision on the symbol generated for the external linkage item in +// an extern crate. + +// build-fail +// aux-build:def_colliding_external.rs +// FIXME(#83838) codegen-units=1 triggers llvm asserts +// compile-flags: -Ccodegen-units=16 + +extern crate def_colliding_external as dep1; + +#[no_mangle] +pub static _rust_extern_with_linkage_collision: i32 = 0; + +mod dep2 { + #[no_mangle] + pub static collision: usize = 0; +} + +fn main() { + unsafe { + println!("{:p}", &dep1::collision); + } +} diff --git a/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr new file mode 100644 index 000000000..06a070822 --- /dev/null +++ b/tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr @@ -0,0 +1,8 @@ +error: symbol `collision` is already defined + --> $DIR/auxiliary/def_colliding_external.rs:6:5 + | +LL | pub static collision: *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs b/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs new file mode 100644 index 000000000..c1df9ccef --- /dev/null +++ b/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs @@ -0,0 +1,26 @@ +// build-fail +// FIXME(#83838) codegen-units=1 triggers llvm asserts +// compile-flags: -Ccodegen-units=16 +#![feature(linkage)] + +mod dep1 { + extern "C" { + #[linkage = "external"] + #[no_mangle] + pub static collision: *const i32; //~ ERROR symbol `collision` is already defined + } +} + +#[no_mangle] +pub static _rust_extern_with_linkage_collision: i32 = 0; + +mod dep2 { + #[no_mangle] + pub static collision: usize = 0; +} + +fn main() { + unsafe { + println!("{:p}", &dep1::collision); + } +} diff --git a/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr b/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr new file mode 100644 index 000000000..e0be1ac21 --- /dev/null +++ b/tests/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr @@ -0,0 +1,8 @@ +error: symbol `collision` is already defined + --> $DIR/linkage-detect-local-generated-name-collision.rs:10:9 + | +LL | pub static collision: *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/linkage-attr/linkage-import.rs b/tests/ui/linkage-attr/linkage-import.rs new file mode 100644 index 000000000..f754ddc6e --- /dev/null +++ b/tests/ui/linkage-attr/linkage-import.rs @@ -0,0 +1,8 @@ +// build-pass +// aux-build:def_external.rs + +extern crate def_external as dep; + +fn main() { + println!("{:p}", &dep::EXTERN); +} diff --git a/tests/ui/linkage-attr/linkage1.rs b/tests/ui/linkage-attr/linkage1.rs new file mode 100644 index 000000000..deab7a251 --- /dev/null +++ b/tests/ui/linkage-attr/linkage1.rs @@ -0,0 +1,32 @@ +// run-pass +// ignore-windows +// ignore-macos +// ignore-emscripten doesn't support this linkage +// ignore-sgx weak linkage not permitted +// aux-build:linkage1.rs + +#![feature(linkage)] + +extern crate linkage1 as other; + +extern "C" { + #[linkage = "extern_weak"] + static foo: *const isize; + #[linkage = "extern_weak"] + static something_that_should_never_exist: *mut isize; +} + +fn main() { + // It appears that the --as-needed flag to linkers will not pull in a dynamic + // library unless it satisfies a non weak undefined symbol. The 'other' crate + // is compiled as a dynamic library where it would only be used for a + // weak-symbol as part of an executable, so the dynamic library would be + // discarded. By adding and calling `other::bar`, we get around this problem. + other::bar(); + + unsafe { + assert!(!foo.is_null()); + assert_eq!(*foo, 3); + assert!(something_that_should_never_exist.is_null()); + } +} diff --git a/tests/ui/linkage-attr/linkage2.rs b/tests/ui/linkage-attr/linkage2.rs new file mode 100644 index 000000000..aa42874f7 --- /dev/null +++ b/tests/ui/linkage-attr/linkage2.rs @@ -0,0 +1,13 @@ +// check-fail + +#![feature(linkage)] + +extern "C" { + #[linkage = "extern_weak"] + static foo: i32; +//~^ ERROR: invalid type for variable with `#[linkage]` attribute +} + +fn main() { + println!("{}", unsafe { foo }); +} diff --git a/tests/ui/linkage-attr/linkage2.stderr b/tests/ui/linkage-attr/linkage2.stderr new file mode 100644 index 000000000..7265f711f --- /dev/null +++ b/tests/ui/linkage-attr/linkage2.stderr @@ -0,0 +1,9 @@ +error[E0791]: invalid type for variable with `#[linkage]` attribute + --> $DIR/linkage2.rs:7:5 + | +LL | static foo: i32; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0791`. diff --git a/tests/ui/linkage-attr/linkage3.rs b/tests/ui/linkage-attr/linkage3.rs new file mode 100644 index 000000000..112eb1d3b --- /dev/null +++ b/tests/ui/linkage-attr/linkage3.rs @@ -0,0 +1,17 @@ +// FIXME https://github.com/rust-lang/rust/issues/59774 + +// check-fail +// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" + +#![feature(linkage)] + +extern "C" { + #[linkage = "foo"] + static foo: *const i32; +//~^ ERROR: invalid linkage specified +} + +fn main() { + println!("{:?}", unsafe { foo }); +} diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr new file mode 100644 index 000000000..f2579c6e8 --- /dev/null +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -0,0 +1,8 @@ +error: invalid linkage specified + --> $DIR/linkage3.rs:11:5 + | +LL | static foo: *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/linkage-attr/linkage4.rs b/tests/ui/linkage-attr/linkage4.rs new file mode 100644 index 000000000..3b935f972 --- /dev/null +++ b/tests/ui/linkage-attr/linkage4.rs @@ -0,0 +1,5 @@ +#[linkage = "external"] +static foo: isize = 0; +//~^^ ERROR: the `linkage` attribute is experimental and not portable + +fn main() {} diff --git a/tests/ui/linkage-attr/linkage4.stderr b/tests/ui/linkage-attr/linkage4.stderr new file mode 100644 index 000000000..30d4d2b7b --- /dev/null +++ b/tests/ui/linkage-attr/linkage4.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `linkage` attribute is experimental and not portable across platforms + --> $DIR/linkage4.rs:1:1 + | +LL | #[linkage = "external"] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29603 for more information + = help: add `#![feature(linkage)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint-unknown-lints-at-crate-level.rs b/tests/ui/lint-unknown-lints-at-crate-level.rs new file mode 100644 index 000000000..61d27f1ef --- /dev/null +++ b/tests/ui/lint-unknown-lints-at-crate-level.rs @@ -0,0 +1,7 @@ +// run-pass +// compile-flags: -D warnings -D unknown-lints + +#![allow(unknown_lints)] +#![allow(random_lint_name)] + +fn main() {} diff --git a/tests/ui/lint/auxiliary/add-impl.rs b/tests/ui/lint/auxiliary/add-impl.rs new file mode 100644 index 000000000..9d0e3068a --- /dev/null +++ b/tests/ui/lint/auxiliary/add-impl.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AddImpl)] +// Unnecessary qualification `bar::foo` +// https://github.com/rust-lang/rust/issues/71898 +pub fn derive(input: TokenStream) -> TokenStream { + "impl B { + fn foo(&self) { use bar::foo; bar::foo() } + } + + fn foo() {} + + mod bar { pub fn foo() {} } + ".parse().unwrap() +} diff --git a/tests/ui/lint/auxiliary/external_extern_fn.rs b/tests/ui/lint/auxiliary/external_extern_fn.rs new file mode 100644 index 000000000..c2a8cadc6 --- /dev/null +++ b/tests/ui/lint/auxiliary/external_extern_fn.rs @@ -0,0 +1,3 @@ +extern "C" { + pub fn extern_fn(x: u8); +} diff --git a/tests/ui/lint/auxiliary/inherited_stability.rs b/tests/ui/lint/auxiliary/inherited_stability.rs new file mode 100644 index 000000000..62100e5cc --- /dev/null +++ b/tests/ui/lint/auxiliary/inherited_stability.rs @@ -0,0 +1,47 @@ +#![crate_name="inherited_stability"] +#![crate_type = "lib"] +#![unstable(feature = "unstable_test_feature", issue = "none")] +#![feature(staged_api)] + +pub fn unstable() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub mod stable_mod { + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub mod unstable_mod { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + + pub fn unstable() {} +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Stable { + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn unstable(&self); + + #[stable(feature = "rust1", since = "1.0.0")] + fn stable(&self); +} + +impl Stable for usize { + fn unstable(&self) {} + fn stable(&self) {} +} + +pub enum Unstable { + UnstableVariant, + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant +} diff --git a/tests/ui/lint/auxiliary/lint_output_format.rs b/tests/ui/lint/auxiliary/lint_output_format.rs new file mode 100644 index 000000000..4e3547250 --- /dev/null +++ b/tests/ui/lint/auxiliary/lint_output_format.rs @@ -0,0 +1,20 @@ +#![crate_name="lint_output_format"] +#![crate_type = "lib"] +#![feature(staged_api)] +#![unstable(feature = "unstable_test_feature", issue = "none")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn foo() -> usize { + 20 +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn bar() -> usize { + 40 +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn baz() -> usize { + 30 +} diff --git a/tests/ui/lint/auxiliary/lint_stability.rs b/tests/ui/lint/auxiliary/lint_stability.rs new file mode 100644 index 000000000..99c29dcdd --- /dev/null +++ b/tests/ui/lint/auxiliary/lint_stability.rs @@ -0,0 +1,188 @@ +#![crate_name="lint_stability"] +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(associated_type_defaults)] +#![stable(feature = "lint_stability", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated() {} +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_text() {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "99.99.99", note = "text")] +pub fn deprecated_future() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_unstable() {} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_unstable_text() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn unstable() {} +#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] +pub fn unstable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable() {} +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct MethodTester; + +impl MethodTester { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait TraitWithAssociatedTypes { + #[unstable(feature = "unstable_test_feature", issue = "none")] + type TypeUnstable = u8; + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + type TypeDeprecated = u8; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +impl Trait for MethodTester {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub trait UnstableTrait { fn dummy(&self) { } } + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub trait DeprecatedTrait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { } +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub enum UnstableEnum {} +#[stable(feature = "rust1", since = "1.0.0")] +pub enum StableEnum {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableUnitStruct; +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableUnitStruct; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedUnstableVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test { + () => (deprecated()); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg { + ($func:expr) => ($func); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg_nested { + ($func:ident) => (macro_test_arg!($func())); +} diff --git a/tests/ui/lint/auxiliary/lint_stability_fields.rs b/tests/ui/lint/auxiliary/lint_stability_fields.rs new file mode 100644 index 000000000..e72a501e1 --- /dev/null +++ b/tests/ui/lint/auxiliary/lint_stability_fields.rs @@ -0,0 +1,66 @@ +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable { + pub inherit: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override2: u8, + #[stable(feature = "rust2", since = "2.0.0")] + pub override3: u8, +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Stable2(#[stable(feature = "rust2", since = "2.0.0")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] pub u8, + pub u8); + +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Stable3 { + Inherit(u8), + InheritOverride(#[stable(feature = "rust2", since = "2.0.0")] u8), + #[stable(feature = "rust2", since = "2.0.0")] + Override1, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Override2, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + Override3, +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct Unstable { + pub inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + pub override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override2: u8, +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct Unstable2(pub u8, + #[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] pub u8); + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct Deprecated { + pub inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + pub override1: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub override2: u8, +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct Deprecated2(pub u8, + #[stable(feature = "rust1", since = "1.0.0")] pub u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] pub u8); diff --git a/tests/ui/lint/auxiliary/lints-in-foreign-macros.rs b/tests/ui/lint/auxiliary/lints-in-foreign-macros.rs new file mode 100644 index 000000000..b969d9dba --- /dev/null +++ b/tests/ui/lint/auxiliary/lints-in-foreign-macros.rs @@ -0,0 +1,14 @@ +#[macro_export] +macro_rules! bar { + () => {use std::string::ToString;} +} + +#[macro_export] +macro_rules! baz { + ($i:item) => ($i) +} + +#[macro_export] +macro_rules! baz2 { + ($($i:tt)*) => ($($i)*) +} diff --git a/tests/ui/lint/auxiliary/stability-cfg2.rs b/tests/ui/lint/auxiliary/stability-cfg2.rs new file mode 100644 index 000000000..c995038e5 --- /dev/null +++ b/tests/ui/lint/auxiliary/stability-cfg2.rs @@ -0,0 +1,5 @@ +// compile-flags:--cfg foo + +#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))] +#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] +#![feature(staged_api)] diff --git a/tests/ui/lint/auxiliary/stability_cfg1.rs b/tests/ui/lint/auxiliary/stability_cfg1.rs new file mode 100644 index 000000000..2e027cc27 --- /dev/null +++ b/tests/ui/lint/auxiliary/stability_cfg1.rs @@ -0,0 +1,3 @@ +#![cfg_attr(foo, experimental)] +#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] +#![feature(staged_api)] diff --git a/tests/ui/lint/auxiliary/stability_cfg2.rs b/tests/ui/lint/auxiliary/stability_cfg2.rs new file mode 100644 index 000000000..c995038e5 --- /dev/null +++ b/tests/ui/lint/auxiliary/stability_cfg2.rs @@ -0,0 +1,5 @@ +// compile-flags:--cfg foo + +#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))] +#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))] +#![feature(staged_api)] diff --git a/tests/ui/lint/auxiliary/trivial-cast-ice.rs b/tests/ui/lint/auxiliary/trivial-cast-ice.rs new file mode 100644 index 000000000..ab2332d06 --- /dev/null +++ b/tests/ui/lint/auxiliary/trivial-cast-ice.rs @@ -0,0 +1,7 @@ +#[macro_export] +macro_rules! foo { + () => { + let x: &Option = &Some(1); + let _y = x as *const Option; + } +} diff --git a/tests/ui/lint/auxiliary/unaligned_references_external_crate.rs b/tests/ui/lint/auxiliary/unaligned_references_external_crate.rs new file mode 100644 index 000000000..fb486c6b5 --- /dev/null +++ b/tests/ui/lint/auxiliary/unaligned_references_external_crate.rs @@ -0,0 +1,28 @@ +#[macro_export] +macro_rules! mac { + ( + $(#[$attrs:meta])* + pub struct $ident:ident { + $( + $(#[$pin:ident])? + $field_vis:vis $field:ident: $field_ty:ty + ),+ $(,)? + } + ) => { + $(#[$attrs])* + pub struct $ident { + $( + $field_vis $field: $field_ty + ),+ + } + + const _: () = { + #[deny(unaligned_references)] + fn __f(this: &$ident) { + $( + let _ = &this.$field; + )+ + } + }; + }; +} diff --git a/tests/ui/lint/bad-lint-cap.rs b/tests/ui/lint/bad-lint-cap.rs new file mode 100644 index 000000000..e65c8319d --- /dev/null +++ b/tests/ui/lint/bad-lint-cap.rs @@ -0,0 +1,4 @@ +// compile-flags: --cap-lints test +// error-pattern: unknown lint level: `test` + +fn main() {} diff --git a/tests/ui/lint/bad-lint-cap.stderr b/tests/ui/lint/bad-lint-cap.stderr new file mode 100644 index 000000000..f284dbf84 --- /dev/null +++ b/tests/ui/lint/bad-lint-cap.stderr @@ -0,0 +1,2 @@ +error: unknown lint level: `test` + diff --git a/tests/ui/lint/bad-lint-cap2.rs b/tests/ui/lint/bad-lint-cap2.rs new file mode 100644 index 000000000..8bc8aca20 --- /dev/null +++ b/tests/ui/lint/bad-lint-cap2.rs @@ -0,0 +1,8 @@ +// compile-flags: --cap-lints deny + +#![warn(unused)] +#![deny(warnings)] + +use std::option; //~ ERROR + +fn main() {} diff --git a/tests/ui/lint/bad-lint-cap2.stderr b/tests/ui/lint/bad-lint-cap2.stderr new file mode 100644 index 000000000..3f3affe5a --- /dev/null +++ b/tests/ui/lint/bad-lint-cap2.stderr @@ -0,0 +1,15 @@ +error: unused import: `std::option` + --> $DIR/bad-lint-cap2.rs:6:5 + | +LL | use std::option; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/bad-lint-cap2.rs:4:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/bad-lint-cap3.rs b/tests/ui/lint/bad-lint-cap3.rs new file mode 100644 index 000000000..c38105870 --- /dev/null +++ b/tests/ui/lint/bad-lint-cap3.rs @@ -0,0 +1,9 @@ +// check-pass +// compile-flags: --cap-lints warn + +#![warn(unused)] +#![deny(warnings)] + +use std::option; //~ WARN + +fn main() {} diff --git a/tests/ui/lint/bad-lint-cap3.stderr b/tests/ui/lint/bad-lint-cap3.stderr new file mode 100644 index 000000000..0fb65322f --- /dev/null +++ b/tests/ui/lint/bad-lint-cap3.stderr @@ -0,0 +1,15 @@ +warning: unused import: `std::option` + --> $DIR/bad-lint-cap3.rs:7:5 + | +LL | use std::option; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/bad-lint-cap3.rs:5:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[warn(unused_imports)]` implied by `#[warn(warnings)]` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/bare-trait-objects-path.rs b/tests/ui/lint/bare-trait-objects-path.rs new file mode 100644 index 000000000..0e2294715 --- /dev/null +++ b/tests/ui/lint/bare-trait-objects-path.rs @@ -0,0 +1,26 @@ +#![feature(associated_type_defaults)] + +trait Assoc { + fn func() {} + const CONST: u8 = 0; + type Ty = u8; +} + +trait Dyn {} + +impl Assoc for dyn Dyn {} + +fn main() { + Dyn::func(); + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + ::Dyn::func(); + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + Dyn::CONST; + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let _: Dyn::Ty; //~ ERROR ambiguous associated type + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr new file mode 100644 index 000000000..a19f4963c --- /dev/null +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -0,0 +1,62 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:23:12 + | +LL | let _: Dyn::Ty; + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | let _: ::Ty; + | ++++ + + +error[E0223]: ambiguous associated type + --> $DIR/bare-trait-objects-path.rs:23:12 + | +LL | let _: Dyn::Ty; + | ^^^^^^^ help: use the fully-qualified path: `::Ty` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:14:5 + | +LL | Dyn::func(); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | ::func(); + | ++++ + + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:17:5 + | +LL | ::Dyn::func(); + | ^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | ::func(); + | ++++++ ++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-objects-path.rs:20:5 + | +LL | Dyn::CONST; + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | ::CONST; + | ++++ + + +error: aborting due to previous error; 4 warnings emitted + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/lint/clashing-extern-fn-recursion.rs b/tests/ui/lint/clashing-extern-fn-recursion.rs new file mode 100644 index 000000000..ab0fd0a2e --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn-recursion.rs @@ -0,0 +1,119 @@ +// check-pass +// +// This tests checks that clashing_extern_declarations handles types that are recursive through a +// pointer or ref argument. See #75512. + +#![crate_type = "lib"] + +mod raw_ptr_recursion { + mod a { + #[repr(C)] + struct Pointy { + pointy: *const Pointy, + } + + extern "C" { + fn run_pointy(pointy: Pointy); + } + } + mod b { + #[repr(C)] + struct Pointy { + pointy: *const Pointy, + } + + extern "C" { + fn run_pointy(pointy: Pointy); + } + } +} + +mod raw_ptr_recursion_once_removed { + mod a { + #[repr(C)] + struct Pointy1 { + pointy_two: *const Pointy2, + } + + #[repr(C)] + struct Pointy2 { + pointy_one: *const Pointy1, + } + + extern "C" { + fn run_pointy2(pointy: Pointy2); + } + } + + mod b { + #[repr(C)] + struct Pointy1 { + pointy_two: *const Pointy2, + } + + #[repr(C)] + struct Pointy2 { + pointy_one: *const Pointy1, + } + + extern "C" { + fn run_pointy2(pointy: Pointy2); + } + } +} + +mod ref_recursion { + mod a { + #[repr(C)] + struct Reffy<'a> { + reffy: &'a Reffy<'a>, + } + + extern "C" { + fn reffy_recursion(reffy: Reffy); + } + } + mod b { + #[repr(C)] + struct Reffy<'a> { + reffy: &'a Reffy<'a>, + } + + extern "C" { + fn reffy_recursion(reffy: Reffy); + } + } +} + +mod ref_recursion_once_removed { + mod a { + #[repr(C)] + struct Reffy1<'a> { + reffy: &'a Reffy2<'a>, + } + + struct Reffy2<'a> { + reffy: &'a Reffy1<'a>, + } + + extern "C" { + #[allow(improper_ctypes)] + fn reffy_once_removed(reffy: Reffy1); + } + } + mod b { + #[repr(C)] + struct Reffy1<'a> { + reffy: &'a Reffy2<'a>, + } + + struct Reffy2<'a> { + reffy: &'a Reffy1<'a>, + } + + extern "C" { + #[allow(improper_ctypes)] + fn reffy_once_removed(reffy: Reffy1); + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn-wasm.rs b/tests/ui/lint/clashing-extern-fn-wasm.rs new file mode 100644 index 000000000..eeb2b8eae --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn-wasm.rs @@ -0,0 +1,21 @@ +// check-pass +#![crate_type = "lib"] + +#[cfg(target_arch = "wasm32")] +mod wasm_non_clash { + mod a { + #[link(wasm_import_module = "a")] + extern "C" { + pub fn foo(); + } + } + + mod b { + #[link(wasm_import_module = "b")] + extern "C" { + pub fn foo() -> usize; + // #79581: These declarations shouldn't clash because foreign fn names are mangled + // on wasm32. + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs new file mode 100644 index 000000000..809e06026 --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn.rs @@ -0,0 +1,417 @@ +// check-pass +// aux-build:external_extern_fn.rs +#![crate_type = "lib"] +#![warn(clashing_extern_declarations)] + +mod redeclared_different_signature { + mod a { + extern "C" { + fn clash(x: u8); + } + } + mod b { + extern "C" { + fn clash(x: u64); //~ WARN `clash` redeclared with a different signature + } + } +} + +mod redeclared_same_signature { + mod a { + extern "C" { + fn no_clash(x: u8); + } + } + mod b { + extern "C" { + fn no_clash(x: u8); + } + } +} + +extern crate external_extern_fn; +mod extern_no_clash { + // Should not clash with external_extern_fn::extern_fn. + extern "C" { + fn extern_fn(x: u8); + } +} + +extern "C" { + fn some_other_new_name(x: i16); + + #[link_name = "extern_link_name"] + fn some_new_name(x: i16); + + #[link_name = "link_name_same"] + fn both_names_different(x: i16); +} + +fn link_name_clash() { + extern "C" { + fn extern_link_name(x: u32); + //~^ WARN `extern_link_name` redeclared with a different signature + + #[link_name = "some_other_new_name"] + //~^ WARN `some_other_extern_link_name` redeclares `some_other_new_name` with a different + fn some_other_extern_link_name(x: u32); + + #[link_name = "link_name_same"] + //~^ WARN `other_both_names_different` redeclares `link_name_same` with a different + fn other_both_names_different(x: u32); + } +} + +mod a { + extern "C" { + fn different_mod(x: u8); + } +} +mod b { + extern "C" { + fn different_mod(x: u64); //~ WARN `different_mod` redeclared with a different signature + } +} + +extern "C" { + fn variadic_decl(x: u8, ...); +} + +fn variadic_clash() { + extern "C" { + fn variadic_decl(x: u8); //~ WARN `variadic_decl` redeclared with a different signature + } +} + +#[no_mangle] +fn no_mangle_name(x: u8) {} + +extern "C" { + #[link_name = "unique_link_name"] + fn link_name_specified(x: u8); +} + +fn tricky_no_clash() { + extern "C" { + // Shouldn't warn, because the declaration above actually declares a different symbol (and + // Rust's name resolution rules around shadowing will handle this gracefully). + fn link_name_specified() -> u32; + + // The case of a no_mangle name colliding with an extern decl (see #28179) is related but + // shouldn't be reported by ClashingExternDeclarations, because this is an example of + // unmangled name clash causing bad behaviour in functions with a defined body. + fn no_mangle_name() -> u32; + } +} + +mod banana { + mod one { + #[repr(C)] + struct Banana { + weight: u32, + length: u16, + } + extern "C" { + fn weigh_banana(count: *const Banana) -> u64; + } + } + + mod two { + #[repr(C)] + struct Banana { + weight: u32, + length: u16, + } // note: distinct type + // This should not trigger the lint because two::Banana is structurally equivalent to + // one::Banana. + extern "C" { + fn weigh_banana(count: *const Banana) -> u64; + } + } + + mod three { + // This _should_ trigger the lint, because repr(packed) should generate a struct that has a + // different layout. + #[repr(packed)] + struct Banana { + weight: u32, + length: u16, + } + #[allow(improper_ctypes)] + extern "C" { + fn weigh_banana(count: *const Banana) -> u64; + //~^ WARN `weigh_banana` redeclared with a different signature + } + } +} + +mod sameish_members { + mod a { + #[repr(C)] + struct Point { + x: i16, + y: i16, + } + + extern "C" { + fn draw_point(p: Point); + } + } + mod b { + #[repr(C)] + struct Point { + coordinates: [i16; 2], + } + + // It's possible we are overconservative for this case, as accessing the elements of the + // coordinates array might end up correctly accessing `.x` and `.y`. However, this may not + // always be the case, for every architecture and situation. This is also a really odd + // thing to do anyway. + extern "C" { + fn draw_point(p: Point); + //~^ WARN `draw_point` redeclared with a different signature + } + } +} + +mod same_sized_members_clash { + mod a { + #[repr(C)] + struct Point3 { + x: f32, + y: f32, + z: f32, + } + extern "C" { + fn origin() -> Point3; + } + } + mod b { + #[repr(C)] + struct Point3 { + x: i32, + y: i32, + z: i32, // NOTE: Incorrectly redeclared as i32 + } + extern "C" { + fn origin() -> Point3; //~ WARN `origin` redeclared with a different signature + } + } +} + +mod transparent { + #[repr(transparent)] + struct T(usize); + mod a { + use super::T; + extern "C" { + fn transparent() -> T; + fn transparent_incorrect() -> T; + } + } + + mod b { + extern "C" { + // Shouldn't warn here, because repr(transparent) guarantees that T's layout is the + // same as just the usize. + fn transparent() -> usize; + + // Should warn, because there's a signedness conversion here: + fn transparent_incorrect() -> isize; + //~^ WARN `transparent_incorrect` redeclared with a different signature + } + } +} + +mod missing_return_type { + mod a { + extern "C" { + fn missing_return_type() -> usize; + } + } + + mod b { + extern "C" { + // This should output a warning because we can't assume that the first declaration is + // the correct one -- if this one is the correct one, then calling the usize-returning + // version would allow reads into uninitialised memory. + fn missing_return_type(); + //~^ WARN `missing_return_type` redeclared with a different signature + } + } +} + +mod non_zero_and_non_null { + mod a { + extern "C" { + fn non_zero_usize() -> core::num::NonZeroUsize; + fn non_null_ptr() -> core::ptr::NonNull; + } + } + mod b { + extern "C" { + // If there's a clash in either of these cases you're either gaining an incorrect + // invariant that the value is non-zero, or you're missing out on that invariant. Both + // cases are warning for, from both a caller-convenience and optimisation perspective. + fn non_zero_usize() -> usize; + //~^ WARN `non_zero_usize` redeclared with a different signature + fn non_null_ptr() -> *const usize; + //~^ WARN `non_null_ptr` redeclared with a different signature + } + } +} + +// See #75739 +mod non_zero_transparent { + mod a1 { + use std::num::NonZeroUsize; + extern "C" { + fn f1() -> NonZeroUsize; + } + } + + mod b1 { + #[repr(transparent)] + struct X(NonZeroUsize); + use std::num::NonZeroUsize; + extern "C" { + fn f1() -> X; + } + } + + mod a2 { + use std::num::NonZeroUsize; + extern "C" { + fn f2() -> NonZeroUsize; + } + } + + mod b2 { + #[repr(transparent)] + struct X1(NonZeroUsize); + + #[repr(transparent)] + struct X(X1); + + use std::num::NonZeroUsize; + extern "C" { + // Same case as above, but with two layers of newtyping. + fn f2() -> X; + } + } + + mod a3 { + #[repr(transparent)] + struct X(core::ptr::NonNull); + + use std::num::NonZeroUsize; + extern "C" { + fn f3() -> X; + } + } + + mod b3 { + extern "C" { + fn f3() -> core::ptr::NonNull; + } + } + + mod a4 { + #[repr(transparent)] + enum E { + X(std::num::NonZeroUsize), + } + extern "C" { + fn f4() -> E; + } + } + + mod b4 { + extern "C" { + fn f4() -> std::num::NonZeroUsize; + } + } +} + +mod null_optimised_enums { + mod a { + extern "C" { + fn option_non_zero_usize() -> usize; + fn option_non_zero_isize() -> isize; + fn option_non_null_ptr() -> *const usize; + + fn option_non_zero_usize_incorrect() -> usize; + fn option_non_null_ptr_incorrect() -> *const usize; + } + } + mod b { + extern "C" { + // This should be allowed, because these conversions are guaranteed to be FFI-safe (see + // #60300) + fn option_non_zero_usize() -> Option; + fn option_non_zero_isize() -> Option; + fn option_non_null_ptr() -> Option>; + + // However, these should be incorrect (note isize instead of usize) + fn option_non_zero_usize_incorrect() -> isize; + //~^ WARN `option_non_zero_usize_incorrect` redeclared with a different signature + fn option_non_null_ptr_incorrect() -> *const isize; + //~^ WARN `option_non_null_ptr_incorrect` redeclared with a different signature + } + } +} + +#[allow(improper_ctypes)] +mod unknown_layout { + mod a { + extern "C" { + pub fn generic(l: Link); + } + pub struct Link { + pub item: T, + pub next: *const Link, + } + } + + mod b { + extern "C" { + pub fn generic(l: Link); + } + pub struct Link { + pub item: T, + pub next: *const Link, + } + } +} + +mod hidden_niche { + mod a { + extern "C" { + fn hidden_niche_transparent() -> usize; + fn hidden_niche_transparent_no_niche() -> usize; + fn hidden_niche_unsafe_cell() -> usize; + } + } + mod b { + use std::cell::UnsafeCell; + use std::num::NonZeroUsize; + + #[repr(transparent)] + struct Transparent { x: NonZeroUsize } + + #[repr(transparent)] + struct TransparentNoNiche { y: UnsafeCell } + + extern "C" { + fn hidden_niche_transparent() -> Option; + + fn hidden_niche_transparent_no_niche() -> Option; + //~^ WARN redeclared with a different signature + //~| WARN block uses type `Option`, which is not FFI-safe + + fn hidden_niche_unsafe_cell() -> Option>; + //~^ WARN redeclared with a different signature + //~| WARN block uses type `Option>`, which is not FFI-safe + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr new file mode 100644 index 000000000..217eed6c9 --- /dev/null +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -0,0 +1,236 @@ +warning: `clash` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:14:13 + | +LL | fn clash(x: u8); + | ---------------- `clash` previously declared here +... +LL | fn clash(x: u64); + | ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8)` + found `unsafe extern "C" fn(u64)` +note: the lint level is defined here + --> $DIR/clashing-extern-fn.rs:4:9 + | +LL | #![warn(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `extern_link_name` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:52:9 + | +LL | / #[link_name = "extern_link_name"] +LL | | fn some_new_name(x: i16); + | |_____________________________- `extern_link_name` previously declared here +... +LL | fn extern_link_name(x: u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature + --> $DIR/clashing-extern-fn.rs:55:9 + | +LL | fn some_other_new_name(x: i16); + | ------------------------------- `some_other_new_name` previously declared here +... +LL | / #[link_name = "some_other_new_name"] +LL | | +LL | | fn some_other_extern_link_name(x: u32); + | |_______________________________________________^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +warning: `other_both_names_different` redeclares `link_name_same` with a different signature + --> $DIR/clashing-extern-fn.rs:59:9 + | +LL | / #[link_name = "link_name_same"] +LL | | fn both_names_different(x: i16); + | |____________________________________- `link_name_same` previously declared here +... +LL | / #[link_name = "link_name_same"] +LL | | +LL | | fn other_both_names_different(x: u32); + | |______________________________________________^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(i16)` + found `unsafe extern "C" fn(u32)` + +warning: `different_mod` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:72:9 + | +LL | fn different_mod(x: u8); + | ------------------------ `different_mod` previously declared here +... +LL | fn different_mod(x: u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8)` + found `unsafe extern "C" fn(u64)` + +warning: `variadic_decl` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:82:9 + | +LL | fn variadic_decl(x: u8, ...); + | ----------------------------- `variadic_decl` previously declared here +... +LL | fn variadic_decl(x: u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(u8, ...)` + found `unsafe extern "C" fn(u8)` + +warning: `weigh_banana` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:142:13 + | +LL | fn weigh_banana(count: *const Banana) -> u64; + | --------------------------------------------- `weigh_banana` previously declared here +... +LL | fn weigh_banana(count: *const Banana) -> u64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(*const one::Banana) -> u64` + found `unsafe extern "C" fn(*const three::Banana) -> u64` + +warning: `draw_point` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:171:13 + | +LL | fn draw_point(p: Point); + | ------------------------ `draw_point` previously declared here +... +LL | fn draw_point(p: Point); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(sameish_members::a::Point)` + found `unsafe extern "C" fn(sameish_members::b::Point)` + +warning: `origin` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:197:13 + | +LL | fn origin() -> Point3; + | ---------------------- `origin` previously declared here +... +LL | fn origin() -> Point3; + | ^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> same_sized_members_clash::a::Point3` + found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3` + +warning: `transparent_incorrect` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:220:13 + | +LL | fn transparent_incorrect() -> T; + | -------------------------------- `transparent_incorrect` previously declared here +... +LL | fn transparent_incorrect() -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> T` + found `unsafe extern "C" fn() -> isize` + +warning: `missing_return_type` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:238:13 + | +LL | fn missing_return_type() -> usize; + | ---------------------------------- `missing_return_type` previously declared here +... +LL | fn missing_return_type(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn()` + +warning: `non_zero_usize` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:256:13 + | +LL | fn non_zero_usize() -> core::num::NonZeroUsize; + | ----------------------------------------------- `non_zero_usize` previously declared here +... +LL | fn non_zero_usize() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> NonZeroUsize` + found `unsafe extern "C" fn() -> usize` + +warning: `non_null_ptr` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:258:13 + | +LL | fn non_null_ptr() -> core::ptr::NonNull; + | ----------------------------------------------- `non_null_ptr` previously declared here +... +LL | fn non_null_ptr() -> *const usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> NonNull` + found `unsafe extern "C" fn() -> *const usize` + +warning: `option_non_zero_usize_incorrect` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:356:13 + | +LL | fn option_non_zero_usize_incorrect() -> usize; + | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here +... +LL | fn option_non_zero_usize_incorrect() -> isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn() -> isize` + +warning: `option_non_null_ptr_incorrect` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:358:13 + | +LL | fn option_non_null_ptr_incorrect() -> *const usize; + | --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here +... +LL | fn option_non_null_ptr_incorrect() -> *const isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> *const usize` + found `unsafe extern "C" fn() -> *const isize` + +warning: `hidden_niche_transparent_no_niche` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:408:13 + | +LL | fn hidden_niche_transparent_no_niche() -> usize; + | ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here +... +LL | fn hidden_niche_transparent_no_niche() -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn() -> Option` + +warning: `hidden_niche_unsafe_cell` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:412:13 + | +LL | fn hidden_niche_unsafe_cell() -> usize; + | --------------------------------------- `hidden_niche_unsafe_cell` previously declared here +... +LL | fn hidden_niche_unsafe_cell() -> Option>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> usize` + found `unsafe extern "C" fn() -> Option>` + +warning: `extern` block uses type `Option`, which is not FFI-safe + --> $DIR/clashing-extern-fn.rs:408:55 + | +LL | fn hidden_niche_transparent_no_niche() -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + = note: `#[warn(improper_ctypes)]` on by default + +warning: `extern` block uses type `Option>`, which is not FFI-safe + --> $DIR/clashing-extern-fn.rs:412:46 + | +LL | fn hidden_niche_unsafe_cell() -> Option>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +warning: 19 warnings emitted + diff --git a/tests/ui/lint/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr new file mode 100644 index 000000000..d1c66a81c --- /dev/null +++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = help: the default ABI is C + = note: requested on the command line with `-F missing-abi` + +error: aborting due to previous error + diff --git a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr new file mode 100644 index 000000000..779c24c93 --- /dev/null +++ b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr @@ -0,0 +1,11 @@ +warning: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = help: the default ABI is C + = note: requested on the command line with `--force-warn missing-abi` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/cli-lint-override.rs b/tests/ui/lint/cli-lint-override.rs new file mode 100644 index 000000000..a0e853fc3 --- /dev/null +++ b/tests/ui/lint/cli-lint-override.rs @@ -0,0 +1,17 @@ +// Tests that subsequent lints specified via the command line override +// each other, except for ForceWarn and Forbid, which cannot be overridden. +// +// revisions: warn_deny forbid_warn force_warn_deny +// +//[warn_deny] compile-flags: --warn missing_abi --deny missing_abi +//[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi +//[force_warn_deny] compile-flags: --force-warn missing_abi --allow missing_abi +//[force_warn_deny] check-pass + + +extern fn foo() {} +//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated +//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated +//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated + +fn main() {} diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr new file mode 100644 index 000000000..f034cfa93 --- /dev/null +++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = help: the default ABI is C + = note: requested on the command line with `-D missing-abi` + +error: aborting due to previous error + diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/cli-unknown-force-warn.rs new file mode 100644 index 000000000..f3dea87a6 --- /dev/null +++ b/tests/ui/lint/cli-unknown-force-warn.rs @@ -0,0 +1,7 @@ +// Checks that rustc correctly errors when passed an invalid lint with +// `--force-warn`. This is a regression test for issue #86958. +// +// compile-flags: --force-warn foo-qux +// error-pattern: unknown lint: `foo_qux` + +fn main() {} diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr new file mode 100644 index 000000000..9ce9f405a --- /dev/null +++ b/tests/ui/lint/cli-unknown-force-warn.stderr @@ -0,0 +1,11 @@ +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warn foo_qux` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/command-line-lint-group-allow.rs b/tests/ui/lint/command-line-lint-group-allow.rs new file mode 100644 index 000000000..21c0df028 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-allow.rs @@ -0,0 +1,6 @@ +// compile-flags: -A bad-style +// check-pass + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/tests/ui/lint/command-line-lint-group-deny.rs b/tests/ui/lint/command-line-lint-group-deny.rs new file mode 100644 index 000000000..da999f33e --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-deny.rs @@ -0,0 +1,5 @@ +// compile-flags: -D bad-style + +fn main() { + let _InappropriateCamelCasing = true; //~ ERROR should have a snake +} diff --git a/tests/ui/lint/command-line-lint-group-deny.stderr b/tests/ui/lint/command-line-lint-group-deny.stderr new file mode 100644 index 000000000..04c3f6f26 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-deny.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name + --> $DIR/command-line-lint-group-deny.rs:4:9 + | +LL | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing` + | + = note: `-D non-snake-case` implied by `-D bad-style` + +error: aborting due to previous error + diff --git a/tests/ui/lint/command-line-lint-group-forbid.rs b/tests/ui/lint/command-line-lint-group-forbid.rs new file mode 100644 index 000000000..4e5c2aca5 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-forbid.rs @@ -0,0 +1,5 @@ +// compile-flags: -F bad-style + +fn main() { + let _InappropriateCamelCasing = true; //~ ERROR should have a snake +} diff --git a/tests/ui/lint/command-line-lint-group-forbid.stderr b/tests/ui/lint/command-line-lint-group-forbid.stderr new file mode 100644 index 000000000..736782140 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-forbid.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name + --> $DIR/command-line-lint-group-forbid.rs:4:9 + | +LL | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing` + | + = note: `-F non-snake-case` implied by `-F bad-style` + +error: aborting due to previous error + diff --git a/tests/ui/lint/command-line-lint-group-warn.rs b/tests/ui/lint/command-line-lint-group-warn.rs new file mode 100644 index 000000000..f4536f9c9 --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-warn.rs @@ -0,0 +1,7 @@ +// compile-flags: -W bad-style +// check-pass + +fn main() { + let _InappropriateCamelCasing = true; + //~^ WARNING should have a snake case name +} diff --git a/tests/ui/lint/command-line-lint-group-warn.stderr b/tests/ui/lint/command-line-lint-group-warn.stderr new file mode 100644 index 000000000..e9c80b4ef --- /dev/null +++ b/tests/ui/lint/command-line-lint-group-warn.stderr @@ -0,0 +1,10 @@ +warning: variable `_InappropriateCamelCasing` should have a snake case name + --> $DIR/command-line-lint-group-warn.rs:5:9 + | +LL | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing` + | + = note: `-W non-snake-case` implied by `-W bad-style` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/command-line-register-lint-tool.rs b/tests/ui/lint/command-line-register-lint-tool.rs new file mode 100644 index 000000000..d6e95fd3e --- /dev/null +++ b/tests/ui/lint/command-line-register-lint-tool.rs @@ -0,0 +1,7 @@ +// compile-flags: -A known_tool::foo +// check-pass + +#![feature(register_tool)] +#![register_tool(known_tool)] + +fn main() {} diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.rs b/tests/ui/lint/command-line-register-unknown-lint-tool.rs new file mode 100644 index 000000000..59fc02000 --- /dev/null +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.rs @@ -0,0 +1,4 @@ +// compile-flags: -A unknown_tool::foo +// error-pattern: unknown lint tool: `unknown_tool` + +fn main() {} diff --git a/tests/ui/lint/command-line-register-unknown-lint-tool.stderr b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr new file mode 100644 index 000000000..c9a2aff21 --- /dev/null +++ b/tests/ui/lint/command-line-register-unknown-lint-tool.stderr @@ -0,0 +1,11 @@ +error[E0602]: unknown lint tool: `unknown_tool` + | + = note: requested on the command line with `-A unknown_tool::foo` + +error[E0602]: unknown lint tool: `unknown_tool` + | + = note: requested on the command line with `-A unknown_tool::foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/crate_level_only_lint.rs b/tests/ui/lint/crate_level_only_lint.rs new file mode 100644 index 000000000..d9673faa2 --- /dev/null +++ b/tests/ui/lint/crate_level_only_lint.rs @@ -0,0 +1,22 @@ +#![deny(uncommon_codepoints, unused_attributes)] + +mod foo { +#![allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] + +#[allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +const BAR: f64 = 0.000001; + +} + +#[allow(uncommon_codepoints)] +//~^ ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +//~| ERROR allow(uncommon_codepoints) is ignored unless specified at crate level [unused_attributes] +fn main() { +} diff --git a/tests/ui/lint/crate_level_only_lint.stderr b/tests/ui/lint/crate_level_only_lint.stderr new file mode 100644 index 000000000..8fb06df2a --- /dev/null +++ b/tests/ui/lint/crate_level_only_lint.stderr @@ -0,0 +1,62 @@ +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/crate_level_only_lint.rs:1:30 + | +LL | #![deny(uncommon_codepoints, unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:4:10 + | +LL | #![allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:9:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: allow(uncommon_codepoints) is ignored unless specified at crate level + --> $DIR/crate_level_only_lint.rs:17:9 + | +LL | #[allow(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/dead-code/alias-in-pat.rs b/tests/ui/lint/dead-code/alias-in-pat.rs new file mode 100644 index 000000000..69d455f3b --- /dev/null +++ b/tests/ui/lint/dead-code/alias-in-pat.rs @@ -0,0 +1,10 @@ +// run-pass + +#![deny(dead_code)] + +fn main() { + struct Foo { x: T } + type Bar = Foo; + let spam = |Bar { x }| x != 0; + println!("{}", spam(Foo { x: 10 })); +} diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs new file mode 100644 index 000000000..d3e39c0de --- /dev/null +++ b/tests/ui/lint/dead-code/anon-const-in-pat.rs @@ -0,0 +1,45 @@ +// check-pass +#![feature(inline_const_pat)] +#![allow(incomplete_features)] +#![deny(dead_code)] + +const fn one() -> i32 { + 1 +} + +const fn two() -> i32 { + 2 +} + +const fn three() -> i32 { + 3 +} + +fn inline_const() { + // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern + match 1 { + const { one() } => {} + _ => {} + } +} + +fn inline_const_range() { + match 1 { + 1 ..= const { two() } => {} + _ => {} + } +} + +struct S; + +fn const_generic_arg() { + match S::<3> { + S::<{three()}> => {} + } +} + +fn main() { + inline_const(); + inline_const_range(); + const_generic_arg(); +} diff --git a/tests/ui/lint/dead-code/associated-type.rs b/tests/ui/lint/dead-code/associated-type.rs new file mode 100644 index 000000000..1cf66e75a --- /dev/null +++ b/tests/ui/lint/dead-code/associated-type.rs @@ -0,0 +1,19 @@ +// run-pass + +#![deny(dead_code)] + +trait Foo { + type Bar; +} + +struct Used; + +struct Ex; + +impl Foo for Ex { + type Bar = Used; +} + +pub fn main() { + let _x = Ex; +} diff --git a/tests/ui/lint/dead-code/basic.rs b/tests/ui/lint/dead-code/basic.rs new file mode 100644 index 000000000..3b8ffd58c --- /dev/null +++ b/tests/ui/lint/dead-code/basic.rs @@ -0,0 +1,15 @@ +#![deny(dead_code)] +#![allow(unreachable_code)] + +fn foo() { //~ ERROR function `foo` is never used + + // none of these should have any dead_code exposed to the user + panic!(); + + panic!("foo"); + + panic!("bar {}", "baz") +} + + +fn main() {} diff --git a/tests/ui/lint/dead-code/basic.stderr b/tests/ui/lint/dead-code/basic.stderr new file mode 100644 index 000000000..7d068cead --- /dev/null +++ b/tests/ui/lint/dead-code/basic.stderr @@ -0,0 +1,14 @@ +error: function `foo` is never used + --> $DIR/basic.rs:4:4 + | +LL | fn foo() { + | ^^^ + | +note: the lint level is defined here + --> $DIR/basic.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/closure-bang.rs b/tests/ui/lint/dead-code/closure-bang.rs new file mode 100644 index 000000000..8e8636b11 --- /dev/null +++ b/tests/ui/lint/dead-code/closure-bang.rs @@ -0,0 +1,9 @@ +// ignore-test FIXME(#20574) + +#![deny(unreachable_code)] + +fn main() { + let x = || panic!(); + x(); + println!("Foo bar"); //~ ERROR: unreachable statement +} diff --git a/tests/ui/lint/dead-code/const-and-self.rs b/tests/ui/lint/dead-code/const-and-self.rs new file mode 100644 index 000000000..5c96e4d0e --- /dev/null +++ b/tests/ui/lint/dead-code/const-and-self.rs @@ -0,0 +1,54 @@ +// check-pass + +#![warn(dead_code)] + +const TLC: usize = 4; + +trait Tr { fn doit(&self); } + +impl Tr for [usize; TLC] { + fn doit(&self) { + println!("called 4"); + } +} + +struct X; +struct Y; +struct Z; + +trait Foo { + type Ty; + fn foo() -> Self::Ty; +} + +impl Foo for X { + type Ty = Z; + fn foo() -> Self::Ty { + unimplemented!() + } +} + +enum E { + A, + B, //~ WARN variants `B` and `C` are never constructed + C, +} + +type F = E; + +impl E { + fn check(&self) -> bool { + match self { + Self::A => true, + Self::B => false, + F::C => false, + } + } +} + +fn main() { + let s = [0,1,2,3]; + s.doit(); + X::foo(); + E::A.check(); +} diff --git a/tests/ui/lint/dead-code/const-and-self.stderr b/tests/ui/lint/dead-code/const-and-self.stderr new file mode 100644 index 000000000..9d1d7d6ec --- /dev/null +++ b/tests/ui/lint/dead-code/const-and-self.stderr @@ -0,0 +1,19 @@ +warning: variants `B` and `C` are never constructed + --> $DIR/const-and-self.rs:33:5 + | +LL | enum E { + | - variants in this enum +LL | A, +LL | B, + | ^ +LL | C, + | ^ + | +note: the lint level is defined here + --> $DIR/const-and-self.rs:3:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/dead-code/empty-unused-enum.rs b/tests/ui/lint/dead-code/empty-unused-enum.rs new file mode 100644 index 000000000..864501e94 --- /dev/null +++ b/tests/ui/lint/dead-code/empty-unused-enum.rs @@ -0,0 +1,5 @@ +#![deny(unused)] + +enum E {} //~ ERROR enum `E` is never used + +fn main() {} diff --git a/tests/ui/lint/dead-code/empty-unused-enum.stderr b/tests/ui/lint/dead-code/empty-unused-enum.stderr new file mode 100644 index 000000000..6391f0941 --- /dev/null +++ b/tests/ui/lint/dead-code/empty-unused-enum.stderr @@ -0,0 +1,15 @@ +error: enum `E` is never used + --> $DIR/empty-unused-enum.rs:3:6 + | +LL | enum E {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/empty-unused-public-enum.rs b/tests/ui/lint/dead-code/empty-unused-public-enum.rs new file mode 100644 index 000000000..15b04496b --- /dev/null +++ b/tests/ui/lint/dead-code/empty-unused-public-enum.rs @@ -0,0 +1,6 @@ +// build-pass +#![deny(unused)] + +pub enum E {} + +fn main() {} diff --git a/tests/ui/lint/dead-code/enum-variants.rs b/tests/ui/lint/dead-code/enum-variants.rs new file mode 100644 index 000000000..91c97232e --- /dev/null +++ b/tests/ui/lint/dead-code/enum-variants.rs @@ -0,0 +1,14 @@ +// run-pass + +#![deny(dead_code)] + +enum Foo { + A, + B, +} + +pub fn main() { + match Foo::A { + Foo::A | Foo::B => Foo::B + }; +} diff --git a/tests/ui/lint/dead-code/impl-trait.rs b/tests/ui/lint/dead-code/impl-trait.rs new file mode 100644 index 000000000..757b8f83e --- /dev/null +++ b/tests/ui/lint/dead-code/impl-trait.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] + +trait Trait { + type Type; +} + +impl Trait for () { + type Type = (); +} + +type Used = (); +type Unused = (); //~ ERROR type alias `Unused` is never used + +fn foo() -> impl Trait {} + +fn main() { + foo(); +} diff --git a/tests/ui/lint/dead-code/impl-trait.stderr b/tests/ui/lint/dead-code/impl-trait.stderr new file mode 100644 index 000000000..e35e13a9e --- /dev/null +++ b/tests/ui/lint/dead-code/impl-trait.stderr @@ -0,0 +1,14 @@ +error: type alias `Unused` is never used + --> $DIR/impl-trait.rs:12:6 + | +LL | type Unused = (); + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/impl-trait.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/issue-68408-false-positive.rs b/tests/ui/lint/dead-code/issue-68408-false-positive.rs new file mode 100644 index 000000000..7ee6b5d72 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-68408-false-positive.rs @@ -0,0 +1,22 @@ +// check-pass + +// Make sure we don't have any false positives here. + +#![deny(dead_code)] + +enum X { + A { _a: () }, + B { _b: () }, +} +impl X { + fn a() -> X { + X::A { _a: () } + } + fn b() -> Self { + Self::B { _b: () } + } +} + +fn main() { + let (_, _) = (X::a(), X::b()); +} diff --git a/tests/ui/lint/dead-code/issue-85071-2.rs b/tests/ui/lint/dead-code/issue-85071-2.rs new file mode 100644 index 000000000..f0639931c --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071-2.rs @@ -0,0 +1,22 @@ +// A slight variation of issue-85071.rs. Here, a method is called instead +// of a function, and the warning is about an unreachable definition +// instead of an unreachable expression. + +// check-pass + +#![warn(unused_variables,unreachable_code)] + +enum Foo {} + +struct S; +impl S { + fn f(&self) -> Foo {todo!()} +} + +fn main() { + let s = S; + let x = s.f(); + //~^ WARNING: unused variable: `x` + let _y = x; + //~^ WARNING: unreachable definition +} diff --git a/tests/ui/lint/dead-code/issue-85071-2.stderr b/tests/ui/lint/dead-code/issue-85071-2.stderr new file mode 100644 index 000000000..5e963183d --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071-2.stderr @@ -0,0 +1,34 @@ +warning: unreachable definition + --> $DIR/issue-85071-2.rs:20:9 + | +LL | let x = s.f(); + | ----- any code following this expression is unreachable +LL | +LL | let _y = x; + | ^^ unreachable definition + | +note: this expression has type `Foo`, which is uninhabited + --> $DIR/issue-85071-2.rs:18:13 + | +LL | let x = s.f(); + | ^^^^^ +note: the lint level is defined here + --> $DIR/issue-85071-2.rs:7:26 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unused variable: `x` + --> $DIR/issue-85071-2.rs:18:9 + | +LL | let x = s.f(); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/issue-85071-2.rs:7:9 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/dead-code/issue-85071.rs b/tests/ui/lint/dead-code/issue-85071.rs new file mode 100644 index 000000000..d6969321c --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071.rs @@ -0,0 +1,19 @@ +// Checks that an unreachable code warning is emitted when an expression is +// preceded by an expression with an uninhabited type. Previously, the +// variable liveness analysis was "smarter" than the reachability analysis +// in this regard, which led to confusing "unused variable" warnings +// without an accompanying explanatory "unreachable expression" warning. + +// check-pass + +#![warn(unused_variables,unreachable_code)] + +enum Foo {} +fn f() -> Foo {todo!()} + +fn main() { + let x = f(); + //~^ WARNING: unused variable: `x` + let _ = x; + //~^ WARNING: unreachable expression +} diff --git a/tests/ui/lint/dead-code/issue-85071.stderr b/tests/ui/lint/dead-code/issue-85071.stderr new file mode 100644 index 000000000..721fb8148 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85071.stderr @@ -0,0 +1,34 @@ +warning: unreachable expression + --> $DIR/issue-85071.rs:17:13 + | +LL | let x = f(); + | --- any code following this expression is unreachable +LL | +LL | let _ = x; + | ^ unreachable expression + | +note: this expression has type `Foo`, which is uninhabited + --> $DIR/issue-85071.rs:15:13 + | +LL | let x = f(); + | ^^^ +note: the lint level is defined here + --> $DIR/issue-85071.rs:9:26 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unused variable: `x` + --> $DIR/issue-85071.rs:15:9 + | +LL | let x = f(); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/issue-85071.rs:9:9 + | +LL | #![warn(unused_variables,unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/dead-code/issue-85255.rs b/tests/ui/lint/dead-code/issue-85255.rs new file mode 100644 index 000000000..043f68137 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85255.rs @@ -0,0 +1,50 @@ +// Unused `pub` fields in non-`pub` structs should also trigger dead code warnings. +// check-pass + +#![warn(dead_code)] + +struct Foo { + a: i32, //~ WARNING: fields `a` and `b` are never read + pub b: i32, +} + +struct Bar; + +impl Bar { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used +} + +pub(crate) struct Foo1 { + a: i32, //~ WARNING: fields `a` and `b` are never read + pub b: i32, +} + +pub(crate) struct Bar1; + +impl Bar1 { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used +} + +pub(crate) struct Foo2 { + a: i32, //~ WARNING: fields `a` and `b` are never read + pub b: i32, +} + +pub(crate) struct Bar2; + +impl Bar2 { + fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used + pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used +} + + +fn main() { + let _ = Foo { a: 1, b: 2 }; + let _ = Bar; + let _ = Foo1 { a: 1, b: 2 }; + let _ = Bar1; + let _ = Foo2 { a: 1, b: 2 }; + let _ = Bar2; +} diff --git a/tests/ui/lint/dead-code/issue-85255.stderr b/tests/ui/lint/dead-code/issue-85255.stderr new file mode 100644 index 000000000..3497b952f --- /dev/null +++ b/tests/ui/lint/dead-code/issue-85255.stderr @@ -0,0 +1,74 @@ +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:7:5 + | +LL | struct Foo { + | --- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + | +note: the lint level is defined here + --> $DIR/issue-85255.rs:4:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:19:5 + | +LL | pub(crate) struct Foo1 { + | ---- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + +warning: fields `a` and `b` are never read + --> $DIR/issue-85255.rs:31:5 + | +LL | pub(crate) struct Foo2 { + | ---- fields in this struct +LL | a: i32, + | ^ +LL | pub b: i32, + | ^ + +warning: associated function `a` is never used + --> $DIR/issue-85255.rs:14:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function `b` is never used + --> $DIR/issue-85255.rs:15:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: associated function `a` is never used + --> $DIR/issue-85255.rs:26:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function `b` is never used + --> $DIR/issue-85255.rs:27:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: associated function `a` is never used + --> $DIR/issue-85255.rs:38:8 + | +LL | fn a(&self) -> i32 { 5 } + | ^ + +warning: associated function `b` is never used + --> $DIR/issue-85255.rs:39:12 + | +LL | pub fn b(&self) -> i32 { 6 } + | ^ + +warning: 9 warnings emitted + diff --git a/tests/ui/lint/dead-code/leading-underscore.rs b/tests/ui/lint/dead-code/leading-underscore.rs new file mode 100644 index 000000000..d3582961b --- /dev/null +++ b/tests/ui/lint/dead-code/leading-underscore.rs @@ -0,0 +1,31 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![deny(dead_code)] + +static _X: usize = 0; + +fn _foo() {} + +struct _Y { + _z: usize, +} + +enum _Z {} + +impl _Y { + fn _bar() {} +} + +type _A = isize; + +mod _bar { + fn _qux() {} +} + +extern "C" { + #[link_name = "abort"] + fn _abort() -> !; +} + +pub fn main() {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs new file mode 100644 index 000000000..8f5a4c41e --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs @@ -0,0 +1,110 @@ +#![no_std] +#![allow(unused_variables)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] +#![deny(dead_code)] + +#![crate_type="lib"] + +pub use foo2::Bar2; + +mod foo { + pub struct Bar; //~ ERROR: struct `Bar` is never constructed +} + +mod foo2 { + pub struct Bar2; +} + +pub static pub_static: isize = 0; +static priv_static: isize = 0; //~ ERROR: static `priv_static` is never used +const used_static: isize = 0; +pub static used_static2: isize = used_static; +const USED_STATIC: isize = 0; +const STATIC_USED_IN_ENUM_DISCRIMINANT: isize = 10; + +pub const pub_const: isize = 0; +const priv_const: isize = 0; //~ ERROR: constant `priv_const` is never used +const used_const: isize = 0; +pub const used_const2: isize = used_const; +const USED_CONST: isize = 1; +const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11; + +pub type typ = *const UsedStruct4; +pub struct PubStruct; +struct PrivStruct; //~ ERROR: struct `PrivStruct` is never constructed +struct UsedStruct1 { + #[allow(dead_code)] + x: isize +} +struct UsedStruct2(isize); +struct UsedStruct3; +pub struct UsedStruct4; +// this struct is never used directly, but its method is, so we don't want +// to warn it +struct SemiUsedStruct; +impl SemiUsedStruct { + fn la_la_la() {} +} +struct StructUsedAsField; +pub struct StructUsedInEnum; +struct StructUsedInGeneric; +pub struct PubStruct2 { + #[allow(dead_code)] + struct_used_as_field: *const StructUsedAsField +} + +pub enum pub_enum { foo1, bar1 } +pub enum pub_enum2 { a(*const StructUsedInEnum) } +pub enum pub_enum3 { + Foo = STATIC_USED_IN_ENUM_DISCRIMINANT, + Bar = CONST_USED_IN_ENUM_DISCRIMINANT, +} + +enum priv_enum { foo2, bar2 } //~ ERROR: enum `priv_enum` is never used +enum used_enum { + foo3, + bar3 //~ ERROR variant `bar3` is never constructed +} + +fn f() {} + +pub fn pub_fn() { + used_fn(); + let used_struct1 = UsedStruct1 { x: 1 }; + let used_struct2 = UsedStruct2(1); + let used_struct3 = UsedStruct3; + let e = used_enum::foo3; + SemiUsedStruct::la_la_la(); + + let i = 1; + match i { + USED_STATIC => (), + USED_CONST => (), + _ => () + } + f::(); +} +fn priv_fn() { //~ ERROR: function `priv_fn` is never used + let unused_struct = PrivStruct; +} +fn used_fn() {} + +fn foo() { //~ ERROR: function `foo` is never used + bar(); + let unused_enum = priv_enum::foo2; +} + +fn bar() { //~ ERROR: function `bar` is never used + foo(); +} + +fn baz() -> impl Copy { //~ ERROR: function `baz` is never used + "I'm unused, too" +} + +// Code with #[allow(dead_code)] should be marked live (and thus anything it +// calls is marked live) +#[allow(dead_code)] +fn g() { h(); } +fn h() {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr new file mode 100644 index 000000000..eb728b5b9 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr @@ -0,0 +1,71 @@ +error: static `priv_static` is never used + --> $DIR/lint-dead-code-1.rs:20:8 + | +LL | static priv_static: isize = 0; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-1.rs:5:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: constant `priv_const` is never used + --> $DIR/lint-dead-code-1.rs:27:7 + | +LL | const priv_const: isize = 0; + | ^^^^^^^^^^ + +error: struct `PrivStruct` is never constructed + --> $DIR/lint-dead-code-1.rs:35:8 + | +LL | struct PrivStruct; + | ^^^^^^^^^^ + +error: enum `priv_enum` is never used + --> $DIR/lint-dead-code-1.rs:64:6 + | +LL | enum priv_enum { foo2, bar2 } + | ^^^^^^^^^ + +error: variant `bar3` is never constructed + --> $DIR/lint-dead-code-1.rs:67:5 + | +LL | enum used_enum { + | --------- variant in this enum +LL | foo3, +LL | bar3 + | ^^^^ + +error: function `priv_fn` is never used + --> $DIR/lint-dead-code-1.rs:88:4 + | +LL | fn priv_fn() { + | ^^^^^^^ + +error: function `foo` is never used + --> $DIR/lint-dead-code-1.rs:93:4 + | +LL | fn foo() { + | ^^^ + +error: function `bar` is never used + --> $DIR/lint-dead-code-1.rs:98:4 + | +LL | fn bar() { + | ^^^ + +error: function `baz` is never used + --> $DIR/lint-dead-code-1.rs:102:4 + | +LL | fn baz() -> impl Copy { + | ^^^ + +error: struct `Bar` is never constructed + --> $DIR/lint-dead-code-1.rs:12:16 + | +LL | pub struct Bar; + | ^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-2.rs b/tests/ui/lint/dead-code/lint-dead-code-2.rs new file mode 100644 index 000000000..6bfa4d96f --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-2.rs @@ -0,0 +1,41 @@ +#![allow(unused_variables)] +#![deny(dead_code)] +#![feature(rustc_attrs, start)] + +struct Foo; + +trait Bar { + fn bar1(&self); + fn bar2(&self) { + self.bar1(); + } +} + +impl Bar for Foo { + fn bar1(&self) { + live_fn(); + } +} + +fn live_fn() {} + +fn dead_fn() {} //~ ERROR: function `dead_fn` is never used + +#[rustc_main] +fn dead_fn2() {} //~ ERROR: function `dead_fn2` is never used + +fn used_fn() {} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + used_fn(); + let foo = Foo; + foo.bar2(); + 0 +} + +// this is not main +fn main() { //~ ERROR: function `main` is never used + dead_fn(); + dead_fn2(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-2.stderr b/tests/ui/lint/dead-code/lint-dead-code-2.stderr new file mode 100644 index 000000000..85af553c9 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-2.stderr @@ -0,0 +1,26 @@ +error: function `dead_fn` is never used + --> $DIR/lint-dead-code-2.rs:22:4 + | +LL | fn dead_fn() {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-2.rs:2:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `dead_fn2` is never used + --> $DIR/lint-dead-code-2.rs:25:4 + | +LL | fn dead_fn2() {} + | ^^^^^^^^ + +error: function `main` is never used + --> $DIR/lint-dead-code-2.rs:38:4 + | +LL | fn main() { + | ^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.rs b/tests/ui/lint/dead-code/lint-dead-code-3.rs new file mode 100644 index 000000000..293fcdbc5 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-3.rs @@ -0,0 +1,90 @@ +#![allow(unused_variables)] +#![allow(non_camel_case_types)] +#![allow(clashing_extern_declarations)] +#![deny(dead_code)] + +#![crate_type="lib"] + + +pub use extern_foo as x; +extern "C" { + pub fn extern_foo(); +} + +struct Foo; //~ ERROR: struct `Foo` is never constructed +impl Foo { + fn foo(&self) { //~ ERROR: associated function `foo` is never used + bar() + } +} + +fn bar() { //~ ERROR: function `bar` is never used + fn baz() {} + + Foo.foo(); + baz(); +} + +// no warning +struct Foo2; +impl Foo2 { fn foo2(&self) { bar2() } } +fn bar2() { + fn baz2() {} + + Foo2.foo2(); + baz2(); +} + +pub fn pub_fn() { + let foo2_struct = Foo2; + foo2_struct.foo2(); + + blah::baz(); +} + +mod blah { + // not warned because it's used in the parameter of `free` and return of + // `malloc` below, which are also used. + enum c_void {} + + extern "C" { + fn free(p: *const c_void); + fn malloc(size: usize) -> *const c_void; + } + + pub fn baz() { + unsafe { free(malloc(4)); } + } +} + +enum c_void {} //~ ERROR: enum `c_void` is never used +extern "C" { + fn free(p: *const c_void); //~ ERROR: function `free` is never used +} + +// Check provided method +mod inner { + pub trait Trait { + fn f(&self) { f(); } + } + + impl Trait for isize {} + + fn f() {} +} + +fn anon_const() -> [(); { + fn blah() {} //~ ERROR: function `blah` is never used + 1 +}] { + [(); { + fn blah() {} //~ ERROR: function `blah` is never used + 1 + }] +} + +pub fn foo() { + let a: &dyn inner::Trait = &1_isize; + a.f(); + anon_const(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.stderr b/tests/ui/lint/dead-code/lint-dead-code-3.stderr new file mode 100644 index 000000000..26fc13bae --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-3.stderr @@ -0,0 +1,50 @@ +error: struct `Foo` is never constructed + --> $DIR/lint-dead-code-3.rs:14:8 + | +LL | struct Foo; + | ^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-3.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `bar` is never used + --> $DIR/lint-dead-code-3.rs:21:4 + | +LL | fn bar() { + | ^^^ + +error: enum `c_void` is never used + --> $DIR/lint-dead-code-3.rs:60:6 + | +LL | enum c_void {} + | ^^^^^^ + +error: function `blah` is never used + --> $DIR/lint-dead-code-3.rs:77:8 + | +LL | fn blah() {} + | ^^^^ + +error: function `blah` is never used + --> $DIR/lint-dead-code-3.rs:81:12 + | +LL | fn blah() {} + | ^^^^ + +error: associated function `foo` is never used + --> $DIR/lint-dead-code-3.rs:16:8 + | +LL | fn foo(&self) { + | ^^^ + +error: function `free` is never used + --> $DIR/lint-dead-code-3.rs:62:8 + | +LL | fn free(p: *const c_void); + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-4.rs b/tests/ui/lint/dead-code/lint-dead-code-4.rs new file mode 100644 index 000000000..0fc6c6156 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-4.rs @@ -0,0 +1,83 @@ +#![allow(unused_variables)] +#![allow(non_camel_case_types)] +#![deny(dead_code)] + +struct Foo { + x: usize, + b: bool, //~ ERROR: field `b` is never read +} + +fn field_read(f: Foo) -> usize { + f.x.pow(2) +} + +enum XYZ { + X, //~ ERROR variants `X` and `Y` are never constructed + Y { + a: String, + b: i32, + c: i32, + }, + Z +} + +enum ABC { //~ ERROR enum `ABC` is never used + A, + B { + a: String, + b: i32, + c: i32, + }, + C +} + +// ensure struct variants get warning for their fields +enum IJK { + I, //~ ERROR variants `I` and `K` are never constructed + J { + a: String, + b: i32, //~ ERROR fields `b` and `c` are never read + c: i32, + }, + K + +} + +fn struct_variant_partial_use(b: IJK) -> String { + match b { + IJK::J { a, b: _, .. } => a, + _ => "".to_string() + } +} + +fn field_match_in_patterns(b: XYZ) -> String { + match b { + XYZ::Y { a, b: _, .. } => a, + _ => "".to_string() + } +} + +struct Bar { + x: usize, //~ ERROR: fields `x` and `c` are never read + b: bool, + c: bool, + _guard: () +} + +#[repr(C)] +struct Baz { + x: u32, +} + +fn field_match_in_let(f: Bar) -> bool { + let Bar { b, c: _, .. } = f; + b +} + +fn main() { + field_read(Foo { x: 1, b: false }); + field_match_in_patterns(XYZ::Z); + struct_variant_partial_use(IJK::J { a: "".into(), b: 1, c: -1 }); + field_match_in_let(Bar { x: 42, b: true, c: false, _guard: () }); + let _ = Baz { x: 0 }; +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-4.stderr b/tests/ui/lint/dead-code/lint-dead-code-4.stderr new file mode 100644 index 000000000..668c1dacf --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-4.stderr @@ -0,0 +1,66 @@ +error: field `b` is never read + --> $DIR/lint-dead-code-4.rs:7:5 + | +LL | struct Foo { + | --- field in this struct +LL | x: usize, +LL | b: bool, + | ^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-4.rs:3:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: variants `X` and `Y` are never constructed + --> $DIR/lint-dead-code-4.rs:15:5 + | +LL | enum XYZ { + | --- variants in this enum +LL | X, + | ^ +LL | Y { + | ^ + +error: enum `ABC` is never used + --> $DIR/lint-dead-code-4.rs:24:6 + | +LL | enum ABC { + | ^^^ + +error: fields `b` and `c` are never read + --> $DIR/lint-dead-code-4.rs:39:9 + | +LL | J { + | - fields in this variant +LL | a: String, +LL | b: i32, + | ^ +LL | c: i32, + | ^ + +error: variants `I` and `K` are never constructed + --> $DIR/lint-dead-code-4.rs:36:5 + | +LL | enum IJK { + | --- variants in this enum +LL | I, + | ^ +... +LL | K + | ^ + +error: fields `x` and `c` are never read + --> $DIR/lint-dead-code-4.rs:61:5 + | +LL | struct Bar { + | --- fields in this struct +LL | x: usize, + | ^ +LL | b: bool, +LL | c: bool, + | ^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-5.rs b/tests/ui/lint/dead-code/lint-dead-code-5.rs new file mode 100644 index 000000000..ed90fb464 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-5.rs @@ -0,0 +1,50 @@ +#![allow(unused_variables)] +#![deny(dead_code)] + +enum Enum1 { + Variant1(isize), + Variant2 //~ ERROR: variant `Variant2` is never constructed +} + +enum Enum2 { + Variant3(bool), + #[allow(dead_code)] + Variant4(isize), + Variant5 { _x: isize }, //~ ERROR: variants `Variant5` and `Variant6` are never constructed + Variant6(isize), + _Variant7, + Variant8 { _field: bool }, + Variant9, + Variant10(usize) +} + +impl Enum2 { + fn new_variant8() -> Enum2 { + Self::Variant8 { _field: true } + } + + fn new_variant9() -> Enum2 { + Self::Variant9 + } + + fn new_variant10() -> Enum2 { + Self::Variant10(10) + } +} + +enum Enum3 { //~ ERROR: enum `Enum3` is never used + Variant8, + Variant9 +} + +fn main() { + let v = Enum1::Variant1(1); + match v { + Enum1::Variant1(_) => (), + Enum1::Variant2 => () + } + let x = Enum2::Variant3(true); + let _ = Enum2::new_variant8(); + let _ = Enum2::new_variant9(); + let _ = Enum2::new_variant10(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-5.stderr b/tests/ui/lint/dead-code/lint-dead-code-5.stderr new file mode 100644 index 000000000..eaf43e453 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-5.stderr @@ -0,0 +1,34 @@ +error: variant `Variant2` is never constructed + --> $DIR/lint-dead-code-5.rs:6:5 + | +LL | enum Enum1 { + | ----- variant in this enum +LL | Variant1(isize), +LL | Variant2 + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-5.rs:2:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: variants `Variant5` and `Variant6` are never constructed + --> $DIR/lint-dead-code-5.rs:13:5 + | +LL | enum Enum2 { + | ----- variants in this enum +... +LL | Variant5 { _x: isize }, + | ^^^^^^^^ +LL | Variant6(isize), + | ^^^^^^^^ + +error: enum `Enum3` is never used + --> $DIR/lint-dead-code-5.rs:35:6 + | +LL | enum Enum3 { + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/lint-dead-code-6.rs b/tests/ui/lint/dead-code/lint-dead-code-6.rs new file mode 100644 index 000000000..e3074acf1 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-6.rs @@ -0,0 +1,20 @@ +#![deny(dead_code)] + +struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed +impl UnusedStruct { + fn unused_impl_fn_1() { //~ ERROR associated function `unused_impl_fn_1` is never used + println!("blah"); + } + + fn unused_impl_fn_2(var: i32) { //~ ERROR associated function `unused_impl_fn_2` is never used + println!("foo {}", var); + } + + fn unused_impl_fn_3( //~ ERROR associated function `unused_impl_fn_3` is never used + var: i32, + ) { + println!("bar {}", var); + } +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/lint-dead-code-6.stderr b/tests/ui/lint/dead-code/lint-dead-code-6.stderr new file mode 100644 index 000000000..f9d83308a --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-6.stderr @@ -0,0 +1,32 @@ +error: struct `UnusedStruct` is never constructed + --> $DIR/lint-dead-code-6.rs:3:8 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-6.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: associated function `unused_impl_fn_1` is never used + --> $DIR/lint-dead-code-6.rs:5:8 + | +LL | fn unused_impl_fn_1() { + | ^^^^^^^^^^^^^^^^ + +error: associated function `unused_impl_fn_2` is never used + --> $DIR/lint-dead-code-6.rs:9:8 + | +LL | fn unused_impl_fn_2(var: i32) { + | ^^^^^^^^^^^^^^^^ + +error: associated function `unused_impl_fn_3` is never used + --> $DIR/lint-dead-code-6.rs:13:8 + | +LL | fn unused_impl_fn_3( + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs new file mode 100644 index 000000000..2003e1e29 --- /dev/null +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs @@ -0,0 +1,29 @@ +#![warn(dead_code)] + +struct Bar { + #[allow(dead_code)] + a: usize, + #[forbid(dead_code)] + b: usize, //~ ERROR field `b` is never read + #[deny(dead_code)] + c: usize, //~ ERROR fields `c` and `e` are never read + d: usize, //~ WARN fields `d`, `f`, and `g` are never read + #[deny(dead_code)] + e: usize, + f: usize, + g: usize, + _h: usize, +} + +fn main() { + Bar { + a: 1, + b: 1, + c: 1, + d: 1, + e: 1, + f: 1, + g: 1, + _h: 1, + }; +} diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr new file mode 100644 index 000000000..0e5c78a71 --- /dev/null +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -0,0 +1,55 @@ +warning: fields `d`, `f`, and `g` are never read + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:10:5 + | +LL | struct Bar { + | --- fields in this struct +... +LL | d: usize, + | ^ +... +LL | f: usize, + | ^ +LL | g: usize, + | ^ + | +note: the lint level is defined here + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:1:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +error: fields `c` and `e` are never read + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:9:5 + | +LL | struct Bar { + | --- fields in this struct +... +LL | c: usize, + | ^ +... +LL | e: usize, + | ^ + | +note: the lint level is defined here + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:8:12 + | +LL | #[deny(dead_code)] + | ^^^^^^^^^ + +error: field `b` is never read + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:7:5 + | +LL | struct Bar { + | --- field in this struct +... +LL | b: usize, + | ^ + | +note: the lint level is defined here + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:6:14 + | +LL | #[forbid(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/dead-code/newline-span.rs b/tests/ui/lint/dead-code/newline-span.rs new file mode 100644 index 000000000..209c3cd93 --- /dev/null +++ b/tests/ui/lint/dead-code/newline-span.rs @@ -0,0 +1,19 @@ +#![deny(dead_code)] + +fn unused() { //~ error: function `unused` is never used + println!("blah"); +} + +fn unused2(var: i32) { //~ error: function `unused2` is never used + println!("foo {}", var); +} + +fn unused3( //~ error: function `unused3` is never used + var: i32, +) { + println!("bar {}", var); +} + +fn main() { + println!("Hello world!"); +} diff --git a/tests/ui/lint/dead-code/newline-span.stderr b/tests/ui/lint/dead-code/newline-span.stderr new file mode 100644 index 000000000..4eeadccc8 --- /dev/null +++ b/tests/ui/lint/dead-code/newline-span.stderr @@ -0,0 +1,26 @@ +error: function `unused` is never used + --> $DIR/newline-span.rs:3:4 + | +LL | fn unused() { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/newline-span.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `unused2` is never used + --> $DIR/newline-span.rs:7:4 + | +LL | fn unused2(var: i32) { + | ^^^^^^^ + +error: function `unused3` is never used + --> $DIR/newline-span.rs:11:4 + | +LL | fn unused3( + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/self-assign.rs b/tests/ui/lint/dead-code/self-assign.rs new file mode 100644 index 000000000..ea7ce98d8 --- /dev/null +++ b/tests/ui/lint/dead-code/self-assign.rs @@ -0,0 +1,52 @@ +// Test that dead code warnings are issued for superfluous assignments of +// fields or variables to themselves (issue #75356). + +// ignore-test FIXME(81658, 83171) + +// check-pass +#![allow(unused_assignments)] +#![warn(dead_code)] + +fn main() { + let mut x = 0; + x = x; + //~^ WARNING: useless assignment of variable of type `i32` to itself + + x = (x); + //~^ WARNING: useless assignment of variable of type `i32` to itself + + x = {x}; + // block expressions don't count as self-assignments + + + struct S<'a> { f: &'a str } + let mut s = S { f: "abc" }; + s = s; + //~^ WARNING: useless assignment of variable of type `S` to itself + + s.f = s.f; + //~^ WARNING: useless assignment of field of type `&str` to itself + + + struct N0 { x: Box } + struct N1 { n: N0 } + struct N2(N1); + struct N3 { n: N2 }; + let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) }; + n3.n.0.n.x = n3.n.0.n.x; + //~^ WARNING: useless assignment of field of type `Box` to itself + + let mut t = (1, ((2, 3, (4, 5)),)); + t.1.0.2.1 = t.1.0.2.1; + //~^ WARNING: useless assignment of field of type `i32` to itself + + + let mut y = 0; + macro_rules! assign_to_y { + ($cur:expr) => {{ + y = $cur; + }}; + } + assign_to_y!(y); + // self-assignments in macro expansions are not reported either +} diff --git a/tests/ui/lint/dead-code/self-assign.stderr b/tests/ui/lint/dead-code/self-assign.stderr new file mode 100644 index 000000000..bb79c0ec7 --- /dev/null +++ b/tests/ui/lint/dead-code/self-assign.stderr @@ -0,0 +1,44 @@ +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:10:5 + | +LL | x = x; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/self-assign.rs:6:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:13:5 + | +LL | x = (x); + | ^^^^^^^ + +warning: useless assignment of variable of type `S` to itself + --> $DIR/self-assign.rs:22:5 + | +LL | s = s; + | ^^^^^ + +warning: useless assignment of field of type `&str` to itself + --> $DIR/self-assign.rs:25:5 + | +LL | s.f = s.f; + | ^^^^^^^^^ + +warning: useless assignment of field of type `Box` to itself + --> $DIR/self-assign.rs:34:5 + | +LL | n3.n.0.n.x = n3.n.0.n.x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: useless assignment of field of type `i32` to itself + --> $DIR/self-assign.rs:38:5 + | +LL | t.1.0.2.1 = t.1.0.2.1; + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/dead-code/trait-impl.rs b/tests/ui/lint/dead-code/trait-impl.rs new file mode 100644 index 000000000..92e389a93 --- /dev/null +++ b/tests/ui/lint/dead-code/trait-impl.rs @@ -0,0 +1,19 @@ +// check-pass +#![deny(dead_code)] + +enum Foo { + Bar, +} + +fn main() { + let p = [0; 0]; + p.bar(); +} + +trait Bar { + fn bar(&self) -> usize { + 3 + } +} + +impl Bar for [u32; Foo::Bar as usize] {} diff --git a/tests/ui/lint/dead-code/tuple-struct-field.rs b/tests/ui/lint/dead-code/tuple-struct-field.rs new file mode 100644 index 000000000..14fb30be9 --- /dev/null +++ b/tests/ui/lint/dead-code/tuple-struct-field.rs @@ -0,0 +1,37 @@ +#![deny(unused_tuple_struct_fields)] +//~^ NOTE: the lint level is defined here + +use std::marker::PhantomData; + +const LEN: usize = 4; + +struct SingleUnused(i32, [u8; LEN], String); +//~^ ERROR: field `1` is never read +//~| NOTE: field in this struct +//~| HELP: consider changing the field to be of unit type + +struct MultipleUnused(i32, f32, String, u8); +//~^ ERROR: fields `0`, `1`, `2`, and `3` are never read +//~| NOTE: fields in this struct +//~| HELP: consider changing the fields to be of unit type + +struct GoodUnit(()); + +struct GoodPhantom(PhantomData); + +struct Void; +struct GoodVoid(Void); + +fn main() { + let w = SingleUnused(42, [0, 1, 2, 3], "abc".to_string()); + let _ = w.0; + let _ = w.2; + + let m = MultipleUnused(42, 3.14, "def".to_string(), 4u8); + + let gu = GoodUnit(()); + let gp = GoodPhantom(PhantomData); + let gv = GoodVoid(Void); + + let _ = (gu, gp, gv, m); +} diff --git a/tests/ui/lint/dead-code/tuple-struct-field.stderr b/tests/ui/lint/dead-code/tuple-struct-field.stderr new file mode 100644 index 000000000..b8ad5cbe4 --- /dev/null +++ b/tests/ui/lint/dead-code/tuple-struct-field.stderr @@ -0,0 +1,33 @@ +error: field `1` is never read + --> $DIR/tuple-struct-field.rs:8:26 + | +LL | struct SingleUnused(i32, [u8; LEN], String); + | ------------ ^^^^^^^^^ + | | + | field in this struct + | +note: the lint level is defined here + --> $DIR/tuple-struct-field.rs:1:9 + | +LL | #![deny(unused_tuple_struct_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field + | +LL | struct SingleUnused(i32, (), String); + | ~~ + +error: fields `0`, `1`, `2`, and `3` are never read + --> $DIR/tuple-struct-field.rs:13:23 + | +LL | struct MultipleUnused(i32, f32, String, u8); + | -------------- ^^^ ^^^ ^^^^^^ ^^ + | | + | fields in this struct + | +help: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields + | +LL | struct MultipleUnused((), (), (), ()); + | ~~ ~~ ~~ ~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dead-code/type-alias.rs b/tests/ui/lint/dead-code/type-alias.rs new file mode 100644 index 000000000..35a7f125d --- /dev/null +++ b/tests/ui/lint/dead-code/type-alias.rs @@ -0,0 +1,10 @@ +#![deny(dead_code)] + +type Used = u8; +type Unused = u8; //~ ERROR type alias `Unused` is never used + +fn id(x: Used) -> Used { x } + +fn main() { + id(0); +} diff --git a/tests/ui/lint/dead-code/type-alias.stderr b/tests/ui/lint/dead-code/type-alias.stderr new file mode 100644 index 000000000..446447d97 --- /dev/null +++ b/tests/ui/lint/dead-code/type-alias.stderr @@ -0,0 +1,14 @@ +error: type alias `Unused` is never used + --> $DIR/type-alias.rs:4:6 + | +LL | type Unused = u8; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/type-alias.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/type-in-foreign.rs b/tests/ui/lint/dead-code/type-in-foreign.rs new file mode 100644 index 000000000..b6c593f31 --- /dev/null +++ b/tests/ui/lint/dead-code/type-in-foreign.rs @@ -0,0 +1,19 @@ +// Verify that we do not warn on types that are used by foreign functions. +// check-pass +#![deny(dead_code)] + +#[repr(C)] +struct Type(u8); + +#[repr(C)] +struct Param(u8); + +extern "C" { + #[allow(dead_code)] + fn hey(t: Param); + + #[allow(dead_code)] + static much: Type; +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-enum.rs b/tests/ui/lint/dead-code/unused-enum.rs new file mode 100644 index 000000000..20df3e1de --- /dev/null +++ b/tests/ui/lint/dead-code/unused-enum.rs @@ -0,0 +1,12 @@ +#![deny(unused)] + +struct F; //~ ERROR struct `F` is never constructed +struct B; //~ ERROR struct `B` is never constructed + +enum E { + //~^ ERROR enum `E` is never used + Foo(F), + Bar(B), +} + +fn main() {} diff --git a/tests/ui/lint/dead-code/unused-enum.stderr b/tests/ui/lint/dead-code/unused-enum.stderr new file mode 100644 index 000000000..d2602dbb3 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-enum.stderr @@ -0,0 +1,27 @@ +error: struct `F` is never constructed + --> $DIR/unused-enum.rs:3:8 + | +LL | struct F; + | ^ + | +note: the lint level is defined here + --> $DIR/unused-enum.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: struct `B` is never constructed + --> $DIR/unused-enum.rs:4:8 + | +LL | struct B; + | ^ + +error: enum `E` is never used + --> $DIR/unused-enum.rs:6:6 + | +LL | enum E { + | ^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dead-code/unused-struct-variant.rs b/tests/ui/lint/dead-code/unused-struct-variant.rs new file mode 100644 index 000000000..a914e0c33 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-variant.rs @@ -0,0 +1,13 @@ +#![deny(unused)] + +struct F; +struct B; + +enum E { + Foo(F), + Bar(B), //~ ERROR variant `Bar` is never constructed +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/tests/ui/lint/dead-code/unused-struct-variant.stderr b/tests/ui/lint/dead-code/unused-struct-variant.stderr new file mode 100644 index 000000000..d26dd3aff --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-variant.stderr @@ -0,0 +1,18 @@ +error: variant `Bar` is never constructed + --> $DIR/unused-struct-variant.rs:8:5 + | +LL | enum E { + | - variant in this enum +LL | Foo(F), +LL | Bar(B), + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-struct-variant.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/unused-variant-pub.rs b/tests/ui/lint/dead-code/unused-variant-pub.rs new file mode 100644 index 000000000..3a9061340 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-variant-pub.rs @@ -0,0 +1,14 @@ +// build-pass +#![deny(unused)] + +pub struct F; +pub struct B; + +pub enum E { + Foo(F), + Bar(B), +} + +fn main() { + let _ = E::Foo(F); +} diff --git a/tests/ui/lint/dead-code/unused-variant.rs b/tests/ui/lint/dead-code/unused-variant.rs new file mode 100644 index 000000000..82108fa9c --- /dev/null +++ b/tests/ui/lint/dead-code/unused-variant.rs @@ -0,0 +1,12 @@ +#![deny(dead_code)] + +#[derive(Clone)] +enum Enum { + Variant1, //~ ERROR: variant `Variant1` is never constructed + Variant2, +} + +fn main() { + let e = Enum::Variant2; + e.clone(); +} diff --git a/tests/ui/lint/dead-code/unused-variant.stderr b/tests/ui/lint/dead-code/unused-variant.stderr new file mode 100644 index 000000000..6029bf268 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-variant.stderr @@ -0,0 +1,17 @@ +error: variant `Variant1` is never constructed + --> $DIR/unused-variant.rs:5:5 + | +LL | enum Enum { + | ---- variant in this enum +LL | Variant1, + | ^^^^^^^^ + | + = note: `Enum` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis +note: the lint level is defined here + --> $DIR/unused-variant.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/with-core-crate.rs b/tests/ui/lint/dead-code/with-core-crate.rs new file mode 100644 index 000000000..0a94b528f --- /dev/null +++ b/tests/ui/lint/dead-code/with-core-crate.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] +#![allow(unreachable_code)] + +#[macro_use] +extern crate core; + +fn foo() { //~ ERROR function `foo` is never used + + // none of these should have any dead_code exposed to the user + panic!(); + + panic!("foo"); + + panic!("bar {}", "baz") +} + + +fn main() {} diff --git a/tests/ui/lint/dead-code/with-core-crate.stderr b/tests/ui/lint/dead-code/with-core-crate.stderr new file mode 100644 index 000000000..7adcf8848 --- /dev/null +++ b/tests/ui/lint/dead-code/with-core-crate.stderr @@ -0,0 +1,14 @@ +error: function `foo` is never used + --> $DIR/with-core-crate.rs:7:4 + | +LL | fn foo() { + | ^^^ + | +note: the lint level is defined here + --> $DIR/with-core-crate.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/dead-code/with-impl.rs b/tests/ui/lint/dead-code/with-impl.rs new file mode 100644 index 000000000..812fcdd09 --- /dev/null +++ b/tests/ui/lint/dead-code/with-impl.rs @@ -0,0 +1,17 @@ +// run-pass + +#![deny(dead_code)] + +pub struct GenericFoo(#[allow(unused_tuple_struct_fields)] T); + +type Foo = GenericFoo; + +impl Foo { + fn bar(self) -> u8 { + 0 + } +} + +fn main() { + println!("{}", GenericFoo(0).bar()); +} diff --git a/tests/ui/lint/deny-overflowing-literals.rs b/tests/ui/lint/deny-overflowing-literals.rs new file mode 100644 index 000000000..21c8ba7d6 --- /dev/null +++ b/tests/ui/lint/deny-overflowing-literals.rs @@ -0,0 +1,7 @@ +fn main() { + let x: u8 = 256; + //~^ error: literal out of range for `u8` + + for _ in 0..256u8 {} + //~^ error: range endpoint is out of range for `u8` +} diff --git a/tests/ui/lint/deny-overflowing-literals.stderr b/tests/ui/lint/deny-overflowing-literals.stderr new file mode 100644 index 000000000..beb0ad795 --- /dev/null +++ b/tests/ui/lint/deny-overflowing-literals.stderr @@ -0,0 +1,17 @@ +error: literal out of range for `u8` + --> $DIR/deny-overflowing-literals.rs:2:17 + | +LL | let x: u8 = 256; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` + = note: `#[deny(overflowing_literals)]` on by default + +error: range endpoint is out of range for `u8` + --> $DIR/deny-overflowing-literals.rs:5:14 + | +LL | for _ in 0..256u8 {} + | ^^^^^^^^ help: use an inclusive range instead: `0..=255u8` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/empty-lint-attributes.rs b/tests/ui/lint/empty-lint-attributes.rs new file mode 100644 index 000000000..9a0ec2533 --- /dev/null +++ b/tests/ui/lint/empty-lint-attributes.rs @@ -0,0 +1,17 @@ +#![feature(lint_reasons)] + +// check-pass + +// Empty (and reason-only) lint attributes are legal—although we may want to +// lint them in the future (Issue #55112). + +#![allow()] +#![warn(reason = "observationalism")] + +#[forbid()] +fn devoir() {} + +#[deny(reason = "ultion")] +fn waldgrave() {} + +fn main() {} diff --git a/tests/ui/lint/enable-unstable-lib-feature.rs b/tests/ui/lint/enable-unstable-lib-feature.rs new file mode 100644 index 000000000..aa6a973d7 --- /dev/null +++ b/tests/ui/lint/enable-unstable-lib-feature.rs @@ -0,0 +1,13 @@ +// Test that enabling an unstable feature disables warnings + +// aux-build:stability-cfg2.rs + +#![feature(unstable_test_feature)] +#![deny(non_snake_case)] // To trigger a hard error + +// Shouldn't generate a warning about unstable features +extern crate stability_cfg2; + +pub fn BOGUS() { } //~ ERROR + +pub fn main() { } diff --git a/tests/ui/lint/enable-unstable-lib-feature.stderr b/tests/ui/lint/enable-unstable-lib-feature.stderr new file mode 100644 index 000000000..bb4e928ad --- /dev/null +++ b/tests/ui/lint/enable-unstable-lib-feature.stderr @@ -0,0 +1,14 @@ +error: function `BOGUS` should have a snake case name + --> $DIR/enable-unstable-lib-feature.rs:11:8 + | +LL | pub fn BOGUS() { } + | ^^^^^ help: convert the identifier to snake case: `bogus` + | +note: the lint level is defined here + --> $DIR/enable-unstable-lib-feature.rs:6:9 + | +LL | #![deny(non_snake_case)] // To trigger a hard error + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/expansion-time-include.rs b/tests/ui/lint/expansion-time-include.rs new file mode 100644 index 000000000..4ea89d5ad --- /dev/null +++ b/tests/ui/lint/expansion-time-include.rs @@ -0,0 +1,4 @@ +// ignore-test auxiliary file for expansion-time.rs + +1 +2 diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs new file mode 100644 index 000000000..f23c7cb0d --- /dev/null +++ b/tests/ui/lint/expansion-time.rs @@ -0,0 +1,33 @@ +// check-pass + +#[warn(meta_variable_misuse)] +macro_rules! foo { + ( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator +} + +#[warn(missing_fragment_specifier)] +macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier + //~| WARN this was previously accepted + +#[warn(soft_unstable)] +mod benches { + #[bench] //~ WARN use of unstable library feature 'test' + //~| WARN this was previously accepted + fn foo() {} +} + +#[deprecated = "reason"] +macro_rules! deprecated { + () => {} +} + +#[allow(deprecated)] +mod deprecated { + deprecated!(); // No warning +} + +#[warn(incomplete_include)] +fn main() { + // WARN see in the stderr file, the warning points to the included file. + include!("expansion-time-include.rs"); +} diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr new file mode 100644 index 000000000..064ee5fad --- /dev/null +++ b/tests/ui/lint/expansion-time.stderr @@ -0,0 +1,56 @@ +warning: meta-variable repeats with different Kleene operator + --> $DIR/expansion-time.rs:5:29 + | +LL | ( $($i:ident)* ) => { $($i)+ }; + | - ^^ - conflicting repetition + | | + | expected repetition + | +note: the lint level is defined here + --> $DIR/expansion-time.rs:3:8 + | +LL | #[warn(meta_variable_misuse)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: missing fragment specifier + --> $DIR/expansion-time.rs:9:19 + | +LL | macro_rules! m { ($i) => {} } + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 +note: the lint level is defined here + --> $DIR/expansion-time.rs:8:8 + | +LL | #[warn(missing_fragment_specifier)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable + --> $DIR/expansion-time.rs:14:7 + | +LL | #[bench] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 +note: the lint level is defined here + --> $DIR/expansion-time.rs:12:8 + | +LL | #[warn(soft_unstable)] + | ^^^^^^^^^^^^^ + +warning: include macro expected single expression in source + --> $DIR/expansion-time-include.rs:4:1 + | +LL | 2 + | ^ + | +note: the lint level is defined here + --> $DIR/expansion-time.rs:29:8 + | +LL | #[warn(incomplete_include)] + | ^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/expr_attr_paren_order.rs b/tests/ui/lint/expr_attr_paren_order.rs new file mode 100644 index 000000000..e1ec2e951 --- /dev/null +++ b/tests/ui/lint/expr_attr_paren_order.rs @@ -0,0 +1,22 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + + // Test that attributes on parens get concatenated + // in the expected order in the hir folder. + + #[deny(non_snake_case)] #[allow(non_snake_case)] ( + { + let X = 0; + let _ = X; + } + ); + + #[allow(non_snake_case)] #[deny(non_snake_case)] ( + { + let X = 0; //~ ERROR snake case name + let _ = X; + } + ); + +} diff --git a/tests/ui/lint/expr_attr_paren_order.stderr b/tests/ui/lint/expr_attr_paren_order.stderr new file mode 100644 index 000000000..42beed10c --- /dev/null +++ b/tests/ui/lint/expr_attr_paren_order.stderr @@ -0,0 +1,14 @@ +error: variable `X` should have a snake case name + --> $DIR/expr_attr_paren_order.rs:17:17 + | +LL | let X = 0; + | ^ help: convert the identifier to snake case (notice the capitalization): `x` + | +note: the lint level is defined here + --> $DIR/expr_attr_paren_order.rs:15:37 + | +LL | #[allow(non_snake_case)] #[deny(non_snake_case)] ( + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/fn_must_use.rs b/tests/ui/lint/fn_must_use.rs new file mode 100644 index 000000000..b4e9da0fc --- /dev/null +++ b/tests/ui/lint/fn_must_use.rs @@ -0,0 +1,76 @@ +// check-pass + +#![warn(unused_must_use)] + +#[derive(PartialEq, Eq)] +struct MyStruct { + n: usize, +} + +impl MyStruct { + #[must_use] + fn need_to_use_this_method_value(&self) -> usize { + self.n + } + + #[must_use] + fn need_to_use_this_associated_function_value() -> isize { + -1 + } +} + +trait EvenNature { + #[must_use = "no side effects"] + fn is_even(&self) -> bool; +} + +impl EvenNature for MyStruct { + fn is_even(&self) -> bool { + self.n % 2 == 0 + } +} + +trait Replaceable { + fn replace(&mut self, substitute: usize) -> usize; +} + +impl Replaceable for MyStruct { + // ↓ N.b.: `#[must_use]` attribute on a particular trait implementation + // method won't work; the attribute should be on the method signature in + // the trait's definition. + #[must_use] + fn replace(&mut self, substitute: usize) -> usize { + let previously = self.n; + self.n = substitute; + previously + } +} + +#[must_use = "it's important"] +fn need_to_use_this_value() -> bool { + false +} + +fn main() { + need_to_use_this_value(); //~ WARN unused return value + + let mut m = MyStruct { n: 2 }; + let n = MyStruct { n: 3 }; + + m.need_to_use_this_method_value(); //~ WARN unused return value + m.is_even(); // trait method! + //~^ WARN unused return value + + MyStruct::need_to_use_this_associated_function_value(); + //~^ WARN unused return value + + m.replace(3); // won't warn (annotation needs to be in trait definition) + + // comparison methods are `must_use` + 2.eq(&3); //~ WARN unused return value + m.eq(&n); //~ WARN unused return value + + // lint includes comparison operators + 2 == 3; //~ WARN unused comparison + m == n; //~ WARN unused comparison +} diff --git a/tests/ui/lint/fn_must_use.stderr b/tests/ui/lint/fn_must_use.stderr new file mode 100644 index 000000000..657f23c60 --- /dev/null +++ b/tests/ui/lint/fn_must_use.stderr @@ -0,0 +1,69 @@ +warning: unused return value of `need_to_use_this_value` that must be used + --> $DIR/fn_must_use.rs:55:5 + | +LL | need_to_use_this_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: it's important +note: the lint level is defined here + --> $DIR/fn_must_use.rs:3:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used + --> $DIR/fn_must_use.rs:60:5 + | +LL | m.need_to_use_this_method_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused return value of `EvenNature::is_even` that must be used + --> $DIR/fn_must_use.rs:61:5 + | +LL | m.is_even(); // trait method! + | ^^^^^^^^^^^ + | + = note: no side effects + +warning: unused return value of `MyStruct::need_to_use_this_associated_function_value` that must be used + --> $DIR/fn_must_use.rs:64:5 + | +LL | MyStruct::need_to_use_this_associated_function_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused return value of `std::cmp::PartialEq::eq` that must be used + --> $DIR/fn_must_use.rs:70:5 + | +LL | 2.eq(&3); + | ^^^^^^^^ + +warning: unused return value of `std::cmp::PartialEq::eq` that must be used + --> $DIR/fn_must_use.rs:71:5 + | +LL | m.eq(&n); + | ^^^^^^^^ + +warning: unused comparison that must be used + --> $DIR/fn_must_use.rs:74:5 + | +LL | 2 == 3; + | ^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 2 == 3; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/fn_must_use.rs:75:5 + | +LL | m == n; + | ^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = m == n; + | +++++++ + +warning: 8 warnings emitted + diff --git a/tests/ui/lint/for_loop_over_fallibles.rs b/tests/ui/lint/for_loop_over_fallibles.rs new file mode 100644 index 000000000..43d71c2e8 --- /dev/null +++ b/tests/ui/lint/for_loop_over_fallibles.rs @@ -0,0 +1,43 @@ +// check-pass + +fn main() { + // Common + for _ in Some(1) {} + //~^ WARN for loop over an `Option`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + for _ in Ok::<_, ()>(1) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent + + // `Iterator::next` specific + for _ in [0; 0].iter().next() {} + //~^ WARN for loop over an `Option`. This is more readably written as an `if let` statement + //~| HELP to iterate over `[0; 0].iter()` remove the call to `next` + //~| HELP consider using `if let` to clear intent + + // `Result`, but function doesn't return `Result` + for _ in Ok::<_, ()>([0; 0].iter()) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider using `if let` to clear intent +} + +fn _returns_result() -> Result<(), ()> { + // `Result` + for _ in Ok::<_, ()>([0; 0].iter()) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider unwrapping the `Result` with `?` to iterate over its contents + //~| HELP consider using `if let` to clear intent + + // `Result` + for _ in Ok::<_, ()>([0; 0]) {} + //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement + //~| HELP to check pattern in a loop use `while let` + //~| HELP consider unwrapping the `Result` with `?` to iterate over its contents + //~| HELP consider using `if let` to clear intent + + Ok(()) +} diff --git a/tests/ui/lint/for_loop_over_fallibles.stderr b/tests/ui/lint/for_loop_over_fallibles.stderr new file mode 100644 index 000000000..96efdf85c --- /dev/null +++ b/tests/ui/lint/for_loop_over_fallibles.stderr @@ -0,0 +1,101 @@ +warning: for loop over an `Option`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:5:14 + | +LL | for _ in Some(1) {} + | ^^^^^^^ + | + = note: `#[warn(for_loops_over_fallibles)]` on by default +help: to check pattern in a loop use `while let` + | +LL | while let Some(_) = Some(1) {} + | ~~~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Some(_) = Some(1) {} + | ~~~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:9:14 + | +LL | for _ in Ok::<_, ()>(1) {} + | ^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>(1) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>(1) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over an `Option`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:15:14 + | +LL | for _ in [0; 0].iter().next() {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: to iterate over `[0; 0].iter()` remove the call to `next` + | +LL | for _ in [0; 0].iter().by_ref() {} + | ~~~~~~~~~ +help: consider using `if let` to clear intent + | +LL | if let Some(_) = [0; 0].iter().next() {} + | ~~~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:21:14 + | +LL | for _ in Ok::<_, ()>([0; 0].iter()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:29:14 + | +LL | for _ in Ok::<_, ()>([0; 0].iter()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider unwrapping the `Result` with `?` to iterate over its contents + | +LL | for _ in Ok::<_, ()>([0; 0].iter())? {} + | + +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>([0; 0].iter()) {} + | ~~~~~~~~~~ ~~~ + +warning: for loop over a `Result`. This is more readably written as an `if let` statement + --> $DIR/for_loop_over_fallibles.rs:36:14 + | +LL | for _ in Ok::<_, ()>([0; 0]) {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: to check pattern in a loop use `while let` + | +LL | while let Ok(_) = Ok::<_, ()>([0; 0]) {} + | ~~~~~~~~~~~~~ ~~~ +help: consider unwrapping the `Result` with `?` to iterate over its contents + | +LL | for _ in Ok::<_, ()>([0; 0])? {} + | + +help: consider using `if let` to clear intent + | +LL | if let Ok(_) = Ok::<_, ()>([0; 0]) {} + | ~~~~~~~~~~ ~~~ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/forbid-error-capped.rs b/tests/ui/lint/forbid-error-capped.rs new file mode 100644 index 000000000..b56471a75 --- /dev/null +++ b/tests/ui/lint/forbid-error-capped.rs @@ -0,0 +1,15 @@ +// check-pass +// compile-args: --cap-lints=warn -Fwarnings + +// This checks that the forbid attribute checking is ignored when the forbidden +// lint is capped. + +#![forbid(warnings)] +#![allow(unused)] + +#[allow(unused)] +mod bar { + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/lint/forbid-group-group-1.rs b/tests/ui/lint/forbid-group-group-1.rs new file mode 100644 index 000000000..80f7db4e5 --- /dev/null +++ b/tests/ui/lint/forbid-group-group-1.rs @@ -0,0 +1,13 @@ +// Check what happens when we forbid a smaller group but +// then allow a superset of that group. + +#![forbid(nonstandard_style)] + +// FIXME: Arguably this should be an error, but the WARNINGS group is +// treated in a very special (and rather ad-hoc) way and +// it fails to trigger. +#[allow(warnings)] +fn main() { + let A: (); + //~^ ERROR should have a snake case name +} diff --git a/tests/ui/lint/forbid-group-group-1.stderr b/tests/ui/lint/forbid-group-group-1.stderr new file mode 100644 index 000000000..fd425e5f7 --- /dev/null +++ b/tests/ui/lint/forbid-group-group-1.stderr @@ -0,0 +1,15 @@ +error: variable `A` should have a snake case name + --> $DIR/forbid-group-group-1.rs:11:9 + | +LL | let A: (); + | ^ help: convert the identifier to snake case: `a` + | +note: the lint level is defined here + --> $DIR/forbid-group-group-1.rs:4:11 + | +LL | #![forbid(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[forbid(non_snake_case)]` implied by `#[forbid(nonstandard_style)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/forbid-group-group-2.rs b/tests/ui/lint/forbid-group-group-2.rs new file mode 100644 index 000000000..b12fd72da --- /dev/null +++ b/tests/ui/lint/forbid-group-group-2.rs @@ -0,0 +1,26 @@ +// Check what happens when we forbid a bigger group but +// then deny a subset of that group. + +#![forbid(warnings)] +#![deny(forbidden_lint_groups)] + +#[allow(nonstandard_style)] +//~^ ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +//~| ERROR incompatible with previous +//~| WARNING previously accepted by the compiler +fn main() {} diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr new file mode 100644 index 000000000..b2e2bcea1 --- /dev/null +++ b/tests/ui/lint/forbid-group-group-2.stderr @@ -0,0 +1,115 @@ +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/forbid-group-member.rs b/tests/ui/lint/forbid-group-member.rs new file mode 100644 index 000000000..664edeaa8 --- /dev/null +++ b/tests/ui/lint/forbid-group-member.rs @@ -0,0 +1,17 @@ +// Check what happens when we forbid a group but +// then allow a member of that group. +// +// check-pass + +#![forbid(unused)] + +#[allow(unused_variables)] +//~^ WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +//~| WARNING incompatible with previous forbid +//~| WARNING previously accepted +fn main() { + let a: (); +} diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr new file mode 100644 index 000000000..47336d4d8 --- /dev/null +++ b/tests/ui/lint/forbid-group-member.stderr @@ -0,0 +1,39 @@ +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + = note: `#[warn(forbidden_lint_groups)]` on by default + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/forbid-member-group.rs b/tests/ui/lint/forbid-member-group.rs new file mode 100644 index 000000000..e2f76825a --- /dev/null +++ b/tests/ui/lint/forbid-member-group.rs @@ -0,0 +1,11 @@ +// Check what happens when we forbid a member of +// a group but then allow the group. + +#![forbid(unused_variables)] + +#[allow(unused)] +//~^ ERROR incompatible with previous forbid +//~| ERROR incompatible with previous forbid +fn main() { + let a: (); +} diff --git a/tests/ui/lint/forbid-member-group.stderr b/tests/ui/lint/forbid-member-group.stderr new file mode 100644 index 000000000..e65301778 --- /dev/null +++ b/tests/ui/lint/forbid-member-group.stderr @@ -0,0 +1,21 @@ +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error[E0453]: allow(unused) incompatible with previous forbid + --> $DIR/forbid-member-group.rs:6:9 + | +LL | #![forbid(unused_variables)] + | ---------------- `forbid` level set here +LL | +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/force-warn/allow-warnings.rs b/tests/ui/lint/force-warn/allow-warnings.rs new file mode 100644 index 000000000..0199381fc --- /dev/null +++ b/tests/ui/lint/force-warn/allow-warnings.rs @@ -0,0 +1,11 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite allowing all warnings in module +// compile-flags: --force-warn dead_code +// check-pass + +#![allow(warnings)] + +fn dead_function() {} +//~^ WARN function `dead_function` is never used + +fn main() {} diff --git a/tests/ui/lint/force-warn/allow-warnings.stderr b/tests/ui/lint/force-warn/allow-warnings.stderr new file mode 100644 index 000000000..4de68a079 --- /dev/null +++ b/tests/ui/lint/force-warn/allow-warnings.stderr @@ -0,0 +1,10 @@ +warning: function `dead_function` is never used + --> $DIR/allow-warnings.rs:8:4 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn dead-code` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-by-default-lint.rs new file mode 100644 index 000000000..b24ab822d --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.rs @@ -0,0 +1,12 @@ +// --force-warn $LINT causes $LINT (which is allow-by-default) to warn +// compile-flags: --force-warn elided_lifetimes_in_paths +// check-pass + +struct Foo<'a> { + x: &'a u32, +} + +fn foo(x: &Foo) {} +//~^ WARN hidden lifetime parameters in types are deprecated + +fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr new file mode 100644 index 000000000..ac98b5896 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-by-default-lint.stderr @@ -0,0 +1,14 @@ +warning: hidden lifetime parameters in types are deprecated + --> $DIR/allowed-by-default-lint.rs:9:12 + | +LL | fn foo(x: &Foo) {} + | ^^^ expected lifetime parameter + | + = note: requested on the command line with `--force-warn elided-lifetimes-in-paths` +help: indicate the anonymous lifetime + | +LL | fn foo(x: &Foo<'_>) {} + | ++++ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs new file mode 100644 index 000000000..257df13ef --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs @@ -0,0 +1,10 @@ +// --force-warn $LINT causes $LINT (which is deny-by-default) to warn +// despite $LINT being allowed on command line +// compile-flags: -A mutable_transmutes --force-warn mutable_transmutes +// check-pass + +fn main() { + unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior + } +} diff --git a/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr new file mode 100644 index 000000000..6a1fc76e1 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/allowed-cli-deny-by-default-lint.rs:8:17 + | +LL | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn mutable-transmutes` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs new file mode 100644 index 000000000..0d4b468c2 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.rs @@ -0,0 +1,11 @@ +// --force-warn $LINT causes $LINT (which is deny-by-default) to warn +// despite $LINT being allowed in module +// compile-flags: --force-warn mutable_transmutes +// check-pass + +#![allow(mutable_transmutes)] +fn main() { + unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior + } +} diff --git a/tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr new file mode 100644 index 000000000..9ef53d47e --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-deny-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/allowed-deny-by-default-lint.rs:9:17 + | +LL | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn mutable-transmutes` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs new file mode 100644 index 000000000..631a8cb2f --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite $LINT_GROUP (which contains $LINT) being allowed +// compile-flags: --force-warn bare_trait_objects +// check-pass + +#![allow(rust_2018_idioms)] + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr new file mode 100644 index 000000000..0f58953a5 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: requested on the command line with `--force-warn bare-trait-objects` +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs new file mode 100644 index 000000000..06b372867 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.rs @@ -0,0 +1,11 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite $LINT being allowed in module +// compile-flags: --force-warn dead_code +// check-pass + +#![allow(dead_code)] + +fn dead_function() {} +//~^ WARN function `dead_function` is never used + +fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr new file mode 100644 index 000000000..a6634e212 --- /dev/null +++ b/tests/ui/lint/force-warn/allowed-warn-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: function `dead_function` is never used + --> $DIR/allowed-warn-by-default-lint.rs:8:4 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn dead-code` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/cap-lints-allow.rs b/tests/ui/lint/force-warn/cap-lints-allow.rs new file mode 100644 index 000000000..fdba7f410 --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-allow.rs @@ -0,0 +1,16 @@ +// --force-warn $LINT casuses $LINT to warn despite --cap-lints +// set to allow +// compile-flags: --cap-lints allow --force-warn bare_trait_objects +// check-pass + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr new file mode 100644 index 000000000..03a32fa6f --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/cap-lints-allow.rs:8:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: requested on the command line with `--force-warn bare-trait-objects` +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/cap-lints-allow.rs:8:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/cap-lints-allow.rs:8:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs new file mode 100644 index 000000000..e65f156bf --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs @@ -0,0 +1,17 @@ +// --force-warn $LINT_GROUP causes $LINT to warn despite $LINT being +// allowed in module and cap-lints set to warn +// compile-flags: --cap-lints warn --force-warn rust-2021-compatibility +// check-pass +#![allow(ellipsis_inclusive_range_patterns)] + +pub fn f() -> bool { + let x = 123; + match x { + 0...100 => true, + //~^ WARN range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => false, + } +} + +fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr new file mode 100644 index 000000000..d1b764b34 --- /dev/null +++ b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr @@ -0,0 +1,12 @@ +warning: `...` range patterns are deprecated + --> $DIR/cap-lints-warn-allowed-warn-by-default-lint.rs:10:10 + | +LL | 0...100 => true, + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/deny-by-default-lint.rs b/tests/ui/lint/force-warn/deny-by-default-lint.rs new file mode 100644 index 000000000..c2e9377e9 --- /dev/null +++ b/tests/ui/lint/force-warn/deny-by-default-lint.rs @@ -0,0 +1,9 @@ +// --force-warn $LINT causes $LINT (which is deny-by-default) to warn +// compile-flags: --force-warn mutable_transmutes +// check-pass + +fn main() { + unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior + } +} diff --git a/tests/ui/lint/force-warn/deny-by-default-lint.stderr b/tests/ui/lint/force-warn/deny-by-default-lint.stderr new file mode 100644 index 000000000..c644d0fe7 --- /dev/null +++ b/tests/ui/lint/force-warn/deny-by-default-lint.stderr @@ -0,0 +1,10 @@ +warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/deny-by-default-lint.rs:7:17 + | +LL | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn mutable-transmutes` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allow-warnings.rs b/tests/ui/lint/force-warn/lint-group-allow-warnings.rs new file mode 100644 index 000000000..4b95f4d2d --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allow-warnings.rs @@ -0,0 +1,12 @@ +// --force-warn $LINT_GROUP causes $LINT in $LINT_GROUP to warn +// despite all warnings being allowed in module +// warn-by-default lint to warn +// compile-flags: --force-warn nonstandard_style +// check-pass + +#![allow(warnings)] + +pub fn FUNCTION() {} +//~^ WARN function `FUNCTION` should have a snake case name + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr b/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr new file mode 100644 index 000000000..dc7b1b7b9 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr @@ -0,0 +1,10 @@ +warning: function `FUNCTION` should have a snake case name + --> $DIR/lint-group-allow-warnings.rs:9:8 + | +LL | pub fn FUNCTION() {} + | ^^^^^^^^ help: convert the identifier to snake case: `function` + | + = note: `--force-warn non-snake-case` implied by `--force-warn nonstandard-style` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs new file mode 100644 index 000000000..7ad7462dd --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs @@ -0,0 +1,16 @@ +// --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn +// despite $LINT being allowed on command line +// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms +// check-pass + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr new file mode 100644 index 000000000..e17630fd3 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs new file mode 100644 index 000000000..ee5a18c38 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT_GROUP causes $LINT to warn despite +// $LINT_GROUP being allowed in module +// compile-flags: --force-warn rust_2018_idioms +// check-pass + +#![allow(rust_2018_idioms)] + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr new file mode 100644 index 000000000..72198541a --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-lint-group.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-lint-group.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-lint-group.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs new file mode 100644 index 000000000..248aece6f --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn +// despite $LINT being allowed in module +// compile-flags: --force-warn rust-2018-idioms +// check-pass + +#![allow(bare_trait_objects)] + +pub trait SomeTrait {} + +pub fn function(_x: Box) {} +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition + +fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr new file mode 100644 index 000000000..52c870ac2 --- /dev/null +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -0,0 +1,42 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms` +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 + | +LL | pub fn function(_x: Box) {} + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | pub fn function(_x: Box) {} + | +++ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs new file mode 100644 index 000000000..47a480ad7 --- /dev/null +++ b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.rs @@ -0,0 +1,18 @@ +// --force-warn $LINT causes $LINT (which is warn-by-default) to warn +// despite being allowed in one submodule (but not the other) +// compile-flags: --force-warn dead_code +// check-pass + +mod one { + #![allow(dead_code)] + + fn dead_function() {} + //~^ WARN function `dead_function` is never used +} + +mod two { + fn dead_function() {} + //~^ WARN function `dead_function` is never used +} + +fn main() {} diff --git a/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr new file mode 100644 index 000000000..824bcccc0 --- /dev/null +++ b/tests/ui/lint/force-warn/warn-by-default-lint-two-modules.stderr @@ -0,0 +1,16 @@ +warning: function `dead_function` is never used + --> $DIR/warn-by-default-lint-two-modules.rs:9:8 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + | + = note: requested on the command line with `--force-warn dead-code` + +warning: function `dead_function` is never used + --> $DIR/warn-by-default-lint-two-modules.rs:14:8 + | +LL | fn dead_function() {} + | ^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/force-warn/warnings-lint-group.rs b/tests/ui/lint/force-warn/warnings-lint-group.rs new file mode 100644 index 000000000..d1d4f5602 --- /dev/null +++ b/tests/ui/lint/force-warn/warnings-lint-group.rs @@ -0,0 +1,5 @@ +// --force-warn warnings is an error +// compile-flags: --force-warn warnings +// error-pattern: `warnings` lint group is not supported + +fn main() {} diff --git a/tests/ui/lint/force-warn/warnings-lint-group.stderr b/tests/ui/lint/force-warn/warnings-lint-group.stderr new file mode 100644 index 000000000..1faeed337 --- /dev/null +++ b/tests/ui/lint/force-warn/warnings-lint-group.stderr @@ -0,0 +1,7 @@ +error[E0602]: `warnings` lint group is not supported with ´--force-warn´ + +error[E0602]: `warnings` lint group is not supported with ´--force-warn´ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/function-item-references.rs b/tests/ui/lint/function-item-references.rs new file mode 100644 index 000000000..05213f4ed --- /dev/null +++ b/tests/ui/lint/function-item-references.rs @@ -0,0 +1,169 @@ +// check-pass +#![feature(c_variadic)] +#![warn(function_item_references)] +use std::fmt::Pointer; +use std::fmt::Formatter; + +fn nop() { } +fn foo() -> u32 { 42 } +fn bar(x: u32) -> u32 { x } +fn baz(x: u32, y: u32) -> u32 { x + y } +unsafe fn unsafe_fn() { } +extern "C" fn c_fn() { } +unsafe extern "C" fn unsafe_c_fn() { } +unsafe extern fn variadic(_x: u32, _args: ...) { } +fn take_generic_ref<'a, T>(_x: &'a T) { } +fn take_generic_array(_x: [T; N]) { } +fn multiple_generic(_x: T, _y: U) { } +fn multiple_generic_arrays(_x: [T; N], _y: [U; M]) { } + +//function references passed to these functions should never lint +fn call_fn(f: &dyn Fn(u32) -> u32, x: u32) { f(x); } +fn parameterized_call_fn u32>(f: &F, x: u32) { f(x); } + +//function references passed to these functions should lint +fn print_ptr(f: F) { println!("{:p}", f); } +fn bound_by_ptr_trait(_f: F) { } +fn bound_by_ptr_trait_tuple(_t: (F, G)) { } +fn implicit_ptr_trait(f: &F) { println!("{:p}", f); } + +//case found in tinyvec that triggered a compiler error in an earlier version of the lint checker +trait HasItem { + type Item; + fn assoc_item(&self) -> Self::Item; +} +fn _format_assoc_item(data: T, f: &mut Formatter) -> std::fmt::Result + where T::Item: Pointer { + //when the arg type bound by `Pointer` is an associated type, we shouldn't attempt to normalize + Pointer::fmt(&data.assoc_item(), f) +} + +//simple test to make sure that calls to `Pointer::fmt` aren't double counted +fn _call_pointer_fmt(f: &mut Formatter) -> std::fmt::Result { + let zst_ref = &foo; + Pointer::fmt(&zst_ref, f) + //~^ WARNING taking a reference to a function item does not give a function pointer +} + +fn main() { + //`let` bindings with function references shouldn't lint + let _ = &foo; + let _ = &mut foo; + + let zst_ref = &foo; + let fn_item = foo; + let indirect_ref = &fn_item; + + let _mut_zst_ref = &mut foo; + let mut mut_fn_item = foo; + let _mut_indirect_ref = &mut mut_fn_item; + + let cast_zst_ptr = &foo as *const _; + let coerced_zst_ptr: *const _ = &foo; + + let _mut_cast_zst_ptr = &mut foo as *mut _; + let _mut_coerced_zst_ptr: *mut _ = &mut foo; + + let _cast_zst_ref = &foo as &dyn Fn() -> u32; + let _coerced_zst_ref: &dyn Fn() -> u32 = &foo; + + let _mut_cast_zst_ref = &mut foo as &mut dyn Fn() -> u32; + let _mut_coerced_zst_ref: &mut dyn Fn() -> u32 = &mut foo; + + //the suggested way to cast to a function pointer + let fn_ptr = foo as fn() -> u32; + + //correct ways to print function pointers + println!("{:p}", foo as fn() -> u32); + println!("{:p}", fn_ptr); + + //potential ways to incorrectly try printing function pointers + println!("{:p}", &foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + print!("{:p}", &foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + format!("{:p}", &foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p}", &foo as *const _); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", zst_ref); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", cast_zst_ptr); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", coerced_zst_ptr); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p}", &fn_item); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", indirect_ref); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p}", &nop); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &baz); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &unsafe_fn); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &c_fn); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &unsafe_c_fn); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &variadic); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &take_generic_ref::); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &take_generic_array::); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &multiple_generic::); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &multiple_generic_arrays::); + //~^ WARNING taking a reference to a function item does not give a function pointer + println!("{:p}", &std::env::var::); + //~^ WARNING taking a reference to a function item does not give a function pointer + + println!("{:p} {:p} {:p}", &nop, &foo, &bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + //~^^ WARNING taking a reference to a function item does not give a function pointer + //~^^^ WARNING taking a reference to a function item does not give a function pointer + + //using a function reference to call a function shouldn't lint + (&bar)(1); + + //passing a function reference to an arbitrary function shouldn't lint + call_fn(&bar, 1); + parameterized_call_fn(&bar, 1); + std::mem::size_of_val(&foo); + + unsafe { + //potential ways to incorrectly try transmuting function pointers + std::mem::transmute::<_, usize>(&foo); + //~^ WARNING taking a reference to a function item does not give a function pointer + std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); + //~^ WARNING taking a reference to a function item does not give a function pointer + //~^^ WARNING taking a reference to a function item does not give a function pointer + std::mem::transmute::<_, usize>(&take_generic_ref::); + //~^ WARNING taking a reference to a function item does not give a function pointer + + //the correct way to transmute function pointers + std::mem::transmute::<_, usize>(foo as fn() -> u32); + std::mem::transmute::<_, (usize, usize)>((foo as fn() -> u32, bar as fn(u32) -> u32)); + } + + //function references as arguments required to be bound by std::fmt::Pointer should lint + print_ptr(&bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + bound_by_ptr_trait(&bar); + //~^ WARNING taking a reference to a function item does not give a function pointer + bound_by_ptr_trait_tuple((&foo, &bar)); + //~^ WARNING taking a reference to a function item does not give a function pointer + //~^^ WARNING taking a reference to a function item does not give a function pointer + implicit_ptr_trait(&bar); // ignore + + //correct ways to pass function pointers as arguments bound by std::fmt::Pointer + print_ptr(bar as fn(u32) -> u32); + bound_by_ptr_trait(bar as fn(u32) -> u32); + bound_by_ptr_trait_tuple((foo as fn() -> u32, bar as fn(u32) -> u32)); +} diff --git a/tests/ui/lint/function-item-references.stderr b/tests/ui/lint/function-item-references.stderr new file mode 100644 index 000000000..a9d18bb6a --- /dev/null +++ b/tests/ui/lint/function-item-references.stderr @@ -0,0 +1,206 @@ +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:44:18 + | +LL | Pointer::fmt(&zst_ref, f) + | ^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + | +note: the lint level is defined here + --> $DIR/function-item-references.rs:3:9 + | +LL | #![warn(function_item_references)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:81:22 + | +LL | println!("{:p}", &foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:83:20 + | +LL | print!("{:p}", &foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:85:21 + | +LL | format!("{:p}", &foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:88:22 + | +LL | println!("{:p}", &foo as *const _); + | ^^^^^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:90:22 + | +LL | println!("{:p}", zst_ref); + | ^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:92:22 + | +LL | println!("{:p}", cast_zst_ptr); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:94:22 + | +LL | println!("{:p}", coerced_zst_ptr); + | ^^^^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:97:22 + | +LL | println!("{:p}", &fn_item); + | ^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:99:22 + | +LL | println!("{:p}", indirect_ref); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:102:22 + | +LL | println!("{:p}", &nop); + | ^^^^ help: cast `nop` to obtain a function pointer: `nop as fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:104:22 + | +LL | println!("{:p}", &bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:106:22 + | +LL | println!("{:p}", &baz); + | ^^^^ help: cast `baz` to obtain a function pointer: `baz as fn(_, _) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:108:22 + | +LL | println!("{:p}", &unsafe_fn); + | ^^^^^^^^^^ help: cast `unsafe_fn` to obtain a function pointer: `unsafe_fn as unsafe fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:110:22 + | +LL | println!("{:p}", &c_fn); + | ^^^^^ help: cast `c_fn` to obtain a function pointer: `c_fn as extern "C" fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:112:22 + | +LL | println!("{:p}", &unsafe_c_fn); + | ^^^^^^^^^^^^ help: cast `unsafe_c_fn` to obtain a function pointer: `unsafe_c_fn as unsafe extern "C" fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:114:22 + | +LL | println!("{:p}", &variadic); + | ^^^^^^^^^ help: cast `variadic` to obtain a function pointer: `variadic as unsafe extern "C" fn(_, ...)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:116:22 + | +LL | println!("{:p}", &take_generic_ref::); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_ref` to obtain a function pointer: `take_generic_ref:: as fn(_)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:118:22 + | +LL | println!("{:p}", &take_generic_array::); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_array` to obtain a function pointer: `take_generic_array:: as fn(_)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:120:22 + | +LL | println!("{:p}", &multiple_generic::); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic` to obtain a function pointer: `multiple_generic:: as fn(_, _)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:122:22 + | +LL | println!("{:p}", &multiple_generic_arrays::); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `multiple_generic_arrays` to obtain a function pointer: `multiple_generic_arrays:: as fn(_, _)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:124:22 + | +LL | println!("{:p}", &std::env::var::); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `var` to obtain a function pointer: `var:: as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:127:32 + | +LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); + | ^^^^ help: cast `nop` to obtain a function pointer: `nop as fn()` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:127:38 + | +LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:127:44 + | +LL | println!("{:p} {:p} {:p}", &nop, &foo, &bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:142:41 + | +LL | std::mem::transmute::<_, usize>(&foo); + | ^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:144:50 + | +LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:144:50 + | +LL | std::mem::transmute::<_, (usize, usize)>((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:147:41 + | +LL | std::mem::transmute::<_, usize>(&take_generic_ref::); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: cast `take_generic_ref` to obtain a function pointer: `take_generic_ref:: as fn(_)` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:156:15 + | +LL | print_ptr(&bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:158:24 + | +LL | bound_by_ptr_trait(&bar); + | ^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:160:30 + | +LL | bound_by_ptr_trait_tuple((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `bar` to obtain a function pointer: `bar as fn(_) -> _` + +warning: taking a reference to a function item does not give a function pointer + --> $DIR/function-item-references.rs:160:30 + | +LL | bound_by_ptr_trait_tuple((&foo, &bar)); + | ^^^^^^^^^^^^ help: cast `foo` to obtain a function pointer: `foo as fn() -> _` + +warning: 33 warnings emitted + diff --git a/tests/ui/lint/future-incompat-test.rs b/tests/ui/lint/future-incompat-test.rs new file mode 100644 index 000000000..c5f477cc4 --- /dev/null +++ b/tests/ui/lint/future-incompat-test.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zfuture-incompat-test +// check-pass + +// The `-Zfuture-incompat-test flag causes any normal warning to be included +// in the future-incompatible report. The stderr output here should mention +// the future incompatible report (as extracted by compiletest). + +fn main() { + let x = 1; +} diff --git a/tests/ui/lint/future-incompat-test.stderr b/tests/ui/lint/future-incompat-test.stderr new file mode 100644 index 000000000..52674a843 --- /dev/null +++ b/tests/ui/lint/future-incompat-test.stderr @@ -0,0 +1,9 @@ +Future incompatibility report: Future breakage diagnostic: +warning: unused variable: `x` + --> $DIR/future-incompat-test.rs:9:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-A unused-variables` implied by `-A unused` + diff --git a/tests/ui/lint/inclusive-range-pattern-syntax.fixed b/tests/ui/lint/inclusive-range-pattern-syntax.fixed new file mode 100644 index 000000000..bee5d4ae4 --- /dev/null +++ b/tests/ui/lint/inclusive-range-pattern-syntax.fixed @@ -0,0 +1,21 @@ +// check-pass +// run-rustfix + +#![warn(ellipsis_inclusive_range_patterns)] + +fn main() { + let despondency = 2; + match despondency { + 1..=2 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } + + match &despondency { + &(1..=2) => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } +} diff --git a/tests/ui/lint/inclusive-range-pattern-syntax.rs b/tests/ui/lint/inclusive-range-pattern-syntax.rs new file mode 100644 index 000000000..d98c10c26 --- /dev/null +++ b/tests/ui/lint/inclusive-range-pattern-syntax.rs @@ -0,0 +1,21 @@ +// check-pass +// run-rustfix + +#![warn(ellipsis_inclusive_range_patterns)] + +fn main() { + let despondency = 2; + match despondency { + 1...2 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } + + match &despondency { + &1...2 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + _ => {} + } +} diff --git a/tests/ui/lint/inclusive-range-pattern-syntax.stderr b/tests/ui/lint/inclusive-range-pattern-syntax.stderr new file mode 100644 index 000000000..ed9fa0d41 --- /dev/null +++ b/tests/ui/lint/inclusive-range-pattern-syntax.stderr @@ -0,0 +1,25 @@ +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:9:10 + | +LL | 1...2 => {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/inclusive-range-pattern-syntax.rs:4:9 + | +LL | #![warn(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:16:9 + | +LL | &1...2 => {} + | ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs new file mode 100644 index 000000000..dc0bb8ac2 --- /dev/null +++ b/tests/ui/lint/inert-attr-macro.rs @@ -0,0 +1,20 @@ +// check-pass + +#![warn(unused)] + +macro_rules! foo { + () => {} +} + +fn main() { + #[inline] foo!(); //~ WARN unused attribute `inline` + + // This does nothing, since `#[allow(warnings)]` is itself + // an inert attribute on a macro call + #[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow` + //~^ WARN unused attribute `inline` + + // This does work, since the attribute is on a parent + // of the macro invocation. + #[allow(warnings)] { #[inline] foo!(); } +} diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr new file mode 100644 index 000000000..5ccb4ffe7 --- /dev/null +++ b/tests/ui/lint/inert-attr-macro.stderr @@ -0,0 +1,44 @@ +warning: unused attribute `inline` + --> $DIR/inert-attr-macro.rs:10:5 + | +LL | #[inline] foo!(); + | ^^^^^^^^^ + | +note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/inert-attr-macro.rs:10:15 + | +LL | #[inline] foo!(); + | ^^^ +note: the lint level is defined here + --> $DIR/inert-attr-macro.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]` + +warning: unused attribute `allow` + --> $DIR/inert-attr-macro.rs:14:5 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^^^^^^^^^^^^^^^^ + | +note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/inert-attr-macro.rs:14:34 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^ + +warning: unused attribute `inline` + --> $DIR/inert-attr-macro.rs:14:24 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^^^^^^^ + | +note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/inert-attr-macro.rs:14:34 + | +LL | #[allow(warnings)] #[inline] foo!(); + | ^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/inline-trait-and-foreign-items.rs b/tests/ui/lint/inline-trait-and-foreign-items.rs new file mode 100644 index 000000000..13dab7ed9 --- /dev/null +++ b/tests/ui/lint/inline-trait-and-foreign-items.rs @@ -0,0 +1,37 @@ +#![feature(extern_types)] +#![feature(type_alias_impl_trait)] + +#![warn(unused_attributes)] + +trait Trait { + #[inline] //~ WARN `#[inline]` is ignored on constants + //~^ WARN this was previously accepted + const X: u32; + + #[inline] //~ ERROR attribute should be applied to function or closure + type T; + + type U; +} + +impl Trait for () { + #[inline] //~ WARN `#[inline]` is ignored on constants + //~^ WARN this was previously accepted + const X: u32 = 0; + + #[inline] //~ ERROR attribute should be applied to function or closure + type T = Self; + + #[inline] //~ ERROR attribute should be applied to function or closure + type U = impl Trait; //~ ERROR unconstrained opaque type +} + +extern "C" { + #[inline] //~ ERROR attribute should be applied to function or closure + static X: u32; + + #[inline] //~ ERROR attribute should be applied to function or closure + type T; +} + +fn main() {} diff --git a/tests/ui/lint/inline-trait-and-foreign-items.stderr b/tests/ui/lint/inline-trait-and-foreign-items.stderr new file mode 100644 index 000000000..2f1fb4c46 --- /dev/null +++ b/tests/ui/lint/inline-trait-and-foreign-items.stderr @@ -0,0 +1,74 @@ +warning: `#[inline]` is ignored on constants + --> $DIR/inline-trait-and-foreign-items.rs:7:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: see issue #65833 for more information +note: the lint level is defined here + --> $DIR/inline-trait-and-foreign-items.rs:4:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:11:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type T; + | ------- not a function or closure + +warning: `#[inline]` is ignored on constants + --> $DIR/inline-trait-and-foreign-items.rs:18:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: see issue #65833 for more information + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:22:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type T = Self; + | -------------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:25:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type U = impl Trait; + | -------------------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:30:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | static X: u32; + | -------------- not a function or closure + +error[E0518]: attribute should be applied to function or closure + --> $DIR/inline-trait-and-foreign-items.rs:33:5 + | +LL | #[inline] + | ^^^^^^^^^ +LL | type T; + | ------- not a function or closure + +error: unconstrained opaque type + --> $DIR/inline-trait-and-foreign-items.rs:26:14 + | +LL | type U = impl Trait; + | ^^^^^^^^^^ + | + = note: `U` must be used in combination with a concrete type within the same impl + +error: aborting due to 6 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/lint/invalid_value.rs b/tests/ui/lint/invalid_value.rs new file mode 100644 index 000000000..57d8cbe7c --- /dev/null +++ b/tests/ui/lint/invalid_value.rs @@ -0,0 +1,169 @@ +// This test checks that calling `mem::{uninitialized,zeroed}` with certain types results +// in a lint. + +#![feature(never_type, rustc_attrs)] +#![allow(deprecated)] +#![deny(invalid_value)] + +use std::mem::{self, MaybeUninit}; +use std::ptr::NonNull; +use std::num::NonZeroU32; + +enum Void {} + +struct Ref(&'static i32); +struct RefPair((&'static i32, i32)); + +struct Wrap { wrapped: T } +enum WrapEnum { Wrapped(T) } + +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(128)] +#[repr(transparent)] +pub(crate) struct NonBig(u64); + +/// A two-variant enum, thus needs a tag and may not remain uninitialized. +enum Fruit { + Apple, + Banana, +} + +/// Looks like two variants but really only has one. +enum OneFruit { + Apple(!), + Banana, +} + +enum OneFruitNonZero { + Apple(!), + Banana(NonZeroU32), +} + +enum TwoUninhabited { + A(!), + B(Void), +} + +#[rustc_layout_scalar_valid_range_start(254)] +#[rustc_layout_scalar_valid_range_end(1)] +pub(crate) struct WrapAroundRange(u8); + +#[allow(unused)] +fn generic() { + unsafe { + let _val: &'static T = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: &'static T = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<&'static T> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<&'static T> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + } +} + +fn main() { + unsafe { + // Things that cannot even be zero. + let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: (i32, !) = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: (i32, !) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Void = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Void = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: &'static i32 = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: &'static i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Ref = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Ref = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: fn() = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: fn() = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: WrapEnum = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: WrapEnum = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonNull = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: (NonZeroU32, i32) = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: (NonZeroU32, i32) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: TwoUninhabited = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: TwoUninhabited = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: OneFruitNonZero = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: OneFruitNonZero = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things that can be zero, but not uninit. + let _val: bool = mem::zeroed(); + let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap = mem::zeroed(); + let _val: Wrap = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonBig = mem::zeroed(); + let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Fruit = mem::zeroed(); + let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: [bool; 2] = mem::zeroed(); + let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: i32 = mem::zeroed(); + let _val: i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: f32 = mem::zeroed(); + let _val: f32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const () = mem::zeroed(); + let _val: *const () = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: *const [()] = mem::zeroed(); + let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: WrapAroundRange = mem::zeroed(); + let _val: WrapAroundRange = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things where 0 is okay due to rustc implementation details, + // but that are not guaranteed to keep working. + let _val: Result = mem::zeroed(); + let _val: Result = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Some things that happen to be UB-free due to rustc implementation details, + // but are not guaranteed to keep working. + let _val: OneFruit = mem::zeroed(); + let _val: OneFruit = mem::uninitialized(); + + // Transmute-from-0 + let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization + let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization + let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization + + // `MaybeUninit` cases + let _val: NonNull = MaybeUninit::zeroed().assume_init(); //~ ERROR: does not permit zero-initialization + let _val: NonNull = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized + let _val: bool = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized + + // Some more types that should work just fine. + let _val: Option<&'static i32> = mem::zeroed(); + let _val: Option = mem::zeroed(); + let _val: MaybeUninit<&'static i32> = mem::zeroed(); + let _val: bool = MaybeUninit::zeroed().assume_init(); + let _val: [bool; 0] = MaybeUninit::uninit().assume_init(); + let _val: [!; 0] = MaybeUninit::zeroed().assume_init(); + } +} diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr new file mode 100644 index 000000000..48fd4169d --- /dev/null +++ b/tests/ui/lint/invalid_value.stderr @@ -0,0 +1,676 @@ +error: the type `&T` does not permit zero-initialization + --> $DIR/invalid_value.rs:54:32 + | +LL | let _val: &'static T = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null +note: the lint level is defined here + --> $DIR/invalid_value.rs:6:9 + | +LL | #![deny(invalid_value)] + | ^^^^^^^^^^^^^ + +error: the type `&T` does not permit being left uninitialized + --> $DIR/invalid_value.rs:55:32 + | +LL | let _val: &'static T = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `Wrap<&T>` does not permit zero-initialization + --> $DIR/invalid_value.rs:57:38 + | +LL | let _val: Wrap<&'static T> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<&T>` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `Wrap<&T>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:58:38 + | +LL | let _val: Wrap<&'static T> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap<&T>` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `!` does not permit zero-initialization + --> $DIR/invalid_value.rs:65:23 + | +LL | let _val: ! = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `!` does not permit being left uninitialized + --> $DIR/invalid_value.rs:66:23 + | +LL | let _val: ! = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `(i32, !)` does not permit zero-initialization + --> $DIR/invalid_value.rs:68:30 + | +LL | let _val: (i32, !) = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the `!` type has no valid value + +error: the type `(i32, !)` does not permit being left uninitialized + --> $DIR/invalid_value.rs:69:30 + | +LL | let _val: (i32, !) = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: integers must be initialized + +error: the type `Void` does not permit zero-initialization + --> $DIR/invalid_value.rs:71:26 + | +LL | let _val: Void = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: the type `Void` does not permit being left uninitialized + --> $DIR/invalid_value.rs:72:26 + | +LL | let _val: Void = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:12:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: the type `&i32` does not permit zero-initialization + --> $DIR/invalid_value.rs:74:34 + | +LL | let _val: &'static i32 = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `&i32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:75:34 + | +LL | let _val: &'static i32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `Ref` does not permit zero-initialization + --> $DIR/invalid_value.rs:77:25 + | +LL | let _val: Ref = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Ref` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:14:12 + | +LL | struct Ref(&'static i32); + | ^^^^^^^^^^^^ + +error: the type `Ref` does not permit being left uninitialized + --> $DIR/invalid_value.rs:78:25 + | +LL | let _val: Ref = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Ref` must be non-null +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:14:12 + | +LL | struct Ref(&'static i32); + | ^^^^^^^^^^^^ + +error: the type `fn()` does not permit zero-initialization + --> $DIR/invalid_value.rs:80:26 + | +LL | let _val: fn() = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `fn()` does not permit being left uninitialized + --> $DIR/invalid_value.rs:81:26 + | +LL | let _val: fn() = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `Wrap` does not permit zero-initialization + --> $DIR/invalid_value.rs:83:32 + | +LL | let _val: Wrap = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap` must be non-null +note: because function pointers must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/invalid_value.rs:84:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap` must be non-null +note: because function pointers must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `WrapEnum` does not permit zero-initialization + --> $DIR/invalid_value.rs:86:36 + | +LL | let _val: WrapEnum = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `WrapEnum` must be non-null +note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 + | +LL | enum WrapEnum { Wrapped(T) } + | ^ + +error: the type `WrapEnum` does not permit being left uninitialized + --> $DIR/invalid_value.rs:87:36 + | +LL | let _val: WrapEnum = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `WrapEnum` must be non-null +note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:18:28 + | +LL | enum WrapEnum { Wrapped(T) } + | ^ + +error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization + --> $DIR/invalid_value.rs:89:42 + | +LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: `RefPair` must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:15:16 + | +LL | struct RefPair((&'static i32, i32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized + --> $DIR/invalid_value.rs:90:42 + | +LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: `RefPair` must be non-null (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ +note: because references must be non-null (in this struct field) + --> $DIR/invalid_value.rs:15:16 + | +LL | struct RefPair((&'static i32, i32)); + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `NonNull` does not permit zero-initialization + --> $DIR/invalid_value.rs:92:34 + | +LL | let _val: NonNull = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + +error: the type `NonNull` does not permit being left uninitialized + --> $DIR/invalid_value.rs:93:34 + | +LL | let _val: NonNull = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + = note: raw pointers must be initialized + +error: the type `(NonZeroU32, i32)` does not permit zero-initialization + --> $DIR/invalid_value.rs:95:39 + | +LL | let _val: (NonZeroU32, i32) = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + +error: the type `(NonZeroU32, i32)` does not permit being left uninitialized + --> $DIR/invalid_value.rs:96:39 + | +LL | let _val: (NonZeroU32, i32) = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + = note: integers must be initialized + +error: the type `*const dyn Send` does not permit zero-initialization + --> $DIR/invalid_value.rs:98:37 + | +LL | let _val: *const dyn Send = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the vtable of a wide raw pointer must be non-null + +error: the type `*const dyn Send` does not permit being left uninitialized + --> $DIR/invalid_value.rs:99:37 + | +LL | let _val: *const dyn Send = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: the vtable of a wide raw pointer must be non-null + +error: the type `[fn(); 2]` does not permit zero-initialization + --> $DIR/invalid_value.rs:101:31 + | +LL | let _val: [fn(); 2] = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `[fn(); 2]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:102:31 + | +LL | let _val: [fn(); 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `TwoUninhabited` does not permit zero-initialization + --> $DIR/invalid_value.rs:104:36 + | +LL | let _val: TwoUninhabited = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `TwoUninhabited` does not permit being left uninitialized + --> $DIR/invalid_value.rs:105:36 + | +LL | let _val: TwoUninhabited = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/invalid_value.rs:42:1 + | +LL | enum TwoUninhabited { + | ^^^^^^^^^^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit zero-initialization + --> $DIR/invalid_value.rs:107:37 + | +LL | let _val: OneFruitNonZero = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `OneFruitNonZero` must be non-null +note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + +error: the type `OneFruitNonZero` does not permit being left uninitialized + --> $DIR/invalid_value.rs:108:37 + | +LL | let _val: OneFruitNonZero = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `OneFruitNonZero` must be non-null +note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant) + --> $DIR/invalid_value.rs:39:12 + | +LL | Banana(NonZeroU32), + | ^^^^^^^^^^ + = note: integers must be initialized + +error: the type `bool` does not permit being left uninitialized + --> $DIR/invalid_value.rs:112:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: the type `Wrap` does not permit being left uninitialized + --> $DIR/invalid_value.rs:115:32 + | +LL | let _val: Wrap = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `Wrap` must be initialized inside its custom valid range +note: characters must be a valid Unicode codepoint (in this struct field) + --> $DIR/invalid_value.rs:17:18 + | +LL | struct Wrap { wrapped: T } + | ^^^^^^^^^^ + +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/invalid_value.rs:118:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `NonBig` must be initialized inside its custom valid range +note: integers must be initialized (in this struct field) + --> $DIR/invalid_value.rs:23:26 + | +LL | pub(crate) struct NonBig(u64); + | ^^^ + +error: the type `Fruit` does not permit being left uninitialized + --> $DIR/invalid_value.rs:121:27 + | +LL | let _val: Fruit = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $DIR/invalid_value.rs:26:1 + | +LL | enum Fruit { + | ^^^^^^^^^^ + +error: the type `[bool; 2]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:124:31 + | +LL | let _val: [bool; 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: the type `i32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:127:25 + | +LL | let _val: i32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: integers must be initialized + +error: the type `f32` does not permit being left uninitialized + --> $DIR/invalid_value.rs:130:25 + | +LL | let _val: f32 = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: floats must be initialized + +error: the type `*const ()` does not permit being left uninitialized + --> $DIR/invalid_value.rs:133:31 + | +LL | let _val: *const () = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: raw pointers must be initialized + +error: the type `*const [()]` does not permit being left uninitialized + --> $DIR/invalid_value.rs:136:33 + | +LL | let _val: *const [()] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: raw pointers must be initialized + +error: the type `WrapAroundRange` does not permit being left uninitialized + --> $DIR/invalid_value.rs:139:37 + | +LL | let _val: WrapAroundRange = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `WrapAroundRange` must be initialized inside its custom valid range +note: integers must be initialized (in this struct field) + --> $DIR/invalid_value.rs:49:35 + | +LL | pub(crate) struct WrapAroundRange(u8); + | ^^ + +error: the type `Result` does not permit being left uninitialized + --> $DIR/invalid_value.rs:144:38 + | +LL | let _val: Result = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with multiple inhabited variants have to be initialized to a variant + --> $SRC_DIR/core/src/result.rs:LL:COL + +error: the type `&i32` does not permit zero-initialization + --> $DIR/invalid_value.rs:152:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `&[i32]` does not permit zero-initialization + --> $DIR/invalid_value.rs:153:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: references must be non-null + +error: the type `NonZeroU32` does not permit zero-initialization + --> $DIR/invalid_value.rs:154:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::num::NonZeroU32` must be non-null + +error: the type `NonNull` does not permit zero-initialization + --> $DIR/invalid_value.rs:157:34 + | +LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + +error: the type `NonNull` does not permit being left uninitialized + --> $DIR/invalid_value.rs:158:34 + | +LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `std::ptr::NonNull` must be non-null + = note: raw pointers must be initialized + +error: the type `bool` does not permit being left uninitialized + --> $DIR/invalid_value.rs:159:26 + | +LL | let _val: bool = MaybeUninit::uninit().assume_init(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + +error: aborting due to 51 previous errors + diff --git a/tests/ui/lint/issue-101284.rs b/tests/ui/lint/issue-101284.rs new file mode 100644 index 000000000..1381d4f17 --- /dev/null +++ b/tests/ui/lint/issue-101284.rs @@ -0,0 +1,15 @@ +// check-pass +// edition:2021 +#![deny(rust_2021_compatibility)] + +pub struct Warns { + // `Arc` has significant drop + _significant_drop: std::sync::Arc<()>, + field: String, +} + +pub fn test(w: Warns) { + _ = || drop(w.field); +} + +fn main() {} diff --git a/tests/ui/lint/issue-102705.rs b/tests/ui/lint/issue-102705.rs new file mode 100644 index 000000000..5bcc8950a --- /dev/null +++ b/tests/ui/lint/issue-102705.rs @@ -0,0 +1,22 @@ +// check-pass + +#![allow(opaque_hidden_inferred_bound)] +#![allow(dead_code)] + +trait Duh {} + +impl Duh for i32 {} + +trait Trait { + type Assoc: Duh; +} + +impl R> Trait for F { + type Assoc = R; +} + +fn foo() -> impl Trait { + || 42 +} + +fn main() {} diff --git a/tests/ui/lint/issue-103317.fixed b/tests/ui/lint/issue-103317.fixed new file mode 100644 index 000000000..5a987423e --- /dev/null +++ b/tests/ui/lint/issue-103317.fixed @@ -0,0 +1,14 @@ +// check-pass +// run-rustfix + +#[warn(unreachable_pub)] +mod inner { + #[allow(unused)] + pub(crate) enum T { + //~^ WARN unreachable `pub` item + A(u8), + X { a: f32, b: () }, + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-103317.rs b/tests/ui/lint/issue-103317.rs new file mode 100644 index 000000000..c2ba939e1 --- /dev/null +++ b/tests/ui/lint/issue-103317.rs @@ -0,0 +1,14 @@ +// check-pass +// run-rustfix + +#[warn(unreachable_pub)] +mod inner { + #[allow(unused)] + pub enum T { + //~^ WARN unreachable `pub` item + A(u8), + X { a: f32, b: () }, + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-103317.stderr b/tests/ui/lint/issue-103317.stderr new file mode 100644 index 000000000..9c982ddc3 --- /dev/null +++ b/tests/ui/lint/issue-103317.stderr @@ -0,0 +1,17 @@ +warning: unreachable `pub` item + --> $DIR/issue-103317.rs:7:5 + | +LL | pub enum T { + | ---^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates +note: the lint level is defined here + --> $DIR/issue-103317.rs:4:8 + | +LL | #[warn(unreachable_pub)] + | ^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-103435-extra-parentheses.fixed b/tests/ui/lint/issue-103435-extra-parentheses.fixed new file mode 100644 index 000000000..2b01b414b --- /dev/null +++ b/tests/ui/lint/issue-103435-extra-parentheses.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![deny(unused_parens)] + +fn main() { + if let Some(_) = Some(1) {} + //~^ ERROR unnecessary parentheses around pattern + + for _x in 1..10 {} + //~^ ERROR unnecessary parentheses around pattern + + if 2 == 1 {} + //~^ ERROR unnecessary parentheses around `if` condition + + // reported by parser + for _x in 1..10 {} + //~^ ERROR expected one of + //~| ERROR unexpected parentheses surrounding +} diff --git a/tests/ui/lint/issue-103435-extra-parentheses.rs b/tests/ui/lint/issue-103435-extra-parentheses.rs new file mode 100644 index 000000000..8261610cf --- /dev/null +++ b/tests/ui/lint/issue-103435-extra-parentheses.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![deny(unused_parens)] + +fn main() { + if let(Some(_))= Some(1) {} + //~^ ERROR unnecessary parentheses around pattern + + for(_x)in 1..10 {} + //~^ ERROR unnecessary parentheses around pattern + + if(2 == 1){} + //~^ ERROR unnecessary parentheses around `if` condition + + // reported by parser + for(_x in 1..10){} + //~^ ERROR expected one of + //~| ERROR unexpected parentheses surrounding +} diff --git a/tests/ui/lint/issue-103435-extra-parentheses.stderr b/tests/ui/lint/issue-103435-extra-parentheses.stderr new file mode 100644 index 000000000..29c41c910 --- /dev/null +++ b/tests/ui/lint/issue-103435-extra-parentheses.stderr @@ -0,0 +1,61 @@ +error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` + --> $DIR/issue-103435-extra-parentheses.rs:15:12 + | +LL | for(_x in 1..10){} + | ^^ expected one of `)`, `,`, `@`, or `|` + +error: unexpected parentheses surrounding `for` loop head + --> $DIR/issue-103435-extra-parentheses.rs:15:8 + | +LL | for(_x in 1..10){} + | ^ ^ + | +help: remove parentheses in `for` loop + | +LL - for(_x in 1..10){} +LL + for _x in 1..10 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-103435-extra-parentheses.rs:5:11 + | +LL | if let(Some(_))= Some(1) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-103435-extra-parentheses.rs:2:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if let(Some(_))= Some(1) {} +LL + if let Some(_) = Some(1) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-103435-extra-parentheses.rs:8:8 + | +LL | for(_x)in 1..10 {} + | ^ ^ + | +help: remove these parentheses + | +LL - for(_x)in 1..10 {} +LL + for _x in 1..10 {} + | + +error: unnecessary parentheses around `if` condition + --> $DIR/issue-103435-extra-parentheses.rs:11:7 + | +LL | if(2 == 1){} + | ^ ^ + | +help: remove these parentheses + | +LL - if(2 == 1){} +LL + if 2 == 1 {} + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/issue-104392.rs b/tests/ui/lint/issue-104392.rs new file mode 100644 index 000000000..d5608edb4 --- /dev/null +++ b/tests/ui/lint/issue-104392.rs @@ -0,0 +1,11 @@ +fn main() { + { unsafe 92 } //~ ERROR expected `{`, found `92` +} + +fn foo() { + { mod 92 } //~ ERROR expected identifier, found `92` +} + +fn bar() { + { trait 92 } //~ ERROR expected identifier, found `92` +} diff --git a/tests/ui/lint/issue-104392.stderr b/tests/ui/lint/issue-104392.stderr new file mode 100644 index 000000000..8e466439a --- /dev/null +++ b/tests/ui/lint/issue-104392.stderr @@ -0,0 +1,27 @@ +error: expected `{`, found `92` + --> $DIR/issue-104392.rs:2:14 + | +LL | { unsafe 92 } + | ------ ^^ expected `{` + | | + | while parsing this `unsafe` expression + | +help: try placing this code inside a block + | +LL | { unsafe { 92 } } + | + + + +error: expected identifier, found `92` + --> $DIR/issue-104392.rs:6:11 + | +LL | { mod 92 } + | ^^ expected identifier + +error: expected identifier, found `92` + --> $DIR/issue-104392.rs:10:13 + | +LL | { trait 92 } + | ^^ expected identifier + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/issue-104897.rs b/tests/ui/lint/issue-104897.rs new file mode 100644 index 000000000..5fbc658f1 --- /dev/null +++ b/tests/ui/lint/issue-104897.rs @@ -0,0 +1,6 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: format argument must be a string literal + +fn f(){(print!(á diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr new file mode 100644 index 000000000..817a93c2f --- /dev/null +++ b/tests/ui/lint/issue-104897.stderr @@ -0,0 +1,43 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: format argument must be a string literal + --> $DIR/issue-104897.rs:6:16 + | +LL | fn f(){(print!(á + | ^ + | +help: you might be missing a string literal to format with + | +LL | fn f(){(print!("{}", á + | +++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/issue-108155.rs b/tests/ui/lint/issue-108155.rs new file mode 100644 index 000000000..4ae0cbd92 --- /dev/null +++ b/tests/ui/lint/issue-108155.rs @@ -0,0 +1,15 @@ +// check-pass +// check that `deref_into_dyn_supertrait` doesn't cause ICE by eagerly converting +// a cancelled lint + +#![allow(deref_into_dyn_supertrait)] + +trait Trait {} +impl std::ops::Deref for dyn Trait + Send + Sync { + type Target = dyn Trait; + fn deref(&self) -> &Self::Target { + self + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-14309.rs b/tests/ui/lint/issue-14309.rs new file mode 100644 index 000000000..328a4c982 --- /dev/null +++ b/tests/ui/lint/issue-14309.rs @@ -0,0 +1,39 @@ +#![deny(improper_ctypes)] +#![allow(dead_code)] + +struct A { + x: i32 +} + +#[repr(C, packed)] +struct B { + x: i32, + y: A +} + +#[repr(C)] +struct C { + x: i32 +} + +type A2 = A; +type B2 = B; +type C2 = C; + +#[repr(C)] +struct D { + x: C, + y: A +} + +extern "C" { + fn foo(x: A); //~ ERROR type `A`, which is not FFI-safe + fn bar(x: B); //~ ERROR type `A` + fn baz(x: C); + fn qux(x: A2); //~ ERROR type `A` + fn quux(x: B2); //~ ERROR type `A` + fn corge(x: C2); + fn fred(x: D); //~ ERROR type `A` +} + +fn main() { } diff --git a/tests/ui/lint/issue-14309.stderr b/tests/ui/lint/issue-14309.stderr new file mode 100644 index 000000000..9ce62a6b8 --- /dev/null +++ b/tests/ui/lint/issue-14309.stderr @@ -0,0 +1,77 @@ +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:30:15 + | +LL | fn foo(x: A); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ +note: the lint level is defined here + --> $DIR/issue-14309.rs:1:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:31:15 + | +LL | fn bar(x: B); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:33:15 + | +LL | fn qux(x: A2); + | ^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:34:16 + | +LL | fn quux(x: B2); + | ^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/issue-14309.rs:36:16 + | +LL | fn fred(x: D); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/issue-14309.rs:4:1 + | +LL | struct A { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/issue-14837.rs b/tests/ui/lint/issue-14837.rs new file mode 100644 index 000000000..a83bc4150 --- /dev/null +++ b/tests/ui/lint/issue-14837.rs @@ -0,0 +1,11 @@ +// check-pass +// pretty-expanded FIXME #23616 + +#[deny(dead_code)] +pub enum Foo { + Bar { + baz: isize + } +} + +fn main() { } diff --git a/tests/ui/lint/issue-17718-const-naming.rs b/tests/ui/lint/issue-17718-const-naming.rs new file mode 100644 index 000000000..d7f0e7276 --- /dev/null +++ b/tests/ui/lint/issue-17718-const-naming.rs @@ -0,0 +1,8 @@ +#![warn(unused)] +#![deny(warnings)] + +const foo: isize = 3; +//~^ ERROR: should have an upper case name +//~^^ ERROR: constant `foo` is never used + +fn main() {} diff --git a/tests/ui/lint/issue-17718-const-naming.stderr b/tests/ui/lint/issue-17718-const-naming.stderr new file mode 100644 index 000000000..7d2aadd5f --- /dev/null +++ b/tests/ui/lint/issue-17718-const-naming.stderr @@ -0,0 +1,23 @@ +error: constant `foo` is never used + --> $DIR/issue-17718-const-naming.rs:4:7 + | +LL | const foo: isize = 3; + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-17718-const-naming.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(dead_code)]` implied by `#[deny(warnings)]` + +error: constant `foo` should have an upper case name + --> $DIR/issue-17718-const-naming.rs:4:7 + | +LL | const foo: isize = 3; + | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` + | + = note: `#[deny(non_upper_case_globals)]` implied by `#[deny(warnings)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/issue-1866.rs b/tests/ui/lint/issue-1866.rs new file mode 100644 index 000000000..caac0c504 --- /dev/null +++ b/tests/ui/lint/issue-1866.rs @@ -0,0 +1,29 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![warn(clashing_extern_declarations)] + +// pretty-expanded FIXME #23616 + +mod a { + pub type rust_task = usize; + pub mod rustrt { + use super::rust_task; + extern "C" { + pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + } + } +} + +mod b { + pub type rust_task = bool; + pub mod rustrt { + use super::rust_task; + extern "C" { + pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + //~^ WARN `rust_task_is_unwinding` redeclared with a different signature + } + } +} + +pub fn main() {} diff --git a/tests/ui/lint/issue-1866.stderr b/tests/ui/lint/issue-1866.stderr new file mode 100644 index 000000000..d19a13496 --- /dev/null +++ b/tests/ui/lint/issue-1866.stderr @@ -0,0 +1,19 @@ +warning: `rust_task_is_unwinding` redeclared with a different signature + --> $DIR/issue-1866.rs:23:13 + | +LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + | ------------------------------------------------------------ `rust_task_is_unwinding` previously declared here +... +LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn(*const usize) -> bool` + found `unsafe extern "C" fn(*const bool) -> bool` +note: the lint level is defined here + --> $DIR/issue-1866.rs:4:9 + | +LL | #![warn(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-20343.rs b/tests/ui/lint/issue-20343.rs new file mode 100644 index 000000000..000b63984 --- /dev/null +++ b/tests/ui/lint/issue-20343.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(unused_variables)] +// Regression test for Issue #20343. + +// pretty-expanded FIXME #23616 + +#![deny(dead_code)] + +struct B { b: u32 } +struct C; +struct D; + +trait T { fn dummy(&self, a: A) { } } +impl T for () {} + +impl B { + // test for unused code in arguments + fn foo(B { b }: B) -> u32 { b } + + // test for unused code in return type + fn bar() -> C { unsafe { ::std::mem::transmute(()) } } + + // test for unused code in generics + fn baz>() {} +} + +pub fn main() { + let b = B { b: 3 }; + B::foo(b); + B::bar(); + B::baz::<()>(); +} diff --git a/tests/ui/lint/issue-30302.rs b/tests/ui/lint/issue-30302.rs new file mode 100644 index 000000000..5eccb8cd5 --- /dev/null +++ b/tests/ui/lint/issue-30302.rs @@ -0,0 +1,20 @@ +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_snake_case)] +#![deny(unreachable_patterns)] + +enum Stack { + Nil, + Cons(T, Box>) +} + +fn is_empty(s: Stack) -> bool { + match s { + Nil => true, +//~^ ERROR pattern binding `Nil` is named the same as one of the variants of the type `Stack` + _ => false +//~^ ERROR unreachable pattern + } +} + +fn main() {} diff --git a/tests/ui/lint/issue-30302.stderr b/tests/ui/lint/issue-30302.stderr new file mode 100644 index 000000000..baf6c0d7a --- /dev/null +++ b/tests/ui/lint/issue-30302.stderr @@ -0,0 +1,26 @@ +error[E0170]: pattern binding `Nil` is named the same as one of the variants of the type `Stack` + --> $DIR/issue-30302.rs:13:9 + | +LL | Nil => true, + | ^^^ help: to match on the variant, qualify the path: `Stack::Nil` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error: unreachable pattern + --> $DIR/issue-30302.rs:15:9 + | +LL | Nil => true, + | --- matches any value +LL | +LL | _ => false + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/issue-30302.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/lint/issue-31924-non-snake-ffi.rs b/tests/ui/lint/issue-31924-non-snake-ffi.rs new file mode 100644 index 000000000..5b9faca49 --- /dev/null +++ b/tests/ui/lint/issue-31924-non-snake-ffi.rs @@ -0,0 +1,15 @@ +// check-pass + +#![deny(non_snake_case)] + +#[no_mangle] +pub extern "C" fn SparklingGenerationForeignFunctionInterface() {} // OK + +pub struct Foo; + +impl Foo { + #[no_mangle] + pub extern "C" fn SparklingGenerationForeignFunctionInterface() {} // OK +} + +fn main() {} diff --git a/tests/ui/lint/issue-34798.rs b/tests/ui/lint/issue-34798.rs new file mode 100644 index 000000000..f0d710123 --- /dev/null +++ b/tests/ui/lint/issue-34798.rs @@ -0,0 +1,25 @@ +// run-pass +#![forbid(improper_ctypes)] +#![allow(dead_code)] + +#[repr(C)] +pub struct Foo { + size: u8, + __value: ::std::marker::PhantomData, +} + +#[repr(C)] +pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); + +#[repr(C)] +pub struct Bar { + size: u8, + baz: ZeroSizeWithPhantomData, +} + +extern "C" { + pub fn bar(_: *mut Foo, _: *mut Bar); +} + +fn main() { +} diff --git a/tests/ui/lint/issue-35075.rs b/tests/ui/lint/issue-35075.rs new file mode 100644 index 000000000..0e54131c2 --- /dev/null +++ b/tests/ui/lint/issue-35075.rs @@ -0,0 +1,9 @@ +struct Bar { + inner: Foo //~ ERROR cannot find type `Foo` in this scope +} + +enum Baz { + Foo(Foo) //~ ERROR cannot find type `Foo` in this scope +} + +fn main() {} diff --git a/tests/ui/lint/issue-35075.stderr b/tests/ui/lint/issue-35075.stderr new file mode 100644 index 000000000..08bdaa728 --- /dev/null +++ b/tests/ui/lint/issue-35075.stderr @@ -0,0 +1,25 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-35075.rs:2:12 + | +LL | inner: Foo + | ^^^ not found in this scope + | +help: there is an enum variant `Baz::Foo`; try using the variant's enum + | +LL | inner: Baz + | ~~~ + +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-35075.rs:6:9 + | +LL | Foo(Foo) + | ^^^ not found in this scope + | +help: there is an enum variant `Baz::Foo`; try using the variant's enum + | +LL | Foo(Baz) + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs new file mode 100644 index 000000000..0a951cfa9 --- /dev/null +++ b/tests/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs @@ -0,0 +1,27 @@ +// check-pass + +#![warn(unused_parens)] + +macro_rules! the_worship_the_heart_lifts_above { + ( @as_expr, $e:expr) => { $e }; + ( @generate_fn, $name:tt) => { + #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> { + Some(the_worship_the_heart_lifts_above!( @as_expr, $name )) + } + }; + ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); } + // ↑ Notably, this does ð˜¯ð˜°ð˜µ warn: we're declining to lint unused parens in + // function/method arguments inside of nested macros because of situations + // like those reported in Issue #47775 +} + +macro_rules! and_the_heavens_reject_not { + () => { + #[allow(dead_code)] fn the_night_for_the_morrow() -> Option { Some((2)) } + } +} + +the_worship_the_heart_lifts_above!(rah); +and_the_heavens_reject_not!(); + +fn main() {} diff --git a/tests/ui/lint/issue-54099-camel-case-underscore-types.rs b/tests/ui/lint/issue-54099-camel-case-underscore-types.rs new file mode 100644 index 000000000..b2bf87358 --- /dev/null +++ b/tests/ui/lint/issue-54099-camel-case-underscore-types.rs @@ -0,0 +1,14 @@ +// check-pass + +#![forbid(non_camel_case_types)] +#![allow(dead_code)] + +// None of the following types should generate a warning +struct _X {} +struct __X {} +struct __ {} +struct X_ {} +struct X__ {} +struct X___ {} + +fn main() { } diff --git a/tests/ui/lint/issue-57410-1.rs b/tests/ui/lint/issue-57410-1.rs new file mode 100644 index 000000000..d825cb180 --- /dev/null +++ b/tests/ui/lint/issue-57410-1.rs @@ -0,0 +1,18 @@ +// check-pass + +// Originally from #53925. +// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`. + +#![deny(unreachable_pub)] + +mod foo { + mod bar { + pub struct Bar; + } + + pub use self::bar::Bar; +} + +pub use foo::Bar; + +fn main() {} diff --git a/tests/ui/lint/issue-57410.rs b/tests/ui/lint/issue-57410.rs new file mode 100644 index 000000000..0cf4b8068 --- /dev/null +++ b/tests/ui/lint/issue-57410.rs @@ -0,0 +1,17 @@ +// check-pass + +// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`. + +#![deny(unreachable_pub)] + +mod m { + mod imp { + pub fn f() {} + } + + pub use self::imp::f; +} + +pub use self::m::f; + +fn main() {} diff --git a/tests/ui/lint/issue-63364.rs b/tests/ui/lint/issue-63364.rs new file mode 100644 index 000000000..5223267a6 --- /dev/null +++ b/tests/ui/lint/issue-63364.rs @@ -0,0 +1,10 @@ +fn part(_: u16) -> u32 { + 1 +} + +fn main() { + for n in 100_000.. { + //~^ ERROR: literal out of range for `u16` + let _ = part(n); + } +} diff --git a/tests/ui/lint/issue-63364.stderr b/tests/ui/lint/issue-63364.stderr new file mode 100644 index 000000000..9b5453fa8 --- /dev/null +++ b/tests/ui/lint/issue-63364.stderr @@ -0,0 +1,11 @@ +error: literal out of range for `u16` + --> $DIR/issue-63364.rs:6:14 + | +LL | for n in 100_000.. { + | ^^^^^^^ + | + = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535` + = note: `#[deny(overflowing_literals)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs new file mode 100644 index 000000000..c2b81959f --- /dev/null +++ b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs @@ -0,0 +1,29 @@ +#![deny(non_snake_case)] +#![allow(unused_variables)] +#![allow(dead_code)] + +enum Foo { + Bad { + lowerCamelCaseName: bool, + //~^ ERROR structure field `lowerCamelCaseName` should have a snake case name + }, + Good { + snake_case_name: bool, + }, +} + +fn main() { + let b = Foo::Bad { lowerCamelCaseName: true }; + + match b { + Foo::Bad { lowerCamelCaseName } => {} + Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + //~^ ERROR variable `lowerCamelCaseBinding` should have a snake case name + } + + if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `anotherLowerCamelCaseBinding` should have a snake case name + + if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `yetAnotherLowerCamelCaseBinding` should have a snake case name +} diff --git a/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr new file mode 100644 index 000000000..09dc3640f --- /dev/null +++ b/tests/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr @@ -0,0 +1,32 @@ +error: structure field `lowerCamelCaseName` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9 + | +LL | lowerCamelCaseName: bool, + | ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name` + | +note: the lint level is defined here + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: variable `lowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38 + | +LL | Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + | ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding` + +error: variable `anotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41 + | +LL | if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding` + +error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43 + | +LL | if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs new file mode 100644 index 000000000..b4fc33174 --- /dev/null +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs @@ -0,0 +1,50 @@ +// This test is checking that you cannot override a `forbid` by adding in other +// attributes later in the same scope. (We already ensure that you cannot +// override it in nested scopes). + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and currently that happens two or three different times, depending on +// compiler flags. +// +// I decided avoiding the redundant output was not worth the time in engineering +// effort for bug like this, which 1. end users are unlikely to run into in the +// first place, and 2. they won't see the redundant output anyway. + +// compile-flags: -Z deduplicate-diagnostics=yes + +#![forbid(forbidden_lint_groups)] + +fn forbid_first(num: i32) -> i32 { + #![forbid(unused)] + #![deny(unused)] + //~^ ERROR: deny(unused) incompatible with previous forbid + //~| WARNING being phased out + #![warn(unused)] + #![allow(unused)] + + num * num +} + +fn forbid_last(num: i32) -> i32 { + #![deny(unused)] + #![warn(unused)] + #![allow(unused)] + #![forbid(unused)] + + num * num +} + +fn forbid_multiple(num: i32) -> i32 { + #![forbid(unused)] + #![forbid(unused)] + + num * num +} + +fn main() { + forbid_first(10); + forbid_last(10); + forbid_multiple(10); +} diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr new file mode 100644 index 000000000..cc44f8aa5 --- /dev/null +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -0,0 +1,18 @@ +error: deny(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/issue-79546-fuel-ice.rs b/tests/ui/lint/issue-79546-fuel-ice.rs new file mode 100644 index 000000000..0e9f54088 --- /dev/null +++ b/tests/ui/lint/issue-79546-fuel-ice.rs @@ -0,0 +1,8 @@ +// Regression test for the ICE described in #79546. + +// compile-flags: --cap-lints=allow -Zfuel=issue79546=0 +// check-pass +#![crate_name="issue79546"] + +struct S; +fn main() {} diff --git a/tests/ui/lint/issue-79744.rs b/tests/ui/lint/issue-79744.rs new file mode 100644 index 000000000..e9725a027 --- /dev/null +++ b/tests/ui/lint/issue-79744.rs @@ -0,0 +1,13 @@ +fn main() { + let elem = 6i8; + let e2 = 230; + //~^ ERROR literal out of range for `i8` + //~| HELP consider using the type `u8` instead + + let mut vec = Vec::new(); + + vec.push(e2); + vec.push(elem); + + println!("{:?}", vec); +} diff --git a/tests/ui/lint/issue-79744.stderr b/tests/ui/lint/issue-79744.stderr new file mode 100644 index 000000000..c1b56250d --- /dev/null +++ b/tests/ui/lint/issue-79744.stderr @@ -0,0 +1,12 @@ +error: literal out of range for `i8` + --> $DIR/issue-79744.rs:3:14 + | +LL | let e2 = 230; + | ^^^ + | + = note: the literal `230` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + = note: `#[deny(overflowing_literals)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/lint/issue-80988.rs b/tests/ui/lint/issue-80988.rs new file mode 100644 index 000000000..1e116206f --- /dev/null +++ b/tests/ui/lint/issue-80988.rs @@ -0,0 +1,14 @@ +// Regression test for #80988 +// +// check-pass + +#![forbid(warnings)] + +#[deny(warnings)] +//~^ WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +//~| WARNING incompatible with previous forbid +//~| WARNING being phased out +fn main() {} diff --git a/tests/ui/lint/issue-80988.stderr b/tests/ui/lint/issue-80988.stderr new file mode 100644 index 000000000..73e27ffda --- /dev/null +++ b/tests/ui/lint/issue-80988.stderr @@ -0,0 +1,39 @@ +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + = note: `#[warn(forbidden_lint_groups)]` on by default + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: deny(warnings) incompatible with previous forbid + --> $DIR/issue-80988.rs:7:8 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | +LL | #[deny(warnings)] + | ^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/issue-81218.rs b/tests/ui/lint/issue-81218.rs new file mode 100644 index 000000000..f02aa9040 --- /dev/null +++ b/tests/ui/lint/issue-81218.rs @@ -0,0 +1,14 @@ +// Regression test for #81218 +// +// check-pass + +#![forbid(warnings)] + +#[allow(unused_variables)] +fn main() { + // We want to ensure that you don't get an error + // here. The idea is that a derive might generate + // code that would otherwise trigger the "unused variables" + // lint, but it is meant to be suppressed. + let x: (); +} diff --git a/tests/ui/lint/issue-83477.rs b/tests/ui/lint/issue-83477.rs new file mode 100644 index 000000000..4262a2879 --- /dev/null +++ b/tests/ui/lint/issue-83477.rs @@ -0,0 +1,16 @@ +// compile-flags: -Zunstable-options +// check-pass +#![warn(rustc::internal)] + +#[allow(rustc::foo::bar::default_hash_types)] +//~^ WARN unknown lint: `rustc::foo::bar::default_hash_types` +//~| HELP did you mean +//~| SUGGESTION rustc::default_hash_types +#[allow(rustc::foo::default_hash_types)] +//~^ WARN unknown lint: `rustc::foo::default_hash_types` +//~| HELP did you mean +//~| SUGGESTION rustc::default_hash_types +fn main() { + let _ = std::collections::HashMap::::new(); + //~^ WARN prefer `FxHashMap` over `HashMap`, it has better performance +} diff --git a/tests/ui/lint/issue-83477.stderr b/tests/ui/lint/issue-83477.stderr new file mode 100644 index 000000000..f824fc09e --- /dev/null +++ b/tests/ui/lint/issue-83477.stderr @@ -0,0 +1,30 @@ +warning: unknown lint: `rustc::foo::bar::default_hash_types` + --> $DIR/issue-83477.rs:5:9 + | +LL | #[allow(rustc::foo::bar::default_hash_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` + | + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `rustc::foo::default_hash_types` + --> $DIR/issue-83477.rs:9:9 + | +LL | #[allow(rustc::foo::default_hash_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` + +warning: prefer `FxHashMap` over `HashMap`, it has better performance + --> $DIR/issue-83477.rs:14:13 + | +LL | let _ = std::collections::HashMap::::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary +note: the lint level is defined here + --> $DIR/issue-83477.rs:3:9 + | +LL | #![warn(rustc::internal)] + | ^^^^^^^^^^^^^^^ + = note: `#[warn(rustc::default_hash_types)]` implied by `#[warn(rustc::internal)]` + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/issue-86600-lint-twice.rs b/tests/ui/lint/issue-86600-lint-twice.rs new file mode 100644 index 000000000..0e8a837d9 --- /dev/null +++ b/tests/ui/lint/issue-86600-lint-twice.rs @@ -0,0 +1,15 @@ +// Regression test for #86600, where an instance of the +// `illegal_floating_point_literal_pattern` lint was issued twice. + +// check-pass + +fn main() { + let x = 42.0; + + match x { + 5.0 => {} + //~^ WARNING: floating-point types cannot be used in patterns + //~| WARNING: this was previously accepted by the compiler + _ => {} + } +} diff --git a/tests/ui/lint/issue-86600-lint-twice.stderr b/tests/ui/lint/issue-86600-lint-twice.stderr new file mode 100644 index 000000000..5a65c6121 --- /dev/null +++ b/tests/ui/lint/issue-86600-lint-twice.stderr @@ -0,0 +1,12 @@ +warning: floating-point types cannot be used in patterns + --> $DIR/issue-86600-lint-twice.rs:10:9 + | +LL | 5.0 => {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-87274-paren-parent.rs b/tests/ui/lint/issue-87274-paren-parent.rs new file mode 100644 index 000000000..0141c5a25 --- /dev/null +++ b/tests/ui/lint/issue-87274-paren-parent.rs @@ -0,0 +1,9 @@ +// check-pass +// Tests that we properly lint at 'paren' expressions + +fn foo() -> Result<(), String> { + (try!(Ok::(1))); //~ WARN use of deprecated macro `try` + Ok(()) +} + +fn main() {} diff --git a/tests/ui/lint/issue-87274-paren-parent.stderr b/tests/ui/lint/issue-87274-paren-parent.stderr new file mode 100644 index 000000000..f06024298 --- /dev/null +++ b/tests/ui/lint/issue-87274-paren-parent.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated macro `try`: use the `?` operator instead + --> $DIR/issue-87274-paren-parent.rs:5:6 + | +LL | (try!(Ok::(1))); + | ^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/issue-89469.rs b/tests/ui/lint/issue-89469.rs new file mode 100644 index 000000000..3a6ab4528 --- /dev/null +++ b/tests/ui/lint/issue-89469.rs @@ -0,0 +1,20 @@ +// Regression test for #89469, where an extra non_snake_case warning was +// reported for a shorthand field binding. + +// check-pass +#![deny(non_snake_case)] + +#[allow(non_snake_case)] +struct Entry { + A: u16, + a: u16 +} + +fn foo() -> Entry {todo!()} + +pub fn f() { + let Entry { A, a } = foo(); + let _ = (A, a); +} + +fn main() {} diff --git a/tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs b/tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs new file mode 100644 index 000000000..425e2703c --- /dev/null +++ b/tests/ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs @@ -0,0 +1,9 @@ +// check-pass +// Allowing the code lint should work without warning and +// the text flow char in the comment should be ignored. + +#![allow(text_direction_codepoint_in_comment)] + +fn main() { + // U+2066 LEFT-TO-RIGHT ISOLATE follows:â¦â¦ +} diff --git a/tests/ui/lint/issue-97094.rs b/tests/ui/lint/issue-97094.rs new file mode 100644 index 000000000..22525ca11 --- /dev/null +++ b/tests/ui/lint/issue-97094.rs @@ -0,0 +1,50 @@ +#![deny(warnings)] + +// Ensure that unknown lints inside cfg-attr's are linted for + +#![cfg_attr(all(), allow(nonex_lint_top_level))] +//~^ ERROR unknown lint +#![cfg_attr(all(), allow(bare_trait_object))] +//~^ ERROR has been renamed + +#[cfg_attr(all(), allow(nonex_lint_mod))] +//~^ ERROR unknown lint +mod baz { + #![cfg_attr(all(), allow(nonex_lint_mod_inner))] + //~^ ERROR unknown lint +} + +#[cfg_attr(all(), allow(nonex_lint_fn))] +//~^ ERROR unknown lint +pub fn main() {} + +macro_rules! bar { + ($($t:tt)*) => { + $($t)* + }; +} + +bar!( + #[cfg_attr(all(), allow(nonex_lint_in_macro))] + //~^ ERROR unknown lint + pub fn _bar() {} +); + +// No warning for non-applying cfg +#[cfg_attr(any(), allow(nonex_lint_fn))] +pub fn _foo() {} + +// Allowing unknown lints works if inside cfg_attr +#[cfg_attr(all(), allow(unknown_lints))] +mod bar_allowed { + #[allow(nonex_lint_fn)] + fn _foo() {} +} + +// ... but not if the cfg_attr doesn't evaluate +#[cfg_attr(any(), allow(unknown_lints))] +mod bar_not_allowed { + #[allow(nonex_lint_fn)] + //~^ ERROR unknown lint + fn _foo() {} +} diff --git a/tests/ui/lint/issue-97094.stderr b/tests/ui/lint/issue-97094.stderr new file mode 100644 index 000000000..1a0a3eaf2 --- /dev/null +++ b/tests/ui/lint/issue-97094.stderr @@ -0,0 +1,53 @@ +error: unknown lint: `nonex_lint_top_level` + --> $DIR/issue-97094.rs:5:26 + | +LL | #![cfg_attr(all(), allow(nonex_lint_top_level))] + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-97094.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]` + +error: lint `bare_trait_object` has been renamed to `bare_trait_objects` + --> $DIR/issue-97094.rs:7:26 + | +LL | #![cfg_attr(all(), allow(bare_trait_object))] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects` + | + = note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]` + +error: unknown lint: `nonex_lint_mod` + --> $DIR/issue-97094.rs:10:25 + | +LL | #[cfg_attr(all(), allow(nonex_lint_mod))] + | ^^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_mod_inner` + --> $DIR/issue-97094.rs:13:30 + | +LL | #![cfg_attr(all(), allow(nonex_lint_mod_inner))] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_fn` + --> $DIR/issue-97094.rs:17:25 + | +LL | #[cfg_attr(all(), allow(nonex_lint_fn))] + | ^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_in_macro` + --> $DIR/issue-97094.rs:28:29 + | +LL | #[cfg_attr(all(), allow(nonex_lint_in_macro))] + | ^^^^^^^^^^^^^^^^^^^ + +error: unknown lint: `nonex_lint_fn` + --> $DIR/issue-97094.rs:47:13 + | +LL | #[allow(nonex_lint_fn)] + | ^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs new file mode 100644 index 000000000..616eb935e --- /dev/null +++ b/tests/ui/lint/issue-99387.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(private_in_public)] + +pub type Successors<'a> = impl Iterator; + +pub fn f<'a>() -> Successors<'a> { + None.into_iter() +} + +trait Tr { + type Item; +} + +impl<'a> Tr for &'a () { + type Item = Successors<'a>; +} + +pub fn ohno<'a>() -> <&'a () as Tr>::Item { + None.into_iter() +} + +fn main() {} diff --git a/tests/ui/lint/known-tool-in-submodule/root.rs b/tests/ui/lint/known-tool-in-submodule/root.rs new file mode 100644 index 000000000..80806dcbd --- /dev/null +++ b/tests/ui/lint/known-tool-in-submodule/root.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(register_tool)] +#![register_tool(tool)] + +mod submodule; + +fn main() { + submodule::foo(); +} diff --git a/tests/ui/lint/known-tool-in-submodule/submodule.rs b/tests/ui/lint/known-tool-in-submodule/submodule.rs new file mode 100644 index 000000000..bb25e1005 --- /dev/null +++ b/tests/ui/lint/known-tool-in-submodule/submodule.rs @@ -0,0 +1,4 @@ +// ignore-test: not a test + +#[allow(tool::lint)] +pub fn foo() {} diff --git a/tests/ui/lint/let_underscore/let_underscore_drop.rs b/tests/ui/lint/let_underscore/let_underscore_drop.rs new file mode 100644 index 000000000..f298871f1 --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_drop.rs @@ -0,0 +1,14 @@ +// check-pass +#![warn(let_underscore_drop)] + +struct NontrivialDrop; + +impl Drop for NontrivialDrop { + fn drop(&mut self) { + println!("Dropping!"); + } +} + +fn main() { + let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop` +} diff --git a/tests/ui/lint/let_underscore/let_underscore_drop.stderr b/tests/ui/lint/let_underscore/let_underscore_drop.stderr new file mode 100644 index 000000000..7b7de202e --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_drop.stderr @@ -0,0 +1,22 @@ +warning: non-binding let on a type that implements `Drop` + --> $DIR/let_underscore_drop.rs:13:5 + | +LL | let _ = NontrivialDrop; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/let_underscore_drop.rs:2:9 + | +LL | #![warn(let_underscore_drop)] + | ^^^^^^^^^^^^^^^^^^^ +help: consider binding to an unused variable to avoid immediately dropping the value + | +LL | let _unused = NontrivialDrop; + | ~~~~~~~ +help: consider immediately dropping the value + | +LL | drop(NontrivialDrop); + | ~~~~~ + + +warning: 1 warning emitted + diff --git a/tests/ui/lint/let_underscore/let_underscore_lock.rs b/tests/ui/lint/let_underscore/let_underscore_lock.rs new file mode 100644 index 000000000..7423862cd --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_lock.rs @@ -0,0 +1,7 @@ +// check-fail +use std::sync::{Arc, Mutex}; + +fn main() { + let data = Arc::new(Mutex::new(0)); + let _ = data.lock().unwrap(); //~ERROR non-binding let on a synchronization lock +} diff --git a/tests/ui/lint/let_underscore/let_underscore_lock.stderr b/tests/ui/lint/let_underscore/let_underscore_lock.stderr new file mode 100644 index 000000000..fb58af0a4 --- /dev/null +++ b/tests/ui/lint/let_underscore/let_underscore_lock.stderr @@ -0,0 +1,20 @@ +error: non-binding let on a synchronization lock + --> $DIR/let_underscore_lock.rs:6:9 + | +LL | let _ = data.lock().unwrap(); + | ^ ^^^^^^^^^^^^^^^^^^^^ this binding will immediately drop the value assigned to it + | | + | this lock is not assigned to a binding and is immediately dropped + | + = note: `#[deny(let_underscore_lock)]` on by default +help: consider binding to an unused variable to avoid immediately dropping the value + | +LL | let _unused = data.lock().unwrap(); + | ~~~~~~~ +help: consider immediately dropping the value + | +LL | drop(data.lock().unwrap()); + | ~~~~~ + + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-attr-everywhere-early.rs b/tests/ui/lint/lint-attr-everywhere-early.rs new file mode 100644 index 000000000..fd0c4b43e --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-early.rs @@ -0,0 +1,176 @@ +// Tests that lint levels can be set for early lints. +#![allow(non_camel_case_types, unsafe_code, while_true, unused_parens)] + +// The following is a check of the lints used here to verify they do not warn +// when allowed. +fn verify_no_warnings() { + type non_camel_type = i32; // non_camel_case_types + struct NON_CAMEL_IS_ALLOWED; // non_camel_case_types + unsafe {} // unsafe_code + enum Enum { + VARIANT_CAMEL // non_camel_case_types + } + fn generics() {} // non_camel_case_types + while true {} // while_true + type T = (i32); // unused_parens +} + + +// ################## Types + +#[deny(non_camel_case_types)] +type type_outer = i32; //~ ERROR type `type_outer` should have an upper camel case name + +type BareFnPtr = fn(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type +// There aren't any early lints that currently apply to the variadic spot. +// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...); + +// ################## Items +#[deny(non_camel_case_types)] +struct ITEM_OUTER; //~ ERROR type `ITEM_OUTER` should have an upper camel case name + +mod module_inner { + #![deny(unsafe_code)] + fn f() { + unsafe {} //~ ERROR usage of an `unsafe` block + } +} + +struct Associated; +impl Associated { + #![deny(unsafe_code)] + + fn inherent_denied_from_inner() { unsafe {} } //~ usage of an `unsafe` block + + #[deny(while_true)] + fn inherent_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const INHERENT_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with +} + +trait trait_inner { //~ ERROR trait `trait_inner` should have an upper camel case name + #![deny(non_camel_case_types)] +} + +trait AssociatedTrait { + #![deny(unsafe_code)] + + fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block + + #[deny(while_true)] + fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with + + #[deny(non_camel_case_types)] + type assoc_type; //~ ERROR associated type `assoc_type` should have an upper camel case name +} + +impl AssociatedTrait for Associated { + #![deny(unsafe_code)] + + fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block + + #[deny(while_true)] + fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with + + #[deny(unused_parens)] + type assoc_type = (i32); //~ ERROR unnecessary parentheses around type +} + +struct StructFields { + #[deny(unused_parens)]f1: (i32), //~ ERROR unnecessary parentheses around type +} +struct StructTuple(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type + +enum Enum { + #[deny(non_camel_case_types)] + VARIANT_CAMEL, //~ ERROR variant `VARIANT_CAMEL` should have an upper camel case name +} + +extern "C" { + #![deny(unused_parens)] + + fn foreign_denied_from_inner(x: (i32)); //~ ERROR unnecessary parentheses around type +} + +extern "C" { + #[deny(unused_parens)] + fn foreign_denied_from_outer(x: (i32)); //~ ERROR unnecessary parentheses around type +} + +fn function(#[deny(unused_parens)] param: (i32)) {} //~ ERROR unnecessary parentheses around type + +fn generics<#[deny(non_camel_case_types)]foo>() {} //~ ERROR type parameter `foo` should have an upper camel case name + + +// ################## Statements +fn statements() { + #[deny(unused_parens)] + let x = (1); //~ ERROR unnecessary parentheses around assigned value +} + + +// ################## Expressions +fn expressions() { + let closure = |#[deny(unused_parens)] param: (i32)| {}; //~ ERROR unnecessary parentheses around type + + struct Match{f1: i32} + // Strangely unused_parens doesn't fire with {f1: (123)} + let f = Match{#[deny(unused_parens)]f1: {(123)}}; //~ ERROR unnecessary parentheses around block return value + + match f { + #![deny(unsafe_code)] + + #[deny(while_true)] + Match{f1} => { + unsafe {} //~ ERROR usage of an `unsafe` block + while true {} //~ ERROR denote infinite loops with + } + } + + // Statement Block + { + #![deny(unsafe_code)] + unsafe {} //~ ERROR usage of an `unsafe` block + } + let block_tail = { + #[deny(unsafe_code)] + unsafe {} //~ ERROR usage of an `unsafe` block + }; + + // Before expression as a statement. + #[deny(unsafe_code)] + unsafe {}; //~ ERROR usage of an `unsafe` block + + [#[deny(unsafe_code)] unsafe {123}]; //~ ERROR usage of an `unsafe` block + (#[deny(unsafe_code)] unsafe {123},); //~ ERROR usage of an `unsafe` block + fn call(p: i32) {} + call(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block + struct TupleStruct(i32); + TupleStruct(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block +} + + +// ################## Patterns +fn patterns() { + struct PatField{f1: i32, f2: i32}; + let f = PatField{f1: 1, f2: 2}; + match f { + PatField { + #[deny(ellipsis_inclusive_range_patterns)] + f1: 0...100, + //~^ ERROR range patterns are deprecated + //~| WARNING this is accepted in the current edition + .. + } => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-attr-everywhere-early.stderr b/tests/ui/lint/lint-attr-everywhere-early.stderr new file mode 100644 index 000000000..d6c6d5fae --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-early.stderr @@ -0,0 +1,486 @@ +error: type `type_outer` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:22:6 + | +LL | type type_outer = i32; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `TypeOuter` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:21:8 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:24:43 + | +LL | type BareFnPtr = fn(#[deny(unused_parens)](i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:24:28 + | +LL | type BareFnPtr = fn(#[deny(unused_parens)](i32)); + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - type BareFnPtr = fn(#[deny(unused_parens)](i32)); +LL + type BareFnPtr = fn(#[deny(unused_parens)]i32); + | + +error: type `ITEM_OUTER` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:30:8 + | +LL | struct ITEM_OUTER; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `ItemOuter` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:29:8 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:35:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:33:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:43:39 + | +LL | fn inherent_denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:41:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:46:24 + | +LL | fn inherent_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:45:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:49:34 + | +LL | const INHERENT_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:48:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: trait `trait_inner` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:52:7 + | +LL | trait trait_inner { + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `TraitInner` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:53:13 + | +LL | #![deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:59:30 + | +LL | fn denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:57:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:62:21 + | +LL | fn assoc_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:61:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:65:31 + | +LL | const ASSOC_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:64:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: associated type `assoc_type` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:68:10 + | +LL | type assoc_type; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `AssocType` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:67:12 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:74:30 + | +LL | fn denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:72:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:77:21 + | +LL | fn assoc_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:76:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:80:31 + | +LL | const ASSOC_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:79:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:83:23 + | +LL | type assoc_type = (i32); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:82:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - type assoc_type = (i32); +LL + type assoc_type = i32; + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:87:31 + | +LL | #[deny(unused_parens)]f1: (i32), + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:87:12 + | +LL | #[deny(unused_parens)]f1: (i32), + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - #[deny(unused_parens)]f1: (i32), +LL + #[deny(unused_parens)]f1: i32, + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:89:42 + | +LL | struct StructTuple(#[deny(unused_parens)](i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:89:27 + | +LL | struct StructTuple(#[deny(unused_parens)](i32)); + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - struct StructTuple(#[deny(unused_parens)](i32)); +LL + struct StructTuple(#[deny(unused_parens)]i32); + | + +error: variant `VARIANT_CAMEL` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:93:5 + | +LL | VARIANT_CAMEL, + | ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `VariantCamel` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:92:12 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:99:37 + | +LL | fn foreign_denied_from_inner(x: (i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:97:13 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn foreign_denied_from_inner(x: (i32)); +LL + fn foreign_denied_from_inner(x: i32); + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:104:37 + | +LL | fn foreign_denied_from_outer(x: (i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:103:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn foreign_denied_from_outer(x: (i32)); +LL + fn foreign_denied_from_outer(x: i32); + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:107:43 + | +LL | fn function(#[deny(unused_parens)] param: (i32)) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:107:20 + | +LL | fn function(#[deny(unused_parens)] param: (i32)) {} + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn function(#[deny(unused_parens)] param: (i32)) {} +LL + fn function(#[deny(unused_parens)] param: i32) {} + | + +error: type parameter `foo` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:109:42 + | +LL | fn generics<#[deny(non_camel_case_types)]foo>() {} + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:109:20 + | +LL | fn generics<#[deny(non_camel_case_types)]foo>() {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around assigned value + --> $DIR/lint-attr-everywhere-early.rs:115:13 + | +LL | let x = (1); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:114:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let x = (1); +LL + let x = 1; + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:121:50 + | +LL | let closure = |#[deny(unused_parens)] param: (i32)| {}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:121:27 + | +LL | let closure = |#[deny(unused_parens)] param: (i32)| {}; + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let closure = |#[deny(unused_parens)] param: (i32)| {}; +LL + let closure = |#[deny(unused_parens)] param: i32| {}; + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-attr-everywhere-early.rs:125:46 + | +LL | let f = Match{#[deny(unused_parens)]f1: {(123)}}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:125:26 + | +LL | let f = Match{#[deny(unused_parens)]f1: {(123)}}; + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let f = Match{#[deny(unused_parens)]f1: {(123)}}; +LL + let f = Match{#[deny(unused_parens)]f1: {123}}; + | + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:132:13 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:128:17 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:133:13 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:130:16 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:140:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:139:17 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:144:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:143:16 + | +LL | #[deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:149:5 + | +LL | unsafe {}; + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:148:12 + | +LL | #[deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:151:27 + | +LL | [#[deny(unsafe_code)] unsafe {123}]; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:151:13 + | +LL | [#[deny(unsafe_code)] unsafe {123}]; + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:152:27 + | +LL | (#[deny(unsafe_code)] unsafe {123},); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:152:13 + | +LL | (#[deny(unsafe_code)] unsafe {123},); + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:154:31 + | +LL | call(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:154:17 + | +LL | call(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:156:38 + | +LL | TupleStruct(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:156:24 + | +LL | TupleStruct(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^ + +error: `...` range patterns are deprecated + --> $DIR/lint-attr-everywhere-early.rs:167:18 + | +LL | f1: 0...100, + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:166:20 + | +LL | #[deny(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 36 previous errors + diff --git a/tests/ui/lint/lint-attr-everywhere-late.rs b/tests/ui/lint/lint-attr-everywhere-late.rs new file mode 100644 index 000000000..1055157d6 --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-late.rs @@ -0,0 +1,197 @@ +// Tests that lint levels can be set for late lints. +#![allow( + non_snake_case, + overflowing_literals, + missing_docs, + dyn_drop, + enum_intrinsics_non_enums, + clashing_extern_declarations +)] + +extern crate core; +use core::mem::{Discriminant, discriminant}; + +// The following is a check of the lints used here to verify they do not warn +// when allowed. +pub fn missing_docs_allowed() {} // missing_docs +fn dyn_drop_allowed(_x: Box) {} // dyn_drop +fn verify_no_warnings() { + discriminant::(&123); // enum_intrinsics_non_enums + let x: u8 = 1000; // overflowing_literals + let NON_SNAKE_CASE = 1; // non_snake_case +} +mod clashing_extern_allowed { + extern "C" { + fn extern_allowed(); + } +} +extern "C" { + fn extern_allowed(_: i32); // clashing_extern_declarations +} + +// ################## Types + +#[deny(missing_docs)] +pub type MissingDocType = i32; //~ ERROR missing documentation for a type alias + +// There aren't any late lints that I can find that can be easily used with types. +// type BareFnPtr = fn(#[deny()]i32); +// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...); + +// ################## Items +#[deny(missing_docs)] +pub struct ItemOuter; //~ ERROR missing documentation for a struct + +pub mod module_inner { //~ ERROR missing documentation for a module + #![deny(missing_docs)] + pub fn missing_inner() {} //~ ERROR missing documentation for a function +} + +pub struct Associated; +impl Associated { + #![deny(missing_docs)] + + pub fn inherent_denied_from_inner() {} //~ ERROR missing documentation for an associated function +} + +impl Associated { + #[deny(missing_docs)] + pub fn inherent_fn() {} //~ ERROR missing documentation for an associated function + + #[deny(missing_docs)] + pub const INHERENT_CONST: i32 = 1; //~ ERROR missing documentation for an associated constant +} + +pub trait TraitInner { //~ ERROR missing documentation for a trait + #![deny(missing_docs)] +} + +pub trait AssociatedTraitInner { //~ ERROR missing documentation for a trait + #![deny(missing_docs)] + + fn denied_from_inner() {} //~ ERROR missing documentation for an associated function +} + +pub trait AssociatedTrait { + fn denied_from_inner(_x: Box) {} // Used below + + #[deny(missing_docs)] + fn assoc_fn() {} //~ ERROR missing documentation for an associated function + + #[deny(missing_docs)] + const ASSOC_CONST: u8 = 1; //~ ERROR missing documentation for an associated constant + + #[deny(missing_docs)] + type AssocType; //~ ERROR missing documentation for an associated type +} + +struct Foo; + +impl AssociatedTrait for Associated { + #![deny(dyn_drop)] + + fn denied_from_inner(_x: Box) {} //~ ERROR types that do not implement `Drop` + + #[deny(enum_intrinsics_non_enums)] + fn assoc_fn() { discriminant::(&123); } //~ ERROR the return value of + + #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; //~ ERROR literal out of range + type AssocType = i32; +} + + +// There aren't any late lints that can apply to a field that I can find. +// non_snake_case doesn't work on fields +// struct StructFields { +// #[deny()]f1: i32, +// } +// struct StructTuple(#[deny()]i32); + +pub enum Enum { + #[deny(missing_docs)] + Variant1, //~ ERROR missing documentation for a variant +} + +mod clashing_extern { + extern "C" { + fn clashing1(); + fn clashing2(); + } +} +extern "C" { + #![deny(clashing_extern_declarations)] + fn clashing1(_: i32); //~ ERROR `clashing1` redeclared with a different signature +} + +extern "C" { + #[deny(clashing_extern_declarations)] + fn clashing2(_: i32); //~ ERROR `clashing2` redeclared with a different signature +} + +fn function(#[deny(non_snake_case)] PARAM: i32) {} //~ ERROR variable `PARAM` should have a snake case name +// There aren't any late lints that can apply to generics that I can find. +// fn generics<#[deny()]T>() {} + + +// ################## Statements +fn statements() { + #[deny(enum_intrinsics_non_enums)] + let _ = discriminant::(&123); //~ ERROR the return value of +} + + +// ################## Expressions +fn expressions() { + let closure = |#[deny(non_snake_case)] PARAM: i32| {}; //~ ERROR variable `PARAM` should have a snake case name + + struct Match{f1: i32} + // I can't find any late lints for patterns. + // let f = Match{#[deny()]f1: 123}; + + let f = Match{f1: 123}; + match f { + #![deny(enum_intrinsics_non_enums)] + Match{f1} => { + discriminant::(&123); //~ ERROR the return value of + } + } + match f { + #[deny(enum_intrinsics_non_enums)] + Match{f1} => { + discriminant::(&123); //~ ERROR the return value of + } + } + + // Statement Block + { + #![deny(enum_intrinsics_non_enums)] + discriminant::(&123); //~ ERROR the return value of + } + let block_tail = { + #[deny(enum_intrinsics_non_enums)] + discriminant::(&123); //~ ERROR the return value of + }; + + // Before expression as a statement. + #[deny(enum_intrinsics_non_enums)] + discriminant::(&123); //~ ERROR the return value of + + [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; //~ ERROR the return value of + (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); //~ ERROR the return value of + fn call(p: Discriminant) {} + call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); //~ ERROR the return value of + struct TupleStruct(Discriminant); + TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); //~ ERROR the return value of +} + + +// ################## Patterns +fn patterns() { + // There aren't any late lints that I can find that apply to pattern fields. + // + // struct PatField{f1: i32, f2: i32}; + // let f = PatField{f1: 1, f2: 2}; + // let PatField{#[deny()]f1, #[deny()]..} = f; +} + +fn main() {} diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr new file mode 100644 index 000000000..a69c2e0ef --- /dev/null +++ b/tests/ui/lint/lint-attr-everywhere-late.stderr @@ -0,0 +1,428 @@ +error: missing documentation for a type alias + --> $DIR/lint-attr-everywhere-late.rs:35:1 + | +LL | pub type MissingDocType = i32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:34:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a struct + --> $DIR/lint-attr-everywhere-late.rs:43:1 + | +LL | pub struct ItemOuter; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:42:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a module + --> $DIR/lint-attr-everywhere-late.rs:45:1 + | +LL | pub mod module_inner { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:46:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-attr-everywhere-late.rs:47:5 + | +LL | pub fn missing_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:54:5 + | +LL | pub fn inherent_denied_from_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:52:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:59:5 + | +LL | pub fn inherent_fn() {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:58:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> $DIR/lint-attr-everywhere-late.rs:62:5 + | +LL | pub const INHERENT_CONST: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:61:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-attr-everywhere-late.rs:65:1 + | +LL | pub trait TraitInner { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:66:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-attr-everywhere-late.rs:69:1 + | +LL | pub trait AssociatedTraitInner { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:70:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:72:5 + | +LL | fn denied_from_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:79:5 + | +LL | fn assoc_fn() {} + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:78:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> $DIR/lint-attr-everywhere-late.rs:82:5 + | +LL | const ASSOC_CONST: u8 = 1; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:81:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-attr-everywhere-late.rs:85:5 + | +LL | type AssocType; + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:84:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a variant + --> $DIR/lint-attr-everywhere-late.rs:112:5 + | +LL | Variant1, + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:111:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: `clashing1` redeclared with a different signature + --> $DIR/lint-attr-everywhere-late.rs:123:5 + | +LL | fn clashing1(); + | --------------- `clashing1` previously declared here +... +LL | fn clashing1(_: i32); + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn()` + found `unsafe extern "C" fn(i32)` +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:122:13 + | +LL | #![deny(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `clashing2` redeclared with a different signature + --> $DIR/lint-attr-everywhere-late.rs:128:5 + | +LL | fn clashing2(); + | --------------- `clashing2` previously declared here +... +LL | fn clashing2(_: i32); + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn()` + found `unsafe extern "C" fn(i32)` +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:127:12 + | +LL | #[deny(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/lint-attr-everywhere-late.rs:93:38 + | +LL | fn denied_from_inner(_x: Box) {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:91:13 + | +LL | #![deny(dyn_drop)] + | ^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:96:21 + | +LL | fn assoc_fn() { discriminant::(&123); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:96:41 + | +LL | fn assoc_fn() { discriminant::(&123); } + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:95:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-attr-everywhere-late.rs:98:59 + | +LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; + | ^^^^ + | + = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255` +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:98:12 + | +LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; + | ^^^^^^^^^^^^^^^^^^^^ + +error: variable `PARAM` should have a snake case name + --> $DIR/lint-attr-everywhere-late.rs:131:37 + | +LL | fn function(#[deny(non_snake_case)] PARAM: i32) {} + | ^^^^^ help: convert the identifier to snake case: `param` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:131:20 + | +LL | fn function(#[deny(non_snake_case)] PARAM: i32) {} + | ^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:139:13 + | +LL | let _ = discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:139:33 + | +LL | let _ = discriminant::(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:138:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: variable `PARAM` should have a snake case name + --> $DIR/lint-attr-everywhere-late.rs:145:44 + | +LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {}; + | ^^^^^ help: convert the identifier to snake case: `param` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:145:27 + | +LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {}; + | ^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:155:13 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:155:33 + | +LL | discriminant::(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:153:17 + | +LL | #![deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:161:13 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:161:33 + | +LL | discriminant::(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:159:16 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:168:9 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:168:29 + | +LL | discriminant::(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:167:17 + | +LL | #![deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:172:9 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:172:29 + | +LL | discriminant::(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:171:16 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:177:5 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:177:25 + | +LL | discriminant::(&123); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:176:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:179:41 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:179:61 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:179:13 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:180:41 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:180:61 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:180:13 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:182:45 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:182:65 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:182:17 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:184:52 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:184:72 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^ +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:184:24 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 31 previous errors + diff --git a/tests/ui/lint/lint-attr-non-item-node.rs b/tests/ui/lint/lint-attr-non-item-node.rs new file mode 100644 index 000000000..3f05e83a7 --- /dev/null +++ b/tests/ui/lint/lint-attr-non-item-node.rs @@ -0,0 +1,9 @@ +// Checks that lint attributes work on non-item AST nodes + +fn main() { + #[deny(unreachable_code)] + loop { + break; + "unreachable"; //~ ERROR unreachable statement + } +} diff --git a/tests/ui/lint/lint-attr-non-item-node.stderr b/tests/ui/lint/lint-attr-non-item-node.stderr new file mode 100644 index 000000000..583579140 --- /dev/null +++ b/tests/ui/lint/lint-attr-non-item-node.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/lint-attr-non-item-node.rs:7:9 + | +LL | break; + | ----- any code following this expression is unreachable +LL | "unreachable"; + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/lint-attr-non-item-node.rs:4:12 + | +LL | #[deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-cap.rs b/tests/ui/lint/lint-cap.rs new file mode 100644 index 000000000..461b923cc --- /dev/null +++ b/tests/ui/lint/lint-cap.rs @@ -0,0 +1,8 @@ +// run-pass +// compile-flags: --cap-lints allow + +#![deny(warnings)] + +use std::option; + +fn main() {} diff --git a/tests/ui/lint/lint-change-warnings.rs b/tests/ui/lint/lint-change-warnings.rs new file mode 100644 index 000000000..37af3b761 --- /dev/null +++ b/tests/ui/lint/lint-change-warnings.rs @@ -0,0 +1,21 @@ +#![deny(warnings)] +#![allow(dead_code)] + +fn main() { + while true {} //~ ERROR: infinite +} + +#[allow(warnings)] +fn foo() { + while true {} +} + +#[warn(warnings)] +fn bar() { + while true {} //~ WARNING: infinite +} + +#[forbid(warnings)] +fn baz() { + while true {} //~ ERROR: infinite +} diff --git a/tests/ui/lint/lint-change-warnings.stderr b/tests/ui/lint/lint-change-warnings.stderr new file mode 100644 index 000000000..3fd5283aa --- /dev/null +++ b/tests/ui/lint/lint-change-warnings.stderr @@ -0,0 +1,36 @@ +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-change-warnings.rs:5:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-change-warnings.rs:1:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(while_true)]` implied by `#[deny(warnings)]` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/lint-change-warnings.rs:15:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-change-warnings.rs:20:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-change-warnings.rs:18:10 + | +LL | #[forbid(warnings)] + | ^^^^^^^^ + = note: `#[forbid(while_true)]` implied by `#[forbid(warnings)]` + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/lint-const-item-mutation.rs b/tests/ui/lint/lint-const-item-mutation.rs new file mode 100644 index 000000000..4bf5e0a9e --- /dev/null +++ b/tests/ui/lint/lint-const-item-mutation.rs @@ -0,0 +1,66 @@ +// check-pass + +struct MyStruct { + field: bool, + inner_array: [char; 1], + raw_ptr: *mut u8 +} +impl MyStruct { + fn use_mut(&mut self) {} +} + +struct Mutable { + msg: &'static str, +} +impl Drop for Mutable { + fn drop(&mut self) { + println!("{}", self.msg); + } +} + +struct Mutable2 { // this one has drop glue but not a Drop impl + msg: &'static str, + other: String, +} + +const ARRAY: [u8; 1] = [25]; +const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; +const RAW_PTR: *mut u8 = 1 as *mut u8; +const MUTABLE: Mutable = Mutable { msg: "" }; +const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; +const VEC: Vec = Vec::new(); +const PTR: *mut () = 1 as *mut _; +const PTR_TO_ARRAY: *mut [u32; 4] = 0x12345678 as _; +const ARRAY_OF_PTR: [*mut u32; 1] = [1 as *mut _]; + +fn main() { + ARRAY[0] = 5; //~ WARN attempting to modify + MY_STRUCT.field = false; //~ WARN attempting to modify + MY_STRUCT.inner_array[0] = 'b'; //~ WARN attempting to modify + MY_STRUCT.use_mut(); //~ WARN taking + &mut MY_STRUCT; //~ WARN taking + (&mut MY_STRUCT).use_mut(); //~ WARN taking + + // Test that we don't warn when writing through + // a raw pointer + // This is U.B., but this test is check-pass, + // so this never actually executes + unsafe { + *RAW_PTR = 0; + *MY_STRUCT.raw_ptr = 0; + } + + MUTABLE.msg = "wow"; // no warning, because Drop observes the mutation + MUTABLE2.msg = "wow"; //~ WARN attempting to modify + VEC.push(0); //~ WARN taking a mutable reference to a `const` item + + // Test that we don't warn when converting a raw pointer + // into a mutable reference + unsafe { &mut *PTR }; + + // Test that we don't warn when there's a dereference involved. + // If we ever 'leave' the const via a deference, we're going + // to end up modifying something other than the temporary + unsafe { (*PTR_TO_ARRAY)[0] = 1 }; + unsafe { *ARRAY_OF_PTR[0] = 25; } +} diff --git a/tests/ui/lint/lint-const-item-mutation.stderr b/tests/ui/lint/lint-const-item-mutation.stderr new file mode 100644 index 000000000..747c38b80 --- /dev/null +++ b/tests/ui/lint/lint-const-item-mutation.stderr @@ -0,0 +1,118 @@ +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:37:5 + | +LL | ARRAY[0] = 5; + | ^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:26:1 + | +LL | const ARRAY: [u8; 1] = [25]; + | ^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:38:5 + | +LL | MY_STRUCT.field = false; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:39:5 + | +LL | MY_STRUCT.inner_array[0] = 'b'; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:40:5 + | +LL | MY_STRUCT.use_mut(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: mutable reference created due to call to this method + --> $DIR/lint-const-item-mutation.rs:9:5 + | +LL | fn use_mut(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^ +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:41:5 + | +LL | &mut MY_STRUCT; + | ^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:42:5 + | +LL | (&mut MY_STRUCT).use_mut(); + | ^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:27:1 + | +LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: attempting to modify a `const` item + --> $DIR/lint-const-item-mutation.rs:54:5 + | +LL | MUTABLE2.msg = "wow"; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:30:1 + | +LL | const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: taking a mutable reference to a `const` item + --> $DIR/lint-const-item-mutation.rs:55:5 + | +LL | VEC.push(0); + | ^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: mutable reference created due to call to this method + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +note: `const` item defined here + --> $DIR/lint-const-item-mutation.rs:31:1 + | +LL | const VEC: Vec = Vec::new(); + | ^^^^^^^^^^^^^^^^^^^ + +warning: 8 warnings emitted + diff --git a/tests/ui/lint/lint-ctypes-66202.rs b/tests/ui/lint/lint-ctypes-66202.rs new file mode 100644 index 000000000..ebab41d14 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-66202.rs @@ -0,0 +1,17 @@ +// check-pass + +#![deny(improper_ctypes)] + +// This test checks that return types are normalized before being checked for FFI-safety, and that +// transparent newtype wrappers are FFI-safe if the type being wrapped is FFI-safe. + +#[repr(transparent)] +pub struct W(T); + +extern "C" { + pub fn bare() -> (); + pub fn normalize() -> <() as ToOwned>::Owned; + pub fn transparent() -> W<()>; +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-1.rs b/tests/ui/lint/lint-ctypes-73249-1.rs new file mode 100644 index 000000000..cf416c3fe --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-1.rs @@ -0,0 +1,21 @@ +// check-pass +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc: 'static; +} + +impl Foo for () { + type Assoc = u32; +} + +extern "C" { + pub fn lint_me(x: Bar<()>); +} + +#[repr(transparent)] +pub struct Bar { + value: &'static ::Assoc, +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-2.rs b/tests/ui/lint/lint-ctypes-73249-2.rs new file mode 100644 index 000000000..691047c8a --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-2.rs @@ -0,0 +1,29 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for () {} + +type Qux = impl Baz; + +fn assign() -> Qux {} + +pub trait Foo { + type Assoc: 'static; +} + +impl Foo for () { + type Assoc = Qux; +} + +#[repr(transparent)] +pub struct A { + x: &'static ::Assoc, +} + +extern "C" { + pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr new file mode 100644 index 000000000..8073c33dd --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-2.rs:26:25 + | +LL | pub fn lint_me() -> A<()>; + | ^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73249-3.rs b/tests/ui/lint/lint-ctypes-73249-3.rs new file mode 100644 index 000000000..ef8ab7e03 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-3.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for u32 {} + +type Qux = impl Baz; + +fn assign() -> Qux { + 3 +} + +#[repr(C)] +pub struct A { + x: Qux, +} + +extern "C" { + pub fn lint_me() -> A; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-3.stderr b/tests/ui/lint/lint-ctypes-73249-3.stderr new file mode 100644 index 000000000..c41ce666d --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-3.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-3.rs:20:25 + | +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-3.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73249-4.rs b/tests/ui/lint/lint-ctypes-73249-4.rs new file mode 100644 index 000000000..6c72bd691 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-4.rs @@ -0,0 +1,24 @@ +// check-pass +#![deny(improper_ctypes)] + +use std::marker::PhantomData; + +trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = PhantomData<()>; +} + +#[repr(transparent)] +struct Wow where T: Foo> { + x: ::Assoc, + v: u32, +} + +extern "C" { + fn test(v: Wow<()>); +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-5.rs b/tests/ui/lint/lint-ctypes-73249-5.rs new file mode 100644 index 000000000..083fb6c5f --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-5.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for u32 {} + +type Qux = impl Baz; + +fn assign() -> Qux { + 3 +} + +#[repr(transparent)] +pub struct A { + x: Qux, +} + +extern "C" { + pub fn lint_me() -> A; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-5.stderr b/tests/ui/lint/lint-ctypes-73249-5.stderr new file mode 100644 index 000000000..98245c4f1 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249-5.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-5.rs:20:25 + | +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-5.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73249.rs b/tests/ui/lint/lint-ctypes-73249.rs new file mode 100644 index 000000000..5b48fa9b7 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73249.rs @@ -0,0 +1,21 @@ +// check-pass +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +extern "C" { + pub fn lint_me(x: Bar<()>); +} + +#[repr(transparent)] +pub struct Bar { + value: ::Assoc, +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-1.rs b/tests/ui/lint/lint-ctypes-73251-1.rs new file mode 100644 index 000000000..145ba784f --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-1.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz {} + +impl Baz for u32 {} + +type Qux = impl Baz; + +pub trait Foo { + type Assoc; +} + +impl Foo for u32 { + type Assoc = Qux; +} + +fn assign() -> Qux { + 1 +} + +extern "C" { + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr new file mode 100644 index 000000000..9f43576ad --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-1.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `Qux`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-1.rs:23:25 + | +LL | pub fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-1.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73251-2.rs b/tests/ui/lint/lint-ctypes-73251-2.rs new file mode 100644 index 000000000..df71a9457 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-2.rs @@ -0,0 +1,39 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl TraitB for T +where + T: TraitA, +{ + type Assoc = ::Assoc; +} + +type AliasA = impl TraitA; + +type AliasB = impl TraitB; + +fn use_of_a() -> AliasA { + 3 +} + +fn use_of_b() -> AliasB { + 3 +} + +extern "C" { + pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr new file mode 100644 index 000000000..0b3de379c --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `AliasA`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-2.rs:36:25 + | +LL | pub fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-ctypes-73251.rs b/tests/ui/lint/lint-ctypes-73251.rs new file mode 100644 index 000000000..ebc2ca77b --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73251.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +type Bar = impl Foo; + +fn assign() -> Bar {} + +extern "C" { + pub fn lint_me() -> ::Assoc; +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73747.rs b/tests/ui/lint/lint-ctypes-73747.rs new file mode 100644 index 000000000..293ffd5c2 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-73747.rs @@ -0,0 +1,14 @@ +// check-pass + +#[repr(transparent)] +struct NonNullRawComPtr { + inner: std::ptr::NonNull<::VTable>, +} + +trait ComInterface { + type VTable; +} + +extern "C" fn invoke(_: Option>) {} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs new file mode 100644 index 000000000..7c2060805 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -0,0 +1,92 @@ +#![feature(transparent_unions)] +#![feature(ptr_internals)] +#![deny(improper_ctypes)] +#![allow(dead_code)] + +use std::num; + +enum Z {} +enum U { + A, +} +enum B { + C, + D, +} +enum T { + E, + F, + G, +} + +#[repr(C)] +enum ReprC { + A, + B, + C, +} + +#[repr(u8)] +enum U8 { + A, + B, + C, +} + +#[repr(isize)] +enum Isize { + A, + B, + C, +} + +#[repr(transparent)] +struct TransparentStruct(T, std::marker::PhantomData); + +#[repr(transparent)] +enum TransparentEnum { + Variant(T, std::marker::PhantomData), +} + +#[repr(transparent)] +union TransparentUnion { + field: T, +} + +struct Rust(T); + +extern "C" { + fn zf(x: Z); + fn uf(x: U); //~ ERROR `extern` block uses type `U` + fn bf(x: B); //~ ERROR `extern` block uses type `B` + fn tf(x: T); //~ ERROR `extern` block uses type `T` + fn repr_c(x: ReprC); + fn repr_u8(x: U8); + fn repr_isize(x: Isize); + fn option_ref(x: Option<&'static u8>); + fn option_fn(x: Option); + fn nonnull(x: Option>); + fn unique(x: Option>); + fn nonzero_u8(x: Option); + fn nonzero_u16(x: Option); + fn nonzero_u32(x: Option); + fn nonzero_u64(x: Option); + fn nonzero_u128(x: Option); + //~^ ERROR `extern` block uses type `u128` + fn nonzero_usize(x: Option); + fn nonzero_i8(x: Option); + fn nonzero_i16(x: Option); + fn nonzero_i32(x: Option); + fn nonzero_i64(x: Option); + fn nonzero_i128(x: Option); + //~^ ERROR `extern` block uses type `i128` + fn nonzero_isize(x: Option); + fn transparent_struct(x: Option>); + fn transparent_enum(x: Option>); + fn transparent_union(x: Option>); + //~^ ERROR `extern` block uses type + fn repr_rust(x: Option>); //~ ERROR `extern` block uses type + fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR `extern` block uses type +} + +pub fn main() {} diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr new file mode 100644 index 000000000..8554e2617 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -0,0 +1,92 @@ +error: `extern` block uses type `U`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:60:13 + | +LL | fn uf(x: U); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint +note: the type is defined here + --> $DIR/lint-ctypes-enum.rs:9:1 + | +LL | enum U { + | ^^^^^^ +note: the lint level is defined here + --> $DIR/lint-ctypes-enum.rs:3:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `B`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:61:13 + | +LL | fn bf(x: B); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint +note: the type is defined here + --> $DIR/lint-ctypes-enum.rs:12:1 + | +LL | enum B { + | ^^^^^^ + +error: `extern` block uses type `T`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:62:13 + | +LL | fn tf(x: T); + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint +note: the type is defined here + --> $DIR/lint-ctypes-enum.rs:16:1 + | +LL | enum T { + | ^^^^^^ + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:74:23 + | +LL | fn nonzero_u128(x: Option); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:81:23 + | +LL | fn nonzero_i128(x: Option); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `Option>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:86:28 + | +LL | fn transparent_union(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Option>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:88:20 + | +LL | fn repr_rust(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:89:20 + | +LL | fn no_result(x: Result<(), num::NonZeroI32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: aborting due to 8 previous errors + diff --git a/tests/ui/lint/lint-ctypes-fn.rs b/tests/ui/lint/lint-ctypes-fn.rs new file mode 100644 index 000000000..d3b36a9d5 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-fn.rs @@ -0,0 +1,196 @@ +#![feature(rustc_private)] + +#![allow(private_in_public)] +#![deny(improper_ctypes_definitions)] + +extern crate libc; + +use std::default::Default; +use std::marker::PhantomData; + +trait Trait {} + +trait Mirror { type It: ?Sized; } + +impl Mirror for T { type It = Self; } + +#[repr(C)] +pub struct StructWithProjection(*mut ::It); + +#[repr(C)] +pub struct StructWithProjectionAndLifetime<'a>( + &'a mut as Mirror>::It +); + +pub type I32Pair = (i32, i32); + +#[repr(C)] +pub struct ZeroSize; + +pub type RustFn = fn(); + +pub type RustBadRet = extern "C" fn() -> Box; + +pub type CVoidRet = (); + +pub struct Foo; + +#[repr(transparent)] +pub struct TransparentI128(i128); + +#[repr(transparent)] +pub struct TransparentStr(&'static str); + +#[repr(transparent)] +pub struct TransparentBadFn(RustBadRet); + +#[repr(transparent)] +pub struct TransparentInt(u32); + +#[repr(transparent)] +pub struct TransparentRef<'a>(&'a TransparentInt); + +#[repr(transparent)] +pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); + +#[repr(transparent)] +pub struct TransparentUnit(f32, PhantomData); + +#[repr(transparent)] +pub struct TransparentCustomZst(i32, ZeroSize); + +#[repr(C)] +pub struct ZeroSizeWithPhantomData(PhantomData); + +pub extern "C" fn ptr_type1(size: *const Foo) { } + +pub extern "C" fn ptr_type2(size: *const Foo) { } + +pub extern "C" fn ptr_unit(p: *const ()) { } + +pub extern "C" fn ptr_tuple(p: *const ((),)) { } + +pub extern "C" fn slice_type(p: &[u32]) { } +//~^ ERROR: uses type `[u32]` + +pub extern "C" fn str_type(p: &str) { } +//~^ ERROR: uses type `str` + +pub extern "C" fn box_type(p: Box) { } + +pub extern "C" fn opt_box_type(p: Option>) { } + +pub extern "C" fn boxed_slice(p: Box<[u8]>) { } +//~^ ERROR: uses type `Box<[u8]>` + +pub extern "C" fn boxed_string(p: Box) { } +//~^ ERROR: uses type `Box` + +pub extern "C" fn boxed_trait(p: Box) { } +//~^ ERROR: uses type `Box` + +pub extern "C" fn char_type(p: char) { } +//~^ ERROR uses type `char` + +pub extern "C" fn i128_type(p: i128) { } +//~^ ERROR uses type `i128` + +pub extern "C" fn u128_type(p: u128) { } +//~^ ERROR uses type `u128` + +pub extern "C" fn tuple_type(p: (i32, i32)) { } +//~^ ERROR uses type `(i32, i32)` + +pub extern "C" fn tuple_type2(p: I32Pair) { } +//~^ ERROR uses type `(i32, i32)` + +pub extern "C" fn zero_size(p: ZeroSize) { } +//~^ ERROR uses type `ZeroSize` + +pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } +//~^ ERROR uses type `ZeroSizeWithPhantomData` + +pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { +//~^ ERROR uses type `PhantomData` + Default::default() +} + +pub extern "C" fn fn_type(p: RustFn) { } +//~^ ERROR uses type `fn()` + +pub extern "C" fn fn_type2(p: fn()) { } +//~^ ERROR uses type `fn()` + +pub extern "C" fn fn_contained(p: RustBadRet) { } + +pub extern "C" fn transparent_i128(p: TransparentI128) { } +//~^ ERROR: uses type `i128` + +pub extern "C" fn transparent_str(p: TransparentStr) { } +//~^ ERROR: uses type `str` + +pub extern "C" fn transparent_fn(p: TransparentBadFn) { } + +pub extern "C" fn good3(fptr: Option) { } + +pub extern "C" fn good4(aptr: &[u8; 4 as usize]) { } + +pub extern "C" fn good5(s: StructWithProjection) { } + +pub extern "C" fn good6(s: StructWithProjectionAndLifetime) { } + +pub extern "C" fn good7(fptr: extern "C" fn() -> ()) { } + +pub extern "C" fn good8(fptr: extern "C" fn() -> !) { } + +pub extern "C" fn good9() -> () { } + +pub extern "C" fn good10() -> CVoidRet { } + +pub extern "C" fn good11(size: isize) { } + +pub extern "C" fn good12(size: usize) { } + +pub extern "C" fn good13(n: TransparentInt) { } + +pub extern "C" fn good14(p: TransparentRef) { } + +pub extern "C" fn good15(p: TransparentLifetime) { } + +pub extern "C" fn good16(p: TransparentUnit) { } + +pub extern "C" fn good17(p: TransparentCustomZst) { } + +#[allow(improper_ctypes_definitions)] +pub extern "C" fn good18(_: &String) { } + +#[cfg(not(target_arch = "wasm32"))] +pub extern "C" fn good1(size: *const libc::c_int) { } + +#[cfg(not(target_arch = "wasm32"))] +pub extern "C" fn good2(size: *const libc::c_uint) { } + +pub extern "C" fn unused_generic1(size: *const Foo) { } + +pub extern "C" fn unused_generic2() -> PhantomData { +//~^ ERROR uses type `PhantomData` + Default::default() +} + +pub extern "C" fn used_generic1(x: T) { } + +pub extern "C" fn used_generic2(x: T, size: *const Foo) { } + +pub extern "C" fn used_generic3() -> T { + Default::default() +} + +pub extern "C" fn used_generic4(x: Vec) { } +//~^ ERROR: uses type `Vec` + +pub extern "C" fn used_generic5() -> Vec { +//~^ ERROR: uses type `Vec` + Default::default() +} + +fn main() {} diff --git a/tests/ui/lint/lint-ctypes-fn.stderr b/tests/ui/lint/lint-ctypes-fn.stderr new file mode 100644 index 000000000..a05206bf1 --- /dev/null +++ b/tests/ui/lint/lint-ctypes-fn.stderr @@ -0,0 +1,188 @@ +error: `extern` fn uses type `[u32]`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:73:33 + | +LL | pub extern "C" fn slice_type(p: &[u32]) { } + | ^^^^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent +note: the lint level is defined here + --> $DIR/lint-ctypes-fn.rs:4:9 + | +LL | #![deny(improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:76:31 + | +LL | pub extern "C" fn str_type(p: &str) { } + | ^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:83:34 + | +LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { } + | ^^^^^^^^^ not FFI-safe + | + = note: box cannot be represented as a single pointer + +error: `extern` fn uses type `Box`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:86:35 + | +LL | pub extern "C" fn boxed_string(p: Box) { } + | ^^^^^^^^ not FFI-safe + | + = note: box cannot be represented as a single pointer + +error: `extern` fn uses type `Box`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:89:34 + | +LL | pub extern "C" fn boxed_trait(p: Box) { } + | ^^^^^^^^^^^^^^ not FFI-safe + | + = note: box cannot be represented as a single pointer + +error: `extern` fn uses type `char`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:92:32 + | +LL | pub extern "C" fn char_type(p: char) { } + | ^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent + +error: `extern` fn uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:95:32 + | +LL | pub extern "C" fn i128_type(p: i128) { } + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:98:32 + | +LL | pub extern "C" fn u128_type(p: u128) { } + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:101:33 + | +LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } + | ^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:104:34 + | +LL | pub extern "C" fn tuple_type2(p: I32Pair) { } + | ^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` fn uses type `ZeroSize`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:107:32 + | +LL | pub extern "C" fn zero_size(p: ZeroSize) { } + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a member to this struct + = note: this struct has no fields +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:28:1 + | +LL | pub struct ZeroSize; + | ^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:110:40 + | +LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:63:1 + | +LL | pub struct ZeroSizeWithPhantomData(PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `PhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:113:51 + | +LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData { + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` fn uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:118:30 + | +LL | pub extern "C" fn fn_type(p: RustFn) { } + | ^^^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` fn uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:121:31 + | +LL | pub extern "C" fn fn_type2(p: fn()) { } + | ^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` fn uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:126:39 + | +LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } + | ^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:129:38 + | +LL | pub extern "C" fn transparent_str(p: TransparentStr) { } + | ^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` fn uses type `PhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:175:43 + | +LL | pub extern "C" fn unused_generic2() -> PhantomData { + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` fn uses type `Vec`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:188:39 + | +LL | pub extern "C" fn used_generic4(x: Vec) { } + | ^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` fn uses type `Vec`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:191:41 + | +LL | pub extern "C" fn used_generic5() -> Vec { + | ^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: aborting due to 20 previous errors + diff --git a/tests/ui/lint/lint-ctypes.rs b/tests/ui/lint/lint-ctypes.rs new file mode 100644 index 000000000..9165e14b7 --- /dev/null +++ b/tests/ui/lint/lint-ctypes.rs @@ -0,0 +1,118 @@ +#![feature(rustc_private)] + +#![allow(private_in_public)] +#![deny(improper_ctypes)] + +extern crate libc; + +use std::cell::UnsafeCell; +use std::marker::PhantomData; + +trait Bar { } +trait Mirror { type It: ?Sized; } +impl Mirror for T { type It = Self; } +#[repr(C)] +pub struct StructWithProjection(*mut ::It); +#[repr(C)] +pub struct StructWithProjectionAndLifetime<'a>( + &'a mut as Mirror>::It +); +pub type I32Pair = (i32, i32); +#[repr(C)] +pub struct ZeroSize; +pub type RustFn = fn(); +pub type RustBadRet = extern "C" fn() -> Box; +pub type CVoidRet = (); +pub struct Foo; +#[repr(transparent)] +pub struct TransparentI128(i128); +#[repr(transparent)] +pub struct TransparentStr(&'static str); +#[repr(transparent)] +pub struct TransparentBadFn(RustBadRet); +#[repr(transparent)] +pub struct TransparentInt(u32); +#[repr(transparent)] +pub struct TransparentRef<'a>(&'a TransparentInt); +#[repr(transparent)] +pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); +#[repr(transparent)] +pub struct TransparentUnit(f32, PhantomData); +#[repr(transparent)] +pub struct TransparentCustomZst(i32, ZeroSize); + +#[repr(C)] +pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); + +extern "C" { + pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo` + pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo` + pub fn ptr_unit(p: *const ()); + pub fn ptr_tuple(p: *const ((),)); //~ ERROR: uses type `((),)` + pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]` + pub fn str_type(p: &str); //~ ERROR: uses type `str` + pub fn box_type(p: Box); //~ ERROR uses type `Box` + pub fn opt_box_type(p: Option>); + //~^ ERROR uses type `Option>` + pub fn char_type(p: char); //~ ERROR uses type `char` + pub fn i128_type(p: i128); //~ ERROR uses type `i128` + pub fn u128_type(p: u128); //~ ERROR uses type `u128` + pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar` + pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)` + pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)` + pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize` + pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); + //~^ ERROR uses type `ZeroSizeWithPhantomData` + pub fn zero_size_phantom_toplevel() + -> ::std::marker::PhantomData; //~ ERROR uses type `PhantomData` + pub fn fn_type(p: RustFn); //~ ERROR uses type `fn()` + pub fn fn_type2(p: fn()); //~ ERROR uses type `fn()` + pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `Box` + pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128` + pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str` + pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `Box` + pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]` + + pub fn no_niche_a(a: Option>); + //~^ ERROR: uses type `Option>` + pub fn no_niche_b(b: Option>); + //~^ ERROR: uses type `Option>` + + pub static static_u128_type: u128; //~ ERROR: uses type `u128` + pub static static_u128_array_type: [u128; 16]; //~ ERROR: uses type `u128` + + pub fn good3(fptr: Option); + pub fn good4(aptr: &[u8; 4 as usize]); + pub fn good5(s: StructWithProjection); + pub fn good6(s: StructWithProjectionAndLifetime); + pub fn good7(fptr: extern "C" fn() -> ()); + pub fn good8(fptr: extern "C" fn() -> !); + pub fn good9() -> (); + pub fn good10() -> CVoidRet; + pub fn good11(size: isize); + pub fn good12(size: usize); + pub fn good13(n: TransparentInt); + pub fn good14(p: TransparentRef); + pub fn good15(p: TransparentLifetime); + pub fn good16(p: TransparentUnit); + pub fn good17(p: TransparentCustomZst); + #[allow(improper_ctypes)] + pub fn good18(_: &String); + pub fn good20(arr: *const [u8; 8]); + pub static good21: [u8; 8]; + +} + +#[allow(improper_ctypes)] +extern "C" { + pub fn good19(_: &String); +} + +#[cfg(not(target_arch = "wasm32"))] +extern "C" { + pub fn good1(size: *const libc::c_int); + pub fn good2(size: *const libc::c_uint); +} + +fn main() { +} diff --git a/tests/ui/lint/lint-ctypes.stderr b/tests/ui/lint/lint-ctypes.stderr new file mode 100644 index 000000000..121ad0ce8 --- /dev/null +++ b/tests/ui/lint/lint-ctypes.stderr @@ -0,0 +1,262 @@ +error: `extern` block uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:48:28 + | +LL | pub fn ptr_type1(size: *const Foo); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/lint-ctypes.rs:26:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/lint-ctypes.rs:4:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:49:28 + | +LL | pub fn ptr_type2(size: *const Foo); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/lint-ctypes.rs:26:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ + +error: `extern` block uses type `((),)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:51:25 + | +LL | pub fn ptr_tuple(p: *const ((),)); + | ^^^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` block uses type `[u32]`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:52:26 + | +LL | pub fn slice_type(p: &[u32]); + | ^^^^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent + +error: `extern` block uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:53:24 + | +LL | pub fn str_type(p: &str); + | ^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` block uses type `Box`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:54:24 + | +LL | pub fn box_type(p: Box); + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `Option>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:55:28 + | +LL | pub fn opt_box_type(p: Option>); + | ^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `char`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:57:25 + | +LL | pub fn char_type(p: char); + | ^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:58:25 + | +LL | pub fn i128_type(p: i128); + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:59:25 + | +LL | pub fn u128_type(p: u128); + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `dyn Bar`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:60:26 + | +LL | pub fn trait_type(p: &dyn Bar); + | ^^^^^^^^ not FFI-safe + | + = note: trait objects have no C equivalent + +error: `extern` block uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:61:26 + | +LL | pub fn tuple_type(p: (i32, i32)); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` block uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:62:27 + | +LL | pub fn tuple_type2(p: I32Pair); + | ^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` block uses type `ZeroSize`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:63:25 + | +LL | pub fn zero_size(p: ZeroSize); + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a member to this struct + = note: this struct has no fields +note: the type is defined here + --> $DIR/lint-ctypes.rs:22:1 + | +LL | pub struct ZeroSize; + | ^^^^^^^^^^^^^^^^^^^ + +error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:64:33 + | +LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` +note: the type is defined here + --> $DIR/lint-ctypes.rs:45:1 + | +LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` block uses type `PhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:67:12 + | +LL | -> ::std::marker::PhantomData; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` block uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:68:23 + | +LL | pub fn fn_type(p: RustFn); + | ^^^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` block uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:69:24 + | +LL | pub fn fn_type2(p: fn()); + | ^^^^ not FFI-safe + | + = help: consider using an `extern fn(...) -> ...` function pointer instead + = note: this function pointer has Rust-specific calling convention + +error: `extern` block uses type `Box`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:70:28 + | +LL | pub fn fn_contained(p: RustBadRet); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:71:32 + | +LL | pub fn transparent_i128(p: TransparentI128); + | ^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:72:31 + | +LL | pub fn transparent_str(p: TransparentStr); + | ^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `*const u8` and a length instead + = note: string slices have no C equivalent + +error: `extern` block uses type `Box`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:73:30 + | +LL | pub fn transparent_fn(p: TransparentBadFn); + | ^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` block uses type `[u8; 8]`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:74:27 + | +LL | pub fn raw_array(arr: [u8; 8]); + | ^^^^^^^ not FFI-safe + | + = help: consider passing a pointer to the array + = note: passing raw arrays by value is not FFI-safe + +error: `extern` block uses type `Option>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:76:26 + | +LL | pub fn no_niche_a(a: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `Option>`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:78:26 + | +LL | pub fn no_niche_b(b: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:81:34 + | +LL | pub static static_u128_type: u128; + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` block uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:82:40 + | +LL | pub static static_u128_array_type: [u128; 16]; + | ^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: aborting due to 27 previous errors + diff --git a/tests/ui/lint/lint-deref-nullptr.rs b/tests/ui/lint/lint-deref-nullptr.rs new file mode 100644 index 000000000..d052dbd9b --- /dev/null +++ b/tests/ui/lint/lint-deref-nullptr.rs @@ -0,0 +1,38 @@ +// test the deref_nullptr lint + +#![deny(deref_nullptr)] + +use std::ptr; + +struct Struct { + field: u8, +} + +fn f() { + unsafe { + let a = 1; + let ub = *(a as *const i32); + let ub = *(0 as *const i32); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null::(); + //~^ ERROR dereferencing a null pointer + let ub = *ptr::null_mut::(); + //~^ ERROR dereferencing a null pointer + let ub = *(ptr::null::() as *const i32); + //~^ ERROR dereferencing a null pointer + let ub = *(ptr::null::() as *mut i32 as *mut usize as *const u8); + //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null::(); + //~^ ERROR dereferencing a null pointer + let ub = &*ptr::null_mut::(); + //~^ ERROR dereferencing a null pointer + ptr::addr_of!(*ptr::null::()); + //~^ ERROR dereferencing a null pointer + ptr::addr_of_mut!(*ptr::null_mut::()); + //~^ ERROR dereferencing a null pointer + let offset = ptr::addr_of!((*ptr::null::()).field); + //~^ ERROR dereferencing a null pointer + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-deref-nullptr.stderr b/tests/ui/lint/lint-deref-nullptr.stderr new file mode 100644 index 000000000..c6f432e4e --- /dev/null +++ b/tests/ui/lint/lint-deref-nullptr.stderr @@ -0,0 +1,68 @@ +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:15:18 + | +LL | let ub = *(0 as *const i32); + | ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + | +note: the lint level is defined here + --> $DIR/lint-deref-nullptr.rs:3:9 + | +LL | #![deny(deref_nullptr)] + | ^^^^^^^^^^^^^ + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:17:18 + | +LL | let ub = *ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:19:18 + | +LL | let ub = *ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:21:18 + | +LL | let ub = *(ptr::null::() as *const i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:23:18 + | +LL | let ub = *(ptr::null::() as *mut i32 as *mut usize as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:25:19 + | +LL | let ub = &*ptr::null::(); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:27:19 + | +LL | let ub = &*ptr::null_mut::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:29:23 + | +LL | ptr::addr_of!(*ptr::null::()); + | ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:31:27 + | +LL | ptr::addr_of_mut!(*ptr::null_mut::()); + | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: dereferencing a null pointer + --> $DIR/lint-deref-nullptr.rs:33:36 + | +LL | let offset = ptr::addr_of!((*ptr::null::()).field); + | ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-directives-on-use-items-issue-10534.rs b/tests/ui/lint/lint-directives-on-use-items-issue-10534.rs new file mode 100644 index 000000000..e5cb0d3df --- /dev/null +++ b/tests/ui/lint/lint-directives-on-use-items-issue-10534.rs @@ -0,0 +1,24 @@ +#![deny(unused_imports)] +#![allow(non_upper_case_globals)] + +// The aim of this test is to ensure that deny/allow/warn directives +// are applied to individual "use" statements instead of silently +// ignored. + +#[allow(dead_code)] +mod a { pub static x: isize = 3; pub static y: isize = 4; } + +mod b { + use a::x; //~ ERROR: unused import + #[allow(unused_imports)] + use a::y; // no error here +} + +#[allow(unused_imports)] +mod c { + use a::x; + #[deny(unused_imports)] + use a::y; //~ ERROR: unused import +} + +fn main() {} diff --git a/tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr b/tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr new file mode 100644 index 000000000..ccb139e0e --- /dev/null +++ b/tests/ui/lint/lint-directives-on-use-items-issue-10534.stderr @@ -0,0 +1,26 @@ +error: unused import: `a::x` + --> $DIR/lint-directives-on-use-items-issue-10534.rs:12:9 + | +LL | use a::x; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-directives-on-use-items-issue-10534.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `a::y` + --> $DIR/lint-directives-on-use-items-issue-10534.rs:21:9 + | +LL | use a::y; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-directives-on-use-items-issue-10534.rs:20:12 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-enum-intrinsics-non-enums.rs b/tests/ui/lint/lint-enum-intrinsics-non-enums.rs new file mode 100644 index 000000000..8ad337064 --- /dev/null +++ b/tests/ui/lint/lint-enum-intrinsics-non-enums.rs @@ -0,0 +1,67 @@ +// Test the enum_intrinsics_non_enums lint. + +#![feature(variant_count)] + +use std::mem::{discriminant, variant_count}; + +enum SomeEnum { + A, + B, +} + +struct SomeStruct; + +fn generic_discriminant(v: &T) { + discriminant::(v); +} + +fn generic_variant_count() -> usize { + variant_count::() +} + +fn test_discriminant() { + discriminant(&SomeEnum::A); + generic_discriminant(&SomeEnum::B); + + discriminant(&()); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&&SomeEnum::B); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&SomeStruct); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&123u32); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + + discriminant(&&123i8); + //~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type +} + +fn test_variant_count() { + variant_count::(); + generic_variant_count::(); + + variant_count::<&str>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<*const u8>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<()>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + + variant_count::<&SomeEnum>(); + //~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type +} + +fn main() { + test_discriminant(); + test_variant_count(); + + // The lint ignores cases where the type is generic, so these should be + // allowed even though their return values are unspecified + generic_variant_count::(); + generic_discriminant::(&SomeStruct); +} diff --git a/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr b/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr new file mode 100644 index 000000000..63ed2503c --- /dev/null +++ b/tests/ui/lint/lint-enum-intrinsics-non-enums.stderr @@ -0,0 +1,95 @@ +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:26:5 + | +LL | discriminant(&()); + | ^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:26:18 + | +LL | discriminant(&()); + | ^^^ + = note: `#[deny(enum_intrinsics_non_enums)]` on by default + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:29:5 + | +LL | discriminant(&&SomeEnum::B); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&SomeEnum`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:29:18 + | +LL | discriminant(&&SomeEnum::B); + | ^^^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:32:5 + | +LL | discriminant(&SomeStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `SomeStruct`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:32:18 + | +LL | discriminant(&SomeStruct); + | ^^^^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:35:5 + | +LL | discriminant(&123u32); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `u32`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:35:18 + | +LL | discriminant(&123u32); + | ^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:38:5 + | +LL | discriminant(&&123i8); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&i8`, which is not an enum. + --> $DIR/lint-enum-intrinsics-non-enums.rs:38:18 + | +LL | discriminant(&&123i8); + | ^^^^^^^ + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:46:5 + | +LL | variant_count::<&str>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&str`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:49:5 + | +LL | variant_count::<*const u8>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `*const u8`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:52:5 + | +LL | variant_count::<()>(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `()`, which is not an enum. + +error: the return value of `mem::variant_count` is unspecified when called with a non-enum type + --> $DIR/lint-enum-intrinsics-non-enums.rs:55:5 + | +LL | variant_count::<&SomeEnum>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&SomeEnum`, which is not an enum. + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr new file mode 100644 index 000000000..3a84c6c1f --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr @@ -0,0 +1,152 @@ +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:18:20 + | +LL | const N: i32 = T::N << 42; + | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:10:9 + | +LL | #![warn(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: 24 warnings emitted + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr new file mode 100644 index 000000000..3a84c6c1f --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr @@ -0,0 +1,152 @@ +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:18:20 + | +LL | const N: i32 = T::N << 42; + | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:10:9 + | +LL | #![warn(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: 24 warnings emitted + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..3a84c6c1f --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr @@ -0,0 +1,152 @@ +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:18:20 + | +LL | const N: i32 = T::N << 42; + | ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:10:9 + | +LL | #![warn(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left by `42_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow + +warning: 24 warnings emitted + diff --git a/tests/ui/lint/lint-exceeding-bitshifts.rs b/tests/ui/lint/lint-exceeding-bitshifts.rs new file mode 100644 index 000000000..048c1aff8 --- /dev/null +++ b/tests/ui/lint/lint-exceeding-bitshifts.rs @@ -0,0 +1,79 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O +// build-pass +// ignore-pass (test emits codegen-time warnings and verifies that they are not errors) +// normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which" + +#![crate_type="lib"] +#![warn(arithmetic_overflow)] + + +pub trait Foo { + const N: i32; +} + +impl Foo for Vec { + const N: i32 = T::N << 42; //~ WARN: arithmetic operation will overflow +} + +pub fn foo(x: i32) { + let _ = x << 42; //~ WARN: arithmetic operation will overflow +} + +pub fn main() { + let n = 1u8 << 7; + let n = 1u8 << 8; //~ WARN: arithmetic operation will overflow + let n = 1u16 << 15; + let n = 1u16 << 16; //~ WARN: arithmetic operation will overflow + let n = 1u32 << 31; + let n = 1u32 << 32; //~ WARN: arithmetic operation will overflow + let n = 1u64 << 63; + let n = 1u64 << 64; //~ WARN: arithmetic operation will overflow + let n = 1i8 << 7; + let n = 1i8 << 8; //~ WARN: arithmetic operation will overflow + let n = 1i16 << 15; + let n = 1i16 << 16; //~ WARN: arithmetic operation will overflow + let n = 1i32 << 31; + let n = 1i32 << 32; //~ WARN: arithmetic operation will overflow + let n = 1i64 << 63; + let n = 1i64 << 64; //~ WARN: arithmetic operation will overflow + + let n = 1u8 >> 7; + let n = 1u8 >> 8; //~ WARN: arithmetic operation will overflow + let n = 1u16 >> 15; + let n = 1u16 >> 16; //~ WARN: arithmetic operation will overflow + let n = 1u32 >> 31; + let n = 1u32 >> 32; //~ WARN: arithmetic operation will overflow + let n = 1u64 >> 63; + let n = 1u64 >> 64; //~ WARN: arithmetic operation will overflow + let n = 1i8 >> 7; + let n = 1i8 >> 8; //~ WARN: arithmetic operation will overflow + let n = 1i16 >> 15; + let n = 1i16 >> 16; //~ WARN: arithmetic operation will overflow + let n = 1i32 >> 31; + let n = 1i32 >> 32; //~ WARN: arithmetic operation will overflow + let n = 1i64 >> 63; + let n = 1i64 >> 64; //~ WARN: arithmetic operation will overflow + + let n = 1u8; + let n = n << 7; + let n = n << 8; //~ WARN: arithmetic operation will overflow + + let n = 1u8 << -8; //~ WARN: arithmetic operation will overflow + + let n = 1i8<<(1isize+-1); + + let n = 1u8 << (4+3); + let n = 1u8 << (4+4); //~ WARN: arithmetic operation will overflow + let n = 1i64 >> [63][0]; + let n = 1i64 >> [64][0]; //~ WARN: arithmetic operation will overflow + + #[cfg(target_pointer_width = "32")] + const BITS: usize = 32; + #[cfg(target_pointer_width = "64")] + const BITS: usize = 64; + let n = 1_isize << BITS; //~ WARN: arithmetic operation will overflow + let n = 1_usize << BITS; //~ WARN: arithmetic operation will overflow +} diff --git a/tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs b/tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs new file mode 100644 index 000000000..07a32904a --- /dev/null +++ b/tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(stmt_expr_attributes)] +#![deny(unused_parens)] + +// Tests that lint attributes on statements/expressions are +// correctly applied to non-builtin early (AST) lints + +fn main() { + #[allow(unused_parens)] + { + let _ = (9); + } +} diff --git a/tests/ui/lint/lint-ffi-safety-all-phantom.rs b/tests/ui/lint/lint-ffi-safety-all-phantom.rs new file mode 100644 index 000000000..7419d3458 --- /dev/null +++ b/tests/ui/lint/lint-ffi-safety-all-phantom.rs @@ -0,0 +1,22 @@ +// This is a regression test for issue https://github.com/rust-lang/rust/issues/106629. +// It ensures that transparent types where all fields are PhantomData are marked as +// FFI-safe. + +// check-pass + +#[repr(transparent)] +#[derive(Copy, Clone)] +struct MyPhantom(core::marker::PhantomData); + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Bar { + pub x: i32, + _marker: MyPhantom, +} + +extern "C" { + pub fn foo(bar: *mut Bar); +} + +fn main() {} diff --git a/tests/ui/lint/lint-forbid-attr.rs b/tests/ui/lint/lint-forbid-attr.rs new file mode 100644 index 000000000..6d4cfd834 --- /dev/null +++ b/tests/ui/lint/lint-forbid-attr.rs @@ -0,0 +1,7 @@ +#![forbid(deprecated)] + +#[allow(deprecated)] +//~^ ERROR allow(deprecated) incompatible +//~| ERROR allow(deprecated) incompatible +fn main() { +} diff --git a/tests/ui/lint/lint-forbid-attr.stderr b/tests/ui/lint/lint-forbid-attr.stderr new file mode 100644 index 000000000..5977b9c94 --- /dev/null +++ b/tests/ui/lint/lint-forbid-attr.stderr @@ -0,0 +1,21 @@ +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-attr.rs:3:9 + | +LL | #![forbid(deprecated)] + | ---------- `forbid` level set here +LL | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-attr.rs:3:9 + | +LL | #![forbid(deprecated)] + | ---------- `forbid` level set here +LL | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/lint-forbid-cmdline.rs b/tests/ui/lint/lint-forbid-cmdline.rs new file mode 100644 index 000000000..5246ccb57 --- /dev/null +++ b/tests/ui/lint/lint-forbid-cmdline.rs @@ -0,0 +1,6 @@ +// compile-flags: -F deprecated + +#[allow(deprecated)] //~ ERROR allow(deprecated) incompatible + //~| ERROR allow(deprecated) incompatible +fn main() { +} diff --git a/tests/ui/lint/lint-forbid-cmdline.stderr b/tests/ui/lint/lint-forbid-cmdline.stderr new file mode 100644 index 000000000..0a92e58c0 --- /dev/null +++ b/tests/ui/lint/lint-forbid-cmdline.stderr @@ -0,0 +1,19 @@ +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-cmdline.rs:3:9 + | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error[E0453]: allow(deprecated) incompatible with previous forbid + --> $DIR/lint-forbid-cmdline.rs:3:9 + | +LL | #[allow(deprecated)] + | ^^^^^^^^^^ overruled by previous forbid + | + = note: `forbid` lint level was set on command line + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.rs b/tests/ui/lint/lint-forbid-internal-unsafe.rs new file mode 100644 index 000000000..3ee55ba96 --- /dev/null +++ b/tests/ui/lint/lint-forbid-internal-unsafe.rs @@ -0,0 +1,17 @@ +#![forbid(unsafe_code)] +#![feature(allow_internal_unsafe)] + +#[allow_internal_unsafe] +//~^ ERROR: `allow_internal_unsafe` allows defining +macro_rules! evil { + ($e:expr) => { + unsafe { + $e + } + } +} + +fn main() { + println!("{}", evil!(*(0 as *const u8))); + //~^ WARNING dereferencing a null pointer +} diff --git a/tests/ui/lint/lint-forbid-internal-unsafe.stderr b/tests/ui/lint/lint-forbid-internal-unsafe.stderr new file mode 100644 index 000000000..ba425ceb4 --- /dev/null +++ b/tests/ui/lint/lint-forbid-internal-unsafe.stderr @@ -0,0 +1,22 @@ +error: `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site + --> $DIR/lint-forbid-internal-unsafe.rs:4:1 + | +LL | #[allow_internal_unsafe] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-forbid-internal-unsafe.rs:1:11 + | +LL | #![forbid(unsafe_code)] + | ^^^^^^^^^^^ + +warning: dereferencing a null pointer + --> $DIR/lint-forbid-internal-unsafe.rs:15:26 + | +LL | println!("{}", evil!(*(0 as *const u8))); + | ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed + | + = note: `#[warn(deref_nullptr)]` on by default + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-group-nonstandard-style.rs b/tests/ui/lint/lint-group-nonstandard-style.rs new file mode 100644 index 000000000..bd7f327bc --- /dev/null +++ b/tests/ui/lint/lint-group-nonstandard-style.rs @@ -0,0 +1,26 @@ +#![deny(nonstandard_style)] +#![allow(dead_code)] + +fn CamelCase() {} //~ ERROR should have a snake + +#[allow(nonstandard_style)] +mod test { + fn CamelCase() {} + + #[forbid(nonstandard_style)] + mod bad { + fn CamelCase() {} //~ ERROR should have a snake + + static bad: isize = 1; //~ ERROR should have an upper + } + + mod warn { + #![warn(nonstandard_style)] + + fn CamelCase() {} //~ WARN should have a snake + + struct snake_case; //~ WARN should have an upper camel + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-group-nonstandard-style.stderr b/tests/ui/lint/lint-group-nonstandard-style.stderr new file mode 100644 index 000000000..fcd010123 --- /dev/null +++ b/tests/ui/lint/lint-group-nonstandard-style.stderr @@ -0,0 +1,57 @@ +warning: type `snake_case` should have an upper camel case name + --> $DIR/lint-group-nonstandard-style.rs:22:16 + | +LL | struct snake_case; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `SnakeCase` + | +note: the lint level is defined here + --> $DIR/lint-group-nonstandard-style.rs:18:17 + | +LL | #![warn(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[warn(non_camel_case_types)]` implied by `#[warn(nonstandard_style)]` + +error: function `CamelCase` should have a snake case name + --> $DIR/lint-group-nonstandard-style.rs:4:4 + | +LL | fn CamelCase() {} + | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` + | +note: the lint level is defined here + --> $DIR/lint-group-nonstandard-style.rs:1:9 + | +LL | #![deny(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[deny(non_snake_case)]` implied by `#[deny(nonstandard_style)]` + +error: function `CamelCase` should have a snake case name + --> $DIR/lint-group-nonstandard-style.rs:12:12 + | +LL | fn CamelCase() {} + | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` + | +note: the lint level is defined here + --> $DIR/lint-group-nonstandard-style.rs:10:14 + | +LL | #[forbid(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[forbid(non_snake_case)]` implied by `#[forbid(nonstandard_style)]` + +error: static variable `bad` should have an upper case name + --> $DIR/lint-group-nonstandard-style.rs:14:16 + | +LL | static bad: isize = 1; + | ^^^ help: convert the identifier to upper case: `BAD` + | + = note: `#[forbid(non_upper_case_globals)]` implied by `#[forbid(nonstandard_style)]` + +warning: function `CamelCase` should have a snake case name + --> $DIR/lint-group-nonstandard-style.rs:20:12 + | +LL | fn CamelCase() {} + | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case` + | + = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]` + +error: aborting due to 3 previous errors; 2 warnings emitted + diff --git a/tests/ui/lint/lint-impl-fn.rs b/tests/ui/lint/lint-impl-fn.rs new file mode 100644 index 000000000..46874d95c --- /dev/null +++ b/tests/ui/lint/lint-impl-fn.rs @@ -0,0 +1,33 @@ +#![allow(while_true)] +#![allow(dead_code)] + +struct A(isize); + +impl A { + fn foo(&self) { while true {} } + + #[deny(while_true)] + fn bar(&self) { while true {} } //~ ERROR: infinite loops +} + +#[deny(while_true)] +mod foo { + struct B(isize); + + impl B { + fn foo(&self) { while true {} } //~ ERROR: infinite loops + + #[allow(while_true)] + fn bar(&self) { while true {} } + } +} + +#[deny(while_true)] +fn main() { + while true {} //~ ERROR: infinite loops +} + +#[deny(while_true)] +fn bar() { + while cfg!(unix) {} // no error +} diff --git a/tests/ui/lint/lint-impl-fn.stderr b/tests/ui/lint/lint-impl-fn.stderr new file mode 100644 index 000000000..24ec9c7e4 --- /dev/null +++ b/tests/ui/lint/lint-impl-fn.stderr @@ -0,0 +1,38 @@ +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:10:21 + | +LL | fn bar(&self) { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-impl-fn.rs:9:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:18:25 + | +LL | fn foo(&self) { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-impl-fn.rs:13:8 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-impl-fn.rs:27:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-impl-fn.rs:25:8 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/lint-incoherent-auto-trait-objects.rs b/tests/ui/lint/lint-incoherent-auto-trait-objects.rs new file mode 100644 index 000000000..d53b51447 --- /dev/null +++ b/tests/ui/lint/lint-incoherent-auto-trait-objects.rs @@ -0,0 +1,19 @@ +trait Foo {} + +impl Foo for dyn Send {} + +impl Foo for dyn Send + Send {} +//~^ ERROR conflicting implementations +//~| hard error + +impl Foo for dyn Send + Sync {} + +impl Foo for dyn Sync + Send {} +//~^ ERROR conflicting implementations +//~| hard error + +impl Foo for dyn Send + Sync + Send {} +//~^ ERROR conflicting implementations +//~| hard error + +fn main() {} diff --git a/tests/ui/lint/lint-incoherent-auto-trait-objects.stderr b/tests/ui/lint/lint-incoherent-auto-trait-objects.stderr new file mode 100644 index 000000000..553ab3869 --- /dev/null +++ b/tests/ui/lint/lint-incoherent-auto-trait-objects.stderr @@ -0,0 +1,81 @@ +error: conflicting implementations of trait `Foo` for type `(dyn Send + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:5:1 + | +LL | impl Foo for dyn Send {} + | --------------------- first implementation here +LL | +LL | impl Foo for dyn Send + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + = note: `#[deny(order_dependent_trait_objects)]` on by default + +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:11:1 + | +LL | impl Foo for dyn Send + Sync {} + | ---------------------------- first implementation here +LL | +LL | impl Foo for dyn Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:15:1 + | +LL | impl Foo for dyn Sync + Send {} + | ---------------------------- first implementation here +... +LL | impl Foo for dyn Send + Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +error: aborting due to 3 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: conflicting implementations of trait `Foo` for type `(dyn Send + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:5:1 + | +LL | impl Foo for dyn Send {} + | --------------------- first implementation here +LL | +LL | impl Foo for dyn Send + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + = note: `#[deny(order_dependent_trait_objects)]` on by default + +Future breakage diagnostic: +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:11:1 + | +LL | impl Foo for dyn Send + Sync {} + | ---------------------------- first implementation here +LL | +LL | impl Foo for dyn Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + = note: `#[deny(order_dependent_trait_objects)]` on by default + +Future breakage diagnostic: +error: conflicting implementations of trait `Foo` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/lint-incoherent-auto-trait-objects.rs:15:1 + | +LL | impl Foo for dyn Sync + Send {} + | ---------------------------- first implementation here +... +LL | impl Foo for dyn Send + Sync + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + = note: `#[deny(order_dependent_trait_objects)]` on by default + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-bool.rs b/tests/ui/lint/lint-invalid-atomic-ordering-bool.rs new file mode 100644 index 000000000..15ceb6195 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-bool.rs @@ -0,0 +1,28 @@ +// only-x86_64 +use std::sync::atomic::{AtomicBool, Ordering}; + +fn main() { + let x = AtomicBool::new(true); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Allowed store ordering modes + x.store(false, Ordering::Release); + x.store(false, Ordering::SeqCst); + x.store(false, Ordering::Relaxed); + + // Disallowed store ordering modes + x.store(false, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(false, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr new file mode 100644 index 000000000..9f38dcb0b --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-bool.stderr @@ -0,0 +1,35 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:13:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:15:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:24:20 + | +LL | x.store(false, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-bool.rs:26:20 + | +LL | x.store(false, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs new file mode 100644 index 000000000..63204c725 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.rs @@ -0,0 +1,50 @@ +// only-x86_64 +use std::sync::atomic::{AtomicPtr, Ordering}; + +fn main() { + let ptr = &mut 5; + let ptr2 = &mut 10; + // `compare_exchange_weak` testing + let x = AtomicPtr::new(ptr); + + // Allowed ordering combos + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::SeqCst); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Relaxed); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Acquire); + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::SeqCst); + + // AcqRel is always forbidden as a failure ordering + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + + // Release is always forbidden as a failure ordering + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); + //~^ ERROR `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel` +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr new file mode 100644 index 000000000..cc075ce9e --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr @@ -0,0 +1,83 @@ +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:28:67 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:30:67 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Acquire, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:32:67 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Release, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:34:66 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::AcqRel, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:36:66 + | +LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::SeqCst, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:40:67 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Relaxed, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:42:67 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Acquire, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:44:67 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::Release, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:46:66 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::AcqRel, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:48:66 + | +LL | let _ = x.compare_exchange_weak(ptr, ptr2, Ordering::SeqCst, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs new file mode 100644 index 000000000..488d268ee --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.rs @@ -0,0 +1,48 @@ +// only-x86_64 +use std::sync::atomic::{AtomicUsize, Ordering}; + +fn main() { + // `compare_exchange` (not weak) testing + let x = AtomicUsize::new(0); + + // Allowed ordering combos + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::SeqCst); + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Relaxed); + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Acquire); + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::SeqCst); + + // AcqRel is always forbidden as a failure ordering + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + + // Release is always forbidden as a failure ordering + let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); + //~^ ERROR `compare_exchange`'s failure ordering may not be `Release` or `AcqRel` +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr new file mode 100644 index 000000000..fe6c7e55c --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-exchange.stderr @@ -0,0 +1,83 @@ +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:26:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:28:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:30:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:32:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:34:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:38:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:40:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Acquire, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:42:57 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::Release, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:44:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::AcqRel, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-exchange.rs:46:56 + | +LL | let _ = x.compare_exchange(0, 0, Ordering::SeqCst, Ordering::Release); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs b/tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs new file mode 100644 index 000000000..4fb8605b4 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-false-positive.rs @@ -0,0 +1,18 @@ +// only-x86_64 +// check-pass +use std::sync::atomic::{AtomicUsize, Ordering}; + +trait Foo { + fn store(self, ordering: Ordering); +} + +impl Foo for AtomicUsize { + fn store(self, _ordering: Ordering) { + AtomicUsize::store(&self, 4, Ordering::SeqCst); + } +} + +fn main() { + let x = AtomicUsize::new(3); + x.store(Ordering::Acquire); +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fence.rs b/tests/ui/lint/lint-invalid-atomic-ordering-fence.rs new file mode 100644 index 000000000..22034472c --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fence.rs @@ -0,0 +1,21 @@ +// only-x86_64 +use std::sync::atomic::{compiler_fence, fence, Ordering}; + +fn main() { + // Allowed ordering modes + fence(Ordering::Acquire); + fence(Ordering::Release); + fence(Ordering::AcqRel); + fence(Ordering::SeqCst); + + compiler_fence(Ordering::Acquire); + compiler_fence(Ordering::Release); + compiler_fence(Ordering::AcqRel); + compiler_fence(Ordering::SeqCst); + + // Disallowed ordering modes + fence(Ordering::Relaxed); + //~^ ERROR memory fences cannot have `Relaxed` ordering + compiler_fence(Ordering::Relaxed); + //~^ ERROR memory fences cannot have `Relaxed` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr new file mode 100644 index 000000000..38327d607 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fence.stderr @@ -0,0 +1,19 @@ +error: memory fences cannot have `Relaxed` ordering + --> $DIR/lint-invalid-atomic-ordering-fence.rs:17:11 + | +LL | fence(Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: memory fences cannot have `Relaxed` ordering + --> $DIR/lint-invalid-atomic-ordering-fence.rs:19:20 + | +LL | compiler_fence(Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs new file mode 100644 index 000000000..734b63324 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.rs @@ -0,0 +1,49 @@ +// only-x86_64 +use std::sync::atomic::{AtomicIsize, Ordering}; + +fn main() { + // `fetch_update` testing + let x = AtomicIsize::new(0); + + // Allowed ordering combos + let _ = x.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Relaxed, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Relaxed, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Acquire, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Acquire, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Acquire, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Release, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Release, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::Release, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::AcqRel, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::AcqRel, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::AcqRel, Ordering::SeqCst, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::SeqCst, Ordering::Acquire, |old| Some(old + 1)); + let _ = x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |old| Some(old + 1)); + + // AcqRel is always forbidden as a failure ordering + let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + + // Release is always forbidden as a failure ordering + let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); + //~^ ERROR `fetch_update`'s failure ordering may not be `Release` or `AcqRel` + +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr new file mode 100644 index 000000000..33829d68f --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr @@ -0,0 +1,83 @@ +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:26:47 + | +LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:28:47 + | +LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:30:47 + | +LL | let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:32:46 + | +LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:34:46 + | +LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:38:47 + | +LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:40:47 + | +LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:42:47 + | +LL | let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:44:46 + | +LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write + --> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:46:46 + | +LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); + | ^^^^^^^^^^^^^^^^^ invalid failure ordering + | + = help: consider using `Acquire` or `Relaxed` failure ordering instead + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-int.rs b/tests/ui/lint/lint-invalid-atomic-ordering-int.rs new file mode 100644 index 000000000..462c9670f --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-int.rs @@ -0,0 +1,130 @@ +// FIXME: add support for `// only-atomic` to compiletest/header.rs +// only-x86_64 +use std::sync::atomic::{AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, Ordering}; + +fn main() { + // `AtomicI8` test cases + let x = AtomicI8::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicI16` test cases + let x = AtomicI16::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicI32` test cases + let x = AtomicI32::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicI64` test cases + let x = AtomicI64::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicIsize` test cases + let x = AtomicIsize::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-int.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-int.stderr new file mode 100644 index 000000000..36930e2f4 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-int.stderr @@ -0,0 +1,163 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:20:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:22:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:26:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:28:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:45:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:47:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:51:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:53:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:70:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:72:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:76:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:78:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:95:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:97:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:101:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:103:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:120:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:122:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:126:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-int.rs:128:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 20 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs new file mode 100644 index 000000000..984f7edeb --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.rs @@ -0,0 +1,30 @@ +// only-x86_64 +use std::sync::atomic::{AtomicPtr, Ordering}; + +fn main() { + let ptr = &mut 5; + let other_ptr = &mut 10; + let x = AtomicPtr::new(ptr); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Allowed store ordering modes + x.store(other_ptr, Ordering::Release); + x.store(other_ptr, Ordering::SeqCst); + x.store(other_ptr, Ordering::Relaxed); + + // Disallowed store ordering modes + x.store(other_ptr, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(other_ptr, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr new file mode 100644 index 000000000..12f4cad90 --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-ptr.stderr @@ -0,0 +1,35 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:15:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:17:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:26:24 + | +LL | x.store(other_ptr, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-ptr.rs:28:24 + | +LL | x.store(other_ptr, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-uint.rs b/tests/ui/lint/lint-invalid-atomic-ordering-uint.rs new file mode 100644 index 000000000..80ec3b9ee --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-uint.rs @@ -0,0 +1,129 @@ +// only-x86_64 +use std::sync::atomic::{AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering}; + +fn main() { + // `AtomicU8` test cases + let x = AtomicU8::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicU16` test cases + let x = AtomicU16::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicU32` test cases + let x = AtomicU32::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicU64` test cases + let x = AtomicU64::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + + // `AtomicUsize` test cases + let x = AtomicUsize::new(0); + + // Allowed load ordering modes + let _ = x.load(Ordering::Acquire); + let _ = x.load(Ordering::SeqCst); + let _ = x.load(Ordering::Relaxed); + + // Allowed store ordering modes + x.store(1, Ordering::Release); + x.store(1, Ordering::SeqCst); + x.store(1, Ordering::Relaxed); + + // Disallowed load ordering modes + let _ = x.load(Ordering::Release); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + let _ = x.load(Ordering::AcqRel); + //~^ ERROR atomic loads cannot have `Release` or `AcqRel` ordering + + // Disallowed store ordering modes + x.store(1, Ordering::Acquire); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering + x.store(1, Ordering::AcqRel); + //~^ ERROR atomic stores cannot have `Acquire` or `AcqRel` ordering +} diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr new file mode 100644 index 000000000..d26621f2a --- /dev/null +++ b/tests/ui/lint/lint-invalid-atomic-ordering-uint.stderr @@ -0,0 +1,163 @@ +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:19:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + = note: `#[deny(invalid_atomic_ordering)]` on by default + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:21:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:25:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:27:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:44:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:46:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:50:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:52:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:69:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:71:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:75:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:77:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:94:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:96:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:100:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:102:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:119:20 + | +LL | let _ = x.load(Ordering::Release); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic loads cannot have `Release` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:121:20 + | +LL | let _ = x.load(Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:125:16 + | +LL | x.store(1, Ordering::Acquire); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: atomic stores cannot have `Acquire` or `AcqRel` ordering + --> $DIR/lint-invalid-atomic-ordering-uint.rs:127:16 + | +LL | x.store(1, Ordering::AcqRel); + | ^^^^^^^^^^^^^^^^ + | + = help: consider using ordering modes `Release`, `SeqCst` or `Relaxed` + +error: aborting due to 20 previous errors + diff --git a/tests/ui/lint/lint-level-macro-def-mod.rs b/tests/ui/lint/lint-level-macro-def-mod.rs new file mode 100644 index 000000000..79f7d1206 --- /dev/null +++ b/tests/ui/lint/lint-level-macro-def-mod.rs @@ -0,0 +1,17 @@ +// This checks that exported macros lint as part of their module of origin, not +// the root module. +// +// check-pass + +//! Top level documentation +#![deny(missing_docs)] + +#[allow(missing_docs)] +mod module { + #[macro_export] + macro_rules! hello { + () => () + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-level-macro-def.rs b/tests/ui/lint/lint-level-macro-def.rs new file mode 100644 index 000000000..720f4b453 --- /dev/null +++ b/tests/ui/lint/lint-level-macro-def.rs @@ -0,0 +1,17 @@ +// Checks that you can set a lint level specficially for a macro definition. +// +// This is a regression test for issue #59306. +// +// check-pass + + +#[deny(missing_docs)] +mod module { + #[allow(missing_docs)] + #[macro_export] + macro_rules! hello { + () => () + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs b/tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs new file mode 100644 index 000000000..d085db43a --- /dev/null +++ b/tests/ui/lint/lint-lowercase-static-const-pattern-rename.rs @@ -0,0 +1,63 @@ +// check-pass +// Issue #7526: lowercase static constants in patterns look like bindings + +// This is similar to lint-lowercase-static-const-pattern.rs, except it +// shows the expected usual workaround (choosing a different name for +// the static definition) and also demonstrates that one can work +// around this problem locally by renaming the constant in the `use` +// form to an uppercase identifier that placates the lint. + +#![deny(non_upper_case_globals)] + +pub const A : isize = 97; + +fn f() { + let r = match (0,0) { + (0, A) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); + let r = match (0,97) { + (0, A) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 0); +} + +mod m { + #[allow(non_upper_case_globals)] + pub const aha : isize = 7; +} + +fn g() { + use self::m::aha as AHA; + let r = match (0,0) { + (0, AHA) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); + let r = match (0,7) { + (0, AHA) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 0); +} + +fn h() { + let r = match (0,0) { + (0, self::m::aha) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); + let r = match (0,7) { + (0, self::m::aha) => 0, + (x, y) => 1 + x + y, + }; + assert_eq!(r, 0); +} + +pub fn main () { + f(); + g(); + h(); +} diff --git a/tests/ui/lint/lint-lowercase-static-const-pattern.rs b/tests/ui/lint/lint-lowercase-static-const-pattern.rs new file mode 100644 index 000000000..c2e159eec --- /dev/null +++ b/tests/ui/lint/lint-lowercase-static-const-pattern.rs @@ -0,0 +1,51 @@ +// Issue #7526: lowercase static constants in patterns look like bindings + +#![allow(dead_code)] +#![deny(non_upper_case_globals)] + +#[allow(non_upper_case_globals)] +pub const a : isize = 97; + +fn f() { + let r = match (0,0) { + (0, a) => 0, + //~^ ERROR constant in pattern `a` should have an upper case name + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); +} + +mod m { + #[allow(non_upper_case_globals)] + pub const aha : isize = 7; +} + +fn g() { + use self::m::aha; + let r = match (0,0) { + (0, aha) => 0, + //~^ ERROR constant in pattern `aha` should have an upper case name + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); +} + +mod n { + pub const OKAY : isize = 8; +} + +fn h() { + use self::n::OKAY as not_okay; + let r = match (0,0) { + (0, not_okay) => 0, +//~^ ERROR constant in pattern `not_okay` should have an upper case name + (x, y) => 1 + x + y, + }; + assert_eq!(r, 1); +} + +fn main () { + f(); + g(); + h(); +} diff --git a/tests/ui/lint/lint-lowercase-static-const-pattern.stderr b/tests/ui/lint/lint-lowercase-static-const-pattern.stderr new file mode 100644 index 000000000..8780fac05 --- /dev/null +++ b/tests/ui/lint/lint-lowercase-static-const-pattern.stderr @@ -0,0 +1,26 @@ +error: constant in pattern `a` should have an upper case name + --> $DIR/lint-lowercase-static-const-pattern.rs:11:13 + | +LL | (0, a) => 0, + | ^ help: convert the identifier to upper case: `A` + | +note: the lint level is defined here + --> $DIR/lint-lowercase-static-const-pattern.rs:4:9 + | +LL | #![deny(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: constant in pattern `aha` should have an upper case name + --> $DIR/lint-lowercase-static-const-pattern.rs:26:13 + | +LL | (0, aha) => 0, + | ^^^ help: convert the identifier to upper case: `AHA` + +error: constant in pattern `not_okay` should have an upper case name + --> $DIR/lint-lowercase-static-const-pattern.rs:40:13 + | +LL | (0, not_okay) => 0, + | ^^^^^^^^ help: convert the identifier to upper case: `NOT_OKAY` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/lint-malformed.rs b/tests/ui/lint/lint-malformed.rs new file mode 100644 index 000000000..188e702f9 --- /dev/null +++ b/tests/ui/lint/lint-malformed.rs @@ -0,0 +1,6 @@ +#![deny = "foo"] //~ ERROR malformed `deny` attribute input +#![allow(bar = "baz")] //~ ERROR malformed lint attribute + //~| ERROR malformed lint attribute + //~| ERROR malformed lint attribute + //~| ERROR malformed lint attribute +fn main() { } diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr new file mode 100644 index 000000000..91b4e509b --- /dev/null +++ b/tests/ui/lint/lint-malformed.stderr @@ -0,0 +1,33 @@ +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error: malformed `deny` attribute input + --> $DIR/lint-malformed.rs:1:1 + | +LL | #![deny = "foo"] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/lint-malformed.rs:2:10 + | +LL | #![allow(bar = "baz")] + | ^^^^^^^^^^^ bad attribute argument + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/lint-match-arms.rs b/tests/ui/lint/lint-match-arms.rs new file mode 100644 index 000000000..5c2ccc60e --- /dev/null +++ b/tests/ui/lint/lint-match-arms.rs @@ -0,0 +1,18 @@ +fn deny_on_arm() { + match 0 { + #[deny(unused_variables)] + //~^ NOTE the lint level is defined here + y => (), + //~^ ERROR unused variable + } +} + +#[deny(unused_variables)] +fn allow_on_arm() { + match 0 { + #[allow(unused_variables)] + y => (), // OK + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-match-arms.stderr b/tests/ui/lint/lint-match-arms.stderr new file mode 100644 index 000000000..1bc0e41fd --- /dev/null +++ b/tests/ui/lint/lint-match-arms.stderr @@ -0,0 +1,14 @@ +error: unused variable: `y` + --> $DIR/lint-match-arms.rs:5:9 + | +LL | y => (), + | ^ help: if this is intentional, prefix it with an underscore: `_y` + | +note: the lint level is defined here + --> $DIR/lint-match-arms.rs:3:16 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-misplaced-attr.rs b/tests/ui/lint/lint-misplaced-attr.rs new file mode 100644 index 000000000..d06917ea3 --- /dev/null +++ b/tests/ui/lint/lint-misplaced-attr.rs @@ -0,0 +1,10 @@ +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. + +#![deny(unused_attributes)] + +mod a { + #![crate_type = "bin"] //~ ERROR should be in the root module +} + +#[crate_type = "bin"] fn main() {} //~ ERROR should be an inner diff --git a/tests/ui/lint/lint-misplaced-attr.stderr b/tests/ui/lint/lint-misplaced-attr.stderr new file mode 100644 index 000000000..abaf4620e --- /dev/null +++ b/tests/ui/lint/lint-misplaced-attr.stderr @@ -0,0 +1,20 @@ +error: crate-level attribute should be in the root module + --> $DIR/lint-misplaced-attr.rs:7:5 + | +LL | #![crate_type = "bin"] + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-misplaced-attr.rs:4:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/lint-misplaced-attr.rs:10:1 + | +LL | #[crate_type = "bin"] fn main() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-missing-copy-implementations-allow.rs b/tests/ui/lint/lint-missing-copy-implementations-allow.rs new file mode 100644 index 000000000..051a905ae --- /dev/null +++ b/tests/ui/lint/lint-missing-copy-implementations-allow.rs @@ -0,0 +1,35 @@ +// check-pass +#![deny(missing_copy_implementations)] + +// Don't recommend implementing Copy on something stateful like an iterator. +pub struct MyIterator { + num: u8, +} + +impl Iterator for MyIterator { + type Item = u8; + + fn next(&mut self) -> Option { + todo!() + } +} + +pub struct Handle { + inner: *mut (), +} + +pub struct Handle2 { + inner: *const (), +} + +pub enum MaybeHandle { + Ptr(*mut ()), +} + +pub union UnionHandle { + ptr: *mut (), +} + +pub struct Array([u8; 2048]); + +fn main() {} diff --git a/tests/ui/lint/lint-missing-copy-implementations.rs b/tests/ui/lint/lint-missing-copy-implementations.rs new file mode 100644 index 000000000..918f40de1 --- /dev/null +++ b/tests/ui/lint/lint-missing-copy-implementations.rs @@ -0,0 +1,15 @@ +// See issue 19712 + +#![deny(missing_copy_implementations)] + +mod inner { + pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy` + pub field: i32 + } +} + +pub fn foo() -> inner::Foo { + inner::Foo { field: 42 } +} + +fn main() {} diff --git a/tests/ui/lint/lint-missing-copy-implementations.stderr b/tests/ui/lint/lint-missing-copy-implementations.stderr new file mode 100644 index 000000000..e5f5ce20d --- /dev/null +++ b/tests/ui/lint/lint-missing-copy-implementations.stderr @@ -0,0 +1,16 @@ +error: type could implement `Copy`; consider adding `impl Copy` + --> $DIR/lint-missing-copy-implementations.rs:6:5 + | +LL | / pub struct Foo { +LL | | pub field: i32 +LL | | } + | |_____^ + | +note: the lint level is defined here + --> $DIR/lint-missing-copy-implementations.rs:3:9 + | +LL | #![deny(missing_copy_implementations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-missing-doc.rs b/tests/ui/lint/lint-missing-doc.rs new file mode 100644 index 000000000..229725791 --- /dev/null +++ b/tests/ui/lint/lint-missing-doc.rs @@ -0,0 +1,203 @@ +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. +#![deny(missing_docs)] +#![allow(dead_code)] +#![feature(associated_type_defaults, extern_types)] + +//! Some garbage docs for the crate here +#![doc="More garbage"] + +type Typedef = String; +pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias + +struct Foo { + a: isize, + b: isize, +} + +pub struct PubFoo { //~ ERROR: missing documentation for a struct + pub a: isize, //~ ERROR: missing documentation for a struct field + b: isize, +} + +#[allow(missing_docs)] +pub struct PubFoo2 { + pub a: isize, + pub c: isize, +} + +mod module_no_dox {} +pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module + +/// dox +pub fn foo() {} +pub fn foo2() {} //~ ERROR: missing documentation for a function +fn foo3() {} +#[allow(missing_docs)] pub fn foo4() {} + +/// dox +pub trait A { + /// dox + fn foo(&self); + /// dox + fn foo_with_impl(&self) {} +} + +#[allow(missing_docs)] +trait B { + fn foo(&self); + fn foo_with_impl(&self) {} +} + +pub trait C { //~ ERROR: missing documentation for a trait + fn foo(&self); //~ ERROR: missing documentation for an associated function + fn foo_with_impl(&self) {} //~ ERROR: missing documentation for an associated function +} + +#[allow(missing_docs)] +pub trait D { + fn dummy(&self) { } +} + +/// dox +pub trait E: Sized { + type AssociatedType; //~ ERROR: missing documentation for an associated type + type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type + + /// dox + type DocumentedType; + /// dox + type DocumentedTypeDef = Self; + /// dox + fn dummy(&self) {} +} + +impl Foo { + pub fn foo() {} + fn bar() {} +} + +impl PubFoo { + pub fn foo() {} //~ ERROR: missing documentation for an associated function + /// dox + pub fn foo1() {} + fn foo2() {} + #[allow(missing_docs)] pub fn foo3() {} +} + +#[allow(missing_docs)] +trait F { + fn a(); + fn b(&self); +} + +// should need to redefine documentation for implementations of traits +impl F for Foo { + fn a() {} + fn b(&self) {} +} + +// It sure is nice if doc(hidden) implies allow(missing_docs), and that it +// applies recursively +#[doc(hidden)] +mod a { + pub fn baz() {} + pub mod b { + pub fn baz() {} + } +} + +enum Baz { + BazA { + a: isize, + b: isize + }, + BarB +} + +pub enum PubBaz { //~ ERROR: missing documentation for an enum + PubBazA { //~ ERROR: missing documentation for a variant + a: isize, //~ ERROR: missing documentation for a struct field + }, +} + +/// dox +pub enum PubBaz2 { + /// dox + PubBaz2A { + /// dox + a: isize, + }, +} + +#[allow(missing_docs)] +pub enum PubBaz3 { + PubBaz3A { + b: isize + }, +} + +#[doc(hidden)] +pub fn baz() {} + + +const FOO: u32 = 0; +/// dox +pub const FOO1: u32 = 0; +#[allow(missing_docs)] +pub const FOO2: u32 = 0; +#[doc(hidden)] +pub const FOO3: u32 = 0; +pub const FOO4: u32 = 0; //~ ERROR: missing documentation for a const + + +static BAR: u32 = 0; +/// dox +pub static BAR1: u32 = 0; +#[allow(missing_docs)] +pub static BAR2: u32 = 0; +#[doc(hidden)] +pub static BAR3: u32 = 0; +pub static BAR4: u32 = 0; //~ ERROR: missing documentation for a static + + +mod internal_impl { + /// dox + pub fn documented() {} + pub fn undocumented1() {} //~ ERROR: missing documentation for a function + pub fn undocumented2() {} //~ ERROR: missing documentation for a function + fn undocumented3() {} + /// dox + pub mod globbed { + /// dox + pub fn also_documented() {} + pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function + fn also_undocumented2() {} + } +} +/// dox +pub mod public_interface { + pub use internal_impl::documented as foo; + pub use internal_impl::undocumented1 as bar; + pub use internal_impl::{documented, undocumented2}; + pub use internal_impl::globbed::*; +} + +extern "C" { + /// dox + pub fn extern_fn_documented(f: f32) -> f32; + pub fn extern_fn_undocumented(f: f32) -> f32; + //~^ ERROR: missing documentation for a function + + /// dox + pub static EXTERN_STATIC_DOCUMENTED: u8; + pub static EXTERN_STATIC_UNDOCUMENTED: u8; + //~^ ERROR: missing documentation for a static + + /// dox + pub type ExternTyDocumented; + pub type ExternTyUndocumented; + //~^ ERROR: missing documentation for a foreign type +} + +fn main() {} diff --git a/tests/ui/lint/lint-missing-doc.stderr b/tests/ui/lint/lint-missing-doc.stderr new file mode 100644 index 000000000..d68472d4b --- /dev/null +++ b/tests/ui/lint/lint-missing-doc.stderr @@ -0,0 +1,140 @@ +error: missing documentation for a type alias + --> $DIR/lint-missing-doc.rs:11:1 + | +LL | pub type PubTypedef = String; + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-missing-doc.rs:3:9 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a struct + --> $DIR/lint-missing-doc.rs:18:1 + | +LL | pub struct PubFoo { + | ^^^^^^^^^^^^^^^^^ + +error: missing documentation for a struct field + --> $DIR/lint-missing-doc.rs:19:5 + | +LL | pub a: isize, + | ^^^^^^^^^^^^ + +error: missing documentation for a module + --> $DIR/lint-missing-doc.rs:30:1 + | +LL | pub mod pub_module_no_dox {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:34:1 + | +LL | pub fn foo2() {} + | ^^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-missing-doc.rs:52:1 + | +LL | pub trait C { + | ^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-missing-doc.rs:53:5 + | +LL | fn foo(&self); + | ^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-missing-doc.rs:54:5 + | +LL | fn foo_with_impl(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-missing-doc.rs:64:5 + | +LL | type AssociatedType; + | ^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-missing-doc.rs:65:5 + | +LL | type AssociatedTypeDef = Self; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-missing-doc.rs:81:5 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + +error: missing documentation for an enum + --> $DIR/lint-missing-doc.rs:118:1 + | +LL | pub enum PubBaz { + | ^^^^^^^^^^^^^^^ + +error: missing documentation for a variant + --> $DIR/lint-missing-doc.rs:119:5 + | +LL | PubBazA { + | ^^^^^^^ + +error: missing documentation for a struct field + --> $DIR/lint-missing-doc.rs:120:9 + | +LL | a: isize, + | ^^^^^^^^ + +error: missing documentation for a constant + --> $DIR/lint-missing-doc.rs:151:1 + | +LL | pub const FOO4: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a static + --> $DIR/lint-missing-doc.rs:161:1 + | +LL | pub static BAR4: u32 = 0; + | ^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:167:5 + | +LL | pub fn undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:168:5 + | +LL | pub fn undocumented2() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:174:9 + | +LL | pub fn also_undocumented1() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-missing-doc.rs:189:5 + | +LL | pub fn extern_fn_undocumented(f: f32) -> f32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a static + --> $DIR/lint-missing-doc.rs:194:5 + | +LL | pub static EXTERN_STATIC_UNDOCUMENTED: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a foreign type + --> $DIR/lint-missing-doc.rs:199:5 + | +LL | pub type ExternTyUndocumented; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 22 previous errors + diff --git a/tests/ui/lint/lint-non-camel-case-types.rs b/tests/ui/lint/lint-non-camel-case-types.rs new file mode 100644 index 000000000..acd5c5df9 --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-types.rs @@ -0,0 +1,37 @@ +#![forbid(non_camel_case_types)] +#![allow(dead_code)] + +struct ONE_TWO_THREE; +//~^ ERROR type `ONE_TWO_THREE` should have an upper camel case name + +struct foo { //~ ERROR type `foo` should have an upper camel case name + bar: isize, +} + +enum foo2 { //~ ERROR type `foo2` should have an upper camel case name + Bar +} + +struct foo3 { //~ ERROR type `foo3` should have an upper camel case name + bar: isize +} + +type foo4 = isize; //~ ERROR type `foo4` should have an upper camel case name + +enum Foo5 { + bar //~ ERROR variant `bar` should have an upper camel case name +} + +trait foo6 { //~ ERROR trait `foo6` should have an upper camel case name + type foo7; //~ ERROR associated type `foo7` should have an upper camel case name + fn dummy(&self) { } +} + +fn f(_: ty) {} //~ ERROR type parameter `ty` should have an upper camel case name + +#[repr(C)] +struct foo7 { + bar: isize, +} + +fn main() { } diff --git a/tests/ui/lint/lint-non-camel-case-types.stderr b/tests/ui/lint/lint-non-camel-case-types.stderr new file mode 100644 index 000000000..875380b5d --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-types.stderr @@ -0,0 +1,62 @@ +error: type `ONE_TWO_THREE` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:4:8 + | +LL | struct ONE_TWO_THREE; + | ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `OneTwoThree` + | +note: the lint level is defined here + --> $DIR/lint-non-camel-case-types.rs:1:11 + | +LL | #![forbid(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: type `foo` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:7:8 + | +LL | struct foo { + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` + +error: type `foo2` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:11:6 + | +LL | enum foo2 { + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo2` + +error: type `foo3` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:15:8 + | +LL | struct foo3 { + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo3` + +error: type `foo4` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:19:6 + | +LL | type foo4 = isize; + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo4` + +error: variant `bar` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:22:5 + | +LL | bar + | ^^^ help: convert the identifier to upper camel case: `Bar` + +error: trait `foo6` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:25:7 + | +LL | trait foo6 { + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo6` + +error: associated type `foo7` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:26:10 + | +LL | type foo7; + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo7` + +error: type parameter `ty` should have an upper camel case name + --> $DIR/lint-non-camel-case-types.rs:30:6 + | +LL | fn f(_: ty) {} + | ^^ help: convert the identifier to upper camel case: `Ty` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-non-camel-case-variant.rs b/tests/ui/lint/lint-non-camel-case-variant.rs new file mode 100644 index 000000000..2b1a52f25 --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-variant.rs @@ -0,0 +1,10 @@ +// check-pass + +#![deny(non_camel_case_types)] + +pub enum Foo { + #[allow(non_camel_case_types)] + bar +} + +fn main() {} diff --git a/tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs b/tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs new file mode 100644 index 000000000..b832e4bcd --- /dev/null +++ b/tests/ui/lint/lint-non-camel-case-with-trailing-underscores.rs @@ -0,0 +1,11 @@ +// check-pass + +#![allow(dead_code)] +// This is ok because we often use the trailing underscore to mean 'prime' + +// pretty-expanded FIXME #23616 + +#[forbid(non_camel_case_types)] +type Foo_ = isize; + +pub fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-crate-2.rs b/tests/ui/lint/lint-non-snake-case-crate-2.rs new file mode 100644 index 000000000..1b763a9d8 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate-2.rs @@ -0,0 +1,6 @@ +// compile-flags: --crate-name NonSnakeCase +// error-pattern: crate `NonSnakeCase` should have a snake case name + +#![deny(non_snake_case)] + +fn main() {} diff --git a/tests/ui/lint/lint-non-snake-case-crate-2.stderr b/tests/ui/lint/lint-non-snake-case-crate-2.stderr new file mode 100644 index 000000000..4b42145bb --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate-2.stderr @@ -0,0 +1,11 @@ +error: crate `NonSnakeCase` should have a snake case name + | + = help: convert the identifier to snake case: `non_snake_case` +note: the lint level is defined here + --> $DIR/lint-non-snake-case-crate-2.rs:4:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-crate.rs b/tests/ui/lint/lint-non-snake-case-crate.rs new file mode 100644 index 000000000..e4e84261a --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate.rs @@ -0,0 +1,5 @@ +#![crate_name = "NonSnakeCase"] +//~^ ERROR crate `NonSnakeCase` should have a snake case name +#![deny(non_snake_case)] + +fn main() {} diff --git a/tests/ui/lint/lint-non-snake-case-crate.stderr b/tests/ui/lint/lint-non-snake-case-crate.stderr new file mode 100644 index 000000000..da6b89c1e --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-crate.stderr @@ -0,0 +1,14 @@ +error: crate `NonSnakeCase` should have a snake case name + --> $DIR/lint-non-snake-case-crate.rs:1:18 + | +LL | #![crate_name = "NonSnakeCase"] + | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-crate.rs:3:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-functions.rs b/tests/ui/lint/lint-non-snake-case-functions.rs new file mode 100644 index 000000000..fa64a9f98 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-functions.rs @@ -0,0 +1,44 @@ +#![deny(non_snake_case)] +#![allow(dead_code)] + +struct Foo; + +impl Foo { + fn Foo_Method() {} + //~^ ERROR method `Foo_Method` should have a snake case name + + // Don't allow two underscores in a row + fn foo__method(&self) {} + //~^ ERROR method `foo__method` should have a snake case name + + pub fn xyZ(&mut self) {} + //~^ ERROR method `xyZ` should have a snake case name + + fn render_HTML() {} + //~^ ERROR method `render_HTML` should have a snake case name +} + +trait X { + fn ABC(); + //~^ ERROR trait method `ABC` should have a snake case name + + fn a_b_C(&self) {} + //~^ ERROR trait method `a_b_C` should have a snake case name + + fn something__else(&mut self); + //~^ ERROR trait method `something__else` should have a snake case name +} + +impl X for Foo { + // These errors should be caught at the trait definition not the impl + fn ABC() {} + fn something__else(&mut self) {} +} + +fn Cookie() {} +//~^ ERROR function `Cookie` should have a snake case name + +pub fn bi_S_Cuit() {} +//~^ ERROR function `bi_S_Cuit` should have a snake case name + +fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-functions.stderr b/tests/ui/lint/lint-non-snake-case-functions.stderr new file mode 100644 index 000000000..f6ac6b99b --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-functions.stderr @@ -0,0 +1,62 @@ +error: method `Foo_Method` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:7:8 + | +LL | fn Foo_Method() {} + | ^^^^^^^^^^ help: convert the identifier to snake case: `foo_method` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-functions.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: method `foo__method` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:11:8 + | +LL | fn foo__method(&self) {} + | ^^^^^^^^^^^ help: convert the identifier to snake case: `foo_method` + +error: method `xyZ` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:14:12 + | +LL | pub fn xyZ(&mut self) {} + | ^^^ help: convert the identifier to snake case: `xy_z` + +error: method `render_HTML` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:17:8 + | +LL | fn render_HTML() {} + | ^^^^^^^^^^^ help: convert the identifier to snake case: `render_html` + +error: trait method `ABC` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:22:8 + | +LL | fn ABC(); + | ^^^ help: convert the identifier to snake case: `abc` + +error: trait method `a_b_C` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:25:8 + | +LL | fn a_b_C(&self) {} + | ^^^^^ help: convert the identifier to snake case (notice the capitalization): `a_b_c` + +error: trait method `something__else` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:28:8 + | +LL | fn something__else(&mut self); + | ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `something_else` + +error: function `Cookie` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:38:4 + | +LL | fn Cookie() {} + | ^^^^^^ help: convert the identifier to snake case (notice the capitalization): `cookie` + +error: function `bi_S_Cuit` should have a snake case name + --> $DIR/lint-non-snake-case-functions.rs:41:8 + | +LL | pub fn bi_S_Cuit() {} + | ^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `bi_s_cuit` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs new file mode 100644 index 000000000..8cc4f976a --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs @@ -0,0 +1,19 @@ +#![warn(unused)] +#![allow(dead_code)] +#![deny(non_snake_case)] + +mod Impl {} +//~^ ERROR module `Impl` should have a snake case name + +fn While() {} +//~^ ERROR function `While` should have a snake case name + +fn main() { + let Mod: usize = 0; + //~^ ERROR variable `Mod` should have a snake case name + //~^^ WARN unused variable: `Mod` + + let Super: usize = 0; + //~^ ERROR variable `Super` should have a snake case name + //~^^ WARN unused variable: `Super` +} diff --git a/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr new file mode 100644 index 000000000..2841815ec --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr @@ -0,0 +1,67 @@ +warning: unused variable: `Mod` + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9 + | +LL | let Mod: usize = 0; + | ^^^ help: if this is intentional, prefix it with an underscore: `_Mod` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `Super` + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9 + | +LL | let Super: usize = 0; + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_Super` + +error: module `Impl` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:5:5 + | +LL | mod Impl {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:3:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ +help: rename the identifier or convert it to a snake case raw identifier + | +LL | mod r#impl {} + | ~~~~~~ + +error: function `While` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:8:4 + | +LL | fn While() {} + | ^^^^^ + | +help: rename the identifier or convert it to a snake case raw identifier + | +LL | fn r#while() {} + | ~~~~~~~ + +error: variable `Mod` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9 + | +LL | let Mod: usize = 0; + | ^^^ + | +help: rename the identifier or convert it to a snake case raw identifier + | +LL | let r#mod: usize = 0; + | ~~~~~ + +error: variable `Super` should have a snake case name + --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9 + | +LL | let Super: usize = 0; + | ^^^^^ help: rename the identifier + | + = note: `super` cannot be used as a raw identifier + +error: aborting due to 4 previous errors; 2 warnings emitted + diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.rs b/tests/ui/lint/lint-non-snake-case-lifetimes.rs new file mode 100644 index 000000000..de76d2dbe --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-lifetimes.rs @@ -0,0 +1,8 @@ +#![deny(non_snake_case)] +#![allow(dead_code)] + +fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name + _: &'FooBar () +) {} + +fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-lifetimes.stderr b/tests/ui/lint/lint-non-snake-case-lifetimes.stderr new file mode 100644 index 000000000..d4fe26a43 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-lifetimes.stderr @@ -0,0 +1,14 @@ +error: lifetime `'FooBar` should have a snake case name + --> $DIR/lint-non-snake-case-lifetimes.rs:4:6 + | +LL | fn f<'FooBar>( + | ^^^^^^^ help: convert the identifier to snake case: `'foo_bar` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-lifetimes.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-modules.rs b/tests/ui/lint/lint-non-snake-case-modules.rs new file mode 100644 index 000000000..73f123321 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-modules.rs @@ -0,0 +1,10 @@ +#![deny(non_snake_case)] +#![allow(dead_code)] + +mod FooBar { //~ ERROR module `FooBar` should have a snake case name + pub struct S; +} + +fn f(_: FooBar::S) { } + +fn main() { } diff --git a/tests/ui/lint/lint-non-snake-case-modules.stderr b/tests/ui/lint/lint-non-snake-case-modules.stderr new file mode 100644 index 000000000..c8b997c87 --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-modules.stderr @@ -0,0 +1,14 @@ +error: module `FooBar` should have a snake case name + --> $DIR/lint-non-snake-case-modules.rs:4:5 + | +LL | mod FooBar { + | ^^^^^^ help: convert the identifier to snake case: `foo_bar` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-modules.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs new file mode 100644 index 000000000..9f0c87dca --- /dev/null +++ b/tests/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs @@ -0,0 +1,11 @@ +// check-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#![deny(non_snake_case)] + +// This name is neither upper nor lower case +fn 你好() {} + +fn main() {} diff --git a/tests/ui/lint/lint-non-uppercase-associated-const.rs b/tests/ui/lint/lint-non-uppercase-associated-const.rs new file mode 100644 index 000000000..7b0d93960 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-associated-const.rs @@ -0,0 +1,11 @@ +#![deny(non_upper_case_globals)] +#![allow(dead_code)] + +struct Foo; + +impl Foo { + const not_upper: bool = true; +} +//~^^ ERROR associated constant `not_upper` should have an upper case name + +fn main() {} diff --git a/tests/ui/lint/lint-non-uppercase-associated-const.stderr b/tests/ui/lint/lint-non-uppercase-associated-const.stderr new file mode 100644 index 000000000..411ff51aa --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-associated-const.stderr @@ -0,0 +1,14 @@ +error: associated constant `not_upper` should have an upper case name + --> $DIR/lint-non-uppercase-associated-const.rs:7:11 + | +LL | const not_upper: bool = true; + | ^^^^^^^^^ help: convert the identifier to upper case: `NOT_UPPER` + | +note: the lint level is defined here + --> $DIR/lint-non-uppercase-associated-const.rs:1:9 + | +LL | #![deny(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-non-uppercase-statics.rs b/tests/ui/lint/lint-non-uppercase-statics.rs new file mode 100644 index 000000000..5bd143032 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-statics.rs @@ -0,0 +1,11 @@ +#![forbid(non_upper_case_globals)] +#![allow(dead_code)] + +static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name + +static mut bar: isize = 1; //~ ERROR static variable `bar` should have an upper case name + +#[no_mangle] +pub static extern_foo: isize = 1; // OK, because #[no_mangle] supersedes the warning + +fn main() { } diff --git a/tests/ui/lint/lint-non-uppercase-statics.stderr b/tests/ui/lint/lint-non-uppercase-statics.stderr new file mode 100644 index 000000000..c6fd0a6e0 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-statics.stderr @@ -0,0 +1,20 @@ +error: static variable `foo` should have an upper case name + --> $DIR/lint-non-uppercase-statics.rs:4:8 + | +LL | static foo: isize = 1; + | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` + | +note: the lint level is defined here + --> $DIR/lint-non-uppercase-statics.rs:1:11 + | +LL | #![forbid(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: static variable `bar` should have an upper case name + --> $DIR/lint-non-uppercase-statics.rs:6:12 + | +LL | static mut bar: isize = 1; + | ^^^ help: convert the identifier to upper case: `BAR` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-1.rs b/tests/ui/lint/lint-nonstandard-style-unicode-1.rs new file mode 100644 index 000000000..7c45c0993 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-1.rs @@ -0,0 +1,49 @@ +#![allow(dead_code)] + +#![forbid(non_camel_case_types)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 1. non_camel_case_types + +// Can start with non-lowercase letter +struct Θχ; +struct ヒa; + +struct χa; +//~^ ERROR type `χa` should have an upper camel case name + +// If there's already leading or trailing underscores, they get trimmed before checking. +// This is fine: +struct _ヒb; + +// This is not: +struct __χa; +//~^ ERROR type `__χa` should have an upper camel case name + +// Besides this, we cannot have two continuous underscores in the middle. + +struct 对__å¦; +//~^ ERROR type `对__å¦` should have an upper camel case name + +struct ヒ__χ; +//~^ ERROR type `ヒ__χ` should have an upper camel case name + +// also cannot have lowercase letter next to an underscore. +// so this triggers the lint: + +struct Hello_你好; +//~^ ERROR type `Hello_你好` should have an upper camel case name + +struct Hello_World; +//~^ ERROR type `Hello_World` should have an upper camel case name + +struct ä½ _ÓŸ; +//~^ ERROR type `ä½ _ÓŸ` should have an upper camel case name + +// and this is ok: + +struct ä½ _好; + +fn main() {} diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-1.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-1.stderr new file mode 100644 index 000000000..6c2aa225e --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-1.stderr @@ -0,0 +1,50 @@ +error: type `χa` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:14:8 + | +LL | struct χa; + | ^^ help: convert the identifier to upper camel case: `Χa` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-1.rs:3:11 + | +LL | #![forbid(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: type `__χa` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:22:8 + | +LL | struct __χa; + | ^^^^ help: convert the identifier to upper camel case: `Χa` + +error: type `对__å¦` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:27:8 + | +LL | struct 对__å¦; + | ^^^^^^ help: convert the identifier to upper camel case: `对_å¦` + +error: type `ヒ__χ` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:30:8 + | +LL | struct ヒ__χ; + | ^^^^^ help: convert the identifier to upper camel case: `ヒΧ` + +error: type `Hello_你好` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:36:8 + | +LL | struct Hello_你好; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `Hello你好` + +error: type `Hello_World` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:39:8 + | +LL | struct Hello_World; + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `HelloWorld` + +error: type `ä½ _ÓŸ` should have an upper camel case name + --> $DIR/lint-nonstandard-style-unicode-1.rs:42:8 + | +LL | struct ä½ _ÓŸ; + | ^^^^ help: convert the identifier to upper camel case: `ä½ Óž` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-2.rs b/tests/ui/lint/lint-nonstandard-style-unicode-2.rs new file mode 100644 index 000000000..9690be590 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-2.rs @@ -0,0 +1,29 @@ +#![allow(dead_code)] + +#![forbid(non_snake_case)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 2. non_snake_case + +// Can only use non-uppercase letters. +// So this works: + +fn 编程() {} + +// but this doesn't: + +fn Ц() {} +//~^ ERROR function `Ц` should have a snake case name + +// besides this, you cannot use continuous underscores in the middle + +fn 分__éš”() {} +//~^ ERROR function `分__éš”` should have a snake case name + +// but you can use them both at the beginning and at the end. + +fn _______ä¸_è¿ž_ç»­_çš„_å­˜_在_______() {} + +fn main() {} diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr new file mode 100644 index 000000000..8eb0654e0 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-2.stderr @@ -0,0 +1,20 @@ +error: function `Ц` should have a snake case name + --> $DIR/lint-nonstandard-style-unicode-2.rs:17:4 + | +LL | fn Ц() {} + | ^ help: convert the identifier to snake case: `ц` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-2.rs:3:11 + | +LL | #![forbid(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: function `分__éš”` should have a snake case name + --> $DIR/lint-nonstandard-style-unicode-2.rs:22:4 + | +LL | fn 分__éš”() {} + | ^^^^^^ help: convert the identifier to snake case: `分_éš”` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-3.rs b/tests/ui/lint/lint-nonstandard-style-unicode-3.rs new file mode 100644 index 000000000..9175be7a0 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-3.rs @@ -0,0 +1,24 @@ +#![allow(dead_code)] + +#![forbid(non_upper_case_globals)] + +// Some scripts (e.g., hiragana) don't have a concept of +// upper/lowercase + +// 3. non_upper_case_globals + +// Can only use non-lowercase letters. +// So this works: + +static ラ: usize = 0; + +// but this doesn't: + +static τεχ: f32 = 3.14159265; +//~^ ERROR static variable `τεχ` should have an upper case name + +// This has no limit at all on underscore usages. + +static __密__å°__线__内__ç¦__æ­¢__ç­”__题__: bool = true; + +fn main() {} diff --git a/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr b/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr new file mode 100644 index 000000000..970e6b838 --- /dev/null +++ b/tests/ui/lint/lint-nonstandard-style-unicode-3.stderr @@ -0,0 +1,14 @@ +error: static variable `τεχ` should have an upper case name + --> $DIR/lint-nonstandard-style-unicode-3.rs:17:8 + | +LL | static τεχ: f32 = 3.14159265; + | ^^^ help: convert the identifier to upper case: `ΤΕΧ` + | +note: the lint level is defined here + --> $DIR/lint-nonstandard-style-unicode-3.rs:3:11 + | +LL | #![forbid(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-output-format-2.rs b/tests/ui/lint/lint-output-format-2.rs new file mode 100644 index 000000000..985166e09 --- /dev/null +++ b/tests/ui/lint/lint-output-format-2.rs @@ -0,0 +1,15 @@ +// aux-build:lint_output_format.rs + +#![feature(unstable_test_feature)] +// check-pass + +extern crate lint_output_format; +use lint_output_format::{foo, bar}; +//~^ WARNING use of deprecated function `lint_output_format::foo`: text + + +fn main() { + let _x = foo(); + //~^ WARNING use of deprecated function `lint_output_format::foo`: text + let _y = bar(); +} diff --git a/tests/ui/lint/lint-output-format-2.stderr b/tests/ui/lint/lint-output-format-2.stderr new file mode 100644 index 000000000..a36dbd61f --- /dev/null +++ b/tests/ui/lint/lint-output-format-2.stderr @@ -0,0 +1,16 @@ +warning: use of deprecated function `lint_output_format::foo`: text + --> $DIR/lint-output-format-2.rs:7:26 + | +LL | use lint_output_format::{foo, bar}; + | ^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated function `lint_output_format::foo`: text + --> $DIR/lint-output-format-2.rs:12:14 + | +LL | let _x = foo(); + | ^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/lint-output-format.rs b/tests/ui/lint/lint-output-format.rs new file mode 100644 index 000000000..67e8ec8f1 --- /dev/null +++ b/tests/ui/lint/lint-output-format.rs @@ -0,0 +1,13 @@ +// compile-flags: -F unused_features +// aux-build:lint_output_format.rs + +#![allow(deprecated)] + +extern crate lint_output_format; //~ ERROR use of unstable library feature +use lint_output_format::{foo, bar}; //~ ERROR use of unstable library feature +//~| ERROR use of unstable library feature + +fn main() { + let _x = foo(); + let _y = bar(); //~ ERROR use of unstable library feature +} diff --git a/tests/ui/lint/lint-output-format.stderr b/tests/ui/lint/lint-output-format.stderr new file mode 100644 index 000000000..0db79a156 --- /dev/null +++ b/tests/ui/lint/lint-output-format.stderr @@ -0,0 +1,35 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:6:1 + | +LL | extern crate lint_output_format; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:7:26 + | +LL | use lint_output_format::{foo, bar}; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:7:31 + | +LL | use lint_output_format::{foo, bar}; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-output-format.rs:12:14 + | +LL | let _y = bar(); + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-owned-heap-memory.rs b/tests/ui/lint/lint-owned-heap-memory.rs new file mode 100644 index 000000000..af47d5c07 --- /dev/null +++ b/tests/ui/lint/lint-owned-heap-memory.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] +#![forbid(box_pointers)] + + +struct Foo { + x: Box //~ ERROR type uses owned +} + +fn main() { + let _x: Foo = Foo { x : Box::new(10) }; + //~^ ERROR type uses owned +} diff --git a/tests/ui/lint/lint-owned-heap-memory.stderr b/tests/ui/lint/lint-owned-heap-memory.stderr new file mode 100644 index 000000000..5ba396970 --- /dev/null +++ b/tests/ui/lint/lint-owned-heap-memory.stderr @@ -0,0 +1,20 @@ +error: type uses owned (Box type) pointers: Box + --> $DIR/lint-owned-heap-memory.rs:6:5 + | +LL | x: Box + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-owned-heap-memory.rs:2:11 + | +LL | #![forbid(box_pointers)] + | ^^^^^^^^^^^^ + +error: type uses owned (Box type) pointers: Box + --> $DIR/lint-owned-heap-memory.rs:10:29 + | +LL | let _x: Foo = Foo { x : Box::new(10) }; + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.rs b/tests/ui/lint/lint-pre-expansion-extern-module.rs new file mode 100644 index 000000000..30e2ed8b7 --- /dev/null +++ b/tests/ui/lint/lint-pre-expansion-extern-module.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags: -W rust-2018-compatibility +// error-pattern: `try` is a keyword in the 2018 edition + +fn main() {} + +mod lint_pre_expansion_extern_module_aux; diff --git a/tests/ui/lint/lint-pre-expansion-extern-module.stderr b/tests/ui/lint/lint-pre-expansion-extern-module.stderr new file mode 100644 index 000000000..ce3e8806a --- /dev/null +++ b/tests/ui/lint/lint-pre-expansion-extern-module.stderr @@ -0,0 +1,12 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/lint_pre_expansion_extern_module_aux.rs:3:8 + | +LL | pub fn try() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + = note: `-W keyword-idents` implied by `-W rust-2018-compatibility` + +warning: 1 warning emitted + diff --git a/tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs b/tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs new file mode 100644 index 000000000..2df6d08e7 --- /dev/null +++ b/tests/ui/lint/lint-pub-unreachable-for-nested-glob.rs @@ -0,0 +1,28 @@ +// check-pass + +#![deny(unreachable_pub)] + +pub use self::m1::*; + +mod m1 { + pub use self::m2::*; + + mod m2 { + pub struct Item1; + pub struct Item2; + } +} + + +pub use self::o1::{ Item42, Item24 }; + +mod o1 { + pub use self::o2::{ Item42, Item24 }; + + mod o2 { + pub struct Item42; + pub struct Item24; + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs new file mode 100644 index 000000000..0cace0ca0 --- /dev/null +++ b/tests/ui/lint/lint-qualification.rs @@ -0,0 +1,20 @@ +#![deny(unused_qualifications)] +#![allow(deprecated)] + +mod foo { + pub fn bar() {} +} + +fn main() { + use foo::bar; + foo::bar(); //~ ERROR: unnecessary qualification + bar(); + + let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345 + + macro_rules! m { () => { + $crate::foo::bar(); // issue #37357 + ::foo::bar(); // issue #38682 + } } + m!(); +} diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr new file mode 100644 index 000000000..149a782d9 --- /dev/null +++ b/tests/ui/lint/lint-qualification.stderr @@ -0,0 +1,14 @@ +error: unnecessary qualification + --> $DIR/lint-qualification.rs:10:5 + | +LL | foo::bar(); + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-qualification.rs:1:9 + | +LL | #![deny(unused_qualifications)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-range-endpoint-overflow.rs b/tests/ui/lint/lint-range-endpoint-overflow.rs new file mode 100644 index 000000000..7034d56aa --- /dev/null +++ b/tests/ui/lint/lint-range-endpoint-overflow.rs @@ -0,0 +1,17 @@ +#![deny(overflowing_literals)] + +fn main() { + let range_a = 0..256; //~ ERROR range endpoint is out of range for `u8` + let range_b = 0..=255; // ok + let range_c = 0..=256; //~ ERROR literal out of range for `u8` + let range_d = 256..5; //~ ERROR literal out of range for `u8` + let range_e = 0..257; //~ ERROR literal out of range for `u8` + let _range_f = 0..256u8; //~ ERROR range endpoint is out of range for `u8` + let _range_g = 0..128i8; //~ ERROR range endpoint is out of range for `i8` + + range_a.collect::>(); + range_b.collect::>(); + range_c.collect::>(); + range_d.collect::>(); + range_e.collect::>(); +} diff --git a/tests/ui/lint/lint-range-endpoint-overflow.stderr b/tests/ui/lint/lint-range-endpoint-overflow.stderr new file mode 100644 index 000000000..d2df73727 --- /dev/null +++ b/tests/ui/lint/lint-range-endpoint-overflow.stderr @@ -0,0 +1,50 @@ +error: range endpoint is out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:4:19 + | +LL | let range_a = 0..256; + | ^^^^^^ help: use an inclusive range instead: `0..=255` + | +note: the lint level is defined here + --> $DIR/lint-range-endpoint-overflow.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:6:23 + | +LL | let range_c = 0..=256; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:7:19 + | +LL | let range_d = 256..5; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:8:22 + | +LL | let range_e = 0..257; + | ^^^ + | + = note: the literal `257` does not fit into the type `u8` whose range is `0..=255` + +error: range endpoint is out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:9:20 + | +LL | let _range_f = 0..256u8; + | ^^^^^^^^ help: use an inclusive range instead: `0..=255u8` + +error: range endpoint is out of range for `i8` + --> $DIR/lint-range-endpoint-overflow.rs:10:20 + | +LL | let _range_g = 0..128i8; + | ^^^^^^^^ help: use an inclusive range instead: `0..=127i8` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/lint-removed-allow.rs b/tests/ui/lint/lint-removed-allow.rs new file mode 100644 index 000000000..30ba4f02f --- /dev/null +++ b/tests/ui/lint/lint-removed-allow.rs @@ -0,0 +1,8 @@ +// No warnings about removed lint when +// allow(renamed_and_removed_lints) + +#![allow(renamed_and_removed_lints)] + +#[deny(raw_pointer_derive)] +#[deny(unused_variables)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-removed-allow.stderr b/tests/ui/lint/lint-removed-allow.stderr new file mode 100644 index 000000000..029334c2e --- /dev/null +++ b/tests/ui/lint/lint-removed-allow.stderr @@ -0,0 +1,14 @@ +error: unused variable: `unused` + --> $DIR/lint-removed-allow.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-removed-allow.rs:7:8 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-removed-cmdline.rs b/tests/ui/lint/lint-removed-cmdline.rs new file mode 100644 index 000000000..462beabb9 --- /dev/null +++ b/tests/ui/lint/lint-removed-cmdline.rs @@ -0,0 +1,12 @@ +// The raw_pointer_derived lint warns about its removal +// cc #30346 + +// compile-flags:-D raw_pointer_derive + +// error-pattern:lint `raw_pointer_derive` has been removed +// error-pattern:requested on the command line with `-D raw_pointer_derive` + +#![warn(unused)] + +#[deny(warnings)] +fn main() { let unused = (); } diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr new file mode 100644 index 000000000..9be532ef2 --- /dev/null +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -0,0 +1,27 @@ +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + | + = note: requested on the command line with `-D raw_pointer_derive` + +error: unused variable: `unused` + --> $DIR/lint-removed-cmdline.rs:12:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-removed-cmdline.rs:11:8 + | +LL | #[deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error; 3 warnings emitted + diff --git a/tests/ui/lint/lint-removed.rs b/tests/ui/lint/lint-removed.rs new file mode 100644 index 000000000..92f4372c2 --- /dev/null +++ b/tests/ui/lint/lint-removed.rs @@ -0,0 +1,8 @@ +// The raw_pointer_derived lint was removed, but is now reported by +// the renamed_and_removed_lints lint, which means it's a warning by +// default, and allowed in cargo dependency builds. +// cc #30346 + +#[deny(raw_pointer_derive)] //~ WARN `raw_pointer_derive` has been removed +#[deny(unused_variables)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-removed.stderr b/tests/ui/lint/lint-removed.stderr new file mode 100644 index 000000000..dc0515b84 --- /dev/null +++ b/tests/ui/lint/lint-removed.stderr @@ -0,0 +1,22 @@ +warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok + --> $DIR/lint-removed.rs:6:8 + | +LL | #[deny(raw_pointer_derive)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error: unused variable: `unused` + --> $DIR/lint-removed.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-removed.rs:7:8 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-renamed-allow.rs b/tests/ui/lint/lint-renamed-allow.rs new file mode 100644 index 000000000..9cf6f329c --- /dev/null +++ b/tests/ui/lint/lint-renamed-allow.rs @@ -0,0 +1,8 @@ +// No warnings about renamed lint when +// allow(renamed_and_removed_lints) + +#![allow(renamed_and_removed_lints)] + +#[deny(single_use_lifetime)] +#[deny(unused)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-renamed-allow.stderr b/tests/ui/lint/lint-renamed-allow.stderr new file mode 100644 index 000000000..46f6a10de --- /dev/null +++ b/tests/ui/lint/lint-renamed-allow.stderr @@ -0,0 +1,15 @@ +error: unused variable: `unused` + --> $DIR/lint-renamed-allow.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-renamed-allow.rs:7:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-renamed-cmdline.rs b/tests/ui/lint/lint-renamed-cmdline.rs new file mode 100644 index 000000000..c873771e3 --- /dev/null +++ b/tests/ui/lint/lint-renamed-cmdline.rs @@ -0,0 +1,8 @@ +// compile-flags:-D bare_trait_object + +// error-pattern:lint `bare_trait_object` has been renamed to `bare_trait_objects` +// error-pattern:requested on the command line with `-D bare_trait_object` +// error-pattern:unused + +#[deny(unused)] +fn main() { let unused = (); } diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr new file mode 100644 index 000000000..8dfd61ac9 --- /dev/null +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -0,0 +1,27 @@ +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = note: requested on the command line with `-D bare_trait_object` + +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = note: requested on the command line with `-D bare_trait_object` + +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + | + = note: requested on the command line with `-D bare_trait_object` + +error: unused variable: `unused` + --> $DIR/lint-renamed-cmdline.rs:8:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-renamed-cmdline.rs:7:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: aborting due to previous error; 3 warnings emitted + diff --git a/tests/ui/lint/lint-renamed.rs b/tests/ui/lint/lint-renamed.rs new file mode 100644 index 000000000..ca3299430 --- /dev/null +++ b/tests/ui/lint/lint-renamed.rs @@ -0,0 +1,4 @@ +#[deny(bare_trait_object)] +//~^ WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +#[deny(unused)] +fn main() { let unused = (); } //~ ERROR unused diff --git a/tests/ui/lint/lint-renamed.stderr b/tests/ui/lint/lint-renamed.stderr new file mode 100644 index 000000000..984254571 --- /dev/null +++ b/tests/ui/lint/lint-renamed.stderr @@ -0,0 +1,23 @@ +warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` + --> $DIR/lint-renamed.rs:1:8 + | +LL | #[deny(bare_trait_object)] + | ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error: unused variable: `unused` + --> $DIR/lint-renamed.rs:4:17 + | +LL | fn main() { let unused = (); } + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/lint-renamed.rs:3:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-shorthand-field.fixed b/tests/ui/lint/lint-shorthand-field.fixed new file mode 100644 index 000000000..7cd5717bc --- /dev/null +++ b/tests/ui/lint/lint-shorthand-field.fixed @@ -0,0 +1,70 @@ +// run-rustfix + +#![allow(nonstandard_style, unused_variables, unused_mut)] +#![deny(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +fn main() { + { + let Foo { + x, //~ ERROR the `x:` in this pattern is redundant + ref y, //~ ERROR the `y:` in this pattern is redundant + } = Foo { x: 0, y: 0 }; + + let Foo { + x, + ref y, + } = Foo { x: 0, y: 0 }; + } + + { + const x: isize = 1; + + match (Foo { x: 1, y: 1 }) { + Foo { x: x, ..} => {}, + _ => {}, + } + } + + { + struct Bar { + x: x, + } + + struct x; + + match (Bar { x: x }) { + Bar { x: x } => {}, + } + } + + { + struct Bar { + x: Foo, + } + + enum Foo { x } + + match (Bar { x: Foo::x }) { + Bar { x: Foo::x } => {}, + } + } + + { + struct Baz { + x: isize, + y: isize, + z: isize, + } + + let Baz { + mut x, //~ ERROR the `x:` in this pattern is redundant + ref y, //~ ERROR the `y:` in this pattern is redundant + ref mut z, //~ ERROR the `z:` in this pattern is redundant + } = Baz { x: 0, y: 0, z: 0 }; + } +} diff --git a/tests/ui/lint/lint-shorthand-field.rs b/tests/ui/lint/lint-shorthand-field.rs new file mode 100644 index 000000000..22de9c325 --- /dev/null +++ b/tests/ui/lint/lint-shorthand-field.rs @@ -0,0 +1,70 @@ +// run-rustfix + +#![allow(nonstandard_style, unused_variables, unused_mut)] +#![deny(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +fn main() { + { + let Foo { + x: x, //~ ERROR the `x:` in this pattern is redundant + y: ref y, //~ ERROR the `y:` in this pattern is redundant + } = Foo { x: 0, y: 0 }; + + let Foo { + x, + ref y, + } = Foo { x: 0, y: 0 }; + } + + { + const x: isize = 1; + + match (Foo { x: 1, y: 1 }) { + Foo { x: x, ..} => {}, + _ => {}, + } + } + + { + struct Bar { + x: x, + } + + struct x; + + match (Bar { x: x }) { + Bar { x: x } => {}, + } + } + + { + struct Bar { + x: Foo, + } + + enum Foo { x } + + match (Bar { x: Foo::x }) { + Bar { x: Foo::x } => {}, + } + } + + { + struct Baz { + x: isize, + y: isize, + z: isize, + } + + let Baz { + x: mut x, //~ ERROR the `x:` in this pattern is redundant + y: ref y, //~ ERROR the `y:` in this pattern is redundant + z: ref mut z, //~ ERROR the `z:` in this pattern is redundant + } = Baz { x: 0, y: 0, z: 0 }; + } +} diff --git a/tests/ui/lint/lint-shorthand-field.stderr b/tests/ui/lint/lint-shorthand-field.stderr new file mode 100644 index 000000000..2d1ca30f9 --- /dev/null +++ b/tests/ui/lint/lint-shorthand-field.stderr @@ -0,0 +1,38 @@ +error: the `x:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:14:13 + | +LL | x: x, + | ^^^^ help: use shorthand field pattern: `x` + | +note: the lint level is defined here + --> $DIR/lint-shorthand-field.rs:4:9 + | +LL | #![deny(non_shorthand_field_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `y:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:15:13 + | +LL | y: ref y, + | ^^^^^^^^ help: use shorthand field pattern: `ref y` + +error: the `x:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:65:13 + | +LL | x: mut x, + | ^^^^^^^^ help: use shorthand field pattern: `mut x` + +error: the `y:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:66:13 + | +LL | y: ref y, + | ^^^^^^^^ help: use shorthand field pattern: `ref y` + +error: the `z:` in this pattern is redundant + --> $DIR/lint-shorthand-field.rs:67:13 + | +LL | z: ref mut z, + | ^^^^^^^^^^^^ help: use shorthand field pattern: `ref mut z` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/lint-stability-2.rs b/tests/ui/lint/lint-stability-2.rs new file mode 100644 index 000000000..94a8d08c8 --- /dev/null +++ b/tests/ui/lint/lint-stability-2.rs @@ -0,0 +1,413 @@ +// aux-build:lint_stability.rs +// aux-build:stability_cfg1.rs + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate lint_stability; + +mod cross_crate { + extern crate stability_cfg1; + + use lint_stability::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + ::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + ::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + + foo.method_deprecated_unstable(); + //~^ ERROR use of unstable library feature + Foo::method_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + ::method_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable(); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + + foo.method_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + Foo::method_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + ::method_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + + foo.method_unstable(); //~ ERROR use of unstable library feature + Foo::method_unstable(&foo); //~ ERROR use of unstable library feature + ::method_unstable(&foo); //~ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + + foo.method_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + Foo::method_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + ::method_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); + + struct S2(T::TypeDeprecated); + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = StableTupleStruct (1); + + // At the moment, the lint checker only checks stability in + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); + macro_test_arg!(macro_test_arg!(deprecated_text())); + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + foo.trait_deprecated_unstable(); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_deprecated_unstable(); + //~^ ERROR use of unstable library feature + foo.trait_deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + foo.trait_unstable(); //~ ERROR use of unstable library feature + foo.trait_unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_stable(); + } + + struct S; + + impl DeprecatedTrait for S {} + trait LocalTrait2 : DeprecatedTrait { } +} + +mod this_crate { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn unstable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub struct MethodTester; + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} + } + + pub trait Trait { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} + } + + impl Trait for MethodTester {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableUnitStruct; + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableUnitStruct; + + pub enum Enum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableTupleStruct(isize); + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableTupleStruct(isize); + + fn test() { + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + ::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + ::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + ::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + ::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); + } + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); + } + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } + + trait LocalTrait : DeprecatedTrait { } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-2.stderr b/tests/ui/lint/lint-stability-2.stderr new file mode 100644 index 000000000..5b7537fa2 --- /dev/null +++ b/tests/ui/lint/lint-stability-2.stderr @@ -0,0 +1,259 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:40:13 + | +LL | foo.method_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:42:9 + | +LL | Foo::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:44:9 + | +LL | ::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:46:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:48:9 + | +LL | ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:51:13 + | +LL | foo.method_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:53:9 + | +LL | Foo::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:55:9 + | +LL | ::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:57:13 + | +LL | foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:59:9 + | +LL | ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:62:13 + | +LL | foo.method_unstable(); + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:63:9 + | +LL | Foo::method_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:64:9 + | +LL | ::method_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:65:13 + | +LL | foo.trait_unstable(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:66:9 + | +LL | ::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:68:13 + | +LL | foo.method_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:70:9 + | +LL | Foo::method_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:72:9 + | +LL | ::method_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:74:13 + | +LL | foo.trait_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:76:9 + | +LL | ::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:131:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:133:9 + | +LL | ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:135:13 + | +LL | foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:137:9 + | +LL | ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:139:13 + | +LL | foo.trait_unstable(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:140:9 + | +LL | ::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:141:13 + | +LL | foo.trait_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:143:9 + | +LL | ::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:154:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:156:13 + | +LL | foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-2.rs:158:13 + | +LL | foo.trait_unstable(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability-2.rs:159:13 + | +LL | foo.trait_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 32 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-stability-deprecated.rs b/tests/ui/lint/lint-stability-deprecated.rs new file mode 100644 index 000000000..74c35083e --- /dev/null +++ b/tests/ui/lint/lint-stability-deprecated.rs @@ -0,0 +1,464 @@ +// check-pass +// aux-build:lint_stability.rs +// aux-build:inherited_stability.rs +// aux-build:stability_cfg1.rs +// aux-build:stability-cfg2.rs +#![warn(deprecated)] +#![feature(staged_api, unstable_test_feature)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate lint_stability; + +mod cross_crate { + extern crate stability_cfg1; + extern crate stability_cfg2; + + use lint_stability::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); //~ WARN use of deprecated function `lint_stability::deprecated` + foo.method_deprecated(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated` + Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated` + ::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated` + foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + + deprecated_text(); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text + foo.method_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + ::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + + deprecated_unstable(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable` + foo.method_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable` + Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable` + ::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable` + foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + + deprecated_unstable_text(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text + foo.method_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + ::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + ::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + ::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); + + struct S1(T::TypeUnstable); + struct S2(T::TypeDeprecated); + //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + type A = dyn TraitWithAssociatedTypes< + TypeUnstable = u8, + TypeDeprecated = u16, + //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` + //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` + //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` + >; + + let _ = DeprecatedStruct { //~ WARN use of deprecated struct `lint_stability::DeprecatedStruct` + i: 0 //~ WARN use of deprecated field `lint_stability::DeprecatedStruct::i` + }; + let _ = DeprecatedUnstableStruct { + //~^ WARN use of deprecated struct `lint_stability::DeprecatedUnstableStruct` + i: 0 //~ WARN use of deprecated field `lint_stability::DeprecatedUnstableStruct::i` + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; //~ WARN use of deprecated unit struct `lint_stability::DeprecatedUnitStruct` + let _ = DeprecatedUnstableUnitStruct; //~ WARN use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct` + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant` + let _ = Enum::DeprecatedUnstableVariant; //~ WARN use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant` + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct` + let _ = DeprecatedUnstableTupleStruct (1); //~ WARN use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct` + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + + // At the moment, the lint checker only checks stability + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text + macro_test_arg!(deprecated_unstable_text()); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text + macro_test_arg!(macro_test_arg!(deprecated_text())); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + ::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + ::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable` + foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + struct S; + + impl UnstableTrait for S { } + impl DeprecatedTrait for S {} //~ WARN use of deprecated trait `lint_stability::DeprecatedTrait`: text + trait LocalTrait : UnstableTrait { } + trait LocalTrait2 : DeprecatedTrait { } //~ WARN use of deprecated trait `lint_stability::DeprecatedTrait`: text + + impl Trait for S { + fn trait_stable(&self) {} + fn trait_unstable(&self) {} + } +} + +mod inheritance { + extern crate inherited_stability; + use self::inherited_stability::*; + + fn test_inheritance() { + unstable(); + stable(); + + stable_mod::unstable(); + stable_mod::stable(); + + unstable_mod::deprecated(); //~ WARN use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text + unstable_mod::unstable(); + + let _ = Unstable::UnstableVariant; + let _ = Unstable::StableVariant; + + let x: usize = 0; + x.unstable(); + x.stable(); + } +} + +mod this_crate { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn unstable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub struct MethodTester; + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} + } + + pub trait Trait { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} + } + + impl Trait for MethodTester {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableUnitStruct; + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableUnitStruct; + + pub enum Enum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableTupleStruct(isize); + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableTupleStruct(isize); + + fn test() { + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); //~ WARN use of deprecated function `this_crate::deprecated` + foo.method_deprecated(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated` + Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated` + ::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated` + foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + + deprecated_text(); //~ WARN use of deprecated function `this_crate::deprecated_text`: text + foo.method_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + ::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + ::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + ::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); + + let _ = DeprecatedStruct { + //~^ WARN use of deprecated struct `this_crate::DeprecatedStruct` + i: 0 //~ WARN use of deprecated field `this_crate::DeprecatedStruct::i` + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; //~ WARN use of deprecated unit struct `this_crate::DeprecatedUnitStruct` + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; //~ WARN use of deprecated unit variant `this_crate::Enum::DeprecatedVariant` + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); //~ WARN use of deprecated tuple struct `this_crate::DeprecatedTupleStruct` + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + ::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + ::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated` + foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); //~ WARN use of deprecated function `this_crate::test_fn_body::fn_in_body`: text + } + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); //~ WARN use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text + } + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } //~ WARN use of deprecated trait `this_crate::DeprecatedTrait` + + trait LocalTrait : DeprecatedTrait { } //~ WARN use of deprecated trait `this_crate::DeprecatedTrait` +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr new file mode 100644 index 000000000..9f1e7b281 --- /dev/null +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -0,0 +1,656 @@ +warning: use of deprecated function `lint_stability::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:24:9 + | +LL | deprecated(); + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability-deprecated.rs:6:9 + | +LL | #![warn(deprecated)] + | ^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:29:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:31:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:33:9 + | +LL | deprecated_text(); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:38:16 + | +LL | ... Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:40:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:42:9 + | +LL | deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:47:16 + | +LL | ... Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:49:25 + | +LL | ... ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:51:9 + | +LL | deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:56:16 + | +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:58:25 + | +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text + --> $DIR/lint-stability-deprecated.rs:108:17 + | +LL | let _ = DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text + --> $DIR/lint-stability-deprecated.rs:111:17 + | +LL | let _ = DeprecatedUnstableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit struct `lint_stability::DeprecatedUnitStruct`: text + --> $DIR/lint-stability-deprecated.rs:118:17 + | +LL | let _ = DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct`: text + --> $DIR/lint-stability-deprecated.rs:119:17 + | +LL | let _ = DeprecatedUnstableUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant`: text + --> $DIR/lint-stability-deprecated.rs:123:23 + | +LL | let _ = Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text + --> $DIR/lint-stability-deprecated.rs:124:23 + | +LL | let _ = Enum::DeprecatedUnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text + --> $DIR/lint-stability-deprecated.rs:128:17 + | +LL | let _ = DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text + --> $DIR/lint-stability-deprecated.rs:129:17 + | +LL | let _ = DeprecatedUnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:138:25 + | +LL | macro_test_arg!(deprecated_text()); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:139:25 + | +LL | macro_test_arg!(deprecated_unstable_text()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:140:41 + | +LL | macro_test_arg!(macro_test_arg!(deprecated_text())); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:145:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:147:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:149:16 + | +LL | ... Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:151:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:153:16 + | +LL | ... Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:155:25 + | +LL | ... ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:157:16 + | +LL | ... Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:159:25 + | +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:187:10 + | +LL | impl DeprecatedTrait for S {} + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:189:25 + | +LL | trait LocalTrait2 : DeprecatedTrait { } + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:208:23 + | +LL | unstable_mod::deprecated(); + | ^^^^^^^^^^ + +warning: use of deprecated function `this_crate::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:330:9 + | +LL | deprecated(); + | ^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:335:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:337:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `this_crate::deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:339:9 + | +LL | deprecated_text(); + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:344:16 + | +LL | Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:346:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `this_crate::DeprecatedStruct`: text + --> $DIR/lint-stability-deprecated.rs:384:17 + | +LL | let _ = DeprecatedStruct { + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text + --> $DIR/lint-stability-deprecated.rs:391:17 + | +LL | let _ = DeprecatedUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text + --> $DIR/lint-stability-deprecated.rs:395:23 + | +LL | let _ = Enum::DeprecatedVariant; + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text + --> $DIR/lint-stability-deprecated.rs:399:17 + | +LL | let _ = DeprecatedTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:406:16 + | +LL | Trait::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:408:25 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:410:16 + | +LL | Trait::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:412:25 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text + --> $DIR/lint-stability-deprecated.rs:439:9 + | +LL | fn_in_body(); + | ^^^^^^^^^^ + +warning: use of deprecated trait `this_crate::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:459:10 + | +LL | impl DeprecatedTrait for S { } + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated trait `this_crate::DeprecatedTrait`: text + --> $DIR/lint-stability-deprecated.rs:461:24 + | +LL | trait LocalTrait : DeprecatedTrait { } + | ^^^^^^^^^^^^^^^ + +warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text + --> $DIR/lint-stability-deprecated.rs:447:13 + | +LL | fn_in_body(); + | ^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:97:48 + | +LL | struct S2(T::TypeDeprecated); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:102:13 + | +LL | TypeDeprecated = u16, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:25:13 + | +LL | foo.method_deprecated(); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:26:14 + | +LL | Foo::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:27:16 + | +LL | ::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:28:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:30:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:34:13 + | +LL | ... foo.method_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:35:14 + | +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:36:16 + | +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:37:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:39:16 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:43:13 + | +LL | ... foo.method_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:44:14 + | +LL | ... Foo::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:45:16 + | +LL | ... ::method_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:46:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:48:16 + | +LL | ... ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:52:13 + | +LL | ... foo.method_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:53:14 + | +LL | ... Foo::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:54:16 + | +LL | ... ::method_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:55:13 + | +LL | ... foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:57:16 + | +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text + --> $DIR/lint-stability-deprecated.rs:109:13 + | +LL | i: 0 + | ^^^^ + +warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text + --> $DIR/lint-stability-deprecated.rs:113:13 + | +LL | i: 0 + | ^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:144:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:146:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:148:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:150:16 + | +LL | ... ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:152:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:154:16 + | +LL | ... ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:156:13 + | +LL | ... foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:158:16 + | +LL | ... ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:175:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:176:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text + --> $DIR/lint-stability-deprecated.rs:177:13 + | +LL | foo.trait_deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text + --> $DIR/lint-stability-deprecated.rs:178:13 + | +LL | ... foo.trait_deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:331:13 + | +LL | foo.method_deprecated(); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:332:14 + | +LL | Foo::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:333:16 + | +LL | ::method_deprecated(&foo); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:334:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:336:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:340:13 + | +LL | ... foo.method_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:341:14 + | +LL | ... Foo::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:342:16 + | +LL | ... ::method_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:343:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:345:16 + | +LL | ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text + --> $DIR/lint-stability-deprecated.rs:386:13 + | +LL | i: 0 + | ^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:405:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:407:16 + | +LL | ::trait_deprecated(&foo); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:409:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:411:16 + | +LL | ::trait_deprecated_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text + --> $DIR/lint-stability-deprecated.rs:428:13 + | +LL | foo.trait_deprecated(); + | ^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text + --> $DIR/lint-stability-deprecated.rs:429:13 + | +LL | foo.trait_deprecated_text(); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:97:48 + | +LL | struct S2(T::TypeDeprecated); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:102:13 + | +LL | TypeDeprecated = u16, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:102:13 + | +LL | TypeDeprecated = u16, + | ^^^^^^^^^^^^^^^^^^^^ + +warning: 108 warnings emitted + diff --git a/tests/ui/lint/lint-stability-fields-deprecated.rs b/tests/ui/lint/lint-stability-fields-deprecated.rs new file mode 100644 index 000000000..a5511966d --- /dev/null +++ b/tests/ui/lint/lint-stability-fields-deprecated.rs @@ -0,0 +1,344 @@ +// aux-build:lint_stability_fields.rs + +#![deny(deprecated)] +#![allow(dead_code)] +#![feature(staged_api, unstable_test_feature)] + +#![stable(feature = "rust1", since = "1.0.0")] + +mod cross_crate { + extern crate lint_stability_fields; + + use self::lint_stability_fields::*; + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + override3: 4, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + let _ = x.override3; + + let Stable { + inherit: _, + override1: _, + override2: _, + //~^ ERROR use of deprecated field + override3: _, + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3, 4); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + let _ = x.3; + + let Stable2(_, + _, + _, + //~^ ERROR use of deprecated field + _) + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Unstable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + + let Unstable2 + (_, + _, + _) + //~^ ERROR use of deprecated field + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + //~^ ERROR use of deprecated struct + inherit: 1, + //~^ ERROR use of deprecated field + override1: 2, + //~^ ERROR use of deprecated field + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated field + let _ = x.override1; + //~^ ERROR use of deprecated field + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Deprecated { + //~^ ERROR use of deprecated struct + inherit: _, + //~^ ERROR use of deprecated field + override1: _, + //~^ ERROR use of deprecated field + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Deprecated + //~^ ERROR use of deprecated struct + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated tuple struct + + let _ = x.0; + //~^ ERROR use of deprecated field + let _ = x.1; + //~^ ERROR use of deprecated field + let _ = x.2; + //~^ ERROR use of deprecated field + + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + (_, + //~^ ERROR use of deprecated field + _, + //~^ ERROR use of deprecated field + _) + //~^ ERROR use of deprecated field + = x; + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + // the patterns are all fine: + (..) = x; + } +} + +mod this_crate { + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable { + inherit: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] u8); + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Stable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated field + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + + let Stable2(_, + _, + _) + //~^ ERROR use of deprecated field + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Unstable { + inherit: _, + override1: _, + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + //~^ ERROR use of deprecated field + + let Unstable2 + (_, + _, + _) + //~^ ERROR use of deprecated field + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + //~^ ERROR use of deprecated struct + inherit: 1, + //~^ ERROR use of deprecated field + override1: 2, + //~^ ERROR use of deprecated field + override2: 3, + //~^ ERROR use of deprecated field + }; + + let _ = x.inherit; + //~^ ERROR use of deprecated field + let _ = x.override1; + //~^ ERROR use of deprecated field + let _ = x.override2; + //~^ ERROR use of deprecated field + + let Deprecated { + //~^ ERROR use of deprecated struct + inherit: _, + //~^ ERROR use of deprecated field + override1: _, + //~^ ERROR use of deprecated field + override2: _ + //~^ ERROR use of deprecated field + } = x; + + let Deprecated + //~^ ERROR use of deprecated struct + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + //~^ ERROR use of deprecated tuple struct + + let _ = x.0; + //~^ ERROR use of deprecated field + let _ = x.1; + //~^ ERROR use of deprecated field + let _ = x.2; + //~^ ERROR use of deprecated field + + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + (_, + //~^ ERROR use of deprecated field + _, + //~^ ERROR use of deprecated field + _) + //~^ ERROR use of deprecated field + = x; + let Deprecated2 + //~^ ERROR use of deprecated tuple struct + // the patterns are all fine: + (..) = x; + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-fields-deprecated.stderr b/tests/ui/lint/lint-stability-fields-deprecated.stderr new file mode 100644 index 000000000..2d8326020 --- /dev/null +++ b/tests/ui/lint/lint-stability-fields-deprecated.stderr @@ -0,0 +1,380 @@ +error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:99:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability-fields-deprecated.rs:3:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:116:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `cross_crate::lint_stability_fields::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:126:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + +error: use of deprecated tuple struct `cross_crate::lint_stability_fields::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:131:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `cross_crate::lint_stability_fields::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:141:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `cross_crate::lint_stability_fields::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:150:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated struct `this_crate::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:286:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `this_crate::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:303:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + +error: use of deprecated struct `this_crate::Deprecated`: text + --> $DIR/lint-stability-fields-deprecated.rs:313:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:318:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:328:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated tuple struct `this_crate::Deprecated2`: text + --> $DIR/lint-stability-fields-deprecated.rs:337:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:18:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:25:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:32:13 + | +LL | override2: _, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:43:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:49:20 + | +LL | _, + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:60:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:66:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:72:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:85:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:91:14 + | +LL | _) + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:101:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:103:13 + | +LL | override1: 2, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:105:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:109:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:111:17 + | +LL | let _ = x.override1; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:113:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:118:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:120:13 + | +LL | override1: _, + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:122:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:134:17 + | +LL | let _ = x.0; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:136:17 + | +LL | let _ = x.1; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:138:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:143:14 + | +LL | (_, + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:145:14 + | +LL | _, + | ^ + +error: use of deprecated field `cross_crate::lint_stability_fields::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:147:14 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:210:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:216:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Stable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:222:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:232:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate::Stable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:237:20 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:247:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:253:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Unstable::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:259:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:272:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate::Unstable2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:278:14 + | +LL | _) + | ^ + +error: use of deprecated field `this_crate::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:288:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:290:13 + | +LL | override1: 2, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:292:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:296:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:298:17 + | +LL | let _ = x.override1; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:300:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::inherit`: text + --> $DIR/lint-stability-fields-deprecated.rs:305:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override1`: text + --> $DIR/lint-stability-fields-deprecated.rs:307:13 + | +LL | override1: _, + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated::override2`: text + --> $DIR/lint-stability-fields-deprecated.rs:309:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + +error: use of deprecated field `this_crate::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:321:17 + | +LL | let _ = x.0; + | ^^^ + +error: use of deprecated field `this_crate::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:323:17 + | +LL | let _ = x.1; + | ^^^ + +error: use of deprecated field `this_crate::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:325:17 + | +LL | let _ = x.2; + | ^^^ + +error: use of deprecated field `this_crate::Deprecated2::0`: text + --> $DIR/lint-stability-fields-deprecated.rs:330:14 + | +LL | (_, + | ^ + +error: use of deprecated field `this_crate::Deprecated2::1`: text + --> $DIR/lint-stability-fields-deprecated.rs:332:14 + | +LL | _, + | ^ + +error: use of deprecated field `this_crate::Deprecated2::2`: text + --> $DIR/lint-stability-fields-deprecated.rs:334:14 + | +LL | _) + | ^ + +error: aborting due to 62 previous errors + diff --git a/tests/ui/lint/lint-stability-fields.rs b/tests/ui/lint/lint-stability-fields.rs new file mode 100644 index 000000000..51990b6ee --- /dev/null +++ b/tests/ui/lint/lint-stability-fields.rs @@ -0,0 +1,293 @@ +// aux-build:lint_stability_fields.rs +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +mod cross_crate { + extern crate lint_stability_fields; + + mod reexport { + #[stable(feature = "rust1", since = "1.0.0")] + pub use super::lint_stability_fields::*; + } + + use self::lint_stability_fields::*; + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, //~ ERROR use of unstable + override2: 3, //~ ERROR use of unstable + override3: 4, + }; + + let _ = x.inherit; + let _ = x.override1; //~ ERROR use of unstable + let _ = x.override2; //~ ERROR use of unstable + let _ = x.override3; + + let Stable { + inherit: _, + override1: _, //~ ERROR use of unstable + override2: _, //~ ERROR use of unstable + override3: _ + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3, 4); + + let _ = x.0; + let _ = x.1; //~ ERROR use of unstable + let _ = x.2; //~ ERROR use of unstable + let _ = x.3; + + let Stable2(_, + _, //~ ERROR use of unstable + _, //~ ERROR use of unstable + _) + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { //~ ERROR use of unstable + inherit: 1, //~ ERROR use of unstable + override1: 2, + override2: 3, //~ ERROR use of unstable + }; + + let _ = x.inherit; //~ ERROR use of unstable + let _ = x.override1; + let _ = x.override2; //~ ERROR use of unstable + + let Unstable { //~ ERROR use of unstable + inherit: _, //~ ERROR use of unstable + override1: _, + override2: _ //~ ERROR use of unstable + } = x; + + let Unstable //~ ERROR use of unstable + // the patterns are all fine: + { .. } = x; + + // Unstable items are still unstable even when used through a stable "pub use". + let x = reexport::Unstable2(1, 2, 3); //~ ERROR use of unstable + + let x = Unstable2(1, 2, 3); //~ ERROR use of unstable + + let _ = x.0; //~ ERROR use of unstable + let _ = x.1; + let _ = x.2; //~ ERROR use of unstable + + let Unstable2 //~ ERROR use of unstable + (_, //~ ERROR use of unstable + _, + _) //~ ERROR use of unstable + = x; + let Unstable2 //~ ERROR use of unstable + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { //~ ERROR use of unstable + inherit: 1, //~ ERROR use of unstable + override1: 2, + override2: 3, //~ ERROR use of unstable + }; + + let _ = x.inherit; //~ ERROR use of unstable + let _ = x.override1; + let _ = x.override2; //~ ERROR use of unstable + + let Deprecated { //~ ERROR use of unstable + inherit: _, //~ ERROR use of unstable + override1: _, + override2: _ //~ ERROR use of unstable + } = x; + + let Deprecated //~ ERROR use of unstable + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); //~ ERROR use of unstable + + let _ = x.0; //~ ERROR use of unstable + let _ = x.1; + let _ = x.2; //~ ERROR use of unstable + + let Deprecated2 //~ ERROR use of unstable + (_, //~ ERROR use of unstable + _, + _) //~ ERROR use of unstable + = x; + let Deprecated2 //~ ERROR use of unstable + // the patterns are all fine: + (..) = x; + } +} + +mod this_crate { + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable { + inherit: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + #[stable(feature = "rust2", since = "2.0.0")] + override3: u8, + } + + #[stable(feature = "rust1", since = "1.0.0")] + struct Stable2(u8, + #[stable(feature = "rust2", since = "2.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[deprecated(since = "1.0.0", note = "text")] + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + struct Unstable2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] u8); + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated { + inherit: u8, + #[stable(feature = "rust1", since = "1.0.0")] + override1: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + override2: u8, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + struct Deprecated2(u8, + #[stable(feature = "rust1", since = "1.0.0")] u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] u8); + + pub fn foo() { + let x = Stable { + inherit: 1, + override1: 2, + override2: 3, + override3: 4, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + let _ = x.override3; + + let Stable { + inherit: _, + override1: _, + override2: _, + override3: _ + } = x; + // all fine + let Stable { .. } = x; + + let x = Stable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + + let Stable2(_, + _, + _) + = x; + // all fine + let Stable2(..) = x; + + + let x = Unstable { + inherit: 1, + override1: 2, + override2: 3, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + + let Unstable { + inherit: _, + override1: _, + override2: _ + } = x; + + let Unstable + // the patterns are all fine: + { .. } = x; + + + let x = Unstable2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + + let Unstable2 + (_, + _, + _) + = x; + let Unstable2 + // the patterns are all fine: + (..) = x; + + + let x = Deprecated { + inherit: 1, + override1: 2, + override2: 3, + }; + + let _ = x.inherit; + let _ = x.override1; + let _ = x.override2; + + let Deprecated { + inherit: _, + override1: _, + override2: _ + } = x; + + let Deprecated + // the patterns are all fine: + { .. } = x; + + let x = Deprecated2(1, 2, 3); + + let _ = x.0; + let _ = x.1; + let _ = x.2; + + let Deprecated2 + (_, + _, + _) + = x; + let Deprecated2 + // the patterns are all fine: + (..) = x; + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability-fields.stderr b/tests/ui/lint/lint-stability-fields.stderr new file mode 100644 index 000000000..3d2e73c1e --- /dev/null +++ b/tests/ui/lint/lint-stability-fields.stderr @@ -0,0 +1,347 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:56:17 + | +LL | let x = Unstable { + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:66:13 + | +LL | let Unstable { + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:72:13 + | +LL | let Unstable + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:77:17 + | +LL | let x = reexport::Unstable2(1, 2, 3); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:79:17 + | +LL | let x = Unstable2(1, 2, 3); + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:85:13 + | +LL | let Unstable2 + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:90:13 + | +LL | let Unstable2 + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:95:17 + | +LL | let x = Deprecated { + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:105:13 + | +LL | let Deprecated { + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:111:13 + | +LL | let Deprecated + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:115:17 + | +LL | let x = Deprecated2(1, 2, 3); + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:121:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:126:13 + | +LL | let Deprecated2 + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:21:13 + | +LL | override1: 2, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:22:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:27:17 + | +LL | let _ = x.override1; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:28:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:33:13 + | +LL | override1: _, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:34:13 + | +LL | override2: _, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:43:17 + | +LL | let _ = x.1; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:44:17 + | +LL | let _ = x.2; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:48:20 + | +LL | _, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:49:20 + | +LL | _, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:57:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:59:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:62:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:64:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:67:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:69:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:81:17 + | +LL | let _ = x.0; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:83:17 + | +LL | let _ = x.2; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:86:14 + | +LL | (_, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:88:14 + | +LL | _) + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:96:13 + | +LL | inherit: 1, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:98:13 + | +LL | override2: 3, + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:101:17 + | +LL | let _ = x.inherit; + | ^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:103:17 + | +LL | let _ = x.override2; + | ^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:106:13 + | +LL | inherit: _, + | ^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:108:13 + | +LL | override2: _ + | ^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:117:17 + | +LL | let _ = x.0; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:119:17 + | +LL | let _ = x.2; + | ^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:122:14 + | +LL | (_, + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability-fields.rs:124:14 + | +LL | _) + | ^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 43 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-stability.rs b/tests/ui/lint/lint-stability.rs new file mode 100644 index 000000000..d0f0e9f80 --- /dev/null +++ b/tests/ui/lint/lint-stability.rs @@ -0,0 +1,454 @@ +// aux-build:lint_stability.rs +// aux-build:inherited_stability.rs +// aux-build:stability_cfg1.rs +// aux-build:stability-cfg2.rs + +#![allow(deprecated)] +#![allow(dead_code)] +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate lint_stability; + +mod cross_crate { + extern crate stability_cfg1; + extern crate stability_cfg2; //~ ERROR use of unstable library feature + + use lint_stability::*; + + fn test() { + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + ::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + ::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + + deprecated_future(); // Fine; no error. + + deprecated_unstable(); + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + + deprecated_unstable_text(); + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + + unstable(); //~ ERROR use of unstable library feature + Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + + unstable_text(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + Trait::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); + + struct S1(T::TypeUnstable); + //~^ ERROR use of unstable library feature + struct S2(T::TypeDeprecated); + type A = dyn TraitWithAssociatedTypes< + TypeUnstable = u8, //~ ERROR use of unstable library feature + TypeDeprecated = u16, + >; + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = DeprecatedUnstableStruct { + //~^ ERROR use of unstable library feature + i: 0 + }; + let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable library feature + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = DeprecatedUnstableUnitStruct; + //~^ ERROR use of unstable library feature + let _ = UnstableUnitStruct; //~ ERROR use of unstable library feature + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::DeprecatedUnstableVariant; + //~^ ERROR use of unstable library feature + let _ = Enum::UnstableVariant; //~ ERROR use of unstable library feature + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = DeprecatedUnstableTupleStruct (1); + //~^ ERROR use of unstable library feature + let _ = UnstableTupleStruct (1); //~ ERROR use of unstable library feature + let _ = StableTupleStruct (1); + + // At the moment, the lint checker only checks stability in + // in the arguments of macros. + // Eventually, we will want to lint the contents of the + // macro in the module *defining* it. Also, stability levels + // on macros themselves are not yet linted. + macro_test_arg!(deprecated_text()); + macro_test_arg!(deprecated_unstable_text()); + //~^ ERROR use of unstable library feature + macro_test_arg!(macro_test_arg!(deprecated_text())); + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + Trait::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable(&foo); + //~^ ERROR use of unstable library feature + Trait::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + ::trait_deprecated_unstable_text(&foo); + //~^ ERROR use of unstable library feature + Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature + ::trait_unstable(&foo); //~ ERROR use of unstable library feature + Trait::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + ::trait_unstable_text(&foo); + //~^ ERROR use of unstable library feature 'unstable_test_feature': text + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_stable(); + } + + struct S; + + impl UnstableTrait for S { } //~ ERROR use of unstable library feature + impl DeprecatedTrait for S {} + trait LocalTrait : UnstableTrait { } //~ ERROR use of unstable library feature + trait LocalTrait2 : DeprecatedTrait { } + + impl Trait for S { + fn trait_stable(&self) {} + fn trait_unstable(&self) {} //~ ERROR use of unstable library feature + } +} + +mod inheritance { + extern crate inherited_stability; //~ ERROR use of unstable library feature + use self::inherited_stability::*; //~ ERROR use of unstable library feature + + fn test_inheritance() { + unstable(); //~ ERROR use of unstable library feature + stable(); + + stable_mod::unstable(); //~ ERROR use of unstable library feature + stable_mod::stable(); + + unstable_mod::deprecated(); //~ ERROR use of unstable library feature + unstable_mod::unstable(); //~ ERROR use of unstable library feature + + let _ = Unstable::UnstableVariant; //~ ERROR use of unstable library feature + let _ = Unstable::StableVariant; //~ ERROR use of unstable library feature + + let x: usize = 0; + x.stable(); + } +} + +mod this_crate { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated() {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn deprecated_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future() {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn unstable() {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn unstable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable() {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn stable_text() {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub struct MethodTester; + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} + } + + pub trait Trait { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} + } + + impl Trait for MethodTester {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] i: isize + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedUnitStruct; + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableUnitStruct; + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableUnitStruct; + + pub enum Enum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub struct DeprecatedTupleStruct(isize); + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub struct UnstableTupleStruct(isize); + #[stable(feature = "rust1", since = "1.0.0")] + pub struct StableTupleStruct(isize); + + fn test() { + // Only the deprecated cases of the following should generate + // errors, because other stability attributes now have meaning + // only *across* crates, not within a single crate. + + type Foo = MethodTester; + let foo = MethodTester; + + deprecated(); + foo.method_deprecated(); + Foo::method_deprecated(&foo); + ::method_deprecated(&foo); + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + + deprecated_text(); + foo.method_deprecated_text(); + Foo::method_deprecated_text(&foo); + ::method_deprecated_text(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + + deprecated_future(); + + unstable(); + foo.method_unstable(); + Foo::method_unstable(&foo); + ::method_unstable(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + + unstable_text(); + foo.method_unstable_text(); + Foo::method_unstable_text(&foo); + ::method_unstable_text(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + + stable(); + foo.method_stable(); + Foo::method_stable(&foo); + ::method_stable(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + + stable_text(); + foo.method_stable_text(); + Foo::method_stable_text(&foo); + ::method_stable_text(&foo); + foo.trait_stable_text(); + Trait::trait_stable_text(&foo); + ::trait_stable_text(&foo); + ::trait_stable_text(&foo); + + let _ = DeprecatedStruct { + i: 0 + }; + let _ = UnstableStruct { i: 0 }; + let _ = StableStruct { i: 0 }; + + let _ = DeprecatedUnitStruct; + let _ = UnstableUnitStruct; + let _ = StableUnitStruct; + + let _ = Enum::DeprecatedVariant; + let _ = Enum::UnstableVariant; + let _ = Enum::StableVariant; + + let _ = DeprecatedTupleStruct (1); + let _ = UnstableTupleStruct (1); + let _ = StableTupleStruct (1); + } + + fn test_method_param(foo: Foo) { + foo.trait_deprecated(); + Trait::trait_deprecated(&foo); + ::trait_deprecated(&foo); + ::trait_deprecated(&foo); + foo.trait_deprecated_text(); + Trait::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + ::trait_deprecated_text(&foo); + foo.trait_unstable(); + Trait::trait_unstable(&foo); + ::trait_unstable(&foo); + ::trait_unstable(&foo); + foo.trait_unstable_text(); + Trait::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + ::trait_unstable_text(&foo); + foo.trait_stable(); + Trait::trait_stable(&foo); + ::trait_stable(&foo); + ::trait_stable(&foo); + } + + fn test_method_object(foo: &dyn Trait) { + foo.trait_deprecated(); + foo.trait_deprecated_text(); + foo.trait_unstable(); + foo.trait_unstable_text(); + foo.trait_stable(); + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_fn_body() { + fn fn_in_body() {} + fn_in_body(); + } + + impl MethodTester { + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn test_method_body(&self) { + fn fn_in_body() {} + fn_in_body(); + } + } + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub trait DeprecatedTrait { + fn dummy(&self) { } + } + + struct S; + + impl DeprecatedTrait for S { } + + trait LocalTrait : DeprecatedTrait { } +} + +fn main() {} diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr new file mode 100644 index 000000000..bd1a57dc4 --- /dev/null +++ b/tests/ui/lint/lint-stability.stderr @@ -0,0 +1,347 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:17:5 + | +LL | extern crate stability_cfg2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:45:9 + | +LL | deprecated_unstable(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:47:9 + | +LL | Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:49:9 + | +LL | ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:52:9 + | +LL | deprecated_unstable_text(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:54:9 + | +LL | Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:56:9 + | +LL | ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:59:9 + | +LL | unstable(); + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:60:9 + | +LL | Trait::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:61:9 + | +LL | ::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:63:9 + | +LL | unstable_text(); + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:65:9 + | +LL | Trait::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:67:9 + | +LL | ::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:99:17 + | +LL | let _ = DeprecatedUnstableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:103:17 + | +LL | let _ = UnstableStruct { i: 0 }; + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:107:17 + | +LL | let _ = DeprecatedUnstableUnitStruct; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:109:17 + | +LL | let _ = UnstableUnitStruct; + | ^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:113:17 + | +LL | let _ = Enum::DeprecatedUnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:115:17 + | +LL | let _ = Enum::UnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:119:17 + | +LL | let _ = DeprecatedUnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:121:17 + | +LL | let _ = UnstableTupleStruct (1); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:130:25 + | +LL | macro_test_arg!(deprecated_unstable_text()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:144:9 + | +LL | Trait::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:146:9 + | +LL | ::trait_deprecated_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:148:9 + | +LL | Trait::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:150:9 + | +LL | ::trait_deprecated_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:152:9 + | +LL | Trait::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:153:9 + | +LL | ::trait_unstable(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:154:9 + | +LL | Trait::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/lint-stability.rs:156:9 + | +LL | ::trait_unstable_text(&foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:172:10 + | +LL | impl UnstableTrait for S { } + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:174:24 + | +LL | trait LocalTrait : UnstableTrait { } + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:179:9 + | +LL | fn trait_unstable(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:184:5 + | +LL | extern crate inherited_stability; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:185:9 + | +LL | use self::inherited_stability::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:188:9 + | +LL | unstable(); + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:191:9 + | +LL | stable_mod::unstable(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:194:9 + | +LL | unstable_mod::deprecated(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:195:9 + | +LL | unstable_mod::unstable(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:197:17 + | +LL | let _ = Unstable::UnstableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:198:17 + | +LL | let _ = Unstable::StableVariant; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:88:48 + | +LL | struct S1(T::TypeUnstable); + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/lint-stability.rs:92:13 + | +LL | TypeUnstable = u8, + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 43 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/lint-stability2.rs b/tests/ui/lint/lint-stability2.rs new file mode 100644 index 000000000..9ae23dac6 --- /dev/null +++ b/tests/ui/lint/lint-stability2.rs @@ -0,0 +1,13 @@ +// aux-build:lint_stability.rs +// error-pattern: use of deprecated function + +#![deny(deprecated)] + +#[macro_use] +extern crate lint_stability; + +use lint_stability::*; + +fn main() { + macro_test!(); +} diff --git a/tests/ui/lint/lint-stability2.stderr b/tests/ui/lint/lint-stability2.stderr new file mode 100644 index 000000000..51bdf84a3 --- /dev/null +++ b/tests/ui/lint/lint-stability2.stderr @@ -0,0 +1,15 @@ +error: use of deprecated function `lint_stability::deprecated`: text + --> $DIR/lint-stability2.rs:12:5 + | +LL | macro_test!(); + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability2.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + = note: this error originates in the macro `macro_test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-stability3.rs b/tests/ui/lint/lint-stability3.rs new file mode 100644 index 000000000..4452846ec --- /dev/null +++ b/tests/ui/lint/lint-stability3.rs @@ -0,0 +1,14 @@ +// aux-build:lint_stability.rs +// error-pattern: use of deprecated function + +#![deny(deprecated)] +#![allow(warnings)] + +#[macro_use] +extern crate lint_stability; + +use lint_stability::*; + +fn main() { + macro_test_arg_nested!(deprecated_text); +} diff --git a/tests/ui/lint/lint-stability3.stderr b/tests/ui/lint/lint-stability3.stderr new file mode 100644 index 000000000..3bbb60dd3 --- /dev/null +++ b/tests/ui/lint/lint-stability3.stderr @@ -0,0 +1,14 @@ +error: use of deprecated function `lint_stability::deprecated_text`: text + --> $DIR/lint-stability3.rs:13:28 + | +LL | macro_test_arg_nested!(deprecated_text); + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-stability3.rs:4:9 + | +LL | #![deny(deprecated)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs new file mode 100644 index 000000000..d2d72a68f --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.rs @@ -0,0 +1,7 @@ +#![feature(strict_provenance)] +#![deny(fuzzy_provenance_casts)] + +fn main() { + let dangling = 16_usize as *const u8; + //~^ ERROR strict provenance disallows casting integer `usize` to pointer `*const u8` +} diff --git a/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr new file mode 100644 index 000000000..383623b48 --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-fuzzy-casts.stderr @@ -0,0 +1,19 @@ +error: strict provenance disallows casting integer `usize` to pointer `*const u8` + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:5:20 + | +LL | let dangling = 16_usize as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead +note: the lint level is defined here + --> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9 + | +LL | #![deny(fuzzy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ +help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address + | +LL | let dangling = (...).with_addr(16_usize); + | ++++++++++++++++ ~ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-strict-provenance-lossy-casts.rs b/tests/ui/lint/lint-strict-provenance-lossy-casts.rs new file mode 100644 index 000000000..9799a0537 --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-lossy-casts.rs @@ -0,0 +1,18 @@ +#![feature(strict_provenance)] +#![deny(lossy_provenance_casts)] + +fn main() { + let x: u8 = 37; + let addr: usize = &x as *const u8 as usize; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + + let addr_32bit = &x as *const u8 as u32; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + + // don't add unnecessary parens in the suggestion + let ptr = &x as *const u8; + let ptr_addr = ptr as usize; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + let ptr_addr_32bit = ptr as u32; + //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` +} diff --git a/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr b/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr new file mode 100644 index 000000000..aa151fe2d --- /dev/null +++ b/tests/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -0,0 +1,51 @@ +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + --> $DIR/lint-strict-provenance-lossy-casts.rs:6:23 + | +LL | let addr: usize = &x as *const u8 as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead +note: the lint level is defined here + --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9 + | +LL | #![deny(lossy_provenance_casts)] + | ^^^^^^^^^^^^^^^^^^^^^^ +help: use `.addr()` to obtain the address of a pointer + | +LL | let addr: usize = (&x as *const u8).addr(); + | + ~~~~~~~~ + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22 + | +LL | let addr_32bit = &x as *const u8 as u32; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead +help: use `.addr()` to obtain the address of a pointer + | +LL | let addr_32bit = (&x as *const u8).addr() as u32; + | + ~~~~~~~~~~~~~~~ + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize` + --> $DIR/lint-strict-provenance-lossy-casts.rs:14:20 + | +LL | let ptr_addr = ptr as usize; + | ^^^--------- + | | + | help: use `.addr()` to obtain the address of a pointer: `.addr()` + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + +error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` + --> $DIR/lint-strict-provenance-lossy-casts.rs:16:26 + | +LL | let ptr_addr_32bit = ptr as u32; + | ^^^------- + | | + | help: use `.addr()` to obtain the address of a pointer: `.addr() as u32` + | + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/lint-temporary-cstring-as-param.rs b/tests/ui/lint/lint-temporary-cstring-as-param.rs new file mode 100644 index 000000000..9f5805367 --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-param.rs @@ -0,0 +1,11 @@ +#![deny(temporary_cstring_as_ptr)] + +use std::ffi::CString; +use std::os::raw::c_char; + +fn some_function(data: *const c_char) {} + +fn main() { + some_function(CString::new("").unwrap().as_ptr()); + //~^ ERROR getting the inner pointer of a temporary `CString` +} diff --git a/tests/ui/lint/lint-temporary-cstring-as-param.stderr b/tests/ui/lint/lint-temporary-cstring-as-param.stderr new file mode 100644 index 000000000..838b3bc13 --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-param.stderr @@ -0,0 +1,18 @@ +error: getting the inner pointer of a temporary `CString` + --> $DIR/lint-temporary-cstring-as-param.rs:9:45 + | +LL | some_function(CString::new("").unwrap().as_ptr()); + | ------------------------- ^^^^^^ this pointer will be invalid + | | + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime + | + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html +note: the lint level is defined here + --> $DIR/lint-temporary-cstring-as-param.rs:1:9 + | +LL | #![deny(temporary_cstring_as_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-temporary-cstring-as-ptr.rs b/tests/ui/lint/lint-temporary-cstring-as-ptr.rs new file mode 100644 index 000000000..7aa4f2e1e --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-ptr.rs @@ -0,0 +1,9 @@ +// this program is not technically incorrect, but is an obscure enough style to be worth linting +#![deny(temporary_cstring_as_ptr)] + +use std::ffi::CString; + +fn main() { + let s = CString::new("some text").unwrap().as_ptr(); + //~^ ERROR getting the inner pointer of a temporary `CString` +} diff --git a/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr b/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr new file mode 100644 index 000000000..79ef57dd1 --- /dev/null +++ b/tests/ui/lint/lint-temporary-cstring-as-ptr.stderr @@ -0,0 +1,18 @@ +error: getting the inner pointer of a temporary `CString` + --> $DIR/lint-temporary-cstring-as-ptr.rs:7:48 + | +LL | let s = CString::new("some text").unwrap().as_ptr(); + | ---------------------------------- ^^^^^^ this pointer will be invalid + | | + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime + | + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html +note: the lint level is defined here + --> $DIR/lint-temporary-cstring-as-ptr.rs:2:9 + | +LL | #![deny(temporary_cstring_as_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-type-limits.rs b/tests/ui/lint/lint-type-limits.rs new file mode 100644 index 000000000..2b140f869 --- /dev/null +++ b/tests/ui/lint/lint-type-limits.rs @@ -0,0 +1,27 @@ +#![allow(dead_code)] + +// compile-flags: -D unused-comparisons +fn main() { } + +fn foo() { + let mut i = 100_usize; + while i >= 0 { //~ ERROR comparison is useless due to type limits + i -= 1; + } +} + +fn bar() -> i8 { + return 123; +} + +fn bleh() { + let u = 42u8; + let _ = u > 255; //~ ERROR comparison is useless due to type limits + let _ = 255 < u; //~ ERROR comparison is useless due to type limits + let _ = u < 0; //~ ERROR comparison is useless due to type limits + let _ = 0 > u; //~ ERROR comparison is useless due to type limits + let _ = u <= 255; //~ ERROR comparison is useless due to type limits + let _ = 255 >= u; //~ ERROR comparison is useless due to type limits + let _ = u >= 0; //~ ERROR comparison is useless due to type limits + let _ = 0 <= u; //~ ERROR comparison is useless due to type limits +} diff --git a/tests/ui/lint/lint-type-limits.stderr b/tests/ui/lint/lint-type-limits.stderr new file mode 100644 index 000000000..71a2b3bfd --- /dev/null +++ b/tests/ui/lint/lint-type-limits.stderr @@ -0,0 +1,58 @@ +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:8:11 + | +LL | while i >= 0 { + | ^^^^^^ + | + = note: requested on the command line with `-D unused-comparisons` + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:19:13 + | +LL | let _ = u > 255; + | ^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:20:13 + | +LL | let _ = 255 < u; + | ^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:21:13 + | +LL | let _ = u < 0; + | ^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:22:13 + | +LL | let _ = 0 > u; + | ^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:23:13 + | +LL | let _ = u <= 255; + | ^^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:24:13 + | +LL | let _ = 255 >= u; + | ^^^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:25:13 + | +LL | let _ = u >= 0; + | ^^^^^^ + +error: comparison is useless due to type limits + --> $DIR/lint-type-limits.rs:26:13 + | +LL | let _ = 0 <= u; + | ^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/lint/lint-type-limits2.rs b/tests/ui/lint/lint-type-limits2.rs new file mode 100644 index 000000000..3f90119cd --- /dev/null +++ b/tests/ui/lint/lint-type-limits2.rs @@ -0,0 +1,15 @@ +#![allow(dead_code)] +#![warn(overflowing_literals)] + +// compile-flags: -D unused-comparisons +fn main() { } + + +fn bar() -> i8 { + return 123; +} + +fn baz() -> bool { + 128 > bar() //~ ERROR comparison is useless due to type limits + //~| WARN literal out of range for `i8` +} diff --git a/tests/ui/lint/lint-type-limits2.stderr b/tests/ui/lint/lint-type-limits2.stderr new file mode 100644 index 000000000..b3420ad8a --- /dev/null +++ b/tests/ui/lint/lint-type-limits2.stderr @@ -0,0 +1,24 @@ +error: comparison is useless due to type limits + --> $DIR/lint-type-limits2.rs:13:5 + | +LL | 128 > bar() + | ^^^^^^^^^^^ + | + = note: requested on the command line with `-D unused-comparisons` + +warning: literal out of range for `i8` + --> $DIR/lint-type-limits2.rs:13:5 + | +LL | 128 > bar() + | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/lint-type-limits2.rs:2:9 + | +LL | #![warn(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-type-limits3.rs b/tests/ui/lint/lint-type-limits3.rs new file mode 100644 index 000000000..ceecf9ab3 --- /dev/null +++ b/tests/ui/lint/lint-type-limits3.rs @@ -0,0 +1,13 @@ +#![allow(dead_code)] +#![warn(overflowing_literals)] + +// compile-flags: -D unused-comparisons +fn main() { } + +fn qux() { + let mut i = 1i8; + while 200 != i { //~ ERROR comparison is useless due to type limits + //~| WARN literal out of range for `i8` + i += 1; + } +} diff --git a/tests/ui/lint/lint-type-limits3.stderr b/tests/ui/lint/lint-type-limits3.stderr new file mode 100644 index 000000000..db46e7ae7 --- /dev/null +++ b/tests/ui/lint/lint-type-limits3.stderr @@ -0,0 +1,24 @@ +error: comparison is useless due to type limits + --> $DIR/lint-type-limits3.rs:9:11 + | +LL | while 200 != i { + | ^^^^^^^^ + | + = note: requested on the command line with `-D unused-comparisons` + +warning: literal out of range for `i8` + --> $DIR/lint-type-limits3.rs:9:11 + | +LL | while 200 != i { + | ^^^ + | + = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/lint-type-limits3.rs:2:9 + | +LL | #![warn(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/lint-type-overflow.rs b/tests/ui/lint/lint-type-overflow.rs new file mode 100644 index 000000000..9672da6d3 --- /dev/null +++ b/tests/ui/lint/lint-type-overflow.rs @@ -0,0 +1,45 @@ +#![deny(overflowing_literals)] + +fn test(x: i8) { + println!("x {}", x); +} + +#[allow(unused_variables)] +fn main() { + let x1: u8 = 255; // should be OK + let x1: u8 = 256; //~ error: literal out of range for `u8` + + let x1 = 255_u8; // should be OK + let x1 = 256_u8; //~ error: literal out of range for `u8` + + let x2: i8 = -128; // should be OK + let x1: i8 = 128; //~ error: literal out of range for `i8` + + let x3: i8 = -129; //~ error: literal out of range for `i8` + let x3: i8 = -(129); //~ error: literal out of range for `i8` + let x3: i8 = -{129}; //~ error: literal out of range for `i8` + + test(1000); //~ error: literal out of range for `i8` + + let x = 128_i8; //~ error: literal out of range for `i8` + let x = 127_i8; + let x = -128_i8; + let x = -(128_i8); + let x = -129_i8; //~ error: literal out of range for `i8` + + let x: i32 = 2147483647; // should be OK + let x = 2147483647_i32; // should be OK + let x: i32 = 2147483648; //~ error: literal out of range for `i32` + let x = 2147483648_i32; //~ error: literal out of range for `i32` + let x: i32 = -2147483648; // should be OK + let x = -2147483648_i32; // should be OK + let x: i32 = -2147483649; //~ error: literal out of range for `i32` + let x = -2147483649_i32; //~ error: literal out of range for `i32` + let x = 2147483648; //~ error: literal out of range for `i32` + + let x = 9223372036854775808_i64; //~ error: literal out of range for `i64` + let x = -9223372036854775808_i64; // should be OK + let x = 18446744073709551615_i64; //~ error: literal out of range for `i64` + let x: i64 = -9223372036854775809; //~ error: literal out of range for `i64` + let x = -9223372036854775809_i64; //~ error: literal out of range for `i64` +} diff --git a/tests/ui/lint/lint-type-overflow.stderr b/tests/ui/lint/lint-type-overflow.stderr new file mode 100644 index 000000000..48d8228b8 --- /dev/null +++ b/tests/ui/lint/lint-type-overflow.stderr @@ -0,0 +1,167 @@ +error: literal out of range for `u8` + --> $DIR/lint-type-overflow.rs:10:18 + | +LL | let x1: u8 = 256; + | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` +note: the lint level is defined here + --> $DIR/lint-type-overflow.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-type-overflow.rs:13:14 + | +LL | let x1 = 256_u8; + | ^^^^^^ + | + = note: the literal `256_u8` does not fit into the type `u8` whose range is `0..=255` + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:16:18 + | +LL | let x1: i8 = 128; + | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:18:19 + | +LL | let x3: i8 = -129; + | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:19:19 + | +LL | let x3: i8 = -(129); + | ^^^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:20:20 + | +LL | let x3: i8 = -{129}; + | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:22:10 + | +LL | test(1000); + | ^^^^ + | + = note: the literal `1000` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:24:13 + | +LL | let x = 128_i8; + | ^^^^^^ + | + = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead + +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:28:14 + | +LL | let x = -129_i8; + | ^^^^^^ + | + = note: the literal `129_i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `i16` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:32:18 + | +LL | let x: i32 = 2147483648; + | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:33:13 + | +LL | let x = 2147483648_i32; + | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483648_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:36:19 + | +LL | let x: i32 = -2147483649; + | ^^^^^^^^^^ + | + = note: the literal `2147483649` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `i64` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:37:14 + | +LL | let x = -2147483649_i32; + | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483649_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `i64` instead + +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:38:13 + | +LL | let x = 2147483648; + | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` + = help: consider using the type `u32` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:40:13 + | +LL | let x = 9223372036854775808_i64; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775808_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `u64` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:42:13 + | +LL | let x = 18446744073709551615_i64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `18446744073709551615_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `u64` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:43:19 + | +LL | let x: i64 = -9223372036854775809; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `i128` instead + +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:44:14 + | +LL | let x = -9223372036854775809_i64; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` + = help: consider using the type `i128` instead + +error: aborting due to 18 previous errors + diff --git a/tests/ui/lint/lint-type-overflow2.rs b/tests/ui/lint/lint-type-overflow2.rs new file mode 100644 index 000000000..9b1eb510b --- /dev/null +++ b/tests/ui/lint/lint-type-overflow2.rs @@ -0,0 +1,12 @@ +// compile-flags: -O + +#![deny(overflowing_literals)] + +fn main() { + let x2: i8 = --128; //~ ERROR literal out of range for `i8` + + let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32` + let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32` + let x = -1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64` + let x = 1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64` +} diff --git a/tests/ui/lint/lint-type-overflow2.stderr b/tests/ui/lint/lint-type-overflow2.stderr new file mode 100644 index 000000000..eb593d062 --- /dev/null +++ b/tests/ui/lint/lint-type-overflow2.stderr @@ -0,0 +1,48 @@ +error: literal out of range for `i8` + --> $DIR/lint-type-overflow2.rs:6:20 + | +LL | let x2: i8 = --128; + | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/lint-type-overflow2.rs:3:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `f32` + --> $DIR/lint-type-overflow2.rs:8:14 + | +LL | let x = -3.40282357e+38_f32; + | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY` + +error: literal out of range for `f32` + --> $DIR/lint-type-overflow2.rs:9:14 + | +LL | let x = 3.40282357e+38_f32; + | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY` + +error: literal out of range for `f64` + --> $DIR/lint-type-overflow2.rs:10:14 + | +LL | let x = -1.7976931348623159e+308_f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY` + +error: literal out of range for `f64` + --> $DIR/lint-type-overflow2.rs:11:14 + | +LL | let x = 1.7976931348623159e+308_f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/lint-unconditional-recursion.rs b/tests/ui/lint/lint-unconditional-recursion.rs new file mode 100644 index 000000000..ad052d36f --- /dev/null +++ b/tests/ui/lint/lint-unconditional-recursion.rs @@ -0,0 +1,194 @@ +#![deny(unconditional_recursion)] + +#![allow(dead_code)] +fn foo() { //~ ERROR function cannot return without recursing + foo(); +} + +fn bar() { + if true { + bar() + } +} + +fn baz() { //~ ERROR function cannot return without recursing + if true { + baz() + } else { + baz() + } +} + +fn qux() { + loop {} +} + +fn quz() -> bool { //~ ERROR function cannot return without recursing + if true { + while quz() {} + true + } else { + loop { quz(); } + } +} + +// Trait method calls. +trait Foo { + fn bar(&self) { //~ ERROR function cannot return without recursing + self.bar() + } +} + +impl Foo for Box { + fn bar(&self) { //~ ERROR function cannot return without recursing + loop { + self.bar() + } + } +} + +// Trait method call with integer fallback after method resolution. +impl Foo for i32 { + fn bar(&self) { //~ ERROR function cannot return without recursing + 0.bar() + } +} + +impl Foo for u32 { + fn bar(&self) { + 0.bar() + } +} + +// Trait method calls via paths. +trait Foo2 { + fn bar(&self) { //~ ERROR function cannot return without recursing + Foo2::bar(self) + } +} + +impl Foo2 for Box { + fn bar(&self) { //~ ERROR function cannot return without recursing + loop { + Foo2::bar(self) + } + } +} + +struct Baz; +impl Baz { + // Inherent method call. + fn qux(&self) { //~ ERROR function cannot return without recursing + self.qux(); + } + + // Inherent method call via path. + fn as_ref(&self) -> &Self { //~ ERROR function cannot return without recursing + Baz::as_ref(self) + } +} + +// Trait method calls to impls via paths. +impl Default for Baz { + fn default() -> Baz { //~ ERROR function cannot return without recursing + let x = Default::default(); + x + } +} + +// Overloaded operators. +impl std::ops::Deref for Baz { + type Target = (); + fn deref(&self) -> &() { //~ ERROR function cannot return without recursing + &**self + } +} + +impl std::ops::Index for Baz { + type Output = Baz; + fn index(&self, x: usize) -> &Baz { //~ ERROR function cannot return without recursing + &self[x] + } +} + +// Overloaded autoderef. +struct Quux; +impl std::ops::Deref for Quux { + type Target = Baz; + fn deref(&self) -> &Baz { //~ ERROR function cannot return without recursing + self.as_ref() + } +} + +fn all_fine() { + let _f = all_fine; +} + +// issue 26333 +trait Bar { + fn method(&self, x: &T) { + x.method(x) + } +} + +// Do not trigger on functions that may diverge instead of self-recursing (#54444) + +pub fn loops(x: bool) { + if x { + loops(x); + } else { + loop {} + } +} + +pub fn panics(x: bool) { + if x { + panics(!x); + } else { + panic!("panics"); + } +} + +pub fn unreachable1() { + panic!(); + unreachable1(); // WARN unreachable statement +} + +pub fn unreachable2() { + loop {} + unreachable2(); // WARN unreachable statement +} + +pub fn drop_and_replace(mut a: Option) { //~ ERROR function cannot return without recursing + a = None; + drop_and_replace(a); +} + +// Calls are assumed to return normally. +pub fn call() -> String { //~ ERROR function cannot return without recursing + let s = String::new(); + call(); + s +} + +// Arithmetic operations are assumed not to overflow. +pub fn overflow_check(a: i32, b: i32) { //~ ERROR function cannot return without recursing + let _ = a + b; + overflow_check(a, b); +} + +pub struct Point { + pub x: f32, + pub y: f32, +} + +impl Default for Point { + fn default() -> Self { //~ ERROR function cannot return without recursing + Point { + x: Default::default(), + ..Default::default() + } + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-unconditional-recursion.stderr b/tests/ui/lint/lint-unconditional-recursion.stderr new file mode 100644 index 000000000..9d200a789 --- /dev/null +++ b/tests/ui/lint/lint-unconditional-recursion.stderr @@ -0,0 +1,201 @@ +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:4:1 + | +LL | fn foo() { + | ^^^^^^^^ cannot return without recursing +LL | foo(); + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose +note: the lint level is defined here + --> $DIR/lint-unconditional-recursion.rs:1:9 + | +LL | #![deny(unconditional_recursion)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:14:1 + | +LL | fn baz() { + | ^^^^^^^^ cannot return without recursing +LL | if true { +LL | baz() + | ----- recursive call site +LL | } else { +LL | baz() + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:26:1 + | +LL | fn quz() -> bool { + | ^^^^^^^^^^^^^^^^ cannot return without recursing +LL | if true { +LL | while quz() {} + | ----- recursive call site +... +LL | loop { quz(); } + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:37:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | self.bar() + | ---------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:43:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | loop { +LL | self.bar() + | ---------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:52:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | 0.bar() + | ------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:65:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | Foo2::bar(self) + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:71:5 + | +LL | fn bar(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | loop { +LL | Foo2::bar(self) + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:81:5 + | +LL | fn qux(&self) { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | self.qux(); + | ---------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:86:5 + | +LL | fn as_ref(&self) -> &Self { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | Baz::as_ref(self) + | ----------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:93:5 + | +LL | fn default() -> Baz { + | ^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let x = Default::default(); + | ------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:102:5 + | +LL | fn deref(&self) -> &() { + | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | &**self + | ------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:109:5 + | +LL | fn index(&self, x: usize) -> &Baz { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | &self[x] + | ------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:118:5 + | +LL | fn deref(&self) -> &Baz { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | self.as_ref() + | ------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:162:1 + | +LL | pub fn drop_and_replace(mut a: Option) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | a = None; +LL | drop_and_replace(a); + | ------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:168:1 + | +LL | pub fn call() -> String { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let s = String::new(); +LL | call(); + | ------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:175:1 + | +LL | pub fn overflow_check(a: i32, b: i32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let _ = a + b; +LL | overflow_check(a, b); + | -------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:186:5 + | +LL | fn default() -> Self { + | ^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | ..Default::default() + | ------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 18 previous errors + diff --git a/tests/ui/lint/lint-unexported-no-mangle.rs b/tests/ui/lint/lint-unexported-no-mangle.rs new file mode 100644 index 000000000..f260fc323 --- /dev/null +++ b/tests/ui/lint/lint-unexported-no-mangle.rs @@ -0,0 +1,29 @@ +// compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics + +#[no_mangle] +fn foo() { +} + +#[allow(dead_code)] +#[no_mangle] +const FOO: u64 = 1; //~ ERROR const items should never be `#[no_mangle]` + +#[no_mangle] +pub const PUB_FOO: u64 = 1; //~ ERROR const items should never be `#[no_mangle]` + +#[no_mangle] +pub fn bar() { +} + +#[no_mangle] +pub static BAR: u64 = 1; + +#[allow(dead_code)] +#[no_mangle] +static PRIVATE_BAR: u64 = 1; + + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr new file mode 100644 index 000000000..a11ee769c --- /dev/null +++ b/tests/ui/lint/lint-unexported-no-mangle.stderr @@ -0,0 +1,44 @@ +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + +warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported + | + = note: requested on the command line with `-F private_no_mangle_fns` + +warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported + | + = note: requested on the command line with `-F private_no_mangle_statics` + +error: const items should never be `#[no_mangle]` + --> $DIR/lint-unexported-no-mangle.rs:9:1 + | +LL | const FOO: u64 = 1; + | -----^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | + = note: requested on the command line with `-F no-mangle-const-items` + +error: const items should never be `#[no_mangle]` + --> $DIR/lint-unexported-no-mangle.rs:12:1 + | +LL | pub const PUB_FOO: u64 = 1; + | ---------^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + +error: aborting due to 2 previous errors; 6 warnings emitted + diff --git a/tests/ui/lint/lint-unknown-feature-default.rs b/tests/ui/lint/lint-unknown-feature-default.rs new file mode 100644 index 000000000..84a2e5a4b --- /dev/null +++ b/tests/ui/lint/lint-unknown-feature-default.rs @@ -0,0 +1,9 @@ +// check-pass + +// Tests the default for the unused_features lint + +#![allow(stable_features)] +// FIXME(#44232) we should warn that this isn't used. +#![feature(rust1)] + +fn main() {} diff --git a/tests/ui/lint/lint-unknown-feature.rs b/tests/ui/lint/lint-unknown-feature.rs new file mode 100644 index 000000000..1af8d4ff8 --- /dev/null +++ b/tests/ui/lint/lint-unknown-feature.rs @@ -0,0 +1,9 @@ +// check-pass + +#![warn(unused_features)] + +#![allow(stable_features)] +// FIXME(#44232) we should warn that this isn't used. +#![feature(rust1)] + +fn main() {} diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs new file mode 100644 index 000000000..7f3f55fba --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint-cmdline.rs @@ -0,0 +1,9 @@ +// compile-flags:-D bogus -D dead_cod + +// error-pattern:unknown lint: `bogus` +// error-pattern:requested on the command line with `-D bogus` +// error-pattern:unknown lint: `dead_cod` +// error-pattern:requested on the command line with `-D dead_cod` +// error-pattern:did you mean: `dead_code` + +fn main() { } diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr new file mode 100644 index 000000000..3855d5527 --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr @@ -0,0 +1,21 @@ +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error[E0602]: unknown lint: `bogus` + | + = note: requested on the command line with `-D bogus` + +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint.rs b/tests/ui/lint/lint-unknown-lint.rs new file mode 100644 index 000000000..2d842d514 --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint.rs @@ -0,0 +1,13 @@ +#![deny(unknown_lints)] + +#![allow(not_a_real_lint)] //~ ERROR unknown lint + +#![deny(dead_cod)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION dead_code + +#![deny(rust_2018_idiots)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION rust_2018_idioms + +fn main() {} diff --git a/tests/ui/lint/lint-unknown-lint.stderr b/tests/ui/lint/lint-unknown-lint.stderr new file mode 100644 index 000000000..0cb6b4957 --- /dev/null +++ b/tests/ui/lint/lint-unknown-lint.stderr @@ -0,0 +1,26 @@ +error: unknown lint: `not_a_real_lint` + --> $DIR/lint-unknown-lint.rs:3:10 + | +LL | #![allow(not_a_real_lint)] + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unknown-lint.rs:1:9 + | +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ + +error: unknown lint: `dead_cod` + --> $DIR/lint-unknown-lint.rs:5:9 + | +LL | #![deny(dead_cod)] + | ^^^^^^^^ help: did you mean: `dead_code` + +error: unknown lint: `rust_2018_idiots` + --> $DIR/lint-unknown-lint.rs:9:9 + | +LL | #![deny(rust_2018_idiots)] + | ^^^^^^^^^^^^^^^^ help: did you mean: `rust_2018_idioms` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/lint-unnecessary-import-braces.rs b/tests/ui/lint/lint-unnecessary-import-braces.rs new file mode 100644 index 000000000..9a3398a87 --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-import-braces.rs @@ -0,0 +1,11 @@ +#![deny(unused_import_braces)] + +use test::{A}; //~ ERROR braces around A is unnecessary + +mod test { + use test::{self}; // OK + use test::{self as rename}; // OK + pub struct A; +} + +fn main() {} diff --git a/tests/ui/lint/lint-unnecessary-import-braces.stderr b/tests/ui/lint/lint-unnecessary-import-braces.stderr new file mode 100644 index 000000000..2d289404d --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-import-braces.stderr @@ -0,0 +1,14 @@ +error: braces around A is unnecessary + --> $DIR/lint-unnecessary-import-braces.rs:3:1 + | +LL | use test::{A}; + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unnecessary-import-braces.rs:1:9 + | +LL | #![deny(unused_import_braces)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed new file mode 100644 index 000000000..9c144324f --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-parens.fixed @@ -0,0 +1,81 @@ +// run-rustfix + +#![deny(unused_parens)] +#![allow(while_true)] // for rustfix + +#[derive(Eq, PartialEq)] +struct X { y: bool } +impl X { + fn foo(&self, conjunct: bool) -> bool { self.y && conjunct } +} + +fn foo() -> isize { + return 1; //~ ERROR unnecessary parentheses around `return` value +} +fn bar(y: bool) -> X { + return X { y }; //~ ERROR unnecessary parentheses around `return` value +} + +pub fn unused_parens_around_return_type() -> u32 { //~ ERROR unnecessary parentheses around type + panic!() +} + +pub fn unused_parens_around_block_return() -> u32 { + let _foo = { + 5 //~ ERROR unnecessary parentheses around block return value + }; + 5 //~ ERROR unnecessary parentheses around block return value +} + +pub trait Trait { + fn test(&self); +} + +pub fn passes_unused_parens_lint() -> &'static (dyn Trait) { + panic!() +} + +macro_rules! baz { + ($($foo:expr),+) => { + ($($foo),*) + } +} + +pub const CONST_ITEM: usize = 10; //~ ERROR unnecessary parentheses around assigned value +pub static STATIC_ITEM: usize = 10; //~ ERROR unnecessary parentheses around assigned value + +fn main() { + foo(); + bar(true); //~ ERROR unnecessary parentheses around function argument + + if true {} //~ ERROR unnecessary parentheses around `if` condition + while true {} //~ ERROR unnecessary parentheses around `while` condition + match true { //~ ERROR unnecessary parentheses around `match` scrutinee expression + _ => {} + } + if let 1 = 1 {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + while let 1 = 2 {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + let v = X { y: false }; + // struct lits needs parens, so these shouldn't warn. + if (v == X { y: true }) {} + if (X { y: true } == v) {} + if (X { y: false }.y) {} + // this shouldn't warn, because the parens are necessary to disambiguate let chains + if let true = (true && false) {} + + while (X { y: false }.foo(true)) {} + while (true | X { y: false }.y) {} + + match (X { y: false }) { + _ => {} + } + + X { y: false }.foo(true); //~ ERROR unnecessary parentheses around method argument + + let mut _a = 0; //~ ERROR unnecessary parentheses around assigned value + _a = 0; //~ ERROR unnecessary parentheses around assigned value + _a += 1; //~ ERROR unnecessary parentheses around assigned value + + let _a = baz!(3, 4); + let _b = baz!(3); +} diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs new file mode 100644 index 000000000..4fd9cabb3 --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-parens.rs @@ -0,0 +1,81 @@ +// run-rustfix + +#![deny(unused_parens)] +#![allow(while_true)] // for rustfix + +#[derive(Eq, PartialEq)] +struct X { y: bool } +impl X { + fn foo(&self, conjunct: bool) -> bool { self.y && conjunct } +} + +fn foo() -> isize { + return (1); //~ ERROR unnecessary parentheses around `return` value +} +fn bar(y: bool) -> X { + return (X { y }); //~ ERROR unnecessary parentheses around `return` value +} + +pub fn unused_parens_around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type + panic!() +} + +pub fn unused_parens_around_block_return() -> u32 { + let _foo = { + (5) //~ ERROR unnecessary parentheses around block return value + }; + (5) //~ ERROR unnecessary parentheses around block return value +} + +pub trait Trait { + fn test(&self); +} + +pub fn passes_unused_parens_lint() -> &'static (dyn Trait) { + panic!() +} + +macro_rules! baz { + ($($foo:expr),+) => { + ($($foo),*) + } +} + +pub const CONST_ITEM: usize = (10); //~ ERROR unnecessary parentheses around assigned value +pub static STATIC_ITEM: usize = (10); //~ ERROR unnecessary parentheses around assigned value + +fn main() { + foo(); + bar((true)); //~ ERROR unnecessary parentheses around function argument + + if (true) {} //~ ERROR unnecessary parentheses around `if` condition + while (true) {} //~ ERROR unnecessary parentheses around `while` condition + match (true) { //~ ERROR unnecessary parentheses around `match` scrutinee expression + _ => {} + } + if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + let v = X { y: false }; + // struct lits needs parens, so these shouldn't warn. + if (v == X { y: true }) {} + if (X { y: true } == v) {} + if (X { y: false }.y) {} + // this shouldn't warn, because the parens are necessary to disambiguate let chains + if let true = (true && false) {} + + while (X { y: false }.foo(true)) {} + while (true | X { y: false }.y) {} + + match (X { y: false }) { + _ => {} + } + + X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument + + let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value + _a = (0); //~ ERROR unnecessary parentheses around assigned value + _a += (1); //~ ERROR unnecessary parentheses around assigned value + + let _a = baz!(3, 4); + let _b = baz!(3); +} diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr new file mode 100644 index 000000000..e13620f06 --- /dev/null +++ b/tests/ui/lint/lint-unnecessary-parens.stderr @@ -0,0 +1,211 @@ +error: unnecessary parentheses around `return` value + --> $DIR/lint-unnecessary-parens.rs:13:12 + | +LL | return (1); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-unnecessary-parens.rs:3:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (1); +LL + return 1; + | + +error: unnecessary parentheses around `return` value + --> $DIR/lint-unnecessary-parens.rs:16:12 + | +LL | return (X { y }); + | ^ ^ + | +help: remove these parentheses + | +LL - return (X { y }); +LL + return X { y }; + | + +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:19:46 + | +LL | pub fn unused_parens_around_return_type() -> (u32) { + | ^ ^ + | +help: remove these parentheses + | +LL - pub fn unused_parens_around_return_type() -> (u32) { +LL + pub fn unused_parens_around_return_type() -> u32 { + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-unnecessary-parens.rs:25:9 + | +LL | (5) + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-unnecessary-parens.rs:27:5 + | +LL | (5) + | ^ ^ + | +help: remove these parentheses + | +LL - (5) +LL + 5 + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:44:31 + | +LL | pub const CONST_ITEM: usize = (10); + | ^ ^ + | +help: remove these parentheses + | +LL - pub const CONST_ITEM: usize = (10); +LL + pub const CONST_ITEM: usize = 10; + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:45:33 + | +LL | pub static STATIC_ITEM: usize = (10); + | ^ ^ + | +help: remove these parentheses + | +LL - pub static STATIC_ITEM: usize = (10); +LL + pub static STATIC_ITEM: usize = 10; + | + +error: unnecessary parentheses around function argument + --> $DIR/lint-unnecessary-parens.rs:49:9 + | +LL | bar((true)); + | ^ ^ + | +help: remove these parentheses + | +LL - bar((true)); +LL + bar(true); + | + +error: unnecessary parentheses around `if` condition + --> $DIR/lint-unnecessary-parens.rs:51:8 + | +LL | if (true) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if (true) {} +LL + if true {} + | + +error: unnecessary parentheses around `while` condition + --> $DIR/lint-unnecessary-parens.rs:52:11 + | +LL | while (true) {} + | ^ ^ + | +help: remove these parentheses + | +LL - while (true) {} +LL + while true {} + | + +error: unnecessary parentheses around `match` scrutinee expression + --> $DIR/lint-unnecessary-parens.rs:53:11 + | +LL | match (true) { + | ^ ^ + | +help: remove these parentheses + | +LL - match (true) { +LL + match true { + | + +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/lint-unnecessary-parens.rs:56:16 + | +LL | if let 1 = (1) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let 1 = (1) {} +LL + if let 1 = 1 {} + | + +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/lint-unnecessary-parens.rs:57:19 + | +LL | while let 1 = (2) {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let 1 = (2) {} +LL + while let 1 = 2 {} + | + +error: unnecessary parentheses around method argument + --> $DIR/lint-unnecessary-parens.rs:73:24 + | +LL | X { y: false }.foo((true)); + | ^ ^ + | +help: remove these parentheses + | +LL - X { y: false }.foo((true)); +LL + X { y: false }.foo(true); + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:75:18 + | +LL | let mut _a = (0); + | ^ ^ + | +help: remove these parentheses + | +LL - let mut _a = (0); +LL + let mut _a = 0; + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:76:10 + | +LL | _a = (0); + | ^ ^ + | +help: remove these parentheses + | +LL - _a = (0); +LL + _a = 0; + | + +error: unnecessary parentheses around assigned value + --> $DIR/lint-unnecessary-parens.rs:77:11 + | +LL | _a += (1); + | ^ ^ + | +help: remove these parentheses + | +LL - _a += (1); +LL + _a += 1; + | + +error: aborting due to 17 previous errors + diff --git a/tests/ui/lint/lint-unsafe-code.rs b/tests/ui/lint/lint-unsafe-code.rs new file mode 100644 index 000000000..b72e4c3a9 --- /dev/null +++ b/tests/ui/lint/lint-unsafe-code.rs @@ -0,0 +1,130 @@ +#![allow(unused_unsafe)] +#![allow(dead_code)] +#![deny(unsafe_code)] + +struct Bar; +struct Bar2; +struct Bar3; + +#[allow(unsafe_code)] +mod allowed_unsafe { + fn allowed() { unsafe {} } + unsafe fn also_allowed() {} + unsafe trait AllowedUnsafe { } + unsafe impl AllowedUnsafe for super::Bar {} + #[no_mangle] fn allowed2() {} + #[export_name = "foo"] fn allowed3() {} +} + +macro_rules! unsafe_in_macro { + () => {{ + #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function + #[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static + #[export_name = "bar"] fn bar() {} + //~^ ERROR: declaration of a function with `export_name` + #[export_name = "BAR"] static BAR: u32 = 5; + //~^ ERROR: declaration of a static with `export_name` + unsafe {} //~ ERROR: usage of an `unsafe` block + }} +} + +#[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function +#[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static + +trait AssocFnTrait { + fn foo(); +} + +struct AssocFnFoo; + +impl AssocFnFoo { + #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` method +} + +impl AssocFnTrait for AssocFnFoo { + #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` method +} + +#[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a function with `export_name` +#[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: declaration of a static with `export_name` + +#[link_section = ".example_section"] fn uwu() {} //~ ERROR: declaration of a function with `link_section` +#[link_section = ".example_section"] static UWU: u32 = 5; //~ ERROR: declaration of a static with `link_section` + +struct AssocFnBar; + +impl AssocFnBar { + #[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a method with `export_name` +} + +impl AssocFnTrait for AssocFnBar { + #[export_name = "bar"] fn foo() {} //~ ERROR: declaration of a method with `export_name` +} + +unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function +unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait +unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait + +trait Baz { + unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl Baz for Bar { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + + +#[allow(unsafe_code)] +trait A { + unsafe fn allowed_unsafe(&self); + unsafe fn allowed_unsafe_provided(&self) {} +} + +#[allow(unsafe_code)] +impl Baz for Bar2 { + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} +} + +impl Baz for Bar3 { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +#[allow(unsafe_code)] +unsafe trait B { + fn dummy(&self) {} +} + +trait C { + #[allow(unsafe_code)] + unsafe fn baz(&self); + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar { + #[allow(unsafe_code)] + unsafe fn baz(&self) {} + unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +impl C for Bar2 { + unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method +} + +trait D { + #[allow(unsafe_code)] + unsafe fn unsafe_provided(&self) {} +} + +impl D for Bar {} + +fn main() { + unsafe {} //~ ERROR: usage of an `unsafe` block + + unsafe_in_macro!() +} diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr new file mode 100644 index 000000000..037f0a832 --- /dev/null +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -0,0 +1,224 @@ +error: declaration of a `no_mangle` function + --> $DIR/lint-unsafe-code.rs:31:1 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them +note: the lint level is defined here + --> $DIR/lint-unsafe-code.rs:3:9 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: declaration of a `no_mangle` static + --> $DIR/lint-unsafe-code.rs:32:1 + | +LL | #[no_mangle] static FOO: u32 = 5; + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a `no_mangle` method + --> $DIR/lint-unsafe-code.rs:41:5 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a `no_mangle` method + --> $DIR/lint-unsafe-code.rs:45:5 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a function with `export_name` + --> $DIR/lint-unsafe-code.rs:48:1 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a static with `export_name` + --> $DIR/lint-unsafe-code.rs:49:1 + | +LL | #[export_name = "BAR"] static BAR: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a function with `link_section` + --> $DIR/lint-unsafe-code.rs:51:1 + | +LL | #[link_section = ".example_section"] fn uwu() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +error: declaration of a static with `link_section` + --> $DIR/lint-unsafe-code.rs:52:1 + | +LL | #[link_section = ".example_section"] static UWU: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them + +error: declaration of a method with `export_name` + --> $DIR/lint-unsafe-code.rs:57:5 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of a method with `export_name` + --> $DIR/lint-unsafe-code.rs:61:5 + | +LL | #[export_name = "bar"] fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + +error: declaration of an `unsafe` function + --> $DIR/lint-unsafe-code.rs:64:1 + | +LL | unsafe fn baz() {} + | ^^^^^^^^^^^^^^^^^^ + +error: declaration of an `unsafe` trait + --> $DIR/lint-unsafe-code.rs:65:1 + | +LL | unsafe trait Foo {} + | ^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` trait + --> $DIR/lint-unsafe-code.rs:66:1 + | +LL | unsafe impl Foo for Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: declaration of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:69:5 + | +LL | unsafe fn baz(&self); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:70:5 + | +LL | unsafe fn provided(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:71:5 + | +LL | unsafe fn provided_override(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:75:5 + | +LL | unsafe fn baz(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:76:5 + | +LL | unsafe fn provided_override(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:95:5 + | +LL | unsafe fn provided_override(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:106:5 + | +LL | unsafe fn provided(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:112:5 + | +LL | unsafe fn provided(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of an `unsafe` method + --> $DIR/lint-unsafe-code.rs:116:5 + | +LL | unsafe fn baz(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-unsafe-code.rs:127:5 + | +LL | unsafe {} + | ^^^^^^^^^ + +error: declaration of a `no_mangle` function + --> $DIR/lint-unsafe-code.rs:21:9 + | +LL | #[no_mangle] fn foo() {} + | ^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: declaration of a `no_mangle` static + --> $DIR/lint-unsafe-code.rs:22:9 + | +LL | #[no_mangle] static FOO: u32 = 5; + | ^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: declaration of a function with `export_name` + --> $DIR/lint-unsafe-code.rs:23:9 + | +LL | #[export_name = "bar"] fn bar() {} + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: declaration of a static with `export_name` + --> $DIR/lint-unsafe-code.rs:25:9 + | +LL | #[export_name = "BAR"] static BAR: u32 = 5; + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: usage of an `unsafe` block + --> $DIR/lint-unsafe-code.rs:27:9 + | +LL | unsafe {} + | ^^^^^^^^^ +... +LL | unsafe_in_macro!() + | ------------------ in this macro invocation + | + = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 28 previous errors + diff --git a/tests/ui/lint/lint-uppercase-variables.rs b/tests/ui/lint/lint-uppercase-variables.rs new file mode 100644 index 000000000..59dba536f --- /dev/null +++ b/tests/ui/lint/lint-uppercase-variables.rs @@ -0,0 +1,41 @@ +#![warn(unused)] +#![allow(dead_code)] +#![deny(non_snake_case)] + +mod foo { + pub enum Foo { Foo } +} + +struct Something { + X: usize //~ ERROR structure field `X` should have a snake case name +} + +fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name + println!("{}", Xx); +} + +fn main() { + let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name + println!("{}", Test); + + match foo::Foo::Foo { + Foo => {} + //~^ ERROR variable `Foo` should have a snake case name + //~^^ ERROR `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` + } + + let Foo = foo::Foo::Foo; + //~^ ERROR variable `Foo` should have a snake case name + //~^^ ERROR `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` + + fn in_param(Foo: foo::Foo) {} + //~^ ERROR variable `Foo` should have a snake case name + //~^^ ERROR `Foo` is named the same as one of the variants of the type `foo::Foo` + //~^^^ WARN unused variable: `Foo` + + test(1); + + let _ = Something { X: 0 }; +} diff --git a/tests/ui/lint/lint-uppercase-variables.stderr b/tests/ui/lint/lint-uppercase-variables.stderr new file mode 100644 index 000000000..42ec9364b --- /dev/null +++ b/tests/ui/lint/lint-uppercase-variables.stderr @@ -0,0 +1,90 @@ +error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:28:9 + | +LL | let Foo = foo::Foo::Foo; + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + +error[E0170]: pattern binding `Foo` is named the same as one of the variants of the type `foo::Foo` + --> $DIR/lint-uppercase-variables.rs:33:17 + | +LL | fn in_param(Foo: foo::Foo) {} + | ^^^ help: to match on the variant, qualify the path: `foo::Foo::Foo` + +warning: unused variable: `Foo` + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` + | +note: the lint level is defined here + --> $DIR/lint-uppercase-variables.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `Foo` + --> $DIR/lint-uppercase-variables.rs:28:9 + | +LL | let Foo = foo::Foo::Foo; + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` + +warning: unused variable: `Foo` + --> $DIR/lint-uppercase-variables.rs:33:17 + | +LL | fn in_param(Foo: foo::Foo) {} + | ^^^ help: if this is intentional, prefix it with an underscore: `_Foo` + +error: structure field `X` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:10:5 + | +LL | X: usize + | ^ help: convert the identifier to snake case (notice the capitalization): `x` + | +note: the lint level is defined here + --> $DIR/lint-uppercase-variables.rs:3:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: variable `Xx` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:13:9 + | +LL | fn test(Xx: usize) { + | ^^ help: convert the identifier to snake case (notice the capitalization): `xx` + +error: variable `Test` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:18:9 + | +LL | let Test: usize = 0; + | ^^^^ help: convert the identifier to snake case: `test` + +error: variable `Foo` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:22:9 + | +LL | Foo => {} + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + +error: variable `Foo` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:28:9 + | +LL | let Foo = foo::Foo::Foo; + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + +error: variable `Foo` should have a snake case name + --> $DIR/lint-uppercase-variables.rs:33:17 + | +LL | fn in_param(Foo: foo::Foo) {} + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` + +error: aborting due to 9 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs new file mode 100644 index 000000000..71dec40ea --- /dev/null +++ b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs @@ -0,0 +1,3 @@ +// ignore-test: not a test + +pub fn try() {} diff --git a/tests/ui/lint/lints-in-foreign-macros.rs b/tests/ui/lint/lints-in-foreign-macros.rs new file mode 100644 index 000000000..1e8b6788a --- /dev/null +++ b/tests/ui/lint/lints-in-foreign-macros.rs @@ -0,0 +1,21 @@ +// aux-build:lints-in-foreign-macros.rs +// check-pass + +#![warn(unused_imports)] //~ missing documentation for the crate [missing_docs] +#![warn(missing_docs)] + +#[macro_use] +extern crate lints_in_foreign_macros; + +macro_rules! foo { + () => {use std::string::ToString;} //~ WARN: unused import +} + +mod a { foo!(); } +mod b { bar!(); } +mod c { baz!(use std::string::ToString;); } //~ WARN: unused import +mod d { baz2!(use std::string::ToString;); } //~ WARN: unused import +baz!(pub fn undocumented() {}); //~ WARN: missing documentation for a function +baz2!(pub fn undocumented2() {}); //~ WARN: missing documentation for a function + +fn main() {} diff --git a/tests/ui/lint/lints-in-foreign-macros.stderr b/tests/ui/lint/lints-in-foreign-macros.stderr new file mode 100644 index 000000000..f20e16287 --- /dev/null +++ b/tests/ui/lint/lints-in-foreign-macros.stderr @@ -0,0 +1,60 @@ +warning: unused import: `std::string::ToString` + --> $DIR/lints-in-foreign-macros.rs:11:16 + | +LL | () => {use std::string::ToString;} + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | mod a { foo!(); } + | ------ in this macro invocation + | +note: the lint level is defined here + --> $DIR/lints-in-foreign-macros.rs:4:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unused import: `std::string::ToString` + --> $DIR/lints-in-foreign-macros.rs:16:18 + | +LL | mod c { baz!(use std::string::ToString;); } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: unused import: `std::string::ToString` + --> $DIR/lints-in-foreign-macros.rs:17:19 + | +LL | mod d { baz2!(use std::string::ToString;); } + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: missing documentation for the crate + --> $DIR/lints-in-foreign-macros.rs:4:1 + | +LL | / #![warn(unused_imports)] +LL | | #![warn(missing_docs)] +LL | | +LL | | #[macro_use] +... | +LL | | +LL | | fn main() {} + | |____________^ + | +note: the lint level is defined here + --> $DIR/lints-in-foreign-macros.rs:5:9 + | +LL | #![warn(missing_docs)] + | ^^^^^^^^^^^^ + +warning: missing documentation for a function + --> $DIR/lints-in-foreign-macros.rs:18:6 + | +LL | baz!(pub fn undocumented() {}); + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: missing documentation for a function + --> $DIR/lints-in-foreign-macros.rs:19:7 + | +LL | baz2!(pub fn undocumented2() {}); + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/missing-doc-private-macro.rs b/tests/ui/lint/missing-doc-private-macro.rs new file mode 100644 index 000000000..0d4332ed0 --- /dev/null +++ b/tests/ui/lint/missing-doc-private-macro.rs @@ -0,0 +1,43 @@ +// Checks that undocumented private macros will not generate `missing_docs` +// lints, but public ones will. +// +// This is a regression test for issue #57569 +#![deny(missing_docs)] +#![feature(decl_macro)] +//! Empty documentation. + +macro new_style_private_macro { + () => () +} + +pub(crate) macro new_style_crate_macro { + () => () +} + +macro_rules! old_style_private_macro { + () => () +} + +mod submodule { + pub macro new_style_macro_in_private_module { + () => () + } + + macro_rules! old_style_mod_private_macro { + () => () + } + + #[macro_export] + macro_rules! exported_to_top_level { + //~^ ERROR missing documentation for a macro + () => () + } +} + +pub macro top_level_pub_macro { + //~^ ERROR missing documentation for a macro + () => () +} + +/// Empty documentation. +pub fn main() {} diff --git a/tests/ui/lint/missing-doc-private-macro.stderr b/tests/ui/lint/missing-doc-private-macro.stderr new file mode 100644 index 000000000..979b007d0 --- /dev/null +++ b/tests/ui/lint/missing-doc-private-macro.stderr @@ -0,0 +1,20 @@ +error: missing documentation for a macro + --> $DIR/missing-doc-private-macro.rs:31:5 + | +LL | macro_rules! exported_to_top_level { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/missing-doc-private-macro.rs:5:9 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a macro + --> $DIR/missing-doc-private-macro.rs:37:1 + | +LL | pub macro top_level_pub_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/must_not_suspend/boxed.rs b/tests/ui/lint/must_not_suspend/boxed.rs new file mode 100644 index 000000000..1f823fc55 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/boxed.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + + +fn bar() -> Box { + Box::new(Umm { + i: 1 + }) +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ ERROR boxed `Umm` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/boxed.stderr b/tests/ui/lint/must_not_suspend/boxed.stderr new file mode 100644 index 000000000..9efc7b069 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/boxed.stderr @@ -0,0 +1,26 @@ +error: boxed `Umm` held across a suspend point, but should not be + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/boxed.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/boxed.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/dedup.rs b/tests/ui/lint/must_not_suspend/dedup.rs new file mode 100644 index 000000000..81a08579b --- /dev/null +++ b/tests/ui/lint/must_not_suspend/dedup.rs @@ -0,0 +1,20 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +struct No {} + +async fn shushspend() {} + +async fn wheeee(t: T) { + shushspend().await; + drop(t); +} + +async fn yes() { + wheeee(&No {}).await; //~ ERROR `No` held across +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/dedup.stderr b/tests/ui/lint/must_not_suspend/dedup.stderr new file mode 100644 index 000000000..f8978ba57 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/dedup.stderr @@ -0,0 +1,19 @@ +error: `No` held across a suspend point, but should not be + --> $DIR/dedup.rs:16:13 + | +LL | wheeee(&No {}).await; + | ^^^^^ ------ the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/dedup.rs:16:13 + | +LL | wheeee(&No {}).await; + | ^^^^^ +note: the lint level is defined here + --> $DIR/dedup.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs new file mode 100644 index 000000000..1554408c1 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.rs @@ -0,0 +1,9 @@ +// edition:2018 + +#[must_not_suspend = "You gotta use Umm's, ya know?"] //~ ERROR the `#[must_not_suspend]` +struct Umm { + _i: i64 +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr new file mode 100644 index 000000000..ab20a8be8 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/feature-gate-must_not_suspend.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[must_not_suspend]` attribute is an experimental feature + --> $DIR/feature-gate-must_not_suspend.rs:3:1 + | +LL | #[must_not_suspend = "You gotta use Umm's, ya know?"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/must_not_suspend/gated.rs b/tests/ui/lint/must_not_suspend/gated.rs new file mode 100644 index 000000000..b73a76555 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/gated.rs @@ -0,0 +1,17 @@ +// check-pass + +// edition:2018 +#![deny(must_not_suspend)] +//~^ WARNING unknown lint: `must_not_suspend` +//~| WARNING unknown lint: `must_not_suspend` +//~| WARNING unknown lint: `must_not_suspend` + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/gated.stderr b/tests/ui/lint/must_not_suspend/gated.stderr new file mode 100644 index 000000000..64de1ebea --- /dev/null +++ b/tests/ui/lint/must_not_suspend/gated.stderr @@ -0,0 +1,33 @@ +warning: unknown lint: `must_not_suspend` + --> $DIR/gated.rs:4:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `must_not_suspend` lint is unstable + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `must_not_suspend` + --> $DIR/gated.rs:4:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `must_not_suspend` lint is unstable + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +warning: unknown lint: `must_not_suspend` + --> $DIR/gated.rs:4:1 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `must_not_suspend` lint is unstable + = note: see issue #83310 for more information + = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/must_not_suspend/generic.rs b/tests/ui/lint/must_not_suspend/generic.rs new file mode 100644 index 000000000..b3effa020 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/generic.rs @@ -0,0 +1,20 @@ +// edition:2018 +// run-pass +// +// this test shows a case where the lint doesn't fire in generic code +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +struct No {} + +async fn shushspend() {} + +async fn wheeee(t: T) { + shushspend().await; + drop(t); +} + +fn main() { + let _fut = wheeee(No {}); +} diff --git a/tests/ui/lint/must_not_suspend/handled.rs b/tests/ui/lint/must_not_suspend/handled.rs new file mode 100644 index 000000000..8714be644 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/handled.rs @@ -0,0 +1,28 @@ +// edition:2018 +// run-pass +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + _i: i64 +} + + +fn bar() -> Umm { + Umm { + _i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + { + let _guard = bar(); + } + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/issue-89562.rs b/tests/ui/lint/must_not_suspend/issue-89562.rs new file mode 100644 index 000000000..acdb36fcd --- /dev/null +++ b/tests/ui/lint/must_not_suspend/issue-89562.rs @@ -0,0 +1,19 @@ +// edition:2018 +// run-pass + +use std::sync::Mutex; + +// Copied from the issue. Allow-by-default for now, so run-pass +pub async fn foo() { + let foo = Mutex::new(1); + let lock = foo.lock().unwrap(); + + // Prevent mutex lock being held across `.await` point. + drop(lock); + + bar().await; +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/mutex.rs b/tests/ui/lint/must_not_suspend/mutex.rs new file mode 100644 index 000000000..7bb895e7d --- /dev/null +++ b/tests/ui/lint/must_not_suspend/mutex.rs @@ -0,0 +1,13 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +async fn other() {} + +pub async fn uhoh(m: std::sync::Mutex<()>) { + let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/mutex.stderr b/tests/ui/lint/must_not_suspend/mutex.stderr new file mode 100644 index 000000000..c251cb845 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/mutex.stderr @@ -0,0 +1,26 @@ +error: `MutexGuard` held across a suspend point, but should not be + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send` + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/mutex.rs:8:9 + | +LL | let _guard = m.lock().unwrap(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/mutex.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/other_items.rs b/tests/ui/lint/must_not_suspend/other_items.rs new file mode 100644 index 000000000..5aa1abb14 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/other_items.rs @@ -0,0 +1,8 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] //~ ERROR attribute should be +mod inner {} + +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr new file mode 100644 index 000000000..41c889692 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -0,0 +1,10 @@ +error: `must_not_suspend` attribute should be applied to a struct, enum, or trait + --> $DIR/other_items.rs:5:1 + | +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ +LL | mod inner {} + | ------------ is not a struct, enum, or trait + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs b/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs new file mode 100644 index 000000000..1bc4a3812 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref-drop-tracking.rs @@ -0,0 +1,30 @@ +// edition:2018 +// compile-flags: -Zdrop-tracking +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + +struct Bar { + u: Umm, +} + +async fn other() {} + +impl Bar { + async fn uhoh(&mut self) { + let guard = &mut self.u; //~ ERROR `Umm` held across + + other().await; + + *guard = Umm { + i: 2 + } + } +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr b/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr new file mode 100644 index 000000000..180e187c1 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref-drop-tracking.stderr @@ -0,0 +1,27 @@ +error: reference to `Umm` held across a suspend point, but should not be + --> $DIR/ref-drop-tracking.rs:19:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/ref-drop-tracking.rs:19:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref-drop-tracking.rs:19:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +note: the lint level is defined here + --> $DIR/ref-drop-tracking.rs:4:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr new file mode 100644 index 000000000..abf76711b --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr @@ -0,0 +1,27 @@ +error: reference to `Umm` held across a suspend point, but should not be + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref.rs:21:13 + | +LL | let guard = &mut self.u; + | ^^^^^ +note: the lint level is defined here + --> $DIR/ref.rs:6:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr new file mode 100644 index 000000000..41ac09ea7 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr @@ -0,0 +1,27 @@ +error: `Umm` held across a suspend point, but should not be + --> $DIR/ref.rs:21:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/ref.rs:21:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/ref.rs:21:26 + | +LL | let guard = &mut self.u; + | ^^^^^^ +note: the lint level is defined here + --> $DIR/ref.rs:6:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/ref.rs b/tests/ui/lint/must_not_suspend/ref.rs new file mode 100644 index 000000000..f6b23746f --- /dev/null +++ b/tests/ui/lint/must_not_suspend/ref.rs @@ -0,0 +1,29 @@ +// edition:2018 +// revisions: no_drop_tracking drop_tracking +// [drop_tracking] compile-flags: -Zdrop-tracking=yes +// [no_drop_tracking] compile-flags: -Zdrop-tracking=no +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64, +} + +struct Bar { + u: Umm, +} + +async fn other() {} + +impl Bar { + async fn uhoh(&mut self) { + let guard = &mut self.u; //~ ERROR `Umm` held across + + other().await; + + *guard = Umm { i: 2 } + } +} + +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/return.rs b/tests/ui/lint/must_not_suspend/return.rs new file mode 100644 index 000000000..5b1fa5e27 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/return.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] //~ ERROR attribute should be +fn foo() -> i32 { + 0 +} +fn main() {} diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr new file mode 100644 index 000000000..fdada85eb --- /dev/null +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -0,0 +1,12 @@ +error: `must_not_suspend` attribute should be applied to a struct, enum, or trait + --> $DIR/return.rs:5:1 + | +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ +LL | / fn foo() -> i32 { +LL | | 0 +LL | | } + | |_- is not a struct, enum, or trait + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/trait.rs b/tests/ui/lint/must_not_suspend/trait.rs new file mode 100644 index 000000000..6c911cb4b --- /dev/null +++ b/tests/ui/lint/must_not_suspend/trait.rs @@ -0,0 +1,28 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend] +trait Wow {} + +impl Wow for i32 {} + +fn r#impl() -> impl Wow { + 1 +} + +fn r#dyn() -> Box { + Box::new(1) +} + +async fn other() {} + +pub async fn uhoh() { + let _guard1 = r#impl(); //~ ERROR implementer of `Wow` held across + let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across + + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/trait.stderr b/tests/ui/lint/must_not_suspend/trait.stderr new file mode 100644 index 000000000..d64d25aae --- /dev/null +++ b/tests/ui/lint/must_not_suspend/trait.stderr @@ -0,0 +1,37 @@ +error: implementer of `Wow` held across a suspend point, but should not be + --> $DIR/trait.rs:21:9 + | +LL | let _guard1 = r#impl(); + | ^^^^^^^ +... +LL | other().await; + | ------ the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/trait.rs:21:9 + | +LL | let _guard1 = r#impl(); + | ^^^^^^^ +note: the lint level is defined here + --> $DIR/trait.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: boxed `Wow` trait object held across a suspend point, but should not be + --> $DIR/trait.rs:22:9 + | +LL | let _guard2 = r#dyn(); + | ^^^^^^^ +LL | +LL | other().await; + | ------ the value is held across this suspend point + | +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/trait.rs:22:9 + | +LL | let _guard2 = r#dyn(); + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs new file mode 100644 index 000000000..c7e14e425 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs @@ -0,0 +1,9 @@ +#![feature(generators)] + +fn main() { + let _generator = || { + yield ((), ((), ())); + yield ((), ()); + //~^ ERROR mismatched types + }; +} diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr new file mode 100644 index 000000000..cca8cd9bd --- /dev/null +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/tuple-mismatch.rs:6:20 + | +LL | yield ((), ()); + | ^^ expected tuple, found `()` + | + = note: expected tuple `((), ())` + found unit type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/must_not_suspend/unit.rs b/tests/ui/lint/must_not_suspend/unit.rs new file mode 100644 index 000000000..d3a19f704 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/unit.rs @@ -0,0 +1,25 @@ +// edition:2018 +#![feature(must_not_suspend)] +#![deny(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + i: i64 +} + + +fn bar() -> Umm { + Umm { + i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ ERROR `Umm` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/unit.stderr b/tests/ui/lint/must_not_suspend/unit.stderr new file mode 100644 index 000000000..c967dbac5 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/unit.stderr @@ -0,0 +1,26 @@ +error: `Umm` held across a suspend point, but should not be + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/unit.rs:20:9 + | +LL | let _guard = bar(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/unit.rs:3:9 + | +LL | #![deny(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/must_not_suspend/warn.rs b/tests/ui/lint/must_not_suspend/warn.rs new file mode 100644 index 000000000..7fdea66a2 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/warn.rs @@ -0,0 +1,26 @@ +// edition:2018 +// run-pass +#![feature(must_not_suspend)] +#![warn(must_not_suspend)] + +#[must_not_suspend = "You gotta use Umm's, ya know?"] +struct Umm { + _i: i64 +} + + +fn bar() -> Umm { + Umm { + _i: 1 + } +} + +async fn other() {} + +pub async fn uhoh() { + let _guard = bar(); //~ WARNING `Umm` held across + other().await; +} + +fn main() { +} diff --git a/tests/ui/lint/must_not_suspend/warn.stderr b/tests/ui/lint/must_not_suspend/warn.stderr new file mode 100644 index 000000000..fe551c652 --- /dev/null +++ b/tests/ui/lint/must_not_suspend/warn.stderr @@ -0,0 +1,26 @@ +warning: `Umm` held across a suspend point, but should not be + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +LL | other().await; + | ------ the value is held across this suspend point + | +note: You gotta use Umm's, ya know? + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point + --> $DIR/warn.rs:21:9 + | +LL | let _guard = bar(); + | ^^^^^^ +note: the lint level is defined here + --> $DIR/warn.rs:4:9 + | +LL | #![warn(must_not_suspend)] + | ^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/no-coverage.rs b/tests/ui/lint/no-coverage.rs new file mode 100644 index 000000000..ff24c12b2 --- /dev/null +++ b/tests/ui/lint/no-coverage.rs @@ -0,0 +1,55 @@ +#![feature(extern_types)] +#![feature(no_coverage)] +#![feature(type_alias_impl_trait)] +#![warn(unused_attributes)] +#![no_coverage] +//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + +#[no_coverage] +//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly +trait Trait { + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + const X: u32; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type T; + + type U; +} + +#[no_coverage] +//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly +impl Trait for () { + const X: u32 = 0; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type T = Self; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type U = impl Trait; //~ ERROR unconstrained opaque type +} + +extern "C" { + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + static X: u32; + + #[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code + type T; +} + +#[no_coverage] +fn main() { + #[no_coverage] + //~^ WARN `#[no_coverage]` may only be applied to function definitions + let _ = (); + + match () { + #[no_coverage] + //~^ WARN `#[no_coverage]` may only be applied to function definitions + () => (), + } + + #[no_coverage] + //~^ WARN `#[no_coverage]` may only be applied to function definitions + return (); +} diff --git a/tests/ui/lint/no-coverage.stderr b/tests/ui/lint/no-coverage.stderr new file mode 100644 index 000000000..404efbeac --- /dev/null +++ b/tests/ui/lint/no-coverage.stderr @@ -0,0 +1,101 @@ +warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + --> $DIR/no-coverage.rs:8:1 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/no-coverage.rs:4:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + --> $DIR/no-coverage.rs:20:1 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` may only be applied to function definitions + --> $DIR/no-coverage.rs:42:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` may only be applied to function definitions + --> $DIR/no-coverage.rs:47:9 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +warning: `#[no_coverage]` may only be applied to function definitions + --> $DIR/no-coverage.rs:52:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:11:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | const X: u32; + | ------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:14:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type T; + | ------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:25:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type T = Self; + | -------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:28:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type U = impl Trait; + | -------------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:33:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | static X: u32; + | -------------- not coverable code + +error[E0788]: `#[no_coverage]` must be applied to coverable code + --> $DIR/no-coverage.rs:36:5 + | +LL | #[no_coverage] + | ^^^^^^^^^^^^^^ +LL | type T; + | ------- not coverable code + +warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly + --> $DIR/no-coverage.rs:5:1 + | +LL | #![no_coverage] + | ^^^^^^^^^^^^^^^ + +error: unconstrained opaque type + --> $DIR/no-coverage.rs:29:14 + | +LL | type U = impl Trait; + | ^^^^^^^^^^ + | + = note: `U` must be used in combination with a concrete type within the same impl + +error: aborting due to 7 previous errors; 6 warnings emitted + +For more information about this error, try `rustc --explain E0788`. diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs new file mode 100644 index 000000000..89b296635 --- /dev/null +++ b/tests/ui/lint/noop-method-call.rs @@ -0,0 +1,55 @@ +// check-pass + +#![allow(unused)] +#![warn(noop_method_call)] + +use std::borrow::Borrow; +use std::ops::Deref; + +struct PlainType(T); + +#[derive(Clone)] +struct CloneType(T); + +fn main() { + let non_clone_type_ref = &PlainType(1u32); + let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); + //~^ WARNING call to `.clone()` on a reference in this situation does nothing + + let clone_type_ref = &CloneType(1u32); + let clone_type_ref_clone: CloneType = clone_type_ref.clone(); + + // Calling clone on a double reference doesn't warn since the method call itself + // peels the outer reference off + let clone_type_ref = &&CloneType(1u32); + let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); + + let non_deref_type = &PlainType(1u32); + let non_deref_type_deref: &PlainType = non_deref_type.deref(); + //~^ WARNING call to `.deref()` on a reference in this situation does nothing + + // Dereferencing a &&T does not warn since it has collapsed the double reference + let non_deref_type = &&PlainType(1u32); + let non_deref_type_deref: &PlainType = non_deref_type.deref(); + + let non_borrow_type = &PlainType(1u32); + let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); + //~^ WARNING call to `.borrow()` on a reference in this situation does nothing + + // Borrowing a &&T does not warn since it has collapsed the double reference + let non_borrow_type = &&PlainType(1u32); + let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); + + let xs = ["a", "b", "c"]; + let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // ok, but could use `*x` instead +} + +fn generic(non_clone_type: &PlainType) { + non_clone_type.clone(); + //~^ WARNING call to `.clone()` on a reference in this situation does nothing +} + +fn non_generic(non_clone_type: &PlainType) { + non_clone_type.clone(); + //~^ WARNING call to `.clone()` on a reference in this situation does nothing +} diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr new file mode 100644 index 000000000..6a904d01a --- /dev/null +++ b/tests/ui/lint/noop-method-call.stderr @@ -0,0 +1,47 @@ +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:16:71 + | +LL | let non_clone_type_ref_clone: &PlainType = non_clone_type_ref.clone(); + | ^^^^^^^^ unnecessary method call + | + = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed +note: the lint level is defined here + --> $DIR/noop-method-call.rs:4:9 + | +LL | #![warn(noop_method_call)] + | ^^^^^^^^^^^^^^^^ + +warning: call to `.deref()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:28:63 + | +LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); + | ^^^^^^^^ unnecessary method call + | + = note: the type `&PlainType` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed + +warning: call to `.borrow()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:36:66 + | +LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); + | ^^^^^^^^^ unnecessary method call + | + = note: the type `&PlainType` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed + +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:48:19 + | +LL | non_clone_type.clone(); + | ^^^^^^^^ unnecessary method call + | + = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + +warning: call to `.clone()` on a reference in this situation does nothing + --> $DIR/noop-method-call.rs:53:19 + | +LL | non_clone_type.clone(); + | ^^^^^^^^ unnecessary method call + | + = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/not_found.rs b/tests/ui/lint/not_found.rs new file mode 100644 index 000000000..de120b6e0 --- /dev/null +++ b/tests/ui/lint/not_found.rs @@ -0,0 +1,21 @@ +// check-pass + +// this tests the `unknown_lint` lint, especially the suggestions + +// the suggestion only appears if a lint with the lowercase name exists +#[allow(FOO_BAR)] +//~^ WARNING unknown lint + +// the suggestion appears on all-uppercase names +#[warn(DEAD_CODE)] +//~^ WARNING unknown lint +//~| HELP did you mean + +// the suggestion appears also on mixed-case names +#[deny(Warnings)] +//~^ WARNING unknown lint +//~| HELP did you mean + +fn main() { + unimplemented!(); +} diff --git a/tests/ui/lint/not_found.stderr b/tests/ui/lint/not_found.stderr new file mode 100644 index 000000000..ea118c73c --- /dev/null +++ b/tests/ui/lint/not_found.stderr @@ -0,0 +1,22 @@ +warning: unknown lint: `FOO_BAR` + --> $DIR/not_found.rs:6:9 + | +LL | #[allow(FOO_BAR)] + | ^^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + +warning: unknown lint: `DEAD_CODE` + --> $DIR/not_found.rs:10:8 + | +LL | #[warn(DEAD_CODE)] + | ^^^^^^^^^ help: did you mean: `dead_code` + +warning: unknown lint: `Warnings` + --> $DIR/not_found.rs:15:8 + | +LL | #[deny(Warnings)] + | ^^^^^^^^ help: did you mean (notice the capitalization): `warnings` + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs new file mode 100644 index 000000000..c83bca4a4 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs @@ -0,0 +1,41 @@ +#![feature(type_alias_impl_trait)] +#![allow(unused)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl TraitB for T +where + T: TraitA, +{ + type Assoc = ::Assoc; +} + +type AliasA = impl TraitA; + +type AliasB = impl TraitB; + +fn use_of_a() -> AliasA { + 3 +} + +fn use_of_b() -> AliasB { + 3 +} + +extern "C" { + fn lint_me() -> ::Assoc; + //~^ ERROR `extern` block uses type `AliasB`, which is not FFI-safe +} + +fn main() {} diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr new file mode 100644 index 000000000..e8d696477 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `AliasB`, which is not FFI-safe + --> $DIR/opaque-ty-ffi-normalization-cycle.rs:37:21 + | +LL | fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/opaque-ty-ffi-normalization-cycle.rs:3:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.rs b/tests/ui/lint/opaque-ty-ffi-unsafe.rs new file mode 100644 index 000000000..b7cc38e99 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +type A = impl Fn(); + +pub fn ret_closure() -> A { + || {} +} + +extern "C" { + pub fn a(_: A); + //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes] +} + +fn main() {} diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr new file mode 100644 index 000000000..33aa95854 --- /dev/null +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `A`, which is not FFI-safe + --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 + | +LL | pub fn a(_: A); + | ^ not FFI-safe + | + = note: opaque types have no C equivalent +note: the lint level is defined here + --> $DIR/opaque-ty-ffi-unsafe.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/outer-forbid.rs b/tests/ui/lint/outer-forbid.rs new file mode 100644 index 000000000..ba330258d --- /dev/null +++ b/tests/ui/lint/outer-forbid.rs @@ -0,0 +1,32 @@ +// Forbidding a group (here, `unused`) overrules subsequent allowance of both +// the group, and an individual lint in the group (here, `unused_variables`); +// and, forbidding an individual lint (here, `non_snake_case`) overrules +// subsequent allowance of a lint group containing it (here, `nonstandard_style`). See +// Issue #42873. + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and currently that happens two or three different times, depending on +// compiler flags. +// +// The test is much cleaner if we deduplicate, though. + +// compile-flags: -Z deduplicate-diagnostics=yes + +#![forbid(unused, non_snake_case)] +#![forbid(forbidden_lint_groups)] + +#[allow(unused_variables)] +//~^ ERROR incompatible with previous +//~| WARNING this was previously accepted by the compiler +fn foo() {} + +#[allow(unused)] //~ ERROR incompatible with previous +//~^ WARNING this was previously accepted by the compiler +fn bar() {} + +#[allow(nonstandard_style)] //~ ERROR incompatible with previous +fn main() { + println!("hello forbidden world") +} diff --git a/tests/ui/lint/outer-forbid.stderr b/tests/ui/lint/outer-forbid.stderr new file mode 100644 index 000000000..a47877980 --- /dev/null +++ b/tests/ui/lint/outer-forbid.stderr @@ -0,0 +1,41 @@ +error: allow(unused_variables) incompatible with previous forbid + --> $DIR/outer-forbid.rs:20:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + +error[E0453]: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/outer-forbid.rs:29:9 + | +LL | #![forbid(unused, non_snake_case)] + | -------------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/reasons-erroneous.rs b/tests/ui/lint/reasons-erroneous.rs new file mode 100644 index 000000000..cd693ae16 --- /dev/null +++ b/tests/ui/lint/reasons-erroneous.rs @@ -0,0 +1,54 @@ +#![feature(lint_reasons)] + +#![warn(absolute_paths_not_starting_with_crate, reason = 0)] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason must be a string literal +//~| NOTE reason must be a string literal +#![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason must be a string literal +//~| NOTE reason must be a string literal +#![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +#![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +//~| NOTE bad attribute argument +#![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason in lint attribute must come last +//~| NOTE reason in lint attribute must come last +#![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] +//~^ ERROR malformed lint attribute +//~| ERROR malformed lint attribute +//~| NOTE reason in lint attribute must come last +//~| NOTE reason in lint attribute must come last +#![warn(missing_copy_implementations, reason)] +//~^ WARN unknown lint +//~| NOTE `#[warn(unknown_lints)]` on by default + +fn main() {} diff --git a/tests/ui/lint/reasons-erroneous.stderr b/tests/ui/lint/reasons-erroneous.stderr new file mode 100644 index 000000000..5521af17c --- /dev/null +++ b/tests/ui/lint/reasons-erroneous.stderr @@ -0,0 +1,131 @@ +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:3:58 + | +LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] + | ^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:8:40 + | +LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:40:44 + | +LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] + | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:45:25 + | +LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:3:58 + | +LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)] + | ^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:8:40 + | +LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:13:29 + | +LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:22:23 + | +LL | #![warn(box_pointers, blerp = "or in league with robbers have reversed the signposts")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:31:36 + | +LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:40:44 + | +LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")] + | ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +error[E0452]: malformed lint attribute input + --> $DIR/reasons-erroneous.rs:45:25 + | +LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last + +warning: unknown lint: `reason` + --> $DIR/reasons-erroneous.rs:50:39 + | +LL | #![warn(missing_copy_implementations, reason)] + | ^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + +error: aborting due to 20 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/lint/reasons-forbidden.rs b/tests/ui/lint/reasons-forbidden.rs new file mode 100644 index 000000000..9c2edec4d --- /dev/null +++ b/tests/ui/lint/reasons-forbidden.rs @@ -0,0 +1,34 @@ +#![feature(lint_reasons)] + +// If you turn off deduplicate diagnostics (which rustc turns on by default but +// compiletest turns off when it runs ui tests), then the errors are +// (unfortunately) repeated here because the checking is done as we read in the +// errors, and currently that happens two or three different times, depending on +// compiler flags. +// +// The test is much cleaner if we deduplicate, though. + +// compile-flags: -Z deduplicate-diagnostics=yes + +#![forbid( + unsafe_code, + //~^ NOTE `forbid` level set here + //~| NOTE the lint level is defined here + reason = "our errors & omissions insurance policy doesn't cover unsafe Rust" +)] + +use std::ptr; + +fn main() { + let a_billion_dollar_mistake = ptr::null(); + + #[allow(unsafe_code)] + //~^ ERROR allow(unsafe_code) incompatible with previous forbid + //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust + //~| NOTE overruled by previous forbid + unsafe { + //~^ ERROR usage of an `unsafe` block + //~| NOTE our errors & omissions insurance policy doesn't cover unsafe Rust + *a_billion_dollar_mistake + } +} diff --git a/tests/ui/lint/reasons-forbidden.stderr b/tests/ui/lint/reasons-forbidden.stderr new file mode 100644 index 000000000..ab6f19a01 --- /dev/null +++ b/tests/ui/lint/reasons-forbidden.stderr @@ -0,0 +1,31 @@ +error[E0453]: allow(unsafe_code) incompatible with previous forbid + --> $DIR/reasons-forbidden.rs:25:13 + | +LL | unsafe_code, + | ----------- `forbid` level set here +... +LL | #[allow(unsafe_code)] + | ^^^^^^^^^^^ overruled by previous forbid + | + = note: our errors & omissions insurance policy doesn't cover unsafe Rust + +error: usage of an `unsafe` block + --> $DIR/reasons-forbidden.rs:29:5 + | +LL | / unsafe { +LL | | +LL | | +LL | | *a_billion_dollar_mistake +LL | | } + | |_____^ + | + = note: our errors & omissions insurance policy doesn't cover unsafe Rust +note: the lint level is defined here + --> $DIR/reasons-forbidden.rs:14:5 + | +LL | unsafe_code, + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/reasons.rs b/tests/ui/lint/reasons.rs new file mode 100644 index 000000000..da1c740c4 --- /dev/null +++ b/tests/ui/lint/reasons.rs @@ -0,0 +1,35 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(elided_lifetimes_in_paths, + //~^ NOTE the lint level is defined here + reason = "explicit anonymous lifetimes aid reasoning about ownership")] +#![warn( + nonstandard_style, + //~^ NOTE the lint level is defined here + reason = r#"people shouldn't have to change their usual style habits +to contribute to our project"# +)] +#![allow(unused, reason = "unused code has never killed anypony")] + +use std::fmt; + +pub struct CheaterDetectionMechanism {} + +impl fmt::Debug for CheaterDetectionMechanism { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + //~^ WARN hidden lifetime parameters in types are deprecated + //~| NOTE expected lifetime parameter + //~| NOTE explicit anonymous lifetimes aid + //~| HELP indicate the anonymous lifetime + fmt.debug_struct("CheaterDetectionMechanism").finish() + } +} + +fn main() { + let Social_exchange_psychology = CheaterDetectionMechanism {}; + //~^ WARN should have a snake case name + //~| NOTE #[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)] + //~| NOTE people shouldn't have to change their usual style habits + //~| HELP convert the identifier to snake case +} diff --git a/tests/ui/lint/reasons.stderr b/tests/ui/lint/reasons.stderr new file mode 100644 index 000000000..cd8412153 --- /dev/null +++ b/tests/ui/lint/reasons.stderr @@ -0,0 +1,36 @@ +warning: hidden lifetime parameters in types are deprecated + --> $DIR/reasons.rs:20:34 + | +LL | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + | -----^^^^^^^^^ + | | + | expected lifetime parameter + | + = note: explicit anonymous lifetimes aid reasoning about ownership +note: the lint level is defined here + --> $DIR/reasons.rs:4:9 + | +LL | #![warn(elided_lifetimes_in_paths, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + | ++++ + +warning: variable `Social_exchange_psychology` should have a snake case name + --> $DIR/reasons.rs:30:9 + | +LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology` + | + = note: people shouldn't have to change their usual style habits + to contribute to our project +note: the lint level is defined here + --> $DIR/reasons.rs:8:5 + | +LL | nonstandard_style, + | ^^^^^^^^^^^^^^^^^ + = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]` + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/recommend-literal.rs b/tests/ui/lint/recommend-literal.rs new file mode 100644 index 000000000..453cbf285 --- /dev/null +++ b/tests/ui/lint/recommend-literal.rs @@ -0,0 +1,42 @@ +type Real = double; +//~^ ERROR cannot find type `double` in this scope +//~| HELP perhaps you intended to use this type + +fn main() { + let x: Real = 3.5; + let y: long = 74802374902374923; + //~^ ERROR cannot find type `long` in this scope + //~| HELP perhaps you intended to use this type + let v1: Boolean = true; + //~^ ERROR: cannot find type `Boolean` in this scope [E0412] + //~| HELP perhaps you intended to use this type + let v2: Bool = true; + //~^ ERROR: cannot find type `Bool` in this scope [E0412] + //~| HELP a builtin type with a similar name exists + //~| HELP perhaps you intended to use this type +} + +fn z(a: boolean) { + //~^ ERROR cannot find type `boolean` in this scope + //~| HELP perhaps you intended to use this type +} + +fn a() -> byte { +//~^ ERROR cannot find type `byte` in this scope +//~| HELP perhaps you intended to use this type + 3 +} + +struct Data { //~ HELP you might be missing a type parameter + width: float, + //~^ ERROR cannot find type `float` in this scope + //~| HELP perhaps you intended to use this type + depth: Option, + //~^ ERROR cannot find type `int` in this scope + //~| HELP perhaps you intended to use this type +} + +trait Stuff {} +impl Stuff for short {} +//~^ ERROR cannot find type `short` in this scope +//~| HELP perhaps you intended to use this type diff --git a/tests/ui/lint/recommend-literal.stderr b/tests/ui/lint/recommend-literal.stderr new file mode 100644 index 000000000..424ecadd4 --- /dev/null +++ b/tests/ui/lint/recommend-literal.stderr @@ -0,0 +1,96 @@ +error[E0412]: cannot find type `double` in this scope + --> $DIR/recommend-literal.rs:1:13 + | +LL | type Real = double; + | ^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f64` + +error[E0412]: cannot find type `long` in this scope + --> $DIR/recommend-literal.rs:7:12 + | +LL | let y: long = 74802374902374923; + | ^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `i64` + +error[E0412]: cannot find type `Boolean` in this scope + --> $DIR/recommend-literal.rs:10:13 + | +LL | let v1: Boolean = true; + | ^^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `bool` + +error[E0412]: cannot find type `Bool` in this scope + --> $DIR/recommend-literal.rs:13:13 + | +LL | let v2: Bool = true; + | ^^^^ + | +help: a builtin type with a similar name exists + | +LL | let v2: bool = true; + | ~~~~ +help: perhaps you intended to use this type + | +LL | let v2: bool = true; + | ~~~~ + +error[E0412]: cannot find type `boolean` in this scope + --> $DIR/recommend-literal.rs:19:9 + | +LL | fn z(a: boolean) { + | ^^^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `bool` + +error[E0412]: cannot find type `byte` in this scope + --> $DIR/recommend-literal.rs:24:11 + | +LL | fn a() -> byte { + | ^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `u8` + +error[E0412]: cannot find type `float` in this scope + --> $DIR/recommend-literal.rs:31:12 + | +LL | width: float, + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f32` + +error[E0412]: cannot find type `int` in this scope + --> $DIR/recommend-literal.rs:34:19 + | +LL | depth: Option, + | ^^^ not found in this scope + | +help: perhaps you intended to use this type + | +LL | depth: Option, + | ~~~ +help: you might be missing a type parameter + | +LL | struct Data { + | +++++ + +error[E0412]: cannot find type `short` in this scope + --> $DIR/recommend-literal.rs:40:16 + | +LL | impl Stuff for short {} + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `i16` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs new file mode 100644 index 000000000..5a94ccd74 --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic +#![crate_type="proc-macro"] +#![crate_name="redundant_semi_proc_macro"] +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn should_preserve_spans(_attr: TokenStream, item: TokenStream) -> TokenStream { + eprintln!("{:?}", item); + item +} diff --git a/tests/ui/lint/redundant-semicolon/item-stmt-semi.rs b/tests/ui/lint/redundant-semicolon/item-stmt-semi.rs new file mode 100644 index 000000000..8c79630b7 --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/item-stmt-semi.rs @@ -0,0 +1,6 @@ +#![deny(redundant_semicolons)] + +fn main() { + fn inner() {}; //~ ERROR unnecessary + struct Bar {}; //~ ERROR unnecessary +} diff --git a/tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr b/tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr new file mode 100644 index 000000000..451b152cb --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/item-stmt-semi.stderr @@ -0,0 +1,20 @@ +error: unnecessary trailing semicolon + --> $DIR/item-stmt-semi.rs:4:18 + | +LL | fn inner() {}; + | ^ help: remove this semicolon + | +note: the lint level is defined here + --> $DIR/item-stmt-semi.rs:1:9 + | +LL | #![deny(redundant_semicolons)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolon + --> $DIR/item-stmt-semi.rs:5:18 + | +LL | struct Bar {}; + | ^ help: remove this semicolon + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs new file mode 100644 index 000000000..08a5c6c2b --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -0,0 +1,19 @@ +// aux-build:redundant-semi-proc-macro-def.rs + +#![deny(redundant_semicolons)] +extern crate redundant_semi_proc_macro; +use redundant_semi_proc_macro::should_preserve_spans; + +#[should_preserve_spans] +fn span_preservation() { + let tst = 123;; //~ ERROR unnecessary trailing semicolon + match tst { + // Redundant semicolons are parsed as empty tuple exprs + // for the lint, so ensure the lint doesn't affect + // empty tuple exprs explicitly in source. + 123 => (), + _ => () + };;; //~ ERROR unnecessary trailing semicolons +} + +fn main() {} diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr new file mode 100644 index 000000000..e31d14c55 --- /dev/null +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -0,0 +1,21 @@ +TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(238..241) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(483..486) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(488..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(505..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] +error: unnecessary trailing semicolon + --> $DIR/redundant-semi-proc-macro.rs:9:19 + | +LL | let tst = 123;; + | ^ help: remove this semicolon + | +note: the lint level is defined here + --> $DIR/redundant-semi-proc-macro.rs:3:9 + | +LL | #![deny(redundant_semicolons)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary trailing semicolons + --> $DIR/redundant-semi-proc-macro.rs:16:7 + | +LL | };;; + | ^^ help: remove these semicolons + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/register-tool-lint.rs b/tests/ui/lint/register-tool-lint.rs new file mode 100644 index 000000000..17d3afbf6 --- /dev/null +++ b/tests/ui/lint/register-tool-lint.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![feature(register_tool)] +#![register_tool(xyz)] +#![warn(xyz::my_lint)] // this should not error +#![warn(abc::my_lint)] +//~^ ERROR unknown tool name `abc` found in scoped lint +//~| HELP add `#![register_tool(abc)]` +//~| ERROR unknown tool name `abc` +//~| HELP add `#![register_tool(abc)]` diff --git a/tests/ui/lint/register-tool-lint.stderr b/tests/ui/lint/register-tool-lint.stderr new file mode 100644 index 000000000..842d845ff --- /dev/null +++ b/tests/ui/lint/register-tool-lint.stderr @@ -0,0 +1,19 @@ +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint` + --> $DIR/register-tool-lint.rs:5:9 + | +LL | #![warn(abc::my_lint)] + | ^^^ + | + = help: add `#![register_tool(abc)]` to the crate root + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/lint/renamed-lints-still-apply.rs b/tests/ui/lint/renamed-lints-still-apply.rs new file mode 100644 index 000000000..01cd32536 --- /dev/null +++ b/tests/ui/lint/renamed-lints-still-apply.rs @@ -0,0 +1,9 @@ +// compile-flags: --crate-type lib +#![deny(single_use_lifetime)] +//~^ WARNING renamed +//~| NOTE `#[warn(renamed_and_removed_lints)]` on by default +//~| NOTE defined here +fn _foo<'a>(_x: &'a u32) {} +//~^ ERROR only used once +//~| NOTE this lifetime +//~| NOTE is used only here diff --git a/tests/ui/lint/renamed-lints-still-apply.stderr b/tests/ui/lint/renamed-lints-still-apply.stderr new file mode 100644 index 000000000..e926719bb --- /dev/null +++ b/tests/ui/lint/renamed-lints-still-apply.stderr @@ -0,0 +1,29 @@ +warning: lint `single_use_lifetime` has been renamed to `single_use_lifetimes` + --> $DIR/renamed-lints-still-apply.rs:2:9 + | +LL | #![deny(single_use_lifetime)] + | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `single_use_lifetimes` + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +error: lifetime parameter `'a` only used once + --> $DIR/renamed-lints-still-apply.rs:6:9 + | +LL | fn _foo<'a>(_x: &'a u32) {} + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/renamed-lints-still-apply.rs:2:9 + | +LL | #![deny(single_use_lifetime)] + | ^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - fn _foo<'a>(_x: &'a u32) {} +LL + fn _foo(_x: &u32) {} + | + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs b/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs new file mode 100644 index 000000000..912e831d8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/avoid_delayed_good_path_ice.rs @@ -0,0 +1,8 @@ +// check-pass +#![feature(lint_reasons)] + +#[expect(drop_bounds)] +fn trigger_rustc_lints() { +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs b/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs new file mode 100644 index 000000000..6b255b799 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/catch_multiple_lint_triggers.rs @@ -0,0 +1,45 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +// This expect attribute should catch all lint triggers +#[expect(unused_variables)] +fn check_multiple_lints_1() { + let value_i = 0xff00ff; + let value_ii = 0xff00ff; + let value_iii = 0xff00ff; + let value_iiii = 0xff00ff; + let value_iiiii = 0xff00ff; +} + +// This expect attribute should catch all lint triggers +#[expect(unused_mut)] +fn check_multiple_lints_2() { + let mut a = 0xa; + let mut b = 0xb; + let mut c = 0xc; + println!("The ABC goes as: {:#x} {:#x} {:#x}", a, b, c); +} + +// This expect attribute should catch all lint triggers +#[expect(while_true)] +fn check_multiple_lints_3() { + // `while_true` is an early lint + while true {} + + while true {} + + while true {} + + while true {} + + while true {} +} + +fn main() { + check_multiple_lints_1(); + check_multiple_lints_2(); + check_multiple_lints_3(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs new file mode 100644 index 000000000..9f591ba98 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +#![expect(unused_mut)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + +#![expect(unused_variables)] + +fn main() { + let x = 0; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr new file mode 100644 index 000000000..7237f6fb6 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/crate_level_expect.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/crate_level_expect.rs:7:11 + | +LL | #![expect(unused_mut)] + | ^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs new file mode 100644 index 000000000..b95815bc5 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_inside_macro.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +macro_rules! expect_inside_macro { + () => { + #[expect(unused_variables)] + let x = 0; + }; +} + +fn main() { + expect_inside_macro!(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs new file mode 100644 index 000000000..07c60fa0c --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs @@ -0,0 +1,42 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused_variables)] + +macro_rules! trigger_unused_variables_macro { + () => { + let x = 0; + //~^ WARNING unused variable: `x` [unused_variables] + //~| WARNING unused variable: `x` [unused_variables] + }; +} + +pub fn check_macro() { + // This should trigger the `unused_variables` from inside the macro + trigger_unused_variables_macro!(); +} + +// This should be fulfilled by the macro +#[expect(unused_variables)] +pub fn check_expect_on_item() { + trigger_unused_variables_macro!(); +} + +pub fn check_expect_on_macro() { + // This should be fulfilled by the macro + #[expect(unused_variables)] + trigger_unused_variables_macro!(); + + // FIXME: Lint attributes currently don't work directly on macros, and + // therefore also doesn't work for the new `expect` attribute. This bug + // is being tracked in rust#87391. The test will until then produce two + // warnings about the unused variable x. + // + // The expectation is still marked as fulfilled. I'm not totally why but + // my guess is that this will remain working when rust#87391 has been fixed. +} + +fn main() { + +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr new file mode 100644 index 000000000..817e16fdc --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr @@ -0,0 +1,29 @@ +warning: unused variable: `x` + --> $DIR/expect_lint_from_macro.rs:9:13 + | +LL | let x = 0; + | ^ help: if this is intentional, prefix it with an underscore: `_x` +... +LL | trigger_unused_variables_macro!(); + | --------------------------------- in this macro invocation + | +note: the lint level is defined here + --> $DIR/expect_lint_from_macro.rs:5:9 + | +LL | #![warn(unused_variables)] + | ^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unused variable: `x` + --> $DIR/expect_lint_from_macro.rs:9:13 + | +LL | let x = 0; + | ^ help: if this is intentional, prefix it with an underscore: `_x` +... +LL | trigger_unused_variables_macro!(); + | --------------------------------- in this macro invocation + | + = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs new file mode 100644 index 000000000..928e16106 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.rs @@ -0,0 +1,9 @@ +// should error due to missing feature gate. + +#![warn(unused)] + +#[expect(unused)] +//~^ ERROR: the `#[expect]` attribute is an experimental feature [E0658] +fn main() { + let x = 1; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr new file mode 100644 index 000000000..b5601cf9e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_missing_feature_gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[expect]` attribute is an experimental feature + --> $DIR/expect_missing_feature_gate.rs:5:1 + | +LL | #[expect(unused)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54503 for more information + = help: add `#![feature(lint_reasons)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs new file mode 100644 index 000000000..dc9a719a3 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.rs @@ -0,0 +1,58 @@ +// check-pass + +#![feature(lint_reasons)] + +#![warn(unused)] + +// The warnings are not double triggers, they identify different unfulfilled lint +// expectations one for each listed lint. + +#[expect(unused_variables, unused_mut, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_1() { + // This only trigger `unused_variables` + let who_am_i = 666; +} + +#[expect(unused_variables, unused_mut, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_2() { + // This only triggers `unused_mut` + let mut x = 0; + println!("I use x: {}", x); +} + +#[expect(unused_variables, unused_mut, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_3() { + // This only triggers `while_true` which is also an early lint + while true {} +} + +#[expect(unused, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_with_lint_group_1() { + let who_am_i = 666; + + let mut x = 0; + println!("I use x: {}", x); +} + +#[expect(unused, while_true)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_with_lint_group_2() { + while true {} +} + +fn main() { + check_multiple_lints_1(); + check_multiple_lints_2(); + check_multiple_lints_3(); + + check_multiple_lints_with_lint_group_1(); + check_multiple_lints_with_lint_group_2(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr new file mode 100644 index 000000000..90ee744b2 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_multiple_lints.stderr @@ -0,0 +1,52 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:10:28 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:10:40 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:19:10 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:19:40 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:28:10 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:28:28 + | +LL | #[expect(unused_variables, unused_mut, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:36:18 + | +LL | #[expect(unused, while_true)] + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_multiple_lints.rs:45:10 + | +LL | #[expect(unused, while_true)] + | ^^^^^^ + +warning: 8 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs new file mode 100644 index 000000000..8f94bd6ec --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.rs @@ -0,0 +1,53 @@ +// ignore-tidy-linelength + +#![feature(lint_reasons)] +#![warn(unused_mut)] + +#[expect( + unused_mut, + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + //~| NOTE this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered + reason = "this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered" +)] +mod foo { + fn bar() { + #[allow( + unused_mut, + reason = "this overrides the previous `expect` lint level and allows the `unused_mut` lint here" + )] + let mut v = 0; + } +} + +#[expect( + unused_mut, + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered + reason = "this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered" +)] +mod oof { + #[warn( + unused_mut, + //~^ NOTE the lint level is defined here + reason = "this overrides the previous `expect` lint level and warns about the `unused_mut` lint here" + )] + fn bar() { + let mut v = 0; + //~^ WARNING variable does not need to be mutable [unused_mut] + //~| NOTE this overrides the previous `expect` lint level and warns about the `unused_mut` lint here + //~| HELP remove this `mut` + } +} + +#[expect(unused_variables)] +//~^ WARNING this lint expectation is unfulfilled +#[forbid(unused_variables)] +//~^ NOTE the lint level is defined here +fn check_expect_then_forbid() { + let this_is_my_function = 3; + //~^ ERROR unused variable: `this_is_my_function` [unused_variables] + //~| HELP if this is intentional, prefix it with an underscore +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr new file mode 100644 index 000000000..2c35647b8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr @@ -0,0 +1,52 @@ +error: unused variable: `this_is_my_function` + --> $DIR/expect_nested_lint_levels.rs:48:9 + | +LL | let this_is_my_function = 3; + | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_is_my_function` + | +note: the lint level is defined here + --> $DIR/expect_nested_lint_levels.rs:45:10 + | +LL | #[forbid(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/expect_nested_lint_levels.rs:36:13 + | +LL | let mut v = 0; + | ----^ + | | + | help: remove this `mut` + | + = note: this overrides the previous `expect` lint level and warns about the `unused_mut` lint here +note: the lint level is defined here + --> $DIR/expect_nested_lint_levels.rs:31:9 + | +LL | unused_mut, + | ^^^^^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/expect_nested_lint_levels.rs:7:5 + | +LL | unused_mut, + | ^^^^^^^^^^ + | + = note: this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_nested_lint_levels.rs:24:5 + | +LL | unused_mut, + | ^^^^^^^^^^ + | + = note: this `expect` is overridden by a `warn` attribute before the `unused_mut` lint is triggered + +warning: this lint expectation is unfulfilled + --> $DIR/expect_nested_lint_levels.rs:43:10 + | +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 4 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs new file mode 100644 index 000000000..5fdb71041 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(lint_reasons)] + +#[warn(unused_variables)] + +/// This should catch the unused_variables lint and not emit anything +fn check_fulfilled_expectation(#[expect(unused_variables)] unused_value: u32) {} + +fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) { + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + println!("I use the value {used_value}"); +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr new file mode 100644 index 000000000..69f7cda08 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_on_fn_params.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_on_fn_params.rs:9:43 + | +LL | fn check_unfulfilled_expectation(#[expect(unused_variables)] used_value: u32) { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs new file mode 100644 index 000000000..f80fe88cb --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -0,0 +1,155 @@ +// check-pass +#![feature(lint_reasons)] + +//! This file tests the `#[expect]` attribute implementation for tool lints. The same +//! file is used to test clippy and rustdoc. Any changes to this file should be synced +//! to the other test files. +//! +//! Expectations: +//! * rustc: only rustc lint expectations are emitted +//! * clippy: rustc and Clippy's expectations are emitted +//! * rustdoc: only rustdoc lint expectations are emitted +//! +//! This test can't cover every lint from Clippy, rustdoc and potentially other +//! tools that will be developed. This therefore only tests a small subset of lints + +#![expect(rustdoc::missing_crate_level_docs)] + +mod rustc_ok { + //! See + + #[expect(dead_code)] + pub fn rustc_lints() { + let x = 42.0; + + #[expect(illegal_floating_point_literal_pattern)] + match x { + 5.0 => {} + 6.0 => {} + _ => {} + } + } +} + +mod rustc_warn { + //! See + + #[expect(dead_code)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + pub fn rustc_lints() { + let x = 42; + + #[expect(illegal_floating_point_literal_pattern)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + match x { + 5 => {} + 6 => {} + _ => {} + } + } +} + +pub mod rustdoc_ok { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`Nonexistent`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// http://example.org + pub fn baz() {} +} + +pub mod rustdoc_warn { + //! See + + #[expect(rustdoc::broken_intra_doc_links)] + /// I want to link to [`bar`] but it doesn't exist! + pub fn foo() {} + + #[expect(rustdoc::invalid_html_tags)] + ///

+ pub fn bar() {} + + #[expect(rustdoc::bare_urls)] + /// + pub fn baz() {} +} + +mod clippy_ok { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + b = a; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".bytes().nth(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 42 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + + if a && b || a {} + } +} + +mod clippy_warn { + //! See + + #[expect(clippy::almost_swapped)] + fn foo() { + let mut a = 0; + let mut b = 9; + a = b; + } + + #[expect(clippy::bytes_nth)] + fn bar() { + let _ = "Hello".as_bytes().get(3); + } + + #[expect(clippy::if_same_then_else)] + fn baz() { + let _ = if true { + 33 + } else { + 42 + }; + } + + #[expect(clippy::logic_bug)] + fn burger() { + let a = false; + let b = true; + let c = false; + + if a && b || c {} + } +} + +fn main() { + rustc_warn::rustc_lints(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr new file mode 100644 index 000000000..6d49e7543 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -0,0 +1,16 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:37:14 + | +LL | #[expect(dead_code)] + | ^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_tool_lint_rfc_2383.rs:43:18 + | +LL | #[expect(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs new file mode 100644 index 000000000..d38e65533 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.rs @@ -0,0 +1,39 @@ +// check-pass +// ignore-tidy-linelength + +#![feature(lint_reasons)] +#![warn(unused_mut)] + +#![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] +//~^ WARNING this lint expectation is unfulfilled +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| NOTE idk why you would expect this +//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +#[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] +//~^ WARNING this lint expectation is unfulfilled +//~| NOTE a local: idk why you would expect this +//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message +pub fn normal_test_fn() { + #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + //~^ WARNING this lint expectation is unfulfilled + //~| NOTE this expectation will create a diagnostic with the default lint level + let mut v = vec![1, 1, 2, 3, 5]; + v.sort(); + + // Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly + #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + //~^ WARNING this lint expectation is unfulfilled + //~| NOTE the expectation for `unused` should be fulfilled + //~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + let value = "I'm unused"; +} + +#[expect(warnings, reason = "this suppresses all warnings and also suppresses itself. No warning will be issued")] +pub fn expect_warnings() { + // This lint trigger will be suppressed + #[warn(unused_mut)] + let mut v = vec![1, 1, 2, 3, 5]; +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr new file mode 100644 index 000000000..9a1c3e442 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr @@ -0,0 +1,38 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:7:11 + | +LL | #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: idk why you would expect this + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:13:10 + | +LL | #[expect(unfulfilled_lint_expectations, reason = "a local: idk why you would expect this")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a local: idk why you would expect this + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:18:14 + | +LL | #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")] + | ^^^^^^^^^^ + | + = note: this expectation will create a diagnostic with the default lint level + +warning: this lint expectation is unfulfilled + --> $DIR/expect_unfulfilled_expectation.rs:25:22 + | +LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the expectation for `unused` should be fulfilled + = note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs new file mode 100644 index 000000000..479ee198e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.rs @@ -0,0 +1,34 @@ +#![feature(lint_reasons)] + +#[forbid(unused_variables)] +//~^ NOTE `forbid` level set here +//~| NOTE `forbid` level set here +#[expect(unused_variables)] +//~^ ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +//~| ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +fn expect_forbidden_lint_1() {} + +#[forbid(while_true)] +//~^ NOTE `forbid` level set here +//~| NOTE `forbid` level set here +//~| NOTE the lint level is defined here +#[expect(while_true)] +//~^ ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +//~| ERROR incompatible with previous forbid [E0453] +//~| NOTE overruled by previous forbid +fn expect_forbidden_lint_2() { + // This while loop will produce a `while_true` lint as the lint level + // at this node is still `forbid` and the `while_true` check happens + // before the compilation terminates due to `E0453` + while true {} + //~^ ERROR denote infinite loops with `loop { ... }` + //~| HELP use `loop` +} + +fn main() { + expect_forbidden_lint_1(); + expect_forbidden_lint_2(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr new file mode 100644 index 000000000..a8116e934 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_forbid.stderr @@ -0,0 +1,51 @@ +error[E0453]: expect(unused_variables) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:6:10 + | +LL | #[forbid(unused_variables)] + | ---------------- `forbid` level set here +... +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: expect(while_true) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:17:10 + | +LL | #[forbid(while_true)] + | ---------- `forbid` level set here +... +LL | #[expect(while_true)] + | ^^^^^^^^^^ overruled by previous forbid + +error[E0453]: expect(unused_variables) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:6:10 + | +LL | #[forbid(unused_variables)] + | ---------------- `forbid` level set here +... +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + +error[E0453]: expect(while_true) incompatible with previous forbid + --> $DIR/expect_with_forbid.rs:17:10 + | +LL | #[forbid(while_true)] + | ---------- `forbid` level set here +... +LL | #[expect(while_true)] + | ^^^^^^^^^^ overruled by previous forbid + +error: denote infinite loops with `loop { ... }` + --> $DIR/expect_with_forbid.rs:26:5 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/expect_with_forbid.rs:13:10 + | +LL | #[forbid(while_true)] + | ^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0453`. diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs new file mode 100644 index 000000000..b4183d982 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(unused)] + +#![expect(unused_variables, reason = "")] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +//~| NOTE + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr new file mode 100644 index 000000000..e349e4081 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr @@ -0,0 +1,11 @@ +warning: this lint expectation is unfulfilled + --> $DIR/expect_with_reason.rs:6:11 + | +LL | #![expect(unused_variables, reason = "")] + | ^^^^^^^^^^^^^^^^ + | + = note: + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs new file mode 100644 index 000000000..a3c3933d7 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.rs @@ -0,0 +1,48 @@ +// compile-flags: --force-warn while_true +// compile-flags: --force-warn unused_variables +// compile-flags: --force-warn unused_mut +// check-pass + +#![feature(lint_reasons)] + +fn expect_early_pass_lint() { + #[expect(while_true)] + while true { + //~^ WARNING denote infinite loops with `loop { ... }` [while_true] + //~| NOTE requested on the command line with `--force-warn while-true` + //~| HELP use `loop` + println!("I never stop") + } +} + +#[expect(unused_variables, reason="")] +fn check_specific_lint() { + let x = 2; + //~^ WARNING unused variable: `x` [unused_variables] + //~| NOTE requested on the command line with `--force-warn unused-variables` + //~| HELP if this is intentional, prefix it with an underscore +} + +#[expect(unused)] +fn check_multiple_lints_with_lint_group() { + let fox_name = "Sir Nibbles"; + //~^ WARNING unused variable: `fox_name` [unused_variables] + //~| HELP if this is intentional, prefix it with an underscore + + let mut what_does_the_fox_say = "*ding* *deng* *dung*"; + //~^ WARNING variable does not need to be mutable [unused_mut] + //~| NOTE requested on the command line with `--force-warn unused-mut` + //~| HELP remove this `mut` + + println!("The fox says: {what_does_the_fox_say}"); +} + +#[allow(unused_variables)] +fn check_expect_overrides_allow_lint_level() { + #[expect(unused_variables)] + let this_should_fulfill_the_expectation = "The `#[allow]` has no power here"; + //~^ WARNING unused variable: `this_should_fulfill_the_expectation` [unused_variables] + //~| HELP if this is intentional, prefix it with an underscore +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr new file mode 100644 index 000000000..5942fa8ae --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr @@ -0,0 +1,40 @@ +warning: unused variable: `x` + --> $DIR/force_warn_expected_lints_fulfilled.rs:20:9 + | +LL | let x = 2; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `--force-warn unused-variables` + +warning: unused variable: `fox_name` + --> $DIR/force_warn_expected_lints_fulfilled.rs:28:9 + | +LL | let fox_name = "Sir Nibbles"; + | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_fox_name` + +warning: unused variable: `this_should_fulfill_the_expectation` + --> $DIR/force_warn_expected_lints_fulfilled.rs:43:9 + | +LL | let this_should_fulfill_the_expectation = "The `#[allow]` has no power here"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_fulfill_the_expectation` + +warning: variable does not need to be mutable + --> $DIR/force_warn_expected_lints_fulfilled.rs:32:9 + | +LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*"; + | ----^^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + | + = note: requested on the command line with `--force-warn unused-mut` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: requested on the command line with `--force-warn while-true` + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs new file mode 100644 index 000000000..080e30023 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.rs @@ -0,0 +1,49 @@ +// compile-flags: --force-warn while_true +// compile-flags: --force-warn unused_variables +// compile-flags: --force-warn unused_mut +// check-pass + +#![feature(lint_reasons)] + +fn expect_early_pass_lint(terminate: bool) { + #[expect(while_true)] + //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] + //~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default + while !terminate { + println!("Do you know what a spin lock is?") + } +} + +#[expect(unused_variables, reason="")] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE +fn check_specific_lint() { + let _x = 2; +} + +#[expect(unused)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_multiple_lints_with_lint_group() { + let fox_name = "Sir Nibbles"; + + let what_does_the_fox_say = "*ding* *deng* *dung*"; + + println!("The fox says: {what_does_the_fox_say}"); + println!("~ {fox_name}") +} + + +#[expect(unused)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +fn check_overridden_expectation_lint_level() { + #[allow(unused_variables)] + let this_should_not_fulfill_the_expectation = "maybe"; + //~^ WARNING unused variable: `this_should_not_fulfill_the_expectation` [unused_variables] + //~| NOTE requested on the command line with `--force-warn unused-variables` + //~| HELP if this is intentional, prefix it with an underscore +} + +fn main() { + check_multiple_lints_with_lint_group(); + check_overridden_expectation_lint_level(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr new file mode 100644 index 000000000..c74fabe27 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_unfulfilled.stderr @@ -0,0 +1,38 @@ +warning: unused variable: `this_should_not_fulfill_the_expectation` + --> $DIR/force_warn_expected_lints_unfulfilled.rs:40:9 + | +LL | let this_should_not_fulfill_the_expectation = "maybe"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_not_fulfill_the_expectation` + | + = note: requested on the command line with `--force-warn unused-variables` + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:9:14 + | +LL | #[expect(while_true)] + | ^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:17:10 + | +LL | #[expect(unused_variables, reason="")] + | ^^^^^^^^^^^^^^^^ + | + = note: + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:24:10 + | +LL | #[expect(unused)] + | ^^^^^^ + +warning: this lint expectation is unfulfilled + --> $DIR/force_warn_expected_lints_unfulfilled.rs:36:10 + | +LL | #[expect(unused)] + | ^^^^^^ + +warning: 5 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs new file mode 100644 index 000000000..6624b930e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_early_lints.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(lint_reasons)] + +fn expect_early_pass_lints() { + #[expect(while_true)] + while true { + println!("I never stop") + } + + #[expect(unused_doc_comments)] + /// This comment triggers the `unused_doc_comments` lint + let _sheep = "wolf"; + + let x = 123; + #[expect(ellipsis_inclusive_range_patterns)] + match x { + 0...100 => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs new file mode 100644 index 000000000..5d928b3ca --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/fulfilled_expectation_late_lints.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(unused)] + +#[expect(unused_variables)] +fn check_specific_lint() { + let x = 2; +} + +#[expect(unused)] +fn check_lint_group() { + let x = 15; +} + +#[expect(unused_variables)] +fn check_multiple_lint_emissions() { + let r = 1; + let u = 8; + let s = 2; + let t = 9; +} + +mod check_fulfilled_expect_in_macro { + macro_rules! expect_inside_macro { + () => { + #[expect(unused_variables)] + let x = 0; + }; + } + + pub fn check_macro() { + expect_inside_macro!(); + } +} + +fn main() { + check_specific_lint(); + check_lint_group(); + check_multiple_lint_emissions(); + + check_fulfilled_expect_in_macro::check_macro(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs new file mode 100644 index 000000000..bafdea96e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.rs @@ -0,0 +1,14 @@ +#![feature(lint_reasons)] + +#![deny(unused_attributes)] + +#[allow(reason = "I want to allow something")]//~ ERROR unused attribute +#[expect(reason = "I don't know what I'm waiting for")]//~ ERROR unused attribute +#[warn(reason = "This should be warn by default")]//~ ERROR unused attribute +#[deny(reason = "All listed lints are denied")]//~ ERROR unused attribute +#[forbid(reason = "Just some reason")]//~ ERROR unused attribute + +#[allow(clippy::box_collection, reason = "This is still valid")] +#[warn(dead_code, reason = "This is also reasonable")] + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr new file mode 100644 index 000000000..3e9d70821 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr @@ -0,0 +1,47 @@ +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:5:1 + | +LL | #[allow(reason = "I want to allow something")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` without any lints has no effect +note: the lint level is defined here + --> $DIR/lint-attribute-only-with-reason.rs:3:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:6:1 + | +LL | #[expect(reason = "I don't know what I'm waiting for")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `expect` without any lints has no effect + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:7:1 + | +LL | #[warn(reason = "This should be warn by default")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `warn` without any lints has no effect + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:8:1 + | +LL | #[deny(reason = "All listed lints are denied")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `deny` without any lints has no effect + +error: unused attribute + --> $DIR/lint-attribute-only-with-reason.rs:9:1 + | +LL | #[forbid(reason = "Just some reason")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `forbid` without any lints has no effect + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs new file mode 100644 index 000000000..98080b4e8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(lint_reasons)] +#![warn(unused)] + +#[warn(unused_variables)] +#[expect(unused_variables)] +//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] +//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default +#[allow(unused_variables)] +#[expect(unused_variables)] // Only this expectation will be fulfilled +fn main() { + let x = 2; +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr new file mode 100644 index 000000000..df7d6584f --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/multiple_expect_attrs.stderr @@ -0,0 +1,10 @@ +warning: this lint expectation is unfulfilled + --> $DIR/multiple_expect_attrs.rs:7:10 + | +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs new file mode 100644 index 000000000..2b6c3c6a1 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs @@ -0,0 +1,16 @@ +// This ensures that ICEs like rust#94953 don't happen +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(lint_reasons)] + +// This `expect` will create an expectation with an unstable expectation id +#[expect(while_true)] +fn create_early_lint_pass_expectation() { + // `while_true` is an early lint + while true {} +} + +fn main() { + create_early_lint_pass_expectation(); +} diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout new file mode 100644 index 000000000..0ee3a03c3 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout @@ -0,0 +1,20 @@ +#![feature(prelude_import)] +#![no_std] +// This ensures that ICEs like rust#94953 don't happen +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(lint_reasons)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +// This `expect` will create an expectation with an unstable expectation id +#[expect(while_true)] +fn create_early_lint_pass_expectation() { + // `while_true` is an early lint + while true {} +} + +fn main() { create_early_lint_pass_expectation(); } diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs new file mode 100644 index 000000000..e7da825ae --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs @@ -0,0 +1,16 @@ +#![deny(confusable_idents)] +#![allow(uncommon_codepoints, non_upper_case_globals)] + +const s: usize = 42; +const s_s: usize = 42; + +fn main() { + let s = "rust"; //~ ERROR identifier pair considered confusable + let s_s = "rust2"; //~ ERROR identifier pair considered confusable + not_affected(); +} + +fn not_affected() { + let s1 = 1; + let sl = 'l'; +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr new file mode 100644 index 000000000..e9906c83d --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.stderr @@ -0,0 +1,26 @@ +error: identifier pair considered confusable between `s` and `s` + --> $DIR/lint-confusable-idents.rs:8:9 + | +LL | const s: usize = 42; + | -- this is where the previous identifier occurred +... +LL | let s = "rust"; + | ^ + | +note: the lint level is defined here + --> $DIR/lint-confusable-idents.rs:1:9 + | +LL | #![deny(confusable_idents)] + | ^^^^^^^^^^^^^^^^^ + +error: identifier pair considered confusable between `s_s` and `s_s` + --> $DIR/lint-confusable-idents.rs:9:9 + | +LL | const s_s: usize = 42; + | --- this is where the previous identifier occurred +... +LL | let s_s = "rust2"; + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs new file mode 100644 index 000000000..f62c8a190 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables-2.rs @@ -0,0 +1,19 @@ +// check-pass +#![deny(mixed_script_confusables)] + +struct ΑctuallyNotLatin; + +fn main() { + let λ = 42; // this usage of Greek confirms that Greek is used intentionally. +} + +mod роре { + const エ: &'static str = "アイウ"; + + // this usage of Katakana confirms that Katakana is used intentionally. + fn ニャン() { + let д: usize = 100; // this usage of Cyrillic confirms that Cyrillic is used intentionally. + + println!("meow!"); + } +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs new file mode 100644 index 000000000..9d837d41f --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.rs @@ -0,0 +1,14 @@ +#![deny(mixed_script_confusables)] + +struct ΑctuallyNotLatin; +//~^ ERROR the usage of Script Group `Greek` in this crate consists solely of + +fn main() { + let v = ΑctuallyNotLatin; +} + +mod роре { +//~^ ERROR the usage of Script Group `Cyrillic` in this crate consists solely of + const エ: &'static str = "アイウ"; + //~^ ERROR the usage of Script Group `Japanese, Katakana` in this crate consists solely of +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr new file mode 100644 index 000000000..884a4a453 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr @@ -0,0 +1,34 @@ +error: the usage of Script Group `Greek` in this crate consists solely of mixed script confusables + --> $DIR/lint-mixed-script-confusables.rs:3:8 + | +LL | struct ΑctuallyNotLatin; + | ^^^^^^^^^^^^^^^^ + | + = note: the usage includes 'Α' (U+0391) + = note: please recheck to make sure their usages are indeed what you want +note: the lint level is defined here + --> $DIR/lint-mixed-script-confusables.rs:1:9 + | +LL | #![deny(mixed_script_confusables)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables + --> $DIR/lint-mixed-script-confusables.rs:10:5 + | +LL | mod роре { + | ^^^^ + | + = note: the usage includes 'е' (U+0435), 'о' (U+043E), 'Ñ€' (U+0440) + = note: please recheck to make sure their usages are indeed what you want + +error: the usage of Script Group `Japanese, Katakana` in this crate consists solely of mixed script confusables + --> $DIR/lint-mixed-script-confusables.rs:12:11 + | +LL | const エ: &'static str = "アイウ"; + | ^^ + | + = note: the usage includes 'エ' (U+30A8) + = note: please recheck to make sure their usages are indeed what you want + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs new file mode 100644 index 000000000..8ae174409 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.rs @@ -0,0 +1,12 @@ +#![deny(non_ascii_idents)] + +const חלודה: usize = 2; //~ ERROR identifier contains non-ASCII characters + +fn coöperation() {} //~ ERROR identifier contains non-ASCII characters + +fn main() { + let naïveté = 2; //~ ERROR identifier contains non-ASCII characters + + // using the same identifier the second time won't trigger the lint. + println!("{}", naïveté); +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr new file mode 100644 index 000000000..8ed7f093c --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-non-ascii-idents.stderr @@ -0,0 +1,26 @@ +error: identifier contains non-ASCII characters + --> $DIR/lint-non-ascii-idents.rs:3:7 + | +LL | const חלודה: usize = 2; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-non-ascii-idents.rs:1:9 + | +LL | #![deny(non_ascii_idents)] + | ^^^^^^^^^^^^^^^^ + +error: identifier contains non-ASCII characters + --> $DIR/lint-non-ascii-idents.rs:5:4 + | +LL | fn coöperation() {} + | ^^^^^^^^^^^ + +error: identifier contains non-ASCII characters + --> $DIR/lint-non-ascii-idents.rs:8:9 + | +LL | let naïveté = 2; + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs new file mode 100644 index 000000000..ed8e7dddd --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs @@ -0,0 +1,13 @@ +#![deny(uncommon_codepoints)] + +const µ: f64 = 0.000001; //~ ERROR identifier contains uncommon Unicode codepoints +//~| WARNING should have an upper case name + +fn dijkstra() {} //~ ERROR identifier contains uncommon Unicode codepoints + +fn main() { + let ㇻㇲㇳ = "rust"; //~ ERROR identifier contains uncommon Unicode codepoints + + // using the same identifier the second time won't trigger the lint. + println!("{}", ㇻㇲㇳ); +} diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr new file mode 100644 index 000000000..0533da030 --- /dev/null +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.stderr @@ -0,0 +1,34 @@ +error: identifier contains uncommon Unicode codepoints + --> $DIR/lint-uncommon-codepoints.rs:3:7 + | +LL | const µ: f64 = 0.000001; + | ^ + | +note: the lint level is defined here + --> $DIR/lint-uncommon-codepoints.rs:1:9 + | +LL | #![deny(uncommon_codepoints)] + | ^^^^^^^^^^^^^^^^^^^ + +error: identifier contains uncommon Unicode codepoints + --> $DIR/lint-uncommon-codepoints.rs:6:4 + | +LL | fn dijkstra() {} + | ^^^^^^^ + +error: identifier contains uncommon Unicode codepoints + --> $DIR/lint-uncommon-codepoints.rs:9:9 + | +LL | let ㇻㇲㇳ = "rust"; + | ^^^^^^ + +warning: constant `µ` should have an upper case name + --> $DIR/lint-uncommon-codepoints.rs:3:7 + | +LL | const µ: f64 = 0.000001; + | ^ help: convert the identifier to upper case: `Îœ` + | + = note: `#[warn(non_upper_case_globals)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/tests/ui/lint/rustdoc-group.rs b/tests/ui/lint/rustdoc-group.rs new file mode 100644 index 000000000..130abe425 --- /dev/null +++ b/tests/ui/lint/rustdoc-group.rs @@ -0,0 +1,5 @@ +// check-pass +// compile-flags: --crate-type lib +#![deny(rustdoc)] +//~^ WARNING removed: use `rustdoc::all` +#![deny(rustdoc::all)] // has no effect when run with rustc directly diff --git a/tests/ui/lint/rustdoc-group.stderr b/tests/ui/lint/rustdoc-group.stderr new file mode 100644 index 000000000..fddc863ae --- /dev/null +++ b/tests/ui/lint/rustdoc-group.stderr @@ -0,0 +1,10 @@ +warning: lint `rustdoc` has been removed: use `rustdoc::all` instead + --> $DIR/rustdoc-group.rs:3:9 + | +LL | #![deny(rustdoc)] + | ^^^^^^^ + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/rustdoc-renamed.rs b/tests/ui/lint/rustdoc-renamed.rs new file mode 100644 index 000000000..ecd6155b7 --- /dev/null +++ b/tests/ui/lint/rustdoc-renamed.rs @@ -0,0 +1,15 @@ +#![crate_type = "lib"] + +#![deny(unknown_lints)] +#![deny(renamed_and_removed_lints)] +//~^ NOTE lint level is defined + +// both allowed, since the compiler doesn't yet know what rustdoc lints are valid +#![deny(rustdoc::x)] +#![deny(rustdoc::intra_doc_link_resolution_failure)] + +#![deny(intra_doc_link_resolution_failure)] +//~^ ERROR removed: use `rustdoc::broken_intra_doc_links` +#![deny(non_autolinks)] +// FIXME: the old names for rustdoc lints should warn by default once `rustdoc::` makes it to the +// stable channel. diff --git a/tests/ui/lint/rustdoc-renamed.stderr b/tests/ui/lint/rustdoc-renamed.stderr new file mode 100644 index 000000000..096e867aa --- /dev/null +++ b/tests/ui/lint/rustdoc-renamed.stderr @@ -0,0 +1,14 @@ +error: lint `intra_doc_link_resolution_failure` has been removed: use `rustdoc::broken_intra_doc_links` instead + --> $DIR/rustdoc-renamed.rs:11:9 + | +LL | #![deny(intra_doc_link_resolution_failure)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/rustdoc-renamed.rs:4:9 + | +LL | #![deny(renamed_and_removed_lints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs new file mode 100644 index 000000000..781391cc5 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/auxiliary/foreign-crate.rs @@ -0,0 +1,4 @@ +#[macro_export] +macro_rules! my_macro { + () => { true; } +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs new file mode 100644 index 000000000..374506366 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.rs @@ -0,0 +1,9 @@ +// aux-build:foreign-crate.rs +// check-pass + +extern crate foreign_crate; + +// Test that we do not lint for a macro in a foreign crate +fn main() { + let _ = foreign_crate::my_macro!(); +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs new file mode 100644 index 000000000..fff380934 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs @@ -0,0 +1,51 @@ +// check-pass +// edition:2018 +#![feature(stmt_expr_attributes)] +#![warn(semicolon_in_expressions_from_macros)] + +#[allow(dead_code)] +macro_rules! foo { + ($val:ident) => { + true; //~ WARN trailing semicolon in macro + //~| WARN this was previously accepted + //~| WARN trailing semicolon in macro + //~| WARN this was previously accepted + //~| WARN trailing semicolon in macro + //~| WARN this was previously accepted + } +} + +#[allow(semicolon_in_expressions_from_macros)] +async fn bar() { + foo!(first); +} + +fn main() { + #[allow(semicolon_in_expressions_from_macros)] + let _ = { + foo!(first) + }; + + #[allow(semicolon_in_expressions_from_macros)] + let _ = foo!(second); + + #[allow(semicolon_in_expressions_from_macros)] + fn inner() { + let _ = foo!(third); + } + + #[allow(semicolon_in_expressions_from_macros)] + async { + let _ = foo!(fourth); + }; + + let _ = { + foo!(warn_in_block) + }; + + let _ = foo!(warn_in_expr); + + // This `#[allow]` does not work, since the attribute gets dropped + // when we expand the macro + let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr new file mode 100644 index 000000000..c60120061 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr @@ -0,0 +1,185 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | foo!(warn_in_block) + | ------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(warn_in_expr); + | ------------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ------------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 3 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | foo!(first) + | ----------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:24:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(second); + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:29:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(third); + | ----------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:32:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(fourth); + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:37:13 + | +LL | #[allow(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | foo!(warn_in_block) + | ------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = foo!(warn_in_expr); + | ------------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 + | +LL | true; + | ^ +... +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ------------------------- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/semicolon-in-expressions-from-macros.rs:4:9 + | +LL | #![warn(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs new file mode 100644 index 000000000..2c63311e6 --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.rs @@ -0,0 +1,16 @@ +// check-pass +// Ensure that trailing semicolons cause warnings by default + +macro_rules! foo { + () => { + true; //~ WARN trailing semicolon in macro + //~| WARN this was previously + } +} + +fn main() { + let _val = match true { + true => false, + _ => foo!() + }; +} diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr new file mode 100644 index 000000000..0fec4996f --- /dev/null +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr @@ -0,0 +1,31 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13 + | +LL | true; + | ^ +... +LL | _ => foo!() + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13 + | +LL | true; + | ^ +... +LL | _ => foo!() + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/lint/special-upper-lower-cases.rs b/tests/ui/lint/special-upper-lower-cases.rs new file mode 100644 index 000000000..761be61fa --- /dev/null +++ b/tests/ui/lint/special-upper-lower-cases.rs @@ -0,0 +1,23 @@ +// (#77273) These characters are in the general categories of +// "Uppercase/Lowercase Letter". +// The diagnostics don't provide meaningful suggestions for them +// as we cannot convert them properly. + +// check-pass + +#![allow(uncommon_codepoints, unused)] + +struct ð•Ÿð• ð•¥ð•’ð•”ð•’ð•žð•–ð•; +//~^ WARN: type `ð•Ÿð• ð•¥ð•’ð•”ð•’ð•žð•–ð•` should have an upper camel case name + +// FIXME: How we should handle this? +struct ð•Ÿð• ð•¥_ð•’_ð•”ð•’ð•žð•–ð•; +//~^ WARN: type `ð•Ÿð• ð•¥_ð•’_ð•”ð•’ð•žð•–ð•` should have an upper camel case name + +static ð—»ð—¼ð—»ð˜‚ð—½ð—½ð—²ð—¿ð—°ð—®ð˜€ð—²: i32 = 1; +//~^ WARN: static variable `ð—»ð—¼ð—»ð˜‚ð—½ð—½ð—²ð—¿ð—°ð—®ð˜€ð—²` should have an upper case name + +fn main() { + let ð“¢ð“ð“ð“ð“ð“ð“šð“”ð“¢ = 1; + //~^ WARN: variable `ð“¢ð“ð“ð“ð“ð“ð“šð“”ð“¢` should have a snake case name +} diff --git a/tests/ui/lint/special-upper-lower-cases.stderr b/tests/ui/lint/special-upper-lower-cases.stderr new file mode 100644 index 000000000..2aa13c33b --- /dev/null +++ b/tests/ui/lint/special-upper-lower-cases.stderr @@ -0,0 +1,32 @@ +warning: type `ð•Ÿð• ð•¥ð•’ð•”ð•’ð•žð•–ð•` should have an upper camel case name + --> $DIR/special-upper-lower-cases.rs:10:8 + | +LL | struct ð•Ÿð• ð•¥ð•’ð•”ð•’ð•žð•–ð•; + | ^^^^^^^^^ should have an UpperCamelCase name + | + = note: `#[warn(non_camel_case_types)]` on by default + +warning: type `ð•Ÿð• ð•¥_ð•’_ð•”ð•’ð•žð•–ð•` should have an upper camel case name + --> $DIR/special-upper-lower-cases.rs:14:8 + | +LL | struct ð•Ÿð• ð•¥_ð•’_ð•”ð•’ð•žð•–ð•; + | ^^^^^^^^^^^ should have an UpperCamelCase name + +warning: static variable `ð—»ð—¼ð—»ð˜‚ð—½ð—½ð—²ð—¿ð—°ð—®ð˜€ð—²` should have an upper case name + --> $DIR/special-upper-lower-cases.rs:17:8 + | +LL | static ð—»ð—¼ð—»ð˜‚ð—½ð—½ð—²ð—¿ð—°ð—®ð˜€ð—²: i32 = 1; + | ^^^^^^^^^^^^ should have an UPPER_CASE name + | + = note: `#[warn(non_upper_case_globals)]` on by default + +warning: variable `ð“¢ð“ð“ð“ð“ð“ð“šð“”ð“¢` should have a snake case name + --> $DIR/special-upper-lower-cases.rs:21:9 + | +LL | let ð“¢ð“ð“ð“ð“ð“ð“šð“”ð“¢ = 1; + | ^^^^^^^^^ should have a snake_case name + | + = note: `#[warn(non_snake_case)]` on by default + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/suggestions.fixed b/tests/ui/lint/suggestions.fixed new file mode 100644 index 000000000..35851690b --- /dev/null +++ b/tests/ui/lint/suggestions.fixed @@ -0,0 +1,66 @@ +// ignore-tidy-tab +// run-rustfix + +#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + +#[no_mangle] pub static DISCOVERY: usize = 1; +//~^ ERROR const items should never be `#[no_mangle]` +//~| HELP try a static value + + +//~^ HELP remove this attribute +pub fn defiant(_t: T) {} +//~^ WARN functions generic over types or consts must be mangled + +#[no_mangle] +fn rio_grande() {} + +mod badlands { + // The private-no-mangle lints shouldn't suggest inserting `pub` when the + // item is already `pub` (but triggered the lint because, e.g., it's in a + // private module). (Issue #47383) + #[no_mangle] pub static DAUNTLESS: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + pub fn val_jean() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute + + // ... but we can suggest just-`pub` instead of restricted + #[no_mangle] pub static VETAR: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + pub(crate) fn crossfield() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute +} + +struct Equinox { + warp_factor: f32, +} + +fn main() { + loop { + //~^ WARN denote infinite loops + //~| HELP use `loop` + let registry_no = format!("NX-{}", 74205); + //~^ WARN does not need to be mutable + //~| HELP remove this `mut` + //~| WARN unnecessary parentheses + //~| HELP remove these parentheses + // the line after `mut` has a `\t` at the beginning, this is on purpose + let b = 1; + //~^^ WARN does not need to be mutable + //~| HELP remove this `mut` + let d = Equinox { warp_factor: 9.975 }; + match d { + #[allow(unused_variables)] // for rustfix + Equinox { warp_factor } => {} + //~^ WARN this pattern is redundant + //~| HELP use shorthand field pattern + } + println!("{} {}", registry_no, b); + } +} diff --git a/tests/ui/lint/suggestions.rs b/tests/ui/lint/suggestions.rs new file mode 100644 index 000000000..be6f0d6b3 --- /dev/null +++ b/tests/ui/lint/suggestions.rs @@ -0,0 +1,67 @@ +// ignore-tidy-tab +// run-rustfix + +#![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + +#[no_mangle] const DISCOVERY: usize = 1; +//~^ ERROR const items should never be `#[no_mangle]` +//~| HELP try a static value + +#[no_mangle] +//~^ HELP remove this attribute +pub fn defiant(_t: T) {} +//~^ WARN functions generic over types or consts must be mangled + +#[no_mangle] +fn rio_grande() {} + +mod badlands { + // The private-no-mangle lints shouldn't suggest inserting `pub` when the + // item is already `pub` (but triggered the lint because, e.g., it's in a + // private module). (Issue #47383) + #[no_mangle] pub const DAUNTLESS: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + #[no_mangle] pub fn val_jean() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute + + // ... but we can suggest just-`pub` instead of restricted + #[no_mangle] pub(crate) const VETAR: bool = true; + //~^ ERROR const items should never be `#[no_mangle]` + //~| HELP try a static value + #[allow(dead_code)] // for rustfix + #[no_mangle] pub(crate) fn crossfield() {} + //~^ WARN functions generic over types or consts must be mangled + //~| HELP remove this attribute +} + +struct Equinox { + warp_factor: f32, +} + +fn main() { + while true { + //~^ WARN denote infinite loops + //~| HELP use `loop` + let mut registry_no = (format!("NX-{}", 74205)); + //~^ WARN does not need to be mutable + //~| HELP remove this `mut` + //~| WARN unnecessary parentheses + //~| HELP remove these parentheses + // the line after `mut` has a `\t` at the beginning, this is on purpose + let mut + b = 1; + //~^^ WARN does not need to be mutable + //~| HELP remove this `mut` + let d = Equinox { warp_factor: 9.975 }; + match d { + #[allow(unused_variables)] // for rustfix + Equinox { warp_factor: warp_factor } => {} + //~^ WARN this pattern is redundant + //~| HELP use shorthand field pattern + } + println!("{} {}", registry_no, b); + } +} diff --git a/tests/ui/lint/suggestions.stderr b/tests/ui/lint/suggestions.stderr new file mode 100644 index 000000000..4caee777a --- /dev/null +++ b/tests/ui/lint/suggestions.stderr @@ -0,0 +1,114 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/suggestions.rs:45:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: unnecessary parentheses around assigned value + --> $DIR/suggestions.rs:48:31 + | +LL | let mut registry_no = (format!("NX-{}", 74205)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/suggestions.rs:4:21 + | +LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let mut registry_no = (format!("NX-{}", 74205)); +LL + let mut registry_no = format!("NX-{}", 74205); + | + +warning: variable does not need to be mutable + --> $DIR/suggestions.rs:48:13 + | +LL | let mut registry_no = (format!("NX-{}", 74205)); + | ----^^^^^^^^^^^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/suggestions.rs:4:9 + | +LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 + | ^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/suggestions.rs:54:13 + | +LL | let mut + | ______________^ + | | _____________| + | || +LL | || b = 1; + | ||____________-^ + | |_____________| + | help: remove this `mut` + +error: const items should never be `#[no_mangle]` + --> $DIR/suggestions.rs:6:14 + | +LL | #[no_mangle] const DISCOVERY: usize = 1; + | -----^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | + = note: `#[deny(no_mangle_const_items)]` on by default + +warning: functions generic over types or consts must be mangled + --> $DIR/suggestions.rs:12:1 + | +LL | #[no_mangle] + | ------------ help: remove this attribute +LL | +LL | pub fn defiant(_t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(no_mangle_generic_items)]` on by default + +warning: the `warp_factor:` in this pattern is redundant + --> $DIR/suggestions.rs:61:23 + | +LL | Equinox { warp_factor: warp_factor } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use shorthand field pattern: `warp_factor` + | + = note: `#[warn(non_shorthand_field_patterns)]` on by default + +error: const items should never be `#[no_mangle]` + --> $DIR/suggestions.rs:22:18 + | +LL | #[no_mangle] pub const DAUNTLESS: bool = true; + | ---------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + +warning: functions generic over types or consts must be mangled + --> $DIR/suggestions.rs:26:18 + | +LL | #[no_mangle] pub fn val_jean() {} + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this attribute + +error: const items should never be `#[no_mangle]` + --> $DIR/suggestions.rs:31:18 + | +LL | #[no_mangle] pub(crate) const VETAR: bool = true; + | ----------------^^^^^^^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + +warning: functions generic over types or consts must be mangled + --> $DIR/suggestions.rs:35:18 + | +LL | #[no_mangle] pub(crate) fn crossfield() {} + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this attribute + +error: aborting due to 3 previous errors; 8 warnings emitted + diff --git a/tests/ui/lint/test-allow-dead-extern-static-no-warning.rs b/tests/ui/lint/test-allow-dead-extern-static-no-warning.rs new file mode 100644 index 000000000..2583e431e --- /dev/null +++ b/tests/ui/lint/test-allow-dead-extern-static-no-warning.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags: --test + +#![deny(dead_code)] + +extern "C" { + #[allow(dead_code)] + static Qt: u64; +} + +fn main() {} diff --git a/tests/ui/lint/test-inner-fn.rs b/tests/ui/lint/test-inner-fn.rs new file mode 100644 index 000000000..d419cc6fa --- /dev/null +++ b/tests/ui/lint/test-inner-fn.rs @@ -0,0 +1,19 @@ +// compile-flags: --test -D unnameable_test_items + +#[test] +fn foo() { + #[test] //~ ERROR cannot test inner items [unnameable_test_items] + fn bar() {} + bar(); +} + +mod x { + #[test] + fn foo() { + #[test] //~ ERROR cannot test inner items [unnameable_test_items] + fn bar() {} + bar(); + } +} + +fn main() {} diff --git a/tests/ui/lint/test-inner-fn.stderr b/tests/ui/lint/test-inner-fn.stderr new file mode 100644 index 000000000..7a32bc86b --- /dev/null +++ b/tests/ui/lint/test-inner-fn.stderr @@ -0,0 +1,19 @@ +error: cannot test inner items + --> $DIR/test-inner-fn.rs:5:5 + | +LL | #[test] + | ^^^^^^^ + | + = note: requested on the command line with `-D unnameable-test-items` + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot test inner items + --> $DIR/test-inner-fn.rs:13:9 + | +LL | #[test] + | ^^^^^^^ + | + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/trivial-cast-ice.rs b/tests/ui/lint/trivial-cast-ice.rs new file mode 100644 index 000000000..f781fab22 --- /dev/null +++ b/tests/ui/lint/trivial-cast-ice.rs @@ -0,0 +1,12 @@ +// aux-build:trivial-cast-ice.rs +// check-pass + +// Demonstrates the ICE in #102561 + +#![deny(trivial_casts)] + +extern crate trivial_cast_ice; + +fn main() { + trivial_cast_ice::foo!(); +} diff --git a/tests/ui/lint/trivial-casts-featuring-type-ascription.rs b/tests/ui/lint/trivial-casts-featuring-type-ascription.rs new file mode 100644 index 000000000..96bf2dcfb --- /dev/null +++ b/tests/ui/lint/trivial-casts-featuring-type-ascription.rs @@ -0,0 +1,10 @@ +#![deny(trivial_casts, trivial_numeric_casts)] +#![feature(type_ascription)] + +fn main() { + let lugubrious = 12i32 as i32; + //~^ ERROR trivial numeric cast + let haunted: &u32 = &99; + let _ = haunted as *const u32; + //~^ ERROR trivial cast +} diff --git a/tests/ui/lint/trivial-casts-featuring-type-ascription.stderr b/tests/ui/lint/trivial-casts-featuring-type-ascription.stderr new file mode 100644 index 000000000..5087807b6 --- /dev/null +++ b/tests/ui/lint/trivial-casts-featuring-type-ascription.stderr @@ -0,0 +1,28 @@ +error: trivial numeric cast: `i32` as `i32` + --> $DIR/trivial-casts-featuring-type-ascription.rs:5:22 + | +LL | let lugubrious = 12i32 as i32; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require type ascription or a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts-featuring-type-ascription.rs:1:24 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: trivial cast: `&u32` as `*const u32` + --> $DIR/trivial-casts-featuring-type-ascription.rs:8:13 + | +LL | let _ = haunted as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require type ascription or a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts-featuring-type-ascription.rs:1:9 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/trivial-casts.rs b/tests/ui/lint/trivial-casts.rs new file mode 100644 index 000000000..b17de624a --- /dev/null +++ b/tests/ui/lint/trivial-casts.rs @@ -0,0 +1,9 @@ +#![deny(trivial_casts, trivial_numeric_casts)] + +fn main() { + let lugubrious = 12i32 as i32; + //~^ ERROR trivial numeric cast + let haunted: &u32 = &99; + let _ = haunted as *const u32; + //~^ ERROR trivial cast +} diff --git a/tests/ui/lint/trivial-casts.stderr b/tests/ui/lint/trivial-casts.stderr new file mode 100644 index 000000000..7ace353de --- /dev/null +++ b/tests/ui/lint/trivial-casts.stderr @@ -0,0 +1,28 @@ +error: trivial numeric cast: `i32` as `i32` + --> $DIR/trivial-casts.rs:4:22 + | +LL | let lugubrious = 12i32 as i32; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts.rs:1:24 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: trivial cast: `&u32` as `*const u32` + --> $DIR/trivial-casts.rs:7:13 + | +LL | let _ = haunted as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial-casts.rs:1:9 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/trivial_casts.rs b/tests/ui/lint/trivial_casts.rs new file mode 100644 index 000000000..0a8b9de1d --- /dev/null +++ b/tests/ui/lint/trivial_casts.rs @@ -0,0 +1,85 @@ +// Test the trivial_casts and trivial_numeric_casts lints. For each error we also +// check that the cast can be done using just coercion. + +#![deny(trivial_casts, trivial_numeric_casts)] + +trait Foo { + fn foo(&self) {} +} + +pub struct Bar; + +impl Foo for Bar {} + +pub fn main() { + // Numeric + let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32` + let _: i32 = 42_i32; + + let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8` + let _: u8 = 42_u8; + + // & to * pointers + let x: &u32 = &42; + let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32` + let _: *const u32 = x; + + let x: &mut u32 = &mut 42; + let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32` + let _: *mut u32 = x; + + // unsize array + let x: &[u32; 3] = &[42, 43, 44]; + let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]` + let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]` + let _: &[u32] = x; + let _: *const [u32] = x; + + let x: &mut [u32; 3] = &mut [42, 43, 44]; + let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]` + let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]` + let _: &mut [u32] = x; + let _: *mut [u32] = x; + + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _ = x as Box<[u32]>; + //~^ ERROR trivial cast: `Box<[u32; 3]>` as `Box<[u32]>` + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _: Box<[u32]> = x; + + // unsize trait + let x: &Bar = &Bar; + let _ = x as &dyn Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo` + let _ = x as *const dyn Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo` + let _: &dyn Foo = x; + let _: *const dyn Foo = x; + + let x: &mut Bar = &mut Bar; + let _ = x as &mut dyn Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo` + let _ = x as *mut dyn Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo` + let _: &mut dyn Foo = x; + let _: *mut dyn Foo = x; + + let x: Box = Box::new(Bar); + let _ = x as Box; //~ERROR `Box` as `Box` + let x: Box = Box::new(Bar); + let _: Box = x; + + // functions + fn baz(_x: i32) {} + let _ = &baz as &dyn Fn(i32); //~ERROR `&fn(i32) {baz}` as `&dyn Fn(i32)` + let _: &dyn Fn(i32) = &baz; + let x = |_x: i32| {}; + let _ = &x as &dyn Fn(i32); //~ERROR trivial cast + let _: &dyn Fn(i32) = &x; +} + +// subtyping +pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) { + let _ = a as &'a Bar; //~ERROR trivial cast + let _: &'a Bar = a; + let _ = b as &'a Bar; //~ERROR trivial cast + let _: &'a Bar = b; + let _ = b as &'b Bar; //~ERROR trivial cast + let _: &'b Bar = b; +} diff --git a/tests/ui/lint/trivial_casts.stderr b/tests/ui/lint/trivial_casts.stderr new file mode 100644 index 000000000..74f962835 --- /dev/null +++ b/tests/ui/lint/trivial_casts.stderr @@ -0,0 +1,164 @@ +error: trivial numeric cast: `i32` as `i32` + --> $DIR/trivial_casts.rs:16:13 + | +LL | let _ = 42_i32 as i32; + | ^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial_casts.rs:4:24 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: trivial numeric cast: `u8` as `u8` + --> $DIR/trivial_casts.rs:19:13 + | +LL | let _ = 42_u8 as u8; + | ^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&u32` as `*const u32` + --> $DIR/trivial_casts.rs:24:13 + | +LL | let _ = x as *const u32; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable +note: the lint level is defined here + --> $DIR/trivial_casts.rs:4:9 + | +LL | #![deny(trivial_casts, trivial_numeric_casts)] + | ^^^^^^^^^^^^^ + +error: trivial cast: `&mut u32` as `*mut u32` + --> $DIR/trivial_casts.rs:28:13 + | +LL | let _ = x as *mut u32; + | ^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&[u32; 3]` as `&[u32]` + --> $DIR/trivial_casts.rs:33:13 + | +LL | let _ = x as &[u32]; + | ^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&[u32; 3]` as `*const [u32]` + --> $DIR/trivial_casts.rs:34:13 + | +LL | let _ = x as *const [u32]; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut [u32; 3]` as `&mut [u32]` + --> $DIR/trivial_casts.rs:39:13 + | +LL | let _ = x as &mut [u32]; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut [u32; 3]` as `*mut [u32]` + --> $DIR/trivial_casts.rs:40:13 + | +LL | let _ = x as *mut [u32]; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `Box<[u32; 3]>` as `Box<[u32]>` + --> $DIR/trivial_casts.rs:45:13 + | +LL | let _ = x as Box<[u32]>; + | ^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&Bar` as `&dyn Foo` + --> $DIR/trivial_casts.rs:52:13 + | +LL | let _ = x as &dyn Foo; + | ^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&Bar` as `*const dyn Foo` + --> $DIR/trivial_casts.rs:53:13 + | +LL | let _ = x as *const dyn Foo; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut Bar` as `&mut dyn Foo` + --> $DIR/trivial_casts.rs:58:13 + | +LL | let _ = x as &mut dyn Foo; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&mut Bar` as `*mut dyn Foo` + --> $DIR/trivial_casts.rs:59:13 + | +LL | let _ = x as *mut dyn Foo; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `Box` as `Box` + --> $DIR/trivial_casts.rs:64:13 + | +LL | let _ = x as Box; + | ^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&fn(i32) {baz}` as `&dyn Fn(i32)` + --> $DIR/trivial_casts.rs:70:13 + | +LL | let _ = &baz as &dyn Fn(i32); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&[closure@$DIR/trivial_casts.rs:72:13: 72:22]` as `&dyn Fn(i32)` + --> $DIR/trivial_casts.rs:73:13 + | +LL | let _ = &x as &dyn Fn(i32); + | ^^^^^^^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&'a Bar` as `&'a Bar` + --> $DIR/trivial_casts.rs:79:13 + | +LL | let _ = a as &'a Bar; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&'b Bar` as `&'a Bar` + --> $DIR/trivial_casts.rs:81:13 + | +LL | let _ = b as &'a Bar; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: trivial cast: `&'b Bar` as `&'b Bar` + --> $DIR/trivial_casts.rs:83:13 + | +LL | let _ = b as &'b Bar; + | ^^^^^^^^^^^^ + | + = help: cast can be replaced by coercion; this might require a temporary variable + +error: aborting due to 19 previous errors + diff --git a/tests/ui/lint/type-overflow.rs b/tests/ui/lint/type-overflow.rs new file mode 100644 index 000000000..6234b794c --- /dev/null +++ b/tests/ui/lint/type-overflow.rs @@ -0,0 +1,22 @@ +// check-pass +#![warn(overflowing_literals)] + +fn main() { + let error = 255i8; //~WARNING literal out of range for `i8` + + let ok = 0b1000_0001; // should be ok -> i32 + let ok = 0b0111_1111i8; // should be ok -> 127i8 + + let fail = 0b1000_0001i8; //~WARNING literal out of range for `i8` + + let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for `i64` + + let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for `u32` + + let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + //~^ WARNING literal out of range for `i128` + + let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for `i32` + + let fail = -0b1111_1111i8; //~WARNING literal out of range for `i8` +} diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr new file mode 100644 index 000000000..62cb1f7f4 --- /dev/null +++ b/tests/ui/lint/type-overflow.stderr @@ -0,0 +1,67 @@ +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:5:17 + | +LL | let error = 255i8; + | ^^^^^ + | + = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u8` instead +note: the lint level is defined here + --> $DIR/type-overflow.rs:2:9 + | +LL | #![warn(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:10:16 + | +LL | let fail = 0b1000_0001i8; + | ^^^^^^^^^^^^^ help: consider using the type `u8` instead: `0b1000_0001u8` + | + = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8` + +warning: literal out of range for `i64` + --> $DIR/type-overflow.rs:12:16 + | +LL | let fail = 0x8000_0000_0000_0000i64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x8000_0000_0000_0000u64` + | + = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64` + +warning: literal out of range for `u32` + --> $DIR/type-overflow.rs:14:16 + | +LL | let fail = 0x1_FFFF_FFFFu32; + | ^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x1_FFFF_FFFFu64` + | + = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32` + +warning: literal out of range for `i128` + --> $DIR/type-overflow.rs:16:22 + | +LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128` + = help: consider using the type `u128` instead + +warning: literal out of range for `i32` + --> $DIR/type-overflow.rs:19:16 + | +LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32` + = help: consider using the type `i128` instead + +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:21:17 + | +LL | let fail = -0b1111_1111i8; + | ^^^^^^^^^^^^^ help: consider using the type `i16` instead: `0b1111_1111i16` + | + = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` + = note: and the value `-0b1111_1111i8` will become `1i8` + +warning: 7 warnings emitted + diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs new file mode 100644 index 000000000..e547f031a --- /dev/null +++ b/tests/ui/lint/unaligned_references.rs @@ -0,0 +1,103 @@ +#![deny(unaligned_references)] + +#[repr(packed)] +pub struct Good { + data: u64, + ptr: &'static u64, + data2: [u64; 2], + aligned: [u8; 32], +} + +#[repr(packed(2))] +pub struct Packed2 { + x: u32, + y: u16, + z: u8, +} + +fn main() { + unsafe { + let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; + + let _ = &good.ptr; //~ ERROR reference to packed field + //~^ previously accepted + let _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted + // Error even when turned into raw pointer immediately. + let _ = &good.data as *const _; //~ ERROR reference to packed field + //~^ previously accepted + let _: *const _ = &good.data; //~ ERROR reference to packed field + //~^ previously accepted + // Error on method call. + let _ = good.data.clone(); //~ ERROR reference to packed field + //~^ previously accepted + // Error for nested fields. + let _ = &good.data2[0]; //~ ERROR reference to packed field + //~^ previously accepted + + let _ = &*good.ptr; // ok, behind a pointer + let _ = &good.aligned; // ok, has align 1 + let _ = &good.aligned[2]; // ok, has align 1 + } + + unsafe { + let packed2 = Packed2 { x: 0, y: 0, z: 0 }; + let _ = &packed2.x; //~ ERROR reference to packed field + //~^ previously accepted + let _ = &packed2.y; // ok, has align 2 in packed(2) struct + let _ = &packed2.z; // ok, has align 1 + } + + unsafe { + struct U16(u16); + + impl Drop for U16 { + fn drop(&mut self) { + println!("{:p}", self); + } + } + + struct HasDrop; + + impl Drop for HasDrop { + fn drop(&mut self) {} + } + + #[allow(unused)] + struct Wrapper { + a: U16, + b: HasDrop, + } + #[allow(unused)] + #[repr(packed(2))] + struct Wrapper2 { + a: U16, + b: HasDrop, + } + + // An outer struct with more restrictive packing than the inner struct -- make sure we + // notice that! + #[repr(packed)] + struct Misalign(u8, T); + + let m1 = Misalign( + 0, + Wrapper { + a: U16(10), + b: HasDrop, + }, + ); + let _ref = &m1.1.a; //~ ERROR reference to packed field + //~^ previously accepted + + let m2 = Misalign( + 0, + Wrapper2 { + a: U16(10), + b: HasDrop, + }, + ); + let _ref = &m2.1.a; //~ ERROR reference to packed field + //~^ previously accepted + } +} diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.stderr new file mode 100644 index 000000000..346f49b92 --- /dev/null +++ b/tests/ui/lint/unaligned_references.stderr @@ -0,0 +1,259 @@ +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:22:17 + | +LL | let _ = &good.ptr; + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:24:17 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:27:17 + | +LL | let _ = &good.data as *const _; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:29:27 + | +LL | let _: *const _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:32:17 + | +LL | let _ = good.data.clone(); + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:35:17 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:45:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:90:20 + | +LL | let _ref = &m1.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:100:20 + | +LL | let _ref = &m2.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: aborting due to 9 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:22:17 + | +LL | let _ = &good.ptr; + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:24:17 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:27:17 + | +LL | let _ = &good.data as *const _; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:29:27 + | +LL | let _: *const _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:32:17 + | +LL | let _ = good.data.clone(); + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:35:17 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:45:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:90:20 + | +LL | let _ref = &m1.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:100:20 + | +LL | let _ref = &m2.1.a; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references.rs:1:9 + | +LL | #![deny(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/unaligned_references_external_macro.rs b/tests/ui/lint/unaligned_references_external_macro.rs new file mode 100644 index 000000000..cb597c38e --- /dev/null +++ b/tests/ui/lint/unaligned_references_external_macro.rs @@ -0,0 +1,13 @@ +// aux-build:unaligned_references_external_crate.rs + +extern crate unaligned_references_external_crate; + +unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned + //~^ previously accepted + #[repr(packed)] + pub struct X { + pub field: u16 + } +} + +fn main() {} diff --git a/tests/ui/lint/unaligned_references_external_macro.stderr b/tests/ui/lint/unaligned_references_external_macro.stderr new file mode 100644 index 000000000..c46ca6742 --- /dev/null +++ b/tests/ui/lint/unaligned_references_external_macro.stderr @@ -0,0 +1,61 @@ +error: reference to packed field is unaligned + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/unaligned_references_external_macro.rs:5:1 + | +LL | / unaligned_references_external_crate::mac! { +LL | | +LL | | #[repr(packed)] +LL | | pub struct X { +LL | | pub field: u16 +LL | | } +LL | | } + | |_^ + = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/lint/unnecessary-extern-crate.rs b/tests/ui/lint/unnecessary-extern-crate.rs new file mode 100644 index 000000000..af2bd84bd --- /dev/null +++ b/tests/ui/lint/unnecessary-extern-crate.rs @@ -0,0 +1,71 @@ +// edition:2018 + +#![deny(unused_extern_crates)] +#![feature(test, rustc_private)] + +extern crate libc; +//~^ ERROR unused extern crate +//~| HELP remove +extern crate libc as x; +//~^ ERROR unused extern crate +//~| HELP remove + +extern crate proc_macro; + +#[macro_use] +extern crate test; + +pub extern crate test as y; + +pub extern crate alloc; + +pub(crate) extern crate alloc as a; + +pub(crate) extern crate alloc as b; + +mod foo { + pub(in crate::foo) extern crate alloc as c; + + pub(super) extern crate alloc as d; + + extern crate libc; + //~^ ERROR unused extern crate + //~| HELP remove + + extern crate libc as x; + //~^ ERROR unused extern crate + //~| HELP remove + + pub extern crate test; + + pub extern crate test as y; + + mod bar { + extern crate libc; + //~^ ERROR unused extern crate + //~| HELP remove + + extern crate libc as x; + //~^ ERROR unused extern crate + //~| HELP remove + + pub(in crate::foo::bar) extern crate alloc as e; + + fn dummy() { + e::string::String::new(); + } + } + + fn dummy() { + c::string::String::new(); + d::string::String::new(); + } +} + + +fn main() { + a::string::String::new(); + b::string::String::new(); + + proc_macro::TokenStream::new(); +} diff --git a/tests/ui/lint/unnecessary-extern-crate.stderr b/tests/ui/lint/unnecessary-extern-crate.stderr new file mode 100644 index 000000000..14ba9d052 --- /dev/null +++ b/tests/ui/lint/unnecessary-extern-crate.stderr @@ -0,0 +1,44 @@ +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:6:1 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/unnecessary-extern-crate.rs:3:9 + | +LL | #![deny(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:9:1 + | +LL | extern crate libc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:31:5 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:35:5 + | +LL | extern crate libc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:44:9 + | +LL | extern crate libc; + | ^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:48:9 + | +LL | extern crate libc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unreachable-async-fn.rs b/tests/ui/lint/unreachable-async-fn.rs new file mode 100644 index 000000000..eedd877fe --- /dev/null +++ b/tests/ui/lint/unreachable-async-fn.rs @@ -0,0 +1,9 @@ +// check-pass +// edition:2018 + +#[allow(dead_code)] +async fn foo () { // unreachable lint doesn't trigger + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/lint/unreachable_pub.rs b/tests/ui/lint/unreachable_pub.rs new file mode 100644 index 000000000..a50467ce8 --- /dev/null +++ b/tests/ui/lint/unreachable_pub.rs @@ -0,0 +1,66 @@ +// check-pass + +#![allow(unused)] +#![warn(unreachable_pub)] + +mod private_mod { + // non-leaked `pub` items in private module should be linted + pub use std::fmt; //~ WARNING unreachable_pub + pub use std::env::{Args}; // braced-use has different item spans than unbraced + //~^ WARNING unreachable_pub + + pub struct Hydrogen { //~ WARNING unreachable_pub + // `pub` struct fields, too + pub neutrons: usize, //~ WARNING unreachable_pub + // (... but not more-restricted fields) + pub(crate) electrons: usize + } + impl Hydrogen { + // impls, too + pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub + pub(crate) fn count_electrons(&self) -> usize { self.electrons } + } + impl Clone for Hydrogen { + fn clone(&self) -> Hydrogen { + Hydrogen { neutrons: self.neutrons, electrons: self.electrons } + } + } + + pub enum Helium {} //~ WARNING unreachable_pub + pub union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub + pub fn beryllium() {} //~ WARNING unreachable_pub + pub trait Boron {} //~ WARNING unreachable_pub + pub const CARBON: usize = 1; //~ WARNING unreachable_pub + pub static NITROGEN: usize = 2; //~ WARNING unreachable_pub + pub type Oxygen = bool; //~ WARNING unreachable_pub + + macro_rules! define_empty_struct_with_visibility { + ($visibility: vis, $name: ident) => { $visibility struct $name {} } + //~^ WARNING unreachable_pub + } + define_empty_struct_with_visibility!(pub, Fluorine); + + extern "C" { + pub fn catalyze() -> bool; //~ WARNING unreachable_pub + } + + // items leaked through signatures (see `get_neon` below) are OK + pub struct Neon {} + + // crate-visible items are OK + pub(crate) struct Sodium {} +} + +pub mod public_mod { + // module is public: these are OK, too + pub struct Magnesium {} + pub(crate) struct Aluminum {} +} + +pub fn get_neon() -> private_mod::Neon { + private_mod::Neon {} +} + +fn main() { + let _ = get_neon(); +} diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr new file mode 100644 index 000000000..762834b97 --- /dev/null +++ b/tests/ui/lint/unreachable_pub.stderr @@ -0,0 +1,148 @@ +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:8:13 + | +LL | pub use std::fmt; + | --- ^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates +note: the lint level is defined here + --> $DIR/unreachable_pub.rs:4:9 + | +LL | #![warn(unreachable_pub)] + | ^^^^^^^^^^^^^^^ + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:9:24 + | +LL | pub use std::env::{Args}; // braced-use has different item spans than unbraced + | --- ^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:12:5 + | +LL | pub struct Hydrogen { + | ---^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` field + --> $DIR/unreachable_pub.rs:14:9 + | +LL | pub neutrons: usize, + | ---^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:20:9 + | +LL | pub fn count_neutrons(&self) -> usize { self.neutrons } + | ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:29:5 + | +LL | pub enum Helium {} + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:30:5 + | +LL | pub union Lithium { c1: usize, c2: u8 } + | ---^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:31:5 + | +LL | pub fn beryllium() {} + | ---^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:32:5 + | +LL | pub trait Boron {} + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:33:5 + | +LL | pub const CARBON: usize = 1; + | ---^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:34:5 + | +LL | pub static NITROGEN: usize = 2; + | ---^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:35:5 + | +LL | pub type Oxygen = bool; + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:38:47 + | +LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_empty_struct_with_visibility!(pub, Fluorine); + | --------------------------------------------------- + | | | + | | help: consider restricting its visibility: `pub(crate)` + | in this macro invocation + | + = help: or consider exporting it for use by other crates + = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:44:9 + | +LL | pub fn catalyze() -> bool; + | ---^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: 14 warnings emitted + diff --git a/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs new file mode 100644 index 000000000..26871c98d --- /dev/null +++ b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; + +#[proc_macro] +pub fn forge_unsafe_block(input: TokenStream) -> TokenStream { + let mut output = TokenStream::new(); + output.extend(Some(TokenTree::from(Ident::new("unsafe", Span::call_site())))); + output.extend(Some(TokenTree::from(Group::new(Delimiter::Brace, input)))); + output +} diff --git a/tests/ui/lint/unsafe_code/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs new file mode 100644 index 000000000..a1bd7b413 --- /dev/null +++ b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:forge_unsafe_block.rs + +#[macro_use] +extern crate forge_unsafe_block; + +unsafe fn foo() {} + +#[forbid(unsafe_code)] +fn main() { + // `forbid` doesn't work for non-user-provided unsafe blocks. + // see `UnsafeCode::check_expr`. + forge_unsafe_block! { + foo(); + } +} diff --git a/tests/ui/lint/unused-borrows.rs b/tests/ui/lint/unused-borrows.rs new file mode 100644 index 000000000..4518522ae --- /dev/null +++ b/tests/ui/lint/unused-borrows.rs @@ -0,0 +1,33 @@ +#![deny(unused_must_use)] + +fn foo(_: i32) -> bool { todo!() } + +fn bar() -> &'static i32 { + &42; + //~^ unused + + &mut foo(42); + //~^ unused + + &&42; + //~^ unused + + &&mut 42; + //~^ unused + + &mut &42; + //~^ unused + + let _result = foo(4) + && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines) + && foo(42); + //~^ unused + + let _ = &42; // ok + + &42 // ok +} + +fn main() { + let _ = bar(); +} diff --git a/tests/ui/lint/unused-borrows.stderr b/tests/ui/lint/unused-borrows.stderr new file mode 100644 index 000000000..d8dd2b5fd --- /dev/null +++ b/tests/ui/lint/unused-borrows.stderr @@ -0,0 +1,73 @@ +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:6:5 + | +LL | &42; + | ^^^ the borrow produces a value + | +note: the lint level is defined here + --> $DIR/unused-borrows.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:9:5 + | +LL | &mut foo(42); + | ^^^^^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &mut foo(42); + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:12:5 + | +LL | &&42; + | ^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &&42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:15:5 + | +LL | &&mut 42; + | ^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &&mut 42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:18:5 + | +LL | &mut &42; + | ^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = &mut &42; + | +++++++ + +error: unused borrow that must be used + --> $DIR/unused-borrows.rs:23:5 + | +LL | && foo(42); + | ^^^^^^^^^^ the borrow produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = && foo(42); + | +++++++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unused-braces-while-let-with-mutable-value.rs b/tests/ui/lint/unused-braces-while-let-with-mutable-value.rs new file mode 100644 index 000000000..ac547293c --- /dev/null +++ b/tests/ui/lint/unused-braces-while-let-with-mutable-value.rs @@ -0,0 +1,12 @@ +// check-pass + +#![deny(unused_braces)] + +fn main() { + let mut a = Some(3); + // Shouldn't warn below `a`. + while let Some(ref mut v) = {a} { + a.as_mut().map(|a| std::mem::swap(a, v)); + break; + } +} diff --git a/tests/ui/lint/unused-qualification-in-derive-expansion.rs b/tests/ui/lint/unused-qualification-in-derive-expansion.rs new file mode 100644 index 000000000..c2efbf507 --- /dev/null +++ b/tests/ui/lint/unused-qualification-in-derive-expansion.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:add-impl.rs + +#![forbid(unused_qualifications)] + +#[macro_use] +extern crate add_impl; + +#[derive(AddImpl)] +struct B; + +fn main() { + B.foo(); + foo(); + bar::foo(); +} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs new file mode 100644 index 000000000..b76b4321d --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/lint/unused/issue-104397.rs b/tests/ui/lint/unused/issue-104397.rs new file mode 100644 index 000000000..94e15cd96 --- /dev/null +++ b/tests/ui/lint/unused/issue-104397.rs @@ -0,0 +1,18 @@ +// check-pass + +#![warn(unused)] +#![deny(warnings)] + +struct Inv<'a>(&'a mut &'a ()); + +trait Trait {} +impl Trait for for<'a> fn(Inv<'a>) {} + +fn with_bound() +where + (for<'a> fn(Inv<'a>)): Trait, +{} + +fn main() { + with_bound(); +} diff --git a/tests/ui/lint/unused/issue-105061-array-lint.rs b/tests/ui/lint/unused/issue-105061-array-lint.rs new file mode 100644 index 000000000..9b06a4fde --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-array-lint.rs @@ -0,0 +1,11 @@ +#![warn(unused)] +#![deny(warnings)] + +fn main() { + let _x: ([u32; 3]); //~ ERROR unnecessary parentheses around type + let _y: [u8; (3)]; //~ ERROR unnecessary parentheses around const expression + let _z: ([u8; (3)]); + //~^ ERROR unnecessary parentheses around const expression + //~| ERROR unnecessary parentheses around type + +} diff --git a/tests/ui/lint/unused/issue-105061-array-lint.stderr b/tests/ui/lint/unused/issue-105061-array-lint.stderr new file mode 100644 index 000000000..7eb761aee --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-array-lint.stderr @@ -0,0 +1,56 @@ +error: unnecessary parentheses around type + --> $DIR/issue-105061-array-lint.rs:5:13 + | +LL | let _x: ([u32; 3]); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-105061-array-lint.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]` +help: remove these parentheses + | +LL - let _x: ([u32; 3]); +LL + let _x: [u32; 3]; + | + +error: unnecessary parentheses around const expression + --> $DIR/issue-105061-array-lint.rs:6:18 + | +LL | let _y: [u8; (3)]; + | ^ ^ + | +help: remove these parentheses + | +LL - let _y: [u8; (3)]; +LL + let _y: [u8; 3]; + | + +error: unnecessary parentheses around type + --> $DIR/issue-105061-array-lint.rs:7:13 + | +LL | let _z: ([u8; (3)]); + | ^ ^ + | +help: remove these parentheses + | +LL - let _z: ([u8; (3)]); +LL + let _z: [u8; (3)]; + | + +error: unnecessary parentheses around const expression + --> $DIR/issue-105061-array-lint.rs:7:19 + | +LL | let _z: ([u8; (3)]); + | ^ ^ + | +help: remove these parentheses + | +LL - let _z: ([u8; (3)]); +LL + let _z: ([u8; 3]); + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unused/issue-105061-should-lint.rs b/tests/ui/lint/unused/issue-105061-should-lint.rs new file mode 100644 index 000000000..7e4e09473 --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-should-lint.rs @@ -0,0 +1,23 @@ +#![warn(unused)] +#![deny(warnings)] + +struct Inv<'a>(&'a mut &'a ()); + +trait Trait<'a> {} +impl<'b> Trait<'b> for for<'a> fn(Inv<'a>) {} + +fn with_bound() +where + for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, //~ ERROR unnecessary parentheses around type +{} + +trait Hello {} +fn with_dyn_bound() +where + (dyn Hello<(for<'b> fn(&'b ()))>): Hello //~ ERROR unnecessary parentheses around type +{} + +fn main() { + with_bound(); + with_dyn_bound(); +} diff --git a/tests/ui/lint/unused/issue-105061-should-lint.stderr b/tests/ui/lint/unused/issue-105061-should-lint.stderr new file mode 100644 index 000000000..e591f1ffb --- /dev/null +++ b/tests/ui/lint/unused/issue-105061-should-lint.stderr @@ -0,0 +1,32 @@ +error: unnecessary parentheses around type + --> $DIR/issue-105061-should-lint.rs:11:13 + | +LL | for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-105061-should-lint.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]` +help: remove these parentheses + | +LL - for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, +LL + for<'b> for<'a> fn(Inv<'a>): Trait<'b>, + | + +error: unnecessary parentheses around type + --> $DIR/issue-105061-should-lint.rs:17:16 + | +LL | (dyn Hello<(for<'b> fn(&'b ()))>): Hello + | ^ ^ + | +help: remove these parentheses + | +LL - (dyn Hello<(for<'b> fn(&'b ()))>): Hello +LL + (dyn Hello fn(&'b ())>): Hello + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/issue-105061.rs b/tests/ui/lint/unused/issue-105061.rs new file mode 100644 index 000000000..92d636d0a --- /dev/null +++ b/tests/ui/lint/unused/issue-105061.rs @@ -0,0 +1,17 @@ +#![warn(unused)] +#![deny(warnings)] + +struct Inv<'a>(&'a mut &'a ()); + +trait Trait {} +impl Trait for (for<'a> fn(Inv<'a>),) {} + + +fn with_bound() +where + ((for<'a> fn(Inv<'a>)),): Trait, //~ ERROR unnecessary parentheses around type +{} + +fn main() { + with_bound(); +} diff --git a/tests/ui/lint/unused/issue-105061.stderr b/tests/ui/lint/unused/issue-105061.stderr new file mode 100644 index 000000000..f07aa2012 --- /dev/null +++ b/tests/ui/lint/unused/issue-105061.stderr @@ -0,0 +1,20 @@ +error: unnecessary parentheses around type + --> $DIR/issue-105061.rs:12:6 + | +LL | ((for<'a> fn(Inv<'a>)),): Trait, + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-105061.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]` +help: remove these parentheses + | +LL - ((for<'a> fn(Inv<'a>)),): Trait, +LL + (for<'a> fn(Inv<'a>),): Trait, + | + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-30730.rs b/tests/ui/lint/unused/issue-30730.rs new file mode 100644 index 000000000..d6be90c81 --- /dev/null +++ b/tests/ui/lint/unused/issue-30730.rs @@ -0,0 +1,5 @@ +#![warn(unused)] +#![deny(warnings)] +use std::thread; +//~^ ERROR: unused import +fn main() {} diff --git a/tests/ui/lint/unused/issue-30730.stderr b/tests/ui/lint/unused/issue-30730.stderr new file mode 100644 index 000000000..b299e99a3 --- /dev/null +++ b/tests/ui/lint/unused/issue-30730.stderr @@ -0,0 +1,15 @@ +error: unused import: `std::thread` + --> $DIR/issue-30730.rs:3:5 + | +LL | use std::thread; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-30730.rs:2:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]` + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-46576.rs b/tests/ui/lint/unused/issue-46576.rs new file mode 100644 index 000000000..15f458f38 --- /dev/null +++ b/tests/ui/lint/unused/issue-46576.rs @@ -0,0 +1,21 @@ +#![allow(dead_code)] +#![deny(unused_imports)] + +use std::fs::File; +use std::io::{BufRead, BufReader, Read}; +//~^ ERROR unused import: `BufRead` + +pub fn read_from_file(path: &str) { + let file = File::open(&path).unwrap(); + let mut reader = BufReader::new(file); + let mut s = String::new(); + reader.read_to_string(&mut s).unwrap(); +} + +pub fn read_lines(s: &str) { + for _line in s.lines() { + + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-46576.stderr b/tests/ui/lint/unused/issue-46576.stderr new file mode 100644 index 000000000..6f4d97068 --- /dev/null +++ b/tests/ui/lint/unused/issue-46576.stderr @@ -0,0 +1,14 @@ +error: unused import: `BufRead` + --> $DIR/issue-46576.rs:5:15 + | +LL | use std::io::{BufRead, BufReader, Read}; + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-46576.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs new file mode 100644 index 000000000..4822a9b2c --- /dev/null +++ b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs @@ -0,0 +1,88 @@ +// check-pass + +#![feature(box_patterns)] + +#![warn(unused)] // UI tests pass `-A unused` (#43896) + +struct SoulHistory { + corridors_of_light: usize, + hours_are_suns: bool, + endless_and_singing: bool +} + +struct LovelyAmbition { + lips: usize, + fire: usize +} + +#[derive(Clone, Copy)] +enum Large { + Suit { case: () } +} + +struct Tuple(Large, ()); + +fn main() { + let i_think_continually = 2; //~ WARNING unused variable: `i_think_continually` + let who_from_the_womb_remembered = SoulHistory { + corridors_of_light: 5, + hours_are_suns: true, + endless_and_singing: true + }; + + let mut mut_unused_var = 1; + //~^ WARNING unused variable: `mut_unused_var` + //~| WARNING variable does not need to be mutable + + let (mut var, unused_var) = (1, 2); + //~^ WARNING unused variable: `var` + //~| WARNING unused variable: `unused_var` + //~| WARNING variable does not need to be mutable + // NOTE: `var` comes after `unused_var` lexicographically yet the warning + // for `var` will be emitted before the one for `unused_var`. We use an + // `IndexMap` to ensure this is the case instead of a `BTreeMap`. + + if let SoulHistory { corridors_of_light, //~ WARNING unused variable: `corridors_of_light` + mut hours_are_suns, //~ WARNING `hours_are_suns` is assigned to, but + endless_and_singing: true } = who_from_the_womb_remembered { + hours_are_suns = false; //~ WARNING unused_assignments + } + + let the_spirit = LovelyAmbition { lips: 1, fire: 2 }; + let LovelyAmbition { lips, fire } = the_spirit; //~ WARNING unused variable: `fire` + println!("{}", lips); + + let bag = Large::Suit { + case: () + }; + + // Plain struct + match bag { + Large::Suit { case } => {} //~ WARNING unused variable: `case` + }; + + // Referenced struct + match &bag { + &Large::Suit { case } => {} //~ WARNING unused variable: `case` + }; + + // Boxed struct + match Box::new(bag) { + box Large::Suit { case } => {} //~ WARNING unused variable: `case` + }; + + // Tuple with struct + match (bag,) { + (Large::Suit { case },) => {} //~ WARNING unused variable: `case` + }; + + // Slice with struct + match [bag] { + [Large::Suit { case }] => {} //~ WARNING unused variable: `case` + }; + + // Tuple struct with struct + match Tuple(bag, ()) { + Tuple(Large::Suit { case }, ()) => {} //~ WARNING unused variable: `case` + }; +} diff --git a/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr new file mode 100644 index 000000000..fe2e3afc8 --- /dev/null +++ b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr @@ -0,0 +1,116 @@ +warning: unused variable: `i_think_continually` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 + | +LL | let i_think_continually = 2; + | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_i_think_continually` + | +note: the lint level is defined here + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9 + | +LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `mut_unused_var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:13 + | +LL | let mut mut_unused_var = 1; + | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_mut_unused_var` + +warning: unused variable: `var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:14 + | +LL | let (mut var, unused_var) = (1, 2); + | ^^^ help: if this is intentional, prefix it with an underscore: `_var` + +warning: unused variable: `unused_var` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:19 + | +LL | let (mut var, unused_var) = (1, 2); + | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_var` + +warning: unused variable: `corridors_of_light` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:45:26 + | +LL | if let SoulHistory { corridors_of_light, + | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` + +warning: variable `hours_are_suns` is assigned to, but never used + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:30 + | +LL | mut hours_are_suns, + | ^^^^^^^^^^^^^^ + | + = note: consider using `_hours_are_suns` instead + +warning: value assigned to `hours_are_suns` is never read + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:48:9 + | +LL | hours_are_suns = false; + | ^^^^^^^^^^^^^^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `fire` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:52:32 + | +LL | let LovelyAmbition { lips, fire } = the_spirit; + | ^^^^ help: try ignoring the field: `fire: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:61:23 + | +LL | Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:66:24 + | +LL | &Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:71:27 + | +LL | box Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:76:24 + | +LL | (Large::Suit { case },) => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:81:24 + | +LL | [Large::Suit { case }] => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:86:29 + | +LL | Tuple(Large::Suit { case }, ()) => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: variable does not need to be mutable + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:9 + | +LL | let mut mut_unused_var = 1; + | ----^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + | + = note: `#[warn(unused_mut)]` implied by `#[warn(unused)]` + +warning: variable does not need to be mutable + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:10 + | +LL | let (mut var, unused_var) = (1, 2); + | ----^^^ + | | + | help: remove this `mut` + +warning: 16 warnings emitted + diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed b/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed new file mode 100644 index 000000000..1350b7ca6 --- /dev/null +++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(unused)] + +pub struct S { + pub f1: i32, +} + +pub struct Point { + pub x: i32, + pub y: i32, +} + +pub enum E { + Variant { field: String } +} + +pub fn foo(arg: &E) { + match arg { + E::Variant { field: _ } => (), //~ ERROR unused variable + } +} + +fn main() { + let s = S { f1: 123 }; + let S { f1: _ } = s; //~ ERROR unused variable + + let points = vec![Point { x: 1, y: 2 }]; + let _: i32 = points.iter().map(|Point { x: _, y }| y).sum(); //~ ERROR unused variable + + match (Point { x: 1, y: 2 }) { + Point { y, x: _ } => y, //~ ERROR unused variable + }; +} diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.rs b/tests/ui/lint/unused/issue-54180-unused-ref-field.rs new file mode 100644 index 000000000..7b3392b60 --- /dev/null +++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![deny(unused)] + +pub struct S { + pub f1: i32, +} + +pub struct Point { + pub x: i32, + pub y: i32, +} + +pub enum E { + Variant { field: String } +} + +pub fn foo(arg: &E) { + match arg { + E::Variant { ref field } => (), //~ ERROR unused variable + } +} + +fn main() { + let s = S { f1: 123 }; + let S { ref f1 } = s; //~ ERROR unused variable + + let points = vec![Point { x: 1, y: 2 }]; + let _: i32 = points.iter().map(|Point { x, y }| y).sum(); //~ ERROR unused variable + + match (Point { x: 1, y: 2 }) { + Point { y, ref mut x } => y, //~ ERROR unused variable + }; +} diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr b/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr new file mode 100644 index 000000000..f2e616899 --- /dev/null +++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr @@ -0,0 +1,33 @@ +error: unused variable: `field` + --> $DIR/issue-54180-unused-ref-field.rs:20:22 + | +LL | E::Variant { ref field } => (), + | ^^^^^^^^^ help: try ignoring the field: `field: _` + | +note: the lint level is defined here + --> $DIR/issue-54180-unused-ref-field.rs:3:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `f1` + --> $DIR/issue-54180-unused-ref-field.rs:26:13 + | +LL | let S { ref f1 } = s; + | ^^^^^^ help: try ignoring the field: `f1: _` + +error: unused variable: `x` + --> $DIR/issue-54180-unused-ref-field.rs:32:20 + | +LL | Point { y, ref mut x } => y, + | ^^^^^^^^^ help: try ignoring the field: `x: _` + +error: unused variable: `x` + --> $DIR/issue-54180-unused-ref-field.rs:29:45 + | +LL | let _: i32 = points.iter().map(|Point { x, y }| y).sum(); + | ^ help: try ignoring the field: `x: _` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed new file mode 100644 index 000000000..71ebaea8e --- /dev/null +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed @@ -0,0 +1,113 @@ +// run-rustfix + +#![feature(box_patterns, stmt_expr_attributes, yeet_expr)] + +#![allow( + dead_code, + ellipsis_inclusive_range_patterns, + irrefutable_let_patterns, + unreachable_patterns, + unused_mut, + unused_variables +)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let a = 0; //~ ERROR unnecessary parentheses around pattern + for a in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let a = 0 {} //~ ERROR unnecessary parentheses around pattern + while let a = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo(a: u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + +fn _no_lint_yeet() -> Result<(), ()> { + #[allow(unreachable_code)] + if (do yeet) {} + + Ok(()) +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + + let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. +} + +fn or_patterns_will_lint() { + if let 0 | 1 = 0 {} //~ ERROR unnecessary parentheses around pattern + if let (0 | 1,) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [0 | 1] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | 1 | 2 = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS(0 | 1) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} + +fn main() { + match 1 { + _ => {} //~ ERROR unnecessary parentheses around pattern + y => {} //~ ERROR unnecessary parentheses around pattern + ref r => {} //~ ERROR unnecessary parentheses around pattern + e @ 1...2 => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn + e @ (3...4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) => {} //~ ERROR unnecessary parentheses around pattern + &_ => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } + + match 1 { + _ => {} //~ ERROR unnecessary parentheses around pattern + y => {} //~ ERROR unnecessary parentheses around pattern + ref r => {} //~ ERROR unnecessary parentheses around pattern + e @ 1..=2 => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn + e @ (3..=4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + e @ &(1..=2) => {} //~ ERROR unnecessary parentheses around pattern + &_ => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } +} diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs new file mode 100644 index 000000000..28b662dd0 --- /dev/null +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs @@ -0,0 +1,113 @@ +// run-rustfix + +#![feature(box_patterns, stmt_expr_attributes, yeet_expr)] + +#![allow( + dead_code, + ellipsis_inclusive_range_patterns, + irrefutable_let_patterns, + unreachable_patterns, + unused_mut, + unused_variables +)] +#![deny(unused_parens)] + +fn lint_on_top_level() { + let (a) = 0; //~ ERROR unnecessary parentheses around pattern + for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern + if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern + fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern + let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern +} + +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + +fn _no_lint_yeet() -> Result<(), ()> { + #[allow(unreachable_code)] + if (do yeet) {} + + Ok(()) +} + +// Don't lint in these cases (#64106). +fn or_patterns_no_lint() { + match Box::new(0) { + box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`. + _ => {} + } + + match 0 { + x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`. + _ => {} + } + + if let &(0 | 1) = &0 {} // Should also not lint. + if let &mut (0 | 1) = &mut 0 {} // Same. + + fn foo((Ok(a) | Err(a)): Result) {} // Doesn't parse if we remove parens for now. + + let _ = |(Ok(a) | Err(a)): Result| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or. +} + +fn or_patterns_will_lint() { + if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern + if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern + if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern + if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern + struct TS(u8); + if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern + struct NS { f: u8 } + if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern +} + +// Don't lint on `&(mut x)` because `&mut x` means something else (#55342). +fn deref_mut_binding_no_lint() { + let &(mut x) = &0; +} + +fn main() { + match 1 { + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern + (1...2) => {} // Non ambiguous range pattern should not warn + e @ (3...4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1...2) => {} // Ambiguous range pattern should not warn + &(1...2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } + + match 1 { + (_) => {} //~ ERROR unnecessary parentheses around pattern + (y) => {} //~ ERROR unnecessary parentheses around pattern + (ref r) => {} //~ ERROR unnecessary parentheses around pattern + (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern + (1..=2) => {} // Non ambiguous range pattern should not warn + e @ (3..=4) => {} // Non ambiguous range pattern should not warn + } + + match &1 { + (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern + &(_) => {} //~ ERROR unnecessary parentheses around pattern + e @ &(1..=2) => {} // Ambiguous range pattern should not warn + &(1..=2) => {} // Ambiguous range pattern should not warn + } + + match &1 { + e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn + &_ => {} + } +} diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr new file mode 100644 index 000000000..a5e69e6d9 --- /dev/null +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -0,0 +1,295 @@ +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:16:9 + | +LL | let (a) = 0; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-54538-unused-parens-lint.rs:13:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let (a) = 0; +LL + let a = 0; + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:17:9 + | +LL | for (a) in 0..1 {} + | ^ ^ + | +help: remove these parentheses + | +LL - for (a) in 0..1 {} +LL + for a in 0..1 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:18:12 + | +LL | if let (a) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let (a) = 0 {} +LL + if let a = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:19:15 + | +LL | while let (a) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let (a) = 0 {} +LL + while let a = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:20:12 + | +LL | fn foo((a): u8) {} + | ^ ^ + | +help: remove these parentheses + | +LL - fn foo((a): u8) {} +LL + fn foo(a: u8) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:21:14 + | +LL | let _ = |(a): u8| 0; + | ^ ^ + | +help: remove these parentheses + | +LL - let _ = |(a): u8| 0; +LL + let _ = |a: u8| 0; + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:56:12 + | +LL | if let (0 | 1) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let (0 | 1) = 0 {} +LL + if let 0 | 1 = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:57:13 + | +LL | if let ((0 | 1),) = (0,) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let ((0 | 1),) = (0,) {} +LL + if let (0 | 1,) = (0,) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:58:13 + | +LL | if let [(0 | 1)] = [0] {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let [(0 | 1)] = [0] {} +LL + if let [0 | 1] = [0] {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:59:16 + | +LL | if let 0 | (1 | 2) = 0 {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let 0 | (1 | 2) = 0 {} +LL + if let 0 | 1 | 2 = 0 {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:61:15 + | +LL | if let TS((0 | 1)) = TS(0) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let TS((0 | 1)) = TS(0) {} +LL + if let TS(0 | 1) = TS(0) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:63:20 + | +LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let NS { f: (0 | 1) } = (NS { f: 0 }) {} +LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:73:9 + | +LL | (_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:74:9 + | +LL | (y) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:75:9 + | +LL | (ref r) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:76:9 + | +LL | (e @ 1...2) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1...2) => {} +LL + e @ 1...2 => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:82:9 + | +LL | (e @ &(1...2)) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1...2)) => {} +LL + e @ &(1...2) => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:83:10 + | +LL | &(_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:94:9 + | +LL | (_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (_) => {} +LL + _ => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:95:9 + | +LL | (y) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (y) => {} +LL + y => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:96:9 + | +LL | (ref r) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (ref r) => {} +LL + ref r => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:97:9 + | +LL | (e @ 1..=2) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ 1..=2) => {} +LL + e @ 1..=2 => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:103:9 + | +LL | (e @ &(1..=2)) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - (e @ &(1..=2)) => {} +LL + e @ &(1..=2) => {} + | + +error: unnecessary parentheses around pattern + --> $DIR/issue-54538-unused-parens-lint.rs:104:10 + | +LL | &(_) => {} + | ^ ^ + | +help: remove these parentheses + | +LL - &(_) => {} +LL + &_ => {} + | + +error: aborting due to 24 previous errors + diff --git a/tests/ui/lint/unused/issue-59896.rs b/tests/ui/lint/unused/issue-59896.rs new file mode 100644 index 000000000..ff9f19acf --- /dev/null +++ b/tests/ui/lint/unused/issue-59896.rs @@ -0,0 +1,9 @@ +#![deny(unused_imports)] + +struct S; + +fn main() { + use S; //~ ERROR the item `S` is imported redundantly + + let _s = S; +} diff --git a/tests/ui/lint/unused/issue-59896.stderr b/tests/ui/lint/unused/issue-59896.stderr new file mode 100644 index 000000000..95b7938ae --- /dev/null +++ b/tests/ui/lint/unused/issue-59896.stderr @@ -0,0 +1,17 @@ +error: the item `S` is imported redundantly + --> $DIR/issue-59896.rs:6:9 + | +LL | struct S; + | --------- the item `S` is already defined here +... +LL | use S; + | ^ + | +note: the lint level is defined here + --> $DIR/issue-59896.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs new file mode 100644 index 000000000..e3631d014 --- /dev/null +++ b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs @@ -0,0 +1,85 @@ +// FIXME: should be run-rustfix, but rustfix doesn't currently support multipart suggestions, see +// #53934 + +#![deny(unused)] + +pub enum MyEnum { + A { i: i32, j: i32 }, + B { i: i32, j: i32 }, +} + +pub enum MixedEnum { + A { i: i32 }, + B(i32), +} + +pub fn no_ref(x: MyEnum) { + use MyEnum::*; + + match x { + A { i, j } | B { i, j } => { //~ ERROR unused variable + println!("{}", i); + } + } +} + +pub fn with_ref(x: MyEnum) { + use MyEnum::*; + + match x { + A { i, ref j } | B { i, ref j } => { //~ ERROR unused variable + println!("{}", i); + } + } +} + +pub fn inner_no_ref(x: Option) { + use MyEnum::*; + + match x { + Some(A { i, j } | B { i, j }) => { //~ ERROR unused variable + println!("{}", i); + } + + _ => {} + } +} + +pub fn inner_with_ref(x: Option) { + use MyEnum::*; + + match x { + Some(A { i, ref j } | B { i, ref j }) => { //~ ERROR unused variable + println!("{}", i); + } + + _ => {} + } +} + +pub fn mixed_no_ref(x: MixedEnum) { + match x { + MixedEnum::A { i } | MixedEnum::B(i) => { //~ ERROR unused variable + println!("match"); + } + } +} + +pub fn mixed_with_ref(x: MixedEnum) { + match x { + MixedEnum::A { ref i } | MixedEnum::B(ref i) => { //~ ERROR unused variable + println!("match"); + } + } +} + +pub fn main() { + no_ref(MyEnum::A { i: 1, j: 2 }); + with_ref(MyEnum::A { i: 1, j: 2 }); + + inner_no_ref(Some(MyEnum::A { i: 1, j: 2 })); + inner_with_ref(Some(MyEnum::A { i: 1, j: 2 })); + + mixed_no_ref(MixedEnum::B(5)); + mixed_with_ref(MixedEnum::B(5)); +} diff --git a/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr new file mode 100644 index 000000000..8fc2d1bc8 --- /dev/null +++ b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr @@ -0,0 +1,74 @@ +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:20:16 + | +LL | A { i, j } | B { i, j } => { + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:4:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` +help: try ignoring the field + | +LL | A { i, j: _ } | B { i, j: _ } => { + | ~~~~ ~~~~ + +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:30:16 + | +LL | A { i, ref j } | B { i, ref j } => { + | ^^^^^ ^^^^^ + | +help: try ignoring the field + | +LL | A { i, j: _ } | B { i, j: _ } => { + | ~~~~ ~~~~ + +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:40:21 + | +LL | Some(A { i, j } | B { i, j }) => { + | ^ ^ + | +help: try ignoring the field + | +LL | Some(A { i, j: _ } | B { i, j: _ }) => { + | ~~~~ ~~~~ + +error: unused variable: `j` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:52:21 + | +LL | Some(A { i, ref j } | B { i, ref j }) => { + | ^^^^^ ^^^^^ + | +help: try ignoring the field + | +LL | Some(A { i, j: _ } | B { i, j: _ }) => { + | ~~~~ ~~~~ + +error: unused variable: `i` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:62:24 + | +LL | MixedEnum::A { i } | MixedEnum::B(i) => { + | ^ ^ + | +help: try ignoring the field + | +LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => { + | ~~~~ ~ + +error: unused variable: `i` + --> $DIR/issue-67691-unused-field-in-or-pattern.rs:70:24 + | +LL | MixedEnum::A { ref i } | MixedEnum::B(ref i) => { + | ^^^^^ ^^^^^ + | +help: try ignoring the field + | +LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => { + | ~~~~ ~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unused/issue-70041.rs b/tests/ui/lint/unused/issue-70041.rs new file mode 100644 index 000000000..22e42295e --- /dev/null +++ b/tests/ui/lint/unused/issue-70041.rs @@ -0,0 +1,13 @@ +// compile-flags: --edition=2018 +// run-pass + +macro_rules! regex { + //~^ WARN unused macro definition + () => {}; +} + +#[allow(dead_code)] +use regex; +//~^ WARN unused import + +fn main() {} diff --git a/tests/ui/lint/unused/issue-70041.stderr b/tests/ui/lint/unused/issue-70041.stderr new file mode 100644 index 000000000..b2e6d1aeb --- /dev/null +++ b/tests/ui/lint/unused/issue-70041.stderr @@ -0,0 +1,18 @@ +warning: unused macro definition: `regex` + --> $DIR/issue-70041.rs:4:14 + | +LL | macro_rules! regex { + | ^^^^^ + | + = note: `#[warn(unused_macros)]` on by default + +warning: unused import: `regex` + --> $DIR/issue-70041.rs:10:5 + | +LL | use regex; + | ^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs b/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs new file mode 100644 index 000000000..24d77e36d --- /dev/null +++ b/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs @@ -0,0 +1,23 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/71290 for details. +#![deny(unused_parens)] + +fn x() -> u8 { + ({ 0 }) + 1 +} + +fn y() -> u8 { + ({ 0 } + 1) +} + +pub fn foo(a: bool, b: bool) -> u8 { + (if a { 1 } else { 0 } + if b { 1 } else { 0 }) +} + +pub fn bar() -> u8 { + // Make sure nested expressions are handled correctly as well + ({ 0 } + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs new file mode 100644 index 000000000..8064c3a88 --- /dev/null +++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs @@ -0,0 +1,26 @@ +#![feature(generator_trait)] +#![feature(generators)] +#![deny(unused_braces, unused_parens)] + +use std::ops::Generator; +use std::pin::Pin; + +fn main() { + let mut x = |_| { + while let Some(_) = (yield) {} + while let Some(_) = {yield} {} + + // Only warn these cases + while let Some(_) = ({yield}) {} //~ ERROR: unnecessary parentheses + while let Some(_) = ((yield)) {} //~ ERROR: unnecessary parentheses + {{yield}}; //~ ERROR: unnecessary braces + {( yield )}; //~ ERROR: unnecessary parentheses + while let Some(_) = {(yield)} {} //~ ERROR: unnecessary parentheses + while let Some(_) = {{yield}} {} //~ ERROR: unnecessary braces + + // FIXME: It'd be great if we could also warn them. + ((yield)); + ({ yield }); + }; + let _ = Pin::new(&mut x).resume(Some(5)); +} diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr new file mode 100644 index 000000000..3f1fee332 --- /dev/null +++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr @@ -0,0 +1,84 @@ +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29 + | +LL | while let Some(_) = ({yield}) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24 + | +LL | #![deny(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - while let Some(_) = ({yield}) {} +LL + while let Some(_) = {yield} {} + | + +error: unnecessary parentheses around `let` scrutinee expression + --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29 + | +LL | while let Some(_) = ((yield)) {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = ((yield)) {} +LL + while let Some(_) = (yield) {} + | + +error: unnecessary braces around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10 + | +LL | {{yield}}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9 + | +LL | #![deny(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - {{yield}}; +LL + {yield}; + | + +error: unnecessary parentheses around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10 + | +LL | {( yield )}; + | ^^ ^^ + | +help: remove these parentheses + | +LL - {( yield )}; +LL + {yield}; + | + +error: unnecessary parentheses around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30 + | +LL | while let Some(_) = {(yield)} {} + | ^ ^ + | +help: remove these parentheses + | +LL - while let Some(_) = {(yield)} {} +LL + while let Some(_) = {yield} {} + | + +error: unnecessary braces around block return value + --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30 + | +LL | while let Some(_) = {{yield}} {} + | ^ ^ + | +help: remove these braces + | +LL - while let Some(_) = {{yield}} {} +LL + while let Some(_) = {yield} {} + | + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed b/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed new file mode 100644 index 000000000..aac918f2b --- /dev/null +++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #81314: Unused variable lint should +// span only the identifier and not the rest of the pattern + +#![deny(unused)] + +fn main() { + let [_rest @ ..] = [1, 2, 3]; //~ ERROR unused variable +} + +pub fn foo([_rest @ ..]: &[i32]) { //~ ERROR unused variable +} diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.rs b/tests/ui/lint/unused/issue-81314-unused-span-ident.rs new file mode 100644 index 000000000..78296f425 --- /dev/null +++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.rs @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #81314: Unused variable lint should +// span only the identifier and not the rest of the pattern + +#![deny(unused)] + +fn main() { + let [rest @ ..] = [1, 2, 3]; //~ ERROR unused variable +} + +pub fn foo([rest @ ..]: &[i32]) { //~ ERROR unused variable +} diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr b/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr new file mode 100644 index 000000000..519c71e94 --- /dev/null +++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr @@ -0,0 +1,21 @@ +error: unused variable: `rest` + --> $DIR/issue-81314-unused-span-ident.rs:8:10 + | +LL | let [rest @ ..] = [1, 2, 3]; + | ^^^^ help: if this is intentional, prefix it with an underscore: `_rest` + | +note: the lint level is defined here + --> $DIR/issue-81314-unused-span-ident.rs:5:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `rest` + --> $DIR/issue-81314-unused-span-ident.rs:11:13 + | +LL | pub fn foo([rest @ ..]: &[i32]) { + | ^^^^ help: if this is intentional, prefix it with an underscore: `_rest` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/issue-85913.rs b/tests/ui/lint/unused/issue-85913.rs new file mode 100644 index 000000000..7f3817b6e --- /dev/null +++ b/tests/ui/lint/unused/issue-85913.rs @@ -0,0 +1,13 @@ +#![deny(unused_must_use)] + +pub fn fun() -> i32 { + function() && return 1; + //~^ ERROR: unused logical operation that must be used + return 0; +} + +fn function() -> bool { + true +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-85913.stderr b/tests/ui/lint/unused/issue-85913.stderr new file mode 100644 index 000000000..8234ed3b1 --- /dev/null +++ b/tests/ui/lint/unused/issue-85913.stderr @@ -0,0 +1,18 @@ +error: unused logical operation that must be used + --> $DIR/issue-85913.rs:4:5 + | +LL | function() && return 1; + | ^^^^^^^^^^^^^^^^^^^^^^ the logical operation produces a value + | +note: the lint level is defined here + --> $DIR/issue-85913.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = function() && return 1; + | +++++++ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/issue-88519-unused-paren.rs b/tests/ui/lint/unused/issue-88519-unused-paren.rs new file mode 100644 index 000000000..ce3d15ac1 --- /dev/null +++ b/tests/ui/lint/unused/issue-88519-unused-paren.rs @@ -0,0 +1,85 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/88519 +#![deny(unused_parens)] +#![feature(type_ascription)] + +// binary ops are tested in issue-71290-unused-paren-binop.rs + +mod call { + fn noop() -> u8 { 0 } + fn outside() -> u8 { + ({ noop })() + } + fn inside() -> u8 { + ({ noop }()) + } + fn outside_match() -> u8 { + (match noop { x => x })() + } + fn inside_match() -> u8 { + (match noop { x => x }()) + } + fn outside_if() -> u8 { + (if false { noop } else { noop })() + } + fn inside_if() -> u8 { + (if false { noop } else { noop }()) + } +} + +mod casts { + fn outside() -> u8 { + ({ 0 }) as u8 + } + fn inside() -> u8 { + ({ 0 } as u8) + } + fn outside_match() -> u8 { + (match 0 { x => x }) as u8 + } + fn inside_match() -> u8 { + (match 0 { x => x } as u8) + } + fn outside_if() -> u8 { + (if false { 0 } else { 0 }) as u8 + } + fn inside_if() -> u8 { + (if false { 0 } else { 0 } as u8) + } +} + +mod typeascription { + fn outside() -> u8 { + type_ascribe!(({ 0 }), u8) + } + fn outside_match() -> u8 { + type_ascribe!((match 0 { x => x }), u8) + } + fn outside_if() -> u8 { + type_ascribe!((if false { 0 } else { 0 }), u8) + } +} + +mod index { + fn outside(x: &[u8]) -> u8 { + ({ x })[0] + } + fn inside(x: &[u8]) -> u8 { + ({ x }[0]) + } + fn outside_match(x: &[u8]) -> u8 { + (match x { x => x })[0] + } + fn inside_match(x: &[u8]) -> u8 { + (match x { x => x }[0]) + } + fn outside_if(x: &[u8]) -> u8 { + (if false { x } else { x })[0] + } + fn inside_if(x: &[u8]) -> u8 { + (if false { x } else { x }[0]) + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/issue-90807-unused-paren-error.rs b/tests/ui/lint/unused/issue-90807-unused-paren-error.rs new file mode 100644 index 000000000..2fca2e262 --- /dev/null +++ b/tests/ui/lint/unused/issue-90807-unused-paren-error.rs @@ -0,0 +1,9 @@ +// Make sure unused parens lint emit is emitted for loop and match. +// See https://github.com/rust-lang/rust/issues/90807 +// and https://github.com/rust-lang/rust/pull/91956#discussion_r771647953 +#![deny(unused_parens)] + +fn main() { + for _ in (1..loop { break 2 }) {} //~ERROR + for _ in (1..match () { () => 2 }) {} //~ERROR +} diff --git a/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr b/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr new file mode 100644 index 000000000..b3b809d5f --- /dev/null +++ b/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr @@ -0,0 +1,31 @@ +error: unnecessary parentheses around `for` iterator expression + --> $DIR/issue-90807-unused-paren-error.rs:7:14 + | +LL | for _ in (1..loop { break 2 }) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-90807-unused-paren-error.rs:4:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - for _ in (1..loop { break 2 }) {} +LL + for _ in 1..loop { break 2 } {} + | + +error: unnecessary parentheses around `for` iterator expression + --> $DIR/issue-90807-unused-paren-error.rs:8:14 + | +LL | for _ in (1..match () { () => 2 }) {} + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (1..match () { () => 2 }) {} +LL + for _ in 1..match () { () => 2 } {} + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/issue-90807-unused-paren.rs b/tests/ui/lint/unused/issue-90807-unused-paren.rs new file mode 100644 index 000000000..4c0930f96 --- /dev/null +++ b/tests/ui/lint/unused/issue-90807-unused-paren.rs @@ -0,0 +1,8 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/90807 +#![deny(unused_parens)] + +fn main() { + for _ in (1..{ 2 }) {} +} diff --git a/tests/ui/lint/unused/issue-92751.rs b/tests/ui/lint/unused/issue-92751.rs new file mode 100644 index 000000000..2fb292736 --- /dev/null +++ b/tests/ui/lint/unused/issue-92751.rs @@ -0,0 +1,9 @@ +#[deny(unused)] +pub fn broken(x: Option<()>) -> i32 { + match x { + Some(()) => (1), //~ ERROR unnecessary parentheses around match arm expression + None => (2), //~ ERROR unnecessary parentheses around match arm expression + } +} + +fn main() { } diff --git a/tests/ui/lint/unused/issue-92751.stderr b/tests/ui/lint/unused/issue-92751.stderr new file mode 100644 index 000000000..0a8d8e672 --- /dev/null +++ b/tests/ui/lint/unused/issue-92751.stderr @@ -0,0 +1,32 @@ +error: unnecessary parentheses around match arm expression + --> $DIR/issue-92751.rs:4:21 + | +LL | Some(()) => (1), + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-92751.rs:1:8 + | +LL | #[deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]` +help: remove these parentheses + | +LL - Some(()) => (1), +LL + Some(()) => 1, + | + +error: unnecessary parentheses around match arm expression + --> $DIR/issue-92751.rs:5:17 + | +LL | None => (2), + | ^ ^ + | +help: remove these parentheses + | +LL - None => (2), +LL + None => 2, + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.rs b/tests/ui/lint/unused/lint-unused-extern-crate.rs new file mode 100644 index 000000000..d5e4da526 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-extern-crate.rs @@ -0,0 +1,35 @@ +// aux-build:lint_unused_extern_crate.rs +// aux-build:lint_unused_extern_crate2.rs +// aux-build:lint_unused_extern_crate3.rs +// aux-build:lint_unused_extern_crate4.rs +// aux-build:lint_unused_extern_crate5.rs + +#![deny(unused_extern_crates)] +#![allow(unused_variables)] +#![allow(deprecated)] + +extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate + +pub extern crate lint_unused_extern_crate4; // no error, it is re-exported + +extern crate lint_unused_extern_crate3; // no error, it is used + +extern crate lint_unused_extern_crate2; // no error, the use marks it as used + // even if imported objects aren't used + +extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used + +#[allow(unused_imports)] +use lint_unused_extern_crate2::foo as bar; + +use other::*; + +mod foo { + // Test that this is unused even though an earlier `extern crate` is used. + extern crate lint_unused_extern_crate2; //~ ERROR unused extern crate +} + +fn main() { + lint_unused_extern_crate3::foo(); + let y = foo(); +} diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.stderr b/tests/ui/lint/unused/lint-unused-extern-crate.stderr new file mode 100644 index 000000000..46d8f3bee --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-extern-crate.stderr @@ -0,0 +1,20 @@ +error: unused extern crate + --> $DIR/lint-unused-extern-crate.rs:11:1 + | +LL | extern crate lint_unused_extern_crate5; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/lint-unused-extern-crate.rs:7:9 + | +LL | #![deny(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused extern crate + --> $DIR/lint-unused-extern-crate.rs:29:5 + | +LL | extern crate lint_unused_extern_crate2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs new file mode 100644 index 000000000..4754d8880 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports.rs @@ -0,0 +1,90 @@ +#![deny(unused_imports)] +#![allow(dead_code)] + +use bar::c::cc as cal; + +use std::mem::*; // shouldn't get errors for not using + // everything imported +use std::fmt::{}; +//~^ ERROR unused import: `std::fmt::{}` + +// Should get errors for both 'Some' and 'None' +use std::option::Option::{Some, None}; +//~^ ERROR unused imports: `None`, `Some` + +use test::A; //~ ERROR unused import: `test::A` +// Be sure that if we just bring some methods into scope that they're also +// counted as being used. +use test::B; +// But only when actually used: do not get confused by the method with the same name. +use test::B2; //~ ERROR unused import: `test::B2` + +// Make sure this import is warned about when at least one of its imported names +// is unused +use test2::{foo, bar}; //~ ERROR unused import: `bar` + +mod test2 { + pub fn foo() {} + pub fn bar() {} +} + +mod test { + pub trait A { fn a(&self) {} } + pub trait B { fn b(&self) {} } + pub trait B2 { fn b(&self) {} } + pub struct C; + impl A for C {} + impl B for C {} +} + +mod foo { + pub struct Point{pub x: isize, pub y: isize} + pub struct Square{pub p: Point, pub h: usize, pub w: usize} +} + +mod bar { + // Don't ignore on 'pub use' because we're not sure if it's used or not + pub use std::cmp::PartialEq; + pub struct Square; + + pub mod c { + use foo::Point; + use foo::Square; //~ ERROR unused import: `foo::Square` + pub fn cc(_p: Point) -> super::Square { + fn f() -> super::Square { + super::Square + } + f() + } + } + + #[allow(unused_imports)] + mod foo { + use std::cmp::PartialEq; + } +} + +fn g() { + use self::g; //~ ERROR unused import: `self::g` + //~^ ERROR the item `g` is imported redundantly + fn f() { + self::g(); + } +} + +// cf. issue #35135. +#[allow(unused_variables)] +fn h() { + use test2::foo; //~ ERROR unused import: `test2::foo` + //~^ ERROR the item `foo` is imported redundantly + let foo = 0; +} + +fn main() { + cal(foo::Point{x:3, y:9}); + let mut a = 3; + let mut b = 4; + swap(&mut a, &mut b); + test::C.b(); + let _a = foo(); +} diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr new file mode 100644 index 000000000..0574ca456 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-imports.stderr @@ -0,0 +1,78 @@ +error: unused import: `std::fmt::{}` + --> $DIR/lint-unused-imports.rs:8:5 + | +LL | use std::fmt::{}; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unused-imports.rs:1:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused imports: `None`, `Some` + --> $DIR/lint-unused-imports.rs:12:27 + | +LL | use std::option::Option::{Some, None}; + | ^^^^ ^^^^ + +error: unused import: `test::A` + --> $DIR/lint-unused-imports.rs:15:5 + | +LL | use test::A; + | ^^^^^^^ + +error: unused import: `bar` + --> $DIR/lint-unused-imports.rs:24:18 + | +LL | use test2::{foo, bar}; + | ^^^ + +error: unused import: `foo::Square` + --> $DIR/lint-unused-imports.rs:52:13 + | +LL | use foo::Square; + | ^^^^^^^^^^^ + +error: the item `g` is imported redundantly + --> $DIR/lint-unused-imports.rs:68:9 + | +LL | / fn g() { +LL | | use self::g; + | | ^^^^^^^ +LL | | +LL | | fn f() { +LL | | self::g(); +LL | | } +LL | | } + | |_- the item `g` is already defined here + +error: unused import: `self::g` + --> $DIR/lint-unused-imports.rs:68:9 + | +LL | use self::g; + | ^^^^^^^ + +error: the item `foo` is imported redundantly + --> $DIR/lint-unused-imports.rs:78:9 + | +LL | use test2::{foo, bar}; + | --- the item `foo` is already imported here +... +LL | use test2::foo; + | ^^^^^^^^^^ + +error: unused import: `test2::foo` + --> $DIR/lint-unused-imports.rs:78:9 + | +LL | use test2::foo; + | ^^^^^^^^^^ + +error: unused import: `test::B2` + --> $DIR/lint-unused-imports.rs:20:5 + | +LL | use test::B2; + | ^^^^^^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-mut-self.fixed b/tests/ui/lint/unused/lint-unused-mut-self.fixed new file mode 100644 index 000000000..92ce10358 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-self.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![deny(unused_mut)] + +struct Foo; +impl Foo { + fn foo(self) {} //~ ERROR: variable does not need to be mutable + fn bar(self: Box) {} //~ ERROR: variable does not need to be mutable +} + +fn main() {} diff --git a/tests/ui/lint/unused/lint-unused-mut-self.rs b/tests/ui/lint/unused/lint-unused-mut-self.rs new file mode 100644 index 000000000..70736ce21 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-self.rs @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![deny(unused_mut)] + +struct Foo; +impl Foo { + fn foo(mut self) {} //~ ERROR: variable does not need to be mutable + fn bar(mut self: Box) {} //~ ERROR: variable does not need to be mutable +} + +fn main() {} diff --git a/tests/ui/lint/unused/lint-unused-mut-self.stderr b/tests/ui/lint/unused/lint-unused-mut-self.stderr new file mode 100644 index 000000000..01a524bd3 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-self.stderr @@ -0,0 +1,24 @@ +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-self.rs:10:12 + | +LL | fn foo(mut self) {} + | ----^^^^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/lint-unused-mut-self.rs:6:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-self.rs:11:12 + | +LL | fn bar(mut self: Box) {} + | ----^^^^ + | | + | help: remove this `mut` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.rs b/tests/ui/lint/unused/lint-unused-mut-variables.rs new file mode 100644 index 000000000..67ec7facf --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-variables.rs @@ -0,0 +1,207 @@ +// edition:2018 + +// Exercise the unused_mut attribute in some positive and negative cases + +#![warn(unused_mut)] +#![feature(async_closure, raw_ref_op)] + +async fn baz_async( + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, +) {} +fn baz( + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) +) {} + +struct RefStruct {} +impl RefStruct { + async fn baz_async( + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + ) {} + fn baz( + &self, + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + ) {} +} + +trait RefTrait { + fn baz( + &self, + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + ) {} +} +impl RefTrait for () { + fn baz( + &self, + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + ) {} +} + +fn main() { + let _ = async move | + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + | {}; + let _ = | + mut a: i32, + //~^ WARN: variable does not need to be mutable + #[allow(unused_mut)] mut b: i32, + #[allow(unused_mut)] (mut c, d): (i32, i32) + | {}; + + // negative cases + let mut a = 3; //~ WARN: variable does not need to be mutable + + let mut a = 2; //~ WARN: variable does not need to be mutable + + let mut b = 3; //~ WARN: variable does not need to be mutable + + let mut a = vec![3]; //~ WARN: variable does not need to be mutable + + let (mut a, b) = (1, 2); //~ WARN: variable does not need to be mutable + + let mut a; //~ WARN: variable does not need to be mutable + + a = 3; + + let mut b; //~ WARN: variable does not need to be mutable + + if true { + b = 3; + } else { + b = 4; + } + + match 30 { + mut x => {} //~ WARN: variable does not need to be mutable + + } + + match (30, 2) { + // FIXME: Here's a false positive, + // shouldn't be removed `mut` not to be bound with a different way. + (mut x, 1) | //~ WARN: variable does not need to be mutable + + (mut x, 2) | + (mut x, 3) => { + } + _ => {} + } + + let x = |mut y: isize| 10; //~ WARN: variable does not need to be mutable + + fn what(mut foo: isize) {} //~ WARN: variable does not need to be mutable + + + let mut a = &mut 5; //~ WARN: variable does not need to be mutable + + *a = 4; + + let mut a = 5; + let mut b = (&mut a,); //~ WARN: variable does not need to be mutable + *b.0 = 4; + + let mut x = &mut 1; //~ WARN: variable does not need to be mutable + + let mut f = || { + *x += 1; + }; + f(); + + fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { + &mut arg[..] //~^ WARN: variable does not need to be mutable + + } + + let mut v : &mut Vec<()> = &mut vec![]; //~ WARN: variable does not need to be mutable + + v.push(()); + + // positive cases + let mut a = 2; + a = 3; + let mut a = Vec::new(); + a.push(3); + let mut a = Vec::new(); + callback(|| { + a.push(3); + }); + let mut a = Vec::new(); + callback(|| { + callback(|| { + a.push(3); + }); + }); + let (mut a, b) = (1, 2); + a = 34; + + match 30 { + mut x => { + x = 21; + } + } + + match (30, 2) { + (mut x, 1) | + (mut x, 2) | + (mut x, 3) => { + x = 21 + } + _ => {} + } + + // Attribute should be respected on match arms + match 0 { + #[allow(unused_mut)] + mut x => { + let mut y = 1; + }, + } + + let x = |mut y: isize| y = 32; + fn nothing(mut foo: isize) { foo = 37; } + + // leading underscore should avoid the warning, just like the + // unused variable lint. + let mut _allowed = 1; + + let mut raw_address_of_mut = 1; // OK + let mut_ptr = &raw mut raw_address_of_mut; + + let mut raw_address_of_const = 1; //~ WARN: variable does not need to be mutable + let const_ptr = &raw const raw_address_of_const; +} + +fn callback(f: F) where F: FnOnce() {} + +// make sure the lint attribute can be turned off +#[allow(unused_mut)] +fn foo(mut a: isize) { + let mut a = 3; + let mut b = vec![2]; +} + +// make sure the lint attribute can be turned off on let statements +#[deny(unused_mut)] +fn bar() { + #[allow(unused_mut)] + let mut a = 3; + let mut b = vec![2]; //~ ERROR: variable does not need to be mutable + +} diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.stderr b/tests/ui/lint/unused/lint-unused-mut-variables.stderr new file mode 100644 index 000000000..805ed2b40 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-mut-variables.stderr @@ -0,0 +1,222 @@ +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:9:5 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/lint-unused-mut-variables.rs:5:9 + | +LL | #![warn(unused_mut)] + | ^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:23:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:14:5 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:29:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:39:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:48:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:57:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:62:9 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:107:14 + | +LL | let x = |mut y: isize| 10; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:69:9 + | +LL | let mut a = 3; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:71:9 + | +LL | let mut a = 2; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:73:9 + | +LL | let mut b = 3; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:75:9 + | +LL | let mut a = vec![3]; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:77:10 + | +LL | let (mut a, b) = (1, 2); + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:79:9 + | +LL | let mut a; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:83:9 + | +LL | let mut b; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:92:9 + | +LL | mut x => {} + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:99:10 + | +LL | (mut x, 1) | + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:112:9 + | +LL | let mut a = &mut 5; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:117:9 + | +LL | let mut b = (&mut a,); + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:120:9 + | +LL | let mut x = &mut 1; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:132:9 + | +LL | let mut v : &mut Vec<()> = &mut vec![]; + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:187:9 + | +LL | let mut raw_address_of_const = 1; + | ----^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:109:13 + | +LL | fn what(mut foo: isize) {} + | ----^^^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:127:20 + | +LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { + | ----^^^ + | | + | help: remove this `mut` + +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:205:9 + | +LL | let mut b = vec![2]; + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/lint-unused-mut-variables.rs:201:8 + | +LL | #[deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error; 25 warnings emitted + diff --git a/tests/ui/lint/unused/lint-unused-variables.rs b/tests/ui/lint/unused/lint-unused-variables.rs new file mode 100644 index 000000000..6850e9992 --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-variables.rs @@ -0,0 +1,79 @@ +// compile-flags: --cfg something +// edition:2018 + +#![feature(async_closure)] +#![deny(unused_variables)] + +async fn foo_async( + a: i32, + //~^ ERROR unused variable: `a` + #[allow(unused_variables)] b: i32, +) {} +fn foo( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` +) {} + +struct RefStruct {} +impl RefStruct { + async fn bar_async( + &self, + a: i32, + //~^ ERROR unused variable: `a` + #[allow(unused_variables)] b: i32, + ) {} + fn bar( + &self, + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} +} +trait RefTrait { + fn bar( + &self, + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} +} +impl RefTrait for RefStruct { + fn bar( + &self, + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} + fn issue_64682_associated_fn( + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + ) {} +} + +fn main() { + let _: fn(_, _) = foo; + let a = async move | + a: i32, + //~^ ERROR unused variable: `a` + #[allow(unused_variables)] b: i32, + | {}; + let b = | + #[allow(unused_variables)] a: i32, + b: i32, + //~^ ERROR unused variable: `b` + | {}; + let _ = a(1, 2); + let _ = b(1, 2); +} diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr new file mode 100644 index 000000000..fd9a5bcbf --- /dev/null +++ b/tests/ui/lint/unused/lint-unused-variables.stderr @@ -0,0 +1,74 @@ +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:8:5 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/lint-unused-variables.rs:5:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:14:5 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:22:9 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:29:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:34:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:42:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:47:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:55:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:60:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `a` + --> $DIR/lint-unused-variables.rs:68:9 + | +LL | a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/lint-unused-variables.rs:74:9 + | +LL | b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: aborting due to 11 previous errors + diff --git a/tests/ui/lint/unused/must-use-box-from-raw.rs b/tests/ui/lint/unused/must-use-box-from-raw.rs new file mode 100644 index 000000000..9ea772689 --- /dev/null +++ b/tests/ui/lint/unused/must-use-box-from-raw.rs @@ -0,0 +1,11 @@ +// #99269 + +// check-pass + +#![warn(unused_must_use)] + +unsafe fn free(ptr: *mut T) { + Box::from_raw(ptr); //~ WARNING unused return value +} + +fn main() {} diff --git a/tests/ui/lint/unused/must-use-box-from-raw.stderr b/tests/ui/lint/unused/must-use-box-from-raw.stderr new file mode 100644 index 000000000..47ab613be --- /dev/null +++ b/tests/ui/lint/unused/must-use-box-from-raw.stderr @@ -0,0 +1,15 @@ +warning: unused return value of `Box::::from_raw` that must be used + --> $DIR/must-use-box-from-raw.rs:8:5 + | +LL | Box::from_raw(ptr); + | ^^^^^^^^^^^^^^^^^^ + | + = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box` +note: the lint level is defined here + --> $DIR/must-use-box-from-raw.rs:5:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/unused/must-use-ops.rs b/tests/ui/lint/unused/must-use-ops.rs new file mode 100644 index 000000000..60f877aa8 --- /dev/null +++ b/tests/ui/lint/unused/must-use-ops.rs @@ -0,0 +1,51 @@ +// Issue #50124 - Test warning for unused operator expressions + +// check-pass + +#![warn(unused_must_use)] +#![feature(never_type)] + +fn deref_never(x: &!) { + // Don't lint for uninhabited typess + *x; +} + +fn main() { + let val = 1; + let val_pointer = &val; + + // Comparison Operators + val == 1; //~ WARNING unused comparison + val < 1; //~ WARNING unused comparison + val <= 1; //~ WARNING unused comparison + val != 1; //~ WARNING unused comparison + val >= 1; //~ WARNING unused comparison + val > 1; //~ WARNING unused comparison + + // Arithmetic Operators + val + 2; //~ WARNING unused arithmetic operation + val - 2; //~ WARNING unused arithmetic operation + val / 2; //~ WARNING unused arithmetic operation + val * 2; //~ WARNING unused arithmetic operation + val % 2; //~ WARNING unused arithmetic operation + + // Logical Operators + true && true; //~ WARNING unused logical operation + false || true; //~ WARNING unused logical operation + + // Bitwise Operators + 5 ^ val; //~ WARNING unused bitwise operation + 5 & val; //~ WARNING unused bitwise operation + 5 | val; //~ WARNING unused bitwise operation + 5 << val; //~ WARNING unused bitwise operation + 5 >> val; //~ WARNING unused bitwise operation + + // Unary Operators + !val; //~ WARNING unused unary operation + -val; //~ WARNING unused unary operation + *val_pointer; //~ WARNING unused unary operation + + if false { + deref_never(&panic!()); + } +} diff --git a/tests/ui/lint/unused/must-use-ops.stderr b/tests/ui/lint/unused/must-use-ops.stderr new file mode 100644 index 000000000..79a53d39c --- /dev/null +++ b/tests/ui/lint/unused/must-use-ops.stderr @@ -0,0 +1,238 @@ +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:18:5 + | +LL | val == 1; + | ^^^^^^^^ the comparison produces a value + | +note: the lint level is defined here + --> $DIR/must-use-ops.rs:5:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val == 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:19:5 + | +LL | val < 1; + | ^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val < 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:20:5 + | +LL | val <= 1; + | ^^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val <= 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:21:5 + | +LL | val != 1; + | ^^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val != 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:22:5 + | +LL | val >= 1; + | ^^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val >= 1; + | +++++++ + +warning: unused comparison that must be used + --> $DIR/must-use-ops.rs:23:5 + | +LL | val > 1; + | ^^^^^^^ the comparison produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val > 1; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:26:5 + | +LL | val + 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val + 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:27:5 + | +LL | val - 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val - 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:28:5 + | +LL | val / 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val / 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:29:5 + | +LL | val * 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val * 2; + | +++++++ + +warning: unused arithmetic operation that must be used + --> $DIR/must-use-ops.rs:30:5 + | +LL | val % 2; + | ^^^^^^^ the arithmetic operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = val % 2; + | +++++++ + +warning: unused logical operation that must be used + --> $DIR/must-use-ops.rs:33:5 + | +LL | true && true; + | ^^^^^^^^^^^^ the logical operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = true && true; + | +++++++ + +warning: unused logical operation that must be used + --> $DIR/must-use-ops.rs:34:5 + | +LL | false || true; + | ^^^^^^^^^^^^^ the logical operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = false || true; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:37:5 + | +LL | 5 ^ val; + | ^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 ^ val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:38:5 + | +LL | 5 & val; + | ^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 & val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:39:5 + | +LL | 5 | val; + | ^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 | val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:40:5 + | +LL | 5 << val; + | ^^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 << val; + | +++++++ + +warning: unused bitwise operation that must be used + --> $DIR/must-use-ops.rs:41:5 + | +LL | 5 >> val; + | ^^^^^^^^ the bitwise operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = 5 >> val; + | +++++++ + +warning: unused unary operation that must be used + --> $DIR/must-use-ops.rs:44:5 + | +LL | !val; + | ^^^^ the unary operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = !val; + | +++++++ + +warning: unused unary operation that must be used + --> $DIR/must-use-ops.rs:45:5 + | +LL | -val; + | ^^^^ the unary operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = -val; + | +++++++ + +warning: unused unary operation that must be used + --> $DIR/must-use-ops.rs:46:5 + | +LL | *val_pointer; + | ^^^^^^^^^^^^ the unary operation produces a value + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = *val_pointer; + | +++++++ + +warning: 21 warnings emitted + diff --git a/tests/ui/lint/unused/must_use-array.rs b/tests/ui/lint/unused/must_use-array.rs new file mode 100644 index 000000000..b7bae4b0a --- /dev/null +++ b/tests/ui/lint/unused/must_use-array.rs @@ -0,0 +1,54 @@ +#![deny(unused_must_use)] + +#[must_use] +#[derive(Clone, Copy)] +struct S; + +struct A; + +#[must_use] +trait T {} + +impl T for A {} + +fn empty() -> [S; 0] { + [] +} + +fn singleton() -> [S; 1] { + [S] +} + +fn many() -> [S; 4] { + [S, S, S, S] +} + +fn array_of_impl_trait() -> [impl T; 2] { + [A, A] +} + +fn impl_array() -> [(u8, Box); 2] { + [(0, Box::new(A)), (0, Box::new(A))] +} + +fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] { + [[[S], [S]]] +} + +fn usize_max() -> [S; usize::MAX] { + [S; usize::MAX] +} + +fn main() { + empty(); // ok + singleton(); //~ ERROR unused array of `S` that must be used + many(); //~ ERROR unused array of `S` that must be used + ([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used + array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used + impl_array(); + //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used + array_of_arrays_of_arrays(); + //~^ ERROR unused array of arrays of arrays of `S` that must be used + usize_max(); + //~^ ERROR unused array of `S` that must be used +} diff --git a/tests/ui/lint/unused/must_use-array.stderr b/tests/ui/lint/unused/must_use-array.stderr new file mode 100644 index 000000000..61ef2088d --- /dev/null +++ b/tests/ui/lint/unused/must_use-array.stderr @@ -0,0 +1,50 @@ +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:44:5 + | +LL | singleton(); + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-array.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:45:5 + | +LL | many(); + | ^^^^^^ + +error: unused array of `S` in tuple element 0 that must be used + --> $DIR/must_use-array.rs:46:6 + | +LL | ([S], 0, ()); + | ^^^ + +error: unused array of implementers of `T` that must be used + --> $DIR/must_use-array.rs:47:5 + | +LL | array_of_impl_trait(); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: unused array of boxed `T` trait objects in tuple element 1 that must be used + --> $DIR/must_use-array.rs:48:5 + | +LL | impl_array(); + | ^^^^^^^^^^^^ + +error: unused array of arrays of arrays of `S` that must be used + --> $DIR/must_use-array.rs:50:5 + | +LL | array_of_arrays_of_arrays(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused array of `S` that must be used + --> $DIR/must_use-array.rs:52:5 + | +LL | usize_max(); + | ^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/unused/must_use-in-stdlib-traits.rs b/tests/ui/lint/unused/must_use-in-stdlib-traits.rs new file mode 100644 index 000000000..70dddf61f --- /dev/null +++ b/tests/ui/lint/unused/must_use-in-stdlib-traits.rs @@ -0,0 +1,47 @@ +#![deny(unused_must_use)] +#![feature(arbitrary_self_types)] + +use std::iter::Iterator; +use std::future::Future; + +use std::task::{Context, Poll}; +use std::pin::Pin; +use std::unimplemented; + +struct MyFuture; + +impl Future for MyFuture { + type Output = u32; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +fn iterator() -> impl Iterator { + std::iter::empty::() +} + +fn future() -> impl Future { + MyFuture +} + +fn square_fn_once() -> impl FnOnce(u32) -> u32 { + |x| x * x +} + +fn square_fn_mut() -> impl FnMut(u32) -> u32 { + |x| x * x +} + +fn square_fn() -> impl Fn(u32) -> u32 { + |x| x * x +} + +fn main() { + iterator(); //~ ERROR unused implementer of `Iterator` that must be used + future(); //~ ERROR unused implementer of `Future` that must be used + square_fn_once(); //~ ERROR unused implementer of `FnOnce` that must be used + square_fn_mut(); //~ ERROR unused implementer of `FnMut` that must be used + square_fn(); //~ ERROR unused implementer of `Fn` that must be used +} diff --git a/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr b/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr new file mode 100644 index 000000000..ef738708d --- /dev/null +++ b/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr @@ -0,0 +1,47 @@ +error: unused implementer of `Iterator` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:42:4 + | +LL | iterator(); + | ^^^^^^^^^^ + | + = note: iterators are lazy and do nothing unless consumed +note: the lint level is defined here + --> $DIR/must_use-in-stdlib-traits.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:43:4 + | +LL | future(); + | ^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused implementer of `FnOnce` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:44:4 + | +LL | square_fn_once(); + | ^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused implementer of `FnMut` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:45:4 + | +LL | square_fn_mut(); + | ^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused implementer of `Fn` that must be used + --> $DIR/must_use-in-stdlib-traits.rs:46:4 + | +LL | square_fn(); + | ^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-trait.rs b/tests/ui/lint/unused/must_use-trait.rs new file mode 100644 index 000000000..0aa751443 --- /dev/null +++ b/tests/ui/lint/unused/must_use-trait.rs @@ -0,0 +1,39 @@ +#![deny(unused_must_use)] + +#[must_use] +trait Critical {} + +trait NotSoCritical {} + +trait DecidedlyUnimportant {} + +struct Anon; + +impl Critical for Anon {} +impl NotSoCritical for Anon {} +impl DecidedlyUnimportant for Anon {} + +fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant { + Anon {} +} + +fn get_boxed_critical() -> Box { + Box::new(Anon {}) +} + +fn get_nested_boxed_critical() -> Box> { + Box::new(Box::new(Anon {})) +} + +fn get_critical_tuple() -> (u32, Box, impl Critical, ()) { + (0, get_boxed_critical(), get_critical(), ()) +} + +fn main() { + get_critical(); //~ ERROR unused implementer of `Critical` that must be used + get_boxed_critical(); //~ ERROR unused boxed `Critical` trait object that must be used + get_nested_boxed_critical(); + //~^ ERROR unused boxed boxed `Critical` trait object that must be used + get_critical_tuple(); //~ ERROR unused boxed `Critical` trait object in tuple element 1 + //~^ ERROR unused implementer of `Critical` in tuple element 2 +} diff --git a/tests/ui/lint/unused/must_use-trait.stderr b/tests/ui/lint/unused/must_use-trait.stderr new file mode 100644 index 000000000..2f5496484 --- /dev/null +++ b/tests/ui/lint/unused/must_use-trait.stderr @@ -0,0 +1,38 @@ +error: unused implementer of `Critical` that must be used + --> $DIR/must_use-trait.rs:33:5 + | +LL | get_critical(); + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-trait.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused boxed `Critical` trait object that must be used + --> $DIR/must_use-trait.rs:34:5 + | +LL | get_boxed_critical(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused boxed boxed `Critical` trait object that must be used + --> $DIR/must_use-trait.rs:35:5 + | +LL | get_nested_boxed_critical(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused boxed `Critical` trait object in tuple element 1 that must be used + --> $DIR/must_use-trait.rs:37:5 + | +LL | get_critical_tuple(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: unused implementer of `Critical` in tuple element 2 that must be used + --> $DIR/must_use-trait.rs:37:5 + | +LL | get_critical_tuple(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-tuple.rs b/tests/ui/lint/unused/must_use-tuple.rs new file mode 100644 index 000000000..0f0aa2025 --- /dev/null +++ b/tests/ui/lint/unused/must_use-tuple.rs @@ -0,0 +1,17 @@ +#![deny(unused_must_use)] + +fn foo() -> (Result<(), ()>, ()) { + (Ok::<(), ()>(()), ()) +} + +fn main() { + (Ok::<(), ()>(()),); //~ ERROR unused `Result` + + (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5); + //~^ ERROR unused `Result` + //~^^ ERROR unused `Result` + + foo(); //~ ERROR unused `Result` + + ((Err::<(), ()>(()), ()), ()); //~ ERROR unused `Result` +} diff --git a/tests/ui/lint/unused/must_use-tuple.stderr b/tests/ui/lint/unused/must_use-tuple.stderr new file mode 100644 index 000000000..63e0318fb --- /dev/null +++ b/tests/ui/lint/unused/must_use-tuple.stderr @@ -0,0 +1,47 @@ +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:8:6 + | +LL | (Ok::<(), ()>(()),); + | ^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +note: the lint level is defined here + --> $DIR/must_use-tuple.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:10:6 + | +LL | (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5); + | ^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: unused `Result` in tuple element 2 that must be used + --> $DIR/must_use-tuple.rs:10:27 + | +LL | (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5); + | ^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:14:5 + | +LL | foo(); + | ^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: unused `Result` in tuple element 0 that must be used + --> $DIR/must_use-tuple.rs:16:7 + | +LL | ((Err::<(), ()>(()), ()), ()); + | ^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/must_use-unit.rs b/tests/ui/lint/unused/must_use-unit.rs new file mode 100644 index 000000000..4dd4798ab --- /dev/null +++ b/tests/ui/lint/unused/must_use-unit.rs @@ -0,0 +1,16 @@ +#![feature(never_type)] +#![deny(unused_must_use)] + +#[must_use] +fn foo() {} + +#[must_use] +fn bar() -> ! { + unimplemented!() +} + +fn main() { + foo(); //~ unused return value of `foo` + + bar(); //~ unused return value of `bar` +} diff --git a/tests/ui/lint/unused/must_use-unit.stderr b/tests/ui/lint/unused/must_use-unit.stderr new file mode 100644 index 000000000..9fcbc5074 --- /dev/null +++ b/tests/ui/lint/unused/must_use-unit.stderr @@ -0,0 +1,20 @@ +error: unused return value of `foo` that must be used + --> $DIR/must_use-unit.rs:13:5 + | +LL | foo(); + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/must_use-unit.rs:2:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `bar` that must be used + --> $DIR/must_use-unit.rs:15:5 + | +LL | bar(); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/no-unused-parens-return-block.rs b/tests/ui/lint/unused/no-unused-parens-return-block.rs new file mode 100644 index 000000000..37dc519a2 --- /dev/null +++ b/tests/ui/lint/unused/no-unused-parens-return-block.rs @@ -0,0 +1,9 @@ +// run-pass + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + match (return) {} // ok + if (return) {} // ok +} diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs new file mode 100644 index 000000000..4be93aa15 --- /dev/null +++ b/tests/ui/lint/unused/unused-async.rs @@ -0,0 +1,62 @@ +// edition:2018 +#![deny(unused_must_use)] + + +#[must_use] +async fn foo() -> i32 { + 1 +} + +#[must_use] +fn bar() -> impl std::future::Future { + async { + 42 + } +} + +async fn baz() -> i32 { + 0 +} + +struct Wowee {} + +impl Wowee { + #[must_use] + async fn test_method() -> i32 { + 1 + } +} + +async fn test() { + foo(); //~ ERROR unused return value of `foo` that must be used + //~^ ERROR unused implementer of `Future` that must be used + foo().await; //~ ERROR unused output of future returned by `foo` that must be used + bar(); //~ ERROR unused return value of `bar` that must be used + //~^ ERROR unused implementer of `Future` that must be used + bar().await; //~ ERROR unused output of future returned by `bar` that must be used + baz(); //~ ERROR unused implementer of `Future` that must be used + baz().await; // ok +} + +/* FIXME(guswynn) update this test when async-fn-in-traits works +trait Doer { + #[must_use] + async fn test_trait_method() -> i32; + WARNING must_use + async fn test_other_trait() -> i32; +} + +impl Doer for Wowee { + async fn test_trait_method() -> i32 { + 1 + } + #[must_use] + async fn test_other_trait() -> i32 { + WARNING must_use + 1 + } +} +*/ + +fn main() { +} diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr new file mode 100644 index 000000000..4bcb26dc1 --- /dev/null +++ b/tests/ui/lint/unused/unused-async.stderr @@ -0,0 +1,55 @@ +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:31:5 + | +LL | foo(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them +note: the lint level is defined here + --> $DIR/unused-async.rs:2:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `foo` that must be used + --> $DIR/unused-async.rs:31:5 + | +LL | foo(); + | ^^^^^ + +error: unused output of future returned by `foo` that must be used + --> $DIR/unused-async.rs:33:5 + | +LL | foo().await; + | ^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:34:5 + | +LL | bar(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused return value of `bar` that must be used + --> $DIR/unused-async.rs:34:5 + | +LL | bar(); + | ^^^^^ + +error: unused output of future returned by `bar` that must be used + --> $DIR/unused-async.rs:36:5 + | +LL | bar().await; + | ^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-async.rs:37:5 + | +LL | baz(); + | ^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs new file mode 100644 index 000000000..692617eac --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -0,0 +1,105 @@ +// Tests for repeating attribute warnings. +// aux-build:lint_unused_extern_crate.rs +// compile-flags:--test +// Not tested due to extra requirements: +// - panic_handler: needs extra setup +// - target_feature: platform-specific +// - link_section: platform-specific +// - proc_macro, proc_macro_derive, proc_macro_attribute: needs to be a +// proc-macro, and have special handling for mixing. +// - unstable attributes (not going to bother) +// - no_main: extra setup +#![deny(unused_attributes)] +#![crate_name = "unused_attr_duplicate"] +#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![recursion_limit = "128"] +#![recursion_limit = "256"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![type_length_limit = "1048576"] +#![type_length_limit = "1"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_std] +#![no_std] //~ ERROR unused attribute +#![no_implicit_prelude] +#![no_implicit_prelude] //~ ERROR unused attribute +#![windows_subsystem = "console"] +#![windows_subsystem = "windows"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#![no_builtins] +#![no_builtins] //~ ERROR unused attribute + +#[no_link] +#[no_link] //~ ERROR unused attribute +extern crate lint_unused_extern_crate; + +#[macro_use] +#[macro_use] //~ ERROR unused attribute +pub mod m { + #[macro_export] + #[macro_export] //~ ERROR unused attribute + macro_rules! foo { + () => {}; + } +} + +#[path = "auxiliary/lint_unused_extern_crate.rs"] +#[path = "bar.rs"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +pub mod from_path; + +#[test] +#[ignore] +#[ignore = "some text"] //~ ERROR unused attribute +#[should_panic] +#[should_panic(expected = "values don't match")] //~ ERROR unused attribute +//~^ WARN this was previously accepted +fn t1() {} + +#[must_use] +#[must_use = "some message"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +// No warnings for #[repr], would require more logic. +#[repr(C)] +#[repr(C)] +#[non_exhaustive] +#[non_exhaustive] //~ ERROR unused attribute +pub struct X; + +#[automatically_derived] +#[automatically_derived] //~ ERROR unused attribute +impl X {} + +#[inline(always)] +#[inline(never)] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[cold] +#[cold] //~ ERROR unused attribute +#[track_caller] +#[track_caller] //~ ERROR unused attribute +pub fn xyz() {} + +// No warnings for #[link], would require more logic. +#[link(name = "rust_test_helpers", kind = "static")] +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[link_name = "this_does_not_exist"] //~ ERROR unused attribute + //~^ WARN this was previously accepted + #[link_name = "rust_dbg_extern_identity_u32"] + pub fn name_in_rust(v: u32) -> u32; +} + +#[export_name = "exported_symbol_name"] //~ ERROR unused attribute +//~^ WARN this was previously accepted +#[export_name = "exported_symbol_name2"] +pub fn export_test() {} + +#[no_mangle] +#[no_mangle] //~ ERROR unused attribute +pub fn no_mangle_test() {} + +#[used] +#[used] //~ ERROR unused attribute +static FOO: u32 = 0; + +fn main() {} diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr new file mode 100644 index 000000000..769b17487 --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -0,0 +1,293 @@ +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:33:1 + | +LL | #[no_link] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:32:1 + | +LL | #[no_link] + | ^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/unused-attr-duplicate.rs:12:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:37:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:36:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:47:1 + | +LL | #[path = "bar.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:46:1 + | +LL | #[path = "auxiliary/lint_unused_extern_crate.rs"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:53:1 + | +LL | #[ignore = "some text"] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:52:1 + | +LL | #[ignore] + | ^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:55:1 + | +LL | #[should_panic(expected = "values don't match")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:54:1 + | +LL | #[should_panic] + | ^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:60:1 + | +LL | #[must_use = "some message"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:59:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:66:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:65:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:70:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:69:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:74:1 + | +LL | #[inline(never)] + | ^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:73:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:77:1 + | +LL | #[cold] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:76:1 + | +LL | #[cold] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:79:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:78:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:92:1 + | +LL | #[export_name = "exported_symbol_name"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:94:1 + | +LL | #[export_name = "exported_symbol_name2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:98:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:97:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:102:1 + | +LL | #[used] + | ^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:101:1 + | +LL | #[used] + | ^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:86:5 + | +LL | #[link_name = "this_does_not_exist"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:88:5 + | +LL | #[link_name = "rust_dbg_extern_identity_u32"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:14:1 + | +LL | #![crate_name = "unused_attr_duplicate2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:13:1 + | +LL | #![crate_name = "unused_attr_duplicate"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:17:1 + | +LL | #![recursion_limit = "256"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:16:1 + | +LL | #![recursion_limit = "128"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:20:1 + | +LL | #![type_length_limit = "1"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:19:1 + | +LL | #![type_length_limit = "1048576"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:23:1 + | +LL | #![no_std] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:22:1 + | +LL | #![no_std] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:25:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:24:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:27:1 + | +LL | #![windows_subsystem = "windows"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:26:1 + | +LL | #![windows_subsystem = "console"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:30:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:29:1 + | +LL | #![no_builtins] + | ^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:40:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:39:5 + | +LL | #[macro_export] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 23 previous errors + diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs new file mode 100644 index 000000000..c0fc280ab --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs @@ -0,0 +1,33 @@ +#![deny(unused_attributes)] +// Unused attributes on macro_rules requires special handling since the +// macro_rules definition does not survive towards HIR. + +// A sample of various built-in attributes. +#[macro_export] +#[macro_use] //~ ERROR `#[macro_use]` only has an effect +#[path="foo"] //~ ERROR #[path]` only has an effect +#[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute +macro_rules! foo { + () => {}; +} + +// The following should not warn about unused attributes. +#[allow(unused)] +macro_rules! foo2 { + () => {}; +} + +#[cfg(FALSE)] +macro_rules! foo { + () => {}; +} + +/// Some docs +#[deprecated] +#[doc = "more docs"] +#[macro_export] +macro_rules! bar { + () => {}; +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr new file mode 100644 index 000000000..e3ca90d9a --- /dev/null +++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr @@ -0,0 +1,26 @@ +error: `#[macro_use]` only has an effect on `extern crate` and modules + --> $DIR/unused-attr-macro-rules.rs:7:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-attr-macro-rules.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[path]` only has an effect on modules + --> $DIR/unused-attr-macro-rules.rs:8:1 + | +LL | #[path="foo"] + | ^^^^^^^^^^^^^ + +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/unused-attr-macro-rules.rs:9:1 + | +LL | #[recursion_limit="1"] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs new file mode 100644 index 000000000..c96c90731 --- /dev/null +++ b/tests/ui/lint/unused/unused-closure.rs @@ -0,0 +1,35 @@ +// Test that closures and generators are "must use" types. +// edition:2018 + +#![feature(async_closure)] +#![feature(generators)] +#![deny(unused_must_use)] + +fn unused() { + || { //~ ERROR unused closure that must be used + println!("Hello!"); + }; + + async {}; //~ ERROR unused implementer of `Future` that must be used + || async {}; //~ ERROR unused closure that must be used + async || {}; //~ ERROR unused closure that must be used + + + [Box::new([|| {}; 10]); 1]; //~ ERROR unused array of boxed arrays of closures that must be used + + vec![|| "a"].pop().unwrap(); //~ ERROR unused closure that must be used + + let b = false; + || true; //~ ERROR unused closure that must be used + println!("{}", b); +} + +fn ignored() { + let _ = || {}; + let _ = || yield 42; +} + +fn main() { + unused(); + ignored(); +} diff --git a/tests/ui/lint/unused/unused-closure.stderr b/tests/ui/lint/unused/unused-closure.stderr new file mode 100644 index 000000000..c3a82402e --- /dev/null +++ b/tests/ui/lint/unused/unused-closure.stderr @@ -0,0 +1,65 @@ +error: unused closure that must be used + --> $DIR/unused-closure.rs:9:5 + | +LL | / || { +LL | | println!("Hello!"); +LL | | }; + | |_____^ + | + = note: closures are lazy and do nothing unless called +note: the lint level is defined here + --> $DIR/unused-closure.rs:6:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused implementer of `Future` that must be used + --> $DIR/unused-closure.rs:13:5 + | +LL | async {}; + | ^^^^^^^^ + | + = note: futures do nothing unless you `.await` or poll them + +error: unused closure that must be used + --> $DIR/unused-closure.rs:14:5 + | +LL | || async {}; + | ^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:15:5 + | +LL | async || {}; + | ^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused array of boxed arrays of closures that must be used + --> $DIR/unused-closure.rs:18:5 + | +LL | [Box::new([|| {}; 10]); 1]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:20:5 + | +LL | vec![|| "a"].pop().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: unused closure that must be used + --> $DIR/unused-closure.rs:23:9 + | +LL | || true; + | ^^^^^^^ + | + = note: closures are lazy and do nothing unless called + +error: aborting due to 7 previous errors + diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs new file mode 100644 index 000000000..54d86c31f --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs @@ -0,0 +1,46 @@ +#![deny(unused_doc_comments)] + +fn doc_comment_on_match_arms(num: u8) -> bool { + match num { + 3 => true, + /// useless doc comment + //~^ ERROR: unused doc comment + _ => false, + } +} + +fn doc_comment_between_if_else(num: u8) -> bool { + if num == 3 { + true //~ ERROR: mismatched types + } + /// useless doc comment + else { //~ ERROR: expected expression, found keyword `else` + false + } +} + +fn doc_comment_on_expr(num: u8) -> bool { + /// useless doc comment + //~^ ERROR: attributes on expressions are experimental + //~| ERROR: unused doc comment + num == 3 +} + +fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {} +//~^ ERROR: unused doc comment + +fn doc_comment_on_block() { + /// unused doc comment + //~^ ERROR: unused doc comment + { + let x = 12; + } +} + +/// unused doc comment +//~^ ERROR: unused doc comment +extern "C" { + fn foo(); +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr new file mode 100644 index 000000000..078b780d8 --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr @@ -0,0 +1,95 @@ +error: expected expression, found keyword `else` + --> $DIR/unused-doc-comments-edge-cases.rs:17:5 + | +LL | else { + | ^^^^ expected expression + +error[E0658]: attributes on expressions are experimental + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + = help: `///` is for documentation comments. For a plain comment, use `//`. + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:6:9 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | _ => false, + | ---------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment +note: the lint level is defined here + --> $DIR/unused-doc-comments-edge-cases.rs:1:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:23:5 + | +LL | /// useless doc comment + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | num == 3 + | --- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:29:27 + | +LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {} + | ^^^^^^^^^^^^ - rustdoc does not generate documentation for generic parameters + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:33:5 + | +LL | /// unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / { +LL | | let x = 12; +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:40:1 + | +LL | /// unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / extern "C" { +LL | | fn foo(); +LL | | } + | |_- rustdoc does not generate documentation for extern blocks + | + = help: use `//` for a plain comment + +error[E0308]: mismatched types + --> $DIR/unused-doc-comments-edge-cases.rs:14:9 + | +LL | / if num == 3 { +LL | | true + | | ^^^^ expected `()`, found `bool` +LL | | } + | |_____- expected this to be `()` + | +help: you might have meant to return this value + | +LL | return true; + | ++++++ + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.rs b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs new file mode 100644 index 000000000..05828ebb2 --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs @@ -0,0 +1,17 @@ +#![deny(unused_doc_comments)] +#![feature(rustc_attrs)] + +macro_rules! foo { () => {}; } + +fn main() { + /// line1 //~ ERROR: unused doc comment + /// line2 + /// line3 + foo!(); + + // Ensure we still detect another doc-comment block. + /// line1 //~ ERROR: unused doc comment + /// line2 + /// line3 + foo!(); +} diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr b/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr new file mode 100644 index 000000000..26b1c2b05 --- /dev/null +++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr @@ -0,0 +1,31 @@ +error: unused doc comment + --> $DIR/unused-doc-comments-for-macros.rs:7:5 + | +LL | / /// line1 +LL | | /// line2 +LL | | /// line3 + | |_____--------^ + | | + | rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion +note: the lint level is defined here + --> $DIR/unused-doc-comments-for-macros.rs:1:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/unused-doc-comments-for-macros.rs:13:5 + | +LL | / /// line1 +LL | | /// line2 +LL | | /// line3 + | |_____--------^ + | | + | rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.rs b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs new file mode 100644 index 000000000..4d51db89b --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs @@ -0,0 +1,27 @@ +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +macro_rules! num { + (one) => { 1 }; + // Most simple (and common) case + (two) => { compile_error!("foo"); }; + // Some nested use + (two_) => { foo(compile_error!("foo")); }; + (three) => { 3 }; + (four) => { 4 }; //~ ERROR: rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// compile_error not used as a macro invocation +macro_rules! num2 { + (one) => { 1 }; + // Only identifier present + (two) => { fn compile_error() {} }; //~ ERROR: rule of macro + // Only identifier and bang present + (two_) => { compile_error! }; //~ ERROR: rule of macro + (three) => { 3 }; +} +const _NUM2: u8 = num2!(one) + num2!(three); + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr new file mode 100644 index 000000000..76af8c967 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr @@ -0,0 +1,26 @@ +error: 5th rule of macro `num` is never used + --> $DIR/unused-macro-rules-compile-error.rs:12:5 + | +LL | (four) => { 4 }; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules-compile-error.rs:1:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 3rd rule of macro `num2` is never used + --> $DIR/unused-macro-rules-compile-error.rs:22:5 + | +LL | (two_) => { compile_error! }; + | ^^^^^^ + +error: 2nd rule of macro `num2` is never used + --> $DIR/unused-macro-rules-compile-error.rs:20:5 + | +LL | (two) => { fn compile_error() {} }; + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.rs b/tests/ui/lint/unused/unused-macro-rules-decl.rs new file mode 100644 index 000000000..537c84940 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-decl.rs @@ -0,0 +1,49 @@ +#![feature(decl_macro)] +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +// Most simple case +macro num { + (one) => { 1 }, + (two) => { 2 }, //~ ERROR: 2nd rule of macro + (three) => { 3 }, + (four) => { 4 }, //~ ERROR: 4th rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// Check that allowing the lint works +#[allow(unused_macro_rules)] +macro num_allowed { + (one) => { 1 }, + (two) => { 2 }, + (three) => { 3 }, + (four) => { 4 }, +} +const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three); + +// Check that macro calls inside the macro trigger as usage +macro num_rec { + (one) => { 1 }, + (two) => { + num_rec!(one) + num_rec!(one) + }, + (three) => { //~ ERROR: 3rd rule of macro + num_rec!(one) + num_rec!(two) + }, + (four) => { + num_rec!(two) + num_rec!(two) + }, +} +const _NUM_RECURSIVE: u8 = num_rec!(four); + +// No error if the macro is public +pub macro num_public { + (one) => { 1 }, + (two) => { 2 }, + (three) => { 3 }, + (four) => { 4 }, +} +const _NUM_PUBLIC: u8 = num_public!(one) + num_public!(three); + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.stderr b/tests/ui/lint/unused/unused-macro-rules-decl.stderr new file mode 100644 index 000000000..4d9b22fed --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-decl.stderr @@ -0,0 +1,26 @@ +error: 4th rule of macro `num` is never used + --> $DIR/unused-macro-rules-decl.rs:11:5 + | +LL | (four) => { 4 }, + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules-decl.rs:2:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 2nd rule of macro `num` is never used + --> $DIR/unused-macro-rules-decl.rs:9:5 + | +LL | (two) => { 2 }, + | ^^^^^ + +error: 3rd rule of macro `num_rec` is never used + --> $DIR/unused-macro-rules-decl.rs:31:5 + | +LL | (three) => { + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs new file mode 100644 index 000000000..a826026ec --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs @@ -0,0 +1,11 @@ +#![deny(unused_macro_rules)] + +macro_rules! foo { + (v) => {}; + (w) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +fn main() { + foo!(v); +} diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr new file mode 100644 index 000000000..797c86710 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr @@ -0,0 +1,8 @@ +error: macro rhs must be delimited + --> $DIR/unused-macro-rules-malformed-rule.rs:6:11 + | +LL | () => 0; + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-macro-rules.rs b/tests/ui/lint/unused/unused-macro-rules.rs new file mode 100644 index 000000000..eeaf4d1b0 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules.rs @@ -0,0 +1,47 @@ +#![deny(unused_macro_rules)] +// To make sure we are not hitting this +#![deny(unused_macros)] + +// Most simple case +macro_rules! num { + (one) => { 1 }; + (two) => { 2 }; //~ ERROR: 2nd rule of macro + (three) => { 3 }; + (four) => { 4 }; //~ ERROR: 4th rule of macro +} +const _NUM: u8 = num!(one) + num!(three); + +// Check that allowing the lint works +#[allow(unused_macro_rules)] +macro_rules! num_allowed { + (one) => { 1 }; + (two) => { 2 }; + (three) => { 3 }; + (four) => { 4 }; +} +const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three); + +// Check that macro calls inside the macro trigger as usage +macro_rules! num_rec { + (one) => { 1 }; + (two) => { + num_rec!(one) + num_rec!(one) + }; + (three) => { //~ ERROR: 3rd rule of macro + num_rec!(one) + num_rec!(two) + }; + (four) => { num_rec!(two) + num_rec!(two) }; +} +const _NUM_RECURSIVE: u8 = num_rec!(four); + +// No error if the macro is being exported +#[macro_export] +macro_rules! num_exported { + (one) => { 1 }; + (two) => { 2 }; + (three) => { 3 }; + (four) => { 4 }; +} +const _NUM_EXPORTED: u8 = num_exported!(one) + num_exported!(three); + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macro-rules.stderr b/tests/ui/lint/unused/unused-macro-rules.stderr new file mode 100644 index 000000000..2b3098a51 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-rules.stderr @@ -0,0 +1,26 @@ +error: 4th rule of macro `num` is never used + --> $DIR/unused-macro-rules.rs:10:5 + | +LL | (four) => { 4 }; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-rules.rs:1:9 + | +LL | #![deny(unused_macro_rules)] + | ^^^^^^^^^^^^^^^^^^ + +error: 2nd rule of macro `num` is never used + --> $DIR/unused-macro-rules.rs:8:5 + | +LL | (two) => { 2 }; + | ^^^^^ + +error: 3rd rule of macro `num_rec` is never used + --> $DIR/unused-macro-rules.rs:30:5 + | +LL | (three) => { + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs new file mode 100644 index 000000000..ce187047b --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs @@ -0,0 +1,9 @@ +#![allow(unused_macros)] + +// Issue #21370 + +macro_rules! test { + ($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty` +} + +fn main() { } diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr new file mode 100644 index 000000000..6edf0a2cf --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr @@ -0,0 +1,10 @@ +error: invalid fragment specifier `t_ty` + --> $DIR/unused-macro-with-bad-frag-spec.rs:6:6 + | +LL | ($wrong:t_ty) => () + | ^^^^^^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.rs b/tests/ui/lint/unused/unused-macro-with-follow-violation.rs new file mode 100644 index 000000000..1666dae69 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.rs @@ -0,0 +1,7 @@ +#![allow(unused_macros)] + +macro_rules! test { + ($e:expr +) => () //~ ERROR not allowed for `expr` fragments +} + +fn main() { } diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr new file mode 100644 index 000000000..5eced4f06 --- /dev/null +++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr @@ -0,0 +1,10 @@ +error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments + --> $DIR/unused-macro-with-follow-violation.rs:4:14 + | +LL | ($e:expr +) => () + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-macros-decl.rs b/tests/ui/lint/unused/unused-macros-decl.rs new file mode 100644 index 000000000..21f6108b1 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-decl.rs @@ -0,0 +1,28 @@ +#![feature(decl_macro)] +#![deny(unused_macros)] +// To make sure we are not hitting this +#![deny(unused_macro_rules)] + +// Most simple case +macro unused { //~ ERROR: unused macro definition + () => {} +} + +#[allow(unused_macros)] +mod bar { + // Test that putting the #[deny] close to the macro's definition + // works. + + #[deny(unused_macros)] + macro unused { //~ ERROR: unused macro definition + () => {} + } +} + +mod boo { + pub(crate) macro unused { //~ ERROR: unused macro definition + () => {} + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macros-decl.stderr b/tests/ui/lint/unused/unused-macros-decl.stderr new file mode 100644 index 000000000..1f426b9d9 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-decl.stderr @@ -0,0 +1,32 @@ +error: unused macro definition: `unused` + --> $DIR/unused-macros-decl.rs:7:7 + | +LL | macro unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-decl.rs:2:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros-decl.rs:17:11 + | +LL | macro unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-decl.rs:16:12 + | +LL | #[deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros-decl.rs:23:22 + | +LL | pub(crate) macro unused { + | ^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macros-malformed-rule.rs b/tests/ui/lint/unused/unused-macros-malformed-rule.rs new file mode 100644 index 000000000..d4c35fad9 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-malformed-rule.rs @@ -0,0 +1,15 @@ +#![deny(unused_macros)] + +macro_rules! foo { //~ ERROR: unused macro definition + (v) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +macro_rules! bar { + (v) => {}; + () => 0; //~ ERROR: macro rhs must be delimited +} + +fn main() { + bar!(v); +} diff --git a/tests/ui/lint/unused/unused-macros-malformed-rule.stderr b/tests/ui/lint/unused/unused-macros-malformed-rule.stderr new file mode 100644 index 000000000..9a880dccf --- /dev/null +++ b/tests/ui/lint/unused/unused-macros-malformed-rule.stderr @@ -0,0 +1,26 @@ +error: macro rhs must be delimited + --> $DIR/unused-macros-malformed-rule.rs:5:11 + | +LL | () => 0; + | ^ + +error: macro rhs must be delimited + --> $DIR/unused-macros-malformed-rule.rs:10:11 + | +LL | () => 0; + | ^ + +error: unused macro definition: `foo` + --> $DIR/unused-macros-malformed-rule.rs:3:14 + | +LL | macro_rules! foo { + | ^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros-malformed-rule.rs:1:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-macros.rs b/tests/ui/lint/unused/unused-macros.rs new file mode 100644 index 000000000..70b50b208 --- /dev/null +++ b/tests/ui/lint/unused/unused-macros.rs @@ -0,0 +1,31 @@ +#![deny(unused_macros)] +// To make sure we are not hitting this +#![deny(unused_macro_rules)] + +// Most simple case +macro_rules! unused { //~ ERROR: unused macro definition + () => {}; +} + +// Test macros created by macros +macro_rules! create_macro { + () => { + macro_rules! m { //~ ERROR: unused macro definition + () => {}; + } + }; +} +create_macro!(); + +#[allow(unused_macros)] +mod bar { + // Test that putting the #[deny] close to the macro's definition + // works. + + #[deny(unused_macros)] + macro_rules! unused { //~ ERROR: unused macro definition + () => {}; + } +} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-macros.stderr b/tests/ui/lint/unused/unused-macros.stderr new file mode 100644 index 000000000..d0baf5bec --- /dev/null +++ b/tests/ui/lint/unused/unused-macros.stderr @@ -0,0 +1,32 @@ +error: unused macro definition: `unused` + --> $DIR/unused-macros.rs:6:14 + | +LL | macro_rules! unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros.rs:1:9 + | +LL | #![deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: unused macro definition: `m` + --> $DIR/unused-macros.rs:13:22 + | +LL | macro_rules! m { + | ^ + +error: unused macro definition: `unused` + --> $DIR/unused-macros.rs:26:18 + | +LL | macro_rules! unused { + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macros.rs:25:12 + | +LL | #[deny(unused_macros)] + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed b/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed new file mode 100644 index 000000000..c21f18015 --- /dev/null +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#![forbid(unused_mut)] + +fn main() { + let x = 1; + //~^ ERROR: variable does not need to be mutable + (move|| { println!("{}", x); })(); +} diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.rs b/tests/ui/lint/unused/unused-mut-warning-captured-var.rs new file mode 100644 index 000000000..3119d83a0 --- /dev/null +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#![forbid(unused_mut)] + +fn main() { + let mut x = 1; + //~^ ERROR: variable does not need to be mutable + (move|| { println!("{}", x); })(); +} diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr new file mode 100644 index 000000000..20aeedcc2 --- /dev/null +++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/unused-mut-warning-captured-var.rs:6:9 + | +LL | let mut x = 1; + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/unused-mut-warning-captured-var.rs:3:11 + | +LL | #![forbid(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused-result.rs b/tests/ui/lint/unused/unused-result.rs new file mode 100644 index 000000000..e283eaa88 --- /dev/null +++ b/tests/ui/lint/unused/unused-result.rs @@ -0,0 +1,42 @@ +#![allow(dead_code)] +#![deny(unused_results, unused_must_use)] +//~^ NOTE: the lint level is defined here +//~| NOTE: the lint level is defined here + +#[must_use] +enum MustUse { Test } + +#[must_use = "some message"] +enum MustUseMsg { Test2 } + +fn foo() -> T { panic!() } + +fn bar() -> isize { return foo::(); } +fn baz() -> MustUse { return foo::(); } +fn qux() -> MustUseMsg { return foo::(); } + +#[allow(unused_results)] +fn test() { + foo::(); + foo::(); //~ ERROR: unused `MustUse` that must be used + foo::(); //~ ERROR: unused `MustUseMsg` that must be used + //~^ NOTE: some message +} + +#[allow(unused_results, unused_must_use)] +fn test2() { + foo::(); + foo::(); + foo::(); +} + +fn main() { + foo::(); //~ ERROR: unused result of type `isize` + foo::(); //~ ERROR: unused `MustUse` that must be used + foo::(); //~ ERROR: unused `MustUseMsg` that must be used + //~^ NOTE: some message + + let _ = foo::(); + let _ = foo::(); + let _ = foo::(); +} diff --git a/tests/ui/lint/unused/unused-result.stderr b/tests/ui/lint/unused/unused-result.stderr new file mode 100644 index 000000000..4e1ba1fd9 --- /dev/null +++ b/tests/ui/lint/unused/unused-result.stderr @@ -0,0 +1,48 @@ +error: unused `MustUse` that must be used + --> $DIR/unused-result.rs:21:5 + | +LL | foo::(); + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-result.rs:2:25 + | +LL | #![deny(unused_results, unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused `MustUseMsg` that must be used + --> $DIR/unused-result.rs:22:5 + | +LL | foo::(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: some message + +error: unused result of type `isize` + --> $DIR/unused-result.rs:34:5 + | +LL | foo::(); + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-result.rs:2:9 + | +LL | #![deny(unused_results, unused_must_use)] + | ^^^^^^^^^^^^^^ + +error: unused `MustUse` that must be used + --> $DIR/unused-result.rs:35:5 + | +LL | foo::(); + | ^^^^^^^^^^^^^^^^ + +error: unused `MustUseMsg` that must be used + --> $DIR/unused-result.rs:36:5 + | +LL | foo::(); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: some message + +error: aborting due to 5 previous errors + diff --git a/tests/ui/lint/unused/unused-supertrait.rs b/tests/ui/lint/unused/unused-supertrait.rs new file mode 100644 index 000000000..64a8e5204 --- /dev/null +++ b/tests/ui/lint/unused/unused-supertrait.rs @@ -0,0 +1,11 @@ +#![deny(unused_must_use)] + +fn it() -> impl ExactSizeIterator { + let x: Box> = todo!(); + x +} + +fn main() { + it(); + //~^ ERROR unused implementer of `Iterator` that must be used +} diff --git a/tests/ui/lint/unused/unused-supertrait.stderr b/tests/ui/lint/unused/unused-supertrait.stderr new file mode 100644 index 000000000..cb45add9c --- /dev/null +++ b/tests/ui/lint/unused/unused-supertrait.stderr @@ -0,0 +1,15 @@ +error: unused implementer of `Iterator` that must be used + --> $DIR/unused-supertrait.rs:9:5 + | +LL | it(); + | ^^^^ + | + = note: iterators are lazy and do nothing unless consumed +note: the lint level is defined here + --> $DIR/unused-supertrait.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs new file mode 100644 index 000000000..51f868706 --- /dev/null +++ b/tests/ui/lint/unused/unused_attributes-must_use.rs @@ -0,0 +1,131 @@ +#![allow(dead_code, path_statements)] +#![deny(unused_attributes, unused_must_use)] +#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)] + +#[must_use] //~ ERROR `#[must_use]` has no effect +extern crate std as std2; + +#[must_use] //~ ERROR `#[must_use]` has no effect +mod test_mod {} + +#[must_use] //~ ERROR `#[must_use]` has no effect +use std::arch::global_asm; + +#[must_use] //~ ERROR `#[must_use]` has no effect +const CONST: usize = 4; +#[must_use] //~ ERROR `#[must_use]` has no effect +#[no_mangle] +static STATIC: usize = 4; + +#[must_use] +struct X; + +#[must_use] +enum Y { + Z, +} + +#[must_use] +union U { + unit: (), +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +impl U { + #[must_use] + fn method() -> i32 { + 4 + } +} + +#[must_use] +#[no_mangle] +fn foo() -> i64 { + 4 +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +extern "Rust" { + #[link_name = "STATIC"] + #[must_use] //~ ERROR `#[must_use]` has no effect + static FOREIGN_STATIC: usize; + + #[link_name = "foo"] + #[must_use] + fn foreign_foo() -> i64; +} + +#[must_use] //~ ERROR unused attribute +global_asm!(""); + +#[must_use] //~ ERROR `#[must_use]` has no effect +type UseMe = (); + +fn qux<#[must_use] T>(_: T) {} //~ ERROR `#[must_use]` has no effect + +#[must_use] +trait Use { + #[must_use] //~ ERROR `#[must_use]` has no effect + const ASSOC_CONST: usize = 4; + #[must_use] //~ ERROR `#[must_use]` has no effect + type AssocTy; + + #[must_use] + fn get_four(&self) -> usize { + 4 + } +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +impl Use for () { + type AssocTy = (); +} + +#[must_use] //~ ERROR `#[must_use]` has no effect +trait Alias = Use; + +#[must_use] //~ ERROR `#[must_use]` has no effect +macro_rules! cool_macro { + () => { + 4 + }; +} + +fn main() { + #[must_use] //~ ERROR `#[must_use]` has no effect + let x = || {}; + x(); + + let x = #[must_use] //~ ERROR `#[must_use]` has no effect + || {}; + x(); + + X; //~ ERROR that must be used + Y::Z; //~ ERROR that must be used + U { unit: () }; //~ ERROR that must be used + U::method(); //~ ERROR that must be used + foo(); //~ ERROR that must be used + + unsafe { + foreign_foo(); //~ ERROR that must be used + }; + + CONST; + STATIC; + unsafe { FOREIGN_STATIC }; + cool_macro!(); + qux(4); + ().get_four(); //~ ERROR that must be used + + match Some(4) { + #[must_use] //~ ERROR `#[must_use]` has no effect + Some(res) => res, + None => 0, + }; + + struct PatternField { + foo: i32, + } + let s = PatternField { #[must_use] foo: 123 }; //~ ERROR `#[must_use]` has no effect + let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect +} diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr new file mode 100644 index 000000000..0f699429e --- /dev/null +++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr @@ -0,0 +1,187 @@ +error: unused attribute `must_use` + --> $DIR/unused_attributes-must_use.rs:58:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | +note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm` + --> $DIR/unused_attributes-must_use.rs:59:1 + | +LL | global_asm!(""); + | ^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/unused_attributes-must_use.rs:2:9 + | +LL | #![deny(unused_attributes, unused_must_use)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an extern crate + --> $DIR/unused_attributes-must_use.rs:5:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a module + --> $DIR/unused_attributes-must_use.rs:8:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a use + --> $DIR/unused_attributes-must_use.rs:11:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a constant item + --> $DIR/unused_attributes-must_use.rs:14:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a static item + --> $DIR/unused_attributes-must_use.rs:16:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an implementation block + --> $DIR/unused_attributes-must_use.rs:33:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a foreign module + --> $DIR/unused_attributes-must_use.rs:47:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a type alias + --> $DIR/unused_attributes-must_use.rs:61:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a type parameter + --> $DIR/unused_attributes-must_use.rs:64:8 + | +LL | fn qux<#[must_use] T>(_: T) {} + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an implementation block + --> $DIR/unused_attributes-must_use.rs:79:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a trait alias + --> $DIR/unused_attributes-must_use.rs:84:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a macro def + --> $DIR/unused_attributes-must_use.rs:87:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a statement + --> $DIR/unused_attributes-must_use.rs:95:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a closure + --> $DIR/unused_attributes-must_use.rs:99:13 + | +LL | let x = #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an match arm + --> $DIR/unused_attributes-must_use.rs:121:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a struct field + --> $DIR/unused_attributes-must_use.rs:129:28 + | +LL | let s = PatternField { #[must_use] foo: 123 }; + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a pattern field + --> $DIR/unused_attributes-must_use.rs:130:24 + | +LL | let PatternField { #[must_use] foo } = s; + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an associated const + --> $DIR/unused_attributes-must_use.rs:68:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to an associated type + --> $DIR/unused_attributes-must_use.rs:70:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: `#[must_use]` has no effect when applied to a foreign static item + --> $DIR/unused_attributes-must_use.rs:50:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: unused `X` that must be used + --> $DIR/unused_attributes-must_use.rs:103:5 + | +LL | X; + | ^ + | +note: the lint level is defined here + --> $DIR/unused_attributes-must_use.rs:2:28 + | +LL | #![deny(unused_attributes, unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused `Y` that must be used + --> $DIR/unused_attributes-must_use.rs:104:5 + | +LL | Y::Z; + | ^^^^ + +error: unused `U` that must be used + --> $DIR/unused_attributes-must_use.rs:105:5 + | +LL | U { unit: () }; + | ^^^^^^^^^^^^^^ + +error: unused return value of `U::method` that must be used + --> $DIR/unused_attributes-must_use.rs:106:5 + | +LL | U::method(); + | ^^^^^^^^^^^ + +error: unused return value of `foo` that must be used + --> $DIR/unused_attributes-must_use.rs:107:5 + | +LL | foo(); + | ^^^^^ + +error: unused return value of `foreign_foo` that must be used + --> $DIR/unused_attributes-must_use.rs:110:9 + | +LL | foreign_foo(); + | ^^^^^^^^^^^^^ + +error: unused return value of `Use::get_four` that must be used + --> $DIR/unused_attributes-must_use.rs:118:5 + | +LL | ().get_four(); + | ^^^^^^^^^^^^^ + +error: aborting due to 28 previous errors + diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs new file mode 100644 index 000000000..7d2e5ab6f --- /dev/null +++ b/tests/ui/lint/unused/useless-comment.rs @@ -0,0 +1,45 @@ +#![feature(stmt_expr_attributes)] + +#![deny(unused_doc_comments)] + +macro_rules! mac { + () => {} +} + +/// foo //~ ERROR unused doc comment +mac!(); + +fn foo() { + /// a //~ ERROR unused doc comment + let x = 12; + + /// multi-line //~ unused doc comment + /// doc comment + /// that is unused + match x { + /// c //~ ERROR unused doc comment + 1 => {}, + _ => {} + } + + /// foo //~ ERROR unused doc comment + unsafe {} + + #[doc = "foo"] //~ ERROR unused doc comment + #[doc = "bar"] //~ ERROR unused doc comment + 3; + + /// bar //~ ERROR unused doc comment + mac!(); + + let x = /** comment */ 47; //~ ERROR unused doc comment + + /// dox //~ ERROR unused doc comment + { + + } +} + +fn main() { + foo(); +} diff --git a/tests/ui/lint/unused/useless-comment.stderr b/tests/ui/lint/unused/useless-comment.stderr new file mode 100644 index 000000000..8bb5bdaeb --- /dev/null +++ b/tests/ui/lint/unused/useless-comment.stderr @@ -0,0 +1,110 @@ +error: unused doc comment + --> $DIR/useless-comment.rs:9:1 + | +LL | /// foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion +note: the lint level is defined here + --> $DIR/useless-comment.rs:3:9 + | +LL | #![deny(unused_doc_comments)] + | ^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/useless-comment.rs:32:5 + | +LL | /// bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion + +error: unused doc comment + --> $DIR/useless-comment.rs:13:5 + | +LL | /// a + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:16:5 + | +LL | / /// multi-line +LL | | /// doc comment +LL | | /// that is unused + | |______________________^ +LL | / match x { +LL | | /// c +LL | | 1 => {}, +LL | | _ => {} +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:20:9 + | +LL | /// c + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | 1 => {}, + | ------- rustdoc does not generate documentation for match arms + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:25:5 + | +LL | /// foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe {} + | --------- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:28:5 + | +LL | #[doc = "foo"] + | ^^^^^^^^^^^^^^ +LL | #[doc = "bar"] +LL | 3; + | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:29:5 + | +LL | #[doc = "bar"] + | ^^^^^^^^^^^^^^ +LL | 3; + | - rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:35:13 + | +LL | let x = /** comment */ 47; + | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions + | + = help: use `/* */` for a plain comment + +error: unused doc comment + --> $DIR/useless-comment.rs:37:5 + | +LL | /// dox + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / { +LL | | +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: aborting due to 10 previous errors + diff --git a/tests/ui/lint/unused_braces.fixed b/tests/ui/lint/unused_braces.fixed new file mode 100644 index 000000000..e691fb37e --- /dev/null +++ b/tests/ui/lint/unused_braces.fixed @@ -0,0 +1,57 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces, unused_parens)] +#![allow(unreachable_code, unused_unsafe)] // for rustfix + +fn consume(_: T) {} + +fn main() { + let _ = 7; + //~^WARN unnecessary parentheses + + // Do not emit a lint in these cases, + // as we have to be careful with + // `ref` patterns. + { + let _ = { 7 }; + + if let 7 = { 7 } { } + + match { 7 } { + _ => (), + } + } + + if true { + //~^ WARN unnecessary braces + } + + while false { + //~^ WARN unnecessary braces + } + + let _: [u8; 3]; + //~^ WARN unnecessary braces + + consume(7); + //~^ WARN unnecessary braces + + // Do not emit lint for multiline blocks. + let _ = { + 7 + }; + + // Do not emit lint for unsafe blocks. + let _ = unsafe { 7 }; + + // Do not emit lint, as the `{` would then + // be parsed as part of the `return`. + if { return } { + + } + + // regression test for https://github.com/rust-lang/rust/issues/106899 + return println!("!"); + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces.rs b/tests/ui/lint/unused_braces.rs new file mode 100644 index 000000000..0d260d2cb --- /dev/null +++ b/tests/ui/lint/unused_braces.rs @@ -0,0 +1,57 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces, unused_parens)] +#![allow(unreachable_code, unused_unsafe)] // for rustfix + +fn consume(_: T) {} + +fn main() { + let _ = (7); + //~^WARN unnecessary parentheses + + // Do not emit a lint in these cases, + // as we have to be careful with + // `ref` patterns. + { + let _ = { 7 }; + + if let 7 = { 7 } { } + + match { 7 } { + _ => (), + } + } + + if { true } { + //~^ WARN unnecessary braces + } + + while { false } { + //~^ WARN unnecessary braces + } + + let _: [u8; { 3 }]; + //~^ WARN unnecessary braces + + consume({ 7 }); + //~^ WARN unnecessary braces + + // Do not emit lint for multiline blocks. + let _ = { + 7 + }; + + // Do not emit lint for unsafe blocks. + let _ = unsafe { 7 }; + + // Do not emit lint, as the `{` would then + // be parsed as part of the `return`. + if { return } { + + } + + // regression test for https://github.com/rust-lang/rust/issues/106899 + return { println!("!") }; + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces.stderr b/tests/ui/lint/unused_braces.stderr new file mode 100644 index 000000000..0b4a1c321 --- /dev/null +++ b/tests/ui/lint/unused_braces.stderr @@ -0,0 +1,84 @@ +warning: unnecessary parentheses around assigned value + --> $DIR/unused_braces.rs:10:13 + | +LL | let _ = (7); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:4:24 + | +LL | #![warn(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _ = (7); +LL + let _ = 7; + | + +warning: unnecessary braces around `if` condition + --> $DIR/unused_braces.rs:26:8 + | +LL | if { true } { + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:4:9 + | +LL | #![warn(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - if { true } { +LL + if true { + | + +warning: unnecessary braces around `while` condition + --> $DIR/unused_braces.rs:30:11 + | +LL | while { false } { + | ^^ ^^ + | +help: remove these braces + | +LL - while { false } { +LL + while false { + | + +warning: unnecessary braces around const expression + --> $DIR/unused_braces.rs:34:17 + | +LL | let _: [u8; { 3 }]; + | ^^ ^^ + | +help: remove these braces + | +LL - let _: [u8; { 3 }]; +LL + let _: [u8; 3]; + | + +warning: unnecessary braces around function argument + --> $DIR/unused_braces.rs:37:13 + | +LL | consume({ 7 }); + | ^^ ^^ + | +help: remove these braces + | +LL - consume({ 7 }); +LL + consume(7); + | + +warning: unnecessary braces around `return` value + --> $DIR/unused_braces.rs:55:12 + | +LL | return { println!("!") }; + | ^^ ^^ + | +help: remove these braces + | +LL - return { println!("!") }; +LL + return println!("!"); + | + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/unused_braces_borrow.fixed b/tests/ui/lint/unused_braces_borrow.fixed new file mode 100644 index 000000000..583506f89 --- /dev/null +++ b/tests/ui/lint/unused_braces_borrow.fixed @@ -0,0 +1,26 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces)] + +// changing `&{ expr }` to `&expr` changes the semantic of the program +// so we should not warn this case + +#[repr(packed)] +pub struct A { + pub a: u8, + pub b: u32, +} + +fn consume(_: T) {} + +fn main() { + let a = A { + a: 42, + b: 1729, + }; + + consume(&{ a.b }); + consume(a.b); + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces_borrow.rs b/tests/ui/lint/unused_braces_borrow.rs new file mode 100644 index 000000000..b7c529d73 --- /dev/null +++ b/tests/ui/lint/unused_braces_borrow.rs @@ -0,0 +1,26 @@ +// check-pass +// run-rustfix + +#![warn(unused_braces)] + +// changing `&{ expr }` to `&expr` changes the semantic of the program +// so we should not warn this case + +#[repr(packed)] +pub struct A { + pub a: u8, + pub b: u32, +} + +fn consume(_: T) {} + +fn main() { + let a = A { + a: 42, + b: 1729, + }; + + consume(&{ a.b }); + consume({ a.b }); + //~^ WARN unnecessary braces +} diff --git a/tests/ui/lint/unused_braces_borrow.stderr b/tests/ui/lint/unused_braces_borrow.stderr new file mode 100644 index 000000000..05f7432b8 --- /dev/null +++ b/tests/ui/lint/unused_braces_borrow.stderr @@ -0,0 +1,19 @@ +warning: unnecessary braces around function argument + --> $DIR/unused_braces_borrow.rs:24:13 + | +LL | consume({ a.b }); + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/unused_braces_borrow.rs:4:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ a.b }); +LL + consume(a.b); + | + +warning: 1 warning emitted + diff --git a/tests/ui/lint/unused_braces_macro.rs b/tests/ui/lint/unused_braces_macro.rs new file mode 100644 index 000000000..bfee95378 --- /dev/null +++ b/tests/ui/lint/unused_braces_macro.rs @@ -0,0 +1,6 @@ +// build-pass +pub fn foo () {} + +fn main() { + foo::<{cfg!(feature = "foo")}>(); +} diff --git a/tests/ui/lint/unused_import_warning_issue_45268.rs b/tests/ui/lint/unused_import_warning_issue_45268.rs new file mode 100644 index 000000000..5ae482863 --- /dev/null +++ b/tests/ui/lint/unused_import_warning_issue_45268.rs @@ -0,0 +1,49 @@ +// check-pass + +#![warn(unused_imports)] // Warning explanation here, it's OK + +mod test { + pub trait A { + fn a(); + } + + impl A for () { + fn a() { } + } + + pub trait B { + fn b(self); + } + + impl B for () { + fn b(self) { } + } + + pub trait Unused { + } +} + +use test::Unused; // This is really unused, so warning is OK + //~^ WARNING unused import +use test::A; // This is used by the test2::func() through import of super::* +use test::B; // This is used by the test2::func() through import of super::* + +mod test2 { + use super::*; + pub fn func() { + let _ = <()>::a(); + let _ = ().b(); + test3::inner_func(); + } + mod test3 { + use super::*; + pub fn inner_func() { + let _ = <()>::a(); + let _ = ().b(); + } + } +} + +fn main() { + test2::func(); +} diff --git a/tests/ui/lint/unused_import_warning_issue_45268.stderr b/tests/ui/lint/unused_import_warning_issue_45268.stderr new file mode 100644 index 000000000..fa8699abc --- /dev/null +++ b/tests/ui/lint/unused_import_warning_issue_45268.stderr @@ -0,0 +1,14 @@ +warning: unused import: `test::Unused` + --> $DIR/unused_import_warning_issue_45268.rs:26:5 + | +LL | use test::Unused; // This is really unused, so warning is OK + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused_import_warning_issue_45268.rs:3:9 + | +LL | #![warn(unused_imports)] // Warning explanation here, it's OK + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/unused_labels.rs b/tests/ui/lint/unused_labels.rs new file mode 100644 index 000000000..87a5392fd --- /dev/null +++ b/tests/ui/lint/unused_labels.rs @@ -0,0 +1,85 @@ +// The output should warn when a loop label is not used. However, it +// should also deal with the edge cases where a label is shadowed, +// within nested loops + +// check-pass + +#![warn(unused_labels)] + +fn main() { + 'unused_while_label: while 0 == 0 { + //~^ WARN unused label + } + + let opt = Some(0); + 'unused_while_let_label: while let Some(_) = opt { + //~^ WARN unused label + } + + 'unused_for_label: for _ in 0..10 { + //~^ WARN unused label + } + + 'used_loop_label: loop { + break 'used_loop_label; + } + + 'used_loop_label_outer_1: for _ in 0..10 { + 'used_loop_label_inner_1: for _ in 0..10 { + break 'used_loop_label_inner_1; + } + break 'used_loop_label_outer_1; + } + + 'used_loop_label_outer_2: for _ in 0..10 { + 'unused_loop_label_inner_2: for _ in 0..10 { + //~^ WARN unused label + break 'used_loop_label_outer_2; + } + } + + 'unused_loop_label_outer_3: for _ in 0..10 { + //~^ WARN unused label + 'used_loop_label_inner_3: for _ in 0..10 { + break 'used_loop_label_inner_3; + } + } + + // You should be able to break the same label many times + 'many_used: loop { + if true { + break 'many_used; + } else { + break 'many_used; + } + } + + // Test breaking many times with the same inner label doesn't break the + // warning on the outer label + 'many_used_shadowed: for _ in 0..10 { + //~^ WARN unused label + 'many_used_shadowed: for _ in 0..10 { + //~^ WARN label name `'many_used_shadowed` shadows a label name that is already in scope + if 1 % 2 == 0 { + break 'many_used_shadowed; + } else { + break 'many_used_shadowed; + } + } + } + + 'unused_loop_label: loop { + //~^ WARN unused label + break; + } + + // Make sure unused block labels give warnings... + 'unused_block_label: { + //~^ WARN unused label + } + + // ...and that used ones don't: + 'used_block_label: { + break 'used_block_label; + } +} diff --git a/tests/ui/lint/unused_labels.stderr b/tests/ui/lint/unused_labels.stderr new file mode 100644 index 000000000..846da792b --- /dev/null +++ b/tests/ui/lint/unused_labels.stderr @@ -0,0 +1,65 @@ +warning: label name `'many_used_shadowed` shadows a label name that is already in scope + --> $DIR/unused_labels.rs:61:9 + | +LL | 'many_used_shadowed: for _ in 0..10 { + | ------------------- first declared here +LL | +LL | 'many_used_shadowed: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^ label `'many_used_shadowed` already in scope + +warning: unused label + --> $DIR/unused_labels.rs:10:5 + | +LL | 'unused_while_label: while 0 == 0 { + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused_labels.rs:7:9 + | +LL | #![warn(unused_labels)] + | ^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:15:5 + | +LL | 'unused_while_let_label: while let Some(_) = opt { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:19:5 + | +LL | 'unused_for_label: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:35:9 + | +LL | 'unused_loop_label_inner_2: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:41:5 + | +LL | 'unused_loop_label_outer_3: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:59:5 + | +LL | 'many_used_shadowed: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:71:5 + | +LL | 'unused_loop_label: loop { + | ^^^^^^^^^^^^^^^^^^ + +warning: unused label + --> $DIR/unused_labels.rs:77:5 + | +LL | 'unused_block_label: { + | ^^^^^^^^^^^^^^^^^^^ + +warning: 9 warnings emitted + diff --git a/tests/ui/lint/unused_parens_json_suggestion.fixed b/tests/ui/lint/unused_parens_json_suggestion.fixed new file mode 100644 index 000000000..c40045404 --- /dev/null +++ b/tests/ui/lint/unused_parens_json_suggestion.fixed @@ -0,0 +1,26 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not + // the malformed `1 / (2 + 3` + let _a = 1 / (2 + 3); //~ERROR unnecessary parentheses + f(); +} + +fn f() -> bool { + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_json_suggestion.rs b/tests/ui/lint/unused_parens_json_suggestion.rs new file mode 100644 index 000000000..962c8bdd7 --- /dev/null +++ b/tests/ui/lint/unused_parens_json_suggestion.rs @@ -0,0 +1,26 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not + // the malformed `1 / (2 + 3` + let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses + f(); +} + +fn f() -> bool { + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_json_suggestion.stderr b/tests/ui/lint/unused_parens_json_suggestion.stderr new file mode 100644 index 000000000..ea19e0cdc --- /dev/null +++ b/tests/ui/lint/unused_parens_json_suggestion.stderr @@ -0,0 +1,21 @@ +{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); + --> $DIR/unused_parens_json_suggestion.rs:16:14 + | +LL | let _a = (1 / (2 + 3)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused_parens_json_suggestion.rs:10:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _a = (1 / (2 + 3)); +LL + let _a = 1 / (2 + 3); + | + +"} +{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error + +"} diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.rs b/tests/ui/lint/unused_parens_multibyte_recovery.rs new file mode 100644 index 000000000..8fcfae22a --- /dev/null +++ b/tests/ui/lint/unused_parens_multibyte_recovery.rs @@ -0,0 +1,11 @@ +// ignore-tidy-trailing-newlines +// +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: format argument must be a string literal +// +// Verify that unused parens lint does not try to create a span +// which points in the middle of a multibyte character. + +fn f(){(print!(á \ No newline at end of file diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr new file mode 100644 index 000000000..a0302b17e --- /dev/null +++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr @@ -0,0 +1,43 @@ +error: this file contains an unclosed delimiter + --> $DIR/unused_parens_multibyte_recovery.rs:11:17 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/unused_parens_multibyte_recovery.rs:11:17 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/unused_parens_multibyte_recovery.rs:11:17 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: format argument must be a string literal + --> $DIR/unused_parens_multibyte_recovery.rs:11:16 + | +LL | fn f(){(print!(á + | ^ + | +help: you might be missing a string literal to format with + | +LL | fn f(){(print!("{}", á + | +++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.fixed b/tests/ui/lint/unused_parens_remove_json_suggestion.fixed new file mode 100644 index 000000000..8a57cd573 --- /dev/null +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.fixed @@ -0,0 +1,61 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + + let _b = false; + + if _b { //~ ERROR unnecessary parentheses + println!("hello"); + } + + f(); + +} + +fn f() -> bool { + let c = false; + + if c { //~ ERROR unnecessary parentheses + println!("next"); + } + + if c { //~ ERROR unnecessary parentheses + println!("prev"); + } + + while false && true { + if c { //~ ERROR unnecessary parentheses + println!("norm"); + } + + } + + while true && false { //~ ERROR unnecessary parentheses + for _ in 0 .. 3 { //~ ERROR unnecessary parentheses + println!("e~") + } + } + + for _ in 0 .. 3 { //~ ERROR unnecessary parentheses + while true && false { //~ ERROR unnecessary parentheses + println!("e~") + } + } + + + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.rs b/tests/ui/lint/unused_parens_remove_json_suggestion.rs new file mode 100644 index 000000000..952332d54 --- /dev/null +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.rs @@ -0,0 +1,61 @@ +// compile-flags: --error-format json +// run-rustfix + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn main() { + + let _b = false; + + if (_b) { //~ ERROR unnecessary parentheses + println!("hello"); + } + + f(); + +} + +fn f() -> bool { + let c = false; + + if(c) { //~ ERROR unnecessary parentheses + println!("next"); + } + + if (c){ //~ ERROR unnecessary parentheses + println!("prev"); + } + + while (false && true){ + if (c) { //~ ERROR unnecessary parentheses + println!("norm"); + } + + } + + while(true && false) { //~ ERROR unnecessary parentheses + for _ in (0 .. 3){ //~ ERROR unnecessary parentheses + println!("e~") + } + } + + for _ in (0 .. 3) { //~ ERROR unnecessary parentheses + while (true && false) { //~ ERROR unnecessary parentheses + println!("e~") + } + } + + + loop { + if (break { return true }) { + } + } + false +} diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.stderr b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr new file mode 100644 index 000000000..f4c6ceaf1 --- /dev/null +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -0,0 +1,125 @@ +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) { + --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 + | +LL | if (_b) { + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused_parens_remove_json_suggestion.rs:10:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - if (_b) { +LL + if _b { + | + +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) { + --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 + | +LL | if(c) { + | ^ ^ + | +help: remove these parentheses + | +LL - if(c) { +LL + if c { + | + +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){ + --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 + | +LL | if (c){ + | ^ ^ + | +help: remove these parentheses + | +LL - if (c){ +LL + if c { + | + +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 + | +LL | while (false && true){ + | ^ ^ + | +help: remove these parentheses + | +LL - while (false && true){ +LL + while false && true { + | + +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) { + --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 + | +LL | if (c) { + | ^ ^ + | +help: remove these parentheses + | +LL - if (c) { +LL + if c { + | + +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) { + --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 + | +LL | while(true && false) { + | ^ ^ + | +help: remove these parentheses + | +LL - while(true && false) { +LL + while true && false { + | + +"} +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ + --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 + | +LL | for _ in (0 .. 3){ + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3){ +LL + for _ in 0 .. 3 { + | + +"} +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { + --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 + | +LL | for _ in (0 .. 3) { + | ^ ^ + | +help: remove these parentheses + | +LL - for _ in (0 .. 3) { +LL + for _ in 0 .. 3 { + | + +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) { + --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 + | +LL | while (true && false) { + | ^ ^ + | +help: remove these parentheses + | +LL - while (true && false) { +LL + while true && false { + | + +"} +{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors + +"} diff --git a/tests/ui/lint/unused_variables-issue-82488.fixed b/tests/ui/lint/unused_variables-issue-82488.fixed new file mode 100644 index 000000000..3cb2c90d0 --- /dev/null +++ b/tests/ui/lint/unused_variables-issue-82488.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![deny(unused_variables)] + +struct Point { + x: u32, + y: u32 +} + +fn process_point(Point { x, y: _renamed }: Point) { +//~^ ERROR unused variable: `renamed` + let _ = x; +} + +fn main() { + process_point(Point { x: 0, y: 0 }); +} diff --git a/tests/ui/lint/unused_variables-issue-82488.rs b/tests/ui/lint/unused_variables-issue-82488.rs new file mode 100644 index 000000000..007b0799b --- /dev/null +++ b/tests/ui/lint/unused_variables-issue-82488.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![deny(unused_variables)] + +struct Point { + x: u32, + y: u32 +} + +fn process_point(Point { x, y: renamed }: Point) { +//~^ ERROR unused variable: `renamed` + let _ = x; +} + +fn main() { + process_point(Point { x: 0, y: 0 }); +} diff --git a/tests/ui/lint/unused_variables-issue-82488.stderr b/tests/ui/lint/unused_variables-issue-82488.stderr new file mode 100644 index 000000000..dce03a0f7 --- /dev/null +++ b/tests/ui/lint/unused_variables-issue-82488.stderr @@ -0,0 +1,14 @@ +error: unused variable: `renamed` + --> $DIR/unused_variables-issue-82488.rs:9:32 + | +LL | fn process_point(Point { x, y: renamed }: Point) { + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_renamed` + | +note: the lint level is defined here + --> $DIR/unused_variables-issue-82488.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/lint/use-redundant.rs b/tests/ui/lint/use-redundant.rs new file mode 100644 index 000000000..53315dcf6 --- /dev/null +++ b/tests/ui/lint/use-redundant.rs @@ -0,0 +1,27 @@ +// check-pass +#![warn(unused_imports)] + +use crate::foo::Bar; + +mod foo { + pub type Bar = i32; +} + +fn baz() -> Bar { + 3 +} + +mod m1 { pub struct S {} } +mod m2 { pub struct S {} } + +use m1::*; //~ WARNING unused import +use m2::*; //~ WARNING unused import + +fn main() { + use crate::foo::Bar; //~ WARNING imported redundantly + let _a: Bar = 3; + baz(); + + use m1::S; + let _s = S {}; +} diff --git a/tests/ui/lint/use-redundant.stderr b/tests/ui/lint/use-redundant.stderr new file mode 100644 index 000000000..c861a1956 --- /dev/null +++ b/tests/ui/lint/use-redundant.stderr @@ -0,0 +1,29 @@ +warning: unused import: `m1::*` + --> $DIR/use-redundant.rs:17:5 + | +LL | use m1::*; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant.rs:2:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: unused import: `m2::*` + --> $DIR/use-redundant.rs:18:5 + | +LL | use m2::*; + | ^^^^^ + +warning: the item `Bar` is imported redundantly + --> $DIR/use-redundant.rs:21:9 + | +LL | use crate::foo::Bar; + | --------------- the item `Bar` is already imported here +... +LL | use crate::foo::Bar; + | ^^^^^^^^^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/use_suggestion_json.rs b/tests/ui/lint/use_suggestion_json.rs new file mode 100644 index 000000000..7d641e08b --- /dev/null +++ b/tests/ui/lint/use_suggestion_json.rs @@ -0,0 +1,13 @@ +// ignore-windows +// ignore-sgx std::os::fortanix_sgx::usercalls::alloc::Iter changes compiler suggestions +// compile-flags: --error-format pretty-json --json=diagnostic-rendered-ansi + +// The output for humans should just highlight the whole span without showing +// the suggested replacement, but we also want to test that suggested +// replacement only removes one set of parentheses, rather than naïvely +// stripping away any starting or ending parenthesis characters—hence this +// test of the JSON error format. + +fn main() { + let x: Iter; +} diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr new file mode 100644 index 000000000..d17514303 --- /dev/null +++ b/tests/ui/lint/use_suggestion_json.stderr @@ -0,0 +1,3 @@ +{"message":"`--error-format=pretty-json` is unstable","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: `--error-format=pretty-json` is unstable\u001b[0m + +"} diff --git a/tests/ui/lint/warn-ctypes-inhibit.rs b/tests/ui/lint/warn-ctypes-inhibit.rs new file mode 100644 index 000000000..15d8b09d2 --- /dev/null +++ b/tests/ui/lint/warn-ctypes-inhibit.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +// compile-flags:-D improper-ctypes + +// pretty-expanded FIXME #23616 +#![allow(improper_ctypes)] + +mod libc { + extern "C" { + pub fn malloc(size: isize) -> *const u8; + } +} + +pub fn main() {} diff --git a/tests/ui/lint/warn-path-statement.rs b/tests/ui/lint/warn-path-statement.rs new file mode 100644 index 000000000..2435be623 --- /dev/null +++ b/tests/ui/lint/warn-path-statement.rs @@ -0,0 +1,17 @@ +// compile-flags: -D path-statements +struct Droppy; + +impl Drop for Droppy { + fn drop(&mut self) {} +} + +fn main() { + let x = 10; + x; //~ ERROR path statement with no effect + + let y = Droppy; + y; //~ ERROR path statement drops value + + let z = (Droppy,); + z; //~ ERROR path statement drops value +} diff --git a/tests/ui/lint/warn-path-statement.stderr b/tests/ui/lint/warn-path-statement.stderr new file mode 100644 index 000000000..248d2ef29 --- /dev/null +++ b/tests/ui/lint/warn-path-statement.stderr @@ -0,0 +1,22 @@ +error: path statement with no effect + --> $DIR/warn-path-statement.rs:10:5 + | +LL | x; + | ^^ + | + = note: requested on the command line with `-D path-statements` + +error: path statement drops value + --> $DIR/warn-path-statement.rs:13:5 + | +LL | y; + | ^^ help: use `drop` to clarify the intent: `drop(y);` + +error: path statement drops value + --> $DIR/warn-path-statement.rs:16:5 + | +LL | z; + | ^^ help: use `drop` to clarify the intent: `drop(z);` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs new file mode 100644 index 000000000..4684fe145 --- /dev/null +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs @@ -0,0 +1,13 @@ +#![deny(unused_attributes)] + +trait Trait { + #[inline] //~ ERROR `#[inline]` is ignored on function prototypes + fn foo(); +} + +extern "C" { + #[inline] //~ ERROR `#[inline]` is ignored on function prototypes + fn foo(); +} + +fn main() {} diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr new file mode 100644 index 000000000..ab19d80e7 --- /dev/null +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr @@ -0,0 +1,20 @@ +error: `#[inline]` is ignored on function prototypes + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5 + | +LL | #[inline] + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[inline]` is ignored on function prototypes + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5 + | +LL | #[inline] + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/list.rs b/tests/ui/list.rs new file mode 100644 index 000000000..ffe9f9386 --- /dev/null +++ b/tests/ui/list.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(non_camel_case_types)] +// pretty-expanded FIXME #23616 + +enum list { #[allow(unused_tuple_struct_fields)] cons(isize, Box), nil, } + +pub fn main() { + list::cons(10, Box::new(list::cons(11, Box::new(list::cons(12, Box::new(list::nil)))))); +} diff --git a/tests/ui/liveness/liveness-asm.rs b/tests/ui/liveness/liveness-asm.rs new file mode 100644 index 000000000..ea5f033cb --- /dev/null +++ b/tests/ui/liveness/liveness-asm.rs @@ -0,0 +1,45 @@ +// Ensure inout asm! operands are marked as used by the liveness pass + +// only-x86_64 +// check-pass + +#![allow(dead_code)] +#![warn(unused_assignments)] +#![warn(unused_variables)] + +use std::arch::asm; + +// Test the single inout case +unsafe fn f1(mut src: *const u8) { + asm!("/*{0}*/", inout(reg) src); //~ WARN value assigned to `src` is never read +} + +unsafe fn f2(mut src: *const u8) -> *const u8 { + asm!("/*{0}*/", inout(reg) src); + src +} + +// Test the split inout case +unsafe fn f3(mut src: *const u8) { + asm!("/*{0}*/", inout(reg) src => src); //~ WARN value assigned to `src` is never read +} + +unsafe fn f4(mut src: *const u8) -> *const u8 { + asm!("/*{0}*/", inout(reg) src => src); + src +} + +// Tests the use of field projections +struct S { + field: *mut u8, +} + +unsafe fn f5(src: &mut S) { + asm!("/*{0}*/", inout(reg) src.field); +} + +unsafe fn f6(src: &mut S) { + asm!("/*{0}*/", inout(reg) src.field => src.field); +} + +fn main() {} diff --git a/tests/ui/liveness/liveness-asm.stderr b/tests/ui/liveness/liveness-asm.stderr new file mode 100644 index 000000000..57d89e44d --- /dev/null +++ b/tests/ui/liveness/liveness-asm.stderr @@ -0,0 +1,23 @@ +warning: value assigned to `src` is never read + --> $DIR/liveness-asm.rs:14:32 + | +LL | asm!("/*{0}*/", inout(reg) src); + | ^^^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/liveness-asm.rs:7:9 + | +LL | #![warn(unused_assignments)] + | ^^^^^^^^^^^^^^^^^^ + +warning: value assigned to `src` is never read + --> $DIR/liveness-asm.rs:24:39 + | +LL | asm!("/*{0}*/", inout(reg) src => src); + | ^^^ + | + = help: maybe it is overwritten before being read? + +warning: 2 warnings emitted + diff --git a/tests/ui/liveness/liveness-assign-imm-local-after-ret.rs b/tests/ui/liveness/liveness-assign-imm-local-after-ret.rs new file mode 100644 index 000000000..b463f4368 --- /dev/null +++ b/tests/ui/liveness/liveness-assign-imm-local-after-ret.rs @@ -0,0 +1,16 @@ +// run-pass + +#![allow(unreachable_code)] +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +fn test() { + let _v: isize; + _v = 1; + return; + _v = 2; +} + +pub fn main() { +} diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs new file mode 100644 index 000000000..08911c5bd --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.rs @@ -0,0 +1,12 @@ +fn test() { + let v: isize; + //~^ HELP consider making this binding mutable + //~| SUGGESTION mut v + loop { + v = 1; //~ ERROR cannot assign twice to immutable variable `v` + //~| NOTE cannot assign twice to immutable variable + } +} + +fn main() { +} diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr new file mode 100644 index 000000000..66cdce7da --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-loop.stderr @@ -0,0 +1,12 @@ +error[E0384]: cannot assign twice to immutable variable `v` + --> $DIR/liveness-assign-imm-local-in-loop.rs:6:9 + | +LL | let v: isize; + | - help: consider making this binding mutable: `mut v` +... +LL | v = 1; + | ^^^^^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs new file mode 100644 index 000000000..1752d9690 --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.rs @@ -0,0 +1,12 @@ +fn test() { + let v: isize; + //~^ HELP consider making this binding mutable + //~| SUGGESTION mut v + v = 2; //~ NOTE first assignment + v += 1; //~ ERROR cannot assign twice to immutable variable `v` + //~| NOTE cannot assign twice to immutable + v.clone(); +} + +fn main() { +} diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr new file mode 100644 index 000000000..5db9539cb --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-in-op-eq.stderr @@ -0,0 +1,14 @@ +error[E0384]: cannot assign twice to immutable variable `v` + --> $DIR/liveness-assign-imm-local-in-op-eq.rs:6:5 + | +LL | let v: isize; + | - help: consider making this binding mutable: `mut v` +... +LL | v = 2; + | ----- first assignment to `v` +LL | v += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs new file mode 100644 index 000000000..c9b16e439 --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs @@ -0,0 +1,12 @@ +fn test() { + let b = Box::new(1); //~ NOTE first assignment + //~| HELP consider making this binding mutable + //~| SUGGESTION mut b + drop(b); + b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b` + //~| NOTE cannot assign twice to immutable + drop(b); +} + +fn main() { +} diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr new file mode 100644 index 000000000..bb7e7e27a --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.stderr @@ -0,0 +1,15 @@ +error[E0384]: cannot assign twice to immutable variable `b` + --> $DIR/liveness-assign-imm-local-with-drop.rs:6:5 + | +LL | let b = Box::new(1); + | - + | | + | first assignment to `b` + | help: consider making this binding mutable: `mut b` +... +LL | b = Box::new(2); + | ^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs new file mode 100644 index 000000000..4bb2db27a --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.rs @@ -0,0 +1,12 @@ +fn test() { + let v: isize = 1; //~ NOTE first assignment + //~| HELP consider making this binding mutable + //~| SUGGESTION mut v + v.clone(); + v = 2; //~ ERROR cannot assign twice to immutable variable `v` + //~| NOTE cannot assign twice to immutable + v.clone(); +} + +fn main() { +} diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr new file mode 100644 index 000000000..80458a70a --- /dev/null +++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-init.stderr @@ -0,0 +1,15 @@ +error[E0384]: cannot assign twice to immutable variable `v` + --> $DIR/liveness-assign-imm-local-with-init.rs:6:5 + | +LL | let v: isize = 1; + | - + | | + | first assignment to `v` + | help: consider making this binding mutable: `mut v` +... +LL | v = 2; + | ^^^^^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/liveness/liveness-closure-require-ret.rs b/tests/ui/liveness/liveness-closure-require-ret.rs new file mode 100644 index 000000000..b86d1fe4a --- /dev/null +++ b/tests/ui/liveness/liveness-closure-require-ret.rs @@ -0,0 +1,2 @@ +fn force(f: F) -> isize where F: FnOnce() -> isize { f() } +fn main() { println!("{}", force(|| {})); } //~ ERROR mismatched types diff --git a/tests/ui/liveness/liveness-closure-require-ret.stderr b/tests/ui/liveness/liveness-closure-require-ret.stderr new file mode 100644 index 000000000..07b2ef6cd --- /dev/null +++ b/tests/ui/liveness/liveness-closure-require-ret.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/liveness-closure-require-ret.rs:2:37 + | +LL | fn main() { println!("{}", force(|| {})); } + | ^^ expected `isize`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-consts.rs b/tests/ui/liveness/liveness-consts.rs new file mode 100644 index 000000000..8fe2453ca --- /dev/null +++ b/tests/ui/liveness/liveness-consts.rs @@ -0,0 +1,63 @@ +// check-pass +#![warn(unused)] +#![allow(unreachable_code)] + +pub static A: i32 = { + let mut i = 0; + let mut a = 0; //~ WARN variable `a` is assigned to, but never used + while i < 10 { + i += 1; + a += 1; + } + i +}; + +pub const B: u32 = { + let mut b = 1; + b += 1; //~ WARN value assigned to `b` is never read + b = 42; + b +}; + +pub enum E { + V1 = { + let e = 1; //~ WARN unused variable: `e` + 1 + }, + V2 = { + let _f = 10; + 2 + } +} + +pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] { + //~^ WARN unused variable: `s` + //~| WARN unused variable: `z` + x +} + +pub trait T { + const T: usize = { + let mut t = 10; + t = t + t; //~ WARN value assigned to `t` is never read + 20 + }; +} + +impl T for String { + const T: usize = { + let w = 10; //~ WARN unused variable: `w` + loop { + break; + let _ = w; + } + 44 + }; +} + +fn main() { + let _ = [(); { + let z = 42; //~ WARN unused variable: `z` + 35 + }]; +} diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr new file mode 100644 index 000000000..6199ea96c --- /dev/null +++ b/tests/ui/liveness/liveness-consts.stderr @@ -0,0 +1,63 @@ +warning: variable `a` is assigned to, but never used + --> $DIR/liveness-consts.rs:7:13 + | +LL | let mut a = 0; + | ^ + | + = note: consider using `_a` instead +note: the lint level is defined here + --> $DIR/liveness-consts.rs:2:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: value assigned to `b` is never read + --> $DIR/liveness-consts.rs:17:5 + | +LL | b += 1; + | ^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `e` + --> $DIR/liveness-consts.rs:24:13 + | +LL | let e = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_e` + +warning: unused variable: `s` + --> $DIR/liveness-consts.rs:33:24 + | +LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] { + | ^ help: if this is intentional, prefix it with an underscore: `_s` + +warning: unused variable: `z` + --> $DIR/liveness-consts.rs:33:55 + | +LL | pub fn f(x: [u8; { let s = 17; 100 }]) -> [u8; { let z = 18; 100 }] { + | ^ help: if this is intentional, prefix it with an underscore: `_z` + +warning: value assigned to `t` is never read + --> $DIR/liveness-consts.rs:42:9 + | +LL | t = t + t; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `w` + --> $DIR/liveness-consts.rs:49:13 + | +LL | let w = 10; + | ^ help: if this is intentional, prefix it with an underscore: `_w` + +warning: unused variable: `z` + --> $DIR/liveness-consts.rs:60:13 + | +LL | let z = 42; + | ^ help: if this is intentional, prefix it with an underscore: `_z` + +warning: 8 warnings emitted + diff --git a/tests/ui/liveness/liveness-dead.rs b/tests/ui/liveness/liveness-dead.rs new file mode 100644 index 000000000..004663c85 --- /dev/null +++ b/tests/ui/liveness/liveness-dead.rs @@ -0,0 +1,39 @@ +#![allow(dead_code)] +#![deny(unused_assignments)] + +fn f1(x: &mut isize) { + *x = 1; // no error +} + +fn f2() { + let mut x: isize = 3; //~ ERROR: value assigned to `x` is never read + x = 4; + x.clone(); +} + +fn f3() { + let mut x: isize = 3; + x.clone(); + x = 4; //~ ERROR: value assigned to `x` is never read +} + +fn f4(mut x: i32) { //~ ERROR: value passed to `x` is never read + x = 4; + x.clone(); +} + +fn f5(mut x: i32) { + x.clone(); + x = 4; //~ ERROR: value assigned to `x` is never read +} + +// #22630 +fn f6() { + let mut done = false; + while !done { + done = true; // no error + continue; + } +} + +fn main() {} diff --git a/tests/ui/liveness/liveness-dead.stderr b/tests/ui/liveness/liveness-dead.stderr new file mode 100644 index 000000000..de6d5bd99 --- /dev/null +++ b/tests/ui/liveness/liveness-dead.stderr @@ -0,0 +1,39 @@ +error: value assigned to `x` is never read + --> $DIR/liveness-dead.rs:9:13 + | +LL | let mut x: isize = 3; + | ^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/liveness-dead.rs:2:9 + | +LL | #![deny(unused_assignments)] + | ^^^^^^^^^^^^^^^^^^ + +error: value assigned to `x` is never read + --> $DIR/liveness-dead.rs:17:5 + | +LL | x = 4; + | ^ + | + = help: maybe it is overwritten before being read? + +error: value passed to `x` is never read + --> $DIR/liveness-dead.rs:20:11 + | +LL | fn f4(mut x: i32) { + | ^ + | + = help: maybe it is overwritten before being read? + +error: value assigned to `x` is never read + --> $DIR/liveness-dead.rs:27:5 + | +LL | x = 4; + | ^ + | + = help: maybe it is overwritten before being read? + +error: aborting due to 4 previous errors + diff --git a/tests/ui/liveness/liveness-derive.rs b/tests/ui/liveness/liveness-derive.rs new file mode 100644 index 000000000..1921d0d72 --- /dev/null +++ b/tests/ui/liveness/liveness-derive.rs @@ -0,0 +1,38 @@ +// Test for interaction between #[automatically_derived] attribute used by +// built-in derives and lints generated by liveness pass. +// +// edition:2018 +// check-pass +#![warn(unused)] + +pub trait T: Sized { + const N: usize; + fn t(&self) -> Self; +} + +impl T for u32 { + const N: usize = { + let a = 0; //~ WARN unused variable: `a` + 4 + }; + + fn t(&self) -> Self { + let b = 16; //~ WARN unused variable: `b` + 0 + } +} + +#[automatically_derived] +impl T for i32 { + const N: usize = { + let c = 0; + 4 + }; + + fn t(&self) -> Self { + let d = 17; + 0 + } +} + +fn main() {} diff --git a/tests/ui/liveness/liveness-derive.stderr b/tests/ui/liveness/liveness-derive.stderr new file mode 100644 index 000000000..c03d90991 --- /dev/null +++ b/tests/ui/liveness/liveness-derive.stderr @@ -0,0 +1,21 @@ +warning: unused variable: `a` + --> $DIR/liveness-derive.rs:15:13 + | +LL | let a = 0; + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/liveness-derive.rs:6:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `b` + --> $DIR/liveness-derive.rs:20:13 + | +LL | let b = 16; + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +warning: 2 warnings emitted + diff --git a/tests/ui/liveness/liveness-forgot-ret.rs b/tests/ui/liveness/liveness-forgot-ret.rs new file mode 100644 index 000000000..b8c2bc734 --- /dev/null +++ b/tests/ui/liveness/liveness-forgot-ret.rs @@ -0,0 +1,6 @@ +fn god_exists(a: isize) -> bool { return god_exists(a); } + +fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } +//~^ ERROR mismatched types + +fn main() { f(12); } diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr new file mode 100644 index 000000000..ddbdbdb0f --- /dev/null +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/liveness-forgot-ret.rs:3:19 + | +LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } + | - ^^^^^ expected `isize`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +help: consider returning the local binding `a` + | +LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-issue-2163.rs b/tests/ui/liveness/liveness-issue-2163.rs new file mode 100644 index 000000000..a632b5b9c --- /dev/null +++ b/tests/ui/liveness/liveness-issue-2163.rs @@ -0,0 +1,8 @@ +use std::vec::Vec; + +fn main() { + let a: Vec = Vec::new(); + a.iter().all(|_| -> bool { + //~^ ERROR mismatched types + }); +} diff --git a/tests/ui/liveness/liveness-issue-2163.stderr b/tests/ui/liveness/liveness-issue-2163.stderr new file mode 100644 index 000000000..2adc2d438 --- /dev/null +++ b/tests/ui/liveness/liveness-issue-2163.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/liveness-issue-2163.rs:5:30 + | +LL | a.iter().all(|_| -> bool { + | ______________________________^ +LL | | +LL | | }); + | |_____^ expected `bool`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-missing-ret2.rs b/tests/ui/liveness/liveness-missing-ret2.rs new file mode 100644 index 000000000..a18669f72 --- /dev/null +++ b/tests/ui/liveness/liveness-missing-ret2.rs @@ -0,0 +1,7 @@ +fn f() -> isize { //~ ERROR mismatched types + // Make sure typestate doesn't interpret this match expression as + // the function result + match true { true => { } _ => {} }; +} + +fn main() { } diff --git a/tests/ui/liveness/liveness-missing-ret2.stderr b/tests/ui/liveness/liveness-missing-ret2.stderr new file mode 100644 index 000000000..afdb733cd --- /dev/null +++ b/tests/ui/liveness/liveness-missing-ret2.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/liveness-missing-ret2.rs:1:11 + | +LL | fn f() -> isize { + | - ^^^^^ expected `isize`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-move-call-arg.rs b/tests/ui/liveness/liveness-move-call-arg.rs new file mode 100644 index 000000000..1bc2ea6b9 --- /dev/null +++ b/tests/ui/liveness/liveness-move-call-arg.rs @@ -0,0 +1,11 @@ +fn take(_x: Box) {} + + +fn main() { + + let x: Box = Box::new(25); + + loop { + take(x); //~ ERROR use of moved value: `x` + } +} diff --git a/tests/ui/liveness/liveness-move-call-arg.stderr b/tests/ui/liveness/liveness-move-call-arg.stderr new file mode 100644 index 000000000..d14cd6cb4 --- /dev/null +++ b/tests/ui/liveness/liveness-move-call-arg.stderr @@ -0,0 +1,26 @@ +error[E0382]: use of moved value: `x` + --> $DIR/liveness-move-call-arg.rs:9:14 + | +LL | let x: Box = Box::new(25); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | +LL | loop { + | ---- inside of this loop +LL | take(x); + | ^ value moved here, in previous iteration of loop + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/liveness-move-call-arg.rs:1:13 + | +LL | fn take(_x: Box) {} + | ---- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | take(x.clone()); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-move-in-loop.rs b/tests/ui/liveness/liveness-move-in-loop.rs new file mode 100644 index 000000000..064be14d6 --- /dev/null +++ b/tests/ui/liveness/liveness-move-in-loop.rs @@ -0,0 +1,17 @@ +fn main() { + + let y: Box = 42.into(); + let mut x: Box; + + loop { + println!("{}", y); + loop { + loop { + loop { + x = y; //~ ERROR use of moved value + x.clone(); + } + } + } + } +} diff --git a/tests/ui/liveness/liveness-move-in-loop.stderr b/tests/ui/liveness/liveness-move-in-loop.stderr new file mode 100644 index 000000000..a060914f1 --- /dev/null +++ b/tests/ui/liveness/liveness-move-in-loop.stderr @@ -0,0 +1,26 @@ +error[E0382]: use of moved value: `y` + --> $DIR/liveness-move-in-loop.rs:11:25 + | +LL | let y: Box = 42.into(); + | - move occurs because `y` has type `Box`, which does not implement the `Copy` trait +... +LL | loop { + | ---- inside of this loop +LL | println!("{}", y); +LL | loop { + | ---- inside of this loop +LL | loop { + | ---- inside of this loop +LL | loop { + | ---- inside of this loop +LL | x = y; + | ^ value moved here, in previous iteration of loop + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x = y.clone(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-move-in-while.rs b/tests/ui/liveness/liveness-move-in-while.rs new file mode 100644 index 000000000..7c0cd282c --- /dev/null +++ b/tests/ui/liveness/liveness-move-in-while.rs @@ -0,0 +1,13 @@ +fn main() { + + let y: Box = 42.into(); + let mut x: Box; + + loop { + println!("{}", y); //~ ERROR borrow of moved value: `y` + while true { while true { while true { x = y; x.clone(); } } } + //~^ WARN denote infinite loops with + //~| WARN denote infinite loops with + //~| WARN denote infinite loops with + } +} diff --git a/tests/ui/liveness/liveness-move-in-while.stderr b/tests/ui/liveness/liveness-move-in-while.stderr new file mode 100644 index 000000000..4dff7447d --- /dev/null +++ b/tests/ui/liveness/liveness-move-in-while.stderr @@ -0,0 +1,46 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/liveness-move-in-while.rs:8:9 + | +LL | while true { while true { while true { x = y; x.clone(); } } } + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: denote infinite loops with `loop { ... }` + --> $DIR/liveness-move-in-while.rs:8:22 + | +LL | while true { while true { while true { x = y; x.clone(); } } } + | ^^^^^^^^^^ help: use `loop` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/liveness-move-in-while.rs:8:35 + | +LL | while true { while true { while true { x = y; x.clone(); } } } + | ^^^^^^^^^^ help: use `loop` + +error[E0382]: borrow of moved value: `y` + --> $DIR/liveness-move-in-while.rs:7:24 + | +LL | let y: Box = 42.into(); + | - move occurs because `y` has type `Box`, which does not implement the `Copy` trait +... +LL | loop { + | ---- inside of this loop +LL | println!("{}", y); + | ^ value borrowed here after move +LL | while true { while true { while true { x = y; x.clone(); } } } + | ---------- ---------- ---------- - value moved here, in previous iteration of loop + | | | | + | | | inside of this loop + | | inside of this loop + | inside of this loop + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | while true { while true { while true { x = y.clone(); x.clone(); } } } + | ++++++++ + +error: aborting due to previous error; 3 warnings emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-return-last-stmt-semi.rs b/tests/ui/liveness/liveness-return-last-stmt-semi.rs new file mode 100644 index 000000000..dff859429 --- /dev/null +++ b/tests/ui/liveness/liveness-return-last-stmt-semi.rs @@ -0,0 +1,18 @@ +// regression test for #8005 + +macro_rules! test { () => { fn foo() -> i32 { 1; } } } + //~^ ERROR mismatched types + +fn no_return() -> i32 {} //~ ERROR mismatched types + +fn bar(x: u32) -> u32 { //~ ERROR mismatched types + x * 2; +} + +fn baz(x: u64) -> u32 { //~ ERROR mismatched types + x * 2; +} + +fn main() { + test!(); +} diff --git a/tests/ui/liveness/liveness-return-last-stmt-semi.stderr b/tests/ui/liveness/liveness-return-last-stmt-semi.stderr new file mode 100644 index 000000000..de0843aa6 --- /dev/null +++ b/tests/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/liveness-return-last-stmt-semi.rs:6:19 + | +LL | fn no_return() -> i32 {} + | --------- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/liveness-return-last-stmt-semi.rs:8:19 + | +LL | fn bar(x: u32) -> u32 { + | --- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +LL | x * 2; + | - help: remove this semicolon to return this value + +error[E0308]: mismatched types + --> $DIR/liveness-return-last-stmt-semi.rs:12:19 + | +LL | fn baz(x: u64) -> u32 { + | --- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/liveness-return-last-stmt-semi.rs:3:41 + | +LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } + | --- ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +... +LL | test!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-unused.rs b/tests/ui/liveness/liveness-unused.rs new file mode 100644 index 000000000..9c7be15fc --- /dev/null +++ b/tests/ui/liveness/liveness-unused.rs @@ -0,0 +1,141 @@ +#![warn(unused)] +#![deny(unused_variables)] +#![deny(unused_assignments)] +#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)] + +use std::ops::AddAssign; + +fn f1(x: isize) { + //~^ ERROR unused variable: `x` +} + +fn f1b(x: &mut isize) { + //~^ ERROR unused variable: `x` +} + +#[allow(unused_variables)] +fn f1c(x: isize) {} + +fn f1d() { + let x: isize; + //~^ ERROR unused variable: `x` +} + +fn f2() { + let x = 3; + //~^ ERROR unused variable: `x` +} + +fn f3() { + let mut x = 3; + //~^ ERROR variable `x` is assigned to, but never used + x += 4; + //~^ ERROR value assigned to `x` is never read +} + +fn f3b() { + let mut z = 3; + //~^ ERROR variable `z` is assigned to, but never used + loop { + z += 4; + } +} + +#[allow(unused_variables)] +fn f3c() { + let mut z = 3; + loop { z += 4; } +} + +#[allow(unused_variables)] +#[allow(unused_assignments)] +fn f3d() { + let mut x = 3; + x += 4; +} + +fn f4() { + match Some(3) { + Some(i) => { + //~^ ERROR unused variable: `i` + } + None => {} + } +} + +enum tri { + a(isize), b(isize), c(isize) +} + +fn f4b() -> isize { + match tri::a(3) { + tri::a(i) | tri::b(i) | tri::c(i) => { + i + } + } +} + +fn f5a() { + for x in 1..10 { } + //~^ ERROR unused variable: `x` +} + +fn f5b() { + for (x, _) in [1, 2, 3].iter().enumerate() { } + //~^ ERROR unused variable: `x` +} + +fn f5c() { + for (_, x) in [1, 2, 3].iter().enumerate() { + //~^ ERROR unused variable: `x` + continue; + drop(*x as i32); //~ WARNING unreachable statement + } +} + +struct View<'a>(&'a mut [i32]); + +impl<'a> AddAssign for View<'a> { + fn add_assign(&mut self, rhs: i32) { + for lhs in self.0.iter_mut() { + *lhs += rhs; + } + } +} + +fn f6() { + let mut array = [1, 2, 3]; + let mut v = View(&mut array); + + // ensure an error shows up for x even if lhs of an overloaded add assign + + let x; + //~^ ERROR variable `x` is assigned to, but never used + + *({ + x = 0; //~ ERROR value assigned to `x` is never read + &mut v + }) += 1; +} + + +struct MutRef<'a>(&'a mut i32); + +impl<'a> AddAssign for MutRef<'a> { + fn add_assign(&mut self, rhs: i32) { + *self.0 += rhs; + } +} + +fn f7() { + let mut a = 1; + { + // `b` does not trigger unused_variables + let mut b = MutRef(&mut a); + b += 1; + } + drop(a); +} + +fn main() { +} diff --git a/tests/ui/liveness/liveness-unused.stderr b/tests/ui/liveness/liveness-unused.stderr new file mode 100644 index 000000000..f6c478ddb --- /dev/null +++ b/tests/ui/liveness/liveness-unused.stderr @@ -0,0 +1,116 @@ +warning: unreachable statement + --> $DIR/liveness-unused.rs:92:9 + | +LL | continue; + | -------- any code following this expression is unreachable +LL | drop(*x as i32); + | ^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/liveness-unused.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:8:7 + | +LL | fn f1(x: isize) { + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | +note: the lint level is defined here + --> $DIR/liveness-unused.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:12:8 + | +LL | fn f1b(x: &mut isize) { + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:20:9 + | +LL | let x: isize; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:25:9 + | +LL | let x = 3; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: variable `x` is assigned to, but never used + --> $DIR/liveness-unused.rs:30:13 + | +LL | let mut x = 3; + | ^ + | + = note: consider using `_x` instead + +error: value assigned to `x` is never read + --> $DIR/liveness-unused.rs:32:5 + | +LL | x += 4; + | ^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/liveness-unused.rs:3:9 + | +LL | #![deny(unused_assignments)] + | ^^^^^^^^^^^^^^^^^^ + +error: variable `z` is assigned to, but never used + --> $DIR/liveness-unused.rs:37:13 + | +LL | let mut z = 3; + | ^ + | + = note: consider using `_z` instead + +error: unused variable: `i` + --> $DIR/liveness-unused.rs:59:12 + | +LL | Some(i) => { + | ^ help: if this is intentional, prefix it with an underscore: `_i` + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:79:9 + | +LL | for x in 1..10 { } + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:84:10 + | +LL | for (x, _) in [1, 2, 3].iter().enumerate() { } + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: unused variable: `x` + --> $DIR/liveness-unused.rs:89:13 + | +LL | for (_, x) in [1, 2, 3].iter().enumerate() { + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: variable `x` is assigned to, but never used + --> $DIR/liveness-unused.rs:112:9 + | +LL | let x; + | ^ + | + = note: consider using `_x` instead + +error: value assigned to `x` is never read + --> $DIR/liveness-unused.rs:116:9 + | +LL | x = 0; + | ^ + | + = help: maybe it is overwritten before being read? + +error: aborting due to 13 previous errors; 1 warning emitted + diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs new file mode 100644 index 000000000..d446d57d3 --- /dev/null +++ b/tests/ui/liveness/liveness-upvars.rs @@ -0,0 +1,144 @@ +// edition:2018 +// check-pass +#![feature(generators)] +#![warn(unused)] +#![allow(unreachable_code)] + +pub fn unintentional_copy_one() { + let mut last = None; + let mut f = move |s| { + last = Some(s); //~ WARN value assigned to `last` is never read + //~| WARN unused variable: `last` + }; + f("a"); + f("b"); + f("c"); + dbg!(last.unwrap()); +} + +pub fn unintentional_copy_two() { + let mut sum = 0; + (1..10).for_each(move |x| { + sum += x; //~ WARN unused variable: `sum` + }); + dbg!(sum); +} + +pub fn f() { + let mut c = 0; + + // Captured by value, but variable is dead on entry. + let _ = move || { + c = 1; //~ WARN value captured by `c` is never read + println!("{}", c); + }; + let _ = async move { + c = 1; //~ WARN value captured by `c` is never read + println!("{}", c); + }; + + // Read and written to, but never actually used. + let _ = move || { + c += 1; //~ WARN unused variable: `c` + }; + let _ = async move { + c += 1; //~ WARN value assigned to `c` is never read + //~| WARN unused variable: `c` + }; + + let _ = move || { + println!("{}", c); + // Value is read by closure itself on later invocations. + c += 1; + }; + let b = Box::new(42); + let _ = move || { + println!("{}", c); + // Never read because this is FnOnce closure. + c += 1; //~ WARN value assigned to `c` is never read + drop(b); + }; + let _ = async move { + println!("{}", c); + // Never read because this is a generator. + c += 1; //~ WARN value assigned to `c` is never read + }; +} + +pub fn nested() { + let mut d = None; + let mut e = None; + let _ = || { + let _ = || { + d = Some("d1"); //~ WARN value assigned to `d` is never read + d = Some("d2"); + }; + let _ = move || { + e = Some("e1"); //~ WARN value assigned to `e` is never read + //~| WARN unused variable: `e` + e = Some("e2"); //~ WARN value assigned to `e` is never read + }; + }; +} + +pub fn g(mut v: T) { + let _ = |r| { + if r { + v = T::default(); //~ WARN value assigned to `v` is never read + } else { + drop(v); + } + }; +} + +pub fn h() { + let mut z = T::default(); + let _ = move |b| { + loop { + if b { + z = T::default(); //~ WARN value assigned to `z` is never read + //~| WARN unused variable: `z` + } else { + return; + } + } + dbg!(z); + }; +} + +async fn yield_now() { + todo!(); +} + +pub fn async_generator() { + let mut state: u32 = 0; + + let _ = async { + state = 1; + yield_now().await; + state = 2; + yield_now().await; + state = 3; + }; + + let _ = async move { + state = 4; //~ WARN value assigned to `state` is never read + //~| WARN unused variable: `state` + yield_now().await; + state = 5; //~ WARN value assigned to `state` is never read + }; +} + +pub fn generator() { + let mut s: u32 = 0; + let _ = |_| { + s = 0; + yield (); + s = 1; //~ WARN value assigned to `s` is never read + yield (s = 2); + s = yield (); //~ WARN value assigned to `s` is never read + s = 3; + }; +} + +fn main() {} diff --git a/tests/ui/liveness/liveness-upvars.stderr b/tests/ui/liveness/liveness-upvars.stderr new file mode 100644 index 000000000..82f62371e --- /dev/null +++ b/tests/ui/liveness/liveness-upvars.stderr @@ -0,0 +1,185 @@ +warning: value assigned to `last` is never read + --> $DIR/liveness-upvars.rs:10:9 + | +LL | last = Some(s); + | ^^^^ + | + = help: maybe it is overwritten before being read? +note: the lint level is defined here + --> $DIR/liveness-upvars.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` + +warning: unused variable: `last` + --> $DIR/liveness-upvars.rs:10:9 + | +LL | last = Some(s); + | ^^^^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: unused variable: `sum` + --> $DIR/liveness-upvars.rs:22:9 + | +LL | sum += x; + | ^^^ + | + = help: did you mean to capture by reference instead? + +warning: value captured by `c` is never read + --> $DIR/liveness-upvars.rs:32:9 + | +LL | c = 1; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: value captured by `c` is never read + --> $DIR/liveness-upvars.rs:36:9 + | +LL | c = 1; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: unused variable: `c` + --> $DIR/liveness-upvars.rs:42:9 + | +LL | c += 1; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: value assigned to `c` is never read + --> $DIR/liveness-upvars.rs:45:9 + | +LL | c += 1; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `c` + --> $DIR/liveness-upvars.rs:45:9 + | +LL | c += 1; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: value assigned to `c` is never read + --> $DIR/liveness-upvars.rs:58:9 + | +LL | c += 1; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `c` is never read + --> $DIR/liveness-upvars.rs:64:9 + | +LL | c += 1; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `d` is never read + --> $DIR/liveness-upvars.rs:73:13 + | +LL | d = Some("d1"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `e` is never read + --> $DIR/liveness-upvars.rs:77:13 + | +LL | e = Some("e1"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `e` is never read + --> $DIR/liveness-upvars.rs:79:13 + | +LL | e = Some("e2"); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `e` + --> $DIR/liveness-upvars.rs:77:13 + | +LL | e = Some("e1"); + | ^ + | + = help: did you mean to capture by reference instead? + +warning: value assigned to `v` is never read + --> $DIR/liveness-upvars.rs:87:13 + | +LL | v = T::default(); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `z` is never read + --> $DIR/liveness-upvars.rs:99:17 + | +LL | z = T::default(); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `z` + --> $DIR/liveness-upvars.rs:99:17 + | +LL | z = T::default(); + | ^ + | + = help: did you mean to capture by reference instead? + +warning: value assigned to `state` is never read + --> $DIR/liveness-upvars.rs:125:9 + | +LL | state = 4; + | ^^^^^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `state` is never read + --> $DIR/liveness-upvars.rs:128:9 + | +LL | state = 5; + | ^^^^^ + | + = help: maybe it is overwritten before being read? + +warning: unused variable: `state` + --> $DIR/liveness-upvars.rs:125:9 + | +LL | state = 4; + | ^^^^^ + | + = help: did you mean to capture by reference instead? + +warning: value assigned to `s` is never read + --> $DIR/liveness-upvars.rs:137:9 + | +LL | s = 1; + | ^ + | + = help: maybe it is overwritten before being read? + +warning: value assigned to `s` is never read + --> $DIR/liveness-upvars.rs:139:9 + | +LL | s = yield (); + | ^ + | + = help: maybe it is overwritten before being read? + +warning: 22 warnings emitted + diff --git a/tests/ui/liveness/liveness-use-after-move.rs b/tests/ui/liveness/liveness-use-after-move.rs new file mode 100644 index 000000000..46102ca1e --- /dev/null +++ b/tests/ui/liveness/liveness-use-after-move.rs @@ -0,0 +1,8 @@ +fn main() { + + let x: Box<_> = 5.into(); + let y = x; + + println!("{}", *x); //~ ERROR borrow of moved value: `x` + y.clone(); +} diff --git a/tests/ui/liveness/liveness-use-after-move.stderr b/tests/ui/liveness/liveness-use-after-move.stderr new file mode 100644 index 000000000..3accba197 --- /dev/null +++ b/tests/ui/liveness/liveness-use-after-move.stderr @@ -0,0 +1,20 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/liveness-use-after-move.rs:6:20 + | +LL | let x: Box<_> = 5.into(); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | let y = x; + | - value moved here +LL | +LL | println!("{}", *x); + | ^^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | let y = x.clone(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/liveness/liveness-use-after-send.rs b/tests/ui/liveness/liveness-use-after-send.rs new file mode 100644 index 000000000..6fcd91a9d --- /dev/null +++ b/tests/ui/liveness/liveness-use-after-send.rs @@ -0,0 +1,19 @@ +use std::marker; + +fn send(ch: Chan, data: T) { + println!("{:?}", ch); + println!("{:?}", data); + panic!(); +} + +#[derive(Debug)] +struct Chan(isize, marker::PhantomData); + +// Tests that "log(debug, message);" is flagged as using +// message after the send deinitializes it +fn test00_start(ch: Chan>, message: Box, _count: Box) { + send(ch, message); + println!("{}", message); //~ ERROR borrow of moved value: `message` +} + +fn main() { panic!(); } diff --git a/tests/ui/liveness/liveness-use-after-send.stderr b/tests/ui/liveness/liveness-use-after-send.stderr new file mode 100644 index 000000000..65d55ca8f --- /dev/null +++ b/tests/ui/liveness/liveness-use-after-send.stderr @@ -0,0 +1,24 @@ +error[E0382]: borrow of moved value: `message` + --> $DIR/liveness-use-after-send.rs:16:20 + | +LL | fn test00_start(ch: Chan>, message: Box, _count: Box) { + | ------- move occurs because `message` has type `Box`, which does not implement the `Copy` trait +LL | send(ch, message); + | ------- value moved here +LL | println!("{}", message); + | ^^^^^^^ value borrowed here after move + | +note: consider changing this parameter type in function `send` to borrow instead if owning the value isn't necessary + --> $DIR/liveness-use-after-send.rs:3:54 + | +LL | fn send(ch: Chan, data: T) { + | ---- in this function ^ this parameter takes ownership of the value + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | send(ch, message.clone()); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/log-err-phi.rs b/tests/ui/log-err-phi.rs new file mode 100644 index 000000000..c0e04d2c9 --- /dev/null +++ b/tests/ui/log-err-phi.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + if false { + println!("{}", "foobar"); + } +} diff --git a/tests/ui/log-knows-the-names-of-variants.rs b/tests/ui/log-knows-the-names-of-variants.rs new file mode 100644 index 000000000..cf2876b6e --- /dev/null +++ b/tests/ui/log-knows-the-names-of-variants.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#[derive(Debug)] +enum foo { + a(usize), + b(String), + c, +} + +#[derive(Debug)] +enum bar { + d, e, f +} + +pub fn main() { + assert_eq!("a(22)".to_string(), format!("{:?}", foo::a(22))); + assert_eq!("c".to_string(), format!("{:?}", foo::c)); + assert_eq!("d".to_string(), format!("{:?}", bar::d)); +} diff --git a/tests/ui/log-poly.rs b/tests/ui/log-poly.rs new file mode 100644 index 000000000..14e1b40e1 --- /dev/null +++ b/tests/ui/log-poly.rs @@ -0,0 +1,13 @@ +// run-pass + +#[derive(Debug)] +enum Numbers { + Three +} + +pub fn main() { + println!("{:?}", 1); + println!("{:?}", 2.0f64); + println!("{:?}", Numbers::Three); + println!("{:?}", vec![4]); +} diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/logging-only-prints-once.rs new file mode 100644 index 000000000..6d16819ce --- /dev/null +++ b/tests/ui/logging-only-prints-once.rs @@ -0,0 +1,30 @@ +// run-pass +// ignore-windows +// ignore-emscripten no threads support + +use std::cell::Cell; +use std::fmt; +use std::thread; + +struct Foo(Cell); + +impl fmt::Debug for Foo { + fn fmt(&self, _fmt: &mut fmt::Formatter) -> fmt::Result { + let Foo(ref f) = *self; + assert_eq!(f.get(), 0); + f.set(1); + Ok(()) + } +} + +pub fn main() { + thread::spawn(move || { + let mut f = Foo(Cell::new(0)); + println!("{:?}", f); + let Foo(ref mut f) = f; + assert_eq!(f.get(), 1); + }) + .join() + .ok() + .unwrap(); +} diff --git a/tests/ui/loops/for-each-loop-panic.rs b/tests/ui/loops/for-each-loop-panic.rs new file mode 100644 index 000000000..5156999f4 --- /dev/null +++ b/tests/ui/loops/for-each-loop-panic.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:moop +// ignore-emscripten no processes + +fn main() { + for _ in 0_usize..10_usize { + panic!("moop"); + } +} diff --git a/tests/ui/loops/issue-82916.rs b/tests/ui/loops/issue-82916.rs new file mode 100644 index 000000000..8633ea1e8 --- /dev/null +++ b/tests/ui/loops/issue-82916.rs @@ -0,0 +1,10 @@ +struct S(i32); + +fn foo(x: Vec) { + for y in x { + + } + let z = x; //~ ERROR use of moved value: `x` +} + +fn main() {} diff --git a/tests/ui/loops/issue-82916.stderr b/tests/ui/loops/issue-82916.stderr new file mode 100644 index 000000000..e6a60d7bc --- /dev/null +++ b/tests/ui/loops/issue-82916.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `x` + --> $DIR/issue-82916.rs:7:13 + | +LL | fn foo(x: Vec) { + | - move occurs because `x` has type `Vec`, which does not implement the `Copy` trait +LL | for y in x { + | - `x` moved due to this implicit call to `.into_iter()` +... +LL | let z = x; + | ^ value used here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `x` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider iterating over a slice of the `Vec`'s content to avoid moving into the `for` loop + | +LL | for y in &x { + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/loops/loop-break-unsize.rs b/tests/ui/loops/loop-break-unsize.rs new file mode 100644 index 000000000..974c63cea --- /dev/null +++ b/tests/ui/loops/loop-break-unsize.rs @@ -0,0 +1,8 @@ +// Regression test for #62312 +// check-pass + +fn main() { + let _ = loop { + break Box::new(()) as Box; + }; +} diff --git a/tests/ui/loops/loop-break-value-no-repeat.rs b/tests/ui/loops/loop-break-value-no-repeat.rs new file mode 100644 index 000000000..1c0b7a018 --- /dev/null +++ b/tests/ui/loops/loop-break-value-no-repeat.rs @@ -0,0 +1,14 @@ +#![allow(unused_variables)] + +use std::ptr; + +// Test that we only report **one** error here and that is that +// `break` with an expression is illegal in this context. In +// particular, we don't report any mismatched types error, which is +// besides the point. + +fn main() { + for _ in &[1,2,3] { + break 22 //~ ERROR `break` with value from a `for` loop + } +} diff --git a/tests/ui/loops/loop-break-value-no-repeat.stderr b/tests/ui/loops/loop-break-value-no-repeat.stderr new file mode 100644 index 000000000..605a1841c --- /dev/null +++ b/tests/ui/loops/loop-break-value-no-repeat.stderr @@ -0,0 +1,16 @@ +error[E0571]: `break` with value from a `for` loop + --> $DIR/loop-break-value-no-repeat.rs:12:9 + | +LL | for _ in &[1,2,3] { + | ----------------- you can't `break` with a value in a `for` loop +LL | break 22 + | ^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `for` loop + | +LL | break + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0571`. diff --git a/tests/ui/loops/loop-break-value.rs b/tests/ui/loops/loop-break-value.rs new file mode 100644 index 000000000..51c9a36a0 --- /dev/null +++ b/tests/ui/loops/loop-break-value.rs @@ -0,0 +1,98 @@ +#![feature(never_type)] + +fn main() { + let val: ! = loop { break break; }; + //~^ ERROR mismatched types + + loop { + if true { + break "asdf"; + } else { + break 123; //~ ERROR mismatched types + } + }; + + let _: i32 = loop { + break "asdf"; //~ ERROR mismatched types + }; + + let _: i32 = 'outer_loop: loop { + loop { + break 'outer_loop "nope"; //~ ERROR mismatched types + break "ok"; + }; + }; + + 'while_loop: while true { //~ WARN denote infinite loops with + break; + break (); //~ ERROR `break` with value from a `while` loop + loop { + break 'while_loop 123; + //~^ ERROR `break` with value from a `while` loop + break 456; + break 789; + }; + } + + while let Some(_) = Some(()) { + if break () { //~ ERROR `break` with value from a `while` loop + } + } + + while let Some(_) = Some(()) { + break None; + //~^ ERROR `break` with value from a `while` loop + } + + 'while_let_loop: while let Some(_) = Some(()) { + loop { + break 'while_let_loop "nope"; + //~^ ERROR `break` with value from a `while` loop + break 33; + }; + } + + for _ in &[1,2,3] { + break (); //~ ERROR `break` with value from a `for` loop + break [()]; + //~^ ERROR `break` with value from a `for` loop + } + + 'for_loop: for _ in &[1,2,3] { + loop { + break Some(3); + break 'for_loop Some(17); + //~^ ERROR `break` with value from a `for` loop + }; + } + + let _: i32 = 'a: loop { + let _: () = 'b: loop { + break ('c: loop { + break; + break 'c 123; //~ ERROR mismatched types + }); + break 'a 123; + }; + }; + + loop { + break (break, break); //~ ERROR mismatched types + }; + + loop { + break; + break 2; //~ ERROR mismatched types + }; + + loop { + break 2; + break; //~ ERROR mismatched types + break 4; + }; + + 'LOOP: for _ in 0 .. 9 { + break LOOP; + //~^ ERROR cannot find value `LOOP` in this scope + } +} diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr new file mode 100644 index 000000000..ccb27c350 --- /dev/null +++ b/tests/ui/loops/loop-break-value.stderr @@ -0,0 +1,193 @@ +error[E0425]: cannot find value `LOOP` in this scope + --> $DIR/loop-break-value.rs:95:15 + | +LL | 'LOOP: for _ in 0 .. 9 { + | ----- a label with a similar name exists +LL | break LOOP; + | ^^^^ + | | + | not found in this scope + | help: use the similarly named label: `'LOOP` + +warning: denote infinite loops with `loop { ... }` + --> $DIR/loop-break-value.rs:26:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0571]: `break` with value from a `while` loop + --> $DIR/loop-break-value.rs:28:9 + | +LL | 'while_loop: while true { + | ----------------------- you can't `break` with a value in a `while` loop +LL | break; +LL | break (); + | ^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ +help: alternatively, you might have meant to use the available loop label + | +LL | break 'while_loop; + | ~~~~~~~~~~~ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/loop-break-value.rs:30:13 + | +LL | 'while_loop: while true { + | ----------------------- you can't `break` with a value in a `while` loop +... +LL | break 'while_loop 123; + | ^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break 'while_loop; + | ~~~~~~~~~~~~~~~~~ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/loop-break-value.rs:38:12 + | +LL | while let Some(_) = Some(()) { + | ---------------------------- you can't `break` with a value in a `while` loop +LL | if break () { + | ^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | if break { + | ~~~~~ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/loop-break-value.rs:43:9 + | +LL | while let Some(_) = Some(()) { + | ---------------------------- you can't `break` with a value in a `while` loop +LL | break None; + | ^^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ + +error[E0571]: `break` with value from a `while` loop + --> $DIR/loop-break-value.rs:49:13 + | +LL | 'while_let_loop: while let Some(_) = Some(()) { + | --------------------------------------------- you can't `break` with a value in a `while` loop +LL | loop { +LL | break 'while_let_loop "nope"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break 'while_let_loop; + | ~~~~~~~~~~~~~~~~~~~~~ + +error[E0571]: `break` with value from a `for` loop + --> $DIR/loop-break-value.rs:56:9 + | +LL | for _ in &[1,2,3] { + | ----------------- you can't `break` with a value in a `for` loop +LL | break (); + | ^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `for` loop + | +LL | break; + | ~~~~~ + +error[E0571]: `break` with value from a `for` loop + --> $DIR/loop-break-value.rs:57:9 + | +LL | for _ in &[1,2,3] { + | ----------------- you can't `break` with a value in a `for` loop +LL | break (); +LL | break [()]; + | ^^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `for` loop + | +LL | break; + | ~~~~~ + +error[E0571]: `break` with value from a `for` loop + --> $DIR/loop-break-value.rs:64:13 + | +LL | 'for_loop: for _ in &[1,2,3] { + | ---------------------------- you can't `break` with a value in a `for` loop +... +LL | break 'for_loop Some(17); + | ^^^^^^^^^^^^^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `for` loop + | +LL | break 'for_loop; + | ~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:4:31 + | +LL | let val: ! = loop { break break; }; + | ^^^^^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:11:19 + | +LL | break 123; + | ^^^ expected `&str`, found integer + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:16:15 + | +LL | break "asdf"; + | ^^^^^^ expected `i32`, found `&str` + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:21:31 + | +LL | break 'outer_loop "nope"; + | ^^^^^^ expected `i32`, found `&str` + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:73:26 + | +LL | break 'c 123; + | ^^^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:80:15 + | +LL | break (break, break); + | ^^^^^^^^^^^^^^ expected `()`, found tuple + | + = note: expected unit type `()` + found tuple `(!, !)` + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:85:15 + | +LL | break 2; + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:90:9 + | +LL | break; + | ^^^^^ + | | + | expected integer, found `()` + | help: give it a value of the expected type: `break value` + +error: aborting due to 17 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0308, E0425, E0571. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-labeled-break-value.rs b/tests/ui/loops/loop-labeled-break-value.rs new file mode 100644 index 000000000..3488b057b --- /dev/null +++ b/tests/ui/loops/loop-labeled-break-value.rs @@ -0,0 +1,11 @@ +fn main() { + loop { + let _: i32 = loop { break }; //~ ERROR mismatched types + } + loop { + let _: i32 = 'inner: loop { break 'inner }; //~ ERROR mismatched types + } + loop { + let _: i32 = 'inner2: loop { loop { break 'inner2 } }; //~ ERROR mismatched types + } +} diff --git a/tests/ui/loops/loop-labeled-break-value.stderr b/tests/ui/loops/loop-labeled-break-value.stderr new file mode 100644 index 000000000..aa04d330f --- /dev/null +++ b/tests/ui/loops/loop-labeled-break-value.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/loop-labeled-break-value.rs:3:29 + | +LL | let _: i32 = loop { break }; + | ^^^^^ + | | + | expected `i32`, found `()` + | help: give it a value of the expected type: `break 42` + +error[E0308]: mismatched types + --> $DIR/loop-labeled-break-value.rs:6:37 + | +LL | let _: i32 = 'inner: loop { break 'inner }; + | ^^^^^^^^^^^^ + | | + | expected `i32`, found `()` + | help: give it a value of the expected type: `break 'inner 42` + +error[E0308]: mismatched types + --> $DIR/loop-labeled-break-value.rs:9:45 + | +LL | let _: i32 = 'inner2: loop { loop { break 'inner2 } }; + | ^^^^^^^^^^^^^ + | | + | expected `i32`, found `()` + | help: give it a value of the expected type: `break 'inner2 42` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-no-implicit-break.rs b/tests/ui/loops/loop-no-implicit-break.rs new file mode 100644 index 000000000..93078cb4b --- /dev/null +++ b/tests/ui/loops/loop-no-implicit-break.rs @@ -0,0 +1,31 @@ +fn main() { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; +} + +fn foo() -> i8 { + let a: i8 = loop { + 1 //~ ERROR mismatched types + }; + + let b: i8 = loop { + break 1; + }; + + loop { + 1 //~ ERROR mismatched types + } + + loop { + return 1; + } + + loop { + 1 //~ ERROR mismatched types + } +} diff --git a/tests/ui/loops/loop-no-implicit-break.stderr b/tests/ui/loops/loop-no-implicit-break.stderr new file mode 100644 index 000000000..8a1afdea2 --- /dev/null +++ b/tests/ui/loops/loop-no-implicit-break.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:3:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | +++++ + + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:13:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to break the loop with this value + | +LL | break 1; + | +++++ + + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:21:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/loop-no-implicit-break.rs:29:9 + | +LL | 1 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | return 1; + | ++++++ + + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-proper-liveness.rs b/tests/ui/loops/loop-proper-liveness.rs new file mode 100644 index 000000000..6546e3977 --- /dev/null +++ b/tests/ui/loops/loop-proper-liveness.rs @@ -0,0 +1,32 @@ +fn test1() { + // In this test the outer 'a loop may terminate without `x` getting initialised. Although the + // `x = loop { ... }` statement is reached, the value itself ends up never being computed and + // thus leaving `x` uninit. + let x: i32; + 'a: loop { + x = loop { break 'a }; + } + println!("{:?}", x); //~ ERROR E0381 +} + +// test2 and test3 should not fail. +fn test2() { + // In this test the `'a` loop will never terminate thus making the use of `x` unreachable. + let x: i32; + 'a: loop { + x = loop { continue 'a }; + } + println!("{:?}", x); +} + +fn test3() { + let x: i32; + // Similarly, the use of variable `x` is unreachable. + 'a: loop { + x = loop { return }; + } + println!("{:?}", x); +} + +fn main() { +} diff --git a/tests/ui/loops/loop-proper-liveness.stderr b/tests/ui/loops/loop-proper-liveness.stderr new file mode 100644 index 000000000..f9d94b681 --- /dev/null +++ b/tests/ui/loops/loop-proper-liveness.stderr @@ -0,0 +1,18 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/loop-proper-liveness.rs:9:22 + | +LL | let x: i32; + | - binding declared here but left uninitialized +... +LL | println!("{:?}", x); + | ^ `x` used here but it isn't initialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let x: i32 = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/loops/loop-properly-diverging-2.rs b/tests/ui/loops/loop-properly-diverging-2.rs new file mode 100644 index 000000000..97b3972c1 --- /dev/null +++ b/tests/ui/loops/loop-properly-diverging-2.rs @@ -0,0 +1,6 @@ +fn forever2() -> i32 { + let x: i32 = loop { break }; //~ ERROR mismatched types + x +} + +fn main() {} diff --git a/tests/ui/loops/loop-properly-diverging-2.stderr b/tests/ui/loops/loop-properly-diverging-2.stderr new file mode 100644 index 000000000..5030a2935 --- /dev/null +++ b/tests/ui/loops/loop-properly-diverging-2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/loop-properly-diverging-2.rs:2:23 + | +LL | let x: i32 = loop { break }; + | ^^^^^ + | | + | expected `i32`, found `()` + | help: give it a value of the expected type: `break 42` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loud_ui.rs b/tests/ui/loud_ui.rs new file mode 100644 index 000000000..6a151fa49 --- /dev/null +++ b/tests/ui/loud_ui.rs @@ -0,0 +1,6 @@ +// should-fail + +// this test ensures that when we forget to use +// any `//~ ERROR` comments whatsoever, that the test doesn't succeed + +fn main() {} diff --git a/tests/ui/lowering/issue-96847.rs b/tests/ui/lowering/issue-96847.rs new file mode 100644 index 000000000..2aa34c8b3 --- /dev/null +++ b/tests/ui/lowering/issue-96847.rs @@ -0,0 +1,14 @@ +// run-pass + +// Test that this doesn't abort during AST lowering. In #96847 it did abort +// because the attribute was being lowered twice. + +#![feature(stmt_expr_attributes)] +#![feature(lang_items)] + +fn main() { + for _ in [1,2,3] { + #![lang="foo"] + println!("foo"); + } +} diff --git a/tests/ui/lto/all-crates.rs b/tests/ui/lto/all-crates.rs new file mode 100644 index 000000000..e910b2a9f --- /dev/null +++ b/tests/ui/lto/all-crates.rs @@ -0,0 +1,8 @@ +// run-pass + +// compile-flags: -Clto=thin +// no-prefer-dynamic + +fn main() { + println!("hello!"); +} diff --git a/tests/ui/lto/auxiliary/debuginfo-lto-aux.rs b/tests/ui/lto/auxiliary/debuginfo-lto-aux.rs new file mode 100644 index 000000000..dd471154b --- /dev/null +++ b/tests/ui/lto/auxiliary/debuginfo-lto-aux.rs @@ -0,0 +1,29 @@ +// compile-flags: -g --crate-type=rlib + +pub struct StructWithLifetime<'a>(&'a i32); +pub fn mk_struct_with_lt<'a>(x: &'a i32) -> StructWithLifetime<'a> { + StructWithLifetime(x) +} + +pub struct RegularStruct(u32); +pub fn mk_regular_struct(x: u32) -> RegularStruct { + RegularStruct(x) +} + +pub fn take_fn(f: fn(i32) -> i32, x: i32) -> i32 { + f(x) +} + +pub fn with_closure(x: i32) -> i32 { + let closure = |i| { x + i }; + + closure(1) + closure(2) +} + +pub fn generic_fn(x: T) -> (T, u32) { + (x, 1) +} + +pub fn user_of_generic_fn(x: f32) -> (f32, u32) { + generic_fn(x) +} diff --git a/tests/ui/lto/auxiliary/dylib.rs b/tests/ui/lto/auxiliary/dylib.rs new file mode 100644 index 000000000..e8b7f8f9f --- /dev/null +++ b/tests/ui/lto/auxiliary/dylib.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z thinlto -C codegen-units=8 + +#[inline] +pub fn foo(b: u8) { + b.to_string(); +} diff --git a/tests/ui/lto/auxiliary/lto-duplicate-symbols1.rs b/tests/ui/lto/auxiliary/lto-duplicate-symbols1.rs new file mode 100644 index 000000000..ec6d05603 --- /dev/null +++ b/tests/ui/lto/auxiliary/lto-duplicate-symbols1.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/tests/ui/lto/auxiliary/lto-duplicate-symbols2.rs b/tests/ui/lto/auxiliary/lto-duplicate-symbols2.rs new file mode 100644 index 000000000..ec6d05603 --- /dev/null +++ b/tests/ui/lto/auxiliary/lto-duplicate-symbols2.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#[no_mangle] +pub extern "C" fn foo() {} diff --git a/tests/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs b/tests/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs new file mode 100644 index 000000000..d24375b2d --- /dev/null +++ b/tests/ui/lto/auxiliary/lto-rustc-loads-linker-plugin.rs @@ -0,0 +1,6 @@ +// compile-flags: -Clinker-plugin-lto +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/tests/ui/lto/auxiliary/msvc-imp-present.rs b/tests/ui/lto/auxiliary/msvc-imp-present.rs new file mode 100644 index 000000000..933af050a --- /dev/null +++ b/tests/ui/lto/auxiliary/msvc-imp-present.rs @@ -0,0 +1,11 @@ +// no-prefer-dynamic +// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic + +#![crate_type = "rlib"] +#![crate_type = "dylib"] + +pub static A: u32 = 43; + +pub mod a { + pub static A: u32 = 43; +} diff --git a/tests/ui/lto/auxiliary/thin-lto-inlines-aux.rs b/tests/ui/lto/auxiliary/thin-lto-inlines-aux.rs new file mode 100644 index 000000000..5fd3f1996 --- /dev/null +++ b/tests/ui/lto/auxiliary/thin-lto-inlines-aux.rs @@ -0,0 +1,7 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn bar() -> u32 { + 3 +} diff --git a/tests/ui/lto/auxiliary/thinlto-dylib.rs b/tests/ui/lto/auxiliary/thinlto-dylib.rs new file mode 100644 index 000000000..9d17c35da --- /dev/null +++ b/tests/ui/lto/auxiliary/thinlto-dylib.rs @@ -0,0 +1,23 @@ +// Auxiliary crate for test issue-105637: the LTOed dylib which had duplicate symbols from libstd, +// breaking the panic hook feature. +// +// This simulates the `rustc_driver` crate, and the main crate simulates rustc's main binary hooking +// into this driver. + +// compile-flags: -Zdylib-lto -C lto=thin + +use std::panic; + +pub fn main() { + // Install the hook we want to see executed + panic::set_hook(Box::new(|_| { + eprintln!("LTOed auxiliary crate panic hook"); + })); + + // Trigger the panic hook with an ICE + run_compiler(); +} + +fn run_compiler() { + panic!("ICEing"); +} diff --git a/tests/ui/lto/debuginfo-lto.rs b/tests/ui/lto/debuginfo-lto.rs new file mode 100644 index 000000000..43f75b034 --- /dev/null +++ b/tests/ui/lto/debuginfo-lto.rs @@ -0,0 +1,25 @@ +// run-pass +// This test case makes sure that we don't run into LLVM's dreaded +// "possible ODR violation" assertion when compiling with LTO + Debuginfo. +// It covers cases that have traditionally been prone to cause this error. +// If new cases emerge, add them to this file. + +// aux-build:debuginfo-lto-aux.rs +// compile-flags: -C lto -g +// no-prefer-dynamic +// ignore-asmjs wasm2js does not support source maps yet + +extern crate debuginfo_lto_aux; + +fn some_fn(x: i32) -> i32 { + x + 1 +} + +fn main() { + let i = 0; + let _ = debuginfo_lto_aux::mk_struct_with_lt(&i); + let _ = debuginfo_lto_aux::mk_regular_struct(1); + let _ = debuginfo_lto_aux::take_fn(some_fn, 1); + let _ = debuginfo_lto_aux::with_closure(22); + let _ = debuginfo_lto_aux::generic_fn(0f32); +} diff --git a/tests/ui/lto/dylib-works.rs b/tests/ui/lto/dylib-works.rs new file mode 100644 index 000000000..9e0782b59 --- /dev/null +++ b/tests/ui/lto/dylib-works.rs @@ -0,0 +1,9 @@ +// run-pass + +// aux-build:dylib.rs + +extern crate dylib; + +fn main() { + dylib::foo(1); +} diff --git a/tests/ui/lto/fat-lto.rs b/tests/ui/lto/fat-lto.rs new file mode 100644 index 000000000..c8d8095a2 --- /dev/null +++ b/tests/ui/lto/fat-lto.rs @@ -0,0 +1,7 @@ +// run-pass +// compile-flags: -Clto=fat +// no-prefer-dynamic + +fn main() { + println!("hello!"); +} diff --git a/tests/ui/lto/issue-100772.rs b/tests/ui/lto/issue-100772.rs new file mode 100644 index 000000000..d6b067192 --- /dev/null +++ b/tests/ui/lto/issue-100772.rs @@ -0,0 +1,11 @@ +// run-pass +// needs-sanitizer-cfi +// compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +// no-prefer-dynamic +// only-x86_64-unknown-linux-gnu + +#![feature(allocator_api)] + +fn main() { + let _ = Box::new_in(&[0, 1], &std::alloc::Global); +} diff --git a/tests/ui/lto/issue-105637.rs b/tests/ui/lto/issue-105637.rs new file mode 100644 index 000000000..0d9f0bec0 --- /dev/null +++ b/tests/ui/lto/issue-105637.rs @@ -0,0 +1,28 @@ +// Regression test for issue #105637: `-Zdylib-lto` with LTO duplicated symbols from other dylibs, +// in this case from libstd. +// +// That manifested as both `rustc_driver` and rustc's "main" (`compiler/rustc`) having their own +// `std::panicking::HOOK` static, and the hook in rustc's main (the default stdlib's) being executed +// when rustc ICEs, instead of the overriden hook from `rustc_driver` (which also displays the query +// stack and information on how to open a GH issue for the encountered ICE). +// +// In this test, we reproduce this setup by installing a panic hook in both the main and an LTOed +// dylib: the last hook set should be the one being executed, the dylib's. + +// aux-build: thinlto-dylib.rs +// run-fail +// check-run-results + +extern crate thinlto_dylib; + +use std::panic; + +fn main() { + // We don't want to see this panic hook executed + std::panic::set_hook(Box::new(|_| { + eprintln!("main crate panic hook"); + })); + + // Have the LTOed dylib install its own hook and panic, we want to see its hook executed. + thinlto_dylib::main(); +} diff --git a/tests/ui/lto/issue-105637.run.stderr b/tests/ui/lto/issue-105637.run.stderr new file mode 100644 index 000000000..43388e776 --- /dev/null +++ b/tests/ui/lto/issue-105637.run.stderr @@ -0,0 +1 @@ +LTOed auxiliary crate panic hook diff --git a/tests/ui/lto/issue-11154.rs b/tests/ui/lto/issue-11154.rs new file mode 100644 index 000000000..e11cdc82f --- /dev/null +++ b/tests/ui/lto/issue-11154.rs @@ -0,0 +1,6 @@ +// build-fail +// compile-flags: -C lto -C prefer-dynamic + +// error-pattern: cannot prefer dynamic linking + +fn main() {} diff --git a/tests/ui/lto/issue-11154.stderr b/tests/ui/lto/issue-11154.stderr new file mode 100644 index 000000000..8eec8b37c --- /dev/null +++ b/tests/ui/lto/issue-11154.stderr @@ -0,0 +1,6 @@ +error: cannot prefer dynamic linking when performing LTO + +note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO + +error: aborting due to previous error + diff --git a/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs b/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs new file mode 100644 index 000000000..f381240e7 --- /dev/null +++ b/tests/ui/lto/lto-and-no-bitcode-in-rlib.rs @@ -0,0 +1,3 @@ +// compile-flags: -C lto -C embed-bitcode=no + +fn main() {} diff --git a/tests/ui/lto/lto-and-no-bitcode-in-rlib.stderr b/tests/ui/lto/lto-and-no-bitcode-in-rlib.stderr new file mode 100644 index 000000000..11e370e91 --- /dev/null +++ b/tests/ui/lto/lto-and-no-bitcode-in-rlib.stderr @@ -0,0 +1,2 @@ +error: options `-C embed-bitcode=no` and `-C lto` are incompatible + diff --git a/tests/ui/lto/lto-duplicate-symbols.rs b/tests/ui/lto/lto-duplicate-symbols.rs new file mode 100644 index 000000000..e540094a3 --- /dev/null +++ b/tests/ui/lto/lto-duplicate-symbols.rs @@ -0,0 +1,11 @@ +// build-fail +// aux-build:lto-duplicate-symbols1.rs +// aux-build:lto-duplicate-symbols2.rs +// error-pattern:Linking globals named 'foo': symbol multiply defined! +// compile-flags: -C lto +// no-prefer-dynamic +// normalize-stderr-test: "lto-duplicate-symbols2\.lto_duplicate_symbols2\.[0-9a-zA-Z]+-cgu" -> "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu" +extern crate lto_duplicate_symbols1; +extern crate lto_duplicate_symbols2; + +fn main() {} diff --git a/tests/ui/lto/lto-duplicate-symbols.stderr b/tests/ui/lto/lto-duplicate-symbols.stderr new file mode 100644 index 000000000..f66afa94f --- /dev/null +++ b/tests/ui/lto/lto-duplicate-symbols.stderr @@ -0,0 +1,6 @@ +warning: Linking globals named 'foo': symbol multiply defined! + +error: failed to load bitcode of module "lto-duplicate-symbols2.lto_duplicate_symbols2.HASH-cgu.0.rcgu.o": + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/lto/lto-many-codegen-units.rs b/tests/ui/lto/lto-many-codegen-units.rs new file mode 100644 index 000000000..f0f461ffe --- /dev/null +++ b/tests/ui/lto/lto-many-codegen-units.rs @@ -0,0 +1,6 @@ +// run-pass +// compile-flags: -C lto -C codegen-units=8 +// no-prefer-dynamic + +fn main() { +} diff --git a/tests/ui/lto/lto-opt-level-s.rs b/tests/ui/lto/lto-opt-level-s.rs new file mode 100644 index 000000000..a7d9d5024 --- /dev/null +++ b/tests/ui/lto/lto-opt-level-s.rs @@ -0,0 +1,7 @@ +// compile-flags: -Clinker-plugin-lto -Copt-level=s +// build-pass +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/tests/ui/lto/lto-opt-level-z.rs b/tests/ui/lto/lto-opt-level-z.rs new file mode 100644 index 000000000..bf1f5e2b2 --- /dev/null +++ b/tests/ui/lto/lto-opt-level-z.rs @@ -0,0 +1,7 @@ +// compile-flags: -Clinker-plugin-lto -Copt-level=z +// build-pass +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/tests/ui/lto/lto-rustc-loads-linker-plugin.rs b/tests/ui/lto/lto-rustc-loads-linker-plugin.rs new file mode 100644 index 000000000..6ef1d4540 --- /dev/null +++ b/tests/ui/lto/lto-rustc-loads-linker-plugin.rs @@ -0,0 +1,17 @@ +// compile-flags: -C lto +// aux-build:lto-rustc-loads-linker-plugin.rs +// run-pass +// no-prefer-dynamic + +// This test ensures that if a dependency was compiled with +// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against +// that upstream rlib. This should work because LTO implies we're not actually +// linking against upstream rlibs since we're generating the object code +// locally. This test will fail if rustc can't find bytecode in rlibs compiled +// with `-Clinker-plugin-lto`. + +extern crate lto_rustc_loads_linker_plugin; + +fn main() { + lto_rustc_loads_linker_plugin::foo(); +} diff --git a/tests/ui/lto/lto-still-runs-thread-dtors.rs b/tests/ui/lto/lto-still-runs-thread-dtors.rs new file mode 100644 index 000000000..1c7368b36 --- /dev/null +++ b/tests/ui/lto/lto-still-runs-thread-dtors.rs @@ -0,0 +1,34 @@ +// run-pass +// compile-flags: -C lto +// no-prefer-dynamic +// ignore-emscripten no threads support +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +use std::thread; + +static mut HIT: usize = 0; + +thread_local!(static A: Foo = Foo); + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { + HIT += 1; + } + } +} + +fn main() { + unsafe { + assert_eq!(HIT, 0); + thread::spawn(|| { + assert_eq!(HIT, 0); + A.with(|_| ()); + assert_eq!(HIT, 0); + }).join().unwrap(); + assert_eq!(HIT, 1); + } +} diff --git a/tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs b/tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs new file mode 100644 index 000000000..4d54ce32f --- /dev/null +++ b/tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs @@ -0,0 +1,13 @@ +// compile-flags: -C lto=thin +// aux-build:lto-rustc-loads-linker-plugin.rs +// run-pass +// no-prefer-dynamic + +// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with +// ThinLTO. + +extern crate lto_rustc_loads_linker_plugin; + +fn main() { + lto_rustc_loads_linker_plugin::foo(); +} diff --git a/tests/ui/lto/msvc-imp-present.rs b/tests/ui/lto/msvc-imp-present.rs new file mode 100644 index 000000000..5498afb29 --- /dev/null +++ b/tests/ui/lto/msvc-imp-present.rs @@ -0,0 +1,22 @@ +// run-pass + +// aux-build:msvc-imp-present.rs +// compile-flags: -Z thinlto -C codegen-units=8 +// no-prefer-dynamic + +// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name` +// for all exported statics. This is done because we apply `dllimport` to all +// imported constants and this allows everything to actually link correctly. +// +// The ThinLTO passes aggressively remove symbols if they can, and this test +// asserts that the ThinLTO passes don't remove these compiler-generated +// `_imp_*` symbols. The external library that we link in here is compiled with +// ThinLTO and multiple codegen units and has a few exported constants. Note +// that we also namely compile the library as both a dylib and an rlib, but we +// link the rlib to ensure that we assert those generated symbols exist. + +extern crate msvc_imp_present as bar; + +fn main() { + println!("{}", bar::A); +} diff --git a/tests/ui/lto/thin-lto-global-allocator.rs b/tests/ui/lto/thin-lto-global-allocator.rs new file mode 100644 index 000000000..e00c5caf9 --- /dev/null +++ b/tests/ui/lto/thin-lto-global-allocator.rs @@ -0,0 +1,7 @@ +// run-pass +// compile-flags: -Z thinlto -C codegen-units=2 + +#[global_allocator] +static A: std::alloc::System = std::alloc::System; + +fn main() {} diff --git a/tests/ui/lto/thin-lto-inlines.rs b/tests/ui/lto/thin-lto-inlines.rs new file mode 100644 index 000000000..dca791807 --- /dev/null +++ b/tests/ui/lto/thin-lto-inlines.rs @@ -0,0 +1,30 @@ +// run-pass + +// compile-flags: -Z thinlto -C codegen-units=8 -O +// ignore-emscripten can't inspect instructions on emscripten + +// We want to assert here that ThinLTO will inline across codegen units. There's +// not really a great way to do that in general so we sort of hack around it by +// praying two functions go into separate codegen units and then assuming that +// if inlining *doesn't* happen the first byte of the functions will differ. + +pub fn foo() -> u32 { + bar::bar() +} + +mod bar { + pub fn bar() -> u32 { + 3 + } +} + +fn main() { + println!("{} {}", foo(), bar::bar()); + + unsafe { + let foo = foo as usize as *const u8; + let bar = bar::bar as usize as *const u8; + + assert_eq!(*foo, *bar); + } +} diff --git a/tests/ui/lto/thin-lto-inlines2.rs b/tests/ui/lto/thin-lto-inlines2.rs new file mode 100644 index 000000000..1eb29657c --- /dev/null +++ b/tests/ui/lto/thin-lto-inlines2.rs @@ -0,0 +1,28 @@ +// run-pass + +// compile-flags: -C codegen-units=8 -O -C lto=thin +// aux-build:thin-lto-inlines-aux.rs +// no-prefer-dynamic +// ignore-emscripten can't inspect instructions on emscripten + +// We want to assert here that ThinLTO will inline across codegen units. There's +// not really a great way to do that in general so we sort of hack around it by +// praying two functions go into separate codegen units and then assuming that +// if inlining *doesn't* happen the first byte of the functions will differ. + +extern crate thin_lto_inlines_aux as bar; + +pub fn foo() -> u32 { + bar::bar() +} + +fn main() { + println!("{} {}", foo(), bar::bar()); + + unsafe { + let foo = foo as usize as *const u8; + let bar = bar::bar as usize as *const u8; + + assert_eq!(*foo, *bar); + } +} diff --git a/tests/ui/lto/weak-works.rs b/tests/ui/lto/weak-works.rs new file mode 100644 index 000000000..163a38702 --- /dev/null +++ b/tests/ui/lto/weak-works.rs @@ -0,0 +1,28 @@ +// run-pass + +// compile-flags: -C codegen-units=8 -Z thinlto +// ignore-windows + +#![feature(linkage)] + +pub mod foo { + #[linkage = "weak"] + #[no_mangle] + pub extern "C" fn FOO() -> i32 { + 0 + } +} + +mod bar { + extern "C" { + fn FOO() -> i32; + } + + pub fn bar() -> i32 { + unsafe { FOO() } + } +} + +fn main() { + bar::bar(); +} diff --git a/tests/ui/lub-glb/empty-binder-future-compat.rs b/tests/ui/lub-glb/empty-binder-future-compat.rs new file mode 100644 index 000000000..8700a88a3 --- /dev/null +++ b/tests/ui/lub-glb/empty-binder-future-compat.rs @@ -0,0 +1,22 @@ +// check-pass +fn lt_in_fn_fn<'a: 'a>() -> fn(fn(&'a ())) { + |_| () +} + + +fn foo<'a, 'b, 'lower>(v: bool) +where + 'a: 'lower, + 'b: 'lower, +{ + // if we infer `x` to be higher ranked in the future, + // this would cause a type error. + let x = match v { + true => lt_in_fn_fn::<'a>(), + false => lt_in_fn_fn::<'b>(), + }; + + let _: fn(fn(&'lower())) = x; +} + +fn main() {} diff --git a/tests/ui/lub-glb/empty-binders-err.rs b/tests/ui/lub-glb/empty-binders-err.rs new file mode 100644 index 000000000..557480173 --- /dev/null +++ b/tests/ui/lub-glb/empty-binders-err.rs @@ -0,0 +1,55 @@ +fn lt<'a: 'a>() -> &'a () { + &() +} + +fn lt_in_fn<'a: 'a>() -> fn(&'a ()) { + |_| () +} + +struct Contra<'a>(fn(&'a ())); +fn lt_in_contra<'a: 'a>() -> Contra<'a> { + Contra(|_| ()) +} + +fn covariance<'a, 'b, 'upper>(v: bool) +where + 'upper: 'a, + 'upper: 'b, + +{ + let _: &'upper () = match v { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + true => lt::<'a>(), + false => lt::<'b>(), + }; +} + +fn contra_fn<'a, 'b, 'lower>(v: bool) +where + 'a: 'lower, + 'b: 'lower, + +{ + + let _: fn(&'lower ()) = match v { + //~^ ERROR lifetime may not live long enough + true => lt_in_fn::<'a>(), + false => lt_in_fn::<'b>(), + }; +} + +fn contra_struct<'a, 'b, 'lower>(v: bool) +where + 'a: 'lower, + 'b: 'lower, + +{ + let _: Contra<'lower> = match v { + //~^ ERROR lifetime may not live long enough + true => lt_in_contra::<'a>(), + false => lt_in_contra::<'b>(), + }; +} + +fn main() {} diff --git a/tests/ui/lub-glb/empty-binders-err.stderr b/tests/ui/lub-glb/empty-binders-err.stderr new file mode 100644 index 000000000..f86f22d5e --- /dev/null +++ b/tests/ui/lub-glb/empty-binders-err.stderr @@ -0,0 +1,59 @@ +error: lifetime may not live long enough + --> $DIR/empty-binders-err.rs:20:12 + | +LL | fn covariance<'a, 'b, 'upper>(v: bool) + | -- ------ lifetime `'upper` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'upper () = match v { + | ^^^^^^^^^^ type annotation requires that `'a` must outlive `'upper` + | + = help: consider adding the following bound: `'a: 'upper` + +error: lifetime may not live long enough + --> $DIR/empty-binders-err.rs:20:12 + | +LL | fn covariance<'a, 'b, 'upper>(v: bool) + | -- ------ lifetime `'upper` defined here + | | + | lifetime `'b` defined here +... +LL | let _: &'upper () = match v { + | ^^^^^^^^^^ type annotation requires that `'b` must outlive `'upper` + | + = help: consider adding the following bound: `'b: 'upper` + +help: the following changes may resolve your lifetime errors + | + = help: add bound `'a: 'upper` + = help: add bound `'b: 'upper` + +error: lifetime may not live long enough + --> $DIR/empty-binders-err.rs:35:12 + | +LL | fn contra_fn<'a, 'b, 'lower>(v: bool) + | -- ------ lifetime `'lower` defined here + | | + | lifetime `'a` defined here +... +LL | let _: fn(&'lower ()) = match v { + | ^^^^^^^^^^^^^^ type annotation requires that `'lower` must outlive `'a` + | + = help: consider adding the following bound: `'lower: 'a` + +error: lifetime may not live long enough + --> $DIR/empty-binders-err.rs:48:12 + | +LL | fn contra_struct<'a, 'b, 'lower>(v: bool) + | -- ------ lifetime `'lower` defined here + | | + | lifetime `'a` defined here +... +LL | let _: Contra<'lower> = match v { + | ^^^^^^^^^^^^^^ type annotation requires that `'lower` must outlive `'a` + | + = help: consider adding the following bound: `'lower: 'a` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lub-glb/empty-binders.rs b/tests/ui/lub-glb/empty-binders.rs new file mode 100644 index 000000000..f9d07e79f --- /dev/null +++ b/tests/ui/lub-glb/empty-binders.rs @@ -0,0 +1,45 @@ +// check-pass +// +// Check that computing the lub works even for empty binders. +fn lt<'a: 'a>() -> &'a () { + &() +} + +fn lt_in_fn<'a: 'a>() -> fn(&'a ()) { + |_| () +} + +struct Contra<'a>(fn(&'a ())); +fn lt_in_contra<'a: 'a>() -> Contra<'a> { + Contra(|_| ()) +} + +fn ok<'a, 'b, 'upper, 'lower>(v: bool) +where + 'upper: 'a, + 'upper: 'b, + 'a: 'lower, + 'b: 'lower, + +{ + let _: &'lower () = match v { + true => lt::<'a>(), + false => lt::<'b>(), + }; + + // This errored in the past because LUB and GLB always + // bailed out when encountering binders, even if they were + // empty. + let _: fn(&'upper ()) = match v { + true => lt_in_fn::<'a>(), + false => lt_in_fn::<'b>(), + }; + + // This was already accepted, as relate didn't encounter any binders. + let _: Contra<'upper> = match v { + true => lt_in_contra::<'a>(), + false => lt_in_contra::<'b>(), + }; +} + +fn main() {} diff --git a/tests/ui/lub-glb/old-lub-glb-hr-eq.rs b/tests/ui/lub-glb/old-lub-glb-hr-eq.rs new file mode 100644 index 000000000..fbf4aee02 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-eq.rs @@ -0,0 +1,27 @@ +// Test that we give a note when the old LUB/GLB algorithm would have +// succeeded but the new code (which requires equality) gives an +// error. However, now that we handle subtyping correctly, we no +// longer get an error, because we recognize these two types as +// equivalent! +// +// check-pass + +fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { + // The two types above are actually equivalent. With the older + // leak check, though, we didn't consider them as equivalent, and + // hence we gave errors. But now we've fixed that. + let z = match 22 { + 0 => x, + _ => y, + }; +} + +fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) { + let z = match 22 { + // No error with an explicit cast: + 0 => x as for<'a> fn(&'a u8, &'a u8), + _ => y, + }; +} + +fn main() {} diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr new file mode 100644 index 000000000..4448f9326 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.baseleak.stderr @@ -0,0 +1,21 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq1.rs:17:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => x, + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` +LL | | _ => y, + | | ^ one type is more general than the other +LL | | +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr new file mode 100644 index 000000000..0d6131135 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/old-lub-glb-hr-noteq1.rs:17:14 + | +LL | _ => y, + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr new file mode 100644 index 000000000..dd0fdf3a1 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr @@ -0,0 +1,20 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq1.rs:14:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => x, + | | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` +LL | | _ => y, + | | ^ one type is more general than the other +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr new file mode 100644 index 000000000..cb046d0b0 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/old-lub-glb-hr-noteq1.rs:14:14 + | +LL | _ => y, + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.rs b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.rs new file mode 100644 index 000000000..589119abb --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.rs @@ -0,0 +1,29 @@ +// Test taking the LUB of two function types that are not equatable but where one is more +// general than the other. Test the case where the more general type (`x`) is the first +// match arm specifically. + +// revisions: leak noleak +//[noleak] compile-flags:-Zno-leak-check + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => x, + _ => y, + //[leak]~^ ERROR `match` arms have incompatible types + //[noleak]~^^ ERROR mismatched types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr new file mode 100644 index 000000000..e54fcf068 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr @@ -0,0 +1,19 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/old-lub-glb-hr-noteq2.rs:25:14 + | +LL | let z = match 22 { + | _____________- +LL | | 0 => y, + | | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8` +LL | | _ => x, + | | ^ one type is more general than the other +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.rs new file mode 100644 index 000000000..9940c40da --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.rs @@ -0,0 +1,39 @@ +// Test taking the LUB of two function types that are not equatable but where +// one is more general than the other. Test the case where the more general type +// (`x`) is the second match arm specifically. +// +// FIXME(#73154) Pure NLL checker without leak check accepts this test. +// (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens +// is that, due to the ordering of the match arms, we pick the correct "more +// general" fn type, and we ignore the errors from the non-NLL type checker that +// requires equality. The NLL type checker only requires a subtyping +// relationship, and that holds. To unblock landing NLL - and ensure that we can +// choose to make this always in error in the future - we perform the leak check +// after coercing a function pointer. + +// revisions: leak noleak +//[noleak] compile-flags: -Zno-leak-check + +//[noleak] check-pass + +fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // The two types above are not equivalent. With the older LUB/GLB + // algorithm, this may have worked (I don't remember), but now it + // doesn't because we require equality. + let z = match 22 { + 0 => y, + _ => x, + //[leak]~^ ERROR `match` arms have incompatible types + }; +} + +fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) { + // But we can *upcast* explicitly the type of `x` and figure + // things out: + let z = match 22 { + 0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8, + _ => y, + }; +} + +fn main() {} diff --git a/tests/ui/lub-glb/old-lub-glb-object.rs b/tests/ui/lub-glb/old-lub-glb-object.rs new file mode 100644 index 000000000..b6ead9c68 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-object.rs @@ -0,0 +1,23 @@ +// Test that we give a note when the old LUB/GLB algorithm would have +// succeeded but the new code (which is stricter) gives an error. + +trait Foo {} + +fn foo(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { + let z = match 22 { + 0 => x, + _ => y, + //~^ ERROR mismatched types + //~| ERROR mismatched types + }; +} + +fn bar(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { + // Accepted with explicit case: + let z = match 22 { + 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, + _ => y, + }; +} + +fn main() {} diff --git a/tests/ui/lub-glb/old-lub-glb-object.stderr b/tests/ui/lub-glb/old-lub-glb-object.stderr new file mode 100644 index 000000000..3d0c171e0 --- /dev/null +++ b/tests/ui/lub-glb/old-lub-glb-object.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:9:14 + | +LL | _ => y, + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` + +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:9:14 + | +LL | _ => y, + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macro-quote-test.rs b/tests/ui/macro-quote-test.rs new file mode 100644 index 000000000..2ba61acad --- /dev/null +++ b/tests/ui/macro-quote-test.rs @@ -0,0 +1,10 @@ +// Test that a macro can emit delimiters with nothing inside - `()`, `{}` + +// run-pass +// aux-build:hello_macro.rs + +extern crate hello_macro; + +fn main() { + hello_macro::hello!(); +} diff --git a/tests/ui/macro_backtrace/auxiliary/ping.rs b/tests/ui/macro_backtrace/auxiliary/ping.rs new file mode 100644 index 000000000..25b9efbc9 --- /dev/null +++ b/tests/ui/macro_backtrace/auxiliary/ping.rs @@ -0,0 +1,30 @@ +// Test that the macro backtrace facility works (supporting file) + +// a non-local macro +#[macro_export] +macro_rules! ping { + () => { + pong!(); + } +} + +#[macro_export] +macro_rules! deep { + () => { + foo!(); + } +} + +#[macro_export] +macro_rules! foo { + () => { + bar!(); + } +} + +#[macro_export] +macro_rules! bar { + () => { + ping!(); + } +} diff --git a/tests/ui/macro_backtrace/main.-Zmacro-backtrace.stderr b/tests/ui/macro_backtrace/main.-Zmacro-backtrace.stderr new file mode 100644 index 000000000..bf85a2d75 --- /dev/null +++ b/tests/ui/macro_backtrace/main.-Zmacro-backtrace.stderr @@ -0,0 +1,72 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` + --> $DIR/main.rs:10:20 + | +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- in this expansion of `pong!` +... +LL | pong!(); + | ------- in this macro invocation + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` + --> $DIR/main.rs:10:20 + | +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- in this expansion of `pong!` (#2) +... +LL | ping!(); + | ------- in this macro invocation (#1) + | + ::: $DIR/auxiliary/ping.rs:5:1 + | +LL | macro_rules! ping { + | ----------------- in this expansion of `ping!` (#1) +LL | () => { +LL | pong!(); + | ------- in this macro invocation (#2) + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` + --> $DIR/main.rs:10:20 + | +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- in this expansion of `pong!` (#5) +... +LL | deep!(); + | ------- in this macro invocation (#1) + | + ::: $DIR/auxiliary/ping.rs:5:1 + | +LL | macro_rules! ping { + | ----------------- in this expansion of `ping!` (#4) +LL | () => { +LL | pong!(); + | ------- in this macro invocation (#5) +... +LL | macro_rules! deep { + | ----------------- in this expansion of `deep!` (#1) +LL | () => { +LL | foo!(); + | ------ in this macro invocation (#2) +... +LL | macro_rules! foo { + | ---------------- in this expansion of `foo!` (#2) +LL | () => { +LL | bar!(); + | ------ in this macro invocation (#3) +... +LL | macro_rules! bar { + | ---------------- in this expansion of `bar!` (#3) +LL | () => { +LL | ping!(); + | ------- in this macro invocation (#4) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macro_backtrace/main.default.stderr b/tests/ui/macro_backtrace/main.default.stderr new file mode 100644 index 000000000..9ed4b3525 --- /dev/null +++ b/tests/ui/macro_backtrace/main.default.stderr @@ -0,0 +1,35 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` + --> $DIR/main.rs:10:20 + | +LL | () => { syntax error }; + | ^^^^^ expected one of 8 possible tokens +... +LL | pong!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `pong` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` + --> $DIR/main.rs:10:20 + | +LL | () => { syntax error }; + | ^^^^^ expected one of 8 possible tokens +... +LL | ping!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `pong` which comes from the expansion of the macro `ping` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` + --> $DIR/main.rs:10:20 + | +LL | () => { syntax error }; + | ^^^^^ expected one of 8 possible tokens +... +LL | deep!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `pong` which comes from the expansion of the macro `deep` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macro_backtrace/main.rs b/tests/ui/macro_backtrace/main.rs new file mode 100644 index 000000000..6cee3b4cd --- /dev/null +++ b/tests/ui/macro_backtrace/main.rs @@ -0,0 +1,23 @@ +// Test that the macro backtrace facility works +// aux-build:ping.rs +// revisions: default -Zmacro-backtrace +//[-Zmacro-backtrace] compile-flags: -Z macro-backtrace + +#[macro_use] extern crate ping; + +// a local macro +macro_rules! pong { + () => { syntax error }; +} +//~^^ ERROR expected one of +//~| ERROR expected one of +//~| ERROR expected one of + +#[allow(non_camel_case_types)] +struct syntax; + +fn main() { + pong!(); + ping!(); + deep!(); +} diff --git a/tests/ui/macros/ambiguity-legacy-vs-modern.rs b/tests/ui/macros/ambiguity-legacy-vs-modern.rs new file mode 100644 index 000000000..216b9dd05 --- /dev/null +++ b/tests/ui/macros/ambiguity-legacy-vs-modern.rs @@ -0,0 +1,46 @@ +// Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules" +// is disambiguated to mitigate regressions from macro modularization. +// Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. + +#![feature(decl_macro)] + +fn same_unnamed_mod() { + macro m() { 0 } + + macro_rules! m { () => (()) } + + m!() // OK +} + +fn nested_unnamed_mod() { + macro m() { 0 } + + { + macro_rules! m { () => (()) } + + m!() // OK + } +} + +fn nested_unnamed_mod_fail() { + macro_rules! m { () => (()) } + + { + macro m() { 0 } + + m!() //~ ERROR `m` is ambiguous + } +} + +fn nexted_named_mod_fail() { + macro m() { 0 } + + #[macro_use] + mod inner { + macro_rules! m { () => (()) } + } + + m!() //~ ERROR `m` is ambiguous +} + +fn main() {} diff --git a/tests/ui/macros/ambiguity-legacy-vs-modern.stderr b/tests/ui/macros/ambiguity-legacy-vs-modern.stderr new file mode 100644 index 000000000..330aa6acf --- /dev/null +++ b/tests/ui/macros/ambiguity-legacy-vs-modern.stderr @@ -0,0 +1,39 @@ +error[E0659]: `m` is ambiguous + --> $DIR/ambiguity-legacy-vs-modern.rs:31:9 + | +LL | m!() + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module +note: `m` could refer to the macro defined here + --> $DIR/ambiguity-legacy-vs-modern.rs:26:5 + | +LL | macro_rules! m { () => (()) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `m` could also refer to the macro defined here + --> $DIR/ambiguity-legacy-vs-modern.rs:29:9 + | +LL | macro m() { 0 } + | ^^^^^^^^^^^^^^^ + +error[E0659]: `m` is ambiguous + --> $DIR/ambiguity-legacy-vs-modern.rs:43:5 + | +LL | m!() + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a `macro_rules` name and a non-`macro_rules` name from another module +note: `m` could refer to the macro defined here + --> $DIR/ambiguity-legacy-vs-modern.rs:40:9 + | +LL | macro_rules! m { () => (()) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `m` could also refer to the macro defined here + --> $DIR/ambiguity-legacy-vs-modern.rs:36:5 + | +LL | macro m() { 0 } + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/assert-as-macro.rs b/tests/ui/macros/assert-as-macro.rs new file mode 100644 index 000000000..23c054808 --- /dev/null +++ b/tests/ui/macros/assert-as-macro.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:assertion failed: 1 == 2 +// ignore-emscripten no processes + +fn main() { + assert!(1 == 2); +} diff --git a/tests/ui/macros/assert-eq-macro-msg.rs b/tests/ui/macros/assert-eq-macro-msg.rs new file mode 100644 index 000000000..accbd2d1e --- /dev/null +++ b/tests/ui/macros/assert-eq-macro-msg.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: `(left == right)` +// error-pattern: left: `2` +// error-pattern:right: `3`: 1 + 1 definitely should be 3' +// ignore-emscripten no processes + +fn main() { + assert_eq!(1 + 1, 3, "1 + 1 definitely should be 3"); +} diff --git a/tests/ui/macros/assert-eq-macro-panic.rs b/tests/ui/macros/assert-eq-macro-panic.rs new file mode 100644 index 000000000..5e505c30b --- /dev/null +++ b/tests/ui/macros/assert-eq-macro-panic.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:assertion failed: `(left == right)` +// error-pattern: left: `14` +// error-pattern:right: `15` +// ignore-emscripten no processes + +fn main() { + assert_eq!(14, 15); +} diff --git a/tests/ui/macros/assert-eq-macro-success.rs b/tests/ui/macros/assert-eq-macro-success.rs new file mode 100644 index 000000000..57858b348 --- /dev/null +++ b/tests/ui/macros/assert-eq-macro-success.rs @@ -0,0 +1,13 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Point { x : isize } + +pub fn main() { + assert_eq!(14,14); + assert_eq!("abc".to_string(),"abc".to_string()); + assert_eq!(Box::new(Point{x:34}),Box::new(Point{x:34})); + assert_eq!(&Point{x:34},&Point{x:34}); + assert_eq!(42, 42, "foo bar"); + assert_eq!(42, 42, "a {} c", "b"); + assert_eq!(42, 42, "{x}, {y}, {z}", x = 1, y = 2, z = 3); +} diff --git a/tests/ui/macros/assert-eq-macro-unsized.rs b/tests/ui/macros/assert-eq-macro-unsized.rs new file mode 100644 index 000000000..00823216b --- /dev/null +++ b/tests/ui/macros/assert-eq-macro-unsized.rs @@ -0,0 +1,4 @@ +// run-pass +pub fn main() { + assert_eq!([1, 2, 3][..], vec![1, 2, 3][..]); +} diff --git a/tests/ui/macros/assert-format-lazy.rs b/tests/ui/macros/assert-format-lazy.rs new file mode 100644 index 000000000..c7f05d763 --- /dev/null +++ b/tests/ui/macros/assert-format-lazy.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: -C debug_assertions=yes + +#[allow(unreachable_code)] +fn main() { + assert!(true, "Failed: {:?}", panic!("assert! evaluated format expressions")); + debug_assert!(true, "Failed: {:?}", panic!("debug_assert! evaluated format expressions")); + assert_eq!(1, 1, "Failed: {:?}", panic!("assert_eq! evaluated format expressions")); + debug_assert_eq!(1, 1, "Failed: {:?}", panic!("debug_assert_eq! evaluated format expressions")); + assert_ne!(1, 2, "Failed: {:?}", panic!("assert_ne! evaluated format expressions")); + debug_assert_ne!(1, 2, "Failed: {:?}", panic!("debug_assert_ne! evaluated format expressions")); +} diff --git a/tests/ui/macros/assert-macro-explicit.rs b/tests/ui/macros/assert-macro-explicit.rs new file mode 100644 index 000000000..578ef5632 --- /dev/null +++ b/tests/ui/macros/assert-macro-explicit.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: false' +// ignore-emscripten no processes + +fn main() { + assert!(false); +} diff --git a/tests/ui/macros/assert-macro-fmt.rs b/tests/ui/macros/assert-macro-fmt.rs new file mode 100644 index 000000000..b8d319d85 --- /dev/null +++ b/tests/ui/macros/assert-macro-fmt.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'test-assert-fmt 42 rust' +// ignore-emscripten no processes + +fn main() { + assert!(false, "test-assert-fmt {} {}", 42, "rust"); +} diff --git a/tests/ui/macros/assert-macro-owned.rs b/tests/ui/macros/assert-macro-owned.rs new file mode 100644 index 000000000..753675872 --- /dev/null +++ b/tests/ui/macros/assert-macro-owned.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'test-assert-owned' +// ignore-emscripten no processes + +#![allow(non_fmt_panics)] + +fn main() { + assert!(false, "test-assert-owned".to_string()); +} diff --git a/tests/ui/macros/assert-macro-static.rs b/tests/ui/macros/assert-macro-static.rs new file mode 100644 index 000000000..dc5274a7e --- /dev/null +++ b/tests/ui/macros/assert-macro-static.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'test-assert-static' +// ignore-emscripten no processes + +fn main() { + assert!(false, "test-assert-static"); +} diff --git a/tests/ui/macros/assert-matches-macro-msg.rs b/tests/ui/macros/assert-matches-macro-msg.rs new file mode 100644 index 000000000..fd8cd5a1a --- /dev/null +++ b/tests/ui/macros/assert-matches-macro-msg.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: `(left matches right)` +// error-pattern: left: `2` +// error-pattern:right: `3`: 1 + 1 definitely should be 3' +// ignore-emscripten no processes + +#![feature(assert_matches)] + +use std::assert_matches::assert_matches; + +fn main() { + assert_matches!(1 + 1, 3, "1 + 1 definitely should be 3"); +} diff --git a/tests/ui/macros/assert-ne-macro-msg.rs b/tests/ui/macros/assert-ne-macro-msg.rs new file mode 100644 index 000000000..fc0472b99 --- /dev/null +++ b/tests/ui/macros/assert-ne-macro-msg.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'assertion failed: `(left != right)` +// error-pattern: left: `2` +// error-pattern:right: `2`: 1 + 1 definitely should not be 2' +// ignore-emscripten no processes + +fn main() { + assert_ne!(1 + 1, 2, "1 + 1 definitely should not be 2"); +} diff --git a/tests/ui/macros/assert-ne-macro-panic.rs b/tests/ui/macros/assert-ne-macro-panic.rs new file mode 100644 index 000000000..4f507d7b5 --- /dev/null +++ b/tests/ui/macros/assert-ne-macro-panic.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:assertion failed: `(left != right)` +// error-pattern: left: `14` +// error-pattern:right: `14` +// ignore-emscripten no processes + +fn main() { + assert_ne!(14, 14); +} diff --git a/tests/ui/macros/assert-ne-macro-success.rs b/tests/ui/macros/assert-ne-macro-success.rs new file mode 100644 index 000000000..89b3a4c9d --- /dev/null +++ b/tests/ui/macros/assert-ne-macro-success.rs @@ -0,0 +1,13 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Point { x : isize } + +pub fn main() { + assert_ne!(666,14); + assert_ne!("666".to_string(),"abc".to_string()); + assert_ne!(Box::new(Point{x:666}),Box::new(Point{x:34})); + assert_ne!(&Point{x:666},&Point{x:34}); + assert_ne!(666, 42, "no gods no masters"); + assert_ne!(666, 42, "6 {} 6", "6"); + assert_ne!(666, 42, "{x}, {y}, {z}", x = 6, y = 6, z = 6); +} diff --git a/tests/ui/macros/assert-ne-macro-unsized.rs b/tests/ui/macros/assert-ne-macro-unsized.rs new file mode 100644 index 000000000..e8a86e3da --- /dev/null +++ b/tests/ui/macros/assert-ne-macro-unsized.rs @@ -0,0 +1,4 @@ +// run-pass +pub fn main() { + assert_ne!([6, 6, 6][..], vec![1, 2, 3][..]); +} diff --git a/tests/ui/macros/assert-trailing-junk.rs b/tests/ui/macros/assert-trailing-junk.rs new file mode 100644 index 000000000..da725e19e --- /dev/null +++ b/tests/ui/macros/assert-trailing-junk.rs @@ -0,0 +1,27 @@ +// revisions: with-generic-asset without-generic-asset +// [with-generic-asset] compile-flags: --cfg feature="generic_assert" + +// Ensure assert macro does not ignore trailing garbage. +// +// See https://github.com/rust-lang/rust/issues/60024 for details. + +fn main() { + assert!(true some extra junk, "whatever"); + //~^ ERROR expected one of + + assert!(true some extra junk); + //~^ ERROR expected one of + + assert!(true, "whatever" blah); + //~^ ERROR no rules expected + + assert!(true "whatever" blah); + //~^ ERROR unexpected string literal + //~^^ ERROR no rules expected + + assert!(true;); + //~^ ERROR macro requires an expression + + assert!(false || true "error message"); + //~^ ERROR unexpected string literal +} diff --git a/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr b/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr new file mode 100644 index 000000000..1e73320e4 --- /dev/null +++ b/tests/ui/macros/assert-trailing-junk.with-generic-asset.stderr @@ -0,0 +1,58 @@ +error: expected one of `,`, `.`, `?`, or an operator, found `some` + --> $DIR/assert-trailing-junk.rs:9:18 + | +LL | assert!(true some extra junk, "whatever"); + | ^^^^ expected one of `,`, `.`, `?`, or an operator + +error: expected one of `,`, `.`, `?`, or an operator, found `some` + --> $DIR/assert-trailing-junk.rs:12:18 + | +LL | assert!(true some extra junk); + | ^^^^ expected one of `,`, `.`, `?`, or an operator + +error: no rules expected the token `blah` + --> $DIR/assert-trailing-junk.rs:15:30 + | +LL | assert!(true, "whatever" blah); + | -^^^^ no rules expected this token in macro call + | | + | help: missing comma here + | + = note: while trying to match sequence start + +error: unexpected string literal + --> $DIR/assert-trailing-junk.rs:18:18 + | +LL | assert!(true "whatever" blah); + | -^^^^^^^^^^ + | | + | help: try adding a comma + +error: no rules expected the token `blah` + --> $DIR/assert-trailing-junk.rs:18:29 + | +LL | assert!(true "whatever" blah); + | -^^^^ no rules expected this token in macro call + | | + | help: missing comma here + | + = note: while trying to match sequence start + +error: macro requires an expression as an argument + --> $DIR/assert-trailing-junk.rs:22:5 + | +LL | assert!(true;); + | ^^^^^^^^^^^^-^ + | | + | help: try removing semicolon + +error: unexpected string literal + --> $DIR/assert-trailing-junk.rs:25:27 + | +LL | assert!(false || true "error message"); + | -^^^^^^^^^^^^^^^ + | | + | help: try adding a comma + +error: aborting due to 7 previous errors + diff --git a/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr b/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr new file mode 100644 index 000000000..1e73320e4 --- /dev/null +++ b/tests/ui/macros/assert-trailing-junk.without-generic-asset.stderr @@ -0,0 +1,58 @@ +error: expected one of `,`, `.`, `?`, or an operator, found `some` + --> $DIR/assert-trailing-junk.rs:9:18 + | +LL | assert!(true some extra junk, "whatever"); + | ^^^^ expected one of `,`, `.`, `?`, or an operator + +error: expected one of `,`, `.`, `?`, or an operator, found `some` + --> $DIR/assert-trailing-junk.rs:12:18 + | +LL | assert!(true some extra junk); + | ^^^^ expected one of `,`, `.`, `?`, or an operator + +error: no rules expected the token `blah` + --> $DIR/assert-trailing-junk.rs:15:30 + | +LL | assert!(true, "whatever" blah); + | -^^^^ no rules expected this token in macro call + | | + | help: missing comma here + | + = note: while trying to match sequence start + +error: unexpected string literal + --> $DIR/assert-trailing-junk.rs:18:18 + | +LL | assert!(true "whatever" blah); + | -^^^^^^^^^^ + | | + | help: try adding a comma + +error: no rules expected the token `blah` + --> $DIR/assert-trailing-junk.rs:18:29 + | +LL | assert!(true "whatever" blah); + | -^^^^ no rules expected this token in macro call + | | + | help: missing comma here + | + = note: while trying to match sequence start + +error: macro requires an expression as an argument + --> $DIR/assert-trailing-junk.rs:22:5 + | +LL | assert!(true;); + | ^^^^^^^^^^^^-^ + | | + | help: try removing semicolon + +error: unexpected string literal + --> $DIR/assert-trailing-junk.rs:25:27 + | +LL | assert!(false || true "error message"); + | -^^^^^^^^^^^^^^^ + | | + | help: try adding a comma + +error: aborting due to 7 previous errors + diff --git a/tests/ui/macros/assert.rs b/tests/ui/macros/assert.rs new file mode 100644 index 000000000..a314db907 --- /dev/null +++ b/tests/ui/macros/assert.rs @@ -0,0 +1,9 @@ +// revisions: with-generic-asset without-generic-asset +// [with-generic-asset] compile-flags: --cfg feature="generic_assert" + +fn main() { + assert!(); //~ ERROR requires a boolean expression + assert!(struct); //~ ERROR expected expression + debug_assert!(); //~ ERROR requires a boolean expression + debug_assert!(struct); //~ ERROR expected expression +} diff --git a/tests/ui/macros/assert.with-generic-asset.stderr b/tests/ui/macros/assert.with-generic-asset.stderr new file mode 100644 index 000000000..51d8f28a3 --- /dev/null +++ b/tests/ui/macros/assert.with-generic-asset.stderr @@ -0,0 +1,28 @@ +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:5:5 + | +LL | assert!(); + | ^^^^^^^^^ boolean expression required + +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:6:13 + | +LL | assert!(struct); + | ^^^^^^ expected expression + +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:7:5 + | +LL | debug_assert!(); + | ^^^^^^^^^^^^^^^ boolean expression required + | + = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:8:19 + | +LL | debug_assert!(struct); + | ^^^^^^ expected expression + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/assert.without-generic-asset.stderr b/tests/ui/macros/assert.without-generic-asset.stderr new file mode 100644 index 000000000..51d8f28a3 --- /dev/null +++ b/tests/ui/macros/assert.without-generic-asset.stderr @@ -0,0 +1,28 @@ +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:5:5 + | +LL | assert!(); + | ^^^^^^^^^ boolean expression required + +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:6:13 + | +LL | assert!(struct); + | ^^^^^^ expected expression + +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:7:5 + | +LL | debug_assert!(); + | ^^^^^^^^^^^^^^^ boolean expression required + | + = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:8:19 + | +LL | debug_assert!(struct); + | ^^^^^^ expected expression + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/attr-empty-expr.rs b/tests/ui/macros/attr-empty-expr.rs new file mode 100644 index 000000000..d4d1a3ee7 --- /dev/null +++ b/tests/ui/macros/attr-empty-expr.rs @@ -0,0 +1,11 @@ +// AST-based macro attributes expanding to an empty expression produce an error and not ICE. + +#![feature(custom_test_frameworks)] +#![feature(stmt_expr_attributes)] +#![feature(test)] + +fn main() { + let _ = #[test] 0; //~ ERROR removing an expression is not supported in this position + let _ = #[bench] 1; //~ ERROR removing an expression is not supported in this position + let _ = #[test_case] 2; //~ ERROR removing an expression is not supported in this position +} diff --git a/tests/ui/macros/attr-empty-expr.stderr b/tests/ui/macros/attr-empty-expr.stderr new file mode 100644 index 000000000..53721053b --- /dev/null +++ b/tests/ui/macros/attr-empty-expr.stderr @@ -0,0 +1,20 @@ +error: removing an expression is not supported in this position + --> $DIR/attr-empty-expr.rs:8:13 + | +LL | let _ = #[test] 0; + | ^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/attr-empty-expr.rs:9:13 + | +LL | let _ = #[bench] 1; + | ^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/attr-empty-expr.rs:10:13 + | +LL | let _ = #[test_case] 2; + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/attr-from-macro.rs b/tests/ui/macros/attr-from-macro.rs new file mode 100644 index 000000000..bb3a5c94d --- /dev/null +++ b/tests/ui/macros/attr-from-macro.rs @@ -0,0 +1,20 @@ +// aux-build:attr-from-macro.rs +// run-pass + +extern crate attr_from_macro; + +attr_from_macro::creator! { + struct Foo; + enum Bar; + enum FooBar; +} + +fn main() { + // Checking the `repr(u32)` on the enum. + assert_eq!(4, std::mem::size_of::()); + // Checking the `repr(u16)` on the enum. + assert_eq!(2, std::mem::size_of::()); + + // Checking the Debug impl on the types. + eprintln!("{:?} {:?} {:?}", Foo, Bar::A, FooBar::A); +} diff --git a/tests/ui/macros/auxiliary/attr-from-macro.rs b/tests/ui/macros/auxiliary/attr-from-macro.rs new file mode 100644 index 000000000..9b388675c --- /dev/null +++ b/tests/ui/macros/auxiliary/attr-from-macro.rs @@ -0,0 +1,15 @@ +#[macro_export] +macro_rules! creator { + (struct $name1:ident; enum $name2:ident; enum $name3:ident;) => { + #[derive(Debug)] + pub struct $name1; + + #[derive(Debug)] + #[repr(u32)] + pub enum $name2 { A } + + #[derive(Debug)] + #[repr(u16)] + pub enum $name3 { A } + } +} diff --git a/tests/ui/macros/auxiliary/define-macro.rs b/tests/ui/macros/auxiliary/define-macro.rs new file mode 100644 index 000000000..4956907c5 --- /dev/null +++ b/tests/ui/macros/auxiliary/define-macro.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! define_macro { + ($i:ident) => { + macro_rules! $i { () => {} } + } +} diff --git a/tests/ui/macros/auxiliary/deprecated-macros.rs b/tests/ui/macros/auxiliary/deprecated-macros.rs new file mode 100644 index 000000000..657a7252a --- /dev/null +++ b/tests/ui/macros/auxiliary/deprecated-macros.rs @@ -0,0 +1,3 @@ +#[deprecated(since = "1.0.0", note = "deprecation note")] +#[macro_export] +macro_rules! deprecated_macro{ () => () } diff --git a/tests/ui/macros/auxiliary/dollar-crate-nested-encoding.rs b/tests/ui/macros/auxiliary/dollar-crate-nested-encoding.rs new file mode 100644 index 000000000..bbe6a48c5 --- /dev/null +++ b/tests/ui/macros/auxiliary/dollar-crate-nested-encoding.rs @@ -0,0 +1,10 @@ +pub type S = u8; + +macro_rules! generate_exported { () => { + #[macro_export] + macro_rules! exported { + () => ($crate::S) + } +}} + +generate_exported!(); diff --git a/tests/ui/macros/auxiliary/foreign-crate-macro-pat.rs b/tests/ui/macros/auxiliary/foreign-crate-macro-pat.rs new file mode 100644 index 000000000..26d4c96d5 --- /dev/null +++ b/tests/ui/macros/auxiliary/foreign-crate-macro-pat.rs @@ -0,0 +1,11 @@ +// edition:2018 + +#[macro_export] +macro_rules! custom_matches { + ($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => { + match $expression { + $( $pattern )|+ $( if $guard )? => true, + _ => false + } + } +} diff --git a/tests/ui/macros/auxiliary/issue-100199.rs b/tests/ui/macros/auxiliary/issue-100199.rs new file mode 100644 index 000000000..9e190b542 --- /dev/null +++ b/tests/ui/macros/auxiliary/issue-100199.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, Ident, Span, TokenStream, TokenTree}; + +#[proc_macro_attribute] +pub fn struct_with_bound(_: TokenStream, _: TokenStream) -> TokenStream { + let crate_ident = TokenTree::Ident(Ident::new("crate", Span::call_site())); + let trait_ident = TokenTree::Ident(Ident::new("MyTrait", Span::call_site())); + quote!( + struct Foo {} + ) +} diff --git a/tests/ui/macros/auxiliary/issue-19163.rs b/tests/ui/macros/auxiliary/issue-19163.rs new file mode 100644 index 000000000..0c0d9e43c --- /dev/null +++ b/tests/ui/macros/auxiliary/issue-19163.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +#[macro_export] +macro_rules! mywrite { + ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*))) +} diff --git a/tests/ui/macros/auxiliary/issue-40469.rs b/tests/ui/macros/auxiliary/issue-40469.rs new file mode 100644 index 000000000..4f2f41f2c --- /dev/null +++ b/tests/ui/macros/auxiliary/issue-40469.rs @@ -0,0 +1 @@ +macro_rules! m { () => { $crate::main(); } } diff --git a/tests/ui/macros/auxiliary/issue-75982.rs b/tests/ui/macros/auxiliary/issue-75982.rs new file mode 100644 index 000000000..1e1a6126a --- /dev/null +++ b/tests/ui/macros/auxiliary/issue-75982.rs @@ -0,0 +1,12 @@ +const _: () = { + #[macro_export] + macro_rules! first_macro { + () => {} + } + mod foo { + #[macro_export] + macro_rules! second_macro { + () => {} + } + } +}; diff --git a/tests/ui/macros/auxiliary/macro-comma-support.rs b/tests/ui/macros/auxiliary/macro-comma-support.rs new file mode 100644 index 000000000..6a452c185 --- /dev/null +++ b/tests/ui/macros/auxiliary/macro-comma-support.rs @@ -0,0 +1 @@ +() diff --git a/tests/ui/macros/auxiliary/macro-def-site-super.rs b/tests/ui/macros/auxiliary/macro-def-site-super.rs new file mode 100644 index 000000000..cab747c2c --- /dev/null +++ b/tests/ui/macros/auxiliary/macro-def-site-super.rs @@ -0,0 +1,13 @@ +#![feature(decl_macro)] + +mod inner1 { + pub struct Struct {} + + pub mod inner2 { + pub macro mac() { + super::Struct + } + } +} + +pub use inner1::inner2 as public; diff --git a/tests/ui/macros/auxiliary/macro-in-other-crate.rs b/tests/ui/macros/auxiliary/macro-in-other-crate.rs new file mode 100644 index 000000000..db8e92018 --- /dev/null +++ b/tests/ui/macros/auxiliary/macro-in-other-crate.rs @@ -0,0 +1,14 @@ +#[macro_export] +macro_rules! mac { + ($ident:ident) => { let $ident = 42; } +} + +#[macro_export] +macro_rules! inline { + () => () +} + +#[macro_export] +macro_rules! from_prelude { + () => () +} diff --git a/tests/ui/macros/auxiliary/macro-include-items-expr.rs b/tests/ui/macros/auxiliary/macro-include-items-expr.rs new file mode 100644 index 000000000..7394f194b --- /dev/null +++ b/tests/ui/macros/auxiliary/macro-include-items-expr.rs @@ -0,0 +1,3 @@ +// ignore-test: this is not a test + +1 diff --git a/tests/ui/macros/auxiliary/macro-include-items-item.rs b/tests/ui/macros/auxiliary/macro-include-items-item.rs new file mode 100644 index 000000000..7d54745e0 --- /dev/null +++ b/tests/ui/macros/auxiliary/macro-include-items-item.rs @@ -0,0 +1,3 @@ +// ignore-test: this is not a test + +fn foo() { bar() } diff --git a/tests/ui/macros/auxiliary/macro_crate_def_only.rs b/tests/ui/macros/auxiliary/macro_crate_def_only.rs new file mode 100644 index 000000000..c267eefde --- /dev/null +++ b/tests/ui/macros/auxiliary/macro_crate_def_only.rs @@ -0,0 +1,4 @@ +#[macro_export] +macro_rules! make_a_5 { + () => (5) +} diff --git a/tests/ui/macros/auxiliary/macro_crate_nonterminal.rs b/tests/ui/macros/auxiliary/macro_crate_nonterminal.rs new file mode 100644 index 000000000..2e2440462 --- /dev/null +++ b/tests/ui/macros/auxiliary/macro_crate_nonterminal.rs @@ -0,0 +1,12 @@ +pub fn increment(x: usize) -> usize { + x + 1 +} + +#[macro_export] +macro_rules! increment { + ($x:expr) => ($crate::increment($x)) +} + +pub fn check_local() { + assert_eq!(increment!(3), 4); +} diff --git a/tests/ui/macros/auxiliary/macro_export_inner_module.rs b/tests/ui/macros/auxiliary/macro_export_inner_module.rs new file mode 100644 index 000000000..d71af9ee6 --- /dev/null +++ b/tests/ui/macros/auxiliary/macro_export_inner_module.rs @@ -0,0 +1,6 @@ +pub mod inner { + #[macro_export] + macro_rules! foo { + () => (1) + } +} diff --git a/tests/ui/macros/auxiliary/macro_with_super_1.rs b/tests/ui/macros/auxiliary/macro_with_super_1.rs new file mode 100644 index 000000000..b015500df --- /dev/null +++ b/tests/ui/macros/auxiliary/macro_with_super_1.rs @@ -0,0 +1,16 @@ +#![crate_type = "lib"] + +#[macro_export] +macro_rules! declare { + () => ( + pub fn aaa() {} + + pub mod bbb { + use super::aaa; + + pub fn ccc() { + aaa(); + } + } + ) +} diff --git a/tests/ui/macros/auxiliary/or-pattern.rs b/tests/ui/macros/auxiliary/or-pattern.rs new file mode 100644 index 000000000..a319c405e --- /dev/null +++ b/tests/ui/macros/auxiliary/or-pattern.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] + +#[macro_export] +macro_rules! a { + ($x:pat|) => (); +} diff --git a/tests/ui/macros/auxiliary/proc_macro_def.rs b/tests/ui/macros/auxiliary/proc_macro_def.rs new file mode 100644 index 000000000..0497e4ae0 --- /dev/null +++ b/tests/ui/macros/auxiliary/proc_macro_def.rs @@ -0,0 +1,35 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn attr_tru(_attr: TokenStream, item: TokenStream) -> TokenStream { + let name = item.into_iter().nth(1).unwrap(); + quote!(fn $name() -> bool { true }) +} + +#[proc_macro_attribute] +pub fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream { + quote!($item) +} + +#[proc_macro] +pub fn tru(_ts: TokenStream) -> TokenStream { + quote!(true) +} + +#[proc_macro] +pub fn ret_tru(_ts: TokenStream) -> TokenStream { + quote!(return true;) +} + +#[proc_macro] +pub fn identity(ts: TokenStream) -> TokenStream { + quote!($ts) +} diff --git a/tests/ui/macros/auxiliary/proc_macro_sequence.rs b/tests/ui/macros/auxiliary/proc_macro_sequence.rs new file mode 100644 index 000000000..1331480d8 --- /dev/null +++ b/tests/ui/macros/auxiliary/proc_macro_sequence.rs @@ -0,0 +1,27 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span, proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, Span, TokenStream, TokenTree}; + +fn assert_same_span(a: Span, b: Span) { + assert_eq!(a.start(), b.start()); + assert_eq!(a.end(), b.end()); +} + +// This macro generates a macro with the same macro definition as `manual_foo` in +// `same-sequence-span.rs` but with the same span for all sequences. +#[proc_macro] +pub fn make_foo(_: TokenStream) -> TokenStream { + let result = quote! { + macro_rules! generated_foo { + (1 $$x:expr $$($$y:tt,)* $$(= $$z:tt)*) => {}; + } + }; + + result +} diff --git a/tests/ui/macros/auxiliary/two_macros-rpass.rs b/tests/ui/macros/auxiliary/two_macros-rpass.rs new file mode 100644 index 000000000..441a978dd --- /dev/null +++ b/tests/ui/macros/auxiliary/two_macros-rpass.rs @@ -0,0 +1,5 @@ +#[macro_export] +macro_rules! macro_one { ($($t:tt)*) => ($($t)*) } + +#[macro_export] +macro_rules! macro_two { ($($t:tt)*) => ($($t)*) } diff --git a/tests/ui/macros/auxiliary/two_macros.rs b/tests/ui/macros/auxiliary/two_macros.rs new file mode 100644 index 000000000..2330c75c8 --- /dev/null +++ b/tests/ui/macros/auxiliary/two_macros.rs @@ -0,0 +1,5 @@ +#[macro_export] +macro_rules! macro_one { () => ("one") } + +#[macro_export] +macro_rules! macro_two { () => ("two") } diff --git a/tests/ui/macros/auxiliary/unstable-macros.rs b/tests/ui/macros/auxiliary/unstable-macros.rs new file mode 100644 index 000000000..3aadd4b0c --- /dev/null +++ b/tests/ui/macros/auxiliary/unstable-macros.rs @@ -0,0 +1,16 @@ +#![feature(decl_macro)] +#![feature(staged_api)] +#![stable(feature = "unit_test", since = "1.0.0")] + +#[unstable(feature = "unstable_macros", issue = "none")] +#[macro_export] +macro_rules! unstable_macro{ () => () } + +#[stable(feature = "deprecated_macros", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "deprecation note")] +#[macro_export] +macro_rules! deprecated_macro{ () => () } + +// FIXME: Cannot use a `pub` macro 2.0 in a staged API crate due to reachability issues. +// #[unstable(feature = "unstable_macros", issue = "none")] +// pub macro unstable_macro_modern() {} diff --git a/tests/ui/macros/auxiliary/use-macro-self.rs b/tests/ui/macros/auxiliary/use-macro-self.rs new file mode 100644 index 000000000..f1307411a --- /dev/null +++ b/tests/ui/macros/auxiliary/use-macro-self.rs @@ -0,0 +1,6 @@ +pub mod foobarius {} + +#[macro_export] +macro_rules! foobarius { + () => { () } +} diff --git a/tests/ui/macros/bad-concat.rs b/tests/ui/macros/bad-concat.rs new file mode 100644 index 000000000..263cd074d --- /dev/null +++ b/tests/ui/macros/bad-concat.rs @@ -0,0 +1,8 @@ +fn main() { + let x: u32 = 42; + let y: f64 = 3.14; + let z = "foo"; + let _ = concat!(x, y, z, "bar"); + //~^ ERROR expected a literal + //~| NOTE only literals +} diff --git a/tests/ui/macros/bad-concat.stderr b/tests/ui/macros/bad-concat.stderr new file mode 100644 index 000000000..4316fd312 --- /dev/null +++ b/tests/ui/macros/bad-concat.stderr @@ -0,0 +1,10 @@ +error: expected a literal + --> $DIR/bad-concat.rs:5:21 + | +LL | let _ = concat!(x, y, z, "bar"); + | ^ ^ ^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + +error: aborting due to previous error + diff --git a/tests/ui/macros/bad_hello.rs b/tests/ui/macros/bad_hello.rs new file mode 100644 index 000000000..aaa9e243a --- /dev/null +++ b/tests/ui/macros/bad_hello.rs @@ -0,0 +1,6 @@ +fn main() { + println!(3 + 4); + //~^ ERROR format argument must be a string literal + println!(3, 4); + //~^ ERROR format argument must be a string literal +} diff --git a/tests/ui/macros/bad_hello.stderr b/tests/ui/macros/bad_hello.stderr new file mode 100644 index 000000000..fc9bb82b7 --- /dev/null +++ b/tests/ui/macros/bad_hello.stderr @@ -0,0 +1,24 @@ +error: format argument must be a string literal + --> $DIR/bad_hello.rs:2:14 + | +LL | println!(3 + 4); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | println!("{}", 3 + 4); + | +++++ + +error: format argument must be a string literal + --> $DIR/bad_hello.rs:4:14 + | +LL | println!(3, 4); + | ^ + | +help: you might be missing a string literal to format with + | +LL | println!("{} {}", 3, 4); + | ++++++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/bang-after-name.fixed b/tests/ui/macros/bang-after-name.fixed new file mode 100644 index 000000000..c107ddd5d --- /dev/null +++ b/tests/ui/macros/bang-after-name.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_macros)] + +macro_rules! foo { //~ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/tests/ui/macros/bang-after-name.rs b/tests/ui/macros/bang-after-name.rs new file mode 100644 index 000000000..7654d8c44 --- /dev/null +++ b/tests/ui/macros/bang-after-name.rs @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_macros)] + +macro_rules! foo! { //~ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/tests/ui/macros/bang-after-name.stderr b/tests/ui/macros/bang-after-name.stderr new file mode 100644 index 000000000..f609c4943 --- /dev/null +++ b/tests/ui/macros/bang-after-name.stderr @@ -0,0 +1,8 @@ +error: macro names aren't followed by a `!` + --> $DIR/bang-after-name.rs:4:17 + | +LL | macro_rules! foo! { + | ^ help: remove the `!` + +error: aborting due to previous error + diff --git a/tests/ui/macros/best-failure.rs b/tests/ui/macros/best-failure.rs new file mode 100644 index 000000000..bbdd465d5 --- /dev/null +++ b/tests/ui/macros/best-failure.rs @@ -0,0 +1,11 @@ +macro_rules! number { + (neg false, $self:ident) => { $self }; + ($signed:tt => $ty:ty;) => { + number!(neg $signed, $self); + //~^ ERROR no rules expected the token `$` + }; +} + +number! { false => u8; } + +fn main() {} diff --git a/tests/ui/macros/best-failure.stderr b/tests/ui/macros/best-failure.stderr new file mode 100644 index 000000000..a52fc5e3d --- /dev/null +++ b/tests/ui/macros/best-failure.stderr @@ -0,0 +1,21 @@ +error: no rules expected the token `$` + --> $DIR/best-failure.rs:4:30 + | +LL | macro_rules! number { + | ------------------- when calling this macro +... +LL | number!(neg $signed, $self); + | ^^^^^ no rules expected this token in macro call +... +LL | number! { false => u8; } + | ------------------------ in this macro invocation + | +note: while trying to match meta-variable `$self:ident` + --> $DIR/best-failure.rs:2:17 + | +LL | (neg false, $self:ident) => { $self }; + | ^^^^^^^^^^^ + = note: this error originates in the macro `number` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/builtin-prelude-no-accidents.rs b/tests/ui/macros/builtin-prelude-no-accidents.rs new file mode 100644 index 000000000..01691a82d --- /dev/null +++ b/tests/ui/macros/builtin-prelude-no-accidents.rs @@ -0,0 +1,8 @@ +// Names of public modules in libstd and libcore don't accidentally get into prelude +// because macros with the same names are in prelude. + +fn main() { + env::current_dir; //~ ERROR use of undeclared crate or module `env` + type A = panic::PanicInfo; //~ ERROR use of undeclared crate or module `panic` + type B = vec::Vec; //~ ERROR use of undeclared crate or module `vec` +} diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr new file mode 100644 index 000000000..56af618d4 --- /dev/null +++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `env` + --> $DIR/builtin-prelude-no-accidents.rs:5:5 + | +LL | env::current_dir; + | ^^^ use of undeclared crate or module `env` + +error[E0433]: failed to resolve: use of undeclared crate or module `panic` + --> $DIR/builtin-prelude-no-accidents.rs:6:14 + | +LL | type A = panic::PanicInfo; + | ^^^^^ use of undeclared crate or module `panic` + +error[E0433]: failed to resolve: use of undeclared crate or module `vec` + --> $DIR/builtin-prelude-no-accidents.rs:7:14 + | +LL | type B = vec::Vec; + | ^^^ use of undeclared crate or module `vec` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/builtin-std-paths-fail.rs b/tests/ui/macros/builtin-std-paths-fail.rs new file mode 100644 index 000000000..c1a4e32a6 --- /dev/null +++ b/tests/ui/macros/builtin-std-paths-fail.rs @@ -0,0 +1,25 @@ +#[derive( + core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core` + //~| ERROR could not find `RustcDecodable` in `core` + core::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `core` + //~| ERROR could not find `RustcDecodable` in `core` +)] +#[core::bench] //~ ERROR could not find `bench` in `core` +#[core::global_allocator] //~ ERROR could not find `global_allocator` in `core` +#[core::test_case] //~ ERROR could not find `test_case` in `core` +#[core::test] //~ ERROR could not find `test` in `core` +struct Core; + +#[derive( + std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std` + //~| ERROR could not find `RustcDecodable` in `std` + std::RustcDecodable, //~ ERROR could not find `RustcDecodable` in `std` + //~| ERROR could not find `RustcDecodable` in `std` +)] +#[std::bench] //~ ERROR could not find `bench` in `std` +#[std::global_allocator] //~ ERROR could not find `global_allocator` in `std` +#[std::test_case] //~ ERROR could not find `test_case` in `std` +#[std::test] //~ ERROR could not find `test` in `std` +struct Std; + +fn main() {} diff --git a/tests/ui/macros/builtin-std-paths-fail.stderr b/tests/ui/macros/builtin-std-paths-fail.stderr new file mode 100644 index 000000000..ba6261011 --- /dev/null +++ b/tests/ui/macros/builtin-std-paths-fail.stderr @@ -0,0 +1,99 @@ +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:2:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:4:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:2:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `core` + --> $DIR/builtin-std-paths-fail.rs:4:11 + | +LL | core::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `core` + +error[E0433]: failed to resolve: could not find `bench` in `core` + --> $DIR/builtin-std-paths-fail.rs:7:9 + | +LL | #[core::bench] + | ^^^^^ could not find `bench` in `core` + +error[E0433]: failed to resolve: could not find `global_allocator` in `core` + --> $DIR/builtin-std-paths-fail.rs:8:9 + | +LL | #[core::global_allocator] + | ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `core` + +error[E0433]: failed to resolve: could not find `test_case` in `core` + --> $DIR/builtin-std-paths-fail.rs:9:9 + | +LL | #[core::test_case] + | ^^^^^^^^^ could not find `test_case` in `core` + +error[E0433]: failed to resolve: could not find `test` in `core` + --> $DIR/builtin-std-paths-fail.rs:10:9 + | +LL | #[core::test] + | ^^^^ could not find `test` in `core` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:14:10 + | +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:16:10 + | +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:14:10 + | +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + +error[E0433]: failed to resolve: could not find `RustcDecodable` in `std` + --> $DIR/builtin-std-paths-fail.rs:16:10 + | +LL | std::RustcDecodable, + | ^^^^^^^^^^^^^^ could not find `RustcDecodable` in `std` + +error[E0433]: failed to resolve: could not find `bench` in `std` + --> $DIR/builtin-std-paths-fail.rs:19:8 + | +LL | #[std::bench] + | ^^^^^ could not find `bench` in `std` + +error[E0433]: failed to resolve: could not find `global_allocator` in `std` + --> $DIR/builtin-std-paths-fail.rs:20:8 + | +LL | #[std::global_allocator] + | ^^^^^^^^^^^^^^^^ could not find `global_allocator` in `std` + +error[E0433]: failed to resolve: could not find `test_case` in `std` + --> $DIR/builtin-std-paths-fail.rs:21:8 + | +LL | #[std::test_case] + | ^^^^^^^^^ could not find `test_case` in `std` + +error[E0433]: failed to resolve: could not find `test` in `std` + --> $DIR/builtin-std-paths-fail.rs:22:8 + | +LL | #[std::test] + | ^^^^ could not find `test` in `std` + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/builtin-std-paths.rs b/tests/ui/macros/builtin-std-paths.rs new file mode 100644 index 000000000..2083f9ba3 --- /dev/null +++ b/tests/ui/macros/builtin-std-paths.rs @@ -0,0 +1,32 @@ +// check-pass + +#[derive( + core::clone::Clone, + core::marker::Copy, + core::fmt::Debug, + core::default::Default, + core::cmp::Eq, + core::hash::Hash, + core::cmp::Ord, + core::cmp::PartialEq, + core::cmp::PartialOrd, +)] +struct Core; + +#[derive( + std::clone::Clone, + std::marker::Copy, + std::fmt::Debug, + std::default::Default, + std::cmp::Eq, + std::hash::Hash, + std::cmp::Ord, + std::cmp::PartialEq, + std::cmp::PartialOrd, +)] +struct Std; + +fn main() { + core::column!(); + std::column!(); +} diff --git a/tests/ui/macros/cfg.rs b/tests/ui/macros/cfg.rs new file mode 100644 index 000000000..2aac50a9d --- /dev/null +++ b/tests/ui/macros/cfg.rs @@ -0,0 +1,6 @@ +fn main() { + cfg!(); //~ ERROR macro requires a cfg-pattern + cfg!(123); //~ ERROR expected identifier + cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string + cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern +} diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr new file mode 100644 index 000000000..2633d5f72 --- /dev/null +++ b/tests/ui/macros/cfg.stderr @@ -0,0 +1,31 @@ +error: macro requires a cfg-pattern as an argument + --> $DIR/cfg.rs:2:5 + | +LL | cfg!(); + | ^^^^^^ cfg-pattern required + | + = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected identifier, found `123` + --> $DIR/cfg.rs:3:10 + | +LL | cfg!(123); + | ^^^ expected identifier + +error[E0565]: literal in `cfg` predicate value must be a string + --> $DIR/cfg.rs:4:16 + | +LL | cfg!(foo = 123); + | ^^^ + +error: expected 1 cfg-pattern + --> $DIR/cfg.rs:5:5 + | +LL | cfg!(foo, bar); + | ^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/macros/colorful-write-macros.rs b/tests/ui/macros/colorful-write-macros.rs new file mode 100644 index 000000000..eb1872cc7 --- /dev/null +++ b/tests/ui/macros/colorful-write-macros.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +use std::io::Write; +use std::fmt; + +struct Foo<'a> { + writer: &'a mut (dyn Write+'a), + other: &'a str, +} + +struct Bar; + +impl fmt::Write for Bar { + fn write_str(&mut self, _: &str) -> fmt::Result { + Ok(()) + } +} + +fn borrowing_writer_from_struct_and_formatting_struct_field(foo: Foo) { + write!(foo.writer, "{}", foo.other).unwrap(); +} + +fn main() { + let mut w = Vec::new(); + write!(&mut w as &mut dyn Write, "").unwrap(); + write!(&mut w, "").unwrap(); // should coerce + println!("ok"); + + let mut s = Bar; + { + use std::fmt::Write; + write!(&mut s, "test").unwrap(); + } +} diff --git a/tests/ui/macros/concat-bytes-error.rs b/tests/ui/macros/concat-bytes-error.rs new file mode 100644 index 000000000..db5d3cab0 --- /dev/null +++ b/tests/ui/macros/concat-bytes-error.rs @@ -0,0 +1,50 @@ +#![feature(concat_bytes)] + +fn main() { + concat_bytes!(pie); //~ ERROR expected a byte literal + concat_bytes!(pie, pie); //~ ERROR expected a byte literal + concat_bytes!("tnrsi", "tnri"); //~ ERROR cannot concatenate string literals + concat_bytes!(2.8); //~ ERROR cannot concatenate float literals + concat_bytes!(300); //~ ERROR cannot concatenate numeric literals + concat_bytes!('a'); //~ ERROR cannot concatenate character literals + concat_bytes!(true, false); //~ ERROR cannot concatenate boolean literals + concat_bytes!(42, b"va", b'l'); //~ ERROR cannot concatenate numeric literals + concat_bytes!(42, b"va", b'l', [1, 2]); //~ ERROR cannot concatenate numeric literals + concat_bytes!([ + "hi", //~ ERROR cannot concatenate string literals + ]); + concat_bytes!([ + 'a', //~ ERROR cannot concatenate character literals + ]); + concat_bytes!([ + true, //~ ERROR cannot concatenate boolean literals + ]); + concat_bytes!([ + false, //~ ERROR cannot concatenate boolean literals + ]); + concat_bytes!([ + 2.6, //~ ERROR cannot concatenate float literals + ]); + concat_bytes!([ + 265, //~ ERROR numeric literal is out of bounds + ]); + concat_bytes!([ + -33, //~ ERROR expected a byte literal + ]); + concat_bytes!([ + b"hi!", //~ ERROR cannot concatenate doubly nested array + ]); + concat_bytes!([ + [5, 6, 7], //~ ERROR cannot concatenate doubly nested array + ]); + concat_bytes!(5u16); //~ ERROR cannot concatenate numeric literals + concat_bytes!([5u16]); //~ ERROR numeric literal is not a `u8` + concat_bytes!([3; ()]); //~ ERROR repeat count is not a positive number + concat_bytes!([3; -2]); //~ ERROR repeat count is not a positive number + concat_bytes!([pie; -2]); //~ ERROR repeat count is not a positive number + concat_bytes!([pie; 2]); //~ ERROR expected a byte literal + concat_bytes!([2.2; 0]); //~ ERROR cannot concatenate float literals + concat_bytes!([5.5; ()]); //~ ERROR repeat count is not a positive number + concat_bytes!([[1, 2, 3]; 3]); //~ ERROR cannot concatenate doubly nested array + concat_bytes!([[42; 2]; 3]); //~ ERROR cannot concatenate doubly nested array +} diff --git a/tests/ui/macros/concat-bytes-error.stderr b/tests/ui/macros/concat-bytes-error.stderr new file mode 100644 index 000000000..d6cd1a3d1 --- /dev/null +++ b/tests/ui/macros/concat-bytes-error.stderr @@ -0,0 +1,181 @@ +error: expected a byte literal + --> $DIR/concat-bytes-error.rs:4:19 + | +LL | concat_bytes!(pie); + | ^^^ + | + = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()` + +error: expected a byte literal + --> $DIR/concat-bytes-error.rs:5:19 + | +LL | concat_bytes!(pie, pie); + | ^^^ ^^^ + | + = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()` + +error: cannot concatenate string literals + --> $DIR/concat-bytes-error.rs:6:19 + | +LL | concat_bytes!("tnrsi", "tnri"); + | ^^^^^^^ help: try using a byte string: `b"tnrsi"` + +error: cannot concatenate float literals + --> $DIR/concat-bytes-error.rs:7:19 + | +LL | concat_bytes!(2.8); + | ^^^ + +error: cannot concatenate numeric literals + --> $DIR/concat-bytes-error.rs:8:19 + | +LL | concat_bytes!(300); + | ^^^ help: try wrapping the number in an array: `[300]` + +error: cannot concatenate character literals + --> $DIR/concat-bytes-error.rs:9:19 + | +LL | concat_bytes!('a'); + | ^^^ help: try using a byte character: `b'a'` + +error: cannot concatenate boolean literals + --> $DIR/concat-bytes-error.rs:10:19 + | +LL | concat_bytes!(true, false); + | ^^^^ + +error: cannot concatenate numeric literals + --> $DIR/concat-bytes-error.rs:11:19 + | +LL | concat_bytes!(42, b"va", b'l'); + | ^^ help: try wrapping the number in an array: `[42]` + +error: cannot concatenate numeric literals + --> $DIR/concat-bytes-error.rs:12:19 + | +LL | concat_bytes!(42, b"va", b'l', [1, 2]); + | ^^ help: try wrapping the number in an array: `[42]` + +error: cannot concatenate string literals + --> $DIR/concat-bytes-error.rs:14:9 + | +LL | "hi", + | ^^^^ + +error: cannot concatenate character literals + --> $DIR/concat-bytes-error.rs:17:9 + | +LL | 'a', + | ^^^ help: try using a byte character: `b'a'` + +error: cannot concatenate boolean literals + --> $DIR/concat-bytes-error.rs:20:9 + | +LL | true, + | ^^^^ + +error: cannot concatenate boolean literals + --> $DIR/concat-bytes-error.rs:23:9 + | +LL | false, + | ^^^^^ + +error: cannot concatenate float literals + --> $DIR/concat-bytes-error.rs:26:9 + | +LL | 2.6, + | ^^^ + +error: numeric literal is out of bounds + --> $DIR/concat-bytes-error.rs:29:9 + | +LL | 265, + | ^^^ + +error: expected a byte literal + --> $DIR/concat-bytes-error.rs:32:9 + | +LL | -33, + | ^^^ + | + = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()` + +error: cannot concatenate doubly nested array + --> $DIR/concat-bytes-error.rs:35:9 + | +LL | b"hi!", + | ^^^^^^ + | + = note: byte strings are treated as arrays of bytes + = help: try flattening the array + +error: cannot concatenate doubly nested array + --> $DIR/concat-bytes-error.rs:38:9 + | +LL | [5, 6, 7], + | ^^^^^^^^^ + +error: cannot concatenate numeric literals + --> $DIR/concat-bytes-error.rs:40:19 + | +LL | concat_bytes!(5u16); + | ^^^^ help: try wrapping the number in an array: `[5u16]` + +error: numeric literal is not a `u8` + --> $DIR/concat-bytes-error.rs:41:20 + | +LL | concat_bytes!([5u16]); + | ^^^^ + +error: repeat count is not a positive number + --> $DIR/concat-bytes-error.rs:42:23 + | +LL | concat_bytes!([3; ()]); + | ^^ + +error: repeat count is not a positive number + --> $DIR/concat-bytes-error.rs:43:23 + | +LL | concat_bytes!([3; -2]); + | ^^ + +error: repeat count is not a positive number + --> $DIR/concat-bytes-error.rs:44:25 + | +LL | concat_bytes!([pie; -2]); + | ^^ + +error: expected a byte literal + --> $DIR/concat-bytes-error.rs:45:20 + | +LL | concat_bytes!([pie; 2]); + | ^^^ + | + = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()` + +error: cannot concatenate float literals + --> $DIR/concat-bytes-error.rs:46:20 + | +LL | concat_bytes!([2.2; 0]); + | ^^^ + +error: repeat count is not a positive number + --> $DIR/concat-bytes-error.rs:47:25 + | +LL | concat_bytes!([5.5; ()]); + | ^^ + +error: cannot concatenate doubly nested array + --> $DIR/concat-bytes-error.rs:48:20 + | +LL | concat_bytes!([[1, 2, 3]; 3]); + | ^^^^^^^^^ + +error: cannot concatenate doubly nested array + --> $DIR/concat-bytes-error.rs:49:20 + | +LL | concat_bytes!([[42; 2]; 3]); + | ^^^^^^^ + +error: aborting due to 28 previous errors + diff --git a/tests/ui/macros/concat-bytes.rs b/tests/ui/macros/concat-bytes.rs new file mode 100644 index 000000000..fd8f99417 --- /dev/null +++ b/tests/ui/macros/concat-bytes.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(concat_bytes)] + +fn main() { + assert_eq!(concat_bytes!(), &[]); + assert_eq!( + concat_bytes!(b'A', b"BC", [68, b'E', 70], [b'G'; 1], [72; 2], [73u8; 3], [65; 0]), + b"ABCDEFGHHIII", + ); + assert_eq!( + concat_bytes!( + concat_bytes!(b"AB", b"CD"), + concat_bytes!(b"EF", b"GH"), + ), + b"ABCDEFGH", + ); +} diff --git a/tests/ui/macros/concat-rpass.rs b/tests/ui/macros/concat-rpass.rs new file mode 100644 index 000000000..0c30a39d6 --- /dev/null +++ b/tests/ui/macros/concat-rpass.rs @@ -0,0 +1,18 @@ +// run-pass + +pub fn main() { + assert_eq!(format!(concat!("foo", "bar", "{}"), "baz"), "foobarbaz".to_string()); + assert_eq!(format!(concat!()), "".to_string()); + // check trailing comma is allowed in concat + assert_eq!(concat!("qux", "quux",).to_string(), "quxquux".to_string()); + + assert_eq!( + concat!(1, 2, 3, 4f32, 4.0, 'a', true), + "12344.0atrue" + ); + + assert!(match "12344.0atrue" { + concat!(1, 2, 3, 4f32, 4.0, 'a', true) => true, + _ => false + }) +} diff --git a/tests/ui/macros/concat.rs b/tests/ui/macros/concat.rs new file mode 100644 index 000000000..d7ab7d626 --- /dev/null +++ b/tests/ui/macros/concat.rs @@ -0,0 +1,6 @@ +fn main() { + concat!(b'f'); //~ ERROR: cannot concatenate a byte string literal + concat!(b"foo"); //~ ERROR: cannot concatenate a byte string literal + concat!(foo); //~ ERROR: expected a literal + concat!(foo()); //~ ERROR: expected a literal +} diff --git a/tests/ui/macros/concat.stderr b/tests/ui/macros/concat.stderr new file mode 100644 index 000000000..61fb9de1e --- /dev/null +++ b/tests/ui/macros/concat.stderr @@ -0,0 +1,30 @@ +error: cannot concatenate a byte string literal + --> $DIR/concat.rs:2:13 + | +LL | concat!(b'f'); + | ^^^^ + +error: cannot concatenate a byte string literal + --> $DIR/concat.rs:3:13 + | +LL | concat!(b"foo"); + | ^^^^^^ + +error: expected a literal + --> $DIR/concat.rs:4:13 + | +LL | concat!(foo); + | ^^^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + +error: expected a literal + --> $DIR/concat.rs:5:13 + | +LL | concat!(foo()); + | ^^^^^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/conditional-debug-macro-on.rs b/tests/ui/macros/conditional-debug-macro-on.rs new file mode 100644 index 000000000..8665da897 --- /dev/null +++ b/tests/ui/macros/conditional-debug-macro-on.rs @@ -0,0 +1,8 @@ +// run-pass +pub fn main() { + // exits early if println! evaluates its arguments, otherwise it + // will hit the panic. + println!("{:?}", { if true { return; } }); + + panic!(); +} diff --git a/tests/ui/macros/cross-crate-pat-span.rs b/tests/ui/macros/cross-crate-pat-span.rs new file mode 100644 index 000000000..ed67142ce --- /dev/null +++ b/tests/ui/macros/cross-crate-pat-span.rs @@ -0,0 +1,12 @@ +// edition:2021 +// check-pass +// aux-build: foreign-crate-macro-pat.rs +// +// Tests that the edition of the foreign crate is used +// when determining the behavior of the `:pat` matcher. + +extern crate foreign_crate_macro_pat; + +fn main() { + let _b = foreign_crate_macro_pat::custom_matches!(b'3', b'0' ..= b'9'); +} diff --git a/tests/ui/macros/derive-in-eager-expansion-hang.rs b/tests/ui/macros/derive-in-eager-expansion-hang.rs new file mode 100644 index 000000000..0729e14d5 --- /dev/null +++ b/tests/ui/macros/derive-in-eager-expansion-hang.rs @@ -0,0 +1,14 @@ +// Regression test for the issue #44692 + +macro_rules! hang { () => { + { //~ ERROR format argument must be a string literal + #[derive(Clone)] + struct S; + + "" + } +}} + +fn main() { + format_args!(hang!()); +} diff --git a/tests/ui/macros/derive-in-eager-expansion-hang.stderr b/tests/ui/macros/derive-in-eager-expansion-hang.stderr new file mode 100644 index 000000000..e0a4f3878 --- /dev/null +++ b/tests/ui/macros/derive-in-eager-expansion-hang.stderr @@ -0,0 +1,22 @@ +error: format argument must be a string literal + --> $DIR/derive-in-eager-expansion-hang.rs:4:5 + | +LL | / { +LL | | #[derive(Clone)] +LL | | struct S; +LL | | +LL | | "" +LL | | } + | |_____^ +... +LL | format_args!(hang!()); + | ------- in this macro invocation + | + = note: this error originates in the macro `hang` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might be missing a string literal to format with + | +LL | format_args!("{}", hang!()); + | +++++ + +error: aborting due to previous error + diff --git a/tests/ui/macros/die-macro-2.rs b/tests/ui/macros/die-macro-2.rs new file mode 100644 index 000000000..ebbce528a --- /dev/null +++ b/tests/ui/macros/die-macro-2.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:test +// ignore-emscripten no processes + +fn main() { + panic!("test"); +} diff --git a/tests/ui/macros/die-macro-expr.rs b/tests/ui/macros/die-macro-expr.rs new file mode 100644 index 000000000..c4b5f68dd --- /dev/null +++ b/tests/ui/macros/die-macro-expr.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:test +// ignore-emscripten no processes + +fn main() { + let __isize: isize = panic!("test"); +} diff --git a/tests/ui/macros/die-macro-pure.rs b/tests/ui/macros/die-macro-pure.rs new file mode 100644 index 000000000..588fbe61b --- /dev/null +++ b/tests/ui/macros/die-macro-pure.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:test +// ignore-emscripten no processes + +fn f() { + panic!("test"); +} + +fn main() { + f(); +} diff --git a/tests/ui/macros/die-macro.rs b/tests/ui/macros/die-macro.rs new file mode 100644 index 000000000..2a726efe8 --- /dev/null +++ b/tests/ui/macros/die-macro.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +// Just testing that panic!() type checks in statement or expr + + +#![allow(unreachable_code)] + +fn f() { + panic!(); + + let _x: isize = panic!(); +} + +pub fn main() { + +} diff --git a/tests/ui/macros/doc-comment.rs b/tests/ui/macros/doc-comment.rs new file mode 100644 index 000000000..9de39e9b5 --- /dev/null +++ b/tests/ui/macros/doc-comment.rs @@ -0,0 +1,25 @@ +// check-pass +// Tests that we properly handle a nested macro expansion +// involving a `#[doc]` attribute +#![deny(missing_docs)] +//! Crate docs + +macro_rules! doc_comment { + ($x:expr, $($tt:tt)*) => { + #[doc = $x] + $($tt)* + } +} + +macro_rules! make_comment { + () => { + doc_comment!("Function docs", + pub fn bar() {} + ); + } +} + + +make_comment!(); + +fn main() {} diff --git a/tests/ui/macros/dollar-crate-nested-encoding.rs b/tests/ui/macros/dollar-crate-nested-encoding.rs new file mode 100644 index 000000000..5242f7830 --- /dev/null +++ b/tests/ui/macros/dollar-crate-nested-encoding.rs @@ -0,0 +1,8 @@ +// check-pass +// aux-build:dollar-crate-nested-encoding.rs + +extern crate dollar_crate_nested_encoding; + +type A = dollar_crate_nested_encoding::exported!(); + +fn main() {} diff --git a/tests/ui/macros/duplicate-builtin.rs b/tests/ui/macros/duplicate-builtin.rs new file mode 100644 index 000000000..35f0f4290 --- /dev/null +++ b/tests/ui/macros/duplicate-builtin.rs @@ -0,0 +1,17 @@ +// compile-flags:--crate-type lib +#![feature(decl_macro)] +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +pub macro test($item:item) { +//~^ NOTE previously defined + /* compiler built-in */ +} + +mod inner { + #[rustc_builtin_macro] + pub macro test($item:item) { + //~^ ERROR attempted to define built-in macro more than once [E0773] + /* compiler built-in */ + } +} diff --git a/tests/ui/macros/duplicate-builtin.stderr b/tests/ui/macros/duplicate-builtin.stderr new file mode 100644 index 000000000..58accea27 --- /dev/null +++ b/tests/ui/macros/duplicate-builtin.stderr @@ -0,0 +1,21 @@ +error[E0773]: attempted to define built-in macro more than once + --> $DIR/duplicate-builtin.rs:13:5 + | +LL | / pub macro test($item:item) { +LL | | +LL | | /* compiler built-in */ +LL | | } + | |_____^ + | +note: previously defined here + --> $DIR/duplicate-builtin.rs:6:1 + | +LL | / pub macro test($item:item) { +LL | | +LL | | /* compiler built-in */ +LL | | } + | |_^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0773`. diff --git a/tests/ui/macros/edition-macro-pats.rs b/tests/ui/macros/edition-macro-pats.rs new file mode 100644 index 000000000..040894712 --- /dev/null +++ b/tests/ui/macros/edition-macro-pats.rs @@ -0,0 +1,12 @@ +// run-pass +// edition:2021 + +macro_rules! foo { + (a $x:pat_param) => {}; + (b $x:pat) => {}; +} + +fn main() { + foo!(a None); + foo!(b 1 | 2); +} diff --git a/tests/ui/macros/empty-trailing-stmt.rs b/tests/ui/macros/empty-trailing-stmt.rs new file mode 100644 index 000000000..3d78ed4a4 --- /dev/null +++ b/tests/ui/macros/empty-trailing-stmt.rs @@ -0,0 +1,10 @@ +macro_rules! empty { + () => { } +} + +fn foo() -> bool { //~ ERROR mismatched + { true } //~ ERROR mismatched + empty!(); +} + +fn main() {} diff --git a/tests/ui/macros/empty-trailing-stmt.stderr b/tests/ui/macros/empty-trailing-stmt.stderr new file mode 100644 index 000000000..97a2edd39 --- /dev/null +++ b/tests/ui/macros/empty-trailing-stmt.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/empty-trailing-stmt.rs:6:7 + | +LL | { true } + | ^^^^ expected `()`, found `bool` + | +help: you might have meant to return this value + | +LL | { return true; } + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/empty-trailing-stmt.rs:5:13 + | +LL | fn foo() -> bool { + | --- ^^^^ expected `bool`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macros/format-args-temporaries-async.rs b/tests/ui/macros/format-args-temporaries-async.rs new file mode 100644 index 000000000..d959329b9 --- /dev/null +++ b/tests/ui/macros/format-args-temporaries-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2021 + +use std::fmt::{self, Display}; +use std::future::Future; +use std::io; +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct AsyncStdout; + +impl AsyncStdout { + fn write_fmt<'a>(&'a mut self, _args: fmt::Arguments) -> WriteFmtFuture<'a, Self> + where + Self: Unpin, + { + WriteFmtFuture(self) + } +} + +struct WriteFmtFuture<'a, T>(&'a mut T); + +impl<'a, T> Future for WriteFmtFuture<'a, T> { + type Output = io::Result<()>; + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + unimplemented!() + } +} + +async fn async_main() { + let _write = write!(&mut AsyncStdout, "...").await; + let _writeln = writeln!(&mut AsyncStdout, "...").await; +} + +fn main() { + let _ = async_main; +} diff --git a/tests/ui/macros/format-args-temporaries-in-write.rs b/tests/ui/macros/format-args-temporaries-in-write.rs new file mode 100644 index 000000000..339ccbc33 --- /dev/null +++ b/tests/ui/macros/format-args-temporaries-in-write.rs @@ -0,0 +1,50 @@ +// check-fail + +use std::fmt::{self, Display}; + +struct Mutex; + +impl Mutex { + fn lock(&self) -> MutexGuard { + MutexGuard(self) + } +} + +struct MutexGuard<'a>(&'a Mutex); + +impl<'a> Drop for MutexGuard<'a> { + fn drop(&mut self) { + // Empty but this is a necessary part of the repro. Otherwise borrow + // checker is fine with 'a dangling at the time that MutexGuard goes out + // of scope. + } +} + +struct Out; + +impl Out { + fn write_fmt(&self, _args: fmt::Arguments) {} +} + +impl<'a> Display for MutexGuard<'a> { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +fn main() { + // FIXME(dtolnay): We actually want both of these to work. I think it's + // sadly unimplementable today though. + + let _write = { + let mutex = Mutex; + write!(Out, "{}", mutex.lock()) /* no semicolon */ + //~^ ERROR `mutex` does not live long enough + }; + + let _writeln = { + let mutex = Mutex; + writeln!(Out, "{}", mutex.lock()) /* no semicolon */ + //~^ ERROR `mutex` does not live long enough + }; +} diff --git a/tests/ui/macros/format-args-temporaries-in-write.stderr b/tests/ui/macros/format-args-temporaries-in-write.stderr new file mode 100644 index 000000000..287cd7d67 --- /dev/null +++ b/tests/ui/macros/format-args-temporaries-in-write.stderr @@ -0,0 +1,33 @@ +error[E0597]: `mutex` does not live long enough + --> $DIR/format-args-temporaries-in-write.rs:41:27 + | +LL | write!(Out, "{}", mutex.lock()) /* no semicolon */ + | ^^^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` + | | + | `mutex` dropped here while still borrowed + | + +error[E0597]: `mutex` does not live long enough + --> $DIR/format-args-temporaries-in-write.rs:47:29 + | +LL | writeln!(Out, "{}", mutex.lock()) /* no semicolon */ + | ^^^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` + | | + | `mutex` dropped here while still borrowed + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/macros/format-args-temporaries.rs b/tests/ui/macros/format-args-temporaries.rs new file mode 100644 index 000000000..59323828b --- /dev/null +++ b/tests/ui/macros/format-args-temporaries.rs @@ -0,0 +1,54 @@ +// check-pass + +use std::fmt::{self, Display}; + +struct Mutex; + +impl Mutex { + fn lock(&self) -> MutexGuard { + MutexGuard(self) + } +} + +struct MutexGuard<'a>(&'a Mutex); + +impl<'a> Drop for MutexGuard<'a> { + fn drop(&mut self) { + // Empty but this is a necessary part of the repro. Otherwise borrow + // checker is fine with 'a dangling at the time that MutexGuard goes out + // of scope. + } +} + +impl<'a> Display for MutexGuard<'a> { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +fn main() { + let _print = { + let mutex = Mutex; + print!("{}", mutex.lock()) /* no semicolon */ + }; + + let _println = { + let mutex = Mutex; + println!("{}", mutex.lock()) /* no semicolon */ + }; + + let _eprint = { + let mutex = Mutex; + eprint!("{}", mutex.lock()) /* no semicolon */ + }; + + let _eprintln = { + let mutex = Mutex; + eprintln!("{}", mutex.lock()) /* no semicolon */ + }; + + let _panic = { + let mutex = Mutex; + panic!("{}", mutex.lock()) /* no semicolon */ + }; +} diff --git a/tests/ui/macros/format-foreign.rs b/tests/ui/macros/format-foreign.rs new file mode 100644 index 000000000..ac65838f2 --- /dev/null +++ b/tests/ui/macros/format-foreign.rs @@ -0,0 +1,17 @@ +fn main() { + println!("%.*3$s %s!\n", "Hello,", "World", 4); //~ ERROR multiple unused formatting arguments + println!("%1$*2$.*3$f", 123.456); //~ ERROR never used + println!(r###"%.*3$s + %s!\n +"###, "Hello,", "World", 4); + //~^ ERROR multiple unused formatting arguments + // correctly account for raw strings in inline suggestions + + // This should *not* produce hints, on the basis that there's equally as + // many "correct" format specifiers. It's *probably* just an actual typo. + println!("{} %f", "one", 2.0); //~ ERROR never used + + println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used + println!("$1 $0 $$ $NAME", 1, 2, NAME=3); + //~^ ERROR multiple unused formatting arguments +} diff --git a/tests/ui/macros/format-foreign.stderr b/tests/ui/macros/format-foreign.stderr new file mode 100644 index 000000000..7971c2ab2 --- /dev/null +++ b/tests/ui/macros/format-foreign.stderr @@ -0,0 +1,82 @@ +error: multiple unused formatting arguments + --> $DIR/format-foreign.rs:2:30 + | +LL | println!("%.*3$s %s!\n", "Hello,", "World", 4); + | -------------- ^^^^^^^^ ^^^^^^^ ^ argument never used + | | | | + | | | argument never used + | | argument never used + | multiple missing formatting specifiers + | + = note: printf formatting is not supported; see the documentation for `std::fmt` +help: format specifiers use curly braces + | +LL | println!("{:.2$} {}!\n", "Hello,", "World", 4); + | ~~~~~~ ~~ + +error: argument never used + --> $DIR/format-foreign.rs:3:29 + | +LL | println!("%1$*2$.*3$f", 123.456); + | ----------- ^^^^^^^ argument never used + | | + | help: format specifiers use curly braces: `{0:1$.2$}` + | + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: multiple unused formatting arguments + --> $DIR/format-foreign.rs:6:7 + | +LL | println!(r###"%.*3$s + | ______________- +LL | | %s!\n +LL | | "###, "Hello,", "World", 4); + | | - ^^^^^^^^ ^^^^^^^ ^ argument never used + | | | | | + | | | | argument never used + | |____| argument never used + | multiple missing formatting specifiers + | + = note: printf formatting is not supported; see the documentation for `std::fmt` +help: format specifiers use curly braces + | +LL ~ println!(r###"{:.2$} +LL ~ {}!\n + | + +error: argument never used + --> $DIR/format-foreign.rs:12:30 + | +LL | println!("{} %f", "one", 2.0); + | ------- ^^^ argument never used + | | + | formatting specifier missing + +error: named argument never used + --> $DIR/format-foreign.rs:14:39 + | +LL | println!("Hi there, $NAME.", NAME="Tim"); + | ----- ^^^^^ named argument never used + | | + | help: format specifiers use curly braces: `{NAME}` + | + = note: shell formatting is not supported; see the documentation for `std::fmt` + +error: multiple unused formatting arguments + --> $DIR/format-foreign.rs:15:32 + | +LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3); + | ---------------- ^ ^ ^ named argument never used + | | | | + | | | argument never used + | | argument never used + | multiple missing formatting specifiers + | + = note: shell formatting is not supported; see the documentation for `std::fmt` +help: format specifiers use curly braces + | +LL | println!("{1} {0} $$ {NAME}", 1, 2, NAME=3); + | ~~~ ~~~ ~~~~~~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/macros/format-parse-errors.rs b/tests/ui/macros/format-parse-errors.rs new file mode 100644 index 000000000..ffa7a2817 --- /dev/null +++ b/tests/ui/macros/format-parse-errors.rs @@ -0,0 +1,17 @@ +fn main() { + let foo = ""; + let bar = ""; + format!(); //~ ERROR requires at least a format string argument + format!(struct); //~ ERROR expected expression + format!("s", name =); //~ ERROR expected expression + format!( + "s {foo} {} {}", + foo = foo, + bar, //~ ERROR positional arguments cannot follow named arguments + ); + format!("s {foo}", foo = struct); //~ ERROR expected expression + format!("s", struct); //~ ERROR expected expression + + // This error should come after parsing errors to ensure they are non-fatal. + format!(123); //~ ERROR format argument must be a string literal +} diff --git a/tests/ui/macros/format-parse-errors.stderr b/tests/ui/macros/format-parse-errors.stderr new file mode 100644 index 000000000..f9ea4c633 --- /dev/null +++ b/tests/ui/macros/format-parse-errors.stderr @@ -0,0 +1,53 @@ +error: requires at least a format string argument + --> $DIR/format-parse-errors.rs:4:5 + | +LL | format!(); + | ^^^^^^^^^ + | + = note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found keyword `struct` + --> $DIR/format-parse-errors.rs:5:13 + | +LL | format!(struct); + | ^^^^^^ expected expression + +error: expected expression, found end of macro arguments + --> $DIR/format-parse-errors.rs:6:24 + | +LL | format!("s", name =); + | ^ expected expression + +error: positional arguments cannot follow named arguments + --> $DIR/format-parse-errors.rs:10:9 + | +LL | foo = foo, + | --------- named argument +LL | bar, + | ^^^ positional arguments must be before named arguments + +error: expected expression, found keyword `struct` + --> $DIR/format-parse-errors.rs:12:30 + | +LL | format!("s {foo}", foo = struct); + | ^^^^^^ expected expression + +error: expected expression, found keyword `struct` + --> $DIR/format-parse-errors.rs:13:18 + | +LL | format!("s", struct); + | ^^^^^^ expected expression + +error: format argument must be a string literal + --> $DIR/format-parse-errors.rs:16:13 + | +LL | format!(123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | format!("{}", 123); + | +++++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/macros/format-unused-lables.rs b/tests/ui/macros/format-unused-lables.rs new file mode 100644 index 000000000..56382b101 --- /dev/null +++ b/tests/ui/macros/format-unused-lables.rs @@ -0,0 +1,18 @@ +fn main() { + println!("Test", 123, 456, 789); + //~^ ERROR multiple unused formatting arguments + + println!("Test2", + 123, //~ ERROR multiple unused formatting arguments + 456, + 789 + ); + + println!("Some stuff", UNUSED="args"); //~ ERROR named argument never used + + println!("Some more $STUFF", + "woo!", //~ ERROR multiple unused formatting arguments + STUFF= + "things" + , UNUSED="args"); +} diff --git a/tests/ui/macros/format-unused-lables.stderr b/tests/ui/macros/format-unused-lables.stderr new file mode 100644 index 000000000..fad87fa2a --- /dev/null +++ b/tests/ui/macros/format-unused-lables.stderr @@ -0,0 +1,50 @@ +error: multiple unused formatting arguments + --> $DIR/format-unused-lables.rs:2:22 + | +LL | println!("Test", 123, 456, 789); + | ------ ^^^ ^^^ ^^^ argument never used + | | | | + | | | argument never used + | | argument never used + | multiple missing formatting specifiers + +error: multiple unused formatting arguments + --> $DIR/format-unused-lables.rs:6:9 + | +LL | println!("Test2", + | ------- multiple missing formatting specifiers +LL | 123, + | ^^^ argument never used +LL | 456, + | ^^^ argument never used +LL | 789 + | ^^^ argument never used + +error: named argument never used + --> $DIR/format-unused-lables.rs:11:35 + | +LL | println!("Some stuff", UNUSED="args"); + | ------------ ^^^^^^ named argument never used + | | + | formatting specifier missing + +error: multiple unused formatting arguments + --> $DIR/format-unused-lables.rs:14:9 + | +LL | println!("Some more $STUFF", + | ------------------ + | | | + | | help: format specifiers use curly braces: `{STUFF}` + | multiple missing formatting specifiers +LL | "woo!", + | ^^^^^^ argument never used +LL | STUFF= +LL | "things" + | ^^^^^^^^ named argument never used +LL | , UNUSED="args"); + | ^^^^^^ named argument never used + | + = note: shell formatting is not supported; see the documentation for `std::fmt` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/global-asm.rs b/tests/ui/macros/global-asm.rs new file mode 100644 index 000000000..26e90edce --- /dev/null +++ b/tests/ui/macros/global-asm.rs @@ -0,0 +1,7 @@ +use std::arch::global_asm; + +fn main() { + global_asm!(); //~ ERROR requires at least a template string argument + global_asm!(struct); //~ ERROR expected expression + global_asm!(123); //~ ERROR asm template must be a string literal +} diff --git a/tests/ui/macros/global-asm.stderr b/tests/ui/macros/global-asm.stderr new file mode 100644 index 000000000..3c26ec65a --- /dev/null +++ b/tests/ui/macros/global-asm.stderr @@ -0,0 +1,20 @@ +error: requires at least a template string argument + --> $DIR/global-asm.rs:4:5 + | +LL | global_asm!(); + | ^^^^^^^^^^^^^ + +error: expected expression, found keyword `struct` + --> $DIR/global-asm.rs:5:17 + | +LL | global_asm!(struct); + | ^^^^^^ expected expression + +error: asm template must be a string literal + --> $DIR/global-asm.rs:6:17 + | +LL | global_asm!(123); + | ^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/html-literals.rs b/tests/ui/macros/html-literals.rs new file mode 100644 index 000000000..26f00fed9 --- /dev/null +++ b/tests/ui/macros/html-literals.rs @@ -0,0 +1,95 @@ +// run-pass + +#![allow(non_camel_case_types)] +// A test of the macro system. Can we do HTML literals? + +/* + +This is an HTML parser written as a macro. It's all CPS, and we have +to carry around a bunch of state. The arguments to macros all look like this: + +{ tag_stack* # expr* # tokens } + +The stack keeps track of where we are in the tree. The expr is a list +of children of the current node. The tokens are everything that's +left. + +*/ +use HTMLFragment::{tag, text}; + +macro_rules! html { + ( $($body:tt)* ) => ( + parse_node!( []; []; $($body)* ) + ) +} + +macro_rules! parse_node { + ( + [:$head:ident ($(:$head_nodes:expr),*) + $(:$tags:ident ($(:$tag_nodes:expr),*))*]; + [$(:$nodes:expr),*]; + $($rest:tt)* + ) => ( + parse_node!( + [$(: $tags ($(:$tag_nodes),*))*]; + [$(:$head_nodes,)* :tag(stringify!($head).to_string(), + vec![$($nodes),*])]; + $($rest)* + ) + ); + + ( + [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; + [$(:$nodes:expr),*]; + <$tag:ident> $($rest:tt)* + ) => ( + parse_node!( + [:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*]; + []; + $($rest)* + ) + ); + + ( + [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; + [$(:$nodes:expr),*]; + . $($rest:tt)* + ) => ( + parse_node!( + [$(: $tags ($(:$tag_nodes),*))*]; + [$(:$nodes,)* :text(".".to_string())]; + $($rest)* + ) + ); + + ( + [$(:$tags:ident ($(:$tag_nodes:expr),*) )*]; + [$(:$nodes:expr),*]; + $word:ident $($rest:tt)* + ) => ( + parse_node!( + [$(: $tags ($(:$tag_nodes),*))*]; + [$(:$nodes,)* :text(stringify!($word).to_string())]; + $($rest)* + ) + ); + + ( []; [:$e:expr]; ) => ( $e ); +} + +pub fn main() { + let _page = html! ( + + This is the title. + +

This is some text

+ + + ); +} + +#[allow(unused_tuple_struct_fields)] +enum HTMLFragment { + tag(String, Vec ), + text(String), +} diff --git a/tests/ui/macros/include-single-expr-helper-1.rs b/tests/ui/macros/include-single-expr-helper-1.rs new file mode 100644 index 000000000..aa6380bd2 --- /dev/null +++ b/tests/ui/macros/include-single-expr-helper-1.rs @@ -0,0 +1,5 @@ +// ignore-test auxiliary file for include-single-expr.rs + +0 + +// trailing comment permitted diff --git a/tests/ui/macros/include-single-expr-helper.rs b/tests/ui/macros/include-single-expr-helper.rs new file mode 100644 index 000000000..84d8b6960 --- /dev/null +++ b/tests/ui/macros/include-single-expr-helper.rs @@ -0,0 +1,5 @@ +// ignore-test auxiliary file for include-single-expr.rs + +0 +10 +100 diff --git a/tests/ui/macros/include-single-expr.rs b/tests/ui/macros/include-single-expr.rs new file mode 100644 index 000000000..0f4c29ec0 --- /dev/null +++ b/tests/ui/macros/include-single-expr.rs @@ -0,0 +1,6 @@ +// error-pattern include macro expected single expression + +fn main() { + include!("include-single-expr-helper.rs"); + include!("include-single-expr-helper-1.rs"); +} diff --git a/tests/ui/macros/include-single-expr.stderr b/tests/ui/macros/include-single-expr.stderr new file mode 100644 index 000000000..80eecf8f1 --- /dev/null +++ b/tests/ui/macros/include-single-expr.stderr @@ -0,0 +1,10 @@ +error: include macro expected single expression in source + --> $DIR/include-single-expr-helper.rs:4:1 + | +LL | 10 + | ^^ + | + = note: `#[deny(incomplete_include)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-100199.rs b/tests/ui/macros/issue-100199.rs new file mode 100644 index 000000000..6e50afa07 --- /dev/null +++ b/tests/ui/macros/issue-100199.rs @@ -0,0 +1,16 @@ +#[issue_100199::struct_with_bound] //~ ERROR cannot find trait `MyTrait` in the crate root +struct Foo {} +// The above must be on the first line so that it's span points to pos 0. +// This used to trigger an ICE because the diagnostic emitter would get +// an unexpected dummy span (lo == 0 == hi) while attempting to print a +// suggestion. + +// aux-build: issue-100199.rs + +extern crate issue_100199; + +mod traits { + pub trait MyTrait {} +} + +fn main() {} diff --git a/tests/ui/macros/issue-100199.stderr b/tests/ui/macros/issue-100199.stderr new file mode 100644 index 000000000..2cb45dc12 --- /dev/null +++ b/tests/ui/macros/issue-100199.stderr @@ -0,0 +1,15 @@ +error[E0405]: cannot find trait `MyTrait` in the crate root + --> $DIR/issue-100199.rs:1:1 + | +LL | #[issue_100199::struct_with_bound] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root + | + = note: this error originates in the attribute macro `issue_100199::struct_with_bound` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider importing this trait + | +LL | use traits::MyTrait; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/macros/issue-102878.rs b/tests/ui/macros/issue-102878.rs new file mode 100644 index 000000000..aac589193 --- /dev/null +++ b/tests/ui/macros/issue-102878.rs @@ -0,0 +1,10 @@ +macro_rules!test{($l:expr,$_:r)=>({const:y y)} +//~^ ERROR mismatched closing delimiter: `)` +//~| ERROR invalid fragment specifier `r` +//~| ERROR expected identifier, found keyword `const` +//~| ERROR expected identifier, found keyword `const` +//~| ERROR expected identifier, found `:` + +fn s(){test!(1,i)} + +fn main() {} diff --git a/tests/ui/macros/issue-102878.stderr b/tests/ui/macros/issue-102878.stderr new file mode 100644 index 000000000..e0b8855a3 --- /dev/null +++ b/tests/ui/macros/issue-102878.stderr @@ -0,0 +1,60 @@ +error: mismatched closing delimiter: `)` + --> $DIR/issue-102878.rs:1:35 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | -^ ^ mismatched closing delimiter + | || + | |unclosed delimiter + | closing delimiter possibly meant for this + +error: invalid fragment specifier `r` + --> $DIR/issue-102878.rs:1:27 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: expected identifier, found keyword `const` + --> $DIR/issue-102878.rs:1:36 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^^^^^ expected identifier, found keyword +... +LL | fn s(){test!(1,i)} + | ---------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) +help: escape `const` to use it as an identifier + | +LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)} + | ++ + +error: expected identifier, found keyword `const` + --> $DIR/issue-102878.rs:1:36 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^^^^^ expected identifier, found keyword +... +LL | fn s(){test!(1,i)} + | ---------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) +help: escape `const` to use it as an identifier + | +LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)} + | ++ + +error: expected identifier, found `:` + --> $DIR/issue-102878.rs:1:41 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^ expected identifier +... +LL | fn s(){test!(1,i)} + | ---------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + diff --git a/tests/ui/macros/issue-103529.rs b/tests/ui/macros/issue-103529.rs new file mode 100644 index 000000000..fa05baed7 --- /dev/null +++ b/tests/ui/macros/issue-103529.rs @@ -0,0 +1,13 @@ +macro_rules! m { + ($s:stmt) => {} +} + +m! { mut x } +//~^ ERROR expected expression, found keyword `mut` +//~| ERROR expected a statement +m! { auto x } +//~^ ERROR invalid variable declaration +m! { var x } +//~^ ERROR invalid variable declaration + +fn main() {} diff --git a/tests/ui/macros/issue-103529.stderr b/tests/ui/macros/issue-103529.stderr new file mode 100644 index 000000000..61e322afc --- /dev/null +++ b/tests/ui/macros/issue-103529.stderr @@ -0,0 +1,39 @@ +error: expected expression, found keyword `mut` + --> $DIR/issue-103529.rs:5:6 + | +LL | m! { mut x } + | ^^^ expected expression + +error: expected a statement + --> $DIR/issue-103529.rs:5:10 + | +LL | ($s:stmt) => {} + | ------- while parsing argument for this `stmt` macro fragment +... +LL | m! { mut x } + | ^ + +error: invalid variable declaration + --> $DIR/issue-103529.rs:8:6 + | +LL | m! { auto x } + | ^^^^ + | +help: write `let` instead of `auto` to introduce a new variable + | +LL | m! { let x } + | ~~~ + +error: invalid variable declaration + --> $DIR/issue-103529.rs:10:6 + | +LL | m! { var x } + | ^^^ + | +help: write `let` instead of `var` to introduce a new variable + | +LL | m! { let x } + | ~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/issue-104769-concat_bytes-invalid-literal.rs b/tests/ui/macros/issue-104769-concat_bytes-invalid-literal.rs new file mode 100644 index 000000000..24150376e --- /dev/null +++ b/tests/ui/macros/issue-104769-concat_bytes-invalid-literal.rs @@ -0,0 +1,8 @@ +#![feature(concat_bytes)] + +fn main() { + concat_bytes!(7Y); + //~^ ERROR invalid suffix `Y` for number literal + concat_bytes!(888888888888888888888888888888888888888); + //~^ ERROR integer literal is too large +} diff --git a/tests/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr b/tests/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr new file mode 100644 index 000000000..8807279c2 --- /dev/null +++ b/tests/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr @@ -0,0 +1,18 @@ +error: invalid suffix `Y` for number literal + --> $DIR/issue-104769-concat_bytes-invalid-literal.rs:4:19 + | +LL | concat_bytes!(7Y); + | ^^ invalid suffix `Y` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: integer literal is too large + --> $DIR/issue-104769-concat_bytes-invalid-literal.rs:6:19 + | +LL | concat_bytes!(888888888888888888888888888888888888888); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-105011.rs b/tests/ui/macros/issue-105011.rs new file mode 100644 index 000000000..da12c3814 --- /dev/null +++ b/tests/ui/macros/issue-105011.rs @@ -0,0 +1,3 @@ +fn main() { + println!(""y); //~ ERROR suffixes on string literals are invalid +} diff --git a/tests/ui/macros/issue-105011.stderr b/tests/ui/macros/issue-105011.stderr new file mode 100644 index 000000000..e898af7fa --- /dev/null +++ b/tests/ui/macros/issue-105011.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/issue-105011.rs:2:14 + | +LL | println!(""y); + | ^^^ invalid suffix `y` + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-10536.rs b/tests/ui/macros/issue-10536.rs new file mode 100644 index 000000000..f536d8f94 --- /dev/null +++ b/tests/ui/macros/issue-10536.rs @@ -0,0 +1,19 @@ +// We only want to assert that this doesn't ICE, we don't particularly care +// about whether it nor it fails to compile. + +macro_rules! foo{ + () => {{ + macro_rules! bar{() => (())} + 1 + }} +} + +pub fn main() { + foo!(); + + assert!({one! two()}); //~ ERROR expected one of `(`, `[`, or `{`, found `two` + + // regardless of whether nested macro_rules works, the following should at + // least throw a conventional error. + assert!({one! two}); //~ ERROR expected one of `(`, `[`, or `{`, found `two` +} diff --git a/tests/ui/macros/issue-10536.stderr b/tests/ui/macros/issue-10536.stderr new file mode 100644 index 000000000..cc0484458 --- /dev/null +++ b/tests/ui/macros/issue-10536.stderr @@ -0,0 +1,14 @@ +error: expected one of `(`, `[`, or `{`, found `two` + --> $DIR/issue-10536.rs:14:19 + | +LL | assert!({one! two()}); + | ^^^ expected one of `(`, `[`, or `{` + +error: expected one of `(`, `[`, or `{`, found `two` + --> $DIR/issue-10536.rs:18:19 + | +LL | assert!({one! two}); + | ^^^ expected one of `(`, `[`, or `{` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-16098.rs b/tests/ui/macros/issue-16098.rs new file mode 100644 index 000000000..00acc20fc --- /dev/null +++ b/tests/ui/macros/issue-16098.rs @@ -0,0 +1,16 @@ +macro_rules! prob1 { + (0) => { + 0 + }; + ($n:expr) => { + if ($n % 3 == 0) || ($n % 5 == 0) { + $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!` + } else { + prob1!($n - 1); + } + }; +} + +fn main() { + println!("Problem 1: {}", prob1!(1000)); +} diff --git a/tests/ui/macros/issue-16098.stderr b/tests/ui/macros/issue-16098.stderr new file mode 100644 index 000000000..64280219d --- /dev/null +++ b/tests/ui/macros/issue-16098.stderr @@ -0,0 +1,14 @@ +error: recursion limit reached while expanding `prob1!` + --> $DIR/issue-16098.rs:7:18 + | +LL | $n + prob1!($n - 1); + | ^^^^^^^^^^^^^^ +... +LL | println!("Problem 1: {}", prob1!(1000)); + | ------------ in this macro invocation + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`) + = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-19163.rs b/tests/ui/macros/issue-19163.rs new file mode 100644 index 000000000..d98c5912a --- /dev/null +++ b/tests/ui/macros/issue-19163.rs @@ -0,0 +1,11 @@ +// aux-build:issue-19163.rs + +#[macro_use] extern crate issue_19163; + +use std::io::Write; + +fn main() { + let mut v = vec![]; + mywrite!(&v, "Hello world"); + //~^ ERROR cannot borrow data in a `&` reference as mutable +} diff --git a/tests/ui/macros/issue-19163.stderr b/tests/ui/macros/issue-19163.stderr new file mode 100644 index 000000000..ae1ae1426 --- /dev/null +++ b/tests/ui/macros/issue-19163.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-19163.rs:9:5 + | +LL | mywrite!(&v, "Hello world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | + = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/macros/issue-21356.rs b/tests/ui/macros/issue-21356.rs new file mode 100644 index 000000000..ae623929d --- /dev/null +++ b/tests/ui/macros/issue-21356.rs @@ -0,0 +1,6 @@ +#![allow(unused_macros)] + +macro_rules! test { ($wrong:t_ty ..) => () } + //~^ ERROR: invalid fragment specifier `t_ty` + +fn main() {} diff --git a/tests/ui/macros/issue-21356.stderr b/tests/ui/macros/issue-21356.stderr new file mode 100644 index 000000000..17014c6ce --- /dev/null +++ b/tests/ui/macros/issue-21356.stderr @@ -0,0 +1,10 @@ +error: invalid fragment specifier `t_ty` + --> $DIR/issue-21356.rs:3:22 + | +LL | macro_rules! test { ($wrong:t_ty ..) => () } + | ^^^^^^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-22463.rs b/tests/ui/macros/issue-22463.rs new file mode 100644 index 000000000..fdf5a2fca --- /dev/null +++ b/tests/ui/macros/issue-22463.rs @@ -0,0 +1,20 @@ +// run-pass +macro_rules! items { + () => { + type A = (); + fn a() {} + } +} + +trait Foo { + type A; + fn a(); +} + +impl Foo for () { + items!(); +} + +fn main() { + +} diff --git a/tests/ui/macros/issue-25274.rs b/tests/ui/macros/issue-25274.rs new file mode 100644 index 000000000..65b29bba8 --- /dev/null +++ b/tests/ui/macros/issue-25274.rs @@ -0,0 +1,18 @@ +// run-pass + +macro_rules! test { + ( + fn fun() -> Option>; + ) => { + fn fun(x: $t) -> Option> + { Some(Box::new(x)) } + } +} + +test! { + fn fun() -> Option>; +} + +fn main() { + println!("{}", fun(0).unwrap()); +} diff --git a/tests/ui/macros/issue-25385.rs b/tests/ui/macros/issue-25385.rs new file mode 100644 index 000000000..ea042a6c7 --- /dev/null +++ b/tests/ui/macros/issue-25385.rs @@ -0,0 +1,12 @@ +macro_rules! foo { + ($e:expr) => { $e.foo() } + //~^ ERROR no method named `foo` found +} + +fn main() { + let a = 1i32; + foo!(a); + + foo!(1i32.foo()); + //~^ ERROR no method named `foo` found +} diff --git a/tests/ui/macros/issue-25385.stderr b/tests/ui/macros/issue-25385.stderr new file mode 100644 index 000000000..39dbdd753 --- /dev/null +++ b/tests/ui/macros/issue-25385.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `foo` found for type `i32` in the current scope + --> $DIR/issue-25385.rs:2:23 + | +LL | ($e:expr) => { $e.foo() } + | ^^^ method not found in `i32` +... +LL | foo!(a); + | ------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: no method named `foo` found for type `i32` in the current scope + --> $DIR/issue-25385.rs:10:15 + | +LL | foo!(1i32.foo()); + | ^^^ method not found in `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/macros/issue-26322.rs b/tests/ui/macros/issue-26322.rs new file mode 100644 index 000000000..c1dc80eb7 --- /dev/null +++ b/tests/ui/macros/issue-26322.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +macro_rules! columnline { + () => ( + (column!(), line!()) + ) +} + +macro_rules! indirectcolumnline { + () => ( + (||{ columnline!() })() + ) +} + +fn main() { + let closure = || { + columnline!() + }; + let iflet = if let Some(_) = Some(0) { + columnline!() + } else { (0, 0) }; + let cl = columnline!(); + assert_eq!(closure(), (9, 19)); + assert_eq!(iflet, (9, 22)); + assert_eq!(cl, (14, 24)); + let indirect = indirectcolumnline!(); + assert_eq!(indirect, (20, 28)); +} diff --git a/tests/ui/macros/issue-29084.rs b/tests/ui/macros/issue-29084.rs new file mode 100644 index 000000000..d16252686 --- /dev/null +++ b/tests/ui/macros/issue-29084.rs @@ -0,0 +1,13 @@ +macro_rules! foo { + ($d:expr) => {{ + fn bar(d: u8) { } + bar(&mut $d); + //~^ ERROR mismatched types + //~| expected `u8`, found `&mut u8` + }} +} + +fn main() { + foo!(0u8); + //~^ in this expansion of foo! +} diff --git a/tests/ui/macros/issue-29084.stderr b/tests/ui/macros/issue-29084.stderr new file mode 100644 index 000000000..f83e19213 --- /dev/null +++ b/tests/ui/macros/issue-29084.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-29084.rs:4:13 + | +LL | bar(&mut $d); + | --- ^^^^^^^ expected `u8`, found `&mut u8` + | | + | arguments to this function are incorrect +... +LL | foo!(0u8); + | --------- in this macro invocation + | +note: function defined here + --> $DIR/issue-29084.rs:3:12 + | +LL | fn bar(d: u8) { } + | ^^^ ----- +... +LL | foo!(0u8); + | --------- in this macro invocation + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macros/issue-30143.rs b/tests/ui/macros/issue-30143.rs new file mode 100644 index 000000000..ac4c1da5c --- /dev/null +++ b/tests/ui/macros/issue-30143.rs @@ -0,0 +1,11 @@ +use std::fmt::Write; + +fn main() { + println!(0); + //~^ ERROR format argument must be a string literal + eprintln!('a'); + //~^ ERROR format argument must be a string literal + let mut s = String::new(); + writeln!(s, true).unwrap(); + //~^ ERROR format argument must be a string literal +} diff --git a/tests/ui/macros/issue-30143.stderr b/tests/ui/macros/issue-30143.stderr new file mode 100644 index 000000000..fd2378dbc --- /dev/null +++ b/tests/ui/macros/issue-30143.stderr @@ -0,0 +1,35 @@ +error: format argument must be a string literal + --> $DIR/issue-30143.rs:4:14 + | +LL | println!(0); + | ^ + | +help: you might be missing a string literal to format with + | +LL | println!("{}", 0); + | +++++ + +error: format argument must be a string literal + --> $DIR/issue-30143.rs:6:15 + | +LL | eprintln!('a'); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | eprintln!("{}", 'a'); + | +++++ + +error: format argument must be a string literal + --> $DIR/issue-30143.rs:9:17 + | +LL | writeln!(s, true).unwrap(); + | ^^^^ + | +help: you might be missing a string literal to format with + | +LL | writeln!(s, "{}", true).unwrap(); + | +++++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/issue-33185.rs b/tests/ui/macros/issue-33185.rs new file mode 100644 index 000000000..0d6669146 --- /dev/null +++ b/tests/ui/macros/issue-33185.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] + +#[macro_export] +macro_rules! state { + ( $( $name:ident : $field:ty )* ) => ( + #[derive(Default)] + struct State { + $($name : $field),* + } + ) +} + +state! { x: i64 } + +pub fn main() { +} diff --git a/tests/ui/macros/issue-34171.rs b/tests/ui/macros/issue-34171.rs new file mode 100644 index 000000000..157c58c45 --- /dev/null +++ b/tests/ui/macros/issue-34171.rs @@ -0,0 +1,10 @@ +// check-pass + +macro_rules! null { ($i:tt) => {} } +macro_rules! apply_null { + ($i:item) => { null! { $i } } +} + +fn main() { + apply_null!(#[cfg(all())] fn f() {}); +} diff --git a/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs b/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs new file mode 100644 index 000000000..d78139365 --- /dev/null +++ b/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs @@ -0,0 +1,15 @@ +macro_rules! make_item { + ($a:ident) => { + struct $a; + }; //~^ ERROR expected expression + //~| ERROR expected expression +} + +fn a() { + make_item!(A) +} +fn b() { + make_item!(B) +} + +fn main() {} diff --git a/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr b/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr new file mode 100644 index 000000000..00139662d --- /dev/null +++ b/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr @@ -0,0 +1,34 @@ +error: expected expression, found keyword `struct` + --> $DIR/issue-34421-mac-expr-bad-stmt-good-add-semi.rs:3:9 + | +LL | struct $a; + | ^^^^^^ expected expression +... +LL | make_item!(A) + | ------------- in this macro invocation + | + = note: the macro call doesn't expand to an expression, but it can expand to a statement + = note: this error originates in the macro `make_item` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `;` to interpret the expansion as a statement + | +LL | make_item!(A); + | + + +error: expected expression, found keyword `struct` + --> $DIR/issue-34421-mac-expr-bad-stmt-good-add-semi.rs:3:9 + | +LL | struct $a; + | ^^^^^^ expected expression +... +LL | make_item!(B) + | ------------- in this macro invocation + | + = note: the macro call doesn't expand to an expression, but it can expand to a statement + = note: this error originates in the macro `make_item` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add `;` to interpret the expansion as a statement + | +LL | make_item!(B); + | + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-35450.rs b/tests/ui/macros/issue-35450.rs new file mode 100644 index 000000000..ac4c16306 --- /dev/null +++ b/tests/ui/macros/issue-35450.rs @@ -0,0 +1,5 @@ +macro_rules! m { ($($t:tt)*) => { $($t)* } } + +fn main() { + m!($t); //~ ERROR expected expression +} diff --git a/tests/ui/macros/issue-35450.stderr b/tests/ui/macros/issue-35450.stderr new file mode 100644 index 000000000..f2065689f --- /dev/null +++ b/tests/ui/macros/issue-35450.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `$` + --> $DIR/issue-35450.rs:4:8 + | +LL | m!($t); + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-37175.rs b/tests/ui/macros/issue-37175.rs new file mode 100644 index 000000000..9ec9d48d1 --- /dev/null +++ b/tests/ui/macros/issue-37175.rs @@ -0,0 +1,5 @@ +// run-pass +macro_rules! m { (<$t:ty>) => { stringify!($t) } } +fn main() { + println!("{}", m!(>)); +} diff --git a/tests/ui/macros/issue-38715.rs b/tests/ui/macros/issue-38715.rs new file mode 100644 index 000000000..85ed97663 --- /dev/null +++ b/tests/ui/macros/issue-38715.rs @@ -0,0 +1,17 @@ +#[macro_export] +macro_rules! foo { () => {} } + +#[macro_export] +macro_rules! foo { () => {} } //~ ERROR the name `foo` is defined multiple times + +mod inner1 { + #[macro_export] + macro_rules! bar { () => {} } +} + +mod inner2 { + #[macro_export] + macro_rules! bar { () => {} } //~ ERROR the name `bar` is defined multiple times +} + +fn main() {} diff --git a/tests/ui/macros/issue-38715.stderr b/tests/ui/macros/issue-38715.stderr new file mode 100644 index 000000000..828a7f459 --- /dev/null +++ b/tests/ui/macros/issue-38715.stderr @@ -0,0 +1,25 @@ +error[E0428]: the name `foo` is defined multiple times + --> $DIR/issue-38715.rs:5:1 + | +LL | macro_rules! foo { () => {} } + | ---------------- previous definition of the macro `foo` here +... +LL | macro_rules! foo { () => {} } + | ^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the macro namespace of this module + +error[E0428]: the name `bar` is defined multiple times + --> $DIR/issue-38715.rs:14:5 + | +LL | macro_rules! bar { () => {} } + | ---------------- previous definition of the macro `bar` here +... +LL | macro_rules! bar { () => {} } + | ^^^^^^^^^^^^^^^^ `bar` redefined here + | + = note: `bar` must be defined only once in the macro namespace of this module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/macros/issue-39388.rs b/tests/ui/macros/issue-39388.rs new file mode 100644 index 000000000..a8e31a648 --- /dev/null +++ b/tests/ui/macros/issue-39388.rs @@ -0,0 +1,9 @@ +#![allow(unused_macros)] + +macro_rules! assign { + (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?` + $($a)* = $($b)* + } +} + +fn main() {} diff --git a/tests/ui/macros/issue-39388.stderr b/tests/ui/macros/issue-39388.stderr new file mode 100644 index 000000000..62e7dff54 --- /dev/null +++ b/tests/ui/macros/issue-39388.stderr @@ -0,0 +1,8 @@ +error: expected one of: `*`, `+`, or `?` + --> $DIR/issue-39388.rs:4:22 + | +LL | (($($a:tt)*) = ($($b:tt))*) => { + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-39404.rs b/tests/ui/macros/issue-39404.rs new file mode 100644 index 000000000..2229f2c39 --- /dev/null +++ b/tests/ui/macros/issue-39404.rs @@ -0,0 +1,7 @@ +#![allow(unused)] + +macro_rules! m { ($i) => {} } +//~^ ERROR missing fragment specifier +//~| WARN previously accepted + +fn main() {} diff --git a/tests/ui/macros/issue-39404.stderr b/tests/ui/macros/issue-39404.stderr new file mode 100644 index 000000000..3886a70bb --- /dev/null +++ b/tests/ui/macros/issue-39404.stderr @@ -0,0 +1,12 @@ +error: missing fragment specifier + --> $DIR/issue-39404.rs:3:19 + | +LL | macro_rules! m { ($i) => {} } + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + = note: `#[deny(missing_fragment_specifier)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-40469.rs b/tests/ui/macros/issue-40469.rs new file mode 100644 index 000000000..25e08ef85 --- /dev/null +++ b/tests/ui/macros/issue-40469.rs @@ -0,0 +1,9 @@ +// run-pass +// ignore-pretty issue #37195 + +#![allow(dead_code)] + +include!("auxiliary/issue-40469.rs"); +fn f() { m!(); } + +fn main() {} diff --git a/tests/ui/macros/issue-40770.rs b/tests/ui/macros/issue-40770.rs new file mode 100644 index 000000000..c9713c157 --- /dev/null +++ b/tests/ui/macros/issue-40770.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_macros)] +macro_rules! m { + ($e:expr) => { + macro_rules! n { () => { $e } } + } +} + +fn main() { + m!(foo!()); +} diff --git a/tests/ui/macros/issue-41776.rs b/tests/ui/macros/issue-41776.rs new file mode 100644 index 000000000..24696d86d --- /dev/null +++ b/tests/ui/macros/issue-41776.rs @@ -0,0 +1,3 @@ +fn main() { + include!(line!()); //~ ERROR argument must be a string literal +} diff --git a/tests/ui/macros/issue-41776.stderr b/tests/ui/macros/issue-41776.stderr new file mode 100644 index 000000000..e06873b50 --- /dev/null +++ b/tests/ui/macros/issue-41776.stderr @@ -0,0 +1,8 @@ +error: argument must be a string literal + --> $DIR/issue-41776.rs:2:14 + | +LL | include!(line!()); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-41803.rs b/tests/ui/macros/issue-41803.rs new file mode 100644 index 000000000..bccfdc611 --- /dev/null +++ b/tests/ui/macros/issue-41803.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_macro_rules)] + +/// A compile-time map from identifiers to arbitrary (heterogeneous) expressions +macro_rules! ident_map { + ( $name:ident = { $($key:ident => $e:expr,)* } ) => { + macro_rules! $name { + $( + ( $key ) => { $e }; + )* + // Empty invocation expands to nothing. Needed when the map is empty. + () => {}; + } + }; +} + +ident_map!(my_map = { + main => 0, +}); + +fn main() { + my_map!(main); +} diff --git a/tests/ui/macros/issue-42954.fixed b/tests/ui/macros/issue-42954.fixed new file mode 100644 index 000000000..a73054c92 --- /dev/null +++ b/tests/ui/macros/issue-42954.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused_must_use, unused_comparisons)] + +macro_rules! is_plainly_printable { + ($i: ident) => { + ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments + }; +} + +fn main() { + let c = 'a'; + is_plainly_printable!(c); +} diff --git a/tests/ui/macros/issue-42954.rs b/tests/ui/macros/issue-42954.rs new file mode 100644 index 000000000..5f9b0e31d --- /dev/null +++ b/tests/ui/macros/issue-42954.rs @@ -0,0 +1,14 @@ +// run-rustfix + +#![allow(unused_must_use, unused_comparisons)] + +macro_rules! is_plainly_printable { + ($i: ident) => { + $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments + }; +} + +fn main() { + let c = 'a'; + is_plainly_printable!(c); +} diff --git a/tests/ui/macros/issue-42954.stderr b/tests/ui/macros/issue-42954.stderr new file mode 100644 index 000000000..396a91994 --- /dev/null +++ b/tests/ui/macros/issue-42954.stderr @@ -0,0 +1,19 @@ +error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison + --> $DIR/issue-42954.rs:7:19 + | +LL | $i as u32 < 0 + | ^ - interpreted as generic arguments + | | + | not interpreted as comparison +... +LL | is_plainly_printable!(c); + | ------------------------ in this macro invocation + | + = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info) +help: try comparing the cast value + | +LL | ($i as u32) < 0 + | + + + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-44127.rs b/tests/ui/macros/issue-44127.rs new file mode 100644 index 000000000..21b2e6826 --- /dev/null +++ b/tests/ui/macros/issue-44127.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(decl_macro)] + +pub struct Foo { + bar: u32, +} +pub macro pattern($a:pat) { + Foo { bar: $a } +} + +fn main() { + match (Foo { bar: 3 }) { + pattern!(3) => println!("Test OK"), + _ => unreachable!(), + } +} diff --git a/tests/ui/macros/issue-5060.rs b/tests/ui/macros/issue-5060.rs new file mode 100644 index 000000000..c4760bc02 --- /dev/null +++ b/tests/ui/macros/issue-5060.rs @@ -0,0 +1,16 @@ +// run-pass +macro_rules! print_hd_tl { + ($field_hd:ident, $($field_tl:ident),+) => ({ + print!("{}", stringify!($field_hd)); + print!("::["); + $( + print!("{}", stringify!($field_tl)); + print!(", "); + )+ + print!("]\n"); + }) +} + +pub fn main() { + print_hd_tl!(x, y, z, w) +} diff --git a/tests/ui/macros/issue-51848.rs b/tests/ui/macros/issue-51848.rs new file mode 100644 index 000000000..4792bdd64 --- /dev/null +++ b/tests/ui/macros/issue-51848.rs @@ -0,0 +1,20 @@ +// In case of macro expansion, the errors should be matched using the deepest callsite in the +// macro call stack whose span is in the current file + +macro_rules! macro_with_error { + ( ) => { + println!("{"); //~ ERROR invalid + }; +} + +fn foo() { + +} + +fn main() { + macro_with_error!(); + //^ In case of a local macro we want the error to be matched in the macro definition, not here + + println!("}"); //~ ERROR invalid + //^ In case of an external macro we want the error to be matched here +} diff --git a/tests/ui/macros/issue-51848.stderr b/tests/ui/macros/issue-51848.stderr new file mode 100644 index 000000000..c25bedf37 --- /dev/null +++ b/tests/ui/macros/issue-51848.stderr @@ -0,0 +1,24 @@ +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/issue-51848.rs:6:20 + | +LL | println!("{"); + | -^ expected `'}'` in format string + | | + | because of this opening brace +... +LL | macro_with_error!(); + | ------------------- in this macro invocation + | + = note: if you intended to print `{`, you can escape it using `{{` + = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: invalid format string: unmatched `}` found + --> $DIR/issue-51848.rs:18:15 + | +LL | println!("}"); + | ^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-52169.rs b/tests/ui/macros/issue-52169.rs new file mode 100644 index 000000000..f178cd30c --- /dev/null +++ b/tests/ui/macros/issue-52169.rs @@ -0,0 +1,15 @@ +// run-pass + +#[allow(unused_macro_rules)] +macro_rules! a { + ($i:literal) => { "right" }; + ($i:tt) => { "wrong" }; +} + +macro_rules! b { + ($i:literal) => { a!($i) }; +} + +fn main() { + assert_eq!(b!(0), "right"); +} diff --git a/tests/ui/macros/issue-54441.rs b/tests/ui/macros/issue-54441.rs new file mode 100644 index 000000000..b24d7e1f6 --- /dev/null +++ b/tests/ui/macros/issue-54441.rs @@ -0,0 +1,11 @@ +macro_rules! m { + () => { + let //~ ERROR macro expansion ignores token `let` and any following + }; +} + +extern "C" { + m!(); +} + +fn main() {} diff --git a/tests/ui/macros/issue-54441.stderr b/tests/ui/macros/issue-54441.stderr new file mode 100644 index 000000000..bbbca211b --- /dev/null +++ b/tests/ui/macros/issue-54441.stderr @@ -0,0 +1,13 @@ +error: macro expansion ignores token `let` and any following + --> $DIR/issue-54441.rs:3:9 + | +LL | let + | ^^^ +... +LL | m!(); + | ---- caused by the macro expansion here + | + = note: the usage of `m!` is likely invalid in foreign item context + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-57597.rs b/tests/ui/macros/issue-57597.rs new file mode 100644 index 000000000..ebeb3fe07 --- /dev/null +++ b/tests/ui/macros/issue-57597.rs @@ -0,0 +1,80 @@ +// Regression test for #57597. +// +// Make sure that nested matchers work correctly rather than causing an infinite loop or crash. + +// edition:2018 + +macro_rules! foo1 { + ($($($i:ident)?)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo2 { + ($($($i:ident)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo3 { + ($($($i:ident)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo4 { + ($($($($i:ident)?)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo5 { + ($($($($i:ident)*)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo6 { + ($($($($i:ident)?)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo7 { + ($($($($i:ident)?)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo8 { + ($($($($i:ident)*)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo9 { + ($($($($i:ident)?)*)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo10 { + ($($($($i:ident)?)*)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo11 { + ($($($($i:ident)+)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo12 { + ($($($($i:ident)+)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +fn main() { + foo1!(); + foo2!(); + foo3!(); + foo4!(); + foo5!(); + foo6!(); + foo7!(); + foo8!(); + foo9!(); + foo10!(); + foo11!(); + foo12!(); +} diff --git a/tests/ui/macros/issue-57597.stderr b/tests/ui/macros/issue-57597.stderr new file mode 100644 index 000000000..0a02ac8c4 --- /dev/null +++ b/tests/ui/macros/issue-57597.stderr @@ -0,0 +1,74 @@ +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:8:7 + | +LL | ($($($i:ident)?)+) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:13:7 + | +LL | ($($($i:ident)?)*) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:18:7 + | +LL | ($($($i:ident)?)?) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:23:7 + | +LL | ($($($($i:ident)?)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:28:7 + | +LL | ($($($($i:ident)*)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:33:7 + | +LL | ($($($($i:ident)?)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:38:7 + | +LL | ($($($($i:ident)?)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:43:7 + | +LL | ($($($($i:ident)*)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:48:7 + | +LL | ($($($($i:ident)?)*)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:53:7 + | +LL | ($($($($i:ident)?)*)+) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:58:7 + | +LL | ($($($($i:ident)+)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:63:7 + | +LL | ($($($($i:ident)+)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/macros/issue-58490.rs b/tests/ui/macros/issue-58490.rs new file mode 100644 index 000000000..97e71c9a1 --- /dev/null +++ b/tests/ui/macros/issue-58490.rs @@ -0,0 +1,26 @@ +// Regression test for #58490 + +macro_rules! a { + ( @1 $i:item ) => { + a! { @2 $i } + }; + ( @2 $i:item ) => { + $i + }; +} +mod b { + a! { + @1 + #[macro_export] + macro_rules! b { () => () } + } + #[macro_export] + macro_rules! b { () => () } + //~^ ERROR: the name `b` is defined multiple times +} +mod c { + #[allow(unused_imports)] + use crate::b; +} + +fn main() {} diff --git a/tests/ui/macros/issue-58490.stderr b/tests/ui/macros/issue-58490.stderr new file mode 100644 index 000000000..b1f0896f3 --- /dev/null +++ b/tests/ui/macros/issue-58490.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `b` is defined multiple times + --> $DIR/issue-58490.rs:18:5 + | +LL | macro_rules! b { () => () } + | -------------- previous definition of the macro `b` here +... +LL | macro_rules! b { () => () } + | ^^^^^^^^^^^^^^ `b` redefined here + | + = note: `b` must be defined only once in the macro namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/macros/issue-61033-1.rs b/tests/ui/macros/issue-61033-1.rs new file mode 100644 index 000000000..18df3f6ee --- /dev/null +++ b/tests/ui/macros/issue-61033-1.rs @@ -0,0 +1,10 @@ +// Regression test for issue #61033. + +macro_rules! test1 { + ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ ERROR this must repeat at least once +} + +fn main() { + test1!(x,); + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/macros/issue-61033-1.stderr b/tests/ui/macros/issue-61033-1.stderr new file mode 100644 index 000000000..18205c343 --- /dev/null +++ b/tests/ui/macros/issue-61033-1.stderr @@ -0,0 +1,17 @@ +error: this must repeat at least once + --> $DIR/issue-61033-1.rs:4:34 + | +LL | ($x:ident, $($tt:tt)*) => { $($tt)+ } + | ^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-61033-1.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macros/issue-61033-2.rs b/tests/ui/macros/issue-61033-2.rs new file mode 100644 index 000000000..1760ba158 --- /dev/null +++ b/tests/ui/macros/issue-61033-2.rs @@ -0,0 +1,25 @@ +// Regression test for issue #61033. + +macro_rules! test2 { + ( + $(* $id1:ident)* + $(+ $id2:ident)* + ) => { + $( + //~^ ERROR meta-variable `id1` repeats 2 times + //~| ERROR meta-variable `id1` repeats 2 times + $id1 + $id2 // $id1 and $id2 may repeat different numbers of times + )* + } +} + +fn main() { + test2! { + * a * b + + a + b + c + } + test2! { + * a * b + + a + b + c + d + } +} diff --git a/tests/ui/macros/issue-61033-2.stderr b/tests/ui/macros/issue-61033-2.stderr new file mode 100644 index 000000000..cdfe7934a --- /dev/null +++ b/tests/ui/macros/issue-61033-2.stderr @@ -0,0 +1,24 @@ +error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times + --> $DIR/issue-61033-2.rs:8:10 + | +LL | $( + | __________^ +LL | | +LL | | +LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times +LL | | )* + | |_________^ + +error: meta-variable `id1` repeats 2 times, but `id2` repeats 4 times + --> $DIR/issue-61033-2.rs:8:10 + | +LL | $( + | __________^ +LL | | +LL | | +LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times +LL | | )* + | |_________^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-61053-different-kleene.rs b/tests/ui/macros/issue-61053-different-kleene.rs new file mode 100644 index 000000000..9b7babdbb --- /dev/null +++ b/tests/ui/macros/issue-61053-different-kleene.rs @@ -0,0 +1,30 @@ +#![deny(meta_variable_misuse)] + +macro_rules! foo { + () => {}; + ( $( $i:ident = $($j:ident),+ );* ) => { $( $( $i = $j; )* )* }; + //~^ ERROR meta-variable repeats with + ( $( $($j:ident),+ );* ) => { $( $( $j; )+ )+ }; //~ERROR meta-variable repeats with +} + +macro_rules! bar { + () => {}; + (test) => { + macro_rules! nested { + () => {}; + ( $( $i:ident = $($j:ident),+ );* ) => { $( $( $i = $j; )* )* }; + //~^ ERROR meta-variable repeats with + ( $( $($j:ident),+ );* ) => { $( $( $j; )+ )+ }; //~ERROR meta-variable repeats with + } + }; + ( $( $i:ident = $($j:ident),+ );* ) => { + $(macro_rules! $i { + () => { 0 $( + $j )* }; //~ ERROR meta-variable repeats with + })* + }; +} + +fn main() { + foo!(); + bar!(); +} diff --git a/tests/ui/macros/issue-61053-different-kleene.stderr b/tests/ui/macros/issue-61053-different-kleene.stderr new file mode 100644 index 000000000..aa8bac13b --- /dev/null +++ b/tests/ui/macros/issue-61053-different-kleene.stderr @@ -0,0 +1,45 @@ +error: meta-variable repeats with different Kleene operator + --> $DIR/issue-61053-different-kleene.rs:5:57 + | +LL | ( $( $i:ident = $($j:ident),+ );* ) => { $( $( $i = $j; )* )* }; + | - expected repetition ^^ - conflicting repetition + | +note: the lint level is defined here + --> $DIR/issue-61053-different-kleene.rs:1:9 + | +LL | #![deny(meta_variable_misuse)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: meta-variable repeats with different Kleene operator + --> $DIR/issue-61053-different-kleene.rs:7:41 + | +LL | ( $( $($j:ident),+ );* ) => { $( $( $j; )+ )+ }; + | - ^^ - conflicting repetition + | | + | expected repetition + +error: meta-variable repeats with different Kleene operator + --> $DIR/issue-61053-different-kleene.rs:15:65 + | +LL | ( $( $i:ident = $($j:ident),+ );* ) => { $( $( $i = $j; )* )* }; + | - expected repetition ^^ - conflicting repetition + +error: meta-variable repeats with different Kleene operator + --> $DIR/issue-61053-different-kleene.rs:17:49 + | +LL | ( $( $($j:ident),+ );* ) => { $( $( $j; )+ )+ }; + | - ^^ - conflicting repetition + | | + | expected repetition + +error: meta-variable repeats with different Kleene operator + --> $DIR/issue-61053-different-kleene.rs:22:28 + | +LL | ( $( $i:ident = $($j:ident),+ );* ) => { + | - expected repetition +LL | $(macro_rules! $i { +LL | () => { 0 $( + $j )* }; + | ^^ - conflicting repetition + +error: aborting due to 5 previous errors + diff --git a/tests/ui/macros/issue-61053-duplicate-binder.rs b/tests/ui/macros/issue-61053-duplicate-binder.rs new file mode 100644 index 000000000..34aa571c1 --- /dev/null +++ b/tests/ui/macros/issue-61053-duplicate-binder.rs @@ -0,0 +1,14 @@ +#![deny(meta_variable_misuse)] + +macro_rules! foo { + () => {}; + (error) => { + macro_rules! bar { + ($x:tt $x:tt) => { $x }; //~ ERROR duplicate matcher binding + } + }; +} + +fn main() { + foo!(); +} diff --git a/tests/ui/macros/issue-61053-duplicate-binder.stderr b/tests/ui/macros/issue-61053-duplicate-binder.stderr new file mode 100644 index 000000000..5a2af45d0 --- /dev/null +++ b/tests/ui/macros/issue-61053-duplicate-binder.stderr @@ -0,0 +1,16 @@ +error: duplicate matcher binding + --> $DIR/issue-61053-duplicate-binder.rs:7:20 + | +LL | ($x:tt $x:tt) => { $x }; + | -- ^^ + | | + | previous declaration + | +note: the lint level is defined here + --> $DIR/issue-61053-duplicate-binder.rs:1:9 + | +LL | #![deny(meta_variable_misuse)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-61053-missing-repetition.rs b/tests/ui/macros/issue-61053-missing-repetition.rs new file mode 100644 index 000000000..6b36c730b --- /dev/null +++ b/tests/ui/macros/issue-61053-missing-repetition.rs @@ -0,0 +1,28 @@ +#![deny(meta_variable_misuse)] + +macro_rules! foo { + () => {}; + ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* }; + //~^ ERROR variable 'j' is still repeating +} + +macro_rules! bar { + () => {}; + (test) => { + macro_rules! nested { + () => {}; + ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* }; + //~^ ERROR variable 'j' is still repeating + } + }; + ( $( $i:ident = $($j:ident),+ );* ) => { + $(macro_rules! $i { + () => { $j }; //~ ERROR variable 'j' is still repeating + })* + }; +} + +fn main() { + foo!(); + bar!(); +} diff --git a/tests/ui/macros/issue-61053-missing-repetition.stderr b/tests/ui/macros/issue-61053-missing-repetition.stderr new file mode 100644 index 000000000..738f711f0 --- /dev/null +++ b/tests/ui/macros/issue-61053-missing-repetition.stderr @@ -0,0 +1,33 @@ +error: variable 'j' is still repeating at this depth + --> $DIR/issue-61053-missing-repetition.rs:5:52 + | +LL | ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* }; + | - ^^ + | | + | expected repetition + | +note: the lint level is defined here + --> $DIR/issue-61053-missing-repetition.rs:1:9 + | +LL | #![deny(meta_variable_misuse)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: variable 'j' is still repeating at this depth + --> $DIR/issue-61053-missing-repetition.rs:14:60 + | +LL | ($( $i:ident = $($j:ident),+ );*) => { $( $i = $j; )* }; + | - ^^ + | | + | expected repetition + +error: variable 'j' is still repeating at this depth + --> $DIR/issue-61053-missing-repetition.rs:20:21 + | +LL | ( $( $i:ident = $($j:ident),+ );* ) => { + | - expected repetition +LL | $(macro_rules! $i { +LL | () => { $j }; + | ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/issue-61053-unbound.rs b/tests/ui/macros/issue-61053-unbound.rs new file mode 100644 index 000000000..b75cdce0c --- /dev/null +++ b/tests/ui/macros/issue-61053-unbound.rs @@ -0,0 +1,28 @@ +#![deny(meta_variable_misuse)] + +macro_rules! foo { + () => {}; + ($( $i:ident = $($j:ident),+ );*) => { $( $( $i = $k; )+ )* }; + //~^ ERROR unknown macro variable +} + +macro_rules! bar { + () => {}; + (test) => { + macro_rules! nested { + () => {}; + ($( $i:ident = $($j:ident),+ );*) => { $( $( $i = $k; )+ )* }; + //~^ ERROR unknown macro variable + } + }; + ( $( $i:ident = $($j:ident),+ );* ) => { + $(macro_rules! $i { + () => { $( $i = $k)+ }; //~ ERROR unknown macro variable + })* + }; +} + +fn main() { + foo!(); + bar!(); +} diff --git a/tests/ui/macros/issue-61053-unbound.stderr b/tests/ui/macros/issue-61053-unbound.stderr new file mode 100644 index 000000000..0d64effc9 --- /dev/null +++ b/tests/ui/macros/issue-61053-unbound.stderr @@ -0,0 +1,26 @@ +error: unknown macro variable `k` + --> $DIR/issue-61053-unbound.rs:5:55 + | +LL | ($( $i:ident = $($j:ident),+ );*) => { $( $( $i = $k; )+ )* }; + | ^^ + | +note: the lint level is defined here + --> $DIR/issue-61053-unbound.rs:1:9 + | +LL | #![deny(meta_variable_misuse)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unknown macro variable `k` + --> $DIR/issue-61053-unbound.rs:14:63 + | +LL | ($( $i:ident = $($j:ident),+ );*) => { $( $( $i = $k; )+ )* }; + | ^^ + +error: unknown macro variable `k` + --> $DIR/issue-61053-unbound.rs:20:29 + | +LL | () => { $( $i = $k)+ }; + | ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/issue-63102.rs b/tests/ui/macros/issue-63102.rs new file mode 100644 index 000000000..6af5b1868 --- /dev/null +++ b/tests/ui/macros/issue-63102.rs @@ -0,0 +1,8 @@ +// check-pass + +#![feature(decl_macro)] +macro foo { + () => {}, +} + +fn main() {} diff --git a/tests/ui/macros/issue-6596-1.rs b/tests/ui/macros/issue-6596-1.rs new file mode 100644 index 000000000..25f1d6500 --- /dev/null +++ b/tests/ui/macros/issue-6596-1.rs @@ -0,0 +1,10 @@ +macro_rules! e { + ($inp:ident) => ( + $nonexistent + //~^ ERROR expected expression, found `$` + ); +} + +fn main() { + e!(foo); +} diff --git a/tests/ui/macros/issue-6596-1.stderr b/tests/ui/macros/issue-6596-1.stderr new file mode 100644 index 000000000..7ab3685c5 --- /dev/null +++ b/tests/ui/macros/issue-6596-1.stderr @@ -0,0 +1,13 @@ +error: expected expression, found `$` + --> $DIR/issue-6596-1.rs:3:9 + | +LL | $nonexistent + | ^^^^^^^^^^^^ expected expression +... +LL | e!(foo); + | ------- in this macro invocation + | + = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-68058.rs b/tests/ui/macros/issue-68058.rs new file mode 100644 index 000000000..24da2620c --- /dev/null +++ b/tests/ui/macros/issue-68058.rs @@ -0,0 +1,14 @@ +// check-pass + +macro_rules! foo { + ($doc: expr) => { + fn f() { + #[doc = $doc] + () + } + }; +} + +foo!("doc"); + +fn main() {} diff --git a/tests/ui/macros/issue-68060.rs b/tests/ui/macros/issue-68060.rs new file mode 100644 index 000000000..fb40cd538 --- /dev/null +++ b/tests/ui/macros/issue-68060.rs @@ -0,0 +1,15 @@ +fn main() { + (0..) + .map( + #[target_feature(enable = "")] + //~^ ERROR: attribute should be applied to a function + //~| ERROR: feature named `` is not valid + //~| NOTE: `` is not valid for this target + #[track_caller] + //~^ ERROR: `#[track_caller]` on closures is currently unstable + //~| NOTE: see issue #87417 + |_| (), + //~^ NOTE: not a function + ) + .next(); +} diff --git a/tests/ui/macros/issue-68060.stderr b/tests/ui/macros/issue-68060.stderr new file mode 100644 index 000000000..52e6ed92e --- /dev/null +++ b/tests/ui/macros/issue-68060.stderr @@ -0,0 +1,27 @@ +error: attribute should be applied to a function definition + --> $DIR/issue-68060.rs:4:13 + | +LL | #[target_feature(enable = "")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | |_| (), + | ------ not a function definition + +error: the feature named `` is not valid for this target + --> $DIR/issue-68060.rs:4:30 + | +LL | #[target_feature(enable = "")] + | ^^^^^^^^^^^ `` is not valid for this target + +error[E0658]: `#[track_caller]` on closures is currently unstable + --> $DIR/issue-68060.rs:8:13 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #87417 for more information + = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/issue-69838-dir/bar.rs b/tests/ui/macros/issue-69838-dir/bar.rs new file mode 100644 index 000000000..ec12f8c5c --- /dev/null +++ b/tests/ui/macros/issue-69838-dir/bar.rs @@ -0,0 +1,3 @@ +// ignore-test -- this is an auxiliary file as part of another test. + +pub fn i_am_in_bar() {} diff --git a/tests/ui/macros/issue-69838-dir/included.rs b/tests/ui/macros/issue-69838-dir/included.rs new file mode 100644 index 000000000..9900b8fd5 --- /dev/null +++ b/tests/ui/macros/issue-69838-dir/included.rs @@ -0,0 +1,3 @@ +// ignore-test -- this is an auxiliary file as part of another test. + +pub mod bar; diff --git a/tests/ui/macros/issue-69838-mods-relative-to-included-path.rs b/tests/ui/macros/issue-69838-mods-relative-to-included-path.rs new file mode 100644 index 000000000..2a4e97f0e --- /dev/null +++ b/tests/ui/macros/issue-69838-mods-relative-to-included-path.rs @@ -0,0 +1,7 @@ +// check-pass + +include!("issue-69838-dir/included.rs"); + +fn main() { + bar::i_am_in_bar(); +} diff --git a/tests/ui/macros/issue-70446.rs b/tests/ui/macros/issue-70446.rs new file mode 100644 index 000000000..407094d55 --- /dev/null +++ b/tests/ui/macros/issue-70446.rs @@ -0,0 +1,13 @@ +// check-pass + +macro_rules! foo { + ($(: $p:path)? $(: $l:lifetime)? ) => { bar! {$(: $p)? $(: $l)? } }; +} + +macro_rules! bar { + ($(: $p:path)? $(: $l:lifetime)? ) => {}; +} + +foo! {: 'a } + +fn main() {} diff --git a/tests/ui/macros/issue-75982-foreign-macro-weird-mod.rs b/tests/ui/macros/issue-75982-foreign-macro-weird-mod.rs new file mode 100644 index 000000000..e76b09d4b --- /dev/null +++ b/tests/ui/macros/issue-75982-foreign-macro-weird-mod.rs @@ -0,0 +1,13 @@ +// aux-build:issue-75982.rs +// check-pass + +// Regression test for issue #75982 +// Tests that don't ICE when invoking a foreign macro +// that occurs inside a module with a weird parent. + +extern crate issue_75982; + +fn main() { + issue_75982::first_macro!(); + issue_75982::second_macro!(); +} diff --git a/tests/ui/macros/issue-77475.rs b/tests/ui/macros/issue-77475.rs new file mode 100644 index 000000000..7b32a33ea --- /dev/null +++ b/tests/ui/macros/issue-77475.rs @@ -0,0 +1,10 @@ +// check-pass +// Regression test of #77475, this used to be ICE. + +#![feature(decl_macro)] + +use crate as _; + +pub macro ice(){} + +fn main() {} diff --git a/tests/ui/macros/issue-78325-inconsistent-resolution.rs b/tests/ui/macros/issue-78325-inconsistent-resolution.rs new file mode 100644 index 000000000..919eca4f9 --- /dev/null +++ b/tests/ui/macros/issue-78325-inconsistent-resolution.rs @@ -0,0 +1,12 @@ +macro_rules! define_other_core { + ( ) => { + extern crate std as core; + //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern` + }; +} + +fn main() { + core::panic!(); +} + +define_other_core!(); diff --git a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr new file mode 100644 index 000000000..53a0a0793 --- /dev/null +++ b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr @@ -0,0 +1,13 @@ +error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` + --> $DIR/issue-78325-inconsistent-resolution.rs:3:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-78333.rs b/tests/ui/macros/issue-78333.rs new file mode 100644 index 000000000..c376f2067 --- /dev/null +++ b/tests/ui/macros/issue-78333.rs @@ -0,0 +1,13 @@ +// build-pass + +#![no_implicit_prelude] + +fn main() { + ::std::panic!(); + ::std::todo!(); + ::std::unimplemented!(); + ::std::assert_eq!(0, 0); + ::std::assert_ne!(0, 1); + ::std::dbg!(123); + ::std::unreachable!(); +} diff --git a/tests/ui/macros/issue-78892-substitution-in-statement-attr.rs b/tests/ui/macros/issue-78892-substitution-in-statement-attr.rs new file mode 100644 index 000000000..9d1fae7a2 --- /dev/null +++ b/tests/ui/macros/issue-78892-substitution-in-statement-attr.rs @@ -0,0 +1,14 @@ +// check-pass + +// regression test for #78892 + +macro_rules! mac { + ($lint_name:ident) => {{ + #[allow($lint_name)] + let _ = (); + }}; +} + +fn main() { + mac!(dead_code) +} diff --git a/tests/ui/macros/issue-81006.rs b/tests/ui/macros/issue-81006.rs new file mode 100644 index 000000000..602eb5974 --- /dev/null +++ b/tests/ui/macros/issue-81006.rs @@ -0,0 +1,10 @@ +// check-fail + +// First format below would cause a panic, second would generate error with incorrect span + +fn main() { + let _ = format!("→{}→\n"); + //~^ ERROR 1 positional argument in format string, but no arguments were given + let _ = format!("→{} \n"); + //~^ ERROR 1 positional argument in format string, but no arguments were given +} diff --git a/tests/ui/macros/issue-81006.stderr b/tests/ui/macros/issue-81006.stderr new file mode 100644 index 000000000..14a8cbe01 --- /dev/null +++ b/tests/ui/macros/issue-81006.stderr @@ -0,0 +1,14 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-81006.rs:6:23 + | +LL | let _ = format!("→{}→\n"); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-81006.rs:8:23 + | +LL | let _ = format!("→{} \n"); + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-83340.rs b/tests/ui/macros/issue-83340.rs new file mode 100644 index 000000000..d26200295 --- /dev/null +++ b/tests/ui/macros/issue-83340.rs @@ -0,0 +1,8 @@ +// check-fail + +fn main() { + println!( + "\ +\n {} │", //~ ERROR: 1 positional argument in format string, but no arguments were given + ); +} diff --git a/tests/ui/macros/issue-83340.stderr b/tests/ui/macros/issue-83340.stderr new file mode 100644 index 000000000..1935de02b --- /dev/null +++ b/tests/ui/macros/issue-83340.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-83340.rs:6:4 + | +LL | \n {} │", + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-83344.rs b/tests/ui/macros/issue-83344.rs new file mode 100644 index 000000000..c5f7f7235 --- /dev/null +++ b/tests/ui/macros/issue-83344.rs @@ -0,0 +1,6 @@ +// check-fail + +fn main() { + println!("{}\ +"); //~^ ERROR: 1 positional argument in format string, but no arguments were given +} diff --git a/tests/ui/macros/issue-83344.stderr b/tests/ui/macros/issue-83344.stderr new file mode 100644 index 000000000..1ef70f87a --- /dev/null +++ b/tests/ui/macros/issue-83344.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-83344.rs:4:15 + | +LL | println!("{}\ + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-84195-lint-anon-const.rs b/tests/ui/macros/issue-84195-lint-anon-const.rs new file mode 100644 index 000000000..71c768320 --- /dev/null +++ b/tests/ui/macros/issue-84195-lint-anon-const.rs @@ -0,0 +1,14 @@ +// Regression test for issue #84195 +// Checks that we properly fire lints that occur inside +// anon consts. + +#![deny(semicolon_in_expressions_from_macros)] + +macro_rules! len { + () => { 0; }; //~ ERROR trailing semicolon + //~| WARN this was previously accepted +} + +fn main() { + let val: [u8; len!()] = []; +} diff --git a/tests/ui/macros/issue-84195-lint-anon-const.stderr b/tests/ui/macros/issue-84195-lint-anon-const.stderr new file mode 100644 index 000000000..29ccd17e0 --- /dev/null +++ b/tests/ui/macros/issue-84195-lint-anon-const.stderr @@ -0,0 +1,39 @@ +error: trailing semicolon in macro used in expression position + --> $DIR/issue-84195-lint-anon-const.rs:8:14 + | +LL | () => { 0; }; + | ^ +... +LL | let val: [u8; len!()] = []; + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/issue-84195-lint-anon-const.rs:5:9 + | +LL | #![deny(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +Future incompatibility report: Future breakage diagnostic: +error: trailing semicolon in macro used in expression position + --> $DIR/issue-84195-lint-anon-const.rs:8:14 + | +LL | () => { 0; }; + | ^ +... +LL | let val: [u8; len!()] = []; + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 +note: the lint level is defined here + --> $DIR/issue-84195-lint-anon-const.rs:5:9 + | +LL | #![deny(semicolon_in_expressions_from_macros)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/macros/issue-84429-matches-edition.rs b/tests/ui/macros/issue-84429-matches-edition.rs new file mode 100644 index 000000000..53f134c26 --- /dev/null +++ b/tests/ui/macros/issue-84429-matches-edition.rs @@ -0,0 +1,9 @@ +// edition:2021 +// check-pass +// +// Regression test for issue #84429 +// Tests that we can properly invoke `matches!` from a 2021-edition crate. + +fn main() { + let _b = matches!(b'3', b'0' ..= b'9'); +} diff --git a/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.rs b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.rs new file mode 100644 index 000000000..7a1e62d49 --- /dev/null +++ b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.rs @@ -0,0 +1,16 @@ +// Regression test for #84632: Recursion limit is ignored +// for builtin macros that eagerly expands. + +#![recursion_limit = "15"] +macro_rules! a { + () => (""); + (A) => (concat!("", a!())); + (A, $($A:ident),*) => (concat!("", a!($($A),*))) + //~^ ERROR recursion limit reached + //~| HELP consider increasing the recursion limit +} + +fn main() { + a!(A, A, A, A, A); + a!(A, A, A, A, A, A, A, A, A, A, A); +} diff --git a/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr new file mode 100644 index 000000000..e266617bd --- /dev/null +++ b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr @@ -0,0 +1,14 @@ +error: recursion limit reached while expanding `concat!` + --> $DIR/issue-84632-eager-expansion-recursion-limit.rs:8:28 + | +LL | (A, $($A:ident),*) => (concat!("", a!($($A),*))) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | a!(A, A, A, A, A, A, A, A, A, A, A); + | ----------------------------------- in this macro invocation + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`) + = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-86082-option-env-invalid-char.rs b/tests/ui/macros/issue-86082-option-env-invalid-char.rs new file mode 100644 index 000000000..b556b24d6 --- /dev/null +++ b/tests/ui/macros/issue-86082-option-env-invalid-char.rs @@ -0,0 +1,10 @@ +// check-pass +// +// Regression test for issue #86082 +// +// Checks that option_env! does not panic on receiving an invalid +// environment variable name. + +fn main() { + option_env!("\0="); +} diff --git a/tests/ui/macros/issue-86865.rs b/tests/ui/macros/issue-86865.rs new file mode 100644 index 000000000..01e0a20a5 --- /dev/null +++ b/tests/ui/macros/issue-86865.rs @@ -0,0 +1,11 @@ +use std::fmt::Write; + +fn main() { + println!(b"foo"); + //~^ ERROR format argument must be a string literal + //~| HELP consider removing the leading `b` + let mut s = String::new(); + write!(s, b"foo{}", "bar"); + //~^ ERROR format argument must be a string literal + //~| HELP consider removing the leading `b` +} diff --git a/tests/ui/macros/issue-86865.stderr b/tests/ui/macros/issue-86865.stderr new file mode 100644 index 000000000..eed755366 --- /dev/null +++ b/tests/ui/macros/issue-86865.stderr @@ -0,0 +1,18 @@ +error: format argument must be a string literal + --> $DIR/issue-86865.rs:4:14 + | +LL | println!(b"foo"); + | -^^^^^ + | | + | help: consider removing the leading `b` + +error: format argument must be a string literal + --> $DIR/issue-86865.rs:8:15 + | +LL | write!(s, b"foo{}", "bar"); + | -^^^^^^^ + | | + | help: consider removing the leading `b` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/issue-8709.rs b/tests/ui/macros/issue-8709.rs new file mode 100644 index 000000000..ea7525d44 --- /dev/null +++ b/tests/ui/macros/issue-8709.rs @@ -0,0 +1,14 @@ +// run-pass + +macro_rules! sty { + ($t:ty) => (stringify!($t)) +} + +macro_rules! spath { + ($t:path) => (stringify!($t)) +} + +fn main() { + assert_eq!(sty!(isize), "isize"); + assert_eq!(spath!(std::option), "std::option"); +} diff --git a/tests/ui/macros/issue-87877.rs b/tests/ui/macros/issue-87877.rs new file mode 100644 index 000000000..a40e2c5f9 --- /dev/null +++ b/tests/ui/macros/issue-87877.rs @@ -0,0 +1,25 @@ +// check-pass + +macro_rules! two_items { + () => { + extern "C" {} + extern "C" {} + }; +} + +macro_rules! single_expr_funneler { + ($expr:expr) => { + $expr; // note the semicolon, it changes the statement kind during parsing + }; +} + +macro_rules! single_item_funneler { + ($item:item) => { + $item + }; +} + +fn main() { + single_expr_funneler! { two_items! {} } + single_item_funneler! { two_items! {} } +} diff --git a/tests/ui/macros/issue-88206.rs b/tests/ui/macros/issue-88206.rs new file mode 100644 index 000000000..14e2f6606 --- /dev/null +++ b/tests/ui/macros/issue-88206.rs @@ -0,0 +1,66 @@ +// compile-flags: -Z deduplicate-diagnostics=yes + +#![warn(unused_imports)] + +use std::str::*; +//~^ NOTE `from_utf8` is imported here, but it is a function +//~| NOTE `from_utf8_mut` is imported here, but it is a function +//~| NOTE `from_utf8_unchecked` is imported here, but it is a function + +mod hey { + pub trait Serialize {} + pub trait Deserialize {} + + pub struct X(i32); +} + +use hey::{Serialize, Deserialize, X}; +//~^ NOTE `Serialize` is imported here, but it is only a trait, without a derive macro +//~| NOTE `Deserialize` is imported here, but it is a trait +//~| NOTE `X` is imported here, but it is a struct + +#[derive(Serialize)] +//~^ ERROR cannot find derive macro `Serialize` +struct A; + +#[derive(from_utf8_mut)] +//~^ ERROR cannot find derive macro `from_utf8_mut` +struct B; + +#[derive(println)] +//~^ ERROR cannot find derive macro `println` +//~| NOTE `println` is in scope, but it is a function-like macro +struct C; + +#[Deserialize] +//~^ ERROR cannot find attribute `Deserialize` +struct D; + +#[from_utf8_unchecked] +//~^ ERROR cannot find attribute `from_utf8_unchecked` +struct E; + +#[println] +//~^ ERROR cannot find attribute `println` +//~| NOTE `println` is in scope, but it is a function-like macro +struct F; + +fn main() { + from_utf8!(); + //~^ ERROR cannot find macro `from_utf8` + + Box!(); + //~^ ERROR cannot find macro `Box` + //~| NOTE `Box` is in scope, but it is a struct + + Copy!(); + //~^ ERROR cannot find macro `Copy` + //~| NOTE `Copy` is in scope, but it is a derive macro + + test!(); + //~^ ERROR cannot find macro `test` + //~| NOTE `test` is in scope, but it is an attribute + + X!(); + //~^ ERROR cannot find macro `X` +} diff --git a/tests/ui/macros/issue-88206.stderr b/tests/ui/macros/issue-88206.stderr new file mode 100644 index 000000000..f7f5b5648 --- /dev/null +++ b/tests/ui/macros/issue-88206.stderr @@ -0,0 +1,114 @@ +error: cannot find macro `X` in this scope + --> $DIR/issue-88206.rs:64:5 + | +LL | X!(); + | ^ + | +note: `X` is imported here, but it is a struct, not a macro + --> $DIR/issue-88206.rs:17:35 + | +LL | use hey::{Serialize, Deserialize, X}; + | ^ + +error: cannot find macro `test` in this scope + --> $DIR/issue-88206.rs:60:5 + | +LL | test!(); + | ^^^^ + | + = note: `test` is in scope, but it is an attribute: `#[test]` + +error: cannot find macro `Copy` in this scope + --> $DIR/issue-88206.rs:56:5 + | +LL | Copy!(); + | ^^^^ + | + = note: `Copy` is in scope, but it is a derive macro: `#[derive(Copy)]` + +error: cannot find macro `Box` in this scope + --> $DIR/issue-88206.rs:52:5 + | +LL | Box!(); + | ^^^ + | + = note: `Box` is in scope, but it is a struct, not a macro + +error: cannot find macro `from_utf8` in this scope + --> $DIR/issue-88206.rs:49:5 + | +LL | from_utf8!(); + | ^^^^^^^^^ + | +note: `from_utf8` is imported here, but it is a function, not a macro + --> $DIR/issue-88206.rs:5:5 + | +LL | use std::str::*; + | ^^^^^^^^^^^ + +error: cannot find attribute `println` in this scope + --> $DIR/issue-88206.rs:43:3 + | +LL | #[println] + | ^^^^^^^ + | + = note: `println` is in scope, but it is a function-like macro + +error: cannot find attribute `from_utf8_unchecked` in this scope + --> $DIR/issue-88206.rs:39:3 + | +LL | #[from_utf8_unchecked] + | ^^^^^^^^^^^^^^^^^^^ + | +note: `from_utf8_unchecked` is imported here, but it is a function, not an attribute + --> $DIR/issue-88206.rs:5:5 + | +LL | use std::str::*; + | ^^^^^^^^^^^ + +error: cannot find attribute `Deserialize` in this scope + --> $DIR/issue-88206.rs:35:3 + | +LL | #[Deserialize] + | ^^^^^^^^^^^ + | +note: `Deserialize` is imported here, but it is a trait, not an attribute + --> $DIR/issue-88206.rs:17:22 + | +LL | use hey::{Serialize, Deserialize, X}; + | ^^^^^^^^^^^ + +error: cannot find derive macro `println` in this scope + --> $DIR/issue-88206.rs:30:10 + | +LL | #[derive(println)] + | ^^^^^^^ + | + = note: `println` is in scope, but it is a function-like macro + +error: cannot find derive macro `from_utf8_mut` in this scope + --> $DIR/issue-88206.rs:26:10 + | +LL | #[derive(from_utf8_mut)] + | ^^^^^^^^^^^^^ + | +note: `from_utf8_mut` is imported here, but it is a function, not a derive macro + --> $DIR/issue-88206.rs:5:5 + | +LL | use std::str::*; + | ^^^^^^^^^^^ + +error: cannot find derive macro `Serialize` in this scope + --> $DIR/issue-88206.rs:22:10 + | +LL | #[derive(Serialize)] + | ^^^^^^^^^ + | +note: `Serialize` is imported here, but it is only a trait, without a derive macro + --> $DIR/issue-88206.rs:17:11 + | +LL | use hey::{Serialize, Deserialize, X}; + | ^^^^^^^^^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/macros/issue-88228.rs b/tests/ui/macros/issue-88228.rs new file mode 100644 index 000000000..60ba2eab7 --- /dev/null +++ b/tests/ui/macros/issue-88228.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z deduplicate-diagnostics=yes +// edition:2018 + +mod hey { + pub use Copy as Bla; + pub use std::println as bla; +} + +#[derive(Bla)] +//~^ ERROR cannot find derive macro `Bla` +//~| HELP consider importing this derive macro +struct A; + +#[derive(println)] +//~^ ERROR cannot find derive macro `println` +//~|`println` is in scope, but it is a function-like macro +struct B; + +fn main() { + bla!(); + //~^ ERROR cannot find macro `bla` + //~| HELP consider importing this macro +} diff --git a/tests/ui/macros/issue-88228.stderr b/tests/ui/macros/issue-88228.stderr new file mode 100644 index 000000000..fe8a1deae --- /dev/null +++ b/tests/ui/macros/issue-88228.stderr @@ -0,0 +1,28 @@ +error: cannot find macro `bla` in this scope + --> $DIR/issue-88228.rs:20:5 + | +LL | bla!(); + | ^^^ + | + = help: consider importing this macro: + crate::hey::bla + +error: cannot find derive macro `println` in this scope + --> $DIR/issue-88228.rs:14:10 + | +LL | #[derive(println)] + | ^^^^^^^ + | + = note: `println` is in scope, but it is a function-like macro + +error: cannot find derive macro `Bla` in this scope + --> $DIR/issue-88228.rs:9:10 + | +LL | #[derive(Bla)] + | ^^^ + | + = help: consider importing this derive macro: + crate::hey::Bla + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/issue-8851.rs b/tests/ui/macros/issue-8851.rs new file mode 100644 index 000000000..faacfe5f8 --- /dev/null +++ b/tests/ui/macros/issue-8851.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +// after fixing #9384 and implementing hygiene for match bindings, +// this now fails because the insertion of the 'y' into the match +// doesn't cause capture. Making this macro hygienic (as I've done) +// could very well make this test case completely pointless.... + +// pretty-expanded FIXME #23616 + +enum T { + A(isize), + B(usize) +} + +macro_rules! test { + ($id:ident, $e:expr) => ( + fn foo(t: T) -> isize { + match t { + T::A($id) => $e, + T::B($id) => $e + } + } + ) +} + +test!(y, 10 + (y as isize)); + +pub fn main() { + foo(T::A(20)); +} diff --git a/tests/ui/macros/issue-92267.rs b/tests/ui/macros/issue-92267.rs new file mode 100644 index 000000000..f1daaeb74 --- /dev/null +++ b/tests/ui/macros/issue-92267.rs @@ -0,0 +1,3 @@ +// check-fail + +pub fn main() { println!("🦀%%%", 0) } //~ ERROR argument never used diff --git a/tests/ui/macros/issue-92267.stderr b/tests/ui/macros/issue-92267.stderr new file mode 100644 index 000000000..5359f68cd --- /dev/null +++ b/tests/ui/macros/issue-92267.stderr @@ -0,0 +1,16 @@ +error: argument never used + --> $DIR/issue-92267.rs:3:34 + | +LL | pub fn main() { println!("🦀%%%", 0) } + | ^ argument never used + | +note: format specifiers use curly braces, and the conversion specifier ` + ` is unknown or unsupported + --> $DIR/issue-92267.rs:3:30 + | +LL | pub fn main() { println!("🦀%%%", 0) } + | ^^ + = note: printf formatting is not supported; see the documentation for `std::fmt` + +error: aborting due to previous error + diff --git a/tests/ui/macros/issue-95267.rs b/tests/ui/macros/issue-95267.rs new file mode 100644 index 000000000..a2fe402bc --- /dev/null +++ b/tests/ui/macros/issue-95267.rs @@ -0,0 +1,14 @@ +// check-pass + +// The doc comment here is ignored. This is a bug, but #95267 showed that +// existing programs rely on this behaviour, and changing it would require some +// care and a transition period. +macro_rules! f { + ( + /// ab + ) => {}; +} + +fn main() { + f!(); +} diff --git a/tests/ui/macros/issue-95533.rs b/tests/ui/macros/issue-95533.rs new file mode 100644 index 000000000..905c14dc5 --- /dev/null +++ b/tests/ui/macros/issue-95533.rs @@ -0,0 +1,8 @@ +// check-pass + +#![no_implicit_prelude] +// the macro should not rely on the prelude being imported +::std::thread_local! { static P: () = (); } +::std::thread_local! { static Q: () = const { () }; } + +fn main () {} diff --git a/tests/ui/macros/issue-98466-allow.rs b/tests/ui/macros/issue-98466-allow.rs new file mode 100644 index 000000000..c260148c1 --- /dev/null +++ b/tests/ui/macros/issue-98466-allow.rs @@ -0,0 +1,16 @@ +// check-pass +#![allow(named_arguments_used_positionally)] + +fn main() { + let mut _x: usize; + _x = 1; + println!("_x is {}", _x = 5); + println!("_x is {}", y = _x); + println!("first positional arg {}, second positional arg {}, _x is {}", 1, 2, y = _x); + + let mut _x: usize; + _x = 1; + let _f = format!("_x is {}", _x = 5); + let _f = format!("_x is {}", y = _x); + let _f = format!("first positional arg {}, second positional arg {}, _x is {}", 1, 2, y = _x); +} diff --git a/tests/ui/macros/issue-98466.fixed b/tests/ui/macros/issue-98466.fixed new file mode 100644 index 000000000..e46e22f00 --- /dev/null +++ b/tests/ui/macros/issue-98466.fixed @@ -0,0 +1,51 @@ +// check-pass +// run-rustfix + +fn main() { + let mut _x: usize; + _x = 1; + println!("_x is {_x}", _x = 5); + //~^ WARNING named argument `_x` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + println!("_x is {y}", y = _x); + //~^ WARNING named argument `y` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + println!("first positional arg {}, second positional arg {}, _x is {y}", 1, 2, y = _x); + //~^ WARNING named argument `y` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + let mut _x: usize; + _x = 1; + let _f = format!("_x is {_x}", _x = 5); + //~^ WARNING named argument `_x` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + let _f = format!("_x is {y}", y = _x); + //~^ WARNING named argument `y` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + let _f = format!("first positional arg {}, second positional arg {}, _x is {y}", 1, 2, y = _x); + //~^ WARNING named argument `y` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + let s = "0.009"; + // Confirm that named arguments used in formatting are correctly considered. + println!(".{:0 $DIR/issue-98466.rs:7:26 + | +LL | println!("_x is {}", _x = 5); + | -- ^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `_x` by position + | + = note: `#[warn(named_arguments_used_positionally)]` on by default +help: use the named argument by name to avoid ambiguity + | +LL | println!("_x is {_x}", _x = 5); + | ++ + +warning: named argument `y` is not used by name + --> $DIR/issue-98466.rs:10:26 + | +LL | println!("_x is {}", y = _x); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("_x is {y}", y = _x); + | + + +warning: named argument `y` is not used by name + --> $DIR/issue-98466.rs:13:83 + | +LL | println!("first positional arg {}, second positional arg {}, _x is {}", 1, 2, y = _x); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("first positional arg {}, second positional arg {}, _x is {y}", 1, 2, y = _x); + | + + +warning: named argument `_x` is not used by name + --> $DIR/issue-98466.rs:19:34 + | +LL | let _f = format!("_x is {}", _x = 5); + | -- ^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `_x` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | let _f = format!("_x is {_x}", _x = 5); + | ++ + +warning: named argument `y` is not used by name + --> $DIR/issue-98466.rs:22:34 + | +LL | let _f = format!("_x is {}", y = _x); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | let _f = format!("_x is {y}", y = _x); + | + + +warning: named argument `y` is not used by name + --> $DIR/issue-98466.rs:25:91 + | +LL | let _f = format!("first positional arg {}, second positional arg {}, _x is {}", 1, 2, y = _x); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | let _f = format!("first positional arg {}, second positional arg {}, _x is {y}", 1, 2, y = _x); + | + + +warning: 6 warnings emitted + diff --git a/tests/ui/macros/issue-99261.rs b/tests/ui/macros/issue-99261.rs new file mode 100644 index 000000000..40d26d08c --- /dev/null +++ b/tests/ui/macros/issue-99261.rs @@ -0,0 +1,17 @@ +// check-pass + +#![deny(named_arguments_used_positionally)] + +fn main() { + let value: f64 = 314.15926; + let digits_before_decimal = 1; + let digits_after_decimal = 2; + let width = digits_before_decimal + 1 + digits_after_decimal; + + println!( + "{value:0>width$.digits_after_decimal$}", + value = value, + width = width, + digits_after_decimal = digits_after_decimal, + ); +} diff --git a/tests/ui/macros/issue-99265.fixed b/tests/ui/macros/issue-99265.fixed new file mode 100644 index 000000000..f3be9c628 --- /dev/null +++ b/tests/ui/macros/issue-99265.fixed @@ -0,0 +1,139 @@ +// check-pass +// run-rustfix + +fn main() { + println!("{b} {a}", a=1, b=2); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("{} {a} {b} {c} {d}", 0, a=1, b=2, c=3, d=4); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `d` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:width$}!", "x", width = 5); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!( + "{}, Hello {f:width$.precision$} {g:width2$.precision2$}! {f}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + 1, + f = 0.02f32, + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + width = 5, + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + precision = 2, + //~^ WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + g = 0.02f32, + //~^ WARNING named argument `g` is not used by name [named_arguments_used_positionally] + width2 = 5, + //~^ WARNING named argument `width2` is not used by name [named_arguments_used_positionally + precision2 = 2 + //~^ WARNING named argument `precision2` is not used by name [named_arguments_used_positionally] + ); + + println!("Hello {f:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + + let width = 5; + let precision = 2; + println!("Hello {f:width$.precision$}!", f = 0.02f32); + + let val = 5; + println!("{v:v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{v:v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{v:v$.v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{v:v$.v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("{a} {a} {a}", a = 1); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("aaaaaaaaaaaaaaa\ + {a:b$.c$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("aaaaaaaaaaaaaaa\ + {a:b$.c$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("{{{x:width$.precision$}}}", x = 1.0, width = 3, precision = 2); + //~^ WARNING named argument `x` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `width` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity +} diff --git a/tests/ui/macros/issue-99265.rs b/tests/ui/macros/issue-99265.rs new file mode 100644 index 000000000..e7cf60876 --- /dev/null +++ b/tests/ui/macros/issue-99265.rs @@ -0,0 +1,139 @@ +// check-pass +// run-rustfix + +fn main() { + println!("{b} {}", a=1, b=2); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `d` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:1$}!", "x", width = 5); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!( + "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + 1, + f = 0.02f32, + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + width = 5, + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + precision = 2, + //~^ WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + g = 0.02f32, + //~^ WARNING named argument `g` is not used by name [named_arguments_used_positionally] + width2 = 5, + //~^ WARNING named argument `width2` is not used by name [named_arguments_used_positionally + precision2 = 2 + //~^ WARNING named argument `precision2` is not used by name [named_arguments_used_positionally] + ); + + println!("Hello {:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {0:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + + let width = 5; + let precision = 2; + println!("Hello {f:width$.precision$}!", f = 0.02f32); + + let val = 5; + println!("{:0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{0:0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{:0$.0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{0:0$.0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("{} {a} {0}", a = 1); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("aaaaaaaaaaaaaaa\ + {:1$.2$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("aaaaaaaaaaaaaaa\ + {0:1$.2$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + //~^ WARNING named argument `x` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `width` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity +} diff --git a/tests/ui/macros/issue-99265.stderr b/tests/ui/macros/issue-99265.stderr new file mode 100644 index 000000000..9185dbff6 --- /dev/null +++ b/tests/ui/macros/issue-99265.stderr @@ -0,0 +1,562 @@ +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:5:24 + | +LL | println!("{b} {}", a=1, b=2); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `a` by position + | + = note: `#[warn(named_arguments_used_positionally)]` on by default +help: use the named argument by name to avoid ambiguity + | +LL | println!("{b} {a}", a=1, b=2); + | + + +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:9:35 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `a` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {a} {} {} {}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `b` is not used by name + --> $DIR/issue-99265.rs:9:40 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `b` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {} {b} {} {}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `c` is not used by name + --> $DIR/issue-99265.rs:9:45 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `c` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {} {} {c} {}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `d` is not used by name + --> $DIR/issue-99265.rs:9:50 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `d` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {} {} {} {d}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `width` is not used by name + --> $DIR/issue-99265.rs:19:35 + | +LL | println!("Hello {:1$}!", "x", width = 5); + | -- ^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `width` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {:width$}!", "x", width = 5); + | ~~~~~~ + +warning: named argument `f` is not used by name + --> $DIR/issue-99265.rs:23:33 + | +LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -------- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | + + +warning: named argument `precision` is not used by name + --> $DIR/issue-99265.rs:23:57 + | +LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -- ^^^^^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `precision` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {:1$.precision$}!", f = 0.02f32, width = 5, precision = 2); + | ~~~~~~~~~~ + +warning: named argument `width` is not used by name + --> $DIR/issue-99265.rs:23:46 + | +LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -- ^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `width` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2); + | ~~~~~~ + +warning: named argument `f` is not used by name + --> $DIR/issue-99265.rs:31:34 + | +LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | --------- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | ~ + +warning: named argument `precision` is not used by name + --> $DIR/issue-99265.rs:31:58 + | +LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -- ^^^^^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `precision` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {0:1$.precision$}!", f = 0.02f32, width = 5, precision = 2); + | ~~~~~~~~~~ + +warning: named argument `width` is not used by name + --> $DIR/issue-99265.rs:31:47 + | +LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -- ^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `width` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2); + | ~~~~~~ + +warning: named argument `f` is not used by name + --> $DIR/issue-99265.rs:49:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | --------- this formatting argument uses named argument `f` by position +... +LL | f = 0.02f32, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {f:2$.3$} {4:5$.6$}! {1}", + | ~ + +warning: named argument `precision` is not used by name + --> $DIR/issue-99265.rs:54:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `precision` by position +... +LL | precision = 2, + | ^^^^^^^^^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:2$.precision$} {4:5$.6$}! {1}", + | ~~~~~~~~~~ + +warning: named argument `width` is not used by name + --> $DIR/issue-99265.rs:52:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `width` by position +... +LL | width = 5, + | ^^^^^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:width$.3$} {4:5$.6$}! {1}", + | ~~~~~~ + +warning: named argument `g` is not used by name + --> $DIR/issue-99265.rs:56:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | --------- this formatting argument uses named argument `g` by position +... +LL | g = 0.02f32, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:2$.3$} {g:5$.6$}! {1}", + | ~ + +warning: named argument `precision2` is not used by name + --> $DIR/issue-99265.rs:60:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `precision2` by position +... +LL | precision2 = 2 + | ^^^^^^^^^^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:2$.3$} {4:5$.precision2$}! {1}", + | ~~~~~~~~~~~ + +warning: named argument `width2` is not used by name + --> $DIR/issue-99265.rs:58:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `width2` by position +... +LL | width2 = 5, + | ^^^^^^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}", + | ~~~~~~~ + +warning: named argument `f` is not used by name + --> $DIR/issue-99265.rs:49:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | --- this formatting argument uses named argument `f` by position +... +LL | f = 0.02f32, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {f}", + | ~ + +warning: named argument `f` is not used by name + --> $DIR/issue-99265.rs:64:31 + | +LL | println!("Hello {:0.1}!", f = 0.02f32); + | ------ ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f:0.1}!", f = 0.02f32); + | + + +warning: named argument `f` is not used by name + --> $DIR/issue-99265.rs:68:32 + | +LL | println!("Hello {0:0.1}!", f = 0.02f32); + | ------- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f:0.1}!", f = 0.02f32); + | ~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:79:23 + | +LL | println!("{:0$}", v = val); + | ----- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{v:0$}", v = val); + | + + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:79:23 + | +LL | println!("{:0$}", v = val); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{:v$}", v = val); + | ~~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:84:24 + | +LL | println!("{0:0$}", v = val); + | ------ ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{v:0$}", v = val); + | ~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:84:24 + | +LL | println!("{0:0$}", v = val); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{0:v$}", v = val); + | ~~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:89:26 + | +LL | println!("{:0$.0$}", v = val); + | -------- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{v:0$.0$}", v = val); + | + + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:89:26 + | +LL | println!("{:0$.0$}", v = val); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{:0$.v$}", v = val); + | ~~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:89:26 + | +LL | println!("{:0$.0$}", v = val); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{:v$.0$}", v = val); + | ~~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:96:27 + | +LL | println!("{0:0$.0$}", v = val); + | --------- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{v:0$.0$}", v = val); + | ~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:96:27 + | +LL | println!("{0:0$.0$}", v = val); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{0:0$.v$}", v = val); + | ~~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:96:27 + | +LL | println!("{0:0$.0$}", v = val); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `v` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{0:v$.0$}", v = val); + | ~~ + +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:104:28 + | +LL | println!("{} {a} {0}", a = 1); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `a` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{a} {a} {0}", a = 1); + | + + +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:104:28 + | +LL | println!("{} {a} {0}", a = 1); + | --- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `a` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {a} {a}", a = 1); + | ~ + +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:115:14 + | +LL | {:1$.2$}", + | -------- this formatting argument uses named argument `a` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {a:1$.2$}", + | + + +warning: named argument `c` is not used by name + --> $DIR/issue-99265.rs:115:30 + | +LL | {:1$.2$}", + | -- this formatting argument uses named argument `c` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {:1$.c$}", + | ~~ + +warning: named argument `b` is not used by name + --> $DIR/issue-99265.rs:115:23 + | +LL | {:1$.2$}", + | -- this formatting argument uses named argument `b` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {:b$.2$}", + | ~~ + +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:126:14 + | +LL | {0:1$.2$}", + | --------- this formatting argument uses named argument `a` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {a:1$.2$}", + | ~ + +warning: named argument `c` is not used by name + --> $DIR/issue-99265.rs:126:30 + | +LL | {0:1$.2$}", + | -- this formatting argument uses named argument `c` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {0:1$.c$}", + | ~~ + +warning: named argument `b` is not used by name + --> $DIR/issue-99265.rs:126:23 + | +LL | {0:1$.2$}", + | -- this formatting argument uses named argument `b` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {0:b$.2$}", + | ~~ + +warning: named argument `x` is not used by name + --> $DIR/issue-99265.rs:132:30 + | +LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | -------- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `x` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | + + +warning: named argument `precision` is not used by name + --> $DIR/issue-99265.rs:132:50 + | +LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | -- ^^^^^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `precision` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{{{:1$.precision$}}}", x = 1.0, width = 3, precision = 2); + | ~~~~~~~~~~ + +warning: named argument `width` is not used by name + --> $DIR/issue-99265.rs:132:39 + | +LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | -- ^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `width` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2); + | ~~~~~~ + +warning: 42 warnings emitted + diff --git a/tests/ui/macros/issue-99907.fixed b/tests/ui/macros/issue-99907.fixed new file mode 100644 index 000000000..9e0e1b80e --- /dev/null +++ b/tests/ui/macros/issue-99907.fixed @@ -0,0 +1,24 @@ +// check-pass +// run-rustfix + +fn main() { + println!("Hello {f:.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:1.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity +} diff --git a/tests/ui/macros/issue-99907.rs b/tests/ui/macros/issue-99907.rs new file mode 100644 index 000000000..eebcfc2ef --- /dev/null +++ b/tests/ui/macros/issue-99907.rs @@ -0,0 +1,24 @@ +// check-pass +// run-rustfix + +fn main() { + println!("Hello {:.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:1.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello { }!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello { }!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity +} diff --git a/tests/ui/macros/issue-99907.stderr b/tests/ui/macros/issue-99907.stderr new file mode 100644 index 000000000..eefb28dee --- /dev/null +++ b/tests/ui/macros/issue-99907.stderr @@ -0,0 +1,68 @@ +warning: named argument `f` is not used by name + --> $DIR/issue-99907.rs:5:30 + | +LL | println!("Hello {:.1}!", f = 0.02f32); + | ----- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | + = note: `#[warn(named_arguments_used_positionally)]` on by default +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f:.1}!", f = 0.02f32); + | + + +warning: named argument `f` is not used by name + --> $DIR/issue-99907.rs:9:31 + | +LL | println!("Hello {:1.1}!", f = 0.02f32); + | ------ ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f:1.1}!", f = 0.02f32); + | + + +warning: named argument `f` is not used by name + --> $DIR/issue-99907.rs:13:27 + | +LL | println!("Hello {}!", f = 0.02f32); + | -- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f}!", f = 0.02f32); + | + + +warning: named argument `f` is not used by name + --> $DIR/issue-99907.rs:17:28 + | +LL | println!("Hello { }!", f = 0.02f32); + | --- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f}!", f = 0.02f32); + | + + +warning: named argument `f` is not used by name + --> $DIR/issue-99907.rs:21:29 + | +LL | println!("Hello { }!", f = 0.02f32); + | ---- ^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `f` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("Hello {f}!", f = 0.02f32); + | + + +warning: 5 warnings emitted + diff --git a/tests/ui/macros/lint-trailing-macro-call.rs b/tests/ui/macros/lint-trailing-macro-call.rs new file mode 100644 index 000000000..f8e847563 --- /dev/null +++ b/tests/ui/macros/lint-trailing-macro-call.rs @@ -0,0 +1,16 @@ +// check-pass +// +// Ensures that we properly lint +// a removed 'expression' resulting from a macro +// in trailing expression position + +macro_rules! expand_it { + () => { + #[cfg(FALSE)] 25; //~ WARN trailing semicolon in macro + //~| WARN this was previously + } +} + +fn main() { + expand_it!() +} diff --git a/tests/ui/macros/lint-trailing-macro-call.stderr b/tests/ui/macros/lint-trailing-macro-call.stderr new file mode 100644 index 000000000..13cecc3a3 --- /dev/null +++ b/tests/ui/macros/lint-trailing-macro-call.stderr @@ -0,0 +1,35 @@ +warning: trailing semicolon in macro used in expression position + --> $DIR/lint-trailing-macro-call.rs:9:25 + | +LL | #[cfg(FALSE)] 25; + | ^ +... +LL | expand_it!() + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it` + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/lint-trailing-macro-call.rs:9:25 + | +LL | #[cfg(FALSE)] 25; + | ^ +... +LL | expand_it!() + | ------------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it` + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/macros/local-ambiguity-multiple-parsing-options.rs b/tests/ui/macros/local-ambiguity-multiple-parsing-options.rs new file mode 100644 index 000000000..396748109 --- /dev/null +++ b/tests/ui/macros/local-ambiguity-multiple-parsing-options.rs @@ -0,0 +1,8 @@ +fn main() {} + +macro_rules! ambiguity { + ($($i:ident)* $j:ident) => {}; +} + +ambiguity!(error); //~ ERROR local ambiguity +ambiguity!(error); //~ ERROR local ambiguity diff --git a/tests/ui/macros/local-ambiguity-multiple-parsing-options.stderr b/tests/ui/macros/local-ambiguity-multiple-parsing-options.stderr new file mode 100644 index 000000000..68b278fd3 --- /dev/null +++ b/tests/ui/macros/local-ambiguity-multiple-parsing-options.stderr @@ -0,0 +1,14 @@ +error: local ambiguity when calling macro `ambiguity`: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: local ambiguity when calling macro `ambiguity`: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/log_syntax-trace_macros-macro-locations.rs b/tests/ui/macros/log_syntax-trace_macros-macro-locations.rs new file mode 100644 index 000000000..2d78ae6f9 --- /dev/null +++ b/tests/ui/macros/log_syntax-trace_macros-macro-locations.rs @@ -0,0 +1,22 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![feature(trace_macros, log_syntax)] + +// make sure these macros can be used as in the various places that +// macros can occur. + +// items +trace_macros!(false); +log_syntax!(); + +fn main() { + + // statements + trace_macros!(false); + log_syntax!(); + + // expressions + (trace_macros!(false), + log_syntax!()); +} diff --git a/tests/ui/macros/log_syntax-trace_macros-macro-locations.stdout b/tests/ui/macros/log_syntax-trace_macros-macro-locations.stdout new file mode 100644 index 000000000..b28b04f64 --- /dev/null +++ b/tests/ui/macros/log_syntax-trace_macros-macro-locations.stdout @@ -0,0 +1,3 @@ + + + diff --git a/tests/ui/macros/macro-2.rs b/tests/ui/macros/macro-2.rs new file mode 100644 index 000000000..a315981b6 --- /dev/null +++ b/tests/ui/macros/macro-2.rs @@ -0,0 +1,12 @@ +// run-pass +pub fn main() { + + macro_rules! mylambda_tt { + ($x:ident, $body:expr) => ({ + fn f($x: isize) -> isize { return $body; } + f + }) + } + + assert_eq!(mylambda_tt!(y, y * 2)(8), 16); +} diff --git a/tests/ui/macros/macro-as-fn-body.rs b/tests/ui/macros/macro-as-fn-body.rs new file mode 100644 index 000000000..6781c9a9e --- /dev/null +++ b/tests/ui/macros/macro-as-fn-body.rs @@ -0,0 +1,33 @@ +// +// run-pass +// +// Description - ensure Interpolated blocks can act as valid function bodies +// Covered cases: free functions, struct methods, and default trait functions + +macro_rules! def_fn { + ($body:block) => { + fn bar() $body + } +} + +trait Foo { + def_fn!({ println!("foo"); }); +} + +struct Baz {} + +impl Foo for Baz {} + +struct Qux {} + +impl Qux { + def_fn!({ println!("qux"); }); +} + +def_fn!({ println!("quux"); }); + +pub fn main() { + Baz::bar(); + Qux::bar(); + bar(); +} diff --git a/tests/ui/macros/macro-at-most-once-rep-2015-rpass.rs b/tests/ui/macros/macro-at-most-once-rep-2015-rpass.rs new file mode 100644 index 000000000..66597c0ac --- /dev/null +++ b/tests/ui/macros/macro-at-most-once-rep-2015-rpass.rs @@ -0,0 +1,50 @@ +// run-pass + +#![allow(unused_mut)] + +// Check that when `?` is followed by what looks like a Kleene operator (?, +, and *) +// then that `?` is not interpreted as a separator. In other words, `$(pat)?+` matches `pat +` +// or `+` but does not match `pat` or `pat ? pat`. + +// edition:2015 + +macro_rules! foo { + // Check for `?`. + ($($a:ident)? ? $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `+`. + ($($a:ident)? + $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `*`. + ($($a:ident)? * $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `;`, not a kleene operator. + ($($a:ident)? ; $num:expr) => { + let mut x = 0; + + $( + x += $a; + )? + + assert_eq!(x, $num); + }; +} + +pub fn main() { + let a = 1; + + // Accept 0 repetitions. + foo!( ; 0); + foo!( + 0); + foo!( * 0); + foo!( ? 0); + + // Accept 1 repetition. + foo!(a ; 1); + foo!(a + 1); + foo!(a * 1); + foo!(a ? 1); +} diff --git a/tests/ui/macros/macro-at-most-once-rep-2015.rs b/tests/ui/macros/macro-at-most-once-rep-2015.rs new file mode 100644 index 000000000..f68100d45 --- /dev/null +++ b/tests/ui/macros/macro-at-most-once-rep-2015.rs @@ -0,0 +1,42 @@ +// Tests that `?` is a Kleene op and not a macro separator in the 2015 edition. + +// edition:2015 + +macro_rules! foo { + ($(a)?) => {}; +} + +// The Kleene op `?` does not admit a separator before it. +macro_rules! baz { + ($(a),?) => {}; //~ERROR the `?` macro repetition operator +} + +macro_rules! barplus { + ($(a)?+) => {}; // ok. matches "a+" and "+" +} + +macro_rules! barstar { + ($(a)?*) => {}; // ok. matches "a*" and "*" +} + +pub fn main() { + foo!(); + foo!(a); + foo!(a?); //~ ERROR no rules expected the token `?` + foo!(a?a); //~ ERROR no rules expected the token `?` + foo!(a?a?a); //~ ERROR no rules expected the token `?` + + barplus!(); //~ERROR unexpected end of macro invocation + barplus!(a); //~ERROR unexpected end of macro invocation + barplus!(a?); //~ ERROR no rules expected the token `?` + barplus!(a?a); //~ ERROR no rules expected the token `?` + barplus!(a+); + barplus!(+); + + barstar!(); //~ERROR unexpected end of macro invocation + barstar!(a); //~ERROR unexpected end of macro invocation + barstar!(a?); //~ ERROR no rules expected the token `?` + barstar!(a?a); //~ ERROR no rules expected the token `?` + barstar!(a*); + barstar!(*); +} diff --git a/tests/ui/macros/macro-at-most-once-rep-2015.stderr b/tests/ui/macros/macro-at-most-once-rep-2015.stderr new file mode 100644 index 000000000..7c45b85bc --- /dev/null +++ b/tests/ui/macros/macro-at-most-once-rep-2015.stderr @@ -0,0 +1,161 @@ +error: the `?` macro repetition operator does not take a separator + --> $DIR/macro-at-most-once-rep-2015.rs:11:10 + | +LL | ($(a),?) => {}; + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:25:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence end + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:26:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?a); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence end + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:27:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?a?a); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence end + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:29:5 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(); + | ^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2015.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:30:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a); + | ^ missing tokens in macro arguments + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2015.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:31:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a?); + | ^ no rules expected this token in macro call + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2015.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:32:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a?a); + | ^ no rules expected this token in macro call + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2015.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:36:5 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(); + | ^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2015.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2015.rs:37:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a); + | ^ missing tokens in macro arguments + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2015.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:38:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a?); + | ^ no rules expected this token in macro call + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2015.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2015.rs:39:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a?a); + | ^ no rules expected this token in macro call + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2015.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/macros/macro-at-most-once-rep-2018-rpass.rs b/tests/ui/macros/macro-at-most-once-rep-2018-rpass.rs new file mode 100644 index 000000000..b37f38530 --- /dev/null +++ b/tests/ui/macros/macro-at-most-once-rep-2018-rpass.rs @@ -0,0 +1,50 @@ +// run-pass + +#![allow(unused_mut)] + +// Check that when `?` is followed by what looks like a Kleene operator (?, +, and *) +// then that `?` is not interpreted as a separator. In other words, `$(pat)?+` matches `pat +` +// or `+` but does not match `pat` or `pat ? pat`. + +// edition:2018 + +macro_rules! foo { + // Check for `?`. + ($($a:ident)? ? $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `+`. + ($($a:ident)? + $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `*`. + ($($a:ident)? * $num:expr) => { + foo!($($a)? ; $num); + }; + // Check for `;`, not a kleene operator. + ($($a:ident)? ; $num:expr) => { + let mut x = 0; + + $( + x += $a; + )? + + assert_eq!(x, $num); + }; +} + +pub fn main() { + let a = 1; + + // Accept 0 repetitions. + foo!( ; 0); + foo!( + 0); + foo!( * 0); + foo!( ? 0); + + // Accept 1 repetition. + foo!(a ; 1); + foo!(a + 1); + foo!(a * 1); + foo!(a ? 1); +} diff --git a/tests/ui/macros/macro-at-most-once-rep-2018.rs b/tests/ui/macros/macro-at-most-once-rep-2018.rs new file mode 100644 index 000000000..886a25bbc --- /dev/null +++ b/tests/ui/macros/macro-at-most-once-rep-2018.rs @@ -0,0 +1,42 @@ +// Tests that `?` is a Kleene op and not a macro separator in the 2018 edition. + +// edition:2018 + +macro_rules! foo { + ($(a)?) => {}; +} + +// The Kleene op `?` does not admit a separator before it. +macro_rules! baz { + ($(a),?) => {}; //~ERROR the `?` macro repetition operator +} + +macro_rules! barplus { + ($(a)?+) => {}; // ok. matches "a+" and "+" +} + +macro_rules! barstar { + ($(a)?*) => {}; // ok. matches "a*" and "*" +} + +pub fn main() { + foo!(); + foo!(a); + foo!(a?); //~ ERROR no rules expected the token `?` + foo!(a?a); //~ ERROR no rules expected the token `?` + foo!(a?a?a); //~ ERROR no rules expected the token `?` + + barplus!(); //~ERROR unexpected end of macro invocation + barplus!(a); //~ERROR unexpected end of macro invocation + barplus!(a?); //~ ERROR no rules expected the token `?` + barplus!(a?a); //~ ERROR no rules expected the token `?` + barplus!(a+); + barplus!(+); + + barstar!(); //~ERROR unexpected end of macro invocation + barstar!(a); //~ERROR unexpected end of macro invocation + barstar!(a?); //~ ERROR no rules expected the token `?` + barstar!(a?a); //~ ERROR no rules expected the token `?` + barstar!(a*); + barstar!(*); +} diff --git a/tests/ui/macros/macro-at-most-once-rep-2018.stderr b/tests/ui/macros/macro-at-most-once-rep-2018.stderr new file mode 100644 index 000000000..696520b28 --- /dev/null +++ b/tests/ui/macros/macro-at-most-once-rep-2018.stderr @@ -0,0 +1,161 @@ +error: the `?` macro repetition operator does not take a separator + --> $DIR/macro-at-most-once-rep-2018.rs:11:10 + | +LL | ($(a),?) => {}; + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:25:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence end + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:26:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?a); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence end + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:27:11 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a?a?a); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence end + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2018.rs:29:5 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(); + | ^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2018.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2018.rs:30:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a); + | ^ missing tokens in macro arguments + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2018.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:31:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a?); + | ^ no rules expected this token in macro call + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2018.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:32:15 + | +LL | macro_rules! barplus { + | -------------------- when calling this macro +... +LL | barplus!(a?a); + | ^ no rules expected this token in macro call + | +note: while trying to match `+` + --> $DIR/macro-at-most-once-rep-2018.rs:15:11 + | +LL | ($(a)?+) => {}; // ok. matches "a+" and "+" + | ^ + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2018.rs:36:5 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(); + | ^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2018.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: unexpected end of macro invocation + --> $DIR/macro-at-most-once-rep-2018.rs:37:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a); + | ^ missing tokens in macro arguments + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2018.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:38:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a?); + | ^ no rules expected this token in macro call + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2018.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: no rules expected the token `?` + --> $DIR/macro-at-most-once-rep-2018.rs:39:15 + | +LL | macro_rules! barstar { + | -------------------- when calling this macro +... +LL | barstar!(a?a); + | ^ no rules expected this token in macro call + | +note: while trying to match `*` + --> $DIR/macro-at-most-once-rep-2018.rs:19:11 + | +LL | ($(a)?*) => {}; // ok. matches "a*" and "*" + | ^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/macros/macro-attribute-expansion.rs b/tests/ui/macros/macro-attribute-expansion.rs new file mode 100644 index 000000000..f01e5c44a --- /dev/null +++ b/tests/ui/macros/macro-attribute-expansion.rs @@ -0,0 +1,16 @@ +// run-pass +macro_rules! descriptions { + ($name:ident is $desc:expr) => { + // Check that we will correctly expand attributes + #[doc = $desc] + #[allow(dead_code)] + const $name : &'static str = $desc; + } +} + +// item +descriptions! { DOG is "an animal" } +descriptions! { RUST is "a language" } + +pub fn main() { +} diff --git a/tests/ui/macros/macro-attribute.rs b/tests/ui/macros/macro-attribute.rs new file mode 100644 index 000000000..88834a967 --- /dev/null +++ b/tests/ui/macros/macro-attribute.rs @@ -0,0 +1,2 @@ +#[doc = $not_there] //~ ERROR expected expression, found `$` +fn main() { } diff --git a/tests/ui/macros/macro-attribute.stderr b/tests/ui/macros/macro-attribute.stderr new file mode 100644 index 000000000..3316d3872 --- /dev/null +++ b/tests/ui/macros/macro-attribute.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `$` + --> $DIR/macro-attribute.rs:1:9 + | +LL | #[doc = $not_there] + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-attributes.rs b/tests/ui/macros/macro-attributes.rs new file mode 100644 index 000000000..d382e8b71 --- /dev/null +++ b/tests/ui/macros/macro-attributes.rs @@ -0,0 +1,23 @@ +// run-pass + +macro_rules! compiles_fine { + (#[$at:meta]) => { + // test that the different types of attributes work + #[attribute] + /// Documentation! + #[$at] + + // check that the attributes are recognised by requiring this + // to be removed to avoid a compile error + #[cfg(always_remove)] + static MISTYPED: () = "foo"; + } +} + +// item +compiles_fine!(#[foo]); + +pub fn main() { + // statement + compiles_fine!(#[bar]); +} diff --git a/tests/ui/macros/macro-backtrace-invalid-internals.rs b/tests/ui/macros/macro-backtrace-invalid-internals.rs new file mode 100644 index 000000000..9501e7cd0 --- /dev/null +++ b/tests/ui/macros/macro-backtrace-invalid-internals.rs @@ -0,0 +1,61 @@ +// Macros in statement vs expression position handle backtraces differently. + +macro_rules! fake_method_stmt { + () => { + 1.fake() //~ ERROR no method + } +} + +macro_rules! fake_field_stmt { + () => { + 1.fake //~ ERROR doesn't have fields + } +} + +macro_rules! fake_anon_field_stmt { + () => { + (1).0 //~ ERROR doesn't have fields + } +} + +macro_rules! fake_method_expr { + () => { + 1.fake() //~ ERROR no method + } +} + +macro_rules! fake_field_expr { + () => { + 1.fake //~ ERROR doesn't have fields + } +} + +macro_rules! fake_anon_field_expr { + () => { + (1).0 //~ ERROR doesn't have fields + } +} + +macro_rules! real_method_stmt { + () => { + 2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}` + } +} + +macro_rules! real_method_expr { + () => { + 2.0.neg() //~ ERROR can't call method `neg` on ambiguous numeric type `{float}` + } +} + +fn main() { + fake_method_stmt!(); + fake_field_stmt!(); + fake_anon_field_stmt!(); + real_method_stmt!(); + + let _ = fake_method_expr!(); + let _ = fake_field_expr!(); + let _ = fake_anon_field_expr!(); + let _ = real_method_expr!(); +} diff --git a/tests/ui/macros/macro-backtrace-invalid-internals.stderr b/tests/ui/macros/macro-backtrace-invalid-internals.stderr new file mode 100644 index 000000000..aa8f06a0d --- /dev/null +++ b/tests/ui/macros/macro-backtrace-invalid-internals.stderr @@ -0,0 +1,100 @@ +error[E0599]: no method named `fake` found for type `{integer}` in the current scope + --> $DIR/macro-backtrace-invalid-internals.rs:5:13 + | +LL | 1.fake() + | ^^^^ method not found in `{integer}` +... +LL | fake_method_stmt!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `fake_method_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/macro-backtrace-invalid-internals.rs:11:13 + | +LL | 1.fake + | ^^^^ +... +LL | fake_field_stmt!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `fake_field_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/macro-backtrace-invalid-internals.rs:17:15 + | +LL | (1).0 + | ^ +... +LL | fake_anon_field_stmt!(); + | ----------------------- in this macro invocation + | + = note: this error originates in the macro `fake_anon_field_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` + --> $DIR/macro-backtrace-invalid-internals.rs:41:15 + | +LL | 2.0.neg() + | ^^^ +... +LL | real_method_stmt!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `real_method_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | 2.0_f32.neg() + | ~~~~~~~ + +error[E0599]: no method named `fake` found for type `{integer}` in the current scope + --> $DIR/macro-backtrace-invalid-internals.rs:23:13 + | +LL | 1.fake() + | ^^^^ method not found in `{integer}` +... +LL | let _ = fake_method_expr!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `fake_method_expr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/macro-backtrace-invalid-internals.rs:29:13 + | +LL | 1.fake + | ^^^^ +... +LL | let _ = fake_field_expr!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `fake_field_expr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/macro-backtrace-invalid-internals.rs:35:15 + | +LL | (1).0 + | ^ +... +LL | let _ = fake_anon_field_expr!(); + | ----------------------- in this macro invocation + | + = note: this error originates in the macro `fake_anon_field_expr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` + --> $DIR/macro-backtrace-invalid-internals.rs:47:15 + | +LL | 2.0.neg() + | ^^^ +... +LL | let _ = real_method_expr!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `real_method_expr` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | 2.0_f32.neg() + | ~~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0599, E0610, E0689. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/macros/macro-backtrace-nested.rs b/tests/ui/macros/macro-backtrace-nested.rs new file mode 100644 index 000000000..13d80163d --- /dev/null +++ b/tests/ui/macros/macro-backtrace-nested.rs @@ -0,0 +1,20 @@ +// In expression position, but not statement position, when we expand a macro, +// we replace the span of the expanded expression with that of the call site. + +macro_rules! nested_expr { + () => (fake) //~ ERROR cannot find + //~^ ERROR cannot find +} + +macro_rules! call_nested_expr { + () => (nested_expr!()) +} + +macro_rules! call_nested_expr_sum { + () => { 1 + nested_expr!(); } +} + +fn main() { + 1 + call_nested_expr!(); + call_nested_expr_sum!(); +} diff --git a/tests/ui/macros/macro-backtrace-nested.stderr b/tests/ui/macros/macro-backtrace-nested.stderr new file mode 100644 index 000000000..dadedfbe8 --- /dev/null +++ b/tests/ui/macros/macro-backtrace-nested.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find value `fake` in this scope + --> $DIR/macro-backtrace-nested.rs:5:12 + | +LL | () => (fake) + | ^^^^ not found in this scope +... +LL | 1 + call_nested_expr!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `nested_expr` which comes from the expansion of the macro `call_nested_expr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `fake` in this scope + --> $DIR/macro-backtrace-nested.rs:5:12 + | +LL | () => (fake) + | ^^^^ not found in this scope +... +LL | call_nested_expr_sum!(); + | ----------------------- in this macro invocation + | + = note: this error originates in the macro `nested_expr` which comes from the expansion of the macro `call_nested_expr_sum` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/macro-backtrace-println.rs b/tests/ui/macros/macro-backtrace-println.rs new file mode 100644 index 000000000..859dd019d --- /dev/null +++ b/tests/ui/macros/macro-backtrace-println.rs @@ -0,0 +1,19 @@ +// The `format_args!` syntax extension issues errors before code expansion +// has completed, but we still need a backtrace. + +// This test includes stripped-down versions of `print!` and `println!`, +// because we can't otherwise verify the lines of the backtrace. + +fn print(_args: std::fmt::Arguments) {} + +macro_rules! myprint { + ($($arg:tt)*) => (print(format_args!($($arg)*))); +} + +macro_rules! myprintln { + ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); //~ ERROR no arguments were given +} + +fn main() { + myprintln!("{}"); +} diff --git a/tests/ui/macros/macro-backtrace-println.stderr b/tests/ui/macros/macro-backtrace-println.stderr new file mode 100644 index 000000000..b4e2883e8 --- /dev/null +++ b/tests/ui/macros/macro-backtrace-println.stderr @@ -0,0 +1,13 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-backtrace-println.rs:14:30 + | +LL | ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); + | ^^^^^^^^^^^^^^^^^^^ +... +LL | myprintln!("{}"); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `concat` which comes from the expansion of the macro `myprintln` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-block-nonterminal.rs b/tests/ui/macros/macro-block-nonterminal.rs new file mode 100644 index 000000000..a6c9dd6e1 --- /dev/null +++ b/tests/ui/macros/macro-block-nonterminal.rs @@ -0,0 +1,11 @@ +// run-pass + +macro_rules! do_block{ + ($val:block) => {$val} +} + +fn main() { + let s; + do_block!({ s = "it works!"; }); + assert_eq!(s, "it works!"); +} diff --git a/tests/ui/macros/macro-comma-behavior-rpass.rs b/tests/ui/macros/macro-comma-behavior-rpass.rs new file mode 100644 index 000000000..8406b4e78 --- /dev/null +++ b/tests/ui/macros/macro-comma-behavior-rpass.rs @@ -0,0 +1,98 @@ +// run-pass +// needs-unwind +#![allow(unused_imports)] +// Ideally, any macro call with a trailing comma should behave +// identically to a call without the comma. +// +// This checks the behavior of macros with trailing commas in key +// places where regressions in behavior seem highly possible (due +// to it being e.g., a place where the addition of an argument +// causes it to go down a code path with subtly different behavior). +// +// There is a companion failing test. + +// compile-flags: --test -C debug_assertions=yes +// revisions: std core + +#![cfg_attr(core, no_std)] + +#[cfg(core)] +use core::fmt; +#[cfg(std)] +use std::fmt; + +// an easy mistake in the implementation of 'assert!' +// would cause this to say "explicit panic" +#[test] +#[should_panic(expected = "assertion failed")] +fn assert_1arg() { + assert!(false,); +} + +// same as 'assert_1arg' +#[test] +#[should_panic(expected = "assertion failed")] +fn debug_assert_1arg() { + debug_assert!(false,); +} + +// make sure we don't accidentally forward to `write!("text")` +#[cfg(std)] +#[test] +fn writeln_1arg() { + use fmt::Write; + + let mut s = String::new(); + writeln!(&mut s,).unwrap(); + assert_eq!(&s, "\n"); +} + +// A number of format_args-like macros have special-case treatment +// for a single message string, which is not formatted. +// +// This test ensures that the addition of a trailing comma does not +// suddenly cause these strings to get formatted when they otherwise +// would not be. This is an easy mistake to make by having such a macro +// accept ", $($tok:tt)*" instead of ", $($tok:tt)+" after its minimal +// set of arguments. +// +// (Example: Issue #48042) +#[test] +#[allow(non_fmt_panics)] +fn to_format_or_not_to_format() { + // ("{}" is the easiest string to test because if this gets + // sent to format_args!, it'll simply fail to compile. + // "{{}}" is an example of an input that could compile and + // produce an incorrect program, but testing the panics + // would be burdensome.) + let falsum = || false; + + assert!(true, "{}",); + + // assert_eq!(1, 1, "{}",); // see check-fail + // assert_ne!(1, 2, "{}",); // see check-fail + + debug_assert!(true, "{}",); + + // debug_assert_eq!(1, 1, "{}",); // see check-fail + // debug_assert_ne!(1, 2, "{}",); // see check-fail + // eprint!("{}",); // see check-fail + // eprintln!("{}",); // see check-fail + // format!("{}",); // see check-fail + // format_args!("{}",); // see check-fail + + if falsum() { + panic!("{}",); + } + + // print!("{}",); // see check-fail + // println!("{}",); // see check-fail + // unimplemented!("{}",); // see check-fail + + if falsum() { + unreachable!("{}",); + } + + // write!(&mut stdout, "{}",); // see check-fail + // writeln!(&mut stdout, "{}",); // see check-fail +} diff --git a/tests/ui/macros/macro-comma-behavior.core.stderr b/tests/ui/macros/macro-comma-behavior.core.stderr new file mode 100644 index 000000000..ac15e9fa8 --- /dev/null +++ b/tests/ui/macros/macro-comma-behavior.core.stderr @@ -0,0 +1,50 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:21:23 + | +LL | assert_eq!(1, 1, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:24:23 + | +LL | assert_ne!(1, 2, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:30:29 + | +LL | debug_assert_eq!(1, 1, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:33:29 + | +LL | debug_assert_ne!(1, 2, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:52:19 + | +LL | format_args!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:68:21 + | +LL | unimplemented!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:77:24 + | +LL | write!(f, "{}",)?; + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:81:26 + | +LL | writeln!(f, "{}",)?; + | ^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/macros/macro-comma-behavior.rs b/tests/ui/macros/macro-comma-behavior.rs new file mode 100644 index 000000000..27d50ff3d --- /dev/null +++ b/tests/ui/macros/macro-comma-behavior.rs @@ -0,0 +1,89 @@ +// Companion test to the similarly-named file in run-pass. + +// compile-flags: -C debug_assertions=yes +// revisions: std core + +#![feature(lang_items)] +#![cfg_attr(core, no_std)] + +#[cfg(std)] use std::fmt; +#[cfg(core)] use core::fmt; +#[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {} +#[cfg(core)] #[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0; +#[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} } + +// (see documentation of the similarly-named test in run-pass) +fn to_format_or_not_to_format() { + let falsum = || false; + + // assert!(true, "{}",); // see run-pass + + assert_eq!(1, 1, "{}",); + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + assert_ne!(1, 2, "{}",); + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + + // debug_assert!(true, "{}",); // see run-pass + + debug_assert_eq!(1, 1, "{}",); + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + debug_assert_ne!(1, 2, "{}",); + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + + #[cfg(std)] { + eprint!("{}",); + //[std]~^ ERROR no arguments + } + + #[cfg(std)] { + eprintln!("{}",); + //[std]~^ ERROR no arguments + } + + #[cfg(std)] { + format!("{}",); + //[std]~^ ERROR no arguments + } + + format_args!("{}",); + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + + // if falsum() { panic!("{}",); } // see run-pass + + #[cfg(std)] { + print!("{}",); + //[std]~^ ERROR no arguments + } + + #[cfg(std)] { + println!("{}",); + //[std]~^ ERROR no arguments + } + + unimplemented!("{}",); + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + + // if falsum() { unreachable!("{}",); } // see run-pass + + struct S; + impl fmt::Display for S { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}",)?; + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + + writeln!(f, "{}",)?; + //[core]~^ ERROR no arguments + //[std]~^^ ERROR no arguments + Ok(()) + } + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-comma-behavior.std.stderr b/tests/ui/macros/macro-comma-behavior.std.stderr new file mode 100644 index 000000000..7fd060e22 --- /dev/null +++ b/tests/ui/macros/macro-comma-behavior.std.stderr @@ -0,0 +1,80 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:21:23 + | +LL | assert_eq!(1, 1, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:24:23 + | +LL | assert_ne!(1, 2, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:30:29 + | +LL | debug_assert_eq!(1, 1, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:33:29 + | +LL | debug_assert_ne!(1, 2, "{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:38:18 + | +LL | eprint!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:43:20 + | +LL | eprintln!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:48:18 + | +LL | format!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:52:19 + | +LL | format_args!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:59:17 + | +LL | print!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:64:19 + | +LL | println!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:68:21 + | +LL | unimplemented!("{}",); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:77:24 + | +LL | write!(f, "{}",)?; + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/macro-comma-behavior.rs:81:26 + | +LL | writeln!(f, "{}",)?; + | ^^ + +error: aborting due to 13 previous errors + diff --git a/tests/ui/macros/macro-comma-support-rpass.rs b/tests/ui/macros/macro-comma-support-rpass.rs new file mode 100644 index 000000000..25b8c3cc6 --- /dev/null +++ b/tests/ui/macros/macro-comma-support-rpass.rs @@ -0,0 +1,355 @@ +// run-pass +// This is meant to be a comprehensive test of invocations with/without +// trailing commas (or other, similar optionally-trailing separators). +// Every macro is accounted for, even those not tested in this file. +// (There will be a note indicating why). + +// std and core are both tested because they may contain separate +// implementations for some macro_rules! macros as an implementation +// detail. + +// ignore-pretty issue #37195 + +// compile-flags: --test -C debug_assertions=yes +// revisions: std core + +#![cfg_attr(core, no_std)] + +#![allow(deprecated)] // for deprecated `try!()` macro +#![feature(concat_idents)] + +#[cfg(std)] use std::fmt; +#[cfg(core)] use core::fmt; + +#[test] +fn assert() { + assert!(true); + assert!(true,); + assert!(true, "hello"); + assert!(true, "hello",); + assert!(true, "hello {}", "world"); + assert!(true, "hello {}", "world",); +} + +#[test] +fn assert_eq() { + assert_eq!(1, 1); + assert_eq!(1, 1,); + assert_eq!(1, 1, "hello"); + assert_eq!(1, 1, "hello",); + assert_eq!(1, 1, "hello {}", "world"); + assert_eq!(1, 1, "hello {}", "world",); +} + +#[test] +fn assert_ne() { + assert_ne!(1, 2); + assert_ne!(1, 2,); + assert_ne!(1, 2, "hello"); + assert_ne!(1, 2, "hello",); + assert_ne!(1, 2, "hello {}", "world"); + assert_ne!(1, 2, "hello {}", "world",); +} + +#[test] +fn cfg() { + let _ = cfg!(pants); + let _ = cfg!(pants,); + let _ = cfg!(pants = "pants"); + let _ = cfg!(pants = "pants",); + let _ = cfg!(all(pants)); + let _ = cfg!(all(pants),); + let _ = cfg!(all(pants,)); + let _ = cfg!(all(pants,),); +} + +#[test] +fn column() { + let _ = column!(); +} + +// compile_error! is in a check-fail companion to this test + +#[test] +fn concat() { + let _ = concat!(); + let _ = concat!("hello"); + let _ = concat!("hello",); + let _ = concat!("hello", " world"); + let _ = concat!("hello", " world",); +} + +#[test] +fn concat_idents() { + fn foo() {} + fn foobar() {} + + concat_idents!(foo)(); + concat_idents!(foo,)(); + concat_idents!(foo, bar)(); + concat_idents!(foo, bar,)(); +} + +#[test] +fn debug_assert() { + debug_assert!(true); + debug_assert!(true, ); + debug_assert!(true, "hello"); + debug_assert!(true, "hello",); + debug_assert!(true, "hello {}", "world"); + debug_assert!(true, "hello {}", "world",); +} + +#[test] +fn debug_assert_eq() { + debug_assert_eq!(1, 1); + debug_assert_eq!(1, 1,); + debug_assert_eq!(1, 1, "hello"); + debug_assert_eq!(1, 1, "hello",); + debug_assert_eq!(1, 1, "hello {}", "world"); + debug_assert_eq!(1, 1, "hello {}", "world",); +} + +#[test] +fn debug_assert_ne() { + debug_assert_ne!(1, 2); + debug_assert_ne!(1, 2,); + debug_assert_ne!(1, 2, "hello"); + debug_assert_ne!(1, 2, "hello",); + debug_assert_ne!(1, 2, "hello {}", "world"); + debug_assert_ne!(1, 2, "hello {}", "world",); +} + +#[test] +fn env() { + let _ = env!("PATH"); + let _ = env!("PATH",); + let _ = env!("PATH", "not found"); + let _ = env!("PATH", "not found",); +} + +#[cfg(std)] +#[test] +fn eprint() { + eprint!("hello"); + eprint!("hello",); + eprint!("hello {}", "world"); + eprint!("hello {}", "world",); +} + +#[cfg(std)] +#[test] +fn eprintln() { + eprintln!(); + eprintln!("hello"); + eprintln!("hello",); + eprintln!("hello {}", "world"); + eprintln!("hello {}", "world",); +} + +#[test] +fn file() { + let _ = file!(); +} + +#[cfg(std)] +#[test] +fn format() { + let _ = format!("hello"); + let _ = format!("hello",); + let _ = format!("hello {}", "world"); + let _ = format!("hello {}", "world",); +} + +#[test] +fn format_args() { + let _ = format_args!("hello"); + let _ = format_args!("hello",); + let _ = format_args!("hello {}", "world"); + let _ = format_args!("hello {}", "world",); +} + +#[test] +fn include() { + let _ = include!("auxiliary/macro-comma-support.rs"); + let _ = include!("auxiliary/macro-comma-support.rs",); +} + +#[test] +fn include_bytes() { + let _ = include_bytes!("auxiliary/macro-comma-support.rs"); + let _ = include_bytes!("auxiliary/macro-comma-support.rs",); +} + +#[test] +fn include_str() { + let _ = include_str!("auxiliary/macro-comma-support.rs"); + let _ = include_str!("auxiliary/macro-comma-support.rs",); +} + +#[test] +fn line() { + let _ = line!(); +} + +#[test] +fn matches() { + let _ = matches!(1, x if x > 0); + let _ = matches!(1, x if x > 0,); +} + +#[test] +fn module_path() { + let _ = module_path!(); +} + +#[test] +fn option_env() { + let _ = option_env!("PATH"); + let _ = option_env!("PATH",); +} + +#[test] +fn panic() { + // prevent 'unreachable code' warnings + let falsum = || false; + + if falsum() { panic!(); } + if falsum() { panic!("hello"); } + if falsum() { panic!("hello",); } + if falsum() { panic!("hello {}", "world"); } + if falsum() { panic!("hello {}", "world",); } +} + +#[cfg(std)] +#[test] +fn print() { + print!("hello"); + print!("hello",); + print!("hello {}", "world"); + print!("hello {}", "world",); +} + +#[cfg(std)] +#[test] +fn println() { + println!(); + println!("hello"); + println!("hello",); + println!("hello {}", "world"); + println!("hello {}", "world",); +} + +// stringify! is N/A + +#[cfg(std)] +#[test] +fn thread_local() { + // this has an optional trailing *semicolon* + thread_local! { + #[allow(unused)] pub static A: () = () + } + + thread_local! { + #[allow(unused)] pub static AA: () = (); + } + + thread_local! { + #[allow(unused)] pub static AAA: () = (); + #[allow(unused)] pub static AAAA: () = () + } + + thread_local! { + #[allow(unused)] pub static AAAAG: () = (); + #[allow(unused)] pub static AAAAGH: () = (); + } +} + +#[test] +fn try() { + fn inner() -> Result<(), ()> { + try!(Ok(())); + try!(Ok(()),); + Ok(()) + } + + inner().unwrap(); +} + +#[test] +fn unimplemented() { + // prevent 'unreachable code' warnings + let falsum = || false; + + if falsum() { unimplemented!(); } + if falsum() { unimplemented!("hello"); } + if falsum() { unimplemented!("hello",); } + if falsum() { unimplemented!("hello {}", "world"); } + if falsum() { unimplemented!("hello {}", "world",); } +} + +#[test] +fn unreachable() { + // prevent 'unreachable code' warnings + let falsum = || false; + + if falsum() { unreachable!(); } + if falsum() { unreachable!("hello"); } + if falsum() { unreachable!("hello",); } + if falsum() { unreachable!("hello {}", "world"); } + if falsum() { unreachable!("hello {}", "world",); } +} + +#[cfg(std)] +#[test] +fn vec() { + let _: Vec<()> = vec![]; + let _ = vec![0]; + let _ = vec![0,]; + let _ = vec![0, 1]; + let _ = vec![0, 1,]; +} + +// give a test body access to a fmt::Formatter, which seems +// to be the easiest way to use 'write!' on core. +macro_rules! test_with_formatter { + ( + #[test] + fn $fname:ident($f:ident: &mut fmt::Formatter) $block:block + ) => { + #[test] + fn $fname() { + struct Struct; + impl fmt::Display for Struct { + fn fmt(&self, $f: &mut fmt::Formatter) -> fmt::Result { + Ok($block) + } + } + + // suppress "unused" + assert!(true, "{}", Struct); + } + }; +} + +test_with_formatter! { + #[test] + fn write(f: &mut fmt::Formatter) { + let _ = write!(f, "hello"); + let _ = write!(f, "hello",); + let _ = write!(f, "hello {}", "world"); + let _ = write!(f, "hello {}", "world",); + } +} + +test_with_formatter! { + #[test] + fn writeln(f: &mut fmt::Formatter) { + let _ = writeln!(f); + let _ = writeln!(f,); + let _ = writeln!(f, "hello"); + let _ = writeln!(f, "hello",); + let _ = writeln!(f, "hello {}", "world"); + let _ = writeln!(f, "hello {}", "world",); + } +} diff --git a/tests/ui/macros/macro-comma-support.rs b/tests/ui/macros/macro-comma-support.rs new file mode 100644 index 000000000..7df5b6233 --- /dev/null +++ b/tests/ui/macros/macro-comma-support.rs @@ -0,0 +1,10 @@ +// This is a companion to the similarly-named test in run-pass. +// +// It tests macros that unavoidably produce compile errors. + +fn compile_error() { + compile_error!("lel"); //~ ERROR lel + compile_error!("lel",); //~ ERROR lel +} + +fn main() {} diff --git a/tests/ui/macros/macro-comma-support.stderr b/tests/ui/macros/macro-comma-support.stderr new file mode 100644 index 000000000..874efccd3 --- /dev/null +++ b/tests/ui/macros/macro-comma-support.stderr @@ -0,0 +1,14 @@ +error: lel + --> $DIR/macro-comma-support.rs:6:5 + | +LL | compile_error!("lel"); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: lel + --> $DIR/macro-comma-support.rs:7:5 + | +LL | compile_error!("lel",); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-context.rs b/tests/ui/macros/macro-context.rs new file mode 100644 index 000000000..d09fdf118 --- /dev/null +++ b/tests/ui/macros/macro-context.rs @@ -0,0 +1,21 @@ +// (typeof used because it's surprisingly hard to find an unparsed token after a stmt) +macro_rules! m { + () => ( i ; typeof ); //~ ERROR expected expression, found reserved keyword `typeof` + //~| ERROR macro expansion ignores token `typeof` + //~| ERROR macro expansion ignores token `;` + //~| ERROR macro expansion ignores token `;` + //~| ERROR cannot find type `i` in this scope + //~| ERROR cannot find value `i` in this scope + //~| WARN trailing semicolon in macro + //~| WARN this was previously +} + +fn main() { + let a: m!(); + let i = m!(); + match 0 { + m!() => {} + } + + m!(); +} diff --git a/tests/ui/macros/macro-context.stderr b/tests/ui/macros/macro-context.stderr new file mode 100644 index 000000000..7785f4159 --- /dev/null +++ b/tests/ui/macros/macro-context.stderr @@ -0,0 +1,99 @@ +error: macro expansion ignores token `;` and any following + --> $DIR/macro-context.rs:3:15 + | +LL | () => ( i ; typeof ); + | ^ +... +LL | let a: m!(); + | ---- caused by the macro expansion here + | + = note: the usage of `m!` is likely invalid in type context + +error: macro expansion ignores token `typeof` and any following + --> $DIR/macro-context.rs:3:17 + | +LL | () => ( i ; typeof ); + | ^^^^^^ +... +LL | let i = m!(); + | ---- caused by the macro expansion here + | + = note: the usage of `m!` is likely invalid in expression context + +error: macro expansion ignores token `;` and any following + --> $DIR/macro-context.rs:3:15 + | +LL | () => ( i ; typeof ); + | ^ +... +LL | m!() => {} + | ---- caused by the macro expansion here + | + = note: the usage of `m!` is likely invalid in pattern context + +error: expected expression, found reserved keyword `typeof` + --> $DIR/macro-context.rs:3:17 + | +LL | () => ( i ; typeof ); + | ^^^^^^ expected expression +... +LL | m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a builtin type with a similar name exists: `i8` +... +LL | let a: m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ not found in this scope +... +LL | let i = m!(); + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: trailing semicolon in macro used in expression position + --> $DIR/macro-context.rs:3:15 + | +LL | () => ( i ; typeof ); + | ^ +... +LL | let i = m!(); + | ---- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/macro-context.rs:3:15 + | +LL | () => ( i ; typeof ); + | ^ +... +LL | let i = m!(); + | ---- in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/macros/macro-crate-def-only.rs b/tests/ui/macros/macro-crate-def-only.rs new file mode 100644 index 000000000..514b33e38 --- /dev/null +++ b/tests/ui/macros/macro-crate-def-only.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:macro_crate_def_only.rs + + +#[macro_use] #[no_link] +extern crate macro_crate_def_only; + +pub fn main() { + assert_eq!(5, make_a_5!()); +} diff --git a/tests/ui/macros/macro-crate-nonterminal-non-root.rs b/tests/ui/macros/macro-crate-nonterminal-non-root.rs new file mode 100644 index 000000000..67899556f --- /dev/null +++ b/tests/ui/macros/macro-crate-nonterminal-non-root.rs @@ -0,0 +1,9 @@ +// aux-build:macro_crate_nonterminal.rs + +mod foo { + #[macro_use] + extern crate macro_crate_nonterminal; //~ ERROR must be at the crate root +} + +fn main() { +} diff --git a/tests/ui/macros/macro-crate-nonterminal-non-root.stderr b/tests/ui/macros/macro-crate-nonterminal-non-root.stderr new file mode 100644 index 000000000..1eca0186d --- /dev/null +++ b/tests/ui/macros/macro-crate-nonterminal-non-root.stderr @@ -0,0 +1,9 @@ +error[E0468]: an `extern crate` loading macros must be at the crate root + --> $DIR/macro-crate-nonterminal-non-root.rs:5:5 + | +LL | extern crate macro_crate_nonterminal; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0468`. diff --git a/tests/ui/macros/macro-crate-nonterminal-renamed.rs b/tests/ui/macros/macro-crate-nonterminal-renamed.rs new file mode 100644 index 000000000..87bd397f0 --- /dev/null +++ b/tests/ui/macros/macro-crate-nonterminal-renamed.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:macro_crate_nonterminal.rs + +#[macro_use] +extern crate macro_crate_nonterminal as new_name; + +pub fn main() { + new_name::check_local(); + assert_eq!(increment!(5), 6); +} diff --git a/tests/ui/macros/macro-crate-nonterminal.rs b/tests/ui/macros/macro-crate-nonterminal.rs new file mode 100644 index 000000000..4b1056fc7 --- /dev/null +++ b/tests/ui/macros/macro-crate-nonterminal.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:macro_crate_nonterminal.rs + +#[macro_use] +extern crate macro_crate_nonterminal; + +pub fn main() { + macro_crate_nonterminal::check_local(); + assert_eq!(increment!(5), 6); +} diff --git a/tests/ui/macros/macro-crate-use.rs b/tests/ui/macros/macro-crate-use.rs new file mode 100644 index 000000000..5c37cac96 --- /dev/null +++ b/tests/ui/macros/macro-crate-use.rs @@ -0,0 +1,17 @@ +// run-pass + +pub fn increment(x: usize) -> usize { + x + 1 +} + +#[macro_export] +macro_rules! increment { + ($x:expr) => ({ + use $crate::increment; + increment($x) + }) +} + +fn main() { + assert_eq!(increment!(3), 4); +} diff --git a/tests/ui/macros/macro-deep_expansion.rs b/tests/ui/macros/macro-deep_expansion.rs new file mode 100644 index 000000000..e13d8e1fc --- /dev/null +++ b/tests/ui/macros/macro-deep_expansion.rs @@ -0,0 +1,17 @@ +// run-pass + +macro_rules! foo2 { + () => { + "foo" + } +} + +macro_rules! foo { + () => { + foo2!() + } +} + +fn main() { + assert_eq!(concat!(foo!(), "bar"), "foobar") +} diff --git a/tests/ui/macros/macro-def-site-super.rs b/tests/ui/macros/macro-def-site-super.rs new file mode 100644 index 000000000..716a8ced5 --- /dev/null +++ b/tests/ui/macros/macro-def-site-super.rs @@ -0,0 +1,10 @@ +// `super` in a `macro` refers to the parent module of the macro itself and not its reexport. + +// check-pass +// aux-build:macro-def-site-super.rs + +extern crate macro_def_site_super; + +type A = macro_def_site_super::public::mac!(); + +fn main() {} diff --git a/tests/ui/macros/macro-delimiter-significance.rs b/tests/ui/macros/macro-delimiter-significance.rs new file mode 100644 index 000000000..89f222b05 --- /dev/null +++ b/tests/ui/macros/macro-delimiter-significance.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() { + vec![1_usize, 2, 3].len(); +} diff --git a/tests/ui/macros/macro-deprecation.rs b/tests/ui/macros/macro-deprecation.rs new file mode 100644 index 000000000..a7f327cf5 --- /dev/null +++ b/tests/ui/macros/macro-deprecation.rs @@ -0,0 +1,13 @@ +// check-pass +// aux-build:deprecated-macros.rs + +#[macro_use] extern crate deprecated_macros; + +#[deprecated(since = "1.0.0", note = "local deprecation note")] +#[macro_export] +macro_rules! local_deprecated{ () => () } + +fn main() { + local_deprecated!(); //~ WARN use of deprecated macro `local_deprecated`: local deprecation note + deprecated_macro!(); //~ WARN use of deprecated macro `deprecated_macro`: deprecation note +} diff --git a/tests/ui/macros/macro-deprecation.stderr b/tests/ui/macros/macro-deprecation.stderr new file mode 100644 index 000000000..07849d7ce --- /dev/null +++ b/tests/ui/macros/macro-deprecation.stderr @@ -0,0 +1,16 @@ +warning: use of deprecated macro `local_deprecated`: local deprecation note + --> $DIR/macro-deprecation.rs:11:5 + | +LL | local_deprecated!(); + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated macro `deprecated_macro`: deprecation note + --> $DIR/macro-deprecation.rs:12:5 + | +LL | deprecated_macro!(); + | ^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/macros/macro-doc-comments.rs b/tests/ui/macros/macro-doc-comments.rs new file mode 100644 index 000000000..fcc64cc06 --- /dev/null +++ b/tests/ui/macros/macro-doc-comments.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(non_snake_case)] + +macro_rules! doc { + ( + $(#[$outer:meta])* + mod $i:ident { + $(#![$inner:meta])* + } + ) => + ( + $(#[$outer])* + pub mod $i { + $(#![$inner])* + } + ) +} + +doc! { + /// Outer doc + mod Foo { + //! Inner doc + } +} + +fn main() { } diff --git a/tests/ui/macros/macro-doc-escapes.rs b/tests/ui/macros/macro-doc-escapes.rs new file mode 100644 index 000000000..ff5a5793b --- /dev/null +++ b/tests/ui/macros/macro-doc-escapes.rs @@ -0,0 +1,16 @@ +// run-pass +// When expanding a macro, documentation attributes (including documentation comments) must be +// passed "as is" without being parsed. Otherwise, some text will be incorrectly interpreted as +// escape sequences, leading to an ICE. +// +// Related issues: #25929, #25943 + +macro_rules! homura { + (#[$x:meta]) => () +} + +homura! { + /// \madoka \x41 +} + +fn main() { } diff --git a/tests/ui/macros/macro-doc-raw-str-hashes.rs b/tests/ui/macros/macro-doc-raw-str-hashes.rs new file mode 100644 index 000000000..a003bff3c --- /dev/null +++ b/tests/ui/macros/macro-doc-raw-str-hashes.rs @@ -0,0 +1,30 @@ +// run-pass +// The number of `#`s used to wrap the documentation comment should differ regarding the content. +// +// Related issue: #27489 + +macro_rules! homura { + ($x:expr, #[$y:meta]) => (assert_eq!($x, stringify!($y))) +} + +fn main() { + homura! { + r#"doc = r" Madoka""#, + /// Madoka + }; + + homura! { + r##"doc = r#" One quote mark: ["]"#"##, + /// One quote mark: ["] + }; + + homura! { + r##"doc = r#" Two quote marks: [""]"#"##, + /// Two quote marks: [""] + }; + + homura! { + r#####"doc = r####" Raw string ending sequences: ["###]"####"#####, + /// Raw string ending sequences: ["###] + }; +} diff --git a/tests/ui/macros/macro-error.rs b/tests/ui/macros/macro-error.rs new file mode 100644 index 000000000..59ed79e91 --- /dev/null +++ b/tests/ui/macros/macro-error.rs @@ -0,0 +1,9 @@ +macro_rules! foo { + ($a:expr) => a; //~ ERROR macro rhs must be delimited +} + +fn main() { + foo!(0); // Check that we report errors at macro definition, not expansion. + + let _: cfg!(foo) = (); //~ ERROR non-type macro in type position +} diff --git a/tests/ui/macros/macro-error.stderr b/tests/ui/macros/macro-error.stderr new file mode 100644 index 000000000..2539a6d51 --- /dev/null +++ b/tests/ui/macros/macro-error.stderr @@ -0,0 +1,14 @@ +error: macro rhs must be delimited + --> $DIR/macro-error.rs:2:18 + | +LL | ($a:expr) => a; + | ^ + +error: non-type macro in type position: cfg + --> $DIR/macro-error.rs:8:12 + | +LL | let _: cfg!(foo) = (); + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-expanded-include/file.txt b/tests/ui/macros/macro-expanded-include/file.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/macros/macro-expanded-include/foo/mod.rs b/tests/ui/macros/macro-expanded-include/foo/mod.rs new file mode 100644 index 000000000..cff110470 --- /dev/null +++ b/tests/ui/macros/macro-expanded-include/foo/mod.rs @@ -0,0 +1,9 @@ +// ignore-test + +macro_rules! m { + () => { include!("file.txt"); } +} + +macro_rules! n { + () => { unsafe { core::arch::asm!(include_str!("file.txt")); } } +} diff --git a/tests/ui/macros/macro-expanded-include/test.rs b/tests/ui/macros/macro-expanded-include/test.rs new file mode 100644 index 000000000..20da58a7e --- /dev/null +++ b/tests/ui/macros/macro-expanded-include/test.rs @@ -0,0 +1,13 @@ +// needs-asm-support +// build-pass (FIXME(62277): could be check-pass?) +#![allow(unused)] + +#[macro_use] +mod foo; + +m!(); +fn f() { + n!(); +} + +fn main() {} diff --git a/tests/ui/macros/macro-expansion-tests.rs b/tests/ui/macros/macro-expansion-tests.rs new file mode 100644 index 000000000..38f4937c1 --- /dev/null +++ b/tests/ui/macros/macro-expansion-tests.rs @@ -0,0 +1,40 @@ +#![allow(unused_macros)] + +mod macros_cant_escape_fns { + fn f() { + macro_rules! m { () => { 3 + 4 } } + } + fn g() -> i32 { m!() } + //~^ ERROR cannot find macro +} + +mod macros_cant_escape_mods { + mod f { + macro_rules! m { () => { 3 + 4 } } + } + fn g() -> i32 { m!() } + //~^ ERROR cannot find macro +} + +mod macros_can_escape_flattened_mods_test { + #[macro_use] + mod f { + macro_rules! m { () => { 3 + 4 } } + } + fn g() -> i32 { m!() } +} + +fn macro_tokens_should_match() { + macro_rules! m { (a) => { 13 } } + m!(a); +} + +// should be able to use a bound identifier as a literal in a macro definition: +fn self_macro_parsing() { + macro_rules! foo { (zz) => { 287; } } + fn f(zz: i32) { + foo!(zz); + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-expansion-tests.stderr b/tests/ui/macros/macro-expansion-tests.stderr new file mode 100644 index 000000000..8b3f7ca88 --- /dev/null +++ b/tests/ui/macros/macro-expansion-tests.stderr @@ -0,0 +1,18 @@ +error: cannot find macro `m` in this scope + --> $DIR/macro-expansion-tests.rs:7:21 + | +LL | fn g() -> i32 { m!() } + | ^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find macro `m` in this scope + --> $DIR/macro-expansion-tests.rs:15:21 + | +LL | fn g() -> i32 { m!() } + | ^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-export-inner-module.rs b/tests/ui/macros/macro-export-inner-module.rs new file mode 100644 index 000000000..1f23e90b6 --- /dev/null +++ b/tests/ui/macros/macro-export-inner-module.rs @@ -0,0 +1,9 @@ +// run-pass +//aux-build:macro_export_inner_module.rs + +#[macro_use] #[no_link] +extern crate macro_export_inner_module; + +pub fn main() { + assert_eq!(1, foo!()); +} diff --git a/tests/ui/macros/macro-first-set.rs b/tests/ui/macros/macro-first-set.rs new file mode 100644 index 000000000..eeb1ddd84 --- /dev/null +++ b/tests/ui/macros/macro-first-set.rs @@ -0,0 +1,272 @@ +// run-pass +#![allow(unused_macro_rules)] + +//{{{ issue 40569 ============================================================== + +macro_rules! my_struct { + ($(#[$meta:meta])* $ident:ident) => { + $(#[$meta])* struct $ident; + } +} + +my_struct!(#[derive(Debug, PartialEq)] Foo40569); + +fn test_40569() { + assert_eq!(Foo40569, Foo40569); +} + +//}}} + +//{{{ issue 26444 ============================================================== + +macro_rules! foo_26444 { + ($($beginning:ident),*; $middle:ident; $($end:ident),*) => { + stringify!($($beginning,)* $middle $(,$end)*) + } +} + +fn test_26444() { + assert_eq!("a, b, c, d, e", foo_26444!(a, b; c; d, e)); + assert_eq!("f", foo_26444!(; f ;)); +} + +macro_rules! pat_26444 { + ($fname:ident $($arg:pat)* =) => {} +} + +pat_26444!(foo 1 2 5...7 =); +pat_26444!(bar Some(ref x) Ok(ref mut y) &(w, z) =); + +//}}} + +//{{{ issue 40984 ============================================================== + +macro_rules! thread_local_40984 { + () => {}; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => { + thread_local_40984!($($rest)*); + }; + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => {}; +} + +thread_local_40984! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; +} + +//}}} + +//{{{ issue 35650 ============================================================== + +macro_rules! size { + ($ty:ty) => { + std::mem::size_of::<$ty>() + }; + ($size:tt) => { + $size + }; +} + +fn test_35650() { + assert_eq!(size!(u64), 8); + assert_eq!(size!(5), 5); +} + +//}}} + +//{{{ issue 27832 ============================================================== + +macro_rules! m { + ( $i:ident ) => (); + ( $t:tt $j:tt ) => (); +} + +m!(c); +m!(t 9); +m!(0 9); +m!(struct); +m!(struct Foo); + +macro_rules! m2 { + ( $b:expr ) => (); + ( $t:tt $u:tt ) => (); +} + +m2!(3); +m2!(1 2); +m2!(_ 1); +m2!(enum Foo); + +//}}} + +//{{{ issue 39964 ============================================================== + +macro_rules! foo_39964 { + ($a:ident) => {}; + (_) => {}; +} + +foo_39964!(_); + +//}}} + +//{{{ issue 34030 ============================================================== + +macro_rules! foo_34030 { + ($($t:ident),* /) => {}; +} + +foo_34030!(a, b/); +foo_34030!(a/); +foo_34030!(/); + +//}}} + +//{{{ issue 24189 ============================================================== + +macro_rules! foo_24189 { + ( + pub enum $name:ident { + $( #[$attr:meta] )* $var:ident + } + ) => { + pub enum $name { + $( #[$attr] )* $var + } + }; +} + +foo_24189! { + pub enum Foo24189 { + #[doc = "Bar"] Baz + } +} + +macro_rules! serializable { + ( + $(#[$struct_meta:meta])* + pub struct $name:ident { + $( + $(#[$field_meta:meta])* + $field:ident: $type_:ty + ),* , + } + ) => { + $(#[$struct_meta])* + pub struct $name { + $( + $(#[$field_meta])* + $field: $type_ + ),* , + } + } +} + +serializable! { + #[allow(dead_code)] + /// This is a test + pub struct Tester { + #[allow(dead_code)] + name: String, + } +} + +macro_rules! foo_24189_c { + ( $( > )* $x:ident ) => { }; +} +foo_24189_c!( > a ); + +fn test_24189() { + let _ = Foo24189::Baz; + let _ = Tester { name: "".to_owned() }; +} + +//}}} + +//{{{ issue 50903 ============================================================== + +macro_rules! foo_50903 { + ($($lif:lifetime ,)* #) => {}; +} + +foo_50903!('a, 'b, #); +foo_50903!('a, #); +foo_50903!(#); + +//}}} + +//{{{ issue 51477 ============================================================== + +macro_rules! foo_51477 { + ($lifetime:lifetime) => { + "last token is lifetime" + }; + ($other:tt) => { + "last token is other" + }; + ($first:tt $($rest:tt)*) => { + foo_51477!($($rest)*) + }; +} + +fn test_51477() { + assert_eq!("last token is lifetime", foo_51477!('a)); + assert_eq!("last token is other", foo_51477!(@)); + assert_eq!("last token is lifetime", foo_51477!(@ {} 'a)); +} + +//}}} + +//{{{ some more tests ========================================================== + +macro_rules! test_block { + (< $($b:block)* >) => {} +} + +test_block!(<>); +test_block!(<{}>); +test_block!(<{1}{2}>); + +macro_rules! test_ty { + ($($t:ty),* $(,)*) => {} +} + +test_ty!(); +test_ty!(,); +test_ty!(u8); +test_ty!(u8,); + +macro_rules! test_path { + ($($t:path),* $(,)*) => {} +} + +test_path!(); +test_path!(,); +test_path!(::std); +test_path!(std::ops,); +test_path!(any, super, super::super::self::path, X::Z<'a, T=U>); + +macro_rules! test_lifetime { + (1. $($l:lifetime)* $($b:block)*) => {}; + (2. $($b:block)* $($l:lifetime)*) => {}; +} + +test_lifetime!(1. 'a 'b {} {}); +test_lifetime!(2. {} {} 'a 'b); + +//}}} + +fn main() { + test_26444(); + test_40569(); + test_35650(); + test_24189(); + test_51477(); +} diff --git a/tests/ui/macros/macro-follow-rpass.rs b/tests/ui/macros/macro-follow-rpass.rs new file mode 100644 index 000000000..ca9365563 --- /dev/null +++ b/tests/ui/macros/macro-follow-rpass.rs @@ -0,0 +1,183 @@ +// run-pass +#![allow(unused_macros)] +// Check the macro follow sets (see corresponding cfail test). + +// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)} +macro_rules! follow_pat { + ($p:pat =>) => {}; + ($p:pat ,) => {}; + ($p:pat =) => {}; + ($p:pat |) => {}; + ($p:pat if) => {}; + ($p:pat in) => {}; +} +// FOLLOW(expr) = {FatArrow, Comma, Semicolon} +macro_rules! follow_expr { + ($e:expr =>) => {}; + ($e:expr ,) => {}; + ($e:expr ;) => {}; +} +// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or, +// Ident(as), Ident(where), OpenDelim(Bracket), Nonterminal(Block)} +macro_rules! follow_ty { + ($t:ty {}) => {}; + ($t:ty ,) => {}; + ($t:ty =>) => {}; + ($t:ty :) => {}; + ($t:ty =) => {}; + ($t:ty >) => {}; + ($t:ty ;) => {}; + ($t:ty |) => {}; + ($t:ty as) => {}; + ($t:ty where) => {}; + ($t:ty []) => {}; + ($t:ty $b:block) => {}; +} +// FOLLOW(stmt) = FOLLOW(expr) +macro_rules! follow_stmt { + ($s:stmt =>) => {}; + ($s:stmt ,) => {}; + ($s:stmt ;) => {}; +} +// FOLLOW(path) = FOLLOW(ty) +macro_rules! follow_path { + ($p:path {}) => {}; + ($p:path ,) => {}; + ($p:path =>) => {}; + ($p:path :) => {}; + ($p:path =) => {}; + ($p:path >) => {}; + ($p:path ;) => {}; + ($p:path |) => {}; + ($p:path as) => {}; + ($p:path where) => {}; + ($p:path []) => {}; + ($p:path $b:block) => {}; +} +// FOLLOW(block) = any token +macro_rules! follow_block { + ($b:block ()) => {}; + ($b:block []) => {}; + ($b:block {}) => {}; + ($b:block ,) => {}; + ($b:block =>) => {}; + ($b:block :) => {}; + ($b:block =) => {}; + ($b:block >) => {}; + ($b:block ;) => {}; + ($b:block |) => {}; + ($b:block +) => {}; + ($b:block ident) => {}; + ($b:block $p:pat) => {}; + ($b:block $e:expr) => {}; + ($b:block $t:ty) => {}; + ($b:block $s:stmt) => {}; + ($b:block $p:path) => {}; + ($b:block $c:block) => {}; + ($b:block $i:ident) => {}; + ($b:block $t:tt) => {}; + ($b:block $i:item) => {}; + ($b:block $m:meta) => {}; +} +// FOLLOW(ident) = any token +macro_rules! follow_ident { + ($i:ident ()) => {}; + ($i:ident []) => {}; + ($i:ident {}) => {}; + ($i:ident ,) => {}; + ($i:ident =>) => {}; + ($i:ident :) => {}; + ($i:ident =) => {}; + ($i:ident >) => {}; + ($i:ident ;) => {}; + ($i:ident |) => {}; + ($i:ident +) => {}; + ($i:ident ident) => {}; + ($i:ident $p:pat) => {}; + ($i:ident $e:expr) => {}; + ($i:ident $t:ty) => {}; + ($i:ident $s:stmt) => {}; + ($i:ident $p:path) => {}; + ($i:ident $b:block) => {}; + ($i:ident $j:ident) => {}; + ($i:ident $t:tt) => {}; + ($i:ident $j:item) => {}; + ($i:ident $m:meta) => {}; +} +// FOLLOW(tt) = any token +macro_rules! follow_tt { + ($t:tt ()) => {}; + ($t:tt []) => {}; + ($t:tt {}) => {}; + ($t:tt ,) => {}; + ($t:tt =>) => {}; + ($t:tt :) => {}; + ($t:tt =) => {}; + ($t:tt >) => {}; + ($t:tt ;) => {}; + ($t:tt |) => {}; + ($t:tt +) => {}; + ($t:tt ident) => {}; + ($t:tt $p:pat) => {}; + ($t:tt $e:expr) => {}; + ($t:tt $v:ty) => {}; + ($t:tt $s:stmt) => {}; + ($t:tt $p:path) => {}; + ($t:tt $b:block) => {}; + ($t:tt $i:ident) => {}; + ($t:tt $v:tt) => {}; + ($t:tt $i:item) => {}; + ($t:tt $m:meta) => {}; +} +// FOLLOW(item) = any token +macro_rules! follow_item { + ($i:item ()) => {}; + ($i:item []) => {}; + ($i:item {}) => {}; + ($i:item ,) => {}; + ($i:item =>) => {}; + ($i:item :) => {}; + ($i:item =) => {}; + ($i:item >) => {}; + ($i:item ;) => {}; + ($i:item |) => {}; + ($i:item +) => {}; + ($i:item ident) => {}; + ($i:item $p:pat) => {}; + ($i:item $e:expr) => {}; + ($i:item $t:ty) => {}; + ($i:item $s:stmt) => {}; + ($i:item $p:path) => {}; + ($i:item $b:block) => {}; + ($i:item $j:ident) => {}; + ($i:item $t:tt) => {}; + ($i:item $j:item) => {}; + ($i:item $m:meta) => {}; +} +// FOLLOW(meta) = any token +macro_rules! follow_meta { + ($m:meta ()) => {}; + ($m:meta []) => {}; + ($m:meta {}) => {}; + ($m:meta ,) => {}; + ($m:meta =>) => {}; + ($m:meta :) => {}; + ($m:meta =) => {}; + ($m:meta >) => {}; + ($m:meta ;) => {}; + ($m:meta |) => {}; + ($m:meta +) => {}; + ($m:meta ident) => {}; + ($m:meta $p:pat) => {}; + ($m:meta $e:expr) => {}; + ($m:meta $t:ty) => {}; + ($m:meta $s:stmt) => {}; + ($m:meta $p:path) => {}; + ($m:meta $b:block) => {}; + ($m:meta $i:ident) => {}; + ($m:meta $t:tt) => {}; + ($m:meta $i:item) => {}; + ($m:meta $n:meta) => {}; +} + +fn main() {} diff --git a/tests/ui/macros/macro-follow.rs b/tests/ui/macros/macro-follow.rs new file mode 100644 index 000000000..8054418d9 --- /dev/null +++ b/tests/ui/macros/macro-follow.rs @@ -0,0 +1,114 @@ +// +// Check the macro follow sets (see corresponding rpass test). + +#![allow(unused_macros)] + +// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)} +macro_rules! follow_pat { + ($p:pat ()) => {}; //~ERROR `$p:pat` is followed by `(` + ($p:pat []) => {}; //~ERROR `$p:pat` is followed by `[` + ($p:pat {}) => {}; //~ERROR `$p:pat` is followed by `{` + ($p:pat :) => {}; //~ERROR `$p:pat` is followed by `:` + ($p:pat >) => {}; //~ERROR `$p:pat` is followed by `>` + ($p:pat +) => {}; //~ERROR `$p:pat` is followed by `+` + ($p:pat ident) => {}; //~ERROR `$p:pat` is followed by `ident` + ($p:pat $q:pat) => {}; //~ERROR `$p:pat` is followed by `$q:pat` + ($p:pat $e:expr) => {}; //~ERROR `$p:pat` is followed by `$e:expr` + ($p:pat $t:ty) => {}; //~ERROR `$p:pat` is followed by `$t:ty` + ($p:pat $s:stmt) => {}; //~ERROR `$p:pat` is followed by `$s:stmt` + ($p:pat $q:path) => {}; //~ERROR `$p:pat` is followed by `$q:path` + ($p:pat $b:block) => {}; //~ERROR `$p:pat` is followed by `$b:block` + ($p:pat $i:ident) => {}; //~ERROR `$p:pat` is followed by `$i:ident` + ($p:pat $t:tt) => {}; //~ERROR `$p:pat` is followed by `$t:tt` + ($p:pat $i:item) => {}; //~ERROR `$p:pat` is followed by `$i:item` + ($p:pat $m:meta) => {}; //~ERROR `$p:pat` is followed by `$m:meta` +} +// FOLLOW(expr) = {FatArrow, Comma, Semicolon} +macro_rules! follow_expr { + ($e:expr ()) => {}; //~ERROR `$e:expr` is followed by `(` + ($e:expr []) => {}; //~ERROR `$e:expr` is followed by `[` + ($e:expr {}) => {}; //~ERROR `$e:expr` is followed by `{` + ($e:expr =) => {}; //~ERROR `$e:expr` is followed by `=` + ($e:expr |) => {}; //~ERROR `$e:expr` is followed by `|` + ($e:expr :) => {}; //~ERROR `$e:expr` is followed by `:` + ($e:expr >) => {}; //~ERROR `$e:expr` is followed by `>` + ($e:expr +) => {}; //~ERROR `$e:expr` is followed by `+` + ($e:expr ident) => {}; //~ERROR `$e:expr` is followed by `ident` + ($e:expr if) => {}; //~ERROR `$e:expr` is followed by `if` + ($e:expr in) => {}; //~ERROR `$e:expr` is followed by `in` + ($e:expr $p:pat) => {}; //~ERROR `$e:expr` is followed by `$p:pat` + ($e:expr $f:expr) => {}; //~ERROR `$e:expr` is followed by `$f:expr` + ($e:expr $t:ty) => {}; //~ERROR `$e:expr` is followed by `$t:ty` + ($e:expr $s:stmt) => {}; //~ERROR `$e:expr` is followed by `$s:stmt` + ($e:expr $p:path) => {}; //~ERROR `$e:expr` is followed by `$p:path` + ($e:expr $b:block) => {}; //~ERROR `$e:expr` is followed by `$b:block` + ($e:expr $i:ident) => {}; //~ERROR `$e:expr` is followed by `$i:ident` + ($e:expr $t:tt) => {}; //~ERROR `$e:expr` is followed by `$t:tt` + ($e:expr $i:item) => {}; //~ERROR `$e:expr` is followed by `$i:item` + ($e:expr $m:meta) => {}; //~ERROR `$e:expr` is followed by `$m:meta` +} +// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or, +// Ident(as), Ident(where), OpenDelim(Bracket), Nonterminal(Block)} +macro_rules! follow_ty { + ($t:ty ()) => {}; //~ERROR `$t:ty` is followed by `(` + ($t:ty []) => {}; // ok (RFC 1462) + ($t:ty +) => {}; //~ERROR `$t:ty` is followed by `+` + ($t:ty ident) => {}; //~ERROR `$t:ty` is followed by `ident` + ($t:ty if) => {}; //~ERROR `$t:ty` is followed by `if` + ($t:ty $p:pat) => {}; //~ERROR `$t:ty` is followed by `$p:pat` + ($t:ty $e:expr) => {}; //~ERROR `$t:ty` is followed by `$e:expr` + ($t:ty $r:ty) => {}; //~ERROR `$t:ty` is followed by `$r:ty` + ($t:ty $s:stmt) => {}; //~ERROR `$t:ty` is followed by `$s:stmt` + ($t:ty $p:path) => {}; //~ERROR `$t:ty` is followed by `$p:path` + ($t:ty $b:block) => {}; // ok (RFC 1494) + ($t:ty $i:ident) => {}; //~ERROR `$t:ty` is followed by `$i:ident` + ($t:ty $r:tt) => {}; //~ERROR `$t:ty` is followed by `$r:tt` + ($t:ty $i:item) => {}; //~ERROR `$t:ty` is followed by `$i:item` + ($t:ty $m:meta) => {}; //~ERROR `$t:ty` is followed by `$m:meta` +} +// FOLLOW(stmt) = FOLLOW(expr) +macro_rules! follow_stmt { + ($s:stmt ()) => {}; //~ERROR `$s:stmt` is followed by `(` + ($s:stmt []) => {}; //~ERROR `$s:stmt` is followed by `[` + ($s:stmt {}) => {}; //~ERROR `$s:stmt` is followed by `{` + ($s:stmt =) => {}; //~ERROR `$s:stmt` is followed by `=` + ($s:stmt |) => {}; //~ERROR `$s:stmt` is followed by `|` + ($s:stmt :) => {}; //~ERROR `$s:stmt` is followed by `:` + ($s:stmt >) => {}; //~ERROR `$s:stmt` is followed by `>` + ($s:stmt +) => {}; //~ERROR `$s:stmt` is followed by `+` + ($s:stmt ident) => {}; //~ERROR `$s:stmt` is followed by `ident` + ($s:stmt if) => {}; //~ERROR `$s:stmt` is followed by `if` + ($s:stmt in) => {}; //~ERROR `$s:stmt` is followed by `in` + ($s:stmt $p:pat) => {}; //~ERROR `$s:stmt` is followed by `$p:pat` + ($s:stmt $e:expr) => {}; //~ERROR `$s:stmt` is followed by `$e:expr` + ($s:stmt $t:ty) => {}; //~ERROR `$s:stmt` is followed by `$t:ty` + ($s:stmt $t:stmt) => {}; //~ERROR `$s:stmt` is followed by `$t:stmt` + ($s:stmt $p:path) => {}; //~ERROR `$s:stmt` is followed by `$p:path` + ($s:stmt $b:block) => {}; //~ERROR `$s:stmt` is followed by `$b:block` + ($s:stmt $i:ident) => {}; //~ERROR `$s:stmt` is followed by `$i:ident` + ($s:stmt $t:tt) => {}; //~ERROR `$s:stmt` is followed by `$t:tt` + ($s:stmt $i:item) => {}; //~ERROR `$s:stmt` is followed by `$i:item` + ($s:stmt $m:meta) => {}; //~ERROR `$s:stmt` is followed by `$m:meta` +} +// FOLLOW(path) = FOLLOW(ty) +macro_rules! follow_path { + ($p:path ()) => {}; //~ERROR `$p:path` is followed by `(` + ($p:path []) => {}; // ok (RFC 1462) + ($p:path +) => {}; //~ERROR `$p:path` is followed by `+` + ($p:path ident) => {}; //~ERROR `$p:path` is followed by `ident` + ($p:path if) => {}; //~ERROR `$p:path` is followed by `if` + ($p:path $q:pat) => {}; //~ERROR `$p:path` is followed by `$q:pat` + ($p:path $e:expr) => {}; //~ERROR `$p:path` is followed by `$e:expr` + ($p:path $t:ty) => {}; //~ERROR `$p:path` is followed by `$t:ty` + ($p:path $s:stmt) => {}; //~ERROR `$p:path` is followed by `$s:stmt` + ($p:path $q:path) => {}; //~ERROR `$p:path` is followed by `$q:path` + ($p:path $b:block) => {}; // ok (RFC 1494) + ($p:path $i:ident) => {}; //~ERROR `$p:path` is followed by `$i:ident` + ($p:path $t:tt) => {}; //~ERROR `$p:path` is followed by `$t:tt` + ($p:path $i:item) => {}; //~ERROR `$p:path` is followed by `$i:item` + ($p:path $m:meta) => {}; //~ERROR `$p:path` is followed by `$m:meta` +} +// FOLLOW(block) = any token +// FOLLOW(ident) = any token + +fn main() {} diff --git a/tests/ui/macros/macro-follow.stderr b/tests/ui/macros/macro-follow.stderr new file mode 100644 index 000000000..61ae79d23 --- /dev/null +++ b/tests/ui/macros/macro-follow.stderr @@ -0,0 +1,682 @@ +error: `$p:pat` is followed by `(`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:8:13 + | +LL | ($p:pat ()) => {}; + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `[`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:9:13 + | +LL | ($p:pat []) => {}; + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `{`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:10:13 + | +LL | ($p:pat {}) => {}; + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `:`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:11:13 + | +LL | ($p:pat :) => {}; + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `>`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:12:13 + | +LL | ($p:pat >) => {}; + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `+`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:13:13 + | +LL | ($p:pat +) => {}; + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `ident`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:14:13 + | +LL | ($p:pat ident) => {}; + | ^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$q:pat`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:15:13 + | +LL | ($p:pat $q:pat) => {}; + | ^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$e:expr`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:16:13 + | +LL | ($p:pat $e:expr) => {}; + | ^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$t:ty`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:17:13 + | +LL | ($p:pat $t:ty) => {}; + | ^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$s:stmt`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:18:13 + | +LL | ($p:pat $s:stmt) => {}; + | ^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$q:path`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:19:13 + | +LL | ($p:pat $q:path) => {}; + | ^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$b:block`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:20:13 + | +LL | ($p:pat $b:block) => {}; + | ^^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$i:ident`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:21:13 + | +LL | ($p:pat $i:ident) => {}; + | ^^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$t:tt`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:22:13 + | +LL | ($p:pat $t:tt) => {}; + | ^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$i:item`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:23:13 + | +LL | ($p:pat $i:item) => {}; + | ^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$p:pat` is followed by `$m:meta`, which is not allowed for `pat` fragments + --> $DIR/macro-follow.rs:24:13 + | +LL | ($p:pat $m:meta) => {}; + | ^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$e:expr` is followed by `(`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:28:14 + | +LL | ($e:expr ()) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `[`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:29:14 + | +LL | ($e:expr []) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `{`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:30:14 + | +LL | ($e:expr {}) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `=`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:31:14 + | +LL | ($e:expr =) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `|`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:32:14 + | +LL | ($e:expr |) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `:`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:33:14 + | +LL | ($e:expr :) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `>`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:34:14 + | +LL | ($e:expr >) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:35:14 + | +LL | ($e:expr +) => {}; + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `ident`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:36:14 + | +LL | ($e:expr ident) => {}; + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `if`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:37:14 + | +LL | ($e:expr if) => {}; + | ^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `in`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:38:14 + | +LL | ($e:expr in) => {}; + | ^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$p:pat`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:39:14 + | +LL | ($e:expr $p:pat) => {}; + | ^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$f:expr`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:40:14 + | +LL | ($e:expr $f:expr) => {}; + | ^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$t:ty`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:41:14 + | +LL | ($e:expr $t:ty) => {}; + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$s:stmt`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:42:14 + | +LL | ($e:expr $s:stmt) => {}; + | ^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$p:path`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:43:14 + | +LL | ($e:expr $p:path) => {}; + | ^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$b:block`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:44:14 + | +LL | ($e:expr $b:block) => {}; + | ^^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$i:ident`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:45:14 + | +LL | ($e:expr $i:ident) => {}; + | ^^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$t:tt`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:46:14 + | +LL | ($e:expr $t:tt) => {}; + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$i:item`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:47:14 + | +LL | ($e:expr $i:item) => {}; + | ^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$e:expr` is followed by `$m:meta`, which is not allowed for `expr` fragments + --> $DIR/macro-follow.rs:48:14 + | +LL | ($e:expr $m:meta) => {}; + | ^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$t:ty` is followed by `(`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:53:12 + | +LL | ($t:ty ()) => {}; + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `+`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:55:12 + | +LL | ($t:ty +) => {}; + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `ident`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:56:12 + | +LL | ($t:ty ident) => {}; + | ^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `if`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:57:12 + | +LL | ($t:ty if) => {}; + | ^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$p:pat`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:58:12 + | +LL | ($t:ty $p:pat) => {}; + | ^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$e:expr`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:59:12 + | +LL | ($t:ty $e:expr) => {}; + | ^^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$r:ty`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:60:12 + | +LL | ($t:ty $r:ty) => {}; + | ^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$s:stmt`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:61:12 + | +LL | ($t:ty $s:stmt) => {}; + | ^^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$p:path`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:62:12 + | +LL | ($t:ty $p:path) => {}; + | ^^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$i:ident`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:64:12 + | +LL | ($t:ty $i:ident) => {}; + | ^^^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$r:tt`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:65:12 + | +LL | ($t:ty $r:tt) => {}; + | ^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$i:item`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:66:12 + | +LL | ($t:ty $i:item) => {}; + | ^^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$t:ty` is followed by `$m:meta`, which is not allowed for `ty` fragments + --> $DIR/macro-follow.rs:67:12 + | +LL | ($t:ty $m:meta) => {}; + | ^^^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$s:stmt` is followed by `(`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:71:14 + | +LL | ($s:stmt ()) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `[`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:72:14 + | +LL | ($s:stmt []) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `{`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:73:14 + | +LL | ($s:stmt {}) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `=`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:74:14 + | +LL | ($s:stmt =) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `|`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:75:14 + | +LL | ($s:stmt |) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `:`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:76:14 + | +LL | ($s:stmt :) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `>`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:77:14 + | +LL | ($s:stmt >) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `+`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:78:14 + | +LL | ($s:stmt +) => {}; + | ^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `ident`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:79:14 + | +LL | ($s:stmt ident) => {}; + | ^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `if`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:80:14 + | +LL | ($s:stmt if) => {}; + | ^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `in`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:81:14 + | +LL | ($s:stmt in) => {}; + | ^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$p:pat`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:82:14 + | +LL | ($s:stmt $p:pat) => {}; + | ^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$e:expr`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:83:14 + | +LL | ($s:stmt $e:expr) => {}; + | ^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$t:ty`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:84:14 + | +LL | ($s:stmt $t:ty) => {}; + | ^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$t:stmt`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:85:14 + | +LL | ($s:stmt $t:stmt) => {}; + | ^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$p:path`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:86:14 + | +LL | ($s:stmt $p:path) => {}; + | ^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$b:block`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:87:14 + | +LL | ($s:stmt $b:block) => {}; + | ^^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$i:ident`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:88:14 + | +LL | ($s:stmt $i:ident) => {}; + | ^^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$t:tt`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:89:14 + | +LL | ($s:stmt $t:tt) => {}; + | ^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$i:item`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:90:14 + | +LL | ($s:stmt $i:item) => {}; + | ^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$s:stmt` is followed by `$m:meta`, which is not allowed for `stmt` fragments + --> $DIR/macro-follow.rs:91:14 + | +LL | ($s:stmt $m:meta) => {}; + | ^^^^^^^ not allowed after `stmt` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$p:path` is followed by `(`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:95:14 + | +LL | ($p:path ()) => {}; + | ^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `+`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:97:14 + | +LL | ($p:path +) => {}; + | ^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `ident`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:98:14 + | +LL | ($p:path ident) => {}; + | ^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `if`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:99:14 + | +LL | ($p:path if) => {}; + | ^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$q:pat`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:100:14 + | +LL | ($p:path $q:pat) => {}; + | ^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$e:expr`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:101:14 + | +LL | ($p:path $e:expr) => {}; + | ^^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$t:ty`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:102:14 + | +LL | ($p:path $t:ty) => {}; + | ^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$s:stmt`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:103:14 + | +LL | ($p:path $s:stmt) => {}; + | ^^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$q:path`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:104:14 + | +LL | ($p:path $q:path) => {}; + | ^^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$i:ident`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:106:14 + | +LL | ($p:path $i:ident) => {}; + | ^^^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$t:tt`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:107:14 + | +LL | ($p:path $t:tt) => {}; + | ^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$i:item`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:108:14 + | +LL | ($p:path $i:item) => {}; + | ^^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$p:path` is followed by `$m:meta`, which is not allowed for `path` fragments + --> $DIR/macro-follow.rs:109:14 + | +LL | ($p:path $m:meta) => {}; + | ^^^^^^^ not allowed after `path` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: aborting due to 85 previous errors + diff --git a/tests/ui/macros/macro-followed-by-seq-bad.rs b/tests/ui/macros/macro-followed-by-seq-bad.rs new file mode 100644 index 000000000..b73742f77 --- /dev/null +++ b/tests/ui/macros/macro-followed-by-seq-bad.rs @@ -0,0 +1,11 @@ +// Regression test for issue #25436: check that things which can be +// followed by any token also permit X* to come afterwards. + +#![allow(unused_macros)] + +macro_rules! foo { + ( $a:expr $($b:tt)* ) => { }; //~ ERROR not allowed for `expr` fragments + ( $a:ty $($b:tt)* ) => { }; //~ ERROR not allowed for `ty` fragments +} + +fn main() { } diff --git a/tests/ui/macros/macro-followed-by-seq-bad.stderr b/tests/ui/macros/macro-followed-by-seq-bad.stderr new file mode 100644 index 000000000..7097979ae --- /dev/null +++ b/tests/ui/macros/macro-followed-by-seq-bad.stderr @@ -0,0 +1,18 @@ +error: `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments + --> $DIR/macro-followed-by-seq-bad.rs:7:15 + | +LL | ( $a:expr $($b:tt)* ) => { }; + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$a:ty` is followed by `$b:tt`, which is not allowed for `ty` fragments + --> $DIR/macro-followed-by-seq-bad.rs:8:13 + | +LL | ( $a:ty $($b:tt)* ) => { }; + | ^^^^^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-followed-by-seq.rs b/tests/ui/macros/macro-followed-by-seq.rs new file mode 100644 index 000000000..71d59d8d3 --- /dev/null +++ b/tests/ui/macros/macro-followed-by-seq.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_macros)] +// Regression test for issue #25436: check that things which can be +// followed by any token also permit X* to come afterwards. + +macro_rules! foo { + ( $a:tt $($b:tt)* ) => { }; + ( $a:ident $($b:tt)* ) => { }; + ( $a:item $($b:tt)* ) => { }; + ( $a:block $($b:tt)* ) => { }; + ( $a:meta $($b:tt)* ) => { } +} + +fn main() { } diff --git a/tests/ui/macros/macro-in-expression-context-2.rs b/tests/ui/macros/macro-in-expression-context-2.rs new file mode 100644 index 000000000..9423f0a35 --- /dev/null +++ b/tests/ui/macros/macro-in-expression-context-2.rs @@ -0,0 +1,8 @@ +macro_rules! empty { () => () } + +fn main() { + match 42 { + _ => { empty!() } +//~^ ERROR macro expansion ends with an incomplete expression + }; +} diff --git a/tests/ui/macros/macro-in-expression-context-2.stderr b/tests/ui/macros/macro-in-expression-context-2.stderr new file mode 100644 index 000000000..d0312c485 --- /dev/null +++ b/tests/ui/macros/macro-in-expression-context-2.stderr @@ -0,0 +1,17 @@ +error: macro expansion ends with an incomplete expression: expected expression + --> $DIR/macro-in-expression-context-2.rs:5:16 + | +LL | macro_rules! empty { () => () } + | -- in this macro arm +... +LL | _ => { empty!() } + | ^^^^^^^^ expected expression + | + = note: the macro call doesn't expand to an expression, but it can expand to a statement +help: add `;` to interpret the expansion as a statement + | +LL | _ => { empty!(); } + | + + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-in-expression-context.fixed b/tests/ui/macros/macro-in-expression-context.fixed new file mode 100644 index 000000000..f22caf279 --- /dev/null +++ b/tests/ui/macros/macro-in-expression-context.fixed @@ -0,0 +1,27 @@ +// run-rustfix + +macro_rules! foo { + () => { + assert_eq!("A", "A"); + //~^ WARN trailing semicolon in macro + //~| WARN this was previously + //~| NOTE macro invocations at the end of a block + //~| NOTE to ignore the value produced by the macro + //~| NOTE for more information + //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default + assert_eq!("B", "B"); + } + //~^^ ERROR macro expansion ignores token `assert_eq` and any following + //~| NOTE the usage of `foo!` is likely invalid in expression context +} + +fn main() { + foo!(); + //~^ NOTE caused by the macro expansion here + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion +} diff --git a/tests/ui/macros/macro-in-expression-context.rs b/tests/ui/macros/macro-in-expression-context.rs new file mode 100644 index 000000000..1a056e582 --- /dev/null +++ b/tests/ui/macros/macro-in-expression-context.rs @@ -0,0 +1,27 @@ +// run-rustfix + +macro_rules! foo { + () => { + assert_eq!("A", "A"); + //~^ WARN trailing semicolon in macro + //~| WARN this was previously + //~| NOTE macro invocations at the end of a block + //~| NOTE to ignore the value produced by the macro + //~| NOTE for more information + //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default + assert_eq!("B", "B"); + } + //~^^ ERROR macro expansion ignores token `assert_eq` and any following + //~| NOTE the usage of `foo!` is likely invalid in expression context +} + +fn main() { + foo!() + //~^ NOTE caused by the macro expansion here + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion + //~| NOTE in this expansion +} diff --git a/tests/ui/macros/macro-in-expression-context.stderr b/tests/ui/macros/macro-in-expression-context.stderr new file mode 100644 index 000000000..3f492b141 --- /dev/null +++ b/tests/ui/macros/macro-in-expression-context.stderr @@ -0,0 +1,50 @@ +error: macro expansion ignores token `assert_eq` and any following + --> $DIR/macro-in-expression-context.rs:12:9 + | +LL | assert_eq!("B", "B"); + | ^^^^^^^^^ +... +LL | foo!() + | ------ caused by the macro expansion here + | + = note: the usage of `foo!` is likely invalid in expression context +help: you might be missing a semicolon here + | +LL | foo!(); + | + + +warning: trailing semicolon in macro used in expression position + --> $DIR/macro-in-expression-context.rs:5:29 + | +LL | assert_eq!("A", "A"); + | ^ +... +LL | foo!() + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error; 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: trailing semicolon in macro used in expression position + --> $DIR/macro-in-expression-context.rs:5:29 + | +LL | assert_eq!("A", "A"); + | ^ +... +LL | foo!() + | ------ in this macro invocation + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79813 + = note: macro invocations at the end of a block are treated as expressions + = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` + = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default + = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/macros/macro-in-fn.rs b/tests/ui/macros/macro-in-fn.rs new file mode 100644 index 000000000..d354fe4a7 --- /dev/null +++ b/tests/ui/macros/macro-in-fn.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(decl_macro)] + +pub fn moo() { + pub macro ABC() {{}} +} + +fn main() {} diff --git a/tests/ui/macros/macro-include-items.rs b/tests/ui/macros/macro-include-items.rs new file mode 100644 index 000000000..332bf59c9 --- /dev/null +++ b/tests/ui/macros/macro-include-items.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-pretty issue #37195 + +fn bar() {} + +include!(concat!("", "", "auxiliary/", "macro-include-items-item.rs")); + +fn main() { + foo(); + assert_eq!(include!(concat!("", "auxiliary/", "macro-include-items-expr.rs")), 1_usize); +} diff --git a/tests/ui/macros/macro-inner-attributes.rs b/tests/ui/macros/macro-inner-attributes.rs new file mode 100644 index 000000000..a8cda2307 --- /dev/null +++ b/tests/ui/macros/macro-inner-attributes.rs @@ -0,0 +1,20 @@ +#![feature(rustc_attrs)] + +macro_rules! test { ($nm:ident, + #[$a:meta], + $i:item) => (mod $nm { #![$a] $i }); } + +test!(a, + #[cfg(qux)], + pub fn bar() { }); + +test!(b, + #[cfg(not(qux))], + pub fn bar() { }); + +#[rustc_dummy] +fn main() { + a::bar(); + //~^ ERROR failed to resolve: use of undeclared crate or module `a` + b::bar(); +} diff --git a/tests/ui/macros/macro-inner-attributes.stderr b/tests/ui/macros/macro-inner-attributes.stderr new file mode 100644 index 000000000..77b648615 --- /dev/null +++ b/tests/ui/macros/macro-inner-attributes.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `a` + --> $DIR/macro-inner-attributes.rs:17:5 + | +LL | a::bar(); + | ^ use of undeclared crate or module `a` + | +help: there is a crate or module with a similar name + | +LL | b::bar(); + | ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro-input-future-proofing.rs b/tests/ui/macros/macro-input-future-proofing.rs new file mode 100644 index 000000000..9a5bdb08a --- /dev/null +++ b/tests/ui/macros/macro-input-future-proofing.rs @@ -0,0 +1,23 @@ +#![allow(unused_macros)] + +macro_rules! errors_everywhere { + ($ty:ty <) => (); //~ ERROR `$ty:ty` is followed by `<`, which is not allowed for `ty` + ($ty:ty < foo ,) => (); //~ ERROR `$ty:ty` is followed by `<`, which is not allowed for `ty` + ($ty:ty , ) => (); + ( ( $ty:ty ) ) => (); + ( { $ty:ty } ) => (); + ( [ $ty:ty ] ) => (); + ($bl:block < ) => (); + ($pa:pat >) => (); //~ ERROR `$pa:pat` is followed by `>`, which is not allowed for `pat` + ($pa:pat , ) => (); + ($pa:pat $pb:pat $ty:ty ,) => (); + //~^ ERROR `$pa:pat` is followed by `$pb:pat`, which is not allowed + //~^^ ERROR `$pb:pat` is followed by `$ty:ty`, which is not allowed + ($($ty:ty)* -) => (); //~ ERROR `$ty:ty` is followed by `-` + ($($a:ty, $b:ty)* -) => (); //~ ERROR `$b:ty` is followed by `-` + ($($ty:ty)-+) => (); //~ ERROR `$ty:ty` is followed by `-`, which is not allowed for `ty` + ( $($a:expr)* $($b:tt)* ) => { }; + //~^ ERROR `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments +} + +fn main() { } diff --git a/tests/ui/macros/macro-input-future-proofing.stderr b/tests/ui/macros/macro-input-future-proofing.stderr new file mode 100644 index 000000000..542486927 --- /dev/null +++ b/tests/ui/macros/macro-input-future-proofing.stderr @@ -0,0 +1,74 @@ +error: `$ty:ty` is followed by `<`, which is not allowed for `ty` fragments + --> $DIR/macro-input-future-proofing.rs:4:13 + | +LL | ($ty:ty <) => (); + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$ty:ty` is followed by `<`, which is not allowed for `ty` fragments + --> $DIR/macro-input-future-proofing.rs:5:13 + | +LL | ($ty:ty < foo ,) => (); + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$pa:pat` is followed by `>`, which is not allowed for `pat` fragments + --> $DIR/macro-input-future-proofing.rs:11:14 + | +LL | ($pa:pat >) => (); + | ^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$pa:pat` is followed by `$pb:pat`, which is not allowed for `pat` fragments + --> $DIR/macro-input-future-proofing.rs:13:14 + | +LL | ($pa:pat $pb:pat $ty:ty ,) => (); + | ^^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$pb:pat` is followed by `$ty:ty`, which is not allowed for `pat` fragments + --> $DIR/macro-input-future-proofing.rs:13:22 + | +LL | ($pa:pat $pb:pat $ty:ty ,) => (); + | ^^^^^^ not allowed after `pat` fragments + | + = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in` + +error: `$ty:ty` is followed by `-`, which is not allowed for `ty` fragments + --> $DIR/macro-input-future-proofing.rs:16:17 + | +LL | ($($ty:ty)* -) => (); + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$b:ty` is followed by `-`, which is not allowed for `ty` fragments + --> $DIR/macro-input-future-proofing.rs:17:23 + | +LL | ($($a:ty, $b:ty)* -) => (); + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$ty:ty` is followed by `-`, which is not allowed for `ty` fragments + --> $DIR/macro-input-future-proofing.rs:18:15 + | +LL | ($($ty:ty)-+) => (); + | ^ not allowed after `ty` fragments + | + = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where` + +error: `$a:expr` is followed by `$b:tt`, which is not allowed for `expr` fragments + --> $DIR/macro-input-future-proofing.rs:19:21 + | +LL | ( $($a:expr)* $($b:tt)* ) => { }; + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs new file mode 100644 index 000000000..35003a79a --- /dev/null +++ b/tests/ui/macros/macro-interpolation.rs @@ -0,0 +1,33 @@ +// run-pass + +macro_rules! overly_complicated { + ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) => + ({ + fn $fnname($arg: $ty) -> Option<$ty> $body + match $fnname($val) { + Some($pat) => { + $res + } + _ => { panic!(); } + } + }) + +} + +macro_rules! qpath { + (path, <$type:ty as $trait:path>::$name:ident) => { + <$type as $trait>::$name + }; + + (ty, <$type:ty as $trait:ty>::$name:ident) => { + <$type as $trait>::$name + }; +} + +pub fn main() { + let _: qpath!(path, ::Owned); + let _: qpath!(ty, ::Owned); + + assert!(overly_complicated!(f, x, Option, { return Some(x); }, + Some(8), Some(y), y) == 8) +} diff --git a/tests/ui/macros/macro-invalid-fragment-spec.rs b/tests/ui/macros/macro-invalid-fragment-spec.rs new file mode 100644 index 000000000..dc4d75096 --- /dev/null +++ b/tests/ui/macros/macro-invalid-fragment-spec.rs @@ -0,0 +1,8 @@ +macro_rules! foo( + ($x:foo) => () + //~^ ERROR invalid fragment specifier +); + +fn main() { + foo!(foo); +} diff --git a/tests/ui/macros/macro-invalid-fragment-spec.stderr b/tests/ui/macros/macro-invalid-fragment-spec.stderr new file mode 100644 index 000000000..b04734482 --- /dev/null +++ b/tests/ui/macros/macro-invalid-fragment-spec.stderr @@ -0,0 +1,10 @@ +error: invalid fragment specifier `foo` + --> $DIR/macro-invalid-fragment-spec.rs:2:6 + | +LL | ($x:foo) => () + | ^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs b/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs new file mode 100644 index 000000000..8f9dcb947 --- /dev/null +++ b/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs @@ -0,0 +1,10 @@ +// run-pass +// pretty-expanded FIXME #23616 + +macro_rules! four { + () => (4) +} + +fn main() { + let _x: [u16; four!()]; +} diff --git a/tests/ui/macros/macro-lifetime-used-with-bound.rs b/tests/ui/macros/macro-lifetime-used-with-bound.rs new file mode 100644 index 000000000..ea3f74c9a --- /dev/null +++ b/tests/ui/macros/macro-lifetime-used-with-bound.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_variables)] +macro_rules! foo { + ($l:lifetime, $l2:lifetime) => { + fn f<$l: $l2, $l2>(arg: &$l str, arg2: &$l2 str) -> &$l str { + arg + } + } +} + +pub fn main() { + foo!('a, 'b); + let x: &'static str = f("hi", "there"); + assert_eq!("hi", x); +} diff --git a/tests/ui/macros/macro-lifetime-used-with-labels.rs b/tests/ui/macros/macro-lifetime-used-with-labels.rs new file mode 100644 index 000000000..59017da3b --- /dev/null +++ b/tests/ui/macros/macro-lifetime-used-with-labels.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(stable_features)] +#![allow(unused_labels)] +#![allow(unreachable_code)] + +macro_rules! x { + ($a:lifetime) => { + $a: loop { + break $a; + panic!("failed"); + } + } +} +macro_rules! br { + ($a:lifetime) => { + break $a; + } +} +macro_rules! br2 { + ($b:lifetime) => { + 'b: loop { + break $b; // this $b should refer to the outer loop. + } + } +} +fn main() { + x!('a); + 'c: loop { + br!('c); + panic!("failed"); + } + 'b: loop { + br2!('b); + panic!("failed"); + } +} diff --git a/tests/ui/macros/macro-lifetime-used-with-static.rs b/tests/ui/macros/macro-lifetime-used-with-static.rs new file mode 100644 index 000000000..8552c4b81 --- /dev/null +++ b/tests/ui/macros/macro-lifetime-used-with-static.rs @@ -0,0 +1,14 @@ +// run-pass +macro_rules! foo { + ($l:lifetime) => { + fn f(arg: &$l str) -> &$l str { + arg + } + } +} + +pub fn main() { + foo!('static); + let x: &'static str = f("hi"); + assert_eq!("hi", x); +} diff --git a/tests/ui/macros/macro-lifetime.rs b/tests/ui/macros/macro-lifetime.rs new file mode 100644 index 000000000..5931fe009 --- /dev/null +++ b/tests/ui/macros/macro-lifetime.rs @@ -0,0 +1,14 @@ +// run-pass +macro_rules! foo { + ($l:lifetime) => { + fn f<$l>(arg: &$l str) -> &$l str { + arg + } + } +} + +pub fn main() { + foo!('a); + let x: &'static str = f("hi"); + assert_eq!("hi", x); +} diff --git a/tests/ui/macros/macro-literal.rs b/tests/ui/macros/macro-literal.rs new file mode 100644 index 000000000..3c2e71f9c --- /dev/null +++ b/tests/ui/macros/macro-literal.rs @@ -0,0 +1,134 @@ +// run-pass + +macro_rules! mtester { + ($l:literal) => { + &format!("macro caught literal: {}", $l) + }; + ($e:expr) => { + &format!("macro caught expr: {}", $e) + }; +} + +macro_rules! two_negative_literals { + ($l1:literal $l2:literal) => { + &format!("macro caught literals: {}, {}", $l1, $l2) + }; +} + +macro_rules! only_expr { + ($e:expr) => { + &format!("macro caught expr: {}", $e) + }; +} + +#[allow(unused_macro_rules)] +macro_rules! mtester_dbg { + ($l:literal) => { + &format!("macro caught literal: {:?}", $l) + }; + ($e:expr) => { + &format!("macro caught expr: {:?}", $e) + }; +} + +macro_rules! catch_range { + ($s:literal ..= $e:literal) => { + &format!("macro caught literal: {} ..= {}", $s, $e) + }; + (($s:expr) ..= ($e:expr)) => { // Must use ')' before '..=' + &format!("macro caught expr: {} ..= {}", $s, $e) + }; +} + +macro_rules! pat_match { + ($s:literal ..= $e:literal) => { + match 3 { + $s ..= $e => "literal, in range", + _ => "literal, other", + } + }; + ($s:pat) => { + match 3 { + $s => "pat, single", + _ => "pat, other", + } + }; +} + +macro_rules! match_attr { + (#[$attr:meta] $e:literal) => { + "attr matched literal" + }; + (#[$attr:meta] $e:expr) => { + "attr matched expr" + }; +} + +macro_rules! match_produced_attr { + ($lit: literal) => { + // Struct with doc comment passed via $literal + #[doc = $lit] + struct LiteralProduced; + }; + ($expr: expr) => { + struct ExprProduced; + }; +} + +macro_rules! test_user { + ($s:literal, $e:literal) => { + { + let mut v = Vec::new(); + for i in $s .. $e { + v.push(i); + } + "literal" + } + }; + ($s:expr, $e: expr) => { + { + let mut v = Vec::new(); + for i in $s .. $e { + v.push(i); + } + "expr" + } + }; +} + +pub fn main() { + // Cases where 'literal' catches + assert_eq!(mtester!("str"), "macro caught literal: str"); + assert_eq!(mtester!(2), "macro caught literal: 2"); + assert_eq!(mtester!(2.2), "macro caught literal: 2.2"); + assert_eq!(mtester!(1u32), "macro caught literal: 1"); + assert_eq!(mtester!(0x32), "macro caught literal: 50"); + assert_eq!(mtester!('c'), "macro caught literal: c"); + assert_eq!(mtester!(-1.2), "macro caught literal: -1.2"); + assert_eq!(two_negative_literals!(-2 -3), "macro caught literals: -2, -3"); + assert_eq!(catch_range!(2 ..= 3), "macro caught literal: 2 ..= 3"); + assert_eq!(match_attr!(#[attr] 1), "attr matched literal"); + assert_eq!(test_user!(10, 20), "literal"); + assert_eq!(mtester!(false), "macro caught literal: false"); + assert_eq!(mtester!(true), "macro caught literal: true"); + match_produced_attr!("a"); + let _a = LiteralProduced; + assert_eq!(pat_match!(1 ..= 3), "literal, in range"); + assert_eq!(pat_match!(4 ..= 6), "literal, other"); + + // Cases where 'expr' catches + assert_eq!(mtester!((-1.2)), "macro caught expr: -1.2"); + assert_eq!(only_expr!(-1.2), "macro caught expr: -1.2"); + assert_eq!(mtester!((1 + 3)), "macro caught expr: 4"); + assert_eq!(mtester_dbg!(()), "macro caught expr: ()"); + assert_eq!(catch_range!((1 + 1) ..= (2 + 2)), "macro caught expr: 2 ..= 4"); + assert_eq!(match_attr!(#[attr] (1 + 2)), "attr matched expr"); + assert_eq!(test_user!(10, (20 + 2)), "expr"); + + match_produced_attr!((3 + 2)); + let _b = ExprProduced; + + // Cases where 'pat' matched + assert_eq!(pat_match!(3), "pat, single"); + assert_eq!(pat_match!(6), "pat, other"); +} diff --git a/tests/ui/macros/macro-local-data-key-priv.rs b/tests/ui/macros/macro-local-data-key-priv.rs new file mode 100644 index 000000000..2e4f88f9a --- /dev/null +++ b/tests/ui/macros/macro-local-data-key-priv.rs @@ -0,0 +1,10 @@ +// check that the local data keys are private by default. + +mod bar { + thread_local!(static baz: f64 = 0.0); +} + +fn main() { + bar::baz.with(|_| ()); + //~^ ERROR `baz` is private +} diff --git a/tests/ui/macros/macro-local-data-key-priv.stderr b/tests/ui/macros/macro-local-data-key-priv.stderr new file mode 100644 index 000000000..fb8cab279 --- /dev/null +++ b/tests/ui/macros/macro-local-data-key-priv.stderr @@ -0,0 +1,16 @@ +error[E0603]: constant `baz` is private + --> $DIR/macro-local-data-key-priv.rs:8:10 + | +LL | bar::baz.with(|_| ()); + | ^^^ private constant + | +note: the constant `baz` is defined here + --> $DIR/macro-local-data-key-priv.rs:4:5 + | +LL | thread_local!(static baz: f64 = 0.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::__thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/macros/macro-match-nonterminal.rs b/tests/ui/macros/macro-match-nonterminal.rs new file mode 100644 index 000000000..5d9eb55fe --- /dev/null +++ b/tests/ui/macros/macro-match-nonterminal.rs @@ -0,0 +1,14 @@ +macro_rules! test { + ($a, $b) => { + //~^ ERROR missing fragment + //~| ERROR missing fragment + //~| ERROR missing fragment + //~| WARN this was previously accepted + //~| WARN this was previously accepted + () + }; +} + +fn main() { + test!() +} diff --git a/tests/ui/macros/macro-match-nonterminal.stderr b/tests/ui/macros/macro-match-nonterminal.stderr new file mode 100644 index 000000000..ef7261c02 --- /dev/null +++ b/tests/ui/macros/macro-match-nonterminal.stderr @@ -0,0 +1,27 @@ +error: missing fragment specifier + --> $DIR/macro-match-nonterminal.rs:2:8 + | +LL | ($a, $b) => { + | ^ + +error: missing fragment specifier + --> $DIR/macro-match-nonterminal.rs:2:8 + | +LL | ($a, $b) => { + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + = note: `#[deny(missing_fragment_specifier)]` on by default + +error: missing fragment specifier + --> $DIR/macro-match-nonterminal.rs:2:10 + | +LL | ($a, $b) => { + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/macro-meta-items-modern.rs b/tests/ui/macros/macro-meta-items-modern.rs new file mode 100644 index 000000000..bc6938d4a --- /dev/null +++ b/tests/ui/macros/macro-meta-items-modern.rs @@ -0,0 +1,11 @@ +// check-pass + +macro_rules! check { ($meta:meta) => () } + +check!(meta(a b c d)); +check!(meta[a b c d]); +check!(meta { a b c d }); +check!(meta); +check!(meta = 0); + +fn main() {} diff --git a/tests/ui/macros/macro-meta-items.rs b/tests/ui/macros/macro-meta-items.rs new file mode 100644 index 000000000..4cbc252ae --- /dev/null +++ b/tests/ui/macros/macro-meta-items.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: --cfg foo + +macro_rules! compiles_fine { + ($at:meta) => { + #[cfg($at)] + static MISTYPED: () = "foo"; + } +} +macro_rules! emit { + ($at:meta) => { + #[cfg($at)] + static MISTYPED: &'static str = "foo"; + } +} + +// item +compiles_fine!(bar); +emit!(foo); + +fn foo() { + println!("{}", MISTYPED); +} + +pub fn main() { + // statement + compiles_fine!(baz); + emit!(baz); + println!("{}", MISTYPED); +} diff --git a/tests/ui/macros/macro-method-issue-4621.rs b/tests/ui/macros/macro-method-issue-4621.rs new file mode 100644 index 000000000..342fad5f6 --- /dev/null +++ b/tests/ui/macros/macro-method-issue-4621.rs @@ -0,0 +1,10 @@ +// run-pass + +struct A; + +macro_rules! make_thirteen_method {() => (fn thirteen(&self)->isize {13})} +impl A { make_thirteen_method!(); } + +fn main() { + assert_eq!(A.thirteen(),13); +} diff --git a/tests/ui/macros/macro-missing-delimiters.rs b/tests/ui/macros/macro-missing-delimiters.rs new file mode 100644 index 000000000..290d7615e --- /dev/null +++ b/tests/ui/macros/macro-missing-delimiters.rs @@ -0,0 +1,7 @@ +macro_rules! baz( + baz => () //~ ERROR invalid macro matcher; +); + +fn main() { + baz!(baz); +} diff --git a/tests/ui/macros/macro-missing-delimiters.stderr b/tests/ui/macros/macro-missing-delimiters.stderr new file mode 100644 index 000000000..e7c37c8dd --- /dev/null +++ b/tests/ui/macros/macro-missing-delimiters.stderr @@ -0,0 +1,8 @@ +error: invalid macro matcher; matchers must be contained in balanced delimiters + --> $DIR/macro-missing-delimiters.rs:2:5 + | +LL | baz => () + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.rs b/tests/ui/macros/macro-missing-fragment-deduplication.rs new file mode 100644 index 000000000..c1e6ba746 --- /dev/null +++ b/tests/ui/macros/macro-missing-fragment-deduplication.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes + +macro_rules! m { + ($name) => {} + //~^ ERROR missing fragment + //~| ERROR missing fragment + //~| WARN this was previously accepted +} + +fn main() { + m!(); + m!(); + m!(); + m!(); +} diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.stderr b/tests/ui/macros/macro-missing-fragment-deduplication.stderr new file mode 100644 index 000000000..3b9e716e1 --- /dev/null +++ b/tests/ui/macros/macro-missing-fragment-deduplication.stderr @@ -0,0 +1,18 @@ +error: missing fragment specifier + --> $DIR/macro-missing-fragment-deduplication.rs:4:6 + | +LL | ($name) => {} + | ^^^^^ + +error: missing fragment specifier + --> $DIR/macro-missing-fragment-deduplication.rs:4:6 + | +LL | ($name) => {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + = note: `#[deny(missing_fragment_specifier)]` on by default + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs new file mode 100644 index 000000000..210c85ebb --- /dev/null +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -0,0 +1,26 @@ +#![warn(missing_fragment_specifier)] + +macro_rules! used_arm { + ( $( any_token $field_rust_type )* ) => {}; + //~^ ERROR missing fragment + //~| WARN missing fragment + //~| WARN this was previously accepted +} + +macro_rules! used_macro_unused_arm { + () => {}; + ( $name ) => {}; + //~^ WARN missing fragment + //~| WARN this was previously accepted +} + +macro_rules! unused_macro { + ( $name ) => {}; + //~^ WARN missing fragment + //~| WARN this was previously accepted +} + +fn main() { + used_arm!(); + used_macro_unused_arm!(); +} diff --git a/tests/ui/macros/macro-missing-fragment.stderr b/tests/ui/macros/macro-missing-fragment.stderr new file mode 100644 index 000000000..2aa1e58f6 --- /dev/null +++ b/tests/ui/macros/macro-missing-fragment.stderr @@ -0,0 +1,40 @@ +error: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:4:20 + | +LL | ( $( any_token $field_rust_type )* ) => {}; + | ^^^^^^^^^^^^^^^^ + +warning: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:4:20 + | +LL | ( $( any_token $field_rust_type )* ) => {}; + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 +note: the lint level is defined here + --> $DIR/macro-missing-fragment.rs:1:9 + | +LL | #![warn(missing_fragment_specifier)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:12:7 + | +LL | ( $name ) => {}; + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + +warning: missing fragment specifier + --> $DIR/macro-missing-fragment.rs:18:7 + | +LL | ( $name ) => {}; + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + +error: aborting due to previous error; 3 warnings emitted + diff --git a/tests/ui/macros/macro-multiple-items.rs b/tests/ui/macros/macro-multiple-items.rs new file mode 100644 index 000000000..3b6dfd9bc --- /dev/null +++ b/tests/ui/macros/macro-multiple-items.rs @@ -0,0 +1,16 @@ +// run-pass +macro_rules! make_foo { + () => ( + struct Foo; + + impl Foo { + fn bar(&self) {} + } + ) +} + +make_foo!(); + +pub fn main() { + Foo.bar() +} diff --git a/tests/ui/macros/macro-multiple-matcher-bindings.rs b/tests/ui/macros/macro-multiple-matcher-bindings.rs new file mode 100644 index 000000000..7d39dc0a5 --- /dev/null +++ b/tests/ui/macros/macro-multiple-matcher-bindings.rs @@ -0,0 +1,21 @@ +// Test that duplicate matcher binding names are caught at declaration time, rather than at macro +// invocation time. + +#![allow(unused_macros)] + +macro_rules! foo1 { + ($a:ident, $a:ident) => {}; //~ERROR duplicate matcher binding + ($a:ident, $a:path) => {}; //~ERROR duplicate matcher binding +} + +macro_rules! foo2 { + ($a:ident) => {}; // OK + ($a:path) => {}; // OK +} + +macro_rules! foo3 { + ($a:ident, $($a:ident),*) => {}; //~ERROR duplicate matcher binding + ($($a:ident)+ # $($($a:path),+);*) => {}; //~ERROR duplicate matcher binding +} + +fn main() {} diff --git a/tests/ui/macros/macro-multiple-matcher-bindings.stderr b/tests/ui/macros/macro-multiple-matcher-bindings.stderr new file mode 100644 index 000000000..3ad1297ff --- /dev/null +++ b/tests/ui/macros/macro-multiple-matcher-bindings.stderr @@ -0,0 +1,34 @@ +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:7:16 + | +LL | ($a:ident, $a:ident) => {}; + | -------- ^^^^^^^^ duplicate binding + | | + | previous binding + +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:8:16 + | +LL | ($a:ident, $a:path) => {}; + | -------- ^^^^^^^ duplicate binding + | | + | previous binding + +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:17:18 + | +LL | ($a:ident, $($a:ident),*) => {}; + | -------- ^^^^^^^^ duplicate binding + | | + | previous binding + +error: duplicate matcher binding + --> $DIR/macro-multiple-matcher-bindings.rs:18:25 + | +LL | ($($a:ident)+ # $($($a:path),+);*) => {}; + | -------- ^^^^^^^ duplicate binding + | | + | previous binding + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/macro-name-typo.rs b/tests/ui/macros/macro-name-typo.rs new file mode 100644 index 000000000..1ddc419d3 --- /dev/null +++ b/tests/ui/macros/macro-name-typo.rs @@ -0,0 +1,3 @@ +fn main() { + printlx!("oh noes!"); //~ ERROR cannot find +} diff --git a/tests/ui/macros/macro-name-typo.stderr b/tests/ui/macros/macro-name-typo.stderr new file mode 100644 index 000000000..d7c8aaae2 --- /dev/null +++ b/tests/ui/macros/macro-name-typo.stderr @@ -0,0 +1,11 @@ +error: cannot find macro `printlx` in this scope + --> $DIR/macro-name-typo.rs:2:5 + | +LL | printlx!("oh noes!"); + | ^^^^^^^ help: a macro with a similar name exists: `println` + --> $SRC_DIR/std/src/macros.rs:LL:COL + | + = note: similarly named macro `println` defined here + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-named-default.rs b/tests/ui/macros/macro-named-default.rs new file mode 100644 index 000000000..9b6cd1916 --- /dev/null +++ b/tests/ui/macros/macro-named-default.rs @@ -0,0 +1,18 @@ +// run-pass +macro_rules! default { + ($($x:tt)*) => { $($x)* } +} + +default! { + struct A; +} + +impl A { + default! { + fn foo(&self) {} + } +} + +fn main() { + A.foo(); +} diff --git a/tests/ui/macros/macro-nested_definition_issue-31946.rs b/tests/ui/macros/macro-nested_definition_issue-31946.rs new file mode 100644 index 000000000..a83c5b2e4 --- /dev/null +++ b/tests/ui/macros/macro-nested_definition_issue-31946.rs @@ -0,0 +1,9 @@ +// run-pass +fn main() { + println!("{}", { + macro_rules! foo { + ($name:expr) => { concat!("hello ", $name) } + } + foo!("rust") + }); +} diff --git a/tests/ui/macros/macro-nested_expr.rs b/tests/ui/macros/macro-nested_expr.rs new file mode 100644 index 000000000..f1433cbf4 --- /dev/null +++ b/tests/ui/macros/macro-nested_expr.rs @@ -0,0 +1,22 @@ +// run-pass +// #42164 + +#![feature(decl_macro)] +#![allow(dead_code)] + +pub macro m($inner_str:expr) { + #[doc = $inner_str] + struct S; +} + +macro_rules! define_f { + ($name:expr) => { + #[export_name = $name] + fn f() {} + } +} + +fn main() { + define_f!(concat!("exported_", "f")); + m!(stringify!(foo)); +} diff --git a/tests/ui/macros/macro-nested_stmt_macros.rs b/tests/ui/macros/macro-nested_stmt_macros.rs new file mode 100644 index 000000000..5d4758a0c --- /dev/null +++ b/tests/ui/macros/macro-nested_stmt_macros.rs @@ -0,0 +1,23 @@ +// run-pass +macro_rules! foo { + () => { + struct Bar; + struct Baz; + } +} + +macro_rules! grault { + () => { + foo!(); + struct Xyzzy; + } +} + +fn static_assert_exists() { } + +fn main() { + grault!(); + static_assert_exists::(); + static_assert_exists::(); + static_assert_exists::(); +} diff --git a/tests/ui/macros/macro-non-lifetime.rs b/tests/ui/macros/macro-non-lifetime.rs new file mode 100644 index 000000000..26e1f2afa --- /dev/null +++ b/tests/ui/macros/macro-non-lifetime.rs @@ -0,0 +1,8 @@ +// Test for issue #50381: non-lifetime passed to :lifetime. + +macro_rules! m { ($x:lifetime) => { } } + +fn main() { + m!(a); + //~^ ERROR no rules expected the token `a` +} diff --git a/tests/ui/macros/macro-non-lifetime.stderr b/tests/ui/macros/macro-non-lifetime.stderr new file mode 100644 index 000000000..e1ed87f94 --- /dev/null +++ b/tests/ui/macros/macro-non-lifetime.stderr @@ -0,0 +1,17 @@ +error: no rules expected the token `a` + --> $DIR/macro-non-lifetime.rs:6:8 + | +LL | macro_rules! m { ($x:lifetime) => { } } + | -------------- when calling this macro +... +LL | m!(a); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$x:lifetime` + --> $DIR/macro-non-lifetime.rs:3:19 + | +LL | macro_rules! m { ($x:lifetime) => { } } + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-nt-list.rs b/tests/ui/macros/macro-nt-list.rs new file mode 100644 index 000000000..36aa74f08 --- /dev/null +++ b/tests/ui/macros/macro-nt-list.rs @@ -0,0 +1,21 @@ +// run-pass +// pretty-expanded FIXME #23616 + +macro_rules! list { + ( ($($id:ident),*) ) => (()); + ( [$($id:ident),*] ) => (()); + ( {$($id:ident),*} ) => (()); +} + +macro_rules! tt_list { + ( ($($tt:tt),*) ) => (()); +} + +pub fn main() { + list!( () ); + list!( [] ); + list!( {} ); + + tt_list!( (a, b, c) ); + tt_list!( () ); +} diff --git a/tests/ui/macros/macro-of-higher-order.rs b/tests/ui/macros/macro-of-higher-order.rs new file mode 100644 index 000000000..ec551d6cd --- /dev/null +++ b/tests/ui/macros/macro-of-higher-order.rs @@ -0,0 +1,22 @@ +// run-pass + +macro_rules! higher_order { + (subst $lhs:tt => $rhs:tt) => ({ + macro_rules! anon { $lhs => $rhs } + anon!(1_usize, 2_usize, "foo") + }); +} + +macro_rules! outer { + ($x:expr; $fragment:ident) => { + macro_rules! inner { ($y:$fragment) => { $x + $y } } + } +} + +fn main() { + let val = higher_order!(subst ($x:expr, $y:expr, $foo:expr) => (($x + $y, $foo))); + assert_eq!(val, (3, "foo")); + + outer!(2; expr); + assert_eq!(inner!(3), 5); +} diff --git a/tests/ui/macros/macro-or-patterns-back-compat.fixed b/tests/ui/macros/macro-or-patterns-back-compat.fixed new file mode 100644 index 000000000..b0d56e9bb --- /dev/null +++ b/tests/ui/macros/macro-or-patterns-back-compat.fixed @@ -0,0 +1,39 @@ +// run-rustfix +// aux-build:or-pattern.rs + +#![deny(rust_2021_incompatible_or_patterns)] +#![allow(unused_macros)] + +#[macro_use] +extern crate or_pattern; + +macro_rules! foo { ($x:pat_param | $y:pat) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition +macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition + +macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok +macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok +macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => { + //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + //~| WARN this is accepted in the current edition + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); + a!(1|); +} diff --git a/tests/ui/macros/macro-or-patterns-back-compat.rs b/tests/ui/macros/macro-or-patterns-back-compat.rs new file mode 100644 index 000000000..9e24b5106 --- /dev/null +++ b/tests/ui/macros/macro-or-patterns-back-compat.rs @@ -0,0 +1,39 @@ +// run-rustfix +// aux-build:or-pattern.rs + +#![deny(rust_2021_incompatible_or_patterns)] +#![allow(unused_macros)] + +#[macro_use] +extern crate or_pattern; + +macro_rules! foo { ($x:pat | $y:pat) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition + +macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok +macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok +macro_rules! ogg { ($x:pat | $y:pat_param) => {} } +//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro +//~| WARN this is accepted in the current edition +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + //~| WARN this is accepted in the current edition + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); + a!(1|); +} diff --git a/tests/ui/macros/macro-or-patterns-back-compat.stderr b/tests/ui/macros/macro-or-patterns-back-compat.stderr new file mode 100644 index 000000000..e04dfefa4 --- /dev/null +++ b/tests/ui/macros/macro-or-patterns-back-compat.stderr @@ -0,0 +1,43 @@ +error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + --> $DIR/macro-or-patterns-back-compat.rs:10:21 + | +LL | macro_rules! foo { ($x:pat | $y:pat) => {} } + | ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/macro-or-patterns-back-compat.rs:4:9 + | +LL | #![deny(rust_2021_incompatible_or_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + --> $DIR/macro-or-patterns-back-compat.rs:13:23 + | +LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } + | ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + --> $DIR/macro-or-patterns-back-compat.rs:19:21 + | +LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} } + | ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro + --> $DIR/macro-or-patterns-back-compat.rs:23:26 + | +LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + | ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/macro-outer-attributes.rs b/tests/ui/macros/macro-outer-attributes.rs new file mode 100644 index 000000000..0752f7e31 --- /dev/null +++ b/tests/ui/macros/macro-outer-attributes.rs @@ -0,0 +1,20 @@ +#![feature(rustc_attrs)] + +macro_rules! test { ($nm:ident, + #[$a:meta], + $i:item) => (mod $nm { #[$a] $i }); } + +test!(a, + #[cfg(qux)], + pub fn bar() { }); + +test!(b, + #[cfg(not(qux))], + pub fn bar() { }); + +// test1!(#[bar]) +#[rustc_dummy] +fn main() { + a::bar(); //~ ERROR cannot find function `bar` in module `a` + b::bar(); +} diff --git a/tests/ui/macros/macro-outer-attributes.stderr b/tests/ui/macros/macro-outer-attributes.stderr new file mode 100644 index 000000000..4ea760ab8 --- /dev/null +++ b/tests/ui/macros/macro-outer-attributes.stderr @@ -0,0 +1,19 @@ +error[E0425]: cannot find function `bar` in module `a` + --> $DIR/macro-outer-attributes.rs:18:8 + | +LL | a::bar(); + | ^^^ not found in `a` + | +help: consider importing this function + | +LL | use b::bar; + | +help: if you import `bar`, refer to it directly + | +LL - a::bar(); +LL + bar(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/macro-parameter-span.rs b/tests/ui/macros/macro-parameter-span.rs new file mode 100644 index 000000000..5609f84e1 --- /dev/null +++ b/tests/ui/macros/macro-parameter-span.rs @@ -0,0 +1,13 @@ +macro_rules! foo { + ($id: ident) => { + $id + } +} + +// Testing that the error span points to the parameter 'x' in the callsite, +// not to the macro variable '$id' +fn main() { + foo!( + x //~ ERROR cannot find value `x` in this scope + ); +} diff --git a/tests/ui/macros/macro-parameter-span.stderr b/tests/ui/macros/macro-parameter-span.stderr new file mode 100644 index 000000000..24e3e89ea --- /dev/null +++ b/tests/ui/macros/macro-parameter-span.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/macro-parameter-span.rs:11:9 + | +LL | x + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/macro-pat-follow-2018.rs b/tests/ui/macros/macro-pat-follow-2018.rs new file mode 100644 index 000000000..ce2911de9 --- /dev/null +++ b/tests/ui/macros/macro-pat-follow-2018.rs @@ -0,0 +1,15 @@ +// run-pass +// edition:2018 + +macro_rules! pat_bar { + ($p:pat | $p2:pat) => {{ + match Some(1u8) { + $p | $p2 => {} + _ => {} + } + }}; +} + +fn main() { + pat_bar!(Some(1u8) | None); +} diff --git a/tests/ui/macros/macro-pat-follow.rs b/tests/ui/macros/macro-pat-follow.rs new file mode 100644 index 000000000..8e02789fd --- /dev/null +++ b/tests/ui/macros/macro-pat-follow.rs @@ -0,0 +1,21 @@ +// run-pass +macro_rules! pat_in { + ($p:pat in $e:expr) => {{ + let mut iter = $e.into_iter(); + while let $p = iter.next() {} + }}; +} + +macro_rules! pat_if { + ($p:pat if $e:expr) => {{ + match Some(1u8) { + $p if $e => {} + _ => {} + } + }}; +} + +fn main() { + pat_in!(Some(_) in 0..10); + pat_if!(Some(x) if x > 0); +} diff --git a/tests/ui/macros/macro-pat-neg-lit.rs b/tests/ui/macros/macro-pat-neg-lit.rs new file mode 100644 index 000000000..79c68fd25 --- /dev/null +++ b/tests/ui/macros/macro-pat-neg-lit.rs @@ -0,0 +1,25 @@ +// run-pass +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* + _ => None + } + } + } +} + +enum_number!(Change { + Down = -1, + None = 0, + Up = 1, +}); + +fn main() { + if let Some(Change::Down) = foo(-1) {} else { panic!() } +} diff --git a/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs b/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs new file mode 100644 index 000000000..f5a97eca2 --- /dev/null +++ b/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs @@ -0,0 +1,20 @@ +// edition:2021 +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); +} diff --git a/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr b/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr new file mode 100644 index 000000000..a06487be3 --- /dev/null +++ b/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr @@ -0,0 +1,32 @@ +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:3:28 + | +LL | macro_rules! foo { ($x:pat | $y:pat) => {} } + | ------ ^ not allowed after `pat` fragments + | | + | help: try a `pat_param` fragment specifier instead: `$x:pat_param` + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32 + | +LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } + | ------ ^ not allowed after `pat` fragments + | | + | help: try a `pat_param` fragment specifier instead: `$x:pat_param` + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36 + | +LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { + | -------- ^ not allowed after `pat` fragments + | | + | help: try a `pat_param` fragment specifier instead: `$pat:pat_param` + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/macro-pat-pattern-followed-by-or.rs b/tests/ui/macros/macro-pat-pattern-followed-by-or.rs new file mode 100644 index 000000000..54bd13d7e --- /dev/null +++ b/tests/ui/macros/macro-pat-pattern-followed-by-or.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } // should be ok +macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } // should be ok +macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { // should be ok + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); +} diff --git a/tests/ui/macros/macro-pat.rs b/tests/ui/macros/macro-pat.rs new file mode 100644 index 000000000..baf816e53 --- /dev/null +++ b/tests/ui/macros/macro-pat.rs @@ -0,0 +1,65 @@ +// run-pass + +macro_rules! mypat { + () => ( + Some('y') + ) +} + +macro_rules! char_x { + () => ( + 'x' + ) +} + +macro_rules! some { + ($x:pat) => ( + Some($x) + ) +} + +macro_rules! indirect { + () => ( + some!(char_x!()) + ) +} + +macro_rules! ident_pat { + ($x:ident) => ( + $x + ) +} + +fn f(c: Option) -> usize { + match c { + Some('x') => 1, + mypat!() => 2, + _ => 3, + } +} + +pub fn main() { + assert_eq!(1, f(Some('x'))); + assert_eq!(2, f(Some('y'))); + assert_eq!(3, f(None)); + + assert_eq!(1, match Some('x') { + Some(char_x!()) => 1, + _ => 2, + }); + + assert_eq!(1, match Some('x') { + some!(char_x!()) => 1, + _ => 2, + }); + + assert_eq!(1, match Some('x') { + indirect!() => 1, + _ => 2, + }); + + assert_eq!(3, { + let ident_pat!(x) = 2; + x+1 + }); +} diff --git a/tests/ui/macros/macro-pat2021-pattern-followed-by-or.rs b/tests/ui/macros/macro-pat2021-pattern-followed-by-or.rs new file mode 100644 index 000000000..b4be03aad --- /dev/null +++ b/tests/ui/macros/macro-pat2021-pattern-followed-by-or.rs @@ -0,0 +1,22 @@ +// edition:2021 + +#![allow(unused_macros)] +macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok +macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok +macro_rules! ogg { ($x:pat | $y:pat_param) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments +macro_rules! match_any { + ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + match $expr { + $( + $( $pat => $expr_arm, )+ + )+ + } + }; +} + +fn main() { + let result: Result = Err(42); + let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into()); + assert_eq!(int, 42); +} diff --git a/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr b/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr new file mode 100644 index 000000000..c3754dde0 --- /dev/null +++ b/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr @@ -0,0 +1,32 @@ +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:4:28 + | +LL | macro_rules! foo { ($x:pat | $y:pat) => {} } + | ------ ^ not allowed after `pat` fragments + | | + | help: try a `pat_param` fragment specifier instead: `$x:pat_param` + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:7:28 + | +LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} } + | ------ ^ not allowed after `pat` fragments + | | + | help: try a `pat_param` fragment specifier instead: `$x:pat_param` + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments + --> $DIR/macro-pat2021-pattern-followed-by-or.rs:9:35 + | +LL | ( $expr:expr , $( $( $pat:pat)|+ => $expr_arm:pat),+ ) => { + | -------- ^ not allowed after `pat` fragments + | | + | help: try a `pat_param` fragment specifier instead: `$pat:pat_param` + | + = note: allowed there are: `=>`, `,`, `=`, `if` or `in` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/macro-path-prelude-fail-1.rs b/tests/ui/macros/macro-path-prelude-fail-1.rs new file mode 100644 index 000000000..d93792bdf --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-1.rs @@ -0,0 +1,8 @@ +mod m { + fn check() { + Vec::clone!(); //~ ERROR failed to resolve: `Vec` is a struct, not a module + u8::clone!(); //~ ERROR failed to resolve: `u8` is a builtin type, not a module + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-path-prelude-fail-1.stderr b/tests/ui/macros/macro-path-prelude-fail-1.stderr new file mode 100644 index 000000000..f8377ffb3 --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-1.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: `Vec` is a struct, not a module + --> $DIR/macro-path-prelude-fail-1.rs:3:9 + | +LL | Vec::clone!(); + | ^^^ `Vec` is a struct, not a module + +error[E0433]: failed to resolve: `u8` is a builtin type, not a module + --> $DIR/macro-path-prelude-fail-1.rs:4:9 + | +LL | u8::clone!(); + | ^^ `u8` is a builtin type, not a module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro-path-prelude-fail-2.rs b/tests/ui/macros/macro-path-prelude-fail-2.rs new file mode 100644 index 000000000..816a3c4cc --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-2.rs @@ -0,0 +1,7 @@ +mod m { + fn check() { + Result::Ok!(); //~ ERROR failed to resolve: partially resolved path in a macro + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-path-prelude-fail-2.stderr b/tests/ui/macros/macro-path-prelude-fail-2.stderr new file mode 100644 index 000000000..9574b7a1e --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-2.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: partially resolved path in a macro + --> $DIR/macro-path-prelude-fail-2.rs:3:9 + | +LL | Result::Ok!(); + | ^^^^^^^^^^ partially resolved path in a macro + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro-path-prelude-fail-3.rs b/tests/ui/macros/macro-path-prelude-fail-3.rs new file mode 100644 index 000000000..68eb350a9 --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-3.rs @@ -0,0 +1,3 @@ +fn main() { + inline!(); //~ ERROR cannot find macro `inline` in this scope +} diff --git a/tests/ui/macros/macro-path-prelude-fail-3.stderr b/tests/ui/macros/macro-path-prelude-fail-3.stderr new file mode 100644 index 000000000..f1c3512bc --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-3.stderr @@ -0,0 +1,13 @@ +error: cannot find macro `inline` in this scope + --> $DIR/macro-path-prelude-fail-3.rs:2:5 + | +LL | inline!(); + | ^^^^^^ help: a macro with a similar name exists: `line` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: similarly named macro `line` defined here + | + = note: `inline` is in scope, but it is an attribute: `#[inline]` + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-path-prelude-fail-4.rs b/tests/ui/macros/macro-path-prelude-fail-4.rs new file mode 100644 index 000000000..0f93fcdaa --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-4.rs @@ -0,0 +1,4 @@ +#[derive(inline)] //~ ERROR expected derive macro, found built-in attribute `inline` +struct S; + +fn main() {} diff --git a/tests/ui/macros/macro-path-prelude-fail-4.stderr b/tests/ui/macros/macro-path-prelude-fail-4.stderr new file mode 100644 index 000000000..dfd6818b6 --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-fail-4.stderr @@ -0,0 +1,8 @@ +error: expected derive macro, found built-in attribute `inline` + --> $DIR/macro-path-prelude-fail-4.rs:1:10 + | +LL | #[derive(inline)] + | ^^^^^^ not a derive macro + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-path-prelude-pass.rs b/tests/ui/macros/macro-path-prelude-pass.rs new file mode 100644 index 000000000..7cf346286 --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-pass.rs @@ -0,0 +1,9 @@ +// check-pass + +mod m { + fn check() { + std::panic!(); // OK + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-path-prelude-shadowing.rs b/tests/ui/macros/macro-path-prelude-shadowing.rs new file mode 100644 index 000000000..d71812000 --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-shadowing.rs @@ -0,0 +1,33 @@ +// aux-build:macro-in-other-crate.rs + +#![feature(decl_macro)] + +macro_rules! add_macro_expanded_things_to_macro_prelude {() => { + #[macro_use] + extern crate macro_in_other_crate; +}} + +add_macro_expanded_things_to_macro_prelude!(); + +mod m1 { + fn check() { + inline!(); // OK. Theoretically ambiguous, but we do not consider built-in attributes + // as candidates for non-attribute macro invocations to avoid regressions + // on stable channel + } +} + +mod m2 { + pub mod std { + pub macro panic() {} + } +} + +mod m3 { + use m2::*; // glob-import user-defined `std` + fn check() { + std::panic!(); //~ ERROR `std` is ambiguous + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-path-prelude-shadowing.stderr b/tests/ui/macros/macro-path-prelude-shadowing.stderr new file mode 100644 index 000000000..4a864c2e9 --- /dev/null +++ b/tests/ui/macros/macro-path-prelude-shadowing.stderr @@ -0,0 +1,19 @@ +error[E0659]: `std` is ambiguous + --> $DIR/macro-path-prelude-shadowing.rs:29:9 + | +LL | std::panic!(); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution + = note: `std` could refer to a built-in crate +note: `std` could also refer to the module imported here + --> $DIR/macro-path-prelude-shadowing.rs:27:9 + | +LL | use m2::*; // glob-import user-defined `std` + | ^^^^^ + = help: consider adding an explicit import of `std` to disambiguate + = help: or use `self::std` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/macro-path.rs b/tests/ui/macros/macro-path.rs new file mode 100644 index 000000000..6c011c897 --- /dev/null +++ b/tests/ui/macros/macro-path.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_camel_case_types)] + + +mod m { + pub type t = isize; +} + +macro_rules! foo { + ($p:path) => ({ + fn f() -> $p { 10 } + f() + }) +} + +pub fn main() { + assert_eq!(foo!(m::t), 10); +} diff --git a/tests/ui/macros/macro-pub-matcher.rs b/tests/ui/macros/macro-pub-matcher.rs new file mode 100644 index 000000000..7b02a70be --- /dev/null +++ b/tests/ui/macros/macro-pub-matcher.rs @@ -0,0 +1,117 @@ +// run-pass +#![allow(dead_code, unused_imports, unused_macro_rules)] + +/** +Ensure that `:vis` matches can be captured in existing positions, and passed +through without the need for reparse tricks. +*/ +macro_rules! vis_passthru { + ($vis:vis const $name:ident: $ty:ty = $e:expr;) => { $vis const $name: $ty = $e; }; + ($vis:vis enum $name:ident {}) => { $vis struct $name {} }; + ($vis:vis extern "C" fn $name:ident() {}) => { $vis extern "C" fn $name() {} }; + ($vis:vis fn $name:ident() {}) => { $vis fn $name() {} }; + ($vis:vis mod $name:ident {}) => { $vis mod $name {} }; + ($vis:vis static $name:ident: $ty:ty = $e:expr;) => { $vis static $name: $ty = $e; }; + ($vis:vis struct $name:ident;) => { $vis struct $name; }; + ($vis:vis trait $name:ident {}) => { $vis trait $name {} }; + ($vis:vis type $name:ident = $ty:ty;) => { $vis type $name = $ty; }; + ($vis:vis use $path:ident as $name:ident;) => { $vis use self::$path as $name; }; +} + +mod with_pub { + vis_passthru! { pub const A: i32 = 0; } + vis_passthru! { pub enum B {} } + vis_passthru! { pub extern "C" fn c() {} } + vis_passthru! { pub mod d {} } + vis_passthru! { pub static E: i32 = 0; } + vis_passthru! { pub struct F; } + vis_passthru! { pub trait G {} } + vis_passthru! { pub type H = i32; } + vis_passthru! { pub use A as I; } +} + +mod without_pub { + vis_passthru! { const A: i32 = 0; } + vis_passthru! { enum B {} } + vis_passthru! { extern "C" fn c() {} } + vis_passthru! { mod d {} } + vis_passthru! { static E: i32 = 0; } + vis_passthru! { struct F; } + vis_passthru! { trait G {} } + vis_passthru! { type H = i32; } + vis_passthru! { use A as I; } +} + +mod with_pub_restricted { + vis_passthru! { pub(crate) const A: i32 = 0; } + vis_passthru! { pub(crate) enum B {} } + vis_passthru! { pub(crate) extern "C" fn c() {} } + vis_passthru! { pub(crate) mod d {} } + vis_passthru! { pub(crate) static E: i32 = 0; } + vis_passthru! { pub(crate) struct F; } + vis_passthru! { pub(crate) trait G {} } + vis_passthru! { pub(crate) type H = i32; } + vis_passthru! { pub(crate) use A as I; } +} + +mod with_crate { + vis_passthru! { pub(crate) const A: i32 = 0; } + vis_passthru! { pub(crate) enum B {} } + vis_passthru! { pub(crate) extern "C" fn c() {} } + vis_passthru! { pub(crate) mod d {} } + vis_passthru! { pub(crate) static E: i32 = 0; } + vis_passthru! { pub(crate) struct F; } + vis_passthru! { pub(crate) trait G {} } + vis_passthru! { pub(crate) type H = i32; } + vis_passthru! { pub(crate) use A as I; } +} + +mod garden { + mod with_pub_restricted_path { + vis_passthru! { pub(in garden) const A: i32 = 0; } + vis_passthru! { pub(in garden) enum B {} } + vis_passthru! { pub(in garden) extern "C" fn c() {} } + vis_passthru! { pub(in garden) mod d {} } + vis_passthru! { pub(in garden) static E: i32 = 0; } + vis_passthru! { pub(in garden) struct F; } + vis_passthru! { pub(in garden) trait G {} } + vis_passthru! { pub(in garden) type H = i32; } + vis_passthru! { pub(in garden) use A as I; } + } +} + +/* +Ensure that the `:vis` matcher works in a more complex situation: parsing a +struct definition. +*/ +macro_rules! vis_parse_struct { + ($(#[$($attrs:tt)*])* $vis:vis struct $name:ident {$($body:tt)*}) => { + vis_parse_struct! { @parse_fields $(#[$($attrs)*])*, $vis, $name, $($body)* } + }; + + ($(#[$($attrs:tt)*])* $vis:vis struct $name:ident ($($body:tt)*);) => { + vis_parse_struct! { @parse_tuple $(#[$($attrs)*])*, $vis, $name, $($body)* } + }; + + (@parse_fields + $(#[$attrs:meta])*, $vis:vis, $name:ident, $($fvis:vis $fname:ident: $fty:ty),* $(,)*) => { + $(#[$attrs])* $vis struct $name { $($fvis $fname: $fty,)* } + }; + + (@parse_tuple + $(#[$attrs:meta])*, $vis:vis, $name:ident, $($fvis:vis $fty:ty),* $(,)*) => { + $(#[$attrs])* $vis struct $name ( $($fvis $fty,)* ); + }; +} + +mod test_struct { + vis_parse_struct! { pub(crate) struct A { pub a: i32, b: i32, pub(crate) c: i32 } } + vis_parse_struct! { pub struct B { a: i32, pub(crate) b: i32, pub c: i32 } } + vis_parse_struct! { struct C { pub(crate) a: i32, pub b: i32, c: i32 } } + + vis_parse_struct! { pub(crate) struct D (pub i32, i32, pub(crate) i32); } + vis_parse_struct! { pub struct E (i32, pub(crate) i32, pub i32); } + vis_parse_struct! { struct F (pub(crate) i32, pub i32, i32); } +} + +fn main() {} diff --git a/tests/ui/macros/macro-reexport-removed.rs b/tests/ui/macros/macro-reexport-removed.rs new file mode 100644 index 000000000..874c94d08 --- /dev/null +++ b/tests/ui/macros/macro-reexport-removed.rs @@ -0,0 +1,8 @@ +// aux-build:two_macros.rs + +#![feature(macro_reexport)] //~ ERROR feature has been removed + +#[macro_reexport(macro_one)] //~ ERROR cannot find attribute `macro_reexport` in this scope +extern crate two_macros; + +fn main() {} diff --git a/tests/ui/macros/macro-reexport-removed.stderr b/tests/ui/macros/macro-reexport-removed.stderr new file mode 100644 index 000000000..475a586dd --- /dev/null +++ b/tests/ui/macros/macro-reexport-removed.stderr @@ -0,0 +1,17 @@ +error[E0557]: feature has been removed + --> $DIR/macro-reexport-removed.rs:3:12 + | +LL | #![feature(macro_reexport)] + | ^^^^^^^^^^^^^^ feature has been removed + | + = note: subsumed by `pub use` + +error: cannot find attribute `macro_reexport` in this scope + --> $DIR/macro-reexport-removed.rs:5:3 + | +LL | #[macro_reexport(macro_one)] + | ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/macros/macro-seq-followed-by-seq.rs b/tests/ui/macros/macro-seq-followed-by-seq.rs new file mode 100644 index 000000000..8f0f4fd4a --- /dev/null +++ b/tests/ui/macros/macro-seq-followed-by-seq.rs @@ -0,0 +1,17 @@ +// run-pass +// Test of allowing two sequences repetitions in a row, +// functionality added as byproduct of RFC amendment #1384 +// https://github.com/rust-lang/rfcs/pull/1384 + +// Old version of Rust would reject this macro definition, even though +// there are no local ambiguities (the initial `banana` and `orange` +// tokens are enough for the expander to distinguish which case is +// intended). +macro_rules! foo { + ( $(banana $a:ident)* $(orange $b:tt)* ) => { }; +} + +fn main() { + foo!( banana id1 banana id2 + orange hi orange (hello world) ); +} diff --git a/tests/ui/macros/macro-shadowing-relaxed.rs b/tests/ui/macros/macro-shadowing-relaxed.rs new file mode 100644 index 000000000..b2a639218 --- /dev/null +++ b/tests/ui/macros/macro-shadowing-relaxed.rs @@ -0,0 +1,25 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:macro-in-other-crate.rs + +#![feature(decl_macro)] + +macro_rules! my_include {() => { + // Outer + macro m() {} + #[macro_use(from_prelude)] extern crate macro_in_other_crate; + + fn inner() { + // Inner + macro m() {} + macro_rules! from_prelude { () => {} } + + // OK, both `m` and `from_prelude` are macro-expanded, + // but no more macro-expanded than their counterpart from outer scope. + m!(); + from_prelude!(); + } +}} + +my_include!(); + +fn main() {} diff --git a/tests/ui/macros/macro-shadowing.rs b/tests/ui/macros/macro-shadowing.rs new file mode 100644 index 000000000..7f956dd7d --- /dev/null +++ b/tests/ui/macros/macro-shadowing.rs @@ -0,0 +1,26 @@ +// aux-build:two_macros.rs + +#![allow(unused_macros)] + +macro_rules! foo { () => {} } +macro_rules! macro_one { () => {} } +#[macro_use(macro_two)] extern crate two_macros; + +macro_rules! m1 { () => { + macro_rules! foo { () => {} } + + #[macro_use] //~ ERROR `macro_two` is already in scope + extern crate two_macros as __; +}} +m1!(); + +foo!(); //~ ERROR `foo` is ambiguous + +macro_rules! m2 { () => { + macro_rules! foo { () => {} } + foo!(); +}} +m2!(); +//^ Since `foo` is not used outside this expansion, it is not a shadowing error. + +fn main() {} diff --git a/tests/ui/macros/macro-shadowing.stderr b/tests/ui/macros/macro-shadowing.stderr new file mode 100644 index 000000000..a052b43ac --- /dev/null +++ b/tests/ui/macros/macro-shadowing.stderr @@ -0,0 +1,37 @@ +error: `macro_two` is already in scope + --> $DIR/macro-shadowing.rs:12:5 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ +... +LL | m1!(); + | ----- in this macro invocation + | + = note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) + = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `foo` is ambiguous + --> $DIR/macro-shadowing.rs:17:1 + | +LL | foo!(); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `foo` could refer to the macro defined here + --> $DIR/macro-shadowing.rs:10:5 + | +LL | macro_rules! foo { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | m1!(); + | ----- in this macro invocation +note: `foo` could also refer to the macro defined here + --> $DIR/macro-shadowing.rs:5:1 + | +LL | macro_rules! foo { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/macro-stability-rpass.rs b/tests/ui/macros/macro-stability-rpass.rs new file mode 100644 index 000000000..2d02b9528 --- /dev/null +++ b/tests/ui/macros/macro-stability-rpass.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:unstable-macros.rs + +#![unstable(feature = "one_two_three_testing", issue = "none")] +#![feature(staged_api, unstable_macros, local_unstable)] + +#[macro_use] extern crate unstable_macros; + +#[unstable(feature = "local_unstable", issue = "none")] +macro_rules! local_unstable { () => () } + +fn main() { + unstable_macro!(); + local_unstable!(); +} diff --git a/tests/ui/macros/macro-stability.rs b/tests/ui/macros/macro-stability.rs new file mode 100644 index 000000000..ed7618a67 --- /dev/null +++ b/tests/ui/macros/macro-stability.rs @@ -0,0 +1,31 @@ +// aux-build:unstable-macros.rs + +#![feature(decl_macro)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[macro_use] +extern crate unstable_macros; + +#[unstable(feature = "local_unstable", issue = "none")] +macro_rules! local_unstable { () => () } + +#[unstable(feature = "local_unstable", issue = "none")] +macro local_unstable_modern() {} + +#[stable(feature = "deprecated_macros", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "local deprecation note")] +#[macro_export] +macro_rules! local_deprecated{ () => () } + +fn main() { + local_unstable!(); //~ ERROR use of unstable library feature 'local_unstable' + local_unstable_modern!(); //~ ERROR use of unstable library feature 'local_unstable' + unstable_macro!(); //~ ERROR use of unstable library feature 'unstable_macros' + // unstable_macro_modern!(); // ERROR use of unstable library feature 'unstable_macros' + + deprecated_macro!(); + //~^ WARN use of deprecated macro `deprecated_macro`: deprecation note + local_deprecated!(); + //~^ WARN use of deprecated macro `local_deprecated`: local deprecation note +} diff --git a/tests/ui/macros/macro-stability.stderr b/tests/ui/macros/macro-stability.stderr new file mode 100644 index 000000000..2cfdb52b1 --- /dev/null +++ b/tests/ui/macros/macro-stability.stderr @@ -0,0 +1,41 @@ +error[E0658]: use of unstable library feature 'local_unstable' + --> $DIR/macro-stability.rs:22:5 + | +LL | local_unstable!(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(local_unstable)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'local_unstable' + --> $DIR/macro-stability.rs:23:5 + | +LL | local_unstable_modern!(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(local_unstable)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_macros' + --> $DIR/macro-stability.rs:24:5 + | +LL | unstable_macro!(); + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_macros)]` to the crate attributes to enable + +warning: use of deprecated macro `deprecated_macro`: deprecation note + --> $DIR/macro-stability.rs:27:5 + | +LL | deprecated_macro!(); + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated macro `local_deprecated`: local deprecation note + --> $DIR/macro-stability.rs:29:5 + | +LL | local_deprecated!(); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/macro-stmt-matchers.rs b/tests/ui/macros/macro-stmt-matchers.rs new file mode 100644 index 000000000..a643e50e9 --- /dev/null +++ b/tests/ui/macros/macro-stmt-matchers.rs @@ -0,0 +1,7 @@ +// build-pass (FIXME(62277): could be check-pass?) + + +fn main() { + macro_rules! m { ($s:stmt;) => { $s } } + m!(vec![].push(0);); +} diff --git a/tests/ui/macros/macro-stmt.rs b/tests/ui/macros/macro-stmt.rs new file mode 100644 index 000000000..c9a0b879a --- /dev/null +++ b/tests/ui/macros/macro-stmt.rs @@ -0,0 +1,31 @@ +// run-pass +macro_rules! myfn { + ( $f:ident, ( $( $x:ident ),* ), $body:block ) => ( + fn $f( $( $x : isize),* ) -> isize $body + ) +} + +myfn!(add, (a,b), { return a+b; } ); + +pub fn main() { + + macro_rules! mylet { + ($x:ident, $val:expr) => ( + let $x = $val; + ) + } + + mylet!(y, 8*2); + assert_eq!(y, 16); + + myfn!(mult, (a,b), { a*b } ); + + assert_eq!(mult(2, add(4,4)), 16); + + macro_rules! actually_an_expr_macro { + () => ( 16 ) + } + + assert_eq!({ actually_an_expr_macro!() }, 16); + +} diff --git a/tests/ui/macros/macro-stmt_macro_in_expr_macro.rs b/tests/ui/macros/macro-stmt_macro_in_expr_macro.rs new file mode 100644 index 000000000..528d0b28b --- /dev/null +++ b/tests/ui/macros/macro-stmt_macro_in_expr_macro.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +macro_rules! foo { + () => { + struct Bar; + struct Baz; + } +} + +macro_rules! grault { + () => {{ + foo!(); + struct Xyzzy; + 0 + }} +} + +fn main() { + let x = grault!(); + assert_eq!(x, 0); +} diff --git a/tests/ui/macros/macro-tt-followed-by-seq.rs b/tests/ui/macros/macro-tt-followed-by-seq.rs new file mode 100644 index 000000000..080dbcfdd --- /dev/null +++ b/tests/ui/macros/macro-tt-followed-by-seq.rs @@ -0,0 +1,28 @@ +// run-pass +// Regression test for issue #25436: permit token-trees to be followed +// by sequences, enabling more general parsing. + +use self::Join::*; + +#[derive(Debug)] +#[allow(unused_tuple_struct_fields)] +enum Join { + Keep(A,B), + Skip(A,B), +} + +macro_rules! parse_list { + ( < $a:expr; > $($b:tt)* ) => { Keep(parse_item!($a),parse_list!($($b)*)) }; + ( $a:tt $($b:tt)* ) => { Skip(parse_item!($a), parse_list!($($b)*)) }; + ( ) => { () }; +} + +macro_rules! parse_item { + ( $x:expr ) => { $x } +} + +fn main() { + let list = parse_list!(<1;> 2 <3;> 4); + assert_eq!("Keep(1, Skip(2, Keep(3, Skip(4, ()))))", + format!("{:?}", list)); +} diff --git a/tests/ui/macros/macro-tt-matchers.rs b/tests/ui/macros/macro-tt-matchers.rs new file mode 100644 index 000000000..2ee41b088 --- /dev/null +++ b/tests/ui/macros/macro-tt-matchers.rs @@ -0,0 +1,11 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] + +macro_rules! foo { + ($x:tt) => (type Alias = $x;) +} + +foo!(Box); + + +fn main() {} diff --git a/tests/ui/macros/macro-use-all-and-none.rs b/tests/ui/macros/macro-use-all-and-none.rs new file mode 100644 index 000000000..c8bd44008 --- /dev/null +++ b/tests/ui/macros/macro-use-all-and-none.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:two_macros-rpass.rs + +#![warn(unused_attributes)] + +#[macro_use] +#[macro_use()] //~ WARNING unused attribute +extern crate two_macros_rpass; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/tests/ui/macros/macro-use-all-and-none.stderr b/tests/ui/macros/macro-use-all-and-none.stderr new file mode 100644 index 000000000..00b10dccd --- /dev/null +++ b/tests/ui/macros/macro-use-all-and-none.stderr @@ -0,0 +1,15 @@ +warning: unused attribute + --> $DIR/macro-use-all-and-none.rs:7:1 + | +LL | #[macro_use()] + | ^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `macro_use` with an empty list has no effect +note: the lint level is defined here + --> $DIR/macro-use-all-and-none.rs:4:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/macros/macro-use-all.rs b/tests/ui/macros/macro-use-all.rs new file mode 100644 index 000000000..48c7b77e5 --- /dev/null +++ b/tests/ui/macros/macro-use-all.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:two_macros.rs + +#[macro_use] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/tests/ui/macros/macro-use-bad-args-1.rs b/tests/ui/macros/macro-use-bad-args-1.rs new file mode 100644 index 000000000..ec0b64a10 --- /dev/null +++ b/tests/ui/macros/macro-use-bad-args-1.rs @@ -0,0 +1,6 @@ +#![no_std] + +#[macro_use(foo(bar))] //~ ERROR bad macro import +extern crate std; + +fn main() {} diff --git a/tests/ui/macros/macro-use-bad-args-1.stderr b/tests/ui/macros/macro-use-bad-args-1.stderr new file mode 100644 index 000000000..4e5482a51 --- /dev/null +++ b/tests/ui/macros/macro-use-bad-args-1.stderr @@ -0,0 +1,9 @@ +error[E0466]: bad macro import + --> $DIR/macro-use-bad-args-1.rs:3:13 + | +LL | #[macro_use(foo(bar))] + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0466`. diff --git a/tests/ui/macros/macro-use-bad-args-2.rs b/tests/ui/macros/macro-use-bad-args-2.rs new file mode 100644 index 000000000..c5f8f62c1 --- /dev/null +++ b/tests/ui/macros/macro-use-bad-args-2.rs @@ -0,0 +1,6 @@ +#![no_std] + +#[macro_use(foo="bar")] //~ ERROR bad macro import +extern crate std; + +fn main() {} diff --git a/tests/ui/macros/macro-use-bad-args-2.stderr b/tests/ui/macros/macro-use-bad-args-2.stderr new file mode 100644 index 000000000..c958104ea --- /dev/null +++ b/tests/ui/macros/macro-use-bad-args-2.stderr @@ -0,0 +1,9 @@ +error[E0466]: bad macro import + --> $DIR/macro-use-bad-args-2.rs:3:13 + | +LL | #[macro_use(foo="bar")] + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0466`. diff --git a/tests/ui/macros/macro-use-both.rs b/tests/ui/macros/macro-use-both.rs new file mode 100644 index 000000000..ed5d1312f --- /dev/null +++ b/tests/ui/macros/macro-use-both.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:two_macros.rs + +#[macro_use(macro_one, macro_two)] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/tests/ui/macros/macro-use-one.rs b/tests/ui/macros/macro-use-one.rs new file mode 100644 index 000000000..f74795e68 --- /dev/null +++ b/tests/ui/macros/macro-use-one.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:two_macros.rs + +#[macro_use(macro_two)] +extern crate two_macros; + +pub fn main() { + macro_two!(); +} diff --git a/tests/ui/macros/macro-use-scope.rs b/tests/ui/macros/macro-use-scope.rs new file mode 100644 index 000000000..5e58fc9c1 --- /dev/null +++ b/tests/ui/macros/macro-use-scope.rs @@ -0,0 +1,22 @@ +// aux-build:two_macros.rs + +// build-pass (FIXME(62277): could be check-pass?) +#![allow(unused)] + +fn f() { + let _ = macro_one!(); +} +#[macro_use(macro_one)] // Check that this macro is usable in the above function +extern crate two_macros; + +fn g() { + macro_two!(); +} +macro_rules! m { () => { + #[macro_use(macro_two)] // Check that this macro is usable in the above function + extern crate two_macros as _two_macros; +} } +m!(); + + +fn main() {} diff --git a/tests/ui/macros/macro-use-undef.rs b/tests/ui/macros/macro-use-undef.rs new file mode 100644 index 000000000..ae3054e7b --- /dev/null +++ b/tests/ui/macros/macro-use-undef.rs @@ -0,0 +1,8 @@ +// aux-build:two_macros.rs + +#[macro_use(macro_two, no_way)] //~ ERROR imported macro not found +extern crate two_macros; + +pub fn main() { + macro_two!(); +} diff --git a/tests/ui/macros/macro-use-undef.stderr b/tests/ui/macros/macro-use-undef.stderr new file mode 100644 index 000000000..85b86e221 --- /dev/null +++ b/tests/ui/macros/macro-use-undef.stderr @@ -0,0 +1,9 @@ +error[E0469]: imported macro not found + --> $DIR/macro-use-undef.rs:3:24 + | +LL | #[macro_use(macro_two, no_way)] + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0469`. diff --git a/tests/ui/macros/macro-use-wrong-name.rs b/tests/ui/macros/macro-use-wrong-name.rs new file mode 100644 index 000000000..d142b5800 --- /dev/null +++ b/tests/ui/macros/macro-use-wrong-name.rs @@ -0,0 +1,9 @@ +// aux-build:two_macros.rs + +#[macro_use(macro_one)] +extern crate two_macros; + +pub fn main() { + macro_two!(); + //~^ ERROR cannot find macro +} diff --git a/tests/ui/macros/macro-use-wrong-name.stderr b/tests/ui/macros/macro-use-wrong-name.stderr new file mode 100644 index 000000000..ca5f0f190 --- /dev/null +++ b/tests/ui/macros/macro-use-wrong-name.stderr @@ -0,0 +1,16 @@ +error: cannot find macro `macro_two` in this scope + --> $DIR/macro-use-wrong-name.rs:7:5 + | +LL | macro_two!(); + | ^^^^^^^^^ help: a macro with a similar name exists: `macro_one` + | + ::: $DIR/auxiliary/two_macros.rs:2:1 + | +LL | macro_rules! macro_one { () => ("one") } + | ---------------------- similarly named macro `macro_one` defined here + | + = help: consider importing this macro: + two_macros::macro_two + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro-with-attrs1.rs b/tests/ui/macros/macro-with-attrs1.rs new file mode 100644 index 000000000..4e943b224 --- /dev/null +++ b/tests/ui/macros/macro-with-attrs1.rs @@ -0,0 +1,13 @@ +// run-pass +// compile-flags: --cfg foo + + +#[cfg(foo)] +macro_rules! foo { () => (1) } + +#[cfg(not(foo))] +macro_rules! foo { () => (2) } + +pub fn main() { + assert_eq!(foo!(), 1); +} diff --git a/tests/ui/macros/macro-with-attrs2.rs b/tests/ui/macros/macro-with-attrs2.rs new file mode 100644 index 000000000..78c408102 --- /dev/null +++ b/tests/ui/macros/macro-with-attrs2.rs @@ -0,0 +1,11 @@ +// run-pass + +#[cfg(foo)] +macro_rules! foo { () => (1) } + +#[cfg(not(foo))] +macro_rules! foo { () => (2) } + +pub fn main() { + assert_eq!(foo!(), 2); +} diff --git a/tests/ui/macros/macro-with-braces-in-expr-position.rs b/tests/ui/macros/macro-with-braces-in-expr-position.rs new file mode 100644 index 000000000..f7d87434d --- /dev/null +++ b/tests/ui/macros/macro-with-braces-in-expr-position.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +macro_rules! expr { ($e: expr) => { $e } } + +macro_rules! spawn { + ($($code: tt)*) => { + expr!(thread::spawn(move|| {$($code)*}).join()) + } +} + +pub fn main() { + spawn! { + println!("stmt"); + }; + let _ = spawn! { + println!("expr"); + }; +} diff --git a/tests/ui/macros/macro_path_as_generic_bound.rs b/tests/ui/macros/macro_path_as_generic_bound.rs new file mode 100644 index 000000000..663f85688 --- /dev/null +++ b/tests/ui/macros/macro_path_as_generic_bound.rs @@ -0,0 +1,9 @@ +trait Foo {} + +macro_rules! foo(($t:path) => { + impl Foo for T {} +}); + +foo!(m::m2::A); //~ ERROR failed to resolve + +fn main() {} diff --git a/tests/ui/macros/macro_path_as_generic_bound.stderr b/tests/ui/macros/macro_path_as_generic_bound.stderr new file mode 100644 index 000000000..00d954d24 --- /dev/null +++ b/tests/ui/macros/macro_path_as_generic_bound.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `m` + --> $DIR/macro_path_as_generic_bound.rs:7:6 + | +LL | foo!(m::m2::A); + | ^ use of undeclared crate or module `m` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/macro_rules-unmatchable-literals.rs b/tests/ui/macros/macro_rules-unmatchable-literals.rs new file mode 100644 index 000000000..bde0fe1a0 --- /dev/null +++ b/tests/ui/macros/macro_rules-unmatchable-literals.rs @@ -0,0 +1,14 @@ +// Pinning tests for things that don't work to make sure we notice if that changes + +#![crate_type = "lib"] + +macro_rules! octal_with_bad_digit { + ( 0o1238 ) => {}; //~ ERROR invalid digit +} + +macro_rules! binary_with_bad_digit { + ( 0b012 ) => {}; //~ ERROR invalid digit +} + +// This can't happen for Hex and Decimal as things like `123A` and `0xFFG` +// get treated as unknown *suffixes*, rather than digits. diff --git a/tests/ui/macros/macro_rules-unmatchable-literals.stderr b/tests/ui/macros/macro_rules-unmatchable-literals.stderr new file mode 100644 index 000000000..956a66979 --- /dev/null +++ b/tests/ui/macros/macro_rules-unmatchable-literals.stderr @@ -0,0 +1,14 @@ +error: invalid digit for a base 8 literal + --> $DIR/macro_rules-unmatchable-literals.rs:6:12 + | +LL | ( 0o1238 ) => {}; + | ^ + +error: invalid digit for a base 2 literal + --> $DIR/macro_rules-unmatchable-literals.rs:10:11 + | +LL | ( 0b012 ) => {}; + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro_undefined.rs b/tests/ui/macros/macro_undefined.rs new file mode 100644 index 000000000..6ca1eb568 --- /dev/null +++ b/tests/ui/macros/macro_undefined.rs @@ -0,0 +1,13 @@ +// Test macro_undefined issue + +mod m { + #[macro_export] + macro_rules! kl { + () => () + } +} + +fn main() { + k!(); //~ ERROR cannot find + kl!(); +} diff --git a/tests/ui/macros/macro_undefined.stderr b/tests/ui/macros/macro_undefined.stderr new file mode 100644 index 000000000..4ab16bd10 --- /dev/null +++ b/tests/ui/macros/macro_undefined.stderr @@ -0,0 +1,11 @@ +error: cannot find macro `k` in this scope + --> $DIR/macro_undefined.rs:11:5 + | +LL | macro_rules! kl { + | --------------- similarly named macro `kl` defined here +... +LL | k!(); + | ^ help: a macro with a similar name exists: `kl` + +error: aborting due to previous error + diff --git a/tests/ui/macros/macro_with_super_2.rs b/tests/ui/macros/macro_with_super_2.rs new file mode 100644 index 000000000..2901a74f6 --- /dev/null +++ b/tests/ui/macros/macro_with_super_2.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:macro_with_super_1.rs + +// pretty-expanded FIXME #23616 + +#[macro_use] +extern crate macro_with_super_1; + +declare!(); + +fn main() { + bbb::ccc(); +} diff --git a/tests/ui/macros/macros-in-extern.rs b/tests/ui/macros/macros-in-extern.rs new file mode 100644 index 000000000..568ae3a85 --- /dev/null +++ b/tests/ui/macros/macros-in-extern.rs @@ -0,0 +1,51 @@ +// run-pass +// ignore-wasm32 + +#![feature(decl_macro)] + +macro_rules! returns_isize( + ($ident:ident) => ( + fn $ident() -> isize; + ) +); + +macro takes_u32_returns_u32($ident:ident) { + fn $ident(arg: u32) -> u32; +} + +macro_rules! emits_nothing( + () => () +); + +macro_rules! emits_multiple( + () => { + fn f1() -> u32; + fn f2() -> u32; + } +); + +mod defs { + #[no_mangle] + extern "C" fn f1() -> u32 { + 1 + } + #[no_mangle] + extern "C" fn f2() -> u32 { + 2 + } +} + +fn main() { + assert_eq!(unsafe { rust_get_test_int() }, 1); + assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32); + assert_eq!(unsafe { f1() }, 1); + assert_eq!(unsafe { f2() }, 2); +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + returns_isize!(rust_get_test_int); + takes_u32_returns_u32!(rust_dbg_extern_identity_u32); + emits_nothing!(); + emits_multiple!(); +} diff --git a/tests/ui/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs new file mode 100644 index 000000000..ab14c3589 --- /dev/null +++ b/tests/ui/macros/macros-nonfatal-errors.rs @@ -0,0 +1,139 @@ +// normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG (" + +// test that errors in a (selection) of macros don't kill compilation +// immediately, so that we get more errors listed at a time. + +#![feature(trace_macros, concat_idents)] +#![feature(stmt_expr_attributes)] + +use std::arch::asm; + +#[derive(Default)] +struct DefaultInnerAttrStruct { + #[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants + foo: (), +} + +#[derive(Default)] +struct DefaultInnerAttrTupleStruct(#[default] ()); +//~^ ERROR the `#[default]` attribute may only be used on unit enum variants + +#[derive(Default)] +#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants +struct DefaultOuterAttrStruct {} + +#[derive(Default)] +#[default] //~ ERROR the `#[default]` attribute may only be used on unit enum variants +enum DefaultOuterAttrEnum { + #[default] + Foo, +} + +#[rustfmt::skip] // needs some work to handle this case +#[repr(u8)] +#[derive(Default)] +enum AttrOnInnerExpression { + Foo = #[default] 0, //~ ERROR the `#[default]` attribute may only be used on unit enum variants + Bar([u8; #[default] 1]), //~ ERROR the `#[default]` attribute may only be used on unit enum variants + #[default] + Baz, +} + +#[derive(Default)] //~ ERROR no default declared +enum NoDeclaredDefault { + Foo, + Bar, +} + +#[derive(Default)] //~ ERROR multiple declared defaults +enum MultipleDefaults { + #[default] + Foo, + #[default] + Bar, + #[default] + Baz, +} + +#[derive(Default)] +enum ExtraDeriveTokens { + #[default = 1] //~ ERROR `#[default]` attribute does not accept a value + Foo, +} + +#[derive(Default)] +enum TwoDefaultAttrs { + #[default] + #[default] + Foo, //~ERROR multiple `#[default]` attributes + Bar, +} + +#[derive(Default)] +enum ManyDefaultAttrs { + #[default] + #[default] + #[default] + #[default] + Foo, //~ERROR multiple `#[default]` attributes + Bar, +} + +#[derive(Default)] +enum DefaultHasFields { + #[default] + Foo {}, //~ ERROR the `#[default]` attribute may only be used on unit enum variants + Bar, +} + +#[derive(Default)] +enum NonExhaustiveDefault { + #[default] + #[non_exhaustive] + Foo, //~ ERROR default variant must be exhaustive + Bar, +} + +fn main() { + asm!(invalid); //~ ERROR + llvm_asm!(invalid); //~ ERROR + + concat_idents!("not", "idents"); //~ ERROR + + option_env!(invalid); //~ ERROR + env!(invalid); //~ ERROR + env!(foo, abr, baz); //~ ERROR + env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); //~ ERROR + + format!(invalid); //~ ERROR + + include!(invalid); //~ ERROR + + include_str!(invalid); //~ ERROR + include_str!("i'd be quite surprised if a file with this name existed"); //~ ERROR + include_bytes!(invalid); //~ ERROR + include_bytes!("i'd be quite surprised if a file with this name existed"); //~ ERROR + + trace_macros!(invalid); //~ ERROR +} + +/// Check that `#[derive(Default)]` does use a `T : Default` bound when the +/// `#[default]` variant is `#[non_exhaustive]` (should this end up allowed). +const _: () = { + #[derive(Default)] + enum NonExhaustiveDefaultGeneric { + #[default] + #[non_exhaustive] + Foo, //~ ERROR default variant must be exhaustive + Bar(T), + } + + fn assert_impls_default() {} + + enum NotDefault {} + + // Note: the `derive(Default)` currently bails early enough for trait-checking + // not to happen. Should it bail late enough, or even pass, make sure to + // assert that the following line fails. + let _ = assert_impls_default::>; +}; diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr new file mode 100644 index 000000000..d42f6c179 --- /dev/null +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -0,0 +1,235 @@ +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:13:5 + | +LL | #[default] + | ^^^^^^^^^^ + +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:18:36 + | +LL | struct DefaultInnerAttrTupleStruct(#[default] ()); + | ^^^^^^^^^^ + +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:22:1 + | +LL | #[default] + | ^^^^^^^^^^ + +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:26:1 + | +LL | #[default] + | ^^^^^^^^^^ + +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:36:11 + | +LL | Foo = #[default] 0, + | ^^^^^^^^^^ + +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:37:14 + | +LL | Bar([u8; #[default] 1]), + | ^^^^^^^^^^ + +error: no default declared + --> $DIR/macros-nonfatal-errors.rs:42:10 + | +LL | #[derive(Default)] + | ^^^^^^^ + | + = help: make a unit variant default by placing `#[default]` above it + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: multiple declared defaults + --> $DIR/macros-nonfatal-errors.rs:48:10 + | +LL | #[derive(Default)] + | ^^^^^^^ +... +LL | Foo, + | --- first default +LL | #[default] +LL | Bar, + | --- additional default +LL | #[default] +LL | Baz, + | --- additional default + | + = note: only one variant can be default + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `#[default]` attribute does not accept a value + --> $DIR/macros-nonfatal-errors.rs:60:5 + | +LL | #[default = 1] + | ^^^^^^^^^^^^^^ + | + = help: try using `#[default]` + +error: multiple `#[default]` attributes + --> $DIR/macros-nonfatal-errors.rs:68:5 + | +LL | #[default] + | ---------- `#[default]` used here +LL | #[default] + | ---------- `#[default]` used again here +LL | Foo, + | ^^^ + | + = note: only one `#[default]` attribute is needed +help: try removing this + --> $DIR/macros-nonfatal-errors.rs:67:5 + | +LL | #[default] + | ^^^^^^^^^^ + +error: multiple `#[default]` attributes + --> $DIR/macros-nonfatal-errors.rs:78:5 + | +LL | #[default] + | ---------- `#[default]` used here +LL | #[default] + | ---------- `#[default]` used again here +... +LL | Foo, + | ^^^ + | + = note: only one `#[default]` attribute is needed +help: try removing these + --> $DIR/macros-nonfatal-errors.rs:75:5 + | +LL | #[default] + | ^^^^^^^^^^ +LL | #[default] + | ^^^^^^^^^^ +LL | #[default] + | ^^^^^^^^^^ + +error: the `#[default]` attribute may only be used on unit enum variants + --> $DIR/macros-nonfatal-errors.rs:85:5 + | +LL | Foo {}, + | ^^^ + | + = help: consider a manual implementation of `Default` + +error: default variant must be exhaustive + --> $DIR/macros-nonfatal-errors.rs:93:5 + | +LL | #[non_exhaustive] + | ----------------- declared `#[non_exhaustive]` here +LL | Foo, + | ^^^ + | + = help: consider a manual implementation of `Default` + +error: asm template must be a string literal + --> $DIR/macros-nonfatal-errors.rs:98:10 + | +LL | asm!(invalid); + | ^^^^^^^ + +error: concat_idents! requires ident args + --> $DIR/macros-nonfatal-errors.rs:101:5 + | +LL | concat_idents!("not", "idents"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: argument must be a string literal + --> $DIR/macros-nonfatal-errors.rs:103:17 + | +LL | option_env!(invalid); + | ^^^^^^^ + +error: expected string literal + --> $DIR/macros-nonfatal-errors.rs:104:10 + | +LL | env!(invalid); + | ^^^^^^^ + +error: expected string literal + --> $DIR/macros-nonfatal-errors.rs:105:10 + | +LL | env!(foo, abr, baz); + | ^^^ + +error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined + --> $DIR/macros-nonfatal-errors.rs:106:5 + | +LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: format argument must be a string literal + --> $DIR/macros-nonfatal-errors.rs:108:13 + | +LL | format!(invalid); + | ^^^^^^^ + | +help: you might be missing a string literal to format with + | +LL | format!("{}", invalid); + | +++++ + +error: argument must be a string literal + --> $DIR/macros-nonfatal-errors.rs:110:14 + | +LL | include!(invalid); + | ^^^^^^^ + +error: argument must be a string literal + --> $DIR/macros-nonfatal-errors.rs:112:18 + | +LL | include_str!(invalid); + | ^^^^^^^ + +error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/macros-nonfatal-errors.rs:113:5 + | +LL | include_str!("i'd be quite surprised if a file with this name existed"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: argument must be a string literal + --> $DIR/macros-nonfatal-errors.rs:114:20 + | +LL | include_bytes!(invalid); + | ^^^^^^^ + +error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/macros-nonfatal-errors.rs:115:5 + | +LL | include_bytes!("i'd be quite surprised if a file with this name existed"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trace_macros! accepts only `true` or `false` + --> $DIR/macros-nonfatal-errors.rs:117:5 + | +LL | trace_macros!(invalid); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: default variant must be exhaustive + --> $DIR/macros-nonfatal-errors.rs:127:9 + | +LL | #[non_exhaustive] + | ----------------- declared `#[non_exhaustive]` here +LL | Foo, + | ^^^ + | + = help: consider a manual implementation of `Default` + +error: cannot find macro `llvm_asm` in this scope + --> $DIR/macros-nonfatal-errors.rs:99:5 + | +LL | llvm_asm!(invalid); + | ^^^^^^^^ + +error: aborting due to 28 previous errors + diff --git a/tests/ui/macros/malformed_macro_lhs.rs b/tests/ui/macros/malformed_macro_lhs.rs new file mode 100644 index 000000000..f57d2fb4d --- /dev/null +++ b/tests/ui/macros/malformed_macro_lhs.rs @@ -0,0 +1,7 @@ +macro_rules! my_precioooous { + t => (1); //~ ERROR invalid macro matcher +} + +fn main() { + my_precioooous!(); +} diff --git a/tests/ui/macros/malformed_macro_lhs.stderr b/tests/ui/macros/malformed_macro_lhs.stderr new file mode 100644 index 000000000..adf64b089 --- /dev/null +++ b/tests/ui/macros/malformed_macro_lhs.stderr @@ -0,0 +1,8 @@ +error: invalid macro matcher; matchers must be contained in balanced delimiters + --> $DIR/malformed_macro_lhs.rs:2:5 + | +LL | t => (1); + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/meta-item-absolute-path.rs b/tests/ui/macros/meta-item-absolute-path.rs new file mode 100644 index 000000000..8ed911cbc --- /dev/null +++ b/tests/ui/macros/meta-item-absolute-path.rs @@ -0,0 +1,5 @@ +#[derive(::Absolute)] //~ ERROR failed to resolve + //~| ERROR failed to resolve +struct S; + +fn main() {} diff --git a/tests/ui/macros/meta-item-absolute-path.stderr b/tests/ui/macros/meta-item-absolute-path.stderr new file mode 100644 index 000000000..c53971e24 --- /dev/null +++ b/tests/ui/macros/meta-item-absolute-path.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: maybe a missing crate `Absolute`? + --> $DIR/meta-item-absolute-path.rs:1:12 + | +LL | #[derive(::Absolute)] + | ^^^^^^^^ maybe a missing crate `Absolute`? + +error[E0433]: failed to resolve: maybe a missing crate `Absolute`? + --> $DIR/meta-item-absolute-path.rs:1:12 + | +LL | #[derive(::Absolute)] + | ^^^^^^^^ maybe a missing crate `Absolute`? + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.rs b/tests/ui/macros/meta-variable-depth-outside-repeat.rs new file mode 100644 index 000000000..b7fb94785 --- /dev/null +++ b/tests/ui/macros/meta-variable-depth-outside-repeat.rs @@ -0,0 +1,12 @@ +#![feature(macro_metavar_expr)] + +macro_rules! metavar { + ( $i:expr ) => { + ${length(0)} + //~^ ERROR meta-variable expression `length` with depth parameter must be called inside of a macro repetition + }; +} + +const _: i32 = metavar!(0); + +fn main() {} diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr new file mode 100644 index 000000000..fad150cad --- /dev/null +++ b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr @@ -0,0 +1,8 @@ +error: meta-variable expression `length` with depth parameter must be called inside of a macro repetition + --> $DIR/meta-variable-depth-outside-repeat.rs:5:10 + | +LL | ${length(0)} + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/macros/meta-variable-misuse.rs b/tests/ui/macros/meta-variable-misuse.rs new file mode 100644 index 000000000..99a2f9401 --- /dev/null +++ b/tests/ui/macros/meta-variable-misuse.rs @@ -0,0 +1,34 @@ +// run-pass +#![deny(meta_variable_misuse)] + +macro_rules! foo { + ($($m:ident $($f:ident $v:tt)+),*) => { + $($(macro_rules! $f { () => { $v } })+)* + $(macro_rules! $m { () => { $(fn $f() -> i32 { $v })+ } })* + } +} + +foo!(m a 1 b 2, n c 3); +m!(); +n!(); + +macro_rules! no_shadow { + ($x:tt) => { macro_rules! bar { ($x:tt) => { 42 }; } }; +} +no_shadow!(z); + +macro_rules! make_plus { + ($n: ident $x:expr) => { macro_rules! $n { ($y:expr) => { $x + $y }; } }; +} +make_plus!(add3 3); + +fn main() { + assert_eq!(a!(), 1); + assert_eq!(b!(), 2); + assert_eq!(c!(), 3); + assert_eq!(a(), 1); + assert_eq!(b(), 2); + assert_eq!(c(), 3); + assert_eq!(bar!(z:tt), 42); + assert_eq!(add3!(9), 12); +} diff --git a/tests/ui/macros/missing-bang-in-decl.fixed b/tests/ui/macros/missing-bang-in-decl.fixed new file mode 100644 index 000000000..b1aa3298b --- /dev/null +++ b/tests/ui/macros/missing-bang-in-decl.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_macros)] + +macro_rules! foo { + //~^ ERROR expected `!` after `macro_rules` + () => {}; +} + +macro_rules! bar { + //~^ ERROR expected `!` after `macro_rules` + //~^^ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/tests/ui/macros/missing-bang-in-decl.rs b/tests/ui/macros/missing-bang-in-decl.rs new file mode 100644 index 000000000..8393f15fc --- /dev/null +++ b/tests/ui/macros/missing-bang-in-decl.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![allow(unused_macros)] + +macro_rules foo { + //~^ ERROR expected `!` after `macro_rules` + () => {}; +} + +macro_rules bar! { + //~^ ERROR expected `!` after `macro_rules` + //~^^ ERROR macro names aren't followed by a `!` + () => {}; +} + +fn main() {} diff --git a/tests/ui/macros/missing-bang-in-decl.stderr b/tests/ui/macros/missing-bang-in-decl.stderr new file mode 100644 index 000000000..dfabafb0a --- /dev/null +++ b/tests/ui/macros/missing-bang-in-decl.stderr @@ -0,0 +1,20 @@ +error: expected `!` after `macro_rules` + --> $DIR/missing-bang-in-decl.rs:5:1 + | +LL | macro_rules foo { + | ^^^^^^^^^^^ help: add a `!`: `macro_rules!` + +error: expected `!` after `macro_rules` + --> $DIR/missing-bang-in-decl.rs:10:1 + | +LL | macro_rules bar! { + | ^^^^^^^^^^^ help: add a `!`: `macro_rules!` + +error: macro names aren't followed by a `!` + --> $DIR/missing-bang-in-decl.rs:10:16 + | +LL | macro_rules bar! { + | ^ help: remove the `!` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/missing-comma.rs b/tests/ui/macros/missing-comma.rs new file mode 100644 index 000000000..92f8a7795 --- /dev/null +++ b/tests/ui/macros/missing-comma.rs @@ -0,0 +1,34 @@ +macro_rules! foo { + ($a:ident) => (); + ($a:ident, $b:ident) => (); + ($a:ident, $b:ident, $c:ident) => (); + ($a:ident, $b:ident, $c:ident, $d:ident) => (); + ($a:ident, $b:ident, $c:ident, $d:ident, $e:ident) => (); +} + +macro_rules! bar { + ($lvl:expr, $($arg:tt)+) => {} +} + +macro_rules! check { + ($ty:ty, $expected:expr) => {}; + ($ty_of:expr, $expected:expr) => {}; +} + +fn main() { + println!("{}" a); + //~^ ERROR expected `,`, found `a` + foo!(a b); + //~^ ERROR no rules expected the token `b` + foo!(a, b, c, d e); + //~^ ERROR no rules expected the token `e` + foo!(a, b, c d, e); + //~^ ERROR no rules expected the token `d` + foo!(a, b, c d e); + //~^ ERROR no rules expected the token `d` + bar!(Level::Error, ); + //~^ ERROR unexpected end of macro invocation + check!(::fmt, "fmt"); + check!(::fmt, "fmt",); + //~^ ERROR no rules expected the token `,` +} diff --git a/tests/ui/macros/missing-comma.stderr b/tests/ui/macros/missing-comma.stderr new file mode 100644 index 000000000..81877a29e --- /dev/null +++ b/tests/ui/macros/missing-comma.stderr @@ -0,0 +1,104 @@ +error: expected `,`, found `a` + --> $DIR/missing-comma.rs:19:19 + | +LL | println!("{}" a); + | ^ expected `,` + +error: no rules expected the token `b` + --> $DIR/missing-comma.rs:21:12 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a b); + | -^ no rules expected this token in macro call + | | + | help: missing comma here + | +note: while trying to match meta-variable `$a:ident` + --> $DIR/missing-comma.rs:2:6 + | +LL | ($a:ident) => (); + | ^^^^^^^^ + +error: no rules expected the token `e` + --> $DIR/missing-comma.rs:23:21 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a, b, c, d e); + | -^ no rules expected this token in macro call + | | + | help: missing comma here + | +note: while trying to match meta-variable `$d:ident` + --> $DIR/missing-comma.rs:5:36 + | +LL | ($a:ident, $b:ident, $c:ident, $d:ident) => (); + | ^^^^^^^^ + +error: no rules expected the token `d` + --> $DIR/missing-comma.rs:25:18 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a, b, c d, e); + | -^ no rules expected this token in macro call + | | + | help: missing comma here + | +note: while trying to match meta-variable `$c:ident` + --> $DIR/missing-comma.rs:4:26 + | +LL | ($a:ident, $b:ident, $c:ident) => (); + | ^^^^^^^^ + +error: no rules expected the token `d` + --> $DIR/missing-comma.rs:27:18 + | +LL | macro_rules! foo { + | ---------------- when calling this macro +... +LL | foo!(a, b, c d e); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$c:ident` + --> $DIR/missing-comma.rs:4:26 + | +LL | ($a:ident, $b:ident, $c:ident) => (); + | ^^^^^^^^ + +error: unexpected end of macro invocation + --> $DIR/missing-comma.rs:29:23 + | +LL | macro_rules! bar { + | ---------------- when calling this macro +... +LL | bar!(Level::Error, ); + | ^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$arg:tt` + --> $DIR/missing-comma.rs:10:19 + | +LL | ($lvl:expr, $($arg:tt)+) => {} + | ^^^^^^^ + +error: no rules expected the token `,` + --> $DIR/missing-comma.rs:32:38 + | +LL | macro_rules! check { + | ------------------ when calling this macro +... +LL | check!(::fmt, "fmt",); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$expected:expr` + --> $DIR/missing-comma.rs:14:14 + | +LL | ($ty:ty, $expected:expr) => {}; + | ^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/macros/must-use-in-macro-55516.rs b/tests/ui/macros/must-use-in-macro-55516.rs new file mode 100644 index 000000000..e7c346286 --- /dev/null +++ b/tests/ui/macros/must-use-in-macro-55516.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Wunused + +// make sure write!() can't hide its unused Result + +fn main() { + use std::fmt::Write; + let mut example = String::new(); + write!(&mut example, "{}", 42); //~WARN must be used +} diff --git a/tests/ui/macros/must-use-in-macro-55516.stderr b/tests/ui/macros/must-use-in-macro-55516.stderr new file mode 100644 index 000000000..8878b0eea --- /dev/null +++ b/tests/ui/macros/must-use-in-macro-55516.stderr @@ -0,0 +1,12 @@ +warning: unused `Result` that must be used + --> $DIR/must-use-in-macro-55516.rs:9:5 + | +LL | write!(&mut example, "{}", 42); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled + = note: `-W unused-must-use` implied by `-W unused` + = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/macros/no-std-macros.rs b/tests/ui/macros/no-std-macros.rs new file mode 100644 index 000000000..ada643c7a --- /dev/null +++ b/tests/ui/macros/no-std-macros.rs @@ -0,0 +1,13 @@ +// compile-flags: --crate-type=lib +// check-pass +// issue #55482 +#![no_std] + +macro_rules! foo { + ($e:expr) => { + $crate::core::assert!($e); + $crate::core::assert_eq!($e, true); + }; +} + +pub fn foo() { foo!(true); } diff --git a/tests/ui/macros/none-delim-lookahead.rs b/tests/ui/macros/none-delim-lookahead.rs new file mode 100644 index 000000000..bf4fddea1 --- /dev/null +++ b/tests/ui/macros/none-delim-lookahead.rs @@ -0,0 +1,15 @@ +// check-pass + +macro_rules! make_struct { + ($name:ident) => { + #[derive(Debug)] + struct Foo { + #[cfg(not(FALSE))] + field: fn($name: bool) + } + } +} + +make_struct!(param_name); + +fn main() {} diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs new file mode 100644 index 000000000..84fffe44d --- /dev/null +++ b/tests/ui/macros/nonterminal-matching.rs @@ -0,0 +1,26 @@ +// Check that we are refusing to match on complex nonterminals for which tokens are +// unavailable and we'd have to go through AST comparisons. + +#![feature(decl_macro)] + +macro simple_nonterminal($nt_ident: ident, $nt_lifetime: lifetime, $nt_tt: tt) { + macro n(a $nt_ident b $nt_lifetime c $nt_tt d) { + struct S; + } + + n!(a $nt_ident b $nt_lifetime c $nt_tt d); +} + +macro complex_nonterminal($nt_item: item) { + macro n(a $nt_item b) { + struct S; + } + + n!(a $nt_item b); //~ ERROR no rules expected the token `enum E {}` +} + +simple_nonterminal!(a, 'a, (x, y, z)); // OK + +complex_nonterminal!(enum E {}); + +fn main() {} diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr new file mode 100644 index 000000000..5bbd54390 --- /dev/null +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -0,0 +1,24 @@ +error: no rules expected the token `enum E {}` + --> $DIR/nonterminal-matching.rs:19:10 + | +LL | macro n(a $nt_item b) { + | --------------------- when calling this macro +... +LL | n!(a $nt_item b); + | ^^^^^^^^ no rules expected this token in macro call +... +LL | complex_nonterminal!(enum E {}); + | ------------------------------- in this macro invocation + | +note: while trying to match `enum E {}` + --> $DIR/nonterminal-matching.rs:15:15 + | +LL | macro n(a $nt_item b) { + | ^^^^^^^^ +... +LL | complex_nonterminal!(enum E {}); + | ------------------------------- in this macro invocation + = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/not-utf8.bin b/tests/ui/macros/not-utf8.bin new file mode 100644 index 000000000..4148e5b88 Binary files /dev/null and b/tests/ui/macros/not-utf8.bin differ diff --git a/tests/ui/macros/not-utf8.rs b/tests/ui/macros/not-utf8.rs new file mode 100644 index 000000000..1cb1fdcb8 --- /dev/null +++ b/tests/ui/macros/not-utf8.rs @@ -0,0 +1,5 @@ +// error-pattern: did not contain valid UTF-8 + +fn foo() { + include!("not-utf8.bin") +} diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr new file mode 100644 index 000000000..7e1f2dcad --- /dev/null +++ b/tests/ui/macros/not-utf8.stderr @@ -0,0 +1,10 @@ +error: couldn't read $DIR/not-utf8.bin: stream did not contain valid UTF-8 + --> $DIR/not-utf8.rs:4:5 + | +LL | include!("not-utf8.bin") + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/out-of-order-shadowing.rs b/tests/ui/macros/out-of-order-shadowing.rs new file mode 100644 index 000000000..a0d1a9737 --- /dev/null +++ b/tests/ui/macros/out-of-order-shadowing.rs @@ -0,0 +1,10 @@ +// aux-build:define-macro.rs + +macro_rules! bar { () => {} } +define_macro!(bar); +bar!(); //~ ERROR `bar` is ambiguous + +macro_rules! m { () => { #[macro_use] extern crate define_macro; } } +m!(); + +fn main() {} diff --git a/tests/ui/macros/out-of-order-shadowing.stderr b/tests/ui/macros/out-of-order-shadowing.stderr new file mode 100644 index 000000000..dedefac5c --- /dev/null +++ b/tests/ui/macros/out-of-order-shadowing.stderr @@ -0,0 +1,22 @@ +error[E0659]: `bar` is ambiguous + --> $DIR/out-of-order-shadowing.rs:5:1 + | +LL | bar!(); + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `bar` could refer to the macro defined here + --> $DIR/out-of-order-shadowing.rs:4:1 + | +LL | define_macro!(bar); + | ^^^^^^^^^^^^^^^^^^ +note: `bar` could also refer to the macro defined here + --> $DIR/out-of-order-shadowing.rs:3:1 + | +LL | macro_rules! bar { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `define_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/parse-complex-macro-invoc-op.rs b/tests/ui/macros/parse-complex-macro-invoc-op.rs new file mode 100644 index 000000000..8fef9b0ed --- /dev/null +++ b/tests/ui/macros/parse-complex-macro-invoc-op.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(stable_features)] + +// Test parsing binary operators after macro invocations. + +// pretty-expanded FIXME #23616 + +#![feature(macro_rules)] + +macro_rules! id { + ($e: expr) => { $e } +} + +fn foo() { + id!(1) + 1; + id![1] - 1; + id!(1) * 1; + id![1] / 1; + id!(1) % 1; + + id!(1) & 1; + id![1] | 1; + id!(1) ^ 1; + + let mut x = 1; + id![x] = 2; + id!(x) += 1; + + id!(1f64).clone(); + + id!([1, 2, 3])[1]; + id![drop](1); + + id!(true) && true; + id![true] || true; +} + +fn main() {} diff --git a/tests/ui/macros/paths-in-macro-invocations.rs b/tests/ui/macros/paths-in-macro-invocations.rs new file mode 100644 index 000000000..622818a92 --- /dev/null +++ b/tests/ui/macros/paths-in-macro-invocations.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(dead_code)] +// aux-build:two_macros-rpass.rs + +extern crate two_macros_rpass as two_macros; + +::two_macros::macro_one!(); +two_macros::macro_one!(); + +mod foo { pub use two_macros::macro_one as bar; } + +trait T { + foo::bar!(); + ::foo::bar!(); +} + +struct S { + x: foo::bar!(i32), + y: ::foo::bar!(i32), +} + +impl S { + foo::bar!(); + ::foo::bar!(); +} + +fn main() { + foo::bar!(); + ::foo::bar!(); + + let _ = foo::bar!(0); + let _ = ::foo::bar!(0); + + let foo::bar!(_) = 0; + let ::foo::bar!(_) = 0; +} diff --git a/tests/ui/macros/proc_macro.rs b/tests/ui/macros/proc_macro.rs new file mode 100644 index 000000000..66f9cdc55 --- /dev/null +++ b/tests/ui/macros/proc_macro.rs @@ -0,0 +1,37 @@ +// run-pass +// aux-build:proc_macro_def.rs +// ignore-cross-compile + +extern crate proc_macro_def; + +use proc_macro_def::{attr_tru, attr_identity, identity, ret_tru, tru}; + +#[attr_tru] +fn f1() -> bool { + return false; +} + +#[attr_identity] +fn f2() -> bool { + return identity!(true); +} + +fn f3() -> identity!(bool) { + ret_tru!(); +} + +fn f4(x: bool) -> bool { + match x { + identity!(true) => false, + identity!(false) => true, + } +} + +fn main() { + assert!(f1()); + assert!(f2()); + assert!(tru!()); + assert!(f3()); + assert!(identity!(5 == 5)); + assert!(f4(false)); +} diff --git a/tests/ui/macros/pub-item-inside-macro.rs b/tests/ui/macros/pub-item-inside-macro.rs new file mode 100644 index 000000000..d07681453 --- /dev/null +++ b/tests/ui/macros/pub-item-inside-macro.rs @@ -0,0 +1,18 @@ +// run-pass +// Issue #14660 + +// pretty-expanded FIXME #23616 + +mod bleh { + macro_rules! foo { + () => { + pub fn bar() { } + } + } + + foo!(); +} + +fn main() { + bleh::bar(); +} diff --git a/tests/ui/macros/pub-method-inside-macro.rs b/tests/ui/macros/pub-method-inside-macro.rs new file mode 100644 index 000000000..bc918c7a4 --- /dev/null +++ b/tests/ui/macros/pub-method-inside-macro.rs @@ -0,0 +1,22 @@ +// run-pass +// Issue #17436 + +// pretty-expanded FIXME #23616 + +mod bleh { + macro_rules! foo { + () => { + pub fn bar(&self) { } + } + } + + pub struct S; + + impl S { + foo!(); + } +} + +fn main() { + bleh::S.bar(); +} diff --git a/tests/ui/macros/recovery-allowed.rs b/tests/ui/macros/recovery-allowed.rs new file mode 100644 index 000000000..ebf65f1cc --- /dev/null +++ b/tests/ui/macros/recovery-allowed.rs @@ -0,0 +1,8 @@ +macro_rules! please_recover { + ($a:expr) => {}; +} + +please_recover! { not 1 } +//~^ ERROR unexpected `1` after identifier + +fn main() {} diff --git a/tests/ui/macros/recovery-allowed.stderr b/tests/ui/macros/recovery-allowed.stderr new file mode 100644 index 000000000..ec036e8b1 --- /dev/null +++ b/tests/ui/macros/recovery-allowed.stderr @@ -0,0 +1,10 @@ +error: unexpected `1` after identifier + --> $DIR/recovery-allowed.rs:5:23 + | +LL | please_recover! { not 1 } + | ----^ + | | + | help: use `!` to perform bitwise not + +error: aborting due to previous error + diff --git a/tests/ui/macros/recovery-forbidden.rs b/tests/ui/macros/recovery-forbidden.rs new file mode 100644 index 000000000..5dd261933 --- /dev/null +++ b/tests/ui/macros/recovery-forbidden.rs @@ -0,0 +1,13 @@ +// check-pass + +macro_rules! dont_recover_here { + ($e:expr) => { + compile_error!("Must not recover to single !1 expr"); + }; + + (not $a:literal) => {}; +} + +dont_recover_here! { not 1 } + +fn main() {} diff --git a/tests/ui/macros/restricted-shadowing-legacy.rs b/tests/ui/macros/restricted-shadowing-legacy.rs new file mode 100644 index 000000000..f5cac2dfb --- /dev/null +++ b/tests/ui/macros/restricted-shadowing-legacy.rs @@ -0,0 +1,289 @@ +// Legend: +// `N` - number of combination, from 0 to 4*4*4=64 +// `Outer < Invoc` means that expansion that produced macro definition `Outer` +// is a strict ancestor of expansion that produced macro definition `Inner`. +// `>`, `=` and `Unordered` mean "strict descendant", "same" and +// "not in ordering relation" for parent expansions. +// `+` - possible configuration +// `-` - configuration impossible due to properties of partial ordering +// `-?` - configuration impossible due to block/scope syntax +// `+?` - configuration possible only with legacy scoping + +// N | Outer ~ Invoc | Invoc ~ Inner | Outer ~ Inner | Possible | +// 1 | < | < | < | + | +// 2 | < | < | = | - | +// 3 | < | < | > | - | +// 4 | < | < | Unordered | - | +// 5 | < | = | < | + | +// 6 | < | = | = | - | +// 7 | < | = | > | - | +// 8 | < | = | Unordered | - | +// 9 | < | > | < | + | +// 10 | < | > | = | + | +// 11 | < | > | > | -? | +// 12 | < | > | Unordered | -? | +// 13 | < | Unordered | < | + | +// 14 | < | Unordered | = | - | +// 15 | < | Unordered | > | - | +// 16 | < | Unordered | Unordered | -? | +// 17 | = | < | < | + | +// 18 | = | < | = | - | +// 19 | = | < | > | - | +// 20 | = | < | Unordered | - | +// 21 | = | = | < | - | +// 22 | = | = | = | + | +// 23 | = | = | > | - | +// 24 | = | = | Unordered | - | +// 25 | = | > | < | - | +// 26 | = | > | = | - | +// 27 | = | > | > | -? | +// 28 | = | > | Unordered | - | +// 29 | = | Unordered | < | - | +// 30 | = | Unordered | = | - | +// 31 | = | Unordered | > | - | +// 32 | = | Unordered | Unordered | -? | +// 33 | > | < | < | +? | +// 34 | > | < | = | +? | +// 35 | > | < | > | +? | +// 36 | > | < | Unordered | + | +// 37 | > | = | < | - | +// 38 | > | = | = | - | +// 39 | > | = | > | + | +// 40 | > | = | Unordered | - | +// 41 | > | > | < | - | +// 42 | > | > | = | - | +// 43 | > | > | > | -? | +// 44 | > | > | Unordered | - | +// 45 | > | Unordered | < | - | +// 46 | > | Unordered | = | - | +// 47 | > | Unordered | > | -? | +// 48 | > | Unordered | Unordered | -? | +// 49 | Unordered | < | < | -? | +// 50 | Unordered | < | = | - | +// 51 | Unordered | < | > | - | +// 52 | Unordered | < | Unordered | + | +// 53 | Unordered | = | < | - | +// 54 | Unordered | = | = | - | +// 55 | Unordered | = | > | - | +// 56 | Unordered | = | Unordered | + | +// 57 | Unordered | > | < | - | +// 58 | Unordered | > | = | - | +// 59 | Unordered | > | > | + | +// 60 | Unordered | > | Unordered | + | +// 61 | Unordered | Unordered | < | +? | +// 62 | Unordered | Unordered | = | +? | +// 63 | Unordered | Unordered | > | +? | +// 64 | Unordered | Unordered | Unordered | + | + +#![feature(decl_macro, rustc_attrs)] + +struct Right; +// struct Wrong; // not defined + +macro_rules! include { () => { + macro_rules! gen_outer { () => { + macro_rules! m { () => { Wrong } } + }} + macro_rules! gen_inner { () => { + macro_rules! m { () => { Right } } + }} + macro_rules! gen_invoc { () => { + m!() + }} + + // ----------------------------------------------------------- + + fn check1() { + macro_rules! m { () => {} } + + macro_rules! gen_gen_inner_invoc { () => { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + }} + gen_gen_inner_invoc!(); + } + + fn check5() { + macro_rules! m { () => { Wrong } } + + macro_rules! gen_inner_invoc { () => { + macro_rules! m { () => { Right } } + m!(); // OK + }} + gen_inner_invoc!(); + } + + fn check9() { + macro_rules! m { () => { Wrong } } + + macro_rules! gen_inner_gen_invoc { () => { + macro_rules! m { () => { Right } } + gen_invoc!(); // OK + }} + gen_inner_gen_invoc!(); + } + + fn check10() { + macro_rules! m { () => { Wrong } } + + macro_rules! m { () => { Right } } + + gen_invoc!(); // OK + } + + fn check13() { + macro_rules! m { () => {} } + + gen_inner!(); + + macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + + fn check17() { + macro_rules! m { () => {} } + + gen_inner!(); + + m!(); //~ ERROR `m` is ambiguous + } + + fn check22() { + macro_rules! m { () => { Wrong } } + + macro_rules! m { () => { Right } } + + m!(); // OK + } + + fn check36() { + gen_outer!(); + + gen_inner!(); + + m!(); //~ ERROR `m` is ambiguous + } + + fn check39() { + gen_outer!(); + + macro_rules! m { () => { Right } } + + m!(); // OK + } + + fn check52() { + gen_outer!(); + + macro_rules! gen_gen_inner_invoc { () => { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + }} + gen_gen_inner_invoc!(); + } + + fn check56() { + gen_outer!(); + + macro_rules! gen_inner_invoc { () => { + macro_rules! m { () => { Right } } + m!(); // OK + }} + gen_inner_invoc!(); + } + + fn check59() { + gen_outer!(); + + macro_rules! m { () => { Right } } + + gen_invoc!(); // OK + } + + fn check60() { + gen_outer!(); + + macro_rules! gen_inner_gen_invoc { () => { + macro_rules! m { () => { Right } } + gen_invoc!(); // OK + }} + gen_inner_gen_invoc!(); + } + + fn check64() { + gen_outer!(); + + gen_inner!(); + + macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + + // ----------------------------------------------------------- + // These configurations are only possible with legacy macro scoping + + fn check33() { + macro_rules! gen_outer_gen_inner { () => { + macro_rules! m { () => {} } + gen_inner!(); + }} + gen_outer_gen_inner!(); + + m!(); //~ ERROR `m` is ambiguous + } + + fn check34() { + macro_rules! gen_outer_inner { () => { + macro_rules! m { () => { Wrong } } + macro_rules! m { () => { Right } } + }} + gen_outer_inner!(); + + m!(); // OK + } + + fn check35() { + macro_rules! gen_gen_outer_inner { () => { + gen_outer!(); + macro_rules! m { () => { Right } } + }} + gen_gen_outer_inner!(); + + m!(); // OK + } + + fn check61() { + macro_rules! gen_outer_gen_inner { () => { + macro_rules! m { () => {} } + gen_inner!(); + }} + gen_outer_gen_inner!(); + + macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + + fn check62() { + macro_rules! gen_outer_inner { () => { + macro_rules! m { () => { Wrong } } + macro_rules! m { () => { Right } } + }} + gen_outer_inner!(); + + gen_invoc!(); // OK + } + + fn check63() { + macro_rules! gen_gen_outer_inner { () => { + gen_outer!(); + macro_rules! m { () => { Right } } + }} + gen_gen_outer_inner!(); + + gen_invoc!(); // OK + } +}} + +include!(); + +fn main() {} diff --git a/tests/ui/macros/restricted-shadowing-legacy.stderr b/tests/ui/macros/restricted-shadowing-legacy.stderr new file mode 100644 index 000000000..b8865112e --- /dev/null +++ b/tests/ui/macros/restricted-shadowing-legacy.stderr @@ -0,0 +1,227 @@ +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:101:13 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:97:9 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:139:42 + | +LL | macro_rules! gen_invoc { () => { m!() } } + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:135:9 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:148:9 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:144:9 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:164:9 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:85:9 + | +LL | macro_rules! m { () => { Wrong } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:180:13 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:85:9 + | +LL | macro_rules! m { () => { Wrong } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:218:42 + | +LL | macro_rules! gen_invoc { () => { m!() } } + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:85:9 + | +LL | macro_rules! m { () => { Wrong } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:232:9 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:227:13 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-legacy.rs:262:42 + | +LL | macro_rules! gen_invoc { () => { m!() } } + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:88:9 + | +LL | macro_rules! m { () => { Right } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-legacy.rs:257:13 + | +LL | macro_rules! m { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/restricted-shadowing-modern.rs b/tests/ui/macros/restricted-shadowing-modern.rs new file mode 100644 index 000000000..1151a829e --- /dev/null +++ b/tests/ui/macros/restricted-shadowing-modern.rs @@ -0,0 +1,241 @@ +// Legend: +// `N` - number of combination, from 0 to 4*4*4=64 +// `Outer < Invoc` means that expansion that produced macro definition `Outer` +// is a strict ancestor of expansion that produced macro definition `Inner`. +// `>`, `=` and `Unordered` mean "strict descendant", "same" and +// "not in ordering relation" for parent expansions. +// `+` - possible configuration +// `-` - configuration impossible due to properties of partial ordering +// `-?` - configuration impossible due to block/scope syntax +// `+?` - configuration possible only with legacy scoping + +// N | Outer ~ Invoc | Invoc ~ Inner | Outer ~ Inner | Possible | +// 1 | < | < | < | + | +// 2 | < | < | = | - | +// 3 | < | < | > | - | +// 4 | < | < | Unordered | - | +// 5 | < | = | < | + | +// 6 | < | = | = | - | +// 7 | < | = | > | - | +// 8 | < | = | Unordered | - | +// 9 | < | > | < | + | +// 10 | < | > | = | + | +// 11 | < | > | > | -? | +// 12 | < | > | Unordered | -? | +// 13 | < | Unordered | < | + | +// 14 | < | Unordered | = | - | +// 15 | < | Unordered | > | - | +// 16 | < | Unordered | Unordered | -? | +// 17 | = | < | < | + | +// 18 | = | < | = | - | +// 19 | = | < | > | - | +// 20 | = | < | Unordered | - | +// 21 | = | = | < | - | +// 22 | = | = | = | + | +// 23 | = | = | > | - | +// 24 | = | = | Unordered | - | +// 25 | = | > | < | - | +// 26 | = | > | = | - | +// 27 | = | > | > | -? | +// 28 | = | > | Unordered | - | +// 29 | = | Unordered | < | - | +// 30 | = | Unordered | = | - | +// 31 | = | Unordered | > | - | +// 32 | = | Unordered | Unordered | -? | +// 33 | > | < | < | -? | +// 34 | > | < | = | -? | +// 35 | > | < | > | -? | +// 36 | > | < | Unordered | + | +// 37 | > | = | < | - | +// 38 | > | = | = | - | +// 39 | > | = | > | + | +// 40 | > | = | Unordered | - | +// 41 | > | > | < | - | +// 42 | > | > | = | - | +// 43 | > | > | > | -? | +// 44 | > | > | Unordered | - | +// 45 | > | Unordered | < | - | +// 46 | > | Unordered | = | - | +// 47 | > | Unordered | > | -? | +// 48 | > | Unordered | Unordered | -? | +// 49 | Unordered | < | < | -? | +// 50 | Unordered | < | = | - | +// 51 | Unordered | < | > | - | +// 52 | Unordered | < | Unordered | + | +// 53 | Unordered | = | < | - | +// 54 | Unordered | = | = | - | +// 55 | Unordered | = | > | - | +// 56 | Unordered | = | Unordered | + | +// 57 | Unordered | > | < | - | +// 58 | Unordered | > | = | - | +// 59 | Unordered | > | > | + | +// 60 | Unordered | > | Unordered | + | +// 61 | Unordered | Unordered | < | -? | +// 62 | Unordered | Unordered | = | -? | +// 63 | Unordered | Unordered | > | -? | +// 64 | Unordered | Unordered | Unordered | + | + +#![feature(decl_macro, rustc_attrs)] + +struct Right; +// struct Wrong; // not defined + +#[rustc_macro_transparency = "transparent"] +macro include() { + #[rustc_macro_transparency = "transparent"] + macro gen_outer() { + macro m() { Wrong } + } + #[rustc_macro_transparency = "transparent"] + macro gen_inner() { + macro m() { Right } + } + #[rustc_macro_transparency = "transparent"] + macro gen_invoc() { + m!() + } + + fn check1() { + macro m() {} + { + #[rustc_macro_transparency = "transparent"] + macro gen_gen_inner_invoc() { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + gen_gen_inner_invoc!(); + } + } + + fn check5() { + macro m() { Wrong } + { + #[rustc_macro_transparency = "transparent"] + macro gen_inner_invoc() { + macro m() { Right } + m!(); // OK + } + gen_inner_invoc!(); + } + } + + fn check9() { + macro m() { Wrong } + { + #[rustc_macro_transparency = "transparent"] + macro gen_inner_gen_invoc() { + macro m() { Right } + gen_invoc!(); // OK + } + gen_inner_gen_invoc!(); + } + } + + fn check10() { + macro m() { Wrong } + { + macro m() { Right } + gen_invoc!(); // OK + } + } + + fn check13() { + macro m() {} + { + gen_inner!(); + #[rustc_macro_transparency = "transparent"] + macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + } + + fn check17() { + macro m() {} + { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + } + + fn check22() { + macro m() { Wrong } + { + macro m() { Right } + m!(); // OK + } + } + + fn check36() { + gen_outer!(); + { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + } + + fn check39() { + gen_outer!(); + { + macro m() { Right } + m!(); // OK + } + } + + fn check52() { + gen_outer!(); + { + #[rustc_macro_transparency = "transparent"] + macro gen_gen_inner_invoc() { + gen_inner!(); + m!(); //~ ERROR `m` is ambiguous + } + gen_gen_inner_invoc!(); + } + } + + fn check56() { + gen_outer!(); + { + #[rustc_macro_transparency = "transparent"] + macro gen_inner_invoc() { + macro m() { Right } + m!(); // OK + } + gen_inner_invoc!(); + } + } + + fn check59() { + gen_outer!(); + { + macro m() { Right } + gen_invoc!(); // OK + } + } + + fn check60() { + gen_outer!(); + { + #[rustc_macro_transparency = "transparent"] + macro gen_inner_gen_invoc() { + macro m() { Right } + gen_invoc!(); // OK + } + gen_inner_gen_invoc!(); + } + } + + fn check64() { + gen_outer!(); + { + gen_inner!(); + #[rustc_macro_transparency = "transparent"] + macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous + gen_invoc!(); + } + } +} + +include!(); + +fn main() {} diff --git a/tests/ui/macros/restricted-shadowing-modern.stderr b/tests/ui/macros/restricted-shadowing-modern.stderr new file mode 100644 index 000000000..27665bfc3 --- /dev/null +++ b/tests/ui/macros/restricted-shadowing-modern.stderr @@ -0,0 +1,171 @@ +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:104:17 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:99:9 + | +LL | macro m() {} + | ^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:147:33 + | +LL | macro gen_invoc() { m!() } + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:143:9 + | +LL | macro m() {} + | ^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:156:13 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:153:9 + | +LL | macro m() {} + | ^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:172:13 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:87:9 + | +LL | macro m() { Wrong } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:190:17 + | +LL | m!(); + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:87:9 + | +LL | macro m() { Wrong } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `m` is ambiguous + --> $DIR/restricted-shadowing-modern.rs:233:33 + | +LL | macro gen_invoc() { m!() } + | ^ ambiguous name +... +LL | include!(); + | ---------- in this macro invocation + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:91:9 + | +LL | macro m() { Right } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation +note: `m` could also refer to the macro defined here + --> $DIR/restricted-shadowing-modern.rs:87:9 + | +LL | macro m() { Wrong } + | ^^^^^^^^^^^^^^^^^^^ +... +LL | include!(); + | ---------- in this macro invocation + = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs new file mode 100644 index 000000000..b8b6f0846 --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs @@ -0,0 +1,186 @@ +// edition:2021 +// ignore-tidy-linelength +// only-x86_64 +// run-pass +// needs-unwind Asserting on contents of error message + +#![allow(path_statements, unused_allocation)] +#![feature(box_syntax, core_intrinsics, generic_assert, generic_assert_internals)] + +macro_rules! test { + ( + let mut $elem_ident:ident = $elem_expr:expr; + [ $($assert:tt)* ] => $msg:literal + ) => { + { + #[allow(unused_assignments, unused_mut, unused_variables)] + let rslt = std::panic::catch_unwind(|| { + let mut $elem_ident = $elem_expr; + assert!($($assert)*); + }); + let err = rslt.unwrap_err(); + if let Some(elem) = err.downcast_ref::() { + assert_eq!(elem, &$msg); + } + else if let Some(elem) = err.downcast_ref::<&str>() { + assert_eq!(elem, &$msg); + } + else { + panic!("assert!( ... ) should return a string"); + } + } + } +} + +macro_rules! tests { + ( + let mut $elem_ident:ident = $elem_expr:expr; + + $( + [ $($elem_assert:tt)* ] => $elem_msg:literal + )+ + ) => { + $( + test!( + let mut $elem_ident = $elem_expr; + [ $($elem_assert)* ] => $elem_msg + ); + )+ + } +} + +const FOO: Foo = Foo { bar: 1 }; + +#[derive(Clone, Copy, Debug, PartialEq)] +struct Foo { + bar: i32 +} + +impl Foo { + fn add(&self, a: i32, b: i32) -> i32 { a + b } +} + +fn add(a: i32, b: i32) -> i32 { a + b } + +fn main() { + // ***** Allowed ***** + + tests!( + let mut elem = 1i32; + + // addr of + [ &elem == &3 ] => "Assertion failed: &elem == &3\nWith captures:\n elem = 1\n" + + // array + [ [elem][0] == 3 ] => "Assertion failed: [elem][0] == 3\nWith captures:\n elem = 1\n" + + // binary + [ elem + 1 == 3 ] => "Assertion failed: elem + 1 == 3\nWith captures:\n elem = 1\n" + + // call + [ add(elem, elem) == 3 ] => "Assertion failed: add(elem, elem) == 3\nWith captures:\n elem = 1\n" + + // cast + [ elem as i32 == 3 ] => "Assertion failed: elem as i32 == 3\nWith captures:\n elem = 1\n" + + // index + [ [1i32, 1][elem as usize] == 3 ] => "Assertion failed: [1i32, 1][elem as usize] == 3\nWith captures:\n elem = 1\n" + + // method call + [ FOO.add(elem, elem) == 3 ] => "Assertion failed: FOO.add(elem, elem) == 3\nWith captures:\n elem = 1\n" + + // paren + [ (elem) == 3 ] => "Assertion failed: (elem) == 3\nWith captures:\n elem = 1\n" + + // range + [ (0..elem) == (0..3) ] => "Assertion failed: (0..elem) == (0..3)\nWith captures:\n elem = 1\n" + + // repeat + [ [elem; 1] == [3; 1] ] => "Assertion failed: [elem; 1] == [3; 1]\nWith captures:\n elem = 1\n" + + // struct + [ Foo { bar: elem } == Foo { bar: 3 } ] => "Assertion failed: Foo { bar: elem } == Foo { bar: 3 }\nWith captures:\n elem = 1\n" + + // tuple + [ (elem, 1) == (3, 3) ] => "Assertion failed: (elem, 1) == (3, 3)\nWith captures:\n elem = 1\n" + + // unary + [ -elem == -3 ] => "Assertion failed: -elem == -3\nWith captures:\n elem = 1\n" + ); + + // ***** Disallowed ***** + + tests!( + let mut elem = 1i32; + + // assign + [ { let local = elem; local } == 3 ] => "Assertion failed: { let local = elem; local } == 3" + + // assign op + [ { elem += 1; elem } == 3 ] => "Assertion failed: { elem += 1; elem } == 3" + + // async + [ { let _ = async { elem }; elem } == 3 ] => "Assertion failed: { let _ = async { elem }; elem } == 3" + + // await + + // block + [ { elem } == 3 ] => "Assertion failed: { elem } == 3" + + // box + [ box elem == box 3 ] => "Assertion failed: box elem == box 3" + + // break + [ loop { break elem; } == 3 ] => "Assertion failed: loop { break elem; } == 3" + + // closure + [(|| elem)() == 3 ] => "Assertion failed: (|| elem)() == 3" + + // const block + + // continue + + // err + + // field + [ FOO.bar == 3 ] => "Assertion failed: FOO.bar == 3" + + // for loop + [ { for _ in 0..elem { elem; } elem } == 3 ] => "Assertion failed: { for _ in 0..elem { elem; } elem } == 3" + + // if + [ if true { elem } else { elem } == 3 ] => "Assertion failed: if true { elem } else { elem } == 3" + + // inline asm + + // let + [ if let true = true { elem } else { elem } == 3 ] => "Assertion failed: if let true = true { elem } else { elem } == 3" + + // lit + + // loop + [ loop { elem; break elem; } == 3 ] => "Assertion failed: loop { elem; break elem; } == 3" + + // mac call + + // match + [ match elem { _ => elem } == 3 ] => "Assertion failed: match elem { _ => elem, } == 3" + + // ret + [ (|| { return elem; })() == 3 ] => "Assertion failed: (|| { return elem; })() == 3" + + // try + [ (|| { Some(Some(elem)?) })() == Some(3) ] => "Assertion failed: (|| { Some(Some(elem)?) })() == Some(3)" + + // try block + + // underscore + + // while + [ { while false { elem; break; } elem } == 3 ] => "Assertion failed: { while false { elem; break; } elem } == 3" + + // yeet + + // yield + ); +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs new file mode 100644 index 000000000..d46f396ee --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs @@ -0,0 +1,44 @@ +// aux-build:common.rs +// ignore-tidy-linelength +// only-x86_64 +// run-pass +// needs-unwind Asserting on contents of error message + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +extern crate common; + +#[derive(Clone, Copy, PartialEq)] +struct CopyNoDebug(i32); + +#[derive(Debug, PartialEq)] +struct NoCopyDebug(i32); + +#[derive(PartialEq)] +struct NoCopyNoDebug(i32); + +fn main() { + // Has Copy but does not have Debug + common::test!( + let mut copy_no_debug = CopyNoDebug(1); + [ copy_no_debug == CopyNoDebug(3) ] => "Assertion failed: copy_no_debug == CopyNoDebug(3)\nWith captures:\n copy_no_debug = N/A\n" + ); + + // Does not have Copy but has Debug + common::test!( + let mut no_copy_debug = NoCopyDebug(1); + [ no_copy_debug == NoCopyDebug(3) ] => "Assertion failed: no_copy_debug == NoCopyDebug(3)\nWith captures:\n no_copy_debug = N/A\n" + ); + + // Does not have Copy and does not have Debug + common::test!( + let mut no_copy_no_debug = NoCopyNoDebug(1); + [ no_copy_no_debug == NoCopyNoDebug(3) ] => "Assertion failed: no_copy_no_debug == NoCopyNoDebug(3)\nWith captures:\n no_copy_no_debug = N/A\n" + ); + + // Unevaluated (Expression short-circuited) + common::test!( + let mut elem = true; + [ false && elem ] => "Assertion failed: false && elem\nWith captures:\n elem = N/A\n" + ); +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs new file mode 100644 index 000000000..6a1435f79 --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs @@ -0,0 +1,13 @@ +// compile-flags: --test +// run-pass + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +#[should_panic(expected = "Custom user message")] +#[test] +fn test() { + assert!(1 == 3, "Custom user message"); +} + +fn main() { +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs new file mode 100644 index 000000000..1f5a29ab5 --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs @@ -0,0 +1,15 @@ +// aux-build:common.rs +// only-x86_64 +// run-pass +// needs-unwind Asserting on contents of error message + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +extern crate common; + +fn main() { + common::test!( + let mut _nothing = (); + [ 1 == 3 ] => "Assertion failed: 1 == 3" + ); +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs new file mode 100644 index 000000000..903ed507c --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs @@ -0,0 +1,25 @@ +#[macro_export] +macro_rules! test { + ( + let mut $elem_ident:ident = $elem_expr:expr; + [ $($assert:tt)* ] => $msg:literal + ) => { + { + #[allow(unused_assignments, unused_mut, unused_variables)] + let rslt = std::panic::catch_unwind(|| { + let mut $elem_ident = $elem_expr; + assert!($($assert)*); + }); + let err = rslt.unwrap_err(); + if let Some(elem) = err.downcast_ref::() { + assert_eq!(elem, &$msg); + } + else if let Some(elem) = err.downcast_ref::<&str>() { + assert_eq!(elem, &$msg); + } + else { + panic!("assert!( ... ) should return a string"); + } + } + } +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs new file mode 100644 index 000000000..01860adaa --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs @@ -0,0 +1,26 @@ +// compile-flags: --test +// ignore-tidy-linelength +// run-pass + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +use std::fmt::{Debug, Formatter}; + +#[derive(Clone, Copy, PartialEq)] +struct CopyDebug(i32); + +impl Debug for CopyDebug { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + f.write_str("With great power comes great electricity bills") + } +} + +#[should_panic(expected = "Assertion failed: copy_debug == CopyDebug(3)\nWith captures:\n copy_debug = With great power comes great electricity bills\n")] +#[test] +fn test() { + let copy_debug = CopyDebug(1); + assert!(copy_debug == CopyDebug(3)); +} + +fn main() { +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs new file mode 100644 index 000000000..5ec84b08f --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs @@ -0,0 +1,32 @@ +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +fn arbitrary_consuming_method_for_demonstration_purposes() { + let elem = 1i32; + assert!(elem as usize); +} + +fn addr_of() { + let elem = 1i32; + assert!(&elem); +} + +fn binary() { + let elem = 1i32; + assert!(elem == 1); + assert!(elem >= 1); + assert!(elem > 0); + assert!(elem < 3); + assert!(elem <= 3); + assert!(elem != 3); +} + +fn unary() { + let elem = &1i32; + assert!(*elem); +} + +fn main() { +} diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout new file mode 100644 index 000000000..90f858f80 --- /dev/null +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout @@ -0,0 +1,147 @@ +#![feature(prelude_import)] +#![no_std] +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn arbitrary_consuming_method_for_demonstration_purposes() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*{ + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + __local_bind0 + } as usize)) { + + + + + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem as usize\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn addr_of() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!&*__local_bind0) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: &elem\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn binary() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 == 1)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 >= 1)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem >= 1\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 > 0)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem > 0\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 < 3)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem < 3\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 <= 3)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem <= 3\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!(*__local_bind0 != 3)) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem != 3\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn unary() { + let elem = &1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if ::core::intrinsics::unlikely(!**__local_bind0) { + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: *elem\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} +fn main() {} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs new file mode 100644 index 000000000..ab8d95a41 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs @@ -0,0 +1,271 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +fn main() { + macro_rules! one_nested_count_and_length { + ( $( [ $( $l:literal ),* ] ),* ) => { + [ + // outer-most repetition + $( + // inner-most repetition + $( + ${ignore(l)} ${index()}, ${length()}, + )* + ${count(l)}, ${index()}, ${length()}, + )* + ${count(l)}, + ] + }; + } + assert_eq!( + one_nested_count_and_length!(["foo"], ["bar", "baz"]), + [ + // # ["foo"] + + // ## inner-most repetition (first iteration) + // + // `index` is 0 because this is the first inner-most iteration. + // `length` is 1 because there is only one inner-most repetition, "foo". + 0, 1, + + // ## outer-most repetition (first iteration) + // + // `count` is 1 because of "foo", i,e, `$l` has only one repetition, + // `index` is 0 because this is the first outer-most iteration. + // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + 1, 0, 2, + + // # ["bar", "baz"] + + // ## inner-most repetition (first iteration) + // + // `index` is 0 because this is the first inner-most iteration + // `length` is 2 because there are repetitions, "bar" and "baz" + 0, 2, + + // ## inner-most repetition (second iteration) + // + // `index` is 1 because this is the second inner-most iteration + // `length` is 2 because there are repetitions, "bar" and "baz" + 1, 2, + + // ## outer-most repetition (second iteration) + // + // `count` is 2 because of "bar" and "baz", i,e, `$l` has two repetitions, + // `index` is 1 because this is the second outer-most iteration + // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + 2, 1, 2, + + // # last count + + // Because there are a total of 3 repetitions of `$l`, "foo", "bar" and "baz" + 3, + ] + ); + + // Based on the above explanation, the following macros should be straightforward + + // Grouped from the outer-most to the inner-most + macro_rules! three_nested_count { + ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { + &[ + $( $( $( + &[ + ${ignore(i)} ${count(i, 0)}, + ][..], + )* )* )* + + $( $( + &[ + ${ignore(i)} ${count(i, 0)}, + ${ignore(i)} ${count(i, 1)}, + ][..], + )* )* + + $( + &[ + ${ignore(i)} ${count(i, 0)}, + ${ignore(i)} ${count(i, 1)}, + ${ignore(i)} ${count(i, 2)}, + ][..], + )* + + &[ + ${count(i, 0)}, + ${count(i, 1)}, + ${count(i, 2)}, + ${count(i, 3)}, + ][..] + ][..] + } + } + assert_eq!( + three_nested_count!( + { + [ (a b c) (d e f) ] + [ (g h) (i j k l m) ] + [ (n) ] + } + { + [ (o) (p q) (r s) ] + [ (t u v w x y z) ] + } + ), + &[ + // a b c + &[3][..], + // d e f + &[3][..], + // g h + &[2][..], + // i j k l m + &[5][..], + // n + &[1][..], + // o + &[1][..], + // p q + &[2][..], + // r s + &[2][..], + // t u v w x y z + &[7][..], + + // (a b c) (d e f) + &[2, 6][..], + // (g h) (i j k l m) + &[2, 7][..], + // (n) + &[1, 1][..], + // (o) (p q) (r s) + &[3, 5][..], + // (t u v w x y z) + &[1, 7][..], + + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + &[3, 5, 14][..], + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + &[2, 4, 12][..], + + // { + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + // } + // { + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + // } + &[2, 5, 9, 26][..] + ][..] + ); + + // Grouped from the outer-most to the inner-most + macro_rules! three_nested_length { + ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { + &[ + $( $( $( $( + &[ + ${ignore(i)} ${length(3)}, + ${ignore(i)} ${length(2)}, + ${ignore(i)} ${length(1)}, + ${ignore(i)} ${length(0)}, + ][..], + )* )* )* )* + + $( $( $( + &[ + ${ignore(i)} ${length(2)}, + ${ignore(i)} ${length(1)}, + ${ignore(i)} ${length(0)}, + ][..], + )* )* )* + + $( $( + &[ + ${ignore(i)} ${length(1)}, + ${ignore(i)} ${length(0)}, + ][..], + )* )* + + $( + &[ + ${ignore(i)} ${length(0)}, + ][..], + )* + ][..] + } + } + assert_eq!( + three_nested_length!( + { + [ (a b c) (d e f) ] + [ (g h) (i j k l m) ] + [ (n) ] + } + { + [ (o) (p q) (r s) ] + [ (t u v w x y z) ] + } + ), + &[ + // a b c + &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], + // d e f + &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], + // g h + &[2, 3, 2, 2][..], &[2, 3, 2, 2][..], + // i j k l m + &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], + &[2, 3, 2, 5][..], + // n + &[2, 3, 1, 1][..], + // o + &[2, 2, 3, 1][..], + // p q + &[2, 2, 3, 2][..], &[2, 2, 3, 2][..], + // r s + &[2, 2, 3, 2][..], &[2, 2, 3, 2][..], + // t u v w x y z + &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], + + // (a b c) (d e f) + &[2, 3, 2][..], &[2, 3, 2][..], + // (g h) (i j k l m) + &[2, 3, 2][..], &[2, 3, 2][..], + // (n) + &[2, 3, 1][..], + // (o) (p q) (r s) + &[2, 2, 3][..], &[2, 2, 3][..], &[2, 2, 3][..], + // (t u v w x y z) + &[2, 2, 1][..], + + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + &[2, 3][..], &[2, 3][..], &[2, 3,][..], + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + &[2, 2][..], &[2, 2][..], + + // { + // [ (a b c) (d e f) ] + // [ (g h) (i j k l m) ] + // [ (n) ] + // } + // { + // [ (o) (p q) (r s) ] + // [ (t u v w x y z) ] + // } + &[2][..], &[2][..] + ][..] + ); + + // It is possible to say, to some degree, that count is an "amalgamation" of length (see + // each length line result and compare them with the count results) +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs b/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs new file mode 100644 index 000000000..ed94c27cf --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs @@ -0,0 +1,28 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +macro_rules! nested { + ( $a:ident ) => { + macro_rules! $a { + ( $$( $b:ident ),* ) => { + $$( + macro_rules! $b { + ( $$$$( $c:ident ),* ) => { + $$$$( + fn $c() -> &'static str { stringify!($c) } + ),* + }; + } + )* + }; + } + }; +} + +fn main() { + nested!(a); + a!(b); + b!(c); + assert_eq!(c(), "c"); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs new file mode 100644 index 000000000..d05cd1b31 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs @@ -0,0 +1,148 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +/// Count the number of idents in a macro repetition. +macro_rules! count_idents { + ( $( $i:ident ),* ) => { + ${count(i)} + }; +} + +/// Count the number of idents in a 2-dimensional macro repetition. +macro_rules! count_idents_2 { + ( $( [ $( $i:ident ),* ] ),* ) => { + ${count(i)} + }; +} + +/// Mostly counts the number of OUTER-MOST repetitions +macro_rules! count_depth_limits { + ( $( { $( [ $( $outer:ident : ( $( $inner:ident )* ) )* ] )* } )* ) => { + ( + ( + ${count(inner)}, + ${count(inner, 0)}, + ${count(inner, 1)}, + ${count(inner, 2)}, + ${count(inner, 3)}, + ), + ( + ${count(outer)}, + ${count(outer, 0)}, + ${count(outer, 1)}, + ${count(outer, 2)}, + ), + ) + }; +} + +/// Produce (index, length) pairs for literals in a macro repetition. +/// The literal is not included in the output, so this macro uses the +/// `ignore` meta-variable expression to create a non-expanding +/// repetition binding. +macro_rules! enumerate_literals { + ( $( ($l:stmt) ),* ) => { + [$( ${ignore(l)} (${index()}, ${length()}) ),*] + }; +} + +/// Produce index and length tuples for literals in a 2-dimensional +/// macro repetition. +macro_rules! enumerate_literals_2 { + ( $( [ $( ($l:literal) ),* ] ),* ) => { + [ + $( + $( + ( + ${index(1)}, + ${length(1)}, + ${index(0)}, + ${length(0)}, + $l + ), + )* + )* + ] + }; +} + +/// Generate macros that count idents and then add a constant number +/// to the count. +/// +/// This macro uses dollar escaping to make it unambiguous as to which +/// macro the repetition belongs to. +macro_rules! make_count_adders { + ( $( $i:ident, $b:literal );* ) => { + $( + macro_rules! $i { + ( $$( $$j:ident ),* ) => { + $b + $${count(j)} + }; + } + )* + }; +} + +make_count_adders! { plus_one, 1; plus_five, 5 } + +/// Generate a macro that allows selection of a particular literal +/// from a sequence of inputs by their identifier. +/// +/// This macro uses dollar escaping to make it unambiguous as to which +/// macro the repetition belongs to, and to allow expansion of an +/// identifier the name of which is not known in the definition +/// of `make_picker`. +macro_rules! make_picker { + ( $m:ident => $( $i:ident ),* ; $p:ident ) => { + macro_rules! $m { + ( $( $$ $i:literal ),* ) => { + $$ $p + }; + } + }; +} + +make_picker!(first => a, b; a); + +make_picker!(second => a, b; b); + +fn main() { + assert_eq!(count_idents!(a, b, c), 3); + assert_eq!(count_idents_2!([a, b, c], [d, e], [f]), 6); + assert_eq!( + count_depth_limits! { + { + [ A: (a b c) D: (d e f) ] + [ G: (g h) I: (i j k l m) ] + [ N: (n) ] + } + { + [ O: (o) P: (p q) R: (r s) ] + [ T: (t u v w x y z) ] + } + }, + ((26, 2, 5, 9, 26), (9, 2, 5, 9)) + ); + assert_eq!(enumerate_literals![("foo"), ("bar")], [(0, 2), (1, 2)]); + assert_eq!( + enumerate_literals_2![ + [("foo"), ("bar"), ("baz")], + [("qux"), ("quux"), ("quuz"), ("xyzzy")] + ], + [ + (0, 2, 0, 3, "foo"), + (0, 2, 1, 3, "bar"), + (0, 2, 2, 3, "baz"), + + (1, 2, 0, 4, "qux"), + (1, 2, 1, 4, "quux"), + (1, 2, 2, 4, "quuz"), + (1, 2, 3, 4, "xyzzy"), + ] + ); + assert_eq!(plus_one!(a, b, c), 4); + assert_eq!(plus_five!(a, b), 7); + assert_eq!(first!(1, 2), 1); + assert_eq!(second!(1, 2), 2); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs new file mode 100644 index 000000000..b954967c4 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs @@ -0,0 +1,102 @@ +// run-pass + +#![feature(macro_metavar_expr)] + +#[derive(Debug)] +struct Example<'a> { + _indexes: &'a [(u32, u32)], + _counts: &'a [u32], + _nested: Vec>, +} + +macro_rules! example { + ( $( [ $( ( $( $x:ident )* ) )* ] )* ) => { + Example { + _indexes: &[], + _counts: &[${count(x, 0)}, ${count(x, 1)}, ${count(x, 2)}], + _nested: vec![ + $( + Example { + _indexes: &[(${index()}, ${length()})], + _counts: &[${count(x, 0)}, ${count(x, 1)}], + _nested: vec![ + $( + Example { + _indexes: &[(${index(1)}, ${length(1)}), (${index()}, ${length()})], + _counts: &[${count(x)}], + _nested: vec![ + $( + Example { + _indexes: &[ + (${index(2)}, ${length(2)}), + (${index(1)}, ${length(1)}), + (${index()}, ${length()}) + ], + _counts: &[], + _nested: vec![], + ${ignore(x)} + } + ),* + ] + } + ),* + ] + } + ),* + ] + } + }; +} + +static EXPECTED: &str = concat!( + "Example { _indexes: [], _counts: [2, 4, 13], _nested: [", + concat!( + "Example { _indexes: [(0, 2)], _counts: [3, 10], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (0, 3)], _counts: [4], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (0, 3), (0, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (0, 3), (1, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (0, 3), (2, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (0, 3), (3, 4)], _counts: [], _nested: [] }", + ), + "] }, ", + "Example { _indexes: [(0, 2), (1, 3)], _counts: [4], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (1, 3), (0, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (1, 3), (1, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (1, 3), (2, 4)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (1, 3), (3, 4)], _counts: [], _nested: [] }", + ), + "] }, ", + "Example { _indexes: [(0, 2), (2, 3)], _counts: [2], _nested: [", + concat!( + "Example { _indexes: [(0, 2), (2, 3), (0, 2)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(0, 2), (2, 3), (1, 2)], _counts: [], _nested: [] }", + ), + "] }", + ), + "] }, ", + "Example { _indexes: [(1, 2)], _counts: [1, 3], _nested: [", + concat!( + "Example { _indexes: [(1, 2), (0, 1)], _counts: [3], _nested: [", + concat!( + "Example { _indexes: [(1, 2), (0, 1), (0, 3)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(1, 2), (0, 1), (1, 3)], _counts: [], _nested: [] }, ", + "Example { _indexes: [(1, 2), (0, 1), (2, 3)], _counts: [], _nested: [] }", + ), + "] }", + ), + "] }", + ), + "] }", +); + +fn main() { + let e = example! { + [ ( A B C D ) ( E F G H ) ( I J ) ] + [ ( K L M ) ] + }; + let debug = format!("{:?}", e); + assert_eq!(debug, EXPECTED); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs new file mode 100644 index 000000000..6a0d68bd6 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs @@ -0,0 +1,43 @@ +#![feature(macro_metavar_expr)] + +macro_rules! a { + ( $( { $( [ $( ( $( $foo:ident )* ) )* ] )* } )* ) => { + ( + ${count(foo, 0)}, + ${count(foo, 10)}, + //~^ ERROR depth parameter on meta-variable expression `count` must be less than 4 + ) + }; +} + +macro_rules! b { + ( $( { $( [ $( $foo:ident )* ] )* } )* ) => { + ( + $( $( $( + ${ignore(foo)} + ${index(0)}, + ${index(10)}, + //~^ ERROR depth parameter on meta-variable expression `index` must be less than 3 + )* )* )* + ) + }; +} + +macro_rules! c { + ( $( { $( $foo:ident )* } )* ) => { + ( + $( $( + ${ignore(foo)} + ${length(0)} + ${length(10)} + //~^ ERROR depth parameter on meta-variable expression `length` must be less than 2 + )* )* + ) + }; +} + +fn main() { + a!( { [ (a) ] [ (b c) ] } ); + b!( { [ a b ] } ); + c!({ a }); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr new file mode 100644 index 000000000..236122b64 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr @@ -0,0 +1,20 @@ +error: depth parameter on meta-variable expression `count` must be less than 4 + --> $DIR/out-of-bounds-arguments.rs:7:14 + | +LL | ${count(foo, 10)}, + | ^^^^^^^^^^^^^^^^ + +error: depth parameter on meta-variable expression `index` must be less than 3 + --> $DIR/out-of-bounds-arguments.rs:19:18 + | +LL | ${index(10)}, + | ^^^^^^^^^^^ + +error: depth parameter on meta-variable expression `length` must be less than 2 + --> $DIR/out-of-bounds-arguments.rs:32:18 + | +LL | ${length(10)} + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs new file mode 100644 index 000000000..b4fef11f1 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs @@ -0,0 +1,44 @@ +macro_rules! count { + ( $( $e:stmt ),* ) => { + ${ count(e) } + //~^ ERROR meta-variable expressions are unstable + }; +} + +macro_rules! dollar_dollar { + () => { + macro_rules! bar { + ( $$( $$any:tt )* ) => { $$( $$any )* }; + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + } + }; +} + +macro_rules! index { + ( $( $e:stmt ),* ) => { + $( ${ignore(e)} ${index()} )* + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + }; +} + +macro_rules! ignore { + ( $( $i:stmt ),* ) => {{ + 0 $( + 1 ${ignore(i)} )* + //~^ ERROR meta-variable expressions are unstable + }}; +} + +macro_rules! length { + ( $( $e:stmt ),* ) => { + $( ${ignore(e)} ${length()} )* + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + }; +} + +fn main() { +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr new file mode 100644 index 000000000..ecf598b10 --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr @@ -0,0 +1,93 @@ +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:3:10 + | +LL | ${ count(e) } + | ^^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:16 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:20 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:39 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:43 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:13 + | +LL | $( ${ignore(e)} ${index()} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:26 + | +LL | $( ${ignore(e)} ${index()} )* + | ^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:30:19 + | +LL | 0 $( + 1 ${ignore(i)} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:37:13 + | +LL | $( ${ignore(e)} ${length()} )* + | ^^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:37:26 + | +LL | $( ${ignore(e)} ${length()} )* + | ^^^^^^^^^^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs new file mode 100644 index 000000000..fdf16442d --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs @@ -0,0 +1,165 @@ +#![feature(macro_metavar_expr)] + +// `curly` = Right hand side curly brackets +// `no_rhs_dollar` = No dollar sign at the right hand side meta variable "function" +// `round` = Left hand side round brackets + +macro_rules! curly__no_rhs_dollar__round { + ( $( $i:ident ),* ) => { ${ count(i) } }; +} + +macro_rules! curly__no_rhs_dollar__no_round { + ( $i:ident ) => { ${ count(i) } }; + //~^ ERROR `count` can not be placed inside the inner-most repetition +} + +macro_rules! curly__rhs_dollar__round { + ( $( $i:ident ),* ) => { ${ count($i) } }; + //~^ ERROR expected identifier, found `$` + //~| ERROR expected expression, found `$` +} + +macro_rules! curly__rhs_dollar__no_round { + ( $i:ident ) => { ${ count($i) } }; + //~^ ERROR expected identifier, found `$` + //~| ERROR expected expression, found `$` +} + +macro_rules! no_curly__no_rhs_dollar__round { + ( $( $i:ident ),* ) => { count(i) }; + //~^ ERROR cannot find function `count` in this scope + //~| ERROR cannot find value `i` in this scope +} + +macro_rules! no_curly__no_rhs_dollar__no_round { + ( $i:ident ) => { count(i) }; + //~^ ERROR cannot find function `count` in this scope + //~| ERROR cannot find value `i` in this scope +} + +macro_rules! no_curly__rhs_dollar__round { + ( $( $i:ident ),* ) => { count($i) }; + //~^ ERROR variable 'i' is still repeating at this depth +} + +macro_rules! no_curly__rhs_dollar__no_round { + ( $i:ident ) => { count($i) }; + //~^ ERROR cannot find function `count` in this scope +} + +// Other scenarios + +macro_rules! dollar_dollar_in_the_lhs { + ( $$ $a:ident ) => { + //~^ ERROR unexpected token: $ + }; +} + +macro_rules! extra_garbage_after_metavar { + ( $( $i:ident ),* ) => { + ${count() a b c} + //~^ ERROR unexpected token: a + //~| ERROR expected expression, found `$` + ${count(i a b c)} + //~^ ERROR unexpected token: a + ${count(i, 1 a b c)} + //~^ ERROR unexpected token: a + ${count(i) a b c} + //~^ ERROR unexpected token: a + + ${ignore(i) a b c} + //~^ ERROR unexpected token: a + ${ignore(i a b c)} + //~^ ERROR unexpected token: a + + ${index() a b c} + //~^ ERROR unexpected token: a + ${index(1 a b c)} + //~^ ERROR unexpected token: a + + ${index() a b c} + //~^ ERROR unexpected token: a + ${index(1 a b c)} + //~^ ERROR unexpected token: a + }; +} + +const IDX: usize = 1; +macro_rules! metavar_depth_is_not_literal { + ( $( $i:ident ),* ) => { ${ index(IDX) } }; + //~^ ERROR meta-variable expression depth must be a literal + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_in_the_lhs { + ( ${ length() } ) => { + //~^ ERROR unexpected token: { + //~| ERROR expected one of: `*`, `+`, or `?` + }; +} + +macro_rules! metavar_token_without_ident { + ( $( $i:ident ),* ) => { ${ ignore() } }; + //~^ ERROR expected identifier + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_with_literal_suffix { + ( $( $i:ident ),* ) => { ${ index(1u32) } }; + //~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions + //~| ERROR expected expression, found `$` +} + +macro_rules! metavar_without_parens { + ( $( $i:ident ),* ) => { ${ count{i} } }; + //~^ ERROR meta-variable expression parameter must be wrapped in parentheses + //~| ERROR expected expression, found `$` +} + +macro_rules! open_brackets_without_tokens { + ( $( $i:ident ),* ) => { ${ {} } }; + //~^ ERROR expected expression, found `$` + //~| ERROR expected identifier +} + +macro_rules! unknown_count_ident { + ( $( $i:ident )* ) => { + ${count(foo)} + //~^ ERROR variable `foo` is not recognized in meta-variable expression + }; +} + +macro_rules! unknown_ignore_ident { + ( $( $i:ident )* ) => { + ${ignore(bar)} + //~^ ERROR variable `bar` is not recognized in meta-variable expression + }; +} + +macro_rules! unknown_metavar { + ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + //~^ ERROR unrecognized meta-variable expression + //~| ERROR expected expression +} + +fn main() { + curly__no_rhs_dollar__round!(a, b, c); + curly__no_rhs_dollar__no_round!(a); + curly__rhs_dollar__round!(a, b, c); + curly__rhs_dollar__no_round!(a); + no_curly__no_rhs_dollar__round!(a, b, c); + no_curly__no_rhs_dollar__no_round!(a); + no_curly__rhs_dollar__round!(a, b, c); + no_curly__rhs_dollar__no_round!(a); + //~^ ERROR cannot find value `a` in this scope + + extra_garbage_after_metavar!(a); + metavar_depth_is_not_literal!(a); + metavar_token_without_ident!(a); + metavar_with_literal_suffix!(a); + metavar_without_parens!(a); + open_brackets_without_tokens!(a); + unknown_count_ident!(a); + unknown_ignore_ident!(a); + unknown_metavar!(a); +} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr new file mode 100644 index 000000000..a6cff95fd --- /dev/null +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr @@ -0,0 +1,385 @@ +error: expected identifier, found `$` + --> $DIR/syntax-errors.rs:17:33 + | +LL | ( $( $i:ident ),* ) => { ${ count($i) } }; + | ^^^^^ - help: try removing `$` + +error: expected identifier, found `$` + --> $DIR/syntax-errors.rs:23:26 + | +LL | ( $i:ident ) => { ${ count($i) } }; + | ^^^^^ - help: try removing `$` + +error: unexpected token: $ + --> $DIR/syntax-errors.rs:53:8 + | +LL | ( $$ $a:ident ) => { + | ^ + +note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions + --> $DIR/syntax-errors.rs:53:8 + | +LL | ( $$ $a:ident ) => { + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:60:19 + | +LL | ${count() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:60:19 + | +LL | ${count() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:63:19 + | +LL | ${count(i a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:63:19 + | +LL | ${count(i a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:65:22 + | +LL | ${count(i, 1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:65:22 + | +LL | ${count(i, 1 a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:67:20 + | +LL | ${count(i) a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:67:20 + | +LL | ${count(i) a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:70:21 + | +LL | ${ignore(i) a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:70:21 + | +LL | ${ignore(i) a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:72:20 + | +LL | ${ignore(i a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:72:20 + | +LL | ${ignore(i a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:75:19 + | +LL | ${index() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:75:19 + | +LL | ${index() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:77:19 + | +LL | ${index(1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:77:19 + | +LL | ${index(1 a b c)} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:80:19 + | +LL | ${index() a b c} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:80:19 + | +LL | ${index() a b c} + | ^ + +error: unexpected token: a + --> $DIR/syntax-errors.rs:82:19 + | +LL | ${index(1 a b c)} + | ^ + | +note: meta-variable expression must not have trailing tokens + --> $DIR/syntax-errors.rs:82:19 + | +LL | ${index(1 a b c)} + | ^ + +error: meta-variable expression depth must be a literal + --> $DIR/syntax-errors.rs:89:33 + | +LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; + | ^^^^^ + +error: unexpected token: { + --> $DIR/syntax-errors.rs:95:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions + --> $DIR/syntax-errors.rs:95:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +error: expected one of: `*`, `+`, or `?` + --> $DIR/syntax-errors.rs:95:8 + | +LL | ( ${ length() } ) => { + | ^^^^^^^^^^^^ + +error: expected identifier + --> $DIR/syntax-errors.rs:102:33 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^^^^^^ + +error: only unsuffixes integer literals are supported in meta-variable expressions + --> $DIR/syntax-errors.rs:108:33 + | +LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; + | ^^^^^ + +error: meta-variable expression parameter must be wrapped in parentheses + --> $DIR/syntax-errors.rs:114:33 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^^^^^ + +error: expected identifier + --> $DIR/syntax-errors.rs:120:31 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^^^^^^ + +error: unrecognized meta-variable expression + --> $DIR/syntax-errors.rs:140:33 + | +LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + | ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and length + +error: `count` can not be placed inside the inner-most repetition + --> $DIR/syntax-errors.rs:12:24 + | +LL | ( $i:ident ) => { ${ count(i) } }; + | ^^^^^^^^^^^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:17:30 + | +LL | ( $( $i:ident ),* ) => { ${ count($i) } }; + | ^ expected expression +... +LL | curly__rhs_dollar__round!(a, b, c); + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `curly__rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:23:23 + | +LL | ( $i:ident ) => { ${ count($i) } }; + | ^ expected expression +... +LL | curly__rhs_dollar__no_round!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: variable 'i' is still repeating at this depth + --> $DIR/syntax-errors.rs:41:36 + | +LL | ( $( $i:ident ),* ) => { count($i) }; + | ^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:60:9 + | +LL | ${count() a b c} + | ^ expected expression +... +LL | extra_garbage_after_metavar!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:89:30 + | +LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; + | ^ expected expression +... +LL | metavar_depth_is_not_literal!(a); + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:102:30 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^ expected expression +... +LL | metavar_token_without_ident!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:108:30 + | +LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; + | ^ expected expression +... +LL | metavar_with_literal_suffix!(a); + | ------------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:114:30 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^ expected expression +... +LL | metavar_without_parens!(a); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:120:30 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^ expected expression +... +LL | open_brackets_without_tokens!(a); + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: variable `foo` is not recognized in meta-variable expression + --> $DIR/syntax-errors.rs:127:17 + | +LL | ${count(foo)} + | ^^^ + +error: variable `bar` is not recognized in meta-variable expression + --> $DIR/syntax-errors.rs:134:18 + | +LL | ${ignore(bar)} + | ^^^ + +error: expected expression, found `$` + --> $DIR/syntax-errors.rs:140:30 + | +LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; + | ^ expected expression +... +LL | unknown_metavar!(a); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/syntax-errors.rs:29:36 + | +LL | ( $( $i:ident ),* ) => { count(i) }; + | ^ not found in this scope +... +LL | no_curly__no_rhs_dollar__round!(a, b, c); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/syntax-errors.rs:35:29 + | +LL | ( $i:ident ) => { count(i) }; + | ^ not found in this scope +... +LL | no_curly__no_rhs_dollar__no_round!(a); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `a` in this scope + --> $DIR/syntax-errors.rs:153:37 + | +LL | no_curly__rhs_dollar__no_round!(a); + | ^ not found in this scope + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:29:30 + | +LL | ( $( $i:ident ),* ) => { count(i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__no_rhs_dollar__round!(a, b, c); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:35:23 + | +LL | ( $i:ident ) => { count(i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__no_rhs_dollar__no_round!(a); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find function `count` in this scope + --> $DIR/syntax-errors.rs:46:23 + | +LL | ( $i:ident ) => { count($i) }; + | ^^^^^ not found in this scope +... +LL | no_curly__rhs_dollar__no_round!(a); + | ---------------------------------- in this macro invocation + | + = note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 40 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/same-sequence-span.rs b/tests/ui/macros/same-sequence-span.rs new file mode 100644 index 000000000..e0bb4d985 --- /dev/null +++ b/tests/ui/macros/same-sequence-span.rs @@ -0,0 +1,22 @@ +// aux-build:proc_macro_sequence.rs + +// Regression test for issue #62831: Check that multiple sequences with the same span in the +// left-hand side of a macro definition behave as if they had unique spans, and in particular that +// they don't crash the compiler. + +#![allow(unused_macros)] + +extern crate proc_macro_sequence; + +// When ignoring spans, this macro has the same macro definition as `generated_foo` in +// `proc_macro_sequence.rs`. +macro_rules! manual_foo { + (1 $x:expr $($y:tt,)* //~ERROR `$x:expr` may be followed by `$y:tt` + $(= $z:tt)* //~ERROR `$x:expr` may be followed by `=` + ) => {}; +} + +proc_macro_sequence::make_foo!(); //~ERROR `$x:expr` may be followed by `$y:tt` + //~^ERROR `$x:expr` may be followed by `=` + +fn main() {} diff --git a/tests/ui/macros/same-sequence-span.stderr b/tests/ui/macros/same-sequence-span.stderr new file mode 100644 index 000000000..bdd191e8e --- /dev/null +++ b/tests/ui/macros/same-sequence-span.stderr @@ -0,0 +1,43 @@ +error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:14:18 + | +LL | (1 $x:expr $($y:tt,)* + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:15:18 + | +LL | $(= $z:tt)* + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:19:1 + | +LL | proc_macro_sequence::make_foo!(); + | ^------------------------------- + | | + | _in this macro invocation + | | +LL | | +LL | | +LL | | fn main() {} + | |_________________________________^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + = note: this error originates in the macro `proc_macro_sequence::make_foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:19:1 + | +LL | proc_macro_sequence::make_foo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + = note: this error originates in the macro `proc_macro_sequence::make_foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/semi-after-macro-ty.rs b/tests/ui/macros/semi-after-macro-ty.rs new file mode 100644 index 000000000..f83ace8fa --- /dev/null +++ b/tests/ui/macros/semi-after-macro-ty.rs @@ -0,0 +1,8 @@ +// run-pass +macro_rules! foo { + ($t:ty; $p:path;) => {} +} + +fn main() { + foo!(i32; i32;); +} diff --git a/tests/ui/macros/span-covering-argument-1.rs b/tests/ui/macros/span-covering-argument-1.rs new file mode 100644 index 000000000..9b9506c80 --- /dev/null +++ b/tests/ui/macros/span-covering-argument-1.rs @@ -0,0 +1,13 @@ +macro_rules! bad { + ($s:ident whatever) => { + { + let $s = 0; + *&mut $s = 0; + //~^ ERROR cannot borrow `foo` as mutable, as it is not declared as mutable [E0596] + } + } +} + +fn main() { + bad!(foo whatever); +} diff --git a/tests/ui/macros/span-covering-argument-1.stderr b/tests/ui/macros/span-covering-argument-1.stderr new file mode 100644 index 000000000..e57347b36 --- /dev/null +++ b/tests/ui/macros/span-covering-argument-1.stderr @@ -0,0 +1,18 @@ +error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable + --> $DIR/span-covering-argument-1.rs:5:14 + | +LL | *&mut $s = 0; + | ^^^^^^^ cannot borrow as mutable +... +LL | bad!(foo whatever); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `bad` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider changing this to be mutable + | +LL | let mut $s = 0; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/macros/stmt_expr_attr_macro_parse.rs b/tests/ui/macros/stmt_expr_attr_macro_parse.rs new file mode 100644 index 000000000..570191d2c --- /dev/null +++ b/tests/ui/macros/stmt_expr_attr_macro_parse.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_macro_rules)] + +macro_rules! m { + ($e:expr) => { + "expr includes attr" + }; + (#[$attr:meta] $e:expr) => { + "expr excludes attr" + } +} + +macro_rules! n { + (#[$attr:meta] $e:expr) => { + "expr excludes attr" + }; + ($e:expr) => { + "expr includes attr" + } +} + +fn main() { + assert_eq!(m!(#[attr] 1), "expr includes attr"); + assert_eq!(n!(#[attr] 1), "expr excludes attr"); +} diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs new file mode 100644 index 000000000..5cd217df6 --- /dev/null +++ b/tests/ui/macros/stringify.rs @@ -0,0 +1,889 @@ +// run-pass +// edition:2021 +// compile-flags: --test + +#![feature(async_closure)] +#![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(const_trait_impl)] +#![feature(decl_macro)] +#![feature(generators)] +#![feature(more_qualified_paths)] +#![feature(raw_ref_op)] +#![feature(trait_alias)] +#![feature(try_blocks)] +#![feature(type_ascription)] +#![deny(unused_macros)] + +macro_rules! stringify_block { + ($block:block) => { + stringify!($block) + }; +} + +macro_rules! stringify_expr { + ($expr:expr) => { + stringify!($expr) + }; +} + +macro_rules! stringify_item { + ($item:item) => { + stringify!($item) + }; +} + +macro_rules! stringify_meta { + ($meta:meta) => { + stringify!($meta) + }; +} + +macro_rules! stringify_pat { + ($pat:pat) => { + stringify!($pat) + }; +} + +macro_rules! stringify_path { + ($path:path) => { + stringify!($path) + }; +} + +macro_rules! stringify_stmt { + ($stmt:stmt) => { + stringify!($stmt) + }; +} + +macro_rules! stringify_ty { + ($ty:ty) => { + stringify!($ty) + }; +} + +macro_rules! stringify_vis { + ($vis:vis) => { + stringify!($vis) + }; +} + +#[test] +fn test_block() { + assert_eq!(stringify_block!({}), "{}"); + assert_eq!(stringify_block!({ true }), "{ true }"); + assert_eq!(stringify_block!({ return }), "{ return }"); + assert_eq!( + stringify_block!({ + return; + }), + "{ return; }", + ); + assert_eq!( + stringify_block!({ + let _; + true + }), + "{ let _; true }", + ); +} + +#[test] +fn test_expr() { + // ExprKind::Box + assert_eq!(stringify_expr!(box expr), "box expr"); + + // ExprKind::Array + assert_eq!(stringify_expr!([]), "[]"); + assert_eq!(stringify_expr!([true]), "[true]"); + assert_eq!(stringify_expr!([true,]), "[true]"); + assert_eq!(stringify_expr!([true, true]), "[true, true]"); + + // ExprKind::Call + assert_eq!(stringify_expr!(f()), "f()"); + assert_eq!(stringify_expr!(f::()), "f::()"); + assert_eq!(stringify_expr!(f::<1>()), "f::<1>()"); + assert_eq!(stringify_expr!(f::<'a, u8, 1>()), "f::<'a, u8, 1>()"); + assert_eq!(stringify_expr!(f(true)), "f(true)"); + assert_eq!(stringify_expr!(f(true,)), "f(true)"); + assert_eq!(stringify_expr!(()()), "()()"); + + // ExprKind::MethodCall + assert_eq!(stringify_expr!(x.f()), "x.f()"); + assert_eq!(stringify_expr!(x.f::()), "x.f::()"); + + // ExprKind::Tup + assert_eq!(stringify_expr!(()), "()"); + assert_eq!(stringify_expr!((true,)), "(true,)"); + assert_eq!(stringify_expr!((true, false)), "(true, false)"); + assert_eq!(stringify_expr!((true, false,)), "(true, false)"); + + // ExprKind::Binary + assert_eq!(stringify_expr!(true || false), "true || false"); + assert_eq!(stringify_expr!(true || false && false), "true || false && false"); + + // ExprKind::Unary + assert_eq!(stringify_expr!(*expr), "*expr"); + assert_eq!(stringify_expr!(!expr), "!expr"); + assert_eq!(stringify_expr!(-expr), "-expr"); + + // ExprKind::Lit + assert_eq!(stringify_expr!('x'), "'x'"); + assert_eq!(stringify_expr!(1_000_i8), "1_000_i8"); + assert_eq!(stringify_expr!(1.00000000000000001), "1.00000000000000001"); + + // ExprKind::Cast + assert_eq!(stringify_expr!(expr as T), "expr as T"); + assert_eq!(stringify_expr!(expr as T), "expr as T"); + + // ExprKind::Type + assert_eq!(stringify_expr!(expr: T), "expr: T"); + assert_eq!(stringify_expr!(expr: T), "expr: T"); + + // ExprKind::If + assert_eq!(stringify_expr!(if true {}), "if true {}"); + assert_eq!( + stringify_expr!(if true { + } else { + }), + "if true {} else {}", + ); + assert_eq!( + stringify_expr!(if let true = true { + } else { + }), + "if let true = true {} else {}", + ); + assert_eq!( + stringify_expr!(if true { + } else if false { + }), + "if true {} else if false {}", + ); + assert_eq!( + stringify_expr!(if true { + } else if false { + } else { + }), + "if true {} else if false {} else {}", + ); + assert_eq!( + stringify_expr!(if true { + return; + } else if false { + 0 + } else { + 0 + }), + "if true { return; } else if false { 0 } else { 0 }", + ); + + // ExprKind::While + assert_eq!(stringify_expr!(while true {}), "while true {}"); + assert_eq!(stringify_expr!('a: while true {}), "'a: while true {}"); + assert_eq!(stringify_expr!(while let true = true {}), "while let true = true {}"); + + // ExprKind::ForLoop + assert_eq!(stringify_expr!(for _ in x {}), "for _ in x {}"); + assert_eq!(stringify_expr!('a: for _ in x {}), "'a: for _ in x {}"); + + // ExprKind::Loop + assert_eq!(stringify_expr!(loop {}), "loop {}"); + assert_eq!(stringify_expr!('a: loop {}), "'a: loop {}"); + + // ExprKind::Match + assert_eq!(stringify_expr!(match self {}), "match self {}"); + assert_eq!( + stringify_expr!(match self { + Ok => 1, + }), + "match self { Ok => 1, }", + ); + assert_eq!( + stringify_expr!(match self { + Ok => 1, + Err => 0, + }), + "match self { Ok => 1, Err => 0, }", + ); + + // ExprKind::Closure + assert_eq!(stringify_expr!(|| {}), "|| {}"); + assert_eq!(stringify_expr!(|x| {}), "|x| {}"); + assert_eq!(stringify_expr!(|x: u8| {}), "|x: u8| {}"); + assert_eq!(stringify_expr!(|| ()), "|| ()"); + assert_eq!(stringify_expr!(move || self), "move || self"); + assert_eq!(stringify_expr!(async || self), "async || self"); + assert_eq!(stringify_expr!(async move || self), "async move || self"); + assert_eq!(stringify_expr!(static || self), "static || self"); + assert_eq!(stringify_expr!(static move || self), "static move || self"); + #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5149 + assert_eq!( + stringify_expr!(static async || self), + "static async || self", + ); + #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5149 + assert_eq!( + stringify_expr!(static async move || self), + "static async move || self", + ); + assert_eq!(stringify_expr!(|| -> u8 { self }), "|| -> u8 { self }"); + assert_eq!(stringify_expr!(1 + || {}), "1 + (|| {})"); // ?? + + // ExprKind::Block + assert_eq!(stringify_expr!({}), "{}"); + assert_eq!(stringify_expr!(unsafe {}), "unsafe {}"); + assert_eq!(stringify_expr!('a: {}), "'a: {}"); + assert_eq!( + stringify_expr!( + #[attr] + {} + ), + "#[attr] {}", + ); + assert_eq!( + stringify_expr!( + { + #![attr] + } + ), + "{\n\ + \x20 #![attr]\n\ + }", + ); + + // ExprKind::Async + assert_eq!(stringify_expr!(async {}), "async {}"); + assert_eq!(stringify_expr!(async move {}), "async move {}"); + + // ExprKind::Await + assert_eq!(stringify_expr!(expr.await), "expr.await"); + + // ExprKind::TryBlock + assert_eq!(stringify_expr!(try {}), "try {}"); + + // ExprKind::Assign + assert_eq!(stringify_expr!(expr = true), "expr = true"); + + // ExprKind::AssignOp + assert_eq!(stringify_expr!(expr += true), "expr += true"); + + // ExprKind::Field + assert_eq!(stringify_expr!(expr.field), "expr.field"); + assert_eq!(stringify_expr!(expr.0), "expr.0"); + + // ExprKind::Index + assert_eq!(stringify_expr!(expr[true]), "expr[true]"); + + // ExprKind::Range + assert_eq!(stringify_expr!(..), ".."); + assert_eq!(stringify_expr!(..hi), "..hi"); + assert_eq!(stringify_expr!(lo..), "lo.."); + assert_eq!(stringify_expr!(lo..hi), "lo..hi"); + assert_eq!(stringify_expr!(..=hi), "..=hi"); + assert_eq!(stringify_expr!(lo..=hi), "lo..=hi"); + assert_eq!(stringify_expr!(-2..=-1), "-2..=-1"); + + // ExprKind::Path + assert_eq!(stringify_expr!(thing), "thing"); + assert_eq!(stringify_expr!(m::thing), "m::thing"); + assert_eq!(stringify_expr!(self::thing), "self::thing"); + assert_eq!(stringify_expr!(crate::thing), "crate::thing"); + assert_eq!(stringify_expr!(Self::thing), "Self::thing"); + assert_eq!(stringify_expr!(::thing), "::thing"); + assert_eq!(stringify_expr!(Self::<'static>), "Self::<'static>"); + + // ExprKind::AddrOf + assert_eq!(stringify_expr!(&expr), "&expr"); + assert_eq!(stringify_expr!(&mut expr), "&mut expr"); + assert_eq!(stringify_expr!(&raw const expr), "&raw const expr"); + assert_eq!(stringify_expr!(&raw mut expr), "&raw mut expr"); + + // ExprKind::Break + assert_eq!(stringify_expr!(break), "break"); + assert_eq!(stringify_expr!(break 'a), "break 'a"); + assert_eq!(stringify_expr!(break true), "break true"); + assert_eq!(stringify_expr!(break 'a true), "break 'a true"); + + // ExprKind::Continue + assert_eq!(stringify_expr!(continue), "continue"); + assert_eq!(stringify_expr!(continue 'a), "continue 'a"); + + // ExprKind::Ret + assert_eq!(stringify_expr!(return), "return"); + assert_eq!(stringify_expr!(return true), "return true"); + + // ExprKind::MacCall + assert_eq!(stringify_expr!(mac!(...)), "mac!(...)"); + assert_eq!(stringify_expr!(mac![...]), "mac![...]"); + assert_eq!(stringify_expr!(mac! { ... }), "mac! { ... }"); + + // ExprKind::Struct + assert_eq!(stringify_expr!(Struct {}), "Struct {}"); + #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151 + assert_eq!(stringify_expr!(::Type {}), "::Type {}"); + assert_eq!(stringify_expr!(Struct { .. }), "Struct { .. }"); + assert_eq!(stringify_expr!(Struct { ..base }), "Struct { ..base }"); + assert_eq!(stringify_expr!(Struct { x }), "Struct { x }"); + assert_eq!(stringify_expr!(Struct { x, .. }), "Struct { x, .. }"); + assert_eq!(stringify_expr!(Struct { x, ..base }), "Struct { x, ..base }"); + assert_eq!(stringify_expr!(Struct { x: true }), "Struct { x: true }"); + assert_eq!(stringify_expr!(Struct { x: true, .. }), "Struct { x: true, .. }"); + assert_eq!(stringify_expr!(Struct { x: true, ..base }), "Struct { x: true, ..base }"); + + // ExprKind::Repeat + assert_eq!(stringify_expr!([(); 0]), "[(); 0]"); + + // ExprKind::Paren + assert_eq!(stringify_expr!((expr)), "(expr)"); + + // ExprKind::Try + assert_eq!(stringify_expr!(expr?), "expr?"); + + // ExprKind::Yield + assert_eq!(stringify_expr!(yield), "yield"); + assert_eq!(stringify_expr!(yield true), "yield true"); +} + +#[test] +fn test_item() { + // ItemKind::ExternCrate + assert_eq!( + stringify_item!( + extern crate std; + ), + "extern crate std;", + ); + assert_eq!( + stringify_item!( + pub extern crate self as std; + ), + "pub extern crate self as std;", + ); + + // ItemKind::Use + assert_eq!( + stringify_item!( + pub use crate::{a, b::c}; + ), + "pub use crate::{a, b::c};", + ); + + // ItemKind::Static + assert_eq!( + stringify_item!( + pub static S: () = {}; + ), + "pub static S: () = {};", + ); + assert_eq!( + stringify_item!( + static mut S: () = {}; + ), + "static mut S: () = {};", + ); + assert_eq!( + stringify_item!( + static S: (); + ), + "static S: ();", + ); + assert_eq!( + stringify_item!( + static mut S: (); + ), + "static mut S: ();", + ); + + // ItemKind::Const + assert_eq!( + stringify_item!( + pub const S: () = {}; + ), + "pub const S: () = {};", + ); + assert_eq!( + stringify_item!( + const S: (); + ), + "const S: ();", + ); + + // ItemKind::Fn + assert_eq!( + stringify_item!( + pub default const async unsafe extern "C" fn f() {} + ), + "pub default const async unsafe extern \"C\" fn f() {}", + ); + + // ItemKind::Mod + assert_eq!( + stringify_item!( + pub mod m; + ), + "pub mod m;", + ); + assert_eq!( + stringify_item!( + mod m {} + ), + "mod m {}", + ); + assert_eq!( + stringify_item!( + unsafe mod m; + ), + "unsafe mod m;", + ); + assert_eq!( + stringify_item!( + unsafe mod m {} + ), + "unsafe mod m {}", + ); + + // ItemKind::ForeignMod + assert_eq!( + stringify_item!( + extern "C" {} + ), + "extern \"C\" {}", + ); + #[rustfmt::skip] + assert_eq!( + stringify_item!( + pub extern "C" {} + ), + "extern \"C\" {}", + ); + assert_eq!( + stringify_item!( + unsafe extern "C++" {} + ), + "unsafe extern \"C++\" {}", + ); + + // ItemKind::TyAlias + #[rustfmt::skip] + assert_eq!( + stringify_item!( + pub default type Type<'a>: Bound + where + Self: 'a, + = T; + ), + "pub default type Type<'a>: Bound where Self: 'a = T;", + ); + + // ItemKind::Enum + assert_eq!( + stringify_item!( + pub enum Void {} + ), + "pub enum Void {}", + ); + assert_eq!( + stringify_item!( + enum Empty { + Unit, + Tuple(), + Struct {}, + } + ), + "enum Empty { Unit, Tuple(), Struct {}, }", + ); + assert_eq!( + stringify_item!( + enum Enum + where + T: 'a, + { + Unit, + Tuple(T), + Struct { t: T }, + } + ), + "enum Enum where T: 'a {\n\ + \x20 Unit,\n\ + \x20 Tuple(T),\n\ + \x20 Struct {\n\ + \x20 t: T,\n\ + \x20 },\n\ + }", + ); + + // ItemKind::Struct + assert_eq!( + stringify_item!( + pub struct Unit; + ), + "pub struct Unit;", + ); + assert_eq!( + stringify_item!( + struct Tuple(); + ), + "struct Tuple();", + ); + assert_eq!( + stringify_item!( + struct Tuple(T); + ), + "struct Tuple(T);", + ); + assert_eq!( + stringify_item!( + struct Struct {} + ), + "struct Struct {}", + ); + assert_eq!( + stringify_item!( + struct Struct + where + T: 'a, + { + t: T, + } + ), + "struct Struct where T: 'a {\n\ + \x20 t: T,\n\ + }", + ); + + // ItemKind::Union + assert_eq!( + stringify_item!( + pub union Union {} + ), + "pub union Union {}", + ); + assert_eq!( + stringify_item!( + union Union where T: 'a { + t: T, + } + ), + "union Union where T: 'a {\n\ + \x20 t: T,\n\ + }", + ); + + // ItemKind::Trait + assert_eq!( + stringify_item!( + pub unsafe auto trait Send {} + ), + "pub unsafe auto trait Send {}", + ); + assert_eq!( + stringify_item!( + trait Trait<'a>: Sized + where + Self: 'a, + { + } + ), + "trait Trait<'a>: Sized where Self: 'a {}", + ); + + // ItemKind::TraitAlias + assert_eq!( + stringify_item!( + pub trait Trait = Sized where T: 'a; + ), + "pub trait Trait = Sized where T: 'a;", + ); + + // ItemKind::Impl + assert_eq!( + stringify_item!( + pub impl Struct {} + ), + "pub impl Struct {}", + ); + assert_eq!( + stringify_item!( + impl Struct {} + ), + "impl Struct {}", + ); + assert_eq!( + stringify_item!( + pub impl Trait for Struct {} + ), + "pub impl Trait for Struct {}", + ); + assert_eq!( + stringify_item!( + impl const Trait for T {} + ), + "impl const Trait for T {}", + ); + assert_eq!( + stringify_item!( + impl ~const Struct {} + ), + "impl Struct {}", // FIXME + ); + + // ItemKind::MacCall + assert_eq!(stringify_item!(mac!(...);), "mac!(...);"); + assert_eq!(stringify_item!(mac![...];), "mac![...];"); + assert_eq!(stringify_item!(mac! { ... }), "mac! { ... }"); + + // ItemKind::MacroDef + assert_eq!( + stringify_item!( + macro_rules! stringify { + () => {}; + } + ), + "macro_rules! stringify { () => {} ; }", // FIXME + ); + assert_eq!( + stringify_item!( + pub macro stringify() {} + ), + "pub macro stringify { () => {} }", + ); +} + +#[test] +fn test_meta() { + assert_eq!(stringify_meta!(k), "k"); + assert_eq!(stringify_meta!(k = "v"), "k = \"v\""); + assert_eq!(stringify_meta!(list(k1, k2 = "v")), "list(k1, k2 = \"v\")"); + assert_eq!(stringify_meta!(serde::k), "serde::k"); +} + +#[test] +fn test_pat() { + // PatKind::Wild + assert_eq!(stringify_pat!(_), "_"); + + // PatKind::Ident + assert_eq!(stringify_pat!(_x), "_x"); + assert_eq!(stringify_pat!(ref _x), "ref _x"); + assert_eq!(stringify_pat!(mut _x), "mut _x"); + assert_eq!(stringify_pat!(ref mut _x), "ref mut _x"); + assert_eq!(stringify_pat!(ref mut _x @ _), "ref mut _x @ _"); + + // PatKind::Struct + assert_eq!(stringify_pat!(Struct {}), "Struct {}"); + assert_eq!(stringify_pat!(Struct:: {}), "Struct:: {}"); + assert_eq!(stringify_pat!(Struct::<'static> {}), "Struct::<'static> {}"); + assert_eq!(stringify_pat!(Struct { x }), "Struct { x }"); + assert_eq!(stringify_pat!(Struct { x: _x }), "Struct { x: _x }"); + assert_eq!(stringify_pat!(Struct { .. }), "Struct { .. }"); + assert_eq!(stringify_pat!(Struct { x, .. }), "Struct { x, .. }"); + assert_eq!(stringify_pat!(Struct { x: _x, .. }), "Struct { x: _x, .. }"); + #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5151 + assert_eq!( + stringify_pat!(::Type {}), + "::Type {}", + ); + + // PatKind::TupleStruct + assert_eq!(stringify_pat!(Tuple()), "Tuple()"); + assert_eq!(stringify_pat!(Tuple::()), "Tuple::()"); + assert_eq!(stringify_pat!(Tuple::<'static>()), "Tuple::<'static>()"); + assert_eq!(stringify_pat!(Tuple(x)), "Tuple(x)"); + assert_eq!(stringify_pat!(Tuple(..)), "Tuple(..)"); + assert_eq!(stringify_pat!(Tuple(x, ..)), "Tuple(x, ..)"); + assert_eq!(stringify_pat!(::Type()), "::Type()"); + + // PatKind::Or + assert_eq!(stringify_pat!(true | false), "true | false"); + assert_eq!(stringify_pat!(| true), "true"); + assert_eq!(stringify_pat!(|true| false), "true | false"); + + // PatKind::Path + assert_eq!(stringify_pat!(crate::Path), "crate::Path"); + assert_eq!(stringify_pat!(Path::), "Path::"); + assert_eq!(stringify_pat!(Path::<'static>), "Path::<'static>"); + assert_eq!(stringify_pat!(::Type), "::Type"); + + // PatKind::Tuple + assert_eq!(stringify_pat!(()), "()"); + assert_eq!(stringify_pat!((true,)), "(true,)"); + assert_eq!(stringify_pat!((true, false)), "(true, false)"); + + // PatKind::Box + assert_eq!(stringify_pat!(box pat), "box pat"); + + // PatKind::Ref + assert_eq!(stringify_pat!(&pat), "&pat"); + assert_eq!(stringify_pat!(&mut pat), "&mut pat"); + + // PatKind::Lit + assert_eq!(stringify_pat!(1_000_i8), "1_000_i8"); + + // PatKind::Range + assert_eq!(stringify_pat!(..1), "..1"); + assert_eq!(stringify_pat!(0..), "0.."); + assert_eq!(stringify_pat!(0..1), "0..1"); + assert_eq!(stringify_pat!(0..=1), "0..=1"); + assert_eq!(stringify_pat!(-2..=-1), "-2..=-1"); + + // PatKind::Slice + assert_eq!(stringify_pat!([]), "[]"); + assert_eq!(stringify_pat!([true]), "[true]"); + assert_eq!(stringify_pat!([true,]), "[true]"); + assert_eq!(stringify_pat!([true, false]), "[true, false]"); + + // PatKind::Rest + assert_eq!(stringify_pat!(..), ".."); + + // PatKind::Paren + assert_eq!(stringify_pat!((pat)), "(pat)"); + + // PatKind::MacCall + assert_eq!(stringify_pat!(mac!(...)), "mac!(...)"); + assert_eq!(stringify_pat!(mac![...]), "mac![...]"); + assert_eq!(stringify_pat!(mac! { ... }), "mac! { ... }"); +} + +#[test] +fn test_path() { + assert_eq!(stringify_path!(thing), "thing"); + assert_eq!(stringify_path!(m::thing), "m::thing"); + assert_eq!(stringify_path!(self::thing), "self::thing"); + assert_eq!(stringify_path!(crate::thing), "crate::thing"); + assert_eq!(stringify_path!(Self::thing), "Self::thing"); + assert_eq!(stringify_path!(Self<'static>), "Self<'static>"); + assert_eq!(stringify_path!(Self::<'static>), "Self<'static>"); + assert_eq!(stringify_path!(Self()), "Self()"); + assert_eq!(stringify_path!(Self() -> ()), "Self() -> ()"); +} + +#[test] +fn test_stmt() { + // StmtKind::Local + assert_eq!(stringify_stmt!(let _), "let _;"); + assert_eq!(stringify_stmt!(let x = true), "let x = true;"); + assert_eq!(stringify_stmt!(let x: bool = true), "let x: bool = true;"); + + // StmtKind::Item + assert_eq!( + stringify_stmt!( + struct S; + ), + "struct S;", + ); + + // StmtKind::Expr + assert_eq!(stringify_stmt!(loop {}), "loop {}"); + + // StmtKind::Semi + assert_eq!(stringify_stmt!(1 + 1), "1 + 1;"); + + // StmtKind::Empty + assert_eq!(stringify_stmt!(;), ";"); + + // StmtKind::MacCall + assert_eq!(stringify_stmt!(mac!(...)), "mac!(...)"); + assert_eq!(stringify_stmt!(mac![...]), "mac![...]"); + assert_eq!(stringify_stmt!(mac! { ... }), "mac! { ... }"); +} + +#[test] +fn test_ty() { + // TyKind::Slice + assert_eq!(stringify_ty!([T]), "[T]"); + + // TyKind::Array + assert_eq!(stringify_ty!([T; 0]), "[T; 0]"); + + // TyKind::Ptr + assert_eq!(stringify_ty!(*const T), "*const T"); + assert_eq!(stringify_ty!(*mut T), "*mut T"); + + // TyKind::Ref + assert_eq!(stringify_ty!(&T), "&T"); + assert_eq!(stringify_ty!(&mut T), "&mut T"); + assert_eq!(stringify_ty!(&'a T), "&'a T"); + assert_eq!(stringify_ty!(&'a mut T), "&'a mut T"); + + // TyKind::BareFn + assert_eq!(stringify_ty!(fn()), "fn()"); + assert_eq!(stringify_ty!(fn() -> ()), "fn() -> ()"); + assert_eq!(stringify_ty!(fn(u8)), "fn(u8)"); + assert_eq!(stringify_ty!(fn(x: u8)), "fn(x: u8)"); + #[rustfmt::skip] + assert_eq!(stringify_ty!(for<> fn()), "fn()"); + assert_eq!(stringify_ty!(for<'a> fn()), "for<'a> fn()"); + + // TyKind::Never + assert_eq!(stringify_ty!(!), "!"); + + // TyKind::Tup + assert_eq!(stringify_ty!(()), "()"); + assert_eq!(stringify_ty!((T,)), "(T,)"); + assert_eq!(stringify_ty!((T, U)), "(T, U)"); + + // TyKind::Path + assert_eq!(stringify_ty!(T), "T"); + assert_eq!(stringify_ty!(Ref<'a>), "Ref<'a>"); + assert_eq!(stringify_ty!(PhantomData), "PhantomData"); + assert_eq!(stringify_ty!(PhantomData::), "PhantomData"); + assert_eq!(stringify_ty!(Fn() -> !), "Fn() -> !"); + assert_eq!(stringify_ty!(Fn(u8) -> !), "Fn(u8) -> !"); + assert_eq!(stringify_ty!(::Type), "::Type"); + + // TyKind::TraitObject + assert_eq!(stringify_ty!(dyn Send), "dyn Send"); + assert_eq!(stringify_ty!(dyn Send + 'a), "dyn Send + 'a"); + assert_eq!(stringify_ty!(dyn 'a + Send), "dyn 'a + Send"); + assert_eq!(stringify_ty!(dyn ?Sized), "dyn ?Sized"); + assert_eq!(stringify_ty!(dyn ~const Clone), "dyn Clone"); // FIXME + assert_eq!(stringify_ty!(dyn for<'a> Send), "dyn for<'a> Send"); + + // TyKind::ImplTrait + assert_eq!(stringify_ty!(impl Send), "impl Send"); + assert_eq!(stringify_ty!(impl Send + 'a), "impl Send + 'a"); + assert_eq!(stringify_ty!(impl 'a + Send), "impl 'a + Send"); + assert_eq!(stringify_ty!(impl ?Sized), "impl ?Sized"); + assert_eq!(stringify_ty!(impl ~const Clone), "impl Clone"); // FIXME + assert_eq!(stringify_ty!(impl for<'a> Send), "impl for<'a> Send"); + + // TyKind::Paren + assert_eq!(stringify_ty!((T)), "(T)"); + + // TyKind::Infer + assert_eq!(stringify_ty!(_), "_"); + + // TyKind::MacCall + assert_eq!(stringify_ty!(mac!(...)), "mac!(...)"); + assert_eq!(stringify_ty!(mac![...]), "mac![...]"); + assert_eq!(stringify_ty!(mac! { ... }), "mac! { ... }"); +} + +#[test] +fn test_vis() { + // VisibilityKind::Public + assert_eq!(stringify_vis!(pub), "pub "); + + // VisibilityKind::Restricted + assert_eq!(stringify_vis!(pub(crate)), "pub(crate) "); + assert_eq!(stringify_vis!(pub(self)), "pub(self) "); + assert_eq!(stringify_vis!(pub(super)), "pub(super) "); + assert_eq!(stringify_vis!(pub(in crate)), "pub(in crate) "); + assert_eq!(stringify_vis!(pub(in self)), "pub(in self) "); + assert_eq!(stringify_vis!(pub(in super)), "pub(in super) "); + assert_eq!(stringify_vis!(pub(in path::to)), "pub(in path::to) "); + assert_eq!(stringify_vis!(pub(in ::path::to)), "pub(in ::path::to) "); + assert_eq!(stringify_vis!(pub(in self::path::to)), "pub(in self::path::to) "); + assert_eq!(stringify_vis!(pub(in super::path::to)), "pub(in super::path::to) "); + + // VisibilityKind::Inherited + // Directly calling `stringify_vis!()` does not work. + macro_rules! stringify_inherited_vis { + ($vis:vis struct) => { + stringify_vis!($vis) + }; + } + assert_eq!(stringify_inherited_vis!(struct), ""); +} diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs new file mode 100644 index 000000000..ae6de3c50 --- /dev/null +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -0,0 +1,18 @@ +macro_rules! values { + ($($token:ident($value:literal) $(as $inner:ty)? => $attr:meta,)*) => { + #[derive(Debug)] + pub enum TokenKind { + $( + #[$attr] + $token $($inner)? = $value, + )* + } + }; +} +//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)` +//~| ERROR macro expansion ignores token `(String)` and any following + +values!(STRING(1) as (String) => cfg(test),); +//~^ ERROR expected one of `!` or `::`, found `` + +fn main() {} diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr new file mode 100644 index 000000000..c42ee9b29 --- /dev/null +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -0,0 +1,31 @@ +error: expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)` + --> $DIR/syntax-error-recovery.rs:7:26 + | +LL | $token $($inner)? = $value, + | ^^^^^^ expected one of `(`, `,`, `=`, `{`, or `}` +... +LL | values!(STRING(1) as (String) => cfg(test),); + | -------------------------------------------- in this macro invocation + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macro expansion ignores token `(String)` and any following + --> $DIR/syntax-error-recovery.rs:7:26 + | +LL | $token $($inner)? = $value, + | ^^^^^^ +... +LL | values!(STRING(1) as (String) => cfg(test),); + | -------------------------------------------- caused by the macro expansion here + | + = note: the usage of `values!` is likely invalid in item context + +error: expected one of `!` or `::`, found `` + --> $DIR/syntax-error-recovery.rs:15:9 + | +LL | values!(STRING(1) as (String) => cfg(test),); + | ^^^^^^ expected one of `!` or `::` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/syntax-extension-cfg.rs b/tests/ui/macros/syntax-extension-cfg.rs new file mode 100644 index 000000000..2e929fc1d --- /dev/null +++ b/tests/ui/macros/syntax-extension-cfg.rs @@ -0,0 +1,24 @@ +// run-pass +// compile-flags: --cfg foo --cfg qux="foo" + + +pub fn main() { + // check + if ! cfg!(foo) { panic!() } + if cfg!(not(foo)) { panic!() } + + if ! cfg!(qux="foo") { panic!() } + if cfg!(not(qux="foo")) { panic!() } + + if ! cfg!(all(foo, qux="foo")) { panic!() } + if cfg!(not(all(foo, qux="foo"))) { panic!() } + if cfg!(all(not(all(foo, qux="foo")))) { panic!() } + + if cfg!(not_a_cfg) { panic!() } + if cfg!(all(not_a_cfg, foo, qux="foo")) { panic!() } + if cfg!(all(not_a_cfg, foo, qux="foo")) { panic!() } + if ! cfg!(any(not_a_cfg, foo)) { panic!() } + + if ! cfg!(not(not_a_cfg)) { panic!() } + if ! cfg!(all(not(not_a_cfg), foo, qux="foo")) { panic!() } +} diff --git a/tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment b/tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment new file mode 100644 index 000000000..d752015a4 --- /dev/null +++ b/tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment @@ -0,0 +1,7 @@ +/* this is for run-pass/syntax-extension-source-utils.rs */ + +{ + assert!(file!().ends_with("includeme.fragment")); + assert_eq!(line!(), 5u32); + format!("victory robot {}", line!()) +} diff --git a/tests/ui/macros/syntax-extension-source-utils.rs b/tests/ui/macros/syntax-extension-source-utils.rs new file mode 100644 index 000000000..7e46260d5 --- /dev/null +++ b/tests/ui/macros/syntax-extension-source-utils.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(stable_features)] + +// ignore-pretty issue #37195 + +pub mod m1 { + pub mod m2 { + pub fn where_am_i() -> String { + (module_path!()).to_string() + } + } +} + +macro_rules! indirect_line { () => ( line!() ) } + +pub fn main() { + assert_eq!(line!(), 17); + assert_eq!(column!(), 16); + assert_eq!(indirect_line!(), 19); + assert!((file!().ends_with("syntax-extension-source-utils.rs"))); + assert_eq!(stringify!((2*3) + 5).to_string(), "(2 * 3) + 5".to_string()); + assert!(include!("syntax-extension-source-utils-files/includeme.\ + fragment").to_string() + == "victory robot 6".to_string()); + + assert!( + include_str!("syntax-extension-source-utils-files/includeme.\ + fragment").to_string() + .starts_with("/* this is for ")); + assert!( + include_bytes!("syntax-extension-source-utils-files/includeme.fragment") + [1] == (42 as u8)); // '*' + // The Windows tests are wrapped in an extra module for some reason + assert!((m1::m2::where_am_i().ends_with("m1::m2"))); + + assert_eq!((36, "(2 * 3) + 5"), (line!(), stringify!((2*3) + 5))); +} diff --git a/tests/ui/macros/trace-macro.rs b/tests/ui/macros/trace-macro.rs new file mode 100644 index 000000000..576120811 --- /dev/null +++ b/tests/ui/macros/trace-macro.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z trace-macros +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + println!("Hello, World!"); +} diff --git a/tests/ui/macros/trace-macro.stderr b/tests/ui/macros/trace-macro.stderr new file mode 100644 index 000000000..43272248c --- /dev/null +++ b/tests/ui/macros/trace-macro.stderr @@ -0,0 +1,9 @@ +note: trace_macro + --> $DIR/trace-macro.rs:5:5 + | +LL | println!("Hello, World!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expanding `println! { "Hello, World!" }` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl! ("Hello, World!")) ; }` + diff --git a/tests/ui/macros/trace_faulty_macros.rs b/tests/ui/macros/trace_faulty_macros.rs new file mode 100644 index 000000000..b2fdd2e19 --- /dev/null +++ b/tests/ui/macros/trace_faulty_macros.rs @@ -0,0 +1,43 @@ +// compile-flags: -Z trace-macros + +#![recursion_limit = "4"] + +macro_rules! my_faulty_macro { + () => { + my_faulty_macro!(bcd); //~ ERROR no rules + }; +} + +macro_rules! pat_macro { + () => { + pat_macro!(A{a:a, b:0, c:_, ..}); + }; + ($a:pat) => { + $a //~ ERROR expected expression + }; +} + +macro_rules! my_recursive_macro { + () => { + my_recursive_macro!(); //~ ERROR recursion limit + }; +} + +macro_rules! my_macro { + () => {}; +} + +fn main() { + my_faulty_macro!(); + my_recursive_macro!(); + test!(); + non_exisiting!(); + derive!(Debug); + let a = pat_macro!(); +} + +#[my_macro] +fn use_bang_macro_as_attr() {} + +#[derive(Debug)] //~ ERROR `derive` may only be applied to `struct`s +fn use_derive_macro_as_attr() {} diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr new file mode 100644 index 000000000..21e47da07 --- /dev/null +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -0,0 +1,85 @@ +error: no rules expected the token `bcd` + --> $DIR/trace_faulty_macros.rs:7:26 + | +LL | macro_rules! my_faulty_macro { + | ---------------------------- when calling this macro +LL | () => { +LL | my_faulty_macro!(bcd); + | ^^^ no rules expected this token in macro call +... +LL | my_faulty_macro!(); + | ------------------ in this macro invocation + | + = note: while trying to match end of macro + = note: this error originates in the macro `my_faulty_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: trace_macro + --> $DIR/trace_faulty_macros.rs:31:5 + | +LL | my_faulty_macro!(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: expanding `my_faulty_macro! { }` + = note: to `my_faulty_macro! (bcd) ;` + = note: expanding `my_faulty_macro! { bcd }` + +error: recursion limit reached while expanding `my_recursive_macro!` + --> $DIR/trace_faulty_macros.rs:22:9 + | +LL | my_recursive_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | my_recursive_macro!(); + | --------------------- in this macro invocation + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`trace_faulty_macros`) + = note: this error originates in the macro `my_recursive_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: trace_macro + --> $DIR/trace_faulty_macros.rs:32:5 + | +LL | my_recursive_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: expanding `my_recursive_macro! { }` + = note: to `my_recursive_macro! () ;` + = note: expanding `my_recursive_macro! { }` + = note: to `my_recursive_macro! () ;` + = note: expanding `my_recursive_macro! { }` + = note: to `my_recursive_macro! () ;` + = note: expanding `my_recursive_macro! { }` + = note: to `my_recursive_macro! () ;` + +error: expected expression, found `A { a: a, b: 0, c: _, .. }` + --> $DIR/trace_faulty_macros.rs:16:9 + | +LL | $a + | ^^ expected expression +... +LL | let a = pat_macro!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `pat_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/trace_faulty_macros.rs:42:1 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ not applicable here +LL | fn use_derive_macro_as_attr() {} + | -------------------------------- not a `struct`, `enum` or `union` + +note: trace_macro + --> $DIR/trace_faulty_macros.rs:36:13 + | +LL | let a = pat_macro!(); + | ^^^^^^^^^^^^ + | + = note: expanding `pat_macro! { }` + = note: to `pat_macro! (A { a : a, b : 0, c : _, .. }) ;` + = note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }` + = note: to `A { a: a, b: 0, c: _, .. }` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/macros/trace_macros-format.rs b/tests/ui/macros/trace_macros-format.rs new file mode 100644 index 000000000..afca45ca0 --- /dev/null +++ b/tests/ui/macros/trace_macros-format.rs @@ -0,0 +1,18 @@ +#![feature(trace_macros)] + +fn main() { + trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false` + trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false` + trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false` + trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false` + trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false` + trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false` + + + // should be fine: + macro_rules! expando { + ($x: ident) => { trace_macros!($x) } + } + + expando!(true); +} diff --git a/tests/ui/macros/trace_macros-format.stderr b/tests/ui/macros/trace_macros-format.stderr new file mode 100644 index 000000000..c32027086 --- /dev/null +++ b/tests/ui/macros/trace_macros-format.stderr @@ -0,0 +1,38 @@ +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-format.rs:4:5 + | +LL | trace_macros!(); + | ^^^^^^^^^^^^^^^ + +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-format.rs:5:5 + | +LL | trace_macros!(1); + | ^^^^^^^^^^^^^^^^ + +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-format.rs:6:5 + | +LL | trace_macros!(ident); + | ^^^^^^^^^^^^^^^^^^^^ + +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-format.rs:7:5 + | +LL | trace_macros!(for); + | ^^^^^^^^^^^^^^^^^^ + +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-format.rs:8:5 + | +LL | trace_macros!(true,); + | ^^^^^^^^^^^^^^^^^^^^ + +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-format.rs:9:5 + | +LL | trace_macros!(false 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/macros/try-macro.rs b/tests/ui/macros/try-macro.rs new file mode 100644 index 000000000..824c77d9d --- /dev/null +++ b/tests/ui/macros/try-macro.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(deprecated)] // for deprecated `try!()` macro +use std::num::{ParseFloatError, ParseIntError}; + +fn main() { + assert_eq!(simple(), Ok(1)); + assert_eq!(nested(), Ok(2)); + assert_eq!(merge_ok(), Ok(3.0)); + assert_eq!(merge_int_err(), Err(Error::Int)); + assert_eq!(merge_float_err(), Err(Error::Float)); +} + +fn simple() -> Result { + Ok(try!("1".parse())) +} + +fn nested() -> Result { + Ok(try!(try!("2".parse::()).to_string().parse::())) +} + +fn merge_ok() -> Result { + Ok(try!("1".parse::()) as f32 + try!("2.0".parse::())) +} + +fn merge_int_err() -> Result { + Ok(try!("a".parse::()) as f32 + try!("2.0".parse::())) +} + +fn merge_float_err() -> Result { + Ok(try!("1".parse::()) as f32 + try!("b".parse::())) +} + +#[derive(Debug, PartialEq)] +enum Error { + Int, + Float, +} + +impl From for Error { + fn from(_: ParseIntError) -> Error { + Error::Int + } +} + +impl From for Error { + fn from(_: ParseFloatError) -> Error { + Error::Float + } +} diff --git a/tests/ui/macros/two-macro-use.rs b/tests/ui/macros/two-macro-use.rs new file mode 100644 index 000000000..07022bb01 --- /dev/null +++ b/tests/ui/macros/two-macro-use.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:two_macros.rs + +#[macro_use(macro_one)] +#[macro_use(macro_two)] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/tests/ui/macros/type-macros-hlist.rs b/tests/ui/macros/type-macros-hlist.rs new file mode 100644 index 000000000..946b5bd5d --- /dev/null +++ b/tests/ui/macros/type-macros-hlist.rs @@ -0,0 +1,80 @@ +// run-pass +#![allow(unused_macro_rules)] + +use std::ops::*; + +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +struct Nil; + // empty HList +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +struct Cons(H, T); + // cons cell of HList + + // trait to classify valid HLists +trait HList { } +impl HList for Nil { } +impl HList for Cons { } + +// term-level macro for HLists +macro_rules! hlist({ } => { Nil } ; { $ head : expr } => { + Cons ( $ head , Nil ) } ; { + $ head : expr , $ ( $ tail : expr ) , * } => { + Cons ( $ head , hlist ! ( $ ( $ tail ) , * ) ) } ;); + +// type-level macro for HLists +macro_rules! HList({ } => { Nil } ; { $ head : ty } => { + Cons < $ head , Nil > } ; { + $ head : ty , $ ( $ tail : ty ) , * } => { + Cons < $ head , HList ! ( $ ( $ tail ) , * ) > } ;); + +// nil case for HList append +impl Add for Nil { + type + Output + = + Ys; + + fn add(self, rhs: Ys) -> Ys { rhs } +} + +// cons case for HList append +impl Add for Cons + where Xs: Add { + type + Output + = + Cons; + + fn add(self, rhs: Ys) -> Cons { Cons(self.0, self.1 + rhs) } +} + +// type macro Expr allows us to expand the + operator appropriately +macro_rules! Expr({ ( $ ( $ LHS : tt ) + ) } => { Expr ! ( $ ( $ LHS ) + ) } ; + { HList ! [ $ ( $ LHS : tt ) * ] + $ ( $ RHS : tt ) + } => { + < Expr ! ( HList ! [ $ ( $ LHS ) * ] ) as Add < Expr ! ( + $ ( $ RHS ) + ) >> :: Output } ; { + $ LHS : tt + $ ( $ RHS : tt ) + } => { + < Expr ! ( $ LHS ) as Add < Expr ! ( $ ( $ RHS ) + ) >> :: + Output } ; { $ LHS : ty } => { $ LHS } ;); + +// test demonstrating term level `xs + ys` and type level `Expr!(Xs + Ys)` +fn main() { + fn aux(xs: Xs, ys: Ys) -> Expr!(Xs + Ys) where + Xs: Add { + xs + ys + } + + let xs: HList!(& str , bool , Vec < u64 >) = + hlist!("foo" , false , vec ! [ ]); + let ys: HList!(u64 , [ u8 ; 3 ] , ( )) = + hlist!(0 , [ 0 , 1 , 2 ] , ( )); + + // demonstrate recursive expansion of Expr! + let zs: + Expr!(( + HList ! [ & str ] + HList ! [ bool ] + HList ! [ Vec < u64 > + ] ) + ( HList ! [ u64 ] + HList ! [ [ u8 ; 3 ] , ( ) ] ) + + HList ! [ ]) = aux(xs, ys); + assert_eq!(zs , hlist ! [ + "foo" , false , vec ! [ ] , 0 , [ 0 , 1 , 2 ] , ( ) ]) +} diff --git a/tests/ui/macros/type-macros-simple.rs b/tests/ui/macros/type-macros-simple.rs new file mode 100644 index 000000000..dd3ad2ef0 --- /dev/null +++ b/tests/ui/macros/type-macros-simple.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +macro_rules! Tuple { + { $A:ty,$B:ty } => { ($A, $B) } +} + +fn main() { + let x: Tuple!(i32, i32) = (1, 2); +} + +fn issue_36540() { + let i32 = 0; + macro_rules! m { () => { i32 } } + struct S(m!(), T) where T: Trait; + + let x: m!() = m!(); + std::cell::Cell::::new(m!()); + impl std::ops::Index for dyn Trait<(m!(), T)> + where T: Trait + { + type Output = m!(); + fn index(&self, i: m!()) -> &m!() { + unimplemented!() + } + } +} + +trait Trait {} +impl Trait for i32 {} diff --git a/tests/ui/macros/typeck-macro-interaction-issue-8852.rs b/tests/ui/macros/typeck-macro-interaction-issue-8852.rs new file mode 100644 index 000000000..f2b089b74 --- /dev/null +++ b/tests/ui/macros/typeck-macro-interaction-issue-8852.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] + +enum T { + A(isize), + B(f64) +} + +// after fixing #9384 and implementing hygiene for match bindings, +// this now fails because the insertion of the 'y' into the match +// doesn't cause capture. Making this macro hygienic (as I've done) +// could very well make this test case completely pointless.... + +macro_rules! test { + ($id1:ident, $id2:ident, $e:expr) => ( + fn foo(a:T, b:T) -> T { + match (a, b) { + (T::A($id1), T::A($id2)) => T::A($e), + (T::B($id1), T::B($id2)) => T::B($e), + _ => panic!() + } + } + ) +} + +test!(x,y,x + y); + +pub fn main() { + foo(T::A(1), T::A(2)); +} diff --git a/tests/ui/macros/unimplemented-macro-panic.rs b/tests/ui/macros/unimplemented-macro-panic.rs new file mode 100644 index 000000000..e7169903f --- /dev/null +++ b/tests/ui/macros/unimplemented-macro-panic.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:not implemented +// ignore-emscripten no processes + +fn main() { + unimplemented!() +} diff --git a/tests/ui/macros/unknown-builtin.rs b/tests/ui/macros/unknown-builtin.rs new file mode 100644 index 000000000..16f9139e6 --- /dev/null +++ b/tests/ui/macros/unknown-builtin.rs @@ -0,0 +1,14 @@ +// error-pattern: attempted to define built-in macro more than once + +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown` + +#[rustc_builtin_macro] +macro_rules! line { () => () } //~ NOTE previously defined here + +fn main() { + line!(); + std::prelude::v1::line!(); +} diff --git a/tests/ui/macros/unknown-builtin.stderr b/tests/ui/macros/unknown-builtin.stderr new file mode 100644 index 000000000..22f54e04e --- /dev/null +++ b/tests/ui/macros/unknown-builtin.stderr @@ -0,0 +1,18 @@ +error: cannot find a built-in macro with name `unknown` + --> $DIR/unknown-builtin.rs:6:1 + | +LL | macro_rules! unknown { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0773]: attempted to define built-in macro more than once + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | +note: previously defined here + --> $DIR/unknown-builtin.rs:9:1 + | +LL | macro_rules! line { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0773`. diff --git a/tests/ui/macros/unreachable-arg.edition_2021.stderr b/tests/ui/macros/unreachable-arg.edition_2021.stderr new file mode 100644 index 000000000..d70ef31ee --- /dev/null +++ b/tests/ui/macros/unreachable-arg.edition_2021.stderr @@ -0,0 +1,13 @@ +error: format argument must be a string literal + --> $DIR/unreachable-arg.rs:15:18 + | +LL | unreachable!(a); + | ^ + | +help: you might be missing a string literal to format with + | +LL | unreachable!("{}", a); + | +++++ + +error: aborting due to previous error + diff --git a/tests/ui/macros/unreachable-arg.rs b/tests/ui/macros/unreachable-arg.rs new file mode 100644 index 000000000..4024bd20b --- /dev/null +++ b/tests/ui/macros/unreachable-arg.rs @@ -0,0 +1,16 @@ +// ignore-emscripten no processes + +// revisions: edition_2015 edition_2021 +// [edition_2015]edition:2015 +// [edition_2021]edition:2021 +// [edition_2015]run-fail +// [edition_2021]check-fail +// [edition_2015]error-pattern:internal error: entered unreachable code: hello +// [edition_2021]error-pattern:format argument must be a string literal + +#![allow(non_fmt_panics)] + +fn main() { + let a = "hello"; + unreachable!(a); +} diff --git a/tests/ui/macros/unreachable-fmt-msg.rs b/tests/ui/macros/unreachable-fmt-msg.rs new file mode 100644 index 000000000..eb17ed927 --- /dev/null +++ b/tests/ui/macros/unreachable-fmt-msg.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:internal error: entered unreachable code: 6 is not prime +// ignore-emscripten no processes + +fn main() { + unreachable!("{} is not {}", 6u32, "prime"); +} diff --git a/tests/ui/macros/unreachable-format-arg.rs b/tests/ui/macros/unreachable-format-arg.rs new file mode 100644 index 000000000..ff059ad9e --- /dev/null +++ b/tests/ui/macros/unreachable-format-arg.rs @@ -0,0 +1,15 @@ +// run-fail +// ignore-emscripten no processes + +// revisions: edition_2015 edition_2021 +// [edition_2015]edition:2015 +// [edition_2021]edition:2021 +// [edition_2015]error-pattern:internal error: entered unreachable code: x is {x} +// [edition_2021]error-pattern:internal error: entered unreachable code: x is 5 + +#![allow(non_fmt_panics)] + +fn main() { + let x = 5; + unreachable!("x is {x}"); +} diff --git a/tests/ui/macros/unreachable-format-args.edition_2015.stderr b/tests/ui/macros/unreachable-format-args.edition_2015.stderr new file mode 100644 index 000000000..2cc2e134b --- /dev/null +++ b/tests/ui/macros/unreachable-format-args.edition_2015.stderr @@ -0,0 +1,12 @@ +error: there is no argument named `x` + --> $DIR/unreachable-format-args.rs:13:5 + | +LL | unreachable!("x is {x} and y is {y}", y = 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: did you intend to capture a variable `x` 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 the macro `$crate::concat` which comes from the expansion of the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/macros/unreachable-format-args.rs b/tests/ui/macros/unreachable-format-args.rs new file mode 100644 index 000000000..04a31fc1b --- /dev/null +++ b/tests/ui/macros/unreachable-format-args.rs @@ -0,0 +1,14 @@ +// ignore-emscripten no processes + +// revisions: edition_2015 edition_2021 +// [edition_2015]edition:2015 +// [edition_2021]edition:2021 +// [edition_2015]check-fail +// [edition_2021]run-fail +// [edition_2015]error-pattern:there is no argument named `x` +// [edition_2021]error-pattern:internal error: entered unreachable code: x is 5 and y is 0 + +fn main() { + let x = 5; + unreachable!("x is {x} and y is {y}", y = 0); +} diff --git a/tests/ui/macros/unreachable-macro-panic.rs b/tests/ui/macros/unreachable-macro-panic.rs new file mode 100644 index 000000000..55e2102e2 --- /dev/null +++ b/tests/ui/macros/unreachable-macro-panic.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:internal error: entered unreachable code +// ignore-emscripten no processes + +fn main() { + unreachable!() +} diff --git a/tests/ui/macros/unreachable-static-msg.rs b/tests/ui/macros/unreachable-static-msg.rs new file mode 100644 index 000000000..55edf3af7 --- /dev/null +++ b/tests/ui/macros/unreachable-static-msg.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:internal error: entered unreachable code: uhoh +// ignore-emscripten no processes + +fn main() { + unreachable!("uhoh") +} diff --git a/tests/ui/macros/unreachable.rs b/tests/ui/macros/unreachable.rs new file mode 100644 index 000000000..55e2102e2 --- /dev/null +++ b/tests/ui/macros/unreachable.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:internal error: entered unreachable code +// ignore-emscripten no processes + +fn main() { + unreachable!() +} diff --git a/tests/ui/macros/use-macro-self.rs b/tests/ui/macros/use-macro-self.rs new file mode 100644 index 000000000..06464ab0b --- /dev/null +++ b/tests/ui/macros/use-macro-self.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(unused_imports)] +// aux-build:use-macro-self.rs + +#[macro_use] +extern crate use_macro_self; + +use use_macro_self::foobarius::{self}; + +fn main() { + let _: () = foobarius!(); // OK, the macro returns `()` +} diff --git a/tests/ui/macros/vec-macro-in-pattern.rs b/tests/ui/macros/vec-macro-in-pattern.rs new file mode 100644 index 000000000..ce4298b8b --- /dev/null +++ b/tests/ui/macros/vec-macro-in-pattern.rs @@ -0,0 +1,10 @@ +// This is a regression test for #61933 +// Verify that the vec![] macro may not be used in patterns +// and that the resulting diagnostic is actually helpful. + +fn main() { + match Some(vec![42]) { + Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns + _ => {} + } +} diff --git a/tests/ui/macros/vec-macro-in-pattern.stderr b/tests/ui/macros/vec-macro-in-pattern.stderr new file mode 100644 index 000000000..7060f5d8b --- /dev/null +++ b/tests/ui/macros/vec-macro-in-pattern.stderr @@ -0,0 +1,10 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/vec-macro-in-pattern.rs:7:14 + | +LL | Some(vec![43]) => {} + | ^^^^^^^^ + | + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/main-wrong-location.rs b/tests/ui/main-wrong-location.rs new file mode 100644 index 000000000..d7deeaed9 --- /dev/null +++ b/tests/ui/main-wrong-location.rs @@ -0,0 +1,5 @@ +mod m { + // An inferred main entry point + // must appear at the top of the crate + fn main() { } +} //~ ERROR `main` function not found diff --git a/tests/ui/main-wrong-location.stderr b/tests/ui/main-wrong-location.stderr new file mode 100644 index 000000000..3d64b0a67 --- /dev/null +++ b/tests/ui/main-wrong-location.stderr @@ -0,0 +1,17 @@ +error[E0601]: `main` function not found in crate `main_wrong_location` + --> $DIR/main-wrong-location.rs:5:2 + | +LL | } + | ^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`) + | +note: here is a function named `main` + --> $DIR/main-wrong-location.rs:4:5 + | +LL | fn main() { } + | ^^^^^^^^^ + = note: you have one or more functions named `main` not defined at the crate level + = help: consider moving the `main` function definitions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/main-wrong-type.rs b/tests/ui/main-wrong-type.rs new file mode 100644 index 000000000..31deba72a --- /dev/null +++ b/tests/ui/main-wrong-type.rs @@ -0,0 +1,8 @@ +struct S { + x: isize, + y: isize, +} + +fn main(foo: S) { +//~^ ERROR: `main` function has wrong type [E0580] +} diff --git a/tests/ui/main-wrong-type.stderr b/tests/ui/main-wrong-type.stderr new file mode 100644 index 000000000..43efaf884 --- /dev/null +++ b/tests/ui/main-wrong-type.stderr @@ -0,0 +1,12 @@ +error[E0580]: `main` function has wrong type + --> $DIR/main-wrong-type.rs:6:1 + | +LL | fn main(foo: S) { + | ^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `fn()` + found fn pointer `fn(S)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0580`. diff --git a/tests/ui/malformed/issue-69341-malformed-derive-inert.rs b/tests/ui/malformed/issue-69341-malformed-derive-inert.rs new file mode 100644 index 000000000..fc4c3f4e6 --- /dev/null +++ b/tests/ui/malformed/issue-69341-malformed-derive-inert.rs @@ -0,0 +1,6 @@ +fn main() {} + +struct CLI { + #[derive(parse())] //~ ERROR expected non-macro attribute, found attribute macro + path: (), +} diff --git a/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr b/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr new file mode 100644 index 000000000..04f7ebe01 --- /dev/null +++ b/tests/ui/malformed/issue-69341-malformed-derive-inert.stderr @@ -0,0 +1,8 @@ +error: expected non-macro attribute, found attribute macro `derive` + --> $DIR/issue-69341-malformed-derive-inert.rs:4:7 + | +LL | #[derive(parse())] + | ^^^^^^ not a non-macro attribute + +error: aborting due to previous error + diff --git a/tests/ui/malformed/malformed-derive-entry.rs b/tests/ui/malformed/malformed-derive-entry.rs new file mode 100644 index 000000000..77fa2f566 --- /dev/null +++ b/tests/ui/malformed/malformed-derive-entry.rs @@ -0,0 +1,14 @@ +#[derive(Copy(Bad))] +//~^ ERROR traits in `#[derive(...)]` don't accept arguments +//~| ERROR the trait bound +struct Test1; + +#[derive(Copy="bad")] +//~^ ERROR traits in `#[derive(...)]` don't accept values +//~| ERROR the trait bound +struct Test2; + +#[derive] //~ ERROR malformed `derive` attribute input +struct Test4; + +fn main() {} diff --git a/tests/ui/malformed/malformed-derive-entry.stderr b/tests/ui/malformed/malformed-derive-entry.stderr new file mode 100644 index 000000000..6ff6fbabb --- /dev/null +++ b/tests/ui/malformed/malformed-derive-entry.stderr @@ -0,0 +1,49 @@ +error: traits in `#[derive(...)]` don't accept arguments + --> $DIR/malformed-derive-entry.rs:1:14 + | +LL | #[derive(Copy(Bad))] + | ^^^^^ help: remove the arguments + +error: traits in `#[derive(...)]` don't accept values + --> $DIR/malformed-derive-entry.rs:6:14 + | +LL | #[derive(Copy="bad")] + | ^^^^^^ help: remove the value + +error: malformed `derive` attribute input + --> $DIR/malformed-derive-entry.rs:11:1 + | +LL | #[derive] + | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` + +error[E0277]: the trait bound `Test1: Clone` is not satisfied + --> $DIR/malformed-derive-entry.rs:1:10 + | +LL | #[derive(Copy(Bad))] + | ^^^^ the trait `Clone` is not implemented for `Test1` + | +note: required by a bound in `Copy` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Test1` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0277]: the trait bound `Test2: Clone` is not satisfied + --> $DIR/malformed-derive-entry.rs:6:10 + | +LL | #[derive(Copy="bad")] + | ^^^^ the trait `Clone` is not implemented for `Test2` + | +note: required by a bound in `Copy` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Test2` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/malformed/malformed-interpolated.rs b/tests/ui/malformed/malformed-interpolated.rs new file mode 100644 index 000000000..0d84e723f --- /dev/null +++ b/tests/ui/malformed/malformed-interpolated.rs @@ -0,0 +1,16 @@ +#![feature(rustc_attrs)] + +macro_rules! check { + ($expr: expr) => ( + #[rustc_dummy = $expr] + use main as _; + ); +} + +check!("0"); // OK +check!(0); // OK +check!(0u8); //~ ERROR suffixed literals are not allowed in attributes +check!(-0); //~ ERROR unexpected expression: `-0` +check!(0 + 0); //~ ERROR unexpected expression: `0 + 0` + +fn main() {} diff --git a/tests/ui/malformed/malformed-interpolated.stderr b/tests/ui/malformed/malformed-interpolated.stderr new file mode 100644 index 000000000..c24d9f153 --- /dev/null +++ b/tests/ui/malformed/malformed-interpolated.stderr @@ -0,0 +1,22 @@ +error: suffixed literals are not allowed in attributes + --> $DIR/malformed-interpolated.rs:12:8 + | +LL | check!(0u8); + | ^^^ + | + = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) + +error: unexpected expression: `-0` + --> $DIR/malformed-interpolated.rs:13:8 + | +LL | check!(-0); + | ^^ + +error: unexpected expression: `0 + 0` + --> $DIR/malformed-interpolated.rs:14:8 + | +LL | check!(0 + 0); + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/malformed/malformed-meta-delim.rs b/tests/ui/malformed/malformed-meta-delim.rs new file mode 100644 index 000000000..5b1614b69 --- /dev/null +++ b/tests/ui/malformed/malformed-meta-delim.rs @@ -0,0 +1,11 @@ +fn main() {} + +#[allow { foo_lint } ] +//~^ ERROR wrong meta list delimiters +//~| HELP the delimiters should be `(` and `)` +fn delim_brace() {} + +#[allow [ foo_lint ] ] +//~^ ERROR wrong meta list delimiters +//~| HELP the delimiters should be `(` and `)` +fn delim_bracket() {} diff --git a/tests/ui/malformed/malformed-meta-delim.stderr b/tests/ui/malformed/malformed-meta-delim.stderr new file mode 100644 index 000000000..27636c3d5 --- /dev/null +++ b/tests/ui/malformed/malformed-meta-delim.stderr @@ -0,0 +1,24 @@ +error: wrong meta list delimiters + --> $DIR/malformed-meta-delim.rs:3:9 + | +LL | #[allow { foo_lint } ] + | ^^^^^^^^^^^^ + | +help: the delimiters should be `(` and `)` + | +LL | #[allow ( foo_lint ) ] + | ~ ~ + +error: wrong meta list delimiters + --> $DIR/malformed-meta-delim.rs:8:9 + | +LL | #[allow [ foo_lint ] ] + | ^^^^^^^^^^^^ + | +help: the delimiters should be `(` and `)` + | +LL | #[allow ( foo_lint ) ] + | ~ ~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/malformed/malformed-plugin-1.rs b/tests/ui/malformed/malformed-plugin-1.rs new file mode 100644 index 000000000..d4c1a2a16 --- /dev/null +++ b/tests/ui/malformed/malformed-plugin-1.rs @@ -0,0 +1,5 @@ +#![feature(plugin)] +#![plugin] //~ ERROR malformed `plugin` attribute +//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated + +fn main() {} diff --git a/tests/ui/malformed/malformed-plugin-1.stderr b/tests/ui/malformed/malformed-plugin-1.stderr new file mode 100644 index 000000000..505f6b6f1 --- /dev/null +++ b/tests/ui/malformed/malformed-plugin-1.stderr @@ -0,0 +1,16 @@ +error: malformed `plugin` attribute input + --> $DIR/malformed-plugin-1.rs:2:1 + | +LL | #![plugin] + | ^^^^^^^^^^ help: must be of the form: `#![plugin(name)]` + +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 + --> $DIR/malformed-plugin-1.rs:2:1 + | +LL | #![plugin] + | ^^^^^^^^^^ help: may be removed in a future compiler version + | + = note: `#[warn(deprecated)]` on by default + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/malformed/malformed-plugin-2.rs b/tests/ui/malformed/malformed-plugin-2.rs new file mode 100644 index 000000000..ba80d97a3 --- /dev/null +++ b/tests/ui/malformed/malformed-plugin-2.rs @@ -0,0 +1,5 @@ +#![feature(plugin)] +#![plugin="bleh"] //~ ERROR malformed `plugin` attribute +//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated + +fn main() {} diff --git a/tests/ui/malformed/malformed-plugin-2.stderr b/tests/ui/malformed/malformed-plugin-2.stderr new file mode 100644 index 000000000..52bbd82a3 --- /dev/null +++ b/tests/ui/malformed/malformed-plugin-2.stderr @@ -0,0 +1,16 @@ +error: malformed `plugin` attribute input + --> $DIR/malformed-plugin-2.rs:2:1 + | +LL | #![plugin="bleh"] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![plugin(name)]` + +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 + --> $DIR/malformed-plugin-2.rs:2:1 + | +LL | #![plugin="bleh"] + | ^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version + | + = note: `#[warn(deprecated)]` on by default + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/malformed/malformed-plugin-3.rs b/tests/ui/malformed/malformed-plugin-3.rs new file mode 100644 index 000000000..d2bd8f9f8 --- /dev/null +++ b/tests/ui/malformed/malformed-plugin-3.rs @@ -0,0 +1,5 @@ +#![feature(plugin)] +#![plugin(foo="bleh")] //~ ERROR malformed `plugin` attribute +//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated + +fn main() {} diff --git a/tests/ui/malformed/malformed-plugin-3.stderr b/tests/ui/malformed/malformed-plugin-3.stderr new file mode 100644 index 000000000..64cb429ea --- /dev/null +++ b/tests/ui/malformed/malformed-plugin-3.stderr @@ -0,0 +1,17 @@ +error[E0498]: malformed `plugin` attribute + --> $DIR/malformed-plugin-3.rs:2:11 + | +LL | #![plugin(foo="bleh")] + | ^^^^^^^^^^ malformed attribute + +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 + --> $DIR/malformed-plugin-3.rs:2:1 + | +LL | #![plugin(foo="bleh")] + | ^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version + | + = note: `#[warn(deprecated)]` on by default + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0498`. diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs new file mode 100644 index 000000000..ac1444bba --- /dev/null +++ b/tests/ui/malformed/malformed-regressions.rs @@ -0,0 +1,12 @@ +#[doc] //~ ERROR attribute must be of the form +//~^ WARN this was previously accepted +#[ignore()] //~ ERROR attribute must be of the form +//~^ WARN this was previously accepted +#[inline = ""] //~ ERROR attribute must be of the form +//~^ WARN this was previously accepted +#[link] //~ ERROR attribute must be of the form +//~^ WARN this was previously accepted +#[link = ""] //~ ERROR attribute must be of the form +//~^ WARN this was previously accepted + +fn main() {} diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr new file mode 100644 index 000000000..9bfbe7eba --- /dev/null +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -0,0 +1,48 @@ +error: attribute must be of the form `#[doc(hidden|inline|...)]` or `#[doc = "string"]` + --> $DIR/malformed-regressions.rs:1:1 + | +LL | #[doc] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + = note: `#[deny(ill_formed_attribute_input)]` on by default + +error: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]` + --> $DIR/malformed-regressions.rs:3:1 + | +LL | #[ignore()] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: attribute must be of the form `#[inline]` or `#[inline(always|never)]` + --> $DIR/malformed-regressions.rs:5:1 + | +LL | #[inline = ""] + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/malformed-regressions.rs:7:1 + | +LL | #[link] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` + --> $DIR/malformed-regressions.rs:9:1 + | +LL | #[link = ""] + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + +error: aborting due to 5 previous errors + diff --git a/tests/ui/malformed/malformed-special-attrs.rs b/tests/ui/malformed/malformed-special-attrs.rs new file mode 100644 index 000000000..05b7ebe46 --- /dev/null +++ b/tests/ui/malformed/malformed-special-attrs.rs @@ -0,0 +1,13 @@ +#[cfg_attr] //~ ERROR malformed `cfg_attr` attribute +struct S1; + +#[cfg_attr = ""] //~ ERROR malformed `cfg_attr` attribute +struct S2; + +#[derive] //~ ERROR malformed `derive` attribute +struct S3; + +#[derive = ""] //~ ERROR malformed `derive` attribute +struct S4; + +fn main() {} diff --git a/tests/ui/malformed/malformed-special-attrs.stderr b/tests/ui/malformed/malformed-special-attrs.stderr new file mode 100644 index 000000000..1764c3969 --- /dev/null +++ b/tests/ui/malformed/malformed-special-attrs.stderr @@ -0,0 +1,30 @@ +error: malformed `cfg_attr` attribute input + --> $DIR/malformed-special-attrs.rs:1:1 + | +LL | #[cfg_attr] + | ^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` + | + = note: for more information, visit + +error: malformed `cfg_attr` attribute input + --> $DIR/malformed-special-attrs.rs:4:1 + | +LL | #[cfg_attr = ""] + | ^^^^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` + | + = note: for more information, visit + +error: malformed `derive` attribute input + --> $DIR/malformed-special-attrs.rs:7:1 + | +LL | #[derive] + | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` + +error: malformed `derive` attribute input + --> $DIR/malformed-special-attrs.rs:10:1 + | +LL | #[derive = ""] + | ^^^^^^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/manual/manual-link-bad-form.rs b/tests/ui/manual/manual-link-bad-form.rs new file mode 100644 index 000000000..bc9b6be02 --- /dev/null +++ b/tests/ui/manual/manual-link-bad-form.rs @@ -0,0 +1,5 @@ +// compile-flags:-l static= +// error-pattern: library name must not be empty + +fn main() { +} diff --git a/tests/ui/manual/manual-link-bad-form.stderr b/tests/ui/manual/manual-link-bad-form.stderr new file mode 100644 index 000000000..7fd7a1066 --- /dev/null +++ b/tests/ui/manual/manual-link-bad-form.stderr @@ -0,0 +1,2 @@ +error: library name must not be empty + diff --git a/tests/ui/manual/manual-link-bad-kind.rs b/tests/ui/manual/manual-link-bad-kind.rs new file mode 100644 index 000000000..c50a6c034 --- /dev/null +++ b/tests/ui/manual/manual-link-bad-kind.rs @@ -0,0 +1,5 @@ +// compile-flags:-l bar=foo +// error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg + +fn main() { +} diff --git a/tests/ui/manual/manual-link-bad-kind.stderr b/tests/ui/manual/manual-link-bad-kind.stderr new file mode 100644 index 000000000..647c4c61e --- /dev/null +++ b/tests/ui/manual/manual-link-bad-kind.stderr @@ -0,0 +1,2 @@ +error: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg + diff --git a/tests/ui/manual/manual-link-bad-search-path.rs b/tests/ui/manual/manual-link-bad-search-path.rs new file mode 100644 index 000000000..0fe23b02a --- /dev/null +++ b/tests/ui/manual/manual-link-bad-search-path.rs @@ -0,0 +1,5 @@ +// compile-flags:-L native= +// error-pattern: empty search path given via `-L` + +fn main() { +} diff --git a/tests/ui/manual/manual-link-bad-search-path.stderr b/tests/ui/manual/manual-link-bad-search-path.stderr new file mode 100644 index 000000000..2c0649ea1 --- /dev/null +++ b/tests/ui/manual/manual-link-bad-search-path.stderr @@ -0,0 +1,2 @@ +error: empty search path given via `-L` + diff --git a/tests/ui/manual/manual-link-framework.rs b/tests/ui/manual/manual-link-framework.rs new file mode 100644 index 000000000..57c5966e9 --- /dev/null +++ b/tests/ui/manual/manual-link-framework.rs @@ -0,0 +1,7 @@ +// ignore-macos +// ignore-ios +// compile-flags:-l framework=foo +// error-pattern: library kind `framework` is only supported on Apple targets + +fn main() { +} diff --git a/tests/ui/manual/manual-link-framework.stderr b/tests/ui/manual/manual-link-framework.stderr new file mode 100644 index 000000000..de045d56c --- /dev/null +++ b/tests/ui/manual/manual-link-framework.stderr @@ -0,0 +1,4 @@ +error: library kind `framework` is only supported on Apple targets + +error: aborting due to previous error + diff --git a/tests/ui/manual/manual-link-unsupported-kind.rs b/tests/ui/manual/manual-link-unsupported-kind.rs new file mode 100644 index 000000000..b8ec575a4 --- /dev/null +++ b/tests/ui/manual/manual-link-unsupported-kind.rs @@ -0,0 +1,5 @@ +// compile-flags:-l raw-dylib=foo +// error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg + +fn main() { +} diff --git a/tests/ui/manual/manual-link-unsupported-kind.stderr b/tests/ui/manual/manual-link-unsupported-kind.stderr new file mode 100644 index 000000000..ae4a1ec9a --- /dev/null +++ b/tests/ui/manual/manual-link-unsupported-kind.stderr @@ -0,0 +1,2 @@ +error: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg + diff --git a/tests/ui/marker_trait_attr/issue-61651-type-mismatch.rs b/tests/ui/marker_trait_attr/issue-61651-type-mismatch.rs new file mode 100644 index 000000000..0af706615 --- /dev/null +++ b/tests/ui/marker_trait_attr/issue-61651-type-mismatch.rs @@ -0,0 +1,17 @@ +// check-pass +// Regression test for issue #61651 +// Verifies that we don't try to constrain inference +// variables due to the presence of multiple applicable +// marker trait impls + +#![feature(marker_trait_attr)] + +#[marker] // Remove this line and it works?!? +trait Foo {} +impl Foo for u8 {} +impl Foo<[u8; 1]> for u8 {} +fn foo, U>(_: T) -> U { unimplemented!() } + +fn main() { + let _: u16 = foo(0_u8); +} diff --git a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs new file mode 100644 index 000000000..0bf620934 --- /dev/null +++ b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs @@ -0,0 +1,23 @@ +#![feature(marker_trait_attr)] + +#[marker] //~ ERROR attribute should be applied to a trait +struct Struct {} + +#[marker] //~ ERROR attribute should be applied to a trait +impl Struct {} + +#[marker] //~ ERROR attribute should be applied to a trait +union Union { + x: i32, +} + +#[marker] //~ ERROR attribute should be applied to a trait +const CONST: usize = 10; + +#[marker] //~ ERROR attribute should be applied to a trait +fn function() {} + +#[marker] //~ ERROR attribute should be applied to a trait +type Type = (); + +fn main() {} diff --git a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr new file mode 100644 index 000000000..19a5290dd --- /dev/null +++ b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr @@ -0,0 +1,52 @@ +error: attribute should be applied to a trait + --> $DIR/marker-attribute-on-non-trait.rs:3:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | struct Struct {} + | ---------------- not a trait + +error: attribute should be applied to a trait + --> $DIR/marker-attribute-on-non-trait.rs:6:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | impl Struct {} + | -------------- not a trait + +error: attribute should be applied to a trait + --> $DIR/marker-attribute-on-non-trait.rs:9:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | / union Union { +LL | | x: i32, +LL | | } + | |_- not a trait + +error: attribute should be applied to a trait + --> $DIR/marker-attribute-on-non-trait.rs:14:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | const CONST: usize = 10; + | ------------------------ not a trait + +error: attribute should be applied to a trait + --> $DIR/marker-attribute-on-non-trait.rs:17:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | fn function() {} + | ---------------- not a trait + +error: attribute should be applied to a trait + --> $DIR/marker-attribute-on-non-trait.rs:20:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | type Type = (); + | --------------- not a trait + +error: aborting due to 6 previous errors + diff --git a/tests/ui/marker_trait_attr/marker-attribute-with-values.rs b/tests/ui/marker_trait_attr/marker-attribute-with-values.rs new file mode 100644 index 000000000..9e07f0eae --- /dev/null +++ b/tests/ui/marker_trait_attr/marker-attribute-with-values.rs @@ -0,0 +1,12 @@ +#![feature(marker_trait_attr)] + +#[marker(always)] //~ ERROR malformed `marker` attribute +trait Marker1 {} + +#[marker("never")] //~ ERROR malformed `marker` attribute +trait Marker2 {} + +#[marker(key = "value")] //~ ERROR malformed `marker` attribute +trait Marker3 {} + +fn main() {} diff --git a/tests/ui/marker_trait_attr/marker-attribute-with-values.stderr b/tests/ui/marker_trait_attr/marker-attribute-with-values.stderr new file mode 100644 index 000000000..6f9c9508e --- /dev/null +++ b/tests/ui/marker_trait_attr/marker-attribute-with-values.stderr @@ -0,0 +1,20 @@ +error: malformed `marker` attribute input + --> $DIR/marker-attribute-with-values.rs:3:1 + | +LL | #[marker(always)] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[marker]` + +error: malformed `marker` attribute input + --> $DIR/marker-attribute-with-values.rs:6:1 + | +LL | #[marker("never")] + | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[marker]` + +error: malformed `marker` attribute input + --> $DIR/marker-attribute-with-values.rs:9:1 + | +LL | #[marker(key = "value")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[marker]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/marker_trait_attr/marker-trait-with-associated-items.rs b/tests/ui/marker_trait_attr/marker-trait-with-associated-items.rs new file mode 100644 index 000000000..a6e00ecc9 --- /dev/null +++ b/tests/ui/marker_trait_attr/marker-trait-with-associated-items.rs @@ -0,0 +1,40 @@ +#![feature(marker_trait_attr)] +#![feature(associated_type_defaults)] + +#[marker] +trait MarkerConst { + const N: usize; + //~^ ERROR marker traits cannot have associated items +} + +#[marker] +trait MarkerType { + type Output; + //~^ ERROR marker traits cannot have associated items +} + +#[marker] +trait MarkerFn { + fn foo(); + //~^ ERROR marker traits cannot have associated items +} + +#[marker] +trait MarkerConstWithDefault { + const N: usize = 43; + //~^ ERROR marker traits cannot have associated items +} + +#[marker] +trait MarkerTypeWithDefault { + type Output = (); + //~^ ERROR marker traits cannot have associated items +} + +#[marker] +trait MarkerFnWithDefault { + fn foo() {} + //~^ ERROR marker traits cannot have associated items +} + +fn main() {} diff --git a/tests/ui/marker_trait_attr/marker-trait-with-associated-items.stderr b/tests/ui/marker_trait_attr/marker-trait-with-associated-items.stderr new file mode 100644 index 000000000..ac218e30b --- /dev/null +++ b/tests/ui/marker_trait_attr/marker-trait-with-associated-items.stderr @@ -0,0 +1,39 @@ +error[E0714]: marker traits cannot have associated items + --> $DIR/marker-trait-with-associated-items.rs:6:5 + | +LL | const N: usize; + | ^^^^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/marker-trait-with-associated-items.rs:12:5 + | +LL | type Output; + | ^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/marker-trait-with-associated-items.rs:18:5 + | +LL | fn foo(); + | ^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/marker-trait-with-associated-items.rs:24:5 + | +LL | const N: usize = 43; + | ^^^^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/marker-trait-with-associated-items.rs:30:5 + | +LL | type Output = (); + | ^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/marker-trait-with-associated-items.rs:36:5 + | +LL | fn foo() {} + | ^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0714`. diff --git a/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs new file mode 100644 index 000000000..1e413120a --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(marker_trait_attr)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +#[marker] +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for Vec {} + +fn foo(t: T) -> T { + t +} + +fn main() { + assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); + assert_eq!(vec![1], foo(vec![1])); +} diff --git a/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr new file mode 100644 index 000000000..649e58915 --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs b/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs new file mode 100644 index 000000000..62aa22d41 --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs @@ -0,0 +1,10 @@ +// check-pass +#![feature(marker_trait_attr)] + +#[marker] +trait Marker {} + +impl Marker for &'static () {} +impl Marker for &'static () {} + +fn main() {} diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs new file mode 100644 index 000000000..eabce1aef --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs @@ -0,0 +1,9 @@ +#![feature(marker_trait_attr)] + +#[marker] +trait Marker {} + +impl Marker for &'_ () {} //~ ERROR type annotations needed +impl Marker for &'_ () {} //~ ERROR type annotations needed + +fn main() {} diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr new file mode 100644 index 000000000..3cd59d692 --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr @@ -0,0 +1,31 @@ +error[E0283]: type annotations needed: cannot satisfy `&(): Marker` + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:17 + | +LL | impl Marker for &'_ () {} + | ^^^^^^ + | +note: multiple `impl`s satisfying `&(): Marker` found + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 + | +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed: cannot satisfy `&(): Marker` + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:17 + | +LL | impl Marker for &'_ () {} + | ^^^^^^ + | +note: multiple `impl`s satisfying `&(): Marker` found + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 + | +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Marker for &'_ () {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait.rs b/tests/ui/marker_trait_attr/overlap-marker-trait.rs new file mode 100644 index 000000000..67e551797 --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-marker-trait.rs @@ -0,0 +1,29 @@ +// Test for RFC 1268: we allow overlapping impls of marker traits, +// that is, traits with #[marker]. In this case, a type `T` is +// `MyMarker` if it is either `Debug` or `Display`. This test just +// checks that we don't consider **all** types to be `MyMarker`. + +#![feature(marker_trait_attr)] + +use std::fmt::{Debug, Display}; + +#[marker] +trait Marker {} + +impl Marker for T {} +impl Marker for T {} + +fn is_marker() { } + +struct NotDebugOrDisplay; + +fn main() { + // Debug && Display: + is_marker::(); + + // Debug && !Display: + is_marker::>(); + + // !Debug && !Display + is_marker::(); //~ ERROR +} diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait.stderr new file mode 100644 index 000000000..133bc0484 --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-marker-trait.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied + --> $DIR/overlap-marker-trait.rs:28:17 + | +LL | is_marker::(); + | ^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay` + | +note: required by a bound in `is_marker` + --> $DIR/overlap-marker-trait.rs:16:17 + | +LL | fn is_marker() { } + | ^^^^^^ required by this bound in `is_marker` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs b/tests/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs new file mode 100644 index 000000000..f7654458f --- /dev/null +++ b/tests/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs @@ -0,0 +1,27 @@ +// run-pass +// Tests for RFC 1268: we allow overlapping impls of marker traits, +// that is, traits with #[marker]. In this case, a type `T` is +// `MyMarker` if it is either `Debug` or `Display`. + +#![feature(marker_trait_attr)] + +use std::fmt::{Debug, Display}; + +#[marker] +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for T {} + +fn foo(t: T) -> T { + t +} + +fn main() { + // Debug && Display: + assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); + + // Debug && !Display: + assert_eq!(vec![1], foo(vec![1])); +} diff --git a/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs b/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs new file mode 100644 index 000000000..a8f3db5f5 --- /dev/null +++ b/tests/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs @@ -0,0 +1,9 @@ +// check-pass +#![feature(marker_trait_attr)] + +#[marker] +pub trait F {} +impl F for T where T: Copy {} +impl F for T where T: 'static {} + +fn main() {} diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs new file mode 100644 index 000000000..5376fc89d --- /dev/null +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs @@ -0,0 +1,23 @@ +#![feature(marker_trait_attr)] + +#[marker] +trait Marker { + const N: usize = 0; + fn do_something() {} +} + +struct OverrideConst; +impl Marker for OverrideConst { +//~^ ERROR impls for marker traits cannot contain items + const N: usize = 1; +} + +struct OverrideFn; +impl Marker for OverrideFn { +//~^ ERROR impls for marker traits cannot contain items + fn do_something() { + println!("Hello world!"); + } +} + +fn main() {} diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr new file mode 100644 index 000000000..1d30c6d56 --- /dev/null +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr @@ -0,0 +1,15 @@ +error[E0715]: impls for marker traits cannot contain items + --> $DIR/override-item-on-marker-trait.rs:10:1 + | +LL | impl Marker for OverrideConst { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0715]: impls for marker traits cannot contain items + --> $DIR/override-item-on-marker-trait.rs:16:1 + | +LL | impl Marker for OverrideFn { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0715`. diff --git a/tests/ui/marker_trait_attr/region-overlap.rs b/tests/ui/marker_trait_attr/region-overlap.rs new file mode 100644 index 000000000..b3c667103 --- /dev/null +++ b/tests/ui/marker_trait_attr/region-overlap.rs @@ -0,0 +1,8 @@ +#![feature(marker_trait_attr)] + +#[marker] +trait A {} +impl<'a> A for (&'static (), &'a ()) {} //~ ERROR type annotations needed +impl<'a> A for (&'a (), &'static ()) {} //~ ERROR type annotations needed + +fn main() {} diff --git a/tests/ui/marker_trait_attr/region-overlap.stderr b/tests/ui/marker_trait_attr/region-overlap.stderr new file mode 100644 index 000000000..c6497b466 --- /dev/null +++ b/tests/ui/marker_trait_attr/region-overlap.stderr @@ -0,0 +1,31 @@ +error[E0283]: type annotations needed: cannot satisfy `(&'static (), &'a ()): A` + --> $DIR/region-overlap.rs:5:16 + | +LL | impl<'a> A for (&'static (), &'a ()) {} + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found + --> $DIR/region-overlap.rs:5:1 + | +LL | impl<'a> A for (&'static (), &'a ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> A for (&'a (), &'static ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0283]: type annotations needed: cannot satisfy `(&'a (), &'static ()): A` + --> $DIR/region-overlap.rs:6:16 + | +LL | impl<'a> A for (&'a (), &'static ()) {} + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found + --> $DIR/region-overlap.rs:5:1 + | +LL | impl<'a> A for (&'static (), &'a ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> A for (&'a (), &'static ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/marker_trait_attr/unsound-overlap.rs b/tests/ui/marker_trait_attr/unsound-overlap.rs new file mode 100644 index 000000000..2e5101b82 --- /dev/null +++ b/tests/ui/marker_trait_attr/unsound-overlap.rs @@ -0,0 +1,25 @@ +#![feature(marker_trait_attr)] + +#[marker] +trait A {} + +trait B {} + +impl B for T {} +impl A for T {} +impl A for &str {} +impl A for (T,) {} +trait TraitWithAssoc { + type Assoc; +} + +impl TraitWithAssoc for T { + type Assoc = T; +} + +impl TraitWithAssoc for ((&str,),) { + //~^ ERROR conflicting implementations + type Assoc = ((&'static str,),); +} + +fn main() {} diff --git a/tests/ui/marker_trait_attr/unsound-overlap.stderr b/tests/ui/marker_trait_attr/unsound-overlap.stderr new file mode 100644 index 000000000..5ebac8270 --- /dev/null +++ b/tests/ui/marker_trait_attr/unsound-overlap.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `TraitWithAssoc` for type `((&str,),)` + --> $DIR/unsound-overlap.rs:20:1 + | +LL | impl TraitWithAssoc for T { + | ------------------------------- first implementation here +... +LL | impl TraitWithAssoc for ((&str,),) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `((&str,),)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/match/auxiliary/match_non_exhaustive_lib.rs b/tests/ui/match/auxiliary/match_non_exhaustive_lib.rs new file mode 100644 index 000000000..3be72551e --- /dev/null +++ b/tests/ui/match/auxiliary/match_non_exhaustive_lib.rs @@ -0,0 +1,5 @@ +#[non_exhaustive] +pub enum E1 {} + +#[non_exhaustive] +pub enum E2 { A, B } diff --git a/tests/ui/match/const_non_normal_zst_ref_pattern.rs b/tests/ui/match/const_non_normal_zst_ref_pattern.rs new file mode 100644 index 000000000..a114fafb6 --- /dev/null +++ b/tests/ui/match/const_non_normal_zst_ref_pattern.rs @@ -0,0 +1,9 @@ +// check-pass + +const FOO: isize = 10; +const ZST: &() = unsafe { std::mem::transmute(FOO) }; +fn main() { + match &() { + ZST => 9, + }; +} diff --git a/tests/ui/match/expr-match-panic-fn.rs b/tests/ui/match/expr-match-panic-fn.rs new file mode 100644 index 000000000..ea471717e --- /dev/null +++ b/tests/ui/match/expr-match-panic-fn.rs @@ -0,0 +1,19 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn f() -> ! { + panic!() +} + +fn g() -> isize { + let x = match true { + true => f(), + false => 10, + }; + return x; +} + +fn main() { + g(); +} diff --git a/tests/ui/match/expr-match-panic.rs b/tests/ui/match/expr-match-panic.rs new file mode 100644 index 000000000..53f8a8bd3 --- /dev/null +++ b/tests/ui/match/expr-match-panic.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn main() { + let _x = match true { + false => 0, + true => panic!(), + }; +} diff --git a/tests/ui/match/expr_before_ident_pat.rs b/tests/ui/match/expr_before_ident_pat.rs new file mode 100644 index 000000000..27ef3d05a --- /dev/null +++ b/tests/ui/match/expr_before_ident_pat.rs @@ -0,0 +1,13 @@ +macro_rules! funny { + ($a:expr, $b:ident) => { + match [1, 2] { + [$a, $b] => {} + } + }; +} + +fn main() { + funny!(a, a); + //~^ ERROR cannot find value `a` in this scope + //~| ERROR arbitrary expressions aren't allowed in patterns +} diff --git a/tests/ui/match/expr_before_ident_pat.stderr b/tests/ui/match/expr_before_ident_pat.stderr new file mode 100644 index 000000000..57a2d2b26 --- /dev/null +++ b/tests/ui/match/expr_before_ident_pat.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/expr_before_ident_pat.rs:10:12 + | +LL | funny!(a, a); + | ^ not found in this scope + +error: arbitrary expressions aren't allowed in patterns + --> $DIR/expr_before_ident_pat.rs:10:12 + | +LL | funny!(a, a); + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/match/guards.rs b/tests/ui/match/guards.rs new file mode 100644 index 000000000..10a4bb673 --- /dev/null +++ b/tests/ui/match/guards.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(non_shorthand_field_patterns)] + +#[derive(Copy, Clone)] +struct Pair { x: isize, y: isize } + +pub fn main() { + let a: isize = + match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } }; + assert_eq!(a, 2); + + let b: isize = + match (Pair {x: 10, y: 20}) { + x if x.x < 5 && x.y < 5 => { 1 } + Pair {x: x, y: y} if x == 10 && y == 20 => { 2 } + Pair {x: _x, y: _y} => { 3 } + }; + assert_eq!(b, 2); +} diff --git a/tests/ui/match/issue-11319.rs b/tests/ui/match/issue-11319.rs new file mode 100644 index 000000000..ab69ab250 --- /dev/null +++ b/tests/ui/match/issue-11319.rs @@ -0,0 +1,13 @@ +fn main() { + match Some(10) { + //~^ NOTE `match` arms have incompatible types + Some(5) => false, + //~^ NOTE this is found to be of type `bool` + Some(2) => true, + //~^ NOTE this is found to be of type `bool` + None => (), + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `bool`, found `()` + _ => true + } +} diff --git a/tests/ui/match/issue-11319.stderr b/tests/ui/match/issue-11319.stderr new file mode 100644 index 000000000..fc44205e8 --- /dev/null +++ b/tests/ui/match/issue-11319.stderr @@ -0,0 +1,21 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-11319.rs:8:20 + | +LL | / match Some(10) { +LL | | +LL | | Some(5) => false, + | | ----- this is found to be of type `bool` +LL | | +LL | | Some(2) => true, + | | ---- this is found to be of type `bool` +LL | | +LL | | None => (), + | | ^^ expected `bool`, found `()` +... | +LL | | _ => true +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/issue-11940.rs b/tests/ui/match/issue-11940.rs new file mode 100644 index 000000000..6815c87ed --- /dev/null +++ b/tests/ui/match/issue-11940.rs @@ -0,0 +1,11 @@ +// run-pass + +const TEST_STR: &'static str = "abcd"; + +fn main() { + let s = "abcd"; + match s { + TEST_STR => (), + _ => unreachable!() + } +} diff --git a/tests/ui/match/issue-12552.rs b/tests/ui/match/issue-12552.rs new file mode 100644 index 000000000..b7f71dd1c --- /dev/null +++ b/tests/ui/match/issue-12552.rs @@ -0,0 +1,11 @@ +// this code used to cause an ICE + +fn main() { + let t = Err(0); + match t { + Some(k) => match k { //~ ERROR mismatched types + a => println!("{}", a) + }, + None => () //~ ERROR mismatched types + } +} diff --git a/tests/ui/match/issue-12552.stderr b/tests/ui/match/issue-12552.stderr new file mode 100644 index 000000000..4b027eba2 --- /dev/null +++ b/tests/ui/match/issue-12552.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/issue-12552.rs:6:5 + | +LL | match t { + | - this expression has type `Result<_, {integer}>` +LL | Some(k) => match k { + | ^^^^^^^ expected enum `Result`, found enum `Option` + | + = note: expected enum `Result<_, {integer}>` + found enum `Option<_>` +help: try wrapping the pattern in `Ok` + | +LL | Ok(Some(k)) => match k { + | +++ + + +error[E0308]: mismatched types + --> $DIR/issue-12552.rs:9:5 + | +LL | match t { + | - this expression has type `Result<_, {integer}>` +... +LL | None => () + | ^^^^ expected enum `Result`, found enum `Option` + | + = note: expected enum `Result<_, {integer}>` + found enum `Option<_>` +help: try wrapping the pattern in `Ok` + | +LL | Ok(None) => () + | +++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/issue-18060.rs b/tests/ui/match/issue-18060.rs new file mode 100644 index 000000000..b5f3d0f74 --- /dev/null +++ b/tests/ui/match/issue-18060.rs @@ -0,0 +1,8 @@ +// run-pass +// Regression test for #18060: match arms were matching in the wrong order. + +fn main() { + assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 }); + assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 }); + assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 }); +} diff --git a/tests/ui/match/issue-26251.rs b/tests/ui/match/issue-26251.rs new file mode 100644 index 000000000..a3e26a412 --- /dev/null +++ b/tests/ui/match/issue-26251.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(overlapping_range_endpoints)] + +fn main() { + let x = 'a'; + + let y = match x { + 'a'..='b' if false => "one", + 'a' => "two", + 'a'..='b' => "three", + _ => panic!("what?"), + }; + + assert_eq!(y, "two"); +} diff --git a/tests/ui/match/issue-26996.rs b/tests/ui/match/issue-26996.rs new file mode 100644 index 000000000..84037b72a --- /dev/null +++ b/tests/ui/match/issue-26996.rs @@ -0,0 +1,24 @@ +// run-pass + +// This test is bogus (i.e., should be check-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it +// +// ignore-test + +// This test is checking that the write to `c.0` (which has been moved out of) +// won't overwrite the state in `c2`. +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + +fn main() { + let mut c = (1, "".to_owned()); + match c { + c2 => { + c.0 = 2; + assert_eq!(c2.0, 1); + } + } +} diff --git a/tests/ui/match/issue-27021.rs b/tests/ui/match/issue-27021.rs new file mode 100644 index 000000000..ef3b114a5 --- /dev/null +++ b/tests/ui/match/issue-27021.rs @@ -0,0 +1,28 @@ +// run-pass + +// This test is bogus (i.e., should be check-fail) during the period +// where #54986 is implemented and #54987 is *not* implemented. For +// now: just ignore it +// +// ignore-test + +// These are variants of issue-26996.rs. In all cases we are writing +// into a record field that has been moved out of, and ensuring that +// such a write won't overwrite the state of the thing it was moved +// into. +// +// That's a fine thing to test when this code is accepted by the +// compiler, and this code is being transcribed accordingly into +// the ui test issue-21232-partial-init-and-use.rs + +fn main() { + let mut c = (1, (1, "".to_owned())); + match c { + c2 => { (c.1).0 = 2; assert_eq!((c2.1).0, 1); } + } + + let mut c = (1, (1, (1, "".to_owned()))); + match c.1 { + c2 => { ((c.1).1).0 = 3; assert_eq!((c2.1).0, 1); } + } +} diff --git a/tests/ui/match/issue-33498.rs b/tests/ui/match/issue-33498.rs new file mode 100644 index 000000000..9c8a97e7e --- /dev/null +++ b/tests/ui/match/issue-33498.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_variables)] +pub fn main() { + let x = (0, 2); + + match x { + (0, ref y) => {} + (y, 0) => {} + _ => (), + } +} diff --git a/tests/ui/match/issue-41255.rs b/tests/ui/match/issue-41255.rs new file mode 100644 index 000000000..d163801fd --- /dev/null +++ b/tests/ui/match/issue-41255.rs @@ -0,0 +1,50 @@ +// Matching against float literals should result in a linter error + +#![feature(exclusive_range_pattern)] +#![allow(unused)] +#![forbid(illegal_floating_point_literal_pattern)] + +fn main() { + let x = 42.0; + match x { + 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + //~| ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns + //~| ERROR floating-point types cannot be used in patterns + //~| WARNING hard error + //~| WARNING hard error + + ..71.0 => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + ..=72.0 => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + 71.0.. => {} + //~^ ERROR floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + _ => {}, + }; + let y = 5.0; + // Same for tuples + match (x, 5) { + (3.14, 1) => {}, //~ ERROR floating-point types cannot be used + //~| WARNING hard error + _ => {}, + } + // Or structs + struct Foo { x: f32 }; + match (Foo { x }) { + Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used + //~| WARNING hard error + _ => {}, + } +} diff --git a/tests/ui/match/issue-41255.stderr b/tests/ui/match/issue-41255.stderr new file mode 100644 index 000000000..9bc49654e --- /dev/null +++ b/tests/ui/match/issue-41255.stderr @@ -0,0 +1,115 @@ +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:10:9 + | +LL | 5.0 => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 +note: the lint level is defined here + --> $DIR/issue-41255.rs:5:11 + | +LL | #![forbid(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:12:9 + | +LL | 5.0f32 => {}, + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:14:10 + | +LL | -5.0 => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:16:9 + | +LL | 1.0 .. 33.0 => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:16:16 + | +LL | 1.0 .. 33.0 => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:20:9 + | +LL | 39.0 ..= 70.0 => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:20:18 + | +LL | 39.0 ..= 70.0 => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:25:11 + | +LL | ..71.0 => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:28:12 + | +LL | ..=72.0 => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:31:9 + | +LL | 71.0.. => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:39:10 + | +LL | (3.14, 1) => {}, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: floating-point types cannot be used in patterns + --> $DIR/issue-41255.rs:46:18 + | +LL | Foo { x: 2.0 } => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: aborting due to 12 previous errors + diff --git a/tests/ui/match/issue-42679.rs b/tests/ui/match/issue-42679.rs new file mode 100644 index 000000000..46a0bd35d --- /dev/null +++ b/tests/ui/match/issue-42679.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum Test { + Foo(usize), + Bar(isize), +} + +fn main() { + let a = Box::new(Test::Foo(10)); + let b = Box::new(Test::Bar(-20)); + match (a, b) { + (_, box Test::Foo(_)) => unreachable!(), + (box Test::Foo(x), b) => { + assert_eq!(x, 10); + assert_eq!(b, Box::new(Test::Bar(-20))); + }, + _ => unreachable!(), + } +} diff --git a/tests/ui/match/issue-46920-byte-array-patterns.rs b/tests/ui/match/issue-46920-byte-array-patterns.rs new file mode 100644 index 000000000..2a8b4bb49 --- /dev/null +++ b/tests/ui/match/issue-46920-byte-array-patterns.rs @@ -0,0 +1,28 @@ +// run-pass +const CURSOR_PARTITION_LABEL: &'static [u8] = b"partition"; +const CURSOR_EVENT_TYPE_LABEL: &'static [u8] = b"event_type"; +const BYTE_PATTERN: &'static [u8; 5] = b"hello"; + +fn match_slice(x: &[u8]) -> u32 { + match x { + CURSOR_PARTITION_LABEL => 0, + CURSOR_EVENT_TYPE_LABEL => 1, + _ => 2, + } +} + +fn match_array(x: &[u8; 5]) -> bool { + match x { + BYTE_PATTERN => true, + _ => false + } +} + +fn main() { + assert_eq!(match_slice(b"abcde"), 2); + assert_eq!(match_slice(b"event_type"), 1); + assert_eq!(match_slice(b"partition"), 0); + + assert_eq!(match_array(b"hello"), true); + assert_eq!(match_array(b"hella"), false); +} diff --git a/tests/ui/match/issue-5530.rs b/tests/ui/match/issue-5530.rs new file mode 100644 index 000000000..72731cbb1 --- /dev/null +++ b/tests/ui/match/issue-5530.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code)] + +enum Enum { + Foo { foo: usize }, + Bar { bar: usize } +} + +fn fun1(e1: &Enum, e2: &Enum) -> usize { + match (e1, e2) { + (&Enum::Foo { foo: _ }, &Enum::Foo { foo: _ }) => 0, + (&Enum::Foo { foo: _ }, &Enum::Bar { bar: _ }) => 1, + (&Enum::Bar { bar: _ }, &Enum::Bar { bar: _ }) => 2, + (&Enum::Bar { bar: _ }, &Enum::Foo { foo: _ }) => 3, + } +} + +fn fun2(e1: &Enum, e2: &Enum) -> usize { + match (e1, e2) { + (&Enum::Foo { foo: _ }, &Enum::Foo { foo: _ }) => 0, + (&Enum::Foo { foo: _ }, _ ) => 1, + (&Enum::Bar { bar: _ }, &Enum::Bar { bar: _ }) => 2, + (&Enum::Bar { bar: _ }, _ ) => 3, + } +} + +pub fn main() { + let foo = Enum::Foo { foo: 1 }; + let bar = Enum::Bar { bar: 1 }; + + assert_eq!(fun1(&foo, &foo), 0); + assert_eq!(fun1(&foo, &bar), 1); + assert_eq!(fun1(&bar, &bar), 2); + assert_eq!(fun1(&bar, &foo), 3); + + assert_eq!(fun2(&foo, &foo), 0); + assert_eq!(fun2(&foo, &bar), 1); // fun2 returns 0 + assert_eq!(fun2(&bar, &bar), 2); + assert_eq!(fun2(&bar, &foo), 3); // fun2 returns 2 +} diff --git a/tests/ui/match/issue-56685.rs b/tests/ui/match/issue-56685.rs new file mode 100644 index 000000000..f320c99ed --- /dev/null +++ b/tests/ui/match/issue-56685.rs @@ -0,0 +1,44 @@ +#![allow(dead_code)] +#![deny(unused_variables)] + +// This test aims to check that unused variable suggestions update bindings in all +// match arms. + +fn main() { + enum E { + A(i32,), + B(i32,), + } + + match E::A(1) { + E::A(x) | E::B(x) => {} + //~^ ERROR unused variable: `x` + } + + enum F { + A(i32, i32,), + B(i32, i32,), + C(i32, i32,), + } + + let _ = match F::A(1, 2) { + F::A(x, y) | F::B(x, y) => { y }, + //~^ ERROR unused variable: `x` + F::C(a, b) => { 3 } + //~^ ERROR unused variable: `a` + //~^^ ERROR unused variable: `b` + }; + + let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + //~^ ERROR unused variable: `x` + y + } else { + 3 + }; + + while let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + //~^ ERROR unused variable: `x` + let _ = y; + break; + } +} diff --git a/tests/ui/match/issue-56685.stderr b/tests/ui/match/issue-56685.stderr new file mode 100644 index 000000000..ccf357d4a --- /dev/null +++ b/tests/ui/match/issue-56685.stderr @@ -0,0 +1,63 @@ +error: unused variable: `x` + --> $DIR/issue-56685.rs:14:14 + | +LL | E::A(x) | E::B(x) => {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/issue-56685.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ +help: if this is intentional, prefix it with an underscore + | +LL | E::A(_x) | E::B(_x) => {} + | ~~ ~~ + +error: unused variable: `x` + --> $DIR/issue-56685.rs:25:14 + | +LL | F::A(x, y) | F::B(x, y) => { y }, + | ^ ^ + | +help: if this is intentional, prefix it with an underscore + | +LL | F::A(_x, y) | F::B(_x, y) => { y }, + | ~~ ~~ + +error: unused variable: `a` + --> $DIR/issue-56685.rs:27:14 + | +LL | F::C(a, b) => { 3 } + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/issue-56685.rs:27:17 + | +LL | F::C(a, b) => { 3 } + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `x` + --> $DIR/issue-56685.rs:32:25 + | +LL | let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + | ^ ^ + | +help: if this is intentional, prefix it with an underscore + | +LL | let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) { + | ~~ ~~ + +error: unused variable: `x` + --> $DIR/issue-56685.rs:39:20 + | +LL | while let F::A(x, y) | F::B(x, y) = F::A(1, 2) { + | ^ ^ + | +help: if this is intentional, prefix it with an underscore + | +LL | while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) { + | ~~ ~~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/match/issue-70972-dyn-trait.rs b/tests/ui/match/issue-70972-dyn-trait.rs new file mode 100644 index 000000000..97d161c59 --- /dev/null +++ b/tests/ui/match/issue-70972-dyn-trait.rs @@ -0,0 +1,10 @@ +const F: &'static dyn Send = &7u32; + +fn main() { + let a: &dyn Send = &7u32; + match a { + F => panic!(), + //~^ ERROR `&dyn Send` cannot be used in patterns + _ => {} + } +} diff --git a/tests/ui/match/issue-70972-dyn-trait.stderr b/tests/ui/match/issue-70972-dyn-trait.stderr new file mode 100644 index 000000000..7581070eb --- /dev/null +++ b/tests/ui/match/issue-70972-dyn-trait.stderr @@ -0,0 +1,8 @@ +error: `&dyn Send` cannot be used in patterns + --> $DIR/issue-70972-dyn-trait.rs:6:9 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/match/issue-72680.rs b/tests/ui/match/issue-72680.rs new file mode 100644 index 000000000..c13cace76 --- /dev/null +++ b/tests/ui/match/issue-72680.rs @@ -0,0 +1,63 @@ +// run-pass + +fn main() { + assert!(f("", 0)); + assert!(f("a", 1)); + assert!(f("b", 1)); + + assert!(!f("", 1)); + assert!(!f("a", 0)); + assert!(!f("b", 0)); + + assert!(!f("asdf", 32)); + + //// + + assert!(!g(true, true, true)); + assert!(!g(false, true, true)); + assert!(!g(true, false, true)); + assert!(!g(false, false, true)); + assert!(!g(true, true, false)); + + assert!(g(false, true, false)); + assert!(g(true, false, false)); + assert!(g(false, false, false)); + + //// + + assert!(!h(true, true, true)); + assert!(!h(false, true, true)); + assert!(!h(true, false, true)); + assert!(!h(false, false, true)); + assert!(!h(true, true, false)); + + assert!(h(false, true, false)); + assert!(h(true, false, false)); + assert!(h(false, false, false)); +} + +fn f(s: &str, num: usize) -> bool { + match (s, num) { + ("", 0) | ("a" | "b", 1) => true, + + _ => false, + } +} + +fn g(x: bool, y: bool, z: bool) -> bool { + match (x, y, x, z) { + (true | false, false, true, false) => true, + (false, true | false, true | false, false) => true, + (true | false, true | false, true | false, true) => false, + (true, true | false, true | false, false) => false, + } +} + +fn h(x: bool, y: bool, z: bool) -> bool { + match (x, (y, (x, (z,)))) { + (true | false, (false, (true, (false,)))) => true, + (false, (true | false, (true | false, (false,)))) => true, + (true | false, (true | false, (true | false, (true,)))) => false, + (true, (true | false, (true | false, (false,)))) => false, + } +} diff --git a/tests/ui/match/issue-72896.rs b/tests/ui/match/issue-72896.rs new file mode 100644 index 000000000..3a8b82037 --- /dev/null +++ b/tests/ui/match/issue-72896.rs @@ -0,0 +1,23 @@ +// run-pass +trait EnumSetType { + type Repr; +} + +enum Enum8 { } +impl EnumSetType for Enum8 { + type Repr = u8; +} + +#[derive(PartialEq, Eq)] +struct EnumSet { + __enumset_underlying: T::Repr, +} + +const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; + +fn main() { + match CONST_SET { + CONST_SET => { /* ok */ } + _ => panic!("match fell through?"), + } +} diff --git a/tests/ui/match/issue-74050-end-span.rs b/tests/ui/match/issue-74050-end-span.rs new file mode 100644 index 000000000..cc81214e2 --- /dev/null +++ b/tests/ui/match/issue-74050-end-span.rs @@ -0,0 +1,13 @@ +fn main() { + let mut args = std::env::args_os(); + let _arg = match args.next() { + Some(arg) => { + match arg.to_str() { + //~^ ERROR `arg` does not live long enough + Some(s) => s, + None => return, + } + } + None => return, + }; +} diff --git a/tests/ui/match/issue-74050-end-span.stderr b/tests/ui/match/issue-74050-end-span.stderr new file mode 100644 index 000000000..59c091e44 --- /dev/null +++ b/tests/ui/match/issue-74050-end-span.stderr @@ -0,0 +1,15 @@ +error[E0597]: `arg` does not live long enough + --> $DIR/issue-74050-end-span.rs:5:19 + | +LL | let _arg = match args.next() { + | ---- borrow later stored here +LL | Some(arg) => { +LL | match arg.to_str() { + | ^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - `arg` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/match/issue-82392.rs b/tests/ui/match/issue-82392.rs new file mode 100644 index 000000000..d26d88304 --- /dev/null +++ b/tests/ui/match/issue-82392.rs @@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +pub fn main() { + if true { + } else if let Some(a) = Some(3) { + } +} diff --git a/tests/ui/match/issue-82392.stdout b/tests/ui/match/issue-82392.stdout new file mode 100644 index 000000000..ffe730743 --- /dev/null +++ b/tests/ui/match/issue-82392.stdout @@ -0,0 +1,16 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass + +fn main() ({ + (if (true as bool) + ({ } as + ()) else if (let Some(a) = + ((Some as + fn(i32) -> Option {Option::::Some})((3 as i32)) as + Option) as bool) ({ } as ()) as ()) + } as ()) diff --git a/tests/ui/match/issue-82866.rs b/tests/ui/match/issue-82866.rs new file mode 100644 index 000000000..95cd62261 --- /dev/null +++ b/tests/ui/match/issue-82866.rs @@ -0,0 +1,7 @@ +fn main() { + match x { + //~^ ERROR cannot find value `x` in this scope + Some::(v) => (), + //~^ ERROR cannot find type `v` in this scope + } +} diff --git a/tests/ui/match/issue-82866.stderr b/tests/ui/match/issue-82866.stderr new file mode 100644 index 000000000..f9e3360a5 --- /dev/null +++ b/tests/ui/match/issue-82866.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-82866.rs:2:11 + | +LL | match x { + | ^ not found in this scope + +error[E0412]: cannot find type `v` in this scope + --> $DIR/issue-82866.rs:4:16 + | +LL | Some::(v) => (), + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/match/issue-84434.rs b/tests/ui/match/issue-84434.rs new file mode 100644 index 000000000..423481fd5 --- /dev/null +++ b/tests/ui/match/issue-84434.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/84434 +// check-pass + +use std::path::Path; +struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, +}; + +fn main() {} diff --git a/tests/ui/match/issue-91058.rs b/tests/ui/match/issue-91058.rs new file mode 100644 index 000000000..4845937d5 --- /dev/null +++ b/tests/ui/match/issue-91058.rs @@ -0,0 +1,11 @@ +struct S(()); + +fn main() { + let array = [S(())]; + + match array { + [()] => {} + //~^ ERROR mismatched types [E0308] + _ => {} + } +} diff --git a/tests/ui/match/issue-91058.stderr b/tests/ui/match/issue-91058.stderr new file mode 100644 index 000000000..ec1d7e21f --- /dev/null +++ b/tests/ui/match/issue-91058.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-91058.rs:7:10 + | +LL | match array { + | ----- this expression has type `[S; 1]` +LL | [()] => {} + | ^^ expected struct `S`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/issue-92100.rs b/tests/ui/match/issue-92100.rs new file mode 100644 index 000000000..baac570dd --- /dev/null +++ b/tests/ui/match/issue-92100.rs @@ -0,0 +1,7 @@ +#![feature(half_open_range_patterns_in_slices)] + +fn main() { + match [1, 2] { + [a.., a] => {} //~ ERROR cannot find value `a` in this scope + } +} diff --git a/tests/ui/match/issue-92100.stderr b/tests/ui/match/issue-92100.stderr new file mode 100644 index 000000000..0f694c587 --- /dev/null +++ b/tests/ui/match/issue-92100.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-92100.rs:5:10 + | +LL | [a.., a] => {} + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/match/match-arm-resolving-to-never.rs b/tests/ui/match/match-arm-resolving-to-never.rs new file mode 100644 index 000000000..6ef249c05 --- /dev/null +++ b/tests/ui/match/match-arm-resolving-to-never.rs @@ -0,0 +1,19 @@ +enum E { + A, + B, + C, + D, + E, + F, +} + +fn main() { + match E::F { + E::A => 1, + E::B => 2, + E::C => 3, + E::D => 4, + E::E => unimplemented!(""), + E::F => "", //~ ERROR `match` arms have incompatible types + }; +} diff --git a/tests/ui/match/match-arm-resolving-to-never.stderr b/tests/ui/match/match-arm-resolving-to-never.stderr new file mode 100644 index 000000000..686fbd0ba --- /dev/null +++ b/tests/ui/match/match-arm-resolving-to-never.stderr @@ -0,0 +1,18 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-arm-resolving-to-never.rs:17:17 + | +LL | / match E::F { +LL | | E::A => 1, +LL | | E::B => 2, +LL | | E::C => 3, +LL | | E::D => 4, +LL | | E::E => unimplemented!(""), + | | ------------------ this and all prior arms are found to be of type `{integer}` +LL | | E::F => "", + | | ^^ expected integer, found `&str` +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-bot-panic.rs b/tests/ui/match/match-bot-panic.rs new file mode 100644 index 000000000..e4a6f6d6f --- /dev/null +++ b/tests/ui/match/match-bot-panic.rs @@ -0,0 +1,16 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn foo(s: String) {} + +fn main() { + let i = match Some::(3) { + None:: => panic!(), + Some::(_) => panic!(), + }; + foo(i); +} diff --git a/tests/ui/match/match-disc-bot.rs b/tests/ui/match/match-disc-bot.rs new file mode 100644 index 000000000..18cfd5e23 --- /dev/null +++ b/tests/ui/match/match-disc-bot.rs @@ -0,0 +1,16 @@ +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn f() -> ! { + panic!("quux") +} +fn g() -> isize { + match f() { + true => 1, + false => 0, + } +} +fn main() { + g(); +} diff --git a/tests/ui/match/match-fn-call.rs b/tests/ui/match/match-fn-call.rs new file mode 100644 index 000000000..99092602c --- /dev/null +++ b/tests/ui/match/match-fn-call.rs @@ -0,0 +1,12 @@ +use std::path::Path; + +fn main() { + let path = Path::new("foo"); + match path { + Path::new("foo") => println!("foo"), + //~^ ERROR expected tuple struct or tuple variant + Path::new("bar") => println!("bar"), + //~^ ERROR expected tuple struct or tuple variant + _ => (), + } +} diff --git a/tests/ui/match/match-fn-call.stderr b/tests/ui/match/match-fn-call.stderr new file mode 100644 index 000000000..297aa4cd9 --- /dev/null +++ b/tests/ui/match/match-fn-call.stderr @@ -0,0 +1,19 @@ +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/match-fn-call.rs:6:9 + | +LL | Path::new("foo") => println!("foo"), + | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/match-fn-call.rs:8:9 + | +LL | Path::new("bar") => println!("bar"), + | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/tests/ui/match/match-ill-type2.rs b/tests/ui/match/match-ill-type2.rs new file mode 100644 index 000000000..6612f6e39 --- /dev/null +++ b/tests/ui/match/match-ill-type2.rs @@ -0,0 +1,7 @@ +fn main() { + match 1i32 { + 1i32 => 1, + 2u32 => 1, //~ ERROR mismatched types + _ => 2, + }; +} diff --git a/tests/ui/match/match-ill-type2.stderr b/tests/ui/match/match-ill-type2.stderr new file mode 100644 index 000000000..5078f03d6 --- /dev/null +++ b/tests/ui/match/match-ill-type2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/match-ill-type2.rs:4:9 + | +LL | match 1i32 { + | ---- this expression has type `i32` +LL | 1i32 => 1, +LL | 2u32 => 1, + | ^^^^ expected `i32`, found `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-incompat-type-semi.rs b/tests/ui/match/match-incompat-type-semi.rs new file mode 100644 index 000000000..37f6beabd --- /dev/null +++ b/tests/ui/match/match-incompat-type-semi.rs @@ -0,0 +1,52 @@ +// Diagnostic enhancement explained in issue #75418. +// Point at the last statement in the block if there's no tail expression, +// and suggest removing the semicolon if appropriate. + +fn main() { + let _ = match Some(42) { + Some(x) => { + x + }, + None => { + 0; + //~^ ERROR incompatible types + //~| HELP consider removing this semicolon + }, + }; + + let _ = if let Some(x) = Some(42) { + x + } else { + 0; + //~^ ERROR incompatible types + //~| HELP consider removing this semicolon + }; + + let _ = match Some(42) { + Some(x) => { + x + }, + None => { + (); + //~^ ERROR incompatible types + }, + }; + + let _ = match Some(42) { + Some(x) => { + x + }, + None => { //~ ERROR incompatible types + }, + }; + + let _ = match Some(42) { + Some(x) => "rust-lang.org" + .chars() + .skip(1) + .chain(Some(x as u8 as char)) + .take(10) + .any(char::is_alphanumeric), + None => {} //~ ERROR incompatible types + }; +} diff --git a/tests/ui/match/match-incompat-type-semi.stderr b/tests/ui/match/match-incompat-type-semi.stderr new file mode 100644 index 000000000..008b1c1e9 --- /dev/null +++ b/tests/ui/match/match-incompat-type-semi.stderr @@ -0,0 +1,88 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:11:13 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `{integer}` +LL | | }, +LL | | None => { +LL | | 0; + | | ^- + | | || + | | |help: consider removing this semicolon + | | expected integer, found `()` +... | +LL | | }, +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/match-incompat-type-semi.rs:20:9 + | +LL | let _ = if let Some(x) = Some(42) { + | _____________- +LL | | x + | | - expected because of this +LL | | } else { +LL | | 0; + | | ^- + | | || + | | |help: consider removing this semicolon + | | expected integer, found `()` +LL | | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:30:13 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `{integer}` +LL | | }, +LL | | None => { +LL | | (); + | | ^^^ expected integer, found `()` +LL | | +LL | | }, +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:39:17 + | +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => { +LL | x + | - this is found to be of type `{integer}` +LL | }, +LL | None => { + | _________________^ +LL | | }, + | |_________^ expected integer, found `()` + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:50:17 + | +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => "rust-lang.org" + | ____________________- +LL | | .chars() +LL | | .skip(1) +LL | | .chain(Some(x as u8 as char)) +LL | | .take(10) +LL | | .any(char::is_alphanumeric), + | |_______________________________________- this is found to be of type `bool` +LL | None => {} + | ^^ expected `bool`, found `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-join.rs b/tests/ui/match/match-join.rs new file mode 100644 index 000000000..b0f2593c8 --- /dev/null +++ b/tests/ui/match/match-join.rs @@ -0,0 +1,11 @@ +// a good test that we merge paths correctly in the presence of a +// variable that's used before it's declared + +fn my_panic() -> ! { panic!(); } + +fn main() { + match true { false => { my_panic(); } true => { } } + + println!("{}", x); //~ ERROR cannot find value `x` in this scope + let x: isize; +} diff --git a/tests/ui/match/match-join.stderr b/tests/ui/match/match-join.stderr new file mode 100644 index 000000000..27a82c124 --- /dev/null +++ b/tests/ui/match/match-join.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/match-join.rs:9:20 + | +LL | println!("{}", x); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/match/match-no-arms-unreachable-after.rs b/tests/ui/match/match-no-arms-unreachable-after.rs new file mode 100644 index 000000000..8f83fd1a3 --- /dev/null +++ b/tests/ui/match/match-no-arms-unreachable-after.rs @@ -0,0 +1,12 @@ +#![allow(warnings)] +#![deny(unreachable_code)] + +enum Void { } + +fn foo(v: Void) { + match v { } + let x = 2; //~ ERROR unreachable +} + +fn main() { +} diff --git a/tests/ui/match/match-no-arms-unreachable-after.stderr b/tests/ui/match/match-no-arms-unreachable-after.stderr new file mode 100644 index 000000000..a0a369726 --- /dev/null +++ b/tests/ui/match/match-no-arms-unreachable-after.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/match-no-arms-unreachable-after.rs:8:5 + | +LL | match v { } + | ----------- any code following this expression is unreachable +LL | let x = 2; + | ^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/match-no-arms-unreachable-after.rs:2:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/match/match-on-negative-integer-ranges.rs b/tests/ui/match/match-on-negative-integer-ranges.rs new file mode 100644 index 000000000..53e9ea9a5 --- /dev/null +++ b/tests/ui/match/match-on-negative-integer-ranges.rs @@ -0,0 +1,7 @@ +// run-pass + +fn main() { + assert_eq!(false, match -50_i8 { -128i8..=-101i8 => true, _ => false, }); + + assert_eq!(false, if let -128i8..=-101i8 = -50_i8 { true } else { false }); +} diff --git a/tests/ui/match/match-pattern-field-mismatch-2.rs b/tests/ui/match/match-pattern-field-mismatch-2.rs new file mode 100644 index 000000000..fa03cdac2 --- /dev/null +++ b/tests/ui/match/match-pattern-field-mismatch-2.rs @@ -0,0 +1,16 @@ +fn main() { + enum Color { + Rgb(usize, usize, usize), + Cmyk(usize, usize, usize, usize), + NoColor, + } + + fn foo(c: Color) { + match c { + Color::Rgb(_, _, _) => { } + Color::Cmyk(_, _, _, _) => { } + Color::NoColor(_) => { } + //~^ ERROR expected tuple struct or tuple variant, found unit variant `Color::NoColor` + } + } +} diff --git a/tests/ui/match/match-pattern-field-mismatch-2.stderr b/tests/ui/match/match-pattern-field-mismatch-2.stderr new file mode 100644 index 000000000..ba32d0e99 --- /dev/null +++ b/tests/ui/match/match-pattern-field-mismatch-2.stderr @@ -0,0 +1,12 @@ +error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor` + --> $DIR/match-pattern-field-mismatch-2.rs:12:11 + | +LL | NoColor, + | ------- `Color::NoColor` defined here +... +LL | Color::NoColor(_) => { } + | ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/match/match-pattern-field-mismatch.rs b/tests/ui/match/match-pattern-field-mismatch.rs new file mode 100644 index 000000000..a4fa97fef --- /dev/null +++ b/tests/ui/match/match-pattern-field-mismatch.rs @@ -0,0 +1,16 @@ +fn main() { + enum Color { + Rgb(usize, usize, usize), + Cmyk(usize, usize, usize, usize), + NoColor, + } + + fn foo(c: Color) { + match c { + Color::Rgb(_, _) => { } + //~^ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 + Color::Cmyk(_, _, _, _) => { } + Color::NoColor => { } + } + } +} diff --git a/tests/ui/match/match-pattern-field-mismatch.stderr b/tests/ui/match/match-pattern-field-mismatch.stderr new file mode 100644 index 000000000..c994ee4f6 --- /dev/null +++ b/tests/ui/match/match-pattern-field-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields + --> $DIR/match-pattern-field-mismatch.rs:10:22 + | +LL | Rgb(usize, usize, usize), + | ----- ----- ----- tuple variant has 3 fields +... +LL | Color::Rgb(_, _) => { } + | ^ ^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Color::Rgb(_, _, _) => { } + | +++ +help: use `..` to ignore all fields + | +LL | Color::Rgb(..) => { } + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/match/match-range-fail-2.rs b/tests/ui/match/match-range-fail-2.rs new file mode 100644 index 000000000..792664e1d --- /dev/null +++ b/tests/ui/match/match-range-fail-2.rs @@ -0,0 +1,24 @@ +#![feature(exclusive_range_pattern)] + +fn main() { + match 5 { + 6 ..= 1 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper + + match 5 { + 0 .. 0 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + + match 5u64 { + 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper +} diff --git a/tests/ui/match/match-range-fail-2.stderr b/tests/ui/match/match-range-fail-2.stderr new file mode 100644 index 000000000..7a0852d7e --- /dev/null +++ b/tests/ui/match/match-range-fail-2.stderr @@ -0,0 +1,40 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:5:9 + | +LL | 6 ..= 1 => { } + | ^ lower bound larger than upper bound + +error[E0579]: lower range bound must be less than upper + --> $DIR/match-range-fail-2.rs:12:9 + | +LL | 0 .. 0 => { } + | ^ + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:19:9 + | +LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:5:9 + | +LL | 6 ..= 1 => { } + | ^ lower bound larger than upper bound + +error[E0579]: lower range bound must be less than upper + --> $DIR/match-range-fail-2.rs:12:9 + | +LL | 0 .. 0 => { } + | ^ + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:19:9 + | +LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0030, E0579. +For more information about an error, try `rustc --explain E0030`. diff --git a/tests/ui/match/match-range-fail.rs b/tests/ui/match/match-range-fail.rs new file mode 100644 index 000000000..e53c8463e --- /dev/null +++ b/tests/ui/match/match-range-fail.rs @@ -0,0 +1,22 @@ +fn main() { + match "wow" { + "bar" ..= "foo" => { } + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match "wow" { + 10 ..= "what" => () + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match "wow" { + true ..= "what" => {} + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match 5 { + 'c' ..= 100 => { } + _ => { } + }; + //~^^^ ERROR mismatched types +} diff --git a/tests/ui/match/match-range-fail.stderr b/tests/ui/match/match-range-fail.stderr new file mode 100644 index 000000000..65db92df1 --- /dev/null +++ b/tests/ui/match/match-range-fail.stderr @@ -0,0 +1,40 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:3:9 + | +LL | "bar" ..= "foo" => { } + | -----^^^^^----- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:8:16 + | +LL | 10 ..= "what" => () + | -- ^^^^^^ this is of type `&'static str` but it should be `char` or numeric + | | + | this is of type `{integer}` + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:13:9 + | +LL | true ..= "what" => {} + | ----^^^^^------ + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/match-range-fail.rs:18:9 + | +LL | match 5 { + | - this expression has type `{integer}` +LL | 'c' ..= 100 => { } + | ^^^ --- this is of type `{integer}` + | | + | expected integer, found `char` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0029, E0308. +For more information about an error, try `rustc --explain E0029`. diff --git a/tests/ui/match/match-ref-mut-invariance.rs b/tests/ui/match/match-ref-mut-invariance.rs new file mode 100644 index 000000000..4250696c6 --- /dev/null +++ b/tests/ui/match/match-ref-mut-invariance.rs @@ -0,0 +1,15 @@ +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `match`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + match self.0 { ref mut x => x } + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/match/match-ref-mut-invariance.stderr b/tests/ui/match/match-ref-mut-invariance.stderr new file mode 100644 index 000000000..3b7e53cd5 --- /dev/null +++ b/tests/ui/match/match-ref-mut-invariance.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/match-ref-mut-invariance.rs:10:9 + | +LL | impl<'b> S<'b> { + | -- lifetime `'b` defined here +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | -- lifetime `'a` defined here +LL | match self.0 { ref mut x => x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/match/match-ref-mut-let-invariance.rs b/tests/ui/match/match-ref-mut-let-invariance.rs new file mode 100644 index 000000000..a33be09ac --- /dev/null +++ b/tests/ui/match/match-ref-mut-let-invariance.rs @@ -0,0 +1,16 @@ +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `let`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + let ref mut x = self.0; + x + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/match/match-ref-mut-let-invariance.stderr b/tests/ui/match/match-ref-mut-let-invariance.stderr new file mode 100644 index 000000000..f4d1cea67 --- /dev/null +++ b/tests/ui/match/match-ref-mut-let-invariance.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/match-ref-mut-let-invariance.rs:11:9 + | +LL | impl<'b> S<'b> { + | -- lifetime `'b` defined here +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | -- lifetime `'a` defined here +LL | let ref mut x = self.0; +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/match/match-ref-mut-stability.rs b/tests/ui/match/match-ref-mut-stability.rs new file mode 100644 index 000000000..52120360b --- /dev/null +++ b/tests/ui/match/match-ref-mut-stability.rs @@ -0,0 +1,37 @@ +// Check that `ref mut` variables don't change address between the match guard +// and the arm expression. + +// run-pass + +// Test that z always point to the same temporary. +fn referent_stability() { + let p; + match 0 { + ref mut z if { p = z as *const _; true } => assert_eq!(p, z as *const _), + _ => unreachable!(), + }; +} + +// Test that z is always effectively the same variable. +fn variable_stability() { + let p; + match 0 { + ref mut z if { p = &z as *const _; true } => assert_eq!(p, &z as *const _), + _ => unreachable!(), + }; +} + +// Test that a borrow of *z can cross from the guard to the arm. +fn persist_borrow() { + let r; + match 0 { + ref mut z if { r = z as &_; true } => assert_eq!(*r, 0), + _ => unreachable!(), + } +} + +fn main() { + referent_stability(); + variable_stability(); + persist_borrow(); +} diff --git a/tests/ui/match/match-struct.rs b/tests/ui/match/match-struct.rs new file mode 100644 index 000000000..7a54c54b9 --- /dev/null +++ b/tests/ui/match/match-struct.rs @@ -0,0 +1,11 @@ +struct S { a: isize } +enum E { C(isize) } + +fn main() { + match (S { a: 1 }) { + E::C(_) => (), + //~^ ERROR mismatched types + //~| expected struct `S`, found enum `E` + _ => () + } +} diff --git a/tests/ui/match/match-struct.stderr b/tests/ui/match/match-struct.stderr new file mode 100644 index 000000000..a475bd5e5 --- /dev/null +++ b/tests/ui/match/match-struct.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/match-struct.rs:6:9 + | +LL | match (S { a: 1 }) { + | ------------ this expression has type `S` +LL | E::C(_) => (), + | ^^^^^^^ expected struct `S`, found enum `E` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-tag-nullary.rs b/tests/ui/match/match-tag-nullary.rs new file mode 100644 index 000000000..bb2f59969 --- /dev/null +++ b/tests/ui/match/match-tag-nullary.rs @@ -0,0 +1,4 @@ +enum A { A } +enum B { B } + +fn main() { let x: A = A::A; match x { B::B => { } } } //~ ERROR mismatched types diff --git a/tests/ui/match/match-tag-nullary.stderr b/tests/ui/match/match-tag-nullary.stderr new file mode 100644 index 000000000..a6add31d1 --- /dev/null +++ b/tests/ui/match/match-tag-nullary.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/match-tag-nullary.rs:4:40 + | +LL | enum B { B } + | - unit variant defined here +LL | +LL | fn main() { let x: A = A::A; match x { B::B => { } } } + | - ^^^^ expected enum `A`, found enum `B` + | | + | this expression has type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-tag-unary.rs b/tests/ui/match/match-tag-unary.rs new file mode 100644 index 000000000..aedceafb4 --- /dev/null +++ b/tests/ui/match/match-tag-unary.rs @@ -0,0 +1,4 @@ +enum A { A(isize) } +enum B { B(isize) } + +fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types diff --git a/tests/ui/match/match-tag-unary.stderr b/tests/ui/match/match-tag-unary.stderr new file mode 100644 index 000000000..31f77bdff --- /dev/null +++ b/tests/ui/match/match-tag-unary.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/match-tag-unary.rs:4:43 + | +LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } + | - ^^^^^^^ expected enum `A`, found enum `B` + | | + | this expression has type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-type-err-first-arm.rs b/tests/ui/match/match-type-err-first-arm.rs new file mode 100644 index 000000000..e9027eb24 --- /dev/null +++ b/tests/ui/match/match-type-err-first-arm.rs @@ -0,0 +1,50 @@ +fn main() { + let _ = test_func1(1); + let _ = test_func2(1); +} + +fn test_func1(n: i32) -> i32 { //~ NOTE expected `i32` because of return type + match n { + 12 => 'b', + //~^ ERROR mismatched types + //~| NOTE expected `i32`, found `char` + _ => 42, + } +} + +fn test_func2(n: i32) -> i32 { + let x = match n { //~ NOTE `match` arms have incompatible types + 12 => 'b', //~ NOTE this is found to be of type `char` + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + }; + x +} + +fn test_func3(n: i32) -> i32 { + let x = match n { //~ NOTE `match` arms have incompatible types + 1 => 'b', + 2 => 'b', + 3 => 'b', + 4 => 'b', + 5 => 'b', + 6 => 'b', + //~^ NOTE this and all prior arms are found to be of type `char` + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + }; + x +} + +fn test_func4() { + match Some(0u32) { //~ NOTE `match` arms have incompatible types + Some(x) => { + x //~ NOTE this is found to be of type `u32` + }, + None => {} + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `u32`, found `()` + }; +} diff --git a/tests/ui/match/match-type-err-first-arm.stderr b/tests/ui/match/match-type-err-first-arm.stderr new file mode 100644 index 000000000..1cfe7ce1e --- /dev/null +++ b/tests/ui/match/match-type-err-first-arm.stderr @@ -0,0 +1,65 @@ +error[E0308]: mismatched types + --> $DIR/match-type-err-first-arm.rs:8:15 + | +LL | fn test_func1(n: i32) -> i32 { + | --- expected `i32` because of return type +LL | match n { +LL | 12 => 'b', + | ^^^ expected `i32`, found `char` + | +help: you can cast a `char` to an `i32`, since a `char` always occupies 4 bytes + | +LL | 12 => 'b' as i32, + | ++++++ + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:18:14 + | +LL | let x = match n { + | _____________- +LL | | 12 => 'b', + | | --- this is found to be of type `char` +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:34:14 + | +LL | let x = match n { + | _____________- +LL | | 1 => 'b', +LL | | 2 => 'b', +LL | | 3 => 'b', +... | +LL | | 6 => 'b', + | | --- this and all prior arms are found to be of type `char` +LL | | +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:46:17 + | +LL | / match Some(0u32) { +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `u32` +LL | | }, +LL | | None => {} + | | ^^ expected `u32`, found `()` +LL | | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-unresolved-one-arm.rs b/tests/ui/match/match-unresolved-one-arm.rs new file mode 100644 index 000000000..fa65d87b3 --- /dev/null +++ b/tests/ui/match/match-unresolved-one-arm.rs @@ -0,0 +1,7 @@ +fn foo() -> T { panic!("Rocks for my pillow") } + +fn main() { + let x = match () { //~ ERROR type annotations needed + () => foo() // T here should be unresolved + }; +} diff --git a/tests/ui/match/match-unresolved-one-arm.stderr b/tests/ui/match/match-unresolved-one-arm.stderr new file mode 100644 index 000000000..e3b501b2f --- /dev/null +++ b/tests/ui/match/match-unresolved-one-arm.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/match-unresolved-one-arm.rs:4:9 + | +LL | let x = match () { + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: /* Type */ = match () { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/match/match-vec-mismatch-2.rs b/tests/ui/match/match-vec-mismatch-2.rs new file mode 100644 index 000000000..553095837 --- /dev/null +++ b/tests/ui/match/match-vec-mismatch-2.rs @@ -0,0 +1,6 @@ +fn main() { + match () { + [()] => { } + //~^ ERROR expected an array or slice, found `()` + } +} diff --git a/tests/ui/match/match-vec-mismatch-2.stderr b/tests/ui/match/match-vec-mismatch-2.stderr new file mode 100644 index 000000000..5247bea62 --- /dev/null +++ b/tests/ui/match/match-vec-mismatch-2.stderr @@ -0,0 +1,9 @@ +error[E0529]: expected an array or slice, found `()` + --> $DIR/match-vec-mismatch-2.rs:3:9 + | +LL | [()] => { } + | ^^^^ pattern cannot match with input type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/match/match-wildcards.rs b/tests/ui/match/match-wildcards.rs new file mode 100644 index 000000000..43f6e4913 --- /dev/null +++ b/tests/ui/match/match-wildcards.rs @@ -0,0 +1,21 @@ +// run-fail +// error-pattern:squirrelcupcake +// ignore-emscripten no processes + +fn cmp() -> isize { + match (Some('a'), None::) { + (Some(_), _) => { + panic!("squirrelcupcake"); + } + (_, Some(_)) => { + panic!(); + } + _ => { + panic!("wat"); + } + } +} + +fn main() { + println!("{}", cmp()); +} diff --git a/tests/ui/match/match_non_exhaustive.rs b/tests/ui/match/match_non_exhaustive.rs new file mode 100644 index 000000000..f162dd60f --- /dev/null +++ b/tests/ui/match/match_non_exhaustive.rs @@ -0,0 +1,32 @@ +// aux-build:match_non_exhaustive_lib.rs + +/* The error message for non-exhaustive matches on non-local enums + * marked as non-exhaustive should mention the fact that the enum + * is marked as non-exhaustive (issue #85227). + */ + +// Ignore non_exhaustive in the same crate +#[non_exhaustive] +enum L { A, B } + +extern crate match_non_exhaustive_lib; +use match_non_exhaustive_lib::{E1, E2}; + +fn foo() -> L {todo!()} +fn bar() -> (E1, E2) {todo!()} + +fn main() { + let l = foo(); + // No error for enums defined in this crate + match l { L::A => (), L::B => () }; + // (except if the match is already non-exhaustive) + match l { L::A => () }; + //~^ ERROR: non-exhaustive patterns: `L::B` not covered [E0004] + + // E1 is not visibly uninhabited from here + let (e1, e2) = bar(); + match e1 {}; + //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004] + match e2 { E2::A => (), E2::B => () }; + //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] +} diff --git a/tests/ui/match/match_non_exhaustive.stderr b/tests/ui/match/match_non_exhaustive.stderr new file mode 100644 index 000000000..46ee8d517 --- /dev/null +++ b/tests/ui/match/match_non_exhaustive.stderr @@ -0,0 +1,56 @@ +error[E0004]: non-exhaustive patterns: `L::B` not covered + --> $DIR/match_non_exhaustive.rs:23:11 + | +LL | match l { L::A => () }; + | ^ pattern `L::B` not covered + | +note: `L` defined here + --> $DIR/match_non_exhaustive.rs:10:13 + | +LL | enum L { A, B } + | - ^ not covered + = note: the matched value is of type `L` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match l { L::A => (), L::B => todo!() }; + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: type `E1` is non-empty + --> $DIR/match_non_exhaustive.rs:28:11 + | +LL | match e1 {}; + | ^^ + | +note: `E1` defined here + --> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1 + | +LL | pub enum E1 {} + | ^^^^^^^^^^^ + = note: the matched value is of type `E1`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match e1 { +LL + _ => todo!(), +LL ~ }; + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match_non_exhaustive.rs:30:11 + | +LL | match e2 { E2::A => (), E2::B => () }; + | ^^ pattern `_` not covered + | +note: `E2` defined here + --> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1 + | +LL | pub enum E2 { A, B } + | ^^^^^^^^^^^ + = note: the matched value is of type `E2`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match e2 { E2::A => (), E2::B => (), _ => todo!() }; + | ++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/match/pattern-deref-miscompile.rs b/tests/ui/match/pattern-deref-miscompile.rs new file mode 100644 index 000000000..caa6d184a --- /dev/null +++ b/tests/ui/match/pattern-deref-miscompile.rs @@ -0,0 +1,46 @@ +// run-pass + +fn main() { + match b"." as &[u8] { + b"." if true => {}, + b"." => panic!(), + b".." => panic!(), + b"" => panic!(), + _ => panic!(), + } + match b"." as &[u8] { + b"." if false => panic!(), + b"." => {}, + b".." => panic!(), + b"" => panic!(), + _ => panic!(), + } + match b".." as &[u8] { + b"." if true => panic!(), // the miscompile caused this arm to be reached + b"." => panic!(), + b".." => {}, + b"" => panic!(), + _ => panic!(), + } + match b".." as &[u8] { + b"." if false => panic!(), + b"." => panic!(), + b".." => {}, + b"" => panic!(), + _ => panic!(), + } + match b"" as &[u8] { + b"." if true => panic!(), + b"." => panic!(), + b".." => panic!(), + b"" => {}, + _ => panic!(), + } + match b"" as &[u8] { + b"." if false => panic!(), + b"." => panic!(), + b".." => panic!(), + b"" => {}, + _ => panic!(), + } +} diff --git a/tests/ui/match/single-line.rs b/tests/ui/match/single-line.rs new file mode 100644 index 000000000..0f69d089f --- /dev/null +++ b/tests/ui/match/single-line.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = match Some(42) { Some(x) => x, None => "" }; //~ ERROR E0308 +} diff --git a/tests/ui/match/single-line.stderr b/tests/ui/match/single-line.stderr new file mode 100644 index 000000000..ec3b76e3f --- /dev/null +++ b/tests/ui/match/single-line.stderr @@ -0,0 +1,12 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/single-line.rs:2:52 + | +LL | let _ = match Some(42) { Some(x) => x, None => "" }; + | -------------- - ^^ expected integer, found `&str` + | | | + | | this is found to be of type `{integer}` + | `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/max-min-classes.rs b/tests/ui/max-min-classes.rs new file mode 100644 index 000000000..f9a39e486 --- /dev/null +++ b/tests/ui/max-min-classes.rs @@ -0,0 +1,32 @@ +// run-pass + +#![allow(non_snake_case)] +trait Product { + fn product(&self) -> isize; +} + +struct Foo { + x: isize, + y: isize, +} + +impl Foo { + pub fn sum(&self) -> isize { + self.x + self.y + } +} + +impl Product for Foo { + fn product(&self) -> isize { + self.x * self.y + } +} + +fn Foo(x: isize, y: isize) -> Foo { + Foo { x: x, y: y } +} + +pub fn main() { + let foo = Foo(3, 20); + println!("{} {}", foo.sum(), foo.product()); +} diff --git a/tests/ui/maximal_mir_to_hir_coverage.rs b/tests/ui/maximal_mir_to_hir_coverage.rs new file mode 100644 index 000000000..5ca54633f --- /dev/null +++ b/tests/ui/maximal_mir_to_hir_coverage.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zmaximal-hir-to-mir-coverage +// run-pass + +// Just making sure this flag is accepted and doesn't crash the compiler + +fn main() { + let x = 1; + let y = x + 1; + println!("{y}"); +} diff --git a/tests/ui/maybe-bounds.rs b/tests/ui/maybe-bounds.rs new file mode 100644 index 000000000..02ed45c65 --- /dev/null +++ b/tests/ui/maybe-bounds.rs @@ -0,0 +1,9 @@ +trait Tr: ?Sized {} +//~^ ERROR `?Trait` is not permitted in supertraits + +type A1 = dyn Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types +type A2 = dyn for<'a> Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types + +fn main() {} diff --git a/tests/ui/maybe-bounds.stderr b/tests/ui/maybe-bounds.stderr new file mode 100644 index 000000000..1d823b6ac --- /dev/null +++ b/tests/ui/maybe-bounds.stderr @@ -0,0 +1,22 @@ +error: `?Trait` is not permitted in supertraits + --> $DIR/maybe-bounds.rs:1:11 + | +LL | trait Tr: ?Sized {} + | ^^^^^^ + | + = note: traits are `?Sized` by default + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bounds.rs:4:20 + | +LL | type A1 = dyn Tr + (?Sized); + | ^^^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bounds.rs:6:28 + | +LL | type A2 = dyn for<'a> Tr + (?Sized); + | ^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/meta/auxiliary/env.rs b/tests/ui/meta/auxiliary/env.rs new file mode 100644 index 000000000..b3644d8d5 --- /dev/null +++ b/tests/ui/meta/auxiliary/env.rs @@ -0,0 +1,9 @@ +// Check that aux builds can also use rustc-env, but environment is configured +// separately from the main test case. +// +// rustc-env:COMPILETEST_BAR=bar + +pub fn test() { + assert_eq!(option_env!("COMPILETEST_FOO"), None); + assert_eq!(env!("COMPILETEST_BAR"), "bar"); +} diff --git a/tests/ui/meta/expected-error-correct-rev.a.stderr b/tests/ui/meta/expected-error-correct-rev.a.stderr new file mode 100644 index 000000000..4adeebe2a --- /dev/null +++ b/tests/ui/meta/expected-error-correct-rev.a.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/expected-error-correct-rev.rs:7:18 + | +LL | let x: u32 = 22_usize; + | --- ^^^^^^^^ expected `u32`, found `usize` + | | + | expected due to this + | +help: change the type of the numeric literal from `usize` to `u32` + | +LL | let x: u32 = 22_u32; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/meta/expected-error-correct-rev.rs b/tests/ui/meta/expected-error-correct-rev.rs new file mode 100644 index 000000000..26798c3df --- /dev/null +++ b/tests/ui/meta/expected-error-correct-rev.rs @@ -0,0 +1,10 @@ +// revisions: a + +// Counterpart to `expected-error-wrong-rev.rs` + +#[cfg(a)] +fn foo() { + let x: u32 = 22_usize; //[a]~ ERROR mismatched types +} + +fn main() { } diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr new file mode 100644 index 000000000..87330155e --- /dev/null +++ b/tests/ui/meta/meta-expected-error-wrong-rev.a.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/meta-expected-error-wrong-rev.rs:13:18 + | +LL | let x: u32 = 22_usize; + | --- ^^^^^^^^ expected `u32`, found `usize` + | | + | expected due to this + | +help: change the type of the numeric literal from `usize` to `u32` + | +LL | let x: u32 = 22_u32; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/meta/meta-expected-error-wrong-rev.rs b/tests/ui/meta/meta-expected-error-wrong-rev.rs new file mode 100644 index 000000000..c30d4fe0a --- /dev/null +++ b/tests/ui/meta/meta-expected-error-wrong-rev.rs @@ -0,0 +1,16 @@ +// ignore-compare-mode-polonius + +// revisions: a +// should-fail + +// This is a "meta-test" of the compilertest framework itself. In +// particular, it includes the right error message, but the message +// targets the wrong revision, so we expect the execution to fail. +// See also `meta-expected-error-correct-rev.rs`. + +#[cfg(a)] +fn foo() { + let x: u32 = 22_usize; //[b]~ ERROR mismatched types +} + +fn main() { } diff --git a/tests/ui/meta/revision-bad.rs b/tests/ui/meta/revision-bad.rs new file mode 100644 index 000000000..37ddbe99a --- /dev/null +++ b/tests/ui/meta/revision-bad.rs @@ -0,0 +1,22 @@ +// Meta test for compiletest: check that when we give the wrong error +// patterns, the test fails. + +// run-fail +// revisions: foo bar +// should-fail +// needs-run-enabled +//[foo] error-pattern:bar +//[bar] error-pattern:foo + +#[cfg(foo)] +fn die() { + panic!("foo"); +} +#[cfg(bar)] +fn die() { + panic!("bar"); +} + +fn main() { + die(); +} diff --git a/tests/ui/meta/revision-ok.rs b/tests/ui/meta/revision-ok.rs new file mode 100644 index 000000000..bbeae41b8 --- /dev/null +++ b/tests/ui/meta/revision-ok.rs @@ -0,0 +1,21 @@ +// Meta test for compiletest: check that when we give the right error +// patterns, the test passes. See all `revision-bad.rs`. + +// run-fail +// revisions: foo bar +//[foo] error-pattern:foo +//[bar] error-pattern:bar +// ignore-emscripten no processes + +#[cfg(foo)] +fn die() { + panic!("foo"); +} +#[cfg(bar)] +fn die() { + panic!("bar"); +} + +fn main() { + die(); +} diff --git a/tests/ui/meta/rustc-env.rs b/tests/ui/meta/rustc-env.rs new file mode 100644 index 000000000..7d4e005be --- /dev/null +++ b/tests/ui/meta/rustc-env.rs @@ -0,0 +1,18 @@ +// Compiletest meta test checking that rustc-env and unset-rustc-env directives +// can be used to configure environment for rustc. +// +// run-pass +// aux-build:env.rs +// rustc-env:COMPILETEST_FOO=foo +// +// An environment variable that is likely to be set, but should be safe to unset. +// unset-rustc-env:PWD + +extern crate env; + +fn main() { + assert_eq!(env!("COMPILETEST_FOO"), "foo"); + assert_eq!(option_env!("COMPILETEST_BAR"), None); + assert_eq!(option_env!("PWD"), None); + env::test(); +} diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs new file mode 100644 index 000000000..85beaee8d --- /dev/null +++ b/tests/ui/methods/assign-to-method.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zsave-analysis +// Also regression test for #69409 + +struct Cat { + meows : usize, + how_hungry : isize, +} + +impl Cat { + pub fn speak(&self) { self.meows += 1; } +} + +fn cat(in_x : usize, in_y : isize) -> Cat { + Cat { + meows: in_x, + how_hungry: in_y + } +} + +fn main() { + let nyan : Cat = cat(52, 99); + nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method + nyan.speak += || println!("meow"); //~ ERROR attempted to take value of method +} diff --git a/tests/ui/methods/assign-to-method.stderr b/tests/ui/methods/assign-to-method.stderr new file mode 100644 index 000000000..cafe9abae --- /dev/null +++ b/tests/ui/methods/assign-to-method.stderr @@ -0,0 +1,19 @@ +error[E0615]: attempted to take value of method `speak` on type `Cat` + --> $DIR/assign-to-method.rs:22:10 + | +LL | nyan.speak = || println!("meow"); + | ^^^^^ method, not a field + | + = help: methods are immutable and cannot be assigned to + +error[E0615]: attempted to take value of method `speak` on type `Cat` + --> $DIR/assign-to-method.rs:23:10 + | +LL | nyan.speak += || println!("meow"); + | ^^^^^ method, not a field + | + = help: methods are immutable and cannot be assigned to + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/methods/auxiliary/ambig_impl_2_lib.rs b/tests/ui/methods/auxiliary/ambig_impl_2_lib.rs new file mode 100644 index 000000000..0ed68bf69 --- /dev/null +++ b/tests/ui/methods/auxiliary/ambig_impl_2_lib.rs @@ -0,0 +1,4 @@ +pub trait Me { + fn me(&self) -> usize; +} +impl Me for usize { fn me(&self) -> usize { *self } } diff --git a/tests/ui/methods/auxiliary/macro-in-other-crate.rs b/tests/ui/methods/auxiliary/macro-in-other-crate.rs new file mode 100644 index 000000000..feda08463 --- /dev/null +++ b/tests/ui/methods/auxiliary/macro-in-other-crate.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! mac { + ($ident:ident) => { let $ident = 42; } +} + +#[macro_export] +macro_rules! inline { + () => () +} diff --git a/tests/ui/methods/auxiliary/method_self_arg1.rs b/tests/ui/methods/auxiliary/method_self_arg1.rs new file mode 100644 index 000000000..f89019fe5 --- /dev/null +++ b/tests/ui/methods/auxiliary/method_self_arg1.rs @@ -0,0 +1,35 @@ +#![crate_type = "lib"] + +static mut COUNT: u64 = 1; + +pub fn get_count() -> u64 { unsafe { COUNT } } + +#[derive(Copy, Clone)] +pub struct Foo; + +impl Foo { + pub fn foo(self, x: &Foo) { + unsafe { COUNT *= 2; } + // Test internal call. + Foo::bar(&self); + Foo::bar(x); + + Foo::baz(self); + Foo::baz(*x); + + Foo::qux(Box::new(self)); + Foo::qux(Box::new(*x)); + } + + pub fn bar(&self) { + unsafe { COUNT *= 3; } + } + + pub fn baz(self) { + unsafe { COUNT *= 5; } + } + + pub fn qux(self: Box) { + unsafe { COUNT *= 7; } + } +} diff --git a/tests/ui/methods/auxiliary/method_self_arg2.rs b/tests/ui/methods/auxiliary/method_self_arg2.rs new file mode 100644 index 000000000..967254562 --- /dev/null +++ b/tests/ui/methods/auxiliary/method_self_arg2.rs @@ -0,0 +1,52 @@ +#![crate_type = "lib"] + +static mut COUNT: u64 = 1; + +pub fn get_count() -> u64 { unsafe { COUNT } } + +#[derive(Copy, Clone)] +pub struct Foo; + +impl Foo { + pub fn run_trait(self) { + unsafe { COUNT *= 17; } + // Test internal call. + Bar::foo1(&self); + Bar::foo2(self); + Bar::foo3(Box::new(self)); + + Bar::bar1(&self); + Bar::bar2(self); + Bar::bar3(Box::new(self)); + } +} + +pub trait Bar : Sized { + fn foo1(&self); + fn foo2(self); + fn foo3(self: Box); + + fn bar1(&self) { + unsafe { COUNT *= 7; } + } + fn bar2(self) { + unsafe { COUNT *= 11; } + } + fn bar3(self: Box) { + unsafe { COUNT *= 13; } + } +} + +impl Bar for Foo { + fn foo1(&self) { + unsafe { COUNT *= 2; } + } + + fn foo2(self) { + unsafe { COUNT *= 3; } + } + + fn foo3(self: Box) { + unsafe { COUNT *= 5; } + } +} diff --git a/tests/ui/methods/field-method-suggestion-using-return-ty.rs b/tests/ui/methods/field-method-suggestion-using-return-ty.rs new file mode 100644 index 000000000..07b975c44 --- /dev/null +++ b/tests/ui/methods/field-method-suggestion-using-return-ty.rs @@ -0,0 +1,18 @@ +struct Wrapper(T); + +impl Wrapper> { + fn inner_mut(&self) -> Option<&mut i32> { + self.as_mut() + //~^ ERROR no method named `as_mut` found for reference `&Wrapper>` in the current scope + //~| HELP one of the expressions' fields has a method of the same name + //~| HELP items from traits can only be used if + } + + fn inner_mut_bad(&self) -> Option<&mut u32> { + self.as_mut() + //~^ ERROR no method named `as_mut` found for reference `&Wrapper>` in the current scope + //~| HELP items from traits can only be used if + } +} + +fn main() {} diff --git a/tests/ui/methods/field-method-suggestion-using-return-ty.stderr b/tests/ui/methods/field-method-suggestion-using-return-ty.stderr new file mode 100644 index 000000000..51c52a07e --- /dev/null +++ b/tests/ui/methods/field-method-suggestion-using-return-ty.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `as_mut` found for reference `&Wrapper>` in the current scope + --> $DIR/field-method-suggestion-using-return-ty.rs:5:14 + | +LL | self.as_mut() + | ^^^^^^ method not found in `&Wrapper>` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_mut`, perhaps you need to implement it: + candidate #1: `AsMut` +help: one of the expressions' fields has a method of the same name + | +LL | self.0.as_mut() + | ++ + +error[E0599]: no method named `as_mut` found for reference `&Wrapper>` in the current scope + --> $DIR/field-method-suggestion-using-return-ty.rs:12:14 + | +LL | self.as_mut() + | ^^^^^^ method not found in `&Wrapper>` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_mut`, perhaps you need to implement it: + candidate #1: `AsMut` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/issues/issue-105732.rs b/tests/ui/methods/issues/issue-105732.rs new file mode 100644 index 000000000..d70050658 --- /dev/null +++ b/tests/ui/methods/issues/issue-105732.rs @@ -0,0 +1,14 @@ +#![feature(auto_traits)] + +auto trait Foo { + fn g(&self); //~ ERROR auto traits cannot have associated items +} + +trait Bar { + fn f(&self) { + // issue #105788 + self.g(); //~ ERROR no method named `g` found for reference `&Self` in the current scope + } +} + +fn main() {} diff --git a/tests/ui/methods/issues/issue-105732.stderr b/tests/ui/methods/issues/issue-105732.stderr new file mode 100644 index 000000000..769664254 --- /dev/null +++ b/tests/ui/methods/issues/issue-105732.stderr @@ -0,0 +1,18 @@ +error[E0380]: auto traits cannot have associated items + --> $DIR/issue-105732.rs:4:8 + | +LL | auto trait Foo { + | --- auto trait cannot have associated items +LL | fn g(&self); + | ---^-------- help: remove these associated items + +error[E0599]: no method named `g` found for reference `&Self` in the current scope + --> $DIR/issue-105732.rs:10:14 + | +LL | self.g(); + | ^ help: there is a method with a similar name: `f` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0380, E0599. +For more information about an error, try `rustc --explain E0380`. diff --git a/tests/ui/methods/issues/issue-61525.rs b/tests/ui/methods/issues/issue-61525.rs new file mode 100644 index 000000000..c5ca0326e --- /dev/null +++ b/tests/ui/methods/issues/issue-61525.rs @@ -0,0 +1,20 @@ +pub trait Example { + fn query(self, q: Q); +} + +impl Example for i32 { + fn query(self, _: Q) { + unimplemented!() + } +} + +mod nested { + use super::Example; + fn example() { + 1.query::("") + //~^ ERROR the size for values of type `dyn ToString` cannot be known at compilation time + //~| ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr new file mode 100644 index 000000000..3e73b950a --- /dev/null +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time + --> $DIR/issue-61525.rs:14:33 + | +LL | 1.query::("") + | ----- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn ToString` +note: required by a bound in `Example::query` + --> $DIR/issue-61525.rs:2:14 + | +LL | fn query(self, q: Q); + | ^ required by this bound in `Example::query` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn query(self, q: Q); + | ++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-61525.rs:14:33 + | +LL | 1.query::("") + | --------------------- ^^ expected trait object `dyn ToString`, found `&str` + | | + | arguments to this method are incorrect + | + = note: expected trait object `dyn ToString` + found reference `&'static str` +note: associated function defined here + --> $DIR/issue-61525.rs:2:8 + | +LL | fn query(self, q: Q); + | ^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/methods/issues/issue-84495.rs b/tests/ui/methods/issues/issue-84495.rs new file mode 100644 index 000000000..28c094bf2 --- /dev/null +++ b/tests/ui/methods/issues/issue-84495.rs @@ -0,0 +1,4 @@ +fn main() { + let x: i32 = 1; + println!("{:?}", x.count()); //~ ERROR is not an iterator +} diff --git a/tests/ui/methods/issues/issue-84495.stderr b/tests/ui/methods/issues/issue-84495.stderr new file mode 100644 index 000000000..b0217a7c8 --- /dev/null +++ b/tests/ui/methods/issues/issue-84495.stderr @@ -0,0 +1,13 @@ +error[E0599]: `i32` is not an iterator + --> $DIR/issue-84495.rs:3:24 + | +LL | println!("{:?}", x.count()); + | ^^^^^ `i32` is not an iterator + | + = note: the following trait bounds were not satisfied: + `i32: Iterator` + which is required by `&mut i32: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/issues/issue-90315.rs b/tests/ui/methods/issues/issue-90315.rs new file mode 100644 index 000000000..fbecaf9b9 --- /dev/null +++ b/tests/ui/methods/issues/issue-90315.rs @@ -0,0 +1,75 @@ +#![allow(unused)] +fn main() { + let arr = &[0, 1, 2, 3]; + for _i in 0..arr.len().rev() { + //~^ ERROR can't call method + //~| surround the range in parentheses + // The above error used to say “the method `rev` exists for type `usize`â€. + // This regression test ensures it doesn't say that any more. + } + + // Test for #102396 + for i in 1..11.rev() { + //~^ ERROR can't call method + //~| HELP surround the range in parentheses + } + + let end: usize = 10; + for i in 1..end.rev() { + //~^ ERROR can't call method + //~| HELP surround the range in parentheses + } + + for i in 1..(end + 1).rev() { + //~^ ERROR can't call method + //~| HELP surround the range in parentheses + } + + if 1..(end + 1).is_empty() { + //~^ ERROR can't call method + //~| ERROR mismatched types [E0308] + //~| HELP surround the range in parentheses + } + + if 1..(end + 1).is_sorted() { + //~^ ERROR mismatched types [E0308] + //~| ERROR can't call method + //~| HELP surround the range in parentheses + } + + let _res: i32 = 3..6.take(2).sum(); + //~^ ERROR can't call method + //~| ERROR mismatched types [E0308] + //~| HELP surround the range in parentheses + + let _sum: i32 = 3..6.sum(); + //~^ ERROR can't call method + //~| ERROR mismatched types [E0308] + //~| HELP surround the range in parentheses + + let a = 1 as usize; + let b = 10 as usize; + + for _a in a..=b.rev() { + //~^ ERROR can't call method + //~| HELP surround the range in parentheses + } + + let _res = ..10.contains(3); + //~^ ERROR can't call method + //~| HELP surround the range in parentheses + + if 1..end.error_method() { + //~^ ERROR no method named `error_method` + //~| ERROR mismatched types [E0308] + // Won't suggest + } + + let _res = b.take(1)..a; + //~^ ERROR `usize` is not an iterator + + let _res: i32 = ..6.take(2).sum(); + //~^ ERROR can't call method `take` on ambiguous numeric type + //~| HELP you must specify a concrete type for this numeric value + // Won't suggest because `RangeTo` dest not implemented `take` +} diff --git a/tests/ui/methods/issues/issue-90315.stderr b/tests/ui/methods/issues/issue-90315.stderr new file mode 100644 index 000000000..4d3c086ff --- /dev/null +++ b/tests/ui/methods/issues/issue-90315.stderr @@ -0,0 +1,190 @@ +error[E0689]: can't call method `rev` on type `usize` + --> $DIR/issue-90315.rs:4:28 + | +LL | for _i in 0..arr.len().rev() { + | ^^^ can't call method `rev` on type `usize` + | +help: you must surround the range in parentheses to call its `rev` function + | +LL | for _i in (0..arr.len()).rev() { + | + + + +error[E0689]: can't call method `rev` on type `{integer}` + --> $DIR/issue-90315.rs:12:20 + | +LL | for i in 1..11.rev() { + | ^^^ can't call method `rev` on type `{integer}` + | +help: you must surround the range in parentheses to call its `rev` function + | +LL | for i in (1..11).rev() { + | + + + +error[E0689]: can't call method `rev` on type `usize` + --> $DIR/issue-90315.rs:18:21 + | +LL | for i in 1..end.rev() { + | ^^^ can't call method `rev` on type `usize` + | +help: you must surround the range in parentheses to call its `rev` function + | +LL | for i in (1..end).rev() { + | + + + +error[E0689]: can't call method `rev` on type `usize` + --> $DIR/issue-90315.rs:23:27 + | +LL | for i in 1..(end + 1).rev() { + | ^^^ can't call method `rev` on type `usize` + | +help: you must surround the range in parentheses to call its `rev` function + | +LL | for i in (1..(end + 1)).rev() { + | + + + +error[E0689]: can't call method `is_empty` on type `usize` + --> $DIR/issue-90315.rs:28:21 + | +LL | if 1..(end + 1).is_empty() { + | ^^^^^^^^ can't call method `is_empty` on type `usize` + | +help: you must surround the range in parentheses to call its `is_empty` function + | +LL | if (1..(end + 1)).is_empty() { + | + + + +error[E0308]: mismatched types + --> $DIR/issue-90315.rs:28:8 + | +LL | if 1..(end + 1).is_empty() { + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<{integer}>` + +error[E0689]: can't call method `is_sorted` on type `usize` + --> $DIR/issue-90315.rs:34:21 + | +LL | if 1..(end + 1).is_sorted() { + | ^^^^^^^^^ can't call method `is_sorted` on type `usize` + | +help: you must surround the range in parentheses to call its `is_sorted` function + | +LL | if (1..(end + 1)).is_sorted() { + | + + + +error[E0308]: mismatched types + --> $DIR/issue-90315.rs:34:8 + | +LL | if 1..(end + 1).is_sorted() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<{integer}>` + +error[E0689]: can't call method `take` on type `{integer}` + --> $DIR/issue-90315.rs:40:26 + | +LL | let _res: i32 = 3..6.take(2).sum(); + | ^^^^ can't call method `take` on type `{integer}` + | +help: you must surround the range in parentheses to call its `take` function + | +LL | let _res: i32 = (3..6).take(2).sum(); + | + + + +error[E0308]: mismatched types + --> $DIR/issue-90315.rs:40:21 + | +LL | let _res: i32 = 3..6.take(2).sum(); + | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range` + | | + | expected due to this + | + = note: expected type `i32` + found struct `std::ops::Range<{integer}>` + +error[E0689]: can't call method `sum` on type `{integer}` + --> $DIR/issue-90315.rs:45:26 + | +LL | let _sum: i32 = 3..6.sum(); + | ^^^ can't call method `sum` on type `{integer}` + | +help: you must surround the range in parentheses to call its `sum` function + | +LL | let _sum: i32 = (3..6).sum(); + | + + + +error[E0308]: mismatched types + --> $DIR/issue-90315.rs:45:21 + | +LL | let _sum: i32 = 3..6.sum(); + | --- ^^^^^^^^^^ expected `i32`, found struct `Range` + | | + | expected due to this + | + = note: expected type `i32` + found struct `std::ops::Range<{integer}>` + +error[E0689]: can't call method `rev` on type `usize` + --> $DIR/issue-90315.rs:53:21 + | +LL | for _a in a..=b.rev() { + | ^^^ can't call method `rev` on type `usize` + | +help: you must surround the range in parentheses to call its `rev` function + | +LL | for _a in (a..=b).rev() { + | + + + +error[E0689]: can't call method `contains` on type `{integer}` + --> $DIR/issue-90315.rs:58:21 + | +LL | let _res = ..10.contains(3); + | ^^^^^^^^ can't call method `contains` on type `{integer}` + | +help: you must surround the range in parentheses to call its `contains` function + | +LL | let _res = (..10).contains(3); + | + + + +error[E0599]: no method named `error_method` found for type `usize` in the current scope + --> $DIR/issue-90315.rs:62:15 + | +LL | if 1..end.error_method() { + | ^^^^^^^^^^^^ method not found in `usize` + +error[E0308]: mismatched types + --> $DIR/issue-90315.rs:62:8 + | +LL | if 1..end.error_method() { + | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<{integer}>` + +error[E0599]: `usize` is not an iterator + --> $DIR/issue-90315.rs:68:18 + | +LL | let _res = b.take(1)..a; + | ^^^^ `usize` is not an iterator + | + = note: the following trait bounds were not satisfied: + `usize: Iterator` + which is required by `&mut usize: Iterator` + +error[E0689]: can't call method `take` on ambiguous numeric type `{integer}` + --> $DIR/issue-90315.rs:71:25 + | +LL | let _res: i32 = ..6.take(2).sum(); + | ^^^^ + | +help: you must specify a concrete type for this numeric value, like `i32` + | +LL | let _res: i32 = ..6_i32.take(2).sum(); + | ~~~~~ + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0308, E0599, E0689. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/methods/issues/issue-94581.rs b/tests/ui/methods/issues/issue-94581.rs new file mode 100644 index 000000000..df393e91d --- /dev/null +++ b/tests/ui/methods/issues/issue-94581.rs @@ -0,0 +1,7 @@ +fn get_slice() -> &'static [i32] { + &[1, 2, 3, 4] +} + +fn main() { + let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599] +} diff --git a/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr new file mode 100644 index 000000000..d6be29cf5 --- /dev/null +++ b/tests/ui/methods/issues/issue-94581.stderr @@ -0,0 +1,15 @@ +error[E0599]: `&'static [i32]` is not an iterator + --> $DIR/issue-94581.rs:6:29 + | +LL | let sqsum = get_slice().map(|i| i * i).sum(); + | ^^^ `&'static [i32]` is not an iterator; try calling `.iter()` + | + = note: the following trait bounds were not satisfied: + `&'static [i32]: Iterator` + which is required by `&mut &'static [i32]: Iterator` + `[i32]: Iterator` + which is required by `&mut [i32]: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs new file mode 100644 index 000000000..7b2fc34e1 --- /dev/null +++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.rs @@ -0,0 +1,36 @@ +// Test that we invoking `foo()` successfully resolves to the trait `Foo` +// (prompting the mismatched types error) but does not influence the choice +// of what kind of `Vec` we have, eventually leading to a type error. + +trait Foo { + fn foo(&self) -> isize; +} + +impl Foo for Vec { + fn foo(&self) -> isize {1} +} + +impl Foo for Vec { + fn foo(&self) -> isize {2} +} + +// This is very hokey: we have heuristics to suppress messages about +// type annotations needed. But placing these two bits of code into +// distinct functions, in this order, causes us to print out both +// errors I'd like to see. + +fn m1() { + // we couldn't infer the type of the vector just based on calling foo()... + let mut x = Vec::new(); + //~^ ERROR type annotations needed + x.foo(); //~ ERROR type annotations needed +} + +fn m2() { + let mut x = Vec::new(); + + // ...but we still resolved `foo()` to the trait and hence know the return type. + let y: usize = x.foo(); //~ ERROR mismatched types +} + +fn main() { } diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr new file mode 100644 index 000000000..e0f8a5447 --- /dev/null +++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -0,0 +1,47 @@ +error[E0282]: type annotations needed for `Vec` + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9 + | +LL | let mut x = Vec::new(); + | ^^^^^ + | +help: consider giving `x` an explicit type, where the type for type parameter `T` is specified + | +LL | let mut x: Vec = Vec::new(); + | ++++++++ + +error[E0283]: type annotations needed + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7 + | +LL | x.foo(); + | ^^^ + | +note: multiple `impl`s satisfying `Vec<_>: Foo` found + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1 + | +LL | impl Foo for Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Foo for Vec { + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | as Foo>::foo(&x); + | ++++++++++++++++++++++ ~ + +error[E0308]: mismatched types + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20 + | +LL | let y: usize = x.foo(); + | ----- ^^^^^^^ expected `usize`, found `isize` + | | + | expected due to this + | +help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit + | +LL | let y: usize = x.foo().try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0282, E0283, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/methods/method-ambig-two-traits-cross-crate.rs b/tests/ui/methods/method-ambig-two-traits-cross-crate.rs new file mode 100644 index 000000000..006e315b0 --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-cross-crate.rs @@ -0,0 +1,11 @@ +// Test an ambiguity scenario where one copy of the method is available +// from a trait imported from another crate. + +// aux-build:ambig_impl_2_lib.rs +extern crate ambig_impl_2_lib; +use ambig_impl_2_lib::Me; +trait Me2 { + fn me(&self) -> usize; +} +impl Me2 for usize { fn me(&self) -> usize { *self } } +fn main() { 1_usize.me(); } //~ ERROR E0034 diff --git a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr new file mode 100644 index 000000000..4b2597eed --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr @@ -0,0 +1,24 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-ambig-two-traits-cross-crate.rs:11:21 + | +LL | fn main() { 1_usize.me(); } + | ^^ multiple `me` found + | + = note: candidate #1 is defined in an impl of the trait `Me` for the type `usize` +note: candidate #2 is defined in an impl of the trait `Me2` for the type `usize` + --> $DIR/method-ambig-two-traits-cross-crate.rs:10:22 + | +LL | impl Me2 for usize { fn me(&self) -> usize { *self } } + | ^^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | fn main() { Me::me(&1_usize); } + | ~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | fn main() { Me2::me(&1_usize); } + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.rs b/tests/ui/methods/method-ambig-two-traits-from-bounds.rs new file mode 100644 index 000000000..e3cc5557f --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.rs @@ -0,0 +1,8 @@ +trait A { fn foo(&self); } +trait B { fn foo(&self); } + +fn foo(t: T) { + t.foo(); //~ ERROR E0034 +} + +fn main() {} diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr new file mode 100644 index 000000000..1feaa2c73 --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-ambig-two-traits-from-bounds.rs:5:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/method-ambig-two-traits-from-bounds.rs:1:11 + | +LL | trait A { fn foo(&self); } + | ^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/method-ambig-two-traits-from-bounds.rs:2:11 + | +LL | trait B { fn foo(&self); } + | ^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | A::foo(t); + | ~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | B::foo(t); + | ~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls.rs b/tests/ui/methods/method-ambig-two-traits-from-impls.rs new file mode 100644 index 000000000..22bf84066 --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-from-impls.rs @@ -0,0 +1,16 @@ +trait A { fn foo(self); } +trait B { fn foo(self); } + +struct AB {} + +impl A for AB { + fn foo(self) {} +} + +impl B for AB { + fn foo(self) {} +} + +fn main() { + AB {}.foo(); //~ ERROR E0034 +} diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr new file mode 100644 index 000000000..f69b56892 --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-ambig-two-traits-from-impls.rs:15:11 + | +LL | AB {}.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `AB` + --> $DIR/method-ambig-two-traits-from-impls.rs:7:5 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `AB` + --> $DIR/method-ambig-two-traits-from-impls.rs:11:5 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | A::foo(AB {}); + | ~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | B::foo(AB {}); + | ~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls2.rs b/tests/ui/methods/method-ambig-two-traits-from-impls2.rs new file mode 100644 index 000000000..0a96c1223 --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-from-impls2.rs @@ -0,0 +1,16 @@ +trait A { fn foo(); } +trait B { fn foo(); } + +struct AB {} + +impl A for AB { + fn foo() {} +} + +impl B for AB { + fn foo() {} +} + +fn main() { + AB::foo(); //~ ERROR E0034 +} diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr new file mode 100644 index 000000000..4ba778e0e --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-from-impls2.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-ambig-two-traits-from-impls2.rs:15:9 + | +LL | AB::foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `AB` + --> $DIR/method-ambig-two-traits-from-impls2.rs:7:5 + | +LL | fn foo() {} + | ^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `AB` + --> $DIR/method-ambig-two-traits-from-impls2.rs:11:5 + | +LL | fn foo() {} + | ^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | ::foo(); + | ~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | ::foo(); + | ~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-ambig-two-traits-with-default-method.rs b/tests/ui/methods/method-ambig-two-traits-with-default-method.rs new file mode 100644 index 000000000..aa7094b9e --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-with-default-method.rs @@ -0,0 +1,13 @@ +// Test that we correctly report an ambiguity where two applicable traits +// are in scope and the method being invoked is a default method not +// defined directly in the impl. + +trait Foo { fn method(&self) {} } +trait Bar { fn method(&self) {} } + +impl Foo for usize {} +impl Bar for usize {} + +fn main() { + 1_usize.method(); //~ ERROR E0034 +} diff --git a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr new file mode 100644 index 000000000..e84dff8ba --- /dev/null +++ b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/method-ambig-two-traits-with-default-method.rs:12:13 + | +LL | 1_usize.method(); + | ^^^^^^ multiple `method` found + | +note: candidate #1 is defined in an impl of the trait `Foo` for the type `usize` + --> $DIR/method-ambig-two-traits-with-default-method.rs:5:13 + | +LL | trait Foo { fn method(&self) {} } + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize` + --> $DIR/method-ambig-two-traits-with-default-method.rs:6:13 + | +LL | trait Bar { fn method(&self) {} } + | ^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | Foo::method(&1_usize); + | ~~~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | Bar::method(&1_usize); + | ~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-argument-inference-associated-type.rs b/tests/ui/methods/method-argument-inference-associated-type.rs new file mode 100644 index 000000000..a3c31fab1 --- /dev/null +++ b/tests/ui/methods/method-argument-inference-associated-type.rs @@ -0,0 +1,28 @@ +// run-pass +pub struct ClientMap; +pub struct ClientMap2; + +pub trait Service { + type Request; + fn call(&self, _req: Self::Request); +} + +pub struct S(#[allow(unused_tuple_struct_fields)] T); + +impl Service for ClientMap { + type Request = S>; + fn call(&self, _req: Self::Request) {} +} + + +impl Service for ClientMap2 { + type Request = (Box,); + fn call(&self, _req: Self::Request) {} +} + + +fn main() { + ClientMap.call(S { 0: Box::new(|_msgid| ()) }); + ClientMap.call(S(Box::new(|_msgid| ()))); + ClientMap2.call((Box::new(|_msgid| ()),)); +} diff --git a/tests/ui/methods/method-call-err-msg.rs b/tests/ui/methods/method-call-err-msg.rs new file mode 100644 index 000000000..4807a956a --- /dev/null +++ b/tests/ui/methods/method-call-err-msg.rs @@ -0,0 +1,22 @@ +// Test that parameter cardinality or missing method error gets span exactly. + +pub struct Foo; +impl Foo { + fn zero(self) -> Foo { self } + fn one(self, _: isize) -> Foo { self } + fn two(self, _: isize, _: isize) -> Foo { self } + fn three(self, _: T, _: T, _: T) -> Foo { self } +} + +fn main() { + let x = Foo; + x.zero(0) //~ ERROR this method takes 0 arguments but 1 argument was supplied + .one() //~ ERROR this method takes 1 argument but 0 arguments were supplied + .two(0); //~ ERROR this method takes 2 arguments but 1 argument was supplied + + let y = Foo; + y.zero() + .take() //~ ERROR not an iterator + .one(0); + y.three::(); //~ ERROR this method takes 3 arguments but 0 arguments were supplied +} diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr new file mode 100644 index 000000000..81269b73b --- /dev/null +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -0,0 +1,89 @@ +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/method-call-err-msg.rs:13:7 + | +LL | x.zero(0) + | ^^^^ - argument of type `{integer}` unexpected + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:5:8 + | +LL | fn zero(self) -> Foo { self } + | ^^^^ +help: remove the extra argument + | +LL | x.zero() + | ~~ + +error[E0061]: this method takes 1 argument but 0 arguments were supplied + --> $DIR/method-call-err-msg.rs:14:7 + | +LL | .one() + | ^^^-- an argument of type `isize` is missing + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:6:8 + | +LL | fn one(self, _: isize) -> Foo { self } + | ^^^ -------- +help: provide the argument + | +LL | .one(/* isize */) + | ~~~~~~~~~~~~~ + +error[E0061]: this method takes 2 arguments but 1 argument was supplied + --> $DIR/method-call-err-msg.rs:15:7 + | +LL | .two(0); + | ^^^--- an argument of type `isize` is missing + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:7:8 + | +LL | fn two(self, _: isize, _: isize) -> Foo { self } + | ^^^ -------- -------- +help: provide the argument + | +LL | .two(0, /* isize */); + | ~~~~~~~~~~~~~~~~ + +error[E0599]: `Foo` is not an iterator + --> $DIR/method-call-err-msg.rs:19:7 + | +LL | pub struct Foo; + | -------------- + | | + | method `take` not found for this struct + | doesn't satisfy `Foo: Iterator` +... +LL | .take() + | ^^^^ `Foo` is not an iterator + | + = note: the following trait bounds were not satisfied: + `Foo: Iterator` + which is required by `&mut Foo: Iterator` +note: the trait `Iterator` must be implemented + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `take`, perhaps you need to implement it: + candidate #1: `Iterator` + +error[E0061]: this method takes 3 arguments but 0 arguments were supplied + --> $DIR/method-call-err-msg.rs:21:7 + | +LL | y.three::(); + | ^^^^^^^^^^^^^^-- three arguments of type `usize`, `usize`, and `usize` are missing + | +note: associated function defined here + --> $DIR/method-call-err-msg.rs:8:8 + | +LL | fn three(self, _: T, _: T, _: T) -> Foo { self } + | ^^^^^ ---- ---- ---- +help: provide the arguments + | +LL | y.three::(/* usize */, /* usize */, /* usize */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0061, E0599. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/methods/method-call-lifetime-args-fail.rs b/tests/ui/methods/method-call-lifetime-args-fail.rs new file mode 100644 index 000000000..6bf55844d --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-fail.rs @@ -0,0 +1,72 @@ +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} + fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } + fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } + fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } + fn life_and_type<'a, T>(self) -> &'a T { loop {} } +} + +fn method_call() { + S.early(); // OK + S.early::<'static>(); + //~^ ERROR this associated function takes 2 lifetime arguments but 1 lifetime argument + S.early::<'static, 'static, 'static>(); + //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied + let _: &u8 = S.life_and_type::<'static>(); + S.life_and_type::(); + S.life_and_type::<'static, u8>(); +} + +fn ufcs() { + S::late(S, &0, &0); // OK + S::late::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late::<'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late::<'static, 'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_early(S, &0); // OK + S::late_early::<'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_early::<'static, 'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + + S::late_implicit(S, &0, &0); // OK + S::late_implicit::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit::<'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit::<'static, 'static, 'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_early(S, &0); // OK + S::late_implicit_early::<'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_early::<'static, 'static, 'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_self_early(&S); // OK + S::late_implicit_self_early::<'static, 'static>(&S); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit_self_early::<'static, 'static, 'static>(&S); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_unused_early(S); // OK + S::late_unused_early::<'static, 'static>(S); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_unused_early::<'static, 'static, 'static>(S); + //~^ ERROR cannot specify lifetime arguments explicitly + + S::early(S); // OK + S::early::<'static>(S); + //~^ ERROR this associated function takes 2 lifetime arguments but 1 lifetime argument + S::early::<'static, 'static, 'static>(S); + //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied + let _: &u8 = S::life_and_type::<'static>(S); + S::life_and_type::(S); + S::life_and_type::<'static, u8>(S); +} + +fn main() {} diff --git a/tests/ui/methods/method-call-lifetime-args-fail.stderr b/tests/ui/methods/method-call-lifetime-args-fail.stderr new file mode 100644 index 000000000..249b48ab1 --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-fail.stderr @@ -0,0 +1,235 @@ +error[E0107]: this associated function takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/method-call-lifetime-args-fail.rs:16:7 + | +LL | S.early::<'static>(); + | ^^^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/method-call-lifetime-args-fail.rs:6:8 + | +LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } + | ^^^^^ -- -- +help: add missing lifetime argument + | +LL | S.early::<'static, 'static>(); + | +++++++++ + +error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied + --> $DIR/method-call-lifetime-args-fail.rs:18:7 + | +LL | S.early::<'static, 'static, 'static>(); + | ^^^^^ ------- help: remove this lifetime argument + | | + | expected 2 lifetime arguments + | +note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/method-call-lifetime-args-fail.rs:6:8 + | +LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } + | ^^^^^ -- -- + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:27:15 + | +LL | S::late::<'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:4:13 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:29:15 + | +LL | S::late::<'static, 'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:4:13 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:31:15 + | +LL | S::late::<'static, 'static, 'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:4:13 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:34:21 + | +LL | S::late_early::<'static, 'static>(S, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:7:19 + | +LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:36:21 + | +LL | S::late_early::<'static, 'static, 'static>(S, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:7:19 + | +LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:40:24 + | +LL | S::late_implicit::<'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:5:31 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:42:24 + | +LL | S::late_implicit::<'static, 'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:5:31 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:44:24 + | +LL | S::late_implicit::<'static, 'static, 'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:5:31 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:47:30 + | +LL | S::late_implicit_early::<'static, 'static>(S, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:8:41 + | +LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:49:30 + | +LL | S::late_implicit_early::<'static, 'static, 'static>(S, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:8:41 + | +LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:52:35 + | +LL | S::late_implicit_self_early::<'static, 'static>(&S); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:9:37 + | +LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:54:35 + | +LL | S::late_implicit_self_early::<'static, 'static, 'static>(&S); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:9:37 + | +LL | fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} } + | ^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:57:28 + | +LL | S::late_unused_early::<'static, 'static>(S); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:10:26 + | +LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-fail.rs:59:28 + | +LL | S::late_unused_early::<'static, 'static, 'static>(S); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args-fail.rs:10:26 + | +LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} } + | ^^ + +error[E0107]: this associated function takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/method-call-lifetime-args-fail.rs:63:8 + | +LL | S::early::<'static>(S); + | ^^^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/method-call-lifetime-args-fail.rs:6:8 + | +LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } + | ^^^^^ -- -- +help: add missing lifetime argument + | +LL | S::early::<'static, 'static>(S); + | +++++++++ + +error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied + --> $DIR/method-call-lifetime-args-fail.rs:65:8 + | +LL | S::early::<'static, 'static, 'static>(S); + | ^^^^^ ------- help: remove this lifetime argument + | | + | expected 2 lifetime arguments + | +note: associated function defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/method-call-lifetime-args-fail.rs:6:8 + | +LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} } + | ^^^^^ -- -- + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/methods/method-call-lifetime-args-lint-fail.rs b/tests/ui/methods/method-call-lifetime-args-lint-fail.rs new file mode 100644 index 000000000..23893911e --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-lint-fail.rs @@ -0,0 +1,87 @@ +#![deny(late_bound_lifetime_arguments)] +#![allow(unused)] + +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} + fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + + // 'late lifetimes here belong to nested types not to the tested functions. + fn early_tricky_explicit<'a>(_: for<'late> fn(&'late u8), + _: Box Fn(&'late u8)>) + -> &'a u8 { loop {} } + fn early_tricky_implicit<'a>(_: fn(&u8), + _: Box) + -> &'a u8 { loop {} } +} + +fn method_call() { + S.late(&0, &0); // OK + S.late::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late::<'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late::<'static, 'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_early(&0); // OK + S.late_early::<'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_early::<'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_early::<'static, 'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S.late_implicit(&0, &0); // OK + S.late_implicit::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit::<'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit::<'static, 'static, 'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit_early(&0); // OK + S.late_implicit_early::<'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit_early::<'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + S.late_implicit_early::<'static, 'static, 'static>(&0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S::early_tricky_explicit::<'static>(loop {}, loop {}); // OK + S::early_tricky_implicit::<'static>(loop {}, loop {}); // OK +} + +fn ufcs() { + S::late_early::<'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S::late_implicit_early::<'static>(S, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn lint_not_inference_error() { + fn f<'early, 'late, T: 'early>() {} + + // Make sure `u8` is substituted and not replaced with an inference variable + f::<'static, u8>; + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/tests/ui/methods/method-call-lifetime-args-lint-fail.stderr b/tests/ui/methods/method-call-lifetime-args-lint-fail.stderr new file mode 100644 index 000000000..394c1ac3c --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-lint-fail.stderr @@ -0,0 +1,187 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:23:14 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | -- the late bound lifetime parameter is introduced here +... +LL | S.late::<'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 +note: the lint level is defined here + --> $DIR/method-call-lifetime-args-lint-fail.rs:1:9 + | +LL | #![deny(late_bound_lifetime_arguments)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:26:14 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | -- the late bound lifetime parameter is introduced here +... +LL | S.late::<'static, 'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:29:14 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | -- the late bound lifetime parameter is introduced here +... +LL | S.late::<'static, 'static, 'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:33:20 + | +LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + | -- the late bound lifetime parameter is introduced here +... +LL | S.late_early::<'static>(&0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:36:20 + | +LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + | -- the late bound lifetime parameter is introduced here +... +LL | S.late_early::<'static, 'static>(&0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:39:20 + | +LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + | -- the late bound lifetime parameter is introduced here +... +LL | S.late_early::<'static, 'static, 'static>(&0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:44:23 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit::<'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:47:23 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit::<'static, 'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:50:23 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit::<'static, 'static, 'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:54:29 + | +LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit_early::<'static>(&0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:57:29 + | +LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit_early::<'static, 'static>(&0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:60:29 + | +LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit_early::<'static, 'static, 'static>(&0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:69:21 + | +LL | fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} } + | -- the late bound lifetime parameter is introduced here +... +LL | S::late_early::<'static>(S, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:73:30 + | +LL | fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} } + | - the late bound lifetime parameter is introduced here +... +LL | S::late_implicit_early::<'static>(S, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint-fail.rs:82:9 + | +LL | fn f<'early, 'late, T: 'early>() {} + | ----- the late bound lifetime parameter is introduced here +... +LL | f::<'static, u8>; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: aborting due to 15 previous errors + diff --git a/tests/ui/methods/method-call-lifetime-args-lint.rs b/tests/ui/methods/method-call-lifetime-args-lint.rs new file mode 100644 index 000000000..14729e1e2 --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-lint.rs @@ -0,0 +1,21 @@ +#![deny(late_bound_lifetime_arguments)] +#![allow(unused)] + +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} +} + +fn method_call() { + S.late::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted + + S.late_implicit::<'static>(&0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/tests/ui/methods/method-call-lifetime-args-lint.stderr b/tests/ui/methods/method-call-lifetime-args-lint.stderr new file mode 100644 index 000000000..b4fc2d717 --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-lint.stderr @@ -0,0 +1,31 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint.rs:12:14 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | -- the late bound lifetime parameter is introduced here +... +LL | S.late::<'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 +note: the lint level is defined here + --> $DIR/method-call-lifetime-args-lint.rs:1:9 + | +LL | #![deny(late_bound_lifetime_arguments)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-lint.rs:16:23 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | - the late bound lifetime parameter is introduced here +... +LL | S.late_implicit::<'static>(&0, &0); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/methods/method-call-lifetime-args-subst-index.rs b/tests/ui/methods/method-call-lifetime-args-subst-index.rs new file mode 100644 index 000000000..8df58a348 --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-subst-index.rs @@ -0,0 +1,15 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(unused)] + +struct S; + +impl S { + fn early_and_type<'a, T>(self) -> &'a T { loop {} } +} + +fn test() { + S.early_and_type::(); +} + + +fn main() {} diff --git a/tests/ui/methods/method-call-lifetime-args-unresolved.rs b/tests/ui/methods/method-call-lifetime-args-unresolved.rs new file mode 100644 index 000000000..ba7231070 --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-unresolved.rs @@ -0,0 +1,6 @@ +fn main() { + 0.clone::<'a>(); + //~^ ERROR use of undeclared lifetime name `'a` + //~| WARN cannot specify lifetime arguments explicitly if late bound + //~| WARN this was previously accepted by the compiler +} diff --git a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr new file mode 100644 index 000000000..25ad360b3 --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr @@ -0,0 +1,24 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/method-call-lifetime-args-unresolved.rs:2:15 + | +LL | fn main() { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | 0.clone::<'a>(); + | ^^ undeclared lifetime + +warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args-unresolved.rs:2:15 + | +LL | 0.clone::<'a>(); + | ^^ + --> $SRC_DIR/core/src/clone.rs:LL:COL + | + = note: the late bound lifetime parameter is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + = note: `#[warn(late_bound_lifetime_arguments)]` on by default + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/methods/method-call-lifetime-args.rs b/tests/ui/methods/method-call-lifetime-args.rs new file mode 100644 index 000000000..3292e9fcd --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args.rs @@ -0,0 +1,15 @@ +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + fn late_implicit(self, _: &u8, _: &u8) {} +} + +fn ufcs() { + S::late::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly + S::late_implicit::<'static>(S, &0, &0); + //~^ ERROR cannot specify lifetime arguments explicitly +} + +fn main() {} diff --git a/tests/ui/methods/method-call-lifetime-args.stderr b/tests/ui/methods/method-call-lifetime-args.stderr new file mode 100644 index 000000000..64ae79e9b --- /dev/null +++ b/tests/ui/methods/method-call-lifetime-args.stderr @@ -0,0 +1,26 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args.rs:9:15 + | +LL | S::late::<'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args.rs:4:13 + | +LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/method-call-lifetime-args.rs:11:24 + | +LL | S::late_implicit::<'static>(S, &0, &0); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/method-call-lifetime-args.rs:5:31 + | +LL | fn late_implicit(self, _: &u8, _: &u8) {} + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/methods/method-call-type-binding.rs b/tests/ui/methods/method-call-type-binding.rs new file mode 100644 index 000000000..f547ca8d1 --- /dev/null +++ b/tests/ui/methods/method-call-type-binding.rs @@ -0,0 +1,3 @@ +fn main() { + 0.clone::(); //~ ERROR associated type bindings are not allowed here +} diff --git a/tests/ui/methods/method-call-type-binding.stderr b/tests/ui/methods/method-call-type-binding.stderr new file mode 100644 index 000000000..4b93082ac --- /dev/null +++ b/tests/ui/methods/method-call-type-binding.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/method-call-type-binding.rs:2:15 + | +LL | 0.clone::(); + | ^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs new file mode 100644 index 000000000..9e53ff079 --- /dev/null +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs @@ -0,0 +1,179 @@ +#![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize)] +#![feature(unsized_locals, unsized_fn_params)] +//~^ WARN the feature `unsized_locals` is incomplete + +// This tests a few edge-cases around `arbitrary_self_types`. Most specifically, +// it checks that the `ObjectCandidate` you get from method matching can't +// match a trait with the same DefId as a supertrait but a bad type parameter. + +use std::marker::PhantomData; + +mod internal { + use std::ops::{CoerceUnsized, Deref, DispatchFromDyn}; + use std::marker::{PhantomData, Unsize}; + + pub struct Smaht(pub Box, pub PhantomData); + + impl Deref for Smaht { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl, U: ?Sized, MISC> CoerceUnsized> + for Smaht + {} + impl, U: ?Sized, MISC> DispatchFromDyn> + for Smaht + {} + + pub trait Foo: X {} + pub trait X { + fn foo(self: Smaht) -> T; + } + + impl X for () { + fn foo(self: Smaht) -> u32 { + 0 + } + } + + pub trait Marker {} + impl Marker for dyn Foo {} + impl X for T { + fn foo(self: Smaht) -> u64 { + 1 + } + } + + impl Deref for dyn Foo { + type Target = (); + fn deref(&self) -> &() { &() } + } + + impl Foo for () {} +} + +pub trait FinalFoo { + fn foo(&self) -> u8; +} + +impl FinalFoo for () { + fn foo(&self) -> u8 { 0 } +} + +mod nuisance_foo { + pub trait NuisanceFoo { + fn foo(self); + } + + impl NuisanceFoo for T { + fn foo(self) {} + } +} + + +fn objectcandidate_impl() { + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::foo` via `ObjectCandidate`. + // + // The `TraitCandidate` is not relevant because `X` is not in scope. + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected `()`, found `u32` +} + +fn traitcandidate_impl() { + use internal::X; + + let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::foo` via `TraitCandidate`. + // + // The `ObjectCandidate` does not apply, as it only applies to + // `X` (and not `X`). + let z = x.foo(); + + // Observe the type of `z` is `u64` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected `()`, found `u64` +} + +fn traitcandidate_impl_with_nuisance() { + use internal::X; + use nuisance_foo::NuisanceFoo; + + let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This picks `>::foo` via `TraitCandidate`. + // + // The `ObjectCandidate` does not apply, as it only applies to + // `X` (and not `X`). + // + // The NuisanceFoo impl has the same priority as the `X` impl, + // so we get a conflict. + let z = x.foo(); //~ ERROR multiple applicable items in scope +} + + +fn neither_impl() { + let x: internal::Smaht<(), u64> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This can't pick the `TraitCandidate` impl, because `Foo` is not + // imported. However, this also can't pick the `ObjectCandidate` + // impl, because it only applies to `X` (and not `X`). + // + // Therefore, neither of the candidates is applicable, and we pick + // the `FinalFoo` impl after another deref, which will return `u8`. + let z = x.foo(); + + // Observe the type of `z` is `u8` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected `()`, found `u8` +} + +fn both_impls() { + use internal::X; + + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + + // This can pick both the `TraitCandidate` and the `ObjectCandidate` impl. + // + // However, the `ObjectCandidate` is considered an "inherent candidate", + // and therefore has priority over both the `TraitCandidate` as well as + // any other "nuisance" candidate" (if present). + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected `()`, found `u32` +} + + +fn both_impls_with_nuisance() { + // Similar to the `both_impls` example, except with a nuisance impl to + // make sure the `ObjectCandidate` indeed has a higher priority. + + use internal::X; + use nuisance_foo::NuisanceFoo; + + let x: internal::Smaht<(), u32> = internal::Smaht(Box::new(()), PhantomData); + let x: internal::Smaht = x; + let z = x.foo(); + + // Observe the type of `z` is `u32` + let _seetype: () = z; //~ ERROR mismatched types + //~| expected `()`, found `u32` +} + +fn main() { +} diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr new file mode 100644 index 000000000..82addab94 --- /dev/null +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -0,0 +1,87 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:2:12 + | +LL | #![feature(unsized_locals, unsized_fn_params)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:87:24 + | +LL | let _seetype: () = z; + | -- ^ expected `()`, found `u32` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:104:24 + | +LL | let _seetype: () = z; + | -- ^ expected `()`, found `u64` + | | + | expected due to this + +error[E0034]: multiple applicable items in scope + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:122:15 + | +LL | let z = x.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `X` for the type `T` + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:45:9 + | +LL | fn foo(self: Smaht) -> u64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `NuisanceFoo` for the type `T` + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:72:9 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +note: candidate #3 is defined in the trait `FinalFoo` + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:59:5 + | +LL | fn foo(&self) -> u8; + | ^^^^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | let z = X::foo(x); + | ~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | let z = NuisanceFoo::foo(x); + | ~~~~~~~~~~~~~~~~~~~ +help: disambiguate the associated function for candidate #3 + | +LL | let z = FinalFoo::foo(x); + | ~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24 + | +LL | let _seetype: () = z; + | -- ^ expected `()`, found `u8` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:157:24 + | +LL | let _seetype: () = z; + | -- ^ expected `()`, found `u32` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:174:24 + | +LL | let _seetype: () = z; + | -- ^ expected `()`, found `u32` + | | + | expected due to this + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0034, E0308. +For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/methods/method-early-bound-lifetimes-on-self.rs b/tests/ui/methods/method-early-bound-lifetimes-on-self.rs new file mode 100644 index 000000000..f2ace32c6 --- /dev/null +++ b/tests/ui/methods/method-early-bound-lifetimes-on-self.rs @@ -0,0 +1,31 @@ +// run-pass +// Check that we successfully handle methods where the `self` type has +// an early-bound lifetime. Issue #18208. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::marker; + +struct Cursor<'a> { + m: marker::PhantomData<&'a ()> +} + +trait CursorNavigator { + fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool; +} + +struct SimpleNavigator; + +impl CursorNavigator for SimpleNavigator { + fn init_cursor<'a, 'b: 'a>(&'a self, _cursor: &mut Cursor<'b>) -> bool { + false + } +} + +fn main() { + let mut c = Cursor { m: marker::PhantomData }; + let n = SimpleNavigator; + n.init_cursor(&mut c); +} diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs new file mode 100644 index 000000000..986fe103c --- /dev/null +++ b/tests/ui/methods/method-lookup-order.rs @@ -0,0 +1,190 @@ +// ignore-tidy-linelength + +// run-pass + +// There are five cfg's below. I explored the set of all non-empty combinations +// of the below five cfg's, which is 2^5 - 1 = 31 combinations. +// +// Of the 31, 11 resulted in ambiguous method resolutions; while it may be good +// to have a test for all of the eleven variations of that error, I am not sure +// this particular test is the best way to encode it. So they are skipped in +// this revisions list (but not in the expansion mapping the binary encoding to +// the corresponding cfg flags). +// +// Notable, here are the cases that will be incompatible if something does not override them first: +// {bar_for_foo, valbar_for_et_foo}: these are higher precedent than the `&mut self` method on `Foo`, and so no case matching bx1x1x is included. +// {mutbar_for_foo, valbar_for_etmut_foo} (which are lower precedent than the inherent `&mut self` method on `Foo`; e.g. b10101 *is* included. + +// revisions: b00001 b00010 b00011 b00100 b00101 b00110 b00111 b01000 b01001 b01100 b01101 b10000 b10001 b10010 b10011 b10101 b10111 b11000 b11001 b11101 + +//[b00001]compile-flags: --cfg inherent_mut +//[b00010]compile-flags: --cfg bar_for_foo +//[b00011]compile-flags: --cfg inherent_mut --cfg bar_for_foo +//[b00100]compile-flags: --cfg mutbar_for_foo +//[b00101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo +//[b00110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo +//[b00111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo +//[b01000]compile-flags: --cfg valbar_for_et_foo +//[b01001]compile-flags: --cfg inherent_mut --cfg valbar_for_et_foo +//[b01010]compile-flags: --cfg bar_for_foo --cfg valbar_for_et_foo +//[b01011]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg valbar_for_et_foo +//[b01100]compile-flags: --cfg mutbar_for_foo --cfg valbar_for_et_foo +//[b01101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo --cfg valbar_for_et_foo +//[b01110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo +//[b01111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo +//[b10000]compile-flags: --cfg valbar_for_etmut_foo +//[b10001]compile-flags: --cfg inherent_mut --cfg valbar_for_etmut_foo +//[b10010]compile-flags: --cfg bar_for_foo --cfg valbar_for_etmut_foo +//[b10011]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg valbar_for_etmut_foo +//[b10100]compile-flags: --cfg mutbar_for_foo --cfg valbar_for_etmut_foo +//[b10101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo --cfg valbar_for_etmut_foo +//[b10110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_etmut_foo +//[b10111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_etmut_foo +//[b11000]compile-flags: --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11001]compile-flags: --cfg inherent_mut --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11010]compile-flags: --cfg bar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11011]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11100]compile-flags: --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11101]compile-flags: --cfg inherent_mut --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11110]compile-flags: --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo +//[b11111]compile-flags: --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo + +struct Foo {} + +type S = &'static str; + +trait Bar { + fn bar(&self, _: &str) -> S; +} + +trait MutBar { + fn bar(&mut self, _: &str) -> S; +} + +trait ValBar { + fn bar(self, _: &str) -> S; +} + +#[cfg(inherent_mut)] +impl Foo { + fn bar(&mut self, _: &str) -> S { + "In struct impl!" + } +} + +#[cfg(bar_for_foo)] +impl Bar for Foo { + fn bar(&self, _: &str) -> S { + "In trait &self impl!" + } +} + +#[cfg(mutbar_for_foo)] +impl MutBar for Foo { + fn bar(&mut self, _: &str) -> S { + "In trait &mut self impl!" + } +} + +#[cfg(valbar_for_et_foo)] +impl ValBar for &Foo { + fn bar(self, _: &str) -> S { + "In trait self impl for &Foo!" + } +} + +#[cfg(valbar_for_etmut_foo)] +impl ValBar for &mut Foo { + fn bar(self, _: &str) -> S { + "In trait self impl for &mut Foo!" + } +} + +fn main() { + #![allow(unused_mut)] // some of the impls above will want it. + + #![allow(unreachable_patterns)] // the cfg-coding pattern below generates unreachable patterns. + + { + macro_rules! all_variants_on_value { + ($e:expr) => { + match $e { + #[cfg(bar_for_foo)] + x => assert_eq!(x, "In trait &self impl!"), + + #[cfg(valbar_for_et_foo)] + x => assert_eq!(x, "In trait self impl for &Foo!"), + + #[cfg(inherent_mut)] + x => assert_eq!(x, "In struct impl!"), + + #[cfg(mutbar_for_foo)] + x => assert_eq!(x, "In trait &mut self impl!"), + + #[cfg(valbar_for_etmut_foo)] + x => assert_eq!(x, "In trait self impl for &mut Foo!"), + } + } + } + + let mut f = Foo {}; + all_variants_on_value!(f.bar("f.bar")); + + let f_mr = &mut Foo {}; + all_variants_on_value!((*f_mr).bar("(*f_mr).bar")); + } + + // This is sort of interesting: `&mut Foo` ends up with a significantly + // different resolution order than what was devised above. Presumably this + // is because we can get to a `&self` method by first a deref of the given + // `&mut Foo` and then an autoref, and that is a longer path than a mere + // auto-ref of a `Foo`. + + { + let f_mr = &mut Foo {}; + + match f_mr.bar("f_mr.bar") { + #[cfg(inherent_mut)] + x => assert_eq!(x, "In struct impl!"), + + #[cfg(valbar_for_etmut_foo)] + x => assert_eq!(x, "In trait self impl for &mut Foo!"), + + #[cfg(mutbar_for_foo)] + x => assert_eq!(x, "In trait &mut self impl!"), + + #[cfg(valbar_for_et_foo)] + x => assert_eq!(x, "In trait self impl for &Foo!"), + + #[cfg(bar_for_foo)] + x => assert_eq!(x, "In trait &self impl!"), + } + } + + + // Note that this isn't actually testing a resolution order; if both of these are + // enabled, it yields an ambiguous method resolution error. The test tries to embed + // that fact by testing *both* orders (and so the only way that can be right is if + // they are not actually compatible). + #[cfg(any(bar_for_foo, valbar_for_et_foo))] + { + let f_r = &Foo {}; + + match f_r.bar("f_r.bar") { + #[cfg(bar_for_foo)] + x => assert_eq!(x, "In trait &self impl!"), + + #[cfg(valbar_for_et_foo)] + x => assert_eq!(x, "In trait self impl for &Foo!"), + } + + match f_r.bar("f_r.bar") { + #[cfg(valbar_for_et_foo)] + x => assert_eq!(x, "In trait self impl for &Foo!"), + + #[cfg(bar_for_foo)] + x => assert_eq!(x, "In trait &self impl!"), + } + } + +} diff --git a/tests/ui/methods/method-macro-backtrace.rs b/tests/ui/methods/method-macro-backtrace.rs new file mode 100644 index 000000000..00fe32b7c --- /dev/null +++ b/tests/ui/methods/method-macro-backtrace.rs @@ -0,0 +1,25 @@ +// forbid-output: in this expansion of + +macro_rules! make_method { + ($name:ident) => ( fn $name(&self) { } ) +} + +struct S; + +impl S { + // We had a bug where these wouldn't clean up macro backtrace frames. + make_method!(foo1); + make_method!(foo2); + make_method!(foo3); + make_method!(foo4); + make_method!(foo5); + make_method!(foo6); + make_method!(foo7); + make_method!(foo8); + + // Cause an error. It shouldn't have any macro backtrace frames. + fn bar(&self) { } + fn bar(&self) { } //~ ERROR duplicate definitions +} + +fn main() { } diff --git a/tests/ui/methods/method-macro-backtrace.stderr b/tests/ui/methods/method-macro-backtrace.stderr new file mode 100644 index 000000000..dd616c4a5 --- /dev/null +++ b/tests/ui/methods/method-macro-backtrace.stderr @@ -0,0 +1,11 @@ +error[E0592]: duplicate definitions with name `bar` + --> $DIR/method-macro-backtrace.rs:22:5 + | +LL | fn bar(&self) { } + | ------------- other definition for `bar` +LL | fn bar(&self) { } + | ^^^^^^^^^^^^^ duplicate definitions for `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/methods/method-missing-call.rs b/tests/ui/methods/method-missing-call.rs new file mode 100644 index 000000000..7ce1e9a4f --- /dev/null +++ b/tests/ui/methods/method-missing-call.rs @@ -0,0 +1,30 @@ +// Tests to make sure that parens are needed for method calls without arguments. +// outputs text to make sure either an anonymous function is provided or +// open-close '()' parens are given + + +struct Point { + x: isize, + y: isize +} +impl Point { + fn new() -> Point { + Point{x:0, y:0} + } + fn get_x(&self) -> isize { + self.x + } +} + +fn main() { + let point: Point = Point::new(); + let px: isize = point + .get_x;//~ ERROR attempted to take value of method `get_x` on type `Point` + + // Ensure the span is useful + let ys = &[1,2,3,4,5,6,7]; + let a = ys.iter() + .map(|x| x) + .filter(|&&x| x == 1) + .filter_map; //~ ERROR attempted to take value of method `filter_map` on type +} diff --git a/tests/ui/methods/method-missing-call.stderr b/tests/ui/methods/method-missing-call.stderr new file mode 100644 index 000000000..040a65d16 --- /dev/null +++ b/tests/ui/methods/method-missing-call.stderr @@ -0,0 +1,25 @@ +error[E0615]: attempted to take value of method `get_x` on type `Point` + --> $DIR/method-missing-call.rs:22:26 + | +LL | .get_x; + | ^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | .get_x(); + | ++ + +error[E0615]: attempted to take value of method `filter_map` on type `Filter, [closure@$DIR/method-missing-call.rs:27:20: 27:23]>, [closure@$DIR/method-missing-call.rs:28:23: 28:28]>` + --> $DIR/method-missing-call.rs:29:16 + | +LL | .filter_map; + | ^^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | .filter_map(_); + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs b/tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs new file mode 100644 index 000000000..daff037b2 --- /dev/null +++ b/tests/ui/methods/method-mut-self-modifies-mut-slice-lvalue.rs @@ -0,0 +1,44 @@ +// run-pass +// Test that an `&mut self` method, when invoked on a place whose +// type is `&mut [u8]`, passes in a pointer to the place and not a +// temporary. Issue #19147. + +use std::slice; +use std::cmp; + +trait MyWriter { + fn my_write(&mut self, buf: &[u8]) -> Result<(), ()>; +} + +impl<'a> MyWriter for &'a mut [u8] { + fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> { + let amt = cmp::min(self.len(), buf.len()); + self[..amt].clone_from_slice(&buf[..amt]); + + let write_len = buf.len(); + unsafe { + *self = slice::from_raw_parts_mut( + self.as_mut_ptr().add(write_len), + self.len() - write_len + ); + } + + Ok(()) + } +} + +fn main() { + let mut buf = [0; 6]; + + { + let mut writer: &mut [_] = &mut buf; + writer.my_write(&[0, 1, 2]).unwrap(); + writer.my_write(&[3, 4, 5]).unwrap(); + } + + // If `my_write` is not modifying `buf` in place, then we will + // wind up with `[3, 4, 5, 0, 0, 0]` because the first call to + // `my_write()` doesn't update the starting point for the write. + + assert_eq!(buf, [0, 1, 2, 3, 4, 5]); +} diff --git a/tests/ui/methods/method-normalize-bounds-issue-20604.rs b/tests/ui/methods/method-normalize-bounds-issue-20604.rs new file mode 100644 index 000000000..9c0b95284 --- /dev/null +++ b/tests/ui/methods/method-normalize-bounds-issue-20604.rs @@ -0,0 +1,61 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(stable_features)] + +// Test that we handle projection types which wind up important for +// resolving methods. This test was reduced from a larger example; the +// call to `foo()` at the end was failing to resolve because the +// winnowing stage of method resolution failed to handle an associated +// type projection. + +// pretty-expanded FIXME #23616 + +#![feature(associated_types)] + +trait Hasher { + type Output; + fn finish(&self) -> Self::Output; +} + +trait Hash { + fn hash(&self, h: &mut H); +} + +trait HashState { + type Wut: Hasher; + fn hasher(&self) -> Self::Wut; +} + +struct SipHasher; +impl Hasher for SipHasher { + type Output = u64; + fn finish(&self) -> u64 { 4 } +} + +impl Hash for isize { + fn hash(&self, h: &mut SipHasher) {} +} + +struct SipState; +impl HashState for SipState { + type Wut = SipHasher; + fn hasher(&self) -> SipHasher { SipHasher } +} + +struct Map { + s: S, +} + +impl Map + where S: HashState, + ::Wut: Hasher, +{ + fn foo(&self, k: K) where K: Hash< ::Wut> {} +} + +fn foo>(map: &Map) { + map.foo(22); +} + +fn main() {} diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.rs b/tests/ui/methods/method-not-found-generic-arg-elision.rs new file mode 100644 index 000000000..799ced5e9 --- /dev/null +++ b/tests/ui/methods/method-not-found-generic-arg-elision.rs @@ -0,0 +1,106 @@ +// Test for issue 81576 +// Remove generic arguments if no method is found for all possible generic argument + +use std::marker::PhantomData; + +struct Wrapper2<'a, T, const C: usize> { + x: &'a T, +} + +impl<'a, const C: usize> Wrapper2<'a, i8, C> { + fn method(&self) {} +} + +impl<'a, const C: usize> Wrapper2<'a, i16, C> { + fn method(&self) {} +} + +impl<'a, const C: usize> Wrapper2<'a, i32, C> { + fn method(&self) {} +} +struct Wrapper(T); + +impl Wrapper { + fn method(&self) {} +} + +impl Wrapper { + fn method(&self) {} +} + +impl Wrapper { + fn method(&self) {} +} + +impl Wrapper { + fn method(&self) {} +} + +impl Wrapper { + fn method(&self) {} +} + +impl Wrapper { + fn method(&self) {} +} + +struct Point { + x: T, + y: T, +} + +impl Point { + fn distance(&self) -> f64 { + self.x.hypot(self.y) + } +} + +struct Other; + +impl Other { + fn other(&self) {} +} + +struct Struct { + _phatom: PhantomData, +} + +impl Default for Struct { + fn default() -> Self { + Self { _phatom: PhantomData } + } +} + +impl Struct { + fn method(&self) {} +} + +fn main() { + let point_f64 = Point { x: 1_f64, y: 1_f64 }; + let d = point_f64.distance(); + let point_i32 = Point { x: 1_i32, y: 1_i32 }; + let d = point_i32.distance(); + //~^ ERROR no method named `distance` found for struct `Point + let d = point_i32.other(); + //~^ ERROR no method named `other` found for struct `Point + let v = vec![1_i32, 2, 3]; + v.iter().map(|x| x * x).extend(std::iter::once(100)); + //~^ ERROR no method named `extend` found for struct `Map + let wrapper = Wrapper(true); + wrapper.method(); + //~^ ERROR no method named `method` found for struct `Wrapper + wrapper.other(); + //~^ ERROR no method named `other` found for struct `Wrapper + let boolean = true; + let wrapper = Wrapper2::<'_, _, 3> { x: &boolean }; + wrapper.method(); + //~^ ERROR no method named `method` found for struct `Wrapper2<'_, bool, 3> + wrapper.other(); + //~^ ERROR no method named `other` found for struct `Wrapper2 + let a = vec![1, 2, 3]; + a.not_found(); + //~^ ERROR no method named `not_found` found for struct `Vec + let s = Struct::::default(); + s.method(); + //~^ ERROR the method `method` exists for struct `Struct`, but its trait bounds were not satisfied +} diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr new file mode 100644 index 000000000..f3db56d1d --- /dev/null +++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr @@ -0,0 +1,104 @@ +error[E0599]: no method named `distance` found for struct `Point` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:82:23 + | +LL | struct Point { + | --------------- method `distance` not found for this struct +... +LL | let d = point_i32.distance(); + | ^^^^^^^^ method not found in `Point` + | + = note: the method was found for + - `Point` + +error[E0599]: no method named `other` found for struct `Point` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:84:23 + | +LL | struct Point { + | --------------- method `other` not found for this struct +... +LL | let d = point_i32.other(); + | ^^^^^ method not found in `Point` + +error[E0599]: no method named `extend` found for struct `Map` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:87:29 + | +LL | v.iter().map(|x| x * x).extend(std::iter::once(100)); + | ^^^^^^ method not found in `Map, [closure@method-not-found-generic-arg-elision.rs:87:18]>` + +error[E0599]: no method named `method` found for struct `Wrapper` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:90:13 + | +LL | struct Wrapper(T); + | ----------------- method `method` not found for this struct +... +LL | wrapper.method(); + | ^^^^^^ method not found in `Wrapper` + | + = note: the method was found for + - `Wrapper` + - `Wrapper` + - `Wrapper` + - `Wrapper` + and 2 more types + +error[E0599]: no method named `other` found for struct `Wrapper` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:92:13 + | +LL | struct Wrapper(T); + | ----------------- method `other` not found for this struct +... +LL | wrapper.other(); + | ^^^^^ method not found in `Wrapper` + +error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3>` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:96:13 + | +LL | struct Wrapper2<'a, T, const C: usize> { + | -------------------------------------- method `method` not found for this struct +... +LL | wrapper.method(); + | ^^^^^^ method not found in `Wrapper2<'_, bool, 3>` + | + = note: the method was found for + - `Wrapper2<'a, i8, C>` + - `Wrapper2<'a, i16, C>` + - `Wrapper2<'a, i32, C>` + +error[E0599]: no method named `other` found for struct `Wrapper2` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:98:13 + | +LL | struct Wrapper2<'a, T, const C: usize> { + | -------------------------------------- method `other` not found for this struct +... +LL | wrapper.other(); + | ^^^^^ method not found in `Wrapper2<'_, bool, 3>` + +error[E0599]: no method named `not_found` found for struct `Vec<{integer}>` in the current scope + --> $DIR/method-not-found-generic-arg-elision.rs:101:7 + | +LL | a.not_found(); + | ^^^^^^^^^ method not found in `Vec<{integer}>` + +error[E0599]: the method `method` exists for struct `Struct`, but its trait bounds were not satisfied + --> $DIR/method-not-found-generic-arg-elision.rs:104:7 + | +LL | struct Struct { + | ---------------- method `method` not found for this struct +... +LL | s.method(); + | ^^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `f64: Eq` + `f64: Ord` + --> $DIR/method-not-found-generic-arg-elision.rs:74:36 + | +LL | impl Struct { + | ^^ ^^^ --------- + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/methods/method-on-ambiguous-numeric-type.rs b/tests/ui/methods/method-on-ambiguous-numeric-type.rs new file mode 100644 index 000000000..82f47438d --- /dev/null +++ b/tests/ui/methods/method-on-ambiguous-numeric-type.rs @@ -0,0 +1,32 @@ +// aux-build:macro-in-other-crate.rs + +#[macro_use] extern crate macro_in_other_crate; + +macro_rules! local_mac { + ($ident:ident) => { let $ident = 42; } +} + +fn main() { + let x = 2.0.neg(); + //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}` + + let y = 2.0; + let x = y.neg(); + //~^ ERROR can't call method `neg` on ambiguous numeric type `{float}` + println!("{:?}", x); + + for i in 0..100 { + println!("{}", i.pow(2)); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + } + + local_mac!(local_bar); + local_bar.pow(2); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` +} + +fn qux() { + mac!(bar); + bar.pow(2); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` +} diff --git a/tests/ui/methods/method-on-ambiguous-numeric-type.stderr b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr new file mode 100644 index 000000000..917334116 --- /dev/null +++ b/tests/ui/methods/method-on-ambiguous-numeric-type.stderr @@ -0,0 +1,56 @@ +error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` + --> $DIR/method-on-ambiguous-numeric-type.rs:10:17 + | +LL | let x = 2.0.neg(); + | ^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | let x = 2.0_f32.neg(); + | ~~~~~~~ + +error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` + --> $DIR/method-on-ambiguous-numeric-type.rs:14:15 + | +LL | let x = y.neg(); + | ^^^ + | +help: you must specify a type for this binding, like `f32` + | +LL | let y: f32 = 2.0; + | +++++ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:19:26 + | +LL | for i in 0..100 { + | - you must specify a type for this binding, like `i32` +LL | println!("{}", i.pow(2)); + | ^^^ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:24:15 + | +LL | local_bar.pow(2); + | ^^^ + | +help: you must specify a type for this binding, like `i32` + | +LL | ($ident:ident) => { let $ident: i32 = 42; } + | +++++ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/method-on-ambiguous-numeric-type.rs:30:9 + | +LL | bar.pow(2); + | ^^^ + | +help: you must specify a type for this binding, like `i32` + --> $DIR/auxiliary/macro-in-other-crate.rs:3:35 + | +LL | ($ident:ident) => { let $ident: i32 = 42; } + | +++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/methods/method-path-in-pattern.rs b/tests/ui/methods/method-path-in-pattern.rs new file mode 100644 index 000000000..406453095 --- /dev/null +++ b/tests/ui/methods/method-path-in-pattern.rs @@ -0,0 +1,32 @@ +struct Foo; + +impl Foo { + fn bar(&self) {} +} + +trait MyTrait { + fn trait_bar() {} +} + +impl MyTrait for Foo {} + +fn main() { + match 0u32 { + Foo::bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + } + match 0u32 { + ::bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + } + match 0u32 { + ::trait_bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + } + if let Foo::bar = 0u32 {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + if let ::bar = 0u32 {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + if let Foo::trait_bar = 0u32 {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function +} diff --git a/tests/ui/methods/method-path-in-pattern.stderr b/tests/ui/methods/method-path-in-pattern.stderr new file mode 100644 index 000000000..63c7abe0e --- /dev/null +++ b/tests/ui/methods/method-path-in-pattern.stderr @@ -0,0 +1,39 @@ +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` + --> $DIR/method-path-in-pattern.rs:15:9 + | +LL | Foo::bar => {} + | ^^^^^^^^ not a unit struct, unit variant or constant + +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` + --> $DIR/method-path-in-pattern.rs:19:9 + | +LL | ::bar => {} + | ^^^^^^^^^^ not a unit struct, unit variant or constant + +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar` + --> $DIR/method-path-in-pattern.rs:23:9 + | +LL | ::trait_bar => {} + | ^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` + --> $DIR/method-path-in-pattern.rs:26:12 + | +LL | if let Foo::bar = 0u32 {} + | ^^^^^^^^ not a unit struct, unit variant or constant + +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::bar` + --> $DIR/method-path-in-pattern.rs:28:12 + | +LL | if let ::bar = 0u32 {} + | ^^^^^^^^^^ not a unit struct, unit variant or constant + +error[E0533]: expected unit struct, unit variant or constant, found associated function `Foo::trait_bar` + --> $DIR/method-path-in-pattern.rs:30:12 + | +LL | if let Foo::trait_bar = 0u32 {} + | ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/methods/method-probe-no-guessing-dyn-trait.rs b/tests/ui/methods/method-probe-no-guessing-dyn-trait.rs new file mode 100644 index 000000000..ec41b7117 --- /dev/null +++ b/tests/ui/methods/method-probe-no-guessing-dyn-trait.rs @@ -0,0 +1,60 @@ +// run-pass +// Check that method matching does not make "guesses" depending on +// Deref impls that don't eventually end up being picked. + +use std::ops::Deref; + +// An impl with less derefs will get called over an impl with more derefs, +// so `(t: Foo<_>).my_fn()` will use ` as MyTrait1>::my_fn(t)`, +// and does *not* force the `_` to equal `()`, because the Deref impl +// was *not* used. + +trait MyTrait1 { + fn my_fn(&self) {} +} + +impl MyTrait1 for Foo {} + +struct Foo(#[allow(unused_tuple_struct_fields)] T); + +impl Deref for Foo<()> { + type Target = dyn MyTrait1 + 'static; + fn deref(&self) -> &(dyn MyTrait1 + 'static) { + panic!() + } +} + +// ...but if there is no impl with less derefs, the "guess" will be +// forced, so `(t: Bar<_>).my_fn2()` is `::my_fn2(*t)`, +// and because the deref impl is used, the `_` is forced to equal `u8`. + +trait MyTrait2 { + fn my_fn2(&self) {} +} + +impl MyTrait2 for u32 {} +struct Bar(#[allow(unused_tuple_struct_fields)] T, u32); +impl Deref for Bar { + type Target = dyn MyTrait2 + 'static; + fn deref(&self) -> &(dyn MyTrait2 + 'static) { + &self.1 + } +} + +// actually invoke things + +fn main() { + let mut foo: Option> = None; + let mut bar: Option> = None; + let mut first_iter = true; + loop { + if !first_iter { + foo.as_ref().unwrap().my_fn(); + bar.as_ref().unwrap().my_fn2(); + break; + } + foo = Some(Foo(0)); + bar = Some(Bar(Default::default(), 0)); + first_iter = false; + } +} diff --git a/tests/ui/methods/method-projection.rs b/tests/ui/methods/method-projection.rs new file mode 100644 index 000000000..21d983f19 --- /dev/null +++ b/tests/ui/methods/method-projection.rs @@ -0,0 +1,61 @@ +// run-pass +// Test that we can use method notation to call methods based on a +// projection bound from a trait. Issue #20469. + +trait MakeString { + fn make_string(&self) -> String; +} + +impl MakeString for isize { + fn make_string(&self) -> String { + format!("{}", *self) + } +} + +impl MakeString for usize { + fn make_string(&self) -> String { + format!("{}", *self) + } +} + +trait Foo { + type F: MakeString; + + fn get(&self) -> &Self::F; +} + +fn foo(f: &F) -> String { + f.get().make_string() +} + +struct SomeStruct { + field: isize, +} + +impl Foo for SomeStruct { + type F = isize; + + fn get(&self) -> &isize { + &self.field + } +} + +struct SomeOtherStruct { + field: usize, +} + +impl Foo for SomeOtherStruct { + type F = usize; + + fn get(&self) -> &usize { + &self.field + } +} + +fn main() { + let x = SomeStruct { field: 22 }; + assert_eq!(foo(&x), format!("22")); + + let x = SomeOtherStruct { field: 44 }; + assert_eq!(foo(&x), format!("44")); +} diff --git a/tests/ui/methods/method-recursive-blanket-impl.rs b/tests/ui/methods/method-recursive-blanket-impl.rs new file mode 100644 index 000000000..a2db75b4e --- /dev/null +++ b/tests/ui/methods/method-recursive-blanket-impl.rs @@ -0,0 +1,41 @@ +// run-pass +#![allow(unused_variables)] +#![allow(unused_imports)] +// Test that we don't trigger on the blanket impl for all `&'a T` but +// rather keep autoderefing and trigger on the underlying impl. To +// know not to stop at the blanket, we have to recursively evaluate +// the `T:Foo` bound. + +// pretty-expanded FIXME #23616 + +use std::marker::Sized; + +// Note: this must be generic for the problem to show up +trait Foo
{ + fn foo(&self, a: A); +} + +impl Foo for [u8] { + fn foo(&self, a: u8) {} +} + +impl<'a, A, T> Foo for &'a T where T: Foo { + fn foo(&self, a: A) { + Foo::foo(*self, a) + } +} + +trait Bar { + fn foo(&self); +} + +struct MyType; + +impl Bar for MyType { + fn foo(&self) {} +} + +fn main() { + let mut m = MyType; + (&mut m).foo() +} diff --git a/tests/ui/methods/method-resolvable-path-in-pattern.rs b/tests/ui/methods/method-resolvable-path-in-pattern.rs new file mode 100644 index 000000000..2973800a4 --- /dev/null +++ b/tests/ui/methods/method-resolvable-path-in-pattern.rs @@ -0,0 +1,14 @@ +struct Foo; + +trait MyTrait { + fn trait_bar() {} +} + +impl MyTrait for Foo {} + +fn main() { + match 0u32 { + ::trait_bar => {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + } +} diff --git a/tests/ui/methods/method-resolvable-path-in-pattern.stderr b/tests/ui/methods/method-resolvable-path-in-pattern.stderr new file mode 100644 index 000000000..7c454a9a7 --- /dev/null +++ b/tests/ui/methods/method-resolvable-path-in-pattern.stderr @@ -0,0 +1,9 @@ +error[E0532]: expected unit struct, unit variant or constant, found associated function `MyTrait::trait_bar` + --> $DIR/method-resolvable-path-in-pattern.rs:11:9 + | +LL | ::trait_bar => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/methods/method-self-arg-1.rs b/tests/ui/methods/method-self-arg-1.rs new file mode 100644 index 000000000..f589f20d8 --- /dev/null +++ b/tests/ui/methods/method-self-arg-1.rs @@ -0,0 +1,17 @@ +// Test method calls with self as an argument cannot subvert type checking. + +struct Foo; + +impl Foo { + fn bar(&self) {} +} + +fn main() { + let x = Foo; + Foo::bar(x); //~ ERROR mismatched types + //~| expected `&Foo`, found struct `Foo` + Foo::bar(&42); //~ ERROR mismatched types + //~| expected struct `Foo`, found integer + //~| expected reference `&Foo` + //~| found reference `&{integer}` +} diff --git a/tests/ui/methods/method-self-arg-1.stderr b/tests/ui/methods/method-self-arg-1.stderr new file mode 100644 index 000000000..01fec6fca --- /dev/null +++ b/tests/ui/methods/method-self-arg-1.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/method-self-arg-1.rs:11:14 + | +LL | Foo::bar(x); + | -------- ^ + | | | + | | expected `&Foo`, found struct `Foo` + | | help: consider borrowing here: `&x` + | arguments to this function are incorrect + | +note: associated function defined here + --> $DIR/method-self-arg-1.rs:6:8 + | +LL | fn bar(&self) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/method-self-arg-1.rs:13:14 + | +LL | Foo::bar(&42); + | -------- ^^^ expected struct `Foo`, found integer + | | + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found reference `&{integer}` +note: associated function defined here + --> $DIR/method-self-arg-1.rs:6:8 + | +LL | fn bar(&self) {} + | ^^^ ----- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/methods/method-self-arg-2.rs b/tests/ui/methods/method-self-arg-2.rs new file mode 100644 index 000000000..0f8c048ac --- /dev/null +++ b/tests/ui/methods/method-self-arg-2.rs @@ -0,0 +1,25 @@ +// Test method calls with self as an argument cannot subvert borrow checking. + + + +struct Foo; + +impl Foo { + fn bar(&self) {} + fn baz(&mut self) {} +} + +fn main() { + let mut x = Foo; + let y = &mut x; + Foo::bar(&x); //~ERROR cannot borrow `x` + y.use_mut(); + + let mut x = Foo; + let y = &mut x; + Foo::baz(&mut x); //~ERROR cannot borrow `x` + y.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/methods/method-self-arg-2.stderr b/tests/ui/methods/method-self-arg-2.stderr new file mode 100644 index 000000000..b98f7a786 --- /dev/null +++ b/tests/ui/methods/method-self-arg-2.stderr @@ -0,0 +1,24 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/method-self-arg-2.rs:15:14 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | Foo::bar(&x); + | ^^ immutable borrow occurs here +LL | y.use_mut(); + | ----------- mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/method-self-arg-2.rs:20:14 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +LL | Foo::baz(&mut x); + | ^^^^^^ second mutable borrow occurs here +LL | y.use_mut(); + | ----------- first borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/methods/method-self-arg-aux1.rs b/tests/ui/methods/method-self-arg-aux1.rs new file mode 100644 index 000000000..79b70a17c --- /dev/null +++ b/tests/ui/methods/method-self-arg-aux1.rs @@ -0,0 +1,18 @@ +// run-pass +// Test method calls with self as an argument (cross-crate) + +// aux-build:method_self_arg1.rs +extern crate method_self_arg1; +use method_self_arg1::Foo; + +fn main() { + let x = Foo; + // Test external call. + Foo::bar(&x); + Foo::baz(x); + Foo::qux(Box::new(x)); + + x.foo(&x); + + assert_eq!(method_self_arg1::get_count(), 2*3*3*3*5*5*5*7*7*7); +} diff --git a/tests/ui/methods/method-self-arg-aux2.rs b/tests/ui/methods/method-self-arg-aux2.rs new file mode 100644 index 000000000..16487b54f --- /dev/null +++ b/tests/ui/methods/method-self-arg-aux2.rs @@ -0,0 +1,22 @@ +// run-pass +// Test method calls with self as an argument (cross-crate) + +// aux-build:method_self_arg2.rs +extern crate method_self_arg2; +use method_self_arg2::{Foo, Bar}; + +fn main() { + let x = Foo; + // Test external call. + Bar::foo1(&x); + Bar::foo2(x); + Bar::foo3(Box::new(x)); + + Bar::bar1(&x); + Bar::bar2(x); + Bar::bar3(Box::new(x)); + + x.run_trait(); + + assert_eq!(method_self_arg2::get_count(), 2*2*3*3*5*5*7*7*11*11*13*13*17); +} diff --git a/tests/ui/methods/method-self-arg-trait.rs b/tests/ui/methods/method-self-arg-trait.rs new file mode 100644 index 000000000..ffa7a552b --- /dev/null +++ b/tests/ui/methods/method-self-arg-trait.rs @@ -0,0 +1,67 @@ +// run-pass +// Test method calls with self as an argument + +static mut COUNT: u64 = 1; + +#[derive(Copy, Clone)] +struct Foo; + +trait Bar : Sized { + fn foo1(&self); + fn foo2(self); + fn foo3(self: Box); + + fn bar1(&self) { + unsafe { COUNT *= 7; } + } + fn bar2(self) { + unsafe { COUNT *= 11; } + } + fn bar3(self: Box) { + unsafe { COUNT *= 13; } + } +} + +impl Bar for Foo { + fn foo1(&self) { + unsafe { COUNT *= 2; } + } + + fn foo2(self) { + unsafe { COUNT *= 3; } + } + + fn foo3(self: Box) { + unsafe { COUNT *= 5; } + } +} + +impl Foo { + fn baz(self) { + unsafe { COUNT *= 17; } + // Test internal call. + Bar::foo1(&self); + Bar::foo2(self); + Bar::foo3(Box::new(self)); + + Bar::bar1(&self); + Bar::bar2(self); + Bar::bar3(Box::new(self)); + } +} + +fn main() { + let x = Foo; + // Test external call. + Bar::foo1(&x); + Bar::foo2(x); + Bar::foo3(Box::new(x)); + + Bar::bar1(&x); + Bar::bar2(x); + Bar::bar3(Box::new(x)); + + x.baz(); + + unsafe { assert_eq!(COUNT, 2*2*3*3*5*5*7*7*11*11*13*13*17); } +} diff --git a/tests/ui/methods/method-self-arg.rs b/tests/ui/methods/method-self-arg.rs new file mode 100644 index 000000000..f738fa19c --- /dev/null +++ b/tests/ui/methods/method-self-arg.rs @@ -0,0 +1,46 @@ +// run-pass +// Test method calls with self as an argument + +static mut COUNT: usize = 1; + +#[derive(Copy, Clone)] +struct Foo; + +impl Foo { + fn foo(self, x: &Foo) { + unsafe { COUNT *= 2; } + // Test internal call. + Foo::bar(&self); + Foo::bar(x); + + Foo::baz(self); + Foo::baz(*x); + + Foo::qux(Box::new(self)); + Foo::qux(Box::new(*x)); + } + + fn bar(&self) { + unsafe { COUNT *= 3; } + } + + fn baz(self) { + unsafe { COUNT *= 5; } + } + + fn qux(self: Box) { + unsafe { COUNT *= 7; } + } +} + +fn main() { + let x = Foo; + // Test external call. + Foo::bar(&x); + Foo::baz(x); + Foo::qux(Box::new(x)); + + x.foo(&x); + + unsafe { assert_eq!(COUNT, 2*3*3*3*5*5*5*7*7*7); } +} diff --git a/tests/ui/methods/method-trait-object-with-hrtb.rs b/tests/ui/methods/method-trait-object-with-hrtb.rs new file mode 100644 index 000000000..d1bee676c --- /dev/null +++ b/tests/ui/methods/method-trait-object-with-hrtb.rs @@ -0,0 +1,41 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Check that method probing ObjectCandidate works in the presence of +// auto traits and/or HRTBs. + +mod internal { + pub trait MyObject<'a> { + type Output; + + fn foo(&self) -> Self::Output; + } + + impl<'a> MyObject<'a> for () { + type Output = &'a u32; + + fn foo(&self) -> Self::Output { &4 } + } +} + +fn t1(d: &dyn for<'a> internal::MyObject<'a, Output=&'a u32>) { + d.foo(); +} + +fn t2(d: &dyn internal::MyObject<'static, Output=&'static u32>) { + d.foo(); +} + +fn t3(d: &(dyn for<'a> internal::MyObject<'a, Output=&'a u32> + Sync)) { + d.foo(); +} + +fn t4(d: &(dyn internal::MyObject<'static, Output=&'static u32> + Sync)) { + d.foo(); +} + +fn main() { + t1(&()); + t2(&()); + t3(&()); + t4(&()); +} diff --git a/tests/ui/methods/method-two-trait-defer-resolution-1.rs b/tests/ui/methods/method-two-trait-defer-resolution-1.rs new file mode 100644 index 000000000..b768620cd --- /dev/null +++ b/tests/ui/methods/method-two-trait-defer-resolution-1.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Test that we pick which version of `foo` to run based on the +// type that is (ultimately) inferred for `x`. + + +trait foo { + fn foo(&self) -> i32; +} + +impl foo for Vec { + fn foo(&self) -> i32 {1} +} + +impl foo for Vec { + fn foo(&self) -> i32 {2} +} + +fn call_foo_uint() -> i32 { + let mut x = Vec::new(); + let y = x.foo(); + x.push(0u32); + y +} + +fn call_foo_int() -> i32 { + let mut x = Vec::new(); + let y = x.foo(); + x.push(0i32); + y +} + +fn main() { + assert_eq!(call_foo_uint(), 1); + assert_eq!(call_foo_int(), 2); +} diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.rs b/tests/ui/methods/method-two-trait-defer-resolution-2.rs new file mode 100644 index 000000000..fc5766da9 --- /dev/null +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.rs @@ -0,0 +1,46 @@ +// run-pass +// Test that when we write `x.foo()`, we do not have to know the +// complete type of `x` in order to type-check the method call. In +// this case, we know that `x: Vec<_1>`, but we don't know what type +// `_1` is (because the call to `push` comes later). To pick between +// the impls, we would have to know `_1`, since we have to know +// whether `_1: MyCopy` or `_1 == Box`. However (and this is the +// point of the test), we don't have to pick between the two impls -- +// it is enough to know that `foo` comes from the `Foo` trait. We can +// codegen the call as `Foo::foo(&x)` and let the specific impl get +// chosen later. + +trait Foo { + fn foo(&self) -> isize; +} + +trait MyCopy { fn foo(&self) { } } +impl MyCopy for i32 { } + +impl Foo for Vec { + fn foo(&self) -> isize {1} +} + +impl Foo for Vec> { + fn foo(&self) -> isize {2} +} + +fn call_foo_copy() -> isize { + let mut x = Vec::new(); + let y = x.foo(); + x.push(0_i32); + y +} + +fn call_foo_other() -> isize { + let mut x: Vec<_> = Vec::new(); + let y = x.foo(); + let z: Box = Box::new(0); + x.push(z); + y +} + +fn main() { + assert_eq!(call_foo_copy(), 1); + assert_eq!(call_foo_other(), 2); +} diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs new file mode 100644 index 000000000..d820d2ad0 --- /dev/null +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs @@ -0,0 +1,27 @@ +// run-pass +// Test that we select between traits A and B. To do that, we must +// consider the `Sized` bound. + +// pretty-expanded FIXME #23616 + +trait A { + fn foo(self); +} + +trait B { + fn foo(self); +} + +impl A for *const T { + fn foo(self) {} +} + +impl B for *const [T] { + fn foo(self) {} +} + +fn main() { + let x: [isize; 4] = [1,2,3,4]; + let xptr = &x[..] as *const [isize]; + xptr.foo(); +} diff --git a/tests/ui/methods/method-where-clause.rs b/tests/ui/methods/method-where-clause.rs new file mode 100644 index 000000000..01692abf9 --- /dev/null +++ b/tests/ui/methods/method-where-clause.rs @@ -0,0 +1,34 @@ +// run-pass +// Test that we can use method notation to call methods based on a +// where clause type, and not only type parameters. + + +trait Foo { + fn foo(&self) -> i32; +} + +impl Foo for Option +{ + fn foo(&self) -> i32 { + self.unwrap_or(22) + } +} + +impl Foo for Option +{ + fn foo(&self) -> i32 { + self.unwrap_or(22) as i32 + } +} + +fn check(x: Option) -> (i32, i32) + where Option : Foo +{ + let y: Option = None; + (x.foo(), y.foo()) +} + +fn main() { + assert_eq!(check(Some(23u32)), (23, 22)); + assert_eq!(check(Some(23)), (23, 22)); +} diff --git a/tests/ui/minus-string.rs b/tests/ui/minus-string.rs new file mode 100644 index 000000000..018f0ef9a --- /dev/null +++ b/tests/ui/minus-string.rs @@ -0,0 +1,3 @@ +// error-pattern:cannot apply unary operator `-` to type `String` + +fn main() { -"foo".to_string(); } diff --git a/tests/ui/minus-string.stderr b/tests/ui/minus-string.stderr new file mode 100644 index 000000000..b429ad304 --- /dev/null +++ b/tests/ui/minus-string.stderr @@ -0,0 +1,9 @@ +error[E0600]: cannot apply unary operator `-` to type `String` + --> $DIR/minus-string.rs:3:13 + | +LL | fn main() { -"foo".to_string(); } + | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/mir-dataflow/README.md b/tests/ui/mir-dataflow/README.md new file mode 100644 index 000000000..a3ab14b23 --- /dev/null +++ b/tests/ui/mir-dataflow/README.md @@ -0,0 +1,53 @@ +This directory contains unit tests for the MIR-based dataflow +analysis. + +These unit tests check the dataflow analysis by embedding calls to a +special `rustc_peek` intrinsic within the code, in tandem with an +attribute `#[rustc_mir(rustc_peek_maybe_init)]` (\*). With that +attribute in place, `rustc_peek` calls are a signal to the compiler to +lookup the computed dataflow state for the Lvalue corresponding to the +argument expression being fed to `rustc_peek`. If the dataflow state +for that Lvalue is a 1-bit at that point in the control flow, then no +error is emitted by the compiler at that point; if it is a 0-bit, then +that invocation of `rustc_peek` will emit an error with the message +"rustc_peek: bit not set". + +(\*): Or `#[rustc_mir(rustc_peek_maybe_uninit)]`, and perhaps other +variants in the future. + +The end effect is that one can write unit tests for MIR dataflow that +perform simple-queries of the computed dataflow state, and the tests +should be able to be robust in the face of changes to how MIR is +represented or constructed. + +---- + +Sometimes understanding the dataflow results is difficult without +looking at the actual MIR control-flow graph being processed with the +corresponding GEN and KILL sets. + +For a graphviz-rendering with dataflow annotations, add the attribute +`#[rustc_mir(borrowck_graphviz_postflow="/path/to/suffix.dot")]` to +the function in question. (You can change the content of +`"suffix.dot"` to control the filenames used for the output). This +will generate a separate file for each dataflow analysis, adding a +prefix (corresponding to the name of the analysis) to the filename in +each generated output path. + + * For example, the above attribute will currently cause two files to + be generated: `/path/to/maybe_init_suffix.dot` and + `/path/to/maybe_uninit_suffix.dot`. + + * The generated `.dot` file shows both the computed dataflow results + on *entry* to each block, as well as the gen- and kill-sets that + were so-called "transfer functions" summarizing the effect of each + basic block. + + * (In addition to the `borrowck_graphviz_postflow` attribute-key + noted above, there is also `borrowck_graphviz_preflow`; it has the + same interface and generates the same set of files, but it renders + the dataflow state after building the gen- and kill-sets but + *before* running the dataflow analysis itself, so each entry-set is + just the initial default state for that dataflow analysis. This is + less useful for understanding the error message output in these + tests.) diff --git a/tests/ui/mir-dataflow/def-inits-1.rs b/tests/ui/mir-dataflow/def-inits-1.rs new file mode 100644 index 000000000..30460824a --- /dev/null +++ b/tests/ui/mir-dataflow/def-inits-1.rs @@ -0,0 +1,51 @@ +// General test of maybe_uninits state computed by MIR dataflow. + +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir(rustc_peek_definite_init,stop_after_dataflow)] +fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { + let ret; + // `ret` starts off uninitialized + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set + + // All function formal parameters start off initialized. + + rustc_peek(&x); + rustc_peek(&y); + rustc_peek(&z); + + ret = if test { + ::std::mem::replace(x, y) + } else { + z = y; + z + }; + + // `z` may be uninitialized here. + rustc_peek(&z); //~ ERROR rustc_peek: bit not set + + // `y` is definitely uninitialized here. + rustc_peek(&y); //~ ERROR rustc_peek: bit not set + + // `x` is still (definitely) initialized (replace above is a reborrow). + rustc_peek(&x); + + ::std::mem::drop(x); + + // `x` is *definitely* uninitialized here + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + + // `ret` is now definitely initialized (via `if` above). + rustc_peek(&ret); + + ret +} +fn main() { + foo(true, &mut S(13), S(14), S(15)); + foo(false, &mut S(13), S(14), S(15)); +} diff --git a/tests/ui/mir-dataflow/def-inits-1.stderr b/tests/ui/mir-dataflow/def-inits-1.stderr new file mode 100644 index 000000000..e2bddb54d --- /dev/null +++ b/tests/ui/mir-dataflow/def-inits-1.stderr @@ -0,0 +1,28 @@ +error: rustc_peek: bit not set + --> $DIR/def-inits-1.rs:14:5 + | +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/def-inits-1.rs:30:5 + | +LL | rustc_peek(&z); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/def-inits-1.rs:33:5 + | +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/def-inits-1.rs:41:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 5 previous errors + diff --git a/tests/ui/mir-dataflow/inits-1.rs b/tests/ui/mir-dataflow/inits-1.rs new file mode 100644 index 000000000..8fb1d4bc7 --- /dev/null +++ b/tests/ui/mir-dataflow/inits-1.rs @@ -0,0 +1,53 @@ +// General test of maybe_inits state computed by MIR dataflow. + +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir(rustc_peek_maybe_init,stop_after_dataflow)] +fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { + let ret; + // `ret` starts off uninitialized, so we get an error report here. + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set + + // All function formal parameters start off initialized. + + rustc_peek(&x); + rustc_peek(&y); + rustc_peek(&z); + + ret = if test { + ::std::mem::replace(x, y) + } else { + z = y; + z + }; + + + // `z` may be initialized here. + rustc_peek(&z); + + // `y` is definitely uninitialized here. + rustc_peek(&y); //~ ERROR rustc_peek: bit not set + + // `x` is still (definitely) initialized (replace above is a reborrow). + rustc_peek(&x); + + ::std::mem::drop(x); + + // `x` is *definitely* uninitialized here + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + + // `ret` is now definitely initialized (via `if` above). + rustc_peek(&ret); + + ret +} + +fn main() { + foo(true, &mut S(13), S(14), S(15)); + foo(false, &mut S(13), S(14), S(15)); +} diff --git a/tests/ui/mir-dataflow/inits-1.stderr b/tests/ui/mir-dataflow/inits-1.stderr new file mode 100644 index 000000000..7a00a70af --- /dev/null +++ b/tests/ui/mir-dataflow/inits-1.stderr @@ -0,0 +1,22 @@ +error: rustc_peek: bit not set + --> $DIR/inits-1.rs:14:5 + | +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/inits-1.rs:34:5 + | +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/inits-1.rs:42:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 4 previous errors + diff --git a/tests/ui/mir-dataflow/liveness-enum.rs b/tests/ui/mir-dataflow/liveness-enum.rs new file mode 100644 index 000000000..5eb04ae8c --- /dev/null +++ b/tests/ui/mir-dataflow/liveness-enum.rs @@ -0,0 +1,22 @@ +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; + +#[rustc_mir(rustc_peek_liveness, stop_after_dataflow)] +fn foo() -> Option { + let mut x = None; + + // `x` is live here since it is used in the next statement... + rustc_peek(x); + + dbg!(x); + + // But not here, since it is overwritten below + rustc_peek(x); //~ ERROR rustc_peek: bit not set + + x = Some(4); + + x +} + +fn main() {} diff --git a/tests/ui/mir-dataflow/liveness-enum.stderr b/tests/ui/mir-dataflow/liveness-enum.stderr new file mode 100644 index 000000000..483944d73 --- /dev/null +++ b/tests/ui/mir-dataflow/liveness-enum.stderr @@ -0,0 +1,10 @@ +error: rustc_peek: bit not set + --> $DIR/liveness-enum.rs:15:5 + | +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mir-dataflow/liveness-projection.rs b/tests/ui/mir-dataflow/liveness-projection.rs new file mode 100644 index 000000000..486f31b63 --- /dev/null +++ b/tests/ui/mir-dataflow/liveness-projection.rs @@ -0,0 +1,32 @@ +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; + +#[rustc_mir(rustc_peek_liveness, stop_after_dataflow)] +fn foo() { + { + let mut x: (i32, i32) = (42, 0); + + // Assignment to a projection does not cause `x` to become live + unsafe { rustc_peek(x); } //~ ERROR bit not set + x.1 = 42; + + x = (0, 42); + + // ...but a read from a projection does. + unsafe { rustc_peek(x); } + println!("{}", x.1); + } + + { + let mut x = 42; + + // Derefs are treated like a read of a local even if they are on the LHS of an assignment. + let p = &mut x; + unsafe { rustc_peek(&p); } + *p = 24; + unsafe { rustc_peek(&p); } //~ ERROR bit not set + } +} + +fn main() {} diff --git a/tests/ui/mir-dataflow/liveness-projection.stderr b/tests/ui/mir-dataflow/liveness-projection.stderr new file mode 100644 index 000000000..f9480c880 --- /dev/null +++ b/tests/ui/mir-dataflow/liveness-projection.stderr @@ -0,0 +1,16 @@ +error: rustc_peek: bit not set + --> $DIR/liveness-projection.rs:11:18 + | +LL | unsafe { rustc_peek(x); } + | ^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/liveness-projection.rs:28:18 + | +LL | unsafe { rustc_peek(&p); } + | ^^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 3 previous errors + diff --git a/tests/ui/mir-dataflow/liveness-ptr.rs b/tests/ui/mir-dataflow/liveness-ptr.rs new file mode 100644 index 000000000..786da523a --- /dev/null +++ b/tests/ui/mir-dataflow/liveness-ptr.rs @@ -0,0 +1,28 @@ +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; + +#[rustc_mir(rustc_peek_liveness, stop_after_dataflow)] +fn foo() -> i32 { + let mut x: i32; + let mut p: *const i32; + + x = 0; + + // `x` is live here since it is used in the next statement... + rustc_peek(x); + + p = &x; + + // ... but not here, even while it can be accessed through `p`. + rustc_peek(x); //~ ERROR rustc_peek: bit not set + let tmp = unsafe { *p }; + + x = tmp + 1; + + rustc_peek(x); + + x +} + +fn main() {} diff --git a/tests/ui/mir-dataflow/liveness-ptr.stderr b/tests/ui/mir-dataflow/liveness-ptr.stderr new file mode 100644 index 000000000..858cdbac3 --- /dev/null +++ b/tests/ui/mir-dataflow/liveness-ptr.stderr @@ -0,0 +1,10 @@ +error: rustc_peek: bit not set + --> $DIR/liveness-ptr.rs:18:5 + | +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mir-dataflow/uninits-1.rs b/tests/ui/mir-dataflow/uninits-1.rs new file mode 100644 index 000000000..c2b4284a7 --- /dev/null +++ b/tests/ui/mir-dataflow/uninits-1.rs @@ -0,0 +1,51 @@ +// General test of maybe_uninits state computed by MIR dataflow. + +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)] +fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { + let ret; + // `ret` starts off uninitialized + rustc_peek(&ret); + + // All function formal parameters start off initialized. + + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + rustc_peek(&y); //~ ERROR rustc_peek: bit not set + rustc_peek(&z); //~ ERROR rustc_peek: bit not set + + ret = if test { + ::std::mem::replace(x, y) + } else { + z = y; + z + }; + + // `z` may be uninitialized here. + rustc_peek(&z); + + // `y` is definitely uninitialized here. + rustc_peek(&y); + + // `x` is still (definitely) initialized (replace above is a reborrow). + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + + ::std::mem::drop(x); + + // `x` is *definitely* uninitialized here + rustc_peek(&x); + + // `ret` is now definitely initialized (via `if` above). + rustc_peek(&ret); //~ ERROR rustc_peek: bit not set + + ret +} +fn main() { + foo(true, &mut S(13), S(14), S(15)); + foo(false, &mut S(13), S(14), S(15)); +} diff --git a/tests/ui/mir-dataflow/uninits-1.stderr b/tests/ui/mir-dataflow/uninits-1.stderr new file mode 100644 index 000000000..c52f5ac7b --- /dev/null +++ b/tests/ui/mir-dataflow/uninits-1.stderr @@ -0,0 +1,34 @@ +error: rustc_peek: bit not set + --> $DIR/uninits-1.rs:18:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/uninits-1.rs:19:5 + | +LL | rustc_peek(&y); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/uninits-1.rs:20:5 + | +LL | rustc_peek(&z); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/uninits-1.rs:36:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + +error: rustc_peek: bit not set + --> $DIR/uninits-1.rs:44:5 + | +LL | rustc_peek(&ret); + | ^^^^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 6 previous errors + diff --git a/tests/ui/mir-dataflow/uninits-2.rs b/tests/ui/mir-dataflow/uninits-2.rs new file mode 100644 index 000000000..c584ee74a --- /dev/null +++ b/tests/ui/mir-dataflow/uninits-2.rs @@ -0,0 +1,24 @@ +// General test of maybe_uninits state computed by MIR dataflow. + +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; +use std::mem::{drop, replace}; + +struct S(i32); + +#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)] +fn foo(x: &mut S) { + // `x` is initialized here, so maybe-uninit bit is 0. + + rustc_peek(&x); //~ ERROR rustc_peek: bit not set + + ::std::mem::drop(x); + + // `x` definitely uninitialized here, so maybe-uninit bit is 1. + rustc_peek(&x); +} +fn main() { + foo(&mut S(13)); + foo(&mut S(13)); +} diff --git a/tests/ui/mir-dataflow/uninits-2.stderr b/tests/ui/mir-dataflow/uninits-2.stderr new file mode 100644 index 000000000..0ef954e35 --- /dev/null +++ b/tests/ui/mir-dataflow/uninits-2.stderr @@ -0,0 +1,10 @@ +error: rustc_peek: bit not set + --> $DIR/uninits-2.rs:14:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mir-unpretty.rs b/tests/ui/mir-unpretty.rs new file mode 100644 index 000000000..30620c69f --- /dev/null +++ b/tests/ui/mir-unpretty.rs @@ -0,0 +1,5 @@ +// compile-flags: -Z unpretty=mir + +fn main() { + let x: () = 0; //~ ERROR: mismatched types +} diff --git a/tests/ui/mir-unpretty.stderr b/tests/ui/mir-unpretty.stderr new file mode 100644 index 000000000..3808f8583 --- /dev/null +++ b/tests/ui/mir-unpretty.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/mir-unpretty.rs:4:17 + | +LL | let x: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mir/auxiliary/issue_76375_aux.rs b/tests/ui/mir/auxiliary/issue_76375_aux.rs new file mode 100644 index 000000000..90f4df739 --- /dev/null +++ b/tests/ui/mir/auxiliary/issue_76375_aux.rs @@ -0,0 +1,20 @@ +// edition:2018 +// compile-flags: -Z mir-opt-level=3 + +#[inline(always)] +pub fn copy_prop(s: bool) -> String { + let a = "Hello world!".to_string(); + let b = a; + let c = b; + if s { + c + } else { + String::new() + } +} + +#[inline(always)] +pub fn dest_prop(x: &[u8]) -> &[u8] { + let y = &x[..x.len()]; + y +} diff --git a/tests/ui/mir/auxiliary/mir_external_refs.rs b/tests/ui/mir/auxiliary/mir_external_refs.rs new file mode 100644 index 000000000..9fd58f1d7 --- /dev/null +++ b/tests/ui/mir/auxiliary/mir_external_refs.rs @@ -0,0 +1,17 @@ +pub struct S(pub u8); + +impl S { + pub fn hey() -> u8 { 24 } +} + +pub trait X { + fn hoy(&self) -> u8 { 25 } +} + +impl X for S {} + +pub enum E { + U(u8) +} + +pub fn regular_fn() -> u8 { 12 } diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs new file mode 100644 index 000000000..624b464ec --- /dev/null +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -0,0 +1,25 @@ +// Regression test for issue 81708 and issue 91816 where running a drop +// elaboration on a MIR which failed borrowck lead to an ICE. + +static A: () = { + let a: [String; 1]; + //~^ ERROR destructor of + a[0] = String::new(); + //~^ ERROR destructor of + //~| ERROR binding `a` isn't initialized +}; + +struct B([T; 1]); + +impl B { + pub const fn f(mut self, other: T) -> Self { + let _this = self; + //~^ ERROR destructor of + self.0[0] = other; + //~^ ERROR destructor of + //~| ERROR use of moved value + self + } +} + +fn main() {} diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr new file mode 100644 index 000000000..d96106172 --- /dev/null +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -0,0 +1,65 @@ +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 + | +LL | a[0] = String::new(); + | ^^^^ + | | + | the destructor for this type cannot be evaluated in statics + | value is dropped here + +error[E0493]: destructor of `[String; 1]` cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:5:9 + | +LL | let a: [String; 1]; + | ^ the destructor for this type cannot be evaluated in statics +... +LL | }; + | - value is dropped here + +error[E0381]: used binding `a` isn't initialized + --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 + | +LL | let a: [String; 1]; + | - binding declared here but left uninitialized +LL | +LL | a[0] = String::new(); + | ^^^^ `a` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let a: [String; 1] = todo!(); + | +++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + | +LL | self.0[0] = other; + | ^^^^^^^^^ + | | + | the destructor for this type cannot be evaluated in constant functions + | value is dropped here + +error[E0493]: destructor of `B` cannot be evaluated at compile-time + --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 + | +LL | let _this = self; + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0382]: use of moved value: `self.0` + --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + | +LL | pub const fn f(mut self, other: T) -> Self { + | -------- move occurs because `self` has type `B`, which does not implement the `Copy` trait +LL | let _this = self; + | ---- value moved here +LL | +LL | self.0[0] = other; + | ^^^^^^^^^ value used here after move + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0381, E0382, E0493. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/mir/important-higher-ranked-regions.rs b/tests/ui/mir/important-higher-ranked-regions.rs new file mode 100644 index 000000000..cadfb3b66 --- /dev/null +++ b/tests/ui/mir/important-higher-ranked-regions.rs @@ -0,0 +1,26 @@ +// check-pass +// compile-flags: -Zvalidate-mir + +// This test checks that bivariant parameters are handled correctly +// in the mir. +#![allow(coherence_leak_check)] +trait Trait { + type Assoc; +} + +struct Foo(T) +where + T: Trait; + +impl Trait for for<'a> fn(&'a ()) { + type Assoc = u32; +} +impl Trait for fn(&'static ()) { + type Assoc = String; +} + +fn foo(x: Foo fn(&'a ()), u32>) -> Foo { + x +} + +fn main() {} diff --git a/tests/ui/mir/issue-101844.rs b/tests/ui/mir/issue-101844.rs new file mode 100644 index 000000000..da8a25f5f --- /dev/null +++ b/tests/ui/mir/issue-101844.rs @@ -0,0 +1,73 @@ +// check-pass + +pub trait FirstTrait { + type Item; + type Extra: Extra<(), Error = Self::Item>; +} + +trait SecondTrait { + type Item2; +} + +trait ThirdTrait: SecondTrait { + type Item3; +} + +trait FourthTrait { + type Item4; +} + +impl SecondTrait for First +where + First: FirstTrait, +{ + type Item2 = First::Extra; +} + +impl ThirdTrait for Second +where + Second: SecondTrait, +{ + type Item3 = T; +} + +impl FourthTrait for Third +where + Third: ThirdTrait, +{ + type Item4 = S; +} + +pub trait Extra { + type Error; +} + +struct ImplShoulExist { + _gen: (D, Req), +} + +impl ImplShoulExist +where + D: FourthTrait, + D::Item4: Extra, + >::Error: Into<()>, +{ + fn access_fn(_: D) { + todo!() + } +} + +impl Extra for ImplShoulExist { + type Error = (); +} + +pub fn broken(ms: MS) +where + MS: FirstTrait, + MS::Item: Into<()>, +{ + // Error: Apparently Balance::new doesn't exist during MIR validation + let _ = ImplShoulExist::::access_fn(ms); +} + +fn main() {} diff --git a/tests/ui/mir/issue-102389.rs b/tests/ui/mir/issue-102389.rs new file mode 100644 index 000000000..8b27d5e55 --- /dev/null +++ b/tests/ui/mir/issue-102389.rs @@ -0,0 +1,8 @@ +enum Enum { A, B, C } + +fn func(inbounds: &Enum, array: &[i16; 3]) -> i16 { + array[*inbounds as usize] + //~^ ERROR [E0507] +} + +fn main() {} diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr new file mode 100644 index 000000000..925dc258a --- /dev/null +++ b/tests/ui/mir/issue-102389.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*inbounds` which is behind a shared reference + --> $DIR/issue-102389.rs:4:11 + | +LL | array[*inbounds as usize] + | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/mir/issue-105809.rs b/tests/ui/mir/issue-105809.rs new file mode 100644 index 000000000..57828feef --- /dev/null +++ b/tests/ui/mir/issue-105809.rs @@ -0,0 +1,36 @@ +// Non-regression test ICE from issue #105809 and duplicates. + +// build-pass: the ICE is during codegen +// compile-flags: --edition 2018 -Zmir-opt-level=1 + +use std::{future::Future, pin::Pin}; + +// Create a `T` without affecting analysis like `loop {}`. +fn create() -> T { + loop {} +} + +async fn trivial_future() {} + +struct Connection { + _h: H, +} + +async fn complex_future(conn: &Connection) { + let small_fut = async move { + let _ = conn; + trivial_future().await; + }; + + let mut tuple = (small_fut,); + let (small_fut_again,) = &mut tuple; + let _ = small_fut_again; +} + +fn main() { + let mut fut = complex_future(&Connection { _h: () }); + + let mut cx = create(); + let future = unsafe { Pin::new_unchecked(&mut fut) }; + let _ = future.poll(&mut cx); +} diff --git a/tests/ui/mir/issue-106062.rs b/tests/ui/mir/issue-106062.rs new file mode 100644 index 000000000..621ba566e --- /dev/null +++ b/tests/ui/mir/issue-106062.rs @@ -0,0 +1,26 @@ +// edition:2018 + +use std::{future::Future, marker::PhantomData}; + +fn spawn(future: T) -> PhantomData +where + T: Future, +{ + loop {} +} + +#[derive(Debug)] +struct IncomingServer {} +impl IncomingServer { + async fn connection_handler(handler: impl Sized) -> Result { + //~^ ERROR expected type, found variant `Ok` [E0573] + loop {} + } + async fn spawn(&self, request_handler: impl Sized) { + async move { + spawn(Self::connection_handler(&request_handler)); + }; + } +} + +fn main() {} diff --git a/tests/ui/mir/issue-106062.stderr b/tests/ui/mir/issue-106062.stderr new file mode 100644 index 000000000..2f6524d03 --- /dev/null +++ b/tests/ui/mir/issue-106062.stderr @@ -0,0 +1,16 @@ +error[E0573]: expected type, found variant `Ok` + --> $DIR/issue-106062.rs:15:64 + | +LL | async fn connection_handler(handler: impl Sized) -> Result { + | ^^ not a type + | +help: try using the variant's enum + | +LL | async fn connection_handler(handler: impl Sized) -> Result { + | ~~~~~~~~~~~~~~~~~~~~ +LL | async fn connection_handler(handler: impl Sized) -> Result { + | ~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/mir/issue-29227.rs b/tests/ui/mir/issue-29227.rs new file mode 100644 index 000000000..e9dfc2840 --- /dev/null +++ b/tests/ui/mir/issue-29227.rs @@ -0,0 +1,142 @@ +// run-pass +// ignore-tidy-linelength + +// Regression test for #29227. The problem here was that MIR +// construction for these gigantic match expressions was very +// inefficient. + +pub trait CharExt : Sized + Copy { + fn is_unicode_uppercase_letter(self) -> bool { false } + fn is_unicode_lowercase_letter(self) -> bool { false } + fn is_unicode_titlecase_letter(self) -> bool { false } + fn is_unicode_modifier_letter(self) -> bool { false } + fn is_unicode_other_letter(self) -> bool { false } + fn is_unicode_letter_number(self) -> bool { false } + fn is_unicode_nonspacing_mark(self) -> bool { false } + fn is_unicode_combining_spacing_mark(self) -> bool { false } + fn is_unicode_decimal_number(self) -> bool{ false } + fn is_unicode_connector_punctiation(self) -> bool { false } + fn is_unicode_space_separator(self) -> bool { false } + + fn is_es_identifier_start(self) -> bool { false } + fn is_es_identifier_part(self) -> bool { false } + fn is_es_whitespace(self) -> bool { false } + fn is_es_line_terminator(self) -> bool { false } + + fn is_unicode_letter(self) -> bool { + self.is_unicode_uppercase_letter() + || self.is_unicode_lowercase_letter() + || self.is_unicode_titlecase_letter() + || self.is_unicode_modifier_letter() + || self.is_unicode_modifier_letter() + || self.is_unicode_letter_number() + } + +} + + +macro_rules! match_char_class { + ($thing:expr, $($c:expr),*) => { + match $thing { + $($c)|* => true, + _ => false + } + } +} + +impl CharExt for char { + fn is_unicode_uppercase_letter(self) -> bool { + match_char_class!(self, + '\u{0041}', '\u{0042}', '\u{0043}', '\u{0044}', '\u{0045}', '\u{0046}', '\u{0047}', '\u{0048}', '\u{0049}', '\u{004A}', '\u{004B}', '\u{004C}', '\u{004D}', '\u{004E}', '\u{004F}', '\u{0050}', '\u{0051}', '\u{0052}', '\u{0053}', '\u{0054}', '\u{0055}', '\u{0056}', '\u{0057}', '\u{0058}', '\u{0059}', '\u{005A}', '\u{00C0}', '\u{00C1}', '\u{00C2}', '\u{00C3}', '\u{00C4}', '\u{00C5}', '\u{00C6}', '\u{00C7}', '\u{00C8}', '\u{00C9}', '\u{00CA}', '\u{00CB}', '\u{00CC}', '\u{00CD}', '\u{00CE}', '\u{00CF}', '\u{00D0}', '\u{00D1}', '\u{00D2}', '\u{00D3}', '\u{00D4}', '\u{00D5}', '\u{00D6}', '\u{00D8}', '\u{00D9}', '\u{00DA}', '\u{00DB}', '\u{00DC}', '\u{00DD}', '\u{00DE}', '\u{0100}', '\u{0102}', '\u{0104}', '\u{0106}', '\u{0108}', '\u{010A}', '\u{010C}', '\u{010E}', '\u{0110}', '\u{0112}', '\u{0114}', '\u{0116}', '\u{0118}', '\u{011A}', '\u{011C}', '\u{011E}', '\u{0120}', '\u{0122}', '\u{0124}', '\u{0126}', '\u{0128}', '\u{012A}', '\u{012C}', '\u{012E}', '\u{0130}', '\u{0132}', '\u{0134}', '\u{0136}', '\u{0139}', '\u{013B}', '\u{013D}', '\u{013F}', '\u{0141}', '\u{0143}', '\u{0145}', '\u{0147}', '\u{014A}', '\u{014C}', '\u{014E}', '\u{0150}', '\u{0152}', '\u{0154}', '\u{0156}', '\u{0158}', '\u{015A}', '\u{015C}', '\u{015E}', '\u{0160}', '\u{0162}', '\u{0164}', '\u{0166}', '\u{0168}', '\u{016A}', '\u{016C}', '\u{016E}', '\u{0170}', '\u{0172}', '\u{0174}', '\u{0176}', '\u{0178}', '\u{0179}', '\u{017B}', '\u{017D}', '\u{0181}', '\u{0182}', '\u{0184}', '\u{0186}', '\u{0187}', '\u{0189}', '\u{018A}', '\u{018B}', '\u{018E}', '\u{018F}', '\u{0190}', '\u{0191}', '\u{0193}', '\u{0194}', '\u{0196}', '\u{0197}', '\u{0198}', '\u{019C}', '\u{019D}', '\u{019F}', '\u{01A0}', '\u{01A2}', '\u{01A4}', '\u{01A6}', '\u{01A7}', '\u{01A9}', '\u{01AC}', '\u{01AE}', '\u{01AF}', '\u{01B1}', '\u{01B2}', '\u{01B3}', '\u{01B5}', '\u{01B7}', '\u{01B8}', '\u{01BC}', '\u{01C4}', '\u{01C7}', '\u{01CA}', '\u{01CD}', '\u{01CF}', '\u{01D1}', '\u{01D3}', '\u{01D5}', '\u{01D7}', '\u{01D9}', '\u{01DB}', '\u{01DE}', '\u{01E0}', '\u{01E2}', '\u{01E4}', '\u{01E6}', '\u{01E8}', '\u{01EA}', '\u{01EC}', '\u{01EE}', '\u{01F1}', '\u{01F4}', '\u{01F6}', '\u{01F7}', '\u{01F8}', '\u{01FA}', '\u{01FC}', '\u{01FE}', '\u{0200}', '\u{0202}', '\u{0204}', '\u{0206}', '\u{0208}', '\u{020A}', '\u{020C}', '\u{020E}', '\u{0210}', '\u{0212}', '\u{0214}', '\u{0216}', '\u{0218}', '\u{021A}', '\u{021C}', '\u{021E}', '\u{0220}', '\u{0222}', '\u{0224}', '\u{0226}', '\u{0228}', '\u{022A}', '\u{022C}', '\u{022E}', '\u{0230}', '\u{0232}', '\u{023A}', '\u{023B}', '\u{023D}', '\u{023E}', '\u{0241}', '\u{0243}', '\u{0244}', '\u{0245}', '\u{0246}', '\u{0248}', '\u{024A}', '\u{024C}', '\u{024E}', '\u{0370}', '\u{0372}', '\u{0376}', '\u{0386}', '\u{0388}', '\u{0389}', '\u{038A}', '\u{038C}', '\u{038E}', '\u{038F}', '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}', '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}', '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}', '\u{03AA}', '\u{03AB}', '\u{03CF}', '\u{03D2}', '\u{03D3}', '\u{03D4}', '\u{03D8}', '\u{03DA}', '\u{03DC}', '\u{03DE}', '\u{03E0}', '\u{03E2}', '\u{03E4}', '\u{03E6}', '\u{03E8}', '\u{03EA}', '\u{03EC}', '\u{03EE}', '\u{03F4}', '\u{03F7}', '\u{03F9}', '\u{03FA}', '\u{03FD}', '\u{03FE}', '\u{03FF}', '\u{0400}', '\u{0401}', '\u{0402}', '\u{0403}', '\u{0404}', '\u{0405}', '\u{0406}', '\u{0407}', '\u{0408}', '\u{0409}', '\u{040A}', '\u{040B}', '\u{040C}', '\u{040D}', '\u{040E}', '\u{040F}', '\u{0410}', '\u{0411}', '\u{0412}', '\u{0413}', '\u{0414}', '\u{0415}', '\u{0416}', '\u{0417}', '\u{0418}', '\u{0419}', '\u{041A}', '\u{041B}', '\u{041C}', '\u{041D}', '\u{041E}', '\u{041F}', '\u{0420}', '\u{0421}', '\u{0422}', '\u{0423}', '\u{0424}', '\u{0425}', '\u{0426}', '\u{0427}', '\u{0428}', '\u{0429}', '\u{042A}', '\u{042B}', '\u{042C}', '\u{042D}', '\u{042E}', '\u{042F}', '\u{0460}', '\u{0462}', '\u{0464}', '\u{0466}', '\u{0468}', '\u{046A}', '\u{046C}', '\u{046E}', '\u{0470}', '\u{0472}', '\u{0474}', '\u{0476}', '\u{0478}', '\u{047A}', '\u{047C}', '\u{047E}', '\u{0480}', '\u{048A}', '\u{048C}', '\u{048E}', '\u{0490}', '\u{0492}', '\u{0494}', '\u{0496}', '\u{0498}', '\u{049A}', '\u{049C}', '\u{049E}', '\u{04A0}', '\u{04A2}', '\u{04A4}', '\u{04A6}', '\u{04A8}', '\u{04AA}', '\u{04AC}', '\u{04AE}', '\u{04B0}', '\u{04B2}', '\u{04B4}', '\u{04B6}', '\u{04B8}', '\u{04BA}', '\u{04BC}', '\u{04BE}', '\u{04C0}', '\u{04C1}', '\u{04C3}', '\u{04C5}', '\u{04C7}', '\u{04C9}', '\u{04CB}', '\u{04CD}', '\u{04D0}', '\u{04D2}', '\u{04D4}', '\u{04D6}', '\u{04D8}', '\u{04DA}', '\u{04DC}', '\u{04DE}', '\u{04E0}', '\u{04E2}', '\u{04E4}', '\u{04E6}', '\u{04E8}', '\u{04EA}', '\u{04EC}', '\u{04EE}', '\u{04F0}', '\u{04F2}', '\u{04F4}', '\u{04F6}', '\u{04F8}', '\u{04FA}', '\u{04FC}', '\u{04FE}', '\u{0500}', '\u{0502}', '\u{0504}', '\u{0506}', '\u{0508}', '\u{050A}', '\u{050C}', '\u{050E}', '\u{0510}', '\u{0512}', '\u{0514}', '\u{0516}', '\u{0518}', '\u{051A}', '\u{051C}', '\u{051E}', '\u{0520}', '\u{0522}', '\u{0531}', '\u{0532}', '\u{0533}', '\u{0534}', '\u{0535}', '\u{0536}', '\u{0537}', '\u{0538}', '\u{0539}', '\u{053A}', '\u{053B}', '\u{053C}', '\u{053D}', '\u{053E}', '\u{053F}', '\u{0540}', '\u{0541}', '\u{0542}', '\u{0543}', '\u{0544}', '\u{0545}', '\u{0546}', '\u{0547}', '\u{0548}', '\u{0549}', '\u{054A}', '\u{054B}', '\u{054C}', '\u{054D}', '\u{054E}', '\u{054F}', '\u{0550}', '\u{0551}', '\u{0552}', '\u{0553}', '\u{0554}', '\u{0555}', '\u{0556}', '\u{10A0}', '\u{10A1}', '\u{10A2}', '\u{10A3}', '\u{10A4}', '\u{10A5}', '\u{10A6}', '\u{10A7}', '\u{10A8}', '\u{10A9}', '\u{10AA}', '\u{10AB}', '\u{10AC}', '\u{10AD}', '\u{10AE}', '\u{10AF}', '\u{10B0}', '\u{10B1}', '\u{10B2}', '\u{10B3}', '\u{10B4}', '\u{10B5}', '\u{10B6}', '\u{10B7}', '\u{10B8}', '\u{10B9}', '\u{10BA}', '\u{10BB}', '\u{10BC}', '\u{10BD}', '\u{10BE}', '\u{10BF}', '\u{10C0}', '\u{10C1}', '\u{10C2}', '\u{10C3}', '\u{10C4}', '\u{10C5}', '\u{1E00}', '\u{1E02}', '\u{1E04}', '\u{1E06}', '\u{1E08}', '\u{1E0A}', '\u{1E0C}', '\u{1E0E}', '\u{1E10}', '\u{1E12}', '\u{1E14}', '\u{1E16}', '\u{1E18}', '\u{1E1A}', '\u{1E1C}', '\u{1E1E}', '\u{1E20}', '\u{1E22}', '\u{1E24}', '\u{1E26}', '\u{1E28}', '\u{1E2A}', '\u{1E2C}', '\u{1E2E}', '\u{1E30}', '\u{1E32}', '\u{1E34}', '\u{1E36}', '\u{1E38}', '\u{1E3A}', '\u{1E3C}', '\u{1E3E}', '\u{1E40}', '\u{1E42}', '\u{1E44}', '\u{1E46}', '\u{1E48}', '\u{1E4A}', '\u{1E4C}', '\u{1E4E}', '\u{1E50}', '\u{1E52}', '\u{1E54}', '\u{1E56}', '\u{1E58}', '\u{1E5A}', '\u{1E5C}', '\u{1E5E}', '\u{1E60}', '\u{1E62}', '\u{1E64}', '\u{1E66}', '\u{1E68}', '\u{1E6A}', '\u{1E6C}', '\u{1E6E}', '\u{1E70}', '\u{1E72}', '\u{1E74}', '\u{1E76}', '\u{1E78}', '\u{1E7A}', '\u{1E7C}', '\u{1E7E}', '\u{1E80}', '\u{1E82}', '\u{1E84}', '\u{1E86}', '\u{1E88}', '\u{1E8A}', '\u{1E8C}', '\u{1E8E}', '\u{1E90}', '\u{1E92}', '\u{1E94}', '\u{1E9E}', '\u{1EA0}', '\u{1EA2}', '\u{1EA4}', '\u{1EA6}', '\u{1EA8}', '\u{1EAA}', '\u{1EAC}', '\u{1EAE}', '\u{1EB0}', '\u{1EB2}', '\u{1EB4}', '\u{1EB6}', '\u{1EB8}', '\u{1EBA}', '\u{1EBC}', '\u{1EBE}', '\u{1EC0}', '\u{1EC2}', '\u{1EC4}', '\u{1EC6}', '\u{1EC8}', '\u{1ECA}', '\u{1ECC}', '\u{1ECE}', '\u{1ED0}', '\u{1ED2}', '\u{1ED4}', '\u{1ED6}', '\u{1ED8}', '\u{1EDA}', '\u{1EDC}', '\u{1EDE}', '\u{1EE0}', '\u{1EE2}', '\u{1EE4}', '\u{1EE6}', '\u{1EE8}', '\u{1EEA}', '\u{1EEC}', '\u{1EEE}', '\u{1EF0}', '\u{1EF2}', '\u{1EF4}', '\u{1EF6}', '\u{1EF8}', '\u{1EFA}', '\u{1EFC}', '\u{1EFE}', '\u{1F08}', '\u{1F09}', '\u{1F0A}', '\u{1F0B}', '\u{1F0C}', '\u{1F0D}', '\u{1F0E}', '\u{1F0F}', '\u{1F18}', '\u{1F19}', '\u{1F1A}', '\u{1F1B}', '\u{1F1C}', '\u{1F1D}', '\u{1F28}', '\u{1F29}', '\u{1F2A}', '\u{1F2B}', '\u{1F2C}', '\u{1F2D}', '\u{1F2E}', '\u{1F2F}', '\u{1F38}', '\u{1F39}', '\u{1F3A}', '\u{1F3B}', '\u{1F3C}', '\u{1F3D}', '\u{1F3E}', '\u{1F3F}', '\u{1F48}', '\u{1F49}', '\u{1F4A}', '\u{1F4B}', '\u{1F4C}', '\u{1F4D}', '\u{1F59}', '\u{1F5B}', '\u{1F5D}', '\u{1F5F}', '\u{1F68}', '\u{1F69}', '\u{1F6A}', '\u{1F6B}', '\u{1F6C}', '\u{1F6D}', '\u{1F6E}', '\u{1F6F}', '\u{1FB8}', '\u{1FB9}', '\u{1FBA}', '\u{1FBB}', '\u{1FC8}', '\u{1FC9}', '\u{1FCA}', '\u{1FCB}', '\u{1FD8}', '\u{1FD9}', '\u{1FDA}', '\u{1FDB}', '\u{1FE8}', '\u{1FE9}', '\u{1FEA}', '\u{1FEB}', '\u{1FEC}', '\u{1FF8}', '\u{1FF9}', '\u{1FFA}', '\u{1FFB}', '\u{2102}', '\u{2107}', '\u{210B}', '\u{210C}', '\u{210D}', '\u{2110}', '\u{2111}', '\u{2112}', '\u{2115}', '\u{2119}', '\u{211A}', '\u{211B}', '\u{211C}', '\u{211D}', '\u{2124}', '\u{2126}', '\u{2128}', '\u{212A}', '\u{212B}', '\u{212C}', '\u{212D}', '\u{2130}', '\u{2131}', '\u{2132}', '\u{2133}', '\u{213E}', '\u{213F}', '\u{2145}', '\u{2183}', '\u{2C00}', '\u{2C01}', '\u{2C02}', '\u{2C03}', '\u{2C04}', '\u{2C05}', '\u{2C06}', '\u{2C07}', '\u{2C08}', '\u{2C09}', '\u{2C0A}', '\u{2C0B}', '\u{2C0C}', '\u{2C0D}', '\u{2C0E}', '\u{2C0F}', '\u{2C10}', '\u{2C11}', '\u{2C12}', '\u{2C13}', '\u{2C14}', '\u{2C15}', '\u{2C16}', '\u{2C17}', '\u{2C18}', '\u{2C19}', '\u{2C1A}', '\u{2C1B}', '\u{2C1C}', '\u{2C1D}', '\u{2C1E}', '\u{2C1F}', '\u{2C20}', '\u{2C21}', '\u{2C22}', '\u{2C23}', '\u{2C24}', '\u{2C25}', '\u{2C26}', '\u{2C27}', '\u{2C28}', '\u{2C29}', '\u{2C2A}', '\u{2C2B}', '\u{2C2C}', '\u{2C2D}', '\u{2C2E}', '\u{2C60}', '\u{2C62}', '\u{2C63}', '\u{2C64}', '\u{2C67}', '\u{2C69}', '\u{2C6B}', '\u{2C6D}', '\u{2C6E}', '\u{2C6F}', '\u{2C72}', '\u{2C75}', '\u{2C80}', '\u{2C82}', '\u{2C84}', '\u{2C86}', '\u{2C88}', '\u{2C8A}', '\u{2C8C}', '\u{2C8E}', '\u{2C90}', '\u{2C92}', '\u{2C94}', '\u{2C96}', '\u{2C98}', '\u{2C9A}', '\u{2C9C}', '\u{2C9E}', '\u{2CA0}', '\u{2CA2}', '\u{2CA4}', '\u{2CA6}', '\u{2CA8}', '\u{2CAA}', '\u{2CAC}', '\u{2CAE}', '\u{2CB0}', '\u{2CB2}', '\u{2CB4}', '\u{2CB6}', '\u{2CB8}', '\u{2CBA}', '\u{2CBC}', '\u{2CBE}', '\u{2CC0}', '\u{2CC2}', '\u{2CC4}', '\u{2CC6}', '\u{2CC8}', '\u{2CCA}', '\u{2CCC}', '\u{2CCE}', '\u{2CD0}', '\u{2CD2}', '\u{2CD4}', '\u{2CD6}', '\u{2CD8}', '\u{2CDA}', '\u{2CDC}', '\u{2CDE}', '\u{2CE0}', '\u{2CE2}', '\u{A640}', '\u{A642}', '\u{A644}', '\u{A646}', '\u{A648}', '\u{A64A}', '\u{A64C}', '\u{A64E}', '\u{A650}', '\u{A652}', '\u{A654}', '\u{A656}', '\u{A658}', '\u{A65A}', '\u{A65C}', '\u{A65E}', '\u{A662}', '\u{A664}', '\u{A666}', '\u{A668}', '\u{A66A}', '\u{A66C}', '\u{A680}', '\u{A682}', '\u{A684}', '\u{A686}', '\u{A688}', '\u{A68A}', '\u{A68C}', '\u{A68E}', '\u{A690}', '\u{A692}', '\u{A694}', '\u{A696}', '\u{A722}', '\u{A724}', '\u{A726}', '\u{A728}', '\u{A72A}', '\u{A72C}', '\u{A72E}', '\u{A732}', '\u{A734}', '\u{A736}', '\u{A738}', '\u{A73A}', '\u{A73C}', '\u{A73E}', '\u{A740}', '\u{A742}', '\u{A744}', '\u{A746}', '\u{A748}', '\u{A74A}', '\u{A74C}', '\u{A74E}', '\u{A750}', '\u{A752}', '\u{A754}', '\u{A756}', '\u{A758}', '\u{A75A}', '\u{A75C}', '\u{A75E}', '\u{A760}', '\u{A762}', '\u{A764}', '\u{A766}', '\u{A768}', '\u{A76A}', '\u{A76C}', '\u{A76E}', '\u{A779}', '\u{A77B}', '\u{A77D}', '\u{A77E}', '\u{A780}', '\u{A782}', '\u{A784}', '\u{A786}', '\u{A78B}', '\u{FF21}', '\u{FF22}', '\u{FF23}', '\u{FF24}', '\u{FF25}', '\u{FF26}', '\u{FF27}', '\u{FF28}', '\u{FF29}', '\u{FF2A}', '\u{FF2B}', '\u{FF2C}', '\u{FF2D}', '\u{FF2E}', '\u{FF2F}', '\u{FF30}', '\u{FF31}', '\u{FF32}', '\u{FF33}', '\u{FF34}', '\u{FF35}', '\u{FF36}', '\u{FF37}', '\u{FF38}', '\u{FF39}', '\u{FF3A}') + } + + fn is_unicode_lowercase_letter(self) -> bool { + match_char_class!(self, + '\u{0061}', '\u{0062}', '\u{0063}', '\u{0064}', '\u{0065}', '\u{0066}', '\u{0067}', '\u{0068}', '\u{0069}', '\u{006A}', '\u{006B}', '\u{006C}', '\u{006D}', '\u{006E}', '\u{006F}', '\u{0070}', '\u{0071}', '\u{0072}', '\u{0073}', '\u{0074}', '\u{0075}', '\u{0076}', '\u{0077}', '\u{0078}', '\u{0079}', '\u{007A}', '\u{00AA}', '\u{00B5}', '\u{00BA}', '\u{00DF}', '\u{00E0}', '\u{00E1}', '\u{00E2}', '\u{00E3}', '\u{00E4}', '\u{00E5}', '\u{00E6}', '\u{00E7}', '\u{00E8}', '\u{00E9}', '\u{00EA}', '\u{00EB}', '\u{00EC}', '\u{00ED}', '\u{00EE}', '\u{00EF}', '\u{00F0}', '\u{00F1}', '\u{00F2}', '\u{00F3}', '\u{00F4}', '\u{00F5}', '\u{00F6}', '\u{00F8}', '\u{00F9}', '\u{00FA}', '\u{00FB}', '\u{00FC}', '\u{00FD}', '\u{00FE}', '\u{00FF}', '\u{0101}', '\u{0103}', '\u{0105}', '\u{0107}', '\u{0109}', '\u{010B}', '\u{010D}', '\u{010F}', '\u{0111}', '\u{0113}', '\u{0115}', '\u{0117}', '\u{0119}', '\u{011B}', '\u{011D}', '\u{011F}', '\u{0121}', '\u{0123}', '\u{0125}', '\u{0127}', '\u{0129}', '\u{012B}', '\u{012D}', '\u{012F}', '\u{0131}', '\u{0133}', '\u{0135}', '\u{0137}', '\u{0138}', '\u{013A}', '\u{013C}', '\u{013E}', '\u{0140}', '\u{0142}', '\u{0144}', '\u{0146}', '\u{0148}', '\u{0149}', '\u{014B}', '\u{014D}', '\u{014F}', '\u{0151}', '\u{0153}', '\u{0155}', '\u{0157}', '\u{0159}', '\u{015B}', '\u{015D}', '\u{015F}', '\u{0161}', '\u{0163}', '\u{0165}', '\u{0167}', '\u{0169}', '\u{016B}', '\u{016D}', '\u{016F}', '\u{0171}', '\u{0173}', '\u{0175}', '\u{0177}', '\u{017A}', '\u{017C}', '\u{017E}', '\u{017F}', '\u{0180}', '\u{0183}', '\u{0185}', '\u{0188}', '\u{018C}', '\u{018D}', '\u{0192}', '\u{0195}', '\u{0199}', '\u{019A}', '\u{019B}', '\u{019E}', '\u{01A1}', '\u{01A3}', '\u{01A5}', '\u{01A8}', '\u{01AA}', '\u{01AB}', '\u{01AD}', '\u{01B0}', '\u{01B4}', '\u{01B6}', '\u{01B9}', '\u{01BA}', '\u{01BD}', '\u{01BE}', '\u{01BF}', '\u{01C6}', '\u{01C9}', '\u{01CC}', '\u{01CE}', '\u{01D0}', '\u{01D2}', '\u{01D4}', '\u{01D6}', '\u{01D8}', '\u{01DA}', '\u{01DC}', '\u{01DD}', '\u{01DF}', '\u{01E1}', '\u{01E3}', '\u{01E5}', '\u{01E7}', '\u{01E9}', '\u{01EB}', '\u{01ED}', '\u{01EF}', '\u{01F0}', '\u{01F3}', '\u{01F5}', '\u{01F9}', '\u{01FB}', '\u{01FD}', '\u{01FF}', '\u{0201}', '\u{0203}', '\u{0205}', '\u{0207}', '\u{0209}', '\u{020B}', '\u{020D}', '\u{020F}', '\u{0211}', '\u{0213}', '\u{0215}', '\u{0217}', '\u{0219}', '\u{021B}', '\u{021D}', '\u{021F}', '\u{0221}', '\u{0223}', '\u{0225}', '\u{0227}', '\u{0229}', '\u{022B}', '\u{022D}', '\u{022F}', '\u{0231}', '\u{0233}', '\u{0234}', '\u{0235}', '\u{0236}', '\u{0237}', '\u{0238}', '\u{0239}', '\u{023C}', '\u{023F}', '\u{0240}', '\u{0242}', '\u{0247}', '\u{0249}', '\u{024B}', '\u{024D}', '\u{024F}', '\u{0250}', '\u{0251}', '\u{0252}', '\u{0253}', '\u{0254}', '\u{0255}', '\u{0256}', '\u{0257}', '\u{0258}', '\u{0259}', '\u{025A}', '\u{025B}', '\u{025C}', '\u{025D}', '\u{025E}', '\u{025F}', '\u{0260}', '\u{0261}', '\u{0262}', '\u{0263}', '\u{0264}', '\u{0265}', '\u{0266}', '\u{0267}', '\u{0268}', '\u{0269}', '\u{026A}', '\u{026B}', '\u{026C}', '\u{026D}', '\u{026E}', '\u{026F}', '\u{0270}', '\u{0271}', '\u{0272}', '\u{0273}', '\u{0274}', '\u{0275}', '\u{0276}', '\u{0277}', '\u{0278}', '\u{0279}', '\u{027A}', '\u{027B}', '\u{027C}', '\u{027D}', '\u{027E}', '\u{027F}', '\u{0280}', '\u{0281}', '\u{0282}', '\u{0283}', '\u{0284}', '\u{0285}', '\u{0286}', '\u{0287}', '\u{0288}', '\u{0289}', '\u{028A}', '\u{028B}', '\u{028C}', '\u{028D}', '\u{028E}', '\u{028F}', '\u{0290}', '\u{0291}', '\u{0292}', '\u{0293}', '\u{0295}', '\u{0296}', '\u{0297}', '\u{0298}', '\u{0299}', '\u{029A}', '\u{029B}', '\u{029C}', '\u{029D}', '\u{029E}', '\u{029F}', '\u{02A0}', '\u{02A1}', '\u{02A2}', '\u{02A3}', '\u{02A4}', '\u{02A5}', '\u{02A6}', '\u{02A7}', '\u{02A8}', '\u{02A9}', '\u{02AA}', '\u{02AB}', '\u{02AC}', '\u{02AD}', '\u{02AE}', '\u{02AF}', '\u{0371}', '\u{0373}', '\u{0377}', '\u{037B}', '\u{037C}', '\u{037D}', '\u{0390}', '\u{03AC}', '\u{03AD}', '\u{03AE}', '\u{03AF}', '\u{03B0}', '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}', '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}', '\u{03C1}', '\u{03C2}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}', '\u{03CA}', '\u{03CB}', '\u{03CC}', '\u{03CD}', '\u{03CE}', '\u{03D0}', '\u{03D1}', '\u{03D5}', '\u{03D6}', '\u{03D7}', '\u{03D9}', '\u{03DB}', '\u{03DD}', '\u{03DF}', '\u{03E1}', '\u{03E3}', '\u{03E5}', '\u{03E7}', '\u{03E9}', '\u{03EB}', '\u{03ED}', '\u{03EF}', '\u{03F0}', '\u{03F1}', '\u{03F2}', '\u{03F3}', '\u{03F5}', '\u{03F8}', '\u{03FB}', '\u{03FC}', '\u{0430}', '\u{0431}', '\u{0432}', '\u{0433}', '\u{0434}', '\u{0435}', '\u{0436}', '\u{0437}', '\u{0438}', '\u{0439}', '\u{043A}', '\u{043B}', '\u{043C}', '\u{043D}', '\u{043E}', '\u{043F}', '\u{0440}', '\u{0441}', '\u{0442}', '\u{0443}', '\u{0444}', '\u{0445}', '\u{0446}', '\u{0447}', '\u{0448}', '\u{0449}', '\u{044A}', '\u{044B}', '\u{044C}', '\u{044D}', '\u{044E}', '\u{044F}', '\u{0450}', '\u{0451}', '\u{0452}', '\u{0453}', '\u{0454}', '\u{0455}', '\u{0456}', '\u{0457}', '\u{0458}', '\u{0459}', '\u{045A}', '\u{045B}', '\u{045C}', '\u{045D}', '\u{045E}', '\u{045F}', '\u{0461}', '\u{0463}', '\u{0465}', '\u{0467}', '\u{0469}', '\u{046B}', '\u{046D}', '\u{046F}', '\u{0471}', '\u{0473}', '\u{0475}', '\u{0477}', '\u{0479}', '\u{047B}', '\u{047D}', '\u{047F}', '\u{0481}', '\u{048B}', '\u{048D}', '\u{048F}', '\u{0491}', '\u{0493}', '\u{0495}', '\u{0497}', '\u{0499}', '\u{049B}', '\u{049D}', '\u{049F}', '\u{04A1}', '\u{04A3}', '\u{04A5}', '\u{04A7}', '\u{04A9}', '\u{04AB}', '\u{04AD}', '\u{04AF}', '\u{04B1}', '\u{04B3}', '\u{04B5}', '\u{04B7}', '\u{04B9}', '\u{04BB}', '\u{04BD}', '\u{04BF}', '\u{04C2}', '\u{04C4}', '\u{04C6}', '\u{04C8}', '\u{04CA}', '\u{04CC}', '\u{04CE}', '\u{04CF}', '\u{04D1}', '\u{04D3}', '\u{04D5}', '\u{04D7}', '\u{04D9}', '\u{04DB}', '\u{04DD}', '\u{04DF}', '\u{04E1}', '\u{04E3}', '\u{04E5}', '\u{04E7}', '\u{04E9}', '\u{04EB}', '\u{04ED}', '\u{04EF}', '\u{04F1}', '\u{04F3}', '\u{04F5}', '\u{04F7}', '\u{04F9}', '\u{04FB}', '\u{04FD}', '\u{04FF}', '\u{0501}', '\u{0503}', '\u{0505}', '\u{0507}', '\u{0509}', '\u{050B}', '\u{050D}', '\u{050F}', '\u{0511}', '\u{0513}', '\u{0515}', '\u{0517}', '\u{0519}', '\u{051B}', '\u{051D}', '\u{051F}', '\u{0521}', '\u{0523}', '\u{0561}', '\u{0562}', '\u{0563}', '\u{0564}', '\u{0565}', '\u{0566}', '\u{0567}', '\u{0568}', '\u{0569}', '\u{056A}', '\u{056B}', '\u{056C}', '\u{056D}', '\u{056E}', '\u{056F}', '\u{0570}', '\u{0571}', '\u{0572}', '\u{0573}', '\u{0574}', '\u{0575}', '\u{0576}', '\u{0577}', '\u{0578}', '\u{0579}', '\u{057A}', '\u{057B}', '\u{057C}', '\u{057D}', '\u{057E}', '\u{057F}', '\u{0580}', '\u{0581}', '\u{0582}', '\u{0583}', '\u{0584}', '\u{0585}', '\u{0586}', '\u{0587}', '\u{1D00}', '\u{1D01}', '\u{1D02}', '\u{1D03}', '\u{1D04}', '\u{1D05}', '\u{1D06}', '\u{1D07}', '\u{1D08}', '\u{1D09}', '\u{1D0A}', '\u{1D0B}', '\u{1D0C}', '\u{1D0D}', '\u{1D0E}', '\u{1D0F}', '\u{1D10}', '\u{1D11}', '\u{1D12}', '\u{1D13}', '\u{1D14}', '\u{1D15}', '\u{1D16}', '\u{1D17}', '\u{1D18}', '\u{1D19}', '\u{1D1A}', '\u{1D1B}', '\u{1D1C}', '\u{1D1D}', '\u{1D1E}', '\u{1D1F}', '\u{1D20}', '\u{1D21}', '\u{1D22}', '\u{1D23}', '\u{1D24}', '\u{1D25}', '\u{1D26}', '\u{1D27}', '\u{1D28}', '\u{1D29}', '\u{1D2A}', '\u{1D2B}', '\u{1D62}', '\u{1D63}', '\u{1D64}', '\u{1D65}', '\u{1D66}', '\u{1D67}', '\u{1D68}', '\u{1D69}', '\u{1D6A}', '\u{1D6B}', '\u{1D6C}', '\u{1D6D}', '\u{1D6E}', '\u{1D6F}', '\u{1D70}', '\u{1D71}', '\u{1D72}', '\u{1D73}', '\u{1D74}', '\u{1D75}', '\u{1D76}', '\u{1D77}', '\u{1D79}', '\u{1D7A}', '\u{1D7B}', '\u{1D7C}', '\u{1D7D}', '\u{1D7E}', '\u{1D7F}', '\u{1D80}', '\u{1D81}', '\u{1D82}', '\u{1D83}', '\u{1D84}', '\u{1D85}', '\u{1D86}', '\u{1D87}', '\u{1D88}', '\u{1D89}', '\u{1D8A}', '\u{1D8B}', '\u{1D8C}', '\u{1D8D}', '\u{1D8E}', '\u{1D8F}', '\u{1D90}', '\u{1D91}', '\u{1D92}', '\u{1D93}', '\u{1D94}', '\u{1D95}', '\u{1D96}', '\u{1D97}', '\u{1D98}', '\u{1D99}', '\u{1D9A}', '\u{1E01}', '\u{1E03}', '\u{1E05}', '\u{1E07}', '\u{1E09}', '\u{1E0B}', '\u{1E0D}', '\u{1E0F}', '\u{1E11}', '\u{1E13}', '\u{1E15}', '\u{1E17}', '\u{1E19}', '\u{1E1B}', '\u{1E1D}', '\u{1E1F}', '\u{1E21}', '\u{1E23}', '\u{1E25}', '\u{1E27}', '\u{1E29}', '\u{1E2B}', '\u{1E2D}', '\u{1E2F}', '\u{1E31}', '\u{1E33}', '\u{1E35}', '\u{1E37}', '\u{1E39}', '\u{1E3B}', '\u{1E3D}', '\u{1E3F}', '\u{1E41}', '\u{1E43}', '\u{1E45}', '\u{1E47}', '\u{1E49}', '\u{1E4B}', '\u{1E4D}', '\u{1E4F}', '\u{1E51}', '\u{1E53}', '\u{1E55}', '\u{1E57}', '\u{1E59}', '\u{1E5B}', '\u{1E5D}', '\u{1E5F}', '\u{1E61}', '\u{1E63}', '\u{1E65}', '\u{1E67}', '\u{1E69}', '\u{1E6B}', '\u{1E6D}', '\u{1E6F}', '\u{1E71}', '\u{1E73}', '\u{1E75}', '\u{1E77}', '\u{1E79}', '\u{1E7B}', '\u{1E7D}', '\u{1E7F}', '\u{1E81}', '\u{1E83}', '\u{1E85}', '\u{1E87}', '\u{1E89}', '\u{1E8B}', '\u{1E8D}', '\u{1E8F}', '\u{1E91}', '\u{1E93}', '\u{1E95}', '\u{1E96}', '\u{1E97}', '\u{1E98}', '\u{1E99}', '\u{1E9A}', '\u{1E9B}', '\u{1E9C}', '\u{1E9D}', '\u{1E9F}', '\u{1EA1}', '\u{1EA3}', '\u{1EA5}', '\u{1EA7}', '\u{1EA9}', '\u{1EAB}', '\u{1EAD}', '\u{1EAF}', '\u{1EB1}', '\u{1EB3}', '\u{1EB5}', '\u{1EB7}', '\u{1EB9}', '\u{1EBB}', '\u{1EBD}', '\u{1EBF}', '\u{1EC1}', '\u{1EC3}', '\u{1EC5}', '\u{1EC7}', '\u{1EC9}', '\u{1ECB}', '\u{1ECD}', '\u{1ECF}', '\u{1ED1}', '\u{1ED3}', '\u{1ED5}', '\u{1ED7}', '\u{1ED9}', '\u{1EDB}', '\u{1EDD}', '\u{1EDF}', '\u{1EE1}', '\u{1EE3}', '\u{1EE5}', '\u{1EE7}', '\u{1EE9}', '\u{1EEB}', '\u{1EED}', '\u{1EEF}', '\u{1EF1}', '\u{1EF3}', '\u{1EF5}', '\u{1EF7}', '\u{1EF9}', '\u{1EFB}', '\u{1EFD}', '\u{1EFF}', '\u{1F00}', '\u{1F01}', '\u{1F02}', '\u{1F03}', '\u{1F04}', '\u{1F05}', '\u{1F06}', '\u{1F07}', '\u{1F10}', '\u{1F11}', '\u{1F12}', '\u{1F13}', '\u{1F14}', '\u{1F15}', '\u{1F20}', '\u{1F21}', '\u{1F22}', '\u{1F23}', '\u{1F24}', '\u{1F25}', '\u{1F26}', '\u{1F27}', '\u{1F30}', '\u{1F31}', '\u{1F32}', '\u{1F33}', '\u{1F34}', '\u{1F35}', '\u{1F36}', '\u{1F37}', '\u{1F40}', '\u{1F41}', '\u{1F42}', '\u{1F43}', '\u{1F44}', '\u{1F45}', '\u{1F50}', '\u{1F51}', '\u{1F52}', '\u{1F53}', '\u{1F54}', '\u{1F55}', '\u{1F56}', '\u{1F57}', '\u{1F60}', '\u{1F61}', '\u{1F62}', '\u{1F63}', '\u{1F64}', '\u{1F65}', '\u{1F66}', '\u{1F67}', '\u{1F70}', '\u{1F71}', '\u{1F72}', '\u{1F73}', '\u{1F74}', '\u{1F75}', '\u{1F76}', '\u{1F77}', '\u{1F78}', '\u{1F79}', '\u{1F7A}', '\u{1F7B}', '\u{1F7C}', '\u{1F7D}', '\u{1F80}', '\u{1F81}', '\u{1F82}', '\u{1F83}', '\u{1F84}', '\u{1F85}', '\u{1F86}', '\u{1F87}', '\u{1F90}', '\u{1F91}', '\u{1F92}', '\u{1F93}', '\u{1F94}', '\u{1F95}', '\u{1F96}', '\u{1F97}', '\u{1FA0}', '\u{1FA1}', '\u{1FA2}', '\u{1FA3}', '\u{1FA4}', '\u{1FA5}', '\u{1FA6}', '\u{1FA7}', '\u{1FB0}', '\u{1FB1}', '\u{1FB2}', '\u{1FB3}', '\u{1FB4}', '\u{1FB6}', '\u{1FB7}', '\u{1FBE}', '\u{1FC2}', '\u{1FC3}', '\u{1FC4}', '\u{1FC6}', '\u{1FC7}', '\u{1FD0}', '\u{1FD1}', '\u{1FD2}', '\u{1FD3}', '\u{1FD6}', '\u{1FD7}', '\u{1FE0}', '\u{1FE1}', '\u{1FE2}', '\u{1FE3}', '\u{1FE4}', '\u{1FE5}', '\u{1FE6}', '\u{1FE7}', '\u{1FF2}', '\u{1FF3}', '\u{1FF4}', '\u{1FF6}', '\u{1FF7}', '\u{2071}', '\u{207F}', '\u{210A}', '\u{210E}', '\u{210F}', '\u{2113}', '\u{212F}', '\u{2134}', '\u{2139}', '\u{213C}', '\u{213D}', '\u{2146}', '\u{2147}', '\u{2148}', '\u{2149}', '\u{214E}', '\u{2184}', '\u{2C30}', '\u{2C31}', '\u{2C32}', '\u{2C33}', '\u{2C34}', '\u{2C35}', '\u{2C36}', '\u{2C37}', '\u{2C38}', '\u{2C39}', '\u{2C3A}', '\u{2C3B}', '\u{2C3C}', '\u{2C3D}', '\u{2C3E}', '\u{2C3F}', '\u{2C40}', '\u{2C41}', '\u{2C42}', '\u{2C43}', '\u{2C44}', '\u{2C45}', '\u{2C46}', '\u{2C47}', '\u{2C48}', '\u{2C49}', '\u{2C4A}', '\u{2C4B}', '\u{2C4C}', '\u{2C4D}', '\u{2C4E}', '\u{2C4F}', '\u{2C50}', '\u{2C51}', '\u{2C52}', '\u{2C53}', '\u{2C54}', '\u{2C55}', '\u{2C56}', '\u{2C57}', '\u{2C58}', '\u{2C59}', '\u{2C5A}', '\u{2C5B}', '\u{2C5C}', '\u{2C5D}', '\u{2C5E}', '\u{2C61}', '\u{2C65}', '\u{2C66}', '\u{2C68}', '\u{2C6A}', '\u{2C6C}', '\u{2C71}', '\u{2C73}', '\u{2C74}', '\u{2C76}', '\u{2C77}', '\u{2C78}', '\u{2C79}', '\u{2C7A}', '\u{2C7B}', '\u{2C7C}', '\u{2C81}', '\u{2C83}', '\u{2C85}', '\u{2C87}', '\u{2C89}', '\u{2C8B}', '\u{2C8D}', '\u{2C8F}', '\u{2C91}', '\u{2C93}', '\u{2C95}', '\u{2C97}', '\u{2C99}', '\u{2C9B}', '\u{2C9D}', '\u{2C9F}', '\u{2CA1}', '\u{2CA3}', '\u{2CA5}', '\u{2CA7}', '\u{2CA9}', '\u{2CAB}', '\u{2CAD}', '\u{2CAF}', '\u{2CB1}', '\u{2CB3}', '\u{2CB5}', '\u{2CB7}', '\u{2CB9}', '\u{2CBB}', '\u{2CBD}', '\u{2CBF}', '\u{2CC1}', '\u{2CC3}', '\u{2CC5}', '\u{2CC7}', '\u{2CC9}', '\u{2CCB}', '\u{2CCD}', '\u{2CCF}', '\u{2CD1}', '\u{2CD3}', '\u{2CD5}', '\u{2CD7}', '\u{2CD9}', '\u{2CDB}', '\u{2CDD}', '\u{2CDF}', '\u{2CE1}', '\u{2CE3}', '\u{2CE4}', '\u{2D00}', '\u{2D01}', '\u{2D02}', '\u{2D03}', '\u{2D04}', '\u{2D05}', '\u{2D06}', '\u{2D07}', '\u{2D08}', '\u{2D09}', '\u{2D0A}', '\u{2D0B}', '\u{2D0C}', '\u{2D0D}', '\u{2D0E}', '\u{2D0F}', '\u{2D10}', '\u{2D11}', '\u{2D12}', '\u{2D13}', '\u{2D14}', '\u{2D15}', '\u{2D16}', '\u{2D17}', '\u{2D18}', '\u{2D19}', '\u{2D1A}', '\u{2D1B}', '\u{2D1C}', '\u{2D1D}', '\u{2D1E}', '\u{2D1F}', '\u{2D20}', '\u{2D21}', '\u{2D22}', '\u{2D23}', '\u{2D24}', '\u{2D25}', '\u{A641}', '\u{A643}', '\u{A645}', '\u{A647}', '\u{A649}', '\u{A64B}', '\u{A64D}', '\u{A64F}', '\u{A651}', '\u{A653}', '\u{A655}', '\u{A657}', '\u{A659}', '\u{A65B}', '\u{A65D}', '\u{A65F}', '\u{A663}', '\u{A665}', '\u{A667}', '\u{A669}', '\u{A66B}', '\u{A66D}', '\u{A681}', '\u{A683}', '\u{A685}', '\u{A687}', '\u{A689}', '\u{A68B}', '\u{A68D}', '\u{A68F}', '\u{A691}', '\u{A693}', '\u{A695}', '\u{A697}', '\u{A723}', '\u{A725}', '\u{A727}', '\u{A729}', '\u{A72B}', '\u{A72D}', '\u{A72F}', '\u{A730}', '\u{A731}', '\u{A733}', '\u{A735}', '\u{A737}', '\u{A739}', '\u{A73B}', '\u{A73D}', '\u{A73F}', '\u{A741}', '\u{A743}', '\u{A745}', '\u{A747}', '\u{A749}', '\u{A74B}', '\u{A74D}', '\u{A74F}', '\u{A751}', '\u{A753}', '\u{A755}', '\u{A757}', '\u{A759}', '\u{A75B}', '\u{A75D}', '\u{A75F}', '\u{A761}', '\u{A763}', '\u{A765}', '\u{A767}', '\u{A769}', '\u{A76B}', '\u{A76D}', '\u{A76F}', '\u{A771}', '\u{A772}', '\u{A773}', '\u{A774}', '\u{A775}', '\u{A776}', '\u{A777}', '\u{A778}', '\u{A77A}', '\u{A77C}', '\u{A77F}', '\u{A781}', '\u{A783}', '\u{A785}', '\u{A787}', '\u{A78C}', '\u{FB00}', '\u{FB01}', '\u{FB02}', '\u{FB03}', '\u{FB04}', '\u{FB05}', '\u{FB06}', '\u{FB13}', '\u{FB14}', '\u{FB15}', '\u{FB16}', '\u{FB17}', '\u{FF41}', '\u{FF42}', '\u{FF43}', '\u{FF44}', '\u{FF45}', '\u{FF46}', '\u{FF47}', '\u{FF48}', '\u{FF49}', '\u{FF4A}', '\u{FF4B}', '\u{FF4C}', '\u{FF4D}', '\u{FF4E}', '\u{FF4F}', '\u{FF50}', '\u{FF51}', '\u{FF52}', '\u{FF53}', '\u{FF54}', '\u{FF55}', '\u{FF56}', '\u{FF57}', '\u{FF58}', '\u{FF59}', '\u{FF5A}') + + } + + fn is_unicode_titlecase_letter(self) -> bool { + match_char_class!(self, + '\u{01C5}', '\u{01C8}', '\u{01CB}', '\u{01F2}', '\u{1F88}', '\u{1F89}', '\u{1F8A}', '\u{1F8B}', '\u{1F8C}', '\u{1F8D}', '\u{1F8E}', '\u{1F8F}', '\u{1F98}', '\u{1F99}', '\u{1F9A}', '\u{1F9B}', '\u{1F9C}', '\u{1F9D}', '\u{1F9E}', '\u{1F9F}', '\u{1FA8}', '\u{1FA9}', '\u{1FAA}', '\u{1FAB}', '\u{1FAC}', '\u{1FAD}', '\u{1FAE}', '\u{1FAF}', '\u{1FBC}', '\u{1FCC}') + } + + fn is_unicode_modifier_letter(self) -> bool { + match_char_class!(self, + '\u{02B0}', '\u{02B1}', '\u{02B2}', '\u{02B3}', '\u{02B4}', '\u{02B5}', '\u{02B6}', '\u{02B7}', '\u{02B8}', '\u{02B9}', '\u{02BA}', '\u{02BB}', '\u{02BC}', '\u{02BD}', '\u{02BE}', '\u{02BF}', '\u{02C0}', '\u{02C1}', '\u{02C6}', '\u{02C7}', '\u{02C8}', '\u{02C9}', '\u{02CA}', '\u{02CB}', '\u{02CC}', '\u{02CD}', '\u{02CE}', '\u{02CF}', '\u{02D0}', '\u{02D1}', '\u{02E0}', '\u{02E1}', '\u{02E2}', '\u{02E3}', '\u{02E4}', '\u{02EC}', '\u{02EE}', '\u{0374}', '\u{037A}', '\u{0559}', '\u{0640}', '\u{06E5}', '\u{06E6}', '\u{07F4}', '\u{07F5}', '\u{07FA}', '\u{0971}', '\u{0E46}', '\u{0EC6}', '\u{10FC}', '\u{17D7}', '\u{1843}', '\u{1C78}', '\u{1C79}', '\u{1C7A}', '\u{1C7B}', '\u{1C7C}', '\u{1C7D}', '\u{1D2C}', '\u{1D2D}', '\u{1D2E}', '\u{1D2F}', '\u{1D30}', '\u{1D31}', '\u{1D32}', '\u{1D33}', '\u{1D34}', '\u{1D35}', '\u{1D36}', '\u{1D37}', '\u{1D38}', '\u{1D39}', '\u{1D3A}', '\u{1D3B}', '\u{1D3C}', '\u{1D3D}', '\u{1D3E}', '\u{1D3F}', '\u{1D40}', '\u{1D41}', '\u{1D42}', '\u{1D43}', '\u{1D44}', '\u{1D45}', '\u{1D46}', '\u{1D47}', '\u{1D48}', '\u{1D49}', '\u{1D4A}', '\u{1D4B}', '\u{1D4C}', '\u{1D4D}', '\u{1D4E}', '\u{1D4F}', '\u{1D50}', '\u{1D51}', '\u{1D52}', '\u{1D53}', '\u{1D54}', '\u{1D55}', '\u{1D56}', '\u{1D57}', '\u{1D58}', '\u{1D59}', '\u{1D5A}', '\u{1D5B}', '\u{1D5C}', '\u{1D5D}', '\u{1D5E}', '\u{1D5F}', '\u{1D60}', '\u{1D61}', '\u{1D78}', '\u{1D9B}', '\u{1D9C}', '\u{1D9D}', '\u{1D9E}', '\u{1D9F}', '\u{1DA0}', '\u{1DA1}', '\u{1DA2}', '\u{1DA3}', '\u{1DA4}', '\u{1DA5}', '\u{1DA6}', '\u{1DA7}', '\u{1DA8}', '\u{1DA9}', '\u{1DAA}', '\u{1DAB}', '\u{1DAC}', '\u{1DAD}', '\u{1DAE}', '\u{1DAF}', '\u{1DB0}', '\u{1DB1}', '\u{1DB2}', '\u{1DB3}', '\u{1DB4}', '\u{1DB5}', '\u{1DB6}', '\u{1DB7}', '\u{1DB8}', '\u{1DB9}', '\u{1DBA}', '\u{1DBB}', '\u{1DBC}', '\u{1DBD}', '\u{1DBE}', '\u{1DBF}', '\u{2090}', '\u{2091}', '\u{2092}', '\u{2093}', '\u{2094}', '\u{2C7D}', '\u{2D6F}', '\u{2E2F}', '\u{3005}', '\u{3031}', '\u{3032}', '\u{3033}', '\u{3034}', '\u{3035}', '\u{303B}', '\u{309D}', '\u{309E}', '\u{30FC}', '\u{30FD}', '\u{30FE}', '\u{A015}', '\u{A60C}', '\u{A67F}', '\u{A717}', '\u{A718}', '\u{A719}', '\u{A71A}', '\u{A71B}', '\u{A71C}', '\u{A71D}', '\u{A71E}', '\u{A71F}', '\u{A770}', '\u{A788}', '\u{FF70}', '\u{FF9E}', '\u{FF9F}') + } + + fn is_unicode_other_letter(self) -> bool { + match_char_class!(self, + '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}') + } + + fn is_unicode_letter_number(self) -> bool { + match_char_class!(self, + '\u{16EE}', '\u{16EF}', '\u{16F0}', '\u{2160}', '\u{2161}', '\u{2162}', '\u{2163}', '\u{2164}', '\u{2165}', '\u{2166}', '\u{2167}', '\u{2168}', '\u{2169}', '\u{216A}', '\u{216B}', '\u{216C}', '\u{216D}', '\u{216E}', '\u{216F}', '\u{2170}', '\u{2171}', '\u{2172}', '\u{2173}', '\u{2174}', '\u{2175}', '\u{2176}', '\u{2177}', '\u{2178}', '\u{2179}', '\u{217A}', '\u{217B}', '\u{217C}', '\u{217D}', '\u{217E}', '\u{217F}', '\u{2180}', '\u{2181}', '\u{2182}', '\u{2185}', '\u{2186}', '\u{2187}', '\u{2188}', '\u{3007}', '\u{3021}', '\u{3022}', '\u{3023}', '\u{3024}', '\u{3025}', '\u{3026}', '\u{3027}', '\u{3028}', '\u{3029}', '\u{3038}', '\u{3039}', '\u{303A}') + } + + fn is_unicode_nonspacing_mark(self) -> bool { + match_char_class!(self, + '\u{0300}', '\u{0301}', '\u{0302}', '\u{0303}', '\u{0304}', '\u{0305}', '\u{0306}', '\u{0307}', '\u{0308}', '\u{0309}', '\u{030A}', '\u{030B}', '\u{030C}', '\u{030D}', '\u{030E}', '\u{030F}', '\u{0310}', '\u{0311}', '\u{0312}', '\u{0313}', '\u{0314}', '\u{0315}', '\u{0316}', '\u{0317}', '\u{0318}', '\u{0319}', '\u{031A}', '\u{031B}', '\u{031C}', '\u{031D}', '\u{031E}', '\u{031F}', '\u{0320}', '\u{0321}', '\u{0322}', '\u{0323}', '\u{0324}', '\u{0325}', '\u{0326}', '\u{0327}', '\u{0328}', '\u{0329}', '\u{032A}', '\u{032B}', '\u{032C}', '\u{032D}', '\u{032E}', '\u{032F}', '\u{0330}', '\u{0331}', '\u{0332}', '\u{0333}', '\u{0334}', '\u{0335}', '\u{0336}', '\u{0337}', '\u{0338}', '\u{0339}', '\u{033A}', '\u{033B}', '\u{033C}', '\u{033D}', '\u{033E}', '\u{033F}', '\u{0340}', '\u{0341}', '\u{0342}', '\u{0343}', '\u{0344}', '\u{0345}', '\u{0346}', '\u{0347}', '\u{0348}', '\u{0349}', '\u{034A}', '\u{034B}', '\u{034C}', '\u{034D}', '\u{034E}', '\u{034F}', '\u{0350}', '\u{0351}', '\u{0352}', '\u{0353}', '\u{0354}', '\u{0355}', '\u{0356}', '\u{0357}', '\u{0358}', '\u{0359}', '\u{035A}', '\u{035B}', '\u{035C}', '\u{035D}', '\u{035E}', '\u{035F}', '\u{0360}', '\u{0361}', '\u{0362}', '\u{0363}', '\u{0364}', '\u{0365}', '\u{0366}', '\u{0367}', '\u{0368}', '\u{0369}', '\u{036A}', '\u{036B}', '\u{036C}', '\u{036D}', '\u{036E}', '\u{036F}', '\u{0483}', '\u{0484}', '\u{0485}', '\u{0486}', '\u{0487}', '\u{0591}', '\u{0592}', '\u{0593}', '\u{0594}', '\u{0595}', '\u{0596}', '\u{0597}', '\u{0598}', '\u{0599}', '\u{059A}', '\u{059B}', '\u{059C}', '\u{059D}', '\u{059E}', '\u{059F}', '\u{05A0}', '\u{05A1}', '\u{05A2}', '\u{05A3}', '\u{05A4}', '\u{05A5}', '\u{05A6}', '\u{05A7}', '\u{05A8}', '\u{05A9}', '\u{05AA}', '\u{05AB}', '\u{05AC}', '\u{05AD}', '\u{05AE}', '\u{05AF}', '\u{05B0}', '\u{05B1}', '\u{05B2}', '\u{05B3}', '\u{05B4}', '\u{05B5}', '\u{05B6}', '\u{05B7}', '\u{05B8}', '\u{05B9}', '\u{05BA}', '\u{05BB}', '\u{05BC}', '\u{05BD}', '\u{05BF}', '\u{05C1}', '\u{05C2}', '\u{05C4}', '\u{05C5}', '\u{05C7}', '\u{0610}', '\u{0611}', '\u{0612}', '\u{0613}', '\u{0614}', '\u{0615}', '\u{0616}', '\u{0617}', '\u{0618}', '\u{0619}', '\u{061A}', '\u{064B}', '\u{064C}', '\u{064D}', '\u{064E}', '\u{064F}', '\u{0650}', '\u{0651}', '\u{0652}', '\u{0653}', '\u{0654}', '\u{0655}', '\u{0656}', '\u{0657}', '\u{0658}', '\u{0659}', '\u{065A}', '\u{065B}', '\u{065C}', '\u{065D}', '\u{065E}', '\u{0670}', '\u{06D6}', '\u{06D7}', '\u{06D8}', '\u{06D9}', '\u{06DA}', '\u{06DB}', '\u{06DC}', '\u{06DF}', '\u{06E0}', '\u{06E1}', '\u{06E2}', '\u{06E3}', '\u{06E4}', '\u{06E7}', '\u{06E8}', '\u{06EA}', '\u{06EB}', '\u{06EC}', '\u{06ED}', '\u{0711}', '\u{0730}', '\u{0731}', '\u{0732}', '\u{0733}', '\u{0734}', '\u{0735}', '\u{0736}', '\u{0737}', '\u{0738}', '\u{0739}', '\u{073A}', '\u{073B}', '\u{073C}', '\u{073D}', '\u{073E}', '\u{073F}', '\u{0740}', '\u{0741}', '\u{0742}', '\u{0743}', '\u{0744}', '\u{0745}', '\u{0746}', '\u{0747}', '\u{0748}', '\u{0749}', '\u{074A}', '\u{07A6}', '\u{07A7}', '\u{07A8}', '\u{07A9}', '\u{07AA}', '\u{07AB}', '\u{07AC}', '\u{07AD}', '\u{07AE}', '\u{07AF}', '\u{07B0}', '\u{07EB}', '\u{07EC}', '\u{07ED}', '\u{07EE}', '\u{07EF}', '\u{07F0}', '\u{07F1}', '\u{07F2}', '\u{07F3}', '\u{0901}', '\u{0902}', '\u{093C}', '\u{0941}', '\u{0942}', '\u{0943}', '\u{0944}', '\u{0945}', '\u{0946}', '\u{0947}', '\u{0948}', '\u{094D}', '\u{0951}', '\u{0952}', '\u{0953}', '\u{0954}', '\u{0962}', '\u{0963}', '\u{0981}', '\u{09BC}', '\u{09C1}', '\u{09C2}', '\u{09C3}', '\u{09C4}', '\u{09CD}', '\u{09E2}', '\u{09E3}', '\u{0A01}', '\u{0A02}', '\u{0A3C}', '\u{0A41}', '\u{0A42}', '\u{0A47}', '\u{0A48}', '\u{0A4B}', '\u{0A4C}', '\u{0A4D}', '\u{0A51}', '\u{0A70}', '\u{0A71}', '\u{0A75}', '\u{0A81}', '\u{0A82}', '\u{0ABC}', '\u{0AC1}', '\u{0AC2}', '\u{0AC3}', '\u{0AC4}', '\u{0AC5}', '\u{0AC7}', '\u{0AC8}', '\u{0ACD}', '\u{0AE2}', '\u{0AE3}', '\u{0B01}', '\u{0B3C}', '\u{0B3F}', '\u{0B41}', '\u{0B42}', '\u{0B43}', '\u{0B44}', '\u{0B4D}', '\u{0B56}', '\u{0B62}', '\u{0B63}', '\u{0B82}', '\u{0BC0}', '\u{0BCD}', '\u{0C3E}', '\u{0C3F}', '\u{0C40}', '\u{0C46}', '\u{0C47}', '\u{0C48}', '\u{0C4A}', '\u{0C4B}', '\u{0C4C}', '\u{0C4D}', '\u{0C55}', '\u{0C56}', '\u{0C62}', '\u{0C63}', '\u{0CBC}', '\u{0CBF}', '\u{0CC6}', '\u{0CCC}', '\u{0CCD}', '\u{0CE2}', '\u{0CE3}', '\u{0D41}', '\u{0D42}', '\u{0D43}', '\u{0D44}', '\u{0D4D}', '\u{0D62}', '\u{0D63}', '\u{0DCA}', '\u{0DD2}', '\u{0DD3}', '\u{0DD4}', '\u{0DD6}', '\u{0E31}', '\u{0E34}', '\u{0E35}', '\u{0E36}', '\u{0E37}', '\u{0E38}', '\u{0E39}', '\u{0E3A}', '\u{0E47}', '\u{0E48}', '\u{0E49}', '\u{0E4A}', '\u{0E4B}', '\u{0E4C}', '\u{0E4D}', '\u{0E4E}', '\u{0EB1}', '\u{0EB4}', '\u{0EB5}', '\u{0EB6}', '\u{0EB7}', '\u{0EB8}', '\u{0EB9}', '\u{0EBB}', '\u{0EBC}', '\u{0EC8}', '\u{0EC9}', '\u{0ECA}', '\u{0ECB}', '\u{0ECC}', '\u{0ECD}', '\u{0F18}', '\u{0F19}', '\u{0F35}', '\u{0F37}', '\u{0F39}', '\u{0F71}', '\u{0F72}', '\u{0F73}', '\u{0F74}', '\u{0F75}', '\u{0F76}', '\u{0F77}', '\u{0F78}', '\u{0F79}', '\u{0F7A}', '\u{0F7B}', '\u{0F7C}', '\u{0F7D}', '\u{0F7E}', '\u{0F80}', '\u{0F81}', '\u{0F82}', '\u{0F83}', '\u{0F84}', '\u{0F86}', '\u{0F87}', '\u{0F90}', '\u{0F91}', '\u{0F92}', '\u{0F93}', '\u{0F94}', '\u{0F95}', '\u{0F96}', '\u{0F97}', '\u{0F99}', '\u{0F9A}', '\u{0F9B}', '\u{0F9C}', '\u{0F9D}', '\u{0F9E}', '\u{0F9F}', '\u{0FA0}', '\u{0FA1}', '\u{0FA2}', '\u{0FA3}', '\u{0FA4}', '\u{0FA5}', '\u{0FA6}', '\u{0FA7}', '\u{0FA8}', '\u{0FA9}', '\u{0FAA}', '\u{0FAB}', '\u{0FAC}', '\u{0FAD}', '\u{0FAE}', '\u{0FAF}', '\u{0FB0}', '\u{0FB1}', '\u{0FB2}', '\u{0FB3}', '\u{0FB4}', '\u{0FB5}', '\u{0FB6}', '\u{0FB7}', '\u{0FB8}', '\u{0FB9}', '\u{0FBA}', '\u{0FBB}', '\u{0FBC}', '\u{0FC6}', '\u{102D}', '\u{102E}', '\u{102F}', '\u{1030}', '\u{1032}', '\u{1033}', '\u{1034}', '\u{1035}', '\u{1036}', '\u{1037}', '\u{1039}', '\u{103A}', '\u{103D}', '\u{103E}', '\u{1058}', '\u{1059}', '\u{105E}', '\u{105F}', '\u{1060}', '\u{1071}', '\u{1072}', '\u{1073}', '\u{1074}', '\u{1082}', '\u{1085}', '\u{1086}', '\u{108D}', '\u{135F}', '\u{1712}', '\u{1713}', '\u{1714}', '\u{1732}', '\u{1733}', '\u{1734}', '\u{1752}', '\u{1753}', '\u{1772}', '\u{1773}', '\u{17B7}', '\u{17B8}', '\u{17B9}', '\u{17BA}', '\u{17BB}', '\u{17BC}', '\u{17BD}', '\u{17C6}', '\u{17C9}', '\u{17CA}', '\u{17CB}', '\u{17CC}', '\u{17CD}', '\u{17CE}', '\u{17CF}', '\u{17D0}', '\u{17D1}', '\u{17D2}', '\u{17D3}', '\u{17DD}', '\u{180B}', '\u{180C}', '\u{180D}', '\u{18A9}', '\u{1920}', '\u{1921}', '\u{1922}', '\u{1927}', '\u{1928}', '\u{1932}', '\u{1939}', '\u{193A}', '\u{193B}', '\u{1A17}', '\u{1A18}', '\u{1B00}', '\u{1B01}', '\u{1B02}', '\u{1B03}', '\u{1B34}', '\u{1B36}', '\u{1B37}', '\u{1B38}', '\u{1B39}', '\u{1B3A}', '\u{1B3C}', '\u{1B42}', '\u{1B6B}', '\u{1B6C}', '\u{1B6D}', '\u{1B6E}', '\u{1B6F}', '\u{1B70}', '\u{1B71}', '\u{1B72}', '\u{1B73}', '\u{1B80}', '\u{1B81}', '\u{1BA2}', '\u{1BA3}', '\u{1BA4}', '\u{1BA5}', '\u{1BA8}', '\u{1BA9}', '\u{1C2C}', '\u{1C2D}', '\u{1C2E}', '\u{1C2F}', '\u{1C30}', '\u{1C31}', '\u{1C32}', '\u{1C33}', '\u{1C36}', '\u{1C37}', '\u{1DC0}', '\u{1DC1}', '\u{1DC2}', '\u{1DC3}', '\u{1DC4}', '\u{1DC5}', '\u{1DC6}', '\u{1DC7}', '\u{1DC8}', '\u{1DC9}', '\u{1DCA}', '\u{1DCB}', '\u{1DCC}', '\u{1DCD}', '\u{1DCE}', '\u{1DCF}', '\u{1DD0}', '\u{1DD1}', '\u{1DD2}', '\u{1DD3}', '\u{1DD4}', '\u{1DD5}', '\u{1DD6}', '\u{1DD7}', '\u{1DD8}', '\u{1DD9}', '\u{1DDA}', '\u{1DDB}', '\u{1DDC}', '\u{1DDD}', '\u{1DDE}', '\u{1DDF}', '\u{1DE0}', '\u{1DE1}', '\u{1DE2}', '\u{1DE3}', '\u{1DE4}', '\u{1DE5}', '\u{1DE6}', '\u{1DFE}', '\u{1DFF}', '\u{20D0}', '\u{20D1}', '\u{20D2}', '\u{20D3}', '\u{20D4}', '\u{20D5}', '\u{20D6}', '\u{20D7}', '\u{20D8}', '\u{20D9}', '\u{20DA}', '\u{20DB}', '\u{20DC}', '\u{20E1}', '\u{20E5}', '\u{20E6}', '\u{20E7}', '\u{20E8}', '\u{20E9}', '\u{20EA}', '\u{20EB}', '\u{20EC}', '\u{20ED}', '\u{20EE}', '\u{20EF}', '\u{20F0}', '\u{2DE0}', '\u{2DE1}', '\u{2DE2}', '\u{2DE3}', '\u{2DE4}', '\u{2DE5}', '\u{2DE6}', '\u{2DE7}', '\u{2DE8}', '\u{2DE9}', '\u{2DEA}', '\u{2DEB}', '\u{2DEC}', '\u{2DED}', '\u{2DEE}', '\u{2DEF}', '\u{2DF0}', '\u{2DF1}', '\u{2DF2}', '\u{2DF3}', '\u{2DF4}', '\u{2DF5}', '\u{2DF6}', '\u{2DF7}', '\u{2DF8}', '\u{2DF9}', '\u{2DFA}', '\u{2DFB}', '\u{2DFC}', '\u{2DFD}', '\u{2DFE}', '\u{2DFF}', '\u{302A}', '\u{302B}', '\u{302C}', '\u{302D}', '\u{302E}', '\u{302F}', '\u{3099}', '\u{309A}', '\u{A66F}', '\u{A67C}', '\u{A67D}', '\u{A802}', '\u{A806}', '\u{A80B}', '\u{A825}', '\u{A826}', '\u{A8C4}', '\u{A926}', '\u{A927}', '\u{A928}', '\u{A929}', '\u{A92A}', '\u{A92B}', '\u{A92C}', '\u{A92D}', '\u{A947}', '\u{A948}', '\u{A949}', '\u{A94A}', '\u{A94B}', '\u{A94C}', '\u{A94D}', '\u{A94E}', '\u{A94F}', '\u{A950}', '\u{A951}', '\u{AA29}', '\u{AA2A}', '\u{AA2B}', '\u{AA2C}', '\u{AA2D}', '\u{AA2E}', '\u{AA31}', '\u{AA32}', '\u{AA35}', '\u{AA36}', '\u{AA43}', '\u{AA4C}', '\u{FB1E}', '\u{FE00}', '\u{FE01}', '\u{FE02}', '\u{FE03}', '\u{FE04}', '\u{FE05}', '\u{FE06}', '\u{FE07}', '\u{FE08}', '\u{FE09}', '\u{FE0A}', '\u{FE0B}', '\u{FE0C}', '\u{FE0D}', '\u{FE0E}', '\u{FE0F}', '\u{FE20}', '\u{FE21}', '\u{FE22}', '\u{FE23}', '\u{FE24}', '\u{FE25}', '\u{FE26}', '\u{01BB}', '\u{01C0}', '\u{01C1}', '\u{01C2}', '\u{01C3}', '\u{0294}', '\u{05D0}', '\u{05D1}', '\u{05D2}', '\u{05D3}', '\u{05D4}', '\u{05D5}', '\u{05D6}', '\u{05D7}', '\u{05D8}', '\u{05D9}', '\u{05DA}', '\u{05DB}', '\u{05DC}', '\u{05DD}', '\u{05DE}', '\u{05DF}', '\u{05E0}', '\u{05E1}', '\u{05E2}', '\u{05E3}', '\u{05E4}', '\u{05E5}', '\u{05E6}', '\u{05E7}', '\u{05E8}', '\u{05E9}', '\u{05EA}', '\u{05F0}', '\u{05F1}', '\u{05F2}', '\u{0621}', '\u{0622}', '\u{0623}', '\u{0624}', '\u{0625}', '\u{0626}', '\u{0627}', '\u{0628}', '\u{0629}', '\u{062A}', '\u{062B}', '\u{062C}', '\u{062D}', '\u{062E}', '\u{062F}', '\u{0630}', '\u{0631}', '\u{0632}', '\u{0633}', '\u{0634}', '\u{0635}', '\u{0636}', '\u{0637}', '\u{0638}', '\u{0639}', '\u{063A}', '\u{063B}', '\u{063C}', '\u{063D}', '\u{063E}', '\u{063F}', '\u{0641}', '\u{0642}', '\u{0643}', '\u{0644}', '\u{0645}', '\u{0646}', '\u{0647}', '\u{0648}', '\u{0649}', '\u{064A}', '\u{066E}', '\u{066F}', '\u{0671}', '\u{0672}', '\u{0673}', '\u{0674}', '\u{0675}', '\u{0676}', '\u{0677}', '\u{0678}', '\u{0679}', '\u{067A}', '\u{067B}', '\u{067C}', '\u{067D}', '\u{067E}', '\u{067F}', '\u{0680}', '\u{0681}', '\u{0682}', '\u{0683}', '\u{0684}', '\u{0685}', '\u{0686}', '\u{0687}', '\u{0688}', '\u{0689}', '\u{068A}', '\u{068B}', '\u{068C}', '\u{068D}', '\u{068E}', '\u{068F}', '\u{0690}', '\u{0691}', '\u{0692}', '\u{0693}', '\u{0694}', '\u{0695}', '\u{0696}', '\u{0697}', '\u{0698}', '\u{0699}', '\u{069A}', '\u{069B}', '\u{069C}', '\u{069D}', '\u{069E}', '\u{069F}', '\u{06A0}', '\u{06A1}', '\u{06A2}', '\u{06A3}', '\u{06A4}', '\u{06A5}', '\u{06A6}', '\u{06A7}', '\u{06A8}', '\u{06A9}', '\u{06AA}', '\u{06AB}', '\u{06AC}', '\u{06AD}', '\u{06AE}', '\u{06AF}', '\u{06B0}', '\u{06B1}', '\u{06B2}', '\u{06B3}', '\u{06B4}', '\u{06B5}', '\u{06B6}', '\u{06B7}', '\u{06B8}', '\u{06B9}', '\u{06BA}', '\u{06BB}', '\u{06BC}', '\u{06BD}', '\u{06BE}', '\u{06BF}', '\u{06C0}', '\u{06C1}', '\u{06C2}', '\u{06C3}', '\u{06C4}', '\u{06C5}', '\u{06C6}', '\u{06C7}', '\u{06C8}', '\u{06C9}', '\u{06CA}', '\u{06CB}', '\u{06CC}', '\u{06CD}', '\u{06CE}', '\u{06CF}', '\u{06D0}', '\u{06D1}', '\u{06D2}', '\u{06D3}', '\u{06D5}', '\u{06EE}', '\u{06EF}', '\u{06FA}', '\u{06FB}', '\u{06FC}', '\u{06FF}', '\u{0710}', '\u{0712}', '\u{0713}', '\u{0714}', '\u{0715}', '\u{0716}', '\u{0717}', '\u{0718}', '\u{0719}', '\u{071A}', '\u{071B}', '\u{071C}', '\u{071D}', '\u{071E}', '\u{071F}', '\u{0720}', '\u{0721}', '\u{0722}', '\u{0723}', '\u{0724}', '\u{0725}', '\u{0726}', '\u{0727}', '\u{0728}', '\u{0729}', '\u{072A}', '\u{072B}', '\u{072C}', '\u{072D}', '\u{072E}', '\u{072F}', '\u{074D}', '\u{074E}', '\u{074F}', '\u{0750}', '\u{0751}', '\u{0752}', '\u{0753}', '\u{0754}', '\u{0755}', '\u{0756}', '\u{0757}', '\u{0758}', '\u{0759}', '\u{075A}', '\u{075B}', '\u{075C}', '\u{075D}', '\u{075E}', '\u{075F}', '\u{0760}', '\u{0761}', '\u{0762}', '\u{0763}', '\u{0764}', '\u{0765}', '\u{0766}', '\u{0767}', '\u{0768}', '\u{0769}', '\u{076A}', '\u{076B}', '\u{076C}', '\u{076D}', '\u{076E}', '\u{076F}', '\u{0770}', '\u{0771}', '\u{0772}', '\u{0773}', '\u{0774}', '\u{0775}', '\u{0776}', '\u{0777}', '\u{0778}', '\u{0779}', '\u{077A}', '\u{077B}', '\u{077C}', '\u{077D}', '\u{077E}', '\u{077F}', '\u{0780}', '\u{0781}', '\u{0782}', '\u{0783}', '\u{0784}', '\u{0785}', '\u{0786}', '\u{0787}', '\u{0788}', '\u{0789}', '\u{078A}', '\u{078B}', '\u{078C}', '\u{078D}', '\u{078E}', '\u{078F}', '\u{0790}', '\u{0791}', '\u{0792}', '\u{0793}', '\u{0794}', '\u{0795}', '\u{0796}', '\u{0797}', '\u{0798}', '\u{0799}', '\u{079A}', '\u{079B}', '\u{079C}', '\u{079D}', '\u{079E}', '\u{079F}', '\u{07A0}', '\u{07A1}', '\u{07A2}', '\u{07A3}', '\u{07A4}', '\u{07A5}', '\u{07B1}', '\u{07CA}', '\u{07CB}', '\u{07CC}', '\u{07CD}', '\u{07CE}', '\u{07CF}', '\u{07D0}', '\u{07D1}', '\u{07D2}', '\u{07D3}', '\u{07D4}', '\u{07D5}', '\u{07D6}', '\u{07D7}', '\u{07D8}', '\u{07D9}', '\u{07DA}', '\u{07DB}', '\u{07DC}', '\u{07DD}', '\u{07DE}', '\u{07DF}', '\u{07E0}', '\u{07E1}', '\u{07E2}', '\u{07E3}', '\u{07E4}', '\u{07E5}', '\u{07E6}', '\u{07E7}', '\u{07E8}', '\u{07E9}', '\u{07EA}', '\u{0904}', '\u{0905}', '\u{0906}', '\u{0907}', '\u{0908}', '\u{0909}', '\u{090A}', '\u{090B}', '\u{090C}', '\u{090D}', '\u{090E}', '\u{090F}', '\u{0910}', '\u{0911}', '\u{0912}', '\u{0913}', '\u{0914}', '\u{0915}', '\u{0916}', '\u{0917}', '\u{0918}', '\u{0919}', '\u{091A}', '\u{091B}', '\u{091C}', '\u{091D}', '\u{091E}', '\u{091F}', '\u{0920}', '\u{0921}', '\u{0922}', '\u{0923}', '\u{0924}', '\u{0925}', '\u{0926}', '\u{0927}', '\u{0928}', '\u{0929}', '\u{092A}', '\u{092B}', '\u{092C}', '\u{092D}', '\u{092E}', '\u{092F}', '\u{0930}', '\u{0931}', '\u{0932}', '\u{0933}', '\u{0934}', '\u{0935}', '\u{0936}', '\u{0937}', '\u{0938}', '\u{0939}', '\u{093D}', '\u{0950}', '\u{0958}', '\u{0959}', '\u{095A}', '\u{095B}', '\u{095C}', '\u{095D}', '\u{095E}', '\u{095F}', '\u{0960}', '\u{0961}', '\u{0972}', '\u{097B}', '\u{097C}', '\u{097D}', '\u{097E}', '\u{097F}', '\u{0985}', '\u{0986}', '\u{0987}', '\u{0988}', '\u{0989}', '\u{098A}', '\u{098B}', '\u{098C}', '\u{098F}', '\u{0990}', '\u{0993}', '\u{0994}', '\u{0995}', '\u{0996}', '\u{0997}', '\u{0998}', '\u{0999}', '\u{099A}', '\u{099B}', '\u{099C}', '\u{099D}', '\u{099E}', '\u{099F}', '\u{09A0}', '\u{09A1}', '\u{09A2}', '\u{09A3}', '\u{09A4}', '\u{09A5}', '\u{09A6}', '\u{09A7}', '\u{09A8}', '\u{09AA}', '\u{09AB}', '\u{09AC}', '\u{09AD}', '\u{09AE}', '\u{09AF}', '\u{09B0}', '\u{09B2}', '\u{09B6}', '\u{09B7}', '\u{09B8}', '\u{09B9}', '\u{09BD}', '\u{09CE}', '\u{09DC}', '\u{09DD}', '\u{09DF}', '\u{09E0}', '\u{09E1}', '\u{09F0}', '\u{09F1}', '\u{0A05}', '\u{0A06}', '\u{0A07}', '\u{0A08}', '\u{0A09}', '\u{0A0A}', '\u{0A0F}', '\u{0A10}', '\u{0A13}', '\u{0A14}', '\u{0A15}', '\u{0A16}', '\u{0A17}', '\u{0A18}', '\u{0A19}', '\u{0A1A}', '\u{0A1B}', '\u{0A1C}', '\u{0A1D}', '\u{0A1E}', '\u{0A1F}', '\u{0A20}', '\u{0A21}', '\u{0A22}', '\u{0A23}', '\u{0A24}', '\u{0A25}', '\u{0A26}', '\u{0A27}', '\u{0A28}', '\u{0A2A}', '\u{0A2B}', '\u{0A2C}', '\u{0A2D}', '\u{0A2E}', '\u{0A2F}', '\u{0A30}', '\u{0A32}', '\u{0A33}', '\u{0A35}', '\u{0A36}', '\u{0A38}', '\u{0A39}', '\u{0A59}', '\u{0A5A}', '\u{0A5B}', '\u{0A5C}', '\u{0A5E}', '\u{0A72}', '\u{0A73}', '\u{0A74}', '\u{0A85}', '\u{0A86}', '\u{0A87}', '\u{0A88}', '\u{0A89}', '\u{0A8A}', '\u{0A8B}', '\u{0A8C}', '\u{0A8D}', '\u{0A8F}', '\u{0A90}', '\u{0A91}', '\u{0A93}', '\u{0A94}', '\u{0A95}', '\u{0A96}', '\u{0A97}', '\u{0A98}', '\u{0A99}', '\u{0A9A}', '\u{0A9B}', '\u{0A9C}', '\u{0A9D}', '\u{0A9E}', '\u{0A9F}', '\u{0AA0}', '\u{0AA1}', '\u{0AA2}', '\u{0AA3}', '\u{0AA4}', '\u{0AA5}', '\u{0AA6}', '\u{0AA7}', '\u{0AA8}', '\u{0AAA}', '\u{0AAB}', '\u{0AAC}', '\u{0AAD}', '\u{0AAE}', '\u{0AAF}', '\u{0AB0}', '\u{0AB2}', '\u{0AB3}', '\u{0AB5}', '\u{0AB6}', '\u{0AB7}', '\u{0AB8}', '\u{0AB9}', '\u{0ABD}', '\u{0AD0}', '\u{0AE0}', '\u{0AE1}', '\u{0B05}', '\u{0B06}', '\u{0B07}', '\u{0B08}', '\u{0B09}', '\u{0B0A}', '\u{0B0B}', '\u{0B0C}', '\u{0B0F}', '\u{0B10}', '\u{0B13}', '\u{0B14}', '\u{0B15}', '\u{0B16}', '\u{0B17}', '\u{0B18}', '\u{0B19}', '\u{0B1A}', '\u{0B1B}', '\u{0B1C}', '\u{0B1D}', '\u{0B1E}', '\u{0B1F}', '\u{0B20}', '\u{0B21}', '\u{0B22}', '\u{0B23}', '\u{0B24}', '\u{0B25}', '\u{0B26}', '\u{0B27}', '\u{0B28}', '\u{0B2A}', '\u{0B2B}', '\u{0B2C}', '\u{0B2D}', '\u{0B2E}', '\u{0B2F}', '\u{0B30}', '\u{0B32}', '\u{0B33}', '\u{0B35}', '\u{0B36}', '\u{0B37}', '\u{0B38}', '\u{0B39}', '\u{0B3D}', '\u{0B5C}', '\u{0B5D}', '\u{0B5F}', '\u{0B60}', '\u{0B61}', '\u{0B71}', '\u{0B83}', '\u{0B85}', '\u{0B86}', '\u{0B87}', '\u{0B88}', '\u{0B89}', '\u{0B8A}', '\u{0B8E}', '\u{0B8F}', '\u{0B90}', '\u{0B92}', '\u{0B93}', '\u{0B94}', '\u{0B95}', '\u{0B99}', '\u{0B9A}', '\u{0B9C}', '\u{0B9E}', '\u{0B9F}', '\u{0BA3}', '\u{0BA4}', '\u{0BA8}', '\u{0BA9}', '\u{0BAA}', '\u{0BAE}', '\u{0BAF}', '\u{0BB0}', '\u{0BB1}', '\u{0BB2}', '\u{0BB3}', '\u{0BB4}', '\u{0BB5}', '\u{0BB6}', '\u{0BB7}', '\u{0BB8}', '\u{0BB9}', '\u{0BD0}', '\u{0C05}', '\u{0C06}', '\u{0C07}', '\u{0C08}', '\u{0C09}', '\u{0C0A}', '\u{0C0B}', '\u{0C0C}', '\u{0C0E}', '\u{0C0F}', '\u{0C10}', '\u{0C12}', '\u{0C13}', '\u{0C14}', '\u{0C15}', '\u{0C16}', '\u{0C17}', '\u{0C18}', '\u{0C19}', '\u{0C1A}', '\u{0C1B}', '\u{0C1C}', '\u{0C1D}', '\u{0C1E}', '\u{0C1F}', '\u{0C20}', '\u{0C21}', '\u{0C22}', '\u{0C23}', '\u{0C24}', '\u{0C25}', '\u{0C26}', '\u{0C27}', '\u{0C28}', '\u{0C2A}', '\u{0C2B}', '\u{0C2C}', '\u{0C2D}', '\u{0C2E}', '\u{0C2F}', '\u{0C30}', '\u{0C31}', '\u{0C32}', '\u{0C33}', '\u{0C35}', '\u{0C36}', '\u{0C37}', '\u{0C38}', '\u{0C39}', '\u{0C3D}', '\u{0C58}', '\u{0C59}', '\u{0C60}', '\u{0C61}', '\u{0C85}', '\u{0C86}', '\u{0C87}', '\u{0C88}', '\u{0C89}', '\u{0C8A}', '\u{0C8B}', '\u{0C8C}', '\u{0C8E}', '\u{0C8F}', '\u{0C90}', '\u{0C92}', '\u{0C93}', '\u{0C94}', '\u{0C95}', '\u{0C96}', '\u{0C97}', '\u{0C98}', '\u{0C99}', '\u{0C9A}', '\u{0C9B}', '\u{0C9C}', '\u{0C9D}', '\u{0C9E}', '\u{0C9F}', '\u{0CA0}', '\u{0CA1}', '\u{0CA2}', '\u{0CA3}', '\u{0CA4}', '\u{0CA5}', '\u{0CA6}', '\u{0CA7}', '\u{0CA8}', '\u{0CAA}', '\u{0CAB}', '\u{0CAC}', '\u{0CAD}', '\u{0CAE}', '\u{0CAF}', '\u{0CB0}', '\u{0CB1}', '\u{0CB2}', '\u{0CB3}', '\u{0CB5}', '\u{0CB6}', '\u{0CB7}', '\u{0CB8}', '\u{0CB9}', '\u{0CBD}', '\u{0CDE}', '\u{0CE0}', '\u{0CE1}', '\u{0D05}', '\u{0D06}', '\u{0D07}', '\u{0D08}', '\u{0D09}', '\u{0D0A}', '\u{0D0B}', '\u{0D0C}', '\u{0D0E}', '\u{0D0F}', '\u{0D10}', '\u{0D12}', '\u{0D13}', '\u{0D14}', '\u{0D15}', '\u{0D16}', '\u{0D17}', '\u{0D18}', '\u{0D19}', '\u{0D1A}', '\u{0D1B}', '\u{0D1C}', '\u{0D1D}', '\u{0D1E}', '\u{0D1F}', '\u{0D20}', '\u{0D21}', '\u{0D22}', '\u{0D23}', '\u{0D24}', '\u{0D25}', '\u{0D26}', '\u{0D27}', '\u{0D28}', '\u{0D2A}', '\u{0D2B}', '\u{0D2C}', '\u{0D2D}', '\u{0D2E}', '\u{0D2F}', '\u{0D30}', '\u{0D31}', '\u{0D32}', '\u{0D33}', '\u{0D34}', '\u{0D35}', '\u{0D36}', '\u{0D37}', '\u{0D38}', '\u{0D39}', '\u{0D3D}', '\u{0D60}', '\u{0D61}', '\u{0D7A}', '\u{0D7B}', '\u{0D7C}', '\u{0D7D}', '\u{0D7E}', '\u{0D7F}', '\u{0D85}', '\u{0D86}', '\u{0D87}', '\u{0D88}', '\u{0D89}', '\u{0D8A}', '\u{0D8B}', '\u{0D8C}', '\u{0D8D}', '\u{0D8E}', '\u{0D8F}', '\u{0D90}', '\u{0D91}', '\u{0D92}', '\u{0D93}', '\u{0D94}', '\u{0D95}', '\u{0D96}', '\u{0D9A}', '\u{0D9B}', '\u{0D9C}', '\u{0D9D}', '\u{0D9E}', '\u{0D9F}', '\u{0DA0}', '\u{0DA1}', '\u{0DA2}', '\u{0DA3}', '\u{0DA4}', '\u{0DA5}', '\u{0DA6}', '\u{0DA7}', '\u{0DA8}', '\u{0DA9}', '\u{0DAA}', '\u{0DAB}', '\u{0DAC}', '\u{0DAD}', '\u{0DAE}', '\u{0DAF}', '\u{0DB0}', '\u{0DB1}', '\u{0DB3}', '\u{0DB4}', '\u{0DB5}', '\u{0DB6}', '\u{0DB7}', '\u{0DB8}', '\u{0DB9}', '\u{0DBA}', '\u{0DBB}', '\u{0DBD}', '\u{0DC0}', '\u{0DC1}', '\u{0DC2}', '\u{0DC3}', '\u{0DC4}', '\u{0DC5}', '\u{0DC6}', '\u{0E01}', '\u{0E02}', '\u{0E03}', '\u{0E04}', '\u{0E05}', '\u{0E06}', '\u{0E07}', '\u{0E08}', '\u{0E09}', '\u{0E0A}', '\u{0E0B}', '\u{0E0C}', '\u{0E0D}', '\u{0E0E}', '\u{0E0F}', '\u{0E10}', '\u{0E11}', '\u{0E12}', '\u{0E13}', '\u{0E14}', '\u{0E15}', '\u{0E16}', '\u{0E17}', '\u{0E18}', '\u{0E19}', '\u{0E1A}', '\u{0E1B}', '\u{0E1C}', '\u{0E1D}', '\u{0E1E}', '\u{0E1F}', '\u{0E20}', '\u{0E21}', '\u{0E22}', '\u{0E23}', '\u{0E24}', '\u{0E25}', '\u{0E26}', '\u{0E27}', '\u{0E28}', '\u{0E29}', '\u{0E2A}', '\u{0E2B}', '\u{0E2C}', '\u{0E2D}', '\u{0E2E}', '\u{0E2F}', '\u{0E30}', '\u{0E32}', '\u{0E33}', '\u{0E40}', '\u{0E41}', '\u{0E42}', '\u{0E43}', '\u{0E44}', '\u{0E45}', '\u{0E81}', '\u{0E82}', '\u{0E84}', '\u{0E87}', '\u{0E88}', '\u{0E8A}', '\u{0E8D}', '\u{0E94}', '\u{0E95}', '\u{0E96}', '\u{0E97}', '\u{0E99}', '\u{0E9A}', '\u{0E9B}', '\u{0E9C}', '\u{0E9D}', '\u{0E9E}', '\u{0E9F}', '\u{0EA1}', '\u{0EA2}', '\u{0EA3}', '\u{0EA5}', '\u{0EA7}', '\u{0EAA}', '\u{0EAB}', '\u{0EAD}', '\u{0EAE}', '\u{0EAF}', '\u{0EB0}', '\u{0EB2}', '\u{0EB3}', '\u{0EBD}', '\u{0EC0}', '\u{0EC1}', '\u{0EC2}', '\u{0EC3}', '\u{0EC4}', '\u{0EDC}', '\u{0EDD}', '\u{0F00}', '\u{0F40}', '\u{0F41}', '\u{0F42}', '\u{0F43}', '\u{0F44}', '\u{0F45}', '\u{0F46}', '\u{0F47}', '\u{0F49}', '\u{0F4A}', '\u{0F4B}', '\u{0F4C}', '\u{0F4D}', '\u{0F4E}', '\u{0F4F}', '\u{0F50}', '\u{0F51}', '\u{0F52}', '\u{0F53}', '\u{0F54}', '\u{0F55}', '\u{0F56}', '\u{0F57}', '\u{0F58}', '\u{0F59}', '\u{0F5A}', '\u{0F5B}', '\u{0F5C}', '\u{0F5D}', '\u{0F5E}', '\u{0F5F}', '\u{0F60}', '\u{0F61}', '\u{0F62}', '\u{0F63}', '\u{0F64}', '\u{0F65}', '\u{0F66}', '\u{0F67}', '\u{0F68}', '\u{0F69}', '\u{0F6A}', '\u{0F6B}', '\u{0F6C}', '\u{0F88}', '\u{0F89}', '\u{0F8A}', '\u{0F8B}', '\u{1000}', '\u{1001}', '\u{1002}', '\u{1003}', '\u{1004}', '\u{1005}', '\u{1006}', '\u{1007}', '\u{1008}', '\u{1009}', '\u{100A}', '\u{100B}', '\u{100C}', '\u{100D}', '\u{100E}', '\u{100F}', '\u{1010}', '\u{1011}', '\u{1012}', '\u{1013}', '\u{1014}', '\u{1015}', '\u{1016}', '\u{1017}', '\u{1018}', '\u{1019}', '\u{101A}', '\u{101B}', '\u{101C}', '\u{101D}', '\u{101E}', '\u{101F}', '\u{1020}', '\u{1021}', '\u{1022}', '\u{1023}', '\u{1024}', '\u{1025}', '\u{1026}', '\u{1027}', '\u{1028}', '\u{1029}', '\u{102A}', '\u{103F}', '\u{1050}', '\u{1051}', '\u{1052}', '\u{1053}', '\u{1054}', '\u{1055}', '\u{105A}', '\u{105B}', '\u{105C}', '\u{105D}', '\u{1061}', '\u{1065}', '\u{1066}', '\u{106E}', '\u{106F}', '\u{1070}', '\u{1075}', '\u{1076}', '\u{1077}', '\u{1078}', '\u{1079}', '\u{107A}', '\u{107B}', '\u{107C}', '\u{107D}', '\u{107E}', '\u{107F}', '\u{1080}', '\u{1081}', '\u{108E}', '\u{10D0}', '\u{10D1}', '\u{10D2}', '\u{10D3}', '\u{10D4}', '\u{10D5}', '\u{10D6}', '\u{10D7}', '\u{10D8}', '\u{10D9}', '\u{10DA}', '\u{10DB}', '\u{10DC}', '\u{10DD}', '\u{10DE}', '\u{10DF}', '\u{10E0}', '\u{10E1}', '\u{10E2}', '\u{10E3}', '\u{10E4}', '\u{10E5}', '\u{10E6}', '\u{10E7}', '\u{10E8}', '\u{10E9}', '\u{10EA}', '\u{10EB}', '\u{10EC}', '\u{10ED}', '\u{10EE}', '\u{10EF}', '\u{10F0}', '\u{10F1}', '\u{10F2}', '\u{10F3}', '\u{10F4}', '\u{10F5}', '\u{10F6}', '\u{10F7}', '\u{10F8}', '\u{10F9}', '\u{10FA}', '\u{1100}', '\u{1101}', '\u{1102}', '\u{1103}', '\u{1104}', '\u{1105}', '\u{1106}', '\u{1107}', '\u{1108}', '\u{1109}', '\u{110A}', '\u{110B}', '\u{110C}', '\u{110D}', '\u{110E}', '\u{110F}', '\u{1110}', '\u{1111}', '\u{1112}', '\u{1113}', '\u{1114}', '\u{1115}', '\u{1116}', '\u{1117}', '\u{1118}', '\u{1119}', '\u{111A}', '\u{111B}', '\u{111C}', '\u{111D}', '\u{111E}', '\u{111F}', '\u{1120}', '\u{1121}', '\u{1122}', '\u{1123}', '\u{1124}', '\u{1125}', '\u{1126}', '\u{1127}', '\u{1128}', '\u{1129}', '\u{112A}', '\u{112B}', '\u{112C}', '\u{112D}', '\u{112E}', '\u{112F}', '\u{1130}', '\u{1131}', '\u{1132}', '\u{1133}', '\u{1134}', '\u{1135}', '\u{1136}', '\u{1137}', '\u{1138}', '\u{1139}', '\u{113A}', '\u{113B}', '\u{113C}', '\u{113D}', '\u{113E}', '\u{113F}', '\u{1140}', '\u{1141}', '\u{1142}', '\u{1143}', '\u{1144}', '\u{1145}', '\u{1146}', '\u{1147}', '\u{1148}', '\u{1149}', '\u{114A}', '\u{114B}', '\u{114C}', '\u{114D}', '\u{114E}', '\u{114F}', '\u{1150}', '\u{1151}', '\u{1152}', '\u{1153}', '\u{1154}', '\u{1155}', '\u{1156}', '\u{1157}', '\u{1158}', '\u{1159}', '\u{115F}', '\u{1160}', '\u{1161}', '\u{1162}', '\u{1163}', '\u{1164}', '\u{1165}', '\u{1166}', '\u{1167}', '\u{1168}', '\u{1169}', '\u{116A}', '\u{116B}', '\u{116C}', '\u{116D}', '\u{116E}', '\u{116F}', '\u{1170}', '\u{1171}', '\u{1172}', '\u{1173}', '\u{1174}', '\u{1175}', '\u{1176}', '\u{1177}', '\u{1178}', '\u{1179}', '\u{117A}', '\u{117B}', '\u{117C}', '\u{117D}', '\u{117E}', '\u{117F}', '\u{1180}', '\u{1181}', '\u{1182}', '\u{1183}', '\u{1184}', '\u{1185}', '\u{1186}', '\u{1187}', '\u{1188}', '\u{1189}', '\u{118A}', '\u{118B}', '\u{118C}', '\u{118D}', '\u{118E}', '\u{118F}', '\u{1190}', '\u{1191}', '\u{1192}', '\u{1193}', '\u{1194}', '\u{1195}', '\u{1196}', '\u{1197}', '\u{1198}', '\u{1199}', '\u{119A}', '\u{119B}', '\u{119C}', '\u{119D}', '\u{119E}', '\u{119F}', '\u{11A0}', '\u{11A1}', '\u{11A2}', '\u{11A8}', '\u{11A9}', '\u{11AA}', '\u{11AB}', '\u{11AC}', '\u{11AD}', '\u{11AE}', '\u{11AF}', '\u{11B0}', '\u{11B1}', '\u{11B2}', '\u{11B3}', '\u{11B4}', '\u{11B5}', '\u{11B6}', '\u{11B7}', '\u{11B8}', '\u{11B9}', '\u{11BA}', '\u{11BB}', '\u{11BC}', '\u{11BD}', '\u{11BE}', '\u{11BF}', '\u{11C0}', '\u{11C1}', '\u{11C2}', '\u{11C3}', '\u{11C4}', '\u{11C5}', '\u{11C6}', '\u{11C7}', '\u{11C8}', '\u{11C9}', '\u{11CA}', '\u{11CB}', '\u{11CC}', '\u{11CD}', '\u{11CE}', '\u{11CF}', '\u{11D0}', '\u{11D1}', '\u{11D2}', '\u{11D3}', '\u{11D4}', '\u{11D5}', '\u{11D6}', '\u{11D7}', '\u{11D8}', '\u{11D9}', '\u{11DA}', '\u{11DB}', '\u{11DC}', '\u{11DD}', '\u{11DE}', '\u{11DF}', '\u{11E0}', '\u{11E1}', '\u{11E2}', '\u{11E3}', '\u{11E4}', '\u{11E5}', '\u{11E6}', '\u{11E7}', '\u{11E8}', '\u{11E9}', '\u{11EA}', '\u{11EB}', '\u{11EC}', '\u{11ED}', '\u{11EE}', '\u{11EF}', '\u{11F0}', '\u{11F1}', '\u{11F2}', '\u{11F3}', '\u{11F4}', '\u{11F5}', '\u{11F6}', '\u{11F7}', '\u{11F8}', '\u{11F9}', '\u{1200}', '\u{1201}', '\u{1202}', '\u{1203}', '\u{1204}', '\u{1205}', '\u{1206}', '\u{1207}', '\u{1208}', '\u{1209}', '\u{120A}', '\u{120B}', '\u{120C}', '\u{120D}', '\u{120E}', '\u{120F}', '\u{1210}', '\u{1211}', '\u{1212}', '\u{1213}', '\u{1214}', '\u{1215}', '\u{1216}', '\u{1217}', '\u{1218}', '\u{1219}', '\u{121A}', '\u{121B}', '\u{121C}', '\u{121D}', '\u{121E}', '\u{121F}', '\u{1220}', '\u{1221}', '\u{1222}', '\u{1223}', '\u{1224}', '\u{1225}', '\u{1226}', '\u{1227}', '\u{1228}', '\u{1229}', '\u{122A}', '\u{122B}', '\u{122C}', '\u{122D}', '\u{122E}', '\u{122F}', '\u{1230}', '\u{1231}', '\u{1232}', '\u{1233}', '\u{1234}', '\u{1235}', '\u{1236}', '\u{1237}', '\u{1238}', '\u{1239}', '\u{123A}', '\u{123B}', '\u{123C}', '\u{123D}', '\u{123E}', '\u{123F}', '\u{1240}', '\u{1241}', '\u{1242}', '\u{1243}', '\u{1244}', '\u{1245}', '\u{1246}', '\u{1247}', '\u{1248}', '\u{124A}', '\u{124B}', '\u{124C}', '\u{124D}', '\u{1250}', '\u{1251}', '\u{1252}', '\u{1253}', '\u{1254}', '\u{1255}', '\u{1256}', '\u{1258}', '\u{125A}', '\u{125B}', '\u{125C}', '\u{125D}', '\u{1260}', '\u{1261}', '\u{1262}', '\u{1263}', '\u{1264}', '\u{1265}', '\u{1266}', '\u{1267}', '\u{1268}', '\u{1269}', '\u{126A}', '\u{126B}', '\u{126C}', '\u{126D}', '\u{126E}', '\u{126F}', '\u{1270}', '\u{1271}', '\u{1272}', '\u{1273}', '\u{1274}', '\u{1275}', '\u{1276}', '\u{1277}', '\u{1278}', '\u{1279}', '\u{127A}', '\u{127B}', '\u{127C}', '\u{127D}', '\u{127E}', '\u{127F}', '\u{1280}', '\u{1281}', '\u{1282}', '\u{1283}', '\u{1284}', '\u{1285}', '\u{1286}', '\u{1287}', '\u{1288}', '\u{128A}', '\u{128B}', '\u{128C}', '\u{128D}', '\u{1290}', '\u{1291}', '\u{1292}', '\u{1293}', '\u{1294}', '\u{1295}', '\u{1296}', '\u{1297}', '\u{1298}', '\u{1299}', '\u{129A}', '\u{129B}', '\u{129C}', '\u{129D}', '\u{129E}', '\u{129F}', '\u{12A0}', '\u{12A1}', '\u{12A2}', '\u{12A3}', '\u{12A4}', '\u{12A5}', '\u{12A6}', '\u{12A7}', '\u{12A8}', '\u{12A9}', '\u{12AA}', '\u{12AB}', '\u{12AC}', '\u{12AD}', '\u{12AE}', '\u{12AF}', '\u{12B0}', '\u{12B2}', '\u{12B3}', '\u{12B4}', '\u{12B5}', '\u{12B8}', '\u{12B9}', '\u{12BA}', '\u{12BB}', '\u{12BC}', '\u{12BD}', '\u{12BE}', '\u{12C0}', '\u{12C2}', '\u{12C3}', '\u{12C4}', '\u{12C5}', '\u{12C8}', '\u{12C9}', '\u{12CA}', '\u{12CB}', '\u{12CC}', '\u{12CD}', '\u{12CE}', '\u{12CF}', '\u{12D0}', '\u{12D1}', '\u{12D2}', '\u{12D3}', '\u{12D4}', '\u{12D5}', '\u{12D6}', '\u{12D8}', '\u{12D9}', '\u{12DA}', '\u{12DB}', '\u{12DC}', '\u{12DD}', '\u{12DE}', '\u{12DF}', '\u{12E0}', '\u{12E1}', '\u{12E2}', '\u{12E3}', '\u{12E4}', '\u{12E5}', '\u{12E6}', '\u{12E7}', '\u{12E8}', '\u{12E9}', '\u{12EA}', '\u{12EB}', '\u{12EC}', '\u{12ED}', '\u{12EE}', '\u{12EF}', '\u{12F0}', '\u{12F1}', '\u{12F2}', '\u{12F3}', '\u{12F4}', '\u{12F5}', '\u{12F6}', '\u{12F7}', '\u{12F8}', '\u{12F9}', '\u{12FA}', '\u{12FB}', '\u{12FC}', '\u{12FD}', '\u{12FE}', '\u{12FF}', '\u{1300}', '\u{1301}', '\u{1302}', '\u{1303}', '\u{1304}', '\u{1305}', '\u{1306}', '\u{1307}', '\u{1308}', '\u{1309}', '\u{130A}', '\u{130B}', '\u{130C}', '\u{130D}', '\u{130E}', '\u{130F}', '\u{1310}', '\u{1312}', '\u{1313}', '\u{1314}', '\u{1315}', '\u{1318}', '\u{1319}', '\u{131A}', '\u{131B}', '\u{131C}', '\u{131D}', '\u{131E}', '\u{131F}', '\u{1320}', '\u{1321}', '\u{1322}', '\u{1323}', '\u{1324}', '\u{1325}', '\u{1326}', '\u{1327}', '\u{1328}', '\u{1329}', '\u{132A}', '\u{132B}', '\u{132C}', '\u{132D}', '\u{132E}', '\u{132F}', '\u{1330}', '\u{1331}', '\u{1332}', '\u{1333}', '\u{1334}', '\u{1335}', '\u{1336}', '\u{1337}', '\u{1338}', '\u{1339}', '\u{133A}', '\u{133B}', '\u{133C}', '\u{133D}', '\u{133E}', '\u{133F}', '\u{1340}', '\u{1341}', '\u{1342}', '\u{1343}', '\u{1344}', '\u{1345}', '\u{1346}', '\u{1347}', '\u{1348}', '\u{1349}', '\u{134A}', '\u{134B}', '\u{134C}', '\u{134D}', '\u{134E}', '\u{134F}', '\u{1350}', '\u{1351}', '\u{1352}', '\u{1353}', '\u{1354}', '\u{1355}', '\u{1356}', '\u{1357}', '\u{1358}', '\u{1359}', '\u{135A}', '\u{1380}', '\u{1381}', '\u{1382}', '\u{1383}', '\u{1384}', '\u{1385}', '\u{1386}', '\u{1387}', '\u{1388}', '\u{1389}', '\u{138A}', '\u{138B}', '\u{138C}', '\u{138D}', '\u{138E}', '\u{138F}', '\u{13A0}', '\u{13A1}', '\u{13A2}', '\u{13A3}', '\u{13A4}', '\u{13A5}', '\u{13A6}', '\u{13A7}', '\u{13A8}', '\u{13A9}', '\u{13AA}', '\u{13AB}', '\u{13AC}', '\u{13AD}', '\u{13AE}', '\u{13AF}', '\u{13B0}', '\u{13B1}', '\u{13B2}', '\u{13B3}', '\u{13B4}', '\u{13B5}', '\u{13B6}', '\u{13B7}', '\u{13B8}', '\u{13B9}', '\u{13BA}', '\u{13BB}', '\u{13BC}', '\u{13BD}', '\u{13BE}', '\u{13BF}', '\u{13C0}', '\u{13C1}', '\u{13C2}', '\u{13C3}', '\u{13C4}', '\u{13C5}', '\u{13C6}', '\u{13C7}', '\u{13C8}', '\u{13C9}', '\u{13CA}', '\u{13CB}', '\u{13CC}', '\u{13CD}', '\u{13CE}', '\u{13CF}', '\u{13D0}', '\u{13D1}', '\u{13D2}', '\u{13D3}', '\u{13D4}', '\u{13D5}', '\u{13D6}', '\u{13D7}', '\u{13D8}', '\u{13D9}', '\u{13DA}', '\u{13DB}', '\u{13DC}', '\u{13DD}', '\u{13DE}', '\u{13DF}', '\u{13E0}', '\u{13E1}', '\u{13E2}', '\u{13E3}', '\u{13E4}', '\u{13E5}', '\u{13E6}', '\u{13E7}', '\u{13E8}', '\u{13E9}', '\u{13EA}', '\u{13EB}', '\u{13EC}', '\u{13ED}', '\u{13EE}', '\u{13EF}', '\u{13F0}', '\u{13F1}', '\u{13F2}', '\u{13F3}', '\u{13F4}', '\u{1401}', '\u{1402}', '\u{1403}', '\u{1404}', '\u{1405}', '\u{1406}', '\u{1407}', '\u{1408}', '\u{1409}', '\u{140A}', '\u{140B}', '\u{140C}', '\u{140D}', '\u{140E}', '\u{140F}', '\u{1410}', '\u{1411}', '\u{1412}', '\u{1413}', '\u{1414}', '\u{1415}', '\u{1416}', '\u{1417}', '\u{1418}', '\u{1419}', '\u{141A}', '\u{141B}', '\u{141C}', '\u{141D}', '\u{141E}', '\u{141F}', '\u{1420}', '\u{1421}', '\u{1422}', '\u{1423}', '\u{1424}', '\u{1425}', '\u{1426}', '\u{1427}', '\u{1428}', '\u{1429}', '\u{142A}', '\u{142B}', '\u{142C}', '\u{142D}', '\u{142E}', '\u{142F}', '\u{1430}', '\u{1431}', '\u{1432}', '\u{1433}', '\u{1434}', '\u{1435}', '\u{1436}', '\u{1437}', '\u{1438}', '\u{1439}', '\u{143A}', '\u{143B}', '\u{143C}', '\u{143D}', '\u{143E}', '\u{143F}', '\u{1440}', '\u{1441}', '\u{1442}', '\u{1443}', '\u{1444}', '\u{1445}', '\u{1446}', '\u{1447}', '\u{1448}', '\u{1449}', '\u{144A}', '\u{144B}', '\u{144C}', '\u{144D}', '\u{144E}', '\u{144F}', '\u{1450}', '\u{1451}', '\u{1452}', '\u{1453}', '\u{1454}', '\u{1455}', '\u{1456}', '\u{1457}', '\u{1458}', '\u{1459}', '\u{145A}', '\u{145B}', '\u{145C}', '\u{145D}', '\u{145E}', '\u{145F}', '\u{1460}', '\u{1461}', '\u{1462}', '\u{1463}', '\u{1464}', '\u{1465}', '\u{1466}', '\u{1467}', '\u{1468}', '\u{1469}', '\u{146A}', '\u{146B}', '\u{146C}', '\u{146D}', '\u{146E}', '\u{146F}', '\u{1470}', '\u{1471}', '\u{1472}', '\u{1473}', '\u{1474}', '\u{1475}', '\u{1476}', '\u{1477}', '\u{1478}', '\u{1479}', '\u{147A}', '\u{147B}', '\u{147C}', '\u{147D}', '\u{147E}', '\u{147F}', '\u{1480}', '\u{1481}', '\u{1482}', '\u{1483}', '\u{1484}', '\u{1485}', '\u{1486}', '\u{1487}', '\u{1488}', '\u{1489}', '\u{148A}', '\u{148B}', '\u{148C}', '\u{148D}', '\u{148E}', '\u{148F}', '\u{1490}', '\u{1491}', '\u{1492}', '\u{1493}', '\u{1494}', '\u{1495}', '\u{1496}', '\u{1497}', '\u{1498}', '\u{1499}', '\u{149A}', '\u{149B}', '\u{149C}', '\u{149D}', '\u{149E}', '\u{149F}', '\u{14A0}', '\u{14A1}', '\u{14A2}', '\u{14A3}', '\u{14A4}', '\u{14A5}', '\u{14A6}', '\u{14A7}', '\u{14A8}', '\u{14A9}', '\u{14AA}', '\u{14AB}', '\u{14AC}', '\u{14AD}', '\u{14AE}', '\u{14AF}', '\u{14B0}', '\u{14B1}', '\u{14B2}', '\u{14B3}', '\u{14B4}', '\u{14B5}', '\u{14B6}', '\u{14B7}', '\u{14B8}', '\u{14B9}', '\u{14BA}', '\u{14BB}', '\u{14BC}', '\u{14BD}', '\u{14BE}', '\u{14BF}', '\u{14C0}', '\u{14C1}', '\u{14C2}', '\u{14C3}', '\u{14C4}', '\u{14C5}', '\u{14C6}', '\u{14C7}', '\u{14C8}', '\u{14C9}', '\u{14CA}', '\u{14CB}', '\u{14CC}', '\u{14CD}', '\u{14CE}', '\u{14CF}', '\u{14D0}', '\u{14D1}', '\u{14D2}', '\u{14D3}', '\u{14D4}', '\u{14D5}', '\u{14D6}', '\u{14D7}', '\u{14D8}', '\u{14D9}', '\u{14DA}', '\u{14DB}', '\u{14DC}', '\u{14DD}', '\u{14DE}', '\u{14DF}', '\u{14E0}', '\u{14E1}', '\u{14E2}', '\u{14E3}', '\u{14E4}', '\u{14E5}', '\u{14E6}', '\u{14E7}', '\u{14E8}', '\u{14E9}', '\u{14EA}', '\u{14EB}', '\u{14EC}', '\u{14ED}', '\u{14EE}', '\u{14EF}', '\u{14F0}', '\u{14F1}', '\u{14F2}', '\u{14F3}', '\u{14F4}', '\u{14F5}', '\u{14F6}', '\u{14F7}', '\u{14F8}', '\u{14F9}', '\u{14FA}', '\u{14FB}', '\u{14FC}', '\u{14FD}', '\u{14FE}', '\u{14FF}', '\u{1500}', '\u{1501}', '\u{1502}', '\u{1503}', '\u{1504}', '\u{1505}', '\u{1506}', '\u{1507}', '\u{1508}', '\u{1509}', '\u{150A}', '\u{150B}', '\u{150C}', '\u{150D}', '\u{150E}', '\u{150F}', '\u{1510}', '\u{1511}', '\u{1512}', '\u{1513}', '\u{1514}', '\u{1515}', '\u{1516}', '\u{1517}', '\u{1518}', '\u{1519}', '\u{151A}', '\u{151B}', '\u{151C}', '\u{151D}', '\u{151E}', '\u{151F}', '\u{1520}', '\u{1521}', '\u{1522}', '\u{1523}', '\u{1524}', '\u{1525}', '\u{1526}', '\u{1527}', '\u{1528}', '\u{1529}', '\u{152A}', '\u{152B}', '\u{152C}', '\u{152D}', '\u{152E}', '\u{152F}', '\u{1530}', '\u{1531}', '\u{1532}', '\u{1533}', '\u{1534}', '\u{1535}', '\u{1536}', '\u{1537}', '\u{1538}', '\u{1539}', '\u{153A}', '\u{153B}', '\u{153C}', '\u{153D}', '\u{153E}', '\u{153F}', '\u{1540}', '\u{1541}', '\u{1542}', '\u{1543}', '\u{1544}', '\u{1545}', '\u{1546}', '\u{1547}', '\u{1548}', '\u{1549}', '\u{154A}', '\u{154B}', '\u{154C}', '\u{154D}', '\u{154E}', '\u{154F}', '\u{1550}', '\u{1551}', '\u{1552}', '\u{1553}', '\u{1554}', '\u{1555}', '\u{1556}', '\u{1557}', '\u{1558}', '\u{1559}', '\u{155A}', '\u{155B}', '\u{155C}', '\u{155D}', '\u{155E}', '\u{155F}', '\u{1560}', '\u{1561}', '\u{1562}', '\u{1563}', '\u{1564}', '\u{1565}', '\u{1566}', '\u{1567}', '\u{1568}', '\u{1569}', '\u{156A}', '\u{156B}', '\u{156C}', '\u{156D}', '\u{156E}', '\u{156F}', '\u{1570}', '\u{1571}', '\u{1572}', '\u{1573}', '\u{1574}', '\u{1575}', '\u{1576}', '\u{1577}', '\u{1578}', '\u{1579}', '\u{157A}', '\u{157B}', '\u{157C}', '\u{157D}', '\u{157E}', '\u{157F}', '\u{1580}', '\u{1581}', '\u{1582}', '\u{1583}', '\u{1584}', '\u{1585}', '\u{1586}', '\u{1587}', '\u{1588}', '\u{1589}', '\u{158A}', '\u{158B}', '\u{158C}', '\u{158D}', '\u{158E}', '\u{158F}', '\u{1590}', '\u{1591}', '\u{1592}', '\u{1593}', '\u{1594}', '\u{1595}', '\u{1596}', '\u{1597}', '\u{1598}', '\u{1599}', '\u{159A}', '\u{159B}', '\u{159C}', '\u{159D}', '\u{159E}', '\u{159F}', '\u{15A0}', '\u{15A1}', '\u{15A2}', '\u{15A3}', '\u{15A4}', '\u{15A5}', '\u{15A6}', '\u{15A7}', '\u{15A8}', '\u{15A9}', '\u{15AA}', '\u{15AB}', '\u{15AC}', '\u{15AD}', '\u{15AE}', '\u{15AF}', '\u{15B0}', '\u{15B1}', '\u{15B2}', '\u{15B3}', '\u{15B4}', '\u{15B5}', '\u{15B6}', '\u{15B7}', '\u{15B8}', '\u{15B9}', '\u{15BA}', '\u{15BB}', '\u{15BC}', '\u{15BD}', '\u{15BE}', '\u{15BF}', '\u{15C0}', '\u{15C1}', '\u{15C2}', '\u{15C3}', '\u{15C4}', '\u{15C5}', '\u{15C6}', '\u{15C7}', '\u{15C8}', '\u{15C9}', '\u{15CA}', '\u{15CB}', '\u{15CC}', '\u{15CD}', '\u{15CE}', '\u{15CF}', '\u{15D0}', '\u{15D1}', '\u{15D2}', '\u{15D3}', '\u{15D4}', '\u{15D5}', '\u{15D6}', '\u{15D7}', '\u{15D8}', '\u{15D9}', '\u{15DA}', '\u{15DB}', '\u{15DC}', '\u{15DD}', '\u{15DE}', '\u{15DF}', '\u{15E0}', '\u{15E1}', '\u{15E2}', '\u{15E3}', '\u{15E4}', '\u{15E5}', '\u{15E6}', '\u{15E7}', '\u{15E8}', '\u{15E9}', '\u{15EA}', '\u{15EB}', '\u{15EC}', '\u{15ED}', '\u{15EE}', '\u{15EF}', '\u{15F0}', '\u{15F1}', '\u{15F2}', '\u{15F3}', '\u{15F4}', '\u{15F5}', '\u{15F6}', '\u{15F7}', '\u{15F8}', '\u{15F9}', '\u{15FA}', '\u{15FB}', '\u{15FC}', '\u{15FD}', '\u{15FE}', '\u{15FF}', '\u{1600}', '\u{1601}', '\u{1602}', '\u{1603}', '\u{1604}', '\u{1605}', '\u{1606}', '\u{1607}', '\u{1608}', '\u{1609}', '\u{160A}', '\u{160B}', '\u{160C}', '\u{160D}', '\u{160E}', '\u{160F}', '\u{1610}', '\u{1611}', '\u{1612}', '\u{1613}', '\u{1614}', '\u{1615}', '\u{1616}', '\u{1617}', '\u{1618}', '\u{1619}', '\u{161A}', '\u{161B}', '\u{161C}', '\u{161D}', '\u{161E}', '\u{161F}', '\u{1620}', '\u{1621}', '\u{1622}', '\u{1623}', '\u{1624}', '\u{1625}', '\u{1626}', '\u{1627}', '\u{1628}', '\u{1629}', '\u{162A}', '\u{162B}', '\u{162C}', '\u{162D}', '\u{162E}', '\u{162F}', '\u{1630}', '\u{1631}', '\u{1632}', '\u{1633}', '\u{1634}', '\u{1635}', '\u{1636}', '\u{1637}', '\u{1638}', '\u{1639}', '\u{163A}', '\u{163B}', '\u{163C}', '\u{163D}', '\u{163E}', '\u{163F}', '\u{1640}', '\u{1641}', '\u{1642}', '\u{1643}', '\u{1644}', '\u{1645}', '\u{1646}', '\u{1647}', '\u{1648}', '\u{1649}', '\u{164A}', '\u{164B}', '\u{164C}', '\u{164D}', '\u{164E}', '\u{164F}', '\u{1650}', '\u{1651}', '\u{1652}', '\u{1653}', '\u{1654}', '\u{1655}', '\u{1656}', '\u{1657}', '\u{1658}', '\u{1659}', '\u{165A}', '\u{165B}', '\u{165C}', '\u{165D}', '\u{165E}', '\u{165F}', '\u{1660}', '\u{1661}', '\u{1662}', '\u{1663}', '\u{1664}', '\u{1665}', '\u{1666}', '\u{1667}', '\u{1668}', '\u{1669}', '\u{166A}', '\u{166B}', '\u{166C}', '\u{166F}', '\u{1670}', '\u{1671}', '\u{1672}', '\u{1673}', '\u{1674}', '\u{1675}', '\u{1676}', '\u{1681}', '\u{1682}', '\u{1683}', '\u{1684}', '\u{1685}', '\u{1686}', '\u{1687}', '\u{1688}', '\u{1689}', '\u{168A}', '\u{168B}', '\u{168C}', '\u{168D}', '\u{168E}', '\u{168F}', '\u{1690}', '\u{1691}', '\u{1692}', '\u{1693}', '\u{1694}', '\u{1695}', '\u{1696}', '\u{1697}', '\u{1698}', '\u{1699}', '\u{169A}', '\u{16A0}', '\u{16A1}', '\u{16A2}', '\u{16A3}', '\u{16A4}', '\u{16A5}', '\u{16A6}', '\u{16A7}', '\u{16A8}', '\u{16A9}', '\u{16AA}', '\u{16AB}', '\u{16AC}', '\u{16AD}', '\u{16AE}', '\u{16AF}', '\u{16B0}', '\u{16B1}', '\u{16B2}', '\u{16B3}', '\u{16B4}', '\u{16B5}', '\u{16B6}', '\u{16B7}', '\u{16B8}', '\u{16B9}', '\u{16BA}', '\u{16BB}', '\u{16BC}', '\u{16BD}', '\u{16BE}', '\u{16BF}', '\u{16C0}', '\u{16C1}', '\u{16C2}', '\u{16C3}', '\u{16C4}', '\u{16C5}', '\u{16C6}', '\u{16C7}', '\u{16C8}', '\u{16C9}', '\u{16CA}', '\u{16CB}', '\u{16CC}', '\u{16CD}', '\u{16CE}', '\u{16CF}', '\u{16D0}', '\u{16D1}', '\u{16D2}', '\u{16D3}', '\u{16D4}', '\u{16D5}', '\u{16D6}', '\u{16D7}', '\u{16D8}', '\u{16D9}', '\u{16DA}', '\u{16DB}', '\u{16DC}', '\u{16DD}', '\u{16DE}', '\u{16DF}', '\u{16E0}', '\u{16E1}', '\u{16E2}', '\u{16E3}', '\u{16E4}', '\u{16E5}', '\u{16E6}', '\u{16E7}', '\u{16E8}', '\u{16E9}', '\u{16EA}', '\u{1700}', '\u{1701}', '\u{1702}', '\u{1703}', '\u{1704}', '\u{1705}', '\u{1706}', '\u{1707}', '\u{1708}', '\u{1709}', '\u{170A}', '\u{170B}', '\u{170C}', '\u{170E}', '\u{170F}', '\u{1710}', '\u{1711}', '\u{1720}', '\u{1721}', '\u{1722}', '\u{1723}', '\u{1724}', '\u{1725}', '\u{1726}', '\u{1727}', '\u{1728}', '\u{1729}', '\u{172A}', '\u{172B}', '\u{172C}', '\u{172D}', '\u{172E}', '\u{172F}', '\u{1730}', '\u{1731}', '\u{1740}', '\u{1741}', '\u{1742}', '\u{1743}', '\u{1744}', '\u{1745}', '\u{1746}', '\u{1747}', '\u{1748}', '\u{1749}', '\u{174A}', '\u{174B}', '\u{174C}', '\u{174D}', '\u{174E}', '\u{174F}', '\u{1750}', '\u{1751}', '\u{1760}', '\u{1761}', '\u{1762}', '\u{1763}', '\u{1764}', '\u{1765}', '\u{1766}', '\u{1767}', '\u{1768}', '\u{1769}', '\u{176A}', '\u{176B}', '\u{176C}', '\u{176E}', '\u{176F}', '\u{1770}', '\u{1780}', '\u{1781}', '\u{1782}', '\u{1783}', '\u{1784}', '\u{1785}', '\u{1786}', '\u{1787}', '\u{1788}', '\u{1789}', '\u{178A}', '\u{178B}', '\u{178C}', '\u{178D}', '\u{178E}', '\u{178F}', '\u{1790}', '\u{1791}', '\u{1792}', '\u{1793}', '\u{1794}', '\u{1795}', '\u{1796}', '\u{1797}', '\u{1798}', '\u{1799}', '\u{179A}', '\u{179B}', '\u{179C}', '\u{179D}', '\u{179E}', '\u{179F}', '\u{17A0}', '\u{17A1}', '\u{17A2}', '\u{17A3}', '\u{17A4}', '\u{17A5}', '\u{17A6}', '\u{17A7}', '\u{17A8}', '\u{17A9}', '\u{17AA}', '\u{17AB}', '\u{17AC}', '\u{17AD}', '\u{17AE}', '\u{17AF}', '\u{17B0}', '\u{17B1}', '\u{17B2}', '\u{17B3}', '\u{17DC}', '\u{1820}', '\u{1821}', '\u{1822}', '\u{1823}', '\u{1824}', '\u{1825}', '\u{1826}', '\u{1827}', '\u{1828}', '\u{1829}', '\u{182A}', '\u{182B}', '\u{182C}', '\u{182D}', '\u{182E}', '\u{182F}', '\u{1830}', '\u{1831}', '\u{1832}', '\u{1833}', '\u{1834}', '\u{1835}', '\u{1836}', '\u{1837}', '\u{1838}', '\u{1839}', '\u{183A}', '\u{183B}', '\u{183C}', '\u{183D}', '\u{183E}', '\u{183F}', '\u{1840}', '\u{1841}', '\u{1842}', '\u{1844}', '\u{1845}', '\u{1846}', '\u{1847}', '\u{1848}', '\u{1849}', '\u{184A}', '\u{184B}', '\u{184C}', '\u{184D}', '\u{184E}', '\u{184F}', '\u{1850}', '\u{1851}', '\u{1852}', '\u{1853}', '\u{1854}', '\u{1855}', '\u{1856}', '\u{1857}', '\u{1858}', '\u{1859}', '\u{185A}', '\u{185B}', '\u{185C}', '\u{185D}', '\u{185E}', '\u{185F}', '\u{1860}', '\u{1861}', '\u{1862}', '\u{1863}', '\u{1864}', '\u{1865}', '\u{1866}', '\u{1867}', '\u{1868}', '\u{1869}', '\u{186A}', '\u{186B}', '\u{186C}', '\u{186D}', '\u{186E}', '\u{186F}', '\u{1870}', '\u{1871}', '\u{1872}', '\u{1873}', '\u{1874}', '\u{1875}', '\u{1876}', '\u{1877}', '\u{1880}', '\u{1881}', '\u{1882}', '\u{1883}', '\u{1884}', '\u{1885}', '\u{1886}', '\u{1887}', '\u{1888}', '\u{1889}', '\u{188A}', '\u{188B}', '\u{188C}', '\u{188D}', '\u{188E}', '\u{188F}', '\u{1890}', '\u{1891}', '\u{1892}', '\u{1893}', '\u{1894}', '\u{1895}', '\u{1896}', '\u{1897}', '\u{1898}', '\u{1899}', '\u{189A}', '\u{189B}', '\u{189C}', '\u{189D}', '\u{189E}', '\u{189F}', '\u{18A0}', '\u{18A1}', '\u{18A2}', '\u{18A3}', '\u{18A4}', '\u{18A5}', '\u{18A6}', '\u{18A7}', '\u{18A8}', '\u{18AA}', '\u{1900}', '\u{1901}', '\u{1902}', '\u{1903}', '\u{1904}', '\u{1905}', '\u{1906}', '\u{1907}', '\u{1908}', '\u{1909}', '\u{190A}', '\u{190B}', '\u{190C}', '\u{190D}', '\u{190E}', '\u{190F}', '\u{1910}', '\u{1911}', '\u{1912}', '\u{1913}', '\u{1914}', '\u{1915}', '\u{1916}', '\u{1917}', '\u{1918}', '\u{1919}', '\u{191A}', '\u{191B}', '\u{191C}', '\u{1950}', '\u{1951}', '\u{1952}', '\u{1953}', '\u{1954}', '\u{1955}', '\u{1956}', '\u{1957}', '\u{1958}', '\u{1959}', '\u{195A}', '\u{195B}', '\u{195C}', '\u{195D}', '\u{195E}', '\u{195F}', '\u{1960}', '\u{1961}', '\u{1962}', '\u{1963}', '\u{1964}', '\u{1965}', '\u{1966}', '\u{1967}', '\u{1968}', '\u{1969}', '\u{196A}', '\u{196B}', '\u{196C}', '\u{196D}', '\u{1970}', '\u{1971}', '\u{1972}', '\u{1973}', '\u{1974}', '\u{1980}', '\u{1981}', '\u{1982}', '\u{1983}', '\u{1984}', '\u{1985}', '\u{1986}', '\u{1987}', '\u{1988}', '\u{1989}', '\u{198A}', '\u{198B}', '\u{198C}', '\u{198D}', '\u{198E}', '\u{198F}', '\u{1990}', '\u{1991}', '\u{1992}', '\u{1993}', '\u{1994}', '\u{1995}', '\u{1996}', '\u{1997}', '\u{1998}', '\u{1999}', '\u{199A}', '\u{199B}', '\u{199C}', '\u{199D}', '\u{199E}', '\u{199F}', '\u{19A0}', '\u{19A1}', '\u{19A2}', '\u{19A3}', '\u{19A4}', '\u{19A5}', '\u{19A6}', '\u{19A7}', '\u{19A8}', '\u{19A9}', '\u{19C1}', '\u{19C2}', '\u{19C3}', '\u{19C4}', '\u{19C5}', '\u{19C6}', '\u{19C7}', '\u{1A00}', '\u{1A01}', '\u{1A02}', '\u{1A03}', '\u{1A04}', '\u{1A05}', '\u{1A06}', '\u{1A07}', '\u{1A08}', '\u{1A09}', '\u{1A0A}', '\u{1A0B}', '\u{1A0C}', '\u{1A0D}', '\u{1A0E}', '\u{1A0F}', '\u{1A10}', '\u{1A11}', '\u{1A12}', '\u{1A13}', '\u{1A14}', '\u{1A15}', '\u{1A16}', '\u{1B05}', '\u{1B06}', '\u{1B07}', '\u{1B08}', '\u{1B09}', '\u{1B0A}', '\u{1B0B}', '\u{1B0C}', '\u{1B0D}', '\u{1B0E}', '\u{1B0F}', '\u{1B10}', '\u{1B11}', '\u{1B12}', '\u{1B13}', '\u{1B14}', '\u{1B15}', '\u{1B16}', '\u{1B17}', '\u{1B18}', '\u{1B19}', '\u{1B1A}', '\u{1B1B}', '\u{1B1C}', '\u{1B1D}', '\u{1B1E}', '\u{1B1F}', '\u{1B20}', '\u{1B21}', '\u{1B22}', '\u{1B23}', '\u{1B24}', '\u{1B25}', '\u{1B26}', '\u{1B27}', '\u{1B28}', '\u{1B29}', '\u{1B2A}', '\u{1B2B}', '\u{1B2C}', '\u{1B2D}', '\u{1B2E}', '\u{1B2F}', '\u{1B30}', '\u{1B31}', '\u{1B32}', '\u{1B33}', '\u{1B45}', '\u{1B46}', '\u{1B47}', '\u{1B48}', '\u{1B49}', '\u{1B4A}', '\u{1B4B}', '\u{1B83}', '\u{1B84}', '\u{1B85}', '\u{1B86}', '\u{1B87}', '\u{1B88}', '\u{1B89}', '\u{1B8A}', '\u{1B8B}', '\u{1B8C}', '\u{1B8D}', '\u{1B8E}', '\u{1B8F}', '\u{1B90}', '\u{1B91}', '\u{1B92}', '\u{1B93}', '\u{1B94}', '\u{1B95}', '\u{1B96}', '\u{1B97}', '\u{1B98}', '\u{1B99}', '\u{1B9A}', '\u{1B9B}', '\u{1B9C}', '\u{1B9D}', '\u{1B9E}', '\u{1B9F}', '\u{1BA0}', '\u{1BAE}', '\u{1BAF}', '\u{1C00}', '\u{1C01}', '\u{1C02}', '\u{1C03}', '\u{1C04}', '\u{1C05}', '\u{1C06}', '\u{1C07}', '\u{1C08}', '\u{1C09}', '\u{1C0A}', '\u{1C0B}', '\u{1C0C}', '\u{1C0D}', '\u{1C0E}', '\u{1C0F}', '\u{1C10}', '\u{1C11}', '\u{1C12}', '\u{1C13}', '\u{1C14}', '\u{1C15}', '\u{1C16}', '\u{1C17}', '\u{1C18}', '\u{1C19}', '\u{1C1A}', '\u{1C1B}', '\u{1C1C}', '\u{1C1D}', '\u{1C1E}', '\u{1C1F}', '\u{1C20}', '\u{1C21}', '\u{1C22}', '\u{1C23}', '\u{1C4D}', '\u{1C4E}', '\u{1C4F}', '\u{1C5A}', '\u{1C5B}', '\u{1C5C}', '\u{1C5D}', '\u{1C5E}', '\u{1C5F}', '\u{1C60}', '\u{1C61}', '\u{1C62}', '\u{1C63}', '\u{1C64}', '\u{1C65}', '\u{1C66}', '\u{1C67}', '\u{1C68}', '\u{1C69}', '\u{1C6A}', '\u{1C6B}', '\u{1C6C}', '\u{1C6D}', '\u{1C6E}', '\u{1C6F}', '\u{1C70}', '\u{1C71}', '\u{1C72}', '\u{1C73}', '\u{1C74}', '\u{1C75}', '\u{1C76}', '\u{1C77}', '\u{2135}', '\u{2136}', '\u{2137}', '\u{2138}', '\u{2D30}', '\u{2D31}', '\u{2D32}', '\u{2D33}', '\u{2D34}', '\u{2D35}', '\u{2D36}', '\u{2D37}', '\u{2D38}', '\u{2D39}', '\u{2D3A}', '\u{2D3B}', '\u{2D3C}', '\u{2D3D}', '\u{2D3E}', '\u{2D3F}', '\u{2D40}', '\u{2D41}', '\u{2D42}', '\u{2D43}', '\u{2D44}', '\u{2D45}', '\u{2D46}', '\u{2D47}', '\u{2D48}', '\u{2D49}', '\u{2D4A}', '\u{2D4B}', '\u{2D4C}', '\u{2D4D}', '\u{2D4E}', '\u{2D4F}', '\u{2D50}', '\u{2D51}', '\u{2D52}', '\u{2D53}', '\u{2D54}', '\u{2D55}', '\u{2D56}', '\u{2D57}', '\u{2D58}', '\u{2D59}', '\u{2D5A}', '\u{2D5B}', '\u{2D5C}', '\u{2D5D}', '\u{2D5E}', '\u{2D5F}', '\u{2D60}', '\u{2D61}', '\u{2D62}', '\u{2D63}', '\u{2D64}', '\u{2D65}', '\u{2D80}', '\u{2D81}', '\u{2D82}', '\u{2D83}', '\u{2D84}', '\u{2D85}', '\u{2D86}', '\u{2D87}', '\u{2D88}', '\u{2D89}', '\u{2D8A}', '\u{2D8B}', '\u{2D8C}', '\u{2D8D}', '\u{2D8E}', '\u{2D8F}', '\u{2D90}', '\u{2D91}', '\u{2D92}', '\u{2D93}', '\u{2D94}', '\u{2D95}', '\u{2D96}', '\u{2DA0}', '\u{2DA1}', '\u{2DA2}', '\u{2DA3}', '\u{2DA4}', '\u{2DA5}', '\u{2DA6}', '\u{2DA8}', '\u{2DA9}', '\u{2DAA}', '\u{2DAB}', '\u{2DAC}', '\u{2DAD}', '\u{2DAE}', '\u{2DB0}', '\u{2DB1}', '\u{2DB2}', '\u{2DB3}', '\u{2DB4}', '\u{2DB5}', '\u{2DB6}', '\u{2DB8}', '\u{2DB9}', '\u{2DBA}', '\u{2DBB}', '\u{2DBC}', '\u{2DBD}', '\u{2DBE}', '\u{2DC0}', '\u{2DC1}', '\u{2DC2}', '\u{2DC3}', '\u{2DC4}', '\u{2DC5}', '\u{2DC6}', '\u{2DC8}', '\u{2DC9}', '\u{2DCA}', '\u{2DCB}', '\u{2DCC}', '\u{2DCD}', '\u{2DCE}', '\u{2DD0}', '\u{2DD1}', '\u{2DD2}', '\u{2DD3}', '\u{2DD4}', '\u{2DD5}', '\u{2DD6}', '\u{2DD8}', '\u{2DD9}', '\u{2DDA}', '\u{2DDB}', '\u{2DDC}', '\u{2DDD}', '\u{2DDE}', '\u{3006}', '\u{303C}', '\u{3041}', '\u{3042}', '\u{3043}', '\u{3044}', '\u{3045}', '\u{3046}', '\u{3047}', '\u{3048}', '\u{3049}', '\u{304A}', '\u{304B}', '\u{304C}', '\u{304D}', '\u{304E}', '\u{304F}', '\u{3050}', '\u{3051}', '\u{3052}', '\u{3053}', '\u{3054}', '\u{3055}', '\u{3056}', '\u{3057}', '\u{3058}', '\u{3059}', '\u{305A}', '\u{305B}', '\u{305C}', '\u{305D}', '\u{305E}', '\u{305F}', '\u{3060}', '\u{3061}', '\u{3062}', '\u{3063}', '\u{3064}', '\u{3065}', '\u{3066}', '\u{3067}', '\u{3068}', '\u{3069}', '\u{306A}', '\u{306B}', '\u{306C}', '\u{306D}', '\u{306E}', '\u{306F}', '\u{3070}', '\u{3071}', '\u{3072}', '\u{3073}', '\u{3074}', '\u{3075}', '\u{3076}', '\u{3077}', '\u{3078}', '\u{3079}', '\u{307A}', '\u{307B}', '\u{307C}', '\u{307D}', '\u{307E}', '\u{307F}', '\u{3080}', '\u{3081}', '\u{3082}', '\u{3083}', '\u{3084}', '\u{3085}', '\u{3086}', '\u{3087}', '\u{3088}', '\u{3089}', '\u{308A}', '\u{308B}', '\u{308C}', '\u{308D}', '\u{308E}', '\u{308F}', '\u{3090}', '\u{3091}', '\u{3092}', '\u{3093}', '\u{3094}', '\u{3095}', '\u{3096}', '\u{309F}', '\u{30A1}', '\u{30A2}', '\u{30A3}', '\u{30A4}', '\u{30A5}', '\u{30A6}', '\u{30A7}', '\u{30A8}', '\u{30A9}', '\u{30AA}', '\u{30AB}', '\u{30AC}', '\u{30AD}', '\u{30AE}', '\u{30AF}', '\u{30B0}', '\u{30B1}', '\u{30B2}', '\u{30B3}', '\u{30B4}', '\u{30B5}', '\u{30B6}', '\u{30B7}', '\u{30B8}', '\u{30B9}', '\u{30BA}', '\u{30BB}', '\u{30BC}', '\u{30BD}', '\u{30BE}', '\u{30BF}', '\u{30C0}', '\u{30C1}', '\u{30C2}', '\u{30C3}', '\u{30C4}', '\u{30C5}', '\u{30C6}', '\u{30C7}', '\u{30C8}', '\u{30C9}', '\u{30CA}', '\u{30CB}', '\u{30CC}', '\u{30CD}', '\u{30CE}', '\u{30CF}', '\u{30D0}', '\u{30D1}', '\u{30D2}', '\u{30D3}', '\u{30D4}', '\u{30D5}', '\u{30D6}', '\u{30D7}', '\u{30D8}', '\u{30D9}', '\u{30DA}', '\u{30DB}', '\u{30DC}', '\u{30DD}', '\u{30DE}', '\u{30DF}', '\u{30E0}', '\u{30E1}', '\u{30E2}', '\u{30E3}', '\u{30E4}', '\u{30E5}', '\u{30E6}', '\u{30E7}', '\u{30E8}', '\u{30E9}', '\u{30EA}', '\u{30EB}', '\u{30EC}', '\u{30ED}', '\u{30EE}', '\u{30EF}', '\u{30F0}', '\u{30F1}', '\u{30F2}', '\u{30F3}', '\u{30F4}', '\u{30F5}', '\u{30F6}', '\u{30F7}', '\u{30F8}', '\u{30F9}', '\u{30FA}', '\u{30FF}', '\u{3105}', '\u{3106}', '\u{3107}', '\u{3108}', '\u{3109}', '\u{310A}', '\u{310B}', '\u{310C}', '\u{310D}', '\u{310E}', '\u{310F}', '\u{3110}', '\u{3111}', '\u{3112}', '\u{3113}', '\u{3114}', '\u{3115}', '\u{3116}', '\u{3117}', '\u{3118}', '\u{3119}', '\u{311A}', '\u{311B}', '\u{311C}', '\u{311D}', '\u{311E}', '\u{311F}', '\u{3120}', '\u{3121}', '\u{3122}', '\u{3123}', '\u{3124}', '\u{3125}', '\u{3126}', '\u{3127}', '\u{3128}', '\u{3129}', '\u{312A}', '\u{312B}', '\u{312C}', '\u{312D}', '\u{3131}', '\u{3132}', '\u{3133}', '\u{3134}', '\u{3135}', '\u{3136}', '\u{3137}', '\u{3138}', '\u{3139}', '\u{313A}', '\u{313B}', '\u{313C}', '\u{313D}', '\u{313E}', '\u{313F}', '\u{3140}', '\u{3141}', '\u{3142}', '\u{3143}', '\u{3144}', '\u{3145}', '\u{3146}', '\u{3147}', '\u{3148}', '\u{3149}', '\u{314A}', '\u{314B}', '\u{314C}', '\u{314D}', '\u{314E}', '\u{314F}', '\u{3150}', '\u{3151}', '\u{3152}', '\u{3153}', '\u{3154}', '\u{3155}', '\u{3156}', '\u{3157}', '\u{3158}', '\u{3159}', '\u{315A}', '\u{315B}', '\u{315C}', '\u{315D}', '\u{315E}', '\u{315F}', '\u{3160}', '\u{3161}', '\u{3162}', '\u{3163}', '\u{3164}', '\u{3165}', '\u{3166}', '\u{3167}', '\u{3168}', '\u{3169}', '\u{316A}', '\u{316B}', '\u{316C}', '\u{316D}', '\u{316E}', '\u{316F}', '\u{3170}', '\u{3171}', '\u{3172}', '\u{3173}', '\u{3174}', '\u{3175}', '\u{3176}', '\u{3177}', '\u{3178}', '\u{3179}', '\u{317A}', '\u{317B}', '\u{317C}', '\u{317D}', '\u{317E}', '\u{317F}', '\u{3180}', '\u{3181}', '\u{3182}', '\u{3183}', '\u{3184}', '\u{3185}', '\u{3186}', '\u{3187}', '\u{3188}', '\u{3189}', '\u{318A}', '\u{318B}', '\u{318C}', '\u{318D}', '\u{318E}', '\u{31A0}', '\u{31A1}', '\u{31A2}', '\u{31A3}', '\u{31A4}', '\u{31A5}', '\u{31A6}', '\u{31A7}', '\u{31A8}', '\u{31A9}', '\u{31AA}', '\u{31AB}', '\u{31AC}', '\u{31AD}', '\u{31AE}', '\u{31AF}', '\u{31B0}', '\u{31B1}', '\u{31B2}', '\u{31B3}', '\u{31B4}', '\u{31B5}', '\u{31B6}', '\u{31B7}', '\u{31F0}', '\u{31F1}', '\u{31F2}', '\u{31F3}', '\u{31F4}', '\u{31F5}', '\u{31F6}', '\u{31F7}', '\u{31F8}', '\u{31F9}', '\u{31FA}', '\u{31FB}', '\u{31FC}', '\u{31FD}', '\u{31FE}', '\u{31FF}', '\u{3400}', '\u{4DB5}', '\u{4E00}', '\u{9FC3}', '\u{A000}', '\u{A001}', '\u{A002}', '\u{A003}', '\u{A004}', '\u{A005}', '\u{A006}', '\u{A007}', '\u{A008}', '\u{A009}', '\u{A00A}', '\u{A00B}', '\u{A00C}', '\u{A00D}', '\u{A00E}', '\u{A00F}', '\u{A010}', '\u{A011}', '\u{A012}', '\u{A013}', '\u{A014}', '\u{A016}', '\u{A017}', '\u{A018}', '\u{A019}', '\u{A01A}', '\u{A01B}', '\u{A01C}', '\u{A01D}', '\u{A01E}', '\u{A01F}', '\u{A020}', '\u{A021}', '\u{A022}', '\u{A023}', '\u{A024}', '\u{A025}', '\u{A026}', '\u{A027}', '\u{A028}', '\u{A029}', '\u{A02A}', '\u{A02B}', '\u{A02C}', '\u{A02D}', '\u{A02E}', '\u{A02F}', '\u{A030}', '\u{A031}', '\u{A032}', '\u{A033}', '\u{A034}', '\u{A035}', '\u{A036}', '\u{A037}', '\u{A038}', '\u{A039}', '\u{A03A}', '\u{A03B}', '\u{A03C}', '\u{A03D}', '\u{A03E}', '\u{A03F}', '\u{A040}', '\u{A041}', '\u{A042}', '\u{A043}', '\u{A044}', '\u{A045}', '\u{A046}', '\u{A047}', '\u{A048}', '\u{A049}', '\u{A04A}', '\u{A04B}', '\u{A04C}', '\u{A04D}', '\u{A04E}', '\u{A04F}', '\u{A050}', '\u{A051}', '\u{A052}', '\u{A053}', '\u{A054}', '\u{A055}', '\u{A056}', '\u{A057}', '\u{A058}', '\u{A059}', '\u{A05A}', '\u{A05B}', '\u{A05C}', '\u{A05D}', '\u{A05E}', '\u{A05F}', '\u{A060}', '\u{A061}', '\u{A062}', '\u{A063}', '\u{A064}', '\u{A065}', '\u{A066}', '\u{A067}', '\u{A068}', '\u{A069}', '\u{A06A}', '\u{A06B}', '\u{A06C}', '\u{A06D}', '\u{A06E}', '\u{A06F}', '\u{A070}', '\u{A071}', '\u{A072}', '\u{A073}', '\u{A074}', '\u{A075}', '\u{A076}', '\u{A077}', '\u{A078}', '\u{A079}', '\u{A07A}', '\u{A07B}', '\u{A07C}', '\u{A07D}', '\u{A07E}', '\u{A07F}', '\u{A080}', '\u{A081}', '\u{A082}', '\u{A083}', '\u{A084}', '\u{A085}', '\u{A086}', '\u{A087}', '\u{A088}', '\u{A089}', '\u{A08A}', '\u{A08B}', '\u{A08C}', '\u{A08D}', '\u{A08E}', '\u{A08F}', '\u{A090}', '\u{A091}', '\u{A092}', '\u{A093}', '\u{A094}', '\u{A095}', '\u{A096}', '\u{A097}', '\u{A098}', '\u{A099}', '\u{A09A}', '\u{A09B}', '\u{A09C}', '\u{A09D}', '\u{A09E}', '\u{A09F}', '\u{A0A0}', '\u{A0A1}', '\u{A0A2}', '\u{A0A3}', '\u{A0A4}', '\u{A0A5}', '\u{A0A6}', '\u{A0A7}', '\u{A0A8}', '\u{A0A9}', '\u{A0AA}', '\u{A0AB}', '\u{A0AC}', '\u{A0AD}', '\u{A0AE}', '\u{A0AF}', '\u{A0B0}', '\u{A0B1}', '\u{A0B2}', '\u{A0B3}', '\u{A0B4}', '\u{A0B5}', '\u{A0B6}', '\u{A0B7}', '\u{A0B8}', '\u{A0B9}', '\u{A0BA}', '\u{A0BB}', '\u{A0BC}', '\u{A0BD}', '\u{A0BE}', '\u{A0BF}', '\u{A0C0}', '\u{A0C1}', '\u{A0C2}', '\u{A0C3}', '\u{A0C4}', '\u{A0C5}', '\u{A0C6}', '\u{A0C7}', '\u{A0C8}', '\u{A0C9}', '\u{A0CA}', '\u{A0CB}', '\u{A0CC}', '\u{A0CD}', '\u{A0CE}', '\u{A0CF}', '\u{A0D0}', '\u{A0D1}', '\u{A0D2}', '\u{A0D3}', '\u{A0D4}', '\u{A0D5}', '\u{A0D6}', '\u{A0D7}', '\u{A0D8}', '\u{A0D9}', '\u{A0DA}', '\u{A0DB}', '\u{A0DC}', '\u{A0DD}', '\u{A0DE}', '\u{A0DF}', '\u{A0E0}', '\u{A0E1}', '\u{A0E2}', '\u{A0E3}', '\u{A0E4}', '\u{A0E5}', '\u{A0E6}', '\u{A0E7}', '\u{A0E8}', '\u{A0E9}', '\u{A0EA}', '\u{A0EB}', '\u{A0EC}', '\u{A0ED}', '\u{A0EE}', '\u{A0EF}', '\u{A0F0}', '\u{A0F1}', '\u{A0F2}', '\u{A0F3}', '\u{A0F4}', '\u{A0F5}', '\u{A0F6}', '\u{A0F7}', '\u{A0F8}', '\u{A0F9}', '\u{A0FA}', '\u{A0FB}', '\u{A0FC}', '\u{A0FD}', '\u{A0FE}', '\u{A0FF}', '\u{A100}', '\u{A101}', '\u{A102}', '\u{A103}', '\u{A104}', '\u{A105}', '\u{A106}', '\u{A107}', '\u{A108}', '\u{A109}', '\u{A10A}', '\u{A10B}', '\u{A10C}', '\u{A10D}', '\u{A10E}', '\u{A10F}', '\u{A110}', '\u{A111}', '\u{A112}', '\u{A113}', '\u{A114}', '\u{A115}', '\u{A116}', '\u{A117}', '\u{A118}', '\u{A119}', '\u{A11A}', '\u{A11B}', '\u{A11C}', '\u{A11D}', '\u{A11E}', '\u{A11F}', '\u{A120}', '\u{A121}', '\u{A122}', '\u{A123}', '\u{A124}', '\u{A125}', '\u{A126}', '\u{A127}', '\u{A128}', '\u{A129}', '\u{A12A}', '\u{A12B}', '\u{A12C}', '\u{A12D}', '\u{A12E}', '\u{A12F}', '\u{A130}', '\u{A131}', '\u{A132}', '\u{A133}', '\u{A134}', '\u{A135}', '\u{A136}', '\u{A137}', '\u{A138}', '\u{A139}', '\u{A13A}', '\u{A13B}', '\u{A13C}', '\u{A13D}', '\u{A13E}', '\u{A13F}', '\u{A140}', '\u{A141}', '\u{A142}', '\u{A143}', '\u{A144}', '\u{A145}', '\u{A146}', '\u{A147}', '\u{A148}', '\u{A149}', '\u{A14A}', '\u{A14B}', '\u{A14C}', '\u{A14D}', '\u{A14E}', '\u{A14F}', '\u{A150}', '\u{A151}', '\u{A152}', '\u{A153}', '\u{A154}', '\u{A155}', '\u{A156}', '\u{A157}', '\u{A158}', '\u{A159}', '\u{A15A}', '\u{A15B}', '\u{A15C}', '\u{A15D}', '\u{A15E}', '\u{A15F}', '\u{A160}', '\u{A161}', '\u{A162}', '\u{A163}', '\u{A164}', '\u{A165}', '\u{A166}', '\u{A167}', '\u{A168}', '\u{A169}', '\u{A16A}', '\u{A16B}', '\u{A16C}', '\u{A16D}', '\u{A16E}', '\u{A16F}', '\u{A170}', '\u{A171}', '\u{A172}', '\u{A173}', '\u{A174}', '\u{A175}', '\u{A176}', '\u{A177}', '\u{A178}', '\u{A179}', '\u{A17A}', '\u{A17B}', '\u{A17C}', '\u{A17D}', '\u{A17E}', '\u{A17F}', '\u{A180}', '\u{A181}', '\u{A182}', '\u{A183}', '\u{A184}', '\u{A185}', '\u{A186}', '\u{A187}', '\u{A188}', '\u{A189}', '\u{A18A}', '\u{A18B}', '\u{A18C}', '\u{A18D}', '\u{A18E}', '\u{A18F}', '\u{A190}', '\u{A191}', '\u{A192}', '\u{A193}', '\u{A194}', '\u{A195}', '\u{A196}', '\u{A197}', '\u{A198}', '\u{A199}', '\u{A19A}', '\u{A19B}', '\u{A19C}', '\u{A19D}', '\u{A19E}', '\u{A19F}', '\u{A1A0}', '\u{A1A1}', '\u{A1A2}', '\u{A1A3}', '\u{A1A4}', '\u{A1A5}', '\u{A1A6}', '\u{A1A7}', '\u{A1A8}', '\u{A1A9}', '\u{A1AA}', '\u{A1AB}', '\u{A1AC}', '\u{A1AD}', '\u{A1AE}', '\u{A1AF}') + } + + fn is_unicode_combining_spacing_mark(self) -> bool { + match_char_class!(self, + '\u{0903}', '\u{093E}', '\u{093F}', '\u{0940}', '\u{0949}', '\u{094A}', '\u{094B}', '\u{094C}', '\u{0982}', '\u{0983}', '\u{09BE}', '\u{09BF}', '\u{09C0}', '\u{09C7}', '\u{09C8}', '\u{09CB}', '\u{09CC}', '\u{09D7}', '\u{0A03}', '\u{0A3E}', '\u{0A3F}', '\u{0A40}', '\u{0A83}', '\u{0ABE}', '\u{0ABF}', '\u{0AC0}', '\u{0AC9}', '\u{0ACB}', '\u{0ACC}', '\u{0B02}', '\u{0B03}', '\u{0B3E}', '\u{0B40}', '\u{0B47}', '\u{0B48}', '\u{0B4B}', '\u{0B4C}', '\u{0B57}', '\u{0BBE}', '\u{0BBF}', '\u{0BC1}', '\u{0BC2}', '\u{0BC6}', '\u{0BC7}', '\u{0BC8}', '\u{0BCA}', '\u{0BCB}', '\u{0BCC}', '\u{0BD7}', '\u{0C01}', '\u{0C02}', '\u{0C03}', '\u{0C41}', '\u{0C42}', '\u{0C43}', '\u{0C44}', '\u{0C82}', '\u{0C83}', '\u{0CBE}', '\u{0CC0}', '\u{0CC1}', '\u{0CC2}', '\u{0CC3}', '\u{0CC4}', '\u{0CC7}', '\u{0CC8}', '\u{0CCA}', '\u{0CCB}', '\u{0CD5}', '\u{0CD6}', '\u{0D02}', '\u{0D03}', '\u{0D3E}', '\u{0D3F}', '\u{0D40}', '\u{0D46}', '\u{0D47}', '\u{0D48}', '\u{0D4A}', '\u{0D4B}', '\u{0D4C}', '\u{0D57}', '\u{0D82}', '\u{0D83}', '\u{0DCF}', '\u{0DD0}', '\u{0DD1}', '\u{0DD8}', '\u{0DD9}', '\u{0DDA}', '\u{0DDB}', '\u{0DDC}', '\u{0DDD}', '\u{0DDE}', '\u{0DDF}', '\u{0DF2}', '\u{0DF3}', '\u{0F3E}', '\u{0F3F}', '\u{0F7F}', '\u{102B}', '\u{102C}', '\u{1031}', '\u{1038}', '\u{103B}', '\u{103C}', '\u{1056}', '\u{1057}', '\u{1062}', '\u{1063}', '\u{1064}', '\u{1067}', '\u{1068}', '\u{1069}', '\u{106A}', '\u{106B}', '\u{106C}', '\u{106D}', '\u{1083}', '\u{1084}', '\u{1087}', '\u{1088}', '\u{1089}', '\u{108A}', '\u{108B}', '\u{108C}', '\u{108F}', '\u{17B6}', '\u{17BE}', '\u{17BF}', '\u{17C0}', '\u{17C1}', '\u{17C2}', '\u{17C3}', '\u{17C4}', '\u{17C5}', '\u{17C7}', '\u{17C8}', '\u{1923}', '\u{1924}', '\u{1925}', '\u{1926}', '\u{1929}', '\u{192A}', '\u{192B}', '\u{1930}', '\u{1931}', '\u{1933}', '\u{1934}', '\u{1935}', '\u{1936}', '\u{1937}', '\u{1938}', '\u{19B0}', '\u{19B1}', '\u{19B2}', '\u{19B3}', '\u{19B4}', '\u{19B5}', '\u{19B6}', '\u{19B7}', '\u{19B8}', '\u{19B9}', '\u{19BA}', '\u{19BB}', '\u{19BC}', '\u{19BD}', '\u{19BE}', '\u{19BF}', '\u{19C0}', '\u{19C8}', '\u{19C9}', '\u{1A19}', '\u{1A1A}', '\u{1A1B}', '\u{1B04}', '\u{1B35}', '\u{1B3B}', '\u{1B3D}', '\u{1B3E}', '\u{1B3F}', '\u{1B40}', '\u{1B41}', '\u{1B43}', '\u{1B44}', '\u{1B82}', '\u{1BA1}', '\u{1BA6}', '\u{1BA7}', '\u{1BAA}', '\u{1C24}', '\u{1C25}', '\u{1C26}', '\u{1C27}', '\u{1C28}', '\u{1C29}', '\u{1C2A}', '\u{1C2B}', '\u{1C34}', '\u{1C35}', '\u{A823}', '\u{A824}', '\u{A827}', '\u{A880}', '\u{A881}', '\u{A8B4}', '\u{A8B5}', '\u{A8B6}', '\u{A8B7}', '\u{A8B8}', '\u{A8B9}', '\u{A8BA}', '\u{A8BB}', '\u{A8BC}', '\u{A8BD}', '\u{A8BE}', '\u{A8BF}', '\u{A8C0}', '\u{A8C1}', '\u{A8C2}', '\u{A8C3}', '\u{A952}', '\u{A953}', '\u{AA2F}', '\u{AA30}', '\u{AA33}', '\u{AA34}', '\u{AA4D}') + } + + fn is_unicode_decimal_number(self) -> bool { + match_char_class!(self, + '\u{0030}', '\u{0031}', '\u{0032}', '\u{0033}', '\u{0034}', '\u{0035}', '\u{0036}', '\u{0037}', '\u{0038}', '\u{0039}', '\u{0660}', '\u{0661}', '\u{0662}', '\u{0663}', '\u{0664}', '\u{0665}', '\u{0666}', '\u{0667}', '\u{0668}', '\u{0669}', '\u{06F0}', '\u{06F1}', '\u{06F2}', '\u{06F3}', '\u{06F4}', '\u{06F5}', '\u{06F6}', '\u{06F7}', '\u{06F8}', '\u{06F9}', '\u{07C0}', '\u{07C1}', '\u{07C2}', '\u{07C3}', '\u{07C4}', '\u{07C5}', '\u{07C6}', '\u{07C7}', '\u{07C8}', '\u{07C9}', '\u{0966}', '\u{0967}', '\u{0968}', '\u{0969}', '\u{096A}', '\u{096B}', '\u{096C}', '\u{096D}', '\u{096E}', '\u{096F}', '\u{09E6}', '\u{09E7}', '\u{09E8}', '\u{09E9}', '\u{09EA}', '\u{09EB}', '\u{09EC}', '\u{09ED}', '\u{09EE}', '\u{09EF}', '\u{0A66}', '\u{0A67}', '\u{0A68}', '\u{0A69}', '\u{0A6A}', '\u{0A6B}', '\u{0A6C}', '\u{0A6D}', '\u{0A6E}', '\u{0A6F}', '\u{0AE6}', '\u{0AE7}', '\u{0AE8}', '\u{0AE9}', '\u{0AEA}', '\u{0AEB}', '\u{0AEC}', '\u{0AED}', '\u{0AEE}', '\u{0AEF}', '\u{0B66}', '\u{0B67}', '\u{0B68}', '\u{0B69}', '\u{0B6A}', '\u{0B6B}', '\u{0B6C}', '\u{0B6D}', '\u{0B6E}', '\u{0B6F}', '\u{0BE6}', '\u{0BE7}', '\u{0BE8}', '\u{0BE9}', '\u{0BEA}', '\u{0BEB}', '\u{0BEC}', '\u{0BED}', '\u{0BEE}', '\u{0BEF}', '\u{0C66}', '\u{0C67}', '\u{0C68}', '\u{0C69}', '\u{0C6A}', '\u{0C6B}', '\u{0C6C}', '\u{0C6D}', '\u{0C6E}', '\u{0C6F}', '\u{0CE6}', '\u{0CE7}', '\u{0CE8}', '\u{0CE9}', '\u{0CEA}', '\u{0CEB}', '\u{0CEC}', '\u{0CED}', '\u{0CEE}', '\u{0CEF}', '\u{0D66}', '\u{0D67}', '\u{0D68}', '\u{0D69}', '\u{0D6A}', '\u{0D6B}', '\u{0D6C}', '\u{0D6D}', '\u{0D6E}', '\u{0D6F}', '\u{0E50}', '\u{0E51}', '\u{0E52}', '\u{0E53}', '\u{0E54}', '\u{0E55}', '\u{0E56}', '\u{0E57}', '\u{0E58}', '\u{0E59}', '\u{0ED0}', '\u{0ED1}', '\u{0ED2}', '\u{0ED3}', '\u{0ED4}', '\u{0ED5}', '\u{0ED6}', '\u{0ED7}', '\u{0ED8}', '\u{0ED9}', '\u{0F20}', '\u{0F21}', '\u{0F22}', '\u{0F23}', '\u{0F24}', '\u{0F25}', '\u{0F26}', '\u{0F27}', '\u{0F28}', '\u{0F29}', '\u{1040}', '\u{1041}', '\u{1042}', '\u{1043}', '\u{1044}', '\u{1045}', '\u{1046}', '\u{1047}', '\u{1048}', '\u{1049}', '\u{1090}', '\u{1091}', '\u{1092}', '\u{1093}', '\u{1094}', '\u{1095}', '\u{1096}', '\u{1097}', '\u{1098}', '\u{1099}', '\u{17E0}', '\u{17E1}', '\u{17E2}', '\u{17E3}', '\u{17E4}', '\u{17E5}', '\u{17E6}', '\u{17E7}', '\u{17E8}', '\u{17E9}', '\u{1810}', '\u{1811}', '\u{1812}', '\u{1813}', '\u{1814}', '\u{1815}', '\u{1816}', '\u{1817}', '\u{1818}', '\u{1819}', '\u{1946}', '\u{1947}', '\u{1948}', '\u{1949}', '\u{194A}', '\u{194B}', '\u{194C}', '\u{194D}', '\u{194E}', '\u{194F}', '\u{19D0}', '\u{19D1}', '\u{19D2}', '\u{19D3}', '\u{19D4}', '\u{19D5}', '\u{19D6}', '\u{19D7}', '\u{19D8}', '\u{19D9}', '\u{1B50}', '\u{1B51}', '\u{1B52}', '\u{1B53}', '\u{1B54}', '\u{1B55}', '\u{1B56}', '\u{1B57}', '\u{1B58}', '\u{1B59}', '\u{1BB0}', '\u{1BB1}', '\u{1BB2}', '\u{1BB3}', '\u{1BB4}', '\u{1BB5}', '\u{1BB6}', '\u{1BB7}', '\u{1BB8}', '\u{1BB9}', '\u{1C40}', '\u{1C41}', '\u{1C42}', '\u{1C43}', '\u{1C44}', '\u{1C45}', '\u{1C46}', '\u{1C47}', '\u{1C48}', '\u{1C49}', '\u{1C50}', '\u{1C51}', '\u{1C52}', '\u{1C53}', '\u{1C54}', '\u{1C55}', '\u{1C56}', '\u{1C57}', '\u{1C58}', '\u{1C59}', '\u{A620}', '\u{A621}', '\u{A622}', '\u{A623}', '\u{A624}', '\u{A625}', '\u{A626}', '\u{A627}', '\u{A628}', '\u{A629}', '\u{A8D0}', '\u{A8D1}', '\u{A8D2}', '\u{A8D3}', '\u{A8D4}', '\u{A8D5}', '\u{A8D6}', '\u{A8D7}', '\u{A8D8}', '\u{A8D9}', '\u{A900}', '\u{A901}', '\u{A902}', '\u{A903}', '\u{A904}', '\u{A905}', '\u{A906}', '\u{A907}', '\u{A908}', '\u{A909}', '\u{AA50}', '\u{AA51}', '\u{AA52}', '\u{AA53}', '\u{AA54}', '\u{AA55}', '\u{AA56}', '\u{AA57}', '\u{AA58}', '\u{AA59}', '\u{FF10}', '\u{FF11}', '\u{FF12}', '\u{FF13}', '\u{FF14}', '\u{FF15}', '\u{FF16}', '\u{FF17}', '\u{FF18}', '\u{FF19}') + } + + fn is_unicode_connector_punctiation(self) -> bool { + match_char_class!(self, + '\u{005F}', '\u{203F}', '\u{2040}', '\u{2054}', '\u{FE33}', '\u{FE34}', '\u{FE4D}', '\u{FE4E}', '\u{FE4F}', '\u{FF3F}') + } + + fn is_unicode_space_separator(self) -> bool { + match_char_class!(self, + '\u{0020}', '\u{00A0}', '\u{1680}', '\u{2000}', '\u{2001}', '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}', '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}') + } + + fn is_es_identifier_start(self) -> bool { + match self { + '$' | '_' | '\\' => true, + c if c.is_unicode_letter() => true, + _ => false + } + } + + // see section 7.6 + fn is_es_identifier_part(self) -> bool { + match self { + '\u{200C}' | '\u{200D}' => true, + c if c.is_es_identifier_start() => true, + c if c.is_unicode_combining_spacing_mark() => true, + c if c.is_unicode_nonspacing_mark() => true, + c if c.is_unicode_decimal_number() => true, + c if c.is_unicode_connector_punctiation() => true, + _ => false + } + } + + fn is_es_whitespace(self) -> bool { + match self { + '\t' | '\u{000B}' | '\u{000C}' | '\u{0020}' | '\u{00A0}' | '\u{FEFF}' => true, + c => c.is_unicode_space_separator() + } + } + + fn is_es_line_terminator(self) -> bool { + match self { + '\n' | '\r' | '\u{2028}' | '\u{2029}' => true, + _ => false + } + } +} + +fn main() { + +} diff --git a/tests/ui/mir/issue-46845.rs b/tests/ui/mir/issue-46845.rs new file mode 100644 index 000000000..fc85b2551 --- /dev/null +++ b/tests/ui/mir/issue-46845.rs @@ -0,0 +1,32 @@ +// run-pass +// To work around #46855 +// compile-flags: -Z mir-opt-level=0 +// Regression test for the inhabitedness of unions with uninhabited variants, issue #46845 + +use std::mem; + +#[derive(Copy, Clone)] +enum Never { } + +// A single uninhabited variant shouldn't make the whole union uninhabited. +union Foo { + a: u64, + _b: Never +} + +// If all the variants are uninhabited, however, the union should be uninhabited. +// NOTE(#49298) the union being uninhabited shouldn't change its size. +union Bar { + _a: (Never, u64), + _b: (u64, Never) +} + +fn main() { + assert_eq!(mem::size_of::(), 8); + // See the note on `Bar`'s definition for why this isn't `0`. + assert_eq!(mem::size_of::(), 8); + + let f = [Foo { a: 42 }, Foo { a: 10 }]; + println!("{}", unsafe { f[0].a }); + assert_eq!(unsafe { f[1].a }, 10); +} diff --git a/tests/ui/mir/issue-60390.rs b/tests/ui/mir/issue-60390.rs new file mode 100644 index 000000000..fd9d6b46d --- /dev/null +++ b/tests/ui/mir/issue-60390.rs @@ -0,0 +1,8 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for #60390, this ICE requires `--emit=mir` flag. + +fn main() { + enum Inner { Member(u32) }; + Inner::Member(0); +} diff --git a/tests/ui/mir/issue-66851.rs b/tests/ui/mir/issue-66851.rs new file mode 100644 index 000000000..878ad4e47 --- /dev/null +++ b/tests/ui/mir/issue-66851.rs @@ -0,0 +1,20 @@ +// This used to mis-compile because the mir-opt `SimplifyArmIdentity` +// did not check that the types matched up in the `Ok(r)` branch. +// +// run-pass +// compile-flags: -Zmir-opt-level=3 + +#[derive(Debug, PartialEq, Eq)] +enum SpecialsRes { Res(u64) } + +fn e103() -> SpecialsRes { + if let Ok(r) = "1".parse() { + SpecialsRes::Res(r) + } else { + SpecialsRes::Res(42) + } +} + +fn main() { + assert_eq!(e103(), SpecialsRes::Res(1)); +} diff --git a/tests/ui/mir/issue-66930.rs b/tests/ui/mir/issue-66930.rs new file mode 100644 index 000000000..5f9eb2bf4 --- /dev/null +++ b/tests/ui/mir/issue-66930.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for #66930, this ICE requires `--emit=mir` flag. + +static UTF8_CHAR_WIDTH: [u8; 0] = []; + +pub fn utf8_char_width(b: u8) -> usize { + UTF8_CHAR_WIDTH[b as usize] as usize +} + +fn main() {} diff --git a/tests/ui/mir/issue-67639-normalization-ice.rs b/tests/ui/mir/issue-67639-normalization-ice.rs new file mode 100644 index 000000000..71150a80b --- /dev/null +++ b/tests/ui/mir/issue-67639-normalization-ice.rs @@ -0,0 +1,34 @@ +// compile-flags: -Z mir-opt-level=4 +// build-pass + +// This used to ICE in const-prop due +// to an empty ParamEnv being used during normalization +// of a generic type + + +fn main() { + join_all::(); +} + +trait Foo { + type Item; +} + +impl Foo for u32 { + type Item = u8; +} + +trait Bar { + type Item2; +} + +impl Bar for u8 { + type Item2 = u64; +} + +fn join_all() +where I: Foo, + I::Item: Bar +{ + Vec::<::Item2>::new(); // ICE occurs processing this line +} diff --git a/tests/ui/mir/issue-67710-inline-projection.rs b/tests/ui/mir/issue-67710-inline-projection.rs new file mode 100644 index 000000000..1ff6b4d62 --- /dev/null +++ b/tests/ui/mir/issue-67710-inline-projection.rs @@ -0,0 +1,17 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass + +// This used to ICE due to the inling pass not examining projections +// for references to locals + +pub fn parse(version: ()) { + p(&b'.', b"0"); +} +#[inline(always)] +fn p(byte: &u8, s: &[u8]) { + !(s[0] == *byte); +} + +fn main() { + parse(()); +} diff --git a/tests/ui/mir/issue-67947.rs b/tests/ui/mir/issue-67947.rs new file mode 100644 index 000000000..f73d38f80 --- /dev/null +++ b/tests/ui/mir/issue-67947.rs @@ -0,0 +1,7 @@ +struct Bug { + A: [(); { *"" }.len()], + //~^ ERROR: cannot move a value of type `str` + //~| ERROR: cannot move out of a shared reference +} + +fn main() {} diff --git a/tests/ui/mir/issue-67947.stderr b/tests/ui/mir/issue-67947.stderr new file mode 100644 index 000000000..7697a411e --- /dev/null +++ b/tests/ui/mir/issue-67947.stderr @@ -0,0 +1,16 @@ +error[E0161]: cannot move a value of type `str` + --> $DIR/issue-67947.rs:2:13 + | +LL | A: [(); { *"" }.len()], + | ^^^^^^^ the size of `str` cannot be statically determined + +error[E0507]: cannot move out of a shared reference + --> $DIR/issue-67947.rs:2:15 + | +LL | A: [(); { *"" }.len()], + | ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0161, E0507. +For more information about an error, try `rustc --explain E0161`. diff --git a/tests/ui/mir/issue-68841.rs b/tests/ui/mir/issue-68841.rs new file mode 100644 index 000000000..550bd452a --- /dev/null +++ b/tests/ui/mir/issue-68841.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z mir-opt-level=3 +// edition:2018 +// build-pass + +#![feature(async_closure)] + +use std::future::Future; + +fn async_closure() -> impl Future { + (async move || -> u8 { 42 })() +} + +fn main() { + let _fut = async_closure(); +} diff --git a/tests/ui/mir/issue-71793-inline-args-storage.rs b/tests/ui/mir/issue-71793-inline-args-storage.rs new file mode 100644 index 000000000..18f2e38d1 --- /dev/null +++ b/tests/ui/mir/issue-71793-inline-args-storage.rs @@ -0,0 +1,16 @@ +// Verifies that inliner emits StorageLive & StorageDead when introducing +// temporaries for arguments, so that they don't become part of the generator. +// Regression test for #71793. +// +// check-pass +// edition:2018 +// compile-args: -Zmir-opt-level=3 + +#![crate_type = "lib"] + +pub async fn connect() {} + +pub async fn connect_many() { + Vec::::new().first().ok_or("").unwrap(); + connect().await; +} diff --git a/tests/ui/mir/issue-73914.rs b/tests/ui/mir/issue-73914.rs new file mode 100644 index 000000000..1e99faade --- /dev/null +++ b/tests/ui/mir/issue-73914.rs @@ -0,0 +1,30 @@ +// build-pass +// compile-flags:-Copt-level=0 +// edition:2018 + +struct S(std::marker::PhantomData); + +impl std::ops::Deref for S { + type Target = T; + + fn deref(&self) -> &Self::Target { + todo!() + } +} +impl std::ops::DerefMut for S { + fn deref_mut(&mut self) -> &mut Self::Target { + todo!() + } +} + +async fn new() -> S { + todo!() +} + +async fn crash() { + *new().await = 1 + 1; +} + +fn main() { + let _ = crash(); +} diff --git a/tests/ui/mir/issue-74739.rs b/tests/ui/mir/issue-74739.rs new file mode 100644 index 000000000..03622358a --- /dev/null +++ b/tests/ui/mir/issue-74739.rs @@ -0,0 +1,14 @@ +// compile-flags: -O +// run-pass + +struct Foo { + x: i32, +} + +pub fn main() { + let mut foo = Foo { x: 42 }; + let x = &mut foo.x; + *x = 13; + let y = foo; + assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug +} diff --git a/tests/ui/mir/issue-75053.rs b/tests/ui/mir/issue-75053.rs new file mode 100644 index 000000000..cb56eaa0b --- /dev/null +++ b/tests/ui/mir/issue-75053.rs @@ -0,0 +1,49 @@ +// compile-flags: -Z mir-opt-level=3 + +#![feature(type_alias_impl_trait, rustc_attrs)] + +use std::marker::PhantomData; + +trait MyIndex { + type O; + fn my_index(self) -> Self::O; +} +trait MyFrom: Sized { + type Error; + fn my_from(value: T) -> Result; +} + +trait F {} +impl F for () {} +type DummyT = impl F; +fn _dummy_t() -> DummyT {} + +struct Phantom1(PhantomData); +struct Phantom2(PhantomData); +struct Scope(Phantom2>); + +impl Scope { + fn new() -> Self { + unimplemented!() + } +} + +impl MyFrom> for Phantom1 { + type Error = (); + fn my_from(_: Phantom2) -> Result { + unimplemented!() + } +} + +impl>>, U> MyIndex> for Scope { + type O = T; + fn my_index(self) -> Self::O { + MyFrom::my_from(self.0).ok().unwrap() + } +} + +#[rustc_error] +fn main() { + //~^ ERROR + let _pos: Phantom1> = Scope::new().my_index(); +} diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr new file mode 100644 index 000000000..64e59e6c4 --- /dev/null +++ b/tests/ui/mir/issue-75053.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-75053.rs:46:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/mir/issue-75419-validation-impl-trait.rs b/tests/ui/mir/issue-75419-validation-impl-trait.rs new file mode 100644 index 000000000..a8741befb --- /dev/null +++ b/tests/ui/mir/issue-75419-validation-impl-trait.rs @@ -0,0 +1,13 @@ +// build-pass + +// This used to fail MIR validation due to the types on both sides of +// an assignment not being equal. +// The failure doesn't occur with a check-only build. + +fn iter_slice<'a, T>(xs: &'a [T]) -> impl Iterator { + xs.iter() +} + +fn main() { + iter_slice::<()> as fn(_) -> _; +} diff --git a/tests/ui/mir/issue-76248.rs b/tests/ui/mir/issue-76248.rs new file mode 100644 index 000000000..18473e79e --- /dev/null +++ b/tests/ui/mir/issue-76248.rs @@ -0,0 +1,29 @@ +// This used to ICE during codegen after MIR inlining of g into f. +// The root cause was a missing fold of length constant in Rvalue::Repeat. +// Regression test for #76248. +// +// build-pass +// compile-flags: -Zmir-opt-level=3 + +const N: usize = 1; + +pub struct Elem { + pub x: [usize; N], + pub m: M, +} + +pub fn f() -> Elem<()> { + g(()) +} + +#[inline] +pub fn g(m: M) -> Elem { + Elem { + x: [0; N], + m, + } +} + +pub fn main() { + f(); +} diff --git a/tests/ui/mir/issue-76375.rs b/tests/ui/mir/issue-76375.rs new file mode 100644 index 000000000..e635caca9 --- /dev/null +++ b/tests/ui/mir/issue-76375.rs @@ -0,0 +1,27 @@ +// Regression test for issue #76375. +// +// edition:2018 +// build-pass +// compile-flags: -Z mir-opt-level=3 +// aux-build:issue_76375_aux.rs + +#![crate_type = "lib"] + +extern crate issue_76375_aux; + +pub async fn g() { + issue_76375_aux::copy_prop(true); + h().await; +} + +pub async fn u() { + let b = [0u8; 32]; + let mut i = 0; + while i != 10 { + issue_76375_aux::dest_prop(&b); + h().await; + i += 1; + } +} + +pub async fn h() {} diff --git a/tests/ui/mir/issue-76740-copy-propagation.rs b/tests/ui/mir/issue-76740-copy-propagation.rs new file mode 100644 index 000000000..1d4ec1176 --- /dev/null +++ b/tests/ui/mir/issue-76740-copy-propagation.rs @@ -0,0 +1,30 @@ +// Regression test for issue #76740. +// run-pass +// compile-flags: -Zmir-opt-level=4 + +#[derive(Copy, Clone)] +pub struct V([usize; 4]); + +impl V { + fn new() -> Self { + V([0; 4]) + } + + #[inline(never)] + fn check(mut self) { + assert_eq!(self.0[0], 0); + self.0[0] = 1; + } +} + +fn main() { + let v = V::new(); + let mut i = 0; + while i != 10 { + // Copy propagation incorrectly assumed that Operand::Move does not + // mutate the local, and used the same v for each V::check call, + // rather than a copy. + v.check(); + i += 1; + } +} diff --git a/tests/ui/mir/issue-76803-branches-not-same.rs b/tests/ui/mir/issue-76803-branches-not-same.rs new file mode 100644 index 000000000..a6a576220 --- /dev/null +++ b/tests/ui/mir/issue-76803-branches-not-same.rs @@ -0,0 +1,19 @@ +// run-pass + +#[derive(Debug, Eq, PartialEq)] +pub enum Type { + A, + B, +} + + +pub fn encode(v: Type) -> Type { + match v { + Type::A => Type::B, + _ => v, + } +} + +fn main() { + assert_eq!(Type::B, encode(Type::A)); +} diff --git a/tests/ui/mir/issue-77002.rs b/tests/ui/mir/issue-77002.rs new file mode 100644 index 000000000..0c37346ea --- /dev/null +++ b/tests/ui/mir/issue-77002.rs @@ -0,0 +1,16 @@ +// compile-flags: -Zmir-opt-level=3 -Copt-level=0 +// run-pass + +type M = [i64; 2]; + +fn f(a: &M) -> M { + let mut b: M = M::default(); + b[0] = a[0] * a[0]; + b +} + +fn main() { + let mut a: M = [1, 1]; + a = f(&a); + assert_eq!(a[0], 1); +} diff --git a/tests/ui/mir/issue-77359-simplify-arm-identity.rs b/tests/ui/mir/issue-77359-simplify-arm-identity.rs new file mode 100644 index 000000000..e58ba50a9 --- /dev/null +++ b/tests/ui/mir/issue-77359-simplify-arm-identity.rs @@ -0,0 +1,35 @@ +// run-pass + +#![allow(dead_code)] + +#[derive(Debug)] +enum MyEnum { + Variant1(Vec), + Variant2, + Variant3, + Variant4, +} + +fn f(arg1: &bool, arg2: &bool, arg3: bool) -> MyStruct { + if *arg1 { + println!("{:?}", f(&arg2, arg2, arg3)); + MyStruct(None) + } else { + match if arg3 { Some(MyEnum::Variant3) } else { None } { + Some(t) => { + let ah = t; + return MyStruct(Some(ah)); + } + _ => MyStruct(None) + } + } +} + +#[derive(Debug)] +struct MyStruct(Option); + +fn main() { + let arg1 = true; + let arg2 = false; + f(&arg1, &arg2, true); +} diff --git a/tests/ui/mir/issue-77911.rs b/tests/ui/mir/issue-77911.rs new file mode 100644 index 000000000..acf4c2054 --- /dev/null +++ b/tests/ui/mir/issue-77911.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass + +use std::fs::File; +use std::io::{BufRead, BufReader}; + +fn file_lines() -> impl Iterator { + BufReader::new(File::open("").unwrap()) + .lines() + .map(Result::unwrap) +} + +fn main() { + for _ in file_lines() {} +} diff --git a/tests/ui/mir/issue-78496.rs b/tests/ui/mir/issue-78496.rs new file mode 100644 index 000000000..a0d1f5a78 --- /dev/null +++ b/tests/ui/mir/issue-78496.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -Z mir-opt-level=3 -C opt-level=0 + +// example from #78496 +pub enum E<'a> { + Empty, + Some(&'a E<'a>), +} + +fn f(e: &E) -> u32 { + if let E::Some(E::Some(_)) = e { 1 } else { 2 } +} + +fn main() { + assert_eq!(f(&E::Empty), 2); +} diff --git a/tests/ui/mir/issue-80949.rs b/tests/ui/mir/issue-80949.rs new file mode 100644 index 000000000..7e34a4f5c --- /dev/null +++ b/tests/ui/mir/issue-80949.rs @@ -0,0 +1,34 @@ +// build-pass + +trait Trait { type Item; } + +impl<'a, X> Trait for &'a Vec { + type Item = &'a X; +} + +impl Trait for Box> { + type Item = X; +} + +fn make_dyn_trait(_: &()) -> Box> { + todo!() +} + +fn diff<'a, M, N, S>(_: N, _: S) +where + M: 'a, + N: Trait, + S: Trait, +{ + todo!() +} + +fn may_panic(_: X) { } + +fn main() { + let dyn_trait = make_dyn_trait(&()); + let storage = vec![()]; + let _x = may_panic(()); + let storage_ref = &storage; + diff(dyn_trait, storage_ref); +} diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs new file mode 100644 index 000000000..0086d2ec1 --- /dev/null +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -0,0 +1,10 @@ +// Test that when in MIR the amount of local_decls and amount of normalized_input_tys don't match +// that an out-of-bounds access does not occur. +#![feature(c_variadic)] + +fn main() {} + +fn foo(_: Bar, ...) -> impl {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR cannot find type `Bar` in this scope +//~| ERROR at least one trait must be specified diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr new file mode 100644 index 000000000..4eb3adc8b --- /dev/null +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -0,0 +1,21 @@ +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^ + +error: at least one trait must be specified + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:24 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^^ + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/issue-83499-input-output-iteration-ice.rs:7:11 + | +LL | fn foo(_: Bar, ...) -> impl {} + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/mir/issue-89485.rs b/tests/ui/mir/issue-89485.rs new file mode 100644 index 000000000..cb507eefe --- /dev/null +++ b/tests/ui/mir/issue-89485.rs @@ -0,0 +1,18 @@ +// Regression test for issue #89485. + +// run-pass + +#[derive(Debug, Eq, PartialEq)] +pub enum Type { + A = 1, + B = 2, +} +pub fn encode(v: Type) -> Type { + match v { + Type::A => Type::B, + _ => v, + } +} +fn main() { + assert_eq!(Type::B, encode(Type::A)); +} diff --git a/tests/ui/mir/issue-91745.rs b/tests/ui/mir/issue-91745.rs new file mode 100644 index 000000000..ca3d66b1c --- /dev/null +++ b/tests/ui/mir/issue-91745.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Foo { + type Bar; +} + +pub trait Broken { + type Assoc; + fn broken(&self) where Self::Assoc: Foo; +} + +impl Broken for T { + type Assoc = (); + fn broken(&self) where Self::Assoc: Foo { + let _x: ::Bar; + } +} + +fn main() { + let _m: &dyn Broken = &(); +} diff --git a/tests/ui/mir/issue-92893.rs b/tests/ui/mir/issue-92893.rs new file mode 100644 index 000000000..635050f37 --- /dev/null +++ b/tests/ui/mir/issue-92893.rs @@ -0,0 +1,8 @@ +struct Bug { + //~^ `let` expressions are not supported here + //~| `let` expressions in this position are unstable [E0658] + //~| expected expression, found `let` statement + a: A +} + +fn main() {} diff --git a/tests/ui/mir/issue-92893.stderr b/tests/ui/mir/issue-92893.stderr new file mode 100644 index 000000000..4a0fcce31 --- /dev/null +++ b/tests/ui/mir/issue-92893.stderr @@ -0,0 +1,26 @@ +error: expected expression, found `let` statement + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^ + +error: `let` expressions are not supported here + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/mir/issue-99852.rs b/tests/ui/mir/issue-99852.rs new file mode 100644 index 000000000..1c675788e --- /dev/null +++ b/tests/ui/mir/issue-99852.rs @@ -0,0 +1,24 @@ +// check-pass +// compile-flags: -Z validate-mir +#![feature(let_chains)] + +fn lambda() -> U +where + T: Default, + U: Default, +{ + let foo: Result = Ok(T::default()); + let baz: U = U::default(); + + if let Ok(foo) = foo && let Ok(bar) = transform(foo) { + bar + } else { + baz + } +} + +fn transform(input: T) -> Result { + todo!() +} + +fn main() {} diff --git a/tests/ui/mir/issue-99866.rs b/tests/ui/mir/issue-99866.rs new file mode 100644 index 000000000..d39ae6ebf --- /dev/null +++ b/tests/ui/mir/issue-99866.rs @@ -0,0 +1,25 @@ +// check-pass +pub trait Backend { + type DescriptorSetLayout; +} + +pub struct Back; + +impl Backend for Back { + type DescriptorSetLayout = u32; +} + +pub struct HalSetLayouts { + vertex_layout: ::DescriptorSetLayout, +} + +impl HalSetLayouts { + pub fn iter(self) -> DSL + where + Back: Backend, + { + self.vertex_layout + } +} + +fn main() {} diff --git a/tests/ui/mir/issue66339.rs b/tests/ui/mir/issue66339.rs new file mode 100644 index 000000000..2507af38c --- /dev/null +++ b/tests/ui/mir/issue66339.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass + +// This used to ICE in const-prop + +fn foo() { + let bar = |_| { }; + let _ = bar("a"); +} + +fn main() { + foo(); +} diff --git a/tests/ui/mir/mir-inlining/array-clone-with-generic-size.rs b/tests/ui/mir/mir-inlining/array-clone-with-generic-size.rs new file mode 100644 index 000000000..e36e8bd74 --- /dev/null +++ b/tests/ui/mir/mir-inlining/array-clone-with-generic-size.rs @@ -0,0 +1,11 @@ +// Checks that we can build a clone shim for array with generic size. +// Regression test for issue #79269. +// +// build-pass +// compile-flags: -Zmir-opt-level=3 -Zvalidate-mir +#[derive(Clone)] +struct Array([T; N]); + +fn main() { + let _ = Array([0u32, 1u32, 2u32]).clone(); +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-100550-unnormalized-projection.rs b/tests/ui/mir/mir-inlining/ice-issue-100550-unnormalized-projection.rs new file mode 100644 index 000000000..f67b07354 --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-100550-unnormalized-projection.rs @@ -0,0 +1,30 @@ +// This test verifies that we do not ICE due to MIR inlining in case of normalization failure +// in a projection. +// +// compile-flags: --crate-type lib -C opt-level=3 +// build-pass + +pub trait Trait { + type Associated; +} +impl Trait for T { + type Associated = T; +} + +pub struct Struct(::Associated); + +pub fn foo() -> Struct +where + T: Trait, +{ + bar() +} + +#[inline] +fn bar() -> Struct { + Struct(baz()) +} + +fn baz() -> T { + unimplemented!() +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-45493.rs b/tests/ui/mir/mir-inlining/ice-issue-45493.rs new file mode 100644 index 000000000..04a23212e --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-45493.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +trait Array { + type Item; +} + +fn foo() { + let _: *mut A::Item = std::ptr::null_mut(); +} + +struct Foo; +impl Array for Foo { type Item = i32; } + +fn main() { + foo::(); +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-45885.rs b/tests/ui/mir/mir-inlining/ice-issue-45885.rs new file mode 100644 index 000000000..09b1279ef --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-45885.rs @@ -0,0 +1,29 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +pub enum Enum { + A, + B, +} + +trait SliceIndex { + type Output; + fn get(&self) -> &Self::Output; +} + +impl SliceIndex for usize { + type Output = Enum; + #[inline(never)] + fn get(&self) -> &Enum { + &Enum::A + } +} + +#[inline(always)] +fn index(t: &T) -> &T::Output { + t.get() +} + +fn main() { + match *index(&0) { Enum::A => true, _ => false }; +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-68347.rs b/tests/ui/mir/mir-inlining/ice-issue-68347.rs new file mode 100644 index 000000000..7c1352509 --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-68347.rs @@ -0,0 +1,28 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 +pub fn main() { + let _x: fn() = handle_debug_column; +} + +fn handle_debug_column() { + let sampler = sample_columns(); + + let foo = || { + sampler.get(17); + }; + foo(); +} + +fn sample_columns() -> impl Sampler { + ColumnGen {} +} + +struct ColumnGen {} + +trait Sampler { + fn get(&self, index: i32); +} + +impl Sampler for ColumnGen { + fn get(&self, _index: i32) {} +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-77306-1.rs b/tests/ui/mir/mir-inlining/ice-issue-77306-1.rs new file mode 100644 index 000000000..ef05ff9ce --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-77306-1.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +// Previously ICEd because we did not normalize during inlining, +// see https://github.com/rust-lang/rust/pull/77306 for more discussion. + +pub fn write() { + create()() +} + +pub fn create() -> impl FnOnce() { + || () +} + +fn main() { + write(); +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-77306-2.rs b/tests/ui/mir/mir-inlining/ice-issue-77306-2.rs new file mode 100644 index 000000000..cb2084013 --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-77306-2.rs @@ -0,0 +1,32 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +struct Cursor {} +struct TokenTree {} + +impl Iterator for Cursor { + type Item = TokenTree; + + fn next(&mut self) -> Option { + None + } +} + +fn tokenstream_probably_equal_for_proc_macro() { + fn break_tokens(_tree: TokenTree) -> impl Iterator { + let token_trees: Vec = vec![]; + token_trees.into_iter() + } + + let c1 = Cursor {}; + let c2 = Cursor {}; + + let mut t1 = c1.flat_map(break_tokens); + let mut t2 = c2.flat_map(break_tokens); + + for (_t1, _t2) in t1.by_ref().zip(t2.by_ref()) {} +} + +fn main() { + tokenstream_probably_equal_for_proc_macro(); +} diff --git a/tests/ui/mir/mir-inlining/ice-issue-77564.rs b/tests/ui/mir/mir-inlining/ice-issue-77564.rs new file mode 100644 index 000000000..0d3fbfe5d --- /dev/null +++ b/tests/ui/mir/mir-inlining/ice-issue-77564.rs @@ -0,0 +1,38 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 + +use std::mem::MaybeUninit; +const N: usize = 2; + +trait CollectArray: Iterator { + fn inner_array(&mut self) -> [A; N]; + fn collect_array(&mut self) -> [A; N] { + let result = self.inner_array(); + assert!(self.next().is_none()); + result + } +} + +impl CollectArray for I +where + I: Iterator, +{ + fn inner_array(&mut self) -> [A; N] { + let mut result: [MaybeUninit; N] = unsafe { MaybeUninit::uninit().assume_init() }; + for (dest, item) in result.iter_mut().zip(self) { + *dest = MaybeUninit::new(item); + } + let temp_ptr: *const [MaybeUninit; N] = &result; + unsafe { std::ptr::read(temp_ptr as *const [A; N]) } + } +} + +fn main() { + assert_eq!( + [[1, 2], [3, 4]] + .iter() + .map(|row| row.iter().collect_array()) + .collect_array(), + [[&1, &2], [&3, &4]] + ); +} diff --git a/tests/ui/mir/mir-inlining/no-trait-method-issue-40473.rs b/tests/ui/mir/mir-inlining/no-trait-method-issue-40473.rs new file mode 100644 index 000000000..8b3cb703d --- /dev/null +++ b/tests/ui/mir/mir-inlining/no-trait-method-issue-40473.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags:-Zmir-opt-level=3 +pub trait Foo { + fn bar(&self) -> usize { 2 } +} + +impl Foo for () { + fn bar(&self) -> usize { 3 } +} + +// Test a case where MIR would inline the default trait method +// instead of bailing out. Issue #40473. +fn main() { + let result = ().bar(); + assert_eq!(result, 3); +} diff --git a/tests/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs b/tests/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs new file mode 100644 index 000000000..e26206826 --- /dev/null +++ b/tests/ui/mir/mir-inlining/var-debuginfo-issue-67586.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags: -Z mir-opt-level=3 -C opt-level=0 -C debuginfo=2 + +#[inline(never)] +pub fn foo(bar: usize) -> usize { + std::convert::identity(bar) +} + +fn main() { + foo(0); +} diff --git a/tests/ui/mir/mir-typeck-normalize-fn-sig.rs b/tests/ui/mir/mir-typeck-normalize-fn-sig.rs new file mode 100644 index 000000000..bdd9321af --- /dev/null +++ b/tests/ui/mir/mir-typeck-normalize-fn-sig.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_variables)] +// This code was creating an ICE in the MIR type checker. The reason +// is that we are reifying a reference to a function (`foo::<'x>`), +// which involves extracting its signature, but we were not +// normalizing the signature afterwards. As a result, we sometimes got +// errors around the `>::Value`, which can be +// normalized to `f64`. + +#![allow(dead_code)] + +trait Foo<'x> { + type Value; +} + +impl<'x> Foo<'x> for u32 { + type Value = f64; +} + +struct Providers<'x> { + foo: for<'y> fn(x: &'x u32, y: &'y u32) -> >::Value, +} + +fn foo<'y, 'x: 'x>(x: &'x u32, y: &'y u32) -> >::Value { + *x as f64 +} + +fn main() { + Providers { foo }; +} diff --git a/tests/ui/mir/mir_adt_construction.rs b/tests/ui/mir/mir_adt_construction.rs new file mode 100644 index 000000000..9fb5896de --- /dev/null +++ b/tests/ui/mir/mir_adt_construction.rs @@ -0,0 +1,92 @@ +// run-pass +use std::fmt; + +#[repr(C)] +enum CEnum { + Hello = 30, + World = 60 +} + +fn test1(c: CEnum) -> i32 { + let c2 = CEnum::Hello; + match (c, c2) { + (CEnum::Hello, CEnum::Hello) => 42, + (CEnum::World, CEnum::Hello) => 0, + _ => 1 + } +} + +#[repr(packed)] +struct Pakd { + a: u64, + b: u32, + c: u16, + d: u8, + e: () +} + +// It is unsafe to use #[derive(Debug)] on a packed struct because the code generated by the derive +// macro takes references to the fields instead of accessing them directly. +impl fmt::Debug for Pakd { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // It's important that we load the fields into locals by-value here. This will do safe + // unaligned loads into the locals, then pass references to the properly-aligned locals to + // the formatting code. + let Pakd { a, b, c, d, e } = *self; + f.debug_struct("Pakd") + .field("a", &a) + .field("b", &b) + .field("c", &c) + .field("d", &d) + .field("e", &e) + .finish() + } +} + +// It is unsafe to use #[derive(PartialEq)] on a packed struct because the code generated by the +// derive macro takes references to the fields instead of accessing them directly. +impl PartialEq for Pakd { + fn eq(&self, other: &Pakd) -> bool { + self.a == other.a && + self.b == other.b && + self.c == other.c && + self.d == other.d && + self.e == other.e + } +} + +impl Drop for Pakd { + fn drop(&mut self) {} +} + +fn test2() -> Pakd { + Pakd { a: 42, b: 42, c: 42, d: 42, e: () } +} + +#[derive(PartialEq, Debug)] +struct TupleLike(u64, u32); + +fn test3() -> TupleLike { + TupleLike(42, 42) +} + +fn test4(x: fn(u64, u32) -> TupleLike) -> (TupleLike, TupleLike) { + let y = TupleLike; + (x(42, 84), y(42, 84)) +} + +fn test5(x: fn(u32) -> Option) -> (Option, Option) { + let y = Some; + (x(42), y(42)) +} + +fn main() { + assert_eq!(test1(CEnum::Hello), 42); + assert_eq!(test1(CEnum::World), 0); + assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () }); + assert_eq!(test3(), TupleLike(42, 42)); + let t4 = test4(TupleLike); + assert_eq!(t4.0, t4.1); + let t5 = test5(Some); + assert_eq!(t5.0, t5.1); +} diff --git a/tests/ui/mir/mir_ascription_coercion.rs b/tests/ui/mir/mir_ascription_coercion.rs new file mode 100644 index 000000000..9e04d6019 --- /dev/null +++ b/tests/ui/mir/mir_ascription_coercion.rs @@ -0,0 +1,10 @@ +// run-pass +// Tests that the result of type ascription has adjustments applied + +#![feature(type_ascription)] + +fn main() { + let x = [1, 2, 3]; + // The RHS should coerce to &[i32] + let _y : &[i32] = type_ascribe!(&x, &[i32; 3]); +} diff --git a/tests/ui/mir/mir_assign_eval_order.rs b/tests/ui/mir/mir_assign_eval_order.rs new file mode 100644 index 000000000..799bf7f3a --- /dev/null +++ b/tests/ui/mir/mir_assign_eval_order.rs @@ -0,0 +1,67 @@ +// Test evaluation order of assignment expressions is right to left. + +// run-pass + +// We would previously not finish evaluating borrow and FRU expressions before +// starting on the LHS + +struct S(i32); + +fn evaluate_reborrow_before_assign() { + let mut x = &1; + let y = &mut &2; + let z = &3; + // There's an implicit reborrow of `x` on the right-hand side of the + // assignment. Note that writing an explicit reborrow would not show this + // bug, as now there would be two reborrows on the right-hand side and at + // least one of them would happen before the left-hand side is evaluated. + *{ x = z; &mut *y } = x; + assert_eq!(*x, 3); + assert_eq!(**y, 1); // y should be assigned the original value of `x`. +} + +fn evaluate_mut_reborrow_before_assign() { + let mut x = &mut 1; + let y = &mut &mut 2; + let z = &mut 3; + *{ x = z; &mut *y } = x; + assert_eq!(*x, 3); + assert_eq!(**y, 1); // y should be assigned the original value of `x`. +} + +// We should evaluate `x[2]` and borrow the value out *before* evaluating the +// LHS and changing its value. +fn evaluate_ref_to_temp_before_assign_slice() { + let mut x = &[S(0), S(1), S(2)][..]; + let y = &mut &S(7); + *{ x = &[S(3), S(4), S(5)]; &mut *y } = &x[2]; + assert_eq!(2, y.0); + assert_eq!(5, x[2].0); +} + +// We should evaluate `x[2]` and copy the value out *before* evaluating the LHS +// and changing its value. +fn evaluate_fru_to_temp_before_assign_slice() { + let mut x = &[S(0), S(1), S(2)][..]; + let y = &mut S(7); + *{ x = &[S(3), S(4), S(5)]; &mut *y } = S { ..x[2] }; + assert_eq!(2, y.0); + assert_eq!(5, x[2].0); +} + +// We should evaluate `*x` and copy the value out *before* evaluating the LHS +// and dropping `x`. +fn evaluate_fru_to_temp_before_assign_box() { + let x = Box::new(S(0)); + let y = &mut S(1); + *{ drop(x); &mut *y } = S { ..*x }; + assert_eq!(0, y.0); +} + +fn main() { + evaluate_reborrow_before_assign(); + evaluate_mut_reborrow_before_assign(); + evaluate_ref_to_temp_before_assign_slice(); + evaluate_fru_to_temp_before_assign_slice(); + evaluate_fru_to_temp_before_assign_box(); +} diff --git a/tests/ui/mir/mir_augmented_assignments.rs b/tests/ui/mir/mir_augmented_assignments.rs new file mode 100644 index 000000000..44454f8f4 --- /dev/null +++ b/tests/ui/mir/mir_augmented_assignments.rs @@ -0,0 +1,160 @@ +// run-pass +use std::mem; +use std::ops::{ + AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, RemAssign, + ShlAssign, ShrAssign, SubAssign, +}; + +#[derive(Debug, PartialEq)] +struct Int(i32); + +struct Slice([i32]); + +impl Slice { + fn new(slice: &mut [i32]) -> &mut Slice { + unsafe { + mem::transmute(slice) + } + } +} + +fn main() { + main_mir(); +} + +fn main_mir() { + let mut x = Int(1); + + x += Int(2); + assert_eq!(x, Int(0b11)); + + x &= Int(0b01); + assert_eq!(x, Int(0b01)); + + x |= Int(0b10); + assert_eq!(x, Int(0b11)); + + x ^= Int(0b01); + assert_eq!(x, Int(0b10)); + + x /= Int(2); + assert_eq!(x, Int(1)); + + x *= Int(3); + assert_eq!(x, Int(3)); + + x %= Int(2); + assert_eq!(x, Int(1)); + + // overloaded RHS + x <<= 1u8; + assert_eq!(x, Int(2)); + + x <<= 1u16; + assert_eq!(x, Int(4)); + + x >>= 1u8; + assert_eq!(x, Int(2)); + + x >>= 1u16; + assert_eq!(x, Int(1)); + + x -= Int(1); + assert_eq!(x, Int(0)); + + // indexed LHS + // FIXME(mir-drop): use the vec![..] macro + let mut v = Vec::new(); + v.push(Int(1)); + v.push(Int(2)); + v[0] += Int(2); + assert_eq!(v[0], Int(3)); + + // unsized RHS + let mut array = [0, 1, 2]; + *Slice::new(&mut array) += 1; + assert_eq!(array[0], 1); + assert_eq!(array[1], 2); + assert_eq!(array[2], 3); + +} + +impl AddAssign for Int { + fn add_assign(&mut self, rhs: Int) { + self.0 += rhs.0; + } +} + +impl BitAndAssign for Int { + fn bitand_assign(&mut self, rhs: Int) { + self.0 &= rhs.0; + } +} + +impl BitOrAssign for Int { + fn bitor_assign(&mut self, rhs: Int) { + self.0 |= rhs.0; + } +} + +impl BitXorAssign for Int { + fn bitxor_assign(&mut self, rhs: Int) { + self.0 ^= rhs.0; + } +} + +impl DivAssign for Int { + fn div_assign(&mut self, rhs: Int) { + self.0 /= rhs.0; + } +} + +impl MulAssign for Int { + fn mul_assign(&mut self, rhs: Int) { + self.0 *= rhs.0; + } +} + +impl RemAssign for Int { + fn rem_assign(&mut self, rhs: Int) { + self.0 %= rhs.0; + } +} + +impl ShlAssign for Int { + fn shl_assign(&mut self, rhs: u8) { + self.0 <<= rhs; + } +} + +impl ShlAssign for Int { + fn shl_assign(&mut self, rhs: u16) { + self.0 <<= rhs; + } +} + +impl ShrAssign for Int { + fn shr_assign(&mut self, rhs: u8) { + self.0 >>= rhs; + } +} + +impl ShrAssign for Int { + fn shr_assign(&mut self, rhs: u16) { + self.0 >>= rhs; + } +} + +impl SubAssign for Int { + fn sub_assign(&mut self, rhs: Int) { + self.0 -= rhs.0; + } +} + +impl AddAssign for Slice { + fn add_assign(&mut self, rhs: i32) { + for lhs in &mut self.0 { + *lhs += rhs; + } + } +} diff --git a/tests/ui/mir/mir_autoderef.rs b/tests/ui/mir/mir_autoderef.rs new file mode 100644 index 000000000..a0e615a73 --- /dev/null +++ b/tests/ui/mir/mir_autoderef.rs @@ -0,0 +1,28 @@ +// run-pass +use std::ops::{Deref, DerefMut}; + +pub struct MyRef(u32); + +impl Deref for MyRef { + type Target = u32; + fn deref(&self) -> &u32 { &self.0 } +} + +impl DerefMut for MyRef { + fn deref_mut(&mut self) -> &mut u32 { &mut self.0 } +} + + +fn deref(x: &MyRef) -> &u32 { + x +} + +fn deref_mut(x: &mut MyRef) -> &mut u32 { + x +} + +fn main() { + let mut r = MyRef(2); + assert_eq!(deref(&r) as *const _, &r.0 as *const _); + assert_eq!(deref_mut(&mut r) as *mut _, &mut r.0 as *mut _); +} diff --git a/tests/ui/mir/mir_boxing.rs b/tests/ui/mir/mir_boxing.rs new file mode 100644 index 000000000..83e1cfb64 --- /dev/null +++ b/tests/ui/mir/mir_boxing.rs @@ -0,0 +1,10 @@ +// run-pass +#![feature(box_syntax)] + +fn test() -> Box { + box 42 +} + +fn main() { + assert_eq!(*test(), 42); +} diff --git a/tests/ui/mir/mir_build_match_comparisons.rs b/tests/ui/mir/mir_build_match_comparisons.rs new file mode 100644 index 000000000..045700557 --- /dev/null +++ b/tests/ui/mir/mir_build_match_comparisons.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(dead_code)] +fn test1(x: i8) -> i32 { + match x { + 1..=10 => 0, + _ => 1, + } +} + +const U: Option = Some(10); +const S: &'static str = "hello"; + +fn test2(x: i8) -> i32 { + match Some(x) { + U => 0, + _ => 1, + } +} + +fn test3(x: &'static str) -> i32 { + match x { + S => 0, + _ => 1, + } +} + +enum Opt { + Some { v: T }, + None +} + +fn test4(x: u64) -> i32 { + let opt = Opt::Some{ v: x }; + match opt { + Opt::Some { v: 10 } => 0, + _ => 1, + } +} + + +fn main() { + assert_eq!(test1(0), 1); + assert_eq!(test1(1), 0); + assert_eq!(test1(2), 0); + assert_eq!(test1(5), 0); + assert_eq!(test1(9), 0); + assert_eq!(test1(10), 0); + assert_eq!(test1(11), 1); + assert_eq!(test1(20), 1); + assert_eq!(test2(10), 0); + assert_eq!(test2(0), 1); + assert_eq!(test2(20), 1); + assert_eq!(test3("hello"), 0); + assert_eq!(test3(""), 1); + assert_eq!(test3("world"), 1); + assert_eq!(test4(10), 0); + assert_eq!(test4(0), 1); + assert_eq!(test4(20), 1); +} diff --git a/tests/ui/mir/mir_call_with_associated_type.rs b/tests/ui/mir/mir_call_with_associated_type.rs new file mode 100644 index 000000000..7103533e1 --- /dev/null +++ b/tests/ui/mir/mir_call_with_associated_type.rs @@ -0,0 +1,16 @@ +// run-pass +trait Trait { + type Type; +} + +impl<'a> Trait for &'a () { + type Type = u32; +} + +fn foo<'a>(t: <&'a () as Trait>::Type) -> <&'a () as Trait>::Type { + t +} + +fn main() { + assert_eq!(foo(4), 4); +} diff --git a/tests/ui/mir/mir_calls_to_shims.rs b/tests/ui/mir/mir_calls_to_shims.rs new file mode 100644 index 000000000..9dc0acfbf --- /dev/null +++ b/tests/ui/mir/mir_calls_to_shims.rs @@ -0,0 +1,49 @@ +// run-pass +// needs-unwind + +#![feature(fn_traits)] +#![feature(never_type)] + +use std::panic; + +fn foo(x: u32, y: u32) -> u32 { x/y } +fn foo_diverges() -> ! { panic!() } + +fn test_fn_ptr(mut t: T) + where T: Fn(u32, u32) -> u32, +{ + let as_fn = >::call; + assert_eq!(as_fn(&t, (9, 3)), 3); + let as_fn_mut = >::call_mut; + assert_eq!(as_fn_mut(&mut t, (18, 3)), 6); + let as_fn_once = >::call_once; + assert_eq!(as_fn_once(t, (24, 3)), 8); +} + +fn assert_panics(f: F) where F: FnOnce() { + let f = panic::AssertUnwindSafe(f); + let result = panic::catch_unwind(move || { + f.0() + }); + if let Ok(..) = result { + panic!("diverging function returned"); + } +} + +fn test_fn_ptr_panic(mut t: T) + where T: Fn() -> ! +{ + let as_fn = >::call; + assert_panics(|| as_fn(&t, ())); + let as_fn_mut = >::call_mut; + assert_panics(|| as_fn_mut(&mut t, ())); + let as_fn_once = >::call_once; + assert_panics(|| as_fn_once(t, ())); +} + +fn main() { + test_fn_ptr(foo); + test_fn_ptr(foo as fn(u32, u32) -> u32); + test_fn_ptr_panic(foo_diverges); + test_fn_ptr_panic(foo_diverges as fn() -> !); +} diff --git a/tests/ui/mir/mir_cast_fn_ret.rs b/tests/ui/mir/mir_cast_fn_ret.rs new file mode 100644 index 000000000..4574dbd85 --- /dev/null +++ b/tests/ui/mir/mir_cast_fn_ret.rs @@ -0,0 +1,23 @@ +// run-pass +#[allow(improper_ctypes_definitions)] +pub extern "C" fn tuple2() -> (u16, u8) { + (1, 2) +} + +#[allow(improper_ctypes_definitions)] +pub extern "C" fn tuple3() -> (u8, u8, u8) { + (1, 2, 3) +} + +pub fn test2() -> u8 { + tuple2().1 +} + +pub fn test3() -> u8 { + tuple3().2 +} + +fn main() { + assert_eq!(test2(), 2); + assert_eq!(test3(), 3); +} diff --git a/tests/ui/mir/mir_codegen_array.rs b/tests/ui/mir/mir_codegen_array.rs new file mode 100644 index 000000000..38e443d8e --- /dev/null +++ b/tests/ui/mir/mir_codegen_array.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_mut)] +fn into_inner() -> [u64; 1024] { + let mut x = 10 + 20; + [x; 1024] +} + +fn main(){ + let x: &[u64] = &[30; 1024]; + assert_eq!(&into_inner()[..], x); +} diff --git a/tests/ui/mir/mir_codegen_array_2.rs b/tests/ui/mir/mir_codegen_array_2.rs new file mode 100644 index 000000000..03d3aa5ad --- /dev/null +++ b/tests/ui/mir/mir_codegen_array_2.rs @@ -0,0 +1,9 @@ +// run-pass +fn into_inner(x: u64) -> [u64; 1024] { + [x; 2*4*8*16] +} + +fn main(){ + let x: &[u64] = &[42; 1024]; + assert_eq!(&into_inner(42)[..], x); +} diff --git a/tests/ui/mir/mir_codegen_call_converging.rs b/tests/ui/mir/mir_codegen_call_converging.rs new file mode 100644 index 000000000..9c340e4e0 --- /dev/null +++ b/tests/ui/mir/mir_codegen_call_converging.rs @@ -0,0 +1,17 @@ +// run-pass +fn converging_fn() -> u64 { + 43 +} + +fn mir() -> u64 { + let x; + loop { + x = converging_fn(); + break; + } + x +} + +fn main() { + assert_eq!(mir(), 43); +} diff --git a/tests/ui/mir/mir_codegen_calls.rs b/tests/ui/mir/mir_codegen_calls.rs new file mode 100644 index 000000000..6a5a4dace --- /dev/null +++ b/tests/ui/mir/mir_codegen_calls.rs @@ -0,0 +1,192 @@ +// run-pass +#![feature(fn_traits, test)] + +extern crate test; + +fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) { + // Test passing a number of arguments including a fat pointer. + // Also returning via an out pointer + fn callee(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) { + (a, b, c) + } + callee(a, b, c) +} + +fn test2(a: isize) -> isize { + // Test passing a single argument. + // Not using out pointer. + fn callee(a: isize) -> isize { + a + } + callee(a) +} + +#[derive(PartialEq, Eq, Debug)] +struct Foo; +impl Foo { + fn inherent_method(&self, a: isize) -> isize { a } +} + +fn test3(x: &Foo, a: isize) -> isize { + // Test calling inherent method + x.inherent_method(a) +} + +trait Bar { + fn extension_method(&self, a: isize) -> isize { a } +} +impl Bar for Foo {} + +fn test4(x: &Foo, a: isize) -> isize { + // Test calling extension method + x.extension_method(a) +} + +fn test5(x: &dyn Bar, a: isize) -> isize { + // Test calling method on trait object + x.extension_method(a) +} + +fn test6(x: &T, a: isize) -> isize { + // Test calling extension method on generic callee + x.extension_method(a) +} + +trait One { + fn one() -> T; +} +impl One for isize { + fn one() -> isize { 1 } +} + +fn test7() -> isize { + // Test calling trait static method + ::one() +} + +struct Two; +impl Two { + fn two() -> isize { 2 } +} + +fn test8() -> isize { + // Test calling impl static method + Two::two() +} + +#[allow(improper_ctypes_definitions)] +extern "C" fn simple_extern(x: u32, y: (u32, u32)) -> u32 { + x + y.0 * y.1 +} + +fn test9() -> u32 { + simple_extern(41, (42, 43)) +} + +fn test_closure(f: &F, x: i32, y: i32) -> i32 + where F: Fn(i32, i32) -> i32 +{ + f(x, y) +} + +fn test_fn_object(f: &dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 { + f(x, y) +} + +fn test_fn_impl(f: &&dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 { + // This call goes through the Fn implementation for &Fn provided in + // core::ops::impls. It expands to a static Fn::call() that calls the + // Fn::call() implementation of the object shim underneath. + f(x, y) +} + +fn test_fn_direct_call(f: &F, x: i32, y: i32) -> i32 + where F: Fn(i32, i32) -> i32 +{ + f.call((x, y)) +} + +fn test_fn_const_call(f: &F) -> i32 + where F: Fn(i32, i32) -> i32 +{ + f.call((100, -1)) +} + +fn test_fn_nil_call(f: &F) -> i32 + where F: Fn() -> i32 +{ + f() +} + +fn test_fn_transmute_zst(x: ()) -> [(); 1] { + fn id(x: T) -> T {x} + + id(unsafe { + std::mem::transmute(x) + }) +} + +fn test_fn_ignored_pair() -> ((), ()) { + ((), ()) +} + +fn test_fn_ignored_pair_0() { + test_fn_ignored_pair().0 +} + +fn id(x: T) -> T { x } + +fn ignored_pair_named() -> (Foo, Foo) { + (Foo, Foo) +} + +fn test_fn_ignored_pair_named() -> (Foo, Foo) { + id(ignored_pair_named()) +} + +fn test_fn_nested_pair(x: &((f32, f32), u32)) -> (f32, f32) { + let y = *x; + let z = y.0; + (z.0, z.1) +} + +fn test_fn_const_arg_by_ref(mut a: [u64; 4]) -> u64 { + // Mutate the by-reference argument, which won't work with + // a non-immediate constant unless it's copied to the stack. + let a = test::black_box(&mut a); + a[0] += a[1]; + a[0] += a[2]; + a[0] += a[3]; + a[0] +} + +fn main() { + assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..])); + assert_eq!(test2(98), 98); + assert_eq!(test3(&Foo, 42), 42); + assert_eq!(test4(&Foo, 970), 970); + assert_eq!(test5(&Foo, 8576), 8576); + assert_eq!(test6(&Foo, 12367), 12367); + assert_eq!(test7(), 1); + assert_eq!(test8(), 2); + assert_eq!(test9(), 41 + 42 * 43); + + let r = 3; + let closure = |x: i32, y: i32| { r*(x + (y*2)) }; + assert_eq!(test_fn_const_call(&closure), 294); + assert_eq!(test_closure(&closure, 100, 1), 306); + let function_object = &closure as &dyn Fn(i32, i32) -> i32; + assert_eq!(test_fn_object(function_object, 100, 2), 312); + assert_eq!(test_fn_impl(&function_object, 100, 3), 318); + assert_eq!(test_fn_direct_call(&closure, 100, 4), 324); + + assert_eq!(test_fn_nil_call(&(|| 42)), 42); + assert_eq!(test_fn_transmute_zst(()), [()]); + + assert_eq!(test_fn_ignored_pair_0(), ()); + assert_eq!(test_fn_ignored_pair_named(), (Foo, Foo)); + assert_eq!(test_fn_nested_pair(&((1.0, 2.0), 0)), (1.0, 2.0)); + + const ARRAY: [u64; 4] = [1, 2, 3, 4]; + assert_eq!(test_fn_const_arg_by_ref(ARRAY), 1 + 2 + 3 + 4); +} diff --git a/tests/ui/mir/mir_codegen_calls_converging_drops.rs b/tests/ui/mir/mir_codegen_calls_converging_drops.rs new file mode 100644 index 000000000..b562f9308 --- /dev/null +++ b/tests/ui/mir/mir_codegen_calls_converging_drops.rs @@ -0,0 +1,26 @@ +// run-fail +// error-pattern:converging_fn called +// error-pattern:0 dropped +// error-pattern:exit +// ignore-emscripten no processes + +struct Droppable(u8); +impl Drop for Droppable { + fn drop(&mut self) { + eprintln!("{} dropped", self.0); + } +} + +fn converging_fn() { + eprintln!("converging_fn called"); +} + +fn mir(d: Droppable) { + converging_fn(); +} + +fn main() { + let d = Droppable(0); + mir(d); + panic!("exit"); +} diff --git a/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs b/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs new file mode 100644 index 000000000..e9446da9e --- /dev/null +++ b/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs @@ -0,0 +1,30 @@ +// run-fail +// error-pattern:complex called +// error-pattern:dropped +// error-pattern:exit +// ignore-emscripten no processes + +struct Droppable; +impl Drop for Droppable { + fn drop(&mut self) { + eprintln!("dropped"); + } +} + +// return value of this function is copied into the return slot +fn complex() -> u64 { + eprintln!("complex called"); + 42 +} + + +fn mir() -> u64 { + let x = Droppable; + return complex(); + drop(x); +} + +pub fn main() { + assert_eq!(mir(), 42); + panic!("exit"); +} diff --git a/tests/ui/mir/mir_codegen_calls_diverging.rs b/tests/ui/mir/mir_codegen_calls_diverging.rs new file mode 100644 index 000000000..736d580e2 --- /dev/null +++ b/tests/ui/mir/mir_codegen_calls_diverging.rs @@ -0,0 +1,15 @@ +// run-fail +// error-pattern:diverging_fn called +// ignore-emscripten no processes + +fn diverging_fn() -> ! { + panic!("diverging_fn called") +} + +fn mir() { + diverging_fn(); +} + +fn main() { + mir(); +} diff --git a/tests/ui/mir/mir_codegen_calls_diverging_drops.rs b/tests/ui/mir/mir_codegen_calls_diverging_drops.rs new file mode 100644 index 000000000..19dba4970 --- /dev/null +++ b/tests/ui/mir/mir_codegen_calls_diverging_drops.rs @@ -0,0 +1,24 @@ +// run-fail +// error-pattern:diverging_fn called +// error-pattern:0 dropped +// needs-unwind this test checks that a destructor is called after panicking + +struct Droppable(u8); +impl Drop for Droppable { + fn drop(&mut self) { + eprintln!("{} dropped", self.0); + } +} + +fn diverging_fn() -> ! { + panic!("diverging_fn called") +} + +fn mir(d: Droppable) { + diverging_fn(); +} + +fn main() { + let d = Droppable(0); + mir(d); +} diff --git a/tests/ui/mir/mir_codegen_critical_edge.rs b/tests/ui/mir/mir_codegen_critical_edge.rs new file mode 100644 index 000000000..5c1f1c3b7 --- /dev/null +++ b/tests/ui/mir/mir_codegen_critical_edge.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code)] +// This code produces a CFG with critical edges that, if we don't +// handle properly, will cause invalid codegen. + +#![feature(rustc_attrs)] + +enum State { + Both, + Front, + Back +} + +pub struct Foo { + state: State, + a: A, + b: B +} + +impl Foo +where A: Iterator, B: Iterator +{ + // This is the function we care about + fn next(&mut self) -> Option { + match self.state { + State::Both => match self.a.next() { + elt @ Some(..) => elt, + None => { + self.state = State::Back; + self.b.next() + } + }, + State::Front => self.a.next(), + State::Back => self.b.next(), + } + } +} + +// Make sure we actually codegen a version of the function +pub fn do_stuff(mut f: Foo>, Box>>) { + let _x = f.next(); +} + +fn main() {} diff --git a/tests/ui/mir/mir_codegen_spike1.rs b/tests/ui/mir/mir_codegen_spike1.rs new file mode 100644 index 000000000..90bdd6b4b --- /dev/null +++ b/tests/ui/mir/mir_codegen_spike1.rs @@ -0,0 +1,12 @@ +// run-pass +// A simple spike test for MIR version of codegen. + +fn sum(x: i32, y: i32) -> i32 { + x + y +} + +fn main() { + let x = sum(22, 44); + assert_eq!(x, 66); + println!("sum()={:?}", x); +} diff --git a/tests/ui/mir/mir_codegen_switch.rs b/tests/ui/mir/mir_codegen_switch.rs new file mode 100644 index 000000000..9c93499d9 --- /dev/null +++ b/tests/ui/mir/mir_codegen_switch.rs @@ -0,0 +1,35 @@ +// run-pass +enum Abc { + A(#[allow(unused_tuple_struct_fields)] u8), + B(#[allow(unused_tuple_struct_fields)] i8), + C, + D, +} + +fn foo(x: Abc) -> i32 { + match x { + Abc::C => 3, + Abc::D => 4, + Abc::B(_) => 2, + Abc::A(_) => 1, + } +} + +fn foo2(x: Abc) -> bool { + match x { + Abc::D => true, + _ => false + } +} + +fn main() { + assert_eq!(1, foo(Abc::A(42))); + assert_eq!(2, foo(Abc::B(-100))); + assert_eq!(3, foo(Abc::C)); + assert_eq!(4, foo(Abc::D)); + + assert_eq!(false, foo2(Abc::A(1))); + assert_eq!(false, foo2(Abc::B(2))); + assert_eq!(false, foo2(Abc::C)); + assert_eq!(true, foo2(Abc::D)); +} diff --git a/tests/ui/mir/mir_codegen_switchint.rs b/tests/ui/mir/mir_codegen_switchint.rs new file mode 100644 index 000000000..c092a6c31 --- /dev/null +++ b/tests/ui/mir/mir_codegen_switchint.rs @@ -0,0 +1,12 @@ +// run-pass +pub fn foo(x: i8) -> i32 { + match x { + 1 => 0, + _ => 1, + } +} + +fn main() { + assert_eq!(foo(0), 1); + assert_eq!(foo(1), 0); +} diff --git a/tests/ui/mir/mir_coercion_casts.rs b/tests/ui/mir/mir_coercion_casts.rs new file mode 100644 index 000000000..7d761181d --- /dev/null +++ b/tests/ui/mir/mir_coercion_casts.rs @@ -0,0 +1,10 @@ +// run-pass +// Tests the coercion casts are handled properly + +fn main() { + // This should produce only a reification of f, + // not a fn -> fn cast as well + let _ = f as fn(&()); +} + +fn f<'a>(_: &'a ()) { } diff --git a/tests/ui/mir/mir_coercions.rs b/tests/ui/mir/mir_coercions.rs new file mode 100644 index 000000000..f3dcc6b85 --- /dev/null +++ b/tests/ui/mir/mir_coercions.rs @@ -0,0 +1,71 @@ +// run-pass +#![feature(coerce_unsized, unsize)] + +use std::ops::CoerceUnsized; +use std::marker::Unsize; + +fn identity_coercion(x: &(dyn Fn(u32)->u32 + Send)) -> &dyn Fn(u32)->u32 { + x +} +fn fn_coercions(f: &fn(u32) -> u32) -> + (unsafe fn(u32) -> u32, + &(dyn Fn(u32) -> u32+Send)) +{ + (*f, f) +} + +fn simple_array_coercion(x: &[u8; 3]) -> &[u8] { x } + +fn square(a: u32) -> u32 { a * a } + +#[derive(PartialEq,Eq)] +struct PtrWrapper<'a, T: 'a+?Sized>(u32, u32, (), &'a T); +impl<'a, T: ?Sized+Unsize, U: ?Sized> + CoerceUnsized> for PtrWrapper<'a, T> {} + +struct TrivPtrWrapper<'a, T: 'a+?Sized>(&'a T); +impl<'a, T: ?Sized+Unsize, U: ?Sized> + CoerceUnsized> for TrivPtrWrapper<'a, T> {} + +fn coerce_ptr_wrapper(p: PtrWrapper<[u8; 3]>) -> PtrWrapper<[u8]> { + p +} + +fn coerce_triv_ptr_wrapper(p: TrivPtrWrapper<[u8; 3]>) -> TrivPtrWrapper<[u8]> { + p +} + +fn coerce_fat_ptr_wrapper(p: PtrWrapper u32+Send>) + -> PtrWrapper u32> { + p +} + +fn coerce_ptr_wrapper_poly<'a, T, Trait: ?Sized>(p: PtrWrapper<'a, T>) + -> PtrWrapper<'a, Trait> + where PtrWrapper<'a, T>: CoerceUnsized> +{ + p +} + +fn main() { + let a = [0,1,2]; + let square_local : fn(u32) -> u32 = square; + let (f,g) = fn_coercions(&square_local); + assert_eq!(f as usize, square as usize); + assert_eq!(g(4), 16); + assert_eq!(identity_coercion(g)(5), 25); + + assert_eq!(simple_array_coercion(&a), &a); + let w = coerce_ptr_wrapper(PtrWrapper(2,3,(),&a)); + assert!(w == PtrWrapper(2,3,(),&a) as PtrWrapper<[u8]>); + + let w = coerce_triv_ptr_wrapper(TrivPtrWrapper(&a)); + assert_eq!(&w.0, &a); + + let z = coerce_fat_ptr_wrapper(PtrWrapper(2,3,(),&square_local)); + assert_eq!((z.3)(6), 36); + + let z: PtrWrapper u32> = + coerce_ptr_wrapper_poly(PtrWrapper(2,3,(),&square_local)); + assert_eq!((z.3)(6), 36); +} diff --git a/tests/ui/mir/mir_const_prop_identity.rs b/tests/ui/mir/mir_const_prop_identity.rs new file mode 100644 index 000000000..25d2202b9 --- /dev/null +++ b/tests/ui/mir/mir_const_prop_identity.rs @@ -0,0 +1,12 @@ +// Regression test for issue #91725. +// +// run-pass +// compile-flags: -Zmir-opt-level=4 + +fn main() { + let a = true; + let _ = &a; + let mut b = false; + b |= a; + assert!(b); +} diff --git a/tests/ui/mir/mir_const_prop_tuple_field_reorder.rs b/tests/ui/mir/mir_const_prop_tuple_field_reorder.rs new file mode 100644 index 000000000..b66a85d07 --- /dev/null +++ b/tests/ui/mir/mir_const_prop_tuple_field_reorder.rs @@ -0,0 +1,27 @@ +// compile-flags: -Z mir-opt-level=3 +// build-pass +#![crate_type="lib"] + +// This used to ICE: const-prop did not account for field reordering of scalar pairs, +// and would generate a tuple like `(0x1337, VariantBar): (FooEnum, isize)`, +// causing assertion failures in codegen when trying to read 0x1337 at the wrong type. + +pub enum FooEnum { + VariantBar, + VariantBaz, + VariantBuz, +} + +pub fn wrong_index() -> isize { + let (_, b) = id((FooEnum::VariantBar, 0x1337)); + b +} + +pub fn wrong_index_two() -> isize { + let (_, (_, b)) = id(((), (FooEnum::VariantBar, 0x1338))); + b +} + +fn id(x: T) -> T { + x +} diff --git a/tests/ui/mir/mir_constval_adts.rs b/tests/ui/mir/mir_constval_adts.rs new file mode 100644 index 000000000..ee9d73451 --- /dev/null +++ b/tests/ui/mir/mir_constval_adts.rs @@ -0,0 +1,34 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Point { + _x: i32, + _y: i32, +} + +#[derive(PartialEq, Eq, Debug)] +struct Newtype(T); + +const STRUCT: Point = Point { _x: 42, _y: 42 }; +const TUPLE1: (i32, i32) = (42, 42); +const TUPLE2: (&'static str, &'static str) = ("hello","world"); +const PAIR_NEWTYPE: (Newtype, Newtype) = (Newtype(42), Newtype(42)); + +fn mir() -> (Point, (i32, i32), (&'static str, &'static str), (Newtype, Newtype)) { + let struct1 = STRUCT; + let tuple1 = TUPLE1; + let tuple2 = TUPLE2; + let pair_newtype = PAIR_NEWTYPE; + (struct1, tuple1, tuple2, pair_newtype) +} + +const NEWTYPE: Newtype<&'static str> = Newtype("foobar"); + +fn test_promoted_newtype_str_ref() { + let x = &NEWTYPE; + assert_eq!(x, &Newtype("foobar")); +} + +fn main(){ + assert_eq!(mir(), (STRUCT, TUPLE1, TUPLE2, PAIR_NEWTYPE)); + test_promoted_newtype_str_ref(); +} diff --git a/tests/ui/mir/mir_detects_invalid_ops.rs b/tests/ui/mir/mir_detects_invalid_ops.rs new file mode 100644 index 000000000..136c03cd9 --- /dev/null +++ b/tests/ui/mir/mir_detects_invalid_ops.rs @@ -0,0 +1,24 @@ +// build-fail + +fn main() { + divide_by_zero(); + mod_by_zero(); + oob_error_for_slices(); +} + +fn divide_by_zero() { + let y = 0; + let _z = 1 / y; //~ ERROR this operation will panic at runtime [unconditional_panic] +} + +fn mod_by_zero() { + let y = 0; + let _z = 1 % y; //~ ERROR this operation will panic at runtime [unconditional_panic] +} + +fn oob_error_for_slices() { + let a: *const [_] = &[1, 2, 3]; + unsafe { + let _b = (*a)[3]; + } +} diff --git a/tests/ui/mir/mir_detects_invalid_ops.stderr b/tests/ui/mir/mir_detects_invalid_ops.stderr new file mode 100644 index 000000000..0fe56f417 --- /dev/null +++ b/tests/ui/mir/mir_detects_invalid_ops.stderr @@ -0,0 +1,16 @@ +error: this operation will panic at runtime + --> $DIR/mir_detects_invalid_ops.rs:11:14 + | +LL | let _z = 1 / y; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/mir_detects_invalid_ops.rs:16:14 + | +LL | let _z = 1 % y; + | ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mir/mir_drop_order.rs b/tests/ui/mir/mir_drop_order.rs new file mode 100644 index 000000000..75f5b171a --- /dev/null +++ b/tests/ui/mir/mir_drop_order.rs @@ -0,0 +1,48 @@ +// run-pass +// needs-unwind + +use std::cell::RefCell; +use std::panic; + +pub struct DropLogger<'a> { + id: usize, + log: &'a panic::AssertUnwindSafe>> +} + +impl<'a> Drop for DropLogger<'a> { + fn drop(&mut self) { + self.log.0.borrow_mut().push(self.id); + } +} + +struct InjectedFailure; + +#[allow(unreachable_code)] +fn main() { + let log = panic::AssertUnwindSafe(RefCell::new(vec![])); + let d = |id| DropLogger { id: id, log: &log }; + let get = || -> Vec<_> { + let mut m = log.0.borrow_mut(); + let n = m.drain(..); + n.collect() + }; + + { + let _x = (d(0), &d(1), d(2), &d(3)); + // all borrows are extended - nothing has been dropped yet + assert_eq!(get(), vec![]); + } + // in a let-statement, extended places are dropped + // *after* the let result (tho they have the same scope + // as far as scope-based borrowck goes). + assert_eq!(get(), vec![0, 2, 3, 1]); + + let _ = std::panic::catch_unwind(|| { + (d(4), &d(5), d(6), &d(7), panic::panic_any(InjectedFailure)); + }); + + // here, the temporaries (5/7) live until the end of the + // containing statement, which is destroyed after the operands + // (4/6) on a panic. + assert_eq!(get(), vec![6, 4, 7, 5]); +} diff --git a/tests/ui/mir/mir_drop_panics.rs b/tests/ui/mir/mir_drop_panics.rs new file mode 100644 index 000000000..0d00426d6 --- /dev/null +++ b/tests/ui/mir/mir_drop_panics.rs @@ -0,0 +1,24 @@ +// run-fail +// needs-unwind +// error-pattern:panic 1 +// error-pattern:drop 2 + +struct Droppable(u32); +impl Drop for Droppable { + fn drop(&mut self) { + if self.0 == 1 { + panic!("panic 1"); + } else { + eprintln!("drop {}", self.0); + } + } +} + +fn mir() { + let x = Droppable(2); + let y = Droppable(1); +} + +fn main() { + mir(); +} diff --git a/tests/ui/mir/mir_dynamic_drops_1.rs b/tests/ui/mir/mir_dynamic_drops_1.rs new file mode 100644 index 000000000..2b33b6166 --- /dev/null +++ b/tests/ui/mir/mir_dynamic_drops_1.rs @@ -0,0 +1,31 @@ +// run-fail +// error-pattern:drop 1 +// error-pattern:drop 2 +// ignore-emscripten no processes + +/// Structure which will not allow to be dropped twice. +struct Droppable<'a>(&'a mut bool, u32); +impl<'a> Drop for Droppable<'a> { + fn drop(&mut self) { + if *self.0 { + eprintln!("{} dropped twice", self.1); + ::std::process::exit(1); + } + eprintln!("drop {}", self.1); + *self.0 = true; + } +} + +fn mir() { + let (mut xv, mut yv) = (false, false); + let x = Droppable(&mut xv, 1); + let y = Droppable(&mut yv, 2); + let mut z = x; + let k = y; + z = k; +} + +fn main() { + mir(); + panic!(); +} diff --git a/tests/ui/mir/mir_dynamic_drops_2.rs b/tests/ui/mir/mir_dynamic_drops_2.rs new file mode 100644 index 000000000..c883efdab --- /dev/null +++ b/tests/ui/mir/mir_dynamic_drops_2.rs @@ -0,0 +1,29 @@ +// run-fail +// error-pattern:drop 1 +// ignore-emscripten no processes + +/// Structure which will not allow to be dropped twice. +struct Droppable<'a>(&'a mut bool, u32); +impl<'a> Drop for Droppable<'a> { + fn drop(&mut self) { + if *self.0 { + eprintln!("{} dropped twice", self.1); + ::std::process::exit(1); + } + eprintln!("drop {}", self.1); + *self.0 = true; + } +} + +fn mir<'a>(d: Droppable<'a>) { + loop { + let x = d; + break; + } +} + +fn main() { + let mut xv = false; + mir(Droppable(&mut xv, 1)); + panic!(); +} diff --git a/tests/ui/mir/mir_dynamic_drops_3.rs b/tests/ui/mir/mir_dynamic_drops_3.rs new file mode 100644 index 000000000..2bcd9fac5 --- /dev/null +++ b/tests/ui/mir/mir_dynamic_drops_3.rs @@ -0,0 +1,35 @@ +// run-fail +// needs-unwind +// error-pattern:unwind happens +// error-pattern:drop 3 +// error-pattern:drop 2 +// error-pattern:drop 1 +// ignore-emscripten no processes + +/// Structure which will not allow to be dropped twice. +struct Droppable<'a>(&'a mut bool, u32); +impl<'a> Drop for Droppable<'a> { + fn drop(&mut self) { + if *self.0 { + eprintln!("{} dropped twice", self.1); + ::std::process::exit(1); + } + eprintln!("drop {}", self.1); + *self.0 = true; + } +} + +fn may_panic<'a>() -> Droppable<'a> { + panic!("unwind happens"); +} + +fn mir<'a>(d: Droppable<'a>) { + let (mut a, mut b) = (false, false); + let y = Droppable(&mut a, 2); + let x = [Droppable(&mut b, 1), y, d, may_panic()]; +} + +fn main() { + let mut c = false; + mir(Droppable(&mut c, 3)); +} diff --git a/tests/ui/mir/mir_early_return_scope.rs b/tests/ui/mir/mir_early_return_scope.rs new file mode 100644 index 000000000..a696471c3 --- /dev/null +++ b/tests/ui/mir/mir_early_return_scope.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(unused_variables)] +static mut DROP: bool = false; + +struct ConnWrap(Conn); +impl ::std::ops::Deref for ConnWrap { + type Target=Conn; + fn deref(&self) -> &Conn { &self.0 } +} + +struct Conn; +impl Drop for Conn { + fn drop(&mut self) { unsafe { DROP = true; } } +} + +fn inner() { + let conn = &*match Some(ConnWrap(Conn)) { + Some(val) => val, + None => return, + }; + return; +} + +fn main() { + inner(); + unsafe { + assert_eq!(DROP, true); + } +} diff --git a/tests/ui/mir/mir_fat_ptr.rs b/tests/ui/mir/mir_fat_ptr.rs new file mode 100644 index 000000000..7c3e07c9e --- /dev/null +++ b/tests/ui/mir/mir_fat_ptr.rs @@ -0,0 +1,52 @@ +// run-pass +// test that ordinary fat pointer operations work. + +struct Wrapper(#[allow(unused_tuple_struct_fields)] u32, T); + +struct FatPtrContainer<'a> { + ptr: &'a [u8] +} + +fn fat_ptr_project(a: &Wrapper<[u8]>) -> &[u8] { + &a.1 +} + +fn fat_ptr_simple(a: &[u8]) -> &[u8] { + a +} + +fn fat_ptr_via_local(a: &[u8]) -> &[u8] { + let x = a; + x +} + +fn fat_ptr_from_struct(s: FatPtrContainer) -> &[u8] { + s.ptr +} + +fn fat_ptr_to_struct(a: &[u8]) -> FatPtrContainer { + FatPtrContainer { ptr: a } +} + +fn fat_ptr_store_to<'a>(a: &'a [u8], b: &mut &'a [u8]) { + *b = a; +} + +fn fat_ptr_constant() -> &'static str { + "HELLO" +} + +fn main() { + let a = Wrapper(4, [7,6,5]); + + let p = fat_ptr_project(&a); + let p = fat_ptr_simple(p); + let p = fat_ptr_via_local(p); + let p = fat_ptr_from_struct(fat_ptr_to_struct(p)); + + let mut target : &[u8] = &[42]; + fat_ptr_store_to(p, &mut target); + assert_eq!(target, &a.1); + + assert_eq!(fat_ptr_constant(), "HELLO"); +} diff --git a/tests/ui/mir/mir_fat_ptr_drop.rs b/tests/ui/mir/mir_fat_ptr_drop.rs new file mode 100644 index 000000000..d865c3499 --- /dev/null +++ b/tests/ui/mir/mir_fat_ptr_drop.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(unused_variables)] +#![allow(stable_features)] + +// test that ordinary fat pointer operations work. + +#![feature(braced_empty_structs)] +#![feature(rustc_attrs)] + +use std::sync::atomic; +use std::sync::atomic::Ordering::SeqCst; + +static COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(0); + +struct DropMe { +} + +impl Drop for DropMe { + fn drop(&mut self) { + COUNTER.fetch_add(1, SeqCst); + } +} + +fn fat_ptr_move_then_drop(a: Box<[DropMe]>) { + let b = a; +} + +fn main() { + let a: Box<[DropMe]> = Box::new([DropMe { }]); + fat_ptr_move_then_drop(a); + assert_eq!(COUNTER.load(SeqCst), 1); +} diff --git a/tests/ui/mir/mir_heavy_promoted.rs b/tests/ui/mir/mir_heavy_promoted.rs new file mode 100644 index 000000000..092299880 --- /dev/null +++ b/tests/ui/mir/mir_heavy_promoted.rs @@ -0,0 +1,11 @@ +// run-pass +// ignore-emscripten apparently only works in optimized mode + +const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024]; + +// Check that the promoted copy of TEST_DATA doesn't +// leave an alloca from an unused temp behind, which, +// without optimizations, can still blow the stack. +fn main() { + println!("{}", TEST_DATA.len()); +} diff --git a/tests/ui/mir/mir_indexing_oob_1.rs b/tests/ui/mir/mir_indexing_oob_1.rs new file mode 100644 index 000000000..6d769b6b2 --- /dev/null +++ b/tests/ui/mir/mir_indexing_oob_1.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 10 +// ignore-emscripten no processes + +const C: [u32; 5] = [0; 5]; + +#[allow(unconditional_panic)] +fn test() -> u32 { + C[10] +} + +fn main() { + test(); +} diff --git a/tests/ui/mir/mir_indexing_oob_2.rs b/tests/ui/mir/mir_indexing_oob_2.rs new file mode 100644 index 000000000..a9e850570 --- /dev/null +++ b/tests/ui/mir/mir_indexing_oob_2.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 10 +// ignore-emscripten no processes + +const C: &'static [u8; 5] = b"hello"; + +#[allow(unconditional_panic)] +fn test() -> u8 { + C[10] +} + +fn main() { + test(); +} diff --git a/tests/ui/mir/mir_indexing_oob_3.rs b/tests/ui/mir/mir_indexing_oob_3.rs new file mode 100644 index 000000000..4f5cab59b --- /dev/null +++ b/tests/ui/mir/mir_indexing_oob_3.rs @@ -0,0 +1,14 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 10 +// ignore-emscripten no processes + +const C: &'static [u8; 5] = b"hello"; + +#[allow(unconditional_panic)] +fn mir() -> u8 { + C[10] +} + +fn main() { + mir(); +} diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs new file mode 100644 index 000000000..6471553e9 --- /dev/null +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -0,0 +1,93 @@ +// run-pass +// needs-unwind + +// See `mir_drop_order.rs` for more information + +#![feature(let_chains)] +#![allow(irrefutable_let_patterns)] + +use std::cell::RefCell; +use std::panic; + +pub struct DropLogger<'a, T> { + extra: T, + id: usize, + log: &'a panic::AssertUnwindSafe>>, +} + +impl<'a, T> Drop for DropLogger<'a, T> { + fn drop(&mut self) { + self.log.0.borrow_mut().push(self.id); + } +} + +struct InjectedFailure; + +#[allow(unreachable_code)] +fn main() { + let log = panic::AssertUnwindSafe(RefCell::new(vec![])); + let d = |id, extra| DropLogger { extra, id: id, log: &log }; + let get = || -> Vec<_> { + let mut m = log.0.borrow_mut(); + let n = m.drain(..); + n.collect() + }; + + { + let _x = ( + d( + 0, + d( + 1, + if let Some(_) = d(2, Some(true)).extra && let DropLogger { .. } = d(3, None) { + None + } else { + Some(true) + } + ).extra + ), + d(4, None), + &d(5, None), + d(6, None), + if let DropLogger { .. } = d(7, None) && let DropLogger { .. } = d(8, None) { + d(9, None) + } + else { + // 10 is not constructed + d(10, None) + }, + ); + assert_eq!(get(), vec![8, 7, 1, 3, 2]); + } + assert_eq!(get(), vec![0, 4, 6, 9, 5]); + + let _ = std::panic::catch_unwind(|| { + ( + d( + 11, + d( + 12, + if let Some(_) = d(13, Some(true)).extra + && let DropLogger { .. } = d(14, None) + { + None + } else { + Some(true) + } + ).extra + ), + d(15, None), + &d(16, None), + d(17, None), + if let DropLogger { .. } = d(18, None) && let DropLogger { .. } = d(19, None) { + d(20, None) + } + else { + // 10 is not constructed + d(21, None) + }, + panic::panic_any(InjectedFailure) + ); + }); + assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]); +} diff --git a/tests/ui/mir/mir_match_arm_guard.rs b/tests/ui/mir/mir_match_arm_guard.rs new file mode 100644 index 000000000..65e4ed041 --- /dev/null +++ b/tests/ui/mir/mir_match_arm_guard.rs @@ -0,0 +1,16 @@ +// run-pass +// #30527 - We were not generating arms with guards in certain cases. + +fn match_with_guard(x: Option) -> i8 { + match x { + Some(xyz) if xyz > 100 => 0, + Some(_) => -1, + None => -2 + } +} + +fn main() { + assert_eq!(match_with_guard(Some(111)), 0); + assert_eq!(match_with_guard(Some(2)), -1); + assert_eq!(match_with_guard(None), -2); +} diff --git a/tests/ui/mir/mir_match_test.rs b/tests/ui/mir/mir_match_test.rs new file mode 100644 index 000000000..1f96d6737 --- /dev/null +++ b/tests/ui/mir/mir_match_test.rs @@ -0,0 +1,83 @@ +#![feature(exclusive_range_pattern)] + +// run-pass + +fn main() { + let incl_range = |x, b| { + match x { + 0..=5 if b => 0, + 5..=10 if b => 1, + 1..=4 if !b => 2, + _ => 3, + } + }; + assert_eq!(incl_range(3, false), 2); + assert_eq!(incl_range(3, true), 0); + assert_eq!(incl_range(5, false), 3); + assert_eq!(incl_range(5, true), 0); + + let excl_range = |x, b| { + match x { + 0..5 if b => 0, + 5..10 if b => 1, + 1..4 if !b => 2, + _ => 3, + } + }; + assert_eq!(excl_range(3, false), 2); + assert_eq!(excl_range(3, true), 0); + assert_eq!(excl_range(5, false), 3); + assert_eq!(excl_range(5, true), 1); + + let incl_range_vs_const = |x, b| { + match x { + 0..=5 if b => 0, + 7 => 1, + 3 => 2, + _ => 3, + } + }; + assert_eq!(incl_range_vs_const(5, false), 3); + assert_eq!(incl_range_vs_const(5, true), 0); + assert_eq!(incl_range_vs_const(3, false), 2); + assert_eq!(incl_range_vs_const(3, true), 0); + assert_eq!(incl_range_vs_const(7, false), 1); + assert_eq!(incl_range_vs_const(7, true), 1); + + let excl_range_vs_const = |x, b| { + match x { + 0..5 if b => 0, + 7 => 1, + 3 => 2, + _ => 3, + } + }; + assert_eq!(excl_range_vs_const(5, false), 3); + assert_eq!(excl_range_vs_const(5, true), 3); + assert_eq!(excl_range_vs_const(3, false), 2); + assert_eq!(excl_range_vs_const(3, true), 0); + assert_eq!(excl_range_vs_const(7, false), 1); + assert_eq!(excl_range_vs_const(7, true), 1); + + let const_vs_incl_range = |x, b| { + match x { + 3 if b => 0, + 5..=7 => 2, + 1..=4 => 1, + _ => 3, + } + }; + assert_eq!(const_vs_incl_range(3, false), 1); + assert_eq!(const_vs_incl_range(3, true), 0); + + let const_vs_excl_range = |x, b| { + match x { + 3 if b => 0, + 5..7 => 2, + 1..4 => 1, + _ => 3, + } + }; + assert_eq!(const_vs_excl_range(3, false), 1); + assert_eq!(const_vs_excl_range(3, true), 0); +} diff --git a/tests/ui/mir/mir_misc_casts.rs b/tests/ui/mir/mir_misc_casts.rs new file mode 100644 index 000000000..2e7fbeee5 --- /dev/null +++ b/tests/ui/mir/mir_misc_casts.rs @@ -0,0 +1,320 @@ +// run-pass +fn func(){} + +const STR: &'static str = "hello"; +const BSTR: &'static [u8; 5] = b"hello"; + +fn from_ptr() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, *const ()) { + let f = 1_usize as *const String; + let c1 = f as isize; + let c2 = f as usize; + let c3 = f as i8; + let c4 = f as i16; + let c5 = f as i32; + let c6 = f as i64; + let c7 = f as u8; + let c8 = f as u16; + let c9 = f as u32; + let c10 = f as u64; + let c11 = f as *const (); + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) +} + +fn from_1() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1 as isize; + let c2 = 1 as usize; + let c3 = 1 as i8; + let c4 = 1 as i16; + let c5 = 1 as i32; + let c6 = 1 as i64; + let c7 = 1 as u8; + let c8 = 1 as u16; + let c9 = 1 as u32; + let c10 = 1 as u64; + let c11 = 1 as f32; + let c12 = 1 as f64; + let c13 = 1 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1usize() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_usize as isize; + let c2 = 1_usize as usize; + let c3 = 1_usize as i8; + let c4 = 1_usize as i16; + let c5 = 1_usize as i32; + let c6 = 1_usize as i64; + let c7 = 1_usize as u8; + let c8 = 1_usize as u16; + let c9 = 1_usize as u32; + let c10 = 1_usize as u64; + let c11 = 1_usize as f32; + let c12 = 1_usize as f64; + let c13 = 1_usize as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1isize() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_isize as isize; + let c2 = 1_isize as usize; + let c3 = 1_isize as i8; + let c4 = 1_isize as i16; + let c5 = 1_isize as i32; + let c6 = 1_isize as i64; + let c7 = 1_isize as u8; + let c8 = 1_isize as u16; + let c9 = 1_isize as u32; + let c10 = 1_isize as u64; + let c11 = 1_isize as f32; + let c12 = 1_isize as f64; + let c13 = 1_isize as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u8() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u8 as isize; + let c2 = 1_u8 as usize; + let c3 = 1_u8 as i8; + let c4 = 1_u8 as i16; + let c5 = 1_u8 as i32; + let c6 = 1_u8 as i64; + let c7 = 1_u8 as u8; + let c8 = 1_u8 as u16; + let c9 = 1_u8 as u32; + let c10 = 1_u8 as u64; + let c11 = 1_u8 as f32; + let c12 = 1_u8 as f64; + let c13 = 1_u8 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i8() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i8 as isize; + let c2 = 1_i8 as usize; + let c3 = 1_i8 as i8; + let c4 = 1_i8 as i16; + let c5 = 1_i8 as i32; + let c6 = 1_i8 as i64; + let c7 = 1_i8 as u8; + let c8 = 1_i8 as u16; + let c9 = 1_i8 as u32; + let c10 = 1_i8 as u64; + let c11 = 1_i8 as f32; + let c12 = 1_i8 as f64; + let c13 = 1_i8 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u16() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u16 as isize; + let c2 = 1_u16 as usize; + let c3 = 1_u16 as i8; + let c4 = 1_u16 as i16; + let c5 = 1_u16 as i32; + let c6 = 1_u16 as i64; + let c7 = 1_u16 as u8; + let c8 = 1_u16 as u16; + let c9 = 1_u16 as u32; + let c10 = 1_u16 as u64; + let c11 = 1_u16 as f32; + let c12 = 1_u16 as f64; + let c13 = 1_u16 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i16() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i16 as isize; + let c2 = 1_i16 as usize; + let c3 = 1_i16 as i8; + let c4 = 1_i16 as i16; + let c5 = 1_i16 as i32; + let c6 = 1_i16 as i64; + let c7 = 1_i16 as u8; + let c8 = 1_i16 as u16; + let c9 = 1_i16 as u32; + let c10 = 1_i16 as u64; + let c11 = 1_i16 as f32; + let c12 = 1_i16 as f64; + let c13 = 1_i16 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u32() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u32 as isize; + let c2 = 1_u32 as usize; + let c3 = 1_u32 as i8; + let c4 = 1_u32 as i16; + let c5 = 1_u32 as i32; + let c6 = 1_u32 as i64; + let c7 = 1_u32 as u8; + let c8 = 1_u32 as u16; + let c9 = 1_u32 as u32; + let c10 = 1_u32 as u64; + let c11 = 1_u32 as f32; + let c12 = 1_u32 as f64; + let c13 = 1_u32 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i32() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i32 as isize; + let c2 = 1_i32 as usize; + let c3 = 1_i32 as i8; + let c4 = 1_i32 as i16; + let c5 = 1_i32 as i32; + let c6 = 1_i32 as i64; + let c7 = 1_i32 as u8; + let c8 = 1_i32 as u16; + let c9 = 1_i32 as u32; + let c10 = 1_i32 as u64; + let c11 = 1_i32 as f32; + let c12 = 1_i32 as f64; + let c13 = 1_i32 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1u64() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_u64 as isize; + let c2 = 1_u64 as usize; + let c3 = 1_u64 as i8; + let c4 = 1_u64 as i16; + let c5 = 1_u64 as i32; + let c6 = 1_u64 as i64; + let c7 = 1_u64 as u8; + let c8 = 1_u64 as u16; + let c9 = 1_u64 as u32; + let c10 = 1_u64 as u64; + let c11 = 1_u64 as f32; + let c12 = 1_u64 as f64; + let c13 = 1_u64 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_1i64() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, *const String) { + let c1 = 1_i64 as isize; + let c2 = 1_i64 as usize; + let c3 = 1_i64 as i8; + let c4 = 1_i64 as i16; + let c5 = 1_i64 as i32; + let c6 = 1_i64 as i64; + let c7 = 1_i64 as u8; + let c8 = 1_i64 as u16; + let c9 = 1_i64 as u32; + let c10 = 1_i64 as u64; + let c11 = 1_i64 as f32; + let c12 = 1_i64 as f64; + let c13 = 1_i64 as *const String; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13) +} + +fn from_bool() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64) { + let c1 = true as isize; + let c2 = true as usize; + let c3 = true as i8; + let c4 = true as i16; + let c5 = true as i32; + let c6 = true as i64; + let c7 = true as u8; + let c8 = true as u16; + let c9 = true as u32; + let c10 = true as u64; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10) +} + +fn from_1f32() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) { + let c1 = 1.0_f32 as isize; + let c2 = 1.0_f32 as usize; + let c3 = 1.0_f32 as i8; + let c4 = 1.0_f32 as i16; + let c5 = 1.0_f32 as i32; + let c6 = 1.0_f32 as i64; + let c7 = 1.0_f32 as u8; + let c8 = 1.0_f32 as u16; + let c9 = 1.0_f32 as u32; + let c10 = 1.0_f32 as u64; + let c11 = 1.0_f32 as f32; + let c12 = 1.0_f32 as f64; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12) +} + +fn from_1f64() +-> (isize, usize, i8, i16, i32, i64, u8, u16, u32, u64, f32, f64) { + let c1 = 1.0f64 as isize; + let c2 = 1.0f64 as usize; + let c3 = 1.0f64 as i8; + let c4 = 1.0f64 as i16; + let c5 = 1.0f64 as i32; + let c6 = 1.0f64 as i64; + let c7 = 1.0f64 as u8; + let c8 = 1.0f64 as u16; + let c9 = 1.0f64 as u32; + let c10 = 1.0f64 as u64; + let c11 = 1.0f64 as f32; + let c12 = 1.0f64 as f64; + (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12) +} + +fn other_casts() +-> (*const u8, *const isize, *const u8, *const u8) { + let c1 = func as *const u8; + let c2 = c1 as *const isize; + + let r = &42u32; + let _ = r as *const u32; + + // fat-ptr -> fat-ptr -> fat-raw-ptr -> thin-ptr + let c3 = STR as &str as *const str as *const u8; + + let c4 = BSTR as *const [u8] as *const [u16] as *const u8; + (c1, c2, c3, c4) +} + +pub fn assert_eq_13(l: (isize, usize, i8, i16, i32, i64, u8, + u16, u32, u64, f32, f64, *const String), + r: (isize, usize, i8, i16, i32, i64, u8, + u16, u32, u64, f32, f64, *const String)) -> bool { + let (l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13) = l; + let (r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13) = r; + l1 == r1 && l2 == r2 && l3 == r3 && l4 == r4 && l5 == r5 && l6 == r6 && l7 == r7 && + l8 == r8 && l9 == r9 && l10 == r10 && l11 == r11 && l12 == r12 && l13 == r13 +} + + +pub fn main() { + let f = 1_usize as *const String; + let t13 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0, f); + let t12 = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.0, 1.0); + assert_eq_13(from_1(), t13); + assert_eq_13(from_1usize(), t13); + assert_eq_13(from_1isize(), t13); + assert_eq_13(from_1u8(), t13); + assert_eq_13(from_1i8(), t13); + assert_eq_13(from_1u16(), t13); + assert_eq_13(from_1i16(), t13); + assert_eq_13(from_1u32(), t13); + assert_eq_13(from_1i32(), t13); + assert_eq_13(from_1u64(), t13); + assert_eq_13(from_1i64(), t13); + assert_eq!(from_1f32(), t12); + assert_eq!(from_1f64(), t12); + + assert_eq!(from_ptr(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 as *const ())); + assert_eq!(from_bool(), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + + assert_eq!(other_casts(), (func as *const u8, func as *const isize, + STR as *const str as *const u8, BSTR as *const [u8] as *const u8)); +} diff --git a/tests/ui/mir/mir_overflow_off.rs b/tests/ui/mir/mir_overflow_off.rs new file mode 100644 index 000000000..0098584dd --- /dev/null +++ b/tests/ui/mir/mir_overflow_off.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags: -C overflow-checks=off + +// Test that with MIR codegen, overflow checks can be +// turned off, even when they're from core::ops::*. + +use std::ops::*; + +fn main() { + assert_eq!(i8::neg(-0x80), -0x80); + + assert_eq!(u8::add(0xff, 1), 0_u8); + assert_eq!(u8::sub(0, 1), 0xff_u8); + assert_eq!(u8::mul(0xff, 2), 0xfe_u8); + assert_eq!(u8::shl(1, 9), 2_u8); + assert_eq!(u8::shr(2, 9), 1_u8); +} diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs new file mode 100644 index 000000000..6aceefbe7 --- /dev/null +++ b/tests/ui/mir/mir_raw_fat_ptr.rs @@ -0,0 +1,216 @@ +// run-pass +// check raw fat pointer ops in mir +// FIXME: please improve this when we get monomorphization support +#![feature(raw_ref_op)] + +use std::mem; + +#[derive(Debug, PartialEq, Eq)] +struct ComparisonResults { + lt: bool, + le: bool, + gt: bool, + ge: bool, + eq: bool, + ne: bool +} + +const LT: ComparisonResults = ComparisonResults { + lt: true, + le: true, + gt: false, + ge: false, + eq: false, + ne: true +}; + +const EQ: ComparisonResults = ComparisonResults { + lt: false, + le: true, + gt: false, + ge: true, + eq: true, + ne: false +}; + +const GT: ComparisonResults = ComparisonResults { + lt: false, + le: false, + gt: true, + ge: true, + eq: false, + ne: true +}; + +fn compare_su8(a: *const S<[u8]>, b: *const S<[u8]>) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +fn compare_au8(a: *const [u8], b: *const [u8]) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +fn compare_foo<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> ComparisonResults { + ComparisonResults { + lt: a < b, + le: a <= b, + gt: a > b, + ge: a >= b, + eq: a == b, + ne: a != b + } +} + +fn simple_eq<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> bool { + let result = a == b; + result +} + +fn assert_inorder(a: &[T], + compare: fn(T, T) -> ComparisonResults) { + for i in 0..a.len() { + for j in 0..a.len() { + let cres = compare(a[i], a[j]); + if i < j { + assert_eq!(cres, LT); + } else if i == j { + assert_eq!(cres, EQ); + } else { + assert_eq!(cres, GT); + } + } + } +} + +trait Foo { fn foo(&self) -> usize; } +impl Foo for T { + fn foo(&self) -> usize { + mem::size_of::() + } +} + +#[allow(unused_tuple_struct_fields)] +struct S(u32, T); + +fn main_ref() { + let array = [0,1,2,3,4]; + let array2 = [5,6,7,8,9]; + + // fat ptr comparison: addr then extra + + // check ordering for arrays + let mut ptrs: Vec<*const [u8]> = vec![ + &array[0..0], &array[0..1], &array, &array[1..] + ]; + + let array_addr = &array as *const [u8] as *const u8 as usize; + let array2_addr = &array2 as *const [u8] as *const u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &array2); + } else { + ptrs.push(&array2); + } + assert_inorder(&ptrs, compare_au8); + + let u8_ = (0u8, 1u8); + let u32_ = (4u32, 5u32); + + // check ordering for ptrs + let buf: &mut [*const dyn Foo] = &mut [ + &u8_, &u8_.0, + &u32_, &u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf, compare_foo); + + // check ordering for structs containing arrays + let ss: (S<[u8; 2]>, + S<[u8; 3]>, + S<[u8; 2]>) = ( + S(7, [8, 9]), + S(10, [11, 12, 13]), + S(4, [5, 6]) + ); + assert_inorder(&[ + &ss.0 as *const S<[u8]>, + &ss.1 as *const S<[u8]>, + &ss.2 as *const S<[u8]> + ], compare_su8); + + assert!(simple_eq(&0u8 as *const _, &0u8 as *const _)); + assert!(!simple_eq(&0u8 as *const _, &1u8 as *const _)); +} + +// similar to above, but using &raw +fn main_raw() { + let array = [0,1,2,3,4]; + let array2 = [5,6,7,8,9]; + + // fat ptr comparison: addr then extra + + // check ordering for arrays + let mut ptrs: Vec<*const [u8]> = vec![ + &raw const array[0..0], &raw const array[0..1], &raw const array, &raw const array[1..] + ]; + + let array_addr = &raw const array as *const u8 as usize; + let array2_addr = &raw const array2 as *const u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &raw const array2); + } else { + ptrs.push(&raw const array2); + } + assert_inorder(&ptrs, compare_au8); + + let u8_ = (0u8, 1u8); + let u32_ = (4u32, 5u32); + + // check ordering for ptrs + let buf: &mut [*const dyn Foo] = &mut [ + &raw const u8_, &raw const u8_.0, + &raw const u32_, &raw const u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf, compare_foo); + + // check ordering for structs containing arrays + let ss: (S<[u8; 2]>, + S<[u8; 3]>, + S<[u8; 2]>) = ( + S(7, [8, 9]), + S(10, [11, 12, 13]), + S(4, [5, 6]) + ); + assert_inorder(&[ + &raw const ss.0 as *const S<[u8]>, + &raw const ss.1 as *const S<[u8]>, + &raw const ss.2 as *const S<[u8]> + ], compare_su8); +} + +fn main() { + main_ref(); + main_raw(); +} diff --git a/tests/ui/mir/mir_refs_correct.rs b/tests/ui/mir/mir_refs_correct.rs new file mode 100644 index 000000000..6cd9526b7 --- /dev/null +++ b/tests/ui/mir/mir_refs_correct.rs @@ -0,0 +1,209 @@ +// run-pass +// aux-build:mir_external_refs.rs + +extern crate mir_external_refs as ext; + +struct S(#[allow(unused_tuple_struct_fields)] u8); +#[derive(Debug, PartialEq, Eq)] +struct Unit; + +impl S { + fn hey() -> u8 { 42 } + fn hey2(&self) -> u8 { 44 } +} + +trait X { + fn hoy(&self) -> u8 { 43 } + fn hoy2() -> u8 { 45 } +} + +trait F { + fn f(self, other: U) -> u64; +} + +impl F for u32 { + fn f(self, other: u32) -> u64 { self as u64 + other as u64 } +} + +impl F for u32 { + fn f(self, other: u64) -> u64 { self as u64 - other } +} + +impl F for u64 { + fn f(self, other: u64) -> u64 { self * other } +} + +impl F for u64 { + fn f(self, other: u32) -> u64 { self ^ other as u64 } +} + +trait T { + fn staticmeth(i: I, o: O) -> (I, O) { (i, o) } +} + +impl T for O {} + +impl X for S {} + +enum E { + U(#[allow(unused_tuple_struct_fields)] u8) +} + +#[derive(PartialEq, Debug, Eq)] +enum CEnum { + A = 0x321, + B = 0x123 +} + +const C: u8 = 84; +const C2: [u8; 5] = [42; 5]; +const C3: [u8; 3] = [42, 41, 40]; +const C4: fn(u8) -> S = S; + +fn regular() -> u8 { + 21 +} + +fn parametric(u: T) -> T { + u +} + +fn t1() -> fn()->u8 { + regular +} + +fn t2() -> fn(u8)->E { + E::U +} + +fn t3() -> fn(u8)->S { + S +} + +fn t4() -> fn()->u8 { + S::hey +} + +fn t5() -> fn(&S)-> u8 { + ::hoy +} + + +fn t6() -> fn()->u8{ + ext::regular_fn +} + +fn t7() -> fn(u8)->ext::E { + ext::E::U +} + +fn t8() -> fn(u8)->ext::S { + ext::S +} + +fn t9() -> fn()->u8 { + ext::S::hey +} + +fn t10() -> fn(&ext::S)->u8 { + ::hoy +} + +fn t11() -> fn(u8)->u8 { + parametric +} + +fn t12() -> u8 { + C +} + +fn t13() -> [u8; 5] { + C2 +} + +fn t13_2() -> [u8; 3] { + C3 +} + +fn t14() -> fn()-> u8 { + ::hoy2 +} + +fn t15() -> fn(&S)-> u8 { + S::hey2 +} + +fn t16() -> fn(u32, u32)->u64 { + F::f +} + +fn t17() -> fn(u32, u64)->u64 { + F::f +} + +fn t18() -> fn(u64, u64)->u64 { + F::f +} + +fn t19() -> fn(u64, u32)->u64 { + F::f +} + +fn t20() -> fn(u64, u32)->(u64, u32) { + >::staticmeth +} + +fn t21() -> Unit { + Unit +} + +fn t22() -> Option { + None +} + +fn t23() -> (CEnum, CEnum) { + (CEnum::A, CEnum::B) +} + +fn t24() -> fn(u8) -> S { + C4 +} + +fn main() { + assert_eq!(t1()(), regular()); + + assert_eq!(t2() as *mut (), E::U as *mut ()); + assert_eq!(t3() as *mut (), S as *mut ()); + + assert_eq!(t4()(), S::hey()); + let s = S(42); + assert_eq!(t5()(&s), ::hoy(&s)); + + + assert_eq!(t6()(), ext::regular_fn()); + assert_eq!(t7() as *mut (), ext::E::U as *mut ()); + assert_eq!(t8() as *mut (), ext::S as *mut ()); + + assert_eq!(t9()(), ext::S::hey()); + let sext = ext::S(6); + assert_eq!(t10()(&sext), ::hoy(&sext)); + + let p = parametric::; + assert_eq!(t11() as *mut (), p as *mut ()); + + assert_eq!(t12(), C); + assert_eq!(t13(), C2); + assert_eq!(t13_2(), C3); + + assert_eq!(t14()(), ::hoy2()); + assert_eq!(t15()(&s), S::hey2(&s)); + assert_eq!(t16()(10u32, 20u32), F::f(10u32, 20u32)); + assert_eq!(t17()(30u32, 10u64), F::f(30u32, 10u64)); + assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64)); + assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32)); + assert_eq!(t20()(123u64, 38u32), >::staticmeth(123, 38)); + assert_eq!(t21(), Unit); + assert_eq!(t22(), None); + assert_eq!(t23(), (CEnum::A, CEnum::B)); + assert_eq!(t24(), C4); +} diff --git a/tests/ui/mir/mir_small_agg_arg.rs b/tests/ui/mir/mir_small_agg_arg.rs new file mode 100644 index 000000000..5a22a0420 --- /dev/null +++ b/tests/ui/mir/mir_small_agg_arg.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_variables)] +fn foo((x, y): (i8, i8)) { +} + +fn main() { + foo((0, 1)); +} diff --git a/tests/ui/mir/mir_static_subtype.rs b/tests/ui/mir/mir_static_subtype.rs new file mode 100644 index 000000000..d471b8f14 --- /dev/null +++ b/tests/ui/mir/mir_static_subtype.rs @@ -0,0 +1,9 @@ +// run-pass +// Test that subtyping the body of a static doesn't cause an ICE. + +fn foo(_ : &()) {} +static X: fn(&'static ()) = foo; + +fn main() { + let _ = X; +} diff --git a/tests/ui/mir/mir_struct_with_assoc_ty.rs b/tests/ui/mir/mir_struct_with_assoc_ty.rs new file mode 100644 index 000000000..26d026bdf --- /dev/null +++ b/tests/ui/mir/mir_struct_with_assoc_ty.rs @@ -0,0 +1,29 @@ +// run-pass +use std::marker::PhantomData; + +pub trait DataBind { + type Data; +} + +impl DataBind for Global { + type Data = T; +} + +pub struct Global(PhantomData); + +pub struct Data { + pub offsets: as DataBind>::Data, +} + +fn create_data() -> Data { + let mut d = Data { offsets: [1, 2] }; + d.offsets[0] = 3; + d +} + + +fn main() { + let d = create_data(); + assert_eq!(d.offsets[0], 3); + assert_eq!(d.offsets[1], 2); +} diff --git a/tests/ui/mir/mir_temp_promotions.rs b/tests/ui/mir/mir_temp_promotions.rs new file mode 100644 index 000000000..845dc4c04 --- /dev/null +++ b/tests/ui/mir/mir_temp_promotions.rs @@ -0,0 +1,10 @@ +// run-pass +fn test1(f: f32) -> bool { + // test that we properly promote temporaries to allocas when a temporary is assigned to + // multiple times (assignment is still happening once ∀ possible dataflows). + !(f.is_nan() || f.is_infinite()) +} + +fn main() { + assert_eq!(test1(0.0), true); +} diff --git a/tests/ui/mir/mir_void_return.rs b/tests/ui/mir/mir_void_return.rs new file mode 100644 index 000000000..d257affc2 --- /dev/null +++ b/tests/ui/mir/mir_void_return.rs @@ -0,0 +1,12 @@ +// run-pass +fn mir() -> (){ + let x = 1; + let mut y = 0; + while y < x { + y += 1 + } +} + +pub fn main() { + mir(); +} diff --git a/tests/ui/mir/mir_void_return_2.rs b/tests/ui/mir/mir_void_return_2.rs new file mode 100644 index 000000000..a1fb0a7db --- /dev/null +++ b/tests/ui/mir/mir_void_return_2.rs @@ -0,0 +1,10 @@ +// run-pass +fn nil() {} + +fn mir(){ + nil() +} + +pub fn main() { + mir(); +} diff --git a/tests/ui/mir/remove-zsts-query-cycle.rs b/tests/ui/mir/remove-zsts-query-cycle.rs new file mode 100644 index 000000000..be4d68f2d --- /dev/null +++ b/tests/ui/mir/remove-zsts-query-cycle.rs @@ -0,0 +1,16 @@ +// Regression test for #88972. Used to cause a query cycle: +// optimized mir -> remove zsts -> layout of a generator -> optimized mir. +// +// edition:2018 +// compile-flags: --crate-type=lib -Zinline-mir=yes +// build-pass + +pub async fn listen() -> Result<(), std::io::Error> { + let f = do_async(); + std::mem::forget(f); + Ok(()) +} + +pub async fn do_async() { + listen().await.unwrap() +} diff --git a/tests/ui/mir/simplify-branch-same.rs b/tests/ui/mir/simplify-branch-same.rs new file mode 100644 index 000000000..d631c33d6 --- /dev/null +++ b/tests/ui/mir/simplify-branch-same.rs @@ -0,0 +1,21 @@ +// Regression test for SimplifyBranchSame miscompilation. +// run-pass + +macro_rules! m { + ($a:expr, $b:expr, $c:block) => { + match $a { + Lto::Fat | Lto::Thin => { $b; (); $c } + Lto::No => { $b; () } + } + } +} + +pub enum Lto { No, Thin, Fat } + +fn f(mut cookie: u32, lto: Lto) -> u32 { + let mut _a = false; + m!(lto, _a = true, {cookie = 0}); + cookie +} + +fn main() { assert_eq!(f(42, Lto::Thin), 0) } diff --git a/tests/ui/mir/ssa-analysis-regression-50041.rs b/tests/ui/mir/ssa-analysis-regression-50041.rs new file mode 100644 index 000000000..ebc3e2f8c --- /dev/null +++ b/tests/ui/mir/ssa-analysis-regression-50041.rs @@ -0,0 +1,36 @@ +// build-pass +// compile-flags: -Z mir-opt-level=4 + +#![crate_type = "lib"] +#![feature(lang_items)] +#![no_std] + +struct NonNull(*const T); + +struct Unique(NonNull); + +#[lang = "owned_box"] +pub struct Box(Unique); + +impl Drop for Box { + fn drop(&mut self) {} +} + +#[lang = "box_free"] +#[inline(always)] +unsafe fn box_free(ptr: Unique) { + dealloc(ptr.0.0) +} + +#[inline(never)] +fn dealloc(_: *const T) {} + +pub struct Foo(T); + +pub fn foo(a: Option>>) -> usize { + let f = match a { + None => Foo(0), + Some(vec) => *vec, + }; + f.0 +} diff --git a/tests/ui/mir/thir-constparam-temp.rs b/tests/ui/mir/thir-constparam-temp.rs new file mode 100644 index 000000000..cdc5910b3 --- /dev/null +++ b/tests/ui/mir/thir-constparam-temp.rs @@ -0,0 +1,20 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +struct Yikes; + +impl Yikes { + fn mut_self(&mut self) {} +} + +fn foo() { + YIKES.mut_self() + //~^ WARNING taking a mutable reference +} + +fn main() { + foo::<{ Yikes }>() +} diff --git a/tests/ui/mir/thir-constparam-temp.stderr b/tests/ui/mir/thir-constparam-temp.stderr new file mode 100644 index 000000000..b77d67e08 --- /dev/null +++ b/tests/ui/mir/thir-constparam-temp.stderr @@ -0,0 +1,22 @@ +warning: taking a mutable reference to a `const` item + --> $DIR/thir-constparam-temp.rs:14:5 + | +LL | YIKES.mut_self() + | ^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: mutable reference created due to call to this method + --> $DIR/thir-constparam-temp.rs:10:5 + | +LL | fn mut_self(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^ +note: `const` item defined here + --> $DIR/thir-constparam-temp.rs:13:8 + | +LL | fn foo() { + | ^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs new file mode 100644 index 000000000..cd6c5bf27 --- /dev/null +++ b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Zvalidate-mir + +fn foo(_a: &str) {} + +fn main() { + let x = foo as fn(&'static str); + + let _ = x == foo; +} diff --git a/tests/ui/mir/validate/needs-reveal-all.rs b/tests/ui/mir/validate/needs-reveal-all.rs new file mode 100644 index 000000000..3852daf24 --- /dev/null +++ b/tests/ui/mir/validate/needs-reveal-all.rs @@ -0,0 +1,52 @@ +// Regression test for #105009. the issue here was that even after the `RevealAll` pass, +// `validate` still used `Reveal::UserFacing`. This meant that it now ends up comparing +// opaque types with their revealed version, resulting in an ICE. +// +// We're using these flags to run the `RevealAll` pass while making it less likely to +// accidentally removing the assignment from `Foo` to `Foo`. + +// compile-flags: -Zinline_mir=yes -Zmir-opt-level=0 -Zvalidate-mir +// run-pass + +use std::hint::black_box; + +trait Func { + type Ret: Id; +} + +trait Id { + type Assoc; +} +impl Id for u32 { + type Assoc = u32; +} +impl Id for i32 { + type Assoc = i32; +} + +impl R, R: Id> Func for F { + type Ret = R; +} + +fn bar() -> impl Copy + Id { + 0u32 +} + +struct Foo { + _func: T, + value: Option<<::Ret as Id>::Assoc>, +} + +fn main() { + let mut fn_def = black_box(Foo { + _func: bar, + value: None, + }); + let fn_ptr = black_box(Foo { + _func: bar as fn() -> _, + value: None, + }); + + fn_def.value = fn_ptr.value; + black_box(fn_def); +} diff --git a/tests/ui/mismatched_types/E0053.rs b/tests/ui/mismatched_types/E0053.rs new file mode 100644 index 000000000..d3146ce54 --- /dev/null +++ b/tests/ui/mismatched_types/E0053.rs @@ -0,0 +1,16 @@ +trait Foo { + fn foo(x: u16); + fn bar(&self); +} + +struct Bar; + +impl Foo for Bar { + fn foo(x: i16) { } + //~^ ERROR method `foo` has an incompatible type for trait + fn bar(&mut self) { } + //~^ ERROR method `bar` has an incompatible type for trait +} + +fn main() { +} diff --git a/tests/ui/mismatched_types/E0053.stderr b/tests/ui/mismatched_types/E0053.stderr new file mode 100644 index 000000000..154f2fcbe --- /dev/null +++ b/tests/ui/mismatched_types/E0053.stderr @@ -0,0 +1,37 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/E0053.rs:9:15 + | +LL | fn foo(x: i16) { } + | ^^^ + | | + | expected `u16`, found `i16` + | help: change the parameter type to match the trait: `u16` + | +note: type in trait + --> $DIR/E0053.rs:2:15 + | +LL | fn foo(x: u16); + | ^^^ + = note: expected signature `fn(u16)` + found signature `fn(i16)` + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/E0053.rs:11:12 + | +LL | fn bar(&mut self) { } + | ^^^^^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `self: &Bar` + | +note: type in trait + --> $DIR/E0053.rs:3:12 + | +LL | fn bar(&self); + | ^^^^^ + = note: expected signature `fn(&Bar)` + found signature `fn(&mut Bar)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/mismatched_types/E0409.rs b/tests/ui/mismatched_types/E0409.rs new file mode 100644 index 000000000..3710534cc --- /dev/null +++ b/tests/ui/mismatched_types/E0409.rs @@ -0,0 +1,9 @@ +fn main() { + let x = (0, 2); + + match x { + (0, ref y) | (y, 0) => {} //~ ERROR E0409 + //~| ERROR E0308 + _ => () + } +} diff --git a/tests/ui/mismatched_types/E0409.stderr b/tests/ui/mismatched_types/E0409.stderr new file mode 100644 index 000000000..7fec6ecd7 --- /dev/null +++ b/tests/ui/mismatched_types/E0409.stderr @@ -0,0 +1,28 @@ +error[E0409]: variable `y` is bound inconsistently across alternatives separated by `|` + --> $DIR/E0409.rs:5:23 + | +LL | (0, ref y) | (y, 0) => {} + | - ^ bound in different ways + | | + | first binding + +error[E0308]: mismatched types + --> $DIR/E0409.rs:5:23 + | +LL | match x { + | - this expression has type `({integer}, {integer})` +LL | (0, ref y) | (y, 0) => {} + | ----- ^ expected `&{integer}`, found integer + | | + | first introduced with type `&{integer}` here + | + = note: in the same arm, a binding must have the same type in all alternatives +help: consider adding `ref` + | +LL | (0, ref y) | (ref y, 0) => {} + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/E0631.rs b/tests/ui/mismatched_types/E0631.rs new file mode 100644 index 000000000..83dbdb77a --- /dev/null +++ b/tests/ui/mismatched_types/E0631.rs @@ -0,0 +1,11 @@ +#![feature(unboxed_closures)] + +fn foo(_: F) {} +fn bar>(_: F) {} +fn main() { + fn f(_: u64) {} + foo(|_: isize| {}); //~ ERROR type mismatch + bar(|_: isize| {}); //~ ERROR type mismatch + foo(f); //~ ERROR type mismatch + bar(f); //~ ERROR type mismatch +} diff --git a/tests/ui/mismatched_types/E0631.stderr b/tests/ui/mismatched_types/E0631.stderr new file mode 100644 index 000000000..410ea4b0b --- /dev/null +++ b/tests/ui/mismatched_types/E0631.stderr @@ -0,0 +1,73 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/E0631.rs:7:5 + | +LL | foo(|_: isize| {}); + | ^^^ ---------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(usize) -> _` + found closure signature `fn(isize) -> _` +note: required by a bound in `foo` + --> $DIR/E0631.rs:3:11 + | +LL | fn foo(_: F) {} + | ^^^^^^^^^ required by this bound in `foo` + +error[E0631]: type mismatch in closure arguments + --> $DIR/E0631.rs:8:5 + | +LL | bar(|_: isize| {}); + | ^^^ ---------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(usize) -> _` + found closure signature `fn(isize) -> _` +note: required by a bound in `bar` + --> $DIR/E0631.rs:4:11 + | +LL | fn bar>(_: F) {} + | ^^^^^^^^^^^^ required by this bound in `bar` + +error[E0631]: type mismatch in function arguments + --> $DIR/E0631.rs:9:9 + | +LL | fn f(_: u64) {} + | ------------ found signature defined here +... +LL | foo(f); + | --- ^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(usize) -> _` + found function signature `fn(u64) -> _` +note: required by a bound in `foo` + --> $DIR/E0631.rs:3:11 + | +LL | fn foo(_: F) {} + | ^^^^^^^^^ required by this bound in `foo` + +error[E0631]: type mismatch in function arguments + --> $DIR/E0631.rs:10:9 + | +LL | fn f(_: u64) {} + | ------------ found signature defined here +... +LL | bar(f); + | --- ^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(usize) -> _` + found function signature `fn(u64) -> _` +note: required by a bound in `bar` + --> $DIR/E0631.rs:4:11 + | +LL | fn bar>(_: F) {} + | ^^^^^^^^^^^^ required by this bound in `bar` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/abridged.rs b/tests/ui/mismatched_types/abridged.rs new file mode 100644 index 000000000..9a5c183ca --- /dev/null +++ b/tests/ui/mismatched_types/abridged.rs @@ -0,0 +1,62 @@ +enum Bar { + Qux, + Zar, +} + +struct Foo { + bar: usize, +} + +struct X { + x: T1, + y: T2, +} + +fn a() -> Foo { + Some(Foo { bar: 1 }) //~ ERROR mismatched types +} + +fn a2() -> Foo { + Ok(Foo { bar: 1}) //~ ERROR mismatched types +} + +fn b() -> Option { + Foo { bar: 1 } //~ ERROR mismatched types +} + +fn c() -> Result { + Foo { bar: 1 } //~ ERROR mismatched types +} + +fn d() -> X, String> { + let x = X { + x: X { + x: "".to_string(), + y: 2, + }, + y: 3, + }; + x //~ ERROR mismatched types +} + +fn e() -> X, String> { + let x = X { + x: X { + x: "".to_string(), + y: 2, + }, + y: "".to_string(), + }; + x //~ ERROR mismatched types +} + +fn f() -> String { + 1+2 //~ ERROR mismatched types +} + + +fn g() -> String { + -2 //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/mismatched_types/abridged.stderr b/tests/ui/mismatched_types/abridged.stderr new file mode 100644 index 000000000..ff1a836c9 --- /dev/null +++ b/tests/ui/mismatched_types/abridged.stderr @@ -0,0 +1,105 @@ +error[E0308]: mismatched types + --> $DIR/abridged.rs:16:5 + | +LL | fn a() -> Foo { + | --- expected `Foo` because of return type +LL | Some(Foo { bar: 1 }) + | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `Option` + | + = note: expected struct `Foo` + found enum `Option` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:20:5 + | +LL | fn a2() -> Foo { + | --- expected `Foo` because of return type +LL | Ok(Foo { bar: 1}) + | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `Result` + | + = note: expected struct `Foo` + found enum `Result` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:24:5 + | +LL | fn b() -> Option { + | ----------- expected `Option` because of return type +LL | Foo { bar: 1 } + | ^^^^^^^^^^^^^^ expected enum `Option`, found struct `Foo` + | + = note: expected enum `Option` + found struct `Foo` +help: try wrapping the expression in `Some` + | +LL | Some(Foo { bar: 1 }) + | +++++ + + +error[E0308]: mismatched types + --> $DIR/abridged.rs:28:5 + | +LL | fn c() -> Result { + | ---------------- expected `Result` because of return type +LL | Foo { bar: 1 } + | ^^^^^^^^^^^^^^ expected enum `Result`, found struct `Foo` + | + = note: expected enum `Result` + found struct `Foo` +help: try wrapping the expression in `Ok` + | +LL | Ok(Foo { bar: 1 }) + | +++ + + +error[E0308]: mismatched types + --> $DIR/abridged.rs:39:5 + | +LL | fn d() -> X, String> { + | ---------------------------- expected `X, String>` because of return type +... +LL | x + | ^ expected struct `String`, found integer + | + = note: expected struct `X, String>` + found struct `X, {integer}>` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:50:5 + | +LL | fn e() -> X, String> { + | ---------------------------- expected `X, String>` because of return type +... +LL | x + | ^ expected struct `String`, found integer + | + = note: expected struct `X, _>` + found struct `X, _>` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:54:5 + | +LL | fn f() -> String { + | ------ expected `String` because of return type +LL | 1+2 + | ^^^ expected struct `String`, found integer + | +help: try using a conversion method + | +LL | (1+2).to_string() + | + +++++++++++++ + +error[E0308]: mismatched types + --> $DIR/abridged.rs:59:5 + | +LL | fn g() -> String { + | ------ expected `String` because of return type +LL | -2 + | ^^ expected struct `String`, found integer + | +help: try using a conversion method + | +LL | (-2).to_string() + | + +++++++++++++ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/assignment-operator-unimplemented.rs b/tests/ui/mismatched_types/assignment-operator-unimplemented.rs new file mode 100644 index 000000000..21df464d5 --- /dev/null +++ b/tests/ui/mismatched_types/assignment-operator-unimplemented.rs @@ -0,0 +1,7 @@ +struct Foo; + +fn main() { + let mut a = Foo; + let ref b = Foo; + a += *b; //~ Error: binary assignment operation `+=` cannot be applied to type `Foo` +} diff --git a/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr b/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr new file mode 100644 index 000000000..2393791a9 --- /dev/null +++ b/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr @@ -0,0 +1,19 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `Foo` + --> $DIR/assignment-operator-unimplemented.rs:6:3 + | +LL | a += *b; + | -^^^^^^ + | | + | cannot use `+=` on type `Foo` + | +note: an implementation of `AddAssign<_>` might be missing for `Foo` + --> $DIR/assignment-operator-unimplemented.rs:1:1 + | +LL | struct Foo; + | ^^^^^^^^^^ must implement `AddAssign<_>` +note: the trait `AddAssign` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/mismatched_types/binops.rs b/tests/ui/mismatched_types/binops.rs new file mode 100644 index 000000000..f359451df --- /dev/null +++ b/tests/ui/mismatched_types/binops.rs @@ -0,0 +1,8 @@ +fn main() { + 1 + Some(1); //~ ERROR cannot add `Option<{integer}>` to `{integer}` + 2 as usize - Some(1); //~ ERROR cannot subtract `Option<{integer}>` from `usize` + 3 * (); //~ ERROR cannot multiply `{integer}` by `()` + 4 / ""; //~ ERROR cannot divide `{integer}` by `&str` + 5 < String::new(); //~ ERROR can't compare `{integer}` with `String` + 6 == Ok(1); //~ ERROR can't compare `{integer}` with `Result<{integer}, _>` +} diff --git a/tests/ui/mismatched_types/binops.stderr b/tests/ui/mismatched_types/binops.stderr new file mode 100644 index 000000000..3585587ed --- /dev/null +++ b/tests/ui/mismatched_types/binops.stderr @@ -0,0 +1,106 @@ +error[E0277]: cannot add `Option<{integer}>` to `{integer}` + --> $DIR/binops.rs:2:7 + | +LL | 1 + Some(1); + | ^ no implementation for `{integer} + Option<{integer}>` + | + = help: the trait `Add>` is not implemented for `{integer}` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&'a f64 as Add> + <&'a i128 as Add> + <&'a i16 as Add> + <&'a i32 as Add> + <&'a i64 as Add> + <&'a i8 as Add> + <&'a isize as Add> + and 48 others + +error[E0277]: cannot subtract `Option<{integer}>` from `usize` + --> $DIR/binops.rs:3:16 + | +LL | 2 as usize - Some(1); + | ^ no implementation for `usize - Option<{integer}>` + | + = help: the trait `Sub>` is not implemented for `usize` + = help: the following other types implement trait `Sub`: + <&'a usize as Sub> + <&usize as Sub<&usize>> + > + + +error[E0277]: cannot multiply `{integer}` by `()` + --> $DIR/binops.rs:4:7 + | +LL | 3 * (); + | ^ no implementation for `{integer} * ()` + | + = help: the trait `Mul<()>` is not implemented for `{integer}` + = help: the following other types implement trait `Mul`: + <&'a f32 as Mul> + <&'a f64 as Mul> + <&'a i128 as Mul> + <&'a i16 as Mul> + <&'a i32 as Mul> + <&'a i64 as Mul> + <&'a i8 as Mul> + <&'a isize as Mul> + and 49 others + +error[E0277]: cannot divide `{integer}` by `&str` + --> $DIR/binops.rs:5:7 + | +LL | 4 / ""; + | ^ no implementation for `{integer} / &str` + | + = help: the trait `Div<&str>` is not implemented for `{integer}` + = help: the following other types implement trait `Div`: + <&'a f32 as Div> + <&'a f64 as Div> + <&'a i128 as Div> + <&'a i16 as Div> + <&'a i32 as Div> + <&'a i64 as Div> + <&'a i8 as Div> + <&'a isize as Div> + and 54 others + +error[E0277]: can't compare `{integer}` with `String` + --> $DIR/binops.rs:6:7 + | +LL | 5 < String::new(); + | ^ no implementation for `{integer} < String` and `{integer} > String` + | + = help: the trait `PartialOrd` is not implemented for `{integer}` + = help: the following other types implement trait `PartialOrd`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +error[E0277]: can't compare `{integer}` with `Result<{integer}, _>` + --> $DIR/binops.rs:7:7 + | +LL | 6 == Ok(1); + | ^^ no implementation for `{integer} == Result<{integer}, _>` + | + = help: the trait `PartialEq>` is not implemented for `{integer}` + = help: the following other types implement trait `PartialEq`: + f32 + f64 + i128 + i16 + i32 + i64 + i8 + isize + and 6 others + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mismatched_types/cast-rfc0401.rs b/tests/ui/mismatched_types/cast-rfc0401.rs new file mode 100644 index 000000000..57222f459 --- /dev/null +++ b/tests/ui/mismatched_types/cast-rfc0401.rs @@ -0,0 +1,72 @@ +fn illegal_cast(u: *const U) -> *const V +{ + u as *const V //~ ERROR is invalid +} + +fn illegal_cast_2(u: *const U) -> *const str +{ + u as *const str //~ ERROR is invalid +} + +trait Foo { fn foo(&self) {} } +impl Foo for T {} + +trait Bar { fn foo(&self) {} } +impl Bar for T {} + +enum E { + A, B +} + +fn main() +{ + let f: f32 = 1.2; + let v = core::ptr::null::(); + let fat_v : *const [u8] = unsafe { &*core::ptr::null::<[u8; 1]>()}; + let fat_sv : *const [i8] = unsafe { &*core::ptr::null::<[i8; 1]>()}; + let foo: &dyn Foo = &f; + + let _ = v as &u8; //~ ERROR non-primitive cast + let _ = v as E; //~ ERROR non-primitive cast + let _ = v as fn(); //~ ERROR non-primitive cast + let _ = v as (u32,); //~ ERROR non-primitive cast + let _ = Some(&v) as *const u8; //~ ERROR non-primitive cast + + let _ = v as f32; //~ ERROR is invalid + let _ = main as f64; //~ ERROR is invalid + let _ = &v as usize; //~ ERROR is invalid + let _ = f as *const u8; //~ ERROR is invalid + let _ = 3_i32 as bool; //~ ERROR cannot cast + let _ = E::A as bool; //~ ERROR cannot cast + let _ = 0x61u32 as char; //~ ERROR can be cast as + + let _ = false as f32; //~ ERROR is invalid + let _ = E::A as f32; //~ ERROR is invalid + let _ = 'a' as f32; //~ ERROR is invalid + + let _ = false as *const u8; //~ ERROR is invalid + let _ = E::A as *const u8; //~ ERROR is invalid + let _ = 'a' as *const u8; //~ ERROR is invalid + + let _ = 42usize as *const [u8]; //~ ERROR cannot cast `usize` to a pointer that is wide + let _ = v as *const [u8]; //~ ERROR cannot cast + let _ = fat_v as *const dyn Foo; //~ ERROR the size for values of type + let _ = foo as *const str; //~ ERROR is invalid + let _ = foo as *mut str; //~ ERROR is invalid + let _ = main as *mut str; //~ ERROR is invalid + let _ = &f as *mut f32; //~ ERROR is invalid + let _ = &f as *const f64; //~ ERROR is invalid + let _ = fat_sv as usize; //~ ERROR is invalid + + let a : *const str = "hello"; + let _ = a as *const dyn Foo; //~ ERROR the size for values of type + + // check no error cascade + let _ = main.f as *const u32; //~ ERROR no field + + let cf: *const dyn Foo = &0; + let _ = cf as *const [u16]; //~ ERROR is invalid + let _ = cf as *const dyn Bar; //~ ERROR is invalid + + vec![0.0].iter().map(|s| s as f32).collect::>(); //~ ERROR is invalid +} diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr new file mode 100644 index 000000000..2a36a352c --- /dev/null +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -0,0 +1,256 @@ +error[E0606]: casting `*const U` as `*const V` is invalid + --> $DIR/cast-rfc0401.rs:3:5 + | +LL | u as *const V + | ^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error[E0606]: casting `*const U` as `*const str` is invalid + --> $DIR/cast-rfc0401.rs:8:5 + | +LL | u as *const str + | ^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error[E0609]: no field `f` on type `fn() {main}` + --> $DIR/cast-rfc0401.rs:65:18 + | +LL | let _ = main.f as *const u32; + | ^ + +error[E0605]: non-primitive cast: `*const u8` as `&u8` + --> $DIR/cast-rfc0401.rs:29:13 + | +LL | let _ = v as &u8; + | ^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL - let _ = v as &u8; +LL + let _ = &*v; + | + +error[E0605]: non-primitive cast: `*const u8` as `E` + --> $DIR/cast-rfc0401.rs:30:13 + | +LL | let _ = v as E; + | ^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `*const u8` as `fn()` + --> $DIR/cast-rfc0401.rs:31:13 + | +LL | let _ = v as fn(); + | ^^^^^^^^^ invalid cast + +error[E0605]: non-primitive cast: `*const u8` as `(u32,)` + --> $DIR/cast-rfc0401.rs:32:13 + | +LL | let _ = v as (u32,); + | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `Option<&*const u8>` as `*const u8` + --> $DIR/cast-rfc0401.rs:33:13 + | +LL | let _ = Some(&v) as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0606]: casting `*const u8` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:35:13 + | +LL | let _ = v as f32; + | ^^^^^^^^ + +error[E0606]: casting `fn() {main}` as `f64` is invalid + --> $DIR/cast-rfc0401.rs:36:13 + | +LL | let _ = main as f64; + | ^^^^^^^^^^^ + +error[E0606]: casting `&*const u8` as `usize` is invalid + --> $DIR/cast-rfc0401.rs:37:13 + | +LL | let _ = &v as usize; + | ^^^^^^^^^^^ + | + = help: cast through a raw pointer first + +error[E0606]: casting `f32` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:38:13 + | +LL | let _ = f as *const u8; + | ^^^^^^^^^^^^^^ + +error[E0054]: cannot cast as `bool` + --> $DIR/cast-rfc0401.rs:39:13 + | +LL | let _ = 3_i32 as bool; + | ^^^^^^^^^^^^^ help: compare with zero instead: `3_i32 != 0` + +error[E0054]: cannot cast as `bool` + --> $DIR/cast-rfc0401.rs:40:13 + | +LL | let _ = E::A as bool; + | ^^^^^^^^^^^^ unsupported cast + +error[E0604]: only `u8` can be cast as `char`, not `u32` + --> $DIR/cast-rfc0401.rs:41:13 + | +LL | let _ = 0x61u32 as char; + | ^^^^^^^^^^^^^^^ + | | + | invalid cast + | help: try `char::from_u32` instead: `char::from_u32(0x61u32)` + +error[E0606]: casting `bool` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:43:13 + | +LL | let _ = false as f32; + | ^^^^^^^^^^^^ + | + = help: cast through an integer first + +error[E0606]: casting `E` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:44:13 + | +LL | let _ = E::A as f32; + | ^^^^^^^^^^^ + | + = help: cast through an integer first + +error[E0606]: casting `char` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:45:13 + | +LL | let _ = 'a' as f32; + | ^^^^^^^^^^ + | + = help: cast through an integer first + +error[E0606]: casting `bool` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:47:13 + | +LL | let _ = false as *const u8; + | ^^^^^^^^^^^^^^^^^^ + +error[E0606]: casting `E` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:48:13 + | +LL | let _ = E::A as *const u8; + | ^^^^^^^^^^^^^^^^^ + +error[E0606]: casting `char` as `*const u8` is invalid + --> $DIR/cast-rfc0401.rs:49:13 + | +LL | let _ = 'a' as *const u8; + | ^^^^^^^^^^^^^^^^ + +error[E0606]: cannot cast `usize` to a pointer that is wide + --> $DIR/cast-rfc0401.rs:51:24 + | +LL | let _ = 42usize as *const [u8]; + | ------- ^^^^^^^^^^^ creating a `*const [u8]` requires both an address and a length + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]` + --> $DIR/cast-rfc0401.rs:52:13 + | +LL | let _ = v as *const [u8]; + | ^^^^^^^^^^^^^^^^ + +error[E0606]: casting `&dyn Foo` as `*const str` is invalid + --> $DIR/cast-rfc0401.rs:54:13 + | +LL | let _ = foo as *const str; + | ^^^^^^^^^^^^^^^^^ + +error[E0606]: casting `&dyn Foo` as `*mut str` is invalid + --> $DIR/cast-rfc0401.rs:55:13 + | +LL | let _ = foo as *mut str; + | ^^^^^^^^^^^^^^^ + +error[E0606]: casting `fn() {main}` as `*mut str` is invalid + --> $DIR/cast-rfc0401.rs:56:13 + | +LL | let _ = main as *mut str; + | ^^^^^^^^^^^^^^^^ + +error[E0606]: casting `&f32` as `*mut f32` is invalid + --> $DIR/cast-rfc0401.rs:57:13 + | +LL | let _ = &f as *mut f32; + | ^^^^^^^^^^^^^^ + +error[E0606]: casting `&f32` as `*const f64` is invalid + --> $DIR/cast-rfc0401.rs:58:13 + | +LL | let _ = &f as *const f64; + | ^^^^^^^^^^^^^^^^ + +error[E0606]: casting `*const [i8]` as `usize` is invalid + --> $DIR/cast-rfc0401.rs:59:13 + | +LL | let _ = fat_sv as usize; + | ^^^^^^^^^^^^^^^ + | + = help: cast through a thin pointer first + +error[E0606]: casting `*const dyn Foo` as `*const [u16]` is invalid + --> $DIR/cast-rfc0401.rs:68:13 + | +LL | let _ = cf as *const [u16]; + | ^^^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error[E0606]: casting `*const dyn Foo` as `*const dyn Bar` is invalid + --> $DIR/cast-rfc0401.rs:69:13 + | +LL | let _ = cf as *const dyn Bar; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: vtable kinds may not match + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/cast-rfc0401.rs:53:13 + | +LL | let _ = fat_v as *const dyn Foo; + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: required for the cast from `[u8]` to the object type `dyn Foo` +help: consider borrowing the value, since `&[u8]` can be coerced into `dyn Foo` + | +LL | let _ = &fat_v as *const dyn Foo; + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/cast-rfc0401.rs:62:13 + | +LL | let _ = a as *const dyn Foo; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn Foo` +help: consider borrowing the value, since `&str` can be coerced into `dyn Foo` + | +LL | let _ = &a as *const dyn Foo; + | + + +error[E0606]: casting `&{float}` as `f32` is invalid + --> $DIR/cast-rfc0401.rs:71:30 + | +LL | vec![0.0].iter().map(|s| s as f32).collect::>(); + | ^^^^^^^^ + | +help: dereference the expression + | +LL | vec![0.0].iter().map(|s| *s as f32).collect::>(); + | + + +error: aborting due to 34 previous errors + +Some errors have detailed explanations: E0054, E0277, E0604, E0605, E0606, E0607, E0609. +For more information about an error, try `rustc --explain E0054`. diff --git a/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed new file mode 100644 index 000000000..efba0543b --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.fixed @@ -0,0 +1,20 @@ +// Regression test for #47244: in this specific scenario, when the +// expected type indicated 1 argument but the closure takes two, we +// would (early on) create type variables for the type of `b`. If the +// user then attempts to invoke a method on `b`, we would get an error +// saying that the type of `b` must be known, which was not very +// helpful. + +// run-rustfix + +use std::collections::HashMap; + +fn main() { + let mut m = HashMap::new(); + m.insert("foo", "bar"); + + let _n = m.iter().map(|(_, b)| { + //~^ ERROR closure is expected to take a single 2-tuple + b.to_string() + }); +} diff --git a/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs new file mode 100644 index 000000000..3ddb93d12 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.rs @@ -0,0 +1,20 @@ +// Regression test for #47244: in this specific scenario, when the +// expected type indicated 1 argument but the closure takes two, we +// would (early on) create type variables for the type of `b`. If the +// user then attempts to invoke a method on `b`, we would get an error +// saying that the type of `b` must be known, which was not very +// helpful. + +// run-rustfix + +use std::collections::HashMap; + +fn main() { + let mut m = HashMap::new(); + m.insert("foo", "bar"); + + let _n = m.iter().map(|_, b| { + //~^ ERROR closure is expected to take a single 2-tuple + b.to_string() + }); +} diff --git a/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr new file mode 100644 index 000000000..d7db90e50 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-count-expected-type-issue-47244.stderr @@ -0,0 +1,16 @@ +error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments + --> $DIR/closure-arg-count-expected-type-issue-47244.rs:16:23 + | +LL | let _n = m.iter().map(|_, b| { + | ^^^ ------ takes 2 distinct arguments + | | + | expected closure that takes a single 2-tuple as argument + | +help: change the closure to accept a tuple instead of individual arguments + | +LL | let _n = m.iter().map(|(_, b)| { + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/mismatched_types/closure-arg-count.rs b/tests/ui/mismatched_types/closure-arg-count.rs new file mode 100644 index 000000000..65c8d6a7e --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-count.rs @@ -0,0 +1,43 @@ +#![feature(unboxed_closures)] + +fn f>(_: F) {} +fn main() { + [1, 2, 3].sort_by(|| panic!()); + //~^ ERROR closure is expected to take + [1, 2, 3].sort_by(|tuple| panic!()); + //~^ ERROR closure is expected to take + [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); + //~^ ERROR closure is expected to take + [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!()); + //~^ ERROR closure is expected to take + f(|| panic!()); + //~^ ERROR closure is expected to take + f( move || panic!()); + //~^ ERROR closure is expected to take + + let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); + //~^ ERROR closure is expected to take + let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); + //~^ ERROR closure is expected to take + let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); + //~^ ERROR closure is expected to take + let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); + //~^ ERROR function is expected to take + let bar = |i, x, y| i; + let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); + //~^ ERROR closure is expected to take + let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); + //~^ ERROR function is expected to take + + let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); + //~^ ERROR function is expected to take + + call(Foo); + //~^ ERROR function is expected to take +} + +fn foo() {} +fn qux(x: usize, y: usize) {} + +fn call(_: F) where F: FnOnce() -> R {} +struct Foo(u8); diff --git a/tests/ui/mismatched_types/closure-arg-count.stderr b/tests/ui/mismatched_types/closure-arg-count.stderr new file mode 100644 index 000000000..2ecab9f02 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-count.stderr @@ -0,0 +1,189 @@ +error[E0593]: closure is expected to take 2 arguments, but it takes 0 arguments + --> $DIR/closure-arg-count.rs:5:15 + | +LL | [1, 2, 3].sort_by(|| panic!()); + | ^^^^^^^ -- takes 0 arguments + | | + | expected closure that takes 2 arguments + | +help: consider changing the closure to take and ignore the expected arguments + | +LL | [1, 2, 3].sort_by(|_, _| panic!()); + | ~~~~~~ + +error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument + --> $DIR/closure-arg-count.rs:7:15 + | +LL | [1, 2, 3].sort_by(|tuple| panic!()); + | ^^^^^^^ ------- takes 1 argument + | | + | expected closure that takes 2 arguments + +error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument + --> $DIR/closure-arg-count.rs:9:15 + | +LL | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!()); + | ^^^^^^^ ----------------- takes a single 2-tuple as argument + | | + | expected closure that takes 2 distinct arguments + | +help: change the closure to take multiple arguments instead of a single tuple + | +LL | [1, 2, 3].sort_by(|tuple, tuple2| panic!()); + | ~~~~~~~~~~~~~~~ + +error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument + --> $DIR/closure-arg-count.rs:11:15 + | +LL | [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!()); + | ^^^^^^^ ----------------------------- takes a single 2-tuple as argument + | | + | expected closure that takes 2 distinct arguments + | +help: change the closure to take multiple arguments instead of a single tuple + | +LL | [1, 2, 3].sort_by(|tuple, tuple2| panic!()); + | ~~~~~~~~~~~~~~~ + +error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments + --> $DIR/closure-arg-count.rs:13:5 + | +LL | f(|| panic!()); + | ^ -- takes 0 arguments + | | + | expected closure that takes 1 argument + | +note: required by a bound in `f` + --> $DIR/closure-arg-count.rs:3:9 + | +LL | fn f>(_: F) {} + | ^^^^^^^^^^^^ required by this bound in `f` +help: consider changing the closure to take and ignore the expected argument + | +LL | f(|_| panic!()); + | ~~~ + +error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments + --> $DIR/closure-arg-count.rs:15:5 + | +LL | f( move || panic!()); + | ^ ---------- takes 0 arguments + | | + | expected closure that takes 1 argument + | +note: required by a bound in `f` + --> $DIR/closure-arg-count.rs:3:9 + | +LL | fn f>(_: F) {} + | ^^^^^^^^^^^^ required by this bound in `f` +help: consider changing the closure to take and ignore the expected argument + | +LL | f( move |_| panic!()); + | ~~~ + +error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments + --> $DIR/closure-arg-count.rs:18:53 + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); + | ^^^ ------ takes 2 distinct arguments + | | + | expected closure that takes a single 2-tuple as argument + | +help: change the closure to accept a tuple instead of individual arguments + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i); + | ~~~~~~~~ + +error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments + --> $DIR/closure-arg-count.rs:20:53 + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); + | ^^^ ------------- takes 2 distinct arguments + | | + | expected closure that takes a single 2-tuple as argument + | +help: change the closure to accept a tuple instead of individual arguments + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i); + | ~~~~~~~~ + +error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments + --> $DIR/closure-arg-count.rs:22:53 + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); + | ^^^ --------- takes 3 distinct arguments + | | + | expected closure that takes a single 2-tuple as argument + +error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments + --> $DIR/closure-arg-count.rs:24:57 + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); + | --- ^^^ expected function that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call +... +LL | fn foo() {} + | -------- takes 0 arguments + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments + --> $DIR/closure-arg-count.rs:27:57 + | +LL | let bar = |i, x, y| i; + | --------- takes 3 distinct arguments +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); + | --- ^^^ expected closure that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments + --> $DIR/closure-arg-count.rs:29:57 + | +LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); + | --- ^^^ expected function that takes a single 2-tuple as argument + | | + | required by a bound introduced by this call +... +LL | fn qux(x: usize, y: usize) {} + | -------------------------- takes 2 distinct arguments + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0593]: function is expected to take 1 argument, but it takes 2 arguments + --> $DIR/closure-arg-count.rs:32:45 + | +LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); + | --- ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument + | | + | required by a bound introduced by this call + | +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0593]: function is expected to take 0 arguments, but it takes 1 argument + --> $DIR/closure-arg-count.rs:35:10 + | +LL | call(Foo); + | ---- ^^^ expected function that takes 0 arguments + | | + | required by a bound introduced by this call +... +LL | struct Foo(u8); + | ---------- takes 1 argument + | +note: required by a bound in `call` + --> $DIR/closure-arg-count.rs:42:30 + | +LL | fn call(_: F) where F: FnOnce() -> R {} + | ^^^^^^^^^^^^^ required by this bound in `call` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed new file mode 100644 index 000000000..6315fcca2 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments +} diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs new file mode 100644 index 000000000..c12c5362e --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments +} diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr new file mode 100644 index 000000000..fb8af4bb7 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr @@ -0,0 +1,38 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24 + | +LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); + | ^^^^ -------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a {integer}) -> _` + found closure signature `fn(i32) -> _` +note: required by a bound in `find` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider borrowing the argument + | +LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24 + | +LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); + | ^^^^ ----------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a {integer}) -> _` + found closure signature `for<'a, 'b, 'c> fn(&'a &'b &'c i32) -> _` +note: required by a bound in `find` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: do not borrow the argument + | +LL - let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); +LL + let _ = (-10..=10).find(|x: &i32| x.signum() == 0); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs new file mode 100644 index 000000000..98abb0ba9 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -0,0 +1,11 @@ +fn main() { + let a = [(1u32, 2u32)]; + a.iter().map(|_: (u32, u32)| 45); //~ ERROR type mismatch + a.iter().map(|_: &(u16, u16)| 45); //~ ERROR type mismatch + a.iter().map(|_: (u16, u16)| 45); //~ ERROR type mismatch +} + +fn baz(_: F) {} +fn _test<'a>(f: fn(*mut &'a u32)) { + baz(f); +} diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr new file mode 100644 index 000000000..811ff0533 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -0,0 +1,46 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:3:14 + | +LL | a.iter().map(|_: (u32, u32)| 45); + | ^^^ --------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(&(u32, u32)) -> _` + found closure signature `fn((u32, u32)) -> _` +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider borrowing the argument + | +LL | a.iter().map(|_: &(u32, u32)| 45); + | + + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:4:14 + | +LL | a.iter().map(|_: &(u16, u16)| 45); + | ^^^ ---------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(&(u32, u32)) -> _` + found closure signature `for<'a> fn(&'a (u16, u16)) -> _` +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:5:14 + | +LL | a.iter().map(|_: (u16, u16)| 45); + | ^^^ --------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(&(u32, u32)) -> _` + found closure signature `fn((u16, u16)) -> _` +note: required by a bound in `map` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/closure-mismatch.rs b/tests/ui/mismatched_types/closure-mismatch.rs new file mode 100644 index 000000000..b0644e796 --- /dev/null +++ b/tests/ui/mismatched_types/closure-mismatch.rs @@ -0,0 +1,11 @@ +trait Foo {} + +impl Foo for T {} + +fn baz(_: T) {} + +fn main() { + baz(|_| ()); + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/closure-mismatch.stderr b/tests/ui/mismatched_types/closure-mismatch.stderr new file mode 100644 index 000000000..a7ef8fa08 --- /dev/null +++ b/tests/ui/mismatched_types/closure-mismatch.stderr @@ -0,0 +1,31 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error[E0308]: mismatched types + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Fn<(&'a (),)>` + found trait `Fn<(&(),)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/closure-mismatch.rs:8:9 + | +LL | baz(|_| ()); + | ^^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-mismatch.rs:5:11 + | +LL | fn baz(_: T) {} + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/const-fn-in-trait.rs b/tests/ui/mismatched_types/const-fn-in-trait.rs new file mode 100644 index 000000000..e04d59c58 --- /dev/null +++ b/tests/ui/mismatched_types/const-fn-in-trait.rs @@ -0,0 +1,11 @@ +trait Foo { + fn f() -> u32; + const fn g(); //~ ERROR cannot be declared const +} + +impl Foo for u32 { + const fn f() -> u32 { 22 } //~ ERROR cannot be declared const + fn g() {} +} + +fn main() { } diff --git a/tests/ui/mismatched_types/const-fn-in-trait.stderr b/tests/ui/mismatched_types/const-fn-in-trait.stderr new file mode 100644 index 000000000..7d1fbe45c --- /dev/null +++ b/tests/ui/mismatched_types/const-fn-in-trait.stderr @@ -0,0 +1,15 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/const-fn-in-trait.rs:3:5 + | +LL | const fn g(); + | ^^^^^ functions in traits cannot be const + +error[E0379]: functions in traits cannot be declared const + --> $DIR/const-fn-in-trait.rs:7:5 + | +LL | const fn f() -> u32 { 22 } + | ^^^^^ functions in traits cannot be const + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.rs b/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.rs new file mode 100644 index 000000000..d302dc99b --- /dev/null +++ b/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.rs @@ -0,0 +1,23 @@ +struct S; +struct Y; + +trait Trait {} + +impl Trait for Y {} + +fn foo() -> impl Trait { + if true { + S + } else { + Y //~ ERROR `if` and `else` have incompatible types + } +} + +fn bar() -> impl Trait { + match true { + true => S, + false => Y, //~ ERROR `match` arms have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr b/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr new file mode 100644 index 000000000..2f814445b --- /dev/null +++ b/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr @@ -0,0 +1,26 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.rs:12:9 + | +LL | / if true { +LL | | S + | | - expected because of this +LL | | } else { +LL | | Y + | | ^ expected struct `S`, found struct `Y` +LL | | } + | |_____- `if` and `else` have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.rs:19:18 + | +LL | / match true { +LL | | true => S, + | | - this is found to be of type `S` +LL | | false => Y, + | | ^ expected struct `S`, found struct `Y` +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/dont-point-return-on-E0308.rs b/tests/ui/mismatched_types/dont-point-return-on-E0308.rs new file mode 100644 index 000000000..f2ba610e2 --- /dev/null +++ b/tests/ui/mismatched_types/dont-point-return-on-E0308.rs @@ -0,0 +1,18 @@ +// edition:2021 + +async fn f(_: &()) {} +//~^ NOTE function defined here +//~| NOTE +// Second note is the span of the underlined argument, I think... + +fn main() { + (|| async { + Err::<(), ()>(())?; + f(()); + //~^ ERROR mismatched types + //~| NOTE arguments to this function are incorrect + //~| NOTE expected `&()`, found `()` + //~| HELP consider borrowing here + Ok::<(), ()>(()) + })(); +} diff --git a/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr b/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr new file mode 100644 index 000000000..13942682d --- /dev/null +++ b/tests/ui/mismatched_types/dont-point-return-on-E0308.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/dont-point-return-on-E0308.rs:11:11 + | +LL | f(()); + | - ^^ + | | | + | | expected `&()`, found `()` + | | help: consider borrowing here: `&()` + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/dont-point-return-on-E0308.rs:3:10 + | +LL | async fn f(_: &()) {} + | ^ ------ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/float-literal-inference-restrictions.rs b/tests/ui/mismatched_types/float-literal-inference-restrictions.rs new file mode 100644 index 000000000..34079b61e --- /dev/null +++ b/tests/ui/mismatched_types/float-literal-inference-restrictions.rs @@ -0,0 +1,4 @@ +fn main() { + let x: f32 = 1; //~ ERROR mismatched types + let y: f32 = 1f64; //~ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/float-literal-inference-restrictions.stderr b/tests/ui/mismatched_types/float-literal-inference-restrictions.stderr new file mode 100644 index 000000000..454373c32 --- /dev/null +++ b/tests/ui/mismatched_types/float-literal-inference-restrictions.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/float-literal-inference-restrictions.rs:2:18 + | +LL | let x: f32 = 1; + | --- ^ + | | | + | | expected `f32`, found integer + | | help: use a float literal: `1.0` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/float-literal-inference-restrictions.rs:3:18 + | +LL | let y: f32 = 1f64; + | --- ^^^^ expected `f32`, found `f64` + | | + | expected due to this + | +help: change the type of the numeric literal from `f64` to `f32` + | +LL | let y: f32 = 1f32; + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/fn-variance-1.rs b/tests/ui/mismatched_types/fn-variance-1.rs new file mode 100644 index 000000000..b8a6c9a9b --- /dev/null +++ b/tests/ui/mismatched_types/fn-variance-1.rs @@ -0,0 +1,17 @@ +fn takes_imm(x: &isize) { } + +fn takes_mut(x: &mut isize) { } + +fn apply(t: T, f: F) where F: FnOnce(T) { + f(t) +} + +fn main() { + apply(&3, takes_imm); + apply(&3, takes_mut); + //~^ ERROR type mismatch + + apply(&mut 3, takes_mut); + apply(&mut 3, takes_imm); + //~^ ERROR type mismatch +} diff --git a/tests/ui/mismatched_types/fn-variance-1.stderr b/tests/ui/mismatched_types/fn-variance-1.stderr new file mode 100644 index 000000000..5794e606e --- /dev/null +++ b/tests/ui/mismatched_types/fn-variance-1.stderr @@ -0,0 +1,41 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/fn-variance-1.rs:11:15 + | +LL | fn takes_mut(x: &mut isize) { } + | --------------------------- found signature defined here +... +LL | apply(&3, takes_mut); + | ----- ^^^^^^^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(&{integer}) -> _` + found function signature `for<'a> fn(&'a mut isize) -> _` +note: required by a bound in `apply` + --> $DIR/fn-variance-1.rs:5:37 + | +LL | fn apply(t: T, f: F) where F: FnOnce(T) { + | ^^^^^^^^^ required by this bound in `apply` + +error[E0631]: type mismatch in function arguments + --> $DIR/fn-variance-1.rs:15:19 + | +LL | fn takes_imm(x: &isize) { } + | ----------------------- found signature defined here +... +LL | apply(&mut 3, takes_imm); + | ----- ^^^^^^^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(&mut {integer}) -> _` + found function signature `for<'a> fn(&'a isize) -> _` +note: required by a bound in `apply` + --> $DIR/fn-variance-1.rs:5:37 + | +LL | fn apply(t: T, f: F) where F: FnOnce(T) { + | ^^^^^^^^^ required by this bound in `apply` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/for-loop-has-unit-body.rs b/tests/ui/mismatched_types/for-loop-has-unit-body.rs new file mode 100644 index 000000000..a9433d7de --- /dev/null +++ b/tests/ui/mismatched_types/for-loop-has-unit-body.rs @@ -0,0 +1,5 @@ +fn main() { + for x in 0..3 { + x //~ ERROR mismatched types + } +} diff --git a/tests/ui/mismatched_types/for-loop-has-unit-body.stderr b/tests/ui/mismatched_types/for-loop-has-unit-body.stderr new file mode 100644 index 000000000..f36fe64bf --- /dev/null +++ b/tests/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/for-loop-has-unit-body.rs:3:9 + | +LL | x + | ^ expected `()`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-106182.fixed b/tests/ui/mismatched_types/issue-106182.fixed new file mode 100644 index 000000000..b8ddebf6f --- /dev/null +++ b/tests/ui/mismatched_types/issue-106182.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +struct _S(u32, Vec); + +fn _foo(x: &_S) { + match x { + _S(mut _y, _v) => { + //~^ ERROR mismatched types [E0308] + } + } +} + +fn main() { +} diff --git a/tests/ui/mismatched_types/issue-106182.rs b/tests/ui/mismatched_types/issue-106182.rs new file mode 100644 index 000000000..6eb6df13a --- /dev/null +++ b/tests/ui/mismatched_types/issue-106182.rs @@ -0,0 +1,14 @@ +// run-rustfix + +struct _S(u32, Vec); + +fn _foo(x: &_S) { + match x { + _S(& (mut _y), _v) => { + //~^ ERROR mismatched types [E0308] + } + } +} + +fn main() { +} diff --git a/tests/ui/mismatched_types/issue-106182.stderr b/tests/ui/mismatched_types/issue-106182.stderr new file mode 100644 index 000000000..ac3ab8e98 --- /dev/null +++ b/tests/ui/mismatched_types/issue-106182.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-106182.rs:7:12 + | +LL | match x { + | - this expression has type `&_S` +LL | _S(& (mut _y), _v) => { + | ^^^^^^^^^^ expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | _S(mut _y, _v) => { + | ~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-19109.rs b/tests/ui/mismatched_types/issue-19109.rs new file mode 100644 index 000000000..eae6a8790 --- /dev/null +++ b/tests/ui/mismatched_types/issue-19109.rs @@ -0,0 +1,8 @@ +trait Trait { } + +fn function(t: &mut dyn Trait) { + t as *mut dyn Trait + //~^ ERROR: mismatched types +} + +fn main() { } diff --git a/tests/ui/mismatched_types/issue-19109.stderr b/tests/ui/mismatched_types/issue-19109.stderr new file mode 100644 index 000000000..5cef64bb1 --- /dev/null +++ b/tests/ui/mismatched_types/issue-19109.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-19109.rs:4:5 + | +LL | fn function(t: &mut dyn Trait) { + | - help: try adding a return type: `-> *mut dyn Trait` +LL | t as *mut dyn Trait + | ^^^^^^^^^^^^^^^^^^^ expected `()`, found `*mut dyn Trait` + | + = note: expected unit type `()` + found raw pointer `*mut dyn Trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-26480.rs b/tests/ui/mismatched_types/issue-26480.rs new file mode 100644 index 000000000..8bd26cebc --- /dev/null +++ b/tests/ui/mismatched_types/issue-26480.rs @@ -0,0 +1,29 @@ +extern "C" { + fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64; +} + +#[inline(always)] +fn size_of(_: T) -> usize { + ::std::mem::size_of::() +} + +macro_rules! write { + ($arr:expr) => {{ + #[allow(non_upper_case_globals)] + const stdout: i32 = 1; + unsafe { + write(stdout, $arr.as_ptr() as *const i8, + $arr.len() * size_of($arr[0])); //~ ERROR mismatched types + } + }} +} + +macro_rules! cast { + ($x:expr) => ($x as ()) //~ ERROR non-primitive cast +} + +fn main() { + let hello = ['H', 'e', 'y']; + write!(hello); + cast!(2); +} diff --git a/tests/ui/mismatched_types/issue-26480.stderr b/tests/ui/mismatched_types/issue-26480.stderr new file mode 100644 index 000000000..ae10a0067 --- /dev/null +++ b/tests/ui/mismatched_types/issue-26480.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> $DIR/issue-26480.rs:16:19 + | +LL | write(stdout, $arr.as_ptr() as *const i8, + | ----- arguments to this function are incorrect +LL | $arr.len() * size_of($arr[0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize` +... +LL | write!(hello); + | ------------- in this macro invocation + | +note: function defined here + --> $DIR/issue-26480.rs:2:8 + | +LL | fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64; + | ^^^^^ + = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit + | +LL | ($arr.len() * size_of($arr[0])).try_into().unwrap()); + | + +++++++++++++++++++++ + +error[E0605]: non-primitive cast: `{integer}` as `()` + --> $DIR/issue-26480.rs:22:19 + | +LL | ($x:expr) => ($x as ()) + | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object +... +LL | cast!(2); + | -------- in this macro invocation + | + = note: this error originates in the macro `cast` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0605. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-35030.rs b/tests/ui/mismatched_types/issue-35030.rs new file mode 100644 index 000000000..91ea7ea80 --- /dev/null +++ b/tests/ui/mismatched_types/issue-35030.rs @@ -0,0 +1,15 @@ +#![allow(non_camel_case_types)] + +trait Parser { + fn parse(text: &str) -> Option; +} + +impl Parser for bool { + fn parse(text: &str) -> Option { + Some(true) //~ ERROR mismatched types + } +} + +fn main() { + println!("{}", bool::parse("ok").unwrap_or(false)); +} diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr new file mode 100644 index 000000000..de4e067fe --- /dev/null +++ b/tests/ui/mismatched_types/issue-35030.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-35030.rs:9:14 + | +LL | impl Parser for bool { + | ---- this type parameter +LL | fn parse(text: &str) -> Option { +LL | Some(true) + | ---- ^^^^ expected type parameter `bool`, found `bool` + | | + | arguments to this enum variant are incorrect + | + = note: expected type parameter `bool` (type parameter `bool`) + found type `bool` (`bool`) +help: the type constructed contains `bool` due to the type of the argument passed + --> $DIR/issue-35030.rs:9:9 + | +LL | Some(true) + | ^^^^^----^ + | | + | this argument influences the type of `Some` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-36053-2.rs b/tests/ui/mismatched_types/issue-36053-2.rs new file mode 100644 index 000000000..17d2292ba --- /dev/null +++ b/tests/ui/mismatched_types/issue-36053-2.rs @@ -0,0 +1,10 @@ +// Regression test for #36053. ICE was caused due to obligations +// being added to a special, dedicated fulfillment cx during +// a probe. + +use std::iter::once; +fn main() { + once::<&str>("str").fuse().filter(|a: &str| true).count(); + //~^ ERROR the method + //~| ERROR type mismatch in closure arguments +} diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr new file mode 100644 index 000000000..a6764a1dc --- /dev/null +++ b/tests/ui/mismatched_types/issue-36053-2.stderr @@ -0,0 +1,41 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-36053-2.rs:7:32 + | +LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | ^^^^^^ --------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `for<'a> fn(&'a &str) -> _` + found closure signature `for<'a> fn(&'a str) -> _` +note: required by a bound in `filter` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL +help: consider borrowing the argument + | +LL | once::<&str>("str").fuse().filter(|a: &&str| true).count(); + | + + +error[E0599]: the method `count` exists for struct `Filter>, [closure@issue-36053-2.rs:7:39]>`, but its trait bounds were not satisfied + --> $DIR/issue-36053-2.rs:7:55 + | +LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); + | --------- ^^^^^ method cannot be called due to unsatisfied trait bounds + | | + | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` + | doesn't satisfy `_: FnMut<(&&str,)>` + --> $SRC_DIR/core/src/iter/adapters/filter.rs:LL:COL + | + = note: doesn't satisfy `_: Iterator` + | + = note: the following trait bounds were not satisfied: + `<[closure@$DIR/issue-36053-2.rs:7:39: 7:48] as FnOnce<(&&str,)>>::Output = bool` + which is required by `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + `[closure@$DIR/issue-36053-2.rs:7:39: 7:48]: FnMut<(&&str,)>` + which is required by `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + which is required by `&mut Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:48]>: Iterator` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0631. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/mismatched_types/issue-38371-unfixable.rs b/tests/ui/mismatched_types/issue-38371-unfixable.rs new file mode 100644 index 000000000..c4316bfdd --- /dev/null +++ b/tests/ui/mismatched_types/issue-38371-unfixable.rs @@ -0,0 +1,5 @@ +fn ugh(&[bar]: &u32) {} //~ ERROR expected an array or slice + +fn bgh(&&bar: u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-38371-unfixable.stderr b/tests/ui/mismatched_types/issue-38371-unfixable.stderr new file mode 100644 index 000000000..3c5e765ab --- /dev/null +++ b/tests/ui/mismatched_types/issue-38371-unfixable.stderr @@ -0,0 +1,21 @@ +error[E0529]: expected an array or slice, found `u32` + --> $DIR/issue-38371-unfixable.rs:1:9 + | +LL | fn ugh(&[bar]: &u32) {} + | ^^^^^ pattern cannot match with input type `u32` + +error[E0308]: mismatched types + --> $DIR/issue-38371-unfixable.rs:3:8 + | +LL | fn bgh(&&bar: u32) {} + | ^^^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0529. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-38371.fixed b/tests/ui/mismatched_types/issue-38371.fixed new file mode 100644 index 000000000..0e20835be --- /dev/null +++ b/tests/ui/mismatched_types/issue-38371.fixed @@ -0,0 +1,18 @@ +// run-rustfix +// see also issue-38371-unfixable.rs +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct Foo {} + +fn foo(_a: &Foo) {} //~ ERROR mismatched types + +fn bar(_a: Foo) {} + +fn qux(_a: &Foo) {} + +fn zar(&_a: &Foo) {} + +fn agh(&_a: &u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-38371.rs b/tests/ui/mismatched_types/issue-38371.rs new file mode 100644 index 000000000..fb9e4c173 --- /dev/null +++ b/tests/ui/mismatched_types/issue-38371.rs @@ -0,0 +1,18 @@ +// run-rustfix +// see also issue-38371-unfixable.rs +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct Foo {} + +fn foo(&_a: Foo) {} //~ ERROR mismatched types + +fn bar(_a: Foo) {} + +fn qux(_a: &Foo) {} + +fn zar(&_a: &Foo) {} + +fn agh(&&_a: &u32) {} //~ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-38371.stderr b/tests/ui/mismatched_types/issue-38371.stderr new file mode 100644 index 000000000..f43427f98 --- /dev/null +++ b/tests/ui/mismatched_types/issue-38371.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-38371.rs:8:8 + | +LL | fn foo(&_a: Foo) {} + | ^^^ --- expected due to this + | | + | expected struct `Foo`, found reference + | + = note: expected struct `Foo` + found reference `&_` +help: to take parameter `_a` by reference, move `&` to the type + | +LL - fn foo(&_a: Foo) {} +LL + fn foo(_a: &Foo) {} + | + +error[E0308]: mismatched types + --> $DIR/issue-38371.rs:16:9 + | +LL | fn agh(&&_a: &u32) {} + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn agh(&&_a: &u32) {} +LL + fn agh(&_a: &u32) {} + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/issue-47706-trait.rs b/tests/ui/mismatched_types/issue-47706-trait.rs new file mode 100644 index 000000000..8fb4e0855 --- /dev/null +++ b/tests/ui/mismatched_types/issue-47706-trait.rs @@ -0,0 +1,8 @@ +trait T { + fn f(&self, _: ()) { + None::<()>.map(Self::f); + } + //~^^ ERROR function is expected to take a single 0-tuple as argument +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-47706-trait.stderr b/tests/ui/mismatched_types/issue-47706-trait.stderr new file mode 100644 index 000000000..a5f38dd53 --- /dev/null +++ b/tests/ui/mismatched_types/issue-47706-trait.stderr @@ -0,0 +1,16 @@ +error[E0593]: function is expected to take a single 0-tuple as argument, but it takes 2 distinct arguments + --> $DIR/issue-47706-trait.rs:3:24 + | +LL | fn f(&self, _: ()) { + | ------------------ takes 2 distinct arguments +LL | None::<()>.map(Self::f); + | --- ^^^^^^^ expected function that takes a single 0-tuple as argument + | | + | required by a bound introduced by this call + | +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/mismatched_types/issue-47706.rs b/tests/ui/mismatched_types/issue-47706.rs new file mode 100644 index 000000000..f47c1e694 --- /dev/null +++ b/tests/ui/mismatched_types/issue-47706.rs @@ -0,0 +1,29 @@ +pub struct Foo { + foo: Option, +} + +impl Foo { + pub fn new(foo: Option, _: ()) -> Foo { + Foo { foo } + } + + pub fn map(self) -> Option { + self.foo.map(Foo::new) + } + //~^^ ERROR function is expected to take 1 argument, but it takes 2 arguments [E0593] +} + +enum Qux { + Bar(i32), +} + +fn foo(f: F) +where + F: Fn(), +{ +} + +fn main() { + foo(Qux::Bar); +} +//~^^ ERROR function is expected to take 0 arguments, but it takes 1 argument [E0593] diff --git a/tests/ui/mismatched_types/issue-47706.stderr b/tests/ui/mismatched_types/issue-47706.stderr new file mode 100644 index 000000000..d9d408844 --- /dev/null +++ b/tests/ui/mismatched_types/issue-47706.stderr @@ -0,0 +1,37 @@ +error[E0593]: function is expected to take 1 argument, but it takes 2 arguments + --> $DIR/issue-47706.rs:11:22 + | +LL | pub fn new(foo: Option, _: ()) -> Foo { + | ------------------------------------------ takes 2 arguments +... +LL | self.foo.map(Foo::new) + | --- ^^^^^^^^ expected function that takes 1 argument + | | + | required by a bound introduced by this call + | +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0593]: function is expected to take 0 arguments, but it takes 1 argument + --> $DIR/issue-47706.rs:27:9 + | +LL | Bar(i32), + | --- takes 1 argument +... +LL | foo(Qux::Bar); + | --- ^^^^^^^^ expected function that takes 0 arguments + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/issue-47706.rs:22:8 + | +LL | fn foo(f: F) + | --- required by a bound in this +LL | where +LL | F: Fn(), + | ^^^^ required by this bound in `foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/mismatched_types/issue-74918-missing-lifetime.rs b/tests/ui/mismatched_types/issue-74918-missing-lifetime.rs new file mode 100644 index 000000000..c7842667d --- /dev/null +++ b/tests/ui/mismatched_types/issue-74918-missing-lifetime.rs @@ -0,0 +1,29 @@ +// Regression test for issue #74918 +// Tests that we don't ICE after emitting an error + +struct ChunkingIterator> { + source: S, +} + +impl> Iterator for ChunkingIterator { + type Item = IteratorChunk; //~ ERROR missing lifetime + + fn next(&mut self) -> Option> { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + todo!() + } +} + +struct IteratorChunk<'a, T, S: Iterator> { + source: &'a mut S, +} + +impl> Iterator for IteratorChunk<'_, T, S> { + type Item = T; + + fn next(&mut self) -> Option { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr new file mode 100644 index 000000000..9ddea1629 --- /dev/null +++ b/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr @@ -0,0 +1,28 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-74918-missing-lifetime.rs:9:30 + | +LL | type Item = IteratorChunk; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type Item<'a> = IteratorChunk<'a, T, S>; + | ++++ +++ + +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/issue-74918-missing-lifetime.rs:11:5 + | +LL | fn next(&mut self) -> Option> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator) -> Option>` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | + = note: expected `fn(&'1 mut ChunkingIterator) -> Option>` + | + = note: expected signature `fn(&'1 mut ChunkingIterator) -> Option>` + found signature `fn(&'1 mut ChunkingIterator) -> Option>` + = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/mismatched_types/issue-75361-mismatched-impl.rs b/tests/ui/mismatched_types/issue-75361-mismatched-impl.rs new file mode 100644 index 000000000..441051447 --- /dev/null +++ b/tests/ui/mismatched_types/issue-75361-mismatched-impl.rs @@ -0,0 +1,24 @@ +// Regresison test for issue #75361 +// Tests that we don't ICE on mismatched types with inference variables + + +trait MyTrait { + type Item; +} + +pub trait Graph { + type EdgeType; + + fn adjacent_edges(&self) -> Box>; +} + +impl Graph for T { + type EdgeType = T; + + fn adjacent_edges(&self) -> Box + '_> { //~ ERROR `impl` + panic!() + } + +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr new file mode 100644 index 000000000..88416ba4b --- /dev/null +++ b/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -0,0 +1,19 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/issue-75361-mismatched-impl.rs:18:3 + | +LL | fn adjacent_edges(&self) -> Box>; + | --------------------------------------------------------------------- expected `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` +... +LL | fn adjacent_edges(&self) -> Box + '_> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` + | + = note: expected signature `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` + found signature `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/issue-75361-mismatched-impl.rs:12:55 + | +LL | fn adjacent_edges(&self) -> Box>; + | ^^^^ consider borrowing this type parameter in the trait + +error: aborting due to previous error + diff --git a/tests/ui/mismatched_types/issue-84976.rs b/tests/ui/mismatched_types/issue-84976.rs new file mode 100644 index 000000000..db6fe0b45 --- /dev/null +++ b/tests/ui/mismatched_types/issue-84976.rs @@ -0,0 +1,25 @@ +/* Checks whether primitive type names are formatted correctly in the + * error messages about mismatched types (#84976). + */ + +fn foo(length: &u32) -> i32 { + 0 +} + +fn bar(length: &f32) -> f64 { + 0.0 +} + +fn main() { + let mut length = 0; + length = { foo(&length) }; + //~^ ERROR mismatched types [E0308] + length = foo(&length); + //~^ ERROR mismatched types [E0308] + + let mut float_length = 0.0; + float_length = { bar(&float_length) }; + //~^ ERROR mismatched types [E0308] + float_length = bar(&float_length); + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/mismatched_types/issue-84976.stderr b/tests/ui/mismatched_types/issue-84976.stderr new file mode 100644 index 000000000..9157566e3 --- /dev/null +++ b/tests/ui/mismatched_types/issue-84976.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/issue-84976.rs:15:16 + | +LL | length = { foo(&length) }; + | ^^^^^^^^^^^^ expected `u32`, found `i32` + | +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | length = { foo(&length).try_into().unwrap() }; + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-84976.rs:17:14 + | +LL | let mut length = 0; + | - expected due to this value +... +LL | length = foo(&length); + | ^^^^^^^^^^^^ expected `u32`, found `i32` + +error[E0308]: mismatched types + --> $DIR/issue-84976.rs:21:22 + | +LL | float_length = { bar(&float_length) }; + | ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64` + +error[E0308]: mismatched types + --> $DIR/issue-84976.rs:23:20 + | +LL | let mut float_length = 0.0; + | --- expected due to this value +... +LL | float_length = bar(&float_length); + | ^^^^^^^^^^^^^^^^^^ expected `f32`, found `f64` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/main.rs b/tests/ui/mismatched_types/main.rs new file mode 100644 index 000000000..e2d09dc21 --- /dev/null +++ b/tests/ui/mismatched_types/main.rs @@ -0,0 +1,4 @@ +fn main() { + let x: u32 = ( //~ ERROR mismatched types + ); +} diff --git a/tests/ui/mismatched_types/main.stderr b/tests/ui/mismatched_types/main.stderr new file mode 100644 index 000000000..a662741af --- /dev/null +++ b/tests/ui/mismatched_types/main.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/main.rs:2:18 + | +LL | let x: u32 = ( + | ____________---___^ + | | | + | | expected due to this +LL | | ); + | |_____^ expected `u32`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/method-help-unsatisfied-bound.rs b/tests/ui/mismatched_types/method-help-unsatisfied-bound.rs new file mode 100644 index 000000000..6303c6e6a --- /dev/null +++ b/tests/ui/mismatched_types/method-help-unsatisfied-bound.rs @@ -0,0 +1,7 @@ +struct Foo; + +fn main() { + let a: Result<(), Foo> = Ok(()); + a.unwrap(); + //~^ ERROR `Foo` doesn't implement `Debug` +} diff --git a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr new file mode 100644 index 000000000..d3b752507 --- /dev/null +++ b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Foo` doesn't implement `Debug` + --> $DIR/method-help-unsatisfied-bound.rs:5:7 + | +LL | a.unwrap(); + | ^^^^^^ `Foo` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `Foo` + = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` +note: required by a bound in `Result::::unwrap` + --> $SRC_DIR/core/src/result.rs:LL:COL +help: consider annotating `Foo` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.rs b/tests/ui/mismatched_types/non_zero_assigned_something.rs new file mode 100644 index 000000000..d2adbe01c --- /dev/null +++ b/tests/ui/mismatched_types/non_zero_assigned_something.rs @@ -0,0 +1,9 @@ +fn main() { + let _: std::num::NonZeroU64 = 1; + //~^ ERROR mismatched types + //~| HELP consider calling `NonZeroU64::new` + + let _: Option = 1; + //~^ ERROR mismatched types + //~| HELP consider calling `NonZeroU64::new` +} diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.stderr b/tests/ui/mismatched_types/non_zero_assigned_something.stderr new file mode 100644 index 000000000..d4b2c902f --- /dev/null +++ b/tests/ui/mismatched_types/non_zero_assigned_something.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/non_zero_assigned_something.rs:2:35 + | +LL | let _: std::num::NonZeroU64 = 1; + | -------------------- ^ expected struct `NonZeroU64`, found integer + | | + | expected due to this + | +help: consider calling `NonZeroU64::new` + | +LL | let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap(); + | ++++++++++++++++ ++++++++++ + +error[E0308]: mismatched types + --> $DIR/non_zero_assigned_something.rs:6:43 + | +LL | let _: Option = 1; + | ---------------------------- ^ expected enum `Option`, found integer + | | + | expected due to this + | + = note: expected enum `Option` + found type `{integer}` +help: consider calling `NonZeroU64::new` + | +LL | let _: Option = NonZeroU64::new(1); + | ++++++++++++++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/normalize-fn-sig.rs b/tests/ui/mismatched_types/normalize-fn-sig.rs new file mode 100644 index 000000000..1a2093c44 --- /dev/null +++ b/tests/ui/mismatched_types/normalize-fn-sig.rs @@ -0,0 +1,16 @@ +trait Foo { + type Bar; +} + +impl Foo for T { + type Bar = i32; +} + +fn foo(_: ::Bar, _: &'static ::Bar) {} + +fn needs_i32_ref_fn(_: fn(&'static i32, i32)) {} + +fn main() { + needs_i32_ref_fn(foo::<()>); + //~^ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/normalize-fn-sig.stderr b/tests/ui/mismatched_types/normalize-fn-sig.stderr new file mode 100644 index 000000000..6c55f29c5 --- /dev/null +++ b/tests/ui/mismatched_types/normalize-fn-sig.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/normalize-fn-sig.rs:14:22 + | +LL | needs_i32_ref_fn(foo::<()>); + | ---------------- ^^^^^^^^^ expected `&i32`, found `i32` + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `fn(&'static i32, i32)` + found fn item `fn(i32, &'static i32) {foo::<()>}` +note: function defined here + --> $DIR/normalize-fn-sig.rs:11:4 + | +LL | fn needs_i32_ref_fn(_: fn(&'static i32, i32)) {} + | ^^^^^^^^^^^^^^^^ ------------------------ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/numeric-literal-cast.rs b/tests/ui/mismatched_types/numeric-literal-cast.rs new file mode 100644 index 000000000..69cfe262f --- /dev/null +++ b/tests/ui/mismatched_types/numeric-literal-cast.rs @@ -0,0 +1,12 @@ +fn foo(_: u16) {} +fn foo1(_: f64) {} +fn foo2(_: i32) {} + +fn main() { + foo(1u8); +//~^ ERROR mismatched types + foo1(2f32); +//~^ ERROR mismatched types + foo2(3i16); +//~^ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/numeric-literal-cast.stderr b/tests/ui/mismatched_types/numeric-literal-cast.stderr new file mode 100644 index 000000000..fcf3eccbc --- /dev/null +++ b/tests/ui/mismatched_types/numeric-literal-cast.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:6:9 + | +LL | foo(1u8); + | --- ^^^ expected `u16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-literal-cast.rs:1:4 + | +LL | fn foo(_: u16) {} + | ^^^ ------ +help: change the type of the numeric literal from `u8` to `u16` + | +LL | foo(1u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:8:10 + | +LL | foo1(2f32); + | ---- ^^^^ expected `f64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-literal-cast.rs:2:4 + | +LL | fn foo1(_: f64) {} + | ^^^^ ------ +help: change the type of the numeric literal from `f32` to `f64` + | +LL | foo1(2f64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-literal-cast.rs:10:10 + | +LL | foo2(3i16); + | ---- ^^^^ expected `i32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-literal-cast.rs:3:4 + | +LL | fn foo2(_: i32) {} + | ^^^^ ------ +help: change the type of the numeric literal from `i16` to `i32` + | +LL | foo2(3i32); + | ~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.rs b/tests/ui/mismatched_types/overloaded-calls-bad.rs new file mode 100644 index 000000000..5b1804d82 --- /dev/null +++ b/tests/ui/mismatched_types/overloaded-calls-bad.rs @@ -0,0 +1,42 @@ +#![feature(fn_traits, unboxed_closures)] + +use std::ops::FnMut; + +struct S { + x: isize, + y: isize, +} + +impl FnMut<(isize,)> for S { + extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize { + self.x * self.y * z + } +} + +impl FnOnce<(isize,)> for S { + type Output = isize; + extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize { + self.call_mut((z,)) + } +} + +struct F; + +impl FnOnce<(i32,)> for F { + type Output = (); + + extern "rust-call" fn call_once(self, args: (i32,)) -> Self::Output {} +} + +fn main() { + let mut s = S { x: 3, y: 3 }; + let ans = s("what"); + //~^ ERROR mismatched types + let ans = s(); + //~^ ERROR function takes 1 argument but 0 arguments were supplied + let ans = s("burma", "shave"); + //~^ ERROR function takes 1 argument but 2 arguments were supplied + + F(""); + //~^ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr new file mode 100644 index 000000000..3a895acbd --- /dev/null +++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr @@ -0,0 +1,66 @@ +error[E0308]: mismatched types + --> $DIR/overloaded-calls-bad.rs:33:17 + | +LL | let ans = s("what"); + | - ^^^^^^ expected `isize`, found `&str` + | | + | arguments to this function are incorrect + | +note: implementation defined here + --> $DIR/overloaded-calls-bad.rs:10:1 + | +LL | impl FnMut<(isize,)> for S { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0057]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/overloaded-calls-bad.rs:35:15 + | +LL | let ans = s(); + | ^-- an argument of type `isize` is missing + | +note: implementation defined here + --> $DIR/overloaded-calls-bad.rs:10:1 + | +LL | impl FnMut<(isize,)> for S { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: provide the argument + | +LL | let ans = s(/* isize */); + | ~~~~~~~~~~~~~ + +error[E0057]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/overloaded-calls-bad.rs:37:15 + | +LL | let ans = s("burma", "shave"); + | ^ ------- ------- argument of type `&'static str` unexpected + | | + | expected `isize`, found `&str` + | +note: implementation defined here + --> $DIR/overloaded-calls-bad.rs:10:1 + | +LL | impl FnMut<(isize,)> for S { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove the extra argument + | +LL | let ans = s(/* isize */); + | ~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/overloaded-calls-bad.rs:40:7 + | +LL | F(""); + | - ^^ expected `i32`, found `&str` + | | + | arguments to this struct are incorrect + | +note: implementation defined here + --> $DIR/overloaded-calls-bad.rs:25:1 + | +LL | impl FnOnce<(i32,)> for F { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0057, E0308. +For more information about an error, try `rustc --explain E0057`. diff --git a/tests/ui/mismatched_types/recovered-block.rs b/tests/ui/mismatched_types/recovered-block.rs new file mode 100644 index 000000000..b230b47d3 --- /dev/null +++ b/tests/ui/mismatched_types/recovered-block.rs @@ -0,0 +1,21 @@ +use std::env; + +pub struct Foo { + text: String +} + +pub fn foo() -> Foo { + let args: Vec = env::args().collect(); + let text = args[1].clone(); + + pub Foo { text } +} +//~^^ ERROR missing `struct` for struct definition + +pub fn bar() -> Foo { + fn + Foo { text: "".to_string() } +} +//~^^ ERROR expected one of `(` or `<`, found `{` + +fn main() {} diff --git a/tests/ui/mismatched_types/recovered-block.stderr b/tests/ui/mismatched_types/recovered-block.stderr new file mode 100644 index 000000000..f275321ab --- /dev/null +++ b/tests/ui/mismatched_types/recovered-block.stderr @@ -0,0 +1,19 @@ +error: missing `struct` for struct definition + --> $DIR/recovered-block.rs:11:8 + | +LL | pub Foo { text } + | ^ + | +help: add `struct` here to parse `Foo` as a public struct + | +LL | pub struct Foo { text } + | ++++++ + +error: expected one of `(` or `<`, found `{` + --> $DIR/recovered-block.rs:17:9 + | +LL | Foo { text: "".to_string() } + | ^ expected one of `(` or `<` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/mismatched_types/ref-pat-suggestions.fixed b/tests/ui/mismatched_types/ref-pat-suggestions.fixed new file mode 100644 index 000000000..d50acd1ac --- /dev/null +++ b/tests/ui/mismatched_types/ref-pat-suggestions.fixed @@ -0,0 +1,37 @@ +// run-rustfix + +fn _f0(_a: &u32) {} //~ ERROR mismatched types +fn _f1(_a: &mut u32) {} //~ ERROR mismatched types +fn _f2(&_a: &u32) {} //~ ERROR mismatched types +fn _f3(&mut _a: &mut u32) {} //~ ERROR mismatched types +fn _f4(&_a: &u32) {} //~ ERROR mismatched types +fn _f5(&mut _a: &mut u32) {} //~ ERROR mismatched types + +fn main() { + let _: fn(u32) = |_a| (); //~ ERROR mismatched types + let _: fn(u32) = |_a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut _a| (); //~ ERROR mismatched types + + let _ = |_a: &u32| (); //~ ERROR mismatched types + let _ = |_a: &mut u32| (); //~ ERROR mismatched types + let _ = |&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types + let _ = |&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types + + #[allow(unused_mut)] + { + struct S(u8); + + let mut _a = 0; //~ ERROR mismatched types + let S(_b) = S(0); //~ ERROR mismatched types + let (_c,) = (0,); //~ ERROR mismatched types + + match 0 { + _d => {} //~ ERROR mismatched types + } + } +} diff --git a/tests/ui/mismatched_types/ref-pat-suggestions.rs b/tests/ui/mismatched_types/ref-pat-suggestions.rs new file mode 100644 index 000000000..1a77f6876 --- /dev/null +++ b/tests/ui/mismatched_types/ref-pat-suggestions.rs @@ -0,0 +1,37 @@ +// run-rustfix + +fn _f0(&_a: u32) {} //~ ERROR mismatched types +fn _f1(&mut _a: u32) {} //~ ERROR mismatched types +fn _f2(&&_a: &u32) {} //~ ERROR mismatched types +fn _f3(&mut &_a: &mut u32) {} //~ ERROR mismatched types +fn _f4(&&mut _a: &u32) {} //~ ERROR mismatched types +fn _f5(&mut &mut _a: &mut u32) {} //~ ERROR mismatched types + +fn main() { + let _: fn(u32) = |&_a| (); //~ ERROR mismatched types + let _: fn(u32) = |&mut _a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&&_a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &_a| (); //~ ERROR mismatched types + let _: fn(&u32) = |&&mut _a| (); //~ ERROR mismatched types + let _: fn(&mut u32) = |&mut &mut _a| (); //~ ERROR mismatched types + + let _ = |&_a: u32| (); //~ ERROR mismatched types + let _ = |&mut _a: u32| (); //~ ERROR mismatched types + let _ = |&&_a: &u32| (); //~ ERROR mismatched types + let _ = |&mut &_a: &mut u32| (); //~ ERROR mismatched types + let _ = |&&mut _a: &u32| (); //~ ERROR mismatched types + let _ = |&mut &mut _a: &mut u32| (); //~ ERROR mismatched types + + #[allow(unused_mut)] + { + struct S(u8); + + let &mut _a = 0; //~ ERROR mismatched types + let S(&mut _b) = S(0); //~ ERROR mismatched types + let (&mut _c,) = (0,); //~ ERROR mismatched types + + match 0 { + &mut _d => {} //~ ERROR mismatched types + } + } +} diff --git a/tests/ui/mismatched_types/ref-pat-suggestions.stderr b/tests/ui/mismatched_types/ref-pat-suggestions.stderr new file mode 100644 index 000000000..63eaa3930 --- /dev/null +++ b/tests/ui/mismatched_types/ref-pat-suggestions.stderr @@ -0,0 +1,386 @@ +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:3:8 + | +LL | fn _f0(&_a: u32) {} + | ^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: to take parameter `_a` by reference, move `&` to the type + | +LL - fn _f0(&_a: u32) {} +LL + fn _f0(_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:4:8 + | +LL | fn _f1(&mut _a: u32) {} + | ^^^^^^^ --- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +note: to declare a mutable parameter use: `mut _a` + --> $DIR/ref-pat-suggestions.rs:4:8 + | +LL | fn _f1(&mut _a: u32) {} + | ^^^^^^^ +help: to take parameter `_a` by reference, move `&mut` to the type + | +LL - fn _f1(&mut _a: u32) {} +LL + fn _f1(_a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:5:9 + | +LL | fn _f2(&&_a: &u32) {} + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn _f2(&&_a: &u32) {} +LL + fn _f2(&_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:6:13 + | +LL | fn _f3(&mut &_a: &mut u32) {} + | ^^^ -------- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - fn _f3(&mut &_a: &mut u32) {} +LL + fn _f3(&mut _a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:7:9 + | +LL | fn _f4(&&mut _a: &u32) {} + | ^^^^^^^ ---- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - fn _f4(&&mut _a: &u32) {} +LL + fn _f4(&_a: &u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:8:13 + | +LL | fn _f5(&mut &mut _a: &mut u32) {} + | ^^^^^^^ -------- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - fn _f5(&mut &mut _a: &mut u32) {} +LL + fn _f5(&mut _a: &mut u32) {} + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:11:23 + | +LL | let _: fn(u32) = |&_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(u32) = |&_a| (); +LL + let _: fn(u32) = |_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:12:23 + | +LL | let _: fn(u32) = |&mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +note: to declare a mutable parameter use: `mut _a` + --> $DIR/ref-pat-suggestions.rs:12:23 + | +LL | let _: fn(u32) = |&mut _a| (); + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let _: fn(u32) = |&mut _a| (); +LL + let _: fn(u32) = |_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:13:25 + | +LL | let _: fn(&u32) = |&&_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(&u32) = |&&_a| (); +LL + let _: fn(&u32) = |&_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:14:33 + | +LL | let _: fn(&mut u32) = |&mut &_a| (); + | ^-- + | || + | |expected due to this + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _: fn(&mut u32) = |&mut &_a| (); +LL + let _: fn(&mut u32) = |&mut _a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:15:25 + | +LL | let _: fn(&u32) = |&&mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(&u32) = |&&mut _a| (); +LL + let _: fn(&u32) = |&_a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:16:33 + | +LL | let _: fn(&mut u32) = |&mut &mut _a| (); + | ^^^^^-- + | | | + | | expected due to this + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _: fn(&mut u32) = |&mut &mut _a| (); +LL + let _: fn(&mut u32) = |&mut _a| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:18:14 + | +LL | let _ = |&_a: u32| (); + | ^^^ --- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: to take parameter `_a` by reference, move `&` to the type + | +LL - let _ = |&_a: u32| (); +LL + let _ = |_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:19:14 + | +LL | let _ = |&mut _a: u32| (); + | ^^^^^^^ --- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +note: to declare a mutable parameter use: `mut _a` + --> $DIR/ref-pat-suggestions.rs:19:14 + | +LL | let _ = |&mut _a: u32| (); + | ^^^^^^^ +help: to take parameter `_a` by reference, move `&mut` to the type + | +LL - let _ = |&mut _a: u32| (); +LL + let _ = |_a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:20:15 + | +LL | let _ = |&&_a: &u32| (); + | ^^^ ---- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _ = |&&_a: &u32| (); +LL + let _ = |&_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:21:19 + | +LL | let _ = |&mut &_a: &mut u32| (); + | ^^^ -------- expected due to this + | | + | expected `u32`, found reference + | + = note: expected type `u32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let _ = |&mut &_a: &mut u32| (); +LL + let _ = |&mut _a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:22:15 + | +LL | let _ = |&&mut _a: &u32| (); + | ^^^^^^^ ---- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _ = |&&mut _a: &u32| (); +LL + let _ = |&_a: &u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:23:19 + | +LL | let _ = |&mut &mut _a: &mut u32| (); + | ^^^^^^^ -------- expected due to this + | | + | expected `u32`, found `&mut _` + | + = note: expected type `u32` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let _ = |&mut &mut _a: &mut u32| (); +LL + let _ = |&mut _a: &mut u32| (); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:29:13 + | +LL | let &mut _a = 0; + | ^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `&mut _` + | help: to declare a mutable variable use: `mut _a` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:30:15 + | +LL | let S(&mut _b) = S(0); + | ^^^^^^^ ---- this expression has type `S` + | | + | expected `u8`, found `&mut _` + | + = note: expected type `u8` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut _b` + --> $DIR/ref-pat-suggestions.rs:30:15 + | +LL | let S(&mut _b) = S(0); + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL | let S(_b) = S(0); + | ~~ + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:31:14 + | +LL | let (&mut _c,) = (0,); + | ^^^^^^^ ---- this expression has type `({integer},)` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut _c` + --> $DIR/ref-pat-suggestions.rs:31:14 + | +LL | let (&mut _c,) = (0,); + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let (&mut _c,) = (0,); +LL + let (_c,) = (0,); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:34:13 + | +LL | match 0 { + | - this expression has type `{integer}` +LL | &mut _d => {} + | ^^^^^^^ expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut _d` + --> $DIR/ref-pat-suggestions.rs:34:13 + | +LL | &mut _d => {} + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - &mut _d => {} +LL + _d => {} + | + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/show_module.rs b/tests/ui/mismatched_types/show_module.rs new file mode 100644 index 000000000..61550b887 --- /dev/null +++ b/tests/ui/mismatched_types/show_module.rs @@ -0,0 +1,18 @@ +pub mod blah { + pub mod baz { + pub struct Foo; + } +} + +pub mod meh { + pub struct Foo; +} + +pub type Foo = blah::baz::Foo; + +fn foo() -> Foo { + meh::Foo + //~^ ERROR mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/mismatched_types/show_module.stderr b/tests/ui/mismatched_types/show_module.stderr new file mode 100644 index 000000000..5e48e0955 --- /dev/null +++ b/tests/ui/mismatched_types/show_module.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/show_module.rs:14:5 + | +LL | fn foo() -> Foo { + | --- expected `baz::Foo` because of return type +LL | meh::Foo + | ^^^^^^^^ expected struct `baz::Foo`, found struct `meh::Foo` + | + = note: struct `meh::Foo` and struct `baz::Foo` have similar names, but are actually distinct types +note: struct `meh::Foo` is defined in module `crate::meh` of the current crate + --> $DIR/show_module.rs:8:5 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ +note: struct `baz::Foo` is defined in module `crate::blah::baz` of the current crate + --> $DIR/show_module.rs:3:9 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/similar_paths.rs b/tests/ui/mismatched_types/similar_paths.rs new file mode 100644 index 000000000..4b9157f39 --- /dev/null +++ b/tests/ui/mismatched_types/similar_paths.rs @@ -0,0 +1,11 @@ +enum Option { + Some(T), + None, +} + +pub fn foo() -> Option { + Some(42_u8) + //~^ ERROR mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/mismatched_types/similar_paths.stderr b/tests/ui/mismatched_types/similar_paths.stderr new file mode 100644 index 000000000..46a383325 --- /dev/null +++ b/tests/ui/mismatched_types/similar_paths.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/similar_paths.rs:7:5 + | +LL | pub fn foo() -> Option { + | ---------- expected `Option` because of return type +LL | Some(42_u8) + | ^^^^^^^^^^^ expected enum `Option`, found enum `std::option::Option` + | + = note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types +note: enum `std::option::Option` is defined in crate `core` + --> $SRC_DIR/core/src/option.rs:LL:COL +note: enum `Option` is defined in the current crate + --> $DIR/similar_paths.rs:1:1 + | +LL | enum Option { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs new file mode 100644 index 000000000..8f5b7cce4 --- /dev/null +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -0,0 +1,10 @@ +#![allow(non_camel_case_types)] + +struct bool; + +fn foo(_: bool) {} + +fn main() { + foo(true); + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr new file mode 100644 index 000000000..8a2f73945 --- /dev/null +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/similar_paths_primitive.rs:8:9 + | +LL | foo(true); + | --- ^^^^ expected struct `bool`, found `bool` + | | + | arguments to this function are incorrect + | + = note: bool and struct `bool` have similar names, but are actually distinct types + = note: bool is a primitive defined by the language +note: struct `bool` is defined in the current crate + --> $DIR/similar_paths_primitive.rs:3:1 + | +LL | struct bool; + | ^^^^^^^^^^^ +note: function defined here + --> $DIR/similar_paths_primitive.rs:5:4 + | +LL | fn foo(_: bool) {} + | ^^^ ------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed new file mode 100644 index 000000000..56f93cfbf --- /dev/null +++ b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +fn main() { + enum Blah { + A(isize, isize, usize), + B(isize, usize), + } + + match Blah::A(1, 1, 2) { + Blah::A(_, x, ref y) | Blah::B(x, ref y) => {} + //~^ ERROR mismatched types + //~| ERROR variable `y` is bound inconsistently across alternatives separated by `|` + } + + match Blah::A(1, 1, 2) { + Blah::A(_, x, y) | Blah::B(x, y) => {} + //~^ ERROR mismatched types + //~| variable `y` is bound inconsistently across alternatives separated by `|` + } +} diff --git a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs new file mode 100644 index 000000000..0c33f99a4 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs @@ -0,0 +1,21 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +fn main() { + enum Blah { + A(isize, isize, usize), + B(isize, usize), + } + + match Blah::A(1, 1, 2) { + Blah::A(_, x, ref y) | Blah::B(x, y) => {} + //~^ ERROR mismatched types + //~| ERROR variable `y` is bound inconsistently across alternatives separated by `|` + } + + match Blah::A(1, 1, 2) { + Blah::A(_, x, y) | Blah::B(x, ref y) => {} + //~^ ERROR mismatched types + //~| variable `y` is bound inconsistently across alternatives separated by `|` + } +} diff --git a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.stderr b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.stderr new file mode 100644 index 000000000..e8357f9a3 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.stderr @@ -0,0 +1,49 @@ +error[E0409]: variable `y` is bound inconsistently across alternatives separated by `|` + --> $DIR/suggest-adding-or-removing-ref-for-binding-pattern.rs:11:43 + | +LL | Blah::A(_, x, ref y) | Blah::B(x, y) => {} + | - first binding ^ bound in different ways + +error[E0409]: variable `y` is bound inconsistently across alternatives separated by `|` + --> $DIR/suggest-adding-or-removing-ref-for-binding-pattern.rs:17:43 + | +LL | Blah::A(_, x, y) | Blah::B(x, ref y) => {} + | - first binding ^ bound in different ways + +error[E0308]: mismatched types + --> $DIR/suggest-adding-or-removing-ref-for-binding-pattern.rs:11:43 + | +LL | match Blah::A(1, 1, 2) { + | ---------------- this expression has type `Blah` +LL | Blah::A(_, x, ref y) | Blah::B(x, y) => {} + | ----- ^ expected `&usize`, found `usize` + | | + | first introduced with type `&usize` here + | + = note: in the same arm, a binding must have the same type in all alternatives +help: consider adding `ref` + | +LL | Blah::A(_, x, ref y) | Blah::B(x, ref y) => {} + | +++ + +error[E0308]: mismatched types + --> $DIR/suggest-adding-or-removing-ref-for-binding-pattern.rs:17:39 + | +LL | match Blah::A(1, 1, 2) { + | ---------------- this expression has type `Blah` +LL | Blah::A(_, x, y) | Blah::B(x, ref y) => {} + | - ^^^^^ expected `usize`, found `&usize` + | | + | first introduced with type `usize` here + | + = note: in the same arm, a binding must have the same type in all alternatives +help: consider removing `ref` + | +LL - Blah::A(_, x, y) | Blah::B(x, ref y) => {} +LL + Blah::A(_, x, y) | Blah::B(x, y) => {} + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed new file mode 100644 index 000000000..f30feaed0 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.fixed @@ -0,0 +1,28 @@ +// run-rustfix + +#![allow(dead_code)] + +struct S; +struct Y; + +trait Trait {} + +impl Trait for S {} +impl Trait for Y {} + +fn foo() -> Box { + if true { + Box::new(S) + } else { + Box::new(Y) //~ ERROR `if` and `else` have incompatible types + } +} + +fn bar() -> Box { + match true { + true => Box::new(S), + false => Box::new(Y), //~ ERROR `match` arms have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs new file mode 100644 index 000000000..2bd8146e2 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.rs @@ -0,0 +1,28 @@ +// run-rustfix + +#![allow(dead_code)] + +struct S; +struct Y; + +trait Trait {} + +impl Trait for S {} +impl Trait for Y {} + +fn foo() -> impl Trait { + if true { + S + } else { + Y //~ ERROR `if` and `else` have incompatible types + } +} + +fn bar() -> impl Trait { + match true { + true => S, + false => Y, //~ ERROR `match` arms have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr new file mode 100644 index 000000000..f58b9c3ec --- /dev/null +++ b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr @@ -0,0 +1,47 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/suggest-boxed-trait-objects-instead-of-impl-trait.rs:17:9 + | +LL | / if true { +LL | | S + | | - expected because of this +LL | | } else { +LL | | Y + | | ^ expected struct `S`, found struct `Y` +LL | | } + | |_____- `if` and `else` have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn foo() -> Box { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ Box::new(S) +LL | } else { +LL ~ Box::new(Y) + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/suggest-boxed-trait-objects-instead-of-impl-trait.rs:24:18 + | +LL | / match true { +LL | | true => S, + | | - this is found to be of type `S` +LL | | false => Y, + | | ^ expected struct `S`, found struct `Y` +LL | | } + | |_____- `match` arms have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn bar() -> Box { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ true => Box::new(S), +LL ~ false => Box::new(Y), + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed new file mode 100644 index 000000000..63b65ab20 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +macro_rules! my_wrapper { + ($expr:expr) => { MyWrapper($expr) } +} + +pub struct MyWrapper(u32); + +fn main() { + let value = MyWrapper(123); + some_fn(value); //~ ERROR mismatched types + some_fn(my_wrapper!(123)); //~ ERROR mismatched types +} + +fn some_fn(wrapped: MyWrapper) { + drop(wrapped); +} diff --git a/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.rs b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.rs new file mode 100644 index 000000000..2ab4e3955 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.rs @@ -0,0 +1,17 @@ +// run-rustfix + +macro_rules! my_wrapper { + ($expr:expr) => { MyWrapper($expr) } +} + +pub struct MyWrapper(u32); + +fn main() { + let value = MyWrapper(123); + some_fn(value.0); //~ ERROR mismatched types + some_fn(my_wrapper!(123).0); //~ ERROR mismatched types +} + +fn some_fn(wrapped: MyWrapper) { + drop(wrapped); +} diff --git a/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr new file mode 100644 index 000000000..35871afb5 --- /dev/null +++ b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched types + --> $DIR/suggest-removing-tuple-struct-field.rs:11:13 + | +LL | some_fn(value.0); + | ------- ^^^^^^^ expected struct `MyWrapper`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-removing-tuple-struct-field.rs:15:4 + | +LL | fn some_fn(wrapped: MyWrapper) { + | ^^^^^^^ ------------------ +help: consider removing the tuple struct field `0` + | +LL - some_fn(value.0); +LL + some_fn(value); + | + +error[E0308]: mismatched types + --> $DIR/suggest-removing-tuple-struct-field.rs:12:13 + | +LL | some_fn(my_wrapper!(123).0); + | ------- ^^^^^^^^^^^^^^^^^^ expected struct `MyWrapper`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-removing-tuple-struct-field.rs:15:4 + | +LL | fn some_fn(wrapped: MyWrapper) { + | ^^^^^^^ ------------------ +help: consider removing the tuple struct field `0` + | +LL - some_fn(my_wrapper!(123).0); +LL + some_fn(my_wrapper!(123)); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/trait-bounds-cant-coerce.rs b/tests/ui/mismatched_types/trait-bounds-cant-coerce.rs new file mode 100644 index 000000000..882533992 --- /dev/null +++ b/tests/ui/mismatched_types/trait-bounds-cant-coerce.rs @@ -0,0 +1,16 @@ +trait Foo { + fn dummy(&self) { } +} + +fn a(_x: Box) { +} + +fn c(x: Box) { + a(x); +} + +fn d(x: Box) { + a(x); //~ ERROR mismatched types [E0308] +} + +fn main() { } diff --git a/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr new file mode 100644 index 000000000..80aef7fcb --- /dev/null +++ b/tests/ui/mismatched_types/trait-bounds-cant-coerce.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/trait-bounds-cant-coerce.rs:13:7 + | +LL | a(x); + | - ^ expected trait `Foo + Send`, found trait `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box<(dyn Foo + Send + 'static)>` + found struct `Box<(dyn Foo + 'static)>` +note: function defined here + --> $DIR/trait-bounds-cant-coerce.rs:5:4 + | +LL | fn a(_x: Box) { + | ^ ----------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/trait-impl-fn-incompatibility.rs b/tests/ui/mismatched_types/trait-impl-fn-incompatibility.rs new file mode 100644 index 000000000..ba206b860 --- /dev/null +++ b/tests/ui/mismatched_types/trait-impl-fn-incompatibility.rs @@ -0,0 +1,14 @@ +trait Foo { + fn foo(x: u16); + fn bar(&mut self, bar: &mut Bar); +} + +struct Bar; + +impl Foo for Bar { + fn foo(x: i16) { } //~ ERROR incompatible type + fn bar(&mut self, bar: &Bar) { } //~ ERROR incompatible type +} + +fn main() { +} diff --git a/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr new file mode 100644 index 000000000..6e7bf5eb4 --- /dev/null +++ b/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -0,0 +1,37 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/trait-impl-fn-incompatibility.rs:9:15 + | +LL | fn foo(x: i16) { } + | ^^^ + | | + | expected `u16`, found `i16` + | help: change the parameter type to match the trait: `u16` + | +note: type in trait + --> $DIR/trait-impl-fn-incompatibility.rs:2:15 + | +LL | fn foo(x: u16); + | ^^^ + = note: expected signature `fn(u16)` + found signature `fn(i16)` + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/trait-impl-fn-incompatibility.rs:10:28 + | +LL | fn bar(&mut self, bar: &Bar) { } + | ^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `&mut Bar` + | +note: type in trait + --> $DIR/trait-impl-fn-incompatibility.rs:3:28 + | +LL | fn bar(&mut self, bar: &mut Bar); + | ^^^^^^^^ + = note: expected signature `fn(&mut Bar, &mut Bar)` + found signature `fn(&mut Bar, &Bar)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs new file mode 100644 index 000000000..307104e47 --- /dev/null +++ b/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs @@ -0,0 +1,22 @@ +#![feature(unboxed_closures,tuple_trait)] + +use std::ops::FnMut; + +fn to_fn_mut>(f: F) -> F { f } + +fn call_it isize>(y: isize, mut f: F) -> isize { + //~^ NOTE required by this bound in `call_it` + //~| NOTE required by a bound in `call_it` + f(2, y) +} + +pub fn main() { + let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); + //~^ NOTE found signature defined here + let z = call_it(3, f); + //~^ ERROR type mismatch + //~| NOTE expected due to this + //~| NOTE expected closure signature `fn(isize, _) -> _` + //~| NOTE required by a bound introduced by this call + println!("{}", z); +} diff --git a/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr new file mode 100644 index 000000000..54b220065 --- /dev/null +++ b/tests/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/unboxed-closures-vtable-mismatch.rs:16:24 + | +LL | let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y }); + | ----------------------------- found signature defined here +LL | +LL | let z = call_it(3, f); + | ------- ^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected closure signature `fn(isize, _) -> _` + found closure signature `fn(usize, _) -> _` +note: required by a bound in `call_it` + --> $DIR/unboxed-closures-vtable-mismatch.rs:7:15 + | +LL | fn call_it isize>(y: isize, mut f: F) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/mismatched_types/wrap-suggestion-privacy.rs b/tests/ui/mismatched_types/wrap-suggestion-privacy.rs new file mode 100644 index 000000000..63cb1a129 --- /dev/null +++ b/tests/ui/mismatched_types/wrap-suggestion-privacy.rs @@ -0,0 +1,24 @@ +mod inner { + pub struct Wrapper(T); +} + +fn needs_wrapper(t: inner::Wrapper) {} +fn needs_wrapping(t: std::num::Wrapping) {} +fn needs_ready(t: std::future::Ready) {} + +fn main() { + // Suggest wrapping expression because type is local + // and its privacy can be easily changed + needs_wrapper(0); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `inner::Wrapper` + + // Suggest wrapping expression because field is accessible + needs_wrapping(0); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `std::num::Wrapping` + + // Do not suggest wrapping expression + needs_ready(Some(0)); + //~^ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr b/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr new file mode 100644 index 000000000..fdd92cbfc --- /dev/null +++ b/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/wrap-suggestion-privacy.rs:12:19 + | +LL | needs_wrapper(0); + | ------------- ^ expected struct `Wrapper`, found integer + | | + | arguments to this function are incorrect + | + = note: expected struct `Wrapper` + found type `{integer}` +note: function defined here + --> $DIR/wrap-suggestion-privacy.rs:5:4 + | +LL | fn needs_wrapper(t: inner::Wrapper) {} + | ^^^^^^^^^^^^^ ---------------------- +help: try wrapping the expression in `inner::Wrapper` (its field is private, but it's local to this crate and its privacy can be changed) + | +LL | needs_wrapper(inner::Wrapper(0)); + | +++++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-suggestion-privacy.rs:17:20 + | +LL | needs_wrapping(0); + | -------------- ^ expected struct `Wrapping`, found integer + | | + | arguments to this function are incorrect + | + = note: expected struct `Wrapping` + found type `{integer}` +note: function defined here + --> $DIR/wrap-suggestion-privacy.rs:6:4 + | +LL | fn needs_wrapping(t: std::num::Wrapping) {} + | ^^^^^^^^^^^^^^ -------------------------- +help: try wrapping the expression in `std::num::Wrapping` + | +LL | needs_wrapping(std::num::Wrapping(0)); + | +++++++++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-suggestion-privacy.rs:22:17 + | +LL | needs_ready(Some(0)); + | ----------- ^^^^^^^ expected struct `Ready`, found enum `Option` + | | + | arguments to this function are incorrect + | + = note: expected struct `std::future::Ready` + found enum `Option<{integer}>` +note: function defined here + --> $DIR/wrap-suggestion-privacy.rs:7:4 + | +LL | fn needs_ready(t: std::future::Ready) {} + | ^^^^^^^^^^^ -------------------------- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/missing-trait-bounds/auxiliary/issue-69725.rs b/tests/ui/missing-trait-bounds/auxiliary/issue-69725.rs new file mode 100644 index 000000000..13606e498 --- /dev/null +++ b/tests/ui/missing-trait-bounds/auxiliary/issue-69725.rs @@ -0,0 +1,8 @@ +#[derive(Clone)] +pub struct Struct(A); + +impl Struct { + pub fn new() -> Self { + todo!() + } +} diff --git a/tests/ui/missing-trait-bounds/issue-35677.fixed b/tests/ui/missing-trait-bounds/issue-35677.fixed new file mode 100644 index 000000000..08174d8d8 --- /dev/null +++ b/tests/ui/missing-trait-bounds/issue-35677.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] +use std::collections::HashSet; +use std::hash::Hash; + +fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { + this.is_subset(other) + //~^ ERROR the method +} + +fn main() {} diff --git a/tests/ui/missing-trait-bounds/issue-35677.rs b/tests/ui/missing-trait-bounds/issue-35677.rs new file mode 100644 index 000000000..2cb394386 --- /dev/null +++ b/tests/ui/missing-trait-bounds/issue-35677.rs @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] +use std::collections::HashSet; +use std::hash::Hash; + +fn is_subset(this: &HashSet, other: &HashSet) -> bool { + this.is_subset(other) + //~^ ERROR the method +} + +fn main() {} diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr new file mode 100644 index 000000000..05d3de80d --- /dev/null +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -0,0 +1,19 @@ +error[E0599]: the method `is_subset` exists for reference `&HashSet`, but its trait bounds were not satisfied + --> $DIR/issue-35677.rs:7:10 + | +LL | this.is_subset(other) + | ^^^^^^^^^ method cannot be called on `&HashSet` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Eq` + `T: PartialEq` + which is required by `T: Eq` + `T: Hash` +help: consider restricting the type parameters to satisfy the trait bounds + | +LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/missing-trait-bounds/issue-69725.fixed b/tests/ui/missing-trait-bounds/issue-69725.fixed new file mode 100644 index 000000000..d57badcfd --- /dev/null +++ b/tests/ui/missing-trait-bounds/issue-69725.fixed @@ -0,0 +1,13 @@ +// run-rustfix +// aux-build:issue-69725.rs +#![allow(dead_code)] + +extern crate issue_69725; +use issue_69725::Struct; + +fn crash() where A: Clone { + let _ = Struct::::new().clone(); + //~^ ERROR: the method +} + +fn main() {} diff --git a/tests/ui/missing-trait-bounds/issue-69725.rs b/tests/ui/missing-trait-bounds/issue-69725.rs new file mode 100644 index 000000000..9c88969c5 --- /dev/null +++ b/tests/ui/missing-trait-bounds/issue-69725.rs @@ -0,0 +1,13 @@ +// run-rustfix +// aux-build:issue-69725.rs +#![allow(dead_code)] + +extern crate issue_69725; +use issue_69725::Struct; + +fn crash() { + let _ = Struct::::new().clone(); + //~^ ERROR: the method +} + +fn main() {} diff --git a/tests/ui/missing-trait-bounds/issue-69725.stderr b/tests/ui/missing-trait-bounds/issue-69725.stderr new file mode 100644 index 000000000..980d9dd16 --- /dev/null +++ b/tests/ui/missing-trait-bounds/issue-69725.stderr @@ -0,0 +1,22 @@ +error[E0599]: the method `clone` exists for struct `Struct`, but its trait bounds were not satisfied + --> $DIR/issue-69725.rs:9:32 + | +LL | let _ = Struct::::new().clone(); + | ^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds + | + ::: $DIR/auxiliary/issue-69725.rs:2:1 + | +LL | pub struct Struct(A); + | -------------------- doesn't satisfy `Struct: Clone` + | + = note: the following trait bounds were not satisfied: + `A: Clone` + which is required by `Struct: Clone` +help: consider restricting the type parameter to satisfy the trait bound + | +LL | fn crash() where A: Clone { + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.fixed b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.fixed new file mode 100644 index 000000000..6b24375e4 --- /dev/null +++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +pub fn foo(s: &[T], t: &[T]) { + let _ = s == t; //~ ERROR binary operation `==` cannot be applied to type `&[T]` +} + +fn main() {} diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.rs b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.rs new file mode 100644 index 000000000..df47be070 --- /dev/null +++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.rs @@ -0,0 +1,7 @@ +// run-rustfix + +pub fn foo(s: &[T], t: &[T]) { + let _ = s == t; //~ ERROR binary operation `==` cannot be applied to type `&[T]` +} + +fn main() {} diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr new file mode 100644 index 000000000..cde075501 --- /dev/null +++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr @@ -0,0 +1,16 @@ +error[E0369]: binary operation `==` cannot be applied to type `&[T]` + --> $DIR/missing-trait-bound-for-op.rs:4:15 + | +LL | let _ = s == t; + | - ^^ - &[T] + | | + | &[T] + | +help: consider restricting type parameter `T` + | +LL | pub fn foo(s: &[T], t: &[T]) { + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.rs b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.rs new file mode 100644 index 000000000..afd47f71c --- /dev/null +++ b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.rs @@ -0,0 +1,31 @@ +#[derive(Default, PartialEq)] +struct Foo { + bar: Box<[T]>, +} + +trait Bar { + fn foo(&self) {} +} + +impl Bar for Foo {} + +impl Foo { + fn bar(&self) { + self.foo(); + //~^ ERROR the method + } +} + +struct Fin where T: Bar { + bar: Box<[T]>, +} + +impl Bar for Fin {} + +impl Fin { + fn bar(&self) { + self.foo(); + //~^ ERROR the method + } +} +fn main() {} diff --git a/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr new file mode 100644 index 000000000..968e285af --- /dev/null +++ b/tests/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr @@ -0,0 +1,48 @@ +error[E0599]: the method `foo` exists for reference `&Foo`, but its trait bounds were not satisfied + --> $DIR/missing-trait-bounds-for-method-call.rs:14:14 + | +LL | struct Foo { + | ------------- doesn't satisfy `Foo: Bar` +... +LL | self.foo(); + | ^^^ method cannot be called on `&Foo` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `T: Bar` + `T: Default` + --> $DIR/missing-trait-bounds-for-method-call.rs:10:9 + | +LL | impl Bar for Foo {} + | ^^^^^^^ ^^^ --- ------ + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here +help: consider restricting the type parameters to satisfy the trait bounds + | +LL | struct Foo where T: Bar, T: Default { + | ++++++++++++++++++++++++ + +error[E0599]: the method `foo` exists for reference `&Fin`, but its trait bounds were not satisfied + --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 + | +LL | struct Fin where T: Bar { + | ------------- doesn't satisfy `Fin: Bar` +... +LL | self.foo(); + | ^^^ method cannot be called on `&Fin` due to unsatisfied trait bounds + | +note: trait bound `T: Default` was not satisfied + --> $DIR/missing-trait-bounds-for-method-call.rs:23:9 + | +LL | impl Bar for Fin {} + | ^^^^^^^ --- ------ + | | + | unsatisfied trait bound introduced here +help: consider restricting the type parameter to satisfy the trait bound + | +LL | struct Fin where T: Bar, T: Default { + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/missing/auxiliary/two_macros.rs b/tests/ui/missing/auxiliary/two_macros.rs new file mode 100644 index 000000000..2330c75c8 --- /dev/null +++ b/tests/ui/missing/auxiliary/two_macros.rs @@ -0,0 +1,5 @@ +#[macro_export] +macro_rules! macro_one { () => ("one") } + +#[macro_export] +macro_rules! macro_two { () => ("two") } diff --git a/tests/ui/missing/missing-allocator.rs b/tests/ui/missing/missing-allocator.rs new file mode 100644 index 000000000..2dc509f2c --- /dev/null +++ b/tests/ui/missing/missing-allocator.rs @@ -0,0 +1,18 @@ +// compile-flags: -C panic=abort +// no-prefer-dynamic + +#![no_std] +#![crate_type = "staticlib"] +#![feature(alloc_error_handler)] + +#[panic_handler] +fn panic(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[alloc_error_handler] +fn oom(_: core::alloc::Layout) -> ! { + loop {} +} + +extern crate alloc; diff --git a/tests/ui/missing/missing-allocator.stderr b/tests/ui/missing/missing-allocator.stderr new file mode 100644 index 000000000..0da5651c1 --- /dev/null +++ b/tests/ui/missing/missing-allocator.stderr @@ -0,0 +1,4 @@ +error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait + +error: aborting due to previous error + diff --git a/tests/ui/missing/missing-block-hint.rs b/tests/ui/missing/missing-block-hint.rs new file mode 100644 index 000000000..89db02a9c --- /dev/null +++ b/tests/ui/missing/missing-block-hint.rs @@ -0,0 +1,9 @@ +fn main() { + { + if (foo) => {} //~ ERROR expected `{`, found `=>` + } + { + if (foo) + bar; //~ ERROR expected `{`, found `bar` + } +} diff --git a/tests/ui/missing/missing-block-hint.stderr b/tests/ui/missing/missing-block-hint.stderr new file mode 100644 index 000000000..16954223a --- /dev/null +++ b/tests/ui/missing/missing-block-hint.stderr @@ -0,0 +1,30 @@ +error: expected `{`, found `=>` + --> $DIR/missing-block-hint.rs:3:18 + | +LL | if (foo) => {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/missing-block-hint.rs:3:12 + | +LL | if (foo) => {} + | ^^^^^ + +error: expected `{`, found `bar` + --> $DIR/missing-block-hint.rs:7:13 + | +LL | bar; + | ^^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/missing-block-hint.rs:6:12 + | +LL | if (foo) + | ^^^^^ +help: try placing this code inside a block + | +LL | { bar; } + | + + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/missing/missing-comma-in-match.fixed b/tests/ui/missing/missing-comma-in-match.fixed new file mode 100644 index 000000000..f091082f3 --- /dev/null +++ b/tests/ui/missing/missing-comma-in-match.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +fn main() { + match &Some(3) { + &None => 1, + &Some(2) => { 3 } + //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` + //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator + _ => 2 + }; +} diff --git a/tests/ui/missing/missing-comma-in-match.rs b/tests/ui/missing/missing-comma-in-match.rs new file mode 100644 index 000000000..54dab4e97 --- /dev/null +++ b/tests/ui/missing/missing-comma-in-match.rs @@ -0,0 +1,11 @@ +// run-rustfix + +fn main() { + match &Some(3) { + &None => 1 + &Some(2) => { 3 } + //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` + //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator + _ => 2 + }; +} diff --git a/tests/ui/missing/missing-comma-in-match.stderr b/tests/ui/missing/missing-comma-in-match.stderr new file mode 100644 index 000000000..fe210f697 --- /dev/null +++ b/tests/ui/missing/missing-comma-in-match.stderr @@ -0,0 +1,10 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` + --> $DIR/missing-comma-in-match.rs:6:18 + | +LL | &None => 1 + | - help: missing a comma here to end this `match` arm +LL | &Some(2) => { 3 } + | ^^ expected one of `,`, `.`, `?`, `}`, or an operator + +error: aborting due to previous error + diff --git a/tests/ui/missing/missing-derivable-attr.rs b/tests/ui/missing/missing-derivable-attr.rs new file mode 100644 index 000000000..58c94de50 --- /dev/null +++ b/tests/ui/missing/missing-derivable-attr.rs @@ -0,0 +1,16 @@ +trait MyEq { + fn eq(&self, other: &Self) -> bool; +} + +struct A { + x: isize +} + +impl MyEq for isize { + fn eq(&self, other: &isize) -> bool { *self == *other } +} + +impl MyEq for A {} //~ ERROR not all trait items implemented, missing: `eq` + +fn main() { +} diff --git a/tests/ui/missing/missing-derivable-attr.stderr b/tests/ui/missing/missing-derivable-attr.stderr new file mode 100644 index 000000000..9b8c0c583 --- /dev/null +++ b/tests/ui/missing/missing-derivable-attr.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `eq` + --> $DIR/missing-derivable-attr.rs:13:1 + | +LL | fn eq(&self, other: &Self) -> bool; + | ----------------------------------- `eq` from trait +... +LL | impl MyEq for A {} + | ^^^^^^^^^^^^^^^ missing `eq` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/missing/missing-fields-in-struct-pattern.rs b/tests/ui/missing/missing-fields-in-struct-pattern.rs new file mode 100644 index 000000000..40304a674 --- /dev/null +++ b/tests/ui/missing/missing-fields-in-struct-pattern.rs @@ -0,0 +1,8 @@ +struct S(usize, usize, usize, usize); + +fn main() { + if let S { a, b, c, d } = S(1, 2, 3, 4) { + //~^ ERROR tuple variant `S` written as struct variant + println!("hi"); + } +} diff --git a/tests/ui/missing/missing-fields-in-struct-pattern.stderr b/tests/ui/missing/missing-fields-in-struct-pattern.stderr new file mode 100644 index 000000000..1fe9f5299 --- /dev/null +++ b/tests/ui/missing/missing-fields-in-struct-pattern.stderr @@ -0,0 +1,14 @@ +error[E0769]: tuple variant `S` written as struct variant + --> $DIR/missing-fields-in-struct-pattern.rs:4:12 + | +LL | if let S { a, b, c, d } = S(1, 2, 3, 4) { + | ^^^^^^^^^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | if let S(a, b, c, d) = S(1, 2, 3, 4) { + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/missing/missing-items/auxiliary/m1.rs b/tests/ui/missing/missing-items/auxiliary/m1.rs new file mode 100644 index 000000000..fcf52c9e8 --- /dev/null +++ b/tests/ui/missing/missing-items/auxiliary/m1.rs @@ -0,0 +1,9 @@ +pub trait X { + const CONSTANT: u32; + type Type; + fn method(&self, s: String) -> Self::Type; + fn method2(self: Box, s: String) -> Self::Type; + fn method3(other: &Self, s: String) -> Self::Type; + fn method4(&self, other: &Self) -> Self::Type; + fn method5(self: &Box) -> Self::Type; +} diff --git a/tests/ui/missing/missing-items/m2.rs b/tests/ui/missing/missing-items/m2.rs new file mode 100644 index 000000000..c2a6914ab --- /dev/null +++ b/tests/ui/missing/missing-items/m2.rs @@ -0,0 +1,12 @@ +// aux-build:m1.rs + + +extern crate m1; + +struct X { +} + +impl m1::X for X { //~ ERROR not all trait items implemented +} + +fn main() {} diff --git a/tests/ui/missing/missing-items/m2.stderr b/tests/ui/missing/missing-items/m2.stderr new file mode 100644 index 000000000..d18fb443a --- /dev/null +++ b/tests/ui/missing/missing-items/m2.stderr @@ -0,0 +1,17 @@ +error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` + --> $DIR/m2.rs:9:1 + | +LL | impl m1::X for X { + | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` in implementation + | + = help: implement the missing item: `const CONSTANT: u32 = 42;` + = help: implement the missing item: `type Type = Type;` + = help: implement the missing item: `fn method(&self, _: String) -> ::Type { todo!() }` + = help: implement the missing item: `fn method2(self: Box, _: String) -> ::Type { todo!() }` + = help: implement the missing item: `fn method3(_: &Self, _: String) -> ::Type { todo!() }` + = help: implement the missing item: `fn method4(&self, _: &Self) -> ::Type { todo!() }` + = help: implement the missing item: `fn method5(self: &Box) -> ::Type { todo!() }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/missing/missing-items/missing-type-parameter.rs b/tests/ui/missing/missing-items/missing-type-parameter.rs new file mode 100644 index 000000000..8a64053a4 --- /dev/null +++ b/tests/ui/missing/missing-items/missing-type-parameter.rs @@ -0,0 +1,5 @@ +fn foo() { } + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/tests/ui/missing/missing-items/missing-type-parameter.stderr b/tests/ui/missing/missing-items/missing-type-parameter.stderr new file mode 100644 index 000000000..722539fca --- /dev/null +++ b/tests/ui/missing/missing-items/missing-type-parameter.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/missing-type-parameter.rs:4:5 + | +LL | foo(); + | ^^^ cannot infer type of the type parameter `X` declared on the function `foo` + | +help: consider specifying the generic argument + | +LL | foo::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/missing/missing-items/missing-type-parameter2.rs b/tests/ui/missing/missing-items/missing-type-parameter2.rs new file mode 100644 index 000000000..e9b32fb71 --- /dev/null +++ b/tests/ui/missing/missing-items/missing-type-parameter2.rs @@ -0,0 +1,19 @@ +struct X(); + +impl X {} +//~^ ERROR cannot find type `N` in this scope +//~| ERROR unresolved item provided when a constant was expected +impl X {} +//~^ ERROR cannot find type `N` in this scope +//~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +//~| ERROR unresolved item provided when a constant was expected + +fn foo(_: T) where T: Send {} +//~^ ERROR cannot find type `T` in this scope +//~| ERROR cannot find type `T` in this scope + +fn bar(_: A) {} +//~^ ERROR cannot find type `A` in this scope + +fn main() { +} diff --git a/tests/ui/missing/missing-items/missing-type-parameter2.stderr b/tests/ui/missing/missing-items/missing-type-parameter2.stderr new file mode 100644 index 000000000..f33951c98 --- /dev/null +++ b/tests/ui/missing/missing-items/missing-type-parameter2.stderr @@ -0,0 +1,121 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/missing-type-parameter2.rs:3:8 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +LL | +LL | impl X {} + | ^ + | +help: a struct with a similar name exists + | +LL | impl X {} + | ~ +help: you might be missing a type parameter + | +LL | impl X {} + | +++ + +error[E0412]: cannot find type `N` in this scope + --> $DIR/missing-type-parameter2.rs:6:28 + | +LL | impl X {} + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | impl X {} + | ~ +help: you might be missing a type parameter + | +LL | impl X {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/missing-type-parameter2.rs:11:20 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +... +LL | fn foo(_: T) where T: Send {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn foo(_: T) where X: Send {} + | ~ +help: you might be missing a type parameter + | +LL | fn foo(_: T) where T: Send {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/missing-type-parameter2.rs:11:11 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +... +LL | fn foo(_: T) where T: Send {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn foo(_: X) where T: Send {} + | ~ +help: you might be missing a type parameter + | +LL | fn foo(_: T) where T: Send {} + | +++ + +error[E0412]: cannot find type `A` in this scope + --> $DIR/missing-type-parameter2.rs:15:24 + | +LL | struct X(); + | ------------------------ similarly named struct `X` defined here +... +LL | fn bar(_: A) {} + | ^ + | +help: a struct with a similar name exists + | +LL | fn bar(_: X) {} + | ~ +help: you might be missing a type parameter + | +LL | fn bar(_: A) {} + | +++ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/missing-type-parameter2.rs:3:8 + | +LL | impl X {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl X<{ N }> {} + | + + + +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/missing-type-parameter2.rs:6:9 + | +LL | impl X {} + | ^^^^^^^^^^^^^^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/missing-type-parameter2.rs:6:28 + | +LL | impl X {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl X<{ N }> {} + | + + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0412, E0747. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/missing/missing-macro-use.rs b/tests/ui/missing/missing-macro-use.rs new file mode 100644 index 000000000..d494c4471 --- /dev/null +++ b/tests/ui/missing/missing-macro-use.rs @@ -0,0 +1,8 @@ +// aux-build:two_macros.rs + +extern crate two_macros; + +pub fn main() { + macro_two!(); + //~^ ERROR cannot find macro `macro_two` in this scope +} diff --git a/tests/ui/missing/missing-macro-use.stderr b/tests/ui/missing/missing-macro-use.stderr new file mode 100644 index 000000000..99e291cda --- /dev/null +++ b/tests/ui/missing/missing-macro-use.stderr @@ -0,0 +1,11 @@ +error: cannot find macro `macro_two` in this scope + --> $DIR/missing-macro-use.rs:6:5 + | +LL | macro_two!(); + | ^^^^^^^^^ + | + = help: consider importing this macro: + two_macros::macro_two + +error: aborting due to previous error + diff --git a/tests/ui/missing/missing-main.rs b/tests/ui/missing/missing-main.rs new file mode 100644 index 000000000..6ad544533 --- /dev/null +++ b/tests/ui/missing/missing-main.rs @@ -0,0 +1,2 @@ +// error-pattern: `main` function not found +fn mian() { } diff --git a/tests/ui/missing/missing-main.stderr b/tests/ui/missing/missing-main.stderr new file mode 100644 index 000000000..5113dc6ec --- /dev/null +++ b/tests/ui/missing/missing-main.stderr @@ -0,0 +1,9 @@ +error[E0601]: `main` function not found in crate `missing_main` + --> $DIR/missing-main.rs:2:14 + | +LL | fn mian() { } + | ^ consider adding a `main` function to `$DIR/missing-main.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/missing/missing-return.rs b/tests/ui/missing/missing-return.rs new file mode 100644 index 000000000..6a171753d --- /dev/null +++ b/tests/ui/missing/missing-return.rs @@ -0,0 +1,5 @@ +// error-pattern: return + +fn f() -> isize { } + +fn main() { f(); } diff --git a/tests/ui/missing/missing-return.stderr b/tests/ui/missing/missing-return.stderr new file mode 100644 index 000000000..ff7f261e0 --- /dev/null +++ b/tests/ui/missing/missing-return.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/missing-return.rs:3:11 + | +LL | fn f() -> isize { } + | - ^^^^^ expected `isize`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/missing/missing-stability.rs b/tests/ui/missing/missing-stability.rs new file mode 100644 index 000000000..0da5808b4 --- /dev/null +++ b/tests/ui/missing/missing-stability.rs @@ -0,0 +1,24 @@ +// Checks that exported items without stability attributes cause an error + +#![crate_type="lib"] +#![feature(staged_api)] + +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +pub fn unmarked() { + //~^ ERROR function has missing stability attribute + () +} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub mod foo { + // #[unstable] is inherited + pub fn unmarked() {} +} + +#[stable(feature = "stable_test_feature", since="1.0.0")] +pub mod bar { + // #[stable] is not inherited + pub fn unmarked() {} + //~^ ERROR function has missing stability attribute +} diff --git a/tests/ui/missing/missing-stability.stderr b/tests/ui/missing/missing-stability.stderr new file mode 100644 index 000000000..659f8c78c --- /dev/null +++ b/tests/ui/missing/missing-stability.stderr @@ -0,0 +1,17 @@ +error: function has missing stability attribute + --> $DIR/missing-stability.rs:8:1 + | +LL | / pub fn unmarked() { +LL | | +LL | | () +LL | | } + | |_^ + +error: function has missing stability attribute + --> $DIR/missing-stability.rs:22:5 + | +LL | pub fn unmarked() {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/missing_debug_impls.rs b/tests/ui/missing_debug_impls.rs new file mode 100644 index 000000000..dc4dacfc4 --- /dev/null +++ b/tests/ui/missing_debug_impls.rs @@ -0,0 +1,38 @@ +// compile-flags: --crate-type lib +#![deny(missing_debug_implementations)] +#![allow(unused)] + +use std::fmt; + +pub enum A {} //~ ERROR type does not implement `Debug` + +#[derive(Debug)] +pub enum B {} + +pub enum C {} + +impl fmt::Debug for C { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +pub struct Foo; //~ ERROR type does not implement `Debug` + +#[derive(Debug)] +pub struct Bar; + +pub struct Baz; + +impl fmt::Debug for Baz { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +struct PrivateStruct; + +enum PrivateEnum {} + +#[derive(Debug)] +struct GenericType(T); diff --git a/tests/ui/missing_debug_impls.stderr b/tests/ui/missing_debug_impls.stderr new file mode 100644 index 000000000..0538f207b --- /dev/null +++ b/tests/ui/missing_debug_impls.stderr @@ -0,0 +1,20 @@ +error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation + --> $DIR/missing_debug_impls.rs:7:1 + | +LL | pub enum A {} + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/missing_debug_impls.rs:2:9 + | +LL | #![deny(missing_debug_implementations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation + --> $DIR/missing_debug_impls.rs:20:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/missing_non_modrs_mod/foo.rs b/tests/ui/missing_non_modrs_mod/foo.rs new file mode 100644 index 000000000..4f41316c8 --- /dev/null +++ b/tests/ui/missing_non_modrs_mod/foo.rs @@ -0,0 +1,4 @@ +// +// ignore-test this is just a helper for the real test in this dir + +mod missing; diff --git a/tests/ui/missing_non_modrs_mod/foo_inline.rs b/tests/ui/missing_non_modrs_mod/foo_inline.rs new file mode 100644 index 000000000..df60629ec --- /dev/null +++ b/tests/ui/missing_non_modrs_mod/foo_inline.rs @@ -0,0 +1,5 @@ +// ignore-test this is just a helper for the real test in this dir + +mod inline { + mod missing; +} diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs new file mode 100644 index 000000000..4ff975af6 --- /dev/null +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs @@ -0,0 +1,2 @@ +mod foo; +fn main() {} diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr new file mode 100644 index 000000000..31e4206a5 --- /dev/null +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -0,0 +1,11 @@ +error[E0583]: file not found for module `missing` + --> $DIR/foo.rs:4:1 + | +LL | mod missing; + | ^^^^^^^^^^^^ + | + = help: to create the module `missing`, create file "$DIR/foo/missing.rs" or "$DIR/foo/missing/mod.rs" + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs new file mode 100644 index 000000000..9ebb4f1bd --- /dev/null +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs @@ -0,0 +1,2 @@ +mod foo_inline; +fn main() {} diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr new file mode 100644 index 000000000..9d252398b --- /dev/null +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -0,0 +1,11 @@ +error[E0583]: file not found for module `missing` + --> $DIR/foo_inline.rs:4:5 + | +LL | mod missing; + | ^^^^^^^^^^^^ + | + = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs" or "$DIR/foo_inline/inline/missing/mod.rs" + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/mod-subitem-as-enum-variant.rs b/tests/ui/mod-subitem-as-enum-variant.rs new file mode 100644 index 000000000..959024c46 --- /dev/null +++ b/tests/ui/mod-subitem-as-enum-variant.rs @@ -0,0 +1,9 @@ +mod Mod { + pub struct FakeVariant(pub T); +} + +fn main() { + Mod::FakeVariant::(0); + Mod::::FakeVariant(0); + //~^ ERROR type arguments are not allowed on module `Mod` [E0109] +} diff --git a/tests/ui/mod-subitem-as-enum-variant.stderr b/tests/ui/mod-subitem-as-enum-variant.stderr new file mode 100644 index 000000000..cf61e94bd --- /dev/null +++ b/tests/ui/mod-subitem-as-enum-variant.stderr @@ -0,0 +1,11 @@ +error[E0109]: type arguments are not allowed on module `Mod` + --> $DIR/mod-subitem-as-enum-variant.rs:7:11 + | +LL | Mod::::FakeVariant(0); + | --- ^^^ type argument not allowed + | | + | not allowed on module `Mod` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/module-macro_use-arguments.rs b/tests/ui/module-macro_use-arguments.rs new file mode 100644 index 000000000..121b492e2 --- /dev/null +++ b/tests/ui/module-macro_use-arguments.rs @@ -0,0 +1,6 @@ +#[macro_use(foo, bar)] //~ ERROR arguments to `macro_use` are not allowed here +mod foo { +} + +fn main() { +} diff --git a/tests/ui/module-macro_use-arguments.stderr b/tests/ui/module-macro_use-arguments.stderr new file mode 100644 index 000000000..af799cb6d --- /dev/null +++ b/tests/ui/module-macro_use-arguments.stderr @@ -0,0 +1,8 @@ +error: arguments to `macro_use` are not allowed here + --> $DIR/module-macro_use-arguments.rs:1:1 + | +LL | #[macro_use(foo, bar)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/modules/auxiliary/dummy_lib.rs b/tests/ui/modules/auxiliary/dummy_lib.rs new file mode 100644 index 000000000..ef805c1f0 --- /dev/null +++ b/tests/ui/modules/auxiliary/dummy_lib.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +pub struct Dummy; diff --git a/tests/ui/modules/auxiliary/two_macros_2.rs b/tests/ui/modules/auxiliary/two_macros_2.rs new file mode 100644 index 000000000..8ad2c0f12 --- /dev/null +++ b/tests/ui/modules/auxiliary/two_macros_2.rs @@ -0,0 +1,3 @@ +macro_rules! macro_one { ($($t:tt)*) => ($($t)*) } + +macro_rules! macro_two { ($($t:tt)*) => ($($t)*) } diff --git a/tests/ui/modules/issue-56411-aux.rs b/tests/ui/modules/issue-56411-aux.rs new file mode 100644 index 000000000..c8e5a0598 --- /dev/null +++ b/tests/ui/modules/issue-56411-aux.rs @@ -0,0 +1,5 @@ +// check-pass + +struct T {} + +fn main() {} diff --git a/tests/ui/modules/issue-56411.rs b/tests/ui/modules/issue-56411.rs new file mode 100644 index 000000000..0a20f5fe9 --- /dev/null +++ b/tests/ui/modules/issue-56411.rs @@ -0,0 +1,18 @@ +macro_rules! import { + ( $(($path:expr, $name:ident)),* ) => { + $( + #[path = $path] + mod $name; + pub use self::$name; + //~^ ERROR the name `issue_56411_aux` is defined multiple times + //~| ERROR `issue_56411_aux` is only public within the crate, and cannot be re-exported outside + + )* + } +} + +import!(("issue-56411-aux.rs", issue_56411_aux)); + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/modules/issue-56411.stderr b/tests/ui/modules/issue-56411.stderr new file mode 100644 index 000000000..6732a8a3d --- /dev/null +++ b/tests/ui/modules/issue-56411.stderr @@ -0,0 +1,33 @@ +error[E0255]: the name `issue_56411_aux` is defined multiple times + --> $DIR/issue-56411.rs:6:21 + | +LL | mod $name; + | ---------- previous definition of the module `issue_56411_aux` here +LL | pub use self::$name; + | ^^^^^^^^^^^ + | | + | `issue_56411_aux` reimported here + | you can use `as` to change the binding name of the import +... +LL | import!(("issue-56411-aux.rs", issue_56411_aux)); + | ------------------------------------------------ in this macro invocation + | + = note: `issue_56411_aux` must be defined only once in the type namespace of this module + = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0365]: `issue_56411_aux` is only public within the crate, and cannot be re-exported outside + --> $DIR/issue-56411.rs:6:21 + | +LL | pub use self::$name; + | ^^^^^^^^^^^ re-export of crate public `issue_56411_aux` +... +LL | import!(("issue-56411-aux.rs", issue_56411_aux)); + | ------------------------------------------------ in this macro invocation + | + = note: consider declaring type or module `issue_56411_aux` with `pub` + = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0255, E0365. +For more information about an error, try `rustc --explain E0255`. diff --git a/tests/ui/modules/mod-inside-fn.rs b/tests/ui/modules/mod-inside-fn.rs new file mode 100644 index 000000000..93050c891 --- /dev/null +++ b/tests/ui/modules/mod-inside-fn.rs @@ -0,0 +1,13 @@ +// run-pass + +fn f() -> isize { + mod m { + pub fn g() -> isize { 720 } + } + + m::g() +} + +pub fn main() { + assert_eq!(f(), 720); +} diff --git a/tests/ui/modules/mod-view-items.rs b/tests/ui/modules/mod-view-items.rs new file mode 100644 index 000000000..db2b30366 --- /dev/null +++ b/tests/ui/modules/mod-view-items.rs @@ -0,0 +1,14 @@ +// run-pass +// Test view items inside non-file-level mods + +// This is a regression test for an issue where we were failing to +// pretty-print such view items. If that happens again, this should +// begin failing. + +// pretty-expanded FIXME #23616 + +mod m { + pub fn f() -> Vec { Vec::new() } +} + +pub fn main() { let _x = m::f(); } diff --git a/tests/ui/modules/mod_dir_implicit.rs b/tests/ui/modules/mod_dir_implicit.rs new file mode 100644 index 000000000..d6ea6a98b --- /dev/null +++ b/tests/ui/modules/mod_dir_implicit.rs @@ -0,0 +1,8 @@ +// run-pass +// ignore-pretty issue #37195 + +mod mod_dir_implicit_aux; + +pub fn main() { + assert_eq!(mod_dir_implicit_aux::foo(), 10); +} diff --git a/tests/ui/modules/mod_dir_implicit_aux/compiletest-ignore-dir b/tests/ui/modules/mod_dir_implicit_aux/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/modules/mod_dir_implicit_aux/mod.rs b/tests/ui/modules/mod_dir_implicit_aux/mod.rs new file mode 100644 index 000000000..4f1eb85e4 --- /dev/null +++ b/tests/ui/modules/mod_dir_implicit_aux/mod.rs @@ -0,0 +1,2 @@ +// run-pass +pub fn foo() -> isize { 10 } diff --git a/tests/ui/modules/mod_dir_path.rs b/tests/ui/modules/mod_dir_path.rs new file mode 100644 index 000000000..70f592d0c --- /dev/null +++ b/tests/ui/modules/mod_dir_path.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_macros)] +// ignore-pretty issue #37195 + +mod mod_dir_simple { + #[path = "test.rs"] + pub mod syrup; +} + +pub fn main() { + assert_eq!(mod_dir_simple::syrup::foo(), 10); + + #[path = "auxiliary"] + mod foo { + mod two_macros_2; + } + + #[path = "auxiliary"] + mod bar { + macro_rules! m { () => { mod two_macros_2; } } + m!(); + } +} diff --git a/tests/ui/modules/mod_dir_path2.rs b/tests/ui/modules/mod_dir_path2.rs new file mode 100644 index 000000000..c3e3e1d63 --- /dev/null +++ b/tests/ui/modules/mod_dir_path2.rs @@ -0,0 +1,12 @@ +// run-pass +// ignore-pretty issue #37195 + +#[path = "mod_dir_simple"] +mod pancakes { + #[path = "test.rs"] + pub mod syrup; +} + +pub fn main() { + assert_eq!(pancakes::syrup::foo(), 10); +} diff --git a/tests/ui/modules/mod_dir_path3.rs b/tests/ui/modules/mod_dir_path3.rs new file mode 100644 index 000000000..fed70c1bc --- /dev/null +++ b/tests/ui/modules/mod_dir_path3.rs @@ -0,0 +1,11 @@ +// run-pass +// ignore-pretty issue #37195 + +#[path = "mod_dir_simple"] +mod pancakes { + pub mod test; +} + +pub fn main() { + assert_eq!(pancakes::test::foo(), 10); +} diff --git a/tests/ui/modules/mod_dir_path_multi.rs b/tests/ui/modules/mod_dir_path_multi.rs new file mode 100644 index 000000000..2b805141a --- /dev/null +++ b/tests/ui/modules/mod_dir_path_multi.rs @@ -0,0 +1,17 @@ +// run-pass +// ignore-pretty issue #37195 + +#[path = "mod_dir_simple"] +mod biscuits { + pub mod test; +} + +#[path = "mod_dir_simple"] +mod gravy { + pub mod test; +} + +pub fn main() { + assert_eq!(biscuits::test::foo(), 10); + assert_eq!(gravy::test::foo(), 10); +} diff --git a/tests/ui/modules/mod_dir_recursive.rs b/tests/ui/modules/mod_dir_recursive.rs new file mode 100644 index 000000000..b109d13d1 --- /dev/null +++ b/tests/ui/modules/mod_dir_recursive.rs @@ -0,0 +1,14 @@ +// run-pass +// ignore-pretty issue #37195 + +// Testing that the parser for each file tracks its modules +// and paths independently. The load_another_mod module should +// not try to reuse the 'mod_dir_simple' path. + +mod mod_dir_simple { + pub mod load_another_mod; +} + +pub fn main() { + assert_eq!(mod_dir_simple::load_another_mod::test::foo(), 10); +} diff --git a/tests/ui/modules/mod_dir_simple.rs b/tests/ui/modules/mod_dir_simple.rs new file mode 100644 index 000000000..1d92c968a --- /dev/null +++ b/tests/ui/modules/mod_dir_simple.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-pretty issue #37195 + +mod mod_dir_simple { + pub mod test; +} + +pub fn main() { + assert_eq!(mod_dir_simple::test::foo(), 10); +} diff --git a/tests/ui/modules/mod_dir_simple/compiletest-ignore-dir b/tests/ui/modules/mod_dir_simple/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/modules/mod_dir_simple/load_another_mod.rs b/tests/ui/modules/mod_dir_simple/load_another_mod.rs new file mode 100644 index 000000000..f96b546aa --- /dev/null +++ b/tests/ui/modules/mod_dir_simple/load_another_mod.rs @@ -0,0 +1,3 @@ +// run-pass +#[path = "test.rs"] +pub mod test; diff --git a/tests/ui/modules/mod_dir_simple/test.rs b/tests/ui/modules/mod_dir_simple/test.rs new file mode 100644 index 000000000..4f1eb85e4 --- /dev/null +++ b/tests/ui/modules/mod_dir_simple/test.rs @@ -0,0 +1,2 @@ +// run-pass +pub fn foo() -> isize { 10 } diff --git a/tests/ui/modules/mod_file.rs b/tests/ui/modules/mod_file.rs new file mode 100644 index 000000000..0ca52889e --- /dev/null +++ b/tests/ui/modules/mod_file.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-pretty issue #37195 + +// Testing that a plain .rs file can load modules from other source files + +mod mod_file_aux; + +pub fn main() { + assert_eq!(mod_file_aux::foo(), 10); +} diff --git a/tests/ui/modules/mod_file_aux.rs b/tests/ui/modules/mod_file_aux.rs new file mode 100644 index 000000000..6d052272e --- /dev/null +++ b/tests/ui/modules/mod_file_aux.rs @@ -0,0 +1,4 @@ +// run-pass +// ignore-test Not a test. Used by other tests + +pub fn foo() -> isize { 10 } diff --git a/tests/ui/modules/mod_file_with_path_attr.rs b/tests/ui/modules/mod_file_with_path_attr.rs new file mode 100644 index 000000000..48e253ead --- /dev/null +++ b/tests/ui/modules/mod_file_with_path_attr.rs @@ -0,0 +1,11 @@ +// run-pass +// ignore-pretty issue #37195 + +// Testing that a plain .rs file can load modules from other source files + +#[path = "mod_file_aux.rs"] +mod m; + +pub fn main() { + assert_eq!(m::foo(), 10); +} diff --git a/tests/ui/modules/module-polymorphism3-files/compiletest-ignore-dir b/tests/ui/modules/module-polymorphism3-files/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/modules/module-polymorphism3-files/float-template/inst_f32.rs b/tests/ui/modules/module-polymorphism3-files/float-template/inst_f32.rs new file mode 100644 index 000000000..49d2b3d4b --- /dev/null +++ b/tests/ui/modules/module-polymorphism3-files/float-template/inst_f32.rs @@ -0,0 +1,3 @@ +// run-pass + +pub type T = f32; diff --git a/tests/ui/modules/module-polymorphism3-files/float-template/inst_f64.rs b/tests/ui/modules/module-polymorphism3-files/float-template/inst_f64.rs new file mode 100644 index 000000000..e2aad480e --- /dev/null +++ b/tests/ui/modules/module-polymorphism3-files/float-template/inst_f64.rs @@ -0,0 +1,3 @@ +// run-pass + +pub type T = f64; diff --git a/tests/ui/modules/module-polymorphism3-files/float-template/inst_float.rs b/tests/ui/modules/module-polymorphism3-files/float-template/inst_float.rs new file mode 100644 index 000000000..5828718cd --- /dev/null +++ b/tests/ui/modules/module-polymorphism3-files/float-template/inst_float.rs @@ -0,0 +1,3 @@ +// run-pass + +pub type T = float; diff --git a/tests/ui/modules/path-invalid-form.rs b/tests/ui/modules/path-invalid-form.rs new file mode 100644 index 000000000..713ef4a79 --- /dev/null +++ b/tests/ui/modules/path-invalid-form.rs @@ -0,0 +1,4 @@ +#[path = 123] //~ ERROR malformed `path` attribute +mod foo; + +fn main() {} diff --git a/tests/ui/modules/path-invalid-form.stderr b/tests/ui/modules/path-invalid-form.stderr new file mode 100644 index 000000000..7e8aa44ef --- /dev/null +++ b/tests/ui/modules/path-invalid-form.stderr @@ -0,0 +1,8 @@ +error: malformed `path` attribute input + --> $DIR/path-invalid-form.rs:1:1 + | +LL | #[path = 123] + | ^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + +error: aborting due to previous error + diff --git a/tests/ui/modules/path-macro.rs b/tests/ui/modules/path-macro.rs new file mode 100644 index 000000000..ce2d1e2da --- /dev/null +++ b/tests/ui/modules/path-macro.rs @@ -0,0 +1,8 @@ +macro_rules! foo { + () => {"bar.rs"}; +} + +#[path = foo!()] //~ ERROR malformed `path` attribute +mod abc; + +fn main() {} diff --git a/tests/ui/modules/path-macro.stderr b/tests/ui/modules/path-macro.stderr new file mode 100644 index 000000000..9a2e01ea2 --- /dev/null +++ b/tests/ui/modules/path-macro.stderr @@ -0,0 +1,8 @@ +error: malformed `path` attribute input + --> $DIR/path-macro.rs:5:1 + | +LL | #[path = foo!()] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + +error: aborting due to previous error + diff --git a/tests/ui/modules/path-no-file-name.rs b/tests/ui/modules/path-no-file-name.rs new file mode 100644 index 000000000..f62cd2a9e --- /dev/null +++ b/tests/ui/modules/path-no-file-name.rs @@ -0,0 +1,7 @@ +// normalize-stderr-test: "\.:.*\(" -> ".: $$ACCESS_DENIED_MSG (" +// normalize-stderr-test: "os error \d+" -> "os error $$ACCESS_DENIED_CODE" + +#[path = "."] +mod m; //~ ERROR couldn't read + +fn main() {} diff --git a/tests/ui/modules/path-no-file-name.stderr b/tests/ui/modules/path-no-file-name.stderr new file mode 100644 index 000000000..32a213c68 --- /dev/null +++ b/tests/ui/modules/path-no-file-name.stderr @@ -0,0 +1,8 @@ +error: couldn't read $DIR/.: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) + --> $DIR/path-no-file-name.rs:5:1 + | +LL | mod m; + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/modules/special_module_name.rs b/tests/ui/modules/special_module_name.rs new file mode 100644 index 000000000..15c59b2da --- /dev/null +++ b/tests/ui/modules/special_module_name.rs @@ -0,0 +1,8 @@ +mod lib; +//~^ WARN found module declaration for lib.rs +//~| ERROR file not found for module `lib` +mod main; +//~^ WARN found module declaration for main.rs +//~| ERROR file not found for module `main` + +fn main() {} diff --git a/tests/ui/modules/special_module_name.stderr b/tests/ui/modules/special_module_name.stderr new file mode 100644 index 000000000..bc4b4f1b3 --- /dev/null +++ b/tests/ui/modules/special_module_name.stderr @@ -0,0 +1,37 @@ +error[E0583]: file not found for module `lib` + --> $DIR/special_module_name.rs:1:1 + | +LL | mod lib; + | ^^^^^^^^ + | + = help: to create the module `lib`, create file "$DIR/lib.rs" or "$DIR/lib/mod.rs" + +error[E0583]: file not found for module `main` + --> $DIR/special_module_name.rs:4:1 + | +LL | mod main; + | ^^^^^^^^^ + | + = help: to create the module `main`, create file "$DIR/main.rs" or "$DIR/main/mod.rs" + +warning: found module declaration for lib.rs + --> $DIR/special_module_name.rs:1:1 + | +LL | mod lib; + | ^^^^^^^^ + | + = note: lib.rs is the root of this crate's library target + = help: to refer to it from other targets, use the library's name as the path + = note: `#[warn(special_module_name)]` on by default + +warning: found module declaration for main.rs + --> $DIR/special_module_name.rs:4:1 + | +LL | mod main; + | ^^^^^^^^^ + | + = note: a binary crate cannot be used as library + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/modules/special_module_name_ignore.rs b/tests/ui/modules/special_module_name_ignore.rs new file mode 100644 index 000000000..07cea9b2b --- /dev/null +++ b/tests/ui/modules/special_module_name_ignore.rs @@ -0,0 +1,9 @@ +// run-pass + +#[path = "auxiliary/dummy_lib.rs"] +mod lib; + +#[path = "auxiliary/dummy_lib.rs"] +mod main; + +fn main() {} diff --git a/tests/ui/modules_and_files_visibility/mod_file_aux.rs b/tests/ui/modules_and_files_visibility/mod_file_aux.rs new file mode 100644 index 000000000..98f42c5cd --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_aux.rs @@ -0,0 +1,3 @@ +// ignore-test Not a test. Used by other tests + +pub fn foo() -> isize { 10 } diff --git a/tests/ui/modules_and_files_visibility/mod_file_correct_spans.rs b/tests/ui/modules_and_files_visibility/mod_file_correct_spans.rs new file mode 100644 index 000000000..c42d2eaa7 --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_correct_spans.rs @@ -0,0 +1,8 @@ +// Testing that the source_map is maintained correctly when parsing mods from external files + +mod mod_file_aux; + +fn main() { + assert!(mod_file_aux::bar() == 10); + //~^ ERROR cannot find function `bar` in module `mod_file_aux` +} diff --git a/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr b/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr new file mode 100644 index 000000000..73044752b --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_correct_spans.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `bar` in module `mod_file_aux` + --> $DIR/mod_file_correct_spans.rs:6:27 + | +LL | assert!(mod_file_aux::bar() == 10); + | ^^^ not found in `mod_file_aux` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig.rs new file mode 100644 index 000000000..e5958af17 --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig.rs @@ -0,0 +1,6 @@ +mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` found at both + +fn main() { + assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared crate or module `mod_file_aux` +} diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr b/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr new file mode 100644 index 000000000..a2c993969 --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr @@ -0,0 +1,18 @@ +error[E0761]: file for module `mod_file_disambig_aux` found at both "$DIR/mod_file_disambig_aux.rs" and "$DIR/mod_file_disambig_aux/mod.rs" + --> $DIR/mod_file_disambig.rs:1:1 + | +LL | mod mod_file_disambig_aux; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: delete or rename one of them to remove the ambiguity + +error[E0433]: failed to resolve: use of undeclared crate or module `mod_file_aux` + --> $DIR/mod_file_disambig.rs:4:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared crate or module `mod_file_aux` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0761. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs new file mode 100644 index 000000000..3bf9609f4 --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs @@ -0,0 +1 @@ +// ignore-test not a test. aux file diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs new file mode 100644 index 000000000..3bf9609f4 --- /dev/null +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs @@ -0,0 +1 @@ +// ignore-test not a test. aux file diff --git a/tests/ui/monomorphize-abi-alignment.rs b/tests/ui/monomorphize-abi-alignment.rs new file mode 100644 index 000000000..a8d8bd1d5 --- /dev/null +++ b/tests/ui/monomorphize-abi-alignment.rs @@ -0,0 +1,35 @@ +// run-pass + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +/*! + * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment, + * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment + * of any field. (Also, `u64` has 8-byte ABI alignment; this is not always true). + * + * On such platforms, if monomorphize uses the "preferred" alignment, then it will unify + * `A` and `B`, even though `S` and `S` have the field `t` at different offsets, + * and apply the wrong instance of the method `unwrap`. + */ + +#[derive(Copy, Clone)] +struct S { i:u8, t:T } + +impl S { + fn unwrap(self) -> T { + self.t + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] +struct A((u32, u32)); + +#[derive(Copy, Clone, PartialEq, Debug)] +struct B(u64); + +pub fn main() { + static Ca: S = S { i: 0, t: A((13, 104)) }; + static Cb: S = S { i: 0, t: B(31337) }; + assert_eq!(Ca.unwrap(), A((13, 104))); + assert_eq!(Cb.unwrap(), B(31337)); +} diff --git a/tests/ui/moves/borrow-closures-instead-of-move.rs b/tests/ui/moves/borrow-closures-instead-of-move.rs new file mode 100644 index 000000000..51771ced7 --- /dev/null +++ b/tests/ui/moves/borrow-closures-instead-of-move.rs @@ -0,0 +1,36 @@ +fn takes_fn(f: impl Fn()) { + loop { + takes_fnonce(f); + //~^ ERROR use of moved value + //~| HELP consider borrowing + } +} + +fn takes_fn_mut(m: impl FnMut()) { + if maybe() { + takes_fnonce(m); + //~^ HELP consider mutably borrowing + } + takes_fnonce(m); + //~^ ERROR use of moved value +} + +fn has_closure() { + let mut x = 0; + let mut closure = || { + x += 1; + }; + takes_fnonce(closure); + //~^ HELP consider mutably borrowing + closure(); + //~^ ERROR borrow of moved value +} + +fn maybe() -> bool { + false +} + +// Could also be Fn[Mut], here it doesn't matter +fn takes_fnonce(_: impl FnOnce()) {} + +fn main() {} diff --git a/tests/ui/moves/borrow-closures-instead-of-move.stderr b/tests/ui/moves/borrow-closures-instead-of-move.stderr new file mode 100644 index 000000000..9a84ddef7 --- /dev/null +++ b/tests/ui/moves/borrow-closures-instead-of-move.stderr @@ -0,0 +1,68 @@ +error[E0382]: use of moved value: `f` + --> $DIR/borrow-closures-instead-of-move.rs:3:22 + | +LL | fn takes_fn(f: impl Fn()) { + | - move occurs because `f` has type `impl Fn()`, which does not implement the `Copy` trait +LL | loop { + | ---- inside of this loop +LL | takes_fnonce(f); + | ^ value moved here, in previous iteration of loop + | +note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary + --> $DIR/borrow-closures-instead-of-move.rs:34:20 + | +LL | fn takes_fnonce(_: impl FnOnce()) {} + | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider borrowing `f` + | +LL | takes_fnonce(&f); + | + + +error[E0382]: use of moved value: `m` + --> $DIR/borrow-closures-instead-of-move.rs:14:18 + | +LL | fn takes_fn_mut(m: impl FnMut()) { + | - move occurs because `m` has type `impl FnMut()`, which does not implement the `Copy` trait +LL | if maybe() { +LL | takes_fnonce(m); + | - value moved here +... +LL | takes_fnonce(m); + | ^ value used here after move + | +note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary + --> $DIR/borrow-closures-instead-of-move.rs:34:20 + | +LL | fn takes_fnonce(_: impl FnOnce()) {} + | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider mutably borrowing `m` + | +LL | takes_fnonce(&mut m); + | ++++ + +error[E0382]: borrow of moved value: `closure` + --> $DIR/borrow-closures-instead-of-move.rs:25:5 + | +LL | takes_fnonce(closure); + | ------- value moved here +LL | +LL | closure(); + | ^^^^^^^ value borrowed here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `x` out of its environment + --> $DIR/borrow-closures-instead-of-move.rs:21:9 + | +LL | x += 1; + | ^ +help: consider mutably borrowing `closure` + | +LL | takes_fnonce(&mut closure); + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/issue-46099-move-in-macro.rs b/tests/ui/moves/issue-46099-move-in-macro.rs new file mode 100644 index 000000000..576fe1f4c --- /dev/null +++ b/tests/ui/moves/issue-46099-move-in-macro.rs @@ -0,0 +1,15 @@ +// Regression test for issue #46099 +// Tests that we don't emit spurious +// 'value moved in previous iteration of loop' message + +macro_rules! test { + ($v:expr) => {{ + drop(&$v); + $v + }} +} + +fn main() { + let b = Box::new(true); + test!({b}); //~ ERROR use of moved value +} diff --git a/tests/ui/moves/issue-46099-move-in-macro.stderr b/tests/ui/moves/issue-46099-move-in-macro.stderr new file mode 100644 index 000000000..94bc9e6f4 --- /dev/null +++ b/tests/ui/moves/issue-46099-move-in-macro.stderr @@ -0,0 +1,16 @@ +error[E0382]: use of moved value: `b` + --> $DIR/issue-46099-move-in-macro.rs:14:12 + | +LL | let b = Box::new(true); + | - move occurs because `b` has type `Box`, which does not implement the `Copy` trait +LL | test!({b}); + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | test!({b.clone()}); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs new file mode 100644 index 000000000..56c225bab --- /dev/null +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -0,0 +1,74 @@ +// Regression test for issue #72649 +// Tests that we don't emit spurious +// 'value moved in previous iteration of loop' message + +struct NonCopy; + +fn good() { + loop { + let value = NonCopy{}; + let _used = value; + } +} + +fn moved_here_1() { + loop { + let value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + let _used = value; + //~^ NOTE value moved here + let _used2 = value; //~ ERROR use of moved value: `value` + //~^ NOTE value used here after move + } +} + +fn moved_here_2() { + let value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + loop { //~ NOTE inside of this loop + let _used = value; + //~^ NOTE value moved here + loop { + let _used2 = value; //~ ERROR use of moved value: `value` + //~^ NOTE value used here after move + } + } +} + +fn moved_loop_1() { + let value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + loop { //~ NOTE inside of this loop + let _used = value; //~ ERROR use of moved value: `value` + //~^ NOTE value moved here, in previous iteration of loop + } +} + +fn moved_loop_2() { + let mut value = NonCopy{}; + //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait + let _used = value; + value = NonCopy{}; + loop { //~ NOTE inside of this loop + let _used2 = value; //~ ERROR use of moved value: `value` + //~^ NOTE value moved here, in previous iteration of loop + } +} + +fn uninit_1() { + loop { + let value: NonCopy; //~ NOTE declared here + let _used = value; //~ ERROR binding `value` isn't initialized + //~^ NOTE `value` used here but it isn't initialized + } +} + +fn uninit_2() { + let mut value: NonCopy; //~ NOTE declared here + loop { + let _used = value; //~ ERROR binding `value` isn't initialized + //~^ NOTE `value` used here but it isn't initialized + } +} + +fn main() {} diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr new file mode 100644 index 000000000..7e119fe8c --- /dev/null +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -0,0 +1,79 @@ +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:20:22 + | +LL | let value = NonCopy{}; + | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +LL | +LL | let _used = value; + | ----- value moved here +LL | +LL | let _used2 = value; + | ^^^^^ value used here after move + +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:32:26 + | +LL | let value = NonCopy{}; + | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +LL | +LL | loop { + | ---- inside of this loop +LL | let _used = value; + | ----- value moved here +... +LL | let _used2 = value; + | ^^^^^ value used here after move + +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:42:21 + | +LL | let value = NonCopy{}; + | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +LL | +LL | loop { + | ---- inside of this loop +LL | let _used = value; + | ^^^^^ value moved here, in previous iteration of loop + +error[E0382]: use of moved value: `value` + --> $DIR/issue-72649-uninit-in-loop.rs:53:22 + | +LL | let mut value = NonCopy{}; + | --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait +... +LL | loop { + | ---- inside of this loop +LL | let _used2 = value; + | ^^^^^ value moved here, in previous iteration of loop + +error[E0381]: used binding `value` isn't initialized + --> $DIR/issue-72649-uninit-in-loop.rs:61:21 + | +LL | let value: NonCopy; + | ----- binding declared here but left uninitialized +LL | let _used = value; + | ^^^^^ `value` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let value: NonCopy = todo!(); + | +++++++++ + +error[E0381]: used binding `value` isn't initialized + --> $DIR/issue-72649-uninit-in-loop.rs:69:21 + | +LL | let mut value: NonCopy; + | --------- binding declared here but left uninitialized +LL | loop { +LL | let _used = value; + | ^^^^^ `value` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut value: NonCopy = todo!(); + | +++++++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/moves/issue-75904-move-closure-loop.rs b/tests/ui/moves/issue-75904-move-closure-loop.rs new file mode 100644 index 000000000..6641a0376 --- /dev/null +++ b/tests/ui/moves/issue-75904-move-closure-loop.rs @@ -0,0 +1,15 @@ +// Regression test for issue #75904 +// Tests that we point at an expression +// that required the upvar to be moved, rather than just borrowed. + +struct NotCopy; + +fn main() { + let mut a = NotCopy; + loop { + || { //~ ERROR use of moved value + &mut a; + a; + }; + } +} diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr new file mode 100644 index 000000000..5e427a1fc --- /dev/null +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -0,0 +1,15 @@ +error[E0382]: use of moved value: `a` + --> $DIR/issue-75904-move-closure-loop.rs:10:9 + | +LL | let mut a = NotCopy; + | ----- move occurs because `a` has type `NotCopy`, which does not implement the `Copy` trait +LL | loop { +LL | || { + | ^^ value moved into closure here, in previous iteration of loop +LL | &mut a; +LL | a; + | - use occurs due to use in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/issue-99470-move-out-of-some.rs b/tests/ui/moves/issue-99470-move-out-of-some.rs new file mode 100644 index 000000000..f404cd3cd --- /dev/null +++ b/tests/ui/moves/issue-99470-move-out-of-some.rs @@ -0,0 +1,9 @@ +fn main() { + let x: &Option> = &Some(Box::new(0)); + + match x { + //~^ ERROR cannot move out of `x` as enum variant `Some` which is behind a shared reference + &Some(_y) => (), + &None => (), + } +} diff --git a/tests/ui/moves/issue-99470-move-out-of-some.stderr b/tests/ui/moves/issue-99470-move-out-of-some.stderr new file mode 100644 index 000000000..c5159471f --- /dev/null +++ b/tests/ui/moves/issue-99470-move-out-of-some.stderr @@ -0,0 +1,21 @@ +error[E0507]: cannot move out of `x` as enum variant `Some` which is behind a shared reference + --> $DIR/issue-99470-move-out-of-some.rs:4:11 + | +LL | match x { + | ^ +LL | +LL | &Some(_y) => (), + | -- + | | + | data moved here + | move occurs because `_y` has type `Box`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Some(_y) => (), +LL + Some(_y) => (), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/move-1-unique.rs b/tests/ui/moves/move-1-unique.rs new file mode 100644 index 000000000..f98d075d1 --- /dev/null +++ b/tests/ui/moves/move-1-unique.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_mut)] +#![allow(dead_code)] + +#[derive(Clone)] +struct Triple { + x: isize, + y: isize, + z: isize, +} + +fn test(x: bool, foo: Box) -> isize { + let bar = foo; + let mut y: Box; + if x { y = bar; } else { y = Box::new(Triple{x: 4, y: 5, z: 6}); } + return y.y; +} + +pub fn main() { + let x: Box<_> = Box::new(Triple{x: 1, y: 2, z: 3}); + assert_eq!(test(true, x.clone()), 2); + assert_eq!(test(true, x.clone()), 2); + assert_eq!(test(true, x.clone()), 2); + assert_eq!(test(false, x), 5); +} diff --git a/tests/ui/moves/move-2-unique.rs b/tests/ui/moves/move-2-unique.rs new file mode 100644 index 000000000..8fda3c1c8 --- /dev/null +++ b/tests/ui/moves/move-2-unique.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] + +struct X { x: isize, y: isize, z: isize } + +pub fn main() { + let x: Box<_> = Box::new(X {x: 1, y: 2, z: 3}); + let y = x; + assert_eq!(y.y, 2); +} diff --git a/tests/ui/moves/move-2.rs b/tests/ui/moves/move-2.rs new file mode 100644 index 000000000..5e0100874 --- /dev/null +++ b/tests/ui/moves/move-2.rs @@ -0,0 +1,6 @@ +// run-pass +#![allow(dead_code)] + +struct X { x: isize, y: isize, z: isize } + +pub fn main() { let x: Box<_> = Box::new(X {x: 1, y: 2, z: 3}); let y = x; assert_eq!(y.y, 2); } diff --git a/tests/ui/moves/move-3-unique.rs b/tests/ui/moves/move-3-unique.rs new file mode 100644 index 000000000..8e5df2c3f --- /dev/null +++ b/tests/ui/moves/move-3-unique.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_mut)] +#![allow(dead_code)] + +#[derive(Clone)] +struct Triple { + x: isize, + y: isize, + z: isize, +} + +fn test(x: bool, foo: Box) -> isize { + let bar = foo; + let mut y: Box; + if x { y = bar; } else { y = Box::new(Triple {x: 4, y: 5, z: 6}); } + return y.y; +} + +pub fn main() { + let x: Box<_> = Box::new(Triple{x: 1, y: 2, z: 3}); + for _ in 0_usize..10000_usize { + assert_eq!(test(true, x.clone()), 2); + } + assert_eq!(test(false, x), 5); +} diff --git a/tests/ui/moves/move-4-unique.rs b/tests/ui/moves/move-4-unique.rs new file mode 100644 index 000000000..24aec7ea6 --- /dev/null +++ b/tests/ui/moves/move-4-unique.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] + +struct Triple {a: isize, b: isize, c: isize} + +fn test(foo: Box) -> Box { + let foo = foo; + let bar = foo; + let baz = bar; + let quux = baz; + return quux; +} + +pub fn main() { + let x = Box::new(Triple{a: 1, b: 2, c: 3}); + let y = test(x); + assert_eq!(y.c, 3); +} diff --git a/tests/ui/moves/move-4.rs b/tests/ui/moves/move-4.rs new file mode 100644 index 000000000..63aa031a6 --- /dev/null +++ b/tests/ui/moves/move-4.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] + +struct Triple { a: isize, b: isize, c: isize } + +fn test(foo: Box) -> Box { + let foo = foo; + let bar = foo; + let baz = bar; + let quux = baz; + return quux; +} + +pub fn main() { + let x = Box::new(Triple{ a: 1, b: 2, c: 3 }); + let y = test(x); + assert_eq!(y.c, 3); +} diff --git a/tests/ui/moves/move-arg-2-unique.rs b/tests/ui/moves/move-arg-2-unique.rs new file mode 100644 index 000000000..9622c8375 --- /dev/null +++ b/tests/ui/moves/move-arg-2-unique.rs @@ -0,0 +1,12 @@ +// run-pass + +fn test(foo: Box> ) { assert_eq!((*foo)[0], 10); } + +pub fn main() { + let x = Box::new(vec![10]); + // Test forgetting a local by move-in + test(x); + + // Test forgetting a temporary by move-in. + test(Box::new(vec![10])); +} diff --git a/tests/ui/moves/move-arg-2.rs b/tests/ui/moves/move-arg-2.rs new file mode 100644 index 000000000..77ee06e19 --- /dev/null +++ b/tests/ui/moves/move-arg-2.rs @@ -0,0 +1,12 @@ +// run-pass + +fn test(foo: Box>) { assert_eq!((*foo)[0], 10); } + +pub fn main() { + let x = Box::new(vec![10]); + // Test forgetting a local by move-in + test(x); + + // Test forgetting a temporary by move-in. + test(Box::new(vec![10])); +} diff --git a/tests/ui/moves/move-arg.rs b/tests/ui/moves/move-arg.rs new file mode 100644 index 000000000..5942cd89f --- /dev/null +++ b/tests/ui/moves/move-arg.rs @@ -0,0 +1,5 @@ +// run-pass + +fn test(foo: isize) { assert_eq!(foo, 10); } + +pub fn main() { let x = 10; test(x); } diff --git a/tests/ui/moves/move-deref-coercion.rs b/tests/ui/moves/move-deref-coercion.rs new file mode 100644 index 000000000..41154388f --- /dev/null +++ b/tests/ui/moves/move-deref-coercion.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +struct NotCopy { + inner: bool +} + +impl NotCopy { + fn inner_method(&self) {} +} + +struct Foo { + first: NotCopy, + second: NotCopy +} + +impl Deref for Foo { + type Target = NotCopy; + fn deref(&self) -> &NotCopy { + &self.second + } +} + +fn use_field(val: Foo) { + let _val = val.first; + val.inner; //~ ERROR borrow of +} + +fn use_method(val: Foo) { + let _val = val.first; + val.inner_method(); //~ ERROR borrow of +} + +fn main() {} diff --git a/tests/ui/moves/move-deref-coercion.stderr b/tests/ui/moves/move-deref-coercion.stderr new file mode 100644 index 000000000..5760f4a7f --- /dev/null +++ b/tests/ui/moves/move-deref-coercion.stderr @@ -0,0 +1,35 @@ +error[E0382]: borrow of partially moved value: `val` + --> $DIR/move-deref-coercion.rs:25:5 + | +LL | let _val = val.first; + | --------- value partially moved here +LL | val.inner; + | ^^^^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait + = note: borrow occurs due to deref coercion to `NotCopy` +note: deref defined here + --> $DIR/move-deref-coercion.rs:17:5 + | +LL | type Target = NotCopy; + | ^^^^^^^^^^^ + +error[E0382]: borrow of partially moved value: `val` + --> $DIR/move-deref-coercion.rs:30:5 + | +LL | let _val = val.first; + | --------- value partially moved here +LL | val.inner_method(); + | ^^^^^^^^^^^^^^^^^^ value borrowed here after partial move + | + = note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait + = note: borrow occurs due to deref coercion to `NotCopy` +note: deref defined here + --> $DIR/move-deref-coercion.rs:17:5 + | +LL | type Target = NotCopy; + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-fn-self-receiver.rs b/tests/ui/moves/move-fn-self-receiver.rs new file mode 100644 index 000000000..946642ef6 --- /dev/null +++ b/tests/ui/moves/move-fn-self-receiver.rs @@ -0,0 +1,79 @@ +use std::pin::Pin; +use std::rc::Rc; +use std::ops::Add; + +struct Foo; + +impl Add for Foo { + type Output = (); + fn add(self, _rhs: Self) -> () {} +} + +impl Foo { + fn use_self(self) {} + fn use_box_self(self: Box) {} + fn use_pin_box_self(self: Pin>) {} + fn use_rc_self(self: Rc) {} + fn use_mut_self(&mut self) -> &mut Self { self } +} + +struct Container(Vec); + +impl Container { + fn custom_into_iter(self) -> impl Iterator { + self.0.into_iter() + } +} + +fn move_out(val: Container) { + val.0.into_iter().next(); + val.0; //~ ERROR use of moved + + let foo = Foo; + foo.use_self(); + foo; //~ ERROR use of moved + + let second_foo = Foo; + second_foo.use_self(); + second_foo; //~ ERROR use of moved + + let boxed_foo = Box::new(Foo); + boxed_foo.use_box_self(); + boxed_foo; //~ ERROR use of moved + + let pin_box_foo = Box::pin(Foo); + pin_box_foo.use_pin_box_self(); + pin_box_foo; //~ ERROR use of moved + + let mut mut_foo = Foo; + let ret = mut_foo.use_mut_self(); + mut_foo; //~ ERROR cannot move out + ret; + + let rc_foo = Rc::new(Foo); + rc_foo.use_rc_self(); + rc_foo; //~ ERROR use of moved + + let foo_add = Foo; + foo_add + Foo; + foo_add; //~ ERROR use of moved + + let implicit_into_iter = vec![true]; + for _val in implicit_into_iter {} + implicit_into_iter; //~ ERROR use of moved + + let explicit_into_iter = vec![true]; + for _val in explicit_into_iter.into_iter() {} + explicit_into_iter; //~ ERROR use of moved + + let container = Container(vec![]); + for _val in container.custom_into_iter() {} + container; //~ ERROR use of moved + + let foo2 = Foo; + loop { + foo2.use_self(); //~ ERROR use of moved + } +} + +fn main() {} diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr new file mode 100644 index 000000000..7f69e5dcf --- /dev/null +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -0,0 +1,177 @@ +error[E0382]: use of moved value: `val.0` + --> $DIR/move-fn-self-receiver.rs:30:5 + | +LL | val.0.into_iter().next(); + | ----------- `val.0` moved due to this method call +LL | val.0; + | ^^^^^ value used here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `val.0` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: move occurs because `val.0` has type `Vec`, which does not implement the `Copy` trait +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | val.0.clone().into_iter().next(); + | ++++++++ + +error[E0382]: use of moved value: `foo` + --> $DIR/move-fn-self-receiver.rs:34:5 + | +LL | let foo = Foo; + | --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait +LL | foo.use_self(); + | ---------- `foo` moved due to this method call +LL | foo; + | ^^^ value used here after move + | +note: `Foo::use_self` takes ownership of the receiver `self`, which moves `foo` + --> $DIR/move-fn-self-receiver.rs:13:17 + | +LL | fn use_self(self) {} + | ^^^^ + +error[E0382]: use of moved value: `second_foo` + --> $DIR/move-fn-self-receiver.rs:38:5 + | +LL | let second_foo = Foo; + | ---------- move occurs because `second_foo` has type `Foo`, which does not implement the `Copy` trait +LL | second_foo.use_self(); + | ---------- `second_foo` moved due to this method call +LL | second_foo; + | ^^^^^^^^^^ value used here after move + +error[E0382]: use of moved value: `boxed_foo` + --> $DIR/move-fn-self-receiver.rs:42:5 + | +LL | let boxed_foo = Box::new(Foo); + | --------- move occurs because `boxed_foo` has type `Box`, which does not implement the `Copy` trait +LL | boxed_foo.use_box_self(); + | -------------- `boxed_foo` moved due to this method call +LL | boxed_foo; + | ^^^^^^^^^ value used here after move + | +note: `Foo::use_box_self` takes ownership of the receiver `self`, which moves `boxed_foo` + --> $DIR/move-fn-self-receiver.rs:14:21 + | +LL | fn use_box_self(self: Box) {} + | ^^^^ + +error[E0382]: use of moved value: `pin_box_foo` + --> $DIR/move-fn-self-receiver.rs:46:5 + | +LL | let pin_box_foo = Box::pin(Foo); + | ----------- move occurs because `pin_box_foo` has type `Pin>`, which does not implement the `Copy` trait +LL | pin_box_foo.use_pin_box_self(); + | ------------------ `pin_box_foo` moved due to this method call +LL | pin_box_foo; + | ^^^^^^^^^^^ value used here after move + | +note: `Foo::use_pin_box_self` takes ownership of the receiver `self`, which moves `pin_box_foo` + --> $DIR/move-fn-self-receiver.rs:15:25 + | +LL | fn use_pin_box_self(self: Pin>) {} + | ^^^^ + +error[E0505]: cannot move out of `mut_foo` because it is borrowed + --> $DIR/move-fn-self-receiver.rs:50:5 + | +LL | let ret = mut_foo.use_mut_self(); + | ---------------------- borrow of `mut_foo` occurs here +LL | mut_foo; + | ^^^^^^^ move out of `mut_foo` occurs here +LL | ret; + | --- borrow later used here + +error[E0382]: use of moved value: `rc_foo` + --> $DIR/move-fn-self-receiver.rs:55:5 + | +LL | let rc_foo = Rc::new(Foo); + | ------ move occurs because `rc_foo` has type `Rc`, which does not implement the `Copy` trait +LL | rc_foo.use_rc_self(); + | ------------- `rc_foo` moved due to this method call +LL | rc_foo; + | ^^^^^^ value used here after move + | +note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc_foo` + --> $DIR/move-fn-self-receiver.rs:16:20 + | +LL | fn use_rc_self(self: Rc) {} + | ^^^^ +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | rc_foo.clone().use_rc_self(); + | ++++++++ + +error[E0382]: use of moved value: `foo_add` + --> $DIR/move-fn-self-receiver.rs:59:5 + | +LL | let foo_add = Foo; + | ------- move occurs because `foo_add` has type `Foo`, which does not implement the `Copy` trait +LL | foo_add + Foo; + | ------------- `foo_add` moved due to usage in operator +LL | foo_add; + | ^^^^^^^ value used here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0382]: use of moved value: `implicit_into_iter` + --> $DIR/move-fn-self-receiver.rs:63:5 + | +LL | let implicit_into_iter = vec![true]; + | ------------------ move occurs because `implicit_into_iter` has type `Vec`, which does not implement the `Copy` trait +LL | for _val in implicit_into_iter {} + | ------------------ `implicit_into_iter` moved due to this implicit call to `.into_iter()` +LL | implicit_into_iter; + | ^^^^^^^^^^^^^^^^^^ value used here after move + | +help: consider iterating over a slice of the `Vec`'s content to avoid moving into the `for` loop + | +LL | for _val in &implicit_into_iter {} + | + + +error[E0382]: use of moved value: `explicit_into_iter` + --> $DIR/move-fn-self-receiver.rs:67:5 + | +LL | let explicit_into_iter = vec![true]; + | ------------------ move occurs because `explicit_into_iter` has type `Vec`, which does not implement the `Copy` trait +LL | for _val in explicit_into_iter.into_iter() {} + | ----------- `explicit_into_iter` moved due to this method call +LL | explicit_into_iter; + | ^^^^^^^^^^^^^^^^^^ value used here after move + | +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | for _val in explicit_into_iter.clone().into_iter() {} + | ++++++++ + +error[E0382]: use of moved value: `container` + --> $DIR/move-fn-self-receiver.rs:71:5 + | +LL | let container = Container(vec![]); + | --------- move occurs because `container` has type `Container`, which does not implement the `Copy` trait +LL | for _val in container.custom_into_iter() {} + | ------------------ `container` moved due to this method call +LL | container; + | ^^^^^^^^^ value used here after move + | +note: `Container::custom_into_iter` takes ownership of the receiver `self`, which moves `container` + --> $DIR/move-fn-self-receiver.rs:23:25 + | +LL | fn custom_into_iter(self) -> impl Iterator { + | ^^^^ + +error[E0382]: use of moved value: `foo2` + --> $DIR/move-fn-self-receiver.rs:75:9 + | +LL | let foo2 = Foo; + | ---- move occurs because `foo2` has type `Foo`, which does not implement the `Copy` trait +LL | loop { + | ---- inside of this loop +LL | foo2.use_self(); + | ^^^^ ---------- `foo2` moved due to this method call, in previous iteration of loop + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-guard-same-consts.rs b/tests/ui/moves/move-guard-same-consts.rs new file mode 100644 index 000000000..b96ef8e19 --- /dev/null +++ b/tests/ui/moves/move-guard-same-consts.rs @@ -0,0 +1,25 @@ +// #47295: We used to have a hack of special-casing adjacent amtch +// arms whose patterns were composed solely of constants to not have +// them linked in the cfg. +// +// This was broken for various reasons. In particular, that hack was +// originally authored under the assunption that other checks +// elsewhere would ensure that the two patterns did not overlap. But +// that assumption did not hold, at least not in the long run (namely, +// overlapping patterns were turned into warnings rather than errors). + + + +fn main() { + let x: Box<_> = Box::new(1); + + let v = (1, 2); + + match v { + (1, 2) if take(x) => (), + (1, 2) if take(x) => (), //~ ERROR use of moved value: `x` + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/tests/ui/moves/move-guard-same-consts.stderr b/tests/ui/moves/move-guard-same-consts.stderr new file mode 100644 index 000000000..86e5f6524 --- /dev/null +++ b/tests/ui/moves/move-guard-same-consts.stderr @@ -0,0 +1,26 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-guard-same-consts.rs:20:24 + | +LL | let x: Box<_> = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | (1, 2) if take(x) => (), + | - value moved here +LL | (1, 2) if take(x) => (), + | ^ value used here after move + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/move-guard-same-consts.rs:25:15 + | +LL | fn take(_: T) -> bool { false } + | ---- ^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | (1, 2) if take(x.clone()) => (), + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-in-guard-1.rs b/tests/ui/moves/move-in-guard-1.rs new file mode 100644 index 000000000..36e39fea6 --- /dev/null +++ b/tests/ui/moves/move-in-guard-1.rs @@ -0,0 +1,15 @@ +pub fn main() { + + + let x: Box<_> = Box::new(1); + + let v = (1, 2); + + match v { + (1, _) if take(x) => (), + (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/tests/ui/moves/move-in-guard-1.stderr b/tests/ui/moves/move-in-guard-1.stderr new file mode 100644 index 000000000..f04cb34d7 --- /dev/null +++ b/tests/ui/moves/move-in-guard-1.stderr @@ -0,0 +1,26 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-in-guard-1.rs:10:24 + | +LL | let x: Box<_> = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | (1, _) if take(x) => (), + | - value moved here +LL | (_, 2) if take(x) => (), + | ^ value used here after move + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/move-in-guard-1.rs:15:15 + | +LL | fn take(_: T) -> bool { false } + | ---- ^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | (1, _) if take(x.clone()) => (), + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-in-guard-2.rs b/tests/ui/moves/move-in-guard-2.rs new file mode 100644 index 000000000..085b7ec6e --- /dev/null +++ b/tests/ui/moves/move-in-guard-2.rs @@ -0,0 +1,13 @@ +pub fn main() { + let x: Box<_> = Box::new(1); + + let v = (1, 2); + + match v { + (1, _) | + (_, 2) if take(x) => (), //~ ERROR use of moved value: `x` + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/tests/ui/moves/move-in-guard-2.stderr b/tests/ui/moves/move-in-guard-2.stderr new file mode 100644 index 000000000..26047861f --- /dev/null +++ b/tests/ui/moves/move-in-guard-2.stderr @@ -0,0 +1,24 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-in-guard-2.rs:8:24 + | +LL | let x: Box<_> = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | (_, 2) if take(x) => (), + | ^ value used here after move + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/move-in-guard-2.rs:13:15 + | +LL | fn take(_: T) -> bool { false } + | ---- ^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | (_, 2) if take(x.clone()) => (), + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-into-dead-array-1.rs b/tests/ui/moves/move-into-dead-array-1.rs new file mode 100644 index 000000000..0b8d76def --- /dev/null +++ b/tests/ui/moves/move-into-dead-array-1.rs @@ -0,0 +1,15 @@ +// Ensure that we cannot move into an uninitialized fixed-size array. + +struct D { _x: u8 } + +fn d() -> D { D { _x: 0 } } + +fn main() { + foo(1); + foo(3); +} + +fn foo(i: usize) { + let mut a: [D; 4]; + a[i] = d(); //~ ERROR E0381 +} diff --git a/tests/ui/moves/move-into-dead-array-1.stderr b/tests/ui/moves/move-into-dead-array-1.stderr new file mode 100644 index 000000000..6db0f0bcb --- /dev/null +++ b/tests/ui/moves/move-into-dead-array-1.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `a` isn't initialized + --> $DIR/move-into-dead-array-1.rs:14:5 + | +LL | let mut a: [D; 4]; + | ----- binding declared here but left uninitialized +LL | a[i] = d(); + | ^^^^ `a` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let mut a: [D; 4] = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/moves/move-into-dead-array-2.rs b/tests/ui/moves/move-into-dead-array-2.rs new file mode 100644 index 000000000..9b66ea35f --- /dev/null +++ b/tests/ui/moves/move-into-dead-array-2.rs @@ -0,0 +1,15 @@ +// Ensure that we cannot move into an uninitialized fixed-size array. + +struct D { _x: u8 } + +fn d() -> D { D { _x: 0 } } + +fn main() { + foo([d(), d(), d(), d()], 1); + foo([d(), d(), d(), d()], 3); +} + +fn foo(mut a: [D; 4], i: usize) { + drop(a); + a[i] = d(); //~ ERROR use of moved value: `a` +} diff --git a/tests/ui/moves/move-into-dead-array-2.stderr b/tests/ui/moves/move-into-dead-array-2.stderr new file mode 100644 index 000000000..19e476c04 --- /dev/null +++ b/tests/ui/moves/move-into-dead-array-2.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `a` + --> $DIR/move-into-dead-array-2.rs:14:5 + | +LL | fn foo(mut a: [D; 4], i: usize) { + | ----- move occurs because `a` has type `[D; 4]`, which does not implement the `Copy` trait +LL | drop(a); + | - value moved here +LL | a[i] = d(); + | ^^^^ value used here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-nullary-fn.rs b/tests/ui/moves/move-nullary-fn.rs new file mode 100644 index 000000000..14c9262c7 --- /dev/null +++ b/tests/ui/moves/move-nullary-fn.rs @@ -0,0 +1,13 @@ +// run-pass +// Issue #922 +// pretty-expanded FIXME #23616 + +fn f2(_thing: F) where F: FnOnce() { } + +fn f(thing: F) where F: FnOnce() { + f2(thing); +} + +pub fn main() { + f(|| {}); +} diff --git a/tests/ui/moves/move-of-addr-of-mut.rs b/tests/ui/moves/move-of-addr-of-mut.rs new file mode 100644 index 000000000..19fd70286 --- /dev/null +++ b/tests/ui/moves/move-of-addr-of-mut.rs @@ -0,0 +1,12 @@ +// Ensure that taking a mutable raw ptr to an uninitialized variable does not change its +// initializedness. + +struct S; + +fn main() { + let mut x: S; + std::ptr::addr_of_mut!(x); //~ ERROR E0381 + + let y = x; // Should error here if `addr_of_mut` is ever allowed on uninitialized variables + drop(y); +} diff --git a/tests/ui/moves/move-of-addr-of-mut.stderr b/tests/ui/moves/move-of-addr-of-mut.stderr new file mode 100644 index 000000000..ddebaa012 --- /dev/null +++ b/tests/ui/moves/move-of-addr-of-mut.stderr @@ -0,0 +1,17 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/move-of-addr-of-mut.rs:8:5 + | +LL | let mut x: S; + | ----- binding declared here but left uninitialized +LL | std::ptr::addr_of_mut!(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` used here but it isn't initialized + | + = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider assigning a value + | +LL | let mut x: S = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/moves/move-out-of-array-1.rs b/tests/ui/moves/move-out-of-array-1.rs new file mode 100644 index 000000000..77cb73e47 --- /dev/null +++ b/tests/ui/moves/move-out-of-array-1.rs @@ -0,0 +1,18 @@ +// Ensure that we cannot move out of a fixed-size array (especially +// when the element type has a destructor). + + +struct D { _x: u8 } + +impl Drop for D { fn drop(&mut self) { } } + +fn main() { + fn d() -> D { D { _x: 0 } } + + let _d1 = foo([d(), d(), d(), d()], 1); + let _d3 = foo([d(), d(), d(), d()], 3); +} + +fn foo(a: [D; 4], i: usize) -> D { + a[i] //~ ERROR cannot move out of type `[D; 4]`, a non-copy array +} diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr new file mode 100644 index 000000000..0af083e5b --- /dev/null +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -0,0 +1,12 @@ +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-1.rs:17:5 + | +LL | a[i] + | ^^^^ + | | + | cannot move out of here + | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/move-out-of-array-ref.rs b/tests/ui/moves/move-out-of-array-ref.rs new file mode 100644 index 000000000..343f00ff2 --- /dev/null +++ b/tests/ui/moves/move-out-of-array-ref.rs @@ -0,0 +1,34 @@ +// Ensure that we cannot move out of a reference to a fixed-size array + +struct D { _x: u8 } + +impl Drop for D { fn drop(&mut self) { } } + +fn move_elem(a: &[D; 4]) -> D { + let [_, e, _, _] = *a; //~ ERROR cannot move + e +} + +fn move_subarr(a: &[D; 4]) -> [D; 2] { + let [_, s @ .. , _] = *a; //~ ERROR cannot move + s +} + +fn move_elem_mut(a: &mut [D; 4]) -> D { + let [_, e, _, _] = *a; //~ ERROR cannot move + e +} + +fn move_subarr_mut(a: &mut [D; 4]) -> [D; 2] { + let [_, s @ .. , _] = *a; //~ ERROR cannot move + s +} + +fn main() { + fn d() -> D { D { _x: 0 } } + + move_elem(&[d(), d(), d(), d()]); + move_subarr(&[d(), d(), d(), d()]); + move_elem_mut(&mut [d(), d(), d(), d()]); + move_subarr_mut(&mut [d(), d(), d(), d()]); +} diff --git a/tests/ui/moves/move-out-of-array-ref.stderr b/tests/ui/moves/move-out-of-array-ref.stderr new file mode 100644 index 000000000..26d4996d6 --- /dev/null +++ b/tests/ui/moves/move-out-of-array-ref.stderr @@ -0,0 +1,63 @@ +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:8:24 + | +LL | let [_, e, _, _] = *a; + | - ^^ cannot move out of here + | | + | data moved here + | move occurs because `e` has type `D`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let [_, e, _, _] = *a; +LL + let [_, e, _, _] = a; + | + +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:13:27 + | +LL | let [_, s @ .. , _] = *a; + | - ^^ cannot move out of here + | | + | data moved here + | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let [_, s @ .. , _] = *a; +LL + let [_, s @ .. , _] = a; + | + +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:18:24 + | +LL | let [_, e, _, _] = *a; + | - ^^ cannot move out of here + | | + | data moved here + | move occurs because `e` has type `D`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let [_, e, _, _] = *a; +LL + let [_, e, _, _] = a; + | + +error[E0508]: cannot move out of type `[D; 4]`, a non-copy array + --> $DIR/move-out-of-array-ref.rs:23:27 + | +LL | let [_, s @ .. , _] = *a; + | - ^^ cannot move out of here + | | + | data moved here + | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let [_, s @ .. , _] = *a; +LL + let [_, s @ .. , _] = a; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/move-out-of-field.rs b/tests/ui/moves/move-out-of-field.rs new file mode 100644 index 000000000..9f697db4f --- /dev/null +++ b/tests/ui/moves/move-out-of-field.rs @@ -0,0 +1,27 @@ +// run-pass + +use std::string::String; + +struct StringBuffer { + s: String, +} + +impl StringBuffer { + pub fn append(&mut self, v: &str) { + self.s.push_str(v); + } +} + +fn to_string(sb: StringBuffer) -> String { + sb.s +} + +pub fn main() { + let mut sb = StringBuffer { + s: String::new(), + }; + sb.append("Hello, "); + sb.append("World!"); + let str = to_string(sb); + assert_eq!(str, "Hello, World!"); +} diff --git a/tests/ui/moves/move-out-of-slice-1.rs b/tests/ui/moves/move-out-of-slice-1.rs new file mode 100644 index 000000000..982648f5b --- /dev/null +++ b/tests/ui/moves/move-out-of-slice-1.rs @@ -0,0 +1,11 @@ +#![feature(box_patterns)] + +struct A; + +fn main() { + let a: Box<[A]> = Box::new([A]); + match a { //~ ERROR cannot move out of type `[A]`, a non-copy slice + box [a] => {}, + _ => {} + } +} diff --git a/tests/ui/moves/move-out-of-slice-1.stderr b/tests/ui/moves/move-out-of-slice-1.stderr new file mode 100644 index 000000000..5a0357cf5 --- /dev/null +++ b/tests/ui/moves/move-out-of-slice-1.stderr @@ -0,0 +1,19 @@ +error[E0508]: cannot move out of type `[A]`, a non-copy slice + --> $DIR/move-out-of-slice-1.rs:7:11 + | +LL | match a { + | ^ cannot move out of here +LL | box [a] => {}, + | - + | | + | data moved here + | move occurs because `a` has type `A`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | box [ref a] => {}, + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/move-out-of-slice-2.rs b/tests/ui/moves/move-out-of-slice-2.rs new file mode 100644 index 000000000..2f7394fbf --- /dev/null +++ b/tests/ui/moves/move-out-of-slice-2.rs @@ -0,0 +1,36 @@ +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete +#![allow(unused)] + +struct A; +#[derive(Clone, Copy)] +struct C; + +fn main() { + let a: Box<[A]> = Box::new([A]); + match *a { + //~^ ERROR cannot move out of type `[A]`, a non-copy slice + [a @ ..] => {} + _ => {} + } + let b: Box<[A]> = Box::new([A, A, A]); + match *b { + //~^ ERROR cannot move out of type `[A]`, a non-copy slice + [_, _, b @ .., _] => {} + _ => {} + } + + // `[C]` isn't `Copy`, even if `C` is. + let c: Box<[C]> = Box::new([C]); + match *c { + //~^ ERROR cannot move out of type `[C]`, a non-copy slice + [c @ ..] => {} + _ => {} + } + let d: Box<[C]> = Box::new([C, C, C]); + match *d { + //~^ ERROR cannot move out of type `[C]`, a non-copy slice + [_, _, d @ .., _] => {} + _ => {} + } +} diff --git a/tests/ui/moves/move-out-of-slice-2.stderr b/tests/ui/moves/move-out-of-slice-2.stderr new file mode 100644 index 000000000..b46854cd6 --- /dev/null +++ b/tests/ui/moves/move-out-of-slice-2.stderr @@ -0,0 +1,80 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/move-out-of-slice-2.rs:1:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0508]: cannot move out of type `[A]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:11:11 + | +LL | match *a { + | ^^ cannot move out of here +LL | +LL | [a @ ..] => {} + | - + | | + | data moved here + | move occurs because `a` has type `[A]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [ref a @ ..] => {} + | +++ + +error[E0508]: cannot move out of type `[A]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:17:11 + | +LL | match *b { + | ^^ cannot move out of here +LL | +LL | [_, _, b @ .., _] => {} + | - + | | + | data moved here + | move occurs because `b` has type `[A]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [_, _, ref b @ .., _] => {} + | +++ + +error[E0508]: cannot move out of type `[C]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:25:11 + | +LL | match *c { + | ^^ cannot move out of here +LL | +LL | [c @ ..] => {} + | - + | | + | data moved here + | move occurs because `c` has type `[C]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [ref c @ ..] => {} + | +++ + +error[E0508]: cannot move out of type `[C]`, a non-copy slice + --> $DIR/move-out-of-slice-2.rs:31:11 + | +LL | match *d { + | ^^ cannot move out of here +LL | +LL | [_, _, d @ .., _] => {} + | - + | | + | data moved here + | move occurs because `d` has type `[C]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [_, _, ref d @ .., _] => {} + | +++ + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/move-out-of-tuple-field.rs b/tests/ui/moves/move-out-of-tuple-field.rs new file mode 100644 index 000000000..66912fa4d --- /dev/null +++ b/tests/ui/moves/move-out-of-tuple-field.rs @@ -0,0 +1,13 @@ +struct Foo(Box); + + + +fn main() { + let x: (Box<_>,) = (Box::new(1),); + let y = x.0; + let z = x.0; //~ ERROR use of moved value: `x.0` + + let x = Foo(Box::new(1)); + let y = x.0; + let z = x.0; //~ ERROR use of moved value: `x.0` +} diff --git a/tests/ui/moves/move-out-of-tuple-field.stderr b/tests/ui/moves/move-out-of-tuple-field.stderr new file mode 100644 index 000000000..bb4eb7677 --- /dev/null +++ b/tests/ui/moves/move-out-of-tuple-field.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `x.0` + --> $DIR/move-out-of-tuple-field.rs:8:13 + | +LL | let y = x.0; + | --- value moved here +LL | let z = x.0; + | ^^^ value used here after move + | + = note: move occurs because `x.0` has type `Box`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x.0` + --> $DIR/move-out-of-tuple-field.rs:12:13 + | +LL | let y = x.0; + | --- value moved here +LL | let z = x.0; + | ^^^ value used here after move + | + = note: move occurs because `x.0` has type `Box`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/move-scalar.rs b/tests/ui/moves/move-scalar.rs new file mode 100644 index 000000000..98bfeb1bc --- /dev/null +++ b/tests/ui/moves/move-scalar.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_mut)] + +pub fn main() { + + let y: isize = 42; + let mut x: isize; + x = y; + assert_eq!(x, 42); +} diff --git a/tests/ui/moves/moves-based-on-type-access-to-field.rs b/tests/ui/moves/moves-based-on-type-access-to-field.rs new file mode 100644 index 000000000..e2003ed6e --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-access-to-field.rs @@ -0,0 +1,14 @@ +// Tests that if you move from `x.f` or `x[0]`, `x` is inaccessible. +// Also tests that we give a more specific error message. + +struct Foo { f: String, y: isize } +fn consume(_s: String) {} +fn touch(_a: &A) {} + +fn f20() { + let x = vec!["hi".to_string()]; + consume(x.into_iter().next().unwrap()); + touch(&x[0]); //~ ERROR borrow of moved value: `x` +} + +fn main() {} diff --git a/tests/ui/moves/moves-based-on-type-access-to-field.stderr b/tests/ui/moves/moves-based-on-type-access-to-field.stderr new file mode 100644 index 000000000..a28f324aa --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-access-to-field.stderr @@ -0,0 +1,20 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-access-to-field.rs:11:12 + | +LL | let x = vec!["hi".to_string()]; + | - move occurs because `x` has type `Vec`, which does not implement the `Copy` trait +LL | consume(x.into_iter().next().unwrap()); + | ----------- `x` moved due to this method call +LL | touch(&x[0]); + | ^ value borrowed here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `x` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | consume(x.clone().into_iter().next().unwrap()); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-block-bad.rs b/tests/ui/moves/moves-based-on-type-block-bad.rs new file mode 100644 index 000000000..eca33167f --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-block-bad.rs @@ -0,0 +1,29 @@ +#![feature(box_patterns)] + + +struct S { + x: Box +} + +enum E { + Foo(Box), + Bar(Box), + Baz +} + +fn f(s: &S, g: G) where G: FnOnce(&S) { + g(s) +} + +fn main() { + let s = S { x: Box::new(E::Bar(Box::new(42))) }; + loop { + f(&s, |hellothere| { + match hellothere.x { //~ ERROR cannot move out + box E::Foo(_) => {} + box E::Bar(x) => println!("{}", x.to_string()), + box E::Baz => {} + } + }) + } +} diff --git a/tests/ui/moves/moves-based-on-type-block-bad.stderr b/tests/ui/moves/moves-based-on-type-block-bad.stderr new file mode 100644 index 000000000..df09ababa --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-block-bad.stderr @@ -0,0 +1,20 @@ +error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is behind a shared reference + --> $DIR/moves-based-on-type-block-bad.rs:22:19 + | +LL | match hellothere.x { + | ^^^^^^^^^^^^ +LL | box E::Foo(_) => {} +LL | box E::Bar(x) => println!("{}", x.to_string()), + | - + | | + | data moved here + | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &hellothere.x { + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/moves-based-on-type-capture-clause-bad.rs b/tests/ui/moves/moves-based-on-type-capture-clause-bad.rs new file mode 100644 index 000000000..b2f68352f --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-capture-clause-bad.rs @@ -0,0 +1,9 @@ +use std::thread; + +fn main() { + let x = "Hello world!".to_string(); + thread::spawn(move|| { + println!("{}", x); + }); + println!("{}", x); //~ ERROR borrow of moved value +} diff --git a/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr b/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr new file mode 100644 index 000000000..34b7ea658 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-capture-clause-bad.stderr @@ -0,0 +1,18 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-capture-clause-bad.rs:8:20 + | +LL | let x = "Hello world!".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | thread::spawn(move|| { + | ------ value moved into closure here +LL | println!("{}", x); + | - variable moved due to use in closure +LL | }); +LL | println!("{}", x); + | ^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-capture-clause.rs b/tests/ui/moves/moves-based-on-type-capture-clause.rs new file mode 100644 index 000000000..4a6a4ed28 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-capture-clause.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let x = "Hello world!".to_string(); + thread::spawn(move|| { + println!("{}", x); + }).join(); +} diff --git a/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs b/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs new file mode 100644 index 000000000..4417fb926 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.rs @@ -0,0 +1,20 @@ +// Test for a subtle failure computing kinds of cyclic types, in which +// temporary kinds wound up being stored in a cache and used later. +// See rustc::ty::type_contents() for more information. + + +struct List { key: isize, next: Option> } + +fn foo(node: Box) -> isize { + let r = match node.next { + Some(right) => consume(right), + None => 0 + }; + consume(node) + r //~ ERROR use of partially moved value: `node` +} + +fn consume(v: Box) -> isize { + v.key +} + +fn main() {} diff --git a/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr new file mode 100644 index 000000000..db4382b58 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of partially moved value: `node` + --> $DIR/moves-based-on-type-cyclic-types-issue-4821.rs:13:13 + | +LL | Some(right) => consume(right), + | ----- value partially moved here +... +LL | consume(node) + r + | ^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref right) => consume(right), + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs b/tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs new file mode 100644 index 000000000..d256e18b6 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.rs @@ -0,0 +1,49 @@ +// Tests that references to move-by-default values trigger moves when +// they occur as part of various kinds of expressions. + +struct Foo { f: A } +fn touch(_a: &A) {} + +fn f00() { + let x = "hi".to_string(); + //~^ NOTE move occurs because `x` has type `String` + let _y = Foo { f:x }; + //~^ NOTE value moved here + touch(&x); //~ ERROR borrow of moved value: `x` + //~^ NOTE value borrowed here after move +} + +fn f05() { + let x = "hi".to_string(); + //~^ NOTE move occurs because `x` has type `String` + let _y = Foo { f:(((x))) }; + //~^ NOTE value moved here + touch(&x); //~ ERROR borrow of moved value: `x` + //~^ NOTE value borrowed here after move +} + +fn f10() { + let x = "hi".to_string(); + let _y = Foo { f:x.clone() }; + touch(&x); +} + +fn f20() { + let x = "hi".to_string(); + let _y = Foo { f:(x).clone() }; + touch(&x); +} + +fn f30() { + let x = "hi".to_string(); + let _y = Foo { f:((x)).clone() }; + touch(&x); +} + +fn f40() { + let x = "hi".to_string(); + let _y = Foo { f:(((((((x)).clone()))))) }; + touch(&x); +} + +fn main() {} diff --git a/tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr b/tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr new file mode 100644 index 000000000..0930df148 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr @@ -0,0 +1,37 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:12:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | +LL | let _y = Foo { f:x }; + | - value moved here +LL | +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = Foo { f:x.clone() }; + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:21:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | +LL | let _y = Foo { f:(((x))) }; + | ------- value moved here +LL | +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = Foo { f:(((x))).clone() }; + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-exprs.rs b/tests/ui/moves/moves-based-on-type-exprs.rs new file mode 100644 index 000000000..4a52d8d32 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-exprs.rs @@ -0,0 +1,93 @@ +// Tests that references to move-by-default values trigger moves when +// they occur as part of various kinds of expressions. + + +struct Foo { f: A } +fn guard(_s: String) -> bool {panic!()} +fn touch(_a: &A) {} + +fn f10() { + let x = "hi".to_string(); + let _y = Foo { f:x }; + touch(&x); //~ ERROR borrow of moved value: `x` +} + +fn f20() { + let x = "hi".to_string(); + let _y = (x, 3); + touch(&x); //~ ERROR borrow of moved value: `x` +} + +fn f21() { + let x = vec![1, 2, 3]; + let _y = (x[0], 3); + touch(&x); +} + +fn f30(cond: bool) { + let x = "hi".to_string(); + let y = "ho".to_string(); + let _y = if cond { + x + } else { + y + }; + touch(&x); //~ ERROR borrow of moved value: `x` + touch(&y); //~ ERROR borrow of moved value: `y` +} + +fn f40(cond: bool) { + let x = "hi".to_string(); + let y = "ho".to_string(); + let _y = match cond { + true => x, + false => y + }; + touch(&x); //~ ERROR borrow of moved value: `x` + touch(&y); //~ ERROR borrow of moved value: `y` +} + +fn f50(cond: bool) { + let x = "hi".to_string(); + let y = "ho".to_string(); + let _y = match cond { + _ if guard(x) => 10, + true => 10, + false => 20, + }; + touch(&x); //~ ERROR borrow of moved value: `x` + touch(&y); +} + +fn f70() { + let x = "hi".to_string(); + let _y = [x]; + touch(&x); //~ ERROR borrow of moved value: `x` +} + +fn f80() { + let x = "hi".to_string(); + let _y = vec![x]; + touch(&x); //~ ERROR borrow of moved value: `x` +} + +fn f100() { + let x = vec!["hi".to_string()]; + let _y = x.into_iter().next().unwrap(); + touch(&x); //~ ERROR borrow of moved value: `x` +} + +fn f110() { + let x = vec!["hi".to_string()]; + let _y = [x.into_iter().next().unwrap(); 1]; + touch(&x); //~ ERROR borrow of moved value: `x` +} + +fn f120() { + let mut x = vec!["hi".to_string(), "ho".to_string()]; + x.swap(0, 1); + touch(&x[0]); + touch(&x[1]); +} + +fn main() {} diff --git a/tests/ui/moves/moves-based-on-type-exprs.stderr b/tests/ui/moves/moves-based-on-type-exprs.stderr new file mode 100644 index 000000000..ab7c27456 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-exprs.stderr @@ -0,0 +1,189 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:12:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let _y = Foo { f:x }; + | - value moved here +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = Foo { f:x.clone() }; + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:18:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let _y = (x, 3); + | - value moved here +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = (x.clone(), 3); + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:35:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +... +LL | x + | - value moved here +... +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x.clone() + | ++++++++ + +error[E0382]: borrow of moved value: `y` + --> $DIR/moves-based-on-type-exprs.rs:36:11 + | +LL | let y = "ho".to_string(); + | - move occurs because `y` has type `String`, which does not implement the `Copy` trait +... +LL | y + | - value moved here +... +LL | touch(&y); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | y.clone() + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:46:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +... +LL | true => x, + | - value moved here +... +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | true => x.clone(), + | ++++++++ + +error[E0382]: borrow of moved value: `y` + --> $DIR/moves-based-on-type-exprs.rs:47:11 + | +LL | let y = "ho".to_string(); + | - move occurs because `y` has type `String`, which does not implement the `Copy` trait +... +LL | false => y + | - value moved here +... +LL | touch(&y); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false => y.clone() + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:58:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +... +LL | _ if guard(x) => 10, + | - value moved here +... +LL | touch(&x); + | ^^ value borrowed here after move + | +note: consider changing this parameter type in function `guard` to borrow instead if owning the value isn't necessary + --> $DIR/moves-based-on-type-exprs.rs:6:14 + | +LL | fn guard(_s: String) -> bool {panic!()} + | ----- ^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | _ if guard(x.clone()) => 10, + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:65:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let _y = [x]; + | - value moved here +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = [x.clone()]; + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:71:11 + | +LL | let x = "hi".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let _y = vec![x]; + | - value moved here +LL | touch(&x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = vec![x.clone()]; + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:77:11 + | +LL | let x = vec!["hi".to_string()]; + | - move occurs because `x` has type `Vec`, which does not implement the `Copy` trait +LL | let _y = x.into_iter().next().unwrap(); + | ----------- `x` moved due to this method call +LL | touch(&x); + | ^^ value borrowed here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `x` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | let _y = x.clone().into_iter().next().unwrap(); + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/moves-based-on-type-exprs.rs:83:11 + | +LL | let x = vec!["hi".to_string()]; + | - move occurs because `x` has type `Vec`, which does not implement the `Copy` trait +LL | let _y = [x.into_iter().next().unwrap(); 1]; + | ----------- `x` moved due to this method call +LL | touch(&x); + | ^^ value borrowed here after move + | +note: `into_iter` takes ownership of the receiver `self`, which moves `x` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | let _y = [x.clone().into_iter().next().unwrap(); 1]; + | ++++++++ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-match-bindings.rs b/tests/ui/moves/moves-based-on-type-match-bindings.rs new file mode 100644 index 000000000..4fb9b40e8 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-match-bindings.rs @@ -0,0 +1,21 @@ +// Tests that bindings to move-by-default values trigger moves of the +// discriminant. Also tests that the compiler explains the move in +// terms of the binding, not the discriminant. + +struct Foo { f: A } +fn guard(_s: String) -> bool {panic!()} +fn touch(_a: &A) {} + +fn f10() { + let x = Foo {f: "hi".to_string()}; + + let y = match x { + Foo {f} => {} + }; + + touch(&x); //~ ERROR borrow of partially moved value: `x` + //~^ value borrowed here after partial move + //~| partial move occurs because `x.f` has type `String` +} + +fn main() {} diff --git a/tests/ui/moves/moves-based-on-type-match-bindings.stderr b/tests/ui/moves/moves-based-on-type-match-bindings.stderr new file mode 100644 index 000000000..225935532 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-match-bindings.stderr @@ -0,0 +1,18 @@ +error[E0382]: borrow of partially moved value: `x` + --> $DIR/moves-based-on-type-match-bindings.rs:16:11 + | +LL | Foo {f} => {} + | - value partially moved here +... +LL | touch(&x); + | ^^ value borrowed here after partial move + | + = note: partial move occurs because `x.f` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo {ref f} => {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs new file mode 100644 index 000000000..490d91ac1 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.rs @@ -0,0 +1,10 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn>(f: F) -> F { f } + +fn test(_x: Box) {} + +fn main() { + let i = Box::new(3); + let _f = to_fn(|| test(i)); //~ ERROR cannot move out +} diff --git a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr new file mode 100644 index 000000000..125e446c3 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr @@ -0,0 +1,13 @@ +error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure + --> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:9:28 + | +LL | let i = Box::new(3); + | - captured outer variable +LL | let _f = to_fn(|| test(i)); + | -- ^ move occurs because `i` has type `Box`, which does not implement the `Copy` trait + | | + | captured by this `Fn` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs new file mode 100644 index 000000000..86fd37e78 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.rs @@ -0,0 +1,35 @@ +// Tests correct kind-checking of the reason stack closures without the :Copy +// bound must be noncopyable. For details see +// https://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/ + +struct R<'a> { + // This struct is needed to create the + // otherwise infinite type of a fn that + // accepts itself as argument: + c: Box +} + +fn innocent_looking_victim() { + let mut x = Some("hello".to_string()); + conspirator(|f, writer| { + if writer { + x = None; + } else { + match x { + Some(ref msg) => { + (f.c)(f, true); + //~^ ERROR: cannot borrow `*f` as mutable more than once at a time + println!("{}", msg); + }, + None => panic!("oops"), + } + } + }) +} + +fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { + let mut r = R {c: Box::new(f)}; + f(&mut r, false) //~ ERROR borrow of moved value +} + +fn main() { innocent_looking_victim() } diff --git a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr new file mode 100644 index 000000000..4759b4589 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr @@ -0,0 +1,28 @@ +error[E0499]: cannot borrow `*f` as mutable more than once at a time + --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:20:27 + | +LL | (f.c)(f, true); + | ----- ^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call + +error[E0382]: borrow of moved value: `f` + --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:32:5 + | +LL | fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { + | ----- move occurs because `f` has type `F`, which does not implement the `Copy` trait +LL | let mut r = R {c: Box::new(f)}; + | - value moved here +LL | f(&mut r, false) + | ^ value borrowed here after move + | +help: consider mutably borrowing `f` + | +LL | let mut r = R {c: Box::new(&mut f)}; + | ++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0499. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-based-on-type-tuple.rs b/tests/ui/moves/moves-based-on-type-tuple.rs new file mode 100644 index 000000000..2e67d8f8a --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-tuple.rs @@ -0,0 +1,10 @@ +fn dup(x: Box) -> Box<(Box,Box)> { + + + Box::new((x, x)) + //~^ use of moved value: `x` [E0382] +} + +fn main() { + dup(Box::new(3)); +} diff --git a/tests/ui/moves/moves-based-on-type-tuple.stderr b/tests/ui/moves/moves-based-on-type-tuple.stderr new file mode 100644 index 000000000..0bcce3012 --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-tuple.stderr @@ -0,0 +1,19 @@ +error[E0382]: use of moved value: `x` + --> $DIR/moves-based-on-type-tuple.rs:4:18 + | +LL | fn dup(x: Box) -> Box<(Box,Box)> { + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | Box::new((x, x)) + | - ^ value used here after move + | | + | value moved here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Box::new((x.clone(), x)) + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/moves-sru-moved-field.rs b/tests/ui/moves/moves-sru-moved-field.rs new file mode 100644 index 000000000..72957c49f --- /dev/null +++ b/tests/ui/moves/moves-sru-moved-field.rs @@ -0,0 +1,23 @@ +type Noncopyable = Box; + + + +struct Foo { + copied: isize, + moved: Box, + noncopyable: Noncopyable +} + +fn test0(f: Foo, g: Noncopyable, h: Noncopyable) { + // just copy implicitly copyable fields from `f`, no moves: + let _b = Foo {moved: Box::new(1), noncopyable: g, ..f}; + let _c = Foo {moved: Box::new(2), noncopyable: h, ..f}; +} + +fn test1(f: Foo, g: Noncopyable, h: Noncopyable) { + // copying move-by-default fields from `f`, so move: + let _b = Foo {noncopyable: g, ..f}; + let _c = Foo {noncopyable: h, ..f}; //~ ERROR use of moved value: `f.moved` +} + +fn main() {} diff --git a/tests/ui/moves/moves-sru-moved-field.stderr b/tests/ui/moves/moves-sru-moved-field.stderr new file mode 100644 index 000000000..cf7213637 --- /dev/null +++ b/tests/ui/moves/moves-sru-moved-field.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `f.moved` + --> $DIR/moves-sru-moved-field.rs:20:14 + | +LL | let _b = Foo {noncopyable: g, ..f}; + | ------------------------- value moved here +LL | let _c = Foo {noncopyable: h, ..f}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `f.moved` has type `Box`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/pin-mut-reborrow.fixed b/tests/ui/moves/pin-mut-reborrow.fixed new file mode 100644 index 000000000..e808186d7 --- /dev/null +++ b/tests/ui/moves/pin-mut-reborrow.fixed @@ -0,0 +1,15 @@ +// run-rustfix +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn foo(self: Pin<&mut Self>) {} +} + +fn main() { + let mut foo = Foo; + let mut foo = Pin::new(&mut foo); + foo.as_mut().foo(); + foo.foo(); //~ ERROR use of moved value +} diff --git a/tests/ui/moves/pin-mut-reborrow.rs b/tests/ui/moves/pin-mut-reborrow.rs new file mode 100644 index 000000000..fee6236eb --- /dev/null +++ b/tests/ui/moves/pin-mut-reborrow.rs @@ -0,0 +1,15 @@ +// run-rustfix +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn foo(self: Pin<&mut Self>) {} +} + +fn main() { + let mut foo = Foo; + let mut foo = Pin::new(&mut foo); + foo.foo(); + foo.foo(); //~ ERROR use of moved value +} diff --git a/tests/ui/moves/pin-mut-reborrow.stderr b/tests/ui/moves/pin-mut-reborrow.stderr new file mode 100644 index 000000000..16fa4bacc --- /dev/null +++ b/tests/ui/moves/pin-mut-reborrow.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/pin-mut-reborrow.rs:14:5 + | +LL | let mut foo = Pin::new(&mut foo); + | ------- move occurs because `foo` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait +LL | foo.foo(); + | ----- `foo` moved due to this method call +LL | foo.foo(); + | ^^^ value used here after move + | +note: `Foo::foo` takes ownership of the receiver `self`, which moves `foo` + --> $DIR/pin-mut-reborrow.rs:7:12 + | +LL | fn foo(self: Pin<&mut Self>) {} + | ^^^^ +help: consider reborrowing the `Pin` instead of moving it + | +LL | foo.as_mut().foo(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/suggest-clone.fixed b/tests/ui/moves/suggest-clone.fixed new file mode 100644 index 000000000..204bfdb10 --- /dev/null +++ b/tests/ui/moves/suggest-clone.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +#[derive(Clone)] +struct Foo; +impl Foo { + fn foo(self) {} +} +fn main() { + let foo = &Foo; + foo.clone().foo(); //~ ERROR cannot move out +} diff --git a/tests/ui/moves/suggest-clone.rs b/tests/ui/moves/suggest-clone.rs new file mode 100644 index 000000000..25dd9f006 --- /dev/null +++ b/tests/ui/moves/suggest-clone.rs @@ -0,0 +1,11 @@ +// run-rustfix + +#[derive(Clone)] +struct Foo; +impl Foo { + fn foo(self) {} +} +fn main() { + let foo = &Foo; + foo.foo(); //~ ERROR cannot move out +} diff --git a/tests/ui/moves/suggest-clone.stderr b/tests/ui/moves/suggest-clone.stderr new file mode 100644 index 000000000..cbb3dfea3 --- /dev/null +++ b/tests/ui/moves/suggest-clone.stderr @@ -0,0 +1,22 @@ +error[E0507]: cannot move out of `*foo` which is behind a shared reference + --> $DIR/suggest-clone.rs:10:5 + | +LL | foo.foo(); + | ^^^^----- + | | | + | | `*foo` moved due to this method call + | move occurs because `*foo` has type `Foo`, which does not implement the `Copy` trait + | +note: `Foo::foo` takes ownership of the receiver `self`, which moves `*foo` + --> $DIR/suggest-clone.rs:6:12 + | +LL | fn foo(self) {} + | ^^^^ +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | foo.clone().foo(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/moves/use_of_moved_value_clone_suggestions.rs b/tests/ui/moves/use_of_moved_value_clone_suggestions.rs new file mode 100644 index 000000000..d5c8d4e6b --- /dev/null +++ b/tests/ui/moves/use_of_moved_value_clone_suggestions.rs @@ -0,0 +1,6 @@ +// `Rc` is not ever `Copy`, we should not suggest adding `T: Copy` constraint +fn duplicate_rc(t: std::rc::Rc) -> (std::rc::Rc, std::rc::Rc) { + (t, t) //~ use of moved value: `t` +} + +fn main() {} diff --git a/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr b/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr new file mode 100644 index 000000000..22e7951db --- /dev/null +++ b/tests/ui/moves/use_of_moved_value_clone_suggestions.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_clone_suggestions.rs:3:9 + | +LL | fn duplicate_rc(t: std::rc::Rc) -> (std::rc::Rc, std::rc::Rc) { + | - move occurs because `t` has type `Rc`, which does not implement the `Copy` trait +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | (t.clone(), t) + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed new file mode 100644 index 000000000..45acf5beb --- /dev/null +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -0,0 +1,86 @@ +// run-rustfix +#![allow(dead_code)] + +fn duplicate_t(t: T) -> (T, T) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_opt(t: Option) -> (Option, Option) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + //~^ HELP consider restricting type parameters + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom(t: S) -> (S, S) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +struct S(T); +trait Trait {} +impl Clone for S { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +impl Copy for S {} + +trait A {} +trait B {} + +// Test where bounds are added with different bound placements +fn duplicate_custom_1(t: S) -> (S, S) where { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_2(t: S) -> (S, S) +where + T: A + Copy + Trait, + //~^ HELP consider further restricting this bound +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_3(t: S) -> (S, S) +where + T: A + Copy + Trait, + //~^ HELP consider further restricting this bound + T: B, +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_4(t: S) -> (S, S) +//~^ HELP consider further restricting this bound +where + T: B, +{ + (t, t) //~ use of moved value: `t` +} + +#[rustfmt::skip] +fn existing_colon(t: T) { + //~^ HELP consider restricting type parameter `T` + [t, t]; //~ use of moved value: `t` +} + +fn existing_colon_in_where(t: T) +where + T:, T: Copy + //~^ HELP consider further restricting type parameter `T` +{ + [t, t]; //~ use of moved value: `t` +} + +fn main() {} diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs new file mode 100644 index 000000000..0a43dd1a9 --- /dev/null +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs @@ -0,0 +1,86 @@ +// run-rustfix +#![allow(dead_code)] + +fn duplicate_t(t: T) -> (T, T) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_opt(t: Option) -> (Option, Option) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + //~^ HELP consider restricting type parameters + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom(t: S) -> (S, S) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +struct S(T); +trait Trait {} +impl Clone for S { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +impl Copy for S {} + +trait A {} +trait B {} + +// Test where bounds are added with different bound placements +fn duplicate_custom_1(t: S) -> (S, S) where { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_2(t: S) -> (S, S) +where + T: A, + //~^ HELP consider further restricting this bound +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_3(t: S) -> (S, S) +where + T: A, + //~^ HELP consider further restricting this bound + T: B, +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_4(t: S) -> (S, S) +//~^ HELP consider further restricting this bound +where + T: B, +{ + (t, t) //~ use of moved value: `t` +} + +#[rustfmt::skip] +fn existing_colon(t: T) { + //~^ HELP consider restricting type parameter `T` + [t, t]; //~ use of moved value: `t` +} + +fn existing_colon_in_where(t: T) +where + T:, + //~^ HELP consider further restricting type parameter `T` +{ + [t, t]; //~ use of moved value: `t` +} + +fn main() {} diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr new file mode 100644 index 000000000..3e37fcb21 --- /dev/null +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -0,0 +1,179 @@ +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:6:9 + | +LL | fn duplicate_t(t: T) -> (T, T) { + | - move occurs because `t` has type `T`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_t(t: T) -> (T, T) { + | ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:11:9 + | +LL | fn duplicate_opt(t: Option) -> (Option, Option) { + | - move occurs because `t` has type `Option`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_opt(t: Option) -> (Option, Option) { + | ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:16:9 + | +LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + | - move occurs because `t` has type `(T,)`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + | ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:21:9 + | +LL | fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + | - move occurs because `t` has type `(A, B)`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameters + | +LL | fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + | ++++++ ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:26:9 + | +LL | fn duplicate_custom(t: S) -> (S, S) { + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_custom(t: S) -> (S, S) { + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:44:9 + | +LL | fn duplicate_custom_1(t: S) -> (S, S) where { + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_custom_1(t: S) -> (S, S) where { + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:52:9 + | +LL | fn duplicate_custom_2(t: S) -> (S, S) + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +... +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting this bound + | +LL | T: A + Copy + Trait, + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:61:9 + | +LL | fn duplicate_custom_3(t: S) -> (S, S) + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +... +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting this bound + | +LL | T: A + Copy + Trait, + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:69:9 + | +LL | fn duplicate_custom_4(t: S) -> (S, S) + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +... +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting this bound + | +LL | fn duplicate_custom_4(t: S) -> (S, S) + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:75:9 + | +LL | fn existing_colon(t: T) { + | - move occurs because `t` has type `T`, which does not implement the `Copy` trait +LL | +LL | [t, t]; + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn existing_colon(t: T) { + | ++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:83:9 + | +LL | fn existing_colon_in_where(t: T) + | - move occurs because `t` has type `T`, which does not implement the `Copy` trait +... +LL | [t, t]; + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting type parameter `T` + | +LL | T:, T: Copy + | ~~~~~~~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/msvc-data-only.rs b/tests/ui/msvc-data-only.rs new file mode 100644 index 000000000..f668b0b06 --- /dev/null +++ b/tests/ui/msvc-data-only.rs @@ -0,0 +1,8 @@ +// run-pass +// aux-build:msvc-data-only-lib.rs + +extern crate msvc_data_only_lib; + +fn main() { + println!("The answer is {} !", msvc_data_only_lib::FOO); +} diff --git a/tests/ui/multibyte.rs b/tests/ui/multibyte.rs new file mode 100644 index 000000000..7e3a577f9 --- /dev/null +++ b/tests/ui/multibyte.rs @@ -0,0 +1,7 @@ +// run-pass +// + +// Test that multibyte characters don't crash the compiler +pub fn main() { + println!("마ì´ë„ˆìŠ¤ 사ì¸ì´ 없으면"); +} diff --git a/tests/ui/multiline-comment.rs b/tests/ui/multiline-comment.rs new file mode 100644 index 000000000..01aaac282 --- /dev/null +++ b/tests/ui/multiline-comment.rs @@ -0,0 +1,7 @@ +// run-pass +// pretty-expanded FIXME #23616 + +/* + * This is a multi-line oldcomment. + */ +pub fn main() { } diff --git a/tests/ui/mut-function-arguments.rs b/tests/ui/mut-function-arguments.rs new file mode 100644 index 000000000..1e682fc4b --- /dev/null +++ b/tests/ui/mut-function-arguments.rs @@ -0,0 +1,19 @@ +// run-pass + +fn f(mut y: Box) { + *y = 5; + assert_eq!(*y, 5); +} + +fn g() { + let frob = |mut q: Box| { *q = 2; assert_eq!(*q, 2); }; + let w = Box::new(37); + frob(w); + +} + +pub fn main() { + let z = Box::new(17); + f(z); + g(); +} diff --git a/tests/ui/mut/mut-cant-alias.rs b/tests/ui/mut/mut-cant-alias.rs new file mode 100644 index 000000000..9146b931a --- /dev/null +++ b/tests/ui/mut/mut-cant-alias.rs @@ -0,0 +1,14 @@ +use std::cell::RefCell; + + + +fn main() { + let m = RefCell::new(0); + let mut b = m.borrow_mut(); + let b1 = &mut *b; + let b2 = &mut *b; //~ ERROR cannot borrow + b1.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/mut/mut-cant-alias.stderr b/tests/ui/mut/mut-cant-alias.stderr new file mode 100644 index 000000000..6046c076f --- /dev/null +++ b/tests/ui/mut/mut-cant-alias.stderr @@ -0,0 +1,13 @@ +error[E0499]: cannot borrow `b` as mutable more than once at a time + --> $DIR/mut-cant-alias.rs:9:20 + | +LL | let b1 = &mut *b; + | - first mutable borrow occurs here +LL | let b2 = &mut *b; + | ^ second mutable borrow occurs here +LL | b1.use_mut(); + | ------------ first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/mut/mut-cross-borrowing.rs b/tests/ui/mut/mut-cross-borrowing.rs new file mode 100644 index 000000000..080faab73 --- /dev/null +++ b/tests/ui/mut/mut-cross-borrowing.rs @@ -0,0 +1,8 @@ +fn f(_: &mut isize) {} + +fn main() { + + let mut x: Box<_> = Box::new(3); + + f(x) //~ ERROR mismatched types +} diff --git a/tests/ui/mut/mut-cross-borrowing.stderr b/tests/ui/mut/mut-cross-borrowing.stderr new file mode 100644 index 000000000..ee739d628 --- /dev/null +++ b/tests/ui/mut/mut-cross-borrowing.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/mut-cross-borrowing.rs:7:7 + | +LL | f(x) + | - ^ + | | | + | | expected `&mut isize`, found struct `Box` + | | help: consider mutably borrowing here: `&mut x` + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut isize` + found struct `Box<{integer}>` +note: function defined here + --> $DIR/mut-cross-borrowing.rs:1:4 + | +LL | fn f(_: &mut isize) {} + | ^ ------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mut/mut-pattern-internal-mutability.rs b/tests/ui/mut/mut-pattern-internal-mutability.rs new file mode 100644 index 000000000..bcee878e3 --- /dev/null +++ b/tests/ui/mut/mut-pattern-internal-mutability.rs @@ -0,0 +1,15 @@ +fn main() { + let foo = &mut 1; + + let &mut x = foo; + x += 1; //~ ERROR cannot assign twice to immutable variable `x` + + // explicitly mut-ify internals + let &mut mut x = foo; + x += 1; + + // check borrowing is detected successfully + let &mut ref x = foo; + *foo += 1; //~ ERROR cannot assign to `*foo` because it is borrowed + drop(x); +} diff --git a/tests/ui/mut/mut-pattern-internal-mutability.stderr b/tests/ui/mut/mut-pattern-internal-mutability.stderr new file mode 100644 index 000000000..6583546aa --- /dev/null +++ b/tests/ui/mut/mut-pattern-internal-mutability.stderr @@ -0,0 +1,25 @@ +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/mut-pattern-internal-mutability.rs:5:5 + | +LL | let &mut x = foo; + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x += 1; + | ^^^^^^ cannot assign twice to immutable variable + +error[E0506]: cannot assign to `*foo` because it is borrowed + --> $DIR/mut-pattern-internal-mutability.rs:13:5 + | +LL | let &mut ref x = foo; + | ----- borrow of `*foo` occurs here +LL | *foo += 1; + | ^^^^^^^^^ assignment to borrowed `*foo` occurs here +LL | drop(x); + | - borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0384, E0506. +For more information about an error, try `rustc --explain E0384`. diff --git a/tests/ui/mut/mut-pattern-mismatched.rs b/tests/ui/mut/mut-pattern-mismatched.rs new file mode 100644 index 000000000..700261fe4 --- /dev/null +++ b/tests/ui/mut/mut-pattern-mismatched.rs @@ -0,0 +1,20 @@ +fn main() { + let foo = &mut 1; + + // (separate lines to ensure the spans are accurate) + + let &_ //~ ERROR mismatched types + //~| expected mutable reference `&mut {integer}` + //~| found reference `&_` + //~| types differ in mutability + = foo; + let &mut _ = foo; + + let bar = &1; + let &_ = bar; + let &mut _ //~ ERROR mismatched types + //~| expected reference `&{integer}` + //~| found mutable reference `&mut _` + //~| types differ in mutability + = bar; +} diff --git a/tests/ui/mut/mut-pattern-mismatched.stderr b/tests/ui/mut/mut-pattern-mismatched.stderr new file mode 100644 index 000000000..cad1cef51 --- /dev/null +++ b/tests/ui/mut/mut-pattern-mismatched.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/mut-pattern-mismatched.rs:6:10 + | +LL | let &_ + | ^^ types differ in mutability +... +LL | = foo; + | --- this expression has type `&mut {integer}` + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/mut-pattern-mismatched.rs:15:9 + | +LL | let &mut _ + | ^^^^^^ types differ in mutability +... +LL | = bar; + | --- this expression has type `&{integer}` + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mut/mut-ref.rs b/tests/ui/mut/mut-ref.rs new file mode 100644 index 000000000..80990b2bf --- /dev/null +++ b/tests/ui/mut/mut-ref.rs @@ -0,0 +1,4 @@ +fn main() { + let mut ref x = 10; //~ ERROR the order of `mut` and `ref` is incorrect + let ref mut y = 11; +} diff --git a/tests/ui/mut/mut-ref.stderr b/tests/ui/mut/mut-ref.stderr new file mode 100644 index 000000000..e6d4901aa --- /dev/null +++ b/tests/ui/mut/mut-ref.stderr @@ -0,0 +1,8 @@ +error: the order of `mut` and `ref` is incorrect + --> $DIR/mut-ref.rs:2:9 + | +LL | let mut ref x = 10; + | ^^^^^^^ help: try switching the order: `ref mut` + +error: aborting due to previous error + diff --git a/tests/ui/mut/mut-suggestion.rs b/tests/ui/mut/mut-suggestion.rs new file mode 100644 index 000000000..8c269d1e7 --- /dev/null +++ b/tests/ui/mut/mut-suggestion.rs @@ -0,0 +1,22 @@ +#[derive(Copy, Clone)] +struct S; + +impl S { + fn mutate(&mut self) { + } +} + +fn func(arg: S) { + //~^ HELP consider changing this to be mutable + //~| SUGGESTION mut + arg.mutate(); + //~^ ERROR cannot borrow `arg` as mutable, as it is not declared as mutable +} + +fn main() { + let local = S; + //~^ HELP consider changing this to be mutable + //~| SUGGESTION mut + local.mutate(); + //~^ ERROR cannot borrow `local` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/mut/mut-suggestion.stderr b/tests/ui/mut/mut-suggestion.stderr new file mode 100644 index 000000000..d89c8b413 --- /dev/null +++ b/tests/ui/mut/mut-suggestion.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable + --> $DIR/mut-suggestion.rs:12:5 + | +LL | arg.mutate(); + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn func(mut arg: S) { + | +++ + +error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable + --> $DIR/mut-suggestion.rs:20:5 + | +LL | local.mutate(); + | ^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut local = S; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/mut/mutable-class-fields-2.rs b/tests/ui/mut/mutable-class-fields-2.rs new file mode 100644 index 000000000..30e54dfc9 --- /dev/null +++ b/tests/ui/mut/mutable-class-fields-2.rs @@ -0,0 +1,24 @@ +struct Cat { + meows : usize, + + how_hungry : isize, +} + +impl Cat { + pub fn eat(&self) { + self.how_hungry -= 5; //~ ERROR cannot assign + } + +} + +fn cat(in_x : usize, in_y : isize) -> Cat { + Cat { + meows: in_x, + how_hungry: in_y + } +} + +fn main() { + let nyan : Cat = cat(52, 99); + nyan.eat(); +} diff --git a/tests/ui/mut/mutable-class-fields-2.stderr b/tests/ui/mut/mutable-class-fields-2.stderr new file mode 100644 index 000000000..c53c6ea30 --- /dev/null +++ b/tests/ui/mut/mutable-class-fields-2.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference + --> $DIR/mutable-class-fields-2.rs:9:5 + | +LL | self.how_hungry -= 5; + | ^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | pub fn eat(&mut self) { + | ~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/mut/mutable-class-fields.rs b/tests/ui/mut/mutable-class-fields.rs new file mode 100644 index 000000000..30768a1ec --- /dev/null +++ b/tests/ui/mut/mutable-class-fields.rs @@ -0,0 +1,16 @@ +struct Cat { + meows : usize, + how_hungry : isize, +} + +fn cat(in_x : usize, in_y : isize) -> Cat { + Cat { + meows: in_x, + how_hungry: in_y + } +} + +fn main() { + let nyan : Cat = cat(52, 99); + nyan.how_hungry = 0; //~ ERROR cannot assign +} diff --git a/tests/ui/mut/mutable-class-fields.stderr b/tests/ui/mut/mutable-class-fields.stderr new file mode 100644 index 000000000..1d731be8a --- /dev/null +++ b/tests/ui/mut/mutable-class-fields.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable + --> $DIR/mutable-class-fields.rs:15:3 + | +LL | nyan.how_hungry = 0; + | ^^^^^^^^^^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut nyan : Cat = cat(52, 99); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/mut/mutable-enum-indirect.rs b/tests/ui/mut/mutable-enum-indirect.rs new file mode 100644 index 000000000..502859c04 --- /dev/null +++ b/tests/ui/mut/mutable-enum-indirect.rs @@ -0,0 +1,19 @@ +// Tests that an `&` pointer to something inherently mutable is itself +// to be considered mutable. + +#![feature(negative_impls)] + +use std::marker::Sync; + +struct NoSync; +impl !Sync for NoSync {} + +enum Foo { A(NoSync) } + +fn bar(_: T) {} + +fn main() { + let x = Foo::A(NoSync); + bar(&x); + //~^ ERROR `NoSync` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr new file mode 100644 index 000000000..9e1f4e1fe --- /dev/null +++ b/tests/ui/mut/mutable-enum-indirect.stderr @@ -0,0 +1,24 @@ +error[E0277]: `NoSync` cannot be shared between threads safely + --> $DIR/mutable-enum-indirect.rs:17:9 + | +LL | bar(&x); + | --- ^^ `NoSync` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync` +note: required because it appears within the type `Foo` + --> $DIR/mutable-enum-indirect.rs:11:6 + | +LL | enum Foo { A(NoSync) } + | ^^^ + = note: required because it appears within the type `&Foo` +note: required by a bound in `bar` + --> $DIR/mutable-enum-indirect.rs:13:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mut/no-mut-lint-for-desugared-mut.rs b/tests/ui/mut/no-mut-lint-for-desugared-mut.rs new file mode 100644 index 000000000..419d58041 --- /dev/null +++ b/tests/ui/mut/no-mut-lint-for-desugared-mut.rs @@ -0,0 +1,8 @@ +// run-pass + +#![deny(unused_mut)] +#![allow(unreachable_code)] + +fn main() { + for _ in { return (); 0..3 } {} // ok +} diff --git a/tests/ui/mutexguard-sync.rs b/tests/ui/mutexguard-sync.rs new file mode 100644 index 000000000..b56418383 --- /dev/null +++ b/tests/ui/mutexguard-sync.rs @@ -0,0 +1,13 @@ +// MutexGuard> must not be Sync, that would be unsound. +use std::sync::Mutex; +use std::cell::Cell; + +fn test_sync(_t: T) {} + +fn main() +{ + let m = Mutex::new(Cell::new(0i32)); + let guard = m.lock().unwrap(); + test_sync(guard); + //~^ ERROR `Cell` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/mutexguard-sync.stderr b/tests/ui/mutexguard-sync.stderr new file mode 100644 index 000000000..3fbb2ddf1 --- /dev/null +++ b/tests/ui/mutexguard-sync.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Cell` cannot be shared between threads safely + --> $DIR/mutexguard-sync.rs:11:15 + | +LL | test_sync(guard); + | --------- ^^^^^ `Cell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `Cell` + = note: required for `MutexGuard<'_, Cell>` to implement `Sync` +note: required by a bound in `test_sync` + --> $DIR/mutexguard-sync.rs:5:17 + | +LL | fn test_sync(_t: T) {} + | ^^^^ required by this bound in `test_sync` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mutual-recursion-group.rs b/tests/ui/mutual-recursion-group.rs new file mode 100644 index 000000000..86b0f1d84 --- /dev/null +++ b/tests/ui/mutual-recursion-group.rs @@ -0,0 +1,16 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +enum colour { red, green, blue, } + +enum tree { children(Box), leaf(colour), } + +enum list { cons(Box, Box), nil, } + +enum small_list { kons(isize, Box), neel, } + +pub fn main() { } diff --git a/tests/ui/namespace/auxiliary/namespace-mix.rs b/tests/ui/namespace/auxiliary/namespace-mix.rs new file mode 100644 index 000000000..fb39d29f8 --- /dev/null +++ b/tests/ui/namespace/auxiliary/namespace-mix.rs @@ -0,0 +1,66 @@ +pub mod c { + pub struct S {} + pub struct TS(); + pub struct US; + pub enum E { + V {}, + TV(), + UV, + } + + pub struct Item; +} + +pub mod xm1 { + pub use ::c::*; + pub type S = ::c::Item; +} +pub mod xm2 { + pub use ::c::*; + pub const S: ::c::Item = ::c::Item; +} + +pub mod xm3 { + pub use ::c::*; + pub type TS = ::c::Item; +} +pub mod xm4 { + pub use ::c::*; + pub const TS: ::c::Item = ::c::Item; +} + +pub mod xm5 { + pub use ::c::*; + pub type US = ::c::Item; +} +pub mod xm6 { + pub use ::c::*; + pub const US: ::c::Item = ::c::Item; +} + +pub mod xm7 { + pub use ::c::E::*; + pub type V = ::c::Item; +} +pub mod xm8 { + pub use ::c::E::*; + pub const V: ::c::Item = ::c::Item; +} + +pub mod xm9 { + pub use ::c::E::*; + pub type TV = ::c::Item; +} +pub mod xmA { + pub use ::c::E::*; + pub const TV: ::c::Item = ::c::Item; +} + +pub mod xmB { + pub use ::c::E::*; + pub type UV = ::c::Item; +} +pub mod xmC { + pub use ::c::E::*; + pub const UV: ::c::Item = ::c::Item; +} diff --git a/tests/ui/namespace/auxiliary/namespaced_enums.rs b/tests/ui/namespace/auxiliary/namespaced_enums.rs new file mode 100644 index 000000000..d3548c76c --- /dev/null +++ b/tests/ui/namespace/auxiliary/namespaced_enums.rs @@ -0,0 +1,10 @@ +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} + pub fn bar(&self) {} +} diff --git a/tests/ui/namespace/namespace-mix.rs b/tests/ui/namespace/namespace-mix.rs new file mode 100644 index 000000000..c5b30f148 --- /dev/null +++ b/tests/ui/namespace/namespace-mix.rs @@ -0,0 +1,155 @@ +// aux-build:namespace-mix.rs + +extern crate namespace_mix; +use namespace_mix::*; + +mod c { + pub struct S {} + pub struct TS(); + pub struct US; + pub enum E { + V {}, + TV(), + UV, + } + + pub struct Item; +} + +// Use something emitting the type argument name, e.g., unsatisfied bound. +trait Impossible {} +fn check(_: T) {} + +mod m1 { + pub use ::c::*; + pub type S = ::c::Item; +} +mod m2 { + pub use ::c::*; + pub const S: ::c::Item = ::c::Item; +} + +fn f12() { + check(m1::S{}); //~ ERROR c::Item + check(m1::S); //~ ERROR expected value, found type alias `m1::S` + check(m2::S{}); //~ ERROR c::S + check(m2::S); //~ ERROR c::Item +} +fn xf12() { + check(xm1::S{}); //~ ERROR c::Item + check(xm1::S); //~ ERROR expected value, found type alias `xm1::S` + check(xm2::S{}); //~ ERROR c::S + check(xm2::S); //~ ERROR c::Item +} + +mod m3 { + pub use ::c::*; + pub type TS = ::c::Item; +} +mod m4 { + pub use ::c::*; + pub const TS: ::c::Item = ::c::Item; +} + +fn f34() { + check(m3::TS{}); //~ ERROR c::Item + check(m3::TS); //~ ERROR c::TS + check(m4::TS{}); //~ ERROR c::TS + check(m4::TS); //~ ERROR c::Item +} +fn xf34() { + check(xm3::TS{}); //~ ERROR c::Item + check(xm3::TS); //~ ERROR c::TS + check(xm4::TS{}); //~ ERROR c::TS + check(xm4::TS); //~ ERROR c::Item +} + +mod m5 { + pub use ::c::*; + pub type US = ::c::Item; +} +mod m6 { + pub use ::c::*; + pub const US: ::c::Item = ::c::Item; +} + +fn f56() { + check(m5::US{}); //~ ERROR c::Item + check(m5::US); //~ ERROR c::US + check(m6::US{}); //~ ERROR c::US + check(m6::US); //~ ERROR c::Item +} +fn xf56() { + check(xm5::US{}); //~ ERROR c::Item + check(xm5::US); //~ ERROR c::US + check(xm6::US{}); //~ ERROR c::US + check(xm6::US); //~ ERROR c::Item +} + +mod m7 { + pub use ::c::E::*; + pub type V = ::c::Item; +} +mod m8 { + pub use ::c::E::*; + pub const V: ::c::Item = ::c::Item; +} + +fn f78() { + check(m7::V{}); //~ ERROR c::Item + check(m7::V); //~ ERROR expected value, found type alias `m7::V` + check(m8::V{}); //~ ERROR c::E + check(m8::V); //~ ERROR c::Item +} +fn xf78() { + check(xm7::V{}); //~ ERROR c::Item + check(xm7::V); //~ ERROR expected value, found type alias `xm7::V` + check(xm8::V{}); //~ ERROR c::E + check(xm8::V); //~ ERROR c::Item +} + +mod m9 { + pub use ::c::E::*; + pub type TV = ::c::Item; +} +mod mA { + pub use ::c::E::*; + pub const TV: ::c::Item = ::c::Item; +} + +fn f9A() { + check(m9::TV{}); //~ ERROR c::Item + check(m9::TV); //~ ERROR c::E + check(mA::TV{}); //~ ERROR c::E + check(mA::TV); //~ ERROR c::Item +} +fn xf9A() { + check(xm9::TV{}); //~ ERROR c::Item + check(xm9::TV); //~ ERROR c::E + check(xmA::TV{}); //~ ERROR c::E + check(xmA::TV); //~ ERROR c::Item +} + +mod mB { + pub use ::c::E::*; + pub type UV = ::c::Item; +} +mod mC { + pub use ::c::E::*; + pub const UV: ::c::Item = ::c::Item; +} + +fn fBC() { + check(mB::UV{}); //~ ERROR c::Item + check(mB::UV); //~ ERROR c::E + check(mC::UV{}); //~ ERROR c::E + check(mC::UV); //~ ERROR c::Item +} +fn xfBC() { + check(xmB::UV{}); //~ ERROR c::Item + check(xmB::UV); //~ ERROR c::E + check(xmC::UV{}); //~ ERROR c::E + check(xmC::UV); //~ ERROR c::Item +} + +fn main() {} diff --git a/tests/ui/namespace/namespace-mix.stderr b/tests/ui/namespace/namespace-mix.stderr new file mode 100644 index 000000000..cb72d4a1c --- /dev/null +++ b/tests/ui/namespace/namespace-mix.stderr @@ -0,0 +1,728 @@ +error[E0423]: expected value, found type alias `m1::S` + --> $DIR/namespace-mix.rs:34:11 + | +LL | pub struct TS(); + | ---------------- similarly named tuple struct `TS` defined here +... +LL | check(m1::S); + | ^^^^^ + | + = note: can't use a type alias as a constructor +help: a tuple struct with a similar name exists + | +LL | check(m1::TS); + | ~~ +help: consider importing one of these items instead + | +LL | use m2::S; + | +LL | use xm2::S; + | +help: if you import `S`, refer to it directly + | +LL - check(m1::S); +LL + check(S); + | + +error[E0423]: expected value, found type alias `xm1::S` + --> $DIR/namespace-mix.rs:40:11 + | +LL | check(xm1::S); + | ^^^^^^ + | + ::: $DIR/auxiliary/namespace-mix.rs:3:5 + | +LL | pub struct TS(); + | ------------- similarly named tuple struct `TS` defined here + | + = note: can't use a type alias as a constructor +help: a tuple struct with a similar name exists + | +LL | check(xm1::TS); + | ~~ +help: consider importing one of these items instead + | +LL | use m2::S; + | +LL | use xm2::S; + | +help: if you import `S`, refer to it directly + | +LL - check(xm1::S); +LL + check(S); + | + +error[E0423]: expected value, found type alias `m7::V` + --> $DIR/namespace-mix.rs:100:11 + | +LL | TV(), + | ---- similarly named tuple variant `TV` defined here +... +LL | check(m7::V); + | ^^^^^ + | + = note: can't use a type alias as a constructor +help: a tuple variant with a similar name exists + | +LL | check(m7::TV); + | ~~ +help: consider importing one of these items instead + | +LL | use m8::V; + | +LL | use xm8::V; + | +help: if you import `V`, refer to it directly + | +LL - check(m7::V); +LL + check(V); + | + +error[E0423]: expected value, found type alias `xm7::V` + --> $DIR/namespace-mix.rs:106:11 + | +LL | check(xm7::V); + | ^^^^^^ + | + ::: $DIR/auxiliary/namespace-mix.rs:7:9 + | +LL | TV(), + | -- similarly named tuple variant `TV` defined here + | + = note: can't use a type alias as a constructor +help: a tuple variant with a similar name exists + | +LL | check(xm7::TV); + | ~~ +help: consider importing one of these items instead + | +LL | use m8::V; + | +LL | use xm8::V; + | +help: if you import `V`, refer to it directly + | +LL - check(xm7::V); +LL + check(V); + | + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:33:11 + | +LL | check(m1::S{}); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::S: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:35:11 + | +LL | check(m2::S{}); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:36:11 + | +LL | check(m2::S); + | ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:39:11 + | +LL | check(xm1::S{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:41:11 + | +LL | check(xm2::S{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:42:11 + | +LL | check(xm2::S); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:55:11 + | +LL | check(m3::TS{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:56:11 + | +LL | check(m3::TS); + | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::TS {c::TS}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::TS: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:57:11 + | +LL | check(m4::TS{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:58:11 + | +LL | check(m4::TS); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:61:11 + | +LL | check(xm3::TS{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:62:11 + | +LL | check(xm3::TS); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:63:11 + | +LL | check(xm4::TS{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:64:11 + | +LL | check(xm4::TS); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:77:11 + | +LL | check(m5::US{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::US: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:78:11 + | +LL | check(m5::US); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::US` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::US: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:79:11 + | +LL | check(m6::US{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::US` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:80:11 + | +LL | check(m6::US); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:83:11 + | +LL | check(xm5::US{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:84:11 + | +LL | check(xm5::US); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:85:11 + | +LL | check(xm6::US{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:86:11 + | +LL | check(xm6::US); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:99:11 + | +LL | check(m7::V{}); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:101:11 + | +LL | check(m8::V{}); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:102:11 + | +LL | check(m8::V); + | ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:105:11 + | +LL | check(xm7::V{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:107:11 + | +LL | check(xm8::V{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:108:11 + | +LL | check(xm8::V); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:121:11 + | +LL | check(m9::TV{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:122:11 + | +LL | check(m9::TV); + | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::E {c::E::TV}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:123:11 + | +LL | check(mA::TV{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:124:11 + | +LL | check(mA::TV); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:127:11 + | +LL | check(xm9::TV{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:128:11 + | +LL | check(xm9::TV); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:129:11 + | +LL | check(xmA::TV{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:130:11 + | +LL | check(xmA::TV); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:143:11 + | +LL | check(mB::UV{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:144:11 + | +LL | check(mB::UV); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:145:11 + | +LL | check(mC::UV{}); + | ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:146:11 + | +LL | check(mC::UV); + | ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:149:11 + | +LL | check(xmB::UV{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:150:11 + | +LL | check(xmB::UV); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:151:11 + | +LL | check(xmC::UV{}); + | ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisfied + --> $DIR/namespace-mix.rs:152:11 + | +LL | check(xmC::UV); + | ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/namespace-mix.rs:21:13 + | +LL | fn check(_: T) {} + | ^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 48 previous errors + +Some errors have detailed explanations: E0277, E0423. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs b/tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs new file mode 100644 index 000000000..feb94b681 --- /dev/null +++ b/tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.rs @@ -0,0 +1,15 @@ +// aux-build:namespaced_enums.rs +extern crate namespaced_enums; + +mod m { + pub use namespaced_enums::Foo::*; +} + +pub fn main() { + use namespaced_enums::Foo::*; + + foo(); //~ ERROR cannot find function `foo` in this scope + m::foo(); //~ ERROR cannot find function `foo` in module `m` + bar(); //~ ERROR cannot find function `bar` in this scope + m::bar(); //~ ERROR cannot find function `bar` in module `m` +} diff --git a/tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr b/tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr new file mode 100644 index 000000000..227d30282 --- /dev/null +++ b/tests/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find function `foo` in module `m` + --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:12:8 + | +LL | m::foo(); + | ^^^ not found in `m` + +error[E0425]: cannot find function `bar` in module `m` + --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:14:8 + | +LL | m::bar(); + | ^^^ not found in `m` + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:11:5 + | +LL | foo(); + | ^^^ not found in this scope + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:13:5 + | +LL | bar(); + | ^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/namespace/namespaced-enum-glob-import-no-impls.rs b/tests/ui/namespace/namespaced-enum-glob-import-no-impls.rs new file mode 100644 index 000000000..ab24f36f9 --- /dev/null +++ b/tests/ui/namespace/namespaced-enum-glob-import-no-impls.rs @@ -0,0 +1,25 @@ +mod m2 { + pub enum Foo { + A, + B(isize), + C { a: isize }, + } + + impl Foo { + pub fn foo() {} + pub fn bar(&self) {} + } +} + +mod m { + pub use m2::Foo::*; +} + +pub fn main() { + use m2::Foo::*; + + foo(); //~ ERROR cannot find function `foo` in this scope + m::foo(); //~ ERROR cannot find function `foo` in module `m` + bar(); //~ ERROR cannot find function `bar` in this scope + m::bar(); //~ ERROR cannot find function `bar` in module `m` +} diff --git a/tests/ui/namespace/namespaced-enum-glob-import-no-impls.stderr b/tests/ui/namespace/namespaced-enum-glob-import-no-impls.stderr new file mode 100644 index 000000000..111ac7ab0 --- /dev/null +++ b/tests/ui/namespace/namespaced-enum-glob-import-no-impls.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find function `foo` in module `m` + --> $DIR/namespaced-enum-glob-import-no-impls.rs:22:8 + | +LL | m::foo(); + | ^^^ not found in `m` + +error[E0425]: cannot find function `bar` in module `m` + --> $DIR/namespaced-enum-glob-import-no-impls.rs:24:8 + | +LL | m::bar(); + | ^^^ not found in `m` + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/namespaced-enum-glob-import-no-impls.rs:21:5 + | +LL | foo(); + | ^^^ not found in this scope + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/namespaced-enum-glob-import-no-impls.rs:23:5 + | +LL | bar(); + | ^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/native-library-link-flags/empty-kind-1.rs b/tests/ui/native-library-link-flags/empty-kind-1.rs new file mode 100644 index 000000000..18937856d --- /dev/null +++ b/tests/ui/native-library-link-flags/empty-kind-1.rs @@ -0,0 +1,6 @@ +// Unspecified kind should fail with an error + +// compile-flags: -l =mylib +// error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg + +fn main() {} diff --git a/tests/ui/native-library-link-flags/empty-kind-1.stderr b/tests/ui/native-library-link-flags/empty-kind-1.stderr new file mode 100644 index 000000000..3e5b05493 --- /dev/null +++ b/tests/ui/native-library-link-flags/empty-kind-1.stderr @@ -0,0 +1,2 @@ +error: unknown library kind ``, expected one of: static, dylib, framework, link-arg + diff --git a/tests/ui/native-library-link-flags/empty-kind-2.rs b/tests/ui/native-library-link-flags/empty-kind-2.rs new file mode 100644 index 000000000..851eb63fc --- /dev/null +++ b/tests/ui/native-library-link-flags/empty-kind-2.rs @@ -0,0 +1,6 @@ +// Unspecified kind should fail with an error + +// compile-flags: -l :+bundle=mylib +// error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg + +fn main() {} diff --git a/tests/ui/native-library-link-flags/empty-kind-2.stderr b/tests/ui/native-library-link-flags/empty-kind-2.stderr new file mode 100644 index 000000000..3e5b05493 --- /dev/null +++ b/tests/ui/native-library-link-flags/empty-kind-2.stderr @@ -0,0 +1,2 @@ +error: unknown library kind ``, expected one of: static, dylib, framework, link-arg + diff --git a/tests/ui/native-library-link-flags/link-arg-error.rs b/tests/ui/native-library-link-flags/link-arg-error.rs new file mode 100644 index 000000000..e041650d0 --- /dev/null +++ b/tests/ui/native-library-link-flags/link-arg-error.rs @@ -0,0 +1,4 @@ +// compile-flags: -l link-arg:+bundle=arg -Z unstable-options +// error-pattern: linking modifier `bundle` is only compatible with `static` linking kind + +fn main() {} diff --git a/tests/ui/native-library-link-flags/link-arg-error.stderr b/tests/ui/native-library-link-flags/link-arg-error.stderr new file mode 100644 index 000000000..e1d01e141 --- /dev/null +++ b/tests/ui/native-library-link-flags/link-arg-error.stderr @@ -0,0 +1,2 @@ +error: linking modifier `bundle` is only compatible with `static` linking kind + diff --git a/tests/ui/native-library-link-flags/link-arg-from-rs.rs b/tests/ui/native-library-link-flags/link-arg-from-rs.rs new file mode 100644 index 000000000..075e4d9e7 --- /dev/null +++ b/tests/ui/native-library-link-flags/link-arg-from-rs.rs @@ -0,0 +1,8 @@ +// link-arg is not supposed to be usable in #[link] attributes + +// compile-flags: +// error-pattern: error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib + +#[link(kind = "link-arg")] +extern "C" {} +pub fn main() {} diff --git a/tests/ui/native-library-link-flags/link-arg-from-rs.stderr b/tests/ui/native-library-link-flags/link-arg-from-rs.stderr new file mode 100644 index 000000000..69a7825c0 --- /dev/null +++ b/tests/ui/native-library-link-flags/link-arg-from-rs.stderr @@ -0,0 +1,16 @@ +error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib + --> $DIR/link-arg-from-rs.rs:6:15 + | +LL | #[link(kind = "link-arg")] + | ^^^^^^^^^^ unknown link kind + +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/link-arg-from-rs.rs:6:1 + | +LL | #[link(kind = "link-arg")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0458, E0459. +For more information about an error, try `rustc --explain E0458`. diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs new file mode 100644 index 000000000..066048795 --- /dev/null +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zunstable-options --crate-type rlib +// build-fail +// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")] +extern "C" { } + +fn main() { } diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr new file mode 100644 index 000000000..246efb8d6 --- /dev/null +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr @@ -0,0 +1,6 @@ +error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +error: could not find native static library `mylib`, perhaps an -L flag is missing? + +error: aborting due to 2 previous errors + diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs new file mode 100644 index 000000000..1d0768d99 --- /dev/null +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs @@ -0,0 +1,7 @@ +// Mixing +bundle and +whole-archive is not allowed + +// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib +// build-fail +// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +fn main() { } diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr new file mode 100644 index 000000000..246efb8d6 --- /dev/null +++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr @@ -0,0 +1,6 @@ +error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +error: could not find native static library `mylib`, perhaps an -L flag is missing? + +error: aborting due to 2 previous errors + diff --git a/tests/ui/native-library-link-flags/modifiers-override-2.rs b/tests/ui/native-library-link-flags/modifiers-override-2.rs new file mode 100644 index 000000000..333f6786b --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-override-2.rs @@ -0,0 +1,3 @@ +// compile-flags:-lstatic:+whole-archive,-whole-archive=foo + +fn main() {} diff --git a/tests/ui/native-library-link-flags/modifiers-override-2.stderr b/tests/ui/native-library-link-flags/modifiers-override-2.stderr new file mode 100644 index 000000000..aa5b59c5b --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-override-2.stderr @@ -0,0 +1,2 @@ +error: multiple `whole-archive` modifiers in a single `-l` option + diff --git a/tests/ui/native-library-link-flags/modifiers-override-3.rs b/tests/ui/native-library-link-flags/modifiers-override-3.rs new file mode 100644 index 000000000..b28c53c6b --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-override-3.rs @@ -0,0 +1,7 @@ +// Regression test for issue #97299, one command line library with modifiers +// overrides another command line library with modifiers. + +// compile-flags:-lstatic:+whole-archive=foo -lstatic:+whole-archive=foo +// error-pattern: overriding linking modifiers from command line is not supported + +fn main() {} diff --git a/tests/ui/native-library-link-flags/modifiers-override-3.stderr b/tests/ui/native-library-link-flags/modifiers-override-3.stderr new file mode 100644 index 000000000..365e56181 --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-override-3.stderr @@ -0,0 +1,4 @@ +error: overriding linking modifiers from command line is not supported + +error: aborting due to previous error + diff --git a/tests/ui/native-library-link-flags/modifiers-override.rs b/tests/ui/native-library-link-flags/modifiers-override.rs new file mode 100644 index 000000000..42cdb5004 --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-override.rs @@ -0,0 +1,16 @@ +// compile-flags:-ldylib:+as-needed=foo -lstatic=bar -Zunstable-options + +#[link(name = "foo")] +#[link( + name = "bar", + kind = "static", + modifiers = "+whole-archive,-whole-archive", + //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument + modifiers = "+bundle" + //~^ ERROR multiple `modifiers` arguments in a single `#[link]` attribute +)] +extern "C" {} +//~^ ERROR overriding linking modifiers from command line is not supported +//~| ERROR overriding linking modifiers from command line is not supported + +fn main() {} diff --git a/tests/ui/native-library-link-flags/modifiers-override.stderr b/tests/ui/native-library-link-flags/modifiers-override.stderr new file mode 100644 index 000000000..eb3ab55c3 --- /dev/null +++ b/tests/ui/native-library-link-flags/modifiers-override.stderr @@ -0,0 +1,26 @@ +error: multiple `modifiers` arguments in a single `#[link]` attribute + --> $DIR/modifiers-override.rs:9:5 + | +LL | modifiers = "+bundle" + | ^^^^^^^^^^^^^^^^^^^^^ + +error: multiple `whole-archive` modifiers in a single `modifiers` argument + --> $DIR/modifiers-override.rs:7:17 + | +LL | modifiers = "+whole-archive,-whole-archive", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: overriding linking modifiers from command line is not supported + --> $DIR/modifiers-override.rs:12:1 + | +LL | extern "C" {} + | ^^^^^^^^^^^^^ + +error: overriding linking modifiers from command line is not supported + --> $DIR/modifiers-override.rs:12:1 + | +LL | extern "C" {} + | ^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/native-library-link-flags/suggest-libname-only-1.rs b/tests/ui/native-library-link-flags/suggest-libname-only-1.rs new file mode 100644 index 000000000..abf988a7c --- /dev/null +++ b/tests/ui/native-library-link-flags/suggest-libname-only-1.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: --crate-type rlib +// error-pattern: could not find native static library `libfoo.a` +// error-pattern: only provide the library name `foo`, not the full filename + +#[link(name = "libfoo.a", kind = "static")] +extern { } + +pub fn main() { } diff --git a/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr b/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr new file mode 100644 index 000000000..64d0a9077 --- /dev/null +++ b/tests/ui/native-library-link-flags/suggest-libname-only-1.stderr @@ -0,0 +1,6 @@ +error: could not find native static library `libfoo.a`, perhaps an -L flag is missing? + | + = help: only provide the library name `foo`, not the full filename + +error: aborting due to previous error + diff --git a/tests/ui/native-library-link-flags/suggest-libname-only-2.rs b/tests/ui/native-library-link-flags/suggest-libname-only-2.rs new file mode 100644 index 000000000..dfa70e56d --- /dev/null +++ b/tests/ui/native-library-link-flags/suggest-libname-only-2.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: --crate-type rlib +// error-pattern: could not find native static library `bar.lib` +// error-pattern: only provide the library name `bar`, not the full filename + +#[link(name = "bar.lib", kind = "static")] +extern { } + +pub fn main() { } diff --git a/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr b/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr new file mode 100644 index 000000000..e166af9ed --- /dev/null +++ b/tests/ui/native-library-link-flags/suggest-libname-only-2.stderr @@ -0,0 +1,6 @@ +error: could not find native static library `bar.lib`, perhaps an -L flag is missing? + | + = help: only provide the library name `bar`, not the full filename + +error: aborting due to previous error + diff --git a/tests/ui/nested-block-comment.rs b/tests/ui/nested-block-comment.rs new file mode 100644 index 000000000..f8dfb5fa8 --- /dev/null +++ b/tests/ui/nested-block-comment.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +/* This test checks that nested comments are supported + + /* + This should not panic + */ +*/ + +pub fn main() { +} diff --git a/tests/ui/nested-cfg-attrs.rs b/tests/ui/nested-cfg-attrs.rs new file mode 100644 index 000000000..c988d4233 --- /dev/null +++ b/tests/ui/nested-cfg-attrs.rs @@ -0,0 +1,4 @@ +#[cfg_attr(all(), cfg_attr(all(), cfg(foo)))] +fn f() {} + +fn main() { f() } //~ ERROR cannot find function `f` in this scope diff --git a/tests/ui/nested-cfg-attrs.stderr b/tests/ui/nested-cfg-attrs.stderr new file mode 100644 index 000000000..f63888b2f --- /dev/null +++ b/tests/ui/nested-cfg-attrs.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/nested-cfg-attrs.rs:4:13 + | +LL | fn main() { f() } + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/nested-class.rs b/tests/ui/nested-class.rs new file mode 100644 index 000000000..303273618 --- /dev/null +++ b/tests/ui/nested-class.rs @@ -0,0 +1,25 @@ +// run-pass + +#![allow(non_camel_case_types)] + +pub fn main() { + struct b { + i: isize, + } + + impl b { + fn do_stuff(&self) -> isize { return 37; } + } + + fn b(i:isize) -> b { + b { + i: i + } + } + + // fn b(x:isize) -> isize { panic!(); } + + let z = b(42); + assert_eq!(z.i, 42); + assert_eq!(z.do_stuff(), 37); +} diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/nested-ty-params.rs new file mode 100644 index 000000000..85413acdb --- /dev/null +++ b/tests/ui/nested-ty-params.rs @@ -0,0 +1,8 @@ +// error-pattern:can't use generic parameters from outer function +fn hd(v: Vec ) -> U { + fn hd1(w: [U]) -> U { return w[0]; } + + return hd1(v); +} + +fn main() {} diff --git a/tests/ui/nested-ty-params.stderr b/tests/ui/nested-ty-params.stderr new file mode 100644 index 000000000..8f4746f5e --- /dev/null +++ b/tests/ui/nested-ty-params.stderr @@ -0,0 +1,23 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/nested-ty-params.rs:3:16 + | +LL | fn hd(v: Vec ) -> U { + | - type parameter from outer function +LL | fn hd1(w: [U]) -> U { return w[0]; } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error[E0401]: can't use generic parameters from outer function + --> $DIR/nested-ty-params.rs:3:23 + | +LL | fn hd(v: Vec ) -> U { + | - type parameter from outer function +LL | fn hd1(w: [U]) -> U { return w[0]; } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/never_type/adjust_never.rs b/tests/ui/never_type/adjust_never.rs new file mode 100644 index 000000000..0d7d2c0ed --- /dev/null +++ b/tests/ui/never_type/adjust_never.rs @@ -0,0 +1,10 @@ +// Test that a variable of type ! can coerce to another type. + +// check-pass + +#![feature(never_type)] + +fn main() { + let x: ! = panic!(); + let y: u32 = x; +} diff --git a/tests/ui/never_type/auto-traits.rs b/tests/ui/never_type/auto-traits.rs new file mode 100644 index 000000000..42ede708e --- /dev/null +++ b/tests/ui/never_type/auto-traits.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(auto_traits)] +#![feature(negative_impls)] +#![feature(never_type)] + +fn main() { + enum Void {} + + auto trait Auto {} + fn assert_auto() {} + assert_auto::(); + assert_auto::(); + + fn assert_send() {} + assert_send::(); + assert_send::(); +} diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.rs b/tests/ui/never_type/call-fn-never-arg-wrong-type.rs new file mode 100644 index 000000000..d06637e74 --- /dev/null +++ b/tests/ui/never_type/call-fn-never-arg-wrong-type.rs @@ -0,0 +1,11 @@ +// Test that we can't pass other types for ! + +#![feature(never_type)] + +fn foo(x: !) -> ! { + x +} + +fn main() { + foo("wow"); //~ ERROR mismatched types +} diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr b/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr new file mode 100644 index 000000000..fa3db33c9 --- /dev/null +++ b/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/call-fn-never-arg-wrong-type.rs:10:9 + | +LL | foo("wow"); + | --- ^^^^^ expected `!`, found `&str` + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found reference `&'static str` +note: function defined here + --> $DIR/call-fn-never-arg-wrong-type.rs:5:4 + | +LL | fn foo(x: !) -> ! { + | ^^^ ---- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/call-fn-never-arg.rs b/tests/ui/never_type/call-fn-never-arg.rs new file mode 100644 index 000000000..9d355817e --- /dev/null +++ b/tests/ui/never_type/call-fn-never-arg.rs @@ -0,0 +1,14 @@ +// Test that we can use a ! for an argument of type ! + +// check-pass + +#![feature(never_type)] +#![allow(unreachable_code)] + +fn foo(x: !) -> ! { + x +} + +fn main() { + foo(panic!("wowzers!")) +} diff --git a/tests/ui/never_type/cast-never.rs b/tests/ui/never_type/cast-never.rs new file mode 100644 index 000000000..0139ebe46 --- /dev/null +++ b/tests/ui/never_type/cast-never.rs @@ -0,0 +1,10 @@ +// Test that we can explicitly cast ! to another type + +// check-pass + +#![feature(never_type)] + +fn main() { + let x: ! = panic!(); + let y: u32 = x as u32; +} diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr new file mode 100644 index 000000000..283aca1b0 --- /dev/null +++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied + --> $DIR/defaulted-never-note.rs:30:9 + | +LL | foo(_x); + | --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` + | | + | required by a bound introduced by this call + | + = help: the trait `ImplementedForUnitButNotNever` is implemented for `()` + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? +note: required by a bound in `foo` + --> $DIR/defaulted-never-note.rs:25:11 + | +LL | fn foo(_t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs new file mode 100644 index 000000000..d30ffcd38 --- /dev/null +++ b/tests/ui/never_type/defaulted-never-note.rs @@ -0,0 +1,41 @@ +// revisions: nofallback fallback +//[nofallback] run-pass +//[fallback] check-fail + +// We need to opt into the `never_type_fallback` feature +// to trigger the requirement that this is testing. +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +#![allow(unused)] + +trait Deserialize: Sized { + fn deserialize() -> Result; +} + +impl Deserialize for () { + fn deserialize() -> Result<(), String> { + Ok(()) + } +} + +trait ImplementedForUnitButNotNever {} + +impl ImplementedForUnitButNotNever for () {} + +fn foo(_t: T) {} +//[fallback]~^ NOTE required by this bound in `foo` +//[fallback]~| NOTE required by a bound in `foo` +fn smeg() { + let _x = return; + foo(_x); + //[fallback]~^ ERROR the trait bound + //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented + //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()` + //[fallback]~| NOTE this error might have been caused + //[fallback]~| NOTE required by a bound introduced by this call + //[fallback]~| HELP did you intend +} + +fn main() { + smeg(); +} diff --git a/tests/ui/never_type/dispatch_from_dyn_zst.rs b/tests/ui/never_type/dispatch_from_dyn_zst.rs new file mode 100644 index 000000000..764f58ce9 --- /dev/null +++ b/tests/ui/never_type/dispatch_from_dyn_zst.rs @@ -0,0 +1,51 @@ +// run-pass + +#![feature(unsize, dispatch_from_dyn, never_type)] + +#![allow(dead_code)] + +use std::{ + ops::DispatchFromDyn, + marker::{Unsize, PhantomData}, +}; + +struct Zst; +struct NestedZst(PhantomData<()>, Zst); + + +struct WithUnit(Box, ()); +impl DispatchFromDyn> for WithUnit + where T: Unsize {} + +struct WithPhantom(Box, PhantomData<()>); +impl DispatchFromDyn> for WithPhantom + where T: Unsize {} + +struct WithNever(Box, !); +impl DispatchFromDyn> for WithNever + where T: Unsize {} + +struct WithZst(Box, Zst); +impl DispatchFromDyn> for WithZst + where T: Unsize {} + +struct WithNestedZst(Box, NestedZst); +impl DispatchFromDyn> for WithNestedZst + where T: Unsize {} + + +struct Generic(Box, A); +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn>> + for Generic> + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} + + +fn main() {} diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs new file mode 100644 index 000000000..45a3362fa --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-control-flow.rs @@ -0,0 +1,100 @@ +// revisions: nofallback fallback +// run-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(unreachable_code)] +// Test various cases where we permit an unconstrained variable +// to fallback based on control-flow. In all of these cases, +// the type variable winds up being the target of both a `!` coercion +// and a coercion from a non-`!` variable, and hence falls back to `()`. +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +trait UnitDefault { + fn default() -> Self; +} + +impl UnitDefault for u32 { + fn default() -> Self { + 0 + } +} + +impl UnitDefault for () { + fn default() -> () { + panic!() + } +} + +fn assignment() { + let x; + + if true { + x = UnitDefault::default(); + } else { + x = return; + } +} + +fn assignment_rev() { + let x; + + if true { + x = return; + } else { + x = UnitDefault::default(); + } +} + +fn if_then_else() { + let _x = if true { + UnitDefault::default() + } else { + return; + }; +} + +fn if_then_else_rev() { + let _x = if true { + return; + } else { + UnitDefault::default() + }; +} + +fn match_arm() { + let _x = match Ok(UnitDefault::default()) { + Ok(v) => v, + Err(()) => return, + }; +} + +fn match_arm_rev() { + let _x = match Ok(UnitDefault::default()) { + Err(()) => return, + Ok(v) => v, + }; +} + +fn loop_break() { + let _x = loop { + if false { + break return; + } else { + break UnitDefault::default(); + } + }; +} + +fn loop_break_rev() { + let _x = loop { + if false { + break return; + } else { + break UnitDefault::default(); + } + }; +} + +fn main() {} diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr new file mode 100644 index 000000000..3215c4669 --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `!: Test` is not satisfied + --> $DIR/diverging-fallback-no-leak.rs:17:23 + | +LL | unconstrained_arg(return); + | ----------------- ^^^^^^ the trait `Test` is not implemented for `!` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Test`: + () + i32 + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? +note: required by a bound in `unconstrained_arg` + --> $DIR/diverging-fallback-no-leak.rs:12:25 + | +LL | fn unconstrained_arg(_: T) {} + | ^^^^ required by this bound in `unconstrained_arg` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/diverging-fallback-no-leak.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs new file mode 100644 index 000000000..03478e19d --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-no-leak.rs @@ -0,0 +1,19 @@ +// revisions: nofallback fallback +//[nofallback] check-pass + +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +fn make_unit() {} + +trait Test {} +impl Test for i32 {} +impl Test for () {} + +fn unconstrained_arg(_: T) {} + +fn main() { + // Here the type variable falls back to `!`, + // and hence we get a type error. + unconstrained_arg(return); + //[fallback]~^ ERROR trait bound `!: Test` is not satisfied +} diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs new file mode 100644 index 000000000..7ea97126f --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -0,0 +1,37 @@ +// Variant of diverging-falllback-control-flow that tests +// the specific case of a free function with an unconstrained +// return type. This captures the pattern we saw in the wild +// in the objc crate, where changing the fallback from `!` to `()` +// resulted in unsoundness. +// +// check-pass + +// revisions: nofallback fallback + +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + + +fn make_unit() {} + +trait UnitReturn {} +impl UnitReturn for i32 {} +impl UnitReturn for () {} + +fn unconstrained_return() -> T { + unsafe { + let make_unit_fn: fn() = make_unit; + let ffi: fn() -> T = std::mem::transmute(make_unit_fn); + ffi() + } +} + +fn main() { + // In Ye Olde Days, the `T` parameter of `unconstrained_return` + // winds up "entangled" with the `!` type that results from + // `panic!`, and hence falls back to `()`. This is kind of unfortunate + // and unexpected. When we introduced the `!` type, the original + // idea was to change that fallback to `!`, but that would have resulted + // in this code no longer compiling (or worse, in some cases it injected + // unsound results). + let _ = if true { unconstrained_return() } else { panic!() }; +} diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.rs b/tests/ui/never_type/diverging-tuple-parts-39485.rs new file mode 100644 index 000000000..0cde61193 --- /dev/null +++ b/tests/ui/never_type/diverging-tuple-parts-39485.rs @@ -0,0 +1,15 @@ +// After #39485, this test used to pass, but that change was reverted +// due to numerous inference failures like #39808, so it now fails +// again. #39485 made it so that diverging types never propagate +// upward; but we now do propagate such types upward in many more +// cases. + +fn g() { + &panic!() //~ ERROR mismatched types +} + +fn f() -> isize { + (return 1, return 2) //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.stderr b/tests/ui/never_type/diverging-tuple-parts-39485.stderr new file mode 100644 index 000000000..52d07ae17 --- /dev/null +++ b/tests/ui/never_type/diverging-tuple-parts-39485.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/diverging-tuple-parts-39485.rs:8:5 + | +LL | &panic!() + | ^^^^^^^^^ expected `()`, found reference + | + = note: expected unit type `()` + found reference `&_` +help: a return type might be missing here + | +LL | fn g() -> _ { + | ++++ +help: consider removing the borrow + | +LL - &panic!() +LL + panic!() + | + +error[E0308]: mismatched types + --> $DIR/diverging-tuple-parts-39485.rs:12:5 + | +LL | fn f() -> isize { + | ----- expected `isize` because of return type +LL | (return 1, return 2) + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple + | + = note: expected type `isize` + found tuple `(!, !)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/exhaustive_patterns.rs b/tests/ui/never_type/exhaustive_patterns.rs new file mode 100644 index 000000000..2e23fa182 --- /dev/null +++ b/tests/ui/never_type/exhaustive_patterns.rs @@ -0,0 +1,21 @@ +// check-fail +// known-bug: #104034 + +#![feature(exhaustive_patterns, never_type)] + +mod inner { + pub struct Wrapper(T); +} + +enum Either { + A(A), + B(inner::Wrapper), +} + +fn foo() -> Either<(), !> { + Either::A(()) +} + +fn main() { + let Either::A(()) = foo(); +} diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr new file mode 100644 index 000000000..40c7c1d10 --- /dev/null +++ b/tests/ui/never_type/exhaustive_patterns.stderr @@ -0,0 +1,25 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/exhaustive_patterns.rs:20:9 + | +LL | let Either::A(()) = foo(); + | ^^^^^^^^^^^^^ pattern `Either::B(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Either<(), !>` defined here + --> $DIR/exhaustive_patterns.rs:10:6 + | +LL | enum Either { + | ^^^^^^ +LL | A(A), +LL | B(inner::Wrapper), + | - not covered + = note: the matched value is of type `Either<(), !>` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Either::A(()) = foo() { todo!() } + | ++ ~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/never_type/expr-empty-ret.rs b/tests/ui/never_type/expr-empty-ret.rs new file mode 100644 index 000000000..ce8ffaf94 --- /dev/null +++ b/tests/ui/never_type/expr-empty-ret.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +// Issue #521 + +// pretty-expanded FIXME #23616 + +fn f() { + let _x = match true { + true => { 10 } + false => { return } + }; +} + +pub fn main() { } diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs new file mode 100644 index 000000000..5c8ce48cb --- /dev/null +++ b/tests/ui/never_type/fallback-closure-ret.rs @@ -0,0 +1,23 @@ +// This test verifies that never type fallback preserves the following code in a +// compiling state. This pattern is fairly common in the wild, notably seen in +// wasmtime v0.16. Typically this is some closure wrapper that expects a +// collection of 'known' signatures, and -> ! is not included in that set. +// +// This test is specifically targeted by the unit type fallback when +// encountering a set of obligations like `?T: Foo` and `Trait::Projection = +// ?T`. In the code below, these are `R: Bar` and `Fn::Output = R`. +// +// revisions: nofallback fallback +// check-pass + +#![cfg_attr(fallback, feature(never_type_fallback))] + +trait Bar { } +impl Bar for () { } +impl Bar for u32 { } + +fn foo(_: impl Fn() -> R) {} + +fn main() { + foo(|| panic!()); +} diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr new file mode 100644 index 000000000..a0f790dba --- /dev/null +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -0,0 +1,17 @@ +error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!` + --> $DIR/fallback-closure-wrap.rs:18:31 + | +LL | let error = Closure::wrap(Box::new(move || { + | _______________________________^ +LL | | +LL | | panic!("Can't connect to server."); +LL | | }) as Box); + | |______^ expected `()`, found `!` + | + = note: expected unit type `()` + found type `!` + = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to the object type `dyn FnMut()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback-closure-wrap.rs new file mode 100644 index 000000000..f88355bb2 --- /dev/null +++ b/tests/ui/never_type/fallback-closure-wrap.rs @@ -0,0 +1,30 @@ +// This is a minified example from Crater breakage observed when attempting to +// stabilize never type, nstoddard/webgl-gui @ 22f0169f. +// +// This particular test case currently fails as the inference to `()` rather +// than `!` happens as a result of an `as` cast, which is not currently tracked. +// Crater did not find many cases of this occurring, but it is included for +// awareness. +// +// revisions: nofallback fallback +//[nofallback] check-pass +//[fallback] check-fail + +#![cfg_attr(fallback, feature(never_type_fallback))] + +use std::marker::PhantomData; + +fn main() { + let error = Closure::wrap(Box::new(move || { + //[fallback]~^ to be a closure that returns `()`, but it returns `!` + panic!("Can't connect to server."); + }) as Box); +} + +struct Closure(PhantomData); + +impl Closure { + fn wrap(data: Box) -> Closure { + todo!() + } +} diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.rs b/tests/ui/never_type/feature-gate-never_type_fallback.rs new file mode 100644 index 000000000..7d0208411 --- /dev/null +++ b/tests/ui/never_type/feature-gate-never_type_fallback.rs @@ -0,0 +1,13 @@ +// This is a feature gate test for `never_type_fallback`. +// It works by using a scenario where the type fall backs to `()` rather than ´!` +// in the case where `#![feature(never_type_fallback)]` would change it to `!`. + +fn main() {} + +trait T {} + +fn should_ret_unit() { + foo(panic!()) //~ ERROR +} + +fn foo(_: impl T) {} diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.stderr b/tests/ui/never_type/feature-gate-never_type_fallback.stderr new file mode 100644 index 000000000..2db1cc4b7 --- /dev/null +++ b/tests/ui/never_type/feature-gate-never_type_fallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/feature-gate-never_type_fallback.rs:10:9 + | +LL | foo(panic!()) + | --- ^^^^^^^^ + | | | + | | the trait `T` is not implemented for `()` + | | this tail expression is of type `()` + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/feature-gate-never_type_fallback.rs:13:16 + | +LL | fn foo(_: impl T) {} + | ^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl-for-never.rs b/tests/ui/never_type/impl-for-never.rs new file mode 100644 index 000000000..9423f0885 --- /dev/null +++ b/tests/ui/never_type/impl-for-never.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(never_type)] + +// Test that we can call static methods on ! both directly and when it appears in a generic + +trait StringifyType { + fn stringify_type() -> &'static str; +} + +impl StringifyType for ! { + fn stringify_type() -> &'static str { + "!" + } +} + +fn maybe_stringify(opt: Option) -> &'static str { + match opt { + Some(_) => T::stringify_type(), + None => "none", + } +} + +fn main() { + println!("! is {}", ::stringify_type()); + println!("None is {}", maybe_stringify(None::)); +} diff --git a/tests/ui/never_type/impl_trait_fallback.rs b/tests/ui/never_type/impl_trait_fallback.rs new file mode 100644 index 000000000..cc9520c1b --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() {} + +trait T {} +impl T for () {} + +fn should_ret_unit() -> impl T { + panic!() +} diff --git a/tests/ui/never_type/impl_trait_fallback2.rs b/tests/ui/never_type/impl_trait_fallback2.rs new file mode 100644 index 000000000..12c187b9e --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback2.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait T {} +impl T for i32 {} + +fn should_ret_unit() -> impl T { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +type Foo = impl T; + +fn a() -> Foo { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +fn b() -> Foo { + 42 +} diff --git a/tests/ui/never_type/impl_trait_fallback2.stderr b/tests/ui/never_type/impl_trait_fallback2.stderr new file mode 100644 index 000000000..78cc83bdb --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback2.rs:8:25 + | +LL | fn should_ret_unit() -> impl T { + | ^^^^^^ the trait `T` is not implemented for `()` + | + = help: the trait `T` is implemented for `i32` + +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback2.rs:15:11 + | +LL | fn a() -> Foo { + | ^^^ the trait `T` is not implemented for `()` + | + = help: the trait `T` is implemented for `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl_trait_fallback3.rs b/tests/ui/never_type/impl_trait_fallback3.rs new file mode 100644 index 000000000..ed645b823 --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback3.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait T { + type Assoc; +} + +type Foo = impl T; + +fn a() -> Foo { + //~^ ERROR the trait bound `(): T` is not satisfied + // This is not a defining use, it doesn't actually constrain the opaque type. + panic!() +} diff --git a/tests/ui/never_type/impl_trait_fallback3.stderr b/tests/ui/never_type/impl_trait_fallback3.stderr new file mode 100644 index 000000000..5d5d216fb --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback3.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback3.rs:11:11 + | +LL | fn a() -> Foo { + | ^^^ the trait `T` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl_trait_fallback4.rs b/tests/ui/never_type/impl_trait_fallback4.rs new file mode 100644 index 000000000..fe62773fa --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback4.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +trait T { + type Assoc: Cake; +} + +trait Cake: std::fmt::Display { + fn cake() -> Self; +} + +type Foo = impl T; + +fn foo() -> impl T { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +fn a() -> Foo { + foo() +} + +fn main() { + println!("{}", ::Assoc::cake()); +} diff --git a/tests/ui/never_type/impl_trait_fallback4.stderr b/tests/ui/never_type/impl_trait_fallback4.stderr new file mode 100644 index 000000000..f2e216e90 --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback4.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback4.rs:13:13 + | +LL | fn foo() -> impl T { + | ^^^^^^ the trait `T` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-10176.rs b/tests/ui/never_type/issue-10176.rs new file mode 100644 index 000000000..6277aa05e --- /dev/null +++ b/tests/ui/never_type/issue-10176.rs @@ -0,0 +1,9 @@ +fn f() -> isize { + (return 1, return 2) +//~^ ERROR mismatched types +//~| expected type `isize` +//~| found tuple `(!, !)` +//~| expected `isize`, found tuple +} + +fn main() {} diff --git a/tests/ui/never_type/issue-10176.stderr b/tests/ui/never_type/issue-10176.stderr new file mode 100644 index 000000000..cd5361ffa --- /dev/null +++ b/tests/ui/never_type/issue-10176.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-10176.rs:2:5 + | +LL | fn f() -> isize { + | ----- expected `isize` because of return type +LL | (return 1, return 2) + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple + | + = note: expected type `isize` + found tuple `(!, !)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-13352.rs b/tests/ui/never_type/issue-13352.rs new file mode 100644 index 000000000..9c884a33c --- /dev/null +++ b/tests/ui/never_type/issue-13352.rs @@ -0,0 +1,9 @@ +fn foo(_: Box) {} + +fn main() { + foo(loop { + std::process::exit(0); + }); + 2_usize + (loop {}); + //~^ ERROR E0277 +} diff --git a/tests/ui/never_type/issue-13352.stderr b/tests/ui/never_type/issue-13352.stderr new file mode 100644 index 000000000..2d22da0b4 --- /dev/null +++ b/tests/ui/never_type/issue-13352.stderr @@ -0,0 +1,16 @@ +error[E0277]: cannot add `()` to `usize` + --> $DIR/issue-13352.rs:7:13 + | +LL | 2_usize + (loop {}); + | ^ no implementation for `usize + ()` + | + = help: the trait `Add<()>` is not implemented for `usize` + = help: the following other types implement trait `Add`: + <&'a usize as Add> + <&usize as Add<&usize>> + > + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-2149.rs b/tests/ui/never_type/issue-2149.rs new file mode 100644 index 000000000..d6426d2cf --- /dev/null +++ b/tests/ui/never_type/issue-2149.rs @@ -0,0 +1,15 @@ +trait VecMonad { + fn bind(&self, f: F) where F: FnMut(A) -> Vec; +} + +impl VecMonad for Vec { + fn bind(&self, mut f: F) where F: FnMut(A) -> Vec { + let mut r = panic!(); + for elt in self { r = r + f(*elt); } + //~^ ERROR E0277 + } +} +fn main() { + ["hi"].bind(|x| [x] ); + //~^ ERROR no method named `bind` found +} diff --git a/tests/ui/never_type/issue-2149.stderr b/tests/ui/never_type/issue-2149.stderr new file mode 100644 index 000000000..58fe2edb1 --- /dev/null +++ b/tests/ui/never_type/issue-2149.stderr @@ -0,0 +1,25 @@ +error[E0277]: cannot add `Vec` to `()` + --> $DIR/issue-2149.rs:8:33 + | +LL | for elt in self { r = r + f(*elt); } + | ^ no implementation for `() + Vec` + | + = help: the trait `Add>` is not implemented for `()` + +error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope + --> $DIR/issue-2149.rs:13:12 + | +LL | ["hi"].bind(|x| [x] ); + | ^^^^ method not found in `[&str; 1]` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `VecMonad` defines an item `bind`, perhaps you need to implement it + --> $DIR/issue-2149.rs:1:1 + | +LL | trait VecMonad { + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-44402.rs b/tests/ui/never_type/issue-44402.rs new file mode 100644 index 000000000..699e480df --- /dev/null +++ b/tests/ui/never_type/issue-44402.rs @@ -0,0 +1,33 @@ +// check-pass + +#![allow(dead_code)] +#![feature(never_type)] +#![feature(exhaustive_patterns)] + +// Regression test for inhabitedness check. The old +// cache used to cause us to incorrectly decide +// that `test_b` was invalid. + +struct Foo { + field1: !, + field2: Option<&'static Bar>, +} + +struct Bar { + field1: &'static Foo +} + +fn test_a() { + let x: Option = None; + match x { None => () } +} + +fn test_b() { + let x: Option = None; + match x { + Some(_) => (), + None => () + } +} + +fn main() { } diff --git a/tests/ui/never_type/issue-51506.rs b/tests/ui/never_type/issue-51506.rs new file mode 100644 index 000000000..d0fe6a0f5 --- /dev/null +++ b/tests/ui/never_type/issue-51506.rs @@ -0,0 +1,41 @@ +#![feature(never_type, specialization)] +#![allow(incomplete_features)] + +use std::iter::{self, Empty}; + +trait Trait { + type Out: Iterator; + + fn f(&self) -> Option; +} + +impl Trait for T { + default type Out = !; //~ ERROR: `!` is not an iterator + + default fn f(&self) -> Option { + None + } +} + +struct X; + +impl Trait for X { + type Out = Empty; + + fn f(&self) -> Option { + Some(iter::empty()) + } +} + +fn f(a: T) { + if let Some(iter) = a.f() { + println!("Some"); + for x in iter { + println!("x = {}", x); + } + } +} + +pub fn main() { + f(10); +} diff --git a/tests/ui/never_type/issue-51506.stderr b/tests/ui/never_type/issue-51506.stderr new file mode 100644 index 000000000..293ec3a72 --- /dev/null +++ b/tests/ui/never_type/issue-51506.stderr @@ -0,0 +1,16 @@ +error[E0277]: `!` is not an iterator + --> $DIR/issue-51506.rs:13:24 + | +LL | default type Out = !; + | ^ `!` is not an iterator + | + = help: the trait `Iterator` is not implemented for `!` +note: required by a bound in `Trait::Out` + --> $DIR/issue-51506.rs:7:15 + | +LL | type Out: Iterator; + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::Out` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs new file mode 100644 index 000000000..0498a8a16 --- /dev/null +++ b/tests/ui/never_type/issue-52443.rs @@ -0,0 +1,14 @@ +fn main() { + [(); & { loop { continue } } ]; //~ ERROR mismatched types + + [(); loop { break }]; //~ ERROR mismatched types + + [(); {while true {break}; 0}]; + //~^ WARN denote infinite loops with + + [(); { for _ in 0usize.. {}; 0}]; + //~^ ERROR `for` is not allowed in a `const` + //~| ERROR cannot convert + //~| ERROR mutable references + //~| ERROR cannot call +} diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr new file mode 100644 index 000000000..33b7a9185 --- /dev/null +++ b/tests/ui/never_type/issue-52443.stderr @@ -0,0 +1,73 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/issue-52443.rs:6:11 + | +LL | [(); {while true {break}; 0}]; + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/issue-52443.rs:9:12 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-52443.rs:2:10 + | +LL | [(); & { loop { continue } } ]; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` +help: consider removing the borrow + | +LL - [(); & { loop { continue } } ]; +LL + [(); { loop { continue } } ]; + | + +error[E0308]: mismatched types + --> $DIR/issue-52443.rs:4:17 + | +LL | [(); loop { break }]; + | ^^^^^ + | | + | expected `usize`, found `()` + | help: give it a value of the expected type: `break 42` + +error[E0015]: cannot convert `RangeFrom` into an iterator in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0015, E0308, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/never_type/issue-5500-1.rs b/tests/ui/never_type/issue-5500-1.rs new file mode 100644 index 000000000..98d6e1a14 --- /dev/null +++ b/tests/ui/never_type/issue-5500-1.rs @@ -0,0 +1,15 @@ +// MIR doesn't generate an error because the assignment isn't reachable. This +// is OK because the test is here to check that the compiler doesn't ICE (cf. +// #5500). + +// check-pass + +struct TrieMapIterator<'a> { + node: &'a usize +} + +fn main() { + let a = 5; + let _iter = TrieMapIterator{node: &a}; + _iter.node = &panic!() +} diff --git a/tests/ui/never_type/issue-96335.rs b/tests/ui/never_type/issue-96335.rs new file mode 100644 index 000000000..411a7c9df --- /dev/null +++ b/tests/ui/never_type/issue-96335.rs @@ -0,0 +1,5 @@ +fn main() { + 0.....{loop{}1}; + //~^ ERROR unexpected token + //~| ERROR mismatched types +} diff --git a/tests/ui/never_type/issue-96335.stderr b/tests/ui/never_type/issue-96335.stderr new file mode 100644 index 000000000..e148b983e --- /dev/null +++ b/tests/ui/never_type/issue-96335.stderr @@ -0,0 +1,32 @@ +error: unexpected token: `...` + --> $DIR/issue-96335.rs:2:6 + | +LL | 0.....{loop{}1}; + | ^^^ + | +help: use `..` for an exclusive range + | +LL | 0....{loop{}1}; + | ~~ +help: or `..=` for an inclusive range + | +LL | 0..=..{loop{}1}; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/issue-96335.rs:2:9 + | +LL | 0.....{loop{}1}; + | ----^^^^^^^^^^^ + | | | + | | expected integer, found struct `RangeTo` + | arguments to this function are incorrect + | + = note: expected type `{integer}` + found struct `RangeTo<{integer}>` +note: associated function defined here + --> $SRC_DIR/core/src/ops/range.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/never-assign-dead-code.rs b/tests/ui/never_type/never-assign-dead-code.rs new file mode 100644 index 000000000..7bb7c8709 --- /dev/null +++ b/tests/ui/never_type/never-assign-dead-code.rs @@ -0,0 +1,12 @@ +// Test that an assignment of type ! makes the rest of the block dead code. + +// check-pass + +#![feature(never_type)] +#![warn(unused)] + +fn main() { + let x: ! = panic!("aah"); //~ WARN unused + drop(x); //~ WARN unreachable + //~^ WARN unreachable +} diff --git a/tests/ui/never_type/never-assign-dead-code.stderr b/tests/ui/never_type/never-assign-dead-code.stderr new file mode 100644 index 000000000..521b82023 --- /dev/null +++ b/tests/ui/never_type/never-assign-dead-code.stderr @@ -0,0 +1,33 @@ +warning: unreachable statement + --> $DIR/never-assign-dead-code.rs:10:5 + | +LL | let x: ! = panic!("aah"); + | ------------- any code following this expression is unreachable +LL | drop(x); + | ^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/never-assign-dead-code.rs:6:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` + +warning: unreachable call + --> $DIR/never-assign-dead-code.rs:10:5 + | +LL | drop(x); + | ^^^^ - any code following this expression is unreachable + | | + | unreachable call + +warning: unused variable: `x` + --> $DIR/never-assign-dead-code.rs:9:9 + | +LL | let x: ! = panic!("aah"); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 3 warnings emitted + diff --git a/tests/ui/never_type/never-assign-wrong-type.rs b/tests/ui/never_type/never-assign-wrong-type.rs new file mode 100644 index 000000000..67e26f566 --- /dev/null +++ b/tests/ui/never_type/never-assign-wrong-type.rs @@ -0,0 +1,8 @@ +// Test that we can't use another type in place of ! + +#![feature(never_type)] +#![deny(warnings)] + +fn main() { + let x: ! = "hello"; //~ ERROR mismatched types +} diff --git a/tests/ui/never_type/never-assign-wrong-type.stderr b/tests/ui/never_type/never-assign-wrong-type.stderr new file mode 100644 index 000000000..ce34d9483 --- /dev/null +++ b/tests/ui/never_type/never-assign-wrong-type.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/never-assign-wrong-type.rs:7:16 + | +LL | let x: ! = "hello"; + | - ^^^^^^^ expected `!`, found `&str` + | | + | expected due to this + | + = note: expected type `!` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/never-associated-type.rs b/tests/ui/never_type/never-associated-type.rs new file mode 100644 index 000000000..3bb917c93 --- /dev/null +++ b/tests/ui/never_type/never-associated-type.rs @@ -0,0 +1,23 @@ +// Test that we can use ! as an associated type. + +// check-pass + +#![feature(never_type)] + +trait Foo { + type Wow; + + fn smeg(&self) -> Self::Wow; +} + +struct Blah; +impl Foo for Blah { + type Wow = !; + fn smeg(&self) -> ! { + panic!("kapow!"); + } +} + +fn main() { + Blah.smeg(); +} diff --git a/tests/ui/never_type/never-from-impl-is-reserved.rs b/tests/ui/never_type/never-from-impl-is-reserved.rs new file mode 100644 index 000000000..9d16015bd --- /dev/null +++ b/tests/ui/never_type/never-from-impl-is-reserved.rs @@ -0,0 +1,12 @@ +// check that the `for T: From` impl is reserved + +#![feature(never_type)] + +pub struct MyFoo; +pub trait MyTrait {} + +impl MyTrait for MyFoo {} +// This will conflict with the first impl if we impl `for T: From`. +impl MyTrait for T where T: From {} //~ ERROR conflicting implementation + +fn main() {} diff --git a/tests/ui/never_type/never-from-impl-is-reserved.stderr b/tests/ui/never_type/never-from-impl-is-reserved.stderr new file mode 100644 index 000000000..f9f7c787e --- /dev/null +++ b/tests/ui/never_type/never-from-impl-is-reserved.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo` + --> $DIR/never-from-impl-is-reserved.rs:10:1 + | +LL | impl MyTrait for MyFoo {} + | ---------------------- first implementation here +LL | // This will conflict with the first impl if we impl `for T: From`. +LL | impl MyTrait for T where T: From {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + | + = note: permitting this impl would forbid us from adding `impl From for T` later; see rust-lang/rust#64715 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/never_type/never-result.rs b/tests/ui/never_type/never-result.rs new file mode 100644 index 000000000..35af37910 --- /dev/null +++ b/tests/ui/never_type/never-result.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(unused_variables)] +#![allow(unreachable_code)] + +// Test that we can extract a ! through pattern matching then use it as several different types. + +#![feature(never_type)] + +fn main() { + let x: Result = Ok(123); + match x { + Ok(z) => (), + Err(y) => { + let q: u32 = y; + let w: i32 = y; + let e: String = y; + y + }, + } +} diff --git a/tests/ui/never_type/never-type-arg.rs b/tests/ui/never_type/never-type-arg.rs new file mode 100644 index 000000000..13cd59e6a --- /dev/null +++ b/tests/ui/never_type/never-type-arg.rs @@ -0,0 +1,17 @@ +// Test that we can use ! as an argument to a trait impl. + +// check-pass + +#![feature(never_type)] + +struct Wub; + +impl PartialEq for Wub { + fn eq(&self, other: &!) -> bool { + *other + } +} + +fn main() { + let _ = Wub == panic!("oh no!"); +} diff --git a/tests/ui/never_type/never-type-rvalues.rs b/tests/ui/never_type/never-type-rvalues.rs new file mode 100644 index 000000000..9ccc73dbf --- /dev/null +++ b/tests/ui/never_type/never-type-rvalues.rs @@ -0,0 +1,38 @@ +// run-pass + +#![feature(never_type)] +#![allow(dead_code)] +#![allow(path_statements)] +#![allow(unreachable_patterns)] + +fn never_direct(x: !) { + x; +} + +fn never_ref_pat(ref x: !) { + *x; +} + +fn never_ref(x: &!) { + let &y = x; + y; +} + +fn never_pointer(x: *const !) { + unsafe { + *x; + } +} + +fn never_slice(x: &[!]) { + x[0]; +} + +fn never_match(x: Result<(), !>) { + match x { + Ok(_) => {}, + Err(_) => {}, + } +} + +pub fn main() { } diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr new file mode 100644 index 000000000..06e902bca --- /dev/null +++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `E: From<()>` is not satisfied + --> $DIR/never-value-fallback-issue-66757.rs:28:26 + | +LL | >::from(never); + | -------------------- ^^^^^ the trait `From<()>` is not implemented for `E` + | | + | required by a bound introduced by this call + | + = help: the trait `From` is implemented for `E` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.rs b/tests/ui/never_type/never-value-fallback-issue-66757.rs new file mode 100644 index 000000000..fc6fe6eb5 --- /dev/null +++ b/tests/ui/never_type/never-value-fallback-issue-66757.rs @@ -0,0 +1,31 @@ +// Regression test for #66757 +// +// Test than when you have a `!` value (e.g., the local variable +// never) and an uninferred variable (here the argument to `From`) it +// doesn't fallback to `()` but rather `!`. +// +// revisions: nofallback fallback +//[fallback] run-pass +//[nofallback] check-fail + +#![feature(never_type)] + +#![cfg_attr(fallback, feature(never_type_fallback))] + +struct E; + +impl From for E { + fn from(_: !) -> E { + E + } +} + +#[allow(unreachable_code)] +#[allow(dead_code)] +#[allow(unused_must_use)] +fn foo(never: !) { + >::from(never); // Ok + >::from(never); //[nofallback]~ ERROR trait bound `E: From<()>` is not satisfied +} + +fn main() { } diff --git a/tests/ui/never_type/never_coercions.rs b/tests/ui/never_type/never_coercions.rs new file mode 100644 index 000000000..105c38635 --- /dev/null +++ b/tests/ui/never_type/never_coercions.rs @@ -0,0 +1,12 @@ +// run-pass +// Test that having something of type ! doesn't screw up type-checking and that it coerces to the +// LUB type of the other match arms. + +fn main() { + let v: Vec = Vec::new(); + match 0u32 { + 0 => &v, + 1 => return, + _ => &v[..], + }; +} diff --git a/tests/ui/never_type/never_transmute_never.rs b/tests/ui/never_type/never_transmute_never.rs new file mode 100644 index 000000000..fce3ced9a --- /dev/null +++ b/tests/ui/never_type/never_transmute_never.rs @@ -0,0 +1,23 @@ +// check-pass + +#![crate_type="lib"] + +#![feature(never_type)] +#![allow(dead_code)] +#![allow(unreachable_code)] +#![allow(unused_variables)] + +struct Foo; + +pub fn f(x: !) -> ! { + x +} + +pub fn ub() { + // This is completely undefined behaviour, + // but we still want to make sure it compiles. + let x: ! = unsafe { + std::mem::transmute::(Foo) + }; + f(x) +} diff --git a/tests/ui/never_type/return-never-coerce.rs b/tests/ui/never_type/return-never-coerce.rs new file mode 100644 index 000000000..d615940ef --- /dev/null +++ b/tests/ui/never_type/return-never-coerce.rs @@ -0,0 +1,18 @@ +// Test that ! coerces to other types. + +// run-fail +// error-pattern:aah! +// ignore-emscripten no processes + +fn call_another_fn T>(f: F) -> T { + f() +} + +fn wub() -> ! { + panic!("aah!"); +} + +fn main() { + let x: i32 = call_another_fn(wub); + let y: u32 = wub(); +} diff --git a/tests/ui/never_type/try_from.rs b/tests/ui/never_type/try_from.rs new file mode 100644 index 000000000..50451576f --- /dev/null +++ b/tests/ui/never_type/try_from.rs @@ -0,0 +1,37 @@ +// run-pass +// This test relies on `TryFrom` being blanket impl for all `T: Into` +// and `TryInto` being blanket impl for all `U: TryFrom` + +// This test was added to show the motivation for doing this +// over `TryFrom` being blanket impl for all `T: From` + +#![feature(never_type)] + +use std::convert::{TryInto, Infallible}; + +struct Foo { + t: T, +} + +// This fails to compile due to coherence restrictions +// as of Rust version 1.32.x, therefore it could not be used +// instead of the `Into` version of the impl, and serves as +// motivation for a blanket impl for all `T: Into`, instead +// of a blanket impl for all `T: From` +/* +impl From> for Box { + fn from(foo: Foo) -> Box { + Box::new(foo.t) + } +} +*/ + +impl Into> for Foo { + fn into(self) -> Vec { + vec![self.t] + } +} + +pub fn main() { + let _: Result, Infallible> = Foo { t: 10 }.try_into(); +} diff --git a/tests/ui/new-impl-syntax.rs b/tests/ui/new-impl-syntax.rs new file mode 100644 index 000000000..e1f2bea9a --- /dev/null +++ b/tests/ui/new-impl-syntax.rs @@ -0,0 +1,29 @@ +// run-pass + +use std::fmt; + +struct Thingy { + x: isize, + y: isize +} + +impl fmt::Debug for Thingy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{{ x: {:?}, y: {:?} }}", self.x, self.y) + } +} + +struct PolymorphicThingy { + x: T +} + +impl fmt::Debug for PolymorphicThingy { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.x) + } +} + +pub fn main() { + println!("{:?}", Thingy { x: 1, y: 2 }); + println!("{:?}", PolymorphicThingy { x: Thingy { x: 1, y: 2 } }); +} diff --git a/tests/ui/new-import-syntax.rs b/tests/ui/new-import-syntax.rs new file mode 100644 index 000000000..f132ed57c --- /dev/null +++ b/tests/ui/new-import-syntax.rs @@ -0,0 +1,5 @@ +// run-pass + +pub fn main() { + println!("Hello world!"); +} diff --git a/tests/ui/new-style-constants.rs b/tests/ui/new-style-constants.rs new file mode 100644 index 000000000..82ed7b557 --- /dev/null +++ b/tests/ui/new-style-constants.rs @@ -0,0 +1,7 @@ +// run-pass + +static FOO: isize = 3; + +pub fn main() { + println!("{}", FOO); +} diff --git a/tests/ui/new-unicode-escapes.rs b/tests/ui/new-unicode-escapes.rs new file mode 100644 index 000000000..850b0de44 --- /dev/null +++ b/tests/ui/new-unicode-escapes.rs @@ -0,0 +1,14 @@ +// run-pass + +pub fn main() { + let s = "\u{2603}"; + assert_eq!(s, "☃"); + + let s = "\u{2a10}\u{2A01}\u{2Aa0}"; + assert_eq!(s, "â¨â¨âª "); + + let s = "\\{20}"; + let mut correct_s = String::from("\\"); + correct_s.push_str("{20}"); + assert_eq!(s, correct_s); +} diff --git a/tests/ui/new-unsafe-pointers.rs b/tests/ui/new-unsafe-pointers.rs new file mode 100644 index 000000000..d99eb4cbd --- /dev/null +++ b/tests/ui/new-unsafe-pointers.rs @@ -0,0 +1,7 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + let _a: *const isize = 3 as *const isize; + let _a: *mut isize = 3 as *mut isize; +} diff --git a/tests/ui/newlambdas.rs b/tests/ui/newlambdas.rs new file mode 100644 index 000000000..90de53856 --- /dev/null +++ b/tests/ui/newlambdas.rs @@ -0,0 +1,14 @@ +// run-pass +// Tests for the new |args| expr lambda syntax + + +fn f(i: isize, f: F) -> isize where F: FnOnce(isize) -> isize { f(i) } + +fn g(_g: G) where G: FnOnce() { } + +pub fn main() { + assert_eq!(f(10, |a| a), 10); + g(||()); + assert_eq!(f(10, |a| a), 10); + g(||{}); +} diff --git a/tests/ui/newtype-polymorphic.rs b/tests/ui/newtype-polymorphic.rs new file mode 100644 index 000000000..a6a725211 --- /dev/null +++ b/tests/ui/newtype-polymorphic.rs @@ -0,0 +1,27 @@ +// run-pass + +#![allow(non_camel_case_types)] + + +#[derive(Clone)] +struct myvec(Vec ); + +fn myvec_deref(mv: myvec) -> Vec { + let myvec(v) = mv; + return v.clone(); +} + +fn myvec_elt(mv: myvec) -> X { + let myvec(v) = mv; + return v.into_iter().next().unwrap(); +} + +pub fn main() { + let mv = myvec(vec![1, 2, 3]); + let mv_clone = mv.clone(); + let mv_clone = myvec_deref(mv_clone); + assert_eq!(mv_clone[1], 2); + assert_eq!(myvec_elt(mv.clone()), 1); + let myvec(v) = mv; + assert_eq!(v[2], 3); +} diff --git a/tests/ui/newtype.rs b/tests/ui/newtype.rs new file mode 100644 index 000000000..f02b66f45 --- /dev/null +++ b/tests/ui/newtype.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(non_camel_case_types)] +#[derive(Copy, Clone)] +struct mytype(Mytype); + +#[derive(Copy, Clone)] +struct Mytype { + compute: fn(mytype) -> isize, + val: isize, +} + +fn compute(i: mytype) -> isize { + let mytype(m) = i; + return m.val + 20; +} + +pub fn main() { + let myval = mytype(Mytype{compute: compute, val: 30}); + println!("{}", compute(myval)); + let mytype(m) = myval; + assert_eq!((m.compute)(myval), 50); +} diff --git a/tests/ui/nll/assign-while-to-immutable.rs b/tests/ui/nll/assign-while-to-immutable.rs new file mode 100644 index 000000000..c803321b5 --- /dev/null +++ b/tests/ui/nll/assign-while-to-immutable.rs @@ -0,0 +1,11 @@ +// We used to incorrectly assign to `x` twice when generating MIR for this +// function, preventing this from compiling. + +// check-pass + +fn main() { + let x = while false { + break; + }; + let y = 'l: while break 'l {}; +} diff --git a/tests/ui/nll/borrow-use-issue-46875.rs b/tests/ui/nll/borrow-use-issue-46875.rs new file mode 100644 index 000000000..42e28b967 --- /dev/null +++ b/tests/ui/nll/borrow-use-issue-46875.rs @@ -0,0 +1,18 @@ +// run-pass + +fn vec() { + let mut _x = vec!['c']; + let _y = &_x; + _x = Vec::new(); +} + +fn int() { + let mut _x = 5; + let _y = &_x; + _x = 7; +} + +fn main() { + vec(); + int(); +} diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs new file mode 100644 index 000000000..7d3b00dfc --- /dev/null +++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs @@ -0,0 +1,25 @@ +// +// run-pass +// +// FIXME(#54366) - We probably shouldn't allow #[thread_local] static mut to get a 'static lifetime. + +#![feature(thread_local)] + +#[thread_local] +static mut X1: u64 = 0; + +struct S1 { + a: &'static mut u64, +} + +impl S1 { + fn new(_x: u64) -> S1 { + S1 { + a: unsafe { &mut X1 }, + } + } +} + +fn main() { + S1::new(0).a; +} diff --git a/tests/ui/nll/borrowed-local-error.rs b/tests/ui/nll/borrowed-local-error.rs new file mode 100644 index 000000000..d333356d9 --- /dev/null +++ b/tests/ui/nll/borrowed-local-error.rs @@ -0,0 +1,12 @@ +fn gimme(x: &(u32,)) -> &u32 { + &x.0 +} + +fn main() { + let x = gimme({ + let v = (22,); + &v + //~^ ERROR `v` does not live long enough [E0597] + }); + println!("{:?}", x); +} diff --git a/tests/ui/nll/borrowed-local-error.stderr b/tests/ui/nll/borrowed-local-error.stderr new file mode 100644 index 000000000..d629caa43 --- /dev/null +++ b/tests/ui/nll/borrowed-local-error.stderr @@ -0,0 +1,15 @@ +error[E0597]: `v` does not live long enough + --> $DIR/borrowed-local-error.rs:8:9 + | +LL | let x = gimme({ + | ----- borrow later used by call +LL | let v = (22,); +LL | &v + | ^^ borrowed value does not live long enough +LL | +LL | }); + | - `v` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/borrowed-match-issue-45045.rs b/tests/ui/nll/borrowed-match-issue-45045.rs new file mode 100644 index 000000000..978eeb868 --- /dev/null +++ b/tests/ui/nll/borrowed-match-issue-45045.rs @@ -0,0 +1,18 @@ +// Regression test for issue #45045 + +enum Xyz { + A, + B, +} + +fn main() { + let mut e = Xyz::A; + let f = &mut e; + let g = f; + match e { + //~^ cannot use `e` because it was mutably borrowed [E0503] + Xyz::A => println!("a"), + Xyz::B => println!("b"), + }; + *g = Xyz::B; +} diff --git a/tests/ui/nll/borrowed-match-issue-45045.stderr b/tests/ui/nll/borrowed-match-issue-45045.stderr new file mode 100644 index 000000000..9d4682667 --- /dev/null +++ b/tests/ui/nll/borrowed-match-issue-45045.stderr @@ -0,0 +1,15 @@ +error[E0503]: cannot use `e` because it was mutably borrowed + --> $DIR/borrowed-match-issue-45045.rs:12:11 + | +LL | let f = &mut e; + | ------ borrow of `e` occurs here +LL | let g = f; +LL | match e { + | ^ use of borrowed `e` +... +LL | *g = Xyz::B; + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/borrowed-referent-issue-38899.rs b/tests/ui/nll/borrowed-referent-issue-38899.rs new file mode 100644 index 000000000..1fe133283 --- /dev/null +++ b/tests/ui/nll/borrowed-referent-issue-38899.rs @@ -0,0 +1,17 @@ +// Regression test for issue #38899 + +pub struct Block<'a> { + current: &'a u8, + unrelated: &'a u8, +} + +fn bump<'a>(mut block: &mut Block<'a>) { + let x = &mut block; + println!("{}", x.current); + let p: &'a u8 = &*block.current; + //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable + drop(x); + drop(p); +} + +fn main() {} diff --git a/tests/ui/nll/borrowed-referent-issue-38899.stderr b/tests/ui/nll/borrowed-referent-issue-38899.stderr new file mode 100644 index 000000000..16588cbcf --- /dev/null +++ b/tests/ui/nll/borrowed-referent-issue-38899.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable + --> $DIR/borrowed-referent-issue-38899.rs:11:21 + | +LL | let x = &mut block; + | ---------- mutable borrow occurs here +LL | println!("{}", x.current); +LL | let p: &'a u8 = &*block.current; + | ^^^^^^^^^^^^^^^ immutable borrow occurs here +LL | +LL | drop(x); + | - mutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/borrowed-temporary-error.rs b/tests/ui/nll/borrowed-temporary-error.rs new file mode 100644 index 000000000..37d0e670d --- /dev/null +++ b/tests/ui/nll/borrowed-temporary-error.rs @@ -0,0 +1,12 @@ +fn gimme(x: &(u32,)) -> &u32 { + &x.0 +} + +fn main() { + let x = gimme({ + let v = 22; + &(v,) + //~^ ERROR temporary value dropped while borrowed [E0716] + }); + println!("{:?}", x); +} diff --git a/tests/ui/nll/borrowed-temporary-error.stderr b/tests/ui/nll/borrowed-temporary-error.stderr new file mode 100644 index 000000000..89781d96f --- /dev/null +++ b/tests/ui/nll/borrowed-temporary-error.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowed-temporary-error.rs:8:10 + | +LL | &(v,) + | ^^^^ creates a temporary value which is freed while still in use +LL | +LL | }); + | - temporary value is freed at the end of this statement +LL | println!("{:?}", x); + | - borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/nll/borrowed-universal-error-2.rs b/tests/ui/nll/borrowed-universal-error-2.rs new file mode 100644 index 000000000..3f9b2f292 --- /dev/null +++ b/tests/ui/nll/borrowed-universal-error-2.rs @@ -0,0 +1,7 @@ +fn foo<'a>(x: &'a (u32,)) -> &'a u32 { + let v = 22; + &v + //~^ ERROR cannot return reference to local variable `v` [E0515] +} + +fn main() {} diff --git a/tests/ui/nll/borrowed-universal-error-2.stderr b/tests/ui/nll/borrowed-universal-error-2.stderr new file mode 100644 index 000000000..7213ed3ba --- /dev/null +++ b/tests/ui/nll/borrowed-universal-error-2.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to local variable `v` + --> $DIR/borrowed-universal-error-2.rs:3:5 + | +LL | &v + | ^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/borrowed-universal-error.rs b/tests/ui/nll/borrowed-universal-error.rs new file mode 100644 index 000000000..fc9ffd470 --- /dev/null +++ b/tests/ui/nll/borrowed-universal-error.rs @@ -0,0 +1,11 @@ +fn gimme(x: &(u32,)) -> &u32 { + &x.0 +} + +fn foo<'a>(x: &'a (u32,)) -> &'a u32 { + let v = 22; + gimme(&(v,)) + //~^ ERROR cannot return value referencing temporary value [E0515] +} + +fn main() {} diff --git a/tests/ui/nll/borrowed-universal-error.stderr b/tests/ui/nll/borrowed-universal-error.stderr new file mode 100644 index 000000000..88a2d8fcf --- /dev/null +++ b/tests/ui/nll/borrowed-universal-error.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/borrowed-universal-error.rs:7:5 + | +LL | gimme(&(v,)) + | ^^^^^^^----^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/cannot-move-block-spans.rs b/tests/ui/nll/cannot-move-block-spans.rs new file mode 100644 index 000000000..e994fd3d5 --- /dev/null +++ b/tests/ui/nll/cannot-move-block-spans.rs @@ -0,0 +1,22 @@ +// Test that the we point to the inner expression when moving out to initialize +// a variable, and that we don't give a useless suggestion such as &{ *r }. + +pub fn deref(r: &String) { + let x = { *r }; //~ ERROR + let y = unsafe { *r }; //~ ERROR + let z = loop { break *r; }; //~ ERROR +} + +pub fn index(arr: [String; 2]) { + let x = { arr[0] }; //~ ERROR + let y = unsafe { arr[0] }; //~ ERROR + let z = loop { break arr[0]; }; //~ ERROR +} + +pub fn additional_statement_cases(r: &String) { + let x = { let mut u = 0; u += 1; *r }; //~ ERROR + let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR + let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/cannot-move-block-spans.stderr b/tests/ui/nll/cannot-move-block-spans.stderr new file mode 100644 index 000000000..0dc5c08ea --- /dev/null +++ b/tests/ui/nll/cannot-move-block-spans.stderr @@ -0,0 +1,118 @@ +error[E0507]: cannot move out of `*r` which is behind a shared reference + --> $DIR/cannot-move-block-spans.rs:5:15 + | +LL | let x = { *r }; + | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let x = { *r }; +LL + let x = { r }; + | + +error[E0507]: cannot move out of `*r` which is behind a shared reference + --> $DIR/cannot-move-block-spans.rs:6:22 + | +LL | let y = unsafe { *r }; + | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let y = unsafe { *r }; +LL + let y = unsafe { r }; + | + +error[E0507]: cannot move out of `*r` which is behind a shared reference + --> $DIR/cannot-move-block-spans.rs:7:26 + | +LL | let z = loop { break *r; }; + | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let z = loop { break *r; }; +LL + let z = loop { break r; }; + | + +error[E0508]: cannot move out of type `[String; 2]`, a non-copy array + --> $DIR/cannot-move-block-spans.rs:11:15 + | +LL | let x = { arr[0] }; + | ^^^^^^ + | | + | cannot move out of here + | move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let x = { &arr[0] }; + | + + +error[E0508]: cannot move out of type `[String; 2]`, a non-copy array + --> $DIR/cannot-move-block-spans.rs:12:22 + | +LL | let y = unsafe { arr[0] }; + | ^^^^^^ + | | + | cannot move out of here + | move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let y = unsafe { &arr[0] }; + | + + +error[E0508]: cannot move out of type `[String; 2]`, a non-copy array + --> $DIR/cannot-move-block-spans.rs:13:26 + | +LL | let z = loop { break arr[0]; }; + | ^^^^^^ + | | + | cannot move out of here + | move occurs because `arr[_]` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let z = loop { break &arr[0]; }; + | + + +error[E0507]: cannot move out of `*r` which is behind a shared reference + --> $DIR/cannot-move-block-spans.rs:17:38 + | +LL | let x = { let mut u = 0; u += 1; *r }; + | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let x = { let mut u = 0; u += 1; *r }; +LL + let x = { let mut u = 0; u += 1; r }; + | + +error[E0507]: cannot move out of `*r` which is behind a shared reference + --> $DIR/cannot-move-block-spans.rs:18:45 + | +LL | let y = unsafe { let mut u = 0; u += 1; *r }; + | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let y = unsafe { let mut u = 0; u += 1; *r }; +LL + let y = unsafe { let mut u = 0; u += 1; r }; + | + +error[E0507]: cannot move out of `*r` which is behind a shared reference + --> $DIR/cannot-move-block-spans.rs:19:49 + | +LL | let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; + | ^^ move occurs because `*r` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; +LL + let z = loop { let mut u = 0; u += 1; break r; u += 2; }; + | + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0507, E0508. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/capture-mut-ref.fixed b/tests/ui/nll/capture-mut-ref.fixed new file mode 100644 index 000000000..2dacb26b6 --- /dev/null +++ b/tests/ui/nll/capture-mut-ref.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +// Check that capturing a mutable reference by move and assigning to its +// referent doesn't make the unused mut lint think that it is mutable. + +#![deny(unused_mut)] + +pub fn mutable_upvar() { + let x = &mut 0; + //~^ ERROR + let _ = move || { + *x = 1; + }; +} + +fn main() {} diff --git a/tests/ui/nll/capture-mut-ref.rs b/tests/ui/nll/capture-mut-ref.rs new file mode 100644 index 000000000..56e01f7b7 --- /dev/null +++ b/tests/ui/nll/capture-mut-ref.rs @@ -0,0 +1,16 @@ +// run-rustfix + +// Check that capturing a mutable reference by move and assigning to its +// referent doesn't make the unused mut lint think that it is mutable. + +#![deny(unused_mut)] + +pub fn mutable_upvar() { + let mut x = &mut 0; + //~^ ERROR + let _ = move || { + *x = 1; + }; +} + +fn main() {} diff --git a/tests/ui/nll/capture-mut-ref.stderr b/tests/ui/nll/capture-mut-ref.stderr new file mode 100644 index 000000000..4898d5692 --- /dev/null +++ b/tests/ui/nll/capture-mut-ref.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/capture-mut-ref.rs:9:9 + | +LL | let mut x = &mut 0; + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/capture-mut-ref.rs:6:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/nll/capture-ref-in-struct.rs b/tests/ui/nll/capture-ref-in-struct.rs new file mode 100644 index 000000000..db6ac7d66 --- /dev/null +++ b/tests/ui/nll/capture-ref-in-struct.rs @@ -0,0 +1,36 @@ +// Test that a structure which tries to store a pointer to `y` into +// `p` (indirectly) fails to compile. + +struct SomeStruct<'a, 'b: 'a> { + p: &'a mut &'b i32, + y: &'b i32, +} + +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + + let closure = SomeStruct { + p: &mut p, + y: &y, + //~^ ERROR `y` does not live long enough [E0597] + }; + + closure.invoke(); + } + + deref(p); +} + +impl<'a, 'b> SomeStruct<'a, 'b> { + fn invoke(self) { + *self.p = self.y; + } +} + +fn deref(_: &i32) { } + +fn main() { } diff --git a/tests/ui/nll/capture-ref-in-struct.stderr b/tests/ui/nll/capture-ref-in-struct.stderr new file mode 100644 index 000000000..cdfe7f6db --- /dev/null +++ b/tests/ui/nll/capture-ref-in-struct.stderr @@ -0,0 +1,15 @@ +error[E0597]: `y` does not live long enough + --> $DIR/capture-ref-in-struct.rs:18:16 + | +LL | y: &y, + | ^^ borrowed value does not live long enough +... +LL | } + | - `y` dropped here while still borrowed +LL | +LL | deref(p); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-access-spans.rs b/tests/ui/nll/closure-access-spans.rs new file mode 100644 index 000000000..2a59e80b2 --- /dev/null +++ b/tests/ui/nll/closure-access-spans.rs @@ -0,0 +1,56 @@ +// check that accesses due to a closure capture give a special note + +fn closure_imm_capture_conflict(mut x: i32) { + let r = &mut x; + || x; //~ ERROR + r.use_mut(); +} + +fn closure_mut_capture_conflict(mut x: i32) { + let r = &mut x; + || x = 2; //~ ERROR + r.use_mut(); +} + +fn closure_unique_capture_conflict(mut x: &mut i32) { + let r = &mut x; + || *x = 2; //~ ERROR + r.use_mut(); +} + +fn closure_copy_capture_conflict(mut x: i32) { + let r = &mut x; + move || x; //~ ERROR + r.use_ref(); +} + +fn closure_move_capture_conflict(mut x: String) { + let r = &x; + || x; //~ ERROR + r.use_ref(); +} + +fn closure_imm_capture_moved(mut x: String) { + let r = x; + || x.len(); //~ ERROR +} + +fn closure_mut_capture_moved(mut x: String) { + let r = x; + || x = String::new(); //~ ERROR +} + +fn closure_unique_capture_moved(x: &mut String) { + let r = x; + || *x = String::new(); //~ ERROR +} + +fn closure_move_capture_moved(x: &mut String) { + let r = x; + || x; //~ ERROR +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/nll/closure-access-spans.stderr b/tests/ui/nll/closure-access-spans.stderr new file mode 100644 index 000000000..0a09353b8 --- /dev/null +++ b/tests/ui/nll/closure-access-spans.stderr @@ -0,0 +1,120 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/closure-access-spans.rs:5:5 + | +LL | let r = &mut x; + | ------ mutable borrow occurs here +LL | || x; + | ^^ - second borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | r.use_mut(); + | ----------- mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closure-access-spans.rs:11:5 + | +LL | let r = &mut x; + | ------ first mutable borrow occurs here +LL | || x = 2; + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | r.use_mut(); + | ----------- first borrow later used here + +error[E0500]: closure requires unique access to `x` but it is already borrowed + --> $DIR/closure-access-spans.rs:17:5 + | +LL | let r = &mut x; + | ------ borrow occurs here +LL | || *x = 2; + | ^^ -- second borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | r.use_mut(); + | ----------- first borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/closure-access-spans.rs:23:13 + | +LL | let r = &mut x; + | ------ borrow of `x` occurs here +LL | move || x; + | ^ use of borrowed `x` +LL | r.use_ref(); + | ----------- borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-access-spans.rs:29:5 + | +LL | let r = &x; + | -- borrow of `x` occurs here +LL | || x; + | ^^ - move occurs due to use in closure + | | + | move out of `x` occurs here +LL | r.use_ref(); + | ----------- borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:35:5 + | +LL | fn closure_imm_capture_moved(mut x: String) { + | ----- move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let r = x; + | - value moved here +LL | || x.len(); + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let r = x.clone(); + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:40:5 + | +LL | fn closure_mut_capture_moved(mut x: String) { + | ----- move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let r = x; + | - value moved here +LL | || x = String::new(); + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let r = x.clone(); + | ++++++++ + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:45:5 + | +LL | fn closure_unique_capture_moved(x: &mut String) { + | - move occurs because `x` has type `&mut String`, which does not implement the `Copy` trait +LL | let r = x; + | - value moved here +LL | || *x = String::new(); + | ^^ -- borrow occurs due to use in closure + | | + | value borrowed here after move + +error[E0382]: use of moved value: `x` + --> $DIR/closure-access-spans.rs:50:5 + | +LL | fn closure_move_capture_moved(x: &mut String) { + | - move occurs because `x` has type `&mut String`, which does not implement the `Copy` trait +LL | let r = x; + | - value moved here +LL | || x; + | ^^ - use occurs due to use in closure + | | + | value used here after move + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0382, E0499, E0500, E0502, E0503, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/closure-borrow-spans.rs b/tests/ui/nll/closure-borrow-spans.rs new file mode 100644 index 000000000..b38f7900e --- /dev/null +++ b/tests/ui/nll/closure-borrow-spans.rs @@ -0,0 +1,100 @@ +// check that existing borrows due to a closure capture give a special note + +fn move_while_borrowed(x: String) { + let f = || x.len(); + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed(mut x: i32) { + let f = || x; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed() { + let f; + { + let x = 1; + f = || x; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed(mut x: i32) { + let f = || x; + x = 1; //~ ERROR + f.use_ref(); +} + +fn copy_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = &x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed_mut() { + let f; + { + let mut x = 1; + f = || x = 0; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + x = 1; //~ ERROR + f.use_ref(); +} + +fn copy_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + let y = &x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed_unique(mut x: &mut i32) { + let f = || *x = 0; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed_unique() { + let mut z = 1; + let f; + { + let x = &mut z; + f = || *x = 0; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + *x = 1; //~ ERROR + f.use_ref(); +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/nll/closure-borrow-spans.stderr b/tests/ui/nll/closure-borrow-spans.stderr new file mode 100644 index 000000000..bada4e1b8 --- /dev/null +++ b/tests/ui/nll/closure-borrow-spans.stderr @@ -0,0 +1,172 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:5:13 + | +LL | let f = || x.len(); + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | let y = x; + | ^ move out of `x` occurs here +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/closure-borrow-spans.rs:11:13 + | +LL | let f = || x; + | -- - first borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | let y = &mut x; + | ^^^^^^ mutable borrow occurs here +LL | f.use_ref(); + | ----------- immutable borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:19:16 + | +LL | f = || x; + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:26:5 + | +LL | let f = || x; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/closure-borrow-spans.rs:32:13 + | +LL | let f = || x = 0; + | -- - borrow occurs due to use of `x` in closure + | | + | borrow of `x` occurs here +LL | let y = x; + | ^ use of borrowed `x` +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/closure-borrow-spans.rs:38:13 + | +LL | let f = || x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | let y = &x; + | ^^ immutable borrow occurs here +LL | f.use_ref(); + | ----------- mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closure-borrow-spans.rs:44:13 + | +LL | let f = || x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let y = &mut x; + | ^^^^^^ second mutable borrow occurs here +LL | f.use_ref(); + | ----------- first borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:52:16 + | +LL | f = || x = 0; + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:59:5 + | +LL | let f = || x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:65:13 + | +LL | let f = || *x = 0; + | -- -- borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | let y = x; + | ^ move out of `x` occurs here +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/closure-borrow-spans.rs:71:13 + | +LL | let f = || *x = 0; + | -- -- first borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | let y = &x; + | ^^ second borrow occurs here +LL | f.use_ref(); + | ----------- first borrow later used here + +error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access + --> $DIR/closure-borrow-spans.rs:77:13 + | +LL | let f = || *x = 0; + | -- -- first borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | let y = &mut x; + | ^^^^^^ second borrow occurs here +LL | f.use_ref(); + | ----------- first borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:86:16 + | +LL | f = || *x = 0; + | -- ^^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | ----------- borrow later used here + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:93:5 + | +LL | let f = || *x = 0; + | -- -- borrow occurs due to use in closure + | | + | borrow of `*x` occurs here +LL | *x = 1; + | ^^^^^^ assignment to borrowed `*x` occurs here +LL | f.use_ref(); + | ----------- borrow later used here + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0499, E0501, E0502, E0503, E0505, E0506, E0597. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/closure-captures.rs b/tests/ui/nll/closure-captures.rs new file mode 100644 index 000000000..16d90b971 --- /dev/null +++ b/tests/ui/nll/closure-captures.rs @@ -0,0 +1,55 @@ +// Some cases with closures that might be problems + +// Should have one error per assignment + +fn one_closure(x: i32) { + || + x = 1; //~ ERROR + move || + x = 1; //~ ERROR +} + +fn two_closures(x: i32) { + || { + || + x = 1; //~ ERROR + }; + move || { + || + x = 1; //~ ERROR + }; +} + +fn fn_ref(f: F) -> F { f } + +fn two_closures_ref_mut(mut x: i32) { + fn_ref(|| { + || //~ ERROR + x = 1;} + ); + fn_ref(move || { + || //~ ERROR + x = 1;}); +} + +// This still gives two messages, but it requires two things to be fixed. +fn two_closures_ref(x: i32) { + fn_ref(|| { + || //~ ERROR + x = 1;} //~ ERROR + ); + fn_ref(move || { + || //~ ERROR + x = 1;}); //~ ERROR +} + +fn two_closures_two_refs(x: &mut i32) { + fn_ref(|| { + || //~ ERROR + *x = 1;}); + fn_ref(move || { + || //~ ERROR + *x = 1;}); +} + +fn main() {} diff --git a/tests/ui/nll/closure-captures.stderr b/tests/ui/nll/closure-captures.stderr new file mode 100644 index 000000000..5233f0b24 --- /dev/null +++ b/tests/ui/nll/closure-captures.stderr @@ -0,0 +1,148 @@ +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/closure-captures.rs:7:5 + | +LL | fn one_closure(x: i32) { + | - help: consider changing this to be mutable: `mut x` +LL | || +LL | x = 1; + | ^^^^^ cannot assign + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/closure-captures.rs:9:5 + | +LL | fn one_closure(x: i32) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x = 1; + | ^^^^^ cannot assign + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/closure-captures.rs:15:9 + | +LL | fn two_closures(x: i32) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x = 1; + | ^^^^^ cannot assign + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/closure-captures.rs:19:9 + | +LL | fn two_closures(x: i32) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x = 1; + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/closure-captures.rs:27:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;} + | - mutable borrow occurs due to use of `x` in closure + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/closure-captures.rs:31:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;}); + | - mutable borrow occurs due to use of `x` in closure + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/closure-captures.rs:39:10 + | +LL | fn two_closures_ref(x: i32) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x = 1;} + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/closure-captures.rs:38:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;} + | - mutable borrow occurs due to use of `x` in closure + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/closure-captures.rs:43:5 + | +LL | fn two_closures_ref(x: i32) { + | - help: consider changing this to be mutable: `mut x` +... +LL | x = 1;}); + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/closure-captures.rs:42:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | x = 1;}); + | - mutable borrow occurs due to use of `x` in closure + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/closure-captures.rs:48:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(|| { + | ------ -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | *x = 1;}); + | -- mutable borrow occurs due to use of `x` in closure + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/closure-captures.rs:51:9 + | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | fn_ref(move || { + | ------ ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | || + | ^^ cannot borrow as mutable +LL | *x = 1;}); + | -- mutable borrow occurs due to use of `x` in closure + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/closure-malformed-projection-input-issue-102800.rs b/tests/ui/nll/closure-malformed-projection-input-issue-102800.rs new file mode 100644 index 000000000..260c16c17 --- /dev/null +++ b/tests/ui/nll/closure-malformed-projection-input-issue-102800.rs @@ -0,0 +1,21 @@ +// Regression test for #102800 +// +// Here we are generating higher-ranked region constraints when normalizing and relating closure +// input types. Previously this was an ICE in the error path because we didn't register enough +// diagnostic information to render the higher-ranked subtyping error. + +// check-fail + +trait Trait { + type Ty; +} + +impl Trait for &'static () { + type Ty = (); +} + +fn main() { + let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; + //~^ ERROR implementation of `Trait` is not general enough + //~| ERROR implementation of `Trait` is not general enough +} diff --git a/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr b/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr new file mode 100644 index 000000000..46dba0064 --- /dev/null +++ b/tests/ui/nll/closure-malformed-projection-input-issue-102800.stderr @@ -0,0 +1,20 @@ +error: implementation of `Trait` is not general enough + --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12 + | +LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... + = note: ...but `Trait` is actually implemented for the type `&'static ()` + +error: implementation of `Trait` is not general enough + --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12 + | +LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`... + = note: ...but `Trait` is actually implemented for the type `&'static ()` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/closure-move-spans.rs b/tests/ui/nll/closure-move-spans.rs new file mode 100644 index 000000000..bf2431870 --- /dev/null +++ b/tests/ui/nll/closure-move-spans.rs @@ -0,0 +1,21 @@ +// check that moves due to a closure capture give a special note + +fn move_after_move(x: String) { + || x; + let y = x; //~ ERROR +} + +fn borrow_after_move(x: String) { + || x; + let y = &x; //~ ERROR +} + +fn borrow_mut_after_move(mut x: String) { + || x; + let y = &mut x; //~ ERROR +} + +fn fn_ref(f: F) -> F { f } +fn fn_mut(f: F) -> F { f } + +fn main() {} diff --git a/tests/ui/nll/closure-move-spans.stderr b/tests/ui/nll/closure-move-spans.stderr new file mode 100644 index 000000000..0446ef7b0 --- /dev/null +++ b/tests/ui/nll/closure-move-spans.stderr @@ -0,0 +1,39 @@ +error[E0382]: use of moved value: `x` + --> $DIR/closure-move-spans.rs:5:13 + | +LL | fn move_after_move(x: String) { + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = x; + | ^ value used here after move + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-move-spans.rs:10:13 + | +LL | fn borrow_after_move(x: String) { + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = &x; + | ^^ value borrowed here after move + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-move-spans.rs:15:13 + | +LL | fn borrow_mut_after_move(mut x: String) { + | ----- move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = &mut x; + | ^^^^^^ value borrowed here after move + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.rs b/tests/ui/nll/closure-requirements/escape-argument-callee.rs new file mode 100644 index 000000000..3aea511b0 --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.rs @@ -0,0 +1,42 @@ +// Test closure that: +// +// - takes an argument `y` with lifetime `'a` (in the code, it's anonymous) +// - stores `y` into another, longer-lived spot with lifetime `'b` +// +// Because `'a` and `'b` are two different, unrelated higher-ranked +// regions with no relationship to one another, this is an error. This +// error is reported by the closure itself and is not propagated to +// its creator: this is because `'a` and `'b` are higher-ranked +// (late-bound) regions and the closure is not allowed to propagate +// additional where clauses between higher-ranked regions, only those +// that appear free in its type (hence, we see it before the closure's +// "external requirements" report). + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + let mut closure = expect_sig(|p, y| *p = y); + //~^ ERROR + closure(&mut p, &y); + } + + deref(p); +} + +fn expect_sig(f: F) -> F + where F: FnMut(&mut &i32, &i32) +{ + f +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr new file mode 100644 index 000000000..363ddfaff --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -0,0 +1,31 @@ +note: no external requirements + --> $DIR/escape-argument-callee.rs:26:38 + | +LL | let mut closure = expect_sig(|p, y| *p = y); + | ^^^^^^ + | + = note: defining type: test::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) i32)), + (), + ] + +error: lifetime may not live long enough + --> $DIR/escape-argument-callee.rs:26:45 + | +LL | let mut closure = expect_sig(|p, y| *p = y); + | - - ^^^^^^ assignment requires that `'1` must outlive `'2` + | | | + | | has type `&'1 i32` + | has type `&'_#2r mut &'2 i32` + +note: no external requirements + --> $DIR/escape-argument-callee.rs:20:1 + | +LL | fn test() { + | ^^^^^^^^^ + | + = note: defining type: test + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/escape-argument.rs b/tests/ui/nll/closure-requirements/escape-argument.rs new file mode 100644 index 000000000..066cd4360 --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-argument.rs @@ -0,0 +1,42 @@ +// Test closure that: +// +// - takes an argument `y` +// - stores `y` into another, longer-lived spot +// +// but is invoked with a spot that doesn't live long +// enough to store `y`. +// +// The error is reported in the caller: invoking the closure links the +// lifetime of the variable that is given as `y` (via subtyping) and +// thus forces the corresponding borrow to live too long. This is +// basically checking that the MIR type checker correctly enforces the +// closure signature. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + let mut closure = expect_sig(|p, y| *p = y); + closure(&mut p, &y); + //~^ ERROR `y` does not live long enough [E0597] + } + + deref(p); +} + +fn expect_sig(f: F) -> F + where F: for<'a, 'b> FnMut(&'a mut &'b i32, &'b i32) +{ + f +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr new file mode 100644 index 000000000..f67c312b9 --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-argument.stderr @@ -0,0 +1,35 @@ +note: no external requirements + --> $DIR/escape-argument.rs:26:38 + | +LL | let mut closure = expect_sig(|p, y| *p = y); + | ^^^^^^ + | + = note: defining type: test::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)), + (), + ] + +note: no external requirements + --> $DIR/escape-argument.rs:20:1 + | +LL | fn test() { + | ^^^^^^^^^ + | + = note: defining type: test + +error[E0597]: `y` does not live long enough + --> $DIR/escape-argument.rs:27:25 + | +LL | closure(&mut p, &y); + | ^^ borrowed value does not live long enough +LL | +LL | } + | - `y` dropped here while still borrowed +LL | +LL | deref(p); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/escape-upvar-nested.rs b/tests/ui/nll/closure-requirements/escape-upvar-nested.rs new file mode 100644 index 000000000..765a3cf96 --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-upvar-nested.rs @@ -0,0 +1,33 @@ +// As in `escape-upvar-ref.rs`, test closure that: +// +// - captures a variable `y` +// - stores reference to `y` into another, longer-lived spot +// +// except that the closure does so via a second closure. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + + let mut closure = || { + let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] + closure1(); + }; + + closure(); + } + + deref(p); +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr new file mode 100644 index 000000000..4fbd5eb19 --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -0,0 +1,53 @@ +note: external requirements + --> $DIR/escape-upvar-nested.rs:21:32 + | +LL | let mut closure1 = || p = &y; + | ^^ + | + = note: defining type: test::{closure#0}::{closure#0} with closure substs [ + i16, + extern "rust-call" fn(()), + (&'_#1r mut &'_#2r i32, &'_#3r i32), + ] + = note: number of external vids: 4 + = note: where '_#3r: '_#2r + +note: external requirements + --> $DIR/escape-upvar-nested.rs:20:27 + | +LL | let mut closure = || { + | ^^ + | + = note: defining type: test::{closure#0} with closure substs [ + i16, + extern "rust-call" fn(()), + (&'_#1r mut &'_#2r i32, &'_#3r i32), + ] + = note: number of external vids: 4 + = note: where '_#3r: '_#2r + +note: no external requirements + --> $DIR/escape-upvar-nested.rs:13:1 + | +LL | fn test() { + | ^^^^^^^^^ + | + = note: defining type: test + +error[E0597]: `y` does not live long enough + --> $DIR/escape-upvar-nested.rs:21:40 + | +LL | let mut closure = || { + | -- value captured here +LL | let mut closure1 = || p = &y; + | ^ borrowed value does not live long enough +... +LL | } + | - `y` dropped here while still borrowed +LL | +LL | deref(p); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/escape-upvar-ref.rs b/tests/ui/nll/closure-requirements/escape-upvar-ref.rs new file mode 100644 index 000000000..0a562a0a1 --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-upvar-ref.rs @@ -0,0 +1,33 @@ +// Test closure that: +// +// - captures a variable `y` by reference +// - stores that reference to `y` into another, longer-lived place (`p`) +// +// Both of these are upvars of reference type (the capture of `y` is +// of type `&'a i32`, the capture of `p` is of type `&mut &'b +// i32`). The closure thus computes a relationship between `'a` and +// `'b`. This relationship is propagated to the closure creator, +// which reports an error. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + let x = 44; + let mut p = &x; + + { + let y = 22; + let mut closure = || p = &y; + //~^ ERROR `y` does not live long enough [E0597] + closure(); + } + + deref(p); +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr new file mode 100644 index 000000000..bc1ceac5b --- /dev/null +++ b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -0,0 +1,39 @@ +note: external requirements + --> $DIR/escape-upvar-ref.rs:23:27 + | +LL | let mut closure = || p = &y; + | ^^ + | + = note: defining type: test::{closure#0} with closure substs [ + i16, + extern "rust-call" fn(()), + (&'_#1r mut &'_#2r i32, &'_#3r i32), + ] + = note: number of external vids: 4 + = note: where '_#3r: '_#2r + +note: no external requirements + --> $DIR/escape-upvar-ref.rs:17:1 + | +LL | fn test() { + | ^^^^^^^^^ + | + = note: defining type: test + +error[E0597]: `y` does not live long enough + --> $DIR/escape-upvar-ref.rs:23:35 + | +LL | let mut closure = || p = &y; + | -- ^ borrowed value does not live long enough + | | + | value captured here +... +LL | } + | - `y` dropped here while still borrowed +LL | +LL | deref(p); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs b/tests/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs new file mode 100644 index 000000000..a83ebc21f --- /dev/null +++ b/tests/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs @@ -0,0 +1,36 @@ +// check-pass + +// Test that we propagate region relations from closures precisely when there is +// more than one non-local lower bound. + +// In this case the closure has signature +// |x: &'4 mut (&'5 (&'1 str, &'2 str), &'3 str)| -> .. +// We end up with a `'3: '5` constraint that we can propagate as +// `'3: '1`, `'3: '2`, but previously we approximated it as `'3: 'static`. + +// As an optimization, we primarily propagate bounds for the "representative" +// of each SCC. As such we have these two similar cases where hopefully one +// of them will test the case we want (case2, when this test was added). +mod case1 { + fn f(s: &str) { + g(s, |x| h(x)); + } + + fn g(_: T, _: F) + where F: Fn(&mut (&(T, T), T)) {} + + fn h(_: &mut (&(T, T), T)) {} +} + +mod case2 { + fn f(s: &str) { + g(s, |x| h(x)); + } + + fn g(_: T, _: F) + where F: Fn(&mut (T, &(T, T))) {} + + fn h(_: &mut (T, &(T, T))) {} +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs new file mode 100644 index 000000000..35a864b88 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs @@ -0,0 +1,51 @@ +// Test where we fail to approximate due to demanding a postdom +// relationship between our upper bounds. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'x: 'b +// 'c: 'y +// +// we have to prove that `'x: 'y`. We currently can only approximate +// via a postdominator -- hence we fail to choose between `'a` and +// `'b` here and report the error in the closure. +fn establish_relationships<'a, 'b, 'c, F>( + _cell_a: Cell<&'a u32>, + _cell_b: Cell<&'b u32>, + _cell_c: Cell<&'c u32>, + _closure: F, +) where + F: for<'x, 'y> FnMut( + Cell<&'a &'x u32>, // shows that 'x: 'a + Cell<&'b &'x u32>, // shows that 'x: 'b + Cell<&'y &'c u32>, // shows that 'c: 'y + Cell<&'x u32>, + Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + establish_relationships( + cell_a, + cell_b, + cell_c, + |_outlives1, _outlives2, _outlives3, x, y| { + // Only works if 'x: 'y: + let p = x.get(); + demand_y(x, y, p) //~ ERROR + }, + ); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr new file mode 100644 index 000000000..7da6ce58b --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -0,0 +1,36 @@ +note: no external requirements + --> $DIR/propagate-approximated-fail-no-postdom.rs:43:9 + | +LL | |_outlives1, _outlives2, _outlives3, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + (), + ] + = note: late-bound region is '_#4r + = note: late-bound region is '_#5r + = note: late-bound region is '_#6r + +error: lifetime may not live long enough + --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13 + | +LL | |_outlives1, _outlives2, _outlives3, x, y| { + | ---------- ---------- has type `Cell<&'2 &'_#3r u32>` + | | + | has type `Cell<&'_#1r &'1 u32>` +... +LL | demand_y(x, y, p) + | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + +note: no external requirements + --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1 + | +LL | fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs b/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs new file mode 100644 index 000000000..7291c6e97 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs @@ -0,0 +1,50 @@ +// Rather convoluted setup where we infer a relationship between two +// free regions in the closure signature (`'a` and `'b`) on the basis +// of a relationship between two bound regions (`'x` and `'y`). +// +// The idea is that, thanks to invoking `demand_y`, `'x: 'y` must +// hold, where `'x` and `'y` are bound regions. The closure can't +// prove that directly, and because `'x` and `'y` are bound it cannot +// ask the caller to prove it either. But it has bounds on `'x` and +// `'y` in terms of `'a` and `'b`, and it can propagate a relationship +// between `'a` and `'b` to the caller. +// +// Note: the use of `Cell` here is to introduce invariance. One less +// variable. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'b: 'y +// +// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must +// hold. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'a &'x u32>, // shows that 'x: 'a + &Cell<&'y &'b u32>, // shows that 'b: 'y + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + //~^ ERROR lifetime may not live long enough + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr new file mode 100644 index 000000000..993687605 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -0,0 +1,39 @@ +note: external requirements + --> $DIR/propagate-approximated-ref.rs:43:47 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)), + (), + ] + = note: late-bound region is '_#3r + = note: late-bound region is '_#4r + = note: number of external vids: 5 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/propagate-approximated-ref.rs:42:1 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error: lifetime may not live long enough + --> $DIR/propagate-approximated-ref.rs:45:9 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs new file mode 100644 index 000000000..afe6f10a5 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs @@ -0,0 +1,40 @@ +// Test a case where we setup relationships like `'x: 'a` or `'a: 'x`, +// where `'x` is bound in closure type but `'a` is free. This forces +// us to approximate `'x` one way or the other. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +fn foo<'a, F>(_cell: Cell<&'a u32>, _f: F) +where + F: for<'x> FnOnce(Cell<&'a u32>, Cell<&'x u32>), +{ +} + +#[rustc_regions] +fn case1() { + let a = 0; + let cell = Cell::new(&a); + foo(cell, |cell_a, cell_x| { + cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure + //~^ ERROR + }) +} + +#[rustc_regions] +fn case2() { + let a = 0; + let cell = Cell::new(&a); + //~^ ERROR `a` does not live long enough + + // As you can see in the stderr output, this closure propoagates a + // requirement that `'a: 'static'. + foo(cell, |cell_a, cell_x| { + cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error + }) +} + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr new file mode 100644 index 000000000..7991abeb7 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -0,0 +1,69 @@ +note: no external requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:21:15 + | +LL | foo(cell, |cell_a, cell_x| { + | ^^^^^^^^^^^^^^^^ + | + = note: defining type: case1::{closure#0} with closure substs [ + i32, + for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)), + (), + ] + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:22:9 + | +LL | foo(cell, |cell_a, cell_x| { + | ------ ------ `cell_x` is a reference that is only valid in the closure body + | | + | `cell_a` declared here, outside of the closure body +LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure + | ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here + +note: no external requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:18:1 + | +LL | fn case1() { + | ^^^^^^^^^^ + | + = note: defining type: case1 + +note: external requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:35:15 + | +LL | foo(cell, |cell_a, cell_x| { + | ^^^^^^^^^^^^^^^^ + | + = note: defining type: case2::{closure#0} with closure substs [ + i32, + for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)), + (), + ] + = note: number of external vids: 2 + = note: where '_#1r: '_#0r + +note: no external requirements + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1 + | +LL | fn case2() { + | ^^^^^^^^^^ + | + = note: defining type: case2 + +error[E0597]: `a` does not live long enough + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26 + | +LL | let cell = Cell::new(&a); + | ^^ borrowed value does not live long enough +... +LL | / foo(cell, |cell_a, cell_x| { +LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error +LL | | }) + | |______- argument requires that `a` is borrowed for `'static` +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0521, E0597. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs new file mode 100644 index 000000000..372209075 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs @@ -0,0 +1,40 @@ +// Test a case where we are trying to prove `'x: 'y` and are forced to +// approximate the shorter end-point (`'y`) to with `'static`. This is +// because `'y` is higher-ranked but we know of no relations to other +// regions. Note that `'static` shows up in the stderr output as `'0`. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// +// so the only way we can ensure that `'x: 'y` is to show that +// `'a: 'static`. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'a &'x u32>, // shows that 'x: 'a + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + //~^ ERROR borrowed data escapes outside of function + + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr new file mode 100644 index 000000000..43dfc3bb9 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -0,0 +1,49 @@ +note: external requirements + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:47 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | ^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) u32>)), + (), + ] + = note: late-bound region is '_#2r + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where '_#1r: '_#0r + +note: no external requirements + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:31:1 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error[E0521]: borrowed data escapes outside of function + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { +LL | | +LL | | +LL | | // Only works if 'x: 'y: +LL | | demand_y(x, y, x.get()) +LL | | }); + | | ^ + | | | + | |______`cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Cell<&'_#9r u32>`, which makes the generic argument `&'_#9r u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs new file mode 100644 index 000000000..9898777c7 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs @@ -0,0 +1,43 @@ +// Test a case where we are trying to prove `'x: 'y` and are forced to +// approximate the shorter end-point (`'y`) to with `'static`. This is +// because `'y` is higher-ranked but we know of only irrelevant +// relations to other regions. Note that `'static` shows up in the +// stderr output as `'0`. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'y: 'b +// +// so the only way we can ensure that `'x: 'y` is to show that +// `'a: 'static`. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'a &'x u32>, // shows that 'x: 'a + &Cell<&'b &'y u32>, // shows that 'y: 'b + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + //~^ ERROR borrowed data escapes outside of function + + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr new file mode 100644 index 000000000..96c734226 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -0,0 +1,49 @@ +note: external requirements + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:47 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)), + (), + ] + = note: late-bound region is '_#3r + = note: late-bound region is '_#4r + = note: number of external vids: 5 + = note: where '_#1r: '_#0r + +note: no external requirements + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:34:1 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error[E0521]: borrowed data escapes outside of function + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +LL | | +LL | | +LL | | // Only works if 'x: 'y: +LL | | demand_y(x, y, x.get()) +LL | | }); + | | ^ + | | | + | |______`cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Cell<&'_#10r u32>`, which makes the generic argument `&'_#10r u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.rs b/tests/ui/nll/closure-requirements/propagate-approximated-val.rs new file mode 100644 index 000000000..5bb5eea99 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.rs @@ -0,0 +1,43 @@ +// A simpler variant of `outlives-from-argument` where cells are +// passed by value. +// +// This is simpler because there are no "extraneous" region +// relationships. In the 'main' variant, there are a number of +// anonymous regions as well. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'x: 'a +// 'b: 'y +// +// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must +// hold. +fn establish_relationships<'a, 'b, F>(_cell_a: Cell<&'a u32>, _cell_b: Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + Cell<&'a &'x u32>, // shows that 'x: 'a + Cell<&'y &'b u32>, // shows that 'b: 'y + Cell<&'x u32>, + Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y: &'y u32) {} + +#[rustc_regions] +fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(outlives1, outlives2, x.get()) + //~^ ERROR lifetime may not live long enough + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr new file mode 100644 index 000000000..03dbd686e --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -0,0 +1,39 @@ +note: external requirements + --> $DIR/propagate-approximated-val.rs:36:45 + | +LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: test::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + (), + ] + = note: late-bound region is '_#3r + = note: late-bound region is '_#4r + = note: number of external vids: 5 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/propagate-approximated-val.rs:35:1 + | +LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: test + +error: lifetime may not live long enough + --> $DIR/propagate-approximated-val.rs:38:9 + | +LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | demand_y(outlives1, outlives2, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.rs new file mode 100644 index 000000000..704a026d2 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.rs @@ -0,0 +1,50 @@ +// Test where we might in theory be able to see that the relationship +// between two bound regions is true within closure and hence have no +// need to propagate; but in fact we do because identity of free +// regions is erased. + +// compile-flags:-Zverbose +// check-pass + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// In theory, callee knows that: +// +// 'x: 'a +// 'a: 'y +// +// and hence could satisfy that `'x: 'y` locally. However, in our +// checking, we ignore the precise free regions that come into the +// region and just assign each position a distinct universally bound +// region. Hence, we propagate a constraint to our caller that will +// wind up being solvable. +fn establish_relationships<'a, F>( + _cell_a: Cell<&'a u32>, + _closure: F, +) where + F: for<'x, 'y> FnMut( + Cell<&'a &'x u32>, // shows that 'x: 'a + Cell<&'y &'a u32>, // shows that 'a: 'y + Cell<&'x u32>, + Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a>(cell_a: Cell<&'a u32>) { + establish_relationships( + cell_a, + |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + let p = x.get(); + demand_y(x, y, p) + }, + ); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr new file mode 100644 index 000000000..d716d3de2 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -0,0 +1,23 @@ +note: external requirements + --> $DIR/propagate-despite-same-free-region.rs:42:9 + | +LL | |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/propagate-despite-same-free-region.rs:39:1 + | +LL | fn supply<'a>(cell_a: Cell<&'a u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs new file mode 100644 index 000000000..dcd05d7fa --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs @@ -0,0 +1,42 @@ +// Similarly to escape-argument-callee, a test case where the closure +// requires a relationship between 2 unrelated higher-ranked regions, +// with no helpful relations between the HRRs and free regions. +// +// In this case, the error is reported by the closure itself. This is +// because it is unable to approximate the higher-ranked region `'x`, +// as it knows of no relationships between `'x` and any +// non-higher-ranked regions. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'b: 'y +// +// but this doesn't really help us in proving that `'x: 'y`, so closure gets an error. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'y &'b u32>, // shows that 'b: 'y + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + //~^ ERROR + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr new file mode 100644 index 000000000..b924873fc --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -0,0 +1,35 @@ +note: no external requirements + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:35:47 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | ^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + (), + ] + = note: late-bound region is '_#2r + = note: late-bound region is '_#3r + +error: lifetime may not live long enough + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | --------- - has type `&'_#7r Cell<&'1 u32>` + | | + | has type `&'_#5r Cell<&'2 &'_#1r u32>` +LL | // Only works if 'x: 'y: +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + +note: no external requirements + --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs new file mode 100644 index 000000000..98be92d1c --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs @@ -0,0 +1,46 @@ +// Similarly to escape-argument-callee, a test case where the closure +// requires a relationship between 2 unrelated higher-ranked regions, +// with no helpful relations between the HRRs and free regions. +// +// In this case, the error is reported by the closure itself. This is +// because it is unable to approximate the higher-ranked region `'x`, +// as it only knows of regions that `'x` is outlived by, and none that +// `'x` outlives. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Callee knows that: +// +// 'a: 'x +// 'b: 'y +// +// but this doesn't really help us in proving that `'x: 'y`, so +// closure gets an error. In particular, we would need to know that +// `'x: 'a`, so that we could approximate `'x` "downwards" to `'a`. +fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F) +where + F: for<'x, 'y> FnMut( + &Cell<&'x &'a u32>, // shows that 'a: 'x + &Cell<&'y &'b u32>, // shows that 'b: 'y + &Cell<&'x u32>, + &Cell<&'y u32>, + ), +{ +} + +fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {} + +#[rustc_regions] +fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + // Only works if 'x: 'y: + demand_y(x, y, x.get()) + //~^ ERROR + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr new file mode 100644 index 000000000..9b25efd0b --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -0,0 +1,35 @@ +note: no external requirements + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:39:47 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)), + (), + ] + = note: late-bound region is '_#3r + = note: late-bound region is '_#4r + +error: lifetime may not live long enough + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9 + | +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ---------- ---------- has type `&'_#8r Cell<&'2 &'_#2r u32>` + | | + | has type `&'_#6r Cell<&'1 &'_#1r u32>` +LL | // Only works if 'x: 'y: +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + +note: no external requirements + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1 + | +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: supply + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/propagate-from-trait-match.rs b/tests/ui/nll/closure-requirements/propagate-from-trait-match.rs new file mode 100644 index 000000000..cda781d8e --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-from-trait-match.rs @@ -0,0 +1,48 @@ +// Test that regions which appear only in the closure's generics (in +// this case, `'a`) are properly mapped to the creator's generics. In +// this case, the closure constrains its type parameter `T` to outlive +// the same `'a` for which it implements `Trait`, which can only be the `'a` +// from the function definition. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait Trait<'a> {} + +fn establish_relationships(value: T, closure: F) +where + F: FnOnce(T), +{ + closure(value) +} + +fn require<'a, T>(t: T) +where + T: Trait<'a> + 'a, +{ +} + +#[rustc_regions] +fn supply<'a, T>(value: T) +where + T: Trait<'a>, +{ + establish_relationships(value, |value| { + // This function call requires that + // + // (a) T: Trait<'a> + // + // and + // + // (b) T: 'a + // + // The latter does not hold. + + require(value); + //~^ ERROR the parameter type `T` may not live long enough + }); +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr new file mode 100644 index 000000000..038a5e11f --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -0,0 +1,38 @@ +note: external requirements + --> $DIR/propagate-from-trait-match.rs:32:36 + | +LL | establish_relationships(value, |value| { + | ^^^^^^^ + | + = note: defining type: supply::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((T,)), + (), + ] + = note: number of external vids: 2 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/propagate-from-trait-match.rs:28:1 + | +LL | / fn supply<'a, T>(value: T) +LL | | where +LL | | T: Trait<'a>, + | |_________________^ + | + = note: defining type: supply::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/propagate-from-trait-match.rs:43:9 + | +LL | require(value); + | ^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Trait<'a> + 'a, + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.rs b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.rs new file mode 100644 index 000000000..a9d2a0771 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.rs @@ -0,0 +1,23 @@ +// Test that we propagate *all* requirements to the caller, not just the first +// one. + +fn once U>(f: F, s: S, t: T) -> U { + f(s, t) +} + +pub fn dangle() -> &'static [i32] { + let other_local_arr = [0, 2, 4]; + let local_arr = other_local_arr; + let mut out: &mut &'static [i32] = &mut (&[1] as _); + once(|mut z: &[i32], mut out_val: &mut &[i32]| { + // We unfortunately point to the first use in the closure in the error + // message + z = &local_arr; //~ ERROR + *out_val = &local_arr; + }, &[] as &[_], &mut *out); + *out +} + +fn main() { + println!("{:?}", dangle()); +} diff --git a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr new file mode 100644 index 000000000..2fec9bc62 --- /dev/null +++ b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr @@ -0,0 +1,17 @@ +error[E0597]: `local_arr` does not live long enough + --> $DIR/propagate-multiple-requirements.rs:15:14 + | +LL | let mut out: &mut &'static [i32] = &mut (&[1] as _); + | ------------------- type annotation requires that `local_arr` is borrowed for `'static` +LL | once(|mut z: &[i32], mut out_val: &mut &[i32]| { + | ----------------------------------------- value captured here +... +LL | z = &local_arr; + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - `local_arr` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs new file mode 100644 index 000000000..8147da09d --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs @@ -0,0 +1,13 @@ +// Basic test for free regions in the NLL code. This test ought to +// report an error due to a reborrowing constraint. Right now, we get +// a variety of errors from the older, AST-based machinery (notably +// borrowck), and then we get the NLL error at the end. + +// compile-flags:-Zverbose + +fn foo(x: &u32) -> &'static u32 { + &*x + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr new file mode 100644 index 000000000..7034492ce --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/region-lbr-anon-does-not-outlive-static.rs:9:5 + | +LL | fn foo(x: &u32) -> &'static u32 { + | - let's call the lifetime of this reference `'1` +LL | &*x + | ^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs b/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs new file mode 100644 index 000000000..4acd2fc92 --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs @@ -0,0 +1,13 @@ +// Basic test for free regions in the NLL code. This test ought to +// report an error due to a reborrowing constraint. Right now, we get +// a variety of errors from the older, AST-based machinery (notably +// borrowck), and then we get the NLL error at the end. + +// compile-flags:-Zverbose + +fn foo<'a>(x: &'a u32) -> &'static u32 { + &*x + //~^ ERROR +} + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr new file mode 100644 index 000000000..d0a24a267 --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/region-lbr-named-does-not-outlive-static.rs:9:5 + | +LL | fn foo<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | &*x + | ^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs new file mode 100644 index 000000000..06e96be80 --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs @@ -0,0 +1,13 @@ +// Basic test for free regions in the NLL code. This test ought to +// report an error due to a reborrowing constraint. Right now, we get +// a variety of errors from the older, AST-based machinery (notably +// borrowck), and then we get the NLL error at the end. + +// compile-flags:-Zverbose + +fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { + &*x + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr new file mode 100644 index 000000000..d0ba53925 --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:9:5 + | +LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | &*x + | ^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs b/tests/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs new file mode 100644 index 000000000..014959fdb --- /dev/null +++ b/tests/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs @@ -0,0 +1,11 @@ +// Basic test for free regions in the NLL code. This test does not +// report an error because of the (implied) bound that `'b: 'a`. + +// check-pass +// compile-flags:-Zverbose + +fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 { + &**x +} + +fn main() {} diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.rs b/tests/ui/nll/closure-requirements/return-wrong-bound-region.rs new file mode 100644 index 000000000..e34a3f6f2 --- /dev/null +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.rs @@ -0,0 +1,23 @@ +// Test closure that takes two references and is supposed to return +// the first, but actually returns the second. This should fail within +// the closure. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +#[rustc_regions] +fn test() { + expect_sig(|a, b| b); // ought to return `a` + //~^ ERROR +} + +fn expect_sig(f: F) -> F + where F: for<'a> FnMut(&'a i32, &i32) -> &'a i32 +{ + f +} + +fn deref(_p: &i32) { } + +fn main() { } diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr new file mode 100644 index 000000000..6db72b886 --- /dev/null +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -0,0 +1,31 @@ +note: no external requirements + --> $DIR/return-wrong-bound-region.rs:11:16 + | +LL | expect_sig(|a, b| b); // ought to return `a` + | ^^^^^^ + | + = note: defining type: test::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32, + (), + ] + +error: lifetime may not live long enough + --> $DIR/return-wrong-bound-region.rs:11:23 + | +LL | expect_sig(|a, b| b); // ought to return `a` + | - - ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | has type `&'1 i32` + | has type `&'2 i32` + +note: no external requirements + --> $DIR/return-wrong-bound-region.rs:10:1 + | +LL | fn test() { + | ^^^^^^^^^ + | + = note: defining type: test + +error: aborting due to previous error + diff --git a/tests/ui/nll/closure-use-spans.rs b/tests/ui/nll/closure-use-spans.rs new file mode 100644 index 000000000..6768250dc --- /dev/null +++ b/tests/ui/nll/closure-use-spans.rs @@ -0,0 +1,21 @@ +// check that liveness due to a closure capture gives a special note + +fn use_as_borrow_capture(mut x: i32) { + let y = &x; + x = 0; //~ ERROR + || *y; +} + +fn use_as_borrow_mut_capture(mut x: i32) { + let y = &mut x; + x = 0; //~ ERROR + || *y = 1; +} + +fn use_as_move_capture(mut x: i32) { + let y = &x; + x = 0; //~ ERROR + move || *y; +} + +fn main() {} diff --git a/tests/ui/nll/closure-use-spans.stderr b/tests/ui/nll/closure-use-spans.stderr new file mode 100644 index 000000000..ad928f1bb --- /dev/null +++ b/tests/ui/nll/closure-use-spans.stderr @@ -0,0 +1,33 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:5:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +LL | x = 0; + | ^^^^^ assignment to borrowed `x` occurs here +LL | || *y; + | -- borrow later captured here by closure + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:11:5 + | +LL | let y = &mut x; + | ------ borrow of `x` occurs here +LL | x = 0; + | ^^^^^ assignment to borrowed `x` occurs here +LL | || *y = 1; + | -- borrow later captured here by closure + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:17:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +LL | x = 0; + | ^^^^^ assignment to borrowed `x` occurs here +LL | move || *y; + | -- borrow later captured here by closure + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/closures-in-loops.rs b/tests/ui/nll/closures-in-loops.rs new file mode 100644 index 000000000..491c186ec --- /dev/null +++ b/tests/ui/nll/closures-in-loops.rs @@ -0,0 +1,24 @@ +// Test messages where a closure capture conflicts with itself because it's in +// a loop. + +fn repreated_move(x: String) { + for i in 0..10 { + || x; //~ ERROR + } +} + +fn repreated_mut_borrow(mut x: String) { + let mut v = Vec::new(); + for i in 0..10 { + v.push(|| x = String::new()); //~ ERROR + } +} + +fn repreated_unique_borrow(x: &mut String) { + let mut v = Vec::new(); + for i in 0..10 { + v.push(|| *x = String::new()); //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/nll/closures-in-loops.stderr b/tests/ui/nll/closures-in-loops.stderr new file mode 100644 index 000000000..1c1a31d35 --- /dev/null +++ b/tests/ui/nll/closures-in-loops.stderr @@ -0,0 +1,35 @@ +error[E0382]: use of moved value: `x` + --> $DIR/closures-in-loops.rs:6:9 + | +LL | fn repreated_move(x: String) { + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | for i in 0..10 { +LL | || x; + | ^^ - use occurs due to use in closure + | | + | value moved into closure here, in previous iteration of loop + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closures-in-loops.rs:13:16 + | +LL | v.push(|| x = String::new()); + | -------^^------------------- + | | | | + | | | borrows occur due to use of `x` in closure + | | `x` was mutably borrowed here in the previous iteration of the loop + | first borrow used here, in later iteration of loop + +error[E0524]: two closures require unique access to `x` at the same time + --> $DIR/closures-in-loops.rs:20:16 + | +LL | v.push(|| *x = String::new()); + | -------^^-------------------- + | | | | + | | | borrows occur due to use of `x` in closure + | | closures are constructed here in different iterations of loop + | first borrow used here, in later iteration of loop + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0499, E0524. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/constant-thread-locals-issue-47053.rs b/tests/ui/nll/constant-thread-locals-issue-47053.rs new file mode 100644 index 000000000..dde0ef7a5 --- /dev/null +++ b/tests/ui/nll/constant-thread-locals-issue-47053.rs @@ -0,0 +1,10 @@ +// Regression test for issue #47053 + +#![feature(thread_local)] + +#[thread_local] +static FOO: isize = 5; + +fn main() { + FOO = 6; //~ ERROR cannot assign to immutable static item `FOO` [E0594] +} diff --git a/tests/ui/nll/constant-thread-locals-issue-47053.stderr b/tests/ui/nll/constant-thread-locals-issue-47053.stderr new file mode 100644 index 000000000..a44acfb5f --- /dev/null +++ b/tests/ui/nll/constant-thread-locals-issue-47053.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `FOO` + --> $DIR/constant-thread-locals-issue-47053.rs:9:5 + | +LL | FOO = 6; + | ^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/constant.rs b/tests/ui/nll/constant.rs new file mode 100644 index 000000000..47f0eadf9 --- /dev/null +++ b/tests/ui/nll/constant.rs @@ -0,0 +1,10 @@ +// Test that MIR borrowck and NLL analysis can handle constants of +// arbitrary types without ICEs. + +// check-pass + +const HI: &str = "hi"; + +fn main() { + assert_eq!(HI, "hi"); +} diff --git a/tests/ui/nll/continue-after-missing-main.rs b/tests/ui/nll/continue-after-missing-main.rs new file mode 100644 index 000000000..778639158 --- /dev/null +++ b/tests/ui/nll/continue-after-missing-main.rs @@ -0,0 +1,29 @@ +#![allow(dead_code)] + +struct Tableau<'a, MP> { + provider: &'a MP, +} + +impl<'adapted_matrix_provider, 'original_data, MP> + Tableau<'adapted_matrix_provider, AdaptedMatrixProvider<'original_data, MP>> +{ + fn provider(&self) -> &'adapted_matrix_provider AdaptedMatrixProvider { + self.provider + } +} + +struct AdaptedMatrixProvider<'a, T> { + original_problem: &'a T, +} + +impl<'a, T> AdaptedMatrixProvider<'a, T> { + fn clone_with_extra_bound(&self) -> Self { + AdaptedMatrixProvider { original_problem: self.original_problem } + } +} + +fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, +) { + let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); +} //~ ERROR `main` function not found in crate diff --git a/tests/ui/nll/continue-after-missing-main.stderr b/tests/ui/nll/continue-after-missing-main.stderr new file mode 100644 index 000000000..0df8d8d70 --- /dev/null +++ b/tests/ui/nll/continue-after-missing-main.stderr @@ -0,0 +1,9 @@ +error[E0601]: `main` function not found in crate `continue_after_missing_main` + --> $DIR/continue-after-missing-main.rs:29:2 + | +LL | } + | ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/nll/decl-macro-illegal-copy.rs b/tests/ui/nll/decl-macro-illegal-copy.rs new file mode 100644 index 000000000..f72432946 --- /dev/null +++ b/tests/ui/nll/decl-macro-illegal-copy.rs @@ -0,0 +1,28 @@ +// Regression test for #46314 + +#![feature(decl_macro)] + +struct NonCopy(String); + +struct Wrapper { + inner: NonCopy, +} + +macro inner_copy($wrapper:ident) { + $wrapper.inner +} + +fn main() { + let wrapper = Wrapper { + inner: NonCopy("foo".into()), + }; + assert_two_non_copy( + inner_copy!(wrapper), + wrapper.inner, + //~^ ERROR use of moved value: `wrapper.inner` [E0382] + ); +} + +fn assert_two_non_copy(a: NonCopy, b: NonCopy) { + assert_eq!(a.0, b.0); +} diff --git a/tests/ui/nll/decl-macro-illegal-copy.stderr b/tests/ui/nll/decl-macro-illegal-copy.stderr new file mode 100644 index 000000000..7948485bd --- /dev/null +++ b/tests/ui/nll/decl-macro-illegal-copy.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `wrapper.inner` + --> $DIR/decl-macro-illegal-copy.rs:21:9 + | +LL | $wrapper.inner + | -------------- value moved here +... +LL | wrapper.inner, + | ^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `wrapper.inner` has type `NonCopy`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs new file mode 100644 index 000000000..96c871946 --- /dev/null +++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs @@ -0,0 +1,12 @@ +// Test that the 'static bound from the Copy impl is respected. Regression test for #29149. + +#[derive(Clone)] +struct Foo<'a>(&'a u32); +impl Copy for Foo<'static> {} + +fn main() { + let s = 2; + let a = (Foo(&s),); //~ ERROR `s` does not live long enough [E0597] + drop(a.0); + drop(a.0); +} diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr new file mode 100644 index 000000000..65be3b37e --- /dev/null +++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr @@ -0,0 +1,14 @@ +error[E0597]: `s` does not live long enough + --> $DIR/do-not-ignore-lifetime-bounds-in-copy-proj.rs:9:18 + | +LL | let a = (Foo(&s),); + | ^^ borrowed value does not live long enough +LL | drop(a.0); + | --- copying this value requires that `s` is borrowed for `'static` +LL | drop(a.0); +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs new file mode 100644 index 000000000..99922cc51 --- /dev/null +++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.rs @@ -0,0 +1,11 @@ +// Test that the 'static bound from the Copy impl is respected. Regression test for #29149. + +#[derive(Clone)] struct Foo<'a>(&'a u32); +impl Copy for Foo<'static> {} + +fn main() { + let s = 2; + let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597] + drop(a); + drop(a); +} diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr new file mode 100644 index 000000000..b811ba4fd --- /dev/null +++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr @@ -0,0 +1,14 @@ +error[E0597]: `s` does not live long enough + --> $DIR/do-not-ignore-lifetime-bounds-in-copy.rs:8:17 + | +LL | let a = Foo(&s); + | ^^ borrowed value does not live long enough +LL | drop(a); + | - copying this value requires that `s` is borrowed for `'static` +LL | drop(a); +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/dont-print-desugared.rs b/tests/ui/nll/dont-print-desugared.rs new file mode 100644 index 000000000..829d78ed4 --- /dev/null +++ b/tests/ui/nll/dont-print-desugared.rs @@ -0,0 +1,21 @@ +// Test that we don't show variables with from for loop desugaring + +fn for_loop(s: &[i32]) { + for &ref mut x in s {} + //~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] +} + +struct D<'a>(&'a ()); + +impl Drop for D<'_> { + fn drop(&mut self) {} +} + +fn for_loop_dropck(v: Vec>) { + for ref mut d in v { + let y = (); + *d = D(&y); //~ ERROR `y` does not live long enough + } +} + +fn main() {} diff --git a/tests/ui/nll/dont-print-desugared.stderr b/tests/ui/nll/dont-print-desugared.stderr new file mode 100644 index 000000000..fad6121cb --- /dev/null +++ b/tests/ui/nll/dont-print-desugared.stderr @@ -0,0 +1,24 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/dont-print-desugared.rs:4:10 + | +LL | for &ref mut x in s {} + | ^^^^^^^^^ cannot borrow as mutable + +error[E0597]: `y` does not live long enough + --> $DIR/dont-print-desugared.rs:17:16 + | +LL | for ref mut d in v { + | - a temporary with access to the borrow is created here ... +LL | let y = (); +LL | *d = D(&y); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `y` dropped here while still borrowed + | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0596, E0597. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/nll/drop-may-dangle.rs b/tests/ui/nll/drop-may-dangle.rs new file mode 100644 index 000000000..b5531c29b --- /dev/null +++ b/tests/ui/nll/drop-may-dangle.rs @@ -0,0 +1,34 @@ +// Basic test for liveness constraints: the region (`R1`) that appears +// in the type of `p` includes the points after `&v[0]` up to (but not +// including) the call to `use_x`. The `else` branch is not included. + +// check-pass + +#![allow(warnings)] +#![feature(dropck_eyepatch)] + +fn use_x(_: usize) -> bool { true } + +fn main() { + let mut v = [1, 2, 3]; + let p: WrapMayDangle<& /* R4 */ usize> = WrapMayDangle { value: &v[0] }; + if true { + // `p` will get dropped at end of this block. However, because of + // the `#[may_dangle]` attribute, we do not need to consider R4 + // live after this point. + use_x(*p.value); + } else { + v[0] += 1; + use_x(22); + } + + v[0] += 1; +} + +struct WrapMayDangle { + value: T +} + +unsafe impl<#[may_dangle] T> Drop for WrapMayDangle { + fn drop(&mut self) { } +} diff --git a/tests/ui/nll/drop-no-may-dangle.rs b/tests/ui/nll/drop-no-may-dangle.rs new file mode 100644 index 000000000..a0ff0c398 --- /dev/null +++ b/tests/ui/nll/drop-no-may-dangle.rs @@ -0,0 +1,30 @@ +// Basic test for liveness constraints: the region (`R1`) that appears +// in the type of `p` must include everything until `p` is dropped +// because of destructor. (Note that the stderr also identifies this +// destructor in the error message.) + +#![allow(warnings)] +#![feature(dropck_eyepatch)] + +fn use_x(_: usize) -> bool { true } + +fn main() { + let mut v = [1, 2, 3]; + let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; + if true { + use_x(*p.value); + } else { + use_x(22); + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + } + + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed +} + +struct WrapMayNotDangle { + value: T +} + +impl Drop for WrapMayNotDangle { + fn drop(&mut self) { } +} diff --git a/tests/ui/nll/drop-no-may-dangle.stderr b/tests/ui/nll/drop-no-may-dangle.stderr new file mode 100644 index 000000000..cb2808809 --- /dev/null +++ b/tests/ui/nll/drop-no-may-dangle.stderr @@ -0,0 +1,26 @@ +error[E0506]: cannot assign to `v[_]` because it is borrowed + --> $DIR/drop-no-may-dangle.rs:18:9 + | +LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; + | ----- borrow of `v[_]` occurs here +... +LL | v[0] += 1; + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here +... +LL | } + | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` + +error[E0506]: cannot assign to `v[_]` because it is borrowed + --> $DIR/drop-no-may-dangle.rs:21:5 + | +LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; + | ----- borrow of `v[_]` occurs here +... +LL | v[0] += 1; + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here +LL | } + | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/empty-type-predicate-2.rs b/tests/ui/nll/empty-type-predicate-2.rs new file mode 100644 index 000000000..20d6e47f7 --- /dev/null +++ b/tests/ui/nll/empty-type-predicate-2.rs @@ -0,0 +1,18 @@ +// Regression test for #65553 +// +// `D::Error:` is lowered to `D::Error: ReEmpty` - check that we don't ICE in +// NLL for the unexpected region. + +// check-pass + +trait Deserializer { + type Error; +} + +fn d1() where D::Error: {} + +fn d2() { + d1::(); +} + +fn main() {} diff --git a/tests/ui/nll/empty-type-predicate.rs b/tests/ui/nll/empty-type-predicate.rs new file mode 100644 index 000000000..d126a455d --- /dev/null +++ b/tests/ui/nll/empty-type-predicate.rs @@ -0,0 +1,11 @@ +// Regression test for #61315 +// +// `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for +// the unexpected region. + +// check-pass + +trait T {} +fn f() where dyn T: {} + +fn main() { f(); } diff --git a/tests/ui/nll/enum-drop-access.rs b/tests/ui/nll/enum-drop-access.rs new file mode 100644 index 000000000..5ef0c3fe7 --- /dev/null +++ b/tests/ui/nll/enum-drop-access.rs @@ -0,0 +1,49 @@ +enum DropOption { + Some(T), + None, +} + +impl Drop for DropOption { + fn drop(&mut self) {} +} + +// Dropping opt could access the value behind the reference, +fn drop_enum(opt: DropOption<&mut i32>) -> Option<&mut i32> { + match opt { + DropOption::Some(&mut ref mut r) => { //~ ERROR + Some(r) + }, + DropOption::None => None, + } +} + +fn optional_drop_enum(opt: Option>) -> Option<&mut i32> { + match opt { + Some(DropOption::Some(&mut ref mut r)) => { //~ ERROR + Some(r) + }, + Some(DropOption::None) | None => None, + } +} + +// Ok, dropping opt doesn't access the reference +fn optional_tuple(opt: Option<(&mut i32, String)>) -> Option<&mut i32> { + match opt { + Some((&mut ref mut r, _)) => { + Some(r) + }, + None => None, + } +} + +// Ok, dropping res doesn't access the Ok case. +fn different_variants(res: Result<&mut i32, String>) -> Option<&mut i32> { + match res { + Ok(&mut ref mut r) => { + Some(r) + }, + Err(_) => None, + } +} + +fn main() {} diff --git a/tests/ui/nll/enum-drop-access.stderr b/tests/ui/nll/enum-drop-access.stderr new file mode 100644 index 000000000..a532ae121 --- /dev/null +++ b/tests/ui/nll/enum-drop-access.stderr @@ -0,0 +1,31 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/enum-drop-access.rs:13:31 + | +LL | fn drop_enum(opt: DropOption<&mut i32>) -> Option<&mut i32> { + | - let's call the lifetime of this reference `'1` +LL | match opt { +LL | DropOption::Some(&mut ref mut r) => { + | ^^^^^^^^^ +LL | Some(r) + | ------- returning this value requires that `*opt.0` is borrowed for `'1` +... +LL | } + | - here, drop of `opt` needs exclusive access to `*opt.0`, because the type `DropOption<&mut i32>` implements the `Drop` trait + +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/enum-drop-access.rs:22:36 + | +LL | fn optional_drop_enum(opt: Option>) -> Option<&mut i32> { + | - let's call the lifetime of this reference `'1` +LL | match opt { +LL | Some(DropOption::Some(&mut ref mut r)) => { + | ^^^^^^^^^ +LL | Some(r) + | ------- returning this value requires that `*opt.0.0` is borrowed for `'1` +... +LL | } + | - here, drop of `opt` needs exclusive access to `*opt.0.0`, because the type `DropOption<&mut i32>` implements the `Drop` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/extra-unused-mut.rs b/tests/ui/nll/extra-unused-mut.rs new file mode 100644 index 000000000..340f2952a --- /dev/null +++ b/tests/ui/nll/extra-unused-mut.rs @@ -0,0 +1,66 @@ +// extra unused mut lint tests for #51918 + +// check-pass + +#![feature(generators)] +#![deny(unused_mut)] + +fn ref_argument(ref _y: i32) {} + +// #51801 +fn mutable_upvar() { + let mut x = 0; + move || { + x = 1; + }; +} + +// #50897 +fn generator_mutable_upvar() { + let mut x = 0; + move || { + x = 1; + yield; + }; +} + +// #51830 +fn ref_closure_argument() { + let _ = Some(0).as_ref().map(|ref _a| true); +} + +struct Expr { + attrs: Vec, +} + +// #51904 +fn parse_dot_or_call_expr_with(mut attrs: Vec) { + let x = Expr { attrs: vec![] }; + Some(Some(x)).map(|expr| + expr.map(|mut expr| { + attrs.push(666); + expr.attrs = attrs; + expr + }) + ); +} + +// Found when trying to bootstrap rustc +fn if_guard(x: Result) { + match x { + Ok(mut r) | Err(mut r) if true => r = 1, + _ => (), + } +} + +// #59620 +fn nested_closures() { + let mut i = 0; + [].iter().for_each(|_: &i32| { + [].iter().for_each(move |_: &i32| { + i += 1; + }); + }); +} + +fn main() {} diff --git a/tests/ui/nll/generator-distinct-lifetime.rs b/tests/ui/nll/generator-distinct-lifetime.rs new file mode 100644 index 000000000..90fe6b569 --- /dev/null +++ b/tests/ui/nll/generator-distinct-lifetime.rs @@ -0,0 +1,25 @@ +#![feature(generators)] + +// Test for issue #47189. Here, both `s` and `t` are live for the +// generator's lifetime, but within the generator they have distinct +// lifetimes. We accept this code -- even though the borrow extends +// over a yield -- because the data that is borrowed (`*x`) is not +// stored on the stack. + +// check-pass + +fn foo(x: &mut u32) { + move || { + let s = &mut *x; + yield; + *s += 1; + + let t = &mut *x; + yield; + *t += 1; + }; +} + +fn main() { + foo(&mut 0); +} diff --git a/tests/ui/nll/generator-upvar-mutability.rs b/tests/ui/nll/generator-upvar-mutability.rs new file mode 100644 index 000000000..c49ea15b8 --- /dev/null +++ b/tests/ui/nll/generator-upvar-mutability.rs @@ -0,0 +1,14 @@ +// Check that generators respect the muatability of their upvars. + +#![feature(generators)] + +fn mutate_upvar() { + let x = 0; + move || { + x = 1; + //~^ ERROR + yield; + }; +} + +fn main() {} diff --git a/tests/ui/nll/generator-upvar-mutability.stderr b/tests/ui/nll/generator-upvar-mutability.stderr new file mode 100644 index 000000000..31b061b61 --- /dev/null +++ b/tests/ui/nll/generator-upvar-mutability.stderr @@ -0,0 +1,12 @@ +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/generator-upvar-mutability.rs:8:9 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | move || { +LL | x = 1; + | ^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/get_default.polonius.stderr b/tests/ui/nll/get_default.polonius.stderr new file mode 100644 index 000000000..476d86cfb --- /dev/null +++ b/tests/ui/nll/get_default.polonius.stderr @@ -0,0 +1,18 @@ +error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable + --> $DIR/get_default.rs:32:17 + | +LL | fn err(map: &mut Map) -> &String { + | - let's call the lifetime of this reference `'1` +LL | loop { +LL | match map.get() { + | --- immutable borrow occurs here +LL | Some(v) => { +LL | map.set(String::new()); // Both AST and MIR error here + | ^^^ mutable borrow occurs here +LL | +LL | return v; + | - returning this value requires that `*map` is borrowed for `'1` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/get_default.rs b/tests/ui/nll/get_default.rs new file mode 100644 index 000000000..ffac8a33d --- /dev/null +++ b/tests/ui/nll/get_default.rs @@ -0,0 +1,44 @@ +// Basic test for free regions in the NLL code. This test ought to +// report an error due to a reborrowing constraint. Right now, we get +// a variety of errors from the older, AST-based machinery (notably +// borrowck), and then we get the NLL error at the end. + +struct Map { +} + +impl Map { + fn get(&self) -> Option<&String> { None } + fn set(&mut self, v: String) { } +} + +fn ok(map: &mut Map) -> &String { + loop { + match map.get() { + Some(v) => { + return v; + } + None => { + map.set(String::new()); // Ideally, this would not error. + //~^ ERROR borrowed as immutable + } + } + } +} + +fn err(map: &mut Map) -> &String { + loop { + match map.get() { + Some(v) => { + map.set(String::new()); // Both AST and MIR error here + //~^ ERROR borrowed as immutable + return v; + } + None => { + map.set(String::new()); // Ideally, just AST would error here + //~^ ERROR borrowed as immutable + } + } + } +} + +fn main() { } diff --git a/tests/ui/nll/get_default.stderr b/tests/ui/nll/get_default.stderr new file mode 100644 index 000000000..6998c0433 --- /dev/null +++ b/tests/ui/nll/get_default.stderr @@ -0,0 +1,48 @@ +error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable + --> $DIR/get_default.rs:21:17 + | +LL | fn ok(map: &mut Map) -> &String { + | - let's call the lifetime of this reference `'1` +LL | loop { +LL | match map.get() { + | --------- immutable borrow occurs here +LL | Some(v) => { +LL | return v; + | - returning this value requires that `*map` is borrowed for `'1` +... +LL | map.set(String::new()); // Ideally, this would not error. + | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here + +error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable + --> $DIR/get_default.rs:32:17 + | +LL | fn err(map: &mut Map) -> &String { + | - let's call the lifetime of this reference `'1` +LL | loop { +LL | match map.get() { + | --------- immutable borrow occurs here +LL | Some(v) => { +LL | map.set(String::new()); // Both AST and MIR error here + | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | +LL | return v; + | - returning this value requires that `*map` is borrowed for `'1` + +error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable + --> $DIR/get_default.rs:37:17 + | +LL | fn err(map: &mut Map) -> &String { + | - let's call the lifetime of this reference `'1` +LL | loop { +LL | match map.get() { + | --------- immutable borrow occurs here +... +LL | return v; + | - returning this value requires that `*map` is borrowed for `'1` +... +LL | map.set(String::new()); // Ideally, just AST would error here + | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/guarantor-issue-46974.rs b/tests/ui/nll/guarantor-issue-46974.rs new file mode 100644 index 000000000..96af4bf5c --- /dev/null +++ b/tests/ui/nll/guarantor-issue-46974.rs @@ -0,0 +1,19 @@ +// Test that NLL analysis propagates lifetimes correctly through +// field accesses, Box accesses, etc. + +fn foo(s: &mut (i32,)) -> i32 { + let t = &mut *s; // this borrow should last for the entire function + let x = &t.0; + *s = (2,); //~ ERROR cannot assign to `*s` + *x +} + +fn bar(s: &Box<(i32,)>) -> &'static i32 { + // FIXME(#46983): error message should be better + &s.0 //~ ERROR lifetime may not live long enough +} + +fn main() { + foo(&mut (0,)); + bar(&Box::new((1,))); +} diff --git a/tests/ui/nll/guarantor-issue-46974.stderr b/tests/ui/nll/guarantor-issue-46974.stderr new file mode 100644 index 000000000..8854dd8d6 --- /dev/null +++ b/tests/ui/nll/guarantor-issue-46974.stderr @@ -0,0 +1,23 @@ +error[E0506]: cannot assign to `*s` because it is borrowed + --> $DIR/guarantor-issue-46974.rs:7:5 + | +LL | let t = &mut *s; // this borrow should last for the entire function + | ------- borrow of `*s` occurs here +LL | let x = &t.0; +LL | *s = (2,); + | ^^^^^^^^^ assignment to borrowed `*s` occurs here +LL | *x + | -- borrow later used here + +error: lifetime may not live long enough + --> $DIR/guarantor-issue-46974.rs:13:5 + | +LL | fn bar(s: &Box<(i32,)>) -> &'static i32 { + | - let's call the lifetime of this reference `'1` +LL | // FIXME(#46983): error message should be better +LL | &s.0 + | ^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-16223.rs b/tests/ui/nll/issue-16223.rs new file mode 100644 index 000000000..0ae0ed3d8 --- /dev/null +++ b/tests/ui/nll/issue-16223.rs @@ -0,0 +1,52 @@ +// Regression test for #16223: without NLL the `if let` construct together with +// the nested box-structure of `Root` causes an unwanted collateral move. + +// The exact error prevented here is: +// +// error[E0382]: use of collaterally moved value: `(root.boxed.rhs as SomeVariant::B).0` +// --> src/main.rs:55:29 +// | +// 56 | lhs: SomeVariant::A(a), +// | - value moved here +// 57 | rhs: SomeVariant::B(b), +// | ^ value used here after move +// | +// = note: move occurs because the value has type `A`, which does not implement the `Copy` trait + +// check-pass + +#![feature(box_patterns)] + +struct Root { + boxed: Box, +} + +struct SetOfVariants { + lhs: SomeVariant, + rhs: SomeVariant, +} + +enum SomeVariant { + A(A), + B(B), +} + +struct A(String); +struct B(String); + +fn main() { + let root = Root { + boxed: Box::new(SetOfVariants { + lhs: SomeVariant::A(A(String::from("This is A"))), + rhs: SomeVariant::B(B(String::from("This is B"))), + }), + }; + if let box SetOfVariants { + lhs: SomeVariant::A(a), + rhs: SomeVariant::B(b), + } = root.boxed + { + println!("a = {}", a.0); + println!("b = {}", b.0); + } +} diff --git a/tests/ui/nll/issue-21114-ebfull.rs b/tests/ui/nll/issue-21114-ebfull.rs new file mode 100644 index 000000000..fc4a6845a --- /dev/null +++ b/tests/ui/nll/issue-21114-ebfull.rs @@ -0,0 +1,18 @@ +// check-pass + +use std::collections::HashMap; +use std::sync::Mutex; + +fn i_used_to_be_able_to(foo: &Mutex>) -> Vec<(usize, usize)> { + let mut foo = foo.lock().unwrap(); + + foo.drain().collect() +} + +fn but_after_nightly_update_now_i_gotta(foo: &Mutex>) -> Vec<(usize, usize)> { + let mut foo = foo.lock().unwrap(); + + return foo.drain().collect(); +} + +fn main() {} diff --git a/tests/ui/nll/issue-21114-kixunil.rs b/tests/ui/nll/issue-21114-kixunil.rs new file mode 100644 index 000000000..666f89f35 --- /dev/null +++ b/tests/ui/nll/issue-21114-kixunil.rs @@ -0,0 +1,17 @@ +// check-pass + +fn from_stdin(min: u64) -> Vec { + use std::io::BufRead; + + let stdin = std::io::stdin(); + let stdin = stdin.lock(); + + stdin.lines() + .map(Result::unwrap) + .map(|val| val.parse()) + .map(Result::unwrap) + .filter(|val| *val >= min) + .collect() +} + +fn main() {} diff --git a/tests/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/tests/ui/nll/issue-21232-partial-init-and-erroneous-use.rs new file mode 100644 index 000000000..46a156d2a --- /dev/null +++ b/tests/ui/nll/issue-21232-partial-init-and-erroneous-use.rs @@ -0,0 +1,60 @@ +// This test enumerates various cases of interest where an ADT or tuple is +// partially initialized and then used in some way that is wrong *even* +// after rust-lang/rust#54987 is implemented. +// +// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987. +// +// See issue-21232-partial-init-and-use.rs for cases of tests that are +// meant to compile and run successfully once rust-lang/rust#54987 is +// implemented. + +struct D { + x: u32, + s: S, +} + +struct S { + y: u32, + z: u32, +} + + +impl Drop for D { + fn drop(&mut self) { } +} + +fn cannot_partially_init_adt_with_drop() { + let d: D; + d.x = 10; //~ ERROR E0381 +} + +fn cannot_partially_init_mutable_adt_with_drop() { + let mut d: D; + d.x = 10; //~ ERROR E0381 +} + +fn cannot_partially_reinit_adt_with_drop() { + let mut d = D { x: 0, s: S{ y: 0, z: 0 } }; + drop(d); + d.x = 10; + //~^ ERROR assign of moved value: `d` [E0382] +} + +fn cannot_partially_init_inner_adt_via_outer_with_drop() { + let d: D; + d.s.y = 20; //~ ERROR E0381 +} + +fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() { + let mut d: D; + d.s.y = 20; //~ ERROR E0381 +} + +fn cannot_partially_reinit_inner_adt_via_outer_with_drop() { + let mut d = D { x: 0, s: S{ y: 0, z: 0} }; + drop(d); + d.s.y = 20; + //~^ ERROR assign to part of moved value: `d` [E0382] +} + +fn main() { } diff --git a/tests/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr new file mode 100644 index 000000000..63f230be7 --- /dev/null +++ b/tests/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr @@ -0,0 +1,64 @@ +error[E0381]: assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5 + | +LL | let d: D; + | - binding declared here but left uninitialized +LL | d.x = 10; + | ^^^^^^^^ `d` assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:33:5 + | +LL | let mut d: D; + | ----- binding declared here but left uninitialized +LL | d.x = 10; + | ^^^^^^^^ `d` assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign of moved value: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:39:5 + | +LL | let mut d = D { x: 0, s: S{ y: 0, z: 0 } }; + | ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait +LL | drop(d); + | - value moved here +LL | d.x = 10; + | ^^^^^^^^ value assigned here after move + +error[E0381]: partially assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:45:5 + | +LL | let d: D; + | - binding declared here but left uninitialized +LL | d.s.y = 20; + | ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `d` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:50:5 + | +LL | let mut d: D; + | ----- binding declared here but left uninitialized +LL | d.s.y = 20; + | ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign to part of moved value: `d` + --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:56:5 + | +LL | let mut d = D { x: 0, s: S{ y: 0, z: 0} }; + | ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait +LL | drop(d); + | - value moved here +LL | d.s.y = 20; + | ^^^^^^^^^^ value partially assigned here after move + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.rs b/tests/ui/nll/issue-21232-partial-init-and-use.rs new file mode 100644 index 000000000..ad3eb2483 --- /dev/null +++ b/tests/ui/nll/issue-21232-partial-init-and-use.rs @@ -0,0 +1,297 @@ +// This test enumerates various cases of interest for partial +// [re]initialization of ADTs and tuples. +// +// See rust-lang/rust#21232, rust-lang/rust#54986, and rust-lang/rust#54987. +// +// All of tests in this file are expected to change from being +// rejected, at least under NLL (by rust-lang/rust#54986) to being +// **accepted** when rust-lang/rust#54987 is implemented. +// (That's why there are assertions in the code.) +// +// See issue-21232-partial-init-and-erroneous-use.rs for cases of +// tests that are meant to continue failing to compile once +// rust-lang/rust#54987 is implemented. + +struct S { + x: u32, + + // Note that even though `y` may implement `Drop`, under #54987 we + // will still allow partial initialization of `S` itself. + y: Y, +} + +enum Void { } + +type B = Box; + +impl S { fn new() -> Self { S { x: 0, y: Box::new(0) } } } + +fn borrow_s(s: &S) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); } +fn move_s(s: S) { assert_eq!(s.x, 10); assert_eq!(*s.y, 20); } +fn borrow_field(x: &u32) { assert_eq!(*x, 10); } + +type T = (u32, B); +type Tvoid = (u32, Void); + +fn borrow_t(t: &T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); } +fn move_t(t: T) { assert_eq!(t.0, 10); assert_eq!(*t.1, 20); } + +struct Q { + v: u32, + r: R, +} + +struct R { + w: u32, + f: F, +} + +impl Q { fn new(f: F) -> Self { Q { v: 0, r: R::new(f) } } } +impl R { fn new(f: F) -> Self { R { w: 0, f } } } + +// Axes to cover: +// * local/field: Is the structure in a local or a field +// * fully/partial/void: Are we fully initializing it before using any part? +// Is whole type empty due to a void component? +// * init/reinit: First initialization, or did we previously initialize and then move out? +// * struct/tuple: Is this a struct or a (X, Y). +// +// As a shorthand for the cases above, adding a numeric summary to +// each test's fn name to denote each point on each axis. +// +// e.g., 1000 = field fully init struct; 0211 = local void reinit tuple + +// It got pretty monotonous writing the same code over and over, and I +// feared I would forget details. So I abstracted some desiderata into +// macros. But I left the initialization code inline, because that's +// where the errors for #54986 will be emitted. + +macro_rules! use_fully { + (struct $s:expr) => { { + borrow_field(& $s.x ); + borrow_s(& $s ); + move_s( $s ); + } }; + + (tuple $t:expr) => { { + borrow_field(& $t.0 ); + borrow_t(& $t ); + move_t( $t ); + } } +} + +macro_rules! use_part { + (struct $s:expr) => { { + borrow_field(& $s.x ); + match $s { S { ref x, y: _ } => { borrow_field(x); } } + } }; + + (tuple $t:expr) => { { + borrow_field(& $t.0 ); + match $t { (ref x, _) => { borrow_field(x); } } + } } +} + +fn test_0000_local_fully_init_and_use_struct() { + let s: S; + s.x = 10; s.y = Box::new(20); //~ ERROR E0381 + use_fully!(struct s); +} + +fn test_0001_local_fully_init_and_use_tuple() { + let t: T; + t.0 = 10; t.1 = Box::new(20); //~ ERROR E0381 + use_fully!(tuple t); +} + +fn test_0010_local_fully_reinit_and_use_struct() { + let mut s: S = S::new(); drop(s); + s.x = 10; s.y = Box::new(20); + //~^ ERROR assign to part of moved value: `s` [E0382] + use_fully!(struct s); +} + +fn test_0011_local_fully_reinit_and_use_tuple() { + let mut t: T = (0, Box::new(0)); drop(t); + t.0 = 10; t.1 = Box::new(20); + //~^ ERROR assign to part of moved value: `t` [E0382] + use_fully!(tuple t); +} + +fn test_0100_local_partial_init_and_use_struct() { + let s: S; + s.x = 10; //~ ERROR E0381 + use_part!(struct s); +} + +fn test_0101_local_partial_init_and_use_tuple() { + let t: T; + t.0 = 10; //~ ERROR E0381 + use_part!(tuple t); +} + +fn test_0110_local_partial_reinit_and_use_struct() { + let mut s: S = S::new(); drop(s); + s.x = 10; + //~^ ERROR assign to part of moved value: `s` [E0382] + use_part!(struct s); +} + +fn test_0111_local_partial_reinit_and_use_tuple() { + let mut t: T = (0, Box::new(0)); drop(t); + t.0 = 10; + //~^ ERROR assign to part of moved value: `t` [E0382] + use_part!(tuple t); +} + +fn test_0200_local_void_init_and_use_struct() { + let s: S; + s.x = 10; //~ ERROR E0381 + use_part!(struct s); +} + +fn test_0201_local_void_init_and_use_tuple() { + let t: Tvoid; + t.0 = 10; //~ ERROR E0381 + use_part!(tuple t); +} + +// NOTE: uniform structure of tests here makes n21n (aka combining +// Void with Reinit) an (even more) senseless case, as we cannot +// safely create initial instance containing Void to move out of and +// then reinitialize. While I was tempted to sidestep this via some +// unsafe code (eek), lets just instead not encode such tests. + +// fn test_0210_local_void_reinit_and_use_struct() { unimplemented!() } +// fn test_0211_local_void_reinit_and_use_tuple() { unimplemented!() } + +fn test_1000_field_fully_init_and_use_struct() { + let q: Q>; + q.r.f.x = 10; q.r.f.y = Box::new(20); //~ ERROR E0381 + use_fully!(struct q.r.f); +} + +fn test_1001_field_fully_init_and_use_tuple() { + let q: Q; + q.r.f.0 = 10; q.r.f.1 = Box::new(20); //~ ERROR E0381 + use_fully!(tuple q.r.f); +} + +fn test_1010_field_fully_reinit_and_use_struct() { + let mut q: Q> = Q::new(S::new()); drop(q.r); + q.r.f.x = 10; q.r.f.y = Box::new(20); + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_fully!(struct q.r.f); +} + +fn test_1011_field_fully_reinit_and_use_tuple() { + let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + q.r.f.0 = 10; q.r.f.1 = Box::new(20); + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_fully!(tuple q.r.f); +} + +fn test_1100_field_partial_init_and_use_struct() { + let q: Q>; + q.r.f.x = 10; //~ ERROR E0381 + use_part!(struct q.r.f); +} + +fn test_1101_field_partial_init_and_use_tuple() { + let q: Q; + q.r.f.0 = 10; //~ ERROR E0381 + use_part!(tuple q.r.f); +} + +fn test_1110_field_partial_reinit_and_use_struct() { + let mut q: Q> = Q::new(S::new()); drop(q.r); + q.r.f.x = 10; + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_part!(struct q.r.f); +} + +fn test_1111_field_partial_reinit_and_use_tuple() { + let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + q.r.f.0 = 10; + //~^ ERROR assign to part of moved value: `q.r` [E0382] + use_part!(tuple q.r.f); +} + +fn test_1200_field_void_init_and_use_struct() { + let mut q: Q>; + q.r.f.x = 10; //~ ERROR E0381 + use_part!(struct q.r.f); +} + +fn test_1201_field_void_init_and_use_tuple() { + let mut q: Q; + q.r.f.0 = 10; //~ ERROR E0381 + use_part!(tuple q.r.f); +} + +// See NOTE abve. + +// fn test_1210_field_void_reinit_and_use_struct() { unimplemented!() } +// fn test_1211_field_void_reinit_and_use_tuple() { unimplemented!() } + +// The below are some additional cases of interest that have been +// transcribed from other bugs based on old erroneous codegen when we +// encountered partial writes. + +fn issue_26996() { + let mut c = (1, "".to_owned()); + match c { + c2 => { + c.0 = 2; //~ ERROR assign to part of moved value + assert_eq!(c2.0, 1); + } + } +} + +fn issue_27021() { + let mut c = (1, (1, "".to_owned())); + match c { + c2 => { + (c.1).0 = 2; //~ ERROR assign to part of moved value + assert_eq!((c2.1).0, 1); + } + } + + let mut c = (1, (1, (1, "".to_owned()))); + match c.1 { + c2 => { + ((c.1).1).0 = 3; //~ ERROR assign to part of moved value + assert_eq!((c2.1).0, 1); + } + } +} + +fn main() { + test_0000_local_fully_init_and_use_struct(); + test_0001_local_fully_init_and_use_tuple(); + test_0010_local_fully_reinit_and_use_struct(); + test_0011_local_fully_reinit_and_use_tuple(); + test_0100_local_partial_init_and_use_struct(); + test_0101_local_partial_init_and_use_tuple(); + test_0110_local_partial_reinit_and_use_struct(); + test_0111_local_partial_reinit_and_use_tuple(); + test_0200_local_void_init_and_use_struct(); + test_0201_local_void_init_and_use_tuple(); + // test_0210_local_void_reinit_and_use_struct(); + // test_0211_local_void_reinit_and_use_tuple(); + test_1000_field_fully_init_and_use_struct(); + test_1001_field_fully_init_and_use_tuple(); + test_1010_field_fully_reinit_and_use_struct(); + test_1011_field_fully_reinit_and_use_tuple(); + test_1100_field_partial_init_and_use_struct(); + test_1101_field_partial_init_and_use_tuple(); + test_1110_field_partial_reinit_and_use_struct(); + test_1111_field_partial_reinit_and_use_tuple(); + test_1200_field_void_init_and_use_struct(); + test_1201_field_void_init_and_use_tuple(); + // test_1210_field_void_reinit_and_use_struct(); + // test_1211_field_void_reinit_and_use_tuple(); + + issue_26996(); + issue_27021(); +} diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr new file mode 100644 index 000000000..97ed414b1 --- /dev/null +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -0,0 +1,260 @@ +error[E0381]: partially assigned binding `s` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:97:5 + | +LL | let s: S; + | - binding declared here but left uninitialized +LL | s.x = 10; s.y = Box::new(20); + | ^^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:103:5 + | +LL | let t: T; + | - binding declared here but left uninitialized +LL | t.0 = 10; t.1 = Box::new(20); + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign to part of moved value: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:109:5 + | +LL | let mut s: S = S::new(); drop(s); + | ----- - value moved here + | | + | move occurs because `s` has type `S>`, which does not implement the `Copy` trait +LL | s.x = 10; s.y = Box::new(20); + | ^^^^^^^^ value partially assigned here after move + +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:116:5 + | +LL | let mut t: T = (0, Box::new(0)); drop(t); + | ----- - value moved here + | | + | move occurs because `t` has type `(u32, Box)`, which does not implement the `Copy` trait +LL | t.0 = 10; t.1 = Box::new(20); + | ^^^^^^^^ value partially assigned here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut t: T = (0, Box::new(0)); drop(t.clone()); + | ++++++++ + +error[E0381]: partially assigned binding `s` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:123:5 + | +LL | let s: S; + | - binding declared here but left uninitialized +LL | s.x = 10; + | ^^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:129:5 + | +LL | let t: T; + | - binding declared here but left uninitialized +LL | t.0 = 10; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign to part of moved value: `s` + --> $DIR/issue-21232-partial-init-and-use.rs:135:5 + | +LL | let mut s: S = S::new(); drop(s); + | ----- - value moved here + | | + | move occurs because `s` has type `S>`, which does not implement the `Copy` trait +LL | s.x = 10; + | ^^^^^^^^ value partially assigned here after move + +error[E0382]: assign to part of moved value: `t` + --> $DIR/issue-21232-partial-init-and-use.rs:142:5 + | +LL | let mut t: T = (0, Box::new(0)); drop(t); + | ----- - value moved here + | | + | move occurs because `t` has type `(u32, Box)`, which does not implement the `Copy` trait +LL | t.0 = 10; + | ^^^^^^^^ value partially assigned here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut t: T = (0, Box::new(0)); drop(t.clone()); + | ++++++++ + +error[E0381]: partially assigned binding `s` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:149:5 + | +LL | let s: S; + | - binding declared here but left uninitialized +LL | s.x = 10; + | ^^^^^^^^ `s` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `t` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:155:5 + | +LL | let t: Tvoid; + | - binding declared here but left uninitialized +LL | t.0 = 10; + | ^^^^^^^^ `t` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:170:5 + | +LL | let q: Q>; + | - binding declared here but left uninitialized +LL | q.r.f.x = 10; q.r.f.y = Box::new(20); + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:176:5 + | +LL | let q: Q; + | - binding declared here but left uninitialized +LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:182:5 + | +LL | let mut q: Q> = Q::new(S::new()); drop(q.r); + | --- value moved here +LL | q.r.f.x = 10; q.r.f.y = Box::new(20); + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R>>`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:189:5 + | +LL | let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + | --- value moved here +LL | q.r.f.0 = 10; q.r.f.1 = Box::new(20); + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R<(u32, Box)>`, which does not implement the `Copy` trait + +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:196:5 + | +LL | let q: Q>; + | - binding declared here but left uninitialized +LL | q.r.f.x = 10; + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:202:5 + | +LL | let q: Q; + | - binding declared here but left uninitialized +LL | q.r.f.0 = 10; + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:208:5 + | +LL | let mut q: Q> = Q::new(S::new()); drop(q.r); + | --- value moved here +LL | q.r.f.x = 10; + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R>>`, which does not implement the `Copy` trait + +error[E0382]: assign to part of moved value: `q.r` + --> $DIR/issue-21232-partial-init-and-use.rs:215:5 + | +LL | let mut q: Q = Q::new((0, Box::new(0))); drop(q.r); + | --- value moved here +LL | q.r.f.0 = 10; + | ^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `q.r` has type `R<(u32, Box)>`, which does not implement the `Copy` trait + +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:222:5 + | +LL | let mut q: Q>; + | ----- binding declared here but left uninitialized +LL | q.r.f.x = 10; + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0381]: partially assigned binding `q` isn't fully initialized + --> $DIR/issue-21232-partial-init-and-use.rs:228:5 + | +LL | let mut q: Q; + | ----- binding declared here but left uninitialized +LL | q.r.f.0 = 10; + | ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized + | + = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit` + +error[E0382]: assign to part of moved value: `c` + --> $DIR/issue-21232-partial-init-and-use.rs:245:13 + | +LL | let mut c = (1, "".to_owned()); + | ----- move occurs because `c` has type `(i32, String)`, which does not implement the `Copy` trait +LL | match c { +LL | c2 => { + | -- value moved here +LL | c.0 = 2; + | ^^^^^^^ value partially assigned here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref c2 => { + | +++ + +error[E0382]: assign to part of moved value: `c` + --> $DIR/issue-21232-partial-init-and-use.rs:255:13 + | +LL | let mut c = (1, (1, "".to_owned())); + | ----- move occurs because `c` has type `(i32, (i32, String))`, which does not implement the `Copy` trait +LL | match c { +LL | c2 => { + | -- value moved here +LL | (c.1).0 = 2; + | ^^^^^^^^^^^ value partially assigned here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref c2 => { + | +++ + +error[E0382]: assign to part of moved value: `c.1` + --> $DIR/issue-21232-partial-init-and-use.rs:263:13 + | +LL | c2 => { + | -- value moved here +LL | ((c.1).1).0 = 3; + | ^^^^^^^^^^^^^^^ value partially assigned here after move + | + = note: move occurs because `c.1` has type `(i32, (i32, String))`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref c2 => { + | +++ + +error: aborting due to 23 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/nll/issue-22323-temp-destruction.rs b/tests/ui/nll/issue-22323-temp-destruction.rs new file mode 100644 index 000000000..3f2ece1cf --- /dev/null +++ b/tests/ui/nll/issue-22323-temp-destruction.rs @@ -0,0 +1,30 @@ +// rust-lang/rust#22323: regression test demonstrating that NLL +// precisely tracks temporary destruction order. + +// check-pass + +fn main() { + let _s = construct().borrow().consume_borrowed(); +} + +fn construct() -> Value { Value } + +pub struct Value; + +impl Value { + fn borrow<'a>(&'a self) -> Borrowed<'a> { unimplemented!() } +} + +pub struct Borrowed<'a> { + _inner: Guard<'a, Value>, +} + +impl<'a> Borrowed<'a> { + fn consume_borrowed(self) -> String { unimplemented!() } +} + +pub struct Guard<'a, T: ?Sized + 'a> { + _lock: &'a T, +} + +impl<'a, T: ?Sized> Drop for Guard<'a, T> { fn drop(&mut self) {} } diff --git a/tests/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs b/tests/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs new file mode 100644 index 000000000..ccfc8937f --- /dev/null +++ b/tests/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs @@ -0,0 +1,63 @@ +// run-pass +// This test illustrates that under NLL, we can remove our overly +// conservative approach for disallowing mutations of match inputs. + +// See further discussion on rust-lang/rust#24535, +// rust-lang/rfcs#1006, and rust-lang/rfcs#107 + +#![feature(if_let_guard)] + +fn main() { + rust_issue_24535(); + rfcs_issue_1006_1(); + rfcs_issue_1006_2(); +} + +fn rust_issue_24535() { + fn compare(a: &u8, b: &mut u8) -> bool { + a == b + } + + let a = 3u8; + + match a { + 0 => panic!("nope"), + 3 if compare(&a, &mut 3) => (), + _ => panic!("nope"), + } + + match a { + 0 => panic!("nope"), + 3 if let true = compare(&a, &mut 3) => (), + _ => panic!("nope"), + } +} + +fn rfcs_issue_1006_1() { + let v = vec!["1".to_string(), "2".to_string(), "3".to_string()]; + match Some(&v) { + Some(iv) if iv.iter().any(|x| &x[..]=="2") => true, + _ => panic!("nope"), + }; +} + +fn rfcs_issue_1006_2() { + #[inline(always)] + fn check<'a, I: Iterator>(mut i: I) -> bool { + i.any(|&x| x == 2) + } + + let slice = [1, 2, 3]; + + match 42 { + _ if slice.iter().any(|&x| x == 2) => { true }, + _ => { panic!("nope"); } + }; + + // (This match is just illustrating how easy it was to circumvent + // the checking performed for the previous `match`.) + match 42 { + _ if check(slice.iter()) => { true }, + _ => { panic!("nope"); } + }; +} diff --git a/tests/ui/nll/issue-27282-move-match-input-into-guard.rs b/tests/ui/nll/issue-27282-move-match-input-into-guard.rs new file mode 100644 index 000000000..85feda582 --- /dev/null +++ b/tests/ui/nll/issue-27282-move-match-input-into-guard.rs @@ -0,0 +1,34 @@ +// Issue 27282: Example 2: This sidesteps the AST checks disallowing +// mutable borrows in match guards by hiding the mutable borrow in a +// guard behind a move (of the mutably borrowed match input) within a +// closure. +// +// This example is not rejected by AST borrowck (and then reliably +// reaches the panic code when executed, despite the compiler warning +// about that match arm being unreachable. + +#![feature(if_let_guard)] + +fn main() { + let b = &mut true; + match b { + //~^ ERROR use of moved value: `b` [E0382] + &mut false => {}, + _ if { (|| { let bar = b; *bar = false; })(); + false } => { }, + &mut true => { println!("You might think we should get here"); }, + _ => panic!("surely we could never get here, since rustc warns it is unreachable."), + } + + let b = &mut true; + match b { + //~^ ERROR use of moved value: `b` [E0382] + &mut false => {} + _ if let Some(()) = { + (|| { let bar = b; *bar = false; })(); + None + } => {} + &mut true => {} + _ => {} + } +} diff --git a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr new file mode 100644 index 000000000..ae7978004 --- /dev/null +++ b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr @@ -0,0 +1,29 @@ +error[E0382]: use of moved value: `b` + --> $DIR/issue-27282-move-match-input-into-guard.rs:14:5 + | +LL | let b = &mut true; + | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait +LL | match b { + | ^^^^^^^ value used here after move +... +LL | _ if { (|| { let bar = b; *bar = false; })(); + | -- - variable moved due to use in closure + | | + | value moved into closure here + +error[E0382]: use of moved value: `b` + --> $DIR/issue-27282-move-match-input-into-guard.rs:24:5 + | +LL | let b = &mut true; + | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait +LL | match b { + | ^^^^^^^ value used here after move +... +LL | (|| { let bar = b; *bar = false; })(); + | -- - variable moved due to use in closure + | | + | value moved into closure here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs new file mode 100644 index 000000000..833ca8afd --- /dev/null +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs @@ -0,0 +1,23 @@ +// Issue 27282: Example 1: This sidesteps the AST checks disallowing +// mutable borrows in match guards by hiding the mutable borrow in a +// guard behind a move (of the ref mut pattern id) within a closure. + +#![feature(if_let_guard)] + +fn main() { + match Some(&4) { + None => {}, + ref mut foo + if { (|| { let bar = foo; bar.take() })(); false } => {}, + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + Some(s) => std::process::exit(*s), + } +} diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr new file mode 100644 index 000000000..45119018d --- /dev/null +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr @@ -0,0 +1,23 @@ +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19 + | +LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34 + | +LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.rs b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.rs new file mode 100644 index 000000000..d17d6f07f --- /dev/null +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.rs @@ -0,0 +1,31 @@ +// This is testing an attempt to corrupt the discriminant of the match +// arm in a guard, followed by an attempt to continue matching on that +// corrupted discriminant in the remaining match arms. +// +// Basically this is testing that our new NLL feature of emitting a +// fake read on each match arm is catching cases like this. +// +// This case is interesting because it includes a guard that +// diverges, and therefore a single final fake-read at the very end +// after the final match arm would not suffice. + +struct ForceFnOnce; + +fn main() { + let mut x = &mut Some(&2); + let force_fn_once = ForceFnOnce; + match x { + &mut None => panic!("unreachable"), + &mut Some(&_) if { + // ForceFnOnce needed to exploit #27282 + (|| { *x = None; drop(force_fn_once); })(); + //~^ ERROR cannot mutably borrow `x` in match guard [E0510] + false + } => {} + &mut Some(&a) if { // this binds to garbage if we've corrupted discriminant + println!("{}", a); + panic!() + } => {} + _ => panic!("unreachable"), + } +} diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr new file mode 100644 index 000000000..a1f973e0f --- /dev/null +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-1.stderr @@ -0,0 +1,14 @@ +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:21:14 + | +LL | match x { + | - value is immutable in match guard +... +LL | (|| { *x = None; drop(force_fn_once); })(); + | ^^ -- borrow occurs due to use of `x` in closure + | | + | cannot mutably borrow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.rs b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.rs new file mode 100644 index 000000000..9c3e7e997 --- /dev/null +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.rs @@ -0,0 +1,40 @@ +// This is testing an attempt to corrupt the discriminant of the match +// arm in a guard, followed by an attempt to continue matching on that +// corrupted discriminant in the remaining match arms. +// +// Basically this is testing that our new NLL feature of emitting a +// fake read on each match arm is catching cases like this. +// +// This case is interesting because it includes a guard that +// diverges, and therefore a single final fake-read at the very end +// after the final match arm would not suffice. +// +// It is also interesting because the access to the corrupted data +// occurs in the pattern-match itself, and not in the guard +// expression. + +struct ForceFnOnce; + +fn main() { + let mut x = &mut Some(&2); + let force_fn_once = ForceFnOnce; + match x { + &mut None => panic!("unreachable"), + &mut Some(&_) + if { + // ForceFnOnce needed to exploit #27282 + (|| { *x = None; drop(force_fn_once); })(); + //~^ ERROR cannot mutably borrow `x` in match guard [E0510] + false + } => {} + + // this segfaults if we corrupted the discriminant, because + // the compiler gets to *assume* that it cannot be the `None` + // case, even though that was the effect of the guard. + &mut Some(&2) + if { + panic!() + } => {} + _ => panic!("unreachable"), + } +} diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr new file mode 100644 index 000000000..dd46308d1 --- /dev/null +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-2.stderr @@ -0,0 +1,14 @@ +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:26:18 + | +LL | match x { + | - value is immutable in match guard +... +LL | (|| { *x = None; drop(force_fn_once); })(); + | ^^ -- borrow occurs due to use of `x` in closure + | | + | cannot mutably borrow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.rs b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.rs new file mode 100644 index 000000000..cff9e963e --- /dev/null +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.rs @@ -0,0 +1,30 @@ +// This is testing an attempt to corrupt the discriminant of the match +// arm in a guard, followed by an attempt to continue matching on that +// corrupted discriminant in the remaining match arms. +// +// Basically this is testing that our new NLL feature of emitting a +// fake read on each match arm is catching cases like this. +// +// This case is interesting because a borrow of **x is untracked, because **x is +// immutable. However, for matches we care that **x refers to the same value +// until we have chosen a match arm. + +struct ForceFnOnce; +fn main() { + let mut x = &mut &Some(&2); + let force_fn_once = ForceFnOnce; + match **x { + None => panic!("unreachable"), + Some(&_) if { + // ForceFnOnce needed to exploit #27282 + (|| { *x = &None; drop(force_fn_once); })(); + //~^ ERROR cannot mutably borrow `x` in match guard [E0510] + false + } => {} + Some(&a) if { // this binds to garbage if we've corrupted discriminant + println!("{}", a); + panic!() + } => {} + _ => panic!("unreachable"), + } +} diff --git a/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr new file mode 100644 index 000000000..4a4a25790 --- /dev/null +++ b/tests/ui/nll/issue-27282-mutate-before-diverging-arm-3.stderr @@ -0,0 +1,14 @@ +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/issue-27282-mutate-before-diverging-arm-3.rs:20:14 + | +LL | match **x { + | --- value is immutable in match guard +... +LL | (|| { *x = &None; drop(force_fn_once); })(); + | ^^ -- borrow occurs due to use of `x` in closure + | | + | cannot mutably borrow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.rs b/tests/ui/nll/issue-27282-mutation-in-guard.rs new file mode 100644 index 000000000..4f41fc23f --- /dev/null +++ b/tests/ui/nll/issue-27282-mutation-in-guard.rs @@ -0,0 +1,26 @@ +#![feature(if_let_guard)] + +fn main() { + match Some(&4) { + None => {}, + ref mut foo + if { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard + false + } => {}, + Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."), + _ => println!("Here is some supposedly unreachable code."), + } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard + None + } => {}, + Some(_) => {}, + } +} diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr new file mode 100644 index 000000000..1ba696593 --- /dev/null +++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr @@ -0,0 +1,23 @@ +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-mutation-in-guard.rs:8:18 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-mutation-in-guard.rs:20:18 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs b/tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs new file mode 100644 index 000000000..ac06b2b01 --- /dev/null +++ b/tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs @@ -0,0 +1,30 @@ +// Issue 27282: This is a variation on issue-27282-move-ref-mut-into-guard.rs +// +// It reborrows instead of moving the `ref mut` pattern borrow. This +// means that our conservative check for mutation in guards will +// reject it. But I want to make sure that we continue to reject it +// (under NLL) even when that conservative check goes away. + +#![feature(if_let_guard)] + +fn main() { + let mut b = &mut true; + match b { + &mut false => {}, + ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); + //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard + false } => { &mut *r; }, + &mut true => { println!("You might think we should get here"); }, + _ => panic!("surely we could never get here, since rustc warns it is unreachable."), + } + + let mut b = &mut true; + match b { + &mut false => {}, + ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })(); + //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard + None } => { &mut *r; }, + &mut true => {}, + _ => {}, + } +} diff --git a/tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr b/tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr new file mode 100644 index 000000000..5eb7a25bf --- /dev/null +++ b/tests/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -0,0 +1,23 @@ +error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25 + | +LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); + | ^^ -- mutable borrow occurs due to use of `r` in closure + | | + | cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:24:40 + | +LL | ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })(); + | ^^ -- mutable borrow occurs due to use of `r` in closure + | | + | cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/nll/issue-27868.rs b/tests/ui/nll/issue-27868.rs new file mode 100644 index 000000000..e436b22db --- /dev/null +++ b/tests/ui/nll/issue-27868.rs @@ -0,0 +1,28 @@ +// Regression test for issue #27868 + +use std::ops::AddAssign; + +struct MyVec(Vec); + +impl Drop for MyVec { + fn drop(&mut self) { + println!("Being dropped."); + } +} + +impl AddAssign for MyVec { + fn add_assign(&mut self, _elem: T) { + println!("In add_assign."); + } +} + +fn main() { + let mut vec = MyVec(vec![0]); + let mut vecvec = vec![vec]; + + vecvec[0] += { + vecvec = vec![]; + //~^ ERROR cannot assign to `vecvec` because it is borrowed [E0506] + 0 + }; +} diff --git a/tests/ui/nll/issue-27868.stderr b/tests/ui/nll/issue-27868.stderr new file mode 100644 index 000000000..e0b3b5494 --- /dev/null +++ b/tests/ui/nll/issue-27868.stderr @@ -0,0 +1,18 @@ +error[E0506]: cannot assign to `vecvec` because it is borrowed + --> $DIR/issue-27868.rs:24:9 + | +LL | vecvec[0] += { + | ------ + | | + | _____borrow of `vecvec` occurs here + | | +LL | | vecvec = vec![]; + | | ^^^^^^ assignment to borrowed `vecvec` occurs here +LL | | +LL | | 0 +LL | | }; + | |_____- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-30104.rs b/tests/ui/nll/issue-30104.rs new file mode 100644 index 000000000..38850cd3f --- /dev/null +++ b/tests/ui/nll/issue-30104.rs @@ -0,0 +1,40 @@ +// Regression test for #30104 + +// check-pass + +use std::ops::{Deref, DerefMut}; + +fn box_two_field(v: &mut Box<(i32, i32)>) { + let _a = &mut v.0; + let _b = &mut v.1; +} + +fn box_destructure(v: &mut Box<(i32, i32)>) { + let (ref mut _head, ref mut _tail) = **v; +} + +struct Wrap(T); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +impl DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +fn smart_two_field(v: &mut Wrap<(i32, i32)>) { + let _a = &mut v.0; + let _b = &mut v.1; +} + +fn smart_destructure(v: &mut Wrap<(i32, i32)>) { + let (ref mut _head, ref mut _tail) = **v; +} + +fn main() {} diff --git a/tests/ui/nll/issue-31567.rs b/tests/ui/nll/issue-31567.rs new file mode 100644 index 000000000..623954e6d --- /dev/null +++ b/tests/ui/nll/issue-31567.rs @@ -0,0 +1,25 @@ +// Regression test for #31567: cached results of projections were +// causing region relations not to be enforced at all the places where +// they have to be enforced. + +struct VecWrapper<'a>(&'a mut S); + +struct S(Box); + +fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 { + let s_inner: &'a S = &*v.0; //~ ERROR borrow may still be in use when destructor runs [E0713] + &s_inner.0 +} + +impl<'a> Drop for VecWrapper<'a> { + fn drop(&mut self) { + *self.0 = S(Box::new(0)); + } +} + +fn main() { + let mut s = S(Box::new(11)); + let vw = VecWrapper(&mut s); + let dangling = get_dangling(vw); + println!("{}", dangling); +} diff --git a/tests/ui/nll/issue-31567.stderr b/tests/ui/nll/issue-31567.stderr new file mode 100644 index 000000000..7d43383e8 --- /dev/null +++ b/tests/ui/nll/issue-31567.stderr @@ -0,0 +1,16 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-31567.rs:10:26 + | +LL | fn get_dangling<'a>(v: VecWrapper<'a>) -> &'a u32 { + | -- lifetime `'a` defined here +LL | let s_inner: &'a S = &*v.0; + | ----- ^^^^^ + | | + | type annotation requires that `*v.0` is borrowed for `'a` +LL | &s_inner.0 +LL | } + | - here, drop of `v` needs exclusive access to `*v.0`, because the type `VecWrapper<'_>` implements the `Drop` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs b/tests/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs new file mode 100644 index 000000000..a8a8e6930 --- /dev/null +++ b/tests/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs @@ -0,0 +1,41 @@ +// check-pass + +// rust-lang/rust#32382: Borrow checker used to complain about +// `foobar_3` in the `impl` below, presumably due to some interaction +// between the use of a lifetime in the associated type and the use of +// the overloaded operator[]. This regression test ensures that we do +// not resume complaining about it in the future. + + +use std::marker::PhantomData; +use std::ops::Index; + +pub trait Context: Clone { + type Container: ?Sized; + fn foobar_1( container: &Self::Container ) -> &str; + fn foobar_2( container: &Self::Container ) -> &str; + fn foobar_3( container: &Self::Container ) -> &str; +} + +#[derive(Clone)] +struct Foobar<'a> { + phantom: PhantomData<&'a ()> +} + +impl<'a> Context for Foobar<'a> { + type Container = [&'a str]; + + fn foobar_1<'r>( container: &'r [&'a str] ) -> &'r str { + container[0] + } + + fn foobar_2<'r>( container: &'r Self::Container ) -> &'r str { + container.index( 0 ) + } + + fn foobar_3<'r>( container: &'r Self::Container ) -> &'r str { + container[0] + } +} + +fn main() { } diff --git a/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.rs b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.rs new file mode 100644 index 000000000..0ec0179e8 --- /dev/null +++ b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.rs @@ -0,0 +1,11 @@ +// This test illustrates a case where full NLL (enabled by the feature +// switch below) produces superior diagnostics to the NLL-migrate +// mode. + +fn doit(data: &'static mut ()) { + || doit(data); + //~^ ERROR lifetime may not live long enough + //~| ERROR `data` does not live long enough +} + +fn main() { } diff --git a/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr new file mode 100644 index 000000000..f7a525ee9 --- /dev/null +++ b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/issue-42574-diagnostic-in-nested-closure.rs:6:8 + | +LL | || doit(data); + | -- ^^^^^^^^^^ argument requires that `'1` must outlive `'static` + | | + | lifetime `'1` represents this closure's body + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure + +error[E0597]: `data` does not live long enough + --> $DIR/issue-42574-diagnostic-in-nested-closure.rs:6:13 + | +LL | || doit(data); + | -- -----^^^^- + | | | | + | | | borrowed value does not live long enough + | | argument requires that `data` is borrowed for `'static` + | value captured here +... +LL | } + | - `data` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-43058.rs b/tests/ui/nll/issue-43058.rs new file mode 100644 index 000000000..227888d17 --- /dev/null +++ b/tests/ui/nll/issue-43058.rs @@ -0,0 +1,26 @@ +// check-pass + +use std::borrow::Cow; + +#[derive(Clone, Debug)] +struct S<'a> { + name: Cow<'a, str> +} + +#[derive(Clone, Debug)] +struct T<'a> { + s: Cow<'a, [S<'a>]> +} + +fn main() { + let s1 = [S { name: Cow::Borrowed("Test1") }, S { name: Cow::Borrowed("Test2") }]; + let b1 = T { s: Cow::Borrowed(&s1) }; + let s2 = [S { name: Cow::Borrowed("Test3") }, S { name: Cow::Borrowed("Test4") }]; + let b2 = T { s: Cow::Borrowed(&s2) }; + + let mut v = Vec::new(); + v.push(b1); + v.push(b2); + + println!("{:?}", v); +} diff --git a/tests/ui/nll/issue-45157.rs b/tests/ui/nll/issue-45157.rs new file mode 100644 index 000000000..8d2bf22a0 --- /dev/null +++ b/tests/ui/nll/issue-45157.rs @@ -0,0 +1,31 @@ +#![allow(unused)] + + +#[derive(Clone, Copy, Default)] +struct S { + a: u8, + b: u8, +} +#[derive(Clone, Copy, Default)] +struct Z { + c: u8, + d: u8, +} + +union U { + s: S, + z: Z, +} + +fn main() { + unsafe { + let mut u = U { s: Default::default() }; + + let mref = &mut u.s.a; + *mref = 22; + + let nref = &u.z.c; + //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502] + println!("{} {}", mref, nref) + } +} diff --git a/tests/ui/nll/issue-45157.stderr b/tests/ui/nll/issue-45157.stderr new file mode 100644 index 000000000..57fd8d49c --- /dev/null +++ b/tests/ui/nll/issue-45157.stderr @@ -0,0 +1,17 @@ +error[E0502]: cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) + --> $DIR/issue-45157.rs:27:20 + | +LL | let mref = &mut u.s.a; + | ---------- mutable borrow occurs here (via `u.s.a`) +... +LL | let nref = &u.z.c; + | ^^^^^^ immutable borrow of `u.z.c` -- which overlaps with `u.s.a` -- occurs here +LL | +LL | println!("{} {}", mref, nref) + | ---- mutable borrow later used here + | + = note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-45696-long-live-borrows-in-boxes.rs b/tests/ui/nll/issue-45696-long-live-borrows-in-boxes.rs new file mode 100644 index 000000000..b3f655628 --- /dev/null +++ b/tests/ui/nll/issue-45696-long-live-borrows-in-boxes.rs @@ -0,0 +1,114 @@ +// rust-lang/rust#45696: This test is checking that we can return +// mutable borrows owned by boxes even when the boxes are dropped. + +// run-pass + +// This function shows quite directly what is going on: We have a +// reborrow of contents within the box. +fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x } + +// This function is the way you'll probably see this in practice (the +// reborrow is now implicit). +fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x } + +// For the remaining tests we just add some fields or other +// indirection to ensure that the compiler isn't just special-casing +// the above `Box<&mut T>` as the only type that would work. + +// Here we add a tuple of indirection between the box and the +// reference. +type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>; + +fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 { + &mut *x.0 +} + +fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 { + x.0 +} + +fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 { + &mut *(x.0).0 +} + +fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 { + (x.0).0 +} + +fn basic_tests() { + let mut x = 2; + let mut y = 3; + let mut z = 4; + *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10; + assert_eq!((x, y, z), (12, 3, 4)); + *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10; + assert_eq!((x, y, z), (22, 3, 4)); + *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10; + assert_eq!((x, y, z), (32, 3, 4)); + *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10; + assert_eq!((x, y, z), (42, 3, 4)); + *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10; + assert_eq!((x, y, z), (52, 3, 4)); + *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10; + assert_eq!((x, y, z), (62, 3, 4)); +} + +// These scribbling tests have been transcribed from +// issue-45696-scribble-on-boxed-borrow.rs +// +// In the context of that file, these tests are meant to show cases +// that should be *accepted* by the compiler, so here we are actually +// checking that the code we get when they are compiled matches our +// expectations. + +struct Scribble<'a>(&'a mut u32); + +impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } } + +// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has* +// to strictly outlive `'a` +fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 { + &mut *s.0 +} + +// this, by analogy to previous case, is also okay. +fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 { + &mut *(*s).0 +} + +// this, by analogy to previous case, is also okay. +fn boxed_boxed_borrowed_scribble<'a>(s: Box>) -> &'a mut u32 { + &mut *(**s).0 +} + +fn scribbling_tests() { + let mut x = 1; + { + let mut long_lived = Scribble(&mut x); + *borrowed_scribble(&mut long_lived) += 10; + assert_eq!(*long_lived.0, 11); + // (Scribble dtor runs here, after `&mut`-borrow above ends) + } + assert_eq!(x, 42); + x = 1; + { + let mut long_lived = Scribble(&mut x); + *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10; + assert_eq!(*long_lived.0, 11); + // (Scribble dtor runs here, after `&mut`-borrow above ends) + } + assert_eq!(x, 42); + x = 1; + { + let mut long_lived = Scribble(&mut x); + *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10; + assert_eq!(*long_lived.0, 11); + // (Scribble dtor runs here, after `&mut`-borrow above ends) + } + assert_eq!(x, 42); +} + +fn main() { + basic_tests(); + scribbling_tests(); +} diff --git a/tests/ui/nll/issue-45696-no-variant-box-recur.rs b/tests/ui/nll/issue-45696-no-variant-box-recur.rs new file mode 100644 index 000000000..39f1607a3 --- /dev/null +++ b/tests/ui/nll/issue-45696-no-variant-box-recur.rs @@ -0,0 +1,47 @@ +// rust-lang/rust#45696: This test checks the compiler won't infinite loop when +// you declare a variable of type `struct A(Box, ...);` (which is impossible +// to construct but *is* possible to declare; see also issues #4287, #44933, +// and #52852). + +// run-pass + +// This test has structs and functions that are by definition unusable +// all over the place, so just go ahead and allow dead_code +#![allow(dead_code)] + +// direct regular recursion with indirect ownership via box +struct C { field: Box } + +// direct non-regular recursion with indirect ownership via box +struct D { field: Box<(D, D)> } + +// indirect regular recursion with indirect ownership via box. +struct E { field: F } +struct F { field: Box } + +// indirect non-regular recursion with indirect ownership via box. +struct G { field: (H, H) } +struct H { field: Box } + +// These enums are cases that are not currently hit by the +// `visit_terminator_drop` recursion down a type's structural +// definition. +// +// But it seems prudent to include them in this test as variants on +// the above, in that they are similarly non-constructable data types +// with destructors that would diverge. +enum I { One(Box) } +enum J { One(Box), Two(Box) } + +fn impossible_to_call_c(_c: C) { } +fn impossible_to_call_d(_d: D) { } +fn impossible_to_call_e(_e: E) { } +fn impossible_to_call_f(_f: F) { } +fn impossible_to_call_g(_g: G) { } +fn impossible_to_call_h(_h: H) { } +fn impossible_to_call_i(_i: I) { } +fn impossible_to_call_j(_j: J) { } + +fn main() { + +} diff --git a/tests/ui/nll/issue-45696-scribble-on-boxed-borrow.rs b/tests/ui/nll/issue-45696-scribble-on-boxed-borrow.rs new file mode 100644 index 000000000..637cf278f --- /dev/null +++ b/tests/ui/nll/issue-45696-scribble-on-boxed-borrow.rs @@ -0,0 +1,67 @@ +// rust-lang/rust#45696: This test is checking that we *cannot* return +// mutable borrows that would be scribbled over by destructors before +// the return occurs. + +// ignore-compare-mode-polonius + +struct Scribble<'a>(&'a mut u32); + +impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } } + +// this is okay: The `Scribble` here *has* to strictly outlive `'a` +fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 { + &mut *s.0 +} + +// this, by analogy to previous case, is also okay. +fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 { + &mut *(*s).0 +} + +// this, by analogy to previous case, is also okay. +fn boxed_boxed_borrowed_scribble<'a>(s: Box>) -> &'a mut u32 { + &mut *(**s).0 +} + +// this is not okay: in between the time that we take the mutable +// borrow and the caller receives it as a return value, the drop of +// `s` will scribble on it, violating our aliasing guarantees. +// +// * (Maybe in the future the two-phase borrows system will be +// extended to support this case. But for now, it is an error in +// NLL, even with two-phase borrows.) +fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 { + &mut *s.0 //~ ERROR borrow may still be in use when destructor runs [E0713] +} + +// This, by analogy to previous case, is *also* not okay. +fn boxed_scribbled<'a>(s: Box>) -> &'a mut u32 { + &mut *(*s).0 //~ ERROR borrow may still be in use when destructor runs [E0713] +} + +// This, by analogy to previous case, is *also* not okay. +fn boxed_boxed_scribbled<'a>(s: Box>>) -> &'a mut u32 { + &mut *(**s).0 //~ ERROR borrow may still be in use when destructor runs [E0713] +} + +fn main() { + let mut x = 1; + { + let mut long_lived = Scribble(&mut x); + *borrowed_scribble(&mut long_lived) += 10; + // (Scribble dtor runs here, after `&mut`-borrow above ends) + } + { + let mut long_lived = Scribble(&mut x); + *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10; + // (Scribble dtor runs here, after `&mut`-borrow above ends) + } + { + let mut long_lived = Scribble(&mut x); + *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10; + // (Scribble dtor runs here, after `&mut`-borrow above ends) + } + *scribbled(Scribble(&mut x)) += 10; + *boxed_scribbled(Box::new(Scribble(&mut x))) += 10; + *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10; +} diff --git a/tests/ui/nll/issue-45696-scribble-on-boxed-borrow.stderr b/tests/ui/nll/issue-45696-scribble-on-boxed-borrow.stderr new file mode 100644 index 000000000..db0a17199 --- /dev/null +++ b/tests/ui/nll/issue-45696-scribble-on-boxed-borrow.stderr @@ -0,0 +1,33 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:34:5 + | +LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 { + | -- lifetime `'a` defined here +LL | &mut *s.0 + | ^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a` +LL | } + | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait + +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:39:5 + | +LL | fn boxed_scribbled<'a>(s: Box>) -> &'a mut u32 { + | -- lifetime `'a` defined here +LL | &mut *(*s).0 + | ^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a` +LL | } + | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait + +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:44:5 + | +LL | fn boxed_boxed_scribbled<'a>(s: Box>>) -> &'a mut u32 { + | -- lifetime `'a` defined here +LL | &mut *(**s).0 + | ^^^^^^^^^^^^^ returning this value requires that `*s.0` is borrowed for `'a` +LL | } + | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/issue-46023.rs b/tests/ui/nll/issue-46023.rs new file mode 100644 index 000000000..a923eb244 --- /dev/null +++ b/tests/ui/nll/issue-46023.rs @@ -0,0 +1,8 @@ +fn main() { + let x = 0; + + (move || { + x = 1; + //~^ ERROR cannot assign to `x`, as it is not declared as mutable [E0594] + })() +} diff --git a/tests/ui/nll/issue-46023.stderr b/tests/ui/nll/issue-46023.stderr new file mode 100644 index 000000000..ca19c2501 --- /dev/null +++ b/tests/ui/nll/issue-46023.stderr @@ -0,0 +1,12 @@ +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/issue-46023.rs:5:9 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | x = 1; + | ^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/issue-46036.rs b/tests/ui/nll/issue-46036.rs new file mode 100644 index 000000000..18af33c18 --- /dev/null +++ b/tests/ui/nll/issue-46036.rs @@ -0,0 +1,12 @@ +// Issue 46036: [NLL] false edges on infinite loops +// Infinite loops should create false edges to the cleanup block. + +struct Foo { x: &'static u32 } + +fn foo() { + let a = 3; + let foo = Foo { x: &a }; //~ ERROR E0597 + loop { } +} + +fn main() { } diff --git a/tests/ui/nll/issue-46036.stderr b/tests/ui/nll/issue-46036.stderr new file mode 100644 index 000000000..e6e95ee61 --- /dev/null +++ b/tests/ui/nll/issue-46036.stderr @@ -0,0 +1,15 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-46036.rs:8:24 + | +LL | let foo = Foo { x: &a }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `a` is borrowed for `'static` +LL | loop { } +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-46589.rs b/tests/ui/nll/issue-46589.rs new file mode 100644 index 000000000..0a4c20d15 --- /dev/null +++ b/tests/ui/nll/issue-46589.rs @@ -0,0 +1,31 @@ +// This tests passes in Polonius mode, so is skipped in the automated compare-mode. +// We will manually check it passes in Polonius tests, as we can't have a test here +// which conditionally passes depending on a test revision/compile-flags. + +// ignore-compare-mode-polonius + +struct Foo; + +impl Foo { + fn get_self(&mut self) -> Option<&mut Self> { + Some(self) + } + + fn new_self(&mut self) -> &mut Self { + self + } + + fn trigger_bug(&mut self) { + let other = &mut (&mut *self); + + *other = match (*other).get_self() { + Some(s) => s, + None => (*other).new_self() + //~^ ERROR cannot borrow `**other` as mutable more than once at a time [E0499] + }; + + let c = other; + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-46589.stderr b/tests/ui/nll/issue-46589.stderr new file mode 100644 index 000000000..60ef3f7b8 --- /dev/null +++ b/tests/ui/nll/issue-46589.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `**other` as mutable more than once at a time + --> $DIR/issue-46589.rs:23:21 + | +LL | *other = match (*other).get_self() { + | ------------------- first mutable borrow occurs here +LL | Some(s) => s, +LL | None => (*other).new_self() + | ^^^^^^^^^^^^^^^^^^^ + | | + | second mutable borrow occurs here + | first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/issue-47022.rs b/tests/ui/nll/issue-47022.rs new file mode 100644 index 000000000..521643c66 --- /dev/null +++ b/tests/ui/nll/issue-47022.rs @@ -0,0 +1,33 @@ +// check-pass + +struct LoadedObject { + bodies: Vec, + color: Color, +} + +struct Body; + +#[derive(Clone)] +struct Color; + +struct Graphic { + color: Color, +} + +fn convert(objects: Vec) -> (Vec, Vec) { + objects + .into_iter() + .flat_map(|LoadedObject { bodies, color, .. }| { + bodies.into_iter().map(move |body| { + ( + body, + Graphic { + color: color.clone(), + }, + ) + }) + }) + .unzip() +} + +fn main() {} diff --git a/tests/ui/nll/issue-47153-generic-const.rs b/tests/ui/nll/issue-47153-generic-const.rs new file mode 100644 index 000000000..9f4d57111 --- /dev/null +++ b/tests/ui/nll/issue-47153-generic-const.rs @@ -0,0 +1,18 @@ +// run-pass + +// Regression test for #47153: constants in a generic context (such as +// a trait) used to ICE. + +#![allow(warnings)] + +trait Foo { + const B: bool = true; +} + +struct Bar { x: T } + +impl Bar { + const B: bool = true; +} + +fn main() { } diff --git a/tests/ui/nll/issue-47388.rs b/tests/ui/nll/issue-47388.rs new file mode 100644 index 000000000..207af380e --- /dev/null +++ b/tests/ui/nll/issue-47388.rs @@ -0,0 +1,10 @@ +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy = FancyNum{ num: 5 }; + let fancy_ref = &(&mut fancy); + fancy_ref.num = 6; //~ ERROR E0594 + println!("{}", fancy_ref.num); +} diff --git a/tests/ui/nll/issue-47388.stderr b/tests/ui/nll/issue-47388.stderr new file mode 100644 index 000000000..c780451df --- /dev/null +++ b/tests/ui/nll/issue-47388.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference + --> $DIR/issue-47388.rs:8:5 + | +LL | fancy_ref.num = 6; + | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let fancy_ref = &mut (&mut fancy); + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/issue-47470.rs b/tests/ui/nll/issue-47470.rs new file mode 100644 index 000000000..72ee7f886 --- /dev/null +++ b/tests/ui/nll/issue-47470.rs @@ -0,0 +1,22 @@ +// Regression test for #47470: cached results of projections were +// causing region relations not to be enforced at all the places where +// they have to be enforced. + +struct Foo<'a>(&'a ()); +trait Bar { + type Assoc; + fn get(self) -> Self::Assoc; +} + +impl<'a> Bar for Foo<'a> { + type Assoc = &'a u32; + fn get(self) -> Self::Assoc { + let local = 42; + &local //~ ERROR cannot return reference to local variable `local` + } +} + +fn main() { + let f = Foo(&()).get(); + println!("{}", f); +} diff --git a/tests/ui/nll/issue-47470.stderr b/tests/ui/nll/issue-47470.stderr new file mode 100644 index 000000000..0b1247d60 --- /dev/null +++ b/tests/ui/nll/issue-47470.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to local variable `local` + --> $DIR/issue-47470.rs:15:9 + | +LL | &local + | ^^^^^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-47589.rs b/tests/ui/nll/issue-47589.rs new file mode 100644 index 000000000..280bf0811 --- /dev/null +++ b/tests/ui/nll/issue-47589.rs @@ -0,0 +1,23 @@ +// run-pass + +pub struct DescriptorSet<'a> { + pub slots: Vec> +} + +pub trait ResourcesTrait<'r>: Sized { + type DescriptorSet: 'r; +} + +pub struct Resources; + +impl<'a> ResourcesTrait<'a> for Resources { + type DescriptorSet = DescriptorSet<'a>; +} + +pub enum AttachInfo<'a, R: ResourcesTrait<'a>> { + NextDescriptorSet(Box) +} + +fn main() { + let _x = DescriptorSet {slots: Vec::new()}; +} diff --git a/tests/ui/nll/issue-48070.rs b/tests/ui/nll/issue-48070.rs new file mode 100644 index 000000000..a9fe3521d --- /dev/null +++ b/tests/ui/nll/issue-48070.rs @@ -0,0 +1,22 @@ +// run-pass + +struct Foo { + x: u32 +} + +impl Foo { + fn twiddle(&mut self) -> &mut Self { self } + fn twaddle(&mut self) -> &mut Self { self } + fn emit(&mut self) { + self.x += 1; + } +} + +fn main() { + let mut foo = Foo { x: 0 }; + match 22 { + 22 => &mut foo, + 44 => foo.twiddle(), + _ => foo.twaddle(), + }.emit(); +} diff --git a/tests/ui/nll/issue-48238.rs b/tests/ui/nll/issue-48238.rs new file mode 100644 index 000000000..d2e9285fa --- /dev/null +++ b/tests/ui/nll/issue-48238.rs @@ -0,0 +1,10 @@ +// Regression test for issue #48238 + +fn use_val<'a>(val: &'a u8) -> &'a u8 { + val +} + +fn main() { + let orig: u8 = 5; + move || use_val(&orig); //~ ERROR +} diff --git a/tests/ui/nll/issue-48238.stderr b/tests/ui/nll/issue-48238.stderr new file mode 100644 index 000000000..0aa1eedad --- /dev/null +++ b/tests/ui/nll/issue-48238.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/issue-48238.rs:9:13 + | +LL | move || use_val(&orig); + | ------- ^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure is &'2 u8 + | lifetime `'1` represents this closure's body + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-48623-closure.rs b/tests/ui/nll/issue-48623-closure.rs new file mode 100644 index 000000000..3f8587eed --- /dev/null +++ b/tests/ui/nll/issue-48623-closure.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(path_statements)] +#![allow(dead_code)] + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +fn reborrow_from_closure(r: &mut ()) -> &mut () { + let d = WithDrop; + (move || { d; &mut *r })() +} + +fn main() {} diff --git a/tests/ui/nll/issue-48623-generator.rs b/tests/ui/nll/issue-48623-generator.rs new file mode 100644 index 000000000..08d2584ee --- /dev/null +++ b/tests/ui/nll/issue-48623-generator.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(path_statements)] +#![allow(dead_code)] + +#![feature(generators, generator_trait)] + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +fn reborrow_from_generator(r: &mut ()) { + let d = WithDrop; + move || { d; yield; &mut *r }; //~ WARN unused generator that must be used +} + +fn main() {} diff --git a/tests/ui/nll/issue-48623-generator.stderr b/tests/ui/nll/issue-48623-generator.stderr new file mode 100644 index 000000000..bfdfca210 --- /dev/null +++ b/tests/ui/nll/issue-48623-generator.stderr @@ -0,0 +1,11 @@ +warning: unused generator that must be used + --> $DIR/issue-48623-generator.rs:15:5 + | +LL | move || { d; yield; &mut *r }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: generators are lazy and do nothing unless resumed + = note: `#[warn(unused_must_use)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/nll/issue-48697.rs b/tests/ui/nll/issue-48697.rs new file mode 100644 index 000000000..16e29ab2a --- /dev/null +++ b/tests/ui/nll/issue-48697.rs @@ -0,0 +1,10 @@ +// Regression test for #48697 + +fn foo(x: &i32) -> &i32 { + let z = 4; + let f = &|y| y; + let k = f(&z); + f(x) //~ cannot return value referencing local variable +} + +fn main() {} diff --git a/tests/ui/nll/issue-48697.stderr b/tests/ui/nll/issue-48697.stderr new file mode 100644 index 000000000..f0c29b72b --- /dev/null +++ b/tests/ui/nll/issue-48697.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing local variable `z` + --> $DIR/issue-48697.rs:7:5 + | +LL | let k = f(&z); + | -- `z` is borrowed here +LL | f(x) + | ^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-48803.rs b/tests/ui/nll/issue-48803.rs new file mode 100644 index 000000000..f7fd04179 --- /dev/null +++ b/tests/ui/nll/issue-48803.rs @@ -0,0 +1,13 @@ +fn flatten<'a, 'b, T>(x: &'a &'b T) -> &'a T { + x +} + +fn main() { + let mut x = "original"; + let y = &x; + let z = &y; + let w = flatten(z); + x = "modified"; + //~^ ERROR cannot assign to `x` because it is borrowed [E0506] + println!("{}", w); // prints "modified" +} diff --git a/tests/ui/nll/issue-48803.stderr b/tests/ui/nll/issue-48803.stderr new file mode 100644 index 000000000..2f94039c0 --- /dev/null +++ b/tests/ui/nll/issue-48803.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/issue-48803.rs:10:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +... +LL | x = "modified"; + | ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here +LL | +LL | println!("{}", w); // prints "modified" + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-50343.rs b/tests/ui/nll/issue-50343.rs new file mode 100644 index 000000000..dd0afbbdf --- /dev/null +++ b/tests/ui/nll/issue-50343.rs @@ -0,0 +1,8 @@ +// run-pass + +#![deny(unused_mut)] + +fn main() { + vec![42].iter().map(drop).count(); + vec![(42, 22)].iter().map(|(_x, _y)| ()).count(); +} diff --git a/tests/ui/nll/issue-50461-used-mut-from-moves.rs b/tests/ui/nll/issue-50461-used-mut-from-moves.rs new file mode 100644 index 000000000..2458b171e --- /dev/null +++ b/tests/ui/nll/issue-50461-used-mut-from-moves.rs @@ -0,0 +1,17 @@ +// run-pass + +#![deny(unused_mut)] +#![allow(dead_code)] + +struct Foo { + pub value: i32 +} + +fn use_foo_mut(mut foo: Foo) { + foo = foo; + println!("{}", foo.value); +} + +fn main() { + use_foo_mut(Foo { value: 413 }); +} diff --git a/tests/ui/nll/issue-50716-1.rs b/tests/ui/nll/issue-50716-1.rs new file mode 100644 index 000000000..9c3e24de4 --- /dev/null +++ b/tests/ui/nll/issue-50716-1.rs @@ -0,0 +1,10 @@ +// +// An additional regression test for the issue #50716 “NLL ignores lifetimes +// bounds derived from `Sized` requirements†that checks that the fixed compiler +// accepts this code fragment with both AST and MIR borrow checkers. +// +// check-pass + +struct Qey(Q); + +fn main() {} diff --git a/tests/ui/nll/issue-50716.rs b/tests/ui/nll/issue-50716.rs new file mode 100644 index 000000000..c2fc345fa --- /dev/null +++ b/tests/ui/nll/issue-50716.rs @@ -0,0 +1,17 @@ +// +// Regression test for the issue #50716: NLL ignores lifetimes bounds +// derived from `Sized` requirements + +trait A { + type X: ?Sized; +} + +fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) +where + for<'b> &'b T: A, + <&'static T as A>::X: Sized +{ + let _x = *s; //~ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/issue-50716.stderr b/tests/ui/nll/issue-50716.stderr new file mode 100644 index 000000000..38dd1b5f6 --- /dev/null +++ b/tests/ui/nll/issue-50716.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-50716.rs:14:14 + | +LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) + | -- lifetime `'a` defined here +... +LL | let _x = *s; + | ^^ proving this value is `Sized` requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-51191.rs b/tests/ui/nll/issue-51191.rs new file mode 100644 index 000000000..836587d93 --- /dev/null +++ b/tests/ui/nll/issue-51191.rs @@ -0,0 +1,34 @@ +struct Struct; + +impl Struct { + fn bar(self: &mut Self) { + //~^ WARN function cannot return without recursing + //~^^ HELP a `loop` may express intention better if this is on purpose + (&mut self).bar(); + //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~^^ HELP try removing `&mut` here + } + + fn imm(self) { //~ HELP consider changing this to be mutable + (&mut self).bar(); + //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + } + + fn mtbl(mut self) { + (&mut self).bar(); + } + + fn immref(&self) { + (&mut self).bar(); + //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~^^ ERROR cannot borrow data in a `&` reference as mutable [E0596] + } + + fn mtblref(&mut self) { + (&mut self).bar(); + //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~^^ HELP try removing `&mut` here + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-51191.stderr b/tests/ui/nll/issue-51191.stderr new file mode 100644 index 000000000..27b1f8705 --- /dev/null +++ b/tests/ui/nll/issue-51191.stderr @@ -0,0 +1,72 @@ +warning: function cannot return without recursing + --> $DIR/issue-51191.rs:4:5 + | +LL | fn bar(self: &mut Self) { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | (&mut self).bar(); + | ----------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-51191.rs:7:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/issue-51191.rs:4:18 + | +LL | fn bar(self: &mut Self) { + | ^^^^^^^^^ +help: try removing `&mut` here + --> $DIR/issue-51191.rs:7:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ + +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-51191.rs:13:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn imm(mut self) { + | +++ + +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-51191.rs:22:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-51191.rs:22:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-51191.rs:28:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/issue-51191.rs:27:16 + | +LL | fn mtblref(&mut self) { + | ^^^^^^^^^ +help: try removing `&mut` here + --> $DIR/issue-51191.rs:28:9 + | +LL | (&mut self).bar(); + | ^^^^^^^^^^^ + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/nll/issue-51244.rs b/tests/ui/nll/issue-51244.rs new file mode 100644 index 000000000..c4cbee675 --- /dev/null +++ b/tests/ui/nll/issue-51244.rs @@ -0,0 +1,5 @@ +fn main() { + let ref my_ref @ _ = 0; + *my_ref = 0; + //~^ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594] +} diff --git a/tests/ui/nll/issue-51244.stderr b/tests/ui/nll/issue-51244.stderr new file mode 100644 index 000000000..03d8acc81 --- /dev/null +++ b/tests/ui/nll/issue-51244.stderr @@ -0,0 +1,14 @@ +error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference + --> $DIR/issue-51244.rs:3:5 + | +LL | *my_ref = 0; + | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let ref mut my_ref @ _ = 0; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/nll/issue-51268.rs b/tests/ui/nll/issue-51268.rs new file mode 100644 index 000000000..dcdedf7d4 --- /dev/null +++ b/tests/ui/nll/issue-51268.rs @@ -0,0 +1,21 @@ +struct Bar; + +impl Bar { + fn bar(&mut self, _: impl Fn()) {} +} + +struct Foo { + thing: Bar, + number: usize, +} + +impl Foo { + fn foo(&mut self) { + self.thing.bar(|| { + //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502] + &self.number; + }); + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-51268.stderr b/tests/ui/nll/issue-51268.stderr new file mode 100644 index 000000000..0483bda63 --- /dev/null +++ b/tests/ui/nll/issue-51268.stderr @@ -0,0 +1,17 @@ +error[E0502]: cannot borrow `self.thing` as mutable because it is also borrowed as immutable + --> $DIR/issue-51268.rs:14:9 + | +LL | self.thing.bar(|| { + | ^ --- -- immutable borrow occurs here + | | | + | _________| immutable borrow later used by call + | | +LL | | +LL | | &self.number; + | | ----------- first borrow occurs due to use of `self` in closure +LL | | }); + | |__________^ mutable borrow occurs here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-51345-2.rs b/tests/ui/nll/issue-51345-2.rs new file mode 100644 index 000000000..52f342a85 --- /dev/null +++ b/tests/ui/nll/issue-51345-2.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern: thread 'main' panicked at 'explicit panic' +// ignore-emscripten no processes + +fn main() { + let mut vec = vec![]; + vec.push((vec.len(), panic!())); +} diff --git a/tests/ui/nll/issue-51351.rs b/tests/ui/nll/issue-51351.rs new file mode 100644 index 000000000..591d49584 --- /dev/null +++ b/tests/ui/nll/issue-51351.rs @@ -0,0 +1,21 @@ +// +// Regression test for #51351 and #52133: In the case of #51351, +// late-bound regions (like 'a) that were unused within the arguments of +// a function were overlooked and could case an ICE. In the case of #52133, +// LBR defined on the creator function needed to be added to the free regions +// of the closure, as they were not present in the closure's generic +// declarations otherwise. +// +// check-pass + +fn creash<'a>() { + let x: &'a () = &(); +} + +fn produce<'a>() { + move || { + let x: &'a () = &(); + }; +} + +fn main() {} diff --git a/tests/ui/nll/issue-51512.rs b/tests/ui/nll/issue-51512.rs new file mode 100644 index 000000000..691760eb9 --- /dev/null +++ b/tests/ui/nll/issue-51512.rs @@ -0,0 +1,6 @@ +fn main() { + let range = 0..1; + let r = range; + let x = range.start; + //~^ ERROR use of moved value: `range` [E0382] +} diff --git a/tests/ui/nll/issue-51512.stderr b/tests/ui/nll/issue-51512.stderr new file mode 100644 index 000000000..072e96788 --- /dev/null +++ b/tests/ui/nll/issue-51512.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `range` + --> $DIR/issue-51512.rs:4:13 + | +LL | let range = 0..1; + | ----- move occurs because `range` has type `std::ops::Range`, which does not implement the `Copy` trait +LL | let r = range; + | ----- value moved here +LL | let x = range.start; + | ^^^^^^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let r = range.clone(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-51770.rs b/tests/ui/nll/issue-51770.rs new file mode 100644 index 000000000..3d6bc82f1 --- /dev/null +++ b/tests/ui/nll/issue-51770.rs @@ -0,0 +1,19 @@ +// check-pass + +#![crate_type = "lib"] + +// In an older version, when NLL was still a feature, the following previously did not compile + +use std::ops::Index; + +pub struct Test { + a: T, +} + +impl Index for Test { + type Output = T; + + fn index(&self, _index: usize) -> &Self::Output { + &self.a + } +} diff --git a/tests/ui/nll/issue-52057.rs b/tests/ui/nll/issue-52057.rs new file mode 100644 index 000000000..98f49fe8f --- /dev/null +++ b/tests/ui/nll/issue-52057.rs @@ -0,0 +1,22 @@ +// Regression test for #52057. There is an implied bound +// that `I: 'a` where `'a` is the lifetime of `self` in `parse_first`; +// but to observe that, one must normalize first. +// +// run-pass + +pub trait Parser { + type Input; + + fn parse_first(input: &mut Self::Input); +} + +impl<'a, I, P: ?Sized> Parser for &'a mut P +where + P: Parser, +{ + type Input = I; + + fn parse_first(_: &mut Self::Input) {} +} + +fn main() {} diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs new file mode 100644 index 000000000..7ea1c445d --- /dev/null +++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs @@ -0,0 +1,30 @@ +// rust-lang/rust#52059: Regardless of whether you are moving out of a +// Drop type or just introducing an inadvertent alias via a borrow of +// one of its fields, it is useful to be reminded of the significance +// of the fact that the type implements Drop. + +pub struct S<'a> { url: &'a mut String } + +impl<'a> Drop for S<'a> { fn drop(&mut self) { } } + +fn finish_1(s: S) -> &mut String { + s.url +} +//~^^ ERROR borrow may still be in use when destructor runs + +fn finish_2(s: S) -> &mut String { + let p = &mut *s.url; p +} +//~^^ ERROR borrow may still be in use when destructor runs + +fn finish_3(s: S) -> &mut String { + let p: &mut _ = s.url; p +} +//~^^ ERROR borrow may still be in use when destructor runs + +fn finish_4(s: S) -> &mut String { + let p = s.url; p +} +//~^^ ERROR cannot move out of type `S<'_>`, which implements the `Drop` trait + +fn main() {} diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr new file mode 100644 index 000000000..7f9cbc3c3 --- /dev/null +++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr @@ -0,0 +1,48 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:11:5 + | +LL | fn finish_1(s: S) -> &mut String { + | - has type `S<'1>` +LL | s.url + | ^^^^^ returning this value requires that `*s.url` is borrowed for `'1` +LL | } + | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait + +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:16:13 + | +LL | fn finish_2(s: S) -> &mut String { + | - has type `S<'1>` +LL | let p = &mut *s.url; p + | ^^^^^^^^^^^ - returning this value requires that `*s.url` is borrowed for `'1` +LL | } + | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait + +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:21:21 + | +LL | fn finish_3(s: S) -> &mut String { + | - has type `S<'1>` +LL | let p: &mut _ = s.url; p + | ^^^^^ - returning this value requires that `*s.url` is borrowed for `'1` +LL | } + | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait + +error[E0509]: cannot move out of type `S<'_>`, which implements the `Drop` trait + --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:26:13 + | +LL | let p = s.url; p + | ^^^^^ + | | + | cannot move out of here + | move occurs because `s.url` has type `&mut String`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let p = &s.url; p + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0509, E0713. +For more information about an error, try `rustc --explain E0509`. diff --git a/tests/ui/nll/issue-52078.rs b/tests/ui/nll/issue-52078.rs new file mode 100644 index 000000000..a2bcb91ac --- /dev/null +++ b/tests/ui/nll/issue-52078.rs @@ -0,0 +1,24 @@ +// Regression test for #52078: we were failing to infer a relationship +// between `'a` and `'b` below due to inference variables introduced +// during the normalization process. +// +// check-pass + +struct Drain<'a, T: 'a> { + _marker: ::std::marker::PhantomData<&'a T>, +} + +trait Join { + type Value; + fn get(value: &mut Self::Value); +} + +impl<'a, T> Join for Drain<'a, T> { + type Value = &'a mut Option; + + fn get<'b>(value: &'b mut Self::Value) { + } +} + +fn main() { +} diff --git a/tests/ui/nll/issue-52086.rs b/tests/ui/nll/issue-52086.rs new file mode 100644 index 000000000..0414428e4 --- /dev/null +++ b/tests/ui/nll/issue-52086.rs @@ -0,0 +1,14 @@ +use std::rc::Rc; +use std::sync::Arc; + +struct Bar { field: Vec } + +fn main() { + let x = Rc::new(Bar { field: vec![] }); + drop(x.field); +//~^ ERROR cannot move out of an `Rc` + + let y = Arc::new(Bar { field: vec![] }); + drop(y.field); +//~^ ERROR cannot move out of an `Arc` +} diff --git a/tests/ui/nll/issue-52086.stderr b/tests/ui/nll/issue-52086.stderr new file mode 100644 index 000000000..3b2dae9b7 --- /dev/null +++ b/tests/ui/nll/issue-52086.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of an `Rc` + --> $DIR/issue-52086.rs:8:10 + | +LL | drop(x.field); + | ^^^^^^^ move occurs because value has type `Vec`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of an `Arc` + --> $DIR/issue-52086.rs:12:10 + | +LL | drop(y.field); + | ^^^^^^^ move occurs because value has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/issue-52113.rs b/tests/ui/nll/issue-52113.rs new file mode 100644 index 000000000..ffaef272a --- /dev/null +++ b/tests/ui/nll/issue-52113.rs @@ -0,0 +1,35 @@ +trait Bazinga {} +impl Bazinga for F {} + +fn produce1<'a>(data: &'a u32) -> impl Bazinga + 'a { + let x = move || { + let _data: &'a u32 = data; + }; + x +} + +fn produce2<'a>(data: &'a mut Vec<&'a u32>, value: &'a u32) -> impl Bazinga + 'a { + let x = move || { + let value: &'a u32 = value; + data.push(value); + }; + x +} + +fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazinga + 'a { + let x = move || { + let value: &'a u32 = value; + data.push(value); + }; + x +} + +fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b { + let x = move || { + let value: &'a u32 = value; + data.push(value); //~ ERROR lifetime may not live long enough + }; + x +} + +fn main() {} diff --git a/tests/ui/nll/issue-52113.stderr b/tests/ui/nll/issue-52113.stderr new file mode 100644 index 000000000..84d4eb266 --- /dev/null +++ b/tests/ui/nll/issue-52113.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/issue-52113.rs:30:9 + | +LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | data.push(value); + | ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-52213.rs b/tests/ui/nll/issue-52213.rs new file mode 100644 index 000000000..a016924a8 --- /dev/null +++ b/tests/ui/nll/issue-52213.rs @@ -0,0 +1,15 @@ +fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { + match (&t,) { + ((u,),) => u, + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { + let x = { + let y = Box::new((42,)); + transmute_lifetime(&y) + }; + + println!("{}", x); +} diff --git a/tests/ui/nll/issue-52213.stderr b/tests/ui/nll/issue-52213.stderr new file mode 100644 index 000000000..da31bcd54 --- /dev/null +++ b/tests/ui/nll/issue-52213.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/issue-52213.rs:3:20 + | +LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | match (&t,) { +LL | ((u,),) => u, + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-52533-1.rs b/tests/ui/nll/issue-52533-1.rs new file mode 100644 index 000000000..d15daeddc --- /dev/null +++ b/tests/ui/nll/issue-52533-1.rs @@ -0,0 +1,11 @@ +#![allow(warnings)] + +struct Foo<'a, 'b, T: 'a + 'b> { x: &'a T, y: &'b T } + +fn gimme(_: impl for<'a, 'b, 'c> FnOnce(&'a Foo<'a, 'b, u32>, + &'a Foo<'a, 'c, u32>) -> &'a Foo<'a, 'b, u32>) { } + +fn main() { + gimme(|x, y| y) + //~^ ERROR lifetime may not live long enough +} diff --git a/tests/ui/nll/issue-52533-1.stderr b/tests/ui/nll/issue-52533-1.stderr new file mode 100644 index 000000000..20f19b259 --- /dev/null +++ b/tests/ui/nll/issue-52533-1.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-52533-1.rs:9:18 + | +LL | gimme(|x, y| y) + | - - ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | has type `&Foo<'_, '1, u32>` + | has type `&Foo<'_, '2, u32>` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-52534-1.rs b/tests/ui/nll/issue-52534-1.rs new file mode 100644 index 000000000..d9ea3ae42 --- /dev/null +++ b/tests/ui/nll/issue-52534-1.rs @@ -0,0 +1,48 @@ +struct Test; + +impl Test { + fn bar(&self, x: &u32) -> &u32 { + let x = 22; + &x +//~^ ERROR cannot return reference to local variable + } +} + +fn foo(x: &u32) -> &u32 { + let x = 22; + &x +//~^ ERROR cannot return reference to local variable +} + +fn baz(x: &u32) -> &&u32 { + let x = 22; + &&x +//~^ ERROR cannot return value referencing local variable +//~| ERROR cannot return reference to temporary value +} + +fn foobazbar<'a>(x: u32, y: &'a u32) -> &'a u32 { + let x = 22; + &x +//~^ ERROR cannot return reference to local variable +} + +fn foobar<'a>(x: &'a u32) -> &'a u32 { + let x = 22; + &x +//~^ ERROR cannot return reference to local variable +} + +fn foobaz<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 { + let x = 22; + &x +//~^ ERROR cannot return reference to local variable +} + +fn foobarbaz<'a, 'b>(x: &'a u32, y: &'b u32, z: &'a u32) -> &'a u32 { + let x = 22; + &x +//~^ ERROR cannot return reference to local variable +} + +fn main() { } diff --git a/tests/ui/nll/issue-52534-1.stderr b/tests/ui/nll/issue-52534-1.stderr new file mode 100644 index 000000000..743179f05 --- /dev/null +++ b/tests/ui/nll/issue-52534-1.stderr @@ -0,0 +1,57 @@ +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-52534-1.rs:6:9 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-52534-1.rs:13:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error[E0515]: cannot return value referencing local variable `x` + --> $DIR/issue-52534-1.rs:19:5 + | +LL | &&x + | ^-- + | || + | |`x` is borrowed here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/issue-52534-1.rs:19:5 + | +LL | &&x + | ^-- + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-52534-1.rs:26:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-52534-1.rs:32:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-52534-1.rs:38:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to local variable `x` + --> $DIR/issue-52534-1.rs:44:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-52534-2.rs b/tests/ui/nll/issue-52534-2.rs new file mode 100644 index 000000000..e416264ed --- /dev/null +++ b/tests/ui/nll/issue-52534-2.rs @@ -0,0 +1,14 @@ +fn foo(x: &u32) -> &u32 { + let y; + + { + let x = 32; + y = &x +//~^ ERROR does not live long enough + } + + println!("{}", y); + x +} + +fn main() { } diff --git a/tests/ui/nll/issue-52534-2.stderr b/tests/ui/nll/issue-52534-2.stderr new file mode 100644 index 000000000..ac385e056 --- /dev/null +++ b/tests/ui/nll/issue-52534-2.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-52534-2.rs:6:13 + | +LL | y = &x + | ^^ borrowed value does not live long enough +LL | +LL | } + | - `x` dropped here while still borrowed +LL | +LL | println!("{}", y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-52534.rs b/tests/ui/nll/issue-52534.rs new file mode 100644 index 000000000..559d4c859 --- /dev/null +++ b/tests/ui/nll/issue-52534.rs @@ -0,0 +1,19 @@ +fn foo(_: impl FnOnce(&u32) -> &u32) { +} + +fn baz(_: impl FnOnce(&u32, u32) -> &u32) { +} + +fn bar() { + let x = 22; + foo(|a| &x) +//~^ ERROR does not live long enough +} + +fn foobar() { + let y = 22; + baz(|first, second| &y) +//~^ ERROR does not live long enough +} + +fn main() { } diff --git a/tests/ui/nll/issue-52534.stderr b/tests/ui/nll/issue-52534.stderr new file mode 100644 index 000000000..b2b727fd4 --- /dev/null +++ b/tests/ui/nll/issue-52534.stderr @@ -0,0 +1,31 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-52534.rs:9:14 + | +LL | foo(|a| &x) + | - ^ `x` would have to be valid for `'0`... + | | + | has type `&'0 u32` +LL | +LL | } + | - ...but `x` will be dropped here, when the function `bar` returns + | + = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments + = note: to learn more, visit + +error[E0597]: `y` does not live long enough + --> $DIR/issue-52534.rs:15:26 + | +LL | baz(|first, second| &y) + | ----- ^ `y` would have to be valid for `'0`... + | | + | has type `&'0 u32` +LL | +LL | } + | - ...but `y` will be dropped here, when the function `foobar` returns + | + = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments + = note: to learn more, visit + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-52663-span-decl-captured-variable.rs b/tests/ui/nll/issue-52663-span-decl-captured-variable.rs new file mode 100644 index 000000000..cd1f457a1 --- /dev/null +++ b/tests/ui/nll/issue-52663-span-decl-captured-variable.rs @@ -0,0 +1,11 @@ +fn expect_fn(f: F) where F : Fn() { + f(); +} + +fn main() { + { + let x = (vec![22], vec![44]); + expect_fn(|| drop(x.0)); + //~^ ERROR cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure [E0507] + } +} diff --git a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr new file mode 100644 index 000000000..fb61b30f0 --- /dev/null +++ b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -0,0 +1,13 @@ +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure + --> $DIR/issue-52663-span-decl-captured-variable.rs:8:26 + | +LL | let x = (vec![22], vec![44]); + | - captured outer variable +LL | expect_fn(|| drop(x.0)); + | -- ^^^ move occurs because `x.0` has type `Vec`, which does not implement the `Copy` trait + | | + | captured by this `Fn` closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/issue-52663-trait-object.rs b/tests/ui/nll/issue-52663-trait-object.rs new file mode 100644 index 000000000..f6bbb2d14 --- /dev/null +++ b/tests/ui/nll/issue-52663-trait-object.rs @@ -0,0 +1,16 @@ +trait Foo { fn get(&self); } + +impl Foo for A { + fn get(&self) { } +} + + + +fn main() { + let _ = { + let tmp0 = 3; + let tmp1 = &tmp0; + Box::new(tmp1) as Box + }; + //~^^^ ERROR `tmp0` does not live long enough +} diff --git a/tests/ui/nll/issue-52663-trait-object.stderr b/tests/ui/nll/issue-52663-trait-object.stderr new file mode 100644 index 000000000..5cedea6e6 --- /dev/null +++ b/tests/ui/nll/issue-52663-trait-object.stderr @@ -0,0 +1,13 @@ +error[E0597]: `tmp0` does not live long enough + --> $DIR/issue-52663-trait-object.rs:12:20 + | +LL | let tmp1 = &tmp0; + | ^^^^^ borrowed value does not live long enough +LL | Box::new(tmp1) as Box + | ----------------------------------- borrow later captured here by trait object +LL | }; + | - `tmp0` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-52669.rs b/tests/ui/nll/issue-52669.rs new file mode 100644 index 000000000..e33528ac5 --- /dev/null +++ b/tests/ui/nll/issue-52669.rs @@ -0,0 +1,17 @@ +struct A { + b: B, +} + +#[derive(Clone)] +struct B; + +fn foo(_: A) {} + +fn bar(mut a: A) -> B { + a.b = B; + foo(a); + a.b.clone() +//~^ ERROR borrow of moved value +} + +fn main() {} diff --git a/tests/ui/nll/issue-52669.stderr b/tests/ui/nll/issue-52669.stderr new file mode 100644 index 000000000..807b95f7e --- /dev/null +++ b/tests/ui/nll/issue-52669.stderr @@ -0,0 +1,14 @@ +error[E0382]: borrow of moved value: `a.b` + --> $DIR/issue-52669.rs:13:5 + | +LL | fn bar(mut a: A) -> B { + | ----- move occurs because `a` has type `A`, which does not implement the `Copy` trait +LL | a.b = B; +LL | foo(a); + | - value moved here +LL | a.b.clone() + | ^^^^^^^^^^^ value borrowed here after move + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-52742.rs b/tests/ui/nll/issue-52742.rs new file mode 100644 index 000000000..d3e201b8a --- /dev/null +++ b/tests/ui/nll/issue-52742.rs @@ -0,0 +1,17 @@ +struct Foo<'a, 'b> { + x: &'a u32, + y: &'b u32, +} + +struct Bar<'b> { + z: &'b u32, +} + +impl Foo<'_, '_> { + fn take_bar(&mut self, b: Bar<'_>) { + self.y = b.z + //~^ ERROR + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-52742.stderr b/tests/ui/nll/issue-52742.stderr new file mode 100644 index 000000000..a79738296 --- /dev/null +++ b/tests/ui/nll/issue-52742.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/issue-52742.rs:12:9 + | +LL | fn take_bar(&mut self, b: Bar<'_>) { + | --------- - has type `Bar<'1>` + | | + | has type `&mut Foo<'_, '2>` +LL | self.y = b.z + | ^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-52992.rs b/tests/ui/nll/issue-52992.rs new file mode 100644 index 000000000..530d1a61b --- /dev/null +++ b/tests/ui/nll/issue-52992.rs @@ -0,0 +1,25 @@ +// Regression test for an NLL-related ICE (#52992) -- computing +// implied bounds was causing outlives relations that were not +// properly handled. +// +// check-pass + +fn main() {} + +fn fail<'a>() -> Struct<'a, Generic<()>> { + Struct(&Generic(())) +} + +struct Struct<'a, T>(&'a T) where + T: Trait + 'a, + T::AT: 'a; // only fails with this bound + +struct Generic(T); + +trait Trait { + type AT; +} + +impl Trait for Generic { + type AT = T; // only fails with a generic AT +} diff --git a/tests/ui/nll/issue-53040.rs b/tests/ui/nll/issue-53040.rs new file mode 100644 index 000000000..e4ee6e913 --- /dev/null +++ b/tests/ui/nll/issue-53040.rs @@ -0,0 +1,5 @@ +fn main() { + let mut v: Vec<()> = Vec::new(); + || &mut v; +//~^ ERROR captured variable cannot escape `FnMut` closure body +} diff --git a/tests/ui/nll/issue-53040.stderr b/tests/ui/nll/issue-53040.stderr new file mode 100644 index 000000000..87ffe9b1a --- /dev/null +++ b/tests/ui/nll/issue-53040.stderr @@ -0,0 +1,17 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/issue-53040.rs:3:8 + | +LL | let mut v: Vec<()> = Vec::new(); + | ----- variable defined here +LL | || &mut v; + | - ^^^^^- + | | | | + | | | variable captured here + | | returns a reference to a captured variable which escapes the closure body + | inferred to be a `FnMut` closure + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-53119.rs b/tests/ui/nll/issue-53119.rs new file mode 100644 index 000000000..03c9c071c --- /dev/null +++ b/tests/ui/nll/issue-53119.rs @@ -0,0 +1,23 @@ +// check-pass + +use std::ops::Deref; + +pub struct TypeFieldIterator<'a, T: 'a> { + _t: &'a T, +} + +pub struct Type { + _types: Vec<(Id, T)>, +} + +impl<'a, Id: 'a, T> Iterator for TypeFieldIterator<'a, T> +where T: Deref> { + type Item = &'a (Id, T); + + fn next(&mut self) -> Option<&'a (Id, T)> { + || self.next(); + None + } +} + +fn main() { } diff --git a/tests/ui/nll/issue-53123-raw-pointer-cast.rs b/tests/ui/nll/issue-53123-raw-pointer-cast.rs new file mode 100644 index 000000000..941c9eeb4 --- /dev/null +++ b/tests/ui/nll/issue-53123-raw-pointer-cast.rs @@ -0,0 +1,26 @@ +// run-pass + +#![allow(unused_variables)] + +pub trait TryTransform { + fn try_transform(self, f: F) + where + Self: Sized, + F: FnOnce(Self); +} + +impl<'a, T> TryTransform for &'a mut T { + fn try_transform(self, f: F) + where + // The bug was that `Self: Sized` caused the lifetime of `this` to "extend" for all + // of 'a instead of only lasting as long as the binding is used (for just that line). + Self: Sized, + F: FnOnce(Self), + { + let this: *mut T = self as *mut T; + f(self); + } +} + +fn main() { +} diff --git a/tests/ui/nll/issue-53570.rs b/tests/ui/nll/issue-53570.rs new file mode 100644 index 000000000..35860ba9c --- /dev/null +++ b/tests/ui/nll/issue-53570.rs @@ -0,0 +1,32 @@ +// Regression test for #53570. Here, we need to propagate that `T: 'a` +// but in some versions of NLL we were propagating a stronger +// requirement that `T: 'static`. This arose because we actually had +// to propagate both that `T: 'a` but also `T: 'b` where `'b` is the +// higher-ranked lifetime that appears in the type of the closure +// parameter `x` -- since `'b` cannot be expressed in the caller's +// space, that got promoted th `'static`. +// +// check-pass + +use std::cell::{RefCell, Ref}; + +trait AnyVec<'a> { +} + +trait GenericVec { + fn unwrap<'a, 'b>(vec: &'b dyn AnyVec<'a>) -> &'b [T] where T: 'a; +} + +struct Scratchpad<'a> { + buffers: RefCell>>, +} + +impl<'a> Scratchpad<'a> { + fn get>(&self) -> Ref<[T]> + where T: 'a + { + Ref::map(self.buffers.borrow(), |x| T::unwrap(x.as_ref())) + } +} + +fn main() { } diff --git a/tests/ui/nll/issue-53773.rs b/tests/ui/nll/issue-53773.rs new file mode 100644 index 000000000..ed971b6ce --- /dev/null +++ b/tests/ui/nll/issue-53773.rs @@ -0,0 +1,47 @@ +struct Archive; +struct ArchiveIterator<'a> { + x: &'a Archive, +} +struct ArchiveChild<'a> { + x: &'a Archive, +} + +struct A { + raw: &'static mut Archive, +} +struct Iter<'a> { + raw: &'a mut ArchiveIterator<'a>, +} +struct C<'a> { + raw: &'a mut ArchiveChild<'a>, +} + +impl A { + pub fn iter(&self) -> Iter<'_> { + panic!() + } +} +impl Drop for A { + fn drop(&mut self) {} +} +impl<'a> Drop for C<'a> { + fn drop(&mut self) {} +} + +impl<'a> Iterator for Iter<'a> { + type Item = C<'a>; + fn next(&mut self) -> Option> { + panic!() + } +} + +fn error(archive: &A) { + let mut members: Vec<&mut ArchiveChild<'_>> = vec![]; + for child in archive.iter() { + members.push(child.raw); + //~^ ERROR borrow may still be in use when destructor runs [E0713] + } + members.len(); +} + +fn main() {} diff --git a/tests/ui/nll/issue-53773.stderr b/tests/ui/nll/issue-53773.stderr new file mode 100644 index 000000000..90cba2a14 --- /dev/null +++ b/tests/ui/nll/issue-53773.stderr @@ -0,0 +1,14 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue-53773.rs:41:22 + | +LL | members.push(child.raw); + | -------------^^^^^^^^^- borrow later used here +LL | +LL | } + | - here, drop of `child` needs exclusive access to `*child.raw`, because the type `C<'_>` implements the `Drop` trait + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/issue-53807.rs b/tests/ui/nll/issue-53807.rs new file mode 100644 index 000000000..d494f7e15 --- /dev/null +++ b/tests/ui/nll/issue-53807.rs @@ -0,0 +1,8 @@ +pub fn main(){ + let maybe = Some(vec![true, true]); + loop { + if let Some(thing) = maybe { +//~^ ERROR use of moved value + } + } +} diff --git a/tests/ui/nll/issue-53807.stderr b/tests/ui/nll/issue-53807.stderr new file mode 100644 index 000000000..d8f58b591 --- /dev/null +++ b/tests/ui/nll/issue-53807.stderr @@ -0,0 +1,15 @@ +error[E0382]: use of moved value + --> $DIR/issue-53807.rs:4:21 + | +LL | if let Some(thing) = maybe { + | ^^^^^ value moved here, in previous iteration of loop + | + = note: move occurs because value has type `Vec`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let Some(ref thing) = maybe { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/issue-54189.rs b/tests/ui/nll/issue-54189.rs new file mode 100644 index 000000000..70aecc384 --- /dev/null +++ b/tests/ui/nll/issue-54189.rs @@ -0,0 +1,6 @@ +fn bug() -> impl for <'r> Fn() -> &'r () { || { &() } } +//~^ ERROR binding for associated type `Output` references lifetime `'r` + +fn main() { + let f = bug(); +} diff --git a/tests/ui/nll/issue-54189.stderr b/tests/ui/nll/issue-54189.stderr new file mode 100644 index 000000000..4787abd49 --- /dev/null +++ b/tests/ui/nll/issue-54189.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'r`, which does not appear in the trait input types + --> $DIR/issue-54189.rs:1:35 + | +LL | fn bug() -> impl for <'r> Fn() -> &'r () { || { &() } } + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/nll/issue-54382-use-span-of-tail-of-block.rs b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.rs new file mode 100644 index 000000000..312e6dce8 --- /dev/null +++ b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.rs @@ -0,0 +1,29 @@ +fn main() { + { + let mut _thing1 = D(Box::new("thing1")); + { + let _thing2 = D("thing2"); + side_effects(); + D("other").next(&_thing1) +//~^ ERROR does not live long enough + } + } + + ; +} + +#[derive(Debug)] +struct D(T); + +impl Drop for D { + fn drop(&mut self) { + println!("dropping {:?})", self); + } +} + +impl D { + fn next(&self, _other: U) -> D { D(_other) } + fn end(&self) { } +} + +fn side_effects() { } diff --git a/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr new file mode 100644 index 000000000..d8f43cbc9 --- /dev/null +++ b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr @@ -0,0 +1,23 @@ +error[E0597]: `_thing1` does not live long enough + --> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:29 + | +LL | D("other").next(&_thing1) + | ----------------^^^^^^^^- + | | | + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +... +LL | } + | - `_thing1` dropped here while still borrowed +LL | +LL | ; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | D("other").next(&_thing1); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs new file mode 100644 index 000000000..cae389e8c --- /dev/null +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -0,0 +1,31 @@ +// This is a reduction of a concrete test illustrating a case that was +// annoying to Rust developer niconii (see comment thread on #21114). +// +// With resolving issue #54556, pnkfelix hopes that the new diagnostic +// output produced by NLL helps to *explain* the semantic significance +// of temp drop order, and thus why inserting a semi-colon after the +// `if let` expression in `main` works. + +struct Mutex; +struct MutexGuard<'a>(&'a Mutex); + +impl Drop for Mutex { fn drop(&mut self) { println!("Mutex::drop"); } } +impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { println!("MutexGuard::drop"); } } + +impl Mutex { + fn lock(&self) -> Result { Ok(MutexGuard(self)) } +} + +fn main() { + let counter = Mutex; + + if let Ok(_) = counter.lock() { } //~ ERROR does not live long enough + + // With this code as written, the dynamic semantics here implies + // that `Mutex::drop` for `counter` runs *before* + // `MutexGuard::drop`, which would be unsound since `MutexGuard` + // still has a reference to `counter`. + // + // The goal of #54556 is to explain that within a compiler + // diagnostic. +} diff --git a/tests/ui/nll/issue-54556-niconii.stderr b/tests/ui/nll/issue-54556-niconii.stderr new file mode 100644 index 000000000..a8e1edc54 --- /dev/null +++ b/tests/ui/nll/issue-54556-niconii.stderr @@ -0,0 +1,23 @@ +error[E0597]: `counter` does not live long enough + --> $DIR/issue-54556-niconii.rs:22:20 + | +LL | if let Ok(_) = counter.lock() { } + | ^^^^^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +... +LL | } + | - + | | + | `counter` dropped here while still borrowed + | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Result, ()>` + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | if let Ok(_) = counter.lock() { }; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-stephaneyfx.rs b/tests/ui/nll/issue-54556-stephaneyfx.rs new file mode 100644 index 000000000..b758228e4 --- /dev/null +++ b/tests/ui/nll/issue-54556-stephaneyfx.rs @@ -0,0 +1,35 @@ +// This is a reduction of a concrete test illustrating a case that was +// annoying to Rust developer stephaneyfx (see issue #46413). +// +// With resolving issue #54556, pnkfelix hopes that the new diagnostic +// output produced by NLL helps to *explain* the semantic significance +// of temp drop order, and thus why storing the result in `x` and then +// returning `x` works. + +pub struct Statement; + +pub struct Rows<'stmt>(&'stmt Statement); + +impl<'stmt> Drop for Rows<'stmt> { + fn drop(&mut self) {} +} + +impl<'stmt> Iterator for Rows<'stmt> { + type Item = String; + + fn next(&mut self) -> Option { + None + } +} + +fn get_names() -> Option { + let stmt = Statement; + let rows = Rows(&stmt); //~ ERROR does not live long enough + rows.map(|row| row).next() + // let x = rows.map(|row| row).next(); + // x + // + // Removing the map works too as does removing the Drop impl. +} + +fn main() {} diff --git a/tests/ui/nll/issue-54556-stephaneyfx.stderr b/tests/ui/nll/issue-54556-stephaneyfx.stderr new file mode 100644 index 000000000..036a7a0ab --- /dev/null +++ b/tests/ui/nll/issue-54556-stephaneyfx.stderr @@ -0,0 +1,24 @@ +error[E0597]: `stmt` does not live long enough + --> $DIR/issue-54556-stephaneyfx.rs:27:21 + | +LL | let rows = Rows(&stmt); + | ^^^^^ borrowed value does not live long enough +LL | rows.map(|row| row).next() + | ------------------- a temporary with access to the borrow is created here ... +... +LL | } + | - + | | + | `stmt` dropped here while still borrowed + | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Map, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:19]>` + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = rows.map(|row| row).next(); x + | +++++++ +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.rs b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.rs new file mode 100644 index 000000000..2935caaf2 --- /dev/null +++ b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.rs @@ -0,0 +1,23 @@ +fn main() { + { + let mut _thing1 = D(Box::new("thing1")); + // D("other").next(&_thing1).end() + D(&_thing1).end() //~ ERROR does not live long enough + } + + ; +} + +#[derive(Debug)] +struct D(T); + +impl Drop for D { + fn drop(&mut self) { + println!("dropping {:?})", self); + } +} + +impl D { + fn next(&self, _other: U) -> D { D(_other) } + fn end(&self) { } +} diff --git a/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr new file mode 100644 index 000000000..92f5ffdf3 --- /dev/null +++ b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr @@ -0,0 +1,22 @@ +error[E0597]: `_thing1` does not live long enough + --> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:11 + | +LL | D(&_thing1).end() + | --^^^^^^^^- + | | | + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | } + | - `_thing1` dropped here while still borrowed +LL | +LL | ; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | D(&_thing1).end(); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-used-vs-unused-tails.rs b/tests/ui/nll/issue-54556-used-vs-unused-tails.rs new file mode 100644 index 000000000..a111acca6 --- /dev/null +++ b/tests/ui/nll/issue-54556-used-vs-unused-tails.rs @@ -0,0 +1,56 @@ +// This test case is exploring the space of how blocks with tail +// expressions and statements can be composed, trying to keep each +// case on one line so that we can compare them via a vertical scan +// with the human eye. + +// Each comment on the right side of the line is summarizing the +// expected suggestion from the diagnostic for issue #54556. + +fn main() { + { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` +//~^ ERROR does not live long enough + + { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;` +//~^ ERROR does not live long enough + + { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;` +//~^ ERROR does not live long enough + + let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` +//~^ ERROR does not live long enough + + let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;` +//~^ ERROR does not live long enough + + let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` +//~^ ERROR does not live long enough + let _x = { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error + + let mut _y; + _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` +//~^ ERROR does not live long enough + _y = { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error +} + +fn f_param_ref(_t1: D>) { D(&_t1).unit() } // no error + +fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;` +//~^ ERROR does not live long enough + +fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x` +//~^ ERROR does not live long enough + +#[derive(Debug)] +struct D(T); + +impl Drop for D { + fn drop(&mut self) { + println!("dropping {:?})", self); + } +} + +impl D { + fn next(&self, _other: U) -> D { D(_other) } + fn end(&self) -> String { format!("End({:?})", self.0) } + fn unit(&self) { } +} diff --git a/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr b/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr new file mode 100644 index 000000000..25226e296 --- /dev/null +++ b/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr @@ -0,0 +1,146 @@ +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:10:55 + | +LL | { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` + | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | { let mut _t1 = D(Box::new("t1")); D(&_t1).end(); } ; // suggest `;` + | + + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:13:55 + | +LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;` + | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end(); } } ; // suggest `;` + | + + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:16:55 + | +LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;` + | --^^^^- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end(); }; } // suggest `;` + | + + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:19:55 + | +LL | let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;` + | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end(); } ; // suggest `;` + | + + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:22:55 + | +LL | let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;` + | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit(); } ; // suggest `;` + | + + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:25:55 + | +LL | let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` + | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let _x = { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // `let x = ...; x` + | +++++++ +++ + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:30:55 + | +LL | _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x` + | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | | | + | | | `_t1` dropped here while still borrowed + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | _y = { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // `let x = ...; x` + | +++++++ +++ + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:37:55 + | +LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;` + | --^^^^- - + | | | | + | | | `_t1` dropped here while still borrowed + | | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit(); } // suggest `;` + | + + +error[E0597]: `_t1` does not live long enough + --> $DIR/issue-54556-used-vs-unused-tails.rs:40:55 + | +LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x` + | --^^^^- - + | | | | + | | | `_t1` dropped here while still borrowed + | | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + | | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } // `let x = ...; x` + | +++++++ +++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-54556-wrap-it-up.rs b/tests/ui/nll/issue-54556-wrap-it-up.rs new file mode 100644 index 000000000..11dbef0d8 --- /dev/null +++ b/tests/ui/nll/issue-54556-wrap-it-up.rs @@ -0,0 +1,28 @@ +// This is testing how the diagnostic from issue #54556 behaves when +// the destructor code is attached to a place held in a field of the +// temporary being dropped. +// +// Eventually it would be nice if the diagnostic would actually report +// that specific place and its type that implements the `Drop` trait. +// But for the short term, it is acceptable to just print out the +// whole type of the temporary. + +#![allow(warnings)] + +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +struct Foo<'p> { a: String, b: Wrap<'p> } + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + let s = String::from("str"); + let foo = Foo { a: s, b: wrap }; + x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] +} diff --git a/tests/ui/nll/issue-54556-wrap-it-up.stderr b/tests/ui/nll/issue-54556-wrap-it-up.stderr new file mode 100644 index 000000000..9f27fac15 --- /dev/null +++ b/tests/ui/nll/issue-54556-wrap-it-up.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/issue-54556-wrap-it-up.rs:27:5 + | +LL | let wrap = Wrap { p: &mut x }; + | ------ borrow of `x` occurs here +... +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | } + | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.rs b/tests/ui/nll/issue-54779-anon-static-lifetime.rs new file mode 100644 index 000000000..260b6b109 --- /dev/null +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.rs @@ -0,0 +1,49 @@ +// Regression test for #54779, checks if the diagnostics are confusing. + +trait DebugWith { + fn debug_with<'me>(&'me self, cx: &'me Cx) -> DebugCxPair<'me, Self, Cx> { + DebugCxPair { value: self, cx } + } + + fn fmt_with(&self, cx: &Cx, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result; +} + +struct DebugCxPair<'me, Value: ?Sized, Cx: ?Sized> +where + Value: DebugWith, +{ + value: &'me Value, + cx: &'me Cx, +} + +trait DebugContext {} + +struct Foo { + bar: Bar, +} + +impl DebugWith for Foo { + fn fmt_with( + &self, + cx: &dyn DebugContext, + fmt: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + let Foo { bar } = self; + bar.debug_with(cx); //~ ERROR: lifetime may not live long enough + Ok(()) + } +} + +struct Bar {} + +impl DebugWith for Bar { + fn fmt_with( + &self, + cx: &dyn DebugContext, + fmt: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + Ok(()) + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr new file mode 100644 index 000000000..64ad7a21a --- /dev/null +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-54779-anon-static-lifetime.rs:32:24 + | +LL | cx: &dyn DebugContext, + | - let's call the lifetime of this reference `'1` +... +LL | bar.debug_with(cx); + | ^^ cast requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-54943-3.rs b/tests/ui/nll/issue-54943-3.rs new file mode 100644 index 000000000..077eb1563 --- /dev/null +++ b/tests/ui/nll/issue-54943-3.rs @@ -0,0 +1,19 @@ +// check-pass +// FIXME(#54943) This test targets the scenario where proving the WF requirements requires +// knowing the value of the `_` type present in the user type annotation - unfortunately, figuring +// out the value of that `_` requires type-checking the surrounding code, but that code is dead, +// so our NLL region checker doesn't have access to it. This test should actually fail to compile. + +#![allow(warnings)] + +use std::fmt::Debug; + +fn foo(_: T) { } + +fn bar<'a>() { + return; + + let _x = foo::>(Vec::<&'a u32>::new()); +} + +fn main() {} diff --git a/tests/ui/nll/issue-54943.rs b/tests/ui/nll/issue-54943.rs new file mode 100644 index 000000000..85722300b --- /dev/null +++ b/tests/ui/nll/issue-54943.rs @@ -0,0 +1,10 @@ +fn foo() { } + +fn boo<'a>() { + return; + + let x = foo::<&'a u32>(); + //~^ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/issue-54943.stderr b/tests/ui/nll/issue-54943.stderr new file mode 100644 index 000000000..59be0f983 --- /dev/null +++ b/tests/ui/nll/issue-54943.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-54943.rs:6:13 + | +LL | fn boo<'a>() { + | -- lifetime `'a` defined here +... +LL | let x = foo::<&'a u32>(); + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-55288.rs b/tests/ui/nll/issue-55288.rs new file mode 100644 index 000000000..aab2dc267 --- /dev/null +++ b/tests/ui/nll/issue-55288.rs @@ -0,0 +1,9 @@ +// check-pass + +struct Slice(&'static [&'static [u8]]); + +static MAP: Slice = Slice(&[ + b"CloseEvent" as &'static [u8], +]); + +fn main() {} diff --git a/tests/ui/nll/issue-55344.rs b/tests/ui/nll/issue-55344.rs new file mode 100644 index 000000000..20f18dc46 --- /dev/null +++ b/tests/ui/nll/issue-55344.rs @@ -0,0 +1,14 @@ +// check-pass + +#![deny(unused_mut)] + +pub fn foo() { + return; + + let mut v = 0; + assert_eq!(v, 0); + v = 1; + assert_eq!(v, 1); +} + +fn main() {} diff --git a/tests/ui/nll/issue-55394.rs b/tests/ui/nll/issue-55394.rs new file mode 100644 index 000000000..f813d1c91 --- /dev/null +++ b/tests/ui/nll/issue-55394.rs @@ -0,0 +1,13 @@ +struct Bar; + +struct Foo<'s> { + bar: &'s mut Bar, +} + +impl Foo<'_> { + fn new(bar: &mut Bar) -> Self { + Foo { bar } //~ERROR + } +} + +fn main() { } diff --git a/tests/ui/nll/issue-55394.stderr b/tests/ui/nll/issue-55394.stderr new file mode 100644 index 000000000..24b8c84b4 --- /dev/null +++ b/tests/ui/nll/issue-55394.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/issue-55394.rs:9:9 + | +LL | fn new(bar: &mut Bar) -> Self { + | - ---- return type is Foo<'2> + | | + | let's call the lifetime of this reference `'1` +LL | Foo { bar } + | ^^^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-55401.rs b/tests/ui/nll/issue-55401.rs new file mode 100644 index 000000000..fc45824e9 --- /dev/null +++ b/tests/ui/nll/issue-55401.rs @@ -0,0 +1,6 @@ +fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + let (ref y, _z): (&'a u32, u32) = (&22, 44); + *y //~ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/issue-55401.stderr b/tests/ui/nll/issue-55401.stderr new file mode 100644 index 000000000..4f797f26a --- /dev/null +++ b/tests/ui/nll/issue-55401.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-55401.rs:3:5 + | +LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let (ref y, _z): (&'a u32, u32) = (&22, 44); +LL | *y + | ^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-55511.rs b/tests/ui/nll/issue-55511.rs new file mode 100644 index 000000000..7dfa9c7bc --- /dev/null +++ b/tests/ui/nll/issue-55511.rs @@ -0,0 +1,19 @@ +#![warn(indirect_structural_match)] +use std::cell::Cell; +trait Foo<'a> { + const C: Option>; +} + +impl<'a, T> Foo<'a> for T { + const C: Option> = None; +} + +fn main() { + let a = 22; + let b = Some(Cell::new(&a)); + //~^ ERROR `a` does not live long enough [E0597] + match b { + <() as Foo<'static>>::C => { } + _ => { } + } +} diff --git a/tests/ui/nll/issue-55511.stderr b/tests/ui/nll/issue-55511.stderr new file mode 100644 index 000000000..bf3e58e8c --- /dev/null +++ b/tests/ui/nll/issue-55511.stderr @@ -0,0 +1,15 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-55511.rs:13:28 + | +LL | let b = Some(Cell::new(&a)); + | ^^ borrowed value does not live long enough +... +LL | <() as Foo<'static>>::C => { } + | ----------------------- type annotation requires that `a` is borrowed for `'static` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-55651.rs b/tests/ui/nll/issue-55651.rs new file mode 100644 index 000000000..75ba48271 --- /dev/null +++ b/tests/ui/nll/issue-55651.rs @@ -0,0 +1,28 @@ +// check-pass + +use std::mem::ManuallyDrop; + +struct A; +struct B; + +union U { + a: ManuallyDrop, + b: ManuallyDrop, +} + +fn main() { + unsafe { + { + let mut u = U { a: ManuallyDrop::new(A) }; + let a = u.a; + u.a = ManuallyDrop::new(A); + let a = u.a; // OK + } + { + let mut u = U { a: ManuallyDrop::new(A) }; + let a = u.a; + u.b = ManuallyDrop::new(B); + let a = u.a; // OK + } + } +} diff --git a/tests/ui/nll/issue-55825-const-fn.rs b/tests/ui/nll/issue-55825-const-fn.rs new file mode 100644 index 000000000..8aaa19813 --- /dev/null +++ b/tests/ui/nll/issue-55825-const-fn.rs @@ -0,0 +1,8 @@ +// Regression test for issue #55825 +// Tests that we don't emit a spurious warning in NLL mode + +// check-pass + +const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } + +fn main() { } diff --git a/tests/ui/nll/issue-55850.rs b/tests/ui/nll/issue-55850.rs new file mode 100644 index 000000000..e6279bd02 --- /dev/null +++ b/tests/ui/nll/issue-55850.rs @@ -0,0 +1,35 @@ +#![allow(unused_mut)] +#![feature(generators, generator_trait)] + +use std::marker::Unpin; +use std::ops::Generator; +use std::ops::GeneratorState::Yielded; +use std::pin::Pin; + +pub struct GenIter(G); + +impl Iterator for GenIter +where + G: Generator + Unpin, +{ + type Item = G::Yield; + + fn next(&mut self) -> Option { + match Pin::new(&mut self.0).resume(()) { + Yielded(y) => Some(y), + _ => None + } + } +} + +fn bug<'a>() -> impl Iterator { + GenIter(move || { + let mut s = String::new(); + yield &s[..] //~ ERROR cannot yield value referencing local variable `s` [E0515] + //~| ERROR borrow may still be in use when generator yields + }) +} + +fn main() { + bug(); +} diff --git a/tests/ui/nll/issue-55850.stderr b/tests/ui/nll/issue-55850.stderr new file mode 100644 index 000000000..86a8cdc42 --- /dev/null +++ b/tests/ui/nll/issue-55850.stderr @@ -0,0 +1,19 @@ +error[E0515]: cannot yield value referencing local variable `s` + --> $DIR/issue-55850.rs:28:9 + | +LL | yield &s[..] + | ^^^^^^^-^^^^ + | | | + | | `s` is borrowed here + | yields a value referencing data owned by the current function + +error[E0626]: borrow may still be in use when generator yields + --> $DIR/issue-55850.rs:28:16 + | +LL | yield &s[..] + | -------^---- possible yield occurs here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0515, E0626. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/issue-57100.rs b/tests/ui/nll/issue-57100.rs new file mode 100644 index 000000000..f15929334 --- /dev/null +++ b/tests/ui/nll/issue-57100.rs @@ -0,0 +1,67 @@ +#![allow(unused)] + + +// This tests the error messages for borrows of union fields when the unions are embedded in other +// structs or unions. + +#[derive(Clone, Copy, Default)] +struct Leaf { + l1_u8: u8, + l2_u8: u8, +} + +#[derive(Clone, Copy)] +union First { + f1_leaf: Leaf, + f2_leaf: Leaf, + f3_union: Second, +} + +#[derive(Clone, Copy)] +union Second { + s1_leaf: Leaf, + s2_leaf: Leaf, +} + +struct Root { + r1_u8: u8, + r2_union: First, +} + +// Borrow a different field of the nested union. +fn nested_union() { + unsafe { + let mut r = Root { + r1_u8: 3, + r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } } + }; + + let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8; + // ^^^^^^^ + *mref = 22; + let nref = &r.r2_union.f3_union.s2_leaf.l1_u8; + // ^^^^^^^ + //~^^ ERROR cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`) [E0502] + println!("{} {}", mref, nref) + } +} + +// Borrow a different field of the first union. +fn first_union() { + unsafe { + let mut r = Root { + r1_u8: 3, + r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } } + }; + + let mref = &mut r.r2_union.f2_leaf.l1_u8; + // ^^^^^^^ + *mref = 22; + let nref = &r.r2_union.f1_leaf.l1_u8; + // ^^^^^^^ + //~^^ ERROR cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`) [E0502] + println!("{} {}", mref, nref) + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-57100.stderr b/tests/ui/nll/issue-57100.stderr new file mode 100644 index 000000000..523c3e8d0 --- /dev/null +++ b/tests/ui/nll/issue-57100.stderr @@ -0,0 +1,31 @@ +error[E0502]: cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`) + --> $DIR/issue-57100.rs:42:20 + | +LL | let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8; + | -------------------------------------- mutable borrow occurs here (via `r.r2_union.f3_union.s1_leaf.l1_u8`) +... +LL | let nref = &r.r2_union.f3_union.s2_leaf.l1_u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f3_union.s2_leaf.l1_u8` -- which overlaps with `r.r2_union.f3_union.s1_leaf.l1_u8` -- occurs here +... +LL | println!("{} {}", mref, nref) + | ---- mutable borrow later used here + | + = note: `r.r2_union.f3_union.s2_leaf.l1_u8` is a field of the union `Second`, so it overlaps the field `r.r2_union.f3_union.s1_leaf.l1_u8` + +error[E0502]: cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`) + --> $DIR/issue-57100.rs:60:20 + | +LL | let mref = &mut r.r2_union.f2_leaf.l1_u8; + | ----------------------------- mutable borrow occurs here (via `r.r2_union.f2_leaf.l1_u8`) +... +LL | let nref = &r.r2_union.f1_leaf.l1_u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f1_leaf.l1_u8` -- which overlaps with `r.r2_union.f2_leaf.l1_u8` -- occurs here +... +LL | println!("{} {}", mref, nref) + | ---- mutable borrow later used here + | + = note: `r.r2_union.f1_leaf.l1_u8` is a field of the union `First`, so it overlaps the field `r.r2_union.f2_leaf.l1_u8` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-57265-return-type-wf-check.rs b/tests/ui/nll/issue-57265-return-type-wf-check.rs new file mode 100644 index 000000000..8fb8351ce --- /dev/null +++ b/tests/ui/nll/issue-57265-return-type-wf-check.rs @@ -0,0 +1,24 @@ +use std::any::Any; + +#[derive(Debug, Clone)] +struct S(T); + +// S<&'a T> is in the return type, so we get an implied bound +// &'a T: 'static +fn foo<'a, T>(x: &'a T) -> (S<&'a T>, Box) { + let y = S(x); + + let z = Box::new(y.clone()) as Box; + (y, z) +} + +fn main() { + let x = 5; + + // Check that we require that the argument is of type `&'static String`, + // so that the return type is well-formed. + let (_, z) = foo(&"hello".to_string()); + //~^ ERROR temporary value dropped while borrowed + + println!("{:?}", z.downcast_ref::>()); +} diff --git a/tests/ui/nll/issue-57265-return-type-wf-check.stderr b/tests/ui/nll/issue-57265-return-type-wf-check.stderr new file mode 100644 index 000000000..bb45575fa --- /dev/null +++ b/tests/ui/nll/issue-57265-return-type-wf-check.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-57265-return-type-wf-check.rs:20:23 + | +LL | let (_, z) = foo(&"hello".to_string()); + | -----^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/nll/issue-57280-1-flipped.rs b/tests/ui/nll/issue-57280-1-flipped.rs new file mode 100644 index 000000000..ad4b8dcfd --- /dev/null +++ b/tests/ui/nll/issue-57280-1-flipped.rs @@ -0,0 +1,23 @@ +// This test should compile, as the lifetimes +// in matches don't really matter. +// +// We currently use contravariance when checking the +// type of match arms. + +trait Foo<'a> { + const C: &'a u32; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo<'a>(x: &'static u32) { + match x { + <() as Foo<'a>>::C => { } + //~^ ERROR lifetime may not live long enough + &_ => { } + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-57280-1-flipped.stderr b/tests/ui/nll/issue-57280-1-flipped.stderr new file mode 100644 index 000000000..7a2135a2a --- /dev/null +++ b/tests/ui/nll/issue-57280-1-flipped.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-57280-1-flipped.rs:17:9 + | +LL | fn foo<'a>(x: &'static u32) { + | -- lifetime `'a` defined here +LL | match x { +LL | <() as Foo<'a>>::C => { } + | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-57280-1.rs b/tests/ui/nll/issue-57280-1.rs new file mode 100644 index 000000000..b8979624e --- /dev/null +++ b/tests/ui/nll/issue-57280-1.rs @@ -0,0 +1,19 @@ +// check-pass + +trait Foo<'a> { + const C: &'a u32; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo() { + let a = 22; + match &a { + <() as Foo<'static>>::C => { } + &_ => { } + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-57280.rs b/tests/ui/nll/issue-57280.rs new file mode 100644 index 000000000..b9d336ec3 --- /dev/null +++ b/tests/ui/nll/issue-57280.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Foo { + const BLAH: &'static str; +} + +struct Placeholder; + +impl Foo for Placeholder { + const BLAH: &'static str = "hi"; +} + +fn foo(x: &str) { + match x { + ::BLAH => { } + _ => { } + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs new file mode 100644 index 000000000..eba859cde --- /dev/null +++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs @@ -0,0 +1,38 @@ +// Regression test for issue #57642 +// Tests that we reject a bad higher-ranked subtype + +trait X { + type G; + fn make_g() -> Self::G; +} + +impl<'a> X for fn(&'a ()) { + type G = &'a (); + + fn make_g() -> Self::G { + &() + } +} + +trait Y { + type F; + fn make_f() -> Self::F; +} + +impl Y for fn(T) { + type F = fn(T); + + fn make_f() -> Self::F { + |_| {} + } +} + +fn higher_ranked_region_has_lost_its_binder() { + let x = ::make_g(); //~ ERROR the function +} + +fn magical() { + let x = ::make_f(); //~ ERROR no function +} + +fn main() {} diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr new file mode 100644 index 000000000..6e96f40c0 --- /dev/null +++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr @@ -0,0 +1,31 @@ +error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied + --> $DIR/issue-57642-higher-ranked-subtype.rs:31:25 + | +LL | let x = ::make_g(); + | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `for<'a> fn(&'a ()): X` + = help: items from traits can only be used if the trait is implemented and in scope +note: `X` defines an item `make_g`, perhaps you need to implement it + --> $DIR/issue-57642-higher-ranked-subtype.rs:4:1 + | +LL | trait X { + | ^^^^^^^ + +error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope + --> $DIR/issue-57642-higher-ranked-subtype.rs:35:25 + | +LL | let x = ::make_f(); + | ^^^^^^ function or associated item not found in `for<'a> fn(&'a ())` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Y` defines an item `make_f`, perhaps you need to implement it + --> $DIR/issue-57642-higher-ranked-subtype.rs:17:1 + | +LL | trait Y { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/nll/issue-57843.rs b/tests/ui/nll/issue-57843.rs new file mode 100644 index 000000000..11629690e --- /dev/null +++ b/tests/ui/nll/issue-57843.rs @@ -0,0 +1,26 @@ +// Regression test for an ICE that occurred with the universes code: +// +// The signature of the closure `|_|` was being inferred to +// `exists<'r> fn(&'r u8)`. This should result in a type error since +// the signature `for<'r> fn(&'r u8)` is required. However, due to a +// bug in the type variable generalization code, the placeholder for +// `'r` was leaking out into the writeback phase, causing an ICE. + +trait ClonableFn { + fn clone(&self) -> Box; +} + +impl ClonableFn for F +where + F: Fn(T) + Clone, +{ + fn clone(&self) -> Box { + Box::new(self.clone()) + } +} + +struct Foo(Box ClonableFn<&'a bool>>); + +fn main() { + Foo(Box::new(|_| ())); //~ ERROR implementation of `FnOnce` is not general enough +} diff --git a/tests/ui/nll/issue-57843.stderr b/tests/ui/nll/issue-57843.stderr new file mode 100644 index 000000000..2ab49ec61 --- /dev/null +++ b/tests/ui/nll/issue-57843.stderr @@ -0,0 +1,11 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-57843.rs:25:9 + | +LL | Foo(Box::new(|_| ())); + | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-57960.rs b/tests/ui/nll/issue-57960.rs new file mode 100644 index 000000000..32e45184a --- /dev/null +++ b/tests/ui/nll/issue-57960.rs @@ -0,0 +1,38 @@ +// run-pass + +#![allow(dead_code)] + +trait Range { + const FIRST: u8; + const LAST: u8; +} + +struct OneDigit; +impl Range for OneDigit { + const FIRST: u8 = 0; + const LAST: u8 = 9; +} + +struct TwoDigits; +impl Range for TwoDigits { + const FIRST: u8 = 10; + const LAST: u8 = 99; +} + +struct ThreeDigits; +impl Range for ThreeDigits { + const FIRST: u8 = 100; + const LAST: u8 = 255; +} + +fn digits(x: u8) -> u32 { + match x { + OneDigit::FIRST..=OneDigit::LAST => 1, + TwoDigits::FIRST..=TwoDigits::LAST => 2, + ThreeDigits::FIRST..=ThreeDigits::LAST => 3, + } +} + +fn main() { + assert_eq!(digits(100), 3); +} diff --git a/tests/ui/nll/issue-57989.rs b/tests/ui/nll/issue-57989.rs new file mode 100644 index 000000000..8f3dec454 --- /dev/null +++ b/tests/ui/nll/issue-57989.rs @@ -0,0 +1,10 @@ +// Test for ICE from issue 57989 + +fn f(x: &i32) { + let g = &x; + *x = 0; //~ ERROR cannot assign to `*x`, which is behind a `&` reference + //~| ERROR cannot assign to `*x` because it is borrowed + g; +} + +fn main() {} diff --git a/tests/ui/nll/issue-57989.stderr b/tests/ui/nll/issue-57989.stderr new file mode 100644 index 000000000..31f40d825 --- /dev/null +++ b/tests/ui/nll/issue-57989.stderr @@ -0,0 +1,26 @@ +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/issue-57989.rs:5:5 + | +LL | *x = 0; + | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn f(x: &mut i32) { + | ~~~~~~~~ + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/issue-57989.rs:5:5 + | +LL | let g = &x; + | -- borrow of `*x` occurs here +LL | *x = 0; + | ^^^^^^ assignment to borrowed `*x` occurs here +LL | +LL | g; + | - borrow later used here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0506, E0594. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/issue-58053.rs b/tests/ui/nll/issue-58053.rs new file mode 100644 index 000000000..d5a2fa1a3 --- /dev/null +++ b/tests/ui/nll/issue-58053.rs @@ -0,0 +1,11 @@ +fn main() { + let i = &3; + + let f = |x: &i32| -> &i32 { x }; + //~^ ERROR lifetime may not live long enough + let j = f(i); + + let g = |x: &i32| { x }; + //~^ ERROR lifetime may not live long enough + let k = g(i); +} diff --git a/tests/ui/nll/issue-58053.stderr b/tests/ui/nll/issue-58053.stderr new file mode 100644 index 000000000..bf7416e1a --- /dev/null +++ b/tests/ui/nll/issue-58053.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/issue-58053.rs:4:33 + | +LL | let f = |x: &i32| -> &i32 { x }; + | - - ^ returning this value requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'2` + | let's call the lifetime of this reference `'1` + +error: lifetime may not live long enough + --> $DIR/issue-58053.rs:8:25 + | +LL | let g = |x: &i32| { x }; + | - - ^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure is &'2 i32 + | let's call the lifetime of this reference `'1` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/issue-58299.rs b/tests/ui/nll/issue-58299.rs new file mode 100644 index 000000000..0587fe8b4 --- /dev/null +++ b/tests/ui/nll/issue-58299.rs @@ -0,0 +1,27 @@ +struct A<'a>(&'a ()); + +trait Y { + const X: i32; +} + +impl Y for A<'static> { + const X: i32 = 10; +} + +fn foo<'a>(x: i32) { + match x { + // This uses as Y>::X, but `A<'a>` does not implement `Y`. + A::<'a>::X..=A::<'static>::X => (), //~ ERROR lifetime may not live long enough + _ => (), + } +} + +fn bar<'a>(x: i32) { + match x { + // This uses as Y>::X, but `A<'a>` does not implement `Y`. + A::<'static>::X..=A::<'a>::X => (), //~ ERROR lifetime may not live long enough + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-58299.stderr b/tests/ui/nll/issue-58299.stderr new file mode 100644 index 000000000..509ba67bd --- /dev/null +++ b/tests/ui/nll/issue-58299.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/issue-58299.rs:14:9 + | +LL | fn foo<'a>(x: i32) { + | -- lifetime `'a` defined here +... +LL | A::<'a>::X..=A::<'static>::X => (), + | ^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-58299.rs:22:27 + | +LL | fn bar<'a>(x: i32) { + | -- lifetime `'a` defined here +... +LL | A::<'static>::X..=A::<'a>::X => (), + | ^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/issue-61311-normalize.rs b/tests/ui/nll/issue-61311-normalize.rs new file mode 100644 index 000000000..77d67b07a --- /dev/null +++ b/tests/ui/nll/issue-61311-normalize.rs @@ -0,0 +1,34 @@ +// Regression test for #61311 +// We would ICE after failing to normalize `Self::Proj` in the `impl` below. + +// check-pass + +pub struct Unit; +trait Obj {} + +trait Bound {} +impl Bound for Unit {} + +pub trait HasProj { + type Proj; +} + +impl HasProj for T { + type Proj = Unit; +} + +trait HasProjFn { + type Proj; + fn the_fn(_: Self::Proj); +} + +impl HasProjFn for Unit +where + Box: HasProj, + as HasProj>::Proj: Bound, +{ + type Proj = Unit; + fn the_fn(_: Self::Proj) {} +} + +fn main() {} diff --git a/tests/ui/nll/issue-61320-normalize.rs b/tests/ui/nll/issue-61320-normalize.rs new file mode 100644 index 000000000..095bef03f --- /dev/null +++ b/tests/ui/nll/issue-61320-normalize.rs @@ -0,0 +1,160 @@ +// Regression test for #61320 +// This is the same issue as #61311, just a larger test case. + +// check-pass + +pub struct AndThen +where + A: Future, + B: IntoFuture, +{ + state: (A, B::Future, F), +} + +pub struct FutureResult { + inner: Option>, +} + +impl Future for FutureResult { + type Item = T; + type Error = E; + + fn poll(&mut self) -> Poll { + unimplemented!() + } +} + +pub type Poll = Result; + +impl Future for AndThen +where + A: Future, + B: IntoFuture, + F: FnOnce(A::Item) -> B, +{ + type Item = B::Item; + type Error = B::Error; + + fn poll(&mut self) -> Poll { + unimplemented!() + } +} + +pub trait Future { + type Item; + + type Error; + + fn poll(&mut self) -> Poll; + + fn and_then(self, f: F) -> AndThen + where + F: FnOnce(Self::Item) -> B, + B: IntoFuture, + Self: Sized, + { + unimplemented!() + } +} + +pub trait IntoFuture { + /// The future that this type can be converted into. + type Future: Future; + + /// The item that the future may resolve with. + type Item; + /// The error that the future may resolve with. + type Error; + + /// Consumes this object and produces a future. + fn into_future(self) -> Self::Future; +} + +impl IntoFuture for F { + type Future = F; + type Item = F::Item; + type Error = F::Error; + + fn into_future(self) -> F { + self + } +} + +impl Future for ::std::boxed::Box { + type Item = F::Item; + type Error = F::Error; + + fn poll(&mut self) -> Poll { + (**self).poll() + } +} + +impl IntoFuture for Result { + type Future = FutureResult; + type Item = T; + type Error = E; + + fn into_future(self) -> FutureResult { + unimplemented!() + } +} + +struct Request(T); + +trait RequestContext {} +impl RequestContext for T {} +struct NoContext; +impl AsRef for NoContext { + fn as_ref(&self) -> &Self { + &NoContext + } +} + +type BoxedError = Box; +type DefaultFuture = Box + Send>; + +trait Guard: Sized { + type Result: IntoFuture; + fn from_request(request: &Request<()>) -> Self::Result; +} + +trait FromRequest: Sized { + type Context; + type Future: Future + Send; + fn from_request(request: Request<()>) -> Self::Future; +} + +struct MyGuard; +impl Guard for MyGuard { + type Result = Result; + fn from_request(_request: &Request<()>) -> Self::Result { + Ok(MyGuard) + } +} + +struct Generic { + _inner: I, +} + +impl FromRequest for Generic +where + MyGuard: Guard, + ::Result: IntoFuture, + <::Result as IntoFuture>::Future: Send, + I: FromRequest, +{ + type Future = DefaultFuture; + type Context = NoContext; + fn from_request(headers: Request<()>) -> DefaultFuture { + let _future = ::from_request(&headers) + .into_future() + .and_then(move |_| { + ::from_request(headers) + .into_future() + .and_then(move |fld_inner| Ok(Generic { _inner: fld_inner }).into_future()) + }); + panic!(); + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-61424.fixed b/tests/ui/nll/issue-61424.fixed new file mode 100644 index 000000000..63e00c172 --- /dev/null +++ b/tests/ui/nll/issue-61424.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#![deny(unused_mut)] + +fn main() { + let x; //~ ERROR: variable does not need to be mutable + x = String::new(); + dbg!(x); +} diff --git a/tests/ui/nll/issue-61424.rs b/tests/ui/nll/issue-61424.rs new file mode 100644 index 000000000..3b64996c2 --- /dev/null +++ b/tests/ui/nll/issue-61424.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#![deny(unused_mut)] + +fn main() { + let mut x; //~ ERROR: variable does not need to be mutable + x = String::new(); + dbg!(x); +} diff --git a/tests/ui/nll/issue-61424.stderr b/tests/ui/nll/issue-61424.stderr new file mode 100644 index 000000000..6de6b7f3a --- /dev/null +++ b/tests/ui/nll/issue-61424.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/issue-61424.rs:6:9 + | +LL | let mut x; + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/issue-61424.rs:3:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-62007-assign-const-index.rs b/tests/ui/nll/issue-62007-assign-const-index.rs new file mode 100644 index 000000000..3ea5d3a7a --- /dev/null +++ b/tests/ui/nll/issue-62007-assign-const-index.rs @@ -0,0 +1,32 @@ +// Issue #62007: assigning over a const-index projection of an array +// (in this case, `list[I] = n;`) should in theory be able to kill all borrows +// of `list[0]`, so that `list[0]` could be borrowed on the next +// iteration through the loop. +// +// Currently the compiler does not allow this. We may want to consider +// loosening that restriction in the future. (However, doing so would +// at *least* require T-lang team approval, and probably an RFC; e.g. +// such loosening might make complicate the user's mental mode; it +// also would make code more brittle in the face of refactorings that +// replace constants with variables. + +#![allow(dead_code)] + +struct List { + value: T, + next: Option>>, +} + +fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list[0].value); //~ ERROR cannot borrow `list[_].value` as mutable + if let Some(n) = list[0].next.as_mut() { //~ ERROR cannot borrow `list[_].next` as mutable + list[0] = n; + } else { + return result; + } + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-62007-assign-const-index.stderr b/tests/ui/nll/issue-62007-assign-const-index.stderr new file mode 100644 index 000000000..12e28aa3f --- /dev/null +++ b/tests/ui/nll/issue-62007-assign-const-index.stderr @@ -0,0 +1,27 @@ +error[E0499]: cannot borrow `list[_].value` as mutable more than once at a time + --> $DIR/issue-62007-assign-const-index.rs:23:21 + | +LL | fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { + | - let's call the lifetime of this reference `'1` +... +LL | result.push(&mut list[0].value); + | ^^^^^^^^^^^^^^^^^^ `list[_].value` was mutably borrowed here in the previous iteration of the loop +... +LL | return result; + | ------ returning this value requires that `list[_].value` is borrowed for `'1` + +error[E0499]: cannot borrow `list[_].next` as mutable more than once at a time + --> $DIR/issue-62007-assign-const-index.rs:24:26 + | +LL | fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { + | - let's call the lifetime of this reference `'1` +... +LL | if let Some(n) = list[0].next.as_mut() { + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | `list[_].next` was mutably borrowed here in the previous iteration of the loop + | argument requires that `list[_].next` is borrowed for `'1` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/issue-62007-assign-differing-fields.rs b/tests/ui/nll/issue-62007-assign-differing-fields.rs new file mode 100644 index 000000000..29d92b7b8 --- /dev/null +++ b/tests/ui/nll/issue-62007-assign-differing-fields.rs @@ -0,0 +1,25 @@ +// Double-check we didn't go too far with our resolution to issue +// #62007: assigning over a field projection (`list.1 = n;` in this +// case) should kill only borrows of `list.1`; `list.0` can *not* +// necessarily be borrowed on the next iteration through the loop. + +#![allow(dead_code)] + +struct List { + value: T, + next: Option>>, +} + +fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a mut T> { + let mut result = vec![]; + loop { + result.push(&mut (list.0).value); //~ ERROR cannot borrow `list.0.value` as mutable + if let Some(n) = (list.0).next.as_mut() { //~ ERROR cannot borrow `list.0.next` as mutable + list.1 = n; + } else { + return result; + } + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-62007-assign-differing-fields.stderr b/tests/ui/nll/issue-62007-assign-differing-fields.stderr new file mode 100644 index 000000000..4488431fc --- /dev/null +++ b/tests/ui/nll/issue-62007-assign-differing-fields.stderr @@ -0,0 +1,27 @@ +error[E0499]: cannot borrow `list.0.value` as mutable more than once at a time + --> $DIR/issue-62007-assign-differing-fields.rs:16:21 + | +LL | fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a mut T> { + | -- lifetime `'a` defined here +... +LL | result.push(&mut (list.0).value); + | ^^^^^^^^^^^^^^^^^^^ `list.0.value` was mutably borrowed here in the previous iteration of the loop +... +LL | return result; + | ------ returning this value requires that `list.0.value` is borrowed for `'a` + +error[E0499]: cannot borrow `list.0.next` as mutable more than once at a time + --> $DIR/issue-62007-assign-differing-fields.rs:17:26 + | +LL | fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a mut T> { + | -- lifetime `'a` defined here +... +LL | if let Some(n) = (list.0).next.as_mut() { + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `list.0.next` was mutably borrowed here in the previous iteration of the loop + | argument requires that `list.0.next` is borrowed for `'a` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/issue-63154-normalize.rs b/tests/ui/nll/issue-63154-normalize.rs new file mode 100644 index 000000000..484c12879 --- /dev/null +++ b/tests/ui/nll/issue-63154-normalize.rs @@ -0,0 +1,34 @@ +// Regression test for rust-lang/rust#63154 +// +// Before, we would ICE after failing to normalize the destination type +// when checking call destinations and also when checking MIR +// assignment statements. + +// check-pass + +trait HasAssocType { + type Inner; +} + +impl HasAssocType for () { + type Inner = (); +} + +trait Tr: Fn(I) -> Option {} +impl Option> Tr for Q {} + +fn f() -> impl Tr { + |_| None +} + +fn g(f: impl Tr) -> impl Tr { + f +} + +fn h() { + g(f())(()); +} + +fn main() { + h(); +} diff --git a/tests/ui/nll/issue-67007-escaping-data.rs b/tests/ui/nll/issue-67007-escaping-data.rs new file mode 100644 index 000000000..49ea2e596 --- /dev/null +++ b/tests/ui/nll/issue-67007-escaping-data.rs @@ -0,0 +1,24 @@ +// Regression test for issue #67007 +// Ensures that we show information about the specific regions involved + +// Covariant over 'a, invariant over 'tcx +struct FnCtxt<'a, 'tcx: 'a>(&'a (), *mut &'tcx ()); + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + fn use_it(&self, _: &'tcx ()) {} +} + +struct Consumer<'tcx>(&'tcx ()); + +impl<'tcx> Consumer<'tcx> { + fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { + let other = self.use_fcx(fcx); //~ ERROR lifetime may not live long enough + fcx.use_it(other); + } + + fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () { + &() + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-67007-escaping-data.stderr b/tests/ui/nll/issue-67007-escaping-data.stderr new file mode 100644 index 000000000..ac9c59bf7 --- /dev/null +++ b/tests/ui/nll/issue-67007-escaping-data.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/issue-67007-escaping-data.rs:15:21 + | +LL | impl<'tcx> Consumer<'tcx> { + | ---- lifetime `'tcx` defined here +LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { + | -- lifetime `'a` defined here +LL | let other = self.use_fcx(fcx); + | ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx` + | + = help: consider adding the following bound: `'a: 'tcx` + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-68550.rs b/tests/ui/nll/issue-68550.rs new file mode 100644 index 000000000..6bfd18de1 --- /dev/null +++ b/tests/ui/nll/issue-68550.rs @@ -0,0 +1,15 @@ +// Regression test for issue #68550. +// +// The `&'static A:` where clause was triggering +// ICEs because it wound up being compiled to reference +// the `'empty(U0)` region. + +fn run<'a, A>(x: A) +where + A: 'static, + &'static A: , +{ + let _: &'a A = &x; //~ ERROR `x` does not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/issue-68550.stderr b/tests/ui/nll/issue-68550.stderr new file mode 100644 index 000000000..e234ebb04 --- /dev/null +++ b/tests/ui/nll/issue-68550.stderr @@ -0,0 +1,16 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-68550.rs:12:20 + | +LL | fn run<'a, A>(x: A) + | -- lifetime `'a` defined here +... +LL | let _: &'a A = &x; + | ----- ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'a` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-69114-static-mut-ty.rs b/tests/ui/nll/issue-69114-static-mut-ty.rs new file mode 100644 index 000000000..ce37da053 --- /dev/null +++ b/tests/ui/nll/issue-69114-static-mut-ty.rs @@ -0,0 +1,30 @@ +// Check that borrowck ensures that `static mut` items have the expected type. + +static FOO: u8 = 42; +static mut BAR: &'static u8 = &FOO; +static mut BAR_ELIDED: &u8 = &FOO; + +fn main() { + unsafe { + println!("{} {}", BAR, BAR_ELIDED); + set_bar(); + set_bar_elided(); + println!("{} {}", BAR, BAR_ELIDED); + } +} + +fn set_bar() { + let n = 42; + unsafe { + BAR = &n; + //~^ ERROR does not live long enough + } +} + +fn set_bar_elided() { + let n = 42; + unsafe { + BAR_ELIDED = &n; + //~^ ERROR does not live long enough + } +} diff --git a/tests/ui/nll/issue-69114-static-mut-ty.stderr b/tests/ui/nll/issue-69114-static-mut-ty.stderr new file mode 100644 index 000000000..5e55cb502 --- /dev/null +++ b/tests/ui/nll/issue-69114-static-mut-ty.stderr @@ -0,0 +1,27 @@ +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-mut-ty.rs:19:15 + | +LL | BAR = &n; + | ------^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `n` is borrowed for `'static` +... +LL | } + | - `n` dropped here while still borrowed + +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-mut-ty.rs:27:22 + | +LL | BAR_ELIDED = &n; + | -------------^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `n` is borrowed for `'static` +... +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-69114-static-ty.rs b/tests/ui/nll/issue-69114-static-ty.rs new file mode 100644 index 000000000..3318433a1 --- /dev/null +++ b/tests/ui/nll/issue-69114-static-ty.rs @@ -0,0 +1,9 @@ +// Check that borrowck ensures that `static` items have the expected type. + +static FOO: &'static (dyn Fn(&'static u8) + Send + Sync) = &drop; + +fn main() { + let n = 42; + FOO(&n); + //~^ ERROR does not live long enough +} diff --git a/tests/ui/nll/issue-69114-static-ty.stderr b/tests/ui/nll/issue-69114-static-ty.stderr new file mode 100644 index 000000000..0815e74b5 --- /dev/null +++ b/tests/ui/nll/issue-69114-static-ty.stderr @@ -0,0 +1,15 @@ +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-ty.rs:7:9 + | +LL | FOO(&n); + | ----^^- + | | | + | | borrowed value does not live long enough + | argument requires that `n` is borrowed for `'static` +LL | +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/issue-73159-rpit-static.rs b/tests/ui/nll/issue-73159-rpit-static.rs new file mode 100644 index 000000000..3002408b0 --- /dev/null +++ b/tests/ui/nll/issue-73159-rpit-static.rs @@ -0,0 +1,13 @@ +// Regression test for issue #73159 +// Tests thar we don't suggest replacing 'a with 'static' + +struct Foo<'a>(&'a [u8]); + +impl<'a> Foo<'a> { + fn make_it(&self) -> impl Iterator { + self.0.iter().copied() + //~^ ERROR: captures lifetime that does not appear in bounds + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-73159-rpit-static.stderr b/tests/ui/nll/issue-73159-rpit-static.stderr new file mode 100644 index 000000000..260b9b597 --- /dev/null +++ b/tests/ui/nll/issue-73159-rpit-static.stderr @@ -0,0 +1,12 @@ +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-73159-rpit-static.rs:8:9 + | +LL | impl<'a> Foo<'a> { + | -- hidden type `Copied>` captures the lifetime `'a` as defined here +LL | fn make_it(&self) -> impl Iterator { +LL | self.0.iter().copied() + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/nll/issue-78561.rs b/tests/ui/nll/issue-78561.rs new file mode 100644 index 000000000..55147fcd1 --- /dev/null +++ b/tests/ui/nll/issue-78561.rs @@ -0,0 +1,23 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +pub trait Trait { + type A; + + fn f() -> Self::A; +} + +pub trait Tr2<'a, 'b> {} + +pub struct A(T); +pub trait Tr { + type B; +} + +impl<'a, 'b, T: Tr>> Trait for A { + type A = impl core::fmt::Debug; + + fn f() -> Self::A {} +} + +fn main() {} diff --git a/tests/ui/nll/issue-95272.rs b/tests/ui/nll/issue-95272.rs new file mode 100644 index 000000000..958cbde37 --- /dev/null +++ b/tests/ui/nll/issue-95272.rs @@ -0,0 +1,15 @@ +use std::cell::Cell; + +fn check<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) +where + 'a: 'b, +{ +} + +fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { + let f = check; + //~^ ERROR lifetime may not live long enough + f(x, y); +} + +fn main() {} diff --git a/tests/ui/nll/issue-95272.stderr b/tests/ui/nll/issue-95272.stderr new file mode 100644 index 000000000..03edbc3a6 --- /dev/null +++ b/tests/ui/nll/issue-95272.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/issue-95272.rs:10:13 + | +LL | fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let f = check; + | ^^^^^ assignment requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a function pointer to `check` + = note: the function `check` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/nll/issue-97997.rs b/tests/ui/nll/issue-97997.rs new file mode 100644 index 000000000..c64e720b1 --- /dev/null +++ b/tests/ui/nll/issue-97997.rs @@ -0,0 +1,16 @@ +trait Foo { + const ASSOC: bool = true; +} +impl Foo for fn(T) {} + +fn foo(_x: i32) {} + +fn impls_foo(_x: T) {} + +fn main() { + impls_foo(foo as fn(i32)); + + ::ASSOC; + //~^ ERROR implementation of `Foo` is not general enough + //~| ERROR implementation of `Foo` is not general enough +} diff --git a/tests/ui/nll/issue-97997.stderr b/tests/ui/nll/issue-97997.stderr new file mode 100644 index 000000000..46440c021 --- /dev/null +++ b/tests/ui/nll/issue-97997.stderr @@ -0,0 +1,20 @@ +error: implementation of `Foo` is not general enough + --> $DIR/issue-97997.rs:13:5 + | +LL | ::ASSOC; + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0` + +error: implementation of `Foo` is not general enough + --> $DIR/issue-97997.rs:13:5 + | +LL | ::ASSOC; + | ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/issue-98170.rs b/tests/ui/nll/issue-98170.rs new file mode 100644 index 000000000..6bb12f52d --- /dev/null +++ b/tests/ui/nll/issue-98170.rs @@ -0,0 +1,25 @@ +pub struct MyStruct<'a> { + field: &'a [u32], +} + +impl MyStruct<'_> { + pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> { + Self { field } + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + } +} + +trait Trait<'a> { + fn new(field: &'a [u32]) -> MyStruct<'a>; +} + +impl<'a> Trait<'a> for MyStruct<'_> { + fn new(field: &'a [u32]) -> MyStruct<'a> { + Self { field } + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/nll/issue-98170.stderr b/tests/ui/nll/issue-98170.stderr new file mode 100644 index 000000000..0d17365e7 --- /dev/null +++ b/tests/ui/nll/issue-98170.stderr @@ -0,0 +1,44 @@ +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:7:9 + | +LL | impl MyStruct<'_> { + | -- lifetime `'1` appears in the `impl`'s self type +LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> { + | -- lifetime `'a` defined here +LL | Self { field } + | ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:7:16 + | +LL | impl MyStruct<'_> { + | -- lifetime `'1` appears in the `impl`'s self type +LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> { + | -- lifetime `'a` defined here +LL | Self { field } + | ^^^^^ this usage requires that `'a` must outlive `'1` + +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:19:9 + | +LL | impl<'a> Trait<'a> for MyStruct<'_> { + | -- -- lifetime `'1` appears in the `impl`'s self type + | | + | lifetime `'a` defined here +LL | fn new(field: &'a [u32]) -> MyStruct<'a> { +LL | Self { field } + | ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:19:16 + | +LL | impl<'a> Trait<'a> for MyStruct<'_> { + | -- -- lifetime `'1` appears in the `impl`'s self type + | | + | lifetime `'a` defined here +LL | fn new(field: &'a [u32]) -> MyStruct<'a> { +LL | Self { field } + | ^^^^^ this usage requires that `'a` must outlive `'1` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/nll/issue-98589-closures-relate-named-regions.rs b/tests/ui/nll/issue-98589-closures-relate-named-regions.rs new file mode 100644 index 000000000..6cc4340bb --- /dev/null +++ b/tests/ui/nll/issue-98589-closures-relate-named-regions.rs @@ -0,0 +1,36 @@ +// Regression test for #98589. +// Previously, named lifetime `'a` that appears in the closure was unrelated to `'a` +// that appears in the parent function iff `'a` is early-bound. +// This made the following tests pass borrowck. + +// check-fail + +// The bound `'a: 'a` ensures that `'a` is early-bound. +fn test_early_early<'a: 'a, 'b: 'b>() { + || { None::<&'a &'b ()>; }; + //~^ ERROR lifetime may not live long enough +} + +fn test_early_late<'a: 'a, 'b>() { + || { None::<&'a &'b ()>; }; + //~^ ERROR lifetime may not live long enough +} + +// No early-bound lifetime; included for completeness. +fn test_late_late<'a, 'b>() { + || { None::<&'a &'b ()>; }; + //~^ ERROR lifetime may not live long enough +} + +fn test_early_type<'a: 'a, T>() { + || { None::<&'a T>; }; + //~^ ERROR the parameter type `T` may not live long enough +} + +// No early-bound lifetime; included for completeness. +fn test_late_type<'a, T>() { + || { None::<&'a T>; }; + //~^ ERROR the parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr new file mode 100644 index 000000000..d8b26f0b0 --- /dev/null +++ b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -0,0 +1,61 @@ +error: lifetime may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:10:5 + | +LL | fn test_early_early<'a: 'a, 'b: 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | || { None::<&'a &'b ()>; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:15:10 + | +LL | fn test_early_late<'a: 'a, 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | || { None::<&'a &'b ()>; }; + | ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:21:10 + | +LL | fn test_late_late<'a, 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | || { None::<&'a &'b ()>; }; + | ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:26:10 + | +LL | || { None::<&'a T>; }; + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_early_type<'a: 'a, T: 'a>() { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:32:10 + | +LL | || { None::<&'a T>; }; + | ^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_late_type<'a, T: 'a>() { + | ++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/issue-98693.rs b/tests/ui/nll/issue-98693.rs new file mode 100644 index 000000000..7a325e2e9 --- /dev/null +++ b/tests/ui/nll/issue-98693.rs @@ -0,0 +1,21 @@ +// Regression test for #98693. +// +// The closure encounters an obligation that `T` must outlive `!U1`, +// a placeholder from universe U1. We were ignoring this placeholder +// when promoting the constraint to the enclosing function, and +// thus incorrectly judging the closure to be safe. + +fn assert_static() +where + for<'a> T: 'a, +{ +} + +fn test() { + || { + assert_static::(); + //~^ ERROR the parameter type `T` may not live long enough + }; +} + +fn main() {} diff --git a/tests/ui/nll/issue-98693.stderr b/tests/ui/nll/issue-98693.stderr new file mode 100644 index 000000000..15ca38aa2 --- /dev/null +++ b/tests/ui/nll/issue-98693.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-98693.rs:16:9 + | +LL | assert_static::(); + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test() { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/nll/lint-no-err.rs b/tests/ui/nll/lint-no-err.rs new file mode 100644 index 000000000..2d1d5cb26 --- /dev/null +++ b/tests/ui/nll/lint-no-err.rs @@ -0,0 +1,21 @@ +// check-pass + +// mir borrowck previously incorrectly set `tainted_by_errors` +// when buffering lints, which resulted in ICE later on, +// see #94502. + +struct Repro; +impl Repro { + fn get(&self) -> &i32 { + &3 + } + + fn insert(&mut self, _: i32) {} +} + +fn main() { + let x = &0; + let mut conflict = Repro; + let prev = conflict.get(); + conflict.insert(*prev + *x); +} diff --git a/tests/ui/nll/loan_ends_mid_block_pair.rs b/tests/ui/nll/loan_ends_mid_block_pair.rs new file mode 100644 index 000000000..acd6ec706 --- /dev/null +++ b/tests/ui/nll/loan_ends_mid_block_pair.rs @@ -0,0 +1,29 @@ +#![allow(warnings)] +#![feature(rustc_attrs)] + + +fn main() { +} + +fn nll_fail() { + let mut data = ('a', 'b', 'c'); + let c = &mut data.0; + capitalize(c); + data.0 = 'e'; + //~^ ERROR [E0506] + data.0 = 'f'; + data.0 = 'g'; + capitalize(c); +} + +fn nll_ok() { + let mut data = ('a', 'b', 'c'); + let c = &mut data.0; + capitalize(c); + data.0 = 'e'; + data.0 = 'f'; + data.0 = 'g'; +} + +fn capitalize(_: &mut char) { +} diff --git a/tests/ui/nll/loan_ends_mid_block_pair.stderr b/tests/ui/nll/loan_ends_mid_block_pair.stderr new file mode 100644 index 000000000..eb8442b31 --- /dev/null +++ b/tests/ui/nll/loan_ends_mid_block_pair.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `data.0` because it is borrowed + --> $DIR/loan_ends_mid_block_pair.rs:12:5 + | +LL | let c = &mut data.0; + | ----------- borrow of `data.0` occurs here +LL | capitalize(c); +LL | data.0 = 'e'; + | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here +... +LL | capitalize(c); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/loan_ends_mid_block_vec.rs b/tests/ui/nll/loan_ends_mid_block_vec.rs new file mode 100644 index 000000000..2edcdef0a --- /dev/null +++ b/tests/ui/nll/loan_ends_mid_block_vec.rs @@ -0,0 +1,30 @@ +#![allow(warnings)] +#![feature(rustc_attrs)] + +fn main() { +} + +fn nll_fail() { + let mut data = vec!['a', 'b', 'c']; + let slice = &mut data; + capitalize(slice); + data.push('d'); + //~^ ERROR [E0499] + data.push('e'); + //~^ ERROR [E0499] + data.push('f'); + //~^ ERROR [E0499] + capitalize(slice); +} + +fn nll_ok() { + let mut data = vec!['a', 'b', 'c']; + let slice = &mut data; + capitalize(slice); + data.push('d'); + data.push('e'); + data.push('f'); +} + +fn capitalize(_: &mut [char]) { +} diff --git a/tests/ui/nll/loan_ends_mid_block_vec.stderr b/tests/ui/nll/loan_ends_mid_block_vec.stderr new file mode 100644 index 000000000..22c72af61 --- /dev/null +++ b/tests/ui/nll/loan_ends_mid_block_vec.stderr @@ -0,0 +1,39 @@ +error[E0499]: cannot borrow `data` as mutable more than once at a time + --> $DIR/loan_ends_mid_block_vec.rs:11:5 + | +LL | let slice = &mut data; + | --------- first mutable borrow occurs here +LL | capitalize(slice); +LL | data.push('d'); + | ^^^^^^^^^^^^^^ second mutable borrow occurs here +... +LL | capitalize(slice); + | ----- first borrow later used here + +error[E0499]: cannot borrow `data` as mutable more than once at a time + --> $DIR/loan_ends_mid_block_vec.rs:13:5 + | +LL | let slice = &mut data; + | --------- first mutable borrow occurs here +... +LL | data.push('e'); + | ^^^^^^^^^^^^^^ second mutable borrow occurs here +... +LL | capitalize(slice); + | ----- first borrow later used here + +error[E0499]: cannot borrow `data` as mutable more than once at a time + --> $DIR/loan_ends_mid_block_vec.rs:15:5 + | +LL | let slice = &mut data; + | --------- first mutable borrow occurs here +... +LL | data.push('f'); + | ^^^^^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | capitalize(slice); + | ----- first borrow later used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/local-outlives-static-via-hrtb.rs b/tests/ui/nll/local-outlives-static-via-hrtb.rs new file mode 100644 index 000000000..5f1f9b3a7 --- /dev/null +++ b/tests/ui/nll/local-outlives-static-via-hrtb.rs @@ -0,0 +1,26 @@ +// Test that we handle the case when a local variable is borrowed for `'static` +// due to an outlives constraint involving a region in an incompatible universe + +pub trait Outlives<'this> {} + +impl<'this, T> Outlives<'this> for T where T: 'this {} +trait Reference { + type AssociatedType; +} + +impl<'a, T: 'a> Reference for &'a T { + type AssociatedType = &'a (); +} + +fn assert_static_via_hrtb(_: G) where for<'a> G: Outlives<'a> {} + +fn assert_static_via_hrtb_with_assoc_type(_: &'_ T) +where + for<'a> &'a T: Reference, +{} + +fn main() { + let local = 0; + assert_static_via_hrtb(&local); //~ ERROR `local` does not live long enough + assert_static_via_hrtb_with_assoc_type(&&local); //~ ERROR `local` does not live long enough +} diff --git a/tests/ui/nll/local-outlives-static-via-hrtb.stderr b/tests/ui/nll/local-outlives-static-via-hrtb.stderr new file mode 100644 index 000000000..f5c10f3dd --- /dev/null +++ b/tests/ui/nll/local-outlives-static-via-hrtb.stderr @@ -0,0 +1,38 @@ +error[E0597]: `local` does not live long enough + --> $DIR/local-outlives-static-via-hrtb.rs:24:28 + | +LL | assert_static_via_hrtb(&local); + | -----------------------^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `local` is borrowed for `'static` +LL | assert_static_via_hrtb_with_assoc_type(&&local); +LL | } + | - `local` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/local-outlives-static-via-hrtb.rs:15:53 + | +LL | fn assert_static_via_hrtb(_: G) where for<'a> G: Outlives<'a> {} + | ^^^^^^^^^^^^ + +error[E0597]: `local` does not live long enough + --> $DIR/local-outlives-static-via-hrtb.rs:25:45 + | +LL | assert_static_via_hrtb_with_assoc_type(&&local); + | ----------------------------------------^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `local` is borrowed for `'static` +LL | } + | - `local` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/local-outlives-static-via-hrtb.rs:19:20 + | +LL | for<'a> &'a T: Reference, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/lub-if.rs b/tests/ui/nll/lub-if.rs new file mode 100644 index 000000000..50225a783 --- /dev/null +++ b/tests/ui/nll/lub-if.rs @@ -0,0 +1,44 @@ +// Test that we correctly consider the type of `match` to be the LUB +// of the various arms, particularly in the case where regions are +// involved. + +pub fn opt_str0<'a>(maybestr: &'a Option) -> &'a str { + if maybestr.is_none() { + "(none)" + } else { + let s: &'a str = maybestr.as_ref().unwrap(); + s + } +} + +pub fn opt_str1<'a>(maybestr: &'a Option) -> &'a str { + if maybestr.is_some() { + let s: &'a str = maybestr.as_ref().unwrap(); + s + } else { + "(none)" + } +} + +pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { + if maybestr.is_none() { + "(none)" + } else { + let s: &'a str = maybestr.as_ref().unwrap(); + s + //~^ ERROR lifetime may not live long enough + } +} + +pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { + if maybestr.is_some() { + let s: &'a str = maybestr.as_ref().unwrap(); + s + //~^ ERROR lifetime may not live long enough + } else { + "(none)" + } +} + + +fn main() {} diff --git a/tests/ui/nll/lub-if.stderr b/tests/ui/nll/lub-if.stderr new file mode 100644 index 000000000..03f7f9204 --- /dev/null +++ b/tests/ui/nll/lub-if.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/lub-if.rs:28:9 + | +LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { + | -- lifetime `'a` defined here +... +LL | s + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/lub-if.rs:36:9 + | +LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { + | -- lifetime `'a` defined here +... +LL | s + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/lub-match.rs b/tests/ui/nll/lub-match.rs new file mode 100644 index 000000000..454dd1fc6 --- /dev/null +++ b/tests/ui/nll/lub-match.rs @@ -0,0 +1,47 @@ +// Test that we correctly consider the type of `match` to be the LUB +// of the various arms, particularly in the case where regions are +// involved. + +pub fn opt_str0<'a>(maybestr: &'a Option) -> &'a str { + match *maybestr { + Some(ref s) => { + let s: &'a str = s; + s + } + None => "(none)", + } +} + +pub fn opt_str1<'a>(maybestr: &'a Option) -> &'a str { + match *maybestr { + None => "(none)", + Some(ref s) => { + let s: &'a str = s; + s + } + } +} + +pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { + match *maybestr { + None => "(none)", + Some(ref s) => { + let s: &'a str = s; + s + //~^ ERROR lifetime may not live long enough + } + } +} + +pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { + match *maybestr { + Some(ref s) => { + let s: &'a str = s; + s + //~^ ERROR lifetime may not live long enough + } + None => "(none)", + } +} + +fn main() {} diff --git a/tests/ui/nll/lub-match.stderr b/tests/ui/nll/lub-match.stderr new file mode 100644 index 000000000..208ec07a1 --- /dev/null +++ b/tests/ui/nll/lub-match.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/lub-match.rs:30:13 + | +LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { + | -- lifetime `'a` defined here +... +LL | s + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/lub-match.rs:40:13 + | +LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { + | -- lifetime `'a` defined here +... +LL | s + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/match-cfg-fake-edges.rs b/tests/ui/nll/match-cfg-fake-edges.rs new file mode 100644 index 000000000..1afc7931a --- /dev/null +++ b/tests/ui/nll/match-cfg-fake-edges.rs @@ -0,0 +1,70 @@ +// Test that we have enough false edges to avoid exposing the exact matching +// algorithm in borrow checking. + +#![feature(if_let_guard)] + +fn guard_always_precedes_arm(y: i32) { + let mut x; + // x should always be initialized, as the only way to reach the arm is + // through the guard. + match y { + 0 | 2 if { x = 2; true } => x, + _ => 2, + }; + + let mut x; + match y { + 0 | 2 if let Some(()) = { x = 2; Some(()) } => x, + _ => 2, + }; +} + +fn guard_may_be_skipped(y: i32) { + let x; + // Even though x *is* always initialized, we don't want to have borrowck + // results be based on whether patterns are exhaustive. + match y { + _ if { x = 2; true } => 1, + _ if { + x; //~ ERROR E0381 + false + } => 2, + _ => 3, + }; + + let x; + match y { + _ if let Some(()) = { x = 2; Some(()) } => 1, + _ if let Some(()) = { + x; //~ ERROR E0381 + None + } => 2, + _ => 3, + }; +} + +fn guard_may_be_taken(y: bool) { + let x = String::new(); + // Even though x *is* never moved before the use, we don't want to have + // borrowck results be based on whether patterns are disjoint. + match y { + false if { drop(x); true } => 1, + true => { + x; //~ ERROR use of moved value: `x` + 2 + } + false => 3, + }; + + let x = String::new(); + match y { + false if let Some(()) = { drop(x); Some(()) } => 1, + true => { + x; //~ ERROR use of moved value: `x` + 2 + } + false => 3, + }; +} + +fn main() {} diff --git a/tests/ui/nll/match-cfg-fake-edges.stderr b/tests/ui/nll/match-cfg-fake-edges.stderr new file mode 100644 index 000000000..a6261345c --- /dev/null +++ b/tests/ui/nll/match-cfg-fake-edges.stderr @@ -0,0 +1,72 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/match-cfg-fake-edges.rs:29:13 + | +LL | let x; + | - binding declared here but left uninitialized +... +LL | _ if { x = 2; true } => 1, + | ----- binding initialized here in some conditions +LL | _ if { +LL | x; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/match-cfg-fake-edges.rs:39:13 + | +LL | let x; + | - binding declared here but left uninitialized +LL | match y { +LL | _ if let Some(()) = { x = 2; Some(()) } => 1, + | ----- binding initialized here in some conditions +LL | _ if let Some(()) = { +LL | x; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ + +error[E0382]: use of moved value: `x` + --> $DIR/match-cfg-fake-edges.rs:53:13 + | +LL | let x = String::new(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +... +LL | false if { drop(x); true } => 1, + | - value moved here +LL | true => { +LL | x; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false if { drop(x.clone()); true } => 1, + | ++++++++ + +error[E0382]: use of moved value: `x` + --> $DIR/match-cfg-fake-edges.rs:63:13 + | +LL | let x = String::new(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | match y { +LL | false if let Some(()) = { drop(x); Some(()) } => 1, + | - value moved here +LL | true => { +LL | x; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false if let Some(()) = { drop(x.clone()); Some(()) } => 1, + | ++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/nll/match-cfg-fake-edges2.rs b/tests/ui/nll/match-cfg-fake-edges2.rs new file mode 100644 index 000000000..48f95e03b --- /dev/null +++ b/tests/ui/nll/match-cfg-fake-edges2.rs @@ -0,0 +1,18 @@ +// Test that we have enough false edges to avoid exposing the exact matching +// algorithm in borrow checking. + +fn all_previous_tests_may_be_done(y: &mut (bool, bool)) { + let r = &mut y.1; + // We don't actually test y.1 to select the second arm, but we don't want + // borrowck results to be based on the order we match patterns. + match y { //~ ERROR cannot use `y.1` because it was mutably borrowed + (false, true) => 1, + (true, _) => { + r; + 2 + } + (false, _) => 3, + }; +} + +fn main() {} diff --git a/tests/ui/nll/match-cfg-fake-edges2.stderr b/tests/ui/nll/match-cfg-fake-edges2.stderr new file mode 100644 index 000000000..c6d15a936 --- /dev/null +++ b/tests/ui/nll/match-cfg-fake-edges2.stderr @@ -0,0 +1,15 @@ +error[E0503]: cannot use `y.1` because it was mutably borrowed + --> $DIR/match-cfg-fake-edges2.rs:8:5 + | +LL | let r = &mut y.1; + | -------- borrow of `y.1` occurs here +... +LL | match y { + | ^^^^^^^ use of borrowed `y.1` +... +LL | r; + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/match-guards-always-borrow.rs b/tests/ui/nll/match-guards-always-borrow.rs new file mode 100644 index 000000000..ff63cc092 --- /dev/null +++ b/tests/ui/nll/match-guards-always-borrow.rs @@ -0,0 +1,64 @@ +#![feature(if_let_guard)] + +// Here is arielb1's basic example from rust-lang/rust#27282 +// that AST borrowck is flummoxed by: + +fn should_reject_destructive_mutate_in_guard() { + match Some(&4) { + None => {}, + ref mut foo if { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + false } => { }, + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo if let Some(()) = { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + None } => { }, + Some(s) => std::process::exit(*s), + } +} + +// Here below is a case that needs to keep working: we only use the +// binding via immutable-borrow in the guard, and we mutate in the arm +// body. +fn allow_mutate_in_arm_body() { + match Some(&4) { + None => {}, + ref mut foo if foo.is_some() => { foo.take(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo if let Some(_) = foo => { foo.take(); () } + Some(s) => std::process::exit(*s), + } +} + +// Here below is a case that needs to keep working: we only use the +// binding via immutable-borrow in the guard, and we move into the arm +// body. +fn allow_move_into_arm_body() { + match Some(&4) { + None => {}, + mut foo if foo.is_some() => { foo.unwrap(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + mut foo if let Some(_) = foo => { foo.unwrap(); () } + Some(s) => std::process::exit(*s), + } +} + +fn main() { + should_reject_destructive_mutate_in_guard(); + allow_mutate_in_arm_body(); + allow_move_into_arm_body(); +} diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr new file mode 100644 index 000000000..fa01d3a6f --- /dev/null +++ b/tests/ui/nll/match-guards-always-borrow.stderr @@ -0,0 +1,23 @@ +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/match-guards-always-borrow.rs:10:14 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/match-guards-always-borrow.rs:19:14 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/match-guards-partially-borrow.rs b/tests/ui/nll/match-guards-partially-borrow.rs new file mode 100644 index 000000000..3a9e1654b --- /dev/null +++ b/tests/ui/nll/match-guards-partially-borrow.rs @@ -0,0 +1,332 @@ +// Test that a (partially) mutably borrowed place can be matched on, so long as +// we don't have to read any values that are mutably borrowed to determine +// which arm to take. +// +// Test that we don't allow mutating the value being matched on in a way that +// changes which patterns it matches, until we have chosen an arm. + +#![feature(if_let_guard)] + +fn ok_mutation_in_if_guard(mut q: i32) { + match q { + // OK, mutation doesn't change which patterns g matches + _ if { q = 1; false } => (), + _ => (), + } +} + +fn ok_mutation_in_if_let_guard(mut q: i32) { + match q { + // OK, mutation doesn't change which patterns g matches + _ if let Some(()) = { q = 1; None } => (), + _ => (), + } +} + +fn ok_mutation_in_if_guard2(mut u: bool) { + // OK value of u is unused before modification + match u { + _ => (), + _ if { + u = true; + false + } => (), + x => (), + } +} + +fn ok_mutation_in_if_let_guard2(mut u: bool) { + // OK value of u is unused before modification + match u { + _ => (), + _ if let Some(()) = { + u = true; + None + } => (), + x => (), + } +} + +fn ok_mutation_in_if_guard4(mut w: (&mut bool,)) { + // OK value of u is unused before modification + match w { + _ => (), + _ if { + *w.0 = true; + false + } => (), + x => (), + } +} + +fn ok_mutation_in_if_let_guard4(mut w: (&mut bool,)) { + // OK value of u is unused before modification + match w { + _ => (), + _ if let Some(()) = { + *w.0 = true; + None + } => (), + x => (), + } +} + +fn ok_indirect_mutation_in_if_guard(mut p: &bool) { + match *p { + // OK, mutation doesn't change which patterns s matches + _ if { + p = &true; + false + } => (), + _ => (), + } +} + +fn ok_indirect_mutation_in_if_let_guard(mut p: &bool) { + match *p { + // OK, mutation doesn't change which patterns s matches + _ if let Some(()) = { + p = &true; + None + } => (), + _ => (), + } +} + +fn mutation_invalidates_pattern_in_if_guard(mut q: bool) { + match q { + // q doesn't match the pattern with the guard by the end of the guard. + false if { + q = true; //~ ERROR + true + } => (), + _ => (), + } +} + +fn mutation_invalidates_pattern_in_if_let_guard(mut q: bool) { + match q { + // q doesn't match the pattern with the guard by the end of the guard. + false if let Some(()) = { + q = true; //~ ERROR + Some(()) + } => (), + _ => (), + } +} + +fn mutation_invalidates_previous_pattern_in_if_guard(mut r: bool) { + match r { + // r matches a previous pattern by the end of the guard. + true => (), + _ if { + r = true; //~ ERROR + true + } => (), + _ => (), + } +} + +fn mutation_invalidates_previous_pattern_in_if_let_guard(mut r: bool) { + match r { + // r matches a previous pattern by the end of the guard. + true => (), + _ if let Some(()) = { + r = true; //~ ERROR + Some(()) + } => (), + _ => (), + } +} + +fn match_on_borrowed_early_end_if_guard(mut s: bool) { + let h = &mut s; + // OK value of s is unused before modification. + match s { + _ if { + *h = !*h; + false + } => (), + true => (), + false => (), + } +} + +fn match_on_borrowed_early_end_if_let_guard(mut s: bool) { + let h = &mut s; + // OK value of s is unused before modification. + match s { + _ if let Some(()) = { + *h = !*h; + None + } => (), + true => (), + false => (), + } +} + +fn bad_mutation_in_if_guard(mut t: bool) { + match t { + true => (), + false if { + t = true; //~ ERROR + false + } => (), + false => (), + } +} + +fn bad_mutation_in_if_let_guard(mut t: bool) { + match t { + true => (), + false if let Some(()) = { + t = true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_mutation_in_if_guard2(mut x: Option>) { + // Check that nested patterns are checked. + match x { + None => (), + Some(None) => (), + _ if { + match x { + Some(ref mut r) => *r = None, //~ ERROR + _ => return, + }; + false + } => (), + Some(Some(r)) => println!("{}", r), + } +} + +fn bad_mutation_in_if_let_guard2(mut x: Option>) { + // Check that nested patterns are checked. + match x { + None => (), + Some(None) => (), + _ if let Some(()) = { + match x { + Some(ref mut r) => *r = None, //~ ERROR + _ => return, + }; + None + } => (), + Some(Some(r)) => println!("{}", r), + } +} + +fn bad_mutation_in_if_guard3(mut t: bool) { + match t { + s if { + t = !t; //~ ERROR + false + } => (), // What value should `s` have in the arm? + _ => (), + } +} + +fn bad_mutation_in_if_let_guard3(mut t: bool) { + match t { + s if let Some(()) = { + t = !t; //~ ERROR + None + } => (), // What value should `s` have in the arm? + _ => (), + } +} + +fn bad_indirect_mutation_in_if_guard(mut y: &bool) { + match *y { + true => (), + false if { + y = &true; //~ ERROR + false + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_let_guard(mut y: &bool) { + match *y { + true => (), + false if let Some(()) = { + y = &true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_guard2(mut z: &bool) { + match z { + &true => (), + &false if { + z = &true; //~ ERROR + false + } => (), + &false => (), + } +} + +fn bad_indirect_mutation_in_if_let_guard2(mut z: &bool) { + match z { + &true => (), + &false if let Some(()) = { + z = &true; //~ ERROR + None + } => (), + &false => (), + } +} + +fn bad_indirect_mutation_in_if_guard3(mut a: &bool) { + // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics + match a { + true => (), + false if { + a = &true; //~ ERROR + false + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_let_guard3(mut a: &bool) { + // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics + match a { + true => (), + false if let Some(()) = { + a = &true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_guard4(mut b: &bool) { + match b { + &_ => (), + &_ if { + b = &true; //~ ERROR + false + } => (), + &b => (), + } +} + +fn bad_indirect_mutation_in_if_let_guard4(mut b: &bool) { + match b { + &_ => (), + &_ if let Some(()) = { + b = &true; //~ ERROR + None + } => (), + &b => (), + } +} + +fn main() {} diff --git a/tests/ui/nll/match-guards-partially-borrow.stderr b/tests/ui/nll/match-guards-partially-borrow.stderr new file mode 100644 index 000000000..60b8dee71 --- /dev/null +++ b/tests/ui/nll/match-guards-partially-borrow.stderr @@ -0,0 +1,170 @@ +error[E0510]: cannot assign `q` in match guard + --> $DIR/match-guards-partially-borrow.rs:100:13 + | +LL | match q { + | - value is immutable in match guard +... +LL | q = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `q` in match guard + --> $DIR/match-guards-partially-borrow.rs:111:13 + | +LL | match q { + | - value is immutable in match guard +... +LL | q = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `r` in match guard + --> $DIR/match-guards-partially-borrow.rs:123:13 + | +LL | match r { + | - value is immutable in match guard +... +LL | r = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `r` in match guard + --> $DIR/match-guards-partially-borrow.rs:135:13 + | +LL | match r { + | - value is immutable in match guard +... +LL | r = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `t` in match guard + --> $DIR/match-guards-partially-borrow.rs:172:13 + | +LL | match t { + | - value is immutable in match guard +... +LL | t = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `t` in match guard + --> $DIR/match-guards-partially-borrow.rs:183:13 + | +LL | match t { + | - value is immutable in match guard +... +LL | t = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot mutably borrow `x.0` in match guard + --> $DIR/match-guards-partially-borrow.rs:197:22 + | +LL | match x { + | - value is immutable in match guard +... +LL | Some(ref mut r) => *r = None, + | ^^^^^^^^^ cannot mutably borrow + +error[E0510]: cannot mutably borrow `x.0` in match guard + --> $DIR/match-guards-partially-borrow.rs:213:22 + | +LL | match x { + | - value is immutable in match guard +... +LL | Some(ref mut r) => *r = None, + | ^^^^^^^^^ cannot mutably borrow + +error[E0506]: cannot assign to `t` because it is borrowed + --> $DIR/match-guards-partially-borrow.rs:225:13 + | +LL | s if { + | - borrow of `t` occurs here +LL | t = !t; + | ^^^^^^ assignment to borrowed `t` occurs here +LL | false +LL | } => (), // What value should `s` have in the arm? + | - borrow later used here + +error[E0506]: cannot assign to `t` because it is borrowed + --> $DIR/match-guards-partially-borrow.rs:235:13 + | +LL | s if let Some(()) = { + | - borrow of `t` occurs here +LL | t = !t; + | ^^^^^^ assignment to borrowed `t` occurs here +LL | None +LL | } => (), // What value should `s` have in the arm? + | - borrow later used here + +error[E0510]: cannot assign `y` in match guard + --> $DIR/match-guards-partially-borrow.rs:246:13 + | +LL | match *y { + | -- value is immutable in match guard +... +LL | y = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `y` in match guard + --> $DIR/match-guards-partially-borrow.rs:257:13 + | +LL | match *y { + | -- value is immutable in match guard +... +LL | y = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `z` in match guard + --> $DIR/match-guards-partially-borrow.rs:268:13 + | +LL | match z { + | - value is immutable in match guard +... +LL | z = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `z` in match guard + --> $DIR/match-guards-partially-borrow.rs:279:13 + | +LL | match z { + | - value is immutable in match guard +... +LL | z = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `a` in match guard + --> $DIR/match-guards-partially-borrow.rs:291:13 + | +LL | match a { + | - value is immutable in match guard +... +LL | a = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `a` in match guard + --> $DIR/match-guards-partially-borrow.rs:303:13 + | +LL | match a { + | - value is immutable in match guard +... +LL | a = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `b` in match guard + --> $DIR/match-guards-partially-borrow.rs:314:13 + | +LL | match b { + | - value is immutable in match guard +... +LL | b = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `b` in match guard + --> $DIR/match-guards-partially-borrow.rs:325:13 + | +LL | match b { + | - value is immutable in match guard +... +LL | b = &true; + | ^^^^^^^^^ cannot assign + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0506, E0510. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/match-on-borrowed.rs b/tests/ui/nll/match-on-borrowed.rs new file mode 100644 index 000000000..447dabeb4 --- /dev/null +++ b/tests/ui/nll/match-on-borrowed.rs @@ -0,0 +1,96 @@ +// Test that a (partially) mutably borrowed place can be matched on, so long as +// we don't have to read any values that are mutably borrowed to determine +// which arm to take. +// +// Test that we don't allow mutating the value being matched on in a way that +// changes which patterns it matches, until we have chosen an arm. + +struct A(i32, i32); + +fn struct_example(mut a: A) { + let x = &mut a.0; + match a { // OK, no access of borrowed data + _ if false => (), + A(_, r) => (), + } + x; +} + +fn indirect_struct_example(mut b: &mut A) { + let x = &mut b.0; + match *b { // OK, no access of borrowed data + _ if false => (), + A(_, r) => (), + } + x; +} + +fn underscore_example(mut c: i32) { + let r = &mut c; + match c { // OK, no access of borrowed data (or any data at all) + _ if false => (), + _ => (), + } + r; +} + +enum E { + V(i32, i32), + W, +} + +fn enum_example(mut e: E) { + let x = match e { + E::V(ref mut x, _) => x, + E::W => panic!(), + }; + match e { // Don't know that E uses a tag for its discriminant + //~^ ERROR + _ if false => (), + E::V(_, r) => (), + E::W => (), + } + x; +} + +fn indirect_enum_example(mut f: &mut E) { + let x = match *f { + E::V(ref mut x, _) => x, + E::W => panic!(), + }; + match f { // Don't know that E uses a tag for its discriminant + //~^ ERROR + _ if false => (), + E::V(_, r) => (), + E::W => (), + } + x; +} + +fn match_on_muatbly_borrowed_ref(mut p: &bool) { + let r = &mut p; + match *p { // OK, no access at all + _ if false => (), + _ => (), + } + r; +} + +fn match_on_borrowed(mut t: bool) { + let x = &mut t; + match t { + //~^ ERROR + true => (), + false => (), + } + x; +} + +enum Never {} + +fn never_init() { + let n: Never; + match n {} //~ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/match-on-borrowed.stderr b/tests/ui/nll/match-on-borrowed.stderr new file mode 100644 index 000000000..32666529f --- /dev/null +++ b/tests/ui/nll/match-on-borrowed.stderr @@ -0,0 +1,52 @@ +error[E0503]: cannot use `e` because it was mutably borrowed + --> $DIR/match-on-borrowed.rs:47:11 + | +LL | E::V(ref mut x, _) => x, + | --------- borrow of `e.0` occurs here +... +LL | match e { // Don't know that E uses a tag for its discriminant + | ^ use of borrowed `e.0` +... +LL | x; + | - borrow later used here + +error[E0503]: cannot use `*f` because it was mutably borrowed + --> $DIR/match-on-borrowed.rs:61:11 + | +LL | E::V(ref mut x, _) => x, + | --------- borrow of `f.0` occurs here +... +LL | match f { // Don't know that E uses a tag for its discriminant + | ^ use of borrowed `f.0` +... +LL | x; + | - borrow later used here + +error[E0503]: cannot use `t` because it was mutably borrowed + --> $DIR/match-on-borrowed.rs:81:5 + | +LL | let x = &mut t; + | ------ borrow of `t` occurs here +LL | match t { + | ^^^^^^^ use of borrowed `t` +... +LL | x; + | - borrow later used here + +error[E0381]: used binding `n` isn't initialized + --> $DIR/match-on-borrowed.rs:93:11 + | +LL | let n: Never; + | - binding declared here but left uninitialized +LL | match n {} + | ^ `n` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let n: Never = todo!(); + | +++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0381, E0503. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs new file mode 100644 index 000000000..1de32ddf5 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs @@ -0,0 +1,19 @@ +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +struct Foo<'p> { a: String, b: Wrap<'p> } + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + let s = String::from("str"); + let foo = Foo { a: s, b: wrap }; + std::mem::drop(foo.b); + x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] + // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones +} diff --git a/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr new file mode 100644 index 000000000..80e297807 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/maybe-initialized-drop-implicit-fragment-drop.rs:17:5 + | +LL | let wrap = Wrap { p: &mut x }; + | ------ borrow of `x` occurs here +... +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones +LL | } + | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/maybe-initialized-drop-uninitialized.rs b/tests/ui/nll/maybe-initialized-drop-uninitialized.rs new file mode 100644 index 000000000..32e07cd14 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-uninitialized.rs @@ -0,0 +1,18 @@ +// check-pass + +#![allow(warnings)] + +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + std::mem::drop(wrap); + x = 1; // OK, drop is inert +} diff --git a/tests/ui/nll/maybe-initialized-drop-with-fragment.rs b/tests/ui/nll/maybe-initialized-drop-with-fragment.rs new file mode 100644 index 000000000..778212918 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-with-fragment.rs @@ -0,0 +1,20 @@ +#![allow(warnings)] + +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +struct Foo<'p> { a: String, b: Wrap<'p> } + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + let s = String::from("str"); + let foo = Foo { a: s, b: wrap }; + std::mem::drop(foo.a); + x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] +} diff --git a/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr b/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr new file mode 100644 index 000000000..14074472e --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/maybe-initialized-drop-with-fragment.rs:19:5 + | +LL | let wrap = Wrap { p: &mut x }; + | ------ borrow of `x` occurs here +... +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | } + | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs new file mode 100644 index 000000000..b0d6e27a3 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs @@ -0,0 +1,22 @@ +#![allow(warnings)] + +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +struct Foo<'p> { a: String, b: Wrap<'p> } + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + let s = String::from("str"); + let foo = Foo { a: s, b: wrap }; + std::mem::drop(foo.a); + std::mem::drop(foo.b); + x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] + // FIXME ^ This currently errors and it should not. +} diff --git a/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr new file mode 100644 index 000000000..91c0afc1d --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr @@ -0,0 +1,15 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/maybe-initialized-drop-with-uninitialized-fragments.rs:20:5 + | +LL | let wrap = Wrap { p: &mut x }; + | ------ borrow of `x` occurs here +... +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | // FIXME ^ This currently errors and it should not. +LL | } + | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/maybe-initialized-drop.rs b/tests/ui/nll/maybe-initialized-drop.rs new file mode 100644 index 000000000..44a7ede78 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop.rs @@ -0,0 +1,15 @@ +#![allow(warnings)] + +struct Wrap<'p> { p: &'p mut i32 } + +impl<'p> Drop for Wrap<'p> { + fn drop(&mut self) { + *self.p += 1; + } +} + +fn main() { + let mut x = 0; + let wrap = Wrap { p: &mut x }; + x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506] +} diff --git a/tests/ui/nll/maybe-initialized-drop.stderr b/tests/ui/nll/maybe-initialized-drop.stderr new file mode 100644 index 000000000..9825ba461 --- /dev/null +++ b/tests/ui/nll/maybe-initialized-drop.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/maybe-initialized-drop.rs:14:5 + | +LL | let wrap = Wrap { p: &mut x }; + | ------ borrow of `x` occurs here +LL | x = 1; + | ^^^^^ assignment to borrowed `x` occurs here +LL | } + | - borrow might be used here, when `wrap` is dropped and runs the `Drop` code for type `Wrap` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/nll/mir_check_cast_closure.rs b/tests/ui/nll/mir_check_cast_closure.rs new file mode 100644 index 000000000..4aebcfdb4 --- /dev/null +++ b/tests/ui/nll/mir_check_cast_closure.rs @@ -0,0 +1,9 @@ +#![allow(dead_code)] + +fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 { + let g: fn(_, _) -> _ = |_x, y| y; + g + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/mir_check_cast_closure.stderr b/tests/ui/nll/mir_check_cast_closure.stderr new file mode 100644 index 000000000..72d99aad9 --- /dev/null +++ b/tests/ui/nll/mir_check_cast_closure.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/mir_check_cast_closure.rs:5:5 + | +LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let g: fn(_, _) -> _ = |_x, y| y; +LL | g + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/nll/mir_check_cast_reify.rs b/tests/ui/nll/mir_check_cast_reify.rs new file mode 100644 index 000000000..951459911 --- /dev/null +++ b/tests/ui/nll/mir_check_cast_reify.rs @@ -0,0 +1,39 @@ +#![allow(dead_code)] + +// Test that we relate the type of the fn type to the type of the fn +// ptr when doing a `ReifyFnPointer` cast. +// +// This test is a bit tortured, let me explain: +// + +// The `where 'a: 'a` clause here ensures that `'a` is early bound, +// which is needed below to ensure that this test hits the path we are +// concerned with. +fn foo<'a>(x: &'a u32) -> &'a u32 +where + 'a: 'a, +{ + panic!() +} + +fn bar<'a>(x: &'a u32) -> &'static u32 { + // Here, the type of `foo` is `typeof(foo::<'x>)` for some fresh variable `'x`. + // During NLL region analysis, this will get renumbered to `typeof(foo::<'?0>)` + // where `'?0` is a new region variable. + // + // (Note that if `'a` on `foo` were late-bound, the type would be + // `typeof(foo)`, which would interact differently with because + // the renumbering later.) + // + // This type is then coerced to a fn type `fn(&'?1 u32) -> &'?2 + // u32`. Here, the `'?1` and `'?2` will have been created during + // the NLL region renumbering. + // + // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2` + // as part of checking the `ReifyFnPointer`. + let f: fn(_) -> _ = foo; + f(x) + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/mir_check_cast_reify.stderr b/tests/ui/nll/mir_check_cast_reify.stderr new file mode 100644 index 000000000..9be2670fe --- /dev/null +++ b/tests/ui/nll/mir_check_cast_reify.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/mir_check_cast_reify.rs:35:5 + | +LL | fn bar<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | f(x) + | ^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/mir_check_cast_unsafe_fn.rs b/tests/ui/nll/mir_check_cast_unsafe_fn.rs new file mode 100644 index 000000000..8f55bedfb --- /dev/null +++ b/tests/ui/nll/mir_check_cast_unsafe_fn.rs @@ -0,0 +1,11 @@ +#![allow(dead_code)] + +fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { + // Here the NLL checker must relate the types in `f` to the types + // in `g`. These are related via the `UnsafeFnPointer` cast. + let g: unsafe fn(_) -> _ = f; + unsafe { g(input) } + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/mir_check_cast_unsafe_fn.stderr b/tests/ui/nll/mir_check_cast_unsafe_fn.stderr new file mode 100644 index 000000000..321d17ba6 --- /dev/null +++ b/tests/ui/nll/mir_check_cast_unsafe_fn.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/mir_check_cast_unsafe_fn.rs:7:14 + | +LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | unsafe { g(input) } + | ^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/mir_check_cast_unsize.rs b/tests/ui/nll/mir_check_cast_unsize.rs new file mode 100644 index 000000000..f6c100ab6 --- /dev/null +++ b/tests/ui/nll/mir_check_cast_unsize.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] + +use std::fmt::Debug; + +fn bar<'a>(x: &'a u32) -> &'static dyn Debug { + x + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/mir_check_cast_unsize.stderr b/tests/ui/nll/mir_check_cast_unsize.stderr new file mode 100644 index 000000000..1cd2579e4 --- /dev/null +++ b/tests/ui/nll/mir_check_cast_unsize.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/mir_check_cast_unsize.rs:6:5 + | +LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug { + | -- lifetime `'a` defined here +LL | x + | ^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound + | +LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug + 'a { + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/nll/move-errors.rs b/tests/ui/nll/move-errors.rs new file mode 100644 index 000000000..e0fcd6250 --- /dev/null +++ b/tests/ui/nll/move-errors.rs @@ -0,0 +1,117 @@ +struct A(String); +struct C(D); + +fn suggest_remove_deref() { + let a = &A("".to_string()); + let b = *a; + //~^ ERROR +} + +fn suggest_borrow() { + let a = [A("".to_string())]; + let b = a[0]; + //~^ ERROR +} + +fn suggest_borrow2() { + let mut a = A("".to_string()); + let r = &&mut a; + let s = **r; + //~^ ERROR +} + +fn suggest_borrow3() { + use std::rc::Rc; + let mut a = A("".to_string()); + let r = Rc::new(a); + let s = *r; + //~^ ERROR +} + +fn suggest_borrow4() { + let a = [A("".to_string())][0]; + //~^ ERROR +} + +fn suggest_borrow5() { + let a = &A("".to_string()); + let A(s) = *a; + //~^ ERROR +} + +fn suggest_ref() { + let c = C(D(String::new())); + let C(D(s)) = c; + //~^ ERROR +} + +fn suggest_nothing() { + let a = &A("".to_string()); + let b; + b = *a; + //~^ ERROR +} + +enum B { + V(String), + U(D), +} + +struct D(String); + +impl Drop for D { + fn drop(&mut self) {} +} + +struct F(String, String); + +impl Drop for F { + fn drop(&mut self) {} +} + +fn probably_suggest_borrow() { + let x = [B::V(String::new())]; + match x[0] { + //~^ ERROR + B::U(d) => (), + B::V(s) => (), + } +} + +fn have_to_suggest_ref() { + let x = B::V(String::new()); + match x { + //~^ ERROR + B::V(s) => drop(s), + B::U(D(s)) => (), + }; +} + +fn two_separate_errors() { + let x = (D(String::new()), &String::new()); + match x { + //~^ ERROR + //~^^ ERROR + (D(s), &t) => (), + _ => (), + } +} + +fn have_to_suggest_double_ref() { + let x = F(String::new(), String::new()); + match x { + //~^ ERROR + F(s, mut t) => (), + _ => (), + } +} + +fn double_binding(x: &Result) { + match *x { + //~^ ERROR + Ok(s) | Err(s) => (), + } +} + +fn main() { +} diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr new file mode 100644 index 000000000..58b8aa31d --- /dev/null +++ b/tests/ui/nll/move-errors.stderr @@ -0,0 +1,210 @@ +error[E0507]: cannot move out of `*a` which is behind a shared reference + --> $DIR/move-errors.rs:6:13 + | +LL | let b = *a; + | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let b = *a; +LL + let b = a; + | + +error[E0508]: cannot move out of type `[A; 1]`, a non-copy array + --> $DIR/move-errors.rs:12:13 + | +LL | let b = a[0]; + | ^^^^ + | | + | cannot move out of here + | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let b = &a[0]; + | + + +error[E0507]: cannot move out of `**r` which is behind a shared reference + --> $DIR/move-errors.rs:19:13 + | +LL | let s = **r; + | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let s = **r; +LL + let s = *r; + | + +error[E0507]: cannot move out of an `Rc` + --> $DIR/move-errors.rs:27:13 + | +LL | let s = *r; + | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let s = *r; +LL + let s = r; + | + +error[E0508]: cannot move out of type `[A; 1]`, a non-copy array + --> $DIR/move-errors.rs:32:13 + | +LL | let a = [A("".to_string())][0]; + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because value has type `A`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &[A("".to_string())][0]; + | + + +error[E0507]: cannot move out of `a` which is behind a shared reference + --> $DIR/move-errors.rs:38:16 + | +LL | let A(s) = *a; + | - ^^ + | | + | data moved here + | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let A(s) = *a; +LL + let A(s) = a; + | + +error[E0509]: cannot move out of type `D`, which implements the `Drop` trait + --> $DIR/move-errors.rs:44:19 + | +LL | let C(D(s)) = c; + | - ^ cannot move out of here + | | + | data moved here + | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let C(D(ref s)) = c; + | +++ + +error[E0507]: cannot move out of `*a` which is behind a shared reference + --> $DIR/move-errors.rs:51:9 + | +LL | b = *a; + | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[B; 1]`, a non-copy array + --> $DIR/move-errors.rs:74:11 + | +LL | match x[0] { + | ^^^^ cannot move out of here +LL | +LL | B::U(d) => (), + | - data moved here +LL | B::V(s) => (), + | - ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing here + | +LL | match &x[0] { + | + + +error[E0509]: cannot move out of type `D`, which implements the `Drop` trait + --> $DIR/move-errors.rs:83:11 + | +LL | match x { + | ^ cannot move out of here +... +LL | B::U(D(s)) => (), + | - + | | + | data moved here + | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | B::U(D(ref s)) => (), + | +++ + +error[E0509]: cannot move out of type `D`, which implements the `Drop` trait + --> $DIR/move-errors.rs:92:11 + | +LL | match x { + | ^ cannot move out of here +... +LL | (D(s), &t) => (), + | - + | | + | data moved here + | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (D(ref s), &t) => (), + | +++ + +error[E0507]: cannot move out of `*x.1` which is behind a shared reference + --> $DIR/move-errors.rs:92:11 + | +LL | match x { + | ^ +... +LL | (D(s), &t) => (), + | - + | | + | data moved here + | move occurs because `t` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (D(s), &ref t) => (), + | +++ + +error[E0509]: cannot move out of type `F`, which implements the `Drop` trait + --> $DIR/move-errors.rs:102:11 + | +LL | match x { + | ^ cannot move out of here +LL | +LL | F(s, mut t) => (), + | - ----- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | F(ref s, mut t) => (), + | +++ +help: consider borrowing the pattern binding + | +LL | F(s, ref mut t) => (), + | +++ + +error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference + --> $DIR/move-errors.rs:110:11 + | +LL | match *x { + | ^^ +LL | +LL | Ok(s) | Err(s) => (), + | - + | | + | data moved here + | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *x { +LL + match x { + | + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0507, E0508, E0509. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/nll/move-subpaths-moves-root.rs b/tests/ui/nll/move-subpaths-moves-root.rs new file mode 100644 index 000000000..d266c6bb6 --- /dev/null +++ b/tests/ui/nll/move-subpaths-moves-root.rs @@ -0,0 +1,5 @@ +fn main() { + let x = (vec![1, 2, 3], ); + drop(x.0); + drop(x); //~ ERROR use of partially moved value +} diff --git a/tests/ui/nll/move-subpaths-moves-root.stderr b/tests/ui/nll/move-subpaths-moves-root.stderr new file mode 100644 index 000000000..ae9287f92 --- /dev/null +++ b/tests/ui/nll/move-subpaths-moves-root.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of partially moved value: `x` + --> $DIR/move-subpaths-moves-root.rs:4:10 + | +LL | drop(x.0); + | --- value partially moved here +LL | drop(x); + | ^ value used here after partial move + | + = note: partial move occurs because `x.0` has type `Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/mutating_references.rs b/tests/ui/nll/mutating_references.rs new file mode 100644 index 000000000..eb46b30b6 --- /dev/null +++ b/tests/ui/nll/mutating_references.rs @@ -0,0 +1,24 @@ +// run-pass + +struct List { + value: T, + next: Option>>, +} + +fn to_refs(mut list: &mut List) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list.value); + if let Some(n) = list.next.as_mut() { + list = n; + } else { + return result; + } + } +} + +fn main() { + let mut list = List { value: 1, next: None }; + let vec = to_refs(&mut list); + assert_eq!(vec![&mut 1], vec); +} diff --git a/tests/ui/nll/normalization-bounds-error.rs b/tests/ui/nll/normalization-bounds-error.rs new file mode 100644 index 000000000..b6cfcd987 --- /dev/null +++ b/tests/ui/nll/normalization-bounds-error.rs @@ -0,0 +1,15 @@ +// Check that we error when a bound from the impl is not satisfied when +// normalizing an associated type. + +trait Visitor<'d> { + type Value; +} + +impl<'a, 'd: 'a> Visitor<'d> for &'a () { + type Value = (); +} + +fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} +//~^ ERROR + +fn main() {} diff --git a/tests/ui/nll/normalization-bounds-error.stderr b/tests/ui/nll/normalization-bounds-error.stderr new file mode 100644 index 000000000..0fc3670d6 --- /dev/null +++ b/tests/ui/nll/normalization-bounds-error.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements + --> $DIR/normalization-bounds-error.rs:12:31 + | +LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'d` as defined here... + --> $DIR/normalization-bounds-error.rs:12:14 + | +LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} + | ^^ +note: ...but the lifetime must also be valid for the lifetime `'a` as defined here... + --> $DIR/normalization-bounds-error.rs:12:18 + | +LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} + | ^^ +note: ...so that the types are compatible + --> $DIR/normalization-bounds-error.rs:12:31 + | +LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `Visitor<'d>` + found `Visitor<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/nll/normalization-bounds.rs b/tests/ui/nll/normalization-bounds.rs new file mode 100644 index 000000000..bb6d981e0 --- /dev/null +++ b/tests/ui/nll/normalization-bounds.rs @@ -0,0 +1,15 @@ +// Check that lifetime bounds get checked the right way around with NLL enabled. + +// check-pass + +trait Visitor<'d> { + type Value; +} + +impl<'a, 'd: 'a> Visitor<'d> for &'a () { + type Value = (); +} + +fn visit_seq<'d: 'a, 'a>() -> <&'a () as Visitor<'d>>::Value {} + +fn main() {} diff --git a/tests/ui/nll/outlives-suggestion-more.rs b/tests/ui/nll/outlives-suggestion-more.rs new file mode 100644 index 000000000..2e1359fe5 --- /dev/null +++ b/tests/ui/nll/outlives-suggestion-more.rs @@ -0,0 +1,26 @@ +// Test the more elaborate outlives suggestions. + +// Should suggest: 'a: 'c, 'b: 'd +fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) { + (x, y) //~ERROR lifetime may not live long enough + //~^ERROR lifetime may not live long enough +} + +// Should suggest: 'a: 'c and use 'static instead of 'b +fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) { + (x, y) //~ERROR lifetime may not live long enough + //~^ERROR lifetime may not live long enough +} + +// Should suggest: 'a and 'b are the same and use 'static instead of 'c +fn foo3<'a, 'b, 'c, 'd, 'e>( + x: &'a usize, + y: &'b usize, + z: &'c usize, +) -> (&'b usize, &'a usize, &'static usize) { + (x, y, z) //~ERROR lifetime may not live long enough + //~^ERROR lifetime may not live long enough + //~^^ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/outlives-suggestion-more.stderr b/tests/ui/nll/outlives-suggestion-more.stderr new file mode 100644 index 000000000..c8c604b5b --- /dev/null +++ b/tests/ui/nll/outlives-suggestion-more.stderr @@ -0,0 +1,96 @@ +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:5:5 + | +LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'c` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:5:5 + | +LL | fn foo1<'a, 'b, 'c, 'd>(x: &'a usize, y: &'b usize) -> (&'c usize, &'d usize) { + | -- -- lifetime `'d` defined here + | | + | lifetime `'b` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'d` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'd` + +help: the following changes may resolve your lifetime errors + | + = help: add bound `'a: 'c` + = help: add bound `'b: 'd` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:11:5 + | +LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'c` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:11:5 + | +LL | fn foo2<'a, 'b, 'c>(x: &'a usize, y: &'b usize) -> (&'c usize, &'static usize) { + | -- lifetime `'b` defined here +LL | (x, y) + | ^^^^^^ returning this value requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: add bound `'a: 'c` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:21:5 + | +LL | fn foo3<'a, 'b, 'c, 'd, 'e>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (x, y, z) + | ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:21:5 + | +LL | fn foo3<'a, 'b, 'c, 'd, 'e>( + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (x, y, z) + | ^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-more.rs:21:5 + | +LL | fn foo3<'a, 'b, 'c, 'd, 'e>( + | -- lifetime `'c` defined here +... +LL | (x, y, z) + | ^^^^^^^^^ returning this value requires that `'c` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: `'a` and `'b` must be the same: replace one with the other + = help: replace `'c` with `'static` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/nll/outlives-suggestion-simple.polonius.stderr b/tests/ui/nll/outlives-suggestion-simple.polonius.stderr new file mode 100644 index 000000000..c00288f2e --- /dev/null +++ b/tests/ui/nll/outlives-suggestion-simple.polonius.stderr @@ -0,0 +1,124 @@ +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:6:5 + | +LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x + | ^ returning this value requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:10:5 + | +LL | fn foo2<'a>(x: &'a usize) -> &'static usize { + | -- lifetime `'a` defined here +LL | x + | ^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:14:5 + | +LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:14:5 + | +LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:22:5 + | +LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (x, x) + | ^^^^^^ returning this value requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:22:5 + | +LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +... +LL | (x, x) + | ^^^^^^ returning this value requires that `'a` must outlive `'c` + | + = help: consider adding the following bound: `'a: 'c` + +help: add bound `'a: 'b + 'c` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:31:9 + | +LL | pub fn foo<'a>(x: &'a usize) -> Self { + | -- lifetime `'a` defined here +LL | Foo { x } + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:41:9 + | +LL | impl<'a> Bar<'a> { + | -- lifetime `'a` defined here +LL | pub fn get<'b>(&self) -> &'b usize { + | -- lifetime `'b` defined here +LL | self.x + | ^^^^^^ returning this value requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:52:9 + | +LL | impl<'a> Baz<'a> { + | -- lifetime `'a` defined here +LL | fn get<'b>(&'b self) -> &'a i32 { + | -- lifetime `'b` defined here +LL | self.x + | ^^^^^^ returning this value requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/outlives-suggestion-simple.rs:73:9 + | +LL | fn get_bar(&self) -> Bar2 { + | ----- + | | + | `self` declared here, outside of the associated function body + | `self` is a reference that is only valid in the associated function body +LL | Bar2::new(&self) + | ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/outlives-suggestion-simple.rs b/tests/ui/nll/outlives-suggestion-simple.rs new file mode 100644 index 000000000..2a5c31e3a --- /dev/null +++ b/tests/ui/nll/outlives-suggestion-simple.rs @@ -0,0 +1,75 @@ +// Test the simplest of outlives suggestions. + +fn foo1<'a, 'b>(x: &'a usize) -> &'b usize { + x //~ERROR lifetime may not live long enough +} + +fn foo2<'a>(x: &'a usize) -> &'static usize { + x //~ERROR lifetime may not live long enough +} + +fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { + (x, y) //~ERROR lifetime may not live long enough + //~^ERROR lifetime may not live long enough +} + +fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { + // FIXME: ideally, we suggest 'a: 'b + 'c, but as of today (may 04, 2019), the null error + // reporting stops after the first error in a MIR def so as not to produce too many errors, so + // currently we only report 'a: 'b. The user would then re-run and get another error. + (x, x) //~ERROR lifetime may not live long enough +} + +struct Foo<'a> { + x: &'a usize, +} + +impl Foo<'static> { + pub fn foo<'a>(x: &'a usize) -> Self { + Foo { x } //~ERROR lifetime may not live long enough + } +} + +struct Bar<'a> { + x: &'a usize, +} + +impl<'a> Bar<'a> { + pub fn get<'b>(&self) -> &'b usize { + self.x //~ERROR lifetime may not live long enough + } +} + +// source: https://stackoverflow.com/questions/41417057/why-do-i-get-a-lifetime-error-when-i-use-a-mutable-reference-in-a-struct-instead +struct Baz<'a> { + x: &'a mut i32, +} + +impl<'a> Baz<'a> { + fn get<'b>(&'b self) -> &'a i32 { + self.x //~ERROR lifetime may not live long enough + } +} + +// source: https://stackoverflow.com/questions/41204134/rust-lifetime-error +struct Bar2<'a> { + bar: &'a str, +} +impl<'a> Bar2<'a> { + fn new(foo: &'a Foo2<'a>) -> Bar2<'a> { + Bar2 { bar: foo.raw } + } +} + +pub struct Foo2<'a> { + raw: &'a str, + cell: std::cell::Cell<&'a str>, +} +impl<'a> Foo2<'a> { + // should not produce outlives suggestions to name 'self + fn get_bar(&self) -> Bar2 { + Bar2::new(&self) //~ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/nll/outlives-suggestion-simple.stderr b/tests/ui/nll/outlives-suggestion-simple.stderr new file mode 100644 index 000000000..a8368c494 --- /dev/null +++ b/tests/ui/nll/outlives-suggestion-simple.stderr @@ -0,0 +1,104 @@ +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:4:5 + | +LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:8:5 + | +LL | fn foo2<'a>(x: &'a usize) -> &'static usize { + | -- lifetime `'a` defined here +LL | x + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:12:5 + | +LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:12:5 + | +LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | (x, y) + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:20:5 + | +LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | (x, x) + | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:29:9 + | +LL | pub fn foo<'a>(x: &'a usize) -> Self { + | -- lifetime `'a` defined here +LL | Foo { x } + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:39:9 + | +LL | impl<'a> Bar<'a> { + | -- lifetime `'a` defined here +LL | pub fn get<'b>(&self) -> &'b usize { + | -- lifetime `'b` defined here +LL | self.x + | ^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:50:9 + | +LL | impl<'a> Baz<'a> { + | -- lifetime `'a` defined here +LL | fn get<'b>(&'b self) -> &'a i32 { + | -- lifetime `'b` defined here +LL | self.x + | ^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/outlives-suggestion-simple.rs:71:9 + | +LL | impl<'a> Foo2<'a> { + | -- lifetime `'a` defined here +LL | // should not produce outlives suggestions to name 'self +LL | fn get_bar(&self) -> Bar2 { + | - let's call the lifetime of this reference `'1` +LL | Bar2::new(&self) + | ^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/nll/polonius/assignment-kills-loans.rs b/tests/ui/nll/polonius/assignment-kills-loans.rs new file mode 100644 index 000000000..696bf61ce --- /dev/null +++ b/tests/ui/nll/polonius/assignment-kills-loans.rs @@ -0,0 +1,87 @@ +#![allow(dead_code)] + +// This tests the various kinds of assignments there are. Polonius used to generate `killed` +// facts only on simple assignments, but not projections, incorrectly causing errors to be emitted +// for code accepted by NLL. They are all variations from example code in the NLL RFC. + +// check-pass +// compile-flags: -Z polonius + +struct List { + value: T, + next: Option>>, +} + +// Assignment to a local: the `list` assignment should clear the existing +// borrows of `list.value` and `list.next` +fn assignment_to_local(mut list: &mut List) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list.value); + if let Some(n) = list.next.as_mut() { + list = n; + } else { + return result; + } + } +} + +// Assignment to a deref projection: the `*list` assignment should clear the existing +// borrows of `list.value` and `list.next` +fn assignment_to_deref_projection(mut list: Box<&mut List>) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list.value); + if let Some(n) = list.next.as_mut() { + *list = n; + } else { + return result; + } + } +} + +// Assignment to a field projection: the `list.0` assignment should clear the existing +// borrows of `list.0.value` and `list.0.next` +fn assignment_to_field_projection(mut list: (&mut List,)) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list.0.value); + if let Some(n) = list.0.next.as_mut() { + list.0 = n; + } else { + return result; + } + } +} + +// Assignment to a deref field projection: the `*list.0` assignment should clear the existing +// borrows of `list.0.value` and `list.0.next` +fn assignment_to_deref_field_projection(mut list: (Box<&mut List>,)) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut list.0.value); + if let Some(n) = list.0.next.as_mut() { + *list.0 = n; + } else { + return result; + } + } +} + +// Similar to `assignment_to_deref_field_projection` but through a longer projection chain +fn assignment_through_projection_chain( + mut list: (((((Box<&mut List>,),),),),), +) -> Vec<&mut T> { + let mut result = vec![]; + loop { + result.push(&mut ((((list.0).0).0).0).0.value); + if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { + *((((list.0).0).0).0).0 = n; + } else { + return result; + } + } +} + +fn main() { +} diff --git a/tests/ui/nll/polonius/assignment-to-differing-field.rs b/tests/ui/nll/polonius/assignment-to-differing-field.rs new file mode 100644 index 000000000..7ec3b9049 --- /dev/null +++ b/tests/ui/nll/polonius/assignment-to-differing-field.rs @@ -0,0 +1,49 @@ +#![allow(dead_code)] + +// Compared to `assignment-kills-loans.rs`, we check here +// that we do not kill too many borrows. Assignments to the `.1` +// field projections should leave the borrows on `.0` intact. + +// compile-flags: -Z polonius + +struct List { + value: T, + next: Option>>, +} + + +fn assignment_to_field_projection<'a, T>( + mut list: (&'a mut List, &'a mut List), +) -> Vec<&'a mut T> { + let mut result = vec![]; + loop { + result.push(&mut (list.0).value); + //~^ ERROR cannot borrow `list.0.value` as mutable + + if let Some(n) = (list.0).next.as_mut() { + //~^ ERROR cannot borrow `list.0.next` as mutable + list.1 = n; + } else { + return result; + } + } +} + +fn assignment_through_projection_chain<'a, T>( + mut list: (((((Box<&'a mut List>, Box<&'a mut List>),),),),), +) -> Vec<&'a mut T> { + let mut result = vec![]; + loop { + result.push(&mut ((((list.0).0).0).0).0.value); + //~^ ERROR cannot borrow `list.0.0.0.0.0.value` as mutable + + if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { + //~^ ERROR cannot borrow `list.0.0.0.0.0.next` as mutable + *((((list.0).0).0).0).1 = n; + } else { + return result; + } + } +} + +fn main() {} diff --git a/tests/ui/nll/polonius/assignment-to-differing-field.stderr b/tests/ui/nll/polonius/assignment-to-differing-field.stderr new file mode 100644 index 000000000..afa1b9344 --- /dev/null +++ b/tests/ui/nll/polonius/assignment-to-differing-field.stderr @@ -0,0 +1,51 @@ +error[E0499]: cannot borrow `list.0.value` as mutable more than once at a time + --> $DIR/assignment-to-differing-field.rs:20:21 + | +LL | fn assignment_to_field_projection<'a, T>( + | -- lifetime `'a` defined here +... +LL | result.push(&mut (list.0).value); + | ^^^^^^^^^^^^^^^^^^^ `list.0.value` was mutably borrowed here in the previous iteration of the loop +... +LL | return result; + | ------ returning this value requires that `list.0.value` is borrowed for `'a` + +error[E0499]: cannot borrow `list.0.next` as mutable more than once at a time + --> $DIR/assignment-to-differing-field.rs:23:26 + | +LL | fn assignment_to_field_projection<'a, T>( + | -- lifetime `'a` defined here +... +LL | if let Some(n) = (list.0).next.as_mut() { + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `list.0.next` was mutably borrowed here in the previous iteration of the loop + | argument requires that `list.0.next` is borrowed for `'a` + +error[E0499]: cannot borrow `list.0.0.0.0.0.value` as mutable more than once at a time + --> $DIR/assignment-to-differing-field.rs:37:21 + | +LL | fn assignment_through_projection_chain<'a, T>( + | -- lifetime `'a` defined here +... +LL | result.push(&mut ((((list.0).0).0).0).0.value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `list.0.0.0.0.0.value` was mutably borrowed here in the previous iteration of the loop +... +LL | return result; + | ------ returning this value requires that `list.0.0.0.0.0.value` is borrowed for `'a` + +error[E0499]: cannot borrow `list.0.0.0.0.0.next` as mutable more than once at a time + --> $DIR/assignment-to-differing-field.rs:40:26 + | +LL | fn assignment_through_projection_chain<'a, T>( + | -- lifetime `'a` defined here +... +LL | if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop + | argument requires that `list.0.0.0.0.0.next` is borrowed for `'a` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/call-kills-loans.rs b/tests/ui/nll/polonius/call-kills-loans.rs new file mode 100644 index 000000000..f430e9211 --- /dev/null +++ b/tests/ui/nll/polonius/call-kills-loans.rs @@ -0,0 +1,23 @@ +// `Call` terminators can write to a local which has existing loans +// and those need to be killed like a regular assignment to a local. +// This is a simplified version of issue 47680, is correctly accepted +// by NLL but was incorrectly rejected by Polonius because of these +// missing `killed` facts. + +// check-pass +// compile-flags: -Z polonius + +struct Thing; + +impl Thing { + fn next(&mut self) -> &mut Self { unimplemented!() } +} + +fn main() { + let mut temp = &mut Thing; + + loop { + let v = temp.next(); + temp = v; // accepted by NLL, was incorrectly rejected by Polonius + } +} diff --git a/tests/ui/nll/polonius/issue-46589.rs b/tests/ui/nll/polonius/issue-46589.rs new file mode 100644 index 000000000..648280a1d --- /dev/null +++ b/tests/ui/nll/polonius/issue-46589.rs @@ -0,0 +1,31 @@ +// This test is a copy of `ui/nll/issue-46589.rs` which fails in NLL but succeeds in Polonius. +// As we can't have a test here which conditionally passes depending on a test +// revision/compile-flags. We ensure here that it passes in Polonius mode. + +// check-pass +// compile-flags: -Z polonius + +struct Foo; + +impl Foo { + fn get_self(&mut self) -> Option<&mut Self> { + Some(self) + } + + fn new_self(&mut self) -> &mut Self { + self + } + + fn trigger_bug(&mut self) { + let other = &mut (&mut *self); + + *other = match (*other).get_self() { + Some(s) => s, + None => (*other).new_self() + }; + + let c = other; + } +} + +fn main() {} diff --git a/tests/ui/nll/polonius/polonius-smoke-test.rs b/tests/ui/nll/polonius/polonius-smoke-test.rs new file mode 100644 index 000000000..c4344af71 --- /dev/null +++ b/tests/ui/nll/polonius/polonius-smoke-test.rs @@ -0,0 +1,46 @@ +// Check that Polonius borrow check works for simple cases. +// compile-flags: -Z polonius + +pub fn return_ref_to_local() -> &'static i32 { + let x = 0; + &x //~ ERROR +} + +pub fn use_while_mut() { + let mut x = 0; + let y = &mut x; + let z = x; //~ ERROR + let w = y; +} + +pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 { + let y = &mut *x; + let z = x; //~ ERROR + y +} + +// Cases like this are why we have Polonius. +pub fn position_dependent_outlives(x: &mut i32, cond: bool) -> &mut i32 { + let y = &mut *x; + if cond { + return y; + } else { + *x = 0; + return x; + } +} + +fn foo<'a, 'b>(p: &'b &'a mut usize) -> &'b usize { + p +} + +// Check that we create constraints for well-formedness of function arguments +fn well_formed_function_inputs() { + let s = &mut 1; + let r = &mut *s; + let tmp = foo(&r); + s; //~ ERROR + tmp; +} + +fn main() {} diff --git a/tests/ui/nll/polonius/polonius-smoke-test.stderr b/tests/ui/nll/polonius/polonius-smoke-test.stderr new file mode 100644 index 000000000..fa1a6a9c9 --- /dev/null +++ b/tests/ui/nll/polonius/polonius-smoke-test.stderr @@ -0,0 +1,43 @@ +error[E0515]: cannot return reference to local variable `x` + --> $DIR/polonius-smoke-test.rs:6:5 + | +LL | &x + | ^^ returns a reference to data owned by the current function + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/polonius-smoke-test.rs:12:13 + | +LL | let y = &mut x; + | ------ borrow of `x` occurs here +LL | let z = x; + | ^ use of borrowed `x` +LL | let w = y; + | - borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/polonius-smoke-test.rs:18:13 + | +LL | pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 { + | - let's call the lifetime of this reference `'1` +LL | let y = &mut *x; + | ------- borrow of `*x` occurs here +LL | let z = x; + | ^ move out of `x` occurs here +LL | y + | - returning this value requires that `*x` is borrowed for `'1` + +error[E0505]: cannot move out of `s` because it is borrowed + --> $DIR/polonius-smoke-test.rs:42:5 + | +LL | let r = &mut *s; + | ------- borrow of `*s` occurs here +LL | let tmp = foo(&r); +LL | s; + | ^ move out of `s` occurs here +LL | tmp; + | --- borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0503, E0505, E0515. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/polonius/storagedead-kills-loans.rs b/tests/ui/nll/polonius/storagedead-kills-loans.rs new file mode 100644 index 000000000..669e077de --- /dev/null +++ b/tests/ui/nll/polonius/storagedead-kills-loans.rs @@ -0,0 +1,28 @@ +// Whenever a `StorageDead` MIR statement destroys a value `x`, +// we should kill all loans of `x`. This is extracted from `rand 0.4.6`, +// is correctly accepted by NLL but was incorrectly rejected by +// Polonius because of these missing `killed` facts. + +// check-pass +// compile-flags: -Z polonius + +use std::{io, mem}; +use std::io::Read; + +#[allow(dead_code)] +fn fill(r: &mut dyn Read, mut buf: &mut [u8]) -> io::Result<()> { + while buf.len() > 0 { + match r.read(buf).unwrap() { + 0 => return Err(io::Error::new(io::ErrorKind::Other, + "end of file reached")), + n => buf = &mut mem::replace(&mut buf, &mut [])[n..], + // ^- Polonius had multiple errors on the previous line (where NLL has none) + // as it didn't know `buf` was killed here, and would + // incorrectly reject both the borrow expression, and the assignment. + } + } + Ok(()) +} + +fn main() { +} diff --git a/tests/ui/nll/polonius/subset-relations.rs b/tests/ui/nll/polonius/subset-relations.rs new file mode 100644 index 000000000..f223ab177 --- /dev/null +++ b/tests/ui/nll/polonius/subset-relations.rs @@ -0,0 +1,29 @@ +// Checks that Polonius can compute cases of universal regions errors: +// "illegal subset relation errors", cases where analysis finds that +// two free regions outlive each other, without any evidence that this +// relation holds. + +// compile-flags: -Z polonius + +// returning `y` requires that `'b: 'a`, but it's not known to be true +fn missing_subset<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 { + y //~ ERROR +} + +// `'b: 'a` is explicitly declared +fn valid_subset<'a, 'b: 'a>(x: &'a u32, y: &'b u32) -> &'a u32 { + y +} + +// because of `x`, it is implied that `'b: 'a` holds +fn implied_bounds_subset<'a, 'b>(x: &'a &'b mut u32) -> &'a u32 { + x +} + +// `'b: 'a` is declared, and `'a: 'c` is known via implied bounds: +// `'b: 'c` is therefore known to hold transitively +fn transitively_valid_subset<'a, 'b: 'a, 'c>(x: &'c &'a u32, y: &'b u32) -> &'c u32 { + y +} + +fn main() {} diff --git a/tests/ui/nll/polonius/subset-relations.stderr b/tests/ui/nll/polonius/subset-relations.stderr new file mode 100644 index 000000000..6df5563ea --- /dev/null +++ b/tests/ui/nll/polonius/subset-relations.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/subset-relations.rs:10:5 + | +LL | fn missing_subset<'a, 'b>(x: &'a u32, y: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | y + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/nll/process_or_insert_default.rs b/tests/ui/nll/process_or_insert_default.rs new file mode 100644 index 000000000..84ac9bbd0 --- /dev/null +++ b/tests/ui/nll/process_or_insert_default.rs @@ -0,0 +1,27 @@ +// run-pass + +use std::collections::HashMap; + +fn process_or_insert_default(map: &mut HashMap, key: usize) { + match map.get_mut(&key) { + Some(value) => { + process(value); + } + None => { + map.insert(key, "".to_string()); + } + } +} + +fn process(x: &str) { + assert_eq!(x, "Hello, world"); +} + +fn main() { + let map = &mut HashMap::new(); + map.insert(22, format!("Hello, world")); + map.insert(44, format!("Goodbye, world")); + process_or_insert_default(map, 22); + process_or_insert_default(map, 66); + assert_eq!(map[&66], ""); +} diff --git a/tests/ui/nll/projection-return.rs b/tests/ui/nll/projection-return.rs new file mode 100644 index 000000000..be141339a --- /dev/null +++ b/tests/ui/nll/projection-return.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(rustc_attrs)] + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = u32; +} + +fn foo() -> <() as Foo>::Bar { + 22 +} + +fn main() { } diff --git a/tests/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/tests/ui/nll/promotable-mutable-zst-doesnt-conflict.rs new file mode 100644 index 000000000..3b06b0db3 --- /dev/null +++ b/tests/ui/nll/promotable-mutable-zst-doesnt-conflict.rs @@ -0,0 +1,11 @@ +// Check that mutable promoted length zero arrays don't check for conflicting +// access + +// check-pass + +pub fn main() { + let mut x: Vec<&[i32; 0]> = Vec::new(); + for _ in 0..10 { + x.push(&[]); + } +} diff --git a/tests/ui/nll/promoted-bounds.rs b/tests/ui/nll/promoted-bounds.rs new file mode 100644 index 000000000..5f95ae13c --- /dev/null +++ b/tests/ui/nll/promoted-bounds.rs @@ -0,0 +1,25 @@ +fn shorten_lifetime<'a, 'b, 'min>(a: &'a i32, b: &'b i32) -> &'min i32 +where + 'a: 'min, + 'b: 'min, +{ + if *a < *b { + &a + } else { + &b + } +} + +fn main() { + let promoted_fn_item_ref = &shorten_lifetime; + + let a = &5; + let ptr = { + let l = 3; + let b = &l; //~ ERROR does not live long enough + let c = promoted_fn_item_ref(a, b); + c + }; + + println!("ptr = {:?}", ptr); +} diff --git a/tests/ui/nll/promoted-bounds.stderr b/tests/ui/nll/promoted-bounds.stderr new file mode 100644 index 000000000..df347f4e7 --- /dev/null +++ b/tests/ui/nll/promoted-bounds.stderr @@ -0,0 +1,15 @@ +error[E0597]: `l` does not live long enough + --> $DIR/promoted-bounds.rs:19:17 + | +LL | let ptr = { + | --- borrow later stored here +LL | let l = 3; +LL | let b = &l; + | ^^ borrowed value does not live long enough +... +LL | }; + | - `l` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/promoted-closure-pair.rs b/tests/ui/nll/promoted-closure-pair.rs new file mode 100644 index 000000000..cc9f17fd4 --- /dev/null +++ b/tests/ui/nll/promoted-closure-pair.rs @@ -0,0 +1,10 @@ +// Check that we handle multiple closures in the same promoted constant. + +fn foo() -> &'static i32 { + let z = 0; + let p = &(|y| y, |y| y); + p.0(&z); + p.1(&z) //~ ERROR cannot return +} + +fn main() {} diff --git a/tests/ui/nll/promoted-closure-pair.stderr b/tests/ui/nll/promoted-closure-pair.stderr new file mode 100644 index 000000000..000bdf858 --- /dev/null +++ b/tests/ui/nll/promoted-closure-pair.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `z` + --> $DIR/promoted-closure-pair.rs:7:5 + | +LL | p.1(&z) + | ^^^^--^ + | | | + | | `z` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/promoted-liveness.rs b/tests/ui/nll/promoted-liveness.rs new file mode 100644 index 000000000..e5a8e1e5c --- /dev/null +++ b/tests/ui/nll/promoted-liveness.rs @@ -0,0 +1,8 @@ +// Test that promoted that have larger mir bodies than their containing function +// don't cause an ICE. + +// check-pass + +fn main() { + &["0", "1", "2", "3", "4", "5", "6", "7"]; +} diff --git a/tests/ui/nll/rc-loop.rs b/tests/ui/nll/rc-loop.rs new file mode 100644 index 000000000..e59303d1f --- /dev/null +++ b/tests/ui/nll/rc-loop.rs @@ -0,0 +1,28 @@ +// run-pass + +// A test for something that NLL enables. It sometimes happens that +// the `while let` pattern makes some borrows from a variable (in this +// case, `x`) that you need in order to compute the next value for +// `x`. The lexical checker makes this very painful. The NLL checker +// does not. + +use std::rc::Rc; + +#[derive(Debug, PartialEq, Eq)] +enum Foo { + Base(usize), + Next(Rc), +} + +fn find_base(mut x: Rc) -> Rc { + while let Foo::Next(n) = &*x { + x = n.clone(); + } + x +} + +fn main() { + let chain = Rc::new(Foo::Next(Rc::new(Foo::Base(44)))); + let base = find_base(chain); + assert_eq!(&*base, &Foo::Base(44)); +} diff --git a/tests/ui/nll/ref-suggestion.rs b/tests/ui/nll/ref-suggestion.rs new file mode 100644 index 000000000..346d118f0 --- /dev/null +++ b/tests/ui/nll/ref-suggestion.rs @@ -0,0 +1,17 @@ +fn main() { + let x = vec![1]; + let y = x; + x; //~ ERROR use of moved value + + let x = vec![1]; + let mut y = x; + x; //~ ERROR use of moved value + + let x = (Some(vec![1]), ()); + + match x { + (Some(y), ()) => {}, + _ => {}, + } + x; //~ ERROR use of partially moved value +} diff --git a/tests/ui/nll/ref-suggestion.stderr b/tests/ui/nll/ref-suggestion.stderr new file mode 100644 index 000000000..b1f5117cb --- /dev/null +++ b/tests/ui/nll/ref-suggestion.stderr @@ -0,0 +1,48 @@ +error[E0382]: use of moved value: `x` + --> $DIR/ref-suggestion.rs:4:5 + | +LL | let x = vec![1]; + | - move occurs because `x` has type `Vec`, which does not implement the `Copy` trait +LL | let y = x; + | - value moved here +LL | x; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let y = x.clone(); + | ++++++++ + +error[E0382]: use of moved value: `x` + --> $DIR/ref-suggestion.rs:8:5 + | +LL | let x = vec![1]; + | - move occurs because `x` has type `Vec`, which does not implement the `Copy` trait +LL | let mut y = x; + | - value moved here +LL | x; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut y = x.clone(); + | ++++++++ + +error[E0382]: use of partially moved value: `x` + --> $DIR/ref-suggestion.rs:16:5 + | +LL | (Some(y), ()) => {}, + | - value partially moved here +... +LL | x; + | ^ value used here after partial move + | + = note: partial move occurs because value has type `Vec`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | (Some(ref y), ()) => {}, + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/reference-carried-through-struct-field.rs b/tests/ui/nll/reference-carried-through-struct-field.rs new file mode 100644 index 000000000..effd61084 --- /dev/null +++ b/tests/ui/nll/reference-carried-through-struct-field.rs @@ -0,0 +1,10 @@ +struct Wrap<'a> { w: &'a mut u32 } + +fn foo() { + let mut x = 22; + let wrapper = Wrap { w: &mut x }; + x += 1; //~ ERROR cannot use `x` because it was mutably borrowed [E0503] + *wrapper.w += 1; +} + +fn main() { } diff --git a/tests/ui/nll/reference-carried-through-struct-field.stderr b/tests/ui/nll/reference-carried-through-struct-field.stderr new file mode 100644 index 000000000..56d878e43 --- /dev/null +++ b/tests/ui/nll/reference-carried-through-struct-field.stderr @@ -0,0 +1,13 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/reference-carried-through-struct-field.rs:6:5 + | +LL | let wrapper = Wrap { w: &mut x }; + | ------ borrow of `x` occurs here +LL | x += 1; + | ^^^^^^ use of borrowed `x` +LL | *wrapper.w += 1; + | --------------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/nll/region-ends-after-if-condition.rs b/tests/ui/nll/region-ends-after-if-condition.rs new file mode 100644 index 000000000..f67de03ca --- /dev/null +++ b/tests/ui/nll/region-ends-after-if-condition.rs @@ -0,0 +1,32 @@ +// Basic test for liveness constraints: the region (`R1`) that appears +// in the type of `p` includes the points after `&v[0]` up to (but not +// including) the call to `use_x`. The `else` branch is not included. + +#![allow(warnings)] +#![feature(rustc_attrs)] + +struct MyStruct { + field: String +} + +fn foo1() { + let mut my_struct = MyStruct { field: format!("Hello") }; + + let value = &my_struct.field; + if value.is_empty() { + my_struct.field.push_str("Hello, world!"); + } +} + +fn foo2() { + let mut my_struct = MyStruct { field: format!("Hello") }; + + let value = &my_struct.field; + if value.is_empty() { + my_struct.field.push_str("Hello, world!"); + //~^ ERROR [E0502] + } + drop(value); +} + +fn main() { } diff --git a/tests/ui/nll/region-ends-after-if-condition.stderr b/tests/ui/nll/region-ends-after-if-condition.stderr new file mode 100644 index 000000000..c03e38579 --- /dev/null +++ b/tests/ui/nll/region-ends-after-if-condition.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `my_struct.field` as mutable because it is also borrowed as immutable + --> $DIR/region-ends-after-if-condition.rs:26:9 + | +LL | let value = &my_struct.field; + | ---------------- immutable borrow occurs here +LL | if value.is_empty() { +LL | my_struct.field.push_str("Hello, world!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +... +LL | drop(value); + | ----- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/relate_tys/fn-subtype.rs b/tests/ui/nll/relate_tys/fn-subtype.rs new file mode 100644 index 000000000..ba89fa19c --- /dev/null +++ b/tests/ui/nll/relate_tys/fn-subtype.rs @@ -0,0 +1,8 @@ +// Test that NLL produces correct spans for higher-ranked subtyping errors. +// +// compile-flags:-Zno-leak-check + +fn main() { + let x: fn(&'static ()) = |_| {}; + let y: for<'a> fn(&'a ()) = x; //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/nll/relate_tys/fn-subtype.stderr b/tests/ui/nll/relate_tys/fn-subtype.stderr new file mode 100644 index 000000000..21073647e --- /dev/null +++ b/tests/ui/nll/relate_tys/fn-subtype.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/fn-subtype.rs:7:33 + | +LL | let y: for<'a> fn(&'a ()) = x; + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a> fn(&'a ())` + found fn pointer `fn(&())` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs new file mode 100644 index 000000000..7891bab09 --- /dev/null +++ b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs @@ -0,0 +1,24 @@ +// Test that the NLL `relate_tys` code correctly deduces that a +// function returning either argument CANNOT be upcast to one +// that returns always its first argument. +// +// compile-flags:-Zno-leak-check + +fn make_it() -> for<'a> fn(&'a u32, &'a u32) -> &'a u32 { + panic!() +} + +fn foo() { + let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); + //~^ ERROR mismatched types [E0308] + drop(a); +} + +fn bar() { + // The code path for patterns is mildly different, so go ahead and + // test that too: + let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); + //~^ ERROR mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr new file mode 100644 index 000000000..7d76c916d --- /dev/null +++ b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/hr-fn-aaa-as-aba.rs:12:58 + | +LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); + | ^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` + found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` + +error[E0308]: mismatched types + --> $DIR/hr-fn-aaa-as-aba.rs:20:12 + | +LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` + found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs new file mode 100644 index 000000000..92730341c --- /dev/null +++ b/tests/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs @@ -0,0 +1,23 @@ +// Test an interesting corner case that ought to be legal (though the +// current code actually gets it wrong, see below): a fn that takes +// two arguments that are references with the same lifetime is in fact +// equivalent to a fn that takes two references with distinct +// lifetimes. This is true because the two functions can call one +// another -- effectively, the single lifetime `'a` is just inferred +// to be the intersection of the two distinct lifetimes. +// +// check-pass +// compile-flags:-Zno-leak-check + +use std::cell::Cell; + +fn make_cell_aa() -> Cell fn(&'a u32, &'a u32)> { + panic!() +} + +fn aa_eq_ab() { + let a: Cell fn(&'a u32, &'b u32)> = make_cell_aa(); + drop(a); +} + +fn main() { } diff --git a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs new file mode 100644 index 000000000..7cc0acf45 --- /dev/null +++ b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs @@ -0,0 +1,15 @@ +// Test that the NLL `relate_tys` code correctly deduces that a +// function returning always its first argument can be upcast to one +// that returns either first or second argument. +// +// check-pass +// compile-flags:-Zno-leak-check + +fn make_it() -> for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 { + panic!() +} + +fn main() { + let a: for<'a> fn(&'a u32, &'a u32) -> &'a u32 = make_it(); + drop(a); +} diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs new file mode 100644 index 000000000..05e2ea047 --- /dev/null +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs @@ -0,0 +1,34 @@ +// Test that the NLL solver cannot find a solution +// for `exists { forall { R2: R1 } }`. +// +// In this test, the impl should match `fn(T)` for some `T`, +// but we ask it to match `for<'a> fn(&'a ())`. Due to argument +// contravariance, this effectively requires a `T = &'b ()` where +// `forall<'a> { 'a: 'b }`. Therefore, we get an error. +// +// Note the use of `-Zno-leak-check` here. This is presently required in order +// to skip the leak-check errors. +// +// c.f. Issue #57642. +// +// compile-flags:-Zno-leak-check + +trait Y { + type F; + fn make_f() -> Self::F; +} + +impl Y for fn(T) { + type F = fn(T); + + fn make_f() -> Self::F { + |_| {} + } +} + +fn main() { + let _x = ::make_f(); + //~^ ERROR implementation of `Y` is not general enough + //~| ERROR implementation of `Y` is not general enough + //~| ERROR implementation of `Y` is not general enough +} diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr new file mode 100644 index 000000000..b945ffedd --- /dev/null +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -0,0 +1,29 @@ +error: implementation of `Y` is not general enough + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 + | +LL | let _x = ::make_f(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | + = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + +error: implementation of `Y` is not general enough + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 + | +LL | let _x = ::make_f(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | + = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + +error: implementation of `Y` is not general enough + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 + | +LL | let _x = ::make_f(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | + = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/nll/relate_tys/issue-48071.rs b/tests/ui/nll/relate_tys/issue-48071.rs new file mode 100644 index 000000000..73361a0d3 --- /dev/null +++ b/tests/ui/nll/relate_tys/issue-48071.rs @@ -0,0 +1,24 @@ +// Regression test for #48071. This test used to ICE because -- in +// the leak-check -- it would pass since we knew that the return type +// was `'static`, and hence `'static: 'a` was legal even for a +// placeholder region, but in NLL land it would fail because we had +// rewritten `'static` to a region variable. +// +// check-pass + +trait Foo { + fn foo(&self) { } +} + +impl Foo for () { +} + +type MakeFooFn = for<'a> fn(&'a u8) -> Box; + +fn make_foo(x: &u8) -> Box { + Box::new(()) +} + +fn main() { + let x: MakeFooFn = make_foo as MakeFooFn; +} diff --git a/tests/ui/nll/relate_tys/opaque-hrtb.rs b/tests/ui/nll/relate_tys/opaque-hrtb.rs new file mode 100644 index 000000000..261372523 --- /dev/null +++ b/tests/ui/nll/relate_tys/opaque-hrtb.rs @@ -0,0 +1,14 @@ +trait MyTrait {} + +struct Foo; +impl MyTrait for Foo {} + +fn bar() -> impl MyTrait { + Foo +} + +fn foo() -> impl for<'a> MyTrait<&'a str> { + bar() //~ ERROR implementation of `MyTrait` is not general enough +} + +fn main() {} diff --git a/tests/ui/nll/relate_tys/opaque-hrtb.stderr b/tests/ui/nll/relate_tys/opaque-hrtb.stderr new file mode 100644 index 000000000..d75ec2b57 --- /dev/null +++ b/tests/ui/nll/relate_tys/opaque-hrtb.stderr @@ -0,0 +1,11 @@ +error: implementation of `MyTrait` is not general enough + --> $DIR/opaque-hrtb.rs:11:5 + | +LL | bar() + | ^^^^^ implementation of `MyTrait` is not general enough + | + = note: `impl MyTrait<&'2 str>` must implement `MyTrait<&'1 str>`, for any lifetime `'1`... + = note: ...but it actually implements `MyTrait<&'2 str>`, for some specific lifetime `'2` + +error: aborting due to previous error + diff --git a/tests/ui/nll/relate_tys/trait-hrtb.rs b/tests/ui/nll/relate_tys/trait-hrtb.rs new file mode 100644 index 000000000..7f40e93cd --- /dev/null +++ b/tests/ui/nll/relate_tys/trait-hrtb.rs @@ -0,0 +1,14 @@ +// Test that NLL generates proper error spans for trait HRTB errors +// +// compile-flags:-Zno-leak-check + +trait Foo<'a> {} + +fn make_foo<'a>() -> Box> { + panic!() +} + +fn main() { + let x: Box> = make_foo(); + let y: Box Foo<'a>> = x; //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/nll/relate_tys/trait-hrtb.stderr b/tests/ui/nll/relate_tys/trait-hrtb.stderr new file mode 100644 index 000000000..aa1927711 --- /dev/null +++ b/tests/ui/nll/relate_tys/trait-hrtb.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/trait-hrtb.rs:13:39 + | +LL | let y: Box Foo<'a>> = x; + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'a> Foo<'a>` + found trait object `dyn Foo<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/universe-violation.rs b/tests/ui/nll/relate_tys/universe-violation.rs new file mode 100644 index 000000000..c5f9d4406 --- /dev/null +++ b/tests/ui/nll/relate_tys/universe-violation.rs @@ -0,0 +1,15 @@ +// Test that the NLL `relate_tys` code correctly deduces that a +// function returning either argument CANNOT be upcast to one +// that returns always its first argument. +// +// compile-flags:-Zno-leak-check + +fn make_it() -> fn(&'static u32) -> &'static u32 { + panic!() +} + +fn main() { + let a: fn(_) -> _ = make_it(); + let b: fn(&u32) -> &u32 = a; //~ ERROR mismatched types [E0308] + drop(a); +} diff --git a/tests/ui/nll/relate_tys/universe-violation.stderr b/tests/ui/nll/relate_tys/universe-violation.stderr new file mode 100644 index 000000000..fe801b42c --- /dev/null +++ b/tests/ui/nll/relate_tys/universe-violation.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/universe-violation.rs:13:31 + | +LL | let b: fn(&u32) -> &u32 = a; + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32` + found fn pointer `fn(&u32) -> &u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/relate_tys/var-appears-twice.rs b/tests/ui/nll/relate_tys/var-appears-twice.rs new file mode 100644 index 000000000..77129f446 --- /dev/null +++ b/tests/ui/nll/relate_tys/var-appears-twice.rs @@ -0,0 +1,25 @@ +// Test that the NLL `relate_tys` code correctly deduces that a +// function returning always its first argument can be upcast to one +// that returns either first or second argument. + +use std::cell::Cell; + +type DoubleCell = Cell<(A, A)>; +type DoublePair = (A, A); + +fn make_cell<'b>(x: &'b u32) -> Cell<(&'static u32, &'b u32)> { + panic!() +} + +fn main() { + let a: &'static u32 = &22; + let b = 44; + + // Here we get an error because `DoubleCell<_>` requires the same type + // on both parts of the `Cell`, and we can't have that. + let x: DoubleCell<_> = make_cell(&b); //~ ERROR + + // Here we do not get an error because `DoublePair<_>` permits + // variance on the lifetimes involved. + let y: DoublePair<_> = make_cell(&b).get(); +} diff --git a/tests/ui/nll/relate_tys/var-appears-twice.stderr b/tests/ui/nll/relate_tys/var-appears-twice.stderr new file mode 100644 index 000000000..d032ce6f2 --- /dev/null +++ b/tests/ui/nll/relate_tys/var-appears-twice.stderr @@ -0,0 +1,14 @@ +error[E0597]: `b` does not live long enough + --> $DIR/var-appears-twice.rs:20:38 + | +LL | let x: DoubleCell<_> = make_cell(&b); + | ------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `b` is borrowed for `'static` +... +LL | } + | - `b` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/return-ref-mut-issue-46557.rs b/tests/ui/nll/return-ref-mut-issue-46557.rs new file mode 100644 index 000000000..dca61d39d --- /dev/null +++ b/tests/ui/nll/return-ref-mut-issue-46557.rs @@ -0,0 +1,8 @@ +// Regression test for issue #46557 + +fn gimme_static_mut() -> &'static mut u32 { + let ref mut x = 1234543; + x //~ ERROR cannot return value referencing temporary value [E0515] +} + +fn main() {} diff --git a/tests/ui/nll/return-ref-mut-issue-46557.stderr b/tests/ui/nll/return-ref-mut-issue-46557.stderr new file mode 100644 index 000000000..720440a0a --- /dev/null +++ b/tests/ui/nll/return-ref-mut-issue-46557.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/return-ref-mut-issue-46557.rs:5:5 + | +LL | let ref mut x = 1234543; + | ------- temporary value created here +LL | x + | ^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/nll/return_from_loop.rs b/tests/ui/nll/return_from_loop.rs new file mode 100644 index 000000000..495410894 --- /dev/null +++ b/tests/ui/nll/return_from_loop.rs @@ -0,0 +1,35 @@ +// Basic test for liveness constraints: the region (`R1`) that appears +// in the type of `p` includes the points after `&v[0]` up to (but not +// including) the call to `use_x`. The `else` branch is not included. + +#![allow(warnings)] +#![feature(rustc_attrs)] + +struct MyStruct { + field: String +} + +fn main() { +} + +fn nll_fail() { + let mut my_struct = MyStruct { field: format!("Hello") }; + + let value = &mut my_struct.field; + loop { + my_struct.field.push_str("Hello, world!"); + //~^ ERROR [E0499] + value.len(); + return; + } +} + +fn nll_ok() { + let mut my_struct = MyStruct { field: format!("Hello") }; + + let value = &mut my_struct.field; + loop { + my_struct.field.push_str("Hello, world!"); + return; + } +} diff --git a/tests/ui/nll/return_from_loop.stderr b/tests/ui/nll/return_from_loop.stderr new file mode 100644 index 000000000..bd2b8b158 --- /dev/null +++ b/tests/ui/nll/return_from_loop.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `my_struct.field` as mutable more than once at a time + --> $DIR/return_from_loop.rs:20:9 + | +LL | let value = &mut my_struct.field; + | -------------------- first mutable borrow occurs here +LL | loop { +LL | my_struct.field.push_str("Hello, world!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | value.len(); + | ----------- first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/self-assign-ref-mut.rs b/tests/ui/nll/self-assign-ref-mut.rs new file mode 100644 index 000000000..1ca4cf3a7 --- /dev/null +++ b/tests/ui/nll/self-assign-ref-mut.rs @@ -0,0 +1,20 @@ +// Check that `*y` isn't borrowed after `y = y`. + +// check-pass + +fn main() { + let mut x = 1; + { + let mut y = &mut x; + y = y; + y; + } + x; + { + let mut y = &mut x; + y = y; + y = y; + y; + } + x; +} diff --git a/tests/ui/nll/snocat-regression.rs b/tests/ui/nll/snocat-regression.rs new file mode 100644 index 000000000..b2e5995aa --- /dev/null +++ b/tests/ui/nll/snocat-regression.rs @@ -0,0 +1,16 @@ +// Regression test from https://github.com/rust-lang/rust/pull/98109 + +pub fn negotiate(link: S) +where + for<'a> &'a S: 'a, +{ + || { + //~^ ERROR `S` does not live long enough + // + // FIXME(#98437). This regressed at some point and + // probably should work. + let _x = link; + }; +} + +fn main() {} diff --git a/tests/ui/nll/snocat-regression.stderr b/tests/ui/nll/snocat-regression.stderr new file mode 100644 index 000000000..086898473 --- /dev/null +++ b/tests/ui/nll/snocat-regression.stderr @@ -0,0 +1,14 @@ +error: `S` does not live long enough + --> $DIR/snocat-regression.rs:7:5 + | +LL | / || { +LL | | +LL | | // +LL | | // FIXME(#98437). This regressed at some point and +LL | | // probably should work. +LL | | let _x = link; +LL | | }; + | |_____^ + +error: aborting due to previous error + diff --git a/tests/ui/nll/trait-associated-constant.rs b/tests/ui/nll/trait-associated-constant.rs new file mode 100644 index 000000000..e13ae80f9 --- /dev/null +++ b/tests/ui/nll/trait-associated-constant.rs @@ -0,0 +1,31 @@ +// Test cases where we put various lifetime constraints on trait +// associated constants. + +#![feature(rustc_attrs)] + +use std::option::Option; + +trait Anything<'a: 'b, 'b> { + const AC: Option<&'b str>; +} + +struct OKStruct1 { } + +impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct1 { + const AC: Option<&'b str> = None; +} + +struct FailStruct { } + +impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { + const AC: Option<&'c str> = None; + //~^ ERROR: const not compatible with trait +} + +struct OKStruct2 { } + +impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct2 { + const AC: Option<&'a str> = None; +} + +fn main() {} diff --git a/tests/ui/nll/trait-associated-constant.stderr b/tests/ui/nll/trait-associated-constant.stderr new file mode 100644 index 000000000..cf1c52ba7 --- /dev/null +++ b/tests/ui/nll/trait-associated-constant.stderr @@ -0,0 +1,22 @@ +error[E0308]: const not compatible with trait + --> $DIR/trait-associated-constant.rs:21:5 + | +LL | const AC: Option<&'c str> = None; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected enum `Option<&'b str>` + found enum `Option<&'c str>` +note: the lifetime `'c` as defined here... + --> $DIR/trait-associated-constant.rs:20:18 + | +LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { + | ^^ +note: ...does not necessarily outlive the lifetime `'b` as defined here + --> $DIR/trait-associated-constant.rs:20:14 + | +LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.rs b/tests/ui/nll/ty-outlives/impl-trait-captures.rs new file mode 100644 index 000000000..67b31b8bc --- /dev/null +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.rs @@ -0,0 +1,15 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] + +trait Foo<'a> { +} + +impl<'a, T> Foo<'a> for T { } + +fn foo<'a, T>(x: &T) -> impl Foo<'a> { + x + //~^ ERROR captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr new file mode 100644 index 000000000..7b9ed171d --- /dev/null +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds + --> $DIR/impl-trait-captures.rs:11:5 + | +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { + | -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here +LL | x + | ^ + | +help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound + | +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) { + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/nll/ty-outlives/impl-trait-outlives.rs b/tests/ui/nll/ty-outlives/impl-trait-outlives.rs new file mode 100644 index 000000000..68ccb51fc --- /dev/null +++ b/tests/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -0,0 +1,38 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] + +use std::fmt::Debug; + +fn no_region<'a, T>(x: Box) -> impl Debug + 'a +where + T: Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough [E0309] +} + +fn correct_region<'a, T>(x: Box) -> impl Debug + 'a +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a +where + T: 'b + Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough [E0309] +} + +fn outlives_region<'a, 'b, T>(x: Box) -> impl Debug + 'a +where + T: 'b + Debug, + 'b: 'a, +{ + x +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr b/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr new file mode 100644 index 000000000..64b08a9b3 --- /dev/null +++ b/tests/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/impl-trait-outlives.rs:11:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Debug + 'a, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/impl-trait-outlives.rs:26:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + Debug + 'a, + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/issue-53789-1.rs b/tests/ui/nll/ty-outlives/issue-53789-1.rs new file mode 100644 index 000000000..a5201d4bb --- /dev/null +++ b/tests/ui/nll/ty-outlives/issue-53789-1.rs @@ -0,0 +1,87 @@ +// Regression test for #53789. +// +// check-pass + +use std::collections::BTreeMap; + +trait ValueTree { + type Value; +} + +trait Strategy { + type Value: ValueTree; +} + +type StrategyFor = StrategyType<'static, A>; +type StrategyType<'a, A> = >::Strategy; + +impl Strategy for (K, V) { + type Value = TupleValueTree<(K, V)>; +} + +impl ValueTree for TupleValueTree<(K, V)> { + type Value = BTreeMapValueTree; +} + +struct TupleValueTree { + tree: T, +} + +struct BTreeMapStrategy(std::marker::PhantomData<(K, V)>) +where + K: Strategy, + V: Strategy; + +struct BTreeMapValueTree(std::marker::PhantomData<(K, V)>) +where + K: ValueTree, + V: ValueTree; + +impl Strategy for BTreeMapStrategy +where + K: Strategy, + V: Strategy, +{ + type Value = BTreeMapValueTree; +} + +impl ValueTree for BTreeMapValueTree +where + K: ValueTree, + V: ValueTree, +{ + type Value = BTreeMap; +} + +trait Arbitrary<'a>: Sized { + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy; + type Parameters; + type Strategy: Strategy; + type ValueTree: ValueTree; +} + +impl<'a, A, B> Arbitrary<'a> for BTreeMap +where + A: Arbitrary<'static>, + B: Arbitrary<'static>, + StrategyFor: 'static, + StrategyFor: 'static, +{ + type ValueTree = ::Value; + type Parameters = (A::Parameters, B::Parameters); + type Strategy = BTreeMapStrategy; + fn arbitrary_with(args: Self::Parameters) -> BTreeMapStrategy { + let (a, b) = args; + btree_map(any_with::(a), any_with::(b)) + } +} + +fn btree_map(key: K, value: V) -> BTreeMapStrategy { + unimplemented!() +} + +fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> { + unimplemented!() +} + +fn main() { } diff --git a/tests/ui/nll/ty-outlives/issue-53789-2.rs b/tests/ui/nll/ty-outlives/issue-53789-2.rs new file mode 100644 index 000000000..5109a0e4a --- /dev/null +++ b/tests/ui/nll/ty-outlives/issue-53789-2.rs @@ -0,0 +1,249 @@ +// Regression test for #53789. +// +// check-pass + +use std::cmp::Ord; +use std::collections::BTreeMap; +use std::ops::Range; + +macro_rules! valuetree { + () => { + type ValueTree = ::Value; + }; +} + +macro_rules! product_unpack { + ($factor: pat) => { + ($factor,) + }; + ($($factor: pat),*) => { + ( $( $factor ),* ) + }; + ($($factor: pat),*,) => { + ( $( $factor ),* ) + }; +} + +macro_rules! product_type { + ($factor: ty) => { + ($factor,) + }; + ($($factor: ty),*) => { + ( $( $factor, )* ) + }; + ($($factor: ty),*,) => { + ( $( $factor, )* ) + }; +} + +macro_rules! default { + ($type: ty, $val: expr) => { + impl Default for $type { + fn default() -> Self { + $val.into() + } + } + }; +} + +// Pervasive internal sugar +macro_rules! mapfn { + ($(#[$meta:meta])* [$($vis:tt)*] + fn $name:ident[$($gen:tt)*]($parm:ident: $input:ty) -> $output:ty { + $($body:tt)* + }) => { + $(#[$meta])* + #[derive(Clone, Copy)] + $($vis)* struct $name; + impl $($gen)* statics::MapFn<$input> for $name { + type Output = $output; + } + } +} + +macro_rules! opaque_strategy_wrapper { + ($(#[$smeta:meta])* pub struct $stratname:ident + [$($sgen:tt)*][$($swhere:tt)*] + ($innerstrat:ty) -> $stratvtty:ty; + + $(#[$vmeta:meta])* pub struct $vtname:ident + [$($vgen:tt)*][$($vwhere:tt)*] + ($innervt:ty) -> $actualty:ty; + ) => { + $(#[$smeta])* struct $stratname $($sgen)* (std::marker::PhantomData<(K, V)>) + $($swhere)*; + + $(#[$vmeta])* struct $vtname $($vgen)* ($innervt) $($vwhere)*; + + impl $($sgen)* Strategy for $stratname $($sgen)* $($swhere)* { + type Value = $stratvtty; + } + + impl $($vgen)* ValueTree for $vtname $($vgen)* $($vwhere)* { + type Value = $actualty; + } + } +} + +trait ValueTree { + type Value; +} + +trait Strategy { + type Value: ValueTree; +} + +#[derive(Clone)] +struct VecStrategy { + element: T, + size: Range, +} + +fn vec(element: T, size: Range) -> VecStrategy { + VecStrategy { element: element, size: size } +} + +type ValueFor = <::Value as ValueTree>::Value; + +trait Arbitrary<'a>: Sized { + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy; + + type Parameters: Default; + type Strategy: Strategy; + type ValueTree: ValueTree; +} + +type StrategyFor = StrategyType<'static, A>; +type StrategyType<'a, A> = >::Strategy; + +//#[derive(Clone, PartialEq, Eq, Hash, Debug, From, Into)] +struct SizeBounds(Range); +default!(SizeBounds, 0..100); + +impl From> for SizeBounds { + fn from(high: Range) -> Self { + unimplemented!() + } +} + +impl From for Range { + fn from(high: SizeBounds) -> Self { + unimplemented!() + } +} + +fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> { + unimplemented!() +} + +impl Strategy for (K, V) +where + ::Value: Ord, +{ + type Value = TupleValueTree<(K, V)>; +} + +impl ValueTree for TupleValueTree<(K, V)> +where + ::Value: Ord, +{ + type Value = BTreeMapValueTree; +} + +#[derive(Clone)] +struct VecValueTree { + elements: Vec, +} + +#[derive(Clone, Copy)] +struct TupleValueTree { + tree: T, +} + +opaque_strategy_wrapper! { + #[derive(Clone)] + pub struct BTreeMapStrategy[] + [where K : Strategy, V : Strategy, ValueFor : Ord]( + statics::Filter, + VecToBTreeMap>, MinSize>) + -> BTreeMapValueTree; + + #[derive(Clone)] + pub struct BTreeMapValueTree[] + [where K : ValueTree, V : ValueTree, K::Value : Ord]( + statics::Filter>, + VecToBTreeMap>, MinSize>) + -> BTreeMap; +} + +type RangedParams2 = product_type![SizeBounds, A, B]; + +impl<'a, A, B> Arbitrary<'a> for BTreeMap +where + A: Arbitrary<'static> + Ord, + B: Arbitrary<'static>, + StrategyFor: 'static, + StrategyFor: 'static, +{ + valuetree!(); + type Parameters = RangedParams2; + type Strategy = BTreeMapStrategy; + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + let product_unpack![range, a, b] = args; + btree_map(any_with::(a), any_with::(b), range.into()) + } +} + +#[derive(Clone, Copy)] +struct MinSize(usize); + +mapfn! { + [] fn VecToBTreeMap[] + (vec: Vec<(K, V)>) -> BTreeMap + { + vec.into_iter().collect() + } +} + +fn btree_map( + key: K, + value: V, + size: Range, +) -> BTreeMapStrategy +where + ValueFor: Ord, +{ + unimplemented!() +} + +mod statics { + pub(super) trait MapFn { + type Output; + } + + #[derive(Clone)] + pub struct Filter { + source: S, + fun: F, + } + + impl Filter { + pub fn new(source: S, whence: String, filter: F) -> Self { + unimplemented!() + } + } + + #[derive(Clone)] + pub struct Map { + source: S, + fun: F, + } + + impl Map { + pub fn new(source: S, fun: F) -> Self { + unimplemented!() + } + } +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/issue-55756.rs b/tests/ui/nll/ty-outlives/issue-55756.rs new file mode 100644 index 000000000..e1a3bc3c4 --- /dev/null +++ b/tests/ui/nll/ty-outlives/issue-55756.rs @@ -0,0 +1,37 @@ +// Regression test for #55756. +// +// In this test, the result of `self.callee` is a projection `>::Guard`. As it may contain a destructor, the dropck +// rules require that this type outlivess the scope of `state`. Unfortunately, +// our region inference is not smart enough to figure out how to +// translate a requirement like +// +// >::guard: 'r +// +// into a requirement that `'0: 'r` -- in particular, it fails to do +// so because it *also* knows that `>::Guard: 'a` +// from the trait definition. Faced with so many choices, the current +// solver opts to do nothing. +// +// Fixed by tweaking the solver to recognize that the constraint from +// the environment duplicates one from the trait. +// +// check-pass + +#![crate_type="lib"] + +pub trait Database<'a> { + type Guard: 'a; +} + +pub struct Stateful<'a, D: 'a>(&'a D); + +impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> { + pub fn callee<'a>(&'a self) -> >::Guard { + unimplemented!() + } + pub fn caller<'a>(&'a self) -> >::Guard { + let state = self.callee(); + unimplemented!() + } +} diff --git a/tests/ui/nll/ty-outlives/projection-body.rs b/tests/ui/nll/ty-outlives/projection-body.rs new file mode 100644 index 000000000..b03a539eb --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-body.rs @@ -0,0 +1,27 @@ +// Test that when we infer the lifetime to a subset of the fn body, it +// works out. +// +// check-pass + +trait MyTrait<'a> { + type Output; +} + +fn foo1() +where + for<'x> T: MyTrait<'x>, +{ + // Here the region `'c` in `>::Output` will be + // inferred to a subset of the fn body. + let x = bar::(); + drop(x); +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-implied-bounds.rs b/tests/ui/nll/ty-outlives/projection-implied-bounds.rs new file mode 100644 index 000000000..e1dac0824 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-implied-bounds.rs @@ -0,0 +1,40 @@ +// Test that we can deduce when projections like `T::Item` outlive the +// function body. Test that this does not imply that `T: 'a` holds. + +// compile-flags:-Zverbose + +use std::cell::Cell; + +fn twice(mut value: T, mut f: F) +where + F: FnMut(&T, Cell<&Option>), + T: Iterator, +{ + let mut n = value.next(); + f(&value, Cell::new(&n)); + f(&value, Cell::new(&n)); +} + +fn generic1(value: T) { + // No error here: + twice(value, |value_ref, item| invoke1(item)); +} + +fn invoke1<'a, T>(x: Cell<&'a Option>) +where + T: 'a, +{ +} + +fn generic2(value: T) { + twice(value, |value_ref, item| invoke2(value_ref, item)); + //~^ ERROR the parameter type `T` may not live long enough +} + +fn invoke2<'a, T, U>(a: &T, b: Cell<&'a Option>) +where + T: 'a, +{ +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr new file mode 100644 index 000000000..d949e29b2 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/projection-implied-bounds.rs:30:36 + | +LL | twice(value, |value_ref, item| invoke2(value_ref, item)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn generic2(value: T) { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-closure.rs b/tests/ui/nll/ty-outlives/projection-no-regions-closure.rs new file mode 100644 index 000000000..2d9c008c7 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-no-regions-closure.rs @@ -0,0 +1,55 @@ +// compile-flags:-Zverbose + +// Tests closures that propagate an outlives relationship to their +// creator where the subject is a projection with no regions (`::Item`, to be exact). + +#![allow(warnings)] +#![feature(rustc_attrs)] + +trait Anything { } + +impl Anything for T { } + +fn with_signature<'a, T, F>(x: Box, op: F) -> Box + where F: FnOnce(Box) -> Box +{ + op(x) +} + +#[rustc_regions] +fn no_region<'a, T>(x: Box) -> Box +where + T: Iterator, +{ + with_signature(x, |mut y| Box::new(y.next())) + //~^ ERROR the associated type `::Item` may not live long enough +} + +#[rustc_regions] +fn correct_region<'a, T>(x: Box) -> Box +where + T: 'a + Iterator, +{ + with_signature(x, |mut y| Box::new(y.next())) +} + +#[rustc_regions] +fn wrong_region<'a, 'b, T>(x: Box) -> Box +where + T: 'b + Iterator, +{ + with_signature(x, |mut y| Box::new(y.next())) + //~^ ERROR the associated type `::Item` may not live long enough +} + +#[rustc_regions] +fn outlives_region<'a, 'b, T>(x: Box) -> Box +where + T: 'b + Iterator, + 'b: 'a, +{ + with_signature(x, |mut y| Box::new(y.next())) +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr new file mode 100644 index 000000000..4933b9348 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -0,0 +1,118 @@ +note: external requirements + --> $DIR/projection-no-regions-closure.rs:25:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + (), + ] + = note: number of external vids: 3 + = note: where ::Item: '_#2r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:21:1 + | +LL | / fn no_region<'a, T>(x: Box) -> Box +LL | | where +LL | | T: Iterator, + | |________________^ + | + = note: defining type: no_region::<'_#1r, T> + +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/projection-no-regions-closure.rs:25:31 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'a`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-no-regions-closure.rs:34:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + (), + ] + = note: number of external vids: 3 + = note: where ::Item: '_#2r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:30:1 + | +LL | / fn correct_region<'a, T>(x: Box) -> Box +LL | | where +LL | | T: 'a + Iterator, + | |_____________________^ + | + = note: defining type: correct_region::<'_#1r, T> + +note: external requirements + --> $DIR/projection-no-regions-closure.rs:42:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + (), + ] + = note: number of external vids: 4 + = note: where ::Item: '_#3r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:38:1 + | +LL | / fn wrong_region<'a, 'b, T>(x: Box) -> Box +LL | | where +LL | | T: 'b + Iterator, + | |_____________________^ + | + = note: defining type: wrong_region::<'_#1r, '_#2r, T> + +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/projection-no-regions-closure.rs:42:31 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'a`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-no-regions-closure.rs:52:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + (), + ] + = note: number of external vids: 4 + = note: where ::Item: '_#3r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:47:1 + | +LL | / fn outlives_region<'a, 'b, T>(x: Box) -> Box +LL | | where +LL | | T: 'b + Iterator, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-fn.rs b/tests/ui/nll/ty-outlives/projection-no-regions-fn.rs new file mode 100644 index 000000000..a10a0366a --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-no-regions-fn.rs @@ -0,0 +1,40 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] + +trait Anything { } + +impl Anything for T { } + +fn no_region<'a, T>(mut x: T) -> Box +where + T: Iterator, +{ + Box::new(x.next()) + //~^ ERROR the associated type `::Item` may not live long enough +} + +fn correct_region<'a, T>(mut x: T) -> Box +where + T: 'a + Iterator, +{ + Box::new(x.next()) +} + +fn wrong_region<'a, 'b, T>(mut x: T) -> Box +where + T: 'b + Iterator, +{ + Box::new(x.next()) + //~^ ERROR the associated type `::Item` may not live long enough +} + +fn outlives_region<'a, 'b, T>(mut x: T) -> Box +where + T: 'b + Iterator, + 'b: 'a, +{ + Box::new(x.next()) +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr new file mode 100644 index 000000000..e0ff544fe --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr @@ -0,0 +1,21 @@ +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/projection-no-regions-fn.rs:13:5 + | +LL | Box::new(x.next()) + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'a`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/projection-no-regions-fn.rs:28:5 + | +LL | Box::new(x.next()) + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'a`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.rs b/tests/ui/nll/ty-outlives/projection-one-region-closure.rs new file mode 100644 index 000000000..af361e990 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.rs @@ -0,0 +1,83 @@ +// Test cases where we constrain `>::AssocType` to +// outlive `'a` and there are no bounds in the trait definition of +// `Anything`. This means that the constraint can only be satisfied in two +// ways: +// +// - by ensuring that `T: 'a` and `'b: 'a`, or +// - by something in the where clauses. +// +// As of this writing, the where clause option does not work because +// of limitations in our region inferencing system (this is true both +// with and without NLL). See `projection_outlives`. +// +// Ensuring that both `T: 'a` and `'b: 'a` holds does work (`elements_outlive`). + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a> { + type AssocType; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ + // We are projecting `>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T: 'a, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr new file mode 100644 index 000000000..dbda04c42 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -0,0 +1,155 @@ +note: external requirements + --> $DIR/projection-one-region-closure.rs:45:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where T: '_#2r + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:41:1 + | +LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, + | |____________________^ + | + = note: defining type: no_relationships_late::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:45:39 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Anything<'b> + 'a, + | ++++ + +error: lifetime may not live long enough + --> $DIR/projection-one-region-closure.rs:45:39 + | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-closure.rs:56:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where T: '_#3r + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:51:1 + | +LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'a: 'a, + | |___________^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:56:39 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Anything<'b> + 'a, + | ++++ + +error: lifetime may not live long enough + --> $DIR/projection-one-region-closure.rs:56:39 + | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-closure.rs:70:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where >::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:62:1 + | +LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T::AssocType: 'a, + | |_____________________^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-one-region-closure.rs:80:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where T: '_#3r + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:74:1 + | +LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T: 'a, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs new file mode 100644 index 000000000..6f8513491 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs @@ -0,0 +1,84 @@ +// Test cases where we constrain `>::AssocType` to +// outlive `'a` and there is a unique bound in the trait definition of +// `Anything` -- i.e., we know that `AssocType` outlives `'b`. In this +// case, the best way to satisfy the trait bound is to show that `'b: +// 'a`, which can be done in various ways. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a> { + type AssocType: 'a; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ + // We are projecting `>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'a>, +{ + // Note that in this case the closure still propagates an external + // requirement between two variables in its signature, but the + // creator maps both those two region variables to `'a` on its + // side. + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr new file mode 100644 index 000000000..250c796e2 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -0,0 +1,152 @@ +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:37:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:33:1 + | +LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, + | |____________________^ + | + = note: defining type: no_relationships_late::<'_#1r, T> + +error: lifetime may not live long enough + --> $DIR/projection-one-region-trait-bound-closure.rs:37:39 + | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:47:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:42:1 + | +LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'a: 'a, + | |___________^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + +error: lifetime may not live long enough + --> $DIR/projection-one-region-trait-bound-closure.rs:47:39 + | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:60:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where >::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:52:1 + | +LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T::AssocType: 'a, + | |_____________________^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:69:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:64:1 + | +LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:81:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:73:1 + | +LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'a>, + | |____________________^ + | + = note: defining type: one_region::<'_#1r, T> + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs new file mode 100644 index 000000000..7c0a3bc72 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs @@ -0,0 +1,88 @@ +// Test cases where we constrain `>::AssocType` to +// outlive `'static`. In this case, we don't get any errors, and in fact +// we don't even propagate constraints from the closures to the callers. + +// compile-flags:-Zverbose +// check-pass + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a> { + type AssocType: 'static; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ + // This error is unfortunate. This code ought to type-check: we + // are projecting `>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. However, + // the way the region checker works, we don't register this + // outlives obligation, and hence we get an error: this is because + // what we see is a projection like `>::AssocType`, and we don't yet know if `?0` will + // equal `'b` or not, so we ignore the where-clause. Obviously we + // can do better here with a more involved verification step. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'a>, +{ + // Note that in this case the closure still propagates an external + // requirement between two variables in its signature, but the + // creator maps both those two region variables to `'a` on its + // side. + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr new file mode 100644 index 000000000..b27186b05 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -0,0 +1,114 @@ +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:36:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:32:1 + | +LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, + | |____________________^ + | + = note: defining type: no_relationships_late::<'_#1r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:40:1 + | +LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'a: 'a, + | |___________^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:49:1 + | +LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T::AssocType: 'a, + | |_____________________^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:68:1 + | +LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:77:1 + | +LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'a>, + | |____________________^ + | + = note: defining type: one_region::<'_#1r, T> + diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs new file mode 100644 index 000000000..7b4a3c03a --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs @@ -0,0 +1,112 @@ +// Test cases where we constrain `>::AssocType` +// to outlive `'a` and there are two bounds in the trait definition of +// `Anything` -- i.e., we know that `AssocType` outlives `'a` and +// `'b`. In this case, it's not clear what is the best way to satisfy +// the trait bound, and hence we propagate it to the caller as a type +// test. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a, 'b> { + type AssocType: 'a + 'b; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, 'c, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b, 'c>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR may not live long enough +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR may not live long enough +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + T::AssocType: 'a, +{ + // We are projecting `>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + 'c: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR lifetime may not live long enough +} + +#[rustc_regions] +fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'b>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'a, 'a>, +{ + // Note that in this case the closure still propagates an external + // requirement between two variables in its signature, but the + // creator maps both those two region variables to `'a` on its + // side. + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr new file mode 100644 index 000000000..90f049142 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -0,0 +1,236 @@ +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: late-bound region is '_#4r + = note: number of external vids: 5 + = note: where >::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:34:1 + | +LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, + | |________________________^ + | + = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> + +error[E0309]: the associated type `>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:38:39 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = note: ...so that the type `>::AssocType` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where >::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:43:1 + | +LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | 'a: 'a, + | |___________^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> + +error[E0309]: the associated type `>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:48:39 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = note: ...so that the type `>::AssocType` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where >::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:53:1 + | +LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | T::AssocType: 'a, + | |_____________________^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:70:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where >::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 + | +LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:79:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where >::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:74:1 + | +LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | 'c: 'a, + | |___________^ + | + = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: two_regions::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where >::AssocType: '_#2r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:83:1 + | +LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'b>, + | |________________________^ + | + = note: defining type: two_regions::<'_#1r, T> + +error: lifetime may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:87:5 + | +LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:97:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where >::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:92:1 + | +LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'b>, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:109:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: number of external vids: 3 + = note: where >::AssocType: '_#2r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:101:1 + | +LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'a, 'a>, + | |________________________^ + | + = note: defining type: one_region::<'_#1r, T> + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs new file mode 100644 index 000000000..dce88b88c --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs @@ -0,0 +1,34 @@ +// Test that we are able to establish that `>::Output` outlives `'b` here. We need to prove however +// that `>::Output` outlives `'a`, so we also have to +// prove that `'b: 'a`. + +trait MyTrait<'a> { + type Output; +} + +fn foo1<'a, 'b, T>() -> &'a () +where + T: MyTrait<'a>, + >::Output: 'b, +{ + bar::() //~ ERROR may not live long enough +} + +fn foo2<'a, 'b, T>() -> &'a () +where + T: MyTrait<'a>, + >::Output: 'b, + 'b: 'a, +{ + bar::() // OK +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr new file mode 100644 index 000000000..b4435fe06 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -0,0 +1,12 @@ +error[E0309]: the associated type `>::Output` may not live long enough + --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5 + | +LL | bar::() + | ^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::Output: 'a`... + = note: ...so that the type `>::Output` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs new file mode 100644 index 000000000..987148dce --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs @@ -0,0 +1,25 @@ +// Test that if we need to prove that `>::Output: +// 'a`, but we only know that `>::Output: 'a`, that +// doesn't suffice. + +trait MyTrait<'a> { + type Output; +} + +fn foo1<'a, 'b, T>() -> &'a () +where + for<'x> T: MyTrait<'x>, + >::Output: 'a, +{ + bar::<>::Output>() + //~^ ERROR the associated type `>::Output` may not live long enough +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr new file mode 100644 index 000000000..ddeaf3c1f --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr @@ -0,0 +1,12 @@ +error[E0309]: the associated type `>::Output` may not live long enough + --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5 + | +LL | bar::<>::Output>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::Output: 'a`... + = note: ...so that the type `>::Output` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-env.rs b/tests/ui/nll/ty-outlives/projection-where-clause-env.rs new file mode 100644 index 000000000..a41116232 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-env.rs @@ -0,0 +1,28 @@ +// Test that when we have a `>::Output: 'a` +// relationship in the environment we take advantage of it. In this +// case, that means we **don't** have to prove that `T: 'a`. +// +// Regression test for #53121. +// +// check-pass + +trait MyTrait<'a> { + type Output; +} + +fn foo<'a, T>() -> &'a () +where + T: MyTrait<'a>, + >::Output: 'a, +{ + bar::() +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-none.rs b/tests/ui/nll/ty-outlives/projection-where-clause-none.rs new file mode 100644 index 000000000..bb201e5c0 --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-none.rs @@ -0,0 +1,24 @@ +// Test that we are NOT able to establish that `>::Output: 'a` outlives `'a` here -- we have only one +// recourse, which is to prove that `T: 'a` and `'a: 'a`, but we don't +// know that `T: 'a`. + +trait MyTrait<'a> { + type Output; +} + +fn foo<'a, T>() -> &'a () +where + T: MyTrait<'a>, +{ + bar::() //~ ERROR the parameter type `T` may not live long enough +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr new file mode 100644 index 000000000..0df44644d --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-where-clause-none.rs:14:5 + | +LL | bar::() + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: MyTrait<'a> + 'a, + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/projection-where-clause-trait.rs b/tests/ui/nll/ty-outlives/projection-where-clause-trait.rs new file mode 100644 index 000000000..1a40d3b4c --- /dev/null +++ b/tests/ui/nll/ty-outlives/projection-where-clause-trait.rs @@ -0,0 +1,25 @@ +// Test that we are able to establish that `>::Output: 'a` outlives `'a` (because the trait says +// so). +// +// check-pass + +trait MyTrait<'a> { + type Output: 'a; +} + +fn foo<'a, T>() -> &'a () +where + T: MyTrait<'a>, +{ + bar::() +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs new file mode 100644 index 000000000..4d8380599 --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs @@ -0,0 +1,39 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Invoke in such a way that the callee knows: +// +// - 'a: 'x +// +// and it must prove that `T: 'x`. Callee passes along `T: 'a`. +fn twice<'a, F, T>(v: Cell<&'a ()>, value: T, mut f: F) +where + F: for<'x> FnMut(Option>, &T), +{ + f(None, &value); + f(None, &value); +} + +#[rustc_regions] +fn generic(value: T) { + let cell = Cell::new(&()); + twice(cell, value, |a, b| invoke(a, b)); +} + +#[rustc_regions] +fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { + twice(cell, value, |a, b| invoke(a, b)); + //~^ ERROR the parameter type `T` may not live long enough +} + +fn invoke<'a, 'x, T>(x: Option>, y: &T) +where + T: 'x, +{ +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr new file mode 100644 index 000000000..a442cf12d --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -0,0 +1,59 @@ +note: external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:24:24 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^ + | + = note: defining type: generic::::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)), + (), + ] + = note: number of external vids: 2 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:22:1 + | +LL | fn generic(value: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: generic:: + +note: external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^ + | + = note: defining type: generic_fail::::{closure#0} with closure substs [ + i16, + for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)), + (), + ] + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:28:1 + | +LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: generic_fail:: + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:31 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn generic_fail<'a, T: 'a>(cell: Cell<&'a ()>, value: T) { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs new file mode 100644 index 000000000..4343c3aee --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs @@ -0,0 +1,53 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::fmt::Debug; + +fn with_signature<'a, T, F>(x: Box, op: F) -> Box + where F: FnOnce(Box) -> Box +{ + op(x) +} + +#[rustc_regions] +fn no_region<'a, T>(x: Box) -> Box +where + T: Debug, +{ + // Here, the closure winds up being required to prove that `T: + // 'a`. In principle, it could know that, except that it is + // type-checked in a fully generic way, and hence it winds up with + // a propagated requirement that `T: '_#2`, where `'_#2` appears + // in the return type. The caller makes the mapping from `'_#2` to + // `'a` (and subsequently reports an error). + + with_signature(x, |y| y) + //~^ ERROR the parameter type `T` may not live long enough +} + +fn correct_region<'a, T>(x: Box) -> Box +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box) -> Box +where + T: 'b + Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives_region<'a, 'b, T>(x: Box) -> Box +where + T: 'b + Debug, + 'b: 'a, +{ + x +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr new file mode 100644 index 000000000..35979c8bf --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -0,0 +1,49 @@ +note: external requirements + --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 + | +LL | with_signature(x, |y| y) + | ^^^ + | + = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>, + (), + ] + = note: number of external vids: 3 + = note: where T: '_#2r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-return-type.rs:15:1 + | +LL | / fn no_region<'a, T>(x: Box) -> Box +LL | | where +LL | | T: Debug, + | |_____________^ + | + = note: defining type: no_region::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27 + | +LL | with_signature(x, |y| y) + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Debug + 'a, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + Debug + 'a, + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs new file mode 100644 index 000000000..b80287610 --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs @@ -0,0 +1,82 @@ +// Test that we can propagate `T: 'a` obligations to our caller. See +// `correct_region` for an explanation of how this test is setup; it's +// somewhat intricate. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +fn with_signature<'a, T, F>(a: Cell<&'a ()>, b: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(a, b) +} + +fn require<'a, T>(_a: &Cell<&'a ()>, _b: &T) +where + T: 'a, +{ +} + +#[rustc_regions] +fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { + with_signature(a, b, |x, y| { + // See `correct_region`, which explains the point of this + // test. The only difference is that, in the case of this + // function, there is no where clause *anywhere*, and hence we + // get an error (but reported by the closure creator). + require(&x, &y) + //~^ ERROR the parameter type `T` may not live long enough + }) +} + +#[rustc_regions] +fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) +where + T: 'a, +{ + with_signature(a, b, |x, y| { + // Key point of this test: + // + // The *closure* is being type-checked with all of its free + // regions "universalized". In particular, it does not know + // that `x` has the type `Cell<&'a ()>`, but rather treats it + // as if the type of `x` is `Cell<&'A ()>`, where `'A` is some + // fresh, independent region distinct from the `'a` which + // appears in the environment. The call to `require` here + // forces us then to prove that `T: 'A`, but the closure + // cannot do it on its own. It has to surface this requirement + // to its creator (which knows that `'a == 'A`). + require(&x, &y) + }) +} + +#[rustc_regions] +fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +where + T: 'b, +{ + with_signature(a, b, |x, y| { + // See `correct_region` + require(&x, &y) + //~^ ERROR the parameter type `T` may not live long enough + }) +} + +#[rustc_regions] +fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +where + T: 'b, + 'b: 'a, +{ + with_signature(a, b, |x, y| { + // See `correct_region` + require(&x, &y) + }) +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr new file mode 100644 index 000000000..4c97db58c --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -0,0 +1,122 @@ +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: no_region::::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)), + (), + ] + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:26:1 + | +LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: defining type: no_region:: + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:32:9 + | +LL | require(&x, &y) + | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) { + | ++++ + +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:42:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: number of external vids: 3 + = note: where T: '_#2r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1 + | +LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) +LL | | where +LL | | T: 'a, + | |__________^ + | + = note: defining type: correct_region::<'_#1r, T> + +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: wrong_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where T: '_#2r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1 + | +LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +LL | | where +LL | | T: 'b, + | |__________^ + | + = note: defining type: wrong_region::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9 + | +LL | require(&x, &y) + | ^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + 'a, + | ++++ + +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where T: '_#3r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1 + | +LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +LL | | where +LL | | T: 'b, +LL | | 'b: 'a, + | |___________^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-fn-body.rs b/tests/ui/nll/ty-outlives/ty-param-fn-body.rs new file mode 100644 index 000000000..98239f416 --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-fn-body.rs @@ -0,0 +1,27 @@ +// Test that we assume that universal types like `T` outlive the +// function body. + +#![allow(warnings)] + +use std::cell::Cell; + +// No errors here, because `'a` is local to the body. +fn region_within_body(t: T) { + let some_int = 22; + let cell = Cell::new(&some_int); + outlives(cell, t) +} + +// Error here, because T: 'a is not satisfied. +fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) { + outlives(cell, t) + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives<'a, T>(x: Cell<&'a usize>, y: T) +where + T: 'a, +{ +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr b/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr new file mode 100644 index 000000000..5fb69255d --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn-body.rs:17:5 + | +LL | outlives(cell, t) + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn region_static<'a, T: 'a>(cell: Cell<&'a usize>, t: T) { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-fn.rs b/tests/ui/nll/ty-outlives/ty-param-fn.rs new file mode 100644 index 000000000..4393a3b41 --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-fn.rs @@ -0,0 +1,36 @@ +#![allow(warnings)] + +use std::fmt::Debug; + +fn no_region<'a, T>(x: Box) -> Box +where + T: Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn correct_region<'a, T>(x: Box) -> Box +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box) -> Box +where + T: 'b + Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives_region<'a, 'b, T>(x: Box) -> Box +where + T: 'b + Debug, + 'b: 'a, +{ + x +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/ty-param-fn.stderr b/tests/ui/nll/ty-outlives/ty-param-fn.stderr new file mode 100644 index 000000000..825b26d2f --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-fn.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn.rs:9:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Debug + 'a, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn.rs:24:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + Debug + 'a, + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/nll/ty-outlives/ty-param-implied-bounds.rs b/tests/ui/nll/ty-outlives/ty-param-implied-bounds.rs new file mode 100644 index 000000000..9042844e8 --- /dev/null +++ b/tests/ui/nll/ty-outlives/ty-param-implied-bounds.rs @@ -0,0 +1,28 @@ +// compile-flags:-Zverbose +// check-pass + +// Test that we assume that universal types like `T` outlive the +// function body. + +use std::cell::Cell; + +fn twice(value: T, mut f: F) +where + F: FnMut(Cell<&T>), +{ + f(Cell::new(&value)); + f(Cell::new(&value)); +} + +fn generic(value: T) { + // No error here: + twice(value, |r| invoke(r)); +} + +fn invoke<'a, T>(x: Cell<&'a T>) +where + T: 'a, +{ +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/wf-unreachable.rs b/tests/ui/nll/ty-outlives/wf-unreachable.rs new file mode 100644 index 000000000..c6f4c4afa --- /dev/null +++ b/tests/ui/nll/ty-outlives/wf-unreachable.rs @@ -0,0 +1,52 @@ +// Test that we check that user type annotations are well-formed, even in dead +// code. + +fn uninit<'a>() { + return; + let x: &'static &'a (); //~ ERROR lifetime may not live long enough +} + +fn var_type<'a>() { + return; + let x: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough +} + +fn uninit_infer<'a>() { + let x: &'static &'a _; //~ ERROR lifetime may not live long enough + x = && (); +} + +fn infer<'a>() { + return; + let x: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough +} + +fn uninit_no_var<'a>() { + return; + let _: &'static &'a (); //~ ERROR lifetime may not live long enough +} + +fn no_var<'a>() { + return; + let _: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough +} + +fn infer_no_var<'a>() { + return; + let _: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough +} + +trait X<'a, 'b> {} + +struct C<'a, 'b, T: X<'a, 'b>>(T, &'a (), &'b ()); + +impl X<'_, '_> for i32 {} +impl<'a> X<'a, 'a> for () {} + +// This type annotation is not well-formed because we substitute `()` for `_`. +fn required_substs<'a>() { + return; + let _: C<'static, 'a, _> = C((), &(), &()); //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/ty-outlives/wf-unreachable.stderr b/tests/ui/nll/ty-outlives/wf-unreachable.stderr new file mode 100644 index 000000000..da3bc2083 --- /dev/null +++ b/tests/ui/nll/ty-outlives/wf-unreachable.stderr @@ -0,0 +1,73 @@ +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:6:12 + | +LL | fn uninit<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let x: &'static &'a (); + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:11:12 + | +LL | fn var_type<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let x: &'static &'a () = &&(); + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:15:12 + | +LL | fn uninit_infer<'a>() { + | -- lifetime `'a` defined here +LL | let x: &'static &'a _; + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:21:12 + | +LL | fn infer<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let x: &'static &'a _ = &&(); + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:26:12 + | +LL | fn uninit_no_var<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: &'static &'a (); + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:31:12 + | +LL | fn no_var<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: &'static &'a () = &&(); + | ^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:36:12 + | +LL | fn infer_no_var<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: &'static &'a _ = &&(); + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:49:12 + | +LL | fn required_substs<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: C<'static, 'a, _> = C((), &(), &()); + | ^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/nll/type-alias-free-regions.rs b/tests/ui/nll/type-alias-free-regions.rs new file mode 100644 index 000000000..fd5566f35 --- /dev/null +++ b/tests/ui/nll/type-alias-free-regions.rs @@ -0,0 +1,31 @@ +// Test that we don't assume that type aliases have the same type parameters +// as the type they alias and then panic when we see this. + +type A<'a> = &'a isize; +type B<'a> = Box>; + +struct C<'a> { + f: Box> +} + +trait FromBox<'a> { + fn from_box(b: Box) -> Self; +} + +impl<'a> FromBox<'a> for C<'a> { + fn from_box(b: Box) -> Self { + C { f: b } //~ ERROR + } +} + +trait FromTuple<'a> { + fn from_tuple( b: (B,)) -> Self; +} + +impl<'a> FromTuple<'a> for C<'a> { + fn from_tuple(b: (B,)) -> Self { + C { f: Box::new(b.0) } //~ ERROR + } +} + +fn main() {} diff --git a/tests/ui/nll/type-alias-free-regions.stderr b/tests/ui/nll/type-alias-free-regions.stderr new file mode 100644 index 000000000..45fd5a2f1 --- /dev/null +++ b/tests/ui/nll/type-alias-free-regions.stderr @@ -0,0 +1,22 @@ +error: lifetime may not live long enough + --> $DIR/type-alias-free-regions.rs:17:9 + | +LL | impl<'a> FromBox<'a> for C<'a> { + | -- lifetime `'a` defined here +LL | fn from_box(b: Box) -> Self { + | - has type `Box>` +LL | C { f: b } + | ^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/type-alias-free-regions.rs:27:9 + | +LL | impl<'a> FromTuple<'a> for C<'a> { + | -- lifetime `'a` defined here +LL | fn from_tuple(b: (B,)) -> Self { + | - has type `(Box<&'1 isize>,)` +LL | C { f: Box::new(b.0) } + | ^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/type-check-pointer-coercions.rs b/tests/ui/nll/type-check-pointer-coercions.rs new file mode 100644 index 000000000..66da57248 --- /dev/null +++ b/tests/ui/nll/type-check-pointer-coercions.rs @@ -0,0 +1,37 @@ +fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 { + x //~ ERROR +} + +fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 { + x //~ ERROR +} + +fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + // Two errors because *mut is invariant + x //~ ERROR + //~| ERROR +} + +fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 { + x //~ ERROR +} + +fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 { + let z = &[x; 3]; + let y = z as *const &i32; + y //~ ERROR +} + +fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] { + let z = &[x; 3]; + let y = z as *const [&i32; 3]; + y //~ ERROR +} + +fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] { + let z = &[[x; 2]; 3]; + let y = z as *const [&i32; 2]; + y //~ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/type-check-pointer-coercions.stderr b/tests/ui/nll/type-check-pointer-coercions.stderr new file mode 100644 index 000000000..ef2d92878 --- /dev/null +++ b/tests/ui/nll/type-check-pointer-coercions.stderr @@ -0,0 +1,111 @@ +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:2:5 + | +LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:6:5 + | +LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:11:5 + | +LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Two errors because *mut is invariant +LL | x + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable pointer to `&i32` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:11:5 + | +LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Two errors because *mut is invariant +LL | x + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable pointer to `&i32` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +help: `'b` and `'a` must be the same: replace one with the other + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:16:5 + | +LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:22:5 + | +LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | y + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:28:5 + | +LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | y + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:34:5 + | +LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | y + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/nll/type-check-pointer-comparisons.rs b/tests/ui/nll/type-check-pointer-comparisons.rs new file mode 100644 index 000000000..7b0ffeaef --- /dev/null +++ b/tests/ui/nll/type-check-pointer-comparisons.rs @@ -0,0 +1,31 @@ +// Check that we assert that pointers have a common subtype for comparisons + +fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { + x == y; + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { + x == y; + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { + f == g; + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) { + // Ideally this should compile with the operands swapped as well, but HIR + // type checking prevents it (and stops compilation) for now. + f == g; // OK +} + +fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) { + f == g; // OK +} + +fn main() {} diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr new file mode 100644 index 000000000..0d8480a42 --- /dev/null +++ b/tests/ui/nll/type-check-pointer-comparisons.stderr @@ -0,0 +1,98 @@ +error: lifetime may not live long enough + --> $DIR/type-check-pointer-comparisons.rs:4:5 + | +LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x == y; + | ^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-comparisons.rs:4:10 + | +LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x == y; + | ^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-comparisons.rs:10:5 + | +LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x == y; + | ^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable pointer to `&i32` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-comparisons.rs:10:10 + | +LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x == y; + | ^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable pointer to `&i32` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-comparisons.rs:16:5 + | +LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | f == g; + | ^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-comparisons.rs:16:10 + | +LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | f == g; + | ^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&i32` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 6 previous errors + diff --git a/tests/ui/nll/type-test-universe.rs b/tests/ui/nll/type-test-universe.rs new file mode 100644 index 000000000..f9801c07d --- /dev/null +++ b/tests/ui/nll/type-test-universe.rs @@ -0,0 +1,21 @@ +// Regression test for #98095: make sure that +// we detect that S needs to outlive 'static. + +fn outlives_forall() +where + for<'u> T: 'u, +{ +} + +fn test1() { + outlives_forall::(); + //~^ ERROR `S` does not live long enough +} + +struct Value<'a>(&'a ()); +fn test2<'a>() { + outlives_forall::>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/type-test-universe.stderr b/tests/ui/nll/type-test-universe.stderr new file mode 100644 index 000000000..31e17d64b --- /dev/null +++ b/tests/ui/nll/type-test-universe.stderr @@ -0,0 +1,22 @@ +error: `S` does not live long enough + --> $DIR/type-test-universe.rs:11:5 + | +LL | outlives_forall::(); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: lifetime may not live long enough + --> $DIR/type-test-universe.rs:17:5 + | +LL | fn test2<'a>() { + | -- lifetime `'a` defined here +LL | outlives_forall::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/type-test-universe.rs:6:16 + | +LL | for<'u> T: 'u, + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/unused-mut-issue-50343.fixed b/tests/ui/nll/unused-mut-issue-50343.fixed new file mode 100644 index 000000000..5632de1cd --- /dev/null +++ b/tests/ui/nll/unused-mut-issue-50343.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#![deny(unused_mut)] +#![allow(unused_variables)] // for rustfix + +fn main() { + vec![(42, 22)].iter().map(|(x, _y)| ()).count(); + //~^ ERROR: variable does not need to be mutable +} diff --git a/tests/ui/nll/unused-mut-issue-50343.rs b/tests/ui/nll/unused-mut-issue-50343.rs new file mode 100644 index 000000000..c849ac8c7 --- /dev/null +++ b/tests/ui/nll/unused-mut-issue-50343.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#![deny(unused_mut)] +#![allow(unused_variables)] // for rustfix + +fn main() { + vec![(42, 22)].iter().map(|(mut x, _y)| ()).count(); + //~^ ERROR: variable does not need to be mutable +} diff --git a/tests/ui/nll/unused-mut-issue-50343.stderr b/tests/ui/nll/unused-mut-issue-50343.stderr new file mode 100644 index 000000000..cb02d7620 --- /dev/null +++ b/tests/ui/nll/unused-mut-issue-50343.stderr @@ -0,0 +1,16 @@ +error: variable does not need to be mutable + --> $DIR/unused-mut-issue-50343.rs:7:33 + | +LL | vec![(42, 22)].iter().map(|(mut x, _y)| ()).count(); + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/unused-mut-issue-50343.rs:3:9 + | +LL | #![deny(unused_mut)] + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/adt-brace-enums.rs b/tests/ui/nll/user-annotations/adt-brace-enums.rs new file mode 100644 index 000000000..0d9828342 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-brace-enums.rs @@ -0,0 +1,50 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +enum SomeEnum { + SomeVariant { t: T } +} + +fn no_annot() { + let c = 66; + SomeEnum::SomeVariant { t: &c }; +} + +fn annot_underscore() { + let c = 66; + SomeEnum::SomeVariant::<_> { t: &c }; +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&u32> { t: &c }; +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&'static u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeEnum::SomeVariant::<&'a u32> { t: c }; +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeEnum::SomeVariant::<&'a u32> { t: &c }; //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeEnum::SomeVariant::<&'a u32> { t: c }; + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/adt-brace-enums.stderr b/tests/ui/nll/user-annotations/adt-brace-enums.stderr new file mode 100644 index 000000000..253e38251 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-brace-enums.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-enums.rs:25:48 + | +LL | SomeEnum::SomeVariant::<&'static u32> { t: &c }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-enums.rs:30:43 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +LL | let c = 66; +LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-enums.rs:40:47 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | SomeEnum::SomeVariant::<&'a u32> { t: &c }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/adt-brace-structs.rs b/tests/ui/nll/user-annotations/adt-brace-structs.rs new file mode 100644 index 000000000..bdbfd87d5 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-brace-structs.rs @@ -0,0 +1,48 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +struct SomeStruct { t: T } + +fn no_annot() { + let c = 66; + SomeStruct { t: &c }; +} + +fn annot_underscore() { + let c = 66; + SomeStruct::<_> { t: &c }; +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeStruct::<&u32> { t: &c }; +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeStruct::<&'static u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeStruct::<&'a u32> { t: &c }; //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeStruct::<&'a u32> { t: c }; +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeStruct::<&'a u32> { t: &c }; //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeStruct::<&'a u32> { t: c }; + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/adt-brace-structs.stderr b/tests/ui/nll/user-annotations/adt-brace-structs.stderr new file mode 100644 index 000000000..8b9d1705d --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-brace-structs.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-structs.rs:23:37 + | +LL | SomeStruct::<&'static u32> { t: &c }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-structs.rs:28:32 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +LL | let c = 66; +LL | SomeStruct::<&'a u32> { t: &c }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-brace-structs.rs:38:36 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | SomeStruct::<&'a u32> { t: &c }; + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.rs b/tests/ui/nll/user-annotations/adt-nullary-enums.rs new file mode 100644 index 000000000..53853668d --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-nullary-enums.rs @@ -0,0 +1,69 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![allow(warnings)] + +use std::cell::Cell; + +enum SomeEnum { + SomeVariant(T), + SomeOtherVariant, +} + +fn combine(_: T, _: T) { } + +fn no_annot() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant); +} + +fn annot_underscore() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); +} + +fn annot_reference_any_lifetime() { + let c = 66; + combine(SomeEnum::SomeVariant(Cell::new(&c)), SomeEnum::SomeOtherVariant::>); +} + +fn annot_reference_static_lifetime() { + let c = 66; + combine( + SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR + SomeEnum::SomeOtherVariant::>, + ); +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + combine( + SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR + SomeEnum::SomeOtherVariant::>, + ); +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + combine(SomeEnum::SomeVariant(Cell::new(c)), SomeEnum::SomeOtherVariant::>); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + combine( + SomeEnum::SomeVariant(Cell::new(&c)), //~ ERROR + SomeEnum::SomeOtherVariant::>, + ); + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + combine( + SomeEnum::SomeVariant(Cell::new(c)), + SomeEnum::SomeOtherVariant::>, + ); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr new file mode 100644 index 000000000..3326fa521 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -0,0 +1,45 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-nullary-enums.rs:33:41 + | +LL | / combine( +LL | | SomeEnum::SomeVariant(Cell::new(&c)), + | | ^^ borrowed value does not live long enough +LL | | SomeEnum::SomeOtherVariant::>, +LL | | ); + | |_____- argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-nullary-enums.rs:41:41 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +... +LL | SomeEnum::SomeVariant(Cell::new(&c)), + | ----------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +... +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-nullary-enums.rs:54:45 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | SomeEnum::SomeVariant(Cell::new(&c)), + | ----------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +... +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/adt-tuple-enums.rs b/tests/ui/nll/user-annotations/adt-tuple-enums.rs new file mode 100644 index 000000000..efe8dfda1 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-tuple-enums.rs @@ -0,0 +1,53 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +#![allow(warnings)] + +enum SomeEnum { + SomeVariant(T), + SomeOtherVariant, +} + +fn no_annot() { + let c = 66; + SomeEnum::SomeVariant(&c); +} + +fn annot_underscore() { + let c = 66; + SomeEnum::SomeVariant::<_>(&c); +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&u32>(&c); +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeEnum::SomeVariant::<&'static u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeEnum::SomeVariant::<&'a u32>(c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeEnum::SomeVariant::<&'a u32>(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeEnum::SomeVariant::<&'a u32>(c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/adt-tuple-enums.stderr b/tests/ui/nll/user-annotations/adt-tuple-enums.stderr new file mode 100644 index 000000000..2fa704263 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-tuple-enums.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-enums.rs:28:43 + | +LL | SomeEnum::SomeVariant::<&'static u32>(&c); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-enums.rs:33:38 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +LL | let c = 66; +LL | SomeEnum::SomeVariant::<&'a u32>(&c); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-enums.rs:43:42 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | SomeEnum::SomeVariant::<&'a u32>(&c); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs new file mode 100644 index 000000000..116583223 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.rs @@ -0,0 +1,71 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +struct SomeStruct(T); + +fn no_annot() { + let c = 66; + let f = SomeStruct; + f(&c); +} + +fn annot_underscore() { + let c = 66; + let f = SomeStruct::<_>; + f(&c); +} + +fn annot_reference_any_lifetime() { + let c = 66; + let f = SomeStruct::<&u32>; + f(&c); +} + +fn annot_reference_static_lifetime() { + let c = 66; + let f = SomeStruct::<&'static u32>; + f(&c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + let f = SomeStruct::<&'a u32>; + f(&c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + let f = SomeStruct::<&'a u32>; + f(c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + let f = SomeStruct::<&'a u32>; + f(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_across_closure<'a>(_: &'a u32) { + let f = SomeStruct::<&'a u32>; + let _closure = || { + let c = 66; + f(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + let f = SomeStruct::<&'a u32>; + f(c); + }; +} + +fn annot_reference_named_lifetime_across_closure_ok<'a>(c: &'a u32) { + let f = SomeStruct::<&'a u32>; + let _closure = || { + f(c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr new file mode 100644 index 000000000..9664fb9f5 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr @@ -0,0 +1,56 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct-calls.rs:27:7 + | +LL | f(&c); + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct-calls.rs:33:7 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +... +LL | f(&c); + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct-calls.rs:45:11 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | f(&c); + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct-calls.rs:53:11 + | +LL | let f = SomeStruct::<&'a u32>; + | - lifetime `'1` appears in the type of `f` +... +LL | f(&c); + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'1` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct.rs b/tests/ui/nll/user-annotations/adt-tuple-struct.rs new file mode 100644 index 000000000..37284e1fd --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-tuple-struct.rs @@ -0,0 +1,48 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +struct SomeStruct(T); + +fn no_annot() { + let c = 66; + SomeStruct(&c); +} + +fn annot_underscore() { + let c = 66; + SomeStruct::<_>(&c); +} + +fn annot_reference_any_lifetime() { + let c = 66; + SomeStruct::<&u32>(&c); +} + +fn annot_reference_static_lifetime() { + let c = 66; + SomeStruct::<&'static u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + SomeStruct::<&'a u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + SomeStruct::<&'a u32>(c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + SomeStruct::<&'a u32>(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + SomeStruct::<&'a u32>(c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct.stderr new file mode 100644 index 000000000..76b525225 --- /dev/null +++ b/tests/ui/nll/user-annotations/adt-tuple-struct.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct.rs:23:32 + | +LL | SomeStruct::<&'static u32>(&c); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct.rs:28:27 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +LL | let c = 66; +LL | SomeStruct::<&'a u32>(&c); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/adt-tuple-struct.rs:38:31 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | SomeStruct::<&'a u32>(&c); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/ascribed-type-wf.rs b/tests/ui/nll/user-annotations/ascribed-type-wf.rs new file mode 100644 index 000000000..5db02c46e --- /dev/null +++ b/tests/ui/nll/user-annotations/ascribed-type-wf.rs @@ -0,0 +1,17 @@ +// Regression test for #101350. +// check-fail + +trait Trait { + type Ty; +} + +impl Trait for &'static () { + type Ty = (); +} + +fn extend<'a>() { + None::<<&'a () as Trait>::Ty>; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/ascribed-type-wf.stderr b/tests/ui/nll/user-annotations/ascribed-type-wf.stderr new file mode 100644 index 000000000..91e7c6b8e --- /dev/null +++ b/tests/ui/nll/user-annotations/ascribed-type-wf.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/ascribed-type-wf.rs:13:5 + | +LL | fn extend<'a>() { + | -- lifetime `'a` defined here +LL | None::<<&'a () as Trait>::Ty>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/cast_static_lifetime.rs b/tests/ui/nll/user-annotations/cast_static_lifetime.rs new file mode 100644 index 000000000..bb6129dac --- /dev/null +++ b/tests/ui/nll/user-annotations/cast_static_lifetime.rs @@ -0,0 +1,6 @@ +#![allow(warnings)] + +fn main() { + let x = 22_u32; + let y: &u32 = (&x) as &'static u32; //~ ERROR `x` does not live long enough +} diff --git a/tests/ui/nll/user-annotations/cast_static_lifetime.stderr b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr new file mode 100644 index 000000000..4599d04e7 --- /dev/null +++ b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr @@ -0,0 +1,14 @@ +error[E0597]: `x` does not live long enough + --> $DIR/cast_static_lifetime.rs:5:19 + | +LL | let y: &u32 = (&x) as &'static u32; + | ^^^^---------------- + | | + | borrowed value does not live long enough + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/closure-sig.rs b/tests/ui/nll/user-annotations/closure-sig.rs new file mode 100644 index 000000000..4dbd3fd8d --- /dev/null +++ b/tests/ui/nll/user-annotations/closure-sig.rs @@ -0,0 +1,15 @@ +// This test fails if #104478 is fixed before #104477. + +// check-pass + +struct Printer<'a, 'b>(&'a (), &'b ()); + +impl Printer<'_, '_> { + fn test(self) { + let clo = |_: &'_ Self| {}; + clo(&self); + clo(&self); + } +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/closure-substs.polonius.stderr b/tests/ui/nll/user-annotations/closure-substs.polonius.stderr new file mode 100644 index 000000000..af159a6cd --- /dev/null +++ b/tests/ui/nll/user-annotations/closure-substs.polonius.stderr @@ -0,0 +1,61 @@ +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:8:16 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +... +LL | return x; + | ^ returning this value requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:15:16 + | +LL | |x: &i32| -> &'static i32 { + | - let's call the lifetime of this reference `'1` +LL | return x; + | ^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:15:16 + | +LL | |x: &i32| -> &'static i32 { + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | return x; + | ^ returning this value requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:22:9 + | +LL | fn bar<'a>() { + | -- lifetime `'a` defined here +... +LL | b(x); + | ^^^^ argument requires that `'a` must outlive `'static` + | + = help: consider replacing `'a` with `'static` + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/closure-substs.rs:29:9 + | +LL | |x: &i32, b: fn(&'static i32)| { + | - `x` is a reference that is only valid in the closure body +LL | b(x); + | ^^^^ `x` escapes the closure body here + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/closure-substs.rs:29:9 + | +LL | |x: &i32, b: fn(&'static i32)| { + | - - `b` declared here, outside of the closure body + | | + | `x` is a reference that is only valid in the closure body +LL | b(x); + | ^^^^ `x` escapes the closure body here + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/user-annotations/closure-substs.rs b/tests/ui/nll/user-annotations/closure-substs.rs new file mode 100644 index 000000000..f7af54e8d --- /dev/null +++ b/tests/ui/nll/user-annotations/closure-substs.rs @@ -0,0 +1,31 @@ +// Test that we enforce user-provided type annotations on closures. + +fn foo<'a>() { + // Here `x` is free in the closure sig: + |x: &'a i32| -> &'static i32 { + return x; //~ ERROR lifetime may not live long enough + }; +} + +fn foo1() { + // Here `x` is bound in the closure sig: + |x: &i32| -> &'static i32 { + return x; //~ ERROR lifetime may not live long enough + }; +} + +fn bar<'a>() { + // Here `x` is free in the closure sig: + |x: &'a i32, b: fn(&'static i32)| { + b(x); //~ ERROR lifetime may not live long enough + }; +} + +fn bar1() { + // Here `x` is bound in the closure sig: + |x: &i32, b: fn(&'static i32)| { + b(x); //~ ERROR borrowed data escapes outside of closure + }; +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/closure-substs.stderr b/tests/ui/nll/user-annotations/closure-substs.stderr new file mode 100644 index 000000000..1e8de4ba9 --- /dev/null +++ b/tests/ui/nll/user-annotations/closure-substs.stderr @@ -0,0 +1,42 @@ +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:6:16 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +... +LL | return x; + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:13:16 + | +LL | |x: &i32| -> &'static i32 { + | - let's call the lifetime of this reference `'1` +LL | return x; + | ^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/closure-substs.rs:20:9 + | +LL | fn bar<'a>() { + | -- lifetime `'a` defined here +... +LL | b(x); + | ^^^^ argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of closure + --> $DIR/closure-substs.rs:27:9 + | +LL | |x: &i32, b: fn(&'static i32)| { + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the closure body +LL | b(x); + | ^^^^ + | | + | `x` escapes the closure body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs new file mode 100644 index 000000000..e3a8a5f58 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.rs @@ -0,0 +1,12 @@ +struct Foo<'a> { x: &'a u32 } + +impl<'a> Foo<'a> { + const C: &'a u32 = &22; +} + +fn foo<'a>(_: &'a u32) -> &'static u32 { + >::C //~ ERROR +} + +fn main() { +} diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr new file mode 100644 index 000000000..c39301588 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/constant-in-expr-inherent-1.rs:8:5 + | +LL | fn foo<'a>(_: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | >::C + | ^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs new file mode 100644 index 000000000..90696d4b1 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.rs @@ -0,0 +1,27 @@ +// Test that we still check constants are well-formed, even when we there's no +// type annotation to check. + +const FUN: fn(&'static ()) = |_| {}; +struct A; +impl A { + const ASSOCIATED_FUN: fn(&'static ()) = |_| {}; +} + +struct B<'a>(&'a ()); +impl B<'static> { + const ALSO_ASSOCIATED_FUN: fn(&'static ()) = |_| {}; +} + +trait Z: 'static { + const TRAIT_ASSOCIATED_FUN: fn(&'static Self) = |_| (); +} + +impl Z for () {} + +fn main() { + let x = (); + FUN(&x); //~ ERROR `x` does not live long enough + A::ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough + B::ALSO_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough + <_>::TRAIT_ASSOCIATED_FUN(&x); //~ ERROR `x` does not live long enough +} diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr new file mode 100644 index 000000000..12065a85a --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr @@ -0,0 +1,50 @@ +error[E0597]: `x` does not live long enough + --> $DIR/constant-in-expr-inherent-2.rs:23:9 + | +LL | FUN(&x); + | ----^^- + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/constant-in-expr-inherent-2.rs:24:23 + | +LL | A::ASSOCIATED_FUN(&x); + | ------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/constant-in-expr-inherent-2.rs:25:28 + | +LL | B::ALSO_ASSOCIATED_FUN(&x); + | -----------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +LL | <_>::TRAIT_ASSOCIATED_FUN(&x); +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/constant-in-expr-inherent-2.rs:26:31 + | +LL | <_>::TRAIT_ASSOCIATED_FUN(&x); + | --------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/constant-in-expr-normalize.rs b/tests/ui/nll/user-annotations/constant-in-expr-normalize.rs new file mode 100644 index 000000000..b7095430d --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-normalize.rs @@ -0,0 +1,22 @@ +trait Mirror { + type Me; +} + +impl Mirror for T { + type Me = T; +} + +trait Foo<'a> { + const C: <&'a u32 as Mirror>::Me; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo<'a>(_: &'a u32) -> &'static u32 { + <() as Foo<'a>>::C //~ ERROR +} + +fn main() { +} diff --git a/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr new file mode 100644 index 000000000..541a2cfaf --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-normalize.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/constant-in-expr-normalize.rs:18:5 + | +LL | fn foo<'a>(_: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | <() as Foo<'a>>::C + | ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs new file mode 100644 index 000000000..e0400b2cc --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.rs @@ -0,0 +1,14 @@ +trait Foo<'a> { + const C: &'a u32; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo<'a>(_: &'a u32) -> &'static u32 { + <() as Foo<'a>>::C //~ ERROR +} + +fn main() { +} diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr new file mode 100644 index 000000000..ea0fcb6d6 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/constant-in-expr-trait-item-1.rs:10:5 + | +LL | fn foo<'a>(_: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | <() as Foo<'a>>::C + | ^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs new file mode 100644 index 000000000..73c4e577b --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.rs @@ -0,0 +1,14 @@ +trait Foo<'a> { + const C: &'a u32; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo<'a, T: Foo<'a>>() -> &'static u32 { + >::C //~ ERROR +} + +fn main() { +} diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr new file mode 100644 index 000000000..ff549f1d8 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/constant-in-expr-trait-item-2.rs:10:5 + | +LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { + | -- lifetime `'a` defined here +LL | >::C + | ^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs new file mode 100644 index 000000000..567e31ef9 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.rs @@ -0,0 +1,14 @@ +trait Foo<'a> { + const C: &'a u32; +} + +impl<'a, T> Foo<'a> for T { + const C: &'a u32 = &22; +} + +fn foo<'a, T: Foo<'a>>() -> &'static u32 { + T::C //~ ERROR +} + +fn main() { +} diff --git a/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr new file mode 100644 index 000000000..7f160d8e3 --- /dev/null +++ b/tests/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/constant-in-expr-trait-item-3.rs:10:5 + | +LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { + | -- lifetime `'a` defined here +LL | T::C + | ^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/downcast-infer.rs b/tests/ui/nll/user-annotations/downcast-infer.rs new file mode 100644 index 000000000..b27429f4d --- /dev/null +++ b/tests/ui/nll/user-annotations/downcast-infer.rs @@ -0,0 +1,11 @@ +// check-pass + +// Check that we don't try to downcast `_` when type-checking the annotation. +fn main() { + let x = Some(Some(Some(1))); + + match x { + Some::>(Some(Some(v))) => (), + _ => (), + } +} diff --git a/tests/ui/nll/user-annotations/dump-adt-brace-struct.rs b/tests/ui/nll/user-annotations/dump-adt-brace-struct.rs new file mode 100644 index 000000000..ccda9129d --- /dev/null +++ b/tests/ui/nll/user-annotations/dump-adt-brace-struct.rs @@ -0,0 +1,20 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +struct SomeStruct { t: T } + +#[rustc_dump_user_substs] +fn main() { + SomeStruct { t: 22 }; // Nothing given, no annotation. + + SomeStruct::<_> { t: 22 }; // Nothing interesting given, no annotation. + + SomeStruct:: { t: 22 }; // No lifetime bounds given. + + SomeStruct::<&'static u32> { t: &22 }; //~ ERROR [&ReStatic u32] +} diff --git a/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr b/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr new file mode 100644 index 000000000..586062190 --- /dev/null +++ b/tests/ui/nll/user-annotations/dump-adt-brace-struct.stderr @@ -0,0 +1,8 @@ +error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None } + --> $DIR/dump-adt-brace-struct.rs:19:5 + | +LL | SomeStruct::<&'static u32> { t: &22 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/dump-fn-method.rs b/tests/ui/nll/user-annotations/dump-fn-method.rs new file mode 100644 index 000000000..148d63d84 --- /dev/null +++ b/tests/ui/nll/user-annotations/dump-fn-method.rs @@ -0,0 +1,57 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +// compile-flags:-Zverbose + +#![feature(rustc_attrs)] + +// Note: we reference the names T and U in the comments below. +trait Bazoom { + fn method(&self, arg: T, arg2: U) { } +} + +impl Bazoom for S { +} + +fn foo<'a, T>(_: T) { } + +#[rustc_dump_user_substs] +fn main() { + // Here: nothing is given, so we don't have any annotation. + let x = foo; + x(22); + + // Here: `u32` is given, which doesn't contain any lifetimes, so we don't + // have any annotation. + let x = foo::; + x(22); + + let x = foo::<&'static u32>; //~ ERROR [&ReStatic u32] + x(&22); + + // Here: we only want the `T` to be given, the rest should be variables. + // + // (`T` refers to the declaration of `Bazoom`) + let x = <_ as Bazoom>::method::<_>; //~ ERROR [^0, u32, ^1] + x(&22, 44, 66); + + // Here: all are given and definitely contain no lifetimes, so we + // don't have any annotation. + let x = >::method::; + x(&22, 44, 66); + + // Here: all are given and we have a lifetime. + let x = >::method::; //~ ERROR [u8, &ReStatic u16, u32] + x(&22, &44, 66); + + // Here: we want in particular that *only* the method `U` + // annotation is given, the rest are variables. + // + // (`U` refers to the declaration of `Bazoom`) + let y = 22_u32; + y.method::(44, 66); //~ ERROR [^0, ^1, u32] + + // Here: nothing is given, so we don't have any annotation. + let y = 22_u32; + y.method(44, 66); +} diff --git a/tests/ui/nll/user-annotations/dump-fn-method.stderr b/tests/ui/nll/user-annotations/dump-fn-method.stderr new file mode 100644 index 000000000..d139efa88 --- /dev/null +++ b/tests/ui/nll/user-annotations/dump-fn-method.stderr @@ -0,0 +1,26 @@ +error: user substs: UserSubsts { substs: [&ReStatic u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:29:13 + | +LL | let x = foo::<&'static u32>; + | ^^^^^^^^^^^^^^^^^^^ + +error: user substs: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } + --> $DIR/dump-fn-method.rs:35:13 + | +LL | let x = <_ as Bazoom>::method::<_>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: user substs: UserSubsts { substs: [u8, &ReStatic u16, u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:44:13 + | +LL | let x = >::method::; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: user substs: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } + --> $DIR/dump-fn-method.rs:52:5 + | +LL | y.method::(44, 66); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/nll/user-annotations/fns.rs b/tests/ui/nll/user-annotations/fns.rs new file mode 100644 index 000000000..38db6d1c4 --- /dev/null +++ b/tests/ui/nll/user-annotations/fns.rs @@ -0,0 +1,48 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +fn some_fn(arg: T) { } + +fn no_annot() { + let c = 66; + some_fn(&c); // OK +} + +fn annot_underscore() { + let c = 66; + some_fn::<_>(&c); // OK +} + +fn annot_reference_any_lifetime() { + let c = 66; + some_fn::<&u32>(&c); // OK +} + +fn annot_reference_static_lifetime() { + let c = 66; + some_fn::<&'static u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let c = 66; + some_fn::<&'a u32>(&c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + some_fn::<&'a u32>(c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let _closure = || { + let c = 66; + some_fn::<&'a u32>(&c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let _closure = || { + some_fn::<&'a u32>(c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/fns.stderr b/tests/ui/nll/user-annotations/fns.stderr new file mode 100644 index 000000000..e0640da39 --- /dev/null +++ b/tests/ui/nll/user-annotations/fns.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/fns.rs:23:29 + | +LL | some_fn::<&'static u32>(&c); + | ------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/fns.rs:28:24 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +LL | let c = 66; +LL | some_fn::<&'a u32>(&c); + | -------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/fns.rs:38:28 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | some_fn::<&'a u32>(&c); + | -------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/inherent-associated-constants.rs b/tests/ui/nll/user-annotations/inherent-associated-constants.rs new file mode 100644 index 000000000..fe2641fd6 --- /dev/null +++ b/tests/ui/nll/user-annotations/inherent-associated-constants.rs @@ -0,0 +1,15 @@ +struct A<'a>(&'a ()); + +impl A<'static> { + const IC: i32 = 10; +} + +fn non_wf_associated_const<'a>(x: i32) { + A::<'a>::IC; //~ ERROR lifetime may not live long enough +} + +fn wf_associated_const<'a>(x: i32) { + A::<'static>::IC; +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/inherent-associated-constants.stderr b/tests/ui/nll/user-annotations/inherent-associated-constants.stderr new file mode 100644 index 000000000..ffbfc40f5 --- /dev/null +++ b/tests/ui/nll/user-annotations/inherent-associated-constants.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/inherent-associated-constants.rs:8:5 + | +LL | fn non_wf_associated_const<'a>(x: i32) { + | -- lifetime `'a` defined here +LL | A::<'a>::IC; + | ^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/nll/user-annotations/issue-54124.rs b/tests/ui/nll/user-annotations/issue-54124.rs new file mode 100644 index 000000000..5ae03c894 --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-54124.rs @@ -0,0 +1,8 @@ +fn test<'a>() { + let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough + //~^ ERROR lifetime may not live long enough +} + +fn main() { + test(); +} diff --git a/tests/ui/nll/user-annotations/issue-54124.stderr b/tests/ui/nll/user-annotations/issue-54124.stderr new file mode 100644 index 000000000..2556af2dd --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-54124.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/issue-54124.rs:2:22 + | +LL | fn test<'a>() { + | -- lifetime `'a` defined here +LL | let _:fn(&()) = |_:&'a ()| {}; + | ^ - let's call the lifetime of this reference `'1` + | | + | requires that `'1` must outlive `'a` + +error: lifetime may not live long enough + --> $DIR/issue-54124.rs:2:22 + | +LL | fn test<'a>() { + | -- lifetime `'a` defined here +LL | let _:fn(&()) = |_:&'a ()| {}; + | ^ requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs b/tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs new file mode 100644 index 000000000..ff5b2244e --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-54570-bootstrapping.rs @@ -0,0 +1,30 @@ +// check-pass + +// This test is reduced from a scenario pnkfelix encountered while +// bootstrapping the compiler. + +#[derive(Copy, Clone)] +pub struct Spanned { + pub node: T, + pub span: Span, +} + +pub type Variant = Spanned; +// #[derive(Clone)] pub struct Variant { pub node: VariantKind, pub span: Span, } + +#[derive(Clone)] +pub struct VariantKind { } + +#[derive(Copy, Clone)] +pub struct Span; + +pub fn variant_to_span(variant: Variant) { + match variant { + Variant { + span: _span, + .. + } => { } + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/issue-55219.rs b/tests/ui/nll/user-annotations/issue-55219.rs new file mode 100644 index 000000000..147413663 --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-55219.rs @@ -0,0 +1,18 @@ +// Regression test for #55219: +// +// The `Self::HASH_LEN` here expands to a "self-type" where `T` is not +// known. This unbound inference variable was causing an ICE. +// +// check-pass + +pub struct Foo(T); + +impl Foo { + const HASH_LEN: usize = 20; + + fn stuff() { + let _ = Self::HASH_LEN; + } +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/issue-55241.rs b/tests/ui/nll/user-annotations/issue-55241.rs new file mode 100644 index 000000000..29969c7b4 --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-55241.rs @@ -0,0 +1,26 @@ +// Regression test for #55241: +// +// The reference to `C::HASHED_NULL_NODE` resulted in a type like `>::Out`; normalizing this type requires knowing the +// value of `_`; solving that requires having normalized, so we can +// test against `C: NodeCodec` in the environment. +// +// run-pass + +pub trait Hasher { + type Out: Eq; +} + +pub trait NodeCodec { + const HASHED_NULL_NODE: H::Out; +} + +pub trait Trie> { + /// Returns the root of the trie. + fn root(&self) -> &H::Out; + + /// Is the trie empty? + fn is_empty(&self) -> bool { *self.root() == C::HASHED_NULL_NODE } +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs new file mode 100644 index 000000000..c71937a50 --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs @@ -0,0 +1,68 @@ +// This test is ensuring that type ascriptions on let bindings +// constrain both: +// +// 1. the input expression on the right-hand side (after any potential +// coercion, and allowing for covariance), *and* +// +// 2. the bindings (if any) nested within the pattern on the left-hand +// side (and here, the type-constraint is *invariant*). + +#![allow(dead_code, unused_mut)] +type PairUncoupled<'a, 'b, T> = (&'a T, &'b T); +type PairCoupledRegions<'a, T> = (&'a T, &'a T); +type PairCoupledTypes = (T, T); + +fn uncoupled_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((mut y, mut _z),): (PairUncoupled,) = ((s, &_x),); // ok + // Above compiling does *not* imply below would compile. + // ::std::mem::swap(&mut y, &mut _z); + y +} + +fn swap_regions((mut y, mut _z): PairCoupledRegions) { + ::std::mem::swap(&mut y, &mut _z); +} + +fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),): (PairCoupledRegions,) = ((s, &_x),); + // If above line compiled, so should line below ... + + // swap_regions((y, _z)); + + // ... but the ascribed type also invalidates this use of `y` + y //~ ERROR lifetime may not live long enough +} + +fn swap_types((mut y, mut _z): PairCoupledTypes<&u32>) { + ::std::mem::swap(&mut y, &mut _z); +} + +fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),): (PairCoupledTypes<&u32>,) = ((s, &_x),); + // If above line compiled, so should line below ... + + // swap_types((y, _z)); + + // ... but the ascribed type also invalidates this use of `y` + y //~ ERROR lifetime may not live long enough +} + +fn swap_wilds((mut y, mut _z): PairCoupledTypes<&u32>) { + ::std::mem::swap(&mut y, &mut _z); +} + +fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),): (PairCoupledTypes<_>,) = ((s, &_x),); + // If above line compiled, so should line below + // swap_wilds((y, _z)); + + // ... but the ascribed type also invalidates this use of `y` + y //~ ERROR lifetime may not live long enough +} + +fn main() { + uncoupled_lhs(&3, &4); + coupled_regions_lhs(&3, &4); + coupled_types_lhs(&3, &4); + coupled_wilds_lhs(&3, &4); +} diff --git a/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr new file mode 100644 index 000000000..8399ef04e --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/issue-55748-pat-types-constrain-bindings.rs:33:5 + | +LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-55748-pat-types-constrain-bindings.rs:47:5 + | +LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-55748-pat-types-constrain-bindings.rs:60:5 + | +LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs new file mode 100644 index 000000000..95c655654 --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs @@ -0,0 +1,40 @@ +// Check that repeated type variables are correctly handled + +#![allow(unused)] +#![feature(type_ascription)] + +type PairUncoupled<'a, 'b, T> = (&'a T, &'b T); +type PairCoupledTypes = (T, T); +type PairCoupledRegions<'a, T> = (&'a T, &'a T); + +fn uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),) = type_ascribe!(((s, _x),), (PairUncoupled<_>,)); + y // OK +} + +fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledTypes<_>,)); + y //~ ERROR lifetime may not live long enough +} + +fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledRegions<_>,)); + y //~ ERROR lifetime may not live long enough +} + +fn cast_uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),) = ((s, _x),) as (PairUncoupled<_>,); + y // OK +} + +fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,); + y //~ ERROR lifetime may not live long enough +} + +fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,); + y //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr new file mode 100644 index 000000000..8601691e8 --- /dev/null +++ b/tests/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr @@ -0,0 +1,38 @@ +error: lifetime may not live long enough + --> $DIR/issue-57731-ascibed-coupled-types.rs:17:5 + | +LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledTypes<_>,)); +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5 + | +LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let ((y, _z),) = type_ascribe!(((s, _x),), (PairCoupledRegions<_>,)); +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5 + | +LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,); +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5 + | +LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,); +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/nll/user-annotations/method-call.rs b/tests/ui/nll/user-annotations/method-call.rs new file mode 100644 index 000000000..beafc597a --- /dev/null +++ b/tests/ui/nll/user-annotations/method-call.rs @@ -0,0 +1,69 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +trait Bazoom { + fn method(&self, arg: T, arg2: U) { } +} + +impl Bazoom for T { +} + +fn no_annot() { + let a = 22; + let b = 44; + let c = 66; + a.method(b, &c); // OK +} + +fn annot_underscore() { + let a = 22; + let b = 44; + let c = 66; + a.method::<_>(b, &c); // OK +} + +fn annot_reference_any_lifetime() { + let a = 22; + let b = 44; + let c = 66; + a.method::<&u32>(b, &c); // OK +} + +fn annot_reference_static_lifetime() { + let a = 22; + let b = 44; + let c = 66; + a.method::<&'static u32>(b, &c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let a = 22; + let b = 44; + let c = 66; + a.method::<&'a u32>(b, &c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + let a = 22; + let b = 44; + a.method::<&'a u32>(b, c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let a = 22; + let b = 44; + let _closure = || { + let c = 66; + a.method::<&'a u32>(b, &c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let a = 22; + let b = 44; + let _closure = || { + a.method::<&'a u32>(b, c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/method-call.stderr b/tests/ui/nll/user-annotations/method-call.stderr new file mode 100644 index 000000000..10447e45a --- /dev/null +++ b/tests/ui/nll/user-annotations/method-call.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/method-call.rs:36:34 + | +LL | a.method::<&'static u32>(b, &c); + | -----------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/method-call.rs:43:29 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +... +LL | a.method::<&'a u32>(b, &c); + | ------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/method-call.rs:57:33 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | a.method::<&'a u32>(b, &c); + | ------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.rs b/tests/ui/nll/user-annotations/method-ufcs-1.rs new file mode 100644 index 000000000..950771f35 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-1.rs @@ -0,0 +1,63 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +trait Bazoom: Sized { + fn method(self, arg: T, arg2: U) { } +} + +impl Bazoom for T { +} + +fn annot_underscore() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method::<_>(&a, b, c); // OK +} + +fn annot_reference_any_lifetime() { + let a = 22; + let b = 44; + let c = 66; + <&u32 as Bazoom<_>>::method(&a, b, c); // OK +} + +fn annot_reference_static_lifetime() { + let a = 22; + let b = 44; + let c = 66; + let x = <&'static u32 as Bazoom<_>>::method; + x(&a, b, c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let a = 22; + let b = 44; + let c = 66; + <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(a: &'a u32) { + let b = 44; + let c = 66; + <&'a u32 as Bazoom<_>>::method(&a, b, c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let a = 22; + let b = 44; + let _closure = || { + let c = 66; + <&'a u32 as Bazoom<_>>::method(&a, b, c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(a: &'a u32) { + let b = 44; + let c = 66; + let _closure = || { + <&'a u32 as Bazoom<_>>::method(&a, b, c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr new file mode 100644 index 000000000..962ddfd2b --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr @@ -0,0 +1,46 @@ +error[E0597]: `a` does not live long enough + --> $DIR/method-ufcs-1.rs:30:7 + | +LL | x(&a, b, c); + | --^^------- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'static` +LL | } + | - `a` dropped here while still borrowed + +error[E0597]: `a` does not live long enough + --> $DIR/method-ufcs-1.rs:37:36 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +... +LL | <&'a u32 as Bazoom<_>>::method(&a, b, c); + | -------------------------------^^------- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | } + | - `a` dropped here while still borrowed + +error[E0597]: `a` does not live long enough + --> $DIR/method-ufcs-1.rs:51:41 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | let _closure = || { + | -- value captured here +LL | let c = 66; +LL | <&'a u32 as Bazoom<_>>::method(&a, b, c); + | --------------------------------^------- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | }; +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.rs b/tests/ui/nll/user-annotations/method-ufcs-2.rs new file mode 100644 index 000000000..7dc0f0c12 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-2.rs @@ -0,0 +1,63 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +trait Bazoom: Sized { + fn method(self, arg: T, arg2: U) { } +} + +impl Bazoom for T { +} + +fn annot_underscore() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method(a, &b, c); // OK +} + +fn annot_reference_any_lifetime() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<&u32>>::method(a, &b, c); // OK +} + +fn annot_reference_static_lifetime() { + let a = 22; + let b = 44; + let c = 66; + let x = <&'static u32 as Bazoom<_>>::method; + x(&a, b, c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(b: &'a u32) { + let a = 44; + let c = 66; + <_ as Bazoom<&'a u32>>::method(a, &b, c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let a = 22; + let b = 44; + let _closure = || { + let c = 66; + <_ as Bazoom<&'a u32>>::method(a, &b, c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(b: &'a u32) { + let a = 44; + let c = 66; + let _closure = || { + <_ as Bazoom<&'a u32>>::method(a, &b, c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr new file mode 100644 index 000000000..63d59905e --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr @@ -0,0 +1,46 @@ +error[E0597]: `a` does not live long enough + --> $DIR/method-ufcs-2.rs:30:7 + | +LL | x(&a, b, c); + | --^^------- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'static` +LL | } + | - `a` dropped here while still borrowed + +error[E0597]: `b` does not live long enough + --> $DIR/method-ufcs-2.rs:37:39 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +... +LL | <_ as Bazoom<&'a u32>>::method(a, &b, c); + | ----------------------------------^^---- + | | | + | | borrowed value does not live long enough + | argument requires that `b` is borrowed for `'a` +LL | } + | - `b` dropped here while still borrowed + +error[E0597]: `b` does not live long enough + --> $DIR/method-ufcs-2.rs:51:44 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | let _closure = || { + | -- value captured here +LL | let c = 66; +LL | <_ as Bazoom<&'a u32>>::method(a, &b, c); + | -----------------------------------^---- + | | | + | | borrowed value does not live long enough + | argument requires that `b` is borrowed for `'a` +LL | }; +LL | } + | - `b` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-3.rs b/tests/ui/nll/user-annotations/method-ufcs-3.rs new file mode 100644 index 000000000..59d2009d1 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-3.rs @@ -0,0 +1,69 @@ +// Unit test for the "user substitutions" that are annotated on each +// node. + +trait Bazoom { + fn method(&self, arg: T, arg2: U) { } +} + +impl Bazoom for T { +} + +fn no_annot() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method(&a, b, &c); // OK +} + +fn annot_underscore() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method::<_>(&a, b, &c); // OK +} + +fn annot_reference_any_lifetime() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method::<&u32>(&a, b, &c); // OK +} + +fn annot_reference_static_lifetime() { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c); //~ ERROR +} + +fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + let a = 22; + let b = 44; + let c = 66; + <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR +} + +fn annot_reference_named_lifetime_ok<'a>(c: &'a u32) { + let a = 22; + let b = 44; + <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c); +} + +fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + let a = 22; + let b = 44; + let _closure = || { + let c = 66; + <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); //~ ERROR + }; +} + +fn annot_reference_named_lifetime_in_closure_ok<'a>(c: &'a u32) { + let a = 22; + let b = 44; + let _closure = || { + <_ as Bazoom<_>>::method::<&'a u32>(&a, b, c); + }; +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/method-ufcs-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-3.stderr new file mode 100644 index 000000000..e7851833e --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-3.stderr @@ -0,0 +1,42 @@ +error[E0597]: `c` does not live long enough + --> $DIR/method-ufcs-3.rs:36:53 + | +LL | <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c); + | ------------------------------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/method-ufcs-3.rs:43:48 + | +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +... +LL | <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); + | -------------------------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/method-ufcs-3.rs:57:52 + | +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +... +LL | <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c); + | -------------------------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs new file mode 100644 index 000000000..7bfed61d4 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.rs @@ -0,0 +1,18 @@ +// Check that substitutions given on the self type (here, `A`) carry +// through to NLL. + +struct A<'a> { x: &'a u32 } + +impl<'a> A<'a> { + fn new<'b, T>(x: &'a u32, y: T) -> Self { + Self { x } + } +} + +fn foo<'a>() { + let v = 22; + let x = A::<'a>::new(&v, 22); + //~^ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr new file mode 100644 index 000000000..94861babd --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr @@ -0,0 +1,18 @@ +error[E0597]: `v` does not live long enough + --> $DIR/method-ufcs-inherent-1.rs:14:26 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let v = 22; +LL | let x = A::<'a>::new(&v, 22); + | -------------^^----- + | | | + | | borrowed value does not live long enough + | argument requires that `v` is borrowed for `'a` +LL | +LL | } + | - `v` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs new file mode 100644 index 000000000..cfbc0bcf6 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.rs @@ -0,0 +1,19 @@ +// Check that substitutions given on the self type (here, `A`) can be +// used in combination with annotations given for method arguments. + +struct A<'a> { x: &'a u32 } + +impl<'a> A<'a> { + fn new<'b, T>(x: &'a u32, y: T) -> Self { + Self { x } + } +} + +fn foo<'a>() { + let v = 22; + let x = A::<'a>::new::<&'a u32>(&v, &v); + //~^ ERROR + //~| ERROR +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr new file mode 100644 index 000000000..06f20d9b2 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr @@ -0,0 +1,33 @@ +error[E0597]: `v` does not live long enough + --> $DIR/method-ufcs-inherent-2.rs:14:37 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let v = 22; +LL | let x = A::<'a>::new::<&'a u32>(&v, &v); + | ------------------------^^----- + | | | + | | borrowed value does not live long enough + | argument requires that `v` is borrowed for `'a` +... +LL | } + | - `v` dropped here while still borrowed + +error[E0597]: `v` does not live long enough + --> $DIR/method-ufcs-inherent-2.rs:14:41 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let v = 22; +LL | let x = A::<'a>::new::<&'a u32>(&v, &v); + | ----------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `v` is borrowed for `'a` +... +LL | } + | - `v` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs new file mode 100644 index 000000000..7ddb13360 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.rs @@ -0,0 +1,18 @@ +// Check that inherent methods invoked with `::new` style +// carry their annotations through to NLL. + +struct A<'a> { x: &'a u32 } + +impl<'a> A<'a> { + fn new<'b, T>(x: &'a u32, y: T) -> Self { + Self { x } + } +} + +fn foo<'a>() { + let v = 22; + let x = >::new(&v, 22); + //~^ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr new file mode 100644 index 000000000..4ad61dc81 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr @@ -0,0 +1,18 @@ +error[E0597]: `v` does not live long enough + --> $DIR/method-ufcs-inherent-3.rs:14:26 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let v = 22; +LL | let x = >::new(&v, 22); + | -------------^^----- + | | | + | | borrowed value does not live long enough + | argument requires that `v` is borrowed for `'a` +LL | +LL | } + | - `v` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs new file mode 100644 index 000000000..85e759739 --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.rs @@ -0,0 +1,20 @@ +// Check that inherent methods invoked with `::new` style +// carry their annotations through to NLL in connection with +// method type parameters. + +struct A<'a> { x: &'a u32 } + +impl<'a> A<'a> { + fn new<'b, T>(x: &'a u32, y: T) -> Self { + Self { x } + } +} + +fn foo<'a>() { + let v = 22; + let x = >::new::<&'a u32>(&v, &v); + //~^ ERROR + //~| ERROR +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr new file mode 100644 index 000000000..0f83e99cd --- /dev/null +++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr @@ -0,0 +1,33 @@ +error[E0597]: `v` does not live long enough + --> $DIR/method-ufcs-inherent-4.rs:15:37 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let v = 22; +LL | let x = >::new::<&'a u32>(&v, &v); + | ------------------------^^----- + | | | + | | borrowed value does not live long enough + | argument requires that `v` is borrowed for `'a` +... +LL | } + | - `v` dropped here while still borrowed + +error[E0597]: `v` does not live long enough + --> $DIR/method-ufcs-inherent-4.rs:15:41 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let v = 22; +LL | let x = >::new::<&'a u32>(&v, &v); + | ----------------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `v` is borrowed for `'a` +... +LL | } + | - `v` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/normalization-2.rs b/tests/ui/nll/user-annotations/normalization-2.rs new file mode 100644 index 000000000..be23c3b74 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-2.rs @@ -0,0 +1,152 @@ +// Make sure we honor region constraints when normalizing type annotations. + +// check-fail + +#![feature(more_qualified_paths)] + +trait Trait { + type Assoc; +} + +impl Trait for T +where + T: 'static, +{ + type Assoc = MyTy<()>; +} + +enum MyTy { + Unit, + Tuple(), + Struct {}, + Dumb(T), +} + +impl MyTy { + const CONST: () = (); + fn method() {} + fn method2(&self) {} +} + +trait TraitAssoc { + const TRAIT_CONST: (); + fn trait_method(&self); +} +impl TraitAssoc for T { + const TRAIT_CONST: () = (); + fn trait_method(&self) {} +} + +type Ty<'a> = <&'a () as Trait>::Assoc; + +fn test_local<'a>() { + let _: Ty<'a> = MyTy::Unit; + //~^ ERROR lifetime may not live long enough +} + +fn test_closure_sig<'a, 'b>() { + |_: Ty<'a>| {}; + //~^ ERROR lifetime may not live long enough + || -> Option> { None }; + //~^ ERROR lifetime may not live long enough +} + +fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + >::method::>; + //~^ ERROR lifetime may not live long enough + >::method::>; + //~^ ERROR lifetime may not live long enough + + >::trait_method::>; + //~^ ERROR lifetime may not live long enough + >::trait_method::>; + //~^ ERROR lifetime may not live long enough + + >::CONST; + //~^ ERROR lifetime may not live long enough + >::TRAIT_CONST; + //~^ ERROR lifetime may not live long enough + + >::method::>; + >::trait_method::>; + >::CONST; + >::TRAIT_CONST; + + MyTy::Unit::>; + //~^ ERROR lifetime may not live long enough + MyTy::>::Unit; + //~^ ERROR lifetime may not live long enough +} + +fn test_call<'a, 'b, 'c>() { + >::method::>(); + //~^ ERROR lifetime may not live long enough + >::method::>(); + //~^ ERROR lifetime may not live long enough +} + +fn test_variants<'a, 'b, 'c>() { + >::Struct {}; + //~^ ERROR lifetime may not live long enough + >::Tuple(); + //~^ ERROR lifetime may not live long enough + >::Unit; + //~^ ERROR lifetime may not live long enough +} + +fn test_method_call<'a, 'b>(x: MyTy<()>) { + x.method2::>(); + //~^ ERROR lifetime may not live long enough + x.trait_method::>(); + //~^ ERROR lifetime may not live long enough +} + +fn test_struct_path<'a, 'b, 'c, 'd>() { + struct Struct { x: Option, } + + trait Project { + type Struct; + type Enum; + } + impl Project for T { + type Struct = Struct<()>; + type Enum = MyTy<()>; + } + + // Resolves to enum variant + MyTy::>::Struct {}; // without SelfTy + //~^ ERROR lifetime may not live long enough + as Project>::Enum::Struct {}; // with SelfTy + //~^ ERROR lifetime may not live long enough + + // Resolves to struct and associated type respectively + Struct::> { x: None, }; // without SelfTy + //~^ ERROR lifetime may not live long enough + as Project>::Struct { x: None, }; // with SelfTy + //~^ ERROR lifetime may not live long enough +} + +fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + use MyTy::*; + match MyTy::Unit { + Struct::> {..} => {}, + //~^ ERROR lifetime may not live long enough + Tuple::> (..) => {}, + //~^ ERROR lifetime may not live long enough + Unit::> => {}, + //~^ ERROR lifetime may not live long enough + Dumb(_) => {}, + }; + match MyTy::Unit { + >::Struct {..} => {}, + //~^ ERROR lifetime may not live long enough + >::Tuple (..) => {}, + //~^ ERROR lifetime may not live long enough + >::Unit => {}, + //~^ ERROR lifetime may not live long enough + Dumb(_) => {}, + }; +} + + +fn main() {} diff --git a/tests/ui/nll/user-annotations/normalization-2.stderr b/tests/ui/nll/user-annotations/normalization-2.stderr new file mode 100644 index 000000000..5299282ea --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-2.stderr @@ -0,0 +1,296 @@ +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:43:12 + | +LL | fn test_local<'a>() { + | -- lifetime `'a` defined here +LL | let _: Ty<'a> = MyTy::Unit; + | ^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:48:6 + | +LL | fn test_closure_sig<'a, 'b>() { + | -- lifetime `'a` defined here +LL | |_: Ty<'a>| {}; + | ^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:50:11 + | +LL | fn test_closure_sig<'a, 'b>() { + | -- lifetime `'b` defined here +... +LL | || -> Option> { None }; + | ^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:55:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'a` defined here +LL | >::method::>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:57:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'b` defined here +... +LL | >::method::>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:60:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'c` defined here +... +LL | >::trait_method::>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:62:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'d` defined here +... +LL | >::trait_method::>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:65:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'e` defined here +... +LL | >::CONST; + | ^^^^^^^^^^^^^^^ requires that `'e` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:67:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'f` defined here +... +LL | >::TRAIT_CONST; + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'f` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:75:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'g` defined here +... +LL | MyTy::Unit::>; + | ^^^^^^^^^^^^^^^^^^^^ requires that `'g` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:77:5 + | +LL | fn test_path<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h>() { + | -- lifetime `'h` defined here +... +LL | MyTy::>::Unit; + | ^^^^^^^^^^^^^^^^^^^^ requires that `'h` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + = help: replace `'d` with `'static` + = help: replace `'e` with `'static` + = help: replace `'f` with `'static` + = help: replace `'g` with `'static` + = help: replace `'h` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:82:5 + | +LL | fn test_call<'a, 'b, 'c>() { + | -- lifetime `'a` defined here +LL | >::method::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:84:5 + | +LL | fn test_call<'a, 'b, 'c>() { + | -- lifetime `'b` defined here +... +LL | >::method::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:89:5 + | +LL | fn test_variants<'a, 'b, 'c>() { + | -- lifetime `'a` defined here +LL | >::Struct {}; + | ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:91:5 + | +LL | fn test_variants<'a, 'b, 'c>() { + | -- lifetime `'b` defined here +... +LL | >::Tuple(); + | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:93:5 + | +LL | fn test_variants<'a, 'b, 'c>() { + | -- lifetime `'c` defined here +... +LL | >::Unit; + | ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:98:7 + | +LL | fn test_method_call<'a, 'b>(x: MyTy<()>) { + | -- lifetime `'a` defined here +LL | x.method2::>(); + | ^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:100:7 + | +LL | fn test_method_call<'a, 'b>(x: MyTy<()>) { + | -- lifetime `'b` defined here +... +LL | x.trait_method::>(); + | ^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:117:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'a` defined here +... +LL | MyTy::>::Struct {}; // without SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:119:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'b` defined here +... +LL | as Project>::Enum::Struct {}; // with SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:123:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'c` defined here +... +LL | Struct::> { x: None, }; // without SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:125:5 + | +LL | fn test_struct_path<'a, 'b, 'c, 'd>() { + | -- lifetime `'d` defined here +... +LL | as Project>::Struct { x: None, }; // with SelfTy + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + = help: replace `'d` with `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:132:9 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | -- lifetime `'a` defined here +... +LL | Struct::> {..} => {}, + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:134:9 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | -- lifetime `'b` defined here +... +LL | Tuple::> (..) => {}, + | ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:136:9 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | -- lifetime `'c` defined here +... +LL | Unit::> => {}, + | ^^^^^^^^^^^^^^ requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:141:9 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | -- lifetime `'d` defined here +... +LL | >::Struct {..} => {}, + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'d` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:143:9 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | -- lifetime `'e` defined here +... +LL | >::Tuple (..) => {}, + | ^^^^^^^^^^^^^^^^^^^^ requires that `'e` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-2.rs:145:9 + | +LL | fn test_pattern<'a, 'b, 'c, 'd, 'e, 'f>() { + | -- lifetime `'f` defined here +... +LL | >::Unit => {}, + | ^^^^^^^^^^^^^^ requires that `'f` must outlive `'static` + +help: the following changes may resolve your lifetime errors + | + = help: replace `'a` with `'static` + = help: replace `'b` with `'static` + = help: replace `'c` with `'static` + = help: replace `'d` with `'static` + = help: replace `'e` with `'static` + = help: replace `'f` with `'static` + +error: aborting due to 28 previous errors + diff --git a/tests/ui/nll/user-annotations/normalization-default.rs b/tests/ui/nll/user-annotations/normalization-default.rs new file mode 100644 index 000000000..fa52e6d85 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-default.rs @@ -0,0 +1,22 @@ +// check-fail + +trait Trait { type Assoc; } +impl<'a> Trait for &'a () { type Assoc = &'a (); } + +struct MyTuple::Assoc>(T, U); +fn test_tuple(x: &(), y: &()) { + MyTuple::<_>((), x); + //~^ ERROR + let _: MyTuple::<_> = MyTuple((), y); + //~^ ERROR +} + +struct MyStruct::Assoc> { val: (T, U), } +fn test_struct(x: &(), y: &()) { + MyStruct::<_> { val: ((), x) }; + //~^ ERROR + let _: MyStruct::<_> = MyStruct { val: ((), y) }; + //~^ ERROR +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/normalization-default.stderr b/tests/ui/nll/user-annotations/normalization-default.stderr new file mode 100644 index 000000000..6c73ac692 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-default.stderr @@ -0,0 +1,36 @@ +error: lifetime may not live long enough + --> $DIR/normalization-default.rs:8:22 + | +LL | fn test_tuple(x: &(), y: &()) { + | - let's call the lifetime of this reference `'1` +LL | MyTuple::<_>((), x); + | ^ this usage requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-default.rs:10:12 + | +LL | fn test_tuple(x: &(), y: &()) { + | - let's call the lifetime of this reference `'2` +... +LL | let _: MyTuple::<_> = MyTuple((), y); + | ^^^^^^^^^^^^ type annotation requires that `'2` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-default.rs:16:26 + | +LL | fn test_struct(x: &(), y: &()) { + | - let's call the lifetime of this reference `'1` +LL | MyStruct::<_> { val: ((), x) }; + | ^^^^^^^ this usage requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-default.rs:18:12 + | +LL | fn test_struct(x: &(), y: &()) { + | - let's call the lifetime of this reference `'2` +... +LL | let _: MyStruct::<_> = MyStruct { val: ((), y) }; + | ^^^^^^^^^^^^^ type annotation requires that `'2` must outlive `'static` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/nll/user-annotations/normalization-infer.rs b/tests/ui/nll/user-annotations/normalization-infer.rs new file mode 100644 index 000000000..8bfc272d4 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-infer.rs @@ -0,0 +1,40 @@ +// Annnotations may contain projection types with inference variables as input. +// Make sure we don't get ambiguities when normalizing them. + +// check-fail + +// Single impl. +fn test1(a: A, b: B, c: C) { + trait Tr { type Ty; } + impl Tr for (T,) { type Ty = T; } + + let _: <(_,) as Tr>::Ty = a; //~ ERROR type `A` + Some::<<(_,) as Tr>::Ty>(b); //~ ERROR type `B` + || -> <(_,) as Tr>::Ty { c }; //~ ERROR type `C` + |d: <(_,) as Tr>::Ty| -> D { d }; //~ ERROR type `D` +} + + +// Two impls. The selected impl depends on the actual type. +fn test2(a: A, b: B, c: C) { + trait Tr { type Ty; } + impl Tr for (u8, T) { type Ty = T; } + impl Tr for (i8, T) { type Ty = T; } + type Alias = (<(X, Y) as Tr>::Ty, X); + + fn temp() -> String { todo!() } + + // `u8` impl, requires static. + let _: Alias<_, _> = (a, 0u8); //~ ERROR type `A` + Some::>((b, 0u8)); //~ ERROR type `B` + || -> Alias<_, _> { (c, 0u8) }; //~ ERROR type `C` + + let _: Alias<_, _> = (&temp(), 0u8); //~ ERROR temporary value + Some::>((&temp(), 0u8)); //~ ERROR temporary value + + // `i8` impl, no region constraints. + let _: Alias<_, _> = (&temp(), 0i8); + Some::>((&temp(), 0i8)); +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/normalization-infer.stderr b/tests/ui/nll/user-annotations/normalization-infer.stderr new file mode 100644 index 000000000..12854ab68 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-infer.stderr @@ -0,0 +1,101 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/normalization-infer.rs:11:12 + | +LL | let _: <(_,) as Tr>::Ty = a; + | ^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `B` may not live long enough + --> $DIR/normalization-infer.rs:12:5 + | +LL | Some::<<(_,) as Tr>::Ty>(b); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `C` may not live long enough + --> $DIR/normalization-infer.rs:13:11 + | +LL | || -> <(_,) as Tr>::Ty { c }; + | ^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `D` may not live long enough + --> $DIR/normalization-infer.rs:14:6 + | +LL | |d: <(_,) as Tr>::Ty| -> D { d }; + | ^ ...so that the type `D` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test1(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/normalization-infer.rs:28:12 + | +LL | let _: Alias<_, _> = (a, 0u8); + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test2(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `B` may not live long enough + --> $DIR/normalization-infer.rs:29:5 + | +LL | Some::>((b, 0u8)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `B` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test2(a: A, b: B, c: C) { + | +++++++++ + +error[E0310]: the parameter type `C` may not live long enough + --> $DIR/normalization-infer.rs:30:11 + | +LL | || -> Alias<_, _> { (c, 0u8) }; + | ^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test2(a: A, b: B, c: C) { + | +++++++++ + +error[E0716]: temporary value dropped while borrowed + --> $DIR/normalization-infer.rs:32:28 + | +LL | let _: Alias<_, _> = (&temp(), 0u8); + | ----------- ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/normalization-infer.rs:33:27 + | +LL | Some::>((&temp(), 0u8)); + | --^^^^^^------ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | this usage requires that borrow lasts for `'static` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0310, E0716. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/nll/user-annotations/normalization-self.rs b/tests/ui/nll/user-annotations/normalization-self.rs new file mode 100644 index 000000000..c18760b53 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-self.rs @@ -0,0 +1,26 @@ +// check-fail + +trait Trait { type Assoc; } +impl<'a> Trait for &'a () { type Assoc = &'a (); } + +struct MyTuple(T); +impl MyTuple<<&'static () as Trait>::Assoc> { + fn test(x: &(), y: &()) { + Self(x); + //~^ ERROR + let _: Self = MyTuple(y); + //~^ ERROR + } +} + +struct MyStruct { val: T, } +impl MyStruct<<&'static () as Trait>::Assoc> { + fn test(x: &(), y: &()) { + Self { val: x }; + //~^ ERROR + let _: Self = MyStruct { val: y }; + //~^ ERROR + } +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/normalization-self.stderr b/tests/ui/nll/user-annotations/normalization-self.stderr new file mode 100644 index 000000000..e231ed03c --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization-self.stderr @@ -0,0 +1,36 @@ +error: lifetime may not live long enough + --> $DIR/normalization-self.rs:9:14 + | +LL | fn test(x: &(), y: &()) { + | - let's call the lifetime of this reference `'1` +LL | Self(x); + | ^ this usage requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-self.rs:11:16 + | +LL | fn test(x: &(), y: &()) { + | - let's call the lifetime of this reference `'2` +... +LL | let _: Self = MyTuple(y); + | ^^^^ type annotation requires that `'2` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-self.rs:19:21 + | +LL | fn test(x: &(), y: &()) { + | - let's call the lifetime of this reference `'1` +LL | Self { val: x }; + | ^ this usage requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/normalization-self.rs:21:16 + | +LL | fn test(x: &(), y: &()) { + | - let's call the lifetime of this reference `'2` +... +LL | let _: Self = MyStruct { val: y }; + | ^^^^ type annotation requires that `'2` must outlive `'static` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/nll/user-annotations/normalization.rs b/tests/ui/nll/user-annotations/normalization.rs new file mode 100644 index 000000000..c2e892f57 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization.rs @@ -0,0 +1,17 @@ +// Test that we enforce a `&'static` requirement that is only visible +// after normalization. + +trait Foo { type Out; } +impl Foo for () { type Out = &'static u32; } +impl<'a> Foo for &'a () { type Out = &'a u32; } + +fn main() { + let a = 22; + let _: <() as Foo>::Out = &a; //~ ERROR + + let a = 22; + let _: <&'static () as Foo>::Out = &a; //~ ERROR + + let a = 22; + let _: <&'_ () as Foo>::Out = &a; +} diff --git a/tests/ui/nll/user-annotations/normalization.stderr b/tests/ui/nll/user-annotations/normalization.stderr new file mode 100644 index 000000000..975cb4b66 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalization.stderr @@ -0,0 +1,25 @@ +error[E0597]: `a` does not live long enough + --> $DIR/normalization.rs:10:31 + | +LL | let _: <() as Foo>::Out = &a; + | ---------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `a` is borrowed for `'static` +... +LL | } + | - `a` dropped here while still borrowed + +error[E0597]: `a` does not live long enough + --> $DIR/normalization.rs:13:40 + | +LL | let _: <&'static () as Foo>::Out = &a; + | ------------------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `a` is borrowed for `'static` +... +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/normalize-self-ty.rs b/tests/ui/nll/user-annotations/normalize-self-ty.rs new file mode 100644 index 000000000..df905c878 --- /dev/null +++ b/tests/ui/nll/user-annotations/normalize-self-ty.rs @@ -0,0 +1,23 @@ +// Regression test for #55183: check a case where the self type from +// the inherent impl requires normalization to be equal to the +// user-provided type. +// +// check-pass + +trait Mirror { + type Me; +} + +impl Mirror for T { + type Me = T; +} + +struct Foo(A, B); + +impl Foo::Me> { + fn m(_: A) { } +} + +fn main() { + >::m(&22); +} diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs new file mode 100644 index 000000000..59cd69c0c --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.rs @@ -0,0 +1,22 @@ +enum Foo<'a> { + Bar { field: &'a u32 } +} + +fn in_let() { + let y = 22; + let foo = Foo::Bar { field: &y }; + //~^ ERROR `y` does not live long enough + let Foo::Bar::<'static> { field: _z } = foo; +} + +fn in_match() { + let y = 22; + let foo = Foo::Bar { field: &y }; + //~^ ERROR `y` does not live long enough + match foo { + Foo::Bar::<'static> { field: _z } => { + } + } +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr new file mode 100644 index 000000000..a97e7a9fd --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr @@ -0,0 +1,26 @@ +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_brace_enum_variant.rs:7:33 + | +LL | let foo = Foo::Bar { field: &y }; + | ^^ borrowed value does not live long enough +LL | +LL | let Foo::Bar::<'static> { field: _z } = foo; + | --------------------------------- type annotation requires that `y` is borrowed for `'static` +LL | } + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_brace_enum_variant.rs:14:33 + | +LL | let foo = Foo::Bar { field: &y }; + | ^^ borrowed value does not live long enough +... +LL | Foo::Bar::<'static> { field: _z } => { + | --------------------------------- type annotation requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs new file mode 100644 index 000000000..1586c4ea3 --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.rs @@ -0,0 +1,20 @@ +struct Foo<'a> { field: &'a u32 } + +fn in_let() { + let y = 22; + let foo = Foo { field: &y }; + //~^ ERROR `y` does not live long enough + let Foo::<'static> { field: _z } = foo; +} + +fn in_main() { + let y = 22; + let foo = Foo { field: &y }; + //~^ ERROR `y` does not live long enough + match foo { + Foo::<'static> { field: _z } => { + } + } +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr new file mode 100644 index 000000000..408d7c2a5 --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr @@ -0,0 +1,26 @@ +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_brace_struct.rs:5:28 + | +LL | let foo = Foo { field: &y }; + | ^^ borrowed value does not live long enough +LL | +LL | let Foo::<'static> { field: _z } = foo; + | ---------------------------- type annotation requires that `y` is borrowed for `'static` +LL | } + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_brace_struct.rs:12:28 + | +LL | let foo = Foo { field: &y }; + | ^^ borrowed value does not live long enough +... +LL | Foo::<'static> { field: _z } => { + | ---------------------------- type annotation requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs new file mode 100644 index 000000000..6fa59fdd8 --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.rs @@ -0,0 +1,22 @@ +enum Foo<'a> { + Bar(&'a u32) +} + +fn in_let() { + let y = 22; + let foo = Foo::Bar(&y); + //~^ ERROR `y` does not live long enough + let Foo::Bar::<'static>(_z) = foo; +} + +fn in_match() { + let y = 22; + let foo = Foo::Bar(&y); + //~^ ERROR `y` does not live long enough + match foo { + Foo::Bar::<'static>(_z) => { + } + } +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr new file mode 100644 index 000000000..920c906f6 --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr @@ -0,0 +1,26 @@ +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_tuple_enum_variant.rs:7:24 + | +LL | let foo = Foo::Bar(&y); + | ^^ borrowed value does not live long enough +LL | +LL | let Foo::Bar::<'static>(_z) = foo; + | ----------------------- type annotation requires that `y` is borrowed for `'static` +LL | } + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_tuple_enum_variant.rs:14:24 + | +LL | let foo = Foo::Bar(&y); + | ^^ borrowed value does not live long enough +... +LL | Foo::Bar::<'static>(_z) => { + | ----------------------- type annotation requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs new file mode 100644 index 000000000..7486aab0e --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.rs @@ -0,0 +1,20 @@ +struct Foo<'a>(&'a u32); + +fn in_let() { + let y = 22; + let foo = Foo(&y); + //~^ ERROR `y` does not live long enough + let Foo::<'static>(_z) = foo; +} + +fn in_match() { + let y = 22; + let foo = Foo(&y); + //~^ ERROR `y` does not live long enough + match foo { + Foo::<'static>(_z) => { + } + } +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr new file mode 100644 index 000000000..3f01638d8 --- /dev/null +++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr @@ -0,0 +1,26 @@ +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_tuple_struct.rs:5:19 + | +LL | let foo = Foo(&y); + | ^^ borrowed value does not live long enough +LL | +LL | let Foo::<'static>(_z) = foo; + | ------------------ type annotation requires that `y` is borrowed for `'static` +LL | } + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/pattern_substs_on_tuple_struct.rs:12:19 + | +LL | let foo = Foo(&y); + | ^^ borrowed value does not live long enough +... +LL | Foo::<'static>(_z) => { + | ------------------ type annotation requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/patterns.rs b/tests/ui/nll/user-annotations/patterns.rs new file mode 100644 index 000000000..1f635d7f5 --- /dev/null +++ b/tests/ui/nll/user-annotations/patterns.rs @@ -0,0 +1,136 @@ +// Test that various patterns also enforce types. + +fn variable_no_initializer() { + let x = 22; + let y: &'static u32; + y = &x; //~ ERROR +} + +fn tuple_no_initializer() { + + + let x = 22; + let (y, z): (&'static u32, &'static u32); + y = &x; //~ ERROR +} + +fn ref_with_ascribed_static_type() -> u32 { + // Check the behavior in some wacky cases. + let x = 22; + let y = &x; //~ ERROR + let ref z: &'static u32 = y; + **z +} + +fn ref_with_ascribed_any_type() -> u32 { + let x = 22; + let y = &x; + let ref z: &u32 = y; + **z +} + +struct Single { value: T } + +fn struct_no_initializer() { + + + let x = 22; + let Single { value: y }: Single<&'static u32>; + y = &x; //~ ERROR +} + + +fn struct_no_initializer_must_normalize() { + trait Indirect { type Assoc; } + struct StaticU32; + impl Indirect for StaticU32 { type Assoc = &'static u32; } + struct Single2 { value: ::Assoc } + + let x = 22; + let Single2 { value: mut _y }: Single2; + _y = &x; //~ ERROR +} + +fn variable_with_initializer() { + let x = 22; + let y: &'static u32 = &x; //~ ERROR +} + +fn underscore_with_initializer() { + let x = 22; + let _: &'static u32 = &x; //~ ERROR + + let _: Vec<&'static String> = vec![&String::new()]; + //~^ ERROR temporary value dropped while borrowed [E0716] + + let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44); + //~^ ERROR temporary value dropped while borrowed [E0716] + + let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44); + //~^ ERROR temporary value dropped while borrowed [E0716] +} + +fn pair_underscores_with_initializer() { + let x = 22; + let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR +} + +fn pair_variable_with_initializer() { + let x = 22; + let (y, _): (&'static u32, u32) = (&x, 44); //~ ERROR +} + +fn struct_single_field_variable_with_initializer() { + let x = 22; + let Single { value: y }: Single<&'static u32> = Single { value: &x }; //~ ERROR +} + +fn struct_single_field_underscore_with_initializer() { + let x = 22; + let Single { value: _ }: Single<&'static u32> = Single { value: &x }; //~ ERROR +} + +struct Double { value1: T, value2: T } + +fn struct_double_field_underscore_with_initializer() { + let x = 22; + let Double { value1: _, value2: _ }: Double<&'static u32> = Double { + value1: &x, //~ ERROR + value2: &44, + }; +} + +fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 { + + + + + + + let y: &'a u32 = &22; + y //~ ERROR +} + +fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 { + + + + + + + + let (y, _z): (&'a u32, u32) = (&22, 44); + y //~ ERROR +} + +fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 { + let Single { value: y }: Single<&'a u32> = Single { value: &22 }; + y //~ ERROR +} + +fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 { + let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR + y +} + +fn main() { } diff --git a/tests/ui/nll/user-annotations/patterns.stderr b/tests/ui/nll/user-annotations/patterns.stderr new file mode 100644 index 000000000..de6f8f80f --- /dev/null +++ b/tests/ui/nll/user-annotations/patterns.stderr @@ -0,0 +1,189 @@ +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:6:9 + | +LL | let y: &'static u32; + | ------------ type annotation requires that `x` is borrowed for `'static` +LL | y = &x; + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:14:9 + | +LL | let (y, z): (&'static u32, &'static u32); + | ---------------------------- type annotation requires that `x` is borrowed for `'static` +LL | y = &x; + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:20:13 + | +LL | let y = &x; + | ^^ borrowed value does not live long enough +LL | let ref z: &'static u32 = y; + | ------------ type annotation requires that `x` is borrowed for `'static` +LL | **z +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:39:9 + | +LL | let Single { value: y }: Single<&'static u32>; + | -------------------- type annotation requires that `x` is borrowed for `'static` +LL | y = &x; + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:51:10 + | +LL | let Single2 { value: mut _y }: Single2; + | ------------------ type annotation requires that `x` is borrowed for `'static` +LL | _y = &x; + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:56:27 + | +LL | let y: &'static u32 = &x; + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:61:27 + | +LL | let _: &'static u32 = &x; + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0716]: temporary value dropped while borrowed + --> $DIR/patterns.rs:63:41 + | +LL | let _: Vec<&'static String> = vec![&String::new()]; + | -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/patterns.rs:66:52 + | +LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44); + | ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/patterns.rs:69:53 + | +LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44); + | ------------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:75:40 + | +LL | let (_, _): (&'static u32, u32) = (&x, 44); + | ------------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:80:40 + | +LL | let (y, _): (&'static u32, u32) = (&x, 44); + | ------------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:85:69 + | +LL | let Single { value: y }: Single<&'static u32> = Single { value: &x }; + | -------------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:90:69 + | +LL | let Single { value: _ }: Single<&'static u32> = Single { value: &x }; + | -------------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/patterns.rs:98:17 + | +LL | let Double { value1: _, value2: _ }: Double<&'static u32> = Double { + | -------------------- type annotation requires that `x` is borrowed for `'static` +LL | value1: &x, + | ^^ borrowed value does not live long enough +... +LL | } + | - `x` dropped here while still borrowed + +error: lifetime may not live long enough + --> $DIR/patterns.rs:111:5 + | +LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/patterns.rs:123:5 + | +LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/patterns.rs:128:5 + | +LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let Single { value: y }: Single<&'a u32> = Single { value: &22 }; +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/patterns.rs:132:18 + | +LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 { + | -- lifetime `'a` defined here +LL | let (y, _z): (&'static u32, u32) = (x, 44); + | ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 19 previous errors + +Some errors have detailed explanations: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/promoted-annotation.rs b/tests/ui/nll/user-annotations/promoted-annotation.rs new file mode 100644 index 000000000..b92f8bfd2 --- /dev/null +++ b/tests/ui/nll/user-annotations/promoted-annotation.rs @@ -0,0 +1,10 @@ +// Test that type annotations are checked in promoted constants correctly. + +fn foo<'a>() { + let x = 0; + let f = &drop::<&'a i32>; + f(&x); + //~^ ERROR `x` does not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr new file mode 100644 index 000000000..cb99a6a36 --- /dev/null +++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr @@ -0,0 +1,17 @@ +error[E0597]: `x` does not live long enough + --> $DIR/promoted-annotation.rs:6:7 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let x = 0; +LL | let f = &drop::<&'a i32>; + | ---------------- assignment requires that `x` is borrowed for `'a` +LL | f(&x); + | ^^ borrowed value does not live long enough +LL | +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs b/tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs new file mode 100644 index 000000000..1f7c06038 --- /dev/null +++ b/tests/ui/nll/user-annotations/type-annotation-with-hrtb.rs @@ -0,0 +1,33 @@ +// Regression test for issue #69490 + +// check-pass + +pub trait Trait { + const S: &'static str; +} + +impl Trait<()> for T +where + T: for<'a> Trait<&'a ()>, +{ + // Use of `T::S` here caused an ICE + const S: &'static str = T::S; +} + +// Some similar cases that didn't ICE: + +impl<'a, T> Trait<()> for (T,) +where + T: Trait<&'a ()>, +{ + const S: &'static str = T::S; +} + +impl Trait<()> for [T; 1] +where + T: Trait fn(&'a ())>, +{ + const S: &'static str = T::S; +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs new file mode 100644 index 000000000..88d646dee --- /dev/null +++ b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.rs @@ -0,0 +1,7 @@ +#![allow(warnings)] +#![feature(type_ascription)] + +fn main() { + let x = 22_u32; + let y: &u32 = type_ascribe!(&x, &'static u32); //~ ERROR E0597 +} diff --git a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr new file mode 100644 index 000000000..ccbf3c1d9 --- /dev/null +++ b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr @@ -0,0 +1,14 @@ +error[E0597]: `x` does not live long enough + --> $DIR/type_ascription_static_lifetime.rs:6:33 + | +LL | let y: &u32 = type_ascribe!(&x, &'static u32); + | --------------^^--------------- + | | | + | | borrowed value does not live long enough + | type annotation requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/user-annotations/wf-self-type.rs b/tests/ui/nll/user-annotations/wf-self-type.rs new file mode 100644 index 000000000..539226aab --- /dev/null +++ b/tests/ui/nll/user-annotations/wf-self-type.rs @@ -0,0 +1,13 @@ +struct Foo<'a, 'b: 'a>(&'a &'b ()); + +impl<'a, 'b> Foo<'a, 'b> { + fn xmute(a: &'b ()) -> &'a () { + unreachable!() + } +} + +pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { + Foo::xmute(u) //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/user-annotations/wf-self-type.stderr b/tests/ui/nll/user-annotations/wf-self-type.stderr new file mode 100644 index 000000000..1d3ae7cfb --- /dev/null +++ b/tests/ui/nll/user-annotations/wf-self-type.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/wf-self-type.rs:10:5 + | +LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | Foo::xmute(u) + | ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/nll/vimwiki-core-regression.rs b/tests/ui/nll/vimwiki-core-regression.rs new file mode 100644 index 000000000..0a4ed7e0a --- /dev/null +++ b/tests/ui/nll/vimwiki-core-regression.rs @@ -0,0 +1,37 @@ +// check-pass +// +// Regression test from crater run for +// . + + +pub trait ElementLike {} + +pub struct Located where T: ElementLike { + inner: T, +} + +pub struct BlockElement<'a>(&'a str); + +impl ElementLike for BlockElement<'_> {} + + +pub struct Page<'a> { + /// Comprised of the elements within a page + pub elements: Vec>>, +} + +impl<'a, __IdxT> std::ops::Index<__IdxT> for Page<'a> where + Vec>>: std::ops::Index<__IdxT> +{ + type Output = + >> as + std::ops::Index<__IdxT>>::Output; + + #[inline] + fn index(&self, idx: __IdxT) -> &Self::Output { + >> as + std::ops::Index<__IdxT>>::index(&self.elements, idx) + } +} + +fn main() {} diff --git a/tests/ui/nll/where_clauses_in_functions.rs b/tests/ui/nll/where_clauses_in_functions.rs new file mode 100644 index 000000000..826065d02 --- /dev/null +++ b/tests/ui/nll/where_clauses_in_functions.rs @@ -0,0 +1,15 @@ +#![allow(dead_code)] + +fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) +where + 'a: 'b, +{ + (x, y) +} + +fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + foo(x, y) + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/where_clauses_in_functions.stderr b/tests/ui/nll/where_clauses_in_functions.stderr new file mode 100644 index 000000000..afb25e3bc --- /dev/null +++ b/tests/ui/nll/where_clauses_in_functions.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/where_clauses_in_functions.rs:11:5 + | +LL | fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | foo(x, y) + | ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/nll/where_clauses_in_structs.rs b/tests/ui/nll/where_clauses_in_structs.rs new file mode 100644 index 000000000..fae5d3811 --- /dev/null +++ b/tests/ui/nll/where_clauses_in_structs.rs @@ -0,0 +1,15 @@ +#![allow(dead_code)] + +use std::cell::Cell; + +struct Foo<'a: 'b, 'b> { + x: Cell<&'a u32>, + y: Cell<&'b u32>, +} + +fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) { + Foo { x, y }; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/nll/where_clauses_in_structs.stderr b/tests/ui/nll/where_clauses_in_structs.stderr new file mode 100644 index 000000000..c46cfcb41 --- /dev/null +++ b/tests/ui/nll/where_clauses_in_structs.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/where_clauses_in_structs.rs:11:11 + | +LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | Foo { x, y }; + | ^ this usage requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Cell<&u32>`, which makes the generic argument `&u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/no-capture-arc.rs b/tests/ui/no-capture-arc.rs new file mode 100644 index 000000000..3f0b07577 --- /dev/null +++ b/tests/ui/no-capture-arc.rs @@ -0,0 +1,17 @@ +// error-pattern: borrow of moved value + +use std::sync::Arc; +use std::thread; + +fn main() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let arc_v = Arc::new(v); + + thread::spawn(move|| { + assert_eq!((*arc_v)[3], 4); + }); + + assert_eq!((*arc_v)[2], 3); + + println!("{:?}", *arc_v); +} diff --git a/tests/ui/no-capture-arc.stderr b/tests/ui/no-capture-arc.stderr new file mode 100644 index 000000000..296e1fb3f --- /dev/null +++ b/tests/ui/no-capture-arc.stderr @@ -0,0 +1,19 @@ +error[E0382]: borrow of moved value: `arc_v` + --> $DIR/no-capture-arc.rs:14:16 + | +LL | let arc_v = Arc::new(v); + | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait +LL | +LL | thread::spawn(move|| { + | ------ value moved into closure here +LL | assert_eq!((*arc_v)[3], 4); + | ----- variable moved due to use in closure +... +LL | assert_eq!((*arc_v)[2], 3); + | ^^^^^^^^ value borrowed here after move + | + = note: borrow occurs due to deref coercion to `Vec` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/no-core-1.rs b/tests/ui/no-core-1.rs new file mode 100644 index 000000000..9374f546a --- /dev/null +++ b/tests/ui/no-core-1.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(stable_features)] +#![feature(no_core, core)] +#![no_core] + +extern crate std; +extern crate core; + +use std::option::Option::Some; + +fn main() { + let a = Some("foo"); + a.unwrap(); +} diff --git a/tests/ui/no-core-2.rs b/tests/ui/no-core-2.rs new file mode 100644 index 000000000..b08e63dc7 --- /dev/null +++ b/tests/ui/no-core-2.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(dead_code, unused_imports)] +#![feature(no_core)] +#![no_core] +// edition:2018 + +extern crate std; +extern crate core; +use core::{prelude::v1::*, *}; + +fn foo() { + for _ in &[()] {} +} + +fn bar() -> Option<()> { + None? +} + +fn main() {} diff --git a/tests/ui/no-link-unknown-crate.rs b/tests/ui/no-link-unknown-crate.rs new file mode 100644 index 000000000..c7da2e418 --- /dev/null +++ b/tests/ui/no-link-unknown-crate.rs @@ -0,0 +1,4 @@ +#[no_link] +extern crate doesnt_exist; //~ ERROR can't find crate + +fn main() {} diff --git a/tests/ui/no-link-unknown-crate.stderr b/tests/ui/no-link-unknown-crate.stderr new file mode 100644 index 000000000..068c7139e --- /dev/null +++ b/tests/ui/no-link-unknown-crate.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `doesnt_exist` + --> $DIR/no-link-unknown-crate.rs:2:1 + | +LL | extern crate doesnt_exist; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/no-patterns-in-args-2.rs b/tests/ui/no-patterns-in-args-2.rs new file mode 100644 index 000000000..85b7fc5cd --- /dev/null +++ b/tests/ui/no-patterns-in-args-2.rs @@ -0,0 +1,13 @@ +#![deny(patterns_in_fns_without_body)] + +trait Tr { + fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in functions without bodies + //~^ WARN was previously accepted + fn f2(&arg: u8); //~ ERROR patterns aren't allowed in functions without bodies + fn g1(arg: u8); // OK + fn g2(_: u8); // OK + #[allow(anonymous_parameters)] + fn g3(u8); // OK +} + +fn main() {} diff --git a/tests/ui/no-patterns-in-args-2.stderr b/tests/ui/no-patterns-in-args-2.stderr new file mode 100644 index 000000000..6adcbb9dc --- /dev/null +++ b/tests/ui/no-patterns-in-args-2.stderr @@ -0,0 +1,23 @@ +error[E0642]: patterns aren't allowed in functions without bodies + --> $DIR/no-patterns-in-args-2.rs:6:11 + | +LL | fn f2(&arg: u8); + | ^^^^ pattern not allowed in function without body + +error: patterns aren't allowed in functions without bodies + --> $DIR/no-patterns-in-args-2.rs:4:11 + | +LL | fn f1(mut arg: u8); + | ^^^^^^^ help: remove `mut` from the parameter: `arg` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #35203 +note: the lint level is defined here + --> $DIR/no-patterns-in-args-2.rs:1:9 + | +LL | #![deny(patterns_in_fns_without_body)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/no-patterns-in-args-macro.rs b/tests/ui/no-patterns-in-args-macro.rs new file mode 100644 index 000000000..b5109f9c2 --- /dev/null +++ b/tests/ui/no-patterns-in-args-macro.rs @@ -0,0 +1,26 @@ +macro_rules! m { + ($pat: pat) => { + trait Tr { + fn trait_method($pat: u8); + } + + type A = fn($pat: u8); + + extern "C" { + fn foreign_fn($pat: u8); + } + }; +} + +mod good_pat { + m!(good_pat); // OK +} + +mod bad_pat { + m!((bad, pat)); + //~^ ERROR patterns aren't allowed in function pointer types + //~| ERROR patterns aren't allowed in foreign function declarations + //~| ERROR patterns aren't allowed in functions without bodies +} + +fn main() {} diff --git a/tests/ui/no-patterns-in-args-macro.stderr b/tests/ui/no-patterns-in-args-macro.stderr new file mode 100644 index 000000000..0016c7953 --- /dev/null +++ b/tests/ui/no-patterns-in-args-macro.stderr @@ -0,0 +1,22 @@ +error[E0642]: patterns aren't allowed in functions without bodies + --> $DIR/no-patterns-in-args-macro.rs:20:8 + | +LL | m!((bad, pat)); + | ^^^^^^^^^^ pattern not allowed in function without body + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/no-patterns-in-args-macro.rs:20:8 + | +LL | m!((bad, pat)); + | ^^^^^^^^^^ + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/no-patterns-in-args-macro.rs:20:8 + | +LL | m!((bad, pat)); + | ^^^^^^^^^^ pattern not allowed in foreign function + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0130, E0561, E0642. +For more information about an error, try `rustc --explain E0130`. diff --git a/tests/ui/no-patterns-in-args.rs b/tests/ui/no-patterns-in-args.rs new file mode 100644 index 000000000..54836b0a3 --- /dev/null +++ b/tests/ui/no-patterns-in-args.rs @@ -0,0 +1,16 @@ +extern "C" { + fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations + fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations + fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations + fn g1(arg: u8); // OK + fn g2(_: u8); // OK +// fn g3(u8); // Not yet +} + +type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types +type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types +type B1 = fn(arg: u8); // OK +type B2 = fn(_: u8); // OK +type B3 = fn(u8); // OK + +fn main() {} diff --git a/tests/ui/no-patterns-in-args.stderr b/tests/ui/no-patterns-in-args.stderr new file mode 100644 index 000000000..1c2ce8664 --- /dev/null +++ b/tests/ui/no-patterns-in-args.stderr @@ -0,0 +1,34 @@ +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/no-patterns-in-args.rs:2:11 + | +LL | fn f1(mut arg: u8); + | ^^^^^^^ pattern not allowed in foreign function + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/no-patterns-in-args.rs:3:11 + | +LL | fn f2(&arg: u8); + | ^^^^ pattern not allowed in foreign function + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/no-patterns-in-args.rs:4:11 + | +LL | fn f3(arg @ _: u8); + | ^^^^^^^ pattern not allowed in foreign function + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/no-patterns-in-args.rs:10:14 + | +LL | type A1 = fn(mut arg: u8); + | ^^^^^^^ + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/no-patterns-in-args.rs:11:14 + | +LL | type A2 = fn(&arg: u8); + | ^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0130, E0561. +For more information about an error, try `rustc --explain E0130`. diff --git a/tests/ui/no-reuse-move-arc.rs b/tests/ui/no-reuse-move-arc.rs new file mode 100644 index 000000000..9c957a4e0 --- /dev/null +++ b/tests/ui/no-reuse-move-arc.rs @@ -0,0 +1,15 @@ +use std::sync::Arc; +use std::thread; + +fn main() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let arc_v = Arc::new(v); + + thread::spawn(move|| { + assert_eq!((*arc_v)[3], 4); + }); + + assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v` + + println!("{:?}", *arc_v); +} diff --git a/tests/ui/no-reuse-move-arc.stderr b/tests/ui/no-reuse-move-arc.stderr new file mode 100644 index 000000000..bcd481c33 --- /dev/null +++ b/tests/ui/no-reuse-move-arc.stderr @@ -0,0 +1,19 @@ +error[E0382]: borrow of moved value: `arc_v` + --> $DIR/no-reuse-move-arc.rs:12:16 + | +LL | let arc_v = Arc::new(v); + | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait +LL | +LL | thread::spawn(move|| { + | ------ value moved into closure here +LL | assert_eq!((*arc_v)[3], 4); + | ----- variable moved due to use in closure +... +LL | assert_eq!((*arc_v)[2], 3); + | ^^^^^^^^ value borrowed here after move + | + = note: borrow occurs due to deref coercion to `Vec` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/no-send-res-ports.rs b/tests/ui/no-send-res-ports.rs new file mode 100644 index 000000000..1bac5868e --- /dev/null +++ b/tests/ui/no-send-res-ports.rs @@ -0,0 +1,30 @@ +use std::thread; +use std::rc::Rc; + +#[derive(Debug)] +struct Port(Rc); + +fn main() { + #[derive(Debug)] + struct Foo { + _x: Port<()>, + } + + impl Drop for Foo { + fn drop(&mut self) {} + } + + fn foo(x: Port<()>) -> Foo { + Foo { + _x: x + } + } + + let x = foo(Port(Rc::new(()))); + + thread::spawn(move|| { + //~^ ERROR `Rc<()>` cannot be sent between threads safely + let y = x; + println!("{:?}", y); + }); +} diff --git a/tests/ui/no-send-res-ports.stderr b/tests/ui/no-send-res-ports.stderr new file mode 100644 index 000000000..75561f411 --- /dev/null +++ b/tests/ui/no-send-res-ports.stderr @@ -0,0 +1,37 @@ +error[E0277]: `Rc<()>` cannot be sent between threads safely + --> $DIR/no-send-res-ports.rs:25:19 + | +LL | thread::spawn(move|| { + | ------------- ^----- + | | | + | _____|_____________within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]` + | | | + | | required by a bound introduced by this call +LL | | +LL | | let y = x; +LL | | println!("{:?}", y); +LL | | }); + | |_____^ `Rc<()>` cannot be sent between threads safely + | + = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`, the trait `Send` is not implemented for `Rc<()>` +note: required because it appears within the type `Port<()>` + --> $DIR/no-send-res-ports.rs:5:8 + | +LL | struct Port(Rc); + | ^^^^ +note: required because it appears within the type `Foo` + --> $DIR/no-send-res-ports.rs:9:12 + | +LL | struct Foo { + | ^^^ +note: required because it's used within this closure + --> $DIR/no-send-res-ports.rs:25:19 + | +LL | thread::spawn(move|| { + | ^^^^^^ +note: required by a bound in `spawn` + --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no-warn-on-field-replace-issue-34101.rs b/tests/ui/no-warn-on-field-replace-issue-34101.rs new file mode 100644 index 000000000..15df6d25c --- /dev/null +++ b/tests/ui/no-warn-on-field-replace-issue-34101.rs @@ -0,0 +1,46 @@ +// Issue 34101: Circa 2016-06-05, `fn inline` below issued an +// erroneous warning from the elaborate_drops pass about moving out of +// a field in `Foo`, which has a destructor (and thus cannot have +// content moved out of it). The reason that the warning is erroneous +// in this case is that we are doing a *replace*, not a move, of the +// content in question, and it is okay to replace fields within `Foo`. +// +// Another more subtle problem was that the elaborate_drops was +// creating a separate drop flag for that internally replaced content, +// even though the compiler should enforce an invariant that any drop +// flag for such subcontent of `Foo` will always have the same value +// as the drop flag for `Foo` itself. + + + + + + + + +// check-pass + +struct Foo(String); + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn inline() { + // (dummy variable so `f` gets assigned `var1` in MIR for both fn's) + let _s = (); + let mut f = Foo(String::from("foo")); + f.0 = String::from("bar"); +} + +fn outline() { + let _s = String::from("foo"); + let mut f = Foo(_s); + f.0 = String::from("bar"); +} + + +fn main() { + inline(); + outline(); +} diff --git a/tests/ui/no_crate_type.rs b/tests/ui/no_crate_type.rs new file mode 100644 index 000000000..d8e687e04 --- /dev/null +++ b/tests/ui/no_crate_type.rs @@ -0,0 +1,6 @@ +// regression test for issue 11256 +#![crate_type] //~ ERROR malformed `crate_type` attribute + +fn main() { + return +} diff --git a/tests/ui/no_crate_type.stderr b/tests/ui/no_crate_type.stderr new file mode 100644 index 000000000..93da7c3e0 --- /dev/null +++ b/tests/ui/no_crate_type.stderr @@ -0,0 +1,8 @@ +error: malformed `crate_type` attribute input + --> $DIR/no_crate_type.rs:2:1 + | +LL | #![crate_type] + | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + +error: aborting due to previous error + diff --git a/tests/ui/no_send-enum.rs b/tests/ui/no_send-enum.rs new file mode 100644 index 000000000..bd560649b --- /dev/null +++ b/tests/ui/no_send-enum.rs @@ -0,0 +1,18 @@ +#![feature(negative_impls)] + +use std::marker::Send; + +struct NoSend; +impl !Send for NoSend {} + +enum Foo { + A(NoSend) +} + +fn bar(_: T) {} + +fn main() { + let x = Foo::A(NoSend); + bar(x); + //~^ ERROR `NoSend` cannot be sent between threads safely +} diff --git a/tests/ui/no_send-enum.stderr b/tests/ui/no_send-enum.stderr new file mode 100644 index 000000000..b5a14b551 --- /dev/null +++ b/tests/ui/no_send-enum.stderr @@ -0,0 +1,23 @@ +error[E0277]: `NoSend` cannot be sent between threads safely + --> $DIR/no_send-enum.rs:16:9 + | +LL | bar(x); + | --- ^ `NoSend` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Foo`, the trait `Send` is not implemented for `NoSend` +note: required because it appears within the type `Foo` + --> $DIR/no_send-enum.rs:8:6 + | +LL | enum Foo { + | ^^^ +note: required by a bound in `bar` + --> $DIR/no_send-enum.rs:12:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_send-rc.rs b/tests/ui/no_send-rc.rs new file mode 100644 index 000000000..f31db15ef --- /dev/null +++ b/tests/ui/no_send-rc.rs @@ -0,0 +1,9 @@ +use std::rc::Rc; + +fn bar(_: T) {} + +fn main() { + let x = Rc::new(5); + bar(x); + //~^ ERROR `Rc<{integer}>` cannot be sent between threads safely +} diff --git a/tests/ui/no_send-rc.stderr b/tests/ui/no_send-rc.stderr new file mode 100644 index 000000000..ce25da559 --- /dev/null +++ b/tests/ui/no_send-rc.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Rc<{integer}>` cannot be sent between threads safely + --> $DIR/no_send-rc.rs:7:9 + | +LL | bar(x); + | --- ^ `Rc<{integer}>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `Rc<{integer}>` +note: required by a bound in `bar` + --> $DIR/no_send-rc.rs:3:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_share-enum.rs b/tests/ui/no_share-enum.rs new file mode 100644 index 000000000..44bf1913e --- /dev/null +++ b/tests/ui/no_share-enum.rs @@ -0,0 +1,16 @@ +#![feature(negative_impls)] + +use std::marker::Sync; + +struct NoSync; +impl !Sync for NoSync {} + +enum Foo { A(NoSync) } + +fn bar(_: T) {} + +fn main() { + let x = Foo::A(NoSync); + bar(x); + //~^ ERROR `NoSync` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/no_share-enum.stderr b/tests/ui/no_share-enum.stderr new file mode 100644 index 000000000..5b453e0da --- /dev/null +++ b/tests/ui/no_share-enum.stderr @@ -0,0 +1,23 @@ +error[E0277]: `NoSync` cannot be shared between threads safely + --> $DIR/no_share-enum.rs:14:9 + | +LL | bar(x); + | --- ^ `NoSync` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Foo`, the trait `Sync` is not implemented for `NoSync` +note: required because it appears within the type `Foo` + --> $DIR/no_share-enum.rs:8:6 + | +LL | enum Foo { A(NoSync) } + | ^^^ +note: required by a bound in `bar` + --> $DIR/no_share-enum.rs:10:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/no_share-struct.rs b/tests/ui/no_share-struct.rs new file mode 100644 index 000000000..7d8a36a76 --- /dev/null +++ b/tests/ui/no_share-struct.rs @@ -0,0 +1,14 @@ +#![feature(negative_impls)] + +use std::marker::Sync; + +struct Foo { a: isize } +impl !Sync for Foo {} + +fn bar(_: T) {} + +fn main() { + let x = Foo { a: 5 }; + bar(x); + //~^ ERROR `Foo` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/no_share-struct.stderr b/tests/ui/no_share-struct.stderr new file mode 100644 index 000000000..9ce3a318f --- /dev/null +++ b/tests/ui/no_share-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Foo` cannot be shared between threads safely + --> $DIR/no_share-struct.rs:12:9 + | +LL | bar(x); + | --- ^ `Foo` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `Foo` +note: required by a bound in `bar` + --> $DIR/no_share-struct.rs:8:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/noexporttypeexe.rs b/tests/ui/noexporttypeexe.rs new file mode 100644 index 000000000..964ac9a30 --- /dev/null +++ b/tests/ui/noexporttypeexe.rs @@ -0,0 +1,15 @@ +// aux-build:noexporttypelib.rs + +extern crate noexporttypelib; + +fn main() { + // Here, the type returned by foo() is not exported. + // This used to cause internal errors when serializing + // because the def_id associated with the type was + // not convertible to a path. + let x: isize = noexporttypelib::foo(); + //~^ ERROR mismatched types + //~| expected type `isize` + //~| found enum `Option` + //~| expected `isize`, found enum `Option` +} diff --git a/tests/ui/noexporttypeexe.stderr b/tests/ui/noexporttypeexe.stderr new file mode 100644 index 000000000..7fc239613 --- /dev/null +++ b/tests/ui/noexporttypeexe.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/noexporttypeexe.rs:10:18 + | +LL | let x: isize = noexporttypelib::foo(); + | ----- ^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found enum `Option` + | | + | expected due to this + | + = note: expected type `isize` + found enum `Option` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/non-constant-expr-for-arr-len.rs b/tests/ui/non-constant-expr-for-arr-len.rs new file mode 100644 index 000000000..1b101d323 --- /dev/null +++ b/tests/ui/non-constant-expr-for-arr-len.rs @@ -0,0 +1,8 @@ +// Check that non constant exprs fail for array repeat syntax + +fn main() { + fn bar(n: usize) { + let _x = [0; n]; + //~^ ERROR attempt to use a non-constant value in a constant [E0435] + } +} diff --git a/tests/ui/non-constant-expr-for-arr-len.stderr b/tests/ui/non-constant-expr-for-arr-len.stderr new file mode 100644 index 000000000..d684b8eaa --- /dev/null +++ b/tests/ui/non-constant-expr-for-arr-len.stderr @@ -0,0 +1,11 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/non-constant-expr-for-arr-len.rs:5:22 + | +LL | fn bar(n: usize) { + | - this would need to be a `const` +LL | let _x = [0; n]; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/non-copyable-void.rs b/tests/ui/non-copyable-void.rs new file mode 100644 index 000000000..ddaaee436 --- /dev/null +++ b/tests/ui/non-copyable-void.rs @@ -0,0 +1,14 @@ +// ignore-wasm32-bare no libc to test ffi with + +#![feature(rustc_private)] + +extern crate libc; + +fn main() { + let x : *const Vec = &vec![1,2,3]; + let y : *const libc::c_void = x as *const libc::c_void; + unsafe { + let _z = (*y).clone(); + //~^ ERROR no method named `clone` found + } +} diff --git a/tests/ui/non-copyable-void.stderr b/tests/ui/non-copyable-void.stderr new file mode 100644 index 000000000..99af04e7c --- /dev/null +++ b/tests/ui/non-copyable-void.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `clone` found for enum `c_void` in the current scope + --> $DIR/non-copyable-void.rs:11:23 + | +LL | let _z = (*y).clone(); + | ^^^^^ method not found in `c_void` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/non-fmt-panic.fixed b/tests/ui/non-fmt-panic.fixed new file mode 100644 index 000000000..5191f1877 --- /dev/null +++ b/tests/ui/non-fmt-panic.fixed @@ -0,0 +1,89 @@ +// run-rustfix +// rustfix-only-machine-applicable +// build-pass (FIXME(62277): should be check-pass) +// aux-build:fancy-panic.rs + +extern crate fancy_panic; + +const C: &str = "abc {}"; +static S: &str = "{bla}"; + +#[allow(unreachable_code)] +fn main() { + panic!("{}", "here's a brace: {"); //~ WARN panic message contains a brace + unreachable!("{}", "here's a brace: {"); //~ WARN panic message contains a brace + std::panic!("{}", "another one: }"); //~ WARN panic message contains a brace + core::panic!("{}", "Hello {}"); //~ WARN panic message contains an unused formatting placeholder + assert!(false, "{}", "{:03x} {test} bla"); + //~^ WARN panic message contains unused formatting placeholders + assert!(false, "{}", S); + //~^ WARN panic message is not a string literal + assert!(false, "{}", 123); + //~^ WARN panic message is not a string literal + assert!(false, "{:?}", Some(123)); + //~^ WARN panic message is not a string literal + debug_assert!(false, "{}", "{{}} bla"); //~ WARN panic message contains braces + panic!("{}", C); //~ WARN panic message is not a string literal + panic!("{}", S); //~ WARN panic message is not a string literal + unreachable!("{}", S); //~ WARN panic message is not a string literal + unreachable!("{}", S); //~ WARN panic message is not a string literal + std::panic::panic_any(123); //~ WARN panic message is not a string literal + core::panic!("{}", &*"abc"); //~ WARN panic message is not a string literal + std::panic::panic_any(Some(123)); //~ WARN panic message is not a string literal + panic!("{}", concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder + panic!("{}", concat!("{", "{")); //~ WARN panic message contains braces + + fancy_panic::fancy_panic!("test {} 123"); + //~^ WARN panic message contains an unused formatting placeholder + + fancy_panic::fancy_panic!(); // OK + fancy_panic::fancy_panic!(S); // OK + + macro_rules! a { + () => { 123 }; + } + + std::panic::panic_any(a!()); //~ WARN panic message is not a string literal + unreachable!("{}", a!()); //~ WARN panic message is not a string literal + + panic!("{}", 1); //~ WARN panic message is not a string literal + unreachable!("{}", 1); //~ WARN panic message is not a string literal + assert!(false, "{}", 1); //~ WARN panic message is not a string literal + debug_assert!(false, "{}", 1); //~ WARN panic message is not a string literal + + std::panic::panic_any(123); //~ WARN panic message is not a string literal + std::panic::panic_any(123); //~ WARN panic message is not a string literal + + // Check that the lint only triggers for std::panic and core::panic, + // not any panic macro: + macro_rules! panic { + ($e:expr) => (); + } + panic!("{}"); // OK + panic!(S); // OK + + a(1); + b(1); + c(1); + d(1); +} + +fn a(v: T) { + std::panic::panic_any(v); //~ WARN panic message is not a string literal + assert!(false, v); //~ WARN panic message is not a string literal +} + +fn b(v: T) { + std::panic::panic_any(v); //~ WARN panic message is not a string literal + assert!(false, "{:?}", v); //~ WARN panic message is not a string literal +} + +fn c(v: T) { + std::panic::panic_any(v); //~ WARN panic message is not a string literal + assert!(false, "{}", v); //~ WARN panic message is not a string literal +} + +fn d(v: T) { + std::panic::panic_any(v); //~ WARN panic message is not a string literal + assert!(false, "{}", v); //~ WARN panic message is not a string literal +} diff --git a/tests/ui/non-fmt-panic.rs b/tests/ui/non-fmt-panic.rs new file mode 100644 index 000000000..d0d06b797 --- /dev/null +++ b/tests/ui/non-fmt-panic.rs @@ -0,0 +1,89 @@ +// run-rustfix +// rustfix-only-machine-applicable +// build-pass (FIXME(62277): should be check-pass) +// aux-build:fancy-panic.rs + +extern crate fancy_panic; + +const C: &str = "abc {}"; +static S: &str = "{bla}"; + +#[allow(unreachable_code)] +fn main() { + panic!("here's a brace: {"); //~ WARN panic message contains a brace + unreachable!("here's a brace: {"); //~ WARN panic message contains a brace + std::panic!("another one: }"); //~ WARN panic message contains a brace + core::panic!("Hello {}"); //~ WARN panic message contains an unused formatting placeholder + assert!(false, "{:03x} {test} bla"); + //~^ WARN panic message contains unused formatting placeholders + assert!(false, S); + //~^ WARN panic message is not a string literal + assert!(false, 123); + //~^ WARN panic message is not a string literal + assert!(false, Some(123)); + //~^ WARN panic message is not a string literal + debug_assert!(false, "{{}} bla"); //~ WARN panic message contains braces + panic!(C); //~ WARN panic message is not a string literal + panic!(S); //~ WARN panic message is not a string literal + unreachable!(S); //~ WARN panic message is not a string literal + unreachable!(S); //~ WARN panic message is not a string literal + std::panic!(123); //~ WARN panic message is not a string literal + core::panic!(&*"abc"); //~ WARN panic message is not a string literal + panic!(Some(123)); //~ WARN panic message is not a string literal + panic!(concat!("{", "}")); //~ WARN panic message contains an unused formatting placeholder + panic!(concat!("{", "{")); //~ WARN panic message contains braces + + fancy_panic::fancy_panic!("test {} 123"); + //~^ WARN panic message contains an unused formatting placeholder + + fancy_panic::fancy_panic!(); // OK + fancy_panic::fancy_panic!(S); // OK + + macro_rules! a { + () => { 123 }; + } + + panic!(a!()); //~ WARN panic message is not a string literal + unreachable!(a!()); //~ WARN panic message is not a string literal + + panic!(format!("{}", 1)); //~ WARN panic message is not a string literal + unreachable!(format!("{}", 1)); //~ WARN panic message is not a string literal + assert!(false, format!("{}", 1)); //~ WARN panic message is not a string literal + debug_assert!(false, format!("{}", 1)); //~ WARN panic message is not a string literal + + panic![123]; //~ WARN panic message is not a string literal + panic!{123}; //~ WARN panic message is not a string literal + + // Check that the lint only triggers for std::panic and core::panic, + // not any panic macro: + macro_rules! panic { + ($e:expr) => (); + } + panic!("{}"); // OK + panic!(S); // OK + + a(1); + b(1); + c(1); + d(1); +} + +fn a(v: T) { + panic!(v); //~ WARN panic message is not a string literal + assert!(false, v); //~ WARN panic message is not a string literal +} + +fn b(v: T) { + panic!(v); //~ WARN panic message is not a string literal + assert!(false, v); //~ WARN panic message is not a string literal +} + +fn c(v: T) { + panic!(v); //~ WARN panic message is not a string literal + assert!(false, v); //~ WARN panic message is not a string literal +} + +fn d(v: T) { + panic!(v); //~ WARN panic message is not a string literal + assert!(false, v); //~ WARN panic message is not a string literal +} diff --git a/tests/ui/non-fmt-panic.stderr b/tests/ui/non-fmt-panic.stderr new file mode 100644 index 000000000..162802b7f --- /dev/null +++ b/tests/ui/non-fmt-panic.stderr @@ -0,0 +1,491 @@ +warning: panic message contains a brace + --> $DIR/non-fmt-panic.rs:13:29 + | +LL | panic!("here's a brace: {"); + | ^ + | + = note: this message is not used as a format string, but will be in Rust 2021 + = note: `#[warn(non_fmt_panics)]` on by default +help: add a "{}" format string to use the message literally + | +LL | panic!("{}", "here's a brace: {"); + | +++++ + +warning: panic message contains a brace + --> $DIR/non-fmt-panic.rs:14:35 + | +LL | unreachable!("here's a brace: {"); + | ^ + | + = note: this message is not used as a format string, but will be in Rust 2021 +help: add a "{}" format string to use the message literally + | +LL | unreachable!("{}", "here's a brace: {"); + | +++++ + +warning: panic message contains a brace + --> $DIR/non-fmt-panic.rs:15:31 + | +LL | std::panic!("another one: }"); + | ^ + | + = note: this message is not used as a format string, but will be in Rust 2021 +help: add a "{}" format string to use the message literally + | +LL | std::panic!("{}", "another one: }"); + | +++++ + +warning: panic message contains an unused formatting placeholder + --> $DIR/non-fmt-panic.rs:16:25 + | +LL | core::panic!("Hello {}"); + | ^^ + | + = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 +help: add the missing argument + | +LL | core::panic!("Hello {}", ...); + | +++++ +help: or add a "{}" format string to use the message literally + | +LL | core::panic!("{}", "Hello {}"); + | +++++ + +warning: panic message contains unused formatting placeholders + --> $DIR/non-fmt-panic.rs:17:21 + | +LL | assert!(false, "{:03x} {test} bla"); + | ^^^^^^ ^^^^^^ + | + = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 +help: add the missing arguments + | +LL | assert!(false, "{:03x} {test} bla", ...); + | +++++ +help: or add a "{}" format string to use the message literally + | +LL | assert!(false, "{}", "{:03x} {test} bla"); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:19:20 + | +LL | assert!(false, S); + | ^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | assert!(false, "{}", S); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:21:20 + | +LL | assert!(false, 123); + | ^^^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | assert!(false, "{}", 123); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:23:20 + | +LL | assert!(false, Some(123)); + | ^^^^^^^^^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{:?}" format string to use the `Debug` implementation of `Option` + | +LL | assert!(false, "{:?}", Some(123)); + | +++++++ + +warning: panic message contains braces + --> $DIR/non-fmt-panic.rs:25:27 + | +LL | debug_assert!(false, "{{}} bla"); + | ^^^^ + | + = note: this message is not used as a format string, but will be in Rust 2021 +help: add a "{}" format string to use the message literally + | +LL | debug_assert!(false, "{}", "{{}} bla"); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:26:12 + | +LL | panic!(C); + | ^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", C); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:27:12 + | +LL | panic!(S); + | ^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", S); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:28:18 + | +LL | unreachable!(S); + | ^ + | + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | unreachable!("{}", S); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:29:18 + | +LL | unreachable!(S); + | ^ + | + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | unreachable!("{}", S); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:30:17 + | +LL | std::panic!(123); + | ^^^ + | + = note: this usage of `std::panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | std::panic!("{}", 123); + | +++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(123); + | ~~~~~~~~~~~~~~~~~~~~~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:31:18 + | +LL | core::panic!(&*"abc"); + | ^^^^^^^ + | + = note: this usage of `core::panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | core::panic!("{}", &*"abc"); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:32:12 + | +LL | panic!(Some(123)); + | ^^^^^^^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{:?}" format string to use the `Debug` implementation of `Option` + | +LL | panic!("{:?}", Some(123)); + | +++++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(Some(123)); + | ~~~~~~~~~~~~~~~~~~~~~ + +warning: panic message contains an unused formatting placeholder + --> $DIR/non-fmt-panic.rs:33:12 + | +LL | panic!(concat!("{", "}")); + | ^^^^^^^^^^^^^^^^^ + | + = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 +help: add the missing argument + | +LL | panic!(concat!("{", "}"), ...); + | +++++ +help: or add a "{}" format string to use the message literally + | +LL | panic!("{}", concat!("{", "}")); + | +++++ + +warning: panic message contains braces + --> $DIR/non-fmt-panic.rs:34:5 + | +LL | panic!(concat!("{", "{")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this message is not used as a format string, but will be in Rust 2021 +help: add a "{}" format string to use the message literally + | +LL | panic!("{}", concat!("{", "{")); + | +++++ + +warning: panic message contains an unused formatting placeholder + --> $DIR/non-fmt-panic.rs:36:37 + | +LL | fancy_panic::fancy_panic!("test {} 123"); + | ^^ + | + = note: this message is not used as a format string when given without arguments, but will be in Rust 2021 + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:46:12 + | +LL | panic!(a!()); + | ^^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", a!()); + | +++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(a!()); + | ~~~~~~~~~~~~~~~~~~~~~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:47:18 + | +LL | unreachable!(a!()); + | ^^^^ + | + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | unreachable!("{}", a!()); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:49:12 + | +LL | panic!(format!("{}", 1)); + | ^^^^^^^^^^^^^^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: the `panic!()` macro supports formatting, so there's no need for the `format!()` macro here +help: remove the `format!(..)` macro call + | +LL - panic!(format!("{}", 1)); +LL + panic!("{}", 1); + | + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:50:18 + | +LL | unreachable!(format!("{}", 1)); + | ^^^^^^^^^^^^^^^^ + | + = note: this usage of `unreachable!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: the `unreachable!()` macro supports formatting, so there's no need for the `format!()` macro here +help: remove the `format!(..)` macro call + | +LL - unreachable!(format!("{}", 1)); +LL + unreachable!("{}", 1); + | + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:51:20 + | +LL | assert!(false, format!("{}", 1)); + | ^^^^^^^^^^^^^^^^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: the `assert!()` macro supports formatting, so there's no need for the `format!()` macro here +help: remove the `format!(..)` macro call + | +LL - assert!(false, format!("{}", 1)); +LL + assert!(false, "{}", 1); + | + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:52:26 + | +LL | debug_assert!(false, format!("{}", 1)); + | ^^^^^^^^^^^^^^^^ + | + = note: this usage of `debug_assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: the `debug_assert!()` macro supports formatting, so there's no need for the `format!()` macro here +help: remove the `format!(..)` macro call + | +LL - debug_assert!(false, format!("{}", 1)); +LL + debug_assert!(false, "{}", 1); + | + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:54:12 + | +LL | panic![123]; + | ^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!["{}", 123]; + | +++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(123); + | ~~~~~~~~~~~~~~~~~~~~~~ ~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:55:12 + | +LL | panic!{123}; + | ^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!{"{}", 123}; + | +++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(123); + | ~~~~~~~~~~~~~~~~~~~~~~ ~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:72:12 + | +LL | panic!(v); + | ------ ^ + | | + | help: use std::panic::panic_any instead: `std::panic::panic_any` + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:73:20 + | +LL | assert!(false, v); + | ^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:77:12 + | +LL | panic!(v); + | ^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{:?}" format string to use the `Debug` implementation of `T` + | +LL | panic!("{:?}", v); + | +++++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(v); + | ~~~~~~~~~~~~~~~~~~~~~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:78:20 + | +LL | assert!(false, v); + | ^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{:?}" format string to use the `Debug` implementation of `T` + | +LL | assert!(false, "{:?}", v); + | +++++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:82:12 + | +LL | panic!(v); + | ^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", v); + | +++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(v); + | ~~~~~~~~~~~~~~~~~~~~~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:83:20 + | +LL | assert!(false, v); + | ^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | assert!(false, "{}", v); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:87:12 + | +LL | panic!(v); + | ^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", v); + | +++++ +help: or use std::panic::panic_any instead + | +LL | std::panic::panic_any(v); + | ~~~~~~~~~~~~~~~~~~~~~ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic.rs:88:20 + | +LL | assert!(false, v); + | ^ + | + = note: this usage of `assert!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | assert!(false, "{}", v); + | +++++ + +warning: 35 warnings emitted + diff --git a/tests/ui/non-ice-error-on-worker-io-fail.rs b/tests/ui/non-ice-error-on-worker-io-fail.rs new file mode 100644 index 000000000..134e7d420 --- /dev/null +++ b/tests/ui/non-ice-error-on-worker-io-fail.rs @@ -0,0 +1,40 @@ +// Issue #66530: We would ICE if someone compiled with `-o /dev/null`, +// because we would try to generate auxiliary files in `/dev/` (which +// at least the OS X file system rejects). +// +// An attempt to `-o` into a directory we cannot write into should indeed +// be an error; but not an ICE. +// +// However, some folks run tests as root, which can write `/dev/` and end +// up clobbering `/dev/null`. Instead we'll use a non-existent path, which +// also used to ICE, but even root can't magically write there. + +// compile-flags: -o /does-not-exist/output + +// The error-pattern check occurs *before* normalization, and the error patterns +// are wildly different between build environments. So this is a cop-out (and we +// rely on the checking of the normalized stderr output as our actual +// "verification" of the diagnostic). + +// error-pattern: error + +// On Mac OS X, we get an error like the below +// normalize-stderr-test "failed to write bytecode to /does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying /does-not-exist/" + +// On Linux, we get an error like the below +// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /does-not-exist/" + +// ignore-windows - this is a unix-specific test +// ignore-emscripten - the file-system issues do not replicate here +// ignore-wasm - the file-system issues do not replicate here +// ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu + +#![crate_type="lib"] + +#![cfg_attr(not(feature = "std"), no_std)] +pub mod task { + pub mod __internal { + use crate::task::Waker; + } + pub use core::task::Waker; +} diff --git a/tests/ui/non-ice-error-on-worker-io-fail.stderr b/tests/ui/non-ice-error-on-worker-io-fail.stderr new file mode 100644 index 000000000..edadecf27 --- /dev/null +++ b/tests/ui/non-ice-error-on-worker-io-fail.stderr @@ -0,0 +1,6 @@ +warning: ignoring --out-dir flag due to -o flag + +error: io error modifying /does-not-exist/ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/non_modrs_mods/foors_mod.rs b/tests/ui/non_modrs_mods/foors_mod.rs new file mode 100644 index 000000000..5bf35fbf7 --- /dev/null +++ b/tests/ui/non_modrs_mods/foors_mod.rs @@ -0,0 +1,10 @@ +// run-pass +// +// ignore-test: not a test, used by non_modrs_mods.rs + +pub mod inner_modrs_mod; +pub mod inner_foors_mod; +pub mod inline { + #[path="somename.rs"] + pub mod innie; +} diff --git a/tests/ui/non_modrs_mods/foors_mod/compiletest-ignore-dir b/tests/ui/non_modrs_mods/foors_mod/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/non_modrs_mods/foors_mod/inline/somename.rs b/tests/ui/non_modrs_mods/foors_mod/inline/somename.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/foors_mod/inline/somename.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs b/tests/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs new file mode 100644 index 000000000..4d8eb350b --- /dev/null +++ b/tests/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs @@ -0,0 +1,3 @@ +// run-pass + +pub mod innest; diff --git a/tests/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs b/tests/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs b/tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs b/tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs new file mode 100644 index 000000000..4d8eb350b --- /dev/null +++ b/tests/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs @@ -0,0 +1,3 @@ +// run-pass + +pub mod innest; diff --git a/tests/ui/non_modrs_mods/modrs_mod/compiletest-ignore-dir b/tests/ui/non_modrs_mods/modrs_mod/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/non_modrs_mods/modrs_mod/inline/somename.rs b/tests/ui/non_modrs_mods/modrs_mod/inline/somename.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/modrs_mod/inline/somename.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs b/tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs new file mode 100644 index 000000000..4d8eb350b --- /dev/null +++ b/tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs @@ -0,0 +1,3 @@ +// run-pass + +pub mod innest; diff --git a/tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs b/tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs b/tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs b/tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs new file mode 100644 index 000000000..4d8eb350b --- /dev/null +++ b/tests/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs @@ -0,0 +1,3 @@ +// run-pass + +pub mod innest; diff --git a/tests/ui/non_modrs_mods/modrs_mod/mod.rs b/tests/ui/non_modrs_mods/modrs_mod/mod.rs new file mode 100644 index 000000000..c8efa66d6 --- /dev/null +++ b/tests/ui/non_modrs_mods/modrs_mod/mod.rs @@ -0,0 +1,8 @@ +// run-pass + +pub mod inner_modrs_mod; +pub mod inner_foors_mod; +pub mod inline { + #[path="somename.rs"] + pub mod innie; +} diff --git a/tests/ui/non_modrs_mods/non_modrs_mods.rs b/tests/ui/non_modrs_mods/non_modrs_mods.rs new file mode 100644 index 000000000..f664b0166 --- /dev/null +++ b/tests/ui/non_modrs_mods/non_modrs_mods.rs @@ -0,0 +1,16 @@ +// run-pass +// +// ignore-pretty issue #37195 +pub mod modrs_mod; +pub mod foors_mod; +#[path = "some_crazy_attr_mod_dir/arbitrary_name.rs"] +pub mod attr_mod; +pub fn main() { + modrs_mod::inner_modrs_mod::innest::foo(); + modrs_mod::inner_foors_mod::innest::foo(); + modrs_mod::inline::innie::foo(); + foors_mod::inner_modrs_mod::innest::foo(); + foors_mod::inner_foors_mod::innest::foo(); + foors_mod::inline::innie::foo(); + attr_mod::inner_modrs_mod::innest::foo(); +} diff --git a/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs new file mode 100644 index 000000000..7d5d5b9e5 --- /dev/null +++ b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs @@ -0,0 +1,3 @@ +// run-pass + +pub mod inner_modrs_mod; diff --git a/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/compiletest-ignore-dir b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/compiletest-ignore-dir new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs new file mode 100644 index 000000000..04585f918 --- /dev/null +++ b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs @@ -0,0 +1,3 @@ +// run-pass + +pub fn foo() {} diff --git a/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs new file mode 100644 index 000000000..4d8eb350b --- /dev/null +++ b/tests/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs @@ -0,0 +1,3 @@ +// run-pass + +pub mod innest; diff --git a/tests/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs b/tests/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs new file mode 100644 index 000000000..af6585aad --- /dev/null +++ b/tests/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs @@ -0,0 +1,5 @@ +// build-pass (FIXME(62277): could be check-pass?) + +mod x; + +fn main() {} diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x.rs b/tests/ui/non_modrs_mods_and_inline_mods/x.rs new file mode 100644 index 000000000..a39a7c6d9 --- /dev/null +++ b/tests/ui/non_modrs_mods_and_inline_mods/x.rs @@ -0,0 +1,5 @@ +// ignore-test: not a test + +pub mod y { + pub mod z; +} diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs new file mode 100644 index 000000000..e8442a47f --- /dev/null +++ b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs @@ -0,0 +1 @@ +// ignore-test: not a test diff --git a/tests/ui/noncopyable-class.rs b/tests/ui/noncopyable-class.rs new file mode 100644 index 000000000..11b6eb736 --- /dev/null +++ b/tests/ui/noncopyable-class.rs @@ -0,0 +1,36 @@ +// Test that a class with a non-copyable field can't be +// copied + +#[derive(Debug)] +struct Bar { + x: isize, +} + +impl Drop for Bar { + fn drop(&mut self) {} +} + +fn bar(x:isize) -> Bar { + Bar { + x: x + } +} + +#[derive(Debug)] +struct Foo { + i: isize, + j: Bar, +} + +fn foo(i:isize) -> Foo { + Foo { + i: i, + j: bar(5) + } +} + +fn main() { + let x = foo(10); + let _y = x.clone(); //~ ERROR no method named `clone` found + println!("{:?}", x); +} diff --git a/tests/ui/noncopyable-class.stderr b/tests/ui/noncopyable-class.stderr new file mode 100644 index 000000000..0c696163a --- /dev/null +++ b/tests/ui/noncopyable-class.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `clone` found for struct `Foo` in the current scope + --> $DIR/noncopyable-class.rs:34:16 + | +LL | struct Foo { + | ---------- method `clone` not found for this struct +... +LL | let _y = x.clone(); + | ^^^^^ method not found in `Foo` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/nonscalar-cast.fixed b/tests/ui/nonscalar-cast.fixed new file mode 100644 index 000000000..0a4b98469 --- /dev/null +++ b/tests/ui/nonscalar-cast.fixed @@ -0,0 +1,16 @@ +// run-rustfix + +#[derive(Debug)] +struct Foo { + x: isize +} + +impl From for isize { + fn from(val: Foo) -> isize { + val.x + } +} + +fn main() { + println!("{}", isize::from(Foo { x: 1 })); //~ non-primitive cast: `Foo` as `isize` [E0605] +} diff --git a/tests/ui/nonscalar-cast.rs b/tests/ui/nonscalar-cast.rs new file mode 100644 index 000000000..59fcf0966 --- /dev/null +++ b/tests/ui/nonscalar-cast.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#[derive(Debug)] +struct Foo { + x: isize +} + +impl From for isize { + fn from(val: Foo) -> isize { + val.x + } +} + +fn main() { + println!("{}", Foo { x: 1 } as isize); //~ non-primitive cast: `Foo` as `isize` [E0605] +} diff --git a/tests/ui/nonscalar-cast.stderr b/tests/ui/nonscalar-cast.stderr new file mode 100644 index 000000000..2a7037121 --- /dev/null +++ b/tests/ui/nonscalar-cast.stderr @@ -0,0 +1,11 @@ +error[E0605]: non-primitive cast: `Foo` as `isize` + --> $DIR/nonscalar-cast.rs:15:20 + | +LL | println!("{}", Foo { x: 1 } as isize); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(Foo { x: 1 })` + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/not-clone-closure.rs b/tests/ui/not-clone-closure.rs new file mode 100644 index 000000000..25635bc83 --- /dev/null +++ b/tests/ui/not-clone-closure.rs @@ -0,0 +1,12 @@ +// Check that closures do not implement `Clone` if their environment is not `Clone`. + +struct S(i32); + +fn main() { + let a = S(5); + let hello = move || { + println!("Hello {}", a.0); + }; + + let hello = hello.clone(); //~ ERROR the trait bound `S: Clone` is not satisfied +} diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr new file mode 100644 index 000000000..37d94cf0e --- /dev/null +++ b/tests/ui/not-clone-closure.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` + --> $DIR/not-clone-closure.rs:11:23 + | +LL | let hello = move || { + | ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]` +... +LL | let hello = hello.clone(); + | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S` + | +note: required because it's used within this closure + --> $DIR/not-clone-closure.rs:7:17 + | +LL | let hello = move || { + | ^^^^^^^ +help: consider annotating `S` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-copy-closure.rs b/tests/ui/not-copy-closure.rs new file mode 100644 index 000000000..f6530f9a4 --- /dev/null +++ b/tests/ui/not-copy-closure.rs @@ -0,0 +1,11 @@ +// Check that closures do not implement `Copy` if their environment is not `Copy`. + +fn main() { + let mut a = 5; + let hello = || { + a += 1; + }; + + let b = hello; + let c = hello; //~ ERROR use of moved value: `hello` [E0382] +} diff --git a/tests/ui/not-copy-closure.stderr b/tests/ui/not-copy-closure.stderr new file mode 100644 index 000000000..93e011cce --- /dev/null +++ b/tests/ui/not-copy-closure.stderr @@ -0,0 +1,21 @@ +error[E0382]: use of moved value: `hello` + --> $DIR/not-copy-closure.rs:10:13 + | +LL | let b = hello; + | ----- value moved here +LL | let c = hello; + | ^^^^^ value used here after move + | +note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment + --> $DIR/not-copy-closure.rs:6:9 + | +LL | a += 1; + | ^ +help: consider mutably borrowing `hello` + | +LL | let b = &mut hello; + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/not-enough-arguments.rs b/tests/ui/not-enough-arguments.rs new file mode 100644 index 000000000..4a2ea5e44 --- /dev/null +++ b/tests/ui/not-enough-arguments.rs @@ -0,0 +1,31 @@ +// Check that the only error msg we report is the +// mismatch between the # of params, and not other +// unrelated errors. + +fn foo(a: isize, b: isize, c: isize, d:isize) { + panic!(); +} + +// Check that all arguments are shown in the error message, even if they're across multiple lines. +fn bar( + a: i32, + b: i32, + c: i32, + d: i32, + e: i32, + f: i32, +) { + println!("{}", a); + println!("{}", b); + println!("{}", c); + println!("{}", d); + println!("{}", e); + println!("{}", f); +} + +fn main() { + foo(1, 2, 3); + //~^ ERROR function takes 4 arguments but 3 + bar(1, 2, 3); + //~^ ERROR function takes 6 arguments but 3 +} diff --git a/tests/ui/not-enough-arguments.stderr b/tests/ui/not-enough-arguments.stderr new file mode 100644 index 000000000..8b2dafb4e --- /dev/null +++ b/tests/ui/not-enough-arguments.stderr @@ -0,0 +1,47 @@ +error[E0061]: this function takes 4 arguments but 3 arguments were supplied + --> $DIR/not-enough-arguments.rs:27:3 + | +LL | foo(1, 2, 3); + | ^^^--------- an argument of type `isize` is missing + | +note: function defined here + --> $DIR/not-enough-arguments.rs:5:4 + | +LL | fn foo(a: isize, b: isize, c: isize, d:isize) { + | ^^^ -------- -------- -------- ------- +help: provide the argument + | +LL | foo(1, 2, 3, /* isize */); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 6 arguments but 3 arguments were supplied + --> $DIR/not-enough-arguments.rs:29:3 + | +LL | bar(1, 2, 3); + | ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing + | +note: function defined here + --> $DIR/not-enough-arguments.rs:10:4 + | +LL | fn bar( + | ^^^ +LL | a: i32, + | ------ +LL | b: i32, + | ------ +LL | c: i32, + | ------ +LL | d: i32, + | ------ +LL | e: i32, + | ------ +LL | f: i32, + | ------ +help: provide the arguments + | +LL | bar(1, 2, 3, /* i32 */, /* i32 */, /* i32 */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/not-panic/not-panic-safe-2.rs b/tests/ui/not-panic/not-panic-safe-2.rs new file mode 100644 index 000000000..f3faa7043 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-2.rs @@ -0,0 +1,13 @@ +#![allow(dead_code)] + +use std::panic::UnwindSafe; +use std::rc::Rc; +use std::cell::RefCell; + +fn assert() {} + +fn main() { + assert::>>(); + //~^ ERROR the type `UnsafeCell` may contain interior mutability and a + //~| ERROR the type `UnsafeCell` may contain interior mutability and a +} diff --git a/tests/ui/not-panic/not-panic-safe-2.stderr b/tests/ui/not-panic/not-panic-safe-2.stderr new file mode 100644 index 000000000..3b0f83b3b --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-2.stderr @@ -0,0 +1,34 @@ +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-2.rs:10:14 + | +LL | assert::>>(); + | ^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `RefCell` + = note: required for `Rc>` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-2.rs:7:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-2.rs:10:14 + | +LL | assert::>>(); + | ^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `Cell` + = note: required because it appears within the type `RefCell` + = note: required for `Rc>` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-2.rs:7:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-panic/not-panic-safe-3.rs b/tests/ui/not-panic/not-panic-safe-3.rs new file mode 100644 index 000000000..21f0c0993 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-3.rs @@ -0,0 +1,13 @@ +#![allow(dead_code)] + +use std::panic::UnwindSafe; +use std::sync::Arc; +use std::cell::RefCell; + +fn assert() {} + +fn main() { + assert::>>(); + //~^ ERROR the type `UnsafeCell` may contain interior mutability and a + //~| ERROR the type `UnsafeCell` may contain interior mutability and a +} diff --git a/tests/ui/not-panic/not-panic-safe-3.stderr b/tests/ui/not-panic/not-panic-safe-3.stderr new file mode 100644 index 000000000..9e9a12764 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-3.stderr @@ -0,0 +1,34 @@ +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-3.rs:10:14 + | +LL | assert::>>(); + | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `RefCell` + = note: required for `Arc>` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-3.rs:7:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-3.rs:10:14 + | +LL | assert::>>(); + | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `Cell` + = note: required because it appears within the type `RefCell` + = note: required for `Arc>` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-3.rs:7:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-panic/not-panic-safe-4.rs b/tests/ui/not-panic/not-panic-safe-4.rs new file mode 100644 index 000000000..ba93af5c0 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-4.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] + +use std::panic::UnwindSafe; +use std::cell::RefCell; + +fn assert() {} + +fn main() { + assert::<&RefCell>(); + //~^ ERROR the type `UnsafeCell` may contain interior mutability and a + //~| ERROR the type `UnsafeCell` may contain interior mutability and a +} diff --git a/tests/ui/not-panic/not-panic-safe-4.stderr b/tests/ui/not-panic/not-panic-safe-4.stderr new file mode 100644 index 000000000..9428c1256 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-4.stderr @@ -0,0 +1,44 @@ +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-4.rs:9:14 + | +LL | assert::<&RefCell>(); + | ^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `RefCell` + = note: required for `&RefCell` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-4.rs:6:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` +help: consider removing the leading `&`-reference + | +LL - assert::<&RefCell>(); +LL + assert::>(); + | + +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-4.rs:9:14 + | +LL | assert::<&RefCell>(); + | ^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `Cell` + = note: required because it appears within the type `RefCell` + = note: required for `&RefCell` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-4.rs:6:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` +help: consider removing the leading `&`-reference + | +LL - assert::<&RefCell>(); +LL + assert::>(); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-panic/not-panic-safe-5.rs b/tests/ui/not-panic/not-panic-safe-5.rs new file mode 100644 index 000000000..e0d37517d --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-5.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] + +use std::panic::UnwindSafe; +use std::cell::UnsafeCell; + +fn assert() {} + +fn main() { + assert::<*const UnsafeCell>(); //~ ERROR E0277 +} diff --git a/tests/ui/not-panic/not-panic-safe-5.stderr b/tests/ui/not-panic/not-panic-safe-5.stderr new file mode 100644 index 000000000..cb78370b4 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-5.stderr @@ -0,0 +1,17 @@ +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-5.rs:9:14 + | +LL | assert::<*const UnsafeCell>(); + | ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required for `*const UnsafeCell` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-5.rs:6:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-panic/not-panic-safe-6.rs b/tests/ui/not-panic/not-panic-safe-6.rs new file mode 100644 index 000000000..4915096dc --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-6.rs @@ -0,0 +1,12 @@ +#![allow(dead_code)] + +use std::panic::UnwindSafe; +use std::cell::RefCell; + +fn assert() {} + +fn main() { + assert::<*mut RefCell>(); + //~^ ERROR the type `UnsafeCell` may contain interior mutability and a + //~| ERROR the type `UnsafeCell` may contain interior mutability and a +} diff --git a/tests/ui/not-panic/not-panic-safe-6.stderr b/tests/ui/not-panic/not-panic-safe-6.stderr new file mode 100644 index 000000000..7986e341e --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe-6.stderr @@ -0,0 +1,34 @@ +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-6.rs:9:14 + | +LL | assert::<*mut RefCell>(); + | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `RefCell` + = note: required for `*mut RefCell` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-6.rs:6:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error[E0277]: the type `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + --> $DIR/not-panic-safe-6.rs:9:14 + | +LL | assert::<*mut RefCell>(); + | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary + | + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = note: required because it appears within the type `Cell` + = note: required because it appears within the type `RefCell` + = note: required for `*mut RefCell` to implement `UnwindSafe` +note: required by a bound in `assert` + --> $DIR/not-panic-safe-6.rs:6:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/not-panic/not-panic-safe.rs b/tests/ui/not-panic/not-panic-safe.rs new file mode 100644 index 000000000..1b3c6482c --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] + +use std::panic::UnwindSafe; + +fn assert() {} + +fn main() { + assert::<&mut &mut &i32>(); + //~^ ERROR the type `&mut &mut &i32` may not be safely transferred across an unwind boundary +} diff --git a/tests/ui/not-panic/not-panic-safe.stderr b/tests/ui/not-panic/not-panic-safe.stderr new file mode 100644 index 000000000..37a6aee39 --- /dev/null +++ b/tests/ui/not-panic/not-panic-safe.stderr @@ -0,0 +1,22 @@ +error[E0277]: the type `&mut &mut &i32` may not be safely transferred across an unwind boundary + --> $DIR/not-panic-safe.rs:8:14 + | +LL | assert::<&mut &mut &i32>(); + | ^^^^^^^^^^^^^^ `&mut &mut &i32` may not be safely transferred across an unwind boundary + | + = help: the trait `UnwindSafe` is not implemented for `&mut &mut &i32` + = note: `UnwindSafe` is implemented for `&&mut &i32`, but not for `&mut &mut &i32` +note: required by a bound in `assert` + --> $DIR/not-panic-safe.rs:5:14 + | +LL | fn assert() {} + | ^^^^^^^^^^ required by this bound in `assert` +help: consider removing 2 leading `&`-references + | +LL - assert::<&mut &mut &i32>(); +LL + assert::<&i32>(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/nul-characters.rs b/tests/ui/nul-characters.rs new file mode 100644 index 000000000..11b6e9fe3 --- /dev/null +++ b/tests/ui/nul-characters.rs @@ -0,0 +1,36 @@ +// run-pass + +pub fn main() +{ + let all_nuls1 = "\0\x00\u{0}\u{0}"; + let all_nuls2 = "\u{0}\u{0}\x00\0"; + let all_nuls3 = "\u{0}\u{0}\x00\0"; + let all_nuls4 = "\x00\u{0}\0\u{0}"; + + // sizes for two should suffice + assert_eq!(all_nuls1.len(), 4); + assert_eq!(all_nuls2.len(), 4); + + // string equality should pass between the strings + assert_eq!(all_nuls1, all_nuls2); + assert_eq!(all_nuls2, all_nuls3); + assert_eq!(all_nuls3, all_nuls4); + + // all extracted characters in all_nuls are equivalent to each other + for c1 in all_nuls1.chars() + { + for c2 in all_nuls1.chars() + { + assert_eq!(c1,c2); + } + } + + // testing equality between explicit character literals + assert_eq!('\0', '\x00'); + assert_eq!('\u{0}', '\x00'); + assert_eq!('\u{0}', '\u{0}'); + + // NUL characters should make a difference + assert!("Hello World" != "Hello \0World"); + assert!("Hello World" != "Hello World\0"); +} diff --git a/tests/ui/nullable-pointer-iotareduction.rs b/tests/ui/nullable-pointer-iotareduction.rs new file mode 100644 index 000000000..d345fec81 --- /dev/null +++ b/tests/ui/nullable-pointer-iotareduction.rs @@ -0,0 +1,71 @@ +// run-pass + +// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, +// which "says that a destructor applied to an object built from a constructor +// behaves as expected". -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction +// +// It's a little more complicated here, because of pointers and regions and +// trying to get assert failure messages that at least identify which case +// failed. + +enum E { Thing(isize, T), #[allow(unused_tuple_struct_fields)] Nothing((), ((), ()), [i8; 0]) } +impl E { + fn is_none(&self) -> bool { + match *self { + E::Thing(..) => false, + E::Nothing(..) => true + } + } + fn get_ref(&self) -> (isize, &T) { + match *self { + E::Nothing(..) => panic!("E::get_ref(Nothing::<{}>)", stringify!(T)), + E::Thing(x, ref y) => (x, y) + } + } +} + +macro_rules! check_option { + ($e:expr, $T:ty) => {{ + check_option!($e, $T, |ptr| assert_eq!(*ptr, $e)); + }}; + ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{ + assert!(None::<$T>.is_none()); + let e = $e; + let s_ = Some::<$T>(e); + let $v = s_.as_ref().unwrap(); + $chk + }} +} + +macro_rules! check_fancy { + ($e:expr, $T:ty) => {{ + check_fancy!($e, $T, |ptr| assert_eq!(*ptr, $e)); + }}; + ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{ + assert!(E::Nothing::<$T>((), ((), ()), [23; 0]).is_none()); + let e = $e; + let t_ = E::Thing::<$T>(23, e); + match t_.get_ref() { + (23, $v) => { $chk } + _ => panic!("Thing::<{}>(23, {}).get_ref() != (23, _)", + stringify!($T), stringify!($e)) + } + }} +} + +macro_rules! check_type { + ($($a:tt)*) => {{ + check_option!($($a)*); + check_fancy!($($a)*); + }} +} + +pub fn main() { + check_type!(&17, &isize); + check_type!(Box::new(18), Box); + check_type!("foo".to_string(), String); + check_type!(vec![20, 22], Vec); + check_type!(main, fn(), |pthing| { + assert_eq!(main as fn(), *pthing as fn()) + }); +} diff --git a/tests/ui/nullable-pointer-size.rs b/tests/ui/nullable-pointer-size.rs new file mode 100644 index 000000000..0384553b6 --- /dev/null +++ b/tests/ui/nullable-pointer-size.rs @@ -0,0 +1,35 @@ +// run-pass + +#![allow(dead_code)] + +use std::mem; + +enum E { Thing(isize, T), Nothing((), ((), ()), [i8; 0]) } +struct S(isize, T); + +// These are macros so we get useful assert messages. + +macro_rules! check_option { + ($T:ty) => { + assert_eq!(mem::size_of::>(), mem::size_of::<$T>()); + } +} + +macro_rules! check_fancy { + ($T:ty) => { + assert_eq!(mem::size_of::>(), mem::size_of::>()); + } +} + +macro_rules! check_type { + ($T:ty) => {{ + check_option!($T); + check_fancy!($T); + }} +} + +pub fn main() { + check_type!(&'static isize); + check_type!(Box); + check_type!(extern "C" fn()); +} diff --git a/tests/ui/numbers-arithmetic/arith-unsigned.rs b/tests/ui/numbers-arithmetic/arith-unsigned.rs new file mode 100644 index 000000000..ad57d9f86 --- /dev/null +++ b/tests/ui/numbers-arithmetic/arith-unsigned.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_comparisons)] + +// Unsigned integer operations +pub fn main() { + assert!((0u8 < 255u8)); + assert!((0u8 <= 255u8)); + assert!((255u8 > 0u8)); + assert!((255u8 >= 0u8)); + assert_eq!(250u8 / 10u8, 25u8); + assert_eq!(255u8 % 10u8, 5u8); + assert!((0u16 < 60000u16)); + assert!((0u16 <= 60000u16)); + assert!((60000u16 > 0u16)); + assert!((60000u16 >= 0u16)); + assert_eq!(60000u16 / 10u16, 6000u16); + assert_eq!(60005u16 % 10u16, 5u16); + assert!((0u32 < 4000000000u32)); + assert!((0u32 <= 4000000000u32)); + assert!((4000000000u32 > 0u32)); + assert!((4000000000u32 >= 0u32)); + assert_eq!(4000000000u32 / 10u32, 400000000u32); + assert_eq!(4000000005u32 % 10u32, 5u32); + // 64-bit numbers have some flakiness yet. Not tested + +} diff --git a/tests/ui/numbers-arithmetic/div-mod.rs b/tests/ui/numbers-arithmetic/div-mod.rs new file mode 100644 index 000000000..acb92a7df --- /dev/null +++ b/tests/ui/numbers-arithmetic/div-mod.rs @@ -0,0 +1,19 @@ +// run-pass + + + + +pub fn main() { + let x: isize = 15; + let y: isize = 5; + assert_eq!(x / 5, 3); + assert_eq!(x / 4, 3); + assert_eq!(x / 3, 5); + assert_eq!(x / y, 3); + assert_eq!(15 / y, 3); + assert_eq!(x % 5, 0); + assert_eq!(x % 4, 3); + assert_eq!(x % 3, 0); + assert_eq!(x % y, 0); + assert_eq!(15 % y, 0); +} diff --git a/tests/ui/numbers-arithmetic/divide-by-zero.rs b/tests/ui/numbers-arithmetic/divide-by-zero.rs new file mode 100644 index 000000000..30e0e6c1b --- /dev/null +++ b/tests/ui/numbers-arithmetic/divide-by-zero.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:attempt to divide by zero +// ignore-emscripten no processes + +#[allow(unconditional_panic)] +fn main() { + let y = 0; + let _z = 1 / y; +} diff --git a/tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs b/tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs new file mode 100644 index 000000000..260281d75 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs @@ -0,0 +1,48 @@ +// run-pass + +// Forces evaluation of constants, triggering hard error +fn force(_: T) {} + +fn main() { + { const X: u16 = -1. as u16; force(X); } + { const X: u128 = -100. as u128; force(X); } + + { const X: i8 = f32::NAN as i8; force(X); } + { const X: i32 = f32::NAN as i32; force(X); } + { const X: u64 = f32::NAN as u64; force(X); } + { const X: u128 = f32::NAN as u128; force(X); } + + { const X: i8 = f32::INFINITY as i8; force(X); } + { const X: u32 = f32::INFINITY as u32; force(X); } + { const X: i128 = f32::INFINITY as i128; force(X); } + { const X: u128 = f32::INFINITY as u128; force(X); } + + { const X: u8 = f32::NEG_INFINITY as u8; force(X); } + { const X: u16 = f32::NEG_INFINITY as u16; force(X); } + { const X: i64 = f32::NEG_INFINITY as i64; force(X); } + { const X: i128 = f32::NEG_INFINITY as i128; force(X); } + + { const X: i8 = f64::NAN as i8; force(X); } + { const X: i32 = f64::NAN as i32; force(X); } + { const X: u64 = f64::NAN as u64; force(X); } + { const X: u128 = f64::NAN as u128; force(X); } + + { const X: i8 = f64::INFINITY as i8; force(X); } + { const X: u32 = f64::INFINITY as u32; force(X); } + { const X: i128 = f64::INFINITY as i128; force(X); } + { const X: u128 = f64::INFINITY as u128; force(X); } + + { const X: u8 = f64::NEG_INFINITY as u8; force(X); } + { const X: u16 = f64::NEG_INFINITY as u16; force(X); } + { const X: i64 = f64::NEG_INFINITY as i64; force(X); } + { const X: i128 = f64::NEG_INFINITY as i128; force(X); } + + { const X: u8 = 256. as u8; force(X); } + { const X: i8 = -129. as i8; force(X); } + { const X: i8 = 128. as i8; force(X); } + { const X: i32 = 2147483648. as i32; force(X); } + { const X: i32 = -2147483904. as i32; force(X); } + { const X: u32 = 4294967296. as u32; force(X); } + { const X: u128 = 1e40 as u128; force(X); } + { const X: i128 = 1e40 as i128; force(X); } +} diff --git a/tests/ui/numbers-arithmetic/float-literal-inference.rs b/tests/ui/numbers-arithmetic/float-literal-inference.rs new file mode 100644 index 000000000..c4645e4f8 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float-literal-inference.rs @@ -0,0 +1,13 @@ +// run-pass +struct S { + z: f64 +} + +pub fn main() { + let x: f32 = 4.0; + println!("{}", x); + let y: f64 = 64.0; + println!("{}", y); + let z = S { z: 1.0 }; + println!("{}", z.z); +} diff --git a/tests/ui/numbers-arithmetic/float-nan.rs b/tests/ui/numbers-arithmetic/float-nan.rs new file mode 100644 index 000000000..0cc6473e5 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float-nan.rs @@ -0,0 +1,82 @@ +// run-pass + +pub fn main() { + let nan: f64 = f64::NAN; + assert!((nan).is_nan()); + + let inf: f64 = f64::INFINITY; + let neg_inf: f64 = -f64::INFINITY; + assert_eq!(-inf, neg_inf); + + assert!( nan != nan); + assert!( nan != -nan); + assert!(-nan != -nan); + assert!(-nan != nan); + + assert!( nan != 1.); + assert!( nan != 0.); + assert!( nan != inf); + assert!( nan != -inf); + + assert!( 1. != nan); + assert!( 0. != nan); + assert!( inf != nan); + assert!(-inf != nan); + + assert!(!( nan == nan)); + assert!(!( nan == -nan)); + assert!(!( nan == 1.)); + assert!(!( nan == 0.)); + assert!(!( nan == inf)); + assert!(!( nan == -inf)); + assert!(!( 1. == nan)); + assert!(!( 0. == nan)); + assert!(!( inf == nan)); + assert!(!(-inf == nan)); + assert!(!(-nan == nan)); + assert!(!(-nan == -nan)); + + assert!(!( nan > nan)); + assert!(!( nan > -nan)); + assert!(!( nan > 0.)); + assert!(!( nan > inf)); + assert!(!( nan > -inf)); + assert!(!( 0. > nan)); + assert!(!( inf > nan)); + assert!(!(-inf > nan)); + assert!(!(-nan > nan)); + + assert!(!(nan < 0.)); + assert!(!(nan < 1.)); + assert!(!(nan < -1.)); + assert!(!(nan < inf)); + assert!(!(nan < -inf)); + assert!(!(nan < nan)); + assert!(!(nan < -nan)); + + assert!(!( 0. < nan)); + assert!(!( 1. < nan)); + assert!(!( -1. < nan)); + assert!(!( inf < nan)); + assert!(!(-inf < nan)); + assert!(!(-nan < nan)); + + assert!((nan + inf).is_nan()); + assert!((nan + -inf).is_nan()); + assert!((nan + 0.).is_nan()); + assert!((nan + 1.).is_nan()); + assert!((nan * 1.).is_nan()); + assert!((nan / 1.).is_nan()); + assert!((nan / 0.).is_nan()); + assert!((0.0/0.0f64).is_nan()); + assert!((-inf + inf).is_nan()); + assert!((inf - inf).is_nan()); + + assert!(!(-1.0f64).is_nan()); + assert!(!(0.0f64).is_nan()); + assert!(!(0.1f64).is_nan()); + assert!(!(1.0f64).is_nan()); + assert!(!(inf).is_nan()); + assert!(!(-inf).is_nan()); + assert!(!(1./-inf).is_nan()); +} diff --git a/tests/ui/numbers-arithmetic/float-signature.rs b/tests/ui/numbers-arithmetic/float-signature.rs new file mode 100644 index 000000000..d47280ea2 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float-signature.rs @@ -0,0 +1,9 @@ +// run-pass + + +pub fn main() { + fn foo(n: f64) -> f64 { return n + 0.12345; } + let n: f64 = 0.1; + let m: f64 = foo(n); + println!("{}", m); +} diff --git a/tests/ui/numbers-arithmetic/float.rs b/tests/ui/numbers-arithmetic/float.rs new file mode 100644 index 000000000..d55c05857 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float.rs @@ -0,0 +1,9 @@ +// run-pass +pub fn main() { + let pi = 3.1415927f64; + println!("{}", -pi * (pi + 2.0 / pi) - pi * 5.0); + if pi == 5.0 || pi < 10.0 || pi <= 2.0 || pi != 22.0 / 7.0 || pi >= 10.0 + || pi > 1.0 { + println!("yes"); + } +} diff --git a/tests/ui/numbers-arithmetic/float2.rs b/tests/ui/numbers-arithmetic/float2.rs new file mode 100644 index 000000000..b1bcf8da5 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float2.rs @@ -0,0 +1,26 @@ +// run-pass + + + +pub fn main() { + let a = 1.5e6f64; + let b = 1.5E6f64; + let c = 1e6f64; + let d = 1E6f64; + let e = 3.0f32; + let f = 5.9f64; + let g = 1e6f32; + let h = 1.0e7f64; + let i = 1.0E7f64; + let j = 3.1e+9f64; + let k = 3.2e-10f64; + assert_eq!(a, b); + assert!((c < b)); + assert_eq!(c, d); + assert!((e < g)); + assert!((f < h)); + assert_eq!(g, 1000000.0f32); + assert_eq!(h, i); + assert!((j > k)); + assert!((k < a)); +} diff --git a/tests/ui/numbers-arithmetic/float_math.rs b/tests/ui/numbers-arithmetic/float_math.rs new file mode 100644 index 000000000..a2902ee56 --- /dev/null +++ b/tests/ui/numbers-arithmetic/float_math.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::{fadd_fast, fsub_fast, fmul_fast, fdiv_fast, frem_fast}; + +#[inline(never)] +pub fn test_operations(a: f64, b: f64) { + // make sure they all map to the correct operation + unsafe { + assert_eq!(fadd_fast(a, b), a + b); + assert_eq!(fsub_fast(a, b), a - b); + assert_eq!(fmul_fast(a, b), a * b); + assert_eq!(fdiv_fast(a, b), a / b); + assert_eq!(frem_fast(a, b), a % b); + } +} + +fn main() { + test_operations(1., 2.); + test_operations(10., 5.); +} diff --git a/tests/ui/numbers-arithmetic/floatlits.rs b/tests/ui/numbers-arithmetic/floatlits.rs new file mode 100644 index 000000000..07049af31 --- /dev/null +++ b/tests/ui/numbers-arithmetic/floatlits.rs @@ -0,0 +1,12 @@ +// run-pass + + + +pub fn main() { + let f = 4.999999999999f64; + assert!((f > 4.90f64)); + assert!((f < 5.0f64)); + let g = 4.90000000001e-10f64; + assert!((g > 5e-11f64)); + assert!((g < 5e-9f64)); +} diff --git a/tests/ui/numbers-arithmetic/i128.rs b/tests/ui/numbers-arithmetic/i128.rs new file mode 100644 index 000000000..d61a1ab03 --- /dev/null +++ b/tests/ui/numbers-arithmetic/i128.rs @@ -0,0 +1,107 @@ +// run-pass +#![allow(overflowing_literals)] + +#![feature(test)] + +extern crate test; +use test::black_box as b; + +fn main() { + let x: i128 = -1; + assert_eq!(0, !x); + let y: i128 = -2; + assert_eq!(!1, y); + let z: i128 = 0xABCD_EF; + assert_eq!(z * z, 0x734C_C2F2_A521); + assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41); + assert_eq!(-z * -z, 0x734C_C2F2_A521); + assert_eq!(-z * -z * -z * -z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41); + assert_eq!(-z + -z + -z + -z, -0x2AF3_7BC); + let k: i128 = -0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210; + assert_eq!(k + k, -0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420); + assert_eq!(0, k - k); + assert_eq!(-0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k + z); + assert_eq!(-0x1000_0000_0000_0000_0000_0000_0000_000, + k + 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!(-0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42); + assert_eq!(-k, k / -1); + assert_eq!(-0x91A2_B3C4_D5E6_F8, k >> 65); + assert_eq!(-0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65); + assert!(k < z); + assert!(y > k); + assert!(y < x); + assert_eq!(x as i64, -1); + assert_eq!(z as i64, 0xABCD_EF); + assert_eq!(k as i64, -0xFEDC_BA98_7654_3210); + assert_eq!(k as u128, 0xFEDC_BA98_7654_3210_0123_4567_89AB_CDF0); + assert_eq!(-k as u128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!((-z as f64) as i128, -z); + assert_eq!((-z as f32) as i128, -z); + assert_eq!((-z as f64 * 16.0) as i128, -z * 16); + assert_eq!((-z as f32 * 16.0) as i128, -z * 16); + // Same stuff as above, but blackboxed, to force use of intrinsics + let x: i128 = b(-1); + assert_eq!(0, !x); + let y: i128 = b(-2); + assert_eq!(!1, y); + let z: i128 = b(0xABCD_EF); + assert_eq!(z * z, 0x734C_C2F2_A521); + assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41); + assert_eq!(-z * -z, 0x734C_C2F2_A521); + assert_eq!(-z * -z * -z * -z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41); + assert_eq!(-z + -z + -z + -z, -0x2AF3_7BC); + let k: i128 = b(-0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!(k + k, -0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420); + assert_eq!(0, k - k); + assert_eq!(-0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k + z); + assert_eq!(-0x1000_0000_0000_0000_0000_0000_0000_000, + k + 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!(-0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42); + assert_eq!(-k, k / -1); + assert_eq!(-0x91A2_B3C4_D5E6_F8, k >> 65); + assert_eq!(-0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65); + assert!(k < z); + assert!(y > k); + assert!(y < x); + assert_eq!(x as i64, -1); + assert_eq!(z as i64, 0xABCD_EF); + assert_eq!(k as i64, -0xFEDC_BA98_7654_3210); + assert_eq!(k as u128, 0xFEDC_BA98_7654_3210_0123_4567_89AB_CDF0); + assert_eq!(-k as u128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!((-z as f64) as i128, -z); + assert_eq!((-z as f32) as i128, -z); + assert_eq!((-z as f64 * 16.0) as i128, -z * 16); + assert_eq!((-z as f32 * 16.0) as i128, -z * 16); + // formatting + let j: i128 = -(1 << 67); + assert_eq!("-147573952589676412928", format!("{}", j)); + assert_eq!("fffffffffffffff80000000000000000", format!("{:x}", j)); + assert_eq!("3777777777777777777760000000000000000000000", format!("{:o}", j)); + assert_eq!("1111111111111111111111111111111111111111111111111111111111111\ + 0000000000000000000000000000000000000000000000000000000000000000000", + format!("{:b}", j)); + assert_eq!("-147573952589676412928", format!("{:?}", j)); + // common traits + assert_eq!(x, b(x.clone())); + // overflow checks + assert_eq!((-z).checked_mul(-z), Some(0x734C_C2F2_A521)); + assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521)); + assert_eq!((k).checked_mul(k), None); + let l: i128 = b(i128::MIN); + let o: i128 = b(17); + assert_eq!(l.checked_sub(b(2)), None); + assert_eq!(l.checked_add(l), None); + assert_eq!((-(l + 1)).checked_add(2), None); + assert_eq!(l.checked_sub(l), Some(0)); + assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127)); + assert_eq!(o.checked_shl(b(128)), None); + + // https://github.com/rust-lang/rust/issues/41228 + assert_eq!(b(-87559967289969187895646876466835277875_i128) / + b(84285771033834995895337664386045050880_i128), + -1i128); + + // iter-arithmetic traits + assert_eq!(10i128, [1i128, 2, 3, 4].iter().sum()); + assert_eq!(24i128, [1i128, 2, 3, 4].iter().product()); +} diff --git a/tests/ui/numbers-arithmetic/i32-sub.rs b/tests/ui/numbers-arithmetic/i32-sub.rs new file mode 100644 index 000000000..56df772b4 --- /dev/null +++ b/tests/ui/numbers-arithmetic/i32-sub.rs @@ -0,0 +1,6 @@ +// run-pass + + + + +pub fn main() { let mut x: i32 = -400; x = 0 - x; assert_eq!(x, 400); } diff --git a/tests/ui/numbers-arithmetic/i8-incr.rs b/tests/ui/numbers-arithmetic/i8-incr.rs new file mode 100644 index 000000000..718d259f7 --- /dev/null +++ b/tests/ui/numbers-arithmetic/i8-incr.rs @@ -0,0 +1,12 @@ +// run-pass + + + + +pub fn main() { + let mut x: i8 = -12; + let y: i8 = -12; + x = x + 1; + x = x - 1; + assert_eq!(x, y); +} diff --git a/tests/ui/numbers-arithmetic/int-abs-overflow.rs b/tests/ui/numbers-arithmetic/int-abs-overflow.rs new file mode 100644 index 000000000..d63ba8cb0 --- /dev/null +++ b/tests/ui/numbers-arithmetic/int-abs-overflow.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -C overflow-checks=on +// ignore-emscripten no threads support +// needs-unwind + +use std::thread; + +fn main() { + assert!(thread::spawn(|| i8::MIN.abs()).join().is_err()); + assert!(thread::spawn(|| i16::MIN.abs()).join().is_err()); + assert!(thread::spawn(|| i32::MIN.abs()).join().is_err()); + assert!(thread::spawn(|| i64::MIN.abs()).join().is_err()); + assert!(thread::spawn(|| isize::MIN.abs()).join().is_err()); +} diff --git a/tests/ui/numbers-arithmetic/int.rs b/tests/ui/numbers-arithmetic/int.rs new file mode 100644 index 000000000..b496a70a6 --- /dev/null +++ b/tests/ui/numbers-arithmetic/int.rs @@ -0,0 +1,7 @@ +// run-pass + + + +// pretty-expanded FIXME #23616 + +pub fn main() { let _x: isize = 10; } diff --git a/tests/ui/numbers-arithmetic/integer-literal-radix.rs b/tests/ui/numbers-arithmetic/integer-literal-radix.rs new file mode 100644 index 000000000..8f61ea17a --- /dev/null +++ b/tests/ui/numbers-arithmetic/integer-literal-radix.rs @@ -0,0 +1,19 @@ +// run-pass + +pub fn main() { + let a = 0xBEEF_isize; + let b = 0o755_isize; + let c = 0b10101_isize; + let d = -0xBEEF_isize; + let e = -0o755_isize; + let f = -0b10101_isize; + + assert_eq!(a, 48879); + assert_eq!(b, 493); + assert_eq!(c, 21); + assert_eq!(d, -48879); + assert_eq!(e, -493); + assert_eq!(f, -21); + + +} diff --git a/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs new file mode 100644 index 000000000..80248dc22 --- /dev/null +++ b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn foo(_: *const ()) {} + +fn main() { + let a = 3; + foo(&a as *const _ as *const ()); +} diff --git a/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs new file mode 100644 index 000000000..bec718a3c --- /dev/null +++ b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() { + println!("{}", std::mem::size_of_val(&1)); +} diff --git a/tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs new file mode 100644 index 000000000..d177ced1a --- /dev/null +++ b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs @@ -0,0 +1,60 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + fn id_i8(n: i8) -> i8 { n } + fn id_i16(n: i16) -> i16 { n } + fn id_i32(n: i32) -> i32 { n } + fn id_i64(n: i64) -> i64 { n } + + fn id_uint(n: usize) -> usize { n } + fn id_u8(n: u8) -> u8 { n } + fn id_u16(n: u16) -> u16 { n } + fn id_u32(n: u32) -> u32 { n } + fn id_u64(n: u64) -> u64 { n } + + let _i: i8 = -128; + let j = -128; + id_i8(j); + id_i8(-128); + + let _i: i16 = -32_768; + let j = -32_768; + id_i16(j); + id_i16(-32_768); + + let _i: i32 = -2_147_483_648; + let j = -2_147_483_648; + id_i32(j); + id_i32(-2_147_483_648); + + let _i: i64 = -9_223_372_036_854_775_808; + let j = -9_223_372_036_854_775_808; + id_i64(j); + id_i64(-9_223_372_036_854_775_808); + + let _i: usize = 1; + let j = 1; + id_uint(j); + id_uint(1); + + let _i: u8 = 255; + let j = 255; + id_u8(j); + id_u8(255); + + let _i: u16 = 65_535; + let j = 65_535; + id_u16(j); + id_u16(65_535); + + let _i: u32 = 4_294_967_295; + let j = 4_294_967_295; + id_u32(j); + id_u32(4_294_967_295); + + let _i: u64 = 18_446_744_073_709_551_615; + let j = 18_446_744_073_709_551_615; + id_u64(j); + id_u64(18_446_744_073_709_551_615); +} diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr new file mode 100644 index 000000000..c4abcb784 --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr @@ -0,0 +1,148 @@ +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:11:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:15:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:17:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:19:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:21:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:23:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:27:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:29:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:33:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:35:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:37:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:39:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:41:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:43:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:45:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:49:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:51:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:55:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:57:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr new file mode 100644 index 000000000..c4abcb784 --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr @@ -0,0 +1,148 @@ +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:11:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:15:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:17:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:19:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:21:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:23:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:27:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:29:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:33:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:35:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:37:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:39:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:41:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:43:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:45:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:49:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:51:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:55:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:57:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..c4abcb784 --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr @@ -0,0 +1,148 @@ +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:11:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:15:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:17:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:19:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:21:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:23:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide `1_isize` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide `1_i8` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:27:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i16` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:29:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide `1_i64` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:33:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide `1_i128` by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:35:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:37:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:39:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:41:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:43:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:45:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:49:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:51:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:55:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:57:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.rs b/tests/ui/numbers-arithmetic/issue-8460-const.rs new file mode 100644 index 000000000..02e7567da --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-8460-const.rs @@ -0,0 +1,59 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +// build-fail + +use std::thread; + +fn main() { + assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + //~^ ERROR operation will panic + assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + //~^ ERROR operation will panic +} diff --git a/tests/ui/numbers-arithmetic/issue-8460.rs b/tests/ui/numbers-arithmetic/issue-8460.rs new file mode 100644 index 000000000..77368b87e --- /dev/null +++ b/tests/ui/numbers-arithmetic/issue-8460.rs @@ -0,0 +1,52 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// needs-unwind +#![feature(rustc_attrs)] + +use std::thread; + +trait Int { + fn zero() -> Self; + fn one() -> Self; +} +macro_rules! doit { + ($($t:ident)*) => ($(impl Int for $t { + fn zero() -> Self { 0 } + fn one() -> Self { 1 } + })*) +} +doit! { i8 i16 i32 i64 isize } + +macro_rules! check { + ($($e:expr),*) => { + $(assert!(thread::spawn({ + move|| { $e; } + }).join().is_err());)* + } +} + +fn main() { + check![ + isize::MIN / -isize::one(), + i8::MIN / -i8::one(), + i16::MIN / -i16::one(), + i32::MIN / -i32::one(), + i64::MIN / -i64::one(), + 1isize / isize::zero(), + 1i8 / i8::zero(), + 1i16 / i16::zero(), + 1i32 / i32::zero(), + 1i64 / i64::zero(), + isize::MIN % -isize::one(), + i8::MIN % -i8::one(), + i16::MIN % -i16::one(), + i32::MIN % -i32::one(), + i64::MIN % -i64::one(), + 1isize % isize::zero(), + 1i8 % i8::zero(), + 1i16 % i16::zero(), + 1i32 % i32::zero(), + 1i64 % i64::zero() + ]; +} diff --git a/tests/ui/numbers-arithmetic/mod-zero.rs b/tests/ui/numbers-arithmetic/mod-zero.rs new file mode 100644 index 000000000..083716394 --- /dev/null +++ b/tests/ui/numbers-arithmetic/mod-zero.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:attempt to calculate the remainder with a divisor of zero +// ignore-emscripten no processes + +#[allow(unconditional_panic)] +fn main() { + let y = 0; + let _z = 1 % y; +} diff --git a/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs new file mode 100644 index 000000000..79d78da33 --- /dev/null +++ b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs @@ -0,0 +1,27 @@ +// run-pass +// compile-flags: -C debug_assertions=yes +// needs-unwind +// ignore-emscripten dies with an LLVM error + +use std::panic; + +fn main() { + macro_rules! overflow_test { + ($t:ident) => ( + let r = panic::catch_unwind(|| { + ($t::MAX).next_power_of_two() + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + (($t::MAX >> 1) + 2).next_power_of_two() + }); + assert!(r.is_err()); + ) + } + overflow_test!(u8); + overflow_test!(u16); + overflow_test!(u32); + overflow_test!(u64); + overflow_test!(u128); +} diff --git a/tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs new file mode 100644 index 000000000..982cd97c5 --- /dev/null +++ b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -C debug_assertions=no +// ignore-emscripten dies with an LLVM error + +fn main() { + for i in 129..256 { + assert_eq!((i as u8).next_power_of_two(), 0); + } + + assert_eq!(((1u16 << 15) + 1).next_power_of_two(), 0); + assert_eq!(((1u32 << 31) + 1).next_power_of_two(), 0); + assert_eq!(((1u64 << 63) + 1).next_power_of_two(), 0); + assert_eq!(((1u128 << 127) + 1).next_power_of_two(), 0); +} diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.rs b/tests/ui/numbers-arithmetic/not-suggest-float-literal.rs new file mode 100644 index 000000000..513d02db9 --- /dev/null +++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.rs @@ -0,0 +1,53 @@ +fn add_float_to_integer(x: u8) -> f32 { + x + 100.0 //~ ERROR cannot add `{float}` to `u8` +} + +fn add_str_to_float(x: f64) -> f64 { + x + "foo" //~ ERROR cannot add `&str` to `f64` +} + +fn add_lvar_to_float(x: f64) -> f64 { + let y = 3; + x + y //~ ERROR cannot add `{integer}` to `f64` +} + +fn subtract_float_from_integer(x: u8) -> f32 { + x - 100.0 //~ ERROR cannot subtract `{float}` from `u8` +} + +fn subtract_str_from_f64(x: f64) -> f64 { + x - "foo" //~ ERROR cannot subtract `&str` from `f64` +} + +fn subtract_lvar_from_f64(x: f64) -> f64 { + let y = 3; + x - y //~ ERROR cannot subtract `{integer}` from `f64` +} + +fn multiply_integer_by_float(x: u8) -> f32 { + x * 100.0 //~ ERROR cannot multiply `u8` by `{float}` +} + +fn multiply_f64_by_str(x: f64) -> f64 { + x * "foo" //~ ERROR cannot multiply `f64` by `&str` +} + +fn multiply_f64_by_lvar(x: f64) -> f64 { + let y = 3; + x * y //~ ERROR cannot multiply `f64` by `{integer}` +} + +fn divide_integer_by_float(x: u8) -> u8 { + x / 100.0 //~ ERROR cannot divide `u8` by `{float}` +} + +fn divide_f64_by_str(x: f64) -> f64 { + x / "foo" //~ ERROR cannot divide `f64` by `&str` +} + +fn divide_f64_by_lvar(x: f64) -> f64 { + let y = 3; + x / y //~ ERROR cannot divide `f64` by `{integer}` +} + +fn main() {} diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr new file mode 100644 index 000000000..8f0eef237 --- /dev/null +++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -0,0 +1,160 @@ +error[E0277]: cannot add `{float}` to `u8` + --> $DIR/not-suggest-float-literal.rs:2:7 + | +LL | x + 100.0 + | ^ no implementation for `u8 + {float}` + | + = help: the trait `Add<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Add`: + <&'a u8 as Add> + <&u8 as Add<&u8>> + > + + +error[E0277]: cannot add `&str` to `f64` + --> $DIR/not-suggest-float-literal.rs:6:7 + | +LL | x + "foo" + | ^ no implementation for `f64 + &str` + | + = help: the trait `Add<&str>` is not implemented for `f64` + = help: the following other types implement trait `Add`: + <&'a f64 as Add> + <&f64 as Add<&f64>> + > + + +error[E0277]: cannot add `{integer}` to `f64` + --> $DIR/not-suggest-float-literal.rs:11:7 + | +LL | x + y + | ^ no implementation for `f64 + {integer}` + | + = help: the trait `Add<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Add`: + <&'a f64 as Add> + <&f64 as Add<&f64>> + > + + +error[E0277]: cannot subtract `{float}` from `u8` + --> $DIR/not-suggest-float-literal.rs:15:7 + | +LL | x - 100.0 + | ^ no implementation for `u8 - {float}` + | + = help: the trait `Sub<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Sub`: + <&'a u8 as Sub> + <&u8 as Sub<&u8>> + > + + +error[E0277]: cannot subtract `&str` from `f64` + --> $DIR/not-suggest-float-literal.rs:19:7 + | +LL | x - "foo" + | ^ no implementation for `f64 - &str` + | + = help: the trait `Sub<&str>` is not implemented for `f64` + = help: the following other types implement trait `Sub`: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + + +error[E0277]: cannot subtract `{integer}` from `f64` + --> $DIR/not-suggest-float-literal.rs:24:7 + | +LL | x - y + | ^ no implementation for `f64 - {integer}` + | + = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Sub`: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + + +error[E0277]: cannot multiply `u8` by `{float}` + --> $DIR/not-suggest-float-literal.rs:28:7 + | +LL | x * 100.0 + | ^ no implementation for `u8 * {float}` + | + = help: the trait `Mul<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Mul`: + <&'a u8 as Mul> + <&u8 as Mul<&u8>> + > + + +error[E0277]: cannot multiply `f64` by `&str` + --> $DIR/not-suggest-float-literal.rs:32:7 + | +LL | x * "foo" + | ^ no implementation for `f64 * &str` + | + = help: the trait `Mul<&str>` is not implemented for `f64` + = help: the following other types implement trait `Mul`: + <&'a f64 as Mul> + <&f64 as Mul<&f64>> + > + + +error[E0277]: cannot multiply `f64` by `{integer}` + --> $DIR/not-suggest-float-literal.rs:37:7 + | +LL | x * y + | ^ no implementation for `f64 * {integer}` + | + = help: the trait `Mul<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Mul`: + <&'a f64 as Mul> + <&f64 as Mul<&f64>> + > + + +error[E0277]: cannot divide `u8` by `{float}` + --> $DIR/not-suggest-float-literal.rs:41:7 + | +LL | x / 100.0 + | ^ no implementation for `u8 / {float}` + | + = help: the trait `Div<{float}>` is not implemented for `u8` + = help: the following other types implement trait `Div`: + <&'a u8 as Div> + <&u8 as Div<&u8>> + > + > + + +error[E0277]: cannot divide `f64` by `&str` + --> $DIR/not-suggest-float-literal.rs:45:7 + | +LL | x / "foo" + | ^ no implementation for `f64 / &str` + | + = help: the trait `Div<&str>` is not implemented for `f64` + = help: the following other types implement trait `Div`: + <&'a f64 as Div> + <&f64 as Div<&f64>> + > + + +error[E0277]: cannot divide `f64` by `{integer}` + --> $DIR/not-suggest-float-literal.rs:50:7 + | +LL | x / y + | ^ no implementation for `f64 / {integer}` + | + = help: the trait `Div<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Div`: + <&'a f64 as Div> + <&f64 as Div<&f64>> + > + + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/numbers-arithmetic/num-wrapping.rs b/tests/ui/numbers-arithmetic/num-wrapping.rs new file mode 100644 index 000000000..43b1059f9 --- /dev/null +++ b/tests/ui/numbers-arithmetic/num-wrapping.rs @@ -0,0 +1,448 @@ +// run-pass +#![allow(unused_macros)] + +// compile-flags: -C debug-assertions +// +// Test std::num::Wrapping for {uN, iN, usize, isize} + +#![feature(test)] + +extern crate test; + +use std::num::Wrapping; +use std::ops::{ + Add, Sub, Mul, Div, Rem, BitXor, BitOr, BitAnd, + AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitXorAssign, BitOrAssign, BitAndAssign, + Shl, Shr, ShlAssign, ShrAssign +}; +use test::black_box; + +macro_rules! int_modules { + ($(($name:ident, $size:expr),)*) => ($( + mod $name { + pub const BITS: usize = $size; + pub const MAX: $name = $name::MAX; + pub const MIN: $name = $name::MIN; + } + )*) +} + +int_modules! { + (i8, 8), + (i16, 16), + (i32, 32), + (i64, 64), + (u8, 8), + (u16, 16), + (u32, 32), + (u64, 64), +} + +#[cfg(target_pointer_width = "32")] +int_modules! { + (isize, 32), + (usize, 32), +} + +#[cfg(target_pointer_width = "64")] +int_modules! { + (isize, 64), + (usize, 64), +} + +fn main() { + test_ops(); + test_op_assigns(); + test_sh_ops(); + test_sh_op_assigns(); +} + +fn test_ops() { + macro_rules! op_test { + ($op:ident ($lhs:expr, $rhs:expr) == $ans:expr) => { + assert_eq!(black_box(Wrapping($lhs).$op(Wrapping($rhs))), Wrapping($ans)); + // FIXME(30524): uncomment this test when it's implemented + // assert_eq!(black_box(Wrapping($lhs).$op($rhs)), Wrapping($ans)); + } + } + + op_test!(add(i8::MAX, 1) == i8::MIN); + op_test!(add(i16::MAX, 1) == i16::MIN); + op_test!(add(i32::MAX, 1) == i32::MIN); + op_test!(add(i64::MAX, 1) == i64::MIN); + op_test!(add(isize::MAX, 1) == isize::MIN); + + op_test!(add(u8::MAX, 1) == 0); + op_test!(add(u16::MAX, 1) == 0); + op_test!(add(u32::MAX, 1) == 0); + op_test!(add(u64::MAX, 1) == 0); + op_test!(add(usize::MAX, 1) == 0); + + + op_test!(sub(i8::MIN, 1) == i8::MAX); + op_test!(sub(i16::MIN, 1) == i16::MAX); + op_test!(sub(i32::MIN, 1) == i32::MAX); + op_test!(sub(i64::MIN, 1) == i64::MAX); + op_test!(sub(isize::MIN, 1) == isize::MAX); + + op_test!(sub(0u8, 1) == u8::MAX); + op_test!(sub(0u16, 1) == u16::MAX); + op_test!(sub(0u32, 1) == u32::MAX); + op_test!(sub(0u64, 1) == u64::MAX); + op_test!(sub(0usize, 1) == usize::MAX); + + + op_test!(mul(i8::MAX, 2) == -2); + op_test!(mul(i16::MAX, 2) == -2); + op_test!(mul(i32::MAX, 2) == -2); + op_test!(mul(i64::MAX, 2) == -2); + op_test!(mul(isize::MAX, 2) == -2); + + op_test!(mul(u8::MAX, 2) == u8::MAX - 1); + op_test!(mul(u16::MAX, 2) == u16::MAX - 1); + op_test!(mul(u32::MAX, 2) == u32::MAX - 1); + op_test!(mul(u64::MAX, 2) == u64::MAX - 1); + op_test!(mul(usize::MAX, 2) == usize::MAX - 1); + + + op_test!(div(i8::MIN, -1) == i8::MIN); + op_test!(div(i16::MIN, -1) == i16::MIN); + op_test!(div(i32::MIN, -1) == i32::MIN); + op_test!(div(i64::MIN, -1) == i64::MIN); + op_test!(div(isize::MIN, -1) == isize::MIN); + + + op_test!(rem(i8::MIN, -1) == 0); + op_test!(rem(i16::MIN, -1) == 0); + op_test!(rem(i32::MIN, -1) == 0); + op_test!(rem(i64::MIN, -1) == 0); + op_test!(rem(isize::MIN, -1) == 0); + + // these are not that interesting, just testing to make sure they are implemented correctly + op_test!(bitxor(0b101010i8, 0b100110) == 0b001100); + op_test!(bitxor(0b101010i16, 0b100110) == 0b001100); + op_test!(bitxor(0b101010i32, 0b100110) == 0b001100); + op_test!(bitxor(0b101010i64, 0b100110) == 0b001100); + op_test!(bitxor(0b101010isize, 0b100110) == 0b001100); + + op_test!(bitxor(0b101010u8, 0b100110) == 0b001100); + op_test!(bitxor(0b101010u16, 0b100110) == 0b001100); + op_test!(bitxor(0b101010u32, 0b100110) == 0b001100); + op_test!(bitxor(0b101010u64, 0b100110) == 0b001100); + op_test!(bitxor(0b101010usize, 0b100110) == 0b001100); + + + op_test!(bitor(0b101010i8, 0b100110) == 0b101110); + op_test!(bitor(0b101010i16, 0b100110) == 0b101110); + op_test!(bitor(0b101010i32, 0b100110) == 0b101110); + op_test!(bitor(0b101010i64, 0b100110) == 0b101110); + op_test!(bitor(0b101010isize, 0b100110) == 0b101110); + + op_test!(bitor(0b101010u8, 0b100110) == 0b101110); + op_test!(bitor(0b101010u16, 0b100110) == 0b101110); + op_test!(bitor(0b101010u32, 0b100110) == 0b101110); + op_test!(bitor(0b101010u64, 0b100110) == 0b101110); + op_test!(bitor(0b101010usize, 0b100110) == 0b101110); + + + op_test!(bitand(0b101010i8, 0b100110) == 0b100010); + op_test!(bitand(0b101010i16, 0b100110) == 0b100010); + op_test!(bitand(0b101010i32, 0b100110) == 0b100010); + op_test!(bitand(0b101010i64, 0b100110) == 0b100010); + op_test!(bitand(0b101010isize, 0b100110) == 0b100010); + + op_test!(bitand(0b101010u8, 0b100110) == 0b100010); + op_test!(bitand(0b101010u16, 0b100110) == 0b100010); + op_test!(bitand(0b101010u32, 0b100110) == 0b100010); + op_test!(bitand(0b101010u64, 0b100110) == 0b100010); + op_test!(bitand(0b101010usize, 0b100110) == 0b100010); +} + +fn test_op_assigns() { + macro_rules! op_assign_test { + ($op:ident ($initial:expr, $rhs:expr) == $ans:expr) => { + { + let mut tmp = Wrapping($initial); + tmp = black_box(tmp); + tmp.$op(Wrapping($rhs)); + assert_eq!(black_box(tmp), Wrapping($ans)); + } + + // also test that a &Wrapping right-hand side is possible + { + let mut tmp = Wrapping($initial); + tmp = black_box(tmp); + tmp.$op(&Wrapping($rhs)); + assert_eq!(black_box(tmp), Wrapping($ans)); + } + + // FIXME(30524): uncomment this test + /* + { + let mut tmp = Wrapping($initial); + tmp = black_box(tmp); + tmp.$op($rhs); + assert_eq!(black_box(tmp), Wrapping($ans)); + } + */ + } + } + op_assign_test!(add_assign(i8::MAX, 1) == i8::MIN); + op_assign_test!(add_assign(i16::MAX, 1) == i16::MIN); + op_assign_test!(add_assign(i32::MAX, 1) == i32::MIN); + op_assign_test!(add_assign(i64::MAX, 1) == i64::MIN); + op_assign_test!(add_assign(isize::MAX, 1) == isize::MIN); + + op_assign_test!(add_assign(u8::MAX, 1) == u8::MIN); + op_assign_test!(add_assign(u16::MAX, 1) == u16::MIN); + op_assign_test!(add_assign(u32::MAX, 1) == u32::MIN); + op_assign_test!(add_assign(u64::MAX, 1) == u64::MIN); + op_assign_test!(add_assign(usize::MAX, 1) == usize::MIN); + + + op_assign_test!(sub_assign(i8::MIN, 1) == i8::MAX); + op_assign_test!(sub_assign(i16::MIN, 1) == i16::MAX); + op_assign_test!(sub_assign(i32::MIN, 1) == i32::MAX); + op_assign_test!(sub_assign(i64::MIN, 1) == i64::MAX); + op_assign_test!(sub_assign(isize::MIN, 1) == isize::MAX); + + op_assign_test!(sub_assign(u8::MIN, 1) == u8::MAX); + op_assign_test!(sub_assign(u16::MIN, 1) == u16::MAX); + op_assign_test!(sub_assign(u32::MIN, 1) == u32::MAX); + op_assign_test!(sub_assign(u64::MIN, 1) == u64::MAX); + op_assign_test!(sub_assign(usize::MIN, 1) == usize::MAX); + + + op_assign_test!(mul_assign(i8::MAX, 2) == -2); + op_assign_test!(mul_assign(i16::MAX, 2) == -2); + op_assign_test!(mul_assign(i32::MAX, 2) == -2); + op_assign_test!(mul_assign(i64::MAX, 2) == -2); + op_assign_test!(mul_assign(isize::MAX, 2) == -2); + + op_assign_test!(mul_assign(u8::MAX, 2) == u8::MAX - 1); + op_assign_test!(mul_assign(u16::MAX, 2) == u16::MAX - 1); + op_assign_test!(mul_assign(u32::MAX, 2) == u32::MAX - 1); + op_assign_test!(mul_assign(u64::MAX, 2) == u64::MAX - 1); + op_assign_test!(mul_assign(usize::MAX, 2) == usize::MAX - 1); + + + op_assign_test!(div_assign(i8::MIN, -1) == i8::MIN); + op_assign_test!(div_assign(i16::MIN, -1) == i16::MIN); + op_assign_test!(div_assign(i32::MIN, -1) == i32::MIN); + op_assign_test!(div_assign(i64::MIN, -1) == i64::MIN); + op_assign_test!(div_assign(isize::MIN, -1) == isize::MIN); + + + op_assign_test!(rem_assign(i8::MIN, -1) == 0); + op_assign_test!(rem_assign(i16::MIN, -1) == 0); + op_assign_test!(rem_assign(i32::MIN, -1) == 0); + op_assign_test!(rem_assign(i64::MIN, -1) == 0); + op_assign_test!(rem_assign(isize::MIN, -1) == 0); + + + // these are not that interesting, just testing to make sure they are implemented correctly + op_assign_test!(bitxor_assign(0b101010i8, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010i16, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010i32, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010i64, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010isize, 0b100110) == 0b001100); + + op_assign_test!(bitxor_assign(0b101010u8, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010u16, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010u32, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010u64, 0b100110) == 0b001100); + op_assign_test!(bitxor_assign(0b101010usize, 0b100110) == 0b001100); + + + op_assign_test!(bitor_assign(0b101010i8, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010i16, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010i32, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010i64, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010isize, 0b100110) == 0b101110); + + op_assign_test!(bitor_assign(0b101010u8, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010u16, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010u32, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010u64, 0b100110) == 0b101110); + op_assign_test!(bitor_assign(0b101010usize, 0b100110) == 0b101110); + + + op_assign_test!(bitand_assign(0b101010i8, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010i16, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010i32, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010i64, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010isize, 0b100110) == 0b100010); + + op_assign_test!(bitand_assign(0b101010u8, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010u16, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010u32, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010u64, 0b100110) == 0b100010); + op_assign_test!(bitand_assign(0b101010usize, 0b100110) == 0b100010); +} + +fn test_sh_ops() { + macro_rules! sh_test { + ($op:ident ($lhs:expr, $rhs:expr) == $ans:expr) => { + assert_eq!(black_box(Wrapping($lhs).$op($rhs)), Wrapping($ans)); + } + } + // NOTE: This will break for i8 if we ever get i/u128 + macro_rules! sh_test_all { + ($t:ty) => { + sh_test!(shl(i8::MAX, (i8::BITS + 1) as $t) == -2); + sh_test!(shl(i16::MAX, (i16::BITS + 1) as $t) == -2); + sh_test!(shl(i32::MAX, (i32::BITS + 1) as $t) == -2); + sh_test!(shl(i64::MAX, (i64::BITS + 1) as $t) == -2); + sh_test!(shl(isize::MAX, (isize::BITS + 1) as $t) == -2); + + sh_test!(shl(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX - 1); + sh_test!(shl(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX - 1); + sh_test!(shl(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX - 1); + sh_test!(shl(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX - 1); + sh_test!(shl(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX - 1); + + + sh_test!(shr(i8::MAX, (i8::BITS + 1) as $t) == i8::MAX / 2); + sh_test!(shr(i16::MAX, (i16::BITS + 1) as $t) == i16::MAX / 2); + sh_test!(shr(i32::MAX, (i32::BITS + 1) as $t) == i32::MAX / 2); + sh_test!(shr(i64::MAX, (i64::BITS + 1) as $t) == i64::MAX / 2); + sh_test!(shr(isize::MAX, (isize::BITS + 1) as $t) == isize::MAX / 2); + + sh_test!(shr(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX / 2); + sh_test!(shr(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX / 2); + sh_test!(shr(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX / 2); + sh_test!(shr(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX / 2); + sh_test!(shr(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX / 2); + } + } + macro_rules! sh_test_negative_all { + ($t:ty) => { + sh_test!(shr(i8::MAX, -((i8::BITS + 1) as $t)) == -2); + sh_test!(shr(i16::MAX, -((i16::BITS + 1) as $t)) == -2); + sh_test!(shr(i32::MAX, -((i32::BITS + 1) as $t)) == -2); + sh_test!(shr(i64::MAX, -((i64::BITS + 1) as $t)) == -2); + sh_test!(shr(isize::MAX, -((isize::BITS + 1) as $t)) == -2); + + sh_test!(shr(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX - 1); + sh_test!(shr(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX - 1); + sh_test!(shr(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX - 1); + sh_test!(shr(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX - 1); + sh_test!(shr(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX - 1); + + + sh_test!(shl(i8::MAX, -((i8::BITS + 1) as $t)) == i8::MAX / 2); + sh_test!(shl(i16::MAX, -((i16::BITS + 1) as $t)) == i16::MAX / 2); + sh_test!(shl(i32::MAX, -((i32::BITS + 1) as $t)) == i32::MAX / 2); + sh_test!(shl(i64::MAX, -((i64::BITS + 1) as $t)) == i64::MAX / 2); + sh_test!(shl(isize::MAX, -((isize::BITS + 1) as $t)) == isize::MAX / 2); + + sh_test!(shl(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX / 2); + sh_test!(shl(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX / 2); + sh_test!(shl(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX / 2); + sh_test!(shl(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX / 2); + sh_test!(shl(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX / 2); + } + } + // FIXME(#23545): Uncomment the remaining tests + //sh_test_all!(i8); + //sh_test_all!(u8); + //sh_test_all!(i16); + //sh_test_all!(u16); + //sh_test_all!(i32); + //sh_test_all!(u32); + //sh_test_all!(i64); + //sh_test_all!(u64); + //sh_test_all!(isize); + sh_test_all!(usize); + + //sh_test_negative_all!(i8); + //sh_test_negative_all!(i16); + //sh_test_negative_all!(i32); + //sh_test_negative_all!(i64); + //sh_test_negative_all!(isize); +} + +fn test_sh_op_assigns() { + macro_rules! sh_assign_test { + ($op:ident ($initial:expr, $rhs:expr) == $ans:expr) => {{ + let mut tmp = Wrapping($initial); + tmp = black_box(tmp); + tmp.$op($rhs); + assert_eq!(black_box(tmp), Wrapping($ans)); + }} + } + macro_rules! sh_assign_test_all { + ($t:ty) => { + sh_assign_test!(shl_assign(i8::MAX, (i8::BITS + 1) as $t) == -2); + sh_assign_test!(shl_assign(i16::MAX, (i16::BITS + 1) as $t) == -2); + sh_assign_test!(shl_assign(i32::MAX, (i32::BITS + 1) as $t) == -2); + sh_assign_test!(shl_assign(i64::MAX, (i64::BITS + 1) as $t) == -2); + sh_assign_test!(shl_assign(isize::MAX, (isize::BITS + 1) as $t) == -2); + + sh_assign_test!(shl_assign(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX - 1); + sh_assign_test!(shl_assign(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX - 1); + sh_assign_test!(shl_assign(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX - 1); + sh_assign_test!(shl_assign(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX - 1); + sh_assign_test!(shl_assign(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX - 1); + + + sh_assign_test!(shr_assign(i8::MAX, (i8::BITS + 1) as $t) == i8::MAX / 2); + sh_assign_test!(shr_assign(i16::MAX, (i16::BITS + 1) as $t) == i16::MAX / 2); + sh_assign_test!(shr_assign(i32::MAX, (i32::BITS + 1) as $t) == i32::MAX / 2); + sh_assign_test!(shr_assign(i64::MAX, (i64::BITS + 1) as $t) == i64::MAX / 2); + sh_assign_test!(shr_assign(isize::MAX, (isize::BITS + 1) as $t) == isize::MAX / 2); + + sh_assign_test!(shr_assign(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX / 2); + sh_assign_test!(shr_assign(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX / 2); + sh_assign_test!(shr_assign(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX / 2); + sh_assign_test!(shr_assign(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX / 2); + sh_assign_test!(shr_assign(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX / 2); + } + } + macro_rules! sh_assign_test_negative_all { + ($t:ty) => { + sh_assign_test!(shr_assign(i8::MAX, -((i8::BITS + 1) as $t)) == -2); + sh_assign_test!(shr_assign(i16::MAX, -((i16::BITS + 1) as $t)) == -2); + sh_assign_test!(shr_assign(i32::MAX, -((i32::BITS + 1) as $t)) == -2); + sh_assign_test!(shr_assign(i64::MAX, -((i64::BITS + 1) as $t)) == -2); + sh_assign_test!(shr_assign(isize::MAX, -((isize::BITS + 1) as $t)) == -2); + + sh_assign_test!(shr_assign(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX - 1); + sh_assign_test!(shr_assign(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX - 1); + sh_assign_test!(shr_assign(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX - 1); + sh_assign_test!(shr_assign(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX - 1); + sh_assign_test!(shr_assign(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX - 1); + + + sh_assign_test!(shl_assign(i8::MAX, -((i8::BITS + 1) as $t)) == i8::MAX / 2); + sh_assign_test!(shl_assign(i16::MAX, -((i16::BITS + 1) as $t)) == i16::MAX / 2); + sh_assign_test!(shl_assign(i32::MAX, -((i32::BITS + 1) as $t)) == i32::MAX / 2); + sh_assign_test!(shl_assign(i64::MAX, -((i64::BITS + 1) as $t)) == i64::MAX / 2); + sh_assign_test!(shl_assign(isize::MAX, -((isize::BITS + 1) as $t)) == isize::MAX / 2); + + sh_assign_test!(shl_assign(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX / 2); + sh_assign_test!(shl_assign(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX / 2); + sh_assign_test!(shl_assign(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX / 2); + sh_assign_test!(shl_assign(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX / 2); + sh_assign_test!(shl_assign(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX / 2); + } + } + + // FIXME(#23545): Uncomment the remaining tests + //sh_assign_test_all!(i8); + //sh_assign_test_all!(u8); + //sh_assign_test_all!(i16); + //sh_assign_test_all!(u16); + //sh_assign_test_all!(i32); + //sh_assign_test_all!(u32); + //sh_assign_test_all!(i64); + //sh_assign_test_all!(u64); + //sh_assign_test_all!(isize); + sh_assign_test_all!(usize); + + //sh_assign_test_negative_all!(i8); + //sh_assign_test_negative_all!(i16); + //sh_assign_test_negative_all!(i32); + //sh_assign_test_negative_all!(i64); + //sh_assign_test_negative_all!(isize); +} diff --git a/tests/ui/numbers-arithmetic/numeric-method-autoexport.rs b/tests/ui/numbers-arithmetic/numeric-method-autoexport.rs new file mode 100644 index 000000000..5798c2591 --- /dev/null +++ b/tests/ui/numbers-arithmetic/numeric-method-autoexport.rs @@ -0,0 +1,25 @@ +// run-pass +// This file is intended to test only that methods are automatically +// reachable for each numeric type, for each exported impl, with no imports +// necessary. Testing the methods of the impls is done within the source +// file for each numeric type. + +use std::ops::Add; + +pub fn main() { +// ints + // num + assert_eq!(15_isize.add(6_isize), 21_isize); + assert_eq!(15_i8.add(6i8), 21_i8); + assert_eq!(15_i16.add(6i16), 21_i16); + assert_eq!(15_i32.add(6i32), 21_i32); + assert_eq!(15_i64.add(6i64), 21_i64); + +// uints + // num + assert_eq!(15_usize.add(6_usize), 21_usize); + assert_eq!(15_u8.add(6u8), 21_u8); + assert_eq!(15_u16.add(6u16), 21_u16); + assert_eq!(15_u32.add(6u32), 21_u32); + assert_eq!(15_u64.add(6u64), 21_u64); +} diff --git a/tests/ui/numbers-arithmetic/overflowing-add.rs b/tests/ui/numbers-arithmetic/overflowing-add.rs new file mode 100644 index 000000000..b0f22a74b --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-add.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to add with overflow' +// compile-flags: -C debug-assertions +// ignore-emscripten no processes + +#![allow(arithmetic_overflow)] + +fn main() { + let _x = 200u8 + 200u8 + 200u8; +} diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-1.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-1.rs new file mode 100644 index 000000000..7f8b0c877 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-1.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _x = 1_i32 << 32; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr new file mode 100644 index 000000000..434c9d5b4 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-lsh-1.rs:7:14 + | +LL | let _x = 1_i32 << 32; + | ^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-lsh-1.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-2.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-2.rs new file mode 100644 index 000000000..76718ecd1 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-2.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _x = 1 << -1; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr new file mode 100644 index 000000000..c3b44e5a0 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-lsh-2.rs:7:14 + | +LL | let _x = 1 << -1; + | ^^^^^^^ attempt to shift left by `-1_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-lsh-2.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-3.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-3.rs new file mode 100644 index 000000000..b2bdd09bf --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-3.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _x = 1_u64 << 64; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr new file mode 100644 index 000000000..9d6479bd7 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-lsh-3.rs:7:14 + | +LL | let _x = 1_u64 << 64; + | ^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-lsh-3.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-4.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-4.rs new file mode 100644 index 000000000..1042bfcb3 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-4.rs @@ -0,0 +1,24 @@ +// build-fail +// compile-flags: -C debug-assertions + +// This function is checking that our automatic truncation does not +// sidestep the overflow checking. + +#![deny(arithmetic_overflow)] + +fn main() { + // this signals overflow when checking is on + let x = 1_i8 << 17; + //~^ ERROR: this arithmetic operation will overflow + + // ... but when checking is off, the fallback will truncate the + // input to its lower three bits (= 1). Note that this is *not* + // the behavior of the x86 processor for 8- and 16-bit types, + // but it is necessary to avoid undefined behavior from LLVM. + // + // We check that here, by ensuring the result has only been + // shifted by one place; if overflow checking is turned off, then + // this assertion will pass (and the compiletest driver will + // report that the test did not produce the error expected above). + assert_eq!(x, 2_i8); +} diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr new file mode 100644 index 000000000..2bb5b6a6d --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-lsh-4.rs:11:13 + | +LL | let x = 1_i8 << 17; + | ^^^^^^^^^^ attempt to shift left by `17_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-lsh-4.rs:7:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-mul.rs b/tests/ui/numbers-arithmetic/overflowing-mul.rs new file mode 100644 index 000000000..34ab5d8fa --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-mul.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to multiply with overflow' +// ignore-emscripten no processes +// compile-flags: -C debug-assertions + +#![allow(arithmetic_overflow)] + +fn main() { + let x = 200u8 * 4; +} diff --git a/tests/ui/numbers-arithmetic/overflowing-neg.rs b/tests/ui/numbers-arithmetic/overflowing-neg.rs new file mode 100644 index 000000000..df1198053 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-neg.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to negate with overflow' +// ignore-emscripten no processes +// compile-flags: -C debug-assertions + +#![allow(arithmetic_overflow)] + +fn main() { + let _x = -i8::MIN; +} diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs new file mode 100644 index 000000000..b59efe6f2 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to multiply with overflow' +// ignore-emscripten no processes +// compile-flags: -C debug-assertions + +fn main() { + let _x = 2i32.pow(1024); +} diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs new file mode 100644 index 000000000..f2643c164 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to multiply with overflow' +// ignore-emscripten no processes +// compile-flags: -C debug-assertions + +fn main() { + let _x = 2u32.pow(1024); +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-1.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-1.rs new file mode 100644 index 000000000..80593c865 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-1.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _x = -1_i32 >> 32; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr new file mode 100644 index 000000000..b2b3114d1 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-rsh-1.rs:7:14 + | +LL | let _x = -1_i32 >> 32; + | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-rsh-1.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-2.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-2.rs new file mode 100644 index 000000000..917352bfc --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-2.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _x = -1_i32 >> -1; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr new file mode 100644 index 000000000..ad18c3bb7 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-rsh-2.rs:7:14 + | +LL | let _x = -1_i32 >> -1; + | ^^^^^^^^^^^^ attempt to shift right by `-1_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-rsh-2.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-3.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-3.rs new file mode 100644 index 000000000..1e052990a --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-3.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _x = -1_i64 >> 64; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr new file mode 100644 index 000000000..37d02e09d --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-rsh-3.rs:7:14 + | +LL | let _x = -1_i64 >> 64; + | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-rsh-3.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-4.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-4.rs new file mode 100644 index 000000000..be918becd --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-4.rs @@ -0,0 +1,24 @@ +// build-fail +// compile-flags: -C debug-assertions + +// This function is checking that our (type-based) automatic +// truncation does not sidestep the overflow checking. + +#![deny(arithmetic_overflow)] + +fn main() { + // this signals overflow when checking is on + let x = 2_i8 >> 17; + //~^ ERROR: this arithmetic operation will overflow + + // ... but when checking is off, the fallback will truncate the + // input to its lower three bits (= 1). Note that this is *not* + // the behavior of the x86 processor for 8- and 16-bit types, + // but it is necessary to avoid undefined behavior from LLVM. + // + // We check that here, by ensuring the result is not zero; if + // overflow checking is turned off, then this assertion will pass + // (and the compiletest driver will report that the test did not + // produce the error expected above). + assert_eq!(x, 1_i8); +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr new file mode 100644 index 000000000..692602c07 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-rsh-4.rs:11:13 + | +LL | let x = 2_i8 >> 17; + | ^^^^^^^^^^ attempt to shift right by `17_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-rsh-4.rs:7:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-5.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-5.rs new file mode 100644 index 000000000..f75e779ed --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-5.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _n = 1i64 >> [64][0]; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr new file mode 100644 index 000000000..e3b5859df --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-rsh-5.rs:7:14 + | +LL | let _n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-rsh-5.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-6.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-6.rs new file mode 100644 index 000000000..f75e779ed --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-6.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow)] + +fn main() { + let _n = 1i64 >> [64][0]; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr new file mode 100644 index 000000000..a3475c04c --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr @@ -0,0 +1,14 @@ +error: this arithmetic operation will overflow + --> $DIR/overflowing-rsh-6.rs:7:14 + | +LL | let _n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow + | +note: the lint level is defined here + --> $DIR/overflowing-rsh-6.rs:4:9 + | +LL | #![deny(arithmetic_overflow)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/numbers-arithmetic/overflowing-sub.rs b/tests/ui/numbers-arithmetic/overflowing-sub.rs new file mode 100644 index 000000000..66685ac96 --- /dev/null +++ b/tests/ui/numbers-arithmetic/overflowing-sub.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'attempt to subtract with overflow' +// ignore-emscripten no processes +// compile-flags: -C debug-assertions + +#![allow(arithmetic_overflow)] + +fn main() { + let _x = 42u8 - (42u8 + 1); +} diff --git a/tests/ui/numbers-arithmetic/promoted_overflow.rs b/tests/ui/numbers-arithmetic/promoted_overflow.rs new file mode 100644 index 000000000..ba168f773 --- /dev/null +++ b/tests/ui/numbers-arithmetic/promoted_overflow.rs @@ -0,0 +1,13 @@ +#![allow(arithmetic_overflow)] + +// run-fail +// error-pattern: overflow +// compile-flags: -C overflow-checks=yes +// for some reason, fails to match error string on +// wasm32-unknown-unknown with stripped debuginfo and symbols, +// so don't strip it +// compile-flags:-Cstrip=none + +fn main() { + let x: &'static u32 = &(0u32 - 1); +} diff --git a/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs b/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs new file mode 100644 index 000000000..76279e913 --- /dev/null +++ b/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs @@ -0,0 +1,8 @@ +// run-pass + +// compile-flags: -O + +fn main() { + let x = &(0u32 - 1); + assert_eq!(*x, u32::MAX) +} diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs new file mode 100644 index 000000000..4c6929d66 --- /dev/null +++ b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs @@ -0,0 +1,503 @@ +// ignore-test + +// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction. +// +// Some of these tests come from a similar file in miri, +// tests/run-pass/float.rs. Individual test cases are potentially duplicated +// with the previously existing tests, but since this runs so quickly anyway, +// we're not spending the time to figure out exactly which ones should be +// merged. + +extern crate test; + +use self::test::black_box; + +macro_rules! test { + ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ( + // black_box disables constant evaluation to test run-time conversions: + assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected, + "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty)); + + { + const X: $src_ty = $val; + const Y: $dest_ty = X as $dest_ty; + assert_eq!(Y, $expected, + "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty)); + } + ); + + ($fval:expr, f* -> $ity:ident, $ival:expr) => ( + test!($fval, f32 -> $ity, $ival); + test!($fval, f64 -> $ity, $ival); + ) +} + +macro_rules! common_fptoi_tests { + ($fty:ident -> $($ity:ident)+) => ({ $( + test!($fty::NAN, $fty -> $ity, 0); + test!($fty::INFINITY, $fty -> $ity, $ity::MAX); + test!($fty::NEG_INFINITY, $fty -> $ity, $ity::MIN); + // These two tests are not solely float->int tests, in particular the latter relies on + // `u128::MAX as f32` not being UB. But that's okay, since this file tests int->float + // as well, the test is just slightly misplaced. + test!($ity::MIN as $fty, $fty -> $ity, $ity::MIN); + test!($ity::MAX as $fty, $fty -> $ity, $ity::MAX); + test!(0., $fty -> $ity, 0); + test!($fty::MIN_POSITIVE, $fty -> $ity, 0); + test!(-0.9, $fty -> $ity, 0); + test!(1., $fty -> $ity, 1); + test!(42., $fty -> $ity, 42); + )+ }); + + (f* -> $($ity:ident)+) => ({ + common_fptoi_tests!(f32 -> $($ity)+); + common_fptoi_tests!(f64 -> $($ity)+); + }) +} + +macro_rules! fptoui_tests { + ($fty: ident -> $($ity: ident)+) => ({ $( + test!(-0., $fty -> $ity, 0); + test!(-$fty::MIN_POSITIVE, $fty -> $ity, 0); + test!(-0.99999994, $fty -> $ity, 0); + test!(-1., $fty -> $ity, 0); + test!(-100., $fty -> $ity, 0); + test!(#[allow(overflowing_literals)] -1e50, $fty -> $ity, 0); + test!(#[allow(overflowing_literals)] -1e130, $fty -> $ity, 0); + )+ }); + + (f* -> $($ity:ident)+) => ({ + fptoui_tests!(f32 -> $($ity)+); + fptoui_tests!(f64 -> $($ity)+); + }) +} + +use std::fmt::Debug; + +// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE. +#[track_caller] +#[inline(never)] +fn assert_eq(x: T, y: T) { + assert_eq!(x, y); +} + +trait FloatToInt: Copy { + fn cast(self) -> Int; + unsafe fn cast_unchecked(self) -> Int; +} + +impl FloatToInt for f32 { + fn cast(self) -> i8 { + self as _ + } + unsafe fn cast_unchecked(self) -> i8 { + self.to_int_unchecked() + } +} +impl FloatToInt for f32 { + fn cast(self) -> i32 { + self as _ + } + unsafe fn cast_unchecked(self) -> i32 { + self.to_int_unchecked() + } +} +impl FloatToInt for f32 { + fn cast(self) -> u32 { + self as _ + } + unsafe fn cast_unchecked(self) -> u32 { + self.to_int_unchecked() + } +} +impl FloatToInt for f32 { + fn cast(self) -> i64 { + self as _ + } + unsafe fn cast_unchecked(self) -> i64 { + self.to_int_unchecked() + } +} +impl FloatToInt for f32 { + fn cast(self) -> u64 { + self as _ + } + unsafe fn cast_unchecked(self) -> u64 { + self.to_int_unchecked() + } +} + +impl FloatToInt for f64 { + fn cast(self) -> i8 { + self as _ + } + unsafe fn cast_unchecked(self) -> i8 { + self.to_int_unchecked() + } +} +impl FloatToInt for f64 { + fn cast(self) -> i32 { + self as _ + } + unsafe fn cast_unchecked(self) -> i32 { + self.to_int_unchecked() + } +} +impl FloatToInt for f64 { + fn cast(self) -> u32 { + self as _ + } + unsafe fn cast_unchecked(self) -> u32 { + self.to_int_unchecked() + } +} +impl FloatToInt for f64 { + fn cast(self) -> i64 { + self as _ + } + unsafe fn cast_unchecked(self) -> i64 { + self.to_int_unchecked() + } +} +impl FloatToInt for f64 { + fn cast(self) -> u64 { + self as _ + } + unsafe fn cast_unchecked(self) -> u64 { + self.to_int_unchecked() + } +} +// FIXME emscripten does not support i128 +#[cfg(not(target_os = "emscripten"))] +impl FloatToInt for f64 { + fn cast(self) -> i128 { + self as _ + } + unsafe fn cast_unchecked(self) -> i128 { + self.to_int_unchecked() + } +} +// FIXME emscripten does not support i128 +#[cfg(not(target_os = "emscripten"))] +impl FloatToInt for f64 { + fn cast(self) -> u128 { + self as _ + } + unsafe fn cast_unchecked(self) -> u128 { + self.to_int_unchecked() + } +} + +/// Test this cast both via `as` and via `to_int_unchecked` (i.e., it must not saturate). +#[track_caller] +#[inline(never)] +fn test_both_cast(x: F, y: I) +where + F: FloatToInt, + I: PartialEq + Debug, +{ + assert_eq!(x.cast(), y); + assert_eq!(unsafe { x.cast_unchecked() }, y); +} + +fn casts() { + // f32 -> i8 + test_both_cast::(127.99, 127); + test_both_cast::(-128.99, -128); + + // f32 -> i32 + test_both_cast::(0.0, 0); + test_both_cast::(-0.0, 0); + test_both_cast::(/*0x1p-149*/ f32::from_bits(0x00000001), 0); + test_both_cast::(/*-0x1p-149*/ f32::from_bits(0x80000001), 0); + test_both_cast::(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1); + test_both_cast::(/*-0x1.19999ap+0*/ f32::from_bits(0xbf8ccccd), -1); + test_both_cast::(1.9, 1); + test_both_cast::(-1.9, -1); + test_both_cast::(5.0, 5); + test_both_cast::(-5.0, -5); + test_both_cast::(2147483520.0, 2147483520); + test_both_cast::(-2147483648.0, -2147483648); + // unrepresentable casts + assert_eq::(2147483648.0f32 as i32, i32::MAX); + assert_eq::(-2147483904.0f32 as i32, i32::MIN); + assert_eq::(f32::MAX as i32, i32::MAX); + assert_eq::(f32::MIN as i32, i32::MIN); + assert_eq::(f32::INFINITY as i32, i32::MAX); + assert_eq::(f32::NEG_INFINITY as i32, i32::MIN); + assert_eq::(f32::NAN as i32, 0); + assert_eq::((-f32::NAN) as i32, 0); + + // f32 -> u32 + test_both_cast::(0.0, 0); + test_both_cast::(-0.0, 0); + test_both_cast::(-0.9999999, 0); + test_both_cast::(/*0x1p-149*/ f32::from_bits(0x1), 0); + test_both_cast::(/*-0x1p-149*/ f32::from_bits(0x80000001), 0); + test_both_cast::(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1); + test_both_cast::(1.9, 1); + test_both_cast::(5.0, 5); + test_both_cast::(2147483648.0, 0x8000_0000); + test_both_cast::(4294967040.0, 0u32.wrapping_sub(256)); + test_both_cast::(/*-0x1.ccccccp-1*/ f32::from_bits(0xbf666666), 0); + test_both_cast::(/*-0x1.fffffep-1*/ f32::from_bits(0xbf7fffff), 0); + test_both_cast::((u32::MAX - 128) as f32, u32::MAX - 255); // rounding loss + + // unrepresentable casts: + + // rounds up and then becomes unrepresentable + assert_eq::((u32::MAX - 127) as f32 as u32, u32::MAX); + + assert_eq::(4294967296.0f32 as u32, u32::MAX); + assert_eq::(-5.0f32 as u32, 0); + assert_eq::(f32::MAX as u32, u32::MAX); + assert_eq::(f32::MIN as u32, 0); + assert_eq::(f32::INFINITY as u32, u32::MAX); + assert_eq::(f32::NEG_INFINITY as u32, 0); + assert_eq::(f32::NAN as u32, 0); + assert_eq::((-f32::NAN) as u32, 0); + + // f32 -> i64 + test_both_cast::(4294967296.0, 4294967296); + test_both_cast::(-4294967296.0, -4294967296); + test_both_cast::(9223371487098961920.0, 9223371487098961920); + test_both_cast::(-9223372036854775808.0, -9223372036854775808); + + // f64 -> i8 + test_both_cast::(127.99, 127); + test_both_cast::(-128.99, -128); + + // f64 -> i32 + test_both_cast::(0.0, 0); + test_both_cast::(-0.0, 0); + test_both_cast::(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1); + test_both_cast::( + /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a), + -1, + ); + test_both_cast::(1.9, 1); + test_both_cast::(-1.9, -1); + test_both_cast::(1e8, 100_000_000); + test_both_cast::(2147483647.0, 2147483647); + test_both_cast::(-2147483648.0, -2147483648); + // unrepresentable casts + assert_eq::(2147483648.0f64 as i32, i32::MAX); + assert_eq::(-2147483649.0f64 as i32, i32::MIN); + + // f64 -> i64 + test_both_cast::(0.0, 0); + test_both_cast::(-0.0, 0); + test_both_cast::(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1), 0); + test_both_cast::( + /*-0x0.0000000000001p-1022*/ f64::from_bits(0x8000000000000001), + 0, + ); + test_both_cast::(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1); + test_both_cast::( + /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a), + -1, + ); + test_both_cast::(5.0, 5); + test_both_cast::(5.9, 5); + test_both_cast::(-5.0, -5); + test_both_cast::(-5.9, -5); + test_both_cast::(4294967296.0, 4294967296); + test_both_cast::(-4294967296.0, -4294967296); + test_both_cast::(9223372036854774784.0, 9223372036854774784); + test_both_cast::(-9223372036854775808.0, -9223372036854775808); + // unrepresentable casts + assert_eq::(9223372036854775808.0f64 as i64, i64::MAX); + assert_eq::(-9223372036854777856.0f64 as i64, i64::MIN); + assert_eq::(f64::MAX as i64, i64::MAX); + assert_eq::(f64::MIN as i64, i64::MIN); + assert_eq::(f64::INFINITY as i64, i64::MAX); + assert_eq::(f64::NEG_INFINITY as i64, i64::MIN); + assert_eq::(f64::NAN as i64, 0); + assert_eq::((-f64::NAN) as i64, 0); + + // f64 -> u64 + test_both_cast::(0.0, 0); + test_both_cast::(-0.0, 0); + test_both_cast::(-0.99999999999, 0); + test_both_cast::(5.0, 5); + test_both_cast::(1e16, 10000000000000000); + test_both_cast::((u64::MAX - 1024) as f64, u64::MAX - 2047); // rounding loss + test_both_cast::(9223372036854775808.0, 9223372036854775808); + // unrepresentable casts + assert_eq::(-5.0f64 as u64, 0); + // rounds up and then becomes unrepresentable + assert_eq::((u64::MAX - 1023) as f64 as u64, u64::MAX); + assert_eq::(18446744073709551616.0f64 as u64, u64::MAX); + assert_eq::(f64::MAX as u64, u64::MAX); + assert_eq::(f64::MIN as u64, 0); + assert_eq::(f64::INFINITY as u64, u64::MAX); + assert_eq::(f64::NEG_INFINITY as u64, 0); + assert_eq::(f64::NAN as u64, 0); + assert_eq::((-f64::NAN) as u64, 0); + + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + // f64 -> i128 + assert_eq::(f64::MAX as i128, i128::MAX); + assert_eq::(f64::MIN as i128, i128::MIN); + + // f64 -> u128 + assert_eq::(f64::MAX as u128, u128::MAX); + assert_eq::(f64::MIN as u128, 0); + } + + // int -> f32 + assert_eq::(127i8 as f32, 127.0); + assert_eq::(2147483647i32 as f32, 2147483648.0); + assert_eq::((-2147483648i32) as f32, -2147483648.0); + assert_eq::(1234567890i32 as f32, /*0x1.26580cp+30*/ f32::from_bits(0x4e932c06)); + assert_eq::(16777217i32 as f32, 16777216.0); + assert_eq::((-16777217i32) as f32, -16777216.0); + assert_eq::(16777219i32 as f32, 16777220.0); + assert_eq::((-16777219i32) as f32, -16777220.0); + assert_eq::( + 0x7fffff4000000001i64 as f32, + /*0x1.fffffep+62*/ f32::from_bits(0x5effffff), + ); + assert_eq::( + 0x8000004000000001u64 as i64 as f32, + /*-0x1.fffffep+62*/ f32::from_bits(0xdeffffff), + ); + assert_eq::( + 0x0020000020000001i64 as f32, + /*0x1.000002p+53*/ f32::from_bits(0x5a000001), + ); + assert_eq::( + 0xffdfffffdfffffffu64 as i64 as f32, + /*-0x1.000002p+53*/ f32::from_bits(0xda000001), + ); + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + assert_eq::(i128::MIN as f32, -170141183460469231731687303715884105728.0f32); + assert_eq::(u128::MAX as f32, f32::INFINITY); // saturation + } + + // int -> f64 + assert_eq::(127i8 as f64, 127.0); + assert_eq::(i16::MIN as f64, -32768.0f64); + assert_eq::(2147483647i32 as f64, 2147483647.0); + assert_eq::(-2147483648i32 as f64, -2147483648.0); + assert_eq::(987654321i32 as f64, 987654321.0); + assert_eq::(9223372036854775807i64 as f64, 9223372036854775807.0); + assert_eq::(-9223372036854775808i64 as f64, -9223372036854775808.0); + assert_eq::(4669201609102990i64 as f64, 4669201609102990.0); // Feigenbaum (?) + assert_eq::(9007199254740993i64 as f64, 9007199254740992.0); + assert_eq::(-9007199254740993i64 as f64, -9007199254740992.0); + assert_eq::(9007199254740995i64 as f64, 9007199254740996.0); + assert_eq::(-9007199254740995i64 as f64, -9007199254740996.0); + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + // even that fits... + assert_eq::(u128::MAX as f64, 340282366920938463463374607431768211455.0f64); + } + + // f32 -> f64 + assert_eq::((0.0f32 as f64).to_bits(), 0.0f64.to_bits()); + assert_eq::(((-0.0f32) as f64).to_bits(), (-0.0f64).to_bits()); + assert_eq::(5.0f32 as f64, 5.0f64); + assert_eq::( + /*0x1p-149*/ f32::from_bits(0x1) as f64, + /*0x1p-149*/ f64::from_bits(0x36a0000000000000), + ); + assert_eq::( + /*-0x1p-149*/ f32::from_bits(0x80000001) as f64, + /*-0x1p-149*/ f64::from_bits(0xb6a0000000000000), + ); + assert_eq::( + /*0x1.fffffep+127*/ f32::from_bits(0x7f7fffff) as f64, + /*0x1.fffffep+127*/ f64::from_bits(0x47efffffe0000000), + ); + assert_eq::( + /*-0x1.fffffep+127*/ (-f32::from_bits(0x7f7fffff)) as f64, + /*-0x1.fffffep+127*/ -f64::from_bits(0x47efffffe0000000), + ); + assert_eq::( + /*0x1p-119*/ f32::from_bits(0x4000000) as f64, + /*0x1p-119*/ f64::from_bits(0x3880000000000000), + ); + assert_eq::( + /*0x1.8f867ep+125*/ f32::from_bits(0x7e47c33f) as f64, + 6.6382536710104395e+37, + ); + assert_eq::(f32::INFINITY as f64, f64::INFINITY); + assert_eq::(f32::NEG_INFINITY as f64, f64::NEG_INFINITY); + + // f64 -> f32 + assert_eq::((0.0f64 as f32).to_bits(), 0.0f32.to_bits()); + assert_eq::(((-0.0f64) as f32).to_bits(), (-0.0f32).to_bits()); + assert_eq::(5.0f64 as f32, 5.0f32); + assert_eq::(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1) as f32, 0.0); + assert_eq::(/*-0x0.0000000000001p-1022*/ (-f64::from_bits(0x1)) as f32, -0.0); + assert_eq::( + /*0x1.fffffe0000000p-127*/ f64::from_bits(0x380fffffe0000000) as f32, + /*0x1p-149*/ f32::from_bits(0x800000), + ); + assert_eq::( + /*0x1.4eae4f7024c7p+108*/ f64::from_bits(0x46b4eae4f7024c70) as f32, + /*0x1.4eae5p+108*/ f32::from_bits(0x75a75728), + ); + assert_eq::(f64::MAX as f32, f32::INFINITY); + assert_eq::(f64::MIN as f32, f32::NEG_INFINITY); + assert_eq::(f64::INFINITY as f32, f32::INFINITY); + assert_eq::(f64::NEG_INFINITY as f32, f32::NEG_INFINITY); +} + +pub fn run() { + casts(); // from miri's tests + + common_fptoi_tests!(f* -> i8 i16 i32 i64 u8 u16 u32 u64); + fptoui_tests!(f* -> u8 u16 u32 u64); + // FIXME emscripten does not support i128 + #[cfg(not(target_os = "emscripten"))] + { + common_fptoi_tests!(f* -> i128 u128); + fptoui_tests!(f* -> u128); + } + + // The following tests cover edge cases for some integer types. + + // # u8 + test!(254., f* -> u8, 254); + test!(256., f* -> u8, 255); + + // # i8 + test!(-127., f* -> i8, -127); + test!(-129., f* -> i8, -128); + test!(126., f* -> i8, 126); + test!(128., f* -> i8, 127); + + // # i32 + // -2147483648. is i32::MIN (exactly) + test!(-2147483648., f* -> i32, i32::MIN); + // 2147483648. is i32::MAX rounded up + test!(2147483648., f32 -> i32, 2147483647); + // With 24 significand bits, floats with magnitude in [2^30 + 1, 2^31] are rounded to + // multiples of 2^7. Therefore, nextDown(round(i32::MAX)) is 2^31 - 128: + test!(2147483520., f32 -> i32, 2147483520); + // Similarly, nextUp(i32::MIN) is i32::MIN + 2^8 and nextDown(i32::MIN) is i32::MIN - 2^7 + test!(-2147483904., f* -> i32, i32::MIN); + test!(-2147483520., f* -> i32, -2147483520); + + // # u32 + // round(MAX) and nextUp(round(MAX)) + test!(4294967040., f* -> u32, 4294967040); + test!(4294967296., f* -> u32, 4294967295); + + // # u128 + #[cfg(not(target_os = "emscripten"))] + { + // float->int: + test!(f32::MAX, f32 -> u128, 0xffffff00000000000000000000000000); + // nextDown(f32::MAX) = 2^128 - 2 * 2^104 + const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.; + test!(SECOND_LARGEST_F32, f32 -> u128, 0xfffffe00000000000000000000000000); + } +} diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs new file mode 100644 index 000000000..cad059173 --- /dev/null +++ b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs @@ -0,0 +1,13 @@ +// run-pass +// only-wasm32 +// compile-flags: -Zmir-opt-level=0 -C target-feature=+nontrapping-fptoint + +#![feature(test, stmt_expr_attributes)] +#![deny(overflowing_literals)] + +#[path = "saturating-float-casts-impl.rs"] +mod implementation; + +pub fn main() { + implementation::run(); +} diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts.rs b/tests/ui/numbers-arithmetic/saturating-float-casts.rs new file mode 100644 index 000000000..cc248a9be --- /dev/null +++ b/tests/ui/numbers-arithmetic/saturating-float-casts.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags:-Zmir-opt-level=0 + +#![feature(test, stmt_expr_attributes)] +#![deny(overflowing_literals)] + +#[path = "saturating-float-casts-impl.rs"] +mod implementation; + +pub fn main() { + implementation::run(); +} diff --git a/tests/ui/numbers-arithmetic/shift-near-oflo.rs b/tests/ui/numbers-arithmetic/shift-near-oflo.rs new file mode 100644 index 000000000..55006a113 --- /dev/null +++ b/tests/ui/numbers-arithmetic/shift-near-oflo.rs @@ -0,0 +1,100 @@ +// run-pass +// compile-flags: -C debug-assertions + +// Check that we do *not* overflow on a number of edge cases. +// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs) + +fn main() { + test_left_shift(); + test_right_shift(); +} + +pub static mut HACK: i32 = 0; + +// Work around constant-evaluation +// The point of this test is to exercise the code generated for execution at runtime, +// `id` can never be flagged as a const fn by future aggressive analyses... +// due to the modification of the static +#[inline(never)] +fn id(x: T) -> T { + unsafe { HACK += 1; } + x +} + +fn test_left_shift() { + // negative rhs can panic, but values in [0,N-1] are okay for iN + + macro_rules! tests { + ($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { { + let x = (1 as $iN) << id(0); + assert_eq!(x, 1); + let x = (1 as $uN) << id(0); + assert_eq!(x, 1); + let x = (1 as $iN) << id($max_rhs); + assert_eq!(x, $expect_i); + let x = (1 as $uN) << id($max_rhs); + assert_eq!(x, $expect_u); + // high-order bits on LHS are silently discarded without panic. + let x = (3 as $iN) << id($max_rhs); + assert_eq!(x, $expect_i); + let x = (3 as $uN) << id($max_rhs); + assert_eq!(x, $expect_u); + } } + } + + let x = 1_i8 << id(0); + assert_eq!(x, 1); + let x = 1_u8 << id(0); + assert_eq!(x, 1); + let x = 1_i8 << id(7); + assert_eq!(x, i8::MIN); + let x = 1_u8 << id(7); + assert_eq!(x, 0x80); + // high-order bits on LHS are silently discarded without panic. + let x = 3_i8 << id(7); + assert_eq!(x, i8::MIN); + let x = 3_u8 << id(7); + assert_eq!(x, 0x80); + + // above is (approximately) expanded from: + tests!(i8, u8, 7, i8::MIN, 0x80_u8); + + tests!(i16, u16, 15, i16::MIN, 0x8000_u16); + tests!(i32, u32, 31, i32::MIN, 0x8000_0000_u32); + tests!(i64, u64, 63, i64::MIN, 0x8000_0000_0000_0000_u64); +} + +fn test_right_shift() { + // negative rhs can panic, but values in [0,N-1] are okay for iN + + macro_rules! tests { + ($iN:ty, $uN:ty, $max_rhs:expr, + $signbit_i:expr, $highbit_i:expr, $highbit_u:expr) => + { { + let x = (1 as $iN) >> id(0); + assert_eq!(x, 1); + let x = (1 as $uN) >> id(0); + assert_eq!(x, 1); + let x = ($highbit_i) >> id($max_rhs-1); + assert_eq!(x, 1); + let x = ($highbit_u) >> id($max_rhs); + assert_eq!(x, 1); + // sign-bit is carried by arithmetic right shift + let x = ($signbit_i) >> id($max_rhs); + assert_eq!(x, -1); + // low-order bits on LHS are silently discarded without panic. + let x = ($highbit_i + 1) >> id($max_rhs-1); + assert_eq!(x, 1); + let x = ($highbit_u + 1) >> id($max_rhs); + assert_eq!(x, 1); + let x = ($signbit_i + 1) >> id($max_rhs); + assert_eq!(x, -1); + } } + } + + tests!(i8, u8, 7, i8::MIN, 0x40_i8, 0x80_u8); + tests!(i16, u16, 15, i16::MIN, 0x4000_u16, 0x8000_u16); + tests!(i32, u32, 31, i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32); + tests!(i64, u64, 63, i64::MIN, + 0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64); +} diff --git a/tests/ui/numbers-arithmetic/shift-various-types.rs b/tests/ui/numbers-arithmetic/shift-various-types.rs new file mode 100644 index 000000000..473bda3d7 --- /dev/null +++ b/tests/ui/numbers-arithmetic/shift-various-types.rs @@ -0,0 +1,48 @@ +// run-pass +// Test that we can do shifts by any integral type. + + +struct Panolpy { + i8: i8, + i16: i16, + i32: i32, + i64: i64, + isize: isize, + + u8: u8, + u16: u16, + u32: u32, + u64: u64, + usize: usize, +} + +fn foo(p: &Panolpy) { + assert_eq!(22 >> p.i8, 11); + assert_eq!(22 >> p.i16, 11); + assert_eq!(22 >> p.i32, 11); + assert_eq!(22 >> p.i64, 11); + assert_eq!(22 >> p.isize, 11); + + assert_eq!(22 >> p.u8, 11); + assert_eq!(22 >> p.u16, 11); + assert_eq!(22 >> p.u32, 11); + assert_eq!(22 >> p.u64, 11); + assert_eq!(22 >> p.usize, 11); +} + +fn main() { + let p = Panolpy { + i8: 1, + i16: 1, + i32: 1, + i64: 1, + isize: 1, + + u8: 1, + u16: 1, + u32: 1, + u64: 1, + usize: 1, + }; + foo(&p) +} diff --git a/tests/ui/numbers-arithmetic/shift.rs b/tests/ui/numbers-arithmetic/shift.rs new file mode 100644 index 000000000..2fc77928e --- /dev/null +++ b/tests/ui/numbers-arithmetic/shift.rs @@ -0,0 +1,76 @@ +// run-pass +#![allow(non_upper_case_globals)] +#![allow(overflowing_literals)] + +// Testing shifts for various combinations of integers +// Issue #1570 + + +pub fn main() { + test_misc(); + test_expr(); + test_const(); +} + +fn test_misc() { + assert_eq!(1 << 1 << 1 << 1 << 1 << 1, 32); +} + +fn test_expr() { + let v10 = 10 as usize; + let v4 = 4 as u8; + let v2 = 2 as u8; + assert_eq!(v10 >> v2 as usize, v2 as usize); + assert_eq!(v10 << v4 as usize, 160 as usize); + + let v10 = 10 as u8; + let v4 = 4 as usize; + let v2 = 2 as usize; + assert_eq!(v10 >> v2 as usize, v2 as u8); + assert_eq!(v10 << v4 as usize, 160 as u8); + + let v10 = 10 as isize; + let v4 = 4 as i8; + let v2 = 2 as i8; + assert_eq!(v10 >> v2 as usize, v2 as isize); + assert_eq!(v10 << v4 as usize, 160 as isize); + + let v10 = 10 as i8; + let v4 = 4 as isize; + let v2 = 2 as isize; + assert_eq!(v10 >> v2 as usize, v2 as i8); + assert_eq!(v10 << v4 as usize, 160 as i8); + + let v10 = 10 as usize; + let v4 = 4 as isize; + let v2 = 2 as isize; + assert_eq!(v10 >> v2 as usize, v2 as usize); + assert_eq!(v10 << v4 as usize, 160 as usize); +} + +fn test_const() { + static r1_1: usize = 10_usize >> 2_usize; + static r2_1: usize = 10_usize << 4_usize; + assert_eq!(r1_1, 2 as usize); + assert_eq!(r2_1, 160 as usize); + + static r1_2: u8 = 10u8 >> 2_usize; + static r2_2: u8 = 10u8 << 4_usize; + assert_eq!(r1_2, 2 as u8); + assert_eq!(r2_2, 160 as u8); + + static r1_3: isize = 10 >> 2_usize; + static r2_3: isize = 10 << 4_usize; + assert_eq!(r1_3, 2 as isize); + assert_eq!(r2_3, 160 as isize); + + static r1_4: i8 = 10i8 >> 2_usize; + static r2_4: i8 = 10i8 << 4_usize; + assert_eq!(r1_4, 2 as i8); + assert_eq!(r2_4, 160 as i8); + + static r1_5: usize = 10_usize >> 2_usize; + static r2_5: usize = 10_usize << 4_usize; + assert_eq!(r1_5, 2 as usize); + assert_eq!(r2_5, 160 as usize); +} diff --git a/tests/ui/numbers-arithmetic/signed-shift-const-eval.rs b/tests/ui/numbers-arithmetic/signed-shift-const-eval.rs new file mode 100644 index 000000000..6d0462b46 --- /dev/null +++ b/tests/ui/numbers-arithmetic/signed-shift-const-eval.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(non_camel_case_types)] + + +enum test { thing = -5 >> 1_usize } +pub fn main() { + assert_eq!(test::thing as isize, -3); +} diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.fixed b/tests/ui/numbers-arithmetic/suggest-float-literal.fixed new file mode 100644 index 000000000..9278262a6 --- /dev/null +++ b/tests/ui/numbers-arithmetic/suggest-float-literal.fixed @@ -0,0 +1,37 @@ +// run-rustfix + +#![allow(dead_code)] + +fn add_integer_to_f32(x: f32) -> f32 { + x + 100.0 //~ ERROR cannot add `{integer}` to `f32` +} + +fn add_integer_to_f64(x: f64) -> f64 { + x + 100.0 //~ ERROR cannot add `{integer}` to `f64` +} + +fn subtract_integer_from_f32(x: f32) -> f32 { + x - 100.0 //~ ERROR cannot subtract `{integer}` from `f32` +} + +fn subtract_integer_from_f64(x: f64) -> f64 { + x - 100.0 //~ ERROR cannot subtract `{integer}` from `f64` +} + +fn multiply_f32_by_integer(x: f32) -> f32 { + x * 100.0 //~ ERROR cannot multiply `f32` by `{integer}` +} + +fn multiply_f64_by_integer(x: f64) -> f64 { + x * 100.0 //~ ERROR cannot multiply `f64` by `{integer}` +} + +fn divide_f32_by_integer(x: f32) -> f32 { + x / 100.0 //~ ERROR cannot divide `f32` by `{integer}` +} + +fn divide_f64_by_integer(x: f64) -> f64 { + x / 100.0 //~ ERROR cannot divide `f64` by `{integer}` +} + +fn main() {} diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.rs b/tests/ui/numbers-arithmetic/suggest-float-literal.rs new file mode 100644 index 000000000..59e67f8d3 --- /dev/null +++ b/tests/ui/numbers-arithmetic/suggest-float-literal.rs @@ -0,0 +1,37 @@ +// run-rustfix + +#![allow(dead_code)] + +fn add_integer_to_f32(x: f32) -> f32 { + x + 100 //~ ERROR cannot add `{integer}` to `f32` +} + +fn add_integer_to_f64(x: f64) -> f64 { + x + 100 //~ ERROR cannot add `{integer}` to `f64` +} + +fn subtract_integer_from_f32(x: f32) -> f32 { + x - 100 //~ ERROR cannot subtract `{integer}` from `f32` +} + +fn subtract_integer_from_f64(x: f64) -> f64 { + x - 100 //~ ERROR cannot subtract `{integer}` from `f64` +} + +fn multiply_f32_by_integer(x: f32) -> f32 { + x * 100 //~ ERROR cannot multiply `f32` by `{integer}` +} + +fn multiply_f64_by_integer(x: f64) -> f64 { + x * 100 //~ ERROR cannot multiply `f64` by `{integer}` +} + +fn divide_f32_by_integer(x: f32) -> f32 { + x / 100 //~ ERROR cannot divide `f32` by `{integer}` +} + +fn divide_f64_by_integer(x: f64) -> f64 { + x / 100 //~ ERROR cannot divide `f64` by `{integer}` +} + +fn main() {} diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr new file mode 100644 index 000000000..03779d356 --- /dev/null +++ b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -0,0 +1,139 @@ +error[E0277]: cannot add `{integer}` to `f32` + --> $DIR/suggest-float-literal.rs:6:7 + | +LL | x + 100 + | ^ no implementation for `f32 + {integer}` + | + = help: the trait `Add<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Add`: + <&'a f32 as Add> + <&f32 as Add<&f32>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x + 100.0 + | ++ + +error[E0277]: cannot add `{integer}` to `f64` + --> $DIR/suggest-float-literal.rs:10:7 + | +LL | x + 100 + | ^ no implementation for `f64 + {integer}` + | + = help: the trait `Add<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Add`: + <&'a f64 as Add> + <&f64 as Add<&f64>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x + 100.0 + | ++ + +error[E0277]: cannot subtract `{integer}` from `f32` + --> $DIR/suggest-float-literal.rs:14:7 + | +LL | x - 100 + | ^ no implementation for `f32 - {integer}` + | + = help: the trait `Sub<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Sub`: + <&'a f32 as Sub> + <&f32 as Sub<&f32>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x - 100.0 + | ++ + +error[E0277]: cannot subtract `{integer}` from `f64` + --> $DIR/suggest-float-literal.rs:18:7 + | +LL | x - 100 + | ^ no implementation for `f64 - {integer}` + | + = help: the trait `Sub<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Sub`: + <&'a f64 as Sub> + <&f64 as Sub<&f64>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x - 100.0 + | ++ + +error[E0277]: cannot multiply `f32` by `{integer}` + --> $DIR/suggest-float-literal.rs:22:7 + | +LL | x * 100 + | ^ no implementation for `f32 * {integer}` + | + = help: the trait `Mul<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Mul`: + <&'a f32 as Mul> + <&f32 as Mul<&f32>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x * 100.0 + | ++ + +error[E0277]: cannot multiply `f64` by `{integer}` + --> $DIR/suggest-float-literal.rs:26:7 + | +LL | x * 100 + | ^ no implementation for `f64 * {integer}` + | + = help: the trait `Mul<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Mul`: + <&'a f64 as Mul> + <&f64 as Mul<&f64>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x * 100.0 + | ++ + +error[E0277]: cannot divide `f32` by `{integer}` + --> $DIR/suggest-float-literal.rs:30:7 + | +LL | x / 100 + | ^ no implementation for `f32 / {integer}` + | + = help: the trait `Div<{integer}>` is not implemented for `f32` + = help: the following other types implement trait `Div`: + <&'a f32 as Div> + <&f32 as Div<&f32>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x / 100.0 + | ++ + +error[E0277]: cannot divide `f64` by `{integer}` + --> $DIR/suggest-float-literal.rs:34:7 + | +LL | x / 100 + | ^ no implementation for `f64 / {integer}` + | + = help: the trait `Div<{integer}>` is not implemented for `f64` + = help: the following other types implement trait `Div`: + <&'a f64 as Div> + <&f64 as Div<&f64>> + > + +help: consider using a floating-point literal by writing it with `.0` + | +LL | x / 100.0 + | ++ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/numbers-arithmetic/u128-as-f32.rs b/tests/ui/numbers-arithmetic/u128-as-f32.rs new file mode 100644 index 000000000..839ce932d --- /dev/null +++ b/tests/ui/numbers-arithmetic/u128-as-f32.rs @@ -0,0 +1,46 @@ +// run-pass + +#![feature(test)] +#![deny(overflowing_literals)] +extern crate test; + +use test::black_box; + +macro_rules! test { + ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ({ + { + const X: $src_ty = $val; + const Y: $dest_ty = X as $dest_ty; + assert_eq!(Y, $expected, + "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty)); + } + // black_box disables constant evaluation to test run-time conversions: + assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected, + "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty)); + }); +} + +pub fn main() { + // nextDown(f32::MAX) = 2^128 - 2 * 2^104 + const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.; + + // f32::MAX - 0.5 ULP and smaller should be rounded down + test!(0xfffffe00000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32); + test!(0xfffffe7fffffffffffffffffffffffff, u128 -> f32, SECOND_LARGEST_F32); + test!(0xfffffe80000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32); + // numbers within < 0.5 ULP of f32::MAX it should be rounded to f32::MAX + test!(0xfffffe80000000000000000000000001, u128 -> f32, f32::MAX); + test!(0xfffffeffffffffffffffffffffffffff, u128 -> f32, f32::MAX); + test!(0xffffff00000000000000000000000000, u128 -> f32, f32::MAX); + test!(0xffffff00000000000000000000000001, u128 -> f32, f32::MAX); + test!(0xffffff7fffffffffffffffffffffffff, u128 -> f32, f32::MAX); + // f32::MAX + 0.5 ULP and greater should be rounded to infinity + test!(0xffffff80000000000000000000000000, u128 -> f32, f32::INFINITY); + test!(0xffffff80000000f00000000000000000, u128 -> f32, f32::INFINITY); + test!(0xffffff87ffffffffffffffff00000001, u128 -> f32, f32::INFINITY); + + // u128->f64 should not be affected by the u128->f32 checks + test!(0xffffff80000000000000000000000000, u128 -> f64, + 340282356779733661637539395458142568448.0); + test!(u128::MAX, u128 -> f64, 340282366920938463463374607431768211455.0); +} diff --git a/tests/ui/numbers-arithmetic/u128.rs b/tests/ui/numbers-arithmetic/u128.rs new file mode 100644 index 000000000..d7e28055b --- /dev/null +++ b/tests/ui/numbers-arithmetic/u128.rs @@ -0,0 +1,119 @@ +// run-pass + +#![feature(test)] + +extern crate test; +use test::black_box as b; + +fn main() { + let x: u128 = 0xFFFF_FFFF_FFFF_FFFF__FFFF_FFFF_FFFF_FFFF; + assert_eq!(0, !x); + assert_eq!(0, !x); + let y: u128 = 0xFFFF_FFFF_FFFF_FFFF__FFFF_FFFF_FFFF_FFFE; + assert_eq!(!1, y); + assert_eq!(x, y | 1); + assert_eq!(0xFAFF_0000_FF8F_0000__FFFF_0000_FFFF_FFFE, + y & + 0xFAFF_0000_FF8F_0000__FFFF_0000_FFFF_FFFF); + let z: u128 = 0xABCD_EF; + assert_eq!(z * z, 0x734C_C2F2_A521); + assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41); + assert_eq!(z + z + z + z, 0x2AF3_7BC); + let k: u128 = 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210; + assert_eq!(k + k, 0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420); + assert_eq!(0, k - k); + assert_eq!(0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k - z); + assert_eq!(0x1000_0000_0000_0000_0000_0000_0000_000, + k - 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!(0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42); + assert_eq!(0, k % 42); + assert_eq!(15, z % 42); + assert_eq!(0x169D_A8020_CEC18, k % 0x3ACB_FE49_FF24_AC); + assert_eq!(0x91A2_B3C4_D5E6_F7, k >> 65); + assert_eq!(0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65); + assert!(k > z); + assert!(y > k); + assert!(y < x); + assert_eq!(x as u64, !0); + assert_eq!(z as u64, 0xABCD_EF); + assert_eq!(k as u64, 0xFEDC_BA98_7654_3210); + assert_eq!(k as i128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210); + assert_eq!((z as f64) as u128, z); + assert_eq!((z as f32) as u128, z); + assert_eq!((z as f64 * 16.0) as u128, z * 16); + assert_eq!((z as f32 * 16.0) as u128, z * 16); + let l :u128 = 432 << 100; + assert_eq!((l as f32) as u128, l); + assert_eq!((l as f64) as u128, l); + // formatting + let j: u128 = 1 << 67; + assert_eq!("147573952589676412928", format!("{}", j)); + assert_eq!("80000000000000000", format!("{:x}", j)); + assert_eq!("20000000000000000000000", format!("{:o}", j)); + assert_eq!("10000000000000000000000000000000000000000000000000000000000000000000", + format!("{:b}", j)); + assert_eq!("340282366920938463463374607431768211455", + format!("{}", u128::MAX)); + assert_eq!("147573952589676412928", format!("{:?}", j)); + // common traits + assert_eq!(x, b(x.clone())); + // overflow checks + assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521)); + assert_eq!((k).checked_mul(k), None); + let l: u128 = b(u128::MAX - 10); + let o: u128 = b(17); + assert_eq!(l.checked_add(b(11)), None); + assert_eq!(l.checked_sub(l), Some(0)); + assert_eq!(o.checked_sub(b(18)), None); + assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127)); + assert_eq!(o.checked_shl(b(128)), None); + + // Test cases for all udivmodti4 branches. + // case "0X/0X" + assert_eq!(b(0x69545bd57727c050_u128) / + b(0x3283527a3350d88c_u128), + 2u128); + // case "0X/KX" + assert_eq!(b(0x0_8003c9c50b473ae6_u128) / + b(0x1_283e8838c30fa8f4_u128), + 0u128); + // case "K0/K0" + assert_eq!(b(0xc43f42a207978720_u128 << 64) / + b(0x098e62b74c23cf1a_u128 << 64), + 20u128); + // case "KK/K0" for power-of-two D. + assert_eq!(b(0xa9008fb6c9d81e42_0e25730562a601c8_u128) / + b(1u128 << 120), + 169u128); + // case "KK/K0" with N >= D (https://github.com/rust-lang/rust/issues/41228). + assert_eq!(b(0xe4d26e59f0640328_06da5b06efe83a41_u128) / + b(0x330fcb030ea4447c_u128 << 64), + 4u128); + assert_eq!(b(3u128 << 64 | 1) / + b(3u128 << 64), + 1u128); + // case "KK/K0" with N < D. + assert_eq!(b(0x6655c9fb66ca2884_e2d1dfd470158c62_u128) / + b(0xb35b667cab7e355b_u128 << 64), + 0u128); + // case "KX/0K" for power-of-two D. + assert_eq!(b(0x3e49dd84feb2df59_7b2f97d93a253969_u128) / + b(1u128 << 4), + 0x03e49dd84feb2df5_97b2f97d93a25396_u128); + // case "KX/0K" in general. + assert_eq!(b(0x299692b3a1dae5bd_6162e6f489d2620e_u128) / + b(0x900b6f027571d6f7_u128), + 0x49e95f54b0442578_u128); + // case "KX/KK" with N >= D. + assert_eq!(b(0xc7b889180b67b07d_bc1a3c88783d35b5_u128) / + b(0x1d7e69f53160b9e2_60074771e852f244_u128), + 6u128); + // case "KX/KK" with N < D. + assert_eq!(b(0x679289ac23bb334f_36144401cf882172_u128) / + b(0x7b0b271b64865f05_f54a7b72746c062f_u128), + 0u128); + + // iter-arithmetic traits + assert_eq!(10u128, [1u128, 2, 3, 4].iter().sum()); + assert_eq!(24u128, [1u128, 2, 3, 4].iter().product()); +} diff --git a/tests/ui/numbers-arithmetic/u32-decr.rs b/tests/ui/numbers-arithmetic/u32-decr.rs new file mode 100644 index 000000000..d9e097818 --- /dev/null +++ b/tests/ui/numbers-arithmetic/u32-decr.rs @@ -0,0 +1,10 @@ +// run-pass + + + + +pub fn main() { + let mut word: u32 = 200000; + word = word - 1; + assert_eq!(word, 199999); +} diff --git a/tests/ui/numbers-arithmetic/u8-incr-decr.rs b/tests/ui/numbers-arithmetic/u8-incr-decr.rs new file mode 100644 index 000000000..b16ec011d --- /dev/null +++ b/tests/ui/numbers-arithmetic/u8-incr-decr.rs @@ -0,0 +1,19 @@ +// run-pass + + + + +// These constants were chosen because they aren't used anywhere +// in the rest of the generated code so they're easily grep-able. + +pub fn main() { + let mut x: u8 = 19; // 0x13 + + let mut y: u8 = 35; // 0x23 + + x = x + 7; // 0x7 + + y = y - 9; // 0x9 + + assert_eq!(x, y); +} diff --git a/tests/ui/numbers-arithmetic/u8-incr.rs b/tests/ui/numbers-arithmetic/u8-incr.rs new file mode 100644 index 000000000..5242acf5b --- /dev/null +++ b/tests/ui/numbers-arithmetic/u8-incr.rs @@ -0,0 +1,15 @@ +// run-pass + + + + +pub fn main() { + let mut x: u8 = 12; + let y: u8 = 12; + x = x + 1; + x = x - 1; + assert_eq!(x, y); + // x = 14; + // x = x + 1; + +} diff --git a/tests/ui/numbers-arithmetic/uint.rs b/tests/ui/numbers-arithmetic/uint.rs new file mode 100644 index 000000000..d219eae8f --- /dev/null +++ b/tests/ui/numbers-arithmetic/uint.rs @@ -0,0 +1,7 @@ +// run-pass + + + +// pretty-expanded FIXME #23616 + +pub fn main() { let _x: usize = 10 as usize; } diff --git a/tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs b/tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs new file mode 100644 index 000000000..a4d0a8494 --- /dev/null +++ b/tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs @@ -0,0 +1,23 @@ +// run-pass + +pub fn main() { + let a = 1; + let a_neg: i8 = -a; + println!("{}", a_neg); + + let b = 1; + let b_neg: i16 = -b; + println!("{}", b_neg); + + let c = 1; + let c_neg: i32 = -c; + println!("{}", c_neg); + + let d = 1; + let d_neg: i64 = -d; + println!("{}", d_neg); + + let e = 1; + let e_neg: isize = -e; + println!("{}", e_neg); +} diff --git a/tests/ui/numeric/const-scope.rs b/tests/ui/numeric/const-scope.rs new file mode 100644 index 000000000..053599a9b --- /dev/null +++ b/tests/ui/numeric/const-scope.rs @@ -0,0 +1,12 @@ +const C: i32 = 1i8; //~ ERROR mismatched types +const D: i8 = C; //~ ERROR mismatched types + +const fn foo() { + let c: i32 = 1i8; //~ ERROR mismatched types + let d: i8 = c; //~ ERROR mismatched types +} + +fn main() { + let c: i32 = 1i8; //~ ERROR mismatched types + let d: i8 = c; //~ ERROR mismatched types +} diff --git a/tests/ui/numeric/const-scope.stderr b/tests/ui/numeric/const-scope.stderr new file mode 100644 index 000000000..4e4bcdf23 --- /dev/null +++ b/tests/ui/numeric/const-scope.stderr @@ -0,0 +1,67 @@ +error[E0308]: mismatched types + --> $DIR/const-scope.rs:1:16 + | +LL | const C: i32 = 1i8; + | ^^^ expected `i32`, found `i8` + | +help: change the type of the numeric literal from `i8` to `i32` + | +LL | const C: i32 = 1i32; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:2:15 + | +LL | const D: i8 = C; + | ^ expected `i8`, found `i32` + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:5:18 + | +LL | let c: i32 = 1i8; + | --- ^^^ expected `i32`, found `i8` + | | + | expected due to this + | +help: change the type of the numeric literal from `i8` to `i32` + | +LL | let c: i32 = 1i32; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:6:17 + | +LL | let d: i8 = c; + | -- ^ expected `i8`, found `i32` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:10:18 + | +LL | let c: i32 = 1i8; + | --- ^^^ expected `i32`, found `i8` + | | + | expected due to this + | +help: change the type of the numeric literal from `i8` to `i32` + | +LL | let c: i32 = 1i32; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/const-scope.rs:11:17 + | +LL | let d: i8 = c; + | -- ^ expected `i8`, found `i32` + | | + | expected due to this + | +help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit + | +LL | let d: i8 = c.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/integer-literal-suffix-inference.rs b/tests/ui/numeric/integer-literal-suffix-inference.rs new file mode 100644 index 000000000..c320f2bb7 --- /dev/null +++ b/tests/ui/numeric/integer-literal-suffix-inference.rs @@ -0,0 +1,220 @@ +fn main() { + + // the smallest positive values that need these types + let a8: i8 = 8; + let a16: i16 = 128; + let a32: i32 = 32_768; + let a64: i64 = 2_147_483_648; + + // the smallest negative values that need these types + let c8: i8 = -9; + let c16: i16 = -129; + let c32: i32 = -32_769; + let c64: i64 = -2_147_483_649; + + fn id_i8(n: i8) -> i8 { n } + fn id_i16(n: i16) -> i16 { n } + fn id_i32(n: i32) -> i32 { n } + fn id_i64(n: i64) -> i64 { n } + fn id_isize(n: isize) -> isize { n } + + // the smallest values that need these types + let b8: u8 = 16; + let b16: u16 = 256; + let b32: u32 = 65_536; + let b64: u64 = 4_294_967_296; + + fn id_u8(n: u8) -> u8 { n } + fn id_u16(n: u16) -> u16 { n } + fn id_u32(n: u32) -> u32 { n } + fn id_u64(n: u64) -> u64 { n } + fn id_usize(n: usize) -> usize { n } + + // Values for testing *size + let asize: isize = 1; + let bsize: usize = 3; + + id_i8(a8); // ok + id_i8(a16); + //~^ ERROR mismatched types + //~| expected `i8`, found `i16` + id_i8(a32); + //~^ ERROR mismatched types + //~| expected `i8`, found `i32` + id_i8(a64); + //~^ ERROR mismatched types + //~| expected `i8`, found `i64` + id_i8(asize); + //~^ ERROR mismatched types + //~| expected `i8`, found `isize` + + id_i16(a8); + //~^ ERROR mismatched types + //~| expected `i16`, found `i8` + id_i16(a16); // ok + id_i16(a32); + //~^ ERROR mismatched types + //~| expected `i16`, found `i32` + id_i16(a64); + //~^ ERROR mismatched types + //~| expected `i16`, found `i64` + id_i16(asize); + //~^ ERROR mismatched types + //~| expected `i16`, found `isize` + + id_i32(a8); + //~^ ERROR mismatched types + //~| expected `i32`, found `i8` + id_i32(a16); + //~^ ERROR mismatched types + //~| expected `i32`, found `i16` + id_i32(a32); // ok + id_i32(a64); + //~^ ERROR mismatched types + //~| expected `i32`, found `i64` + id_i32(asize); + //~^ ERROR mismatched types + //~| expected `i32`, found `isize` + + id_i64(a8); + //~^ ERROR mismatched types + //~| expected `i64`, found `i8` + id_i64(a16); + //~^ ERROR mismatched types + //~| expected `i64`, found `i16` + id_i64(a32); + //~^ ERROR mismatched types + //~| expected `i64`, found `i32` + id_i64(a64); // ok + id_i64(asize); + //~^ ERROR mismatched types + //~| expected `i64`, found `isize` + + id_isize(a8); + //~^ ERROR mismatched types + //~| expected `isize`, found `i8` + id_isize(a16); + //~^ ERROR mismatched types + //~| expected `isize`, found `i16` + id_isize(a32); + //~^ ERROR mismatched types + //~| expected `isize`, found `i32` + id_isize(a64); + //~^ ERROR mismatched types + //~| expected `isize`, found `i64` + id_isize(asize); //ok + + id_i8(c8); // ok + id_i8(c16); + //~^ ERROR mismatched types + //~| expected `i8`, found `i16` + id_i8(c32); + //~^ ERROR mismatched types + //~| expected `i8`, found `i32` + id_i8(c64); + //~^ ERROR mismatched types + //~| expected `i8`, found `i64` + + id_i16(c8); + //~^ ERROR mismatched types + //~| expected `i16`, found `i8` + id_i16(c16); // ok + id_i16(c32); + //~^ ERROR mismatched types + //~| expected `i16`, found `i32` + id_i16(c64); + //~^ ERROR mismatched types + //~| expected `i16`, found `i64` + + id_i32(c8); + //~^ ERROR mismatched types + //~| expected `i32`, found `i8` + id_i32(c16); + //~^ ERROR mismatched types + //~| expected `i32`, found `i16` + id_i32(c32); // ok + id_i32(c64); + //~^ ERROR mismatched types + //~| expected `i32`, found `i64` + + id_i64(a8); + //~^ ERROR mismatched types + //~| expected `i64`, found `i8` + id_i64(a16); + //~^ ERROR mismatched types + //~| expected `i64`, found `i16` + id_i64(a32); + //~^ ERROR mismatched types + //~| expected `i64`, found `i32` + id_i64(a64); // ok + + id_u8(b8); // ok + id_u8(b16); + //~^ ERROR mismatched types + //~| expected `u8`, found `u16` + id_u8(b32); + //~^ ERROR mismatched types + //~| expected `u8`, found `u32` + id_u8(b64); + //~^ ERROR mismatched types + //~| expected `u8`, found `u64` + id_u8(bsize); + //~^ ERROR mismatched types + //~| expected `u8`, found `usize` + + id_u16(b8); + //~^ ERROR mismatched types + //~| expected `u16`, found `u8` + id_u16(b16); // ok + id_u16(b32); + //~^ ERROR mismatched types + //~| expected `u16`, found `u32` + id_u16(b64); + //~^ ERROR mismatched types + //~| expected `u16`, found `u64` + id_u16(bsize); + //~^ ERROR mismatched types + //~| expected `u16`, found `usize` + + id_u32(b8); + //~^ ERROR mismatched types + //~| expected `u32`, found `u8` + id_u32(b16); + //~^ ERROR mismatched types + //~| expected `u32`, found `u16` + id_u32(b32); // ok + id_u32(b64); + //~^ ERROR mismatched types + //~| expected `u32`, found `u64` + id_u32(bsize); + //~^ ERROR mismatched types + //~| expected `u32`, found `usize` + + id_u64(b8); + //~^ ERROR mismatched types + //~| expected `u64`, found `u8` + id_u64(b16); + //~^ ERROR mismatched types + //~| expected `u64`, found `u16` + id_u64(b32); + //~^ ERROR mismatched types + //~| expected `u64`, found `u32` + id_u64(b64); // ok + id_u64(bsize); + //~^ ERROR mismatched types + //~| expected `u64`, found `usize` + + id_usize(b8); + //~^ ERROR mismatched types + //~| expected `usize`, found `u8` + id_usize(b16); + //~^ ERROR mismatched types + //~| expected `usize`, found `u16` + id_usize(b32); + //~^ ERROR mismatched types + //~| expected `usize`, found `u32` + id_usize(b64); + //~^ ERROR mismatched types + //~| expected `usize`, found `u64` + id_usize(bsize); //ok +} diff --git a/tests/ui/numeric/integer-literal-suffix-inference.stderr b/tests/ui/numeric/integer-literal-suffix-inference.stderr new file mode 100644 index 000000000..5045f584c --- /dev/null +++ b/tests/ui/numeric/integer-literal-suffix-inference.stderr @@ -0,0 +1,939 @@ +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:38:11 + | +LL | id_i8(a16); + | ----- ^^^ expected `i8`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(a16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:41:11 + | +LL | id_i8(a32); + | ----- ^^^ expected `i8`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(a32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:44:11 + | +LL | id_i8(a64); + | ----- ^^^ expected `i8`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(a64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:47:11 + | +LL | id_i8(asize); + | ----- ^^^^^ expected `i8`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(asize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:51:12 + | +LL | id_i16(a8); + | ------ ^^ expected `i16`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `i8` to an `i16` + | +LL | id_i16(a8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:55:12 + | +LL | id_i16(a32); + | ------ ^^^ expected `i16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit + | +LL | id_i16(a32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:58:12 + | +LL | id_i16(a64); + | ------ ^^^ expected `i16`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit + | +LL | id_i16(a64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:61:12 + | +LL | id_i16(asize); + | ------ ^^^^^ expected `i16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit + | +LL | id_i16(asize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:65:12 + | +LL | id_i32(a8); + | ------ ^^ expected `i32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `i8` to an `i32` + | +LL | id_i32(a8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:68:12 + | +LL | id_i32(a16); + | ------ ^^^ expected `i32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `i16` to an `i32` + | +LL | id_i32(a16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:72:12 + | +LL | id_i32(a64); + | ------ ^^^ expected `i32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit + | +LL | id_i32(a64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:75:12 + | +LL | id_i32(asize); + | ------ ^^^^^ expected `i32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit + | +LL | id_i32(asize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:79:12 + | +LL | id_i64(a8); + | ------ ^^ expected `i64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `i8` to an `i64` + | +LL | id_i64(a8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:82:12 + | +LL | id_i64(a16); + | ------ ^^^ expected `i64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `i16` to an `i64` + | +LL | id_i64(a16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:85:12 + | +LL | id_i64(a32); + | ------ ^^^ expected `i64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `i32` to an `i64` + | +LL | id_i64(a32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:89:12 + | +LL | id_i64(asize); + | ------ ^^^^^ expected `i64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit + | +LL | id_i64(asize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:93:14 + | +LL | id_isize(a8); + | -------- ^^ expected `isize`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:19:8 + | +LL | fn id_isize(n: isize) -> isize { n } + | ^^^^^^^^ -------- +help: you can convert an `i8` to an `isize` + | +LL | id_isize(a8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:96:14 + | +LL | id_isize(a16); + | -------- ^^^ expected `isize`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:19:8 + | +LL | fn id_isize(n: isize) -> isize { n } + | ^^^^^^^^ -------- +help: you can convert an `i16` to an `isize` + | +LL | id_isize(a16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:99:14 + | +LL | id_isize(a32); + | -------- ^^^ expected `isize`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:19:8 + | +LL | fn id_isize(n: isize) -> isize { n } + | ^^^^^^^^ -------- +help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit + | +LL | id_isize(a32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:102:14 + | +LL | id_isize(a64); + | -------- ^^^ expected `isize`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:19:8 + | +LL | fn id_isize(n: isize) -> isize { n } + | ^^^^^^^^ -------- +help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit + | +LL | id_isize(a64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:108:11 + | +LL | id_i8(c16); + | ----- ^^^ expected `i8`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(c16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:111:11 + | +LL | id_i8(c32); + | ----- ^^^ expected `i8`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(c32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:114:11 + | +LL | id_i8(c64); + | ----- ^^^ expected `i8`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:15:8 + | +LL | fn id_i8(n: i8) -> i8 { n } + | ^^^^^ ----- +help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit + | +LL | id_i8(c64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:118:12 + | +LL | id_i16(c8); + | ------ ^^ expected `i16`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `i8` to an `i16` + | +LL | id_i16(c8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:122:12 + | +LL | id_i16(c32); + | ------ ^^^ expected `i16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit + | +LL | id_i16(c32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:125:12 + | +LL | id_i16(c64); + | ------ ^^^ expected `i16`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:16:8 + | +LL | fn id_i16(n: i16) -> i16 { n } + | ^^^^^^ ------ +help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit + | +LL | id_i16(c64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:129:12 + | +LL | id_i32(c8); + | ------ ^^ expected `i32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `i8` to an `i32` + | +LL | id_i32(c8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:132:12 + | +LL | id_i32(c16); + | ------ ^^^ expected `i32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `i16` to an `i32` + | +LL | id_i32(c16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:136:12 + | +LL | id_i32(c64); + | ------ ^^^ expected `i32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:17:8 + | +LL | fn id_i32(n: i32) -> i32 { n } + | ^^^^^^ ------ +help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit + | +LL | id_i32(c64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:140:12 + | +LL | id_i64(a8); + | ------ ^^ expected `i64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `i8` to an `i64` + | +LL | id_i64(a8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:143:12 + | +LL | id_i64(a16); + | ------ ^^^ expected `i64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `i16` to an `i64` + | +LL | id_i64(a16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:146:12 + | +LL | id_i64(a32); + | ------ ^^^ expected `i64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:18:8 + | +LL | fn id_i64(n: i64) -> i64 { n } + | ^^^^^^ ------ +help: you can convert an `i32` to an `i64` + | +LL | id_i64(a32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:152:11 + | +LL | id_u8(b16); + | ----- ^^^ expected `u8`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:27:8 + | +LL | fn id_u8(n: u8) -> u8 { n } + | ^^^^^ ----- +help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit + | +LL | id_u8(b16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:155:11 + | +LL | id_u8(b32); + | ----- ^^^ expected `u8`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:27:8 + | +LL | fn id_u8(n: u8) -> u8 { n } + | ^^^^^ ----- +help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit + | +LL | id_u8(b32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:158:11 + | +LL | id_u8(b64); + | ----- ^^^ expected `u8`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:27:8 + | +LL | fn id_u8(n: u8) -> u8 { n } + | ^^^^^ ----- +help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit + | +LL | id_u8(b64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:161:11 + | +LL | id_u8(bsize); + | ----- ^^^^^ expected `u8`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:27:8 + | +LL | fn id_u8(n: u8) -> u8 { n } + | ^^^^^ ----- +help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit + | +LL | id_u8(bsize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:165:12 + | +LL | id_u16(b8); + | ------ ^^ expected `u16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:28:8 + | +LL | fn id_u16(n: u16) -> u16 { n } + | ^^^^^^ ------ +help: you can convert a `u8` to a `u16` + | +LL | id_u16(b8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:169:12 + | +LL | id_u16(b32); + | ------ ^^^ expected `u16`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:28:8 + | +LL | fn id_u16(n: u16) -> u16 { n } + | ^^^^^^ ------ +help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit + | +LL | id_u16(b32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:172:12 + | +LL | id_u16(b64); + | ------ ^^^ expected `u16`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:28:8 + | +LL | fn id_u16(n: u16) -> u16 { n } + | ^^^^^^ ------ +help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit + | +LL | id_u16(b64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:175:12 + | +LL | id_u16(bsize); + | ------ ^^^^^ expected `u16`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:28:8 + | +LL | fn id_u16(n: u16) -> u16 { n } + | ^^^^^^ ------ +help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit + | +LL | id_u16(bsize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:179:12 + | +LL | id_u32(b8); + | ------ ^^ expected `u32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:29:8 + | +LL | fn id_u32(n: u32) -> u32 { n } + | ^^^^^^ ------ +help: you can convert a `u8` to a `u32` + | +LL | id_u32(b8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:182:12 + | +LL | id_u32(b16); + | ------ ^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:29:8 + | +LL | fn id_u32(n: u32) -> u32 { n } + | ^^^^^^ ------ +help: you can convert a `u16` to a `u32` + | +LL | id_u32(b16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:186:12 + | +LL | id_u32(b64); + | ------ ^^^ expected `u32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:29:8 + | +LL | fn id_u32(n: u32) -> u32 { n } + | ^^^^^^ ------ +help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit + | +LL | id_u32(b64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:189:12 + | +LL | id_u32(bsize); + | ------ ^^^^^ expected `u32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:29:8 + | +LL | fn id_u32(n: u32) -> u32 { n } + | ^^^^^^ ------ +help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit + | +LL | id_u32(bsize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:193:12 + | +LL | id_u64(b8); + | ------ ^^ expected `u64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:30:8 + | +LL | fn id_u64(n: u64) -> u64 { n } + | ^^^^^^ ------ +help: you can convert a `u8` to a `u64` + | +LL | id_u64(b8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:196:12 + | +LL | id_u64(b16); + | ------ ^^^ expected `u64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:30:8 + | +LL | fn id_u64(n: u64) -> u64 { n } + | ^^^^^^ ------ +help: you can convert a `u16` to a `u64` + | +LL | id_u64(b16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:199:12 + | +LL | id_u64(b32); + | ------ ^^^ expected `u64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:30:8 + | +LL | fn id_u64(n: u64) -> u64 { n } + | ^^^^^^ ------ +help: you can convert a `u32` to a `u64` + | +LL | id_u64(b32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:203:12 + | +LL | id_u64(bsize); + | ------ ^^^^^ expected `u64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:30:8 + | +LL | fn id_u64(n: u64) -> u64 { n } + | ^^^^^^ ------ +help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit + | +LL | id_u64(bsize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:207:14 + | +LL | id_usize(b8); + | -------- ^^ expected `usize`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:31:8 + | +LL | fn id_usize(n: usize) -> usize { n } + | ^^^^^^^^ -------- +help: you can convert a `u8` to a `usize` + | +LL | id_usize(b8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:210:14 + | +LL | id_usize(b16); + | -------- ^^^ expected `usize`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:31:8 + | +LL | fn id_usize(n: usize) -> usize { n } + | ^^^^^^^^ -------- +help: you can convert a `u16` to a `usize` + | +LL | id_usize(b16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:213:14 + | +LL | id_usize(b32); + | -------- ^^^ expected `usize`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:31:8 + | +LL | fn id_usize(n: usize) -> usize { n } + | ^^^^^^^^ -------- +help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit + | +LL | id_usize(b32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/integer-literal-suffix-inference.rs:216:14 + | +LL | id_usize(b64); + | -------- ^^^ expected `usize`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/integer-literal-suffix-inference.rs:31:8 + | +LL | fn id_usize(n: usize) -> usize { n } + | ^^^^^^^^ -------- +help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit + | +LL | id_usize(b64.try_into().unwrap()); + | ++++++++++++++++++++ + +error: aborting due to 52 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/len.rs b/tests/ui/numeric/len.rs new file mode 100644 index 000000000..a72540988 --- /dev/null +++ b/tests/ui/numeric/len.rs @@ -0,0 +1,8 @@ +fn main() { + let array = [1, 2, 3]; + test(array.len()); //~ ERROR mismatched types +} + +fn test(length: u32) { + println!("{}", length); +} diff --git a/tests/ui/numeric/len.stderr b/tests/ui/numeric/len.stderr new file mode 100644 index 000000000..55a61b5e4 --- /dev/null +++ b/tests/ui/numeric/len.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/len.rs:3:10 + | +LL | test(array.len()); + | ---- ^^^^^^^^^^^ expected `u32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/len.rs:6:4 + | +LL | fn test(length: u32) { + | ^^^^ ----------- +help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit + | +LL | test(array.len().try_into().unwrap()); + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-cast-2.rs b/tests/ui/numeric/numeric-cast-2.rs new file mode 100644 index 000000000..ad2de5d2b --- /dev/null +++ b/tests/ui/numeric/numeric-cast-2.rs @@ -0,0 +1,11 @@ +fn foo() -> i32 { + 4 +} +fn main() { + let x: u16 = foo(); + //~^ ERROR mismatched types + let y: i64 = x + x; + //~^ ERROR mismatched types + let z: i32 = x + x; + //~^ ERROR mismatched types +} diff --git a/tests/ui/numeric/numeric-cast-2.stderr b/tests/ui/numeric/numeric-cast-2.stderr new file mode 100644 index 000000000..a7b342739 --- /dev/null +++ b/tests/ui/numeric/numeric-cast-2.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/numeric-cast-2.rs:5:18 + | +LL | let x: u16 = foo(); + | --- ^^^^^ expected `u16`, found `i32` + | | + | expected due to this + | +help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit + | +LL | let x: u16 = foo().try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-2.rs:7:18 + | +LL | let y: i64 = x + x; + | --- ^^^^^ expected `i64`, found `u16` + | | + | expected due to this + | +help: you can convert a `u16` to an `i64` + | +LL | let y: i64 = (x + x).into(); + | + ++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-2.rs:9:18 + | +LL | let z: i32 = x + x; + | --- ^^^^^ expected `i32`, found `u16` + | | + | expected due to this + | +help: you can convert a `u16` to an `i32` + | +LL | let z: i32 = (x + x).into(); + | + ++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-cast-binop.fixed b/tests/ui/numeric/numeric-cast-binop.fixed new file mode 100644 index 000000000..edb085e71 --- /dev/null +++ b/tests/ui/numeric/numeric-cast-binop.fixed @@ -0,0 +1,320 @@ +// run-rustfix + +// The `try_into` suggestion doesn't include this, but we do suggest it after applying it +use std::convert::TryInto; + +#[allow(unused_must_use)] +fn main() { + let x_usize: usize = 1; + let x_u128: u128 = 2; + let x_u64: u64 = 3; + let x_u32: u32 = 4; + let x_u16: u16 = 5; + let x_u8: u8 = 6; + let x_isize: isize = 7; + let x_i64: i64 = 8; + let x_i32: i32 = 9; + let x_i16: i16 = 10; + let x_i8: i8 = 11; + let x_i128: i128 = 12; + + /* u<->u */ + { + u16::from(x_u8) > x_u16; + //~^ ERROR mismatched types + u32::from(x_u8) > x_u32; + //~^ ERROR mismatched types + u64::from(x_u8) > x_u64; + //~^ ERROR mismatched types + u128::from(x_u8) > x_u128; + //~^ ERROR mismatched types + usize::from(x_u8) > x_usize; + //~^ ERROR mismatched types + + x_u16 > x_u8.into(); + //~^ ERROR mismatched types + u32::from(x_u16) > x_u32; + //~^ ERROR mismatched types + u64::from(x_u16) > x_u64; + //~^ ERROR mismatched types + u128::from(x_u16) > x_u128; + //~^ ERROR mismatched types + usize::from(x_u16) > x_usize; + //~^ ERROR mismatched types + + x_u32 > x_u8.into(); + //~^ ERROR mismatched types + x_u32 > x_u16.into(); + //~^ ERROR mismatched types + u64::from(x_u32) > x_u64; + //~^ ERROR mismatched types + u128::from(x_u32) > x_u128; + //~^ ERROR mismatched types + x_u32 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_u64 > x_u8.into(); + //~^ ERROR mismatched types + x_u64 > x_u16.into(); + //~^ ERROR mismatched types + x_u64 > x_u32.into(); + //~^ ERROR mismatched types + u128::from(x_u64) > x_u128; + //~^ ERROR mismatched types + x_u64 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_u128 > x_u8.into(); + //~^ ERROR mismatched types + x_u128 > x_u16.into(); + //~^ ERROR mismatched types + x_u128 > x_u32.into(); + //~^ ERROR mismatched types + x_u128 > x_u64.into(); + //~^ ERROR mismatched types + x_u128 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_usize > x_u8.into(); + //~^ ERROR mismatched types + x_usize > x_u16.into(); + //~^ ERROR mismatched types + x_usize > x_u32.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_u64.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + } + + /* i<->i */ + { + i16::from(x_i8) > x_i16; + //~^ ERROR mismatched types + i32::from(x_i8) > x_i32; + //~^ ERROR mismatched types + i64::from(x_i8) > x_i64; + //~^ ERROR mismatched types + i128::from(x_i8) > x_i128; + //~^ ERROR mismatched types + isize::from(x_i8) > x_isize; + //~^ ERROR mismatched types + + x_i16 > x_i8.into(); + //~^ ERROR mismatched types + i32::from(x_i16) > x_i32; + //~^ ERROR mismatched types + i64::from(x_i16) > x_i64; + //~^ ERROR mismatched types + i128::from(x_i16) > x_i128; + //~^ ERROR mismatched types + isize::from(x_i16) > x_isize; + //~^ ERROR mismatched types + + x_i32 > x_i8.into(); + //~^ ERROR mismatched types + x_i32 > x_i16.into(); + //~^ ERROR mismatched types + i64::from(x_i32) > x_i64; + //~^ ERROR mismatched types + i128::from(x_i32) > x_i128; + //~^ ERROR mismatched types + x_i32 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_i64 > x_i8.into(); + //~^ ERROR mismatched types + x_i64 > x_i16.into(); + //~^ ERROR mismatched types + x_i64 > x_i32.into(); + //~^ ERROR mismatched types + i128::from(x_i64) > x_i128; + //~^ ERROR mismatched types + x_i64 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_i128 > x_i8.into(); + //~^ ERROR mismatched types + x_i128 > x_i16.into(); + //~^ ERROR mismatched types + x_i128 > x_i32.into(); + //~^ ERROR mismatched types + x_i128 > x_i64.into(); + //~^ ERROR mismatched types + x_i128 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_isize > x_i8.into(); + //~^ ERROR mismatched types + x_isize > x_i16.into(); + //~^ ERROR mismatched types + x_isize > x_i32.try_into().unwrap(); + //~^ ERROR mismatched types + x_isize > x_i64.try_into().unwrap(); + //~^ ERROR mismatched types + x_isize > x_i128.try_into().unwrap(); + //~^ ERROR mismatched types + } + + /* u<->i */ + { + x_u8 > x_i8.try_into().unwrap(); + //~^ ERROR mismatched types + i16::from(x_u8) > x_i16; + //~^ ERROR mismatched types + i32::from(x_u8) > x_i32; + //~^ ERROR mismatched types + i64::from(x_u8) > x_i64; + //~^ ERROR mismatched types + i128::from(x_u8) > x_i128; + //~^ ERROR mismatched types + isize::from(x_u8) > x_isize; + //~^ ERROR mismatched types + + x_u16 > x_i8.try_into().unwrap(); + //~^ ERROR mismatched types + x_u16 > x_i16.try_into().unwrap(); + //~^ ERROR mismatched types + i32::from(x_u16) > x_i32; + //~^ ERROR mismatched types + i64::from(x_u16) > x_i64; + //~^ ERROR mismatched types + i128::from(x_u16) > x_i128; + //~^ ERROR mismatched types + x_u16 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_u32 > x_i8.try_into().unwrap(); + //~^ ERROR mismatched types + x_u32 > x_i16.try_into().unwrap(); + //~^ ERROR mismatched types + x_u32 > x_i32.try_into().unwrap(); + //~^ ERROR mismatched types + i64::from(x_u32) > x_i64; + //~^ ERROR mismatched types + i128::from(x_u32) > x_i128; + //~^ ERROR mismatched types + x_u32 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_u64 > x_i8.try_into().unwrap(); + //~^ ERROR mismatched types + x_u64 > x_i16.try_into().unwrap(); + //~^ ERROR mismatched types + x_u64 > x_i32.try_into().unwrap(); + //~^ ERROR mismatched types + x_u64 > x_i64.try_into().unwrap(); + //~^ ERROR mismatched types + i128::from(x_u64) > x_i128; + //~^ ERROR mismatched types + x_u64 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_u128 > x_i8.try_into().unwrap(); + //~^ ERROR mismatched types + x_u128 > x_i16.try_into().unwrap(); + //~^ ERROR mismatched types + x_u128 > x_i32.try_into().unwrap(); + //~^ ERROR mismatched types + x_u128 > x_i64.try_into().unwrap(); + //~^ ERROR mismatched types + x_u128 > x_i128.try_into().unwrap(); + //~^ ERROR mismatched types + x_u128 > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_usize > x_i8.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_i16.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_i32.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_i64.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_i128.try_into().unwrap(); + //~^ ERROR mismatched types + x_usize > x_isize.try_into().unwrap(); + //~^ ERROR mismatched types + } + + /* i<->u */ + { + x_i8 > x_u8.try_into().unwrap(); + //~^ ERROR mismatched types + x_i8 > x_u16.try_into().unwrap(); + //~^ ERROR mismatched types + x_i8 > x_u32.try_into().unwrap(); + //~^ ERROR mismatched types + x_i8 > x_u64.try_into().unwrap(); + //~^ ERROR mismatched types + x_i8 > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + x_i8 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_i16 > x_u8.into(); + //~^ ERROR mismatched types + x_i16 > x_u16.try_into().unwrap(); + //~^ ERROR mismatched types + x_i16 > x_u32.try_into().unwrap(); + //~^ ERROR mismatched types + x_i16 > x_u64.try_into().unwrap(); + //~^ ERROR mismatched types + x_i16 > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + x_i16 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_i32 > x_u8.into(); + //~^ ERROR mismatched types + x_i32 > x_u16.into(); + //~^ ERROR mismatched types + x_i32 > x_u32.try_into().unwrap(); + //~^ ERROR mismatched types + x_i32 > x_u64.try_into().unwrap(); + //~^ ERROR mismatched types + x_i32 > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + x_i32 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_i64 > x_u8.into(); + //~^ ERROR mismatched types + x_i64 > x_u16.into(); + //~^ ERROR mismatched types + x_i64 > x_u32.into(); + //~^ ERROR mismatched types + x_i64 > x_u64.try_into().unwrap(); + //~^ ERROR mismatched types + x_i64 > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + x_i64 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_i128 > x_u8.into(); + //~^ ERROR mismatched types + x_i128 > x_u16.into(); + //~^ ERROR mismatched types + x_i128 > x_u32.into(); + //~^ ERROR mismatched types + x_i128 > x_u64.into(); + //~^ ERROR mismatched types + x_i128 > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + x_i128 > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + + x_isize > x_u8.into(); + //~^ ERROR mismatched types + x_isize > x_u16.try_into().unwrap(); + //~^ ERROR mismatched types + x_isize > x_u32.try_into().unwrap(); + //~^ ERROR mismatched types + x_isize > x_u64.try_into().unwrap(); + //~^ ERROR mismatched types + x_isize > x_u128.try_into().unwrap(); + //~^ ERROR mismatched types + x_isize > x_usize.try_into().unwrap(); + //~^ ERROR mismatched types + } +} diff --git a/tests/ui/numeric/numeric-cast-binop.rs b/tests/ui/numeric/numeric-cast-binop.rs new file mode 100644 index 000000000..c1ed8de8a --- /dev/null +++ b/tests/ui/numeric/numeric-cast-binop.rs @@ -0,0 +1,320 @@ +// run-rustfix + +// The `try_into` suggestion doesn't include this, but we do suggest it after applying it +use std::convert::TryInto; + +#[allow(unused_must_use)] +fn main() { + let x_usize: usize = 1; + let x_u128: u128 = 2; + let x_u64: u64 = 3; + let x_u32: u32 = 4; + let x_u16: u16 = 5; + let x_u8: u8 = 6; + let x_isize: isize = 7; + let x_i64: i64 = 8; + let x_i32: i32 = 9; + let x_i16: i16 = 10; + let x_i8: i8 = 11; + let x_i128: i128 = 12; + + /* u<->u */ + { + x_u8 > x_u16; + //~^ ERROR mismatched types + x_u8 > x_u32; + //~^ ERROR mismatched types + x_u8 > x_u64; + //~^ ERROR mismatched types + x_u8 > x_u128; + //~^ ERROR mismatched types + x_u8 > x_usize; + //~^ ERROR mismatched types + + x_u16 > x_u8; + //~^ ERROR mismatched types + x_u16 > x_u32; + //~^ ERROR mismatched types + x_u16 > x_u64; + //~^ ERROR mismatched types + x_u16 > x_u128; + //~^ ERROR mismatched types + x_u16 > x_usize; + //~^ ERROR mismatched types + + x_u32 > x_u8; + //~^ ERROR mismatched types + x_u32 > x_u16; + //~^ ERROR mismatched types + x_u32 > x_u64; + //~^ ERROR mismatched types + x_u32 > x_u128; + //~^ ERROR mismatched types + x_u32 > x_usize; + //~^ ERROR mismatched types + + x_u64 > x_u8; + //~^ ERROR mismatched types + x_u64 > x_u16; + //~^ ERROR mismatched types + x_u64 > x_u32; + //~^ ERROR mismatched types + x_u64 > x_u128; + //~^ ERROR mismatched types + x_u64 > x_usize; + //~^ ERROR mismatched types + + x_u128 > x_u8; + //~^ ERROR mismatched types + x_u128 > x_u16; + //~^ ERROR mismatched types + x_u128 > x_u32; + //~^ ERROR mismatched types + x_u128 > x_u64; + //~^ ERROR mismatched types + x_u128 > x_usize; + //~^ ERROR mismatched types + + x_usize > x_u8; + //~^ ERROR mismatched types + x_usize > x_u16; + //~^ ERROR mismatched types + x_usize > x_u32; + //~^ ERROR mismatched types + x_usize > x_u64; + //~^ ERROR mismatched types + x_usize > x_u128; + //~^ ERROR mismatched types + } + + /* i<->i */ + { + x_i8 > x_i16; + //~^ ERROR mismatched types + x_i8 > x_i32; + //~^ ERROR mismatched types + x_i8 > x_i64; + //~^ ERROR mismatched types + x_i8 > x_i128; + //~^ ERROR mismatched types + x_i8 > x_isize; + //~^ ERROR mismatched types + + x_i16 > x_i8; + //~^ ERROR mismatched types + x_i16 > x_i32; + //~^ ERROR mismatched types + x_i16 > x_i64; + //~^ ERROR mismatched types + x_i16 > x_i128; + //~^ ERROR mismatched types + x_i16 > x_isize; + //~^ ERROR mismatched types + + x_i32 > x_i8; + //~^ ERROR mismatched types + x_i32 > x_i16; + //~^ ERROR mismatched types + x_i32 > x_i64; + //~^ ERROR mismatched types + x_i32 > x_i128; + //~^ ERROR mismatched types + x_i32 > x_isize; + //~^ ERROR mismatched types + + x_i64 > x_i8; + //~^ ERROR mismatched types + x_i64 > x_i16; + //~^ ERROR mismatched types + x_i64 > x_i32; + //~^ ERROR mismatched types + x_i64 > x_i128; + //~^ ERROR mismatched types + x_i64 > x_isize; + //~^ ERROR mismatched types + + x_i128 > x_i8; + //~^ ERROR mismatched types + x_i128 > x_i16; + //~^ ERROR mismatched types + x_i128 > x_i32; + //~^ ERROR mismatched types + x_i128 > x_i64; + //~^ ERROR mismatched types + x_i128 > x_isize; + //~^ ERROR mismatched types + + x_isize > x_i8; + //~^ ERROR mismatched types + x_isize > x_i16; + //~^ ERROR mismatched types + x_isize > x_i32; + //~^ ERROR mismatched types + x_isize > x_i64; + //~^ ERROR mismatched types + x_isize > x_i128; + //~^ ERROR mismatched types + } + + /* u<->i */ + { + x_u8 > x_i8; + //~^ ERROR mismatched types + x_u8 > x_i16; + //~^ ERROR mismatched types + x_u8 > x_i32; + //~^ ERROR mismatched types + x_u8 > x_i64; + //~^ ERROR mismatched types + x_u8 > x_i128; + //~^ ERROR mismatched types + x_u8 > x_isize; + //~^ ERROR mismatched types + + x_u16 > x_i8; + //~^ ERROR mismatched types + x_u16 > x_i16; + //~^ ERROR mismatched types + x_u16 > x_i32; + //~^ ERROR mismatched types + x_u16 > x_i64; + //~^ ERROR mismatched types + x_u16 > x_i128; + //~^ ERROR mismatched types + x_u16 > x_isize; + //~^ ERROR mismatched types + + x_u32 > x_i8; + //~^ ERROR mismatched types + x_u32 > x_i16; + //~^ ERROR mismatched types + x_u32 > x_i32; + //~^ ERROR mismatched types + x_u32 > x_i64; + //~^ ERROR mismatched types + x_u32 > x_i128; + //~^ ERROR mismatched types + x_u32 > x_isize; + //~^ ERROR mismatched types + + x_u64 > x_i8; + //~^ ERROR mismatched types + x_u64 > x_i16; + //~^ ERROR mismatched types + x_u64 > x_i32; + //~^ ERROR mismatched types + x_u64 > x_i64; + //~^ ERROR mismatched types + x_u64 > x_i128; + //~^ ERROR mismatched types + x_u64 > x_isize; + //~^ ERROR mismatched types + + x_u128 > x_i8; + //~^ ERROR mismatched types + x_u128 > x_i16; + //~^ ERROR mismatched types + x_u128 > x_i32; + //~^ ERROR mismatched types + x_u128 > x_i64; + //~^ ERROR mismatched types + x_u128 > x_i128; + //~^ ERROR mismatched types + x_u128 > x_isize; + //~^ ERROR mismatched types + + x_usize > x_i8; + //~^ ERROR mismatched types + x_usize > x_i16; + //~^ ERROR mismatched types + x_usize > x_i32; + //~^ ERROR mismatched types + x_usize > x_i64; + //~^ ERROR mismatched types + x_usize > x_i128; + //~^ ERROR mismatched types + x_usize > x_isize; + //~^ ERROR mismatched types + } + + /* i<->u */ + { + x_i8 > x_u8; + //~^ ERROR mismatched types + x_i8 > x_u16; + //~^ ERROR mismatched types + x_i8 > x_u32; + //~^ ERROR mismatched types + x_i8 > x_u64; + //~^ ERROR mismatched types + x_i8 > x_u128; + //~^ ERROR mismatched types + x_i8 > x_usize; + //~^ ERROR mismatched types + + x_i16 > x_u8; + //~^ ERROR mismatched types + x_i16 > x_u16; + //~^ ERROR mismatched types + x_i16 > x_u32; + //~^ ERROR mismatched types + x_i16 > x_u64; + //~^ ERROR mismatched types + x_i16 > x_u128; + //~^ ERROR mismatched types + x_i16 > x_usize; + //~^ ERROR mismatched types + + x_i32 > x_u8; + //~^ ERROR mismatched types + x_i32 > x_u16; + //~^ ERROR mismatched types + x_i32 > x_u32; + //~^ ERROR mismatched types + x_i32 > x_u64; + //~^ ERROR mismatched types + x_i32 > x_u128; + //~^ ERROR mismatched types + x_i32 > x_usize; + //~^ ERROR mismatched types + + x_i64 > x_u8; + //~^ ERROR mismatched types + x_i64 > x_u16; + //~^ ERROR mismatched types + x_i64 > x_u32; + //~^ ERROR mismatched types + x_i64 > x_u64; + //~^ ERROR mismatched types + x_i64 > x_u128; + //~^ ERROR mismatched types + x_i64 > x_usize; + //~^ ERROR mismatched types + + x_i128 > x_u8; + //~^ ERROR mismatched types + x_i128 > x_u16; + //~^ ERROR mismatched types + x_i128 > x_u32; + //~^ ERROR mismatched types + x_i128 > x_u64; + //~^ ERROR mismatched types + x_i128 > x_u128; + //~^ ERROR mismatched types + x_i128 > x_usize; + //~^ ERROR mismatched types + + x_isize > x_u8; + //~^ ERROR mismatched types + x_isize > x_u16; + //~^ ERROR mismatched types + x_isize > x_u32; + //~^ ERROR mismatched types + x_isize > x_u64; + //~^ ERROR mismatched types + x_isize > x_u128; + //~^ ERROR mismatched types + x_isize > x_usize; + //~^ ERROR mismatched types + } +} diff --git a/tests/ui/numeric/numeric-cast-binop.stderr b/tests/ui/numeric/numeric-cast-binop.stderr new file mode 100644 index 000000000..d5213e3f5 --- /dev/null +++ b/tests/ui/numeric/numeric-cast-binop.stderr @@ -0,0 +1,1719 @@ +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:23:16 + | +LL | x_u8 > x_u16; + | ---- ^^^^^ expected `u8`, found `u16` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16` + | +LL | u16::from(x_u8) > x_u16; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:25:16 + | +LL | x_u8 > x_u32; + | ---- ^^^^^ expected `u8`, found `u32` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32` + | +LL | u32::from(x_u8) > x_u32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:27:16 + | +LL | x_u8 > x_u64; + | ---- ^^^^^ expected `u8`, found `u64` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64` + | +LL | u64::from(x_u8) > x_u64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:29:16 + | +LL | x_u8 > x_u128; + | ---- ^^^^^^ expected `u8`, found `u128` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128` + | +LL | u128::from(x_u8) > x_u128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:31:16 + | +LL | x_u8 > x_usize; + | ---- ^^^^^^^ expected `u8`, found `usize` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize` + | +LL | usize::from(x_u8) > x_usize; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:34:17 + | +LL | x_u16 > x_u8; + | ----- ^^^^ expected `u16`, found `u8` + | | + | expected because this is `u16` + | +help: you can convert a `u8` to a `u16` + | +LL | x_u16 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:36:17 + | +LL | x_u16 > x_u32; + | ----- ^^^^^ expected `u16`, found `u32` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32` + | +LL | u32::from(x_u16) > x_u32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:38:17 + | +LL | x_u16 > x_u64; + | ----- ^^^^^ expected `u16`, found `u64` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64` + | +LL | u64::from(x_u16) > x_u64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:40:17 + | +LL | x_u16 > x_u128; + | ----- ^^^^^^ expected `u16`, found `u128` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128` + | +LL | u128::from(x_u16) > x_u128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:42:17 + | +LL | x_u16 > x_usize; + | ----- ^^^^^^^ expected `u16`, found `usize` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize` + | +LL | usize::from(x_u16) > x_usize; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:45:17 + | +LL | x_u32 > x_u8; + | ----- ^^^^ expected `u32`, found `u8` + | | + | expected because this is `u32` + | +help: you can convert a `u8` to a `u32` + | +LL | x_u32 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:47:17 + | +LL | x_u32 > x_u16; + | ----- ^^^^^ expected `u32`, found `u16` + | | + | expected because this is `u32` + | +help: you can convert a `u16` to a `u32` + | +LL | x_u32 > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:49:17 + | +LL | x_u32 > x_u64; + | ----- ^^^^^ expected `u32`, found `u64` + | | + | expected because this is `u32` + | +help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64` + | +LL | u64::from(x_u32) > x_u64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:51:17 + | +LL | x_u32 > x_u128; + | ----- ^^^^^^ expected `u32`, found `u128` + | | + | expected because this is `u32` + | +help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128` + | +LL | u128::from(x_u32) > x_u128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:53:17 + | +LL | x_u32 > x_usize; + | ----- ^^^^^^^ expected `u32`, found `usize` + | | + | expected because this is `u32` + | +help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit + | +LL | x_u32 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:56:17 + | +LL | x_u64 > x_u8; + | ----- ^^^^ expected `u64`, found `u8` + | | + | expected because this is `u64` + | +help: you can convert a `u8` to a `u64` + | +LL | x_u64 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:58:17 + | +LL | x_u64 > x_u16; + | ----- ^^^^^ expected `u64`, found `u16` + | | + | expected because this is `u64` + | +help: you can convert a `u16` to a `u64` + | +LL | x_u64 > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:60:17 + | +LL | x_u64 > x_u32; + | ----- ^^^^^ expected `u64`, found `u32` + | | + | expected because this is `u64` + | +help: you can convert a `u32` to a `u64` + | +LL | x_u64 > x_u32.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:62:17 + | +LL | x_u64 > x_u128; + | ----- ^^^^^^ expected `u64`, found `u128` + | | + | expected because this is `u64` + | +help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128` + | +LL | u128::from(x_u64) > x_u128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:64:17 + | +LL | x_u64 > x_usize; + | ----- ^^^^^^^ expected `u64`, found `usize` + | | + | expected because this is `u64` + | +help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit + | +LL | x_u64 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:67:18 + | +LL | x_u128 > x_u8; + | ------ ^^^^ expected `u128`, found `u8` + | | + | expected because this is `u128` + | +help: you can convert a `u8` to a `u128` + | +LL | x_u128 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:69:18 + | +LL | x_u128 > x_u16; + | ------ ^^^^^ expected `u128`, found `u16` + | | + | expected because this is `u128` + | +help: you can convert a `u16` to a `u128` + | +LL | x_u128 > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:71:18 + | +LL | x_u128 > x_u32; + | ------ ^^^^^ expected `u128`, found `u32` + | | + | expected because this is `u128` + | +help: you can convert a `u32` to a `u128` + | +LL | x_u128 > x_u32.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:73:18 + | +LL | x_u128 > x_u64; + | ------ ^^^^^ expected `u128`, found `u64` + | | + | expected because this is `u128` + | +help: you can convert a `u64` to a `u128` + | +LL | x_u128 > x_u64.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:75:18 + | +LL | x_u128 > x_usize; + | ------ ^^^^^^^ expected `u128`, found `usize` + | | + | expected because this is `u128` + | +help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:78:19 + | +LL | x_usize > x_u8; + | ------- ^^^^ expected `usize`, found `u8` + | | + | expected because this is `usize` + | +help: you can convert a `u8` to a `usize` + | +LL | x_usize > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:80:19 + | +LL | x_usize > x_u16; + | ------- ^^^^^ expected `usize`, found `u16` + | | + | expected because this is `usize` + | +help: you can convert a `u16` to a `usize` + | +LL | x_usize > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:82:19 + | +LL | x_usize > x_u32; + | ------- ^^^^^ expected `usize`, found `u32` + | | + | expected because this is `usize` + | +help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_u32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:84:19 + | +LL | x_usize > x_u64; + | ------- ^^^^^ expected `usize`, found `u64` + | | + | expected because this is `usize` + | +help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_u64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:86:19 + | +LL | x_usize > x_u128; + | ------- ^^^^^^ expected `usize`, found `u128` + | | + | expected because this is `usize` + | +help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:92:16 + | +LL | x_i8 > x_i16; + | ---- ^^^^^ expected `i8`, found `i16` + | | + | expected because this is `i8` + | +help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16` + | +LL | i16::from(x_i8) > x_i16; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:94:16 + | +LL | x_i8 > x_i32; + | ---- ^^^^^ expected `i8`, found `i32` + | | + | expected because this is `i8` + | +help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32` + | +LL | i32::from(x_i8) > x_i32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:96:16 + | +LL | x_i8 > x_i64; + | ---- ^^^^^ expected `i8`, found `i64` + | | + | expected because this is `i8` + | +help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64` + | +LL | i64::from(x_i8) > x_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:98:16 + | +LL | x_i8 > x_i128; + | ---- ^^^^^^ expected `i8`, found `i128` + | | + | expected because this is `i8` + | +help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_i8) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:100:16 + | +LL | x_i8 > x_isize; + | ---- ^^^^^^^ expected `i8`, found `isize` + | | + | expected because this is `i8` + | +help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize` + | +LL | isize::from(x_i8) > x_isize; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:103:17 + | +LL | x_i16 > x_i8; + | ----- ^^^^ expected `i16`, found `i8` + | | + | expected because this is `i16` + | +help: you can convert an `i8` to an `i16` + | +LL | x_i16 > x_i8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:105:17 + | +LL | x_i16 > x_i32; + | ----- ^^^^^ expected `i16`, found `i32` + | | + | expected because this is `i16` + | +help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32` + | +LL | i32::from(x_i16) > x_i32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:107:17 + | +LL | x_i16 > x_i64; + | ----- ^^^^^ expected `i16`, found `i64` + | | + | expected because this is `i16` + | +help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64` + | +LL | i64::from(x_i16) > x_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:109:17 + | +LL | x_i16 > x_i128; + | ----- ^^^^^^ expected `i16`, found `i128` + | | + | expected because this is `i16` + | +help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_i16) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:111:17 + | +LL | x_i16 > x_isize; + | ----- ^^^^^^^ expected `i16`, found `isize` + | | + | expected because this is `i16` + | +help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize` + | +LL | isize::from(x_i16) > x_isize; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:114:17 + | +LL | x_i32 > x_i8; + | ----- ^^^^ expected `i32`, found `i8` + | | + | expected because this is `i32` + | +help: you can convert an `i8` to an `i32` + | +LL | x_i32 > x_i8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:116:17 + | +LL | x_i32 > x_i16; + | ----- ^^^^^ expected `i32`, found `i16` + | | + | expected because this is `i32` + | +help: you can convert an `i16` to an `i32` + | +LL | x_i32 > x_i16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:118:17 + | +LL | x_i32 > x_i64; + | ----- ^^^^^ expected `i32`, found `i64` + | | + | expected because this is `i32` + | +help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64` + | +LL | i64::from(x_i32) > x_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:120:17 + | +LL | x_i32 > x_i128; + | ----- ^^^^^^ expected `i32`, found `i128` + | | + | expected because this is `i32` + | +help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_i32) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:122:17 + | +LL | x_i32 > x_isize; + | ----- ^^^^^^^ expected `i32`, found `isize` + | | + | expected because this is `i32` + | +help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit + | +LL | x_i32 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:125:17 + | +LL | x_i64 > x_i8; + | ----- ^^^^ expected `i64`, found `i8` + | | + | expected because this is `i64` + | +help: you can convert an `i8` to an `i64` + | +LL | x_i64 > x_i8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:127:17 + | +LL | x_i64 > x_i16; + | ----- ^^^^^ expected `i64`, found `i16` + | | + | expected because this is `i64` + | +help: you can convert an `i16` to an `i64` + | +LL | x_i64 > x_i16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:129:17 + | +LL | x_i64 > x_i32; + | ----- ^^^^^ expected `i64`, found `i32` + | | + | expected because this is `i64` + | +help: you can convert an `i32` to an `i64` + | +LL | x_i64 > x_i32.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:131:17 + | +LL | x_i64 > x_i128; + | ----- ^^^^^^ expected `i64`, found `i128` + | | + | expected because this is `i64` + | +help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_i64) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:133:17 + | +LL | x_i64 > x_isize; + | ----- ^^^^^^^ expected `i64`, found `isize` + | | + | expected because this is `i64` + | +help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit + | +LL | x_i64 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:136:18 + | +LL | x_i128 > x_i8; + | ------ ^^^^ expected `i128`, found `i8` + | | + | expected because this is `i128` + | +help: you can convert an `i8` to an `i128` + | +LL | x_i128 > x_i8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:138:18 + | +LL | x_i128 > x_i16; + | ------ ^^^^^ expected `i128`, found `i16` + | | + | expected because this is `i128` + | +help: you can convert an `i16` to an `i128` + | +LL | x_i128 > x_i16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:140:18 + | +LL | x_i128 > x_i32; + | ------ ^^^^^ expected `i128`, found `i32` + | | + | expected because this is `i128` + | +help: you can convert an `i32` to an `i128` + | +LL | x_i128 > x_i32.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:142:18 + | +LL | x_i128 > x_i64; + | ------ ^^^^^ expected `i128`, found `i64` + | | + | expected because this is `i128` + | +help: you can convert an `i64` to an `i128` + | +LL | x_i128 > x_i64.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:144:18 + | +LL | x_i128 > x_isize; + | ------ ^^^^^^^ expected `i128`, found `isize` + | | + | expected because this is `i128` + | +help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit + | +LL | x_i128 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:147:19 + | +LL | x_isize > x_i8; + | ------- ^^^^ expected `isize`, found `i8` + | | + | expected because this is `isize` + | +help: you can convert an `i8` to an `isize` + | +LL | x_isize > x_i8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:149:19 + | +LL | x_isize > x_i16; + | ------- ^^^^^ expected `isize`, found `i16` + | | + | expected because this is `isize` + | +help: you can convert an `i16` to an `isize` + | +LL | x_isize > x_i16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:151:19 + | +LL | x_isize > x_i32; + | ------- ^^^^^ expected `isize`, found `i32` + | | + | expected because this is `isize` + | +help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_i32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:153:19 + | +LL | x_isize > x_i64; + | ------- ^^^^^ expected `isize`, found `i64` + | | + | expected because this is `isize` + | +help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_i64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:155:19 + | +LL | x_isize > x_i128; + | ------- ^^^^^^ expected `isize`, found `i128` + | | + | expected because this is `isize` + | +help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_i128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:161:16 + | +LL | x_u8 > x_i8; + | ---- ^^^^ expected `u8`, found `i8` + | | + | expected because this is `u8` + | +help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit + | +LL | x_u8 > x_i8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:163:16 + | +LL | x_u8 > x_i16; + | ---- ^^^^^ expected `u8`, found `i16` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16` + | +LL | i16::from(x_u8) > x_i16; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:165:16 + | +LL | x_u8 > x_i32; + | ---- ^^^^^ expected `u8`, found `i32` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32` + | +LL | i32::from(x_u8) > x_i32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:167:16 + | +LL | x_u8 > x_i64; + | ---- ^^^^^ expected `u8`, found `i64` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64` + | +LL | i64::from(x_u8) > x_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:169:16 + | +LL | x_u8 > x_i128; + | ---- ^^^^^^ expected `u8`, found `i128` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_u8) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:171:16 + | +LL | x_u8 > x_isize; + | ---- ^^^^^^^ expected `u8`, found `isize` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize` + | +LL | isize::from(x_u8) > x_isize; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:174:17 + | +LL | x_u16 > x_i8; + | ----- ^^^^ expected `u16`, found `i8` + | | + | expected because this is `u16` + | +help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit + | +LL | x_u16 > x_i8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:176:17 + | +LL | x_u16 > x_i16; + | ----- ^^^^^ expected `u16`, found `i16` + | | + | expected because this is `u16` + | +help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit + | +LL | x_u16 > x_i16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:178:17 + | +LL | x_u16 > x_i32; + | ----- ^^^^^ expected `u16`, found `i32` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32` + | +LL | i32::from(x_u16) > x_i32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:180:17 + | +LL | x_u16 > x_i64; + | ----- ^^^^^ expected `u16`, found `i64` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64` + | +LL | i64::from(x_u16) > x_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:182:17 + | +LL | x_u16 > x_i128; + | ----- ^^^^^^ expected `u16`, found `i128` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_u16) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:184:17 + | +LL | x_u16 > x_isize; + | ----- ^^^^^^^ expected `u16`, found `isize` + | | + | expected because this is `u16` + | +help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit + | +LL | x_u16 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:187:17 + | +LL | x_u32 > x_i8; + | ----- ^^^^ expected `u32`, found `i8` + | | + | expected because this is `u32` + | +help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit + | +LL | x_u32 > x_i8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:189:17 + | +LL | x_u32 > x_i16; + | ----- ^^^^^ expected `u32`, found `i16` + | | + | expected because this is `u32` + | +help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit + | +LL | x_u32 > x_i16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:191:17 + | +LL | x_u32 > x_i32; + | ----- ^^^^^ expected `u32`, found `i32` + | | + | expected because this is `u32` + | +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | x_u32 > x_i32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:193:17 + | +LL | x_u32 > x_i64; + | ----- ^^^^^ expected `u32`, found `i64` + | | + | expected because this is `u32` + | +help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64` + | +LL | i64::from(x_u32) > x_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:195:17 + | +LL | x_u32 > x_i128; + | ----- ^^^^^^ expected `u32`, found `i128` + | | + | expected because this is `u32` + | +help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_u32) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:197:17 + | +LL | x_u32 > x_isize; + | ----- ^^^^^^^ expected `u32`, found `isize` + | | + | expected because this is `u32` + | +help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit + | +LL | x_u32 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:200:17 + | +LL | x_u64 > x_i8; + | ----- ^^^^ expected `u64`, found `i8` + | | + | expected because this is `u64` + | +help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit + | +LL | x_u64 > x_i8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:202:17 + | +LL | x_u64 > x_i16; + | ----- ^^^^^ expected `u64`, found `i16` + | | + | expected because this is `u64` + | +help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit + | +LL | x_u64 > x_i16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:204:17 + | +LL | x_u64 > x_i32; + | ----- ^^^^^ expected `u64`, found `i32` + | | + | expected because this is `u64` + | +help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit + | +LL | x_u64 > x_i32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:206:17 + | +LL | x_u64 > x_i64; + | ----- ^^^^^ expected `u64`, found `i64` + | | + | expected because this is `u64` + | +help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit + | +LL | x_u64 > x_i64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:208:17 + | +LL | x_u64 > x_i128; + | ----- ^^^^^^ expected `u64`, found `i128` + | | + | expected because this is `u64` + | +help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128` + | +LL | i128::from(x_u64) > x_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:210:17 + | +LL | x_u64 > x_isize; + | ----- ^^^^^^^ expected `u64`, found `isize` + | | + | expected because this is `u64` + | +help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit + | +LL | x_u64 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:213:18 + | +LL | x_u128 > x_i8; + | ------ ^^^^ expected `u128`, found `i8` + | | + | expected because this is `u128` + | +help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_i8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:215:18 + | +LL | x_u128 > x_i16; + | ------ ^^^^^ expected `u128`, found `i16` + | | + | expected because this is `u128` + | +help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_i16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:217:18 + | +LL | x_u128 > x_i32; + | ------ ^^^^^ expected `u128`, found `i32` + | | + | expected because this is `u128` + | +help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_i32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:219:18 + | +LL | x_u128 > x_i64; + | ------ ^^^^^ expected `u128`, found `i64` + | | + | expected because this is `u128` + | +help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_i64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:221:18 + | +LL | x_u128 > x_i128; + | ------ ^^^^^^ expected `u128`, found `i128` + | | + | expected because this is `u128` + | +help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_i128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:223:18 + | +LL | x_u128 > x_isize; + | ------ ^^^^^^^ expected `u128`, found `isize` + | | + | expected because this is `u128` + | +help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit + | +LL | x_u128 > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:226:19 + | +LL | x_usize > x_i8; + | ------- ^^^^ expected `usize`, found `i8` + | | + | expected because this is `usize` + | +help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_i8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:228:19 + | +LL | x_usize > x_i16; + | ------- ^^^^^ expected `usize`, found `i16` + | | + | expected because this is `usize` + | +help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_i16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:230:19 + | +LL | x_usize > x_i32; + | ------- ^^^^^ expected `usize`, found `i32` + | | + | expected because this is `usize` + | +help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_i32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:232:19 + | +LL | x_usize > x_i64; + | ------- ^^^^^ expected `usize`, found `i64` + | | + | expected because this is `usize` + | +help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_i64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:234:19 + | +LL | x_usize > x_i128; + | ------- ^^^^^^ expected `usize`, found `i128` + | | + | expected because this is `usize` + | +help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_i128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:236:19 + | +LL | x_usize > x_isize; + | ------- ^^^^^^^ expected `usize`, found `isize` + | | + | expected because this is `usize` + | +help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit + | +LL | x_usize > x_isize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:242:16 + | +LL | x_i8 > x_u8; + | ---- ^^^^ expected `i8`, found `u8` + | | + | expected because this is `i8` + | +help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit + | +LL | x_i8 > x_u8.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:244:16 + | +LL | x_i8 > x_u16; + | ---- ^^^^^ expected `i8`, found `u16` + | | + | expected because this is `i8` + | +help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit + | +LL | x_i8 > x_u16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:246:16 + | +LL | x_i8 > x_u32; + | ---- ^^^^^ expected `i8`, found `u32` + | | + | expected because this is `i8` + | +help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit + | +LL | x_i8 > x_u32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:248:16 + | +LL | x_i8 > x_u64; + | ---- ^^^^^ expected `i8`, found `u64` + | | + | expected because this is `i8` + | +help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit + | +LL | x_i8 > x_u64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:250:16 + | +LL | x_i8 > x_u128; + | ---- ^^^^^^ expected `i8`, found `u128` + | | + | expected because this is `i8` + | +help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit + | +LL | x_i8 > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:252:16 + | +LL | x_i8 > x_usize; + | ---- ^^^^^^^ expected `i8`, found `usize` + | | + | expected because this is `i8` + | +help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit + | +LL | x_i8 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:255:17 + | +LL | x_i16 > x_u8; + | ----- ^^^^ expected `i16`, found `u8` + | | + | expected because this is `i16` + | +help: you can convert a `u8` to an `i16` + | +LL | x_i16 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:257:17 + | +LL | x_i16 > x_u16; + | ----- ^^^^^ expected `i16`, found `u16` + | | + | expected because this is `i16` + | +help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit + | +LL | x_i16 > x_u16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:259:17 + | +LL | x_i16 > x_u32; + | ----- ^^^^^ expected `i16`, found `u32` + | | + | expected because this is `i16` + | +help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit + | +LL | x_i16 > x_u32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:261:17 + | +LL | x_i16 > x_u64; + | ----- ^^^^^ expected `i16`, found `u64` + | | + | expected because this is `i16` + | +help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit + | +LL | x_i16 > x_u64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:263:17 + | +LL | x_i16 > x_u128; + | ----- ^^^^^^ expected `i16`, found `u128` + | | + | expected because this is `i16` + | +help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit + | +LL | x_i16 > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:265:17 + | +LL | x_i16 > x_usize; + | ----- ^^^^^^^ expected `i16`, found `usize` + | | + | expected because this is `i16` + | +help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit + | +LL | x_i16 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:268:17 + | +LL | x_i32 > x_u8; + | ----- ^^^^ expected `i32`, found `u8` + | | + | expected because this is `i32` + | +help: you can convert a `u8` to an `i32` + | +LL | x_i32 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:270:17 + | +LL | x_i32 > x_u16; + | ----- ^^^^^ expected `i32`, found `u16` + | | + | expected because this is `i32` + | +help: you can convert a `u16` to an `i32` + | +LL | x_i32 > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:272:17 + | +LL | x_i32 > x_u32; + | ----- ^^^^^ expected `i32`, found `u32` + | | + | expected because this is `i32` + | +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | x_i32 > x_u32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:274:17 + | +LL | x_i32 > x_u64; + | ----- ^^^^^ expected `i32`, found `u64` + | | + | expected because this is `i32` + | +help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit + | +LL | x_i32 > x_u64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:276:17 + | +LL | x_i32 > x_u128; + | ----- ^^^^^^ expected `i32`, found `u128` + | | + | expected because this is `i32` + | +help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit + | +LL | x_i32 > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:278:17 + | +LL | x_i32 > x_usize; + | ----- ^^^^^^^ expected `i32`, found `usize` + | | + | expected because this is `i32` + | +help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit + | +LL | x_i32 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:281:17 + | +LL | x_i64 > x_u8; + | ----- ^^^^ expected `i64`, found `u8` + | | + | expected because this is `i64` + | +help: you can convert a `u8` to an `i64` + | +LL | x_i64 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:283:17 + | +LL | x_i64 > x_u16; + | ----- ^^^^^ expected `i64`, found `u16` + | | + | expected because this is `i64` + | +help: you can convert a `u16` to an `i64` + | +LL | x_i64 > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:285:17 + | +LL | x_i64 > x_u32; + | ----- ^^^^^ expected `i64`, found `u32` + | | + | expected because this is `i64` + | +help: you can convert a `u32` to an `i64` + | +LL | x_i64 > x_u32.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:287:17 + | +LL | x_i64 > x_u64; + | ----- ^^^^^ expected `i64`, found `u64` + | | + | expected because this is `i64` + | +help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit + | +LL | x_i64 > x_u64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:289:17 + | +LL | x_i64 > x_u128; + | ----- ^^^^^^ expected `i64`, found `u128` + | | + | expected because this is `i64` + | +help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit + | +LL | x_i64 > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:291:17 + | +LL | x_i64 > x_usize; + | ----- ^^^^^^^ expected `i64`, found `usize` + | | + | expected because this is `i64` + | +help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit + | +LL | x_i64 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:294:18 + | +LL | x_i128 > x_u8; + | ------ ^^^^ expected `i128`, found `u8` + | | + | expected because this is `i128` + | +help: you can convert a `u8` to an `i128` + | +LL | x_i128 > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:296:18 + | +LL | x_i128 > x_u16; + | ------ ^^^^^ expected `i128`, found `u16` + | | + | expected because this is `i128` + | +help: you can convert a `u16` to an `i128` + | +LL | x_i128 > x_u16.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:298:18 + | +LL | x_i128 > x_u32; + | ------ ^^^^^ expected `i128`, found `u32` + | | + | expected because this is `i128` + | +help: you can convert a `u32` to an `i128` + | +LL | x_i128 > x_u32.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:300:18 + | +LL | x_i128 > x_u64; + | ------ ^^^^^ expected `i128`, found `u64` + | | + | expected because this is `i128` + | +help: you can convert a `u64` to an `i128` + | +LL | x_i128 > x_u64.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:302:18 + | +LL | x_i128 > x_u128; + | ------ ^^^^^^ expected `i128`, found `u128` + | | + | expected because this is `i128` + | +help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit + | +LL | x_i128 > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:304:18 + | +LL | x_i128 > x_usize; + | ------ ^^^^^^^ expected `i128`, found `usize` + | | + | expected because this is `i128` + | +help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit + | +LL | x_i128 > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:307:19 + | +LL | x_isize > x_u8; + | ------- ^^^^ expected `isize`, found `u8` + | | + | expected because this is `isize` + | +help: you can convert a `u8` to an `isize` + | +LL | x_isize > x_u8.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:309:19 + | +LL | x_isize > x_u16; + | ------- ^^^^^ expected `isize`, found `u16` + | | + | expected because this is `isize` + | +help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_u16.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:311:19 + | +LL | x_isize > x_u32; + | ------- ^^^^^ expected `isize`, found `u32` + | | + | expected because this is `isize` + | +help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_u32.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:313:19 + | +LL | x_isize > x_u64; + | ------- ^^^^^ expected `isize`, found `u64` + | | + | expected because this is `isize` + | +help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_u64.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:315:19 + | +LL | x_isize > x_u128; + | ------- ^^^^^^ expected `isize`, found `u128` + | | + | expected because this is `isize` + | +help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_u128.try_into().unwrap(); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast-binop.rs:317:19 + | +LL | x_isize > x_usize; + | ------- ^^^^^^^ expected `isize`, found `usize` + | | + | expected because this is `isize` + | +help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit + | +LL | x_isize > x_usize.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 132 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-cast-no-fix.rs b/tests/ui/numeric/numeric-cast-no-fix.rs new file mode 100644 index 000000000..63e5f098a --- /dev/null +++ b/tests/ui/numeric/numeric-cast-no-fix.rs @@ -0,0 +1,87 @@ +#[allow(unused_must_use)] +fn main() { + let x_usize: usize = 1; + let x_u128: u128 = 2; + let x_u64: u64 = 3; + let x_u32: u32 = 4; + let x_u16: u16 = 5; + let x_u8: u8 = 6; + + x_usize > -1_isize; + //~^ ERROR mismatched types + x_u128 > -1_isize; + //~^ ERROR mismatched types + x_u64 > -1_isize; + //~^ ERROR mismatched types + x_u32 > -1_isize; + //~^ ERROR mismatched types + x_u16 > -1_isize; + //~^ ERROR mismatched types + x_u8 > -1_isize; + //~^ ERROR mismatched types + + x_usize > -1_i128; + //~^ ERROR mismatched types + x_u128 > -1_i128; + //~^ ERROR mismatched types + x_u64 > -1_i128; + //~^ ERROR mismatched types + x_u32 > -1_i128; + //~^ ERROR mismatched types + x_u16 > -1_i128; + //~^ ERROR mismatched types + x_u8 > -1_i128; + //~^ ERROR mismatched types + + x_usize > -1_i64; + //~^ ERROR mismatched types + x_u128 > -1_i64; + //~^ ERROR mismatched types + x_u64 > -1_i64; + //~^ ERROR mismatched types + x_u32 > -1_i64; + //~^ ERROR mismatched types + x_u16 > -1_i64; + //~^ ERROR mismatched types + x_u8 > -1_i64; + //~^ ERROR mismatched types + + x_usize > -1_i32; + //~^ ERROR mismatched types + x_u128 > -1_i32; + //~^ ERROR mismatched types + x_u64 > -1_i32; + //~^ ERROR mismatched types + x_u32 > -1_i32; + //~^ ERROR mismatched types + x_u16 > -1_i32; + //~^ ERROR mismatched types + x_u8 > -1_i32; + //~^ ERROR mismatched types + + x_usize > -1_i16; + //~^ ERROR mismatched types + x_u128 > -1_i16; + //~^ ERROR mismatched types + x_u64 > -1_i16; + //~^ ERROR mismatched types + x_u32 > -1_i16; + //~^ ERROR mismatched types + x_u16 > -1_i16; + //~^ ERROR mismatched types + x_u8 > -1_i16; + //~^ ERROR mismatched types + + x_usize > -1_i8; + //~^ ERROR mismatched types + x_u128 > -1_i8; + //~^ ERROR mismatched types + x_u64 > -1_i8; + //~^ ERROR mismatched types + x_u32 > -1_i8; + //~^ ERROR mismatched types + x_u16 > -1_i8; + //~^ ERROR mismatched types + x_u8 > -1_i8; + //~^ ERROR mismatched types +} diff --git a/tests/ui/numeric/numeric-cast-no-fix.stderr b/tests/ui/numeric/numeric-cast-no-fix.stderr new file mode 100644 index 000000000..c244e479d --- /dev/null +++ b/tests/ui/numeric/numeric-cast-no-fix.stderr @@ -0,0 +1,396 @@ +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:10:15 + | +LL | x_usize > -1_isize; + | ------- ^^^^^^^^ expected `usize`, found `isize` + | | + | expected because this is `usize` + | + = note: `-1_isize` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:12:14 + | +LL | x_u128 > -1_isize; + | ------ ^^^^^^^^ expected `u128`, found `isize` + | | + | expected because this is `u128` + | + = note: `-1_isize` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:14:13 + | +LL | x_u64 > -1_isize; + | ----- ^^^^^^^^ expected `u64`, found `isize` + | | + | expected because this is `u64` + | + = note: `-1_isize` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:16:13 + | +LL | x_u32 > -1_isize; + | ----- ^^^^^^^^ expected `u32`, found `isize` + | | + | expected because this is `u32` + | + = note: `-1_isize` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:18:13 + | +LL | x_u16 > -1_isize; + | ----- ^^^^^^^^ expected `u16`, found `isize` + | | + | expected because this is `u16` + | + = note: `-1_isize` cannot fit into type `u16` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:20:12 + | +LL | x_u8 > -1_isize; + | ---- ^^^^^^^^ expected `u8`, found `isize` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize` + | +LL | isize::from(x_u8) > -1_isize; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:23:15 + | +LL | x_usize > -1_i128; + | ------- ^^^^^^^ expected `usize`, found `i128` + | | + | expected because this is `usize` + | + = note: `-1_i128` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:25:14 + | +LL | x_u128 > -1_i128; + | ------ ^^^^^^^ expected `u128`, found `i128` + | | + | expected because this is `u128` + | + = note: `-1_i128` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:27:13 + | +LL | x_u64 > -1_i128; + | ----- ^^^^^^^ expected `u64`, found `i128` + | | + | expected because this is `u64` + | +help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u64) > -1_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:29:13 + | +LL | x_u32 > -1_i128; + | ----- ^^^^^^^ expected `u32`, found `i128` + | | + | expected because this is `u32` + | +help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u32) > -1_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:31:13 + | +LL | x_u16 > -1_i128; + | ----- ^^^^^^^ expected `u16`, found `i128` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u16) > -1_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:33:12 + | +LL | x_u8 > -1_i128; + | ---- ^^^^^^^ expected `u8`, found `i128` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128` + | +LL | i128::from(x_u8) > -1_i128; + | +++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:36:15 + | +LL | x_usize > -1_i64; + | ------- ^^^^^^ expected `usize`, found `i64` + | | + | expected because this is `usize` + | + = note: `-1_i64` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:38:14 + | +LL | x_u128 > -1_i64; + | ------ ^^^^^^ expected `u128`, found `i64` + | | + | expected because this is `u128` + | + = note: `-1_i64` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:40:13 + | +LL | x_u64 > -1_i64; + | ----- ^^^^^^ expected `u64`, found `i64` + | | + | expected because this is `u64` + | + = note: `-1_i64` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:42:13 + | +LL | x_u32 > -1_i64; + | ----- ^^^^^^ expected `u32`, found `i64` + | | + | expected because this is `u32` + | +help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64` + | +LL | i64::from(x_u32) > -1_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:44:13 + | +LL | x_u16 > -1_i64; + | ----- ^^^^^^ expected `u16`, found `i64` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64` + | +LL | i64::from(x_u16) > -1_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:46:12 + | +LL | x_u8 > -1_i64; + | ---- ^^^^^^ expected `u8`, found `i64` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64` + | +LL | i64::from(x_u8) > -1_i64; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:49:15 + | +LL | x_usize > -1_i32; + | ------- ^^^^^^ expected `usize`, found `i32` + | | + | expected because this is `usize` + | + = note: `-1_i32` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:51:14 + | +LL | x_u128 > -1_i32; + | ------ ^^^^^^ expected `u128`, found `i32` + | | + | expected because this is `u128` + | + = note: `-1_i32` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:53:13 + | +LL | x_u64 > -1_i32; + | ----- ^^^^^^ expected `u64`, found `i32` + | | + | expected because this is `u64` + | + = note: `-1_i32` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:55:13 + | +LL | x_u32 > -1_i32; + | ----- ^^^^^^ expected `u32`, found `i32` + | | + | expected because this is `u32` + | + = note: `-1_i32` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:57:13 + | +LL | x_u16 > -1_i32; + | ----- ^^^^^^ expected `u16`, found `i32` + | | + | expected because this is `u16` + | +help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32` + | +LL | i32::from(x_u16) > -1_i32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:59:12 + | +LL | x_u8 > -1_i32; + | ---- ^^^^^^ expected `u8`, found `i32` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32` + | +LL | i32::from(x_u8) > -1_i32; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:62:15 + | +LL | x_usize > -1_i16; + | ------- ^^^^^^ expected `usize`, found `i16` + | | + | expected because this is `usize` + | + = note: `-1_i16` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:64:14 + | +LL | x_u128 > -1_i16; + | ------ ^^^^^^ expected `u128`, found `i16` + | | + | expected because this is `u128` + | + = note: `-1_i16` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:66:13 + | +LL | x_u64 > -1_i16; + | ----- ^^^^^^ expected `u64`, found `i16` + | | + | expected because this is `u64` + | + = note: `-1_i16` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:68:13 + | +LL | x_u32 > -1_i16; + | ----- ^^^^^^ expected `u32`, found `i16` + | | + | expected because this is `u32` + | + = note: `-1_i16` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:70:13 + | +LL | x_u16 > -1_i16; + | ----- ^^^^^^ expected `u16`, found `i16` + | | + | expected because this is `u16` + | + = note: `-1_i16` cannot fit into type `u16` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:72:12 + | +LL | x_u8 > -1_i16; + | ---- ^^^^^^ expected `u8`, found `i16` + | | + | expected because this is `u8` + | +help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16` + | +LL | i16::from(x_u8) > -1_i16; + | ++++++++++ + + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:75:15 + | +LL | x_usize > -1_i8; + | ------- ^^^^^ expected `usize`, found `i8` + | | + | expected because this is `usize` + | + = note: `-1_i8` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:77:14 + | +LL | x_u128 > -1_i8; + | ------ ^^^^^ expected `u128`, found `i8` + | | + | expected because this is `u128` + | + = note: `-1_i8` cannot fit into type `u128` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:79:13 + | +LL | x_u64 > -1_i8; + | ----- ^^^^^ expected `u64`, found `i8` + | | + | expected because this is `u64` + | + = note: `-1_i8` cannot fit into type `u64` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:81:13 + | +LL | x_u32 > -1_i8; + | ----- ^^^^^ expected `u32`, found `i8` + | | + | expected because this is `u32` + | + = note: `-1_i8` cannot fit into type `u32` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:83:13 + | +LL | x_u16 > -1_i8; + | ----- ^^^^^ expected `u16`, found `i8` + | | + | expected because this is `u16` + | + = note: `-1_i8` cannot fit into type `u16` + +error[E0308]: mismatched types + --> $DIR/numeric-cast-no-fix.rs:85:12 + | +LL | x_u8 > -1_i8; + | ---- ^^^^^ expected `u8`, found `i8` + | | + | expected because this is `u8` + | + = note: `-1_i8` cannot fit into type `u8` + +error: aborting due to 36 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-cast-without-suggestion.rs b/tests/ui/numeric/numeric-cast-without-suggestion.rs new file mode 100644 index 000000000..faf24a8c1 --- /dev/null +++ b/tests/ui/numeric/numeric-cast-without-suggestion.rs @@ -0,0 +1,38 @@ +fn foo(_x: N) {} + +fn main() { + let x_usize: usize = 1; + let x_u64: u64 = 2; + let x_u32: u32 = 3; + let x_u16: u16 = 4; + let x_u8: u8 = 5; + let x_isize: isize = 6; + let x_i64: i64 = 7; + let x_i32: i32 = 8; + let x_i16: i16 = 9; + let x_i8: i8 = 10; + let x_f64: f64 = 11.0; + let x_f32: f32 = 12.0; + + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types + foo::(x_f32); //~ ERROR mismatched types + foo::(x_f64); //~ ERROR mismatched types +} diff --git a/tests/ui/numeric/numeric-cast-without-suggestion.stderr b/tests/ui/numeric/numeric-cast-without-suggestion.stderr new file mode 100644 index 000000000..581b548ab --- /dev/null +++ b/tests/ui/numeric/numeric-cast-without-suggestion.stderr @@ -0,0 +1,297 @@ +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:17:18 + | +LL | foo::(x_f64); + | ------------ ^^^^^ expected `usize`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:18:18 + | +LL | foo::(x_f32); + | ------------ ^^^^^ expected `usize`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:19:18 + | +LL | foo::(x_f64); + | ------------ ^^^^^ expected `isize`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:20:18 + | +LL | foo::(x_f32); + | ------------ ^^^^^ expected `isize`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:21:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `u64`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:22:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `u64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:23:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `i64`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:24:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `i64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:25:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `u32`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:26:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `u32`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:27:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `i32`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:28:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `i32`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:29:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `u16`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:30:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `u16`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:31:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `i16`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:32:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `i16`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:33:15 + | +LL | foo::(x_f64); + | --------- ^^^^^ expected `u8`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:34:15 + | +LL | foo::(x_f32); + | --------- ^^^^^ expected `u8`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:35:15 + | +LL | foo::(x_f64); + | --------- ^^^^^ expected `i8`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:36:15 + | +LL | foo::(x_f32); + | --------- ^^^^^ expected `i8`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error[E0308]: mismatched types + --> $DIR/numeric-cast-without-suggestion.rs:37:16 + | +LL | foo::(x_f64); + | ---------- ^^^^^ expected `f32`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast-without-suggestion.rs:1:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-cast.fixed b/tests/ui/numeric/numeric-cast.fixed new file mode 100644 index 000000000..cf0560a10 --- /dev/null +++ b/tests/ui/numeric/numeric-cast.fixed @@ -0,0 +1,293 @@ +// run-rustfix + +// The `try_into` suggestion doesn't include this, but we do suggest it after applying it +use std::convert::TryInto; + +fn foo(_x: N) {} + +fn main() { + let x_usize: usize = 1; + let x_u64: u64 = 2; + let x_u32: u32 = 3; + let x_u16: u16 = 4; + let x_u8: u8 = 5; + let x_isize: isize = 6; + let x_i64: i64 = 7; + let x_i32: i32 = 8; + let x_i16: i16 = 9; + let x_i8: i8 = 10; + let x_f64: f64 = 11.0; + let x_f32: f32 = 12.0; + + foo::(x_usize); + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i8.try_into().unwrap()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize); + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.into()); + //~^ ERROR mismatched types + foo::(x_i8.into()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64); + foo::(x_u32.into()); + //~^ ERROR mismatched types + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i8.try_into().unwrap()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.into()); + //~^ ERROR mismatched types + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64); + foo::(x_i32.into()); + //~^ ERROR mismatched types + foo::(x_i16.into()); + //~^ ERROR mismatched types + foo::(x_i8.into()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32); + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i8.try_into().unwrap()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32); + foo::(x_i16.into()); + //~^ ERROR mismatched types + foo::(x_i8.into()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16); + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i8.try_into().unwrap()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16); + foo::(x_i8.into()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u8); + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i8.try_into().unwrap()); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_u8.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_isize.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i64.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i32.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i16.try_into().unwrap()); + //~^ ERROR mismatched types + foo::(x_i8); + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize as f64); + //~^ ERROR mismatched types + foo::(x_u64 as f64); + //~^ ERROR mismatched types + foo::(x_u32.into()); + //~^ ERROR mismatched types + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize as f64); + //~^ ERROR mismatched types + foo::(x_i64 as f64); + //~^ ERROR mismatched types + foo::(x_i32.into()); + //~^ ERROR mismatched types + foo::(x_i16.into()); + //~^ ERROR mismatched types + foo::(x_i8.into()); + //~^ ERROR mismatched types + foo::(x_f64); + foo::(x_f32.into()); + //~^ ERROR mismatched types + + foo::(x_usize as f32); + //~^ ERROR mismatched types + foo::(x_u64 as f32); + //~^ ERROR mismatched types + foo::(x_u32 as f32); + //~^ ERROR mismatched types + foo::(x_u16.into()); + //~^ ERROR mismatched types + foo::(x_u8.into()); + //~^ ERROR mismatched types + foo::(x_isize as f32); + //~^ ERROR mismatched types + foo::(x_i64 as f32); + //~^ ERROR mismatched types + foo::(x_i32 as f32); + //~^ ERROR mismatched types + foo::(x_i16.into()); + //~^ ERROR mismatched types + foo::(x_i8.into()); + //~^ ERROR mismatched types + // foo::(x_f64); + foo::(x_f32); + + foo::((x_u8 as u16).into()); + //~^ ERROR mismatched types + foo::((-x_i8).into()); + //~^ ERROR mismatched types +} diff --git a/tests/ui/numeric/numeric-cast.rs b/tests/ui/numeric/numeric-cast.rs new file mode 100644 index 000000000..7bddfc509 --- /dev/null +++ b/tests/ui/numeric/numeric-cast.rs @@ -0,0 +1,293 @@ +// run-rustfix + +// The `try_into` suggestion doesn't include this, but we do suggest it after applying it +use std::convert::TryInto; + +fn foo(_x: N) {} + +fn main() { + let x_usize: usize = 1; + let x_u64: u64 = 2; + let x_u32: u32 = 3; + let x_u16: u16 = 4; + let x_u8: u8 = 5; + let x_isize: isize = 6; + let x_i64: i64 = 7; + let x_i32: i32 = 8; + let x_i16: i16 = 9; + let x_i8: i8 = 10; + let x_f64: f64 = 11.0; + let x_f32: f32 = 12.0; + + foo::(x_usize); + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + // foo::(x_f64); + // foo::(x_f32); + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + foo::(x_f64); + foo::(x_f32); + //~^ ERROR mismatched types + + foo::(x_usize); + //~^ ERROR mismatched types + foo::(x_u64); + //~^ ERROR mismatched types + foo::(x_u32); + //~^ ERROR mismatched types + foo::(x_u16); + //~^ ERROR mismatched types + foo::(x_u8); + //~^ ERROR mismatched types + foo::(x_isize); + //~^ ERROR mismatched types + foo::(x_i64); + //~^ ERROR mismatched types + foo::(x_i32); + //~^ ERROR mismatched types + foo::(x_i16); + //~^ ERROR mismatched types + foo::(x_i8); + //~^ ERROR mismatched types + // foo::(x_f64); + foo::(x_f32); + + foo::(x_u8 as u16); + //~^ ERROR mismatched types + foo::(-x_i8); + //~^ ERROR mismatched types +} diff --git a/tests/ui/numeric/numeric-cast.stderr b/tests/ui/numeric/numeric-cast.stderr new file mode 100644 index 000000000..d347875d5 --- /dev/null +++ b/tests/ui/numeric/numeric-cast.stderr @@ -0,0 +1,2037 @@ +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:23:18 + | +LL | foo::(x_u64); + | ------------ ^^^^^ expected `usize`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:25:18 + | +LL | foo::(x_u32); + | ------------ ^^^^^ expected `usize`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:27:18 + | +LL | foo::(x_u16); + | ------------ ^^^^^ expected `usize`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to a `usize` + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:29:18 + | +LL | foo::(x_u8); + | ------------ ^^^^ expected `usize`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to a `usize` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:31:18 + | +LL | foo::(x_isize); + | ------------ ^^^^^^^ expected `usize`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:33:18 + | +LL | foo::(x_i64); + | ------------ ^^^^^ expected `usize`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:35:18 + | +LL | foo::(x_i32); + | ------------ ^^^^^ expected `usize`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:37:18 + | +LL | foo::(x_i16); + | ------------ ^^^^^ expected `usize`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_i16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:39:18 + | +LL | foo::(x_i8); + | ------------ ^^^^ expected `usize`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit + | +LL | foo::(x_i8.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:44:18 + | +LL | foo::(x_usize); + | ------------ ^^^^^^^ expected `isize`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:46:18 + | +LL | foo::(x_u64); + | ------------ ^^^^^ expected `isize`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:48:18 + | +LL | foo::(x_u32); + | ------------ ^^^^^ expected `isize`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:50:18 + | +LL | foo::(x_u16); + | ------------ ^^^^^ expected `isize`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit + | +LL | foo::(x_u16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:52:18 + | +LL | foo::(x_u8); + | ------------ ^^^^ expected `isize`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `isize` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:55:18 + | +LL | foo::(x_i64); + | ------------ ^^^^^ expected `isize`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:57:18 + | +LL | foo::(x_i32); + | ------------ ^^^^^ expected `isize`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:59:18 + | +LL | foo::(x_i16); + | ------------ ^^^^^ expected `isize`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `isize` + | +LL | foo::(x_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:61:18 + | +LL | foo::(x_i8); + | ------------ ^^^^ expected `isize`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `isize` + | +LL | foo::(x_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:66:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `u64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:69:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `u64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to a `u64` + | +LL | foo::(x_u32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:71:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `u64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to a `u64` + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:73:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `u64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to a `u64` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:75:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `u64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:77:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `u64`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:79:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `u64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:81:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `u64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit + | +LL | foo::(x_i16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:83:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `u64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit + | +LL | foo::(x_i8.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:88:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `i64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:90:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `i64`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:92:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `i64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `i64` + | +LL | foo::(x_u32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:94:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `i64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `i64` + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:96:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `i64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `i64` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:98:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `i64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:101:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `i64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `i64` + | +LL | foo::(x_i32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:103:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `i64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `i64` + | +LL | foo::(x_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:105:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `i64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `i64` + | +LL | foo::(x_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:110:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `u32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:112:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `u32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:115:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to a `u32` + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:117:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `u32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to a `u32` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:119:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `u32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:121:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `u32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:123:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:125:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `u32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_i16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:127:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `u32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit + | +LL | foo::(x_i8.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:132:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `i32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:134:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `i32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:136:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `i32`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:138:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `i32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `i32` + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:140:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `i32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `i32` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:142:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `i32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:144:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `i32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:147:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `i32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `i32` + | +LL | foo::(x_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:149:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `i32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `i32` + | +LL | foo::(x_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:154:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `u16`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:156:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `u16`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:158:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `u16`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:161:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `u16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to a `u16` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:163:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `u16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:165:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `u16`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:167:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `u16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:169:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `u16`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_i16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:171:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `u16`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit + | +LL | foo::(x_i8.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:176:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `i16`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:178:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `i16`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:180:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `i16`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:182:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `i16`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_u16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:184:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `i16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `i16` + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:186:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `i16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:188:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `i16`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:190:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `i16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:193:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `i16`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `i16` + | +LL | foo::(x_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:198:15 + | +LL | foo::(x_usize); + | --------- ^^^^^^^ expected `u8`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:200:15 + | +LL | foo::(x_u64); + | --------- ^^^^^ expected `u8`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:202:15 + | +LL | foo::(x_u32); + | --------- ^^^^^ expected `u8`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:204:15 + | +LL | foo::(x_u16); + | --------- ^^^^^ expected `u8`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_u16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:207:15 + | +LL | foo::(x_isize); + | --------- ^^^^^^^ expected `u8`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:209:15 + | +LL | foo::(x_i64); + | --------- ^^^^^ expected `u8`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:211:15 + | +LL | foo::(x_i32); + | --------- ^^^^^ expected `u8`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:213:15 + | +LL | foo::(x_i16); + | --------- ^^^^^ expected `u8`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_i16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:215:15 + | +LL | foo::(x_i8); + | --------- ^^^^ expected `u8`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit + | +LL | foo::(x_i8.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:220:15 + | +LL | foo::(x_usize); + | --------- ^^^^^^^ expected `i8`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_usize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:222:15 + | +LL | foo::(x_u64); + | --------- ^^^^^ expected `i8`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_u64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:224:15 + | +LL | foo::(x_u32); + | --------- ^^^^^ expected `i8`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_u32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:226:15 + | +LL | foo::(x_u16); + | --------- ^^^^^ expected `i8`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_u16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:228:15 + | +LL | foo::(x_u8); + | --------- ^^^^ expected `i8`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_u8.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:230:15 + | +LL | foo::(x_isize); + | --------- ^^^^^^^ expected `i8`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_isize.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:232:15 + | +LL | foo::(x_i64); + | --------- ^^^^^ expected `i8`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_i64.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:234:15 + | +LL | foo::(x_i32); + | --------- ^^^^^ expected `i8`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_i32.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:236:15 + | +LL | foo::(x_i16); + | --------- ^^^^^ expected `i8`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit + | +LL | foo::(x_i16.try_into().unwrap()); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:242:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `f64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_usize as f64); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:244:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `f64`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_u64 as f64); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:246:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `f64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(x_u32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:248:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `f64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:250:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `f64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:252:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `f64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to an `f64`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_isize as f64); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:254:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `f64`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to an `f64`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_i64 as f64); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:256:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `f64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(x_i32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:258:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `f64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(x_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:260:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `f64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(x_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:263:16 + | +LL | foo::(x_f32); + | ---------- ^^^^^ expected `f64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `f32` to an `f64` + | +LL | foo::(x_f32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:266:16 + | +LL | foo::(x_usize); + | ---------- ^^^^^^^ expected `f32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_usize as f32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:268:16 + | +LL | foo::(x_u64); + | ---------- ^^^^^ expected `f32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_u64 as f32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:270:16 + | +LL | foo::(x_u32); + | ---------- ^^^^^ expected `f32`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_u32 as f32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:272:16 + | +LL | foo::(x_u16); + | ---------- ^^^^^ expected `f32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(x_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:274:16 + | +LL | foo::(x_u8); + | ---------- ^^^^ expected `f32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(x_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:276:16 + | +LL | foo::(x_isize); + | ---------- ^^^^^^^ expected `f32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `isize` to an `f32`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_isize as f32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:278:16 + | +LL | foo::(x_i64); + | ---------- ^^^^^ expected `f32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i64` to an `f32`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_i64 as f32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:280:16 + | +LL | foo::(x_i32); + | ---------- ^^^^^ expected `f32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary + | +LL | foo::(x_i32 as f32); + | ++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:282:16 + | +LL | foo::(x_i16); + | ---------- ^^^^^ expected `f32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(x_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:284:16 + | +LL | foo::(x_i8); + | ---------- ^^^^ expected `f32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(x_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:289:16 + | +LL | foo::(x_u8 as u16); + | ---------- ^^^^^^^^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to a `u32` + | +LL | foo::((x_u8 as u16).into()); + | + ++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-cast.rs:291:16 + | +LL | foo::(-x_i8); + | ---------- ^^^^^ expected `i32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-cast.rs:6:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `i32` + | +LL | foo::((-x_i8).into()); + | + ++++++++ + +error: aborting due to 113 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-fields.rs b/tests/ui/numeric/numeric-fields.rs new file mode 100644 index 000000000..28234bbdf --- /dev/null +++ b/tests/ui/numeric/numeric-fields.rs @@ -0,0 +1,10 @@ +struct S(u8, u16); + +fn main() { + let s = S{0b1: 10, 0: 11}; + //~^ ERROR struct `S` has no field named `0b1` + match s { + S{0: a, 0x1: b, ..} => {} + //~^ ERROR does not have a field named `0x1` + } +} diff --git a/tests/ui/numeric/numeric-fields.stderr b/tests/ui/numeric/numeric-fields.stderr new file mode 100644 index 000000000..668405ed6 --- /dev/null +++ b/tests/ui/numeric/numeric-fields.stderr @@ -0,0 +1,27 @@ +error[E0560]: struct `S` has no field named `0b1` + --> $DIR/numeric-fields.rs:4:15 + | +LL | struct S(u8, u16); + | - `S` defined here +... +LL | let s = S{0b1: 10, 0: 11}; + | ^^^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let s = S(/* fields */); + | ~~~~~~~~~~~~~~~ + +error[E0026]: struct `S` does not have a field named `0x1` + --> $DIR/numeric-fields.rs:7:17 + | +LL | S{0: a, 0x1: b, ..} => {} + | ^^^ + | | + | struct `S` does not have this field + | help: `S` has a field named `1` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0026, E0560. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed new file mode 100644 index 000000000..6e8c54df4 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs new file mode 100644 index 000000000..b47b0ed02 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.rs @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr new file mode 100644 index 000000000..f4fb14e79 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i32.stderr @@ -0,0 +1,201 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:28:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `i32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:32:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `i32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:36:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `i32`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:40:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `i32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:44:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `i32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:48:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `i32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:52:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `i32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:57:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `i32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:61:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `i32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `i32` + | +LL | foo::(42_i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:65:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `i32`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `i32` + | +LL | foo::(42i32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i32.rs:69:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `i32`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `i32` + | +LL | foo::(42i32); + | ~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed new file mode 100644 index 000000000..03821cd44 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs new file mode 100644 index 000000000..629fe7e74 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.rs @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr new file mode 100644 index 000000000..47efe9f08 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-i64.stderr @@ -0,0 +1,201 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:28:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `i64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:32:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `i64`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:36:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `i64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:40:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `i64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:44:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `i64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:48:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `i64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:53:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `i64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:57:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `i64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:61:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `i64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `i64` + | +LL | foo::(42_i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:65:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `i64`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `i64` + | +LL | foo::(42i64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-i64.rs:69:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `i64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-i64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `i64` + | +LL | foo::(42i64); + | ~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed new file mode 100644 index 000000000..faed65ca4 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs new file mode 100644 index 000000000..df0b4cb62 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.rs @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr new file mode 100644 index 000000000..28b79413f --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-isize.stderr @@ -0,0 +1,201 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:28:18 + | +LL | foo::(42_usize); + | ------------ ^^^^^^^^ expected `isize`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:32:18 + | +LL | foo::(42_u64); + | ------------ ^^^^^^ expected `isize`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:36:18 + | +LL | foo::(42_u32); + | ------------ ^^^^^^ expected `isize`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:40:18 + | +LL | foo::(42_u16); + | ------------ ^^^^^^ expected `isize`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:44:18 + | +LL | foo::(42_u8); + | ------------ ^^^^^ expected `isize`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:49:18 + | +LL | foo::(42_i64); + | ------------ ^^^^^^ expected `isize`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:53:18 + | +LL | foo::(42_i32); + | ------------ ^^^^^^ expected `isize`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:57:18 + | +LL | foo::(42_i16); + | ------------ ^^^^^^ expected `isize`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:61:18 + | +LL | foo::(42_i8); + | ------------ ^^^^^ expected `isize`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `isize` + | +LL | foo::(42_isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:65:18 + | +LL | foo::(42.0_f64); + | ------------ ^^^^^^^^ expected `isize`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `isize` + | +LL | foo::(42isize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-isize.rs:69:18 + | +LL | foo::(42.0_f32); + | ------------ ^^^^^^^^ expected `isize`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-isize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `isize` + | +LL | foo::(42isize); + | ~~~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed new file mode 100644 index 000000000..5955829e7 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs new file mode 100644 index 000000000..5c303036a --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.rs @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr new file mode 100644 index 000000000..d966893a8 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u32.stderr @@ -0,0 +1,201 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:28:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `u32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:32:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `u32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:37:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:41:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `u32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:45:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `u32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:49:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `u32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:53:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:57:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `u32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:61:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `u32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `u32` + | +LL | foo::(42_u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:65:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `u32`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `u32` + | +LL | foo::(42u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u32.rs:69:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `u32`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u32.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `u32` + | +LL | foo::(42u32); + | ~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed new file mode 100644 index 000000000..4623c211c --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs new file mode 100644 index 000000000..3e9995c74 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.rs @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr new file mode 100644 index 000000000..ff332fa91 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-u64.stderr @@ -0,0 +1,201 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:28:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `u64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:33:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `u64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:37:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `u64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:41:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `u64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:45:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `u64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:49:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `u64`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:53:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `u64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:57:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `u64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:61:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `u64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `u64` + | +LL | foo::(42_u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:65:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `u64`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `u64` + | +LL | foo::(42u64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-u64.rs:69:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `u64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-u64.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `u64` + | +LL | foo::(42u64); + | ~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed new file mode 100644 index 000000000..6cb5243ca --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.fixed @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs new file mode 100644 index 000000000..a2304ba26 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.rs @@ -0,0 +1,73 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + +fn main() { + foo::(42_usize); + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr new file mode 100644 index 000000000..4889abee6 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix-usize.stderr @@ -0,0 +1,201 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:29:18 + | +LL | foo::(42_u64); + | ------------ ^^^^^^ expected `usize`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:33:18 + | +LL | foo::(42_u32); + | ------------ ^^^^^^ expected `usize`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:37:18 + | +LL | foo::(42_u16); + | ------------ ^^^^^^ expected `usize`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:41:18 + | +LL | foo::(42_u8); + | ------------ ^^^^^ expected `usize`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:45:18 + | +LL | foo::(42_isize); + | ------------ ^^^^^^^^ expected `usize`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:49:18 + | +LL | foo::(42_i64); + | ------------ ^^^^^^ expected `usize`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:53:18 + | +LL | foo::(42_i32); + | ------------ ^^^^^^ expected `usize`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:57:18 + | +LL | foo::(42_i16); + | ------------ ^^^^^^ expected `usize`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:61:18 + | +LL | foo::(42_i8); + | ------------ ^^^^^ expected `usize`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `usize` + | +LL | foo::(42_usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:65:18 + | +LL | foo::(42.0_f64); + | ------------ ^^^^^^^^ expected `usize`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `usize` + | +LL | foo::(42usize); + | ~~~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix-usize.rs:69:18 + | +LL | foo::(42.0_f32); + | ------------ ^^^^^^^^ expected `usize`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix-usize.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `usize` + | +LL | foo::(42usize); + | ~~~~~ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed b/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed new file mode 100644 index 000000000..69934db21 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix.fixed @@ -0,0 +1,427 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + + +fn main() { + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + foo::(42i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8.into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + + foo::((42_u8 as u16).into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::((-42_i8).into()); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix.rs b/tests/ui/numeric/numeric-suffix/numeric-suffix.rs new file mode 100644 index 000000000..dabf43f82 --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix.rs @@ -0,0 +1,427 @@ +// run-rustfix + +fn foo(_x: N) {} +//~^ NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE function defined here +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE +//~| NOTE + + +fn main() { + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + foo::(42.0_f32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + + foo::(42_usize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_u8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_isize); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i32); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f64); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(42.0_f32); + + foo::(42_u8 as u16); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments + foo::(-42_i8); + //~^ ERROR mismatched types + //~| NOTE expected + //~| NOTE arguments +} diff --git a/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr b/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr new file mode 100644 index 000000000..e05913b9c --- /dev/null +++ b/tests/ui/numeric/numeric-suffix/numeric-suffix.stderr @@ -0,0 +1,1227 @@ +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:143:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `u16`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:147:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `u16`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:151:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `u16`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:156:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `u16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:160:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `u16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:164:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `u16`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:168:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `u16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:172:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `u16`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:176:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `u16`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `u16` + | +LL | foo::(42_u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:180:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `u16`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `u16` + | +LL | foo::(42u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:184:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `u16`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `u16` + | +LL | foo::(42u16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:189:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `i16`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:193:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `i16`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:197:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `i16`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:201:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `i16`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:205:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `i16`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:209:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `i16`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:213:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `i16`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:217:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `i16`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:222:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `i16`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `i16` + | +LL | foo::(42_i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:226:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `i16`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `i16` + | +LL | foo::(42i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:230:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `i16`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `i16` + | +LL | foo::(42i16); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:235:15 + | +LL | foo::(42_usize); + | --------- ^^^^^^^^ expected `u8`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:239:15 + | +LL | foo::(42_u64); + | --------- ^^^^^^ expected `u8`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:243:15 + | +LL | foo::(42_u32); + | --------- ^^^^^^ expected `u8`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:247:15 + | +LL | foo::(42_u16); + | --------- ^^^^^^ expected `u8`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:252:15 + | +LL | foo::(42_isize); + | --------- ^^^^^^^^ expected `u8`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:256:15 + | +LL | foo::(42_i64); + | --------- ^^^^^^ expected `u8`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:260:15 + | +LL | foo::(42_i32); + | --------- ^^^^^^ expected `u8`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:264:15 + | +LL | foo::(42_i16); + | --------- ^^^^^^ expected `u8`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:268:15 + | +LL | foo::(42_i8); + | --------- ^^^^^ expected `u8`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i8` to `u8` + | +LL | foo::(42_u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:272:15 + | +LL | foo::(42.0_f64); + | --------- ^^^^^^^^ expected `u8`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `u8` + | +LL | foo::(42u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:276:15 + | +LL | foo::(42.0_f32); + | --------- ^^^^^^^^ expected `u8`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `u8` + | +LL | foo::(42u8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:281:15 + | +LL | foo::(42_usize); + | --------- ^^^^^^^^ expected `i8`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:285:15 + | +LL | foo::(42_u64); + | --------- ^^^^^^ expected `i8`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:289:15 + | +LL | foo::(42_u32); + | --------- ^^^^^^ expected `i8`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:293:15 + | +LL | foo::(42_u16); + | --------- ^^^^^^ expected `i8`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u16` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:297:15 + | +LL | foo::(42_u8); + | --------- ^^^^^ expected `i8`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u8` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:301:15 + | +LL | foo::(42_isize); + | --------- ^^^^^^^^ expected `i8`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:305:15 + | +LL | foo::(42_i64); + | --------- ^^^^^^ expected `i8`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:309:15 + | +LL | foo::(42_i32); + | --------- ^^^^^^ expected `i8`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:313:15 + | +LL | foo::(42_i16); + | --------- ^^^^^^ expected `i8`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i16` to `i8` + | +LL | foo::(42_i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:318:15 + | +LL | foo::(42.0_f64); + | --------- ^^^^^^^^ expected `i8`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `i8` + | +LL | foo::(42i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:322:15 + | +LL | foo::(42.0_f32); + | --------- ^^^^^^^^ expected `i8`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `i8` + | +LL | foo::(42i8); + | ~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:327:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `f64`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `f64` + | +LL | foo::(42_f64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:331:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `f64`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `f64` + | +LL | foo::(42_f64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:335:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `f64`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(42_u32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:339:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `f64`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(42_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:343:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `f64`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(42_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:347:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `f64`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `f64` + | +LL | foo::(42_f64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:351:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `f64`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `f64` + | +LL | foo::(42_f64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:355:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `f64`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(42_i32.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:359:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `f64`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(42_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:363:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `f64`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer + | +LL | foo::(42_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:368:16 + | +LL | foo::(42.0_f32); + | ---------- ^^^^^^^^ expected `f64`, found `f32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f32` to `f64` + | +LL | foo::(42.0_f64); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:373:16 + | +LL | foo::(42_usize); + | ---------- ^^^^^^^^ expected `f32`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `usize` to `f32` + | +LL | foo::(42_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:377:16 + | +LL | foo::(42_u64); + | ---------- ^^^^^^ expected `f32`, found `u64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u64` to `f32` + | +LL | foo::(42_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:381:16 + | +LL | foo::(42_u32); + | ---------- ^^^^^^ expected `f32`, found `u32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `u32` to `f32` + | +LL | foo::(42_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:385:16 + | +LL | foo::(42_u16); + | ---------- ^^^^^^ expected `f32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(42_u16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:389:16 + | +LL | foo::(42_u8); + | ---------- ^^^^^ expected `f32`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(42_u8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:393:16 + | +LL | foo::(42_isize); + | ---------- ^^^^^^^^ expected `f32`, found `isize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `isize` to `f32` + | +LL | foo::(42_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:397:16 + | +LL | foo::(42_i64); + | ---------- ^^^^^^ expected `f32`, found `i64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i64` to `f32` + | +LL | foo::(42_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:401:16 + | +LL | foo::(42_i32); + | ---------- ^^^^^^ expected `f32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `i32` to `f32` + | +LL | foo::(42_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:405:16 + | +LL | foo::(42_i16); + | ---------- ^^^^^^ expected `f32`, found `i16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(42_i16.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:409:16 + | +LL | foo::(42_i8); + | ---------- ^^^^^ expected `f32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer + | +LL | foo::(42_i8.into()); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:413:16 + | +LL | foo::(42.0_f64); + | ---------- ^^^^^^^^ expected `f32`, found `f64` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: change the type of the numeric literal from `f64` to `f32` + | +LL | foo::(42.0_f32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:419:16 + | +LL | foo::(42_u8 as u16); + | ---------- ^^^^^^^^^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert a `u16` to a `u32` + | +LL | foo::((42_u8 as u16).into()); + | + ++++++++ + +error[E0308]: mismatched types + --> $DIR/numeric-suffix.rs:423:16 + | +LL | foo::(-42_i8); + | ---------- ^^^^^^ expected `i32`, found `i8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/numeric-suffix.rs:3:4 + | +LL | fn foo(_x: N) {} + | ^^^ ----- +help: you can convert an `i8` to an `i32` + | +LL | foo::((-42_i8).into()); + | + ++++++++ + +error: aborting due to 68 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs b/tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs new file mode 100644 index 000000000..f00cde4a7 --- /dev/null +++ b/tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.rs @@ -0,0 +1,34 @@ +// Checks that integers with seeming uppercase base prefixes do not get bogus capitalization +// suggestions. + +fn main() { + _ = 123X1a3; + //~^ ERROR invalid suffix `X1a3` for number literal + //~| NOTE invalid suffix `X1a3` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 456O123; + //~^ ERROR invalid suffix `O123` for number literal + //~| NOTE invalid suffix `O123` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 789B101; + //~^ ERROR invalid suffix `B101` for number literal + //~| NOTE invalid suffix `B101` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 0XYZ; + //~^ ERROR invalid suffix `XYZ` for number literal + //~| NOTE invalid suffix `XYZ` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 0OPQ; + //~^ ERROR invalid suffix `OPQ` for number literal + //~| NOTE invalid suffix `OPQ` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + + _ = 0BCD; + //~^ ERROR invalid suffix `BCD` for number literal + //~| NOTE invalid suffix `BCD` + //~| HELP the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) +} diff --git a/tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr b/tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr new file mode 100644 index 000000000..380c16ca7 --- /dev/null +++ b/tests/ui/numeric/uppercase-base-prefix-invalid-no-fix.stderr @@ -0,0 +1,50 @@ +error: invalid suffix `X1a3` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:5:9 + | +LL | _ = 123X1a3; + | ^^^^^^^ invalid suffix `X1a3` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `O123` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:10:9 + | +LL | _ = 456O123; + | ^^^^^^^ invalid suffix `O123` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `B101` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:15:9 + | +LL | _ = 789B101; + | ^^^^^^^ invalid suffix `B101` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `XYZ` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:20:9 + | +LL | _ = 0XYZ; + | ^^^^ invalid suffix `XYZ` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `OPQ` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:25:9 + | +LL | _ = 0OPQ; + | ^^^^ invalid suffix `OPQ` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `BCD` for number literal + --> $DIR/uppercase-base-prefix-invalid-no-fix.rs:30:9 + | +LL | _ = 0BCD; + | ^^^^ invalid suffix `BCD` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: aborting due to 6 previous errors + diff --git a/tests/ui/numeric/uppercase-base-prefix.fixed b/tests/ui/numeric/uppercase-base-prefix.fixed new file mode 100644 index 000000000..1b1c837ec --- /dev/null +++ b/tests/ui/numeric/uppercase-base-prefix.fixed @@ -0,0 +1,77 @@ +// run-rustfix +// Checks that integers with an uppercase base prefix (0B, 0X, 0O) have a nice error +#![allow(unused_variables)] + +fn main() { + let a = 0xABCDEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEF + + let b = 0o755; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755 + + let c = 0b10101010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010 + + let d = 0xABC_DEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF + + let e = 0o7_55; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55 + + let f = 0b1010_1010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010 + + let g = 0xABC_DEF_u64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF_u64 + + let h = 0o7_55_u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55_u32 + + let i = 0b1010_1010_u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010_u8 + // + let j = 0xABCDEFu64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEFu64 + + let k = 0o755u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755u32 + + let l = 0b10101010u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010u8 +} diff --git a/tests/ui/numeric/uppercase-base-prefix.rs b/tests/ui/numeric/uppercase-base-prefix.rs new file mode 100644 index 000000000..233d553da --- /dev/null +++ b/tests/ui/numeric/uppercase-base-prefix.rs @@ -0,0 +1,77 @@ +// run-rustfix +// Checks that integers with an uppercase base prefix (0B, 0X, 0O) have a nice error +#![allow(unused_variables)] + +fn main() { + let a = 0XABCDEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEF + + let b = 0O755; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755 + + let c = 0B10101010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010 + + let d = 0XABC_DEF; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF + + let e = 0O7_55; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55 + + let f = 0B1010_1010; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010 + + let g = 0XABC_DEF_u64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABC_DEF_u64 + + let h = 0O7_55_u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o7_55_u32 + + let i = 0B1010_1010_u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b1010_1010_u8 + // + let j = 0XABCDEFu64; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0xABCDEFu64 + + let k = 0O755u32; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0o755u32 + + let l = 0B10101010u8; + //~^ ERROR invalid base prefix for number literal + //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + //~| HELP try making the prefix lowercase + //~| SUGGESTION 0b10101010u8 +} diff --git a/tests/ui/numeric/uppercase-base-prefix.stderr b/tests/ui/numeric/uppercase-base-prefix.stderr new file mode 100644 index 000000000..4ba8d5224 --- /dev/null +++ b/tests/ui/numeric/uppercase-base-prefix.stderr @@ -0,0 +1,98 @@ +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:6:13 + | +LL | let a = 0XABCDEF; + | ^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABCDEF` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:12:13 + | +LL | let b = 0O755; + | ^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o755` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:18:13 + | +LL | let c = 0B10101010; + | ^^^^^^^^^^ help: try making the prefix lowercase: `0b10101010` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:24:13 + | +LL | let d = 0XABC_DEF; + | ^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABC_DEF` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:30:13 + | +LL | let e = 0O7_55; + | ^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o7_55` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:36:13 + | +LL | let f = 0B1010_1010; + | ^^^^^^^^^^^ help: try making the prefix lowercase: `0b1010_1010` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:42:13 + | +LL | let g = 0XABC_DEF_u64; + | ^^^^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABC_DEF_u64` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:48:13 + | +LL | let h = 0O7_55_u32; + | ^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o7_55_u32` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:54:13 + | +LL | let i = 0B1010_1010_u8; + | ^^^^^^^^^^^^^^ help: try making the prefix lowercase: `0b1010_1010_u8` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:60:13 + | +LL | let j = 0XABCDEFu64; + | ^^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABCDEFu64` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:66:13 + | +LL | let k = 0O755u32; + | ^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o755u32` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: invalid base prefix for number literal + --> $DIR/uppercase-base-prefix.rs:72:13 + | +LL | let l = 0B10101010u8; + | ^^^^^^^^^^^^ help: try making the prefix lowercase: `0b10101010u8` + | + = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase + +error: aborting due to 12 previous errors + diff --git a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs new file mode 100644 index 000000000..5dae92fee --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs @@ -0,0 +1,48 @@ +// Test that if a struct declares multiple region bounds for a given +// type parameter, an explicit lifetime bound is required on object +// lifetimes within. + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct Ref0 { + r: *mut T +} + +struct Ref1<'a,T:'a+?Sized> { + r: &'a T +} + +struct Ref2<'a,'b:'a,T:'a+'b+?Sized> { + r: &'a &'b T +} + +fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) { + //~^ ERROR lifetime bound for this object type cannot be deduced from context +} + +fn b(t: Ref2) { + //~^ ERROR lifetime bound for this object type cannot be deduced from context +} + +fn c(t: Ref2<&dyn Test>) { + // In this case, the &'a overrides. +} + +fn d(t: Ref2>) { + // In this case, the lifetime parameter from the Ref1 overrides. +} + +fn e(t: Ref2>) { + // In this case, Ref2 is ambiguous, but Ref0 overrides with 'static. +} + +fn f(t: &Ref2) { + //~^ ERROR lifetime bound for this object type cannot be deduced from context +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr new file mode 100644 index 000000000..bd50a27fd --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr @@ -0,0 +1,21 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-ambiguous.rs:23:28 + | +LL | fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) { + | ^^^^^^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-ambiguous.rs:27:14 + | +LL | fn b(t: Ref2) { + | ^^^^^^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-ambiguous.rs:43:15 + | +LL | fn f(t: &Ref2) { + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs b/tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs new file mode 100644 index 000000000..467767ae5 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that `Box` is equivalent to `Box`, both in +// fields and fn arguments. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct { + t: Box, + u: Box, +} + +fn a(t: Box, mut ss: SomeStruct) { + ss.t = t; +} + +fn b(t: Box, mut ss: SomeStruct) { + ss.t = t; +} + +fn c(t: Box, mut ss: SomeStruct) { + ss.u = t; +} + +fn d(t: Box, mut ss: SomeStruct) { + ss.u = t; +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs new file mode 100644 index 000000000..7337383e2 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs @@ -0,0 +1,27 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr new file mode 100644 index 000000000..f06a9da1d --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -0,0 +1,9 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic1.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs new file mode 100644 index 000000000..2a7415174 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs @@ -0,0 +1,30 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: 'a + ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'a`. Or, we *should*, but the +// current code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + + // If it weren't for the conservative path above, we'd expect an + // error here. + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr new file mode 100644 index 000000000..51d8450af --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -0,0 +1,9 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic2.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs new file mode 100644 index 000000000..51be999a6 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs @@ -0,0 +1,23 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +fn is_static(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar(x: &str) -> &dyn Foo { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr new file mode 100644 index 000000000..f721bf394 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -0,0 +1,9 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic3.rs:16:36 + | +LL | fn bar(x: &str) -> &dyn Foo { &() } + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs new file mode 100644 index 000000000..339f3356b --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs @@ -0,0 +1,28 @@ +// Test that `dyn Bar` uses `'static` as the default object +// lifetime bound for the type `XX`. +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box { panic!() } +} + +trait Bar { } + +impl Foo for T { + type Item = dyn Bar; +} + +fn is_static(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'static`, and not `&'x dyn Foo`. +fn bar(x: &str) -> &dyn Foo { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.rs b/tests/ui/object-lifetime/object-lifetime-default-elision.rs new file mode 100644 index 000000000..f7c0261cf --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.rs @@ -0,0 +1,76 @@ +// Test various cases where the old rules under lifetime elision +// yield slightly different results than the new rules. + +#![allow(dead_code)] + +trait SomeTrait { + fn dummy(&self) { } +} + +struct SomeStruct<'a> { + r: Box +} + +fn deref(ss: &T) -> T { + // produces the type of a deref without worrying about whether a + // move out would actually be legal + loop { } +} + +fn load0<'a>(ss: &'a Box) -> Box { + // Under old rules, the fully elaborated types of input/output were: + // + // for<'a,'b> fn(&'a Box) -> Box + // + // Under new rules the result is: + // + // for<'a> fn(&'a Box) -> Box + // + // Therefore, no type error. + + deref(ss) +} + +fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait { + // Under old rules, the fully elaborated types of input/output were: + // + // for<'a,'b> fn(&'a (SomeTrait+'b)) -> &'a (SomeTrait+'a) + // + // Under new rules the result is: + // + // for<'a> fn(&'a (SomeTrait+'a)) -> &'a (SomeTrait+'a) + // + // In both cases, returning `ss` is legal. + + ss +} + +fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + // Same as `load1` but with an explicit name thrown in for fun. + + ss +} + +fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { + // Under old rules, the fully elaborated types of input/output were: + // + // for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a) + // + // Based on the input/output types, the compiler could infer that + // 'c : 'a + // 'b : 'a + // must hold, and therefore it permitted `&'a (Sometrait+'c)` to be + // coerced to `&'b (SomeTrait+'a)`. + // + // Under the newer defaults, though, we get: + // + // for<'a,'b> fn(&'a (SomeTrait+'a)) -> &'b (SomeTrait+'b) + // + // which fails to type check. + + ss + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr new file mode 100644 index 000000000..61e96f59f --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-elision.rs:71:5 + | +LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | ss + | ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs new file mode 100644 index 000000000..f9b3e2238 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs @@ -0,0 +1,37 @@ +// Test various cases where the defaults should lead to errors being +// reported. + +#![allow(dead_code)] + +trait SomeTrait { + fn dummy(&self) { } +} + +struct SomeStruct<'a> { + r: Box +} + +fn load(ss: &mut SomeStruct) -> Box { + // `Box` defaults to a `'static` bound, so this return + // is illegal. + + ss.r + //~^ ERROR lifetime may not live long enough + //~| ERROR cannot move out of +} + +fn store(ss: &mut SomeStruct, b: Box) { + // No error: b is bounded by 'static which outlives the + // (anonymous) lifetime on the struct. + + ss.r = b; +} + +fn store1<'b>(ss: &mut SomeStruct, b: Box) { + // Here we override the lifetimes explicitly, and so naturally we get an error. + + ss.r = b; //~ ERROR explicit lifetime required in the type of `ss` [E0621] +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr new file mode 100644 index 000000000..15b36925c --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -0,0 +1,33 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-from-box-error.rs:18:5 + | +LL | fn load(ss: &mut SomeStruct) -> Box { + | -- has type `&mut SomeStruct<'1>` +... +LL | ss.r + | ^^^^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound + | +LL | fn load(ss: &mut SomeStruct) -> Box { + | ++++ + +error[E0507]: cannot move out of `ss.r` which is behind a mutable reference + --> $DIR/object-lifetime-default-from-box-error.rs:18:5 + | +LL | ss.r + | ^^^^ move occurs because `ss.r` has type `Box`, which does not implement the `Copy` trait + +error[E0621]: explicit lifetime required in the type of `ss` + --> $DIR/object-lifetime-default-from-box-error.rs:33:5 + | +LL | fn store1<'b>(ss: &mut SomeStruct, b: Box) { + | --------------- help: add explicit lifetime `'b` to the type of `ss`: `&mut SomeStruct<'b>` +... +LL | ss.r = b; + | ^^^^ lifetime `'b` required + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0507, E0621. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs b/tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs new file mode 100644 index 000000000..e1a865fa5 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs @@ -0,0 +1,58 @@ +// run-pass +// Test that the lifetime of the enclosing `&` is used for the object +// lifetime bound. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::fmt::Display; + +trait Test { + fn foo(&self) { } +} + +struct Ref<'a,T:'a+?Sized> { + r: &'a T +} + +struct Ref2<'a,'b,T:'a+'b+?Sized> { + a: &'a T, + b: &'b T +} + +struct SomeStruct<'a> { + t: Ref<'a, dyn Test>, + u: Ref<'a, dyn Test+'a>, +} + +fn a<'a>(t: Ref<'a, dyn Test>, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: Ref<'a, dyn Test>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn c<'a>(t: Ref<'a, dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn d<'a>(t: Ref<'a, dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn e<'a>(_: Ref<'a, dyn Display+'static>) {} +fn g<'a, 'b>(_: Ref2<'a, 'b, dyn Display+'static>) {} + + +fn main() { + // Inside a function body, we can just infer all + // lifetimes, to allow Ref<'tmp, Display+'static> + // and Ref2<'tmp, 'tmp, Display+'static>. + let x = &0 as &(dyn Display+'static); + let r: Ref = Ref { r: x }; + let r2: Ref2 = Ref2 { a: x, b: x }; + e(r); + g(r2); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs new file mode 100644 index 000000000..de79eee6a --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs @@ -0,0 +1,20 @@ +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `Box` struct. + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a Box, +} + +fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { + ss.t = t; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr new file mode 100644 index 000000000..7d6f9f39d --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-from-rptr-box-error.rs:15:5 + | +LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { + | -- lifetime `'a` defined here +LL | ss.t = t; + | ^^^^^^^^ assignment requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs new file mode 100644 index 000000000..b61083078 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs @@ -0,0 +1,33 @@ +// run-pass +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `Box` struct. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a Box, + u: &'a Box, +} + +fn a<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +// see also ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs + +fn d<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs new file mode 100644 index 000000000..a09fc03ab --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs @@ -0,0 +1,36 @@ +// run-pass +// Test that the lifetime of the enclosing `&` is used for the object +// lifetime bound. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a mut dyn Test, + u: &'a mut (dyn Test+'a), +} + +fn a<'a>(t: &'a mut dyn Test, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a mut dyn Test, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn c<'a>(t: &'a mut (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn d<'a>(t: &'a mut (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.u = t; +} + + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs new file mode 100644 index 000000000..877486e15 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs @@ -0,0 +1,25 @@ +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `MyBox` struct. + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a MyBox, + u: &'a MyBox, +} + +struct MyBox { + b: Box +} + +fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { + ss.t = t; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr new file mode 100644 index 000000000..2bc8e0978 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:5 + | +LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { + | -- lifetime `'a` defined here +LL | ss.t = t; + | ^^^^^^^^ assignment requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs new file mode 100644 index 000000000..d3e92e162 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs @@ -0,0 +1,37 @@ +// run-pass +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `MyBox` struct. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a MyBox, + u: &'a MyBox, +} + +struct MyBox { + b: Box +} + +fn a<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +// see also ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs + +fn d<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs new file mode 100644 index 000000000..5093b1c27 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs @@ -0,0 +1,42 @@ +// run-pass +// Test that the lifetime of the enclosing `&` is used for the object +// lifetime bound. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::fmt::Display; + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a dyn Test, + u: &'a (dyn Test+'a), +} + +fn a<'a>(t: &'a dyn Test, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a dyn Test, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn c<'a>(t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn d<'a>(t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn e<'a>(_: &'a (dyn Display+'static)) {} + +fn main() { + // Inside a function body, we can just infer both + // lifetimes, to allow &'tmp (Display+'static). + e(&0 as &dyn Display); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-inferred.rs b/tests/ui/object-lifetime/object-lifetime-default-inferred.rs new file mode 100644 index 000000000..8a1156b8f --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-inferred.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that even with prior inferred parameters, object lifetimes of objects after are still +// valid. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] +#![feature(generic_arg_infer)] + +trait Test { + fn foo(&self) { } +} + +struct Foo; +impl Test for Foo {} + +struct SomeStruct<'a> { + t: &'a dyn Test, + u: &'a (dyn Test+'a), +} + +fn a<'a, const N: usize>(_: [u8; N], t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a, T>(_: T, t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn main() { + // Inside a function body, we can just infer both + // lifetimes, to allow &'tmp (Display+'static). + a::<_>([], &Foo as &dyn Test, SomeStruct{t:&Foo,u:&Foo}); + b::<_>(0u8, &Foo as &dyn Test, SomeStruct{t:&Foo,u:&Foo}); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-mybox.rs b/tests/ui/object-lifetime/object-lifetime-default-mybox.rs new file mode 100644 index 000000000..5e6e5e2c0 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-mybox.rs @@ -0,0 +1,37 @@ +// Test a "pass-through" object-lifetime-default that produces errors. + +#![allow(dead_code)] + +trait SomeTrait { + fn dummy(&self) { } +} + +struct MyBox { + r: Box +} + +fn deref(ss: &T) -> T { + // produces the type of a deref without worrying about whether a + // move out would actually be legal + loop { } +} + +fn load0(ss: &MyBox) -> MyBox { + deref(ss) +} + +fn load1<'a,'b>(a: &'a MyBox, + b: &'b MyBox) + -> &'b MyBox +{ + a + //~^ ERROR lifetime may not live long enough +} + +fn load2<'a>(ss: &MyBox) -> MyBox { + load0(ss) + //~^ ERROR borrowed data escapes outside of function +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr b/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr new file mode 100644 index 000000000..a1ef0243e --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-mybox.rs:27:5 + | +LL | fn load1<'a,'b>(a: &'a MyBox, + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/object-lifetime-default-mybox.rs:32:5 + | +LL | fn load2<'a>(ss: &MyBox) -> MyBox { + | -- -- `ss` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | load0(ss) + | ^^^^^^^^^ + | | + | `ss` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/object-lifetime/object-lifetime-default.rs b/tests/ui/object-lifetime/object-lifetime-default.rs new file mode 100644 index 000000000..74f5bb7dd --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default.rs @@ -0,0 +1,50 @@ +#![feature(rustc_attrs)] + +#[rustc_object_lifetime_default] +struct A< + T, //~ ERROR BaseDefault +>(T); + +#[rustc_object_lifetime_default] +struct B< + 'a, + T, //~ ERROR BaseDefault +>(&'a (), T); + +#[rustc_object_lifetime_default] +struct C< + 'a, + T: 'a, //~ ERROR 'a +>(&'a T); + +#[rustc_object_lifetime_default] +struct D< + 'a, + 'b, + T: 'a + 'b, //~ ERROR Ambiguous +>(&'a T, &'b T); + +#[rustc_object_lifetime_default] +struct E< + 'a, + 'b: 'a, + T: 'b, //~ ERROR 'b +>(&'a T, &'b T); + +#[rustc_object_lifetime_default] +struct F< + 'a, + 'b, + T: 'a, //~ ERROR 'a + U: 'b, //~ ERROR 'b +>(&'a T, &'b U); + +#[rustc_object_lifetime_default] +struct G< + 'a, + 'b, + T: 'a, //~ ERROR 'a + U: 'a + 'b, //~ ERROR Ambiguous +>(&'a T, &'b U); + +fn main() {} diff --git a/tests/ui/object-lifetime/object-lifetime-default.stderr b/tests/ui/object-lifetime/object-lifetime-default.stderr new file mode 100644 index 000000000..a58afad3e --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default.stderr @@ -0,0 +1,56 @@ +error: BaseDefault + --> $DIR/object-lifetime-default.rs:5:5 + | +LL | T, + | ^ + +error: BaseDefault + --> $DIR/object-lifetime-default.rs:11:5 + | +LL | T, + | ^ + +error: 'a + --> $DIR/object-lifetime-default.rs:17:5 + | +LL | T: 'a, + | ^ + +error: Ambiguous + --> $DIR/object-lifetime-default.rs:24:5 + | +LL | T: 'a + 'b, + | ^ + +error: 'b + --> $DIR/object-lifetime-default.rs:31:5 + | +LL | T: 'b, + | ^ + +error: 'a + --> $DIR/object-lifetime-default.rs:38:5 + | +LL | T: 'a, + | ^ + +error: 'b + --> $DIR/object-lifetime-default.rs:39:5 + | +LL | U: 'b, + | ^ + +error: 'a + --> $DIR/object-lifetime-default.rs:46:5 + | +LL | T: 'a, + | ^ + +error: Ambiguous + --> $DIR/object-lifetime-default.rs:47:5 + | +LL | U: 'a + 'b, + | ^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/object-pointer-types.rs b/tests/ui/object-pointer-types.rs new file mode 100644 index 000000000..760a50e5b --- /dev/null +++ b/tests/ui/object-pointer-types.rs @@ -0,0 +1,30 @@ +trait Foo { + fn borrowed(&self); + fn borrowed_mut(&mut self); + + fn owned(self: Box); +} + +fn borrowed_receiver(x: &dyn Foo) { + x.borrowed(); + x.borrowed_mut(); // See [1] + x.owned(); //~ ERROR no method named `owned` found +} + +fn borrowed_mut_receiver(x: &mut dyn Foo) { + x.borrowed(); + x.borrowed_mut(); + x.owned(); //~ ERROR no method named `owned` found +} + +fn owned_receiver(x: Box) { + x.borrowed(); + x.borrowed_mut(); // See [1] + x.managed(); //~ ERROR no method named `managed` found + x.owned(); +} + +fn main() {} + +// [1]: These cases are illegal, but the error is not detected +// until borrowck, so see the test borrowck-object-mutability.rs diff --git a/tests/ui/object-pointer-types.stderr b/tests/ui/object-pointer-types.stderr new file mode 100644 index 000000000..a477425ed --- /dev/null +++ b/tests/ui/object-pointer-types.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope + --> $DIR/object-pointer-types.rs:11:7 + | +LL | fn owned(self: Box); + | --------- the method might not be found because of this arbitrary self type +... +LL | x.owned(); + | ^^^^^ method not found in `&dyn Foo` + +error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope + --> $DIR/object-pointer-types.rs:17:7 + | +LL | fn owned(self: Box); + | --------- the method might not be found because of this arbitrary self type +... +LL | x.owned(); + | ^^^^^ method not found in `&mut dyn Foo` + +error[E0599]: no method named `managed` found for struct `Box<(dyn Foo + 'static)>` in the current scope + --> $DIR/object-pointer-types.rs:23:7 + | +LL | x.managed(); + | ^^^^^^^ method not found in `Box<(dyn Foo + 'static)>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/object-safety/issue-102762.rs b/tests/ui/object-safety/issue-102762.rs new file mode 100644 index 000000000..4f4c36345 --- /dev/null +++ b/tests/ui/object-safety/issue-102762.rs @@ -0,0 +1,26 @@ +// compile-flags: --crate-type=lib +// This test checks that the `where_clauses_object_safety` lint does not cause +// other object safety *hard errors* to be suppressed, because we currently +// only emit one object safety error per trait... + +use std::future::Future; +use std::pin::Pin; + +pub trait Fetcher: Send + Sync { + fn get<'a>(self: &'a Box) -> Pin> + 'a>> + where + Self: Sync, + { + todo!() + } +} + +fn fetcher() -> Box { + //~^ ERROR the trait `Fetcher` cannot be made into an object + todo!() +} + +pub fn foo() { + let fetcher = fetcher(); + let _ = fetcher.get(); +} diff --git a/tests/ui/object-safety/issue-102762.stderr b/tests/ui/object-safety/issue-102762.stderr new file mode 100644 index 000000000..5041ebe77 --- /dev/null +++ b/tests/ui/object-safety/issue-102762.stderr @@ -0,0 +1,20 @@ +error[E0038]: the trait `Fetcher` cannot be made into an object + --> $DIR/issue-102762.rs:18:21 + | +LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> + | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` +... +LL | fn fetcher() -> Box { + | ^^^^^^^^^^^ `Fetcher` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-102762.rs:10:22 + | +LL | pub trait Fetcher: Send + Sync { + | ------- this trait cannot be made into an object... +LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> + | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/issue-102933.rs b/tests/ui/object-safety/issue-102933.rs new file mode 100644 index 000000000..843391cff --- /dev/null +++ b/tests/ui/object-safety/issue-102933.rs @@ -0,0 +1,25 @@ +// check-pass + +use std::future::Future; + +pub trait Service { + type Response; + type Future: Future; +} + +pub trait A1: Service {} + +pub trait A2: Service>> + A1 { + fn foo(&self) {} +} + +pub trait B1: Service>> {} + +pub trait B2: Service + B1 { + fn foo(&self) {} +} + +fn main() { + let x: &dyn A2 = todo!(); + let x: &dyn B2 = todo!(); +} diff --git a/tests/ui/object-safety/issue-106247.rs b/tests/ui/object-safety/issue-106247.rs new file mode 100644 index 000000000..64bf59e5d --- /dev/null +++ b/tests/ui/object-safety/issue-106247.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(where_clauses_object_safety)] + +pub trait Trait { + fn method(&self) where Self: Sync; +} + +fn main() {} diff --git a/tests/ui/object-safety/issue-19538.rs b/tests/ui/object-safety/issue-19538.rs new file mode 100644 index 000000000..7054ef41b --- /dev/null +++ b/tests/ui/object-safety/issue-19538.rs @@ -0,0 +1,20 @@ +trait Foo { + fn foo(&self, val: T); +} + +trait Bar: Foo { } + +pub struct Thing; + +impl Foo for Thing { + fn foo(&self, val: T) { } +} + +impl Bar for Thing { } + +fn main() { + let mut thing = Thing; + let test: &mut dyn Bar = &mut thing; + //~^ ERROR E0038 + //~| ERROR E0038 +} diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/object-safety/issue-19538.stderr new file mode 100644 index 000000000..8420637b3 --- /dev/null +++ b/tests/ui/object-safety/issue-19538.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-19538.rs:17:15 + | +LL | let test: &mut dyn Bar = &mut thing; + | ^^^^^^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-19538.rs:2:8 + | +LL | fn foo(&self, val: T); + | ^^^ ...because method `foo` has generic type parameters +... +LL | trait Bar: Foo { } + | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-19538.rs:17:30 + | +LL | let test: &mut dyn Bar = &mut thing; + | ^^^^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-19538.rs:2:8 + | +LL | fn foo(&self, val: T); + | ^^^ ...because method `foo` has generic type parameters +... +LL | trait Bar: Foo { } + | --- this trait cannot be made into an object... + = help: consider moving `foo` to another trait + = note: required for `&mut Thing` to implement `CoerceUnsized<&mut dyn Bar>` + = note: required by cast to type `&mut dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr b/tests/ui/object-safety/object-safety-associated-consts.curr.stderr new file mode 100644 index 000000000..5f94c9284 --- /dev/null +++ b/tests/ui/object-safety/object-safety-associated-consts.curr.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:12:31 + | +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-associated-consts.rs:9:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..f44de07d5 --- /dev/null +++ b/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr @@ -0,0 +1,20 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:14:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-associated-consts.rs:9:11 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | const X: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `X` to another trait + = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/object-safety/object-safety-associated-consts.rs new file mode 100644 index 000000000..e1a772e5a --- /dev/null +++ b/tests/ui/object-safety/object-safety-associated-consts.rs @@ -0,0 +1,19 @@ +// Check that we correctly prevent users from making trait objects +// from traits with associated consts. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Bar { + const X: usize; +} + +fn make_bar(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-bounds.rs b/tests/ui/object-safety/object-safety-bounds.rs new file mode 100644 index 000000000..44bd36932 --- /dev/null +++ b/tests/ui/object-safety/object-safety-bounds.rs @@ -0,0 +1,12 @@ +// Traits with bounds mentioning `Self` are not object safe + +trait X { + type U: PartialEq; +} + +fn f() -> Box> { + //~^ ERROR the trait `X` cannot be made into an object + loop {} +} + +fn main() {} diff --git a/tests/ui/object-safety/object-safety-bounds.stderr b/tests/ui/object-safety/object-safety-bounds.stderr new file mode 100644 index 000000000..29ffb5448 --- /dev/null +++ b/tests/ui/object-safety/object-safety-bounds.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/object-safety-bounds.rs:7:15 + | +LL | fn f() -> Box> { + | ^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-bounds.rs:4:13 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type U: PartialEq; + | ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.rs b/tests/ui/object-safety/object-safety-by-value-self-use.rs new file mode 100644 index 000000000..8e93c5382 --- /dev/null +++ b/tests/ui/object-safety/object-safety-by-value-self-use.rs @@ -0,0 +1,18 @@ +// Check that while a trait with by-value self is object-safe, we +// can't actually invoke it from an object (yet...?). + +#![feature(rustc_attrs)] + +trait Bar { + fn bar(self); +} + +trait Baz { + fn baz(self: Self); +} + +fn use_bar(t: Box) { + t.bar() //~ ERROR cannot move a value of type `dyn Bar` +} + +fn main() { } diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.stderr b/tests/ui/object-safety/object-safety-by-value-self-use.stderr new file mode 100644 index 000000000..94fdcdf26 --- /dev/null +++ b/tests/ui/object-safety/object-safety-by-value-self-use.stderr @@ -0,0 +1,9 @@ +error[E0161]: cannot move a value of type `dyn Bar` + --> $DIR/object-safety-by-value-self-use.rs:15:5 + | +LL | t.bar() + | ^^^^^^^ the size of `dyn Bar` cannot be statically determined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0161`. diff --git a/tests/ui/object-safety/object-safety-by-value-self.rs b/tests/ui/object-safety/object-safety-by-value-self.rs new file mode 100644 index 000000000..c74a4d1cb --- /dev/null +++ b/tests/ui/object-safety/object-safety-by-value-self.rs @@ -0,0 +1,46 @@ +// Check that a trait with by-value self is considered object-safe. + +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +#![allow(trivial_casts)] + +trait Bar { + fn bar(self); +} + +trait Baz { + fn baz(self: Self); +} + +trait Quux { + // Legal because of the where clause: + fn baz(self: Self) where Self : Sized; +} + +fn make_bar(t: &T) -> &dyn Bar { + t // legal +} + +fn make_bar_explicit(t: &T) -> &dyn Bar { + t as &dyn Bar // legal +} + +fn make_baz(t: &T) -> &dyn Baz { + t // legal +} + +fn make_baz_explicit(t: &T) -> &dyn Baz { + t as &dyn Baz // legal +} + +fn make_quux(t: &T) -> &dyn Quux { + t +} + +fn make_quux_explicit(t: &T) -> &dyn Quux { + t as &dyn Quux +} + + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-generics.curr.stderr b/tests/ui/object-safety/object-safety-generics.curr.stderr new file mode 100644 index 000000000..458103752 --- /dev/null +++ b/tests/ui/object-safety/object-safety-generics.curr.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:18:31 + | +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:24:40 + | +LL | fn make_bar_explicit(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..9a2d472d5 --- /dev/null +++ b/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:20:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>` + = note: required by cast to type `&dyn Bar` + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:26:5 + | +LL | t as &dyn Bar + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-generics.rs:10:8 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, t: T); + | ^^^ ...because method `bar` has generic type parameters + = help: consider moving `bar` to another trait + = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>` + = note: required by cast to type `&dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/object-safety/object-safety-generics.rs new file mode 100644 index 000000000..63dcd1699 --- /dev/null +++ b/tests/ui/object-safety/object-safety-generics.rs @@ -0,0 +1,39 @@ +// Check that we correctly prevent users from making trait objects +// from traits with generic methods, unless `where Self : Sized` is +// present. +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + + +trait Bar { + fn bar(&self, t: T); +} + +trait Quux { + fn bar(&self, t: T) + where Self : Sized; +} + +fn make_bar(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_bar_explicit(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t as &dyn Bar + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_quux(t: &T) -> &dyn Quux { + t +} + +fn make_quux_explicit(t: &T) -> &dyn Quux { + t as &dyn Quux +} + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-issue-22040.rs b/tests/ui/object-safety/object-safety-issue-22040.rs new file mode 100644 index 000000000..1fc5c5442 --- /dev/null +++ b/tests/ui/object-safety/object-safety-issue-22040.rs @@ -0,0 +1,42 @@ +// Regression test for #22040. + +use std::fmt::Debug; + +trait Expr: Debug + PartialEq { + fn print_element_count(&self); +} + +//#[derive(PartialEq)] +#[derive(Debug)] +struct SExpr<'x> { + elements: Vec>, + //~^ ERROR E0038 +} + +impl<'x> PartialEq for SExpr<'x> { + fn eq(&self, other:&SExpr<'x>) -> bool { + println!("L1: {} L2: {}", self.elements.len(), other.elements.len()); + + let result = self.elements.len() == other.elements.len(); + + println!("Got compare {}", result); + return result; + } +} + +impl <'x> SExpr<'x> { + fn new() -> SExpr<'x> { return SExpr{elements: Vec::new(),}; } +} + +impl <'x> Expr for SExpr<'x> { + fn print_element_count(&self) { + println!("element count: {}", self.elements.len()); + } +} + +fn main() { + let a: Box = Box::new(SExpr::new()); + let b: Box = Box::new(SExpr::new()); + + // assert_eq!(a , b); +} diff --git a/tests/ui/object-safety/object-safety-issue-22040.stderr b/tests/ui/object-safety/object-safety-issue-22040.stderr new file mode 100644 index 000000000..0262d5362 --- /dev/null +++ b/tests/ui/object-safety/object-safety-issue-22040.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Expr` cannot be made into an object + --> $DIR/object-safety-issue-22040.rs:12:23 + | +LL | elements: Vec>, + | ^^^^^^^^^^^^^ `Expr` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-issue-22040.rs:5:21 + | +LL | trait Expr: Debug + PartialEq { + | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr b/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr new file mode 100644 index 000000000..de430a89b --- /dev/null +++ b/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:22:31 + | +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:11:22 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, x: &Self); + | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:28:31 + | +LL | fn make_baz(t: &T) -> &dyn Baz { + | ^^^^^^^ `Baz` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:15:22 + | +LL | trait Baz { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> Self; + | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..40a298bd1 --- /dev/null +++ b/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:24:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:11:22 + | +LL | trait Bar { + | --- this trait cannot be made into an object... +LL | fn bar(&self, x: &Self); + | ^^^^^ ...because method `bar` references the `Self` type in this parameter + = help: consider moving `bar` to another trait + = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>` + = note: required by cast to type `&dyn Bar` + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:30:5 + | +LL | t + | ^ `Baz` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-mentions-Self.rs:15:22 + | +LL | trait Baz { + | --- this trait cannot be made into an object... +LL | fn baz(&self) -> Self; + | ^^^^ ...because method `baz` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = note: required for `&T` to implement `CoerceUnsized<&dyn Baz>` + = note: required by cast to type `&dyn Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/object-safety/object-safety-mentions-Self.rs new file mode 100644 index 000000000..412d16ff3 --- /dev/null +++ b/tests/ui/object-safety/object-safety-mentions-Self.rs @@ -0,0 +1,42 @@ +// Check that we correctly prevent users from making trait objects +// form traits that make use of `Self` in an argument or return +// position, unless `where Self : Sized` is present.. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + + +trait Bar { + fn bar(&self, x: &Self); +} + +trait Baz { + fn baz(&self) -> Self; +} + +trait Quux { + fn quux(&self, s: &Self) -> Self where Self : Sized; +} + +fn make_bar(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_baz(t: &T) -> &dyn Baz { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn make_quux(t: &T) -> &dyn Quux { + t +} + +fn make_quux_explicit(t: &T) -> &dyn Quux { + t as &dyn Quux +} + +fn main() {} diff --git a/tests/ui/object-safety/object-safety-no-static.curr.stderr b/tests/ui/object-safety/object-safety-no-static.curr.stderr new file mode 100644 index 000000000..1b025229e --- /dev/null +++ b/tests/ui/object-safety/object-safety-no-static.curr.stderr @@ -0,0 +1,25 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:12:22 + | +LL | fn diverges() -> Box { + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-no-static.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo() {} + | ^^^ ...because associated function `foo` has no `self` parameter +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) {} + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..da87b58c9 --- /dev/null +++ b/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:22:27 + | +LL | let b: Box = Box::new(Bar); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-no-static.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo() {} + | ^^^ ...because associated function `foo` has no `self` parameter + = note: required for `Box` to implement `CoerceUnsized>` + = note: required by cast to type `Box` +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) {} + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized {} + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/object-safety/object-safety-no-static.rs new file mode 100644 index 000000000..03b622174 --- /dev/null +++ b/tests/ui/object-safety/object-safety-no-static.rs @@ -0,0 +1,24 @@ +// Check that we correctly prevent users from making trait objects +// from traits with static methods. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Foo { + fn foo() {} +} + +fn diverges() -> Box { + //[curr]~^ ERROR E0038 + loop { } +} + +struct Bar; + +impl Foo for Bar {} + +fn main() { + let b: Box = Box::new(Bar); + //[object_safe_for_dispatch]~^ ERROR E0038 +} diff --git a/tests/ui/object-safety/object-safety-phantom-fn.rs b/tests/ui/object-safety/object-safety-phantom-fn.rs new file mode 100644 index 000000000..3ffeb81c1 --- /dev/null +++ b/tests/ui/object-safety/object-safety-phantom-fn.rs @@ -0,0 +1,22 @@ +// Check that `Self` appearing in a phantom fn does not make a trait not object safe. + +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] + +trait Baz { +} + +trait Bar { +} + +fn make_bar>(t: &T) -> &dyn Bar { + t +} + +fn make_baz(t: &T) -> &dyn Baz { + t +} + + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-sized-2.curr.stderr b/tests/ui/object-safety/object-safety-sized-2.curr.stderr new file mode 100644 index 000000000..b01926412 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized-2.curr.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:14:31 + | +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized-2.rs:9:18 + | +LL | trait Bar + | --- this trait cannot be made into an object... +LL | where Self : Sized + | ^^^^^ ...because it requires `Self: Sized` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..6c29c8d5f --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:16:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized-2.rs:9:18 + | +LL | trait Bar + | --- this trait cannot be made into an object... +LL | where Self : Sized + | ^^^^^ ...because it requires `Self: Sized` + = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/object-safety/object-safety-sized-2.rs new file mode 100644 index 000000000..1e79b8cd9 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized-2.rs @@ -0,0 +1,21 @@ +// Check that we correctly prevent users from making trait objects +// from traits where `Self : Sized`. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Bar + where Self : Sized +{ + fn bar(&self, t: T); +} + +fn make_bar(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-sized.curr.stderr b/tests/ui/object-safety/object-safety-sized.curr.stderr new file mode 100644 index 000000000..974813121 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized.curr.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:12:31 + | +LL | fn make_bar(t: &T) -> &dyn Bar { + | ^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized.rs:8:13 + | +LL | trait Bar : Sized { + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..70a44ed61 --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:14:5 + | +LL | t + | ^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-sized.rs:8:13 + | +LL | trait Bar : Sized { + | --- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/object-safety/object-safety-sized.rs new file mode 100644 index 000000000..b424b892d --- /dev/null +++ b/tests/ui/object-safety/object-safety-sized.rs @@ -0,0 +1,19 @@ +// Check that we correctly prevent users from making trait objects +// from traits where `Self : Sized`. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +trait Bar : Sized { + fn bar(&self, t: T); +} + +fn make_bar(t: &T) -> &dyn Bar { + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 +} + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs new file mode 100644 index 000000000..14e00d2ef --- /dev/null +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs @@ -0,0 +1,15 @@ +//~ ERROR the parameter type `Self` may not live long enough + +trait GatTrait { + type Gat<'a> + where + Self: 'a; +} + +trait SuperTrait: for<'a> GatTrait = T> { + fn c(&self) -> dyn SuperTrait; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `SuperTrait` cannot be made into an object +} + +fn main() {} diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr new file mode 100644 index 000000000..f05b0cd65 --- /dev/null +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr @@ -0,0 +1,43 @@ +error[E0311]: the parameter type `Self` may not live long enough + | + = help: consider adding an explicit lifetime bound `Self: 'a`... + = note: ...so that the type `Self` will meet its required lifetime bounds... +note: ...that is required by this bound + --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15 + | +LL | Self: 'a; + | ^^ + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 + | +LL | trait SuperTrait: for<'a> GatTrait = T> { + | ---------- in this trait +LL | fn c(&self) -> dyn SuperTrait; + | ^^^^^^^^^^^^^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn c(&self) -> Self; + | ~~~~ + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 + | +LL | fn c(&self) -> dyn SuperTrait; + | ^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-supertrait-mentions-GAT.rs:4:10 + | +LL | type Gat<'a> + | ^^^ ...because it contains the generic associated type `Gat` +... +LL | trait SuperTrait: for<'a> GatTrait = T> { + | ---------- this trait cannot be made into an object... + = help: consider moving `Gat` to another trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0311. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs new file mode 100644 index 000000000..2445b33c8 --- /dev/null +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs @@ -0,0 +1,21 @@ +// Check that we correctly prevent users from making trait objects +// form traits that make use of `Self` in an argument or return position. + +trait Bar { + fn bar(&self, x: &T); +} + +trait Baz : Bar { +} + +fn make_bar>(t: &T) -> &dyn Bar { + t +} + +fn make_baz(t: &T) -> &dyn Baz { + //~^ ERROR E0038 + t +} + +fn main() { +} diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr new file mode 100644 index 000000000..a106ab995 --- /dev/null +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-supertrait-mentions-Self.rs:15:31 + | +LL | fn make_baz(t: &T) -> &dyn Baz { + | ^^^^^^^ `Baz` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 + | +LL | trait Baz : Bar { + | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/objects-coerce-freeze-borrored.rs b/tests/ui/objects-coerce-freeze-borrored.rs new file mode 100644 index 000000000..704d77480 --- /dev/null +++ b/tests/ui/objects-coerce-freeze-borrored.rs @@ -0,0 +1,40 @@ +// run-pass +// Test that we can coerce an `@Object` to an `&Object` + + +trait Foo { + fn foo(&self) -> usize; + fn bar(&mut self) -> usize; +} + +impl Foo for usize { + fn foo(&self) -> usize { + *self + } + + fn bar(&mut self) -> usize { + *self += 1; + *self + } +} + +fn do_it_mut(obj: &mut dyn Foo) { + let x = obj.bar(); + let y = obj.foo(); + assert_eq!(x, y); + + do_it_imm(obj, y); +} + +fn do_it_imm(obj: &dyn Foo, v: usize) { + let y = obj.foo(); + assert_eq!(v, y); +} + +pub fn main() { + let mut x: usize = 22; + let obj = &mut x as &mut dyn Foo; + do_it_mut(obj); + do_it_imm(obj, 23); + do_it_mut(obj); +} diff --git a/tests/ui/obsolete-in-place/bad.rs b/tests/ui/obsolete-in-place/bad.rs new file mode 100644 index 000000000..a491bb21a --- /dev/null +++ b/tests/ui/obsolete-in-place/bad.rs @@ -0,0 +1,11 @@ +// Check that `<-` and `in` syntax gets a hard error. + +fn foo() { + let (x, y) = (0, 0); + x <- y; //~ ERROR unexpected token: `<-` +} + +fn main() { + let (foo, bar) = (0, 0); + in(foo) { bar }; //~ ERROR expected expression, found keyword `in` +} diff --git a/tests/ui/obsolete-in-place/bad.stderr b/tests/ui/obsolete-in-place/bad.stderr new file mode 100644 index 000000000..363dfb776 --- /dev/null +++ b/tests/ui/obsolete-in-place/bad.stderr @@ -0,0 +1,19 @@ +error: unexpected token: `<-` + --> $DIR/bad.rs:5:7 + | +LL | x <- y; + | ^^ + | +help: if you meant to write a comparison against a negative value, add a space in between `<` and `-` + | +LL | x < - y; + | ~~~ + +error: expected expression, found keyword `in` + --> $DIR/bad.rs:10:5 + | +LL | in(foo) { bar }; + | ^^ expected expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/occurs-check-2.rs new file mode 100644 index 000000000..f36682a3d --- /dev/null +++ b/tests/ui/occurs-check-2.rs @@ -0,0 +1,10 @@ +fn main() { + + let f; + let g; + + g = f; + f = Box::new(g); + //~^ ERROR mismatched types + //~| cyclic type of infinite size +} diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/occurs-check-2.stderr new file mode 100644 index 000000000..b68c3fa5b --- /dev/null +++ b/tests/ui/occurs-check-2.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/occurs-check-2.rs:7:9 + | +LL | f = Box::new(g); + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(g); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/occurs-check-3.rs b/tests/ui/occurs-check-3.rs new file mode 100644 index 000000000..9c0420401 --- /dev/null +++ b/tests/ui/occurs-check-3.rs @@ -0,0 +1,5 @@ +// From Issue #778 + +enum Clam { A(T) } +fn main() { let c; c = Clam::A(c); match c { Clam::A::(_) => { } } } +//~^ ERROR mismatched types diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/occurs-check-3.stderr new file mode 100644 index 000000000..04c404d54 --- /dev/null +++ b/tests/ui/occurs-check-3.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/occurs-check-3.rs:4:24 + | +LL | fn main() { let c; c = Clam::A(c); match c { Clam::A::(_) => { } } } + | ^^^^^^^^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/occurs-check.rs b/tests/ui/occurs-check.rs new file mode 100644 index 000000000..aec52d839 --- /dev/null +++ b/tests/ui/occurs-check.rs @@ -0,0 +1,8 @@ +fn main() { + + let f; + + f = Box::new(f); + //~^ ERROR mismatched types + //~| cyclic type of infinite size +} diff --git a/tests/ui/occurs-check.stderr b/tests/ui/occurs-check.stderr new file mode 100644 index 000000000..fdbbdc3ab --- /dev/null +++ b/tests/ui/occurs-check.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/occurs-check.rs:5:9 + | +LL | f = Box::new(f); + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(f); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/on-unimplemented/auxiliary/no_debug.rs b/tests/ui/on-unimplemented/auxiliary/no_debug.rs new file mode 100644 index 000000000..fd3dc0abd --- /dev/null +++ b/tests/ui/on-unimplemented/auxiliary/no_debug.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +pub struct Bar; diff --git a/tests/ui/on-unimplemented/bad-annotation.rs b/tests/ui/on-unimplemented/bad-annotation.rs new file mode 100644 index 000000000..f05436b8c --- /dev/null +++ b/tests/ui/on-unimplemented/bad-annotation.rs @@ -0,0 +1,64 @@ +// ignore-tidy-linelength + +#![feature(rustc_attrs)] + +#![allow(unused)] + +#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] +trait Foo +{} + +#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"] +trait MyFromIterator { + /// Builds a container with elements from an external iterator. + fn my_from_iter>(iterator: T) -> Self; +} + +#[rustc_on_unimplemented] +//~^ ERROR malformed `rustc_on_unimplemented` attribute +trait BadAnnotation1 +{} + +#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] +//~^ ERROR there is no parameter `C` on trait `BadAnnotation2` +trait BadAnnotation2 +{} + +#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] +//~^ only named substitution parameters are allowed +trait BadAnnotation3 +{} + +#[rustc_on_unimplemented(lorem="")] +//~^ this attribute must have a valid +trait BadAnnotation4 {} + +#[rustc_on_unimplemented(lorem(ipsum(dolor)))] +//~^ this attribute must have a valid +trait BadAnnotation5 {} + +#[rustc_on_unimplemented(message="x", message="y")] +//~^ this attribute must have a valid +trait BadAnnotation6 {} + +#[rustc_on_unimplemented(message="x", on(desugared, message="y"))] +//~^ this attribute must have a valid +trait BadAnnotation7 {} + +#[rustc_on_unimplemented(on(), message="y")] +//~^ empty `on`-clause +trait BadAnnotation8 {} + +#[rustc_on_unimplemented(on="x", message="y")] +//~^ this attribute must have a valid +trait BadAnnotation9 {} + +#[rustc_on_unimplemented(on(x="y"), message="y")] +trait BadAnnotation10 {} + +#[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")] +//~^ this attribute must have a valid +trait BadAnnotation11 {} + +pub fn main() { +} diff --git a/tests/ui/on-unimplemented/bad-annotation.stderr b/tests/ui/on-unimplemented/bad-annotation.stderr new file mode 100644 index 000000000..a8d3c8680 --- /dev/null +++ b/tests/ui/on-unimplemented/bad-annotation.stderr @@ -0,0 +1,83 @@ +error: malformed `rustc_on_unimplemented` attribute input + --> $DIR/bad-annotation.rs:17:1 + | +LL | #[rustc_on_unimplemented] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL | #[rustc_on_unimplemented = "message"] + | +LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")] + | + +error[E0230]: there is no parameter `C` on trait `BadAnnotation2` + --> $DIR/bad-annotation.rs:22:1 + | +LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0231]: only named substitution parameters are allowed + --> $DIR/bad-annotation.rs:27:1 + | +LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0232]: this attribute must have a valid value + --> $DIR/bad-annotation.rs:32:26 + | +LL | #[rustc_on_unimplemented(lorem="")] + | ^^^^^^^^ expected value here + | + = note: eg `#[rustc_on_unimplemented(message="foo")]` + +error[E0232]: this attribute must have a valid value + --> $DIR/bad-annotation.rs:36:26 + | +LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))] + | ^^^^^^^^^^^^^^^^^^^ expected value here + | + = note: eg `#[rustc_on_unimplemented(message="foo")]` + +error[E0232]: this attribute must have a valid value + --> $DIR/bad-annotation.rs:40:39 + | +LL | #[rustc_on_unimplemented(message="x", message="y")] + | ^^^^^^^^^^^ expected value here + | + = note: eg `#[rustc_on_unimplemented(message="foo")]` + +error[E0232]: this attribute must have a valid value + --> $DIR/bad-annotation.rs:44:39 + | +LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here + | + = note: eg `#[rustc_on_unimplemented(message="foo")]` + +error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]` + --> $DIR/bad-annotation.rs:48:26 + | +LL | #[rustc_on_unimplemented(on(), message="y")] + | ^^^^ empty on-clause here + +error[E0232]: this attribute must have a valid value + --> $DIR/bad-annotation.rs:52:26 + | +LL | #[rustc_on_unimplemented(on="x", message="y")] + | ^^^^^^ expected value here + | + = note: eg `#[rustc_on_unimplemented(message="foo")]` + +error[E0232]: this attribute must have a valid value + --> $DIR/bad-annotation.rs:59:40 + | +LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here + | + = note: eg `#[rustc_on_unimplemented(message="foo")]` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0230, E0231, E0232. +For more information about an error, try `rustc --explain E0230`. diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.rs b/tests/ui/on-unimplemented/expected-comma-found-token.rs new file mode 100644 index 000000000..8fb34f211 --- /dev/null +++ b/tests/ui/on-unimplemented/expected-comma-found-token.rs @@ -0,0 +1,13 @@ +// Tests that two closures cannot simultaneously have mutable +// access to the variable, whether that mutable access be used +// for direct assignment or for taking mutable ref. Issue #6801. + +#![feature(rustc_attrs)] + +#[rustc_on_unimplemented( + message="the message" + label="the label" //~ ERROR expected `,`, found `label` +)] +trait T {} + +fn main() { } diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.stderr b/tests/ui/on-unimplemented/expected-comma-found-token.stderr new file mode 100644 index 000000000..048b72ee3 --- /dev/null +++ b/tests/ui/on-unimplemented/expected-comma-found-token.stderr @@ -0,0 +1,10 @@ +error: expected `,`, found `label` + --> $DIR/expected-comma-found-token.rs:9:5 + | +LL | message="the message" + | - expected `,` +LL | label="the label" + | ^^^^^ unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs new file mode 100644 index 000000000..3cc50e349 --- /dev/null +++ b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.rs @@ -0,0 +1,8 @@ +// Test that `#[rustc_on_unimplemented]` is gated by `rustc_attrs` feature gate. + +#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] +//~^ ERROR this is an internal attribute that will never be stable +trait Foo +{} + +fn main() {} diff --git a/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr new file mode 100644 index 000000000..a4b33963f --- /dev/null +++ b/tests/ui/on-unimplemented/feature-gate-on-unimplemented.stderr @@ -0,0 +1,11 @@ +error[E0658]: this is an internal attribute that will never be stable + --> $DIR/feature-gate-on-unimplemented.rs:3:1 + | +LL | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/on-unimplemented/impl-substs.rs b/tests/ui/on-unimplemented/impl-substs.rs new file mode 100644 index 000000000..fe9c50ec3 --- /dev/null +++ b/tests/ui/on-unimplemented/impl-substs.rs @@ -0,0 +1,15 @@ +#![feature(rustc_attrs)] + +trait Foo { + fn foo(self); +} + +#[rustc_on_unimplemented = "an impl did not match: {A} {B} {C}"] +impl Foo for (A, B, C) { + fn foo(self) {} +} + +fn main() { + Foo::::foo((1i32, 1i32, 1i32)); + //~^ ERROR the trait bound `(i32, i32, i32): Foo` is not satisfied +} diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr new file mode 100644 index 000000000..a0fad0acd --- /dev/null +++ b/tests/ui/on-unimplemented/impl-substs.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(i32, i32, i32): Foo` is not satisfied + --> $DIR/impl-substs.rs:13:23 + | +LL | Foo::::foo((1i32, 1i32, 1i32)); + | ----------------- ^^^^^^^^^^^^^^^^^^ an impl did not match: usize _ _ + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is not implemented for `(i32, i32, i32)` + = help: the trait `Foo` is implemented for `(A, B, C)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/issue-104140.rs b/tests/ui/on-unimplemented/issue-104140.rs new file mode 100644 index 000000000..ade3f7270 --- /dev/null +++ b/tests/ui/on-unimplemented/issue-104140.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +trait Foo {} + +#[rustc_on_unimplemented] //~ ERROR malformed `rustc_on_unimplemented` attribute input +impl Foo for u32 {} + +fn main() {} diff --git a/tests/ui/on-unimplemented/issue-104140.stderr b/tests/ui/on-unimplemented/issue-104140.stderr new file mode 100644 index 000000000..ddb1f50f0 --- /dev/null +++ b/tests/ui/on-unimplemented/issue-104140.stderr @@ -0,0 +1,15 @@ +error: malformed `rustc_on_unimplemented` attribute input + --> $DIR/issue-104140.rs:5:1 + | +LL | #[rustc_on_unimplemented] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: the following are the possible correct uses + | +LL | #[rustc_on_unimplemented = "message"] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/on-unimplemented/multiple-impls.rs b/tests/ui/on-unimplemented/multiple-impls.rs new file mode 100644 index 000000000..a32fd4566 --- /dev/null +++ b/tests/ui/on-unimplemented/multiple-impls.rs @@ -0,0 +1,45 @@ +// Test if the on_unimplemented message override works + +#![feature(rustc_attrs)] + + +struct Foo(T); +struct Bar(T); + +#[rustc_on_unimplemented = "trait message"] +trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +#[rustc_on_unimplemented = "on impl for Foo"] +impl Index> for [i32] { + type Output = i32; + fn index(&self, _index: Foo) -> &i32 { + loop {} + } +} + +#[rustc_on_unimplemented = "on impl for Bar"] +impl Index> for [i32] { + type Output = i32; + fn index(&self, _index: Bar) -> &i32 { + loop {} + } +} + + +fn main() { + Index::index(&[] as &[i32], 2u32); + //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 + Index::index(&[] as &[i32], Foo(2u32)); + //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 + Index::index(&[] as &[i32], Bar(2u32)); + //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 +} diff --git a/tests/ui/on-unimplemented/multiple-impls.stderr b/tests/ui/on-unimplemented/multiple-impls.stderr new file mode 100644 index 000000000..d628b159a --- /dev/null +++ b/tests/ui/on-unimplemented/multiple-impls.stderr @@ -0,0 +1,108 @@ +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:33:33 + | +LL | Index::index(&[] as &[i32], 2u32); + | ------------ ^^^^ trait message + | | + | required by a bound introduced by this call + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:33:5 + | +LL | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:37:33 + | +LL | Index::index(&[] as &[i32], Foo(2u32)); + | ------------ ^^^^^^^^^ on impl for Foo + | | + | required by a bound introduced by this call + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:37:5 + | +LL | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:41:33 + | +LL | Index::index(&[] as &[i32], Bar(2u32)); + | ------------ ^^^^^^^^^ on impl for Bar + | | + | required by a bound introduced by this call + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:41:5 + | +LL | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/multiple-impls.rs:33:5 + | +LL | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^ trait message + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:37:5 + | +LL | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error[E0277]: the trait bound `[i32]: Index>` is not satisfied + --> $DIR/multiple-impls.rs:41:5 + | +LL | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index>` is not implemented for `[i32]` + = help: the following other types implement trait `Index`: + <[i32] as Index>> + <[i32] as Index>> + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/no-debug.rs b/tests/ui/on-unimplemented/no-debug.rs new file mode 100644 index 000000000..bdc80c5b3 --- /dev/null +++ b/tests/ui/on-unimplemented/no-debug.rs @@ -0,0 +1,16 @@ +// aux-build:no_debug.rs + +extern crate no_debug; + +use no_debug::Bar; + +struct Foo; + +fn main() { + println!("{:?} {:?}", Foo, Bar); + println!("{} {}", Foo, Bar); +} +//~^^^ ERROR `Foo` doesn't implement `Debug` +//~| ERROR `Bar` doesn't implement `Debug` +//~^^^^ ERROR `Foo` doesn't implement `std::fmt::Display` +//~| ERROR `Bar` doesn't implement `std::fmt::Display` diff --git a/tests/ui/on-unimplemented/no-debug.stderr b/tests/ui/on-unimplemented/no-debug.stderr new file mode 100644 index 000000000..1035da54d --- /dev/null +++ b/tests/ui/on-unimplemented/no-debug.stderr @@ -0,0 +1,46 @@ +error[E0277]: `Foo` doesn't implement `Debug` + --> $DIR/no-debug.rs:10:27 + | +LL | println!("{:?} {:?}", Foo, Bar); + | ^^^ `Foo` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `Foo` + = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Foo` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error[E0277]: `Bar` doesn't implement `Debug` + --> $DIR/no-debug.rs:10:32 + | +LL | println!("{:?} {:?}", Foo, Bar); + | ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `Bar` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `Foo` doesn't implement `std::fmt::Display` + --> $DIR/no-debug.rs:11:23 + | +LL | println!("{} {}", Foo, Bar); + | ^^^ `Foo` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Foo` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `Bar` doesn't implement `std::fmt::Display` + --> $DIR/no-debug.rs:11:28 + | +LL | println!("{} {}", Foo, Bar); + | ^^^ `Bar` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Bar` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/on-impl.rs b/tests/ui/on-unimplemented/on-impl.rs new file mode 100644 index 000000000..d0537810c --- /dev/null +++ b/tests/ui/on-unimplemented/on-impl.rs @@ -0,0 +1,26 @@ +// Test if the on_unimplemented message override works + +#![feature(rustc_attrs)] + + +#[rustc_on_unimplemented = "invalid"] +trait Index { + type Output: ?Sized; + fn index(&self, index: Idx) -> &Self::Output; +} + +#[rustc_on_unimplemented = "a usize is required to index into a slice"] +impl Index for [i32] { + type Output = i32; + fn index(&self, index: usize) -> &i32 { + &self[index] + } +} + + +fn main() { + Index::::index(&[1, 2, 3] as &[i32], 2u32); + //~^ ERROR E0277 + //~| ERROR E0277 + //~| ERROR E0277 +} diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr new file mode 100644 index 000000000..2253c5992 --- /dev/null +++ b/tests/ui/on-unimplemented/on-impl.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:22:47 + | +LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ------------------- ^^^^ a usize is required to index into a slice + | | + | required by a bound introduced by this call + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:22:5 + | +LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index` is not satisfied + --> $DIR/on-impl.rs:22:5 + | +LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index` is not implemented for `[i32]` + = help: the trait `Index` is implemented for `[i32]` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/on-trait.rs b/tests/ui/on-unimplemented/on-trait.rs new file mode 100644 index 000000000..556813cd4 --- /dev/null +++ b/tests/ui/on-unimplemented/on-trait.rs @@ -0,0 +1,32 @@ +// ignore-tidy-linelength + +#![feature(rustc_attrs)] + +pub mod Bar { + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] + pub trait Foo {} +} + +use Bar::Foo; + +fn foobar>() -> T { + panic!() +} + +#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"] +trait MyFromIterator { + /// Builds a container with elements from an external iterator. + fn my_from_iter>(iterator: T) -> Self; +} + +fn collect, B: MyFromIterator>(it: I) -> B { + MyFromIterator::my_from_iter(it) +} + +pub fn main() { + let x = vec![1u8, 2, 3, 4]; + let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() + //~^ ERROR + + let x: String = foobar(); //~ ERROR +} diff --git a/tests/ui/on-unimplemented/on-trait.stderr b/tests/ui/on-unimplemented/on-trait.stderr new file mode 100644 index 000000000..4b040f1ac --- /dev/null +++ b/tests/ui/on-unimplemented/on-trait.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `Option>: MyFromIterator<&u8>` is not satisfied + --> $DIR/on-trait.rs:28:30 + | +LL | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() + | ^^^^^^^ a collection of type `Option>` cannot be built from an iterator over elements of type `&u8` + | + = help: the trait `MyFromIterator<&u8>` is not implemented for `Option>` +note: required by a bound in `collect` + --> $DIR/on-trait.rs:22:39 + | +LL | fn collect, B: MyFromIterator>(it: I) -> B { + | ^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error[E0277]: the trait bound `String: Foo` is not satisfied + --> $DIR/on-trait.rs:31:21 + | +LL | let x: String = foobar(); + | ^^^^^^ test error `String` with `u8` `_` `u32` in `Foo` + | + = help: the trait `Foo` is not implemented for `String` +note: required by a bound in `foobar` + --> $DIR/on-trait.rs:12:24 + | +LL | fn foobar>() -> T { + | ^^^^^^^^^^^^^^^ required by this bound in `foobar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/parent-label.rs b/tests/ui/on-unimplemented/parent-label.rs new file mode 100644 index 000000000..b65f64968 --- /dev/null +++ b/tests/ui/on-unimplemented/parent-label.rs @@ -0,0 +1,27 @@ +// Test scope annotations from `parent_label` parameter + +#![feature(rustc_attrs)] + +#[rustc_on_unimplemented(parent_label = "in this scope")] +trait Trait {} + +struct Foo; + +fn f(x: T) {} + +fn main() { + let x = || { + f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied + let y = || { + f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied + }; + }; + + { + { + f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied + } + } + + f(Foo {}); //~ ERROR the trait bound `Foo: Trait` is not satisfied +} diff --git a/tests/ui/on-unimplemented/parent-label.stderr b/tests/ui/on-unimplemented/parent-label.stderr new file mode 100644 index 000000000..8cd7412fd --- /dev/null +++ b/tests/ui/on-unimplemented/parent-label.stderr @@ -0,0 +1,69 @@ +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/parent-label.rs:14:11 + | +LL | let x = || { + | -- in this scope +LL | f(Foo {}); + | - ^^^^^^ the trait `Trait` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f` + --> $DIR/parent-label.rs:10:9 + | +LL | fn f(x: T) {} + | ^^^^^ required by this bound in `f` + +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/parent-label.rs:16:15 + | +LL | let y = || { + | -- in this scope +LL | f(Foo {}); + | - ^^^^^^ the trait `Trait` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f` + --> $DIR/parent-label.rs:10:9 + | +LL | fn f(x: T) {} + | ^^^^^ required by this bound in `f` + +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/parent-label.rs:22:15 + | +LL | fn main() { + | --------- in this scope +... +LL | f(Foo {}); + | - ^^^^^^ the trait `Trait` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f` + --> $DIR/parent-label.rs:10:9 + | +LL | fn f(x: T) {} + | ^^^^^ required by this bound in `f` + +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/parent-label.rs:26:7 + | +LL | fn main() { + | --------- in this scope +... +LL | f(Foo {}); + | - ^^^^^^ the trait `Trait` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f` + --> $DIR/parent-label.rs:10:9 + | +LL | fn f(x: T) {} + | ^^^^^ required by this bound in `f` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/slice-index.rs b/tests/ui/on-unimplemented/slice-index.rs new file mode 100644 index 000000000..758220d3c --- /dev/null +++ b/tests/ui/on-unimplemented/slice-index.rs @@ -0,0 +1,10 @@ +// Test new Index error message for slices + +use std::ops::Index; + + +fn main() { + let x = &[1, 2, 3] as &[i32]; + x[1i32]; //~ ERROR E0277 + x[..1i32]; //~ ERROR E0277 +} diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr new file mode 100644 index 000000000..a7ec3bda8 --- /dev/null +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -0,0 +1,25 @@ +error[E0277]: the type `[i32]` cannot be indexed by `i32` + --> $DIR/slice-index.rs:8:7 + | +LL | x[1i32]; + | ^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[i32]` to implement `Index` + +error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` + --> $DIR/slice-index.rs:9:7 + | +LL | x[..1i32]; + | ^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` + = help: the following other types implement trait `SliceIndex`: + as SliceIndex<[T]>> + as SliceIndex> + = note: required for `[i32]` to implement `Index>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/sum.rs b/tests/ui/on-unimplemented/sum.rs new file mode 100644 index 000000000..4f1c521d9 --- /dev/null +++ b/tests/ui/on-unimplemented/sum.rs @@ -0,0 +1,9 @@ +// + +fn main() { + vec![(), ()].iter().sum::(); + //~^ ERROR + + vec![(), ()].iter().product::(); + //~^ ERROR +} diff --git a/tests/ui/on-unimplemented/sum.stderr b/tests/ui/on-unimplemented/sum.stderr new file mode 100644 index 000000000..2a316dba7 --- /dev/null +++ b/tests/ui/on-unimplemented/sum.stderr @@ -0,0 +1,43 @@ +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` + --> $DIR/sum.rs:4:25 + | +LL | vec![(), ()].iter().sum::(); + | ^^^ value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<&()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/sum.rs:4:18 + | +LL | vec![(), ()].iter().sum::(); + | ------------ ^^^^^^ `Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator + --> $DIR/sum.rs:7:25 + | +LL | vec![(), ()].iter().product::(); + | ^^^^^^^ value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator` + | + = help: the trait `Product<&()>` is not implemented for `i32` + = help: the following other types implement trait `Product`: + > + +note: the method call chain might not have had the expected associated types + --> $DIR/sum.rs:7:18 + | +LL | vec![(), ()].iter().product::(); + | ------------ ^^^^^^ `Iterator::Item` is `&()` here + | | + | this expression has type `Vec<()>` +note: required by a bound in `std::iter::Iterator::product` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/once-cant-call-twice-on-heap.rs b/tests/ui/once-cant-call-twice-on-heap.rs new file mode 100644 index 000000000..3fd8c5cad --- /dev/null +++ b/tests/ui/once-cant-call-twice-on-heap.rs @@ -0,0 +1,17 @@ +// Testing guarantees provided by once functions. +// This program would segfault if it were legal. + +use std::sync::Arc; + +fn foo(blk: F) { + blk(); + blk(); //~ ERROR use of moved value +} + +fn main() { + let x = Arc::new(true); + foo(move|| { + assert!(*x); + drop(x); + }); +} diff --git a/tests/ui/once-cant-call-twice-on-heap.stderr b/tests/ui/once-cant-call-twice-on-heap.stderr new file mode 100644 index 000000000..335ac6338 --- /dev/null +++ b/tests/ui/once-cant-call-twice-on-heap.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `blk` + --> $DIR/once-cant-call-twice-on-heap.rs:8:5 + | +LL | fn foo(blk: F) { + | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait +LL | blk(); + | ----- `blk` moved due to this call +LL | blk(); + | ^^^ value used here after move + | +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/once-cant-call-twice-on-heap.rs:7:5 + | +LL | blk(); + | ^^^ +help: consider further restricting this bound + | +LL | fn foo(blk: F) { + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/oom_unwind.rs b/tests/ui/oom_unwind.rs new file mode 100644 index 000000000..21a8fb2b2 --- /dev/null +++ b/tests/ui/oom_unwind.rs @@ -0,0 +1,21 @@ +// compile-flags: -Z oom=panic +// run-pass +// no-prefer-dynamic +// needs-unwind +// only-linux + +use std::hint::black_box; +use std::mem::forget; +use std::panic::catch_unwind; + +fn main() { + let panic = catch_unwind(|| { + // This is guaranteed to exceed even the size of the address space + for _ in 0..16 { + // Truncates to a suitable value for both 32-bit and 64-bit targets. + let alloc_size = 0x1000_0000_1000_0000u64 as usize; + forget(black_box(vec![0u8; alloc_size])); + } + }); + assert!(panic.is_err()); +} diff --git a/tests/ui/op-assign-builtins-by-ref.rs b/tests/ui/op-assign-builtins-by-ref.rs new file mode 100644 index 000000000..96853854d --- /dev/null +++ b/tests/ui/op-assign-builtins-by-ref.rs @@ -0,0 +1,76 @@ +// run-pass + +fn main() { + // test compound assignment operators with ref as right-hand side, + // for each operator, with various types as operands. + + // test AddAssign + { + let mut x = 3i8; + x += &2i8; + assert_eq!(x, 5i8); + } + + // test SubAssign + { + let mut x = 7i16; + x -= &4; + assert_eq!(x, 3i16); + } + + // test MulAssign + { + let mut x = 3f32; + x *= &3f32; + assert_eq!(x, 9f32); + } + + // test DivAssign + { + let mut x = 6f64; + x /= &2f64; + assert_eq!(x, 3f64); + } + + // test RemAssign + { + let mut x = 7i64; + x %= &4i64; + assert_eq!(x, 3i64); + } + + // test BitOrAssign + { + let mut x = 0b1010u8; + x |= &0b1100u8; + assert_eq!(x, 0b1110u8); + } + + // test BitAndAssign + { + let mut x = 0b1010u16; + x &= &0b1100u16; + assert_eq!(x, 0b1000u16); + } + + // test BitXorAssign + { + let mut x = 0b1010u32; + x ^= &0b1100u32; + assert_eq!(x, 0b0110u32); + } + + // test ShlAssign + { + let mut x = 0b1010u64; + x <<= &2u32; + assert_eq!(x, 0b101000u64); + } + + // test ShrAssign + { + let mut x = 0b1010u64; + x >>= &2i16; + assert_eq!(x, 0b10u64); + } +} diff --git a/tests/ui/opeq.rs b/tests/ui/opeq.rs new file mode 100644 index 000000000..9737be97f --- /dev/null +++ b/tests/ui/opeq.rs @@ -0,0 +1,17 @@ +// run-pass + +pub fn main() { + let mut x: isize = 1; + x *= 2; + println!("{}", x); + assert_eq!(x, 2); + x += 3; + println!("{}", x); + assert_eq!(x, 5); + x *= x; + println!("{}", x); + assert_eq!(x, 25); + x /= 5; + println!("{}", x); + assert_eq!(x, 5); +} diff --git a/tests/ui/operator-recovery/less-than-greater-than.rs b/tests/ui/operator-recovery/less-than-greater-than.rs new file mode 100644 index 000000000..2beed528f --- /dev/null +++ b/tests/ui/operator-recovery/less-than-greater-than.rs @@ -0,0 +1,4 @@ +fn main() { + println!("{}", 1 <> 2); + //~^ERROR invalid comparison operator `<>` +} diff --git a/tests/ui/operator-recovery/less-than-greater-than.stderr b/tests/ui/operator-recovery/less-than-greater-than.stderr new file mode 100644 index 000000000..80c921535 --- /dev/null +++ b/tests/ui/operator-recovery/less-than-greater-than.stderr @@ -0,0 +1,8 @@ +error: invalid comparison operator `<>` + --> $DIR/less-than-greater-than.rs:2:22 + | +LL | println!("{}", 1 <> 2); + | ^^ help: `<>` is not a valid comparison operator, use `!=` + +error: aborting due to previous error + diff --git a/tests/ui/operator-recovery/spaceship.rs b/tests/ui/operator-recovery/spaceship.rs new file mode 100644 index 000000000..a65f93896 --- /dev/null +++ b/tests/ui/operator-recovery/spaceship.rs @@ -0,0 +1,4 @@ +fn main() { + println!("{}", 1 <=> 2); + //~^ERROR invalid comparison operator `<=>` +} diff --git a/tests/ui/operator-recovery/spaceship.stderr b/tests/ui/operator-recovery/spaceship.stderr new file mode 100644 index 000000000..ed6bd74c9 --- /dev/null +++ b/tests/ui/operator-recovery/spaceship.stderr @@ -0,0 +1,8 @@ +error: invalid comparison operator `<=>` + --> $DIR/spaceship.rs:2:22 + | +LL | println!("{}", 1 <=> 2); + | ^^^ `<=>` is not a valid comparison operator, use `std::cmp::Ordering` + +error: aborting due to previous error + diff --git a/tests/ui/opt-in-copy.rs b/tests/ui/opt-in-copy.rs new file mode 100644 index 000000000..0b48418e4 --- /dev/null +++ b/tests/ui/opt-in-copy.rs @@ -0,0 +1,22 @@ +struct CantCopyThis; + +struct IWantToCopyThis { + but_i_cant: CantCopyThis, +} + +impl Copy for IWantToCopyThis {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +enum CantCopyThisEither { + A, + B, +} + +enum IWantToCopyThisToo { + ButICant(CantCopyThisEither), +} + +impl Copy for IWantToCopyThisToo {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/opt-in-copy.stderr b/tests/ui/opt-in-copy.stderr new file mode 100644 index 000000000..4461567df --- /dev/null +++ b/tests/ui/opt-in-copy.stderr @@ -0,0 +1,21 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/opt-in-copy.rs:7:15 + | +LL | but_i_cant: CantCopyThis, + | ------------------------ this field does not implement `Copy` +... +LL | impl Copy for IWantToCopyThis {} + | ^^^^^^^^^^^^^^^ + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/opt-in-copy.rs:19:15 + | +LL | ButICant(CantCopyThisEither), + | ------------------ this field does not implement `Copy` +... +LL | impl Copy for IWantToCopyThisToo {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/optimization-fuel-0.rs b/tests/ui/optimization-fuel-0.rs new file mode 100644 index 000000000..2643dbea1 --- /dev/null +++ b/tests/ui/optimization-fuel-0.rs @@ -0,0 +1,17 @@ +// run-pass + +#![crate_name="foo"] + +use std::mem::size_of; + +// compile-flags: -Z fuel=foo=0 + +#[allow(unused_tuple_struct_fields)] +struct S1(u8, u16, u8); +#[allow(unused_tuple_struct_fields)] +struct S2(u8, u16, u8); + +fn main() { + assert_eq!(size_of::(), 6); + assert_eq!(size_of::(), 6); +} diff --git a/tests/ui/optimization-fuel-0.stderr b/tests/ui/optimization-fuel-0.stderr new file mode 100644 index 000000000..f0e2ebfc3 --- /dev/null +++ b/tests/ui/optimization-fuel-0.stderr @@ -0,0 +1,4 @@ +warning: optimization-fuel-exhausted: Reorder fields of "S1" + +warning: 1 warning emitted + diff --git a/tests/ui/optimization-fuel-1.rs b/tests/ui/optimization-fuel-1.rs new file mode 100644 index 000000000..d5e2255d9 --- /dev/null +++ b/tests/ui/optimization-fuel-1.rs @@ -0,0 +1,18 @@ +// run-pass + +#![crate_name="foo"] + +use std::mem::size_of; + +// compile-flags: -Z fuel=foo=1 + +#[allow(unused_tuple_struct_fields)] +struct S1(u8, u16, u8); +#[allow(unused_tuple_struct_fields)] +struct S2(u8, u16, u8); + +fn main() { + let optimized = (size_of::() == 4) as usize + +(size_of::() == 4) as usize; + assert_eq!(optimized, 1); +} diff --git a/tests/ui/optimization-fuel-1.stderr b/tests/ui/optimization-fuel-1.stderr new file mode 100644 index 000000000..53eafb058 --- /dev/null +++ b/tests/ui/optimization-fuel-1.stderr @@ -0,0 +1,4 @@ +warning: optimization-fuel-exhausted: Reorder fields of "S2" + +warning: 1 warning emitted + diff --git a/tests/ui/optimization-remark.rs b/tests/ui/optimization-remark.rs new file mode 100644 index 000000000..d4b39c670 --- /dev/null +++ b/tests/ui/optimization-remark.rs @@ -0,0 +1,28 @@ +// build-pass +// ignore-pass +// min-llvm-version: 14.0.0 +// revisions: all inline merge1 merge2 +// compile-flags: --crate-type=lib -Cdebuginfo=1 -Copt-level=2 +// +// Check that remarks can be enabled individually or with "all": +// +// [all] compile-flags: -Cremark=all +// [inline] compile-flags: -Cremark=inline +// +// Check that values of -Cremark flag are accumulated: +// +// [merge1] compile-flags: -Cremark=all -Cremark=giraffe +// [merge2] compile-flags: -Cremark=inline -Cremark=giraffe +// +// error-pattern: inline: 'f' not inlined into 'g' +// dont-check-compiler-stderr + +#[no_mangle] +#[inline(never)] +pub fn f() { +} + +#[no_mangle] +pub fn g() { + f(); +} diff --git a/tests/ui/or-patterns/already-bound-name.rs b/tests/ui/or-patterns/already-bound-name.rs new file mode 100644 index 000000000..65c25293d --- /dev/null +++ b/tests/ui/or-patterns/already-bound-name.rs @@ -0,0 +1,43 @@ +// This test ensures that the "already bound identifier in a product pattern" +// correctly accounts for or-patterns. + +enum E { A(T, T), B(T) } + +use E::*; + +fn main() { + let (a, a) = (0, 1); // Standard duplication without an or-pattern. + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let (a, A(a, _) | B(a)) = (0, A(1, 2)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + + let (A(a, _) | B(a), a) = (A(0, 1), 2); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let (A(a, a) | B(a)) = A(0, 1); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let (B(a) | A(a, a)) = A(0, 1); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + match A(0, 1) { + B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. + //~^ ERROR identifier `a` is bound more than once in the same pattern + } + + let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR mismatched types + + let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR variable `a` is not bound in all patterns + + let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern +} diff --git a/tests/ui/or-patterns/already-bound-name.stderr b/tests/ui/or-patterns/already-bound-name.stderr new file mode 100644 index 000000000..368782c1e --- /dev/null +++ b/tests/ui/or-patterns/already-bound-name.stderr @@ -0,0 +1,101 @@ +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:9:13 + | +LL | let (a, a) = (0, 1); // Standard duplication without an or-pattern. + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:12:15 + | +LL | let (a, A(a, _) | B(a)) = (0, A(1, 2)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:12:25 + | +LL | let (a, A(a, _) | B(a)) = (0, A(1, 2)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:16:26 + | +LL | let (A(a, _) | B(a), a) = (A(0, 1), 2); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:19:15 + | +LL | let (A(a, a) | B(a)) = A(0, 1); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:22:22 + | +LL | let (B(a) | A(a, a)) = A(0, 1); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:26:21 + | +LL | B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:30:37 + | +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:30:47 + | +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:35:37 + | +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:35:47 + | +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/already-bound-name.rs:35:10 + | +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^^^^ pattern doesn't bind `a` - variable not in all patterns + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:40:50 + | +LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/already-bound-name.rs:40:60 + | +LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once + +error[E0308]: mismatched types + --> $DIR/already-bound-name.rs:30:32 + | +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | - ^ ------- this expression has type `E>` + | | | + | | expected integer, found enum `E` + | first introduced with type `{integer}` here + | + = note: expected type `{integer}` + found enum `E<{integer}>` + = note: a binding must have the same type in all alternatives + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0308, E0408, E0416. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/basic-switch.rs b/tests/ui/or-patterns/basic-switch.rs new file mode 100644 index 000000000..674fbc3cc --- /dev/null +++ b/tests/ui/or-patterns/basic-switch.rs @@ -0,0 +1,31 @@ +// Test basic or-patterns when the target pattern type will be lowered to a +// `Switch` (an `enum`). + +// run-pass + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(x: Option) -> bool { + match x { + // most simple case + Some(Test::Bar | Test::Qux) => true, + // wild case + Some(_) => false, + // empty case + None => false, + } +} + +fn main() { + assert!(!test(Some(Test::Foo))); + assert!(test(Some(Test::Bar))); + assert!(!test(Some(Test::Baz))); + assert!(test(Some(Test::Qux))); + assert!(!test(None)) +} diff --git a/tests/ui/or-patterns/basic-switchint.rs b/tests/ui/or-patterns/basic-switchint.rs new file mode 100644 index 000000000..adb902caf --- /dev/null +++ b/tests/ui/or-patterns/basic-switchint.rs @@ -0,0 +1,52 @@ +// Test basic or-patterns when the target pattern type will be lowered to +// a `SwitchInt`. This will happen when the target type is an integer. + +// run-pass + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Foo { + One(usize), + Two(usize, usize), +} + +fn test_foo(x: Foo) -> MatchArm { + match x { + // normal pattern. + Foo::One(0) | Foo::One(1) | Foo::One(2) => MatchArm::Arm(0), + // most simple or-pattern. + Foo::One(42 | 255) => MatchArm::Arm(1), + // multiple or-patterns for one structure. + Foo::Two(42 | 255, 1024 | 2048) => MatchArm::Arm(2), + // mix of pattern types in one or-pattern (range). + Foo::One(100 | 110..=120 | 210..=220) => MatchArm::Arm(3), + // multiple or-patterns with wild. + Foo::Two(0..=10 | 100..=110, 0 | _) => MatchArm::Arm(4), + // wild + _ => MatchArm::Wild, + } +} + +fn main() { + // `Foo` tests. + assert_eq!(test_foo(Foo::One(0)), MatchArm::Arm(0)); + assert_eq!(test_foo(Foo::One(42)), MatchArm::Arm(1)); + assert_eq!(test_foo(Foo::One(43)), MatchArm::Wild); + assert_eq!(test_foo(Foo::One(255)), MatchArm::Arm(1)); + assert_eq!(test_foo(Foo::One(256)), MatchArm::Wild); + assert_eq!(test_foo(Foo::Two(42, 1023)), MatchArm::Wild); + assert_eq!(test_foo(Foo::Two(255, 2048)), MatchArm::Arm(2)); + assert_eq!(test_foo(Foo::One(100)), MatchArm::Arm(3)); + assert_eq!(test_foo(Foo::One(115)), MatchArm::Arm(3)); + assert_eq!(test_foo(Foo::One(105)), MatchArm::Wild); + assert_eq!(test_foo(Foo::One(215)), MatchArm::Arm(3)); + assert_eq!(test_foo(Foo::One(121)), MatchArm::Wild); + assert_eq!(test_foo(Foo::Two(0, 42)), MatchArm::Arm(4)); + assert_eq!(test_foo(Foo::Two(100, 0)), MatchArm::Arm(4)); + assert_eq!(test_foo(Foo::Two(42, 0)), MatchArm::Wild); +} diff --git a/tests/ui/or-patterns/bindings-runpass-1.rs b/tests/ui/or-patterns/bindings-runpass-1.rs new file mode 100644 index 000000000..3406d5197 --- /dev/null +++ b/tests/ui/or-patterns/bindings-runpass-1.rs @@ -0,0 +1,23 @@ +// run-pass + +fn two_bindings(x: &((bool, bool), u8)) -> u8 { + match x { + &((true, y) | (y, true), z @ (0 | 4)) => (y as u8) + z, + _ => 20, + } +} + +fn main() { + assert_eq!(two_bindings(&((false, false), 0)), 20); + assert_eq!(two_bindings(&((false, true), 0)), 0); + assert_eq!(two_bindings(&((true, false), 0)), 0); + assert_eq!(two_bindings(&((true, true), 0)), 1); + assert_eq!(two_bindings(&((false, false), 4)), 20); + assert_eq!(two_bindings(&((false, true), 4)), 4); + assert_eq!(two_bindings(&((true, false), 4)), 4); + assert_eq!(two_bindings(&((true, true), 4)), 5); + assert_eq!(two_bindings(&((false, false), 3)), 20); + assert_eq!(two_bindings(&((false, true), 3)), 20); + assert_eq!(two_bindings(&((true, false), 3)), 20); + assert_eq!(two_bindings(&((true, true), 3)), 20); +} diff --git a/tests/ui/or-patterns/bindings-runpass-2.rs b/tests/ui/or-patterns/bindings-runpass-2.rs new file mode 100644 index 000000000..5b9bb748c --- /dev/null +++ b/tests/ui/or-patterns/bindings-runpass-2.rs @@ -0,0 +1,30 @@ +// run-pass + +fn or_at(x: Result) -> u32 { + match x { + Ok(x @ 4) | Err(x @ (6 | 8)) => x, + Ok(x @ 1 | x @ 2) => x, + Err(x @ (0..=10 | 30..=40)) if x % 2 == 0 => x + 100, + Err(x @ 0..=40) => x + 200, + _ => 500, + } +} + +fn main() { + assert_eq!(or_at(Ok(1)), 1); + assert_eq!(or_at(Ok(2)), 2); + assert_eq!(or_at(Ok(3)), 500); + assert_eq!(or_at(Ok(4)), 4); + assert_eq!(or_at(Ok(5)), 500); + assert_eq!(or_at(Ok(6)), 500); + assert_eq!(or_at(Err(1)), 201); + assert_eq!(or_at(Err(2)), 102); + assert_eq!(or_at(Err(3)), 203); + assert_eq!(or_at(Err(4)), 104); + assert_eq!(or_at(Err(5)), 205); + assert_eq!(or_at(Err(6)), 6); + assert_eq!(or_at(Err(7)), 207); + assert_eq!(or_at(Err(8)), 8); + assert_eq!(or_at(Err(20)), 220); + assert_eq!(or_at(Err(50)), 500); +} diff --git a/tests/ui/or-patterns/box-patterns.rs b/tests/ui/or-patterns/box-patterns.rs new file mode 100644 index 000000000..73051401c --- /dev/null +++ b/tests/ui/or-patterns/box-patterns.rs @@ -0,0 +1,36 @@ +// Test or-patterns with box-patterns + +// run-pass + +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(x: Option>) -> MatchArm { + match x { + Some(box Test::Foo | box Test::Bar) => MatchArm::Arm(0), + Some(box Test::Baz) => MatchArm::Arm(1), + Some(_) => MatchArm::Arm(2), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(2)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/tests/ui/or-patterns/consistent-bindings.rs b/tests/ui/or-patterns/consistent-bindings.rs new file mode 100644 index 000000000..ecae1d8a2 --- /dev/null +++ b/tests/ui/or-patterns/consistent-bindings.rs @@ -0,0 +1,39 @@ +// Check that or-patterns with consistent bindings across arms are allowed. + +// edition:2018 + +// check-pass + +fn main() { + // One level: + let (Ok(a) | Err(a)) = Ok(0); + let (Ok(ref a) | Err(ref a)) = Ok(0); + let (Ok(ref mut a) | Err(ref mut a)) = Ok(0); + + // Two levels: + enum Tri { + V1(S), + V2(T), + V3(U), + } + use Tri::*; + + let (Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b)))): Result<_, Result<_, _>> = + Ok((V1(1), 1)); + + let (Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b)))): Result< + _, + Result<_, _>, + > = Ok((V1(1), 1)); + + // Three levels: + let ( + a, + Err((ref mut b, ref c, d)) + | Ok(( + Ok(V1((ref c, d)) | V2((d, ref c)) | V3((ref c, Ok((_, d)) | Err((d, _))))) + | Err((ref c, d)), + ref mut b, + )), + ): (_, Result<_, _>) = (1, Ok((Ok(V3((1, Ok::<_, (i32, i32)>((1, 1))))), 1))); +} diff --git a/tests/ui/or-patterns/const-fn.rs b/tests/ui/or-patterns/const-fn.rs new file mode 100644 index 000000000..ca512ac71 --- /dev/null +++ b/tests/ui/or-patterns/const-fn.rs @@ -0,0 +1,29 @@ +// check-pass + +const fn foo((Ok(a) | Err(a)): Result) { + let x = Ok(3); + let (Ok(y) | Err(y)) = x; +} + +const X: () = { + let x = Ok(3); + let (Ok(y) | Err(y)) = x; +}; + +static Y: () = { + let x = Ok(3); + let (Ok(y) | Err(y)) = x; +}; + +static mut Z: () = { + let x = Ok(3); + let (Ok(y) | Err(y)) = x; +}; + +fn main() { + let _: [(); { + let x = Ok(3); + let (Ok(y) | Err(y)) = x; + 2 + }]; +} diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs new file mode 100644 index 000000000..5999e04e0 --- /dev/null +++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs @@ -0,0 +1,17 @@ +#![deny(unreachable_patterns)] + +// We wrap patterns in a tuple because top-level or-patterns were special-cased. +fn main() { + match (0u8, 0u8) { + //~^ ERROR non-exhaustive patterns: `(2_u8..=u8::MAX, _)` + (0 | 1, 2 | 3) => {} + } + match ((0u8,),) { + //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX))` + ((0 | 1,) | (2 | 3,),) => {} + } + match (Some(0u8),) { + //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` + (None | Some(0 | 1),) => {} + } +} diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr new file mode 100644 index 000000000..9aa808e6b --- /dev/null +++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr @@ -0,0 +1,42 @@ +error[E0004]: non-exhaustive patterns: `(2_u8..=u8::MAX, _)` not covered + --> $DIR/exhaustiveness-non-exhaustive.rs:5:11 + | +LL | match (0u8, 0u8) { + | ^^^^^^^^^^ pattern `(2_u8..=u8::MAX, _)` not covered + | + = note: the matched value is of type `(u8, u8)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (0 | 1, 2 | 3) => {} +LL + (2_u8..=u8::MAX, _) => todo!() + | + +error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered + --> $DIR/exhaustiveness-non-exhaustive.rs:9:11 + | +LL | match ((0u8,),) { + | ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered + | + = note: the matched value is of type `((u8,),)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ ((0 | 1,) | (2 | 3,),) => {} +LL + ((4_u8..=u8::MAX)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered + --> $DIR/exhaustiveness-non-exhaustive.rs:13:11 + | +LL | match (Some(0u8),) { + | ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered + | + = note: the matched value is of type `(Option,)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (None | Some(0 | 1),) => {} +LL + (Some(2_u8..=u8::MAX)) => todo!() + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/or-patterns/exhaustiveness-pass.rs b/tests/ui/or-patterns/exhaustiveness-pass.rs new file mode 100644 index 000000000..e8c8a0e7b --- /dev/null +++ b/tests/ui/or-patterns/exhaustiveness-pass.rs @@ -0,0 +1,38 @@ +#![deny(unreachable_patterns)] + +// check-pass + +// We wrap patterns in a tuple because top-level or-patterns were special-cased. +fn main() { + match (0,) { + (1 | 2,) => {} + _ => {} + } + + match (0, 0) { + (1 | 2, 3 | 4) => {} + (1, 2) => {} + (3, 1) => {} + _ => {} + } + match (Some(0u8),) { + (None | Some(0 | 1),) => {} + (Some(2..=255),) => {} + } + match ((0,),) { + ((0 | 1,) | (2 | 3,),) => {} + ((_,),) => {} + } + match (&[0u8][..],) { + ([] | [0 | 1..=255] | [_, ..],) => {} + } + + match ((0, 0),) { + ((0, 0) | (0, 1),) => {} + _ => {} + } + match ((0, 0),) { + ((0, 0) | (1, 0),) => {} + _ => {} + } +} diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs new file mode 100644 index 000000000..8429799ca --- /dev/null +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -0,0 +1,152 @@ +#![deny(unreachable_patterns)] + +// We wrap patterns in a tuple because top-level or-patterns were special-cased. +fn main() { + match (0u8,) { + (1 | 2,) => {} + (1,) => {} //~ ERROR unreachable pattern + _ => {} + } + match (0u8,) { + (1 | 2,) => {} + (2,) => {} //~ ERROR unreachable pattern + _ => {} + } + match (0u8,) { + (1,) => {} + (2,) => {} + (1 | 2,) => {} //~ ERROR unreachable pattern + _ => {} + } + match (0u8, 0u8) { + (1 | 2, 3 | 4) => {} + (1, 3) => {} //~ ERROR unreachable pattern + (1, 4) => {} //~ ERROR unreachable pattern + (2, 4) => {} //~ ERROR unreachable pattern + (2 | 1, 4) => {} //~ ERROR unreachable pattern + (1, 5 | 6) => {} + (1, 4 | 5) => {} //~ ERROR unreachable pattern + _ => {} + } + match (true, true) { + (false | true, false | true) => (), + } + match (Some(0u8),) { + (None | Some(1 | 2),) => {} + (Some(1),) => {} //~ ERROR unreachable pattern + (None,) => {} //~ ERROR unreachable pattern + _ => {} + } + match ((0u8,),) { + ((1 | 2,) | (3 | 4,),) => {} + ((1..=4,),) => {} //~ ERROR unreachable pattern + _ => {} + } + + match (0,) { + (1 | 1,) => {} //~ ERROR unreachable + _ => {} + } + match 0 { + (0 | 1) | 1 => {} //~ ERROR unreachable + _ => {} + } + match 0 { + // We get two errors because recursive or-pattern expansion means we don't notice the two + // errors span a whole pattern. This could be better but doesn't matter much + 0 | (0 | 0) => {} + //~^ ERROR unreachable + //~| ERROR unreachable + _ => {} + } + match None { + // There is only one error that correctly points to the whole subpattern + Some(0) | + Some( //~ ERROR unreachable + 0 | 0) => {} + _ => {} + } + match [0; 2] { + [0 + | 0 //~ ERROR unreachable + , 0 + | 0] => {} //~ ERROR unreachable + _ => {} + } + match &[][..] { + [0] => {} + [0, _] => {} + [0, _, _] => {} + [1, ..] => {} + [1 //~ ERROR unreachable + | 2, ..] => {} + _ => {} + } + match &[][..] { + [true] => {} + [true | false, ..] => {} + _ => {} + } + match &[][..] { + [false] => {} + [true, ..] => {} + [true //~ ERROR unreachable + | false, ..] => {} + _ => {} + } + match (true, None) { + (true, Some(_)) => {} + (false, Some(true)) => {} + (true | false, None | Some(true //~ ERROR unreachable + | false)) => {} + } + macro_rules! t_or_f { + () => { + (true //~ ERROR unreachable + | false) + }; + } + match (true, None) { + (true, Some(_)) => {} + (false, Some(true)) => {} + (true | false, None | Some(t_or_f!())) => {} + } + match Some(0) { + Some(0) => {} + Some(0 //~ ERROR unreachable + | 1) => {} + _ => {} + } + + // A subpattern that is only unreachable in one branch is overall reachable. + match (true, true) { + (true, true) => {} + (false | true, false | true) => {} + } + match (true, true) { + (true, true) => {} + (false, false) => {} + (false | true, false | true) => {} + } + // https://github.com/rust-lang/rust/issues/76836 + match None { + Some(false) => {} + None | Some(true + | false) => {} //~ ERROR unreachable + } + + // A subpattern that is unreachable in all branches is overall unreachable. + match (true, true) { + (false, true) => {} + (true, true) => {} + (false | true, false + | true) => {} //~ ERROR unreachable + } + match (true, true) { + (true, false) => {} + (true, true) => {} + (false + | true, //~ ERROR unreachable + false | true) => {} + } +} diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr new file mode 100644 index 000000000..3f7d47dcb --- /dev/null +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -0,0 +1,170 @@ +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:7:9 + | +LL | (1,) => {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/exhaustiveness-unreachable-pattern.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:12:9 + | +LL | (2,) => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:18:9 + | +LL | (1 | 2,) => {} + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:23:9 + | +LL | (1, 3) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:24:9 + | +LL | (1, 4) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:25:9 + | +LL | (2, 4) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:26:9 + | +LL | (2 | 1, 4) => {} + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:28:9 + | +LL | (1, 4 | 5) => {} + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:36:9 + | +LL | (Some(1),) => {} + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9 + | +LL | (None,) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:42:9 + | +LL | ((1..=4,),) => {} + | ^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:47:14 + | +LL | (1 | 1,) => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:51:19 + | +LL | (0 | 1) | 1 => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:57:14 + | +LL | 0 | (0 | 0) => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:57:18 + | +LL | 0 | (0 | 0) => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:65:13 + | +LL | / Some( +LL | | 0 | 0) => {} + | |______________________^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:71:15 + | +LL | | 0 + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:73:15 + | +LL | | 0] => {} + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:81:10 + | +LL | [1 + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:93:10 + | +LL | [true + | ^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:100:36 + | +LL | (true | false, None | Some(true + | ^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:105:14 + | +LL | (true + | ^^^^ +... +LL | (true | false, None | Some(t_or_f!())) => {} + | --------- in this macro invocation + | + = note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 + | +LL | Some(0 + | ^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:135:19 + | +LL | | false) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:143:15 + | +LL | | true) => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/exhaustiveness-unreachable-pattern.rs:149:15 + | +LL | | true, + | ^^^^ + +error: aborting due to 26 previous errors + diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.fixed b/tests/ui/or-patterns/fn-param-wrap-parens.fixed new file mode 100644 index 000000000..b9490aaf9 --- /dev/null +++ b/tests/ui/or-patterns/fn-param-wrap-parens.fixed @@ -0,0 +1,13 @@ +// Test the suggestion to wrap an or-pattern as a function parameter in parens. + +// run-rustfix + +#![allow(warnings)] + +fn main() {} + +enum E { A, B } +use E::*; + +#[cfg(FALSE)] +fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.rs b/tests/ui/or-patterns/fn-param-wrap-parens.rs new file mode 100644 index 000000000..8e703d274 --- /dev/null +++ b/tests/ui/or-patterns/fn-param-wrap-parens.rs @@ -0,0 +1,13 @@ +// Test the suggestion to wrap an or-pattern as a function parameter in parens. + +// run-rustfix + +#![allow(warnings)] + +fn main() {} + +enum E { A, B } +use E::*; + +#[cfg(FALSE)] +fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.stderr b/tests/ui/or-patterns/fn-param-wrap-parens.stderr new file mode 100644 index 000000000..732702841 --- /dev/null +++ b/tests/ui/or-patterns/fn-param-wrap-parens.stderr @@ -0,0 +1,8 @@ +error: top-level or-patterns are not allowed in function parameters + --> $DIR/fn-param-wrap-parens.rs:13:9 + | +LL | fn fun1(A | B: E) {} + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: aborting due to previous error + diff --git a/tests/ui/or-patterns/for-loop.rs b/tests/ui/or-patterns/for-loop.rs new file mode 100644 index 000000000..11b61cb69 --- /dev/null +++ b/tests/ui/or-patterns/for-loop.rs @@ -0,0 +1,16 @@ +// Check that or patterns are lowered correctly in `for` loops. +// run-pass + +fn main() { + let v = vec![Ok(2), Err(3), Ok(5)]; + let mut w = Vec::new(); + for &(Ok(i) | Err(i)) in &v { + w.push(i); + } + let mut u = Vec::new(); + for Ok(i) | Err(i) in v { + u.push(i); + } + assert_eq!(w, [2, 3, 5]); + assert_eq!(u, [2, 3, 5]); +} diff --git a/tests/ui/or-patterns/if-let-while-let.rs b/tests/ui/or-patterns/if-let-while-let.rs new file mode 100644 index 000000000..92a1bb256 --- /dev/null +++ b/tests/ui/or-patterns/if-let-while-let.rs @@ -0,0 +1,20 @@ +// Check that or patterns are lowered correctly in `if let` and `while let` expressions. +// run-pass + +fn main() { + let mut opt = Some(3); + let mut w = Vec::new(); + while let Some(ref mut val @ (3 | 4 | 6)) = opt { + w.push(*val); + *val += 1; + } + assert_eq!(w, [3, 4]); + if let &(None | Some(6 | 7)) = &opt { + unreachable!(); + } + if let Some(x @ (4 | 5 | 6)) = opt { + assert_eq!(x, 5); + } else { + unreachable!(); + } +} diff --git a/tests/ui/or-patterns/inconsistent-modes.rs b/tests/ui/or-patterns/inconsistent-modes.rs new file mode 100644 index 000000000..a87a10ce8 --- /dev/null +++ b/tests/ui/or-patterns/inconsistent-modes.rs @@ -0,0 +1,25 @@ +// This test ensures that or patterns require binding mode consistency across arms. + +#![allow(non_camel_case_types)] +fn main() { + // One level: + let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); + //~^ ERROR variable `a` is bound inconsistently + let (Ok(ref mut a) | Err(a)): Result = Ok(0); + //~^ ERROR variable `a` is bound inconsistently + let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + //~^ ERROR variable `a` is bound inconsistently + //~| ERROR mismatched types + let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + //~^ ERROR variable `a` is bound inconsistently + //~| ERROR variable `b` is bound inconsistently + //~| ERROR mismatched types + + // Two levels: + let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); + //~^ ERROR variable `a` is bound inconsistently + + // Three levels: + let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); + //~^ ERROR variable `a` is bound inconsistently +} diff --git a/tests/ui/or-patterns/inconsistent-modes.stderr b/tests/ui/or-patterns/inconsistent-modes.stderr new file mode 100644 index 000000000..f6367ef82 --- /dev/null +++ b/tests/ui/or-patterns/inconsistent-modes.stderr @@ -0,0 +1,80 @@ +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:6:26 + | +LL | let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:8:30 + | +LL | let (Ok(ref mut a) | Err(a)): Result = Ok(0); + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:10:34 + | +LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + | - first binding ^ bound in different ways + +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:13:40 + | +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | - first binding ^ bound in different ways + +error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:13:47 + | +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | - first binding ^ bound in different ways + +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:19:39 + | +LL | let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:23:34 + | +LL | let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); + | - ^ bound in different ways + | | + | first binding + +error[E0308]: mismatched types + --> $DIR/inconsistent-modes.rs:10:26 + | +LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + | ----- ^^^^^^^^^ -------------------- expected due to this + | | | + | | types differ in mutability + | first introduced with type `&&u8` here + | + = note: expected reference `&&u8` + found mutable reference `&mut &mut u8` + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/inconsistent-modes.rs:13:32 + | +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` + | | | + | | types differ in mutability + | first introduced with type `&{integer}` here + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + = note: a binding must have the same type in all alternatives + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/inner-or-pat.or3.stderr b/tests/ui/or-patterns/inner-or-pat.or3.stderr new file mode 100644 index 000000000..2236a38c3 --- /dev/null +++ b/tests/ui/or-patterns/inner-or-pat.or3.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/inner-or-pat.rs:38:54 + | +LL | match x { + | - this expression has type `&str` +LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | + | ^^ expected `str`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/inner-or-pat.or4.stderr b/tests/ui/or-patterns/inner-or-pat.or4.stderr new file mode 100644 index 000000000..058873ff5 --- /dev/null +++ b/tests/ui/or-patterns/inner-or-pat.or4.stderr @@ -0,0 +1,11 @@ +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/inner-or-pat.rs:53:37 + | +LL | (x @ "red" | (x @ "blue" | "red")) => { + | - ^^^^^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/or-patterns/inner-or-pat.rs b/tests/ui/or-patterns/inner-or-pat.rs new file mode 100644 index 000000000..f4cf4b0c1 --- /dev/null +++ b/tests/ui/or-patterns/inner-or-pat.rs @@ -0,0 +1,73 @@ +// revisions: or1 or2 or3 or4 or5 +// [or1] run-pass +// [or2] run-pass +// [or5] run-pass + +#![allow(unreachable_patterns)] +#![allow(unused_variables)] +#![allow(unused_parens)] +#![allow(dead_code)] + + + +fn foo() { + let x = "foo"; + match x { + x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) | + x @ ("black" | "pink") | + x @ ("red" | "blue") => { + } + _ => (), + } +} + +fn bar() { + let x = "foo"; + match x { + x @ ("foo" | "bar") | + (x @ "red" | (x @ "blue" | x @ "red")) => { + } + _ => (), + } +} + +#[cfg(or3)] +fn zot() { + let x = "foo"; + match x { + x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | + //[or3]~^ ERROR mismatched types + x @ ("black" | "pink") | + x @ ("red" | "blue") => { + } + _ => (), + } +} + + +#[cfg(or4)] +fn hey() { + let x = "foo"; + match x { + x @ ("foo" | "bar") | + (x @ "red" | (x @ "blue" | "red")) => { + //[or4]~^ variable `x` is not bound in all patterns + } + _ => (), + } +} + +fn don() { + enum Foo { + A, + B, + C, + } + + match Foo::A { + | _foo @ (Foo::A | Foo::B) => {} + Foo::C => {} + }; +} + +fn main(){} diff --git a/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs b/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs new file mode 100644 index 000000000..181c77009 --- /dev/null +++ b/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs @@ -0,0 +1,15 @@ +// In this regression test we check that a trailing `|` in an or-pattern just +// before the `if` token of a `match` guard will receive parser recovery with +// an appropriate error message. + +enum E { A, B } + +fn main() { + match E::A { + E::A | + E::B | //~ ERROR a trailing `|` is not allowed in an or-pattern + if true => { + let recovery_witness: bool = 0; //~ ERROR mismatched types + } + } +} diff --git a/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr b/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr new file mode 100644 index 000000000..9b827794f --- /dev/null +++ b/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr @@ -0,0 +1,19 @@ +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/issue-64879-trailing-before-guard.rs:10:14 + | +LL | E::A | + | ---- while parsing this or-pattern starting here +LL | E::B | + | ^ help: remove the `|` + +error[E0308]: mismatched types + --> $DIR/issue-64879-trailing-before-guard.rs:12:42 + | +LL | let recovery_witness: bool = 0; + | ---- ^ expected `bool`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/issue-67514-irrefutable-param.rs b/tests/ui/or-patterns/issue-67514-irrefutable-param.rs new file mode 100644 index 000000000..73931def8 --- /dev/null +++ b/tests/ui/or-patterns/issue-67514-irrefutable-param.rs @@ -0,0 +1,9 @@ +// Check that we don't ICE for irrefutable or-patterns in function parameters + +// check-pass + +fn foo((Some(_) | None): Option) {} + +fn main() { + foo(None); +} diff --git a/tests/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs b/tests/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs new file mode 100644 index 000000000..7339a7e23 --- /dev/null +++ b/tests/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs @@ -0,0 +1,12 @@ +// check-pass + +enum MyEnum { + FirstCase(u8), + OtherCase(u16), +} + +fn my_fn(x @ (MyEnum::FirstCase(_) | MyEnum::OtherCase(_)): MyEnum) {} + +fn main() { + my_fn(MyEnum::FirstCase(0)); +} diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs new file mode 100644 index 000000000..3538aad5d --- /dev/null +++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs @@ -0,0 +1,7 @@ +fn main() { + let (0 | (1 | 2)) = 0; //~ ERROR refutable pattern in local binding + match 0 { + //~^ ERROR non-exhaustive patterns + 0 | (1 | 2) => {} + } +} diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr new file mode 100644 index 000000000..4adcf4fee --- /dev/null +++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -0,0 +1,31 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:2:10 + | +LL | let (0 | (1 | 2)) = 0; + | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let (0 | (1 | 2)) = 0 { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11 + | +LL | match 0 { + | ^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ 0 | (1 | 2) => {} +LL + i32::MIN..=-1_i32 | 3_i32..=i32::MAX => todo!() + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs new file mode 100644 index 000000000..408ac24f3 --- /dev/null +++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() { + let (0 | (1 | _)) = 0; + if let 0 | (1 | 2) = 0 {} + if let x @ 0 | x @ (1 | 2) = 0 {} +} diff --git a/tests/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs b/tests/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs new file mode 100644 index 000000000..8a3c640b1 --- /dev/null +++ b/tests/ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs @@ -0,0 +1,21 @@ +// check-pass + +#![deny(unreachable_patterns)] + +fn main() { + match (3,42) { + (a,_) | (_,a) if a > 10 => {println!("{}", a)} + _ => () + } + + match Some((3,42)) { + Some((a, _)) | Some((_, a)) if a > 10 => {println!("{}", a)} + _ => () + + } + + match Some((3,42)) { + Some((a, _) | (_, a)) if a > 10 => {println!("{}", a)} + _ => () + } +} diff --git a/tests/ui/or-patterns/let-pattern.rs b/tests/ui/or-patterns/let-pattern.rs new file mode 100644 index 000000000..97207e83e --- /dev/null +++ b/tests/ui/or-patterns/let-pattern.rs @@ -0,0 +1,17 @@ +// run-pass + +fn or_pat_let(x: Result) -> u32 { + let (Ok(y) | Err(y)) = x; + y +} + +fn or_pat_arg((Ok(y) | Err(y)): Result) -> u32 { + y +} + +fn main() { + assert_eq!(or_pat_let(Ok(3)), 3); + assert_eq!(or_pat_let(Err(5)), 5); + assert_eq!(or_pat_arg(Ok(7)), 7); + assert_eq!(or_pat_arg(Err(9)), 9); +} diff --git a/tests/ui/or-patterns/macro-pat.rs b/tests/ui/or-patterns/macro-pat.rs new file mode 100644 index 000000000..20d8f84c2 --- /dev/null +++ b/tests/ui/or-patterns/macro-pat.rs @@ -0,0 +1,41 @@ +// run-pass +// edition:2021 + +use Foo::*; + +#[allow(dead_code)] +#[derive(Eq, PartialEq, Debug)] +enum Foo { + A(u64), + B(u64), + C, + D, +} + +macro_rules! foo { + ($orpat:pat, $val:expr) => { + match $val { + x @ ($orpat) => x, // leading vert would not be allowed in $orpat + _ => B(0xDEADBEEFu64), + } + }; +} + +macro_rules! bar { + ($orpat:pat, $val:expr) => { + match $val { + $orpat => 42, // leading vert allowed here + _ => 0xDEADBEEFu64, + } + }; +} + +fn main() { + // Test or-pattern. + let y = foo!(A(_)|B(_), A(32)); + assert_eq!(y, A(32)); + + // Leading vert in or-pattern. + let y = bar!(|C| D, C); + assert_eq!(y, 42u64); +} diff --git a/tests/ui/or-patterns/mismatched-bindings-async-fn.rs b/tests/ui/or-patterns/mismatched-bindings-async-fn.rs new file mode 100644 index 000000000..d1cb73aaf --- /dev/null +++ b/tests/ui/or-patterns/mismatched-bindings-async-fn.rs @@ -0,0 +1,14 @@ +// Regression test for #71297 +// edition:2018 + +async fn a((x | s): String) {} +//~^ ERROR variable `x` is not bound in all patterns +//~| ERROR variable `s` is not bound in all patterns + +async fn b() { + let (x | s) = String::new(); + //~^ ERROR variable `x` is not bound in all patterns + //~| ERROR variable `s` is not bound in all patterns +} + +fn main() {} diff --git a/tests/ui/or-patterns/mismatched-bindings-async-fn.stderr b/tests/ui/or-patterns/mismatched-bindings-async-fn.stderr new file mode 100644 index 000000000..81602fffa --- /dev/null +++ b/tests/ui/or-patterns/mismatched-bindings-async-fn.stderr @@ -0,0 +1,35 @@ +error[E0408]: variable `s` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:4:13 + | +LL | async fn a((x | s): String) {} + | ^ - variable not in all patterns + | | + | pattern doesn't bind `s` + +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:4:17 + | +LL | async fn a((x | s): String) {} + | - ^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error[E0408]: variable `s` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:9:10 + | +LL | let (x | s) = String::new(); + | ^ - variable not in all patterns + | | + | pattern doesn't bind `s` + +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/mismatched-bindings-async-fn.rs:9:14 + | +LL | let (x | s) = String::new(); + | - ^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/or-patterns/missing-bindings.rs b/tests/ui/or-patterns/missing-bindings.rs new file mode 100644 index 000000000..7c26012c0 --- /dev/null +++ b/tests/ui/or-patterns/missing-bindings.rs @@ -0,0 +1,81 @@ +// This test ensures that or patterns do not allow missing bindings in any of the arms. + +// edition:2018 + +#![allow(non_camel_case_types)] + +fn main() {} + +fn check_handling_of_paths() { + mod bar { + pub enum foo { + alpha, + beta, + charlie + } + } + + use bar::foo::{alpha, charlie}; + let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns + match Some(alpha) { + Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns + } +} + +fn check_misc_nesting() { + enum E { A(T, T), B(T) } + use E::*; + enum Vars3 { V1(S), V2(T), V3(U) } + use Vars3::*; + + // One level: + const X: E = B(0); + let (A(a, _) | _) = X; //~ ERROR variable `a` is not bound in all patterns + let (_ | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(..) | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(a, _) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(_, a) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(a, b) | B(a)) = X; //~ ERROR variable `b` is not bound in all patterns + + // Two levels: + const Y: E> = B(B(0)); + let (A(A(..) | B(_), _) | B(a)) = Y; //~ ERROR variable `a` is not bound in all patterns + let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; + //~^ ERROR variable `a` is not bound in all patterns + let (A(A(a, b) | B(c), d) | B(e)) = Y; + //~^ ERROR variable `a` is not bound in all patterns + //~| ERROR variable `a` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + //~| ERROR variable `c` is not bound in all patterns + //~| ERROR variable `c` is not bound in all patterns + //~| ERROR variable `d` is not bound in all patterns + //~| ERROR variable `e` is not bound in all patterns + + // Three levels: + let ( + V1( + //~^ ERROR variable `b` is not bound in all patterns + //~| ERROR variable `c` is not bound in all patterns + A( + Ok(a) | Err(_), //~ ERROR variable `a` is not bound in all patterns + _ + ) | + B(Ok(a) | Err(a)) + ) | + V2( + A( + A(_, a) | //~ ERROR variable `b` is not bound in all patterns + B(b), //~ ERROR variable `a` is not bound in all patterns + _ + ) | + B(_) + //~^ ERROR variable `a` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + ) | + V3(c), + //~^ ERROR variable `a` is not bound in all patterns + ) + : (Vars3>, E>, u8>,) + = (V3(0),); +} diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr new file mode 100644 index 000000000..8fafa275b --- /dev/null +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -0,0 +1,242 @@ +error[E0408]: variable `beta` is not bound in all patterns + --> $DIR/missing-bindings.rs:19:10 + | +LL | let (alpha | beta | charlie) = alpha; + | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` + | | | + | | variable not in all patterns + | pattern doesn't bind `beta` + +error[E0408]: variable `beta` is not bound in all patterns + --> $DIR/missing-bindings.rs:21:14 + | +LL | Some(alpha | beta) => {} + | ^^^^^ ---- variable not in all patterns + | | + | pattern doesn't bind `beta` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:33:20 + | +LL | let (A(a, _) | _) = X; + | - ^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:34:10 + | +LL | let (_ | B(a)) = X; + | ^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:35:10 + | +LL | let (A(..) | B(a)) = X; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:36:20 + | +LL | let (A(a, _) | B(_)) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:37:20 + | +LL | let (A(_, a) | B(_)) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:38:20 + | +LL | let (A(a, b) | B(a)) = X; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:42:10 + | +LL | let (A(A(..) | B(_), _) | B(a)) = Y; + | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:43:12 + | +LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:22 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:22 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:12 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `c` + +error[E0408]: variable `d` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:33 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `d` + | | + | variable not in all patterns + +error[E0408]: variable `e` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:10 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `e` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:33 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:33 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:45:33 + | +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `c` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:61:29 + | +LL | Ok(a) | Err(_), + | - ^^^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:69:21 + | +LL | A(_, a) | + | - variable not in all patterns +LL | B(b), + | ^^^^ pattern doesn't bind `a` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:68:21 + | +LL | A(_, a) | + | ^^^^^^^ pattern doesn't bind `b` +LL | B(b), + | - variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:72:17 + | +LL | A(_, a) | + | - variable not in all patterns +... +LL | B(_) + | ^^^^ pattern doesn't bind `a` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:72:17 + | +LL | B(b), + | - variable not in all patterns +... +LL | B(_) + | ^^^^ pattern doesn't bind `b` + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/missing-bindings.rs:76:13 + | +LL | B(Ok(a) | Err(a)) + | - variable not in all patterns +... +LL | A(_, a) | + | - variable not in all patterns +... +LL | V3(c), + | ^^^^^ pattern doesn't bind `a` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/missing-bindings.rs:57:13 + | +LL | / V1( +LL | | +LL | | +LL | | A( +... | +LL | | B(Ok(a) | Err(a)) +LL | | ) | + | |_____________^ pattern doesn't bind `b` +... +LL | B(b), + | - variable not in all patterns +... +LL | V3(c), + | ^^^^^ pattern doesn't bind `b` + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/missing-bindings.rs:57:13 + | +LL | / V1( +LL | | +LL | | +LL | | A( +... | +LL | | B(Ok(a) | Err(a)) +LL | | ) | + | |_____________^ pattern doesn't bind `c` +LL | / V2( +LL | | A( +LL | | A(_, a) | +LL | | B(b), +... | +LL | | +LL | | ) | + | |_____________^ pattern doesn't bind `c` +LL | V3(c), + | - variable not in all patterns + +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/or-patterns/mix-with-wild.rs b/tests/ui/or-patterns/mix-with-wild.rs new file mode 100644 index 000000000..d9911cda1 --- /dev/null +++ b/tests/ui/or-patterns/mix-with-wild.rs @@ -0,0 +1,18 @@ +// Test that an or-pattern works with a wild pattern. This tests two things: +// +// 1) The Wild pattern should cause the pattern to always succeed. +// 2) or-patterns should work with simplifyable patterns. + +// run-pass + +pub fn test(x: Option) -> bool { + match x { + Some(0 | _) => true, + _ => false, + } +} + +fn main() { + assert!(test(Some(42))); + assert!(!test(None)); +} diff --git a/tests/ui/or-patterns/multiple-pattern-typo.rs b/tests/ui/or-patterns/multiple-pattern-typo.rs new file mode 100644 index 000000000..5f2012533 --- /dev/null +++ b/tests/ui/or-patterns/multiple-pattern-typo.rs @@ -0,0 +1,44 @@ +//! Test for `||` in or-patterns + +fn main() { + let x = 3; + + match x { + 1 | 2 || 3 => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } + + match x { + (1 | 2 || 3) => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } + + match (x,) { + (1 | 2 || 3,) => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } + + struct TS(u8); + + match TS(x) { + TS(1 | 2 || 3) => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } + + struct NS { f: u8 } + + match (NS { f: x }) { + NS { f: 1 | 2 || 3 } => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } + + match [x] { + [1 | 2 || 3] => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } + + match x { + || 1 | 2 | 3 => (), //~ ERROR unexpected token `||` in pattern + _ => (), + } +} diff --git a/tests/ui/or-patterns/multiple-pattern-typo.stderr b/tests/ui/or-patterns/multiple-pattern-typo.stderr new file mode 100644 index 000000000..b0a82b367 --- /dev/null +++ b/tests/ui/or-patterns/multiple-pattern-typo.stderr @@ -0,0 +1,56 @@ +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:7:15 + | +LL | 1 | 2 || 3 => (), + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:12:16 + | +LL | (1 | 2 || 3) => (), + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:17:16 + | +LL | (1 | 2 || 3,) => (), + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:24:18 + | +LL | TS(1 | 2 || 3) => (), + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:31:23 + | +LL | NS { f: 1 | 2 || 3 } => (), + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:36:16 + | +LL | [1 | 2 || 3] => (), + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/multiple-pattern-typo.rs:41:9 + | +LL | || 1 | 2 | 3 => (), + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/or-patterns/nested-undelimited-precedence.rs b/tests/ui/or-patterns/nested-undelimited-precedence.rs new file mode 100644 index 000000000..047836203 --- /dev/null +++ b/tests/ui/or-patterns/nested-undelimited-precedence.rs @@ -0,0 +1,44 @@ +// This test tests the precedence of `|` (or-patterns) undelimited nested patterns. In particular, +// we want to reserve the syntactic space of a pattern followed by a type annotation for possible +// future type ascription, so we need to make sure that any time a pattern is followed by type +// annotation (for now), the pattern is not a top-level or-pattern. However, there are also a few +// types of patterns that allow undelimited subpatterns that could cause the same ambiguity. +// Currently, those should be impossible due to precedence rule. This test enforces that. + +enum E { + A, + B, +} + +fn foo() { + use E::*; + + // ok + let b @ (A | B): E = A; + + let b @ A | B: E = A; //~ERROR `b` is not bound in all patterns + //~^ ERROR top-level or-patterns are not allowed +} + +enum F { + A(usize), + B(usize), +} + +fn bar() { + use F::*; + + // ok + let (A(x) | B(x)): F = A(3); + + let &A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &&A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &mut A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &&mut A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed +} + +fn main() {} diff --git a/tests/ui/or-patterns/nested-undelimited-precedence.stderr b/tests/ui/or-patterns/nested-undelimited-precedence.stderr new file mode 100644 index 000000000..2e25d8b3e --- /dev/null +++ b/tests/ui/or-patterns/nested-undelimited-precedence.stderr @@ -0,0 +1,86 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:19:9 + | +LL | let b @ A | B: E = A; + | ^^^^^^^^^ help: wrap the pattern in parentheses: `(b @ A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:34:9 + | +LL | let &A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:36:9 + | +LL | let &&A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:38:9 + | +LL | let &mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&mut A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:40:9 + | +LL | let &&mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&mut A(_) | B(_))` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/nested-undelimited-precedence.rs:19:17 + | +LL | let b @ A | B: E = A; + | - ^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:34:9 + | +LL | let &A(_) | B(_): F = A(3); + | ^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:36:9 + | +LL | let &&A(_) | B(_): F = A(3); + | ^^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:38:9 + | +LL | let &mut A(_) | B(_): F = A(3); + | ^^^^^^^^^ - expected due to this + | | + | expected enum `F`, found `&mut _` + | + = note: expected enum `F` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:40:9 + | +LL | let &&mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0308, E0408. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/or-patterns-binding-type-mismatch.rs b/tests/ui/or-patterns/or-patterns-binding-type-mismatch.rs new file mode 100644 index 000000000..fa470de7f --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-binding-type-mismatch.rs @@ -0,0 +1,66 @@ +// Here we test type checking of bindings when combined with or-patterns. +// Specifically, we ensure that introducing bindings of different types result in type errors. + +fn main() { + enum Blah { + A(isize, isize, usize), + B(isize, isize), + } + + match Blah::A(1, 1, 2) { + Blah::A(_, x, y) | Blah::B(x, y) => {} //~ ERROR mismatched types + } + + match Some(Blah::A(1, 1, 2)) { + Some(Blah::A(_, x, y) | Blah::B(x, y)) => {} //~ ERROR mismatched types + } + + match (0u8, 1u16) { + (x, y) | (y, x) => {} //~ ERROR mismatched types + //~^ ERROR mismatched types + } + + match Some((0u8, Some((1u16, 2u32)))) { + Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + _ => {} + } + + if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { + //~^ ERROR mismatched types + } + + if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) { + //~^ ERROR mismatched types + } + + if let (x, y) | (y, x) = (0u8, 1u16) { + //~^ ERROR mismatched types + //~| ERROR mismatched types + } + + if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + = Some((0u8, Some((1u16, 2u32)))) + {} + + let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); + //~^ ERROR mismatched types + + let ((x, y) | (y, x)) = (0u8, 1u16); + //~^ ERROR mismatched types + //~| ERROR mismatched types + + fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} + //~^ ERROR mismatched types + + fn f2(((x, y) | (y, x)): (u8, u16)) {} + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/tests/ui/or-patterns/or-patterns-binding-type-mismatch.stderr new file mode 100644 index 000000000..00ce46c56 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -0,0 +1,257 @@ +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:11:39 + | +LL | match Blah::A(1, 1, 2) { + | ---------------- this expression has type `Blah` +LL | Blah::A(_, x, y) | Blah::B(x, y) => {} + | - ^ expected `usize`, found `isize` + | | + | first introduced with type `usize` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:15:44 + | +LL | match Some(Blah::A(1, 1, 2)) { + | ---------------------- this expression has type `Option` +LL | Some(Blah::A(_, x, y) | Blah::B(x, y)) => {} + | - ^ expected `usize`, found `isize` + | | + | first introduced with type `usize` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:19:19 + | +LL | match (0u8, 1u16) { + | ----------- this expression has type `(u8, u16)` +LL | (x, y) | (y, x) => {} + | - ^ expected `u16`, found `u8` + | | + | first introduced with type `u16` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:19:22 + | +LL | match (0u8, 1u16) { + | ----------- this expression has type `(u8, u16)` +LL | (x, y) | (y, x) => {} + | - ^ expected `u8`, found `u16` + | | + | first introduced with type `u8` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:24:41 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | - ^ expected `u16`, found `u8` + | | + | first introduced with type `u16` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:24:50 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | - ^ expected `u8`, found `u16` + | | + | first introduced with type `u8` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:24:59 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | - ^ expected `u32`, found `u16` + | | + | first introduced with type `u32` here + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:24:62 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | - first introduced with type `u8` here ^ expected `u8`, found `u32` + | + = note: in the same arm, a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:32:42 + | +LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { + | - ^ ---------------- this expression has type `Blah` + | | | + | | expected `usize`, found `isize` + | first introduced with type `usize` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:36:47 + | +LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) { + | - ^ ---------------------- this expression has type `Option` + | | | + | | expected `usize`, found `isize` + | first introduced with type `usize` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:40:22 + | +LL | if let (x, y) | (y, x) = (0u8, 1u16) { + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u16`, found `u8` + | first introduced with type `u16` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:40:25 + | +LL | if let (x, y) | (y, x) = (0u8, 1u16) { + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u8`, found `u16` + | first introduced with type `u8` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:45:44 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | - ^ expected `u16`, found `u8` + | | + | first introduced with type `u16` here +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:45:53 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | - ^ expected `u8`, found `u16` + | | + | first introduced with type `u8` here +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:45:62 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | - ^ expected `u32`, found `u16` + | | + | first introduced with type `u32` here +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:45:65 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | - first introduced with type `u8` here ^ expected `u8`, found `u32` +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `Option<(u8, Option<(u16, u32)>)>` + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:53:40 + | +LL | let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); + | - ^ ---------------- this expression has type `Blah` + | | | + | | expected `usize`, found `isize` + | first introduced with type `usize` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:56:20 + | +LL | let ((x, y) | (y, x)) = (0u8, 1u16); + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u16`, found `u8` + | first introduced with type `u16` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:56:23 + | +LL | let ((x, y) | (y, x)) = (0u8, 1u16); + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u8`, found `u16` + | first introduced with type `u8` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:60:42 + | +LL | fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} + | - ^ ---- expected due to this + | | | + | | expected `usize`, found `isize` + | first introduced with type `usize` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:63:22 + | +LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} + | - ^ --------- expected due to this + | | | + | | expected `u16`, found `u8` + | first introduced with type `u16` here + | + = note: a binding must have the same type in all alternatives + +error[E0308]: mismatched types + --> $DIR/or-patterns-binding-type-mismatch.rs:63:25 + | +LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} + | - ^ --------- expected due to this + | | | + | | expected `u8`, found `u16` + | first introduced with type `u8` here + | + = note: a binding must have the same type in all alternatives + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs new file mode 100644 index 000000000..e56f9ffe2 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs @@ -0,0 +1,131 @@ +// Test that or-patterns are pass-through with respect to default binding modes. + +// check-pass + +#![allow(irrefutable_let_patterns)] + +fn main() { + // A regression test for a mistake we made at one point: + match &1 { + e @ &(1..=2) | e @ &(3..=4) => {} + _ => {} + } + + match &0 { + 0 | &1 => {} + _ => {} + } + + type R<'a> = &'a Result; + + let res: R<'_> = &Ok(0); + + match res { + // Alternatives propagate expected type / binding mode independently. + Ok(mut x) | &Err(mut x) => drop::(x), + } + match res { + &(Ok(x) | Err(x)) => drop::(x), + } + match res { + Ok(x) | Err(x) => drop::<&u8>(x), + } + if let Ok(mut x) | &Err(mut x) = res { + drop::(x); + } + if let &(Ok(x) | Err(x)) = res { + drop::(x); + } + let (Ok(mut x) | &Err(mut x)) = res; + drop::(x); + let &(Ok(x) | Err(x)) = res; + drop::(x); + let (Ok(x) | Err(x)) = res; + drop::<&u8>(x); + for Ok(mut x) | &Err(mut x) in std::iter::once(res) { + drop::(x); + } + for &(Ok(x) | Err(x)) in std::iter::once(res) { + drop::(x); + } + for Ok(x) | Err(x) in std::iter::once(res) { + drop::<&u8>(x); + } + fn f1((Ok(mut x) | &Err(mut x)): R<'_>) { + drop::(x); + } + fn f2(&(Ok(x) | Err(x)): R<'_>) { + drop::(x); + } + fn f3((Ok(x) | Err(x)): R<'_>) { + drop::<&u8>(x); + } + + // Wrap inside another type (a product for a simplity with irrefutable contexts). + #[derive(Copy, Clone)] + struct Wrap(T); + let wres = Wrap(res); + + match wres { + Wrap(Ok(mut x) | &Err(mut x)) => drop::(x), + } + match wres { + Wrap(&(Ok(x) | Err(x))) => drop::(x), + } + match wres { + Wrap(Ok(x) | Err(x)) => drop::<&u8>(x), + } + if let Wrap(Ok(mut x) | &Err(mut x)) = wres { + drop::(x); + } + if let Wrap(&(Ok(x) | Err(x))) = wres { + drop::(x); + } + if let Wrap(Ok(x) | Err(x)) = wres { + drop::<&u8>(x); + } + let Wrap(Ok(mut x) | &Err(mut x)) = wres; + drop::(x); + let Wrap(&(Ok(x) | Err(x))) = wres; + drop::(x); + let Wrap(Ok(x) | Err(x)) = wres; + drop::<&u8>(x); + for Wrap(Ok(mut x) | &Err(mut x)) in std::iter::once(wres) { + drop::(x); + } + for Wrap(&(Ok(x) | Err(x))) in std::iter::once(wres) { + drop::(x); + } + for Wrap(Ok(x) | Err(x)) in std::iter::once(wres) { + drop::<&u8>(x); + } + fn fw1(Wrap(Ok(mut x) | &Err(mut x)): Wrap>) { + drop::(x); + } + fn fw2(Wrap(&(Ok(x) | Err(x))): Wrap>) { + drop::(x); + } + fn fw3(Wrap(Ok(x) | Err(x)): Wrap>) { + drop::<&u8>(x); + } + + // Nest some more: + + enum Tri

{ + A(P), + B(P), + C(P), + } + + let tri = &Tri::A(&Ok(0)); + let (Tri::A(Ok(mut x) | Err(mut x)) + | Tri::B(&Ok(mut x) | Err(mut x)) + | &Tri::C(Ok(mut x) | Err(mut x))) = tri; + drop::(x); + + match tri { + Tri::A(Ok(mut x) | Err(mut x)) + | Tri::B(&Ok(mut x) | Err(mut x)) + | &Tri::C(Ok(mut x) | Err(mut x)) => drop::(x), + } +} diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs new file mode 100644 index 000000000..a624cbc89 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.rs @@ -0,0 +1,13 @@ +// Test that :pat doesn't accept top-level or-patterns in edition 2018. + +// edition:2018 + +fn main() {} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {}; +} + +accept_pat!(p | q); //~ ERROR no rules expected the token `|` +accept_pat!(|p| q); //~ ERROR no rules expected the token `|` diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr new file mode 100644 index 000000000..acc2099bb --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr @@ -0,0 +1,32 @@ +error: no rules expected the token `|` + --> $DIR/or-patterns-syntactic-fail-2018.rs:12:15 + | +LL | macro_rules! accept_pat { + | ----------------------- when calling this macro +... +LL | accept_pat!(p | q); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$p:pat` + --> $DIR/or-patterns-syntactic-fail-2018.rs:9:6 + | +LL | ($p:pat) => {}; + | ^^^^^^ + +error: no rules expected the token `|` + --> $DIR/or-patterns-syntactic-fail-2018.rs:13:13 + | +LL | macro_rules! accept_pat { + | ----------------------- when calling this macro +... +LL | accept_pat!(|p| q); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$p:pat` + --> $DIR/or-patterns-syntactic-fail-2018.rs:9:6 + | +LL | ($p:pat) => {}; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail.rs b/tests/ui/or-patterns/or-patterns-syntactic-fail.rs new file mode 100644 index 000000000..358e9d034 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -0,0 +1,30 @@ +// Test some cases where or-patterns may ostensibly be allowed but are in fact not. +// This is not a semantic test. We only test parsing. + +fn main() {} + +enum E { A, B } +use E::*; + +fn no_top_level_or_patterns() { + // We do *not* allow or-patterns at the top level of lambdas... + let _ = |A | B: E| (); //~ ERROR no implementation for `E | ()` + // -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`. + + // ...and for now neither do we allow or-patterns at the top level of functions. + fn fun1(A | B: E) {} + //~^ ERROR top-level or-patterns are not allowed + + fn fun2(| A | B: E) {} + //~^ ERROR top-level or-patterns are not allowed + + // We don't allow top-level or-patterns before type annotation in let-statements because we + // want to reserve this syntactic space for possible future type ascription. + let A | B: E = A; + //~^ ERROR top-level or-patterns are not allowed + + let | A | B: E = A; + //~^ ERROR top-level or-patterns are not allowed + + let (A | B): E = A; // ok -- wrapped in parens +} diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr new file mode 100644 index 000000000..10d42b7e3 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -0,0 +1,43 @@ +error: top-level or-patterns are not allowed in function parameters + --> $DIR/or-patterns-syntactic-fail.rs:15:13 + | +LL | fn fun1(A | B: E) {} + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in function parameters + --> $DIR/or-patterns-syntactic-fail.rs:18:13 + | +LL | fn fun2(| A | B: E) {} + | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/or-patterns-syntactic-fail.rs:23:9 + | +LL | let A | B: E = A; + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/or-patterns-syntactic-fail.rs:26:9 + | +LL | let | A | B: E = A; + | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error[E0369]: no implementation for `E | ()` + --> $DIR/or-patterns-syntactic-fail.rs:11:22 + | +LL | let _ = |A | B: E| (); + | ----^ -- () + | | + | E + | +note: an implementation of `BitOr<_>` might be missing for `E` + --> $DIR/or-patterns-syntactic-fail.rs:6:1 + | +LL | enum E { A, B } + | ^^^^^^ must implement `BitOr<_>` +note: the trait `BitOr` must be implemented + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/or-patterns/or-patterns-syntactic-pass-2021.rs b/tests/ui/or-patterns/or-patterns-syntactic-pass-2021.rs new file mode 100644 index 000000000..c0d148d92 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-pass-2021.rs @@ -0,0 +1,12 @@ +// Tests that :pat in macros in edition 2021 allows top-level or-patterns. + +// run-pass +// edition:2021 + +macro_rules! accept_pat { + ($p:pat) => {}; +} + +accept_pat!(p | q); + +fn main() {} diff --git a/tests/ui/or-patterns/or-patterns-syntactic-pass.rs b/tests/ui/or-patterns/or-patterns-syntactic-pass.rs new file mode 100644 index 000000000..92750bec8 --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -0,0 +1,78 @@ +// Here we test all the places `|` is *syntactically* allowed. +// This is not a semantic test. We only test parsing. + +// check-pass + +fn main() {} + +// Test the `pat` macro fragment parser: +macro_rules! accept_pat { + ($p:pat) => {}; +} + +accept_pat!((p | q)); +accept_pat!((p | q,)); +accept_pat!(TS(p | q)); +accept_pat!(NS { f: p | q }); +accept_pat!([p | q]); + +// Non-macro tests: + +#[cfg(FALSE)] +fn or_patterns() { + // Top level of `let`: + let (| A | B); + let (A | B); + let (A | B): u8; + let (A | B) = 0; + let (A | B): u8 = 0; + + // Top level of `for`: + for | A | B in 0 {} + for A | B in 0 {} + + // Top level of `while`: + while let | A | B = 0 {} + while let A | B = 0 {} + + // Top level of `if`: + if let | A | B = 0 {} + if let A | B = 0 {} + + // Top level of `match` arms: + match 0 { + | A | B => {} + A | B => {} + } + + // Functions: + fn fun((A | B): _) {} + + // Lambdas: + let _ = |(A | B): u8| (); + + // Parenthesis and tuple patterns: + let (A | B); + let (A | B,); + + // Tuple struct patterns: + let A(B | C); + let E::V(B | C); + + // Struct patterns: + let S { f1: B | C, f2 }; + let E::V { f1: B | C, f2 }; + + // Slice patterns: + let [A | B, .. | ..]; + + // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`: + let (box 0 | 1); // Unstable; we *can* change the precedence if we want. + //~^ WARN box pattern syntax is experimental + //~| WARN unstable syntax + let (&0 | 1); + let (&mut 0 | 1); + let (x @ 0 | 1); + let (ref x @ 0 | 1); + let (ref mut x @ 0 | 1); +} diff --git a/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr b/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr new file mode 100644 index 000000000..c43fe192a --- /dev/null +++ b/tests/ui/or-patterns/or-patterns-syntactic-pass.stderr @@ -0,0 +1,13 @@ +warning: box pattern syntax is experimental + --> $DIR/or-patterns-syntactic-pass.rs:70:10 + | +LL | let (box 0 | 1); // Unstable; we *can* change the precedence if we want. + | ^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 1 warning emitted + diff --git a/tests/ui/or-patterns/remove-leading-vert.fixed b/tests/ui/or-patterns/remove-leading-vert.fixed new file mode 100644 index 000000000..b1cd0a944 --- /dev/null +++ b/tests/ui/or-patterns/remove-leading-vert.fixed @@ -0,0 +1,48 @@ +// Test the suggestion to remove a leading, or trailing `|`. + +// run-rustfix + +#![allow(warnings)] + +fn main() {} + +#[cfg(FALSE)] +fn leading() { + fn fun1( A: E) {} //~ ERROR top-level or-patterns are not allowed + fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter + let ( | A): E; + let ( | A): (E); //~ ERROR unexpected token `||` in pattern + let ( | A,): (E,); + let [ | A ]: [E; 1]; + let [ | A ]: [E; 1]; //~ ERROR unexpected token `||` in pattern + let TS( | A ): TS; + let TS( | A ): TS; //~ ERROR unexpected token `||` in pattern + let NS { f: | A }: NS; + let NS { f: | A }: NS; //~ ERROR unexpected token `||` in pattern +} + +#[cfg(FALSE)] +fn trailing() { + let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern + let (a ,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern + let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern + let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern + let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern + let ( A | B ): E; //~ ERROR unexpected token `||` in pattern + //~^ ERROR a trailing `|` is not allowed in an or-pattern + match A { + A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern + A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern + A | B => {} //~ ERROR unexpected token `||` in pattern + //~^ ERROR a trailing `|` is not allowed in an or-pattern + | A | B => {} + //~^ ERROR a trailing `|` is not allowed in an or-pattern + } + + // These test trailing-vert in `let` bindings, but they also test that we don't emit a + // duplicate suggestion that would confuse rustfix. + + let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern +} diff --git a/tests/ui/or-patterns/remove-leading-vert.rs b/tests/ui/or-patterns/remove-leading-vert.rs new file mode 100644 index 000000000..dc12382aa --- /dev/null +++ b/tests/ui/or-patterns/remove-leading-vert.rs @@ -0,0 +1,48 @@ +// Test the suggestion to remove a leading, or trailing `|`. + +// run-rustfix + +#![allow(warnings)] + +fn main() {} + +#[cfg(FALSE)] +fn leading() { + fn fun1( | A: E) {} //~ ERROR top-level or-patterns are not allowed + fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter + let ( | A): E; + let ( || A): (E); //~ ERROR unexpected token `||` in pattern + let ( | A,): (E,); + let [ | A ]: [E; 1]; + let [ || A ]: [E; 1]; //~ ERROR unexpected token `||` in pattern + let TS( | A ): TS; + let TS( || A ): TS; //~ ERROR unexpected token `||` in pattern + let NS { f: | A }: NS; + let NS { f: || A }: NS; //~ ERROR unexpected token `||` in pattern +} + +#[cfg(FALSE)] +fn trailing() { + let ( A | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern + let (a |,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern + let ( A | B | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern + let [ A | B | ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern + let S { f: B | }; //~ ERROR a trailing `|` is not allowed in an or-pattern + let ( A || B | ): E; //~ ERROR unexpected token `||` in pattern + //~^ ERROR a trailing `|` is not allowed in an or-pattern + match A { + A | => {} //~ ERROR a trailing `|` is not allowed in an or-pattern + A || => {} //~ ERROR a trailing `|` is not allowed in an or-pattern + A || B | => {} //~ ERROR unexpected token `||` in pattern + //~^ ERROR a trailing `|` is not allowed in an or-pattern + | A | B | => {} + //~^ ERROR a trailing `|` is not allowed in an or-pattern + } + + // These test trailing-vert in `let` bindings, but they also test that we don't emit a + // duplicate suggestion that would confuse rustfix. + + let a | : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a | = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a | ; //~ ERROR a trailing `|` is not allowed in an or-pattern +} diff --git a/tests/ui/or-patterns/remove-leading-vert.stderr b/tests/ui/or-patterns/remove-leading-vert.stderr new file mode 100644 index 000000000..af51c67e1 --- /dev/null +++ b/tests/ui/or-patterns/remove-leading-vert.stderr @@ -0,0 +1,162 @@ +error: top-level or-patterns are not allowed in function parameters + --> $DIR/remove-leading-vert.rs:11:14 + | +LL | fn fun1( | A: E) {} + | ^^^ help: remove the `|`: `A` + +error: unexpected `||` before function parameter + --> $DIR/remove-leading-vert.rs:12:14 + | +LL | fn fun2( || A: E) {} + | ^^ help: remove the `||` + | + = note: alternatives in or-patterns are separated with `|`, not `||` + +error: unexpected token `||` in pattern + --> $DIR/remove-leading-vert.rs:14:11 + | +LL | let ( || A): (E); + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` in pattern + --> $DIR/remove-leading-vert.rs:17:11 + | +LL | let [ || A ]: [E; 1]; + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` in pattern + --> $DIR/remove-leading-vert.rs:19:13 + | +LL | let TS( || A ): TS; + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: unexpected token `||` in pattern + --> $DIR/remove-leading-vert.rs:21:17 + | +LL | let NS { f: || A }: NS; + | ^^ help: use a single `|` to separate multiple alternative patterns: `|` + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:26:13 + | +LL | let ( A | ): E; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:27:12 + | +LL | let (a |,): (E,); + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:28:17 + | +LL | let ( A | B | ): E; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:29:17 + | +LL | let [ A | B | ]: [E; 1]; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:30:18 + | +LL | let S { f: B | }; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: unexpected token `||` in pattern + --> $DIR/remove-leading-vert.rs:31:13 + | +LL | let ( A || B | ): E; + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:31:18 + | +LL | let ( A || B | ): E; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:34:11 + | +LL | A | => {} + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:35:11 + | +LL | A || => {} + | - ^^ help: remove the `||` + | | + | while parsing this or-pattern starting here + | + = note: alternatives in or-patterns are separated with `|`, not `||` + +error: unexpected token `||` in pattern + --> $DIR/remove-leading-vert.rs:36:11 + | +LL | A || B | => {} + | - ^^ help: use a single `|` to separate multiple alternative patterns: `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:36:16 + | +LL | A || B | => {} + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:38:17 + | +LL | | A | B | => {} + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:45:11 + | +LL | let a | : u8 = 0; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:46:11 + | +LL | let a | = 0; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/remove-leading-vert.rs:47:11 + | +LL | let a | ; + | - ^ help: remove the `|` + | | + | while parsing this or-pattern starting here + +error: aborting due to 21 previous errors + diff --git a/tests/ui/or-patterns/search-via-bindings.rs b/tests/ui/or-patterns/search-via-bindings.rs new file mode 100644 index 000000000..d98606ded --- /dev/null +++ b/tests/ui/or-patterns/search-via-bindings.rs @@ -0,0 +1,63 @@ +// Check that we expand multiple or-patterns from left to right. + +// run-pass + +fn search(target: (bool, bool, bool)) -> u32 { + let x = ((false, true), (false, true), (false, true)); + let mut guard_count = 0; + match x { + ((a, _) | (_, a), (b @ _, _) | (_, b @ _), (c @ false, _) | (_, c @ true)) + if { + guard_count += 1; + (a, b, c) == target + } => + { + guard_count + } + _ => unreachable!(), + } +} + +// Equivalent to the above code, but hopefully easier to understand. +fn search_old_style(target: (bool, bool, bool)) -> u32 { + let x = ((false, true), (false, true), (false, true)); + let mut guard_count = 0; + match x { + ((a, _), (b @ _, _), (c @ false, _)) + | ((a, _), (b @ _, _), (_, c @ true)) + | ((a, _), (_, b @ _), (c @ false, _)) + | ((a, _), (_, b @ _), (_, c @ true)) + | ((_, a), (b @ _, _), (c @ false, _)) + | ((_, a), (b @ _, _), (_, c @ true)) + | ((_, a), (_, b @ _), (c @ false, _)) + | ((_, a), (_, b @ _), (_, c @ true)) + if { + guard_count += 1; + (a, b, c) == target + } => + { + guard_count + } + _ => unreachable!(), + } +} + +fn main() { + assert_eq!(search((false, false, false)), 1); + assert_eq!(search((false, false, true)), 2); + assert_eq!(search((false, true, false)), 3); + assert_eq!(search((false, true, true)), 4); + assert_eq!(search((true, false, false)), 5); + assert_eq!(search((true, false, true)), 6); + assert_eq!(search((true, true, false)), 7); + assert_eq!(search((true, true, true)), 8); + + assert_eq!(search_old_style((false, false, false)), 1); + assert_eq!(search_old_style((false, false, true)), 2); + assert_eq!(search_old_style((false, true, false)), 3); + assert_eq!(search_old_style((false, true, true)), 4); + assert_eq!(search_old_style((true, false, false)), 5); + assert_eq!(search_old_style((true, false, true)), 6); + assert_eq!(search_old_style((true, true, false)), 7); + assert_eq!(search_old_style((true, true, true)), 8); +} diff --git a/tests/ui/or-patterns/slice-patterns.rs b/tests/ui/or-patterns/slice-patterns.rs new file mode 100644 index 000000000..ed5eace0b --- /dev/null +++ b/tests/ui/or-patterns/slice-patterns.rs @@ -0,0 +1,51 @@ +// Test or-patterns with slice-patterns + +// run-pass + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option]) -> MatchArm { + match foo { + [.., Some(Test::Qux | Test::Foo)] => MatchArm::Arm(0), + [Some(Test::Foo), .., Some(Test::Baz | Test::Bar)] => MatchArm::Arm(1), + [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2), + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + // path 1a + assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Foo), Some(Test::Bar)]), MatchArm::Arm(1)); + // path 3a + assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); + // path 3b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), + MatchArm::Arm(2)); + // path 4 + assert_eq!(test(&foo[4..]), MatchArm::Wild); +} diff --git a/tests/ui/or-patterns/struct-like.rs b/tests/ui/or-patterns/struct-like.rs new file mode 100644 index 000000000..7de690d2d --- /dev/null +++ b/tests/ui/or-patterns/struct-like.rs @@ -0,0 +1,40 @@ +// run-pass + +#[derive(Debug)] +enum Other { + One, + Two, + Three, +} + +#[derive(Debug)] +enum Test { + Foo { first: usize, second: usize }, + Bar { other: Option }, + Baz, +} + +fn test(x: Option) -> bool { + match x { + Some( + Test::Foo { first: 1024 | 2048, second: 2048 | 4096 } + | Test::Bar { other: Some(Other::One | Other::Two) }, + ) => true, + // wild case + Some(_) => false, + // empty case + None => false, + } +} + +fn main() { + assert!(test(Some(Test::Foo { first: 1024, second: 4096 }))); + assert!(!test(Some(Test::Foo { first: 2048, second: 8192 }))); + assert!(!test(Some(Test::Foo { first: 42, second: 2048 }))); + assert!(test(Some(Test::Bar { other: Some(Other::One) }))); + assert!(test(Some(Test::Bar { other: Some(Other::Two) }))); + assert!(!test(Some(Test::Bar { other: Some(Other::Three) }))); + assert!(!test(Some(Test::Bar { other: None }))); + assert!(!test(Some(Test::Baz))); + assert!(!test(None)); +} diff --git a/tests/ui/or-patterns/while-parsing-this-or-pattern.rs b/tests/ui/or-patterns/while-parsing-this-or-pattern.rs new file mode 100644 index 000000000..b9bfb8638 --- /dev/null +++ b/tests/ui/or-patterns/while-parsing-this-or-pattern.rs @@ -0,0 +1,9 @@ +// Test the parser for the "while parsing this or-pattern..." label here. + +fn main() { + match Some(42) { + Some(42) | .=. => {} //~ ERROR expected pattern, found `.` + //~^ while parsing this or-pattern starting here + //~| NOTE expected pattern + } +} diff --git a/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr b/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr new file mode 100644 index 000000000..7ad62ff99 --- /dev/null +++ b/tests/ui/or-patterns/while-parsing-this-or-pattern.stderr @@ -0,0 +1,10 @@ +error: expected pattern, found `.` + --> $DIR/while-parsing-this-or-pattern.rs:5:20 + | +LL | Some(42) | .=. => {} + | -------- ^ expected pattern + | | + | while parsing this or-pattern starting here + +error: aborting due to previous error + diff --git a/tests/ui/order-dependent-cast-inference.rs b/tests/ui/order-dependent-cast-inference.rs new file mode 100644 index 000000000..e666209b9 --- /dev/null +++ b/tests/ui/order-dependent-cast-inference.rs @@ -0,0 +1,8 @@ +fn main() { + // Tests case where inference fails due to the order in which casts are checked. + // Ideally this would compile, see #48270. + let x = &"hello"; + let mut y = 0 as *const _; + //~^ ERROR cannot cast to a pointer of an unknown kind + y = x as *const _; +} diff --git a/tests/ui/order-dependent-cast-inference.stderr b/tests/ui/order-dependent-cast-inference.stderr new file mode 100644 index 000000000..9f4ac0fea --- /dev/null +++ b/tests/ui/order-dependent-cast-inference.stderr @@ -0,0 +1,11 @@ +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/order-dependent-cast-inference.rs:5:22 + | +LL | let mut y = 0 as *const _; + | ^^^^^^^^ needs more type information + | + = note: the type information given here is insufficient to check whether the pointer cast is valid + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0641`. diff --git a/tests/ui/orphan-check-diagnostics.rs b/tests/ui/orphan-check-diagnostics.rs new file mode 100644 index 000000000..c8803b9ae --- /dev/null +++ b/tests/ui/orphan-check-diagnostics.rs @@ -0,0 +1,14 @@ +// aux-build:orphan-check-diagnostics.rs + +// See issue #22388. + +extern crate orphan_check_diagnostics; + +use orphan_check_diagnostics::RemoteTrait; + +trait LocalTrait { fn dummy(&self) { } } + +impl RemoteTrait for T where T: LocalTrait {} +//~^ ERROR type parameter `T` must be used as the type parameter for some local type + +fn main() {} diff --git a/tests/ui/orphan-check-diagnostics.stderr b/tests/ui/orphan-check-diagnostics.stderr new file mode 100644 index 000000000..7a7cea563 --- /dev/null +++ b/tests/ui/orphan-check-diagnostics.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/orphan-check-diagnostics.rs:11:6 + | +LL | impl RemoteTrait for T where T: LocalTrait {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/osx-frameworks.rs b/tests/ui/osx-frameworks.rs new file mode 100644 index 000000000..958183ec0 --- /dev/null +++ b/tests/ui/osx-frameworks.rs @@ -0,0 +1,7 @@ +// ignore-macos this is supposed to succeed on osx + +#[link(name = "foo", kind = "framework")] +extern "C" {} +//~^^ ERROR: link kind `framework` is only supported on Apple targets + +fn main() {} diff --git a/tests/ui/osx-frameworks.stderr b/tests/ui/osx-frameworks.stderr new file mode 100644 index 000000000..e4a5c98dc --- /dev/null +++ b/tests/ui/osx-frameworks.stderr @@ -0,0 +1,9 @@ +error[E0455]: link kind `framework` is only supported on Apple targets + --> $DIR/osx-frameworks.rs:3:29 + | +LL | #[link(name = "foo", kind = "framework")] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0455`. diff --git a/tests/ui/out-pointer-aliasing.rs b/tests/ui/out-pointer-aliasing.rs new file mode 100644 index 000000000..b28a09101 --- /dev/null +++ b/tests/ui/out-pointer-aliasing.rs @@ -0,0 +1,23 @@ +// run-pass + +#[derive(Copy, Clone)] +pub struct Foo { + f1: isize, + _f2: isize, +} + +#[inline(never)] +pub fn foo(f: &mut Foo) -> Foo { + let ret = *f; + f.f1 = 0; + ret +} + +pub fn main() { + let mut f = Foo { + f1: 8, + _f2: 9, + }; + f = foo(&mut f); + assert_eq!(f.f1, 8); +} diff --git a/tests/ui/output-slot-variants.rs b/tests/ui/output-slot-variants.rs new file mode 100644 index 000000000..7c20a2b2f --- /dev/null +++ b/tests/ui/output-slot-variants.rs @@ -0,0 +1,69 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unknown_lints)] +// pretty-expanded FIXME #23616 + +#![allow(dead_assignment)] +#![allow(unused_variables)] + +struct A { a: isize, b: isize } +struct Abox { a: Box, b: Box } + +fn ret_int_i() -> isize { 10 } + +fn ret_ext_i() -> Box { Box::new(10) } + +fn ret_int_rec() -> A { A {a: 10, b: 10} } + +fn ret_ext_rec() -> Box { Box::new(A {a: 10, b: 10}) } + +fn ret_ext_mem() -> Abox { Abox {a: Box::new(10), b: Box::new(10) } } + +fn ret_ext_ext_mem() -> Box { Box::new(Abox{a: Box::new(10), b: Box::new(10) }) } + +pub fn main() { + let mut int_i: isize; + let mut ext_i: Box; + let mut int_rec: A; + let mut ext_rec: Box; + let mut ext_mem: Abox; + let mut ext_ext_mem: Box; + int_i = ret_int_i(); // initializing + + int_i = ret_int_i(); // non-initializing + + int_i = ret_int_i(); // non-initializing + + ext_i = ret_ext_i(); // initializing + + ext_i = ret_ext_i(); // non-initializing + + ext_i = ret_ext_i(); // non-initializing + + int_rec = ret_int_rec(); // initializing + + int_rec = ret_int_rec(); // non-initializing + + int_rec = ret_int_rec(); // non-initializing + + ext_rec = ret_ext_rec(); // initializing + + ext_rec = ret_ext_rec(); // non-initializing + + ext_rec = ret_ext_rec(); // non-initializing + + ext_mem = ret_ext_mem(); // initializing + + ext_mem = ret_ext_mem(); // non-initializing + + ext_mem = ret_ext_mem(); // non-initializing + + ext_ext_mem = ret_ext_ext_mem(); // initializing + + ext_ext_mem = ret_ext_ext_mem(); // non-initializing + + ext_ext_mem = ret_ext_ext_mem(); // non-initializing + +} diff --git a/tests/ui/output-type-mismatch.rs b/tests/ui/output-type-mismatch.rs new file mode 100644 index 000000000..35097aa9e --- /dev/null +++ b/tests/ui/output-type-mismatch.rs @@ -0,0 +1,5 @@ +// error-pattern: mismatched types + +fn f() { } + +fn main() { let i: isize; i = f(); } diff --git a/tests/ui/output-type-mismatch.stderr b/tests/ui/output-type-mismatch.stderr new file mode 100644 index 000000000..4507a4df6 --- /dev/null +++ b/tests/ui/output-type-mismatch.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/output-type-mismatch.rs:5:31 + | +LL | fn main() { let i: isize; i = f(); } + | ----- ^^^ expected `isize`, found `()` + | | + | expected due to this type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/over-constrained-vregs.rs b/tests/ui/over-constrained-vregs.rs new file mode 100644 index 000000000..cc8081476 --- /dev/null +++ b/tests/ui/over-constrained-vregs.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(unused_must_use)] +// Regression test for issue #152. +pub fn main() { + let mut b: usize = 1_usize; + while b < std::mem::size_of::() { + 0_usize << b; + b <<= 1_usize; + println!("{}", b); + } +} diff --git a/tests/ui/overloaded/auxiliary/overloaded_autoderef_xc.rs b/tests/ui/overloaded/auxiliary/overloaded_autoderef_xc.rs new file mode 100644 index 000000000..112455f91 --- /dev/null +++ b/tests/ui/overloaded/auxiliary/overloaded_autoderef_xc.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; + +struct DerefWithHelper { + pub helper: H, + pub value: Option +} + +trait Helper { + fn helper_borrow(&self) -> &T; +} + +impl Helper for Option { + fn helper_borrow(&self) -> &T { + self.as_ref().unwrap() + } +} + +impl> Deref for DerefWithHelper { + type Target = T; + + fn deref(&self) -> &T { + self.helper.helper_borrow() + } +} + +// Test cross-crate autoderef + vtable. +pub fn check(x: T, y: T) -> bool { + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x), value: None }; + d.eq(&y) +} diff --git a/tests/ui/overloaded/fixup-deref-mut.rs b/tests/ui/overloaded/fixup-deref-mut.rs new file mode 100644 index 000000000..6b2fd72b8 --- /dev/null +++ b/tests/ui/overloaded/fixup-deref-mut.rs @@ -0,0 +1,50 @@ +// run-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::ops::{Deref, DerefMut}; + +// Generic unique/owned smaht pointer. +struct Own { + value: *mut T +} + +impl Deref for Own { + type Target = T; + + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.value } + } +} + +impl DerefMut for Own { + fn deref_mut<'a>(&'a mut self) -> &'a mut T { + unsafe { &mut *self.value } + } +} + +struct Point { + x: isize, + y: isize +} + +impl Point { + fn get(&mut self) -> (isize, isize) { + (self.x, self.y) + } +} + +fn test0(mut x: Own) { + let _ = x.get(); +} + +fn test1(mut x: Own>>) { + let _ = x.get(); +} + +fn test2(mut x: Own>>) { + let _ = (**x).get(); +} + +fn main() {} diff --git a/tests/ui/overloaded/issue-14958.rs b/tests/ui/overloaded/issue-14958.rs new file mode 100644 index 000000000..a12564ca9 --- /dev/null +++ b/tests/ui/overloaded/issue-14958.rs @@ -0,0 +1,31 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![feature(fn_traits, unboxed_closures)] + +trait Foo { fn dummy(&self) { }} + +struct Bar; + +impl<'a> std::ops::Fn<(&'a (dyn Foo+'a),)> for Bar { + extern "rust-call" fn call(&self, _: (&'a dyn Foo,)) {} +} + +impl<'a> std::ops::FnMut<(&'a (dyn Foo+'a),)> for Bar { + extern "rust-call" fn call_mut(&mut self, a: (&'a dyn Foo,)) { self.call(a) } +} + +impl<'a> std::ops::FnOnce<(&'a (dyn Foo+'a),)> for Bar { + type Output = (); + extern "rust-call" fn call_once(self, a: (&'a dyn Foo,)) { self.call(a) } +} + +struct Baz; + +impl Foo for Baz {} + +fn main() { + let bar = Bar; + let baz = &Baz; + bar(baz); +} diff --git a/tests/ui/overloaded/overloaded-autoderef-count.rs b/tests/ui/overloaded/overloaded-autoderef-count.rs new file mode 100644 index 000000000..d58deda09 --- /dev/null +++ b/tests/ui/overloaded/overloaded-autoderef-count.rs @@ -0,0 +1,74 @@ +// run-pass +use std::cell::Cell; +use std::ops::{Deref, DerefMut}; + +#[derive(PartialEq)] +struct DerefCounter { + count_imm: Cell, + count_mut: usize, + value: T +} + +impl DerefCounter { + fn new(value: T) -> DerefCounter { + DerefCounter { + count_imm: Cell::new(0), + count_mut: 0, + value: value + } + } + + fn counts(&self) -> (usize, usize) { + (self.count_imm.get(), self.count_mut) + } +} + +impl Deref for DerefCounter { + type Target = T; + + fn deref(&self) -> &T { + self.count_imm.set(self.count_imm.get() + 1); + &self.value + } +} + +impl DerefMut for DerefCounter { + fn deref_mut(&mut self) -> &mut T { + self.count_mut += 1; + &mut self.value + } +} + +#[derive(PartialEq, Debug)] +struct Point { + x: isize, + y: isize +} + +impl Point { + fn get(&self) -> (isize, isize) { + (self.x, self.y) + } +} + +pub fn main() { + let mut p = DerefCounter::new(Point {x: 0, y: 0}); + + let _ = p.x; + assert_eq!(p.counts(), (1, 0)); + + let _ = &p.x; + assert_eq!(p.counts(), (2, 0)); + + let _ = &mut p.y; + assert_eq!(p.counts(), (2, 1)); + + p.x += 3; + assert_eq!(p.counts(), (2, 2)); + + p.get(); + assert_eq!(p.counts(), (3, 2)); + + // Check the final state. + assert_eq!(*p, Point {x: 3, y: 0}); +} diff --git a/tests/ui/overloaded/overloaded-autoderef-indexing.rs b/tests/ui/overloaded/overloaded-autoderef-indexing.rs new file mode 100644 index 000000000..1c8c7cca9 --- /dev/null +++ b/tests/ui/overloaded/overloaded-autoderef-indexing.rs @@ -0,0 +1,20 @@ +// run-pass + +use std::ops::Deref; + +struct DerefArray<'a, T:'a> { + inner: &'a [T] +} + +impl<'a, T> Deref for DerefArray<'a, T> { + type Target = &'a [T]; + + fn deref<'b>(&'b self) -> &'b &'a [T] { + &self.inner + } +} + +pub fn main() { + let a = &[1, 2, 3]; + assert_eq!(DerefArray {inner: a}[1], 2); +} diff --git a/tests/ui/overloaded/overloaded-autoderef-order.rs b/tests/ui/overloaded/overloaded-autoderef-order.rs new file mode 100644 index 000000000..f48bae55f --- /dev/null +++ b/tests/ui/overloaded/overloaded-autoderef-order.rs @@ -0,0 +1,73 @@ +// run-pass + +#![allow(dead_code)] + +use std::rc::Rc; +use std::ops::Deref; + +#[derive(Copy, Clone)] +struct DerefWrapper { + x: X, + y: Y +} + +impl DerefWrapper { + fn get_x(self) -> X { + self.x + } +} + +impl Deref for DerefWrapper { + type Target = Y; + + fn deref(&self) -> &Y { + &self.y + } +} + +mod priv_test { + use std::ops::Deref; + + #[derive(Copy, Clone)] + pub struct DerefWrapperHideX { + x: X, + pub y: Y + } + + impl DerefWrapperHideX { + pub fn new(x: X, y: Y) -> DerefWrapperHideX { + DerefWrapperHideX { + x: x, + y: y + } + } + } + + impl Deref for DerefWrapperHideX { + type Target = Y; + + fn deref(&self) -> &Y { + &self.y + } + } +} + +pub fn main() { + let nested = DerefWrapper {x: true, y: DerefWrapper {x: 0, y: 1}}; + + // Use the first field that you can find. + assert_eq!(nested.x, true); + assert_eq!((*nested).x, 0); + + // Same for methods, even though there are multiple + // candidates (at different nesting levels). + assert_eq!(nested.get_x(), true); + assert_eq!((*nested).get_x(), 0); + + // Also go through multiple levels of indirection. + assert_eq!(Rc::new(nested).x, true); + + let nested_priv = priv_test::DerefWrapperHideX::new(true, DerefWrapper {x: 0, y: 1}); + assert_eq!(nested_priv.x, 0); + assert_eq!((*nested_priv).x, 0); +} diff --git a/tests/ui/overloaded/overloaded-autoderef-vtable.rs b/tests/ui/overloaded/overloaded-autoderef-vtable.rs new file mode 100644 index 000000000..f8e6d1208 --- /dev/null +++ b/tests/ui/overloaded/overloaded-autoderef-vtable.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(dead_code)] + +use std::ops::Deref; + +struct DerefWithHelper { + helper: H, + value: T +} + +trait Helper { + fn helper_borrow(&self) -> &T; +} + +impl Helper for Option { + fn helper_borrow(&self) -> &T { + self.as_ref().unwrap() + } +} + +impl> Deref for DerefWithHelper { + type Target = T; + + fn deref(&self) -> &T { + self.helper.helper_borrow() + } +} + +struct Foo {x: isize} + +impl Foo { + fn foo(&self) -> isize {self.x} +} + +pub fn main() { + let x: DerefWithHelper, Foo> = + DerefWithHelper { helper: Some(Foo {x: 5}), value: Foo { x: 2 } }; + assert_eq!(x.foo(), 5); +} diff --git a/tests/ui/overloaded/overloaded-autoderef-xcrate.rs b/tests/ui/overloaded/overloaded-autoderef-xcrate.rs new file mode 100644 index 000000000..d065e825c --- /dev/null +++ b/tests/ui/overloaded/overloaded-autoderef-xcrate.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:overloaded_autoderef_xc.rs + + +extern crate overloaded_autoderef_xc; + +fn main() { + assert!(overloaded_autoderef_xc::check(5, 5)); +} diff --git a/tests/ui/overloaded/overloaded-autoderef.rs b/tests/ui/overloaded/overloaded-autoderef.rs new file mode 100644 index 000000000..cae3ec906 --- /dev/null +++ b/tests/ui/overloaded/overloaded-autoderef.rs @@ -0,0 +1,43 @@ +// run-pass +#![allow(unused_variables)] +#![allow(stable_features)] + +use std::cell::RefCell; +use std::rc::Rc; + +#[derive(PartialEq, Debug)] +struct Point { + x: isize, + y: isize +} + +pub fn main() { + let box_5: Box<_> = Box::new(5_usize); + let point = Rc::new(Point {x: 2, y: 4}); + assert_eq!(point.x, 2); + assert_eq!(point.y, 4); + + let i = Rc::new(RefCell::new(2)); + let i_value = *i.borrow(); + *i.borrow_mut() = 5; + assert_eq!((i_value, *i.borrow()), (2, 5)); + + let s = Rc::new("foo".to_string()); + assert_eq!(&**s, "foo"); + + let mut_s = Rc::new(RefCell::new(String::from("foo"))); + mut_s.borrow_mut().push_str("bar"); + // HACK assert_eq! would panic here because it stores the LHS and RHS in two locals. + assert_eq!(&**mut_s.borrow(), "foobar"); + assert_eq!(&**mut_s.borrow_mut(), "foobar"); + + let p = Rc::new(RefCell::new(Point {x: 1, y: 2})); + p.borrow_mut().x = 3; + p.borrow_mut().y += 3; + assert_eq!(*p.borrow(), Point {x: 3, y: 5}); + + let v = Rc::new(RefCell::new([1, 2, 3])); + v.borrow_mut()[0] = 3; + v.borrow_mut()[1] += 3; + assert_eq!((v.borrow()[0], v.borrow()[1], v.borrow()[2]), (3, 5, 3)); +} diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.rs b/tests/ui/overloaded/overloaded-calls-nontuple.rs new file mode 100644 index 000000000..32a3b93e0 --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-nontuple.rs @@ -0,0 +1,30 @@ +#![feature(fn_traits, unboxed_closures)] + +use std::ops::FnMut; + +struct S { + x: isize, + y: isize, +} + +impl FnMut for S { + //~^ ERROR type parameter to bare `FnMut` trait must be a tuple + extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + self.x + self.y + z + } +} + +impl FnOnce for S { + //~^ ERROR type parameter to bare `FnOnce` trait must be a tuple + type Output = isize; + extern "rust-call" fn call_once(mut self, z: isize) -> isize { + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + self.call_mut(z) + } +} + +fn main() { + let mut s = S { x: 1, y: 2 }; + drop(s(3)) +} diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr new file mode 100644 index 000000000..2e1600782 --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr @@ -0,0 +1,34 @@ +error[E0059]: type parameter to bare `FnMut` trait must be a tuple + --> $DIR/overloaded-calls-nontuple.rs:10:6 + | +LL | impl FnMut for S { + | ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | +note: required by a bound in `FnMut` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + +error[E0059]: type parameter to bare `FnOnce` trait must be a tuple + --> $DIR/overloaded-calls-nontuple.rs:18:6 + | +LL | impl FnOnce for S { + | ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | +note: required by a bound in `FnOnce` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/overloaded-calls-nontuple.rs:12:5 + | +LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + +error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/overloaded-calls-nontuple.rs:21:5 + | +LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0059, E0277. +For more information about an error, try `rustc --explain E0059`. diff --git a/tests/ui/overloaded/overloaded-calls-object-one-arg.rs b/tests/ui/overloaded/overloaded-calls-object-one-arg.rs new file mode 100644 index 000000000..1afab9a1f --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-object-one-arg.rs @@ -0,0 +1,13 @@ +// run-pass +// Tests calls to closure arguments where the closure takes 1 argument. +// This is a bit tricky due to rust-call ABI. + + +fn foo(f: &mut dyn FnMut(isize) -> isize) -> isize { + f(22) +} + +fn main() { + let z = foo(&mut |x| x *100); + assert_eq!(z, 2200); +} diff --git a/tests/ui/overloaded/overloaded-calls-object-two-args.rs b/tests/ui/overloaded/overloaded-calls-object-two-args.rs new file mode 100644 index 000000000..38087bc87 --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-object-two-args.rs @@ -0,0 +1,13 @@ +// run-pass +// Tests calls to closure arguments where the closure takes 2 arguments. +// This is a bit tricky due to rust-call ABI. + + +fn foo(f: &mut dyn FnMut(isize, isize) -> isize) -> isize { + f(1, 2) +} + +fn main() { + let z = foo(&mut |x, y| x * 10 + y); + assert_eq!(z, 12); +} diff --git a/tests/ui/overloaded/overloaded-calls-object-zero-args.rs b/tests/ui/overloaded/overloaded-calls-object-zero-args.rs new file mode 100644 index 000000000..9a7bfaa9b --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-object-zero-args.rs @@ -0,0 +1,13 @@ +// run-pass +// Tests calls to closure arguments where the closure takes 0 arguments. +// This is a bit tricky due to rust-call ABI. + + +fn foo(f: &mut dyn FnMut() -> isize) -> isize { + f() +} + +fn main() { + let z = foo(&mut || 22); + assert_eq!(z, 22); +} diff --git a/tests/ui/overloaded/overloaded-calls-param-vtables.rs b/tests/ui/overloaded/overloaded-calls-param-vtables.rs new file mode 100644 index 000000000..fde1ad20f --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-param-vtables.rs @@ -0,0 +1,32 @@ +// run-pass +// Tests that nested vtables work with overloaded calls. + +// pretty-expanded FIXME #23616 + +#![feature(unboxed_closures, fn_traits)] + +use std::marker::PhantomData; +use std::ops::Fn; +use std::ops::Add; + +struct G(PhantomData); + +impl<'a, A: Add> Fn<(A,)> for G { + extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 { + arg.add(1) + } +} + +impl<'a, A: Add> FnMut<(A,)> for G { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { self.call(args) } +} + +impl<'a, A: Add> FnOnce<(A,)> for G { + type Output = i32; + extern "rust-call" fn call_once(self, args: (A,)) -> i32 { self.call(args) } +} + +fn main() { + // ICE trigger + (G(PhantomData))(1); +} diff --git a/tests/ui/overloaded/overloaded-calls-simple.rs b/tests/ui/overloaded/overloaded-calls-simple.rs new file mode 100644 index 000000000..413183607 --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-simple.rs @@ -0,0 +1,78 @@ +// run-pass + +#![feature(lang_items, unboxed_closures, fn_traits)] + +use std::ops::{Fn, FnMut, FnOnce}; + +struct S1 { + x: i32, + y: i32, +} + +impl FnMut<(i32,)> for S1 { + extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 { + self.x * self.y * z + } +} + +impl FnOnce<(i32,)> for S1 { + type Output = i32; + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { + self.call_mut(args) + } +} + +struct S2 { + x: i32, + y: i32, +} + +impl Fn<(i32,)> for S2 { + extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 { + self.x * self.y * z + } +} + +impl FnMut<(i32,)> for S2 { + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } +} + +impl FnOnce<(i32,)> for S2 { + type Output = i32; + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } +} + +struct S3 { + x: i32, + y: i32, +} + +impl FnOnce<(i32,i32)> for S3 { + type Output = i32; + extern "rust-call" fn call_once(self, (z,zz): (i32,i32)) -> i32 { + self.x * self.y * z * zz + } +} + +fn main() { + let mut s = S1 { + x: 3, + y: 3, + }; + let ans = s(3); + + assert_eq!(ans, 27); + let s = S2 { + x: 3, + y: 3, + }; + let ans = s.call((3,)); + assert_eq!(ans, 27); + + let s = S3 { + x: 3, + y: 3, + }; + let ans = s(3, 1); + assert_eq!(ans, 27); +} diff --git a/tests/ui/overloaded/overloaded-calls-zero-args.rs b/tests/ui/overloaded/overloaded-calls-zero-args.rs new file mode 100644 index 000000000..69ca88619 --- /dev/null +++ b/tests/ui/overloaded/overloaded-calls-zero-args.rs @@ -0,0 +1,30 @@ +// run-pass + +#![feature(unboxed_closures, fn_traits)] + +use std::ops::FnMut; + +struct S { + x: i32, + y: i32, +} + +impl FnMut<()> for S { + extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 { + self.x * self.y + } +} + +impl FnOnce<()> for S { + type Output = i32; + extern "rust-call" fn call_once(mut self, args: ()) -> i32 { self.call_mut(args) } +} + +fn main() { + let mut s = S { + x: 3, + y: 3, + }; + let ans = s(); + assert_eq!(ans, 9); +} diff --git a/tests/ui/overloaded/overloaded-deref-count.rs b/tests/ui/overloaded/overloaded-deref-count.rs new file mode 100644 index 000000000..e2f1e10b5 --- /dev/null +++ b/tests/ui/overloaded/overloaded-deref-count.rs @@ -0,0 +1,78 @@ +// run-pass + +use std::cell::Cell; +use std::ops::{Deref, DerefMut}; +use std::vec::Vec; + +struct DerefCounter { + count_imm: Cell, + count_mut: usize, + value: T +} + +impl DerefCounter { + fn new(value: T) -> DerefCounter { + DerefCounter { + count_imm: Cell::new(0), + count_mut: 0, + value: value + } + } + + fn counts(&self) -> (usize, usize) { + (self.count_imm.get(), self.count_mut) + } +} + +impl Deref for DerefCounter { + type Target = T; + + fn deref(&self) -> &T { + self.count_imm.set(self.count_imm.get() + 1); + &self.value + } +} + +impl DerefMut for DerefCounter { + fn deref_mut(&mut self) -> &mut T { + self.count_mut += 1; + &mut self.value + } +} + +pub fn main() { + let mut n = DerefCounter::new(0); + let mut v = DerefCounter::new(Vec::new()); + + let _ = *n; // Immutable deref + copy a POD. + assert_eq!(n.counts(), (1, 0)); + + let _ = (&*n, &*v); // Immutable deref + borrow. + assert_eq!(n.counts(), (2, 0)); assert_eq!(v.counts(), (1, 0)); + + let _ = (&mut *n, &mut *v); // Mutable deref + mutable borrow. + assert_eq!(n.counts(), (2, 1)); assert_eq!(v.counts(), (1, 1)); + + let mut v2 = Vec::new(); + v2.push(1); + + *n = 5; *v = v2; // Mutable deref + assignment. + assert_eq!(n.counts(), (2, 2)); assert_eq!(v.counts(), (1, 2)); + + *n -= 3; // Mutable deref + assignment with binary operation. + assert_eq!(n.counts(), (2, 3)); + + // Immutable deref used for calling a method taking &self. (The + // typechecker is smarter now about doing this.) + (*n).to_string(); + assert_eq!(n.counts(), (3, 3)); + + // Mutable deref used for calling a method taking &mut self. + (*v).push(2); + assert_eq!(v.counts(), (1, 3)); + + // Check the final states. + assert_eq!(*n, 2); + let expected: &[_] = &[1, 2]; + assert_eq!((*v), expected); +} diff --git a/tests/ui/overloaded/overloaded-deref.rs b/tests/ui/overloaded/overloaded-deref.rs new file mode 100644 index 000000000..73d8232a3 --- /dev/null +++ b/tests/ui/overloaded/overloaded-deref.rs @@ -0,0 +1,43 @@ +// run-pass +use std::cell::RefCell; +use std::rc::Rc; +use std::string::String; + +#[derive(PartialEq, Debug)] +struct Point { + x: isize, + y: isize +} + +pub fn main() { + assert_eq!(*Rc::new(5), 5); + assert_eq!(***Rc::new(Box::new(Box::new(5))), 5); + assert_eq!(*Rc::new(Point {x: 2, y: 4}), Point {x: 2, y: 4}); + + let i = Rc::new(RefCell::new(2)); + let i_value = *(*i).borrow(); + *(*i).borrow_mut() = 5; + assert_eq!((i_value, *(*i).borrow()), (2, 5)); + + let s = Rc::new("foo".to_string()); + assert_eq!(*s, "foo".to_string()); + assert_eq!((*s), "foo"); + + let mut_s = Rc::new(RefCell::new(String::from("foo"))); + (*(*mut_s).borrow_mut()).push_str("bar"); + // assert_eq! would panic here because it stores the LHS and RHS in two locals. + assert_eq!((*(*mut_s).borrow()), "foobar"); + assert_eq!((*(*mut_s).borrow_mut()), "foobar"); + + let p = Rc::new(RefCell::new(Point {x: 1, y: 2})); + (*(*p).borrow_mut()).x = 3; + (*(*p).borrow_mut()).y += 3; + assert_eq!(*(*p).borrow(), Point {x: 3, y: 5}); + + let v = Rc::new(RefCell::new(vec![1, 2, 3])); + (*(*v).borrow_mut())[0] = 3; + (*(*v).borrow_mut())[1] += 3; + assert_eq!(((*(*v).borrow())[0], + (*(*v).borrow())[1], + (*(*v).borrow())[2]), (3, 5, 3)); +} diff --git a/tests/ui/overloaded/overloaded-index-assoc-list.rs b/tests/ui/overloaded/overloaded-index-assoc-list.rs new file mode 100644 index 000000000..eb027afea --- /dev/null +++ b/tests/ui/overloaded/overloaded-index-assoc-list.rs @@ -0,0 +1,48 @@ +// run-pass +// Test overloading of the `[]` operator. In particular test that it +// takes its argument *by reference*. + +use std::ops::Index; + +struct AssociationList { + pairs: Vec> } + +#[derive(Clone)] +struct AssociationPair { + key: K, + value: V +} + +impl AssociationList { + fn push(&mut self, key: K, value: V) { + self.pairs.push(AssociationPair {key: key, value: value}); + } +} + +impl<'a, K: PartialEq + std::fmt::Debug, V:Clone> Index<&'a K> for AssociationList { + type Output = V; + + fn index(&self, index: &K) -> &V { + for pair in &self.pairs { + if pair.key == *index { + return &pair.value + } + } + panic!("No value found for key: {:?}", index); + } +} + +pub fn main() { + let foo = "foo".to_string(); + let bar = "bar".to_string(); + + let mut list = AssociationList {pairs: Vec::new()}; + list.push(foo.clone(), 22); + list.push(bar.clone(), 44); + + assert_eq!(list[&foo], 22); + assert_eq!(list[&bar], 44); + + assert_eq!(list[&foo], 22); + assert_eq!(list[&bar], 44); +} diff --git a/tests/ui/overloaded/overloaded-index-autoderef.rs b/tests/ui/overloaded/overloaded-index-autoderef.rs new file mode 100644 index 000000000..41f9efa8c --- /dev/null +++ b/tests/ui/overloaded/overloaded-index-autoderef.rs @@ -0,0 +1,75 @@ +// run-pass +#![allow(stable_features)] + +// Test overloaded indexing combined with autoderef. + +use std::ops::{Index, IndexMut}; + +struct Foo { + x: isize, + y: isize, +} + +impl Index for Foo { + type Output = isize; + + fn index(&self, z: isize) -> &isize { + if z == 0 { + &self.x + } else { + &self.y + } + } +} + +impl IndexMut for Foo { + fn index_mut(&mut self, z: isize) -> &mut isize { + if z == 0 { + &mut self.x + } else { + &mut self.y + } + } +} + +trait Int { + fn get(self) -> isize; + fn get_from_ref(&self) -> isize; + fn inc(&mut self); +} + +impl Int for isize { + fn get(self) -> isize { self } + fn get_from_ref(&self) -> isize { *self } + fn inc(&mut self) { *self += 1; } +} + +fn main() { + let mut f: Box<_> = Box::new(Foo { + x: 1, + y: 2, + }); + + assert_eq!(f[1], 2); + + f[0] = 3; + + assert_eq!(f[0], 3); + + // Test explicit IndexMut where `f` must be autoderef: + { + let p = &mut f[1]; + *p = 4; + } + + // Test explicit Index where `f` must be autoderef: + { + let p = &f[1]; + assert_eq!(*p, 4); + } + + // Test calling methods with `&mut self`, `self, and `&self` receivers: + f[1].inc(); + assert_eq!(f[1].get(), 5); + assert_eq!(f[1].get_from_ref(), 5); +} diff --git a/tests/ui/overloaded/overloaded-index-in-field.rs b/tests/ui/overloaded/overloaded-index-in-field.rs new file mode 100644 index 000000000..8a1fa7deb --- /dev/null +++ b/tests/ui/overloaded/overloaded-index-in-field.rs @@ -0,0 +1,46 @@ +// run-pass +// Test using overloaded indexing when the "map" is stored in a +// field. This caused problems at some point. + +use std::ops::Index; + +struct Foo { + x: isize, + y: isize, +} + +struct Bar { + foo: Foo +} + +impl Index for Foo { + type Output = isize; + + fn index(&self, z: isize) -> &isize { + if z == 0 { + &self.x + } else { + &self.y + } + } +} + +trait Int { + fn get(self) -> isize; + fn get_from_ref(&self) -> isize; + fn inc(&mut self); +} + +impl Int for isize { + fn get(self) -> isize { self } + fn get_from_ref(&self) -> isize { *self } + fn inc(&mut self) { *self += 1; } +} + +fn main() { + let f = Bar { foo: Foo { + x: 1, + y: 2, + } }; + assert_eq!(f.foo[1].get(), 2); +} diff --git a/tests/ui/overloaded/overloaded-index.rs b/tests/ui/overloaded/overloaded-index.rs new file mode 100644 index 000000000..5ad6d2e70 --- /dev/null +++ b/tests/ui/overloaded/overloaded-index.rs @@ -0,0 +1,64 @@ +// run-pass +use std::ops::{Index, IndexMut}; + +struct Foo { + x: isize, + y: isize, +} + +impl Index for Foo { + type Output = isize; + + fn index(&self, z: isize) -> &isize { + if z == 0 { + &self.x + } else { + &self.y + } + } +} + +impl IndexMut for Foo { + fn index_mut(&mut self, z: isize) -> &mut isize { + if z == 0 { + &mut self.x + } else { + &mut self.y + } + } +} + +trait Int { + fn get(self) -> isize; + fn get_from_ref(&self) -> isize; + fn inc(&mut self); +} + +impl Int for isize { + fn get(self) -> isize { self } + fn get_from_ref(&self) -> isize { *self } + fn inc(&mut self) { *self += 1; } +} + +fn main() { + let mut f = Foo { + x: 1, + y: 2, + }; + assert_eq!(f[1], 2); + f[0] = 3; + assert_eq!(f[0], 3); + { + let p = &mut f[1]; + *p = 4; + } + { + let p = &f[1]; + assert_eq!(*p, 4); + } + + // Test calling methods with `&mut self`, `self, and `&self` receivers: + f[1].inc(); + assert_eq!(f[1].get(), 5); + assert_eq!(f[1].get_from_ref(), 5); +} diff --git a/tests/ui/overloaded/overloaded_deref_with_ref_pattern.rs b/tests/ui/overloaded/overloaded_deref_with_ref_pattern.rs new file mode 100644 index 000000000..c87ba6a02 --- /dev/null +++ b/tests/ui/overloaded/overloaded_deref_with_ref_pattern.rs @@ -0,0 +1,95 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// Test that we choose Deref or DerefMut appropriately based on mutability of ref bindings (#15609). + +use std::ops::{Deref, DerefMut}; + +struct DerefOk(T); +struct DerefMutOk(T); + +impl Deref for DerefOk { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for DerefOk { + fn deref_mut(&mut self) -> &mut Self::Target { + panic!() + } +} + +impl Deref for DerefMutOk { + type Target = T; + fn deref(&self) -> &Self::Target { + panic!() + } +} + +impl DerefMut for DerefMutOk { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + // Check that mutable ref binding in match picks DerefMut + let mut b = DerefMutOk(0); + match *b { + ref mut n => n, + }; + + // Check that mutable ref binding in let picks DerefMut + let mut y = DerefMutOk(1); + let ref mut z = *y; + + // Check that immutable ref binding in match picks Deref + let mut b = DerefOk(2); + match *b { + ref n => n, + }; + + // Check that immutable ref binding in let picks Deref + let mut y = DerefOk(3); + let ref z = *y; + + // Check that mixed mutable/immutable ref binding in match picks DerefMut + let mut b = DerefMutOk((0, 9)); + match *b { + (ref mut n, ref m) => (n, m), + }; + + let mut b = DerefMutOk((0, 9)); + match *b { + (ref n, ref mut m) => (n, m), + }; + + // Check that mixed mutable/immutable ref binding in let picks DerefMut + let mut y = DerefMutOk((1, 8)); + let (ref mut z, ref a) = *y; + + let mut y = DerefMutOk((1, 8)); + let (ref z, ref mut a) = *y; + + // Check that multiple immutable ref bindings in match picks Deref + let mut b = DerefOk((2, 7)); + match *b { + (ref n, ref m) => (n, m), + }; + + // Check that multiple immutable ref bindings in let picks Deref + let mut y = DerefOk((3, 6)); + let (ref z, ref a) = *y; + + // Check that multiple mutable ref bindings in match picks DerefMut + let mut b = DerefMutOk((4, 5)); + match *b { + (ref mut n, ref mut m) => (n, m), + }; + + // Check that multiple mutable ref bindings in let picks DerefMut + let mut y = DerefMutOk((5, 4)); + let (ref mut z, ref mut a) = *y; +} diff --git a/tests/ui/overloaded/overloaded_deref_with_ref_pattern_issue15609.rs b/tests/ui/overloaded/overloaded_deref_with_ref_pattern_issue15609.rs new file mode 100644 index 000000000..61edd2ace --- /dev/null +++ b/tests/ui/overloaded/overloaded_deref_with_ref_pattern_issue15609.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that we choose Deref or DerefMut appropriately based on mutability of ref bindings (#15609). + +fn main() { + use std::cell::RefCell; + + struct S { + node: E, + } + + enum E { + Foo(u32), + Bar, + } + + // Check match + let x = RefCell::new(S { node: E::Foo(0) }); + + let mut b = x.borrow_mut(); + match b.node { + E::Foo(ref mut n) => *n += 1, + _ => (), + } + + // Check let + let x = RefCell::new(0); + let mut y = x.borrow_mut(); + let ref mut z = *y; + + fn foo(a: &mut RefCell>) { + if let Some(ref mut s) = *a.borrow_mut() { + s.push('a') + } + } +} diff --git a/tests/ui/packed-struct/packed-struct-generic-transmute.rs b/tests/ui/packed-struct/packed-struct-generic-transmute.rs new file mode 100644 index 000000000..c6264b6d2 --- /dev/null +++ b/tests/ui/packed-struct/packed-struct-generic-transmute.rs @@ -0,0 +1,27 @@ +// This assumes the packed and non-packed structs are different sizes. + +// the error points to the start of the file, not the line with the +// transmute + +// error-pattern: cannot transmute between types of different sizes, or dependently-sized types + +use std::mem; + +#[repr(packed)] +struct Foo { + bar: T, + baz: S +} + +struct Oof { + rab: T, + zab: S +} + +fn main() { + let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 }; + unsafe { + let oof: Oof<[u8; 5], i32> = mem::transmute(foo); + println!("{:?} {:?}", &oof.rab[..], oof.zab); + } +} diff --git a/tests/ui/packed-struct/packed-struct-generic-transmute.stderr b/tests/ui/packed-struct/packed-struct-generic-transmute.stderr new file mode 100644 index 000000000..744c832db --- /dev/null +++ b/tests/ui/packed-struct/packed-struct-generic-transmute.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/packed-struct-generic-transmute.rs:24:38 + | +LL | let oof: Oof<[u8; 5], i32> = mem::transmute(foo); + | ^^^^^^^^^^^^^^ + | + = note: source type: `Foo<[u8; 5], i32>` (72 bits) + = note: target type: `Oof<[u8; 5], i32>` (96 bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/packed-struct/packed-struct-transmute.rs b/tests/ui/packed-struct/packed-struct-transmute.rs new file mode 100644 index 000000000..a7d284025 --- /dev/null +++ b/tests/ui/packed-struct/packed-struct-transmute.rs @@ -0,0 +1,29 @@ +// This assumes the packed and non-packed structs are different sizes. + +// the error points to the start of the file, not the line with the +// transmute + +// normalize-stderr-test "\d+ bits" -> "N bits" +// error-pattern: cannot transmute between types of different sizes, or dependently-sized types + +use std::mem; + +#[repr(packed)] +struct Foo { + bar: u8, + baz: usize +} + +#[derive(Debug)] +struct Oof { + rab: u8, + zab: usize +} + +fn main() { + let foo = Foo { bar: 1, baz: 10 }; + unsafe { + let oof: Oof = mem::transmute(foo); + println!("{:?}", oof); + } +} diff --git a/tests/ui/packed-struct/packed-struct-transmute.stderr b/tests/ui/packed-struct/packed-struct-transmute.stderr new file mode 100644 index 000000000..80a8919f7 --- /dev/null +++ b/tests/ui/packed-struct/packed-struct-transmute.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/packed-struct-transmute.rs:26:24 + | +LL | let oof: Oof = mem::transmute(foo); + | ^^^^^^^^^^^^^^ + | + = note: source type: `Foo` (N bits) + = note: target type: `Oof` (N bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/packed/auxiliary/packed.rs b/tests/ui/packed/auxiliary/packed.rs new file mode 100644 index 000000000..cba166fac --- /dev/null +++ b/tests/ui/packed/auxiliary/packed.rs @@ -0,0 +1,19 @@ +#[repr(packed)] +pub struct P1S5 { + a: u8, + b: u32 +} + +#[repr(packed(2))] +pub struct P2S6 { + a: u8, + b: u32, + c: u8 +} + +#[repr(C, packed(2))] +pub struct P2CS8 { + a: u8, + b: u32, + c: u8 +} diff --git a/tests/ui/packed/issue-27060-2.rs b/tests/ui/packed/issue-27060-2.rs new file mode 100644 index 000000000..a001ce1e0 --- /dev/null +++ b/tests/ui/packed/issue-27060-2.rs @@ -0,0 +1,6 @@ +#[repr(packed)] +pub struct Bad { + data: T, //~ ERROR the size for values of type +} + +fn main() {} diff --git a/tests/ui/packed/issue-27060-2.stderr b/tests/ui/packed/issue-27060-2.stderr new file mode 100644 index 000000000..0836ceaec --- /dev/null +++ b/tests/ui/packed/issue-27060-2.stderr @@ -0,0 +1,27 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/issue-27060-2.rs:3:11 + | +LL | pub struct Bad { + | - this type parameter needs to be `std::marker::Sized` +LL | data: T, + | ^ doesn't have a size known at compile-time + | + = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - pub struct Bad { +LL + pub struct Bad { + | +help: borrowed types always have a statically known size + | +LL | data: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | data: Box, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/packed/issue-27060-rpass.rs b/tests/ui/packed/issue-27060-rpass.rs new file mode 100644 index 000000000..d9159f666 --- /dev/null +++ b/tests/ui/packed/issue-27060-rpass.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +#[repr(packed)] +pub struct Good { + data: &'static u32, + data2: [&'static u32; 2], + aligned: [u8; 32], +} + +// kill this test when that turns to a hard error +#[allow(unaligned_references)] +fn main() { + let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] }; + + let _ = &good.data; // ok + let _ = &good.data2[0]; // ok + + let _ = &good.data; + let _ = &good.data2[0]; + let _ = &*good.data; // ok, behind a pointer + let _ = &good.aligned; // ok, has align 1 + let _ = &good.aligned[2]; // ok, has align 1 +} diff --git a/tests/ui/packed/issue-27060-rpass.stderr b/tests/ui/packed/issue-27060-rpass.stderr new file mode 100644 index 000000000..adf9ae9f5 --- /dev/null +++ b/tests/ui/packed/issue-27060-rpass.stderr @@ -0,0 +1,68 @@ +Future incompatibility report: Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/issue-27060-rpass.rs:15:13 + | +LL | let _ = &good.data; // ok + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/issue-27060-rpass.rs:11:9 + | +LL | #[allow(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/issue-27060-rpass.rs:16:13 + | +LL | let _ = &good.data2[0]; // ok + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/issue-27060-rpass.rs:11:9 + | +LL | #[allow(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/issue-27060-rpass.rs:18:13 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/issue-27060-rpass.rs:11:9 + | +LL | #[allow(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/issue-27060-rpass.rs:19:13 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/issue-27060-rpass.rs:11:9 + | +LL | #[allow(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/packed/issue-27060.rs b/tests/ui/packed/issue-27060.rs new file mode 100644 index 000000000..886a00239 --- /dev/null +++ b/tests/ui/packed/issue-27060.rs @@ -0,0 +1,27 @@ +#[repr(packed)] +pub struct Good { + data: &'static u32, + data2: [&'static u32; 2], + aligned: [u8; 32], +} + +fn main() { + let good = Good { + data: &0, + data2: [&0, &0], + aligned: [0; 32] + }; + + let _ = &good.data; //~ ERROR reference to packed field + //~| hard error + let _ = &good.data2[0]; //~ ERROR reference to packed field + //~| hard error + + let _ = &good.data; //~ ERROR reference to packed field + //~| hard error + let _ = &good.data2[0]; //~ ERROR reference to packed field + //~| hard error + let _ = &*good.data; // ok, behind a pointer + let _ = &good.aligned; // ok, has align 1 + let _ = &good.aligned[2]; // ok, has align 1 +} diff --git a/tests/ui/packed/issue-27060.stderr b/tests/ui/packed/issue-27060.stderr new file mode 100644 index 000000000..85e08fa02 --- /dev/null +++ b/tests/ui/packed/issue-27060.stderr @@ -0,0 +1,99 @@ +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:15:13 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:17:13 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:20:13 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:22:13 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: aborting due to 4 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:15:13 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:17:13 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:20:13 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-27060.rs:22:13 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + diff --git a/tests/ui/packed/issue-46152.rs b/tests/ui/packed/issue-46152.rs new file mode 100644 index 000000000..fb1c9fb78 --- /dev/null +++ b/tests/ui/packed/issue-46152.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![feature(unsize, coerce_unsized)] + +#[repr(packed)] +struct UnalignedPtr<'a, T: ?Sized> + where T: 'a, +{ + data: &'a T, +} + +fn main() { + + impl<'a, T, U> std::ops::CoerceUnsized> for UnalignedPtr<'a, T> + where + T: std::marker::Unsize + ?Sized, + U: ?Sized, + { } + + let arr = [1, 2, 3]; + let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr }; + let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned; +} diff --git a/tests/ui/packed/packed-struct-address-of-element.rs b/tests/ui/packed/packed-struct-address-of-element.rs new file mode 100644 index 000000000..d86698cbf --- /dev/null +++ b/tests/ui/packed/packed-struct-address-of-element.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(dead_code)] +#![feature(raw_ref_op)] +// ignore-emscripten weird assertion? + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo = Foo1 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let foo = Foo2 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let mut foo = Foo4C { bar: 1, baz: 2 }; + let brw = &raw mut foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } +} diff --git a/tests/ui/packed/packed-struct-borrow-element-64bit.rs b/tests/ui/packed/packed-struct-borrow-element-64bit.rs new file mode 100644 index 000000000..00bddfe40 --- /dev/null +++ b/tests/ui/packed/packed-struct-borrow-element-64bit.rs @@ -0,0 +1,18 @@ +// run-pass (note: this is spec-UB, but it works for now) +// ignore-32bit (needs `usize` to be 8-aligned to reproduce all the errors below) +#![allow(dead_code)] +// ignore-emscripten weird assertion? + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +#[warn(unaligned_references)] +pub fn main() { + let foo = Foo4C { bar: 1, baz: 2 }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted + assert_eq!(*brw, 2); +} diff --git a/tests/ui/packed/packed-struct-borrow-element-64bit.stderr b/tests/ui/packed/packed-struct-borrow-element-64bit.stderr new file mode 100644 index 000000000..fb2f5615c --- /dev/null +++ b/tests/ui/packed/packed-struct-borrow-element-64bit.stderr @@ -0,0 +1,35 @@ +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element-64bit.rs:15:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/packed-struct-borrow-element-64bit.rs:12:8 + | +LL | #[warn(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element-64bit.rs:15:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/packed-struct-borrow-element-64bit.rs:12:8 + | +LL | #[warn(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/packed/packed-struct-borrow-element.rs b/tests/ui/packed/packed-struct-borrow-element.rs new file mode 100644 index 000000000..a6ee90cef --- /dev/null +++ b/tests/ui/packed/packed-struct-borrow-element.rs @@ -0,0 +1,34 @@ +// run-pass (note: this is spec-UB, but it works for now) +#![allow(dead_code)] +// ignore-emscripten weird assertion? + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +#[warn(unaligned_references)] +pub fn main() { + let foo = Foo1 { bar: 1, baz: 2 }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted + assert_eq!(*brw, 2); + + let foo = Foo2 { bar: 1, baz: 2 }; + let brw = &foo.baz; //~WARN reference to packed field is unaligned + //~^ previously accepted + assert_eq!(*brw, 2); +} diff --git a/tests/ui/packed/packed-struct-borrow-element.stderr b/tests/ui/packed/packed-struct-borrow-element.stderr new file mode 100644 index 000000000..75d55c4f6 --- /dev/null +++ b/tests/ui/packed/packed-struct-borrow-element.stderr @@ -0,0 +1,63 @@ +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:26:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/packed-struct-borrow-element.rs:23:8 + | +LL | #[warn(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:31:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +warning: 2 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:26:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/packed-struct-borrow-element.rs:23:8 + | +LL | #[warn(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: reference to packed field is unaligned + --> $DIR/packed-struct-borrow-element.rs:31:15 + | +LL | let brw = &foo.baz; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) +note: the lint level is defined here + --> $DIR/packed-struct-borrow-element.rs:23:8 + | +LL | #[warn(unaligned_references)] + | ^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs new file mode 100644 index 000000000..9f9f41e25 --- /dev/null +++ b/tests/ui/packed/packed-struct-drop-aligned.rs @@ -0,0 +1,57 @@ +// run-pass +#![feature(generators)] +#![feature(generator_trait)] +use std::cell::Cell; +use std::mem; +use std::ops::Generator; +use std::pin::Pin; + +struct Aligned<'a> { + drop_count: &'a Cell +} + +#[inline(never)] +fn check_align(ptr: *const Aligned) { + assert_eq!(ptr as usize % mem::align_of::(), + 0); +} + +impl<'a> Drop for Aligned<'a> { + fn drop(&mut self) { + check_align(self); + self.drop_count.set(self.drop_count.get() + 1); + } +} + +#[repr(transparent)] +struct NotCopy(#[allow(unused_tuple_struct_fields)] u8); + +#[repr(packed)] +struct Packed<'a>(NotCopy, Aligned<'a>); + +fn main() { + let drop_count = &Cell::new(0); + { + let mut p = Packed(NotCopy(0), Aligned { drop_count }); + p.1 = Aligned { drop_count }; + assert_eq!(drop_count.get(), 1); + } + assert_eq!(drop_count.get(), 2); + + let drop_count = &Cell::new(0); + let mut g = || { + let mut p = Packed(NotCopy(0), Aligned { drop_count }); + let _ = &p; + p.1 = Aligned { drop_count }; + assert_eq!(drop_count.get(), 1); + // Test that a generator drop function moves a value from a packed + // struct to a separate local before dropping it. We move out the + // first field to generate and open drop for the second field. + drop(p.0); + yield; + }; + Pin::new(&mut g).resume(()); + assert_eq!(drop_count.get(), 1); + drop(g); + assert_eq!(drop_count.get(), 2); +} diff --git a/tests/ui/packed/packed-struct-generic-layout.rs b/tests/ui/packed/packed-struct-generic-layout.rs new file mode 100644 index 000000000..e064eede4 --- /dev/null +++ b/tests/ui/packed/packed-struct-generic-layout.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(dead_code)] +#![allow(overflowing_literals)] + + +use std::mem; + +#[repr(packed)] +struct S { + a: T, + b: u8, + c: S +} + +pub fn main() { + unsafe { + let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 }; + let transd : [u8; 9] = mem::transmute(s); + // Don't worry about endianness, the numbers are palindromic. + assert_eq!(transd, + [0xff, 0xff, 0xff, 0xff, + 1, + 0xaa, 0xaa, 0xaa, 0xaa]); + + + let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16}; + let transd : [u8; 4] = mem::transmute(s); + // Again, no endianness problems. + assert_eq!(transd, + [1, 2, 0b10000001, 0b10000001]); + } +} diff --git a/tests/ui/packed/packed-struct-generic-size.rs b/tests/ui/packed/packed-struct-generic-size.rs new file mode 100644 index 000000000..7c93e46c3 --- /dev/null +++ b/tests/ui/packed/packed-struct-generic-size.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_comparisons)] + +use std::mem; + +#[repr(packed)] +struct P1 { + a: T, + b: u8, + c: S +} + +#[repr(packed(2))] +struct P2 { + a: T, + b: u8, + c: S +} + +#[repr(C, packed(4))] +struct P4C { + a: T, + b: u8, + c: S +} + +macro_rules! check { + ($t:ty, $align:expr, $size:expr) => ({ + assert_eq!(mem::align_of::<$t>(), $align); + assert_eq!(mem::size_of::<$t>(), $size); + }); +} + +pub fn main() { + check!(P1, 1, 3); + check!(P1, 1, 11); + + check!(P2, 1, 3); + check!(P2, 2, 12); + + check!(P4C, 1, 3); + check!(P4C, 4, 12); +} diff --git a/tests/ui/packed/packed-struct-layout.rs b/tests/ui/packed/packed-struct-layout.rs new file mode 100644 index 000000000..d49c222e6 --- /dev/null +++ b/tests/ui/packed/packed-struct-layout.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +use std::mem; + +#[repr(packed)] +struct S4 { + a: u8, + b: [u8; 3], +} + +#[repr(packed)] +struct S5 { + a: u8, + b: u32 +} + +pub fn main() { + unsafe { + let s4 = S4 { a: 1, b: [2,3,4] }; + let transd : [u8; 4] = mem::transmute(s4); + assert_eq!(transd, [1, 2, 3, 4]); + + let s5 = S5 { a: 1, b: 0xff_00_00_ff }; + let transd : [u8; 5] = mem::transmute(s5); + // Don't worry about endianness, the u32 is palindromic. + assert_eq!(transd, [1, 0xff, 0, 0, 0xff]); + } +} diff --git a/tests/ui/packed/packed-struct-match.rs b/tests/ui/packed/packed-struct-match.rs new file mode 100644 index 000000000..9a572ced7 --- /dev/null +++ b/tests/ui/packed/packed-struct-match.rs @@ -0,0 +1,45 @@ +// run-pass + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo1 = Foo1 { bar: 1, baz: 2 }; + match foo1 { + Foo1 {bar, baz} => { + assert_eq!(bar, 1); + assert_eq!(baz, 2); + } + } + + let foo2 = Foo2 { bar: 1, baz: 2 }; + match foo2 { + Foo2 {bar, baz} => { + assert_eq!(bar, 1); + assert_eq!(baz, 2); + } + } + + let foo4 = Foo4C { bar: 1, baz: 2 }; + match foo4 { + Foo4C {bar, baz} => { + assert_eq!(bar, 1); + assert_eq!(baz, 2); + } + } +} diff --git a/tests/ui/packed/packed-struct-optimized-enum.rs b/tests/ui/packed/packed-struct-optimized-enum.rs new file mode 100644 index 000000000..5e1a1f518 --- /dev/null +++ b/tests/ui/packed/packed-struct-optimized-enum.rs @@ -0,0 +1,36 @@ +// run-pass +#[repr(packed)] +struct Packed(#[allow(unused_tuple_struct_fields)] T); + +impl Copy for Packed {} +impl Clone for Packed { + fn clone(&self) -> Self { *self } +} + +fn sanity_check_size(one: T) { + let two = [one, one]; + let stride = (&two[1] as *const _ as usize) - (&two[0] as *const _ as usize); + let (size, align) = (std::mem::size_of::(), std::mem::align_of::()); + assert_eq!(stride, size); + assert_eq!(size % align, 0); +} + +fn main() { + // This can fail if rustc and LLVM disagree on the size of a type. + // In this case, `Option>` was erroneously not + // marked as packed despite needing alignment `1` and containing + // its `&()` discriminant, which has alignment larger than `1`. + sanity_check_size((Some(Packed((&(), 0))), true)); + + // In #46769, `Option<(Packed<&()>, bool)>` was found to have + // pointer alignment, without actually being aligned in size. + // e.g., on 64-bit platforms, it had alignment `8` but size `9`. + type PackedRefAndBool<'a> = (Packed<&'a ()>, bool); + sanity_check_size::>(Some((Packed(&()), true))); + + // Make sure we don't pay for the enum optimization in size, + // e.g., we shouldn't need extra padding after the packed data. + assert_eq!(std::mem::align_of::>(), 1); + assert_eq!(std::mem::size_of::>(), + std::mem::size_of::()); +} diff --git a/tests/ui/packed/packed-struct-size-xc.rs b/tests/ui/packed/packed-struct-size-xc.rs new file mode 100644 index 000000000..46112d51d --- /dev/null +++ b/tests/ui/packed/packed-struct-size-xc.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:packed.rs + + +extern crate packed; + +use std::mem; + +macro_rules! check { + ($t:ty, $align:expr, $size:expr) => ({ + assert_eq!(mem::align_of::<$t>(), $align); + assert_eq!(mem::size_of::<$t>(), $size); + }); +} + +pub fn main() { + check!(packed::P1S5, 1, 5); + check!(packed::P2S6, 2, 6); + check!(packed::P2CS8, 2, 8); +} diff --git a/tests/ui/packed/packed-struct-size.rs b/tests/ui/packed/packed-struct-size.rs new file mode 100644 index 000000000..c832c7cfa --- /dev/null +++ b/tests/ui/packed/packed-struct-size.rs @@ -0,0 +1,157 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +use std::mem; + +#[repr(packed)] +struct P1S4 { + a: u8, + b: [u8; 3], +} + +#[repr(packed(2))] +struct P2S4 { + a: u8, + b: [u8; 3], +} + +#[repr(packed)] +struct P1S5 { + a: u8, + b: u32 +} + +#[repr(packed(2))] +struct P2S2 { + a: u8, + b: u8 +} + +#[repr(packed(2))] +struct P2S6 { + a: u8, + b: u32 +} + +#[repr(packed(2))] +struct P2S12 { + a: u32, + b: u64 +} + +#[repr(packed)] +struct P1S13 { + a: i64, + b: f32, + c: u8, +} + +#[repr(packed(2))] +struct P2S14 { + a: i64, + b: f32, + c: u8, +} + +#[repr(packed(4))] +struct P4S16 { + a: u8, + b: f32, + c: i64, + d: u16, +} + +#[repr(C, packed(4))] +struct P4CS20 { + a: u8, + b: f32, + c: i64, + d: u16, +} + +enum Foo { + Bar = 1, + Baz = 2 +} + +#[repr(packed)] +struct P1S3_Foo { + a: u8, + b: u16, + c: Foo +} + +#[repr(packed(2))] +struct P2_Foo { + a: Foo, +} + +#[repr(packed(2))] +struct P2S3_Foo { + a: u8, + b: u16, + c: Foo +} + +#[repr(packed)] +struct P1S7_Option { + a: f32, + b: u8, + c: u16, + d: Option> +} + +#[repr(packed(2))] +struct P2_Option { + a: Option> +} + +#[repr(packed(2))] +struct P2S7_Option { + a: f32, + b: u8, + c: u16, + d: Option> +} + +// Placing packed structs in statics should work +static TEST_P1S4: P1S4 = P1S4 { a: 1, b: [2, 3, 4] }; +static TEST_P1S5: P1S5 = P1S5 { a: 3, b: 67 }; +static TEST_P1S3_Foo: P1S3_Foo = P1S3_Foo { a: 1, b: 2, c: Foo::Baz }; +static TEST_P2S2: P2S2 = P2S2 { a: 1, b: 2 }; +static TEST_P2S4: P2S4 = P2S4 { a: 1, b: [2, 3, 4] }; +static TEST_P2S6: P2S6 = P2S6 { a: 1, b: 2 }; +static TEST_P2S12: P2S12 = P2S12 { a: 1, b: 2 }; +static TEST_P4S16: P4S16 = P4S16 { a: 1, b: 2.0, c: 3, d: 4 }; +static TEST_P4CS20: P4CS20 = P4CS20 { a: 1, b: 2.0, c: 3, d: 4 }; + +fn align_to(value: usize, align: usize) -> usize { + (value + (align - 1)) & !(align - 1) +} + +macro_rules! check { + ($t:ty, $align:expr, $size:expr) => ({ + assert_eq!(mem::align_of::<$t>(), $align); + assert_eq!(mem::size_of::<$t>(), $size); + }); +} + +pub fn main() { + check!(P1S4, 1, 4); + check!(P1S5, 1, 5); + check!(P1S13, 1, 13); + check!(P1S3_Foo, 1, 3 + mem::size_of::()); + check!(P1S7_Option, 1, 7 + mem::size_of::>>()); + + check!(P2S2, 1, 2); + check!(P2S4, 1, 4); + check!(P2S6, 2, 6); + check!(P2S12, 2, 12); + check!(P2S14, 2, 14); + check!(P4S16, 4, 16); + check!(P4CS20, 4, 20); + check!(P2S3_Foo, 2, align_to(3 + mem::size_of::(), 2)); + check!(P2S7_Option, 2, align_to(7 + mem::size_of::(), 2)); +} diff --git a/tests/ui/packed/packed-struct-vec.rs b/tests/ui/packed/packed-struct-vec.rs new file mode 100644 index 000000000..18676cfc2 --- /dev/null +++ b/tests/ui/packed/packed-struct-vec.rs @@ -0,0 +1,120 @@ +// run-pass + +use std::fmt; +use std::mem; + +#[repr(packed)] +#[derive(Copy, Clone)] +struct Foo1 { + bar: u8, + baz: u64 +} + +impl PartialEq for Foo1 { + fn eq(&self, other: &Foo1) -> bool { + self.bar == other.bar && self.baz == other.baz + } +} + +impl fmt::Debug for Foo1 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let bar = self.bar; + let baz = self.baz; + + f.debug_struct("Foo1") + .field("bar", &bar) + .field("baz", &baz) + .finish() + } +} + +#[repr(packed(2))] +#[derive(Copy, Clone)] +struct Foo2 { + bar: u8, + baz: u64 +} + +impl PartialEq for Foo2 { + fn eq(&self, other: &Foo2) -> bool { + self.bar == other.bar && self.baz == other.baz + } +} + +impl fmt::Debug for Foo2 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let bar = self.bar; + let baz = self.baz; + + f.debug_struct("Foo2") + .field("bar", &bar) + .field("baz", &baz) + .finish() + } +} + +#[repr(C, packed(4))] +#[derive(Copy, Clone)] +struct Foo4C { + bar: u8, + baz: u64 +} + +impl PartialEq for Foo4C { + fn eq(&self, other: &Foo4C) -> bool { + self.bar == other.bar && self.baz == other.baz + } +} + +impl fmt::Debug for Foo4C { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let bar = self.bar; + let baz = self.baz; + + f.debug_struct("Foo4C") + .field("bar", &bar) + .field("baz", &baz) + .finish() + } +} + +pub fn main() { + let foo1s = [Foo1 { bar: 1, baz: 2 }; 10]; + + assert_eq!(mem::align_of::<[Foo1; 10]>(), 1); + assert_eq!(mem::size_of::<[Foo1; 10]>(), 90); + + for i in 0..10 { + assert_eq!(foo1s[i], Foo1 { bar: 1, baz: 2}); + } + + for &foo in &foo1s { + assert_eq!(foo, Foo1 { bar: 1, baz: 2 }); + } + + let foo2s = [Foo2 { bar: 1, baz: 2 }; 10]; + + assert_eq!(mem::align_of::<[Foo2; 10]>(), 2); + assert_eq!(mem::size_of::<[Foo2; 10]>(), 100); + + for i in 0..10 { + assert_eq!(foo2s[i], Foo2 { bar: 1, baz: 2}); + } + + for &foo in &foo2s { + assert_eq!(foo, Foo2 { bar: 1, baz: 2 }); + } + + let foo4s = [Foo4C { bar: 1, baz: 2 }; 10]; + + assert_eq!(mem::align_of::<[Foo4C; 10]>(), 4); + assert_eq!(mem::size_of::<[Foo4C; 10]>(), 120); + + for i in 0..10 { + assert_eq!(foo4s[i], Foo4C { bar: 1, baz: 2}); + } + + for &foo in &foo4s { + assert_eq!(foo, Foo4C { bar: 1, baz: 2 }); + } +} diff --git a/tests/ui/packed/packed-tuple-struct-layout.rs b/tests/ui/packed/packed-tuple-struct-layout.rs new file mode 100644 index 000000000..931be5b94 --- /dev/null +++ b/tests/ui/packed/packed-tuple-struct-layout.rs @@ -0,0 +1,23 @@ +// run-pass +use std::mem; + +#[repr(packed)] +#[allow(unused_tuple_struct_fields)] +struct S4(u8,[u8; 3]); + +#[repr(packed)] +#[allow(unused_tuple_struct_fields)] +struct S5(u8,u32); + +pub fn main() { + unsafe { + let s4 = S4(1, [2,3,4]); + let transd : [u8; 4] = mem::transmute(s4); + assert_eq!(transd, [1, 2, 3, 4]); + + let s5 = S5(1, 0xff_00_00_ff); + let transd : [u8; 5] = mem::transmute(s5); + // Don't worry about endianness, the u32 is palindromic. + assert_eq!(transd, [1, 0xff, 0, 0, 0xff]); + } +} diff --git a/tests/ui/packed/packed-tuple-struct-size.rs b/tests/ui/packed/packed-tuple-struct-size.rs new file mode 100644 index 000000000..f7a3c903f --- /dev/null +++ b/tests/ui/packed/packed-tuple-struct-size.rs @@ -0,0 +1,79 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +use std::mem; + +#[repr(packed)] +struct P1S4(u8,[u8; 3]); + +#[repr(packed(2))] +struct P2S4(u8,[u8; 3]); + +#[repr(packed)] +struct P1S5(u8, u32); + +#[repr(packed(2))] +struct P2S6(u8, u32); + +#[repr(packed)] +struct P1S13(i64, f32, u8); + +#[repr(packed(2))] +struct P2S14(i64, f32, u8); + +#[repr(packed(4))] +struct P4S16(u8, f32, i64, u16); + +#[repr(C, packed(4))] +struct P4CS20(u8, f32, i64, u16); + +enum Foo { + Bar = 1, + Baz = 2 +} + +#[repr(packed)] +struct P1S3_Foo(u8, u16, Foo); + +#[repr(packed(2))] +struct P2_Foo(Foo); + +#[repr(packed(2))] +struct P2S3_Foo(u8, u16, Foo); + +#[repr(packed)] +struct P1S7_Option(f32, u8, u16, Option>); + +#[repr(packed(2))] +struct P2_Option(Option>); + +#[repr(packed(2))] +struct P2S7_Option(f32, u8, u16, Option>); + +fn align_to(value: usize, align: usize) -> usize { + (value + (align - 1)) & !(align - 1) +} + +macro_rules! check { + ($t:ty, $align:expr, $size:expr) => ({ + assert_eq!(mem::align_of::<$t>(), $align); + assert_eq!(mem::size_of::<$t>(), $size); + }); +} + +pub fn main() { + check!(P1S4, 1, 4); + check!(P1S5, 1, 5); + check!(P1S13, 1, 13); + check!(P1S3_Foo, 1, 3 + mem::size_of::()); + check!(P1S7_Option, 1, 7 + mem::size_of::>>()); + + check!(P2S4, 1, 4); + check!(P2S6, 2, 6); + check!(P2S14, 2, 14); + check!(P4S16, 4, 16); + check!(P4CS20, 4, 20); + check!(P2S3_Foo, 2, align_to(3 + mem::size_of::(), 2)); + check!(P2S7_Option, 2, align_to(7 + mem::size_of::(), 2)); +} diff --git a/tests/ui/packed/packed-with-inference-vars-issue-61402.rs b/tests/ui/packed/packed-with-inference-vars-issue-61402.rs new file mode 100644 index 000000000..659864c1d --- /dev/null +++ b/tests/ui/packed/packed-with-inference-vars-issue-61402.rs @@ -0,0 +1,22 @@ +// run-pass +// If a struct is packed and its last field has drop glue, then that +// field needs to be Sized (to allow it to be destroyed out-of-place). +// +// This is checked by the compiler during wfcheck. That check used +// to have problems with associated types in the last field - test +// that this doesn't ICE. + +#![allow(unused_imports, dead_code)] + +pub struct S; + +pub trait Trait { type Assoc; } + +impl Trait for S { type Assoc = X; } + +#[repr(C, packed)] +struct PackedAssocSized { + pos: Box<>::Assoc>, +} + +fn main() { println!("Hello, world!"); } diff --git a/tests/ui/panic-handler/auxiliary/some-panic-impl.rs b/tests/ui/panic-handler/auxiliary/some-panic-impl.rs new file mode 100644 index 000000000..0348b3a2d --- /dev/null +++ b/tests/ui/panic-handler/auxiliary/some-panic-impl.rs @@ -0,0 +1,11 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/panic-handler/auxiliary/weak-lang-items.rs b/tests/ui/panic-handler/auxiliary/weak-lang-items.rs new file mode 100644 index 000000000..7a698cf76 --- /dev/null +++ b/tests/ui/panic-handler/auxiliary/weak-lang-items.rs @@ -0,0 +1,22 @@ +// no-prefer-dynamic + +// This aux-file will require the eh_personality function to be codegen'd, but +// it hasn't been defined just yet. Make sure we don't explode. + +#![no_std] +#![crate_type = "rlib"] + +struct A; + +impl core::ops::Drop for A { + fn drop(&mut self) {} +} + +pub fn foo() { + let _a = A; + panic!("wut"); +} + +mod std { + pub use core::{option, fmt}; +} diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs new file mode 100644 index 000000000..775961d3f --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs @@ -0,0 +1,13 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic( + info: PanicInfo, //~ ERROR argument should be `&PanicInfo` +) -> () //~ ERROR return type should be `!` +{ +} diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr new file mode 100644 index 000000000..8b044f766 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr @@ -0,0 +1,14 @@ +error: return type should be `!` + --> $DIR/panic-handler-bad-signature-1.rs:11:6 + | +LL | ) -> () + | ^^ + +error: argument should be `&PanicInfo` + --> $DIR/panic-handler-bad-signature-1.rs:10:11 + | +LL | info: PanicInfo, + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs new file mode 100644 index 000000000..727934000 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs @@ -0,0 +1,14 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic( + info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo` +) -> ! +{ + loop {} +} diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr new file mode 100644 index 000000000..5ab693420 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr @@ -0,0 +1,8 @@ +error: argument should be `&PanicInfo` + --> $DIR/panic-handler-bad-signature-2.rs:10:11 + | +LL | info: &'static PanicInfo, + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs new file mode 100644 index 000000000..ab9c9d7f4 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs @@ -0,0 +1,11 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic() -> ! { //~ ERROR function should have one argument + loop {} +} diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr new file mode 100644 index 000000000..0a70181fd --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr @@ -0,0 +1,8 @@ +error: function should have one argument + --> $DIR/panic-handler-bad-signature-3.rs:9:1 + | +LL | fn panic() -> ! { + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-4.rs b/tests/ui/panic-handler/panic-handler-bad-signature-4.rs new file mode 100644 index 000000000..8240ab083 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-4.rs @@ -0,0 +1,12 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(pi: &PanicInfo) -> ! { + //~^ ERROR should have no type parameters + loop {} +} diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr new file mode 100644 index 000000000..5e46da121 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-bad-signature-4.stderr @@ -0,0 +1,8 @@ +error: should have no type parameters + --> $DIR/panic-handler-bad-signature-4.rs:9:1 + | +LL | fn panic(pi: &PanicInfo) -> ! { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/panic-handler/panic-handler-duplicate.rs b/tests/ui/panic-handler/panic-handler-duplicate.rs new file mode 100644 index 000000000..bd99af999 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-duplicate.rs @@ -0,0 +1,17 @@ +// compile-flags:-C panic=abort + +#![feature(lang_items)] +#![no_std] +#![no_main] + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + loop {} +} + +#[lang = "panic_impl"] +fn panic2(info: &PanicInfo) -> ! { //~ ERROR found duplicate lang item `panic_impl` + loop {} +} diff --git a/tests/ui/panic-handler/panic-handler-duplicate.stderr b/tests/ui/panic-handler/panic-handler-duplicate.stderr new file mode 100644 index 000000000..8cdc4888d --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-duplicate.stderr @@ -0,0 +1,15 @@ +error[E0152]: found duplicate lang item `panic_impl` + --> $DIR/panic-handler-duplicate.rs:15:1 + | +LL | fn panic2(info: &PanicInfo) -> ! { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lang item is first defined here + --> $DIR/panic-handler-duplicate.rs:10:1 + | +LL | fn panic(info: &PanicInfo) -> ! { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/panic-handler/panic-handler-missing.rs b/tests/ui/panic-handler/panic-handler-missing.rs new file mode 100644 index 000000000..6bb062ba6 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-missing.rs @@ -0,0 +1,9 @@ +// dont-check-compiler-stderr +// error-pattern: `#[panic_handler]` function required, but not found + +#![feature(lang_items)] +#![no_main] +#![no_std] + +#[lang = "eh_personality"] +fn eh() {} diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.rs b/tests/ui/panic-handler/panic-handler-requires-panic-info.rs new file mode 100644 index 000000000..f13c12fc5 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.rs @@ -0,0 +1,15 @@ +// compile-flags:-C panic=abort +// error-pattern: language item required, but not found: `panic_info` + +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] +#![no_main] + +#[panic_handler] +fn panic() -> ! { + loop {} +} + +#[lang = "sized"] +trait Sized {} diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr new file mode 100644 index 000000000..2bae12efb --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr @@ -0,0 +1,4 @@ +error: language item required, but not found: `panic_info` + +error: aborting due to previous error + diff --git a/tests/ui/panic-handler/panic-handler-std.rs b/tests/ui/panic-handler/panic-handler-std.rs new file mode 100644 index 000000000..6183c886c --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-std.rs @@ -0,0 +1,12 @@ +// normalize-stderr-test "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" +// error-pattern: found duplicate lang item `panic_impl` + + +use std::panic::PanicInfo; + +#[panic_handler] +fn panic(info: PanicInfo) -> ! { + loop {} +} + +fn main() {} diff --git a/tests/ui/panic-handler/panic-handler-std.stderr b/tests/ui/panic-handler/panic-handler-std.stderr new file mode 100644 index 000000000..7c7feffe7 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-std.stderr @@ -0,0 +1,13 @@ +error[E0152]: found duplicate lang item `panic_impl` + --> $DIR/panic-handler-std.rs:8:1 + | +LL | fn panic(info: PanicInfo) -> ! { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `std` (which `panic_handler_std` depends on) + = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib + = note: second definition in the local crate (`panic_handler_std`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/panic-handler/panic-handler-twice.rs b/tests/ui/panic-handler/panic-handler-twice.rs new file mode 100644 index 000000000..05bef66d8 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-twice.rs @@ -0,0 +1,19 @@ +// dont-check-compiler-stderr +// aux-build:some-panic-impl.rs + +#![feature(lang_items)] +#![no_std] +#![no_main] + +extern crate some_panic_impl; + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + //~^ ERROR found duplicate lang item `panic_impl` + loop {} +} + +#[lang = "eh_personality"] +fn eh() {} diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.rs b/tests/ui/panic-handler/panic-handler-wrong-location.rs new file mode 100644 index 000000000..dca591018 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-wrong-location.rs @@ -0,0 +1,8 @@ +// compile-flags:-C panic=abort + +#![no_std] +#![no_main] + +#[panic_handler] //~ ERROR `panic_impl` language item must be applied to a function +#[no_mangle] +static X: u32 = 42; diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.stderr b/tests/ui/panic-handler/panic-handler-wrong-location.stderr new file mode 100644 index 000000000..ae3ed5ab1 --- /dev/null +++ b/tests/ui/panic-handler/panic-handler-wrong-location.stderr @@ -0,0 +1,11 @@ +error[E0718]: `panic_impl` language item must be applied to a function + --> $DIR/panic-handler-wrong-location.rs:6:1 + | +LL | #[panic_handler] + | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static item + +error: `#[panic_handler]` function required, but not found + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0718`. diff --git a/tests/ui/panic-handler/weak-lang-item-2.rs b/tests/ui/panic-handler/weak-lang-item-2.rs new file mode 100644 index 000000000..a429d8fab --- /dev/null +++ b/tests/ui/panic-handler/weak-lang-item-2.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:weak-lang-items.rs + +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +extern crate weak_lang_items as other; + +use std::thread; + +fn main() { + let _ = thread::spawn(move|| { + other::foo() + }); +} diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs new file mode 100644 index 000000000..14a07a9ef --- /dev/null +++ b/tests/ui/panic-handler/weak-lang-item.rs @@ -0,0 +1,12 @@ +// aux-build:weak-lang-items.rs +// error-pattern: `#[panic_handler]` function required, but not found +// error-pattern: language item required, but not found: `eh_personality` +// needs-unwind since it affects the error output +// ignore-emscripten missing eh_catch_typeinfo lang item + +#![no_std] + +extern crate core; +extern crate weak_lang_items; + +fn main() {} diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr new file mode 100644 index 000000000..202f3309d --- /dev/null +++ b/tests/ui/panic-handler/weak-lang-item.stderr @@ -0,0 +1,22 @@ +error[E0259]: the name `core` is defined multiple times + --> $DIR/weak-lang-item.rs:9:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ `core` reimported here + | + = note: `core` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate core as other_core; + | + +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + | + = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library + = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs new file mode 100644 index 000000000..58a90a592 --- /dev/null +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs @@ -0,0 +1,18 @@ +// build-fail +// compile-flags:-C panic=abort -C prefer-dynamic +// needs-unwind +// ignore-musl - no dylibs here +// ignore-emscripten +// ignore-sgx no dynamic lib support +// error-pattern:`panic_unwind` is not compiled with this crate's panic strategy + +// This is a test where the local crate, compiled with `panic=abort`, links to +// the standard library **dynamically** which is already linked against +// `panic=unwind`. We should fail because the linked panic runtime does not +// correspond with our `-C panic` option. +// +// Note that this test assumes that the dynamic version of the standard library +// is linked to `panic_unwind`, which is currently the case. + +fn main() { +} diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr new file mode 100644 index 000000000..704b81ae1 --- /dev/null +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.stderr @@ -0,0 +1,4 @@ +error: the linked panic runtime `panic_unwind` is not compiled with this crate's panic strategy `abort` + +error: aborting due to previous error + diff --git a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs new file mode 100644 index 000000000..566626513 --- /dev/null +++ b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(unused_variables)] +// compile-flags:-C panic=abort +// aux-build:exit-success-if-unwind.rs +// no-prefer-dynamic +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-macos + +extern crate exit_success_if_unwind; + +use std::process::Command; +use std::env; + +fn main() { + let mut args = env::args_os(); + let me = args.next().unwrap(); + + if let Some(s) = args.next() { + if &*s == "foo" { + exit_success_if_unwind::bar(do_panic); + } + } + + let mut cmd = Command::new(env::args_os().next().unwrap()); + cmd.arg("foo"); + + + // ARMv6 hanges while printing the backtrace, see #41004 + if cfg!(target_arch = "arm") && cfg!(target_env = "gnu") { + cmd.env("RUST_BACKTRACE", "0"); + } + + let s = cmd.status(); + assert!(s.unwrap().code() != Some(0)); +} + +fn do_panic() { + panic!("try to catch me"); +} diff --git a/tests/ui/panic-runtime/abort.rs b/tests/ui/panic-runtime/abort.rs new file mode 100644 index 000000000..dcc4061fd --- /dev/null +++ b/tests/ui/panic-runtime/abort.rs @@ -0,0 +1,43 @@ +// run-pass +#![allow(unused_variables)] +// compile-flags:-C panic=abort +// no-prefer-dynamic +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-macos + +use std::process::Command; +use std::env; + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + std::process::exit(0); + } +} + +fn main() { + let mut args = env::args_os(); + let me = args.next().unwrap(); + + if let Some(s) = args.next() { + if &*s == "foo" { + + let _bomb = Bomb; + + panic!("try to catch me"); + } + } + + let mut cmd = Command::new(env::args_os().next().unwrap()); + cmd.arg("foo"); + + // ARMv6 hanges while printing the backtrace, see #41004 + if cfg!(target_arch = "arm") && cfg!(target_env = "gnu") { + cmd.env("RUST_BACKTRACE", "0"); + } + + let s = cmd.status(); + assert!(s.unwrap().code() != Some(0)); +} diff --git a/tests/ui/panic-runtime/auxiliary/depends.rs b/tests/ui/panic-runtime/auxiliary/depends.rs new file mode 100644 index 000000000..e9bc2f489 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/depends.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![feature(panic_runtime)] +#![crate_type = "rlib"] +#![panic_runtime] +#![no_std] + +extern crate needs_panic_runtime; diff --git a/tests/ui/panic-runtime/auxiliary/exit-success-if-unwind.rs b/tests/ui/panic-runtime/auxiliary/exit-success-if-unwind.rs new file mode 100644 index 000000000..c0e057405 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/exit-success-if-unwind.rs @@ -0,0 +1,16 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + std::process::exit(0); + } +} + +pub fn bar(f: fn()) { + let _bomb = Bomb; + f(); +} diff --git a/tests/ui/panic-runtime/auxiliary/needs-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-abort.rs new file mode 100644 index 000000000..8fad49b5e --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/needs-abort.rs @@ -0,0 +1,5 @@ +// compile-flags:-C panic=abort +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] diff --git a/tests/ui/panic-runtime/auxiliary/needs-panic-runtime.rs b/tests/ui/panic-runtime/auxiliary/needs-panic-runtime.rs new file mode 100644 index 000000000..3f030c169 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/needs-panic-runtime.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![feature(needs_panic_runtime)] +#![crate_type = "rlib"] +#![needs_panic_runtime] +#![no_std] diff --git a/tests/ui/panic-runtime/auxiliary/needs-unwind.rs b/tests/ui/panic-runtime/auxiliary/needs-unwind.rs new file mode 100644 index 000000000..d555b5319 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/needs-unwind.rs @@ -0,0 +1,13 @@ +// compile-flags:-C panic=unwind +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] +#![feature(c_unwind)] + +extern "C-unwind" fn foo() {} + +fn bar() { + let ptr: extern "C-unwind" fn() = foo; + ptr(); +} diff --git a/tests/ui/panic-runtime/auxiliary/panic-runtime-abort.rs b/tests/ui/panic-runtime/auxiliary/panic-runtime-abort.rs new file mode 100644 index 000000000..c92015eee --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/panic-runtime-abort.rs @@ -0,0 +1,17 @@ +// compile-flags:-C panic=abort +// no-prefer-dynamic + +#![feature(panic_runtime)] +#![crate_type = "rlib"] + +#![no_std] +#![panic_runtime] + +#[no_mangle] +pub extern "C" fn __rust_maybe_catch_panic() {} + +#[no_mangle] +pub extern "C" fn __rust_start_panic() {} + +#[no_mangle] +pub extern "C" fn rust_eh_personality() {} diff --git a/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs new file mode 100644 index 000000000..b9ef2f329 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs @@ -0,0 +1,15 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#![no_std] +#![feature(lang_items)] + +use core::panic::PanicInfo; + +#[lang = "panic_impl"] +fn panic_impl(info: &PanicInfo) -> ! { loop {} } +#[lang = "eh_personality"] +fn eh_personality() {} +#[lang = "eh_catch_typeinfo"] +static EH_CATCH_TYPEINFO: u8 = 0; diff --git a/tests/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs b/tests/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs new file mode 100644 index 000000000..2f7aed924 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/panic-runtime-unwind.rs @@ -0,0 +1,17 @@ +// compile-flags:-C panic=unwind +// no-prefer-dynamic + +#![feature(panic_runtime)] +#![crate_type = "rlib"] + +#![no_std] +#![panic_runtime] + +#[no_mangle] +pub extern "C" fn __rust_maybe_catch_panic() {} + +#[no_mangle] +pub extern "C" fn __rust_start_panic() {} + +#[no_mangle] +pub extern "C" fn rust_eh_personality() {} diff --git a/tests/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs b/tests/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs new file mode 100644 index 000000000..2f7aed924 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/panic-runtime-unwind2.rs @@ -0,0 +1,17 @@ +// compile-flags:-C panic=unwind +// no-prefer-dynamic + +#![feature(panic_runtime)] +#![crate_type = "rlib"] + +#![no_std] +#![panic_runtime] + +#[no_mangle] +pub extern "C" fn __rust_maybe_catch_panic() {} + +#[no_mangle] +pub extern "C" fn __rust_start_panic() {} + +#[no_mangle] +pub extern "C" fn rust_eh_personality() {} diff --git a/tests/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs b/tests/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs new file mode 100644 index 000000000..3c0d2d658 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/wants-panic-runtime-abort.rs @@ -0,0 +1,7 @@ +// compile-flags:-C panic=abort +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +extern crate panic_runtime_abort; diff --git a/tests/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs b/tests/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs new file mode 100644 index 000000000..d5f010219 --- /dev/null +++ b/tests/ui/panic-runtime/auxiliary/wants-panic-runtime-unwind.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +extern crate panic_runtime_unwind; diff --git a/tests/ui/panic-runtime/bad-panic-flag1.rs b/tests/ui/panic-runtime/bad-panic-flag1.rs new file mode 100644 index 000000000..1ac6a3423 --- /dev/null +++ b/tests/ui/panic-runtime/bad-panic-flag1.rs @@ -0,0 +1,4 @@ +// compile-flags:-C panic=foo +// error-pattern:either `unwind` or `abort` was expected + +fn main() {} diff --git a/tests/ui/panic-runtime/bad-panic-flag1.stderr b/tests/ui/panic-runtime/bad-panic-flag1.stderr new file mode 100644 index 000000000..013373c6f --- /dev/null +++ b/tests/ui/panic-runtime/bad-panic-flag1.stderr @@ -0,0 +1,2 @@ +error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected + diff --git a/tests/ui/panic-runtime/bad-panic-flag2.rs b/tests/ui/panic-runtime/bad-panic-flag2.rs new file mode 100644 index 000000000..c79701c83 --- /dev/null +++ b/tests/ui/panic-runtime/bad-panic-flag2.rs @@ -0,0 +1,4 @@ +// compile-flags:-C panic +// error-pattern:requires either `unwind` or `abort` + +fn main() {} diff --git a/tests/ui/panic-runtime/bad-panic-flag2.stderr b/tests/ui/panic-runtime/bad-panic-flag2.stderr new file mode 100644 index 000000000..6ab94ea70 --- /dev/null +++ b/tests/ui/panic-runtime/bad-panic-flag2.stderr @@ -0,0 +1,2 @@ +error: codegen option `panic` requires either `unwind` or `abort` (C panic=) + diff --git a/tests/ui/panic-runtime/incompatible-type.rs b/tests/ui/panic-runtime/incompatible-type.rs new file mode 100644 index 000000000..026364a20 --- /dev/null +++ b/tests/ui/panic-runtime/incompatible-type.rs @@ -0,0 +1,24 @@ +// Check that rust_eh_personality can have a different type signature than the +// one hardcoded in the compiler. Regression test for #70117. Used to fail with: +// +// Assertion `isa(Val) && "cast() argument of incompatible type!"' failed. +// +// build-pass +// compile-flags: --crate-type=lib -Ccodegen-units=1 +#![no_std] +#![panic_runtime] +#![feature(panic_runtime)] +#![feature(rustc_attrs)] + +pub struct DropMe; + +impl Drop for DropMe { + fn drop(&mut self) {} +} + +pub fn test(_: DropMe) { + unreachable!(); +} + +#[rustc_std_internal_symbol] +pub unsafe extern "C" fn rust_eh_personality() {} diff --git a/tests/ui/panic-runtime/link-to-abort.rs b/tests/ui/panic-runtime/link-to-abort.rs new file mode 100644 index 000000000..422206c57 --- /dev/null +++ b/tests/ui/panic-runtime/link-to-abort.rs @@ -0,0 +1,11 @@ +// run-pass + +// compile-flags:-C panic=abort +// no-prefer-dynamic +// ignore-macos + +#![feature(panic_abort)] + +extern crate panic_abort; + +fn main() {} diff --git a/tests/ui/panic-runtime/link-to-unwind.rs b/tests/ui/panic-runtime/link-to-unwind.rs new file mode 100644 index 000000000..59036ca99 --- /dev/null +++ b/tests/ui/panic-runtime/link-to-unwind.rs @@ -0,0 +1,10 @@ +// run-pass + +// no-prefer-dynamic + +#![feature(panic_unwind)] + +extern crate panic_unwind; + +fn main() { +} diff --git a/tests/ui/panic-runtime/lto-abort.rs b/tests/ui/panic-runtime/lto-abort.rs new file mode 100644 index 000000000..5cc4c0132 --- /dev/null +++ b/tests/ui/panic-runtime/lto-abort.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_variables)] +// compile-flags:-C lto -C panic=abort +// no-prefer-dynamic +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::process::Command; +use std::env; + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + std::process::exit(0); + } +} + +fn main() { + let mut args = env::args_os(); + let me = args.next().unwrap(); + + if let Some(s) = args.next() { + if &*s == "foo" { + + let _bomb = Bomb; + + panic!("try to catch me"); + } + } + let s = Command::new(env::args_os().next().unwrap()).arg("foo").status(); + assert!(s.unwrap().code() != Some(0)); +} diff --git a/tests/ui/panic-runtime/lto-unwind.rs b/tests/ui/panic-runtime/lto-unwind.rs new file mode 100644 index 000000000..24048ebe0 --- /dev/null +++ b/tests/ui/panic-runtime/lto-unwind.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(unused_variables)] + +// compile-flags:-C lto -C panic=unwind +// needs-unwind +// no-prefer-dynamic +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::process::Command; +use std::env; + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + println!("hurray you ran me"); + } +} + +fn main() { + let mut args = env::args_os(); + let me = args.next().unwrap(); + + if let Some(s) = args.next() { + if &*s == "foo" { + + let _bomb = Bomb; + + panic!("try to catch me"); + } + } + let s = Command::new(env::args_os().next().unwrap()).arg("foo").output(); + let s = s.unwrap(); + assert!(!s.status.success()); + assert!(String::from_utf8_lossy(&s.stdout).contains("hurray you ran me")); +} diff --git a/tests/ui/panic-runtime/need-abort-got-unwind.rs b/tests/ui/panic-runtime/need-abort-got-unwind.rs new file mode 100644 index 000000000..e92400931 --- /dev/null +++ b/tests/ui/panic-runtime/need-abort-got-unwind.rs @@ -0,0 +1,8 @@ +// build-fail +// needs-unwind +// error-pattern:is incompatible with this crate's strategy of `unwind` +// aux-build:needs-abort.rs + +extern crate needs_abort; + +fn main() {} diff --git a/tests/ui/panic-runtime/need-abort-got-unwind.stderr b/tests/ui/panic-runtime/need-abort-got-unwind.stderr new file mode 100644 index 000000000..d29c7875f --- /dev/null +++ b/tests/ui/panic-runtime/need-abort-got-unwind.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` + +error: aborting due to previous error + diff --git a/tests/ui/panic-runtime/need-unwind-got-abort.rs b/tests/ui/panic-runtime/need-unwind-got-abort.rs new file mode 100644 index 000000000..6752ecf90 --- /dev/null +++ b/tests/ui/panic-runtime/need-unwind-got-abort.rs @@ -0,0 +1,9 @@ +// build-fail +// error-pattern:is incompatible with this crate's strategy of `abort` +// aux-build:needs-unwind.rs +// compile-flags:-C panic=abort +// no-prefer-dynamic + +extern crate needs_unwind; + +fn main() {} diff --git a/tests/ui/panic-runtime/need-unwind-got-abort.stderr b/tests/ui/panic-runtime/need-unwind-got-abort.stderr new file mode 100644 index 000000000..4c71df3eb --- /dev/null +++ b/tests/ui/panic-runtime/need-unwind-got-abort.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` + +error: aborting due to previous error + diff --git a/tests/ui/panic-runtime/needs-gate.rs b/tests/ui/panic-runtime/needs-gate.rs new file mode 100644 index 000000000..9e143adfe --- /dev/null +++ b/tests/ui/panic-runtime/needs-gate.rs @@ -0,0 +1,7 @@ +// gate-test-needs_panic_runtime +// gate-test-panic_runtime + +#![panic_runtime] //~ ERROR: is an experimental feature +#![needs_panic_runtime] //~ ERROR: is an experimental feature + +fn main() {} diff --git a/tests/ui/panic-runtime/needs-gate.stderr b/tests/ui/panic-runtime/needs-gate.stderr new file mode 100644 index 000000000..e067ccaeb --- /dev/null +++ b/tests/ui/panic-runtime/needs-gate.stderr @@ -0,0 +1,21 @@ +error[E0658]: the `#[panic_runtime]` attribute is an experimental feature + --> $DIR/needs-gate.rs:4:1 + | +LL | #![panic_runtime] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #32837 for more information + = help: add `#![feature(panic_runtime)]` to the crate attributes to enable + +error[E0658]: the `#[needs_panic_runtime]` attribute is an experimental feature + --> $DIR/needs-gate.rs:5:1 + | +LL | #![needs_panic_runtime] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #32837 for more information + = help: add `#![feature(needs_panic_runtime)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs b/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs new file mode 100644 index 000000000..d57f1643e --- /dev/null +++ b/tests/ui/panic-runtime/runtime-depend-on-needs-runtime.rs @@ -0,0 +1,8 @@ +// dont-check-compiler-stderr +// aux-build:needs-panic-runtime.rs +// aux-build:depends.rs +// error-pattern:cannot depend on a crate that needs a panic runtime + +extern crate depends; + +fn main() {} diff --git a/tests/ui/panic-runtime/transitive-link-a-bunch.rs b/tests/ui/panic-runtime/transitive-link-a-bunch.rs new file mode 100644 index 000000000..0e74e300f --- /dev/null +++ b/tests/ui/panic-runtime/transitive-link-a-bunch.rs @@ -0,0 +1,15 @@ +// build-fail +// needs-unwind +// aux-build:panic-runtime-unwind.rs +// aux-build:panic-runtime-abort.rs +// aux-build:wants-panic-runtime-unwind.rs +// aux-build:wants-panic-runtime-abort.rs +// aux-build:panic-runtime-lang-items.rs +// error-pattern: is not compiled with this crate's panic strategy `unwind` + +#![no_std] +#![no_main] + +extern crate wants_panic_runtime_unwind; +extern crate wants_panic_runtime_abort; +extern crate panic_runtime_lang_items; diff --git a/tests/ui/panic-runtime/transitive-link-a-bunch.stderr b/tests/ui/panic-runtime/transitive-link-a-bunch.stderr new file mode 100644 index 000000000..7f4a8ed29 --- /dev/null +++ b/tests/ui/panic-runtime/transitive-link-a-bunch.stderr @@ -0,0 +1,8 @@ +error: cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_abort + +error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` + +error: the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs new file mode 100644 index 000000000..7ec658ebc --- /dev/null +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -0,0 +1,15 @@ +// build-fail +// dont-check-compiler-stderr +// error-pattern:cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +// aux-build:panic-runtime-unwind.rs +// aux-build:panic-runtime-unwind2.rs +// aux-build:panic-runtime-lang-items.rs + +#![no_std] +#![no_main] + +extern crate panic_runtime_unwind; +extern crate panic_runtime_unwind2; +extern crate panic_runtime_lang_items; + +fn main() {} diff --git a/tests/ui/panic-runtime/unwind-interleaved.rs b/tests/ui/panic-runtime/unwind-interleaved.rs new file mode 100644 index 000000000..a8b3f3493 --- /dev/null +++ b/tests/ui/panic-runtime/unwind-interleaved.rs @@ -0,0 +1,16 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn a() {} + +fn b() { + panic!(); +} + +fn main() { + let _x = vec![0]; + a(); + let _y = vec![0]; + b(); +} diff --git a/tests/ui/panic-runtime/unwind-rec.rs b/tests/ui/panic-runtime/unwind-rec.rs new file mode 100644 index 000000000..a9b7ee8ec --- /dev/null +++ b/tests/ui/panic-runtime/unwind-rec.rs @@ -0,0 +1,15 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn build() -> Vec { + panic!(); +} + +struct Blk { + node: Vec, +} + +fn main() { + let _blk = Blk { node: build() }; +} diff --git a/tests/ui/panic-runtime/unwind-rec2.rs b/tests/ui/panic-runtime/unwind-rec2.rs new file mode 100644 index 000000000..a130f9e87 --- /dev/null +++ b/tests/ui/panic-runtime/unwind-rec2.rs @@ -0,0 +1,23 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn build1() -> Vec { + vec![0, 0, 0, 0, 0, 0, 0] +} + +fn build2() -> Vec { + panic!(); +} + +struct Blk { + node: Vec, + span: Vec, +} + +fn main() { + let _blk = Blk { + node: build1(), + span: build2(), + }; +} diff --git a/tests/ui/panic-runtime/unwind-tables-target-required.rs b/tests/ui/panic-runtime/unwind-tables-target-required.rs new file mode 100644 index 000000000..3abb52b67 --- /dev/null +++ b/tests/ui/panic-runtime/unwind-tables-target-required.rs @@ -0,0 +1,10 @@ +// Tests that the compiler errors if the user tries to turn off unwind tables +// when they are required. +// +// only-x86_64-windows-msvc +// compile-flags: -C force-unwind-tables=no +// +// error-pattern: target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`. + +pub fn main() { +} diff --git a/tests/ui/panic-runtime/unwind-unique.rs b/tests/ui/panic-runtime/unwind-unique.rs new file mode 100644 index 000000000..d66e39110 --- /dev/null +++ b/tests/ui/panic-runtime/unwind-unique.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn failfn() { + panic!(); +} + +fn main() { + Box::new(0); + failfn(); +} diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs new file mode 100644 index 000000000..e33c3bcc3 --- /dev/null +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -0,0 +1,9 @@ +// build-fail +// dont-check-compiler-stderr +// error-pattern:is not compiled with this crate's panic strategy `abort` +// aux-build:panic-runtime-unwind.rs +// compile-flags:-C panic=abort + +extern crate panic_runtime_unwind; + +fn main() {} diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs new file mode 100644 index 000000000..438f1d85a --- /dev/null +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -0,0 +1,10 @@ +// build-fail +// dont-check-compiler-stderr +// error-pattern:is not compiled with this crate's panic strategy `abort` +// aux-build:panic-runtime-unwind.rs +// aux-build:wants-panic-runtime-unwind.rs +// compile-flags:-C panic=abort + +extern crate wants_panic_runtime_unwind; + +fn main() {} diff --git a/tests/ui/panic-runtime/want-unwind-got-abort.rs b/tests/ui/panic-runtime/want-unwind-got-abort.rs new file mode 100644 index 000000000..b6174dc4e --- /dev/null +++ b/tests/ui/panic-runtime/want-unwind-got-abort.rs @@ -0,0 +1,11 @@ +// build-fail +// needs-unwind +// error-pattern:is not compiled with this crate's panic strategy `unwind` +// aux-build:panic-runtime-abort.rs +// aux-build:panic-runtime-lang-items.rs + +#![no_std] +#![no_main] + +extern crate panic_runtime_abort; +extern crate panic_runtime_lang_items; diff --git a/tests/ui/panic-runtime/want-unwind-got-abort.stderr b/tests/ui/panic-runtime/want-unwind-got-abort.stderr new file mode 100644 index 000000000..d306ce6c5 --- /dev/null +++ b/tests/ui/panic-runtime/want-unwind-got-abort.stderr @@ -0,0 +1,4 @@ +error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` + +error: aborting due to previous error + diff --git a/tests/ui/panic-runtime/want-unwind-got-abort2.rs b/tests/ui/panic-runtime/want-unwind-got-abort2.rs new file mode 100644 index 000000000..b54babbef --- /dev/null +++ b/tests/ui/panic-runtime/want-unwind-got-abort2.rs @@ -0,0 +1,12 @@ +// build-fail +// needs-unwind +// error-pattern:is incompatible with this crate's strategy of `unwind` +// aux-build:panic-runtime-abort.rs +// aux-build:wants-panic-runtime-abort.rs +// aux-build:panic-runtime-lang-items.rs + +#![no_std] +#![no_main] + +extern crate wants_panic_runtime_abort; +extern crate panic_runtime_lang_items; diff --git a/tests/ui/panic-runtime/want-unwind-got-abort2.stderr b/tests/ui/panic-runtime/want-unwind-got-abort2.stderr new file mode 100644 index 000000000..014437b7f --- /dev/null +++ b/tests/ui/panic-runtime/want-unwind-got-abort2.stderr @@ -0,0 +1,6 @@ +error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` + +error: the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/panic-while-printing.rs b/tests/ui/panic-while-printing.rs new file mode 100644 index 000000000..3abedf2a7 --- /dev/null +++ b/tests/ui/panic-while-printing.rs @@ -0,0 +1,25 @@ +// run-pass +// needs-unwind + +#![feature(internal_output_capture)] + +use std::fmt; +use std::fmt::{Display, Formatter}; +use std::io::set_output_capture; +use std::sync::{Arc, Mutex}; + +pub struct A; + +impl Display for A { + fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { + panic!(); + } +} + +fn main() { + set_output_capture(Some(Arc::new(Mutex::new(Vec::new())))); + assert!(std::panic::catch_unwind(|| { + eprintln!("{}", A); + }) + .is_err()); +} diff --git a/tests/ui/panic_implementation-closures.rs b/tests/ui/panic_implementation-closures.rs new file mode 100644 index 000000000..b96125aa9 --- /dev/null +++ b/tests/ui/panic_implementation-closures.rs @@ -0,0 +1,10 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![crate_type = "rlib"] +#![no_std] + +#[panic_handler] +pub fn panic_fmt(_: &::core::panic::PanicInfo) -> ! { + |x: u8| x; + loop {} +} diff --git a/tests/ui/panics/abort-on-panic.rs b/tests/ui/panics/abort-on-panic.rs new file mode 100644 index 000000000..1f6ad64c0 --- /dev/null +++ b/tests/ui/panics/abort-on-panic.rs @@ -0,0 +1,98 @@ +// run-pass + +#![allow(unused_must_use)] +#![feature(c_unwind)] +#![feature(panic_always_abort)] +// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that +// we never unwind through them. + +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::io; +use std::io::prelude::*; +use std::process::{exit, Command, Stdio}; +use std::sync::{Arc, Barrier}; +use std::thread; +use std::{env, panic}; + +extern "C" fn panic_in_ffi() { + panic!("Test"); +} + +fn should_have_aborted() { + io::stdout().write(b"This should never be printed.\n"); + let _ = io::stdout().flush(); +} + +fn bomb_out_but_not_abort(msg: &str) { + eprintln!("bombing out: {}", msg); + exit(1); +} + +fn test() { + let _ = panic::catch_unwind(|| { + panic_in_ffi(); + }); + should_have_aborted(); +} + +fn test_always_abort() { + panic::always_abort(); + let _ = panic::catch_unwind(|| { + panic!(); + }); + should_have_aborted(); +} + +fn test_always_abort_thread() { + let barrier = Arc::new(Barrier::new(2)); + let thr = { + let barrier = barrier.clone(); + thread::spawn(move || { + barrier.wait(); + panic!("in thread"); + }) + }; + panic::always_abort(); + barrier.wait(); + let _ = thr.join(); + bomb_out_but_not_abort("joined - but we were supposed to panic!"); +} + +fn main() { + let tests: &[(_, fn())] = &[ + ("test", test), + ("test_always_abort", test_always_abort), + ("test_always_abort_thread", test_always_abort_thread), + ]; + + let args: Vec = env::args().collect(); + if args.len() > 1 { + // This is inside the self-executed command. + for (a, f) in tests { + if &args[1] == a { + return f(); + } + } + bomb_out_but_not_abort("bad test"); + } + + let execute_self_expecting_abort = |arg| { + let mut p = Command::new(&args[0]) + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) + .arg(arg) + .spawn() + .unwrap(); + let status = p.wait().unwrap(); + assert!(!status.success()); + // Any reasonable platform can distinguish a process which + // called exit(1) from one which panicked. + assert_ne!(status.code(), Some(1)); + }; + + for (a, _f) in tests { + execute_self_expecting_abort(a); + } +} diff --git a/tests/ui/panics/args-panic.rs b/tests/ui/panics/args-panic.rs new file mode 100644 index 000000000..7636025c2 --- /dev/null +++ b/tests/ui/panics/args-panic.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:meep +// ignore-emscripten no processes + +fn f(_a: isize, _b: isize, _c: Box) { + panic!("moop"); +} + +fn main() { + f(1, panic!("meep"), Box::new(42)); +} diff --git a/tests/ui/panics/default-backtrace-ice.rs b/tests/ui/panics/default-backtrace-ice.rs new file mode 100644 index 000000000..fd86a3f9d --- /dev/null +++ b/tests/ui/panics/default-backtrace-ice.rs @@ -0,0 +1,9 @@ +// unset-rustc-env:RUST_BACKTRACE +// compile-flags:-Z treat-err-as-bug=1 +// error-pattern:stack backtrace: +// failure-status:101 +// normalize-stderr-test "note: .*" -> "" +// normalize-stderr-test "thread 'rustc' .*" -> "" +// normalize-stderr-test " .*\n" -> "" + +fn main() { missing_ident; } diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr new file mode 100644 index 000000000..a0025d7e2 --- /dev/null +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find value `missing_ident` in this scope +LL | fn main() { missing_ident; } + + +stack backtrace: + +error: internal compiler error: unexpected panic + + + + + + + + + +query stack during panic: +end of query stack diff --git a/tests/ui/panics/doublepanic.rs b/tests/ui/panics/doublepanic.rs new file mode 100644 index 000000000..c1fcc875c --- /dev/null +++ b/tests/ui/panics/doublepanic.rs @@ -0,0 +1,10 @@ +#![allow(unreachable_code)] + +// run-fail +// error-pattern:One +// ignore-emscripten no processes + +fn main() { + panic!("One"); + panic!("Two"); +} diff --git a/tests/ui/panics/explicit-panic-msg.rs b/tests/ui/panics/explicit-panic-msg.rs new file mode 100644 index 000000000..9d8035787 --- /dev/null +++ b/tests/ui/panics/explicit-panic-msg.rs @@ -0,0 +1,15 @@ +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(non_fmt_panics)] + +// run-fail +// error-pattern:wooooo +// ignore-emscripten no processes + +fn main() { + let mut a = 1; + if 1 == 1 { + a = 2; + } + panic!(format!("woooo{}", "o")); +} diff --git a/tests/ui/panics/explicit-panic.rs b/tests/ui/panics/explicit-panic.rs new file mode 100644 index 000000000..27c73d349 --- /dev/null +++ b/tests/ui/panics/explicit-panic.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:explicit +// ignore-emscripten no processes + +fn main() { + panic!(); +} diff --git a/tests/ui/panics/fmt-panic.rs b/tests/ui/panics/fmt-panic.rs new file mode 100644 index 000000000..87fb2e6dd --- /dev/null +++ b/tests/ui/panics/fmt-panic.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern:meh +// ignore-emscripten no processes + +fn main() { + let str_var: String = "meh".to_string(); + panic!("{}", str_var); +} diff --git a/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr new file mode 100644 index 000000000..ac4ed8225 --- /dev/null +++ b/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr @@ -0,0 +1,5 @@ +thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:23:5 +stack backtrace: + 0: std::panicking::begin_panic + 1: issue_47429_short_backtraces::main +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs new file mode 100644 index 000000000..58d0fa62c --- /dev/null +++ b/tests/ui/panics/issue-47429-short-backtraces.rs @@ -0,0 +1,24 @@ +// Regression test for #47429: short backtraces were not terminating correctly + +// compile-flags: -O +// compile-flags:-Cstrip=none +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=1 + +// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test +// ignore-android FIXME #17520 +// ignore-openbsd no support for libbacktrace without filename +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support +// ignore-sgx no subprocess support +// ignore-fuchsia Backtraces not symbolized + +// NOTE(eddyb) output differs between symbol mangling schemes +// revisions: legacy v0 +// [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy +// [v0] compile-flags: -Csymbol-mangling-version=v0 + +fn main() { + panic!() +} diff --git a/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr new file mode 100644 index 000000000..65401fe1c --- /dev/null +++ b/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr @@ -0,0 +1,5 @@ +thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:23:5 +stack backtrace: + 0: std::panicking::begin_panic::<&str> + 1: issue_47429_short_backtraces::main +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/location-detail-panic-no-column.rs b/tests/ui/panics/location-detail-panic-no-column.rs new file mode 100644 index 000000000..7cf1bb09c --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-column.rs @@ -0,0 +1,8 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=line,file +// exec-env:RUST_BACKTRACE=0 + +fn main() { + panic!("column-redacted"); +} diff --git a/tests/ui/panics/location-detail-panic-no-column.run.stderr b/tests/ui/panics/location-detail-panic-no-column.run.stderr new file mode 100644 index 000000000..46c9b8448 --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-column.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'column-redacted', $DIR/location-detail-panic-no-column.rs:7:0 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/location-detail-panic-no-file.rs b/tests/ui/panics/location-detail-panic-no-file.rs new file mode 100644 index 000000000..9bcbf01d1 --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-file.rs @@ -0,0 +1,8 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=line,column +// exec-env:RUST_BACKTRACE=0 + +fn main() { + panic!("file-redacted"); +} diff --git a/tests/ui/panics/location-detail-panic-no-file.run.stderr b/tests/ui/panics/location-detail-panic-no-file.run.stderr new file mode 100644 index 000000000..811f93bf3 --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-file.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'file-redacted', :7:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/location-detail-panic-no-line.rs b/tests/ui/panics/location-detail-panic-no-line.rs new file mode 100644 index 000000000..25df092e1 --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-line.rs @@ -0,0 +1,8 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=file,column +// exec-env:RUST_BACKTRACE=0 + +fn main() { + panic!("line-redacted"); +} diff --git a/tests/ui/panics/location-detail-panic-no-line.run.stderr b/tests/ui/panics/location-detail-panic-no-line.run.stderr new file mode 100644 index 000000000..cc3f1624c --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-line.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'line-redacted', $DIR/location-detail-panic-no-line.rs:0:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/location-detail-panic-no-location-info.rs b/tests/ui/panics/location-detail-panic-no-location-info.rs new file mode 100644 index 000000000..7b609145b --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-location-info.rs @@ -0,0 +1,8 @@ +// run-fail +// check-run-results +// compile-flags: -Zlocation-detail=none +// exec-env:RUST_BACKTRACE=0 + +fn main() { + panic!("no location info"); +} diff --git a/tests/ui/panics/location-detail-panic-no-location-info.run.stderr b/tests/ui/panics/location-detail-panic-no-location-info.run.stderr new file mode 100644 index 000000000..d1c310864 --- /dev/null +++ b/tests/ui/panics/location-detail-panic-no-location-info.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'no location info', :0:0 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/location-detail-unwrap-no-file.rs b/tests/ui/panics/location-detail-unwrap-no-file.rs new file mode 100644 index 000000000..5955d9a25 --- /dev/null +++ b/tests/ui/panics/location-detail-unwrap-no-file.rs @@ -0,0 +1,9 @@ +// run-fail +// check-run-results +// compile-flags: -Copt-level=0 -Zlocation-detail=line,column +// exec-env:RUST_BACKTRACE=0 + +fn main() { + let opt: Option = None; + opt.unwrap(); +} diff --git a/tests/ui/panics/location-detail-unwrap-no-file.run.stderr b/tests/ui/panics/location-detail-unwrap-no-file.run.stderr new file mode 100644 index 000000000..7d8e1d930 --- /dev/null +++ b/tests/ui/panics/location-detail-unwrap-no-file.run.stderr @@ -0,0 +1,2 @@ +thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', :8:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/main-panic.rs b/tests/ui/panics/main-panic.rs new file mode 100644 index 000000000..023ab4701 --- /dev/null +++ b/tests/ui/panics/main-panic.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:thread 'main' panicked at +// ignore-emscripten no processes + +fn main() { + panic!() +} diff --git a/tests/ui/panics/panic-2021.rs b/tests/ui/panics/panic-2021.rs new file mode 100644 index 000000000..e606612e1 --- /dev/null +++ b/tests/ui/panics/panic-2021.rs @@ -0,0 +1,9 @@ +// edition:2021 + +fn main() { + panic!(123); //~ ERROR: format argument must be a string literal + panic!("{}"); //~ ERROR: 1 positional argument in format string + core::panic!("{}"); //~ ERROR: 1 positional argument in format string + assert!(false, 123); //~ ERROR: format argument must be a string literal + assert!(false, "{}"); //~ ERROR: 1 positional argument in format string +} diff --git a/tests/ui/panics/panic-2021.stderr b/tests/ui/panics/panic-2021.stderr new file mode 100644 index 000000000..373c1c2c0 --- /dev/null +++ b/tests/ui/panics/panic-2021.stderr @@ -0,0 +1,42 @@ +error: format argument must be a string literal + --> $DIR/panic-2021.rs:4:12 + | +LL | panic!(123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | panic!("{}", 123); + | +++++ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/panic-2021.rs:5:13 + | +LL | panic!("{}"); + | ^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/panic-2021.rs:6:19 + | +LL | core::panic!("{}"); + | ^^ + +error: format argument must be a string literal + --> $DIR/panic-2021.rs:7:20 + | +LL | assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | assert!(false, "{}", 123); + | +++++ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/panic-2021.rs:8:21 + | +LL | assert!(false, "{}"); + | ^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/panics/panic-arg.rs b/tests/ui/panics/panic-arg.rs new file mode 100644 index 000000000..f7c2dbb09 --- /dev/null +++ b/tests/ui/panics/panic-arg.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:woe +// ignore-emscripten no processes + +fn f(a: isize) { + println!("{}", a); +} + +fn main() { + f(panic!("woe")); +} diff --git a/tests/ui/panics/panic-handler-chain-update-hook.rs b/tests/ui/panics/panic-handler-chain-update-hook.rs new file mode 100644 index 000000000..4dd08ba4a --- /dev/null +++ b/tests/ui/panics/panic-handler-chain-update-hook.rs @@ -0,0 +1,36 @@ +// run-pass +// needs-unwind +#![allow(stable_features)] + +// ignore-emscripten no threads support + +#![feature(std_panic)] +#![feature(panic_update_hook)] + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::panic; +use std::thread; + +static A: AtomicUsize = AtomicUsize::new(0); +static B: AtomicUsize = AtomicUsize::new(0); +static C: AtomicUsize = AtomicUsize::new(0); + +fn main() { + panic::set_hook(Box::new(|_| { A.fetch_add(1, Ordering::SeqCst); })); + panic::update_hook(|prev, info| { + B.fetch_add(1, Ordering::SeqCst); + prev(info); + }); + panic::update_hook(|prev, info| { + C.fetch_add(1, Ordering::SeqCst); + prev(info); + }); + + let _ = thread::spawn(|| { + panic!(); + }).join(); + + assert_eq!(1, A.load(Ordering::SeqCst)); + assert_eq!(1, B.load(Ordering::SeqCst)); + assert_eq!(1, C.load(Ordering::SeqCst)); +} diff --git a/tests/ui/panics/panic-handler-chain.rs b/tests/ui/panics/panic-handler-chain.rs new file mode 100644 index 000000000..73d6e790d --- /dev/null +++ b/tests/ui/panics/panic-handler-chain.rs @@ -0,0 +1,30 @@ +// run-pass +// needs-unwind +#![allow(stable_features)] + +// ignore-emscripten no threads support + +#![feature(std_panic)] + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::panic; +use std::thread; + +static A: AtomicUsize = AtomicUsize::new(0); +static B: AtomicUsize = AtomicUsize::new(0); + +fn main() { + panic::set_hook(Box::new(|_| { A.fetch_add(1, Ordering::SeqCst); })); + let hook = panic::take_hook(); + panic::set_hook(Box::new(move |info| { + B.fetch_add(1, Ordering::SeqCst); + hook(info); + })); + + let _ = thread::spawn(|| { + panic!(); + }).join(); + + assert_eq!(1, A.load(Ordering::SeqCst)); + assert_eq!(1, B.load(Ordering::SeqCst)); +} diff --git a/tests/ui/panics/panic-handler-flail-wildly.rs b/tests/ui/panics/panic-handler-flail-wildly.rs new file mode 100644 index 000000000..679dc7de8 --- /dev/null +++ b/tests/ui/panics/panic-handler-flail-wildly.rs @@ -0,0 +1,56 @@ +// run-pass +// needs-unwind + +#![allow(stable_features)] +#![allow(unused_must_use)] + +// ignore-emscripten no threads support + +#![feature(std_panic)] + +use std::panic; +use std::thread; + +fn a() { + panic::set_hook(Box::new(|_| println!("hello yes this is a"))); + panic::take_hook(); + panic::set_hook(Box::new(|_| println!("hello yes this is a part 2"))); + panic::take_hook(); +} + +fn b() { + panic::take_hook(); + panic::take_hook(); + panic::take_hook(); + panic::take_hook(); + panic::take_hook(); + panic!(); +} + +fn c() { + panic::set_hook(Box::new(|_| ())); + panic::set_hook(Box::new(|_| ())); + panic::set_hook(Box::new(|_| ())); + panic::set_hook(Box::new(|_| ())); + panic::set_hook(Box::new(|_| ())); + panic::set_hook(Box::new(|_| ())); + panic!(); +} + +fn main() { + for _ in 0..10 { + let mut handles = vec![]; + for _ in 0..10 { + handles.push(thread::spawn(a)); + } + for _ in 0..10 { + handles.push(thread::spawn(b)); + } + for _ in 0..10 { + handles.push(thread::spawn(c)); + } + for handle in handles { + let _ = handle.join(); + } + } +} diff --git a/tests/ui/panics/panic-handler-set-twice.rs b/tests/ui/panics/panic-handler-set-twice.rs new file mode 100644 index 000000000..274453020 --- /dev/null +++ b/tests/ui/panics/panic-handler-set-twice.rs @@ -0,0 +1,25 @@ +// run-pass +// needs-unwind +#![allow(unused_variables)] +#![allow(stable_features)] + +#![feature(std_panic)] + +// ignore-emscripten no threads support + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::panic; +use std::thread; + +static A: AtomicUsize = AtomicUsize::new(0); + +fn main() { + panic::set_hook(Box::new(|_| ())); + panic::set_hook(Box::new(|info| { A.fetch_add(1, Ordering::SeqCst); })); + + let _ = thread::spawn(|| { + panic!(); + }).join(); + + assert_eq!(1, A.load(Ordering::SeqCst)); +} diff --git a/tests/ui/panics/panic-in-dtor-drops-fields.rs b/tests/ui/panics/panic-in-dtor-drops-fields.rs new file mode 100644 index 000000000..c0963aa31 --- /dev/null +++ b/tests/ui/panics/panic-in-dtor-drops-fields.rs @@ -0,0 +1,38 @@ +// run-pass +// needs-unwind +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +// ignore-emscripten no threads support + +use std::thread; + +static mut dropped: bool = false; + +struct A { + b: B, +} + +struct B { + foo: isize, +} + +impl Drop for A { + fn drop(&mut self) { + panic!() + } +} + +impl Drop for B { + fn drop(&mut self) { + unsafe { dropped = true; } + } +} + +pub fn main() { + let ret = thread::spawn(move|| { + let _a = A { b: B { foo: 3 } }; + }).join(); + assert!(ret.is_err()); + unsafe { assert!(dropped); } +} diff --git a/tests/ui/panics/panic-macro-any-wrapped.rs b/tests/ui/panics/panic-macro-any-wrapped.rs new file mode 100644 index 000000000..663bf6713 --- /dev/null +++ b/tests/ui/panics/panic-macro-any-wrapped.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'Box' +// ignore-emscripten no processes + +#![allow(non_fmt_panics)] + +fn main() { + panic!(Box::new(612_i64)); +} diff --git a/tests/ui/panics/panic-macro-any.rs b/tests/ui/panics/panic-macro-any.rs new file mode 100644 index 000000000..c7df53654 --- /dev/null +++ b/tests/ui/panics/panic-macro-any.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:panicked at 'Box' +// ignore-emscripten no processes + +#![allow(non_fmt_panics)] + +fn main() { + panic!(Box::new(413) as Box); +} diff --git a/tests/ui/panics/panic-macro-explicit.rs b/tests/ui/panics/panic-macro-explicit.rs new file mode 100644 index 000000000..ac4d6f812 --- /dev/null +++ b/tests/ui/panics/panic-macro-explicit.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'explicit panic' +// ignore-emscripten no processes + +fn main() { + panic!(); +} diff --git a/tests/ui/panics/panic-macro-fmt.rs b/tests/ui/panics/panic-macro-fmt.rs new file mode 100644 index 000000000..a755ebc0f --- /dev/null +++ b/tests/ui/panics/panic-macro-fmt.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'test-fail-fmt 42 rust' +// ignore-emscripten no processes + +fn main() { + panic!("test-fail-fmt {} {}", 42, "rust"); +} diff --git a/tests/ui/panics/panic-macro-owned.rs b/tests/ui/panics/panic-macro-owned.rs new file mode 100644 index 000000000..b898fde77 --- /dev/null +++ b/tests/ui/panics/panic-macro-owned.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'test-fail-owned' +// ignore-emscripten no processes + +fn main() { + panic!("test-fail-owned"); +} diff --git a/tests/ui/panics/panic-macro-static.rs b/tests/ui/panics/panic-macro-static.rs new file mode 100644 index 000000000..a1d467cbf --- /dev/null +++ b/tests/ui/panics/panic-macro-static.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:panicked at 'test-fail-static' +// ignore-emscripten no processes + +fn main() { + panic!("test-fail-static"); +} diff --git a/tests/ui/panics/panic-main.rs b/tests/ui/panics/panic-main.rs new file mode 100644 index 000000000..87df7688f --- /dev/null +++ b/tests/ui/panics/panic-main.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:moop +// ignore-emscripten no processes + +fn main() { + panic!("moop"); +} diff --git a/tests/ui/panics/panic-parens.rs b/tests/ui/panics/panic-parens.rs new file mode 100644 index 000000000..59ab54446 --- /dev/null +++ b/tests/ui/panics/panic-parens.rs @@ -0,0 +1,20 @@ +// Fail macros without arguments need to be disambiguated in +// certain positions + +// run-fail +// error-pattern:oops +// ignore-emscripten no processes + +fn bigpanic() { + while (panic!("oops")) { + if (panic!()) { + match (panic!()) { + () => {} + } + } + } +} + +fn main() { + bigpanic(); +} diff --git a/tests/ui/panics/panic-recover-propagate.rs b/tests/ui/panics/panic-recover-propagate.rs new file mode 100644 index 000000000..e110d94b6 --- /dev/null +++ b/tests/ui/panics/panic-recover-propagate.rs @@ -0,0 +1,27 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::panic; +use std::thread; + +static A: AtomicUsize = AtomicUsize::new(0); + +fn main() { + panic::set_hook(Box::new(|_| { + A.fetch_add(1, Ordering::SeqCst); + })); + + let result = thread::spawn(|| { + let result = panic::catch_unwind(|| { + panic!("hi there"); + }); + + panic::resume_unwind(result.unwrap_err()); + }).join(); + + let msg = *result.unwrap_err().downcast::<&'static str>().unwrap(); + assert_eq!("hi there", msg); + assert_eq!(1, A.load(Ordering::SeqCst)); +} diff --git a/tests/ui/panics/panic-set-handler.rs b/tests/ui/panics/panic-set-handler.rs new file mode 100644 index 000000000..3c00183e2 --- /dev/null +++ b/tests/ui/panics/panic-set-handler.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:greetings from the panic handler +// ignore-emscripten no processes + +use std::panic; + +fn main() { + panic::set_hook(Box::new(|i| { + eprintln!("greetings from the panic handler"); + })); + panic!("foobar"); +} diff --git a/tests/ui/panics/panic-set-unset-handler.rs b/tests/ui/panics/panic-set-unset-handler.rs new file mode 100644 index 000000000..dde0c72f7 --- /dev/null +++ b/tests/ui/panics/panic-set-unset-handler.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'foobar' +// ignore-emscripten no processes + +use std::panic; + +fn main() { + panic::set_hook(Box::new(|i| { + eprint!("greetings from the panic handler"); + })); + panic::take_hook(); + panic!("foobar"); +} diff --git a/tests/ui/panics/panic-short-backtrace-windows-x86_64.rs b/tests/ui/panics/panic-short-backtrace-windows-x86_64.rs new file mode 100644 index 000000000..39ffe86dd --- /dev/null +++ b/tests/ui/panics/panic-short-backtrace-windows-x86_64.rs @@ -0,0 +1,53 @@ +// This test has been spuriously failing a lot recently (#92000). +// Ignore it until the underlying issue is fixed. +// ignore-test + +// Regression test for #87481: short backtrace formatting cut off the entire stack trace. + +// Codegen-units is specified here so that we can replicate a typical rustc invocation which +// is not normally limited to 1 CGU. This is important so that the `__rust_begin_short_backtrace` +// and `__rust_end_short_backtrace` symbols are not marked internal to the CGU and thus will be +// named in the symbol table. +// compile-flags: -O -Ccodegen-units=8 + +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=1 + +// We need to normalize out frame 5 because without debug info, dbghelp.dll doesn't know where CGU +// internal functions like `main` start or end and so it will return whatever symbol happens +// to be located near the address. +// normalize-stderr-test: "5: .*" -> "5: some Rust fn" + +// Backtraces are pretty broken in general on i686-pc-windows-msvc (#62897). +// only-x86_64-pc-windows-msvc + +fn main() { + a(); +} + +// Make these no_mangle so dbghelp.dll can figure out the symbol names. + +#[no_mangle] +#[inline(never)] +fn a() { + b(); +} + +#[no_mangle] +#[inline(never)] +fn b() { + c(); +} + +#[no_mangle] +#[inline(never)] +fn c() { + d(); +} + +#[no_mangle] +#[inline(never)] +fn d() { + panic!("d was called"); +} diff --git a/tests/ui/panics/panic-short-backtrace-windows-x86_64.run.stderr b/tests/ui/panics/panic-short-backtrace-windows-x86_64.run.stderr new file mode 100644 index 000000000..799a8b30e --- /dev/null +++ b/tests/ui/panics/panic-short-backtrace-windows-x86_64.run.stderr @@ -0,0 +1,9 @@ +thread 'main' panicked at 'd was called', $DIR/panic-short-backtrace-windows-x86_64.rs:48:5 +stack backtrace: + 0: std::panicking::begin_panic + 1: d + 2: c + 3: b + 4: a + 5: some Rust fn +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/panic-take-handler-nop.rs b/tests/ui/panics/panic-take-handler-nop.rs new file mode 100644 index 000000000..41cbac97c --- /dev/null +++ b/tests/ui/panics/panic-take-handler-nop.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:thread 'main' panicked at 'foobar' +// ignore-emscripten no processes + +use std::panic; + +fn main() { + panic::take_hook(); + panic!("foobar"); +} diff --git a/tests/ui/panics/panic-task-name-none.rs b/tests/ui/panics/panic-task-name-none.rs new file mode 100644 index 000000000..4e95fb5bd --- /dev/null +++ b/tests/ui/panics/panic-task-name-none.rs @@ -0,0 +1,13 @@ +// run-fail +// error-pattern:thread '' panicked at 'test' +// ignore-emscripten Needs threads + +use std::thread; + +fn main() { + let r: Result<(), _> = thread::spawn(move || { + panic!("test"); + }) + .join(); + assert!(r.is_ok()); +} diff --git a/tests/ui/panics/panic-task-name-owned.rs b/tests/ui/panics/panic-task-name-owned.rs new file mode 100644 index 000000000..f85be7bb8 --- /dev/null +++ b/tests/ui/panics/panic-task-name-owned.rs @@ -0,0 +1,18 @@ +// run-fail +// error-pattern:thread 'owned name' panicked at 'test' +// ignore-emscripten Needs threads. + +use std::thread::Builder; + +fn main() { + let r: () = Builder::new() + .name("owned name".to_string()) + .spawn(move || { + panic!("test"); + () + }) + .unwrap() + .join() + .unwrap(); + panic!(); +} diff --git a/tests/ui/panics/panic.rs b/tests/ui/panics/panic.rs new file mode 100644 index 000000000..b6227a582 --- /dev/null +++ b/tests/ui/panics/panic.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:1 == 2 +// ignore-emscripten no processes + +fn main() { + assert!(1 == 2); +} diff --git a/tests/ui/panics/result-get-panic.rs b/tests/ui/panics/result-get-panic.rs new file mode 100644 index 000000000..461f30b91 --- /dev/null +++ b/tests/ui/panics/result-get-panic.rs @@ -0,0 +1,9 @@ +// run-fail +// error-pattern:called `Result::unwrap()` on an `Err` value +// ignore-emscripten no processes + +use std::result::Result::Err; + +fn main() { + println!("{}", Err::("kitty".to_string()).unwrap()); +} diff --git a/tests/ui/panics/runtime-switch.legacy.run.stderr b/tests/ui/panics/runtime-switch.legacy.run.stderr new file mode 100644 index 000000000..0f7655163 --- /dev/null +++ b/tests/ui/panics/runtime-switch.legacy.run.stderr @@ -0,0 +1,5 @@ +thread 'main' panicked at 'explicit panic', $DIR/runtime-switch.rs:26:5 +stack backtrace: + 0: std::panicking::begin_panic + 1: runtime_switch::main +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs new file mode 100644 index 000000000..882340e49 --- /dev/null +++ b/tests/ui/panics/runtime-switch.rs @@ -0,0 +1,27 @@ +// Test for std::panic::set_backtrace_style. + +// compile-flags: -O +// compile-flags:-Cstrip=none +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=0 + +// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test +// ignore-android FIXME #17520 +// ignore-openbsd no support for libbacktrace without filename +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support +// ignore-sgx no subprocess support +// ignore-fuchsia Backtrace not symbolized + +// NOTE(eddyb) output differs between symbol mangling schemes +// revisions: legacy v0 +// [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy +// [v0] compile-flags: -Csymbol-mangling-version=v0 + +#![feature(panic_backtrace_config)] + +fn main() { + std::panic::set_backtrace_style(std::panic::BacktraceStyle::Short); + panic!() +} diff --git a/tests/ui/panics/runtime-switch.v0.run.stderr b/tests/ui/panics/runtime-switch.v0.run.stderr new file mode 100644 index 000000000..a4ae44131 --- /dev/null +++ b/tests/ui/panics/runtime-switch.v0.run.stderr @@ -0,0 +1,5 @@ +thread 'main' panicked at 'explicit panic', $DIR/runtime-switch.rs:26:5 +stack backtrace: + 0: std::panicking::begin_panic::<&str> + 1: runtime_switch::main +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/test-panic.rs b/tests/ui/panics/test-panic.rs new file mode 100644 index 000000000..85c9279cd --- /dev/null +++ b/tests/ui/panics/test-panic.rs @@ -0,0 +1,9 @@ +// run-fail +// check-stdout +// compile-flags: --test +// ignore-emscripten + +#[test] +fn test_foo() { + panic!() +} diff --git a/tests/ui/panics/test-should-fail-bad-message.rs b/tests/ui/panics/test-should-fail-bad-message.rs new file mode 100644 index 000000000..701f26776 --- /dev/null +++ b/tests/ui/panics/test-should-fail-bad-message.rs @@ -0,0 +1,10 @@ +// run-fail +// check-stdout +// compile-flags: --test +// ignore-emscripten + +#[test] +#[should_panic(expected = "foobar")] +fn test_foo() { + panic!("blah") +} diff --git a/tests/ui/panics/test-should-panic-bad-message.rs b/tests/ui/panics/test-should-panic-bad-message.rs new file mode 100644 index 000000000..a82c4e144 --- /dev/null +++ b/tests/ui/panics/test-should-panic-bad-message.rs @@ -0,0 +1,10 @@ +// run-fail +// compile-flags: --test +// check-stdout +// ignore-emscripten no processes + +#[test] +#[should_panic(expected = "foo")] +pub fn test_bar() { + panic!("bar") +} diff --git a/tests/ui/panics/test-should-panic-no-message.rs b/tests/ui/panics/test-should-panic-no-message.rs new file mode 100644 index 000000000..13f67a41c --- /dev/null +++ b/tests/ui/panics/test-should-panic-no-message.rs @@ -0,0 +1,10 @@ +// run-fail +// compile-flags: --test +// check-stdout +// ignore-emscripten no processes + +#[test] +#[should_panic(expected = "foo")] +pub fn test_explicit() { + panic!() +} diff --git a/tests/ui/panics/unique-panic.rs b/tests/ui/panics/unique-panic.rs new file mode 100644 index 000000000..ae7911e59 --- /dev/null +++ b/tests/ui/panics/unique-panic.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern: panic +// for some reason, fails to match error string on +// wasm32-unknown-unknown with stripped debuginfo and symbols, +// so don't strip it +// compile-flags:-Cstrip=none + +fn main() { + Box::new(panic!()); +} diff --git a/tests/ui/panics/while-body-panics.rs b/tests/ui/panics/while-body-panics.rs new file mode 100644 index 000000000..2c05eb389 --- /dev/null +++ b/tests/ui/panics/while-body-panics.rs @@ -0,0 +1,14 @@ +#![allow(while_true)] + +// run-fail +// error-pattern:quux +// ignore-emscripten no processes + +fn main() { + let _x: isize = { + while true { + panic!("quux"); + } + 8 + }; +} diff --git a/tests/ui/panics/while-panic.rs b/tests/ui/panics/while-panic.rs new file mode 100644 index 000000000..3c6ee8fa3 --- /dev/null +++ b/tests/ui/panics/while-panic.rs @@ -0,0 +1,14 @@ +#![allow(while_true)] + +// run-fail +// error-pattern:giraffe +// ignore-emscripten no processes + +fn main() { + panic!("{}", { + while true { + panic!("giraffe") + } + "clandestine" + }); +} diff --git a/tests/ui/paren-span.rs b/tests/ui/paren-span.rs new file mode 100644 index 000000000..c8cb63d51 --- /dev/null +++ b/tests/ui/paren-span.rs @@ -0,0 +1,21 @@ +// Be smart about span of parenthesized expression in macro. + +macro_rules! paren { + ($e:expr) => (($e)) + // ^^^^ do not highlight here +} + +mod m { + pub struct S { + x: i32 + } + pub fn make() -> S { + S { x: 0 } + } +} + +fn main() { + let s = m::make(); + paren!(s.x); //~ ERROR field `x` of struct `S` is private + // ^^^ highlight here +} diff --git a/tests/ui/paren-span.stderr b/tests/ui/paren-span.stderr new file mode 100644 index 000000000..fc3137157 --- /dev/null +++ b/tests/ui/paren-span.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `x` of struct `S` is private + --> $DIR/paren-span.rs:19:14 + | +LL | paren!(s.x); + | ^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/parser/ascii-only-character-escape.rs b/tests/ui/parser/ascii-only-character-escape.rs new file mode 100644 index 000000000..725c8ad23 --- /dev/null +++ b/tests/ui/parser/ascii-only-character-escape.rs @@ -0,0 +1,6 @@ +fn main() { + let x = "\x80"; //~ ERROR out of range hex escape + let y = "\xff"; //~ ERROR out of range hex escape + let z = "\xe2"; //~ ERROR out of range hex escape + let a = b"\x00e2"; // ok because byte literal +} diff --git a/tests/ui/parser/ascii-only-character-escape.stderr b/tests/ui/parser/ascii-only-character-escape.stderr new file mode 100644 index 000000000..b599b35f4 --- /dev/null +++ b/tests/ui/parser/ascii-only-character-escape.stderr @@ -0,0 +1,20 @@ +error: out of range hex escape + --> $DIR/ascii-only-character-escape.rs:2:14 + | +LL | let x = "\x80"; + | ^^^^ must be a character in the range [\x00-\x7f] + +error: out of range hex escape + --> $DIR/ascii-only-character-escape.rs:3:14 + | +LL | let y = "\xff"; + | ^^^^ must be a character in the range [\x00-\x7f] + +error: out of range hex escape + --> $DIR/ascii-only-character-escape.rs:4:14 + | +LL | let z = "\xe2"; + | ^^^^ must be a character in the range [\x00-\x7f] + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/assoc-const-underscore-semantic-fail.rs b/tests/ui/parser/assoc-const-underscore-semantic-fail.rs new file mode 100644 index 000000000..d37ce06c5 --- /dev/null +++ b/tests/ui/parser/assoc-const-underscore-semantic-fail.rs @@ -0,0 +1,17 @@ +// Semantically, an associated constant cannot use `_` as a name. + +fn main() {} + +const _: () = { + pub trait A { + const _: () = (); //~ ERROR `const` items in this context need a name + } + impl A for () { + const _: () = (); //~ ERROR `const` items in this context need a name + //~^ ERROR const `_` is not a member of trait `A` + } + struct B; + impl B { + const _: () = (); //~ ERROR `const` items in this context need a name + } +}; diff --git a/tests/ui/parser/assoc-const-underscore-semantic-fail.stderr b/tests/ui/parser/assoc-const-underscore-semantic-fail.stderr new file mode 100644 index 000000000..538bf0ec1 --- /dev/null +++ b/tests/ui/parser/assoc-const-underscore-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:7:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:10:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:15:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error[E0438]: const `_` is not a member of trait `A` + --> $DIR/assoc-const-underscore-semantic-fail.rs:10:9 + | +LL | const _: () = (); + | ^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0438`. diff --git a/tests/ui/parser/assoc-const-underscore-syntactic-pass.rs b/tests/ui/parser/assoc-const-underscore-syntactic-pass.rs new file mode 100644 index 000000000..60da408c8 --- /dev/null +++ b/tests/ui/parser/assoc-const-underscore-syntactic-pass.rs @@ -0,0 +1,18 @@ +// All constant items (associated or otherwise) may syntactically use `_` as a name. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +const _: () = { + pub trait A { + const _: () = (); + } + impl A for () { + const _: () = (); + } + impl dyn A { + const _: () = (); + } +}; diff --git a/tests/ui/parser/assoc-oddities-1.rs b/tests/ui/parser/assoc-oddities-1.rs new file mode 100644 index 000000000..5914805e5 --- /dev/null +++ b/tests/ui/parser/assoc-oddities-1.rs @@ -0,0 +1,11 @@ +// compile-flags: -Z parse-only + +fn main() { + // following lines below parse and must not fail + x = if c { a } else { b }(); + x = if true { 1 } else { 0 } as *mut _; + // however this does not parse and probably should fail to retain compat? + // N.B., `..` here is arbitrary, failure happens/should happen ∀ops that aren’t `=` + // see assoc-oddities-2 and assoc-oddities-3 + ..if c { a } else { b }[n]; //~ ERROR expected one of +} diff --git a/tests/ui/parser/assoc-oddities-1.stderr b/tests/ui/parser/assoc-oddities-1.stderr new file mode 100644 index 000000000..acf71b489 --- /dev/null +++ b/tests/ui/parser/assoc-oddities-1.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, or `}`, found `[` + --> $DIR/assoc-oddities-1.rs:10:28 + | +LL | ..if c { a } else { b }[n]; + | ^ expected one of `.`, `;`, `?`, or `}` + +error: aborting due to previous error + diff --git a/tests/ui/parser/assoc-oddities-2.rs b/tests/ui/parser/assoc-oddities-2.rs new file mode 100644 index 000000000..3d35aad74 --- /dev/null +++ b/tests/ui/parser/assoc-oddities-2.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z parse-only + +fn main() { + // see assoc-oddities-1 for explanation + x..if c { a } else { b }[n]; //~ ERROR expected one of +} diff --git a/tests/ui/parser/assoc-oddities-2.stderr b/tests/ui/parser/assoc-oddities-2.stderr new file mode 100644 index 000000000..d3b90c34c --- /dev/null +++ b/tests/ui/parser/assoc-oddities-2.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, or `}`, found `[` + --> $DIR/assoc-oddities-2.rs:5:29 + | +LL | x..if c { a } else { b }[n]; + | ^ expected one of `.`, `;`, `?`, or `}` + +error: aborting due to previous error + diff --git a/tests/ui/parser/assoc-static-semantic-fail.rs b/tests/ui/parser/assoc-static-semantic-fail.rs new file mode 100644 index 000000000..a8759d209 --- /dev/null +++ b/tests/ui/parser/assoc-static-semantic-fail.rs @@ -0,0 +1,52 @@ +// Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item. + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +fn main() {} + +struct S; +impl S { + static IA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static IB: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body + default static IC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + //~| ERROR a static item cannot be `default` + pub(crate) default static ID: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body + //~| ERROR a static item cannot be `default` +} + +trait T { + static TA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static TB: u8; + //~^ ERROR associated `static` items are not allowed + default static TC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + //~| ERROR a static item cannot be `default` + pub(crate) default static TD: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR unnecessary visibility qualifier + //~| ERROR a static item cannot be `default` +} + +impl T for S { + static TA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static TB: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body + default static TC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + //~| ERROR a static item cannot be `default` + pub default static TD: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body + //~| ERROR unnecessary visibility qualifier + //~| ERROR a static item cannot be `default` +} diff --git a/tests/ui/parser/assoc-static-semantic-fail.stderr b/tests/ui/parser/assoc-static-semantic-fail.stderr new file mode 100644 index 000000000..8a74f49b9 --- /dev/null +++ b/tests/ui/parser/assoc-static-semantic-fail.stderr @@ -0,0 +1,177 @@ +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:10:5 + | +LL | static IA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:12:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:15:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:15:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:18:16 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:18:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:25:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:29:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:29:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:32:16 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:32:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:39:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:41:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:44:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:44:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:47:9 + | +LL | pub default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:47:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:12:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:18:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:32:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^ + +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:41:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:47:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:47:5 + | +LL | pub default static TD: u8; + | ^^^ `pub` not permitted here because it's implied + +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-static-semantic-fail.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 24 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/assoc-static-syntactic-fail.rs b/tests/ui/parser/assoc-static-syntactic-fail.rs new file mode 100644 index 000000000..492f2ea16 --- /dev/null +++ b/tests/ui/parser/assoc-static-syntactic-fail.rs @@ -0,0 +1,33 @@ +// Syntactically, we do allow e.g., `static X: u8 = 0;` as an associated item. + +fn main() {} + +#[cfg(FALSE)] +impl S { + static IA: u8 = 0; //~ ERROR associated `static` items are not allowed + static IB: u8; //~ ERROR associated `static` items are not allowed + default static IC: u8 = 0; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` + pub(crate) default static ID: u8; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` +} + +#[cfg(FALSE)] +trait T { + static TA: u8 = 0; //~ ERROR associated `static` items are not allowed + static TB: u8; //~ ERROR associated `static` items are not allowed + default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` + pub(crate) default static TD: u8; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` +} + +#[cfg(FALSE)] +impl T for S { + static TA: u8 = 0; //~ ERROR associated `static` items are not allowed + static TB: u8; //~ ERROR associated `static` items are not allowed + default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` + pub default static TD: u8; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` +} diff --git a/tests/ui/parser/assoc-static-syntactic-fail.stderr b/tests/ui/parser/assoc-static-syntactic-fail.stderr new file mode 100644 index 000000000..e97236145 --- /dev/null +++ b/tests/ui/parser/assoc-static-syntactic-fail.stderr @@ -0,0 +1,122 @@ +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:7:5 + | +LL | static IA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:8:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:9:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:9:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:11:16 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:11:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:17:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:18:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:19:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:19:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:21:16 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:21:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:27:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:28:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:29:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:29:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:31:9 + | +LL | pub default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:31:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors + diff --git a/tests/ui/parser/assoc-type-in-type-arg.rs b/tests/ui/parser/assoc-type-in-type-arg.rs new file mode 100644 index 000000000..000956ea2 --- /dev/null +++ b/tests/ui/parser/assoc-type-in-type-arg.rs @@ -0,0 +1,11 @@ +trait Tr { + type TrSubtype; +} + +struct Bar<'a, Item: Tr, ::TrSubtype: 'a> { + //~^ ERROR bounds on associated types do not belong here + item: Item, + item_sub: &'a ::TrSubtype, +} + +fn main() {} diff --git a/tests/ui/parser/assoc-type-in-type-arg.stderr b/tests/ui/parser/assoc-type-in-type-arg.stderr new file mode 100644 index 000000000..b637702f2 --- /dev/null +++ b/tests/ui/parser/assoc-type-in-type-arg.stderr @@ -0,0 +1,8 @@ +error: bounds on associated types do not belong here + --> $DIR/assoc-type-in-type-arg.rs:5:26 + | +LL | struct Bar<'a, Item: Tr, ::TrSubtype: 'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ belongs in `where` clause + +error: aborting due to previous error + diff --git a/tests/ui/parser/associated-types-project-from-hrtb-explicit.rs b/tests/ui/parser/associated-types-project-from-hrtb-explicit.rs new file mode 100644 index 000000000..b238a9ca2 --- /dev/null +++ b/tests/ui/parser/associated-types-project-from-hrtb-explicit.rs @@ -0,0 +1,16 @@ +// Test you can't use a higher-ranked trait bound inside of a qualified +// path (just won't parse). + +pub trait Foo { + type A; + + fn get(&self, t: T) -> Self::A; +} + +fn foo2(x: Foo<&'x isize>>::A) + //~^ ERROR expected identifier, found keyword `for` + //~| ERROR expected one of `::` or `>` +{ +} + +pub fn main() {} diff --git a/tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr b/tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr new file mode 100644 index 000000000..aa0fa0e3c --- /dev/null +++ b/tests/ui/parser/associated-types-project-from-hrtb-explicit.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `for` + --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:21 + | +LL | fn foo2(x: Foo<&'x isize>>::A) + | ^^^ expected identifier, found keyword + +error: expected one of `::` or `>`, found `Foo` + --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:29 + | +LL | fn foo2(x: Foo<&'x isize>>::A) + | ^^^ expected one of `::` or `>` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/attr-bad-meta-2.rs b/tests/ui/parser/attr-bad-meta-2.rs new file mode 100644 index 000000000..db612ed88 --- /dev/null +++ b/tests/ui/parser/attr-bad-meta-2.rs @@ -0,0 +1,2 @@ +#[path =] //~ ERROR expected expression, found `]` +mod m {} diff --git a/tests/ui/parser/attr-bad-meta-2.stderr b/tests/ui/parser/attr-bad-meta-2.stderr new file mode 100644 index 000000000..6fc6fb665 --- /dev/null +++ b/tests/ui/parser/attr-bad-meta-2.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `]` + --> $DIR/attr-bad-meta-2.rs:1:9 + | +LL | #[path =] + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr-bad-meta-3.rs b/tests/ui/parser/attr-bad-meta-3.rs new file mode 100644 index 000000000..b51e9f221 --- /dev/null +++ b/tests/ui/parser/attr-bad-meta-3.rs @@ -0,0 +1,2 @@ +#[path() token] //~ ERROR expected `]`, found `token` +mod m {} diff --git a/tests/ui/parser/attr-bad-meta-3.stderr b/tests/ui/parser/attr-bad-meta-3.stderr new file mode 100644 index 000000000..4fa420c79 --- /dev/null +++ b/tests/ui/parser/attr-bad-meta-3.stderr @@ -0,0 +1,8 @@ +error: expected `]`, found `token` + --> $DIR/attr-bad-meta-3.rs:1:10 + | +LL | #[path() token] + | ^^^^^ expected `]` + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr-bad-meta.rs b/tests/ui/parser/attr-bad-meta.rs new file mode 100644 index 000000000..8001977f5 --- /dev/null +++ b/tests/ui/parser/attr-bad-meta.rs @@ -0,0 +1,2 @@ +#[path*] //~ ERROR expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*` +mod m {} diff --git a/tests/ui/parser/attr-bad-meta.stderr b/tests/ui/parser/attr-bad-meta.stderr new file mode 100644 index 000000000..8d65c423c --- /dev/null +++ b/tests/ui/parser/attr-bad-meta.stderr @@ -0,0 +1,8 @@ +error: expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*` + --> $DIR/attr-bad-meta.rs:1:7 + | +LL | #[path*] + | ^ expected one of `(`, `::`, `=`, `[`, `]`, or `{` + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr-before-eof.rs b/tests/ui/parser/attr-before-eof.rs new file mode 100644 index 000000000..6af1783e6 --- /dev/null +++ b/tests/ui/parser/attr-before-eof.rs @@ -0,0 +1,3 @@ +fn main() {} + +#[derive(Debug)] //~ERROR expected item after attributes diff --git a/tests/ui/parser/attr-before-eof.stderr b/tests/ui/parser/attr-before-eof.stderr new file mode 100644 index 000000000..a2acb9437 --- /dev/null +++ b/tests/ui/parser/attr-before-eof.stderr @@ -0,0 +1,8 @@ +error: expected item after attributes + --> $DIR/attr-before-eof.rs:3:1 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr-dangling-in-fn.rs b/tests/ui/parser/attr-dangling-in-fn.rs new file mode 100644 index 000000000..c7c45bafb --- /dev/null +++ b/tests/ui/parser/attr-dangling-in-fn.rs @@ -0,0 +1,8 @@ +// error-pattern:expected statement + +fn f() { + #[foo = "bar"] +} + +fn main() { +} diff --git a/tests/ui/parser/attr-dangling-in-fn.stderr b/tests/ui/parser/attr-dangling-in-fn.stderr new file mode 100644 index 000000000..b1bb3ab3b --- /dev/null +++ b/tests/ui/parser/attr-dangling-in-fn.stderr @@ -0,0 +1,8 @@ +error: expected statement after outer attribute + --> $DIR/attr-dangling-in-fn.rs:4:3 + | +LL | #[foo = "bar"] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr-dangling-in-mod.rs b/tests/ui/parser/attr-dangling-in-mod.rs new file mode 100644 index 000000000..261ed3913 --- /dev/null +++ b/tests/ui/parser/attr-dangling-in-mod.rs @@ -0,0 +1,6 @@ +// error-pattern:expected item + +fn main() { +} + +#[foo = "bar"] diff --git a/tests/ui/parser/attr-dangling-in-mod.stderr b/tests/ui/parser/attr-dangling-in-mod.stderr new file mode 100644 index 000000000..1c892eac0 --- /dev/null +++ b/tests/ui/parser/attr-dangling-in-mod.stderr @@ -0,0 +1,8 @@ +error: expected item after attributes + --> $DIR/attr-dangling-in-mod.rs:6:1 + | +LL | #[foo = "bar"] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attr-stmt-expr-attr-bad.rs new file mode 100644 index 000000000..469c3855c --- /dev/null +++ b/tests/ui/parser/attr-stmt-expr-attr-bad.rs @@ -0,0 +1,109 @@ +fn main() {} + +#[cfg(FALSE)] fn e() { let _ = box #![attr] 0; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = [#[attr]]; } +//~^ ERROR expected expression, found `]` +#[cfg(FALSE)] fn e() { let _ = foo#[attr](); } +//~^ ERROR expected one of +#[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } +//~^ ERROR an inner attribute is not permitted in this context +//~| ERROR expected expression, found `)` +#[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } +//~^ ERROR an inner attribute is not permitted in this context +//~| ERROR expected expression, found `)` +#[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; } +//~^ ERROR expected one of +#[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; } +//~^ ERROR expected expression, found `..` +#[cfg(FALSE)] fn e() { let _ = #[attr] ..; } +//~^ ERROR expected expression, found `..` +#[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; } +//~^ ERROR expected one of +#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } +//~^ ERROR expected one of +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } +//~^ ERROR an inner attribute is not permitted in this context +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } +//~^ ERROR outer attributes are not allowed on `if` +#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } +//~^ ERROR an inner attribute is not permitted in this context + +#[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } +//~^ ERROR an inner attribute is not permitted following an outer attribute +#[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } +//~^ ERROR an inner attribute is not permitted following an outer attribute +#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } +//~^ ERROR an inner attribute is not permitted following an outer attribute +#[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } +//~^ ERROR an inner attribute is not permitted following an outer attribute +#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } +//~^ ERROR an inner attribute is not permitted following an outer attribute + +// FIXME: Allow attributes in pattern constexprs? +// note: requires parens in patterns to allow disambiguation + +#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } +//~^ ERROR inclusive range with no end +//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } +//~^ ERROR inclusive range with no end +//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +#[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } +//~^ ERROR unexpected token: `#` +#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } +//~^ ERROR inclusive range with no end +//~| ERROR expected one of `=>`, `if`, or `|`, found `#` + +#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } +//~^ ERROR unexpected token: `#` +//~| ERROR expected one of `.` +#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } +//~^ ERROR unexpected token: `#` +//~| ERROR expected one of `.` + +// make sure we don't catch this bug again... +#[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } +//~^ ERROR expected statement after outer attribute +#[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } +//~^ ERROR expected statement after outer attribute diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attr-stmt-expr-attr-bad.stderr new file mode 100644 index 000000000..872c560cb --- /dev/null +++ b/tests/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -0,0 +1,445 @@ +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:3:36 + | +LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected expression, found `]` + --> $DIR/attr-stmt-expr-attr-bad.rs:5:40 + | +LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; } + | ^ expected expression + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:7:35 + | +LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); } + | ^ expected one of 8 possible tokens + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:9:36 + | +LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected expression, found `)` + --> $DIR/attr-stmt-expr-attr-bad.rs:9:44 + | +LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } + | ^ expected expression + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:12:38 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected expression, found `)` + --> $DIR/attr-stmt-expr-attr-bad.rs:12:46 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } + | ^ expected expression + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:15:36 + | +LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:17:33 + | +LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:19:33 + | +LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:21:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; } + | ^ expected one of 8 possible tokens + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:23:35 + | +LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:25:40 + | +LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:27:35 + | +LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:29:40 + | +LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected expression, found `..` + --> $DIR/attr-stmt-expr-attr-bad.rs:31:40 + | +LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; } + | ^^ expected expression + +error: expected expression, found `..` + --> $DIR/attr-stmt-expr-attr-bad.rs:33:40 + | +LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; } + | ^^ expected expression + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:35:41 + | +LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:37:45 + | +LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:39:37 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } + | -- ^^^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `if` + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:41:38 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:43:40 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; } + | ^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:45:45 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } + | ---- ^^^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `else` + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:47:46 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:49:45 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } + | ---- ^^^^^^^ ------- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `else` + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:51:50 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } + | -- ^^^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `if` + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:53:51 + | +LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:55:45 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } + | -- ^^^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `if` + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:57:46 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:59:48 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } + | ^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:61:53 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } + | ---- ^^^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `else` + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:63:54 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:65:53 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } + | ---- ^^^^^^^ --------------- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `else` + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/attr-stmt-expr-attr-bad.rs:67:66 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } + | -- ^^^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `if` + +error: an inner attribute is not permitted in this context + --> $DIR/attr-stmt-expr-attr-bad.rs:69:67 + | +LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } + | ^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted following an outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:72:32 + | +LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } + | ------- ^^^^^^^^ not permitted following an outer attribute + | | + | previous outer attribute + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted following an outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:74:32 + | +LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } + | ------- ^^^^^^^^ not permitted following an outer attribute + | | + | previous outer attribute + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted following an outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:76:32 + | +LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } + | ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation + | | | + | | not permitted following an outer attribute + | previous outer attribute + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the item macro invocation, change the attribute from inner to outer style + | +LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } +LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); } + | + +error: an inner attribute is not permitted following an outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:78:32 + | +LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } + | ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation + | | | + | | not permitted following an outer attribute + | previous outer attribute + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the item macro invocation, change the attribute from inner to outer style + | +LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } +LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; } + | + +error: an inner attribute is not permitted following an outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 + | +LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } + | ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation + | | | + | | not permitted following an outer attribute + | previous outer attribute + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the item macro invocation, change the attribute from inner to outer style + | +LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } +LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; } + | + +error[E0586]: inclusive range with no end + --> $DIR/attr-stmt-expr-attr-bad.rs:86:35 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:86:38 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } + | ^ expected one of `=>`, `if`, or `|` + +error[E0586]: inclusive range with no end + --> $DIR/attr-stmt-expr-attr-bad.rs:89:35 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:89:38 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } + | ^ expected one of `=>`, `if`, or `|` + +error: unexpected token: `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:92:39 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } + | ^ + +error[E0586]: inclusive range with no end + --> $DIR/attr-stmt-expr-attr-bad.rs:94:35 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:94:38 + | +LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } + | ^ expected one of `=>`, `if`, or `|` + +error: unexpected token: `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:98:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } + | ^ + +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:98:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } + | ^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: unexpected token: `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:101:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } + | ^ + +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` + --> $DIR/attr-stmt-expr-attr-bad.rs:101:34 + | +LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } + | ^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: expected statement after outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:106:37 + | +LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } + | ^^^^^^^ + +error: expected statement after outer attribute + --> $DIR/attr-stmt-expr-attr-bad.rs:108:37 + | +LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } + | ^^^^^^^ + +error: aborting due to 53 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/parser/attr-with-a-semicolon.rs b/tests/ui/parser/attr-with-a-semicolon.rs new file mode 100644 index 000000000..56fe40b91 --- /dev/null +++ b/tests/ui/parser/attr-with-a-semicolon.rs @@ -0,0 +1,4 @@ +#[derive(Debug, Clone)]; //~ERROR expected item after attributes +struct Foo; + +fn main() {} diff --git a/tests/ui/parser/attr-with-a-semicolon.stderr b/tests/ui/parser/attr-with-a-semicolon.stderr new file mode 100644 index 000000000..0de3490b8 --- /dev/null +++ b/tests/ui/parser/attr-with-a-semicolon.stderr @@ -0,0 +1,14 @@ +error: expected item after attributes + --> $DIR/attr-with-a-semicolon.rs:1:1 + | +LL | #[derive(Debug, Clone)]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider removing this semicolon + | +LL - #[derive(Debug, Clone)]; +LL + #[derive(Debug, Clone)] + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/attr.rs b/tests/ui/parser/attr.rs new file mode 100644 index 000000000..42b2dfde8 --- /dev/null +++ b/tests/ui/parser/attr.rs @@ -0,0 +1,6 @@ +#![feature(lang_items)] + +fn main() {} + +#![lang = "foo"] //~ ERROR an inner attribute is not permitted in this context +fn foo() {} diff --git a/tests/ui/parser/attr.stderr b/tests/ui/parser/attr.stderr new file mode 100644 index 000000000..7cd0ac224 --- /dev/null +++ b/tests/ui/parser/attr.stderr @@ -0,0 +1,17 @@ +error: an inner attribute is not permitted in this context + --> $DIR/attr.rs:5:1 + | +LL | #![lang = "foo"] + | ^^^^^^^^^^^^^^^^ +LL | fn foo() {} + | ----------- the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the function, change the attribute from inner to outer style + | +LL - #![lang = "foo"] +LL + #[lang = "foo"] + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs b/tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs new file mode 100644 index 000000000..c2cc91d8f --- /dev/null +++ b/tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs @@ -0,0 +1,3 @@ +fn foo<#[attr]>() {} //~ ERROR attribute without generic parameters + +fn main() {} diff --git a/tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr b/tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr new file mode 100644 index 000000000..4c5964715 --- /dev/null +++ b/tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr @@ -0,0 +1,8 @@ +error: attribute without generic parameters + --> $DIR/attribute-with-no-generics-in-parameter-list.rs:1:8 + | +LL | fn foo<#[attr]>() {} + | ^^^^^^^ attributes are only permitted when preceding parameters + +error: aborting due to previous error + diff --git a/tests/ui/parser/attrs-after-extern-mod.rs b/tests/ui/parser/attrs-after-extern-mod.rs new file mode 100644 index 000000000..e3f0fa0fc --- /dev/null +++ b/tests/ui/parser/attrs-after-extern-mod.rs @@ -0,0 +1,7 @@ +// Make sure there's an error when given `extern { ... #[attr] }`. + +fn main() {} + +extern "C" { + #[cfg(stage37)] //~ ERROR expected item after attributes +} diff --git a/tests/ui/parser/attrs-after-extern-mod.stderr b/tests/ui/parser/attrs-after-extern-mod.stderr new file mode 100644 index 000000000..135d98457 --- /dev/null +++ b/tests/ui/parser/attrs-after-extern-mod.stderr @@ -0,0 +1,12 @@ +error: expected item after attributes + --> $DIR/attrs-after-extern-mod.rs:6:5 + | +LL | extern "C" { + | - while parsing this item list starting here +LL | #[cfg(stage37)] + | ^^^^^^^^^^^^^^^ +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-char-literals.rs b/tests/ui/parser/bad-char-literals.rs new file mode 100644 index 000000000..748b4a222 --- /dev/null +++ b/tests/ui/parser/bad-char-literals.rs @@ -0,0 +1,20 @@ +// ignore-tidy-cr +// ignore-tidy-tab + +fn main() { + // these literals are just silly. + '''; + //~^ ERROR: character constant must be escaped: `'` + + // note that this is a literal "\n" byte + ' +'; + //~^^ ERROR: character constant must be escaped: `\n` + + // note that this is a literal "\r" byte + ' '; //~ ERROR: character constant must be escaped: `\r` + + // note that this is a literal tab character here + ' '; + //~^ ERROR: character constant must be escaped: `\t` +} diff --git a/tests/ui/parser/bad-char-literals.stderr b/tests/ui/parser/bad-char-literals.stderr new file mode 100644 index 000000000..a22ddbac1 --- /dev/null +++ b/tests/ui/parser/bad-char-literals.stderr @@ -0,0 +1,28 @@ +error: character constant must be escaped: `'` + --> $DIR/bad-char-literals.rs:6:6 + | +LL | '''; + | ^ help: escape the character: `\'` + +error: character constant must be escaped: `\n` + --> $DIR/bad-char-literals.rs:10:6 + | +LL | ' + | ______^ +LL | | '; + | |_ help: escape the character: `\n` + +error: character constant must be escaped: `\r` + --> $DIR/bad-char-literals.rs:15:6 + | +LL | ' '; + | ^ help: escape the character: `\r` + +error: character constant must be escaped: `\t` + --> $DIR/bad-char-literals.rs:18:6 + | +LL | ' '; + | ^^^^ help: escape the character: `\t` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/bad-crate-name.rs b/tests/ui/parser/bad-crate-name.rs new file mode 100644 index 000000000..837d5c354 --- /dev/null +++ b/tests/ui/parser/bad-crate-name.rs @@ -0,0 +1,5 @@ +extern crate krate-name-here; +//~^ ERROR crate name using dashes are not valid in `extern crate` statements +//~| ERROR can't find crate for `krate_name_here` + +fn main() {} diff --git a/tests/ui/parser/bad-crate-name.stderr b/tests/ui/parser/bad-crate-name.stderr new file mode 100644 index 000000000..c98a620f1 --- /dev/null +++ b/tests/ui/parser/bad-crate-name.stderr @@ -0,0 +1,20 @@ +error: crate name using dashes are not valid in `extern crate` statements + --> $DIR/bad-crate-name.rs:1:14 + | +LL | extern crate krate-name-here; + | ^^^^^^^^^^^^^^^ dash-separated idents are not valid + | +help: if the original crate name uses dashes you need to use underscores in the code + | +LL | extern crate krate_name_here; + | ~ ~ + +error[E0463]: can't find crate for `krate_name_here` + --> $DIR/bad-crate-name.rs:1:1 + | +LL | extern crate krate-name-here; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/parser/bad-escape-suggest-raw-string.rs b/tests/ui/parser/bad-escape-suggest-raw-string.rs new file mode 100644 index 000000000..978b92cbc --- /dev/null +++ b/tests/ui/parser/bad-escape-suggest-raw-string.rs @@ -0,0 +1,7 @@ +fn main() { + let ok = r"ab\[c"; + let bad = "ab\[c"; + //~^ ERROR unknown character escape: `[` + //~| HELP for more information, visit + //~| HELP if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal +} diff --git a/tests/ui/parser/bad-escape-suggest-raw-string.stderr b/tests/ui/parser/bad-escape-suggest-raw-string.stderr new file mode 100644 index 000000000..fc34bd328 --- /dev/null +++ b/tests/ui/parser/bad-escape-suggest-raw-string.stderr @@ -0,0 +1,14 @@ +error: unknown character escape: `[` + --> $DIR/bad-escape-suggest-raw-string.rs:3:19 + | +LL | let bad = "ab\[c"; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL | let bad = r"ab\[c"; + | ~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.fixed b/tests/ui/parser/bad-fn-ptr-qualifier.fixed new file mode 100644 index 000000000..ad8e718cf --- /dev/null +++ b/tests/ui/parser/bad-fn-ptr-qualifier.fixed @@ -0,0 +1,26 @@ +// run-rustfix +// edition:2018 +// Most of items are taken from ./recover-const-async-fn-ptr.rs but this is able to apply rustfix. + +pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T2 = unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T4 = extern fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T6 = unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `const` +//~| ERROR an `fn` pointer type cannot be `async` + +pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT2 = for<'a> unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT4 = for<'a> extern fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT5 = for<'a> unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `async` +pub type FTT6 = for<'a> unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `const` +//~| ERROR an `fn` pointer type cannot be `async` + +fn main() {} diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.rs b/tests/ui/parser/bad-fn-ptr-qualifier.rs new file mode 100644 index 000000000..c04813dad --- /dev/null +++ b/tests/ui/parser/bad-fn-ptr-qualifier.rs @@ -0,0 +1,26 @@ +// run-rustfix +// edition:2018 +// Most of items are taken from ./recover-const-async-fn-ptr.rs but this is able to apply rustfix. + +pub type T0 = const fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T1 = const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T2 = const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T3 = async fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T4 = async extern fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T5 = async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T6 = const async unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `const` +//~| ERROR an `fn` pointer type cannot be `async` + +pub type FTT0 = for<'a> const fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT1 = for<'a> const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT2 = for<'a> const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT3 = for<'a> async fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT4 = for<'a> async extern fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT5 = for<'a> async unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `async` +pub type FTT6 = for<'a> const async unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `const` +//~| ERROR an `fn` pointer type cannot be `async` + +fn main() {} diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.stderr b/tests/ui/parser/bad-fn-ptr-qualifier.stderr new file mode 100644 index 000000000..265e31329 --- /dev/null +++ b/tests/ui/parser/bad-fn-ptr-qualifier.stderr @@ -0,0 +1,146 @@ +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:5:15 + | +LL | pub type T0 = const fn(); + | -----^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:6:15 + | +LL | pub type T1 = const extern "C" fn(); + | -----^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:7:15 + | +LL | pub type T2 = const unsafe extern fn(); + | -----^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:8:15 + | +LL | pub type T3 = async fn(); + | -----^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:9:15 + | +LL | pub type T4 = async extern fn(); + | -----^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:10:15 + | +LL | pub type T5 = async unsafe extern "C" fn(); + | -----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:11:15 + | +LL | pub type T6 = const async unsafe extern "C" fn(); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:11:15 + | +LL | pub type T6 = const async unsafe extern "C" fn(); + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:15:17 + | +LL | pub type FTT0 = for<'a> const fn(); + | ^^^^^^^^-----^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:16:17 + | +LL | pub type FTT1 = for<'a> const extern "C" fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:17:17 + | +LL | pub type FTT2 = for<'a> const unsafe extern fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:18:17 + | +LL | pub type FTT3 = for<'a> async fn(); + | ^^^^^^^^-----^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:19:17 + | +LL | pub type FTT4 = for<'a> async extern fn(); + | ^^^^^^^^-----^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:20:17 + | +LL | pub type FTT5 = for<'a> async unsafe extern "C" fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/bad-fn-ptr-qualifier.rs:22:17 + | +LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/bad-fn-ptr-qualifier.rs:22:17 + | +LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn(); + | ^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: aborting due to 16 previous errors + diff --git a/tests/ui/parser/bad-if-statements.rs b/tests/ui/parser/bad-if-statements.rs new file mode 100644 index 000000000..2c501e3a5 --- /dev/null +++ b/tests/ui/parser/bad-if-statements.rs @@ -0,0 +1,38 @@ +fn a() { + if {} + //~^ ERROR missing condition for `if` expression +} + +fn b() { + if true && {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn c() { + let x = {}; + if true x + //~^ ERROR expected `{`, found `x` +} + +fn a2() { + if {} else {} + //~^ ERROR missing condition for `if` expression +} + +fn b2() { + if true && {} else {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn c2() { + let x = {}; + if true x else {} + //~^ ERROR expected `{`, found `x` +} + +fn d() { + if true else {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn main() {} diff --git a/tests/ui/parser/bad-if-statements.stderr b/tests/ui/parser/bad-if-statements.stderr new file mode 100644 index 000000000..ee839db64 --- /dev/null +++ b/tests/ui/parser/bad-if-statements.stderr @@ -0,0 +1,86 @@ +error: missing condition for `if` expression + --> $DIR/bad-if-statements.rs:2:7 + | +LL | if {} + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:7:5 + | +LL | if true && {} + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/bad-if-statements.rs:7:8 + | +LL | if true && {} + | ^^^^^^^ + +error: expected `{`, found `x` + --> $DIR/bad-if-statements.rs:13:13 + | +LL | if true x + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/bad-if-statements.rs:13:8 + | +LL | if true x + | ^^^^ +help: try placing this code inside a block + | +LL | if true { x } + | + + + +error: missing condition for `if` expression + --> $DIR/bad-if-statements.rs:18:7 + | +LL | if {} else {} + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:23:5 + | +LL | if true && {} else {} + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/bad-if-statements.rs:23:8 + | +LL | if true && {} else {} + | ^^^^^^^ + +error: expected `{`, found `x` + --> $DIR/bad-if-statements.rs:29:13 + | +LL | if true x else {} + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/bad-if-statements.rs:29:8 + | +LL | if true x else {} + | ^^^^ +help: try placing this code inside a block + | +LL | if true { x } else {} + | + + + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:34:5 + | +LL | if true else {} + | ^^ + | +help: add a block here + --> $DIR/bad-if-statements.rs:34:12 + | +LL | if true else {} + | ^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/parser/bad-interpolated-block.rs b/tests/ui/parser/bad-interpolated-block.rs new file mode 100644 index 000000000..c6d7ae383 --- /dev/null +++ b/tests/ui/parser/bad-interpolated-block.rs @@ -0,0 +1,13 @@ +fn main() {} + +macro_rules! m { + ($b:block) => { + 'lab: $b; //~ ERROR cannot use a `block` macro fragment here + unsafe $b; //~ ERROR cannot use a `block` macro fragment here + |x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here + } +} + +fn foo() { + m!({}); +} diff --git a/tests/ui/parser/bad-interpolated-block.stderr b/tests/ui/parser/bad-interpolated-block.stderr new file mode 100644 index 000000000..2a0999afd --- /dev/null +++ b/tests/ui/parser/bad-interpolated-block.stderr @@ -0,0 +1,39 @@ +error: cannot use a `block` macro fragment here + --> $DIR/bad-interpolated-block.rs:5:15 + | +LL | 'lab: $b; + | ------^^ + | | + | the `block` fragment is within this context +... +LL | m!({}); + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot use a `block` macro fragment here + --> $DIR/bad-interpolated-block.rs:6:16 + | +LL | unsafe $b; + | -------^^ + | | + | the `block` fragment is within this context +... +LL | m!({}); + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot use a `block` macro fragment here + --> $DIR/bad-interpolated-block.rs:7:23 + | +LL | |x: u8| -> () $b; + | ^^ the `block` fragment is within this context +... +LL | m!({}); + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/bad-let-as-field.rs b/tests/ui/parser/bad-let-as-field.rs new file mode 100644 index 000000000..fec2bc256 --- /dev/null +++ b/tests/ui/parser/bad-let-as-field.rs @@ -0,0 +1,6 @@ +struct Foo { + let: i32, + //~^ ERROR expected identifier, found keyword +} + +fn main() {} diff --git a/tests/ui/parser/bad-let-as-field.stderr b/tests/ui/parser/bad-let-as-field.stderr new file mode 100644 index 000000000..57def42b1 --- /dev/null +++ b/tests/ui/parser/bad-let-as-field.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found keyword `let` + --> $DIR/bad-let-as-field.rs:2:5 + | +LL | struct Foo { + | --- while parsing this struct +LL | let: i32, + | ^^^ expected identifier, found keyword + | +help: escape `let` to use it as an identifier + | +LL | r#let: i32, + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-lit-suffixes.rs b/tests/ui/parser/bad-lit-suffixes.rs new file mode 100644 index 000000000..8cb9ef7e0 --- /dev/null +++ b/tests/ui/parser/bad-lit-suffixes.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] + +extern + "C"suffix //~ ERROR suffixes on string literals are invalid + fn foo() {} + +extern + "C"suffix //~ ERROR suffixes on string literals are invalid +{} + +fn main() { + ""suffix; //~ ERROR suffixes on string literals are invalid + b""suffix; //~ ERROR suffixes on byte string literals are invalid + r#""#suffix; //~ ERROR suffixes on string literals are invalid + br#""#suffix; //~ ERROR suffixes on byte string literals are invalid + 'a'suffix; //~ ERROR suffixes on char literals are invalid + b'a'suffix; //~ ERROR suffixes on byte literals are invalid + + 1234u1024; //~ ERROR invalid width `1024` for integer literal + 1234i1024; //~ ERROR invalid width `1024` for integer literal + 1234f1024; //~ ERROR invalid width `1024` for float literal + 1234.5f1024; //~ ERROR invalid width `1024` for float literal + + 1234suffix; //~ ERROR invalid suffix `suffix` for number literal + 0b101suffix; //~ ERROR invalid suffix `suffix` for number literal + 1.0suffix; //~ ERROR invalid suffix `suffix` for float literal + 1.0e10suffix; //~ ERROR invalid suffix `suffix` for float literal +} + +#[rustc_dummy = "string"suffix] +//~^ ERROR unexpected expression: `"string"suffix` +fn f() {} + +#[must_use = "string"suffix] +//~^ ERROR unexpected expression: `"string"suffix` +fn g() {} + +#[link(name = "string"suffix)] +//~^ ERROR suffixes on string literals are invalid +extern "C" {} + +#[rustc_layout_scalar_valid_range_start(0suffix)] +//~^ ERROR invalid suffix `suffix` for number literal +struct S; diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr new file mode 100644 index 000000000..756f99ab1 --- /dev/null +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -0,0 +1,140 @@ +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:4:5 + | +LL | "C"suffix + | ^^^^^^^^^ invalid suffix `suffix` + +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:8:5 + | +LL | "C"suffix + | ^^^^^^^^^ invalid suffix `suffix` + +error: unexpected expression: `"string"suffix` + --> $DIR/bad-lit-suffixes.rs:30:17 + | +LL | #[rustc_dummy = "string"suffix] + | ^^^^^^^^^^^^^^ + +error: unexpected expression: `"string"suffix` + --> $DIR/bad-lit-suffixes.rs:34:14 + | +LL | #[must_use = "string"suffix] + | ^^^^^^^^^^^^^^ + +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:38:15 + | +LL | #[link(name = "string"suffix)] + | ^^^^^^^^^^^^^^ invalid suffix `suffix` + +error: invalid suffix `suffix` for number literal + --> $DIR/bad-lit-suffixes.rs:42:41 + | +LL | #[rustc_layout_scalar_valid_range_start(0suffix)] + | ^^^^^^^ invalid suffix `suffix` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:12:5 + | +LL | ""suffix; + | ^^^^^^^^ invalid suffix `suffix` + +error: suffixes on byte string literals are invalid + --> $DIR/bad-lit-suffixes.rs:13:5 + | +LL | b""suffix; + | ^^^^^^^^^ invalid suffix `suffix` + +error: suffixes on string literals are invalid + --> $DIR/bad-lit-suffixes.rs:14:5 + | +LL | r#""#suffix; + | ^^^^^^^^^^^ invalid suffix `suffix` + +error: suffixes on byte string literals are invalid + --> $DIR/bad-lit-suffixes.rs:15:5 + | +LL | br#""#suffix; + | ^^^^^^^^^^^^ invalid suffix `suffix` + +error: suffixes on char literals are invalid + --> $DIR/bad-lit-suffixes.rs:16:5 + | +LL | 'a'suffix; + | ^^^^^^^^^ invalid suffix `suffix` + +error: suffixes on byte literals are invalid + --> $DIR/bad-lit-suffixes.rs:17:5 + | +LL | b'a'suffix; + | ^^^^^^^^^^ invalid suffix `suffix` + +error: invalid width `1024` for integer literal + --> $DIR/bad-lit-suffixes.rs:19:5 + | +LL | 1234u1024; + | ^^^^^^^^^ + | + = help: valid widths are 8, 16, 32, 64 and 128 + +error: invalid width `1024` for integer literal + --> $DIR/bad-lit-suffixes.rs:20:5 + | +LL | 1234i1024; + | ^^^^^^^^^ + | + = help: valid widths are 8, 16, 32, 64 and 128 + +error: invalid width `1024` for float literal + --> $DIR/bad-lit-suffixes.rs:21:5 + | +LL | 1234f1024; + | ^^^^^^^^^ + | + = help: valid widths are 32 and 64 + +error: invalid width `1024` for float literal + --> $DIR/bad-lit-suffixes.rs:22:5 + | +LL | 1234.5f1024; + | ^^^^^^^^^^^ + | + = help: valid widths are 32 and 64 + +error: invalid suffix `suffix` for number literal + --> $DIR/bad-lit-suffixes.rs:24:5 + | +LL | 1234suffix; + | ^^^^^^^^^^ invalid suffix `suffix` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `suffix` for number literal + --> $DIR/bad-lit-suffixes.rs:25:5 + | +LL | 0b101suffix; + | ^^^^^^^^^^^ invalid suffix `suffix` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `suffix` for float literal + --> $DIR/bad-lit-suffixes.rs:26:5 + | +LL | 1.0suffix; + | ^^^^^^^^^ invalid suffix `suffix` + | + = help: valid suffixes are `f32` and `f64` + +error: invalid suffix `suffix` for float literal + --> $DIR/bad-lit-suffixes.rs:27:5 + | +LL | 1.0e10suffix; + | ^^^^^^^^^^^^ invalid suffix `suffix` + | + = help: valid suffixes are `f32` and `f64` + +error: aborting due to 20 previous errors + diff --git a/tests/ui/parser/bad-match.rs b/tests/ui/parser/bad-match.rs new file mode 100644 index 000000000..04100d170 --- /dev/null +++ b/tests/ui/parser/bad-match.rs @@ -0,0 +1,4 @@ +fn main() { + let isize x = 5; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `x` + match x; +} diff --git a/tests/ui/parser/bad-match.stderr b/tests/ui/parser/bad-match.stderr new file mode 100644 index 000000000..13784c409 --- /dev/null +++ b/tests/ui/parser/bad-match.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `x` + --> $DIR/bad-match.rs:2:13 + | +LL | let isize x = 5; + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-name.rs b/tests/ui/parser/bad-name.rs new file mode 100644 index 000000000..9b4271692 --- /dev/null +++ b/tests/ui/parser/bad-name.rs @@ -0,0 +1,5 @@ +// error-pattern: expected + +fn main() { + let x.y::.z foo; +} diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr new file mode 100644 index 000000000..a36b67794 --- /dev/null +++ b/tests/ui/parser/bad-name.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.` + --> $DIR/bad-name.rs:4:8 + | +LL | let x.y::.z foo; + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-pointer-type.rs b/tests/ui/parser/bad-pointer-type.rs new file mode 100644 index 000000000..6a82acb4c --- /dev/null +++ b/tests/ui/parser/bad-pointer-type.rs @@ -0,0 +1,5 @@ +fn foo(_: *()) { + //~^ ERROR expected `mut` or `const` keyword in raw pointer type +} + +fn main() {} diff --git a/tests/ui/parser/bad-pointer-type.stderr b/tests/ui/parser/bad-pointer-type.stderr new file mode 100644 index 000000000..b7225ca88 --- /dev/null +++ b/tests/ui/parser/bad-pointer-type.stderr @@ -0,0 +1,15 @@ +error: expected `mut` or `const` keyword in raw pointer type + --> $DIR/bad-pointer-type.rs:1:11 + | +LL | fn foo(_: *()) { + | ^ + | +help: add `mut` or `const` here + | +LL | fn foo(_: *const ()) { + | +++++ +LL | fn foo(_: *mut ()) { + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs new file mode 100644 index 000000000..218cd7678 --- /dev/null +++ b/tests/ui/parser/bad-recover-kw-after-impl.rs @@ -0,0 +1,15 @@ +// check-pass + +// edition:2021 +// for the `impl` + keyword test + +macro_rules! impl_primitive { + ($ty:ty) => { + compile_error!("whoops"); + }; + (impl async) => {}; +} + +impl_primitive!(impl async); + +fn main() {} diff --git a/tests/ui/parser/bad-recover-ty-after-impl.rs b/tests/ui/parser/bad-recover-ty-after-impl.rs new file mode 100644 index 000000000..510e08ba0 --- /dev/null +++ b/tests/ui/parser/bad-recover-ty-after-impl.rs @@ -0,0 +1,17 @@ +// check-pass + +macro_rules! impl_primitive { + ($ty:ty) => { impl_primitive!(impl $ty); }; + (impl $ty:ty) => { fn a(_: $ty) {} } +} + +impl_primitive! { u8 } + +macro_rules! test { + ($ty:ty) => { compile_error!("oh no"); }; + (impl &) => {}; +} + +test!(impl &); + +fn main() {} diff --git a/tests/ui/parser/bad-struct-following-where.rs b/tests/ui/parser/bad-struct-following-where.rs new file mode 100644 index 000000000..823880b1b --- /dev/null +++ b/tests/ui/parser/bad-struct-following-where.rs @@ -0,0 +1,2 @@ +struct A where T: Sized ! +//~^ ERROR expected `{` after struct name, found diff --git a/tests/ui/parser/bad-struct-following-where.stderr b/tests/ui/parser/bad-struct-following-where.stderr new file mode 100644 index 000000000..bb79776dc --- /dev/null +++ b/tests/ui/parser/bad-struct-following-where.stderr @@ -0,0 +1,8 @@ +error: expected `{` after struct name, found `!` + --> $DIR/bad-struct-following-where.rs:1:25 + | +LL | struct A where T: Sized ! + | ^ expected `{` after struct name + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-value-ident-false.rs b/tests/ui/parser/bad-value-ident-false.rs new file mode 100644 index 000000000..4645ab4a7 --- /dev/null +++ b/tests/ui/parser/bad-value-ident-false.rs @@ -0,0 +1,2 @@ +fn false() { } //~ ERROR expected identifier, found keyword `false` +fn main() { } diff --git a/tests/ui/parser/bad-value-ident-false.stderr b/tests/ui/parser/bad-value-ident-false.stderr new file mode 100644 index 000000000..30c05ecf3 --- /dev/null +++ b/tests/ui/parser/bad-value-ident-false.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `false` + --> $DIR/bad-value-ident-false.rs:1:4 + | +LL | fn false() { } + | ^^^^^ expected identifier, found keyword + | +help: escape `false` to use it as an identifier + | +LL | fn r#false() { } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/bad-value-ident-true.rs b/tests/ui/parser/bad-value-ident-true.rs new file mode 100644 index 000000000..0f64266d3 --- /dev/null +++ b/tests/ui/parser/bad-value-ident-true.rs @@ -0,0 +1,2 @@ +fn true() { } //~ ERROR expected identifier, found keyword `true` +fn main() { } diff --git a/tests/ui/parser/bad-value-ident-true.stderr b/tests/ui/parser/bad-value-ident-true.stderr new file mode 100644 index 000000000..74137fa70 --- /dev/null +++ b/tests/ui/parser/bad-value-ident-true.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `true` + --> $DIR/bad-value-ident-true.rs:1:4 + | +LL | fn true() { } + | ^^^^ expected identifier, found keyword + | +help: escape `true` to use it as an identifier + | +LL | fn r#true() { } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/bare-struct-body.rs b/tests/ui/parser/bare-struct-body.rs new file mode 100644 index 000000000..a557e861d --- /dev/null +++ b/tests/ui/parser/bare-struct-body.rs @@ -0,0 +1,15 @@ +struct Foo { + val: (), +} + +fn foo() -> Foo { //~ ERROR struct literal body without path + val: (), +} + +fn main() { + let x = foo(); + x.val == 42; //~ ERROR mismatched types + let x = { //~ ERROR struct literal body without path + val: (), + }; +} diff --git a/tests/ui/parser/bare-struct-body.stderr b/tests/ui/parser/bare-struct-body.stderr new file mode 100644 index 000000000..7d17ea596 --- /dev/null +++ b/tests/ui/parser/bare-struct-body.stderr @@ -0,0 +1,43 @@ +error: struct literal body without path + --> $DIR/bare-struct-body.rs:5:17 + | +LL | fn foo() -> Foo { + | _________________^ +LL | | val: (), +LL | | } + | |_^ + | +help: you might have forgotten to add the struct literal inside the block + | +LL ~ fn foo() -> Foo { SomeStruct { +LL | val: (), +LL ~ } } + | + +error: struct literal body without path + --> $DIR/bare-struct-body.rs:12:13 + | +LL | let x = { + | _____________^ +LL | | val: (), +LL | | }; + | |_____^ + | +help: you might have forgotten to add the struct literal inside the block + | +LL ~ let x = { SomeStruct { +LL | val: (), +LL ~ } }; + | + +error[E0308]: mismatched types + --> $DIR/bare-struct-body.rs:11:14 + | +LL | x.val == 42; + | ----- ^^ expected `()`, found integer + | | + | expected because this is `()` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/bastion-of-the-turbofish.rs b/tests/ui/parser/bastion-of-the-turbofish.rs new file mode 100644 index 000000000..e12857008 --- /dev/null +++ b/tests/ui/parser/bastion-of-the-turbofish.rs @@ -0,0 +1,43 @@ +// check-pass + +// Bastion of the Turbofish +// ------------------------ +// Beware travellers, lest you venture into waters callous and unforgiving, +// where hope must be abandoned, ere it is cruelly torn from you. For here +// stands the bastion of the Turbofish: an impenetrable fortress holding +// unshaking against those who would dare suggest the supererogation of the +// Turbofish. +// +// Once I was young and foolish and had the impudence to imagine that I could +// shake free from the coils by which that creature had us tightly bound. I +// dared to suggest that there was a better way: a brighter future, in which +// Rustaceans both new and old could be rid of that vile beast. But alas! In +// my foolhardiness my ignorance was unveiled and my dreams were dashed +// unforgivingly against the rock of syntactic ambiguity. +// +// This humble program, small and insignificant though it might seem, +// demonstrates that to which we had previously cast a blind eye: an ambiguity +// in permitting generic arguments to be provided without the consent of the +// Great Turbofish. Should you be so naïve as to try to revolt against its +// mighty clutches, here shall its wrath be indomitably displayed. This +// program must pass for all eternity: forever watched by the guardian angel +// which gave this beast its name, and stands fundamentally at odds with the +// impetuous rebellion against the Turbofish. +// +// My heart aches in sorrow, for I know I am defeated. Let this be a warning +// to all those who come after: for they too must overcome the impassible +// hurdle of defeating the great beast, championed by a resolute winged +// guardian. +// +// Here stands the Bastion of the Turbofish, a memorial to Anna Harren, +// Guardian Angel of these Hallowed Grounds. <3 + +// See https://github.com/rust-lang/rust/pull/53562 +// and https://github.com/rust-lang/rfcs/pull/2527 +// and https://twitter.com/garblefart/status/1393236602856611843 +// for context. + +fn main() { + let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated"); + let _: (bool, bool) = (the(resolute)); +} diff --git a/tests/ui/parser/better-expected.rs b/tests/ui/parser/better-expected.rs new file mode 100644 index 000000000..16b61caa4 --- /dev/null +++ b/tests/ui/parser/better-expected.rs @@ -0,0 +1,3 @@ +fn main() { + let x: [isize 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` +} diff --git a/tests/ui/parser/better-expected.stderr b/tests/ui/parser/better-expected.stderr new file mode 100644 index 000000000..21bf8d19a --- /dev/null +++ b/tests/ui/parser/better-expected.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `3` + --> $DIR/better-expected.rs:2:19 + | +LL | let x: [isize 3]; + | - ^ expected one of 7 possible tokens + | | + | while parsing the type for `x` + +error: aborting due to previous error + diff --git a/tests/ui/parser/bind-struct-early-modifiers.rs b/tests/ui/parser/bind-struct-early-modifiers.rs new file mode 100644 index 000000000..c4b1937de --- /dev/null +++ b/tests/ui/parser/bind-struct-early-modifiers.rs @@ -0,0 +1,7 @@ +fn main() { + struct Foo { x: isize } + match (Foo { x: 10 }) { + Foo { ref x: ref x } => {}, //~ ERROR expected `,` + _ => {} + } +} diff --git a/tests/ui/parser/bind-struct-early-modifiers.stderr b/tests/ui/parser/bind-struct-early-modifiers.stderr new file mode 100644 index 000000000..b35762a88 --- /dev/null +++ b/tests/ui/parser/bind-struct-early-modifiers.stderr @@ -0,0 +1,10 @@ +error: expected `,` + --> $DIR/bind-struct-early-modifiers.rs:4:20 + | +LL | Foo { ref x: ref x } => {}, + | --- ^ + | | + | while parsing the fields for this pattern + +error: aborting due to previous error + diff --git a/tests/ui/parser/block-no-opening-brace.rs b/tests/ui/parser/block-no-opening-brace.rs new file mode 100644 index 000000000..8a6599488 --- /dev/null +++ b/tests/ui/parser/block-no-opening-brace.rs @@ -0,0 +1,31 @@ +// edition:2018 + +#![feature(try_blocks)] + +fn main() {} + +fn f1() { + loop + let x = 0; //~ ERROR expected `{`, found keyword `let` + drop(0); + } + +fn f2() { + while true + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f3() { + for x in 0..1 + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f4() { + try //~ ERROR expected expression, found reserved keyword `try` + let x = 0; + } + +fn f5() { + async + let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let` + } diff --git a/tests/ui/parser/block-no-opening-brace.stderr b/tests/ui/parser/block-no-opening-brace.stderr new file mode 100644 index 000000000..f232f480c --- /dev/null +++ b/tests/ui/parser/block-no-opening-brace.stderr @@ -0,0 +1,55 @@ +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:9:9 + | +LL | loop + | ---- while parsing this `loop` expression +LL | let x = 0; + | ^^^ expected `{` + | +help: try placing this code inside a block + | +LL | { let x = 0; } + | + + + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:15:9 + | +LL | while true + | ----- ---- this `while` condition successfully parsed + | | + | while parsing the body of this `while` expression +LL | let x = 0; + | ^^^ expected `{` + | +help: try placing this code inside a block + | +LL | { let x = 0; } + | + + + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:20:9 + | +LL | let x = 0; + | ^^^ expected `{` + | +help: try placing this code inside a block + | +LL | { let x = 0; } + | + + + +error: expected expression, found reserved keyword `try` + --> $DIR/block-no-opening-brace.rs:24:5 + | +LL | try + | ^^^ expected expression + +error: expected one of `move`, `|`, or `||`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:30:9 + | +LL | async + | - expected one of `move`, `|`, or `||` +LL | let x = 0; + | ^^^ unexpected token + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/bound-single-question-mark.rs b/tests/ui/parser/bound-single-question-mark.rs new file mode 100644 index 000000000..64d702d14 --- /dev/null +++ b/tests/ui/parser/bound-single-question-mark.rs @@ -0,0 +1 @@ +fn f() {} //~ ERROR expected identifier, found `>` diff --git a/tests/ui/parser/bound-single-question-mark.stderr b/tests/ui/parser/bound-single-question-mark.stderr new file mode 100644 index 000000000..82937a517 --- /dev/null +++ b/tests/ui/parser/bound-single-question-mark.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `>` + --> $DIR/bound-single-question-mark.rs:1:10 + | +LL | fn f() {} + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-lifetime-1.rs b/tests/ui/parser/bounds-lifetime-1.rs new file mode 100644 index 000000000..e458f644c --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-1.rs @@ -0,0 +1,3 @@ +type A = for<'a 'b> fn(); //~ ERROR expected one of `,`, `:`, or `>`, found `'b` + +fn main() {} diff --git a/tests/ui/parser/bounds-lifetime-1.stderr b/tests/ui/parser/bounds-lifetime-1.stderr new file mode 100644 index 000000000..000e84f63 --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-1.stderr @@ -0,0 +1,8 @@ +error: expected one of `,`, `:`, or `>`, found `'b` + --> $DIR/bounds-lifetime-1.rs:1:17 + | +LL | type A = for<'a 'b> fn(); + | ^^ expected one of `,`, `:`, or `>` + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-lifetime-2.rs b/tests/ui/parser/bounds-lifetime-2.rs new file mode 100644 index 000000000..f184107bb --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-2.rs @@ -0,0 +1,3 @@ +type A = for<'a + 'b> fn(); //~ ERROR expected one of `,`, `:`, or `>`, found `+` + +fn main() {} diff --git a/tests/ui/parser/bounds-lifetime-2.stderr b/tests/ui/parser/bounds-lifetime-2.stderr new file mode 100644 index 000000000..dd3e69c11 --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-2.stderr @@ -0,0 +1,8 @@ +error: expected one of `,`, `:`, or `>`, found `+` + --> $DIR/bounds-lifetime-2.rs:1:17 + | +LL | type A = for<'a + 'b> fn(); + | ^ expected one of `,`, `:`, or `>` + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-lifetime-where-1.rs b/tests/ui/parser/bounds-lifetime-where-1.rs new file mode 100644 index 000000000..f1a002a9f --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-where-1.rs @@ -0,0 +1,3 @@ +type A where 'a; //~ ERROR expected `:`, found `;` + +fn main() {} diff --git a/tests/ui/parser/bounds-lifetime-where-1.stderr b/tests/ui/parser/bounds-lifetime-where-1.stderr new file mode 100644 index 000000000..b6bd86693 --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-where-1.stderr @@ -0,0 +1,8 @@ +error: expected `:`, found `;` + --> $DIR/bounds-lifetime-where-1.rs:1:16 + | +LL | type A where 'a; + | ^ expected `:` + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-lifetime-where.rs b/tests/ui/parser/bounds-lifetime-where.rs new file mode 100644 index 000000000..7ff75233d --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-where.rs @@ -0,0 +1,10 @@ +type A where 'a: 'b + 'c = u8; // OK +type A where 'a: 'b, = u8; // OK +type A where 'a: = u8; // OK +type A where 'a:, = u8; // OK +type A where 'a: 'b + 'c = u8; // OK +type A where = u8; // OK +type A where 'a: 'b + = u8; // OK +type A where , = u8; //~ ERROR expected one of `;`, `=`, `where`, lifetime, or type, found `,` + +fn main() {} diff --git a/tests/ui/parser/bounds-lifetime-where.stderr b/tests/ui/parser/bounds-lifetime-where.stderr new file mode 100644 index 000000000..785a1fb67 --- /dev/null +++ b/tests/ui/parser/bounds-lifetime-where.stderr @@ -0,0 +1,8 @@ +error: expected one of `;`, `=`, `where`, lifetime, or type, found `,` + --> $DIR/bounds-lifetime-where.rs:8:14 + | +LL | type A where , = u8; + | ^ expected one of `;`, `=`, `where`, lifetime, or type + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-lifetime.rs b/tests/ui/parser/bounds-lifetime.rs new file mode 100644 index 000000000..c9251ac53 --- /dev/null +++ b/tests/ui/parser/bounds-lifetime.rs @@ -0,0 +1,11 @@ +type A = for<'a:> fn(); // OK +type A = for<'a:,> fn(); // OK +type A = for<'a> fn(); // OK +type A = for<> fn(); // OK +type A = for<'a: 'b + 'c> fn(); // OK (rejected later by ast_validation) +type A = for<'a: 'b,> fn(); // OK(rejected later by ast_validation) +type A = for<'a: 'b +> fn(); // OK (rejected later by ast_validation) +type A = for<'a, T> fn(); // OK (rejected later by ast_validation) +type A = for<,> fn(); //~ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime + +fn main() {} diff --git a/tests/ui/parser/bounds-lifetime.stderr b/tests/ui/parser/bounds-lifetime.stderr new file mode 100644 index 000000000..e47a21d89 --- /dev/null +++ b/tests/ui/parser/bounds-lifetime.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + --> $DIR/bounds-lifetime.rs:9:14 + | +LL | type A = for<,> fn(); + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-obj-parens.rs b/tests/ui/parser/bounds-obj-parens.rs new file mode 100644 index 000000000..8c446d27d --- /dev/null +++ b/tests/ui/parser/bounds-obj-parens.rs @@ -0,0 +1,7 @@ +// check-pass + +#![allow(bare_trait_objects)] + +type A = Box<(Fn(u8) -> u8) + 'static + Send + Sync>; // OK (but see #39318) + +fn main() {} diff --git a/tests/ui/parser/bounds-type-where.rs b/tests/ui/parser/bounds-type-where.rs new file mode 100644 index 000000000..2520ecb29 --- /dev/null +++ b/tests/ui/parser/bounds-type-where.rs @@ -0,0 +1,11 @@ +type A where for<'a> for<'b> Trait1 + ?Trait2: 'a + Trait = u8; // OK +type A where T: Trait, = u8; // OK +type A where T: = u8; // OK +type A where T:, = u8; // OK +type A where T: Trait + Trait = u8; // OK +type A where = u8; // OK +type A where T: Trait + = u8; // OK +type A where T, = u8; +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` + +fn main() {} diff --git a/tests/ui/parser/bounds-type-where.stderr b/tests/ui/parser/bounds-type-where.stderr new file mode 100644 index 000000000..5636ee75c --- /dev/null +++ b/tests/ui/parser/bounds-type-where.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` + --> $DIR/bounds-type-where.rs:8:15 + | +LL | type A where T, = u8; + | ^ expected one of 8 possible tokens + +error: aborting due to previous error + diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs new file mode 100644 index 000000000..4ae4549ea --- /dev/null +++ b/tests/ui/parser/bounds-type.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z parse-only + +struct S< + T: 'a + Tr, // OK + T: Tr + 'a, // OK + T: 'a, // OK + T:, // OK + T: ?for<'a> Trait, // OK + T: Tr +, // OK + T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds + + T: ~const Tr, // OK + T: ~const ?Tr, // OK + T: ~const Tr + 'a, // OK + T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds +>; + +fn main() {} diff --git a/tests/ui/parser/bounds-type.stderr b/tests/ui/parser/bounds-type.stderr new file mode 100644 index 000000000..005bc1e54 --- /dev/null +++ b/tests/ui/parser/bounds-type.stderr @@ -0,0 +1,14 @@ +error: `?` may only modify trait bounds, not lifetime bounds + --> $DIR/bounds-type.rs:10:8 + | +LL | T: ?'a, + | ^ + +error: `~const` may only modify trait bounds, not lifetime bounds + --> $DIR/bounds-type.rs:15:8 + | +LL | T: ~const 'a, + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/byte-literals.rs b/tests/ui/parser/byte-literals.rs new file mode 100644 index 000000000..896dc1a1a --- /dev/null +++ b/tests/ui/parser/byte-literals.rs @@ -0,0 +1,12 @@ +// ignore-tidy-tab + +static FOO: u8 = b'\f'; //~ ERROR unknown byte escape + +pub fn main() { + b'\f'; //~ ERROR unknown byte escape + b'\x0Z'; //~ ERROR invalid character in numeric character escape: `Z` + b' '; //~ ERROR byte constant must be escaped + b'''; //~ ERROR byte constant must be escaped + b'é'; //~ ERROR non-ASCII character in byte literal + b'a //~ ERROR unterminated byte constant [E0763] +} diff --git a/tests/ui/parser/byte-literals.stderr b/tests/ui/parser/byte-literals.stderr new file mode 100644 index 000000000..efa55ae05 --- /dev/null +++ b/tests/ui/parser/byte-literals.stderr @@ -0,0 +1,54 @@ +error: unknown byte escape: `f` + --> $DIR/byte-literals.rs:3:21 + | +LL | static FOO: u8 = b'\f'; + | ^ unknown byte escape + | + = help: for more information, visit + +error: unknown byte escape: `f` + --> $DIR/byte-literals.rs:6:8 + | +LL | b'\f'; + | ^ unknown byte escape + | + = help: for more information, visit + +error: invalid character in numeric character escape: `Z` + --> $DIR/byte-literals.rs:7:10 + | +LL | b'\x0Z'; + | ^ invalid character in numeric character escape + +error: byte constant must be escaped: `\t` + --> $DIR/byte-literals.rs:8:7 + | +LL | b' '; + | ^^^^ help: escape the character: `\t` + +error: byte constant must be escaped: `'` + --> $DIR/byte-literals.rs:9:7 + | +LL | b'''; + | ^ help: escape the character: `\'` + +error: non-ASCII character in byte literal + --> $DIR/byte-literals.rs:10:7 + | +LL | b'é'; + | ^ must be ASCII + | +help: if you meant to use the unicode code point for 'é', use a \xHH escape + | +LL | b'\xE9'; + | ~~~~ + +error[E0763]: unterminated byte constant + --> $DIR/byte-literals.rs:11:6 + | +LL | b'a + | ^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0763`. diff --git a/tests/ui/parser/byte-string-literals.rs b/tests/ui/parser/byte-string-literals.rs new file mode 100644 index 000000000..30a4f50c4 --- /dev/null +++ b/tests/ui/parser/byte-string-literals.rs @@ -0,0 +1,9 @@ +static FOO: &'static [u8] = b"\f"; //~ ERROR unknown byte escape + +pub fn main() { + b"\f"; //~ ERROR unknown byte escape + b"\x0Z"; //~ ERROR invalid character in numeric character escape: `Z` + b"é"; //~ ERROR non-ASCII character in byte string literal + br##"é"##; //~ ERROR non-ASCII character in raw byte string literal + b"a //~ ERROR unterminated double quote byte string +} diff --git a/tests/ui/parser/byte-string-literals.stderr b/tests/ui/parser/byte-string-literals.stderr new file mode 100644 index 000000000..5b96cc3d1 --- /dev/null +++ b/tests/ui/parser/byte-string-literals.stderr @@ -0,0 +1,50 @@ +error: unknown byte escape: `f` + --> $DIR/byte-string-literals.rs:1:32 + | +LL | static FOO: &'static [u8] = b"\f"; + | ^ unknown byte escape + | + = help: for more information, visit + +error: unknown byte escape: `f` + --> $DIR/byte-string-literals.rs:4:8 + | +LL | b"\f"; + | ^ unknown byte escape + | + = help: for more information, visit + +error: invalid character in numeric character escape: `Z` + --> $DIR/byte-string-literals.rs:5:10 + | +LL | b"\x0Z"; + | ^ invalid character in numeric character escape + +error: non-ASCII character in byte string literal + --> $DIR/byte-string-literals.rs:6:7 + | +LL | b"é"; + | ^ must be ASCII + | +help: if you meant to use the unicode code point for 'é', use a \xHH escape + | +LL | b"\xE9"; + | ~~~~ + +error: non-ASCII character in raw byte string literal + --> $DIR/byte-string-literals.rs:7:10 + | +LL | br##"é"##; + | ^ must be ASCII + +error[E0766]: unterminated double quote byte string + --> $DIR/byte-string-literals.rs:8:6 + | +LL | b"a + | ______^ +LL | | } + | |__^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0766`. diff --git a/tests/ui/parser/can-begin-expr-check.rs b/tests/ui/parser/can-begin-expr-check.rs new file mode 100644 index 000000000..e5be8de79 --- /dev/null +++ b/tests/ui/parser/can-begin-expr-check.rs @@ -0,0 +1,20 @@ +pub fn main() { + + return; + return (); + return as (); + return return as (); + return return return; + + return if true { + () + } else { + () + }; + + loop { + return break as (); + } + + return enum; //~ ERROR expected one of `;`, `}`, or an operator, found keyword `enum` +} diff --git a/tests/ui/parser/can-begin-expr-check.stderr b/tests/ui/parser/can-begin-expr-check.stderr new file mode 100644 index 000000000..9569ababa --- /dev/null +++ b/tests/ui/parser/can-begin-expr-check.stderr @@ -0,0 +1,8 @@ +error: expected one of `;`, `}`, or an operator, found keyword `enum` + --> $DIR/can-begin-expr-check.rs:19:12 + | +LL | return enum; + | ^^^^ expected one of `;`, `}`, or an operator + +error: aborting due to previous error + diff --git a/tests/ui/parser/chained-comparison-suggestion.rs b/tests/ui/parser/chained-comparison-suggestion.rs new file mode 100644 index 000000000..bbd46082c --- /dev/null +++ b/tests/ui/parser/chained-comparison-suggestion.rs @@ -0,0 +1,53 @@ +// Check that we get nice suggestions when attempting a chained comparison. + +fn comp1() { + 1 < 2 <= 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + +fn comp2() { + 1 < 2 < 3; //~ ERROR comparison operators cannot be chained +} + +fn comp3() { + 1 <= 2 < 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + +fn comp4() { + 1 <= 2 <= 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + +fn comp5() { + 1 > 2 >= 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + +fn comp6() { + 1 > 2 > 3; //~ ERROR comparison operators cannot be chained +} + +fn comp7() { + 1 >= 2 > 3; //~ ERROR comparison operators cannot be chained +} + +fn comp8() { + 1 >= 2 >= 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + +fn comp9() { + 1 == 2 < 3; //~ ERROR comparison operators cannot be chained +} + +fn comp10() { + 1 > 2 == false; //~ ERROR comparison operators cannot be chained +} + +fn comp11() { + 1 == 2 == 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/parser/chained-comparison-suggestion.stderr b/tests/ui/parser/chained-comparison-suggestion.stderr new file mode 100644 index 000000000..ae243816d --- /dev/null +++ b/tests/ui/parser/chained-comparison-suggestion.stderr @@ -0,0 +1,172 @@ +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:4:7 + | +LL | 1 < 2 <= 3; + | ^ ^^ + | +help: split the comparison into two + | +LL | 1 < 2 && 2 <= 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:9:7 + | +LL | 1 < 2 < 3; + | ^ ^ + | +help: split the comparison into two + | +LL | 1 < 2 && 2 < 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:13:7 + | +LL | 1 <= 2 < 3; + | ^^ ^ + | +help: split the comparison into two + | +LL | 1 <= 2 && 2 < 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:18:7 + | +LL | 1 <= 2 <= 3; + | ^^ ^^ + | +help: split the comparison into two + | +LL | 1 <= 2 && 2 <= 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:23:7 + | +LL | 1 > 2 >= 3; + | ^ ^^ + | +help: split the comparison into two + | +LL | 1 > 2 && 2 >= 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:28:7 + | +LL | 1 > 2 > 3; + | ^ ^ + | +help: split the comparison into two + | +LL | 1 > 2 && 2 > 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:32:7 + | +LL | 1 >= 2 > 3; + | ^^ ^ + | +help: split the comparison into two + | +LL | 1 >= 2 && 2 > 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:36:7 + | +LL | 1 >= 2 >= 3; + | ^^ ^^ + | +help: split the comparison into two + | +LL | 1 >= 2 && 2 >= 3; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:41:7 + | +LL | 1 == 2 < 3; + | ^^ ^ + | +help: parenthesize the comparison + | +LL | 1 == (2 < 3); + | + + + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:45:7 + | +LL | 1 > 2 == false; + | ^ ^^ + | +help: parenthesize the comparison + | +LL | (1 > 2) == false; + | + + + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:49:7 + | +LL | 1 == 2 == 3; + | ^^ ^^ + | +help: split the comparison into two + | +LL | 1 == 2 && 2 == 3; + | ++++ + +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:4:14 + | +LL | 1 < 2 <= 3; + | ----- ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:13:14 + | +LL | 1 <= 2 < 3; + | ------ ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:18:15 + | +LL | 1 <= 2 <= 3; + | ------ ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:23:14 + | +LL | 1 > 2 >= 3; + | ----- ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:36:15 + | +LL | 1 >= 2 >= 3; + | ------ ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:49:15 + | +LL | 1 == 2 == 3; + | ------ ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/char/whitespace-character-literal.rs b/tests/ui/parser/char/whitespace-character-literal.rs new file mode 100644 index 000000000..de5e09204 --- /dev/null +++ b/tests/ui/parser/char/whitespace-character-literal.rs @@ -0,0 +1,10 @@ +// This tests that the error generated when a character literal has multiple +// characters in it contains a note about non-printing characters. + +fn main() { + let _hair_space_around = ' x​'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + //~| HELP: consider removing the non-printing characters + //~| SUGGESTION: x +} diff --git a/tests/ui/parser/char/whitespace-character-literal.stderr b/tests/ui/parser/char/whitespace-character-literal.stderr new file mode 100644 index 000000000..d73de41a8 --- /dev/null +++ b/tests/ui/parser/char/whitespace-character-literal.stderr @@ -0,0 +1,16 @@ +error: character literal may only contain one codepoint + --> $DIR/whitespace-character-literal.rs:5:30 + | +LL | let _hair_space_around = ' x​'; + | ^--^ + | | + | help: consider removing the non-printing characters: `x` + | +note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + --> $DIR/whitespace-character-literal.rs:5:31 + | +LL | let _hair_space_around = ' x​'; + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/circular_modules_hello.rs b/tests/ui/parser/circular_modules_hello.rs new file mode 100644 index 000000000..6968ca97b --- /dev/null +++ b/tests/ui/parser/circular_modules_hello.rs @@ -0,0 +1,8 @@ +// ignore-test: this is an auxiliary file for circular-modules-main.rs + +#[path = "circular_modules_main.rs"] +mod circular_modules_main; + +pub fn say_hello() { + println!("{}", circular_modules_main::hi_str()); +} diff --git a/tests/ui/parser/circular_modules_main.rs b/tests/ui/parser/circular_modules_main.rs new file mode 100644 index 000000000..d4b47efe6 --- /dev/null +++ b/tests/ui/parser/circular_modules_main.rs @@ -0,0 +1,12 @@ +// error-pattern: circular modules + +#[path = "circular_modules_hello.rs"] +mod circular_modules_hello; + +pub fn hi_str() -> String { + "Hi!".to_string() +} + +fn main() { + circular_modules_hello::say_hello(); +} diff --git a/tests/ui/parser/circular_modules_main.stderr b/tests/ui/parser/circular_modules_main.stderr new file mode 100644 index 000000000..1094def60 --- /dev/null +++ b/tests/ui/parser/circular_modules_main.stderr @@ -0,0 +1,25 @@ +error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs + --> $DIR/circular_modules_hello.rs:4:1 + | +LL | mod circular_modules_main; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0425]: cannot find function `hi_str` in module `circular_modules_main` + --> $DIR/circular_modules_hello.rs:7:43 + | +LL | println!("{}", circular_modules_main::hi_str()); + | ^^^^^^ not found in `circular_modules_main` + | +help: consider importing this function + | +LL | use hi_str; + | +help: if you import `hi_str`, refer to it directly + | +LL - println!("{}", circular_modules_main::hi_str()); +LL + println!("{}", hi_str()); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/class-implements-bad-trait.rs b/tests/ui/parser/class-implements-bad-trait.rs new file mode 100644 index 000000000..f2f85d026 --- /dev/null +++ b/tests/ui/parser/class-implements-bad-trait.rs @@ -0,0 +1,9 @@ +// error-pattern:nonexistent +class cat : nonexistent { + let meows: usize; + new(in_x : usize) { self.meows = in_x; } +} + +fn main() { + let nyan = cat(0); +} diff --git a/tests/ui/parser/class-implements-bad-trait.stderr b/tests/ui/parser/class-implements-bad-trait.stderr new file mode 100644 index 000000000..3a4dea95d --- /dev/null +++ b/tests/ui/parser/class-implements-bad-trait.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `cat` + --> $DIR/class-implements-bad-trait.rs:2:7 + | +LL | class cat : nonexistent { + | ^^^ expected one of `!` or `::` + +error: aborting due to previous error + diff --git a/tests/ui/parser/closure-return-syntax.rs b/tests/ui/parser/closure-return-syntax.rs new file mode 100644 index 000000000..c6a08abef --- /dev/null +++ b/tests/ui/parser/closure-return-syntax.rs @@ -0,0 +1,7 @@ +// Test that we cannot parse a closure with an explicit return type +// unless it uses braces. + +fn main() { + let x = || -> i32 22; + //~^ ERROR expected `{`, found `22` +} diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr new file mode 100644 index 000000000..3d16a2067 --- /dev/null +++ b/tests/ui/parser/closure-return-syntax.stderr @@ -0,0 +1,13 @@ +error: expected `{`, found `22` + --> $DIR/closure-return-syntax.rs:5:23 + | +LL | let x = || -> i32 22; + | ^^ expected `{` + | +help: try placing this code inside a block + | +LL | let x = || -> i32 { 22 }; + | + + + +error: aborting due to previous error + diff --git a/tests/ui/parser/column-offset-1-based.rs b/tests/ui/parser/column-offset-1-based.rs new file mode 100644 index 000000000..0c24478c2 --- /dev/null +++ b/tests/ui/parser/column-offset-1-based.rs @@ -0,0 +1 @@ +# //~ ERROR expected one of `!` or `[`, found `` diff --git a/tests/ui/parser/column-offset-1-based.stderr b/tests/ui/parser/column-offset-1-based.stderr new file mode 100644 index 000000000..766d72a0a --- /dev/null +++ b/tests/ui/parser/column-offset-1-based.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `[`, found `` + --> $DIR/column-offset-1-based.rs:1:1 + | +LL | # + | ^ expected one of `!` or `[` + +error: aborting due to previous error + diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs new file mode 100644 index 000000000..53e3c6f96 --- /dev/null +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs @@ -0,0 +1,15 @@ +struct NInts([u8; N]); +impl NInts {} //~ ERROR unexpected `const` parameter declaration + +fn main() { + let _: () = 42; //~ ERROR mismatched types +} + +fn banana(a: >::BAR) {} +//~^ ERROR unexpected `const` parameter declaration +//~| ERROR cannot find type `T` in this scope +fn chaenomeles() { + path::path::Struct::() + //~^ ERROR unexpected `const` parameter declaration + //~| ERROR failed to resolve: use of undeclared crate or module `path` +} diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr new file mode 100644 index 000000000..96885d11e --- /dev/null +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr @@ -0,0 +1,47 @@ +error: unexpected `const` parameter declaration + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:2:12 + | +LL | impl NInts {} + | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration + | +help: `const` parameters must be declared for the `impl` + | +LL | impl NInts {} + | ++++++++++++++++ ~ + +error: unexpected `const` parameter declaration + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:17 + | +LL | fn banana(a: >::BAR) {} + | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration + +error: unexpected `const` parameter declaration + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:26 + | +LL | path::path::Struct::() + | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration + +error[E0433]: failed to resolve: use of undeclared crate or module `path` + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5 + | +LL | path::path::Struct::() + | ^^^^ use of undeclared crate or module `path` + +error[E0412]: cannot find type `T` in this scope + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 + | +LL | fn banana(a: >::BAR) {} + | ^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:5:17 + | +LL | let _: () = 42; + | -- ^^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0412, E0433. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs new file mode 100644 index 000000000..d8346653c --- /dev/null +++ b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs @@ -0,0 +1,13 @@ +// check-pass + +#[cfg(FALSE)] +fn syntax() { + foo::(); + //~^ WARN associated type bounds are unstable + //~| WARN unstable syntax + foo::(); + //~^ WARN associated type bounds are unstable + //~| WARN unstable syntax +} + +fn main() {} diff --git a/tests/ui/parser/constraints-before-generic-args-syntactic-pass.stderr b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.stderr new file mode 100644 index 000000000..7e843c7f4 --- /dev/null +++ b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.stderr @@ -0,0 +1,24 @@ +warning: associated type bounds are unstable + --> $DIR/constraints-before-generic-args-syntactic-pass.rs:5:19 + | +LL | foo::(); + | ^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: associated type bounds are unstable + --> $DIR/constraints-before-generic-args-syntactic-pass.rs:8:23 + | +LL | foo::(); + | ^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 2 warnings emitted + diff --git a/tests/ui/parser/default-on-wrong-item-kind.rs b/tests/ui/parser/default-on-wrong-item-kind.rs new file mode 100644 index 000000000..98a95cfa3 --- /dev/null +++ b/tests/ui/parser/default-on-wrong-item-kind.rs @@ -0,0 +1,140 @@ +// Test parsing for `default` where it doesn't belong. +// Specifically, we are interested in kinds of items or items in certain contexts. +// Also test item kinds in `extern` blocks and associated contexts which are not allowed there. + +fn main() {} + +#[cfg(FALSE)] +mod free_items { + default extern crate foo; //~ ERROR an extern crate cannot be `default` + default use foo; //~ ERROR a `use` import cannot be `default` + default static foo: u8; //~ ERROR a static item cannot be `default` + default const foo: u8; + default fn foo(); + default mod foo {} //~ ERROR a module cannot be `default` + default extern "C" {} //~ ERROR an extern block cannot be `default` + default type foo = u8; + default enum foo {} //~ ERROR an enum cannot be `default` + default struct foo {} //~ ERROR a struct cannot be `default` + default union foo {} //~ ERROR a union cannot be `default` + default trait foo {} //~ ERROR a trait cannot be `default` + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` + default impl foo {} + default!(); + default::foo::bar!(); + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` +} + +#[cfg(FALSE)] +extern "C" { + default extern crate foo; //~ ERROR an extern crate cannot be `default` + //~^ ERROR extern crate is not supported in `extern` blocks + default use foo; //~ ERROR a `use` import cannot be `default` + //~^ ERROR `use` import is not supported in `extern` blocks + default static foo: u8; //~ ERROR a static item cannot be `default` + default const foo: u8; + //~^ ERROR extern items cannot be `const` + default fn foo(); + default mod foo {} //~ ERROR a module cannot be `default` + //~^ ERROR module is not supported in `extern` blocks + default extern "C" {} //~ ERROR an extern block cannot be `default` + //~^ ERROR extern block is not supported in `extern` blocks + default type foo = u8; + default enum foo {} //~ ERROR an enum cannot be `default` + //~^ ERROR enum is not supported in `extern` blocks + default struct foo {} //~ ERROR a struct cannot be `default` + //~^ ERROR struct is not supported in `extern` blocks + default union foo {} //~ ERROR a union cannot be `default` + //~^ ERROR union is not supported in `extern` blocks + default trait foo {} //~ ERROR a trait cannot be `default` + //~^ ERROR trait is not supported in `extern` blocks + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` + //~^ ERROR trait alias is not supported in `extern` blocks + default impl foo {} + //~^ ERROR implementation is not supported in `extern` blocks + default!(); + default::foo::bar!(); + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` + //~^ ERROR macro definition is not supported in `extern` blocks + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` + //~^ ERROR macro definition is not supported in `extern` blocks +} + +#[cfg(FALSE)] +impl S { + default extern crate foo; //~ ERROR an extern crate cannot be `default` + //~^ ERROR extern crate is not supported in `trait`s or `impl`s + default use foo; //~ ERROR a `use` import cannot be `default` + //~^ ERROR `use` import is not supported in `trait`s or `impl`s + default static foo: u8; //~ ERROR a static item cannot be `default` + //~^ ERROR associated `static` items are not allowed + default const foo: u8; + default fn foo(); + default mod foo {}//~ ERROR a module cannot be `default` + //~^ ERROR module is not supported in `trait`s or `impl`s + default extern "C" {} //~ ERROR an extern block cannot be `default` + //~^ ERROR extern block is not supported in `trait`s or `impl`s + default type foo = u8; + default enum foo {} //~ ERROR an enum cannot be `default` + //~^ ERROR enum is not supported in `trait`s or `impl`s + default struct foo {} //~ ERROR a struct cannot be `default` + //~^ ERROR struct is not supported in `trait`s or `impl`s + default union foo {} //~ ERROR a union cannot be `default` + //~^ ERROR union is not supported in `trait`s or `impl`s + default trait foo {} //~ ERROR a trait cannot be `default` + //~^ ERROR trait is not supported in `trait`s or `impl`s + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` + //~^ ERROR trait alias is not supported in `trait`s or `impl`s + default impl foo {} + //~^ ERROR implementation is not supported in `trait`s or `impl`s + default!(); + default::foo::bar!(); + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s +} + +#[cfg(FALSE)] +trait T { + default extern crate foo; //~ ERROR an extern crate cannot be `default` + //~^ ERROR extern crate is not supported in `trait`s or `impl`s + default use foo; //~ ERROR a `use` import cannot be `default` + //~^ ERROR `use` import is not supported in `trait`s or `impl`s + default static foo: u8; //~ ERROR a static item cannot be `default` + //~^ ERROR associated `static` items are not allowed + default const foo: u8; + default fn foo(); + default mod foo {}//~ ERROR a module cannot be `default` + //~^ ERROR module is not supported in `trait`s or `impl`s + default extern "C" {} //~ ERROR an extern block cannot be `default` + //~^ ERROR extern block is not supported in `trait`s or `impl`s + default type foo = u8; + default enum foo {} //~ ERROR an enum cannot be `default` + //~^ ERROR enum is not supported in `trait`s or `impl`s + default struct foo {} //~ ERROR a struct cannot be `default` + //~^ ERROR struct is not supported in `trait`s or `impl`s + default union foo {} //~ ERROR a union cannot be `default` + //~^ ERROR union is not supported in `trait`s or `impl`s + default trait foo {} //~ ERROR a trait cannot be `default` + //~^ ERROR trait is not supported in `trait`s or `impl`s + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` + //~^ ERROR trait alias is not supported in `trait`s or `impl`s + default impl foo {} + //~^ ERROR implementation is not supported in `trait`s or `impl`s + default!(); + default::foo::bar!(); + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s +} diff --git a/tests/ui/parser/default-on-wrong-item-kind.stderr b/tests/ui/parser/default-on-wrong-item-kind.stderr new file mode 100644 index 000000000..af513f761 --- /dev/null +++ b/tests/ui/parser/default-on-wrong-item-kind.stderr @@ -0,0 +1,760 @@ +error: an extern crate cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:9:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a `use` import cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:10:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a static item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:11:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a module cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:14:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an extern block cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:15:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an enum cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:17:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a struct cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:18:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a union cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:19:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a trait cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:20:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a trait alias cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:21:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:25:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:26:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:27:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:28:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an extern crate cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:33:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern crate is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:33:5 + | +LL | default extern crate foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the extern crate out to a nearby module scope + +error: a `use` import cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:35:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: `use` import is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:35:5 + | +LL | default use foo; + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the `use` import out to a nearby module scope + +error: a static item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:37:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern items cannot be `const` + --> $DIR/default-on-wrong-item-kind.rs:38:19 + | +LL | default const foo: u8; + | --------------^^^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: a module cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:41:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: module is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:41:5 + | +LL | default mod foo {} + | ^^^^^^^^^^^^^^^ + | + = help: consider moving the module out to a nearby module scope + +error: an extern block cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:43:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern block is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:43:5 + | +LL | default extern "C" {} + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the extern block out to a nearby module scope + +error: an enum cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:46:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: enum is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:46:5 + | +LL | default enum foo {} + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the enum out to a nearby module scope + +error: a struct cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:48:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: struct is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:48:5 + | +LL | default struct foo {} + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: a union cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:50:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: union is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:50:5 + | +LL | default union foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the union out to a nearby module scope + +error: a trait cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:52:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: trait is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:52:5 + | +LL | default trait foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the trait out to a nearby module scope + +error: a trait alias cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:54:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: trait alias is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:54:5 + | +LL | default trait foo = Ord; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the trait alias out to a nearby module scope + +error: implementation is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:56:5 + | +LL | default impl foo {} + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the implementation out to a nearby module scope + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:60:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:61:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:62:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: macro definition is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:62:5 + | +LL | default macro foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the macro definition out to a nearby module scope + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:64:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: macro definition is not supported in `extern` blocks + --> $DIR/default-on-wrong-item-kind.rs:64:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the macro definition out to a nearby module scope + +error: an extern crate cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:70:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern crate is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:70:5 + | +LL | default extern crate foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the extern crate out to a nearby module scope + +error: a `use` import cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:72:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: `use` import is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:72:5 + | +LL | default use foo; + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the `use` import out to a nearby module scope + +error: a static item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:74:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/default-on-wrong-item-kind.rs:74:5 + | +LL | default static foo: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: a module cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:78:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: module is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:78:5 + | +LL | default mod foo {} + | ^^^^^^^^^^^^^^^ + | + = help: consider moving the module out to a nearby module scope + +error: an extern block cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:80:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern block is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:80:5 + | +LL | default extern "C" {} + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the extern block out to a nearby module scope + +error: an enum cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:83:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: enum is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:83:5 + | +LL | default enum foo {} + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the enum out to a nearby module scope + +error: a struct cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:85:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: struct is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:85:5 + | +LL | default struct foo {} + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: a union cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:87:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: union is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:87:5 + | +LL | default union foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the union out to a nearby module scope + +error: a trait cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:89:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: trait is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:89:5 + | +LL | default trait foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the trait out to a nearby module scope + +error: a trait alias cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:91:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: trait alias is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:91:5 + | +LL | default trait foo = Ord; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the trait alias out to a nearby module scope + +error: implementation is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:93:5 + | +LL | default impl foo {} + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the implementation out to a nearby module scope + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:97:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:98:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:99:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: macro definition is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:99:5 + | +LL | default macro foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the macro definition out to a nearby module scope + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:101:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: macro definition is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:101:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the macro definition out to a nearby module scope + +error: an extern crate cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:107:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern crate is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:107:5 + | +LL | default extern crate foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the extern crate out to a nearby module scope + +error: a `use` import cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:109:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: `use` import is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:109:5 + | +LL | default use foo; + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the `use` import out to a nearby module scope + +error: a static item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:111:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: associated `static` items are not allowed + --> $DIR/default-on-wrong-item-kind.rs:111:5 + | +LL | default static foo: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: a module cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:115:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: module is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:115:5 + | +LL | default mod foo {} + | ^^^^^^^^^^^^^^^ + | + = help: consider moving the module out to a nearby module scope + +error: an extern block cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:117:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern block is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:117:5 + | +LL | default extern "C" {} + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the extern block out to a nearby module scope + +error: an enum cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:120:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: enum is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:120:5 + | +LL | default enum foo {} + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the enum out to a nearby module scope + +error: a struct cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:122:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: struct is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:122:5 + | +LL | default struct foo {} + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: a union cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:124:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: union is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:124:5 + | +LL | default union foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the union out to a nearby module scope + +error: a trait cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:126:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: trait is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:126:5 + | +LL | default trait foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the trait out to a nearby module scope + +error: a trait alias cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:128:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: trait alias is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:128:5 + | +LL | default trait foo = Ord; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the trait alias out to a nearby module scope + +error: implementation is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:130:5 + | +LL | default impl foo {} + | ^^^^^^^^^^^^^^^^ + | + = help: consider moving the implementation out to a nearby module scope + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:134:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:135:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:136:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: macro definition is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:136:5 + | +LL | default macro foo {} + | ^^^^^^^^^^^^^^^^^ + | + = help: consider moving the macro definition out to a nearby module scope + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:138:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: macro definition is not supported in `trait`s or `impl`s + --> $DIR/default-on-wrong-item-kind.rs:138:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the macro definition out to a nearby module scope + +error: aborting due to 95 previous errors + diff --git a/tests/ui/parser/default-unmatched-assoc.rs b/tests/ui/parser/default-unmatched-assoc.rs new file mode 100644 index 000000000..168ea3e76 --- /dev/null +++ b/tests/ui/parser/default-unmatched-assoc.rs @@ -0,0 +1,16 @@ +fn main() {} + +trait Foo { + default!(); //~ ERROR cannot find macro `default` in this scope + default do + //~^ ERROR `default` is not followed by an item + //~| ERROR non-item in item list +} + +struct S; +impl S { + default!(); //~ ERROR cannot find macro `default` in this scope + default do + //~^ ERROR `default` is not followed by an item + //~| ERROR non-item in item list +} diff --git a/tests/ui/parser/default-unmatched-assoc.stderr b/tests/ui/parser/default-unmatched-assoc.stderr new file mode 100644 index 000000000..ee35fded9 --- /dev/null +++ b/tests/ui/parser/default-unmatched-assoc.stderr @@ -0,0 +1,54 @@ +error: `default` is not followed by an item + --> $DIR/default-unmatched-assoc.rs:5:5 + | +LL | default do + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: non-item in item list + --> $DIR/default-unmatched-assoc.rs:5:13 + | +LL | trait Foo { + | - item list starts here +LL | default!(); +LL | default do + | ^^ non-item starts here +... +LL | } + | - item list ends here + +error: `default` is not followed by an item + --> $DIR/default-unmatched-assoc.rs:13:5 + | +LL | default do + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: non-item in item list + --> $DIR/default-unmatched-assoc.rs:13:13 + | +LL | impl S { + | - item list starts here +LL | default!(); +LL | default do + | ^^ non-item starts here +... +LL | } + | - item list ends here + +error: cannot find macro `default` in this scope + --> $DIR/default-unmatched-assoc.rs:4:5 + | +LL | default!(); + | ^^^^^^^ + +error: cannot find macro `default` in this scope + --> $DIR/default-unmatched-assoc.rs:12:5 + | +LL | default!(); + | ^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/default-unmatched-extern.rs b/tests/ui/parser/default-unmatched-extern.rs new file mode 100644 index 000000000..8d0ea590f --- /dev/null +++ b/tests/ui/parser/default-unmatched-extern.rs @@ -0,0 +1,8 @@ +fn main() {} + +extern "C" { + default!(); //~ ERROR cannot find macro `default` in this scope + default do + //~^ ERROR `default` is not followed by an item + //~| ERROR non-item in item list +} diff --git a/tests/ui/parser/default-unmatched-extern.stderr b/tests/ui/parser/default-unmatched-extern.stderr new file mode 100644 index 000000000..bb4efd516 --- /dev/null +++ b/tests/ui/parser/default-unmatched-extern.stderr @@ -0,0 +1,28 @@ +error: `default` is not followed by an item + --> $DIR/default-unmatched-extern.rs:5:5 + | +LL | default do + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: non-item in item list + --> $DIR/default-unmatched-extern.rs:5:13 + | +LL | extern "C" { + | - item list starts here +LL | default!(); +LL | default do + | ^^ non-item starts here +... +LL | } + | - item list ends here + +error: cannot find macro `default` in this scope + --> $DIR/default-unmatched-extern.rs:4:5 + | +LL | default!(); + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/default-unmatched.rs b/tests/ui/parser/default-unmatched.rs new file mode 100644 index 000000000..49346e5c6 --- /dev/null +++ b/tests/ui/parser/default-unmatched.rs @@ -0,0 +1,6 @@ +mod foo { + default!(); // OK. + default do + //~^ ERROR `default` is not followed by an item + //~| ERROR expected item, found reserved keyword `do` +} diff --git a/tests/ui/parser/default-unmatched.stderr b/tests/ui/parser/default-unmatched.stderr new file mode 100644 index 000000000..331e003f6 --- /dev/null +++ b/tests/ui/parser/default-unmatched.stderr @@ -0,0 +1,16 @@ +error: `default` is not followed by an item + --> $DIR/default-unmatched.rs:3:5 + | +LL | default do + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: expected item, found reserved keyword `do` + --> $DIR/default-unmatched.rs:3:13 + | +LL | default do + | ^^ expected item + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/default.rs b/tests/ui/parser/default.rs new file mode 100644 index 000000000..52338c1f1 --- /dev/null +++ b/tests/ui/parser/default.rs @@ -0,0 +1,28 @@ +// Test successful and unsuccessful parsing of the `default` contextual keyword + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo() -> T; +} + +impl Foo for u8 { + default fn foo() -> T { + T::default() + } +} + +impl Foo for u16 { + pub default fn foo() -> T { //~ ERROR unnecessary visibility qualifier + T::default() + } +} + +impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` + default pub fn foo() -> T { T::default() } + //~^ ERROR `default` is not followed by an item + //~| ERROR non-item in item list +} + +fn main() {} diff --git a/tests/ui/parser/default.stderr b/tests/ui/parser/default.stderr new file mode 100644 index 000000000..37aa48ccf --- /dev/null +++ b/tests/ui/parser/default.stderr @@ -0,0 +1,48 @@ +error: `default` is not followed by an item + --> $DIR/default.rs:23:5 + | +LL | default pub fn foo() -> T { T::default() } + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: non-item in item list + --> $DIR/default.rs:23:13 + | +LL | impl Foo for u32 { + | - item list starts here +LL | default pub fn foo() -> T { T::default() } + | ^^^ non-item starts here +... +LL | } + | - item list ends here + +error[E0449]: unnecessary visibility qualifier + --> $DIR/default.rs:17:5 + | +LL | pub default fn foo() -> T { + | ^^^ `pub` not permitted here because it's implied + +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/default.rs:22:1 + | +LL | fn foo() -> T; + | -------------------------- `foo` from trait +... +LL | impl Foo for u32 { + | ^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0046, E0449. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/parser/diff-markers/enum-2.rs b/tests/ui/parser/diff-markers/enum-2.rs new file mode 100644 index 000000000..76ea980fc --- /dev/null +++ b/tests/ui/parser/diff-markers/enum-2.rs @@ -0,0 +1,11 @@ +enum E { + Foo { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +||||||| + z: (), +======= + y: i8, +>>>>>>> branch + } +} diff --git a/tests/ui/parser/diff-markers/enum-2.stderr b/tests/ui/parser/diff-markers/enum-2.stderr new file mode 100644 index 000000000..63da5c2a6 --- /dev/null +++ b/tests/ui/parser/diff-markers/enum-2.stderr @@ -0,0 +1,21 @@ +error: encountered diff marker + --> $DIR/enum-2.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ||||||| + | ------- +LL | z: (), +LL | ======= + | ------- +LL | y: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/enum.rs b/tests/ui/parser/diff-markers/enum.rs new file mode 100644 index 000000000..45df6e325 --- /dev/null +++ b/tests/ui/parser/diff-markers/enum.rs @@ -0,0 +1,7 @@ +enum E { +<<<<<<< HEAD //~ ERROR encountered diff marker + Foo(u8), +======= + Bar(i8), +>>>>>>> branch +} diff --git a/tests/ui/parser/diff-markers/enum.stderr b/tests/ui/parser/diff-markers/enum.stderr new file mode 100644 index 000000000..abbf3fb41 --- /dev/null +++ b/tests/ui/parser/diff-markers/enum.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/enum.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | Foo(u8), +LL | ======= + | ------- +LL | Bar(i8), +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/fn-arg.rs b/tests/ui/parser/diff-markers/fn-arg.rs new file mode 100644 index 000000000..86c355628 --- /dev/null +++ b/tests/ui/parser/diff-markers/fn-arg.rs @@ -0,0 +1,16 @@ +trait T { + fn foo( +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch + ) {} +} + +struct S; +impl T for S {} + +fn main() { + S::foo(42); +} diff --git a/tests/ui/parser/diff-markers/fn-arg.stderr b/tests/ui/parser/diff-markers/fn-arg.stderr new file mode 100644 index 000000000..933a20641 --- /dev/null +++ b/tests/ui/parser/diff-markers/fn-arg.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/fn-arg.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ======= + | ------- +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/item-with-attr.rs b/tests/ui/parser/diff-markers/item-with-attr.rs new file mode 100644 index 000000000..985907c08 --- /dev/null +++ b/tests/ui/parser/diff-markers/item-with-attr.rs @@ -0,0 +1,10 @@ +#[attribute] +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/tests/ui/parser/diff-markers/item-with-attr.stderr b/tests/ui/parser/diff-markers/item-with-attr.stderr new file mode 100644 index 000000000..850e2368e --- /dev/null +++ b/tests/ui/parser/diff-markers/item-with-attr.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/item-with-attr.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/item.rs b/tests/ui/parser/diff-markers/item.rs new file mode 100644 index 000000000..4ed36b7b4 --- /dev/null +++ b/tests/ui/parser/diff-markers/item.rs @@ -0,0 +1,9 @@ +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/tests/ui/parser/diff-markers/item.stderr b/tests/ui/parser/diff-markers/item.stderr new file mode 100644 index 000000000..9ab3631a6 --- /dev/null +++ b/tests/ui/parser/diff-markers/item.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/item.rs:1:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/statement.rs b/tests/ui/parser/diff-markers/statement.rs new file mode 100644 index 000000000..e55d16d3b --- /dev/null +++ b/tests/ui/parser/diff-markers/statement.rs @@ -0,0 +1,15 @@ +trait T { + fn foo() {} + fn bar() {} +} + +struct S; +impl T for S {} + +fn main() { +<<<<<<< HEAD //~ ERROR encountered diff marker + S::foo(); +======= + S::bar(); +>>>>>>> branch +} diff --git a/tests/ui/parser/diff-markers/statement.stderr b/tests/ui/parser/diff-markers/statement.stderr new file mode 100644 index 000000000..7ca2495b8 --- /dev/null +++ b/tests/ui/parser/diff-markers/statement.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/statement.rs:10:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | S::foo(); +LL | ======= + | ------- +LL | S::bar(); +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/struct-expr.rs b/tests/ui/parser/diff-markers/struct-expr.rs new file mode 100644 index 000000000..99d2fd662 --- /dev/null +++ b/tests/ui/parser/diff-markers/struct-expr.rs @@ -0,0 +1,12 @@ +struct S { + x: u8, +} +fn main() { + let _ = S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: 42, +======= + x: 0, +>>>>>>> branch + } +} diff --git a/tests/ui/parser/diff-markers/struct-expr.stderr b/tests/ui/parser/diff-markers/struct-expr.stderr new file mode 100644 index 000000000..d70476a98 --- /dev/null +++ b/tests/ui/parser/diff-markers/struct-expr.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/struct-expr.rs:6:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: 42, +LL | ======= + | ------- +LL | x: 0, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/struct.rs b/tests/ui/parser/diff-markers/struct.rs new file mode 100644 index 000000000..d26464d47 --- /dev/null +++ b/tests/ui/parser/diff-markers/struct.rs @@ -0,0 +1,7 @@ +struct S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch +} diff --git a/tests/ui/parser/diff-markers/struct.stderr b/tests/ui/parser/diff-markers/struct.stderr new file mode 100644 index 000000000..cc0b3da66 --- /dev/null +++ b/tests/ui/parser/diff-markers/struct.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ======= + | ------- +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/trait-item.rs b/tests/ui/parser/diff-markers/trait-item.rs new file mode 100644 index 000000000..3227c8212 --- /dev/null +++ b/tests/ui/parser/diff-markers/trait-item.rs @@ -0,0 +1,14 @@ +trait T { +<<<<<<< HEAD //~ ERROR encountered diff marker + fn foo() {} +======= + fn bar() {} +>>>>>>> branch +} + +struct S; +impl T for S {} + +fn main() { + S::foo(); +} diff --git a/tests/ui/parser/diff-markers/trait-item.stderr b/tests/ui/parser/diff-markers/trait-item.stderr new file mode 100644 index 000000000..cdc19f8e0 --- /dev/null +++ b/tests/ui/parser/diff-markers/trait-item.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/trait-item.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/tuple-struct.rs b/tests/ui/parser/diff-markers/tuple-struct.rs new file mode 100644 index 000000000..7eec35c96 --- /dev/null +++ b/tests/ui/parser/diff-markers/tuple-struct.rs @@ -0,0 +1,7 @@ +struct S( +<<<<<<< HEAD //~ ERROR encountered diff marker + u8, +======= + i8, +>>>>>>> branch +); diff --git a/tests/ui/parser/diff-markers/tuple-struct.stderr b/tests/ui/parser/diff-markers/tuple-struct.stderr new file mode 100644 index 000000000..d673db898 --- /dev/null +++ b/tests/ui/parser/diff-markers/tuple-struct.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/tuple-struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | u8, +LL | ======= + | ------- +LL | i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/diff-markers/use-statement.rs b/tests/ui/parser/diff-markers/use-statement.rs new file mode 100644 index 000000000..6306243a5 --- /dev/null +++ b/tests/ui/parser/diff-markers/use-statement.rs @@ -0,0 +1,9 @@ +use foo::{ +<<<<<<< HEAD //~ ERROR encountered diff marker + bar, +======= + baz, +>>>>>>> branch +}; + +fn main() {} diff --git a/tests/ui/parser/diff-markers/use-statement.stderr b/tests/ui/parser/diff-markers/use-statement.stderr new file mode 100644 index 000000000..12e6f57dd --- /dev/null +++ b/tests/ui/parser/diff-markers/use-statement.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/use-statement.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | bar, +LL | ======= + | ------- +LL | baz, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to previous error + diff --git a/tests/ui/parser/do-catch-suggests-try.rs b/tests/ui/parser/do-catch-suggests-try.rs new file mode 100644 index 000000000..f64568d06 --- /dev/null +++ b/tests/ui/parser/do-catch-suggests-try.rs @@ -0,0 +1,10 @@ +#![feature(try_blocks)] + +fn main() { + let _: Option<()> = do catch {}; + //~^ ERROR found removed `do catch` syntax + //~| replace with the new syntax + //~| following RFC #2388, the new non-placeholder syntax is `try` + + let _recovery_witness: () = 1; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/do-catch-suggests-try.stderr b/tests/ui/parser/do-catch-suggests-try.stderr new file mode 100644 index 000000000..cd8907b7e --- /dev/null +++ b/tests/ui/parser/do-catch-suggests-try.stderr @@ -0,0 +1,19 @@ +error: found removed `do catch` syntax + --> $DIR/do-catch-suggests-try.rs:4:25 + | +LL | let _: Option<()> = do catch {}; + | ^^^^^^^^ help: replace with the new syntax: `try` + | + = note: following RFC #2388, the new non-placeholder syntax is `try` + +error[E0308]: mismatched types + --> $DIR/do-catch-suggests-try.rs:9:33 + | +LL | let _recovery_witness: () = 1; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.rs b/tests/ui/parser/do-not-suggest-semicolon-before-array.rs new file mode 100644 index 000000000..7ebf3f6b0 --- /dev/null +++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.rs @@ -0,0 +1,8 @@ +fn foo() {} + +fn bar() -> [u8; 2] { + foo() + [1, 3) //~ ERROR expected one of `.`, `?`, `]`, or an operator, found `,` +} + +fn main() {} diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr new file mode 100644 index 000000000..a9dd52632 --- /dev/null +++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr @@ -0,0 +1,10 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/do-not-suggest-semicolon-before-array.rs:5:5 + | +LL | [1, 3) + | ^ ^ help: `]` may belong here + | | + | unclosed delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs b/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs new file mode 100644 index 000000000..d6f798181 --- /dev/null +++ b/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs @@ -0,0 +1,3 @@ +fn main() { + let _x = vec[1, 2, 3]; //~ ERROR expected one of `.`, `?`, `]`, or an operator +} diff --git a/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr b/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr new file mode 100644 index 000000000..2fe6a28ee --- /dev/null +++ b/tests/ui/parser/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/do-not-suggest-semicolon-between-macro-without-exclamation-mark-and-array.rs:2:19 + | +LL | let _x = vec[1, 2, 3]; + | ^ expected one of `.`, `?`, `]`, or an operator + +error: aborting due to previous error + diff --git a/tests/ui/parser/doc-after-struct-field.rs b/tests/ui/parser/doc-after-struct-field.rs new file mode 100644 index 000000000..03faa6733 --- /dev/null +++ b/tests/ui/parser/doc-after-struct-field.rs @@ -0,0 +1,16 @@ +struct X { + a: u8 /** document a */, + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` +} + +struct Y { + a: u8 /// document a + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` +} + +fn main() { + let x = X { a: 1 }; + let y = Y { a: 1 }; +} diff --git a/tests/ui/parser/doc-after-struct-field.stderr b/tests/ui/parser/doc-after-struct-field.stderr new file mode 100644 index 000000000..ae177f1a2 --- /dev/null +++ b/tests/ui/parser/doc-after-struct-field.stderr @@ -0,0 +1,19 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-after-struct-field.rs:2:11 + | +LL | a: u8 /** document a */, + | ^^^^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-after-struct-field.rs:8:11 + | +LL | a: u8 /// document a + | ^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-attr.rs b/tests/ui/parser/doc-before-attr.rs new file mode 100644 index 000000000..c4125a09f --- /dev/null +++ b/tests/ui/parser/doc-before-attr.rs @@ -0,0 +1,4 @@ +fn main() {} + +/// hi +#[derive(Debug)] //~ERROR expected item after attributes diff --git a/tests/ui/parser/doc-before-attr.stderr b/tests/ui/parser/doc-before-attr.stderr new file mode 100644 index 000000000..14fd01af2 --- /dev/null +++ b/tests/ui/parser/doc-before-attr.stderr @@ -0,0 +1,10 @@ +error: expected item after attributes + --> $DIR/doc-before-attr.rs:4:1 + | +LL | /// hi + | ------ other attributes here +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/doc-before-eof.rs b/tests/ui/parser/doc-before-eof.rs new file mode 100644 index 000000000..b31836e95 --- /dev/null +++ b/tests/ui/parser/doc-before-eof.rs @@ -0,0 +1,3 @@ +fn main() {} + +/// hi //~ERROR expected item after doc comment diff --git a/tests/ui/parser/doc-before-eof.stderr b/tests/ui/parser/doc-before-eof.stderr new file mode 100644 index 000000000..827566267 --- /dev/null +++ b/tests/ui/parser/doc-before-eof.stderr @@ -0,0 +1,8 @@ +error: expected item after doc comment + --> $DIR/doc-before-eof.rs:3:1 + | +LL | /// hi + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything + +error: aborting due to previous error + diff --git a/tests/ui/parser/doc-before-extern-rbrace.rs b/tests/ui/parser/doc-before-extern-rbrace.rs new file mode 100644 index 000000000..515c90ed4 --- /dev/null +++ b/tests/ui/parser/doc-before-extern-rbrace.rs @@ -0,0 +1,6 @@ +fn main() {} + +extern "C" { + /// hi + //~^ ERROR found a documentation comment that doesn't document anything +} diff --git a/tests/ui/parser/doc-before-extern-rbrace.stderr b/tests/ui/parser/doc-before-extern-rbrace.stderr new file mode 100644 index 000000000..8fa12ec26 --- /dev/null +++ b/tests/ui/parser/doc-before-extern-rbrace.stderr @@ -0,0 +1,11 @@ +error[E0584]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-extern-rbrace.rs:4:5 + | +LL | /// hi + | ^^^^^^ this doc comment doesn't document anything + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0584`. diff --git a/tests/ui/parser/doc-before-fn-rbrace.rs b/tests/ui/parser/doc-before-fn-rbrace.rs new file mode 100644 index 000000000..c85021648 --- /dev/null +++ b/tests/ui/parser/doc-before-fn-rbrace.rs @@ -0,0 +1,5 @@ +fn main() { + /// document + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` +} diff --git a/tests/ui/parser/doc-before-fn-rbrace.stderr b/tests/ui/parser/doc-before-fn-rbrace.stderr new file mode 100644 index 000000000..6ea68e42b --- /dev/null +++ b/tests/ui/parser/doc-before-fn-rbrace.stderr @@ -0,0 +1,11 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-fn-rbrace.rs:2:5 + | +LL | /// document + | ^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-identifier.rs b/tests/ui/parser/doc-before-identifier.rs new file mode 100644 index 000000000..76263ad92 --- /dev/null +++ b/tests/ui/parser/doc-before-identifier.rs @@ -0,0 +1,7 @@ +fn /// document +foo() {} +//~^^ ERROR expected identifier, found doc comment `/// document` + +fn main() { + foo(); +} diff --git a/tests/ui/parser/doc-before-identifier.stderr b/tests/ui/parser/doc-before-identifier.stderr new file mode 100644 index 000000000..940d293b6 --- /dev/null +++ b/tests/ui/parser/doc-before-identifier.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found doc comment `/// document` + --> $DIR/doc-before-identifier.rs:1:4 + | +LL | fn /// document + | ^^^^^^^^^^^^ expected identifier, found doc comment + +error: aborting due to previous error + diff --git a/tests/ui/parser/doc-before-mod-rbrace.rs b/tests/ui/parser/doc-before-mod-rbrace.rs new file mode 100644 index 000000000..c65a0a931 --- /dev/null +++ b/tests/ui/parser/doc-before-mod-rbrace.rs @@ -0,0 +1,6 @@ +mod Foo { + /// document + //~^ ERROR expected item after doc comment +} + +fn main() {} diff --git a/tests/ui/parser/doc-before-mod-rbrace.stderr b/tests/ui/parser/doc-before-mod-rbrace.stderr new file mode 100644 index 000000000..d5749c66c --- /dev/null +++ b/tests/ui/parser/doc-before-mod-rbrace.stderr @@ -0,0 +1,8 @@ +error: expected item after doc comment + --> $DIR/doc-before-mod-rbrace.rs:2:5 + | +LL | /// document + | ^^^^^^^^^^^^ this doc comment doesn't document anything + +error: aborting due to previous error + diff --git a/tests/ui/parser/doc-before-rbrace.rs b/tests/ui/parser/doc-before-rbrace.rs new file mode 100644 index 000000000..570306f2c --- /dev/null +++ b/tests/ui/parser/doc-before-rbrace.rs @@ -0,0 +1,5 @@ +fn main() { + println!("Hi"); /// hi + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` +} diff --git a/tests/ui/parser/doc-before-rbrace.stderr b/tests/ui/parser/doc-before-rbrace.stderr new file mode 100644 index 000000000..4d4741dfe --- /dev/null +++ b/tests/ui/parser/doc-before-rbrace.stderr @@ -0,0 +1,11 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-rbrace.rs:2:21 + | +LL | println!("Hi"); /// hi + | ^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-semi.rs b/tests/ui/parser/doc-before-semi.rs new file mode 100644 index 000000000..444b5874e --- /dev/null +++ b/tests/ui/parser/doc-before-semi.rs @@ -0,0 +1,6 @@ +fn main() { + /// hi + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` + ; +} diff --git a/tests/ui/parser/doc-before-semi.stderr b/tests/ui/parser/doc-before-semi.stderr new file mode 100644 index 000000000..a879e13ff --- /dev/null +++ b/tests/ui/parser/doc-before-semi.stderr @@ -0,0 +1,11 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-semi.rs:2:5 + | +LL | /// hi + | ^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-struct-rbrace-1.rs b/tests/ui/parser/doc-before-struct-rbrace-1.rs new file mode 100644 index 000000000..0c8d90c3b --- /dev/null +++ b/tests/ui/parser/doc-before-struct-rbrace-1.rs @@ -0,0 +1,10 @@ +struct X { + a: u8, + /// document + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` +} + +fn main() { + let y = X {a: 1}; +} diff --git a/tests/ui/parser/doc-before-struct-rbrace-1.stderr b/tests/ui/parser/doc-before-struct-rbrace-1.stderr new file mode 100644 index 000000000..94934f734 --- /dev/null +++ b/tests/ui/parser/doc-before-struct-rbrace-1.stderr @@ -0,0 +1,14 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-struct-rbrace-1.rs:3:5 + | +LL | struct X { + | - while parsing this struct +LL | a: u8, +LL | /// document + | ^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-before-struct-rbrace-2.rs b/tests/ui/parser/doc-before-struct-rbrace-2.rs new file mode 100644 index 000000000..2b2aadf79 --- /dev/null +++ b/tests/ui/parser/doc-before-struct-rbrace-2.rs @@ -0,0 +1,9 @@ +struct X { + a: u8 /// document + //~^ ERROR found a documentation comment that doesn't document anything + //~| HELP if a comment was intended use `//` +} + +fn main() { + let y = X {a: 1}; +} diff --git a/tests/ui/parser/doc-before-struct-rbrace-2.stderr b/tests/ui/parser/doc-before-struct-rbrace-2.stderr new file mode 100644 index 000000000..6b5c8c1f8 --- /dev/null +++ b/tests/ui/parser/doc-before-struct-rbrace-2.stderr @@ -0,0 +1,11 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-struct-rbrace-2.rs:2:11 + | +LL | a: u8 /// document + | ^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/doc-comment-in-if-statement.rs b/tests/ui/parser/doc-comment-in-if-statement.rs new file mode 100644 index 000000000..343eac1b8 --- /dev/null +++ b/tests/ui/parser/doc-comment-in-if-statement.rs @@ -0,0 +1,5 @@ +fn main() { + if true /*!*/ {} + //~^ ERROR outer attributes are not allowed on + //~| ERROR expected outer doc comment +} diff --git a/tests/ui/parser/doc-comment-in-if-statement.stderr b/tests/ui/parser/doc-comment-in-if-statement.stderr new file mode 100644 index 000000000..fc0bc5073 --- /dev/null +++ b/tests/ui/parser/doc-comment-in-if-statement.stderr @@ -0,0 +1,25 @@ +error[E0753]: expected outer doc comment + --> $DIR/doc-comment-in-if-statement.rs:2:13 + | +LL | if true /*!*/ {} + | ^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - if true /*!*/ {} +LL + if true /**/ {} + | + +error: outer attributes are not allowed on `if` and `else` branches + --> $DIR/doc-comment-in-if-statement.rs:2:13 + | +LL | if true /*!*/ {} + | -- ^^^^^ -- the attributes are attached to this branch + | | | + | | help: remove the attributes + | the branch belongs to this `if` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0753`. diff --git a/tests/ui/parser/doc-comment-in-stmt.rs b/tests/ui/parser/doc-comment-in-stmt.rs new file mode 100644 index 000000000..b02df1321 --- /dev/null +++ b/tests/ui/parser/doc-comment-in-stmt.rs @@ -0,0 +1,20 @@ +fn foo() -> bool { + false + //!self.allow_ty_infer() + //~^ ERROR found doc comment +} + +fn bar() -> bool { + false + /*! bar */ //~ ERROR found doc comment +} + +fn baz() -> i32 { + 1 /** baz */ //~ ERROR found doc comment +} + +fn quux() -> i32 { + 2 /*! quux */ //~ ERROR found doc comment +} + +fn main() {} diff --git a/tests/ui/parser/doc-comment-in-stmt.stderr b/tests/ui/parser/doc-comment-in-stmt.stderr new file mode 100644 index 000000000..febfb600c --- /dev/null +++ b/tests/ui/parser/doc-comment-in-stmt.stderr @@ -0,0 +1,50 @@ +error: expected one of `.`, `;`, `?`, `}`, or an operator, found doc comment `//!self.allow_ty_infer()` + --> $DIR/doc-comment-in-stmt.rs:3:5 + | +LL | false + | - expected one of `.`, `;`, `?`, `}`, or an operator +LL | //!self.allow_ty_infer() + | ^^^^^^^^^^^^^^^^^^^^^^^^ unexpected token + | +help: add a space before `!` to use a regular comment + | +LL | // !self.allow_ty_infer() + | ~~~~ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found doc comment `/*! bar */` + --> $DIR/doc-comment-in-stmt.rs:9:5 + | +LL | false + | - expected one of `.`, `;`, `?`, `}`, or an operator +LL | /*! bar */ + | ^^^^^^^^^^ unexpected token + | +help: add a space before `!` to use a regular comment + | +LL | /* ! bar */ + | ~~~~ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found doc comment `/** baz */` + --> $DIR/doc-comment-in-stmt.rs:13:7 + | +LL | 1 /** baz */ + | ^^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + | +help: add a space before `*` to use a regular comment + | +LL | 1 /* * baz */ + | ~~~~ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found doc comment `/*! quux */` + --> $DIR/doc-comment-in-stmt.rs:17:7 + | +LL | 2 /*! quux */ + | ^^^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + | +help: add a space before `!` to use a regular comment + | +LL | 2 /* ! quux */ + | ~~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/doc-inside-trait-item.rs b/tests/ui/parser/doc-inside-trait-item.rs new file mode 100644 index 000000000..87b501bd2 --- /dev/null +++ b/tests/ui/parser/doc-inside-trait-item.rs @@ -0,0 +1,6 @@ +trait User{ + fn test(); + /// empty doc + //~^ ERROR found a documentation comment that doesn't document anything +} +fn main() {} diff --git a/tests/ui/parser/doc-inside-trait-item.stderr b/tests/ui/parser/doc-inside-trait-item.stderr new file mode 100644 index 000000000..900124adc --- /dev/null +++ b/tests/ui/parser/doc-inside-trait-item.stderr @@ -0,0 +1,11 @@ +error[E0584]: found a documentation comment that doesn't document anything + --> $DIR/doc-inside-trait-item.rs:3:5 + | +LL | /// empty doc + | ^^^^^^^^^^^^^ this doc comment doesn't document anything + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0584`. diff --git a/tests/ui/parser/dotdotdot-expr.rs b/tests/ui/parser/dotdotdot-expr.rs new file mode 100644 index 000000000..d842fb6e0 --- /dev/null +++ b/tests/ui/parser/dotdotdot-expr.rs @@ -0,0 +1,4 @@ +fn main() { + let _redemptive = 1...21; + //~^ ERROR unexpected token +} diff --git a/tests/ui/parser/dotdotdot-expr.stderr b/tests/ui/parser/dotdotdot-expr.stderr new file mode 100644 index 000000000..e7203f24d --- /dev/null +++ b/tests/ui/parser/dotdotdot-expr.stderr @@ -0,0 +1,17 @@ +error: unexpected token: `...` + --> $DIR/dotdotdot-expr.rs:2:24 + | +LL | let _redemptive = 1...21; + | ^^^ + | +help: use `..` for an exclusive range + | +LL | let _redemptive = 1..21; + | ~~ +help: or `..=` for an inclusive range + | +LL | let _redemptive = 1..=21; + | ~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/double-pointer.rs b/tests/ui/parser/double-pointer.rs new file mode 100644 index 000000000..54d34db4a --- /dev/null +++ b/tests/ui/parser/double-pointer.rs @@ -0,0 +1,7 @@ +fn main() { + let x: i32 = 5; + let ptr: *const i32 = &x; + let dptr: **const i32 = &ptr; + //~^ ERROR expected `mut` or `const` keyword in raw pointer type + //~| HELP add `mut` or `const` here +} diff --git a/tests/ui/parser/double-pointer.stderr b/tests/ui/parser/double-pointer.stderr new file mode 100644 index 000000000..28037f932 --- /dev/null +++ b/tests/ui/parser/double-pointer.stderr @@ -0,0 +1,15 @@ +error: expected `mut` or `const` keyword in raw pointer type + --> $DIR/double-pointer.rs:4:15 + | +LL | let dptr: **const i32 = &ptr; + | ^ + | +help: add `mut` or `const` here + | +LL | let dptr: *const *const i32 = &ptr; + | +++++ +LL | let dptr: *mut *const i32 = &ptr; + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/duplicate-visibility.rs b/tests/ui/parser/duplicate-visibility.rs new file mode 100644 index 000000000..54955944c --- /dev/null +++ b/tests/ui/parser/duplicate-visibility.rs @@ -0,0 +1,9 @@ +fn main() {} + +extern "C" { //~ NOTE while parsing this item list starting here + pub pub fn foo(); + //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub` + //~| NOTE expected one of 8 possible tokens + //~| HELP there is already a visibility modifier, remove one + //~| NOTE explicit visibility first seen here +} //~ NOTE the item list ends here diff --git a/tests/ui/parser/duplicate-visibility.stderr b/tests/ui/parser/duplicate-visibility.stderr new file mode 100644 index 000000000..8ecebf01f --- /dev/null +++ b/tests/ui/parser/duplicate-visibility.stderr @@ -0,0 +1,22 @@ +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub` + --> $DIR/duplicate-visibility.rs:4:9 + | +LL | extern "C" { + | - while parsing this item list starting here +LL | pub pub fn foo(); + | ^^^ + | | + | expected one of 8 possible tokens + | help: there is already a visibility modifier, remove one +... +LL | } + | - the item list ends here + | +note: explicit visibility first seen here + --> $DIR/duplicate-visibility.rs:4:5 + | +LL | pub pub fn foo(); + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/duplicate-where-clauses.rs b/tests/ui/parser/duplicate-where-clauses.rs new file mode 100644 index 000000000..9eb2ffb06 --- /dev/null +++ b/tests/ui/parser/duplicate-where-clauses.rs @@ -0,0 +1,19 @@ +struct A where (): Sized where (): Sized {} +//~^ ERROR cannot define duplicate `where` clauses on an item + +fn b() where (): Sized where (): Sized {} +//~^ ERROR cannot define duplicate `where` clauses on an item + +enum C where (): Sized where (): Sized {} +//~^ ERROR cannot define duplicate `where` clauses on an item + +struct D where (): Sized, where (): Sized {} +//~^ ERROR cannot define duplicate `where` clauses on an item + +fn e() where (): Sized, where (): Sized {} +//~^ ERROR cannot define duplicate `where` clauses on an item + +enum F where (): Sized, where (): Sized {} +//~^ ERROR cannot define duplicate `where` clauses on an item + +fn main() {} diff --git a/tests/ui/parser/duplicate-where-clauses.stderr b/tests/ui/parser/duplicate-where-clauses.stderr new file mode 100644 index 000000000..8250d4f1e --- /dev/null +++ b/tests/ui/parser/duplicate-where-clauses.stderr @@ -0,0 +1,80 @@ +error: cannot define duplicate `where` clauses on an item + --> $DIR/duplicate-where-clauses.rs:1:32 + | +LL | struct A where (): Sized where (): Sized {} + | - ^ + | | + | previous `where` clause starts here + | +help: consider joining the two `where` clauses into one + | +LL | struct A where (): Sized, (): Sized {} + | ~ + +error: cannot define duplicate `where` clauses on an item + --> $DIR/duplicate-where-clauses.rs:4:30 + | +LL | fn b() where (): Sized where (): Sized {} + | - ^ + | | + | previous `where` clause starts here + | +help: consider joining the two `where` clauses into one + | +LL | fn b() where (): Sized, (): Sized {} + | ~ + +error: cannot define duplicate `where` clauses on an item + --> $DIR/duplicate-where-clauses.rs:7:30 + | +LL | enum C where (): Sized where (): Sized {} + | - ^ + | | + | previous `where` clause starts here + | +help: consider joining the two `where` clauses into one + | +LL | enum C where (): Sized, (): Sized {} + | ~ + +error: cannot define duplicate `where` clauses on an item + --> $DIR/duplicate-where-clauses.rs:10:33 + | +LL | struct D where (): Sized, where (): Sized {} + | - ^ + | | + | previous `where` clause starts here + | +help: consider joining the two `where` clauses into one + | +LL | struct D where (): Sized, (): Sized {} + | ~ + +error: cannot define duplicate `where` clauses on an item + --> $DIR/duplicate-where-clauses.rs:13:31 + | +LL | fn e() where (): Sized, where (): Sized {} + | - ^ + | | + | previous `where` clause starts here + | +help: consider joining the two `where` clauses into one + | +LL | fn e() where (): Sized, (): Sized {} + | ~ + +error: cannot define duplicate `where` clauses on an item + --> $DIR/duplicate-where-clauses.rs:16:31 + | +LL | enum F where (): Sized, where (): Sized {} + | - ^ + | | + | previous `where` clause starts here + | +help: consider joining the two `where` clauses into one + | +LL | enum F where (): Sized, (): Sized {} + | ~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs new file mode 100644 index 000000000..d2b02cc2a --- /dev/null +++ b/tests/ui/parser/dyn-trait-compatibility.rs @@ -0,0 +1,14 @@ +type A0 = dyn; +//~^ ERROR cannot find type `dyn` in this scope +type A1 = dyn::dyn; +//~^ ERROR use of undeclared crate or module `dyn` +type A2 = dyn; +//~^ ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +type A3 = dyn<::dyn>; +//~^ ERROR cannot find type `dyn` in this scope +//~| ERROR cannot find type `dyn` in this scope +//~| ERROR use of undeclared crate or module `dyn` + +fn main() {} diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr new file mode 100644 index 000000000..0cae01bd1 --- /dev/null +++ b/tests/ui/parser/dyn-trait-compatibility.stderr @@ -0,0 +1,52 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `dyn` + --> $DIR/dyn-trait-compatibility.rs:3:11 + | +LL | type A1 = dyn::dyn; + | ^^^ use of undeclared crate or module `dyn` + +error[E0433]: failed to resolve: use of undeclared crate or module `dyn` + --> $DIR/dyn-trait-compatibility.rs:9:23 + | +LL | type A3 = dyn<::dyn>; + | ^^^ use of undeclared crate or module `dyn` + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:1:11 + | +LL | type A0 = dyn; + | ^^^ not found in this scope + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:5:11 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:5:15 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:5:20 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:9:11 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:9:16 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0412, E0433. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/else-no-if.rs b/tests/ui/parser/else-no-if.rs new file mode 100644 index 000000000..f0b40ecde --- /dev/null +++ b/tests/ui/parser/else-no-if.rs @@ -0,0 +1,32 @@ +fn foo() { + if true { + } else false { + //~^ ERROR expected `{`, found keyword `false` + } +} + +fn foo2() { + if true { + } else falsy() { + //~^ ERROR expected `{`, found `falsy` + } +} + +fn foo3() { + if true { + } else falsy(); + //~^ ERROR expected `{`, found `falsy` +} + +fn foo4() { + if true { + } else loop{} + //~^ ERROR expected `{`, found keyword `loop` + {} +} + +fn falsy() -> bool { + false +} + +fn main() {} diff --git a/tests/ui/parser/else-no-if.stderr b/tests/ui/parser/else-no-if.stderr new file mode 100644 index 000000000..b9c1a7527 --- /dev/null +++ b/tests/ui/parser/else-no-if.stderr @@ -0,0 +1,50 @@ +error: expected `{`, found keyword `false` + --> $DIR/else-no-if.rs:3:12 + | +LL | } else false { + | ---- ^^^^^ + | | + | expected an `if` or a block after this `else` + | +help: add an `if` if this is the condition of a chained `else if` statement + | +LL | } else if false { + | ++ + +error: expected `{`, found `falsy` + --> $DIR/else-no-if.rs:10:12 + | +LL | } else falsy() { + | ---- ^^^^^ + | | + | expected an `if` or a block after this `else` + | +help: add an `if` if this is the condition of a chained `else if` statement + | +LL | } else if falsy() { + | ++ + +error: expected `{`, found `falsy` + --> $DIR/else-no-if.rs:17:12 + | +LL | } else falsy(); + | ^^^^^ expected `{` + | +help: try placing this code inside a block + | +LL | } else { falsy() }; + | + + + +error: expected `{`, found keyword `loop` + --> $DIR/else-no-if.rs:23:12 + | +LL | } else loop{} + | ^^^^ expected `{` + | +help: try placing this code inside a block + | +LL | } else { loop{} } + | + + + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/emoji-identifiers.rs b/tests/ui/parser/emoji-identifiers.rs new file mode 100644 index 000000000..b50c046bc --- /dev/null +++ b/tests/ui/parser/emoji-identifiers.rs @@ -0,0 +1,19 @@ +struct ABig👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§Family; //~ ERROR identifiers cannot contain emoji +struct 👀; //~ ERROR identifiers cannot contain emoji +impl 👀 { + fn full_of_✨() -> 👀 { //~ ERROR identifiers cannot contain emoji + 👀 + } +} +fn i_like_to_😅_a_lot() -> 👀 { //~ ERROR identifiers cannot contain emoji + 👀::full_of✨() //~ ERROR no function or associated item named `full_of✨` found for struct `👀` + //~^ ERROR identifiers cannot contain emoji +} +fn main() { + let _ = i_like_to_😄_a_lot() âž– 4; //~ ERROR cannot find function `i_like_to_😄_a_lot` in this scope + //~^ ERROR identifiers cannot contain emoji + //~| ERROR unknown start of token: \u{2796} + + let 🦀 = 1;//~ ERROR Ferris cannot be used as an identifier + dbg!(🦀); +} diff --git a/tests/ui/parser/emoji-identifiers.stderr b/tests/ui/parser/emoji-identifiers.stderr new file mode 100644 index 000000000..e645b68ba --- /dev/null +++ b/tests/ui/parser/emoji-identifiers.stderr @@ -0,0 +1,91 @@ +error: unknown start of token: \u{2796} + --> $DIR/emoji-identifiers.rs:13:33 + | +LL | let _ = i_like_to_😄_a_lot() âž– 4; + | ^^ + | +help: Unicode character 'âž–' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not + | +LL | let _ = i_like_to_😄_a_lot() - 4; + | ~ + +error: Ferris cannot be used as an identifier + --> $DIR/emoji-identifiers.rs:17:9 + | +LL | let 🦀 = 1; + | ^^ help: try using their name instead: `ferris` +LL | dbg!(🦀); + | ^^ + +error: identifiers cannot contain emoji: `ABig👩👩👧👧Family` + --> $DIR/emoji-identifiers.rs:1:8 + | +LL | struct ABig👩👩👧👧Family; + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emoji: `👀` + --> $DIR/emoji-identifiers.rs:2:8 + | +LL | struct 👀; + | ^^ +LL | impl 👀 { + | ^^ +LL | fn full_of_✨() -> 👀 { + | ^^ +LL | 👀 + | ^^ +... +LL | fn i_like_to_😅_a_lot() -> 👀 { + | ^^ +LL | 👀::full_of✨() + | ^^ + +error: identifiers cannot contain emoji: `full_of_✨` + --> $DIR/emoji-identifiers.rs:4:8 + | +LL | fn full_of_✨() -> 👀 { + | ^^^^^^^^^^ + +error: identifiers cannot contain emoji: `i_like_to_😅_a_lot` + --> $DIR/emoji-identifiers.rs:8:4 + | +LL | fn i_like_to_😅_a_lot() -> 👀 { + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emoji: `full_of✨` + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | 👀::full_of✨() + | ^^^^^^^^^ + +error: identifiers cannot contain emoji: `i_like_to_😄_a_lot` + --> $DIR/emoji-identifiers.rs:13:13 + | +LL | let _ = i_like_to_😄_a_lot() âž– 4; + | ^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `full_of✨` found for struct `👀` in the current scope + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | struct 👀; + | --------- function or associated item `full_of✨` not found for this struct +... +LL | 👀::full_of✨() + | ^^^^^^^^^ + | | + | function or associated item not found in `👀` + | help: there is an associated function with a similar name: `full_of_✨` + +error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope + --> $DIR/emoji-identifiers.rs:13:13 + | +LL | fn i_like_to_😅_a_lot() -> 👀 { + | ----------------------------- similarly named function `i_like_to_😅_a_lot` defined here +... +LL | let _ = i_like_to_😄_a_lot() âž– 4; + | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_😅_a_lot` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/empty-impl-semicolon.rs b/tests/ui/parser/empty-impl-semicolon.rs new file mode 100644 index 000000000..2485f5b85 --- /dev/null +++ b/tests/ui/parser/empty-impl-semicolon.rs @@ -0,0 +1,4 @@ +struct Foo; +impl Foo; //~ ERROR expected `{}`, found `;` + +fn main() {} diff --git a/tests/ui/parser/empty-impl-semicolon.stderr b/tests/ui/parser/empty-impl-semicolon.stderr new file mode 100644 index 000000000..6ed309eba --- /dev/null +++ b/tests/ui/parser/empty-impl-semicolon.stderr @@ -0,0 +1,10 @@ +error: expected `{}`, found `;` + --> $DIR/empty-impl-semicolon.rs:2:9 + | +LL | impl Foo; + | ^ + | + = help: try using `{}` instead + +error: aborting due to previous error + diff --git a/tests/ui/parser/expr-as-stmt-2.rs b/tests/ui/parser/expr-as-stmt-2.rs new file mode 100644 index 000000000..3a18bdc3b --- /dev/null +++ b/tests/ui/parser/expr-as-stmt-2.rs @@ -0,0 +1,10 @@ +// This is not autofixable because we give extra suggestions to end the first expression with `;`. +fn foo(a: Option, b: Option) -> bool { + if let Some(x) = a { true } else { false } + //~^ ERROR mismatched types + //~| ERROR mismatched types + && //~ ERROR mismatched types + if let Some(y) = a { true } else { false } +} + +fn main() {} diff --git a/tests/ui/parser/expr-as-stmt-2.stderr b/tests/ui/parser/expr-as-stmt-2.stderr new file mode 100644 index 000000000..2b6314c38 --- /dev/null +++ b/tests/ui/parser/expr-as-stmt-2.stderr @@ -0,0 +1,46 @@ +error[E0308]: mismatched types + --> $DIR/expr-as-stmt-2.rs:3:26 + | +LL | if let Some(x) = a { true } else { false } + | ---------------------^^^^----------------- + | | | + | | expected `()`, found `bool` + | expected this to be `()` + | +help: you might have meant to return this value + | +LL | if let Some(x) = a { return true; } else { false } + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt-2.rs:3:40 + | +LL | if let Some(x) = a { true } else { false } + | -----------------------------------^^^^^-- + | | | + | | expected `()`, found `bool` + | expected this to be `()` + | +help: you might have meant to return this value + | +LL | if let Some(x) = a { true } else { return false; } + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt-2.rs:6:5 + | +LL | fn foo(a: Option, b: Option) -> bool { + | ---- expected `bool` because of return type +... +LL | / && +LL | | if let Some(y) = a { true } else { false } + | |______________________________________________^ expected `bool`, found `&&bool` + | +help: parentheses are required to parse this as an expression + | +LL | (if let Some(x) = a { true } else { false }) + | + + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/expr-as-stmt.fixed b/tests/ui/parser/expr-as-stmt.fixed new file mode 100644 index 000000000..b06f62794 --- /dev/null +++ b/tests/ui/parser/expr-as-stmt.fixed @@ -0,0 +1,79 @@ +// run-rustfix +// rustfix-only-machine-applicable +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +fn foo() -> i32 { + ({2}) + {2} //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn bar() -> i32 { + ({2}) + 2 //~ ERROR leading `+` is not supported + //~^ ERROR mismatched types +} + +fn zul() -> u32 { + let foo = 3; + ({ 42 }) + foo; //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types + 32 +} + +fn baz() -> i32 { + ({ 3 }) * 3 //~ ERROR type `{integer}` cannot be dereferenced + //~^ ERROR mismatched types +} + +fn moo(x: u32) -> bool { + (match x { + _ => 1, + }) > 0 //~ ERROR expected expression +} + +fn qux() -> u32 { + ({2}) - 2 //~ ERROR cannot apply unary operator `-` to type `u32` + //~^ ERROR mismatched types +} + +fn space_cadet() -> bool { + ({ true }) | { true } //~ ERROR E0308 + //~^ ERROR expected parameter name +} + +fn revenge_from_mars() -> bool { + ({ true }) && { true } //~ ERROR E0308 + //~^ ERROR mismatched types +} + +fn attack_from_mars() -> bool { + ({ true }) || { true } //~ ERROR E0308 + //~^ ERROR mismatched types +} + +// This gets corrected by adding a semicolon, instead of parens. +// It's placed here to help keep track of the way this diagnostic +// needs to interact with type checking to avoid MachineApplicable +// suggestions that actually break stuff. +// +// If you're wondering what happens if that `foo()` is a `true` like +// all the ones above use? Nothing. It makes neither suggestion in +// that case. +fn asteroids() -> impl FnOnce() -> bool { + { foo(); } || { true } //~ ERROR E0308 +} + +// https://github.com/rust-lang/rust/issues/105179 +fn r#match() -> i32 { + (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +// https://github.com/rust-lang/rust/issues/102171 +fn r#unsafe() -> i32 { + (unsafe { 1 }) + unsafe { 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/parser/expr-as-stmt.rs b/tests/ui/parser/expr-as-stmt.rs new file mode 100644 index 000000000..b39d2b886 --- /dev/null +++ b/tests/ui/parser/expr-as-stmt.rs @@ -0,0 +1,79 @@ +// run-rustfix +// rustfix-only-machine-applicable +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +fn foo() -> i32 { + {2} + {2} //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn bar() -> i32 { + {2} + 2 //~ ERROR leading `+` is not supported + //~^ ERROR mismatched types +} + +fn zul() -> u32 { + let foo = 3; + { 42 } + foo; //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types + 32 +} + +fn baz() -> i32 { + { 3 } * 3 //~ ERROR type `{integer}` cannot be dereferenced + //~^ ERROR mismatched types +} + +fn moo(x: u32) -> bool { + match x { + _ => 1, + } > 0 //~ ERROR expected expression +} + +fn qux() -> u32 { + {2} - 2 //~ ERROR cannot apply unary operator `-` to type `u32` + //~^ ERROR mismatched types +} + +fn space_cadet() -> bool { + { true } | { true } //~ ERROR E0308 + //~^ ERROR expected parameter name +} + +fn revenge_from_mars() -> bool { + { true } && { true } //~ ERROR E0308 + //~^ ERROR mismatched types +} + +fn attack_from_mars() -> bool { + { true } || { true } //~ ERROR E0308 + //~^ ERROR mismatched types +} + +// This gets corrected by adding a semicolon, instead of parens. +// It's placed here to help keep track of the way this diagnostic +// needs to interact with type checking to avoid MachineApplicable +// suggestions that actually break stuff. +// +// If you're wondering what happens if that `foo()` is a `true` like +// all the ones above use? Nothing. It makes neither suggestion in +// that case. +fn asteroids() -> impl FnOnce() -> bool { + { foo() } || { true } //~ ERROR E0308 +} + +// https://github.com/rust-lang/rust/issues/105179 +fn r#match() -> i32 { + match () { () => 1 } + match () { () => 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +// https://github.com/rust-lang/rust/issues/102171 +fn r#unsafe() -> i32 { + unsafe { 1 } + unsafe { 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/parser/expr-as-stmt.stderr b/tests/ui/parser/expr-as-stmt.stderr new file mode 100644 index 000000000..18c8b0b7c --- /dev/null +++ b/tests/ui/parser/expr-as-stmt.stderr @@ -0,0 +1,248 @@ +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:8:9 + | +LL | {2} + {2} + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL | ({2}) + {2} + | + + + +error: leading `+` is not supported + --> $DIR/expr-as-stmt.rs:13:9 + | +LL | {2} + 2 + | ^ unexpected `+` + | +help: parentheses are required to parse this as an expression + | +LL | ({2}) + 2 + | + + + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:19:12 + | +LL | { 42 } + foo; + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL | ({ 42 }) + foo; + | + + + +error: expected expression, found `>` + --> $DIR/expr-as-stmt.rs:32:7 + | +LL | } > 0 + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL ~ (match x { +LL | _ => 1, +LL ~ }) > 0 + | + +error: expected parameter name, found `{` + --> $DIR/expr-as-stmt.rs:41:16 + | +LL | { true } | { true } + | ^ expected parameter name + | +help: parentheses are required to parse this as an expression + | +LL | ({ true }) | { true } + | + + + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:69:26 + | +LL | match () { () => 1 } + match () { () => 1 } + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL | (match () { () => 1 }) + match () { () => 1 } + | + + + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:75:18 + | +LL | unsafe { 1 } + unsafe { 1 } + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL | (unsafe { 1 }) + unsafe { 1 } + | + + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:64:7 + | +LL | { foo() } || { true } + | ^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `i32` + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:8:6 + | +LL | {2} + {2} + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | {return 2;} + {2} + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:13:6 + | +LL | {2} + 2 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | {return 2;} + 2 + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:19:7 + | +LL | { 42 } + foo; + | ^^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | { return 42; } + foo; + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:25:7 + | +LL | { 3 } * 3 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | { return 3; } * 3 + | ++++++ + + +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/expr-as-stmt.rs:25:11 + | +LL | { 3 } * 3 + | ^^^ + | +help: parentheses are required to parse this as an expression + | +LL | ({ 3 }) * 3 + | + + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:36:6 + | +LL | {2} - 2 + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | {return 2;} - 2 + | ++++++ + + +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/expr-as-stmt.rs:36:9 + | +LL | {2} - 2 + | ^^^ cannot apply unary operator `-` + | +help: parentheses are required to parse this as an expression + | +LL | ({2}) - 2 + | + + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:41:7 + | +LL | { true } | { true } + | ^^^^ expected `()`, found `bool` + | +help: you might have meant to return this value + | +LL | { return true; } | { true } + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:46:7 + | +LL | { true } && { true } + | ^^^^ expected `()`, found `bool` + | +help: you might have meant to return this value + | +LL | { return true; } && { true } + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:46:14 + | +LL | fn revenge_from_mars() -> bool { + | ---- expected `bool` because of return type +LL | { true } && { true } + | ^^^^^^^^^^^ expected `bool`, found `&&bool` + | +help: parentheses are required to parse this as an expression + | +LL | ({ true }) && { true } + | + + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:51:7 + | +LL | { true } || { true } + | ^^^^ expected `()`, found `bool` + | +help: you might have meant to return this value + | +LL | { return true; } || { true } + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:51:14 + | +LL | fn attack_from_mars() -> bool { + | ---- expected `bool` because of return type +LL | { true } || { true } + | ^^^^^^^^^^^ expected `bool`, found closure + | + = note: expected type `bool` + found closure `[closure@$DIR/expr-as-stmt.rs:51:14: 51:16]` +help: parentheses are required to parse this as an expression + | +LL | ({ true }) || { true } + | + + + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:69:5 + | +LL | match () { () => 1 } + match () { () => 1 } + | ^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here + | | + | expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:75:14 + | +LL | unsafe { 1 } + unsafe { 1 } + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | unsafe { return 1; } + unsafe { 1 } + | ++++++ + + +error: aborting due to 22 previous errors + +Some errors have detailed explanations: E0308, E0600, E0614. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/extern-abi-from-mac-literal-frag.rs b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs new file mode 100644 index 000000000..8f5d7f4f7 --- /dev/null +++ b/tests/ui/parser/extern-abi-from-mac-literal-frag.rs @@ -0,0 +1,47 @@ +#![allow(clashing_extern_declarations)] +// check-pass + +// In this test we check that the parser accepts an ABI string when it +// comes from a macro `literal` or `expr` fragment as opposed to a hardcoded string. + +fn main() {} + +macro_rules! abi_from_lit_frag { + ($abi:literal) => { + extern $abi { + fn _import(); + } + + extern $abi fn _export() {} + + type _PTR = extern $abi fn(); + } +} + +macro_rules! abi_from_expr_frag { + ($abi:expr) => { + extern $abi { + fn _import(); + } + + extern $abi fn _export() {} + + type _PTR = extern $abi fn(); + }; +} + +mod rust { + abi_from_lit_frag!("Rust"); +} + +mod c { + abi_from_lit_frag!("C"); +} + +mod rust_expr { + abi_from_expr_frag!("Rust"); +} + +mod c_expr { + abi_from_expr_frag!("C"); +} diff --git a/tests/ui/parser/extern-abi-raw-strings.rs b/tests/ui/parser/extern-abi-raw-strings.rs new file mode 100644 index 000000000..fad855a21 --- /dev/null +++ b/tests/ui/parser/extern-abi-raw-strings.rs @@ -0,0 +1,13 @@ +// check-pass + +// Check that the string literal in `extern lit` will accept raw strings. + +fn main() {} + +extern r#"C"# fn foo() {} + +extern r#"C"# { + fn bar(); +} + +type T = extern r#"C"# fn(); diff --git a/tests/ui/parser/extern-abi-string-escaping.rs b/tests/ui/parser/extern-abi-string-escaping.rs new file mode 100644 index 000000000..87bd31aab --- /dev/null +++ b/tests/ui/parser/extern-abi-string-escaping.rs @@ -0,0 +1,13 @@ +// check-pass + +// Check that the string literal in `extern lit` will escapes. + +fn main() {} + +extern "\x43" fn foo() {} + +extern "\x43" { + fn bar(); +} + +type T = extern "\x43" fn(); diff --git a/tests/ui/parser/extern-abi-syntactic.rs b/tests/ui/parser/extern-abi-syntactic.rs new file mode 100644 index 000000000..7d2bbfe8a --- /dev/null +++ b/tests/ui/parser/extern-abi-syntactic.rs @@ -0,0 +1,17 @@ +// check-pass + +// Check that from the grammar's point of view, +// the specific set of ABIs is not part of it. + +fn main() {} + +#[cfg(FALSE)] +extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn foo() {} + +#[cfg(FALSE)] +extern "some_abi_that_we_are_sure_does_not_exist_semantically" { + fn foo(); +} + +#[cfg(FALSE)] +type T = extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn(); diff --git a/tests/ui/parser/extern-crate-async.rs b/tests/ui/parser/extern-crate-async.rs new file mode 100644 index 000000000..6a54ac7f4 --- /dev/null +++ b/tests/ui/parser/extern-crate-async.rs @@ -0,0 +1,12 @@ +// Make sure that we don't parse `extern crate async` +// the front matter of a function leading us astray. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern crate async; + +#[cfg(FALSE)] +extern crate async as something_else; diff --git a/tests/ui/parser/extern-crate-unexpected-token.rs b/tests/ui/parser/extern-crate-unexpected-token.rs new file mode 100644 index 000000000..7687f5e64 --- /dev/null +++ b/tests/ui/parser/extern-crate-unexpected-token.rs @@ -0,0 +1 @@ +extern crte foo; //~ ERROR expected one of `crate` or `{`, found `crte` diff --git a/tests/ui/parser/extern-crate-unexpected-token.stderr b/tests/ui/parser/extern-crate-unexpected-token.stderr new file mode 100644 index 000000000..e9d287ac0 --- /dev/null +++ b/tests/ui/parser/extern-crate-unexpected-token.stderr @@ -0,0 +1,8 @@ +error: expected one of `crate` or `{`, found `crte` + --> $DIR/extern-crate-unexpected-token.rs:1:8 + | +LL | extern crte foo; + | ^^^^ expected one of `crate` or `{` + +error: aborting due to previous error + diff --git a/tests/ui/parser/extern-expected-fn-or-brace.rs b/tests/ui/parser/extern-expected-fn-or-brace.rs new file mode 100644 index 000000000..1dcea1744 --- /dev/null +++ b/tests/ui/parser/extern-expected-fn-or-brace.rs @@ -0,0 +1,3 @@ +// Verifies that the expected token errors for `extern crate` are raised. + +extern "C" mod foo; //~ERROR expected `{`, found keyword `mod` diff --git a/tests/ui/parser/extern-expected-fn-or-brace.stderr b/tests/ui/parser/extern-expected-fn-or-brace.stderr new file mode 100644 index 000000000..258a2c268 --- /dev/null +++ b/tests/ui/parser/extern-expected-fn-or-brace.stderr @@ -0,0 +1,8 @@ +error: expected `{`, found keyword `mod` + --> $DIR/extern-expected-fn-or-brace.rs:3:12 + | +LL | extern "C" mod foo; + | ^^^ expected `{` + +error: aborting due to previous error + diff --git a/tests/ui/parser/extern-foreign-crate.rs b/tests/ui/parser/extern-foreign-crate.rs new file mode 100644 index 000000000..a5da77dc7 --- /dev/null +++ b/tests/ui/parser/extern-foreign-crate.rs @@ -0,0 +1,4 @@ +// Verifies that the expected token errors for `extern crate` are +// raised + +extern crate foo {} //~ERROR expected one of `;` or `as`, found `{` diff --git a/tests/ui/parser/extern-foreign-crate.stderr b/tests/ui/parser/extern-foreign-crate.stderr new file mode 100644 index 000000000..eb75c0fc9 --- /dev/null +++ b/tests/ui/parser/extern-foreign-crate.stderr @@ -0,0 +1,8 @@ +error: expected one of `;` or `as`, found `{` + --> $DIR/extern-foreign-crate.rs:4:18 + | +LL | extern crate foo {} + | ^ expected one of `;` or `as` + +error: aborting due to previous error + diff --git a/tests/ui/parser/extern-no-fn.rs b/tests/ui/parser/extern-no-fn.rs new file mode 100644 index 000000000..73568609c --- /dev/null +++ b/tests/ui/parser/extern-no-fn.rs @@ -0,0 +1,6 @@ +extern "C" { + f(); //~ ERROR expected one of `!` or `::`, found `(` +} + +fn main() { +} diff --git a/tests/ui/parser/extern-no-fn.stderr b/tests/ui/parser/extern-no-fn.stderr new file mode 100644 index 000000000..d9183d564 --- /dev/null +++ b/tests/ui/parser/extern-no-fn.stderr @@ -0,0 +1,12 @@ +error: expected one of `!` or `::`, found `(` + --> $DIR/extern-no-fn.rs:2:6 + | +LL | extern "C" { + | - while parsing this item list starting here +LL | f(); + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/float-field-interpolated.rs b/tests/ui/parser/float-field-interpolated.rs new file mode 100644 index 000000000..a30532035 --- /dev/null +++ b/tests/ui/parser/float-field-interpolated.rs @@ -0,0 +1,17 @@ +struct S(u8, (u8, u8)); + +macro_rules! generate_field_accesses { + ($a:tt, $b:literal, $c:expr) => { + let s = S(0, (0, 0)); + + s.$a; // OK + { s.$b; } //~ ERROR unexpected token: `1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + { s.$c; } //~ ERROR unexpected token: `1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + }; +} + +fn main() { + generate_field_accesses!(1.1, 1.1, 1.1); +} diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr new file mode 100644 index 000000000..664adb358 --- /dev/null +++ b/tests/ui/parser/float-field-interpolated.stderr @@ -0,0 +1,46 @@ +error: unexpected token: `1.1` + --> $DIR/float-field-interpolated.rs:8:13 + | +LL | { s.$b; } + | ^^ +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | --------------------------------------- in this macro invocation + | + = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + --> $DIR/float-field-interpolated.rs:8:13 + | +LL | { s.$b; } + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | --------------------------------------- in this macro invocation + | + = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected token: `1.1` + --> $DIR/float-field-interpolated.rs:10:13 + | +LL | { s.$c; } + | ^^ +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | --------------------------------------- in this macro invocation + | + = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + --> $DIR/float-field-interpolated.rs:10:13 + | +LL | { s.$c; } + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | --------------------------------------- in this macro invocation + | + = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/float-field.rs b/tests/ui/parser/float-field.rs new file mode 100644 index 000000000..eaa7465dc --- /dev/null +++ b/tests/ui/parser/float-field.rs @@ -0,0 +1,62 @@ +struct S(u8, (u8, u8)); + +fn main() { + let s = S(0, (0, 0)); + + s.1e1; //~ ERROR no field `1e1` on type `S` + s.1.; //~ ERROR unexpected token: `;` + s.1.1; + s.1.1e1; //~ ERROR no field `1e1` on type `(u8, u8)` + { s.1e+; } //~ ERROR unexpected token: `1e+` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+` + //~| ERROR expected at least one digit in exponent + { s.1e-; } //~ ERROR unexpected token: `1e-` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-` + //~| ERROR expected at least one digit in exponent + { s.1e+1; } //~ ERROR unexpected token: `1e+1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1` + { s.1e-1; } //~ ERROR unexpected token: `1e-1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1` + { s.1.1e+1; } //~ ERROR unexpected token: `1.1e+1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1` + { s.1.1e-1; } //~ ERROR unexpected token: `1.1e-1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1` + s.0x1e1; //~ ERROR no field `0x1e1` on type `S` + s.0x1.; //~ ERROR no field `0x1` on type `S` + //~| ERROR hexadecimal float literal is not supported + //~| ERROR unexpected token: `;` + s.0x1.1; //~ ERROR no field `0x1` on type `S` + //~| ERROR hexadecimal float literal is not supported + s.0x1.1e1; //~ ERROR no field `0x1` on type `S` + //~| ERROR hexadecimal float literal is not supported + { s.0x1e+; } //~ ERROR expected expression, found `;` + { s.0x1e-; } //~ ERROR expected expression, found `;` + s.0x1e+1; //~ ERROR no field `0x1e` on type `S` + s.0x1e-1; //~ ERROR no field `0x1e` on type `S` + { s.0x1.1e+1; } //~ ERROR unexpected token: `0x1.1e+1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1` + //~| ERROR hexadecimal float literal is not supported + { s.0x1.1e-1; } //~ ERROR unexpected token: `0x1.1e-1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1` + //~| ERROR hexadecimal float literal is not supported + s.1e1f32; //~ ERROR no field `1e1` on type `S` + //~| ERROR suffixes on a tuple index are invalid + s.1.f32; //~ ERROR no field `f32` on type `(u8, u8)` + s.1.1f32; //~ ERROR suffixes on a tuple index are invalid + s.1.1e1f32; //~ ERROR no field `1e1` on type `(u8, u8)` + //~| ERROR suffixes on a tuple index are invalid + { s.1e+f32; } //~ ERROR unexpected token: `1e+f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32` + //~| ERROR expected at least one digit in exponent + { s.1e-f32; } //~ ERROR unexpected token: `1e-f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32` + //~| ERROR expected at least one digit in exponent + { s.1e+1f32; } //~ ERROR unexpected token: `1e+1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32` + { s.1e-1f32; } //~ ERROR unexpected token: `1e-1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32` + { s.1.1e+1f32; } //~ ERROR unexpected token: `1.1e+1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32` + { s.1.1e-1f32; } //~ ERROR unexpected token: `1.1e-1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32` +} diff --git a/tests/ui/parser/float-field.stderr b/tests/ui/parser/float-field.stderr new file mode 100644 index 000000000..7090efc50 --- /dev/null +++ b/tests/ui/parser/float-field.stderr @@ -0,0 +1,349 @@ +error: expected at least one digit in exponent + --> $DIR/float-field.rs:10:9 + | +LL | { s.1e+; } + | ^^^ + +error: expected at least one digit in exponent + --> $DIR/float-field.rs:13:9 + | +LL | { s.1e-; } + | ^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:25:7 + | +LL | s.0x1.; + | ^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:28:7 + | +LL | s.0x1.1; + | ^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:30:7 + | +LL | s.0x1.1e1; + | ^^^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:36:9 + | +LL | { s.0x1.1e+1; } + | ^^^^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:39:9 + | +LL | { s.0x1.1e-1; } + | ^^^^^^^^ + +error: expected at least one digit in exponent + --> $DIR/float-field.rs:48:9 + | +LL | { s.1e+f32; } + | ^^^^^^ + +error: expected at least one digit in exponent + --> $DIR/float-field.rs:51:9 + | +LL | { s.1e-f32; } + | ^^^^^^ + +error: unexpected token: `;` + --> $DIR/float-field.rs:7:9 + | +LL | s.1.; + | ^ + +error: unexpected token: `1e+` + --> $DIR/float-field.rs:10:9 + | +LL | { s.1e+; } + | ^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+` + --> $DIR/float-field.rs:10:9 + | +LL | { s.1e+; } + | ^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-` + --> $DIR/float-field.rs:13:9 + | +LL | { s.1e-; } + | ^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-` + --> $DIR/float-field.rs:13:9 + | +LL | { s.1e-; } + | ^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e+1` + --> $DIR/float-field.rs:16:9 + | +LL | { s.1e+1; } + | ^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1` + --> $DIR/float-field.rs:16:9 + | +LL | { s.1e+1; } + | ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-1` + --> $DIR/float-field.rs:18:9 + | +LL | { s.1e-1; } + | ^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1` + --> $DIR/float-field.rs:18:9 + | +LL | { s.1e-1; } + | ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e+1` + --> $DIR/float-field.rs:20:9 + | +LL | { s.1.1e+1; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1` + --> $DIR/float-field.rs:20:9 + | +LL | { s.1.1e+1; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e-1` + --> $DIR/float-field.rs:22:9 + | +LL | { s.1.1e-1; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1` + --> $DIR/float-field.rs:22:9 + | +LL | { s.1.1e-1; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `;` + --> $DIR/float-field.rs:25:11 + | +LL | s.0x1.; + | ^ + +error: expected expression, found `;` + --> $DIR/float-field.rs:32:14 + | +LL | { s.0x1e+; } + | ^ expected expression + +error: expected expression, found `;` + --> $DIR/float-field.rs:33:14 + | +LL | { s.0x1e-; } + | ^ expected expression + +error: unexpected token: `0x1.1e+1` + --> $DIR/float-field.rs:36:9 + | +LL | { s.0x1.1e+1; } + | ^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1` + --> $DIR/float-field.rs:36:9 + | +LL | { s.0x1.1e+1; } + | ^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `0x1.1e-1` + --> $DIR/float-field.rs:39:9 + | +LL | { s.0x1.1e-1; } + | ^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1` + --> $DIR/float-field.rs:39:9 + | +LL | { s.0x1.1e-1; } + | ^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: suffixes on a tuple index are invalid + --> $DIR/float-field.rs:42:7 + | +LL | s.1e1f32; + | ^^^^^^ invalid suffix `f32` + +error: suffixes on a tuple index are invalid + --> $DIR/float-field.rs:45:7 + | +LL | s.1.1f32; + | ^^^^^^ invalid suffix `f32` + +error: suffixes on a tuple index are invalid + --> $DIR/float-field.rs:46:7 + | +LL | s.1.1e1f32; + | ^^^^^^^^ invalid suffix `f32` + +error: unexpected token: `1e+f32` + --> $DIR/float-field.rs:48:9 + | +LL | { s.1e+f32; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32` + --> $DIR/float-field.rs:48:9 + | +LL | { s.1e+f32; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-f32` + --> $DIR/float-field.rs:51:9 + | +LL | { s.1e-f32; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32` + --> $DIR/float-field.rs:51:9 + | +LL | { s.1e-f32; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e+1f32` + --> $DIR/float-field.rs:54:9 + | +LL | { s.1e+1f32; } + | ^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32` + --> $DIR/float-field.rs:54:9 + | +LL | { s.1e+1f32; } + | ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-1f32` + --> $DIR/float-field.rs:56:9 + | +LL | { s.1e-1f32; } + | ^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32` + --> $DIR/float-field.rs:56:9 + | +LL | { s.1e-1f32; } + | ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e+1f32` + --> $DIR/float-field.rs:58:9 + | +LL | { s.1.1e+1f32; } + | ^^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32` + --> $DIR/float-field.rs:58:9 + | +LL | { s.1.1e+1f32; } + | ^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e-1f32` + --> $DIR/float-field.rs:60:9 + | +LL | { s.1.1e-1f32; } + | ^^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32` + --> $DIR/float-field.rs:60:9 + | +LL | { s.1.1e-1f32; } + | ^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error[E0609]: no field `1e1` on type `S` + --> $DIR/float-field.rs:6:7 + | +LL | s.1e1; + | ^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `1e1` on type `(u8, u8)` + --> $DIR/float-field.rs:9:9 + | +LL | s.1.1e1; + | ^^^ + +error[E0609]: no field `0x1e1` on type `S` + --> $DIR/float-field.rs:24:7 + | +LL | s.0x1e1; + | ^^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1` on type `S` + --> $DIR/float-field.rs:25:7 + | +LL | s.0x1.; + | ^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1` on type `S` + --> $DIR/float-field.rs:28:7 + | +LL | s.0x1.1; + | ^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1` on type `S` + --> $DIR/float-field.rs:30:7 + | +LL | s.0x1.1e1; + | ^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1e` on type `S` + --> $DIR/float-field.rs:34:7 + | +LL | s.0x1e+1; + | ^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1e` on type `S` + --> $DIR/float-field.rs:35:7 + | +LL | s.0x1e-1; + | ^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `1e1` on type `S` + --> $DIR/float-field.rs:42:7 + | +LL | s.1e1f32; + | ^^^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `f32` on type `(u8, u8)` + --> $DIR/float-field.rs:44:9 + | +LL | s.1.f32; + | ^^^ + +error[E0609]: no field `1e1` on type `(u8, u8)` + --> $DIR/float-field.rs:46:7 + | +LL | s.1.1e1f32; + | ^^^^^^^^ + +error: aborting due to 55 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/parser/float-literals.rs b/tests/ui/parser/float-literals.rs new file mode 100644 index 000000000..1e9319fd2 --- /dev/null +++ b/tests/ui/parser/float-literals.rs @@ -0,0 +1,9 @@ +// build-pass +// ignore-tidy-linelength +// Regression test for #31109 and #31407. + +pub fn main() { + let _: f64 = 0.3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333; + + let _: f64 = 1234567890123456789012345678901234567890e-340; +} diff --git a/tests/ui/parser/fn-arg-doc-comment.rs b/tests/ui/parser/fn-arg-doc-comment.rs new file mode 100644 index 000000000..21d753ad0 --- /dev/null +++ b/tests/ui/parser/fn-arg-doc-comment.rs @@ -0,0 +1,30 @@ +pub fn f( //~ NOTE function defined here + /// Comment + //~^ ERROR documentation comments cannot be applied to function parameters + //~| NOTE doc comments are not allowed here + //~| NOTE + id: u8, + /// Other + //~^ ERROR documentation comments cannot be applied to function parameters + //~| NOTE doc comments are not allowed here + //~| NOTE + a: u8, +) {} + +fn bar(id: #[allow(dead_code)] i32) {} +//~^ ERROR attributes cannot be applied to a function parameter's type +//~| NOTE attributes are not allowed here +//~| NOTE function defined here +//~| NOTE + +fn main() { + // verify that the parser recovered and properly typechecked the args + f("", ""); + //~^ ERROR arguments to this function are incorrect + //~| NOTE expected `u8`, found `&str` + //~| NOTE expected `u8`, found `&str` + bar(""); + //~^ ERROR mismatched types + //~| NOTE arguments to this function are incorrect + //~| NOTE expected `i32`, found `&str` +} diff --git a/tests/ui/parser/fn-arg-doc-comment.stderr b/tests/ui/parser/fn-arg-doc-comment.stderr new file mode 100644 index 000000000..c8d7e2efe --- /dev/null +++ b/tests/ui/parser/fn-arg-doc-comment.stderr @@ -0,0 +1,61 @@ +error: attributes cannot be applied to a function parameter's type + --> $DIR/fn-arg-doc-comment.rs:14:12 + | +LL | fn bar(id: #[allow(dead_code)] i32) {} + | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/fn-arg-doc-comment.rs:2:5 + | +LL | /// Comment + | ^^^^^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/fn-arg-doc-comment.rs:7:5 + | +LL | /// Other + | ^^^^^^^^^ doc comments are not allowed here + +error[E0308]: arguments to this function are incorrect + --> $DIR/fn-arg-doc-comment.rs:22:5 + | +LL | f("", ""); + | ^ -- -- expected `u8`, found `&str` + | | + | expected `u8`, found `&str` + | +note: function defined here + --> $DIR/fn-arg-doc-comment.rs:1:8 + | +LL | pub fn f( + | ^ +LL | / /// Comment +LL | | +LL | | +LL | | +LL | | id: u8, + | |__________- +LL | / /// Other +LL | | +LL | | +LL | | +LL | | a: u8, + | |_________- + +error[E0308]: mismatched types + --> $DIR/fn-arg-doc-comment.rs:26:9 + | +LL | bar(""); + | --- ^^ expected `i32`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/fn-arg-doc-comment.rs:14:4 + | +LL | fn bar(id: #[allow(dead_code)] i32) {} + | ^^^ --------------------------- + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/fn-body-eq-expr-semi.rs b/tests/ui/parser/fn-body-eq-expr-semi.rs new file mode 100644 index 000000000..7127ba8da --- /dev/null +++ b/tests/ui/parser/fn-body-eq-expr-semi.rs @@ -0,0 +1,23 @@ +fn main() {} + +fn syntax() { + fn foo() = 42; //~ ERROR function body cannot be `= expression;` + fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;` +} + +extern "C" { + fn foo() = 42; //~ ERROR function body cannot be `= expression;` + //~^ ERROR incorrect function inside `extern` block + fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;` + //~^ ERROR incorrect function inside `extern` block +} + +trait Foo { + fn foo() = 42; //~ ERROR function body cannot be `= expression;` + fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;` +} + +impl Foo for () { + fn foo() = 42; //~ ERROR function body cannot be `= expression;` + fn bar() -> u8 = 42; //~ ERROR function body cannot be `= expression;` +} diff --git a/tests/ui/parser/fn-body-eq-expr-semi.stderr b/tests/ui/parser/fn-body-eq-expr-semi.stderr new file mode 100644 index 000000000..f1255d864 --- /dev/null +++ b/tests/ui/parser/fn-body-eq-expr-semi.stderr @@ -0,0 +1,117 @@ +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:4:14 + | +LL | fn foo() = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn foo() { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:5:20 + | +LL | fn bar() -> u8 = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn bar() -> u8 { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:9:14 + | +LL | fn foo() = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn foo() { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:11:20 + | +LL | fn bar() -> u8 = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn bar() -> u8 { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:16:14 + | +LL | fn foo() = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn foo() { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:17:20 + | +LL | fn bar() -> u8 = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn bar() -> u8 { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:21:14 + | +LL | fn foo() = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn foo() { 42 } + | ~ ~ + +error: function body cannot be `= expression;` + --> $DIR/fn-body-eq-expr-semi.rs:22:20 + | +LL | fn bar() -> u8 = 42; + | ^^^^^ + | +help: surround the expression with `{` and `}` instead of `=` and `;` + | +LL | fn bar() -> u8 { 42 } + | ~ ~ + +error: incorrect function inside `extern` block + --> $DIR/fn-body-eq-expr-semi.rs:9:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn foo() = 42; + | ^^^ ----- help: remove the invalid body: `;` + | | + | cannot have a body + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect function inside `extern` block + --> $DIR/fn-body-eq-expr-semi.rs:11:8 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +... +LL | fn bar() -> u8 = 42; + | ^^^ ----- help: remove the invalid body: `;` + | | + | cannot have a body + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 10 previous errors + diff --git a/tests/ui/parser/fn-body-optional-semantic-fail.rs b/tests/ui/parser/fn-body-optional-semantic-fail.rs new file mode 100644 index 000000000..12df48880 --- /dev/null +++ b/tests/ui/parser/fn-body-optional-semantic-fail.rs @@ -0,0 +1,27 @@ +// Tests the different rules for `fn` forms requiring the presence or lack of a body. + +fn main() { + fn f1(); //~ ERROR free function without a body + fn f2() {} // OK. + + trait X { + fn f1(); // OK. + fn f2() {} // OK. + } + + struct Y; + impl X for Y { + fn f1(); //~ ERROR associated function in `impl` without body + fn f2() {} // OK. + } + + impl Y { + fn f3(); //~ ERROR associated function in `impl` without body + fn f4() {} // OK. + } + + extern "C" { + fn f5(); // OK. + fn f6() {} //~ ERROR incorrect function inside `extern` block + } +} diff --git a/tests/ui/parser/fn-body-optional-semantic-fail.stderr b/tests/ui/parser/fn-body-optional-semantic-fail.stderr new file mode 100644 index 000000000..14bcd7c16 --- /dev/null +++ b/tests/ui/parser/fn-body-optional-semantic-fail.stderr @@ -0,0 +1,40 @@ +error: free function without a body + --> $DIR/fn-body-optional-semantic-fail.rs:4:5 + | +LL | fn f1(); + | ^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: associated function in `impl` without body + --> $DIR/fn-body-optional-semantic-fail.rs:14:9 + | +LL | fn f1(); + | ^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: associated function in `impl` without body + --> $DIR/fn-body-optional-semantic-fail.rs:19:9 + | +LL | fn f3(); + | ^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: incorrect function inside `extern` block + --> $DIR/fn-body-optional-semantic-fail.rs:25:12 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body +LL | fn f5(); // OK. +LL | fn f6() {} + | ^^ -- help: remove the invalid body: `;` + | | + | cannot have a body + | + = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/fn-body-optional-syntactic-pass.rs b/tests/ui/parser/fn-body-optional-syntactic-pass.rs new file mode 100644 index 000000000..f9dbebf0b --- /dev/null +++ b/tests/ui/parser/fn-body-optional-syntactic-pass.rs @@ -0,0 +1,31 @@ +// Ensures that all `fn` forms having or lacking a body are syntactically valid. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + fn f(); + fn f() {} + + trait X { + fn f(); + fn f() {} + } + + impl X for Y { + fn f(); + fn f() {} + } + + impl Y { + fn f(); + fn f() {} + } + + extern "C" { + fn f(); + fn f(); + } +} diff --git a/tests/ui/parser/fn-colon-return-type.rs b/tests/ui/parser/fn-colon-return-type.rs new file mode 100644 index 000000000..0001ef57c --- /dev/null +++ b/tests/ui/parser/fn-colon-return-type.rs @@ -0,0 +1,6 @@ +fn foo(x: i32): i32 { +//~^ ERROR return types are denoted using `->` + x +} + +fn main() {} diff --git a/tests/ui/parser/fn-colon-return-type.stderr b/tests/ui/parser/fn-colon-return-type.stderr new file mode 100644 index 000000000..1de918782 --- /dev/null +++ b/tests/ui/parser/fn-colon-return-type.stderr @@ -0,0 +1,8 @@ +error: return types are denoted using `->` + --> $DIR/fn-colon-return-type.rs:1:15 + | +LL | fn foo(x: i32): i32 { + | ^ help: use `->` instead + +error: aborting due to previous error + diff --git a/tests/ui/parser/fn-defined-using-def.rs b/tests/ui/parser/fn-defined-using-def.rs new file mode 100644 index 000000000..21da34c47 --- /dev/null +++ b/tests/ui/parser/fn-defined-using-def.rs @@ -0,0 +1,10 @@ +// Check what happens when `def` is used to define a function, instead of `fn` +// edition:2021 + +#![allow(dead_code)] + +def foo() {} +//~^ ERROR expected one of `!` or `::`, found `foo` +//~^^ HELP write `fn` instead of `def` to declare a function + +fn main() {} diff --git a/tests/ui/parser/fn-defined-using-def.stderr b/tests/ui/parser/fn-defined-using-def.stderr new file mode 100644 index 000000000..f34329012 --- /dev/null +++ b/tests/ui/parser/fn-defined-using-def.stderr @@ -0,0 +1,10 @@ +error: expected one of `!` or `::`, found `foo` + --> $DIR/fn-defined-using-def.rs:6:5 + | +LL | def foo() {} + | --- ^^^ expected one of `!` or `::` + | | + | help: write `fn` instead of `def` to declare a function + +error: aborting due to previous error + diff --git a/tests/ui/parser/fn-defined-using-fun.rs b/tests/ui/parser/fn-defined-using-fun.rs new file mode 100644 index 000000000..4f7460504 --- /dev/null +++ b/tests/ui/parser/fn-defined-using-fun.rs @@ -0,0 +1,10 @@ +// Check what happens when `fun` is used to define a function, instead of `fn` +// edition:2021 + +#![allow(dead_code)] + +fun foo() {} +//~^ ERROR expected one of `!` or `::`, found `foo` +//~^^ HELP write `fn` instead of `fun` to declare a function + +fn main() {} diff --git a/tests/ui/parser/fn-defined-using-fun.stderr b/tests/ui/parser/fn-defined-using-fun.stderr new file mode 100644 index 000000000..2f6cfff35 --- /dev/null +++ b/tests/ui/parser/fn-defined-using-fun.stderr @@ -0,0 +1,10 @@ +error: expected one of `!` or `::`, found `foo` + --> $DIR/fn-defined-using-fun.rs:6:5 + | +LL | fun foo() {} + | --- ^^^ expected one of `!` or `::` + | | + | help: write `fn` instead of `fun` to declare a function + +error: aborting due to previous error + diff --git a/tests/ui/parser/fn-defined-using-func.rs b/tests/ui/parser/fn-defined-using-func.rs new file mode 100644 index 000000000..2dce96fdc --- /dev/null +++ b/tests/ui/parser/fn-defined-using-func.rs @@ -0,0 +1,10 @@ +// Check what happens when `func` is used to define a function, instead of `fn` +// edition:2021 + +#![allow(dead_code)] + +func foo() {} +//~^ ERROR expected one of `!` or `::`, found `foo` +//~^^ HELP write `fn` instead of `func` to declare a function + +fn main() {} diff --git a/tests/ui/parser/fn-defined-using-func.stderr b/tests/ui/parser/fn-defined-using-func.stderr new file mode 100644 index 000000000..355741e89 --- /dev/null +++ b/tests/ui/parser/fn-defined-using-func.stderr @@ -0,0 +1,10 @@ +error: expected one of `!` or `::`, found `foo` + --> $DIR/fn-defined-using-func.rs:6:6 + | +LL | func foo() {} + | ---- ^^^ expected one of `!` or `::` + | | + | help: write `fn` instead of `func` to declare a function + +error: aborting due to previous error + diff --git a/tests/ui/parser/fn-defined-using-function.rs b/tests/ui/parser/fn-defined-using-function.rs new file mode 100644 index 000000000..fd8782728 --- /dev/null +++ b/tests/ui/parser/fn-defined-using-function.rs @@ -0,0 +1,10 @@ +// Check what happens when `function` is used to define a function, instead of `fn` +// edition:2021 + +#![allow(dead_code)] + +function foo() {} +//~^ ERROR expected one of `!` or `::`, found `foo` +//~^^ HELP write `fn` instead of `function` to declare a function + +fn main() {} diff --git a/tests/ui/parser/fn-defined-using-function.stderr b/tests/ui/parser/fn-defined-using-function.stderr new file mode 100644 index 000000000..43c33a2cd --- /dev/null +++ b/tests/ui/parser/fn-defined-using-function.stderr @@ -0,0 +1,10 @@ +error: expected one of `!` or `::`, found `foo` + --> $DIR/fn-defined-using-function.rs:6:10 + | +LL | function foo() {} + | -------- ^^^ expected one of `!` or `::` + | | + | help: write `fn` instead of `function` to declare a function + +error: aborting due to previous error + diff --git a/tests/ui/parser/fn-field-parse-error-ice.rs b/tests/ui/parser/fn-field-parse-error-ice.rs new file mode 100644 index 000000000..188257ea5 --- /dev/null +++ b/tests/ui/parser/fn-field-parse-error-ice.rs @@ -0,0 +1,10 @@ +// Regression test for #85794 + +struct Baz { + inner : dyn fn () + //~^ ERROR expected `,`, or `}`, found keyword `fn` + //~| ERROR expected identifier, found keyword `fn` + //~| ERROR cannot find type `dyn` in this scope +} + +fn main() {} diff --git a/tests/ui/parser/fn-field-parse-error-ice.stderr b/tests/ui/parser/fn-field-parse-error-ice.stderr new file mode 100644 index 000000000..3bf68e8cc --- /dev/null +++ b/tests/ui/parser/fn-field-parse-error-ice.stderr @@ -0,0 +1,28 @@ +error: expected `,`, or `}`, found keyword `fn` + --> $DIR/fn-field-parse-error-ice.rs:4:16 + | +LL | inner : dyn fn () + | ^ help: try adding a comma: `,` + +error: expected identifier, found keyword `fn` + --> $DIR/fn-field-parse-error-ice.rs:4:17 + | +LL | struct Baz { + | --- while parsing this struct +LL | inner : dyn fn () + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | inner : dyn r#fn () + | ++ + +error[E0412]: cannot find type `dyn` in this scope + --> $DIR/fn-field-parse-error-ice.rs:4:13 + | +LL | inner : dyn fn () + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs new file mode 100644 index 000000000..cf5d3dab4 --- /dev/null +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -0,0 +1,58 @@ +// Ensures that all `fn` forms can have all the function qualifiers syntactically. + +// edition:2018 + +#![feature(const_extern_fn)] + +fn main() { + async fn ff1() {} // OK. + unsafe fn ff2() {} // OK. + const fn ff3() {} // OK. + extern "C" fn ff4() {} // OK. + const async unsafe extern "C" fn ff5() {} + //~^ ERROR functions cannot be both `const` and `async` + //~| ERROR cycle detected + + trait X { + async fn ft1(); //~ ERROR functions in traits cannot be declared `async` + unsafe fn ft2(); // OK. + const fn ft3(); //~ ERROR functions in traits cannot be declared const + extern "C" fn ft4(); // OK. + const async unsafe extern "C" fn ft5(); + //~^ ERROR functions in traits cannot be declared `async` + //~| ERROR functions in traits cannot be declared const + //~| ERROR functions cannot be both `const` and `async` + } + + struct Y; + impl X for Y { + async fn ft1() {} //~ ERROR functions in traits cannot be declared `async` + unsafe fn ft2() {} // OK. + const fn ft3() {} //~ ERROR functions in traits cannot be declared const + extern "C" fn ft4() {} + const async unsafe extern "C" fn ft5() {} + //~^ ERROR functions in traits cannot be declared `async` + //~| ERROR functions in traits cannot be declared const + //~| ERROR functions cannot be both `const` and `async` + //~| ERROR cycle detected + } + + impl Y { + async fn fi1() {} // OK. + unsafe fn fi2() {} // OK. + const fn fi3() {} // OK. + extern "C" fn fi4() {} // OK. + const async unsafe extern "C" fn fi5() {} + //~^ ERROR functions cannot be both `const` and `async` + //~| ERROR cycle detected + } + + extern "C" { + async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers + unsafe fn fe2(); //~ ERROR functions in `extern` blocks cannot have qualifiers + const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers + extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers + const async unsafe extern "C" fn fe5(); //~ ERROR functions in `extern` blocks + //~^ ERROR functions cannot be both `const` and `async` + } +} diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr new file mode 100644 index 000000000..038fdfb2d --- /dev/null +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -0,0 +1,302 @@ +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:12:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^-^^^^^------------------------------ + | | | + | | `async` because of this + | `const` because of this + +error[E0379]: functions in traits cannot be declared const + --> $DIR/fn-header-semantic-fail.rs:19:9 + | +LL | const fn ft3(); + | ^^^^^ functions in traits cannot be const + +error[E0379]: functions in traits cannot be declared const + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^ functions in traits cannot be const + +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^-^^^^^---------------------------- + | | | + | | `async` because of this + | `const` because of this + +error[E0379]: functions in traits cannot be declared const + --> $DIR/fn-header-semantic-fail.rs:31:9 + | +LL | const fn ft3() {} + | ^^^^^ functions in traits cannot be const + +error[E0379]: functions in traits cannot be declared const + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^ functions in traits cannot be const + +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^-^^^^^------------------------------ + | | | + | | `async` because of this + | `const` because of this + +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^-^^^^^------------------------------ + | | | + | | `async` because of this + | `const` because of this + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/fn-header-semantic-fail.rs:51:18 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | async fn fe1(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn fe1(); + | ~~ + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/fn-header-semantic-fail.rs:52:19 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | async fn fe1(); +LL | unsafe fn fe2(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn fe2(); + | ~~ + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/fn-header-semantic-fail.rs:53:18 + | +LL | extern "C" { + | ---------- in this `extern` block +... +LL | const fn fe3(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn fe3(); + | ~~ + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/fn-header-semantic-fail.rs:54:23 + | +LL | extern "C" { + | ---------- in this `extern` block +... +LL | extern "C" fn fe4(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn fe4(); + | ~~ + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/fn-header-semantic-fail.rs:55:42 + | +LL | extern "C" { + | ---------- in this `extern` block +... +LL | const async unsafe extern "C" fn fe5(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn fe5(); + | ~~ + +error: functions cannot be both `const` and `async` + --> $DIR/fn-header-semantic-fail.rs:55:9 + | +LL | const async unsafe extern "C" fn fe5(); + | ^^^^^-^^^^^---------------------------- + | | | + | | `async` because of this + | `const` because of this + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:17:9 + | +LL | async fn ft1(); + | -----^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:21:9 + | +LL | const async unsafe extern "C" fn ft5(); + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:29:9 + | +LL | async fn ft1() {} + | -----^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:12:44 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^ + | +note: ...which requires borrow-checking `main::ff5`... + --> $DIR/fn-header-semantic-fail.rs:12:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `main::ff5`... + --> $DIR/fn-header-semantic-fail.rs:12:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::ff5`... + --> $DIR/fn-header-semantic-fail.rs:12:5 + | +LL | const async unsafe extern "C" fn ff5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/fn-header-semantic-fail.rs:5:1 + | +LL | / #![feature(const_extern_fn)] +LL | | +LL | | fn main() { +LL | | async fn ff1() {} // OK. +... | +LL | | } +LL | | } + | |_^ + +error[E0391]: cycle detected when computing type of `main::::ft5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:33:48 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^ + | +note: ...which requires borrow-checking `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::::ft5`... + --> $DIR/fn-header-semantic-fail.rs:33:9 + | +LL | const async unsafe extern "C" fn ft5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::::ft5::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/fn-header-semantic-fail.rs:5:1 + | +LL | / #![feature(const_extern_fn)] +LL | | +LL | | fn main() { +LL | | async fn ff1() {} // OK. +... | +LL | | } +LL | | } + | |_^ + +error[E0391]: cycle detected when computing type of `main::::fi5::{opaque#0}` + --> $DIR/fn-header-semantic-fail.rs:45:48 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^ + | +note: ...which requires borrow-checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `main::::fi5`... + --> $DIR/fn-header-semantic-fail.rs:45:9 + | +LL | const async unsafe extern "C" fn fi5() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing whether `impl core::future::future::Future` is freeze... + = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future: core::marker::Freeze`... + = note: ...which again requires computing type of `main::::fi5::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/fn-header-semantic-fail.rs:5:1 + | +LL | / #![feature(const_extern_fn)] +LL | | +LL | | fn main() { +LL | | async fn ff1() {} // OK. +... | +LL | | } +LL | | } + | |_^ + +error: aborting due to 21 previous errors + +Some errors have detailed explanations: E0379, E0391, E0706. +For more information about an error, try `rustc --explain E0379`. diff --git a/tests/ui/parser/fn-header-syntactic-pass.rs b/tests/ui/parser/fn-header-syntactic-pass.rs new file mode 100644 index 000000000..68f1f7901 --- /dev/null +++ b/tests/ui/parser/fn-header-syntactic-pass.rs @@ -0,0 +1,47 @@ +// Ensures that all `fn` forms can have all the function qualifiers syntactically. + +// check-pass +// edition:2018 + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + async fn f(); + unsafe fn f(); + const fn f(); + extern "C" fn f(); + const async unsafe extern "C" fn f(); + + trait X { + async fn f(); + unsafe fn f(); + const fn f(); + extern "C" fn f(); + const async unsafe extern "C" fn f(); + } + + impl X for Y { + async fn f(); + unsafe fn f(); + const fn f(); + extern "C" fn f(); + const async unsafe extern "C" fn f(); + } + + impl Y { + async fn f(); + unsafe fn f(); + const fn f(); + extern "C" fn f(); + const async unsafe extern "C" fn f(); + } + + extern "C" { + fn f(); + fn f(); + fn f(); + fn f(); + fn f(); + } +} diff --git a/tests/ui/parser/fn-returns-fn-pointer.rs b/tests/ui/parser/fn-returns-fn-pointer.rs new file mode 100644 index 000000000..15590e324 --- /dev/null +++ b/tests/ui/parser/fn-returns-fn-pointer.rs @@ -0,0 +1,6 @@ +// check-pass +// Regression test for #78507. +fn foo() -> Option Option> { + Some(|| Some(true)) +} +fn main() {} diff --git a/tests/ui/parser/foreign-const-semantic-fail.rs b/tests/ui/parser/foreign-const-semantic-fail.rs new file mode 100644 index 000000000..c9940b74a --- /dev/null +++ b/tests/ui/parser/foreign-const-semantic-fail.rs @@ -0,0 +1,9 @@ +fn main() {} + +extern "C" { + const A: isize; + //~^ ERROR extern items cannot be `const` + const B: isize = 42; + //~^ ERROR extern items cannot be `const` + //~| ERROR incorrect `static` inside `extern` block +} diff --git a/tests/ui/parser/foreign-const-semantic-fail.stderr b/tests/ui/parser/foreign-const-semantic-fail.stderr new file mode 100644 index 000000000..8dc66c0d0 --- /dev/null +++ b/tests/ui/parser/foreign-const-semantic-fail.stderr @@ -0,0 +1,35 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:4:11 + | +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:6:11 + | +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `static` inside `extern` block + --> $DIR/foreign-const-semantic-fail.rs:6:11 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body +... +LL | const B: isize = 42; + | ^ -- the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/foreign-const-syntactic-fail.rs b/tests/ui/parser/foreign-const-syntactic-fail.rs new file mode 100644 index 000000000..a6e77f846 --- /dev/null +++ b/tests/ui/parser/foreign-const-syntactic-fail.rs @@ -0,0 +1,9 @@ +// Syntactically, a `const` item inside an `extern { ... }` block is not allowed. + +fn main() {} + +#[cfg(FALSE)] +extern "C" { + const A: isize; //~ ERROR extern items cannot be `const` + const B: isize = 42; //~ ERROR extern items cannot be `const` +} diff --git a/tests/ui/parser/foreign-const-syntactic-fail.stderr b/tests/ui/parser/foreign-const-syntactic-fail.stderr new file mode 100644 index 000000000..9cf58fa95 --- /dev/null +++ b/tests/ui/parser/foreign-const-syntactic-fail.stderr @@ -0,0 +1,22 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-syntactic-fail.rs:7:11 + | +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-syntactic-fail.rs:8:11 + | +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/foreign-static-semantic-fail.rs b/tests/ui/parser/foreign-static-semantic-fail.rs new file mode 100644 index 000000000..3d427ed0e --- /dev/null +++ b/tests/ui/parser/foreign-static-semantic-fail.rs @@ -0,0 +1,8 @@ +// Syntactically, a foreign static may not have a body. + +fn main() {} + +extern "C" { + static X: u8 = 0; //~ ERROR incorrect `static` inside `extern` block + static mut Y: u8 = 0; //~ ERROR incorrect `static` inside `extern` block +} diff --git a/tests/ui/parser/foreign-static-semantic-fail.stderr b/tests/ui/parser/foreign-static-semantic-fail.stderr new file mode 100644 index 000000000..105508cfe --- /dev/null +++ b/tests/ui/parser/foreign-static-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: incorrect `static` inside `extern` block + --> $DIR/foreign-static-semantic-fail.rs:6:12 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | static X: u8 = 0; + | ^ - the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `static` inside `extern` block + --> $DIR/foreign-static-semantic-fail.rs:7:16 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | static X: u8 = 0; +LL | static mut Y: u8 = 0; + | ^ - the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/foreign-static-syntactic-pass.rs b/tests/ui/parser/foreign-static-syntactic-pass.rs new file mode 100644 index 000000000..599496346 --- /dev/null +++ b/tests/ui/parser/foreign-static-syntactic-pass.rs @@ -0,0 +1,11 @@ +// Syntactically, a foreign static may have a body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern "C" { + static X: u8; + static mut Y: u8; +} diff --git a/tests/ui/parser/foreign-ty-semantic-fail.rs b/tests/ui/parser/foreign-ty-semantic-fail.rs new file mode 100644 index 000000000..96b15232b --- /dev/null +++ b/tests/ui/parser/foreign-ty-semantic-fail.rs @@ -0,0 +1,18 @@ +#![feature(extern_types)] + +fn main() {} + +extern "C" { + type A: Ord; + //~^ ERROR bounds on `type`s in `extern` blocks have no effect + type B<'a> where 'a: 'static; + //~^ ERROR `type`s inside `extern` blocks cannot have generic parameters + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + type C where T: 'static; + //~^ ERROR `type`s inside `extern` blocks cannot have generic parameters + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + type D = u8; + //~^ ERROR incorrect `type` inside `extern` block + + type E: where; +} diff --git a/tests/ui/parser/foreign-ty-semantic-fail.stderr b/tests/ui/parser/foreign-ty-semantic-fail.stderr new file mode 100644 index 000000000..588e4966a --- /dev/null +++ b/tests/ui/parser/foreign-ty-semantic-fail.stderr @@ -0,0 +1,65 @@ +error: bounds on `type`s in `extern` blocks have no effect + --> $DIR/foreign-ty-semantic-fail.rs:6:13 + | +LL | type A: Ord; + | ^^^ + +error: `type`s inside `extern` blocks cannot have generic parameters + --> $DIR/foreign-ty-semantic-fail.rs:8:11 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type B<'a> where 'a: 'static; + | ^^^^ help: remove the generic parameters + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:8:16 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type B<'a> where 'a: 'static; + | ^^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have generic parameters + --> $DIR/foreign-ty-semantic-fail.rs:11:11 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type C where T: 'static; + | ^^^^^^^^ help: remove the generic parameters + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:11:20 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type C where T: 'static; + | ^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `type` inside `extern` block + --> $DIR/foreign-ty-semantic-fail.rs:14:10 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign types and types inside of them cannot have a body +... +LL | type D = u8; + | ^ -- the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/foreign-ty-syntactic-pass.rs b/tests/ui/parser/foreign-ty-syntactic-pass.rs new file mode 100644 index 000000000..a746de1f1 --- /dev/null +++ b/tests/ui/parser/foreign-ty-syntactic-pass.rs @@ -0,0 +1,12 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern "C" { + type A: Ord; + type A<'a> where 'a: 'static; + type A where T: 'static; + type A = u8; + type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq where T: 'static + Copy = Vec; +} diff --git a/tests/ui/parser/if-block-unreachable-expr.rs b/tests/ui/parser/if-block-unreachable-expr.rs new file mode 100644 index 000000000..4063a3370 --- /dev/null +++ b/tests/ui/parser/if-block-unreachable-expr.rs @@ -0,0 +1,8 @@ +// check-pass + +// This regressed from 1.20 -> 1.21 -- the condition is unreachable, +// but it's still an expression, and should parse fine. + +fn main() { + if { if true { return; } else { return; }; } {} +} diff --git a/tests/ui/parser/if-in-in.fixed b/tests/ui/parser/if-in-in.fixed new file mode 100644 index 000000000..0bb88c559 --- /dev/null +++ b/tests/ui/parser/if-in-in.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +fn main() { + for i in 1..2 { //~ ERROR expected iterable, found keyword `in` + println!("{}", i); + } +} diff --git a/tests/ui/parser/if-in-in.rs b/tests/ui/parser/if-in-in.rs new file mode 100644 index 000000000..6c0986fe1 --- /dev/null +++ b/tests/ui/parser/if-in-in.rs @@ -0,0 +1,7 @@ +// run-rustfix + +fn main() { + for i in in 1..2 { //~ ERROR expected iterable, found keyword `in` + println!("{}", i); + } +} diff --git a/tests/ui/parser/if-in-in.stderr b/tests/ui/parser/if-in-in.stderr new file mode 100644 index 000000000..0e69bc4b2 --- /dev/null +++ b/tests/ui/parser/if-in-in.stderr @@ -0,0 +1,10 @@ +error: expected iterable, found keyword `in` + --> $DIR/if-in-in.rs:4:14 + | +LL | for i in in 1..2 { + | ---^^ + | | + | help: remove the duplicated `in` + +error: aborting due to previous error + diff --git a/tests/ui/parser/impl-item-const-pass.rs b/tests/ui/parser/impl-item-const-pass.rs new file mode 100644 index 000000000..d11245613 --- /dev/null +++ b/tests/ui/parser/impl-item-const-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + const Y: u8; +} diff --git a/tests/ui/parser/impl-item-const-semantic-fail.rs b/tests/ui/parser/impl-item-const-semantic-fail.rs new file mode 100644 index 000000000..5d4692f9f --- /dev/null +++ b/tests/ui/parser/impl-item-const-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + const Y: u8; //~ ERROR associated constant in `impl` without body +} diff --git a/tests/ui/parser/impl-item-const-semantic-fail.stderr b/tests/ui/parser/impl-item-const-semantic-fail.stderr new file mode 100644 index 000000000..ec3bee0ce --- /dev/null +++ b/tests/ui/parser/impl-item-const-semantic-fail.stderr @@ -0,0 +1,10 @@ +error: associated constant in `impl` without body + --> $DIR/impl-item-const-semantic-fail.rs:6:5 + | +LL | const Y: u8; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: aborting due to previous error + diff --git a/tests/ui/parser/impl-item-fn-no-body-pass.rs b/tests/ui/parser/impl-item-fn-no-body-pass.rs new file mode 100644 index 000000000..16b09d64e --- /dev/null +++ b/tests/ui/parser/impl-item-fn-no-body-pass.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + fn f(); +} diff --git a/tests/ui/parser/impl-item-fn-no-body-semantic-fail.rs b/tests/ui/parser/impl-item-fn-no-body-semantic-fail.rs new file mode 100644 index 000000000..cb183db59 --- /dev/null +++ b/tests/ui/parser/impl-item-fn-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +fn main() {} + +struct X; + +impl X { + fn f(); //~ ERROR associated function in `impl` without body +} diff --git a/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr new file mode 100644 index 000000000..1acb72736 --- /dev/null +++ b/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr @@ -0,0 +1,10 @@ +error: associated function in `impl` without body + --> $DIR/impl-item-fn-no-body-semantic-fail.rs:6:5 + | +LL | fn f(); + | ^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to previous error + diff --git a/tests/ui/parser/impl-item-type-no-body-pass.rs b/tests/ui/parser/impl-item-type-no-body-pass.rs new file mode 100644 index 000000000..74a9c6ab7 --- /dev/null +++ b/tests/ui/parser/impl-item-type-no-body-pass.rs @@ -0,0 +1,11 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl X { + type Y; + type Z: Ord; + type W: Ord where Self: Eq; + type W where Self: Eq; +} diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs b/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs new file mode 100644 index 000000000..1291a021b --- /dev/null +++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -0,0 +1,20 @@ +fn main() {} + +struct X; + +impl X { + type Y; + //~^ ERROR associated type in `impl` without body + //~| ERROR inherent associated types are unstable + type Z: Ord; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on `type`s in `impl`s have no effect + //~| ERROR inherent associated types are unstable + type W: Ord where Self: Eq; + //~^ ERROR associated type in `impl` without body + //~| ERROR bounds on `type`s in `impl`s have no effect + //~| ERROR inherent associated types are unstable + type W where Self: Eq; + //~^ ERROR associated type in `impl` without body + //~| ERROR inherent associated types are unstable +} diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr new file mode 100644 index 000000000..3856754e0 --- /dev/null +++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -0,0 +1,83 @@ +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:6:5 + | +LL | type Y; + | ^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:13 + | +LL | type Z: Ord; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on `type`s in `impl`s have no effect + --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:13 + | +LL | type W: Ord where Self: Eq; + | ^^^ + +error: associated type in `impl` without body + --> $DIR/impl-item-type-no-body-semantic-fail.rs:17:5 + | +LL | type W where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error[E0658]: inherent associated types are unstable + --> $DIR/impl-item-type-no-body-semantic-fail.rs:6:5 + | +LL | type Y; + | ^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error[E0658]: inherent associated types are unstable + --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 + | +LL | type Z: Ord; + | ^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error[E0658]: inherent associated types are unstable + --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:5 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error[E0658]: inherent associated types are unstable + --> $DIR/impl-item-type-no-body-semantic-fail.rs:17:5 + | +LL | type W where Self: Eq; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/impl-parsing.rs b/tests/ui/parser/impl-parsing.rs new file mode 100644 index 000000000..80ce88855 --- /dev/null +++ b/tests/ui/parser/impl-parsing.rs @@ -0,0 +1,10 @@ +impl ! {} // OK +impl ! where u8: Copy {} // OK + +impl Trait Type {} //~ ERROR missing `for` in a trait impl +impl Trait .. {} //~ ERROR missing `for` in a trait impl +impl ?Sized for Type {} //~ ERROR expected a trait, found type +impl ?Sized for .. {} //~ ERROR expected a trait, found type + +default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` +//~^ ERROR `default` is not followed by an item diff --git a/tests/ui/parser/impl-parsing.stderr b/tests/ui/parser/impl-parsing.stderr new file mode 100644 index 000000000..755addf14 --- /dev/null +++ b/tests/ui/parser/impl-parsing.stderr @@ -0,0 +1,40 @@ +error: missing `for` in a trait impl + --> $DIR/impl-parsing.rs:4:11 + | +LL | impl Trait Type {} + | ^ help: add `for` here + +error: missing `for` in a trait impl + --> $DIR/impl-parsing.rs:5:11 + | +LL | impl Trait .. {} + | ^ help: add `for` here + +error: expected a trait, found type + --> $DIR/impl-parsing.rs:6:6 + | +LL | impl ?Sized for Type {} + | ^^^^^^ + +error: expected a trait, found type + --> $DIR/impl-parsing.rs:7:6 + | +LL | impl ?Sized for .. {} + | ^^^^^^ + +error: `default` is not followed by an item + --> $DIR/impl-parsing.rs:9:1 + | +LL | default unsafe FAIL + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: expected item, found keyword `unsafe` + --> $DIR/impl-parsing.rs:9:9 + | +LL | default unsafe FAIL + | ^^^^^^ expected item + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/impl-qpath.rs b/tests/ui/parser/impl-qpath.rs new file mode 100644 index 000000000..d1f0a0204 --- /dev/null +++ b/tests/ui/parser/impl-qpath.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags: -Z parse-only + +impl <*const u8>::AssocTy {} // OK +impl ::AssocTy {} // OK +impl <'a + Trait>::AssocTy {} // OK +impl <::AssocTy>::AssocTy {} // OK diff --git a/tests/ui/parser/import-from-path.rs b/tests/ui/parser/import-from-path.rs new file mode 100644 index 000000000..3fce08259 --- /dev/null +++ b/tests/ui/parser/import-from-path.rs @@ -0,0 +1,2 @@ +// error-pattern:expected +use foo::{bar}::baz diff --git a/tests/ui/parser/import-from-path.stderr b/tests/ui/parser/import-from-path.stderr new file mode 100644 index 000000000..93bdf82d0 --- /dev/null +++ b/tests/ui/parser/import-from-path.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found `::` + --> $DIR/import-from-path.rs:2:15 + | +LL | use foo::{bar}::baz + | ^^ expected `;` + | + = note: glob-like brace syntax must be last on the path + +error: aborting due to previous error + diff --git a/tests/ui/parser/import-from-rename.rs b/tests/ui/parser/import-from-rename.rs new file mode 100644 index 000000000..27425a3c9 --- /dev/null +++ b/tests/ui/parser/import-from-rename.rs @@ -0,0 +1,10 @@ +// error-pattern:expected + +use foo::{bar} as baz; + +mod foo { + pub fn bar() {} +} + +fn main() { +} diff --git a/tests/ui/parser/import-from-rename.stderr b/tests/ui/parser/import-from-rename.stderr new file mode 100644 index 000000000..d78f6de92 --- /dev/null +++ b/tests/ui/parser/import-from-rename.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found keyword `as` + --> $DIR/import-from-rename.rs:3:16 + | +LL | use foo::{bar} as baz; + | ^^ expected `;` + | + = note: glob-like brace syntax must be last on the path + +error: aborting due to previous error + diff --git a/tests/ui/parser/import-glob-path.rs b/tests/ui/parser/import-glob-path.rs new file mode 100644 index 000000000..de4c07aa7 --- /dev/null +++ b/tests/ui/parser/import-glob-path.rs @@ -0,0 +1,2 @@ +// error-pattern:expected +use foo::*::bar diff --git a/tests/ui/parser/import-glob-path.stderr b/tests/ui/parser/import-glob-path.stderr new file mode 100644 index 000000000..a93ef255c --- /dev/null +++ b/tests/ui/parser/import-glob-path.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found `::` + --> $DIR/import-glob-path.rs:2:11 + | +LL | use foo::*::bar + | ^^ expected `;` + | + = note: the wildcard token must be last on the path + +error: aborting due to previous error + diff --git a/tests/ui/parser/import-glob-rename.rs b/tests/ui/parser/import-glob-rename.rs new file mode 100644 index 000000000..b9b753dcd --- /dev/null +++ b/tests/ui/parser/import-glob-rename.rs @@ -0,0 +1,10 @@ +// error-pattern:expected + +use foo::* as baz; + +mod foo { + pub fn bar() {} +} + +fn main() { +} diff --git a/tests/ui/parser/import-glob-rename.stderr b/tests/ui/parser/import-glob-rename.stderr new file mode 100644 index 000000000..e1a026b63 --- /dev/null +++ b/tests/ui/parser/import-glob-rename.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found keyword `as` + --> $DIR/import-glob-rename.rs:3:12 + | +LL | use foo::* as baz; + | ^^ expected `;` + | + = note: the wildcard token must be last on the path + +error: aborting due to previous error + diff --git a/tests/ui/parser/increment-autofix-2.fixed b/tests/ui/parser/increment-autofix-2.fixed new file mode 100644 index 000000000..580ebaf5d --- /dev/null +++ b/tests/ui/parser/increment-autofix-2.fixed @@ -0,0 +1,63 @@ +// run-rustfix + +struct Foo { + bar: Bar, +} + +struct Bar { + qux: i32, +} + +pub fn post_regular() { + let mut i = 0; + i += 1; //~ ERROR Rust has no postfix increment operator + println!("{}", i); +} + +pub fn post_while() { + let mut i = 0; + while { let tmp = i; i += 1; tmp } < 5 { + //~^ ERROR Rust has no postfix increment operator + println!("{}", i); + } +} + +pub fn post_regular_tmp() { + let mut tmp = 0; + tmp += 1; //~ ERROR Rust has no postfix increment operator + println!("{}", tmp); +} + +pub fn post_while_tmp() { + let mut tmp = 0; + while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 { + //~^ ERROR Rust has no postfix increment operator + println!("{}", tmp); + } +} + +pub fn post_field() { + let mut foo = Foo { bar: Bar { qux: 0 } }; + foo.bar.qux += 1; + //~^ ERROR Rust has no postfix increment operator + println!("{}", foo.bar.qux); +} + +pub fn post_field_tmp() { + struct S { + tmp: i32 + } + let mut s = S { tmp: 0 }; + s.tmp += 1; + //~^ ERROR Rust has no postfix increment operator + println!("{}", s.tmp); +} + +pub fn pre_field() { + let mut foo = Foo { bar: Bar { qux: 0 } }; + foo.bar.qux += 1; + //~^ ERROR Rust has no prefix increment operator + println!("{}", foo.bar.qux); +} + +fn main() {} diff --git a/tests/ui/parser/increment-autofix-2.rs b/tests/ui/parser/increment-autofix-2.rs new file mode 100644 index 000000000..ebe5fa6ca --- /dev/null +++ b/tests/ui/parser/increment-autofix-2.rs @@ -0,0 +1,63 @@ +// run-rustfix + +struct Foo { + bar: Bar, +} + +struct Bar { + qux: i32, +} + +pub fn post_regular() { + let mut i = 0; + i++; //~ ERROR Rust has no postfix increment operator + println!("{}", i); +} + +pub fn post_while() { + let mut i = 0; + while i++ < 5 { + //~^ ERROR Rust has no postfix increment operator + println!("{}", i); + } +} + +pub fn post_regular_tmp() { + let mut tmp = 0; + tmp++; //~ ERROR Rust has no postfix increment operator + println!("{}", tmp); +} + +pub fn post_while_tmp() { + let mut tmp = 0; + while tmp++ < 5 { + //~^ ERROR Rust has no postfix increment operator + println!("{}", tmp); + } +} + +pub fn post_field() { + let mut foo = Foo { bar: Bar { qux: 0 } }; + foo.bar.qux++; + //~^ ERROR Rust has no postfix increment operator + println!("{}", foo.bar.qux); +} + +pub fn post_field_tmp() { + struct S { + tmp: i32 + } + let mut s = S { tmp: 0 }; + s.tmp++; + //~^ ERROR Rust has no postfix increment operator + println!("{}", s.tmp); +} + +pub fn pre_field() { + let mut foo = Foo { bar: Bar { qux: 0 } }; + ++foo.bar.qux; + //~^ ERROR Rust has no prefix increment operator + println!("{}", foo.bar.qux); +} + +fn main() {} diff --git a/tests/ui/parser/increment-autofix-2.stderr b/tests/ui/parser/increment-autofix-2.stderr new file mode 100644 index 000000000..11e985480 --- /dev/null +++ b/tests/ui/parser/increment-autofix-2.stderr @@ -0,0 +1,84 @@ +error: Rust has no postfix increment operator + --> $DIR/increment-autofix-2.rs:13:6 + | +LL | i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | i += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/increment-autofix-2.rs:19:12 + | +LL | while i++ < 5 { + | ----- ^^ not a valid postfix operator + | | + | while parsing the condition of this `while` expression + | +help: use `+= 1` instead + | +LL | while { let tmp = i; i += 1; tmp } < 5 { + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/increment-autofix-2.rs:27:8 + | +LL | tmp++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | tmp += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/increment-autofix-2.rs:33:14 + | +LL | while tmp++ < 5 { + | ----- ^^ not a valid postfix operator + | | + | while parsing the condition of this `while` expression + | +help: use `+= 1` instead + | +LL | while { let tmp_ = tmp; tmp += 1; tmp_ } < 5 { + | ++++++++++++ ~~~~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/increment-autofix-2.rs:41:16 + | +LL | foo.bar.qux++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | foo.bar.qux += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/increment-autofix-2.rs:51:10 + | +LL | s.tmp++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | s.tmp += 1; + | ~~~~ + +error: Rust has no prefix increment operator + --> $DIR/increment-autofix-2.rs:58:5 + | +LL | ++foo.bar.qux; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++foo.bar.qux; +LL + foo.bar.qux += 1; + | + +error: aborting due to 7 previous errors + diff --git a/tests/ui/parser/increment-autofix.fixed b/tests/ui/parser/increment-autofix.fixed new file mode 100644 index 000000000..7a426badf --- /dev/null +++ b/tests/ui/parser/increment-autofix.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +pub fn pre_regular() { + let mut i = 0; + i += 1; //~ ERROR Rust has no prefix increment operator + println!("{}", i); +} + +pub fn pre_while() { + let mut i = 0; + while { i += 1; i } < 5 { + //~^ ERROR Rust has no prefix increment operator + println!("{}", i); + } +} + +pub fn pre_regular_tmp() { + let mut tmp = 0; + tmp += 1; //~ ERROR Rust has no prefix increment operator + println!("{}", tmp); +} + +pub fn pre_while_tmp() { + let mut tmp = 0; + while { tmp += 1; tmp } < 5 { + //~^ ERROR Rust has no prefix increment operator + println!("{}", tmp); + } +} + +fn main() {} diff --git a/tests/ui/parser/increment-autofix.rs b/tests/ui/parser/increment-autofix.rs new file mode 100644 index 000000000..d38603697 --- /dev/null +++ b/tests/ui/parser/increment-autofix.rs @@ -0,0 +1,31 @@ +// run-rustfix + +pub fn pre_regular() { + let mut i = 0; + ++i; //~ ERROR Rust has no prefix increment operator + println!("{}", i); +} + +pub fn pre_while() { + let mut i = 0; + while ++i < 5 { + //~^ ERROR Rust has no prefix increment operator + println!("{}", i); + } +} + +pub fn pre_regular_tmp() { + let mut tmp = 0; + ++tmp; //~ ERROR Rust has no prefix increment operator + println!("{}", tmp); +} + +pub fn pre_while_tmp() { + let mut tmp = 0; + while ++tmp < 5 { + //~^ ERROR Rust has no prefix increment operator + println!("{}", tmp); + } +} + +fn main() {} diff --git a/tests/ui/parser/increment-autofix.stderr b/tests/ui/parser/increment-autofix.stderr new file mode 100644 index 000000000..1dc69fd9f --- /dev/null +++ b/tests/ui/parser/increment-autofix.stderr @@ -0,0 +1,52 @@ +error: Rust has no prefix increment operator + --> $DIR/increment-autofix.rs:5:5 + | +LL | ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++i; +LL + i += 1; + | + +error: Rust has no prefix increment operator + --> $DIR/increment-autofix.rs:11:11 + | +LL | while ++i < 5 { + | ----- ^^ not a valid prefix operator + | | + | while parsing the condition of this `while` expression + | +help: use `+= 1` instead + | +LL | while { i += 1; i } < 5 { + | ~ +++++++++ + +error: Rust has no prefix increment operator + --> $DIR/increment-autofix.rs:19:5 + | +LL | ++tmp; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++tmp; +LL + tmp += 1; + | + +error: Rust has no prefix increment operator + --> $DIR/increment-autofix.rs:25:11 + | +LL | while ++tmp < 5 { + | ----- ^^ not a valid prefix operator + | | + | while parsing the condition of this `while` expression + | +help: use `+= 1` instead + | +LL | while { tmp += 1; tmp } < 5 { + | ~ +++++++++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/inner-attr-after-doc-comment.rs b/tests/ui/parser/inner-attr-after-doc-comment.rs new file mode 100644 index 000000000..36f4191f0 --- /dev/null +++ b/tests/ui/parser/inner-attr-after-doc-comment.rs @@ -0,0 +1,8 @@ +#![feature(lang_items)] +/** + * My module + */ + +#![recursion_limit="100"] +//~^ ERROR an inner attribute is not permitted following an outer doc comment +fn main() {} diff --git a/tests/ui/parser/inner-attr-after-doc-comment.stderr b/tests/ui/parser/inner-attr-after-doc-comment.stderr new file mode 100644 index 000000000..3ec3ad8e9 --- /dev/null +++ b/tests/ui/parser/inner-attr-after-doc-comment.stderr @@ -0,0 +1,23 @@ +error: an inner attribute is not permitted following an outer doc comment + --> $DIR/inner-attr-after-doc-comment.rs:6:1 + | +LL | / /** +LL | | * My module +LL | | */ + | |___- previous doc comment +LL | +LL | #![recursion_limit="100"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer doc comment +LL | +LL | fn main() {} + | ------------ the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the function, change the attribute from inner to outer style + | +LL - #![recursion_limit="100"] +LL + #[recursion_limit="100"] + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/inner-attr-in-trait-def.rs b/tests/ui/parser/inner-attr-in-trait-def.rs new file mode 100644 index 000000000..8dba6b362 --- /dev/null +++ b/tests/ui/parser/inner-attr-in-trait-def.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(non_camel_case_types)] + +fn main() {} + +trait foo_bar { + #![allow(non_camel_case_types)] +} diff --git a/tests/ui/parser/inner-attr.rs b/tests/ui/parser/inner-attr.rs new file mode 100644 index 000000000..1b405e20e --- /dev/null +++ b/tests/ui/parser/inner-attr.rs @@ -0,0 +1,4 @@ +#[feature(lang_items)] + +#![recursion_limit="100"] //~ ERROR an inner attribute is not permitted following an outer attribute +fn main() {} diff --git a/tests/ui/parser/inner-attr.stderr b/tests/ui/parser/inner-attr.stderr new file mode 100644 index 000000000..331c254a5 --- /dev/null +++ b/tests/ui/parser/inner-attr.stderr @@ -0,0 +1,20 @@ +error: an inner attribute is not permitted following an outer attribute + --> $DIR/inner-attr.rs:3:1 + | +LL | #[feature(lang_items)] + | ---------------------- previous outer attribute +LL | +LL | #![recursion_limit="100"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute +LL | fn main() {} + | ------------ the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the function, change the attribute from inner to outer style + | +LL - #![recursion_limit="100"] +LL + #[recursion_limit="100"] + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/int-literal-too-large-span.rs b/tests/ui/parser/int-literal-too-large-span.rs new file mode 100644 index 000000000..666ca9350 --- /dev/null +++ b/tests/ui/parser/int-literal-too-large-span.rs @@ -0,0 +1,7 @@ +// issue #17123 + +fn main() { + 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + //~^ ERROR integer literal is too large + ; // the span shouldn't point to this. +} diff --git a/tests/ui/parser/int-literal-too-large-span.stderr b/tests/ui/parser/int-literal-too-large-span.stderr new file mode 100644 index 000000000..49d6aa5ef --- /dev/null +++ b/tests/ui/parser/int-literal-too-large-span.stderr @@ -0,0 +1,10 @@ +error: integer literal is too large + --> $DIR/int-literal-too-large-span.rs:4:5 + | +LL | 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: aborting due to previous error + diff --git a/tests/ui/parser/intersection-patterns-1.fixed b/tests/ui/parser/intersection-patterns-1.fixed new file mode 100644 index 000000000..44773095b --- /dev/null +++ b/tests/ui/parser/intersection-patterns-1.fixed @@ -0,0 +1,35 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +// run-rustfix + +#![allow(unused_variables)] + +fn main() { + let s: Option = None; + + match s { + y @ Some(x) => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION y @ Some(x) + _ => {} + } + + match 2 { + e @ 1..=5 => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION e @ 1..=5 + _ => {} + } +} diff --git a/tests/ui/parser/intersection-patterns-1.rs b/tests/ui/parser/intersection-patterns-1.rs new file mode 100644 index 000000000..1036b9daf --- /dev/null +++ b/tests/ui/parser/intersection-patterns-1.rs @@ -0,0 +1,35 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +// run-rustfix + +#![allow(unused_variables)] + +fn main() { + let s: Option = None; + + match s { + Some(x) @ y => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION y @ Some(x) + _ => {} + } + + match 2 { + 1 ..= 5 @ e => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION e @ 1..=5 + _ => {} + } +} diff --git a/tests/ui/parser/intersection-patterns-1.stderr b/tests/ui/parser/intersection-patterns-1.stderr new file mode 100644 index 000000000..dc968656c --- /dev/null +++ b/tests/ui/parser/intersection-patterns-1.stderr @@ -0,0 +1,22 @@ +error: pattern on wrong side of `@` + --> $DIR/intersection-patterns-1.rs:17:9 + | +LL | Some(x) @ y => {} + | -------^^^- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `y @ Some(x)` + +error: pattern on wrong side of `@` + --> $DIR/intersection-patterns-1.rs:27:9 + | +LL | 1 ..= 5 @ e => {} + | -------^^^- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `e @ 1..=5` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/intersection-patterns-2.rs b/tests/ui/parser/intersection-patterns-2.rs new file mode 100644 index 000000000..408415e87 --- /dev/null +++ b/tests/ui/parser/intersection-patterns-2.rs @@ -0,0 +1,20 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +fn main() { + let s: Option = None; + + match s { + Some(x) @ Some(y) => {} + //~^ ERROR left-hand side of `@` must be a binding + //~| interpreted as a pattern, not a binding + //~| also a pattern + //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` + _ => {} + } +} diff --git a/tests/ui/parser/intersection-patterns-2.stderr b/tests/ui/parser/intersection-patterns-2.stderr new file mode 100644 index 000000000..f7e78814c --- /dev/null +++ b/tests/ui/parser/intersection-patterns-2.stderr @@ -0,0 +1,13 @@ +error: left-hand side of `@` must be a binding + --> $DIR/intersection-patterns-2.rs:13:9 + | +LL | Some(x) @ Some(y) => {} + | -------^^^------- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: aborting due to previous error + diff --git a/tests/ui/parser/inverted-parameters.rs b/tests/ui/parser/inverted-parameters.rs new file mode 100644 index 000000000..5c4272504 --- /dev/null +++ b/tests/ui/parser/inverted-parameters.rs @@ -0,0 +1,32 @@ +struct S; + +impl S { + fn foo(&self, &str bar) {} + //~^ ERROR expected one of `:`, `@` + //~| HELP declare the type after the parameter binding + //~| SUGGESTION : +} + +fn baz(S quux, xyzzy: i32) {} +//~^ ERROR expected one of `:`, `@` +//~| HELP declare the type after the parameter binding +//~| SUGGESTION : + +fn one(i32 a b) {} +//~^ ERROR expected one of `:`, `@` + +fn pattern((i32, i32) (a, b)) {} +//~^ ERROR expected one of `:` + +fn fizz(i32) {} +//~^ ERROR expected one of `:`, `@` +//~| HELP if this is a parameter name, give it a type +//~| HELP if this is a `self` type, give it a parameter name +//~| HELP if this is a type, explicitly ignore the parameter name + +fn missing_colon(quux S) {} +//~^ ERROR expected one of `:`, `@` +//~| HELP declare the type after the parameter binding +//~| SUGGESTION : + +fn main() {} diff --git a/tests/ui/parser/inverted-parameters.stderr b/tests/ui/parser/inverted-parameters.stderr new file mode 100644 index 000000000..866227782 --- /dev/null +++ b/tests/ui/parser/inverted-parameters.stderr @@ -0,0 +1,61 @@ +error: expected one of `:`, `@`, or `|`, found `bar` + --> $DIR/inverted-parameters.rs:4:24 + | +LL | fn foo(&self, &str bar) {} + | -----^^^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:`, `@`, or `|`, found `quux` + --> $DIR/inverted-parameters.rs:10:10 + | +LL | fn baz(S quux, xyzzy: i32) {} + | --^^^^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:`, `@`, or `|`, found `a` + --> $DIR/inverted-parameters.rs:15:12 + | +LL | fn one(i32 a b) {} + | ^ expected one of `:`, `@`, or `|` + +error: expected one of `:` or `|`, found `(` + --> $DIR/inverted-parameters.rs:18:23 + | +LL | fn pattern((i32, i32) (a, b)) {} + | ^ expected one of `:` or `|` + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/inverted-parameters.rs:21:12 + | +LL | fn fizz(i32) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn fizz(self: i32) {} + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn fizz(i32: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn fizz(_: i32) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `S` + --> $DIR/inverted-parameters.rs:27:23 + | +LL | fn missing_colon(quux S) {} + | -----^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/issue-100197-mut-let.fixed b/tests/ui/parser/issue-100197-mut-let.fixed new file mode 100644 index 000000000..5a8956222 --- /dev/null +++ b/tests/ui/parser/issue-100197-mut-let.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let mut _x = 123; + //~^ ERROR invalid variable declaration +} diff --git a/tests/ui/parser/issue-100197-mut-let.rs b/tests/ui/parser/issue-100197-mut-let.rs new file mode 100644 index 000000000..71103813a --- /dev/null +++ b/tests/ui/parser/issue-100197-mut-let.rs @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + mut let _x = 123; + //~^ ERROR invalid variable declaration +} diff --git a/tests/ui/parser/issue-100197-mut-let.stderr b/tests/ui/parser/issue-100197-mut-let.stderr new file mode 100644 index 000000000..86658e4f3 --- /dev/null +++ b/tests/ui/parser/issue-100197-mut-let.stderr @@ -0,0 +1,8 @@ +error: invalid variable declaration + --> $DIR/issue-100197-mut-let.rs:4:5 + | +LL | mut let _x = 123; + | ^^^^^^^ help: switch the order of `mut` and `let`: `let mut` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-101477-enum.fixed b/tests/ui/parser/issue-101477-enum.fixed new file mode 100644 index 000000000..1dfeae22a --- /dev/null +++ b/tests/ui/parser/issue-101477-enum.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B = 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/tests/ui/parser/issue-101477-enum.rs b/tests/ui/parser/issue-101477-enum.rs new file mode 100644 index 000000000..ea7051d69 --- /dev/null +++ b/tests/ui/parser/issue-101477-enum.rs @@ -0,0 +1,10 @@ +// run-rustfix + +#[allow(dead_code)] +enum Demo { + A = 1, + B == 2 //~ ERROR unexpected `==` + //~^ expected item, found `==` +} + +fn main() {} diff --git a/tests/ui/parser/issue-101477-enum.stderr b/tests/ui/parser/issue-101477-enum.stderr new file mode 100644 index 000000000..1edca391e --- /dev/null +++ b/tests/ui/parser/issue-101477-enum.stderr @@ -0,0 +1,16 @@ +error: unexpected `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ help: try using `=` instead + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: expected item, found `==` + --> $DIR/issue-101477-enum.rs:6:7 + | +LL | B == 2 + | ^^ expected item + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issue-101477-let.fixed b/tests/ui/parser/issue-101477-let.fixed new file mode 100644 index 000000000..9989ad815 --- /dev/null +++ b/tests/ui/parser/issue-101477-let.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x = 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/tests/ui/parser/issue-101477-let.rs b/tests/ui/parser/issue-101477-let.rs new file mode 100644 index 000000000..8b0e8bee1 --- /dev/null +++ b/tests/ui/parser/issue-101477-let.rs @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let x == 2; //~ ERROR unexpected `==` + println!("x: {}", x) +} diff --git a/tests/ui/parser/issue-101477-let.stderr b/tests/ui/parser/issue-101477-let.stderr new file mode 100644 index 000000000..1b30d4b17 --- /dev/null +++ b/tests/ui/parser/issue-101477-let.stderr @@ -0,0 +1,8 @@ +error: unexpected `==` + --> $DIR/issue-101477-let.rs:4:11 + | +LL | let x == 2; + | ^^ help: try using `=` instead + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-102806.rs b/tests/ui/parser/issue-102806.rs new file mode 100644 index 000000000..ba297bdc9 --- /dev/null +++ b/tests/ui/parser/issue-102806.rs @@ -0,0 +1,25 @@ +#![allow(dead_code)] + +#[derive(Default)] +struct V3 { + x: f32, + y: f32, + z: f32, +} + +fn pz(v: V3) { + let _ = V3 { z: 0.0, ...v}; + //~^ ERROR expected `..` + + let _ = V3 { z: 0.0, ...Default::default() }; + //~^ ERROR expected `..` + + let _ = V3 { z: 0.0, ... }; + //~^ expected identifier + //~| ERROR missing fields `x` and `y` in initializer of `V3` + + let V3 { z: val, ... } = v; + //~^ ERROR expected field pattern +} + +fn main() {} diff --git a/tests/ui/parser/issue-102806.stderr b/tests/ui/parser/issue-102806.stderr new file mode 100644 index 000000000..6872b8bc0 --- /dev/null +++ b/tests/ui/parser/issue-102806.stderr @@ -0,0 +1,45 @@ +error: expected `..`, found `...` + --> $DIR/issue-102806.rs:11:26 + | +LL | let _ = V3 { z: 0.0, ...v}; + | ^^^ + | +help: use `..` to fill in the rest of the fields + | +LL | let _ = V3 { z: 0.0, ..v}; + | ~~ + +error: expected `..`, found `...` + --> $DIR/issue-102806.rs:14:26 + | +LL | let _ = V3 { z: 0.0, ...Default::default() }; + | ^^^ + | +help: use `..` to fill in the rest of the fields + | +LL | let _ = V3 { z: 0.0, ..Default::default() }; + | ~~ + +error: expected identifier, found `...` + --> $DIR/issue-102806.rs:17:26 + | +LL | let _ = V3 { z: 0.0, ... }; + | -- ^^^ expected identifier + | | + | while parsing this struct + +error: expected field pattern, found `...` + --> $DIR/issue-102806.rs:21:22 + | +LL | let V3 { z: val, ... } = v; + | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + +error[E0063]: missing fields `x` and `y` in initializer of `V3` + --> $DIR/issue-102806.rs:17:13 + | +LL | let _ = V3 { z: 0.0, ... }; + | ^^ missing `x` and `y` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/issue-103143.rs b/tests/ui/parser/issue-103143.rs new file mode 100644 index 000000000..a584274c4 --- /dev/null +++ b/tests/ui/parser/issue-103143.rs @@ -0,0 +1,5 @@ +fn main() { + x::<#[a]y::> + //~^ ERROR invalid const generic expression + //~| ERROR cannot find value `x` in this scope +} diff --git a/tests/ui/parser/issue-103143.stderr b/tests/ui/parser/issue-103143.stderr new file mode 100644 index 000000000..4035c69af --- /dev/null +++ b/tests/ui/parser/issue-103143.stderr @@ -0,0 +1,20 @@ +error: invalid const generic expression + --> $DIR/issue-103143.rs:2:13 + | +LL | x::<#[a]y::> + | ^^^^^^ + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | x::<#[a]{ y:: }> + | + + + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-103143.rs:2:5 + | +LL | x::<#[a]y::> + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/issue-103381.fixed b/tests/ui/parser/issue-103381.fixed new file mode 100644 index 000000000..6a9fb9910 --- /dev/null +++ b/tests/ui/parser/issue-103381.fixed @@ -0,0 +1,59 @@ +// run-rustfix + +#![feature(let_chains)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(irrefutable_let_patterns)] + +fn err_some(b: bool, x: Option) { + if b && let Some(x) = x {} + //~^ ERROR unexpected `if` in the condition expression +} + +fn err_none(b: bool, x: Option) { + if b && let None = x {} + //~^ ERROR unexpected `if` in the condition expression +} + +fn err_bool_1() { + if true && true { true } else { false }; + //~^ ERROR unexpected `if` in the condition expression +} + +fn err_bool_2() { + if true && false { true } else { false }; + //~^ ERROR unexpected `if` in the condition expression +} + +fn should_ok_1() { + if true && if let x = 1 { true } else { true } {} +} + +fn should_ok_2() { + if true && if let 1 = 1 { true } else { true } {} +} + +fn should_ok_3() { + if true && if true { true } else { false } {} +} + +fn shoule_match_ok() { + #[cfg(feature = "full")] + { + let a = 1; + let b = 2; + if match a { + 1 if b == 1 => true, + _ => false, + } && if a > 1 { true } else { false } + { + true + } + } +} + +fn should_ok_in_nested() { + if true && if true { true } else { false } { true } else { false }; +} + +fn main() {} diff --git a/tests/ui/parser/issue-103381.rs b/tests/ui/parser/issue-103381.rs new file mode 100644 index 000000000..bf79e1010 --- /dev/null +++ b/tests/ui/parser/issue-103381.rs @@ -0,0 +1,59 @@ +// run-rustfix + +#![feature(let_chains)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(irrefutable_let_patterns)] + +fn err_some(b: bool, x: Option) { + if b && if let Some(x) = x {} + //~^ ERROR unexpected `if` in the condition expression +} + +fn err_none(b: bool, x: Option) { + if b && if let None = x {} + //~^ ERROR unexpected `if` in the condition expression +} + +fn err_bool_1() { + if true && if true { true } else { false }; + //~^ ERROR unexpected `if` in the condition expression +} + +fn err_bool_2() { + if true && if false { true } else { false }; + //~^ ERROR unexpected `if` in the condition expression +} + +fn should_ok_1() { + if true && if let x = 1 { true } else { true } {} +} + +fn should_ok_2() { + if true && if let 1 = 1 { true } else { true } {} +} + +fn should_ok_3() { + if true && if true { true } else { false } {} +} + +fn shoule_match_ok() { + #[cfg(feature = "full")] + { + let a = 1; + let b = 2; + if match a { + 1 if b == 1 => true, + _ => false, + } && if a > 1 { true } else { false } + { + true + } + } +} + +fn should_ok_in_nested() { + if true && if true { true } else { false } { true } else { false }; +} + +fn main() {} diff --git a/tests/ui/parser/issue-103381.stderr b/tests/ui/parser/issue-103381.stderr new file mode 100644 index 000000000..85fcc18e7 --- /dev/null +++ b/tests/ui/parser/issue-103381.stderr @@ -0,0 +1,50 @@ +error: unexpected `if` in the condition expression + --> $DIR/issue-103381.rs:9:12 + | +LL | if b && if let Some(x) = x {} + | ^^^^ + | +help: remove the `if` + | +LL - if b && if let Some(x) = x {} +LL + if b && let Some(x) = x {} + | + +error: unexpected `if` in the condition expression + --> $DIR/issue-103381.rs:14:12 + | +LL | if b && if let None = x {} + | ^^^^ + | +help: remove the `if` + | +LL - if b && if let None = x {} +LL + if b && let None = x {} + | + +error: unexpected `if` in the condition expression + --> $DIR/issue-103381.rs:19:15 + | +LL | if true && if true { true } else { false }; + | ^^^^ + | +help: remove the `if` + | +LL - if true && if true { true } else { false }; +LL + if true && true { true } else { false }; + | + +error: unexpected `if` in the condition expression + --> $DIR/issue-103381.rs:24:15 + | +LL | if true && if false { true } else { false }; + | ^^^^ + | +help: remove the `if` + | +LL - if true && if false { true } else { false }; +LL + if true && false { true } else { false }; + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issue-103425.rs b/tests/ui/parser/issue-103425.rs new file mode 100644 index 000000000..c2f8123ca --- /dev/null +++ b/tests/ui/parser/issue-103425.rs @@ -0,0 +1,15 @@ +fn f() -> f32 { + 3 + //~^ ERROR expected `;` + 5.0 +} + +fn k() -> f32 { + 2_u32 + //~^ ERROR expected `;` + 3_i8 + //~^ ERROR expected `;` + 5.0 +} + +fn main() {} diff --git a/tests/ui/parser/issue-103425.stderr b/tests/ui/parser/issue-103425.stderr new file mode 100644 index 000000000..0efe3e3ca --- /dev/null +++ b/tests/ui/parser/issue-103425.stderr @@ -0,0 +1,29 @@ +error: expected `;`, found `5.0` + --> $DIR/issue-103425.rs:2:6 + | +LL | 3 + | ^ help: add `;` here +LL | +LL | 5.0 + | --- unexpected token + +error: expected `;`, found `3_i8` + --> $DIR/issue-103425.rs:8:10 + | +LL | 2_u32 + | ^ help: add `;` here +LL | +LL | 3_i8 + | ---- unexpected token + +error: expected `;`, found `5.0` + --> $DIR/issue-103425.rs:10:9 + | +LL | 3_i8 + | ^ help: add `;` here +LL | +LL | 5.0 + | --- unexpected token + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issue-103451.rs b/tests/ui/parser/issue-103451.rs new file mode 100644 index 000000000..1fdb00148 --- /dev/null +++ b/tests/ui/parser/issue-103451.rs @@ -0,0 +1,5 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected value, found struct `R` +struct R { } +struct S { + x: [u8; R diff --git a/tests/ui/parser/issue-103451.stderr b/tests/ui/parser/issue-103451.stderr new file mode 100644 index 000000000..eb3c92fb4 --- /dev/null +++ b/tests/ui/parser/issue-103451.stderr @@ -0,0 +1,32 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-103451.rs:5:15 + | +LL | struct S { + | - unclosed delimiter +LL | x: [u8; R + | - ^ + | | + | unclosed delimiter + +error[E0423]: expected value, found struct `R` + --> $DIR/issue-103451.rs:5:13 + | +LL | struct R { } + | ------------ `R` defined here +LL | struct S { +LL | x: [u8; R + | ^ help: use struct literal syntax instead: `R {}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/parser/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issue-103748-ICE-wrong-braces.rs new file mode 100644 index 000000000..8012cb652 --- /dev/null +++ b/tests/ui/parser/issue-103748-ICE-wrong-braces.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +struct Apple((Apple, Option(Banana ? Citron))); +//~^ ERROR invalid `?` in type +//~| ERROR expected one of `)` or `,`, found `Citron` +//~| ERROR cannot find type `Citron` in this scope [E0412] +//~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214] +//~| ERROR recursive type `Apple` has infinite size [E0072] diff --git a/tests/ui/parser/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issue-103748-ICE-wrong-braces.stderr new file mode 100644 index 000000000..b0d8b03ae --- /dev/null +++ b/tests/ui/parser/issue-103748-ICE-wrong-braces.stderr @@ -0,0 +1,51 @@ +error: invalid `?` in type + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:36 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | struct Apple((Apple, Option(Option Citron))); + | +++++++ ~ + +error: expected one of `)` or `,`, found `Citron` + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | -^^^^^^ expected one of `)` or `,` + | | + | help: missing `,` + +error[E0412]: cannot find type `Citron` in this scope + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^^^^^^ not found in this scope + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:22 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^^^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | struct Apple((Apple, Option)); + | ~ ~ + +error[E0072]: recursive type `Apple` has infinite size + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^^^^^^^^^^^^ ----- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Apple((Box, Option(Banana ? Citron))); + | ++++ + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0072, E0214, E0412. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/parser/issue-103869.rs b/tests/ui/parser/issue-103869.rs new file mode 100644 index 000000000..28c442bdd --- /dev/null +++ b/tests/ui/parser/issue-103869.rs @@ -0,0 +1,9 @@ +enum VecOrMap{ + vec: Vec, + //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `:` + //~| HELP: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + //~| ERROR expected item, found `:` + map: HashMap +} + +fn main() {} diff --git a/tests/ui/parser/issue-103869.stderr b/tests/ui/parser/issue-103869.stderr new file mode 100644 index 000000000..0b8cd919a --- /dev/null +++ b/tests/ui/parser/issue-103869.stderr @@ -0,0 +1,16 @@ +error: expected one of `(`, `,`, `=`, `{`, or `}`, found `:` + --> $DIR/issue-103869.rs:2:8 + | +LL | vec: Vec, + | ^ expected one of `(`, `,`, `=`, `{`, or `}` + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: expected item, found `:` + --> $DIR/issue-103869.rs:2:8 + | +LL | vec: Vec, + | ^ expected item + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issue-104620.rs b/tests/ui/parser/issue-104620.rs new file mode 100644 index 000000000..f49476c44 --- /dev/null +++ b/tests/ui/parser/issue-104620.rs @@ -0,0 +1,4 @@ +#![feature(rustc_attrs)] + +#![rustc_dummy=5z] //~ ERROR unexpected expression: `5z` +fn main() {} diff --git a/tests/ui/parser/issue-104620.stderr b/tests/ui/parser/issue-104620.stderr new file mode 100644 index 000000000..d06a6b255 --- /dev/null +++ b/tests/ui/parser/issue-104620.stderr @@ -0,0 +1,8 @@ +error: unexpected expression: `5z` + --> $DIR/issue-104620.rs:3:16 + | +LL | #![rustc_dummy=5z] + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-104867-inc-dec-2.rs b/tests/ui/parser/issue-104867-inc-dec-2.rs new file mode 100644 index 000000000..a006421a9 --- /dev/null +++ b/tests/ui/parser/issue-104867-inc-dec-2.rs @@ -0,0 +1,52 @@ +fn test1() { + let mut i = 0; + let _ = i + ++i; //~ ERROR Rust has no prefix increment operator +} + +fn test2() { + let mut i = 0; + let _ = ++i + i; //~ ERROR Rust has no prefix increment operator +} + +fn test3() { + let mut i = 0; + let _ = ++i + ++i; //~ ERROR Rust has no prefix increment operator +} + +fn test4() { + let mut i = 0; + let _ = i + i++; //~ ERROR Rust has no postfix increment operator + // won't suggest since we can not handle the precedences +} + +fn test5() { + let mut i = 0; + let _ = i++ + i; //~ ERROR Rust has no postfix increment operator +} + +fn test6() { + let mut i = 0; + let _ = i++ + i++; //~ ERROR Rust has no postfix increment operator +} + +fn test7() { + let mut i = 0; + let _ = ++i + i++; //~ ERROR Rust has no prefix increment operator +} + +fn test8() { + let mut i = 0; + let _ = i++ + ++i; //~ ERROR Rust has no postfix increment operator +} + +fn test9() { + let mut i = 0; + let _ = (1 + 2 + i)++; //~ ERROR Rust has no postfix increment operator +} + +fn test10() { + let mut i = 0; + let _ = (i++ + 1) + 2; //~ ERROR Rust has no postfix increment operator +} + +fn main() { } diff --git a/tests/ui/parser/issue-104867-inc-dec-2.stderr b/tests/ui/parser/issue-104867-inc-dec-2.stderr new file mode 100644 index 000000000..4e2d05468 --- /dev/null +++ b/tests/ui/parser/issue-104867-inc-dec-2.stderr @@ -0,0 +1,107 @@ +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:3:17 + | +LL | let _ = i + ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = i + { i += 1; i }; + | ~ +++++++++ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:8:13 + | +LL | let _ = ++i + i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = { i += 1; i } + i; + | ~ +++++++++ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:13:13 + | +LL | let _ = ++i + ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = { i += 1; i } + ++i; + | ~ +++++++++ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:18:18 + | +LL | let _ = i + i++; + | ^^ not a valid postfix operator + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:24:14 + | +LL | let _ = i++ + i; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i; i += 1; tmp } + i; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:29:14 + | +LL | let _ = i++ + i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i; i += 1; tmp } + i++; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:34:13 + | +LL | let _ = ++i + i++; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | let _ = { i += 1; i } + i++; + | ~ +++++++++ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:39:14 + | +LL | let _ = i++ + ++i; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = i; i += 1; tmp } + ++i; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:44:24 + | +LL | let _ = (1 + 2 + i)++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) += 1; tmp }; + | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec-2.rs:49:15 + | +LL | let _ = (i++ + 1) + 2; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | let _ = ({ let tmp = i; i += 1; tmp } + 1) + 2; + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/parser/issue-104867-inc-dec.rs b/tests/ui/parser/issue-104867-inc-dec.rs new file mode 100644 index 000000000..760c67b4b --- /dev/null +++ b/tests/ui/parser/issue-104867-inc-dec.rs @@ -0,0 +1,45 @@ +struct S { + x: i32, +} + +fn test1() { + let mut i = 0; + i++; //~ ERROR Rust has no postfix increment operator +} + +fn test2() { + let s = S { x: 0 }; + s.x++; //~ ERROR Rust has no postfix increment operator +} + +fn test3() { + let mut i = 0; + if i++ == 1 {} //~ ERROR Rust has no postfix increment operator +} + +fn test4() { + let mut i = 0; + ++i; //~ ERROR Rust has no prefix increment operator +} + +fn test5() { + let mut i = 0; + if ++i == 1 { } //~ ERROR Rust has no prefix increment operator +} + +fn test6() { + let mut i = 0; + loop { break; } + i++; //~ ERROR Rust has no postfix increment operator + loop { break; } + ++i; +} + +fn test7() { + let mut i = 0; + loop { break; } + ++i; //~ ERROR Rust has no prefix increment operator +} + + +fn main() {} diff --git a/tests/ui/parser/issue-104867-inc-dec.stderr b/tests/ui/parser/issue-104867-inc-dec.stderr new file mode 100644 index 000000000..78bfd3e82 --- /dev/null +++ b/tests/ui/parser/issue-104867-inc-dec.stderr @@ -0,0 +1,81 @@ +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:7:6 + | +LL | i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | i += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:12:8 + | +LL | s.x++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | s.x += 1; + | ~~~~ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:17:9 + | +LL | if i++ == 1 {} + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | if { let tmp = i; i += 1; tmp } == 1 {} + | +++++++++++ ~~~~~~~~~~~~~~~ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec.rs:22:5 + | +LL | ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++i; +LL + i += 1; + | + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec.rs:27:8 + | +LL | if ++i == 1 { } + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL | if { i += 1; i } == 1 { } + | ~ +++++++++ + +error: Rust has no postfix increment operator + --> $DIR/issue-104867-inc-dec.rs:33:6 + | +LL | i++; + | ^^ not a valid postfix operator + | +help: use `+= 1` instead + | +LL | i += 1; + | ~~~~ + +error: Rust has no prefix increment operator + --> $DIR/issue-104867-inc-dec.rs:41:5 + | +LL | ++i; + | ^^ not a valid prefix operator + | +help: use `+= 1` instead + | +LL - ++i; +LL + i += 1; + | + +error: aborting due to 7 previous errors + diff --git a/tests/ui/parser/issue-105366.fixed b/tests/ui/parser/issue-105366.fixed new file mode 100644 index 000000000..ad26643c3 --- /dev/null +++ b/tests/ui/parser/issue-105366.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +struct Foo; + +impl From for Foo { + //~^ ERROR you might have meant to write `impl` instead of `fn` + fn from(_a: i32) -> Self { + Foo + } +} + +fn main() {} diff --git a/tests/ui/parser/issue-105366.rs b/tests/ui/parser/issue-105366.rs new file mode 100644 index 000000000..311b6a60f --- /dev/null +++ b/tests/ui/parser/issue-105366.rs @@ -0,0 +1,12 @@ +// run-rustfix + +struct Foo; + +fn From for Foo { + //~^ ERROR you might have meant to write `impl` instead of `fn` + fn from(_a: i32) -> Self { + Foo + } +} + +fn main() {} diff --git a/tests/ui/parser/issue-105366.stderr b/tests/ui/parser/issue-105366.stderr new file mode 100644 index 000000000..0a7408e2c --- /dev/null +++ b/tests/ui/parser/issue-105366.stderr @@ -0,0 +1,13 @@ +error: you might have meant to write `impl` instead of `fn` + --> $DIR/issue-105366.rs:5:1 + | +LL | fn From for Foo { + | ^^ + | +help: replace `fn` with `impl` here + | +LL | impl From for Foo { + | ~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-105634.rs b/tests/ui/parser/issue-105634.rs new file mode 100644 index 000000000..579aa6e5b --- /dev/null +++ b/tests/ui/parser/issue-105634.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() { + let _a = ..; + let _b = ..=10; + let _c = &..; + let _d = &..=10; +} diff --git a/tests/ui/parser/issue-17718-parse-const.rs b/tests/ui/parser/issue-17718-parse-const.rs new file mode 100644 index 000000000..d5a5f445d --- /dev/null +++ b/tests/ui/parser/issue-17718-parse-const.rs @@ -0,0 +1,7 @@ +// run-pass + +const FOO: usize = 3; + +fn main() { + assert_eq!(FOO, 3); +} diff --git a/tests/ui/parser/issue-39616.rs b/tests/ui/parser/issue-39616.rs new file mode 100644 index 000000000..46b5aa334 --- /dev/null +++ b/tests/ui/parser/issue-39616.rs @@ -0,0 +1,3 @@ +fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0` + +fn main() {} diff --git a/tests/ui/parser/issue-39616.stderr b/tests/ui/parser/issue-39616.stderr new file mode 100644 index 000000000..393d1f2e2 --- /dev/null +++ b/tests/ui/parser/issue-39616.stderr @@ -0,0 +1,8 @@ +error: expected type, found `0` + --> $DIR/issue-39616.rs:1:12 + | +LL | fn foo(a: [0; 1]) {} + | ^ expected type + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-49257.rs b/tests/ui/parser/issue-49257.rs new file mode 100644 index 000000000..a7fa19d52 --- /dev/null +++ b/tests/ui/parser/issue-49257.rs @@ -0,0 +1,14 @@ +// Test for #49257: +// emits good diagnostics for `..` pattern fragments not in the last position. + +#![allow(unused)] + +struct Point { x: u8, y: u8 } + +fn main() { + let p = Point { x: 0, y: 0 }; + let Point { .., y, } = p; //~ ERROR expected `}`, found `,` + let Point { .., y } = p; //~ ERROR expected `}`, found `,` + let Point { .., } = p; //~ ERROR expected `}`, found `,` + let Point { .. } = p; +} diff --git a/tests/ui/parser/issue-49257.stderr b/tests/ui/parser/issue-49257.stderr new file mode 100644 index 000000000..846467f7f --- /dev/null +++ b/tests/ui/parser/issue-49257.stderr @@ -0,0 +1,42 @@ +error: expected `}`, found `,` + --> $DIR/issue-49257.rs:10:19 + | +LL | let Point { .., y, } = p; + | --^ + | | | + | | expected `}` + | `..` must be at the end and cannot have a trailing comma + | +help: move the `..` to the end of the field list + | +LL - let Point { .., y, } = p; +LL + let Point { y, .. } = p; + | + +error: expected `}`, found `,` + --> $DIR/issue-49257.rs:11:19 + | +LL | let Point { .., y } = p; + | --^ + | | | + | | expected `}` + | `..` must be at the end and cannot have a trailing comma + | +help: move the `..` to the end of the field list + | +LL - let Point { .., y } = p; +LL + let Point { y , .. } = p; + | + +error: expected `}`, found `,` + --> $DIR/issue-49257.rs:12:19 + | +LL | let Point { .., } = p; + | --^ + | | | + | | expected `}` + | | help: remove this comma + | `..` must be at the end and cannot have a trailing comma + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issue-61858.rs b/tests/ui/parser/issue-61858.rs new file mode 100644 index 000000000..6c3b56586 --- /dev/null +++ b/tests/ui/parser/issue-61858.rs @@ -0,0 +1,3 @@ +fn main() { + (if foobar) //~ ERROR expected `{`, found `)` +} diff --git a/tests/ui/parser/issue-61858.stderr b/tests/ui/parser/issue-61858.stderr new file mode 100644 index 000000000..03f51c6e3 --- /dev/null +++ b/tests/ui/parser/issue-61858.stderr @@ -0,0 +1,14 @@ +error: expected `{`, found `)` + --> $DIR/issue-61858.rs:2:15 + | +LL | (if foobar) + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-61858.rs:2:9 + | +LL | (if foobar) + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-68091-unicode-ident-after-if.rs b/tests/ui/parser/issue-68091-unicode-ident-after-if.rs new file mode 100644 index 000000000..57d36feb3 --- /dev/null +++ b/tests/ui/parser/issue-68091-unicode-ident-after-if.rs @@ -0,0 +1,10 @@ +macro_rules! x { + ($($c:tt)*) => { + $($c)ö* {} + //~^ ERROR missing condition for `if` expression + }; +} + +fn main() { + x!(if); +} diff --git a/tests/ui/parser/issue-68091-unicode-ident-after-if.stderr b/tests/ui/parser/issue-68091-unicode-ident-after-if.stderr new file mode 100644 index 000000000..6674b924e --- /dev/null +++ b/tests/ui/parser/issue-68091-unicode-ident-after-if.stderr @@ -0,0 +1,10 @@ +error: missing condition for `if` expression + --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14 + | +LL | $($c)ö* {} + | ^ - if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.rs b/tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.rs new file mode 100644 index 000000000..1a90b4724 --- /dev/null +++ b/tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.rs @@ -0,0 +1,9 @@ +macro_rules! x { + ($($c:tt)*) => { + $($c)ö* //~ ERROR macro expansion ends with an incomplete expression: expected expression + }; +} + +fn main() { + x!(!); +} diff --git a/tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.stderr b/tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.stderr new file mode 100644 index 000000000..0b9c364f1 --- /dev/null +++ b/tests/ui/parser/issue-68092-unicode-ident-after-incomplete-expr.stderr @@ -0,0 +1,8 @@ +error: macro expansion ends with an incomplete expression: expected expression + --> $DIR/issue-68092-unicode-ident-after-incomplete-expr.rs:3:14 + | +LL | $($c)ö* + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-81804.rs b/tests/ui/parser/issue-81804.rs new file mode 100644 index 000000000..803bde11e --- /dev/null +++ b/tests/ui/parser/issue-81804.rs @@ -0,0 +1,9 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected pattern, found `=` +// error-pattern: expected one of `)`, `,`, `->`, `where`, or `{`, found `]` +// error-pattern: expected item, found `]` + +fn main() {} + +fn p([=(} diff --git a/tests/ui/parser/issue-81804.stderr b/tests/ui/parser/issue-81804.stderr new file mode 100644 index 000000000..19c4422c6 --- /dev/null +++ b/tests/ui/parser/issue-81804.stderr @@ -0,0 +1,41 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-81804.rs:9:11 + | +LL | fn p([=(} + | -- ^ + | || + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-81804.rs:9:11 + | +LL | fn p([=(} + | -- ^ + | || + | |unclosed delimiter + | unclosed delimiter + +error: expected pattern, found `=` + --> $DIR/issue-81804.rs:9:7 + | +LL | fn p([=(} + | ^ expected pattern + +error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]` + --> $DIR/issue-81804.rs:9:8 + | +LL | fn p([=(} + | ^ -^ + | | | + | | help: `)` may belong here + | unclosed delimiter + +error: expected item, found `]` + --> $DIR/issue-81804.rs:9:11 + | +LL | fn p([=(} + | ^ expected item + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/issue-81827.rs b/tests/ui/parser/issue-81827.rs new file mode 100644 index 000000000..7ec581594 --- /dev/null +++ b/tests/ui/parser/issue-81827.rs @@ -0,0 +1,11 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: mismatched closing delimiter: `]` +// error-pattern: expected one of `)` or `,`, found `{` + +#![crate_name="0"] + + + +fn main() {} + +fn r()->i{0|{#[cfg(r(0{]0 diff --git a/tests/ui/parser/issue-81827.stderr b/tests/ui/parser/issue-81827.stderr new file mode 100644 index 000000000..069de3391 --- /dev/null +++ b/tests/ui/parser/issue-81827.stderr @@ -0,0 +1,35 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-81827.rs:11:27 + | +LL | fn r()->i{0|{#[cfg(r(0{]0 + | - - ^ + | | | + | | unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-81827.rs:11:27 + | +LL | fn r()->i{0|{#[cfg(r(0{]0 + | - - ^ + | | | + | | unclosed delimiter + | unclosed delimiter + +error: mismatched closing delimiter: `]` + --> $DIR/issue-81827.rs:11:23 + | +LL | fn r()->i{0|{#[cfg(r(0{]0 + | - ^^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: expected one of `)` or `,`, found `{` + --> $DIR/issue-81827.rs:11:23 + | +LL | fn r()->i{0|{#[cfg(r(0{]0 + | ^ expected one of `)` or `,` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issue-87694-duplicated-pub.rs b/tests/ui/parser/issue-87694-duplicated-pub.rs new file mode 100644 index 000000000..e3ea61dc4 --- /dev/null +++ b/tests/ui/parser/issue-87694-duplicated-pub.rs @@ -0,0 +1,5 @@ +pub const pub fn test() {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` +//~| HELP there is already a visibility modifier, remove one +//~| NOTE explicit visibility first seen here diff --git a/tests/ui/parser/issue-87694-duplicated-pub.stderr b/tests/ui/parser/issue-87694-duplicated-pub.stderr new file mode 100644 index 000000000..8d242bc9d --- /dev/null +++ b/tests/ui/parser/issue-87694-duplicated-pub.stderr @@ -0,0 +1,17 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-87694-duplicated-pub.rs:1:11 + | +LL | pub const pub fn test() {} + | ^^^ + | | + | expected one of `async`, `extern`, `fn`, or `unsafe` + | help: there is already a visibility modifier, remove one + | +note: explicit visibility first seen here + --> $DIR/issue-87694-duplicated-pub.rs:1:1 + | +LL | pub const pub fn test() {} + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-87694-misplaced-pub.rs b/tests/ui/parser/issue-87694-misplaced-pub.rs new file mode 100644 index 000000000..3f824617c --- /dev/null +++ b/tests/ui/parser/issue-87694-misplaced-pub.rs @@ -0,0 +1,5 @@ +const pub fn test() {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` +//~| HELP visibility `pub` must come before `const` +//~| SUGGESTION pub const diff --git a/tests/ui/parser/issue-87694-misplaced-pub.stderr b/tests/ui/parser/issue-87694-misplaced-pub.stderr new file mode 100644 index 000000000..94c6a29ef --- /dev/null +++ b/tests/ui/parser/issue-87694-misplaced-pub.stderr @@ -0,0 +1,11 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-87694-misplaced-pub.rs:1:7 + | +LL | const pub fn test() {} + | ------^^^ + | | | + | | expected one of `async`, `extern`, `fn`, or `unsafe` + | help: visibility `pub` must come before `const`: `pub const` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-90728.rs b/tests/ui/parser/issue-90728.rs new file mode 100644 index 000000000..d6a898361 --- /dev/null +++ b/tests/ui/parser/issue-90728.rs @@ -0,0 +1,6 @@ +fn main() { + a.5.2E+ + //~^ ERROR: unexpected token: `5.2E+` + //~| ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `5.2E+` + //~| ERROR: expected at least one digit in exponent +} diff --git a/tests/ui/parser/issue-90728.stderr b/tests/ui/parser/issue-90728.stderr new file mode 100644 index 000000000..b55c46030 --- /dev/null +++ b/tests/ui/parser/issue-90728.stderr @@ -0,0 +1,20 @@ +error: expected at least one digit in exponent + --> $DIR/issue-90728.rs:2:7 + | +LL | a.5.2E+ + | ^^^^^ + +error: unexpected token: `5.2E+` + --> $DIR/issue-90728.rs:2:7 + | +LL | a.5.2E+ + | ^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `5.2E+` + --> $DIR/issue-90728.rs:2:7 + | +LL | a.5.2E+ + | ^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issue-91421.rs b/tests/ui/parser/issue-91421.rs new file mode 100644 index 000000000..8bba27f37 --- /dev/null +++ b/tests/ui/parser/issue-91421.rs @@ -0,0 +1,9 @@ +// Regression test for issue #91421. + +fn main() { + let value = if true && { + //~^ ERROR: this `if` expression is missing a block after the condition + //~| HELP: this binary operation is possibly unfinished + 3 + } else { 4 }; +} diff --git a/tests/ui/parser/issue-91421.stderr b/tests/ui/parser/issue-91421.stderr new file mode 100644 index 000000000..2d9652051 --- /dev/null +++ b/tests/ui/parser/issue-91421.stderr @@ -0,0 +1,14 @@ +error: this `if` expression is missing a block after the condition + --> $DIR/issue-91421.rs:4:17 + | +LL | let value = if true && { + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/issue-91421.rs:4:20 + | +LL | let value = if true && { + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.fixed b/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.fixed new file mode 100644 index 000000000..4b4a416b1 --- /dev/null +++ b/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +pub enum Range { + //~^ ERROR `enum` and `struct` are mutually exclusive + Valid { + begin: u32, + len: u32, + }, + Out, +} + +fn main() { +} diff --git a/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.rs b/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.rs new file mode 100644 index 000000000..9cc886641 --- /dev/null +++ b/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.rs @@ -0,0 +1,13 @@ +// run-rustfix + +pub enum struct Range { + //~^ ERROR `enum` and `struct` are mutually exclusive + Valid { + begin: u32, + len: u32, + }, + Out, +} + +fn main() { +} diff --git a/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.stderr b/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.stderr new file mode 100644 index 000000000..edc640bf5 --- /dev/null +++ b/tests/ui/parser/issue-99625-enum-struct-mutually-exclusive.stderr @@ -0,0 +1,8 @@ +error: `enum` and `struct` are mutually exclusive + --> $DIR/issue-99625-enum-struct-mutually-exclusive.rs:3:5 + | +LL | pub enum struct Range { + | ^^^^^^^^^^^ help: replace `enum struct` with: `enum` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issue-99910-const-let-mutually-exclusive.fixed b/tests/ui/parser/issue-99910-const-let-mutually-exclusive.fixed new file mode 100644 index 000000000..64ab6f62b --- /dev/null +++ b/tests/ui/parser/issue-99910-const-let-mutually-exclusive.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + const _FOO: i32 = 123; + //~^ ERROR const` and `let` are mutually exclusive + const _BAR: i32 = 123; + //~^ ERROR `const` and `let` are mutually exclusive +} diff --git a/tests/ui/parser/issue-99910-const-let-mutually-exclusive.rs b/tests/ui/parser/issue-99910-const-let-mutually-exclusive.rs new file mode 100644 index 000000000..50520971f --- /dev/null +++ b/tests/ui/parser/issue-99910-const-let-mutually-exclusive.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + const let _FOO: i32 = 123; + //~^ ERROR const` and `let` are mutually exclusive + let const _BAR: i32 = 123; + //~^ ERROR `const` and `let` are mutually exclusive +} diff --git a/tests/ui/parser/issue-99910-const-let-mutually-exclusive.stderr b/tests/ui/parser/issue-99910-const-let-mutually-exclusive.stderr new file mode 100644 index 000000000..72377fc37 --- /dev/null +++ b/tests/ui/parser/issue-99910-const-let-mutually-exclusive.stderr @@ -0,0 +1,14 @@ +error: `const` and `let` are mutually exclusive + --> $DIR/issue-99910-const-let-mutually-exclusive.rs:4:5 + | +LL | const let _FOO: i32 = 123; + | ^^^^^^^^^ help: remove `let`: `const` + +error: `const` and `let` are mutually exclusive + --> $DIR/issue-99910-const-let-mutually-exclusive.rs:6:5 + | +LL | let const _BAR: i32 = 123; + | ^^^^^^^^^ help: remove `let`: `const` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/auxiliary/issue-21146-inc.rs b/tests/ui/parser/issues/auxiliary/issue-21146-inc.rs new file mode 100644 index 000000000..32a3b9dcc --- /dev/null +++ b/tests/ui/parser/issues/auxiliary/issue-21146-inc.rs @@ -0,0 +1,3 @@ +// include file for issue-21146.rs + +parse_error diff --git a/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs b/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs new file mode 100644 index 000000000..e5604b816 --- /dev/null +++ b/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ICE)] +pub fn derive(_: TokenStream) -> TokenStream { + r#"#[allow(missing_docs)] struct X { }"#.parse().unwrap() +} diff --git a/tests/ui/parser/issues/auxiliary/issue-94340-inc.rs b/tests/ui/parser/issues/auxiliary/issue-94340-inc.rs new file mode 100644 index 000000000..9429e5143 --- /dev/null +++ b/tests/ui/parser/issues/auxiliary/issue-94340-inc.rs @@ -0,0 +1,3 @@ +// include file for issue-94340.rs +#![deny(rust_2018_idioms)] +#![deny(unused_must_use)] diff --git a/tests/ui/parser/issues/issue-101540.rs b/tests/ui/parser/issues/issue-101540.rs new file mode 100644 index 000000000..328ec6f90 --- /dev/null +++ b/tests/ui/parser/issues/issue-101540.rs @@ -0,0 +1,7 @@ +struct S1 { + struct S2 { + //~^ ERROR structs are not allowed in struct definitions + } +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-101540.stderr b/tests/ui/parser/issues/issue-101540.stderr new file mode 100644 index 000000000..8af887050 --- /dev/null +++ b/tests/ui/parser/issues/issue-101540.stderr @@ -0,0 +1,12 @@ +error: structs are not allowed in struct definitions + --> $DIR/issue-101540.rs:2:5 + | +LL | struct S1 { + | -- while parsing this struct +LL | struct S2 { + | ^^^^^^^^^ + | + = help: consider creating a new `struct` definition instead of nesting + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-102182-impl-trait-recover.rs b/tests/ui/parser/issues/issue-102182-impl-trait-recover.rs new file mode 100644 index 000000000..4bfc676d6 --- /dev/null +++ b/tests/ui/parser/issues/issue-102182-impl-trait-recover.rs @@ -0,0 +1,3 @@ +fn foo() {} +//~^ ERROR expected trait bound, found `impl Trait` type +fn main() {} diff --git a/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr b/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr new file mode 100644 index 000000000..52b6ae5df --- /dev/null +++ b/tests/ui/parser/issues/issue-102182-impl-trait-recover.stderr @@ -0,0 +1,14 @@ +error: expected trait bound, found `impl Trait` type + --> $DIR/issue-102182-impl-trait-recover.rs:1:11 + | +LL | fn foo() {} + | ^^^^^^^^^^ not a trait + | +help: use the trait bounds directly + | +LL - fn foo() {} +LL + fn foo() {} + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-10392-2.fixed b/tests/ui/parser/issues/issue-10392-2.fixed new file mode 100644 index 000000000..3386fac17 --- /dev/null +++ b/tests/ui/parser/issues/issue-10392-2.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +pub struct A { pub foo: isize } + +fn a() -> A { panic!() } + +fn main() { + let A { .. } = a(); //~ ERROR: expected `}` +} diff --git a/tests/ui/parser/issues/issue-10392-2.rs b/tests/ui/parser/issues/issue-10392-2.rs new file mode 100644 index 000000000..30628ae31 --- /dev/null +++ b/tests/ui/parser/issues/issue-10392-2.rs @@ -0,0 +1,9 @@ +// run-rustfix + +pub struct A { pub foo: isize } + +fn a() -> A { panic!() } + +fn main() { + let A { .., } = a(); //~ ERROR: expected `}` +} diff --git a/tests/ui/parser/issues/issue-10392-2.stderr b/tests/ui/parser/issues/issue-10392-2.stderr new file mode 100644 index 000000000..4154ecfeb --- /dev/null +++ b/tests/ui/parser/issues/issue-10392-2.stderr @@ -0,0 +1,12 @@ +error: expected `}`, found `,` + --> $DIR/issue-10392-2.rs:8:15 + | +LL | let A { .., } = a(); + | --^ + | | | + | | expected `}` + | | help: remove this comma + | `..` must be at the end and cannot have a trailing comma + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-10392.rs b/tests/ui/parser/issues/issue-10392.rs new file mode 100644 index 000000000..5b0c2fc2b --- /dev/null +++ b/tests/ui/parser/issues/issue-10392.rs @@ -0,0 +1,7 @@ +struct A { foo: isize } + +fn a() -> A { panic!() } + +fn main() { + let A { , } = a(); //~ ERROR expected ident +} diff --git a/tests/ui/parser/issues/issue-10392.stderr b/tests/ui/parser/issues/issue-10392.stderr new file mode 100644 index 000000000..438ea67d3 --- /dev/null +++ b/tests/ui/parser/issues/issue-10392.stderr @@ -0,0 +1,10 @@ +error: expected identifier, found `,` + --> $DIR/issue-10392.rs:6:13 + | +LL | let A { , } = a(); + | - ^ expected identifier + | | + | while parsing the fields for this pattern + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-104088.rs b/tests/ui/parser/issues/issue-104088.rs new file mode 100644 index 000000000..5f794fe2d --- /dev/null +++ b/tests/ui/parser/issues/issue-104088.rs @@ -0,0 +1,26 @@ +fn test() { + if let 123 = 123 { println!("yes"); } +} + +fn test_2() { + let 1x = 123; + //~^ ERROR expected identifier, found number literal +} + +fn test_3() { + let 2x: i32 = 123; + //~^ ERROR expected identifier, found number literal +} + +fn test_4() { + if let 2e1 = 123 { + //~^ ERROR mismatched types + } +} + +fn test_5() { + let 23name = 123; + //~^ ERROR expected identifier, found number literal +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-104088.stderr b/tests/ui/parser/issues/issue-104088.stderr new file mode 100644 index 000000000..ff4b4bdb6 --- /dev/null +++ b/tests/ui/parser/issues/issue-104088.stderr @@ -0,0 +1,29 @@ +error: expected identifier, found number literal + --> $DIR/issue-104088.rs:6:9 + | +LL | let 1x = 123; + | ^^ identifiers cannot start with a number + +error: expected identifier, found number literal + --> $DIR/issue-104088.rs:11:9 + | +LL | let 2x: i32 = 123; + | ^^ identifiers cannot start with a number + +error: expected identifier, found number literal + --> $DIR/issue-104088.rs:22:9 + | +LL | let 23name = 123; + | ^^^^^^ identifiers cannot start with a number + +error[E0308]: mismatched types + --> $DIR/issue-104088.rs:16:12 + | +LL | if let 2e1 = 123 { + | ^^^ --- this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-10636-1.rs b/tests/ui/parser/issues/issue-10636-1.rs new file mode 100644 index 000000000..77c6072d6 --- /dev/null +++ b/tests/ui/parser/issues/issue-10636-1.rs @@ -0,0 +1,8 @@ +struct Obj { + //~^ NOTE: unclosed delimiter + member: usize +) +//~^ ERROR mismatched closing delimiter +//~| NOTE mismatched closing delimiter + +fn main() {} diff --git a/tests/ui/parser/issues/issue-10636-1.stderr b/tests/ui/parser/issues/issue-10636-1.stderr new file mode 100644 index 000000000..1e6294ebe --- /dev/null +++ b/tests/ui/parser/issues/issue-10636-1.stderr @@ -0,0 +1,11 @@ +error: mismatched closing delimiter: `)` + --> $DIR/issue-10636-1.rs:1:12 + | +LL | struct Obj { + | ^ unclosed delimiter +... +LL | ) + | ^ mismatched closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs new file mode 100644 index 000000000..6fb63639d --- /dev/null +++ b/tests/ui/parser/issues/issue-10636-2.rs @@ -0,0 +1,11 @@ +// FIXME(31528) we emit a bunch of silly errors here due to continuing past the +// first one. This would be easy-ish to address by better recovery in tokenisation. + +pub fn trace_option(option: Option) { + option.map(|some| 42; + //~^ ERROR: expected one of + +} +//~^ ERROR: expected expression, found `)` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-10636-2.stderr b/tests/ui/parser/issues/issue-10636-2.stderr new file mode 100644 index 000000000..d4f2da9e3 --- /dev/null +++ b/tests/ui/parser/issues/issue-10636-2.stderr @@ -0,0 +1,16 @@ +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` + --> $DIR/issue-10636-2.rs:5:15 + | +LL | option.map(|some| 42; + | ^ ^ help: `)` may belong here + | | + | unclosed delimiter + +error: expected expression, found `)` + --> $DIR/issue-10636-2.rs:8:1 + | +LL | } + | ^ expected expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-13483.rs b/tests/ui/parser/issues/issue-13483.rs new file mode 100644 index 000000000..4e32fcab3 --- /dev/null +++ b/tests/ui/parser/issues/issue-13483.rs @@ -0,0 +1,17 @@ +fn main() { + if true { + } else if { + //~^ ERROR missing condition for `if` expression + } else { + } +} + +fn foo() { + if true { + } else if { + //~^ ERROR missing condition for `if` expression + } + bar(); +} + +fn bar() {} diff --git a/tests/ui/parser/issues/issue-13483.stderr b/tests/ui/parser/issues/issue-13483.stderr new file mode 100644 index 000000000..f5534090f --- /dev/null +++ b/tests/ui/parser/issues/issue-13483.stderr @@ -0,0 +1,18 @@ +error: missing condition for `if` expression + --> $DIR/issue-13483.rs:3:14 + | +LL | } else if { + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: missing condition for `if` expression + --> $DIR/issue-13483.rs:11:14 + | +LL | } else if { + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-14303-fncall.full.stderr b/tests/ui/parser/issues/issue-14303-fncall.full.stderr new file mode 100644 index 000000000..0c152516a --- /dev/null +++ b/tests/ui/parser/issues/issue-14303-fncall.full.stderr @@ -0,0 +1,9 @@ +error[E0747]: type provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:15:26 + | +LL | .collect::>>(); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr new file mode 100644 index 000000000..571815776 --- /dev/null +++ b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr @@ -0,0 +1,9 @@ +error[E0747]: inferred provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:15:26 + | +LL | .collect::>>(); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/parser/issues/issue-14303-fncall.rs b/tests/ui/parser/issues/issue-14303-fncall.rs new file mode 100644 index 000000000..afc4959f1 --- /dev/null +++ b/tests/ui/parser/issues/issue-14303-fncall.rs @@ -0,0 +1,20 @@ +// revisions: full generic_arg +// can't run rustfix because it doesn't handle multipart suggestions correctly +// we need the above to avoid ast borrowck failure in recovered code +#![cfg_attr(generic_arg, feature(generic_arg_infer))] + + +struct S<'a, T> { + a: &'a T, + b: &'a T, +} + +fn foo<'a, 'b>(start: &'a usize, end: &'a usize) { + let _x = (*start..*end) + .map(|x| S { a: start, b: end }) + .collect::>>(); + //[generic_arg]~^ ERROR inferred provided when a lifetime was expected + //[full]~^^ ERROR type provided when a lifetime was expected +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-14303.rs b/tests/ui/parser/issues/issue-14303.rs new file mode 100644 index 000000000..82850d77a --- /dev/null +++ b/tests/ui/parser/issues/issue-14303.rs @@ -0,0 +1,33 @@ +enum Enum<'a, T, 'b> { +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + A(&'a &'b T) +} + +struct Struct<'a, T, 'b> { +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + x: &'a &'b T +} + +trait Trait<'a, T, 'b> {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +fn foo<'a, T, 'b>(x: &'a T) {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +struct Y(T); +impl<'a, T, 'b> Y {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +mod bar { + pub struct X<'a, 'b, 'c, T> { + a: &'a str, + b: &'b str, + c: &'c str, + t: T, + } +} + +fn bar<'a, 'b, 'c, T>(x: bar::X<'a, T, 'b, 'c>) {} +//~^ ERROR type provided when a lifetime was expected + +fn main() {} diff --git a/tests/ui/parser/issues/issue-14303.stderr b/tests/ui/parser/issues/issue-14303.stderr new file mode 100644 index 000000000..f121107c0 --- /dev/null +++ b/tests/ui/parser/issues/issue-14303.stderr @@ -0,0 +1,39 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-14303.rs:1:18 + | +LL | enum Enum<'a, T, 'b> { + | --------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-14303.rs:6:22 + | +LL | struct Struct<'a, T, 'b> { + | --------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-14303.rs:11:20 + | +LL | trait Trait<'a, T, 'b> {} + | --------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-14303.rs:14:15 + | +LL | fn foo<'a, T, 'b>(x: &'a T) {} + | --------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-14303.rs:18:13 + | +LL | impl<'a, T, 'b> Y {} + | --------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error[E0747]: type provided when a lifetime was expected + --> $DIR/issue-14303.rs:30:37 + | +LL | fn bar<'a, 'b, 'c, T>(x: bar::X<'a, T, 'b, 'c>) {} + | ^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/parser/issues/issue-15914.rs b/tests/ui/parser/issues/issue-15914.rs new file mode 100644 index 000000000..4a5606af6 --- /dev/null +++ b/tests/ui/parser/issues/issue-15914.rs @@ -0,0 +1,4 @@ +fn main() { + let ref + (); //~ ERROR expected identifier, found `(` +} diff --git a/tests/ui/parser/issues/issue-15914.stderr b/tests/ui/parser/issues/issue-15914.stderr new file mode 100644 index 000000000..ea26453f8 --- /dev/null +++ b/tests/ui/parser/issues/issue-15914.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `(` + --> $DIR/issue-15914.rs:3:9 + | +LL | (); + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-15980.rs b/tests/ui/parser/issues/issue-15980.rs new file mode 100644 index 000000000..87faa7d5f --- /dev/null +++ b/tests/ui/parser/issues/issue-15980.rs @@ -0,0 +1,17 @@ +use std::io; + +fn main(){ + let x: io::Result<()> = Ok(()); + match x { + Err(ref e) if e.kind == io::EndOfFile { + //~^ NOTE while parsing this struct + return + //~^ ERROR expected identifier, found keyword `return` + //~| NOTE expected identifier, found keyword + } + //~^ NOTE expected one of `.`, `=>`, `?`, or an operator + _ => {} + //~^ ERROR expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_` + //~| NOTE unexpected token + } +} diff --git a/tests/ui/parser/issues/issue-15980.stderr b/tests/ui/parser/issues/issue-15980.stderr new file mode 100644 index 000000000..c59c81119 --- /dev/null +++ b/tests/ui/parser/issues/issue-15980.stderr @@ -0,0 +1,25 @@ +error: expected identifier, found keyword `return` + --> $DIR/issue-15980.rs:8:13 + | +LL | Err(ref e) if e.kind == io::EndOfFile { + | ------------- while parsing this struct +LL | +LL | return + | ^^^^^^ expected identifier, found keyword + | +help: escape `return` to use it as an identifier + | +LL | r#return + | ++ + +error: expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_` + --> $DIR/issue-15980.rs:13:9 + | +LL | } + | - expected one of `.`, `=>`, `?`, or an operator +LL | +LL | _ => {} + | ^ unexpected token + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-1655.rs b/tests/ui/parser/issues/issue-1655.rs new file mode 100644 index 000000000..e9fc6f153 --- /dev/null +++ b/tests/ui/parser/issues/issue-1655.rs @@ -0,0 +1,10 @@ +mod blade_runner { + #vec[doc( //~ ERROR expected one of `!` or `[`, found `vec` + brief = "Blade Runner is probably the best movie ever", + desc = "I like that in the world of Blade Runner it is always + raining, and that it's always night time. And Aliens + was also a really good movie. + + Alien 3 was crap though." + )] +} diff --git a/tests/ui/parser/issues/issue-1655.stderr b/tests/ui/parser/issues/issue-1655.stderr new file mode 100644 index 000000000..0c390a0ec --- /dev/null +++ b/tests/ui/parser/issues/issue-1655.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `[`, found `vec` + --> $DIR/issue-1655.rs:2:6 + | +LL | #vec[doc( + | ^^^ expected one of `!` or `[` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-17718-const-mut.rs b/tests/ui/parser/issues/issue-17718-const-mut.rs new file mode 100644 index 000000000..795a8c763 --- /dev/null +++ b/tests/ui/parser/issues/issue-17718-const-mut.rs @@ -0,0 +1,7 @@ +const +mut //~ ERROR: const globals cannot be mutable +//~^^ HELP you might want to declare a static instead +FOO: usize = 3; + +fn main() { +} diff --git a/tests/ui/parser/issues/issue-17718-const-mut.stderr b/tests/ui/parser/issues/issue-17718-const-mut.stderr new file mode 100644 index 000000000..8251ce999 --- /dev/null +++ b/tests/ui/parser/issues/issue-17718-const-mut.stderr @@ -0,0 +1,10 @@ +error: const globals cannot be mutable + --> $DIR/issue-17718-const-mut.rs:2:1 + | +LL | const + | ----- help: you might want to declare a static instead: `static` +LL | mut + | ^^^ cannot be mutable + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-17904-2.rs b/tests/ui/parser/issues/issue-17904-2.rs new file mode 100644 index 000000000..186a955c3 --- /dev/null +++ b/tests/ui/parser/issues/issue-17904-2.rs @@ -0,0 +1,3 @@ +struct Bar { x: T } where T: Copy //~ ERROR expected item, found keyword `where` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-17904-2.stderr b/tests/ui/parser/issues/issue-17904-2.stderr new file mode 100644 index 000000000..9c7fdf6cc --- /dev/null +++ b/tests/ui/parser/issues/issue-17904-2.stderr @@ -0,0 +1,8 @@ +error: expected item, found keyword `where` + --> $DIR/issue-17904-2.rs:1:24 + | +LL | struct Bar { x: T } where T: Copy + | ^^^^^ expected item + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-17904.rs b/tests/ui/parser/issues/issue-17904.rs new file mode 100644 index 000000000..020fb41c2 --- /dev/null +++ b/tests/ui/parser/issues/issue-17904.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zparse-only + +struct Baz where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. +struct Baz where U: Eq(U) -> R; // Notice this parses as well. +struct Baz(U) where U: Eq; // This rightfully signals no error as well. +struct Foo where T: Copy, (T); //~ ERROR where clauses are not allowed before tuple struct bodies + +fn main() {} diff --git a/tests/ui/parser/issues/issue-17904.stderr b/tests/ui/parser/issues/issue-17904.stderr new file mode 100644 index 000000000..aa343975d --- /dev/null +++ b/tests/ui/parser/issues/issue-17904.stderr @@ -0,0 +1,17 @@ +error: where clauses are not allowed before tuple struct bodies + --> $DIR/issue-17904.rs:6:15 + | +LL | struct Foo where T: Copy, (T); + | --- ^^^^^^^^^^^^^^ --- the struct body + | | | + | | unexpected where clause + | while parsing this tuple struct + | +help: move the body before the where clause + | +LL - struct Foo where T: Copy, (T); +LL + struct Foo(T) where T: Copy; + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-1802-1.rs b/tests/ui/parser/issues/issue-1802-1.rs new file mode 100644 index 000000000..3c34b0d8f --- /dev/null +++ b/tests/ui/parser/issues/issue-1802-1.rs @@ -0,0 +1,7 @@ +fn log(a: i32, b: i32) {} + +fn main() { + let error = 42; + log(error, 0b); + //~^ ERROR no valid digits found for number +} diff --git a/tests/ui/parser/issues/issue-1802-1.stderr b/tests/ui/parser/issues/issue-1802-1.stderr new file mode 100644 index 000000000..954cc0bee --- /dev/null +++ b/tests/ui/parser/issues/issue-1802-1.stderr @@ -0,0 +1,9 @@ +error[E0768]: no valid digits found for number + --> $DIR/issue-1802-1.rs:5:16 + | +LL | log(error, 0b); + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0768`. diff --git a/tests/ui/parser/issues/issue-1802-2.rs b/tests/ui/parser/issues/issue-1802-2.rs new file mode 100644 index 000000000..3c34b0d8f --- /dev/null +++ b/tests/ui/parser/issues/issue-1802-2.rs @@ -0,0 +1,7 @@ +fn log(a: i32, b: i32) {} + +fn main() { + let error = 42; + log(error, 0b); + //~^ ERROR no valid digits found for number +} diff --git a/tests/ui/parser/issues/issue-1802-2.stderr b/tests/ui/parser/issues/issue-1802-2.stderr new file mode 100644 index 000000000..49043d07b --- /dev/null +++ b/tests/ui/parser/issues/issue-1802-2.stderr @@ -0,0 +1,9 @@ +error[E0768]: no valid digits found for number + --> $DIR/issue-1802-2.rs:5:16 + | +LL | log(error, 0b); + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0768`. diff --git a/tests/ui/parser/issues/issue-19096.rs b/tests/ui/parser/issues/issue-19096.rs new file mode 100644 index 000000000..c5bfd10ee --- /dev/null +++ b/tests/ui/parser/issues/issue-19096.rs @@ -0,0 +1,10 @@ +fn main() { // we don't complain about the return type being `{integer}` + let t = (42, 42); + t.0::; //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `::` +} + +fn foo() -> usize { // we don't complain about the return type being unit + let t = (42, 42); + t.0::; //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `::` + 42; +} diff --git a/tests/ui/parser/issues/issue-19096.stderr b/tests/ui/parser/issues/issue-19096.stderr new file mode 100644 index 000000000..4df7f878b --- /dev/null +++ b/tests/ui/parser/issues/issue-19096.stderr @@ -0,0 +1,14 @@ +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `::` + --> $DIR/issue-19096.rs:3:8 + | +LL | t.0::; + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `::` + --> $DIR/issue-19096.rs:8:8 + | +LL | t.0::; + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-19398.rs b/tests/ui/parser/issues/issue-19398.rs new file mode 100644 index 000000000..46eb320a1 --- /dev/null +++ b/tests/ui/parser/issues/issue-19398.rs @@ -0,0 +1,6 @@ +trait T { + extern "Rust" unsafe fn foo(); + //~^ ERROR expected `{`, found keyword `unsafe` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-19398.stderr b/tests/ui/parser/issues/issue-19398.stderr new file mode 100644 index 000000000..1da00960a --- /dev/null +++ b/tests/ui/parser/issues/issue-19398.stderr @@ -0,0 +1,13 @@ +error: expected `{`, found keyword `unsafe` + --> $DIR/issue-19398.rs:2:19 + | +LL | trait T { + | - while parsing this item list starting here +LL | extern "Rust" unsafe fn foo(); + | ^^^^^^ expected `{` +LL | +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-1.rs b/tests/ui/parser/issues/issue-20616-1.rs new file mode 100644 index 000000000..49e9cb310 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-1.rs @@ -0,0 +1,36 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + + + +type Type_1_<'a, T> = &'a T; + + +type Type_1<'a T> = &'a T; //~ error: expected one of `,`, `:`, or `>`, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-1.stderr b/tests/ui/parser/issues/issue-20616-1.stderr new file mode 100644 index 000000000..816046237 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-1.stderr @@ -0,0 +1,8 @@ +error: expected one of `,`, `:`, or `>`, found `T` + --> $DIR/issue-20616-1.rs:9:16 + | +LL | type Type_1<'a T> = &'a T; + | ^ expected one of `,`, `:`, or `>` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-2.rs b/tests/ui/parser/issues/issue-20616-2.rs new file mode 100644 index 000000000..2f2c6903a --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-2.rs @@ -0,0 +1,36 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + + + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +type Type_2 = Type_1_<'static ()>; //~ error: expected one of `,` or `>`, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-2.stderr b/tests/ui/parser/issues/issue-20616-2.stderr new file mode 100644 index 000000000..42059685c --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-2.stderr @@ -0,0 +1,13 @@ +error: expected one of `,` or `>`, found `(` + --> $DIR/issue-20616-2.rs:12:31 + | +LL | type Type_2 = Type_1_<'static ()>; + | ^ expected one of `,` or `>` + | +help: you might have meant to end the type parameters here + | +LL | type Type_2 = Type_1_<'static> ()>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-3.rs b/tests/ui/parser/issues/issue-20616-3.rs new file mode 100644 index 000000000..b2371051c --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-3.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +type Type_3 = Box; +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-3.stderr b/tests/ui/parser/issues/issue-20616-3.stderr new file mode 100644 index 000000000..dbff116e5 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-3.stderr @@ -0,0 +1,13 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `,` + --> $DIR/issue-20616-3.rs:13:24 + | +LL | type Type_3 = Box; + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_3 = Box,,>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-4.rs b/tests/ui/parser/issues/issue-20616-4.rs new file mode 100644 index 000000000..a71f47ca4 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-4.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +type Type_4 = Type_1_<'static,, T>; +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-4.stderr b/tests/ui/parser/issues/issue-20616-4.stderr new file mode 100644 index 000000000..48a06e00b --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-4.stderr @@ -0,0 +1,13 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `,` + --> $DIR/issue-20616-4.rs:16:34 + | +LL | type Type_4 = Type_1_<'static,, T>; + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_4 = Type_1_<'static>,, T>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-5.rs b/tests/ui/parser/issues/issue-20616-5.rs new file mode 100644 index 000000000..b96d09d59 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-5.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +type Type_5<'a> = Type_1_<'a, (),,>; +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-5.stderr b/tests/ui/parser/issues/issue-20616-5.stderr new file mode 100644 index 000000000..84bee2ad1 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-5.stderr @@ -0,0 +1,13 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `,` + --> $DIR/issue-20616-5.rs:22:34 + | +LL | type Type_5<'a> = Type_1_<'a, (),,>; + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_5<'a> = Type_1_<'a, ()>,,>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-6.rs b/tests/ui/parser/issues/issue-20616-6.rs new file mode 100644 index 000000000..a2c45ecec --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-6.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +type Type_6 = Type_5_<'a,,>; +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-6.stderr b/tests/ui/parser/issues/issue-20616-6.stderr new file mode 100644 index 000000000..67de41b97 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-6.stderr @@ -0,0 +1,13 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `,` + --> $DIR/issue-20616-6.rs:25:26 + | +LL | type Type_6 = Type_5_<'a,,>; + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_6 = Type_5_<'a>,,>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-7.rs b/tests/ui/parser/issues/issue-20616-7.rs new file mode 100644 index 000000000..67209c02a --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-7.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +type Type_7 = Box<(),,>; +//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected ident, found `,` + + +//type Type_9 = Box; // error: expected ident, found `,` diff --git a/tests/ui/parser/issues/issue-20616-7.stderr b/tests/ui/parser/issues/issue-20616-7.stderr new file mode 100644 index 000000000..3b8e07fa0 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-7.stderr @@ -0,0 +1,13 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `,` + --> $DIR/issue-20616-7.rs:28:22 + | +LL | type Type_7 = Box<(),,>; + | ^ expected one of `>`, a const expression, lifetime, or type + | +help: you might have meant to end the type parameters here + | +LL | type Type_7 = Box<()>,,>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-8.rs b/tests/ui/parser/issues/issue-20616-8.rs new file mode 100644 index 000000000..3ceb58d12 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-8.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +type Type_8<'a,,> = &'a (); +//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + + +//type Type_9 = Box; // error: expected identifier, found `,` diff --git a/tests/ui/parser/issues/issue-20616-8.stderr b/tests/ui/parser/issues/issue-20616-8.stderr new file mode 100644 index 000000000..e9f37e50f --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-8.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + --> $DIR/issue-20616-8.rs:31:16 + | +LL | type Type_8<'a,,> = &'a (); + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20616-9.rs b/tests/ui/parser/issues/issue-20616-9.rs new file mode 100644 index 000000000..7f8428448 --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-9.rs @@ -0,0 +1,35 @@ +// We need all these 9 issue-20616-N.rs files +// because we can only catch one parsing error at a time + +type Type_1_<'a, T> = &'a T; + + +//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T` + + +//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(` + + +//type Type_3 = Box; // error: expected type, found `,` + + +//type Type_4 = Type_1_<'static,, T>; // error: expected type, found `,` + + +type Type_5_<'a> = Type_1_<'a, ()>; + + +//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,` + + +//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,` + + +//type Type_7 = Box<(),,>; // error: expected type, found `,` + + +//type Type_8<'a,,> = &'a (); // error: expected identifier, found `,` + + +type Type_9 = Box; +//~^ error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` diff --git a/tests/ui/parser/issues/issue-20616-9.stderr b/tests/ui/parser/issues/issue-20616-9.stderr new file mode 100644 index 000000000..dc309d1bc --- /dev/null +++ b/tests/ui/parser/issues/issue-20616-9.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `,` + --> $DIR/issue-20616-9.rs:34:15 + | +LL | type Type_9 = Box; + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20711-2.rs b/tests/ui/parser/issues/issue-20711-2.rs new file mode 100644 index 000000000..168c7e761 --- /dev/null +++ b/tests/ui/parser/issues/issue-20711-2.rs @@ -0,0 +1,10 @@ +struct Foo; + +impl Foo { + fn foo() {} + + #[stable(feature = "rust1", since = "1.0.0")] + //~^ ERROR expected item after attributes +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-20711-2.stderr b/tests/ui/parser/issues/issue-20711-2.stderr new file mode 100644 index 000000000..12b18bbc5 --- /dev/null +++ b/tests/ui/parser/issues/issue-20711-2.stderr @@ -0,0 +1,14 @@ +error: expected item after attributes + --> $DIR/issue-20711-2.rs:6:5 + | +LL | impl Foo { + | - while parsing this item list starting here +... +LL | #[stable(feature = "rust1", since = "1.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-20711.rs b/tests/ui/parser/issues/issue-20711.rs new file mode 100644 index 000000000..020bb79d6 --- /dev/null +++ b/tests/ui/parser/issues/issue-20711.rs @@ -0,0 +1,8 @@ +struct Foo; + +impl Foo { + #[stable(feature = "rust1", since = "1.0.0")] + //~^ ERROR expected item after attributes +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-20711.stderr b/tests/ui/parser/issues/issue-20711.stderr new file mode 100644 index 000000000..4af4b22be --- /dev/null +++ b/tests/ui/parser/issues/issue-20711.stderr @@ -0,0 +1,13 @@ +error: expected item after attributes + --> $DIR/issue-20711.rs:4:5 + | +LL | impl Foo { + | - while parsing this item list starting here +LL | #[stable(feature = "rust1", since = "1.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-21146.rs b/tests/ui/parser/issues/issue-21146.rs new file mode 100644 index 000000000..19eaffc3e --- /dev/null +++ b/tests/ui/parser/issues/issue-21146.rs @@ -0,0 +1,3 @@ +// error-pattern: expected one of `!` or `::`, found `` +include!("auxiliary/issue-21146-inc.rs"); +fn main() {} diff --git a/tests/ui/parser/issues/issue-21146.stderr b/tests/ui/parser/issues/issue-21146.stderr new file mode 100644 index 000000000..c71fda3d6 --- /dev/null +++ b/tests/ui/parser/issues/issue-21146.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `` + --> $DIR/auxiliary/issue-21146-inc.rs:3:1 + | +LL | parse_error + | ^^^^^^^^^^^ expected one of `!` or `::` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-21153.rs b/tests/ui/parser/issues/issue-21153.rs new file mode 100644 index 000000000..bf5fdb1f3 --- /dev/null +++ b/tests/ui/parser/issues/issue-21153.rs @@ -0,0 +1,6 @@ +trait MyTrait: Iterator { + Item = T; + //~^ ERROR expected one of `!` or `::`, found `=` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-21153.stderr b/tests/ui/parser/issues/issue-21153.stderr new file mode 100644 index 000000000..cbfa9ded3 --- /dev/null +++ b/tests/ui/parser/issues/issue-21153.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found `=` + --> $DIR/issue-21153.rs:2:10 + | +LL | trait MyTrait: Iterator { + | - while parsing this item list starting here +LL | Item = T; + | ^ expected one of `!` or `::` +LL | +LL | } + | - the item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-21475.rs b/tests/ui/parser/issues/issue-21475.rs new file mode 100644 index 000000000..b028fcae0 --- /dev/null +++ b/tests/ui/parser/issues/issue-21475.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_imports, overlapping_range_endpoints)] +// pretty-expanded FIXME #23616 + +use m::{START, END}; + +fn main() { + match 42 { + m::START..=m::END => {}, + 0..=m::END => {}, + m::START..=59 => {}, + _ => {}, + } +} + +mod m { + pub const START: u32 = 4; + pub const END: u32 = 14; +} diff --git a/tests/ui/parser/issues/issue-22647.rs b/tests/ui/parser/issues/issue-22647.rs new file mode 100644 index 000000000..a68614106 --- /dev/null +++ b/tests/ui/parser/issues/issue-22647.rs @@ -0,0 +1,15 @@ +fn main() { + let caller = |f: F| //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` + where F: Fn() -> i32 + { + let x = f(); + println!("Y {}",x); + return x; + }; + + caller(bar_handler); +} + +fn bar_handler() -> i32 { + 5 +} diff --git a/tests/ui/parser/issues/issue-22647.stderr b/tests/ui/parser/issues/issue-22647.stderr new file mode 100644 index 000000000..89b454d19 --- /dev/null +++ b/tests/ui/parser/issues/issue-22647.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` + --> $DIR/issue-22647.rs:2:15 + | +LL | let caller = |f: F| + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-22712.rs b/tests/ui/parser/issues/issue-22712.rs new file mode 100644 index 000000000..774de9c7e --- /dev/null +++ b/tests/ui/parser/issues/issue-22712.rs @@ -0,0 +1,9 @@ +struct Foo { + buffer: B +} + +fn bar() { + let Foo> //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `<` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-22712.stderr b/tests/ui/parser/issues/issue-22712.stderr new file mode 100644 index 000000000..30fabac65 --- /dev/null +++ b/tests/ui/parser/issues/issue-22712.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `<` + --> $DIR/issue-22712.rs:6:12 + | +LL | let Foo> + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-2354-1.rs b/tests/ui/parser/issues/issue-2354-1.rs new file mode 100644 index 000000000..996cf1bcb --- /dev/null +++ b/tests/ui/parser/issues/issue-2354-1.rs @@ -0,0 +1 @@ +static foo: isize = 2; } //~ ERROR unexpected closing delimiter: diff --git a/tests/ui/parser/issues/issue-2354-1.stderr b/tests/ui/parser/issues/issue-2354-1.stderr new file mode 100644 index 000000000..7ea0f2a98 --- /dev/null +++ b/tests/ui/parser/issues/issue-2354-1.stderr @@ -0,0 +1,8 @@ +error: unexpected closing delimiter: `}` + --> $DIR/issue-2354-1.rs:1:24 + | +LL | static foo: isize = 2; } + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-2354.rs b/tests/ui/parser/issues/issue-2354.rs new file mode 100644 index 000000000..c422040cb --- /dev/null +++ b/tests/ui/parser/issues/issue-2354.rs @@ -0,0 +1,15 @@ +fn foo() { //~ NOTE unclosed delimiter + match Some(10) { + //~^ NOTE this delimiter might not be properly closed... + Some(y) => { panic!(); } + None => { panic!(); } +} +//~^ NOTE ...as it matches this but it has different indentation + +fn bar() { + let mut i = 0; + while (i < 1000) {} +} + +fn main() {} +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/issues/issue-2354.stderr b/tests/ui/parser/issues/issue-2354.stderr new file mode 100644 index 000000000..b89ed3958 --- /dev/null +++ b/tests/ui/parser/issues/issue-2354.stderr @@ -0,0 +1,16 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-2354.rs:15:52 + | +LL | fn foo() { + | - unclosed delimiter +LL | match Some(10) { + | - this delimiter might not be properly closed... +... +LL | } + | - ...as it matches this but it has different indentation +... +LL | + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-23620-invalid-escapes.rs b/tests/ui/parser/issues/issue-23620-invalid-escapes.rs new file mode 100644 index 000000000..c1355f0d6 --- /dev/null +++ b/tests/ui/parser/issues/issue-23620-invalid-escapes.rs @@ -0,0 +1,34 @@ +fn main() { + let _ = b"\u{a66e}"; + //~^ ERROR unicode escape in byte string + + let _ = b'\u{a66e}'; + //~^ ERROR unicode escape in byte string + + let _ = b'\u'; + //~^ ERROR incorrect unicode escape sequence + + let _ = b'\x5'; + //~^ ERROR numeric character escape is too short + + let _ = b'\xxy'; + //~^ ERROR invalid character in numeric character escape: `x` + + let _ = '\x5'; + //~^ ERROR numeric character escape is too short + + let _ = '\xxy'; + //~^ ERROR invalid character in numeric character escape: `x` + + let _ = b"\u{a4a4} \xf \u"; + //~^ ERROR unicode escape in byte string + //~^^ ERROR invalid character in numeric character escape: ` ` + //~^^^ ERROR incorrect unicode escape sequence + + let _ = "\xf \u"; + //~^ ERROR invalid character in numeric character escape: ` ` + //~^^ ERROR incorrect unicode escape sequence + + let _ = "\u8f"; + //~^ ERROR incorrect unicode escape sequence +} diff --git a/tests/ui/parser/issues/issue-23620-invalid-escapes.stderr b/tests/ui/parser/issues/issue-23620-invalid-escapes.stderr new file mode 100644 index 000000000..88d97c795 --- /dev/null +++ b/tests/ui/parser/issues/issue-23620-invalid-escapes.stderr @@ -0,0 +1,94 @@ +error: unicode escape in byte string + --> $DIR/issue-23620-invalid-escapes.rs:2:15 + | +LL | let _ = b"\u{a66e}"; + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: unicode escape in byte string + --> $DIR/issue-23620-invalid-escapes.rs:5:15 + | +LL | let _ = b'\u{a66e}'; + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: incorrect unicode escape sequence + --> $DIR/issue-23620-invalid-escapes.rs:8:15 + | +LL | let _ = b'\u'; + | ^^ incorrect unicode escape sequence + | + = help: format of unicode escape sequences is `\u{...}` + +error: numeric character escape is too short + --> $DIR/issue-23620-invalid-escapes.rs:11:15 + | +LL | let _ = b'\x5'; + | ^^^ + +error: invalid character in numeric character escape: `x` + --> $DIR/issue-23620-invalid-escapes.rs:14:17 + | +LL | let _ = b'\xxy'; + | ^ invalid character in numeric character escape + +error: numeric character escape is too short + --> $DIR/issue-23620-invalid-escapes.rs:17:14 + | +LL | let _ = '\x5'; + | ^^^ + +error: invalid character in numeric character escape: `x` + --> $DIR/issue-23620-invalid-escapes.rs:20:16 + | +LL | let _ = '\xxy'; + | ^ invalid character in numeric character escape + +error: unicode escape in byte string + --> $DIR/issue-23620-invalid-escapes.rs:23:15 + | +LL | let _ = b"\u{a4a4} \xf \u"; + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: invalid character in numeric character escape: ` ` + --> $DIR/issue-23620-invalid-escapes.rs:23:27 + | +LL | let _ = b"\u{a4a4} \xf \u"; + | ^ invalid character in numeric character escape + +error: incorrect unicode escape sequence + --> $DIR/issue-23620-invalid-escapes.rs:23:28 + | +LL | let _ = b"\u{a4a4} \xf \u"; + | ^^ incorrect unicode escape sequence + | + = help: format of unicode escape sequences is `\u{...}` + +error: invalid character in numeric character escape: ` ` + --> $DIR/issue-23620-invalid-escapes.rs:28:17 + | +LL | let _ = "\xf \u"; + | ^ invalid character in numeric character escape + +error: incorrect unicode escape sequence + --> $DIR/issue-23620-invalid-escapes.rs:28:18 + | +LL | let _ = "\xf \u"; + | ^^ incorrect unicode escape sequence + | + = help: format of unicode escape sequences is `\u{...}` + +error: incorrect unicode escape sequence + --> $DIR/issue-23620-invalid-escapes.rs:32:14 + | +LL | let _ = "\u8f"; + | ^^^- + | | + | help: format of unicode escape sequences uses braces: `\u{8f}` + +error: aborting due to 13 previous errors + diff --git a/tests/ui/parser/issues/issue-24197.rs b/tests/ui/parser/issues/issue-24197.rs new file mode 100644 index 000000000..aaf513746 --- /dev/null +++ b/tests/ui/parser/issues/issue-24197.rs @@ -0,0 +1,3 @@ +fn main() { + let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` +} diff --git a/tests/ui/parser/issues/issue-24197.stderr b/tests/ui/parser/issues/issue-24197.stderr new file mode 100644 index 000000000..fd7015ccd --- /dev/null +++ b/tests/ui/parser/issues/issue-24197.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` + --> $DIR/issue-24197.rs:2:12 + | +LL | let buf[0] = 0; + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs new file mode 100644 index 000000000..1d128d33e --- /dev/null +++ b/tests/ui/parser/issues/issue-24375.rs @@ -0,0 +1,9 @@ +static tmp : [&'static str; 2] = ["hello", "he"]; + +fn main() { + let z = "hello"; + match z { + tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[` + _ => {} + } +} diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr new file mode 100644 index 000000000..7aed88768 --- /dev/null +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -0,0 +1,8 @@ +error: expected one of `=>`, `@`, `if`, or `|`, found `[` + --> $DIR/issue-24375.rs:6:12 + | +LL | tmp[0] => {} + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-24780.rs b/tests/ui/parser/issues/issue-24780.rs new file mode 100644 index 000000000..017521f57 --- /dev/null +++ b/tests/ui/parser/issues/issue-24780.rs @@ -0,0 +1,9 @@ +// Verify that '>' is not both expected and found at the same time, as it used +// to happen in #24780. For example, following should be an error: +// expected one of ..., `>`, ... found `>`. + +fn foo() -> Vec> { //~ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>` + Vec::new() +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-24780.stderr b/tests/ui/parser/issues/issue-24780.stderr new file mode 100644 index 000000000..d9470191b --- /dev/null +++ b/tests/ui/parser/issues/issue-24780.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `+`, `::`, `where`, or `{`, found `>` + --> $DIR/issue-24780.rs:5:23 + | +LL | fn foo() -> Vec> { + | ^ expected one of `!`, `+`, `::`, `where`, or `{` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-27255.rs b/tests/ui/parser/issues/issue-27255.rs new file mode 100644 index 000000000..d619688e1 --- /dev/null +++ b/tests/ui/parser/issues/issue-27255.rs @@ -0,0 +1,10 @@ +trait A {} + +impl A .. {} +//~^ ERROR missing `for` in a trait impl +//~| ERROR `impl Trait for .. {}` is an obsolete syntax + +impl A usize {} +//~^ ERROR missing `for` in a trait impl + +fn main() {} diff --git a/tests/ui/parser/issues/issue-27255.stderr b/tests/ui/parser/issues/issue-27255.stderr new file mode 100644 index 000000000..391a23556 --- /dev/null +++ b/tests/ui/parser/issues/issue-27255.stderr @@ -0,0 +1,22 @@ +error: missing `for` in a trait impl + --> $DIR/issue-27255.rs:3:7 + | +LL | impl A .. {} + | ^ help: add `for` here + +error: missing `for` in a trait impl + --> $DIR/issue-27255.rs:7:7 + | +LL | impl A usize {} + | ^^^^^^ help: add `for` here + +error: `impl Trait for .. {}` is an obsolete syntax + --> $DIR/issue-27255.rs:3:1 + | +LL | impl A .. {} + | ^^^^^^^^^^^^ + | + = help: use `auto trait Trait {}` instead + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-30318.fixed b/tests/ui/parser/issues/issue-30318.fixed new file mode 100644 index 000000000..71fc82172 --- /dev/null +++ b/tests/ui/parser/issues/issue-30318.fixed @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(unused)] +fn foo() { } + +/// Misplaced comment... +//~^ ERROR expected outer doc comment +fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function + +#[test] //~ ERROR an inner attribute is not permitted in this context +fn baz() { } //~ NOTE the inner attribute doesn't annotate this function +//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually + +/** Misplaced comment... */ +//~^ ERROR expected outer doc comment +fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function + +fn main() { } + +// Misplaced comment... +//~^ ERROR expected outer doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +//~| NOTE other attributes here +/* Misplaced comment... */ +//~^ ERROR expected outer doc comment +//~| NOTE this doc comment doesn't document anything +//~| ERROR expected item after doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items diff --git a/tests/ui/parser/issues/issue-30318.rs b/tests/ui/parser/issues/issue-30318.rs new file mode 100644 index 000000000..465dca2ff --- /dev/null +++ b/tests/ui/parser/issues/issue-30318.rs @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(unused)] +fn foo() { } + +//! Misplaced comment... +//~^ ERROR expected outer doc comment +fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function + +#![test] //~ ERROR an inner attribute is not permitted in this context +fn baz() { } //~ NOTE the inner attribute doesn't annotate this function +//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually + +/*! Misplaced comment... */ +//~^ ERROR expected outer doc comment +fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function + +fn main() { } + +//! Misplaced comment... +//~^ ERROR expected outer doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +//~| NOTE other attributes here +/*! Misplaced comment... */ +//~^ ERROR expected outer doc comment +//~| NOTE this doc comment doesn't document anything +//~| ERROR expected item after doc comment +//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items diff --git a/tests/ui/parser/issues/issue-30318.stderr b/tests/ui/parser/issues/issue-30318.stderr new file mode 100644 index 000000000..c441a92ab --- /dev/null +++ b/tests/ui/parser/issues/issue-30318.stderr @@ -0,0 +1,81 @@ +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:5:1 + | +LL | //! Misplaced comment... + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn bar() { } + | ------------ the inner doc comment doesn't annotate this function + | +help: to annotate the function, change the doc comment from inner to outer style + | +LL | /// Misplaced comment... + | ~ + +error: an inner attribute is not permitted in this context + --> $DIR/issue-30318.rs:9:1 + | +LL | #![test] + | ^^^^^^^^ +LL | fn baz() { } + | ------------ the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the function, change the attribute from inner to outer style + | +LL - #![test] +LL + #[test] + | + +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:13:1 + | +LL | /*! Misplaced comment... */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn bat() { } + | ------------ the inner doc comment doesn't annotate this function + | +help: to annotate the function, change the doc comment from inner to outer style + | +LL | /** Misplaced comment... */ + | ~ + +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:19:1 + | +LL | //! Misplaced comment... + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - //! Misplaced comment... +LL + // Misplaced comment... + | + +error[E0753]: expected outer doc comment + --> $DIR/issue-30318.rs:23:1 + | +LL | /*! Misplaced comment... */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items +help: you might have meant to write a regular comment + | +LL - /*! Misplaced comment... */ +LL + /* Misplaced comment... */ + | + +error: expected item after doc comment + --> $DIR/issue-30318.rs:23:1 + | +LL | //! Misplaced comment... + | ------------------------ other attributes here +... +LL | /*! Misplaced comment... */ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0753`. diff --git a/tests/ui/parser/issues/issue-3036.fixed b/tests/ui/parser/issues/issue-3036.fixed new file mode 100644 index 000000000..e5d5622e6 --- /dev/null +++ b/tests/ui/parser/issues/issue-3036.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +// Testing that semicolon tokens are printed correctly in errors + +fn main() { + let _x = 3; //~ ERROR: expected `;` +} diff --git a/tests/ui/parser/issues/issue-3036.rs b/tests/ui/parser/issues/issue-3036.rs new file mode 100644 index 000000000..2f76fb99b --- /dev/null +++ b/tests/ui/parser/issues/issue-3036.rs @@ -0,0 +1,7 @@ +// run-rustfix + +// Testing that semicolon tokens are printed correctly in errors + +fn main() { + let _x = 3 //~ ERROR: expected `;` +} diff --git a/tests/ui/parser/issues/issue-3036.stderr b/tests/ui/parser/issues/issue-3036.stderr new file mode 100644 index 000000000..e02223931 --- /dev/null +++ b/tests/ui/parser/issues/issue-3036.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found `}` + --> $DIR/issue-3036.rs:6:15 + | +LL | let _x = 3 + | ^ help: add `;` here +LL | } + | - unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-31804.rs b/tests/ui/parser/issues/issue-31804.rs new file mode 100644 index 000000000..d056b77cf --- /dev/null +++ b/tests/ui/parser/issues/issue-31804.rs @@ -0,0 +1,6 @@ +// Test that error recovery in the parser to an EOF does not give an infinite +// spew of errors. + +fn main() { + let +} //~ ERROR expected pattern, found `}` diff --git a/tests/ui/parser/issues/issue-31804.stderr b/tests/ui/parser/issues/issue-31804.stderr new file mode 100644 index 000000000..76e68b0b3 --- /dev/null +++ b/tests/ui/parser/issues/issue-31804.stderr @@ -0,0 +1,8 @@ +error: expected pattern, found `}` + --> $DIR/issue-31804.rs:6:1 + | +LL | } + | ^ expected pattern + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-32214.rs b/tests/ui/parser/issues/issue-32214.rs new file mode 100644 index 000000000..1379eeb58 --- /dev/null +++ b/tests/ui/parser/issues/issue-32214.rs @@ -0,0 +1,6 @@ +trait Trait { type Item; } + +pub fn test >() {} +//~^ ERROR generic arguments must come before the first constraint + +fn main() { } diff --git a/tests/ui/parser/issues/issue-32214.stderr b/tests/ui/parser/issues/issue-32214.stderr new file mode 100644 index 000000000..d0a9b5299 --- /dev/null +++ b/tests/ui/parser/issues/issue-32214.stderr @@ -0,0 +1,15 @@ +error: generic arguments must come before the first constraint + --> $DIR/issue-32214.rs:3:34 + | +LL | pub fn test >() {} + | ------- ^ generic argument + | | + | constraint + | +help: move the constraint after the generic argument + | +LL | pub fn test >() {} + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-32446.rs b/tests/ui/parser/issues/issue-32446.rs new file mode 100644 index 000000000..53e519a72 --- /dev/null +++ b/tests/ui/parser/issues/issue-32446.rs @@ -0,0 +1,4 @@ +fn main() {} + +// This used to end up in an infite loop trying to bump past EOF. +trait T { ... } //~ ERROR diff --git a/tests/ui/parser/issues/issue-32446.stderr b/tests/ui/parser/issues/issue-32446.stderr new file mode 100644 index 000000000..7515369aa --- /dev/null +++ b/tests/ui/parser/issues/issue-32446.stderr @@ -0,0 +1,11 @@ +error: non-item in item list + --> $DIR/issue-32446.rs:4:11 + | +LL | trait T { ... } + | - ^^^ - item list ends here + | | | + | | non-item starts here + | item list starts here + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-32501.rs b/tests/ui/parser/issues/issue-32501.rs new file mode 100644 index 000000000..500242030 --- /dev/null +++ b/tests/ui/parser/issues/issue-32501.rs @@ -0,0 +1,9 @@ +fn main() { + let a = 0; + let _b = 0; + let _ = 0; + let mut b = 0; + let mut _b = 0; + let mut _ = 0; + //~^ ERROR `mut` must be followed by a named binding +} diff --git a/tests/ui/parser/issues/issue-32501.stderr b/tests/ui/parser/issues/issue-32501.stderr new file mode 100644 index 000000000..d53302449 --- /dev/null +++ b/tests/ui/parser/issues/issue-32501.stderr @@ -0,0 +1,10 @@ +error: `mut` must be followed by a named binding + --> $DIR/issue-32501.rs:7:9 + | +LL | let mut _ = 0; + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-32505.rs b/tests/ui/parser/issues/issue-32505.rs new file mode 100644 index 000000000..f31c00e5c --- /dev/null +++ b/tests/ui/parser/issues/issue-32505.rs @@ -0,0 +1,5 @@ +pub fn test() { + foo(|_|) //~ ERROR expected expression, found `)` +} + +fn main() { } diff --git a/tests/ui/parser/issues/issue-32505.stderr b/tests/ui/parser/issues/issue-32505.stderr new file mode 100644 index 000000000..cdd779a93 --- /dev/null +++ b/tests/ui/parser/issues/issue-32505.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `)` + --> $DIR/issue-32505.rs:2:12 + | +LL | foo(|_|) + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-33262.rs b/tests/ui/parser/issues/issue-33262.rs new file mode 100644 index 000000000..3a612f95c --- /dev/null +++ b/tests/ui/parser/issues/issue-33262.rs @@ -0,0 +1,6 @@ +// Issue #33262 + +pub fn main() { + for i in 0..a as { } + //~^ ERROR expected type, found `{` +} diff --git a/tests/ui/parser/issues/issue-33262.stderr b/tests/ui/parser/issues/issue-33262.stderr new file mode 100644 index 000000000..2aff32839 --- /dev/null +++ b/tests/ui/parser/issues/issue-33262.stderr @@ -0,0 +1,8 @@ +error: expected type, found `{` + --> $DIR/issue-33262.rs:4:22 + | +LL | for i in 0..a as { } + | ^ expected type + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-33413.rs b/tests/ui/parser/issues/issue-33413.rs new file mode 100644 index 000000000..7291732ce --- /dev/null +++ b/tests/ui/parser/issues/issue-33413.rs @@ -0,0 +1,9 @@ +struct S; + +impl S { + fn f(*, a: u8) -> u8 {} + //~^ ERROR expected parameter name, found `*` + //~| ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-33413.stderr b/tests/ui/parser/issues/issue-33413.stderr new file mode 100644 index 000000000..b7250f3b0 --- /dev/null +++ b/tests/ui/parser/issues/issue-33413.stderr @@ -0,0 +1,22 @@ +error: expected parameter name, found `*` + --> $DIR/issue-33413.rs:4:10 + | +LL | fn f(*, a: u8) -> u8 {} + | ^ expected parameter name + +error[E0308]: mismatched types + --> $DIR/issue-33413.rs:4:23 + | +LL | fn f(*, a: u8) -> u8 {} + | - ^^ expected `u8`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +help: consider returning the local binding `a` + | +LL | fn f(*, a: u8) -> u8 { a } + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-33418.fixed b/tests/ui/parser/issues/issue-33418.fixed new file mode 100644 index 000000000..ed885ae14 --- /dev/null +++ b/tests/ui/parser/issues/issue-33418.fixed @@ -0,0 +1,19 @@ +// run-rustfix + +trait Tr {} +//~^ ERROR negative bounds are not supported +trait Tr2: SuperA {} +//~^ ERROR negative bounds are not supported +trait Tr3: SuperB {} +//~^ ERROR negative bounds are not supported +trait Tr4: SuperB + SuperD {} +//~^ ERROR negative bounds are not supported +trait Tr5 {} +//~^ ERROR negative bounds are not supported + +trait SuperA {} +trait SuperB {} +trait SuperC {} +trait SuperD {} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-33418.rs b/tests/ui/parser/issues/issue-33418.rs new file mode 100644 index 000000000..9934284ab --- /dev/null +++ b/tests/ui/parser/issues/issue-33418.rs @@ -0,0 +1,21 @@ +// run-rustfix + +trait Tr: !SuperA {} +//~^ ERROR negative bounds are not supported +trait Tr2: SuperA + !SuperB {} +//~^ ERROR negative bounds are not supported +trait Tr3: !SuperA + SuperB {} +//~^ ERROR negative bounds are not supported +trait Tr4: !SuperA + SuperB + + !SuperC + SuperD {} +//~^ ERROR negative bounds are not supported +trait Tr5: !SuperA + + !SuperB {} +//~^ ERROR negative bounds are not supported + +trait SuperA {} +trait SuperB {} +trait SuperC {} +trait SuperD {} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-33418.stderr b/tests/ui/parser/issues/issue-33418.stderr new file mode 100644 index 000000000..9a8733e89 --- /dev/null +++ b/tests/ui/parser/issues/issue-33418.stderr @@ -0,0 +1,36 @@ +error: negative bounds are not supported + --> $DIR/issue-33418.rs:3:9 + | +LL | trait Tr: !SuperA {} + | ^^^^^^^^^ negative bounds are not supported + +error: negative bounds are not supported + --> $DIR/issue-33418.rs:5:19 + | +LL | trait Tr2: SuperA + !SuperB {} + | ^^^^^^^^^ negative bounds are not supported + +error: negative bounds are not supported + --> $DIR/issue-33418.rs:7:10 + | +LL | trait Tr3: !SuperA + SuperB {} + | ^^^^^^^^^ negative bounds are not supported + +error: negative bounds are not supported + --> $DIR/issue-33418.rs:9:10 + | +LL | trait Tr4: !SuperA + SuperB + | ^^^^^^^^^ +LL | + !SuperC + SuperD {} + | ^^^^^^^^^ negative bounds are not supported + +error: negative bounds are not supported + --> $DIR/issue-33418.rs:12:10 + | +LL | trait Tr5: !SuperA + | ^^^^^^^^^ +LL | + !SuperB {} + | ^^^^^^^^^ negative bounds are not supported + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/issues/issue-33455.rs b/tests/ui/parser/issues/issue-33455.rs new file mode 100644 index 000000000..6dff63f5c --- /dev/null +++ b/tests/ui/parser/issues/issue-33455.rs @@ -0,0 +1 @@ +use foo.bar; //~ ERROR expected one of `::`, `;`, or `as`, found `.` diff --git a/tests/ui/parser/issues/issue-33455.stderr b/tests/ui/parser/issues/issue-33455.stderr new file mode 100644 index 000000000..c535ef23b --- /dev/null +++ b/tests/ui/parser/issues/issue-33455.stderr @@ -0,0 +1,8 @@ +error: expected one of `::`, `;`, or `as`, found `.` + --> $DIR/issue-33455.rs:1:8 + | +LL | use foo.bar; + | ^ expected one of `::`, `;`, or `as` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-34222-1.rs b/tests/ui/parser/issues/issue-34222-1.rs new file mode 100644 index 000000000..d36dddc97 --- /dev/null +++ b/tests/ui/parser/issues/issue-34222-1.rs @@ -0,0 +1,3 @@ +fn main() { + /// comment //~ ERROR found a documentation comment that doesn't document anything +} diff --git a/tests/ui/parser/issues/issue-34222-1.stderr b/tests/ui/parser/issues/issue-34222-1.stderr new file mode 100644 index 000000000..b451484ba --- /dev/null +++ b/tests/ui/parser/issues/issue-34222-1.stderr @@ -0,0 +1,11 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/issue-34222-1.rs:2:5 + | +LL | /// comment + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/issues/issue-34255-1.rs b/tests/ui/parser/issues/issue-34255-1.rs new file mode 100644 index 000000000..c70cd8b50 --- /dev/null +++ b/tests/ui/parser/issues/issue-34255-1.rs @@ -0,0 +1,10 @@ +enum Test { + Drill { + field: i32, + } +} + +fn main() { + Test::Drill(field: 42); + //~^ ERROR invalid `struct` delimiters or `fn` call arguments +} diff --git a/tests/ui/parser/issues/issue-34255-1.stderr b/tests/ui/parser/issues/issue-34255-1.stderr new file mode 100644 index 000000000..0e2b0d62e --- /dev/null +++ b/tests/ui/parser/issues/issue-34255-1.stderr @@ -0,0 +1,18 @@ +error: invalid `struct` delimiters or `fn` call arguments + --> $DIR/issue-34255-1.rs:8:5 + | +LL | Test::Drill(field: 42); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: if `Test::Drill` is a struct, use braces as delimiters + | +LL | Test::Drill { field: 42 }; + | ~ ~ +help: if `Test::Drill` is a function, use the arguments directly + | +LL - Test::Drill(field: 42); +LL + Test::Drill(42); + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs new file mode 100644 index 000000000..7bd4b3a16 --- /dev/null +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs @@ -0,0 +1,171 @@ +// edition:2018 +#![crate_type = "lib"] +#![feature(type_ascription)] +use std::future::Future; +use std::pin::Pin; + +// This tests the parser for "x as Y[z]". It errors, but we want to give useful +// errors and parse such that further code gives useful errors. +pub fn index_after_as_cast() { + vec![1, 2, 3] as Vec[0]; + //~^ ERROR: cast cannot be followed by indexing + vec![1, 2, 3]: Vec[0]; + //~^ ERROR: type ascription cannot be followed by indexing +} + +pub fn index_after_cast_to_index() { + (&[0]) as &[i32][0]; + //~^ ERROR: cast cannot be followed by indexing + (&[0i32]): &[i32; 1][0]; + //~^ ERROR: type ascription cannot be followed by indexing +} + +pub fn cast_after_cast() { + if 5u64 as i32 as u16 == 0u16 { + + } + if 5u64: u64: u64 == 0u64 { + + } + let _ = 5u64: u64: u64 as u8 as i8 == 9i8; + let _ = 0i32: i32: i32; + let _ = 0 as i32: i32; + let _ = 0i32: i32 as i32; + let _ = 0 as i32 as i32; + let _ = 0i32: i32: i32 as u32 as i32; +} + +pub fn cast_cast_method_call() { + let _ = 0i32: i32: i32.count_ones(); + //~^ ERROR: type ascription cannot be followed by a method call + let _ = 0 as i32: i32.count_ones(); + //~^ ERROR: type ascription cannot be followed by a method call + let _ = 0i32: i32 as i32.count_ones(); + //~^ ERROR: cast cannot be followed by a method call + let _ = 0 as i32 as i32.count_ones(); + //~^ ERROR: cast cannot be followed by a method call + let _ = 0i32: i32: i32 as u32 as i32.count_ones(); + //~^ ERROR: cast cannot be followed by a method call + let _ = 0i32: i32.count_ones(): u32; + //~^ ERROR: type ascription cannot be followed by a method call + let _ = 0 as i32.count_ones(): u32; + //~^ ERROR: cast cannot be followed by a method call + let _ = 0i32: i32.count_ones() as u32; + //~^ ERROR: type ascription cannot be followed by a method call + let _ = 0 as i32.count_ones() as u32; + //~^ ERROR: cast cannot be followed by a method call + let _ = 0i32: i32: i32.count_ones() as u32 as i32; + //~^ ERROR: type ascription cannot be followed by a method call +} + +pub fn multiline_error() { + let _ = 0 + as i32 + .count_ones(); + //~^^^ ERROR: cast cannot be followed by a method call +} + +// this tests that the precedence for `!x as Y.Z` is still what we expect +pub fn precedence() { + let x: i32 = &vec![1, 2, 3] as &Vec[0]; + //~^ ERROR: cast cannot be followed by indexing +} + +pub fn method_calls() { + 0 as i32.max(0); + //~^ ERROR: cast cannot be followed by a method call + 0: i32.max(0); + //~^ ERROR: type ascription cannot be followed by a method call +} + +pub fn complex() { + let _ = format!( + "{} and {}", + if true { 33 } else { 44 } as i32.max(0), + //~^ ERROR: cast cannot be followed by a method call + if true { 33 } else { 44 }: i32.max(0) + //~^ ERROR: type ascription cannot be followed by a method call + ); +} + +pub fn in_condition() { + if 5u64 as i32.max(0) == 0 { + //~^ ERROR: cast cannot be followed by a method call + } + if 5u64: u64.max(0) == 0 { + //~^ ERROR: type ascription cannot be followed by a method call + } +} + +pub fn inside_block() { + let _ = if true { + 5u64 as u32.max(0) == 0 + //~^ ERROR: cast cannot be followed by a method call + } else { false }; + let _ = if true { + 5u64: u64.max(0) == 0 + //~^ ERROR: type ascription cannot be followed by a method call + } else { false }; +} + +static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); +//~^ ERROR: cast cannot be followed by indexing + +static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); +//~^ ERROR: type ascription cannot be followed by indexing + + +pub fn cast_then_try() -> Result { + Err(0u64) as Result?; + //~^ ERROR: cast cannot be followed by `?` + Err(0u64): Result?; + //~^ ERROR: type ascription cannot be followed by `?` + Ok(1) +} + + +pub fn cast_then_call() { + type F = fn(u8); + // type ascription won't actually do [unique drop fn type] -> fn(u8) casts. + let drop_ptr = drop as fn(u8); + drop as F(); + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] + drop_ptr: F(); + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] +} + +pub fn cast_to_fn_should_work() { + let drop_ptr = drop as fn(u8); + drop as fn(u8); + drop_ptr: fn(u8); +} + +pub fn parens_after_cast_error() { + let drop_ptr = drop as fn(u8); + drop as fn(u8)(0); + //~^ ERROR: cast cannot be followed by a function call + drop_ptr: fn(u8)(0); + //~^ ERROR: type ascription cannot be followed by a function call +} + +pub async fn cast_then_await() { + Box::pin(noop()) as Pin>>.await; + //~^ ERROR: cast cannot be followed by `.await` + + Box::pin(noop()): Pin>.await; + //~^ ERROR: type ascription cannot be followed by `.await` +} + +pub async fn noop() {} + +#[derive(Default)] +pub struct Foo { + pub bar: u32, +} + +pub fn struct_field() { + Foo::default() as Foo.bar; + //~^ ERROR: cannot be followed by a field access + Foo::default(): Foo.bar; + //~^ ERROR: type ascription cannot be followed by a field access +} diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr new file mode 100644 index 000000000..0c328bde2 --- /dev/null +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr @@ -0,0 +1,472 @@ +error: cast cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:10:5 + | +LL | vec![1, 2, 3] as Vec[0]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (vec![1, 2, 3] as Vec)[0]; + | + + + +error: type ascription cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:12:5 + | +LL | vec![1, 2, 3]: Vec[0]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (vec![1, 2, 3]: Vec)[0]; + | + + +help: alternatively, remove the type ascription + | +LL - vec![1, 2, 3]: Vec[0]; +LL + vec![1, 2, 3][0]; + | + +error: cast cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:17:5 + | +LL | (&[0]) as &[i32][0]; + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | ((&[0]) as &[i32])[0]; + | + + + +error: type ascription cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:19:5 + | +LL | (&[0i32]): &[i32; 1][0]; + | ^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | ((&[0i32]): &[i32; 1])[0]; + | + + +help: alternatively, remove the type ascription + | +LL - (&[0i32]): &[i32; 1][0]; +LL + (&[0i32])[0]; + | + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:39:13 + | +LL | let _ = 0i32: i32: i32.count_ones(); + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32).count_ones(); + | + + +help: alternatively, remove the type ascription + | +LL - let _ = 0i32: i32: i32.count_ones(); +LL + let _ = 0i32: i32.count_ones(); + | + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:41:13 + | +LL | let _ = 0 as i32: i32.count_ones(); + | ^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32: i32).count_ones(); + | + + +help: alternatively, remove the type ascription + | +LL - let _ = 0 as i32: i32.count_ones(); +LL + let _ = 0 as i32.count_ones(); + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:43:13 + | +LL | let _ = 0i32: i32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32 as i32).count_ones(); + | + + + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:45:13 + | +LL | let _ = 0 as i32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32 as i32).count_ones(); + | + + + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:47:13 + | +LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32 as u32 as i32).count_ones(); + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:49:13 + | +LL | let _ = 0i32: i32.count_ones(): u32; + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32).count_ones(): u32; + | + + +help: alternatively, remove the type ascription + | +LL - let _ = 0i32: i32.count_ones(): u32; +LL + let _ = 0i32.count_ones(): u32; + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:51:13 + | +LL | let _ = 0 as i32.count_ones(): u32; + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32).count_ones(): u32; + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:53:13 + | +LL | let _ = 0i32: i32.count_ones() as u32; + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32).count_ones() as u32; + | + + +help: alternatively, remove the type ascription + | +LL - let _ = 0i32: i32.count_ones() as u32; +LL + let _ = 0i32.count_ones() as u32; + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:55:13 + | +LL | let _ = 0 as i32.count_ones() as u32; + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32).count_ones() as u32; + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:57:13 + | +LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32).count_ones() as u32 as i32; + | + + +help: alternatively, remove the type ascription + | +LL - let _ = 0i32: i32: i32.count_ones() as u32 as i32; +LL + let _ = 0i32: i32.count_ones() as u32 as i32; + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:62:13 + | +LL | let _ = 0 + | _____________^ +LL | | as i32 + | |______________^ + | +help: try surrounding the expression in parentheses + | +LL ~ let _ = (0 +LL ~ as i32) + | + +error: cast cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:70:18 + | +LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let x: i32 = (&vec![1, 2, 3] as &Vec)[0]; + | + + + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:75:5 + | +LL | 0 as i32.max(0); + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0 as i32).max(0); + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:77:5 + | +LL | 0: i32.max(0); + | ^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0: i32).max(0); + | + + +help: alternatively, remove the type ascription + | +LL - 0: i32.max(0); +LL + 0.max(0); + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:92:8 + | +LL | if 5u64 as i32.max(0) == 0 { + | ^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | if (5u64 as i32).max(0) == 0 { + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:95:8 + | +LL | if 5u64: u64.max(0) == 0 { + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | if (5u64: u64).max(0) == 0 { + | + + +help: alternatively, remove the type ascription + | +LL - if 5u64: u64.max(0) == 0 { +LL + if 5u64.max(0) == 0 { + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:102:9 + | +LL | 5u64 as u32.max(0) == 0 + | ^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (5u64 as u32).max(0) == 0 + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:106:9 + | +LL | 5u64: u64.max(0) == 0 + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (5u64: u64).max(0) == 0 + | + + +help: alternatively, remove the type ascription + | +LL - 5u64: u64.max(0) == 0 +LL + 5u64.max(0) == 0 + | + +error: cast cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:111:24 + | +LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); + | ^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); + | + + + +error: type ascription cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:114:25 + | +LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]); + | + + +help: alternatively, remove the type ascription + | +LL - static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); +LL + static bar2: &[i32] = &(&[1i32,2,3][0..1]); + | + +error: cast cannot be followed by `?` + --> $DIR/issue-35813-postfix-after-cast.rs:119:5 + | +LL | Err(0u64) as Result?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Err(0u64) as Result)?; + | + + + +error: type ascription cannot be followed by `?` + --> $DIR/issue-35813-postfix-after-cast.rs:121:5 + | +LL | Err(0u64): Result?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Err(0u64): Result)?; + | + + +help: alternatively, remove the type ascription + | +LL - Err(0u64): Result?; +LL + Err(0u64)?; + | + +error: cast cannot be followed by a function call + --> $DIR/issue-35813-postfix-after-cast.rs:145:5 + | +LL | drop as fn(u8)(0); + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (drop as fn(u8))(0); + | + + + +error: type ascription cannot be followed by a function call + --> $DIR/issue-35813-postfix-after-cast.rs:147:5 + | +LL | drop_ptr: fn(u8)(0); + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (drop_ptr: fn(u8))(0); + | + + +help: alternatively, remove the type ascription + | +LL - drop_ptr: fn(u8)(0); +LL + drop_ptr(0); + | + +error: cast cannot be followed by `.await` + --> $DIR/issue-35813-postfix-after-cast.rs:152:5 + | +LL | Box::pin(noop()) as Pin>>.await; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Box::pin(noop()) as Pin>>).await; + | + + + +error: type ascription cannot be followed by `.await` + --> $DIR/issue-35813-postfix-after-cast.rs:155:5 + | +LL | Box::pin(noop()): Pin>.await; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Box::pin(noop()): Pin>).await; + | + + +help: alternatively, remove the type ascription + | +LL - Box::pin(noop()): Pin>.await; +LL + Box::pin(noop()).await; + | + +error: cast cannot be followed by a field access + --> $DIR/issue-35813-postfix-after-cast.rs:167:5 + | +LL | Foo::default() as Foo.bar; + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Foo::default() as Foo).bar; + | + + + +error: type ascription cannot be followed by a field access + --> $DIR/issue-35813-postfix-after-cast.rs:169:5 + | +LL | Foo::default(): Foo.bar; + | ^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Foo::default(): Foo).bar; + | + + +help: alternatively, remove the type ascription + | +LL - Foo::default(): Foo.bar; +LL + Foo::default().bar; + | + +error: cast cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:84:9 + | +LL | if true { 33 } else { 44 } as i32.max(0), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (if true { 33 } else { 44 } as i32).max(0), + | + + + +error: type ascription cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:86:9 + | +LL | if true { 33 } else { 44 }: i32.max(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (if true { 33 } else { 44 }: i32).max(0) + | + + +help: alternatively, remove the type ascription + | +LL - if true { 33 } else { 44 }: i32.max(0) +LL + if true { 33 } else { 44 }.max(0) + | + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-35813-postfix-after-cast.rs:131:13 + | +LL | drop as F(); + | ^^^ only `Fn` traits may use parentheses + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-35813-postfix-after-cast.rs:133:15 + | +LL | drop_ptr: F(); + | ^^^ only `Fn` traits may use parentheses + +error: aborting due to 36 previous errors + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/parser/issues/issue-41155.rs b/tests/ui/parser/issues/issue-41155.rs new file mode 100644 index 000000000..5a7488e6f --- /dev/null +++ b/tests/ui/parser/issues/issue-41155.rs @@ -0,0 +1,7 @@ +struct S; + +impl S { + pub //~ ERROR visibility `pub` is not followed by an item +} //~ ERROR non-item in item list + +fn main() {} diff --git a/tests/ui/parser/issues/issue-41155.stderr b/tests/ui/parser/issues/issue-41155.stderr new file mode 100644 index 000000000..8491afae2 --- /dev/null +++ b/tests/ui/parser/issues/issue-41155.stderr @@ -0,0 +1,22 @@ +error: visibility `pub` is not followed by an item + --> $DIR/issue-41155.rs:4:5 + | +LL | pub + | ^^^ the visibility + | + = help: you likely meant to define an item, e.g., `pub fn foo() {}` + +error: non-item in item list + --> $DIR/issue-41155.rs:5:1 + | +LL | impl S { + | - item list starts here +LL | pub +LL | } + | ^ + | | + | non-item starts here + | item list ends here + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-43196.rs b/tests/ui/parser/issues/issue-43196.rs new file mode 100644 index 000000000..0eefa01ce --- /dev/null +++ b/tests/ui/parser/issues/issue-43196.rs @@ -0,0 +1,6 @@ +fn main() { + | +} +//~^ ERROR expected `|`, found `}` +| +//~^ ERROR expected item, found `|` diff --git a/tests/ui/parser/issues/issue-43196.stderr b/tests/ui/parser/issues/issue-43196.stderr new file mode 100644 index 000000000..4f7ed5cc6 --- /dev/null +++ b/tests/ui/parser/issues/issue-43196.stderr @@ -0,0 +1,16 @@ +error: expected `|`, found `}` + --> $DIR/issue-43196.rs:3:1 + | +LL | | + | - expected `|` +LL | } + | ^ unexpected token + +error: expected item, found `|` + --> $DIR/issue-43196.rs:5:1 + | +LL | | + | ^ expected item + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-43692.rs b/tests/ui/parser/issues/issue-43692.rs new file mode 100644 index 000000000..baf8bafb8 --- /dev/null +++ b/tests/ui/parser/issues/issue-43692.rs @@ -0,0 +1,3 @@ +fn main() { + '\u{_10FFFF}'; //~ ERROR invalid start of unicode escape +} diff --git a/tests/ui/parser/issues/issue-43692.stderr b/tests/ui/parser/issues/issue-43692.stderr new file mode 100644 index 000000000..baf998035 --- /dev/null +++ b/tests/ui/parser/issues/issue-43692.stderr @@ -0,0 +1,8 @@ +error: invalid start of unicode escape: `_` + --> $DIR/issue-43692.rs:2:9 + | +LL | '\u{_10FFFF}'; + | ^ invalid start of unicode escape + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-44021.rs b/tests/ui/parser/issues/issue-44021.rs new file mode 100644 index 000000000..0b9558cc9 --- /dev/null +++ b/tests/ui/parser/issues/issue-44021.rs @@ -0,0 +1,6 @@ +struct MyStruct; +impl MyStruct { + fn f() {|x, y} //~ ERROR expected one of `:`, `@`, or `|`, found `}` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-44021.stderr b/tests/ui/parser/issues/issue-44021.stderr new file mode 100644 index 000000000..b888cd989 --- /dev/null +++ b/tests/ui/parser/issues/issue-44021.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `@`, or `|`, found `}` + --> $DIR/issue-44021.rs:3:18 + | +LL | fn f() {|x, y} + | ^ expected one of `:`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-44406.rs b/tests/ui/parser/issues/issue-44406.rs new file mode 100644 index 000000000..a5b7e83a0 --- /dev/null +++ b/tests/ui/parser/issues/issue-44406.rs @@ -0,0 +1,10 @@ +macro_rules! foo { + ($rest: tt) => { + bar(baz: $rest) //~ ERROR invalid `struct` delimiters or `fn` call arguments + } +} + +fn main() { + foo!(true); + //~^ ERROR expected identifier, found keyword +} diff --git a/tests/ui/parser/issues/issue-44406.stderr b/tests/ui/parser/issues/issue-44406.stderr new file mode 100644 index 000000000..1f0c1ea4c --- /dev/null +++ b/tests/ui/parser/issues/issue-44406.stderr @@ -0,0 +1,33 @@ +error: expected identifier, found keyword `true` + --> $DIR/issue-44406.rs:8:10 + | +LL | foo!(true); + | ^^^^ expected identifier, found keyword + | +help: escape `true` to use it as an identifier + | +LL | foo!(r#true); + | ++ + +error: invalid `struct` delimiters or `fn` call arguments + --> $DIR/issue-44406.rs:3:9 + | +LL | bar(baz: $rest) + | ^^^^^^^^^^^^^^^ +... +LL | foo!(true); + | ---------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if `bar` is a struct, use braces as delimiters + | +LL | bar { } + | ~ +help: if `bar` is a function, use the arguments directly + | +LL - bar(baz: $rest) +LL + bar(: $rest) + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-45296.rs b/tests/ui/parser/issues/issue-45296.rs new file mode 100644 index 000000000..d3a97e89f --- /dev/null +++ b/tests/ui/parser/issues/issue-45296.rs @@ -0,0 +1,6 @@ +fn main() { + let unused = (); + + #![allow(unused_variables)] //~ ERROR not permitted in this context + fn foo() {} +} diff --git a/tests/ui/parser/issues/issue-45296.stderr b/tests/ui/parser/issues/issue-45296.stderr new file mode 100644 index 000000000..081a72054 --- /dev/null +++ b/tests/ui/parser/issues/issue-45296.stderr @@ -0,0 +1,17 @@ +error: an inner attribute is not permitted in this context + --> $DIR/issue-45296.rs:4:5 + | +LL | #![allow(unused_variables)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() {} + | ----------- the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the function, change the attribute from inner to outer style + | +LL - #![allow(unused_variables)] +LL + #[allow(unused_variables)] + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-46186.fixed b/tests/ui/parser/issues/issue-46186.fixed new file mode 100644 index 000000000..2cb5a4996 --- /dev/null +++ b/tests/ui/parser/issues/issue-46186.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub struct Struct { + pub a: usize, +} +//~^ ERROR expected item, found `;` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-46186.rs b/tests/ui/parser/issues/issue-46186.rs new file mode 100644 index 000000000..84cad38c5 --- /dev/null +++ b/tests/ui/parser/issues/issue-46186.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub struct Struct { + pub a: usize, +}; +//~^ ERROR expected item, found `;` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-46186.stderr b/tests/ui/parser/issues/issue-46186.stderr new file mode 100644 index 000000000..0766c8a33 --- /dev/null +++ b/tests/ui/parser/issues/issue-46186.stderr @@ -0,0 +1,10 @@ +error: expected item, found `;` + --> $DIR/issue-46186.rs:5:2 + | +LL | }; + | ^ help: remove this semicolon + | + = help: braced struct declarations are not followed by a semicolon + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs new file mode 100644 index 000000000..48a679b2d --- /dev/null +++ b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs @@ -0,0 +1,44 @@ +fn main() {} + +macro_rules! expand_to_enum { + () => { + enum BadE {} + //~^ ERROR enum is not supported in `trait`s or `impl`s + //~| ERROR enum is not supported in `trait`s or `impl`s + //~| ERROR enum is not supported in `extern` blocks + }; +} + +macro_rules! mac_impl { + ($($i:item)*) => { + struct S; + impl S { $($i)* } + } +} + +mac_impl! { + struct BadS; //~ ERROR struct is not supported in `trait`s or `impl`s + expand_to_enum!(); +} + +macro_rules! mac_trait { + ($($i:item)*) => { + trait T { $($i)* } + } +} + +mac_trait! { + struct BadS; //~ ERROR struct is not supported in `trait`s or `impl`s + expand_to_enum!(); +} + +macro_rules! mac_extern { + ($($i:item)*) => { + extern "C" { $($i)* } + } +} + +mac_extern! { + struct BadS; //~ ERROR struct is not supported in `extern` blocks + expand_to_enum!(); +} diff --git a/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr new file mode 100644 index 000000000..fdef8ff6d --- /dev/null +++ b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr @@ -0,0 +1,62 @@ +error: struct is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:20:5 + | +LL | struct BadS; + | ^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: enum is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 + | +LL | enum BadE {} + | ^^^^^^^^^ +... +LL | expand_to_enum!(); + | ----------------- in this macro invocation + | + = help: consider moving the enum out to a nearby module scope + = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:31:5 + | +LL | struct BadS; + | ^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: enum is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 + | +LL | enum BadE {} + | ^^^^^^^^^ +... +LL | expand_to_enum!(); + | ----------------- in this macro invocation + | + = help: consider moving the enum out to a nearby module scope + = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct is not supported in `extern` blocks + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:42:5 + | +LL | struct BadS; + | ^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: enum is not supported in `extern` blocks + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 + | +LL | enum BadE {} + | ^^^^^^^^^ +... +LL | expand_to_enum!(); + | ----------------- in this macro invocation + | + = help: consider moving the enum out to a nearby module scope + = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs new file mode 100644 index 000000000..8592f8a72 --- /dev/null +++ b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs @@ -0,0 +1,34 @@ +// check-pass + +fn main() {} + +macro_rules! mac_impl { + ($i:item) => { + struct S; + impl S { $i } + } +} + +mac_impl! { + fn foo() {} +} + +macro_rules! mac_trait { + ($i:item) => { + trait T { $i } + } +} + +mac_trait! { + fn foo() {} +} + +macro_rules! mac_extern { + ($i:item) => { + extern "C" { $i } + } +} + +mac_extern! { + fn foo(); +} diff --git a/tests/ui/parser/issues/issue-48508-aux.rs b/tests/ui/parser/issues/issue-48508-aux.rs new file mode 100644 index 000000000..ebdc70a04 --- /dev/null +++ b/tests/ui/parser/issues/issue-48508-aux.rs @@ -0,0 +1,7 @@ +// run-pass +// ignore-test Not a test. Used by issue-48508.rs + +pub fn other() -> f64 { + let µ = 1.0; + µ +} diff --git a/tests/ui/parser/issues/issue-48508.rs b/tests/ui/parser/issues/issue-48508.rs new file mode 100644 index 000000000..37d04c5d6 --- /dev/null +++ b/tests/ui/parser/issues/issue-48508.rs @@ -0,0 +1,20 @@ +// run-pass +// Regression test for issue #48508: +// +// Confusion between global and local file offsets caused incorrect handling of multibyte character +// spans when compiling multiple files. One visible effect was an ICE generating debug information +// when a multibyte character is at the end of a scope. The problematic code is actually in +// issue-48508-aux.rs + +// compile-flags:-g +// ignore-pretty issue #37195 +// ignore-asmjs wasm2js does not support source maps yet + +#![allow(uncommon_codepoints)] + +#[path = "issue-48508-aux.rs"] +mod other_file; + +fn main() { + other_file::other(); +} diff --git a/tests/ui/parser/issues/issue-48636.fixed b/tests/ui/parser/issues/issue-48636.fixed new file mode 100644 index 000000000..87c19a32d --- /dev/null +++ b/tests/ui/parser/issues/issue-48636.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +#![allow(dead_code)] + +struct S { + x: u8, + /// The ID of the parent core + y: u8, +} +//~^^^ ERROR found a documentation comment that doesn't document anything + +fn main() {} diff --git a/tests/ui/parser/issues/issue-48636.rs b/tests/ui/parser/issues/issue-48636.rs new file mode 100644 index 000000000..8610dc2f7 --- /dev/null +++ b/tests/ui/parser/issues/issue-48636.rs @@ -0,0 +1,12 @@ +// run-rustfix + +#![allow(dead_code)] + +struct S { + x: u8 + /// The ID of the parent core + y: u8, +} +//~^^^ ERROR found a documentation comment that doesn't document anything + +fn main() {} diff --git a/tests/ui/parser/issues/issue-48636.stderr b/tests/ui/parser/issues/issue-48636.stderr new file mode 100644 index 000000000..6177870d1 --- /dev/null +++ b/tests/ui/parser/issues/issue-48636.stderr @@ -0,0 +1,15 @@ +error[E0585]: found a documentation comment that doesn't document anything + --> $DIR/issue-48636.rs:7:5 + | +LL | struct S { + | - while parsing this struct +LL | x: u8 + | - help: missing comma here: `,` +LL | /// The ID of the parent core + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: doc comments must come before what they document, if a comment was intended use `//` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0585`. diff --git a/tests/ui/parser/issues/issue-49040.rs b/tests/ui/parser/issues/issue-49040.rs new file mode 100644 index 000000000..b7a541dd6 --- /dev/null +++ b/tests/ui/parser/issues/issue-49040.rs @@ -0,0 +1,3 @@ +#![allow(unused_variables)]; //~ ERROR expected item, found `;` +//~^ ERROR `main` function +fn foo() {} diff --git a/tests/ui/parser/issues/issue-49040.stderr b/tests/ui/parser/issues/issue-49040.stderr new file mode 100644 index 000000000..8af7838c7 --- /dev/null +++ b/tests/ui/parser/issues/issue-49040.stderr @@ -0,0 +1,15 @@ +error: expected item, found `;` + --> $DIR/issue-49040.rs:1:28 + | +LL | #![allow(unused_variables)]; + | ^ help: remove this semicolon + +error[E0601]: `main` function not found in crate `issue_49040` + --> $DIR/issue-49040.rs:1:29 + | +LL | #![allow(unused_variables)]; + | ^ consider adding a `main` function to `$DIR/issue-49040.rs` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/parser/issues/issue-51602.rs b/tests/ui/parser/issues/issue-51602.rs new file mode 100644 index 000000000..0e96ca914 --- /dev/null +++ b/tests/ui/parser/issues/issue-51602.rs @@ -0,0 +1,6 @@ +fn main(){ + if i in 1..10 { +//~^ ERROR expected `{`, found keyword `in` + break; + } +} diff --git a/tests/ui/parser/issues/issue-51602.stderr b/tests/ui/parser/issues/issue-51602.stderr new file mode 100644 index 000000000..4a5653fdb --- /dev/null +++ b/tests/ui/parser/issues/issue-51602.stderr @@ -0,0 +1,14 @@ +error: expected `{`, found keyword `in` + --> $DIR/issue-51602.rs:2:10 + | +LL | if i in 1..10 { + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-51602.rs:2:8 + | +LL | if i in 1..10 { + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-52496.rs b/tests/ui/parser/issues/issue-52496.rs new file mode 100644 index 000000000..05461f8b8 --- /dev/null +++ b/tests/ui/parser/issues/issue-52496.rs @@ -0,0 +1,12 @@ +struct Foo { bar: f64, baz: i64, bat: i64 } + +fn main() { + let _ = Foo { bar: .5, baz: 42 }; + //~^ ERROR float literals must have an integer part + //~| ERROR missing field `bat` in initializer of `Foo` + let bar = 1.5f32; + let _ = Foo { bar.into(), bat: -1, . }; + //~^ ERROR expected one of + //~| ERROR missing fields `bar` and `baz` in initializer of `Foo` + //~| ERROR expected identifier, found `.` +} diff --git a/tests/ui/parser/issues/issue-52496.stderr b/tests/ui/parser/issues/issue-52496.stderr new file mode 100644 index 000000000..77335c64c --- /dev/null +++ b/tests/ui/parser/issues/issue-52496.stderr @@ -0,0 +1,38 @@ +error: float literals must have an integer part + --> $DIR/issue-52496.rs:4:24 + | +LL | let _ = Foo { bar: .5, baz: 42 }; + | ^^ help: must have an integer part: `0.5` + +error: expected one of `,`, `:`, or `}`, found `.` + --> $DIR/issue-52496.rs:8:22 + | +LL | let _ = Foo { bar.into(), bat: -1, . }; + | --- - ^ expected one of `,`, `:`, or `}` + | | | + | | help: try naming a field: `bar:` + | while parsing this struct + +error: expected identifier, found `.` + --> $DIR/issue-52496.rs:8:40 + | +LL | let _ = Foo { bar.into(), bat: -1, . }; + | --- ^ expected identifier + | | + | while parsing this struct + +error[E0063]: missing field `bat` in initializer of `Foo` + --> $DIR/issue-52496.rs:4:13 + | +LL | let _ = Foo { bar: .5, baz: 42 }; + | ^^^ missing `bat` + +error[E0063]: missing fields `bar` and `baz` in initializer of `Foo` + --> $DIR/issue-52496.rs:8:13 + | +LL | let _ = Foo { bar.into(), bat: -1, . }; + | ^^^ missing `bar` and `baz` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/issues/issue-54521-1.rs b/tests/ui/parser/issues/issue-54521-1.rs new file mode 100644 index 000000000..8a682ef0a --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-1.rs @@ -0,0 +1,16 @@ +// check-pass + +// This test checks that the `remove extra angle brackets` error doesn't happen for some +// potential edge-cases.. + +struct X { + len: u32, +} + +fn main() { + let x = X { len: 3 }; + + let _ = x.len > (3); + + let _ = x.len >> (3); +} diff --git a/tests/ui/parser/issues/issue-54521-2.fixed b/tests/ui/parser/issues/issue-54521-2.fixed new file mode 100644 index 000000000..a91c4fe43 --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-2.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +// This test checks that the following error is emitted and the suggestion works: +// +// ``` +// let _ = Vec::>>::new(); +// ^^ help: remove extra angle brackets +// ``` + +fn main() { + let _ = Vec::::new(); + //~^ ERROR unmatched angle bracket + + let _ = Vec::::new(); + //~^ ERROR unmatched angle bracket + + let _ = Vec::::new(); + //~^ ERROR unmatched angle bracket + + let _ = Vec::::new(); + //~^ ERROR unmatched angle bracket +} diff --git a/tests/ui/parser/issues/issue-54521-2.rs b/tests/ui/parser/issues/issue-54521-2.rs new file mode 100644 index 000000000..3639aac87 --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-2.rs @@ -0,0 +1,22 @@ +// run-rustfix + +// This test checks that the following error is emitted and the suggestion works: +// +// ``` +// let _ = Vec::>>::new(); +// ^^ help: remove extra angle brackets +// ``` + +fn main() { + let _ = Vec::>>>>::new(); + //~^ ERROR unmatched angle bracket + + let _ = Vec::>>>::new(); + //~^ ERROR unmatched angle bracket + + let _ = Vec::>>::new(); + //~^ ERROR unmatched angle bracket + + let _ = Vec::>::new(); + //~^ ERROR unmatched angle bracket +} diff --git a/tests/ui/parser/issues/issue-54521-2.stderr b/tests/ui/parser/issues/issue-54521-2.stderr new file mode 100644 index 000000000..9556b83b7 --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-2.stderr @@ -0,0 +1,26 @@ +error: unmatched angle brackets + --> $DIR/issue-54521-2.rs:11:25 + | +LL | let _ = Vec::>>>>::new(); + | ^^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-54521-2.rs:14:25 + | +LL | let _ = Vec::>>>::new(); + | ^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-54521-2.rs:17:25 + | +LL | let _ = Vec::>>::new(); + | ^^ help: remove extra angle brackets + +error: unmatched angle bracket + --> $DIR/issue-54521-2.rs:20:25 + | +LL | let _ = Vec::>::new(); + | ^ help: remove extra angle bracket + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issues/issue-54521-3.fixed b/tests/ui/parser/issues/issue-54521-3.fixed new file mode 100644 index 000000000..84ab6866c --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-3.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +// This test checks that the following error is emitted and the suggestion works: +// +// ``` +// let _ = vec![1, 2, 3].into_iter().collect::>>>(); +// ^^ help: remove extra angle brackets +// ``` + +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket +} diff --git a/tests/ui/parser/issues/issue-54521-3.rs b/tests/ui/parser/issues/issue-54521-3.rs new file mode 100644 index 000000000..f1d685041 --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-3.rs @@ -0,0 +1,22 @@ +// run-rustfix + +// This test checks that the following error is emitted and the suggestion works: +// +// ``` +// let _ = vec![1, 2, 3].into_iter().collect::>>>(); +// ^^ help: remove extra angle brackets +// ``` + +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::>>>>>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>>>>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>>>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>>(); + //~^ ERROR unmatched angle bracket +} diff --git a/tests/ui/parser/issues/issue-54521-3.stderr b/tests/ui/parser/issues/issue-54521-3.stderr new file mode 100644 index 000000000..0f23dd621 --- /dev/null +++ b/tests/ui/parser/issues/issue-54521-3.stderr @@ -0,0 +1,26 @@ +error: unmatched angle brackets + --> $DIR/issue-54521-3.rs:11:60 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>>>>>(); + | ^^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-54521-3.rs:14:60 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>>>>(); + | ^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-54521-3.rs:17:60 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>>>(); + | ^^ help: remove extra angle brackets + +error: unmatched angle bracket + --> $DIR/issue-54521-3.rs:20:60 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>>(); + | ^ help: remove extra angle bracket + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issues/issue-5544-a.rs b/tests/ui/parser/issues/issue-5544-a.rs new file mode 100644 index 000000000..3c239c73b --- /dev/null +++ b/tests/ui/parser/issues/issue-5544-a.rs @@ -0,0 +1,4 @@ +fn main() { + let __isize = 340282366920938463463374607431768211456; // 2^128 + //~^ ERROR integer literal is too large +} diff --git a/tests/ui/parser/issues/issue-5544-a.stderr b/tests/ui/parser/issues/issue-5544-a.stderr new file mode 100644 index 000000000..6e68c7585 --- /dev/null +++ b/tests/ui/parser/issues/issue-5544-a.stderr @@ -0,0 +1,10 @@ +error: integer literal is too large + --> $DIR/issue-5544-a.rs:2:19 + | +LL | let __isize = 340282366920938463463374607431768211456; // 2^128 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-5544-b.rs b/tests/ui/parser/issues/issue-5544-b.rs new file mode 100644 index 000000000..93f2ff271 --- /dev/null +++ b/tests/ui/parser/issues/issue-5544-b.rs @@ -0,0 +1,4 @@ +fn main() { + let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff; + //~^ ERROR integer literal is too large +} diff --git a/tests/ui/parser/issues/issue-5544-b.stderr b/tests/ui/parser/issues/issue-5544-b.stderr new file mode 100644 index 000000000..5d0e76d5d --- /dev/null +++ b/tests/ui/parser/issues/issue-5544-b.stderr @@ -0,0 +1,10 @@ +error: integer literal is too large + --> $DIR/issue-5544-b.rs:2:19 + | +LL | let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-56031.rs b/tests/ui/parser/issues/issue-56031.rs new file mode 100644 index 000000000..b68f56814 --- /dev/null +++ b/tests/ui/parser/issues/issue-56031.rs @@ -0,0 +1,6 @@ +struct T; + +impl for T {} +//~^ ERROR missing trait in a trait impl + +fn main() {} diff --git a/tests/ui/parser/issues/issue-56031.stderr b/tests/ui/parser/issues/issue-56031.stderr new file mode 100644 index 000000000..2fa05dd2d --- /dev/null +++ b/tests/ui/parser/issues/issue-56031.stderr @@ -0,0 +1,18 @@ +error: missing trait in a trait impl + --> $DIR/issue-56031.rs:3:5 + | +LL | impl for T {} + | ^ + | +help: add a trait here + | +LL | impl Trait for T {} + | +++++ +help: for an inherent impl, drop this `for` + | +LL - impl for T {} +LL + impl T {} + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-57198.rs b/tests/ui/parser/issues/issue-57198.rs new file mode 100644 index 000000000..714a46cbc --- /dev/null +++ b/tests/ui/parser/issues/issue-57198.rs @@ -0,0 +1,8 @@ +mod m { + pub fn r#for() {} +} + +fn main() { + m::for(); + //~^ ERROR expected identifier, found keyword `for` +} diff --git a/tests/ui/parser/issues/issue-57198.stderr b/tests/ui/parser/issues/issue-57198.stderr new file mode 100644 index 000000000..dd70b4022 --- /dev/null +++ b/tests/ui/parser/issues/issue-57198.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `for` + --> $DIR/issue-57198.rs:6:8 + | +LL | m::for(); + | ^^^ expected identifier, found keyword + | +help: escape `for` to use it as an identifier + | +LL | m::r#for(); + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-57684.fixed b/tests/ui/parser/issues/issue-57684.fixed new file mode 100644 index 000000000..4a432206d --- /dev/null +++ b/tests/ui/parser/issues/issue-57684.fixed @@ -0,0 +1,37 @@ +// run-rustfix + +#![allow(warnings)] + +// This test checks that the following error is emitted when a `=` character is used to initialize +// a struct field when a `:` is expected. +// +// ``` +// error: struct fields are initialized with a colon +// --> $DIR/issue-57684.rs:12:20 +// | +// LL | let _ = X { f1 = 5 }; +// | ^ help: replace equals symbol with a colon: `:` +// ``` + +struct X { + f1: i32, +} + +struct Y { + f1: i32, + f2: i32, + f3: i32, +} + +fn main() { + let _ = X { f1: 5 }; + //~^ ERROR expected `:`, found `=` + + let f3 = 3; + let _ = Y { + f1: 5, + //~^ ERROR expected `:`, found `=` + f2: 4, + f3, + }; +} diff --git a/tests/ui/parser/issues/issue-57684.rs b/tests/ui/parser/issues/issue-57684.rs new file mode 100644 index 000000000..7a62785e3 --- /dev/null +++ b/tests/ui/parser/issues/issue-57684.rs @@ -0,0 +1,37 @@ +// run-rustfix + +#![allow(warnings)] + +// This test checks that the following error is emitted when a `=` character is used to initialize +// a struct field when a `:` is expected. +// +// ``` +// error: struct fields are initialized with a colon +// --> $DIR/issue-57684.rs:12:20 +// | +// LL | let _ = X { f1 = 5 }; +// | ^ help: replace equals symbol with a colon: `:` +// ``` + +struct X { + f1: i32, +} + +struct Y { + f1: i32, + f2: i32, + f3: i32, +} + +fn main() { + let _ = X { f1 = 5 }; + //~^ ERROR expected `:`, found `=` + + let f3 = 3; + let _ = Y { + f1 = 5, + //~^ ERROR expected `:`, found `=` + f2: 4, + f3, + }; +} diff --git a/tests/ui/parser/issues/issue-57684.stderr b/tests/ui/parser/issues/issue-57684.stderr new file mode 100644 index 000000000..514bbffde --- /dev/null +++ b/tests/ui/parser/issues/issue-57684.stderr @@ -0,0 +1,18 @@ +error: expected `:`, found `=` + --> $DIR/issue-57684.rs:27:20 + | +LL | let _ = X { f1 = 5 }; + | -^ + | | + | help: replace equals symbol with a colon: `:` + +error: expected `:`, found `=` + --> $DIR/issue-57684.rs:32:12 + | +LL | f1 = 5, + | -^ + | | + | help: replace equals symbol with a colon: `:` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-57819.fixed b/tests/ui/parser/issues/issue-57819.fixed new file mode 100644 index 000000000..3fab21db2 --- /dev/null +++ b/tests/ui/parser/issues/issue-57819.fixed @@ -0,0 +1,47 @@ +// run-rustfix + +#![allow(warnings)] + +// This test checks that the following error is emitted and the suggestion works: +// +// ``` +// let _ = vec![1, 2, 3].into_iter().collect::<<>(); +// ^^ help: remove extra angle brackets +// ``` + +trait Foo { + type Output; +} + +fn foo() { + // More complex cases with more than one correct leading `<` character: + + bar::<::Output>(); + //~^ ERROR unmatched angle bracket + + bar::<::Output>(); + //~^ ERROR unmatched angle bracket + + bar::<::Output>(); + //~^ ERROR unmatched angle bracket + + bar::<::Output>(); +} + +fn bar() {} + +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); +} diff --git a/tests/ui/parser/issues/issue-57819.rs b/tests/ui/parser/issues/issue-57819.rs new file mode 100644 index 000000000..5cafbf439 --- /dev/null +++ b/tests/ui/parser/issues/issue-57819.rs @@ -0,0 +1,47 @@ +// run-rustfix + +#![allow(warnings)] + +// This test checks that the following error is emitted and the suggestion works: +// +// ``` +// let _ = vec![1, 2, 3].into_iter().collect::<<>(); +// ^^ help: remove extra angle brackets +// ``` + +trait Foo { + type Output; +} + +fn foo() { + // More complex cases with more than one correct leading `<` character: + + bar::<<<<::Output>(); + //~^ ERROR unmatched angle bracket + + bar::<<<::Output>(); + //~^ ERROR unmatched angle bracket + + bar::<<::Output>(); + //~^ ERROR unmatched angle bracket + + bar::<::Output>(); +} + +fn bar() {} + +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::<<<<>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::<<<>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::<<>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::<>(); + //~^ ERROR unmatched angle bracket + + let _ = vec![1, 2, 3].into_iter().collect::>(); +} diff --git a/tests/ui/parser/issues/issue-57819.stderr b/tests/ui/parser/issues/issue-57819.stderr new file mode 100644 index 000000000..493e9835b --- /dev/null +++ b/tests/ui/parser/issues/issue-57819.stderr @@ -0,0 +1,44 @@ +error: unmatched angle brackets + --> $DIR/issue-57819.rs:19:10 + | +LL | bar::<<<<::Output>(); + | ^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-57819.rs:22:10 + | +LL | bar::<<<::Output>(); + | ^^ help: remove extra angle brackets + +error: unmatched angle bracket + --> $DIR/issue-57819.rs:25:10 + | +LL | bar::<<::Output>(); + | ^ help: remove extra angle bracket + +error: unmatched angle brackets + --> $DIR/issue-57819.rs:34:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<<<<>(); + | ^^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-57819.rs:37:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<<<>(); + | ^^^ help: remove extra angle brackets + +error: unmatched angle brackets + --> $DIR/issue-57819.rs:40:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<<>(); + | ^^ help: remove extra angle brackets + +error: unmatched angle bracket + --> $DIR/issue-57819.rs:43:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::<>(); + | ^ help: remove extra angle bracket + +error: aborting due to 7 previous errors + diff --git a/tests/ui/parser/issues/issue-5806.rs b/tests/ui/parser/issues/issue-5806.rs new file mode 100644 index 000000000..b694642a9 --- /dev/null +++ b/tests/ui/parser/issues/issue-5806.rs @@ -0,0 +1,7 @@ +// normalize-stderr-test: "parser:.*\(" -> "parser: $$ACCESS_DENIED_MSG (" +// normalize-stderr-test: "os error \d+" -> "os error $$ACCESS_DENIED_CODE" + +#[path = "../parser"] +mod foo; //~ ERROR couldn't read + +fn main() {} diff --git a/tests/ui/parser/issues/issue-5806.stderr b/tests/ui/parser/issues/issue-5806.stderr new file mode 100644 index 000000000..bdb5c91ff --- /dev/null +++ b/tests/ui/parser/issues/issue-5806.stderr @@ -0,0 +1,8 @@ +error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) + --> $DIR/issue-5806.rs:5:1 + | +LL | mod foo; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs new file mode 100644 index 000000000..25699f9fe --- /dev/null +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs @@ -0,0 +1,4 @@ +// Fixed in #66054. +// ignore-tidy-trailing-newlines +// error-pattern: aborting due to 2 previous errors +#[Ð… \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr new file mode 100644 index 000000000..8a44ee761 --- /dev/null +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr @@ -0,0 +1,16 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 + | +LL | #[Ð… + | - ^ + | | + | unclosed delimiter + +error: expected item after attributes + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:1 + | +LL | #[Ð… + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-58856-1.rs b/tests/ui/parser/issues/issue-58856-1.rs new file mode 100644 index 000000000..ea80eb871 --- /dev/null +++ b/tests/ui/parser/issues/issue-58856-1.rs @@ -0,0 +1,8 @@ +impl A { + //~^ ERROR cannot find type `A` in this scope + fn b(self> + //~^ ERROR expected one of `)`, `,`, or `:`, found `>` + //~| ERROR expected one of `->`, `where`, or `{`, found `>` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-58856-1.stderr b/tests/ui/parser/issues/issue-58856-1.stderr new file mode 100644 index 000000000..96151f3fe --- /dev/null +++ b/tests/ui/parser/issues/issue-58856-1.stderr @@ -0,0 +1,29 @@ +error: expected one of `)`, `,`, or `:`, found `>` + --> $DIR/issue-58856-1.rs:3:9 + | +LL | fn b(self> + | ^ ^ help: `)` may belong here + | | + | unclosed delimiter + +error: expected one of `->`, `where`, or `{`, found `>` + --> $DIR/issue-58856-1.rs:3:14 + | +LL | impl A { + | - while parsing this item list starting here +LL | +LL | fn b(self> + | ^ expected one of `->`, `where`, or `{` +... +LL | } + | - the item list ends here + +error[E0412]: cannot find type `A` in this scope + --> $DIR/issue-58856-1.rs:1:6 + | +LL | impl A { + | ^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/issues/issue-58856-2.rs b/tests/ui/parser/issues/issue-58856-2.rs new file mode 100644 index 000000000..9356d57b0 --- /dev/null +++ b/tests/ui/parser/issues/issue-58856-2.rs @@ -0,0 +1,14 @@ +struct Empty; + +trait Howness {} + +impl Howness for () { + fn how_are_you(&self -> Empty { + //~^ ERROR expected one of `)` or `,`, found `->` + //~| ERROR method `how_are_you` is not a member of trait `Howness` + Empty + } +} +//~^ ERROR non-item in item list + +fn main() {} diff --git a/tests/ui/parser/issues/issue-58856-2.stderr b/tests/ui/parser/issues/issue-58856-2.stderr new file mode 100644 index 000000000..627dd3890 --- /dev/null +++ b/tests/ui/parser/issues/issue-58856-2.stderr @@ -0,0 +1,34 @@ +error: expected one of `)` or `,`, found `->` + --> $DIR/issue-58856-2.rs:6:19 + | +LL | fn how_are_you(&self -> Empty { + | ^ -^^ + | | | + | | help: `)` may belong here + | unclosed delimiter + +error: non-item in item list + --> $DIR/issue-58856-2.rs:11:1 + | +LL | impl Howness for () { + | - item list starts here +... +LL | } + | ^ + | | + | non-item starts here + | item list ends here + +error[E0407]: method `how_are_you` is not a member of trait `Howness` + --> $DIR/issue-58856-2.rs:6:5 + | +LL | / fn how_are_you(&self -> Empty { +LL | | +LL | | +LL | | Empty +LL | | } + | |_____^ not a member of trait `Howness` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0407`. diff --git a/tests/ui/parser/issues/issue-59418.rs b/tests/ui/parser/issues/issue-59418.rs new file mode 100644 index 000000000..0fa191d4a --- /dev/null +++ b/tests/ui/parser/issues/issue-59418.rs @@ -0,0 +1,18 @@ +struct X(i32,i32,i32); + +fn main() { + let a = X(1, 2, 3); + let b = a.1suffix; + //~^ ERROR suffixes on a tuple index are invalid + println!("{}", b); + let c = (1, 2, 3); + let d = c.1suffix; + //~^ ERROR suffixes on a tuple index are invalid + println!("{}", d); + let s = X { 0suffix: 0, 1: 1, 2: 2 }; + //~^ ERROR suffixes on a tuple index are invalid + match s { + X { 0suffix: _, .. } => {} + //~^ ERROR suffixes on a tuple index are invalid + } +} diff --git a/tests/ui/parser/issues/issue-59418.stderr b/tests/ui/parser/issues/issue-59418.stderr new file mode 100644 index 000000000..347051e9f --- /dev/null +++ b/tests/ui/parser/issues/issue-59418.stderr @@ -0,0 +1,26 @@ +error: suffixes on a tuple index are invalid + --> $DIR/issue-59418.rs:5:15 + | +LL | let b = a.1suffix; + | ^^^^^^^ invalid suffix `suffix` + +error: suffixes on a tuple index are invalid + --> $DIR/issue-59418.rs:9:15 + | +LL | let d = c.1suffix; + | ^^^^^^^ invalid suffix `suffix` + +error: suffixes on a tuple index are invalid + --> $DIR/issue-59418.rs:12:17 + | +LL | let s = X { 0suffix: 0, 1: 1, 2: 2 }; + | ^^^^^^^ invalid suffix `suffix` + +error: suffixes on a tuple index are invalid + --> $DIR/issue-59418.rs:15:13 + | +LL | X { 0suffix: _, .. } => {} + | ^^^^^^^ invalid suffix `suffix` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issues/issue-60075.rs b/tests/ui/parser/issues/issue-60075.rs new file mode 100644 index 000000000..e89d78ee8 --- /dev/null +++ b/tests/ui/parser/issues/issue-60075.rs @@ -0,0 +1,11 @@ +fn main() {} + +trait T { + fn qux() -> Option { + let _ = if true { + }); +//~^ ERROR non-item in item list +//~| ERROR mismatched closing delimiter: `)` +//~| ERROR expected one of `.`, `;` + Some(4) + } diff --git a/tests/ui/parser/issues/issue-60075.stderr b/tests/ui/parser/issues/issue-60075.stderr new file mode 100644 index 000000000..210ef700c --- /dev/null +++ b/tests/ui/parser/issues/issue-60075.stderr @@ -0,0 +1,29 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` + --> $DIR/issue-60075.rs:6:10 + | +LL | }); + | ^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: non-item in item list + --> $DIR/issue-60075.rs:6:11 + | +LL | trait T { + | - item list starts here +... +LL | }); + | ^ non-item starts here +... +LL | } + | - item list ends here + +error: mismatched closing delimiter: `)` + --> $DIR/issue-60075.rs:4:31 + | +LL | fn qux() -> Option { + | ^ unclosed delimiter +LL | let _ = if true { +LL | }); + | ^ mismatched closing delimiter + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs new file mode 100644 index 000000000..5259dfe2e --- /dev/null +++ b/tests/ui/parser/issues/issue-62524.rs @@ -0,0 +1,6 @@ +// ignore-tidy-trailing-newlines +// error-pattern: aborting due to 3 previous errors +#![allow(uncommon_codepoints)] + +y![ +Ϥ, \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr new file mode 100644 index 000000000..55eed0402 --- /dev/null +++ b/tests/ui/parser/issues/issue-62524.stderr @@ -0,0 +1,33 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62524.rs:6:3 + | +LL | y![ + | - unclosed delimiter +LL | Ϥ, + | ^ + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-62524.rs:5:3 + | +LL | y![ + | ___^ +LL | | Ϥ, + | |__^ + | +help: change the delimiters to curly braces + | +LL | y! { /* items */ } + | ~~~~~~~~~~~~~~~ +help: add a semicolon + | +LL | Ϥ,; + | + + +error: cannot find macro `y` in this scope + --> $DIR/issue-62524.rs:5:1 + | +LL | y![ + | ^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-62546.rs b/tests/ui/parser/issues/issue-62546.rs new file mode 100644 index 000000000..f06b65058 --- /dev/null +++ b/tests/ui/parser/issues/issue-62546.rs @@ -0,0 +1,3 @@ +pub t(# +//~^ ERROR missing `fn` or `struct` for function or struct definition +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/issues/issue-62546.stderr b/tests/ui/parser/issues/issue-62546.stderr new file mode 100644 index 000000000..32c61391e --- /dev/null +++ b/tests/ui/parser/issues/issue-62546.stderr @@ -0,0 +1,17 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62546.rs:3:52 + | +LL | pub t(# + | - unclosed delimiter +LL | +LL | + | ^ + +error: missing `fn` or `struct` for function or struct definition + --> $DIR/issue-62546.rs:1:4 + | +LL | pub t(# + | ---^- help: if you meant to call a macro, try: `t!` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs new file mode 100644 index 000000000..cfd02183c --- /dev/null +++ b/tests/ui/parser/issues/issue-62554.rs @@ -0,0 +1,6 @@ +// error-pattern:this file contains an unclosed delimiter +// error-pattern:xpected `{`, found `macro_rules` + +fn main() {} + +fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr new file mode 100644 index 000000000..9e62572e3 --- /dev/null +++ b/tests/ui/parser/issues/issue-62554.stderr @@ -0,0 +1,73 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62554.rs:6:89 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | - - - - - ^ + | | | | | | + | | | | | unclosed delimiter + | | | | unclosed delimiter + | | | unclosed delimiter + | unclosed delimiter unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-62554.rs:6:89 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | - - - - - ^ + | | | | | | + | | | | | unclosed delimiter + | | | | unclosed delimiter + | | | unclosed delimiter + | unclosed delimiter unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-62554.rs:6:89 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | - - - - - ^ + | | | | | | + | | | | | unclosed delimiter + | | | | unclosed delimiter + | | | unclosed delimiter + | unclosed delimiter unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-62554.rs:6:89 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | - - - - - ^ + | | | | | | + | | | | | unclosed delimiter + | | | | unclosed delimiter + | | | unclosed delimiter + | unclosed delimiter unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-62554.rs:6:89 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | - - - - - ^ + | | | | | | + | | | | | unclosed delimiter + | | | | unclosed delimiter + | | | unclosed delimiter + | unclosed delimiter unclosed delimiter + +error: expected `{`, found `macro_rules` + --> $DIR/issue-62554.rs:6:23 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | ^^^^^^^^^^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-62554.rs:6:20 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | ^^ +help: try placing this code inside a block + | +LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { } + | + + + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/issues/issue-62660.rs b/tests/ui/parser/issues/issue-62660.rs new file mode 100644 index 000000000..33c8a9fa3 --- /dev/null +++ b/tests/ui/parser/issues/issue-62660.rs @@ -0,0 +1,11 @@ +// Regression test for issue #62660: if a receiver's type does not +// successfully parse, emit the correct error instead of ICE-ing the compiler. + +struct Foo; + +impl Foo { + pub fn foo(_: i32, self: Box`, found `)` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-62660.stderr b/tests/ui/parser/issues/issue-62660.stderr new file mode 100644 index 000000000..14c0bdcb1 --- /dev/null +++ b/tests/ui/parser/issues/issue-62660.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)` + --> $DIR/issue-62660.rs:7:38 + | +LL | pub fn foo(_: i32, self: Box) {} + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-62881.rs b/tests/ui/parser/issues/issue-62881.rs new file mode 100644 index 000000000..b9204595f --- /dev/null +++ b/tests/ui/parser/issues/issue-62881.rs @@ -0,0 +1,6 @@ +fn main() {} + +fn f() -> isize { fn f() -> isize {} pub f< +//~^ ERROR missing `fn` or `struct` for function or struct definition +//~| ERROR mismatched types +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/issues/issue-62881.stderr b/tests/ui/parser/issues/issue-62881.stderr new file mode 100644 index 000000000..87be69baa --- /dev/null +++ b/tests/ui/parser/issues/issue-62881.stderr @@ -0,0 +1,26 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62881.rs:6:52 + | +LL | fn f() -> isize { fn f() -> isize {} pub f< + | - unclosed delimiter +... +LL | + | ^ + +error: missing `fn` or `struct` for function or struct definition + --> $DIR/issue-62881.rs:3:41 + | +LL | fn f() -> isize { fn f() -> isize {} pub f< + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-62881.rs:3:29 + | +LL | fn f() -> isize { fn f() -> isize {} pub f< + | - ^^^^^ expected `isize`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs new file mode 100644 index 000000000..b9c0bf834 --- /dev/null +++ b/tests/ui/parser/issues/issue-62894.rs @@ -0,0 +1,7 @@ +// Regression test for #62894, shouldn't crash. +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn` + +fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + +fn main() {} diff --git a/tests/ui/parser/issues/issue-62894.stderr b/tests/ui/parser/issues/issue-62894.stderr new file mode 100644 index 000000000..07a203bf4 --- /dev/null +++ b/tests/ui/parser/issues/issue-62894.stderr @@ -0,0 +1,50 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62894.rs:7:14 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +LL | +LL | fn main() {} + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-62894.rs:7:14 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +LL | +LL | fn main() {} + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-62894.rs:7:14 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +LL | +LL | fn main() {} + | ^ + +error: expected one of `(`, `[`, or `{`, found keyword `fn` + --> $DIR/issue-62894.rs:7:1 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - expected one of `(`, `[`, or `{` +LL | +LL | fn main() {} + | ^^ unexpected token + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: while parsing argument for this `expr` macro fragment + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issues/issue-62895.rs b/tests/ui/parser/issues/issue-62895.rs new file mode 100644 index 000000000..53f17405d --- /dev/null +++ b/tests/ui/parser/issues/issue-62895.rs @@ -0,0 +1,11 @@ +fn main() {} + +fn v() -> isize { //~ ERROR mismatched types +mod _ { //~ ERROR expected identifier +pub fn g() -> isizee { //~ ERROR cannot find type `isizee` in this scope +mod _ { //~ ERROR expected identifier +pub g() -> is //~ ERROR missing `fn` for function definition +(), w20); +} +(), w20); //~ ERROR expected item, found `;` +} diff --git a/tests/ui/parser/issues/issue-62895.stderr b/tests/ui/parser/issues/issue-62895.stderr new file mode 100644 index 000000000..2e7e500f4 --- /dev/null +++ b/tests/ui/parser/issues/issue-62895.stderr @@ -0,0 +1,47 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-62895.rs:4:5 + | +LL | mod _ { + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-62895.rs:6:5 + | +LL | mod _ { + | ^ expected identifier, found reserved identifier + +error: missing `fn` for function definition + --> $DIR/issue-62895.rs:7:4 + | +LL | pub g() -> is + | ^^^^ + | +help: add `fn` here to parse `g` as a public function + | +LL | pub fn g() -> is + | ++ + +error: expected item, found `;` + --> $DIR/issue-62895.rs:10:9 + | +LL | (), w20); + | ^ help: remove this semicolon + +error[E0412]: cannot find type `isizee` in this scope + --> $DIR/issue-62895.rs:5:15 + | +LL | pub fn g() -> isizee { + | ^^^^^^ help: a builtin type with a similar name exists: `isize` + +error[E0308]: mismatched types + --> $DIR/issue-62895.rs:3:11 + | +LL | fn v() -> isize { + | - ^^^^^ expected `isize`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0412. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-62913.rs b/tests/ui/parser/issues/issue-62913.rs new file mode 100644 index 000000000..0db06f636 --- /dev/null +++ b/tests/ui/parser/issues/issue-62913.rs @@ -0,0 +1,4 @@ +"\u\\" +//~^ ERROR incorrect unicode escape sequence +//~| ERROR invalid trailing slash in literal +//~| ERROR expected item, found `"\u\\"` diff --git a/tests/ui/parser/issues/issue-62913.stderr b/tests/ui/parser/issues/issue-62913.stderr new file mode 100644 index 000000000..6f385e8dc --- /dev/null +++ b/tests/ui/parser/issues/issue-62913.stderr @@ -0,0 +1,22 @@ +error: incorrect unicode escape sequence + --> $DIR/issue-62913.rs:1:2 + | +LL | "\u\" + | ^^^ incorrect unicode escape sequence + | + = help: format of unicode escape sequences is `\u{...}` + +error: invalid trailing slash in literal + --> $DIR/issue-62913.rs:1:5 + | +LL | "\u\" + | ^ invalid trailing slash in literal + +error: expected item, found `"\u\"` + --> $DIR/issue-62913.rs:1:1 + | +LL | "\u\" + | ^^^^^^ expected item + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs new file mode 100644 index 000000000..1c5d0c6f8 --- /dev/null +++ b/tests/ui/parser/issues/issue-62973.rs @@ -0,0 +1,8 @@ +// ignore-tidy-trailing-newlines +// error-pattern: aborting due to 7 previous errors + +fn main() {} + +fn p() { match s { v, E { [) {) } + + diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr new file mode 100644 index 000000000..4737bc718 --- /dev/null +++ b/tests/ui/parser/issues/issue-62973.stderr @@ -0,0 +1,83 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62973.rs:8:2 + | +LL | fn p() { match s { v, E { [) {) } + | - - unclosed delimiter + | | + | unclosed delimiter +LL | +LL | + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-62973.rs:8:2 + | +LL | fn p() { match s { v, E { [) {) } + | - - unclosed delimiter + | | + | unclosed delimiter +LL | +LL | + | ^ + +error: expected one of `,`, `:`, or `}`, found `{` + --> $DIR/issue-62973.rs:6:8 + | +LL | fn p() { match s { v, E { [) {) } + | ^ - ^ expected one of `,`, `:`, or `}` + | | | + | | while parsing this struct + | unclosed delimiter + | +help: `}` may belong here + | +LL | fn p() { match s { v, E} { [) {) } + | + +help: try naming a field + | +LL | fn p() { match s { v, E: E { [) {) } + | ++ + +error: struct literals are not allowed here + --> $DIR/issue-62973.rs:6:16 + | +LL | fn p() { match s { v, E { [) {) } + | ________________^ +LL | | +LL | | + | |_^ + | +help: surround the struct literal with parentheses + | +LL ~ fn p() { match (s { v, E { [) {) } +LL | +LL ~ ) + | + +error: expected one of `.`, `?`, `{`, or an operator, found `}` + --> $DIR/issue-62973.rs:8:2 + | +LL | fn p() { match s { v, E { [) {) } + | ----- while parsing this `match` expression +LL | +LL | + | ^ expected one of `.`, `?`, `{`, or an operator + +error: mismatched closing delimiter: `)` + --> $DIR/issue-62973.rs:6:27 + | +LL | fn p() { match s { v, E { [) {) } + | ^^ mismatched closing delimiter + | | + | unclosed delimiter + +error: mismatched closing delimiter: `)` + --> $DIR/issue-62973.rs:6:30 + | +LL | fn p() { match s { v, E { [) {) } + | ^^ mismatched closing delimiter + | | + | unclosed delimiter + +error: aborting due to 7 previous errors + diff --git a/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs b/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs new file mode 100644 index 000000000..b6e5091b6 --- /dev/null +++ b/tests/ui/parser/issues/issue-63115-range-pat-interpolated.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(exclusive_range_pattern)] + +#![allow(ellipsis_inclusive_range_patterns)] + +fn main() { + macro_rules! mac_expr { + ($e:expr) => { + if let 2...$e = 3 {} + if let 2..=$e = 3 {} + if let 2..$e = 3 {} + if let ..$e = 3 {} + if let ..=$e = 3 {} + if let $e.. = 5 {} + if let $e..5 = 4 {} + if let $e..=5 = 4 {} + } + } + mac_expr!(4); +} diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs new file mode 100644 index 000000000..430bc1d71 --- /dev/null +++ b/tests/ui/parser/issues/issue-63116.rs @@ -0,0 +1,3 @@ +// fixed by #66361 +// error-pattern: aborting due to 3 previous errors +impl W $DIR/issue-63116.rs:3:18 + | +LL | impl W $DIR/issue-63116.rs:3:12 + | +LL | impl W $DIR/issue-63116.rs:3:14 + | +LL | impl W $DIR/issue-63135.rs:3:16 + | +LL | fn i(n{...,f # + | - - ^ + | | | + | | unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-63135.rs:3:16 + | +LL | fn i(n{...,f # + | - - ^ + | | | + | | unclosed delimiter + | unclosed delimiter + +error: expected field pattern, found `...` + --> $DIR/issue-63135.rs:3:8 + | +LL | fn i(n{...,f # + | ^^^ help: to omit remaining fields, use one fewer `.`: `..` + +error: expected `}`, found `,` + --> $DIR/issue-63135.rs:3:11 + | +LL | fn i(n{...,f # + | ---^ + | | | + | | expected `}` + | `..` must be at the end and cannot have a trailing comma + +error: expected one of `!` or `[`, found `}` + --> $DIR/issue-63135.rs:3:16 + | +LL | fn i(n{...,f # + | - ^ expected one of `!` or `[` + | | + | while parsing the fields for this pattern + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/issues/issue-64732.rs b/tests/ui/parser/issues/issue-64732.rs new file mode 100644 index 000000000..2db51ea60 --- /dev/null +++ b/tests/ui/parser/issues/issue-64732.rs @@ -0,0 +1,9 @@ +#![allow(unused)] +fn main() { + let _foo = b'hello\0'; + //~^ ERROR character literal may only contain one codepoint + //~| HELP if you meant to write a byte string literal, use double quotes + let _bar = 'hello'; + //~^ ERROR character literal may only contain one codepoint + //~| HELP if you meant to write a `str` literal, use double quotes +} diff --git a/tests/ui/parser/issues/issue-64732.stderr b/tests/ui/parser/issues/issue-64732.stderr new file mode 100644 index 000000000..804625493 --- /dev/null +++ b/tests/ui/parser/issues/issue-64732.stderr @@ -0,0 +1,24 @@ +error: character literal may only contain one codepoint + --> $DIR/issue-64732.rs:3:16 + | +LL | let _foo = b'hello\0'; + | ^^^^^^^^^^ + | +help: if you meant to write a byte string literal, use double quotes + | +LL | let _foo = b"hello\0"; + | ~~~~~~~~~~ + +error: character literal may only contain one codepoint + --> $DIR/issue-64732.rs:6:16 + | +LL | let _bar = 'hello'; + | ^^^^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | let _bar = "hello"; + | ~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs new file mode 100644 index 000000000..ef89e31d8 --- /dev/null +++ b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs @@ -0,0 +1,28 @@ +// check-pass + +// Here we check that a `:vis` macro matcher subsititued for the empty visibility +// (`VisibilityKind::Inherited`) is accepted when used before an enum variant. + +fn main() {} + +macro_rules! mac_variant { + ($vis:vis MARKER) => { + enum Enum { + $vis Unit, + + $vis Tuple(u8, u16), + + $vis Struct { f: u8 }, + } + } +} + +mac_variant!(MARKER); + +// We also accept visibilities on variants syntactically but not semantically. +#[cfg(FALSE)] +enum E { + pub U, + pub(crate) T(u8), + pub(super) T { f: String } +} diff --git a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs new file mode 100644 index 000000000..b08767b21 --- /dev/null +++ b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs @@ -0,0 +1,28 @@ +// check-pass + +// Here we check that a `:vis` macro matcher subsititued for the empty visibility +// (`VisibilityKind::Inherited`) is accepted when used before an item in a trait. + +fn main() {} + +macro_rules! mac_in_trait { + ($vis:vis MARKER) => { + $vis fn beta() {} + + $vis const GAMMA: u8; + + $vis type Delta; + } +} + +trait Alpha { + mac_in_trait!(MARKER); +} + +// We also accept visibilities on items in traits syntactically but not semantically. +#[cfg(FALSE)] +trait Foo { + pub fn bar(); + pub(crate) type baz; + pub(super) const QUUX: u8; +} diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs new file mode 100644 index 000000000..30f3781bf --- /dev/null +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs @@ -0,0 +1,26 @@ +// Regression test; used to ICE with 'visit_mac_call disabled by default' due to a +// `MutVisitor` in `fn make_all_value_bindings_mutable` (`parse/parser/pat.rs`). + +macro_rules! mac1 { + ($eval:expr) => { + let mut $eval = (); + //~^ ERROR `mut` must be followed by a named binding + }; +} + +macro_rules! mac2 { + ($eval:pat) => { + let mut $eval = (); + //~^ ERROR `mut` must be followed by a named binding + //~| ERROR expected identifier, found `does_not_exist!()` + }; +} + +fn foo() { + mac1! { does_not_exist!() } + //~^ ERROR cannot find macro `does_not_exist` in this scope + mac2! { does_not_exist!() } + //~^ ERROR cannot find macro `does_not_exist` in this scope +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr new file mode 100644 index 000000000..8c032e588 --- /dev/null +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -0,0 +1,49 @@ +error: `mut` must be followed by a named binding + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13 + | +LL | let mut $eval = (); + | ^^^^^^^^^ help: remove the `mut` prefix: `does_not_exist!()` +... +LL | mac1! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + = note: this error originates in the macro `mac1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected identifier, found `does_not_exist!()` + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:17 + | +LL | let mut $eval = (); + | ^^^^^ expected identifier +... +LL | mac2! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `mut` must be followed by a named binding + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:13 + | +LL | let mut $eval = (); + | ^^^ help: remove the `mut` prefix: `does_not_exist!()` +... +LL | mac2! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find macro `does_not_exist` in this scope + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13 + | +LL | mac2! { does_not_exist!() } + | ^^^^^^^^^^^^^^ + +error: cannot find macro `does_not_exist` in this scope + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13 + | +LL | mac1! { does_not_exist!() } + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs b/tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs new file mode 100644 index 000000000..c1826f8ca --- /dev/null +++ b/tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs @@ -0,0 +1,21 @@ +fn main() { + auto n = 0;//~ ERROR invalid variable declaration + //~^ HELP write `let` instead of `auto` to introduce a new variable + auto m;//~ ERROR invalid variable declaration + //~^ HELP write `let` instead of `auto` to introduce a new variable + m = 0; + + var n = 0;//~ ERROR invalid variable declaration + //~^ HELP write `let` instead of `var` to introduce a new variable + var m;//~ ERROR invalid variable declaration + //~^ HELP write `let` instead of `var` to introduce a new variable + m = 0; + + mut n = 0;//~ ERROR invalid variable declaration + //~^ HELP missing keyword + mut var;//~ ERROR invalid variable declaration + //~^ HELP missing keyword + var = 0; + + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.stderr b/tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.stderr new file mode 100644 index 000000000..0a88dd2c4 --- /dev/null +++ b/tests/ui/parser/issues/issue-65257-invalid-var-decl-recovery.stderr @@ -0,0 +1,67 @@ +error: invalid variable declaration + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:2:5 + | +LL | auto n = 0; + | ^^^^ + | +help: write `let` instead of `auto` to introduce a new variable + | +LL | let n = 0; + | ~~~ + +error: invalid variable declaration + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:4:5 + | +LL | auto m; + | ^^^^ + | +help: write `let` instead of `auto` to introduce a new variable + | +LL | let m; + | ~~~ + +error: invalid variable declaration + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:8:5 + | +LL | var n = 0; + | ^^^ + | +help: write `let` instead of `var` to introduce a new variable + | +LL | let n = 0; + | ~~~ + +error: invalid variable declaration + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:10:5 + | +LL | var m; + | ^^^ + | +help: write `let` instead of `var` to introduce a new variable + | +LL | let m; + | ~~~ + +error: invalid variable declaration + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:14:5 + | +LL | mut n = 0; + | ^^^ help: missing keyword: `let mut` + +error: invalid variable declaration + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:16:5 + | +LL | mut var; + | ^^^ help: missing keyword: `let mut` + +error[E0308]: mismatched types + --> $DIR/issue-65257-invalid-var-decl-recovery.rs:20:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs b/tests/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs new file mode 100644 index 000000000..76c07bbfd --- /dev/null +++ b/tests/ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs @@ -0,0 +1,15 @@ +// run-pass + +// Test that failing macro matchers will not cause pre-expansion errors +// even though they use a feature that is pre-expansion gated. + +#[allow(unused_macro_rules)] +macro_rules! m { + ($e:expr) => { 0 }; // This fails on the input below due to `, foo`. + ($e:expr,) => { 1 }; // This also fails to match due to `foo`. + (box $e:expr, foo) => { 2 }; // Successful matcher, we should get `2`. +} + +fn main() { + assert_eq!(2, m!(box 42, foo)); +} diff --git a/tests/ui/parser/issues/issue-6610.rs b/tests/ui/parser/issues/issue-6610.rs new file mode 100644 index 000000000..9ed5a6122 --- /dev/null +++ b/tests/ui/parser/issues/issue-6610.rs @@ -0,0 +1,3 @@ +trait Foo { fn a() } //~ ERROR expected one of `->`, `;`, `where`, or `{`, found `}` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-6610.stderr b/tests/ui/parser/issues/issue-6610.stderr new file mode 100644 index 000000000..4a3bc7525 --- /dev/null +++ b/tests/ui/parser/issues/issue-6610.stderr @@ -0,0 +1,10 @@ +error: expected one of `->`, `;`, `where`, or `{`, found `}` + --> $DIR/issue-6610.rs:1:20 + | +LL | trait Foo { fn a() } + | - ^ expected one of `->`, `;`, `where`, or `{` + | | + | while parsing this `fn` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs new file mode 100644 index 000000000..aed428bfc --- /dev/null +++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs @@ -0,0 +1,14 @@ +// The problem in #66357 was that the call trace: +// +// - parse_fn_block_decl +// - expect_or +// - unexpected +// - expect_one_of +// - expected_one_of_not_found +// - recover_closing_delimiter +// +// ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`. + +fn f() { |[](* } +//~^ ERROR expected one of `,` or `:`, found `(` +//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr new file mode 100644 index 000000000..6cbab855c --- /dev/null +++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr @@ -0,0 +1,16 @@ +error: expected one of `,` or `:`, found `(` + --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 + | +LL | fn f() { |[](* } + | ^ expected one of `,` or `:` + +error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` + --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 + | +LL | fn f() { |[](* } + | ^^ help: `)` may belong here + | | + | unclosed delimiter + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-66473.rs b/tests/ui/parser/issues/issue-66473.rs new file mode 100644 index 000000000..9db4521bb Binary files /dev/null and b/tests/ui/parser/issues/issue-66473.rs differ diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr new file mode 100644 index 000000000..0e8b0a5da Binary files /dev/null and b/tests/ui/parser/issues/issue-66473.stderr differ diff --git a/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.fixed b/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.fixed new file mode 100644 index 000000000..95019b278 --- /dev/null +++ b/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +// In this regression test for #67146, we check that the +// negative outlives bound `!'a` is rejected by the parser. +// This regression was first introduced in PR #57364. + +fn main() {} + +pub fn f1() {} +//~^ ERROR negative bounds are not supported +pub fn f2<'a, T: Ord>() {} +//~^ ERROR negative bounds are not supported +pub fn f3<'a, T: Ord>() {} +//~^ ERROR negative bounds are not supported diff --git a/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs b/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs new file mode 100644 index 000000000..82f54f8fa --- /dev/null +++ b/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs @@ -0,0 +1,14 @@ +// run-rustfix + +// In this regression test for #67146, we check that the +// negative outlives bound `!'a` is rejected by the parser. +// This regression was first introduced in PR #57364. + +fn main() {} + +pub fn f1() {} +//~^ ERROR negative bounds are not supported +pub fn f2<'a, T: Ord + !'a>() {} +//~^ ERROR negative bounds are not supported +pub fn f3<'a, T: !'a + Ord>() {} +//~^ ERROR negative bounds are not supported diff --git a/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.stderr b/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.stderr new file mode 100644 index 000000000..a4a422948 --- /dev/null +++ b/tests/ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.stderr @@ -0,0 +1,20 @@ +error: negative bounds are not supported + --> $DIR/issue-67146-negative-outlives-bound-syntactic-fail.rs:9:12 + | +LL | pub fn f1() {} + | ^^^^^^^^^^ negative bounds are not supported + +error: negative bounds are not supported + --> $DIR/issue-67146-negative-outlives-bound-syntactic-fail.rs:11:22 + | +LL | pub fn f2<'a, T: Ord + !'a>() {} + | ^^^^^ negative bounds are not supported + +error: negative bounds are not supported + --> $DIR/issue-67146-negative-outlives-bound-syntactic-fail.rs:13:16 + | +LL | pub fn f3<'a, T: !'a + Ord>() {} + | ^^^^^ negative bounds are not supported + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs new file mode 100644 index 000000000..87222ef4b --- /dev/null +++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs @@ -0,0 +1,35 @@ +mod a { + use std::marker::PhantomData; + + enum Bug { + V = [PhantomData; { [ () ].len() ].len() as isize, + //~^ ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + } +} + +mod b { + enum Bug { + V = [Vec::new; { [].len() ].len() as isize, + //~^ ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR type annotations needed + } +} + +mod c { + enum Bug { + V = [Vec::new; { [0].len() ].len() as isize, + //~^ ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR mismatched closing delimiter: `]` + //~| ERROR type annotations needed + } +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr new file mode 100644 index 000000000..a00f37ed6 --- /dev/null +++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr @@ -0,0 +1,128 @@ +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 + | +LL | V = [PhantomData; { [ () ].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error: mismatched closing delimiter: `]` + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | - ^ ^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error[E0282]: type annotations needed + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:26 + | +LL | V = [Vec::new; { [].len() ].len() as isize, + | ^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14 + | +LL | V = [Vec::new; { [0].len() ].len() as isize, + | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` + | +help: consider specifying the generic argument + | +LL | V = [Vec::::new; { [0].len() ].len() as isize, + | +++++ + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs b/tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs new file mode 100644 index 000000000..3c49a5a97 --- /dev/null +++ b/tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs @@ -0,0 +1,6 @@ +pub struct Foo { + pub bar: Vecö + //~^ ERROR expected `,`, or `}`, found `ö` +} //~ ERROR expected `:`, found `}` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr new file mode 100644 index 000000000..adabb6859 --- /dev/null +++ b/tests/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr @@ -0,0 +1,19 @@ +error: expected `,`, or `}`, found `ö` + --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:2:22 + | +LL | pub bar: Vecö + | ^ help: try adding a comma: `,` + +error: expected `:`, found `}` + --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:4:1 + | +LL | pub struct Foo { + | --- while parsing this struct +LL | pub bar: Vecö + | - expected `:` +LL | +LL | } + | ^ unexpected token + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-68629.rs b/tests/ui/parser/issues/issue-68629.rs new file mode 100644 index 000000000..672a31f12 Binary files /dev/null and b/tests/ui/parser/issues/issue-68629.rs differ diff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr new file mode 100644 index 000000000..43a903e6c Binary files /dev/null and b/tests/ui/parser/issues/issue-68629.stderr differ diff --git a/tests/ui/parser/issues/issue-68730.rs b/tests/ui/parser/issues/issue-68730.rs new file mode 100644 index 000000000..20e18b4bc Binary files /dev/null and b/tests/ui/parser/issues/issue-68730.rs differ diff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr new file mode 100644 index 000000000..5bca5bbeb Binary files /dev/null and b/tests/ui/parser/issues/issue-68730.stderr differ diff --git a/tests/ui/parser/issues/issue-68788-in-trait-item-propagation.rs b/tests/ui/parser/issues/issue-68788-in-trait-item-propagation.rs new file mode 100644 index 000000000..7c3dd1d5a --- /dev/null +++ b/tests/ui/parser/issues/issue-68788-in-trait-item-propagation.rs @@ -0,0 +1,21 @@ +// Make sure we don't propagate restrictions on trait impl items to items inside them. + +// check-pass +// edition:2018 + +fn main() {} + +trait X { + fn foo(); +} + +impl X for () { + fn foo() { + struct S; + impl S { + pub const X: u8 = 0; + pub const fn bar() {} + async fn qux() {} + } + } +} diff --git a/tests/ui/parser/issues/issue-68890-2.rs b/tests/ui/parser/issues/issue-68890-2.rs new file mode 100644 index 000000000..29c123521 --- /dev/null +++ b/tests/ui/parser/issues/issue-68890-2.rs @@ -0,0 +1,5 @@ +fn main() {} + +type X<'a> = (?'a) +; +//~^ ERROR `?` may only modify trait bounds, not lifetime bounds +//~| ERROR at least one trait is required for an object type diff --git a/tests/ui/parser/issues/issue-68890-2.stderr b/tests/ui/parser/issues/issue-68890-2.stderr new file mode 100644 index 000000000..d9fb7beeb --- /dev/null +++ b/tests/ui/parser/issues/issue-68890-2.stderr @@ -0,0 +1,15 @@ +error: `?` may only modify trait bounds, not lifetime bounds + --> $DIR/issue-68890-2.rs:3:15 + | +LL | type X<'a> = (?'a) +; + | ^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-68890-2.rs:3:14 + | +LL | type X<'a> = (?'a) +; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/parser/issues/issue-68890.rs b/tests/ui/parser/issues/issue-68890.rs new file mode 100644 index 000000000..bab4ed7f8 --- /dev/null +++ b/tests/ui/parser/issues/issue-68890.rs @@ -0,0 +1,4 @@ +enum e{A((?'a a+?+l))} +//~^ ERROR `?` may only modify trait bounds, not lifetime bounds +//~| ERROR expected one of `)`, `+`, or `,` +//~| ERROR expected item, found `)` diff --git a/tests/ui/parser/issues/issue-68890.stderr b/tests/ui/parser/issues/issue-68890.stderr new file mode 100644 index 000000000..2a3bf6b41 --- /dev/null +++ b/tests/ui/parser/issues/issue-68890.stderr @@ -0,0 +1,20 @@ +error: `?` may only modify trait bounds, not lifetime bounds + --> $DIR/issue-68890.rs:1:11 + | +LL | enum e{A((?'a a+?+l))} + | ^ + +error: expected one of `)`, `+`, or `,`, found `a` + --> $DIR/issue-68890.rs:1:15 + | +LL | enum e{A((?'a a+?+l))} + | ^ expected one of `)`, `+`, or `,` + +error: expected item, found `)` + --> $DIR/issue-68890.rs:1:21 + | +LL | enum e{A((?'a a+?+l))} + | ^ expected item + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs b/tests/ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs new file mode 100644 index 000000000..aca9d9eb0 --- /dev/null +++ b/tests/ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs @@ -0,0 +1,16 @@ +// check-pass + +macro_rules! foo { + ($a:literal) => { + bar!($a) + }; +} + +macro_rules! bar { + ($b:literal) => {}; +} + +fn main() { + foo!(-2); + bar!(-2); +} diff --git a/tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs b/tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs new file mode 100644 index 000000000..ca8abd78c --- /dev/null +++ b/tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs @@ -0,0 +1,7 @@ +struct Foo(i32); + +fn main() { + let Foo(...) = Foo(0); //~ ERROR unexpected `...` + let [_, ..., _] = [0, 1]; //~ ERROR unexpected `...` + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.stderr b/tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.stderr new file mode 100644 index 000000000..4961e8fc0 --- /dev/null +++ b/tests/ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.stderr @@ -0,0 +1,29 @@ +error: unexpected `...` + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:4:13 + | +LL | let Foo(...) = Foo(0); + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error: unexpected `...` + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:5:13 + | +LL | let [_, ..., _] = [0, 1]; + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error[E0308]: mismatched types + --> $DIR/issue-70388-recover-dotdotdot-rest-pat.rs:6:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-70388-without-witness.fixed b/tests/ui/parser/issues/issue-70388-without-witness.fixed new file mode 100644 index 000000000..8d981405e --- /dev/null +++ b/tests/ui/parser/issues/issue-70388-without-witness.fixed @@ -0,0 +1,9 @@ +// run-rustfix +// This is for checking if we can apply suggestions as-is. + +pub struct Foo(#[allow(unused_tuple_struct_fields)] i32); + +fn main() { + let Foo(..) = Foo(0); //~ ERROR unexpected `...` + let [_, .., _] = [0, 1]; //~ ERROR unexpected `...` +} diff --git a/tests/ui/parser/issues/issue-70388-without-witness.rs b/tests/ui/parser/issues/issue-70388-without-witness.rs new file mode 100644 index 000000000..bf3607308 --- /dev/null +++ b/tests/ui/parser/issues/issue-70388-without-witness.rs @@ -0,0 +1,9 @@ +// run-rustfix +// This is for checking if we can apply suggestions as-is. + +pub struct Foo(#[allow(unused_tuple_struct_fields)] i32); + +fn main() { + let Foo(...) = Foo(0); //~ ERROR unexpected `...` + let [_, ..., _] = [0, 1]; //~ ERROR unexpected `...` +} diff --git a/tests/ui/parser/issues/issue-70388-without-witness.stderr b/tests/ui/parser/issues/issue-70388-without-witness.stderr new file mode 100644 index 000000000..b750ad4c6 --- /dev/null +++ b/tests/ui/parser/issues/issue-70388-without-witness.stderr @@ -0,0 +1,20 @@ +error: unexpected `...` + --> $DIR/issue-70388-without-witness.rs:7:13 + | +LL | let Foo(...) = Foo(0); + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error: unexpected `...` + --> $DIR/issue-70388-without-witness.rs:8:13 + | +LL | let [_, ..., _] = [0, 1]; + | ^^^ + | | + | not a valid pattern + | help: for a rest pattern, use `..` instead of `...` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs new file mode 100644 index 000000000..aeccd0d9f --- /dev/null +++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs @@ -0,0 +1,18 @@ +struct S {} + +impl S { + fn foo(&mur Self) {} + //~^ ERROR expected identifier, found keyword `Self` + //~| ERROR expected one of `:`, `@` + //~| ERROR the `Self` constructor can only be used with + fn bar(&'static mur Self) {} + //~^ ERROR unexpected lifetime + //~| ERROR expected identifier, found keyword `Self` + //~| ERROR expected one of `:`, `@` + //~| ERROR the `Self` constructor can only be used with + + fn baz(&mur Self @ _) {} + //~^ ERROR expected one of `:`, `@` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr new file mode 100644 index 000000000..421f14540 --- /dev/null +++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr @@ -0,0 +1,56 @@ +error: expected identifier, found keyword `Self` + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17 + | +LL | fn foo(&mur Self) {} + | ^^^^ expected identifier, found keyword + +error: expected one of `:`, `@`, or `|`, found keyword `Self` + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17 + | +LL | fn foo(&mur Self) {} + | -----^^^^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +error: unexpected lifetime `'static` in pattern + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:13 + | +LL | fn bar(&'static mur Self) {} + | ^^^^^^^ help: remove the lifetime + +error: expected identifier, found keyword `Self` + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25 + | +LL | fn bar(&'static mur Self) {} + | ^^^^ expected identifier, found keyword + +error: expected one of `:`, `@`, or `|`, found keyword `Self` + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25 + | +LL | fn bar(&'static mur Self) {} + | -------------^^^^ + | | | + | | expected one of `:`, `@`, or `|` + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:`, `@`, or `|`, found keyword `Self` + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:14:17 + | +LL | fn baz(&mur Self @ _) {} + | ^^^^ expected one of `:`, `@`, or `|` + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17 + | +LL | fn foo(&mur Self) {} + | ^^^^ help: use curly brackets: `Self { /* fields */ }` + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25 + | +LL | fn bar(&'static mur Self) {} + | ^^^^ help: use curly brackets: `Self { /* fields */ }` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs b/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs new file mode 100644 index 000000000..9b6dd7db4 --- /dev/null +++ b/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs @@ -0,0 +1,3 @@ +fn main() { + expr as fun()(:); //~ ERROR expected expression +} diff --git a/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr b/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr new file mode 100644 index 000000000..f03c92e1b --- /dev/null +++ b/tests/ui/parser/issues/issue-70552-ascription-in-parens-after-call.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `:` + --> $DIR/issue-70552-ascription-in-parens-after-call.rs:2:19 + | +LL | expr as fun()(:); + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-1.rs b/tests/ui/parser/issues/issue-70583-block-is-empty-1.rs new file mode 100644 index 000000000..f560f68f6 --- /dev/null +++ b/tests/ui/parser/issues/issue-70583-block-is-empty-1.rs @@ -0,0 +1,20 @@ +pub enum ErrorHandled { + Reported, + TooGeneric, +} + +impl ErrorHandled { + pub fn assert_reported(self) { + match self { + ErrorHandled::Reported => {} + ErrorHandled::TooGeneric => panic!(), + } + } +} + +fn struct_generic(x: Vec) { + for v in x { + println!("{}", v); + } + } +} //~ ERROR unexpected closing delimiter: `}` diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr new file mode 100644 index 000000000..39bf113ef --- /dev/null +++ b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr @@ -0,0 +1,13 @@ +error: unexpected closing delimiter: `}` + --> $DIR/issue-70583-block-is-empty-1.rs:20:1 + | +LL | fn struct_generic(x: Vec) { + | - this opening brace... +... +LL | } + | - ...matches this closing brace +LL | } + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-2.rs b/tests/ui/parser/issues/issue-70583-block-is-empty-2.rs new file mode 100644 index 000000000..80f53338a --- /dev/null +++ b/tests/ui/parser/issues/issue-70583-block-is-empty-2.rs @@ -0,0 +1,14 @@ +pub enum ErrorHandled { + Reported, + TooGeneric, +} + +impl ErrorHandled { + pub fn assert_reported(self) { + match self { + ErrorHandled::Reported => {}} + //^~ ERROR block is empty, you might have not meant to close it + ErrorHandled::TooGeneric => panic!(), + } + } +} //~ ERROR unexpected closing delimiter: `}` diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr new file mode 100644 index 000000000..5d37b2164 --- /dev/null +++ b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr @@ -0,0 +1,11 @@ +error: unexpected closing delimiter: `}` + --> $DIR/issue-70583-block-is-empty-2.rs:14:1 + | +LL | ErrorHandled::Reported => {}} + | -- block is empty, you might have not meant to close it +... +LL | } + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-7222.rs b/tests/ui/parser/issues/issue-7222.rs new file mode 100644 index 000000000..649073166 --- /dev/null +++ b/tests/ui/parser/issues/issue-7222.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 + +pub fn main() { + const FOO: f64 = 10.0; + + match 0.0 { + 0.0 ..= FOO => (), + _ => () + } +} diff --git a/tests/ui/parser/issues/issue-72253.rs b/tests/ui/parser/issues/issue-72253.rs new file mode 100644 index 000000000..1446a796f --- /dev/null +++ b/tests/ui/parser/issues/issue-72253.rs @@ -0,0 +1,6 @@ +fn main() { + let a = std::process::Command::new("echo") + .arg("1") + ,arg("2") //~ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `,` + .output(); +} diff --git a/tests/ui/parser/issues/issue-72253.stderr b/tests/ui/parser/issues/issue-72253.stderr new file mode 100644 index 000000000..477fa09f4 --- /dev/null +++ b/tests/ui/parser/issues/issue-72253.stderr @@ -0,0 +1,10 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `,` + --> $DIR/issue-72253.rs:4:9 + | +LL | .arg("1") + | - expected one of `.`, `;`, `?`, `else`, or an operator +LL | ,arg("2") + | ^ unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-72373.rs b/tests/ui/parser/issues/issue-72373.rs new file mode 100644 index 000000000..4da6061c2 --- /dev/null +++ b/tests/ui/parser/issues/issue-72373.rs @@ -0,0 +1,9 @@ +fn foo(c: &[u32], n: u32) -> u32 { + match *c { + [h, ..] if h > n => 0, + [h, ..] if h == n => 1, + [h, ref ts..] => foo(c, n - h) + foo(ts, n), + //~^ ERROR expected one of `,`, `@`, `]`, or `|`, found `..` + [] => 0, + } +} diff --git a/tests/ui/parser/issues/issue-72373.stderr b/tests/ui/parser/issues/issue-72373.stderr new file mode 100644 index 000000000..0bb99a01e --- /dev/null +++ b/tests/ui/parser/issues/issue-72373.stderr @@ -0,0 +1,13 @@ +error: expected one of `,`, `@`, `]`, or `|`, found `..` + --> $DIR/issue-72373.rs:5:19 + | +LL | [h, ref ts..] => foo(c, n - h) + foo(ts, n), + | ^^ expected one of `,`, `@`, `]`, or `|` + | +help: if you meant to bind the contents of the rest of the array pattern into `ts`, use `@` + | +LL | [h, ref ts @ ..] => foo(c, n - h) + foo(ts, n), + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs new file mode 100644 index 000000000..5f731f8db --- /dev/null +++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs @@ -0,0 +1,19 @@ +#![crate_type="lib"] +fn x<'a>(x: &mut 'a i32){} //~ ERROR lifetime must precede `mut` + +macro_rules! mac { + ($lt:lifetime) => { + fn w<$lt>(w: &mut $lt i32) {} + //~^ ERROR lifetime must precede `mut` + } +} + +mac!('a); + +// avoid false positives +fn y<'a>(y: &mut 'a + Send) { + //~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a` + //~| ERROR at least one trait is required for an object type + let z = y as &mut 'a + Send; + //~^ ERROR expected value, found trait `Send` +} diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr new file mode 100644 index 000000000..799bc16bd --- /dev/null +++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr @@ -0,0 +1,39 @@ +error: lifetime must precede `mut` + --> $DIR/issue-73568-lifetime-after-mut.rs:2:13 + | +LL | fn x<'a>(x: &mut 'a i32){} + | ^^^^^^^ help: place the lifetime before `mut`: `&'a mut` + +error[E0178]: expected a path on the left-hand side of `+`, not `&mut 'a` + --> $DIR/issue-73568-lifetime-after-mut.rs:14:13 + | +LL | fn y<'a>(y: &mut 'a + Send) { + | ^^^^^^^^^^^^^^ help: try adding parentheses: `&mut ('a + Send)` + +error: lifetime must precede `mut` + --> $DIR/issue-73568-lifetime-after-mut.rs:6:22 + | +LL | fn w<$lt>(w: &mut $lt i32) {} + | ^^^^^^^^ help: place the lifetime before `mut`: `&$lt mut` +... +LL | mac!('a); + | -------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found trait `Send` + --> $DIR/issue-73568-lifetime-after-mut.rs:17:28 + | +LL | let z = y as &mut 'a + Send; + | ^^^^ not a value + +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-73568-lifetime-after-mut.rs:14:18 + | +LL | fn y<'a>(y: &mut 'a + Send) { + | ^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0178, E0224, E0423. +For more information about an error, try `rustc --explain E0178`. diff --git a/tests/ui/parser/issues/issue-75599.rs b/tests/ui/parser/issues/issue-75599.rs new file mode 100644 index 000000000..0857676e4 --- /dev/null +++ b/tests/ui/parser/issues/issue-75599.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(non_upper_case_globals)] + +const or: usize = 1; +const and: usize = 2; + +mod or { + pub const X: usize = 3; +} + +mod and { + pub const X: usize = 4; +} + +fn main() { + match 0 { + 0 => {} + or => {} + and => {} + or::X => {} + and::X => {} + _ => {} + } +} diff --git a/tests/ui/parser/issues/issue-76437-async.rs b/tests/ui/parser/issues/issue-76437-async.rs new file mode 100644 index 000000000..84ee3dd21 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-async.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod t { + async pub fn t() {} + //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` + //~| HELP visibility `pub` must come before `async` +} diff --git a/tests/ui/parser/issues/issue-76437-async.stderr b/tests/ui/parser/issues/issue-76437-async.stderr new file mode 100644 index 000000000..2c9c2a8cf --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-async.stderr @@ -0,0 +1,11 @@ +error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-76437-async.rs:4:11 + | +LL | async pub fn t() {} + | ------^^^ + | | | + | | expected one of `extern`, `fn`, or `unsafe` + | help: visibility `pub` must come before `async`: `pub async` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-76437-const-async-unsafe.rs b/tests/ui/parser/issues/issue-76437-const-async-unsafe.rs new file mode 100644 index 000000000..f1e06e4ad --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-const-async-unsafe.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod t { + const async unsafe pub fn t() {} + //~^ ERROR expected one of `extern` or `fn`, found keyword `pub` + //~| HELP visibility `pub` must come before `const async unsafe` +} diff --git a/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr b/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr new file mode 100644 index 000000000..2e91beda1 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-const-async-unsafe.stderr @@ -0,0 +1,11 @@ +error: expected one of `extern` or `fn`, found keyword `pub` + --> $DIR/issue-76437-const-async-unsafe.rs:4:24 + | +LL | const async unsafe pub fn t() {} + | -------------------^^^ + | | | + | | expected one of `extern` or `fn` + | help: visibility `pub` must come before `const async unsafe`: `pub const async unsafe` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-76437-const-async.rs b/tests/ui/parser/issues/issue-76437-const-async.rs new file mode 100644 index 000000000..3c789fdcd --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-const-async.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod t { + const async pub fn t() {} + //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` + //~| HELP visibility `pub` must come before `const async` +} diff --git a/tests/ui/parser/issues/issue-76437-const-async.stderr b/tests/ui/parser/issues/issue-76437-const-async.stderr new file mode 100644 index 000000000..21b96c14d --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-const-async.stderr @@ -0,0 +1,11 @@ +error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-76437-const-async.rs:4:17 + | +LL | const async pub fn t() {} + | ------------^^^ + | | | + | | expected one of `extern`, `fn`, or `unsafe` + | help: visibility `pub` must come before `const async`: `pub const async` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-76437-const.rs b/tests/ui/parser/issues/issue-76437-const.rs new file mode 100644 index 000000000..d3815a523 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-const.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod t { + const pub fn t() {} + //~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + //~| HELP visibility `pub` must come before `const` +} diff --git a/tests/ui/parser/issues/issue-76437-const.stderr b/tests/ui/parser/issues/issue-76437-const.stderr new file mode 100644 index 000000000..cf80d9a90 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-const.stderr @@ -0,0 +1,11 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-76437-const.rs:4:11 + | +LL | const pub fn t() {} + | ------^^^ + | | | + | | expected one of `async`, `extern`, `fn`, or `unsafe` + | help: visibility `pub` must come before `const`: `pub const` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.rs b/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.rs new file mode 100644 index 000000000..daa1d1207 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod t { + unsafe pub(crate) fn t() {} + //~^ ERROR expected one of `extern` or `fn`, found keyword `pub` + //~| HELP visibility `pub(crate)` must come before `unsafe` +} diff --git a/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr b/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr new file mode 100644 index 000000000..fa8f13721 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-pub-crate-unsafe.stderr @@ -0,0 +1,11 @@ +error: expected one of `extern` or `fn`, found keyword `pub` + --> $DIR/issue-76437-pub-crate-unsafe.rs:4:12 + | +LL | unsafe pub(crate) fn t() {} + | -------^^^------- + | | | + | | expected one of `extern` or `fn` + | help: visibility `pub(crate)` must come before `unsafe`: `pub(crate) unsafe` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-76437-unsafe.rs b/tests/ui/parser/issues/issue-76437-unsafe.rs new file mode 100644 index 000000000..785a79a79 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-unsafe.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod t { + unsafe pub fn t() {} + //~^ ERROR expected one of `extern` or `fn`, found keyword `pub` + //~| HELP visibility `pub` must come before `unsafe` +} diff --git a/tests/ui/parser/issues/issue-76437-unsafe.stderr b/tests/ui/parser/issues/issue-76437-unsafe.stderr new file mode 100644 index 000000000..c63292ef8 --- /dev/null +++ b/tests/ui/parser/issues/issue-76437-unsafe.stderr @@ -0,0 +1,11 @@ +error: expected one of `extern` or `fn`, found keyword `pub` + --> $DIR/issue-76437-unsafe.rs:4:12 + | +LL | unsafe pub fn t() {} + | -------^^^ + | | | + | | expected one of `extern` or `fn` + | help: visibility `pub` must come before `unsafe`: `pub unsafe` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-76597.fixed b/tests/ui/parser/issues/issue-76597.fixed new file mode 100644 index 000000000..2d7a30b83 --- /dev/null +++ b/tests/ui/parser/issues/issue-76597.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +#![allow(dead_code)] +#![allow(unused_variables)] +fn f( + x: u8, + y: u8, +) {} +//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-76597.rs b/tests/ui/parser/issues/issue-76597.rs new file mode 100644 index 000000000..521b9c64b --- /dev/null +++ b/tests/ui/parser/issues/issue-76597.rs @@ -0,0 +1,11 @@ +// run-rustfix + +#![allow(dead_code)] +#![allow(unused_variables)] +fn f( + x: u8 + y: u8, +) {} +//~^^ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-76597.stderr b/tests/ui/parser/issues/issue-76597.stderr new file mode 100644 index 000000000..50b23329f --- /dev/null +++ b/tests/ui/parser/issues/issue-76597.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `y` + --> $DIR/issue-76597.rs:7:38 + | +LL | ... x: u8 + | - + | | + | expected one of 7 possible tokens + | help: missing `,` +LL | ... y: u8, + | ^ unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-7970b.rs b/tests/ui/parser/issues/issue-7970b.rs new file mode 100644 index 000000000..1c4abce39 --- /dev/null +++ b/tests/ui/parser/issues/issue-7970b.rs @@ -0,0 +1,4 @@ +fn main() {} + +macro_rules! test {} +//~^ ERROR unexpected end of macro invocation diff --git a/tests/ui/parser/issues/issue-7970b.stderr b/tests/ui/parser/issues/issue-7970b.stderr new file mode 100644 index 000000000..a62226a8a --- /dev/null +++ b/tests/ui/parser/issues/issue-7970b.stderr @@ -0,0 +1,8 @@ +error: unexpected end of macro invocation + --> $DIR/issue-7970b.rs:3:1 + | +LL | macro_rules! test {} + | ^^^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-81806.rs b/tests/ui/parser/issues/issue-81806.rs new file mode 100644 index 000000000..ca86788df --- /dev/null +++ b/tests/ui/parser/issues/issue-81806.rs @@ -0,0 +1,5 @@ +trait T { const +impl //~ ERROR: expected identifier, found keyword `impl` +} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-81806.stderr b/tests/ui/parser/issues/issue-81806.stderr new file mode 100644 index 000000000..40873388d --- /dev/null +++ b/tests/ui/parser/issues/issue-81806.stderr @@ -0,0 +1,17 @@ +error: expected identifier, found keyword `impl` + --> $DIR/issue-81806.rs:2:1 + | +LL | trait T { const + | - while parsing this item list starting here +LL | impl + | ^^^^ expected identifier, found keyword +LL | } + | - the item list ends here + | +help: escape `impl` to use it as an identifier + | +LL | r#impl + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-83639.rs b/tests/ui/parser/issues/issue-83639.rs new file mode 100644 index 000000000..6ddbedfa0 --- /dev/null +++ b/tests/ui/parser/issues/issue-83639.rs @@ -0,0 +1,6 @@ +// check-fail +// ignore-tidy-tab + +fn main() { + """ " //~ ERROR +} diff --git a/tests/ui/parser/issues/issue-83639.stderr b/tests/ui/parser/issues/issue-83639.stderr new file mode 100644 index 000000000..4c10df191 --- /dev/null +++ b/tests/ui/parser/issues/issue-83639.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `" "` + --> $DIR/issue-83639.rs:5:7 + | +LL | """ " + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs new file mode 100644 index 000000000..998949b94 --- /dev/null +++ b/tests/ui/parser/issues/issue-84104.rs @@ -0,0 +1,3 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected one of +#[i=i::<ښܖ< diff --git a/tests/ui/parser/issues/issue-84104.stderr b/tests/ui/parser/issues/issue-84104.stderr new file mode 100644 index 000000000..aff31f2c9 --- /dev/null +++ b/tests/ui/parser/issues/issue-84104.stderr @@ -0,0 +1,16 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-84104.rs:3:13 + | +LL | #[i=i::<ښܖ< + | - ^ + | | + | unclosed delimiter + +error: expected one of `>`, a const expression, lifetime, or type, found `]` + --> $DIR/issue-84104.rs:3:13 + | +LL | #[i=i::<ښܖ< + | ^ expected one of `>`, a const expression, lifetime, or type + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-84117.rs b/tests/ui/parser/issues/issue-84117.rs new file mode 100644 index 000000000..c9ebf1335 --- /dev/null +++ b/tests/ui/parser/issues/issue-84117.rs @@ -0,0 +1,9 @@ +fn main() { + let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + //~^ ERROR expected one of `>`, a const expression + //~| ERROR expected one of `>`, a const expression, lifetime, or type, found `}` + //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` +} +//~^ ERROR expected one of `,` or `>`, found `}` diff --git a/tests/ui/parser/issues/issue-84117.stderr b/tests/ui/parser/issues/issue-84117.stderr new file mode 100644 index 000000000..237bc11bd --- /dev/null +++ b/tests/ui/parser/issues/issue-84117.stderr @@ -0,0 +1,72 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `}` + --> $DIR/issue-84117.rs:2:67 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ----------- ^ expected one of `>`, a const expression, lifetime, or type + | | + | while parsing the type for `inner_local` + | +help: you might have meant to end the type parameters here + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, } + | + +help: use `=` if you meant to assign + | +LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, } + | ~ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + --> $DIR/issue-84117.rs:2:65 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ^ expected one of 8 possible tokens + +error: expected one of `,` or `>`, found `}` + --> $DIR/issue-84117.rs:8:1 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ----------- while parsing the type for `outer_local` - expected one of `,` or `>` +... +LL | } + | ^ unexpected token + | +help: you might have meant to end the type parameters here + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }> + | + +help: use `=` if you meant to assign + | +LL | let outer_local =e_outer<&str, { let inner_local:e_inner<&str, } + | ~ + +error: expected one of `>`, a const expression, lifetime, or type, found `}` + --> $DIR/issue-84117.rs:2:67 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ----------- ^ expected one of `>`, a const expression, lifetime, or type + | | + | while parsing the type for `inner_local` + | +help: you might have meant to end the type parameters here + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, } + | + +help: use `=` if you meant to assign + | +LL | let outer_local:e_outer<&str, { let inner_local =e_inner<&str, } + | ~ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + --> $DIR/issue-84117.rs:2:65 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + --> $DIR/issue-84117.rs:2:33 + | +LL | let outer_local:e_outer<&str, { let inner_local:e_inner<&str, } + | ^ expected one of 8 possible tokens + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/issues/issue-84148-1.rs b/tests/ui/parser/issues/issue-84148-1.rs new file mode 100644 index 000000000..9fa8086c2 --- /dev/null +++ b/tests/ui/parser/issues/issue-84148-1.rs @@ -0,0 +1,3 @@ +fn f(t:for<>t?) +//~^ ERROR: expected one of +//~| ERROR: invalid `?` in type diff --git a/tests/ui/parser/issues/issue-84148-1.stderr b/tests/ui/parser/issues/issue-84148-1.stderr new file mode 100644 index 000000000..9261067c2 --- /dev/null +++ b/tests/ui/parser/issues/issue-84148-1.stderr @@ -0,0 +1,19 @@ +error: invalid `?` in type + --> $DIR/issue-84148-1.rs:1:14 + | +LL | fn f(t:for<>t?) + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | fn f(t:Optiont>) + | +++++++ ~ + +error: expected one of `->`, `where`, or `{`, found `` + --> $DIR/issue-84148-1.rs:1:15 + | +LL | fn f(t:for<>t?) + | ^ expected one of `->`, `where`, or `{` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs new file mode 100644 index 000000000..2f6a7facf --- /dev/null +++ b/tests/ui/parser/issues/issue-84148-2.rs @@ -0,0 +1,3 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: invalid `?` in type +fn f(t:for<>t? diff --git a/tests/ui/parser/issues/issue-84148-2.stderr b/tests/ui/parser/issues/issue-84148-2.stderr new file mode 100644 index 000000000..71d543f9b --- /dev/null +++ b/tests/ui/parser/issues/issue-84148-2.stderr @@ -0,0 +1,27 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-84148-2.rs:3:16 + | +LL | fn f(t:for<>t? + | - ^ + | | + | unclosed delimiter + +error: invalid `?` in type + --> $DIR/issue-84148-2.rs:3:14 + | +LL | fn f(t:for<>t? + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | fn f(t:Optiont> + | +++++++ ~ + +error: expected one of `->`, `where`, or `{`, found `` + --> $DIR/issue-84148-2.rs:3:16 + | +LL | fn f(t:for<>t? + | ^ expected one of `->`, `where`, or `{` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-8537.rs b/tests/ui/parser/issues/issue-8537.rs new file mode 100644 index 000000000..9d0cbce6c --- /dev/null +++ b/tests/ui/parser/issues/issue-8537.rs @@ -0,0 +1,5 @@ +pub extern + "invalid-ab_isize" //~ ERROR invalid ABI +fn foo() {} + +fn main() {} diff --git a/tests/ui/parser/issues/issue-8537.stderr b/tests/ui/parser/issues/issue-8537.stderr new file mode 100644 index 000000000..523cc9dc5 --- /dev/null +++ b/tests/ui/parser/issues/issue-8537.stderr @@ -0,0 +1,11 @@ +error[E0703]: invalid ABI: found `invalid-ab_isize` + --> $DIR/issue-8537.rs:2:3 + | +LL | "invalid-ab_isize" + | ^^^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/parser/issues/issue-86895.rs b/tests/ui/parser/issues/issue-86895.rs new file mode 100644 index 000000000..4cd098431 --- /dev/null +++ b/tests/ui/parser/issues/issue-86895.rs @@ -0,0 +1,3 @@ +const pub () {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe` +pub fn main() {} diff --git a/tests/ui/parser/issues/issue-86895.stderr b/tests/ui/parser/issues/issue-86895.stderr new file mode 100644 index 000000000..575d857c0 --- /dev/null +++ b/tests/ui/parser/issues/issue-86895.stderr @@ -0,0 +1,8 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-86895.rs:1:7 + | +LL | const pub () {} + | ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs new file mode 100644 index 000000000..0b7b67496 --- /dev/null +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -0,0 +1,79 @@ +// Tests that a suggestion is issued if the user wrote a colon instead of +// a path separator in a match arm. + +mod qux { + pub enum Foo { + Bar, + Baz, + } +} + +use qux::Foo; + +fn f() -> Foo { Foo::Bar } + +fn g1() { + match f() { + Foo:Bar => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + match f() { + qux::Foo:Bar => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + match f() { + qux:Foo::Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + match f() { + qux: Foo::Baz if true => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } + if let Foo:Bar = f() { + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + } +} + +fn g1_neg() { + match f() { + ref qux: Foo::Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } +} + +fn g2_neg() { + match f() { + mut qux: Foo::Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + _ => {} + } +} + +fn main() { + let myfoo = Foo::Bar; + match myfoo { + Foo::Bar => {} + Foo:Bar::Baz => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + //~| ERROR: failed to resolve: `Bar` is a variant, not a module + } + match myfoo { + Foo::Bar => {} + Foo:Bar => {} + //~^ ERROR: expected one of + //~| HELP: maybe write a path separator here + } +} diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr new file mode 100644 index 000000000..2050a16be --- /dev/null +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -0,0 +1,90 @@ +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:17:12 + | +LL | Foo:Bar => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:23:17 + | +LL | qux::Foo:Bar => {} + | ^ + | | + | expected one of 8 possible tokens + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:29:12 + | +LL | qux:Foo::Baz => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:35:12 + | +LL | qux: Foo::Baz if true => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:40:15 + | +LL | if let Foo:Bar = f() { + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:48:16 + | +LL | ref qux: Foo::Baz => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:57:16 + | +LL | mut qux: Foo::Baz => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:68:12 + | +LL | Foo:Bar::Baz => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error: expected one of `@` or `|`, found `:` + --> $DIR/issue-87086-colon-path-sep.rs:75:12 + | +LL | Foo:Bar => {} + | ^ + | | + | expected one of `@` or `|` + | help: maybe write a path separator here: `::` + +error[E0433]: failed to resolve: `Bar` is a variant, not a module + --> $DIR/issue-87086-colon-path-sep.rs:68:13 + | +LL | Foo:Bar::Baz => {} + | ^^^ `Bar` is a variant, not a module + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/parser/issues/issue-87197-missing-semicolon.fixed b/tests/ui/parser/issues/issue-87197-missing-semicolon.fixed new file mode 100644 index 000000000..53f071db7 --- /dev/null +++ b/tests/ui/parser/issues/issue-87197-missing-semicolon.fixed @@ -0,0 +1,10 @@ +// run-rustfix +// Parser should know when a semicolon is missing. +// https://github.com/rust-lang/rust/issues/87197 + +fn main() { + let x = 100; //~ ERROR: expected `;` + println!("{}", x); //~ ERROR: expected `;` + let y = 200; //~ ERROR: expected `;` + println!("{}", y); +} diff --git a/tests/ui/parser/issues/issue-87197-missing-semicolon.rs b/tests/ui/parser/issues/issue-87197-missing-semicolon.rs new file mode 100644 index 000000000..db0edf452 --- /dev/null +++ b/tests/ui/parser/issues/issue-87197-missing-semicolon.rs @@ -0,0 +1,10 @@ +// run-rustfix +// Parser should know when a semicolon is missing. +// https://github.com/rust-lang/rust/issues/87197 + +fn main() { + let x = 100 //~ ERROR: expected `;` + println!("{}", x) //~ ERROR: expected `;` + let y = 200 //~ ERROR: expected `;` + println!("{}", y); +} diff --git a/tests/ui/parser/issues/issue-87197-missing-semicolon.stderr b/tests/ui/parser/issues/issue-87197-missing-semicolon.stderr new file mode 100644 index 000000000..57772de1e --- /dev/null +++ b/tests/ui/parser/issues/issue-87197-missing-semicolon.stderr @@ -0,0 +1,26 @@ +error: expected `;`, found `println` + --> $DIR/issue-87197-missing-semicolon.rs:6:16 + | +LL | let x = 100 + | ^ help: add `;` here +LL | println!("{}", x) + | ------- unexpected token + +error: expected `;`, found keyword `let` + --> $DIR/issue-87197-missing-semicolon.rs:7:22 + | +LL | println!("{}", x) + | ^ help: add `;` here +LL | let y = 200 + | --- unexpected token + +error: expected `;`, found `println` + --> $DIR/issue-87197-missing-semicolon.rs:8:16 + | +LL | let y = 200 + | ^ help: add `;` here +LL | println!("{}", y); + | ------- unexpected token + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs new file mode 100644 index 000000000..df0cd5439 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -0,0 +1,9 @@ +// edition:2018 + +// Test that even when `const` is already present, the proposed fix is to remove the second `const` + +const async const fn test() {} +//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` +//~| NOTE expected one of `extern`, `fn`, or `unsafe` +//~| HELP `const` already used earlier, remove this one +//~| NOTE `const` first seen here diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr new file mode 100644 index 000000000..977c6ebfe --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr @@ -0,0 +1,17 @@ +error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const` + --> $DIR/const-async-const.rs:5:13 + | +LL | const async const fn test() {} + | ^^^^^ + | | + | expected one of `extern`, `fn`, or `unsafe` + | help: `const` already used earlier, remove this one + | +note: `const` first seen here + --> $DIR/const-async-const.rs:5:1 + | +LL | const async const fn test() {} + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs new file mode 100644 index 000000000..bbebc99e9 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs @@ -0,0 +1,14 @@ +// edition:2018 + +// There is an order to respect for keywords before a function: +// `, const, async, unsafe, extern, ""` +// +// This test ensures the compiler is helpful about them being misplaced. +// Visibilities are tested elsewhere. + +async unsafe const fn test() {} +//~^ ERROR expected one of `extern` or `fn`, found keyword `const` +//~| NOTE expected one of `extern` or `fn` +//~| HELP `const` must come before `async unsafe` +//~| SUGGESTION const async unsafe +//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr new file mode 100644 index 000000000..f455caba1 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr @@ -0,0 +1,13 @@ +error: expected one of `extern` or `fn`, found keyword `const` + --> $DIR/several-kw-jump.rs:9:14 + | +LL | async unsafe const fn test() {} + | -------------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `const` must come before `async unsafe`: `const async unsafe` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs new file mode 100644 index 000000000..4ff4cf5c8 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs @@ -0,0 +1,14 @@ +// edition:2018 + +// There is an order to respect for keywords before a function: +// `, const, async, unsafe, extern, ""` +// +// This test ensures the compiler is helpful about them being misplaced. +// Visibilities are tested elsewhere. + +unsafe async fn test() {} +//~^ ERROR expected one of `extern` or `fn`, found keyword `async` +//~| NOTE expected one of `extern` or `fn` +//~| HELP `async` must come before `unsafe` +//~| SUGGESTION async unsafe +//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr new file mode 100644 index 000000000..e9eb14bf0 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.stderr @@ -0,0 +1,13 @@ +error: expected one of `extern` or `fn`, found keyword `async` + --> $DIR/wrong-async.rs:9:8 + | +LL | unsafe async fn test() {} + | -------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `async` must come before `unsafe`: `async unsafe` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs new file mode 100644 index 000000000..2f5fbc513 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs @@ -0,0 +1,14 @@ +// edition:2018 + +// There is an order to respect for keywords before a function: +// `, const, async, unsafe, extern, ""` +// +// This test ensures the compiler is helpful about them being misplaced. +// Visibilities are tested elsewhere. + +unsafe const fn test() {} +//~^ ERROR expected one of `extern` or `fn`, found keyword `const` +//~| NOTE expected one of `extern` or `fn` +//~| HELP `const` must come before `unsafe` +//~| SUGGESTION const unsafe +//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr new file mode 100644 index 000000000..0d2bc3472 --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.stderr @@ -0,0 +1,13 @@ +error: expected one of `extern` or `fn`, found keyword `const` + --> $DIR/wrong-const.rs:9:8 + | +LL | unsafe const fn test() {} + | -------^^^^^ + | | | + | | expected one of `extern` or `fn` + | help: `const` must come before `unsafe`: `const unsafe` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs new file mode 100644 index 000000000..df2412e3e --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs @@ -0,0 +1,14 @@ +// edition:2018 + +// There is an order to respect for keywords before a function: +// `, const, async, unsafe, extern, ""` +// +// This test ensures the compiler is helpful about them being misplaced. +// Visibilities are tested elsewhere. + +extern unsafe fn test() {} +//~^ ERROR expected `fn`, found keyword `unsafe` +//~| NOTE expected `fn` +//~| HELP `unsafe` must come before `extern` +//~| SUGGESTION unsafe extern +//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr new file mode 100644 index 000000000..4224713cc --- /dev/null +++ b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.stderr @@ -0,0 +1,13 @@ +error: expected `fn`, found keyword `unsafe` + --> $DIR/wrong-unsafe.rs:9:8 + | +LL | extern unsafe fn test() {} + | -------^^^^^^ + | | | + | | expected `fn` + | help: `unsafe` must come before `extern`: `unsafe extern` + | + = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-87635.rs b/tests/ui/parser/issues/issue-87635.rs new file mode 100644 index 000000000..f70a87fb0 --- /dev/null +++ b/tests/ui/parser/issues/issue-87635.rs @@ -0,0 +1,9 @@ +struct Foo {} + +impl Foo { + pub fn bar() + //~^ ERROR: associated function in `impl` without body +} +//~^ERROR expected one of `->`, `where`, or `{`, found `}` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-87635.stderr b/tests/ui/parser/issues/issue-87635.stderr new file mode 100644 index 000000000..1d459f1b9 --- /dev/null +++ b/tests/ui/parser/issues/issue-87635.stderr @@ -0,0 +1,19 @@ +error: expected one of `->`, `where`, or `{`, found `}` + --> $DIR/issue-87635.rs:6:1 + | +LL | pub fn bar() + | --- - expected one of `->`, `where`, or `{` + | | + | while parsing this `fn` +LL | +LL | } + | ^ unexpected token + +error: associated function in `impl` without body + --> $DIR/issue-87635.rs:4:5 + | +LL | pub fn bar() + | ^^^^^^^^^^^^- help: provide a definition for the function: `{ }` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-87812-path.rs b/tests/ui/parser/issues/issue-87812-path.rs new file mode 100644 index 000000000..b88780876 --- /dev/null +++ b/tests/ui/parser/issues/issue-87812-path.rs @@ -0,0 +1,11 @@ +macro_rules! foo { + ( $f:path ) => {{ + let _: usize = $f; //~ERROR + }}; +} + +struct Baz; + +fn main() { + foo!(Baz); +} diff --git a/tests/ui/parser/issues/issue-87812-path.stderr b/tests/ui/parser/issues/issue-87812-path.stderr new file mode 100644 index 000000000..f8ee05175 --- /dev/null +++ b/tests/ui/parser/issues/issue-87812-path.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-87812-path.rs:3:24 + | +LL | let _: usize = $f; + | ----- ^^ expected `usize`, found struct `Baz` + | | + | expected due to this +... +LL | foo!(Baz); + | --------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-87812.rs b/tests/ui/parser/issues/issue-87812.rs new file mode 100644 index 000000000..0ba87b995 --- /dev/null +++ b/tests/ui/parser/issues/issue-87812.rs @@ -0,0 +1,13 @@ +#![deny(break_with_label_and_loop)] + +macro_rules! foo { + ( $f:block ) => { + '_l: loop { + break '_l $f; //~ERROR + } + }; +} + +fn main() { + let x = foo!({ 3 }); +} diff --git a/tests/ui/parser/issues/issue-87812.stderr b/tests/ui/parser/issues/issue-87812.stderr new file mode 100644 index 000000000..d61ee23a5 --- /dev/null +++ b/tests/ui/parser/issues/issue-87812.stderr @@ -0,0 +1,22 @@ +error: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression + --> $DIR/issue-87812.rs:6:13 + | +LL | break '_l $f; + | ^^^^^^^^^^^^ +... +LL | let x = foo!({ 3 }); + | ----------- in this macro invocation + | +note: the lint level is defined here + --> $DIR/issue-87812.rs:1:9 + | +LL | #![deny(break_with_label_and_loop)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) +help: wrap this expression in parentheses + | +LL | break '_l ($f); + | + + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-88276-unary-plus.fixed b/tests/ui/parser/issues/issue-88276-unary-plus.fixed new file mode 100644 index 000000000..25b7c340f --- /dev/null +++ b/tests/ui/parser/issues/issue-88276-unary-plus.fixed @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_parens)] +fn main() { + let _ = 1; //~ ERROR leading `+` is not supported + let _ = (1.0 + 2.0) * 3.0; //~ ERROR leading `+` is not supported + //~| ERROR leading `+` is not supported + let _ = [3, 4+6]; //~ ERROR leading `+` is not supported +} diff --git a/tests/ui/parser/issues/issue-88276-unary-plus.rs b/tests/ui/parser/issues/issue-88276-unary-plus.rs new file mode 100644 index 000000000..11b2e9d60 --- /dev/null +++ b/tests/ui/parser/issues/issue-88276-unary-plus.rs @@ -0,0 +1,8 @@ +// run-rustfix +#[allow(unused_parens)] +fn main() { + let _ = +1; //~ ERROR leading `+` is not supported + let _ = (1.0 + +2.0) * +3.0; //~ ERROR leading `+` is not supported + //~| ERROR leading `+` is not supported + let _ = [+3, 4+6]; //~ ERROR leading `+` is not supported +} diff --git a/tests/ui/parser/issues/issue-88276-unary-plus.stderr b/tests/ui/parser/issues/issue-88276-unary-plus.stderr new file mode 100644 index 000000000..363e08201 --- /dev/null +++ b/tests/ui/parser/issues/issue-88276-unary-plus.stderr @@ -0,0 +1,50 @@ +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:4:13 + | +LL | let _ = +1; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = +1; +LL + let _ = 1; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:5:20 + | +LL | let _ = (1.0 + +2.0) * +3.0; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = (1.0 + +2.0) * +3.0; +LL + let _ = (1.0 + 2.0) * +3.0; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:5:28 + | +LL | let _ = (1.0 + +2.0) * +3.0; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = (1.0 + +2.0) * +3.0; +LL + let _ = (1.0 + +2.0) * 3.0; + | + +error: leading `+` is not supported + --> $DIR/issue-88276-unary-plus.rs:7:14 + | +LL | let _ = [+3, 4+6]; + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - let _ = [+3, 4+6]; +LL + let _ = [3, 4+6]; + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/issues/issue-88583-union-as-ident.rs b/tests/ui/parser/issues/issue-88583-union-as-ident.rs new file mode 100644 index 000000000..b3d66d46b --- /dev/null +++ b/tests/ui/parser/issues/issue-88583-union-as-ident.rs @@ -0,0 +1,15 @@ +// check-pass + +#![allow(non_camel_case_types)] + +struct union; + +impl union { + pub fn new() -> Self { + union { } + } +} + +fn main() { + let _u = union::new(); +} diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs new file mode 100644 index 000000000..bb69951c7 --- /dev/null +++ b/tests/ui/parser/issues/issue-88770.rs @@ -0,0 +1,11 @@ +// Regression test for the ICE described in #88770. + +// error-pattern:this file contains an unclosed delimiter +// error-pattern:expected one of +// error-pattern:missing `in` in `for` loop +// error-pattern:expected one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e` + +fn m(){print!("",(c for&g +u +e +e diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr new file mode 100644 index 000000000..4e3a21613 --- /dev/null +++ b/tests/ui/parser/issues/issue-88770.stderr @@ -0,0 +1,60 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-88770.rs:11:3 + | +LL | fn m(){print!("",(c for&g + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +... +LL | e + | ^ + +error: missing `in` in `for` loop + --> $DIR/issue-88770.rs:8:26 + | +LL | fn m(){print!("",(c for&g + | __________________________^ +LL | | u + | |_ help: try adding `in` here + +error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found keyword `for` + --> $DIR/issue-88770.rs:8:21 + | +LL | fn m(){print!("",(c for&g + | ^^^ expected one of 8 possible tokens + +error: expected one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e` + --> $DIR/issue-88770.rs:11:1 + | +LL | e + | - expected one of 9 possible tokens +LL | e + | ^ unexpected token + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/issues/issue-88818.rs b/tests/ui/parser/issues/issue-88818.rs new file mode 100644 index 000000000..b9233ca83 --- /dev/null +++ b/tests/ui/parser/issues/issue-88818.rs @@ -0,0 +1,10 @@ +// Regression test for #88818 (improve error message for missing trait +// in `impl for X`). + +struct S { } +impl for S { } +//~^ ERROR: missing trait in a trait impl +//~| HELP: add a trait here +//~| HELP: for an inherent impl, drop this `for` + +fn main() {} diff --git a/tests/ui/parser/issues/issue-88818.stderr b/tests/ui/parser/issues/issue-88818.stderr new file mode 100644 index 000000000..6e624c5a2 --- /dev/null +++ b/tests/ui/parser/issues/issue-88818.stderr @@ -0,0 +1,18 @@ +error: missing trait in a trait impl + --> $DIR/issue-88818.rs:5:5 + | +LL | impl for S { } + | ^ + | +help: add a trait here + | +LL | impl Trait for S { } + | +++++ +help: for an inherent impl, drop this `for` + | +LL - impl for S { } +LL + impl S { } + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-89388.rs b/tests/ui/parser/issues/issue-89388.rs new file mode 100644 index 000000000..9153c071e --- /dev/null +++ b/tests/ui/parser/issues/issue-89388.rs @@ -0,0 +1,7 @@ +// Regression test for #89388. + +fn main() { + let option: Option<&[u8]> = Some(b"..."); + let _ = option.map([_]::to_vec); + //~^ ERROR: missing angle brackets in associated item path +} diff --git a/tests/ui/parser/issues/issue-89388.stderr b/tests/ui/parser/issues/issue-89388.stderr new file mode 100644 index 000000000..cf28bef0f --- /dev/null +++ b/tests/ui/parser/issues/issue-89388.stderr @@ -0,0 +1,8 @@ +error: missing angle brackets in associated item path + --> $DIR/issue-89388.rs:5:24 + | +LL | let _ = option.map([_]::to_vec); + | ^^^^^^^^^^^ help: try: `<[_]>::to_vec` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-89396.fixed b/tests/ui/parser/issues/issue-89396.fixed new file mode 100644 index 000000000..823ad8cd1 --- /dev/null +++ b/tests/ui/parser/issues/issue-89396.fixed @@ -0,0 +1,16 @@ +// Regression test for issue #89396: Try to recover from a +// `=>` -> `=` or `->` typo in a match arm. + +// run-rustfix + +fn main() { + let opt = Some(42); + let _ = match opt { + Some(_) => true, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + None => false, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + }; +} diff --git a/tests/ui/parser/issues/issue-89396.rs b/tests/ui/parser/issues/issue-89396.rs new file mode 100644 index 000000000..f1d9efa52 --- /dev/null +++ b/tests/ui/parser/issues/issue-89396.rs @@ -0,0 +1,16 @@ +// Regression test for issue #89396: Try to recover from a +// `=>` -> `=` or `->` typo in a match arm. + +// run-rustfix + +fn main() { + let opt = Some(42); + let _ = match opt { + Some(_) = true, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + None -> false, + //~^ ERROR: expected one of + //~| HELP: try using a fat arrow here + }; +} diff --git a/tests/ui/parser/issues/issue-89396.stderr b/tests/ui/parser/issues/issue-89396.stderr new file mode 100644 index 000000000..504420574 --- /dev/null +++ b/tests/ui/parser/issues/issue-89396.stderr @@ -0,0 +1,20 @@ +error: expected one of `=>`, `if`, or `|`, found `=` + --> $DIR/issue-89396.rs:9:17 + | +LL | Some(_) = true, + | ^ + | | + | expected one of `=>`, `if`, or `|` + | help: try using a fat arrow here: `=>` + +error: expected one of `=>`, `@`, `if`, or `|`, found `->` + --> $DIR/issue-89396.rs:12:14 + | +LL | None -> false, + | ^^ + | | + | expected one of `=>`, `@`, `if`, or `|` + | help: try using a fat arrow here: `=>` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/issues/issue-89574.rs b/tests/ui/parser/issues/issue-89574.rs new file mode 100644 index 000000000..0a477f1aa --- /dev/null +++ b/tests/ui/parser/issues/issue-89574.rs @@ -0,0 +1,4 @@ +fn main() { + const EMPTY_ARRAY = []; + //~^ missing type for `const` item +} diff --git a/tests/ui/parser/issues/issue-89574.stderr b/tests/ui/parser/issues/issue-89574.stderr new file mode 100644 index 000000000..fb1312c78 --- /dev/null +++ b/tests/ui/parser/issues/issue-89574.stderr @@ -0,0 +1,8 @@ +error: missing type for `const` item + --> $DIR/issue-89574.rs:2:22 + | +LL | const EMPTY_ARRAY = []; + | ^ help: provide a type for the item: `: ` + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs new file mode 100644 index 000000000..fe67d9822 --- /dev/null +++ b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -0,0 +1,15 @@ +// aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs + +#[macro_use] +extern crate issue_89971_outer_attr_following_inner_attr_ice; + +fn main() { + Mew(); + X {}; +} + +#![deny(missing_docs)] +//~^ ERROR an inner attribute is not permitted in this context +#[derive(ICE)] +#[deny(missing_docs)] +struct Mew(); diff --git a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr new file mode 100644 index 000000000..a5ee24445 --- /dev/null +++ b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.stderr @@ -0,0 +1,18 @@ +error: an inner attribute is not permitted in this context + --> $DIR/issue-89971-outer-attr-following-inner-attr-ice.rs:11:1 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct Mew(); + | ------------- the inner attribute doesn't annotate this struct + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the struct, change the attribute from inner to outer style + | +LL - #![deny(missing_docs)] +LL + #[deny(missing_docs)] + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-90993.rs b/tests/ui/parser/issues/issue-90993.rs new file mode 100644 index 000000000..40e6fc748 --- /dev/null +++ b/tests/ui/parser/issues/issue-90993.rs @@ -0,0 +1,6 @@ +fn main() { + ...=. + //~^ ERROR: unexpected token: `...` + //~| ERROR: unexpected `=` after inclusive range + //~| ERROR: expected one of `-`, `;`, `}`, or path, found `.` +} diff --git a/tests/ui/parser/issues/issue-90993.stderr b/tests/ui/parser/issues/issue-90993.stderr new file mode 100644 index 000000000..ab6bce410 --- /dev/null +++ b/tests/ui/parser/issues/issue-90993.stderr @@ -0,0 +1,31 @@ +error: unexpected token: `...` + --> $DIR/issue-90993.rs:2:5 + | +LL | ...=. + | ^^^ + | +help: use `..` for an exclusive range + | +LL | ..=. + | ~~ +help: or `..=` for an inclusive range + | +LL | ..==. + | ~~~ + +error: unexpected `=` after inclusive range + --> $DIR/issue-90993.rs:2:5 + | +LL | ...=. + | ^^^^ help: use `..=` instead + | + = note: inclusive ranges end with a single equals sign (`..=`) + +error: expected one of `-`, `;`, `}`, or path, found `.` + --> $DIR/issue-90993.rs:2:9 + | +LL | ...=. + | ^ expected one of `-`, `;`, `}`, or path + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-91461.rs b/tests/ui/parser/issues/issue-91461.rs new file mode 100644 index 000000000..3e3c411c4 --- /dev/null +++ b/tests/ui/parser/issues/issue-91461.rs @@ -0,0 +1,6 @@ +fn main() { + a(_:b:,) + //~^ ERROR: expected identifier, found reserved identifier `_` + //~| ERROR: expected type, found `,` + //~| ERROR: expected type, found `,` +} diff --git a/tests/ui/parser/issues/issue-91461.stderr b/tests/ui/parser/issues/issue-91461.stderr new file mode 100644 index 000000000..94fcf1721 --- /dev/null +++ b/tests/ui/parser/issues/issue-91461.stderr @@ -0,0 +1,31 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-91461.rs:2:7 + | +LL | a(_:b:,) + | ^ expected identifier, found reserved identifier + +error: expected type, found `,` + --> $DIR/issue-91461.rs:2:11 + | +LL | a(_:b:,) + | - -^ expected type + | | | + | | tried to parse a type due to this type ascription + | while parsing this struct + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: see issue #23416 for more information + +error: expected type, found `,` + --> $DIR/issue-91461.rs:2:11 + | +LL | a(_:b:,) + | -^ expected type + | | + | tried to parse a type due to this type ascription + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: see issue #23416 for more information + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/issues/issue-93282.rs b/tests/ui/parser/issues/issue-93282.rs new file mode 100644 index 000000000..274245f1a --- /dev/null +++ b/tests/ui/parser/issues/issue-93282.rs @@ -0,0 +1,16 @@ +fn main() { + f<'a,> + //~^ ERROR expected + //~| ERROR expected +} + +fn bar(a: usize, b: usize) -> usize { + a + b +} + +fn foo() { + let x = 1; + bar('y, x); + //~^ ERROR expected + //~| ERROR mismatched types +} diff --git a/tests/ui/parser/issues/issue-93282.stderr b/tests/ui/parser/issues/issue-93282.stderr new file mode 100644 index 000000000..c6140bb82 --- /dev/null +++ b/tests/ui/parser/issues/issue-93282.stderr @@ -0,0 +1,50 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/issue-93282.rs:2:9 + | +LL | f<'a,> + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | f<'a',> + | + + +error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,` + --> $DIR/issue-93282.rs:2:9 + | +LL | f<'a,> + | ^ expected one of 9 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | f::<'a,> + | ++ + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/issue-93282.rs:13:11 + | +LL | bar('y, x); + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | bar('y', x); + | + + +error[E0308]: mismatched types + --> $DIR/issue-93282.rs:13:9 + | +LL | bar('y, x); + | --- ^^ expected `usize`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-93282.rs:7:4 + | +LL | fn bar(a: usize, b: usize) -> usize { + | ^^^ -------- + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/issues/issue-93867.rs b/tests/ui/parser/issues/issue-93867.rs new file mode 100644 index 000000000..507447923 --- /dev/null +++ b/tests/ui/parser/issues/issue-93867.rs @@ -0,0 +1,10 @@ +pub struct Entry<'a, K, V> { + k: &'a mut K, + v: V, +} + +pub fn entry<'a, K, V>() -> Entry<'a K, V> { +// ^ missing comma +//~^^ expected one of `,` or `>`, found `K` + unimplemented!() +} diff --git a/tests/ui/parser/issues/issue-93867.stderr b/tests/ui/parser/issues/issue-93867.stderr new file mode 100644 index 000000000..ee0cb4efd --- /dev/null +++ b/tests/ui/parser/issues/issue-93867.stderr @@ -0,0 +1,13 @@ +error: expected one of `,` or `>`, found `K` + --> $DIR/issue-93867.rs:6:38 + | +LL | pub fn entry<'a, K, V>() -> Entry<'a K, V> { + | ^ expected one of `,` or `>` + | +help: you might have meant to end the type parameters here + | +LL | pub fn entry<'a, K, V>() -> Entry<'a> K, V> { + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/issues/issue-94340.rs b/tests/ui/parser/issues/issue-94340.rs new file mode 100644 index 000000000..d0fb84a68 --- /dev/null +++ b/tests/ui/parser/issues/issue-94340.rs @@ -0,0 +1,8 @@ +// Make sure that unexpected inner attributes are not labeled as outer ones in diagnostics when +// trying to parse an item and that they are subsequently ignored not triggering confusing extra +// diagnostics like "expected item after attributes" which is not true for `include!` which can +// include empty files. + +include!("auxiliary/issue-94340-inc.rs"); + +fn main() {} diff --git a/tests/ui/parser/issues/issue-94340.stderr b/tests/ui/parser/issues/issue-94340.stderr new file mode 100644 index 000000000..9fd7c38a8 --- /dev/null +++ b/tests/ui/parser/issues/issue-94340.stderr @@ -0,0 +1,20 @@ +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:2:1 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/auxiliary/issue-94340-inc.rs:3:1 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/item-free-const-no-body-semantic-fail.rs b/tests/ui/parser/item-free-const-no-body-semantic-fail.rs new file mode 100644 index 000000000..613b3c985 --- /dev/null +++ b/tests/ui/parser/item-free-const-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +// Semantically, a free `const` item cannot omit its body. + +fn main() {} + +const A: u8; //~ ERROR free constant item without body +const B; //~ ERROR free constant item without body +//~^ ERROR missing type for `const` item diff --git a/tests/ui/parser/item-free-const-no-body-semantic-fail.stderr b/tests/ui/parser/item-free-const-no-body-semantic-fail.stderr new file mode 100644 index 000000000..5365b0a1f --- /dev/null +++ b/tests/ui/parser/item-free-const-no-body-semantic-fail.stderr @@ -0,0 +1,24 @@ +error: free constant item without body + --> $DIR/item-free-const-no-body-semantic-fail.rs:5:1 + | +LL | const A: u8; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: free constant item without body + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:1 + | +LL | const B; + | ^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: missing type for `const` item + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:8 + | +LL | const B; + | ^ help: provide a type for the item: `: ` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs b/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs new file mode 100644 index 000000000..acfdd3c36 --- /dev/null +++ b/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs @@ -0,0 +1,8 @@ +// Syntactically, a free `const` item can omit its body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +const X: u8; diff --git a/tests/ui/parser/item-free-static-no-body-semantic-fail.rs b/tests/ui/parser/item-free-static-no-body-semantic-fail.rs new file mode 100644 index 000000000..780479e3d --- /dev/null +++ b/tests/ui/parser/item-free-static-no-body-semantic-fail.rs @@ -0,0 +1,11 @@ +// Semantically, a free `static` item cannot omit its body. + +fn main() {} + +static A: u8; //~ ERROR free static item without body +static B; //~ ERROR free static item without body +//~^ ERROR missing type for `static` item + +static mut C: u8; //~ ERROR free static item without body +static mut D; //~ ERROR free static item without body +//~^ ERROR missing type for `static mut` item diff --git a/tests/ui/parser/item-free-static-no-body-semantic-fail.stderr b/tests/ui/parser/item-free-static-no-body-semantic-fail.stderr new file mode 100644 index 000000000..1b61e4305 --- /dev/null +++ b/tests/ui/parser/item-free-static-no-body-semantic-fail.stderr @@ -0,0 +1,46 @@ +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:5:1 + | +LL | static A: u8; + | ^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:1 + | +LL | static B; + | ^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1 + | +LL | static mut C: u8; + | ^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:1 + | +LL | static mut D; + | ^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: missing type for `static` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:9 + | +LL | static B; + | ^ help: provide a type for the item: `: ` + +error: missing type for `static mut` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:13 + | +LL | static mut D; + | ^ help: provide a type for the item: `: ` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs b/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs new file mode 100644 index 000000000..db0039204 --- /dev/null +++ b/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs @@ -0,0 +1,8 @@ +// Syntactically, a free `const` item can omit its body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +static X: u8; diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.rs b/tests/ui/parser/item-free-type-bounds-semantic-fail.rs new file mode 100644 index 000000000..9db4111fb --- /dev/null +++ b/tests/ui/parser/item-free-type-bounds-semantic-fail.rs @@ -0,0 +1,20 @@ +fn main() {} + +fn semantics() { + type A: Ord; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR free type alias without body + type B: Ord = u8; + //~^ ERROR bounds on `type`s in this context have no effect + type C: Ord where 'static: 'static = u8; + //~^ ERROR bounds on `type`s in this context have no effect + type D<_T>: Ord; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR free type alias without body + type E<_T>: Ord = u8; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR type parameter `_T` is unused + type F<_T>: Ord where 'static: 'static = u8; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR type parameter `_T` is unused +} diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr b/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr new file mode 100644 index 000000000..1b0865128 --- /dev/null +++ b/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr @@ -0,0 +1,67 @@ +error: free type alias without body + --> $DIR/item-free-type-bounds-semantic-fail.rs:4:5 + | +LL | type A: Ord; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:4:13 + | +LL | type A: Ord; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:7:13 + | +LL | type B: Ord = u8; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:9:13 + | +LL | type C: Ord where 'static: 'static = u8; + | ^^^ + +error: free type alias without body + --> $DIR/item-free-type-bounds-semantic-fail.rs:11:5 + | +LL | type D<_T>: Ord; + | ^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:11:17 + | +LL | type D<_T>: Ord; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:14:17 + | +LL | type E<_T>: Ord = u8; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:17:17 + | +LL | type F<_T>: Ord where 'static: 'static = u8; + | ^^^ + +error[E0091]: type parameter `_T` is unused + --> $DIR/item-free-type-bounds-semantic-fail.rs:14:12 + | +LL | type E<_T>: Ord = u8; + | ^^ unused type parameter + +error[E0091]: type parameter `_T` is unused + --> $DIR/item-free-type-bounds-semantic-fail.rs:17:12 + | +LL | type F<_T>: Ord where 'static: 'static = u8; + | ^^ unused type parameter + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0091`. diff --git a/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs b/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs new file mode 100644 index 000000000..58fc926d0 --- /dev/null +++ b/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + type A: Ord; + type B: Ord = u8; + type C: Ord where 'static: 'static = u8; + type D<_T>: Ord; + type E<_T>: Ord = u8; + type F<_T>: Ord where 'static: 'static = u8; +} diff --git a/tests/ui/parser/item-kw-case-mismatch.fixed b/tests/ui/parser/item-kw-case-mismatch.fixed new file mode 100644 index 000000000..1794268f2 --- /dev/null +++ b/tests/ui/parser/item-kw-case-mismatch.fixed @@ -0,0 +1,34 @@ +// run-rustfix +// edition:2018 +#![allow(unused_imports)] + +fn main() {} + +use std::ptr::read; //~ ERROR keyword `use` is written in a wrong case +use std::ptr::write; //~ ERROR keyword `use` is written in a wrong case + +async fn _a() {} +//~^ ERROR keyword `fn` is written in a wrong case + +fn _b() {} +//~^ ERROR keyword `fn` is written in a wrong case + +async fn _c() {} +//~^ ERROR keyword `async` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +async fn _d() {} +//~^ ERROR keyword `async` is written in a wrong case + +const unsafe fn _e() {} +//~^ ERROR keyword `const` is written in a wrong case +//~| ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +unsafe extern fn _f() {} +//~^ ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `extern` is written in a wrong case + +extern "C" fn _g() {} +//~^ ERROR keyword `extern` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case diff --git a/tests/ui/parser/item-kw-case-mismatch.rs b/tests/ui/parser/item-kw-case-mismatch.rs new file mode 100644 index 000000000..ac8390efd --- /dev/null +++ b/tests/ui/parser/item-kw-case-mismatch.rs @@ -0,0 +1,34 @@ +// run-rustfix +// edition:2018 +#![allow(unused_imports)] + +fn main() {} + +Use std::ptr::read; //~ ERROR keyword `use` is written in a wrong case +USE std::ptr::write; //~ ERROR keyword `use` is written in a wrong case + +async Fn _a() {} +//~^ ERROR keyword `fn` is written in a wrong case + +Fn _b() {} +//~^ ERROR keyword `fn` is written in a wrong case + +aSYNC fN _c() {} +//~^ ERROR keyword `async` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +Async fn _d() {} +//~^ ERROR keyword `async` is written in a wrong case + +CONST UNSAFE FN _e() {} +//~^ ERROR keyword `const` is written in a wrong case +//~| ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case + +unSAFE EXTern fn _f() {} +//~^ ERROR keyword `unsafe` is written in a wrong case +//~| ERROR keyword `extern` is written in a wrong case + +EXTERN "C" FN _g() {} +//~^ ERROR keyword `extern` is written in a wrong case +//~| ERROR keyword `fn` is written in a wrong case diff --git a/tests/ui/parser/item-kw-case-mismatch.stderr b/tests/ui/parser/item-kw-case-mismatch.stderr new file mode 100644 index 000000000..e66dae825 --- /dev/null +++ b/tests/ui/parser/item-kw-case-mismatch.stderr @@ -0,0 +1,86 @@ +error: keyword `use` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:7:1 + | +LL | Use std::ptr::read; + | ^^^ help: write it in the correct case (notice the capitalization): `use` + +error: keyword `use` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:8:1 + | +LL | USE std::ptr::write; + | ^^^ help: write it in the correct case: `use` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:10:7 + | +LL | async Fn _a() {} + | ^^ help: write it in the correct case (notice the capitalization): `fn` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:13:1 + | +LL | Fn _b() {} + | ^^ help: write it in the correct case (notice the capitalization): `fn` + +error: keyword `async` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:16:1 + | +LL | aSYNC fN _c() {} + | ^^^^^ help: write it in the correct case: `async` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:16:7 + | +LL | aSYNC fN _c() {} + | ^^ help: write it in the correct case: `fn` + +error: keyword `async` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:20:1 + | +LL | Async fn _d() {} + | ^^^^^ help: write it in the correct case: `async` + +error: keyword `const` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:23:1 + | +LL | CONST UNSAFE FN _e() {} + | ^^^^^ help: write it in the correct case: `const` + +error: keyword `unsafe` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:23:7 + | +LL | CONST UNSAFE FN _e() {} + | ^^^^^^ help: write it in the correct case: `unsafe` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:23:14 + | +LL | CONST UNSAFE FN _e() {} + | ^^ help: write it in the correct case: `fn` + +error: keyword `unsafe` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:28:1 + | +LL | unSAFE EXTern fn _f() {} + | ^^^^^^ help: write it in the correct case: `unsafe` + +error: keyword `extern` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:28:8 + | +LL | unSAFE EXTern fn _f() {} + | ^^^^^^ help: write it in the correct case: `extern` + +error: keyword `extern` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:32:1 + | +LL | EXTERN "C" FN _g() {} + | ^^^^^^ help: write it in the correct case: `extern` + +error: keyword `fn` is written in a wrong case + --> $DIR/item-kw-case-mismatch.rs:32:12 + | +LL | EXTERN "C" FN _g() {} + | ^^ help: write it in the correct case: `fn` + +error: aborting due to 14 previous errors + diff --git a/tests/ui/parser/item-needs-block.rs b/tests/ui/parser/item-needs-block.rs new file mode 100644 index 000000000..4edac588e --- /dev/null +++ b/tests/ui/parser/item-needs-block.rs @@ -0,0 +1,10 @@ +trait Trait; +//~^ ERROR expected `{}`, found `;` + +impl Trait for (); +//~^ ERROR expected `{}`, found `;` + +enum Enum; +//~^ ERROR expected `{}`, found `;` + +fn main() {} diff --git a/tests/ui/parser/item-needs-block.stderr b/tests/ui/parser/item-needs-block.stderr new file mode 100644 index 000000000..3cabd0c73 --- /dev/null +++ b/tests/ui/parser/item-needs-block.stderr @@ -0,0 +1,26 @@ +error: expected `{}`, found `;` + --> $DIR/item-needs-block.rs:1:12 + | +LL | trait Trait; + | ^ + | + = help: try using `{}` instead + +error: expected `{}`, found `;` + --> $DIR/item-needs-block.rs:4:18 + | +LL | impl Trait for (); + | ^ + | + = help: try using `{}` instead + +error: expected `{}`, found `;` + --> $DIR/item-needs-block.rs:7:10 + | +LL | enum Enum; + | ^ + | + = help: try using `{}` instead + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/keyword-abstract.rs b/tests/ui/parser/keyword-abstract.rs new file mode 100644 index 000000000..570206575 --- /dev/null +++ b/tests/ui/parser/keyword-abstract.rs @@ -0,0 +1,3 @@ +fn main() { + let abstract = (); //~ ERROR expected identifier, found reserved keyword `abstract` +} diff --git a/tests/ui/parser/keyword-abstract.stderr b/tests/ui/parser/keyword-abstract.stderr new file mode 100644 index 000000000..b7d1ce7cd --- /dev/null +++ b/tests/ui/parser/keyword-abstract.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `abstract` + --> $DIR/keyword-abstract.rs:2:9 + | +LL | let abstract = (); + | ^^^^^^^^ expected identifier, found reserved keyword + | +help: escape `abstract` to use it as an identifier + | +LL | let r#abstract = (); + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-as-as-identifier.rs b/tests/ui/parser/keyword-as-as-identifier.rs new file mode 100644 index 000000000..cd47c8a39 --- /dev/null +++ b/tests/ui/parser/keyword-as-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py as' + +fn main() { + let as = "foo"; //~ error: expected identifier, found keyword `as` +} diff --git a/tests/ui/parser/keyword-as-as-identifier.stderr b/tests/ui/parser/keyword-as-as-identifier.stderr new file mode 100644 index 000000000..3c5ad950d --- /dev/null +++ b/tests/ui/parser/keyword-as-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `as` + --> $DIR/keyword-as-as-identifier.rs:4:9 + | +LL | let as = "foo"; + | ^^ expected identifier, found keyword + | +help: escape `as` to use it as an identifier + | +LL | let r#as = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-box-as-identifier.rs b/tests/ui/parser/keyword-box-as-identifier.rs new file mode 100644 index 000000000..2cf49b66b --- /dev/null +++ b/tests/ui/parser/keyword-box-as-identifier.rs @@ -0,0 +1,10 @@ +fn main() { + let box = 0; + //~^ ERROR expected pattern, found `=` + let box: bool; + //~^ ERROR expected pattern, found `:` + let mut box = 0; + //~^ ERROR expected pattern, found `=` + let (box,) = (0,); + //~^ ERROR expected pattern, found `,` +} diff --git a/tests/ui/parser/keyword-box-as-identifier.stderr b/tests/ui/parser/keyword-box-as-identifier.stderr new file mode 100644 index 000000000..eaa1f8003 --- /dev/null +++ b/tests/ui/parser/keyword-box-as-identifier.stderr @@ -0,0 +1,66 @@ +error: expected pattern, found `=` + --> $DIR/keyword-box-as-identifier.rs:2:13 + | +LL | let box = 0; + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:2:9 + | +LL | let box = 0; + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let r#box = 0; + | ++ + +error: expected pattern, found `:` + --> $DIR/keyword-box-as-identifier.rs:4:12 + | +LL | let box: bool; + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:4:9 + | +LL | let box: bool; + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let r#box: bool; + | ++ + +error: expected pattern, found `=` + --> $DIR/keyword-box-as-identifier.rs:6:17 + | +LL | let mut box = 0; + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:6:13 + | +LL | let mut box = 0; + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let mut r#box = 0; + | ++ + +error: expected pattern, found `,` + --> $DIR/keyword-box-as-identifier.rs:8:13 + | +LL | let (box,) = (0,); + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:8:10 + | +LL | let (box,) = (0,); + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let (r#box,) = (0,); + | ++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/keyword-break-as-identifier.rs b/tests/ui/parser/keyword-break-as-identifier.rs new file mode 100644 index 000000000..04b25a7aa --- /dev/null +++ b/tests/ui/parser/keyword-break-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py break' + +fn main() { + let break = "foo"; //~ error: expected identifier, found keyword `break` +} diff --git a/tests/ui/parser/keyword-break-as-identifier.stderr b/tests/ui/parser/keyword-break-as-identifier.stderr new file mode 100644 index 000000000..a4535eb40 --- /dev/null +++ b/tests/ui/parser/keyword-break-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `break` + --> $DIR/keyword-break-as-identifier.rs:4:9 + | +LL | let break = "foo"; + | ^^^^^ expected identifier, found keyword + | +help: escape `break` to use it as an identifier + | +LL | let r#break = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-const-as-identifier.rs b/tests/ui/parser/keyword-const-as-identifier.rs new file mode 100644 index 000000000..6a2d926bf --- /dev/null +++ b/tests/ui/parser/keyword-const-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py const' + +fn main() { + let const = "foo"; //~ error: expected identifier, found keyword `const` +} diff --git a/tests/ui/parser/keyword-const-as-identifier.stderr b/tests/ui/parser/keyword-const-as-identifier.stderr new file mode 100644 index 000000000..31922f150 --- /dev/null +++ b/tests/ui/parser/keyword-const-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `const` + --> $DIR/keyword-const-as-identifier.rs:4:9 + | +LL | let const = "foo"; + | ^^^^^ expected identifier, found keyword + | +help: escape `const` to use it as an identifier + | +LL | let r#const = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-continue-as-identifier.rs b/tests/ui/parser/keyword-continue-as-identifier.rs new file mode 100644 index 000000000..cfdd62a2d --- /dev/null +++ b/tests/ui/parser/keyword-continue-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py continue' + +fn main() { + let continue = "foo"; //~ error: expected identifier, found keyword `continue` +} diff --git a/tests/ui/parser/keyword-continue-as-identifier.stderr b/tests/ui/parser/keyword-continue-as-identifier.stderr new file mode 100644 index 000000000..81285633f --- /dev/null +++ b/tests/ui/parser/keyword-continue-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `continue` + --> $DIR/keyword-continue-as-identifier.rs:4:9 + | +LL | let continue = "foo"; + | ^^^^^^^^ expected identifier, found keyword + | +help: escape `continue` to use it as an identifier + | +LL | let r#continue = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-else-as-identifier.rs b/tests/ui/parser/keyword-else-as-identifier.rs new file mode 100644 index 000000000..f12dac3ff --- /dev/null +++ b/tests/ui/parser/keyword-else-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py else' + +fn main() { + let else = "foo"; //~ error: expected identifier, found keyword `else` +} diff --git a/tests/ui/parser/keyword-else-as-identifier.stderr b/tests/ui/parser/keyword-else-as-identifier.stderr new file mode 100644 index 000000000..2125fe84a --- /dev/null +++ b/tests/ui/parser/keyword-else-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `else` + --> $DIR/keyword-else-as-identifier.rs:4:9 + | +LL | let else = "foo"; + | ^^^^ expected identifier, found keyword + | +help: escape `else` to use it as an identifier + | +LL | let r#else = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-enum-as-identifier.rs b/tests/ui/parser/keyword-enum-as-identifier.rs new file mode 100644 index 000000000..fe66230d0 --- /dev/null +++ b/tests/ui/parser/keyword-enum-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py enum' + +fn main() { + let enum = "foo"; //~ error: expected identifier, found keyword `enum` +} diff --git a/tests/ui/parser/keyword-enum-as-identifier.stderr b/tests/ui/parser/keyword-enum-as-identifier.stderr new file mode 100644 index 000000000..92d092ccb --- /dev/null +++ b/tests/ui/parser/keyword-enum-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `enum` + --> $DIR/keyword-enum-as-identifier.rs:4:9 + | +LL | let enum = "foo"; + | ^^^^ expected identifier, found keyword + | +help: escape `enum` to use it as an identifier + | +LL | let r#enum = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-final.rs b/tests/ui/parser/keyword-final.rs new file mode 100644 index 000000000..a79a11032 --- /dev/null +++ b/tests/ui/parser/keyword-final.rs @@ -0,0 +1,3 @@ +fn main() { + let final = (); //~ ERROR expected identifier, found reserved keyword `final` +} diff --git a/tests/ui/parser/keyword-final.stderr b/tests/ui/parser/keyword-final.stderr new file mode 100644 index 000000000..f1f9f2e2c --- /dev/null +++ b/tests/ui/parser/keyword-final.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `final` + --> $DIR/keyword-final.rs:2:9 + | +LL | let final = (); + | ^^^^^ expected identifier, found reserved keyword + | +help: escape `final` to use it as an identifier + | +LL | let r#final = (); + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-fn-as-identifier.rs b/tests/ui/parser/keyword-fn-as-identifier.rs new file mode 100644 index 000000000..f30e115f7 --- /dev/null +++ b/tests/ui/parser/keyword-fn-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py fn' + +fn main() { + let fn = "foo"; //~ error: expected identifier, found keyword `fn` +} diff --git a/tests/ui/parser/keyword-fn-as-identifier.stderr b/tests/ui/parser/keyword-fn-as-identifier.stderr new file mode 100644 index 000000000..645efbcae --- /dev/null +++ b/tests/ui/parser/keyword-fn-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `fn` + --> $DIR/keyword-fn-as-identifier.rs:4:9 + | +LL | let fn = "foo"; + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | let r#fn = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-for-as-identifier.rs b/tests/ui/parser/keyword-for-as-identifier.rs new file mode 100644 index 000000000..9e8a2ad53 --- /dev/null +++ b/tests/ui/parser/keyword-for-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py for' + +fn main() { + let for = "foo"; //~ error: expected identifier, found keyword `for` +} diff --git a/tests/ui/parser/keyword-for-as-identifier.stderr b/tests/ui/parser/keyword-for-as-identifier.stderr new file mode 100644 index 000000000..26407cc4d --- /dev/null +++ b/tests/ui/parser/keyword-for-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `for` + --> $DIR/keyword-for-as-identifier.rs:4:9 + | +LL | let for = "foo"; + | ^^^ expected identifier, found keyword + | +help: escape `for` to use it as an identifier + | +LL | let r#for = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-if-as-identifier.rs b/tests/ui/parser/keyword-if-as-identifier.rs new file mode 100644 index 000000000..0bd5756af --- /dev/null +++ b/tests/ui/parser/keyword-if-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py if' + +fn main() { + let if = "foo"; //~ error: expected identifier, found keyword `if` +} diff --git a/tests/ui/parser/keyword-if-as-identifier.stderr b/tests/ui/parser/keyword-if-as-identifier.stderr new file mode 100644 index 000000000..26f9a15a7 --- /dev/null +++ b/tests/ui/parser/keyword-if-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `if` + --> $DIR/keyword-if-as-identifier.rs:4:9 + | +LL | let if = "foo"; + | ^^ expected identifier, found keyword + | +help: escape `if` to use it as an identifier + | +LL | let r#if = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-impl-as-identifier.rs b/tests/ui/parser/keyword-impl-as-identifier.rs new file mode 100644 index 000000000..df529bae0 --- /dev/null +++ b/tests/ui/parser/keyword-impl-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py impl' + +fn main() { + let impl = "foo"; //~ error: expected identifier, found keyword `impl` +} diff --git a/tests/ui/parser/keyword-impl-as-identifier.stderr b/tests/ui/parser/keyword-impl-as-identifier.stderr new file mode 100644 index 000000000..73a50bc38 --- /dev/null +++ b/tests/ui/parser/keyword-impl-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `impl` + --> $DIR/keyword-impl-as-identifier.rs:4:9 + | +LL | let impl = "foo"; + | ^^^^ expected identifier, found keyword + | +help: escape `impl` to use it as an identifier + | +LL | let r#impl = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-in-as-identifier.rs b/tests/ui/parser/keyword-in-as-identifier.rs new file mode 100644 index 000000000..e4499dea2 --- /dev/null +++ b/tests/ui/parser/keyword-in-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py in' + +fn main() { + let in = "foo"; //~ error: expected pattern, found keyword `in` +} diff --git a/tests/ui/parser/keyword-in-as-identifier.stderr b/tests/ui/parser/keyword-in-as-identifier.stderr new file mode 100644 index 000000000..98332b723 --- /dev/null +++ b/tests/ui/parser/keyword-in-as-identifier.stderr @@ -0,0 +1,8 @@ +error: expected pattern, found keyword `in` + --> $DIR/keyword-in-as-identifier.rs:4:9 + | +LL | let in = "foo"; + | ^^ expected pattern + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-let-as-identifier.rs b/tests/ui/parser/keyword-let-as-identifier.rs new file mode 100644 index 000000000..9b1183501 --- /dev/null +++ b/tests/ui/parser/keyword-let-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py let' + +fn main() { + let let = "foo"; //~ error: expected identifier, found keyword `let` +} diff --git a/tests/ui/parser/keyword-let-as-identifier.stderr b/tests/ui/parser/keyword-let-as-identifier.stderr new file mode 100644 index 000000000..86faaed38 --- /dev/null +++ b/tests/ui/parser/keyword-let-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `let` + --> $DIR/keyword-let-as-identifier.rs:4:9 + | +LL | let let = "foo"; + | ^^^ expected identifier, found keyword + | +help: escape `let` to use it as an identifier + | +LL | let r#let = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-loop-as-identifier.rs b/tests/ui/parser/keyword-loop-as-identifier.rs new file mode 100644 index 000000000..46914a19b --- /dev/null +++ b/tests/ui/parser/keyword-loop-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py loop' + +fn main() { + let loop = "foo"; //~ error: expected identifier, found keyword `loop` +} diff --git a/tests/ui/parser/keyword-loop-as-identifier.stderr b/tests/ui/parser/keyword-loop-as-identifier.stderr new file mode 100644 index 000000000..304ad61cc --- /dev/null +++ b/tests/ui/parser/keyword-loop-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `loop` + --> $DIR/keyword-loop-as-identifier.rs:4:9 + | +LL | let loop = "foo"; + | ^^^^ expected identifier, found keyword + | +help: escape `loop` to use it as an identifier + | +LL | let r#loop = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-match-as-identifier.rs b/tests/ui/parser/keyword-match-as-identifier.rs new file mode 100644 index 000000000..d3cecb991 --- /dev/null +++ b/tests/ui/parser/keyword-match-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py match' + +fn main() { + let match = "foo"; //~ error: expected identifier, found keyword `match` +} diff --git a/tests/ui/parser/keyword-match-as-identifier.stderr b/tests/ui/parser/keyword-match-as-identifier.stderr new file mode 100644 index 000000000..25ac397fb --- /dev/null +++ b/tests/ui/parser/keyword-match-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `match` + --> $DIR/keyword-match-as-identifier.rs:4:9 + | +LL | let match = "foo"; + | ^^^^^ expected identifier, found keyword + | +help: escape `match` to use it as an identifier + | +LL | let r#match = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-mod-as-identifier.rs b/tests/ui/parser/keyword-mod-as-identifier.rs new file mode 100644 index 000000000..b9c7b6c78 --- /dev/null +++ b/tests/ui/parser/keyword-mod-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py mod' + +fn main() { + let mod = "foo"; //~ error: expected identifier, found keyword `mod` +} diff --git a/tests/ui/parser/keyword-mod-as-identifier.stderr b/tests/ui/parser/keyword-mod-as-identifier.stderr new file mode 100644 index 000000000..d5688e871 --- /dev/null +++ b/tests/ui/parser/keyword-mod-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `mod` + --> $DIR/keyword-mod-as-identifier.rs:4:9 + | +LL | let mod = "foo"; + | ^^^ expected identifier, found keyword + | +help: escape `mod` to use it as an identifier + | +LL | let r#mod = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-move-as-identifier.rs b/tests/ui/parser/keyword-move-as-identifier.rs new file mode 100644 index 000000000..65be02e3c --- /dev/null +++ b/tests/ui/parser/keyword-move-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py move' + +fn main() { + let move = "foo"; //~ error: expected identifier, found keyword `move` +} diff --git a/tests/ui/parser/keyword-move-as-identifier.stderr b/tests/ui/parser/keyword-move-as-identifier.stderr new file mode 100644 index 000000000..75653cffc --- /dev/null +++ b/tests/ui/parser/keyword-move-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `move` + --> $DIR/keyword-move-as-identifier.rs:4:9 + | +LL | let move = "foo"; + | ^^^^ expected identifier, found keyword + | +help: escape `move` to use it as an identifier + | +LL | let r#move = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-mut-as-identifier.rs b/tests/ui/parser/keyword-mut-as-identifier.rs new file mode 100644 index 000000000..9b919d2b3 --- /dev/null +++ b/tests/ui/parser/keyword-mut-as-identifier.rs @@ -0,0 +1,3 @@ +fn main() { + let mut = "foo"; //~ error: expected identifier, found `=` +} diff --git a/tests/ui/parser/keyword-mut-as-identifier.stderr b/tests/ui/parser/keyword-mut-as-identifier.stderr new file mode 100644 index 000000000..040960835 --- /dev/null +++ b/tests/ui/parser/keyword-mut-as-identifier.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `=` + --> $DIR/keyword-mut-as-identifier.rs:2:13 + | +LL | let mut = "foo"; + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-override.rs b/tests/ui/parser/keyword-override.rs new file mode 100644 index 000000000..009bebd7d --- /dev/null +++ b/tests/ui/parser/keyword-override.rs @@ -0,0 +1,3 @@ +fn main() { + let override = (); //~ ERROR expected identifier, found reserved keyword `override` +} diff --git a/tests/ui/parser/keyword-override.stderr b/tests/ui/parser/keyword-override.stderr new file mode 100644 index 000000000..cdb573686 --- /dev/null +++ b/tests/ui/parser/keyword-override.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `override` + --> $DIR/keyword-override.rs:2:9 + | +LL | let override = (); + | ^^^^^^^^ expected identifier, found reserved keyword + | +help: escape `override` to use it as an identifier + | +LL | let r#override = (); + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-pub-as-identifier.rs b/tests/ui/parser/keyword-pub-as-identifier.rs new file mode 100644 index 000000000..2b2bb1411 --- /dev/null +++ b/tests/ui/parser/keyword-pub-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py pub' + +fn main() { + let pub = "foo"; //~ error: expected identifier, found keyword `pub` +} diff --git a/tests/ui/parser/keyword-pub-as-identifier.stderr b/tests/ui/parser/keyword-pub-as-identifier.stderr new file mode 100644 index 000000000..8d513507c --- /dev/null +++ b/tests/ui/parser/keyword-pub-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `pub` + --> $DIR/keyword-pub-as-identifier.rs:4:9 + | +LL | let pub = "foo"; + | ^^^ expected identifier, found keyword + | +help: escape `pub` to use it as an identifier + | +LL | let r#pub = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-ref-as-identifier.rs b/tests/ui/parser/keyword-ref-as-identifier.rs new file mode 100644 index 000000000..f5e04b5db --- /dev/null +++ b/tests/ui/parser/keyword-ref-as-identifier.rs @@ -0,0 +1,3 @@ +fn main() { + let ref = "foo"; //~ error: expected identifier, found `=` +} diff --git a/tests/ui/parser/keyword-ref-as-identifier.stderr b/tests/ui/parser/keyword-ref-as-identifier.stderr new file mode 100644 index 000000000..618043d89 --- /dev/null +++ b/tests/ui/parser/keyword-ref-as-identifier.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `=` + --> $DIR/keyword-ref-as-identifier.rs:2:13 + | +LL | let ref = "foo"; + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-return-as-identifier.rs b/tests/ui/parser/keyword-return-as-identifier.rs new file mode 100644 index 000000000..e1a2db5e4 --- /dev/null +++ b/tests/ui/parser/keyword-return-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py return' + +fn main() { + let return = "foo"; //~ error: expected identifier, found keyword `return` +} diff --git a/tests/ui/parser/keyword-return-as-identifier.stderr b/tests/ui/parser/keyword-return-as-identifier.stderr new file mode 100644 index 000000000..eeb8e468b --- /dev/null +++ b/tests/ui/parser/keyword-return-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `return` + --> $DIR/keyword-return-as-identifier.rs:4:9 + | +LL | let return = "foo"; + | ^^^^^^ expected identifier, found keyword + | +help: escape `return` to use it as an identifier + | +LL | let r#return = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-static-as-identifier.rs b/tests/ui/parser/keyword-static-as-identifier.rs new file mode 100644 index 000000000..423b9854b --- /dev/null +++ b/tests/ui/parser/keyword-static-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py static' + +fn main() { + let static = "foo"; //~ error: expected identifier, found keyword `static` +} diff --git a/tests/ui/parser/keyword-static-as-identifier.stderr b/tests/ui/parser/keyword-static-as-identifier.stderr new file mode 100644 index 000000000..a3213e2f2 --- /dev/null +++ b/tests/ui/parser/keyword-static-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `static` + --> $DIR/keyword-static-as-identifier.rs:4:9 + | +LL | let static = "foo"; + | ^^^^^^ expected identifier, found keyword + | +help: escape `static` to use it as an identifier + | +LL | let r#static = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-struct-as-identifier.rs b/tests/ui/parser/keyword-struct-as-identifier.rs new file mode 100644 index 000000000..18cfe1159 --- /dev/null +++ b/tests/ui/parser/keyword-struct-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py struct' + +fn main() { + let struct = "foo"; //~ error: expected identifier, found keyword `struct` +} diff --git a/tests/ui/parser/keyword-struct-as-identifier.stderr b/tests/ui/parser/keyword-struct-as-identifier.stderr new file mode 100644 index 000000000..b73361a55 --- /dev/null +++ b/tests/ui/parser/keyword-struct-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `struct` + --> $DIR/keyword-struct-as-identifier.rs:4:9 + | +LL | let struct = "foo"; + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | let r#struct = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-trait-as-identifier.rs b/tests/ui/parser/keyword-trait-as-identifier.rs new file mode 100644 index 000000000..67f81167d --- /dev/null +++ b/tests/ui/parser/keyword-trait-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py trait' + +fn main() { + let trait = "foo"; //~ error: expected identifier, found keyword `trait` +} diff --git a/tests/ui/parser/keyword-trait-as-identifier.stderr b/tests/ui/parser/keyword-trait-as-identifier.stderr new file mode 100644 index 000000000..56ef5f606 --- /dev/null +++ b/tests/ui/parser/keyword-trait-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `trait` + --> $DIR/keyword-trait-as-identifier.rs:4:9 + | +LL | let trait = "foo"; + | ^^^^^ expected identifier, found keyword + | +help: escape `trait` to use it as an identifier + | +LL | let r#trait = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs new file mode 100644 index 000000000..4fa37bdb0 --- /dev/null +++ b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs @@ -0,0 +1,5 @@ +// compile-flags: --edition 2018 + +fn main() { + let try = "foo"; //~ error: expected identifier, found reserved keyword `try` +} diff --git a/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr b/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr new file mode 100644 index 000000000..94a106d47 --- /dev/null +++ b/tests/ui/parser/keyword-try-as-identifier-edition2018.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `try` + --> $DIR/keyword-try-as-identifier-edition2018.rs:4:9 + | +LL | let try = "foo"; + | ^^^ expected identifier, found reserved keyword + | +help: escape `try` to use it as an identifier + | +LL | let r#try = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-type-as-identifier.rs b/tests/ui/parser/keyword-type-as-identifier.rs new file mode 100644 index 000000000..04adddf72 --- /dev/null +++ b/tests/ui/parser/keyword-type-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py type' + +fn main() { + let type = "foo"; //~ error: expected identifier, found keyword `type` +} diff --git a/tests/ui/parser/keyword-type-as-identifier.stderr b/tests/ui/parser/keyword-type-as-identifier.stderr new file mode 100644 index 000000000..624c1006b --- /dev/null +++ b/tests/ui/parser/keyword-type-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `type` + --> $DIR/keyword-type-as-identifier.rs:4:9 + | +LL | let type = "foo"; + | ^^^^ expected identifier, found keyword + | +help: escape `type` to use it as an identifier + | +LL | let r#type = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-typeof.rs b/tests/ui/parser/keyword-typeof.rs new file mode 100644 index 000000000..29dc77d27 --- /dev/null +++ b/tests/ui/parser/keyword-typeof.rs @@ -0,0 +1,3 @@ +fn main() { + let typeof = (); //~ ERROR expected identifier, found reserved keyword `typeof` +} diff --git a/tests/ui/parser/keyword-typeof.stderr b/tests/ui/parser/keyword-typeof.stderr new file mode 100644 index 000000000..4c5324505 --- /dev/null +++ b/tests/ui/parser/keyword-typeof.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `typeof` + --> $DIR/keyword-typeof.rs:2:9 + | +LL | let typeof = (); + | ^^^^^^ expected identifier, found reserved keyword + | +help: escape `typeof` to use it as an identifier + | +LL | let r#typeof = (); + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-unsafe-as-identifier.rs b/tests/ui/parser/keyword-unsafe-as-identifier.rs new file mode 100644 index 000000000..0ff6d188c --- /dev/null +++ b/tests/ui/parser/keyword-unsafe-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe' + +fn main() { + let unsafe = "foo"; //~ error: expected identifier, found keyword `unsafe` +} diff --git a/tests/ui/parser/keyword-unsafe-as-identifier.stderr b/tests/ui/parser/keyword-unsafe-as-identifier.stderr new file mode 100644 index 000000000..b552c9cd3 --- /dev/null +++ b/tests/ui/parser/keyword-unsafe-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `unsafe` + --> $DIR/keyword-unsafe-as-identifier.rs:4:9 + | +LL | let unsafe = "foo"; + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | let r#unsafe = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-use-as-identifier.rs b/tests/ui/parser/keyword-use-as-identifier.rs new file mode 100644 index 000000000..821bedee0 --- /dev/null +++ b/tests/ui/parser/keyword-use-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py use' + +fn main() { + let use = "foo"; //~ error: expected identifier, found keyword `use` +} diff --git a/tests/ui/parser/keyword-use-as-identifier.stderr b/tests/ui/parser/keyword-use-as-identifier.stderr new file mode 100644 index 000000000..630798659 --- /dev/null +++ b/tests/ui/parser/keyword-use-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `use` + --> $DIR/keyword-use-as-identifier.rs:4:9 + | +LL | let use = "foo"; + | ^^^ expected identifier, found keyword + | +help: escape `use` to use it as an identifier + | +LL | let r#use = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-where-as-identifier.rs b/tests/ui/parser/keyword-where-as-identifier.rs new file mode 100644 index 000000000..56301bd20 --- /dev/null +++ b/tests/ui/parser/keyword-where-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py where' + +fn main() { + let where = "foo"; //~ error: expected identifier, found keyword `where` +} diff --git a/tests/ui/parser/keyword-where-as-identifier.stderr b/tests/ui/parser/keyword-where-as-identifier.stderr new file mode 100644 index 000000000..9e72f7940 --- /dev/null +++ b/tests/ui/parser/keyword-where-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `where` + --> $DIR/keyword-where-as-identifier.rs:4:9 + | +LL | let where = "foo"; + | ^^^^^ expected identifier, found keyword + | +help: escape `where` to use it as an identifier + | +LL | let r#where = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword-while-as-identifier.rs b/tests/ui/parser/keyword-while-as-identifier.rs new file mode 100644 index 000000000..22026d15d --- /dev/null +++ b/tests/ui/parser/keyword-while-as-identifier.rs @@ -0,0 +1,5 @@ +// This file was auto-generated using 'src/etc/generate-keyword-tests.py while' + +fn main() { + let while = "foo"; //~ error: expected identifier, found keyword `while` +} diff --git a/tests/ui/parser/keyword-while-as-identifier.stderr b/tests/ui/parser/keyword-while-as-identifier.stderr new file mode 100644 index 000000000..2bb62105d --- /dev/null +++ b/tests/ui/parser/keyword-while-as-identifier.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `while` + --> $DIR/keyword-while-as-identifier.rs:4:9 + | +LL | let while = "foo"; + | ^^^^^ expected identifier, found keyword + | +help: escape `while` to use it as an identifier + | +LL | let r#while = "foo"; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keyword.rs b/tests/ui/parser/keyword.rs new file mode 100644 index 000000000..1eb7886c5 --- /dev/null +++ b/tests/ui/parser/keyword.rs @@ -0,0 +1,5 @@ +pub mod break { + //~^ ERROR expected identifier, found keyword `break` +} + +fn main() {} diff --git a/tests/ui/parser/keyword.stderr b/tests/ui/parser/keyword.stderr new file mode 100644 index 000000000..ee7d72b39 --- /dev/null +++ b/tests/ui/parser/keyword.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found keyword `break` + --> $DIR/keyword.rs:1:9 + | +LL | pub mod break { + | ^^^^^ expected identifier, found keyword + | +help: escape `break` to use it as an identifier + | +LL | pub mod r#break { + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/keywords-followed-by-double-colon.rs b/tests/ui/parser/keywords-followed-by-double-colon.rs new file mode 100644 index 000000000..5c7049f7c --- /dev/null +++ b/tests/ui/parser/keywords-followed-by-double-colon.rs @@ -0,0 +1,8 @@ +fn main() { + struct::foo(); + //~^ ERROR expected identifier +} +fn bar() { + mut::baz(); + //~^ ERROR expected expression, found keyword `mut` +} diff --git a/tests/ui/parser/keywords-followed-by-double-colon.stderr b/tests/ui/parser/keywords-followed-by-double-colon.stderr new file mode 100644 index 000000000..4c4d5e5dd --- /dev/null +++ b/tests/ui/parser/keywords-followed-by-double-colon.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found `::` + --> $DIR/keywords-followed-by-double-colon.rs:2:11 + | +LL | struct::foo(); + | ^^ expected identifier + +error: expected expression, found keyword `mut` + --> $DIR/keywords-followed-by-double-colon.rs:6:5 + | +LL | mut::baz(); + | ^^^ expected expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/kw-in-trait-bounds.rs b/tests/ui/parser/kw-in-trait-bounds.rs new file mode 100644 index 000000000..e9e85339a --- /dev/null +++ b/tests/ui/parser/kw-in-trait-bounds.rs @@ -0,0 +1,39 @@ +// edition:2018 + +fn _f(_: impl fn(), _: &dyn fn()) +//~^ ERROR expected identifier, found keyword `fn` +//~| ERROR expected identifier, found keyword `fn` +//~| ERROR expected identifier, found keyword `fn` +//~| HELP use `Fn` to refer to the trait +//~| HELP use `Fn` to refer to the trait +//~| HELP use `Fn` to refer to the trait +where +G: fn(), + //~^ ERROR expected identifier, found keyword `fn` + //~| HELP use `Fn` to refer to the trait +{} + +fn _g(_: impl struct, _: &dyn struct) +//~^ ERROR expected identifier, found keyword `struct` +//~| ERROR expected identifier, found keyword `struct` +//~| ERROR expected identifier, found keyword `struct` +//~| ERROR cannot find trait `r#struct` in this scope +//~| ERROR cannot find trait `r#struct` in this scope +//~| ERROR cannot find trait `r#struct` in this scope +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP escape `struct` to use it as an identifier +//~| HELP escape `struct` to use it as an identifier +//~| HELP escape `struct` to use it as an identifier +where + B: struct, + //~^ ERROR expected identifier, found keyword `struct` + //~| ERROR cannot find trait `r#struct` in this scope + //~| HELP a trait with a similar name exists + //~| HELP escape `struct` to use it as an identifier +{} + +trait Struct {} + +fn main() {} diff --git a/tests/ui/parser/kw-in-trait-bounds.stderr b/tests/ui/parser/kw-in-trait-bounds.stderr new file mode 100644 index 000000000..2d3aad4d6 --- /dev/null +++ b/tests/ui/parser/kw-in-trait-bounds.stderr @@ -0,0 +1,127 @@ +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:10 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ~~ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:27 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn _f(_: impl Fn(), _: &dyn fn()) + | ~~ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:41 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn _f(_: impl fn(), _: &dyn Fn()) + | ~~ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:11:4 + | +LL | G: fn(), + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | G: Fn(), + | ~~ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:16:10 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:16:29 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g(_: impl r#struct, _: &dyn struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:16:45 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g(_: impl struct, _: &dyn r#struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:30:8 + | +LL | B: struct, + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | B: r#struct, + | ++ + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:16:10 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:30:8 + | +LL | B: struct, + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:16:29 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:16:45 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/label-after-block-like.rs b/tests/ui/parser/label-after-block-like.rs new file mode 100644 index 000000000..55f3f8f9f --- /dev/null +++ b/tests/ui/parser/label-after-block-like.rs @@ -0,0 +1,43 @@ +fn a() { + if let () = () 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn b() { + if true 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn c() { + loop 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn d() { + while true 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn e() { + while let () = () 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn f() { + for _ in 0..0 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn g() { + unsafe 'a {} + //~^ ERROR labeled expression must be followed by `:` + //~| ERROR expected `{`, found `'a` +} + +fn main() {} diff --git a/tests/ui/parser/label-after-block-like.stderr b/tests/ui/parser/label-after-block-like.stderr new file mode 100644 index 000000000..8ff50b124 --- /dev/null +++ b/tests/ui/parser/label-after-block-like.stderr @@ -0,0 +1,176 @@ +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:2:20 + | +LL | if let () = () 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:2:20 + | +LL | if let () = () 'a {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/label-after-block-like.rs:2:8 + | +LL | if let () = () 'a {} + | ^^^^^^^^^^^ +help: try placing this code inside a block + | +LL | if let () = () { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:8:13 + | +LL | if true 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:8:13 + | +LL | if true 'a {} + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/label-after-block-like.rs:8:8 + | +LL | if true 'a {} + | ^^^^ +help: try placing this code inside a block + | +LL | if true { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:14:10 + | +LL | loop 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:14:10 + | +LL | loop 'a {} + | ---- ^^ expected `{` + | | + | while parsing this `loop` expression + | +help: try placing this code inside a block + | +LL | loop { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:20:16 + | +LL | while true 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:20:16 + | +LL | while true 'a {} + | ----- ---- ^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + | +help: try placing this code inside a block + | +LL | while true { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:26:23 + | +LL | while let () = () 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:26:23 + | +LL | while let () = () 'a {} + | ----- ----------- ^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + | +help: try placing this code inside a block + | +LL | while let () = () { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:32:19 + | +LL | for _ in 0..0 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:32:19 + | +LL | for _ in 0..0 'a {} + | ^^ expected `{` + | +help: try placing this code inside a block + | +LL | for _ in 0..0 { 'a {} } + | + + + +error: labeled expression must be followed by `:` + --> $DIR/label-after-block-like.rs:38:12 + | +LL | unsafe 'a {} + | ---^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `{`, found `'a` + --> $DIR/label-after-block-like.rs:38:12 + | +LL | unsafe 'a {} + | ------ ^^ expected `{` + | | + | while parsing this `unsafe` expression + | +help: try placing this code inside a block + | +LL | unsafe { 'a {} } + | + + + +error: aborting due to 14 previous errors + diff --git a/tests/ui/parser/label-is-actually-char.rs b/tests/ui/parser/label-is-actually-char.rs new file mode 100644 index 000000000..183da603d --- /dev/null +++ b/tests/ui/parser/label-is-actually-char.rs @@ -0,0 +1,16 @@ +fn main() { + let c = 'a; + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| HELP add `'` to close the char literal + match c { + 'a'..='b => {} + //~^ ERROR unexpected token: `'b` + //~| HELP add `'` to close the char literal + _ => {} + } + let x = ['a, 'b]; + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected `while`, `for`, `loop` or `{` after a label + //~| HELP add `'` to close the char literal + //~| HELP add `'` to close the char literal +} diff --git a/tests/ui/parser/label-is-actually-char.stderr b/tests/ui/parser/label-is-actually-char.stderr new file mode 100644 index 000000000..28c8d2ada --- /dev/null +++ b/tests/ui/parser/label-is-actually-char.stderr @@ -0,0 +1,46 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/label-is-actually-char.rs:2:15 + | +LL | let c = 'a; + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | let c = 'a'; + | + + +error: unexpected token: `'b` + --> $DIR/label-is-actually-char.rs:6:15 + | +LL | 'a'..='b => {} + | ^^ + | +help: add `'` to close the char literal + | +LL | 'a'..='b' => {} + | + + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/label-is-actually-char.rs:11:16 + | +LL | let x = ['a, 'b]; + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | let x = ['a', 'b]; + | + + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/label-is-actually-char.rs:11:20 + | +LL | let x = ['a, 'b]; + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | let x = ['a, 'b']; + | + + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/labeled-no-colon-expr.rs b/tests/ui/parser/labeled-no-colon-expr.rs new file mode 100644 index 000000000..d9ebd7473 --- /dev/null +++ b/tests/ui/parser/labeled-no-colon-expr.rs @@ -0,0 +1,15 @@ +fn main() { + 'l0 while false {} //~ ERROR labeled expression must be followed by `:` + 'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:` + 'l2 loop {} //~ ERROR labeled expression must be followed by `:` + 'l3 {} //~ ERROR labeled expression must be followed by `:` + 'l4 0; //~ ERROR labeled expression must be followed by `:` + //~^ ERROR expected `while`, `for`, `loop` or `{` + + macro_rules! m { + ($b:block) => { + 'l5 $b; //~ ERROR cannot use a `block` macro fragment here + } + } + m!({}); //~ ERROR labeled expression must be followed by `:` +} diff --git a/tests/ui/parser/labeled-no-colon-expr.stderr b/tests/ui/parser/labeled-no-colon-expr.stderr new file mode 100644 index 000000000..62288fe15 --- /dev/null +++ b/tests/ui/parser/labeled-no-colon-expr.stderr @@ -0,0 +1,95 @@ +error: labeled expression must be followed by `:` + --> $DIR/labeled-no-colon-expr.rs:2:5 + | +LL | 'l0 while false {} + | ----^^^^^^^^^^^^^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/labeled-no-colon-expr.rs:3:5 + | +LL | 'l1 for _ in 0..1 {} + | ----^^^^^^^^^^^^^^^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/labeled-no-colon-expr.rs:4:5 + | +LL | 'l2 loop {} + | ----^^^^^^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: labeled expression must be followed by `:` + --> $DIR/labeled-no-colon-expr.rs:5:5 + | +LL | 'l3 {} + | ----^^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/labeled-no-colon-expr.rs:6:9 + | +LL | 'l4 0; + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider removing the label + | +LL - 'l4 0; +LL + 0; + | + +error: labeled expression must be followed by `:` + --> $DIR/labeled-no-colon-expr.rs:6:9 + | +LL | 'l4 0; + | ----^ + | | | + | | help: add `:` after the label + | the label + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: cannot use a `block` macro fragment here + --> $DIR/labeled-no-colon-expr.rs:11:17 + | +LL | 'l5 $b; + | ----^^ + | | + | the `block` fragment is within this context +... +LL | m!({}); + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: labeled expression must be followed by `:` + --> $DIR/labeled-no-colon-expr.rs:14:8 + | +LL | 'l5 $b; + | ---- help: add `:` after the label + | | + | the label +... +LL | m!({}); + | ^^ + | + = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them + +error: aborting due to 8 previous errors + diff --git a/tests/ui/parser/let-binop.fixed b/tests/ui/parser/let-binop.fixed new file mode 100644 index 000000000..93f7f97b0 --- /dev/null +++ b/tests/ui/parser/let-binop.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let a: i8 = 1; //~ ERROR can't reassign to an uninitialized variable + let _ = a; + let b = 1; //~ ERROR can't reassign to an uninitialized variable + let _ = b; + let c = 1; //~ ERROR can't reassign to an uninitialized variable + let _ = c; +} diff --git a/tests/ui/parser/let-binop.rs b/tests/ui/parser/let-binop.rs new file mode 100644 index 000000000..2adbceae5 --- /dev/null +++ b/tests/ui/parser/let-binop.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let a: i8 *= 1; //~ ERROR can't reassign to an uninitialized variable + let _ = a; + let b += 1; //~ ERROR can't reassign to an uninitialized variable + let _ = b; + let c *= 1; //~ ERROR can't reassign to an uninitialized variable + let _ = c; +} diff --git a/tests/ui/parser/let-binop.stderr b/tests/ui/parser/let-binop.stderr new file mode 100644 index 000000000..dd33e9157 --- /dev/null +++ b/tests/ui/parser/let-binop.stderr @@ -0,0 +1,26 @@ +error: can't reassign to an uninitialized variable + --> $DIR/let-binop.rs:4:15 + | +LL | let a: i8 *= 1; + | ^^ help: initialize the variable + | + = help: if you meant to overwrite, remove the `let` binding + +error: can't reassign to an uninitialized variable + --> $DIR/let-binop.rs:6:11 + | +LL | let b += 1; + | ^^ help: initialize the variable + | + = help: if you meant to overwrite, remove the `let` binding + +error: can't reassign to an uninitialized variable + --> $DIR/let-binop.rs:8:11 + | +LL | let c *= 1; + | ^^ help: initialize the variable + | + = help: if you meant to overwrite, remove the `let` binding + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/lifetime-in-pattern-recover.rs b/tests/ui/parser/lifetime-in-pattern-recover.rs new file mode 100644 index 000000000..7fb14b800 --- /dev/null +++ b/tests/ui/parser/lifetime-in-pattern-recover.rs @@ -0,0 +1,6 @@ +fn main() { + let &'a x = &0; //~ ERROR unexpected lifetime `'a` in pattern + let &'a mut y = &mut 0; //~ ERROR unexpected lifetime `'a` in pattern + + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/lifetime-in-pattern-recover.stderr b/tests/ui/parser/lifetime-in-pattern-recover.stderr new file mode 100644 index 000000000..4bf7f57bf --- /dev/null +++ b/tests/ui/parser/lifetime-in-pattern-recover.stderr @@ -0,0 +1,23 @@ +error: unexpected lifetime `'a` in pattern + --> $DIR/lifetime-in-pattern-recover.rs:2:10 + | +LL | let &'a x = &0; + | ^^ help: remove the lifetime + +error: unexpected lifetime `'a` in pattern + --> $DIR/lifetime-in-pattern-recover.rs:3:10 + | +LL | let &'a mut y = &mut 0; + | ^^ help: remove the lifetime + +error[E0308]: mismatched types + --> $DIR/lifetime-in-pattern-recover.rs:5:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/lifetime-in-pattern.rs b/tests/ui/parser/lifetime-in-pattern.rs new file mode 100644 index 000000000..d3c638d0c --- /dev/null +++ b/tests/ui/parser/lifetime-in-pattern.rs @@ -0,0 +1,7 @@ +fn test(&'a str) { + //~^ ERROR unexpected lifetime `'a` in pattern + //~| ERROR expected one of `:`, `@`, or `|`, found `)` +} + +fn main() { +} diff --git a/tests/ui/parser/lifetime-in-pattern.stderr b/tests/ui/parser/lifetime-in-pattern.stderr new file mode 100644 index 000000000..a1d721e74 --- /dev/null +++ b/tests/ui/parser/lifetime-in-pattern.stderr @@ -0,0 +1,28 @@ +error: unexpected lifetime `'a` in pattern + --> $DIR/lifetime-in-pattern.rs:1:10 + | +LL | fn test(&'a str) { + | ^^ help: remove the lifetime + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/lifetime-in-pattern.rs:1:16 + | +LL | fn test(&'a str) { + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn test(self: &'a str) { + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn test(str: &TypeName) { + | ~~~~~~~~~~~~~~ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn test(_: &'a str) { + | ++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/lifetime-semicolon.fixed b/tests/ui/parser/lifetime-semicolon.fixed new file mode 100644 index 000000000..482b77046 --- /dev/null +++ b/tests/ui/parser/lifetime-semicolon.fixed @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused)] +struct Foo<'a, 'b> { + a: &'a &'b i32 +} + +fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {} +//~^ ERROR expected one of `,` or `>`, found `;` + +fn main() {} diff --git a/tests/ui/parser/lifetime-semicolon.rs b/tests/ui/parser/lifetime-semicolon.rs new file mode 100644 index 000000000..21c8b0a7f --- /dev/null +++ b/tests/ui/parser/lifetime-semicolon.rs @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused)] +struct Foo<'a, 'b> { + a: &'a &'b i32 +} + +fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {} +//~^ ERROR expected one of `,` or `>`, found `;` + +fn main() {} diff --git a/tests/ui/parser/lifetime-semicolon.stderr b/tests/ui/parser/lifetime-semicolon.stderr new file mode 100644 index 000000000..ee486c236 --- /dev/null +++ b/tests/ui/parser/lifetime-semicolon.stderr @@ -0,0 +1,13 @@ +error: expected one of `,` or `>`, found `;` + --> $DIR/lifetime-semicolon.rs:7:31 + | +LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {} + | ^ expected one of `,` or `>` + | +help: use a comma to separate type parameters + | +LL | fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {} + | ~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/lifetime_starts_expressions.rs b/tests/ui/parser/lifetime_starts_expressions.rs new file mode 100644 index 000000000..903b4de6e --- /dev/null +++ b/tests/ui/parser/lifetime_starts_expressions.rs @@ -0,0 +1,39 @@ +#![allow(unused, dead_code)] + +fn foo() -> u32 { + return 'label: loop { break 'label 42; }; +} + +fn bar() -> u32 { + loop { break 'label: loop { break 'label 42; }; } + //~^ ERROR: parentheses are required around this expression to avoid confusion + //~| HELP: wrap the expression in parentheses +} + +fn baz() -> u32 { + 'label: loop { + break 'label + //~^ WARNING: this labeled break expression is easy to confuse with an unlabeled break + loop { break 42; }; + //~^ HELP: wrap this expression in parentheses + }; + + 'label2: loop { + break 'label2 'inner: loop { break 42; }; + // no warnings or errors here + } +} + +pub fn main() { + // Regression test for issue #86948, as resolved in #87026: + let a = 'first_loop: loop { + break 'first_loop 1; + }; + let b = loop { + break 'inner_loop: loop { + //~^ ERROR: parentheses are required around this expression to avoid confusion + //~| HELP: wrap the expression in parentheses + break 'inner_loop 1; + }; + }; +} diff --git a/tests/ui/parser/lifetime_starts_expressions.stderr b/tests/ui/parser/lifetime_starts_expressions.stderr new file mode 100644 index 000000000..82e274325 --- /dev/null +++ b/tests/ui/parser/lifetime_starts_expressions.stderr @@ -0,0 +1,47 @@ +error: parentheses are required around this expression to avoid confusion with a labeled break expression + --> $DIR/lifetime_starts_expressions.rs:8:18 + | +LL | loop { break 'label: loop { break 'label 42; }; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: wrap the expression in parentheses + | +LL | loop { break ('label: loop { break 'label 42; }); } + | + + + +error: parentheses are required around this expression to avoid confusion with a labeled break expression + --> $DIR/lifetime_starts_expressions.rs:33:15 + | +LL | break 'inner_loop: loop { + | _______________^ +LL | | +LL | | +LL | | break 'inner_loop 1; +LL | | }; + | |_________^ + | +help: wrap the expression in parentheses + | +LL ~ break ('inner_loop: loop { +LL | +LL | +LL | break 'inner_loop 1; +LL ~ }); + | + +warning: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression + --> $DIR/lifetime_starts_expressions.rs:15:9 + | +LL | / break 'label +LL | | +LL | | loop { break 42; }; + | |______________________________^ + | + = note: `#[warn(break_with_label_and_loop)]` on by default +help: wrap this expression in parentheses + | +LL | (loop { break 42; }); + | + + + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/parser/macro-bad-delimiter-ident.rs b/tests/ui/parser/macro-bad-delimiter-ident.rs new file mode 100644 index 000000000..f461f06b4 --- /dev/null +++ b/tests/ui/parser/macro-bad-delimiter-ident.rs @@ -0,0 +1,3 @@ +fn main() { + foo! bar < //~ ERROR expected one of `(`, `[`, or `{`, found `bar` +} diff --git a/tests/ui/parser/macro-bad-delimiter-ident.stderr b/tests/ui/parser/macro-bad-delimiter-ident.stderr new file mode 100644 index 000000000..f2365fed2 --- /dev/null +++ b/tests/ui/parser/macro-bad-delimiter-ident.stderr @@ -0,0 +1,8 @@ +error: expected one of `(`, `[`, or `{`, found `bar` + --> $DIR/macro-bad-delimiter-ident.rs:2:10 + | +LL | foo! bar < + | ^^^ expected one of `(`, `[`, or `{` + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro-braces-dot-question.rs b/tests/ui/parser/macro-braces-dot-question.rs new file mode 100644 index 000000000..016b434a6 --- /dev/null +++ b/tests/ui/parser/macro-braces-dot-question.rs @@ -0,0 +1,11 @@ +// check-pass + +use std::io::Write; + +fn main() -> Result<(), std::io::Error> { + vec! { 1, 2, 3 }.len(); + write! { vec![], "" }?; + println!{""} + [0]; // separate statement, not indexing into the result of println. + Ok(()) +} diff --git a/tests/ui/parser/macro-keyword.rs b/tests/ui/parser/macro-keyword.rs new file mode 100644 index 000000000..58489fb2c --- /dev/null +++ b/tests/ui/parser/macro-keyword.rs @@ -0,0 +1,5 @@ +fn macro() { //~ ERROR expected identifier, found reserved keyword `macro` +} + +pub fn main() { +} diff --git a/tests/ui/parser/macro-keyword.stderr b/tests/ui/parser/macro-keyword.stderr new file mode 100644 index 000000000..d794671f8 --- /dev/null +++ b/tests/ui/parser/macro-keyword.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `macro` + --> $DIR/macro-keyword.rs:1:4 + | +LL | fn macro() { + | ^^^^^ expected identifier, found reserved keyword + | +help: escape `macro` to use it as an identifier + | +LL | fn r#macro() { + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro-mismatched-delim-brace-paren.rs b/tests/ui/parser/macro-mismatched-delim-brace-paren.rs new file mode 100644 index 000000000..404aa7b80 --- /dev/null +++ b/tests/ui/parser/macro-mismatched-delim-brace-paren.rs @@ -0,0 +1,7 @@ +macro_rules! foo { ($($tt:tt)*) => () } + +fn main() { + foo! { + bar, "baz", 1, 2.0 + ) //~ ERROR mismatched closing delimiter +} diff --git a/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr b/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr new file mode 100644 index 000000000..077d31800 --- /dev/null +++ b/tests/ui/parser/macro-mismatched-delim-brace-paren.stderr @@ -0,0 +1,11 @@ +error: mismatched closing delimiter: `)` + --> $DIR/macro-mismatched-delim-brace-paren.rs:4:10 + | +LL | foo! { + | ^ unclosed delimiter +LL | bar, "baz", 1, 2.0 +LL | ) + | ^ mismatched closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro-mismatched-delim-paren-brace.rs b/tests/ui/parser/macro-mismatched-delim-paren-brace.rs new file mode 100644 index 000000000..1a1b9edfb --- /dev/null +++ b/tests/ui/parser/macro-mismatched-delim-paren-brace.rs @@ -0,0 +1,5 @@ +fn main() { + foo! ( + bar, "baz", 1, 2.0 + } //~ ERROR mismatched closing delimiter +} //~ ERROR unexpected closing delimiter: `}` diff --git a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr new file mode 100644 index 000000000..967a3e6fd --- /dev/null +++ b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr @@ -0,0 +1,22 @@ +error: unexpected closing delimiter: `}` + --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1 + | +LL | fn main() { + | - this opening brace... +... +LL | } + | - ...matches this closing brace +LL | } + | ^ unexpected closing delimiter + +error: mismatched closing delimiter: `}` + --> $DIR/macro-mismatched-delim-paren-brace.rs:2:10 + | +LL | foo! ( + | ^ unclosed delimiter +LL | bar, "baz", 1, 2.0 +LL | } + | ^ mismatched closing delimiter + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/macro/bad-macro-argument.rs b/tests/ui/parser/macro/bad-macro-argument.rs new file mode 100644 index 000000000..4b6d23890 --- /dev/null +++ b/tests/ui/parser/macro/bad-macro-argument.rs @@ -0,0 +1,4 @@ +fn main() { + let message = "world"; + println!("Hello, {}", message/); //~ ERROR expected expression +} diff --git a/tests/ui/parser/macro/bad-macro-argument.stderr b/tests/ui/parser/macro/bad-macro-argument.stderr new file mode 100644 index 000000000..3cd8accb6 --- /dev/null +++ b/tests/ui/parser/macro/bad-macro-argument.stderr @@ -0,0 +1,8 @@ +error: expected expression, found end of macro arguments + --> $DIR/bad-macro-argument.rs:3:35 + | +LL | println!("Hello, {}", message/); + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro/issue-33569.rs b/tests/ui/parser/macro/issue-33569.rs new file mode 100644 index 000000000..069d181e9 --- /dev/null +++ b/tests/ui/parser/macro/issue-33569.rs @@ -0,0 +1,12 @@ +macro_rules! foo { + { $+ } => { //~ ERROR expected identifier, found `+` + //~^ ERROR missing fragment specifier + //~| ERROR missing fragment specifier + //~| WARN this was previously accepted + $(x)(y) //~ ERROR expected one of: `*`, `+`, or `?` + } +} + +foo!(); + +fn main() {} diff --git a/tests/ui/parser/macro/issue-33569.stderr b/tests/ui/parser/macro/issue-33569.stderr new file mode 100644 index 000000000..0dca090fb --- /dev/null +++ b/tests/ui/parser/macro/issue-33569.stderr @@ -0,0 +1,30 @@ +error: expected identifier, found `+` + --> $DIR/issue-33569.rs:2:8 + | +LL | { $+ } => { + | ^ + +error: expected one of: `*`, `+`, or `?` + --> $DIR/issue-33569.rs:6:13 + | +LL | $(x)(y) + | ^^^ + +error: missing fragment specifier + --> $DIR/issue-33569.rs:2:8 + | +LL | { $+ } => { + | ^ + +error: missing fragment specifier + --> $DIR/issue-33569.rs:2:8 + | +LL | { $+ } => { + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + = note: `#[deny(missing_fragment_specifier)]` on by default + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/macro/issue-37113.rs b/tests/ui/parser/macro/issue-37113.rs new file mode 100644 index 000000000..0044aa561 --- /dev/null +++ b/tests/ui/parser/macro/issue-37113.rs @@ -0,0 +1,11 @@ +macro_rules! test_macro { + ( $( $t:ty ),* $(),*) => { + enum SomeEnum { + $( $t, )* //~ ERROR expected identifier, found `String` + }; + }; +} + +fn main() { + test_macro!(String,); +} diff --git a/tests/ui/parser/macro/issue-37113.stderr b/tests/ui/parser/macro/issue-37113.stderr new file mode 100644 index 000000000..da9e743a0 --- /dev/null +++ b/tests/ui/parser/macro/issue-37113.stderr @@ -0,0 +1,16 @@ +error: expected identifier, found `String` + --> $DIR/issue-37113.rs:4:16 + | +LL | enum SomeEnum { + | -------- while parsing this enum +LL | $( $t, )* + | ^^ expected identifier +... +LL | test_macro!(String,); + | -------------------- in this macro invocation + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + = note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro/issue-37234.rs b/tests/ui/parser/macro/issue-37234.rs new file mode 100644 index 000000000..4debc7479 --- /dev/null +++ b/tests/ui/parser/macro/issue-37234.rs @@ -0,0 +1,9 @@ +macro_rules! failed { + () => {{ + let x = 5 ""; //~ ERROR found `""` + }} +} + +fn main() { + failed!(); +} diff --git a/tests/ui/parser/macro/issue-37234.stderr b/tests/ui/parser/macro/issue-37234.stderr new file mode 100644 index 000000000..d79196204 --- /dev/null +++ b/tests/ui/parser/macro/issue-37234.stderr @@ -0,0 +1,13 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `""` + --> $DIR/issue-37234.rs:3:19 + | +LL | let x = 5 ""; + | ^^ expected one of `.`, `;`, `?`, `else`, or an operator +... +LL | failed!(); + | --------- in this macro invocation + | + = note: this error originates in the macro `failed` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro/literals-are-validated-before-expansion.rs b/tests/ui/parser/macro/literals-are-validated-before-expansion.rs new file mode 100644 index 000000000..c3fc754b5 --- /dev/null +++ b/tests/ui/parser/macro/literals-are-validated-before-expansion.rs @@ -0,0 +1,10 @@ +macro_rules! black_hole { + ($($tt:tt)*) => {} +} + +fn main() { + black_hole! { '\u{FFFFFF}' } + //~^ ERROR: invalid unicode character escape + black_hole! { "this is surrogate: \u{DAAA}" } + //~^ ERROR: invalid unicode character escape +} diff --git a/tests/ui/parser/macro/literals-are-validated-before-expansion.stderr b/tests/ui/parser/macro/literals-are-validated-before-expansion.stderr new file mode 100644 index 000000000..e874f6249 --- /dev/null +++ b/tests/ui/parser/macro/literals-are-validated-before-expansion.stderr @@ -0,0 +1,18 @@ +error: invalid unicode character escape + --> $DIR/literals-are-validated-before-expansion.rs:6:20 + | +LL | black_hole! { '\u{FFFFFF}' } + | ^^^^^^^^^^ invalid escape + | + = help: unicode escape must be at most 10FFFF + +error: invalid unicode character escape + --> $DIR/literals-are-validated-before-expansion.rs:8:39 + | +LL | black_hole! { "this is surrogate: \u{DAAA}" } + | ^^^^^^^^ invalid escape + | + = help: unicode escape must not be a surrogate + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/macro/macro-doc-comments-1.rs b/tests/ui/parser/macro/macro-doc-comments-1.rs new file mode 100644 index 000000000..8d8103bb1 --- /dev/null +++ b/tests/ui/parser/macro/macro-doc-comments-1.rs @@ -0,0 +1,9 @@ +macro_rules! outer { + (#[$outer:meta]) => () +} + +outer! { + //! Inner +} //~^ ERROR no rules expected the token `!` + +fn main() { } diff --git a/tests/ui/parser/macro/macro-doc-comments-1.stderr b/tests/ui/parser/macro/macro-doc-comments-1.stderr new file mode 100644 index 000000000..eaeb62d2c --- /dev/null +++ b/tests/ui/parser/macro/macro-doc-comments-1.stderr @@ -0,0 +1,20 @@ +error: no rules expected the token `!` + --> $DIR/macro-doc-comments-1.rs:6:5 + | +LL | macro_rules! outer { + | ------------------ when calling this macro +... +LL | //! Inner + | ^^^^^^^^^ + | | + | no rules expected this token in macro call + | inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match + | +note: while trying to match `[` + --> $DIR/macro-doc-comments-1.rs:2:7 + | +LL | (#[$outer:meta]) => () + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro/macro-doc-comments-2.rs b/tests/ui/parser/macro/macro-doc-comments-2.rs new file mode 100644 index 000000000..8f33720ae --- /dev/null +++ b/tests/ui/parser/macro/macro-doc-comments-2.rs @@ -0,0 +1,9 @@ +macro_rules! inner { + (#![$inner:meta]) => () +} + +inner! { + /// Outer +} //~^ ERROR no rules expected the token `[` + +fn main() { } diff --git a/tests/ui/parser/macro/macro-doc-comments-2.stderr b/tests/ui/parser/macro/macro-doc-comments-2.stderr new file mode 100644 index 000000000..1dcd95f6f --- /dev/null +++ b/tests/ui/parser/macro/macro-doc-comments-2.stderr @@ -0,0 +1,20 @@ +error: no rules expected the token `[` + --> $DIR/macro-doc-comments-2.rs:6:5 + | +LL | macro_rules! inner { + | ------------------ when calling this macro +... +LL | /// Outer + | ^^^^^^^^^ + | | + | no rules expected this token in macro call + | outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match + | +note: while trying to match `!` + --> $DIR/macro-doc-comments-2.rs:2:7 + | +LL | (#![$inner:meta]) => () + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/macro/macro-incomplete-parse.rs b/tests/ui/parser/macro/macro-incomplete-parse.rs new file mode 100644 index 000000000..544e4aa7b --- /dev/null +++ b/tests/ui/parser/macro/macro-incomplete-parse.rs @@ -0,0 +1,27 @@ +macro_rules! ignored_item { + () => { + fn foo() {} + fn bar() {} + , //~ ERROR macro expansion ignores token `,` + } +} + +macro_rules! ignored_expr { + () => ( 1, //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + + 2 ) +} + +macro_rules! ignored_pat { + () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,` +} + +ignored_item!(); + +fn main() { + ignored_expr!(); + match 1 { + ignored_pat!() => (), + _ => (), + } +} diff --git a/tests/ui/parser/macro/macro-incomplete-parse.stderr b/tests/ui/parser/macro/macro-incomplete-parse.stderr new file mode 100644 index 000000000..707417b72 --- /dev/null +++ b/tests/ui/parser/macro/macro-incomplete-parse.stderr @@ -0,0 +1,35 @@ +error: macro expansion ignores token `,` and any following + --> $DIR/macro-incomplete-parse.rs:5:9 + | +LL | , + | ^ +... +LL | ignored_item!(); + | --------------- caused by the macro expansion here + | + = note: the usage of `ignored_item!` is likely invalid in item context + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/macro-incomplete-parse.rs:10:14 + | +LL | () => ( 1, + | ^ expected one of `.`, `;`, `?`, `}`, or an operator +... +LL | ignored_expr!(); + | --------------- in this macro invocation + | + = note: this error originates in the macro `ignored_expr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macro expansion ignores token `,` and any following + --> $DIR/macro-incomplete-parse.rs:16:14 + | +LL | () => ( 1, 2 ) + | ^ +... +LL | ignored_pat!() => (), + | -------------- caused by the macro expansion here + | + = note: the usage of `ignored_pat!` is likely invalid in pattern context + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/macro/macro-repeat.rs b/tests/ui/parser/macro/macro-repeat.rs new file mode 100644 index 000000000..3ffbea217 --- /dev/null +++ b/tests/ui/parser/macro/macro-repeat.rs @@ -0,0 +1,12 @@ +macro_rules! mac { + ( $($v:tt)* ) => { + $v + //~^ ERROR still repeating at this depth + //~| ERROR still repeating at this depth + }; +} + +fn main() { + mac!(0); + mac!(1); +} diff --git a/tests/ui/parser/macro/macro-repeat.stderr b/tests/ui/parser/macro/macro-repeat.stderr new file mode 100644 index 000000000..63554b197 --- /dev/null +++ b/tests/ui/parser/macro/macro-repeat.stderr @@ -0,0 +1,14 @@ +error: variable 'v' is still repeating at this depth + --> $DIR/macro-repeat.rs:3:9 + | +LL | $v + | ^^ + +error: variable 'v' is still repeating at this depth + --> $DIR/macro-repeat.rs:3:9 + | +LL | $v + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/macro/pub-item-macro.rs b/tests/ui/parser/macro/pub-item-macro.rs new file mode 100644 index 000000000..f5f8a01e6 --- /dev/null +++ b/tests/ui/parser/macro/pub-item-macro.rs @@ -0,0 +1,21 @@ +// Issue #14660 + +macro_rules! priv_x { + () => { + static x: u32 = 0; + }; +} + +macro_rules! pub_x { () => { + pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub` + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation +}} + +mod foo { + pub_x!(); +} + +fn main() { + let y: u32 = foo::x; //~ ERROR static `x` is private +} diff --git a/tests/ui/parser/macro/pub-item-macro.stderr b/tests/ui/parser/macro/pub-item-macro.stderr new file mode 100644 index 000000000..9a2fffcce --- /dev/null +++ b/tests/ui/parser/macro/pub-item-macro.stderr @@ -0,0 +1,31 @@ +error: can't qualify macro invocation with `pub` + --> $DIR/pub-item-macro.rs:10:5 + | +LL | pub priv_x!(); + | ^^^ help: remove the visibility +... +LL | pub_x!(); + | -------- in this macro invocation + | + = help: try adjusting the macro to put `pub` inside the invocation + = note: this error originates in the macro `pub_x` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0603]: static `x` is private + --> $DIR/pub-item-macro.rs:20:23 + | +LL | let y: u32 = foo::x; + | ^ private static + | +note: the static `x` is defined here + --> $DIR/pub-item-macro.rs:5:9 + | +LL | static x: u32 = 0; + | ^^^^^^^^^^^^^^^^^^ +... +LL | pub_x!(); + | -------- in this macro invocation + = note: this error originates in the macro `priv_x` which comes from the expansion of the macro `pub_x` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/parser/macro/trait-non-item-macros.rs b/tests/ui/parser/macro/trait-non-item-macros.rs new file mode 100644 index 000000000..97fb564bf --- /dev/null +++ b/tests/ui/parser/macro/trait-non-item-macros.rs @@ -0,0 +1,13 @@ +macro_rules! bah { + ($a:expr) => { + $a + }; //~^ ERROR macro expansion ignores token `2` and any following +} + +trait Bar { + bah!(2); +} + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/macro/trait-non-item-macros.stderr b/tests/ui/parser/macro/trait-non-item-macros.stderr new file mode 100644 index 000000000..db20e6b24 --- /dev/null +++ b/tests/ui/parser/macro/trait-non-item-macros.stderr @@ -0,0 +1,22 @@ +error: macro expansion ignores token `2` and any following + --> $DIR/trait-non-item-macros.rs:3:9 + | +LL | $a + | ^^ +... +LL | bah!(2); + | ------- caused by the macro expansion here + | + = note: the usage of `bah!` is likely invalid in trait item context + +error[E0308]: mismatched types + --> $DIR/trait-non-item-macros.rs:12:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.rs b/tests/ui/parser/macro/trait-object-macro-matcher.rs new file mode 100644 index 000000000..560195977 --- /dev/null +++ b/tests/ui/parser/macro/trait-object-macro-matcher.rs @@ -0,0 +1,14 @@ +// A single lifetime is not parsed as a type. +// `ty` matcher in particular doesn't accept a single lifetime + +macro_rules! m { + ($t: ty) => { + let _: $t; + }; +} + +fn main() { + m!('static); + //~^ ERROR lifetime in trait object type must be followed by `+` + //~| ERROR at least one trait is required for an object type +} diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.stderr new file mode 100644 index 000000000..40082564b --- /dev/null +++ b/tests/ui/parser/macro/trait-object-macro-matcher.stderr @@ -0,0 +1,15 @@ +error: lifetime in trait object type must be followed by `+` + --> $DIR/trait-object-macro-matcher.rs:11:8 + | +LL | m!('static); + | ^^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/trait-object-macro-matcher.rs:11:8 + | +LL | m!('static); + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/parser/macros-no-semicolon-items.rs b/tests/ui/parser/macros-no-semicolon-items.rs new file mode 100644 index 000000000..3afc275d6 --- /dev/null +++ b/tests/ui/parser/macros-no-semicolon-items.rs @@ -0,0 +1,15 @@ +macro_rules! foo() //~ ERROR semicolon + //~| ERROR unexpected end of macro + +macro_rules! bar { + ($($tokens:tt)*) => {} +} + +bar!( //~ ERROR semicolon + blah + blah + blah +) + +fn main() { +} diff --git a/tests/ui/parser/macros-no-semicolon-items.stderr b/tests/ui/parser/macros-no-semicolon-items.stderr new file mode 100644 index 000000000..6d2431c4a --- /dev/null +++ b/tests/ui/parser/macros-no-semicolon-items.stderr @@ -0,0 +1,47 @@ +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/macros-no-semicolon-items.rs:1:17 + | +LL | macro_rules! foo() + | ^^ + | +help: change the delimiters to curly braces + | +LL | macro_rules! foo{} + | ~~ +help: add a semicolon + | +LL | macro_rules! foo(); + | + + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/macros-no-semicolon-items.rs:8:5 + | +LL | bar!( + | _____^ +LL | | blah +LL | | blah +LL | | blah +LL | | ) + | |_^ + | +help: change the delimiters to curly braces + | +LL ~ bar!{ +LL | blah +LL | blah +LL | blah +LL + } + | +help: add a semicolon + | +LL | ); + | + + +error: unexpected end of macro invocation + --> $DIR/macros-no-semicolon-items.rs:1:1 + | +LL | macro_rules! foo() + | ^^^^^^^^^^^^^^^^^^ missing tokens in macro arguments + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/macros-no-semicolon.rs b/tests/ui/parser/macros-no-semicolon.rs new file mode 100644 index 000000000..24d1ae9e6 --- /dev/null +++ b/tests/ui/parser/macros-no-semicolon.rs @@ -0,0 +1,5 @@ +fn main() { + assert_eq!(1, 2) //~ ERROR: expected `;` + assert_eq!(3, 4) //~ ERROR: expected `;` + println!("hello"); +} diff --git a/tests/ui/parser/macros-no-semicolon.stderr b/tests/ui/parser/macros-no-semicolon.stderr new file mode 100644 index 000000000..f310662db --- /dev/null +++ b/tests/ui/parser/macros-no-semicolon.stderr @@ -0,0 +1,18 @@ +error: expected `;`, found `assert_eq` + --> $DIR/macros-no-semicolon.rs:2:21 + | +LL | assert_eq!(1, 2) + | ^ help: add `;` here +LL | assert_eq!(3, 4) + | --------- unexpected token + +error: expected `;`, found `println` + --> $DIR/macros-no-semicolon.rs:3:21 + | +LL | assert_eq!(3, 4) + | ^ help: add `;` here +LL | println!("hello"); + | ------- unexpected token + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/match-arm-without-braces.rs b/tests/ui/parser/match-arm-without-braces.rs new file mode 100644 index 000000000..bba38fd0f --- /dev/null +++ b/tests/ui/parser/match-arm-without-braces.rs @@ -0,0 +1,87 @@ +struct S; + +impl S { + fn get(_: K) -> Option { + Default::default() + } +} + +enum Val { + Foo, + Bar, +} + +impl Default for Val { + fn default() -> Self { + Val::Foo + } +} + +fn main() { + match S::get(1) { + Some(Val::Foo) => {} + _ => {} + } + match S::get(2) { + Some(Val::Foo) => 3; //~ ERROR `match` arm body without braces + _ => 4, + } + match S::get(5) { + Some(Val::Foo) => + 7; //~ ERROR `match` arm body without braces + 8; + _ => 9, + } + match S::get(10) { + Some(Val::Foo) => + 11; //~ ERROR `match` arm body without braces + 12; + _ => (), + } + match S::get(13) { + None => {} + Some(Val::Foo) => + 14; //~ ERROR `match` arm body without braces + 15; + } + match S::get(16) { + Some(Val::Foo) => 17 //~ ERROR expected `,` following `match` arm + _ => 18, + }; + match S::get(19) { + Some(Val::Foo) => + 20; //~ ERROR `match` arm body without braces + 21 + _ => 22, + } + match S::get(23) { + Some(Val::Foo) => + 24; //~ ERROR `match` arm body without braces + 25 + _ => (), + } + match S::get(26) { + None => {} + Some(Val::Foo) => + 27; //~ ERROR `match` arm body without braces + 28 + } + match S::get(29) { + Some(Val::Foo) => + 30; //~ ERROR expected one of + 31, + _ => 32, + } + match S::get(33) { + Some(Val::Foo) => + 34; //~ ERROR expected one of + 35, + _ => (), + } + match S::get(36) { + None => {} + Some(Val::Foo) => + 37; //~ ERROR expected one of + 38, + } +} diff --git a/tests/ui/parser/match-arm-without-braces.stderr b/tests/ui/parser/match-arm-without-braces.stderr new file mode 100644 index 000000000..37d55aa53 --- /dev/null +++ b/tests/ui/parser/match-arm-without-braces.stderr @@ -0,0 +1,131 @@ +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:26:27 + | +LL | Some(Val::Foo) => 3; + | -- ^- help: use a comma to end a `match` arm expression: `,` + | | | + | | this statement is not surrounded by a body + | while parsing the `match` arm starting here + +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:31:11 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | / 7; +LL | | 8; + | |____________^ these statements are not surrounded by a body + | +help: surround the statements with a body + | +LL ~ { 7; +LL ~ 8; } + | + +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:37:11 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | / 11; +LL | | 12; + | |_____________^ these statements are not surrounded by a body + | +help: surround the statements with a body + | +LL ~ { 11; +LL ~ 12; } + | + +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:44:11 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | / 14; +LL | | 15; + | |_____________^ these statements are not surrounded by a body + | +help: surround the statements with a body + | +LL ~ { 14; +LL ~ 15; } + | + +error: expected `,` following `match` arm + --> $DIR/match-arm-without-braces.rs:48:29 + | +LL | Some(Val::Foo) => 17 + | ^ help: missing a comma here to end this `match` arm: `,` + +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:53:11 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | / 20; +LL | | 21 + | |____________^ these statements are not surrounded by a body + | +help: surround the statements with a body + | +LL ~ { 20; +LL ~ 21 } + | + +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:59:11 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | / 24; +LL | | 25 + | |____________^ these statements are not surrounded by a body + | +help: surround the statements with a body + | +LL ~ { 24; +LL ~ 25 } + | + +error: `match` arm body without braces + --> $DIR/match-arm-without-braces.rs:66:11 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | / 27; +LL | | 28 + | |____________^ these statements are not surrounded by a body + | +help: surround the statements with a body + | +LL ~ { 27; +LL ~ 28 } + | + +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;` + --> $DIR/match-arm-without-braces.rs:71:13 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | 30; + | ^ expected one of `,`, `.`, `?`, `}`, or an operator + +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;` + --> $DIR/match-arm-without-braces.rs:77:13 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | 34; + | ^ expected one of `,`, `.`, `?`, `}`, or an operator + +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `;` + --> $DIR/match-arm-without-braces.rs:84:13 + | +LL | Some(Val::Foo) => + | -- while parsing the `match` arm starting here +LL | 37; + | ^ expected one of `,`, `.`, `?`, `}`, or an operator + +error: aborting due to 11 previous errors + diff --git a/tests/ui/parser/match-arrows-block-then-binop.rs b/tests/ui/parser/match-arrows-block-then-binop.rs new file mode 100644 index 000000000..56c917c74 --- /dev/null +++ b/tests/ui/parser/match-arrows-block-then-binop.rs @@ -0,0 +1,7 @@ +fn main() { + let _ = match 0 { + 0 => { + 0 + } + 5 //~ ERROR expected pattern, found `+` + }; +} diff --git a/tests/ui/parser/match-arrows-block-then-binop.stderr b/tests/ui/parser/match-arrows-block-then-binop.stderr new file mode 100644 index 000000000..cb361a3db --- /dev/null +++ b/tests/ui/parser/match-arrows-block-then-binop.stderr @@ -0,0 +1,15 @@ +error: expected pattern, found `+` + --> $DIR/match-arrows-block-then-binop.rs:5:9 + | +LL | } + 5 + | ^ expected pattern + | +help: parentheses are required to parse this as an expression + | +LL ~ 0 => ({ +LL | 0 +LL ~ }) + 5 + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/match-refactor-to-expr.fixed b/tests/ui/parser/match-refactor-to-expr.fixed new file mode 100644 index 000000000..423147b27 --- /dev/null +++ b/tests/ui/parser/match-refactor-to-expr.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +fn main() { + let foo = + //~ NOTE while parsing this `match` expression + Some(4).unwrap_or(5) + //~^ NOTE expected one of `.`, `?`, `{`, or an operator + ; //~ NOTE unexpected token + //~^ ERROR expected one of `.`, `?`, `{`, or an operator, found `;` + + println!("{}", foo) +} diff --git a/tests/ui/parser/match-refactor-to-expr.rs b/tests/ui/parser/match-refactor-to-expr.rs new file mode 100644 index 000000000..fcba5d044 --- /dev/null +++ b/tests/ui/parser/match-refactor-to-expr.rs @@ -0,0 +1,12 @@ +// run-rustfix + +fn main() { + let foo = + match //~ NOTE while parsing this `match` expression + Some(4).unwrap_or(5) + //~^ NOTE expected one of `.`, `?`, `{`, or an operator + ; //~ NOTE unexpected token + //~^ ERROR expected one of `.`, `?`, `{`, or an operator, found `;` + + println!("{}", foo) +} diff --git a/tests/ui/parser/match-refactor-to-expr.stderr b/tests/ui/parser/match-refactor-to-expr.stderr new file mode 100644 index 000000000..851bef8f2 --- /dev/null +++ b/tests/ui/parser/match-refactor-to-expr.stderr @@ -0,0 +1,16 @@ +error: expected one of `.`, `?`, `{`, or an operator, found `;` + --> $DIR/match-refactor-to-expr.rs:8:9 + | +LL | match + | ----- + | | + | while parsing this `match` expression + | help: try removing this `match` +LL | Some(4).unwrap_or(5) + | - expected one of `.`, `?`, `{`, or an operator +LL | +LL | ; + | ^ unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs new file mode 100644 index 000000000..689176b3e --- /dev/null +++ b/tests/ui/parser/mbe_missing_right_paren.rs @@ -0,0 +1,3 @@ +// ignore-tidy-trailing-newlines +// error-pattern: aborting due to 3 previous errors +macro_rules! abc(ؼ \ No newline at end of file diff --git a/tests/ui/parser/mbe_missing_right_paren.stderr b/tests/ui/parser/mbe_missing_right_paren.stderr new file mode 100644 index 000000000..ccaf77d39 --- /dev/null +++ b/tests/ui/parser/mbe_missing_right_paren.stderr @@ -0,0 +1,31 @@ +error: this file contains an unclosed delimiter + --> $DIR/mbe_missing_right_paren.rs:3:19 + | +LL | macro_rules! abc(ؼ + | - ^ + | | + | unclosed delimiter + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/mbe_missing_right_paren.rs:3:17 + | +LL | macro_rules! abc(ؼ + | ^^ + | +help: change the delimiters to curly braces + | +LL | macro_rules! abc { /* items */ } + | ~~~~~~~~~~~~~~~ +help: add a semicolon + | +LL | macro_rules! abc(ؼ; + | + + +error: unexpected end of macro invocation + --> $DIR/mbe_missing_right_paren.rs:3:19 + | +LL | macro_rules! abc(ؼ + | ^ missing tokens in macro arguments + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs new file mode 100644 index 000000000..8be7c9ee8 --- /dev/null +++ b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.rs @@ -0,0 +1,13 @@ +pub struct Example { a: i32 } + +impl Example { + fn is_pos(&self) -> bool { self.a > 0 } +} + +fn one() -> i32 { 1 } + +fn main() { + if Example { a: one(), }.is_pos() { //~ ERROR invalid struct literal + println!("Positive!"); + } +} diff --git a/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr new file mode 100644 index 000000000..7fd7ffc94 --- /dev/null +++ b/tests/ui/parser/method-call-on-struct-literal-in-if-condition.stderr @@ -0,0 +1,13 @@ +error: invalid struct literal + --> $DIR/method-call-on-struct-literal-in-if-condition.rs:10:8 + | +LL | if Example { a: one(), }.is_pos() { + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: you might need to surround the struct literal in parentheses + | +LL | if (Example { a: one(), }).is_pos() { + | + + + +error: aborting due to previous error + diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs new file mode 100644 index 000000000..8f46970b1 --- /dev/null +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -0,0 +1,13 @@ +fn main() {} + +impl T for () { //~ ERROR cannot find trait `T` in this scope + +fn foo(&self) {} + +trait T { //~ ERROR trait is not supported in `trait`s or `impl`s + fn foo(&self); +} + +pub(crate) struct Bar(); //~ ERROR struct is not supported in `trait`s or `impl`s + +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr new file mode 100644 index 000000000..cc7cc0c55 --- /dev/null +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -0,0 +1,34 @@ +error: this file contains an unclosed delimiter + --> $DIR/missing-close-brace-in-impl-trait.rs:13:52 + | +LL | impl T for () { + | - unclosed delimiter +... +LL | + | ^ + +error: trait is not supported in `trait`s or `impl`s + --> $DIR/missing-close-brace-in-impl-trait.rs:7:1 + | +LL | trait T { + | ^^^^^^^ + | + = help: consider moving the trait out to a nearby module scope + +error: struct is not supported in `trait`s or `impl`s + --> $DIR/missing-close-brace-in-impl-trait.rs:11:1 + | +LL | pub(crate) struct Bar(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error[E0405]: cannot find trait `T` in this scope + --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 + | +LL | impl T for () { + | ^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs new file mode 100644 index 000000000..090a17b41 --- /dev/null +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs @@ -0,0 +1,13 @@ +pub(crate) struct Bar { + foo: T, + +trait T { //~ ERROR expected identifier, found keyword `trait` + fn foo(&self); +} + + +impl T for Bar { +fn foo(&self) {} +} + +fn main() {} //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr new file mode 100644 index 000000000..ad1e90e43 --- /dev/null +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr @@ -0,0 +1,20 @@ +error: this file contains an unclosed delimiter + --> $DIR/missing-close-brace-in-struct.rs:13:65 + | +LL | pub(crate) struct Bar { + | - unclosed delimiter +... +LL | fn main() {} + | ^ + +error: expected identifier, found keyword `trait` + --> $DIR/missing-close-brace-in-struct.rs:4:1 + | +LL | pub(crate) struct Bar { + | --- while parsing this struct +... +LL | trait T { + | ^^^^^ expected identifier, found keyword + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs new file mode 100644 index 000000000..b6932deb5 --- /dev/null +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -0,0 +1,12 @@ +trait T { + fn foo(&self); + +pub(crate) struct Bar(); +//~^ ERROR struct is not supported in `trait`s or `impl`s + +impl T for Bar { +//~^ ERROR implementation is not supported in `trait`s or `impl`s +fn foo(&self) {} +} + +fn main() {} //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr new file mode 100644 index 000000000..7c6254356 --- /dev/null +++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -0,0 +1,27 @@ +error: this file contains an unclosed delimiter + --> $DIR/missing-close-brace-in-trait.rs:12:65 + | +LL | trait T { + | - unclosed delimiter +... +LL | fn main() {} + | ^ + +error: struct is not supported in `trait`s or `impl`s + --> $DIR/missing-close-brace-in-trait.rs:4:1 + | +LL | pub(crate) struct Bar(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the struct out to a nearby module scope + +error: implementation is not supported in `trait`s or `impl`s + --> $DIR/missing-close-brace-in-trait.rs:7:1 + | +LL | impl T for Bar { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider moving the implementation out to a nearby module scope + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/mismatched-delim-brace-empty-block.rs b/tests/ui/parser/mismatched-delim-brace-empty-block.rs new file mode 100644 index 000000000..61d7a9af2 --- /dev/null +++ b/tests/ui/parser/mismatched-delim-brace-empty-block.rs @@ -0,0 +1,5 @@ +fn main() { + +} + let _ = (); +} //~ ERROR unexpected closing delimiter diff --git a/tests/ui/parser/mismatched-delim-brace-empty-block.stderr b/tests/ui/parser/mismatched-delim-brace-empty-block.stderr new file mode 100644 index 000000000..165eb8ae9 --- /dev/null +++ b/tests/ui/parser/mismatched-delim-brace-empty-block.stderr @@ -0,0 +1,14 @@ +error: unexpected closing delimiter: `}` + --> $DIR/mismatched-delim-brace-empty-block.rs:5:1 + | +LL | fn main() { + | - this opening brace... +LL | +LL | } + | - ...matches this closing brace +LL | let _ = (); +LL | } + | ^ unexpected closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs new file mode 100644 index 000000000..da95c1bfa --- /dev/null +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs @@ -0,0 +1,23 @@ +struct Foo { + _a : T1, + _b : T2, +} + +fn test1(arg : T) { + let v : Vec<(u32,_) = vec![]; + //~^ ERROR: expected one of + //~| ERROR: type annotations needed +} + +fn test2(arg1 : T1, arg2 : T2) { + let foo : Foo::(arg : &'a u32) { + let v : Vec<'a = vec![]; + //~^ ERROR: expected one of + //~| ERROR: type annotations needed for `Vec` +} + +fn main() {} diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr new file mode 100644 index 000000000..bad241634 --- /dev/null +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -0,0 +1,66 @@ +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:23 + | +LL | let v : Vec<(u32,_) = vec![]; + | - - ^ expected one of `,`, `:`, or `>` + | | | + | | maybe try to close unmatched angle bracket + | while parsing the type for `v` + | +help: you might have meant to end the type parameters here + | +LL | let v : Vec<(u32,_)> = vec![]; + | + + +error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `{` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:13:32 + | +LL | let foo : Foo::, T2 = Foo {_a : arg1, _b : arg2}; + | + + +error: expected one of `,`, `:`, or `>`, found `=` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18 + | +LL | let v : Vec<'a = vec![]; + | - -- ^ expected one of `,`, `:`, or `>` + | | | + | | maybe try to close unmatched angle bracket + | while parsing the type for `v` + | +help: you might have meant to end the type parameters here + | +LL | let v : Vec<'a> = vec![]; + | + + +error[E0282]: type annotations needed for `Vec` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:7 + | +LL | let v : Vec<(u32,_) = vec![]; + | ^ + | +help: consider giving `v` an explicit type, where the type for type parameter `T` is specified + | +LL | let v: Vec : Vec<(u32,_) = vec![]; + | ++++++++ + +error[E0282]: type annotations needed for `Vec` + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:7 + | +LL | let v : Vec<'a = vec![]; + | ^ + | +help: consider giving `v` an explicit type, where the type for type parameter `T` is specified + | +LL | let v: Vec : Vec<'a = vec![]; + | ++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs b/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs new file mode 100644 index 000000000..d69a56c51 --- /dev/null +++ b/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs @@ -0,0 +1,11 @@ +// run-rustifx +#![allow(unused)] +use std::sync::{Arc, Mutex}; + +pub struct Foo { + a: Mutex, + b: Arc, //~ HELP you might have meant to end the type parameters here + c: Arc>, +} //~ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr new file mode 100644 index 000000000..6d8b0c3fc --- /dev/null +++ b/tests/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr @@ -0,0 +1,18 @@ +error: expected one of `>`, a const expression, lifetime, or type, found `}` + --> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1 + | +LL | pub struct Foo { + | --- while parsing this struct +... +LL | c: Arc>, + | - expected one of `>`, a const expression, lifetime, or type +LL | } + | ^ unexpected token + | +help: you might have meant to end the type parameters here + | +LL | b: Arc>, + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/missing-semicolon.rs b/tests/ui/parser/missing-semicolon.rs new file mode 100644 index 000000000..f68d177c0 --- /dev/null +++ b/tests/ui/parser/missing-semicolon.rs @@ -0,0 +1,8 @@ +macro_rules! m { + ($($e1:expr),*; $($e2:expr),*) => { + $( let x = $e1 )*; //~ ERROR expected one of `.`, `;`, `?`, `else`, or + $( println!("{}", $e2) )*; + } +} + +fn main() { m!(0, 0; 0, 0); } diff --git a/tests/ui/parser/missing-semicolon.stderr b/tests/ui/parser/missing-semicolon.stderr new file mode 100644 index 000000000..e0d5e84ec --- /dev/null +++ b/tests/ui/parser/missing-semicolon.stderr @@ -0,0 +1,13 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found keyword `let` + --> $DIR/missing-semicolon.rs:3:12 + | +LL | $( let x = $e1 )*; + | ^^^ expected one of `.`, `;`, `?`, `else`, or an operator +... +LL | fn main() { m!(0, 0; 0, 0); } + | -------------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs new file mode 100644 index 000000000..810dee957 --- /dev/null +++ b/tests/ui/parser/missing_right_paren.rs @@ -0,0 +1,3 @@ +// ignore-tidy-trailing-newlines +// error-pattern: aborting due to 4 previous errors +fn main((ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr new file mode 100644 index 000000000..3fe0d0f42 --- /dev/null +++ b/tests/ui/parser/missing_right_paren.stderr @@ -0,0 +1,32 @@ +error: this file contains an unclosed delimiter + --> $DIR/missing_right_paren.rs:3:11 + | +LL | fn main((ؼ + | -- ^ + | || + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/missing_right_paren.rs:3:11 + | +LL | fn main((ؼ + | -- ^ + | || + | |unclosed delimiter + | unclosed delimiter + +error: expected one of `:` or `|`, found `)` + --> $DIR/missing_right_paren.rs:3:11 + | +LL | fn main((ؼ + | ^ expected one of `:` or `|` + +error: expected one of `->`, `where`, or `{`, found `` + --> $DIR/missing_right_paren.rs:3:11 + | +LL | fn main((ؼ + | ^ expected one of `->`, `where`, or `{` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/misspelled-macro-rules.fixed b/tests/ui/parser/misspelled-macro-rules.fixed new file mode 100644 index 000000000..62be913d8 --- /dev/null +++ b/tests/ui/parser/misspelled-macro-rules.fixed @@ -0,0 +1,13 @@ +// Regression test for issue #91227. + +// run-rustfix + +#![allow(unused_macros)] + +macro_rules! thing { +//~^ ERROR: expected one of +//~| HELP: perhaps you meant to define a macro + () => {} +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-macro-rules.rs b/tests/ui/parser/misspelled-macro-rules.rs new file mode 100644 index 000000000..4290e6e5e --- /dev/null +++ b/tests/ui/parser/misspelled-macro-rules.rs @@ -0,0 +1,13 @@ +// Regression test for issue #91227. + +// run-rustfix + +#![allow(unused_macros)] + +marco_rules! thing { +//~^ ERROR: expected one of +//~| HELP: perhaps you meant to define a macro + () => {} +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-macro-rules.stderr b/tests/ui/parser/misspelled-macro-rules.stderr new file mode 100644 index 000000000..56df71238 --- /dev/null +++ b/tests/ui/parser/misspelled-macro-rules.stderr @@ -0,0 +1,10 @@ +error: expected one of `(`, `[`, or `{`, found `thing` + --> $DIR/misspelled-macro-rules.rs:7:14 + | +LL | marco_rules! thing { + | ----------- ^^^^^ expected one of `(`, `[`, or `{` + | | + | help: perhaps you meant to define a macro: `macro_rules` + +error: aborting due to previous error + diff --git a/tests/ui/parser/mod_file_not_exist.rs b/tests/ui/parser/mod_file_not_exist.rs new file mode 100644 index 000000000..7b079eb02 --- /dev/null +++ b/tests/ui/parser/mod_file_not_exist.rs @@ -0,0 +1,9 @@ +// ignore-windows + +mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` +//~^ HELP to create the module `not_a_real_file`, create file + +fn main() { + assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared crate or module `mod_file_aux` +} diff --git a/tests/ui/parser/mod_file_not_exist.stderr b/tests/ui/parser/mod_file_not_exist.stderr new file mode 100644 index 000000000..62456d518 --- /dev/null +++ b/tests/ui/parser/mod_file_not_exist.stderr @@ -0,0 +1,18 @@ +error[E0583]: file not found for module `not_a_real_file` + --> $DIR/mod_file_not_exist.rs:3:1 + | +LL | mod not_a_real_file; + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" or "$DIR/not_a_real_file/mod.rs" + +error[E0433]: failed to resolve: use of undeclared crate or module `mod_file_aux` + --> $DIR/mod_file_not_exist.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared crate or module `mod_file_aux` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/parser/mod_file_not_exist_windows.rs b/tests/ui/parser/mod_file_not_exist_windows.rs new file mode 100644 index 000000000..5db21e2bb --- /dev/null +++ b/tests/ui/parser/mod_file_not_exist_windows.rs @@ -0,0 +1,9 @@ +// only-windows + +mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` +//~^ HELP to create the module `not_a_real_file`, create file + +fn main() { + assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared crate or module `mod_file_aux` +} diff --git a/tests/ui/parser/mod_file_not_exist_windows.stderr b/tests/ui/parser/mod_file_not_exist_windows.stderr new file mode 100644 index 000000000..d5143dbe9 --- /dev/null +++ b/tests/ui/parser/mod_file_not_exist_windows.stderr @@ -0,0 +1,18 @@ +error[E0583]: file not found for module `not_a_real_file` + --> $DIR/mod_file_not_exist_windows.rs:3:1 + | +LL | mod not_a_real_file; + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" or "$DIR/not_a_real_file/mod.rs" + +error[E0433]: failed to resolve: use of undeclared crate or module `mod_file_aux` + --> $DIR/mod_file_not_exist_windows.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared crate or module `mod_file_aux` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/parser/mod_file_with_path_attr.rs b/tests/ui/parser/mod_file_with_path_attr.rs new file mode 100644 index 000000000..9450d89e5 --- /dev/null +++ b/tests/ui/parser/mod_file_with_path_attr.rs @@ -0,0 +1,8 @@ +// normalize-stderr-test: "not_a_real_file.rs:.*\(" -> "not_a_real_file.rs: $$FILE_NOT_FOUND_MSG (" + +#[path = "not_a_real_file.rs"] +mod m; //~ ERROR not_a_real_file.rs + +fn main() { + assert_eq!(m::foo(), 10); +} diff --git a/tests/ui/parser/mod_file_with_path_attr.stderr b/tests/ui/parser/mod_file_with_path_attr.stderr new file mode 100644 index 000000000..cd1add73d --- /dev/null +++ b/tests/ui/parser/mod_file_with_path_attr.stderr @@ -0,0 +1,8 @@ +error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/mod_file_with_path_attr.rs:4:1 + | +LL | mod m; + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/multibyte-char-use-seperator-issue-80134.rs b/tests/ui/parser/multibyte-char-use-seperator-issue-80134.rs new file mode 100644 index 000000000..7e7995d67 --- /dev/null +++ b/tests/ui/parser/multibyte-char-use-seperator-issue-80134.rs @@ -0,0 +1,10 @@ +// Regression test for #80134. + +fn main() { + (()é); + //~^ ERROR: expected one of `)`, `,`, `.`, `?`, or an operator + //~| ERROR: cannot find value `é` in this scope + (()æ°·); + //~^ ERROR: expected one of `)`, `,`, `.`, `?`, or an operator + //~| ERROR: cannot find value `æ°·` in this scope +} diff --git a/tests/ui/parser/multibyte-char-use-seperator-issue-80134.stderr b/tests/ui/parser/multibyte-char-use-seperator-issue-80134.stderr new file mode 100644 index 000000000..21e71aa12 --- /dev/null +++ b/tests/ui/parser/multibyte-char-use-seperator-issue-80134.stderr @@ -0,0 +1,33 @@ +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `é` + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:4:8 + | +LL | (()é); + | ^ + | | + | expected one of `)`, `,`, `.`, `?`, or an operator + | help: missing `,` + +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `æ°·` + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:7:8 + | +LL | (()æ°·); + | -^ + | | + | expected one of `)`, `,`, `.`, `?`, or an operator + | help: missing `,` + +error[E0425]: cannot find value `é` in this scope + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:4:8 + | +LL | (()é); + | ^ not found in this scope + +error[E0425]: cannot find value `æ°·` in this scope + --> $DIR/multibyte-char-use-seperator-issue-80134.rs:7:8 + | +LL | (()æ°·); + | ^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/multiline-comment-line-tracking.rs b/tests/ui/parser/multiline-comment-line-tracking.rs new file mode 100644 index 000000000..d4735e8a7 --- /dev/null +++ b/tests/ui/parser/multiline-comment-line-tracking.rs @@ -0,0 +1,9 @@ +// Parse error on line X, but is reported on line Y instead. + +/* 1 + * 2 + * 3 + */ +fn main() { + %; //~ ERROR expected expression, found `%` +} diff --git a/tests/ui/parser/multiline-comment-line-tracking.stderr b/tests/ui/parser/multiline-comment-line-tracking.stderr new file mode 100644 index 000000000..cac0c801a --- /dev/null +++ b/tests/ui/parser/multiline-comment-line-tracking.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `%` + --> $DIR/multiline-comment-line-tracking.rs:8:3 + | +LL | %; + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/multitrait.rs b/tests/ui/parser/multitrait.rs new file mode 100644 index 000000000..f9b4b37ac --- /dev/null +++ b/tests/ui/parser/multitrait.rs @@ -0,0 +1,9 @@ +struct S { + y: isize +} + +impl Cmp, ToString for S { +//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` + fn eq(&&other: S) { false } + fn to_string(&self) -> String { "hi".to_string() } +} diff --git a/tests/ui/parser/multitrait.stderr b/tests/ui/parser/multitrait.stderr new file mode 100644 index 000000000..5a8bb2f7a --- /dev/null +++ b/tests/ui/parser/multitrait.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,` + --> $DIR/multitrait.rs:5:9 + | +LL | impl Cmp, ToString for S { + | ^ expected one of 8 possible tokens + +error: aborting due to previous error + diff --git a/tests/ui/parser/mut-patterns.rs b/tests/ui/parser/mut-patterns.rs new file mode 100644 index 000000000..8b83d6ab2 --- /dev/null +++ b/tests/ui/parser/mut-patterns.rs @@ -0,0 +1,48 @@ +// Can't put mut in non-ident pattern + +// edition:2018 + +#![feature(box_patterns)] +#![allow(warnings)] + +pub fn main() { + let mut _ = 0; //~ ERROR `mut` must be followed by a named binding + let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding + + let mut (x @ y) = 0; //~ ERROR `mut` must be attached to each individual binding + + let mut mut x = 0; + //~^ ERROR `mut` on a binding may not be repeated + //~| remove the additional `mut`s + + struct Foo { x: isize } + let mut Foo { x: x } = Foo { x: 3 }; + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + let mut Foo { x } = Foo { x: 3 }; + //~^ ERROR `mut` must be attached to each individual binding + //~| add `mut` to each binding + + struct r#yield(u8, u8); + let mut mut yield(become, await) = r#yield(0, 0); + //~^ ERROR `mut` on a binding may not be repeated + //~| ERROR `mut` must be attached to each individual binding + //~| ERROR expected identifier, found reserved keyword `yield` + //~| ERROR expected identifier, found reserved keyword `become` + //~| ERROR expected identifier, found keyword `await` + + struct W(T, U); + struct B { f: Box } + let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + //~^ ERROR `mut` must be attached to each individual binding + = W(0, W(1, W(2, W(3, B { f: Box::new(4u8) })))); + + // Make sure we don't accidentally allow `mut $p` where `$p:pat`. + macro_rules! foo { + ($p:pat) => { + let mut $p = 0; //~ ERROR expected identifier, found `x` + } + } + foo!(x); +} diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr new file mode 100644 index 000000000..f179d8c9e --- /dev/null +++ b/tests/ui/parser/mut-patterns.stderr @@ -0,0 +1,114 @@ +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:9:9 + | +LL | let mut _ = 0; + | ^^^^^ help: remove the `mut` prefix: `_` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:10:9 + | +LL | let mut (_, _) = (0, 0); + | ^^^^^^^^^^ help: remove the `mut` prefix: `(_, _)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:12:9 + | +LL | let mut (x @ y) = 0; + | ^^^^^^^^^^^ help: add `mut` to each binding: `(mut x @ mut y)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:14:13 + | +LL | let mut mut x = 0; + | ^^^ help: remove the additional `mut`s + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:19:9 + | +LL | let mut Foo { x: x } = Foo { x: 3 }; + | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:23:9 + | +LL | let mut Foo { x } = Foo { x: 3 }; + | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:28:13 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^ help: remove the additional `mut`s + +error: expected identifier, found reserved keyword `yield` + --> $DIR/mut-patterns.rs:28:17 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found reserved keyword + | +help: escape `yield` to use it as an identifier + | +LL | let mut mut r#yield(become, await) = r#yield(0, 0); + | ++ + +error: expected identifier, found reserved keyword `become` + --> $DIR/mut-patterns.rs:28:23 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^ expected identifier, found reserved keyword + | +help: escape `become` to use it as an identifier + | +LL | let mut mut yield(r#become, await) = r#yield(0, 0); + | ++ + +error: expected identifier, found keyword `await` + --> $DIR/mut-patterns.rs:28:31 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | let mut mut yield(become, r#await) = r#yield(0, 0); + | ++ + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:28:9 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:37:9 + | +LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found `x` + --> $DIR/mut-patterns.rs:44:21 + | +LL | let mut $p = 0; + | ^^ expected identifier +... +LL | foo!(x); + | ------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors + diff --git a/tests/ui/parser/nested-bad-turbofish.rs b/tests/ui/parser/nested-bad-turbofish.rs new file mode 100644 index 000000000..02099fde2 --- /dev/null +++ b/tests/ui/parser/nested-bad-turbofish.rs @@ -0,0 +1,3 @@ +fn main() { + foo<::V>(); //~ ERROR +} diff --git a/tests/ui/parser/nested-bad-turbofish.stderr b/tests/ui/parser/nested-bad-turbofish.stderr new file mode 100644 index 000000000..d82fa80e5 --- /dev/null +++ b/tests/ui/parser/nested-bad-turbofish.stderr @@ -0,0 +1,11 @@ +error: comparison operators cannot be chained + --> $DIR/nested-bad-turbofish.rs:2:16 + | +LL | foo<::V>(); + | ^ ^ + | + = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + = help: or use `(...)` if you meant to specify fn arguments + +error: aborting due to previous error + diff --git a/tests/ui/parser/nested-missing-closing-angle-bracket.rs b/tests/ui/parser/nested-missing-closing-angle-bracket.rs new file mode 100644 index 000000000..84ffdd176 --- /dev/null +++ b/tests/ui/parser/nested-missing-closing-angle-bracket.rs @@ -0,0 +1,4 @@ +fn main() { + let v : Vec:: = vec![vec![]]; + //~^ ERROR: expected one of +} diff --git a/tests/ui/parser/nested-missing-closing-angle-bracket.stderr b/tests/ui/parser/nested-missing-closing-angle-bracket.stderr new file mode 100644 index 000000000..b85bc0256 --- /dev/null +++ b/tests/ui/parser/nested-missing-closing-angle-bracket.stderr @@ -0,0 +1,8 @@ +error: expected one of `,` or `>`, found `;` + --> $DIR/nested-missing-closing-angle-bracket.rs:2:46 + | +LL | let v : Vec:: = vec![vec![]]; + | - while parsing the type for `v` ^ expected one of `,` or `>` + +error: aborting due to previous error + diff --git a/tests/ui/parser/new-unicode-escapes-1.rs b/tests/ui/parser/new-unicode-escapes-1.rs new file mode 100644 index 000000000..d6a54660e --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-1.rs @@ -0,0 +1,3 @@ +pub fn main() { + let s = "\u{2603"; //~ ERROR unterminated unicode escape +} diff --git a/tests/ui/parser/new-unicode-escapes-1.stderr b/tests/ui/parser/new-unicode-escapes-1.stderr new file mode 100644 index 000000000..d133e46b4 --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-1.stderr @@ -0,0 +1,13 @@ +error: unterminated unicode escape + --> $DIR/new-unicode-escapes-1.rs:2:14 + | +LL | let s = "\u{2603"; + | ^^^^^^^ missing a closing `}` + | +help: terminate the unicode escape + | +LL | let s = "\u{2603}"; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/new-unicode-escapes-2.rs b/tests/ui/parser/new-unicode-escapes-2.rs new file mode 100644 index 000000000..cbb614c19 --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-2.rs @@ -0,0 +1,3 @@ +pub fn main() { + let s = "\u{260311111111}"; //~ ERROR overlong unicode escape +} diff --git a/tests/ui/parser/new-unicode-escapes-2.stderr b/tests/ui/parser/new-unicode-escapes-2.stderr new file mode 100644 index 000000000..2f3f8c0f9 --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-2.stderr @@ -0,0 +1,8 @@ +error: overlong unicode escape + --> $DIR/new-unicode-escapes-2.rs:2:14 + | +LL | let s = "\u{260311111111}"; + | ^^^^^^^^^^^^^^^^ must have at most 6 hex digits + +error: aborting due to previous error + diff --git a/tests/ui/parser/new-unicode-escapes-3.rs b/tests/ui/parser/new-unicode-escapes-3.rs new file mode 100644 index 000000000..295ab08c0 --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-3.rs @@ -0,0 +1,4 @@ +pub fn main() { + let s1 = "\u{d805}"; //~ ERROR invalid unicode character escape + let s2 = "\u{ffffff}"; //~ ERROR invalid unicode character escape +} diff --git a/tests/ui/parser/new-unicode-escapes-3.stderr b/tests/ui/parser/new-unicode-escapes-3.stderr new file mode 100644 index 000000000..f5a0f8fc7 --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-3.stderr @@ -0,0 +1,18 @@ +error: invalid unicode character escape + --> $DIR/new-unicode-escapes-3.rs:2:15 + | +LL | let s1 = "\u{d805}"; + | ^^^^^^^^ invalid escape + | + = help: unicode escape must not be a surrogate + +error: invalid unicode character escape + --> $DIR/new-unicode-escapes-3.rs:3:15 + | +LL | let s2 = "\u{ffffff}"; + | ^^^^^^^^^^ invalid escape + | + = help: unicode escape must be at most 10FFFF + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/new-unicode-escapes-4.rs b/tests/ui/parser/new-unicode-escapes-4.rs new file mode 100644 index 000000000..79882713e --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-4.rs @@ -0,0 +1,4 @@ +pub fn main() { + let s = "\u{lol}"; + //~^ ERROR invalid character in unicode escape: `l` +} diff --git a/tests/ui/parser/new-unicode-escapes-4.stderr b/tests/ui/parser/new-unicode-escapes-4.stderr new file mode 100644 index 000000000..514591af1 --- /dev/null +++ b/tests/ui/parser/new-unicode-escapes-4.stderr @@ -0,0 +1,8 @@ +error: invalid character in unicode escape: `l` + --> $DIR/new-unicode-escapes-4.rs:2:17 + | +LL | let s = "\u{lol}"; + | ^ invalid character in unicode escape + +error: aborting due to previous error + diff --git a/tests/ui/parser/no-binary-float-literal.rs b/tests/ui/parser/no-binary-float-literal.rs new file mode 100644 index 000000000..e07ff6518 --- /dev/null +++ b/tests/ui/parser/no-binary-float-literal.rs @@ -0,0 +1,8 @@ +fn main() { + 0b101010f64; + //~^ ERROR binary float literal is not supported + 0b101.010; + //~^ ERROR binary float literal is not supported + 0b101p4f64; + //~^ ERROR invalid suffix `p4f64` for number literal +} diff --git a/tests/ui/parser/no-binary-float-literal.stderr b/tests/ui/parser/no-binary-float-literal.stderr new file mode 100644 index 000000000..cfd448684 --- /dev/null +++ b/tests/ui/parser/no-binary-float-literal.stderr @@ -0,0 +1,22 @@ +error: binary float literal is not supported + --> $DIR/no-binary-float-literal.rs:4:5 + | +LL | 0b101.010; + | ^^^^^^^^^ + +error: binary float literal is not supported + --> $DIR/no-binary-float-literal.rs:2:5 + | +LL | 0b101010f64; + | ^^^^^^^^^^^ not supported + +error: invalid suffix `p4f64` for number literal + --> $DIR/no-binary-float-literal.rs:6:5 + | +LL | 0b101p4f64; + | ^^^^^^^^^^ invalid suffix `p4f64` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs new file mode 100644 index 000000000..1993124ed --- /dev/null +++ b/tests/ui/parser/no-const-fn-in-extern-block.rs @@ -0,0 +1,8 @@ +extern "C" { + const fn foo(); + //~^ ERROR functions in `extern` blocks cannot have qualifiers + const unsafe fn bar(); + //~^ ERROR functions in `extern` blocks cannot have qualifiers +} + +fn main() {} diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr new file mode 100644 index 000000000..4ac0e2655 --- /dev/null +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -0,0 +1,29 @@ +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/no-const-fn-in-extern-block.rs:2:14 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | const fn foo(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn foo(); + | ~~ + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/no-const-fn-in-extern-block.rs:4:21 + | +LL | extern "C" { + | ---------- in this `extern` block +... +LL | const unsafe fn bar(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn bar(); + | ~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/no-hex-float-literal.rs b/tests/ui/parser/no-hex-float-literal.rs new file mode 100644 index 000000000..bf11dee08 --- /dev/null +++ b/tests/ui/parser/no-hex-float-literal.rs @@ -0,0 +1,9 @@ +fn main() { + 0xABC.Df; + //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields + 0x567.89; + //~^ ERROR hexadecimal float literal is not supported + 0xDEAD.BEEFp-2f; + //~^ ERROR invalid suffix `f` for float literal + //~| ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/tests/ui/parser/no-hex-float-literal.stderr b/tests/ui/parser/no-hex-float-literal.stderr new file mode 100644 index 000000000..258ab06d5 --- /dev/null +++ b/tests/ui/parser/no-hex-float-literal.stderr @@ -0,0 +1,29 @@ +error: hexadecimal float literal is not supported + --> $DIR/no-hex-float-literal.rs:4:5 + | +LL | 0x567.89; + | ^^^^^^^^ + +error: invalid suffix `f` for float literal + --> $DIR/no-hex-float-literal.rs:6:18 + | +LL | 0xDEAD.BEEFp-2f; + | ^^ invalid suffix `f` + | + = help: valid suffixes are `f32` and `f64` + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/no-hex-float-literal.rs:2:11 + | +LL | 0xABC.Df; + | ^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/no-hex-float-literal.rs:6:12 + | +LL | 0xDEAD.BEEFp-2f; + | ^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/parser/no-unsafe-self.rs b/tests/ui/parser/no-unsafe-self.rs new file mode 100644 index 000000000..d1cd8ad53 --- /dev/null +++ b/tests/ui/parser/no-unsafe-self.rs @@ -0,0 +1,14 @@ +trait A { + fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer + fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer + fn bar(*self); //~ ERROR cannot pass `self` by raw pointer +} + +struct X; +impl A for X { + fn foo(*mut self) { } //~ ERROR cannot pass `self` by raw pointer + fn baz(*const self) { } //~ ERROR cannot pass `self` by raw pointer + fn bar(*self) { } //~ ERROR cannot pass `self` by raw pointer +} + +fn main() { } diff --git a/tests/ui/parser/no-unsafe-self.stderr b/tests/ui/parser/no-unsafe-self.stderr new file mode 100644 index 000000000..23323945e --- /dev/null +++ b/tests/ui/parser/no-unsafe-self.stderr @@ -0,0 +1,38 @@ +error: cannot pass `self` by raw pointer + --> $DIR/no-unsafe-self.rs:2:17 + | +LL | fn foo(*mut self); + | ^^^^ cannot pass `self` by raw pointer + +error: cannot pass `self` by raw pointer + --> $DIR/no-unsafe-self.rs:3:19 + | +LL | fn baz(*const self); + | ^^^^ cannot pass `self` by raw pointer + +error: cannot pass `self` by raw pointer + --> $DIR/no-unsafe-self.rs:4:13 + | +LL | fn bar(*self); + | ^^^^ cannot pass `self` by raw pointer + +error: cannot pass `self` by raw pointer + --> $DIR/no-unsafe-self.rs:9:17 + | +LL | fn foo(*mut self) { } + | ^^^^ cannot pass `self` by raw pointer + +error: cannot pass `self` by raw pointer + --> $DIR/no-unsafe-self.rs:10:19 + | +LL | fn baz(*const self) { } + | ^^^^ cannot pass `self` by raw pointer + +error: cannot pass `self` by raw pointer + --> $DIR/no-unsafe-self.rs:11:13 + | +LL | fn bar(*self) { } + | ^^^^ cannot pass `self` by raw pointer + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/not-a-pred.rs b/tests/ui/parser/not-a-pred.rs new file mode 100644 index 000000000..5518b554d --- /dev/null +++ b/tests/ui/parser/not-a-pred.rs @@ -0,0 +1,15 @@ +fn f(a: isize, b: isize) : lt(a, b) { } +//~^ ERROR return types are denoted using `->` +//~| ERROR expected type, found function `lt` [E0573] +//~| ERROR expected type, found local variable `a` [E0573] +//~| ERROR expected type, found local variable `b` [E0573] + +fn lt(a: isize, b: isize) { } + +fn main() { + let a: isize = 10; + let b: isize = 23; + check (lt(a, b)); + //~^ ERROR cannot find function `check` in this scope [E0425] + f(a, b); +} diff --git a/tests/ui/parser/not-a-pred.stderr b/tests/ui/parser/not-a-pred.stderr new file mode 100644 index 000000000..bcc64a687 --- /dev/null +++ b/tests/ui/parser/not-a-pred.stderr @@ -0,0 +1,34 @@ +error: return types are denoted using `->` + --> $DIR/not-a-pred.rs:1:26 + | +LL | fn f(a: isize, b: isize) : lt(a, b) { } + | ^ help: use `->` instead + +error[E0573]: expected type, found function `lt` + --> $DIR/not-a-pred.rs:1:28 + | +LL | fn f(a: isize, b: isize) : lt(a, b) { } + | ^^^^^^^^ not a type + +error[E0573]: expected type, found local variable `a` + --> $DIR/not-a-pred.rs:1:31 + | +LL | fn f(a: isize, b: isize) : lt(a, b) { } + | ^ not a type + +error[E0573]: expected type, found local variable `b` + --> $DIR/not-a-pred.rs:1:34 + | +LL | fn f(a: isize, b: isize) : lt(a, b) { } + | ^ not a type + +error[E0425]: cannot find function `check` in this scope + --> $DIR/not-a-pred.rs:12:5 + | +LL | check (lt(a, b)); + | ^^^^^ not found in this scope + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0425, E0573. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/nt-parsing-has-recovery.rs b/tests/ui/parser/nt-parsing-has-recovery.rs new file mode 100644 index 000000000..ccbeb398a --- /dev/null +++ b/tests/ui/parser/nt-parsing-has-recovery.rs @@ -0,0 +1,10 @@ +macro_rules! foo { + ($e:expr) => {} +} + +foo!(1 + @); //~ ERROR expected expression, found `@` +foo!(1 + @); //~ ERROR expected expression, found `@` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/nt-parsing-has-recovery.stderr b/tests/ui/parser/nt-parsing-has-recovery.stderr new file mode 100644 index 000000000..263c4ad53 --- /dev/null +++ b/tests/ui/parser/nt-parsing-has-recovery.stderr @@ -0,0 +1,29 @@ +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:5:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:6:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error[E0308]: mismatched types + --> $DIR/nt-parsing-has-recovery.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/numeric-lifetime.rs b/tests/ui/parser/numeric-lifetime.rs new file mode 100644 index 000000000..2d82354c6 --- /dev/null +++ b/tests/ui/parser/numeric-lifetime.rs @@ -0,0 +1,8 @@ +struct S<'1> { s: &'1 usize } +//~^ ERROR lifetimes cannot start with a number +//~| ERROR lifetimes cannot start with a number +fn main() { + // verify that the parse error doesn't stop type checking + let x: usize = ""; + //~^ ERROR mismatched types +} diff --git a/tests/ui/parser/numeric-lifetime.stderr b/tests/ui/parser/numeric-lifetime.stderr new file mode 100644 index 000000000..7c1bcb726 --- /dev/null +++ b/tests/ui/parser/numeric-lifetime.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/numeric-lifetime.rs:6:20 + | +LL | let x: usize = ""; + | ----- ^^ expected `usize`, found `&str` + | | + | expected due to this + +error: lifetimes cannot start with a number + --> $DIR/numeric-lifetime.rs:1:10 + | +LL | struct S<'1> { s: &'1 usize } + | ^^ + +error: lifetimes cannot start with a number + --> $DIR/numeric-lifetime.rs:1:20 + | +LL | struct S<'1> { s: &'1 usize } + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/obsolete-syntax-impl-for-dotdot.rs b/tests/ui/parser/obsolete-syntax-impl-for-dotdot.rs new file mode 100644 index 000000000..e928f09aa --- /dev/null +++ b/tests/ui/parser/obsolete-syntax-impl-for-dotdot.rs @@ -0,0 +1,9 @@ +trait Trait1 {} +trait Trait2 {} + +#[cfg(not_enabled)] +impl Trait1 for .. {} + +impl Trait2 for .. {} //~ ERROR `impl Trait for .. {}` is an obsolete syntax + +fn main() {} diff --git a/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr b/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr new file mode 100644 index 000000000..b7108ced0 --- /dev/null +++ b/tests/ui/parser/obsolete-syntax-impl-for-dotdot.stderr @@ -0,0 +1,10 @@ +error: `impl Trait for .. {}` is an obsolete syntax + --> $DIR/obsolete-syntax-impl-for-dotdot.rs:7:1 + | +LL | impl Trait2 for .. {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: use `auto trait Trait {}` instead + +error: aborting due to previous error + diff --git a/tests/ui/parser/old-suffixes-are-really-forbidden.rs b/tests/ui/parser/old-suffixes-are-really-forbidden.rs new file mode 100644 index 000000000..eea95b7d6 --- /dev/null +++ b/tests/ui/parser/old-suffixes-are-really-forbidden.rs @@ -0,0 +1,4 @@ +fn main() { + let a = 1_is; //~ ERROR invalid suffix + let b = 2_us; //~ ERROR invalid suffix +} diff --git a/tests/ui/parser/old-suffixes-are-really-forbidden.stderr b/tests/ui/parser/old-suffixes-are-really-forbidden.stderr new file mode 100644 index 000000000..fb309793b --- /dev/null +++ b/tests/ui/parser/old-suffixes-are-really-forbidden.stderr @@ -0,0 +1,18 @@ +error: invalid suffix `is` for number literal + --> $DIR/old-suffixes-are-really-forbidden.rs:2:13 + | +LL | let a = 1_is; + | ^^^^ invalid suffix `is` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: invalid suffix `us` for number literal + --> $DIR/old-suffixes-are-really-forbidden.rs:3:13 + | +LL | let b = 2_us; + | ^^^^ invalid suffix `us` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/omitted-arg-in-item-fn.rs b/tests/ui/parser/omitted-arg-in-item-fn.rs new file mode 100644 index 000000000..49cbc4d6b --- /dev/null +++ b/tests/ui/parser/omitted-arg-in-item-fn.rs @@ -0,0 +1,4 @@ +fn foo(x) { //~ ERROR expected one of `:`, `@`, or `|`, found `)` +} + +fn main() {} diff --git a/tests/ui/parser/omitted-arg-in-item-fn.stderr b/tests/ui/parser/omitted-arg-in-item-fn.stderr new file mode 100644 index 000000000..ce2eab051 --- /dev/null +++ b/tests/ui/parser/omitted-arg-in-item-fn.stderr @@ -0,0 +1,22 @@ +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/omitted-arg-in-item-fn.rs:1:9 + | +LL | fn foo(x) { + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo(self: x) { + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn foo(x: TypeName) { + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo(_: x) { + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/operator-associativity.rs b/tests/ui/parser/operator-associativity.rs new file mode 100644 index 000000000..4f40c80bc --- /dev/null +++ b/tests/ui/parser/operator-associativity.rs @@ -0,0 +1,4 @@ +// run-pass +// Testcase for issue #130, operator associativity. + +pub fn main() { assert_eq!(3 * 5 / 2, 7); } diff --git a/tests/ui/parser/paamayim-nekudotayim.rs b/tests/ui/parser/paamayim-nekudotayim.rs new file mode 100644 index 000000000..cb151d652 --- /dev/null +++ b/tests/ui/parser/paamayim-nekudotayim.rs @@ -0,0 +1,5 @@ +// http://phpsadness.com/sad/1 + +fn main() { + ::; //~ ERROR expected identifier, found `;` +} diff --git a/tests/ui/parser/paamayim-nekudotayim.stderr b/tests/ui/parser/paamayim-nekudotayim.stderr new file mode 100644 index 000000000..6ceba07f4 --- /dev/null +++ b/tests/ui/parser/paamayim-nekudotayim.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `;` + --> $DIR/paamayim-nekudotayim.rs:4:7 + | +LL | ::; + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/parser/parse-assoc-type-lt.rs b/tests/ui/parser/parse-assoc-type-lt.rs new file mode 100644 index 000000000..d3fe6079a --- /dev/null +++ b/tests/ui/parser/parse-assoc-type-lt.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Foo { + type T; + fn foo() -> Box<::T>; +} + +fn main() {} diff --git a/tests/ui/parser/parse-error-correct.rs b/tests/ui/parser/parse-error-correct.rs new file mode 100644 index 000000000..13759a235 --- /dev/null +++ b/tests/ui/parser/parse-error-correct.rs @@ -0,0 +1,10 @@ +// Test that the parser is error correcting missing idents. Despite a parsing +// error (or two), we still run type checking (and don't get extra errors there). + +fn main() { + let y = 42; + let x = y.; //~ ERROR unexpected token + let x = y.(); //~ ERROR unexpected token + //~^ ERROR expected function, found `{integer}` + let x = y.foo; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E061 +} diff --git a/tests/ui/parser/parse-error-correct.stderr b/tests/ui/parser/parse-error-correct.stderr new file mode 100644 index 000000000..691df9126 --- /dev/null +++ b/tests/ui/parser/parse-error-correct.stderr @@ -0,0 +1,33 @@ +error: unexpected token: `;` + --> $DIR/parse-error-correct.rs:6:15 + | +LL | let x = y.; + | ^ + +error: unexpected token: `(` + --> $DIR/parse-error-correct.rs:7:15 + | +LL | let x = y.(); + | ^ + +error[E0618]: expected function, found `{integer}` + --> $DIR/parse-error-correct.rs:7:13 + | +LL | let y = 42; + | - `y` has type `{integer}` +LL | let x = y.; +LL | let x = y.(); + | ^--- + | | + | call expression requires function + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/parse-error-correct.rs:9:15 + | +LL | let x = y.foo; + | ^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0610, E0618. +For more information about an error, try `rustc --explain E0610`. diff --git a/tests/ui/parser/parse-panic.rs b/tests/ui/parser/parse-panic.rs new file mode 100644 index 000000000..aeb2ba4fa --- /dev/null +++ b/tests/ui/parser/parse-panic.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unreachable_code)] + +fn dont_call_me() { panic!(); println!("{}", 1); } + +pub fn main() { } diff --git a/tests/ui/parser/parser-recovery-1.rs b/tests/ui/parser/parser-recovery-1.rs new file mode 100644 index 000000000..7e26b4f2b --- /dev/null +++ b/tests/ui/parser/parser-recovery-1.rs @@ -0,0 +1,13 @@ +// Test that we can recover from missing braces in the parser. + +trait Foo { + fn bar() { + let x = foo(); + //~^ ERROR cannot find function `foo` in this scope +} + +fn main() { + let x = y.; + //~^ ERROR unexpected token + //~| ERROR cannot find value `y` in this scope +} //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/parser-recovery-1.stderr b/tests/ui/parser/parser-recovery-1.stderr new file mode 100644 index 000000000..0cb771ea3 --- /dev/null +++ b/tests/ui/parser/parser-recovery-1.stderr @@ -0,0 +1,35 @@ +error: this file contains an unclosed delimiter + --> $DIR/parser-recovery-1.rs:13:54 + | +LL | trait Foo { + | - unclosed delimiter +LL | fn bar() { + | - this delimiter might not be properly closed... +... +LL | } + | - ...as it matches this but it has different indentation +... +LL | } + | ^ + +error: unexpected token: `;` + --> $DIR/parser-recovery-1.rs:10:15 + | +LL | let x = y.; + | ^ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/parser-recovery-1.rs:10:13 + | +LL | let x = y.; + | ^ not found in this scope + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/parser-recovery-1.rs:5:17 + | +LL | let x = foo(); + | ^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/parser-recovery-2.rs b/tests/ui/parser/parser-recovery-2.rs new file mode 100644 index 000000000..48b22afff --- /dev/null +++ b/tests/ui/parser/parser-recovery-2.rs @@ -0,0 +1,12 @@ +// Test that we can recover from mismatched braces in the parser. + +trait Foo { + fn bar() { + let x = foo(); //~ ERROR cannot find function `foo` in this scope + ) //~ ERROR mismatched closing delimiter: `)` +} + +fn main() { + let x = y.; //~ ERROR unexpected token + //~^ ERROR cannot find value `y` in this scope +} diff --git a/tests/ui/parser/parser-recovery-2.stderr b/tests/ui/parser/parser-recovery-2.stderr new file mode 100644 index 000000000..8829cf4c1 --- /dev/null +++ b/tests/ui/parser/parser-recovery-2.stderr @@ -0,0 +1,30 @@ +error: unexpected token: `;` + --> $DIR/parser-recovery-2.rs:10:15 + | +LL | let x = y.; + | ^ + +error: mismatched closing delimiter: `)` + --> $DIR/parser-recovery-2.rs:4:14 + | +LL | fn bar() { + | ^ unclosed delimiter +LL | let x = foo(); +LL | ) + | ^ mismatched closing delimiter + +error[E0425]: cannot find value `y` in this scope + --> $DIR/parser-recovery-2.rs:10:13 + | +LL | let x = y.; + | ^ not found in this scope + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/parser-recovery-2.rs:5:17 + | +LL | let x = foo(); + | ^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/parser-unicode-whitespace.rs b/tests/ui/parser/parser-unicode-whitespace.rs new file mode 100644 index 000000000..555cd68c3 --- /dev/null +++ b/tests/ui/parser/parser-unicode-whitespace.rs @@ -0,0 +1,12 @@ +// run-pass +// Beware editing: it has numerous whitespace characters which are important. +// It contains one ranges from the 'PATTERN_WHITE_SPACE' property outlined in +// https://unicode.org/Public/UNIDATA/PropList.txt +// +// The characters in the first expression of the assertion can be generated +// from: "4\u{0C}+\n\t\r7\t*\u{20}2\u{85}/\u{200E}3\u{200F}*\u{2028}2\u{2029}" +pub fn main() { +assert_eq!(4 + + +7 * 2Â…/‎3â€*
2
, 4 + 7 * 2 / 3 * 2); +} diff --git a/tests/ui/parser/pat-lt-bracket-1.rs b/tests/ui/parser/pat-lt-bracket-1.rs new file mode 100644 index 000000000..2e2001434 --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-1.rs @@ -0,0 +1,7 @@ +fn main() { + match 42 { + x < 7 => (), + //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + _ => () + } +} diff --git a/tests/ui/parser/pat-lt-bracket-1.stderr b/tests/ui/parser/pat-lt-bracket-1.stderr new file mode 100644 index 000000000..e8ccbad66 --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-1.stderr @@ -0,0 +1,8 @@ +error: expected one of `=>`, `@`, `if`, or `|`, found `<` + --> $DIR/pat-lt-bracket-1.rs:3:7 + | +LL | x < 7 => (), + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-lt-bracket-2.rs b/tests/ui/parser/pat-lt-bracket-2.rs new file mode 100644 index 000000000..3a778ed14 --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-2.rs @@ -0,0 +1,4 @@ +fn a(B<) {} + //~^ error: expected one of `:`, `@`, or `|`, found `<` + +fn main() {} diff --git a/tests/ui/parser/pat-lt-bracket-2.stderr b/tests/ui/parser/pat-lt-bracket-2.stderr new file mode 100644 index 000000000..c78f96e1a --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-2.stderr @@ -0,0 +1,18 @@ +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/pat-lt-bracket-2.rs:1:7 + | +LL | fn a(B<) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn a(self: B<) {} + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn a(_: B<) {} + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-lt-bracket-3.rs b/tests/ui/parser/pat-lt-bracket-3.rs new file mode 100644 index 000000000..a8bdfd3fa --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-3.rs @@ -0,0 +1,14 @@ +struct Foo(T, T); + +impl Foo { + fn foo(&self) { + match *self { + Foo(x, y) => { + //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + println!("Goodbye, World!") + } + } + } +} + +fn main() {} diff --git a/tests/ui/parser/pat-lt-bracket-3.stderr b/tests/ui/parser/pat-lt-bracket-3.stderr new file mode 100644 index 000000000..bacf868e3 --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-3.stderr @@ -0,0 +1,8 @@ +error: expected one of `=>`, `@`, `if`, or `|`, found `<` + --> $DIR/pat-lt-bracket-3.rs:6:16 + | +LL | Foo(x, y) => { + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-lt-bracket-4.rs b/tests/ui/parser/pat-lt-bracket-4.rs new file mode 100644 index 000000000..de314f6c6 --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-4.rs @@ -0,0 +1,11 @@ +enum BtNode { + Node(u32,Box,Box), + Leaf(u32), +} + +fn main() { + let y = match 10 { + Foo::A(value) => value, //~ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + Foo::B => 7, + }; +} diff --git a/tests/ui/parser/pat-lt-bracket-4.stderr b/tests/ui/parser/pat-lt-bracket-4.stderr new file mode 100644 index 000000000..911c276b9 --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-4.stderr @@ -0,0 +1,8 @@ +error: expected one of `=>`, `@`, `if`, or `|`, found `<` + --> $DIR/pat-lt-bracket-4.rs:8:12 + | +LL | Foo::A(value) => value, + | ^ expected one of `=>`, `@`, `if`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-lt-bracket-5.rs b/tests/ui/parser/pat-lt-bracket-5.rs new file mode 100644 index 000000000..aaece1f6b --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-5.rs @@ -0,0 +1,3 @@ +fn main() { + let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[` +} diff --git a/tests/ui/parser/pat-lt-bracket-5.stderr b/tests/ui/parser/pat-lt-bracket-5.stderr new file mode 100644 index 000000000..e23674bce --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-5.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[` + --> $DIR/pat-lt-bracket-5.rs:2:10 + | +LL | let v[0] = v[1]; + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-lt-bracket-6.rs b/tests/ui/parser/pat-lt-bracket-6.rs new file mode 100644 index 000000000..7becffa9f --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-6.rs @@ -0,0 +1,9 @@ +fn main() { + struct Test(&'static u8, [u8; 0]); + let x = Test(&0, []); + + let Test(&desc[..]) = x; + //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` +} + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr new file mode 100644 index 000000000..035d0dbfe --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-6.stderr @@ -0,0 +1,18 @@ +error: expected one of `)`, `,`, `@`, or `|`, found `[` + --> $DIR/pat-lt-bracket-6.rs:5:19 + | +LL | let Test(&desc[..]) = x; + | ^ + | | + | expected one of `)`, `,`, `@`, or `|` + | help: missing `,` + +error[E0308]: mismatched types + --> $DIR/pat-lt-bracket-6.rs:9:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected `()`, found integer + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/pat-lt-bracket-7.rs b/tests/ui/parser/pat-lt-bracket-7.rs new file mode 100644 index 000000000..327aef5ad --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-7.rs @@ -0,0 +1,9 @@ +fn main() { + struct Thing(u8, [u8; 0]); + let foo = core::iter::empty(); + + for Thing(x[]) in foo {} + //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` +} + +const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/tests/ui/parser/pat-lt-bracket-7.stderr b/tests/ui/parser/pat-lt-bracket-7.stderr new file mode 100644 index 000000000..004dcfb2a --- /dev/null +++ b/tests/ui/parser/pat-lt-bracket-7.stderr @@ -0,0 +1,18 @@ +error: expected one of `)`, `,`, `@`, or `|`, found `[` + --> $DIR/pat-lt-bracket-7.rs:5:16 + | +LL | for Thing(x[]) in foo {} + | ^ + | | + | expected one of `)`, `,`, `@`, or `|` + | help: missing `,` + +error[E0308]: mismatched types + --> $DIR/pat-lt-bracket-7.rs:9:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected `()`, found integer + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/pat-ranges-1.rs b/tests/ui/parser/pat-ranges-1.rs new file mode 100644 index 000000000..1dafb5a07 --- /dev/null +++ b/tests/ui/parser/pat-ranges-1.rs @@ -0,0 +1,5 @@ +// Parsing of range patterns + +fn main() { + let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, `=`, or `|`, found `..=` +} diff --git a/tests/ui/parser/pat-ranges-1.stderr b/tests/ui/parser/pat-ranges-1.stderr new file mode 100644 index 000000000..b64a3ce5c --- /dev/null +++ b/tests/ui/parser/pat-ranges-1.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, or `|`, found `..=` + --> $DIR/pat-ranges-1.rs:4:21 + | +LL | let macropus!() ..= 11 = 12; + | ^^^ expected one of `:`, `;`, `=`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-ranges-2.rs b/tests/ui/parser/pat-ranges-2.rs new file mode 100644 index 000000000..1593222ac --- /dev/null +++ b/tests/ui/parser/pat-ranges-2.rs @@ -0,0 +1,5 @@ +// Parsing of range patterns + +fn main() { + let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` +} diff --git a/tests/ui/parser/pat-ranges-2.stderr b/tests/ui/parser/pat-ranges-2.stderr new file mode 100644 index 000000000..1a9e33beb --- /dev/null +++ b/tests/ui/parser/pat-ranges-2.stderr @@ -0,0 +1,8 @@ +error: expected one of `::`, `:`, `;`, `=`, or `|`, found `!` + --> $DIR/pat-ranges-2.rs:4:26 + | +LL | let 10 ..= makropulos!() = 12; + | ^ expected one of `::`, `:`, `;`, `=`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-ranges-3.rs b/tests/ui/parser/pat-ranges-3.rs new file mode 100644 index 000000000..8976dcf0d --- /dev/null +++ b/tests/ui/parser/pat-ranges-3.rs @@ -0,0 +1,5 @@ +// Parsing of range patterns + +fn main() { + let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, `=`, or `|`, found `+` +} diff --git a/tests/ui/parser/pat-ranges-3.stderr b/tests/ui/parser/pat-ranges-3.stderr new file mode 100644 index 000000000..c9787b789 --- /dev/null +++ b/tests/ui/parser/pat-ranges-3.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, or `|`, found `+` + --> $DIR/pat-ranges-3.rs:4:19 + | +LL | let 10 ..= 10 + 3 = 12; + | ^ expected one of `:`, `;`, `=`, or `|` + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-ranges-4.rs b/tests/ui/parser/pat-ranges-4.rs new file mode 100644 index 000000000..61188976b --- /dev/null +++ b/tests/ui/parser/pat-ranges-4.rs @@ -0,0 +1,6 @@ +// Parsing of range patterns + +fn main() { + let 10 - 3 ..= 10 = 8; + //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` +} diff --git a/tests/ui/parser/pat-ranges-4.stderr b/tests/ui/parser/pat-ranges-4.stderr new file mode 100644 index 000000000..69084b5a4 --- /dev/null +++ b/tests/ui/parser/pat-ranges-4.stderr @@ -0,0 +1,8 @@ +error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-` + --> $DIR/pat-ranges-4.rs:4:12 + | +LL | let 10 - 3 ..= 10 = 8; + | ^ expected one of 7 possible tokens + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-ref-enum.rs b/tests/ui/parser/pat-ref-enum.rs new file mode 100644 index 000000000..412dd141d --- /dev/null +++ b/tests/ui/parser/pat-ref-enum.rs @@ -0,0 +1,8 @@ +fn matcher(x: Option) { + match x { + ref Some(i) => {} //~ ERROR expected identifier, found enum pattern + None => {} + } +} + +fn main() {} diff --git a/tests/ui/parser/pat-ref-enum.stderr b/tests/ui/parser/pat-ref-enum.stderr new file mode 100644 index 000000000..a3bce3372 --- /dev/null +++ b/tests/ui/parser/pat-ref-enum.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found enum pattern + --> $DIR/pat-ref-enum.rs:3:11 + | +LL | ref Some(i) => {} + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-tuple-1.rs b/tests/ui/parser/pat-tuple-1.rs new file mode 100644 index 000000000..0e49b547f --- /dev/null +++ b/tests/ui/parser/pat-tuple-1.rs @@ -0,0 +1,5 @@ +fn main() { + match (0, 1) { + (, ..) => {} //~ ERROR expected pattern, found `,` + } +} diff --git a/tests/ui/parser/pat-tuple-1.stderr b/tests/ui/parser/pat-tuple-1.stderr new file mode 100644 index 000000000..391f2c428 --- /dev/null +++ b/tests/ui/parser/pat-tuple-1.stderr @@ -0,0 +1,8 @@ +error: expected pattern, found `,` + --> $DIR/pat-tuple-1.rs:3:10 + | +LL | (, ..) => {} + | ^ expected pattern + +error: aborting due to previous error + diff --git a/tests/ui/parser/pat-tuple-2.rs b/tests/ui/parser/pat-tuple-2.rs new file mode 100644 index 000000000..a8f3debd3 --- /dev/null +++ b/tests/ui/parser/pat-tuple-2.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() { + match (0, 1, 2) { + (pat, ..,) => {} + } +} diff --git a/tests/ui/parser/pat-tuple-3.rs b/tests/ui/parser/pat-tuple-3.rs new file mode 100644 index 000000000..1486ab231 --- /dev/null +++ b/tests/ui/parser/pat-tuple-3.rs @@ -0,0 +1,6 @@ +fn main() { + match (0, 1, 2) { + (.., pat, ..) => {} + //~^ ERROR `..` can only be used once per tuple pattern + } +} diff --git a/tests/ui/parser/pat-tuple-3.stderr b/tests/ui/parser/pat-tuple-3.stderr new file mode 100644 index 000000000..9ac0611c5 --- /dev/null +++ b/tests/ui/parser/pat-tuple-3.stderr @@ -0,0 +1,10 @@ +error: `..` can only be used once per tuple pattern + --> $DIR/pat-tuple-3.rs:3:19 + | +LL | (.., pat, ..) => {} + | -- ^^ can only be used once per tuple pattern + | | + | previously used here + +error: aborting due to previous error + diff --git a/tests/ui/parser/pub-method-macro.rs b/tests/ui/parser/pub-method-macro.rs new file mode 100644 index 000000000..0183bdcf6 --- /dev/null +++ b/tests/ui/parser/pub-method-macro.rs @@ -0,0 +1,23 @@ +// Issue #18317 + +mod bleh { + macro_rules! defn { + ($n:ident) => ( + fn $n (&self) -> i32 { + println!("{}", stringify!($n)); + 1 + } + ) + } + + #[derive(Copy, Clone)] + pub struct S; + + impl S { + pub defn!(f); //~ ERROR can't qualify macro invocation with `pub` + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation + } +} + +fn main() {} diff --git a/tests/ui/parser/pub-method-macro.stderr b/tests/ui/parser/pub-method-macro.stderr new file mode 100644 index 000000000..7c7a90926 --- /dev/null +++ b/tests/ui/parser/pub-method-macro.stderr @@ -0,0 +1,10 @@ +error: can't qualify macro invocation with `pub` + --> $DIR/pub-method-macro.rs:17:9 + | +LL | pub defn!(f); + | ^^^ help: remove the visibility + | + = help: try adjusting the macro to put `pub` inside the invocation + +error: aborting due to previous error + diff --git a/tests/ui/parser/public-instead-of-pub-1.fixed b/tests/ui/parser/public-instead-of-pub-1.fixed new file mode 100644 index 000000000..a4fa68ba5 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-1.fixed @@ -0,0 +1,11 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// run-rustfix + +pub enum Test { + //~^ ERROR expected one of `!` or `::`, found keyword `enum` + //~^^ HELP write `pub` instead of `public` to make the item public + A, + B, +} + +fn main() { } diff --git a/tests/ui/parser/public-instead-of-pub-1.rs b/tests/ui/parser/public-instead-of-pub-1.rs new file mode 100644 index 000000000..43565c9b1 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-1.rs @@ -0,0 +1,11 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// run-rustfix + +public enum Test { + //~^ ERROR expected one of `!` or `::`, found keyword `enum` + //~^^ HELP write `pub` instead of `public` to make the item public + A, + B, +} + +fn main() { } diff --git a/tests/ui/parser/public-instead-of-pub-1.stderr b/tests/ui/parser/public-instead-of-pub-1.stderr new file mode 100644 index 000000000..795a5bcf5 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-1.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found keyword `enum` + --> $DIR/public-instead-of-pub-1.rs:4:8 + | +LL | public enum Test { + | ^^^^ expected one of `!` or `::` + | +help: write `pub` instead of `public` to make the item public + | +LL | pub enum Test { + | ~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/public-instead-of-pub-2.rs b/tests/ui/parser/public-instead-of-pub-2.rs new file mode 100644 index 000000000..8a43c361e --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-2.rs @@ -0,0 +1,7 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// Won't give help message for this case + +public let x = 1; +//~^ ERROR expected one of `!` or `::`, found keyword `let` + +fn main() { } diff --git a/tests/ui/parser/public-instead-of-pub-2.stderr b/tests/ui/parser/public-instead-of-pub-2.stderr new file mode 100644 index 000000000..efe225656 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-2.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `let` + --> $DIR/public-instead-of-pub-2.rs:4:8 + | +LL | public let x = 1; + | ^^^ expected one of `!` or `::` + +error: aborting due to previous error + diff --git a/tests/ui/parser/public-instead-of-pub-3.fixed b/tests/ui/parser/public-instead-of-pub-3.fixed new file mode 100644 index 000000000..14f620f41 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-3.fixed @@ -0,0 +1,9 @@ +// run-rustfix +mod test { + pub const X: i32 = 123; + //~^ ERROR expected one of `!` or `::`, found keyword `const` +} + +fn main() { + println!("{}", test::X); +} diff --git a/tests/ui/parser/public-instead-of-pub-3.rs b/tests/ui/parser/public-instead-of-pub-3.rs new file mode 100644 index 000000000..ee27cb1a1 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-3.rs @@ -0,0 +1,9 @@ +// run-rustfix +mod test { + public const X: i32 = 123; + //~^ ERROR expected one of `!` or `::`, found keyword `const` +} + +fn main() { + println!("{}", test::X); +} diff --git a/tests/ui/parser/public-instead-of-pub-3.stderr b/tests/ui/parser/public-instead-of-pub-3.stderr new file mode 100644 index 000000000..72efae08d --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub-3.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found keyword `const` + --> $DIR/public-instead-of-pub-3.rs:3:12 + | +LL | public const X: i32 = 123; + | ^^^^^ expected one of `!` or `::` + | +help: write `pub` instead of `public` to make the item public + | +LL | pub const X: i32 = 123; + | ~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/public-instead-of-pub.fixed b/tests/ui/parser/public-instead-of-pub.fixed new file mode 100644 index 000000000..01db60999 --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub.fixed @@ -0,0 +1,8 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// edition:2018 +// run-rustfix +pub struct X; +//~^ ERROR expected one of `!` or `::`, found keyword `struct` +//~^^ HELP write `pub` instead of `public` to make the item public + +fn main() {} diff --git a/tests/ui/parser/public-instead-of-pub.rs b/tests/ui/parser/public-instead-of-pub.rs new file mode 100644 index 000000000..18e0fd3af --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub.rs @@ -0,0 +1,8 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// edition:2018 +// run-rustfix +public struct X; +//~^ ERROR expected one of `!` or `::`, found keyword `struct` +//~^^ HELP write `pub` instead of `public` to make the item public + +fn main() {} diff --git a/tests/ui/parser/public-instead-of-pub.stderr b/tests/ui/parser/public-instead-of-pub.stderr new file mode 100644 index 000000000..af875491e --- /dev/null +++ b/tests/ui/parser/public-instead-of-pub.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found keyword `struct` + --> $DIR/public-instead-of-pub.rs:4:8 + | +LL | public struct X; + | ^^^^^^ expected one of `!` or `::` + | +help: write `pub` instead of `public` to make the item public + | +LL | pub struct X; + | ~~~ + +error: aborting due to previous error + diff --git a/tests/ui/parser/qualified-path-in-turbofish.fixed b/tests/ui/parser/qualified-path-in-turbofish.fixed new file mode 100644 index 000000000..404d2f776 --- /dev/null +++ b/tests/ui/parser/qualified-path-in-turbofish.fixed @@ -0,0 +1,19 @@ +// run-rustfix +trait T { + type Ty; +} + +struct Impl; + +impl T for Impl { + type Ty = u32; +} + +fn template() -> i64 { + 3 +} + +fn main() { + template::<::Ty>(); + //~^ ERROR found single colon before projection in qualified path +} diff --git a/tests/ui/parser/qualified-path-in-turbofish.rs b/tests/ui/parser/qualified-path-in-turbofish.rs new file mode 100644 index 000000000..2f4b2ed34 --- /dev/null +++ b/tests/ui/parser/qualified-path-in-turbofish.rs @@ -0,0 +1,19 @@ +// run-rustfix +trait T { + type Ty; +} + +struct Impl; + +impl T for Impl { + type Ty = u32; +} + +fn template() -> i64 { + 3 +} + +fn main() { + template::<:Ty>(); + //~^ ERROR found single colon before projection in qualified path +} diff --git a/tests/ui/parser/qualified-path-in-turbofish.stderr b/tests/ui/parser/qualified-path-in-turbofish.stderr new file mode 100644 index 000000000..8857d2ef3 --- /dev/null +++ b/tests/ui/parser/qualified-path-in-turbofish.stderr @@ -0,0 +1,8 @@ +error: found single colon before projection in qualified path + --> $DIR/qualified-path-in-turbofish.rs:17:27 + | +LL | template::<:Ty>(); + | ^ help: use double colon: `::` + +error: aborting due to previous error + diff --git a/tests/ui/parser/range-3.rs b/tests/ui/parser/range-3.rs new file mode 100644 index 000000000..2c917a24e --- /dev/null +++ b/tests/ui/parser/range-3.rs @@ -0,0 +1,6 @@ +// Test range syntax - syntax errors. + +pub fn main() { + let r = 1..2..3; + //~^ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `..` +} diff --git a/tests/ui/parser/range-3.stderr b/tests/ui/parser/range-3.stderr new file mode 100644 index 000000000..340167f18 --- /dev/null +++ b/tests/ui/parser/range-3.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `..` + --> $DIR/range-3.rs:4:17 + | +LL | let r = 1..2..3; + | ^^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: aborting due to previous error + diff --git a/tests/ui/parser/range-4.rs b/tests/ui/parser/range-4.rs new file mode 100644 index 000000000..c970c96de --- /dev/null +++ b/tests/ui/parser/range-4.rs @@ -0,0 +1,6 @@ +// Test range syntax - syntax errors. + +pub fn main() { + let r = ..1..2; + //~^ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `..` +} diff --git a/tests/ui/parser/range-4.stderr b/tests/ui/parser/range-4.stderr new file mode 100644 index 000000000..720d48938 --- /dev/null +++ b/tests/ui/parser/range-4.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `..` + --> $DIR/range-4.rs:4:16 + | +LL | let r = ..1..2; + | ^^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: aborting due to previous error + diff --git a/tests/ui/parser/range-inclusive-extra-equals.rs b/tests/ui/parser/range-inclusive-extra-equals.rs new file mode 100644 index 000000000..d41c0699c --- /dev/null +++ b/tests/ui/parser/range-inclusive-extra-equals.rs @@ -0,0 +1,10 @@ +// Makes sure that a helpful message is shown when someone mistypes +// an inclusive range as `..==` rather than `..=`. This is an +// easy mistake, because of the resemblance to`==`. +// See #86395 for a bit of background. + +pub fn main() { + if let 1..==3 = 1 {} //~ERROR unexpected `=` after inclusive range + //~|HELP use `..=` instead + //~|NOTE inclusive ranges end with a single equals sign +} diff --git a/tests/ui/parser/range-inclusive-extra-equals.stderr b/tests/ui/parser/range-inclusive-extra-equals.stderr new file mode 100644 index 000000000..d37b6be4f --- /dev/null +++ b/tests/ui/parser/range-inclusive-extra-equals.stderr @@ -0,0 +1,10 @@ +error: unexpected `=` after inclusive range + --> $DIR/range-inclusive-extra-equals.rs:7:13 + | +LL | if let 1..==3 = 1 {} + | ^^^^ help: use `..=` instead + | + = note: inclusive ranges end with a single equals sign (`..=`) + +error: aborting due to previous error + diff --git a/tests/ui/parser/range_inclusive.fixed b/tests/ui/parser/range_inclusive.fixed new file mode 100644 index 000000000..fe23880d1 --- /dev/null +++ b/tests/ui/parser/range_inclusive.fixed @@ -0,0 +1,7 @@ +// run-rustfix +// Make sure that inclusive ranges with no end point don't parse. + +pub fn main() { + for _ in 1.. {} //~ERROR inclusive range with no end + //~^HELP use `..` instead +} diff --git a/tests/ui/parser/range_inclusive.rs b/tests/ui/parser/range_inclusive.rs new file mode 100644 index 000000000..bc6d2413d --- /dev/null +++ b/tests/ui/parser/range_inclusive.rs @@ -0,0 +1,7 @@ +// run-rustfix +// Make sure that inclusive ranges with no end point don't parse. + +pub fn main() { + for _ in 1..= {} //~ERROR inclusive range with no end + //~^HELP use `..` instead +} diff --git a/tests/ui/parser/range_inclusive.stderr b/tests/ui/parser/range_inclusive.stderr new file mode 100644 index 000000000..8a9178263 --- /dev/null +++ b/tests/ui/parser/range_inclusive.stderr @@ -0,0 +1,11 @@ +error[E0586]: inclusive range with no end + --> $DIR/range_inclusive.rs:5:15 + | +LL | for _ in 1..= {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/parser/range_inclusive_dotdotdot.rs b/tests/ui/parser/range_inclusive_dotdotdot.rs new file mode 100644 index 000000000..c3e600e77 --- /dev/null +++ b/tests/ui/parser/range_inclusive_dotdotdot.rs @@ -0,0 +1,23 @@ +// Make sure that inclusive ranges with `...` syntax don't parse. + +use std::ops::RangeToInclusive; + +fn return_range_to() -> RangeToInclusive { + return ...1; //~ERROR unexpected token: `...` + //~^HELP use `..` for an exclusive range + //~^^HELP or `..=` for an inclusive range +} + +pub fn main() { + let x = ...0; //~ERROR unexpected token: `...` + //~^HELP use `..` for an exclusive range + //~^^HELP or `..=` for an inclusive range + + let x = 5...5; //~ERROR unexpected token: `...` + //~^HELP use `..` for an exclusive range + //~^^HELP or `..=` for an inclusive range + + for _ in 0...1 {} //~ERROR unexpected token: `...` + //~^HELP use `..` for an exclusive range + //~^^HELP or `..=` for an inclusive range +} diff --git a/tests/ui/parser/range_inclusive_dotdotdot.stderr b/tests/ui/parser/range_inclusive_dotdotdot.stderr new file mode 100644 index 000000000..2dc2c87eb --- /dev/null +++ b/tests/ui/parser/range_inclusive_dotdotdot.stderr @@ -0,0 +1,62 @@ +error: unexpected token: `...` + --> $DIR/range_inclusive_dotdotdot.rs:6:12 + | +LL | return ...1; + | ^^^ + | +help: use `..` for an exclusive range + | +LL | return ..1; + | ~~ +help: or `..=` for an inclusive range + | +LL | return ..=1; + | ~~~ + +error: unexpected token: `...` + --> $DIR/range_inclusive_dotdotdot.rs:12:13 + | +LL | let x = ...0; + | ^^^ + | +help: use `..` for an exclusive range + | +LL | let x = ..0; + | ~~ +help: or `..=` for an inclusive range + | +LL | let x = ..=0; + | ~~~ + +error: unexpected token: `...` + --> $DIR/range_inclusive_dotdotdot.rs:16:14 + | +LL | let x = 5...5; + | ^^^ + | +help: use `..` for an exclusive range + | +LL | let x = 5..5; + | ~~ +help: or `..=` for an inclusive range + | +LL | let x = 5..=5; + | ~~~ + +error: unexpected token: `...` + --> $DIR/range_inclusive_dotdotdot.rs:20:15 + | +LL | for _ in 0...1 {} + | ^^^ + | +help: use `..` for an exclusive range + | +LL | for _ in 0..1 {} + | ~~ +help: or `..=` for an inclusive range + | +LL | for _ in 0..=1 {} + | ~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/ranges-precedence.rs b/tests/ui/parser/ranges-precedence.rs new file mode 100644 index 000000000..db241ed0c --- /dev/null +++ b/tests/ui/parser/ranges-precedence.rs @@ -0,0 +1,52 @@ +// run-pass +// Test that the precedence of ranges is correct + + + +struct Foo { + foo: usize, +} + +impl Foo { + fn bar(&self) -> usize { 5 } +} + +fn main() { + let x = 1+3..4+5; + assert_eq!(x, (4..9)); + + let x = 1..4+5; + assert_eq!(x, (1..9)); + + let x = 1+3..4; + assert_eq!(x, (4..4)); + + let a = Foo { foo: 3 }; + let x = a.foo..a.bar(); + assert_eq!(x, (3..5)); + + let x = 1+3..; + assert_eq!(x, (4..)); + let x = ..1+3; + assert_eq!(x, (..4)); + + let a = &[0, 1, 2, 3, 4, 5, 6]; + let x = &a[1+1..2+2]; + assert_eq!(x, &a[2..4]); + let x = &a[..1+2]; + assert_eq!(x, &a[..3]); + let x = &a[1+2..]; + assert_eq!(x, &a[3..]); + + for _i in 2+4..10-3 {} + + let i = 42; + for _ in 1..i {} + for _ in 1.. { break; } + + let x = [1]..[2]; + assert_eq!(x, (([1])..([2]))); + + let y = ..; + assert_eq!(y, (..)); +} diff --git a/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs new file mode 100644 index 000000000..bdfc29a3d --- /dev/null +++ b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs @@ -0,0 +1,5 @@ +// This won't actually panic because of the error comment -- the `"` needs to be +// the last byte in the file (including not having a trailing newline) +// Prior to the fix you get the error: 'expected item, found `r" ...`' +// because the string being unterminated wasn't properly detected. +r" //~ unterminated raw string diff --git a/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr new file mode 100644 index 000000000..3a7e2a4b1 --- /dev/null +++ b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr @@ -0,0 +1,9 @@ +error[E0748]: unterminated raw string + --> $DIR/issue-70677-panic-on-unterminated-raw-str-at-eof.rs:5:1 + | +LL | r" + | ^ unterminated raw string + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-byte-string-eof.rs b/tests/ui/parser/raw/raw-byte-string-eof.rs new file mode 100644 index 000000000..b74907b72 --- /dev/null +++ b/tests/ui/parser/raw/raw-byte-string-eof.rs @@ -0,0 +1,3 @@ +pub fn main() { + br##"a"#; //~ unterminated raw string +} diff --git a/tests/ui/parser/raw/raw-byte-string-eof.stderr b/tests/ui/parser/raw/raw-byte-string-eof.stderr new file mode 100644 index 000000000..a76668e80 --- /dev/null +++ b/tests/ui/parser/raw/raw-byte-string-eof.stderr @@ -0,0 +1,13 @@ +error[E0748]: unterminated raw string + --> $DIR/raw-byte-string-eof.rs:2:5 + | +LL | br##"a"#; + | ^ - help: consider terminating the string here: `##` + | | + | unterminated raw string + | + = note: this raw string should be terminated with `"##` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-byte-string-literals.rs b/tests/ui/parser/raw/raw-byte-string-literals.rs new file mode 100644 index 000000000..1b859fee5 --- /dev/null +++ b/tests/ui/parser/raw/raw-byte-string-literals.rs @@ -0,0 +1,7 @@ +// ignore-tidy-cr + +pub fn main() { + br"a "; //~ ERROR bare CR not allowed in raw string + br"é"; //~ ERROR non-ASCII character in raw byte string literal + br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation +} diff --git a/tests/ui/parser/raw/raw-byte-string-literals.stderr b/tests/ui/parser/raw/raw-byte-string-literals.stderr new file mode 100644 index 000000000..a2f27d1ed --- /dev/null +++ b/tests/ui/parser/raw/raw-byte-string-literals.stderr @@ -0,0 +1,20 @@ +error: bare CR not allowed in raw string + --> $DIR/raw-byte-string-literals.rs:4:9 + | +LL | br"a "; + | ^ + +error: non-ASCII character in raw byte string literal + --> $DIR/raw-byte-string-literals.rs:5:8 + | +LL | br"é"; + | ^ must be ASCII + +error: found invalid character; only `#` is allowed in raw string delimitation: ~ + --> $DIR/raw-byte-string-literals.rs:6:5 + | +LL | br##~"a"~##; + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/raw/raw-literal-keywords.rs b/tests/ui/parser/raw/raw-literal-keywords.rs new file mode 100644 index 000000000..a986980fa --- /dev/null +++ b/tests/ui/parser/raw/raw-literal-keywords.rs @@ -0,0 +1,25 @@ +fn test_if() { + r#if true { } //~ ERROR found keyword `true` +} + +fn test_struct() { + r#struct Test; //~ ERROR found `Test` +} + +fn test_union() { + r#union Test; //~ ERROR found `Test` +} + +fn test_if_2() { + let _ = r#if; //~ ERROR cannot find value `r#if` in this scope +} + +fn test_struct_2() { + let _ = r#struct; //~ ERROR cannot find value `r#struct` in this scope +} + +fn test_union_2() { + let _ = r#union; //~ ERROR cannot find value `union` in this scope +} + +fn main() {} diff --git a/tests/ui/parser/raw/raw-literal-keywords.stderr b/tests/ui/parser/raw/raw-literal-keywords.stderr new file mode 100644 index 000000000..f7b6c894a --- /dev/null +++ b/tests/ui/parser/raw/raw-literal-keywords.stderr @@ -0,0 +1,39 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found keyword `true` + --> $DIR/raw-literal-keywords.rs:2:10 + | +LL | r#if true { } + | ^^^^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` + --> $DIR/raw-literal-keywords.rs:6:14 + | +LL | r#struct Test; + | ^^^^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` + --> $DIR/raw-literal-keywords.rs:10:13 + | +LL | r#union Test; + | ^^^^ expected one of 8 possible tokens + +error[E0425]: cannot find value `r#if` in this scope + --> $DIR/raw-literal-keywords.rs:14:13 + | +LL | let _ = r#if; + | ^^^^ not found in this scope + +error[E0425]: cannot find value `r#struct` in this scope + --> $DIR/raw-literal-keywords.rs:18:13 + | +LL | let _ = r#struct; + | ^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `union` in this scope + --> $DIR/raw-literal-keywords.rs:22:13 + | +LL | let _ = r#union; + | ^^^^^^^ not found in this scope + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/raw/raw-literal-self.rs b/tests/ui/parser/raw/raw-literal-self.rs new file mode 100644 index 000000000..a0c9e24c2 --- /dev/null +++ b/tests/ui/parser/raw/raw-literal-self.rs @@ -0,0 +1,4 @@ +fn main() { + let r#self: (); + //~^ ERROR `self` cannot be a raw identifier +} diff --git a/tests/ui/parser/raw/raw-literal-self.stderr b/tests/ui/parser/raw/raw-literal-self.stderr new file mode 100644 index 000000000..2a40dfe20 --- /dev/null +++ b/tests/ui/parser/raw/raw-literal-self.stderr @@ -0,0 +1,8 @@ +error: `self` cannot be a raw identifier + --> $DIR/raw-literal-self.rs:2:9 + | +LL | let r#self: (); + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/raw/raw-literal-underscore.rs b/tests/ui/parser/raw/raw-literal-underscore.rs new file mode 100644 index 000000000..a9d9e13a9 --- /dev/null +++ b/tests/ui/parser/raw/raw-literal-underscore.rs @@ -0,0 +1,4 @@ +fn main() { + let r#_: (); + //~^ ERROR `_` cannot be a raw identifier +} diff --git a/tests/ui/parser/raw/raw-literal-underscore.stderr b/tests/ui/parser/raw/raw-literal-underscore.stderr new file mode 100644 index 000000000..d7a364d85 --- /dev/null +++ b/tests/ui/parser/raw/raw-literal-underscore.stderr @@ -0,0 +1,8 @@ +error: `_` cannot be a raw identifier + --> $DIR/raw-literal-underscore.rs:2:9 + | +LL | let r#_: (); + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/raw/raw-str-delim.rs b/tests/ui/parser/raw/raw-str-delim.rs new file mode 100644 index 000000000..2f13893ce --- /dev/null +++ b/tests/ui/parser/raw/raw-str-delim.rs @@ -0,0 +1,3 @@ +static s: &'static str = + r#~"#"~# //~ ERROR found invalid character; only `#` is allowed in raw string delimitation +; diff --git a/tests/ui/parser/raw/raw-str-delim.stderr b/tests/ui/parser/raw/raw-str-delim.stderr new file mode 100644 index 000000000..8a04f99a1 --- /dev/null +++ b/tests/ui/parser/raw/raw-str-delim.stderr @@ -0,0 +1,8 @@ +error: found invalid character; only `#` is allowed in raw string delimitation: ~ + --> $DIR/raw-str-delim.rs:2:5 + | +LL | r#~"#"~# + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/raw/raw-str-in-macro-call.rs b/tests/ui/parser/raw/raw-str-in-macro-call.rs new file mode 100644 index 000000000..462c2279f --- /dev/null +++ b/tests/ui/parser/raw/raw-str-in-macro-call.rs @@ -0,0 +1,14 @@ +// check-pass + +macro_rules! m1 { + ($tt:tt #) => () +} + +macro_rules! m2 { + ($tt:tt) => () +} + +fn main() { + m1!(r#"abc"##); + m2!(r#"abc"#); +} diff --git a/tests/ui/parser/raw/raw-str-unbalanced.rs b/tests/ui/parser/raw/raw-str-unbalanced.rs new file mode 100644 index 000000000..38537f8b3 --- /dev/null +++ b/tests/ui/parser/raw/raw-str-unbalanced.rs @@ -0,0 +1,22 @@ +static s: &'static str = + r#""## //~ ERROR too many `#` when terminating raw string +; + +static s2: &'static str = + r#" + "#### //~ ERROR too many `#` when terminating raw string +; + +const A: &'static str = r"" //~ ERROR expected `;`, found `#` + +// Test +#[test] +fn test() {} + +const B: &'static str = r""## //~ ERROR too many `#` when terminating raw string + +// Test +#[test] +fn test2() {} + +fn main() {} diff --git a/tests/ui/parser/raw/raw-str-unbalanced.stderr b/tests/ui/parser/raw/raw-str-unbalanced.stderr new file mode 100644 index 000000000..eac8c06c1 --- /dev/null +++ b/tests/ui/parser/raw/raw-str-unbalanced.stderr @@ -0,0 +1,36 @@ +error: too many `#` when terminating raw string + --> $DIR/raw-str-unbalanced.rs:2:10 + | +LL | r#""## + | -----^ help: remove the extra `#` + | | + | this raw string started with 1 `#` + +error: too many `#` when terminating raw string + --> $DIR/raw-str-unbalanced.rs:7:9 + | +LL | / r#" +LL | | "#### + | | -^^^ help: remove the extra `#`s + | |________| + | this raw string started with 1 `#` + +error: expected `;`, found `#` + --> $DIR/raw-str-unbalanced.rs:10:28 + | +LL | const A: &'static str = r"" + | ^ help: add `;` here +... +LL | #[test] + | - unexpected token + +error: too many `#` when terminating raw string + --> $DIR/raw-str-unbalanced.rs:16:28 + | +LL | const B: &'static str = r""## + | ---^^ help: remove the extra `#`s + | | + | this raw string started with 0 `#`s + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/raw/raw-str-unterminated.rs b/tests/ui/parser/raw/raw-str-unterminated.rs new file mode 100644 index 000000000..fd3172955 --- /dev/null +++ b/tests/ui/parser/raw/raw-str-unterminated.rs @@ -0,0 +1,4 @@ +static s: &'static str = + r#" string literal goes on + and on + //~^^ ERROR unterminated raw string diff --git a/tests/ui/parser/raw/raw-str-unterminated.stderr b/tests/ui/parser/raw/raw-str-unterminated.stderr new file mode 100644 index 000000000..077f763f1 --- /dev/null +++ b/tests/ui/parser/raw/raw-str-unterminated.stderr @@ -0,0 +1,11 @@ +error[E0748]: unterminated raw string + --> $DIR/raw-str-unterminated.rs:2:5 + | +LL | r#" string literal goes on + | ^ unterminated raw string + | + = note: this raw string should be terminated with `"#` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-string-2.rs b/tests/ui/parser/raw/raw-string-2.rs new file mode 100644 index 000000000..067332d28 --- /dev/null +++ b/tests/ui/parser/raw/raw-string-2.rs @@ -0,0 +1,4 @@ +fn main() { + let x = r###"here's a long string"# "# "##; + //~^ ERROR unterminated raw string +} diff --git a/tests/ui/parser/raw/raw-string-2.stderr b/tests/ui/parser/raw/raw-string-2.stderr new file mode 100644 index 000000000..8bbac9d7b --- /dev/null +++ b/tests/ui/parser/raw/raw-string-2.stderr @@ -0,0 +1,11 @@ +error[E0748]: unterminated raw string + --> $DIR/raw-string-2.rs:2:13 + | +LL | let x = r###"here's a long string"# "# "##; + | ^ unterminated raw string -- help: consider terminating the string here: `###` + | + = note: this raw string should be terminated with `"###` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/raw/raw-string.rs b/tests/ui/parser/raw/raw-string.rs new file mode 100644 index 000000000..84f07c4a9 --- /dev/null +++ b/tests/ui/parser/raw/raw-string.rs @@ -0,0 +1,4 @@ +fn main() { + let x = r##"lol"#; + //~^ ERROR unterminated raw string +} diff --git a/tests/ui/parser/raw/raw-string.stderr b/tests/ui/parser/raw/raw-string.stderr new file mode 100644 index 000000000..b2b853a89 --- /dev/null +++ b/tests/ui/parser/raw/raw-string.stderr @@ -0,0 +1,13 @@ +error[E0748]: unterminated raw string + --> $DIR/raw-string.rs:2:13 + | +LL | let x = r##"lol"#; + | ^ - help: consider terminating the string here: `##` + | | + | unterminated raw string + | + = note: this raw string should be terminated with `"##` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0748`. diff --git a/tests/ui/parser/recover-assoc-const-constraint.rs b/tests/ui/parser/recover-assoc-const-constraint.rs new file mode 100644 index 000000000..1453e6cb5 --- /dev/null +++ b/tests/ui/parser/recover-assoc-const-constraint.rs @@ -0,0 +1,9 @@ +#[cfg(FALSE)] +fn syntax() { + bar::(); + //~^ ERROR associated const equality is incomplete + bar::(); + //~^ ERROR associated const equality is incomplete +} + +fn main() {} diff --git a/tests/ui/parser/recover-assoc-const-constraint.stderr b/tests/ui/parser/recover-assoc-const-constraint.stderr new file mode 100644 index 000000000..2d36ce4e9 --- /dev/null +++ b/tests/ui/parser/recover-assoc-const-constraint.stderr @@ -0,0 +1,21 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:3:11 + | +LL | bar::(); + | ^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:5:11 + | +LL | bar::(); + | ^^^^^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/recover-assoc-eq-missing-term.rs b/tests/ui/parser/recover-assoc-eq-missing-term.rs new file mode 100644 index 000000000..4b42c44dc --- /dev/null +++ b/tests/ui/parser/recover-assoc-eq-missing-term.rs @@ -0,0 +1,6 @@ +#[cfg(FALSE)] +fn syntax() { + bar::(); //~ ERROR missing type to the right of `=` +} + +fn main() {} diff --git a/tests/ui/parser/recover-assoc-eq-missing-term.stderr b/tests/ui/parser/recover-assoc-eq-missing-term.stderr new file mode 100644 index 000000000..152f7f2fb --- /dev/null +++ b/tests/ui/parser/recover-assoc-eq-missing-term.stderr @@ -0,0 +1,18 @@ +error: missing type to the right of `=` + --> $DIR/recover-assoc-eq-missing-term.rs:3:17 + | +LL | bar::(); + | ^^^ + | +help: to constrain the associated type, add a type after `=` + | +LL | bar::(); + | +++++++ +help: remove the `=` if `Item` is a type + | +LL - bar::(); +LL + bar::(); + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover-assoc-lifetime-constraint.rs new file mode 100644 index 000000000..558fcdfe1 --- /dev/null +++ b/tests/ui/parser/recover-assoc-lifetime-constraint.rs @@ -0,0 +1,6 @@ +#[cfg(FALSE)] +fn syntax() { + bar::(); //~ ERROR associated lifetimes are not supported +} + +fn main() {} diff --git a/tests/ui/parser/recover-assoc-lifetime-constraint.stderr b/tests/ui/parser/recover-assoc-lifetime-constraint.stderr new file mode 100644 index 000000000..79437533d --- /dev/null +++ b/tests/ui/parser/recover-assoc-lifetime-constraint.stderr @@ -0,0 +1,12 @@ +error: associated lifetimes are not supported + --> $DIR/recover-assoc-lifetime-constraint.rs:3:11 + | +LL | bar::(); + | ^^^^^^^-- + | | + | the lifetime is given here + | + = help: if you meant to specify a trait object, write `dyn Trait + 'lifetime` + +error: aborting due to previous error + diff --git a/tests/ui/parser/recover-const-async-fn-ptr.rs b/tests/ui/parser/recover-const-async-fn-ptr.rs new file mode 100644 index 000000000..25af8772c --- /dev/null +++ b/tests/ui/parser/recover-const-async-fn-ptr.rs @@ -0,0 +1,25 @@ +// edition:2018 + +type T0 = const fn(); //~ ERROR an `fn` pointer type cannot be `const` +type T1 = const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +type T2 = const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const` +type T3 = async fn(); //~ ERROR an `fn` pointer type cannot be `async` +type T4 = async extern fn(); //~ ERROR an `fn` pointer type cannot be `async` +type T5 = async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +type T6 = const async unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `const` +//~| ERROR an `fn` pointer type cannot be `async` + +type FT0 = for<'a> const fn(); //~ ERROR an `fn` pointer type cannot be `const` +type FT1 = for<'a> const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +type FT2 = for<'a> const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const` +type FT3 = for<'a> async fn(); //~ ERROR an `fn` pointer type cannot be `async` +type FT4 = for<'a> async extern fn(); //~ ERROR an `fn` pointer type cannot be `async` +type FT5 = for<'a> async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +type FT6 = for<'a> const async unsafe extern "C" fn(); +//~^ ERROR an `fn` pointer type cannot be `const` +//~| ERROR an `fn` pointer type cannot be `async` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/recover-const-async-fn-ptr.stderr b/tests/ui/parser/recover-const-async-fn-ptr.stderr new file mode 100644 index 000000000..7012096b6 --- /dev/null +++ b/tests/ui/parser/recover-const-async-fn-ptr.stderr @@ -0,0 +1,155 @@ +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:3:11 + | +LL | type T0 = const fn(); + | -----^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:4:11 + | +LL | type T1 = const extern "C" fn(); + | -----^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:5:11 + | +LL | type T2 = const unsafe extern fn(); + | -----^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:6:11 + | +LL | type T3 = async fn(); + | -----^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:7:11 + | +LL | type T4 = async extern fn(); + | -----^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:8:11 + | +LL | type T5 = async unsafe extern "C" fn(); + | -----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:9:11 + | +LL | type T6 = const async unsafe extern "C" fn(); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:9:11 + | +LL | type T6 = const async unsafe extern "C" fn(); + | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:13:12 + | +LL | type FT0 = for<'a> const fn(); + | ^^^^^^^^-----^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:14:12 + | +LL | type FT1 = for<'a> const extern "C" fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:15:12 + | +LL | type FT2 = for<'a> const unsafe extern fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:16:12 + | +LL | type FT3 = for<'a> async fn(); + | ^^^^^^^^-----^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:17:12 + | +LL | type FT4 = for<'a> async extern fn(); + | ^^^^^^^^-----^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:18:12 + | +LL | type FT5 = for<'a> async unsafe extern "C" fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error: an `fn` pointer type cannot be `const` + --> $DIR/recover-const-async-fn-ptr.rs:19:12 + | +LL | type FT6 = for<'a> const async unsafe extern "C" fn(); + | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `const` because of this + | help: remove the `const` qualifier + +error: an `fn` pointer type cannot be `async` + --> $DIR/recover-const-async-fn-ptr.rs:19:12 + | +LL | type FT6 = for<'a> const async unsafe extern "C" fn(); + | ^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | help: remove the `async` qualifier + +error[E0308]: mismatched types + --> $DIR/recover-const-async-fn-ptr.rs:24:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-enum.rs b/tests/ui/parser/recover-enum.rs new file mode 100644 index 000000000..08dd939e2 --- /dev/null +++ b/tests/ui/parser/recover-enum.rs @@ -0,0 +1,11 @@ +fn main() { + enum Test { + Very //~ HELP missing `,` + Bad(usize) //~ HELP missing `,` + //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad` + Stuff { a: usize } //~ HELP missing `,` + //~^ ERROR expected one of `,`, `=`, or `}`, found `Stuff` + Here + //~^ ERROR expected one of `,`, `=`, or `}`, found `Here` + } +} diff --git a/tests/ui/parser/recover-enum.stderr b/tests/ui/parser/recover-enum.stderr new file mode 100644 index 000000000..a2b650e4f --- /dev/null +++ b/tests/ui/parser/recover-enum.stderr @@ -0,0 +1,37 @@ +error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad` + --> $DIR/recover-enum.rs:4:9 + | +LL | Very + | - + | | + | expected one of `(`, `,`, `=`, `{`, or `}` + | help: missing `,` +LL | Bad(usize) + | ^^^ unexpected token + +error: expected one of `,`, `=`, or `}`, found `Stuff` + --> $DIR/recover-enum.rs:6:9 + | +LL | Bad(usize) + | - + | | + | expected one of `,`, `=`, or `}` + | help: missing `,` +LL | +LL | Stuff { a: usize } + | ^^^^^ unexpected token + +error: expected one of `,`, `=`, or `}`, found `Here` + --> $DIR/recover-enum.rs:8:9 + | +LL | Stuff { a: usize } + | - + | | + | expected one of `,`, `=`, or `}` + | help: missing `,` +LL | +LL | Here + | ^^^^ unexpected token + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/recover-enum2.rs b/tests/ui/parser/recover-enum2.rs new file mode 100644 index 000000000..0c9420889 --- /dev/null +++ b/tests/ui/parser/recover-enum2.rs @@ -0,0 +1,28 @@ +fn main() { + enum Test { + Var1, + Var2(String), + Var3 { + abc: {}, //~ ERROR: expected type, found `{` + }, + } + + // recover... + let a = 1; + enum Test2 { + Fine, + } + + enum Test3 { + StillFine { + def: i32, + }, + } + + { + // fail again + enum Test4 { + Nope(i32 {}) //~ ERROR: found `{` + } + } +} diff --git a/tests/ui/parser/recover-enum2.stderr b/tests/ui/parser/recover-enum2.stderr new file mode 100644 index 000000000..7634bca92 --- /dev/null +++ b/tests/ui/parser/recover-enum2.stderr @@ -0,0 +1,16 @@ +error: expected type, found `{` + --> $DIR/recover-enum2.rs:6:18 + | +LL | Var3 { + | ---- while parsing this struct +LL | abc: {}, + | ^ expected type + +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{` + --> $DIR/recover-enum2.rs:25:22 + | +LL | Nope(i32 {}) + | ^ expected one of 7 possible tokens + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs b/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs new file mode 100644 index 000000000..e815c7611 --- /dev/null +++ b/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.rs @@ -0,0 +1,6 @@ +struct TypedArenaChunk { + next: Option> + //~^ ERROR unmatched angle bracket +} + +fn main() {} diff --git a/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr b/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr new file mode 100644 index 000000000..17237c930 --- /dev/null +++ b/tests/ui/parser/recover-field-extra-angle-brackets-in-struct-with-a-field.stderr @@ -0,0 +1,11 @@ +error: unmatched angle bracket + --> $DIR/recover-field-extra-angle-brackets-in-struct-with-a-field.rs:2:25 + | +LL | next: Option> + | _________________________^ +LL | | +LL | | } + | |_ help: remove extra angle bracket + +error: aborting due to previous error + diff --git a/tests/ui/parser/recover-field-extra-angle-brackets.rs b/tests/ui/parser/recover-field-extra-angle-brackets.rs new file mode 100644 index 000000000..5e0e00bcb --- /dev/null +++ b/tests/ui/parser/recover-field-extra-angle-brackets.rs @@ -0,0 +1,14 @@ +// Tests that we recover from extra trailing angle brackets +// in a struct field + +struct BadStruct { + first: Vec>, //~ ERROR unmatched angle bracket + second: bool +} + +fn bar(val: BadStruct) { + val.first; + val.second; +} + +fn main() {} diff --git a/tests/ui/parser/recover-field-extra-angle-brackets.stderr b/tests/ui/parser/recover-field-extra-angle-brackets.stderr new file mode 100644 index 000000000..318e55f6e --- /dev/null +++ b/tests/ui/parser/recover-field-extra-angle-brackets.stderr @@ -0,0 +1,8 @@ +error: unmatched angle bracket + --> $DIR/recover-field-extra-angle-brackets.rs:5:19 + | +LL | first: Vec>, + | ^ help: remove extra angle bracket + +error: aborting due to previous error + diff --git a/tests/ui/parser/recover-field-semi.rs b/tests/ui/parser/recover-field-semi.rs new file mode 100644 index 000000000..b70357886 --- /dev/null +++ b/tests/ui/parser/recover-field-semi.rs @@ -0,0 +1,16 @@ +struct Foo { + foo: i32; + //~^ ERROR struct fields are separated by `,` +} + +union Bar { //~ ERROR + foo: i32; + //~^ ERROR union fields are separated by `,` +} + +enum Baz { + Qux { foo: i32; } + //~^ ERROR struct fields are separated by `,` +} + +fn main() {} diff --git a/tests/ui/parser/recover-field-semi.stderr b/tests/ui/parser/recover-field-semi.stderr new file mode 100644 index 000000000..3cf484748 --- /dev/null +++ b/tests/ui/parser/recover-field-semi.stderr @@ -0,0 +1,35 @@ +error: struct fields are separated by `,` + --> $DIR/recover-field-semi.rs:2:13 + | +LL | struct Foo { + | --- while parsing this struct +LL | foo: i32; + | ^ help: replace `;` with `,` + +error: union fields are separated by `,` + --> $DIR/recover-field-semi.rs:7:13 + | +LL | union Bar { + | --- while parsing this union +LL | foo: i32; + | ^ help: replace `;` with `,` + +error: struct fields are separated by `,` + --> $DIR/recover-field-semi.rs:12:19 + | +LL | Qux { foo: i32; } + | --- ^ help: replace `;` with `,` + | | + | while parsing this struct + +error: unions cannot have zero fields + --> $DIR/recover-field-semi.rs:6:1 + | +LL | / union Bar { +LL | | foo: i32; +LL | | +LL | | } + | |_^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.rs b/tests/ui/parser/recover-fn-ptr-with-generics.rs new file mode 100644 index 000000000..31de418be --- /dev/null +++ b/tests/ui/parser/recover-fn-ptr-with-generics.rs @@ -0,0 +1,31 @@ +fn main() { + type Predicate = fn<'a>(&'a str) -> bool; + //~^ ERROR function pointer types may not have generic parameters + + type Identity = fn(T) -> T; + //~^ ERROR function pointer types may not have generic parameters + //~| ERROR cannot find type `T` in this scope + //~| ERROR cannot find type `T` in this scope + + let _: fn(); + //~^ ERROR function pointer types may not have generic parameters + + let _: for<'outer> fn<'inner>(); + //~^ ERROR function pointer types may not have generic parameters + + let _: for<> fn<'r>(); + //~^ ERROR function pointer types may not have generic parameters + + type Hmm = fn<>(); + //~^ ERROR function pointer types may not have generic parameters + + let _: extern fn<'a: 'static>(); + //~^ ERROR function pointer types may not have generic parameters + //~| ERROR lifetime bounds cannot be used in this context + + let _: for<'any> extern "C" fn<'u>(); + //~^ ERROR function pointer types may not have generic parameters + + type QuiteBroken = fn(); + //~^ ERROR expected identifier, found `>` +} diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover-fn-ptr-with-generics.stderr new file mode 100644 index 000000000..1da9c1857 --- /dev/null +++ b/tests/ui/parser/recover-fn-ptr-with-generics.stderr @@ -0,0 +1,111 @@ +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:2:24 + | +LL | type Predicate = fn<'a>(&'a str) -> bool; + | ^^^^ + | +help: consider moving the lifetime parameter to a `for` parameter list + | +LL - type Predicate = fn<'a>(&'a str) -> bool; +LL + type Predicate = for<'a> fn(&'a str) -> bool; + | + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:5:23 + | +LL | type Identity = fn(T) -> T; + | ^^^ + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:10:14 + | +LL | let _: fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider moving the lifetime parameters to a `for` parameter list + | +LL - let _: fn(); +LL + let _: for<'e, 'f> fn(); + | + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:13:26 + | +LL | let _: for<'outer> fn<'inner>(); + | ^^^^^^^^ + | +help: consider moving the lifetime parameter to the `for` parameter list + | +LL - let _: for<'outer> fn<'inner>(); +LL + let _: for<'outer, 'inner> fn(); + | + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:16:20 + | +LL | let _: for<> fn<'r>(); + | ^^^^ + | +help: consider moving the lifetime parameter to the `for` parameter list + | +LL - let _: for<> fn<'r>(); +LL + let _: for<'r> fn(); + | + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:19:18 + | +LL | type Hmm = fn<>(); + | ^^ + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:22:21 + | +LL | let _: extern fn<'a: 'static>(); + | ^^^^^^^^^^^^^ + | +help: consider moving the lifetime parameter to a `for` parameter list + | +LL - let _: extern fn<'a: 'static>(); +LL + let _: for<'a> extern fn(); + | + +error: function pointer types may not have generic parameters + --> $DIR/recover-fn-ptr-with-generics.rs:26:35 + | +LL | let _: for<'any> extern "C" fn<'u>(); + | ^^^^ + | +help: consider moving the lifetime parameter to the `for` parameter list + | +LL - let _: for<'any> extern "C" fn<'u>(); +LL + let _: for<'any, 'u> extern "C" fn(); + | + +error: expected identifier, found `>` + --> $DIR/recover-fn-ptr-with-generics.rs:29:32 + | +LL | type QuiteBroken = fn(); + | ^ expected identifier + +error: lifetime bounds cannot be used in this context + --> $DIR/recover-fn-ptr-with-generics.rs:22:26 + | +LL | let _: extern fn<'a: 'static>(); + | ^^^^^^^ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/recover-fn-ptr-with-generics.rs:5:27 + | +LL | type Identity = fn(T) -> T; + | ^ not found in this scope + +error[E0412]: cannot find type `T` in this scope + --> $DIR/recover-fn-ptr-with-generics.rs:5:33 + | +LL | type Identity = fn(T) -> T; + | ^ not found in this scope + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/recover-fn-trait-from-fn-kw.rs b/tests/ui/parser/recover-fn-trait-from-fn-kw.rs new file mode 100644 index 000000000..b6611e627 --- /dev/null +++ b/tests/ui/parser/recover-fn-trait-from-fn-kw.rs @@ -0,0 +1,12 @@ +fn foo(_: impl fn() -> i32) {} +//~^ ERROR expected identifier, found keyword `fn` + +fn foo2(_: T) {} +//~^ ERROR expected identifier, found keyword `fn` + +fn main() { + foo(|| ()); + //~^ mismatched types + foo2(|_: ()| {}); + //~^ type mismatch in closure arguments +} diff --git a/tests/ui/parser/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover-fn-trait-from-fn-kw.stderr new file mode 100644 index 000000000..3681a796c --- /dev/null +++ b/tests/ui/parser/recover-fn-trait-from-fn-kw.stderr @@ -0,0 +1,48 @@ +error: expected identifier, found keyword `fn` + --> $DIR/recover-fn-trait-from-fn-kw.rs:1:16 + | +LL | fn foo(_: impl fn() -> i32) {} + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn foo(_: impl Fn() -> i32) {} + | ~~ + +error: expected identifier, found keyword `fn` + --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12 + | +LL | fn foo2(_: T) {} + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn foo2(_: T) {} + | ~~ + +error[E0308]: mismatched types + --> $DIR/recover-fn-trait-from-fn-kw.rs:8:12 + | +LL | foo(|| ()); + | ^^ expected `i32`, found `()` + +error[E0631]: type mismatch in closure arguments + --> $DIR/recover-fn-trait-from-fn-kw.rs:10:5 + | +LL | foo2(|_: ()| {}); + | ^^^^ ------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(i32) -> _` + found closure signature `fn(()) -> _` +note: required by a bound in `foo2` + --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12 + | +LL | fn foo2(_: T) {} + | ^^^^^^^ required by this bound in `foo2` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-for-loop-parens-around-head.rs b/tests/ui/parser/recover-for-loop-parens-around-head.rs new file mode 100644 index 000000000..053b428bd --- /dev/null +++ b/tests/ui/parser/recover-for-loop-parens-around-head.rs @@ -0,0 +1,15 @@ +// Here we test that the parser is able to recover in a situation like +// `for ( $pat in $expr )` since that is familiar syntax in other languages. +// Instead we suggest that the user writes `for $pat in $expr`. + +#![deny(unused)] // Make sure we don't trigger `unused_parens`. + +fn main() { + let vec = vec![1, 2, 3]; + + for ( elem in vec ) { + //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in` + //~| ERROR unexpected parentheses surrounding `for` loop head + const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types + } +} diff --git a/tests/ui/parser/recover-for-loop-parens-around-head.stderr b/tests/ui/parser/recover-for-loop-parens-around-head.stderr new file mode 100644 index 000000000..3bad29f20 --- /dev/null +++ b/tests/ui/parser/recover-for-loop-parens-around-head.stderr @@ -0,0 +1,27 @@ +error: expected one of `)`, `,`, `@`, or `|`, found keyword `in` + --> $DIR/recover-for-loop-parens-around-head.rs:10:16 + | +LL | for ( elem in vec ) { + | ^^ expected one of `)`, `,`, `@`, or `|` + +error: unexpected parentheses surrounding `for` loop head + --> $DIR/recover-for-loop-parens-around-head.rs:10:9 + | +LL | for ( elem in vec ) { + | ^ ^ + | +help: remove parentheses in `for` loop + | +LL - for ( elem in vec ) { +LL + for elem in vec { + | + +error[E0308]: mismatched types + --> $DIR/recover-for-loop-parens-around-head.rs:13:38 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected `()`, found integer + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-from-bad-variant.rs b/tests/ui/parser/recover-from-bad-variant.rs new file mode 100644 index 000000000..e8887147c --- /dev/null +++ b/tests/ui/parser/recover-from-bad-variant.rs @@ -0,0 +1,15 @@ +enum Enum { + Foo { a: usize, b: usize }, + Bar(usize, usize), +} + +fn main() { + let x = Enum::Foo(a: 3, b: 4); + //~^ ERROR invalid `struct` delimiters or `fn` call arguments + match x { + Enum::Foo(a, b) => {} + //~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo` + Enum::Bar { a, b } => {} + //~^ ERROR tuple variant `Enum::Bar` written as struct variant + } +} diff --git a/tests/ui/parser/recover-from-bad-variant.stderr b/tests/ui/parser/recover-from-bad-variant.stderr new file mode 100644 index 000000000..04968bbdf --- /dev/null +++ b/tests/ui/parser/recover-from-bad-variant.stderr @@ -0,0 +1,37 @@ +error: invalid `struct` delimiters or `fn` call arguments + --> $DIR/recover-from-bad-variant.rs:7:13 + | +LL | let x = Enum::Foo(a: 3, b: 4); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: if `Enum::Foo` is a struct, use braces as delimiters + | +LL | let x = Enum::Foo { a: 3, b: 4 }; + | ~ ~ +help: if `Enum::Foo` is a function, use the arguments directly + | +LL - let x = Enum::Foo(a: 3, b: 4); +LL + let x = Enum::Foo(3, 4); + | + +error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum::Foo` + --> $DIR/recover-from-bad-variant.rs:10:9 + | +LL | Enum::Foo(a, b) => {} + | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error[E0769]: tuple variant `Enum::Bar` written as struct variant + --> $DIR/recover-from-bad-variant.rs:12:9 + | +LL | Enum::Bar { a, b } => {} + | ^^^^^^^^^^^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | Enum::Bar(a, b) => {} + | ~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0164, E0769. +For more information about an error, try `rustc --explain E0164`. diff --git a/tests/ui/parser/recover-from-homoglyph.rs b/tests/ui/parser/recover-from-homoglyph.rs new file mode 100644 index 000000000..99ce0d1a6 --- /dev/null +++ b/tests/ui/parser/recover-from-homoglyph.rs @@ -0,0 +1,4 @@ +fn main() { + println!(""); //~ ERROR unknown start of token: \u{37e} + let x: usize = (); //~ ERROR mismatched types +} diff --git a/tests/ui/parser/recover-from-homoglyph.stderr b/tests/ui/parser/recover-from-homoglyph.stderr new file mode 100644 index 000000000..f11ca9fd5 --- /dev/null +++ b/tests/ui/parser/recover-from-homoglyph.stderr @@ -0,0 +1,22 @@ +error: unknown start of token: \u{37e} + --> $DIR/recover-from-homoglyph.rs:2:17 + | +LL | println!(""); + | ^ + | +help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not + | +LL | println!(""); + | ~ + +error[E0308]: mismatched types + --> $DIR/recover-from-homoglyph.rs:3:20 + | +LL | let x: usize = (); + | ----- ^^ expected `usize`, found `()` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-labeled-non-block-expr.fixed b/tests/ui/parser/recover-labeled-non-block-expr.fixed new file mode 100644 index 000000000..c2e76444d --- /dev/null +++ b/tests/ui/parser/recover-labeled-non-block-expr.fixed @@ -0,0 +1,26 @@ +// run-rustfix +fn main() { + let _ = 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + + match () { () => {}, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + 'label: { match () { () => break 'label, } }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + #[allow(unused_labels)] + 'label: { match () { () => 'lp: loop { break 'lp 0 }, } }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + + let x = 1; + let _i = 'label: { match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label + 0 => 42, + 1 if false => break 'label 17, + 1 => { + if true { + break 'label 13 + } else { + break 'label 0; + } + } + _ => 1, + } }; + + let other = 3; + let _val = 'label: { (1, if other == 3 { break 'label (2, 3) } else { other }) }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label +} diff --git a/tests/ui/parser/recover-labeled-non-block-expr.rs b/tests/ui/parser/recover-labeled-non-block-expr.rs new file mode 100644 index 000000000..fc11c646a --- /dev/null +++ b/tests/ui/parser/recover-labeled-non-block-expr.rs @@ -0,0 +1,26 @@ +// run-rustfix +fn main() { + let _ = 'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + + 'label: match () { () => {}, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + 'label: match () { () => break 'label, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + #[allow(unused_labels)] + 'label: match () { () => 'lp: loop { break 'lp 0 }, }; //~ ERROR expected `while`, `for`, `loop` or `{` after a label + + let x = 1; + let _i = 'label: match x { //~ ERROR expected `while`, `for`, `loop` or `{` after a label + 0 => 42, + 1 if false => break 'label 17, + 1 => { + if true { + break 'label 13 + } else { + break 'label 0; + } + } + _ => 1, + }; + + let other = 3; + let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other }); //~ ERROR expected `while`, `for`, `loop` or `{` after a label +} diff --git a/tests/ui/parser/recover-labeled-non-block-expr.stderr b/tests/ui/parser/recover-labeled-non-block-expr.stderr new file mode 100644 index 000000000..d66ce6950 --- /dev/null +++ b/tests/ui/parser/recover-labeled-non-block-expr.stderr @@ -0,0 +1,74 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/recover-labeled-non-block-expr.rs:3:21 + | +LL | let _ = 'label: 1 + 1; + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider removing the label + | +LL - let _ = 'label: 1 + 1; +LL + let _ = 1 + 1; + | + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/recover-labeled-non-block-expr.rs:5:13 + | +LL | 'label: match () { () => {}, }; + | ^^^^^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider removing the label + | +LL - 'label: match () { () => {}, }; +LL + match () { () => {}, }; + | + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/recover-labeled-non-block-expr.rs:6:13 + | +LL | 'label: match () { () => break 'label, }; + | ^^^^^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider enclosing expression in a block + | +LL | 'label: { match () { () => break 'label, } }; + | + + + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/recover-labeled-non-block-expr.rs:8:13 + | +LL | 'label: match () { () => 'lp: loop { break 'lp 0 }, }; + | ^^^^^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider enclosing expression in a block + | +LL | 'label: { match () { () => 'lp: loop { break 'lp 0 }, } }; + | + + + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/recover-labeled-non-block-expr.rs:11:22 + | +LL | let _i = 'label: match x { + | ^^^^^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider enclosing expression in a block + | +LL ~ let _i = 'label: { match x { +LL | 0 => 42, + ... +LL | _ => 1, +LL ~ } }; + | + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/recover-labeled-non-block-expr.rs:25:24 + | +LL | let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other }); + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider enclosing expression in a block + | +LL | let _val = 'label: { (1, if other == 3 { break 'label (2, 3) } else { other }) }; + | + + + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/recover-missing-semi-before-item.fixed b/tests/ui/parser/recover-missing-semi-before-item.fixed new file mode 100644 index 000000000..0be17e69e --- /dev/null +++ b/tests/ui/parser/recover-missing-semi-before-item.fixed @@ -0,0 +1,61 @@ +// run-rustfix + +#![allow(unused_variables, dead_code)] + +fn for_struct() { + let foo = 3; //~ ERROR expected `;`, found keyword `struct` + struct Foo; +} + +fn for_union() { + let foo = 3; //~ ERROR expected `;`, found `union` + union Foo { + foo: usize, + } +} + +fn for_enum() { + let foo = 3; //~ ERROR expected `;`, found keyword `enum` + enum Foo { + Bar, + } +} + +fn for_fn() { + let foo = 3; //~ ERROR expected `;`, found keyword `fn` + fn foo() {} +} + +fn for_extern() { + let foo = 3; //~ ERROR expected `;`, found keyword `extern` + extern fn foo() {} +} + +fn for_impl() { + struct Foo; + let foo = 3; //~ ERROR expected `;`, found keyword `impl` + impl Foo {} +} + +fn for_use() { + let foo = 3; //~ ERROR expected `;`, found keyword `pub` + pub use bar::Bar; +} + +fn for_mod() { + let foo = 3; //~ ERROR expected `;`, found keyword `mod` + mod foo {} +} + +fn for_type() { + let foo = 3; //~ ERROR expected `;`, found keyword `type` + type Foo = usize; +} + +mod bar { + pub struct Bar; +} + +const X: i32 = 123; //~ ERROR expected `;`, found keyword `fn` + +fn main() {} diff --git a/tests/ui/parser/recover-missing-semi-before-item.rs b/tests/ui/parser/recover-missing-semi-before-item.rs new file mode 100644 index 000000000..867b7b749 --- /dev/null +++ b/tests/ui/parser/recover-missing-semi-before-item.rs @@ -0,0 +1,61 @@ +// run-rustfix + +#![allow(unused_variables, dead_code)] + +fn for_struct() { + let foo = 3 //~ ERROR expected `;`, found keyword `struct` + struct Foo; +} + +fn for_union() { + let foo = 3 //~ ERROR expected `;`, found `union` + union Foo { + foo: usize, + } +} + +fn for_enum() { + let foo = 3 //~ ERROR expected `;`, found keyword `enum` + enum Foo { + Bar, + } +} + +fn for_fn() { + let foo = 3 //~ ERROR expected `;`, found keyword `fn` + fn foo() {} +} + +fn for_extern() { + let foo = 3 //~ ERROR expected `;`, found keyword `extern` + extern fn foo() {} +} + +fn for_impl() { + struct Foo; + let foo = 3 //~ ERROR expected `;`, found keyword `impl` + impl Foo {} +} + +fn for_use() { + let foo = 3 //~ ERROR expected `;`, found keyword `pub` + pub use bar::Bar; +} + +fn for_mod() { + let foo = 3 //~ ERROR expected `;`, found keyword `mod` + mod foo {} +} + +fn for_type() { + let foo = 3 //~ ERROR expected `;`, found keyword `type` + type Foo = usize; +} + +mod bar { + pub struct Bar; +} + +const X: i32 = 123 //~ ERROR expected `;`, found keyword `fn` + +fn main() {} diff --git a/tests/ui/parser/recover-missing-semi-before-item.stderr b/tests/ui/parser/recover-missing-semi-before-item.stderr new file mode 100644 index 000000000..61c43f2f1 --- /dev/null +++ b/tests/ui/parser/recover-missing-semi-before-item.stderr @@ -0,0 +1,83 @@ +error: expected `;`, found keyword `struct` + --> $DIR/recover-missing-semi-before-item.rs:6:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | struct Foo; + | ------ unexpected token + +error: expected `;`, found `union` + --> $DIR/recover-missing-semi-before-item.rs:11:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | union Foo { + | ----- unexpected token + +error: expected `;`, found keyword `enum` + --> $DIR/recover-missing-semi-before-item.rs:18:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | enum Foo { + | ---- unexpected token + +error: expected `;`, found keyword `fn` + --> $DIR/recover-missing-semi-before-item.rs:25:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | fn foo() {} + | -- unexpected token + +error: expected `;`, found keyword `extern` + --> $DIR/recover-missing-semi-before-item.rs:30:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | extern fn foo() {} + | ------ unexpected token + +error: expected `;`, found keyword `impl` + --> $DIR/recover-missing-semi-before-item.rs:36:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | impl Foo {} + | ---- unexpected token + +error: expected `;`, found keyword `pub` + --> $DIR/recover-missing-semi-before-item.rs:41:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | pub use bar::Bar; + | --- unexpected token + +error: expected `;`, found keyword `mod` + --> $DIR/recover-missing-semi-before-item.rs:46:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | mod foo {} + | --- unexpected token + +error: expected `;`, found keyword `type` + --> $DIR/recover-missing-semi-before-item.rs:51:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | type Foo = usize; + | ---- unexpected token + +error: expected `;`, found keyword `fn` + --> $DIR/recover-missing-semi-before-item.rs:59:19 + | +LL | const X: i32 = 123 + | ^ help: add `;` here +LL | +LL | fn main() {} + | -- unexpected token + +error: aborting due to 10 previous errors + diff --git a/tests/ui/parser/recover-missing-semi.rs b/tests/ui/parser/recover-missing-semi.rs new file mode 100644 index 000000000..f47d5e680 --- /dev/null +++ b/tests/ui/parser/recover-missing-semi.rs @@ -0,0 +1,13 @@ +fn main() { + let _: usize = () + //~^ ERROR mismatched types + //~| ERROR expected `;` + let _ = 3; +} + +fn foo() -> usize { + let _: usize = () + //~^ ERROR mismatched types + //~| ERROR expected `;` + return 3; +} diff --git a/tests/ui/parser/recover-missing-semi.stderr b/tests/ui/parser/recover-missing-semi.stderr new file mode 100644 index 000000000..ba4798285 --- /dev/null +++ b/tests/ui/parser/recover-missing-semi.stderr @@ -0,0 +1,37 @@ +error: expected `;`, found keyword `let` + --> $DIR/recover-missing-semi.rs:2:22 + | +LL | let _: usize = () + | ^ help: add `;` here +... +LL | let _ = 3; + | --- unexpected token + +error: expected `;`, found keyword `return` + --> $DIR/recover-missing-semi.rs:9:22 + | +LL | let _: usize = () + | ^ help: add `;` here +... +LL | return 3; + | ------ unexpected token + +error[E0308]: mismatched types + --> $DIR/recover-missing-semi.rs:2:20 + | +LL | let _: usize = () + | ----- ^^ expected `usize`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/recover-missing-semi.rs:9:20 + | +LL | let _: usize = () + | ----- ^^ expected `usize`, found `()` + | | + | expected due to this + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover-quantified-closure.rs new file mode 100644 index 000000000..df22f5e06 --- /dev/null +++ b/tests/ui/parser/recover-quantified-closure.rs @@ -0,0 +1,12 @@ +fn main() { + for<'a> |x: &'a u8| *x + 1; + //~^ ERROR `for<...>` binders for closures are experimental + //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present +} + +enum Foo { Bar } +fn foo(x: impl Iterator) { + for ::Bar in x {} + //~^ ERROR expected one of `const`, `move`, `static`, `|` + //~^^ ERROR `for<...>` binders for closures are experimental +} diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr new file mode 100644 index 000000000..9ec4d2c03 --- /dev/null +++ b/tests/ui/parser/recover-quantified-closure.stderr @@ -0,0 +1,37 @@ +error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::` + --> $DIR/recover-quantified-closure.rs:9:14 + | +LL | for ::Bar in x {} + | ^^ expected one of `const`, `move`, `static`, `|`, or `||` + +error[E0658]: `for<...>` binders for closures are experimental + --> $DIR/recover-quantified-closure.rs:2:5 + | +LL | for<'a> |x: &'a u8| *x + 1; + | ^^^^^^^ + | + = note: see issue #97362 for more information + = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable + = help: consider removing `for<...>` + +error[E0658]: `for<...>` binders for closures are experimental + --> $DIR/recover-quantified-closure.rs:9:5 + | +LL | for ::Bar in x {} + | ^^^^^^^^^ + | + = note: see issue #97362 for more information + = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable + = help: consider removing `for<...>` + +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/recover-quantified-closure.rs:2:25 + | +LL | for<'a> |x: &'a u8| *x + 1; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/recover-range-pats.rs b/tests/ui/parser/recover-range-pats.rs new file mode 100644 index 000000000..156c7ad94 --- /dev/null +++ b/tests/ui/parser/recover-range-pats.rs @@ -0,0 +1,159 @@ +// Here we test all kinds of range patterns in terms of parsing / recovery. +// We want to ensure that: +// 1. Things parse as they should. +// 2. Or at least we have parser recovery if they don't. + +#![feature(exclusive_range_pattern)] +#![deny(ellipsis_inclusive_range_patterns)] + +fn main() {} + +const X: u8 = 0; +const Y: u8 = 3; + +fn exclusive_from_to() { + if let 0..3 = 0 {} // OK. + if let 0..Y = 0 {} // OK. + if let X..3 = 0 {} // OK. + if let X..Y = 0 {} // OK. + if let true..Y = 0 {} //~ ERROR only `char` and numeric types + if let X..true = 0 {} //~ ERROR only `char` and numeric types + if let .0..Y = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + if let X.. .0 = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part +} + +fn inclusive_from_to() { + if let 0..=3 = 0 {} // OK. + if let 0..=Y = 0 {} // OK. + if let X..=3 = 0 {} // OK. + if let X..=Y = 0 {} // OK. + if let true..=Y = 0 {} //~ ERROR only `char` and numeric types + if let X..=true = 0 {} //~ ERROR only `char` and numeric types + if let .0..=Y = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + if let X..=.0 = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part +} + +fn inclusive2_from_to() { + if let 0...3 = 0 {} + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + if let 0...Y = 0 {} + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + if let X...3 = 0 {} + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + if let X...Y = 0 {} + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + if let true...Y = 0 {} //~ ERROR only `char` and numeric types + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + if let X...true = 0 {} //~ ERROR only `char` and numeric types + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + if let .0...Y = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + //~| WARN this is accepted in the current edition + //~| ERROR `...` range patterns are deprecated + if let X... .0 = 0 {} //~ ERROR mismatched types + //~^ ERROR float literals must have an integer part + //~| ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition +} + +fn exclusive_from() { + if let 0.. = 0 {} + if let X.. = 0 {} + if let true.. = 0 {} + //~^ ERROR only `char` and numeric types + if let .0.. = 0 {} + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive_from() { + if let 0..= = 0 {} //~ ERROR inclusive range with no end + if let X..= = 0 {} //~ ERROR inclusive range with no end + if let true..= = 0 {} //~ ERROR inclusive range with no end + //~| ERROR only `char` and numeric types + if let .0..= = 0 {} //~ ERROR inclusive range with no end + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive2_from() { + if let 0... = 0 {} //~ ERROR inclusive range with no end + if let X... = 0 {} //~ ERROR inclusive range with no end + if let true... = 0 {} //~ ERROR inclusive range with no end + //~| ERROR only `char` and numeric types + if let .0... = 0 {} //~ ERROR inclusive range with no end + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn exclusive_to() { + if let ..0 = 0 {} + if let ..Y = 0 {} + if let ..true = 0 {} + //~^ ERROR only `char` and numeric types + if let .. .0 = 0 {} + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive_to() { + if let ..=3 = 0 {} + if let ..=Y = 0 {} + if let ..=true = 0 {} + //~^ ERROR only `char` and numeric types + if let ..=.0 = 0 {} + //~^ ERROR float literals must have an integer part + //~| ERROR mismatched types +} + +fn inclusive2_to() { + if let ...3 = 0 {} + //~^ ERROR range-to patterns with `...` are not allowed + if let ...Y = 0 {} + //~^ ERROR range-to patterns with `...` are not allowed + if let ...true = 0 {} + //~^ ERROR range-to patterns with `...` are not allowed + //~| ERROR only `char` and numeric types + if let ....3 = 0 {} + //~^ ERROR float literals must have an integer part + //~| ERROR range-to patterns with `...` are not allowed + //~| ERROR mismatched types +} + +fn with_macro_expr_var() { + macro_rules! mac2 { + ($e1:expr, $e2:expr) => { + let $e1..$e2; + let $e1...$e2; + //~^ ERROR `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + let $e1..=$e2; + } + } + + mac2!(0, 1); + + macro_rules! mac { + ($e:expr) => { + let ..$e; + let ...$e; + //~^ ERROR range-to patterns with `...` are not allowed + let ..=$e; + let $e..; + let $e...; //~ ERROR inclusive range with no end + let $e..=; //~ ERROR inclusive range with no end + } + } + + mac!(0); +} diff --git a/tests/ui/parser/recover-range-pats.stderr b/tests/ui/parser/recover-range-pats.stderr new file mode 100644 index 000000000..c54f13e01 --- /dev/null +++ b/tests/ui/parser/recover-range-pats.stderr @@ -0,0 +1,484 @@ +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:21:12 + | +LL | if let .0..Y = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:23:16 + | +LL | if let X.. .0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:34:12 + | +LL | if let .0..=Y = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:36:16 + | +LL | if let X..=.0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:59:12 + | +LL | if let .0...Y = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:63:17 + | +LL | if let X... .0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:74:12 + | +LL | if let .0.. = 0 {} + | ^^ help: must have an integer part: `0.0` + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:80:13 + | +LL | if let 0..= = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:81:13 + | +LL | if let X..= = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:82:16 + | +LL | if let true..= = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:84:12 + | +LL | if let .0..= = 0 {} + | ^^ help: must have an integer part: `0.0` + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:84:14 + | +LL | if let .0..= = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:90:13 + | +LL | if let 0... = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:91:13 + | +LL | if let X... = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:92:16 + | +LL | if let true... = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:94:12 + | +LL | if let .0... = 0 {} + | ^^ help: must have an integer part: `0.0` + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:94:14 + | +LL | if let .0... = 0 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:104:15 + | +LL | if let .. .0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:114:15 + | +LL | if let ..=.0 = 0 {} + | ^^ help: must have an integer part: `0.0` + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:120:12 + | +LL | if let ...3 = 0 {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:122:12 + | +LL | if let ...Y = 0 {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:124:12 + | +LL | if let ...true = 0 {} + | ^^^ help: use `..=` instead + +error: float literals must have an integer part + --> $DIR/recover-range-pats.rs:127:15 + | +LL | if let ....3 = 0 {} + | ^^ help: must have an integer part: `0.3` + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:127:12 + | +LL | if let ....3 = 0 {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/recover-range-pats.rs:149:17 + | +LL | let ...$e; + | ^^^ help: use `..=` instead +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:153:19 + | +LL | let $e...; + | ^^^ help: use `..` instead +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0586]: inclusive range with no end + --> $DIR/recover-range-pats.rs:154:19 + | +LL | let $e..=; + | ^^^ help: use `..` instead +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:41:13 + | +LL | if let 0...3 = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/recover-range-pats.rs:7:9 + | +LL | #![deny(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:44:13 + | +LL | if let 0...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:47:13 + | +LL | if let X...3 = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:50:13 + | +LL | if let X...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:53:16 + | +LL | if let true...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:56:13 + | +LL | if let X...true = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:59:14 + | +LL | if let .0...Y = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:63:13 + | +LL | if let X... .0 = 0 {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:137:20 + | +LL | let $e1...$e2; + | ^^^ help: use `..=` for an inclusive range +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:19:12 + | +LL | if let true..Y = 0 {} + | ^^^^ - this is of type `u8` + | | + | this is of type `bool` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:20:15 + | +LL | if let X..true = 0 {} + | - ^^^^ this is of type `bool` but it should be `char` or numeric + | | + | this is of type `u8` + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:21:12 + | +LL | if let .0..Y = 0 {} + | ^^ - - this expression has type `{integer}` + | | | + | | this is of type `u8` + | expected integer, found floating-point number + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:23:16 + | +LL | if let X.. .0 = 0 {} + | - ^^ - this expression has type `u8` + | | | + | | expected integer, found floating-point number + | this is of type `u8` + | + = note: expected type `u8` + found type `{float}` + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:32:12 + | +LL | if let true..=Y = 0 {} + | ^^^^ - this is of type `u8` + | | + | this is of type `bool` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:33:16 + | +LL | if let X..=true = 0 {} + | - ^^^^ this is of type `bool` but it should be `char` or numeric + | | + | this is of type `u8` + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:34:12 + | +LL | if let .0..=Y = 0 {} + | ^^ - - this expression has type `{integer}` + | | | + | | this is of type `u8` + | expected integer, found floating-point number + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:36:16 + | +LL | if let X..=.0 = 0 {} + | - ^^ - this expression has type `u8` + | | | + | | expected integer, found floating-point number + | this is of type `u8` + | + = note: expected type `u8` + found type `{float}` + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:53:12 + | +LL | if let true...Y = 0 {} + | ^^^^ - this is of type `u8` + | | + | this is of type `bool` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:56:16 + | +LL | if let X...true = 0 {} + | - ^^^^ this is of type `bool` but it should be `char` or numeric + | | + | this is of type `u8` + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:59:12 + | +LL | if let .0...Y = 0 {} + | ^^ - - this expression has type `{integer}` + | | | + | | this is of type `u8` + | expected integer, found floating-point number + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:63:17 + | +LL | if let X... .0 = 0 {} + | - ^^ - this expression has type `u8` + | | | + | | expected integer, found floating-point number + | this is of type `u8` + | + = note: expected type `u8` + found type `{float}` + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:72:12 + | +LL | if let true.. = 0 {} + | ^^^^ this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:74:12 + | +LL | if let .0.. = 0 {} + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:82:12 + | +LL | if let true..= = 0 {} + | ^^^^ this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:84:12 + | +LL | if let .0..= = 0 {} + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:92:12 + | +LL | if let true... = 0 {} + | ^^^^ this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:94:12 + | +LL | if let .0... = 0 {} + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:102:14 + | +LL | if let ..true = 0 {} + | ^^^^ this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:104:15 + | +LL | if let .. .0 = 0 {} + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:112:15 + | +LL | if let ..=true = 0 {} + | ^^^^ this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:114:15 + | +LL | if let ..=.0 = 0 {} + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/recover-range-pats.rs:124:15 + | +LL | if let ...true = 0 {} + | ^^^^ this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/recover-range-pats.rs:127:15 + | +LL | if let ....3 = 0 {} + | ^^ - this expression has type `{integer}` + | | + | expected integer, found floating-point number + +error: aborting due to 60 previous errors + +Some errors have detailed explanations: E0029, E0308, E0586. +For more information about an error, try `rustc --explain E0029`. diff --git a/tests/ui/parser/recover-ref-dyn-mut.rs b/tests/ui/parser/recover-ref-dyn-mut.rs new file mode 100644 index 000000000..3016275cc --- /dev/null +++ b/tests/ui/parser/recover-ref-dyn-mut.rs @@ -0,0 +1,9 @@ +// Test that the parser detects `&dyn mut`, offers a help message, and +// recovers. + +fn main() { + let r: &dyn mut Trait; + //~^ ERROR: `mut` must precede `dyn` + //~| HELP: place `mut` before `dyn` + //~| ERROR: cannot find trait `Trait` in this scope [E0405] +} diff --git a/tests/ui/parser/recover-ref-dyn-mut.stderr b/tests/ui/parser/recover-ref-dyn-mut.stderr new file mode 100644 index 000000000..c048c8ea1 --- /dev/null +++ b/tests/ui/parser/recover-ref-dyn-mut.stderr @@ -0,0 +1,15 @@ +error: `mut` must precede `dyn` + --> $DIR/recover-ref-dyn-mut.rs:5:12 + | +LL | let r: &dyn mut Trait; + | ^^^^^^^^ help: place `mut` before `dyn`: `&mut dyn` + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/recover-ref-dyn-mut.rs:5:21 + | +LL | let r: &dyn mut Trait; + | ^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/recover-struct.rs b/tests/ui/parser/recover-struct.rs new file mode 100644 index 000000000..bfa5b454c --- /dev/null +++ b/tests/ui/parser/recover-struct.rs @@ -0,0 +1,7 @@ +fn main() { + struct Test { + Very + Bad //~ ERROR found `Bad` + Stuff + } +} diff --git a/tests/ui/parser/recover-struct.stderr b/tests/ui/parser/recover-struct.stderr new file mode 100644 index 000000000..9f6fb06ca --- /dev/null +++ b/tests/ui/parser/recover-struct.stderr @@ -0,0 +1,12 @@ +error: expected `:`, found `Bad` + --> $DIR/recover-struct.rs:4:9 + | +LL | struct Test { + | ---- while parsing this struct +LL | Very + | - expected `:` +LL | Bad + | ^^^ unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/parser/recover-tuple-pat.rs b/tests/ui/parser/recover-tuple-pat.rs new file mode 100644 index 000000000..7fded752d --- /dev/null +++ b/tests/ui/parser/recover-tuple-pat.rs @@ -0,0 +1,12 @@ +// NOTE: This doesn't recover anymore. + +fn main() { + let x = (1, 2, 3, 4); + match x { + (1, .., 4) => {} + (1, .=., 4) => { let _: usize = ""; } + //~^ ERROR expected pattern, found `.` + (.=., 4) => {} + (1, 2, 3, 4) => {} + } +} diff --git a/tests/ui/parser/recover-tuple-pat.stderr b/tests/ui/parser/recover-tuple-pat.stderr new file mode 100644 index 000000000..93a6a66a6 --- /dev/null +++ b/tests/ui/parser/recover-tuple-pat.stderr @@ -0,0 +1,8 @@ +error: expected pattern, found `.` + --> $DIR/recover-tuple-pat.rs:7:13 + | +LL | (1, .=., 4) => { let _: usize = ""; } + | ^ expected pattern + +error: aborting due to previous error + diff --git a/tests/ui/parser/recover-tuple.rs b/tests/ui/parser/recover-tuple.rs new file mode 100644 index 000000000..59e2695de --- /dev/null +++ b/tests/ui/parser/recover-tuple.rs @@ -0,0 +1,11 @@ +fn main() { + // no complaints about the tuple not matching the expected type + let x: (usize, usize, usize) = (3, .=.); + //~^ ERROR expected expression, found `.` + // verify that the parser recovers: + let y: usize = ""; //~ ERROR mismatched types + // no complaints about the type + foo(x); +} + +fn foo(_: (usize, usize, usize)) {} diff --git a/tests/ui/parser/recover-tuple.stderr b/tests/ui/parser/recover-tuple.stderr new file mode 100644 index 000000000..88891b54b --- /dev/null +++ b/tests/ui/parser/recover-tuple.stderr @@ -0,0 +1,17 @@ +error: expected expression, found `.` + --> $DIR/recover-tuple.rs:3:40 + | +LL | let x: (usize, usize, usize) = (3, .=.); + | ^ expected expression + +error[E0308]: mismatched types + --> $DIR/recover-tuple.rs:6:20 + | +LL | let y: usize = ""; + | ----- ^^ expected `usize`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/recover-unticked-labels.fixed b/tests/ui/parser/recover-unticked-labels.fixed new file mode 100644 index 000000000..159d995b8 --- /dev/null +++ b/tests/ui/parser/recover-unticked-labels.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +fn main() { + 'label: loop { break 'label }; //~ error: cannot find value `label` in this scope + 'label: loop { break 'label 0 }; //~ error: expected a label, found an identifier + 'label: loop { continue 'label }; //~ error: expected a label, found an identifier +} diff --git a/tests/ui/parser/recover-unticked-labels.rs b/tests/ui/parser/recover-unticked-labels.rs new file mode 100644 index 000000000..56034de68 --- /dev/null +++ b/tests/ui/parser/recover-unticked-labels.rs @@ -0,0 +1,7 @@ +// run-rustfix + +fn main() { + 'label: loop { break label }; //~ error: cannot find value `label` in this scope + 'label: loop { break label 0 }; //~ error: expected a label, found an identifier + 'label: loop { continue label }; //~ error: expected a label, found an identifier +} diff --git a/tests/ui/parser/recover-unticked-labels.stderr b/tests/ui/parser/recover-unticked-labels.stderr new file mode 100644 index 000000000..c115dffb1 --- /dev/null +++ b/tests/ui/parser/recover-unticked-labels.stderr @@ -0,0 +1,25 @@ +error: expected a label, found an identifier + --> $DIR/recover-unticked-labels.rs:5:26 + | +LL | 'label: loop { break label 0 }; + | ^^^^^ help: labels start with a tick: `'label` + +error: expected a label, found an identifier + --> $DIR/recover-unticked-labels.rs:6:29 + | +LL | 'label: loop { continue label }; + | ^^^^^ help: labels start with a tick: `'label` + +error[E0425]: cannot find value `label` in this scope + --> $DIR/recover-unticked-labels.rs:4:26 + | +LL | 'label: loop { break label }; + | ------ ^^^^^ + | | | + | | not found in this scope + | | help: use the similarly named label: `'label` + | a label with a similar name exists + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed new file mode 100644 index 000000000..227c40e97 --- /dev/null +++ b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.fixed @@ -0,0 +1,15 @@ +// Regression test for issues #100790 and #106439. +// run-rustfix + +pub struct Example(usize) +where + (): Sized; +//~^^^ ERROR where clauses are not allowed before tuple struct bodies + +struct _Demo(pub usize, usize) +where + (): Sized, + String: Clone; +//~^^^^ ERROR where clauses are not allowed before tuple struct bodies + +fn main() {} diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs new file mode 100644 index 000000000..3699e6fe5 --- /dev/null +++ b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.rs @@ -0,0 +1,17 @@ +// Regression test for issues #100790 and #106439. +// run-rustfix + +pub struct Example +where + (): Sized, +(usize); +//~^^^ ERROR where clauses are not allowed before tuple struct bodies + +struct _Demo +where + (): Sized, + String: Clone, +(pub usize, usize); +//~^^^^ ERROR where clauses are not allowed before tuple struct bodies + +fn main() {} diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr new file mode 100644 index 000000000..18aa5fadb --- /dev/null +++ b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-0.stderr @@ -0,0 +1,40 @@ +error: where clauses are not allowed before tuple struct bodies + --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:5:1 + | +LL | pub struct Example + | ------- while parsing this tuple struct +LL | / where +LL | | (): Sized, + | |______________^ unexpected where clause +LL | (usize); + | ------- the struct body + | +help: move the body before the where clause + | +LL ~ pub struct Example(usize) +LL | where +LL ~ (): Sized; + | + +error: where clauses are not allowed before tuple struct bodies + --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:11:1 + | +LL | struct _Demo + | ----- while parsing this tuple struct +LL | / where +LL | | (): Sized, +LL | | String: Clone, + | |__________________^ unexpected where clause +LL | (pub usize, usize); + | ------------------ the struct body + | +help: move the body before the where clause + | +LL ~ struct _Demo(pub usize, usize) +LL | where +LL | (): Sized, +LL ~ String: Clone; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs new file mode 100644 index 000000000..f515ae81e --- /dev/null +++ b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.rs @@ -0,0 +1,7 @@ +// Regression test for issues #100790 and #106439. + +// Make sure that we still show a helpful error message even if the trailing semicolon is missing. + +struct Foo where T: MyTrait, (T) +//~^ ERROR where clauses are not allowed before tuple struct bodies +//~| ERROR expected `;`, found `` diff --git a/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr new file mode 100644 index 000000000..2219c2a73 --- /dev/null +++ b/tests/ui/parser/recover-where-clause-before-tuple-struct-body-1.stderr @@ -0,0 +1,23 @@ +error: where clauses are not allowed before tuple struct bodies + --> $DIR/recover-where-clause-before-tuple-struct-body-1.rs:5:15 + | +LL | struct Foo where T: MyTrait, (T) + | --- ^^^^^^^^^^^^^^^^^ --- the struct body + | | | + | | unexpected where clause + | while parsing this tuple struct + | +help: move the body before the where clause + | +LL - struct Foo where T: MyTrait, (T) +LL + struct Foo(T) where T: MyTrait + | + +error: expected `;`, found `` + --> $DIR/recover-where-clause-before-tuple-struct-body-1.rs:5:35 + | +LL | struct Foo where T: MyTrait, (T) + | ^ expected `;` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recovered-struct-variant.rs b/tests/ui/parser/recovered-struct-variant.rs new file mode 100644 index 000000000..5b195dcc3 --- /dev/null +++ b/tests/ui/parser/recovered-struct-variant.rs @@ -0,0 +1,13 @@ +enum Foo { + A { a, b: usize } + //~^ ERROR expected `:`, found `,` +} + +fn main() { + // no complaints about non-existing fields + let f = Foo::A { a:3, b: 4}; + match f { + // no complaints about non-existing fields + Foo::A {a, b} => {} + } +} diff --git a/tests/ui/parser/recovered-struct-variant.stderr b/tests/ui/parser/recovered-struct-variant.stderr new file mode 100644 index 000000000..78c67866f --- /dev/null +++ b/tests/ui/parser/recovered-struct-variant.stderr @@ -0,0 +1,10 @@ +error: expected `:`, found `,` + --> $DIR/recovered-struct-variant.rs:2:10 + | +LL | A { a, b: usize } + | - ^ expected `:` + | | + | while parsing this struct + +error: aborting due to previous error + diff --git a/tests/ui/parser/regions-out-of-scope-slice.rs b/tests/ui/parser/regions-out-of-scope-slice.rs new file mode 100644 index 000000000..d223619e1 --- /dev/null +++ b/tests/ui/parser/regions-out-of-scope-slice.rs @@ -0,0 +1,11 @@ +// This basically tests the parser's recovery on `'blk` in the wrong place. + +fn foo(cond: bool) { + let mut x; + + if cond { + x = &'blk [1,2,3]; //~ ERROR borrow expressions cannot be annotated with lifetimes + } +} + +fn main() {} diff --git a/tests/ui/parser/regions-out-of-scope-slice.stderr b/tests/ui/parser/regions-out-of-scope-slice.stderr new file mode 100644 index 000000000..bbc657ffd --- /dev/null +++ b/tests/ui/parser/regions-out-of-scope-slice.stderr @@ -0,0 +1,11 @@ +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/regions-out-of-scope-slice.rs:7:13 + | +LL | x = &'blk [1,2,3]; + | ^----^^^^^^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.rs b/tests/ui/parser/removed-syntax-closure-lifetime.rs new file mode 100644 index 000000000..e807a1794 --- /dev/null +++ b/tests/ui/parser/removed-syntax-closure-lifetime.rs @@ -0,0 +1,2 @@ +type closure = Box; +//~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` diff --git a/tests/ui/parser/removed-syntax-closure-lifetime.stderr b/tests/ui/parser/removed-syntax-closure-lifetime.stderr new file mode 100644 index 000000000..e107c6b78 --- /dev/null +++ b/tests/ui/parser/removed-syntax-closure-lifetime.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/` + --> $DIR/removed-syntax-closure-lifetime.rs:1:22 + | +LL | type closure = Box; + | ^ expected one of 9 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | type closure = Box/fn()>; + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-enum-newtype.rs b/tests/ui/parser/removed-syntax-enum-newtype.rs new file mode 100644 index 000000000..518f90b2b --- /dev/null +++ b/tests/ui/parser/removed-syntax-enum-newtype.rs @@ -0,0 +1 @@ +enum e = isize; //~ ERROR expected one of `<`, `where`, or `{`, found `=` diff --git a/tests/ui/parser/removed-syntax-enum-newtype.stderr b/tests/ui/parser/removed-syntax-enum-newtype.stderr new file mode 100644 index 000000000..8f7ca3567 --- /dev/null +++ b/tests/ui/parser/removed-syntax-enum-newtype.stderr @@ -0,0 +1,10 @@ +error: expected one of `<`, `where`, or `{`, found `=` + --> $DIR/removed-syntax-enum-newtype.rs:1:8 + | +LL | enum e = isize; + | - ^ expected one of `<`, `where`, or `{` + | | + | while parsing this enum + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-field-let-2.rs b/tests/ui/parser/removed-syntax-field-let-2.rs new file mode 100644 index 000000000..7ff91b476 --- /dev/null +++ b/tests/ui/parser/removed-syntax-field-let-2.rs @@ -0,0 +1,12 @@ +struct Foo { + let x: i32, + //~^ ERROR expected identifier, found keyword + let y: i32, + //~^ ERROR expected identifier, found keyword +} + +fn main() { + let _ = Foo { + //~^ ERROR missing fields `x` and `y` in initializer of `Foo` + }; +} diff --git a/tests/ui/parser/removed-syntax-field-let-2.stderr b/tests/ui/parser/removed-syntax-field-let-2.stderr new file mode 100644 index 000000000..fda0919b9 --- /dev/null +++ b/tests/ui/parser/removed-syntax-field-let-2.stderr @@ -0,0 +1,33 @@ +error: expected identifier, found keyword `let` + --> $DIR/removed-syntax-field-let-2.rs:2:5 + | +LL | let x: i32, + | ^^^- + | | + | expected identifier, found keyword + | help: remove this `let` keyword + | + = note: the `let` keyword is not allowed in `struct` fields + = note: see for more information + +error: expected identifier, found keyword `let` + --> $DIR/removed-syntax-field-let-2.rs:4:5 + | +LL | let y: i32, + | ^^^- + | | + | expected identifier, found keyword + | help: remove this `let` keyword + | + = note: the `let` keyword is not allowed in `struct` fields + = note: see for more information + +error[E0063]: missing fields `x` and `y` in initializer of `Foo` + --> $DIR/removed-syntax-field-let-2.rs:9:13 + | +LL | let _ = Foo { + | ^^^ missing `x` and `y` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/removed-syntax-field-let.rs b/tests/ui/parser/removed-syntax-field-let.rs new file mode 100644 index 000000000..6d64de296 --- /dev/null +++ b/tests/ui/parser/removed-syntax-field-let.rs @@ -0,0 +1,6 @@ +struct S { + let foo: (), + //~^ ERROR expected identifier, found keyword `let` +} + +fn main() {} diff --git a/tests/ui/parser/removed-syntax-field-let.stderr b/tests/ui/parser/removed-syntax-field-let.stderr new file mode 100644 index 000000000..9bc18dabd --- /dev/null +++ b/tests/ui/parser/removed-syntax-field-let.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `let` + --> $DIR/removed-syntax-field-let.rs:2:5 + | +LL | let foo: (), + | ^^^- + | | + | expected identifier, found keyword + | help: remove this `let` keyword + | + = note: the `let` keyword is not allowed in `struct` fields + = note: see for more information + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-field-semicolon.rs b/tests/ui/parser/removed-syntax-field-semicolon.rs new file mode 100644 index 000000000..808f2a5cc --- /dev/null +++ b/tests/ui/parser/removed-syntax-field-semicolon.rs @@ -0,0 +1,6 @@ +struct S { + bar: (); + //~^ ERROR struct fields are separated by `,` +} + +fn main() {} diff --git a/tests/ui/parser/removed-syntax-field-semicolon.stderr b/tests/ui/parser/removed-syntax-field-semicolon.stderr new file mode 100644 index 000000000..532d4fb2b --- /dev/null +++ b/tests/ui/parser/removed-syntax-field-semicolon.stderr @@ -0,0 +1,10 @@ +error: struct fields are separated by `,` + --> $DIR/removed-syntax-field-semicolon.rs:2:12 + | +LL | struct S { + | - while parsing this struct +LL | bar: (); + | ^ help: replace `;` with `,` + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-fixed-vec.rs b/tests/ui/parser/removed-syntax-fixed-vec.rs new file mode 100644 index 000000000..560efecb9 --- /dev/null +++ b/tests/ui/parser/removed-syntax-fixed-vec.rs @@ -0,0 +1 @@ +type v = [isize * 3]; //~ ERROR expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` diff --git a/tests/ui/parser/removed-syntax-fixed-vec.stderr b/tests/ui/parser/removed-syntax-fixed-vec.stderr new file mode 100644 index 000000000..a2b97544f --- /dev/null +++ b/tests/ui/parser/removed-syntax-fixed-vec.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `*` + --> $DIR/removed-syntax-fixed-vec.rs:1:17 + | +LL | type v = [isize * 3]; + | ^ expected one of 7 possible tokens + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-fn-sigil.rs b/tests/ui/parser/removed-syntax-fn-sigil.rs new file mode 100644 index 000000000..725843429 --- /dev/null +++ b/tests/ui/parser/removed-syntax-fn-sigil.rs @@ -0,0 +1,3 @@ +fn main() { + let x: fn~() = || (); //~ ERROR expected `(`, found `~` +} diff --git a/tests/ui/parser/removed-syntax-fn-sigil.stderr b/tests/ui/parser/removed-syntax-fn-sigil.stderr new file mode 100644 index 000000000..196a5af47 --- /dev/null +++ b/tests/ui/parser/removed-syntax-fn-sigil.stderr @@ -0,0 +1,10 @@ +error: expected `(`, found `~` + --> $DIR/removed-syntax-fn-sigil.rs:2:14 + | +LL | let x: fn~() = || (); + | - ^ expected `(` + | | + | while parsing the type for `x` + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-mode.rs b/tests/ui/parser/removed-syntax-mode.rs new file mode 100644 index 000000000..a438db3b0 --- /dev/null +++ b/tests/ui/parser/removed-syntax-mode.rs @@ -0,0 +1,4 @@ +fn f(+x: isize) {} +//~^ ERROR expected parameter name, found `+` + +fn main() {} diff --git a/tests/ui/parser/removed-syntax-mode.stderr b/tests/ui/parser/removed-syntax-mode.stderr new file mode 100644 index 000000000..d0393b379 --- /dev/null +++ b/tests/ui/parser/removed-syntax-mode.stderr @@ -0,0 +1,8 @@ +error: expected parameter name, found `+` + --> $DIR/removed-syntax-mode.rs:1:6 + | +LL | fn f(+x: isize) {} + | ^ expected parameter name + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.rs b/tests/ui/parser/removed-syntax-mut-vec-expr.rs new file mode 100644 index 000000000..2ee95db5a --- /dev/null +++ b/tests/ui/parser/removed-syntax-mut-vec-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let v = [mut 1, 2, 3, 4]; //~ ERROR expected expression, found keyword `mut` +} diff --git a/tests/ui/parser/removed-syntax-mut-vec-expr.stderr b/tests/ui/parser/removed-syntax-mut-vec-expr.stderr new file mode 100644 index 000000000..313420fb9 --- /dev/null +++ b/tests/ui/parser/removed-syntax-mut-vec-expr.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `mut` + --> $DIR/removed-syntax-mut-vec-expr.rs:2:14 + | +LL | let v = [mut 1, 2, 3, 4]; + | ^^^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.rs b/tests/ui/parser/removed-syntax-mut-vec-ty.rs new file mode 100644 index 000000000..923a7ea37 --- /dev/null +++ b/tests/ui/parser/removed-syntax-mut-vec-ty.rs @@ -0,0 +1 @@ +type v = [mut isize]; //~ ERROR expected type, found keyword `mut` diff --git a/tests/ui/parser/removed-syntax-mut-vec-ty.stderr b/tests/ui/parser/removed-syntax-mut-vec-ty.stderr new file mode 100644 index 000000000..02b518e25 --- /dev/null +++ b/tests/ui/parser/removed-syntax-mut-vec-ty.stderr @@ -0,0 +1,8 @@ +error: expected type, found keyword `mut` + --> $DIR/removed-syntax-mut-vec-ty.rs:1:11 + | +LL | type v = [mut isize]; + | ^^^ expected type + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.rs b/tests/ui/parser/removed-syntax-ptr-lifetime.rs new file mode 100644 index 000000000..cc69af44a --- /dev/null +++ b/tests/ui/parser/removed-syntax-ptr-lifetime.rs @@ -0,0 +1 @@ +type bptr = &lifetime/isize; //~ ERROR expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` diff --git a/tests/ui/parser/removed-syntax-ptr-lifetime.stderr b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr new file mode 100644 index 000000000..914de43e6 --- /dev/null +++ b/tests/ui/parser/removed-syntax-ptr-lifetime.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `::`, `;`, `<`, or `where`, found `/` + --> $DIR/removed-syntax-ptr-lifetime.rs:1:22 + | +LL | type bptr = &lifetime/isize; + | ^ expected one of `!`, `(`, `::`, `;`, `<`, or `where` + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-record.rs b/tests/ui/parser/removed-syntax-record.rs new file mode 100644 index 000000000..d1d91c8f7 --- /dev/null +++ b/tests/ui/parser/removed-syntax-record.rs @@ -0,0 +1 @@ +type t = { f: () }; //~ ERROR expected type, found `{` diff --git a/tests/ui/parser/removed-syntax-record.stderr b/tests/ui/parser/removed-syntax-record.stderr new file mode 100644 index 000000000..0a1655840 --- /dev/null +++ b/tests/ui/parser/removed-syntax-record.stderr @@ -0,0 +1,8 @@ +error: expected type, found `{` + --> $DIR/removed-syntax-record.rs:1:10 + | +LL | type t = { f: () }; + | ^ expected type + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-static-fn.rs b/tests/ui/parser/removed-syntax-static-fn.rs new file mode 100644 index 000000000..cd643b874 --- /dev/null +++ b/tests/ui/parser/removed-syntax-static-fn.rs @@ -0,0 +1,10 @@ +struct S; + +impl S { + static fn f() {} + //~^ ERROR expected identifier, found keyword `fn` + //~| ERROR expected one of `:`, `;`, or `=` + //~| ERROR missing type for `static` item +} + +fn main() {} diff --git a/tests/ui/parser/removed-syntax-static-fn.stderr b/tests/ui/parser/removed-syntax-static-fn.stderr new file mode 100644 index 000000000..52e065894 --- /dev/null +++ b/tests/ui/parser/removed-syntax-static-fn.stderr @@ -0,0 +1,25 @@ +error: expected identifier, found keyword `fn` + --> $DIR/removed-syntax-static-fn.rs:4:12 + | +LL | static fn f() {} + | ^^ expected identifier, found keyword + +error: expected one of `:`, `;`, or `=`, found `f` + --> $DIR/removed-syntax-static-fn.rs:4:15 + | +LL | impl S { + | - while parsing this item list starting here +LL | static fn f() {} + | ^ expected one of `:`, `;`, or `=` +... +LL | } + | - the item list ends here + +error: missing type for `static` item + --> $DIR/removed-syntax-static-fn.rs:4:14 + | +LL | static fn f() {} + | ^ help: provide a type for the item: `: ` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.rs b/tests/ui/parser/removed-syntax-uniq-mut-expr.rs new file mode 100644 index 000000000..08ef4b432 --- /dev/null +++ b/tests/ui/parser/removed-syntax-uniq-mut-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let a_box = box mut 42; //~ ERROR expected expression, found keyword `mut` +} diff --git a/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr b/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr new file mode 100644 index 000000000..63d2fdb8c --- /dev/null +++ b/tests/ui/parser/removed-syntax-uniq-mut-expr.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `mut` + --> $DIR/removed-syntax-uniq-mut-expr.rs:2:21 + | +LL | let a_box = box mut 42; + | ^^^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.rs b/tests/ui/parser/removed-syntax-uniq-mut-ty.rs new file mode 100644 index 000000000..a8dee5bbd --- /dev/null +++ b/tests/ui/parser/removed-syntax-uniq-mut-ty.rs @@ -0,0 +1,2 @@ +type mut_box = Box; +//~^ ERROR expected one of `>`, a const expression, lifetime, or type, found keyword `mut` diff --git a/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr b/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr new file mode 100644 index 000000000..39db0be9f --- /dev/null +++ b/tests/ui/parser/removed-syntax-uniq-mut-ty.stderr @@ -0,0 +1,8 @@ +error: expected one of `>`, a const expression, lifetime, or type, found keyword `mut` + --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20 + | +LL | type mut_box = Box; + | ^^^ expected one of `>`, a const expression, lifetime, or type + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-with-1.rs b/tests/ui/parser/removed-syntax-with-1.rs new file mode 100644 index 000000000..2c1e152dc --- /dev/null +++ b/tests/ui/parser/removed-syntax-with-1.rs @@ -0,0 +1,10 @@ +fn main() { + struct S { + foo: (), + bar: (), + } + + let a = S { foo: (), bar: () }; + let b = S { foo: () with a, bar: () }; + //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with` +} diff --git a/tests/ui/parser/removed-syntax-with-1.stderr b/tests/ui/parser/removed-syntax-with-1.stderr new file mode 100644 index 000000000..c3f747b61 --- /dev/null +++ b/tests/ui/parser/removed-syntax-with-1.stderr @@ -0,0 +1,11 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with` + --> $DIR/removed-syntax-with-1.rs:8:25 + | +LL | let b = S { foo: () with a, bar: () }; + | - -^^^^ expected one of `,`, `.`, `?`, `}`, or an operator + | | | + | | help: try adding a comma: `,` + | while parsing this struct + +error: aborting due to previous error + diff --git a/tests/ui/parser/removed-syntax-with-2.rs b/tests/ui/parser/removed-syntax-with-2.rs new file mode 100644 index 000000000..451057c66 --- /dev/null +++ b/tests/ui/parser/removed-syntax-with-2.rs @@ -0,0 +1,11 @@ +fn main() { + struct S { + foo: (), + bar: (), + } + + let a = S { foo: (), bar: () }; + let b = S { foo: (), with a }; + //~^ ERROR expected one of `,`, `:`, or `}`, found `a` + //~| ERROR missing field `bar` in initializer of `S` +} diff --git a/tests/ui/parser/removed-syntax-with-2.stderr b/tests/ui/parser/removed-syntax-with-2.stderr new file mode 100644 index 000000000..c6ae1ce67 --- /dev/null +++ b/tests/ui/parser/removed-syntax-with-2.stderr @@ -0,0 +1,17 @@ +error: expected one of `,`, `:`, or `}`, found `a` + --> $DIR/removed-syntax-with-2.rs:8:31 + | +LL | let b = S { foo: (), with a }; + | - ^ expected one of `,`, `:`, or `}` + | | + | while parsing this struct + +error[E0063]: missing field `bar` in initializer of `S` + --> $DIR/removed-syntax-with-2.rs:8:13 + | +LL | let b = S { foo: (), with a }; + | ^ missing `bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/require-parens-for-chained-comparison.rs b/tests/ui/parser/require-parens-for-chained-comparison.rs new file mode 100644 index 000000000..5b90e905a --- /dev/null +++ b/tests/ui/parser/require-parens-for-chained-comparison.rs @@ -0,0 +1,38 @@ +fn main() { + false == false == false; + //~^ ERROR comparison operators cannot be chained + //~| HELP split the comparison into two + + false == 0 < 2; + //~^ ERROR comparison operators cannot be chained + //~| HELP parenthesize the comparison + + f(); + //~^ ERROR comparison operators cannot be chained + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + + f, Option>>(1, 2); + //~^ ERROR comparison operators cannot be chained + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + + let _ = f(); + //~^ ERROR expected one of + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + + let _ = f<'_, i8>(); + //~^ ERROR expected one of + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| ERROR expected + //~| HELP add `'` to close the char literal + + f<'_>(); + //~^ comparison operators cannot be chained + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| ERROR expected + //~| HELP add `'` to close the char literal + + let _ = f; + //~^ ERROR comparison operators cannot be chained + //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| HELP or use `(...)` if you meant to specify fn arguments +} diff --git a/tests/ui/parser/require-parens-for-chained-comparison.stderr b/tests/ui/parser/require-parens-for-chained-comparison.stderr new file mode 100644 index 000000000..52e201c43 --- /dev/null +++ b/tests/ui/parser/require-parens-for-chained-comparison.stderr @@ -0,0 +1,110 @@ +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:2:11 + | +LL | false == false == false; + | ^^ ^^ + | +help: split the comparison into two + | +LL | false == false && false == false; + | ++++++++ + +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:6:11 + | +LL | false == 0 < 2; + | ^^ ^ + | +help: parenthesize the comparison + | +LL | false == (0 < 2); + | + + + +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:10:6 + | +LL | f(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | f::(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:14:6 + | +LL | f, Option>>(1, 2); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | f::, Option>>(1, 2); + | ++ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,` + --> $DIR/require-parens-for-chained-comparison.rs:18:17 + | +LL | let _ = f(); + | ^ expected one of 8 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let _ = f::(); + | ++ + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/require-parens-for-chained-comparison.rs:22:17 + | +LL | let _ = f<'_, i8>(); + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | let _ = f<'_', i8>(); + | + + +error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,` + --> $DIR/require-parens-for-chained-comparison.rs:22:17 + | +LL | let _ = f<'_, i8>(); + | ^ expected one of 9 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | let _ = f::<'_, i8>(); + | ++ + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/require-parens-for-chained-comparison.rs:28:9 + | +LL | f<'_>(); + | ^ expected `while`, `for`, `loop` or `{` after a label + | +help: add `'` to close the char literal + | +LL | f<'_'>(); + | + + +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:28:6 + | +LL | f<'_>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | f::<'_>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/require-parens-for-chained-comparison.rs:34:14 + | +LL | let _ = f; + | ^ ^ + | + = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + = help: or use `(...)` if you meant to specify fn arguments + +error: aborting due to 10 previous errors + diff --git a/tests/ui/parser/self-in-function-arg.rs b/tests/ui/parser/self-in-function-arg.rs new file mode 100644 index 000000000..6172ffe1b --- /dev/null +++ b/tests/ui/parser/self-in-function-arg.rs @@ -0,0 +1,3 @@ +fn foo(x:i32, self: i32) -> i32 { self } //~ ERROR unexpected `self` parameter in function + +fn main() {} diff --git a/tests/ui/parser/self-in-function-arg.stderr b/tests/ui/parser/self-in-function-arg.stderr new file mode 100644 index 000000000..47d8381b0 --- /dev/null +++ b/tests/ui/parser/self-in-function-arg.stderr @@ -0,0 +1,8 @@ +error: unexpected `self` parameter in function + --> $DIR/self-in-function-arg.rs:1:15 + | +LL | fn foo(x:i32, self: i32) -> i32 { self } + | ^^^^ must be the first parameter of an associated function + +error: aborting due to previous error + diff --git a/tests/ui/parser/self-param-semantic-fail.rs b/tests/ui/parser/self-param-semantic-fail.rs new file mode 100644 index 000000000..621aab279 --- /dev/null +++ b/tests/ui/parser/self-param-semantic-fail.rs @@ -0,0 +1,64 @@ +// This test ensures that `self` is semantically rejected +// in contexts with `FnDecl` but outside of associated `fn`s. +// FIXME(Centril): For now closures are an exception. + +fn main() {} + +fn free() { + fn f1(self) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f2(mut self) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f3(&self) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f4(&mut self) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f5<'a>(&'a self) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f6<'a>(&'a mut self) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f7(self: u8) {} + //~^ ERROR `self` parameter is only allowed in associated functions + fn f8(mut self: u8) {} + //~^ ERROR `self` parameter is only allowed in associated functions +} + +extern "C" { + fn f1(self); + //~^ ERROR `self` parameter is only allowed in associated functions + fn f2(mut self); + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR patterns aren't allowed in + fn f3(&self); + //~^ ERROR `self` parameter is only allowed in associated functions + fn f4(&mut self); + //~^ ERROR `self` parameter is only allowed in associated functions + fn f5<'a>(&'a self); + //~^ ERROR `self` parameter is only allowed in associated functions + fn f6<'a>(&'a mut self); + //~^ ERROR `self` parameter is only allowed in associated functions + fn f7(self: u8); + //~^ ERROR `self` parameter is only allowed in associated functions + fn f8(mut self: u8); +//~^ ERROR `self` parameter is only allowed in associated functions +//~| ERROR patterns aren't allowed in +} + +type X1 = fn(self); +//~^ ERROR `self` parameter is only allowed in associated functions +type X2 = fn(mut self); +//~^ ERROR `self` parameter is only allowed in associated functions +//~| ERROR patterns aren't allowed in +type X3 = fn(&self); +//~^ ERROR `self` parameter is only allowed in associated functions +type X4 = fn(&mut self); +//~^ ERROR `self` parameter is only allowed in associated functions +type X5 = for<'a> fn(&'a self); +//~^ ERROR `self` parameter is only allowed in associated functions +type X6 = for<'a> fn(&'a mut self); +//~^ ERROR `self` parameter is only allowed in associated functions +type X7 = fn(self: u8); +//~^ ERROR `self` parameter is only allowed in associated functions +type X8 = fn(mut self: u8); +//~^ ERROR `self` parameter is only allowed in associated functions +//~| ERROR patterns aren't allowed in diff --git a/tests/ui/parser/self-param-semantic-fail.stderr b/tests/ui/parser/self-param-semantic-fail.stderr new file mode 100644 index 000000000..e5d679773 --- /dev/null +++ b/tests/ui/parser/self-param-semantic-fail.stderr @@ -0,0 +1,220 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:8:11 + | +LL | fn f1(self) {} + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:10:11 + | +LL | fn f2(mut self) {} + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:12:11 + | +LL | fn f3(&self) {} + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:14:11 + | +LL | fn f4(&mut self) {} + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:16:15 + | +LL | fn f5<'a>(&'a self) {} + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:18:15 + | +LL | fn f6<'a>(&'a mut self) {} + | ^^^^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:20:11 + | +LL | fn f7(self: u8) {} + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:22:11 + | +LL | fn f8(mut self: u8) {} + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:27:11 + | +LL | fn f1(self); + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:29:11 + | +LL | fn f2(mut self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/self-param-semantic-fail.rs:29:11 + | +LL | fn f2(mut self); + | ^^^^^^^^ pattern not allowed in foreign function + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:32:11 + | +LL | fn f3(&self); + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:34:11 + | +LL | fn f4(&mut self); + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:36:15 + | +LL | fn f5<'a>(&'a self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:38:15 + | +LL | fn f6<'a>(&'a mut self); + | ^^^^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:40:11 + | +LL | fn f7(self: u8); + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:42:11 + | +LL | fn f8(mut self: u8); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/self-param-semantic-fail.rs:42:11 + | +LL | fn f8(mut self: u8); + | ^^^^^^^^ pattern not allowed in foreign function + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:47:14 + | +LL | type X1 = fn(self); + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:49:14 + | +LL | type X2 = fn(mut self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/self-param-semantic-fail.rs:49:14 + | +LL | type X2 = fn(mut self); + | ^^^^^^^^ + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:52:14 + | +LL | type X3 = fn(&self); + | ^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:54:14 + | +LL | type X4 = fn(&mut self); + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:56:22 + | +LL | type X5 = for<'a> fn(&'a self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:58:22 + | +LL | type X6 = for<'a> fn(&'a mut self); + | ^^^^^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:60:14 + | +LL | type X7 = fn(self: u8); + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/self-param-semantic-fail.rs:62:14 + | +LL | type X8 = fn(mut self: u8); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/self-param-semantic-fail.rs:62:14 + | +LL | type X8 = fn(mut self: u8); + | ^^^^^^^^ + +error: aborting due to 28 previous errors + +Some errors have detailed explanations: E0130, E0561. +For more information about an error, try `rustc --explain E0130`. diff --git a/tests/ui/parser/self-param-syntactic-pass.rs b/tests/ui/parser/self-param-syntactic-pass.rs new file mode 100644 index 000000000..d7bb7863c --- /dev/null +++ b/tests/ui/parser/self-param-syntactic-pass.rs @@ -0,0 +1,66 @@ +// This test ensures that `self` is syntactically accepted in all places an `FnDecl` is parsed. +// FIXME(Centril): For now closures are an exception. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn free() { + fn f(self) {} + fn f(mut self) {} + fn f(&self) {} + fn f(&mut self) {} + fn f(&'a self) {} + fn f(&'a mut self) {} + fn f(self: u8) {} + fn f(mut self: u8) {} +} + +#[cfg(FALSE)] +extern "C" { + fn f(self); + fn f(mut self); + fn f(&self); + fn f(&mut self); + fn f(&'a self); + fn f(&'a mut self); + fn f(self: u8); + fn f(mut self: u8); +} + +#[cfg(FALSE)] +trait X { + fn f(self) {} + fn f(mut self) {} + fn f(&self) {} + fn f(&mut self) {} + fn f(&'a self) {} + fn f(&'a mut self) {} + fn f(self: u8) {} + fn f(mut self: u8) {} +} + +#[cfg(FALSE)] +impl X for Y { + fn f(self) {} + fn f(mut self) {} + fn f(&self) {} + fn f(&mut self) {} + fn f(&'a self) {} + fn f(&'a mut self) {} + fn f(self: u8) {} + fn f(mut self: u8) {} +} + +#[cfg(FALSE)] +impl X for Y { + type X = fn(self); + type X = fn(mut self); + type X = fn(&self); + type X = fn(&mut self); + type X = fn(&'a self); + type X = fn(&'a mut self); + type X = fn(self: u8); + type X = fn(mut self: u8); +} diff --git a/tests/ui/parser/semi-after-closure-in-macro.rs b/tests/ui/parser/semi-after-closure-in-macro.rs new file mode 100644 index 000000000..14efb6100 --- /dev/null +++ b/tests/ui/parser/semi-after-closure-in-macro.rs @@ -0,0 +1,14 @@ +// check-pass + +// Checks that the fix in #103222 doesn't also disqualify semicolons after +// closures within parentheses *in macros*, where they're totally allowed. + +macro_rules! m { + (($expr:expr ; )) => { + $expr + }; +} + +fn main() { + let x = m!(( ||() ; )); +} diff --git a/tests/ui/parser/several-carriage-returns-in-doc-comment.rs b/tests/ui/parser/several-carriage-returns-in-doc-comment.rs new file mode 100644 index 000000000..ee14c55d2 --- /dev/null +++ b/tests/ui/parser/several-carriage-returns-in-doc-comment.rs @@ -0,0 +1,10 @@ +// Issue #62863 +// ignore-tidy-cr + +// Note: if you see ^M in this file, that's how your editor renders literal `\r` + +/// This do c comment contains three isolated `\r` symbols +//~^ ERROR bare CR not allowed in doc-comment +//~| ERROR bare CR not allowed in doc-comment +//~| ERROR bare CR not allowed in doc-comment +fn main() {} diff --git a/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr new file mode 100644 index 000000000..07066fc22 --- /dev/null +++ b/tests/ui/parser/several-carriage-returns-in-doc-comment.stderr @@ -0,0 +1,20 @@ +error: bare CR not allowed in doc-comment + --> $DIR/several-carriage-returns-in-doc-comment.rs:6:12 + | +LL | /// This do c comment contains three isolated `\r` symbols + | ^ + +error: bare CR not allowed in doc-comment + --> $DIR/several-carriage-returns-in-doc-comment.rs:6:32 + | +LL | /// This do c comment contains three isolated `\r` symbols + | ^ + +error: bare CR not allowed in doc-comment + --> $DIR/several-carriage-returns-in-doc-comment.rs:6:52 + | +LL | /// This do c comment contains three isolated `\r` symbols + | ^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs b/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs new file mode 100644 index 000000000..a25051808 --- /dev/null +++ b/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs @@ -0,0 +1,2 @@ + +#!B //~ expected `[`, found `B` diff --git a/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr b/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr new file mode 100644 index 000000000..896a9dc83 --- /dev/null +++ b/tests/ui/parser/shebang/issue-71471-ignore-tidy.stderr @@ -0,0 +1,8 @@ +error: expected `[`, found `B` + --> $DIR/issue-71471-ignore-tidy.rs:2:3 + | +LL | #!B + | ^ expected `[` + +error: aborting due to previous error + diff --git a/tests/ui/parser/shebang/multiline-attrib.rs b/tests/ui/parser/shebang/multiline-attrib.rs new file mode 100644 index 000000000..931c94c7f --- /dev/null +++ b/tests/ui/parser/shebang/multiline-attrib.rs @@ -0,0 +1,7 @@ +#! +[allow(unused_variables)] +// check-pass + +fn main() { + let x = 5; +} diff --git a/tests/ui/parser/shebang/regular-attrib.rs b/tests/ui/parser/shebang/regular-attrib.rs new file mode 100644 index 000000000..ca8fb0830 --- /dev/null +++ b/tests/ui/parser/shebang/regular-attrib.rs @@ -0,0 +1,5 @@ +#![allow(unused_variables)] +// check-pass +fn main() { + let x = 5; +} diff --git a/tests/ui/parser/shebang/shebang-and-attrib.rs b/tests/ui/parser/shebang/shebang-and-attrib.rs new file mode 100644 index 000000000..61b89c655 --- /dev/null +++ b/tests/ui/parser/shebang/shebang-and-attrib.rs @@ -0,0 +1,9 @@ +#!/usr/bin/env run-cargo-script + +// check-pass +#![allow(unused_variables)] + + +fn main() { + let x = 5; +} diff --git a/tests/ui/parser/shebang/shebang-comment.rs b/tests/ui/parser/shebang/shebang-comment.rs new file mode 100644 index 000000000..2b1ab0c57 --- /dev/null +++ b/tests/ui/parser/shebang/shebang-comment.rs @@ -0,0 +1,6 @@ +#!//bin/bash + +// check-pass +fn main() { + println!("a valid shebang (that is also a rust comment)") +} diff --git a/tests/ui/parser/shebang/shebang-doc-comment.rs b/tests/ui/parser/shebang/shebang-doc-comment.rs new file mode 100644 index 000000000..72866753e --- /dev/null +++ b/tests/ui/parser/shebang/shebang-doc-comment.rs @@ -0,0 +1,3 @@ +#!///bin/bash +[allow(unused_variables)] +//~^ ERROR expected item, found `[` diff --git a/tests/ui/parser/shebang/shebang-doc-comment.stderr b/tests/ui/parser/shebang/shebang-doc-comment.stderr new file mode 100644 index 000000000..2227d45ec --- /dev/null +++ b/tests/ui/parser/shebang/shebang-doc-comment.stderr @@ -0,0 +1,8 @@ +error: expected item, found `[` + --> $DIR/shebang-doc-comment.rs:2:1 + | +LL | [allow(unused_variables)] + | ^ expected item + +error: aborting due to previous error + diff --git a/tests/ui/parser/shebang/shebang-empty.rs b/tests/ui/parser/shebang/shebang-empty.rs new file mode 100644 index 000000000..e38cc637e --- /dev/null +++ b/tests/ui/parser/shebang/shebang-empty.rs @@ -0,0 +1,4 @@ +#! + +// check-pass +fn main() {} diff --git a/tests/ui/parser/shebang/shebang-must-start-file.rs b/tests/ui/parser/shebang/shebang-must-start-file.rs new file mode 100644 index 000000000..e0392572d --- /dev/null +++ b/tests/ui/parser/shebang/shebang-must-start-file.rs @@ -0,0 +1,6 @@ +// something on the first line for tidy +#!/bin/bash //~ expected `[`, found `/` + +fn main() { + println!("ok!"); +} diff --git a/tests/ui/parser/shebang/shebang-must-start-file.stderr b/tests/ui/parser/shebang/shebang-must-start-file.stderr new file mode 100644 index 000000000..50543e8bd --- /dev/null +++ b/tests/ui/parser/shebang/shebang-must-start-file.stderr @@ -0,0 +1,8 @@ +error: expected `[`, found `/` + --> $DIR/shebang-must-start-file.rs:2:3 + | +LL | #!/bin/bash + | ^ expected `[` + +error: aborting due to previous error + diff --git a/tests/ui/parser/shebang/shebang-space.rs b/tests/ui/parser/shebang/shebang-space.rs new file mode 100644 index 000000000..0978b759d --- /dev/null +++ b/tests/ui/parser/shebang/shebang-space.rs @@ -0,0 +1,5 @@ +#! + +// check-pass +// ignore-tidy-end-whitespace +fn main() {} diff --git a/tests/ui/parser/shebang/sneaky-attrib.rs b/tests/ui/parser/shebang/sneaky-attrib.rs new file mode 100644 index 000000000..b406cc3aa --- /dev/null +++ b/tests/ui/parser/shebang/sneaky-attrib.rs @@ -0,0 +1,16 @@ +#!//bin/bash + + +// This could not possibly be a shebang & also a valid rust file, since a Rust file +// can't start with `[` +/* + [ (mixing comments to also test that we ignore both types of comments) + + */ + +[allow(unused_variables)] + +// check-pass +fn main() { + let x = 5; +} diff --git a/tests/ui/parser/shebang/valid-shebang.rs b/tests/ui/parser/shebang/valid-shebang.rs new file mode 100644 index 000000000..e480d3da3 --- /dev/null +++ b/tests/ui/parser/shebang/valid-shebang.rs @@ -0,0 +1,6 @@ +#!/usr/bin/env run-cargo-script + +// check-pass +fn main() { + println!("Hello World!"); +} diff --git a/tests/ui/parser/similar-tokens.rs b/tests/ui/parser/similar-tokens.rs new file mode 100644 index 000000000..e3024c61a --- /dev/null +++ b/tests/ui/parser/similar-tokens.rs @@ -0,0 +1,11 @@ +#![allow(unused_imports)] + +pub mod x { + pub struct A; + pub struct B; +} + +// `.` is similar to `,` so list parsing should continue to closing `}` +use x::{A. B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.` + +fn main() {} diff --git a/tests/ui/parser/similar-tokens.stderr b/tests/ui/parser/similar-tokens.stderr new file mode 100644 index 000000000..90acfc052 --- /dev/null +++ b/tests/ui/parser/similar-tokens.stderr @@ -0,0 +1,11 @@ +error: expected one of `,`, `::`, `as`, or `}`, found `.` + --> $DIR/similar-tokens.rs:9:10 + | +LL | use x::{A. B}; + | ^ + | | + | expected one of `,`, `::`, `as`, or `}` + | help: missing `,` + +error: aborting due to previous error + diff --git a/tests/ui/parser/slowparse-bstring.rs b/tests/ui/parser/slowparse-bstring.rs new file mode 100644 index 000000000..f3a6a6683 --- /dev/null +++ b/tests/ui/parser/slowparse-bstring.rs @@ -0,0 +1,6 @@ +// run-pass +// ignore-tidy-linelength + +// Issue #16624 + +fn main() { b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; } diff --git a/tests/ui/parser/slowparse-string.rs b/tests/ui/parser/slowparse-string.rs new file mode 100644 index 000000000..6ebc61dae --- /dev/null +++ b/tests/ui/parser/slowparse-string.rs @@ -0,0 +1,6 @@ +// run-pass +// ignore-tidy-linelength + +// Issue #16624 + +fn main() { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; } diff --git a/tests/ui/parser/stmt_expr_attrs_placement.rs b/tests/ui/parser/stmt_expr_attrs_placement.rs new file mode 100644 index 000000000..5e9d29a15 --- /dev/null +++ b/tests/ui/parser/stmt_expr_attrs_placement.rs @@ -0,0 +1,38 @@ +#![feature(stmt_expr_attributes)] + +// Test that various placements of the inner attribute are parsed correctly, +// or not. + +fn main() { + let a = #![allow(warnings)] (1, 2); + //~^ ERROR an inner attribute is not permitted in this context + + let b = (#![allow(warnings)] 1, 2); + //~^ ERROR an inner attribute is not permitted in this context + + let c = { + #![allow(warnings)] + (#![allow(warnings)] 1, 2) + //~^ ERROR an inner attribute is not permitted in this context + }; + + let d = { + #![allow(warnings)] + let e = (#![allow(warnings)] 1, 2); + //~^ ERROR an inner attribute is not permitted in this context + e + }; + + let e = [#![allow(warnings)] 1, 2]; + //~^ ERROR an inner attribute is not permitted in this context + + let f = [#![allow(warnings)] 1; 0]; + //~^ ERROR an inner attribute is not permitted in this context + + let g = match true { #![allow(warnings)] _ => {} }; + + + struct MyStruct { field: u8 } + let h = MyStruct { #![allow(warnings)] field: 0 }; + //~^ ERROR an inner attribute is not permitted in this context +} diff --git a/tests/ui/parser/stmt_expr_attrs_placement.stderr b/tests/ui/parser/stmt_expr_attrs_placement.stderr new file mode 100644 index 000000000..bf4005698 --- /dev/null +++ b/tests/ui/parser/stmt_expr_attrs_placement.stderr @@ -0,0 +1,65 @@ +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:7:13 + | +LL | let a = #![allow(warnings)] (1, 2); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:10:14 + | +LL | let b = (#![allow(warnings)] 1, 2); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:15:10 + | +LL | (#![allow(warnings)] 1, 2) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:21:18 + | +LL | let e = (#![allow(warnings)] 1, 2); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:26:14 + | +LL | let e = [#![allow(warnings)] 1, 2]; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:29:14 + | +LL | let f = [#![allow(warnings)] 1; 0]; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: an inner attribute is not permitted in this context + --> $DIR/stmt_expr_attrs_placement.rs:36:24 + | +LL | let h = MyStruct { #![allow(warnings)] field: 0 }; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files + = note: outer attributes, like `#[test]`, annotate the item following them + +error: aborting due to 7 previous errors + diff --git a/tests/ui/parser/stripped-nested-outline-mod-pass.rs b/tests/ui/parser/stripped-nested-outline-mod-pass.rs new file mode 100644 index 000000000..1b4669a43 --- /dev/null +++ b/tests/ui/parser/stripped-nested-outline-mod-pass.rs @@ -0,0 +1,13 @@ +// Expansion drives parsing, so conditional compilation will strip +// out outline modules and we will never attempt parsing them. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +mod foo { + mod bar { + mod baz; // This was an error before. + } +} diff --git a/tests/ui/parser/struct-default-values-and-missing-field-separator.fixed b/tests/ui/parser/struct-default-values-and-missing-field-separator.fixed new file mode 100644 index 000000000..28191b826 --- /dev/null +++ b/tests/ui/parser/struct-default-values-and-missing-field-separator.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +enum E { + A, +} + +struct S { + field1: i32, //~ ERROR default values on `struct` fields aren't supported + field2: E, //~ ERROR default values on `struct` fields aren't supported + field3: i32, //~ ERROR default values on `struct` fields aren't supported + field4: i32, //~ ERROR default values on `struct` fields aren't supported + field5: E, //~ ERROR default values on `struct` fields aren't supported + field6: E, //~ ERROR default values on `struct` fields aren't supported +} + +struct S1 { + field1: i32, //~ ERROR expected `,`, or `}`, found `field2` + field2: E, //~ ERROR expected `,`, or `}`, found `field3` + field3: i32, //~ ERROR default values on `struct` fields aren't supported + field4: i32, //~ ERROR default values on `struct` fields aren't supported + field5: E, //~ ERROR default values on `struct` fields aren't supported + field6: E, //~ ERROR default values on `struct` fields aren't supported +} + +struct S2 { + field1 : i32, //~ ERROR expected `:`, found `=` + field2: E, //~ ERROR expected `:`, found `;` +} + +const fn foo(_: i32) -> E { + E::A +} + +fn main() {} diff --git a/tests/ui/parser/struct-default-values-and-missing-field-separator.rs b/tests/ui/parser/struct-default-values-and-missing-field-separator.rs new file mode 100644 index 000000000..924cb08a9 --- /dev/null +++ b/tests/ui/parser/struct-default-values-and-missing-field-separator.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +enum E { + A, +} + +struct S { + field1: i32 = 42, //~ ERROR default values on `struct` fields aren't supported + field2: E = E::A, //~ ERROR default values on `struct` fields aren't supported + field3: i32 = 1 + 2, //~ ERROR default values on `struct` fields aren't supported + field4: i32 = { 1 + 2 }, //~ ERROR default values on `struct` fields aren't supported + field5: E = foo(42), //~ ERROR default values on `struct` fields aren't supported + field6: E = { foo(42) }, //~ ERROR default values on `struct` fields aren't supported +} + +struct S1 { + field1: i32 //~ ERROR expected `,`, or `}`, found `field2` + field2: E //~ ERROR expected `,`, or `}`, found `field3` + field3: i32 = 1 + 2, //~ ERROR default values on `struct` fields aren't supported + field4: i32 = { 1 + 2 }, //~ ERROR default values on `struct` fields aren't supported + field5: E = foo(42), //~ ERROR default values on `struct` fields aren't supported + field6: E = { foo(42) }, //~ ERROR default values on `struct` fields aren't supported +} + +struct S2 { + field1 = i32, //~ ERROR expected `:`, found `=` + field2; E, //~ ERROR expected `:`, found `;` +} + +const fn foo(_: i32) -> E { + E::A +} + +fn main() {} diff --git a/tests/ui/parser/struct-default-values-and-missing-field-separator.stderr b/tests/ui/parser/struct-default-values-and-missing-field-separator.stderr new file mode 100644 index 000000000..7f16ebcfc --- /dev/null +++ b/tests/ui/parser/struct-default-values-and-missing-field-separator.stderr @@ -0,0 +1,92 @@ +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:9:16 + | +LL | field1: i32 = 42, + | ^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:10:14 + | +LL | field2: E = E::A, + | ^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:11:16 + | +LL | field3: i32 = 1 + 2, + | ^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:12:16 + | +LL | field4: i32 = { 1 + 2 }, + | ^^^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:13:14 + | +LL | field5: E = foo(42), + | ^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:14:14 + | +LL | field6: E = { foo(42) }, + | ^^^^^^^^^^^^^^ help: remove this unsupported default value + +error: expected `,`, or `}`, found `field2` + --> $DIR/struct-default-values-and-missing-field-separator.rs:18:16 + | +LL | field1: i32 + | ^ help: try adding a comma: `,` + +error: expected `,`, or `}`, found `field3` + --> $DIR/struct-default-values-and-missing-field-separator.rs:19:14 + | +LL | field2: E + | ^ help: try adding a comma: `,` + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:20:16 + | +LL | field3: i32 = 1 + 2, + | ^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:21:16 + | +LL | field4: i32 = { 1 + 2 }, + | ^^^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:22:14 + | +LL | field5: E = foo(42), + | ^^^^^^^^^^ help: remove this unsupported default value + +error: default values on `struct` fields aren't supported + --> $DIR/struct-default-values-and-missing-field-separator.rs:23:14 + | +LL | field6: E = { foo(42) }, + | ^^^^^^^^^^^^^^ help: remove this unsupported default value + +error: expected `:`, found `=` + --> $DIR/struct-default-values-and-missing-field-separator.rs:27:12 + | +LL | field1 = i32, + | ^ + | | + | expected `:` + | help: field names and their types are separated with `:` + +error: expected `:`, found `;` + --> $DIR/struct-default-values-and-missing-field-separator.rs:28:11 + | +LL | field2; E, + | ^ + | | + | expected `:` + | help: field names and their types are separated with `:` + +error: aborting due to 14 previous errors + diff --git a/tests/ui/parser/struct-field-numeric-shorthand.rs b/tests/ui/parser/struct-field-numeric-shorthand.rs new file mode 100644 index 000000000..645abd9c7 --- /dev/null +++ b/tests/ui/parser/struct-field-numeric-shorthand.rs @@ -0,0 +1,9 @@ +struct Rgb(u8, u8, u8); + +fn main() { + let _ = Rgb { 0, 1, 2 }; + //~^ ERROR expected identifier, found `0` + //~| ERROR expected identifier, found `1` + //~| ERROR expected identifier, found `2` + //~| ERROR missing fields `0`, `1` and `2` in initializer of `Rgb` +} diff --git a/tests/ui/parser/struct-field-numeric-shorthand.stderr b/tests/ui/parser/struct-field-numeric-shorthand.stderr new file mode 100644 index 000000000..bfb8a931b --- /dev/null +++ b/tests/ui/parser/struct-field-numeric-shorthand.stderr @@ -0,0 +1,33 @@ +error: expected identifier, found `0` + --> $DIR/struct-field-numeric-shorthand.rs:4:19 + | +LL | let _ = Rgb { 0, 1, 2 }; + | --- ^ expected identifier + | | + | while parsing this struct + +error: expected identifier, found `1` + --> $DIR/struct-field-numeric-shorthand.rs:4:22 + | +LL | let _ = Rgb { 0, 1, 2 }; + | --- ^ expected identifier + | | + | while parsing this struct + +error: expected identifier, found `2` + --> $DIR/struct-field-numeric-shorthand.rs:4:25 + | +LL | let _ = Rgb { 0, 1, 2 }; + | --- ^ expected identifier + | | + | while parsing this struct + +error[E0063]: missing fields `0`, `1` and `2` in initializer of `Rgb` + --> $DIR/struct-field-numeric-shorthand.rs:4:13 + | +LL | let _ = Rgb { 0, 1, 2 }; + | ^^^ missing `0`, `1` and `2` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/parser/struct-filed-with-attr.fixed b/tests/ui/parser/struct-filed-with-attr.fixed new file mode 100644 index 000000000..a799ec8ca --- /dev/null +++ b/tests/ui/parser/struct-filed-with-attr.fixed @@ -0,0 +1,18 @@ +// Issue: 100461, Try to give a helpful diagnostic even when the next struct field has an attribute. +// run-rustfix + +struct Feelings { + owo: bool, + //~^ ERROR expected `,`, or `}`, found `#` + #[allow(unused)] + uwu: bool, +} + +impl Feelings { + #[allow(unused)] + fn hmm(&self) -> bool { + self.owo + } +} + +fn main() { } diff --git a/tests/ui/parser/struct-filed-with-attr.rs b/tests/ui/parser/struct-filed-with-attr.rs new file mode 100644 index 000000000..bfc78e15b --- /dev/null +++ b/tests/ui/parser/struct-filed-with-attr.rs @@ -0,0 +1,18 @@ +// Issue: 100461, Try to give a helpful diagnostic even when the next struct field has an attribute. +// run-rustfix + +struct Feelings { + owo: bool + //~^ ERROR expected `,`, or `}`, found `#` + #[allow(unused)] + uwu: bool, +} + +impl Feelings { + #[allow(unused)] + fn hmm(&self) -> bool { + self.owo + } +} + +fn main() { } diff --git a/tests/ui/parser/struct-filed-with-attr.stderr b/tests/ui/parser/struct-filed-with-attr.stderr new file mode 100644 index 000000000..c2cd7e82e --- /dev/null +++ b/tests/ui/parser/struct-filed-with-attr.stderr @@ -0,0 +1,8 @@ +error: expected `,`, or `}`, found `#` + --> $DIR/struct-filed-with-attr.rs:5:14 + | +LL | owo: bool + | ^ help: try adding a comma: `,` + +error: aborting due to previous error + diff --git a/tests/ui/parser/struct-literal-in-for.rs b/tests/ui/parser/struct-literal-in-for.rs new file mode 100644 index 000000000..3227ae37b --- /dev/null +++ b/tests/ui/parser/struct-literal-in-for.rs @@ -0,0 +1,17 @@ +struct Foo { + x: isize, +} + +impl Foo { + fn hi(&self) -> bool { + true + } +} + +fn main() { + for x in Foo { //~ ERROR struct literals are not allowed here + x: 3 //~^ ERROR `bool` is not an iterator + }.hi() { + println!("yo"); + } +} diff --git a/tests/ui/parser/struct-literal-in-for.stderr b/tests/ui/parser/struct-literal-in-for.stderr new file mode 100644 index 000000000..1c91eba68 --- /dev/null +++ b/tests/ui/parser/struct-literal-in-for.stderr @@ -0,0 +1,31 @@ +error: struct literals are not allowed here + --> $DIR/struct-literal-in-for.rs:12:14 + | +LL | for x in Foo { + | ______________^ +LL | | x: 3 +LL | | }.hi() { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ for x in (Foo { +LL | x: 3 +LL ~ }).hi() { + | + +error[E0277]: `bool` is not an iterator + --> $DIR/struct-literal-in-for.rs:12:14 + | +LL | for x in Foo { + | ______________^ +LL | | x: 3 +LL | | }.hi() { + | |__________^ `bool` is not an iterator + | + = help: the trait `Iterator` is not implemented for `bool` + = note: required for `bool` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/parser/struct-literal-in-if.rs b/tests/ui/parser/struct-literal-in-if.rs new file mode 100644 index 000000000..2ce2c8f18 --- /dev/null +++ b/tests/ui/parser/struct-literal-in-if.rs @@ -0,0 +1,17 @@ +struct Foo { + x: isize, +} + +impl Foo { + fn hi(&self) -> bool { + true + } +} + +fn main() { + if Foo { //~ ERROR struct literals are not allowed here + x: 3 + }.hi() { + println!("yo"); + } +} diff --git a/tests/ui/parser/struct-literal-in-if.stderr b/tests/ui/parser/struct-literal-in-if.stderr new file mode 100644 index 000000000..b5a9864bb --- /dev/null +++ b/tests/ui/parser/struct-literal-in-if.stderr @@ -0,0 +1,18 @@ +error: struct literals are not allowed here + --> $DIR/struct-literal-in-if.rs:12:8 + | +LL | if Foo { + | ________^ +LL | | x: 3 +LL | | }.hi() { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ if (Foo { +LL | x: 3 +LL ~ }).hi() { + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.rs b/tests/ui/parser/struct-literal-in-match-discriminant.rs new file mode 100644 index 000000000..ce132df5a --- /dev/null +++ b/tests/ui/parser/struct-literal-in-match-discriminant.rs @@ -0,0 +1,13 @@ +struct Foo { + x: isize, +} + +fn main() { + match Foo { //~ ERROR struct literals are not allowed here + x: 3 + } { + Foo { + x: x + } => {} + } +} diff --git a/tests/ui/parser/struct-literal-in-match-discriminant.stderr b/tests/ui/parser/struct-literal-in-match-discriminant.stderr new file mode 100644 index 000000000..692b4d735 --- /dev/null +++ b/tests/ui/parser/struct-literal-in-match-discriminant.stderr @@ -0,0 +1,18 @@ +error: struct literals are not allowed here + --> $DIR/struct-literal-in-match-discriminant.rs:6:11 + | +LL | match Foo { + | ___________^ +LL | | x: 3 +LL | | } { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ match (Foo { +LL | x: 3 +LL ~ }) { + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/struct-literal-in-match-guard.rs b/tests/ui/parser/struct-literal-in-match-guard.rs new file mode 100644 index 000000000..bf0551b5c --- /dev/null +++ b/tests/ui/parser/struct-literal-in-match-guard.rs @@ -0,0 +1,18 @@ +// check-pass + +// Unlike `if` condition, `match` guards accept struct literals. +// This is detected in . + +#[derive(PartialEq)] +struct Foo { + x: isize, +} + +fn foo(f: Foo) { + match () { + () if f == Foo { x: 42 } => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/parser/struct-literal-in-while.rs b/tests/ui/parser/struct-literal-in-while.rs new file mode 100644 index 000000000..5000ce85b --- /dev/null +++ b/tests/ui/parser/struct-literal-in-while.rs @@ -0,0 +1,17 @@ +struct Foo { + x: isize, +} + +impl Foo { + fn hi(&self) -> bool { + true + } +} + +fn main() { + while Foo { //~ ERROR struct literals are not allowed here + x: 3 + }.hi() { + println!("yo"); + } +} diff --git a/tests/ui/parser/struct-literal-in-while.stderr b/tests/ui/parser/struct-literal-in-while.stderr new file mode 100644 index 000000000..17e9277e0 --- /dev/null +++ b/tests/ui/parser/struct-literal-in-while.stderr @@ -0,0 +1,18 @@ +error: struct literals are not allowed here + --> $DIR/struct-literal-in-while.rs:12:11 + | +LL | while Foo { + | ___________^ +LL | | x: 3 +LL | | }.hi() { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ while (Foo { +LL | x: 3 +LL ~ }).hi() { + | + +error: aborting due to previous error + diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.rs b/tests/ui/parser/struct-literal-restrictions-in-lamda.rs new file mode 100644 index 000000000..e185153dc --- /dev/null +++ b/tests/ui/parser/struct-literal-restrictions-in-lamda.rs @@ -0,0 +1,17 @@ +struct Foo { + x: isize, +} + +impl Foo { + fn hi(&self) -> bool { + true + } +} + +fn main() { + while || Foo { //~ ERROR struct literals are not allowed here + x: 3 //~^ ERROR mismatched types + }.hi() { + println!("yo"); + } +} diff --git a/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr b/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr new file mode 100644 index 000000000..0852c7cb4 --- /dev/null +++ b/tests/ui/parser/struct-literal-restrictions-in-lamda.stderr @@ -0,0 +1,37 @@ +error: struct literals are not allowed here + --> $DIR/struct-literal-restrictions-in-lamda.rs:12:14 + | +LL | while || Foo { + | ______________^ +LL | | x: 3 +LL | | }.hi() { + | |_____^ + | +help: surround the struct literal with parentheses + | +LL ~ while || (Foo { +LL | x: 3 +LL ~ }).hi() { + | + +error[E0308]: mismatched types + --> $DIR/struct-literal-restrictions-in-lamda.rs:12:11 + | +LL | while || Foo { + | ___________^ +LL | | x: 3 +LL | | }.hi() { + | |__________^ expected `bool`, found closure + | + = note: expected type `bool` + found closure `[closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 12:13]` +help: use parentheses to call this closure + | +LL ~ while (|| Foo { +LL | x: 3 +LL ~ }.hi())() { + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/struct-literal-variant-in-if.rs b/tests/ui/parser/struct-literal-variant-in-if.rs new file mode 100644 index 000000000..4ef8effaf --- /dev/null +++ b/tests/ui/parser/struct-literal-variant-in-if.rs @@ -0,0 +1,25 @@ +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +enum E { + V { field: bool }, + I { field1: bool, field2: usize }, + J { field: isize }, + K { field: &'static str}, +} +fn test_E(x: E) { + let field = true; + if x == E::V { field } {} + //~^ ERROR expected value, found struct variant `E::V` + //~| ERROR mismatched types + if x == E::I { field1: true, field2: 42 } {} + //~^ ERROR struct literals are not allowed here + if x == E::V { field: false } {} + //~^ ERROR struct literals are not allowed here + if x == E::J { field: -42 } {} + //~^ ERROR struct literals are not allowed here + if x == E::K { field: "" } {} + //~^ ERROR struct literals are not allowed here + let y: usize = (); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/parser/struct-literal-variant-in-if.stderr b/tests/ui/parser/struct-literal-variant-in-if.stderr new file mode 100644 index 000000000..9f0c0074d --- /dev/null +++ b/tests/ui/parser/struct-literal-variant-in-if.stderr @@ -0,0 +1,71 @@ +error: struct literals are not allowed here + --> $DIR/struct-literal-variant-in-if.rs:13:13 + | +LL | if x == E::I { field1: true, field2: 42 } {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::I { field1: true, field2: 42 }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literal-variant-in-if.rs:15:13 + | +LL | if x == E::V { field: false } {} + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::V { field: false }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literal-variant-in-if.rs:17:13 + | +LL | if x == E::J { field: -42 } {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::J { field: -42 }) {} + | + + + +error: struct literals are not allowed here + --> $DIR/struct-literal-variant-in-if.rs:19:13 + | +LL | if x == E::K { field: "" } {} + | ^^^^^^^^^^^^^^^^^^ + | +help: surround the struct literal with parentheses + | +LL | if x == (E::K { field: "" }) {} + | + + + +error[E0533]: expected value, found struct variant `E::V` + --> $DIR/struct-literal-variant-in-if.rs:10:13 + | +LL | if x == E::V { field } {} + | ^^^^ not a value + +error[E0308]: mismatched types + --> $DIR/struct-literal-variant-in-if.rs:10:20 + | +LL | if x == E::V { field } {} + | ---------------^^^^^-- + | | | + | | expected `()`, found `bool` + | expected this to be `()` + +error[E0308]: mismatched types + --> $DIR/struct-literal-variant-in-if.rs:21:20 + | +LL | let y: usize = (); + | ----- ^^ expected `usize`, found `()` + | | + | expected due to this + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0308, E0533. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/suggest-assoc-const.fixed b/tests/ui/parser/suggest-assoc-const.fixed new file mode 100644 index 000000000..259f37b23 --- /dev/null +++ b/tests/ui/parser/suggest-assoc-const.fixed @@ -0,0 +1,10 @@ +// Issue: 101797, Suggest associated const for incorrect use of let in traits +// run-rustfix +trait Trait { + const _X: i32; + //~^ ERROR non-item in item list +} + +fn main() { + +} diff --git a/tests/ui/parser/suggest-assoc-const.rs b/tests/ui/parser/suggest-assoc-const.rs new file mode 100644 index 000000000..c7be712ec --- /dev/null +++ b/tests/ui/parser/suggest-assoc-const.rs @@ -0,0 +1,10 @@ +// Issue: 101797, Suggest associated const for incorrect use of let in traits +// run-rustfix +trait Trait { + let _X: i32; + //~^ ERROR non-item in item list +} + +fn main() { + +} diff --git a/tests/ui/parser/suggest-assoc-const.stderr b/tests/ui/parser/suggest-assoc-const.stderr new file mode 100644 index 000000000..2ddfa07c5 --- /dev/null +++ b/tests/ui/parser/suggest-assoc-const.stderr @@ -0,0 +1,8 @@ +error: non-item in item list + --> $DIR/suggest-assoc-const.rs:4:5 + | +LL | let _X: i32; + | ^^^ help: consider using `const` instead of `let` for associated const: `const` + +error: aborting due to previous error + diff --git a/tests/ui/parser/suggest-const-for-global-var.rs b/tests/ui/parser/suggest-const-for-global-var.rs new file mode 100644 index 000000000..d6216cb7a --- /dev/null +++ b/tests/ui/parser/suggest-const-for-global-var.rs @@ -0,0 +1,6 @@ +let X: i32 = 12; +//~^ ERROR expected item, found keyword `let` + +fn main() { + println!("{}", X); +} diff --git a/tests/ui/parser/suggest-const-for-global-var.stderr b/tests/ui/parser/suggest-const-for-global-var.stderr new file mode 100644 index 000000000..94e44ec7f --- /dev/null +++ b/tests/ui/parser/suggest-const-for-global-var.stderr @@ -0,0 +1,8 @@ +error: expected item, found keyword `let` + --> $DIR/suggest-const-for-global-var.rs:1:1 + | +LL | let X: i32 = 12; + | ^^^ consider using `const` or `static` instead of `let` for global variables + +error: aborting due to previous error + diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed new file mode 100644 index 000000000..637047354 --- /dev/null +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +trait Foo { + fn bar() {} //~ ERROR non-item in item list +} + +fn main() {} diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs new file mode 100644 index 000000000..4650b05e2 --- /dev/null +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs @@ -0,0 +1,7 @@ +// run-rustfix + +trait Foo { + fn bar() {}; //~ ERROR non-item in item list +} + +fn main() {} diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr new file mode 100644 index 000000000..396e0c130 --- /dev/null +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -0,0 +1,15 @@ +error: non-item in item list + --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16 + | +LL | trait Foo { + | - item list starts here +LL | fn bar() {}; + | ^ + | | + | non-item starts here + | help: consider removing this semicolon +LL | } + | - item list ends here + +error: aborting due to previous error + diff --git a/tests/ui/parser/suggest-semi-in-array.rs b/tests/ui/parser/suggest-semi-in-array.rs new file mode 100644 index 000000000..9ce2e59e5 --- /dev/null +++ b/tests/ui/parser/suggest-semi-in-array.rs @@ -0,0 +1,5 @@ +fn main() { + let v = [1 + 2]; + //~^ ERROR expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found `2` +} diff --git a/tests/ui/parser/suggest-semi-in-array.stderr b/tests/ui/parser/suggest-semi-in-array.stderr new file mode 100644 index 000000000..d7cd6efae --- /dev/null +++ b/tests/ui/parser/suggest-semi-in-array.stderr @@ -0,0 +1,10 @@ +error: expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found `2` + --> $DIR/suggest-semi-in-array.rs:3:5 + | +LL | let v = [1 + | - expected one of `,`, `.`, `;`, `?`, `]`, or an operator +LL | 2]; + | ^ unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/parser/suggest-semicolon-before-array.fixed b/tests/ui/parser/suggest-semicolon-before-array.fixed new file mode 100644 index 000000000..a06b58b27 --- /dev/null +++ b/tests/ui/parser/suggest-semicolon-before-array.fixed @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] + +fn foo() {} + +fn bar() -> [u8; 2] { + foo(); + [1, 3] //~ ERROR expected `;`, found `[` +} + +fn main() {} diff --git a/tests/ui/parser/suggest-semicolon-before-array.rs b/tests/ui/parser/suggest-semicolon-before-array.rs new file mode 100644 index 000000000..f601ca2ae --- /dev/null +++ b/tests/ui/parser/suggest-semicolon-before-array.rs @@ -0,0 +1,11 @@ +// run-rustfix +#![allow(dead_code)] + +fn foo() {} + +fn bar() -> [u8; 2] { + foo() + [1, 3] //~ ERROR expected `;`, found `[` +} + +fn main() {} diff --git a/tests/ui/parser/suggest-semicolon-before-array.stderr b/tests/ui/parser/suggest-semicolon-before-array.stderr new file mode 100644 index 000000000..8a33321fb --- /dev/null +++ b/tests/ui/parser/suggest-semicolon-before-array.stderr @@ -0,0 +1,13 @@ +error: expected `;`, found `[` + --> $DIR/suggest-semicolon-before-array.rs:8:5 + | +LL | [1, 3] + | ^ + | +help: consider adding `;` here + | +LL | foo(); + | + + +error: aborting due to previous error + diff --git a/tests/ui/parser/trailing-carriage-return-in-string.rs b/tests/ui/parser/trailing-carriage-return-in-string.rs new file mode 100644 index 000000000..5d3c31944 --- /dev/null +++ b/tests/ui/parser/trailing-carriage-return-in-string.rs @@ -0,0 +1,14 @@ +// Issue #11669 + +// ignore-tidy-cr + +fn main() { + // \r\n + let ok = "This is \ + a test"; + // \r only + let bad = "This is \ a test"; + //~^ ERROR unknown character escape: `\r` + //~| HELP this is an isolated carriage return + +} diff --git a/tests/ui/parser/trailing-carriage-return-in-string.stderr b/tests/ui/parser/trailing-carriage-return-in-string.stderr new file mode 100644 index 000000000..8a44e0270 --- /dev/null +++ b/tests/ui/parser/trailing-carriage-return-in-string.stderr @@ -0,0 +1,10 @@ +error: unknown character escape: `\r` + --> $DIR/trailing-carriage-return-in-string.rs:10:25 + | +LL | let bad = "This is \ a test"; + | ^ unknown character escape + | + = help: this is an isolated carriage return; consider checking your editor and version control settings + +error: aborting due to previous error + diff --git a/tests/ui/parser/trailing-plus-in-bounds.rs b/tests/ui/parser/trailing-plus-in-bounds.rs new file mode 100644 index 000000000..400649bcf --- /dev/null +++ b/tests/ui/parser/trailing-plus-in-bounds.rs @@ -0,0 +1,9 @@ +// check-pass + +#![allow(bare_trait_objects)] + +use std::fmt::Debug; + +fn main() { + let x: Box = Box::new(3) as Box; // Trailing `+` is OK +} diff --git a/tests/ui/parser/trailing-question-in-macro-type.rs b/tests/ui/parser/trailing-question-in-macro-type.rs new file mode 100644 index 000000000..e2a681ddd --- /dev/null +++ b/tests/ui/parser/trailing-question-in-macro-type.rs @@ -0,0 +1,14 @@ +macro_rules! fn_expr { + ($return_type:ty : $body:expr) => { + (|| -> $return_type { $body })() + }; + ($body:expr) => { + (|| $body)() + }; +} + + +fn main() { + fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) }; + //~^ ERROR cannot find value `o` in this scope +} diff --git a/tests/ui/parser/trailing-question-in-macro-type.stderr b/tests/ui/parser/trailing-question-in-macro-type.stderr new file mode 100644 index 000000000..c096ae04f --- /dev/null +++ b/tests/ui/parser/trailing-question-in-macro-type.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `o` in this scope + --> $DIR/trailing-question-in-macro-type.rs:12:15 + | +LL | fn_expr!{ o?.when(|&i| i > 0)?.when(|&i| i%2 == 0) }; + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/trailing-question-in-type.fixed b/tests/ui/parser/trailing-question-in-type.fixed new file mode 100644 index 000000000..6ea24484e --- /dev/null +++ b/tests/ui/parser/trailing-question-in-type.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn foo() -> Option { //~ ERROR invalid `?` in type + let x: Option = Some(1); //~ ERROR invalid `?` in type + x +} + +fn main() { + let _: Option = foo(); +} diff --git a/tests/ui/parser/trailing-question-in-type.rs b/tests/ui/parser/trailing-question-in-type.rs new file mode 100644 index 000000000..b1c508365 --- /dev/null +++ b/tests/ui/parser/trailing-question-in-type.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn foo() -> i32? { //~ ERROR invalid `?` in type + let x: i32? = Some(1); //~ ERROR invalid `?` in type + x +} + +fn main() { + let _: Option = foo(); +} diff --git a/tests/ui/parser/trailing-question-in-type.stderr b/tests/ui/parser/trailing-question-in-type.stderr new file mode 100644 index 000000000..a3cd419c0 --- /dev/null +++ b/tests/ui/parser/trailing-question-in-type.stderr @@ -0,0 +1,24 @@ +error: invalid `?` in type + --> $DIR/trailing-question-in-type.rs:3:16 + | +LL | fn foo() -> i32? { + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | fn foo() -> Option { + | +++++++ ~ + +error: invalid `?` in type + --> $DIR/trailing-question-in-type.rs:4:15 + | +LL | let x: i32? = Some(1); + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | let x: Option = Some(1); + | +++++++ ~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/trait-bounds-not-on-impl.rs b/tests/ui/parser/trait-bounds-not-on-impl.rs new file mode 100644 index 000000000..02563847e --- /dev/null +++ b/tests/ui/parser/trait-bounds-not-on-impl.rs @@ -0,0 +1,7 @@ +trait Foo {} + +struct Bar; + +impl Foo + Owned for Bar {} //~ ERROR expected a trait, found type + +fn main() { } diff --git a/tests/ui/parser/trait-bounds-not-on-impl.stderr b/tests/ui/parser/trait-bounds-not-on-impl.stderr new file mode 100644 index 000000000..8d2d5e3d7 --- /dev/null +++ b/tests/ui/parser/trait-bounds-not-on-impl.stderr @@ -0,0 +1,8 @@ +error: expected a trait, found type + --> $DIR/trait-bounds-not-on-impl.rs:5:6 + | +LL | impl Foo + Owned for Bar {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/tests/ui/parser/trait-item-with-defaultness-fail-semantic.rs new file mode 100644 index 000000000..f2d97b7ba --- /dev/null +++ b/tests/ui/parser/trait-item-with-defaultness-fail-semantic.rs @@ -0,0 +1,12 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +fn main() {} + +trait X { + default const A: u8; //~ ERROR `default` is only allowed on items in trait impls + default const B: u8 = 0; //~ ERROR `default` is only allowed on items in trait impls + default type D; //~ ERROR `default` is only allowed on items in trait impls + default type C: Ord; //~ ERROR `default` is only allowed on items in trait impls + default fn f1(); //~ ERROR `default` is only allowed on items in trait impls + default fn f2() {} //~ ERROR `default` is only allowed on items in trait impls +} diff --git a/tests/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/tests/ui/parser/trait-item-with-defaultness-fail-semantic.stderr new file mode 100644 index 000000000..be858cd65 --- /dev/null +++ b/tests/ui/parser/trait-item-with-defaultness-fail-semantic.stderr @@ -0,0 +1,60 @@ +error: `default` is only allowed on items in trait impls + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5 + | +LL | default const A: u8; + | -------^^^^^^^^^^^^^ + | | + | `default` because of this + +error: `default` is only allowed on items in trait impls + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5 + | +LL | default const B: u8 = 0; + | -------^^^^^^^^^^^^^^^^^ + | | + | `default` because of this + +error: `default` is only allowed on items in trait impls + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5 + | +LL | default type D; + | -------^^^^^^^^ + | | + | `default` because of this + +error: `default` is only allowed on items in trait impls + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5 + | +LL | default type C: Ord; + | -------^^^^^^^^^^^^^ + | | + | `default` because of this + +error: `default` is only allowed on items in trait impls + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:10:5 + | +LL | default fn f1(); + | -------^^^^^^^^^ + | | + | `default` because of this + +error: `default` is only allowed on items in trait impls + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:11:5 + | +LL | default fn f2() {} + | -------^^^^^^^^ + | | + | `default` because of this + +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/trait-item-with-defaultness-fail-semantic.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 6 previous errors; 1 warning emitted + diff --git a/tests/ui/parser/trait-item-with-defaultness-pass.rs b/tests/ui/parser/trait-item-with-defaultness-pass.rs new file mode 100644 index 000000000..a6318bd99 --- /dev/null +++ b/tests/ui/parser/trait-item-with-defaultness-pass.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +trait X { + default const A: u8; + default const B: u8 = 0; + default type D; + default type C: Ord; + default fn f1(); + default fn f2() {} +} diff --git a/tests/ui/parser/trait-object-bad-parens.rs b/tests/ui/parser/trait-object-bad-parens.rs new file mode 100644 index 000000000..8e267c744 --- /dev/null +++ b/tests/ui/parser/trait-object-bad-parens.rs @@ -0,0 +1,16 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] +#![allow(bare_trait_objects)] + +auto trait Auto {} + +fn main() { + let _: Box<((Auto)) + Auto>; + //~^ ERROR expected a path on the left-hand side of `+`, not `((Auto))` + let _: Box<(Auto + Auto) + Auto>; + //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto + Auto)` + let _: Box<(Auto +) + Auto>; + //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto)` + let _: Box<(dyn Auto) + Auto>; + //~^ ERROR expected a path on the left-hand side of `+`, not `(dyn Auto)` +} diff --git a/tests/ui/parser/trait-object-bad-parens.stderr b/tests/ui/parser/trait-object-bad-parens.stderr new file mode 100644 index 000000000..74e484eeb --- /dev/null +++ b/tests/ui/parser/trait-object-bad-parens.stderr @@ -0,0 +1,27 @@ +error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))` + --> $DIR/trait-object-bad-parens.rs:8:16 + | +LL | let _: Box<((Auto)) + Auto>; + | ^^^^^^^^^^^^^^^ expected a path + +error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)` + --> $DIR/trait-object-bad-parens.rs:10:16 + | +LL | let _: Box<(Auto + Auto) + Auto>; + | ^^^^^^^^^^^^^^^^^^^^ expected a path + +error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)` + --> $DIR/trait-object-bad-parens.rs:12:16 + | +LL | let _: Box<(Auto +) + Auto>; + | ^^^^^^^^^^^^^^^ expected a path + +error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)` + --> $DIR/trait-object-bad-parens.rs:14:16 + | +LL | let _: Box<(dyn Auto) + Auto>; + | ^^^^^^^^^^^^^^^^^ expected a path + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0178`. diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs new file mode 100644 index 000000000..cc04ac052 --- /dev/null +++ b/tests/ui/parser/trait-object-delimiters.rs @@ -0,0 +1,17 @@ +// edition:2018 + +fn foo1(_: &dyn Drop + AsRef) {} //~ ERROR ambiguous `+` in a type +//~^ ERROR only auto traits can be used as additional traits in a trait object + +fn foo2(_: &dyn (Drop + AsRef)) {} //~ ERROR incorrect braces around trait bounds + +fn foo3(_: &dyn {Drop + AsRef}) {} //~ ERROR expected parameter name, found `{` +//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` +//~| ERROR at least one trait is required for an object type + +fn foo4(_: &dyn >) {} //~ ERROR expected identifier, found `<` + +fn foo5(_: &(dyn Drop + dyn AsRef)) {} //~ ERROR invalid `dyn` keyword +//~^ ERROR only auto traits can be used as additional traits in a trait object + +fn main() {} diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr new file mode 100644 index 000000000..99c451545 --- /dev/null +++ b/tests/ui/parser/trait-object-delimiters.stderr @@ -0,0 +1,78 @@ +error: ambiguous `+` in a type + --> $DIR/trait-object-delimiters.rs:3:13 + | +LL | fn foo1(_: &dyn Drop + AsRef) {} + | ^^^^^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(dyn Drop + AsRef)` + +error: incorrect braces around trait bounds + --> $DIR/trait-object-delimiters.rs:6:17 + | +LL | fn foo2(_: &dyn (Drop + AsRef)) {} + | ^ ^ + | +help: remove the parentheses + | +LL - fn foo2(_: &dyn (Drop + AsRef)) {} +LL + fn foo2(_: &dyn Drop + AsRef) {} + | + +error: expected parameter name, found `{` + --> $DIR/trait-object-delimiters.rs:8:17 + | +LL | fn foo3(_: &dyn {Drop + AsRef}) {} + | ^ expected parameter name + +error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` + --> $DIR/trait-object-delimiters.rs:8:17 + | +LL | fn foo3(_: &dyn {Drop + AsRef}) {} + | -^ expected one of 10 possible tokens + | | + | help: missing `,` + +error: expected identifier, found `<` + --> $DIR/trait-object-delimiters.rs:12:17 + | +LL | fn foo4(_: &dyn >) {} + | ^ expected identifier + +error: invalid `dyn` keyword + --> $DIR/trait-object-delimiters.rs:14:25 + | +LL | fn foo5(_: &(dyn Drop + dyn AsRef)) {} + | ^^^ help: remove this keyword + | + = help: `dyn` is only needed at the start of a trait `+`-separated list + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-object-delimiters.rs:3:24 + | +LL | fn foo1(_: &dyn Drop + AsRef) {} + | ---- ^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Drop + AsRef {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0224]: at least one trait is required for an object type + --> $DIR/trait-object-delimiters.rs:8:13 + | +LL | fn foo3(_: &dyn {Drop + AsRef}) {} + | ^^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-object-delimiters.rs:14:29 + | +LL | fn foo5(_: &(dyn Drop + dyn AsRef)) {} + | ---- ^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Drop + AsRef {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0224, E0225. +For more information about an error, try `rustc --explain E0224`. diff --git a/tests/ui/parser/trait-object-lifetime-parens.rs b/tests/ui/parser/trait-object-lifetime-parens.rs new file mode 100644 index 000000000..f44ebe5ba --- /dev/null +++ b/tests/ui/parser/trait-object-lifetime-parens.rs @@ -0,0 +1,13 @@ +#![allow(bare_trait_objects)] + +trait Trait {} + +fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not supported + +fn check<'a>() { + let _: Box; //~ ERROR parenthesized lifetime bounds are not supported + // FIXME: It'd be great if we could add suggestion to the following case. + let _: Box<('a) + Trait>; //~ ERROR lifetime in trait object type must be followed by `+` +} + +fn main() {} diff --git a/tests/ui/parser/trait-object-lifetime-parens.stderr b/tests/ui/parser/trait-object-lifetime-parens.stderr new file mode 100644 index 000000000..9c7a9662c --- /dev/null +++ b/tests/ui/parser/trait-object-lifetime-parens.stderr @@ -0,0 +1,20 @@ +error: parenthesized lifetime bounds are not supported + --> $DIR/trait-object-lifetime-parens.rs:5:21 + | +LL | fn f<'a, T: Trait + ('a)>() {} + | ^^^^ help: remove the parentheses + +error: parenthesized lifetime bounds are not supported + --> $DIR/trait-object-lifetime-parens.rs:8:24 + | +LL | let _: Box; + | ^^^^ help: remove the parentheses + +error: lifetime in trait object type must be followed by `+` + --> $DIR/trait-object-lifetime-parens.rs:10:17 + | +LL | let _: Box<('a) + Trait>; + | ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/trait-object-polytrait-priority.rs b/tests/ui/parser/trait-object-polytrait-priority.rs new file mode 100644 index 000000000..63425f3e2 --- /dev/null +++ b/tests/ui/parser/trait-object-polytrait-priority.rs @@ -0,0 +1,10 @@ +#![allow(bare_trait_objects)] + +trait Trait<'a> {} + +fn main() { + let _: &for<'a> Trait<'a> + 'static; + //~^ ERROR expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>` + //~| HELP try adding parentheses + //~| SUGGESTION &(for<'a> Trait<'a> + 'static) +} diff --git a/tests/ui/parser/trait-object-polytrait-priority.stderr b/tests/ui/parser/trait-object-polytrait-priority.stderr new file mode 100644 index 000000000..a6add6079 --- /dev/null +++ b/tests/ui/parser/trait-object-polytrait-priority.stderr @@ -0,0 +1,9 @@ +error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>` + --> $DIR/trait-object-polytrait-priority.rs:6:12 + | +LL | let _: &for<'a> Trait<'a> + 'static; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try adding parentheses: `&(for<'a> Trait<'a> + 'static)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0178`. diff --git a/tests/ui/parser/trait-object-trait-parens.rs b/tests/ui/parser/trait-object-trait-parens.rs new file mode 100644 index 000000000..438034bc3 --- /dev/null +++ b/tests/ui/parser/trait-object-trait-parens.rs @@ -0,0 +1,23 @@ +trait Trait<'a> {} + +trait Obj {} + +fn f Trait<'a>)>() {} + +fn main() { + let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; + //~^ ERROR `?Trait` is not permitted in trait object types + //~| ERROR only auto traits can be used as additional traits + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let _: Box Trait<'a>) + (Obj)>; + //~^ ERROR `?Trait` is not permitted in trait object types + //~| ERROR only auto traits can be used as additional traits + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let _: Box Trait<'a> + (Obj) + (?Sized)>; + //~^ ERROR `?Trait` is not permitted in trait object types + //~| ERROR only auto traits can be used as additional traits + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr new file mode 100644 index 000000000..5e07a3fe6 --- /dev/null +++ b/tests/ui/parser/trait-object-trait-parens.stderr @@ -0,0 +1,94 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:8:24 + | +LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; + | ^^^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:13:16 + | +LL | let _: Box Trait<'a>) + (Obj)>; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:18:44 + | +LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; + | ^^^^^^^^ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/trait-object-trait-parens.rs:8:16 + | +LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | let _: Box Trait<'a>)>; + | +++ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-object-trait-parens.rs:8:35 + | +LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; + | ----- ^^^^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + for<'a> Trait<'a> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/trait-object-trait-parens.rs:13:16 + | +LL | let _: Box Trait<'a>) + (Obj)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let _: Box Trait<'a>) + (Obj)>; + | +++ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-object-trait-parens.rs:13:47 + | +LL | let _: Box Trait<'a>) + (Obj)>; + | ------------------- ^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/trait-object-trait-parens.rs:18:16 + | +LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; + | +++ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-object-trait-parens.rs:18:36 + | +LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; + | ----------------- ^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error: aborting due to 6 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/parser/trait-plusequal-splitting.rs b/tests/ui/parser/trait-plusequal-splitting.rs new file mode 100644 index 000000000..6ca677450 --- /dev/null +++ b/tests/ui/parser/trait-plusequal-splitting.rs @@ -0,0 +1,8 @@ +// Fixes issue where `+` in generics weren't parsed if they were part of a `+=`. + +// check-pass + +struct Whitespace { t: T } +struct TokenSplit { t: T } + +fn main() {} diff --git a/tests/ui/parser/trait-pub-assoc-const.rs b/tests/ui/parser/trait-pub-assoc-const.rs new file mode 100644 index 000000000..219ffa309 --- /dev/null +++ b/tests/ui/parser/trait-pub-assoc-const.rs @@ -0,0 +1,6 @@ +trait Foo { + pub const Foo: u32; + //~^ ERROR unnecessary visibility qualifier +} + +fn main() {} diff --git a/tests/ui/parser/trait-pub-assoc-const.stderr b/tests/ui/parser/trait-pub-assoc-const.stderr new file mode 100644 index 000000000..efd09a036 --- /dev/null +++ b/tests/ui/parser/trait-pub-assoc-const.stderr @@ -0,0 +1,9 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/trait-pub-assoc-const.rs:2:5 + | +LL | pub const Foo: u32; + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/trait-pub-assoc-ty.rs b/tests/ui/parser/trait-pub-assoc-ty.rs new file mode 100644 index 000000000..a78dfbdcd --- /dev/null +++ b/tests/ui/parser/trait-pub-assoc-ty.rs @@ -0,0 +1,6 @@ +trait Foo { + pub type Foo; + //~^ ERROR unnecessary visibility qualifier +} + +fn main() {} diff --git a/tests/ui/parser/trait-pub-assoc-ty.stderr b/tests/ui/parser/trait-pub-assoc-ty.stderr new file mode 100644 index 000000000..e76373f5c --- /dev/null +++ b/tests/ui/parser/trait-pub-assoc-ty.stderr @@ -0,0 +1,9 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/trait-pub-assoc-ty.rs:2:5 + | +LL | pub type Foo; + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/trait-pub-method.rs b/tests/ui/parser/trait-pub-method.rs new file mode 100644 index 000000000..1f6ee028a --- /dev/null +++ b/tests/ui/parser/trait-pub-method.rs @@ -0,0 +1,6 @@ +trait Foo { + pub fn foo(); + //~^ ERROR unnecessary visibility qualifier +} + +fn main() {} diff --git a/tests/ui/parser/trait-pub-method.stderr b/tests/ui/parser/trait-pub-method.stderr new file mode 100644 index 000000000..0e3fe027c --- /dev/null +++ b/tests/ui/parser/trait-pub-method.stderr @@ -0,0 +1,9 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/trait-pub-method.rs:2:5 + | +LL | pub fn foo(); + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/parser/type-alias-where-fixable.fixed b/tests/ui/parser/type-alias-where-fixable.fixed new file mode 100644 index 000000000..2f47c0d91 --- /dev/null +++ b/tests/ui/parser/type-alias-where-fixable.fixed @@ -0,0 +1,28 @@ +// check-pass +// run-rustfix + +trait Trait { + // Fine. + type Assoc where u32: Copy; + // Fine. + type Assoc2 where u32: Copy, i32: Copy; +} + +impl Trait for u32 { + // Not fine, suggests moving. + type Assoc = () where u32: Copy; + //~^ WARNING where clause not allowed here + // Not fine, suggests moving `u32: Copy` + type Assoc2 = () where i32: Copy, u32: Copy; + //~^ WARNING where clause not allowed here +} + +impl Trait for i32 { + // Fine. + type Assoc = () where u32: Copy; + // Not fine, suggests moving both. + type Assoc2 = () where u32: Copy, i32: Copy; + //~^ WARNING where clause not allowed here +} + +fn main() {} diff --git a/tests/ui/parser/type-alias-where-fixable.rs b/tests/ui/parser/type-alias-where-fixable.rs new file mode 100644 index 000000000..b20aa9398 --- /dev/null +++ b/tests/ui/parser/type-alias-where-fixable.rs @@ -0,0 +1,28 @@ +// check-pass +// run-rustfix + +trait Trait { + // Fine. + type Assoc where u32: Copy; + // Fine. + type Assoc2 where u32: Copy, i32: Copy; +} + +impl Trait for u32 { + // Not fine, suggests moving. + type Assoc where u32: Copy = (); + //~^ WARNING where clause not allowed here + // Not fine, suggests moving `u32: Copy` + type Assoc2 where u32: Copy = () where i32: Copy; + //~^ WARNING where clause not allowed here +} + +impl Trait for i32 { + // Fine. + type Assoc = () where u32: Copy; + // Not fine, suggests moving both. + type Assoc2 where u32: Copy, i32: Copy = (); + //~^ WARNING where clause not allowed here +} + +fn main() {} diff --git a/tests/ui/parser/type-alias-where-fixable.stderr b/tests/ui/parser/type-alias-where-fixable.stderr new file mode 100644 index 000000000..f0acb388b --- /dev/null +++ b/tests/ui/parser/type-alias-where-fixable.stderr @@ -0,0 +1,42 @@ +warning: where clause not allowed here + --> $DIR/type-alias-where-fixable.rs:13:16 + | +LL | type Assoc where u32: Copy = (); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information + = note: `#[warn(deprecated_where_clause_location)]` on by default +help: move it to the end of the type declaration + | +LL - type Assoc where u32: Copy = (); +LL + type Assoc = () where u32: Copy; + | + +warning: where clause not allowed here + --> $DIR/type-alias-where-fixable.rs:16:17 + | +LL | type Assoc2 where u32: Copy = () where i32: Copy; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL - type Assoc2 where u32: Copy = () where i32: Copy; +LL + type Assoc2 = () where i32: Copy, u32: Copy; + | + +warning: where clause not allowed here + --> $DIR/type-alias-where-fixable.rs:24:17 + | +LL | type Assoc2 where u32: Copy, i32: Copy = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL - type Assoc2 where u32: Copy, i32: Copy = (); +LL + type Assoc2 = () where u32: Copy, i32: Copy; + | + +warning: 3 warnings emitted + diff --git a/tests/ui/parser/type-alias-where.rs b/tests/ui/parser/type-alias-where.rs new file mode 100644 index 000000000..62e301cb4 --- /dev/null +++ b/tests/ui/parser/type-alias-where.rs @@ -0,0 +1,11 @@ +// check-fail + +// Fine, but lints as unused +type Foo where u32: Copy = (); +// Not fine. +type Bar = () where u32: Copy; +//~^ ERROR where clauses are not allowed +type Baz = () where; +//~^ ERROR where clauses are not allowed + +fn main() {} diff --git a/tests/ui/parser/type-alias-where.stderr b/tests/ui/parser/type-alias-where.stderr new file mode 100644 index 000000000..fb8381792 --- /dev/null +++ b/tests/ui/parser/type-alias-where.stderr @@ -0,0 +1,18 @@ +error: where clauses are not allowed after the type for type aliases + --> $DIR/type-alias-where.rs:6:15 + | +LL | type Bar = () where u32: Copy; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #89122 for more information + +error: where clauses are not allowed after the type for type aliases + --> $DIR/type-alias-where.rs:8:15 + | +LL | type Baz = () where; + | ^^^^^ + | + = note: see issue #89122 for more information + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/type-parameters-in-field-exprs.rs b/tests/ui/parser/type-parameters-in-field-exprs.rs new file mode 100644 index 000000000..4cd77ebbd --- /dev/null +++ b/tests/ui/parser/type-parameters-in-field-exprs.rs @@ -0,0 +1,17 @@ +struct Foo { + x: isize, + y: isize, +} + +fn main() { + let f = Foo { + x: 1, + y: 2, + }; + f.x::; + //~^ ERROR field expressions cannot have generic arguments + f.x::<>; + //~^ ERROR field expressions cannot have generic arguments + f.x::(); + //~^ ERROR field expressions cannot have generic arguments +} diff --git a/tests/ui/parser/type-parameters-in-field-exprs.stderr b/tests/ui/parser/type-parameters-in-field-exprs.stderr new file mode 100644 index 000000000..ce7364d35 --- /dev/null +++ b/tests/ui/parser/type-parameters-in-field-exprs.stderr @@ -0,0 +1,20 @@ +error: field expressions cannot have generic arguments + --> $DIR/type-parameters-in-field-exprs.rs:11:10 + | +LL | f.x::; + | ^^^^^^^ + +error: field expressions cannot have generic arguments + --> $DIR/type-parameters-in-field-exprs.rs:13:10 + | +LL | f.x::<>; + | ^^ + +error: field expressions cannot have generic arguments + --> $DIR/type-parameters-in-field-exprs.rs:15:7 + | +LL | f.x::(); + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/unbalanced-doublequote.rs b/tests/ui/parser/unbalanced-doublequote.rs new file mode 100644 index 000000000..f21316205 --- /dev/null +++ b/tests/ui/parser/unbalanced-doublequote.rs @@ -0,0 +1,6 @@ +// error-pattern: unterminated double quote string + + +fn main() { + " +} diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr new file mode 100644 index 000000000..94b300a7b --- /dev/null +++ b/tests/ui/parser/unbalanced-doublequote.stderr @@ -0,0 +1,10 @@ +error[E0765]: unterminated double quote string + --> $DIR/unbalanced-doublequote.rs:5:5 + | +LL | / " +LL | | } + | |__^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0765`. diff --git a/tests/ui/parser/unclosed-braces.rs b/tests/ui/parser/unclosed-braces.rs new file mode 100644 index 000000000..ed94fff38 --- /dev/null +++ b/tests/ui/parser/unclosed-braces.rs @@ -0,0 +1,22 @@ +struct S { + x: [usize; 3], +} + +fn foo() { + { + { + println!("hi"); + } + } +} + +fn main() { +//~^ NOTE unclosed delimiter + { + { + //~^ NOTE this delimiter might not be properly closed... + foo(); + } + //~^ NOTE ...as it matches this but it has different indentation +} +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/unclosed-braces.stderr b/tests/ui/parser/unclosed-braces.stderr new file mode 100644 index 000000000..cbc5f8de4 --- /dev/null +++ b/tests/ui/parser/unclosed-braces.stderr @@ -0,0 +1,17 @@ +error: this file contains an unclosed delimiter + --> $DIR/unclosed-braces.rs:22:52 + | +LL | fn main() { + | - unclosed delimiter +... +LL | { + | - this delimiter might not be properly closed... +... +LL | } + | - ...as it matches this but it has different indentation +... +LL | + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.rs b/tests/ui/parser/unclosed-delimiter-in-dep.rs new file mode 100644 index 000000000..6db1b66e9 --- /dev/null +++ b/tests/ui/parser/unclosed-delimiter-in-dep.rs @@ -0,0 +1,6 @@ +mod unclosed_delim_mod; + +fn main() { + let _: usize = unclosed_delim_mod::new(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.stderr b/tests/ui/parser/unclosed-delimiter-in-dep.stderr new file mode 100644 index 000000000..1366ef1bb --- /dev/null +++ b/tests/ui/parser/unclosed-delimiter-in-dep.stderr @@ -0,0 +1,25 @@ +error: mismatched closing delimiter: `}` + --> $DIR/unclosed_delim_mod.rs:5:7 + | +LL | pub fn new() -> Result { + | - closing delimiter possibly meant for this +LL | Ok(Value { + | ^ unclosed delimiter +LL | } +LL | } + | ^ mismatched closing delimiter + +error[E0308]: mismatched types + --> $DIR/unclosed-delimiter-in-dep.rs:4:20 + | +LL | let _: usize = unclosed_delim_mod::new(); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found enum `Result` + | | + | expected due to this + | + = note: expected type `usize` + found enum `Result` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/unclosed_delim_mod.rs b/tests/ui/parser/unclosed_delim_mod.rs new file mode 100644 index 000000000..d977d2c03 --- /dev/null +++ b/tests/ui/parser/unclosed_delim_mod.rs @@ -0,0 +1,8 @@ +fn main() {} + +pub struct Value {} +pub fn new() -> Result { + Ok(Value { + } +} +//~^ ERROR mismatched closing delimiter diff --git a/tests/ui/parser/unclosed_delim_mod.stderr b/tests/ui/parser/unclosed_delim_mod.stderr new file mode 100644 index 000000000..a46d020b9 --- /dev/null +++ b/tests/ui/parser/unclosed_delim_mod.stderr @@ -0,0 +1,13 @@ +error: mismatched closing delimiter: `}` + --> $DIR/unclosed_delim_mod.rs:5:7 + | +LL | pub fn new() -> Result { + | - closing delimiter possibly meant for this +LL | Ok(Value { + | ^ unclosed delimiter +LL | } +LL | } + | ^ mismatched closing delimiter + +error: aborting due to previous error + diff --git a/tests/ui/parser/underscore-suffix-for-float.rs b/tests/ui/parser/underscore-suffix-for-float.rs new file mode 100644 index 000000000..c9b7eced0 --- /dev/null +++ b/tests/ui/parser/underscore-suffix-for-float.rs @@ -0,0 +1,4 @@ +fn main() { + let a = 42._; //~ ERROR expected identifier, found reserved identifier `_` + //~| ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/tests/ui/parser/underscore-suffix-for-float.stderr b/tests/ui/parser/underscore-suffix-for-float.stderr new file mode 100644 index 000000000..a5f3b6551 --- /dev/null +++ b/tests/ui/parser/underscore-suffix-for-float.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore-suffix-for-float.rs:2:16 + | +LL | let a = 42._; + | ^ expected identifier, found reserved identifier + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/underscore-suffix-for-float.rs:2:16 + | +LL | let a = 42._; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/parser/underscore-suffix-for-string.rs b/tests/ui/parser/underscore-suffix-for-string.rs new file mode 100644 index 000000000..bd260752e --- /dev/null +++ b/tests/ui/parser/underscore-suffix-for-string.rs @@ -0,0 +1,17 @@ +macro_rules! sink { + ($tt:tt) => {()} +} + +fn main() { + let _ = "Foo"_; + //~^ ERROR underscore literal suffix is not allowed + + // This is ok, because `__` is a valid identifier and the macro consumes it + // before proper parsing happens. + let _ = sink!("Foo"__); + + // This is not ok, even as an input to a macro, because the `_` suffix is + // never allowed. + sink!("Foo"_); + //~^ ERROR underscore literal suffix is not allowed +} diff --git a/tests/ui/parser/underscore-suffix-for-string.stderr b/tests/ui/parser/underscore-suffix-for-string.stderr new file mode 100644 index 000000000..2fe2c130e --- /dev/null +++ b/tests/ui/parser/underscore-suffix-for-string.stderr @@ -0,0 +1,14 @@ +error: underscore literal suffix is not allowed + --> $DIR/underscore-suffix-for-string.rs:6:18 + | +LL | let _ = "Foo"_; + | ^ + +error: underscore literal suffix is not allowed + --> $DIR/underscore-suffix-for-string.rs:15:16 + | +LL | sink!("Foo"_); + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/underscore_item_not_const.rs b/tests/ui/parser/underscore_item_not_const.rs new file mode 100644 index 000000000..c01ac4752 --- /dev/null +++ b/tests/ui/parser/underscore_item_not_const.rs @@ -0,0 +1,16 @@ +// Test that various non-const items do not syntactically permit `_` as a name. + +static _: () = (); //~ ERROR expected identifier, found reserved identifier `_` +struct _(); //~ ERROR expected identifier, found reserved identifier `_` +enum _ {} //~ ERROR expected identifier, found reserved identifier `_` +fn _() {} //~ ERROR expected identifier, found reserved identifier `_` +mod _ {} //~ ERROR expected identifier, found reserved identifier `_` +type _ = (); //~ ERROR expected identifier, found reserved identifier `_` +use _; //~ ERROR expected identifier, found reserved identifier `_` +use _ as g; //~ ERROR expected identifier, found reserved identifier `_` +trait _ {} //~ ERROR expected identifier, found reserved identifier `_` +trait _ = Copy; //~ ERROR expected identifier, found reserved identifier `_` +macro_rules! _ { () => {} } //~ ERROR expected identifier, found reserved identifier `_` +union _ { f: u8 } //~ ERROR expected one of `!` or `::`, found reserved identifier `_` + +fn main() {} diff --git a/tests/ui/parser/underscore_item_not_const.stderr b/tests/ui/parser/underscore_item_not_const.stderr new file mode 100644 index 000000000..0bc7642dd --- /dev/null +++ b/tests/ui/parser/underscore_item_not_const.stderr @@ -0,0 +1,74 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:3:8 + | +LL | static _: () = (); + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:4:8 + | +LL | struct _(); + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:5:6 + | +LL | enum _ {} + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:6:4 + | +LL | fn _() {} + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:7:5 + | +LL | mod _ {} + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:8:6 + | +LL | type _ = (); + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:9:5 + | +LL | use _; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:10:5 + | +LL | use _ as g; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:11:7 + | +LL | trait _ {} + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:12:7 + | +LL | trait _ = Copy; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:13:14 + | +LL | macro_rules! _ { () => {} } + | ^ expected identifier, found reserved identifier + +error: expected one of `!` or `::`, found reserved identifier `_` + --> $DIR/underscore_item_not_const.rs:14:7 + | +LL | union _ { f: u8 } + | ^ expected one of `!` or `::` + +error: aborting due to 12 previous errors + diff --git a/tests/ui/parser/unicode-character-literal.fixed b/tests/ui/parser/unicode-character-literal.fixed new file mode 100644 index 000000000..26ef5ffa1 --- /dev/null +++ b/tests/ui/parser/unicode-character-literal.fixed @@ -0,0 +1,21 @@ +// Regression test for #88684: Improve diagnostics for combining marks +// in character literals. + +// run-rustfix + +fn main() { + let _spade = "â™ ï¸"; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `â™ ` is followed by the combining mark `\u{fe0f}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _s = "ṩ̂̊"; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _a = 'Ã…'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `A` is followed by the combining mark `\u{30a}` + //~| HELP: consider using the normalized form `\u{c5}` of this character +} diff --git a/tests/ui/parser/unicode-character-literal.rs b/tests/ui/parser/unicode-character-literal.rs new file mode 100644 index 000000000..d331522c0 --- /dev/null +++ b/tests/ui/parser/unicode-character-literal.rs @@ -0,0 +1,21 @@ +// Regression test for #88684: Improve diagnostics for combining marks +// in character literals. + +// run-rustfix + +fn main() { + let _spade = 'â™ ï¸'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `â™ ` is followed by the combining mark `\u{fe0f}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _s = 'ṩ̂̊'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + //~| HELP: if you meant to write a `str` literal, use double quotes + + let _a = 'AÌŠ'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: this `A` is followed by the combining mark `\u{30a}` + //~| HELP: consider using the normalized form `\u{c5}` of this character +} diff --git a/tests/ui/parser/unicode-character-literal.stderr b/tests/ui/parser/unicode-character-literal.stderr new file mode 100644 index 000000000..5cd3bd0fe --- /dev/null +++ b/tests/ui/parser/unicode-character-literal.stderr @@ -0,0 +1,48 @@ +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:7:18 + | +LL | let _spade = 'â™ ï¸'; + | ^^^ + | +note: this `â™ ` is followed by the combining mark `\u{fe0f}` + --> $DIR/unicode-character-literal.rs:7:19 + | +LL | let _spade = 'â™ ï¸'; + | ^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _spade = "â™ ï¸"; + | ~~~ + +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:12:14 + | +LL | let _s = 'ṩ̂̊'; + | ^^^ + | +note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}` + --> $DIR/unicode-character-literal.rs:12:15 + | +LL | let _s = 'ṩ̂̊'; + | ^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _s = "ṩ̂̊"; + | ~~~ + +error: character literal may only contain one codepoint + --> $DIR/unicode-character-literal.rs:17:14 + | +LL | let _a = 'AÌŠ'; + | ^-^ + | | + | help: consider using the normalized form `\u{c5}` of this character: `Ã…` + | +note: this `A` is followed by the combining mark `\u{30a}` + --> $DIR/unicode-character-literal.rs:17:15 + | +LL | let _a = 'AÌŠ'; + | ^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/unicode-chars.rs b/tests/ui/parser/unicode-chars.rs new file mode 100644 index 000000000..cd25c7566 --- /dev/null +++ b/tests/ui/parser/unicode-chars.rs @@ -0,0 +1,12 @@ +fn main() { + let y = 0; + //~^ ERROR unknown start of token: \u{37e} + //~^^ HELP Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not +     let x = 0; + //~^ ERROR unknown start of token: \u{a0} + //~^^ NOTE character appears 3 more times + //~^^^ HELP Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not + let _ = 1 ⩵ 2; + //~^ ERROR unknown start of token + //~^^ HELP Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not +} diff --git a/tests/ui/parser/unicode-chars.stderr b/tests/ui/parser/unicode-chars.stderr new file mode 100644 index 000000000..086de5ec0 --- /dev/null +++ b/tests/ui/parser/unicode-chars.stderr @@ -0,0 +1,36 @@ +error: unknown start of token: \u{37e} + --> $DIR/unicode-chars.rs:2:14 + | +LL | let y = 0; + | ^ + | +help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not + | +LL | let y = 0; + | ~ + +error: unknown start of token: \u{a0} + --> $DIR/unicode-chars.rs:5:5 + | +LL |     let x = 0; + | ^^^^ + | + = note: character appears 3 more times +help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not + | +LL | let x = 0; + | ++++ + +error: unknown start of token: \u{2a75} + --> $DIR/unicode-chars.rs:9:15 + | +LL | let _ = 1 ⩵ 2; + | ^ + | +help: Unicode character '⩵' (Two Consecutive Equals Signs) looks like '==' (Double Equals Sign), but it is not + | +LL | let _ = 1 == 2; + | ~~ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/unicode-control-codepoints.rs b/tests/ui/parser/unicode-control-codepoints.rs new file mode 100644 index 000000000..df099bb62 --- /dev/null +++ b/tests/ui/parser/unicode-control-codepoints.rs @@ -0,0 +1,39 @@ +fn main() { + // if access_level != "us‫e‪r" { // Check if admin + //~^ ERROR unicode codepoint changing visible direction of text present in comment + println!("us\u{202B}e\u{202A}r"); + println!("{:?}", r#"us\u{202B}e\u{202A}r"#); + println!("{:?}", b"us\u{202B}e\u{202A}r"); + //~^ ERROR unicode escape in byte string + //~| ERROR unicode escape in byte string + println!("{:?}", br##"us\u{202B}e\u{202A}r"##); + + println!("{:?}", "/*‮ } â¦if isAdmin⩠⦠begin admins only "); + //~^ ERROR unicode codepoint changing visible direction of text present in literal + + println!("{:?}", r##"/*‮ } â¦if isAdmin⩠⦠begin admins only "##); + //~^ ERROR unicode codepoint changing visible direction of text present in literal + println!("{:?}", b"/*‮ } â¦if isAdmin⩠⦠begin admins only "); + //~^ ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + //~| ERROR non-ASCII character in byte string literal + println!("{:?}", br##"/*‮ } â¦if isAdmin⩠⦠begin admins only "##); + //~^ ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + //~| ERROR non-ASCII character in raw byte string literal + println!("{:?}", '‮'); + //~^ ERROR unicode codepoint changing visible direction of text present in literal +} + +//"/*‮ } â¦if isAdmin⩠⦠begin admins only */" +//~^ ERROR unicode codepoint changing visible direction of text present in comment + +/** '‮'); */fn foo() {} +//~^ ERROR unicode codepoint changing visible direction of text present in doc comment + +/** + * + * '‮'); */fn bar() {} +//~^^^ ERROR unicode codepoint changing visible direction of text present in doc comment diff --git a/tests/ui/parser/unicode-control-codepoints.stderr b/tests/ui/parser/unicode-control-codepoints.stderr new file mode 100644 index 000000000..fc071a941 --- /dev/null +++ b/tests/ui/parser/unicode-control-codepoints.stderr @@ -0,0 +1,192 @@ +error: unicode escape in byte string + --> $DIR/unicode-control-codepoints.rs:6:26 + | +LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: unicode escape in byte string + --> $DIR/unicode-control-codepoints.rs:6:35 + | +LL | println!("{:?}", b"us\u{202B}e\u{202A}r"); + | ^^^^^^^^ unicode escape in byte string + | + = help: unicode escape sequences cannot be used as a byte or in a byte string + +error: non-ASCII character in byte string literal + --> $DIR/unicode-control-codepoints.rs:16:26 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ must be ASCII but is '\u{202e}' + | +help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes + | +LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in byte string literal + --> $DIR/unicode-control-codepoints.rs:16:30 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ must be ASCII but is '\u{2066}' + | +help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes + | +LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in byte string literal + --> $DIR/unicode-control-codepoints.rs:16:41 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ must be ASCII but is '\u{2069}' + | +help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes + | +LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in byte string literal + --> $DIR/unicode-control-codepoints.rs:16:43 + | +LL | println!("{:?}", b"/* } if isAdmin begin admins only "); + | ^ must be ASCII but is '\u{2066}' + | +help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes + | +LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only "); + | ~~~~~~~~~~~~ + +error: non-ASCII character in raw byte string literal + --> $DIR/unicode-control-codepoints.rs:21:29 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{202e}' + +error: non-ASCII character in raw byte string literal + --> $DIR/unicode-control-codepoints.rs:21:33 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{2066}' + +error: non-ASCII character in raw byte string literal + --> $DIR/unicode-control-codepoints.rs:21:44 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{2069}' + +error: non-ASCII character in raw byte string literal + --> $DIR/unicode-control-codepoints.rs:21:46 + | +LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##); + | ^ must be ASCII but is '\u{2066}' + +error: unicode codepoint changing visible direction of text present in comment + --> $DIR/unicode-control-codepoints.rs:2:5 + | +LL | // if access_level != "user" { // Check if admin + | ^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ + | | || + | | |'\u{202a}' + | | '\u{202b}' + | this comment contains invisible unicode text flow control codepoints + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = note: `#[deny(text_direction_codepoint_in_comment)]` on by default + = help: if their presence wasn't intentional, you can remove them + +error: unicode codepoint changing visible direction of text present in comment + --> $DIR/unicode-control-codepoints.rs:30:1 + | +LL | //"/* } if isAdmin begin admins only */" + | ^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ + | | | | || + | | | | |'\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' + | | '\u{202e}' + | this comment contains invisible unicode text flow control codepoints + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them + +error: unicode codepoint changing visible direction of text present in literal + --> $DIR/unicode-control-codepoints.rs:11:22 + | +LL | println!("{:?}", "/* } if isAdmin begin admins only "); + | ^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^ + | | | | || + | | | | |'\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' + | | '\u{202e}' + | this literal contains invisible unicode text flow control codepoints + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = note: `#[deny(text_direction_codepoint_in_literal)]` on by default + = help: if their presence wasn't intentional, you can remove them +help: if you want to keep them but make them visible in your source code, you can escape them + | +LL | println!("{:?}", "/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only "); + | ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ + +error: unicode codepoint changing visible direction of text present in literal + --> $DIR/unicode-control-codepoints.rs:14:22 + | +LL | println!("{:?}", r##"/* } if isAdmin begin admins only "##); + | ^^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^ + | | | | || + | | | | |'\u{2066}' + | | | | '\u{2069}' + | | | '\u{2066}' + | | '\u{202e}' + | this literal contains invisible unicode text flow control codepoints + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them +help: if you want to keep them but make them visible in your source code, you can escape them + | +LL | println!("{:?}", r##"/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only "##); + | ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ + +error: unicode codepoint changing visible direction of text present in literal + --> $DIR/unicode-control-codepoints.rs:26:22 + | +LL | println!("{:?}", ''); + | ^- + | || + | |'\u{202e}' + | this literal contains an invisible unicode text flow control codepoint + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = help: if their presence wasn't intentional, you can remove them +help: if you want to keep them but make them visible in your source code, you can escape them + | +LL | println!("{:?}", '\u{202e}'); + | ~~~~~~~~ + +error: unicode codepoint changing visible direction of text present in doc comment + --> $DIR/unicode-control-codepoints.rs:33:1 + | +LL | /** ''); */fn foo() {} + | ^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = note: if their presence wasn't intentional, you can remove them + = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}' + +error: unicode codepoint changing visible direction of text present in doc comment + --> $DIR/unicode-control-codepoints.rs:36:1 + | +LL | / /** +LL | | * +LL | | * ''); */fn bar() {} + | |___________^ this doc comment contains an invisible unicode text flow control codepoint + | + = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen + = note: if their presence wasn't intentional, you can remove them + = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}' + +error: aborting due to 17 previous errors + diff --git a/tests/ui/parser/unicode-quote-chars.rs b/tests/ui/parser/unicode-quote-chars.rs new file mode 100644 index 000000000..868d2b227 --- /dev/null +++ b/tests/ui/parser/unicode-quote-chars.rs @@ -0,0 +1,8 @@ +fn main() { + println!(“hello worldâ€); + //~^ ERROR unknown start of token: \u{201c} + //~^^ HELP Unicode characters '“' (Left Double Quotation Mark) and 'â€' (Right Double Quotation Mark) look like '"' (Quotation Mark), but are not + //~^^^ ERROR unknown start of token: \u{201d} + //~^^^^ HELP Unicode character 'â€' (Right Double Quotation Mark) looks like '"' (Quotation Mark), but it is not + //~^^^^^ ERROR expected `,`, found `world` +} diff --git a/tests/ui/parser/unicode-quote-chars.stderr b/tests/ui/parser/unicode-quote-chars.stderr new file mode 100644 index 000000000..092abeb53 --- /dev/null +++ b/tests/ui/parser/unicode-quote-chars.stderr @@ -0,0 +1,30 @@ +error: unknown start of token: \u{201c} + --> $DIR/unicode-quote-chars.rs:2:14 + | +LL | println!(“hello worldâ€); + | ^ + | +help: Unicode characters '“' (Left Double Quotation Mark) and 'â€' (Right Double Quotation Mark) look like '"' (Quotation Mark), but are not + | +LL | println!("hello world"); + | ~~~~~~~~~~~~~ + +error: unknown start of token: \u{201d} + --> $DIR/unicode-quote-chars.rs:2:26 + | +LL | println!(“hello worldâ€); + | ^ + | +help: Unicode character 'â€' (Right Double Quotation Mark) looks like '"' (Quotation Mark), but it is not + | +LL | println!(“hello world"); + | ~ + +error: expected `,`, found `world` + --> $DIR/unicode-quote-chars.rs:2:21 + | +LL | println!(“hello worldâ€); + | ^^^^^ expected `,` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/unmatched-delimiter-at-end-of-file.rs b/tests/ui/parser/unmatched-delimiter-at-end-of-file.rs new file mode 100644 index 000000000..f56013266 --- /dev/null +++ b/tests/ui/parser/unmatched-delimiter-at-end-of-file.rs @@ -0,0 +1,11 @@ +struct S { + x: usize, + y: usize, +} + +fn main() { + S { x: 4, + y: 5 }; +} + +fn foo() { //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr new file mode 100644 index 000000000..430a13e6e --- /dev/null +++ b/tests/ui/parser/unmatched-delimiter-at-end-of-file.stderr @@ -0,0 +1,8 @@ +error: this file contains an unclosed delimiter + --> $DIR/unmatched-delimiter-at-end-of-file.rs:11:63 + | +LL | fn foo() { + | - unclosed delimiter ^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/unmatched-langle-1.rs b/tests/ui/parser/unmatched-langle-1.rs new file mode 100644 index 000000000..fdf2ae398 --- /dev/null +++ b/tests/ui/parser/unmatched-langle-1.rs @@ -0,0 +1,9 @@ +// Check that a suggestion is issued if there are too many `<`s in a +// generic argument list, and that the parser recovers properly. + +fn main() { + foo::<<<>(); + //~^ ERROR: unmatched angle brackets + //~| ERROR: cannot find function `foo` in this scope [E0425] + //~| ERROR: cannot find type `Ty` in this scope [E0412] +} diff --git a/tests/ui/parser/unmatched-langle-1.stderr b/tests/ui/parser/unmatched-langle-1.stderr new file mode 100644 index 000000000..cdf74bded --- /dev/null +++ b/tests/ui/parser/unmatched-langle-1.stderr @@ -0,0 +1,22 @@ +error: unmatched angle brackets + --> $DIR/unmatched-langle-1.rs:5:10 + | +LL | foo::<<<>(); + | ^^^ help: remove extra angle brackets + +error[E0412]: cannot find type `Ty` in this scope + --> $DIR/unmatched-langle-1.rs:5:14 + | +LL | foo::<<<>(); + | ^^ not found in this scope + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/unmatched-langle-1.rs:5:5 + | +LL | foo::<<<>(); + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/unmatched-langle-2.rs b/tests/ui/parser/unmatched-langle-2.rs new file mode 100644 index 000000000..8de0d7d89 --- /dev/null +++ b/tests/ui/parser/unmatched-langle-2.rs @@ -0,0 +1,15 @@ +// When there are too many opening `<`s, the compiler would previously +// suggest nonsense if the `<`s were interspersed with other tokens: +// +// error: unmatched angle brackets +// --> unmatched-langle.rs:2:10 +// | +// 2 | foo::(); +// | ^^^ help: remove extra angle brackets +// +// This test makes sure that this is no longer happening. + +fn main() { + foo::(); + //~^ ERROR: expected `::`, found `(` +} diff --git a/tests/ui/parser/unmatched-langle-2.stderr b/tests/ui/parser/unmatched-langle-2.stderr new file mode 100644 index 000000000..773bb33d8 --- /dev/null +++ b/tests/ui/parser/unmatched-langle-2.stderr @@ -0,0 +1,8 @@ +error: expected `::`, found `(` + --> $DIR/unmatched-langle-2.rs:13:20 + | +LL | foo::(); + | ^ expected `::` + +error: aborting due to previous error + diff --git a/tests/ui/parser/unnecessary-let.rs b/tests/ui/parser/unnecessary-let.rs new file mode 100644 index 000000000..627910962 --- /dev/null +++ b/tests/ui/parser/unnecessary-let.rs @@ -0,0 +1,11 @@ +fn main() { + for let x of [1, 2, 3] {} + //~^ ERROR expected pattern, found `let` + //~| ERROR missing `in` in `for` loop + + match 1 { + let 1 => {} + //~^ ERROR expected pattern, found `let` + _ => {} + } +} diff --git a/tests/ui/parser/unnecessary-let.stderr b/tests/ui/parser/unnecessary-let.stderr new file mode 100644 index 000000000..952119cae --- /dev/null +++ b/tests/ui/parser/unnecessary-let.stderr @@ -0,0 +1,20 @@ +error: expected pattern, found `let` + --> $DIR/unnecessary-let.rs:2:9 + | +LL | for let x of [1, 2, 3] {} + | ^^^ help: remove the unnecessary `let` keyword + +error: missing `in` in `for` loop + --> $DIR/unnecessary-let.rs:2:15 + | +LL | for let x of [1, 2, 3] {} + | ^^ help: try using `in` here instead + +error: expected pattern, found `let` + --> $DIR/unnecessary-let.rs:7:9 + | +LL | let 1 => {} + | ^^^ help: remove the unnecessary `let` keyword + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs new file mode 100644 index 000000000..77856fb67 --- /dev/null +++ b/tests/ui/parser/unsafe-foreign-mod-2.rs @@ -0,0 +1,8 @@ +extern "C" unsafe { + //~^ ERROR expected `{`, found keyword `unsafe` + //~| ERROR extern block cannot be declared unsafe + unsafe fn foo(); + //~^ ERROR functions in `extern` blocks cannot have qualifiers +} + +fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr new file mode 100644 index 000000000..7cc2de141 --- /dev/null +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -0,0 +1,28 @@ +error: expected `{`, found keyword `unsafe` + --> $DIR/unsafe-foreign-mod-2.rs:1:12 + | +LL | extern "C" unsafe { + | ^^^^^^ expected `{` + +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod-2.rs:1:12 + | +LL | extern "C" unsafe { + | ^^^^^^ + +error: functions in `extern` blocks cannot have qualifiers + --> $DIR/unsafe-foreign-mod-2.rs:4:15 + | +LL | extern "C" unsafe { + | ----------------- in this `extern` block +... +LL | unsafe fn foo(); + | ^^^ + | +help: remove the qualifiers + | +LL | fn foo(); + | ~~ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs new file mode 100644 index 000000000..eab134a4a --- /dev/null +++ b/tests/ui/parser/unsafe-foreign-mod.rs @@ -0,0 +1,5 @@ +unsafe extern "C" { + //~^ ERROR extern block cannot be declared unsafe +} + +fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr new file mode 100644 index 000000000..4acf72c5d --- /dev/null +++ b/tests/ui/parser/unsafe-foreign-mod.stderr @@ -0,0 +1,8 @@ +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod.rs:1:1 + | +LL | unsafe extern "C" { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/parser/unsafe-mod.rs b/tests/ui/parser/unsafe-mod.rs new file mode 100644 index 000000000..7916d878e --- /dev/null +++ b/tests/ui/parser/unsafe-mod.rs @@ -0,0 +1,9 @@ +unsafe mod m { + //~^ ERROR module cannot be declared unsafe +} + +unsafe mod n; +//~^ ERROR module cannot be declared unsafe +//~^^ ERROR file not found for module `n` + +fn main() {} diff --git a/tests/ui/parser/unsafe-mod.stderr b/tests/ui/parser/unsafe-mod.stderr new file mode 100644 index 000000000..dac6e7a35 --- /dev/null +++ b/tests/ui/parser/unsafe-mod.stderr @@ -0,0 +1,23 @@ +error[E0583]: file not found for module `n` + --> $DIR/unsafe-mod.rs:5:1 + | +LL | unsafe mod n; + | ^^^^^^^^^^^^^ + | + = help: to create the module `n`, create file "$DIR/n.rs" or "$DIR/n/mod.rs" + +error: module cannot be declared unsafe + --> $DIR/unsafe-mod.rs:1:1 + | +LL | unsafe mod m { + | ^^^^^^ + +error: module cannot be declared unsafe + --> $DIR/unsafe-mod.rs:5:1 + | +LL | unsafe mod n; + | ^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0583`. diff --git a/tests/ui/parser/unsized.rs b/tests/ui/parser/unsized.rs new file mode 100644 index 000000000..e7fd7a196 --- /dev/null +++ b/tests/ui/parser/unsized.rs @@ -0,0 +1,7 @@ +// Test syntax checks for `type` keyword. + +struct S1 for type; +//~^ ERROR expected `where`, `{`, `(`, or `;` after struct name, found keyword `for` + +pub fn main() { +} diff --git a/tests/ui/parser/unsized.stderr b/tests/ui/parser/unsized.stderr new file mode 100644 index 000000000..3d4ed526b --- /dev/null +++ b/tests/ui/parser/unsized.stderr @@ -0,0 +1,8 @@ +error: expected `where`, `{`, `(`, or `;` after struct name, found keyword `for` + --> $DIR/unsized.rs:3:11 + | +LL | struct S1 for type; + | ^^^ expected `where`, `{`, `(`, or `;` after struct name + +error: aborting due to previous error + diff --git a/tests/ui/parser/unsized2.rs b/tests/ui/parser/unsized2.rs new file mode 100644 index 000000000..21370b329 --- /dev/null +++ b/tests/ui/parser/unsized2.rs @@ -0,0 +1,7 @@ +// Test syntax checks for `type` keyword. + +fn f() {} + +pub fn main() { + f(); //~ ERROR expected expression, found keyword `type` +} diff --git a/tests/ui/parser/unsized2.stderr b/tests/ui/parser/unsized2.stderr new file mode 100644 index 000000000..17e39b292 --- /dev/null +++ b/tests/ui/parser/unsized2.stderr @@ -0,0 +1,8 @@ +error: expected expression, found keyword `type` + --> $DIR/unsized2.rs:6:7 + | +LL | f(); + | ^^^^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/parser/use-as-where-use-ends-with-mod-sep.rs b/tests/ui/parser/use-as-where-use-ends-with-mod-sep.rs new file mode 100644 index 000000000..b4bb48418 --- /dev/null +++ b/tests/ui/parser/use-as-where-use-ends-with-mod-sep.rs @@ -0,0 +1,2 @@ +use std::any:: as foo; //~ ERROR expected identifier, found keyword `as` +//~^ ERROR: expected one of `::`, `;`, or `as`, found `foo` diff --git a/tests/ui/parser/use-as-where-use-ends-with-mod-sep.stderr b/tests/ui/parser/use-as-where-use-ends-with-mod-sep.stderr new file mode 100644 index 000000000..192ab5eb7 --- /dev/null +++ b/tests/ui/parser/use-as-where-use-ends-with-mod-sep.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `as` + --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:16 + | +LL | use std::any:: as foo; + | ^^ expected identifier, found keyword + +error: expected one of `::`, `;`, or `as`, found `foo` + --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:19 + | +LL | use std::any:: as foo; + | ^^^ expected one of `::`, `;`, or `as` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/use-colon-as-mod-sep.rs b/tests/ui/parser/use-colon-as-mod-sep.rs new file mode 100644 index 000000000..e1e8756b0 --- /dev/null +++ b/tests/ui/parser/use-colon-as-mod-sep.rs @@ -0,0 +1,11 @@ +// Recover from using a colon as a path separator. + +use std::process:Command; +//~^ ERROR expected `::`, found `:` +use std:fs::File; +//~^ ERROR expected `::`, found `:` +use std:collections:HashMap; +//~^ ERROR expected `::`, found `:` +//~| ERROR expected `::`, found `:` + +fn main() { } diff --git a/tests/ui/parser/use-colon-as-mod-sep.stderr b/tests/ui/parser/use-colon-as-mod-sep.stderr new file mode 100644 index 000000000..e825dfed1 --- /dev/null +++ b/tests/ui/parser/use-colon-as-mod-sep.stderr @@ -0,0 +1,28 @@ +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:3:17 + | +LL | use std::process:Command; + | ^ help: use double colon + | + = note: import paths are delimited using `::` + +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:5:8 + | +LL | use std:fs::File; + | ^ help: use double colon + +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:7:8 + | +LL | use std:collections:HashMap; + | ^ help: use double colon + +error: expected `::`, found `:` + --> $DIR/use-colon-as-mod-sep.rs:7:20 + | +LL | use std:collections:HashMap; + | ^ help: use double colon + +error: aborting due to 4 previous errors + diff --git a/tests/ui/parser/use-ends-with-mod-sep.rs b/tests/ui/parser/use-ends-with-mod-sep.rs new file mode 100644 index 000000000..ad8da4d18 --- /dev/null +++ b/tests/ui/parser/use-ends-with-mod-sep.rs @@ -0,0 +1 @@ +use std::any::; //~ ERROR expected identifier, found `;` diff --git a/tests/ui/parser/use-ends-with-mod-sep.stderr b/tests/ui/parser/use-ends-with-mod-sep.stderr new file mode 100644 index 000000000..bd0d881a0 --- /dev/null +++ b/tests/ui/parser/use-ends-with-mod-sep.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `;` + --> $DIR/use-ends-with-mod-sep.rs:1:15 + | +LL | use std::any::; + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs new file mode 100644 index 000000000..41742f37f --- /dev/null +++ b/tests/ui/parser/use-unclosed-brace.rs @@ -0,0 +1,12 @@ +// error-pattern: expected one of `,`, `::`, `as`, or `}`, found `;` +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected item, found `}` +use foo::{bar, baz; + +use std::fmt::Display; + +mod bar { } + +mod baz { } + +fn main() {} diff --git a/tests/ui/parser/use-unclosed-brace.stderr b/tests/ui/parser/use-unclosed-brace.stderr new file mode 100644 index 000000000..438fe9c47 --- /dev/null +++ b/tests/ui/parser/use-unclosed-brace.stderr @@ -0,0 +1,27 @@ +error: this file contains an unclosed delimiter + --> $DIR/use-unclosed-brace.rs:12:14 + | +LL | use foo::{bar, baz; + | - unclosed delimiter +... +LL | fn main() {} + | ^ + +error: expected one of `,`, `::`, `as`, or `}`, found `;` + --> $DIR/use-unclosed-brace.rs:4:10 + | +LL | use foo::{bar, baz; + | ^ ^ + | | | + | | expected one of `,`, `::`, `as`, or `}` + | | help: `}` may belong here + | unclosed delimiter + +error: expected item, found `}` + --> $DIR/use-unclosed-brace.rs:12:14 + | +LL | fn main() {} + | ^ expected item + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/utf16-be-without-bom.rs b/tests/ui/parser/utf16-be-without-bom.rs new file mode 100644 index 000000000..22aa19717 Binary files /dev/null and b/tests/ui/parser/utf16-be-without-bom.rs differ diff --git a/tests/ui/parser/utf16-be-without-bom.stderr b/tests/ui/parser/utf16-be-without-bom.stderr new file mode 100644 index 000000000..768d2c531 Binary files /dev/null and b/tests/ui/parser/utf16-be-without-bom.stderr differ diff --git a/tests/ui/parser/utf16-le-without-bom.rs b/tests/ui/parser/utf16-le-without-bom.rs new file mode 100644 index 000000000..3c1049929 Binary files /dev/null and b/tests/ui/parser/utf16-le-without-bom.rs differ diff --git a/tests/ui/parser/utf16-le-without-bom.stderr b/tests/ui/parser/utf16-le-without-bom.stderr new file mode 100644 index 000000000..4f4b91e39 Binary files /dev/null and b/tests/ui/parser/utf16-le-without-bom.stderr differ diff --git a/tests/ui/parser/utf8_idents-rpass.rs b/tests/ui/parser/utf8_idents-rpass.rs new file mode 100644 index 000000000..206744a58 --- /dev/null +++ b/tests/ui/parser/utf8_idents-rpass.rs @@ -0,0 +1,39 @@ +// run-pass +// +#![allow(non_snake_case)] + +pub fn main() { + let ε = 0.00001f64; + let Π = 3.14f64; + let लंच = Π * Π + 1.54; + assert!(((लंच - 1.54) - (Π * Π)).abs() < ε); + assert_eq!(სáƒáƒ­áƒ›áƒ”ლáƒáƒ“_გემრიელი_სáƒáƒ“ილი(), 0); +} + +fn სáƒáƒ­áƒ›áƒ”ლáƒáƒ“_გემრიელი_სáƒáƒ“ილი() -> isize { + + // Lunch in several languages. + + let ランム= 10; + let åˆé¤ = 10; + + let ×רוחת_צהריי = 10; + let غداء = 10_usize; + let Õ¬Õ¡Õ¶Õ¹ = 10; + let обед = 10; + let абед = 10; + let μεσημεÏιανό = 10; + let hádegismatur = 10; + let ручек = 10; + + let ăn_trÆ°a = 10; + let อาหารà¸à¸¥à¸²à¸‡à¸§à¸±à¸™ = 10; + + // Lunchy arithmetic, mm. + + assert_eq!(hádegismatur * ручек * обед, 1000); + assert_eq!(10, ×רוחת_צהריי); + assert_eq!(ランム+ åˆé¤ + μεσημεÏιανό, 30); + assert_eq!(ăn_trÆ°a + อาหารà¸à¸¥à¸²à¸‡à¸§à¸±à¸™, 20); + return (абед + Õ¬Õ¡Õ¶Õ¹) >> غداء; +} diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs new file mode 100644 index 000000000..9eeee195e --- /dev/null +++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs @@ -0,0 +1,9 @@ +fn f1<'a>(x: u8, y: &'a ...) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn f2<'a>(x: u8, y: Vec<&'a ...>) {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr new file mode 100644 index 000000000..8b9d676a4 --- /dev/null +++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr @@ -0,0 +1,24 @@ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:1:25 + | +LL | fn f1<'a>(x: u8, y: &'a ...) {} + | ^^^ + +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:4:29 + | +LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0743. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs new file mode 100644 index 000000000..0b61e267d --- /dev/null +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -0,0 +1,77 @@ +#![feature(c_variadic)] +#![allow(anonymous_parameters)] + +fn main() {} + +fn f1_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + +fn f1_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f2_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + +extern "C" fn f2_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f2_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern "C" fn f3_1(x: isize, ...) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + +extern "C" fn f3_2(...) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR C-variadic function must be declared with at least one named argument + +extern "C" fn f3_3(..., x: isize) {} +//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR `...` must be the last argument of a C-variadic function + +extern "C" { + fn e_f1(...); + //~^ ERROR C-variadic function must be declared with at least one named argument + fn e_f2(..., x: isize); +//~^ ERROR `...` must be the last argument of a C-variadic function +} + +struct X; + +impl X { + fn i_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + fn i_f2(...) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn i_f3(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn i_f4(..., x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function +} + +trait T { + fn t_f1(x: isize, ...) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + fn t_f2(x: isize, ...); + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + fn t_f3(...) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f4(...); + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR C-variadic function must be declared with at least one named argument + fn t_f5(..., x: isize) {} + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function + fn t_f6(..., x: isize); + //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic + //~| ERROR `...` must be the last argument of a C-variadic function +} diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr new file mode 100644 index 000000000..f1cbbb279 --- /dev/null +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -0,0 +1,206 @@ +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 + | +LL | fn f1_1(x: isize, ...) {} + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 + | +LL | fn f1_2(...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 + | +LL | fn f1_2(...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:13:30 + | +LL | extern "C" fn f2_1(x: isize, ...) {} + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:16:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:16:20 + | +LL | extern "C" fn f2_2(...) {} + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:20:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:20:20 + | +LL | extern "C" fn f2_3(..., x: isize) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:24:30 + | +LL | extern "C" fn f3_1(x: isize, ...) {} + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20 + | +LL | extern "C" fn f3_2(...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:27:20 + | +LL | extern "C" fn f3_2(...) {} + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:31:20 + | +LL | extern "C" fn f3_3(..., x: isize) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:31:20 + | +LL | extern "C" fn f3_3(..., x: isize) {} + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:36:13 + | +LL | fn e_f1(...); + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:38:13 + | +LL | fn e_f2(..., x: isize); + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:45:23 + | +LL | fn i_f1(x: isize, ...) {} + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13 + | +LL | fn i_f2(...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:47:13 + | +LL | fn i_f2(...) {} + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:28 + | +LL | fn i_f3(..., x: isize, ...) {} + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:54:13 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:54:13 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:54:28 + | +LL | fn i_f4(..., x: isize, ...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:23 + | +LL | fn t_f1(x: isize, ...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:63:23 + | +LL | fn t_f2(x: isize, ...); + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + | +LL | fn t_f3(...) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + | +LL | fn t_f3(...) {} + | ^^^ + +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13 + | +LL | fn t_f4(...); + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:68:13 + | +LL | fn t_f4(...); + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:71:13 + | +LL | fn t_f5(..., x: isize) {} + | ^^^ + +error: `...` must be the last argument of a C-variadic function + --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13 + | +LL | fn t_f6(..., x: isize); + | ^^^ + +error: only foreign or `unsafe extern "C"` functions may be C-variadic + --> $DIR/variadic-ffi-semantic-restrictions.rs:74:13 + | +LL | fn t_f6(..., x: isize); + | ^^^ + +error: aborting due to 34 previous errors + diff --git a/tests/ui/parser/variadic-ffi-syntactic-pass.rs b/tests/ui/parser/variadic-ffi-syntactic-pass.rs new file mode 100644 index 000000000..3875d6af1 --- /dev/null +++ b/tests/ui/parser/variadic-ffi-syntactic-pass.rs @@ -0,0 +1,53 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn f1_1(x: isize, ...) {} + +#[cfg(FALSE)] +fn f1_2(...) {} + +#[cfg(FALSE)] +extern "C" fn f2_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern "C" fn f2_2(...) {} + +#[cfg(FALSE)] +extern "C" fn f2_3(..., x: isize) {} + +#[cfg(FALSE)] +extern fn f3_1(x: isize, ...) {} + +#[cfg(FALSE)] +extern fn f3_2(...) {} + +#[cfg(FALSE)] +extern fn f3_3(..., x: isize) {} + +#[cfg(FALSE)] +extern { + fn e_f1(...); + fn e_f2(..., x: isize); +} + +struct X; + +#[cfg(FALSE)] +impl X { + fn i_f1(x: isize, ...) {} + fn i_f2(...) {} + fn i_f3(..., x: isize, ...) {} + fn i_f4(..., x: isize, ...) {} +} + +#[cfg(FALSE)] +trait T { + fn t_f1(x: isize, ...) {} + fn t_f2(x: isize, ...); + fn t_f3(...) {} + fn t_f4(...); + fn t_f5(..., x: isize) {} + fn t_f6(..., x: isize); +} diff --git a/tests/ui/parser/virtual-structs.rs b/tests/ui/parser/virtual-structs.rs new file mode 100644 index 000000000..ce57a3454 --- /dev/null +++ b/tests/ui/parser/virtual-structs.rs @@ -0,0 +1,10 @@ +// Test diagnostics for the removed struct inheritance feature. + +virtual struct SuperStruct { +//~^ ERROR expected item, found reserved keyword `virtual` + f1: isize, +} + +struct Struct : SuperStruct; + +pub fn main() {} diff --git a/tests/ui/parser/virtual-structs.stderr b/tests/ui/parser/virtual-structs.stderr new file mode 100644 index 000000000..a5211d83f --- /dev/null +++ b/tests/ui/parser/virtual-structs.stderr @@ -0,0 +1,8 @@ +error: expected item, found reserved keyword `virtual` + --> $DIR/virtual-structs.rs:3:1 + | +LL | virtual struct SuperStruct { + | ^^^^^^^ expected item + +error: aborting due to previous error + diff --git a/tests/ui/parser/where-clauses-no-bounds-or-predicates.rs b/tests/ui/parser/where-clauses-no-bounds-or-predicates.rs new file mode 100644 index 000000000..e80db5372 --- /dev/null +++ b/tests/ui/parser/where-clauses-no-bounds-or-predicates.rs @@ -0,0 +1,15 @@ +// Empty predicate list is OK +fn equal1(_: &T, _: &T) -> bool where { + true +} + +// Empty bound list is OK +fn equal2(_: &T, _: &T) -> bool where T: { + true +} + +fn foo<'a>() where 'a {} +//~^ ERROR expected `:`, found `{` + +fn main() { +} diff --git a/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr b/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr new file mode 100644 index 000000000..b80b0a409 --- /dev/null +++ b/tests/ui/parser/where-clauses-no-bounds-or-predicates.stderr @@ -0,0 +1,8 @@ +error: expected `:`, found `{` + --> $DIR/where-clauses-no-bounds-or-predicates.rs:11:23 + | +LL | fn foo<'a>() where 'a {} + | ^ expected `:` + +error: aborting due to previous error + diff --git a/tests/ui/parser/where_with_bound.rs b/tests/ui/parser/where_with_bound.rs new file mode 100644 index 000000000..3ca45f188 --- /dev/null +++ b/tests/ui/parser/where_with_bound.rs @@ -0,0 +1,5 @@ +fn foo() where ::Item: ToString, T: Iterator { } +//~^ ERROR generic parameters on `where` clauses are reserved for future use +//~| ERROR cannot find type `Item` in the crate root + +fn main() {} diff --git a/tests/ui/parser/where_with_bound.stderr b/tests/ui/parser/where_with_bound.stderr new file mode 100644 index 000000000..ff98b3f5f --- /dev/null +++ b/tests/ui/parser/where_with_bound.stderr @@ -0,0 +1,15 @@ +error: generic parameters on `where` clauses are reserved for future use + --> $DIR/where_with_bound.rs:1:19 + | +LL | fn foo() where ::Item: ToString, T: Iterator { } + | ^^^ currently unsupported + +error[E0412]: cannot find type `Item` in the crate root + --> $DIR/where_with_bound.rs:1:24 + | +LL | fn foo() where ::Item: ToString, T: Iterator { } + | ^^^^ not found in the crate root + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/parser/while-if-let-without-body.rs b/tests/ui/parser/while-if-let-without-body.rs new file mode 100644 index 000000000..063c0145c --- /dev/null +++ b/tests/ui/parser/while-if-let-without-body.rs @@ -0,0 +1,13 @@ +fn main() { + let container = vec![Some(1), Some(2), None]; + + let mut i = 0; + while if let Some(thing) = container.get(i) { + //~^ NOTE while parsing the body of this `while` expression + //~| NOTE this `while` condition successfully parsed + println!("{:?}", thing); + i += 1; + } +} +//~^ ERROR expected `{`, found `}` +//~| NOTE expected `{` diff --git a/tests/ui/parser/while-if-let-without-body.stderr b/tests/ui/parser/while-if-let-without-body.stderr new file mode 100644 index 000000000..2dac45c11 --- /dev/null +++ b/tests/ui/parser/while-if-let-without-body.stderr @@ -0,0 +1,18 @@ +error: expected `{`, found `}` + --> $DIR/while-if-let-without-body.rs:11:1 + | +LL | while if let Some(thing) = container.get(i) { + | _____-----_- + | | | + | | while parsing the body of this `while` expression +LL | | +LL | | +LL | | println!("{:?}", thing); +LL | | i += 1; +LL | | } + | |_____- this `while` condition successfully parsed +LL | } + | ^ expected `{` + +error: aborting due to previous error + diff --git a/tests/ui/parser/wrong-escape-of-curly-braces.rs b/tests/ui/parser/wrong-escape-of-curly-braces.rs new file mode 100644 index 000000000..8e5258acd --- /dev/null +++ b/tests/ui/parser/wrong-escape-of-curly-braces.rs @@ -0,0 +1,8 @@ +fn main() { + let ok = "{{everything fine}}"; + let bad = "\{it is wrong\}"; + //~^ ERROR unknown character escape: `{` + //~| HELP if used in a formatting string, curly braces are escaped with `{{` and `}}` + //~| ERROR unknown character escape: `}` + //~| HELP if used in a formatting string, curly braces are escaped with `{{` and `}}` +} diff --git a/tests/ui/parser/wrong-escape-of-curly-braces.stderr b/tests/ui/parser/wrong-escape-of-curly-braces.stderr new file mode 100644 index 000000000..ff1a2fb0f --- /dev/null +++ b/tests/ui/parser/wrong-escape-of-curly-braces.stderr @@ -0,0 +1,18 @@ +error: unknown character escape: `{` + --> $DIR/wrong-escape-of-curly-braces.rs:3:17 + | +LL | let bad = "\{it is wrong\}"; + | ^ unknown character escape + | + = help: if used in a formatting string, curly braces are escaped with `{{` and `}}` + +error: unknown character escape: `}` + --> $DIR/wrong-escape-of-curly-braces.rs:3:30 + | +LL | let bad = "\{it is wrong\}"; + | ^ unknown character escape + | + = help: if used in a formatting string, curly braces are escaped with `{{` and `}}` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/partialeq_help.rs b/tests/ui/partialeq_help.rs new file mode 100644 index 000000000..34b88b8a8 --- /dev/null +++ b/tests/ui/partialeq_help.rs @@ -0,0 +1,12 @@ +fn foo(a: &T, b: T) { + a == b; //~ ERROR E0277 +} + +fn foo2(a: &T, b: T) where { + a == b; //~ ERROR E0277 +} + +fn main() { + foo(&1, 1); + foo2(&1, 1); +} diff --git a/tests/ui/partialeq_help.stderr b/tests/ui/partialeq_help.stderr new file mode 100644 index 000000000..fdff94f42 --- /dev/null +++ b/tests/ui/partialeq_help.stderr @@ -0,0 +1,27 @@ +error[E0277]: can't compare `&T` with `T` + --> $DIR/partialeq_help.rs:2:7 + | +LL | a == b; + | ^^ no implementation for `&T == T` + | + = help: the trait `PartialEq` is not implemented for `&T` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn foo(a: &T, b: T) where &T: PartialEq { + | ++++++++++++++++++++++ + +error[E0277]: can't compare `&T` with `T` + --> $DIR/partialeq_help.rs:6:7 + | +LL | a == b; + | ^^ no implementation for `&T == T` + | + = help: the trait `PartialEq` is not implemented for `&T` +help: consider extending the `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn foo2(a: &T, b: T) where &T: PartialEq { + | ++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/path-lookahead.fixed b/tests/ui/path-lookahead.fixed new file mode 100644 index 000000000..928955630 --- /dev/null +++ b/tests/ui/path-lookahead.fixed @@ -0,0 +1,17 @@ +// run-pass +// run-rustfix + +#![allow(dead_code)] +#![warn(unused_parens)] + +// Parser test for #37765 + +fn with_parens(arg: T) -> String { + return ::to_string(&arg); //~WARN unnecessary parentheses around `return` value +} + +fn no_parens(arg: T) -> String { + return ::to_string(&arg); +} + +fn main() {} diff --git a/tests/ui/path-lookahead.rs b/tests/ui/path-lookahead.rs new file mode 100644 index 000000000..d05c75fe8 --- /dev/null +++ b/tests/ui/path-lookahead.rs @@ -0,0 +1,17 @@ +// run-pass +// run-rustfix + +#![allow(dead_code)] +#![warn(unused_parens)] + +// Parser test for #37765 + +fn with_parens(arg: T) -> String { + return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value +} + +fn no_parens(arg: T) -> String { + return ::to_string(&arg); +} + +fn main() {} diff --git a/tests/ui/path-lookahead.stderr b/tests/ui/path-lookahead.stderr new file mode 100644 index 000000000..2cc786fd9 --- /dev/null +++ b/tests/ui/path-lookahead.stderr @@ -0,0 +1,19 @@ +warning: unnecessary parentheses around `return` value + --> $DIR/path-lookahead.rs:10:12 + | +LL | return (::to_string(&arg)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/path-lookahead.rs:5:9 + | +LL | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - return (::to_string(&arg)); +LL + return ::to_string(&arg); + | + +warning: 1 warning emitted + diff --git a/tests/ui/path.rs b/tests/ui/path.rs new file mode 100644 index 000000000..4c137de82 --- /dev/null +++ b/tests/ui/path.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +mod foo { + pub fn bar(_offset: usize) { } +} + +pub fn main() { foo::bar(0); } diff --git a/tests/ui/paths-containing-nul.rs b/tests/ui/paths-containing-nul.rs new file mode 100644 index 000000000..cb40c4f6f --- /dev/null +++ b/tests/ui/paths-containing-nul.rs @@ -0,0 +1,49 @@ +// run-pass + +#![allow(deprecated)] +// ignore-wasm32-bare no files or I/O +// ignore-emscripten no files +// ignore-sgx no files + +use std::fs; +use std::io; + +fn assert_invalid_input(on: &str, result: io::Result) { + fn inner(on: &str, result: io::Result<()>) { + match result { + Ok(()) => panic!("{} didn't return an error on a path with NUL", on), + Err(e) => assert!(e.kind() == io::ErrorKind::InvalidInput, + "{} returned a strange {:?} on a path with NUL", on, e.kind()), + } + } + inner(on, result.map(drop)) +} + +fn main() { + assert_invalid_input("File::open", fs::File::open("\0")); + assert_invalid_input("File::create", fs::File::create("\0")); + assert_invalid_input("remove_file", fs::remove_file("\0")); + assert_invalid_input("metadata", fs::metadata("\0")); + assert_invalid_input("symlink_metadata", fs::symlink_metadata("\0")); + + // If `dummy_file` does not exist, then we might get another unrelated error + let dummy_file = std::env::current_exe().unwrap(); + + assert_invalid_input("rename1", fs::rename("\0", "a")); + assert_invalid_input("rename2", fs::rename(&dummy_file, "\0")); + assert_invalid_input("copy1", fs::copy("\0", "a")); + assert_invalid_input("copy2", fs::copy(&dummy_file, "\0")); + assert_invalid_input("hard_link1", fs::hard_link("\0", "a")); + assert_invalid_input("hard_link2", fs::hard_link(&dummy_file, "\0")); + assert_invalid_input("soft_link1", fs::soft_link("\0", "a")); + assert_invalid_input("soft_link2", fs::soft_link(&dummy_file, "\0")); + assert_invalid_input("read_link", fs::read_link("\0")); + assert_invalid_input("canonicalize", fs::canonicalize("\0")); + assert_invalid_input("create_dir", fs::create_dir("\0")); + assert_invalid_input("create_dir_all", fs::create_dir_all("\0")); + assert_invalid_input("remove_dir", fs::remove_dir("\0")); + assert_invalid_input("remove_dir_all", fs::remove_dir_all("\0")); + assert_invalid_input("read_dir", fs::read_dir("\0")); + assert_invalid_input("set_permissions", + fs::set_permissions("\0", fs::metadata(".").unwrap().permissions())); +} diff --git a/tests/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs b/tests/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs new file mode 100644 index 000000000..f7373c453 --- /dev/null +++ b/tests/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs @@ -0,0 +1,20 @@ +pub struct Z0; +pub struct Z1(); + +pub struct S(pub u8, pub u8, pub u8); +pub struct M( + pub u8, + pub u8, + pub u8, +); + +pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + +pub enum E2 { + S(u8, u8, u8), + M( + u8, + u8, + u8, + ), +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs new file mode 100644 index 000000000..2b349f0ed --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs @@ -0,0 +1,47 @@ +// run-pass + +// Test copy + +struct A { a: i32, b: i32 } +struct B { a: i32, b: C } +struct D { a: i32, d: C } +#[derive(Copy,Clone)] +struct C { c: i32 } + +pub fn main() { + match (A {a: 10, b: 20}) { + x@A {a, b: 20} => { assert!(x.a == 10); assert!(a == 10); } + A {b: _b, ..} => { panic!(); } + } + + let mut x@B {b, ..} = B {a: 10, b: C {c: 20}}; + assert_eq!(x.a, 10); + x.b.c = 30; + assert_eq!(b.c, 20); + let mut y@D {d, ..} = D {a: 10, d: C {c: 20}}; + assert_eq!(y.a, 10); + y.d.c = 30; + assert_eq!(d.c, 20); + + let some_b = Some(B { a: 10, b: C { c: 20 } }); + + // in irrefutable pattern + if let Some(x @ B { b, .. }) = some_b { + assert_eq!(x.b.c, 20); + assert_eq!(b.c, 20); + } else { + unreachable!(); + } + + let some_b = Some(B { a: 10, b: C { c: 20 } }); + + if let Some(x @ B { b: mut b @ C { c }, .. }) = some_b { + assert_eq!(x.b.c, 20); + assert_eq!(b.c, 20); + b.c = 30; + assert_eq!(b.c, 30); + assert_eq!(c, 20); + } else { + unreachable!(); + } +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs new file mode 100644 index 000000000..9d1f08d6e --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs @@ -0,0 +1,37 @@ +// This test is taken directly from #16053. +// It checks that you cannot use an AND-pattern (`binding @ pat`) +// where one side is by-ref and the other is by-move. + +struct X { + x: (), +} + +fn main() { + let x = Some(X { x: () }); + match x { + Some(ref _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + None => panic!(), + } + + let x = Some(X { x: () }); + match x { + Some(_z @ ref _y) => {} + //~^ ERROR borrow of moved value + None => panic!(), + } + + let mut x = Some(X { x: () }); + match x { + Some(ref mut _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + None => panic!(), + } + + let mut x = Some(X { x: () }); + match x { + Some(_z @ ref mut _y) => {} + //~^ ERROR borrow of moved value + None => panic!(), + } +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr new file mode 100644 index 000000000..c8b45fd24 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -0,0 +1,79 @@ +error: cannot move out of value because it is borrowed + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14 + | +LL | Some(ref _y @ _z) => {} + | ------^^^-- + | | | + | | value moved into `_z` here + | value borrowed, by `_y`, here + +error: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14 + | +LL | Some(_z @ ref _y) => {} + | --^^^------ + | | | + | | value borrowed here after move + | value moved into `_z` here + | move occurs because `_z` has type `X` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _z @ ref _y) => {} + | +++ + +error: cannot move out of value because it is borrowed + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14 + | +LL | Some(ref mut _y @ _z) => {} + | ----------^^^-- + | | | + | | value moved into `_z` here + | value borrowed, by `_y`, here + +error: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14 + | +LL | Some(_z @ ref mut _y) => {} + | --^^^---------- + | | | + | | value borrowed here after move + | value moved into `_z` here + | move occurs because `_z` has type `X` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _z @ ref mut _y) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14 + | +LL | Some(ref _y @ _z) => {} + | ^^^^^^ -- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `X`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _y @ ref _z) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14 + | +LL | Some(ref mut _y @ _z) => {} + | ^^^^^^^^^^ -- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `X`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref mut _y @ ref _z) => {} + | +++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs new file mode 100644 index 000000000..1816a74a0 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs @@ -0,0 +1,11 @@ +// See issue #12534. + +fn main() {} + +struct A(Box); + +fn f(a @ A(u): A) -> Box { + //~^ ERROR use of partially moved value + drop(a); + u +} diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr new file mode 100644 index 000000000..a481ca468 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of partially moved value + --> $DIR/bind-by-move-no-subbindings-fun-param.rs:7:6 + | +LL | fn f(a @ A(u): A) -> Box { + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs new file mode 100644 index 000000000..a61d68215 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -0,0 +1,31 @@ +// Test that moving on both sides of an `@` pattern is not allowed. + +fn main() { + struct U; // Not copy! + + // Prevent promotion: + fn u() -> U { + U + } + + let a @ b = U; //~ ERROR use of moved value + + let a @ (b, c) = (U, U); //~ ERROR use of partially moved value + + let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value + + match Ok(U) { + a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value + //~^ ERROR use of moved value + } + + fn fun(a @ b: U) {} //~ ERROR use of moved value + + match [u(), u(), u(), u()] { + xs @ [a, .., b] => {} //~ ERROR use of partially moved value + } + + match [u(), u(), u(), u()] { + xs @ [_, ys @ .., _] => {} //~ ERROR use of partially moved value + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr new file mode 100644 index 000000000..324897151 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -0,0 +1,112 @@ +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:11:9 + | +LL | let a @ b = U; + | ^ - - move occurs because value has type `U`, which does not implement the `Copy` trait + | | | + | | value moved here + | value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:13:9 + | +LL | let a @ (b, c) = (U, U); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, ref c) = (U, U); + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:15:9 + | +LL | let a @ (b, c) = (u(), u()); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, ref c) = (u(), u()); + | +++ +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:18:16 + | +LL | match Ok(U) { + | ----- move occurs because value has type `Result`, which does not implement the `Copy` trait +LL | a @ Ok(b) | a @ Err(b) => {} + | - ^ value used here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Ok(b) | a @ Err(b) => {} + | +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:18:29 + | +LL | match Ok(U) { + | ----- move occurs because value has type `Result`, which does not implement the `Copy` trait +LL | a @ Ok(b) | a @ Err(b) => {} + | - ^ value used here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Ok(b) | ref a @ Err(b) => {} + | +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:25:9 + | +LL | xs @ [a, .., b] => {} + | ^^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref xs @ [a, .., ref b] => {} + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:29:9 + | +LL | xs @ [_, ys @ .., _] => {} + | ^^ -- value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref xs @ [_, ref ys @ .., _] => {} + | +++ +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-move-and-move.rs:22:12 + | +LL | fn fun(a @ b: U) {} + | ^ - value moved here + | | + | value used here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs new file mode 100644 index 000000000..fbdefd9d3 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs @@ -0,0 +1,84 @@ +// check-pass + +// Test `@` patterns combined with `box` patterns. + +#![feature(box_patterns)] + +#[derive(Copy, Clone)] +struct C; + +fn c() -> C { C } + +struct NC; + +fn nc() -> NC { NC } + +fn main() { + let ref a @ box b = Box::new(C); // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + + let ref a @ box b = Box::new(c()); // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + + fn f3(ref a @ box b: Box) { // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + } + match Box::new(c()) { + ref a @ box b => { // OK; the type is `Copy`. + drop(b); + drop(b); + drop(a); + } + } + + let ref a @ box ref b = Box::new(NC); // OK. + drop(a); + drop(b); + + fn f4(ref a @ box ref b: Box) { // OK. + drop(a); + drop(b) + } + + match Box::new(nc()) { + ref a @ box ref b => { // OK. + drop(a); + drop(b); + } + } + + match Box::new([Ok(c()), Err(nc()), Ok(c())]) { + box [Ok(a), ref xs @ .., Err(ref b)] => { + let _: C = a; + let _: &[Result; 1] = xs; + let _: &NC = b; + } + _ => {} + } + + match [Ok(Box::new(c())), Err(Box::new(nc())), Ok(Box::new(c())), Ok(Box::new(c()))] { + [Ok(box a), ref xs @ .., Err(box ref b), Err(box ref c)] => { + let _: C = a; + let _: &[Result, Box>; 1] = xs; + let _: &NC = b; + let _: &NC = c; + } + _ => {} + } + + match Box::new([Ok(c()), Err(nc()), Ok(c())]) { + box [Ok(a), ref xs @ .., Err(b)] => {} + _ => {} + } + + match [Ok(Box::new(c())), Err(Box::new(nc())), Ok(Box::new(c())), Ok(Box::new(c()))] { + [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} + _ => {} + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs new file mode 100644 index 000000000..45aa65e67 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs @@ -0,0 +1,69 @@ +// Test `@` patterns combined with `box` patterns. + +#![feature(box_patterns)] + +#[derive(Copy, Clone)] +struct C; + +fn c() -> C { + C +} + +struct NC; + +fn nc() -> NC { + NC +} + +fn main() { + let a @ box &b = Box::new(&C); + + let a @ box b = Box::new(C); + + fn f1(a @ box &b: Box<&C>) {} + + fn f2(a @ box b: Box) {} + + match Box::new(C) { + a @ box b => {} + } + + let ref a @ box b = Box::new(NC); //~ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + + let ref a @ box ref mut b = Box::new(nc()); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref a @ box ref mut b = Box::new(NC); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref a @ box ref mut b = Box::new(NC); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = NC; + let ref a @ box ref mut b = Box::new(NC); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = NC; + drop(a); + + let ref mut a @ box ref b = Box::new(NC); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = Box::new(NC); + drop(b); + + fn f5(ref mut a @ box ref b: Box) { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = Box::new(NC); + drop(b); + } + + match Box::new(nc()) { + ref mut a @ box ref b => { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = Box::new(NC); + drop(b); + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr new file mode 100644 index 000000000..f27df32cc --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -0,0 +1,145 @@ +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-at-and-box.rs:31:9 + | +LL | let ref a @ box b = Box::new(NC); + | -----^^^^^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:34:9 + | +LL | let ref a @ box ref mut b = Box::new(nc()); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:36:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:38:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:42:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | -----^^^^^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:48:9 + | +LL | let ref mut a @ box ref b = Box::new(NC); + | ---------^^^^^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:62:9 + | +LL | ref mut a @ box ref b => { + | ---------^^^^^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:54:11 + | +LL | fn f5(ref mut a @ box ref b: Box) { + | ---------^^^^^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-at-and-box.rs:31:9 + | +LL | let ref a @ box b = Box::new(NC); + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `NC`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ box ref b = Box::new(NC); + | +++ + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:38:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = NC; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:42:9 + | +LL | let ref a @ box ref mut b = Box::new(NC); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = NC; + | ------- mutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:48:9 + | +LL | let ref mut a @ box ref b = Box::new(NC); + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:62:9 + | +LL | ref mut a @ box ref b => { + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:54:11 + | +LL | fn f5(ref mut a @ box ref b: Box) { + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs new file mode 100644 index 000000000..0108861cf --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs @@ -0,0 +1,49 @@ +// check-pass + +// Test `Copy` bindings in the rhs of `@` patterns. + +#[derive(Copy, Clone)] +struct C; + +fn mk_c() -> C { C } + +#[derive(Copy, Clone)] +struct P(A, B); + +enum E { L(A), R(B) } + +fn main() { + let a @ b @ c @ d = C; + let a @ (b, c) = (C, mk_c()); + let a @ P(b, P(c, d)) = P(mk_c(), P(C, C)); + let a @ [b, c] = [C, C]; + let a @ [b, .., c] = [C, mk_c(), C]; + let a @ [b, mid @ .., c] = [C, mk_c(), C]; + let a @ &(b, c) = &(C, C); + let a @ &(b, &P(c, d)) = &(mk_c(), &P(C, C)); + + fn foo(a @ [b, mid @ .., c]: [C; 3]) {} + + use self::E::*; + match L(C) { + L(a) | R(a) => { + let a: C = a; + drop(a); + drop(a); + } + } + match R(&L(&mk_c())) { + L(L(&a)) | L(R(&a)) | R(L(&a)) | R(R(&a)) => { + let a: C = a; + drop(a); + drop(a); + } + } + + match Ok(mk_c()) { + Ok(ref a @ b) | Err(b @ ref a) => { + let _: &C = a; + let _: C = b; + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs new file mode 100644 index 000000000..82f16fca6 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs @@ -0,0 +1,7 @@ +// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented even with promotion. +// Currently this logic exists in THIR match checking as opposed to borrowck. + +fn main() { + struct U; + let a @ ref b = U; //~ ERROR borrow of moved value +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr new file mode 100644 index 000000000..d6474f1b4 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -0,0 +1,17 @@ +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:6:9 + | +LL | let a @ ref b = U; + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs new file mode 100644 index 000000000..06dc6e1c4 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs @@ -0,0 +1,80 @@ +// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented. + +fn main() { + struct U; + + // Prevent promotion. + fn u() -> U { + U + } + + fn f1(a @ ref b: U) {} + //~^ ERROR borrow of moved value + + fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of partially moved value + fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + //~^ ERROR borrow of moved value + + let a @ ref b = U; + //~^ ERROR borrow of moved value + let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of partially moved value + let a @ [ref mut b, ref c] = [U, U]; + //~^ ERROR borrow of moved value + let a @ ref b = u(); + //~^ ERROR borrow of moved value + let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of partially moved value + let a @ [ref mut b, ref c] = [u(), u()]; + //~^ ERROR borrow of moved value + + match Some(U) { + a @ Some(ref b) => {} + //~^ ERROR borrow of moved value + None => {} + } + match Some((U, U)) { + a @ Some((mut b @ ref mut c, d @ ref e)) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + None => {} + } + match Some([U, U]) { + mut a @ Some([ref b, ref mut c]) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some(u()) { + a @ Some(ref b) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some((u(), u())) { + a @ Some((mut b @ ref mut c, d @ ref e)) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + None => {} + } + match Some([u(), u()]) { + mut a @ Some([ref b, ref mut c]) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr new file mode 100644 index 000000000..389e86e64 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -0,0 +1,487 @@ +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:22:9 + | +LL | let a @ ref b = U; + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -^^^^^^^^^^^^---------^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (ref mut b @ ref mut c, d @ ref e) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (mut b @ ref mut c, ref d @ ref e) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9 + | +LL | let a @ [ref mut b, ref c] = [U, U]; + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ [ref mut b, ref c] = [U, U]; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9 + | +LL | let a @ ref b = u(); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = u(); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -^^^^^^^^^^^^---------^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (ref mut b @ ref mut c, d @ ref e) = (u(), u()); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9 + | +LL | let a @ [ref mut b, ref c] = [u(), u()]; + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ [ref mut b, ref c] = [u(), u()]; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9 + | +LL | a @ Some(ref b) => {} + | -^^^^^^^^-----^ + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9 + | +LL | mut a @ Some([ref b, ref mut c]) => {} + | -----^^^^^^^^^-----^^---------^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([ref b, ref mut c]) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 + | +LL | a @ Some(ref b) => {} + | -^^^^^^^^-----^ + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 + | +LL | mut a @ Some([ref b, ref mut c]) => {} + | -----^^^^^^^^^-----^^---------^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([ref b, ref mut c]) => {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 + | +LL | fn f1(a @ ref b: U) {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f1(ref a @ ref b: U) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -----^^^^^^^^-----^^^^^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(ref mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(mut a @ (ref b @ ref c, mut d @ ref e): (U, U)) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -----^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(mut a @ (b @ ref c, ref mut d @ ref e): (U, U)) {} + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11 + | +LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {} + | +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (U, U); + | +++ +++ + +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); + | +++ +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 + | +LL | match Some((U, U)) { + | ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | - value moved here ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30 + | +LL | match Some([U, U]) { + | ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait +LL | mut a @ Some([ref b, ref mut c]) => {} + | ----- ^^^^^^^^^ value borrowed here after move + | | + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18 + | +LL | match Some(u()) { + | --------- move occurs because value has type `Option`, which does not implement the `Copy` trait +LL | a @ Some(ref b) => {} + | - ^^^^^ value borrowed here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + | +LL | match Some((u(), u())) { + | ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | - value moved here ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30 + | +LL | match Some([u(), u()]) { + | ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait +LL | mut a @ Some([ref b, ref mut c]) => {} + | ----- ^^^^^^^^^ value borrowed here after move + | | + | value moved here + +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | ^^^^^ ----- value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 33 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs new file mode 100644 index 000000000..0b0a78010 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs @@ -0,0 +1,82 @@ +// Test that `ref mut? @ pat_with_by_move_bindings` is prevented. + +fn main() { + struct U; + + // Prevent promotion. + fn u() -> U { + U + } + + fn f1(ref a @ b: U) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value + + let ref a @ b = U; + //~^ ERROR cannot move out of value because it is borrowed + let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + let ref mut a @ [b, mut c] = [U, U]; + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value + let ref a @ b = u(); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + let ref mut a @ [b, mut c] = [u(), u()]; + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value + + match Some(U) { + ref a @ Some(b) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some((U, U)) { + ref a @ Some((ref b @ mut c, ref d @ e)) => {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + None => {} + } + match Some([U, U]) { + ref mut a @ Some([b, mut c]) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some(u()) { + ref a @ Some(b) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some((u(), u())) { + ref a @ Some((ref b @ mut c, ref d @ e)) => {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some([u(), u()]) { + ref mut a @ Some([b, mut c]) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr new file mode 100644 index 000000000..770bb8953 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -0,0 +1,375 @@ +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:24:9 + | +LL | let ref a @ b = U; + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:26:9 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:26:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:26:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9 + | +LL | let ref mut a @ [b, mut c] = [U, U]; + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 + | +LL | let ref a @ b = u(); + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:9 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9 + | +LL | let ref mut a @ [b, mut c] = [u(), u()]; + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:47:9 + | +LL | ref a @ Some(b) => {} + | -----^^^^^^^^-^ + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:52:9 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:52:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:52:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ---------^^^^^^^^^-^^-----^^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9 + | +LL | ref a @ Some(b) => {} + | -----^^^^^^^^-^ + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ---------^^^^^^^^^-^^-----^^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 + | +LL | fn f1(ref a @ b: U) {} + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11 + | +LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9 + | +LL | let ref mut a @ [b, mut c] = [U, U]; + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ [b, ref mut c] = [U, U]; + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 + | +LL | let ref a @ b = u(); + | ^^^^^ - --- move occurs because value has type `U`, which does not implement the `Copy` trait + | | | + | | value moved here + | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = u(); + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | ^^^^^ ----- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref b @ ref mut c, ref d @ e) = (u(), u()); + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref b @ mut c, ref d @ ref e) = (u(), u()); + | +++ + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9 + | +LL | let ref mut a @ [b, mut c] = [u(), u()]; + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ [b, ref mut c] = [u(), u()]; + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | ^^^^^ ----- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((ref b @ ref mut c, ref d @ e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((ref b @ mut c, ref d @ ref e)) => {} + | +++ + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 + | +LL | fn f1(ref a @ b: U) {} + | ^^^^^ - value moved here + | | + | value borrowed here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | ^^^^^ ----- value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | ^^^^^ - value moved here + | | + | value borrowed here after move + | + = note: move occurs because value has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11 + | +LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 36 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs new file mode 100644 index 000000000..df213f688 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs @@ -0,0 +1,45 @@ +// check-pass + +// Test that `ref` patterns may be used on both sides +// of an `@` pattern according to NLL borrowck. + +fn main() { + struct U; // Not copy! + + // Promotion: + let ref a @ ref b = U; + let _: &U = a; + let _: &U = b; + + // Prevent promotion: + fn u() -> U { U } + + let ref a @ ref b = u(); + let _: &U = a; + let _: &U = b; + + let ref a @ (ref b, [ref c, ref d]) = (u(), [u(), u()]); + let _: &(U, [U; 2]) = a; + let _: &U = b; + let _: &U = c; + let _: &U = d; + + fn f1(ref a @ (ref b, [ref c, ref mid @ .., ref d]): (U, [U; 4])) {} + + let a @ (b, [c, d]) = &(u(), [u(), u()]); + let _: &(U, [U; 2]) = a; + let _: &U = b; + let _: &U = c; + let _: &U = d; + + let ref a @ &ref b = &u(); + let _: &&U = a; + let _: &U = b; + + match Ok(u()) { + ref a @ Ok(ref b) | ref a @ Err(ref b) => { + let _: &Result = a; + let _: &U = b; + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs new file mode 100644 index 000000000..6bc0d346c --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -0,0 +1,136 @@ +enum Option { + None, + Some(T), +} + +fn main() { + match &mut Some(1) { + ref mut z @ &mut Some(ref a) => { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + **z = None; + println!("{}", *a); + } + _ => () + } + + struct U; + + // Prevent promotion: + fn u() -> U { U } + + fn f1(ref a @ ref mut b: U) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + fn f2(ref mut a @ ref b: U) {} + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + fn f4_also_moved(ref a @ ref mut b @ c: U) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + + let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + + let ref a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref mut a @ ref b = U; + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + let ref mut a @ (ref b, ref c) = (U, U); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + + let ref mut a @ ref b = u(); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *a = u(); + drop(b); + let ref a @ ref mut b = u(); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = u(); + drop(a); + + let ref mut a @ ref b = U; + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + *a = U; + drop(b); + let ref a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + *b = U; + drop(a); + + match Ok(U) { + ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *a = Err(U); + drop(b); + } + } + + match Ok(U) { + ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *b = U; + drop(a); + } + } + + match Ok(U) { + ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard + _ => {} + } + match Ok(U) { + ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot assign to `*a`, as it is immutable for the pattern guard + _ => {} + } + match Ok(U) { + ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot move out of `b` in pattern guard + //~| ERROR cannot move out of `b` in pattern guard + _ => {} + } + match Ok(U) { + ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot move out of `a` in pattern guard + //~| ERROR cannot move out of `a` in pattern guard + _ => {} + } + + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = U; + *c = U; + + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = U; + drop(a); + + let ref a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + *b = U; //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *c = U; + drop(a); + let ref mut a @ (ref b, ref c) = (U, U); + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr new file mode 100644 index 000000000..8546b4bb4 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -0,0 +1,445 @@ +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9 + | +LL | ref mut z @ &mut Some(ref a) => { + | ---------^^^^^^^^^^^^^-----^ + | | | + | | immutable borrow, by `a`, occurs here + | mutable borrow, by `z`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:9 + | +LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub + | ---------^^^^-----------------^ + | | | | + | | | another mutable borrow, by `c`, occurs here + | | also borrowed as immutable, by `b`, here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:22 + | +LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub + | -----^^^--------- + | | | + | | mutable borrow, by `c`, occurs here + | immutable borrow, by `b`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9 + | +LL | let ref a @ ref mut b = U; + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9 + | +LL | let ref mut a @ ref b = U; + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9 + | +LL | let ref mut a @ (ref b, ref c) = (U, U); + | ---------^^^^-----^^-----^ + | | | | + | | | immutable borrow, by `c`, occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 + | +LL | let ref mut a @ ref b = u(); + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9 + | +LL | let ref a @ ref mut b = u(); + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:57:9 + | +LL | let ref mut a @ ref b = U; + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:61:9 + | +LL | let ref a @ ref mut b = U; + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:9 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { + | ---------^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:33 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { + | ---------^^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | -----^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | -----^^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | -----^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | -----^^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + | ---------^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + | ---------^^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | -----^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | -----^^^^^^^---------^ + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ---------^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ---------^^^^^^^-----^ + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | -----^^^^---------^^---------^ + | | | | + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9 + | +LL | let ref mut a @ (ref b, ref c) = (U, U); + | ---------^^^^-----^^-----^ + | | | | + | | | immutable borrow, by `c`, occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11 + | +LL | fn f1(ref a @ ref mut b: U) {} + | -----^^^--------- + | | | + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11 + | +LL | fn f2(ref mut a @ ref b: U) {} + | ---------^^^----- + | | | + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11 + | +LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} + | -----^^^^^^^^^^^----------------^^^^^^^^ + | | | + | | mutable borrow, by `mid`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | -----^^^------------- + | | | | + | | | also moved into `c` here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | ---------^^^- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31 + | +LL | ref mut z @ &mut Some(ref a) => { + | --------- ^^^^^ immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | **z = None; + | ---------- mutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 + | +LL | let ref mut a @ ref b = u(); + | ^^^^^^^^^ ----- immutable borrow occurs here + | | + | mutable borrow occurs here +... +LL | drop(b); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9 + | +LL | let ref a @ ref mut b = u(); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = u(); + | -------- mutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | ----- ^^^^^^^^^ mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | drop(a); + | - immutable borrow later used here + +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { + | ----- ^^^^^^^^^ mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | drop(a); + | - immutable borrow later used here + +error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^^ cannot assign + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} + | ^^^^^^^^^^^ cannot assign + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error[E0507]: cannot move out of `b` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `b` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `a` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `a` in pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + | +LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} + | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +... +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | ^^^^^ --------- mutable borrow occurs here + | | + | immutable borrow occurs here +LL | +LL | *b = U; + | ------ mutable borrow later used here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | ----- ^^^^^^^^^ - value moved here + | | | + | | value borrowed here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 47 previous errors + +Some errors have detailed explanations: E0382, E0502, E0507, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs new file mode 100644 index 000000000..99739c7bc --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -0,0 +1,109 @@ +// Test that `ref mut x @ ref mut y` and varieties of that are not allowed. + +fn main() { + struct U; + + fn u() -> U { U } + + fn f1(ref mut a @ ref mut b: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + fn f2(ref mut a @ ref mut b: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + fn f3( + ref mut a @ [ + //~^ ERROR cannot borrow value as mutable more than once at a time + [ref b @ .., _], + [_, ref mut mid @ ..], + .., + [..], + ] : [[U; 4]; 5] + ) {} + fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + drop(a); + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + drop(b); + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + *a = U; + let ref mut a @ ref mut b = U; + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + *b = U; + + let ref mut a @ ( + //~^ ERROR cannot borrow value as mutable more than once at a time + ref mut b, + [ + ref mut c, + ref mut d, + ref e, + ] + ) = (U, [U, U, U]); + + let ref mut a @ ( + //~^ ERROR cannot borrow value as mutable more than once at a time + ref mut b, + [ + ref mut c, + ref mut d, + ref e, + ] + ) = (u(), [u(), u(), u()]); + + let a @ (ref mut b, ref mut c) = (U, U); + //~^ ERROR borrow of moved value + let mut val = (U, [U, U]); + let a @ (b, [c, d]) = &mut val; // Same as ^-- + //~^ ERROR borrow of moved value + + let a @ &mut ref mut b = &mut U; + //~^ ERROR borrow of moved value + let a @ &mut (ref mut b, ref mut c) = &mut (U, U); + //~^ ERROR borrow of moved value + + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + } + } + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + *b = U; + } + } + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + *a = Err(U); + + // FIXME: The binding name value used above makes for problematic diagnostics. + // Resolve that somehow... + } + } + match Ok(U) { + ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + drop(a); + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr new file mode 100644 index 000000000..ad4ce7952 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -0,0 +1,359 @@ +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:26:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:33:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:36:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9 + | +LL | let ref mut a @ ref mut b = U; + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:44:9 + | +LL | let ref mut a @ ( + | ^-------- + | | + | _________first mutable borrow, by `a`, occurs here + | | +LL | | +LL | | ref mut b, + | | --------- another mutable borrow, by `b`, occurs here +LL | | [ +LL | | ref mut c, + | | --------- another mutable borrow, by `c`, occurs here +LL | | ref mut d, + | | --------- another mutable borrow, by `d`, occurs here +LL | | ref e, + | | ----- also borrowed as immutable, by `e`, here +LL | | ] +LL | | ) = (U, [U, U, U]); + | |_____^ + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:54:9 + | +LL | let ref mut a @ ( + | ^-------- + | | + | _________first mutable borrow, by `a`, occurs here + | | +LL | | +LL | | ref mut b, + | | --------- another mutable borrow, by `b`, occurs here +LL | | [ +LL | | ref mut c, + | | --------- another mutable borrow, by `c`, occurs here +LL | | ref mut d, + | | --------- another mutable borrow, by `d`, occurs here +LL | | ref e, + | | ----- also borrowed as immutable, by `e`, here +LL | | ] +LL | | ) = (u(), [u(), u(), u()]); + | |_________^ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:64:9 + | +LL | let a @ (ref mut b, ref mut c) = (U, U); + | -^^^^---------^^---------^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9 + | +LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- + | -^^^^-^^^-^^-^^ + | | | | | + | | | | value borrowed here after move + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, [c, d]) = &mut val; // Same as ^-- + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 + | +LL | let a @ &mut ref mut b = &mut U; + | -^^^^^^^^--------- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ &mut ref mut b = &mut U; + | +++ + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9 + | +LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); + | -^^^^^^^^^---------^^---------^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ &mut (ref mut b, ref mut c) = &mut (U, U); + | +++ + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:76:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:9 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:37 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | ---------^^^^^^^---------^ + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11 + | +LL | fn f1(ref mut a @ ref mut b: U) {} + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11 + | +LL | fn f2(ref mut a @ ref mut b: U) {} + | ---------^^^--------- + | | | + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9 + | +LL | ref mut a @ [ + | ^-------- + | | + | _________first mutable borrow, by `a`, occurs here + | | +LL | | +LL | | [ref b @ .., _], + | | ---------- also borrowed as immutable, by `b`, here +LL | | [_, ref mut mid @ ..], + | | ---------------- another mutable borrow, by `mid`, occurs here +LL | | .., +LL | | [..], +LL | | ] : [[U; 4]; 5] + | |_________^ + +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | ---------^^^------------- + | | | | + | | | also moved into `c` here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | ---------^^^- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9 + | +LL | let ref mut a @ ref mut b = U; + | ^^^^^^^^^ --------- first mutable borrow occurs here + | | + | second mutable borrow occurs here +... +LL | drop(b); + | - first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9 + | +LL | let ref mut a @ ref mut b = U; + | ^^^^^^^^^ --------- first mutable borrow occurs here + | | + | second mutable borrow occurs here +... +LL | *b = U; + | ------ first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | *a = Err(U); + | ----------- first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | *a = Err(U); + | ----------- first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | drop(a); + | - first borrow later used here + +error[E0499]: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53 + | +LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { + | --------- ^^^^^^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here +... +LL | drop(a); + | - first borrow later used here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | --------- ^^^^^^^^^ - value moved here + | | | + | | value borrowed here after move + | move occurs because value has type `U`, which does not implement the `Copy` trait + +error: aborting due to 31 previous errors + +Some errors have detailed explanations: E0382, E0499. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/box-patterns.rs b/tests/ui/pattern/bindings-after-at/box-patterns.rs new file mode 100644 index 000000000..9db37253c --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/box-patterns.rs @@ -0,0 +1,35 @@ +// Test bindings-after-at with box-patterns + +// run-pass + +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(x: Option>) -> MatchArm { + match x { + ref bar @ Some(box n) if n > 0 => { + // bar is a &Option> + assert_eq!(bar, &x); + + MatchArm::Arm(0) + }, + Some(ref bar @ box n) if n < 0 => { + // bar is a &Box here + assert_eq!(**bar, n); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(2))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(-1))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(0))), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs new file mode 100644 index 000000000..1e2c2968c --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.rs @@ -0,0 +1,14 @@ +// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden. + +#[derive(Copy, Clone)] +struct C; + +struct NC(A, B); + +fn main() { + // this compiles + let a @ NC(b, c) = NC(C, C); + + let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); + //~^ ERROR use of partially moved value +} diff --git a/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr new file mode 100644 index 000000000..e0e623fa5 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of partially moved value + --> $DIR/copy-and-move-mixed.rs:12:9 + | +LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); + | ^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `NC`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ NC(b, ref c @ NC(d, e)) = NC(C, NC(C, C)); + | +++ +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs new file mode 100644 index 000000000..dfd4d0285 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs @@ -0,0 +1,48 @@ +// Ensures the independence of each side in `binding @ subpat` +// determine their binding modes independently of each other. +// +// That is, `binding` does not influence `subpat`. +// This is important because we might want to allow `p1 @ p2`, +// where both `p1` and `p2` are syntactically unrestricted patterns. +// If `binding` is allowed to influence `subpat`, +// this would create problems for the generalization aforementioned. + + +fn main() { + struct NotCopy; + + fn f1(a @ b: &NotCopy) { // OK + let _: &NotCopy = a; + } + fn f2(ref a @ b: &NotCopy) { + let _: &&NotCopy = a; // Ok + } + + let a @ b = &NotCopy; // OK + let _: &NotCopy = a; + let ref a @ b = &NotCopy; // OK + let _: &&NotCopy = a; + + let ref a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; + let ref mut a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed + //~^ ERROR borrow of moved value + let _a: &NotCopy = a; + let _b: NotCopy = b; + match Ok(NotCopy) { + Ok(ref a @ b) | Err(b @ ref a) => { + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + let _a: &NotCopy = a; + let _b: NotCopy = b; + } + } + match NotCopy { + ref a @ b => { + //~^ ERROR cannot move out of value because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; + } + } +} diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr new file mode 100644 index 000000000..638bdd6db --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -0,0 +1,68 @@ +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:26:9 + | +LL | let ref a @ b = NotCopy; + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:29:9 + | +LL | let ref mut a @ b = NotCopy; + | ---------^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:34:12 + | +LL | Ok(ref a @ b) | Err(b @ ref a) => { + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: borrow of moved value + --> $DIR/default-binding-modes-both-sides-independent.rs:34:29 + | +LL | Ok(ref a @ b) | Err(b @ ref a) => { + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Ok(ref a @ b) | Err(ref b @ ref a) => { + | +++ + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:42:9 + | +LL | ref a @ b => { + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error[E0382]: borrow of moved value + --> $DIR/default-binding-modes-both-sides-independent.rs:29:9 + | +LL | let ref mut a @ b = NotCopy; + | ^^^^^^^^^ - ------- move occurs because value has type `NotCopy`, which does not implement the `Copy` trait + | | | + | | value moved here + | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ ref b = NotCopy; + | +++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs b/tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs new file mode 100644 index 000000000..fe7d1eba1 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-mode-lint.rs @@ -0,0 +1,12 @@ +// check-pass + +#![deny(unused_mut)] + +fn main() { + let mut is_mut @ not_mut = 42; + &mut is_mut; + ¬_mut; + let not_mut @ mut is_mut = 42; + &mut is_mut; + ¬_mut; +} diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs new file mode 100644 index 000000000..e7d99534d --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.rs @@ -0,0 +1,11 @@ +fn main() { + let mut is_mut @ not_mut = 42; + &mut is_mut; + &mut not_mut; + //~^ ERROR cannot borrow + + let not_mut @ mut is_mut = 42; + &mut is_mut; + &mut not_mut; + //~^ ERROR cannot borrow +} diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr new file mode 100644 index 000000000..54118dc36 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable + --> $DIR/nested-binding-modes-mut.rs:4:5 + | +LL | &mut not_mut; + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut is_mut @ mut not_mut = 42; + | +++ + +error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable + --> $DIR/nested-binding-modes-mut.rs:9:5 + | +LL | &mut not_mut; + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut not_mut @ mut is_mut = 42; + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs new file mode 100644 index 000000000..adfb0387f --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.rs @@ -0,0 +1,11 @@ +fn main() { + let ref is_ref @ is_val = 42; + *is_ref; + *is_val; + //~^ ERROR cannot be dereferenced + + let is_val @ ref is_ref = 42; + *is_ref; + *is_val; + //~^ ERROR cannot be dereferenced +} diff --git a/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr new file mode 100644 index 000000000..b378fe356 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-binding-modes-ref.stderr @@ -0,0 +1,15 @@ +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/nested-binding-modes-ref.rs:4:5 + | +LL | *is_val; + | ^^^^^^^ + +error[E0614]: type `{integer}` cannot be dereferenced + --> $DIR/nested-binding-modes-ref.rs:9:5 + | +LL | *is_val; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/pattern/bindings-after-at/nested-patterns.rs b/tests/ui/pattern/bindings-after-at/nested-patterns.rs new file mode 100644 index 000000000..f06563d56 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-patterns.rs @@ -0,0 +1,14 @@ +// run-pass + + +struct A { a: u8, b: u8 } + +pub fn main() { + match (A { a: 10, b: 20 }) { + ref x @ A { ref a, b: 20 } => { + assert_eq!(x.a, 10); + assert_eq!(*a, 10); + } + A { b: ref _b, .. } => panic!(), + } +} diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs new file mode 100644 index 000000000..a709e34b5 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs @@ -0,0 +1,33 @@ +// Here we check that type ascription is syntactically invalid when +// not in the top position of an ascribing `let` binding or function parameter. + + +// This has no effect. +// We include it to demonstrate that this is the case: +#![feature(type_ascription)] + +fn main() {} + +fn _ok() { + let _a @ _b: u8 = 0; // OK. + fn _f(_a @ _b: u8) {} // OK. +} + +#[cfg(FALSE)] +fn case_1() { + let a: u8 @ b = 0; + //~^ ERROR expected one of `!` +} + +#[cfg(FALSE)] +fn case_2() { + let a @ (b: u8); + //~^ ERROR expected one of `!` + //~| ERROR expected one of `)` +} + +#[cfg(FALSE)] +fn case_3() { + let a: T1 @ Outer(b: T2); + //~^ ERROR expected one of `!` +} diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr new file mode 100644 index 000000000..27660ae40 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr @@ -0,0 +1,26 @@ +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:18:15 + | +LL | let a: u8 @ b = 0; + | ^ expected one of 7 possible tokens + +error: expected one of `)`, `,`, `@`, or `|`, found `:` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:15 + | +LL | let a @ (b: u8); + | ^ expected one of `)`, `,`, `@`, or `|` + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `)` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:19 + | +LL | let a @ (b: u8); + | ^ expected one of 7 possible tokens + +error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` + --> $DIR/nested-type-ascription-syntactically-invalid.rs:31:15 + | +LL | let a: T1 @ Outer(b: T2); + | ^ expected one of 7 possible tokens + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs b/tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs new file mode 100644 index 000000000..383e377a5 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs @@ -0,0 +1,43 @@ +// Test bindings-after-at with or-patterns and box-patterns + +// run-pass + +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option>) -> MatchArm { + match foo { + ref bar @ Some(box Test::Foo | box Test::Bar) => { + assert_eq!(bar, &foo); + + MatchArm::Arm(0) + }, + Some(ref bar @ box Test::Baz | ref bar @ box Test::Qux) => { + assert!(**bar == Test::Baz || **bar == Test::Qux); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs new file mode 100644 index 000000000..d315f7ee3 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -0,0 +1,54 @@ +// Test bindings-after-at with or-patterns and slice-patterns + +// run-pass + + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option]) -> MatchArm { + match foo { + bar @ [Some(Test::Foo), .., Some(Test::Qux | Test::Foo)] => { + assert_eq!(bar, foo); + + MatchArm::Arm(0) + }, + [.., bar @ Some(Test::Bar | Test::Qux), _] => { + assert!(bar == &Some(Test::Bar) || bar == &Some(Test::Qux)); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + // path 1a + assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Qux), Some(Test::Baz)]), MatchArm::Arm(1)); + // path 3 + assert_eq!(test(&foo[1..2]), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/or-patterns.rs b/tests/ui/pattern/bindings-after-at/or-patterns.rs new file mode 100644 index 000000000..fcc361489 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/or-patterns.rs @@ -0,0 +1,38 @@ +// Test bindings-after-at with or-patterns + +// run-pass + + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option) -> MatchArm { + match foo { + bar @ Some(Test::Foo | Test::Bar) => { + assert!(bar == Some(Test::Foo) || bar == Some(Test::Bar)); + + MatchArm::Arm(0) + }, + Some(_) => MatchArm::Arm(1), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Test::Foo)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Bar)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Baz)), MatchArm::Arm(1)); + assert_eq!(test(Some(Test::Qux)), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs new file mode 100644 index 000000000..f167a3952 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs @@ -0,0 +1,29 @@ +// Test that `binding @ subpat` acts as a product context with respect to duplicate binding names. +// The code that is tested here lives in resolve (see `resolve_pattern_inner`). + + +fn main() { + fn f(a @ a @ a: ()) {} + //~^ ERROR identifier `a` is bound more than once in this parameter list + //~| ERROR identifier `a` is bound more than once in this parameter list + + match Ok(0) { + Ok(a @ b @ a) + //~^ ERROR identifier `a` is bound more than once in the same pattern + | Err(a @ b @ a) + //~^ ERROR identifier `a` is bound more than once in the same pattern + => {} + } + + let a @ a @ a = (); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern + let ref a @ ref a = (); + //~^ ERROR identifier `a` is bound more than once in the same pattern + let ref mut a @ ref mut a = (); + //~^ ERROR identifier `a` is bound more than once in the same pattern + + let a @ (Ok(a) | Err(a)) = Ok(()); + //~^ ERROR identifier `a` is bound more than once in the same pattern + //~| ERROR identifier `a` is bound more than once in the same pattern +} diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr new file mode 100644 index 000000000..a165549f6 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -0,0 +1,64 @@ +error[E0415]: identifier `a` is bound more than once in this parameter list + --> $DIR/pat-at-same-name-both.rs:6:14 + | +LL | fn f(a @ a @ a: ()) {} + | ^ used as parameter more than once + +error[E0415]: identifier `a` is bound more than once in this parameter list + --> $DIR/pat-at-same-name-both.rs:6:18 + | +LL | fn f(a @ a @ a: ()) {} + | ^ used as parameter more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:11:20 + | +LL | Ok(a @ b @ a) + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:13:23 + | +LL | | Err(a @ b @ a) + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:18:13 + | +LL | let a @ a @ a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:18:17 + | +LL | let a @ a @ a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:21:21 + | +LL | let ref a @ ref a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:23:29 + | +LL | let ref mut a @ ref mut a = (); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:26:17 + | +LL | let a @ (Ok(a) | Err(a)) = Ok(()); + | ^ used in a pattern more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/pat-at-same-name-both.rs:26:26 + | +LL | let a @ (Ok(a) | Err(a)) = Ok(()); + | ^ used in a pattern more than once + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0415, E0416. +For more information about an error, try `rustc --explain E0415`. diff --git a/tests/ui/pattern/bindings-after-at/slice-patterns.rs b/tests/ui/pattern/bindings-after-at/slice-patterns.rs new file mode 100644 index 000000000..4f4c96e45 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/slice-patterns.rs @@ -0,0 +1,39 @@ +// Test bindings-after-at with slice-patterns + +// run-pass + + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(foo: &[i32]) -> MatchArm { + match foo { + [bar @ .., n] if n == &5 => { + for i in bar { + assert!(i < &5); + } + + MatchArm::Arm(0) + }, + bar @ [x0, .., xn] => { + assert_eq!(x0, &1); + assert_eq!(x0, &1); + assert_eq!(xn, &4); + assert_eq!(bar, &[1, 2, 3, 4]); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![1, 2, 3, 4, 5]; + + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..4]), MatchArm::Arm(1)); + assert_eq!(test(&foo[0..1]), MatchArm::Wild); +} diff --git a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs new file mode 100644 index 000000000..50ac0ef27 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs @@ -0,0 +1,16 @@ +// Here we check that `_ @ sub` is syntactically invalid +// and comes with a nice actionable suggestion. + +fn main() {} + +#[cfg(FALSE)] +fn wild_before_at_is_bad_syntax() { + let _ @ a = 0; + //~^ ERROR pattern on wrong side of `@` + let _ @ ref a = 0; + //~^ ERROR pattern on wrong side of `@` + let _ @ ref mut a = 0; + //~^ ERROR pattern on wrong side of `@` + let _ @ (a, .., b) = (0, 1, 2, 3); + //~^ ERROR left-hand side of `@` must be a binding +} diff --git a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr new file mode 100644 index 000000000..2f4541584 --- /dev/null +++ b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.stderr @@ -0,0 +1,43 @@ +error: pattern on wrong side of `@` + --> $DIR/wild-before-at-syntactically-rejected.rs:8:9 + | +LL | let _ @ a = 0; + | -^^^- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `a @ _` + +error: pattern on wrong side of `@` + --> $DIR/wild-before-at-syntactically-rejected.rs:10:9 + | +LL | let _ @ ref a = 0; + | -^^^----- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `ref a @ _` + +error: pattern on wrong side of `@` + --> $DIR/wild-before-at-syntactically-rejected.rs:12:9 + | +LL | let _ @ ref mut a = 0; + | -^^^--------- + | | | + | | binding on the right, should be on the left + | pattern on the left, should be on the right + | help: switch the order: `ref mut a @ _` + +error: left-hand side of `@` must be a binding + --> $DIR/wild-before-at-syntactically-rejected.rs:14:9 + | +LL | let _ @ (a, .., b) = (0, 1, 2, 3); + | -^^^---------- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/for-loop-bad-item.rs b/tests/ui/pattern/for-loop-bad-item.rs new file mode 100644 index 000000000..9a56a399b --- /dev/null +++ b/tests/ui/pattern/for-loop-bad-item.rs @@ -0,0 +1,20 @@ +struct Qux(i32); + +fn bad() { + let mut map = std::collections::HashMap::new(); + map.insert(('a', 'b'), ('c', 'd')); + + for ((_, _), (&mut c, _)) in &mut map { + //~^ ERROR mismatched types + if c == 'e' {} + } +} + +fn bad2() { + for Some(Qux(_)) | None in [Some(""), None] { + //~^ ERROR mismatched types + todo!(); + } +} + +fn main() {} diff --git a/tests/ui/pattern/for-loop-bad-item.stderr b/tests/ui/pattern/for-loop-bad-item.stderr new file mode 100644 index 000000000..f064a25a9 --- /dev/null +++ b/tests/ui/pattern/for-loop-bad-item.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/for-loop-bad-item.rs:7:19 + | +LL | for ((_, _), (&mut c, _)) in &mut map { + | ^^^^^^ -------- this is an iterator with items of type `(&(char, char), &mut (char, char))` + | | + | expected `char`, found `&mut _` + | + = note: expected type `char` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut c` + --> $DIR/for-loop-bad-item.rs:7:19 + | +LL | for ((_, _), (&mut c, _)) in &mut map { + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - for ((_, _), (&mut c, _)) in &mut map { +LL + for ((_, _), (c, _)) in &mut map { + | + +error[E0308]: mismatched types + --> $DIR/for-loop-bad-item.rs:14:14 + | +LL | for Some(Qux(_)) | None in [Some(""), None] { + | ^^^^^^ ---------------- this is an iterator with items of type `Option<&str>` + | | + | expected `str`, found struct `Qux` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/ignore-all-the-things.rs b/tests/ui/pattern/ignore-all-the-things.rs new file mode 100644 index 000000000..5980e1a85 --- /dev/null +++ b/tests/ui/pattern/ignore-all-the-things.rs @@ -0,0 +1,44 @@ +// run-pass + +#![allow(non_shorthand_field_patterns)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo(isize, isize, isize, isize); +struct Bar{a: isize, b: isize, c: isize, d: isize} + +pub fn main() { + let Foo(..) = Foo(5, 5, 5, 5); + let Foo(..) = Foo(5, 5, 5, 5); + let Bar{..} = Bar{a: 5, b: 5, c: 5, d: 5}; + let (..) = (5, 5, 5, 5); + let Foo(a, b, ..) = Foo(5, 5, 5, 5); + let Foo(.., d) = Foo(5, 5, 5, 5); + let (a, b, ..) = (5, 5, 5, 5); + let (.., c, d) = (5, 5, 5, 5); + let Bar{b: b, ..} = Bar{a: 5, b: 5, c: 5, d: 5}; + match [5, 5, 5, 5] { + [..] => { } + } + match [5, 5, 5, 5] { + [a, ..] => { } + } + match [5, 5, 5, 5] { + [.., b] => { } + } + match [5, 5, 5, 5] { + [a, .., b] => { } + } + match [5, 5, 5] { + [..] => { } + } + match [5, 5, 5] { + [a, ..] => { } + } + match [5, 5, 5] { + [.., a] => { } + } + match [5, 5, 5] { + [a, .., b] => { } + } +} diff --git a/tests/ui/pattern/integer-range-binding.rs b/tests/ui/pattern/integer-range-binding.rs new file mode 100644 index 000000000..ff065882d --- /dev/null +++ b/tests/ui/pattern/integer-range-binding.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + let -2147483648..=2147483647 = 1; + let 0..=255 = 0u8; + let -128..=127 = 0i8; + let '\u{0000}'..='\u{10FFFF}' = 'v'; +} diff --git a/tests/ui/pattern/issue-10392.rs b/tests/ui/pattern/issue-10392.rs new file mode 100644 index 000000000..926fa9480 --- /dev/null +++ b/tests/ui/pattern/issue-10392.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_variables)] + +struct A { foo: isize } +struct B { a: isize, b: isize, c: isize } + +fn mka() -> A { panic!() } +fn mkb() -> B { panic!() } + +fn test() { + let A { foo, } = mka(); + let A { + foo, + } = mka(); + + let B { a, b, c, } = mkb(); + + match mka() { + A { foo: _foo, } => {} + } + + match Some(mka()) { + Some(A { foo: _foo, }) => {} + None => {} + } +} + +pub fn main() { + if false { test() } +} diff --git a/tests/ui/pattern/issue-106552.rs b/tests/ui/pattern/issue-106552.rs new file mode 100644 index 000000000..aa2c141e0 --- /dev/null +++ b/tests/ui/pattern/issue-106552.rs @@ -0,0 +1,7 @@ +fn main() { + let 5 = 6; + //~^ error refutable pattern in local binding [E0005] + + let x @ 5 = 6; + //~^ error refutable pattern in local binding [E0005] +} diff --git a/tests/ui/pattern/issue-106552.stderr b/tests/ui/pattern/issue-106552.stderr new file mode 100644 index 000000000..ed5d40c09 --- /dev/null +++ b/tests/ui/pattern/issue-106552.stderr @@ -0,0 +1,35 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/issue-106552.rs:2:9 + | +LL | let 5 = 6; + | ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let 5 = 6 { todo!() } + | ++ ~~~~~~~~~~~ +help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits + | +LL | let _5 = 6; + | + + +error[E0005]: refutable pattern in local binding + --> $DIR/issue-106552.rs:5:9 + | +LL | let x @ 5 = 6; + | ^^^^^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` +help: you might want to use `let else` to handle the variants that aren't matched + | +LL | let x @ 5 = 6 else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/issue-11577.rs b/tests/ui/pattern/issue-11577.rs new file mode 100644 index 000000000..70177c5ed --- /dev/null +++ b/tests/ui/pattern/issue-11577.rs @@ -0,0 +1,18 @@ +// run-pass +// Destructuring struct variants would ICE where regular structs wouldn't + +enum Foo { + VBar { num: isize } +} + +struct SBar { num: isize } + +pub fn main() { + let vbar = Foo::VBar { num: 1 }; + let Foo::VBar { num } = vbar; + assert_eq!(num, 1); + + let sbar = SBar { num: 2 }; + let SBar { num } = sbar; + assert_eq!(num, 2); +} diff --git a/tests/ui/pattern/issue-12582.rs b/tests/ui/pattern/issue-12582.rs new file mode 100644 index 000000000..f3366704e --- /dev/null +++ b/tests/ui/pattern/issue-12582.rs @@ -0,0 +1,21 @@ +// run-pass + +pub fn main() { + let x = 1; + let y = 2; + + assert_eq!(3, match (x, y) { + (1, 1) => 1, + (2, 2) => 2, + (1..=2, 2) => 3, + _ => 4, + }); + + // nested tuple + assert_eq!(3, match ((x, y),) { + ((1, 1),) => 1, + ((2, 2),) => 2, + ((1..=2, 2),) => 3, + _ => 4, + }); +} diff --git a/tests/ui/pattern/issue-14221.rs b/tests/ui/pattern/issue-14221.rs new file mode 100644 index 000000000..13427d2c9 --- /dev/null +++ b/tests/ui/pattern/issue-14221.rs @@ -0,0 +1,21 @@ +#![deny(unreachable_patterns)] +#![allow(unused_variables)] +#![allow(non_snake_case)] + +pub enum E { + A, + B, +} + +pub mod b { + pub fn key(e: ::E) -> &'static str { + match e { + A => "A", +//~^ ERROR pattern binding `A` is named the same as one of the variants of the type `E` + B => "B", //~ ERROR: unreachable pattern +//~^ ERROR pattern binding `B` is named the same as one of the variants of the type `E` + } + } +} + +fn main() {} diff --git a/tests/ui/pattern/issue-14221.stderr b/tests/ui/pattern/issue-14221.stderr new file mode 100644 index 000000000..7ea51b5f8 --- /dev/null +++ b/tests/ui/pattern/issue-14221.stderr @@ -0,0 +1,32 @@ +error[E0170]: pattern binding `A` is named the same as one of the variants of the type `E` + --> $DIR/issue-14221.rs:13:13 + | +LL | A => "A", + | ^ help: to match on the variant, qualify the path: `E::A` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `B` is named the same as one of the variants of the type `E` + --> $DIR/issue-14221.rs:15:13 + | +LL | B => "B", + | ^ help: to match on the variant, qualify the path: `E::B` + +error: unreachable pattern + --> $DIR/issue-14221.rs:15:13 + | +LL | A => "A", + | - matches any value +LL | +LL | B => "B", + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/issue-14221.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/pattern/issue-15080.rs b/tests/ui/pattern/issue-15080.rs new file mode 100644 index 000000000..4dd6981d4 --- /dev/null +++ b/tests/ui/pattern/issue-15080.rs @@ -0,0 +1,22 @@ +// run-pass + +fn main() { + let mut x: &[_] = &[1, 2, 3, 4]; + + let mut result = vec![]; + loop { + x = match *x { + [1, n, 3, ref rest @ ..] => { + result.push(n); + rest + } + [n, ref rest @ ..] => { + result.push(n); + rest + } + [] => + break + } + } + assert_eq!(result, [2, 4]); +} diff --git a/tests/ui/pattern/issue-17718-patterns.rs b/tests/ui/pattern/issue-17718-patterns.rs new file mode 100644 index 000000000..2ca0f67f8 --- /dev/null +++ b/tests/ui/pattern/issue-17718-patterns.rs @@ -0,0 +1,12 @@ +static A1: usize = 1; +static mut A2: usize = 1; +const A3: usize = 1; + +fn main() { + match 1 { + A1 => {} //~ ERROR: match bindings cannot shadow statics + A2 => {} //~ ERROR: match bindings cannot shadow statics + A3 => {} + _ => {} + } +} diff --git a/tests/ui/pattern/issue-17718-patterns.stderr b/tests/ui/pattern/issue-17718-patterns.stderr new file mode 100644 index 000000000..109091c2a --- /dev/null +++ b/tests/ui/pattern/issue-17718-patterns.stderr @@ -0,0 +1,21 @@ +error[E0530]: match bindings cannot shadow statics + --> $DIR/issue-17718-patterns.rs:7:9 + | +LL | static A1: usize = 1; + | --------------------- the static `A1` is defined here +... +LL | A1 => {} + | ^^ cannot be named the same as a static + +error[E0530]: match bindings cannot shadow statics + --> $DIR/issue-17718-patterns.rs:8:9 + | +LL | static mut A2: usize = 1; + | ------------------------- the static `A2` is defined here +... +LL | A2 => {} + | ^^ cannot be named the same as a static + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs new file mode 100644 index 000000000..c26e457f9 --- /dev/null +++ b/tests/ui/pattern/issue-22546.rs @@ -0,0 +1,52 @@ +// run-pass +#![allow(unused_variables)] +// Parsing patterns with paths with type parameters (issue #22544) + +use std::default::Default; + +#[derive(Default)] +pub struct Foo(T, T); + +impl Foo { + fn foo(&self) { + match *self { + Foo::(ref x, ref y) => println!("Goodbye, World! {} {}", x, y) + } + } +} + +trait Tr { + type U; +} + +impl Tr for Foo { + type U = T; +} + +struct Wrapper { + value: T +} + +fn main() { + let Foo::(a, b) = Default::default(); + + let f = Foo(2,3); + f.foo(); + + let w = Wrapper { value: Foo(10u8, 11u8) }; + match w { + Wrapper::> { value: Foo(10, 11) } => {}, + ::Wrapper::< as Tr>::U> { value: Foo::(11, 16) } => { panic!() }, + _ => { panic!() } + } + + if let None:: = Some(8) { + panic!(); + } + if let None:: { .. } = Some(8) { + panic!(); + } + if let Option::None:: { .. } = Some(8) { + panic!(); + } +} diff --git a/tests/ui/pattern/issue-27320.rs b/tests/ui/pattern/issue-27320.rs new file mode 100644 index 000000000..d1aa56b91 --- /dev/null +++ b/tests/ui/pattern/issue-27320.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_variables)] +#![allow(dead_code)] + +macro_rules! piece( + ($piece:pat) => ($piece); +); + +enum Piece {A, B} + +fn main() { + match Piece::A { + piece!(pt@ Piece::A) | piece!(pt@ Piece::B) => {} + } +} diff --git a/tests/ui/pattern/issue-52240.rs b/tests/ui/pattern/issue-52240.rs new file mode 100644 index 000000000..5def55778 --- /dev/null +++ b/tests/ui/pattern/issue-52240.rs @@ -0,0 +1,16 @@ +// issue-52240: Can turn immutable into mut with `ref mut` + +enum Foo { + Bar(i32), +} + +fn main() { + let arr = vec!(Foo::Bar(0)); + if let (Some(Foo::Bar(ref mut val)), _) = (&arr.get(0), 0) { + //~^ ERROR cannot borrow data in a `&` reference as mutable + *val = 9001; + } + match arr[0] { + Foo::Bar(ref s) => println!("{}", s) + } +} diff --git a/tests/ui/pattern/issue-52240.stderr b/tests/ui/pattern/issue-52240.stderr new file mode 100644 index 000000000..69b663b17 --- /dev/null +++ b/tests/ui/pattern/issue-52240.stderr @@ -0,0 +1,9 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-52240.rs:9:27 + | +LL | if let (Some(Foo::Bar(ref mut val)), _) = (&arr.get(0), 0) { + | ^^^^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/issue-6449.rs b/tests/ui/pattern/issue-6449.rs new file mode 100644 index 000000000..bfd4c1232 --- /dev/null +++ b/tests/ui/pattern/issue-6449.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code)] + +enum Foo { + Bar(isize), + Baz, +} + +enum Other { + Other1(Foo), + Other2(Foo, Foo), +} + +fn main() { + match Foo::Baz { + ::Foo::Bar(3) => panic!(), + ::Foo::Bar(_) if false => panic!(), + ::Foo::Bar(..) if false => panic!(), + ::Foo::Bar(_n) => panic!(), + ::Foo::Baz => {} + } + match Foo::Bar(3) { + ::Foo::Bar(3) => {} + ::Foo::Bar(_) if false => panic!(), + ::Foo::Bar(..) if false => panic!(), + ::Foo::Bar(_n) => panic!(), + ::Foo::Baz => panic!(), + } + match Foo::Bar(4) { + ::Foo::Bar(3) => panic!(), + ::Foo::Bar(_) if false => panic!(), + ::Foo::Bar(..) if false => panic!(), + ::Foo::Bar(n) => assert_eq!(n, 4), + ::Foo::Baz => panic!(), + } + + match Other::Other1(Foo::Baz) { + ::Other::Other1(::Foo::Baz) => {} + ::Other::Other1(::Foo::Bar(_)) => {} + ::Other::Other2(::Foo::Baz, ::Foo::Bar(_)) => {} + ::Other::Other2(::Foo::Bar(..), ::Foo::Baz) => {} + ::Other::Other2(..) => {} + } +} diff --git a/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.rs b/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.rs new file mode 100644 index 000000000..48a8e0482 --- /dev/null +++ b/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.rs @@ -0,0 +1,14 @@ +// Regression test for #66270, fixed by #66246 + +struct Bug { + incorrect_field: 0, + //~^ ERROR expected type +} + +struct Empty {} + +fn main() { + let Bug { + any_field: Empty {}, + } = Bug {}; +} diff --git a/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr new file mode 100644 index 000000000..f40642f30 --- /dev/null +++ b/tests/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr @@ -0,0 +1,10 @@ +error: expected type, found `0` + --> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22 + | +LL | struct Bug { + | --- while parsing this struct +LL | incorrect_field: 0, + | ^ expected type + +error: aborting due to previous error + diff --git a/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs b/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs new file mode 100644 index 000000000..ae28c1403 --- /dev/null +++ b/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs @@ -0,0 +1,21 @@ +// Regression test for #67037. +// +// In type checking patterns, E0023 occurs when the tuple pattern and the expected +// tuple pattern have different number of fields. For example, as below, `P()`, +// the tuple struct pattern, has 0 fields, but requires 1 field. +// +// In emitting E0023, we try to see if this is a case of e.g., `Some(a, b, c)` but where +// the scrutinee was of type `Some((a, b, c))`, and suggest that parentheses be added. +// +// However, we did not account for the expected type being different than the tuple pattern type. +// This caused an issue when the tuple pattern type (`P`) was generic. +// Specifically, we tried deriving the 0th field's type using the `substs` of the expected type. +// When attempting to substitute `T`, there was no such substitution, so "out of range" occurred. + +struct U {} // 0 type parameters offered +struct P(T); // 1 type parameter wanted + +fn main() { + let P() = U {}; //~ ERROR mismatched types + //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 1 field +} diff --git a/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr new file mode 100644 index 000000000..75a231f6b --- /dev/null +++ b/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9 + | +LL | let P() = U {}; + | ^^^ ---- this expression has type `U` + | | + | expected struct `U`, found struct `P` + | + = note: expected struct `U` + found struct `P<_>` + +error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 1 field + --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9 + | +LL | struct P(T); // 1 type parameter wanted + | - tuple struct has 1 field +... +LL | let P() = U {}; + | ^^^ expected 1 field, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | let P(_) = U {}; + | + +help: use `..` to ignore all fields + | +LL | let P(..) = U {}; + | ++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0023, E0308. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs b/tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs new file mode 100644 index 000000000..05d097eaf --- /dev/null +++ b/tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs @@ -0,0 +1,40 @@ +// Test for issue #67776: binding named the same as enum variant +// should report an error even when matching against a reference type + +#![allow(unused_variables)] +#![allow(non_snake_case)] + +enum Foo { + Bar, + Baz, +} + + +fn fn1(e: Foo) { + match e { + Bar => {}, + //~^ ERROR named the same as one of the variants of the type `Foo` + Baz => {}, + //~^ ERROR named the same as one of the variants of the type `Foo` + } +} + +fn fn2(e: &Foo) { + match e { + Bar => {}, + //~^ ERROR named the same as one of the variants of the type `Foo` + Baz => {}, + //~^ ERROR named the same as one of the variants of the type `Foo` + } +} + +fn fn3(e: &mut &&mut Foo) { + match e { + Bar => {}, + //~^ ERROR named the same as one of the variants of the type `Foo` + Baz => {}, + //~^ ERROR named the same as one of the variants of the type `Foo` + } +} + +fn main() {} diff --git a/tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr b/tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr new file mode 100644 index 000000000..da580c7ac --- /dev/null +++ b/tests/ui/pattern/issue-67776-match-same-name-enum-variant-refs.stderr @@ -0,0 +1,41 @@ +error[E0170]: pattern binding `Bar` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:15:9 + | +LL | Bar => {}, + | ^^^ help: to match on the variant, qualify the path: `Foo::Bar` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:17:9 + | +LL | Baz => {}, + | ^^^ help: to match on the variant, qualify the path: `Foo::Baz` + +error[E0170]: pattern binding `Bar` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:24:9 + | +LL | Bar => {}, + | ^^^ help: to match on the variant, qualify the path: `Foo::Bar` + +error[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:26:9 + | +LL | Baz => {}, + | ^^^ help: to match on the variant, qualify the path: `Foo::Baz` + +error[E0170]: pattern binding `Bar` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:33:9 + | +LL | Bar => {}, + | ^^^ help: to match on the variant, qualify the path: `Foo::Bar` + +error[E0170]: pattern binding `Baz` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-67776-match-same-name-enum-variant-refs.rs:35:9 + | +LL | Baz => {}, + | ^^^ help: to match on the variant, qualify the path: `Foo::Baz` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs new file mode 100644 index 000000000..95ead6b5d --- /dev/null +++ b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.rs @@ -0,0 +1,26 @@ +pub enum EFoo { + A, +} + +pub trait Foo { + const X: EFoo; +} + +struct Abc; + +impl Foo for Abc { + const X: EFoo = EFoo::A; +} + +struct Def; +impl Foo for Def { + const X: EFoo = EFoo::A; +} + +pub fn test(arg: EFoo, A::X: EFoo) { + //~^ ERROR associated consts cannot be referenced in patterns + let A::X = arg; + //~^ ERROR associated consts cannot be referenced in patterns +} + +fn main() {} diff --git a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr new file mode 100644 index 000000000..54ecc2498 --- /dev/null +++ b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr @@ -0,0 +1,15 @@ +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40 + | +LL | pub fn test(arg: EFoo, A::X: EFoo) { + | ^^^^ + +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/issue-68393-let-pat-assoc-constant.rs:22:9 + | +LL | let A::X = arg; + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/pattern/issue-72565.rs b/tests/ui/pattern/issue-72565.rs new file mode 100644 index 000000000..1e262fd50 --- /dev/null +++ b/tests/ui/pattern/issue-72565.rs @@ -0,0 +1,8 @@ +const F: &'static dyn PartialEq = &7u32; + +fn main() { + let a: &dyn PartialEq = &7u32; + match a { + F => panic!(), //~ ERROR: `&dyn PartialEq` cannot be used in patterns + } +} diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr new file mode 100644 index 000000000..2f82616b2 --- /dev/null +++ b/tests/ui/pattern/issue-72565.stderr @@ -0,0 +1,8 @@ +error: `&dyn PartialEq` cannot be used in patterns + --> $DIR/issue-72565.rs:6:9 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/issue-72574-1.rs b/tests/ui/pattern/issue-72574-1.rs new file mode 100644 index 000000000..1b80a2179 --- /dev/null +++ b/tests/ui/pattern/issue-72574-1.rs @@ -0,0 +1,10 @@ +fn main() { + let x = (1, 2, 3); + match x { + (_a, _x @ ..) => {} + _ => {} + } +} +//~^^^^ ERROR `_x @` is not allowed in a tuple +//~| ERROR: `..` patterns are not allowed here +//~| ERROR: mismatched types diff --git a/tests/ui/pattern/issue-72574-1.stderr b/tests/ui/pattern/issue-72574-1.stderr new file mode 100644 index 000000000..653869a23 --- /dev/null +++ b/tests/ui/pattern/issue-72574-1.stderr @@ -0,0 +1,34 @@ +error: `_x @` is not allowed in a tuple + --> $DIR/issue-72574-1.rs:4:14 + | +LL | (_a, _x @ ..) => {} + | ^^^^^^^ this is only allowed in slice patterns + | + = help: remove this and bind each tuple field independently +help: if you don't need to use the contents of _x, discard the tuple's remaining fields + | +LL | (_a, ..) => {} + | ~~ + +error: `..` patterns are not allowed here + --> $DIR/issue-72574-1.rs:4:19 + | +LL | (_a, _x @ ..) => {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0308]: mismatched types + --> $DIR/issue-72574-1.rs:4:9 + | +LL | match x { + | - this expression has type `({integer}, {integer}, {integer})` +LL | (_a, _x @ ..) => {} + | ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements + | + = note: expected tuple `({integer}, {integer}, {integer})` + found tuple `(_, _)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/issue-72574-2.rs b/tests/ui/pattern/issue-72574-2.rs new file mode 100644 index 000000000..0ad2db848 --- /dev/null +++ b/tests/ui/pattern/issue-72574-2.rs @@ -0,0 +1,12 @@ +struct Binder(i32, i32, i32); + +fn main() { + let x = Binder(1, 2, 3); + match x { + Binder(_a, _x @ ..) => {} + _ => {} + } +} +//~^^^^ ERROR `_x @` is not allowed in a tuple struct +//~| ERROR: `..` patterns are not allowed here +//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields diff --git a/tests/ui/pattern/issue-72574-2.stderr b/tests/ui/pattern/issue-72574-2.stderr new file mode 100644 index 000000000..05650f05c --- /dev/null +++ b/tests/ui/pattern/issue-72574-2.stderr @@ -0,0 +1,37 @@ +error: `_x @` is not allowed in a tuple struct + --> $DIR/issue-72574-2.rs:6:20 + | +LL | Binder(_a, _x @ ..) => {} + | ^^^^^^^ this is only allowed in slice patterns + | + = help: remove this and bind each tuple field independently +help: if you don't need to use the contents of _x, discard the tuple's remaining fields + | +LL | Binder(_a, ..) => {} + | ~~ + +error: `..` patterns are not allowed here + --> $DIR/issue-72574-2.rs:6:25 + | +LL | Binder(_a, _x @ ..) => {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields + --> $DIR/issue-72574-2.rs:6:16 + | +LL | struct Binder(i32, i32, i32); + | --- --- --- tuple struct has 3 fields +... +LL | Binder(_a, _x @ ..) => {} + | ^^ ^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Binder(_a, _x @ .., _) => {} + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/issue-74539.rs b/tests/ui/pattern/issue-74539.rs new file mode 100644 index 000000000..0b25f87ec --- /dev/null +++ b/tests/ui/pattern/issue-74539.rs @@ -0,0 +1,15 @@ +enum E { + A(u8, u8), +} + +fn main() { + let e = E::A(2, 3); + match e { + E::A(x @ ..) => { + //~^ ERROR: `x @` is not allowed in a tuple struct + //~| ERROR: `..` patterns are not allowed here + //~| ERROR: this pattern has 1 field, but the corresponding tuple variant has 2 fields + x + } + }; +} diff --git a/tests/ui/pattern/issue-74539.stderr b/tests/ui/pattern/issue-74539.stderr new file mode 100644 index 000000000..7443946c0 --- /dev/null +++ b/tests/ui/pattern/issue-74539.stderr @@ -0,0 +1,37 @@ +error: `x @` is not allowed in a tuple struct + --> $DIR/issue-74539.rs:8:14 + | +LL | E::A(x @ ..) => { + | ^^^^^^ this is only allowed in slice patterns + | + = help: remove this and bind each tuple field independently +help: if you don't need to use the contents of x, discard the tuple's remaining fields + | +LL | E::A(..) => { + | ~~ + +error: `..` patterns are not allowed here + --> $DIR/issue-74539.rs:8:18 + | +LL | E::A(x @ ..) => { + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/issue-74539.rs:8:14 + | +LL | A(u8, u8), + | -- -- tuple variant has 2 fields +... +LL | E::A(x @ ..) => { + | ^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::A(x @ .., _) => { + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/issue-74702.rs b/tests/ui/pattern/issue-74702.rs new file mode 100644 index 000000000..0aeb3b217 --- /dev/null +++ b/tests/ui/pattern/issue-74702.rs @@ -0,0 +1,7 @@ +fn main() { + let (foo @ ..,) = (0, 0); + //~^ ERROR: `foo @` is not allowed in a tuple + //~| ERROR: `..` patterns are not allowed here + //~| ERROR: mismatched types + dbg!(foo); +} diff --git a/tests/ui/pattern/issue-74702.stderr b/tests/ui/pattern/issue-74702.stderr new file mode 100644 index 000000000..f2e2c8f02 --- /dev/null +++ b/tests/ui/pattern/issue-74702.stderr @@ -0,0 +1,34 @@ +error: `foo @` is not allowed in a tuple + --> $DIR/issue-74702.rs:2:10 + | +LL | let (foo @ ..,) = (0, 0); + | ^^^^^^^^ this is only allowed in slice patterns + | + = help: remove this and bind each tuple field independently +help: if you don't need to use the contents of foo, discard the tuple's remaining fields + | +LL | let (..,) = (0, 0); + | ~~ + +error: `..` patterns are not allowed here + --> $DIR/issue-74702.rs:2:16 + | +LL | let (foo @ ..,) = (0, 0); + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0308]: mismatched types + --> $DIR/issue-74702.rs:2:9 + | +LL | let (foo @ ..,) = (0, 0); + | ^^^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element + | + = note: expected tuple `({integer}, {integer})` + found tuple `(_,)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/issue-74954.rs b/tests/ui/pattern/issue-74954.rs new file mode 100644 index 000000000..269ec3c7a --- /dev/null +++ b/tests/ui/pattern/issue-74954.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() { + if let Some([b'@', filename @ ..]) = Some(b"@abc123") { + println!("filename {:?}", filename); + } +} diff --git a/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.rs b/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.rs new file mode 100644 index 000000000..a5e9b1db5 --- /dev/null +++ b/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.rs @@ -0,0 +1,9 @@ +// Regression test for correct pretty-printing of an AST representing `&(mut x)` in help +// suggestion diagnostic. + +fn main() { + let mut &x = &0; + //~^ ERROR `mut` must be attached to each individual binding + //~| HELP add `mut` to each binding + //~| SUGGESTION &(mut x) +} diff --git a/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr b/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr new file mode 100644 index 000000000..75b6c163b --- /dev/null +++ b/tests/ui/pattern/issue-80186-mut-binding-help-suggestion.stderr @@ -0,0 +1,10 @@ +error: `mut` must be attached to each individual binding + --> $DIR/issue-80186-mut-binding-help-suggestion.rs:5:9 + | +LL | let mut &x = &0; + | ^^^^^^ help: add `mut` to each binding: `&(mut x)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: aborting due to previous error + diff --git a/tests/ui/pattern/issue-8351-1.rs b/tests/ui/pattern/issue-8351-1.rs new file mode 100644 index 000000000..139f027cb --- /dev/null +++ b/tests/ui/pattern/issue-8351-1.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +enum E { + Foo{f: isize}, + Bar, +} + +pub fn main() { + let e = E::Foo{f: 0}; + match e { + E::Foo{f: 1} => panic!(), + E::Foo{..} => (), + _ => panic!(), + } +} diff --git a/tests/ui/pattern/issue-8351-2.rs b/tests/ui/pattern/issue-8351-2.rs new file mode 100644 index 000000000..bc66cbb77 --- /dev/null +++ b/tests/ui/pattern/issue-8351-2.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +enum E { + Foo{f: isize, b: bool}, + Bar, +} + +pub fn main() { + let e = E::Foo{f: 0, b: false}; + match e { + E::Foo{f: 1, b: true} => panic!(), + E::Foo{b: false, f: 0} => (), + _ => panic!(), + } +} diff --git a/tests/ui/pattern/issue-88074-pat-range-type-inference-err.rs b/tests/ui/pattern/issue-88074-pat-range-type-inference-err.rs new file mode 100644 index 000000000..16df272df --- /dev/null +++ b/tests/ui/pattern/issue-88074-pat-range-type-inference-err.rs @@ -0,0 +1,28 @@ +trait Zero { + const ZERO: Self; +} + +impl Zero for String { + const ZERO: Self = String::new(); +} + +fn foo() { + match String::new() { + Zero::ZERO ..= Zero::ZERO => {}, + //~^ ERROR only `char` and numeric types are allowed in range patterns + _ => {}, + } +} + +fn bar() { + match Zero::ZERO { + Zero::ZERO ..= Zero::ZERO => {}, + //~^ ERROR type annotations needed [E0282] + _ => {}, + } +} + +fn main() { + foo(); + bar(); +} diff --git a/tests/ui/pattern/issue-88074-pat-range-type-inference-err.stderr b/tests/ui/pattern/issue-88074-pat-range-type-inference-err.stderr new file mode 100644 index 000000000..8e528f8c1 --- /dev/null +++ b/tests/ui/pattern/issue-88074-pat-range-type-inference-err.stderr @@ -0,0 +1,19 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/issue-88074-pat-range-type-inference-err.rs:11:9 + | +LL | Zero::ZERO ..= Zero::ZERO => {}, + | ----------^^^^^---------- + | | | + | | this is of type `String` but it should be `char` or numeric + | this is of type `String` but it should be `char` or numeric + +error[E0282]: type annotations needed + --> $DIR/issue-88074-pat-range-type-inference-err.rs:19:9 + | +LL | Zero::ZERO ..= Zero::ZERO => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0029, E0282. +For more information about an error, try `rustc --explain E0029`. diff --git a/tests/ui/pattern/issue-88074-pat-range-type-inference.rs b/tests/ui/pattern/issue-88074-pat-range-type-inference.rs new file mode 100644 index 000000000..27db7d8c7 --- /dev/null +++ b/tests/ui/pattern/issue-88074-pat-range-type-inference.rs @@ -0,0 +1,16 @@ +// check-pass + +trait Zero { + const ZERO: Self; +} + +impl Zero for i32 { + const ZERO: Self = 0; +} + +fn main() { + match 1 { + Zero::ZERO ..= 1 => {}, + _ => {}, + } +} diff --git a/tests/ui/pattern/issue-92074-macro-ice.rs b/tests/ui/pattern/issue-92074-macro-ice.rs new file mode 100644 index 000000000..039d3b314 --- /dev/null +++ b/tests/ui/pattern/issue-92074-macro-ice.rs @@ -0,0 +1,36 @@ +pub enum En { + A(Vec) +} + +fn get_usize() -> usize { + 0 +} + +macro_rules! force_expr { + ($e:expr) => { $e } +} + +macro_rules! force_pat { + ($a:expr, $b:expr) => { $a..=$b } +} + +macro_rules! make_vec { + () => { force_expr!(Vec::new()) } //~ ERROR arbitrary expressions aren't allowed +} + +macro_rules! make_pat { + () => { force_pat!(get_usize(), get_usize()) } + //~^ ERROR arbitrary expressions aren't allowed + //~| ERROR arbitrary expressions aren't allowed +} + +#[allow(unreachable_code)] +fn f() -> Result<(), impl core::fmt::Debug> { + let x: En = loop {}; + + assert!(matches!(x, En::A(make_vec!()))); + assert!(matches!(5, make_pat!())); + Ok::<(), &'static str>(()) +} + +fn main() {} diff --git a/tests/ui/pattern/issue-92074-macro-ice.stderr b/tests/ui/pattern/issue-92074-macro-ice.stderr new file mode 100644 index 000000000..b340afff0 --- /dev/null +++ b/tests/ui/pattern/issue-92074-macro-ice.stderr @@ -0,0 +1,35 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/issue-92074-macro-ice.rs:18:25 + | +LL | () => { force_expr!(Vec::new()) } + | ^^^^^^^^^^ +... +LL | assert!(matches!(x, En::A(make_vec!()))); + | ----------- in this macro invocation + | + = note: this error originates in the macro `make_vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: arbitrary expressions aren't allowed in patterns + --> $DIR/issue-92074-macro-ice.rs:22:24 + | +LL | () => { force_pat!(get_usize(), get_usize()) } + | ^^^^^^^^^^^ +... +LL | assert!(matches!(5, make_pat!())); + | ----------- in this macro invocation + | + = note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: arbitrary expressions aren't allowed in patterns + --> $DIR/issue-92074-macro-ice.rs:22:37 + | +LL | () => { force_pat!(get_usize(), get_usize()) } + | ^^^^^^^^^^^ +... +LL | assert!(matches!(5, make_pat!())); + | ----------- in this macro invocation + | + = note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/issue-95878.rs b/tests/ui/pattern/issue-95878.rs new file mode 100644 index 000000000..f59814468 --- /dev/null +++ b/tests/ui/pattern/issue-95878.rs @@ -0,0 +1,12 @@ +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + fn spam(&mut self, baz: &mut Vec) { + match 15 { + ref Self => (), + //~^ ERROR expected identifier, found keyword `Self` + } + } +} + +fn main() {} diff --git a/tests/ui/pattern/issue-95878.stderr b/tests/ui/pattern/issue-95878.stderr new file mode 100644 index 000000000..e0eea06e0 --- /dev/null +++ b/tests/ui/pattern/issue-95878.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found keyword `Self` + --> $DIR/issue-95878.rs:6:17 + | +LL | ref Self => (), + | ^^^^ expected identifier, found keyword + +error: aborting due to previous error + diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs new file mode 100644 index 000000000..5445696fd --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs @@ -0,0 +1,29 @@ +// check-pass + +fn main() {} + +struct U; + +fn slice() { + let mut arr = [U, U, U, U, U, U, U, U]; + let [ref _x0, _x1, _, mut _x3, .., ref _x6, _x7] = arr; + _x3 = U; + let [ref mut _x0, _, ref _x2, _, _x4, ref mut _x5, _x6, _] = arr; + *_x5 = U; + let [_, _, _x2, _, _, _x5, _, _] = arr; + *_x0 = U; + let [ref _x0, ..] = arr; + let [_x0, ..] = arr; +} + +fn tuple() { + let mut tup = (U, U, U, U, U); + let (ref _x0, mut _x1, ref _x2, ..) = tup; + _x1 = U; + let (ref mut _x0, _, _, ref _x3, _x4) = tup; + let (_, _, _, _x3, _) = tup; + *_x0 = U; + drop(_x2); + drop(tup.2); + let (_x0, _, _, ..) = tup; +} diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs new file mode 100644 index 000000000..a6144c949 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs @@ -0,0 +1,48 @@ +fn main() {} + +struct U; + +fn slice() { + let mut arr = [U, U, U, U, U]; + let hold_all = &arr; + let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; //~ ERROR cannot move out of `arr[..]` + _x1 = U; //~ ERROR cannot assign twice to immutable variable `_x1` + drop(hold_all); + let [_x0, ..] = arr; //~ ERROR cannot move out of `arr[..]` + drop(_x0_hold); + let [_, _, ref mut _x2, _x3, mut _x4] = arr; + //~^ ERROR cannot borrow `arr[..]` as mutable + //~| ERROR cannot move out of `arr[..]` because it is borrowed + //~| ERROR cannot move out of `arr[..]` because it is borrowed + drop(xs_hold); +} + +fn tuple() { + let mut tup = (U, U, U, U); + let (ref _x0, _x1, ref _x2, ..) = tup; + _x1 = U; //~ ERROR cannot assign twice to immutable variable + let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also + let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also + *_x0 = U; //~ ERROR cannot assign to `*_x0`, which is behind a `&` reference + *_x2 = U; //~ ERROR cannot assign to `*_x2`, which is behind a `&` reference + drop(tup.1); //~ ERROR use of moved value: `tup.1` + let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1` + let (.., ref mut _x3) = tup; + let _x3_hold = &tup.3; //~ ERROR cannot borrow `tup.3` as immutable + let _x3_hold = &mut tup.3; //~ ERROR cannot borrow `tup.3` as mutable more + let (.., ref mut _x4_hold) = tup; //~ ERROR cannot borrow `tup.3` as mutable more + let (.., ref _x4_hold) = tup; //~ ERROR cannot borrow `tup.3` as immutable + drop(_x3); +} + +fn closure() { + let mut tup = (U, U, U); + let c1 = || { + let (ref _x0, _x1, _) = tup; + }; + let c2 = || { + //~^ ERROR use of moved value + let (ref mut _x0, _, _x2) = tup; + }; + drop(c1); +} diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr new file mode 100644 index 000000000..1b93267b3 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -0,0 +1,216 @@ +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:8:24 + | +LL | let hold_all = &arr; + | ---- borrow of `arr` occurs here +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ^^^ move out of `arr[..]` occurs here +LL | _x1 = U; +LL | drop(hold_all); + | -------- borrow later used here + +error[E0384]: cannot assign twice to immutable variable `_x1` + --> $DIR/borrowck-move-ref-pattern.rs:9:5 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | --- + | | + | first assignment to `_x1` + | help: consider making this binding mutable: `mut _x1` +LL | _x1 = U; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:11:10 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ------------ borrow of `arr[..]` occurs here +... +LL | let [_x0, ..] = arr; + | ^^^ move out of `arr[..]` occurs here +LL | drop(_x0_hold); + | -------- borrow later used here + +error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-move-ref-pattern.rs:13:16 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ----------- immutable borrow occurs here +... +LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; + | ^^^^^^^^^^^ mutable borrow occurs here +... +LL | drop(xs_hold); + | ------- immutable borrow later used here + +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:13:29 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ----------- borrow of `arr[..]` occurs here +... +LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; + | ^^^ move out of `arr[..]` occurs here +... +LL | drop(xs_hold); + | ------- borrow later used here + +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:13:34 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ----------- borrow of `arr[..]` occurs here +... +LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; + | ^^^^^^^ move out of `arr[..]` occurs here +... +LL | drop(xs_hold); + | ------- borrow later used here + +error[E0384]: cannot assign twice to immutable variable `_x1` + --> $DIR/borrowck-move-ref-pattern.rs:23:5 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | --- + | | + | first assignment to `_x1` + | help: consider making this binding mutable: `mut _x1` +LL | _x1 = U; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-move-ref-pattern.rs:24:20 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | ------- immutable borrow occurs here +LL | _x1 = U; +LL | let _x0_hold = &mut tup.0; + | ^^^^^^^^^^ mutable borrow occurs here +LL | let (ref mut _x0_hold, ..) = tup; +LL | *_x0 = U; + | -------- immutable borrow later used here + +error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-move-ref-pattern.rs:25:10 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | ------- immutable borrow occurs here +... +LL | let (ref mut _x0_hold, ..) = tup; + | ^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | *_x0 = U; + | -------- immutable borrow later used here + +error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference + --> $DIR/borrowck-move-ref-pattern.rs:26:5 + | +LL | *_x0 = U; + | ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let (ref mut _x0, _x1, ref _x2, ..) = tup; + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference + --> $DIR/borrowck-move-ref-pattern.rs:27:5 + | +LL | *_x2 = U; + | ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let (ref _x0, _x1, ref mut _x2, ..) = tup; + | ~~~~~~~~~~~ + +error[E0382]: use of moved value: `tup.1` + --> $DIR/borrowck-move-ref-pattern.rs:28:10 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | --- value moved here +... +LL | drop(tup.1); + | ^^^^^ value used here after move + | + = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let (ref _x0, ref _x1, ref _x2, ..) = tup; + | +++ + +error[E0382]: borrow of moved value: `tup.1` + --> $DIR/borrowck-move-ref-pattern.rs:29:20 + | +LL | drop(tup.1); + | ----- value moved here +LL | let _x1_hold = &tup.1; + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait + +error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-move-ref-pattern.rs:31:20 + | +LL | let (.., ref mut _x3) = tup; + | ----------- mutable borrow occurs here +LL | let _x3_hold = &tup.3; + | ^^^^^^ immutable borrow occurs here +... +LL | drop(_x3); + | --- mutable borrow later used here + +error[E0499]: cannot borrow `tup.3` as mutable more than once at a time + --> $DIR/borrowck-move-ref-pattern.rs:32:20 + | +LL | let (.., ref mut _x3) = tup; + | ----------- first mutable borrow occurs here +LL | let _x3_hold = &tup.3; +LL | let _x3_hold = &mut tup.3; + | ^^^^^^^^^^ second mutable borrow occurs here +... +LL | drop(_x3); + | --- first borrow later used here + +error[E0499]: cannot borrow `tup.3` as mutable more than once at a time + --> $DIR/borrowck-move-ref-pattern.rs:33:14 + | +LL | let (.., ref mut _x3) = tup; + | ----------- first mutable borrow occurs here +... +LL | let (.., ref mut _x4_hold) = tup; + | ^^^^^^^^^^^^^^^^ second mutable borrow occurs here +LL | let (.., ref _x4_hold) = tup; +LL | drop(_x3); + | --- first borrow later used here + +error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-move-ref-pattern.rs:34:14 + | +LL | let (.., ref mut _x3) = tup; + | ----------- mutable borrow occurs here +... +LL | let (.., ref _x4_hold) = tup; + | ^^^^^^^^^^^^ immutable borrow occurs here +LL | drop(_x3); + | --- mutable borrow later used here + +error[E0382]: use of moved value: `tup` + --> $DIR/borrowck-move-ref-pattern.rs:43:14 + | +LL | let mut tup = (U, U, U); + | ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait +LL | let c1 = || { + | -- value moved into closure here +LL | let (ref _x0, _x1, _) = tup; + | --- variable moved due to use in closure +LL | }; +LL | let c2 = || { + | ^^ value used here after move +LL | +LL | let (ref mut _x0, _, _x2) = tup; + | --- use occurs due to use in closure + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0382, E0384, E0499, E0502, E0505, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs b/tests/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs new file mode 100644 index 000000000..ff7b625a6 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs @@ -0,0 +1,12 @@ +// When conflicts between by-move bindings in `by_move_1 @ has_by_move` patterns +// happen and that code is unreachable according to borrowck, we accept this code. +// In particular, we want to ensure here that an ICE does not happen, which it did originally. + +// check-pass + +fn main() { + return; + + struct S; + let a @ (b, c) = (S, S); +} diff --git a/tests/ui/pattern/move-ref-patterns/issue-53840.rs b/tests/ui/pattern/move-ref-patterns/issue-53840.rs new file mode 100644 index 000000000..80effc497 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/issue-53840.rs @@ -0,0 +1,20 @@ +// check-pass + +enum E { + Foo(String, String, String), +} + +struct Bar { + a: String, + b: String, +} + +fn main() { + let bar = Bar { a: "1".to_string(), b: "2".to_string() }; + match E::Foo("".into(), "".into(), "".into()) { + E::Foo(a, b, ref c) => {} + } + match bar { + Bar { a, ref b } => {} + } +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs new file mode 100644 index 000000000..ebb1683af --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs @@ -0,0 +1,120 @@ +fn main() { + struct S; // Not `Copy`. + + let mut tup0 = (S, S); + let mut tup1 = (S, S, S); + let tup2 = (S, S); + let tup3 = (S, S, S); + let tup4 = (S, S); + let mut arr0 = [S, S, S]; + let mut arr1 = [S, S, S, S, S]; + let arr2 = [S, S, S]; + let arr3 = [S, S, S, S, S]; + + // The `mov` bindings require that we capture the scrutinees by-move. + let mut closure = || { + // Tuples... + let (ref mut borrow, mov) = tup0; + let (mov, _, ref mut borrow) = tup1; + let (ref borrow, mov) = tup2; + let (mov, _, ref borrow) = tup3; + let (ref borrow, mov) = tup4; + // Arrays... + let [mov @ .., ref borrow] = arr0; + let [_, ref mut borrow @ .., _, mov] = arr1; + let [mov @ .., ref borrow] = arr2; + let [_, ref borrow @ .., _, mov] = arr3; + }; + + // Now we try to borrow and move the captures, which should result in errors... + // ...for tuples: + drop(&tup0); //~ ERROR borrow of moved value: `tup0` + drop(&tup1); //~ ERROR borrow of moved value: `tup1` + drop(&tup2); //~ ERROR borrow of moved value: `tup2` + drop(&tup3); //~ ERROR borrow of moved value: `tup3` + // Ostensibly this should compile. + // However, because closures don't capture individual fields, which is changed in RFC 2229, + // this won't compile because the entire product is moved into the closure. + // The same applies to the array patterns below. + drop(&tup4.0); //~ ERROR borrow of moved value: `tup4` + // ...for arrays: + drop(&arr0); //~ ERROR borrow of moved value: `arr0` + let [_, mov1, mov2, mov3, _] = &arr1; //~ ERROR borrow of moved value: `arr1` + drop(&arr2); //~ ERROR borrow of moved value: `arr2` + let [_, mov1, mov2, mov3, _] = &arr3; //~ ERROR borrow of moved value: `arr3` + + // Let's redo ^--- with a `match` + sum type: + macro_rules! m { + ($p:pat = $s:expr) => { + match $s { + Some($p) => {} + _ => {} + } + }; + } + let mut tup0: Option<(S, S)> = None; + let mut tup1: Option<(S, S, S)> = None; + let tup2: Option<(S, S)> = None; + let tup3: Option<(S, S, S)> = None; + let tup4: Option<(S, S)> = None; + let mut arr0: Option<[S; 3]> = None; + let mut arr1: Option<[S; 5]> = None; + let arr2: Option<[S; 3]> = None; + let arr3: Option<[S; 5]> = None; + let mut closure = || { + m!((ref mut borrow, mov) = tup0); + m!((mov, _, ref mut borrow) = tup1); + m!((ref borrow, mov) = tup2); + m!((mov, _, ref borrow) = tup3); + m!((ref borrow, mov) = tup4); + m!([mov @ .., ref borrow] = arr0); + m!([_, ref mut borrow @ .., _, mov] = arr1); + m!([mov @ .., ref borrow] = arr2); + m!([_, ref borrow @ .., _, mov] = arr3); + }; + drop(&tup0); //~ ERROR borrow of moved value: `tup0` + drop(&tup1); //~ ERROR borrow of moved value: `tup1` + drop(&tup2); //~ ERROR borrow of moved value: `tup2` + drop(&tup3); //~ ERROR borrow of moved value: `tup3` + m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` + drop(&arr0); //~ ERROR borrow of moved value: `arr0` + m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` + drop(&arr2); //~ ERROR borrow of moved value: `arr2` + m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` + + // Let's redo ^--- with `if let` (which may diverge from `match` in the future): + macro_rules! m { + ($p:pat = $s:expr) => { + if let Some($p) = $s {} + }; + } + let mut tup0: Option<(S, S)> = None; + let mut tup1: Option<(S, S, S)> = None; + let tup2: Option<(S, S)> = None; + let tup3: Option<(S, S, S)> = None; + let tup4: Option<(S, S)> = None; + let mut arr0: Option<[S; 3]> = None; + let mut arr1: Option<[S; 5]> = None; + let arr2: Option<[S; 3]> = None; + let arr3: Option<[S; 5]> = None; + let mut closure = || { + m!((ref mut borrow, mov) = tup0); + m!((mov, _, ref mut borrow) = tup1); + m!((ref borrow, mov) = tup2); + m!((mov, _, ref borrow) = tup3); + m!((ref borrow, mov) = tup4); + m!([mov @ .., ref borrow] = arr0); + m!([_, ref mut borrow @ .., _, mov] = arr1); + m!([mov @ .., ref borrow] = arr2); + m!([_, ref borrow @ .., _, mov] = arr3); + }; + drop(&tup0); //~ ERROR borrow of moved value: `tup0` + drop(&tup1); //~ ERROR borrow of moved value: `tup1` + drop(&tup2); //~ ERROR borrow of moved value: `tup2` + drop(&tup3); //~ ERROR borrow of moved value: `tup3` + m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` + drop(&arr0); //~ ERROR borrow of moved value: `arr0` + m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` + drop(&arr2); //~ ERROR borrow of moved value: `arr2` + m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr new file mode 100644 index 000000000..f19fed089 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr @@ -0,0 +1,404 @@ +error[E0382]: borrow of moved value: `tup0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:31:10 + | +LL | let mut tup0 = (S, S); + | -------- move occurs because `tup0` has type `(S, S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | // Tuples... +LL | let (ref mut borrow, mov) = tup0; + | ---- variable moved due to use in closure +... +LL | drop(&tup0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:32:10 + | +LL | let mut tup1 = (S, S, S); + | -------- move occurs because `tup1` has type `(S, S, S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (mov, _, ref mut borrow) = tup1; + | ---- variable moved due to use in closure +... +LL | drop(&tup1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10 + | +LL | let tup2 = (S, S); + | ---- move occurs because `tup2` has type `(S, S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (ref borrow, mov) = tup2; + | ---- variable moved due to use in closure +... +LL | drop(&tup2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10 + | +LL | let tup3 = (S, S, S); + | ---- move occurs because `tup3` has type `(S, S, S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (mov, _, ref borrow) = tup3; + | ---- variable moved due to use in closure +... +LL | drop(&tup3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup4` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:39:10 + | +LL | let tup4 = (S, S); + | ---- move occurs because `tup4` has type `(S, S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (ref borrow, mov) = tup4; + | ---- variable moved due to use in closure +... +LL | drop(&tup4.0); + | ^^^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10 + | +LL | let mut arr0 = [S, S, S]; + | -------- move occurs because `arr0` has type `[S; 3]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [mov @ .., ref borrow] = arr0; + | ---- variable moved due to use in closure +... +LL | drop(&arr0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:42:36 + | +LL | let mut arr1 = [S, S, S, S, S]; + | -------- move occurs because `arr1` has type `[S; 5]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [_, ref mut borrow @ .., _, mov] = arr1; + | ---- variable moved due to use in closure +... +LL | let [_, mov1, mov2, mov3, _] = &arr1; + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10 + | +LL | let arr2 = [S, S, S]; + | ---- move occurs because `arr2` has type `[S; 3]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [mov @ .., ref borrow] = arr2; + | ---- variable moved due to use in closure +... +LL | drop(&arr2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36 + | +LL | let arr3 = [S, S, S, S, S]; + | ---- move occurs because `arr3` has type `[S; 5]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [_, ref borrow @ .., _, mov] = arr3; + | ---- variable moved due to use in closure +... +LL | let [_, mov1, mov2, mov3, _] = &arr3; + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:75:10 + | +LL | let mut tup0: Option<(S, S)> = None; + | -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); + | ---- variable moved due to use in closure +... +LL | drop(&tup0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:76:10 + | +LL | let mut tup1: Option<(S, S, S)> = None; + | -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); +LL | m!((mov, _, ref mut borrow) = tup1); + | ---- variable moved due to use in closure +... +LL | drop(&tup1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10 + | +LL | let tup2: Option<(S, S)> = None; + | ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup2); + | ---- variable moved due to use in closure +... +LL | drop(&tup2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10 + | +LL | let tup3: Option<(S, S, S)> = None; + | ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((mov, _, ref borrow) = tup3); + | ---- variable moved due to use in closure +... +LL | drop(&tup3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup4` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:79:21 + | +LL | let tup4: Option<(S, S)> = None; + | ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup4); + | ---- variable moved due to use in closure +... +LL | m!((ref x, _) = &tup4); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10 + | +LL | let mut arr0: Option<[S; 3]> = None; + | -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr0); + | ---- variable moved due to use in closure +... +LL | drop(&arr0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:81:35 + | +LL | let mut arr1: Option<[S; 5]> = None; + | -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref mut borrow @ .., _, mov] = arr1); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10 + | +LL | let arr2: Option<[S; 3]> = None; + | ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait +LL | let arr3: Option<[S; 5]> = None; +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr2); + | ---- variable moved due to use in closure +... +LL | drop(&arr2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35 + | +LL | let arr3: Option<[S; 5]> = None; + | ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref borrow @ .., _, mov] = arr3); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:111:10 + | +LL | let mut tup0: Option<(S, S)> = None; + | -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); + | ---- variable moved due to use in closure +... +LL | drop(&tup0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:112:10 + | +LL | let mut tup1: Option<(S, S, S)> = None; + | -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); +LL | m!((mov, _, ref mut borrow) = tup1); + | ---- variable moved due to use in closure +... +LL | drop(&tup1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10 + | +LL | let tup2: Option<(S, S)> = None; + | ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup2); + | ---- variable moved due to use in closure +... +LL | drop(&tup2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10 + | +LL | let tup3: Option<(S, S, S)> = None; + | ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((mov, _, ref borrow) = tup3); + | ---- variable moved due to use in closure +... +LL | drop(&tup3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup4` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:115:21 + | +LL | let tup4: Option<(S, S)> = None; + | ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup4); + | ---- variable moved due to use in closure +... +LL | m!((ref x, _) = &tup4); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10 + | +LL | let mut arr0: Option<[S; 3]> = None; + | -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr0); + | ---- variable moved due to use in closure +... +LL | drop(&arr0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:117:35 + | +LL | let mut arr1: Option<[S; 5]> = None; + | -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref mut borrow @ .., _, mov] = arr1); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10 + | +LL | let arr2: Option<[S; 3]> = None; + | ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait +LL | let arr3: Option<[S; 5]> = None; +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr2); + | ---- variable moved due to use in closure +... +LL | drop(&arr2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35 + | +LL | let arr3: Option<[S; 5]> = None; + | ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref borrow @ .., _, mov] = arr3); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr3); + | ^^^^^ value borrowed here after move + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs new file mode 100644 index 000000000..583f70f41 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs @@ -0,0 +1,28 @@ +// check-pass + +fn main() { + struct U; + fn accept_fn_once(_: impl FnOnce()) {} + fn accept_fn_mut(_: impl FnMut()) {} + fn accept_fn(_: impl Fn()) {} + + let mut tup = (U, U, U); + let (ref _x0, _x1, ref mut _x2) = tup; + let c1 = || { + drop::<&U>(_x0); + drop::(_x1); + drop::<&mut U>(_x2); + }; + accept_fn_once(c1); + + let c2 = || { + drop::<&U>(_x0); + drop::<&mut U>(_x2); + }; + accept_fn_mut(c2); + + let c3 = || { + drop::<&U>(_x0); + }; + accept_fn(c3); +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs new file mode 100644 index 000000000..cd619cc41 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs @@ -0,0 +1,32 @@ +fn main() { + struct U; + fn accept_fn_once(_: &impl FnOnce()) {} + fn accept_fn_mut(_: &impl FnMut()) {} + fn accept_fn(_: &impl Fn()) {} + + let mut tup = (U, U, U); + let (ref _x0, _x1, ref mut _x2) = tup; + let c1 = || { + //~^ ERROR expected a closure that implements the `FnMut` + //~| ERROR expected a closure that implements the `Fn` + drop::<&U>(_x0); + drop::(_x1); + drop::<&mut U>(_x2); + }; + accept_fn_once(&c1); + accept_fn_mut(&c1); + accept_fn(&c1); + + let c2 = || { + //~^ ERROR expected a closure that implements the `Fn` + drop::<&U>(_x0); + drop::<&mut U>(_x2); + }; + accept_fn_mut(&c2); + accept_fn(&c2); + + let c3 = || { + drop::<&U>(_x0); + }; + accept_fn(&c3); +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr new file mode 100644 index 000000000..eba65a618 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr @@ -0,0 +1,63 @@ +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/move-ref-patterns-closure-captures.rs:9:14 + | +LL | let c1 = || { + | ^^ this closure implements `FnOnce`, not `FnMut` +... +LL | drop::(_x1); + | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment +... +LL | accept_fn_mut(&c1); + | ------------- --- the requirement to implement `FnMut` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `accept_fn_mut` + --> $DIR/move-ref-patterns-closure-captures.rs:4:31 + | +LL | fn accept_fn_mut(_: &impl FnMut()) {} + | ^^^^^^^ required by this bound in `accept_fn_mut` + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/move-ref-patterns-closure-captures.rs:9:14 + | +LL | let c1 = || { + | ^^ this closure implements `FnOnce`, not `Fn` +... +LL | drop::(_x1); + | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment +... +LL | accept_fn(&c1); + | --------- --- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `accept_fn` + --> $DIR/move-ref-patterns-closure-captures.rs:5:27 + | +LL | fn accept_fn(_: &impl Fn()) {} + | ^^^^ required by this bound in `accept_fn` + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/move-ref-patterns-closure-captures.rs:20:14 + | +LL | let c2 = || { + | ^^ this closure implements `FnMut`, not `Fn` +... +LL | drop::<&mut U>(_x2); + | --- closure is `FnMut` because it mutates the variable `_x2` here +... +LL | accept_fn(&c2); + | --------- --- the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `accept_fn` + --> $DIR/move-ref-patterns-closure-captures.rs:5:27 + | +LL | fn accept_fn(_: &impl Fn()) {} + | ^^^^ required by this bound in `accept_fn` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed new file mode 100644 index 000000000..5f04fc83d --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(unused_variables)] +fn main() { + struct U; + + // A tuple is a "non-reference pattern". + // A `mut` binding pattern resets the binding mode to by-value. + + let mut p = (U, U); + let (a, ref mut b) = &mut p; + //~^ ERROR cannot move out of a mutable reference +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs new file mode 100644 index 000000000..5dc1ae2fe --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(unused_variables)] +fn main() { + struct U; + + // A tuple is a "non-reference pattern". + // A `mut` binding pattern resets the binding mode to by-value. + + let mut p = (U, U); + let (a, mut b) = &mut p; + //~^ ERROR cannot move out of a mutable reference +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr new file mode 100644 index 000000000..d3ab533e3 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a mutable reference + --> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22 + | +LL | let (a, mut b) = &mut p; + | ----- ^^^^^^ + | | + | data moved here + | move occurs because `b` has type `U`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (a, ref mut b) = &mut p; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs new file mode 100644 index 000000000..6c913c245 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs @@ -0,0 +1,10 @@ +fn main() { + struct U; + + // A tuple is a "non-reference pattern". + // A `mut` binding pattern resets the binding mode to by-value. + + let p = (U, U); + let (a, mut b) = &p; + //~^ ERROR cannot move out of a shared reference +} diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr new file mode 100644 index 000000000..65030b622 --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/move-ref-patterns-default-binding-modes.rs:8:22 + | +LL | let (a, mut b) = &p; + | ----- ^^ + | | + | data moved here + | move occurs because `b` has type `U`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (a, ref mut b) = &p; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs new file mode 100644 index 000000000..1d6d9acea --- /dev/null +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs @@ -0,0 +1,79 @@ +// run-pass + +// This test checks the dynamic semantics and drop order of pattern matching +// where a product pattern has both a by-move and by-ref binding. + +use std::cell::RefCell; +use std::rc::Rc; + +struct X { + x: Box, + d: DropOrderListPtr, +} + +type DropOrderListPtr = Rc>>; + +impl Drop for X { + fn drop(&mut self) { + self.d.borrow_mut().push(*self.x); + } +} + +enum DoubleOption { + Some2(T, U), + _None2, +} + +fn main() { + let d: DropOrderListPtr = <_>::default(); + { + let mk = |v| X { x: Box::new(v), d: d.clone() }; + let check = |a1: &X, a2, b1: &X, b2| { + assert_eq!(*a1.x, a2); + assert_eq!(*b1.x, b2); + }; + + let x = DoubleOption::Some2(mk(1), mk(2)); + match x { + DoubleOption::Some2(ref a, b) => check(a, 1, &b, 2), + DoubleOption::_None2 => panic!(), + } + let x = DoubleOption::Some2(mk(3), mk(4)); + match x { + DoubleOption::Some2(a, ref b) => check(&a, 3, b, 4), + DoubleOption::_None2 => panic!(), + } + match DoubleOption::Some2(mk(5), mk(6)) { + DoubleOption::Some2(ref a, b) => check(a, 5, &b, 6), + DoubleOption::_None2 => panic!(), + } + match DoubleOption::Some2(mk(7), mk(8)) { + DoubleOption::Some2(a, ref b) => check(&a, 7, b, 8), + DoubleOption::_None2 => panic!(), + } + { + let (a, ref b) = (mk(9), mk(10)); + let (ref c, d) = (mk(11), mk(12)); + check(&a, 9, b, 10); + check(c, 11, &d, 12); + } + fn fun([a, ref mut b, ref xs @ .., ref c, d]: [X; 6]) { + assert_eq!(*a.x, 13); + assert_eq!(*b.x, 14); + assert_eq!(&[*xs[0].x, *xs[1].x], &[15, 16]); + assert_eq!(*c.x, 17); + assert_eq!(*d.x, 18); + } + fun([mk(13), mk(14), mk(15), mk(16), mk(17), mk(18)]); + + let lam = |(a, ref b, c, ref mut d): (X, X, X, X)| { + assert_eq!(*a.x, 19); + assert_eq!(*b.x, 20); + assert_eq!(*c.x, 21); + assert_eq!(*d.x, 22); + }; + lam((mk(19), mk(20), mk(21), mk(22))); + } + let expected = [2, 3, 6, 5, 7, 8, 12, 11, 9, 10, 18, 13, 14, 15, 16, 17, 21, 19, 20, 22, 4, 1]; + assert_eq!(&*d.borrow(), &expected); +} diff --git a/tests/ui/pattern/non-constant-in-const-path.rs b/tests/ui/pattern/non-constant-in-const-path.rs new file mode 100644 index 000000000..3918485ba --- /dev/null +++ b/tests/ui/pattern/non-constant-in-const-path.rs @@ -0,0 +1,18 @@ +// Checks if we emit `PatternError`s correctly. +// This is also a regression test for #27895 and #68394. + +static FOO: u8 = 10; + +fn main() { + let x = 0; + let 0u8..=x = 0; + //~^ ERROR: runtime values cannot be referenced in patterns + let 0u8..=FOO = 0; + //~^ ERROR: statics cannot be referenced in patterns + match 1 { + 0 ..= x => {} + //~^ ERROR: runtime values cannot be referenced in patterns + 0 ..= FOO => {} + //~^ ERROR: statics cannot be referenced in patterns + }; +} diff --git a/tests/ui/pattern/non-constant-in-const-path.stderr b/tests/ui/pattern/non-constant-in-const-path.stderr new file mode 100644 index 000000000..53c3974f7 --- /dev/null +++ b/tests/ui/pattern/non-constant-in-const-path.stderr @@ -0,0 +1,28 @@ +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:8:15 + | +LL | let 0u8..=x = 0; + | ^ + +error[E0158]: statics cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:10:15 + | +LL | let 0u8..=FOO = 0; + | ^^^ + +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:13:15 + | +LL | 0 ..= x => {} + | ^ + +error[E0158]: statics cannot be referenced in patterns + --> $DIR/non-constant-in-const-path.rs:15:15 + | +LL | 0 ..= FOO => {} + | ^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0158. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs new file mode 100644 index 000000000..5c3315473 --- /dev/null +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -0,0 +1,14 @@ +// edition:2021 +#![allow(incomplete_features)] +#![allow(unreachable_code)] +#![feature(const_async_blocks)] +#![feature(inline_const_pat)] + +fn main() { + match loop {} { + const { || {} } => {}, //~ ERROR cannot be used in patterns + } + match loop {} { + const { async {} } => {}, //~ ERROR cannot be used in patterns + } +} diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr new file mode 100644 index 000000000..dea7c4695 --- /dev/null +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -0,0 +1,14 @@ +error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:9:9 + | +LL | const { || {} } => {}, + | ^^^^^^^^^^^^^^^ + +error: `[async block@$DIR/non-structural-match-types.rs:12:17: 12:25]` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:12:9 + | +LL | const { async {} } => {}, + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/pat-shadow-in-nested-binding.rs b/tests/ui/pattern/pat-shadow-in-nested-binding.rs new file mode 100644 index 000000000..7badbb6b9 --- /dev/null +++ b/tests/ui/pattern/pat-shadow-in-nested-binding.rs @@ -0,0 +1,6 @@ +#[allow(non_camel_case_types)] +struct foo(usize); + +fn main() { + let (foo, _) = (2, 3); //~ ERROR let bindings cannot shadow tuple structs +} diff --git a/tests/ui/pattern/pat-shadow-in-nested-binding.stderr b/tests/ui/pattern/pat-shadow-in-nested-binding.stderr new file mode 100644 index 000000000..0c5824be9 --- /dev/null +++ b/tests/ui/pattern/pat-shadow-in-nested-binding.stderr @@ -0,0 +1,12 @@ +error[E0530]: let bindings cannot shadow tuple structs + --> $DIR/pat-shadow-in-nested-binding.rs:5:10 + | +LL | struct foo(usize); + | ------------------ the tuple struct `foo` is defined here +... +LL | let (foo, _) = (2, 3); + | ^^^ cannot be named the same as a tuple struct + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/pattern/pat-struct-field-expr-has-type.rs b/tests/ui/pattern/pat-struct-field-expr-has-type.rs new file mode 100644 index 000000000..1d18214de --- /dev/null +++ b/tests/ui/pattern/pat-struct-field-expr-has-type.rs @@ -0,0 +1,9 @@ +struct S { + f: u8, +} + +fn main() { + match (S { f: 42 }) { + S { f: Ok(_) } => {} //~ ERROR mismatched types + } +} diff --git a/tests/ui/pattern/pat-struct-field-expr-has-type.stderr b/tests/ui/pattern/pat-struct-field-expr-has-type.stderr new file mode 100644 index 000000000..3a61d4293 --- /dev/null +++ b/tests/ui/pattern/pat-struct-field-expr-has-type.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/pat-struct-field-expr-has-type.rs:7:16 + | +LL | match (S { f: 42 }) { + | ------------- this expression has type `S` +LL | S { f: Ok(_) } => {} + | ^^^^^ expected `u8`, found enum `Result` + | + = note: expected type `u8` + found enum `Result<_, _>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/pat-tuple-bad-type.rs b/tests/ui/pattern/pat-tuple-bad-type.rs new file mode 100644 index 000000000..98481167a --- /dev/null +++ b/tests/ui/pattern/pat-tuple-bad-type.rs @@ -0,0 +1,15 @@ +fn main() { + let x; //~ ERROR type annotations needed + + match x { + (..) => {} + _ => {} + } + + match 0u8 { + (..) => {} //~ ERROR mismatched types + _ => {} + } + + x = 10; +} diff --git a/tests/ui/pattern/pat-tuple-bad-type.stderr b/tests/ui/pattern/pat-tuple-bad-type.stderr new file mode 100644 index 000000000..da369d333 --- /dev/null +++ b/tests/ui/pattern/pat-tuple-bad-type.stderr @@ -0,0 +1,26 @@ +error[E0282]: type annotations needed + --> $DIR/pat-tuple-bad-type.rs:2:9 + | +LL | let x; + | ^ +... +LL | (..) => {} + | ---- type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let x: /* Type */; + | ++++++++++++ + +error[E0308]: mismatched types + --> $DIR/pat-tuple-bad-type.rs:10:9 + | +LL | match 0u8 { + | --- this expression has type `u8` +LL | (..) => {} + | ^^^^ expected `u8`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/pattern/pat-tuple-field-count-cross.rs b/tests/ui/pattern/pat-tuple-field-count-cross.rs new file mode 100644 index 000000000..b63da4e15 --- /dev/null +++ b/tests/ui/pattern/pat-tuple-field-count-cross.rs @@ -0,0 +1,57 @@ +// aux-build:declarations-for-tuple-field-count-errors.rs + +extern crate declarations_for_tuple_field_count_errors; + +use declarations_for_tuple_field_count_errors::*; + +fn main() { + match Z0 { + Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` + Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` + } + match Z1() { + Z1 => {} //~ ERROR match bindings cannot shadow tuple structs + Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields + } + + match S(1, 2, 3) { + S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields + S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields + S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields + S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields + } + match M(1, 2, 3) { + M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields + M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields + M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields + M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields + } + + match E1::Z0 { + E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` + E1::Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` + } + match E1::Z1() { + E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` + E1::Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields + } + match E1::S(1, 2, 3) { + E1::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields + E1::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields + E1::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields + E1::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields + } + + match E2::S(1, 2, 3) { + E2::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields + E2::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields + E2::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields + E2::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields + } + match E2::M(1, 2, 3) { + E2::M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields + E2::M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields + E2::M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields + E2::M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields + } +} diff --git a/tests/ui/pattern/pat-tuple-field-count-cross.stderr b/tests/ui/pattern/pat-tuple-field-count-cross.stderr new file mode 100644 index 000000000..d92957461 --- /dev/null +++ b/tests/ui/pattern/pat-tuple-field-count-cross.stderr @@ -0,0 +1,531 @@ +error[E0530]: match bindings cannot shadow tuple structs + --> $DIR/pat-tuple-field-count-cross.rs:13:9 + | +LL | use declarations_for_tuple_field_count_errors::*; + | -------------------------------------------- the tuple struct `Z1` is imported here +... +LL | Z1 => {} + | ^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `Z1(..)` + +error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` + --> $DIR/pat-tuple-field-count-cross.rs:9:9 + | +LL | Z0() => {} + | ^^^^ + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1 + | +LL | pub struct Z0; + | ------------- `Z0` defined here +LL | pub struct Z1(); + | ------------- similarly named tuple struct `Z1` defined here + | +help: use this syntax instead + | +LL | Z0 => {} + | ~~ +help: a tuple struct with a similar name exists + | +LL | Z1() => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` + --> $DIR/pat-tuple-field-count-cross.rs:10:9 + | +LL | Z0(x) => {} + | ^^^^^ + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1 + | +LL | pub struct Z0; + | ------------- `Z0` defined here +LL | pub struct Z1(); + | ------------- similarly named tuple struct `Z1` defined here + | +help: use this syntax instead + | +LL | Z0 => {} + | ~~ +help: a tuple struct with a similar name exists + | +LL | Z1(x) => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0` + --> $DIR/pat-tuple-field-count-cross.rs:31:9 + | +LL | E1::Z0() => {} + | ^^^^^^^^ + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- similarly named tuple variant `Z1` defined here + | | + | `E1::Z0` defined here + | +help: use this syntax instead + | +LL | E1::Z0 => {} + | ~~~~~~ +help: a tuple variant with a similar name exists + | +LL | E1::Z1() => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0` + --> $DIR/pat-tuple-field-count-cross.rs:32:9 + | +LL | E1::Z0(x) => {} + | ^^^^^^^^^ + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- similarly named tuple variant `Z1` defined here + | | + | `E1::Z0` defined here + | +help: use this syntax instead + | +LL | E1::Z0 => {} + | ~~~~~~ +help: a tuple variant with a similar name exists + | +LL | E1::Z1(x) => {} + | ~~ + +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1` + --> $DIR/pat-tuple-field-count-cross.rs:35:9 + | +LL | E1::Z1 => {} + | ^^^^^^ + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- `E1::Z1` defined here + | | + | similarly named unit variant `Z0` defined here + | +help: use the tuple variant pattern syntax instead + | +LL | E1::Z1(/* fields */) => {} + | ~~~~~~~~~~~~~~~~~~~~ +help: a unit variant with a similar name exists + | +LL | E1::Z0 => {} + | ~~ + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 fields + --> $DIR/pat-tuple-field-count-cross.rs:14:12 + | +LL | Z1(x) => {} + | ^ expected 0 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:2:1 + | +LL | pub struct Z1(); + | ------------- tuple struct has 0 fields + +error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:18:9 + | +LL | S() => {} + | ^^^ expected 3 fields, found 0 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14 + | +LL | pub struct S(pub u8, pub u8, pub u8); + | ------ ------ ------ tuple struct has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _, _) => {} + | +++++++ +help: use `..` to ignore all fields + | +LL | S(..) => {} + | ++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:19:11 + | +LL | S(1) => {} + | ^ expected 3 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14 + | +LL | pub struct S(pub u8, pub u8, pub u8); + | ------ ------ ------ tuple struct has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | S(1, _, _) => {} + | ++++++ +help: use `..` to ignore the rest of the fields + | +LL | S(1, ..) => {} + | ++++ + +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:20:11 + | +LL | S(xyz, abc) => {} + | ^^^ ^^^ expected 3 fields, found 2 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14 + | +LL | pub struct S(pub u8, pub u8, pub u8); + | ------ ------ ------ tuple struct has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | S(xyz, abc, _) => {} + | +++ + +error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:21:11 + | +LL | S(1, 2, 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14 + | +LL | pub struct S(pub u8, pub u8, pub u8); + | ------ ------ ------ tuple struct has 3 fields + +error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:24:9 + | +LL | M() => {} + | ^^^ expected 3 fields, found 0 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:12 + | +LL | pub struct M( + | - tuple struct defined here +LL | pub u8, + | ------ +LL | pub u8, + | ------ +LL | pub u8, + | ------ tuple struct has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | M(_, _, _) => {} + | +++++++ +help: use `..` to ignore all fields + | +LL | M(..) => {} + | ++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:25:11 + | +LL | M(1) => {} + | ^ expected 3 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:12 + | +LL | pub struct M( + | - tuple struct defined here +LL | pub u8, + | ------ +LL | pub u8, + | ------ +LL | pub u8, + | ------ tuple struct has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | M(1, _, _) => {} + | ++++++ +help: use `..` to ignore the rest of the fields + | +LL | M(1, ..) => {} + | ++++ + +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:26:11 + | +LL | M(xyz, abc) => {} + | ^^^ ^^^ expected 3 fields, found 2 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:12 + | +LL | pub struct M( + | - tuple struct defined here +LL | pub u8, + | ------ +LL | pub u8, + | ------ +LL | pub u8, + | ------ tuple struct has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | M(xyz, abc, _) => {} + | +++ + +error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:27:11 + | +LL | M(1, 2, 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:12 + | +LL | pub struct M( + | - tuple struct defined here +LL | pub u8, + | ------ +LL | pub u8, + | ------ +LL | pub u8, + | ------ tuple struct has 3 fields + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 0 fields + --> $DIR/pat-tuple-field-count-cross.rs:36:16 + | +LL | E1::Z1(x) => {} + | ^ expected 0 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- tuple variant has 0 fields + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:39:9 + | +LL | E1::S() => {} + | ^^^^^^^ expected 3 fields, found 0 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E1::S(_, _, _) => {} + | +++++++ +help: use `..` to ignore all fields + | +LL | E1::S(..) => {} + | ++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:40:15 + | +LL | E1::S(1) => {} + | ^ expected 3 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E1::S(1, _, _) => {} + | ++++++ +help: use `..` to ignore the rest of the fields + | +LL | E1::S(1, ..) => {} + | ++++ + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:41:15 + | +LL | E1::S(xyz, abc) => {} + | ^^^ ^^^ expected 3 fields, found 2 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E1::S(xyz, abc, _) => {} + | +++ + +error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:42:15 + | +LL | E1::S(1, 2, 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27 + | +LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) } + | -- -- -- tuple variant has 3 fields + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:46:9 + | +LL | E2::S() => {} + | ^^^^^^^ expected 3 fields, found 0 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7 + | +LL | S(u8, u8, u8), + | -- -- -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E2::S(_, _, _) => {} + | +++++++ +help: use `..` to ignore all fields + | +LL | E2::S(..) => {} + | ++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:47:15 + | +LL | E2::S(1) => {} + | ^ expected 3 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7 + | +LL | S(u8, u8, u8), + | -- -- -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E2::S(1, _, _) => {} + | ++++++ +help: use `..` to ignore the rest of the fields + | +LL | E2::S(1, ..) => {} + | ++++ + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:48:15 + | +LL | E2::S(xyz, abc) => {} + | ^^^ ^^^ expected 3 fields, found 2 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7 + | +LL | S(u8, u8, u8), + | -- -- -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E2::S(xyz, abc, _) => {} + | +++ + +error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:49:15 + | +LL | E2::S(1, 2, 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7 + | +LL | S(u8, u8, u8), + | -- -- -- tuple variant has 3 fields + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:52:9 + | +LL | E2::M() => {} + | ^^^^^^^ expected 3 fields, found 0 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5 + | +LL | M( + | - tuple variant defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E2::M(_, _, _) => {} + | +++++++ +help: use `..` to ignore all fields + | +LL | E2::M(..) => {} + | ++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:53:15 + | +LL | E2::M(1) => {} + | ^ expected 3 fields, found 1 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5 + | +LL | M( + | - tuple variant defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E2::M(1, _, _) => {} + | ++++++ +help: use `..` to ignore the rest of the fields + | +LL | E2::M(1, ..) => {} + | ++++ + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:54:15 + | +LL | E2::M(xyz, abc) => {} + | ^^^ ^^^ expected 3 fields, found 2 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5 + | +LL | M( + | - tuple variant defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple variant has 3 fields + | +help: use `_` to explicitly ignore each field + | +LL | E2::M(xyz, abc, _) => {} + | +++ + +error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields + --> $DIR/pat-tuple-field-count-cross.rs:55:15 + | +LL | E2::M(1, 2, 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + | + ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5 + | +LL | M( + | - tuple variant defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple variant has 3 fields + +error: aborting due to 28 previous errors + +Some errors have detailed explanations: E0023, E0530, E0532. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/pat-tuple-overfield.rs b/tests/ui/pattern/pat-tuple-overfield.rs new file mode 100644 index 000000000..c863c6575 --- /dev/null +++ b/tests/ui/pattern/pat-tuple-overfield.rs @@ -0,0 +1,74 @@ +struct S(u8, u8, u8); +struct M( + u8, + u8, + u8, + u8, + u8, +); + +struct Z0; +struct Z1(); +enum E1 { + Z0, + Z1(), +} + +fn main() { + match (1, 2, 3) { + (1, 2, 3, 4) => {} //~ ERROR mismatched types + (1, 2, .., 3, 4) => {} //~ ERROR mismatched types + _ => {} + } + match S(1, 2, 3) { + S(1, 2, 3, 4) => {} + //~^ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields + S(1, 2, .., 3, 4) => {} + //~^ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields + _ => {} + } + match M(1, 2, 3, 4, 5) { + M(1, 2, 3, 4, 5, 6) => {} + //~^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields + M(1, + 2, + 3, + 4, + 5, + 6) => {} + //~^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields + M( + 1, + 2, + 3, + 4, + 5, + 6, + ) => {} + //~^^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields + } + match Z0 { + Z0 => {} + Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` + Z0(_) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` + Z0(_, _) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0` + } + match Z1() { + Z1 => {} //~ ERROR match bindings cannot shadow tuple structs + Z1() => {} + Z1(_) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields + Z1(_, _) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 0 fields + } + match E1::Z0 { + E1::Z0 => {} + E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` + E1::Z0(_) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` + E1::Z0(_, _) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0` + } + match E1::Z1() { + E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1` + E1::Z1() => {} + E1::Z1(_) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields + E1::Z1(_, _) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 0 fields + } +} diff --git a/tests/ui/pattern/pat-tuple-overfield.stderr b/tests/ui/pattern/pat-tuple-overfield.stderr new file mode 100644 index 000000000..54d89e031 --- /dev/null +++ b/tests/ui/pattern/pat-tuple-overfield.stderr @@ -0,0 +1,312 @@ +error[E0530]: match bindings cannot shadow tuple structs + --> $DIR/pat-tuple-overfield.rs:57:9 + | +LL | struct Z1(); + | ------------ the tuple struct `Z1` is defined here +... +LL | Z1 => {} + | ^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `Z1(..)` + +error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` + --> $DIR/pat-tuple-overfield.rs:52:9 + | +LL | struct Z0; + | ---------- `Z0` defined here +LL | struct Z1(); + | ------------ similarly named tuple struct `Z1` defined here +... +LL | Z0() => {} + | ^^^^ + | +help: use this syntax instead + | +LL | Z0 => {} + | ~~ +help: a tuple struct with a similar name exists + | +LL | Z1() => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` + --> $DIR/pat-tuple-overfield.rs:53:9 + | +LL | struct Z0; + | ---------- `Z0` defined here +LL | struct Z1(); + | ------------ similarly named tuple struct `Z1` defined here +... +LL | Z0(_) => {} + | ^^^^^ + | +help: use this syntax instead + | +LL | Z0 => {} + | ~~ +help: a tuple struct with a similar name exists + | +LL | Z1(_) => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0` + --> $DIR/pat-tuple-overfield.rs:54:9 + | +LL | struct Z0; + | ---------- `Z0` defined here +LL | struct Z1(); + | ------------ similarly named tuple struct `Z1` defined here +... +LL | Z0(_, _) => {} + | ^^^^^^^^ + | +help: use this syntax instead + | +LL | Z0 => {} + | ~~ +help: a tuple struct with a similar name exists + | +LL | Z1(_, _) => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0` + --> $DIR/pat-tuple-overfield.rs:64:9 + | +LL | Z0, + | -- `E1::Z0` defined here +LL | Z1(), + | ---- similarly named tuple variant `Z1` defined here +... +LL | E1::Z0() => {} + | ^^^^^^^^ + | +help: use this syntax instead + | +LL | E1::Z0 => {} + | ~~~~~~ +help: a tuple variant with a similar name exists + | +LL | E1::Z1() => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0` + --> $DIR/pat-tuple-overfield.rs:65:9 + | +LL | Z0, + | -- `E1::Z0` defined here +LL | Z1(), + | ---- similarly named tuple variant `Z1` defined here +... +LL | E1::Z0(_) => {} + | ^^^^^^^^^ + | +help: use this syntax instead + | +LL | E1::Z0 => {} + | ~~~~~~ +help: a tuple variant with a similar name exists + | +LL | E1::Z1(_) => {} + | ~~ + +error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0` + --> $DIR/pat-tuple-overfield.rs:66:9 + | +LL | Z0, + | -- `E1::Z0` defined here +LL | Z1(), + | ---- similarly named tuple variant `Z1` defined here +... +LL | E1::Z0(_, _) => {} + | ^^^^^^^^^^^^ + | +help: use this syntax instead + | +LL | E1::Z0 => {} + | ~~~~~~ +help: a tuple variant with a similar name exists + | +LL | E1::Z1(_, _) => {} + | ~~ + +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1` + --> $DIR/pat-tuple-overfield.rs:69:9 + | +LL | Z0, + | -- similarly named unit variant `Z0` defined here +LL | Z1(), + | ---- `E1::Z1` defined here +... +LL | E1::Z1 => {} + | ^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | E1::Z1() => {} + | ~~~~~~~~ +help: a unit variant with a similar name exists + | +LL | E1::Z0 => {} + | ~~ + +error[E0308]: mismatched types + --> $DIR/pat-tuple-overfield.rs:19:9 + | +LL | match (1, 2, 3) { + | --------- this expression has type `({integer}, {integer}, {integer})` +LL | (1, 2, 3, 4) => {} + | ^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements + | + = note: expected tuple `({integer}, {integer}, {integer})` + found tuple `(_, _, _, _)` + +error[E0308]: mismatched types + --> $DIR/pat-tuple-overfield.rs:20:9 + | +LL | match (1, 2, 3) { + | --------- this expression has type `({integer}, {integer}, {integer})` +LL | (1, 2, 3, 4) => {} +LL | (1, 2, .., 3, 4) => {} + | ^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements + | + = note: expected tuple `({integer}, {integer}, {integer})` + found tuple `(_, _, _, _)` + +error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-overfield.rs:24:11 + | +LL | struct S(u8, u8, u8); + | -- -- -- tuple struct has 3 fields +... +LL | S(1, 2, 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + +error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields + --> $DIR/pat-tuple-overfield.rs:26:11 + | +LL | struct S(u8, u8, u8); + | -- -- -- tuple struct has 3 fields +... +LL | S(1, 2, .., 3, 4) => {} + | ^ ^ ^ ^ expected 3 fields, found 4 + +error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields + --> $DIR/pat-tuple-overfield.rs:31:11 + | +LL | struct M( + | - tuple struct defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple struct has 5 fields +... +LL | M(1, 2, 3, 4, 5, 6) => {} + | ^ ^ ^ ^ ^ ^ expected 5 fields, found 6 + +error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields + --> $DIR/pat-tuple-overfield.rs:33:11 + | +LL | struct M( + | - tuple struct defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple struct has 5 fields +... +LL | M(1, + | - ^ +LL | 2, + | ^ +LL | 3, + | ^ +LL | 4, + | ^ +LL | 5, + | ^ +LL | 6) => {} + | ^ expected 5 fields, found 6 + +error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields + --> $DIR/pat-tuple-overfield.rs:41:13 + | +LL | struct M( + | - tuple struct defined here +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- +LL | u8, + | -- tuple struct has 5 fields +... +LL | M( + | - +LL | 1, + | ^ +LL | 2, + | ^ +LL | 3, + | ^ +LL | 4, + | ^ +LL | 5, + | ^ +LL | 6, + | ^ expected 5 fields, found 6 + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 fields + --> $DIR/pat-tuple-overfield.rs:59:12 + | +LL | struct Z1(); + | --------- tuple struct has 0 fields +... +LL | Z1(_) => {} + | ^ expected 0 fields, found 1 + +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 0 fields + --> $DIR/pat-tuple-overfield.rs:60:12 + | +LL | struct Z1(); + | --------- tuple struct has 0 fields +... +LL | Z1(_, _) => {} + | ^ ^ expected 0 fields, found 2 + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 0 fields + --> $DIR/pat-tuple-overfield.rs:71:16 + | +LL | Z1(), + | -- tuple variant has 0 fields +... +LL | E1::Z1(_) => {} + | ^ expected 0 fields, found 1 + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 0 fields + --> $DIR/pat-tuple-overfield.rs:72:16 + | +LL | Z1(), + | -- tuple variant has 0 fields +... +LL | E1::Z1(_, _) => {} + | ^ ^ expected 0 fields, found 2 + +error: aborting due to 19 previous errors + +Some errors have detailed explanations: E0023, E0308, E0530, E0532. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/pat-tuple-underfield.rs b/tests/ui/pattern/pat-tuple-underfield.rs new file mode 100644 index 000000000..dac60e3fa --- /dev/null +++ b/tests/ui/pattern/pat-tuple-underfield.rs @@ -0,0 +1,67 @@ +struct S(i32, f32); +enum E { + S(i32, f32), +} +struct Point4(i32, i32, i32, i32); + +fn main() { + match S(0, 1.0) { + S(x) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + } + match S(0, 1.0) { + S(_) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields + } + match S(0, 1.0) { + S() => {} + //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields + + // Test non-standard formatting + S () => {} + //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields + } + + match E::S(0, 1.0) { + E::S(x) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + } + match E::S(0, 1.0) { + E::S(_) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields + } + match E::S(0, 1.0) { + E::S() => {} + //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields + + // Test non-standard formatting + E::S () => {} + //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields + } + match E::S(0, 1.0) { + E::S => {} + //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `E::S` + //~| HELP use the tuple variant pattern syntax instead + } + + match Point4(0, 1, 2, 3) { + Point4( a , _ ) => {} + //~^ ERROR this pattern has 2 fields, but the corresponding tuple struct has 4 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore the rest of the fields + } +} diff --git a/tests/ui/pattern/pat-tuple-underfield.stderr b/tests/ui/pattern/pat-tuple-underfield.stderr new file mode 100644 index 000000000..e75f9b38d --- /dev/null +++ b/tests/ui/pattern/pat-tuple-underfield.stderr @@ -0,0 +1,167 @@ +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` + --> $DIR/pat-tuple-underfield.rs:56:9 + | +LL | S(i32, f32), + | ----------- `E::S` defined here +... +LL | E::S => {} + | ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)` + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:9:11 + | +LL | struct S(i32, f32); + | --- --- tuple struct has 2 fields +... +LL | S(x) => {} + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(x, _) => {} + | +++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:14:11 + | +LL | struct S(i32, f32); + | --- --- tuple struct has 2 fields +... +LL | S(_) => {} + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _) => {} + | +++ +help: use `..` to ignore all fields + | +LL | S(..) => {} + | ~~ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:20:9 + | +LL | struct S(i32, f32); + | --- --- tuple struct has 2 fields +... +LL | S() => {} + | ^^^ expected 2 fields, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _) => {} + | ++++ +help: use `..` to ignore all fields + | +LL | S(..) => {} + | ++ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:26:9 + | +LL | struct S(i32, f32); + | --- --- tuple struct has 2 fields +... +LL | S () => {} + | ^^^^ expected 2 fields, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | S (_, _) => {} + | ++++ +help: use `..` to ignore all fields + | +LL | S (..) => {} + | ++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:33:14 + | +LL | S(i32, f32), + | --- --- tuple variant has 2 fields +... +LL | E::S(x) => {} + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(x, _) => {} + | +++ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:38:14 + | +LL | S(i32, f32), + | --- --- tuple variant has 2 fields +... +LL | E::S(_) => {} + | ^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(_, _) => {} + | +++ +help: use `..` to ignore all fields + | +LL | E::S(..) => {} + | ~~ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:44:9 + | +LL | S(i32, f32), + | --- --- tuple variant has 2 fields +... +LL | E::S() => {} + | ^^^^^^ expected 2 fields, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(_, _) => {} + | ++++ +help: use `..` to ignore all fields + | +LL | E::S(..) => {} + | ++ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:50:9 + | +LL | S(i32, f32), + | --- --- tuple variant has 2 fields +... +LL | E::S () => {} + | ^^^^^^^ expected 2 fields, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | E::S (_, _) => {} + | ++++ +help: use `..` to ignore all fields + | +LL | E::S (..) => {} + | ++ + +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields + --> $DIR/pat-tuple-underfield.rs:62:19 + | +LL | struct Point4(i32, i32, i32, i32); + | --- --- --- --- tuple struct has 4 fields +... +LL | Point4( a , _ ) => {} + | ^ ^ expected 4 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Point4( a , _ , _, _) => {} + | ++++++ +help: use `..` to ignore the rest of the fields + | +LL | Point4( a, ..) => {} + | ~~~~ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0023, E0532. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/pat-type-err-formal-param.rs b/tests/ui/pattern/pat-type-err-formal-param.rs new file mode 100644 index 000000000..54336b349 --- /dev/null +++ b/tests/ui/pattern/pat-type-err-formal-param.rs @@ -0,0 +1,8 @@ +// Test the `.span_label(..)` to the type when there's a +// type error in a pattern due to a the formal parameter. + +fn main() {} + +struct Tuple(u8); + +fn foo(Tuple(_): String) {} //~ ERROR mismatched types diff --git a/tests/ui/pattern/pat-type-err-formal-param.stderr b/tests/ui/pattern/pat-type-err-formal-param.stderr new file mode 100644 index 000000000..206713a4b --- /dev/null +++ b/tests/ui/pattern/pat-type-err-formal-param.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/pat-type-err-formal-param.rs:8:8 + | +LL | fn foo(Tuple(_): String) {} + | ^^^^^^^^ ------ expected due to this + | | + | expected struct `String`, found struct `Tuple` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/pat-type-err-let-stmt.rs b/tests/ui/pattern/pat-type-err-let-stmt.rs new file mode 100644 index 000000000..6e9850b65 --- /dev/null +++ b/tests/ui/pattern/pat-type-err-let-stmt.rs @@ -0,0 +1,16 @@ +// Test the `.span_label` to the type / scrutinee +// when there's a type error in checking a pattern. + +fn main() { + // We want to point at the `Option`. + let Ok(0): Option = 42u8; + //~^ ERROR mismatched types + //~| ERROR mismatched types + + // We want to point at the `Option`. + let Ok(0): Option; + //~^ ERROR mismatched types + + // We want to point at the scrutinee. + let Ok(0) = 42u8; //~ ERROR mismatched types +} diff --git a/tests/ui/pattern/pat-type-err-let-stmt.stderr b/tests/ui/pattern/pat-type-err-let-stmt.stderr new file mode 100644 index 000000000..090bd6711 --- /dev/null +++ b/tests/ui/pattern/pat-type-err-let-stmt.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/pat-type-err-let-stmt.rs:6:29 + | +LL | let Ok(0): Option = 42u8; + | ---------- ^^^^ expected enum `Option`, found `u8` + | | + | expected due to this + | + = note: expected enum `Option` + found type `u8` +help: try wrapping the expression in `Some` + | +LL | let Ok(0): Option = Some(42u8); + | +++++ + + +error[E0308]: mismatched types + --> $DIR/pat-type-err-let-stmt.rs:6:9 + | +LL | let Ok(0): Option = 42u8; + | ^^^^^ ---------- expected due to this + | | + | expected enum `Option`, found enum `Result` + | + = note: expected enum `Option` + found enum `Result<_, _>` + +error[E0308]: mismatched types + --> $DIR/pat-type-err-let-stmt.rs:11:9 + | +LL | let Ok(0): Option; + | ^^^^^ ---------- expected due to this + | | + | expected enum `Option`, found enum `Result` + | + = note: expected enum `Option` + found enum `Result<_, _>` + +error[E0308]: mismatched types + --> $DIR/pat-type-err-let-stmt.rs:15:9 + | +LL | let Ok(0) = 42u8; + | ^^^^^ ---- this expression has type `u8` + | | + | expected `u8`, found enum `Result` + | + = note: expected type `u8` + found enum `Result<_, _>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/patkind-litrange-no-expr.rs b/tests/ui/pattern/patkind-litrange-no-expr.rs new file mode 100644 index 000000000..7ef541cb5 --- /dev/null +++ b/tests/ui/pattern/patkind-litrange-no-expr.rs @@ -0,0 +1,24 @@ +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + enum $name { + $($variant = $value,)* + } + + fn foo(value: i32) -> Option<$name> { + match value { + $( $value => Some($name::$variant), )* // PatKind::Lit + $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range + _ => None + } + } + } +} + +enum_number!(Change { + Pos = 1, + Neg = -1, + Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns + //~| ERROR arbitrary expressions aren't allowed in patterns +}); + +fn main() {} diff --git a/tests/ui/pattern/patkind-litrange-no-expr.stderr b/tests/ui/pattern/patkind-litrange-no-expr.stderr new file mode 100644 index 000000000..eb1ee7e45 --- /dev/null +++ b/tests/ui/pattern/patkind-litrange-no-expr.stderr @@ -0,0 +1,14 @@ +error: arbitrary expressions aren't allowed in patterns + --> $DIR/patkind-litrange-no-expr.rs:20:13 + | +LL | Arith = 1 + 1, + | ^^^^^ + +error: arbitrary expressions aren't allowed in patterns + --> $DIR/patkind-litrange-no-expr.rs:20:13 + | +LL | Arith = 1 + 1, + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/pattern-binding-disambiguation.rs b/tests/ui/pattern/pattern-binding-disambiguation.rs new file mode 100644 index 000000000..ce1d8c6c0 --- /dev/null +++ b/tests/ui/pattern/pattern-binding-disambiguation.rs @@ -0,0 +1,57 @@ +struct UnitStruct; +struct TupleStruct(); +struct BracedStruct{} + +enum E { + UnitVariant, + TupleVariant(), + BracedVariant{}, +} +use E::*; + +const CONST: () = (); +static STATIC: () = (); + +fn function() {} + +fn main() { + let doesnt_matter = 0; + + match UnitStruct { + UnitStruct => {} // OK, `UnitStruct` is a unit struct pattern + } + match doesnt_matter { + TupleStruct => {} //~ ERROR match bindings cannot shadow tuple structs + } + match doesnt_matter { + BracedStruct => {} // OK, `BracedStruct` is a fresh binding + } + match UnitVariant { + UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern + } + match doesnt_matter { + TupleVariant => {} //~ ERROR match bindings cannot shadow tuple variants + } + match doesnt_matter { + BracedVariant => {} // OK, `BracedVariant` is a fresh binding + } + match CONST { + CONST => {} // OK, `CONST` is a const pattern + } + match doesnt_matter { + STATIC => {} //~ ERROR match bindings cannot shadow statics + } + match doesnt_matter { + function => {} // OK, `function` is a fresh binding + } + + let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern + let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs + let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding + let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern + let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants + let BracedVariant = doesnt_matter; // OK, `BracedVariant` is a fresh binding + let CONST = CONST; // OK, `CONST` is a const pattern + let STATIC = doesnt_matter; //~ ERROR let bindings cannot shadow statics + let function = doesnt_matter; // OK, `function` is a fresh binding +} diff --git a/tests/ui/pattern/pattern-binding-disambiguation.stderr b/tests/ui/pattern/pattern-binding-disambiguation.stderr new file mode 100644 index 000000000..d54467b3c --- /dev/null +++ b/tests/ui/pattern/pattern-binding-disambiguation.stderr @@ -0,0 +1,63 @@ +error[E0530]: match bindings cannot shadow tuple structs + --> $DIR/pattern-binding-disambiguation.rs:24:9 + | +LL | struct TupleStruct(); + | --------------------- the tuple struct `TupleStruct` is defined here +... +LL | TupleStruct => {} + | ^^^^^^^^^^^ + | | + | cannot be named the same as a tuple struct + | help: try specify the pattern arguments: `TupleStruct(..)` + +error[E0530]: match bindings cannot shadow tuple variants + --> $DIR/pattern-binding-disambiguation.rs:33:9 + | +LL | use E::*; + | ---- the tuple variant `TupleVariant` is imported here +... +LL | TupleVariant => {} + | ^^^^^^^^^^^^ + | | + | cannot be named the same as a tuple variant + | help: try specify the pattern arguments: `TupleVariant(..)` + +error[E0530]: match bindings cannot shadow statics + --> $DIR/pattern-binding-disambiguation.rs:42:9 + | +LL | static STATIC: () = (); + | ----------------------- the static `STATIC` is defined here +... +LL | STATIC => {} + | ^^^^^^ cannot be named the same as a static + +error[E0530]: let bindings cannot shadow tuple structs + --> $DIR/pattern-binding-disambiguation.rs:49:9 + | +LL | struct TupleStruct(); + | --------------------- the tuple struct `TupleStruct` is defined here +... +LL | let TupleStruct = doesnt_matter; + | ^^^^^^^^^^^ cannot be named the same as a tuple struct + +error[E0530]: let bindings cannot shadow tuple variants + --> $DIR/pattern-binding-disambiguation.rs:52:9 + | +LL | use E::*; + | ---- the tuple variant `TupleVariant` is imported here +... +LL | let TupleVariant = doesnt_matter; + | ^^^^^^^^^^^^ cannot be named the same as a tuple variant + +error[E0530]: let bindings cannot shadow statics + --> $DIR/pattern-binding-disambiguation.rs:55:9 + | +LL | static STATIC: () = (); + | ----------------------- the static `STATIC` is defined here +... +LL | let STATIC = doesnt_matter; + | ^^^^^^ cannot be named the same as a static + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/pattern/pattern-error-continue.rs b/tests/ui/pattern/pattern-error-continue.rs new file mode 100644 index 000000000..0702a9986 --- /dev/null +++ b/tests/ui/pattern/pattern-error-continue.rs @@ -0,0 +1,35 @@ +// Test that certain pattern-match type errors are non-fatal + +enum A { + B(isize, isize), + C(isize, isize, isize), + D +} + +struct S { + a: isize +} + +fn f(_c: char) {} + +fn main() { + match A::B(1, 2) { + A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but + A::D(_) => (), //~ ERROR expected tuple struct or tuple variant, found unit variant `A::D` + _ => () + } + match 'c' { + S { .. } => (), + //~^ ERROR mismatched types + //~| expected `char`, found struct `S` + + _ => () + } + f(true); + //~^ ERROR mismatched types + //~| expected `char`, found `bool` + + match () { + E::V => {} //~ ERROR failed to resolve: use of undeclared type `E` + } +} diff --git a/tests/ui/pattern/pattern-error-continue.stderr b/tests/ui/pattern/pattern-error-continue.stderr new file mode 100644 index 000000000..4c2eff63a --- /dev/null +++ b/tests/ui/pattern/pattern-error-continue.stderr @@ -0,0 +1,62 @@ +error[E0433]: failed to resolve: use of undeclared type `E` + --> $DIR/pattern-error-continue.rs:33:9 + | +LL | E::V => {} + | ^ use of undeclared type `E` + +error[E0532]: expected tuple struct or tuple variant, found unit variant `A::D` + --> $DIR/pattern-error-continue.rs:18:9 + | +LL | B(isize, isize), + | --------------- similarly named tuple variant `B` defined here +LL | C(isize, isize, isize), +LL | D + | - `A::D` defined here +... +LL | A::D(_) => (), + | ^^^^^^^ + | +help: use this syntax instead + | +LL | A::D => (), + | ~~~~ +help: a tuple variant with a similar name exists + | +LL | A::B(_) => (), + | ~ + +error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields + --> $DIR/pattern-error-continue.rs:17:14 + | +LL | B(isize, isize), + | ----- ----- tuple variant has 2 fields +... +LL | A::B(_, _, _) => (), + | ^ ^ ^ expected 2 fields, found 3 + +error[E0308]: mismatched types + --> $DIR/pattern-error-continue.rs:22:9 + | +LL | match 'c' { + | --- this expression has type `char` +LL | S { .. } => (), + | ^^^^^^^^ expected `char`, found struct `S` + +error[E0308]: mismatched types + --> $DIR/pattern-error-continue.rs:28:7 + | +LL | f(true); + | - ^^^^ expected `char`, found `bool` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/pattern-error-continue.rs:13:4 + | +LL | fn f(_c: char) {} + | ^ -------- + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0023, E0308, E0433, E0532. +For more information about an error, try `rustc --explain E0023`. diff --git a/tests/ui/pattern/pattern-ident-path-generics.rs b/tests/ui/pattern/pattern-ident-path-generics.rs new file mode 100644 index 000000000..48c02623f --- /dev/null +++ b/tests/ui/pattern/pattern-ident-path-generics.rs @@ -0,0 +1,6 @@ +fn main() { + match Some("foo") { + None:: => {} //~ ERROR mismatched types + Some(_) => {} + } +} diff --git a/tests/ui/pattern/pattern-ident-path-generics.stderr b/tests/ui/pattern/pattern-ident-path-generics.stderr new file mode 100644 index 000000000..01b082bd3 --- /dev/null +++ b/tests/ui/pattern/pattern-ident-path-generics.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/pattern-ident-path-generics.rs:3:9 + | +LL | match Some("foo") { + | ----------- this expression has type `Option<&str>` +LL | None:: => {} + | ^^^^^^^^^^^^^ expected `&str`, found `isize` + | + = note: expected enum `Option<&str>` + found enum `Option` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/pattern-tyvar-2.rs b/tests/ui/pattern/pattern-tyvar-2.rs new file mode 100644 index 000000000..7647c766e --- /dev/null +++ b/tests/ui/pattern/pattern-tyvar-2.rs @@ -0,0 +1,6 @@ +enum Bar { T1((), Option>), T2, } + +fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } } +//~^ ERROR cannot multiply `Vec` by `{integer}` + +fn main() { } diff --git a/tests/ui/pattern/pattern-tyvar-2.stderr b/tests/ui/pattern/pattern-tyvar-2.stderr new file mode 100644 index 000000000..121817e70 --- /dev/null +++ b/tests/ui/pattern/pattern-tyvar-2.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot multiply `Vec` by `{integer}` + --> $DIR/pattern-tyvar-2.rs:3:71 + | +LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } } + | - ^ - {integer} + | | + | Vec + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/pattern/pattern-tyvar.rs b/tests/ui/pattern/pattern-tyvar.rs new file mode 100644 index 000000000..e2cbf0519 --- /dev/null +++ b/tests/ui/pattern/pattern-tyvar.rs @@ -0,0 +1,12 @@ +enum Bar { T1((), Option>), T2 } + +fn foo(t: Bar) { + match t { + Bar::T1(_, Some::(x)) => { //~ ERROR mismatched types + println!("{}", x); + } + _ => { panic!(); } + } +} + +fn main() { } diff --git a/tests/ui/pattern/pattern-tyvar.stderr b/tests/ui/pattern/pattern-tyvar.stderr new file mode 100644 index 000000000..f1e2a9d72 --- /dev/null +++ b/tests/ui/pattern/pattern-tyvar.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/pattern-tyvar.rs:5:18 + | +LL | match t { + | - this expression has type `Bar` +LL | Bar::T1(_, Some::(x)) => { + | ^^^^^^^^^^^^^^^^ expected struct `Vec`, found `isize` + | + = note: expected enum `Option>` + found enum `Option` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rest-pat-semantic-disallowed.rs b/tests/ui/pattern/rest-pat-semantic-disallowed.rs new file mode 100644 index 000000000..156285e0f --- /dev/null +++ b/tests/ui/pattern/rest-pat-semantic-disallowed.rs @@ -0,0 +1,83 @@ +// Here we test that rest patterns, i.e. `..`, are not allowed +// outside of slice (+ ident patterns within those), tuple, +// and tuple struct patterns and that duplicates are caught in these contexts. + +#![feature(box_patterns)] + +fn main() {} + +macro_rules! mk_pat { + () => { .. } //~ ERROR `..` patterns are not allowed here +} + +fn rest_patterns() { + let mk_pat!(); + + // Top level: + fn foo(..: u8) {} //~ ERROR `..` patterns are not allowed here + let ..; //~ ERROR `..` patterns are not allowed here + + // Box patterns: + let box ..; //~ ERROR `..` patterns are not allowed here + + // In or-patterns: + match 1 { + 1 | .. => {} //~ ERROR `..` patterns are not allowed here + } + + // Ref patterns: + let &..; //~ ERROR `..` patterns are not allowed here + let &mut ..; //~ ERROR `..` patterns are not allowed here + + // Ident patterns: + let x @ ..; //~ ERROR `..` patterns are not allowed here + //~^ ERROR type annotations needed + let ref x @ ..; //~ ERROR `..` patterns are not allowed here + let ref mut x @ ..; //~ ERROR `..` patterns are not allowed here + + // Tuple: + let (..): (u8,); // OK. + let (..,): (u8,); // OK. + let ( + .., + .., //~ ERROR `..` can only be used once per tuple pattern + .. //~ ERROR `..` can only be used once per tuple pattern + ): (u8, u8, u8); + let ( + .., + x, + .. //~ ERROR `..` can only be used once per tuple pattern + ): (u8, u8, u8); + + struct A(u8, u8, u8); + + // Tuple struct (same idea as for tuple patterns): + let A(..); // OK. + let A(..,); // OK. + let A( + .., + .., //~ ERROR `..` can only be used once per tuple struct pattern + .. //~ ERROR `..` can only be used once per tuple struct pattern + ); + let A( + .., + x, + .. //~ ERROR `..` can only be used once per tuple struct pattern + ); + + // Array/Slice: + let [..]: &[u8]; // OK. + let [..,]: &[u8]; // OK. + let [ + .., + .., //~ ERROR `..` can only be used once per slice pattern + .. //~ ERROR `..` can only be used once per slice pattern + ]: &[u8]; + let [ + .., + ref x @ .., //~ ERROR `..` can only be used once per slice pattern + ref mut y @ .., //~ ERROR `..` can only be used once per slice pattern + (ref z @ ..), //~ ERROR `..` patterns are not allowed here + .. //~ ERROR `..` can only be used once per slice pattern + ]: &[u8]; +} diff --git a/tests/ui/pattern/rest-pat-semantic-disallowed.stderr b/tests/ui/pattern/rest-pat-semantic-disallowed.stderr new file mode 100644 index 000000000..beba7def9 --- /dev/null +++ b/tests/ui/pattern/rest-pat-semantic-disallowed.stderr @@ -0,0 +1,201 @@ +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:10:13 + | +LL | () => { .. } + | ^^ +... +LL | let mk_pat!(); + | --------- in this macro invocation + | + = note: only allowed in tuple, tuple struct, and slice patterns + = note: this error originates in the macro `mk_pat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:18:9 + | +LL | let ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:21:13 + | +LL | let box ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:25:13 + | +LL | 1 | .. => {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:29:10 + | +LL | let &..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:30:14 + | +LL | let &mut ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:33:13 + | +LL | let x @ ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:35:17 + | +LL | let ref x @ ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:36:21 + | +LL | let ref mut x @ ..; + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` can only be used once per tuple pattern + --> $DIR/rest-pat-semantic-disallowed.rs:43:9 + | +LL | .., + | -- previously used here +LL | .., + | ^^ can only be used once per tuple pattern + +error: `..` can only be used once per tuple pattern + --> $DIR/rest-pat-semantic-disallowed.rs:44:9 + | +LL | .., + | -- previously used here +LL | .., +LL | .. + | ^^ can only be used once per tuple pattern + +error: `..` can only be used once per tuple pattern + --> $DIR/rest-pat-semantic-disallowed.rs:49:9 + | +LL | .., + | -- previously used here +LL | x, +LL | .. + | ^^ can only be used once per tuple pattern + +error: `..` can only be used once per tuple struct pattern + --> $DIR/rest-pat-semantic-disallowed.rs:59:9 + | +LL | .., + | -- previously used here +LL | .., + | ^^ can only be used once per tuple struct pattern + +error: `..` can only be used once per tuple struct pattern + --> $DIR/rest-pat-semantic-disallowed.rs:60:9 + | +LL | .., + | -- previously used here +LL | .., +LL | .. + | ^^ can only be used once per tuple struct pattern + +error: `..` can only be used once per tuple struct pattern + --> $DIR/rest-pat-semantic-disallowed.rs:65:9 + | +LL | .., + | -- previously used here +LL | x, +LL | .. + | ^^ can only be used once per tuple struct pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:73:9 + | +LL | .., + | -- previously used here +LL | .., + | ^^ can only be used once per slice pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:74:9 + | +LL | .., + | -- previously used here +LL | .., +LL | .. + | ^^ can only be used once per slice pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:78:17 + | +LL | .., + | -- previously used here +LL | ref x @ .., + | ^^ can only be used once per slice pattern + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:79:21 + | +LL | .., + | -- previously used here +LL | ref x @ .., +LL | ref mut y @ .., + | ^^ can only be used once per slice pattern + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:80:18 + | +LL | (ref z @ ..), + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: `..` can only be used once per slice pattern + --> $DIR/rest-pat-semantic-disallowed.rs:81:9 + | +LL | .., + | -- previously used here +... +LL | .. + | ^^ can only be used once per slice pattern + +error: `..` patterns are not allowed here + --> $DIR/rest-pat-semantic-disallowed.rs:17:12 + | +LL | fn foo(..: u8) {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0282]: type annotations needed + --> $DIR/rest-pat-semantic-disallowed.rs:33:9 + | +LL | let x @ ..; + | ^^^^^^ + | +help: consider giving this pattern a type + | +LL | let x @ ..: /* Type */; + | ++++++++++++ + +error: aborting due to 23 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/pattern/rest-pat-syntactic.rs b/tests/ui/pattern/rest-pat-syntactic.rs new file mode 100644 index 000000000..4da5a2db7 --- /dev/null +++ b/tests/ui/pattern/rest-pat-syntactic.rs @@ -0,0 +1,73 @@ +// Here we test that `..` is allowed in all pattern locations *syntactically*. +// The semantic test is in `rest-pat-semantic-disallowed.rs`. + +// check-pass + +fn main() {} + +macro_rules! accept_pat { + ($p:pat) => {} +} + +accept_pat!(..); + +#[cfg(FALSE)] +fn rest_patterns() { + // Top level: + fn foo(..: u8) {} + let ..; + + // Box patterns: + let box ..; + //~^ WARN box pattern syntax is experimental + //~| WARN unstable syntax + + // In or-patterns: + match x { + .. | .. => {} + } + + // Ref patterns: + let &..; + let &mut ..; + + // Ident patterns: + let x @ ..; + let ref x @ ..; + let ref mut x @ ..; + + // Tuple: + let (..); // This is interpreted as a tuple pattern, not a parenthesis one. + let (..,); // Allowing trailing comma. + let (.., .., ..); // Duplicates also. + let (.., P, ..); // Including with things in between. + + // Tuple struct (same idea as for tuple patterns): + let A(..); + let A(..,); + let A(.., .., ..); + let A(.., P, ..); + + // Array/Slice (like with tuple patterns): + let [..]; + let [..,]; + let [.., .., ..]; + let [.., P, ..]; + + // Random walk to guard against special casing: + match x { + .. | + [ + ( + box .., //~ WARN box pattern syntax is experimental + &(..), + &mut .., + x @ .. + ), + ref x @ .., + ] | + ref mut x @ .. + => {} + } + //~| WARN unstable syntax +} diff --git a/tests/ui/pattern/rest-pat-syntactic.stderr b/tests/ui/pattern/rest-pat-syntactic.stderr new file mode 100644 index 000000000..37019b7d5 --- /dev/null +++ b/tests/ui/pattern/rest-pat-syntactic.stderr @@ -0,0 +1,24 @@ +warning: box pattern syntax is experimental + --> $DIR/rest-pat-syntactic.rs:21:9 + | +LL | let box ..; + | ^^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: box pattern syntax is experimental + --> $DIR/rest-pat-syntactic.rs:62:17 + | +LL | box .., + | ^^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 2 warnings emitted + diff --git a/tests/ui/pattern/size-and-align.rs b/tests/ui/pattern/size-and-align.rs new file mode 100644 index 000000000..a32b5de72 --- /dev/null +++ b/tests/ui/pattern/size-and-align.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(non_camel_case_types)] +enum clam { a(T, isize), b, } + +fn uhoh(v: Vec> ) { + match v[1] { + clam::a::(ref _t, ref u) => { + println!("incorrect"); + println!("{}", u); + panic!(); + } + clam::b:: => { println!("correct"); } + } +} + +pub fn main() { + let v: Vec> = vec![clam::b::, clam::b::, clam::a::(42, 17)]; + uhoh::(v); +} diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed new file mode 100644 index 000000000..b28dce881 --- /dev/null +++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + match Some(1) { //~ ERROR non-exhaustive patterns: `None` not covered + Some(1) => {} + // hello + Some(_) => {} + None => todo!() + } +} diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.rs b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.rs new file mode 100644 index 000000000..42493a632 --- /dev/null +++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + match Some(1) { //~ ERROR non-exhaustive patterns: `None` not covered + Some(1) => {} + // hello + Some(_) => {} + } +} diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr new file mode 100644 index 000000000..2a016048f --- /dev/null +++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/suggest-adding-appropriate-missing-pattern-excluding-comments.rs:4:11 + | +LL | match Some(1) { + | ^^^^^^^ pattern `None` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Some(_) => {} +LL + None => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs new file mode 100644 index 000000000..7d1cac8a4 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -0,0 +1,32 @@ +// The precise semantics of inhabitedness with respect to unions and references is currently +// undecided. This test file currently checks a conservative choice. + +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +#![allow(dead_code)] +#![allow(unreachable_code)] + +pub union Foo { + foo: !, +} + +fn uninhab_ref() -> &'static ! { + unimplemented!() +} + +fn uninhab_union() -> Foo { + unimplemented!() +} + +fn match_on_uninhab() { + match uninhab_ref() { + //~^ ERROR non-exhaustive patterns: type `&!` is non-empty + } + + match uninhab_union() { + //~^ ERROR non-exhaustive patterns: type `Foo` is non-empty + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr new file mode 100644 index 000000000..cd5c283f9 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr @@ -0,0 +1,37 @@ +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/always-inhabited-union-ref.rs:23:11 + | +LL | match uninhab_ref() { + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_ref() { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `Foo` is non-empty + --> $DIR/always-inhabited-union-ref.rs:27:11 + | +LL | match uninhab_union() { + | ^^^^^^^^^^^^^^^ + | +note: `Foo` defined here + --> $DIR/always-inhabited-union-ref.rs:10:11 + | +LL | pub union Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_union() { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/auxiliary/empty.rs b/tests/ui/pattern/usefulness/auxiliary/empty.rs new file mode 100644 index 000000000..29a03c9e8 --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/empty.rs @@ -0,0 +1,10 @@ +#![crate_type = "rlib"] +pub enum EmptyForeignEnum {} + +pub struct VisiblyUninhabitedForeignStruct { + pub field: EmptyForeignEnum, +} + +pub struct SecretlyUninhabitedForeignStruct { + _priv: EmptyForeignEnum, +} diff --git a/tests/ui/pattern/usefulness/auxiliary/hidden.rs b/tests/ui/pattern/usefulness/auxiliary/hidden.rs new file mode 100644 index 000000000..364514ba1 --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/hidden.rs @@ -0,0 +1,14 @@ +pub enum HiddenEnum { + A, + B, + #[doc(hidden)] + C, +} + +#[derive(Default)] +pub struct HiddenStruct { + pub one: u8, + pub two: bool, + #[doc(hidden)] + pub hide: usize, +} diff --git a/tests/ui/pattern/usefulness/auxiliary/unstable.rs b/tests/ui/pattern/usefulness/auxiliary/unstable.rs new file mode 100644 index 000000000..a06b3a6e4 --- /dev/null +++ b/tests/ui/pattern/usefulness/auxiliary/unstable.rs @@ -0,0 +1,23 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum UnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} + +#[derive(Default)] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable: bool, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable2: usize, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, +} diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs new file mode 100644 index 000000000..02599d7c0 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs @@ -0,0 +1,18 @@ +#![allow(warnings)] + +struct MyType; + +impl PartialEq for MyType { + fn eq(&self, y: &usize) -> bool { + true + } +} + +const CONSTANT: &&MyType = &&MyType; + +fn main() { + if let CONSTANT = &&MyType { + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + println!("did match!"); + } +} diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr new file mode 100644 index 000000000..358421cd6 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/const-partial_eq-fallback-ice.rs:14:12 + | +LL | if let CONSTANT = &&MyType { + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/const-pat-ice.rs b/tests/ui/pattern/usefulness/const-pat-ice.rs new file mode 100644 index 000000000..abfacf393 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-pat-ice.rs @@ -0,0 +1,11 @@ +// check-pass + +const FOO: &&&u32 = &&&42; + +fn main() { + match unimplemented!() { + &&&42 => {}, + FOO => {}, + _ => {}, + } +} diff --git a/tests/ui/pattern/usefulness/const-private-fields.rs b/tests/ui/pattern/usefulness/const-private-fields.rs new file mode 100644 index 000000000..06c832ca4 --- /dev/null +++ b/tests/ui/pattern/usefulness/const-private-fields.rs @@ -0,0 +1,30 @@ +// check-pass +// +// Check that we don't ignore private fields in usefulness checking +#![deny(unreachable_patterns)] + +mod inner { + #[derive(PartialEq, Eq)] + pub struct PrivateField { + pub x: bool, + y: bool, + } + + pub const FOO: PrivateField = PrivateField { x: true, y: true }; + pub const BAR: PrivateField = PrivateField { x: true, y: false }; +} +use inner::*; + +fn main() { + match FOO { + FOO => {} + BAR => {} + _ => {} + } + + match FOO { + FOO => {} + PrivateField { x: true, .. } => {} + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs new file mode 100644 index 000000000..ca4fcd85b --- /dev/null +++ b/tests/ui/pattern/usefulness/consts-opaque.rs @@ -0,0 +1,145 @@ +// This file tests the exhaustiveness algorithm on opaque constants. Most of the examples give +// unnecessary warnings because const_to_pat.rs converts a constant pattern to a wildcard when the +// constant is not allowed as a pattern. This is an edge case so we may not care to fix it. +// See also https://github.com/rust-lang/rust/issues/78057 + +#![deny(unreachable_patterns)] + +#[derive(PartialEq)] +struct Foo(i32); +impl Eq for Foo {} +const FOO: Foo = Foo(42); +const FOO_REF: &Foo = &Foo(42); +const FOO_REF_REF: &&Foo = &&Foo(42); + +#[derive(PartialEq)] +struct Bar; +impl Eq for Bar {} +const BAR: Bar = Bar; + +#[derive(PartialEq)] +enum Baz { + Baz1, + Baz2 +} +impl Eq for Baz {} +const BAZ: Baz = Baz::Baz1; + +fn main() { + match FOO { + FOO => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + match FOO_REF { + FOO_REF => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Foo(_) => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + // This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071) + match FOO_REF_REF { + FOO_REF_REF => {} + //~^ WARNING must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARNING this was previously accepted by the compiler but is being phased out + Foo(_) => {} + } + + match BAR { + Bar => {} + BAR => {} // should not be emitting unreachable warning + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + //~| ERROR unreachable pattern + _ => {} + //~^ ERROR unreachable pattern + } + + match BAR { + BAR => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Bar => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + _ => {} + //~^ ERROR unreachable pattern + } + + match BAR { + BAR => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + BAR => {} // should not be emitting unreachable warning + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + //~| ERROR unreachable pattern + _ => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + match BAZ { + BAZ => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Baz::Baz1 => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + _ => {} + //~^ ERROR unreachable pattern + } + + match BAZ { + Baz::Baz1 => {} + BAZ => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => {} + //~^ ERROR unreachable pattern + } + + match BAZ { + BAZ => {} + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + Baz::Baz2 => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + _ => {} // should not be emitting unreachable warning + //~^ ERROR unreachable pattern + } + + type Quux = fn(usize, usize) -> usize; + fn quux(a: usize, b: usize) -> usize { a + b } + const QUUX: Quux = quux; + + match QUUX { + QUUX => {} + QUUX => {} + _ => {} + } + + #[derive(PartialEq, Eq)] + struct Wrap(T); + const WRAPQUUX: Wrap = Wrap(quux); + + match WRAPQUUX { + WRAPQUUX => {} + WRAPQUUX => {} + Wrap(_) => {} + } + + match WRAPQUUX { + Wrap(_) => {} + WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer + //~^ ERROR unreachable pattern + } + + #[derive(PartialEq, Eq)] + enum WhoKnows { + Yay(T), + Nope, + }; + const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); + + match WHOKNOWSQUUX { + WHOKNOWSQUUX => {} + WhoKnows::Yay(_) => {} + WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer + //~^ ERROR unreachable pattern + WhoKnows::Nope => {} + } +} diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr new file mode 100644 index 000000000..35396751a --- /dev/null +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -0,0 +1,202 @@ +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:30:9 + | +LL | FOO => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:32:9 + | +LL | FOO => {} + | --- matches any value +LL | +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/consts-opaque.rs:6:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:37:9 + | +LL | FOO_REF => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:39:9 + | +LL | FOO_REF => {} + | ------- matches any value +LL | +LL | Foo(_) => {} // should not be emitting unreachable warning + | ^^^^^^ unreachable pattern + +warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:45:9 + | +LL | FOO_REF_REF => {} + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(indirect_structural_match)]` on by default + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:53:9 + | +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:53:9 + | +LL | Bar => {} + | --- matches any value +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:56:9 + | +LL | Bar => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:61:9 + | +LL | BAR => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:63:9 + | +LL | BAR => {} + | --- matches any value +LL | +LL | Bar => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:65:9 + | +LL | BAR => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:70:9 + | +LL | BAR => {} + | ^^^ + +error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:72:9 + | +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:72:9 + | +LL | BAR => {} + | --- matches any value +LL | +LL | BAR => {} // should not be emitting unreachable warning + | ^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:75:9 + | +LL | BAR => {} + | --- matches any value +... +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:80:9 + | +LL | BAZ => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:82:9 + | +LL | BAZ => {} + | --- matches any value +LL | +LL | Baz::Baz1 => {} // should not be emitting unreachable warning + | ^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:84:9 + | +LL | BAZ => {} + | --- matches any value +... +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:90:9 + | +LL | BAZ => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:92:9 + | +LL | BAZ => {} + | --- matches any value +LL | +LL | _ => {} + | ^ unreachable pattern + +error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/consts-opaque.rs:97:9 + | +LL | BAZ => {} + | ^^^ + +error: unreachable pattern + --> $DIR/consts-opaque.rs:99:9 + | +LL | BAZ => {} + | --- matches any value +LL | +LL | Baz::Baz2 => {} // should not be emitting unreachable warning + | ^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:101:9 + | +LL | BAZ => {} + | --- matches any value +... +LL | _ => {} // should not be emitting unreachable warning + | ^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:127:9 + | +LL | Wrap(_) => {} + | ------- matches any value +LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer + | ^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/consts-opaque.rs:141:9 + | +LL | WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer + | ^^^^^^^^^^^^ + +error: aborting due to 24 previous errors; 1 warning emitted + diff --git a/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs new file mode 100644 index 000000000..c85af7f3b --- /dev/null +++ b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs @@ -0,0 +1,16 @@ +#![feature(if_let_guard)] + +#![deny(irrefutable_let_patterns)] + +fn main() { + if let _ = 5 {} //~ ERROR irrefutable `if let` pattern + + while let _ = 5 { //~ ERROR irrefutable `while let` pattern + break; + } + + match 5 { + _ if let _ = 2 => {} //~ ERROR irrefutable `if let` guard pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr new file mode 100644 index 000000000..cdb6b5c7a --- /dev/null +++ b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr @@ -0,0 +1,34 @@ +error: irrefutable `if let` pattern + --> $DIR/deny-irrefutable-let-patterns.rs:6:8 + | +LL | if let _ = 5 {} + | ^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` +note: the lint level is defined here + --> $DIR/deny-irrefutable-let-patterns.rs:3:9 + | +LL | #![deny(irrefutable_let_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: irrefutable `while let` pattern + --> $DIR/deny-irrefutable-let-patterns.rs:8:11 + | +LL | while let _ = 5 { + | ^^^^^^^^^ + | + = note: this pattern will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + +error: irrefutable `if let` guard pattern + --> $DIR/deny-irrefutable-let-patterns.rs:13:18 + | +LL | _ if let _ = 2 => {} + | ^ + | + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.rs b/tests/ui/pattern/usefulness/doc-hidden-fields.rs new file mode 100644 index 000000000..4163b87dc --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-fields.rs @@ -0,0 +1,26 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::HiddenStruct; + +struct InCrate { + a: usize, + b: bool, + #[doc(hidden)] + im_hidden: u8 +} + +fn main() { + let HiddenStruct { one, two } = HiddenStruct::default(); + //~^ pattern requires `..` due to inaccessible fields + + let HiddenStruct { one } = HiddenStruct::default(); + //~^ pattern does not mention field `two` and inaccessible fields + + let HiddenStruct { one, hide } = HiddenStruct::default(); + //~^ pattern does not mention field `two` + + let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; + //~^ pattern does not mention field `im_hidden` +} diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr new file mode 100644 index 000000000..f277bfbc8 --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr @@ -0,0 +1,59 @@ +error: pattern requires `..` due to inaccessible fields + --> $DIR/doc-hidden-fields.rs:15:9 + | +LL | let HiddenStruct { one, two } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); + | ++++ + +error[E0027]: pattern does not mention field `two` and inaccessible fields + --> $DIR/doc-hidden-fields.rs:18:9 + | +LL | let HiddenStruct { one } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^ missing field `two` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let HiddenStruct { one, .. } = HiddenStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `two` + --> $DIR/doc-hidden-fields.rs:21:9 + | +LL | let HiddenStruct { one, hide } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `two` + | +help: include the missing field in the pattern + | +LL | let HiddenStruct { one, hide, two } = HiddenStruct::default(); + | ~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `im_hidden` + --> $DIR/doc-hidden-fields.rs:24:9 + | +LL | let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ^^^^^^^^^^^^^^^^ missing field `im_hidden` + | +help: include the missing field in the pattern + | +LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs new file mode 100644 index 000000000..5d4181a30 --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -0,0 +1,43 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::HiddenEnum; + +enum InCrate { + A, + B, + #[doc(hidden)] + C, +} + +fn main() { + match HiddenEnum::A { + HiddenEnum::A => {} + HiddenEnum::B => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered + + match HiddenEnum::A { + HiddenEnum::A => {} + HiddenEnum::C => {} + } + //~^^^^ non-exhaustive patterns: `HiddenEnum::B` not covered + + match HiddenEnum::A { + HiddenEnum::A => {} + } + //~^^^ non-exhaustive patterns: `HiddenEnum::B` and `_` not covered + + match None { + None => {} + Some(HiddenEnum::A) => {} + } + //~^^^^ non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered + + match InCrate::A { + InCrate::A => {} + InCrate::B => {} + } + //~^^^^ non-exhaustive patterns: `InCrate::C` not covered +} diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr new file mode 100644 index 000000000..17e1a2304 --- /dev/null +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -0,0 +1,102 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:15:11 + | +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ pattern `_` not covered + | +note: `HiddenEnum` defined here + --> $DIR/auxiliary/hidden.rs:1:1 + | +LL | pub enum HiddenEnum { + | ^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `HiddenEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ HiddenEnum::B => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `HiddenEnum::B` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:21:11 + | +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered + | +note: `HiddenEnum` defined here + --> $DIR/auxiliary/hidden.rs:3:5 + | +LL | pub enum HiddenEnum { + | ------------------- +LL | A, +LL | B, + | ^ not covered + = note: the matched value is of type `HiddenEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ HiddenEnum::C => {} +LL + HiddenEnum::B => todo!() + | + +error[E0004]: non-exhaustive patterns: `HiddenEnum::B` and `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:27:11 + | +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered + | +note: `HiddenEnum` defined here + --> $DIR/auxiliary/hidden.rs:3:5 + | +LL | pub enum HiddenEnum { + | ------------------- +LL | A, +LL | B, + | ^ not covered + = note: the matched value is of type `HiddenEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ HiddenEnum::A => {} +LL + HiddenEnum::B | _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:32:11 + | +LL | match None { + | ^^^^ patterns `Some(HiddenEnum::B)` and `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Some(HiddenEnum::A) => {} +LL + Some(HiddenEnum::B) | Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `InCrate::C` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:38:11 + | +LL | match InCrate::A { + | ^^^^^^^^^^ pattern `InCrate::C` not covered + | +note: `InCrate` defined here + --> $DIR/doc-hidden-non-exhaustive.rs:11:5 + | +LL | enum InCrate { + | ------- +... +LL | C, + | ^ not covered + = note: the matched value is of type `InCrate` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ InCrate::B => {} +LL + InCrate::C => todo!() + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr new file mode 100644 index 000000000..5e12bc1d2 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -0,0 +1,303 @@ +error: unreachable pattern + --> $DIR/empty-match.rs:37:9 + | +LL | _ => {}, + | ^ + | +note: the lint level is defined here + --> $DIR/empty-match.rs:8:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-match.rs:40:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:47:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:50:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:57:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:60:9 + | +LL | _ if false => {}, + | ^ + +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/empty-match.rs:78:20 + | +LL | match_no_arms!(0u8); + | ^^^ + | + = note: the matched value is of type `u8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:79:20 + | +LL | match_no_arms!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty + --> $DIR/empty-match.rs:80:20 + | +LL | match_no_arms!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty + --> $DIR/empty-match.rs:81:20 + | +LL | match_no_arms!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty + --> $DIR/empty-match.rs:82:20 + | +LL | match_no_arms!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:83:20 + | +LL | match_no_arms!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:84:20 + | +LL | match_no_arms!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:85:20 + | +LL | match_no_arms!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:87:24 + | +LL | match_guarded_arm!(0u8); + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered + --> $DIR/empty-match.rs:88:24 + | +LL | match_guarded_arm!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyStruct1 => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered + --> $DIR/empty-match.rs:89:24 + | +LL | match_guarded_arm!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyStruct2(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered + --> $DIR/empty-match.rs:90:24 + | +LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyUnion1 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered + --> $DIR/empty-match.rs:91:24 + | +LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyUnion2 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:92:24 + | +LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyEnum1::Foo(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:93:24 + | +LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:94:24 + | +LL | match_guarded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + _ => todo!() + | + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr new file mode 100644 index 000000000..5e12bc1d2 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -0,0 +1,303 @@ +error: unreachable pattern + --> $DIR/empty-match.rs:37:9 + | +LL | _ => {}, + | ^ + | +note: the lint level is defined here + --> $DIR/empty-match.rs:8:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-match.rs:40:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:47:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:50:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:57:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $DIR/empty-match.rs:60:9 + | +LL | _ if false => {}, + | ^ + +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/empty-match.rs:78:20 + | +LL | match_no_arms!(0u8); + | ^^^ + | + = note: the matched value is of type `u8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:79:20 + | +LL | match_no_arms!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty + --> $DIR/empty-match.rs:80:20 + | +LL | match_no_arms!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty + --> $DIR/empty-match.rs:81:20 + | +LL | match_no_arms!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty + --> $DIR/empty-match.rs:82:20 + | +LL | match_no_arms!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:83:20 + | +LL | match_no_arms!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:84:20 + | +LL | match_no_arms!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:85:20 + | +LL | match_no_arms!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:87:24 + | +LL | match_guarded_arm!(0u8); + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered + --> $DIR/empty-match.rs:88:24 + | +LL | match_guarded_arm!(NonEmptyStruct1); + | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered + | +note: `NonEmptyStruct1` defined here + --> $DIR/empty-match.rs:14:8 + | +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyStruct1 => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered + --> $DIR/empty-match.rs:89:24 + | +LL | match_guarded_arm!(NonEmptyStruct2(true)); + | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered + | +note: `NonEmptyStruct2` defined here + --> $DIR/empty-match.rs:15:8 + | +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyStruct2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyStruct2(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered + --> $DIR/empty-match.rs:90:24 + | +LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered + | +note: `NonEmptyUnion1` defined here + --> $DIR/empty-match.rs:16:7 + | +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyUnion1 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered + --> $DIR/empty-match.rs:91:24 + | +LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered + | +note: `NonEmptyUnion2` defined here + --> $DIR/empty-match.rs:19:7 + | +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyUnion2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyUnion2 { .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered + --> $DIR/empty-match.rs:92:24 + | +LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered + | +note: `NonEmptyEnum1` defined here + --> $DIR/empty-match.rs:24:5 + | +LL | enum NonEmptyEnum1 { + | ------------- +LL | Foo(bool), + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum1` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {} +LL + NonEmptyEnum1::Foo(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + --> $DIR/empty-match.rs:93:24 + | +LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + | +note: `NonEmptyEnum2` defined here + --> $DIR/empty-match.rs:27:5 + | +LL | enum NonEmptyEnum2 { + | ------------- +LL | Foo(bool), + | ^^^ not covered +LL | Bar, + | ^^^ not covered + = note: the matched value is of type `NonEmptyEnum2` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() + | + +error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + --> $DIR/empty-match.rs:94:24 + | +LL | match_guarded_arm!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + | +note: `NonEmptyEnum5` defined here + --> $DIR/empty-match.rs:30:6 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `NonEmptyEnum5` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ _ if false => {} +LL + _ => todo!() + | + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs new file mode 100644 index 000000000..9cdc0413b --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -0,0 +1,95 @@ +// aux-build:empty.rs +// revisions: normal exhaustive_patterns +// +// This tests a match with no arms on various types. +#![feature(never_type)] +#![feature(never_type_fallback)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![deny(unreachable_patterns)] + +extern crate empty; + +enum EmptyEnum {} + +struct NonEmptyStruct1; +struct NonEmptyStruct2(bool); +union NonEmptyUnion1 { + foo: (), +} +union NonEmptyUnion2 { + foo: (), + bar: (), +} +enum NonEmptyEnum1 { + Foo(bool), +} +enum NonEmptyEnum2 { + Foo(bool), + Bar, +} +enum NonEmptyEnum5 { + V1, V2, V3, V4, V5, +} + +fn empty_enum(x: EmptyEnum) { + match x {} // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +fn empty_foreign_enum(x: empty::EmptyForeignEnum) { + match x {} // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +fn never(x: !) { + match x {} // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +macro_rules! match_no_arms { + ($e:expr) => { + match $e {} + }; +} +macro_rules! match_guarded_arm { + ($e:expr) => { + match $e { + _ if false => {} + } + }; +} + +fn main() { + match_no_arms!(0u8); //~ ERROR type `u8` is non-empty + match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty + match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty + match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty + match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty + match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered + match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + + match_guarded_arm!(0u8); //~ ERROR `_` not covered + match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered + match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered + match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered + match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered + match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered + match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered + match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered +} diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs new file mode 100644 index 000000000..095f5ac9a --- /dev/null +++ b/tests/ui/pattern/usefulness/floats.rs @@ -0,0 +1,19 @@ +#![allow(illegal_floating_point_literal_pattern)] +#![deny(unreachable_patterns)] + +fn main() { + match 0.0 { + 0.0..=1.0 => {} + _ => {} // ok + } + + match 0.0 { //~ ERROR non-exhaustive patterns + 0.0..=1.0 => {} + } + + match 1.0f64 { + 0.01f64 ..= 6.5f64 => {} + 0.02f64 => {} //~ ERROR unreachable pattern + _ => {} + }; +} diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr new file mode 100644 index 000000000..c926e50b3 --- /dev/null +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -0,0 +1,28 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/floats.rs:10:11 + | +LL | match 0.0 { + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `f64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 0.0..=1.0 => {} +LL + _ => todo!() + | + +error: unreachable pattern + --> $DIR/floats.rs:16:7 + | +LL | 0.02f64 => {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/floats.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/guards.rs b/tests/ui/pattern/usefulness/guards.rs new file mode 100644 index 000000000..b15440cf6 --- /dev/null +++ b/tests/ui/pattern/usefulness/guards.rs @@ -0,0 +1,22 @@ +#![feature(exclusive_range_pattern)] +#![deny(unreachable_patterns)] + +enum Q { R(Option) } + +pub fn main() { + match Q::R(None) { + Q::R(S) if S.is_some() => {} + _ => {} + } + + match 0u8 { //~ ERROR non-exhaustive patterns + 0 .. 128 => {} + 128 ..= 255 if true => {} + } + + match 0u8 { + 0 .. 128 => {} + 128 ..= 255 if false => {} + 128 ..= 255 => {} // ok, because previous arm was guarded + } +} diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr new file mode 100644 index 000000000..0c1563c16 --- /dev/null +++ b/tests/ui/pattern/usefulness/guards.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered + --> $DIR/guards.rs:12:11 + | +LL | match 0u8 { + | ^^^ pattern `128_u8..=u8::MAX` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 128 ..= 255 if true => {} +LL + 128_u8..=u8::MAX => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs new file mode 100644 index 000000000..0f5f49c4c --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs @@ -0,0 +1,101 @@ +#![feature(exclusive_range_pattern)] +#![allow(overlapping_range_endpoints)] +#![deny(unreachable_patterns)] + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +macro_rules! test_int { + ($s:expr, $min:path, $max:path) => { + m!($s, $min..=$max); + m!($s, $min..5 | 5..=$max); + m!($s, $min..=4 | 5..=$max); + m!($s, $min..$max | $max); + m!(($s, true), ($min..5, true) | (5..=$max, true) | ($min..=$max, false)); + } +} + +fn main() { + test_int!(0u8, u8::MIN, u8::MAX); + test_int!(0u16, u16::MIN, u16::MAX); + test_int!(0u32, u32::MIN, u32::MAX); + test_int!(0u64, u64::MIN, u64::MAX); + test_int!(0u128, u128::MIN, u128::MAX); + + test_int!(0i8, i8::MIN, i8::MAX); + test_int!(0i16, i16::MIN, i16::MAX); + test_int!(0i32, i32::MIN, i32::MAX); + test_int!(0i64, i64::MIN, i64::MAX); + test_int!(0i128, i128::MIN, i128::MAX); + + m!('a', '\u{0}'..=char::MAX); + m!('a', '\u{0}'..='\u{10_FFFF}'); + // We can get away with just covering the following two ranges, which correspond to all valid + // Unicode Scalar Values. + m!('a', '\u{0}'..='\u{D7FF}' | '\u{E000}'..=char::MAX); + m!('a', '\u{0}'..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..=char::MAX); + + let 0..=255 = 0u8; + let -128..=127 = 0i8; + let -2147483648..=2147483647 = 0i32; + let '\u{0000}'..='\u{10FFFF}' = 'v'; + + // Almost exhaustive + m!(0u8, 0..255); //~ ERROR non-exhaustive patterns + m!(0u8, 0..=254); //~ ERROR non-exhaustive patterns + m!(0u8, 1..=255); //~ ERROR non-exhaustive patterns + m!(0u8, 0..42 | 43..=255); //~ ERROR non-exhaustive patterns + m!(0i8, -128..127); //~ ERROR non-exhaustive patterns + m!(0i8, -128..=126); //~ ERROR non-exhaustive patterns + m!(0i8, -127..=127); //~ ERROR non-exhaustive patterns + match 0i8 { //~ ERROR non-exhaustive patterns + i8::MIN ..= -1 => {} + 1 ..= i8::MAX => {} + } + const ALMOST_MAX: u128 = u128::MAX - 1; + m!(0u128, 0..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0u128, 0..=4); //~ ERROR non-exhaustive patterns + m!(0u128, 1..=u128::MAX); //~ ERROR non-exhaustive patterns + + // More complicatedly (non-)exhaustive + match 0u8 { + 0 ..= 30 => {} + 20 ..= 70 => {} + 50 ..= 255 => {} + } + match (0u8, true) { //~ ERROR non-exhaustive patterns + (0 ..= 125, false) => {} + (128 ..= 255, false) => {} + (0 ..= 255, true) => {} + } + match (0u8, true) { // ok + (0 ..= 125, false) => {} + (128 ..= 255, false) => {} + (0 ..= 255, true) => {} + (125 .. 128, false) => {} + } + match (true, 0u8) { + (true, 0 ..= 255) => {} + (false, 0 ..= 125) => {} + (false, 128 ..= 255) => {} + (false, 125 .. 128) => {} + } + match Some(0u8) { + None => {} + Some(0 ..= 125) => {} + Some(128 ..= 255) => {} + Some(125 .. 128) => {} + } + const FOO: u8 = 41; + const BAR: &u8 = &42; + match &0u8 { + 0..41 => {} + &FOO => {} + BAR => {} + 43..=255 => {} + } + +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr new file mode 100644 index 000000000..f30ba05df --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -0,0 +1,149 @@ +error[E0004]: non-exhaustive patterns: `u8::MAX` not covered + --> $DIR/exhaustiveness.rs:47:8 + | +LL | m!(0u8, 0..255); + | ^^^ pattern `u8::MAX` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u8::MAX` not covered + --> $DIR/exhaustiveness.rs:48:8 + | +LL | m!(0u8, 0..=254); + | ^^^ pattern `u8::MAX` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u8` not covered + --> $DIR/exhaustiveness.rs:49:8 + | +LL | m!(0u8, 1..=255); + | ^^^ pattern `0_u8` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u8 => todo!() } + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `42_u8` not covered + --> $DIR/exhaustiveness.rs:50:8 + | +LL | m!(0u8, 0..42 | 43..=255); + | ^^^ pattern `42_u8` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 42_u8 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MAX` not covered + --> $DIR/exhaustiveness.rs:51:8 + | +LL | m!(0i8, -128..127); + | ^^^ pattern `i8::MAX` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MAX` not covered + --> $DIR/exhaustiveness.rs:52:8 + | +LL | m!(0i8, -128..=126); + | ^^^ pattern `i8::MAX` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MIN` not covered + --> $DIR/exhaustiveness.rs:53:8 + | +LL | m!(0i8, -127..=127); + | ^^^ pattern `i8::MIN` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i8::MIN => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_i8` not covered + --> $DIR/exhaustiveness.rs:54:11 + | +LL | match 0i8 { + | ^^^ pattern `0_i8` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 1 ..= i8::MAX => {} +LL + 0_i8 => todo!() + | + +error[E0004]: non-exhaustive patterns: `u128::MAX` not covered + --> $DIR/exhaustiveness.rs:59:8 + | +LL | m!(0u128, 0..=ALMOST_MAX); + | ^^^^^ pattern `u128::MAX` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u128::MAX => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered + --> $DIR/exhaustiveness.rs:60:8 + | +LL | m!(0u128, 0..=4); + | ^^^^^ pattern `5_u128..=u128::MAX` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() } + | +++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u128` not covered + --> $DIR/exhaustiveness.rs:61:8 + | +LL | m!(0u128, 1..=u128::MAX); + | ^^^^^ pattern `0_u128` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u128 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered + --> $DIR/exhaustiveness.rs:69:11 + | +LL | match (0u8, true) { + | ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered + | + = note: the matched value is of type `(u8, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (0 ..= 255, true) => {} +LL + (126_u8..=127_u8, false) => todo!() + | + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs new file mode 100644 index 000000000..5ea92b070 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs @@ -0,0 +1,59 @@ +#![feature(exclusive_range_pattern)] +#![deny(overlapping_range_endpoints)] + +macro_rules! m { + ($s:expr, $t1:pat, $t2:pat) => { + match $s { + $t1 => {} + $t2 => {} + _ => {} + } + } +} + +fn main() { + m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20..=30, 31..=40); + m!(0u8, 20..=30, 29..=40); + m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20.. 30, 28..=40); + m!(0u8, 20.. 30, 30..=40); + m!(0u8, 20..=30, 30..=30); + m!(0u8, 20..=30, 30..=31); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20..=30, 29..=30); + m!(0u8, 20..=30, 20..=20); + m!(0u8, 20..=30, 20..=21); + m!(0u8, 20..=30, 19..=20); //~ ERROR multiple patterns overlap on their endpoints + m!(0u8, 20..=30, 20); + m!(0u8, 20..=30, 25); + m!(0u8, 20..=30, 30); + m!(0u8, 20.. 30, 29); + m!(0u8, 20, 20..=30); + m!(0u8, 25, 20..=30); + m!(0u8, 30, 20..=30); + + match 0u8 { + 0..=10 => {} + 20..=30 => {} + 10..=20 => {} //~ ERROR multiple patterns overlap on their endpoints + _ => {} + } + match (0u8, true) { + (0..=10, true) => {} + (10..20, true) => {} // not detected + (10..20, false) => {} + _ => {} + } + match (true, 0u8) { + (true, 0..=10) => {} + (true, 10..20) => {} //~ ERROR multiple patterns overlap on their endpoints + (false, 10..20) => {} + _ => {} + } + match Some(0u8) { + Some(0..=10) => {} + Some(10..20) => {} //~ ERROR multiple patterns overlap on their endpoints + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr new file mode 100644 index 000000000..ea0e8f6e4 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr @@ -0,0 +1,89 @@ +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:15:22 + | +LL | m!(0u8, 20..=30, 30..=40); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges +note: the lint level is defined here + --> $DIR/overlapping_range_endpoints.rs:2:9 + | +LL | #![deny(overlapping_range_endpoints)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:16:22 + | +LL | m!(0u8, 30..=40, 20..=30); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:19:22 + | +LL | m!(0u8, 20.. 30, 29..=40); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `29_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:23:22 + | +LL | m!(0u8, 20..=30, 30..=31); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `30_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:27:22 + | +LL | m!(0u8, 20..=30, 19..=20); + | ------- ^^^^^^^ ... with this range + | | + | this range overlaps on `20_u8`... + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:39:9 + | +LL | 0..=10 => {} + | ------ this range overlaps on `10_u8`... +LL | 20..=30 => {} + | ------- this range overlaps on `20_u8`... +LL | 10..=20 => {} + | ^^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:50:16 + | +LL | (true, 0..=10) => {} + | ------ this range overlaps on `10_u8`... +LL | (true, 10..20) => {} + | ^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges + +error: multiple patterns overlap on their endpoints + --> $DIR/overlapping_range_endpoints.rs:56:14 + | +LL | Some(0..=10) => {} + | ------ this range overlaps on `10_u8`... +LL | Some(10..20) => {} + | ^^^^^^ ... with this range + | + = note: you likely meant to write mutually exclusive ranges + +error: aborting due to 8 previous errors + diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr new file mode 100644 index 000000000..9f277fa1e --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/pointer-sized-int.rs:48:11 + | +LL | match 7usize {} + | ^^^^^^ + | + = note: the matched value is of type `usize` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match 7usize { +LL + _ => todo!(), +LL + } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr new file mode 100644 index 000000000..e3eb98ccd --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr @@ -0,0 +1,170 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:12:11 + | +LL | match 0usize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 0 ..= usize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:17:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ isize::MIN ..= isize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:22:8 + | +LL | m!(0usize, 0..=usize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:24:8 + | +LL | m!(0usize, 0..5 | 5..=usize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:26:8 + | +LL | m!(0usize, 0..usize::MAX | usize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/pointer-sized-int.rs:28:8 + | +LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); + | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(usize, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, (_, _) => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:31:8 + | +LL | m!(0isize, isize::MIN..=isize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:33:8 + | +LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:35:8 + | +LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/pointer-sized-int.rs:37:8 + | +LL | m!((0isize, true), (isize::MIN..5, true) + | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(isize, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, (_, _) => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/pointer-sized-int.rs:41:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 1 ..= isize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/pointer-sized-int.rs:48:11 + | +LL | match 7usize {} + | ^^^^^^ + | + = note: the matched value is of type `usize` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match 7usize { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs new file mode 100644 index 000000000..1ed18c267 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs @@ -0,0 +1,50 @@ +// revisions: allow deny +#![feature(exclusive_range_pattern)] +#![cfg_attr(allow, feature(precise_pointer_size_matching))] + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +fn main() { + match 0usize { + //[deny]~^ ERROR non-exhaustive patterns + 0 ..= usize::MAX => {} + } + + match 0isize { + //[deny]~^ ERROR non-exhaustive patterns + isize::MIN ..= isize::MAX => {} + } + + m!(0usize, 0..=usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0usize, 0..5 | 5..=usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0usize, 0..usize::MAX | usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); + //[deny]~^ ERROR non-exhaustive patterns + + m!(0isize, isize::MIN..=isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0isize, isize::MIN..5 | 5..=isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!(0isize, isize::MIN..isize::MAX | isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns + m!((0isize, true), (isize::MIN..5, true) + | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false)); + //[deny]~^^ ERROR non-exhaustive patterns + + match 0isize { + //[deny]~^ ERROR non-exhaustive patterns + isize::MIN ..= -1 => {} + 0 => {} + 1 ..= isize::MAX => {} + } + + match 7usize {} + //~^ ERROR non-exhaustive patterns +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs new file mode 100644 index 000000000..a2aa655ca --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs @@ -0,0 +1,18 @@ +// This tests that the lint message explains the reason for the error. +fn main() { + match 0usize { + //~^ ERROR non-exhaustive patterns: `_` not covered + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `usize` + //~| NOTE `usize` does not have a fixed maximum value + 0..=usize::MAX => {} + } + + match 0isize { + //~^ ERROR non-exhaustive patterns: `_` not covered + //~| NOTE pattern `_` not covered + //~| NOTE the matched value is of type `isize` + //~| NOTE `isize` does not have a fixed maximum value + isize::MIN..=isize::MAX => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr new file mode 100644 index 000000000..30492c982 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr @@ -0,0 +1,33 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/precise_pointer_matching-message.rs:3:11 + | +LL | match 0usize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 0..=usize::MAX => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/precise_pointer_matching-message.rs:11:11 + | +LL | match 0isize { + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ isize::MIN..=isize::MAX => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs new file mode 100644 index 000000000..fb4d59b05 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs @@ -0,0 +1,113 @@ +#![feature(exclusive_range_pattern)] +#![allow(overlapping_range_endpoints)] +#![deny(unreachable_patterns)] + +macro_rules! m { + ($s:expr, $t1:pat, $t2:pat) => { + match $s { + $t1 => {} + $t2 => {} + _ => {} + } + } +} + +fn main() { + m!(0u8, 42, 41); + m!(0u8, 42, 42); //~ ERROR unreachable pattern + m!(0u8, 42, 43); + + m!(0u8, 20..=30, 19); + m!(0u8, 20..=30, 20); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 21); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 25); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 29); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 31); + m!(0u8, 20..30, 19); + m!(0u8, 20..30, 20); //~ ERROR unreachable pattern + m!(0u8, 20..30, 21); //~ ERROR unreachable pattern + m!(0u8, 20..30, 25); //~ ERROR unreachable pattern + m!(0u8, 20..30, 29); //~ ERROR unreachable pattern + m!(0u8, 20..30, 30); + m!(0u8, 20..30, 31); + + m!(0u8, 20..=30, 20..=30); //~ ERROR unreachable pattern + m!(0u8, 20.. 30, 20.. 30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 20.. 30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 19..=30); + m!(0u8, 20..=30, 21..=30); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 20..=29); //~ ERROR unreachable pattern + m!(0u8, 20..=30, 20..=31); + m!('a', 'A'..='z', 'a'..='z'); //~ ERROR unreachable pattern + + match 0u8 { + 5 => {}, + 6 => {}, + 7 => {}, + 8 => {}, + 5..=8 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0u8 { + 0..10 => {}, + 10..20 => {}, + 5..15 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0u8 { + 0..10 => {}, + 10..20 => {}, + 20..30 => {}, + 5..25 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0u8 { + 0..10 => {}, + 10 => {}, + 11..=23 => {}, + 19..30 => {}, + 5..25 => {}, //~ ERROR unreachable pattern + _ => {}, + } + match 0usize { + 0..10 => {}, + 10..20 => {}, + 5..15 => {}, //~ ERROR unreachable pattern + _ => {}, + } + // Chars between '\u{D7FF}' and '\u{E000}' are invalid even though ranges that contain them are + // allowed. + match 'a' { + _ => {}, + '\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern + } + match 'a' { + '\u{0}'..='\u{D7FF}' => {}, + '\u{E000}'..='\u{10_FFFF}' => {}, + '\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable + } + + match (0u8, true) { + (0..=255, false) => {} + (0..=255, true) => {} // ok + } + match (true, 0u8) { + (false, 0..=255) => {} + (true, 0..=255) => {} // ok + } + + const FOO: i32 = 42; + const BAR: &i32 = &42; + match &0 { + &42 => {} + &FOO => {} //~ ERROR unreachable pattern + BAR => {} //~ ERROR unreachable pattern + _ => {} + } + // Regression test, see https://github.com/rust-lang/rust/pull/66326#issuecomment-552889933 + match &0 { + BAR => {} // ok + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr new file mode 100644 index 000000000..0ffb0ffd8 --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -0,0 +1,154 @@ +error: unreachable pattern + --> $DIR/reachability.rs:17:17 + | +LL | m!(0u8, 42, 42); + | ^^ + | +note: the lint level is defined here + --> $DIR/reachability.rs:3:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:21:22 + | +LL | m!(0u8, 20..=30, 20); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:22:22 + | +LL | m!(0u8, 20..=30, 21); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:23:22 + | +LL | m!(0u8, 20..=30, 25); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:24:22 + | +LL | m!(0u8, 20..=30, 29); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:25:22 + | +LL | m!(0u8, 20..=30, 30); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:28:21 + | +LL | m!(0u8, 20..30, 20); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:29:21 + | +LL | m!(0u8, 20..30, 21); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:30:21 + | +LL | m!(0u8, 20..30, 25); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:31:21 + | +LL | m!(0u8, 20..30, 29); + | ^^ + +error: unreachable pattern + --> $DIR/reachability.rs:35:22 + | +LL | m!(0u8, 20..=30, 20..=30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:36:22 + | +LL | m!(0u8, 20.. 30, 20.. 30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:37:22 + | +LL | m!(0u8, 20..=30, 20.. 30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:39:22 + | +LL | m!(0u8, 20..=30, 21..=30); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:40:22 + | +LL | m!(0u8, 20..=30, 20..=29); + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:42:24 + | +LL | m!('a', 'A'..='z', 'a'..='z'); + | ^^^^^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:49:9 + | +LL | 5..=8 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:55:9 + | +LL | 5..15 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:62:9 + | +LL | 5..25 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:70:9 + | +LL | 5..25 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:76:9 + | +LL | 5..15 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:83:9 + | +LL | _ => {}, + | - matches any value +LL | '\u{D7FF}'..='\u{E000}' => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/reachability.rs:104:9 + | +LL | &FOO => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/reachability.rs:105:9 + | +LL | BAR => {} + | ^^^ + +error: aborting due to 24 previous errors + diff --git a/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs b/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs new file mode 100644 index 000000000..d400ef0bb --- /dev/null +++ b/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(irrefutable_let_patterns)] + +fn main() { + if let _ = 5 {} + + while let _ = 5 { + break; + } +} diff --git a/tests/ui/pattern/usefulness/irrefutable-unit.rs b/tests/ui/pattern/usefulness/irrefutable-unit.rs new file mode 100644 index 000000000..dd8f03b6d --- /dev/null +++ b/tests/ui/pattern/usefulness/irrefutable-unit.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let ((),()) = ((),()); +} diff --git a/tests/ui/pattern/usefulness/issue-12116.rs b/tests/ui/pattern/usefulness/issue-12116.rs new file mode 100644 index 000000000..3cb92a540 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12116.rs @@ -0,0 +1,21 @@ +#![feature(box_patterns)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![deny(unreachable_patterns)] + + +enum IntList { + Cons(isize, Box), + Nil +} + +fn tail(source_list: &IntList) -> IntList { + match source_list { + &IntList::Cons(val, box ref next_list) => tail(next_list), + &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), + //~^ ERROR unreachable pattern + _ => panic!(), + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr new file mode 100644 index 000000000..7f15c4703 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12116.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-12116.rs:15:9 + | +LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-12116.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-12369.rs b/tests/ui/pattern/usefulness/issue-12369.rs new file mode 100644 index 000000000..0481c1fd9 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12369.rs @@ -0,0 +1,11 @@ +#![deny(unreachable_patterns)] + +fn main() { + let sl = vec![1,2,3]; + let v: isize = match &*sl { + &[] => 0, + &[a,b,c] => 3, + &[a, ref rest @ ..] => a, + &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern + }; +} diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr new file mode 100644 index 000000000..aab2be78c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-12369.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-12369.rs:9:9 + | +LL | &[10,a, ref rest @ ..] => 10 + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-12369.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-13727.rs b/tests/ui/pattern/usefulness/issue-13727.rs new file mode 100644 index 000000000..7fb565ef3 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-13727.rs @@ -0,0 +1,15 @@ +#![allow(overflowing_literals)] +#![deny(unreachable_patterns)] + +fn test(val: u8) { + match val { + 256 => print!("0b1110\n"), + 512 => print!("0b1111\n"), + //~^ ERROR: unreachable pattern + _ => print!("fail\n"), + } +} + +fn main() { + test(1); +} diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr new file mode 100644 index 000000000..07ca56a56 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-13727.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-13727.rs:7:5 + | +LL | 512 => print!("0b1111\n"), + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-13727.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-15129.rs b/tests/ui/pattern/usefulness/issue-15129.rs new file mode 100644 index 000000000..f02e5c0c6 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-15129.rs @@ -0,0 +1,17 @@ +pub enum T { + T1(()), + T2(()), +} + +pub enum V { + V1(isize), + V2(bool), +} + +fn main() { + match (T::T1(()), V::V2(true)) { + //~^ ERROR non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered + (T::T1(()), V::V1(i)) => (), + (T::T2(()), V::V2(b)) => (), + } +} diff --git a/tests/ui/pattern/usefulness/issue-15129.stderr b/tests/ui/pattern/usefulness/issue-15129.stderr new file mode 100644 index 000000000..ee8410b76 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-15129.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered + --> $DIR/issue-15129.rs:12:11 + | +LL | match (T::T1(()), V::V2(true)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered + | + = note: the matched value is of type `(T, V)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (T::T2(()), V::V2(b)) => (), +LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-2111.rs b/tests/ui/pattern/usefulness/issue-2111.rs new file mode 100644 index 000000000..d27beaeff --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-2111.rs @@ -0,0 +1,11 @@ +fn foo(a: Option, b: Option) { + match (a, b) { + //~^ ERROR: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered + (Some(a), Some(b)) if a == b => {} + (Some(_), None) | (None, Some(_)) => {} + } +} + +fn main() { + foo(None, None); +} diff --git a/tests/ui/pattern/usefulness/issue-2111.stderr b/tests/ui/pattern/usefulness/issue-2111.stderr new file mode 100644 index 000000000..01890b73c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-2111.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered + --> $DIR/issue-2111.rs:2:11 + | +LL | match (a, b) { + | ^^^^^^ patterns `(None, None)` and `(Some(_), Some(_))` not covered + | + = note: the matched value is of type `(Option, Option)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (Some(_), None) | (None, Some(_)) => {} +LL + (None, None) | (Some(_), Some(_)) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-30240-b.rs b/tests/ui/pattern/usefulness/issue-30240-b.rs new file mode 100644 index 000000000..01a6e7d8c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240-b.rs @@ -0,0 +1,15 @@ +#![deny(unreachable_patterns)] + +fn main() { + match "world" { + "hello" => {} + _ => {}, + } + + match "world" { + ref _x if false => {} + "hello" => {} + "hello" => {} //~ ERROR unreachable pattern + _ => {}, + } +} diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr new file mode 100644 index 000000000..59d64bc25 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-30240-b.rs:12:9 + | +LL | "hello" => {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-30240-b.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/issue-30240-rpass.rs b/tests/ui/pattern/usefulness/issue-30240-rpass.rs new file mode 100644 index 000000000..ab16614fd --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240-rpass.rs @@ -0,0 +1,14 @@ +// run-pass +fn main() { + let &ref a = &[0i32] as &[_]; + assert_eq!(a, &[0i32] as &[_]); + + let &ref a = "hello"; + assert_eq!(a, "hello"); + + match "foo" { + "fool" => unreachable!(), + "foo" => {}, + ref _x => unreachable!() + } +} diff --git a/tests/ui/pattern/usefulness/issue-30240.rs b/tests/ui/pattern/usefulness/issue-30240.rs new file mode 100644 index 000000000..a0c0d1626 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240.rs @@ -0,0 +1,10 @@ +fn main() { + match "world" { //~ ERROR non-exhaustive patterns: `&_` + "hello" => {} + } + + match "world" { //~ ERROR non-exhaustive patterns: `&_` + ref _x if false => {} + "hello" => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr new file mode 100644 index 000000000..759fdeafe --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-30240.stderr @@ -0,0 +1,29 @@ +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/issue-30240.rs:2:11 + | +LL | match "world" { + | ^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&str` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ "hello" => {} +LL + &_ => todo!() + | + +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/issue-30240.rs:6:11 + | +LL | match "world" { + | ^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&str` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ "hello" => {} +LL + &_ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3096-1.rs b/tests/ui/pattern/usefulness/issue-3096-1.rs new file mode 100644 index 000000000..edc3b3223 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-1.rs @@ -0,0 +1,3 @@ +fn main() { + match () { } //~ ERROR non-exhaustive +} diff --git a/tests/ui/pattern/usefulness/issue-3096-1.stderr b/tests/ui/pattern/usefulness/issue-3096-1.stderr new file mode 100644 index 000000000..d8884394f --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-1.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `()` is non-empty + --> $DIR/issue-3096-1.rs:2:11 + | +LL | match () { } + | ^^ + | + = note: the matched value is of type `()` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match () { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3096-2.rs b/tests/ui/pattern/usefulness/issue-3096-2.rs new file mode 100644 index 000000000..a26e42580 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-2.rs @@ -0,0 +1,6 @@ +enum Bottom { } + +fn main() { + let x = &() as *const () as *const Bottom; + match x { } //~ ERROR non-exhaustive patterns +} diff --git a/tests/ui/pattern/usefulness/issue-3096-2.stderr b/tests/ui/pattern/usefulness/issue-3096-2.stderr new file mode 100644 index 000000000..2df8911ba --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3096-2.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty + --> $DIR/issue-3096-2.rs:5:11 + | +LL | match x { } + | ^ + | + = note: the matched value is of type `*const Bottom` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-31221.rs b/tests/ui/pattern/usefulness/issue-31221.rs new file mode 100644 index 000000000..e03f1ec5b --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31221.rs @@ -0,0 +1,34 @@ +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_snake_case)] +#![deny(unreachable_patterns)] + +#[derive(Clone, Copy)] +enum Enum { + Var1, + Var2, +} + +fn main() { + use Enum::*; + let s = Var1; + match s { + Var1 => (), + Var3 => (), + Var2 => (), + //~^ ERROR unreachable pattern + }; + match &s { + &Var1 => (), + &Var3 => (), + &Var2 => (), + //~^ ERROR unreachable pattern + }; + let t = (Var1, Var1); + match t { + (Var1, b) => (), + (c, d) => (), + anything => () + //~^ ERROR unreachable pattern + }; +} diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr new file mode 100644 index 000000000..7d3491444 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31221.stderr @@ -0,0 +1,32 @@ +error: unreachable pattern + --> $DIR/issue-31221.rs:18:9 + | +LL | Var3 => (), + | ---- matches any value +LL | Var2 => (), + | ^^^^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/issue-31221.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/issue-31221.rs:24:9 + | +LL | &Var3 => (), + | ----- matches any value +LL | &Var2 => (), + | ^^^^^ unreachable pattern + +error: unreachable pattern + --> $DIR/issue-31221.rs:31:9 + | +LL | (c, d) => (), + | ------ matches any value +LL | anything => () + | ^^^^^^^^ unreachable pattern + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/issue-31561.rs b/tests/ui/pattern/usefulness/issue-31561.rs new file mode 100644 index 000000000..82414f041 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31561.rs @@ -0,0 +1,11 @@ +enum Thing { + Foo(u8), + Bar, + Baz +} + +fn main() { + let Thing::Foo(y) = Thing::Foo(1); + //~^ ERROR refutable pattern in local binding + //~| `Thing::Bar` and `Thing::Baz` not covered +} diff --git a/tests/ui/pattern/usefulness/issue-31561.stderr b/tests/ui/pattern/usefulness/issue-31561.stderr new file mode 100644 index 000000000..5367de5e5 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-31561.stderr @@ -0,0 +1,27 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/issue-31561.rs:8:9 + | +LL | let Thing::Foo(y) = Thing::Foo(1); + | ^^^^^^^^^^^^^ patterns `Thing::Bar` and `Thing::Baz` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Thing` defined here + --> $DIR/issue-31561.rs:1:6 + | +LL | enum Thing { + | ^^^^^ +LL | Foo(u8), +LL | Bar, + | --- not covered +LL | Baz + | --- not covered + = note: the matched value is of type `Thing` +help: you might want to use `let else` to handle the variants that aren't matched + | +LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/issue-35609.rs b/tests/ui/pattern/usefulness/issue-35609.rs new file mode 100644 index 000000000..8ef75e351 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-35609.rs @@ -0,0 +1,43 @@ +enum Enum { + A, B, C, D, E, F +} +use Enum::*; + +struct S(Enum, ()); +struct Sd { x: Enum, y: () } + +fn main() { + match (A, ()) { //~ ERROR non-exhaustive + (A, _) => {} + } + + match (A, A) { //~ ERROR non-exhaustive + (_, A) => {} + } + + match ((A, ()), ()) { //~ ERROR non-exhaustive + ((A, ()), _) => {} + } + + match ((A, ()), A) { //~ ERROR non-exhaustive + ((A, ()), _) => {} + } + + match ((A, ()), ()) { //~ ERROR non-exhaustive + ((A, _), _) => {} + } + + + match S(A, ()) { //~ ERROR non-exhaustive + S(A, _) => {} + } + + match (Sd { x: A, y: () }) { //~ ERROR non-exhaustive + Sd { x: A, y: _ } => {} + } + + match Some(A) { //~ ERROR non-exhaustive + Some(A) => (), + None => () + } +} diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr new file mode 100644 index 000000000..12113957d --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-35609.stderr @@ -0,0 +1,119 @@ +error[E0004]: non-exhaustive patterns: `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered + --> $DIR/issue-35609.rs:10:11 + | +LL | match (A, ()) { + | ^^^^^^^ patterns `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered + | + = note: the matched value is of type `(Enum, ())` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ (A, _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered + --> $DIR/issue-35609.rs:14:11 + | +LL | match (A, A) { + | ^^^^^^ patterns `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered + | + = note: the matched value is of type `(Enum, Enum)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ (_, A) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + --> $DIR/issue-35609.rs:18:11 + | +LL | match ((A, ()), ()) { + | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + | + = note: the matched value is of type `((Enum, ()), ())` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ((A, ()), _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + --> $DIR/issue-35609.rs:22:11 + | +LL | match ((A, ()), A) { + | ^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + | + = note: the matched value is of type `((Enum, ()), Enum)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ((A, ()), _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + --> $DIR/issue-35609.rs:26:11 + | +LL | match ((A, ()), ()) { + | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered + | + = note: the matched value is of type `((Enum, ()), ())` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ((A, _), _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered + --> $DIR/issue-35609.rs:31:11 + | +LL | match S(A, ()) { + | ^^^^^^^^ patterns `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered + | +note: `S` defined here + --> $DIR/issue-35609.rs:6:8 + | +LL | struct S(Enum, ()); + | ^ + = note: the matched value is of type `S` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ S(A, _) => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered + --> $DIR/issue-35609.rs:35:11 + | +LL | match (Sd { x: A, y: () }) { + | ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered + | +note: `Sd` defined here + --> $DIR/issue-35609.rs:7:8 + | +LL | struct Sd { x: Enum, y: () } + | ^^ + = note: the matched value is of type `Sd` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ Sd { x: A, y: _ } => {} +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered + --> $DIR/issue-35609.rs:39:11 + | +LL | match Some(A) { + | ^^^^^^^ patterns `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ None => (), +LL + _ => todo!() + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-3601.rs b/tests/ui/pattern/usefulness/issue-3601.rs new file mode 100644 index 000000000..6215a2398 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3601.rs @@ -0,0 +1,34 @@ +#![feature(box_patterns)] + +struct HTMLImageData { + image: Option +} + +struct ElementData { + kind: Box +} + +enum ElementKind { + HTMLImageElement(HTMLImageData) +} + +enum NodeKind { + Element(ElementData) +} + +struct NodeData { + kind: Box, +} + +fn main() { + let mut id = HTMLImageData { image: None }; + let ed = ElementData { kind: Box::new(ElementKind::HTMLImageElement(id)) }; + let n = NodeData { kind: Box::new(NodeKind::Element(ed)) }; + + // n.b. span could be better + match n.kind { + box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns + box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true } + }, + }; +} diff --git a/tests/ui/pattern/usefulness/issue-3601.stderr b/tests/ui/pattern/usefulness/issue-3601.stderr new file mode 100644 index 000000000..59d7bcd4b --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-3601.stderr @@ -0,0 +1,18 @@ +error[E0004]: non-exhaustive patterns: `box _` not covered + --> $DIR/issue-3601.rs:30:44 + | +LL | box NodeKind::Element(ed) => match ed.kind { + | ^^^^^^^ pattern `box _` not covered + | +note: `Box` defined here + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + = note: the matched value is of type `Box` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true } +LL + box _ => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-39362.rs b/tests/ui/pattern/usefulness/issue-39362.rs new file mode 100644 index 000000000..ea3c8f88e --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-39362.rs @@ -0,0 +1,18 @@ +enum Foo { + Bar { bar: Bar, id: usize } +} + +enum Bar { + A, B, C, D, E, F +} + +fn test(f: Foo) { + match f { + //~^ ERROR non-exhaustive patterns + //~| patterns + Foo::Bar { bar: Bar::A, .. } => (), + Foo::Bar { bar: Bar::B, .. } => (), + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr new file mode 100644 index 000000000..b8b17918a --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-39362.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered + --> $DIR/issue-39362.rs:10:11 + | +LL | match f { + | ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered + | +note: `Foo` defined here + --> $DIR/issue-39362.rs:2:5 + | +LL | enum Foo { + | --- +LL | Bar { bar: Bar, id: usize } + | ^^^ not covered + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ Foo::Bar { bar: Bar::B, .. } => (), +LL ~ _ => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-40221.rs b/tests/ui/pattern/usefulness/issue-40221.rs new file mode 100644 index 000000000..e1f7e975b --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-40221.rs @@ -0,0 +1,16 @@ +enum P { + C(PC), +} + +enum PC { + Q, + QA, +} + +fn test(proto: P) { + match proto { //~ ERROR non-exhaustive patterns + P::C(PC::Q) => (), + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr new file mode 100644 index 000000000..4973e42b0 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-40221.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `P::C(PC::QA)` not covered + --> $DIR/issue-40221.rs:11:11 + | +LL | match proto { + | ^^^^^ pattern `P::C(PC::QA)` not covered + | +note: `P` defined here + --> $DIR/issue-40221.rs:2:5 + | +LL | enum P { + | - +LL | C(PC), + | ^ not covered + = note: the matched value is of type `P` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ P::C(PC::Q) => (), +LL ~ P::C(PC::QA) => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-4321.rs b/tests/ui/pattern/usefulness/issue-4321.rs new file mode 100644 index 000000000..9715f2eba --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-4321.rs @@ -0,0 +1,8 @@ +fn main() { + let tup = (true, true); + println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered + (false, false) => "foo", + (false, true) => "bar", + (true, true) => "baz" + }); +} diff --git a/tests/ui/pattern/usefulness/issue-4321.stderr b/tests/ui/pattern/usefulness/issue-4321.stderr new file mode 100644 index 000000000..293273174 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-4321.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(true, false)` not covered + --> $DIR/issue-4321.rs:3:31 + | +LL | println!("foo {:}", match tup { + | ^^^ pattern `(true, false)` not covered + | + = note: the matched value is of type `(bool, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (true, true) => "baz", +LL + (true, false) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-50900.rs b/tests/ui/pattern/usefulness/issue-50900.rs new file mode 100644 index 000000000..9cc760e9a --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-50900.rs @@ -0,0 +1,19 @@ +#[derive(PartialEq, Eq)] +pub struct Tag(pub Context, pub u16); + +#[derive(PartialEq, Eq)] +pub enum Context { + Tiff, + Exif, +} + +impl Tag { + const ExifIFDPointer: Tag = Tag(Context::Tiff, 34665); +} + +fn main() { + match Tag::ExifIFDPointer { + //~^ ERROR: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered + Tag::ExifIFDPointer => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-50900.stderr b/tests/ui/pattern/usefulness/issue-50900.stderr new file mode 100644 index 000000000..348246d28 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-50900.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered + --> $DIR/issue-50900.rs:15:11 + | +LL | match Tag::ExifIFDPointer { + | ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Context::Exif, _)` not covered + | +note: `Tag` defined here + --> $DIR/issue-50900.rs:2:12 + | +LL | pub struct Tag(pub Context, pub u16); + | ^^^ + = note: the matched value is of type `Tag` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Tag::ExifIFDPointer => {} +LL + Tag(Context::Exif, _) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs b/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs new file mode 100644 index 000000000..5b0482de2 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs @@ -0,0 +1,11 @@ +// check-pass + +// This used to cause a stack overflow during exhaustiveness checking in the compiler. + +fn main() { + const LARGE_SIZE: usize = 1024 * 1024; + let [..] = [0u8; LARGE_SIZE]; + match [0u8; LARGE_SIZE] { + [..] => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-56379.rs b/tests/ui/pattern/usefulness/issue-56379.rs new file mode 100644 index 000000000..097cf98d0 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-56379.rs @@ -0,0 +1,14 @@ +enum Foo { + A(bool), + B(bool), + C(bool), +} + +fn main() { + match Foo::A(true) { + //~^ ERROR non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered + Foo::A(true) => {} + Foo::B(true) => {} + Foo::C(true) => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr new file mode 100644 index 000000000..6eed6bfae --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-56379.stderr @@ -0,0 +1,27 @@ +error[E0004]: non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered + --> $DIR/issue-56379.rs:8:11 + | +LL | match Foo::A(true) { + | ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered + | +note: `Foo` defined here + --> $DIR/issue-56379.rs:2:5 + | +LL | enum Foo { + | --- +LL | A(bool), + | ^ not covered +LL | B(bool), + | ^ not covered +LL | C(bool), + | ^ not covered + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Foo::C(true) => {} +LL + Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-57472.rs b/tests/ui/pattern/usefulness/issue-57472.rs new file mode 100644 index 000000000..113100637 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-57472.rs @@ -0,0 +1,35 @@ +#![crate_type="lib"] +#![deny(unreachable_patterns)] + +mod test_struct { + // Test the exact copy of the minimal example + // posted in the issue. + pub struct Punned { + foo: [u8; 1], + bar: [u8; 1], + } + + pub fn test(punned: Punned) { + match punned { + Punned { foo: [_], .. } => println!("foo"), + Punned { bar: [_], .. } => println!("bar"), + //~^ ERROR unreachable pattern [unreachable_patterns] + } + } +} + +mod test_union { + // Test the same thing using a union. + pub union Punned { + foo: [u8; 1], + bar: [u8; 1], + } + + pub fn test(punned: Punned) { + match punned { + Punned { foo: [_] } => println!("foo"), + Punned { bar: [_] } => println!("bar"), + //~^ ERROR unreachable pattern [unreachable_patterns] + } + } +} diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr new file mode 100644 index 000000000..26efdf6db --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-57472.stderr @@ -0,0 +1,20 @@ +error: unreachable pattern + --> $DIR/issue-57472.rs:15:13 + | +LL | Punned { bar: [_], .. } => println!("bar"), + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-57472.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/issue-57472.rs:31:13 + | +LL | Punned { bar: [_] } => println!("bar"), + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs b/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs new file mode 100644 index 000000000..54dfa889e --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs @@ -0,0 +1,15 @@ +// check-pass + +#![deny(unreachable_patterns)] + +const C0: &'static [u8] = b"\x00"; + +fn main() { + let x: &[u8] = &[0]; + match x { + &[] => {} + &[1..=255] => {} + C0 => {} + &[_, _, ..] => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-66501.rs b/tests/ui/pattern/usefulness/issue-66501.rs new file mode 100644 index 000000000..ffcfd4ad8 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-66501.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(unreachable_patterns)] + +fn main() { + const CONST: &[Option<()>; 1] = &[Some(())]; + match &[Some(())] { + &[None] => {} + CONST => {} + &[Some(())] => {} + } +} diff --git a/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs b/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs new file mode 100644 index 000000000..e2ff9ac87 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs @@ -0,0 +1,22 @@ +// check-pass + +// In PR 71930, it was discovered that the code to retrieve the inferred type of a match scrutinee +// was incorrect. + +fn f() -> ! { + panic!() +} + +fn g() -> usize { + match f() { // Should infer type `bool` + false => 0, + true => 1, + } +} + +fn h() -> usize { + match f() { // Should infer type `!` + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-72377.rs b/tests/ui/pattern/usefulness/issue-72377.rs new file mode 100644 index 000000000..b5ad3075c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-72377.rs @@ -0,0 +1,17 @@ +#[derive(PartialEq, Eq)] +enum X { A, B, C, } + +fn main() { + let x = X::A; + let y = Some(X::A); + + match (x, y) { + //~^ ERROR non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 + //~| more not covered + (_, None) => false, + (v, Some(w)) if v == w => true, + (X::B, Some(X::C)) => false, + (X::B, Some(X::A)) => false, + (X::A, Some(X::C)) | (X::C, Some(X::A)) => false, + }; +} diff --git a/tests/ui/pattern/usefulness/issue-72377.stderr b/tests/ui/pattern/usefulness/issue-72377.stderr new file mode 100644 index 000000000..123dd051d --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-72377.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered + --> $DIR/issue-72377.rs:8:11 + | +LL | match (x, y) { + | ^^^^^^ patterns `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered + | + = note: the matched value is of type `(X, Option)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false, +LL ~ _ => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs b/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs new file mode 100644 index 000000000..058f41967 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs @@ -0,0 +1,56 @@ +// check-pass + +// From https://github.com/rust-lang/rust/issues/72476 +// and https://github.com/rust-lang/rust/issues/89393 + +trait Trait { + type Projection; +} + +struct A; +impl Trait for A { + type Projection = bool; +} + +struct B; +impl Trait for B { + type Projection = (u32, u32); +} + +struct Next(T::Projection); + +fn foo1(item: Next) { + match item { + Next(true) => {} + Next(false) => {} + } +} + +fn foo2(x: ::Projection) { + match x { + true => {} + false => {} + } +} + +fn foo3(x: Next) { + let Next((_, _)) = x; + match x { + Next((_, _)) => {} + } +} + +fn foo4(x: ::Projection) { + let (_, _) = x; + match x { + (_, _) => {} + } +} + +fn foo5(x: ::Projection) { + match x { + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs new file mode 100644 index 000000000..cbfcf0eaf --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs @@ -0,0 +1,12 @@ +enum A {} + //~^ NOTE `A` defined here + //~| NOTE + +fn f(a: &A) { + match a {} + //~^ ERROR non-exhaustive patterns: type `&A` is non-empty + //~| NOTE the matched value is of type `&A` + //~| NOTE references are always considered inhabited +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr new file mode 100644 index 000000000..bf05d616d --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: type `&A` is non-empty + --> $DIR/issue-78123-non-exhaustive-reference.rs:6:11 + | +LL | match a {} + | ^ + | +note: `A` defined here + --> $DIR/issue-78123-non-exhaustive-reference.rs:1:6 + | +LL | enum A {} + | ^ + = note: the matched value is of type `&A` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match a { +LL + _ => todo!(), +LL + } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs b/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs new file mode 100644 index 000000000..2879caf2c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs @@ -0,0 +1,25 @@ +// check-pass +// From https://github.com/rust-lang/rust/issues/78549 + +fn main() { + match "foo" { + "foo" => {}, + &_ => {}, + } + + match "foo" { + &_ => {}, + "foo" => {}, + } + + match ("foo", 0, "bar") { + (&_, 0, &_) => {}, + ("foo", _, "bar") => {}, + (&_, _, &_) => {}, + } + + match (&"foo", "bar") { + (&"foo", &_) => {}, + (&&_, &_) => {}, + } +} diff --git a/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs b/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs new file mode 100644 index 000000000..aac7d7d53 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs @@ -0,0 +1,27 @@ +// check-pass +#![deny(unreachable_patterns)] +pub enum TypeCtor { + Slice, + Array, +} + +pub struct ApplicationTy(TypeCtor); + +macro_rules! ty_app { + ($ctor:pat) => { + ApplicationTy($ctor) + }; +} + +fn _foo(ty: ApplicationTy) { + match ty { + ty_app!(TypeCtor::Array) | ty_app!(TypeCtor::Slice) => {} + } + + // same as above, with the macro expanded + match ty { + ApplicationTy(TypeCtor::Array) | ApplicationTy(TypeCtor::Slice) => {} + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs new file mode 100644 index 000000000..c1bfcc734 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs @@ -0,0 +1,6 @@ +// This used to ICE in exhaustiveness checking. Explanation here: +// https://github.com/rust-lang/rust/issues/82772#issuecomment-905946768 +fn main() { + let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of + let Box { .. }: Box<()>; +} diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr new file mode 100644 index 000000000..2c8c85bb1 --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `1` of struct `Box` is private + --> $DIR/issue-82772-match-box-as-struct.rs:4:15 + | +LL | let Box { 1: _, .. }: Box<()>; + | ^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/pattern/usefulness/issue-88747.rs b/tests/ui/pattern/usefulness/issue-88747.rs new file mode 100644 index 000000000..948c99f9c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-88747.rs @@ -0,0 +1,14 @@ +// check-pass: this used to be a stack overflow because of recursion in `usefulness.rs` + +macro_rules! long_tuple_arg { + ([$($t:tt)*]#$($h:tt)*) => { + long_tuple_arg!{[$($t)*$($t)*]$($h)*} + }; + ([$([$t:tt $y:tt])*]) => { + pub fn _f(($($t,)*): ($($y,)*)) {} + } +} + +long_tuple_arg!{[[_ u8]]########## ###} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/match-arm-statics-2.rs b/tests/ui/pattern/usefulness/match-arm-statics-2.rs new file mode 100644 index 000000000..3c9c16561 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics-2.rs @@ -0,0 +1,62 @@ +use self::Direction::{North, East, South, West}; + +#[derive(PartialEq, Eq)] +struct NewBool(bool); + +#[derive(PartialEq, Eq)] +enum Direction { + North, + East, + South, + West +} + +const TRUE_TRUE: (bool, bool) = (true, true); + +fn nonexhaustive_1() { + match (true, false) { + //~^ ERROR non-exhaustive patterns: `(true, false)` not covered + TRUE_TRUE => (), + (false, false) => (), + (false, true) => () + } +} + +const NONE: Option = None; +const EAST: Direction = East; + +fn nonexhaustive_2() { + match Some(Some(North)) { + //~^ ERROR non-exhaustive patterns: `Some(Some(Direction::West))` not covered + Some(NONE) => (), + Some(Some(North)) => (), + Some(Some(EAST)) => (), + Some(Some(South)) => (), + None => () + } +} + +const NEW_FALSE: NewBool = NewBool(false); +struct Foo { + bar: Option, + baz: NewBool +} + +const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE }; + +fn nonexhaustive_3() { + match (Foo { bar: Some(North), baz: NewBool(true) }) { + //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` + Foo { bar: None, baz: NewBool(true) } => (), + Foo { bar: _, baz: NEW_FALSE } => (), + Foo { bar: Some(West), baz: NewBool(true) } => (), + Foo { bar: Some(South), .. } => (), + Foo { bar: Some(EAST), .. } => () + } +} + +fn main() { + nonexhaustive_1(); + nonexhaustive_2(); + nonexhaustive_3(); +} diff --git a/tests/ui/pattern/usefulness/match-arm-statics-2.stderr b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr new file mode 100644 index 000000000..e4dd35a59 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -0,0 +1,54 @@ +error[E0004]: non-exhaustive patterns: `(true, false)` not covered + --> $DIR/match-arm-statics-2.rs:17:11 + | +LL | match (true, false) { + | ^^^^^^^^^^^^^ pattern `(true, false)` not covered + | + = note: the matched value is of type `(bool, bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (false, true) => (), +LL + (true, false) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(Some(Direction::West))` not covered + --> $DIR/match-arm-statics-2.rs:29:11 + | +LL | match Some(Some(North)) { + | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(Direction::West))` not covered + | +note: `Option>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + | + = note: not covered + = note: the matched value is of type `Option>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => (), +LL + Some(Some(Direction::West)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered + --> $DIR/match-arm-statics-2.rs:48:11 + | +LL | match (Foo { bar: Some(North), baz: NewBool(true) }) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered + | +note: `Foo` defined here + --> $DIR/match-arm-statics-2.rs:40:8 + | +LL | struct Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Foo { bar: Some(EAST), .. } => (), +LL + Foo { bar: Some(Direction::North), baz: NewBool(true) } => todo!() + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-arm-statics.rs b/tests/ui/pattern/usefulness/match-arm-statics.rs new file mode 100644 index 000000000..91db76ebb --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics.rs @@ -0,0 +1,69 @@ +#![allow(dead_code)] +#![deny(unreachable_patterns)] + +use self::Direction::{North, East, South, West}; + +#[derive(PartialEq, Eq)] +struct NewBool(bool); + +#[derive(PartialEq, Eq)] +enum Direction { + North, + East, + South, + West +} + +const TRUE_TRUE: (bool, bool) = (true, true); + +fn unreachable_1() { + match (true, false) { + TRUE_TRUE => (), + (false, false) => (), + (false, true) => (), + (true, false) => (), + (true, true) => () + //~^ ERROR unreachable pattern + } +} + +const NONE: Option = None; +const EAST: Direction = East; + +fn unreachable_2() { + match Some(Some(North)) { + Some(NONE) => (), + Some(Some(North)) => (), + Some(Some(EAST)) => (), + Some(Some(South)) => (), + Some(Some(West)) => (), + Some(Some(East)) => (), + //~^ ERROR unreachable pattern + None => () + } +} + +const NEW_FALSE: NewBool = NewBool(false); +struct Foo { + bar: Option, + baz: NewBool +} + +fn unreachable_3() { + match (Foo { bar: Some(EAST), baz: NewBool(true) }) { + Foo { bar: None, baz: NewBool(true) } => (), + Foo { bar: _, baz: NEW_FALSE } => (), + Foo { bar: Some(West), baz: NewBool(true) } => (), + Foo { bar: Some(South), .. } => (), + Foo { bar: Some(EAST), .. } => (), + Foo { bar: Some(North), baz: NewBool(true) } => (), + Foo { bar: Some(EAST), baz: NewBool(false) } => () + //~^ ERROR unreachable pattern + } +} + +fn main() { + unreachable_1(); + unreachable_2(); + unreachable_3(); +} diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr new file mode 100644 index 000000000..a5dffebf6 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr @@ -0,0 +1,26 @@ +error: unreachable pattern + --> $DIR/match-arm-statics.rs:25:9 + | +LL | (true, true) => () + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-arm-statics.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-arm-statics.rs:40:9 + | +LL | Some(Some(East)) => (), + | ^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-arm-statics.rs:60:9 + | +LL | Foo { bar: Some(EAST), baz: NewBool(false) } => () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs new file mode 100644 index 000000000..33468d03f --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs @@ -0,0 +1,13 @@ +fn main() { + let buf = &[0, 1, 2, 3]; + + match buf { //~ ERROR non-exhaustive + b"AAAA" => {} + } + + let buf: &[u8] = buf; + + match buf { //~ ERROR non-exhaustive + b"AAAA" => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr new file mode 100644 index 000000000..a90f32f7a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr @@ -0,0 +1,29 @@ +error[E0004]: non-exhaustive patterns: `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered + --> $DIR/match-byte-array-patterns-2.rs:4:11 + | +LL | match buf { + | ^^^ patterns `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered + | + = note: the matched value is of type `&[u8; 4]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ b"AAAA" => {} +LL + &[0_u8..=64_u8, _, _, _] | &[66_u8..=u8::MAX, _, _, _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered + --> $DIR/match-byte-array-patterns-2.rs:10:11 + | +LL | match buf { + | ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered + | + = note: the matched value is of type `&[u8]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ b"AAAA" => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.rs b/tests/ui/pattern/usefulness/match-byte-array-patterns.rs new file mode 100644 index 000000000..9b6c8bd55 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.rs @@ -0,0 +1,55 @@ +#![deny(unreachable_patterns)] + +fn main() { + let buf = &[0, 1, 2, 3]; + + match buf { + b"AAAA" => {}, + &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, 0x41, 0x41, 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[_, 0x41, 0x41, 0x41] => {}, + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, .., 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + let buf: &[u8] = buf; + + match buf { + b"AAAA" => {}, + &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, 0x41, 0x41, 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[_, 0x41, 0x41, 0x41] => {}, + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } + + match buf { + &[0x41, .., 0x41] => {} + b"AAAA" => {}, //~ ERROR unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr new file mode 100644 index 000000000..0c582be8d --- /dev/null +++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr @@ -0,0 +1,56 @@ +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:8:9 + | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-byte-array-patterns.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:14:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:20:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:26:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:34:9 + | +LL | &[0x41, 0x41, 0x41, 0x41] => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:40:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:46:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-byte-array-patterns.rs:52:9 + | +LL | b"AAAA" => {}, + | ^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.rs b/tests/ui/pattern/usefulness/match-non-exhaustive.rs new file mode 100644 index 000000000..3b210a115 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-non-exhaustive.rs @@ -0,0 +1,4 @@ +fn main() { + match 0 { 1 => () } //~ ERROR non-exhaustive patterns + match 0 { 0 if false => () } //~ ERROR non-exhaustive patterns +} diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.stderr b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr new file mode 100644 index 000000000..08dde523a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr @@ -0,0 +1,27 @@ +error[E0004]: non-exhaustive patterns: `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered + --> $DIR/match-non-exhaustive.rs:2:11 + | +LL | match 0 { 1 => () } + | ^ patterns `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL | match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() } + | ++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match-non-exhaustive.rs:3:11 + | +LL | match 0 { 0 if false => () } + | ^ pattern `_` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match 0 { 0 if false => (), _ => todo!() } + | ++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs new file mode 100644 index 000000000..315eb03d1 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.rs @@ -0,0 +1,21 @@ +#![feature(never_type)] +#![feature(exhaustive_patterns)] + +mod private { + pub struct Private { + _bot: !, + pub misc: bool, + } + pub const DATA: Option = None; +} + +fn main() { + match private::DATA { + //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + None => {} + Some(private::Private { + misc: false, + .. + }) => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.stderr new file mode 100644 index 000000000..86f75d15c --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + --> $DIR/match-privately-empty.rs:13:11 + | +LL | match private::DATA { + | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ }) => {} +LL + Some(Private { misc: true, .. }) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-ref-ice.rs b/tests/ui/pattern/usefulness/match-ref-ice.rs new file mode 100644 index 000000000..dee110f96 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-ref-ice.rs @@ -0,0 +1,16 @@ +#![deny(unreachable_patterns)] + +// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose +// arity is always 0, an ICE occurs. +// +// Related issue: #23009 + +fn main() { + let homura = [1, 2, 3]; + + match homura { + [1, ref _madoka, 3] => (), + [1, 2, 3] => (), //~ ERROR unreachable pattern + [_, _, _] => (), + } +} diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr new file mode 100644 index 000000000..fad0940ba --- /dev/null +++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/match-ref-ice.rs:13:9 + | +LL | [1, 2, 3] => (), + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-ref-ice.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.rs b/tests/ui/pattern/usefulness/match-slice-patterns.rs new file mode 100644 index 000000000..92d74b8c2 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-slice-patterns.rs @@ -0,0 +1,12 @@ +fn check(list: &[Option<()>]) { + match list { + //~^ ERROR `&[_, Some(_), .., None, _]` not covered + &[] => {}, + &[_] => {}, + &[_, _] => {}, + &[_, None, ..] => {}, + &[.., Some(_), _] => {}, + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.stderr b/tests/ui/pattern/usefulness/match-slice-patterns.stderr new file mode 100644 index 000000000..961dd5901 --- /dev/null +++ b/tests/ui/pattern/usefulness/match-slice-patterns.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered + --> $DIR/match-slice-patterns.rs:2:11 + | +LL | match list { + | ^^^^ pattern `&[_, Some(_), .., None, _]` not covered + | + = note: the matched value is of type `&[Option<()>]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[.., Some(_), _] => {} +LL ~ &[_, Some(_), .., None, _] => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.rs b/tests/ui/pattern/usefulness/match-vec-fixed.rs new file mode 100644 index 000000000..e611779de --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-fixed.rs @@ -0,0 +1,18 @@ +#![deny(unreachable_patterns)] + +fn a() { + let v = [1, 2, 3]; + match v { + [_, _, _] => {} + [_, _, _] => {} //~ ERROR unreachable pattern + } + match v { + [_, 1, _] => {} + [_, 1, _] => {} //~ ERROR unreachable pattern + _ => {} + } +} + +fn main() { + a(); +} diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr new file mode 100644 index 000000000..e388a06cb --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr @@ -0,0 +1,20 @@ +error: unreachable pattern + --> $DIR/match-vec-fixed.rs:7:9 + | +LL | [_, _, _] => {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-vec-fixed.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-vec-fixed.rs:11:9 + | +LL | [_, 1, _] => {} + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.rs b/tests/ui/pattern/usefulness/match-vec-unreachable.rs new file mode 100644 index 000000000..3342389be --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.rs @@ -0,0 +1,29 @@ +#![deny(unreachable_patterns)] + +fn main() { + let x: Vec<(isize, isize)> = Vec::new(); + let x: &[(isize, isize)] = &x; + match *x { + [a, (2, 3), _] => (), + [(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern + _ => () + } + + let x: Vec = vec!["foo".to_string(), + "bar".to_string(), + "baz".to_string()]; + let x: &[String] = &x; + match *x { + [ref a, _, _, ..] => { println!("{}", a); } + [_, _, _, _, _] => { } //~ ERROR unreachable pattern + _ => { } + } + + let x: Vec = vec!['a', 'b', 'c']; + let x: &[char] = &x; + match *x { + ['a', 'b', 'c', ref _tail @ ..] => {} + ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr new file mode 100644 index 000000000..672fd92fb --- /dev/null +++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr @@ -0,0 +1,26 @@ +error: unreachable pattern + --> $DIR/match-vec-unreachable.rs:8:9 + | +LL | [(1, 2), (2, 3), b] => (), + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/match-vec-unreachable.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-vec-unreachable.rs:18:9 + | +LL | [_, _, _, _, _] => { } + | ^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-vec-unreachable.rs:26:9 + | +LL | ['a', 'b', 'c'] => {} + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/pattern/usefulness/nested-exhaustive-match.rs b/tests/ui/pattern/usefulness/nested-exhaustive-match.rs new file mode 100644 index 000000000..8b2294f84 --- /dev/null +++ b/tests/ui/pattern/usefulness/nested-exhaustive-match.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Foo { foo: bool, bar: Option, baz: isize } + +pub fn main() { + match (Foo{foo: true, bar: Some(10), baz: 20}) { + Foo{foo: true, bar: Some(_), ..} => {} + Foo{foo: false, bar: None, ..} => {} + Foo{foo: true, bar: None, ..} => {} + Foo{foo: false, bar: Some(_), ..} => {} + } +} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs new file mode 100644 index 000000000..5145f7690 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -0,0 +1,107 @@ +// Test the "defined here" and "not covered" diagnostic hints. +// We also make sure that references are peeled off from the scrutinee type +// so that the diagnostics work better with default binding modes. + +#[derive(Clone)] +enum E { + //~^ NOTE + //~| NOTE + //~| NOTE + //~| NOTE + //~| NOTE + //~| NOTE + A, + B, + //~^ NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + C + //~^ not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered + //~| not covered +} + +fn by_val(e: E) { + let e1 = e.clone(); + match e1 { //~ ERROR non-exhaustive patterns: `E::B` and `E::C` not covered + //~^ NOTE patterns `E::B` and `E::C` not covered + //~| NOTE the matched value is of type `E` + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding + //~| patterns `E::B` and `E::C` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE the matched value is of type `E` +} + +fn by_ref_once(e: &E) { + match e { + //~^ ERROR non-exhaustive patterns + //~| patterns `&E::B` and `&E::C` not covered + //~| NOTE the matched value is of type `&E` + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding + //~| patterns `&E::B` and `&E::C` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE the matched value is of type `&E` +} + +fn by_ref_thrice(e: & &mut &E) { + match e { + //~^ ERROR non-exhaustive patterns + //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE the matched value is of type `&&mut &E` + E::A => {} + } + + let E::A = e; + //~^ ERROR refutable pattern in local binding + //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + //~| NOTE the matched value is of type `&&mut &E` +} + +enum Opt { + //~^ NOTE + //~| NOTE + Some(u8), + None, + //~^ NOTE `Opt` defined here + //~| NOTE not covered + //~| NOTE not covered +} + +fn ref_pat(e: Opt) { + match e { + //~^ ERROR non-exhaustive patterns + //~| pattern `Opt::None` not covered + //~| NOTE the matched value is of type `Opt` + Opt::Some(ref _x) => {} + } + + let Opt::Some(ref _x) = e; + //~^ ERROR refutable pattern in local binding + //~| NOTE the matched value is of type `Opt` + //~| NOTE pattern `Opt::None` not covered + //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with + //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr new file mode 100644 index 000000000..769d4070f --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -0,0 +1,194 @@ +error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered + --> $DIR/non-exhaustive-defined-here.rs:35:11 + | +LL | match e1 { + | ^^ patterns `E::B` and `E::C` not covered + | +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:14:5 + | +LL | enum E { + | - +... +LL | B, + | ^ not covered +... +LL | C + | ^ not covered + = note: the matched value is of type `E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ E::A => {} +LL + E::B | E::C => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:41:9 + | +LL | let E::A = e; + | ^^^^ patterns `E::B` and `E::C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:6:6 + | +LL | enum E { + | ^ +... +LL | B, + | - not covered +... +LL | C + | - not covered + = note: the matched value is of type `E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered + --> $DIR/non-exhaustive-defined-here.rs:50:11 + | +LL | match e { + | ^ patterns `&E::B` and `&E::C` not covered + | +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:14:5 + | +LL | enum E { + | - +... +LL | B, + | ^ not covered +... +LL | C + | ^ not covered + = note: the matched value is of type `&E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ E::A => {} +LL + &E::B | &E::C => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:57:9 + | +LL | let E::A = e; + | ^^^^ patterns `&E::B` and `&E::C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:6:6 + | +LL | enum E { + | ^ +... +LL | B, + | - not covered +... +LL | C + | - not covered + = note: the matched value is of type `&E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered + --> $DIR/non-exhaustive-defined-here.rs:66:11 + | +LL | match e { + | ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered + | +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:14:5 + | +LL | enum E { + | - +... +LL | B, + | ^ not covered +... +LL | C + | ^ not covered + = note: the matched value is of type `&&mut &E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ E::A => {} +LL + &&mut &E::B | &&mut &E::C => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:73:9 + | +LL | let E::A = e; + | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/non-exhaustive-defined-here.rs:6:6 + | +LL | enum E { + | ^ +... +LL | B, + | - not covered +... +LL | C + | - not covered + = note: the matched value is of type `&&mut &E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let E::A = e { todo!() } + | ++ ~~~~~~~~~~~ + +error[E0004]: non-exhaustive patterns: `Opt::None` not covered + --> $DIR/non-exhaustive-defined-here.rs:92:11 + | +LL | match e { + | ^ pattern `Opt::None` not covered + | +note: `Opt` defined here + --> $DIR/non-exhaustive-defined-here.rs:85:5 + | +LL | enum Opt { + | --- +... +LL | None, + | ^^^^ not covered + = note: the matched value is of type `Opt` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Opt::Some(ref _x) => {} +LL + Opt::None => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/non-exhaustive-defined-here.rs:99:9 + | +LL | let Opt::Some(ref _x) = e; + | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Opt` defined here + --> $DIR/non-exhaustive-defined-here.rs:81:6 + | +LL | enum Opt { + | ^^^ +... +LL | None, + | ---- not covered + = note: the matched value is of type `Opt` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Opt::Some(ref _x) = e else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs new file mode 100644 index 000000000..69c3c7658 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs @@ -0,0 +1,19 @@ +enum T { A(U), B } +enum U { C, D } + +fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str { + match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some(&[]), Err(_))` not covered + (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)", + (Some(&[_, ..]), Ok(_)) | (Some(&[_, ..]), Err(())) => "Some(non-empty), any", + (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)", + (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)" + } +} + +fn main() { + let x = T::A(U::C); + match x { //~ ERROR non-exhaustive patterns: `T::A(U::C)` not covered + T::A(U::D) => { panic!("hello"); } + T::B => { panic!("goodbye"); } + } +} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr new file mode 100644 index 000000000..44f327421 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -0,0 +1,34 @@ +error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered + --> $DIR/non-exhaustive-match-nested.rs:5:11 + | +LL | match (l1, l2) { + | ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered + | + = note: the matched value is of type `(Option<&[T]>, Result<&[T], ()>)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)", +LL + (Some(&[]), Err(_)) => todo!() + | + +error[E0004]: non-exhaustive patterns: `T::A(U::C)` not covered + --> $DIR/non-exhaustive-match-nested.rs:15:11 + | +LL | match x { + | ^ pattern `T::A(U::C)` not covered + | +note: `T` defined here + --> $DIR/non-exhaustive-match-nested.rs:1:10 + | +LL | enum T { A(U), B } + | - ^ not covered + = note: the matched value is of type `T` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ T::B => { panic!("goodbye"); } +LL + T::A(U::C) => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.rs b/tests/ui/pattern/usefulness/non-exhaustive-match.rs new file mode 100644 index 000000000..1cb58b8ce --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.rs @@ -0,0 +1,63 @@ +#![allow(illegal_floating_point_literal_pattern)] + +enum T { A, B } + +fn main() { + let x = T::A; + match x { T::B => { } } //~ ERROR non-exhaustive patterns: `T::A` not covered + match true { //~ ERROR non-exhaustive patterns: `false` not covered + true => {} + } + match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered + None => {} + } + match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` + // and `(_, _, 5_i32..=i32::MAX)` not covered + (_, _, 4) => {} + } + match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered + (T::A, T::B) => {} + (T::B, T::A) => {} + } + match T::A { //~ ERROR non-exhaustive patterns: `T::B` not covered + T::A => {} + } + // This is exhaustive, though the algorithm got it wrong at one point + match (T::A, T::B) { + (T::A, _) => {} + (_, T::A) => {} + (T::B, T::B) => {} + } + let vec = vec![Some(42), None, Some(21)]; + let vec: &[Option] = &vec; + match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered + [Some(..), None, ref tail @ ..] => {} + [Some(..), Some(..), ref tail @ ..] => {} + [None] => {} + } + let vec = vec![1]; + let vec: &[isize] = &vec; + match *vec { + [_, ref tail @ ..] => (), + [] => () + } + let vec = vec![0.5f32]; + let vec: &[f32] = &vec; + match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _, ..]` not covered + [0.1, 0.2, 0.3] => (), + [0.1, 0.2] => (), + [0.1] => (), + [] => () + } + let vec = vec![Some(42), None, Some(21)]; + let vec: &[Option] = &vec; + match *vec { + [Some(..), None, ref tail @ ..] => {} + [Some(..), Some(..), ref tail @ ..] => {} + [None, None, ref tail @ ..] => {} + [None, Some(..), ref tail @ ..] => {} + [Some(_)] => {} + [None] => {} + [] => {} + } +} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr new file mode 100644 index 000000000..e2260f50b --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -0,0 +1,121 @@ +error[E0004]: non-exhaustive patterns: `T::A` not covered + --> $DIR/non-exhaustive-match.rs:7:11 + | +LL | match x { T::B => { } } + | ^ pattern `T::A` not covered + | +note: `T` defined here + --> $DIR/non-exhaustive-match.rs:3:10 + | +LL | enum T { A, B } + | - ^ not covered + = note: the matched value is of type `T` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match x { T::B => { }, T::A => todo!() } + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `false` not covered + --> $DIR/non-exhaustive-match.rs:8:11 + | +LL | match true { + | ^^^^ pattern `false` not covered + | + = note: the matched value is of type `bool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ true => {} +LL + false => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/non-exhaustive-match.rs:11:11 + | +LL | match Some(10) { + | ^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {} +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered + --> $DIR/non-exhaustive-match.rs:14:11 + | +LL | match (2, 3, 4) { + | ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered + | + = note: the matched value is of type `(i32, i32, i32)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (_, _, 4) => {} +LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!() + | + +error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered + --> $DIR/non-exhaustive-match.rs:18:11 + | +LL | match (T::A, T::A) { + | ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered + | + = note: the matched value is of type `(T, T)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ (T::B, T::A) => {} +LL + (T::A, T::A) | (T::B, T::B) => todo!() + | + +error[E0004]: non-exhaustive patterns: `T::B` not covered + --> $DIR/non-exhaustive-match.rs:22:11 + | +LL | match T::A { + | ^^^^ pattern `T::B` not covered + | +note: `T` defined here + --> $DIR/non-exhaustive-match.rs:3:13 + | +LL | enum T { A, B } + | - ^ not covered + = note: the matched value is of type `T` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ T::A => {} +LL + T::B => todo!() + | + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/non-exhaustive-match.rs:33:11 + | +LL | match *vec { + | ^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[Option]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [None] => {} +LL + [] => todo!() + | + +error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered + --> $DIR/non-exhaustive-match.rs:46:11 + | +LL | match *vec { + | ^^^^ pattern `[_, _, _, _, ..]` not covered + | + = note: the matched value is of type `[f32]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [] => (), +LL + [_, _, _, _, ..] => todo!() + | + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs new file mode 100644 index 000000000..4bd344219 --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs @@ -0,0 +1,89 @@ +struct Foo { + first: bool, + second: Option<[usize; 4]> +} + +fn struct_with_a_nested_enum_and_vector() { + match (Foo { first: true, second: None }) { +//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered + Foo { first: true, second: None } => (), + Foo { first: true, second: Some(_) } => (), + Foo { first: false, second: None } => (), + Foo { first: false, second: Some([1, 2, 3, 4]) } => () + } +} + +enum Color { + Red, + Green, + CustomRGBA { a: bool, r: u8, g: u8, b: u8 } +} + +fn enum_with_single_missing_variant() { + match Color::Red { + //~^ ERROR non-exhaustive patterns: `Color::Red` not covered + Color::CustomRGBA { .. } => (), + Color::Green => () + } +} + +enum Direction { + North, East, South, West +} + +fn enum_with_multiple_missing_variants() { + match Direction::North { + //~^ ERROR non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered + Direction::North => () + } +} + +enum ExcessiveEnum { + First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth +} + +fn enum_with_excessive_missing_variants() { + match ExcessiveEnum::First { + //~^ ERROR `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered + + ExcessiveEnum::First => () + } +} + +fn enum_struct_variant() { + match Color::Red { + //~^ ERROR non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered + Color::Red => (), + Color::Green => (), + Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (), + Color::CustomRGBA { a: false, r: _, g: _, b: _ } => () + } +} + +enum Enum { + First, + Second(bool) +} + +fn vectors_with_nested_enums() { + let x: &'static [Enum] = &[Enum::First, Enum::Second(false)]; + match *x { + //~^ ERROR non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered + [] => (), + [_] => (), + [Enum::First, _] => (), + [Enum::Second(true), Enum::First] => (), + [Enum::Second(true), Enum::Second(true)] => (), + [Enum::Second(false), _] => (), + [_, _, ref tail @ .., _] => () + } +} + +fn missing_nil() { + match ((), false) { + //~^ ERROR non-exhaustive patterns: `((), false)` not covered + ((), true) => () + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr new file mode 100644 index 000000000..b8af566de --- /dev/null +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -0,0 +1,129 @@ +error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:7:11 + | +LL | match (Foo { first: true, second: None }) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered + | +note: `Foo` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:1:8 + | +LL | struct Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (), +LL + Foo { first: false, second: Some([_, _, _, _]) } => todo!() + | + +error[E0004]: non-exhaustive patterns: `Color::Red` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:23:11 + | +LL | match Color::Red { + | ^^^^^^^^^^ pattern `Color::Red` not covered + | +note: `Color` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:17:5 + | +LL | enum Color { + | ----- +LL | Red, + | ^^^ not covered + = note: the matched value is of type `Color` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Color::Green => (), +LL + Color::Red => todo!() + | + +error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:35:11 + | +LL | match Direction::North { + | ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered + | +note: `Direction` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:31:12 + | +LL | enum Direction { + | --------- +LL | North, East, South, West + | ^^^^ ^^^^^ ^^^^ not covered + | | | + | | not covered + | not covered + = note: the matched value is of type `Direction` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ Direction::North => (), +LL + Direction::East | Direction::South | Direction::West => todo!() + | + +error[E0004]: non-exhaustive patterns: `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered + --> $DIR/non-exhaustive-pattern-witness.rs:46:11 + | +LL | match ExcessiveEnum::First { + | ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered + | +note: `ExcessiveEnum` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:41:6 + | +LL | enum ExcessiveEnum { + | ^^^^^^^^^^^^^ + = note: the matched value is of type `ExcessiveEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ ExcessiveEnum::First => (), +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:54:11 + | +LL | match Color::Red { + | ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered + | +note: `Color` defined here + --> $DIR/non-exhaustive-pattern-witness.rs:19:5 + | +LL | enum Color { + | ----- +... +LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 } + | ^^^^^^^^^^ not covered + = note: the matched value is of type `Color` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (), +LL + Color::CustomRGBA { a: true, .. } => todo!() + | + +error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:70:11 + | +LL | match *x { + | ^^ pattern `[Enum::Second(true), Enum::Second(false)]` not covered + | + = note: the matched value is of type `[Enum]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [_, _, ref tail @ .., _] => (), +LL + [Enum::Second(true), Enum::Second(false)] => todo!() + | + +error[E0004]: non-exhaustive patterns: `((), false)` not covered + --> $DIR/non-exhaustive-pattern-witness.rs:83:11 + | +LL | match ((), false) { + | ^^^^^^^^^^^ pattern `((), false)` not covered + | + = note: the matched value is of type `((), bool)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ ((), true) => (), +LL + ((), false) => todo!() + | + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.rs b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs new file mode 100644 index 000000000..7a3e991d5 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs @@ -0,0 +1,9 @@ +fn func((1, (Some(1), 2..=3)): (isize, (Option, isize))) { } +//~^ ERROR refutable pattern in function argument +//~| `(_, _)` not covered + +fn main() { + let (1, (Some(1), 2..=3)) = (1, (None, 2)); + //~^ ERROR refutable pattern in local binding + //~| `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered +} diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr new file mode 100644 index 000000000..c518de477 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr @@ -0,0 +1,25 @@ +error[E0005]: refutable pattern in function argument + --> $DIR/refutable-pattern-errors.rs:1:9 + | +LL | fn func((1, (Some(1), 2..=3)): (isize, (Option, isize))) { } + | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(isize, (Option, isize))` + +error[E0005]: refutable pattern in local binding + --> $DIR/refutable-pattern-errors.rs:6:9 + | +LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); + | ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `(i32, (Option, i32))` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() } + | ++ ~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs new file mode 100644 index 000000000..17dc38ab2 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs @@ -0,0 +1,6 @@ +fn main() { + let f = |3: isize| println!("hello"); + //~^ ERROR refutable pattern in function argument + //~| `_` not covered + f(4); +} diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr new file mode 100644 index 000000000..55f0b2319 --- /dev/null +++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr @@ -0,0 +1,11 @@ +error[E0005]: refutable pattern in function argument + --> $DIR/refutable-pattern-in-fn-arg.rs:2:14 + | +LL | let f = |3: isize| println!("hello"); + | ^ pattern `_` not covered + | + = note: the matched value is of type `isize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.rs b/tests/ui/pattern/usefulness/slice-pattern-const-2.rs new file mode 100644 index 000000000..4bf8d0fd2 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.rs @@ -0,0 +1,31 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s = &[0x00; 4][..]; //Slice of any value + const MAGIC_TEST: &[u32] = &[4, 5, 6, 7]; //Const slice to pattern match with + match s { + MAGIC_TEST => (), + [0x00, 0x00, 0x00, 0x00] => (), + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + MAGIC_TEST => (), + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + [4, 5, 6, 7] => (), + MAGIC_TEST => (), //~ ERROR unreachable pattern + _ => (), + } + const FOO: [u32; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } +} diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr new file mode 100644 index 000000000..dcad11a38 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr @@ -0,0 +1,32 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:9:9 + | +LL | [4, 5, 6, 7] => (), + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-pattern-const-2.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:15:9 + | +LL | [4, 5, 6, 7] => (), + | ^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:21:9 + | +LL | MAGIC_TEST => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:28:9 + | +LL | FOO => (), + | ^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.rs b/tests/ui/pattern/usefulness/slice-pattern-const-3.rs new file mode 100644 index 000000000..2ca8323f0 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.rs @@ -0,0 +1,31 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s = &["0x00"; 4][..]; //Slice of any value + const MAGIC_TEST: &[&str] = &["4", "5", "6", "7"]; //Const slice to pattern match with + match s { + MAGIC_TEST => (), + ["0x00", "0x00", "0x00", "0x00"] => (), + ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + ["0x00", "0x00", "0x00", "0x00"] => (), + MAGIC_TEST => (), + ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + ["0x00", "0x00", "0x00", "0x00"] => (), + ["4", "5", "6", "7"] => (), + MAGIC_TEST => (), //~ ERROR unreachable pattern + _ => (), + } + const FOO: [&str; 1] = ["boo"]; + match ["baa"] { + ["0x00"] => (), + ["boo"] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } +} diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr new file mode 100644 index 000000000..b90b3a88a --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr @@ -0,0 +1,32 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:9:9 + | +LL | ["4", "5", "6", "7"] => (), + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-pattern-const-3.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:15:9 + | +LL | ["4", "5", "6", "7"] => (), + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:21:9 + | +LL | MAGIC_TEST => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:28:9 + | +LL | FOO => (), + | ^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.rs b/tests/ui/pattern/usefulness/slice-pattern-const.rs new file mode 100644 index 000000000..89195d5b1 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const.rs @@ -0,0 +1,54 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s = &[0x00; 4][..]; //Slice of any value + const MAGIC_TEST: &[u8] = b"TEST"; //Const slice to pattern match with + match s { + MAGIC_TEST => (), + [0x00, 0x00, 0x00, 0x00] => (), + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + MAGIC_TEST => (), + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + _ => (), + } + match s { + [0x00, 0x00, 0x00, 0x00] => (), + [84, 69, 83, 84] => (), + MAGIC_TEST => (), //~ ERROR unreachable pattern + _ => (), + } + const FOO: [u8; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), //~ ERROR unreachable pattern + _ => (), + } + const BAR: &[u8; 1] = &[4]; + match &[99] { + [0x00] => (), + [4] => (), + BAR => (), //~ ERROR unreachable pattern + b"a" => (), + _ => (), + } + + const BOO: &[u8; 0] = &[]; + match &[] { + [] => (), + BOO => (), //~ ERROR unreachable pattern + b"" => (), //~ ERROR unreachable pattern + _ => (), //~ ERROR unreachable pattern + } + + const CONST1: &[bool; 1] = &[true]; + match &[false] { + CONST1 => {} + [true] => {} //~ ERROR unreachable pattern + [false] => {} + } +} diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr new file mode 100644 index 000000000..1fffb9fed --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr @@ -0,0 +1,62 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:9:9 + | +LL | [84, 69, 83, 84] => (), + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-pattern-const.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:15:9 + | +LL | [84, 69, 83, 84] => (), + | ^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:21:9 + | +LL | MAGIC_TEST => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:28:9 + | +LL | FOO => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:35:9 + | +LL | BAR => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:43:9 + | +LL | BOO => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:44:9 + | +LL | b"" => (), + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:45:9 + | +LL | _ => (), + | ^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:51:9 + | +LL | [true] => {} + | ^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs new file mode 100644 index 000000000..46e0da5be --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs @@ -0,0 +1,129 @@ +fn main() { + let s: &[bool] = &[true; 0]; + let s1: &[bool; 1] = &[false; 1]; + let s2: &[bool; 2] = &[false; 2]; + let s3: &[bool; 3] = &[false; 3]; + let s10: &[bool; 10] = &[false; 10]; + + match s2 { + //~^ ERROR `&[false, _]` not covered + [true, .., true] => {} + } + match s3 { + //~^ ERROR `&[false, ..]` not covered + [true, .., true] => {} + } + match s10 { + //~^ ERROR `&[false, ..]` not covered + [true, .., true] => {} + } + + match s1 { + [true, ..] => {} + [.., false] => {} + } + match s2 { + //~^ ERROR `&[false, true]` not covered + [true, ..] => {} + [.., false] => {} + } + match s3 { + //~^ ERROR `&[false, .., true]` not covered + [true, ..] => {} + [.., false] => {} + } + match s { + //~^ ERROR `&[false, .., true]` not covered + [] => {} + [true, ..] => {} + [.., false] => {} + } + + match s { + //~^ ERROR `&[_, ..]` not covered + [] => {} + } + match s { + //~^ ERROR `&[_, _, ..]` not covered + [] => {} + [_] => {} + } + match s { + //~^ ERROR `&[false, ..]` not covered + [] => {} + [true, ..] => {} + } + match s { + //~^ ERROR `&[false, _, ..]` not covered + [] => {} + [_] => {} + [true, ..] => {} + } + match s { + //~^ ERROR `&[_, .., false]` not covered + [] => {} + [_] => {} + [.., true] => {} + } + + match s { + //~^ ERROR `&[_, _, .., true]` not covered + [] => {} + [_] => {} + [_, _] => {} + [.., false] => {} + } + match s { + //~^ ERROR `&[true, _, .., _]` not covered + [] => {} + [_] => {} + [_, _] => {} + [false, .., false] => {} + } + + const CONST: &[bool] = &[true]; + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + &[true] => {} + } + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + CONST => {} + } + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + CONST => {} + &[false] => {} + } + match s { + //~^ ERROR `&[]` and `&[_, _, ..]` not covered + &[false] => {} + CONST => {} + } + match s { + //~^ ERROR `&[_, _, ..]` not covered + &[] => {} + CONST => {} + } + match s { + //~^ ERROR `&[false]` not covered + &[] => {} + CONST => {} + &[_, _, ..] => {} + } + match s { + [] => {} + [false] => {} + CONST => {} + [_, _, ..] => {} + } + const CONST1: &[bool; 1] = &[true]; + match s1 { + //~^ ERROR `&[false]` not covered + CONST1 => {} + } + match s1 { + CONST1 => {} + [false] => {} + } +} diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr new file mode 100644 index 000000000..5d1e170ae --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -0,0 +1,263 @@ +error[E0004]: non-exhaustive patterns: `&[false, _]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:8:11 + | +LL | match s2 { + | ^^ pattern `&[false, _]` not covered + | + = note: the matched value is of type `&[bool; 2]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [true, .., true] => {} +LL + &[false, _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:12:11 + | +LL | match s3 { + | ^^ pattern `&[false, ..]` not covered + | + = note: the matched value is of type `&[bool; 3]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [true, .., true] => {} +LL + &[false, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:16:11 + | +LL | match s10 { + | ^^^ pattern `&[false, ..]` not covered + | + = note: the matched value is of type `&[bool; 10]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [true, .., true] => {} +LL + &[false, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:25:11 + | +LL | match s2 { + | ^^ pattern `&[false, true]` not covered + | + = note: the matched value is of type `&[bool; 2]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [.., false] => {} +LL + &[false, true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:30:11 + | +LL | match s3 { + | ^^ pattern `&[false, .., true]` not covered + | + = note: the matched value is of type `&[bool; 3]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [.., false] => {} +LL + &[false, .., true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:35:11 + | +LL | match s { + | ^ pattern `&[false, .., true]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [.., false] => {} +LL + &[false, .., true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:42:11 + | +LL | match s { + | ^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [] => {} +LL + &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:46:11 + | +LL | match s { + | ^ pattern `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [_] => {} +LL + &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:51:11 + | +LL | match s { + | ^ pattern `&[false, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [true, ..] => {} +LL + &[false, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:56:11 + | +LL | match s { + | ^ pattern `&[false, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [true, ..] => {} +LL + &[false, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:62:11 + | +LL | match s { + | ^ pattern `&[_, .., false]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [.., true] => {} +LL + &[_, .., false] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:69:11 + | +LL | match s { + | ^ pattern `&[_, _, .., true]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [.., false] => {} +LL + &[_, _, .., true] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:76:11 + | +LL | match s { + | ^ pattern `&[true, _, .., _]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [false, .., false] => {} +LL + &[true, _, .., _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:85:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[true] => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:89:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ CONST => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:93:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[false] => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:98:11 + | +LL | match s { + | ^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ CONST => {} +LL + &[] | &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:103:11 + | +LL | match s { + | ^ pattern `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ CONST => {} +LL + &[_, _, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:108:11 + | +LL | match s { + | ^ pattern `&[false]` not covered + | + = note: the matched value is of type `&[bool]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[_, _, ..] => {} +LL + &[false] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[false]` not covered + --> $DIR/slice-patterns-exhaustiveness.rs:121:11 + | +LL | match s1 { + | ^^ pattern `&[false]` not covered + | + = note: the matched value is of type `&[bool; 1]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ CONST1 => {} +LL + &[false] => todo!() + | + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs b/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs new file mode 100644 index 000000000..cbf64e2c5 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs @@ -0,0 +1,26 @@ +// check-pass + +fn main() { + let s: &[bool] = &[true; 0]; + let s0: &[bool; 0] = &[]; + let s1: &[bool; 1] = &[false; 1]; + let s2: &[bool; 2] = &[false; 2]; + + let [] = s0; + let [_] = s1; + let [_, _] = s2; + + let [..] = s; + let [..] = s0; + let [..] = s1; + let [..] = s2; + + let [_, ..] = s1; + let [.., _] = s1; + let [_, ..] = s2; + let [.., _] = s2; + + let [_, _, ..] = s2; + let [_, .., _] = s2; + let [.., _, _] = s2; +} diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.rs b/tests/ui/pattern/usefulness/slice-patterns-reachability.rs new file mode 100644 index 000000000..7c747b5e0 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.rs @@ -0,0 +1,25 @@ +#![deny(unreachable_patterns)] + +fn main() { + let s: &[bool] = &[]; + + match s { + [true, ..] => {} + [true, ..] => {} //~ ERROR unreachable pattern + [true] => {} //~ ERROR unreachable pattern + [..] => {} + } + match s { + [.., true] => {} + [.., true] => {} //~ ERROR unreachable pattern + [true] => {} //~ ERROR unreachable pattern + [..] => {} + } + match s { + [false, .., true] => {} + [false, .., true] => {} //~ ERROR unreachable pattern + [false, true] => {} //~ ERROR unreachable pattern + [false] => {} + [..] => {} + } +} diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr new file mode 100644 index 000000000..607ffb765 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr @@ -0,0 +1,44 @@ +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:8:9 + | +LL | [true, ..] => {} + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/slice-patterns-reachability.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:9:9 + | +LL | [true] => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:14:9 + | +LL | [.., true] => {} + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:15:9 + | +LL | [true] => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:20:9 + | +LL | [false, .., true] => {} + | ^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-patterns-reachability.rs:21:9 + | +LL | [false, true] => {} + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.rs b/tests/ui/pattern/usefulness/stable-gated-fields.rs new file mode 100644 index 000000000..90f40a8d6 --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-fields.rs @@ -0,0 +1,16 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableStruct; + +fn main() { + let UnstableStruct { stable } = UnstableStruct::default(); + //~^ pattern does not mention field `stable2` and inaccessible fields + + let UnstableStruct { stable, stable2 } = UnstableStruct::default(); + //~^ pattern requires `..` due to inaccessible fields + + // OK: stable field is matched + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); +} diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.stderr b/tests/ui/pattern/usefulness/stable-gated-fields.stderr new file mode 100644 index 000000000..cf98c51a2 --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-fields.stderr @@ -0,0 +1,29 @@ +error[E0027]: pattern does not mention field `stable2` and inaccessible fields + --> $DIR/stable-gated-fields.rs:8:9 + | +LL | let UnstableStruct { stable } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ~~~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, .. } = UnstableStruct::default(); + | ~~~~~~ + +error: pattern requires `..` due to inaccessible fields + --> $DIR/stable-gated-fields.rs:11:9 + | +LL | let UnstableStruct { stable, stable2 } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.rs b/tests/ui/pattern/usefulness/stable-gated-patterns.rs new file mode 100644 index 000000000..03db01160 --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.rs @@ -0,0 +1,18 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableEnum; + +fn main() { + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + } + //~^^^ non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered +} diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr new file mode 100644 index 000000000..7b8588a3c --- /dev/null +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -0,0 +1,42 @@ +error[E0004]: non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered + --> $DIR/stable-gated-patterns.rs:8:11 + | +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered + | +note: `UnstableEnum` defined here + --> $DIR/auxiliary/unstable.rs:9:5 + | +LL | pub enum UnstableEnum { + | --------------------- +... +LL | Stable2, + | ^^^^^^^ not covered + = note: the matched value is of type `UnstableEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ UnstableEnum::Stable => {} +LL + UnstableEnum::Stable2 | _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/stable-gated-patterns.rs:13:11 + | +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered + | +note: `UnstableEnum` defined here + --> $DIR/auxiliary/unstable.rs:5:1 + | +LL | pub enum UnstableEnum { + | ^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UnstableEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ UnstableEnum::Stable2 => {} +LL + _ => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs new file mode 100644 index 000000000..b1fc0f5ad --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs @@ -0,0 +1,12 @@ +enum A { + B { x: Option }, + C +} + +fn main() { + let x = A::B { x: Some(3) }; + match x { //~ ERROR non-exhaustive patterns + A::C => {} + A::B { x: None } => {} + } +} diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr new file mode 100644 index 000000000..85c97be29 --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -0,0 +1,23 @@ +error[E0004]: non-exhaustive patterns: `A::B { x: Some(_) }` not covered + --> $DIR/struct-like-enum-nonexhaustive.rs:8:11 + | +LL | match x { + | ^ pattern `A::B { x: Some(_) }` not covered + | +note: `A` defined here + --> $DIR/struct-like-enum-nonexhaustive.rs:2:5 + | +LL | enum A { + | - +LL | B { x: Option }, + | ^ not covered + = note: the matched value is of type `A` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ A::B { x: None } => {} +LL + A::B { x: Some(_) } => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs b/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs new file mode 100644 index 000000000..93f0a9317 --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs @@ -0,0 +1,15 @@ +#![deny(unreachable_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +pub fn main() { + let a = Foo { x: 1, y: 2 }; + match a { + Foo { x: _x, y: _y } => (), + Foo { .. } => () //~ ERROR unreachable pattern + } + +} diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr new file mode 100644 index 000000000..fbee33de6 --- /dev/null +++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr @@ -0,0 +1,16 @@ +error: unreachable pattern + --> $DIR/struct-pattern-match-useless.rs:12:9 + | +LL | Foo { x: _x, y: _y } => (), + | -------------------- matches any value +LL | Foo { .. } => () + | ^^^^^^^^^^ unreachable pattern + | +note: the lint level is defined here + --> $DIR/struct-pattern-match-useless.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pattern/usefulness/top-level-alternation.rs b/tests/ui/pattern/usefulness/top-level-alternation.rs new file mode 100644 index 000000000..e8cd12ea4 --- /dev/null +++ b/tests/ui/pattern/usefulness/top-level-alternation.rs @@ -0,0 +1,57 @@ +#![deny(unreachable_patterns)] + +fn main() { + while let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern + if let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern + + match 0u8 { + 0 + | 0 => {} //~ ERROR unreachable pattern + _ => {} + } + match Some(0u8) { + Some(0) + | Some(0) => {} //~ ERROR unreachable pattern + _ => {} + } + match (0u8, 0u8) { + (0, _) | (_, 0) => {} + (0, 0) => {} //~ ERROR unreachable pattern + (1, 1) => {} + _ => {} + } + match (0u8, 0u8) { + (0, 1) | (2, 3) => {} + (0, 3) => {} + (2, 1) => {} + _ => {} + } + match (0u8, 0u8) { + (_, 0) | (_, 1) => {} + _ => {} + } + match (0u8, 0u8) { + (0, _) | (1, _) => {} + _ => {} + } + match Some(0u8) { + None | Some(_) => {} + _ => {} //~ ERROR unreachable pattern + } + match Some(0u8) { + None | Some(_) => {} + Some(_) => {} //~ ERROR unreachable pattern + None => {} //~ ERROR unreachable pattern + } + match Some(0u8) { + Some(_) => {} + None => {} + None | Some(_) => {} //~ ERROR unreachable pattern + } + match 0u8 { + 1 | 2 => {}, + 1..=2 => {}, //~ ERROR unreachable pattern + _ => {}, + } + let (0 | 0) = 0 else { return }; //~ ERROR unreachable pattern +} diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr new file mode 100644 index 000000000..17fa951c5 --- /dev/null +++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr @@ -0,0 +1,74 @@ +error: unreachable pattern + --> $DIR/top-level-alternation.rs:4:23 + | +LL | while let 0..=2 | 1 = 0 {} + | ^ + | +note: the lint level is defined here + --> $DIR/top-level-alternation.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:5:20 + | +LL | if let 0..=2 | 1 = 0 {} + | ^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:9:15 + | +LL | | 0 => {} + | ^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:14:15 + | +LL | | Some(0) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:19:9 + | +LL | (0, 0) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:39:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:43:9 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:44:9 + | +LL | None => {} + | ^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:49:9 + | +LL | None | Some(_) => {} + | ^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:53:9 + | +LL | 1..=2 => {}, + | ^^^^^ + +error: unreachable pattern + --> $DIR/top-level-alternation.rs:56:14 + | +LL | let (0 | 0) = 0 else { return }; + | ^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs new file mode 100644 index 000000000..76bcf3fbd --- /dev/null +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs @@ -0,0 +1,9 @@ +struct Foo(isize, isize); + +fn main() { + let x = Foo(1, 2); + match x { //~ ERROR non-exhaustive + Foo(1, b) => println!("{}", b), + Foo(2, b) => println!("{}", b) + } +} diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr new file mode 100644 index 000000000..e2a65ff85 --- /dev/null +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr @@ -0,0 +1,21 @@ +error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered + --> $DIR/tuple-struct-nonexhaustive.rs:5:11 + | +LL | match x { + | ^ pattern `Foo(_, _)` not covered + | +note: `Foo` defined here + --> $DIR/tuple-struct-nonexhaustive.rs:1:8 + | +LL | struct Foo(isize, isize); + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Foo(2, b) => println!("{}", b), +LL + Foo(_, _) => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs new file mode 100644 index 000000000..cb44c1da7 --- /dev/null +++ b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs @@ -0,0 +1,36 @@ +#[deny(unreachable_patterns)] + +fn parse_data1(data: &[u8]) -> u32 { + match data { + b"" => 1, + _ => 2, + } +} + +fn parse_data2(data: &[u8]) -> u32 { + match data { //~ ERROR non-exhaustive patterns: `&[_, ..]` not covered + b"" => 1, + } +} + +fn parse_data3(data: &[u8; 0]) -> u8 { + match data { + b"" => 1, + } +} + +fn parse_data4(data: &[u8]) -> u8 { + match data { //~ ERROR non-exhaustive patterns + b"aaa" => 0, + [_, _, _] => 1, + } +} + +fn parse_data5(data: &[u8; 3]) -> u8 { + match data { + b"aaa" => 0, + [_, _, _] => 1, + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr new file mode 100644 index 000000000..acae605da --- /dev/null +++ b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr @@ -0,0 +1,29 @@ +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/type_polymorphic_byte_str_literals.rs:11:11 + | +LL | match data { + | ^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[u8]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ b"" => 1, +LL ~ &[_, ..] => todo!(), + | + +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered + --> $DIR/type_polymorphic_byte_str_literals.rs:23:11 + | +LL | match data { + | ^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered + | + = note: the matched value is of type `&[u8]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms + | +LL ~ [_, _, _] => 1, +LL ~ _ => todo!(), + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/uninhabited.rs b/tests/ui/pattern/usefulness/uninhabited.rs new file mode 100644 index 000000000..5622808d4 --- /dev/null +++ b/tests/ui/pattern/usefulness/uninhabited.rs @@ -0,0 +1,143 @@ +// check-pass +// aux-build:empty.rs +// +// This tests plays with matching and uninhabited types. This also serves as a test for the +// `Ty::is_inhabited_from` function. +#![feature(never_type)] +#![feature(never_type_fallback)] +#![feature(exhaustive_patterns)] +#![deny(unreachable_patterns)] + +macro_rules! assert_empty { + ($ty:ty) => { + const _: () = { + fn assert_empty(x: $ty) { + match x {} + match Some(x) { + None => {} + } + } + }; + }; +} +macro_rules! assert_non_empty { + ($ty:ty) => { + const _: () = { + fn assert_non_empty(x: $ty) { + match x { + _ => {} + } + match Some(x) { + None => {} + Some(_) => {} + } + } + }; + }; +} + +extern crate empty; +assert_empty!(empty::EmptyForeignEnum); +assert_empty!(empty::VisiblyUninhabitedForeignStruct); +assert_non_empty!(empty::SecretlyUninhabitedForeignStruct); + +enum Void {} +assert_empty!(Void); + +enum Enum2 { + Foo(Void), + Bar(!), +} +assert_empty!(Enum2); + +enum Enum3 { + Foo(Void), + Bar { + x: u64, + y: !, + }, +} +assert_empty!(Enum3); + +enum Enum4 { + Foo(u64), + Bar(!), +} +assert_non_empty!(Enum4); + +struct Struct1(empty::EmptyForeignEnum); +assert_empty!(Struct1); + +struct Struct2 { + x: u64, + y: !, +} +assert_empty!(Struct2); + +union Union { + foo: !, +} +assert_non_empty!(Union); + +assert_empty!((!, String)); + +assert_non_empty!(&'static !); +assert_non_empty!(&'static Struct1); +assert_non_empty!(&'static &'static &'static !); + +assert_empty!([!; 1]); +assert_empty!([Void; 2]); +assert_non_empty!([!; 0]); +assert_non_empty!(&'static [!]); + +mod visibility { + /// This struct can only be seen to be inhabited in modules `b`, `c` or `d`, because otherwise + /// the uninhabitedness of both `SecretlyUninhabited` structs is hidden. + struct SometimesEmptyStruct { + x: a::b::SecretlyUninhabited, + y: c::AlsoSecretlyUninhabited, + } + + /// This enum can only be seen to be inhabited in module `d`. + enum SometimesEmptyEnum { + X(c::AlsoSecretlyUninhabited), + Y(c::d::VerySecretlyUninhabited), + } + + mod a { + use super::*; + pub mod b { + use super::*; + pub struct SecretlyUninhabited { + _priv: !, + } + assert_empty!(SometimesEmptyStruct); + } + + assert_non_empty!(SometimesEmptyStruct); + assert_non_empty!(SometimesEmptyEnum); + } + + mod c { + use super::*; + pub struct AlsoSecretlyUninhabited { + _priv: ::Struct1, + } + assert_empty!(SometimesEmptyStruct); + assert_non_empty!(SometimesEmptyEnum); + + pub mod d { + use super::*; + pub struct VerySecretlyUninhabited { + _priv: !, + } + assert_empty!(SometimesEmptyStruct); + assert_empty!(SometimesEmptyEnum); + } + } + + assert_non_empty!(SometimesEmptyStruct); + assert_non_empty!(SometimesEmptyEnum); +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.rs b/tests/ui/pattern/usefulness/unstable-gated-fields.rs new file mode 100644 index 000000000..2b473ae98 --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-fields.rs @@ -0,0 +1,18 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableStruct; + +fn main() { + let UnstableStruct { stable, stable2, } = UnstableStruct::default(); + //~^ pattern does not mention field `unstable` + + let UnstableStruct { stable, unstable, } = UnstableStruct::default(); + //~^ pattern does not mention field `stable2` + + // OK: stable field is matched + let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); +} diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr new file mode 100644 index 000000000..e4f5fa06b --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr @@ -0,0 +1,33 @@ +error[E0027]: pattern does not mention field `unstable` + --> $DIR/unstable-gated-fields.rs:10:9 + | +LL | let UnstableStruct { stable, stable2, } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `unstable` + | +help: include the missing field in the pattern + | +LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); + | ~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `stable2` + --> $DIR/unstable-gated-fields.rs:13:9 + | +LL | let UnstableStruct { stable, unstable, } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` + | +help: include the missing field in the pattern + | +LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::default(); + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default(); + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.rs b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs new file mode 100644 index 000000000..7046555e0 --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -0,0 +1,22 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableEnum; + +fn main() { + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `UnstableEnum::Unstable` not covered + + // Ok: all variants are explicitly matched + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + UnstableEnum::Unstable => {} + } +} diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr new file mode 100644 index 000000000..6dc9a4058 --- /dev/null +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -0,0 +1,24 @@ +error[E0004]: non-exhaustive patterns: `UnstableEnum::Unstable` not covered + --> $DIR/unstable-gated-patterns.rs:10:11 + | +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered + | +note: `UnstableEnum` defined here + --> $DIR/auxiliary/unstable.rs:11:5 + | +LL | pub enum UnstableEnum { + | --------------------- +... +LL | Unstable, + | ^^^^^^^^ not covered + = note: the matched value is of type `UnstableEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ UnstableEnum::Stable2 => {} +LL + UnstableEnum::Unstable => todo!() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/phantom-auto-trait.rs b/tests/ui/phantom-auto-trait.rs new file mode 100644 index 000000000..0172ca335 --- /dev/null +++ b/tests/ui/phantom-auto-trait.rs @@ -0,0 +1,30 @@ +// Ensure that auto trait checks `T` when it encounters a `PhantomData` field, instead of +// checking the `PhantomData` type itself (which almost always implements an auto trait). + +#![feature(auto_traits)] + +use std::marker::{PhantomData}; + +unsafe auto trait Zen {} + +unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + +struct Guard<'a, T: 'a> { + _marker: PhantomData<&'a T>, +} + +struct Nested(T); + +fn is_zen(_: T) {} + +fn not_sync(x: Guard) { + is_zen(x) + //~^ ERROR `T` cannot be shared between threads safely [E0277] +} + +fn nested_not_sync(x: Nested>) { + is_zen(x) + //~^ ERROR `T` cannot be shared between threads safely [E0277] +} + +fn main() {} diff --git a/tests/ui/phantom-auto-trait.stderr b/tests/ui/phantom-auto-trait.stderr new file mode 100644 index 000000000..4769d53eb --- /dev/null +++ b/tests/ui/phantom-auto-trait.stderr @@ -0,0 +1,66 @@ +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/phantom-auto-trait.rs:21:12 + | +LL | is_zen(x) + | ------ ^ `T` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | +note: required for `&T` to implement `Zen` + --> $DIR/phantom-auto-trait.rs:10:24 + | +LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + | ^^^ ^^^^^ ---- unsatisfied trait bound introduced here + = note: required because it appears within the type `PhantomData<&T>` +note: required because it appears within the type `Guard<'_, T>` + --> $DIR/phantom-auto-trait.rs:12:8 + | +LL | struct Guard<'a, T: 'a> { + | ^^^^^ +note: required by a bound in `is_zen` + --> $DIR/phantom-auto-trait.rs:18:14 + | +LL | fn is_zen(_: T) {} + | ^^^ required by this bound in `is_zen` +help: consider restricting type parameter `T` + | +LL | fn not_sync(x: Guard) { + | +++++++++++++++++++ + +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/phantom-auto-trait.rs:26:12 + | +LL | is_zen(x) + | ------ ^ `T` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | +note: required for `&T` to implement `Zen` + --> $DIR/phantom-auto-trait.rs:10:24 + | +LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} + | ^^^ ^^^^^ ---- unsatisfied trait bound introduced here + = note: required because it appears within the type `PhantomData<&T>` +note: required because it appears within the type `Guard<'_, T>` + --> $DIR/phantom-auto-trait.rs:12:8 + | +LL | struct Guard<'a, T: 'a> { + | ^^^^^ +note: required because it appears within the type `Nested>` + --> $DIR/phantom-auto-trait.rs:16:8 + | +LL | struct Nested(T); + | ^^^^^^ +note: required by a bound in `is_zen` + --> $DIR/phantom-auto-trait.rs:18:14 + | +LL | fn is_zen(_: T) {} + | ^^^ required by this bound in `is_zen` +help: consider restricting type parameter `T` + | +LL | fn nested_not_sync(x: Nested>) { + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs new file mode 100644 index 000000000..5826a18b5 --- /dev/null +++ b/tests/ui/pin-macro/cant_access_internals.rs @@ -0,0 +1,12 @@ +// edition:2018 + +use core::{ + marker::PhantomPinned, + mem, + pin::{pin, Pin}, +}; + +fn main() { + let mut phantom_pinned = pin!(PhantomPinned); + mem::take(phantom_pinned.pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals' +} diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr new file mode 100644 index 000000000..d43027657 --- /dev/null +++ b/tests/ui/pin-macro/cant_access_internals.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unsafe_pin_internals' + --> $DIR/cant_access_internals.rs:11:15 + | +LL | mem::take(phantom_pinned.pointer); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs new file mode 100644 index 000000000..59774bc75 --- /dev/null +++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs @@ -0,0 +1,28 @@ +// edition:2018 + +use core::{ + convert::identity, + marker::PhantomPinned, + mem::drop as stuff, + pin::pin, +}; + +fn function_call_stops_borrow_extension() { + let phantom_pinned = identity(pin!(PhantomPinned)); + //~^ ERROR temporary value dropped while borrowed + stuff(phantom_pinned) +} + +fn promotion_only_works_for_the_innermost_block() { + let phantom_pinned = { + let phantom_pinned = pin!(PhantomPinned); + //~^ ERROR temporary value dropped while borrowed + phantom_pinned + }; + stuff(phantom_pinned) +} + +fn main() { + function_call_stops_borrow_extension(); + promotion_only_works_for_the_innermost_block(); +} diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr new file mode 100644 index 000000000..4ecc6370d --- /dev/null +++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr @@ -0,0 +1,31 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35 + | +LL | let phantom_pinned = identity(pin!(PhantomPinned)); + | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | +LL | stuff(phantom_pinned) + | -------------- borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30 + | +LL | let phantom_pinned = { + | -------------- borrow later stored here +LL | let phantom_pinned = pin!(PhantomPinned); + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +... +LL | }; + | - temporary value is freed at the end of this statement + | + = note: consider using a `let` binding to create a longer lived value + = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.rs b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.rs new file mode 100644 index 000000000..50f1fe873 --- /dev/null +++ b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.rs @@ -0,0 +1,17 @@ +fn unrelated() -> Result<(), std::string::ParseError> { // #57664 + let x = 0; + + match x { + 1 => { + let property_value_as_string = "a".parse()?; + } + 2 => { + let value: &bool = unsafe { &42 }; + //~^ ERROR mismatched types + } + }; + + Ok(()) +} + +fn main() {} diff --git a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr new file mode 100644 index 000000000..f5a5f1ab3 --- /dev/null +++ b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41 + | +LL | let value: &bool = unsafe { &42 }; + | ^^^ expected `bool`, found integer + | + = note: expected reference `&bool` + found reference `&{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/polymorphization/closure_in_upvar/fn.rs b/tests/ui/polymorphization/closure_in_upvar/fn.rs new file mode 100644 index 000000000..e10308588 --- /dev/null +++ b/tests/ui/polymorphization/closure_in_upvar/fn.rs @@ -0,0 +1,29 @@ +// build-pass +// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 + +fn foo(f: impl Fn()) { + let x = |_: ()| (); + + // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to + // `x` that will differ for each instantiation despite polymorphisation of the varying + // argument. + let y = || x(()); + + // Consider `f` used in `foo`. + f(); + // Use `y` so that it is visited in monomorphisation collection. + y(); +} + +fn entry_a() { + foo(|| ()); +} + +fn entry_b() { + foo(|| ()); +} + +fn main() { + entry_a(); + entry_b(); +} diff --git a/tests/ui/polymorphization/closure_in_upvar/fnmut.rs b/tests/ui/polymorphization/closure_in_upvar/fnmut.rs new file mode 100644 index 000000000..62164ff94 --- /dev/null +++ b/tests/ui/polymorphization/closure_in_upvar/fnmut.rs @@ -0,0 +1,34 @@ +// build-pass +// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 + +fn foo(f: impl Fn()) { + // Mutate an upvar from `x` so that it implements `FnMut`. + let mut outer = 3; + let mut x = |_: ()| { + outer = 4; + () + }; + + // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to + // `x` that will differ for each instantiation despite polymorphisation of the varying + // argument. + let mut y = || x(()); + + // Consider `f` used in `foo`. + f(); + // Use `y` so that it is visited in monomorphisation collection. + y(); +} + +fn entry_a() { + foo(|| ()); +} + +fn entry_b() { + foo(|| ()); +} + +fn main() { + entry_a(); + entry_b(); +} diff --git a/tests/ui/polymorphization/closure_in_upvar/fnonce.rs b/tests/ui/polymorphization/closure_in_upvar/fnonce.rs new file mode 100644 index 000000000..7a364882f --- /dev/null +++ b/tests/ui/polymorphization/closure_in_upvar/fnonce.rs @@ -0,0 +1,34 @@ +// build-pass +// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 + +fn foo(f: impl Fn()) { + // Move a non-copy type into `x` so that it implements `FnOnce`. + let outer = Vec::::new(); + let x = move |_: ()| { + let inner = outer; + () + }; + + // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to + // `x` that will differ for each instantiation despite polymorphisation of the varying + // argument. + let y = || x(()); + + // Consider `f` used in `foo`. + f(); + // Use `y` so that it is visited in monomorphisation collection. + y(); +} + +fn entry_a() { + foo(|| ()); +} + +fn entry_b() { + foo(|| ()); +} + +fn main() { + entry_a(); + entry_b(); +} diff --git a/tests/ui/polymorphization/closure_in_upvar/other.rs b/tests/ui/polymorphization/closure_in_upvar/other.rs new file mode 100644 index 000000000..27d59ec88 --- /dev/null +++ b/tests/ui/polymorphization/closure_in_upvar/other.rs @@ -0,0 +1,38 @@ +// build-pass +// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 + +fn y_uses_f(f: impl Fn()) { + let x = |_: ()| (); + + let y = || { + f(); + x(()); + }; + + f(); + y(); +} + +fn x_uses_f(f: impl Fn()) { + let x = |_: ()| { f(); }; + + let y = || x(()); + + f(); + y(); +} + +fn entry_a() { + x_uses_f(|| ()); + y_uses_f(|| ()); +} + +fn entry_b() { + x_uses_f(|| ()); + y_uses_f(|| ()); +} + +fn main() { + entry_a(); + entry_b(); +} diff --git a/tests/ui/polymorphization/const_parameters/closures.rs b/tests/ui/polymorphization/const_parameters/closures.rs new file mode 100644 index 000000000..2f41beeb9 --- /dev/null +++ b/tests/ui/polymorphization/const_parameters/closures.rs @@ -0,0 +1,67 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![feature(generic_const_exprs, rustc_attrs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +// This test checks that the polymorphization analysis correctly detects unused const +// parameters in closures. + +// Function doesn't have any generic parameters to be unused. +#[rustc_polymorphize_error] +pub fn no_parameters() { + let _ = || {}; +} + +// Function has an unused generic parameter in parent and closure. +#[rustc_polymorphize_error] +pub fn unused() -> usize { + //~^ ERROR item has unused generic parameters + let add_one = |x: usize| x + 1; + //~^ ERROR item has unused generic parameters + add_one(3) +} + +// Function has an unused generic parameter in closure, but not in parent. +#[rustc_polymorphize_error] +pub fn used_parent() -> usize { + let x: usize = T; + let add_one = |x: usize| x + 1; + //~^ ERROR item has unused generic parameters + x + add_one(3) +} + +// Function uses generic parameter in value of a binding in closure. +#[rustc_polymorphize_error] +pub fn used_binding() -> usize { + let x = || { + let y: usize = T; + y + }; + + x() +} + +// Closure uses a value as an upvar, which used the generic parameter. +#[rustc_polymorphize_error] +pub fn unused_upvar() -> usize { + let x: usize = T; + let y = || x; + //~^ ERROR item has unused generic parameters + y() +} + +// Closure uses generic parameter in substitutions to another function. +#[rustc_polymorphize_error] +pub fn used_substs() -> usize { + let x = || unused::(); + x() +} + +fn main() { + no_parameters(); + let _ = unused::<1>(); + let _ = used_parent::<1>(); + let _ = used_binding::<1>(); + let _ = unused_upvar::<1>(); + let _ = used_substs::<1>(); +} diff --git a/tests/ui/polymorphization/const_parameters/closures.stderr b/tests/ui/polymorphization/const_parameters/closures.stderr new file mode 100644 index 000000000..4e927f773 --- /dev/null +++ b/tests/ui/polymorphization/const_parameters/closures.stderr @@ -0,0 +1,44 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closures.rs:3:12 + | +LL | #![feature(generic_const_exprs, rustc_attrs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: item has unused generic parameters + --> $DIR/closures.rs:19:19 + | +LL | pub fn unused() -> usize { + | -------------- generic parameter `T` is unused +LL | +LL | let add_one = |x: usize| x + 1; + | ^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:17:8 + | +LL | pub fn unused() -> usize { + | ^^^^^^ -------------- generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:28:19 + | +LL | pub fn used_parent() -> usize { + | -------------- generic parameter `T` is unused +LL | let x: usize = T; +LL | let add_one = |x: usize| x + 1; + | ^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:48:13 + | +LL | pub fn unused_upvar() -> usize { + | -------------- generic parameter `T` is unused +LL | let x: usize = T; +LL | let y = || x; + | ^^ + +error: aborting due to 4 previous errors; 1 warning emitted + diff --git a/tests/ui/polymorphization/const_parameters/functions.rs b/tests/ui/polymorphization/const_parameters/functions.rs new file mode 100644 index 000000000..cbc1b63fb --- /dev/null +++ b/tests/ui/polymorphization/const_parameters/functions.rs @@ -0,0 +1,37 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![feature(generic_const_exprs, rustc_attrs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +// This test checks that the polymorphization analysis correctly detects unused const +// parameters in functions. + +// Function doesn't have any generic parameters to be unused. +#[rustc_polymorphize_error] +pub fn no_parameters() {} + +// Function has an unused generic parameter. +#[rustc_polymorphize_error] +pub fn unused() { + //~^ ERROR item has unused generic parameters +} + +// Function uses generic parameter in value of a binding. +#[rustc_polymorphize_error] +pub fn used_binding() -> usize { + let x: usize = T; + x +} + +// Function uses generic parameter in substitutions to another function. +#[rustc_polymorphize_error] +pub fn used_substs() { + unused::() +} + +fn main() { + no_parameters(); + unused::<1>(); + used_binding::<1>(); + used_substs::<1>(); +} diff --git a/tests/ui/polymorphization/const_parameters/functions.stderr b/tests/ui/polymorphization/const_parameters/functions.stderr new file mode 100644 index 000000000..9d0922ac7 --- /dev/null +++ b/tests/ui/polymorphization/const_parameters/functions.stderr @@ -0,0 +1,17 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/functions.rs:3:12 + | +LL | #![feature(generic_const_exprs, rustc_attrs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: item has unused generic parameters + --> $DIR/functions.rs:15:8 + | +LL | pub fn unused() { + | ^^^^^^ -------------- generic parameter `T` is unused + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/polymorphization/drop_shims/simple.rs b/tests/ui/polymorphization/drop_shims/simple.rs new file mode 100644 index 000000000..2695dc6d4 --- /dev/null +++ b/tests/ui/polymorphization/drop_shims/simple.rs @@ -0,0 +1,22 @@ +// check-pass +// compile-flags:-Zpolymorphize=on + +pub struct OnDrop(pub F); + +impl Drop for OnDrop { + fn drop(&mut self) { } +} + +fn foo( + _: R, + _: S, +) { + let bar = || { + let _ = OnDrop(|| ()); + }; + let _ = bar(); +} + +fn main() { + foo(3u32, || {}); +} diff --git a/tests/ui/polymorphization/drop_shims/transitive.rs b/tests/ui/polymorphization/drop_shims/transitive.rs new file mode 100644 index 000000000..c22891171 --- /dev/null +++ b/tests/ui/polymorphization/drop_shims/transitive.rs @@ -0,0 +1,27 @@ +// check-pass +// compile-flags:-Zpolymorphize=on + +pub struct OnDrop(pub F); + +impl Drop for OnDrop { + fn drop(&mut self) { } +} + +fn bar(f: F) { + let _ = OnDrop(|| ()); + f() +} + +fn foo( + _: R, + _: S, +) { + let bar = || { + bar(|| {}) + }; + let _ = bar(); +} + +fn main() { + foo(3u32, || {}); +} diff --git a/tests/ui/polymorphization/generators.rs b/tests/ui/polymorphization/generators.rs new file mode 100644 index 000000000..779bac0ac --- /dev/null +++ b/tests/ui/polymorphization/generators.rs @@ -0,0 +1,92 @@ +// build-fail +// compile-flags:-Zpolymorphize=on -Zinline-mir=off +#![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +use std::marker::Unpin; +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +enum YieldOrReturn { + Yield(Y), + Return(R), +} + +fn finish(mut t: T) -> Vec> +where + T: Generator<(), Yield = Y, Return = R> + Unpin, +{ + let mut results = Vec::new(); + loop { + match Pin::new(&mut t).resume(()) { + GeneratorState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)), + GeneratorState::Complete(returned) => { + results.push(YieldOrReturn::Return(returned)); + return results; + } + } + } +} + +// This test checks that the polymorphization analysis functions on generators. + +#[rustc_polymorphize_error] +pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + || { + //~^ ERROR item has unused generic parameters + yield 1; + 2 + } +} + +#[rustc_polymorphize_error] +pub fn used_type_in_yield() -> impl Generator<(), Yield = Y, Return = u32> + Unpin { + || { + yield Y::default(); + 2 + } +} + +#[rustc_polymorphize_error] +pub fn used_type_in_return() -> impl Generator<(), Yield = u32, Return = R> + Unpin { + || { + yield 3; + R::default() + } +} + +#[rustc_polymorphize_error] +pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + || { + //~^ ERROR item has unused generic parameters + yield 1; + 2 + } +} + +#[rustc_polymorphize_error] +pub fn used_const_in_yield() -> impl Generator<(), Yield = u32, Return = u32> + Unpin +{ + || { + yield Y; + 2 + } +} + +#[rustc_polymorphize_error] +pub fn used_const_in_return() -> impl Generator<(), Yield = u32, Return = u32> + Unpin +{ + || { + yield 4; + R + } +} + +fn main() { + finish(unused_type::()); + finish(used_type_in_yield::()); + finish(used_type_in_return::()); + finish(unused_const::<1u32>()); + finish(used_const_in_yield::<1u32>()); + finish(used_const_in_return::<1u32>()); +} diff --git a/tests/ui/polymorphization/generators.stderr b/tests/ui/polymorphization/generators.stderr new file mode 100644 index 000000000..84888f6fb --- /dev/null +++ b/tests/ui/polymorphization/generators.stderr @@ -0,0 +1,39 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/generators.rs:3:12 + | +LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: item has unused generic parameters + --> $DIR/generators.rs:35:5 + | +LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | - generic parameter `T` is unused +LL | || { + | ^^ + +note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:35:5: 35:7], u32, u32>` + --> $DIR/generators.rs:86:5 + | +LL | finish(unused_type::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/generators.rs:60:5 + | +LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | ------------ generic parameter `T` is unused +LL | || { + | ^^ + +note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:60:5: 60:7], u32, u32>` + --> $DIR/generators.rs:89:5 + | +LL | finish(unused_const::<1u32>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/polymorphization/issue-74614.rs b/tests/ui/polymorphization/issue-74614.rs new file mode 100644 index 000000000..8b0c00b13 --- /dev/null +++ b/tests/ui/polymorphization/issue-74614.rs @@ -0,0 +1,18 @@ +// compile-flags:-Zpolymorphize=on +// build-pass + +fn test() { + std::mem::size_of::(); +} + +pub fn foo(_: T) -> &'static fn() { + &(test:: as fn()) +} + +fn outer() { + foo(|| ()); +} + +fn main() { + outer::(); +} diff --git a/tests/ui/polymorphization/issue-74636.rs b/tests/ui/polymorphization/issue-74636.rs new file mode 100644 index 000000000..4c532f451 --- /dev/null +++ b/tests/ui/polymorphization/issue-74636.rs @@ -0,0 +1,16 @@ +// compile-flags:-Zpolymorphize=on +// build-pass + +use std::any::TypeId; + +pub fn foo(_: T) -> TypeId { + TypeId::of::() +} + +fn outer() { + foo(|| ()); +} + +fn main() { + outer::(); +} diff --git a/tests/ui/polymorphization/lifetimes.rs b/tests/ui/polymorphization/lifetimes.rs new file mode 100644 index 000000000..f26df4523 --- /dev/null +++ b/tests/ui/polymorphization/lifetimes.rs @@ -0,0 +1,25 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![feature(rustc_attrs)] + +// This test checks that the polymorphization analysis doesn't break when the +// function/closure doesn't just have generic parameters. + +// Function has an unused generic parameter. +#[rustc_polymorphize_error] +pub fn unused<'a, T>(_: &'a u32) { + //~^ ERROR item has unused generic parameters +} + +#[rustc_polymorphize_error] +pub fn used<'a, T: Default>(_: &'a u32) -> u32 { + let _: T = Default::default(); + let add_one = |x: u32| x + 1; + //~^ ERROR item has unused generic parameters + add_one(3) +} + +fn main() { + unused::(&3); + used::(&3); +} diff --git a/tests/ui/polymorphization/lifetimes.stderr b/tests/ui/polymorphization/lifetimes.stderr new file mode 100644 index 000000000..4773dd4fa --- /dev/null +++ b/tests/ui/polymorphization/lifetimes.stderr @@ -0,0 +1,17 @@ +error: item has unused generic parameters + --> $DIR/lifetimes.rs:10:8 + | +LL | pub fn unused<'a, T>(_: &'a u32) { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/lifetimes.rs:17:19 + | +LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/polymorphization/normalized_sig_types.rs b/tests/ui/polymorphization/normalized_sig_types.rs new file mode 100644 index 000000000..d732b1071 --- /dev/null +++ b/tests/ui/polymorphization/normalized_sig_types.rs @@ -0,0 +1,26 @@ +// build-pass +// compile-flags:-Zpolymorphize=on + +pub trait ParallelIterator: Sized { + fn drive>(_: C) { + C::into_folder(); + } +} + +pub trait Consumer: Sized { + type Result; + fn into_folder() -> Self::Result; +} + +impl ParallelIterator for () {} + +impl Consumer for F { + type Result = (); + fn into_folder() -> Self::Result { + unimplemented!() + } +} + +fn main() { + <()>::drive(|| ()); +} diff --git a/tests/ui/polymorphization/predicates.rs b/tests/ui/polymorphization/predicates.rs new file mode 100644 index 000000000..6a5fc2e33 --- /dev/null +++ b/tests/ui/polymorphization/predicates.rs @@ -0,0 +1,95 @@ +// build-fail +// compile-flags: -Copt-level=0 -Zpolymorphize=on + +#![feature(rustc_attrs)] + +// This test checks that `T` is considered used in `foo`, because it is used in a predicate for +// `I`, which is used. + +#[rustc_polymorphize_error] +fn bar() { + //~^ ERROR item has unused generic parameters +} + +#[rustc_polymorphize_error] +fn foo(_: I) +//~^ ERROR item has unused generic parameters +where + I: Iterator, +{ + bar::() +} + +#[rustc_polymorphize_error] +fn baz(_: I) +//~^ ERROR item has unused generic parameters +where + std::iter::Repeat: Iterator, +{ + bar::() +} + +// In addition, check that `I` is considered used in `next::{{closure}}`, because `T` is used and +// `T` is really just `I::Item`. `E` is used due to the fixed-point marking of predicates. + +pub(crate) struct Foo<'a, I, E>(I, &'a E); + +impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> +where + I: Iterator, +{ + type Item = T; + + #[rustc_polymorphize_error] + fn next(&mut self) -> Option { + self.find(|_| true) + //~^ ERROR item has unused generic parameters + } +} + +// Furthermore, check that `B` is considered used because `C` is used, and that `A` is considered +// used because `B` is now used. + +trait Baz {} + +impl Baz for u8 {} +impl Baz for u16 {} + +#[rustc_polymorphize_error] +fn quux() -> usize +//~^ ERROR item has unused generic parameters +where + A: Baz, + B: Baz, +{ + std::mem::size_of::() +} + +// Finally, check that `F` is considered used because `G` is used when neither are in the self-ty +// of the predicate. + +trait Foobar {} + +impl Foobar for () {} + +#[rustc_polymorphize_error] +fn foobar() -> usize +//~^ ERROR item has unused generic parameters +where + (): Foobar, +{ + std::mem::size_of::() +} + +fn main() { + let x = &[2u32]; + foo(x.iter()); + baz(x.iter()); + + let mut a = Foo([(1u32, 1u16)].iter(), &1u16); + let _ = a.next(); + + let _ = quux::(); + + let _ = foobar::(); +} diff --git a/tests/ui/polymorphization/predicates.stderr b/tests/ui/polymorphization/predicates.stderr new file mode 100644 index 000000000..80bb2af25 --- /dev/null +++ b/tests/ui/polymorphization/predicates.stderr @@ -0,0 +1,51 @@ +error: item has unused generic parameters + --> $DIR/predicates.rs:15:4 + | +LL | fn foo(_: I) + | ^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:24:4 + | +LL | fn baz(_: I) + | ^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:45:19 + | +LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> + | - - generic parameter `E` is unused + | | + | generic parameter `I` is unused +... +LL | self.find(|_| true) + | ^^^ + +error: item has unused generic parameters + --> $DIR/predicates.rs:59:4 + | +LL | fn quux() -> usize + | ^^^^ - - generic parameter `B` is unused + | | + | generic parameter `A` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:76:4 + | +LL | fn foobar() -> usize + | ^^^^^^ - generic parameter `F` is unused + +error: item has unused generic parameters + --> $DIR/predicates.rs:10:4 + | +LL | fn bar() { + | ^^^ - generic parameter `I` is unused + +note: the above error was encountered while instantiating `fn foo::, T>` + --> $DIR/predicates.rs:86:5 + | +LL | foo(x.iter()); + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/polymorphization/promoted-function-1.rs b/tests/ui/polymorphization/promoted-function-1.rs new file mode 100644 index 000000000..2cd026734 --- /dev/null +++ b/tests/ui/polymorphization/promoted-function-1.rs @@ -0,0 +1,12 @@ +// build-fail +// compile-flags: -Zpolymorphize=on +#![crate_type = "lib"] +#![feature(rustc_attrs)] + +fn foo<'a>(_: &'a ()) {} + +#[rustc_polymorphize_error] +pub fn test() { + //~^ ERROR item has unused generic parameters + foo(&()); +} diff --git a/tests/ui/polymorphization/promoted-function-1.stderr b/tests/ui/polymorphization/promoted-function-1.stderr new file mode 100644 index 000000000..fcbb86949 --- /dev/null +++ b/tests/ui/polymorphization/promoted-function-1.stderr @@ -0,0 +1,8 @@ +error: item has unused generic parameters + --> $DIR/promoted-function-1.rs:9:8 + | +LL | pub fn test() { + | ^^^^ - generic parameter `T` is unused + +error: aborting due to previous error + diff --git a/tests/ui/polymorphization/promoted-function-2.rs b/tests/ui/polymorphization/promoted-function-2.rs new file mode 100644 index 000000000..d2d0f3368 --- /dev/null +++ b/tests/ui/polymorphization/promoted-function-2.rs @@ -0,0 +1,16 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![crate_type = "lib"] +#![feature(generic_const_exprs, rustc_attrs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +#[rustc_polymorphize_error] +fn test() { + //~^ ERROR item has unused generic parameters + let x = [0; 3 + 4]; +} + +pub fn caller() { + test::(); + test::>(); +} diff --git a/tests/ui/polymorphization/promoted-function-2.stderr b/tests/ui/polymorphization/promoted-function-2.stderr new file mode 100644 index 000000000..547569df7 --- /dev/null +++ b/tests/ui/polymorphization/promoted-function-2.stderr @@ -0,0 +1,17 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/promoted-function-2.rs:4:12 + | +LL | #![feature(generic_const_exprs, rustc_attrs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: item has unused generic parameters + --> $DIR/promoted-function-2.rs:8:4 + | +LL | fn test() { + | ^^^^ - generic parameter `T` is unused + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/polymorphization/promoted-function-3.rs b/tests/ui/polymorphization/promoted-function-3.rs new file mode 100644 index 000000000..bbd991e36 --- /dev/null +++ b/tests/ui/polymorphization/promoted-function-3.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -Zpolymorphize=on -Zmir-opt-level=4 + +fn caller() -> &'static usize { + callee::() +} + +fn callee() -> &'static usize { + &std::mem::size_of::() +} + +fn main() { + assert_eq!(caller::<(), ()>(), &0); +} diff --git a/tests/ui/polymorphization/promoted-function.rs b/tests/ui/polymorphization/promoted-function.rs new file mode 100644 index 000000000..a56a8e70e --- /dev/null +++ b/tests/ui/polymorphization/promoted-function.rs @@ -0,0 +1,15 @@ +// run-pass +// compile-flags:-Zpolymorphize=on + +fn fop() {} + +fn bar() -> &'static fn() { + &(fop:: as fn()) +} +pub const FN: &'static fn() = &(fop:: as fn()); + +fn main() { + bar::(); + bar::(); + (FN)(); +} diff --git a/tests/ui/polymorphization/symbol-ambiguity.rs b/tests/ui/polymorphization/symbol-ambiguity.rs new file mode 100644 index 000000000..6277a902f --- /dev/null +++ b/tests/ui/polymorphization/symbol-ambiguity.rs @@ -0,0 +1,22 @@ +// build-pass +// compile-flags: -Zpolymorphize=on -Csymbol-mangling-version=v0 + +pub(crate) struct Foo<'a, I, E>(I, &'a E); + +impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> +where + I: Iterator, +{ + type Item = T; + + fn next(&mut self) -> Option { + self.find(|_| true) + } +} + +fn main() { + let mut a = Foo([(1u32, 1u16)].iter(), &1u16); + let mut b = Foo([(1u16, 1u32)].iter(), &1u32); + let _ = a.next(); + let _ = b.next(); +} diff --git a/tests/ui/polymorphization/too-many-generic-params.rs b/tests/ui/polymorphization/too-many-generic-params.rs new file mode 100644 index 000000000..ec6244630 --- /dev/null +++ b/tests/ui/polymorphization/too-many-generic-params.rs @@ -0,0 +1,85 @@ +// build-pass +#![feature(rustc_attrs)] + +// This test checks that the analysis doesn't panic when there are >64 generic parameters, but +// instead considers those parameters used. + +#[rustc_polymorphize_error] +fn bar() +{ + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option

= None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; +} + +fn main() { + bar::(); +} diff --git a/tests/ui/polymorphization/type_parameters/closures.rs b/tests/ui/polymorphization/type_parameters/closures.rs new file mode 100644 index 000000000..07ab1355a --- /dev/null +++ b/tests/ui/polymorphization/type_parameters/closures.rs @@ -0,0 +1,161 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![feature(stmt_expr_attributes, rustc_attrs)] + +// This test checks that the polymorphization analysis correctly detects unused type +// parameters in closures. + +// Function doesn't have any generic parameters to be unused. +#[rustc_polymorphize_error] +pub fn no_parameters() { + let _ = || {}; +} + +// Function has an unused generic parameter in parent and closure. +#[rustc_polymorphize_error] +pub fn unused() -> u32 { + //~^ ERROR item has unused generic parameters + + let add_one = |x: u32| x + 1; + //~^ ERROR item has unused generic parameters + add_one(3) +} + +// Function has an unused generic parameter in closure, but not in parent. +#[rustc_polymorphize_error] +pub fn used_parent() -> u32 { + let _: T = Default::default(); + let add_one = |x: u32| x + 1; + //~^ ERROR item has unused generic parameters + add_one(3) +} + +// Function uses generic parameter in value of a binding in closure. +#[rustc_polymorphize_error] +pub fn used_binding_value() -> T { + let x = || { + let y: T = Default::default(); + y + }; + + x() +} + +// Function uses generic parameter in generic of a binding in closure. +#[rustc_polymorphize_error] +pub fn used_binding_generic() -> Option { + let x = || { + let y: Option = None; + y + }; + + x() +} + +// Function and closure uses generic parameter in argument. +#[rustc_polymorphize_error] +pub fn used_argument(t: T) -> u32 { + let x = |_: T| 3; + x(t) +} + +// Closure uses generic parameter in argument. +#[rustc_polymorphize_error] +pub fn used_argument_closure() -> u32 { + let t: T = Default::default(); + + let x = |_: T| 3; + x(t) +} + +// Closure uses generic parameter as upvar. +#[rustc_polymorphize_error] +pub fn used_upvar() -> T { + let x: T = Default::default(); + + let y = || x; + y() +} + +// Closure uses generic parameter in substitutions to another function. +#[rustc_polymorphize_error] +pub fn used_substs() -> u32 { + let x = || unused::(); + x() +} + +struct Foo(F); + +impl Foo { + // Function has an unused generic parameter from impl and fn. + #[rustc_polymorphize_error] + pub fn unused_all() -> u32 { + //~^ ERROR item has unused generic parameters + let add_one = |x: u32| x + 1; + //~^ ERROR item has unused generic parameters + add_one(3) + } + + // Function uses generic parameter from impl and fn in closure. + #[rustc_polymorphize_error] + pub fn used_both() -> u32 { + let add_one = |x: u32| { + let _: F = Default::default(); + let _: G = Default::default(); + x + 1 + }; + + add_one(3) + } + + // Function uses generic parameter from fn in closure. + #[rustc_polymorphize_error] + pub fn used_fn() -> u32 { + //~^ ERROR item has unused generic parameters + let add_one = |x: u32| { + //~^ ERROR item has unused generic parameters + let _: G = Default::default(); + x + 1 + }; + + add_one(3) + } + + // Function uses generic parameter from impl in closure. + #[rustc_polymorphize_error] + pub fn used_impl() -> u32 { + //~^ ERROR item has unused generic parameters + let add_one = |x: u32| { + //~^ ERROR item has unused generic parameters + let _: F = Default::default(); + x + 1 + }; + + add_one(3) + } + + // Closure uses generic parameter in substitutions to another function. + #[rustc_polymorphize_error] + pub fn used_substs() -> u32 { + let x = || unused::(); + x() + } +} + +fn main() { + no_parameters(); + let _ = unused::(); + let _ = used_parent::(); + let _ = used_binding_value::(); + let _ = used_binding_generic::(); + let _ = used_argument(3u32); + let _ = used_argument_closure::(); + let _ = used_upvar::(); + let _ = used_substs::(); + + let _ = Foo::::unused_all::(); + let _ = Foo::::used_both::(); + let _ = Foo::::used_impl::(); + let _ = Foo::::used_fn::(); + let _ = Foo::::used_substs(); +} diff --git a/tests/ui/polymorphization/type_parameters/closures.stderr b/tests/ui/polymorphization/type_parameters/closures.stderr new file mode 100644 index 000000000..94a4a08bd --- /dev/null +++ b/tests/ui/polymorphization/type_parameters/closures.stderr @@ -0,0 +1,80 @@ +error: item has unused generic parameters + --> $DIR/closures.rs:19:19 + | +LL | pub fn unused() -> u32 { + | - generic parameter `T` is unused +... +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:16:8 + | +LL | pub fn unused() -> u32 { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:28:19 + | +LL | pub fn used_parent() -> u32 { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:94:23 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn unused_all() -> u32 { + | - generic parameter `G` is unused +LL | +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:92:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn unused_all() -> u32 { + | ^^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:128:23 + | +LL | pub fn used_impl() -> u32 { + | - generic parameter `G` is unused +LL | +LL | let add_one = |x: u32| { + | ^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:126:12 + | +LL | pub fn used_impl() -> u32 { + | ^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:115:23 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | let add_one = |x: u32| { + | ^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:113:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn used_fn() -> u32 { + | ^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/polymorphization/type_parameters/functions.rs b/tests/ui/polymorphization/type_parameters/functions.rs new file mode 100644 index 000000000..aad957e1d --- /dev/null +++ b/tests/ui/polymorphization/type_parameters/functions.rs @@ -0,0 +1,96 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![feature(rustc_attrs)] + +// This test checks that the polymorphization analysis correctly detects unused type +// parameters in functions. + +// Function doesn't have any generic parameters to be unused. +#[rustc_polymorphize_error] +pub fn no_parameters() {} + +// Function has an unused generic parameter. +#[rustc_polymorphize_error] +pub fn unused() { + //~^ ERROR item has unused generic parameters +} + +// Function uses generic parameter in value of a binding. +#[rustc_polymorphize_error] +pub fn used_binding_value() { + let _: T = Default::default(); +} + +// Function uses generic parameter in generic of a binding. +#[rustc_polymorphize_error] +pub fn used_binding_generic() { + let _: Option = None; +} + +// Function uses generic parameter in argument. +#[rustc_polymorphize_error] +pub fn used_argument(_: T) {} + +// Function uses generic parameter in substitutions to another function. +#[rustc_polymorphize_error] +pub fn used_substs() { + unused::() +} + +struct Foo(F); + +impl Foo { + // Function has an unused generic parameter from impl. + #[rustc_polymorphize_error] + pub fn unused_impl() { + //~^ ERROR item has unused generic parameters + } + + // Function has an unused generic parameter from impl and fn. + #[rustc_polymorphize_error] + pub fn unused_both() { + //~^ ERROR item has unused generic parameters + } + + // Function uses generic parameter from impl. + #[rustc_polymorphize_error] + pub fn used_impl() { + let _: F = Default::default(); + } + + // Function uses generic parameter from impl. + #[rustc_polymorphize_error] + pub fn used_fn() { + //~^ ERROR item has unused generic parameters + let _: G = Default::default(); + } + + // Function uses generic parameter from impl. + #[rustc_polymorphize_error] + pub fn used_both() { + let _: F = Default::default(); + let _: G = Default::default(); + } + + // Function uses generic parameter in substitutions to another function. + #[rustc_polymorphize_error] + pub fn used_substs() { + unused::() + } +} + +fn main() { + no_parameters(); + unused::(); + used_binding_value::(); + used_binding_generic::(); + used_argument(3u32); + used_substs::(); + + Foo::::unused_impl(); + Foo::::unused_both::(); + Foo::::used_impl(); + Foo::::used_fn::(); + Foo::::used_both::(); + Foo::::used_substs(); +} diff --git a/tests/ui/polymorphization/type_parameters/functions.stderr b/tests/ui/polymorphization/type_parameters/functions.stderr new file mode 100644 index 000000000..d629ff7bb --- /dev/null +++ b/tests/ui/polymorphization/type_parameters/functions.stderr @@ -0,0 +1,35 @@ +error: item has unused generic parameters + --> $DIR/functions.rs:14:8 + | +LL | pub fn unused() { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/functions.rs:45:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn unused_impl() { + | ^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/functions.rs:51:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn unused_both() { + | ^^^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/functions.rs:63:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn used_fn() { + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/polymorphization/unsized_cast.rs b/tests/ui/polymorphization/unsized_cast.rs new file mode 100644 index 000000000..b803fec2c --- /dev/null +++ b/tests/ui/polymorphization/unsized_cast.rs @@ -0,0 +1,30 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![feature(fn_traits, rustc_attrs, unboxed_closures)] + +// This test checks that the polymorphization analysis considers a closure +// as using all generic parameters if it does an unsizing cast. + +#[rustc_polymorphize_error] +fn foo() { + let _: T = Default::default(); + (|| Box::new(|| {}) as Box)(); + //~^ ERROR item has unused generic parameters + //~^^ ERROR item has unused generic parameters +} + +#[rustc_polymorphize_error] +fn foo2() { + let _: T = Default::default(); + (|| { + //~^ ERROR item has unused generic parameters + let call: extern "rust-call" fn(_, _) = Fn::call; + call(&|| {}, ()); + //~^ ERROR item has unused generic parameters + })(); +} + +fn main() { + foo::(); + foo2::(); +} diff --git a/tests/ui/polymorphization/unsized_cast.stderr b/tests/ui/polymorphization/unsized_cast.stderr new file mode 100644 index 000000000..27f88d281 --- /dev/null +++ b/tests/ui/polymorphization/unsized_cast.stderr @@ -0,0 +1,38 @@ +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:11:18 + | +LL | fn foo() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box)(); + | ^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:11:6 + | +LL | fn foo() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box)(); + | ^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:22:15 + | +LL | fn foo2() { + | - generic parameter `T` is unused +... +LL | call(&|| {}, ()); + | ^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:19:6 + | +LL | fn foo2() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| { + | ^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/pptypedef.rs b/tests/ui/pptypedef.rs new file mode 100644 index 000000000..e28d323f8 --- /dev/null +++ b/tests/ui/pptypedef.rs @@ -0,0 +1,11 @@ +fn let_in(x: T, f: F) where F: FnOnce(T) {} + +fn main() { + let_in(3u32, |i| { assert!(i == 3i32); }); + //~^ ERROR mismatched types + //~| expected `u32`, found `i32` + + let_in(3i32, |i| { assert!(i == 3u32); }); + //~^ ERROR mismatched types + //~| expected `i32`, found `u32` +} diff --git a/tests/ui/pptypedef.stderr b/tests/ui/pptypedef.stderr new file mode 100644 index 000000000..08b90b365 --- /dev/null +++ b/tests/ui/pptypedef.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> $DIR/pptypedef.rs:4:37 + | +LL | let_in(3u32, |i| { assert!(i == 3i32); }); + | - ^^^^ expected `u32`, found `i32` + | | + | expected because this is `u32` + | +help: change the type of the numeric literal from `i32` to `u32` + | +LL | let_in(3u32, |i| { assert!(i == 3u32); }); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/pptypedef.rs:8:37 + | +LL | let_in(3i32, |i| { assert!(i == 3u32); }); + | - ^^^^ expected `i32`, found `u32` + | | + | expected because this is `i32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | let_in(3i32, |i| { assert!(i == 3i32); }); + | ~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/primitive-binop-lhs-mut.rs b/tests/ui/primitive-binop-lhs-mut.rs new file mode 100644 index 000000000..4f1c456ac --- /dev/null +++ b/tests/ui/primitive-binop-lhs-mut.rs @@ -0,0 +1,6 @@ +// run-pass + +fn main() { + let x = Box::new(0); + assert_eq!(0, *x + { drop(x); let _ = Box::new(main); 0 }); +} diff --git a/tests/ui/print-fuel/print-fuel.rs b/tests/ui/print-fuel/print-fuel.rs new file mode 100644 index 000000000..f68de00b9 --- /dev/null +++ b/tests/ui/print-fuel/print-fuel.rs @@ -0,0 +1,13 @@ +#![crate_name="foo"] +#![allow(dead_code)] + +// (#55495: The --error-format is to sidestep an issue in our test harness) +// compile-flags: -C opt-level=0 --error-format human -Z print-fuel=foo +// check-pass + +struct S1(u8, u16, u8); +struct S2(u8, u16, u8); +struct S3(u8, u16, u8); + +fn main() { +} diff --git a/tests/ui/print-fuel/print-fuel.stderr b/tests/ui/print-fuel/print-fuel.stderr new file mode 100644 index 000000000..cc88cc077 --- /dev/null +++ b/tests/ui/print-fuel/print-fuel.stderr @@ -0,0 +1 @@ +Fuel used by foo: 3 diff --git a/tests/ui/print-stdout-eprint-stderr.rs b/tests/ui/print-stdout-eprint-stderr.rs new file mode 100644 index 000000000..cfa9aec80 --- /dev/null +++ b/tests/ui/print-stdout-eprint-stderr.rs @@ -0,0 +1,32 @@ +// run-pass +// ignore-emscripten spawning processes is not supported +// ignore-sgx no processes + +use std::{env, process}; + +fn child() { + print!("[stdout 0]"); + print!("[stdout {}]", 1); + println!("[stdout {}]", 2); + println!(); + eprint!("[stderr 0]"); + eprint!("[stderr {}]", 1); + eprintln!("[stderr {}]", 2); + eprintln!(); +} + +fn parent() { + let this = env::args().next().unwrap(); + let output = process::Command::new(this).arg("-").output().unwrap(); + assert!(output.status.success()); + + let stdout = String::from_utf8(output.stdout).unwrap(); + let stderr = String::from_utf8(output.stderr).unwrap(); + + assert_eq!(stdout, "[stdout 0][stdout 1][stdout 2]\n\n"); + assert_eq!(stderr, "[stderr 0][stderr 1][stderr 2]\n\n"); +} + +fn main() { + if env::args().count() == 2 { child() } else { parent() } +} diff --git a/tests/ui/print_type_sizes/anonymous.rs b/tests/ui/print_type_sizes/anonymous.rs new file mode 100644 index 000000000..2b008ca3b --- /dev/null +++ b/tests/ui/print_type_sizes/anonymous.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z print-type-sizes +// build-pass + +// All of the types that occur in this function are uninteresting, in +// that one cannot control the sizes of these types with the same sort +// of enum-variant manipulation tricks. + +#![feature(start)] + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _byte: u8 = 0; + let _word: usize = 0; + let _tuple: (u8, usize)= (0, 0); + let _array: [u8; 128] = [0; 128]; + let _fn: fn (u8) -> u8 = id; + let _diverging: fn (u8) -> ! = bye; + + fn id(x: u8) -> u8 { x }; + fn bye(_: u8) -> ! { loop { } } + + 0 +} diff --git a/tests/ui/print_type_sizes/async.rs b/tests/ui/print_type_sizes/async.rs new file mode 100644 index 000000000..1598b0696 --- /dev/null +++ b/tests/ui/print_type_sizes/async.rs @@ -0,0 +1,11 @@ +// compile-flags: -Z print-type-sizes --crate-type lib +// edition:2021 +// build-pass +// ignore-pass + +async fn wait() {} + +pub async fn test(arg: [u8; 8192]) { + wait().await; + drop(arg); +} diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout new file mode 100644 index 000000000..6e47bb493 --- /dev/null +++ b/tests/ui/print_type_sizes/async.stdout @@ -0,0 +1,34 @@ +print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 16385 bytes +print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size field `.arg`: 8192 bytes +print-type-size field `.__awaitee`: 1 bytes +print-type-size variant `Unresumed`: 8192 bytes +print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 8192 bytes +print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 8192 bytes +print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes +print-type-size field `.value`: 8192 bytes +print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 8192 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 8192 bytes +print-type-size type: `[async fn body@$DIR/async.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes +print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes +print-type-size field `.value`: 1 bytes +print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:6:17: 6:19]>`: 1 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 1 bytes +print-type-size field `.uninit`: 0 bytes +print-type-size field `.value`: 1 bytes +print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Ready`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Pending`: 0 bytes diff --git a/tests/ui/print_type_sizes/generator.rs b/tests/ui/print_type_sizes/generator.rs new file mode 100644 index 000000000..d1cd36274 --- /dev/null +++ b/tests/ui/print_type_sizes/generator.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass + +#![feature(generators, generator_trait)] + +use std::ops::Generator; + +fn generator(array: [u8; C]) -> impl Generator { + move |()| { + yield (); + let _ = array; + } +} + +pub fn foo() { + let _ = generator([0; 8192]); +} diff --git a/tests/ui/print_type_sizes/generator.stdout b/tests/ui/print_type_sizes/generator.stdout new file mode 100644 index 000000000..28d4a6e6c --- /dev/null +++ b/tests/ui/print_type_sizes/generator.stdout @@ -0,0 +1,10 @@ +print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Unresumed`: 8192 bytes +print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Returned`: 8192 bytes +print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Panicked`: 8192 bytes +print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes +print-type-size variant `Suspend0`: 8192 bytes +print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes diff --git a/tests/ui/print_type_sizes/generator_discr_placement.rs b/tests/ui/print_type_sizes/generator_discr_placement.rs new file mode 100644 index 000000000..1a85fe95b --- /dev/null +++ b/tests/ui/print_type_sizes/generator_discr_placement.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z print-type-sizes --crate-type lib +// build-pass +// ignore-pass + +// Tests a generator that has its discriminant as the *final* field. + +// Avoid emitting panic handlers, like the rest of these tests... +#![feature(generators)] + +pub fn foo() { + let a = || { + { + let w: i32 = 4; + yield; + drop(w); + } + { + let z: i32 = 7; + yield; + drop(z); + } + }; +} diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/generator_discr_placement.stdout new file mode 100644 index 000000000..7f8f4ccae --- /dev/null +++ b/tests/ui/print_type_sizes/generator_discr_placement.stdout @@ -0,0 +1,11 @@ +print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Suspend0`: 7 bytes +print-type-size padding: 3 bytes +print-type-size field `.w`: 4 bytes, alignment: 4 bytes +print-type-size variant `Suspend1`: 7 bytes +print-type-size padding: 3 bytes +print-type-size field `.z`: 4 bytes, alignment: 4 bytes +print-type-size variant `Unresumed`: 0 bytes +print-type-size variant `Returned`: 0 bytes +print-type-size variant `Panicked`: 0 bytes diff --git a/tests/ui/print_type_sizes/generics.rs b/tests/ui/print_type_sizes/generics.rs new file mode 100644 index 000000000..05097087d --- /dev/null +++ b/tests/ui/print_type_sizes/generics.rs @@ -0,0 +1,51 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. +// FIXME: consider using an attribute instead of side-effects. + +// This file illustrates how generics are handled: types have to be +// monomorphized, in the MIR of the original function in which they +// occur, to have their size reported. + +#[derive(Copy, Clone)] +pub struct Pair { + _car: T, + _cdr: T, +} + +impl Pair { + fn new(a: T, d: T) -> Self { + Pair { + _car: a, + _cdr: d, + } + } +} + +#[derive(Copy, Clone)] +pub struct SevenBytes([u8; 7]); +pub struct FiftyBytes([u8; 50]); + +pub struct ZeroSized; + +impl SevenBytes { + fn new() -> Self { SevenBytes([0; 7]) } +} + +impl FiftyBytes { + fn new() -> Self { FiftyBytes([0; 50]) } +} + +pub fn f1(x: T) { + let _v: Pair = Pair::new(x, x); + let _v2: Pair = + Pair::new(FiftyBytes::new(), FiftyBytes::new()); +} + +pub fn start() { + let _b: Pair = Pair::new(0, 0); + let _s: Pair = Pair::new(SevenBytes::new(), SevenBytes::new()); + let ref _z: ZeroSized = ZeroSized; + f1::(SevenBytes::new()); +} diff --git a/tests/ui/print_type_sizes/generics.stdout b/tests/ui/print_type_sizes/generics.stdout new file mode 100644 index 000000000..0f02f3979 --- /dev/null +++ b/tests/ui/print_type_sizes/generics.stdout @@ -0,0 +1,14 @@ +print-type-size type: `Pair`: 100 bytes, alignment: 1 bytes +print-type-size field `._car`: 50 bytes +print-type-size field `._cdr`: 50 bytes +print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes +print-type-size field `.0`: 50 bytes +print-type-size type: `Pair`: 14 bytes, alignment: 1 bytes +print-type-size field `._car`: 7 bytes +print-type-size field `._cdr`: 7 bytes +print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes +print-type-size field `.0`: 7 bytes +print-type-size type: `Pair`: 2 bytes, alignment: 1 bytes +print-type-size field `._car`: 1 bytes +print-type-size field `._cdr`: 1 bytes +print-type-size type: `ZeroSized`: 0 bytes, alignment: 1 bytes diff --git a/tests/ui/print_type_sizes/multiple_types.rs b/tests/ui/print_type_sizes/multiple_types.rs new file mode 100644 index 000000000..915903892 --- /dev/null +++ b/tests/ui/print_type_sizes/multiple_types.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass + +// This file illustrates that when multiple structural types occur in +// a function, every one of them is included in the output. + +pub struct SevenBytes([u8; 7]); +pub struct FiftyBytes([u8; 50]); + +pub enum Enum { + Small(SevenBytes), + Large(FiftyBytes), +} diff --git a/tests/ui/print_type_sizes/multiple_types.stdout b/tests/ui/print_type_sizes/multiple_types.stdout new file mode 100644 index 000000000..641188154 --- /dev/null +++ b/tests/ui/print_type_sizes/multiple_types.stdout @@ -0,0 +1,10 @@ +print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Large`: 50 bytes +print-type-size field `.0`: 50 bytes +print-type-size variant `Small`: 7 bytes +print-type-size field `.0`: 7 bytes +print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes +print-type-size field `.0`: 50 bytes +print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes +print-type-size field `.0`: 7 bytes diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs new file mode 100644 index 000000000..5e620f248 --- /dev/null +++ b/tests/ui/print_type_sizes/niche-filling.rs @@ -0,0 +1,97 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. +// FIXME: consider using an attribute instead of side-effects. + +// This file illustrates how niche-filling enums are handled, +// modelled after cases like `Option<&u32>`, `Option` and such. +// +// It uses NonZeroU32 rather than `&_` or `Unique<_>`, because +// the test is not set up to deal with target-dependent pointer width. +// +// It avoids using u64/i64 because on some targets that is only 4-byte +// aligned (while on most it is 8-byte aligned) and so the resulting +// padding and overall computed sizes can be quite different. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +use std::num::NonZeroU32; + +pub enum MyOption { None, Some(T) } + +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] +pub struct MyNotNegativeOne { + _i: i32, +} + +impl Default for MyOption { + fn default() -> Self { MyOption::None } +} + +pub enum EmbeddedDiscr { + None, + Record { pre: u8, val: NonZeroU32, post: u16 }, +} + +impl Default for EmbeddedDiscr { + fn default() -> Self { EmbeddedDiscr::None } +} + +#[derive(Default)] +pub struct IndirectNonZero { + pre: u8, + nested: NestedNonZero, + post: u16, +} + +pub struct NestedNonZero { + pre: u8, + val: NonZeroU32, + post: u16, +} + +impl Default for NestedNonZero { + fn default() -> Self { + NestedNonZero { pre: 0, val: unsafe { NonZeroU32::new_unchecked(1) }, post: 0 } + } +} + +pub enum Enum4 { + One(A), + Two(B), + Three(C), + Four(D) +} + +pub union Union1 { + a: A, +} + +pub union Union2 { + a: A, + b: B, +} + +pub fn test() { + let _x: MyOption = Default::default(); + let _y: EmbeddedDiscr = Default::default(); + let _z: MyOption = Default::default(); + let _a: MyOption = Default::default(); + let _b: MyOption = Default::default(); + let _c: MyOption = Default::default(); + let _d: MyOption> = Default::default(); + let _e: Enum4<(), char, (), ()> = Enum4::One(()); + let _f: Enum4<(), (), bool, ()> = Enum4::One(()); + let _g: Enum4<(), (), (), MyOption> = Enum4::One(()); + let _h: MyOption = Default::default(); + + // Unions do not currently participate in niche filling. + let _i: MyOption> = Default::default(); + + // ...even when theoretically possible. + let _j: MyOption> = Default::default(); + let _k: MyOption> = Default::default(); +} diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout new file mode 100644 index 000000000..d1753c26c --- /dev/null +++ b/tests/ui/print_type_sizes/niche-filling.stdout @@ -0,0 +1,112 @@ +print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes +print-type-size field `.nested`: 8 bytes +print-type-size field `.post`: 2 bytes +print-type-size field `.pre`: 1 bytes +print-type-size end padding: 1 bytes +print-type-size type: `MyOption`: 12 bytes, alignment: 4 bytes +print-type-size variant `Some`: 12 bytes +print-type-size field `.0`: 12 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Record`: 7 bytes +print-type-size field `.pre`: 1 bytes +print-type-size field `.post`: 2 bytes +print-type-size field `.val`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes +print-type-size field `.val`: 4 bytes +print-type-size field `.post`: 2 bytes +print-type-size field `.pre`: 1 bytes +print-type-size end padding: 1 bytes +print-type-size type: `Enum4<(), char, (), ()>`: 4 bytes, alignment: 4 bytes +print-type-size variant `Two`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `One`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Three`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Four`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size type: `MyNotNegativeOne`: 4 bytes, alignment: 4 bytes +print-type-size field `._i`: 4 bytes +print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `Union1`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union1`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union2`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes +print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union2`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes +print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes +print-type-size variant `Four`: 2 bytes +print-type-size field `.0`: 2 bytes +print-type-size variant `One`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Two`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Three`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size type: `MyOption>`: 2 bytes, alignment: 1 bytes +print-type-size variant `Some`: 2 bytes +print-type-size field `.0`: 2 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption`: 2 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Some`: 1 bytes +print-type-size field `.0`: 1 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `Enum4<(), (), bool, ()>`: 1 bytes, alignment: 1 bytes +print-type-size variant `Three`: 1 bytes +print-type-size field `.0`: 1 bytes +print-type-size variant `One`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Two`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size variant `Four`: 0 bytes +print-type-size field `.0`: 0 bytes +print-type-size type: `MyOption`: 1 bytes, alignment: 1 bytes +print-type-size variant `Some`: 1 bytes +print-type-size field `.0`: 1 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption`: 1 bytes, alignment: 1 bytes +print-type-size variant `Some`: 1 bytes +print-type-size field `.0`: 1 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `std::cmp::Ordering`: 1 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Less`: 0 bytes +print-type-size variant `Equal`: 0 bytes +print-type-size variant `Greater`: 0 bytes diff --git a/tests/ui/print_type_sizes/no_duplicates.rs b/tests/ui/print_type_sizes/no_duplicates.rs new file mode 100644 index 000000000..2ec5d9e64 --- /dev/null +++ b/tests/ui/print_type_sizes/no_duplicates.rs @@ -0,0 +1,19 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. +// FIXME: consider using an attribute instead of side-effects. + +// This file illustrates that when the same type occurs repeatedly +// (even if multiple functions), it is only printed once in the +// print-type-sizes output. + +pub struct SevenBytes([u8; 7]); + +pub fn f1() { + let _s: SevenBytes = SevenBytes([0; 7]); +} + +pub fn test() { + let _s: SevenBytes = SevenBytes([0; 7]); +} diff --git a/tests/ui/print_type_sizes/no_duplicates.stdout b/tests/ui/print_type_sizes/no_duplicates.stdout new file mode 100644 index 000000000..50180f356 --- /dev/null +++ b/tests/ui/print_type_sizes/no_duplicates.stdout @@ -0,0 +1,2 @@ +print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes +print-type-size field `.0`: 7 bytes diff --git a/tests/ui/print_type_sizes/packed.rs b/tests/ui/print_type_sizes/packed.rs new file mode 100644 index 000000000..5ddfe4bf4 --- /dev/null +++ b/tests/ui/print_type_sizes/packed.rs @@ -0,0 +1,59 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. +// FIXME: consider using an attribute instead of side-effects. + +// This file illustrates how packing is handled; it should cause +// the elimination of padding that would normally be introduced +// to satisfy alignment desirata. +// +// It avoids using u64/i64 because on some targets that is only 4-byte +// aligned (while on most it is 8-byte aligned) and so the resulting +// padding and overall computed sizes can be quite different. + +#![allow(dead_code)] + +#[derive(Default)] +#[repr(packed)] +pub struct Packed1 { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[derive(Default)] +#[repr(packed(2))] +pub struct Packed2 { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[derive(Default)] +#[repr(packed(2))] +#[repr(C)] +pub struct Packed2C { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} + +#[derive(Default)] +pub struct Padded { + a: u8, + b: u8, + g: i32, + c: u8, + h: i16, + d: u8, +} diff --git a/tests/ui/print_type_sizes/packed.stdout b/tests/ui/print_type_sizes/packed.stdout new file mode 100644 index 000000000..58e1bac9e --- /dev/null +++ b/tests/ui/print_type_sizes/packed.stdout @@ -0,0 +1,31 @@ +print-type-size type: `Packed2C`: 12 bytes, alignment: 2 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size field `.g`: 4 bytes +print-type-size field `.c`: 1 bytes +print-type-size padding: 1 bytes +print-type-size field `.h`: 2 bytes +print-type-size field `.d`: 1 bytes +print-type-size end padding: 1 bytes +print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes +print-type-size field `.g`: 4 bytes +print-type-size field `.h`: 2 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size field `.c`: 1 bytes +print-type-size field `.d`: 1 bytes +print-type-size end padding: 2 bytes +print-type-size type: `Packed1`: 10 bytes, alignment: 1 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size field `.g`: 4 bytes +print-type-size field `.c`: 1 bytes +print-type-size field `.h`: 2 bytes +print-type-size field `.d`: 1 bytes +print-type-size type: `Packed2`: 10 bytes, alignment: 2 bytes +print-type-size field `.g`: 4 bytes +print-type-size field `.h`: 2 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size field `.c`: 1 bytes +print-type-size field `.d`: 1 bytes diff --git a/tests/ui/print_type_sizes/padding.rs b/tests/ui/print_type_sizes/padding.rs new file mode 100644 index 000000000..f41c677dc --- /dev/null +++ b/tests/ui/print_type_sizes/padding.rs @@ -0,0 +1,28 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass + +// This file illustrates how padding is handled: alignment +// requirements can lead to the introduction of padding, either before +// fields or at the end of the structure as a whole. +// +// It avoids using u64/i64 because on some targets that is only 4-byte +// aligned (while on most it is 8-byte aligned) and so the resulting +// padding and overall computed sizes can be quite different. + +#![allow(dead_code)] + +struct S { + a: bool, + b: bool, + g: i32, +} + +enum E1 { + A(i32, i8), + B(S), +} + +enum E2 { + A(i8, i32), + B(S), +} diff --git a/tests/ui/print_type_sizes/padding.stdout b/tests/ui/print_type_sizes/padding.stdout new file mode 100644 index 000000000..9afdf7624 --- /dev/null +++ b/tests/ui/print_type_sizes/padding.stdout @@ -0,0 +1,23 @@ +print-type-size type: `E1`: 12 bytes, alignment: 4 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `B`: 11 bytes +print-type-size padding: 3 bytes +print-type-size field `.0`: 8 bytes, alignment: 4 bytes +print-type-size variant `A`: 7 bytes +print-type-size field `.1`: 1 bytes +print-type-size padding: 2 bytes +print-type-size field `.0`: 4 bytes, alignment: 4 bytes +print-type-size type: `E2`: 12 bytes, alignment: 4 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `B`: 11 bytes +print-type-size padding: 3 bytes +print-type-size field `.0`: 8 bytes, alignment: 4 bytes +print-type-size variant `A`: 7 bytes +print-type-size field `.0`: 1 bytes +print-type-size padding: 2 bytes +print-type-size field `.1`: 4 bytes, alignment: 4 bytes +print-type-size type: `S`: 8 bytes, alignment: 4 bytes +print-type-size field `.g`: 4 bytes +print-type-size field `.a`: 1 bytes +print-type-size field `.b`: 1 bytes +print-type-size end padding: 2 bytes diff --git a/tests/ui/print_type_sizes/repr-align.rs b/tests/ui/print_type_sizes/repr-align.rs new file mode 100644 index 000000000..0bd11ebc9 --- /dev/null +++ b/tests/ui/print_type_sizes/repr-align.rs @@ -0,0 +1,32 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. +// FIXME: consider using an attribute instead of side-effects. + +// This file illustrates how padding is handled: alignment +// requirements can lead to the introduction of padding, either before +// fields or at the end of the structure as a whole. +// +// It avoids using u64/i64 because on some targets that is only 4-byte +// aligned (while on most it is 8-byte aligned) and so the resulting +// padding and overall computed sizes can be quite different. + +#![allow(dead_code)] + +#[repr(align(16))] +#[derive(Default)] +struct A(i32); + +enum E { + A(i32), + B(A) +} + +#[derive(Default)] +pub struct S { + a: i32, + b: i32, + c: A, + d: i8, +} diff --git a/tests/ui/print_type_sizes/repr-align.stdout b/tests/ui/print_type_sizes/repr-align.stdout new file mode 100644 index 000000000..33671bd8e --- /dev/null +++ b/tests/ui/print_type_sizes/repr-align.stdout @@ -0,0 +1,16 @@ +print-type-size type: `E`: 32 bytes, alignment: 16 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `B`: 28 bytes +print-type-size padding: 12 bytes +print-type-size field `.0`: 16 bytes, alignment: 16 bytes +print-type-size variant `A`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size type: `S`: 32 bytes, alignment: 16 bytes +print-type-size field `.c`: 16 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes +print-type-size field `.d`: 1 bytes +print-type-size end padding: 7 bytes +print-type-size type: `A`: 16 bytes, alignment: 16 bytes +print-type-size field `.0`: 4 bytes +print-type-size end padding: 12 bytes diff --git a/tests/ui/print_type_sizes/repr_int_c.rs b/tests/ui/print_type_sizes/repr_int_c.rs new file mode 100644 index 000000000..6b103776a --- /dev/null +++ b/tests/ui/print_type_sizes/repr_int_c.rs @@ -0,0 +1,19 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass + +// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)` +// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug). + +#![allow(dead_code)] + +#[repr(C, u8)] +enum ReprCu8 { + A(u16), + B, +} + +#[repr(u8)] +enum Repru8 { + A(u16), + B, +} diff --git a/tests/ui/print_type_sizes/repr_int_c.stdout b/tests/ui/print_type_sizes/repr_int_c.stdout new file mode 100644 index 000000000..254b3c7a8 --- /dev/null +++ b/tests/ui/print_type_sizes/repr_int_c.stdout @@ -0,0 +1,12 @@ +print-type-size type: `ReprCu8`: 4 bytes, alignment: 2 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `A`: 3 bytes +print-type-size padding: 1 bytes +print-type-size field `.0`: 2 bytes, alignment: 2 bytes +print-type-size variant `B`: 1 bytes +print-type-size type: `Repru8`: 4 bytes, alignment: 2 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `A`: 3 bytes +print-type-size padding: 1 bytes +print-type-size field `.0`: 2 bytes, alignment: 2 bytes +print-type-size variant `B`: 0 bytes diff --git a/tests/ui/print_type_sizes/uninhabited.rs b/tests/ui/print_type_sizes/uninhabited.rs new file mode 100644 index 000000000..86fab7b50 --- /dev/null +++ b/tests/ui/print_type_sizes/uninhabited.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. +// FIXME: consider using an attribute instead of side-effects. + +#![feature(never_type)] + +pub fn test() { + let _x: Option = None; + let _y: Result = Ok(42); + let _z: Result = loop {}; +} diff --git a/tests/ui/print_type_sizes/uninhabited.stdout b/tests/ui/print_type_sizes/uninhabited.stdout new file mode 100644 index 000000000..5eb5384bc --- /dev/null +++ b/tests/ui/print_type_sizes/uninhabited.stdout @@ -0,0 +1,6 @@ +print-type-size type: `std::result::Result`: 4 bytes, alignment: 4 bytes +print-type-size variant `Ok`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size type: `std::option::Option`: 0 bytes, alignment: 1 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `std::result::Result`: 0 bytes, alignment: 1 bytes diff --git a/tests/ui/print_type_sizes/variants.rs b/tests/ui/print_type_sizes/variants.rs new file mode 100644 index 000000000..5a3020520 --- /dev/null +++ b/tests/ui/print_type_sizes/variants.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass + +// This file illustrates two things: +// +// 1. Only types that appear in a monomorphized function appear in the +// print-type-sizes output, and +// +// 2. For an enum, the print-type-sizes output will also include the +// size of each variant. + +pub struct SevenBytes([u8; 7]); +pub struct FiftyBytes([u8; 50]); + +pub enum Enum { + Small(SevenBytes), + Large(FiftyBytes), +} diff --git a/tests/ui/print_type_sizes/variants.stdout b/tests/ui/print_type_sizes/variants.stdout new file mode 100644 index 000000000..641188154 --- /dev/null +++ b/tests/ui/print_type_sizes/variants.stdout @@ -0,0 +1,10 @@ +print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `Large`: 50 bytes +print-type-size field `.0`: 50 bytes +print-type-size variant `Small`: 7 bytes +print-type-size field `.0`: 7 bytes +print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes +print-type-size field `.0`: 50 bytes +print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes +print-type-size field `.0`: 7 bytes diff --git a/tests/ui/print_type_sizes/zero-sized-fields.rs b/tests/ui/print_type_sizes/zero-sized-fields.rs new file mode 100644 index 000000000..09415824d --- /dev/null +++ b/tests/ui/print_type_sizes/zero-sized-fields.rs @@ -0,0 +1,43 @@ +// compile-flags: -Z print-type-sizes --crate-type=lib +// build-pass +// ignore-pass + +// At one point, zero-sized fields such as those in this file were causing +// incorrect output from `-Z print-type-sizes`. + +struct S1 { + x: u32, + y: u32, + tag: (), +} + +struct Void(); +struct Empty {} + +struct S5 { + tagw: TagW, + w: u32, + unit: (), + x: u32, + void: Void, + y: u32, + empty: Empty, + z: u32, + tagz: TagZ, +} + +pub fn test() { + let _s1: S1 = S1 { x: 0, y: 0, tag: () }; + + let _s5: S5<(), Empty> = S5 { + tagw: (), + w: 1, + unit: (), + x: 2, + void: Void(), + y: 3, + empty: Empty {}, + z: 4, + tagz: Empty {}, + }; +} diff --git a/tests/ui/print_type_sizes/zero-sized-fields.stdout b/tests/ui/print_type_sizes/zero-sized-fields.stdout new file mode 100644 index 000000000..72f59c4bb --- /dev/null +++ b/tests/ui/print_type_sizes/zero-sized-fields.stdout @@ -0,0 +1,16 @@ +print-type-size type: `S5<(), Empty>`: 16 bytes, alignment: 4 bytes +print-type-size field `.tagw`: 0 bytes +print-type-size field `.unit`: 0 bytes +print-type-size field `.void`: 0 bytes +print-type-size field `.empty`: 0 bytes +print-type-size field `.tagz`: 0 bytes +print-type-size field `.w`: 4 bytes +print-type-size field `.x`: 4 bytes +print-type-size field `.y`: 4 bytes +print-type-size field `.z`: 4 bytes +print-type-size type: `S1`: 8 bytes, alignment: 4 bytes +print-type-size field `.tag`: 0 bytes +print-type-size field `.x`: 4 bytes +print-type-size field `.y`: 4 bytes +print-type-size type: `Empty`: 0 bytes, alignment: 1 bytes +print-type-size type: `Void`: 0 bytes, alignment: 1 bytes diff --git a/tests/ui/privacy/associated-item-privacy-inherent.rs b/tests/ui/privacy/associated-item-privacy-inherent.rs new file mode 100644 index 000000000..7b7c734a9 --- /dev/null +++ b/tests/ui/privacy/associated-item-privacy-inherent.rs @@ -0,0 +1,112 @@ +#![feature(decl_macro, associated_type_defaults)] +#![allow(unused, private_in_public)] + +mod priv_nominal { + pub struct Pub; + impl Pub { + fn method(&self) {} + const CONST: u8 = 0; + // type AssocTy = u8; + } + + pub macro mac() { + let value = Pub::method; + //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private + value; + //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private + Pub.method(); + //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private + Pub::CONST; + //~^ ERROR associated constant `CONST` is private + // let _: Pub::AssocTy; + // pub type InSignatureTy = Pub::AssocTy; + } +} +fn priv_nominal() { + priv_nominal::mac!(); +} + +mod priv_signature { + struct Priv; + pub struct Pub; + impl Pub { + pub fn method(&self, arg: Priv) {} + } + + pub macro mac() { + let value = Pub::method; + //~^ ERROR type `priv_signature::Priv` is private + value; + //~^ ERROR type `priv_signature::Priv` is private + Pub.method(loop {}); + //~^ ERROR type `priv_signature::Priv` is private + } +} +fn priv_signature() { + priv_signature::mac!(); +} + +mod priv_substs { + struct Priv; + pub struct Pub; + impl Pub { + pub fn method(&self) {} + } + + pub macro mac() { + let value = Pub::method::; + //~^ ERROR type `priv_substs::Priv` is private + value; + //~^ ERROR type `priv_substs::Priv` is private + Pub.method::(); + //~^ ERROR type `priv_substs::Priv` is private + } +} +fn priv_substs() { + priv_substs::mac!(); +} + +mod priv_parent_substs { + struct Priv; + pub struct Pub(T); + impl Pub { + pub fn method(&self) {} + pub fn static_method() {} + pub const CONST: u8 = 0; + // pub type AssocTy = u8; + } + + pub macro mac() { + let value = ::method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + let value = Pub::method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + let value = ::static_method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + let value = Pub::static_method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + Pub(Priv).method(); + //~^ ERROR type `priv_parent_substs::Priv` is private + + ::CONST; + //~^ ERROR type `priv_parent_substs::Priv` is private + Pub::CONST; + //~^ ERROR type `priv_parent_substs::Priv` is private + + // let _: Pub::AssocTy; + // pub type InSignatureTy = Pub::AssocTy; + } +} +fn priv_parent_substs() { + priv_parent_substs::mac!(); +} + +fn main() {} diff --git a/tests/ui/privacy/associated-item-privacy-inherent.stderr b/tests/ui/privacy/associated-item-privacy-inherent.stderr new file mode 100644 index 000000000..f4d4ee459 --- /dev/null +++ b/tests/ui/privacy/associated-item-privacy-inherent.stderr @@ -0,0 +1,233 @@ +error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private + --> $DIR/associated-item-privacy-inherent.rs:13:21 + | +LL | let value = Pub::method; + | ^^^^^^^^^^^ private type +... +LL | priv_nominal::mac!(); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private + --> $DIR/associated-item-privacy-inherent.rs:15:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_nominal::mac!(); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private + --> $DIR/associated-item-privacy-inherent.rs:17:13 + | +LL | Pub.method(); + | ^^^^^^ private type +... +LL | priv_nominal::mac!(); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: associated constant `CONST` is private + --> $DIR/associated-item-privacy-inherent.rs:19:9 + | +LL | Pub::CONST; + | ^^^^^^^^^^ private associated constant +... +LL | priv_nominal::mac!(); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_signature::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:37:21 + | +LL | let value = Pub::method; + | ^^^^^^^^^^^ private type +... +LL | priv_signature::mac!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_signature::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:39:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_signature::mac!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_signature::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:41:13 + | +LL | Pub.method(loop {}); + | ^^^^^^ private type +... +LL | priv_signature::mac!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:57:21 + | +LL | let value = Pub::method::; + | ^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_substs::mac!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:59:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_substs::mac!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:61:9 + | +LL | Pub.method::(); + | ^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_substs::mac!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:80:21 + | +LL | let value = ::method; + | ^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:82:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:84:21 + | +LL | let value = Pub::method; + | ^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:86:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:88:21 + | +LL | let value = ::static_method; + | ^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:90:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:92:21 + | +LL | let value = Pub::static_method; + | ^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:94:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:96:19 + | +LL | Pub(Priv).method(); + | ^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:99:10 + | +LL | ::CONST; + | ^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-inherent.rs:101:9 + | +LL | Pub::CONST; + | ^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 21 previous errors + diff --git a/tests/ui/privacy/associated-item-privacy-trait.rs b/tests/ui/privacy/associated-item-privacy-trait.rs new file mode 100644 index 000000000..c686a2177 --- /dev/null +++ b/tests/ui/privacy/associated-item-privacy-trait.rs @@ -0,0 +1,134 @@ +#![feature(decl_macro, associated_type_defaults)] +#![allow(unused, private_in_public)] + +mod priv_trait { + trait PrivTr { + fn method(&self) {} + const CONST: u8 = 0; + type AssocTy = u8; + } + pub struct Pub; + impl PrivTr for Pub {} + pub trait PubTr: PrivTr {} + + pub macro mac() { + let value = ::method; + //~^ ERROR type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private + value; + //~^ ERROR type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private + Pub.method(); + //~^ ERROR type `for<'a> fn(&'a Self) {::method}` is private + ::CONST; + //~^ ERROR associated constant `PrivTr::CONST` is private + let _: ::AssocTy; + //~^ ERROR associated type `PrivTr::AssocTy` is private + pub type InSignatureTy = ::AssocTy; + //~^ ERROR trait `PrivTr` is private + pub trait InSignatureTr: PrivTr {} + //~^ ERROR trait `PrivTr` is private + impl PrivTr for u8 {} + //~^ ERROR trait `PrivTr` is private + } +} +fn priv_trait() { + priv_trait::mac!(); +} + +mod priv_signature { + pub trait PubTr { + fn method(&self, arg: Priv) {} + } + struct Priv; + pub struct Pub; + impl PubTr for Pub {} + + pub macro mac() { + let value = ::method; + //~^ ERROR type `priv_signature::Priv` is private + value; + //~^ ERROR type `priv_signature::Priv` is private + Pub.method(loop {}); + //~^ ERROR type `priv_signature::Priv` is private + } +} +fn priv_signature() { + priv_signature::mac!(); +} + +mod priv_substs { + pub trait PubTr { + fn method(&self) {} + } + struct Priv; + pub struct Pub; + impl PubTr for Pub {} + + pub macro mac() { + let value = ::method::; + //~^ ERROR type `priv_substs::Priv` is private + value; + //~^ ERROR type `priv_substs::Priv` is private + Pub.method::(); + //~^ ERROR type `priv_substs::Priv` is private + } +} +fn priv_substs() { + priv_substs::mac!(); +} + +mod priv_parent_substs { + pub trait PubTr { + fn method(&self) {} + const CONST: u8 = 0; + type AssocTy = u8; + } + struct Priv; + pub struct Pub; + impl PubTr for Pub {} + impl PubTr for Priv {} + + pub macro mac() { + let value = ::method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + let value = >::method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + Pub.method(); + //~^ ERROR type `priv_parent_substs::Priv` is private + + let value = >::method; + //~^ ERROR type `priv_parent_substs::Priv` is private + value; + //~^ ERROR type `priv_parent_substs::Priv` is private + Priv.method(); + //~^ ERROR type `priv_parent_substs::Priv` is private + + ::CONST; + //~^ ERROR type `priv_parent_substs::Priv` is private + >::CONST; + //~^ ERROR type `priv_parent_substs::Priv` is private + >::CONST; + //~^ ERROR type `priv_parent_substs::Priv` is private + + let _: ::AssocTy; // FIXME no longer an error?! + let _: >::AssocTy; + //~^ ERROR type `priv_parent_substs::Priv` is private + let _: >::AssocTy; + //~^ ERROR type `priv_parent_substs::Priv` is private + + pub type InSignatureTy1 = ::AssocTy; + //~^ ERROR type `priv_parent_substs::Priv` is private + pub type InSignatureTy2 = >::AssocTy; + //~^ ERROR type `priv_parent_substs::Priv` is private + impl PubTr for u8 {} + //~^ ERROR type `priv_parent_substs::Priv` is private + } +} +fn priv_parent_substs() { + priv_parent_substs::mac!(); +} + +fn main() {} diff --git a/tests/ui/privacy/associated-item-privacy-trait.stderr b/tests/ui/privacy/associated-item-privacy-trait.stderr new file mode 100644 index 000000000..eb905bf7e --- /dev/null +++ b/tests/ui/privacy/associated-item-privacy-trait.stderr @@ -0,0 +1,332 @@ +error: type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private + --> $DIR/associated-item-privacy-trait.rs:15:21 + | +LL | let value = ::method; + | ^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private + --> $DIR/associated-item-privacy-trait.rs:17:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `for<'a> fn(&'a Self) {::method}` is private + --> $DIR/associated-item-privacy-trait.rs:19:13 + | +LL | Pub.method(); + | ^^^^^^ private type +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: associated constant `PrivTr::CONST` is private + --> $DIR/associated-item-privacy-trait.rs:21:9 + | +LL | ::CONST; + | ^^^^^^^^^^^^^^^^^^^^^^ private associated constant +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: associated type `PrivTr::AssocTy` is private + --> $DIR/associated-item-privacy-trait.rs:23:16 + | +LL | let _: ::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-trait.rs:25:34 + | +LL | pub type InSignatureTy = ::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-trait.rs:27:34 + | +LL | pub trait InSignatureTr: PrivTr {} + | ^^^^^^ private trait +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-trait.rs:29:14 + | +LL | impl PrivTr for u8 {} + | ^^^^^^ private trait +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_signature::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:46:21 + | +LL | let value = ::method; + | ^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_signature::mac!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_signature::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:48:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_signature::mac!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_signature::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:50:13 + | +LL | Pub.method(loop {}); + | ^^^^^^ private type +... +LL | priv_signature::mac!(); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:67:21 + | +LL | let value = ::method::; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_substs::mac!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:69:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_substs::mac!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:71:9 + | +LL | Pub.method::(); + | ^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_substs::mac!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:91:21 + | +LL | let value = ::method; + | ^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:93:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:95:21 + | +LL | let value = >::method; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:97:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:99:9 + | +LL | Pub.method(); + | ^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:102:21 + | +LL | let value = >::method; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:104:9 + | +LL | value; + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:106:9 + | +LL | Priv.method(); + | ^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:109:9 + | +LL | ::CONST; + | ^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:111:9 + | +LL | >::CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:113:9 + | +LL | >::CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:117:30 + | +LL | let _: >::AssocTy; + | ^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:119:17 + | +LL | let _: >::AssocTy; + | ^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:122:35 + | +LL | pub type InSignatureTy1 = ::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:124:35 + | +LL | pub type InSignatureTy2 = >::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:126:14 + | +LL | impl PubTr for u8 {} + | ^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 30 previous errors + diff --git a/tests/ui/privacy/associated-item-privacy-type-binding.rs b/tests/ui/privacy/associated-item-privacy-type-binding.rs new file mode 100644 index 000000000..9826b83a3 --- /dev/null +++ b/tests/ui/privacy/associated-item-privacy-type-binding.rs @@ -0,0 +1,64 @@ +#![feature(decl_macro, associated_type_defaults)] +#![allow(unused, private_in_public)] + +mod priv_trait { + trait PrivTr { + type AssocTy = u8; + } + pub trait PubTr: PrivTr {} + + pub macro mac1() { + let _: Box>; + //~^ ERROR trait `PrivTr` is private + //~| ERROR trait `PrivTr` is private + type InSignatureTy2 = Box>; + //~^ ERROR trait `PrivTr` is private + trait InSignatureTr2: PubTr {} + //~^ ERROR trait `PrivTr` is private + } + pub macro mac2() { + let _: Box>; + //~^ ERROR trait `PrivTr` is private + //~| ERROR trait `PrivTr` is private + type InSignatureTy1 = Box>; + //~^ ERROR trait `PrivTr` is private + trait InSignatureTr1: PrivTr {} + //~^ ERROR trait `PrivTr` is private + } +} +fn priv_trait1() { + priv_trait::mac1!(); +} +fn priv_trait2() { + priv_trait::mac2!(); +} + +mod priv_parent_substs { + pub trait PubTrWithParam { + type AssocTy = u8; + } + struct Priv; + pub trait PubTr: PubTrWithParam {} + + pub macro mac() { + let _: Box>; + //~^ ERROR type `Priv` is private + //~| ERROR type `Priv` is private + let _: Box>; + //~^ ERROR type `Priv` is private + //~| ERROR type `Priv` is private + pub type InSignatureTy1 = Box>; + //~^ ERROR type `Priv` is private + pub type InSignatureTy2 = Box>; + //~^ ERROR type `Priv` is private + trait InSignatureTr1: PubTrWithParam {} + //~^ ERROR type `Priv` is private + trait InSignatureTr2: PubTr {} + //~^ ERROR type `Priv` is private + } +} +fn priv_parent_substs() { + priv_parent_substs::mac!(); +} + +fn main() {} diff --git a/tests/ui/privacy/associated-item-privacy-type-binding.stderr b/tests/ui/privacy/associated-item-privacy-type-binding.stderr new file mode 100644 index 000000000..de9893816 --- /dev/null +++ b/tests/ui/privacy/associated-item-privacy-type-binding.stderr @@ -0,0 +1,178 @@ +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:11:13 + | +LL | let _: Box>; + | ^ private trait +... +LL | priv_trait::mac1!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:11:16 + | +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac1!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:14:31 + | +LL | type InSignatureTy2 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac1!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:16:31 + | +LL | trait InSignatureTr2: PubTr {} + | ^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac1!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:20:13 + | +LL | let _: Box>; + | ^ private trait +... +LL | priv_trait::mac2!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:20:16 + | +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac2!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:23:31 + | +LL | type InSignatureTy1 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac2!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-type-binding.rs:25:31 + | +LL | trait InSignatureTr1: PrivTr {} + | ^^^^^^^^^^^^^^^^^^^^ private trait +... +LL | priv_trait::mac2!(); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:44:13 + | +LL | let _: Box>; + | ^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:44:16 + | +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:47:13 + | +LL | let _: Box>; + | ^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:47:16 + | +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:50:35 + | +LL | pub type InSignatureTy1 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:52:35 + | +LL | pub type InSignatureTy2 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:54:31 + | +LL | trait InSignatureTr1: PubTrWithParam {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `Priv` is private + --> $DIR/associated-item-privacy-type-binding.rs:56:31 + | +LL | trait InSignatureTr2: PubTr {} + | ^^^^^^^^^^^^^^^^^^^ private type +... +LL | priv_parent_substs::mac!(); + | -------------------------- in this macro invocation + | + = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 16 previous errors + diff --git a/tests/ui/privacy/auxiliary/cci_class.rs b/tests/ui/privacy/auxiliary/cci_class.rs new file mode 100644 index 000000000..de2945d74 --- /dev/null +++ b/tests/ui/privacy/auxiliary/cci_class.rs @@ -0,0 +1,14 @@ +pub mod kitties { + pub struct cat { + meows : usize, + + pub how_hungry : isize, + } + + pub fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } + } +} diff --git a/tests/ui/privacy/auxiliary/cci_class_5.rs b/tests/ui/privacy/auxiliary/cci_class_5.rs new file mode 100644 index 000000000..3aeaa83d3 --- /dev/null +++ b/tests/ui/privacy/auxiliary/cci_class_5.rs @@ -0,0 +1,17 @@ +pub mod kitties { + pub struct cat { + meows : usize, + pub how_hungry : isize, + } + + impl cat { + fn nap(&self) {} + } + + pub fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } + } +} diff --git a/tests/ui/privacy/auxiliary/ctor_aux.rs b/tests/ui/privacy/auxiliary/ctor_aux.rs new file mode 100644 index 000000000..9c99cca9a --- /dev/null +++ b/tests/ui/privacy/auxiliary/ctor_aux.rs @@ -0,0 +1,25 @@ +// edition:2021 +//! Missing docs lint warns about undocumented exported items. +//! Use the lint to additionally verify that items are reachable +//! but not exported. +#![allow(non_camel_case_types)] +#![deny(missing_docs)] + +mod hidden { + pub struct s; + pub enum e { x, y, z } + pub use e::*; + impl s { + pub fn f(&self) {} + } + impl e { + pub fn g(&self) {} + } +} +// Hide all type definitions while reexporting their constructors: +mod e {} +mod x {} +mod y {} +mod z {} +mod s {} +pub use hidden::*; diff --git a/tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs b/tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs new file mode 100644 index 000000000..5f9c22681 --- /dev/null +++ b/tests/ui/privacy/auxiliary/impl_privacy_xc_2.rs @@ -0,0 +1,13 @@ +#![crate_type = "lib"] + +pub struct Fish { + pub x: isize +} + +mod unexported { + use super::Fish; + impl PartialEq for Fish { + fn eq(&self, _: &Fish) -> bool { true } + fn ne(&self, _: &Fish) -> bool { false } + } +} diff --git a/tests/ui/privacy/auxiliary/issue-17718-const-privacy.rs b/tests/ui/privacy/auxiliary/issue-17718-const-privacy.rs new file mode 100644 index 000000000..93cf4bf3e --- /dev/null +++ b/tests/ui/privacy/auxiliary/issue-17718-const-privacy.rs @@ -0,0 +1,8 @@ +pub use foo::FOO2; + +pub const FOO: usize = 3; +const BAR: usize = 3; + +mod foo { + pub const FOO2: usize = 3; +} diff --git a/tests/ui/privacy/auxiliary/issue-57264-1.rs b/tests/ui/privacy/auxiliary/issue-57264-1.rs new file mode 100644 index 000000000..9302fa0d9 --- /dev/null +++ b/tests/ui/privacy/auxiliary/issue-57264-1.rs @@ -0,0 +1,9 @@ +mod inner { + pub struct PubUnnameable; +} + +pub struct Pub(T); + +impl Pub { + pub fn pub_method() {} +} diff --git a/tests/ui/privacy/auxiliary/issue-57264-2.rs b/tests/ui/privacy/auxiliary/issue-57264-2.rs new file mode 100644 index 000000000..416206b4f --- /dev/null +++ b/tests/ui/privacy/auxiliary/issue-57264-2.rs @@ -0,0 +1,10 @@ +mod inner { + pub struct PubUnnameable; + + impl PubUnnameable { + pub fn pub_method(self) {} + } +} + +pub trait PubTraitWithSingleImplementor {} +impl PubTraitWithSingleImplementor for Option {} diff --git a/tests/ui/privacy/auxiliary/issue-75907.rs b/tests/ui/privacy/auxiliary/issue-75907.rs new file mode 100644 index 000000000..389c9c351 --- /dev/null +++ b/tests/ui/privacy/auxiliary/issue-75907.rs @@ -0,0 +1,17 @@ +pub struct Bar(pub u8, u8, u8); + +pub fn make_bar() -> Bar { + Bar(1, 12, 10) +} + +mod inner { + pub struct Foo(u8, pub u8, u8); + + impl Foo { + pub fn new() -> Foo { + Foo(1, 12, 10) + } + } +} + +pub use inner::Foo; diff --git a/tests/ui/privacy/auxiliary/issue-92755.rs b/tests/ui/privacy/auxiliary/issue-92755.rs new file mode 100644 index 000000000..6f8527346 --- /dev/null +++ b/tests/ui/privacy/auxiliary/issue-92755.rs @@ -0,0 +1,17 @@ +mod machine { + pub struct A { + pub b: B, + } + pub struct B {} + impl B { + pub fn f(&self) {} + } +} + +pub struct Context { + pub a: machine::A, +} + +pub fn ctx() -> Context { + todo!(); +} diff --git a/tests/ui/privacy/auxiliary/priv-impl-prim-ty.rs b/tests/ui/privacy/auxiliary/priv-impl-prim-ty.rs new file mode 100644 index 000000000..8ccbd3f12 --- /dev/null +++ b/tests/ui/privacy/auxiliary/priv-impl-prim-ty.rs @@ -0,0 +1,9 @@ +pub trait A { + fn frob(&self); +} + +impl A for isize { fn frob(&self) {} } + +pub fn frob(t: T) { + t.frob(); +} diff --git a/tests/ui/privacy/auxiliary/privacy_reexport.rs b/tests/ui/privacy/auxiliary/privacy_reexport.rs new file mode 100644 index 000000000..6b72dbc92 --- /dev/null +++ b/tests/ui/privacy/auxiliary/privacy_reexport.rs @@ -0,0 +1,6 @@ +pub extern crate core; +pub use foo as bar; + +pub mod foo { + pub fn frob() {} +} diff --git a/tests/ui/privacy/auxiliary/privacy_tuple_struct.rs b/tests/ui/privacy/auxiliary/privacy_tuple_struct.rs new file mode 100644 index 000000000..223cda4b2 --- /dev/null +++ b/tests/ui/privacy/auxiliary/privacy_tuple_struct.rs @@ -0,0 +1,4 @@ +pub struct A(()); +pub struct B(isize); +pub struct C(pub isize, isize); +pub struct D(pub isize); diff --git a/tests/ui/privacy/auxiliary/private-inferred-type.rs b/tests/ui/privacy/auxiliary/private-inferred-type.rs new file mode 100644 index 000000000..7ac913f5b --- /dev/null +++ b/tests/ui/privacy/auxiliary/private-inferred-type.rs @@ -0,0 +1,36 @@ +#![feature(decl_macro)] + +fn priv_fn() {} +static PRIV_STATIC: u8 = 0; +enum PrivEnum { Variant } +pub enum PubEnum { Variant } +trait PrivTrait { fn method() {} } +impl PrivTrait for u8 {} +pub trait PubTrait { fn method() {} } +impl PubTrait for u8 {} +struct PrivTupleStruct(u8); +pub struct PubTupleStruct(u8); +impl PubTupleStruct { fn method() {} } + +struct Priv; +pub type Alias = Priv; +pub struct Pub(pub T); + +impl Pub { + pub fn static_method() {} +} +impl Pub { + fn priv_method(&self) {} +} + +pub macro m() { + priv_fn; + PRIV_STATIC; + PrivEnum::Variant; + PubEnum::Variant; + ::method; + ::method; + PrivTupleStruct; + PubTupleStruct; + Pub(0u8).priv_method(); +} diff --git a/tests/ui/privacy/auxiliary/pub_use_mods_xcrate.rs b/tests/ui/privacy/auxiliary/pub_use_mods_xcrate.rs new file mode 100644 index 000000000..74d3504d5 --- /dev/null +++ b/tests/ui/privacy/auxiliary/pub_use_mods_xcrate.rs @@ -0,0 +1,10 @@ +pub mod a { + pub use a::b::c; + + pub mod b { + pub mod c { + fn f(){} + fn g(){} + } + } +} diff --git a/tests/ui/privacy/auxiliary/pub_use_xcrate1.rs b/tests/ui/privacy/auxiliary/pub_use_xcrate1.rs new file mode 100644 index 000000000..772c9627a --- /dev/null +++ b/tests/ui/privacy/auxiliary/pub_use_xcrate1.rs @@ -0,0 +1,3 @@ +pub struct Foo { + pub name: isize +} diff --git a/tests/ui/privacy/auxiliary/pub_use_xcrate2.rs b/tests/ui/privacy/auxiliary/pub_use_xcrate2.rs new file mode 100644 index 000000000..20d7066d3 --- /dev/null +++ b/tests/ui/privacy/auxiliary/pub_use_xcrate2.rs @@ -0,0 +1,3 @@ +extern crate pub_use_xcrate1; + +pub use pub_use_xcrate1::Foo; diff --git a/tests/ui/privacy/auxiliary/reachable-unnameable-items.rs b/tests/ui/privacy/auxiliary/reachable-unnameable-items.rs new file mode 100644 index 000000000..20f110b1a --- /dev/null +++ b/tests/ui/privacy/auxiliary/reachable-unnameable-items.rs @@ -0,0 +1,106 @@ +use inner_private_module::*; + +mod inner_private_module { + pub struct Unnameable1; + pub struct Unnameable2; + #[derive(Clone, Copy)] + pub struct Unnameable3; + pub struct Unnameable4; + pub struct Unnameable5; + pub struct Unnameable6; + pub struct Unnameable7; + #[derive(Default)] + pub struct Unnameable8; + pub enum UnnameableEnum { + NameableVariant + } + pub trait UnnameableTrait { + type Alias: Default; + } + + impl Unnameable1 { + pub fn method_of_unnameable_type1(&self) -> &'static str { + "Hello1" + } + } + impl Unnameable2 { + pub fn method_of_unnameable_type2(&self) -> &'static str { + "Hello2" + } + } + impl Unnameable3 { + pub fn method_of_unnameable_type3(&self) -> &'static str { + "Hello3" + } + } + impl Unnameable4 { + pub fn method_of_unnameable_type4(&self) -> &'static str { + "Hello4" + } + } + impl Unnameable5 { + pub fn method_of_unnameable_type5(&self) -> &'static str { + "Hello5" + } + } + impl Unnameable6 { + pub fn method_of_unnameable_type6(&self) -> &'static str { + "Hello6" + } + } + impl Unnameable7 { + pub fn method_of_unnameable_type7(&self) -> &'static str { + "Hello7" + } + } + impl Unnameable8 { + pub fn method_of_unnameable_type8(&self) -> &'static str { + "Hello8" + } + } + impl UnnameableEnum { + pub fn method_of_unnameable_enum(&self) -> &'static str { + "HelloEnum" + } + } +} + +pub fn function_returning_unnameable_type() -> Unnameable1 { + Unnameable1 +} + +pub const CONSTANT_OF_UNNAMEABLE_TYPE: Unnameable2 = + Unnameable2; + +pub fn function_accepting_unnameable_type(_: Option) {} + +pub type AliasOfUnnameableType = Unnameable4; + +impl Unnameable1 { + pub fn inherent_method_returning_unnameable_type(&self) -> Unnameable5 { + Unnameable5 + } +} + +pub trait Tr { + fn trait_method_returning_unnameable_type(&self) -> Unnameable6 { + Unnameable6 + } +} +impl Tr for Unnameable1 {} + +pub use inner_private_module::UnnameableEnum::NameableVariant; + +pub struct Struct { + pub field_of_unnameable_type: Unnameable7 +} + +pub static STATIC: Struct = Struct { field_of_unnameable_type: Unnameable7 } ; + +impl UnnameableTrait for AliasOfUnnameableType { + type Alias = Unnameable8; +} + +pub fn generic_function() -> T::Alias { + Default::default() +} diff --git a/tests/ui/privacy/crate-private-reexport.rs b/tests/ui/privacy/crate-private-reexport.rs new file mode 100644 index 000000000..fa4f88666 --- /dev/null +++ b/tests/ui/privacy/crate-private-reexport.rs @@ -0,0 +1,66 @@ +fn f1() {} +enum E1 { V } +struct S1 { + #[rustfmt::skip] + bar: i32, +} +mod m1 { + pub use ::f1; //~ ERROR `f1` is only public within the crate, and cannot be re-exported outside + pub use ::S1; //~ ERROR `S1` is only public within the crate, and cannot be re-exported outside + pub use ::E1; //~ ERROR `E1` is only public within the crate, and cannot be re-exported outside + pub use ::E1::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +pub(crate) fn f2() {} +pub(crate) enum E2 { + V +} +pub(crate) struct S2 { + #[rustfmt::skip] + bar: i32, +} +mod m2 { + pub use ::f2; //~ ERROR `f2` is only public within the crate, and cannot be re-exported outside + pub use ::S2; //~ ERROR `S2` is only public within the crate, and cannot be re-exported outside + pub use ::E2; //~ ERROR `E2` is only public within the crate, and cannot be re-exported outside + pub use ::E2::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +mod m3 { + pub(crate) fn f3() {} + pub(crate) enum E3 { + V + } + pub(crate) struct S3 { + #[rustfmt::skip] + bar: i32, + } +} +pub use m3::f3; //~ ERROR `f3` is only public within the crate, and cannot be re-exported outside +pub use m3::S3; //~ ERROR `S3` is only public within the crate, and cannot be re-exported outside +pub use m3::E3; //~ ERROR `E3` is only public within the crate, and cannot be re-exported outside +pub use m3::E3::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside + +pub(self) fn f4() {} +pub use ::f4 as f5; //~ ERROR `f4` is only public within the crate, and cannot be re-exported outside + +pub mod m10 { + pub mod m { + pub(super) fn f6() {} + pub(crate) fn f7() {} + pub(in crate::m10) fn f8() {} + } + pub use self::m::f6; //~ ERROR `f6` is private, and cannot be re-exported + pub use self::m::f7; //~ ERROR `f7` is only public within the crate, and cannot be re-exported outside + pub use self::m::f8; //~ ERROR `f8` is private, and cannot be re-exported +} +pub use m10::m::f6; //~ ERROR function `f6` is private +pub use m10::m::f7; //~ ERROR `f7` is only public within the crate, and cannot be re-exported outside +pub use m10::m::f8; //~ ERROR function `f8` is private + +pub mod m11 { + pub(self) fn f9() {} +} +pub use m11::f9; //~ ERROR function `f9` is private + +fn main() {} diff --git a/tests/ui/privacy/crate-private-reexport.stderr b/tests/ui/privacy/crate-private-reexport.stderr new file mode 100644 index 000000000..66e11e821 --- /dev/null +++ b/tests/ui/privacy/crate-private-reexport.stderr @@ -0,0 +1,220 @@ +error[E0364]: `f1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:8:13 + | +LL | pub use ::f1; + | ^^^^ + | +note: consider marking `f1` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:8:13 + | +LL | pub use ::f1; + | ^^^^ + +error[E0365]: `S1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:9:13 + | +LL | pub use ::S1; + | ^^^^ re-export of crate public `S1` + | + = note: consider declaring type or module `S1` with `pub` + +error[E0365]: `E1` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:10:13 + | +LL | pub use ::E1; + | ^^^^ re-export of crate public `E1` + | + = note: consider declaring type or module `E1` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:11:13 + | +LL | pub use ::E1::V; + | ^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:11:13 + | +LL | pub use ::E1::V; + | ^^^^^^^ + +error[E0364]: `f2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:23:13 + | +LL | pub use ::f2; + | ^^^^ + | +note: consider marking `f2` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:23:13 + | +LL | pub use ::f2; + | ^^^^ + +error[E0365]: `S2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:24:13 + | +LL | pub use ::S2; + | ^^^^ re-export of crate public `S2` + | + = note: consider declaring type or module `S2` with `pub` + +error[E0365]: `E2` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:25:13 + | +LL | pub use ::E2; + | ^^^^ re-export of crate public `E2` + | + = note: consider declaring type or module `E2` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:26:13 + | +LL | pub use ::E2::V; + | ^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:26:13 + | +LL | pub use ::E2::V; + | ^^^^^^^ + +error[E0364]: `f3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:39:9 + | +LL | pub use m3::f3; + | ^^^^^^ + | +note: consider marking `f3` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:39:9 + | +LL | pub use m3::f3; + | ^^^^^^ + +error[E0365]: `S3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:40:9 + | +LL | pub use m3::S3; + | ^^^^^^ re-export of crate public `S3` + | + = note: consider declaring type or module `S3` with `pub` + +error[E0365]: `E3` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:41:9 + | +LL | pub use m3::E3; + | ^^^^^^ re-export of crate public `E3` + | + = note: consider declaring type or module `E3` with `pub` + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:42:9 + | +LL | pub use m3::E3::V; + | ^^^^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:42:9 + | +LL | pub use m3::E3::V; + | ^^^^^^^^^ + +error[E0364]: `f4` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:45:9 + | +LL | pub use ::f4 as f5; + | ^^^^^^^^^^ + | +note: consider marking `f4` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:45:9 + | +LL | pub use ::f4 as f5; + | ^^^^^^^^^^ + +error[E0364]: `f6` is private, and cannot be re-exported + --> $DIR/crate-private-reexport.rs:53:13 + | +LL | pub use self::m::f6; + | ^^^^^^^^^^^ + | +note: consider marking `f6` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:53:13 + | +LL | pub use self::m::f6; + | ^^^^^^^^^^^ + +error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:54:13 + | +LL | pub use self::m::f7; + | ^^^^^^^^^^^ + | +note: consider marking `f7` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:54:13 + | +LL | pub use self::m::f7; + | ^^^^^^^^^^^ + +error[E0364]: `f8` is private, and cannot be re-exported + --> $DIR/crate-private-reexport.rs:55:13 + | +LL | pub use self::m::f8; + | ^^^^^^^^^^^ + | +note: consider marking `f8` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:55:13 + | +LL | pub use self::m::f8; + | ^^^^^^^^^^^ + +error[E0364]: `f7` is only public within the crate, and cannot be re-exported outside + --> $DIR/crate-private-reexport.rs:58:9 + | +LL | pub use m10::m::f7; + | ^^^^^^^^^^ + | +note: consider marking `f7` as `pub` in the imported module + --> $DIR/crate-private-reexport.rs:58:9 + | +LL | pub use m10::m::f7; + | ^^^^^^^^^^ + +error[E0603]: function `f6` is private + --> $DIR/crate-private-reexport.rs:57:17 + | +LL | pub use m10::m::f6; + | ^^ private function + | +note: the function `f6` is defined here + --> $DIR/crate-private-reexport.rs:49:9 + | +LL | pub(super) fn f6() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f8` is private + --> $DIR/crate-private-reexport.rs:59:17 + | +LL | pub use m10::m::f8; + | ^^ private function + | +note: the function `f8` is defined here + --> $DIR/crate-private-reexport.rs:51:9 + | +LL | pub(in crate::m10) fn f8() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f9` is private + --> $DIR/crate-private-reexport.rs:64:14 + | +LL | pub use m11::f9; + | ^^ private function + | +note: the function `f9` is defined here + --> $DIR/crate-private-reexport.rs:62:5 + | +LL | pub(self) fn f9() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0364, E0365, E0603. +For more information about an error, try `rustc --explain E0364`. diff --git a/tests/ui/privacy/ctor.rs b/tests/ui/privacy/ctor.rs new file mode 100644 index 000000000..0ec15d68e --- /dev/null +++ b/tests/ui/privacy/ctor.rs @@ -0,0 +1,16 @@ +// Verify that a type is considered reachable when its constructor is +// reachable. The auxiliary library is constructed so that all types are +// shadowed and cannot be named directly, while their constructors are +// reexported. Regression test for issue #96934. +// +// aux-build:ctor_aux.rs +// edition:2021 +// build-pass + +extern crate ctor_aux; + +fn main() { + ctor_aux::s.f(); + ctor_aux::x.g(); + ctor_aux::y.g(); +} diff --git a/tests/ui/privacy/decl-macro.rs b/tests/ui/privacy/decl-macro.rs new file mode 100644 index 000000000..1eb49bd53 --- /dev/null +++ b/tests/ui/privacy/decl-macro.rs @@ -0,0 +1,9 @@ +#![feature(decl_macro)] + +mod m { + macro mac() {} +} + +fn main() { + m::mac!(); //~ ERROR macro `mac` is private +} diff --git a/tests/ui/privacy/decl-macro.stderr b/tests/ui/privacy/decl-macro.stderr new file mode 100644 index 000000000..5bc6f07ff --- /dev/null +++ b/tests/ui/privacy/decl-macro.stderr @@ -0,0 +1,15 @@ +error[E0603]: macro `mac` is private + --> $DIR/decl-macro.rs:8:8 + | +LL | m::mac!(); + | ^^^ private macro + | +note: the macro `mac` is defined here + --> $DIR/decl-macro.rs:4:5 + | +LL | macro mac() {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/effective_visibilities.rs b/tests/ui/privacy/effective_visibilities.rs new file mode 100644 index 000000000..ff20e20d3 --- /dev/null +++ b/tests/ui/privacy/effective_visibilities.rs @@ -0,0 +1,76 @@ +#![feature(rustc_attrs)] + +#[rustc_effective_visibility] +mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + #[rustc_effective_visibility] + pub mod inner1 { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + + #[rustc_effective_visibility] + extern "C" {} //~ ERROR not in the table + + #[rustc_effective_visibility] + pub trait PubTrait { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + const A: i32; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + type B; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + } + + #[rustc_effective_visibility] + struct PrivStruct; //~ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + //~| ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + + #[rustc_effective_visibility] + pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + a: u8, //~ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + #[rustc_effective_visibility] + pub b: u8, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + } + + #[rustc_effective_visibility] + pub enum Enum { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + A( //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + //~| ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + PubUnion, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + ), + } + } + + #[rustc_effective_visibility] + macro_rules! none_macro { //~ ERROR not in the table + () => {}; + } + + #[macro_export] + #[rustc_effective_visibility] + macro_rules! public_macro { //~ ERROR Direct: pub(self), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + () => {}; + } + + #[rustc_effective_visibility] + pub struct ReachableStruct { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + pub a: u8, //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + } +} + +#[rustc_effective_visibility] +pub use outer::inner1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} } + +mod half_public_import { + #[rustc_effective_visibility] + pub type HalfPublicImport = u8; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + #[allow(non_upper_case_globals)] + pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) +} + +#[rustc_effective_visibility] +pub use half_public_import::HalfPublicImport; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +fn main() {} diff --git a/tests/ui/privacy/effective_visibilities.stderr b/tests/ui/privacy/effective_visibilities.stderr new file mode 100644 index 000000000..046b6095f --- /dev/null +++ b/tests/ui/privacy/effective_visibilities.stderr @@ -0,0 +1,140 @@ +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities.rs:4:1 + | +LL | mod outer { + | ^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:6:5 + | +LL | pub mod inner1 { + | ^^^^^^^^^^^^^^ + +error: not in the table + --> $DIR/effective_visibilities.rs:9:9 + | +LL | extern "C" {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:12:9 + | +LL | pub trait PubTrait { + | ^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + --> $DIR/effective_visibilities.rs:20:9 + | +LL | struct PrivStruct; + | ^^^^^^^^^^^^^^^^^ + +error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + --> $DIR/effective_visibilities.rs:20:9 + | +LL | struct PrivStruct; + | ^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:24:9 + | +LL | pub union PubUnion { + | ^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(self), Reexported: pub(self), Reachable: pub(self), ReachableThroughImplTrait: pub(self) + --> $DIR/effective_visibilities.rs:26:13 + | +LL | a: u8, + | ^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:28:13 + | +LL | pub b: u8, + | ^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:32:9 + | +LL | pub enum Enum { + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:34:13 + | +LL | A( + | ^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:34:13 + | +LL | A( + | ^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:37:17 + | +LL | PubUnion, + | ^^^^^^^^ + +error: not in the table + --> $DIR/effective_visibilities.rs:43:5 + | +LL | macro_rules! none_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(self), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:49:5 + | +LL | macro_rules! public_macro { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:54:5 + | +LL | pub struct ReachableStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:56:9 + | +LL | pub a: u8, + | ^^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:61:9 + | +LL | pub use outer::inner1; + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:67:5 + | +LL | pub type HalfPublicImport = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities.rs:70:5 + | +LL | pub(crate) const HalfPublicImport: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:74:9 + | +LL | pub use half_public_import::HalfPublicImport; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:14:13 + | +LL | const A: i32; + | ^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities.rs:16:13 + | +LL | type B; + | ^^^^^^ + +error: aborting due to 23 previous errors + diff --git a/tests/ui/privacy/effective_visibilities_glob.rs b/tests/ui/privacy/effective_visibilities_glob.rs new file mode 100644 index 000000000..eb9dcd6cd --- /dev/null +++ b/tests/ui/privacy/effective_visibilities_glob.rs @@ -0,0 +1,21 @@ +// Effective visibility tracking for imports is fine-grained, so `S2` is not fully exported +// even if its parent import (`m::*`) is fully exported as a `use` item. + +#![feature(rustc_attrs)] + +mod m { + #[rustc_effective_visibility] + pub struct S1 {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + #[rustc_effective_visibility] + pub struct S2 {} //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) +} + +mod glob { + #[rustc_effective_visibility] + pub use crate::m::*; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub +} + +#[rustc_effective_visibility] +pub use glob::S1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + +fn main() {} diff --git a/tests/ui/privacy/effective_visibilities_glob.stderr b/tests/ui/privacy/effective_visibilities_glob.stderr new file mode 100644 index 000000000..0496cd5df --- /dev/null +++ b/tests/ui/privacy/effective_visibilities_glob.stderr @@ -0,0 +1,26 @@ +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:8:5 + | +LL | pub struct S1 {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities_glob.rs:10:5 + | +LL | pub struct S2 {} + | ^^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:15:13 + | +LL | pub use crate::m::*; + | ^^^^^^^^ + +error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub + --> $DIR/effective_visibilities_glob.rs:19:9 + | +LL | pub use glob::S1; + | ^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/privacy/effective_visibilities_invariants.rs b/tests/ui/privacy/effective_visibilities_invariants.rs new file mode 100644 index 000000000..af5a2bed6 --- /dev/null +++ b/tests/ui/privacy/effective_visibilities_invariants.rs @@ -0,0 +1,12 @@ +// Invariant checking doesn't ICE in some cases with errors (issue #104249). + +#![feature(staged_api)] //~ ERROR module has missing stability attribute + +pub mod m {} //~ ERROR module has missing stability attribute + +pub mod m { //~ ERROR the name `m` is defined multiple times + mod inner {} + type Inner = u8; +} + +fn main() {} diff --git a/tests/ui/privacy/effective_visibilities_invariants.stderr b/tests/ui/privacy/effective_visibilities_invariants.stderr new file mode 100644 index 000000000..fd205f405 --- /dev/null +++ b/tests/ui/privacy/effective_visibilities_invariants.stderr @@ -0,0 +1,32 @@ +error[E0428]: the name `m` is defined multiple times + --> $DIR/effective_visibilities_invariants.rs:7:1 + | +LL | pub mod m {} + | --------- previous definition of the module `m` here +LL | +LL | pub mod m { + | ^^^^^^^^^ `m` redefined here + | + = note: `m` must be defined only once in the type namespace of this module + +error: module has missing stability attribute + --> $DIR/effective_visibilities_invariants.rs:3:1 + | +LL | / #![feature(staged_api)] +LL | | +LL | | pub mod m {} +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: module has missing stability attribute + --> $DIR/effective_visibilities_invariants.rs:5:1 + | +LL | pub mod m {} + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/privacy/export-tag-variant.rs b/tests/ui/privacy/export-tag-variant.rs new file mode 100644 index 000000000..46c10067c --- /dev/null +++ b/tests/ui/privacy/export-tag-variant.rs @@ -0,0 +1,7 @@ +mod foo { + pub fn x() { } + + enum Y { Y1 } +} + +fn main() { let z = foo::Y::Y1; } //~ ERROR: enum `Y` is private diff --git a/tests/ui/privacy/export-tag-variant.stderr b/tests/ui/privacy/export-tag-variant.stderr new file mode 100644 index 000000000..f73bd454d --- /dev/null +++ b/tests/ui/privacy/export-tag-variant.stderr @@ -0,0 +1,15 @@ +error[E0603]: enum `Y` is private + --> $DIR/export-tag-variant.rs:7:26 + | +LL | fn main() { let z = foo::Y::Y1; } + | ^ private enum + | +note: the enum `Y` is defined here + --> $DIR/export-tag-variant.rs:4:5 + | +LL | enum Y { Y1 } + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/impl-privacy-xc-2.rs b/tests/ui/privacy/impl-privacy-xc-2.rs new file mode 100644 index 000000000..390764588 --- /dev/null +++ b/tests/ui/privacy/impl-privacy-xc-2.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:impl_privacy_xc_2.rs + +extern crate impl_privacy_xc_2; + +pub fn main() { + let fish1 = impl_privacy_xc_2::Fish { x: 1 }; + let fish2 = impl_privacy_xc_2::Fish { x: 2 }; + if fish1.eq(&fish2) { println!("yes") } else { println!("no") }; +} diff --git a/tests/ui/privacy/issue-13641.rs b/tests/ui/privacy/issue-13641.rs new file mode 100644 index 000000000..198cea428 --- /dev/null +++ b/tests/ui/privacy/issue-13641.rs @@ -0,0 +1,13 @@ +mod a { + struct Foo; + impl Foo { pub fn new() {} } + enum Bar {} + impl Bar { pub fn new() {} } +} + +fn main() { + a::Foo::new(); + //~^ ERROR: struct `Foo` is private + a::Bar::new(); + //~^ ERROR: enum `Bar` is private +} diff --git a/tests/ui/privacy/issue-13641.stderr b/tests/ui/privacy/issue-13641.stderr new file mode 100644 index 000000000..cdd0772d3 --- /dev/null +++ b/tests/ui/privacy/issue-13641.stderr @@ -0,0 +1,27 @@ +error[E0603]: struct `Foo` is private + --> $DIR/issue-13641.rs:9:8 + | +LL | a::Foo::new(); + | ^^^ private struct + | +note: the struct `Foo` is defined here + --> $DIR/issue-13641.rs:2:5 + | +LL | struct Foo; + | ^^^^^^^^^^^ + +error[E0603]: enum `Bar` is private + --> $DIR/issue-13641.rs:11:8 + | +LL | a::Bar::new(); + | ^^^ private enum + | +note: the enum `Bar` is defined here + --> $DIR/issue-13641.rs:4:5 + | +LL | enum Bar {} + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/issue-17718-const-privacy.rs b/tests/ui/privacy/issue-17718-const-privacy.rs new file mode 100644 index 000000000..6ab3a60df --- /dev/null +++ b/tests/ui/privacy/issue-17718-const-privacy.rs @@ -0,0 +1,16 @@ +// aux-build:issue-17718-const-privacy.rs + +extern crate issue_17718_const_privacy as other; + +use a::B; //~ ERROR: constant `B` is private +use other::{ + FOO, + BAR, //~ ERROR: constant `BAR` is private + FOO2, +}; + +mod a { + const B: usize = 3; +} + +fn main() {} diff --git a/tests/ui/privacy/issue-17718-const-privacy.stderr b/tests/ui/privacy/issue-17718-const-privacy.stderr new file mode 100644 index 000000000..133a6360b --- /dev/null +++ b/tests/ui/privacy/issue-17718-const-privacy.stderr @@ -0,0 +1,27 @@ +error[E0603]: constant `B` is private + --> $DIR/issue-17718-const-privacy.rs:5:8 + | +LL | use a::B; + | ^ private constant + | +note: the constant `B` is defined here + --> $DIR/issue-17718-const-privacy.rs:13:5 + | +LL | const B: usize = 3; + | ^^^^^^^^^^^^^^^^^^^ + +error[E0603]: constant `BAR` is private + --> $DIR/issue-17718-const-privacy.rs:8:5 + | +LL | BAR, + | ^^^ private constant + | +note: the constant `BAR` is defined here + --> $DIR/auxiliary/issue-17718-const-privacy.rs:4:1 + | +LL | const BAR: usize = 3; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/issue-29161.rs b/tests/ui/privacy/issue-29161.rs new file mode 100644 index 000000000..d80405aa8 --- /dev/null +++ b/tests/ui/privacy/issue-29161.rs @@ -0,0 +1,15 @@ +mod a { + struct A; + + impl Default for A { + pub fn default() -> A { //~ ERROR unnecessary visibility qualifier + A + } + } +} + + +fn main() { + a::A::default(); + //~^ ERROR struct `A` is private + } diff --git a/tests/ui/privacy/issue-29161.stderr b/tests/ui/privacy/issue-29161.stderr new file mode 100644 index 000000000..7ce95e4b0 --- /dev/null +++ b/tests/ui/privacy/issue-29161.stderr @@ -0,0 +1,22 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/issue-29161.rs:5:9 + | +LL | pub fn default() -> A { + | ^^^ `pub` not permitted here because it's implied + +error[E0603]: struct `A` is private + --> $DIR/issue-29161.rs:13:8 + | +LL | a::A::default(); + | ^ private struct + | +note: the struct `A` is defined here + --> $DIR/issue-29161.rs:2:5 + | +LL | struct A; + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0449, E0603. +For more information about an error, try `rustc --explain E0449`. diff --git a/tests/ui/privacy/issue-30079.rs b/tests/ui/privacy/issue-30079.rs new file mode 100644 index 000000000..a02a932d0 --- /dev/null +++ b/tests/ui/privacy/issue-30079.rs @@ -0,0 +1,39 @@ +struct SemiPriv; + +mod m1 { + struct Priv; + impl ::SemiPriv { + pub fn f(_: Priv) {} //~ WARN private type `m1::Priv` in public interface + //~^ WARNING hard error + } + + impl Priv { + pub fn f(_: Priv) {} // ok + } +} + +mod m2 { + struct Priv; + impl ::std::ops::Deref for ::SemiPriv { + type Target = Priv; //~ ERROR private type `m2::Priv` in public interface + fn deref(&self) -> &Self::Target { unimplemented!() } + } + + impl ::std::ops::Deref for Priv { + type Target = Priv; // ok + fn deref(&self) -> &Self::Target { unimplemented!() } + } +} + +trait SemiPrivTrait { + type Assoc; +} + +mod m3 { + struct Priv; + impl ::SemiPrivTrait for () { + type Assoc = Priv; //~ ERROR private type `m3::Priv` in public interface + } +} + +fn main() {} diff --git a/tests/ui/privacy/issue-30079.stderr b/tests/ui/privacy/issue-30079.stderr new file mode 100644 index 000000000..9179ff339 --- /dev/null +++ b/tests/ui/privacy/issue-30079.stderr @@ -0,0 +1,31 @@ +warning: private type `m1::Priv` in public interface (error E0446) + --> $DIR/issue-30079.rs:6:9 + | +LL | pub fn f(_: Priv) {} + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + = note: `#[warn(private_in_public)]` on by default + +error[E0446]: private type `m2::Priv` in public interface + --> $DIR/issue-30079.rs:18:9 + | +LL | struct Priv; + | ----------- `m2::Priv` declared as private +LL | impl ::std::ops::Deref for ::SemiPriv { +LL | type Target = Priv; + | ^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `m3::Priv` in public interface + --> $DIR/issue-30079.rs:35:9 + | +LL | struct Priv; + | ----------- `m3::Priv` declared as private +LL | impl ::SemiPrivTrait for () { +LL | type Assoc = Priv; + | ^^^^^^^^^^ can't leak private type + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs new file mode 100644 index 000000000..6f115e78e --- /dev/null +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.rs @@ -0,0 +1,40 @@ +#[deny(unused_imports)] +mod rank { + pub use self::Professor::*; + //~^ ERROR glob import doesn't reexport anything + pub use self::Lieutenant::{JuniorGrade, Full}; + //~^ ERROR `JuniorGrade` is private, and cannot be re-exported + //~| ERROR `Full` is private, and cannot be re-exported + pub use self::PettyOfficer::*; + //~^ ERROR glob import doesn't reexport anything + pub use self::Crewman::*; + //~^ ERROR glob import doesn't reexport anything + + enum Professor { + Adjunct, + Assistant, + Associate, + Full + } + + enum Lieutenant { + JuniorGrade, + Full, + } + + pub(in rank) enum PettyOfficer { + SecondClass, + FirstClass, + Chief, + MasterChief + } + + pub(crate) enum Crewman { + Recruit, + Apprentice, + Full + } + +} + +fn main() {} diff --git a/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr new file mode 100644 index 000000000..59b181fab --- /dev/null +++ b/tests/ui/privacy/issue-46209-private-enum-variant-reexport.stderr @@ -0,0 +1,51 @@ +error[E0364]: `JuniorGrade` is private, and cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:5:32 + | +LL | pub use self::Lieutenant::{JuniorGrade, Full}; + | ^^^^^^^^^^^ + | +note: consider marking `JuniorGrade` as `pub` in the imported module + --> $DIR/issue-46209-private-enum-variant-reexport.rs:5:32 + | +LL | pub use self::Lieutenant::{JuniorGrade, Full}; + | ^^^^^^^^^^^ + +error[E0364]: `Full` is private, and cannot be re-exported + --> $DIR/issue-46209-private-enum-variant-reexport.rs:5:45 + | +LL | pub use self::Lieutenant::{JuniorGrade, Full}; + | ^^^^ + | +note: consider marking `Full` as `pub` in the imported module + --> $DIR/issue-46209-private-enum-variant-reexport.rs:5:45 + | +LL | pub use self::Lieutenant::{JuniorGrade, Full}; + | ^^^^ + +error: glob import doesn't reexport anything because no candidate is public enough + --> $DIR/issue-46209-private-enum-variant-reexport.rs:3:13 + | +LL | pub use self::Professor::*; + | ^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-46209-private-enum-variant-reexport.rs:1:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: glob import doesn't reexport anything because no candidate is public enough + --> $DIR/issue-46209-private-enum-variant-reexport.rs:8:13 + | +LL | pub use self::PettyOfficer::*; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: glob import doesn't reexport anything because no candidate is public enough + --> $DIR/issue-46209-private-enum-variant-reexport.rs:10:13 + | +LL | pub use self::Crewman::*; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/privacy/issue-57264-1.rs b/tests/ui/privacy/issue-57264-1.rs new file mode 100644 index 000000000..59ebc4f54 --- /dev/null +++ b/tests/ui/privacy/issue-57264-1.rs @@ -0,0 +1,8 @@ +// check-pass +// aux-build:issue-57264-1.rs + +extern crate issue_57264_1; + +fn main() { + issue_57264_1::Pub::pub_method(); +} diff --git a/tests/ui/privacy/issue-57264-2.rs b/tests/ui/privacy/issue-57264-2.rs new file mode 100644 index 000000000..36ce5fd3b --- /dev/null +++ b/tests/ui/privacy/issue-57264-2.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:issue-57264-2.rs + +extern crate issue_57264_2; + +fn infer(arg: T) -> T { arg } + +fn main() { + infer(None).unwrap().pub_method(); +} diff --git a/tests/ui/privacy/issue-75062-fieldless-tuple-struct.rs b/tests/ui/privacy/issue-75062-fieldless-tuple-struct.rs new file mode 100644 index 000000000..4601a3d47 --- /dev/null +++ b/tests/ui/privacy/issue-75062-fieldless-tuple-struct.rs @@ -0,0 +1,10 @@ +// Regression test for issue #75062 +// Tests that we don't ICE on a privacy error for a fieldless tuple struct. + +mod foo { + struct Bar(); +} + +fn main() { + foo::Bar(); //~ ERROR tuple struct +} diff --git a/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr b/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr new file mode 100644 index 000000000..14a12003e --- /dev/null +++ b/tests/ui/privacy/issue-75062-fieldless-tuple-struct.stderr @@ -0,0 +1,15 @@ +error[E0603]: tuple struct `Bar` is private + --> $DIR/issue-75062-fieldless-tuple-struct.rs:9:10 + | +LL | foo::Bar(); + | ^^^ private tuple struct + | +note: the tuple struct `Bar` is defined here + --> $DIR/issue-75062-fieldless-tuple-struct.rs:5:5 + | +LL | struct Bar(); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/issue-75906.rs b/tests/ui/privacy/issue-75906.rs new file mode 100644 index 000000000..710039d79 --- /dev/null +++ b/tests/ui/privacy/issue-75906.rs @@ -0,0 +1,13 @@ +mod m { + pub struct Foo { x: u8 } + + pub struct Bar(u8); +} + +use m::{Foo, Bar}; + +fn main() { + let x = Foo { x: 12 }; + let y = Bar(12); + //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423] +} diff --git a/tests/ui/privacy/issue-75906.stderr b/tests/ui/privacy/issue-75906.stderr new file mode 100644 index 000000000..600dc7c87 --- /dev/null +++ b/tests/ui/privacy/issue-75906.stderr @@ -0,0 +1,19 @@ +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/issue-75906.rs:11:13 + | +LL | let y = Bar(12); + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75906.rs:4:20 + | +LL | pub struct Bar(u8); + | ^^ private field +help: consider making the field publicly accessible + | +LL | pub struct Bar(pub u8); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/issue-75907.rs b/tests/ui/privacy/issue-75907.rs new file mode 100644 index 000000000..3bed841d1 --- /dev/null +++ b/tests/ui/privacy/issue-75907.rs @@ -0,0 +1,18 @@ +// Test for diagnostic improvement issue #75907 + +mod foo { + pub(crate) struct Foo(u8); + pub(crate) struct Bar(pub u8, pub(in crate::foo) u8, Foo); + + pub(crate) fn make_bar() -> Bar { + Bar(1, 12, Foo(10)) + } +} + +use foo::{make_bar, Bar, Foo}; + +fn main() { + let Bar(x, y, Foo(z)) = make_bar(); + //~^ ERROR cannot match against a tuple struct which contains private fields + //~| ERROR cannot match against a tuple struct which contains private fields +} diff --git a/tests/ui/privacy/issue-75907.stderr b/tests/ui/privacy/issue-75907.stderr new file mode 100644 index 000000000..f7cb874c2 --- /dev/null +++ b/tests/ui/privacy/issue-75907.stderr @@ -0,0 +1,37 @@ +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/issue-75907.rs:15:9 + | +LL | let Bar(x, y, Foo(z)) = make_bar(); + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75907.rs:15:16 + | +LL | let Bar(x, y, Foo(z)) = make_bar(); + | ^ ^^^^^^ private field + | | + | private field +help: consider making the fields publicly accessible + | +LL | pub(crate) struct Bar(pub u8, pub u8, pub Foo); + | ~~~ ~~~ +++ + +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/issue-75907.rs:15:19 + | +LL | let Bar(x, y, Foo(z)) = make_bar(); + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75907.rs:15:23 + | +LL | let Bar(x, y, Foo(z)) = make_bar(); + | ^ private field +help: consider making the field publicly accessible + | +LL | pub(crate) struct Foo(pub u8); + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/privacy/issue-75907_b.rs b/tests/ui/privacy/issue-75907_b.rs new file mode 100644 index 000000000..fdfc5907c --- /dev/null +++ b/tests/ui/privacy/issue-75907_b.rs @@ -0,0 +1,14 @@ +// Test for diagnostic improvement issue #75907, extern crate +// aux-build:issue-75907.rs + +extern crate issue_75907 as a; + +use a::{make_bar, Bar, Foo}; + +fn main() { + let Bar(x, y, z) = make_bar(); + //~^ ERROR cannot match against a tuple struct which contains private fields + + let Foo(x, y, z) = Foo::new(); + //~^ ERROR cannot match against a tuple struct which contains private fields +} diff --git a/tests/ui/privacy/issue-75907_b.stderr b/tests/ui/privacy/issue-75907_b.stderr new file mode 100644 index 000000000..b82d08473 --- /dev/null +++ b/tests/ui/privacy/issue-75907_b.stderr @@ -0,0 +1,31 @@ +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/issue-75907_b.rs:9:9 + | +LL | let Bar(x, y, z) = make_bar(); + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75907_b.rs:9:16 + | +LL | let Bar(x, y, z) = make_bar(); + | ^ ^ private field + | | + | private field + +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/issue-75907_b.rs:12:9 + | +LL | let Foo(x, y, z) = Foo::new(); + | ^^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-75907_b.rs:12:13 + | +LL | let Foo(x, y, z) = Foo::new(); + | ^ ^ private field + | | + | private field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/privacy/issue-79593.rs b/tests/ui/privacy/issue-79593.rs new file mode 100644 index 000000000..39c222f7c --- /dev/null +++ b/tests/ui/privacy/issue-79593.rs @@ -0,0 +1,29 @@ +mod foo { + pub struct Pub { private: () } + + pub enum Enum { + Variant { x: (), y: () }, + Other + } + + fn correct() { + Pub {}; + //~^ ERROR missing field `private` in initializer of `Pub` + Enum::Variant { x: () }; + //~^ ERROR missing field `y` in initializer of `Enum` + } +} + +fn correct() { + foo::Pub {}; + //~^ ERROR cannot construct `Pub` with struct literal syntax due to private fields +} + +fn wrong() { + foo::Enum::Variant { x: () }; + //~^ ERROR missing field `y` in initializer of `Enum` + foo::Enum::Variant { }; + //~^ ERROR missing fields `x` and `y` in initializer of `Enum` +} + +fn main() {} diff --git a/tests/ui/privacy/issue-79593.stderr b/tests/ui/privacy/issue-79593.stderr new file mode 100644 index 000000000..21ba760ad --- /dev/null +++ b/tests/ui/privacy/issue-79593.stderr @@ -0,0 +1,35 @@ +error[E0063]: missing field `private` in initializer of `Pub` + --> $DIR/issue-79593.rs:10:9 + | +LL | Pub {}; + | ^^^ missing `private` + +error[E0063]: missing field `y` in initializer of `Enum` + --> $DIR/issue-79593.rs:12:9 + | +LL | Enum::Variant { x: () }; + | ^^^^^^^^^^^^^ missing `y` + +error: cannot construct `Pub` with struct literal syntax due to private fields + --> $DIR/issue-79593.rs:18:5 + | +LL | foo::Pub {}; + | ^^^^^^^^ + | + = note: ... and other private field `private` that was not provided + +error[E0063]: missing field `y` in initializer of `Enum` + --> $DIR/issue-79593.rs:23:5 + | +LL | foo::Enum::Variant { x: () }; + | ^^^^^^^^^^^^^^^^^^ missing `y` + +error[E0063]: missing fields `x` and `y` in initializer of `Enum` + --> $DIR/issue-79593.rs:25:5 + | +LL | foo::Enum::Variant { }; + | ^^^^^^^^^^^^^^^^^^ missing `x` and `y` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/privacy/issue-92755.rs b/tests/ui/privacy/issue-92755.rs new file mode 100644 index 000000000..49559152b --- /dev/null +++ b/tests/ui/privacy/issue-92755.rs @@ -0,0 +1,10 @@ +// aux-build:issue-92755.rs +// build-pass + +// Thank you @tmiasko for providing the content of this test! + +extern crate issue_92755; + +fn main() { + issue_92755::ctx().a.b.f(); +} diff --git a/tests/ui/privacy/legacy-ctor-visibility.rs b/tests/ui/privacy/legacy-ctor-visibility.rs new file mode 100644 index 000000000..5732b6446 --- /dev/null +++ b/tests/ui/privacy/legacy-ctor-visibility.rs @@ -0,0 +1,15 @@ +use m::S; + +mod m { + pub struct S(u8); + + mod n { + use S; + fn f() { + S(10); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `S` + } + } +} + +fn main() {} diff --git a/tests/ui/privacy/legacy-ctor-visibility.stderr b/tests/ui/privacy/legacy-ctor-visibility.stderr new file mode 100644 index 000000000..c8057d85e --- /dev/null +++ b/tests/ui/privacy/legacy-ctor-visibility.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `S` + --> $DIR/legacy-ctor-visibility.rs:9:13 + | +LL | S(10); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/macro-private-reexport.rs b/tests/ui/privacy/macro-private-reexport.rs new file mode 100644 index 000000000..d0aab528e --- /dev/null +++ b/tests/ui/privacy/macro-private-reexport.rs @@ -0,0 +1,17 @@ +// edition:2021 + +#![feature(decl_macro)] + +mod foo { + macro_rules! bar { + () => {}; + } + + pub use bar as _; //~ ERROR `bar` is only public within the crate, and cannot be re-exported outside + + macro baz() {} + + pub use baz as _; //~ ERROR `baz` is private, and cannot be re-exported +} + +fn main() {} diff --git a/tests/ui/privacy/macro-private-reexport.stderr b/tests/ui/privacy/macro-private-reexport.stderr new file mode 100644 index 000000000..b8768f361 --- /dev/null +++ b/tests/ui/privacy/macro-private-reexport.stderr @@ -0,0 +1,29 @@ +error[E0364]: `bar` is only public within the crate, and cannot be re-exported outside + --> $DIR/macro-private-reexport.rs:10:13 + | +LL | pub use bar as _; + | ^^^^^^^^ + | +help: consider adding a `#[macro_export]` to the macro in the imported module + --> $DIR/macro-private-reexport.rs:6:5 + | +LL | / macro_rules! bar { +LL | | () => {}; +LL | | } + | |_____^ + +error[E0364]: `baz` is private, and cannot be re-exported + --> $DIR/macro-private-reexport.rs:14:13 + | +LL | pub use baz as _; + | ^^^^^^^^ + | +note: consider marking `baz` as `pub` in the imported module + --> $DIR/macro-private-reexport.rs:14:13 + | +LL | pub use baz as _; + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/privacy/priv-impl-prim-ty.rs b/tests/ui/privacy/priv-impl-prim-ty.rs new file mode 100644 index 000000000..5d6a6b64e --- /dev/null +++ b/tests/ui/privacy/priv-impl-prim-ty.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:priv-impl-prim-ty.rs + +// pretty-expanded FIXME #23616 + +extern crate priv_impl_prim_ty as bar; + +pub fn main() { + bar::frob(1); + +} diff --git a/tests/ui/privacy/priv-in-bad-locations.rs b/tests/ui/privacy/priv-in-bad-locations.rs new file mode 100644 index 000000000..76af8c6cd --- /dev/null +++ b/tests/ui/privacy/priv-in-bad-locations.rs @@ -0,0 +1,17 @@ +pub extern "C" { //~ ERROR unnecessary visibility qualifier + pub fn bar(); +} + +trait A { + fn foo(&self) {} +} + +struct B; + +pub impl B {} //~ ERROR unnecessary visibility qualifier + +pub impl A for B { //~ ERROR unnecessary visibility qualifier + pub fn foo(&self) {} //~ ERROR unnecessary visibility qualifier +} + +pub fn main() {} diff --git a/tests/ui/privacy/priv-in-bad-locations.stderr b/tests/ui/privacy/priv-in-bad-locations.stderr new file mode 100644 index 000000000..75bd2fe47 --- /dev/null +++ b/tests/ui/privacy/priv-in-bad-locations.stderr @@ -0,0 +1,31 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/priv-in-bad-locations.rs:1:1 + | +LL | pub extern "C" { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual foreign items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/priv-in-bad-locations.rs:11:1 + | +LL | pub impl B {} + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual impl items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/priv-in-bad-locations.rs:13:1 + | +LL | pub impl A for B { + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/priv-in-bad-locations.rs:14:5 + | +LL | pub fn foo(&self) {} + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/privacy/privacy-in-paths.rs b/tests/ui/privacy/privacy-in-paths.rs new file mode 100644 index 000000000..9cee2b89d --- /dev/null +++ b/tests/ui/privacy/privacy-in-paths.rs @@ -0,0 +1,30 @@ +mod foo { + pub use self::bar::S; + mod bar { + pub struct S; + pub use baz; + } + + trait T { + type Assoc; + } + impl T for () { + type Assoc = S; + } +} + +impl foo::S { + fn f() {} +} + +pub mod baz { + fn f() {} + + fn g() { + ::foo::bar::baz::f(); //~ERROR module `bar` is private + ::foo::bar::S::f(); //~ERROR module `bar` is private + <() as ::foo::T>::Assoc::f(); //~ERROR trait `T` is private + } +} + +fn main() {} diff --git a/tests/ui/privacy/privacy-in-paths.stderr b/tests/ui/privacy/privacy-in-paths.stderr new file mode 100644 index 000000000..2eb3ebb51 --- /dev/null +++ b/tests/ui/privacy/privacy-in-paths.stderr @@ -0,0 +1,39 @@ +error[E0603]: module `bar` is private + --> $DIR/privacy-in-paths.rs:24:16 + | +LL | ::foo::bar::baz::f(); + | ^^^ private module + | +note: the module `bar` is defined here + --> $DIR/privacy-in-paths.rs:3:5 + | +LL | mod bar { + | ^^^^^^^ + +error[E0603]: module `bar` is private + --> $DIR/privacy-in-paths.rs:25:16 + | +LL | ::foo::bar::S::f(); + | ^^^ private module + | +note: the module `bar` is defined here + --> $DIR/privacy-in-paths.rs:3:5 + | +LL | mod bar { + | ^^^^^^^ + +error[E0603]: trait `T` is private + --> $DIR/privacy-in-paths.rs:26:23 + | +LL | <() as ::foo::T>::Assoc::f(); + | ^ private trait + | +note: the trait `T` is defined here + --> $DIR/privacy-in-paths.rs:8:5 + | +LL | trait T { + | ^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/privacy-ns.rs b/tests/ui/privacy/privacy-ns.rs new file mode 100644 index 000000000..c32e3f178 --- /dev/null +++ b/tests/ui/privacy/privacy-ns.rs @@ -0,0 +1,114 @@ +// run-pass +#![allow(non_snake_case)] + + +// Check we do the correct privacy checks when we import a name and there is an +// item with that name in both the value and type namespaces. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] +#![allow(unused_imports)] + + +// public type, private value +pub mod foo1 { + pub trait Bar { + fn dummy(&self) { } + } + pub struct Baz; + + fn Bar() { } +} + +fn test_unused1() { + use foo1::*; +} + +fn test_single1() { + use foo1::Bar; + + let _x: Box; +} + +fn test_list1() { + use foo1::{Bar,Baz}; + + let _x: Box; +} + +fn test_glob1() { + use foo1::*; + + let _x: Box; +} + +// private type, public value +pub mod foo2 { + trait Bar { + fn dummy(&self) { } + } + pub struct Baz; + + pub fn Bar() { } +} + +fn test_unused2() { + use foo2::*; +} + +fn test_single2() { + use foo2::Bar; + + Bar(); +} + +fn test_list2() { + use foo2::{Bar,Baz}; + + Bar(); +} + +fn test_glob2() { + use foo2::*; + + Bar(); +} + +// public type, public value +pub mod foo3 { + pub trait Bar { + fn dummy(&self) { } + } + pub struct Baz; + + pub fn Bar() { } +} + +fn test_unused3() { + use foo3::*; +} + +fn test_single3() { + use foo3::Bar; + + Bar(); + let _x: Box; +} + +fn test_list3() { + use foo3::{Bar,Baz}; + + Bar(); + let _x: Box; +} + +fn test_glob3() { + use foo3::*; + + Bar(); + let _x: Box; +} + +fn main() { +} diff --git a/tests/ui/privacy/privacy-ns1.rs b/tests/ui/privacy/privacy-ns1.rs new file mode 100644 index 000000000..1af5b857e --- /dev/null +++ b/tests/ui/privacy/privacy-ns1.rs @@ -0,0 +1,56 @@ +// Check we do the correct privacy checks when we import a name and there is an +// item with that name in both the value and type namespaces. + +#![allow(dead_code)] +#![allow(unused_imports)] + + +// public type, private value +pub mod foo1 { + pub trait Bar { + } + pub struct Baz; + + fn Bar() { } +} + +fn test_glob1() { + use foo1::*; + + Bar(); //~ ERROR expected function, tuple struct or tuple variant, found trait `Bar` +} + +// private type, public value +pub mod foo2 { + trait Bar { + } + pub struct Baz; + + pub fn Bar() { } +} + +fn test_glob2() { + use foo2::*; + + let _x: Box; + //~^ ERROR constant provided when a type was expected +} + +// neither public +pub mod foo3 { + trait Bar { + } + pub struct Baz; + + fn Bar() { } +} + +fn test_glob3() { + use foo3::*; + + Bar(); //~ ERROR cannot find function, tuple struct or tuple variant `Bar` in this scope + let _x: Box; //~ ERROR cannot find type `Bar` in this scope +} + +fn main() { +} diff --git a/tests/ui/privacy/privacy-ns1.stderr b/tests/ui/privacy/privacy-ns1.stderr new file mode 100644 index 000000000..91bc84e70 --- /dev/null +++ b/tests/ui/privacy/privacy-ns1.stderr @@ -0,0 +1,67 @@ +error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar` + --> $DIR/privacy-ns1.rs:20:5 + | +LL | pub struct Baz; + | --------------- similarly named unit struct `Baz` defined here +... +LL | Bar(); + | ^^^ + | +help: a unit struct with a similar name exists + | +LL | Baz(); + | ~~~ +help: consider importing this function instead + | +LL | use foo2::Bar; + | + +error[E0425]: cannot find function, tuple struct or tuple variant `Bar` in this scope + --> $DIR/privacy-ns1.rs:51:5 + | +LL | pub struct Baz; + | --------------- similarly named unit struct `Baz` defined here +... +LL | Bar(); + | ^^^ + | +help: a unit struct with a similar name exists + | +LL | Baz(); + | ~~~ +help: consider importing this function + | +LL | use foo2::Bar; + | + +error[E0412]: cannot find type `Bar` in this scope + --> $DIR/privacy-ns1.rs:52:17 + | +LL | pub struct Baz; + | --------------- similarly named struct `Baz` defined here +... +LL | let _x: Box; + | ^^^ + | +help: a struct with a similar name exists + | +LL | let _x: Box; + | ~~~ +help: consider importing this trait + | +LL | use foo1::Bar; + | + +error[E0747]: constant provided when a type was expected + --> $DIR/privacy-ns1.rs:35:17 + | +LL | let _x: Box; + | ^^^ + | + = help: `Bar` is a function item, not a type + = help: function item types cannot be named directly + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0412, E0423, E0425, E0747. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/privacy/privacy-ns2.rs b/tests/ui/privacy/privacy-ns2.rs new file mode 100644 index 000000000..47035ef3a --- /dev/null +++ b/tests/ui/privacy/privacy-ns2.rs @@ -0,0 +1,79 @@ +// Check we do the correct privacy checks when we import a name and there is an +// item with that name in both the value and type namespaces. + +#![allow(dead_code)] +#![allow(unused_imports)] + + +// public type, private value +pub mod foo1 { + pub trait Bar { + } + pub struct Baz; + + fn Bar() { } +} + +fn test_single1() { + use foo1::Bar; + + Bar(); //~ ERROR expected function, tuple struct or tuple variant, found trait `Bar` +} + +fn test_list1() { + use foo1::{Bar,Baz}; + + Bar(); //~ ERROR expected function, tuple struct or tuple variant, found trait `Bar` +} + +// private type, public value +pub mod foo2 { + trait Bar { + } + pub struct Baz; + + pub fn Bar() { } +} + +fn test_single2() { + use foo2::Bar; + + let _x : Box; //~ ERROR constant provided when a type was expected + let _x : Bar(); //~ ERROR expected type, found function `Bar` +} + +fn test_list2() { + use foo2::{Bar,Baz}; + + let _x: Box; //~ ERROR constant provided when a type was expected +} + +// neither public +pub mod foo3 { + trait Bar { + } + pub struct Baz; + + fn Bar() { } +} + +fn test_unused3() { + use foo3::Bar; //~ ERROR `Bar` is private +} + +fn test_single3() { + use foo3::Bar; //~ ERROR `Bar` is private + + Bar(); + let _x: Box; +} + +fn test_list3() { + use foo3::{Bar,Baz}; //~ ERROR `Bar` is private + + Bar(); + let _x: Box; +} + +fn main() { +} diff --git a/tests/ui/privacy/privacy-ns2.stderr b/tests/ui/privacy/privacy-ns2.stderr new file mode 100644 index 000000000..904e9013f --- /dev/null +++ b/tests/ui/privacy/privacy-ns2.stderr @@ -0,0 +1,102 @@ +error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar` + --> $DIR/privacy-ns2.rs:20:5 + | +LL | Bar(); + | ^^^ not a function, tuple struct or tuple variant + | +help: consider importing this function instead + | +LL | use foo2::Bar; + | + +error[E0423]: expected function, tuple struct or tuple variant, found trait `Bar` + --> $DIR/privacy-ns2.rs:26:5 + | +LL | pub struct Baz; + | --------------- similarly named unit struct `Baz` defined here +... +LL | Bar(); + | ^^^ + | +help: a unit struct with a similar name exists + | +LL | Baz(); + | ~~~ +help: consider importing this function instead + | +LL | use foo2::Bar; + | + +error[E0573]: expected type, found function `Bar` + --> $DIR/privacy-ns2.rs:42:14 + | +LL | let _x : Bar(); + | ^^^^^ not a type + | +help: use `=` if you meant to assign + | +LL | let _x = Bar(); + | ~ +help: consider importing this trait instead + | +LL | use foo1::Bar; + | + +error[E0603]: trait `Bar` is private + --> $DIR/privacy-ns2.rs:61:15 + | +LL | use foo3::Bar; + | ^^^ private trait + | +note: the trait `Bar` is defined here + --> $DIR/privacy-ns2.rs:53:5 + | +LL | trait Bar { + | ^^^^^^^^^ + +error[E0603]: trait `Bar` is private + --> $DIR/privacy-ns2.rs:65:15 + | +LL | use foo3::Bar; + | ^^^ private trait + | +note: the trait `Bar` is defined here + --> $DIR/privacy-ns2.rs:53:5 + | +LL | trait Bar { + | ^^^^^^^^^ + +error[E0603]: trait `Bar` is private + --> $DIR/privacy-ns2.rs:72:16 + | +LL | use foo3::{Bar,Baz}; + | ^^^ private trait + | +note: the trait `Bar` is defined here + --> $DIR/privacy-ns2.rs:53:5 + | +LL | trait Bar { + | ^^^^^^^^^ + +error[E0747]: constant provided when a type was expected + --> $DIR/privacy-ns2.rs:41:18 + | +LL | let _x : Box; + | ^^^ + | + = help: `Bar` is a function item, not a type + = help: function item types cannot be named directly + +error[E0747]: constant provided when a type was expected + --> $DIR/privacy-ns2.rs:48:17 + | +LL | let _x: Box; + | ^^^ + | + = help: `Bar` is a function item, not a type + = help: function item types cannot be named directly + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0423, E0573, E0603, E0747. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/privacy-reexport.rs b/tests/ui/privacy/privacy-reexport.rs new file mode 100644 index 000000000..b3ec3af04 --- /dev/null +++ b/tests/ui/privacy/privacy-reexport.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:privacy_reexport.rs + +// pretty-expanded FIXME #23616 + +extern crate privacy_reexport; + +pub fn main() { + // Check that public extern crates are visible to outside crates + privacy_reexport::core::cell::Cell::new(0); + + privacy_reexport::bar::frob(); +} diff --git a/tests/ui/privacy/privacy-sanity.rs b/tests/ui/privacy/privacy-sanity.rs new file mode 100644 index 000000000..8bbf1ab5d --- /dev/null +++ b/tests/ui/privacy/privacy-sanity.rs @@ -0,0 +1,82 @@ +#![feature(negative_impls)] + +pub trait Tr { + fn f(); + const C: u8; + type T; +} +pub struct S { + pub a: u8 +} +struct Ts(pub u8); + +pub impl Tr for S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} //~ ERROR unnecessary visibility qualifier + pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier + pub type T = u8; //~ ERROR unnecessary visibility qualifier +} +pub impl S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} + pub const C: u8 = 0; + // pub type T = u8; +} +pub extern "C" { //~ ERROR unnecessary visibility qualifier + pub fn f(); + pub static St: u8; +} + +const MAIN: u8 = { + pub trait Tr { + fn f(); + const C: u8; + type T; + } + pub struct S { + pub a: u8 + } + struct Ts(pub u8); + + pub impl Tr for S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} //~ ERROR unnecessary visibility qualifier + pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier + pub type T = u8; //~ ERROR unnecessary visibility qualifier + } + pub impl S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} + pub const C: u8 = 0; + // pub type T = u8; + } + pub extern "C" { //~ ERROR unnecessary visibility qualifier + pub fn f(); + pub static St: u8; + } + + 0 +}; + +fn main() { + pub trait Tr { + fn f(); + const C: u8; + type T; + } + pub struct S { + pub a: u8 + } + struct Ts(pub u8); + + pub impl Tr for S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} //~ ERROR unnecessary visibility qualifier + pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier + pub type T = u8; //~ ERROR unnecessary visibility qualifier + } + pub impl S { //~ ERROR unnecessary visibility qualifier + pub fn f() {} + pub const C: u8 = 0; + // pub type T = u8; + } + pub extern "C" { //~ ERROR unnecessary visibility qualifier + pub fn f(); + pub static St: u8; + } +} diff --git a/tests/ui/privacy/privacy-sanity.stderr b/tests/ui/privacy/privacy-sanity.stderr new file mode 100644 index 000000000..c92553fd1 --- /dev/null +++ b/tests/ui/privacy/privacy-sanity.stderr @@ -0,0 +1,123 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:13:1 + | +LL | pub impl Tr for S { + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:14:5 + | +LL | pub fn f() {} + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:15:5 + | +LL | pub const C: u8 = 0; + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:16:5 + | +LL | pub type T = u8; + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:18:1 + | +LL | pub impl S { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual impl items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:23:1 + | +LL | pub extern "C" { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual foreign items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:39:5 + | +LL | pub impl Tr for S { + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:40:9 + | +LL | pub fn f() {} + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:41:9 + | +LL | pub const C: u8 = 0; + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:42:9 + | +LL | pub type T = u8; + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:44:5 + | +LL | pub impl S { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual impl items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:49:5 + | +LL | pub extern "C" { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual foreign items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:68:5 + | +LL | pub impl Tr for S { + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:69:9 + | +LL | pub fn f() {} + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:70:9 + | +LL | pub const C: u8 = 0; + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:71:9 + | +LL | pub type T = u8; + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:73:5 + | +LL | pub impl S { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual impl items instead + +error[E0449]: unnecessary visibility qualifier + --> $DIR/privacy-sanity.rs:78:5 + | +LL | pub extern "C" { + | ^^^ `pub` not permitted here because it's implied + | + = note: place qualifiers on individual foreign items instead + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/privacy/privacy-ufcs.rs b/tests/ui/privacy/privacy-ufcs.rs new file mode 100644 index 000000000..fec7f4134 --- /dev/null +++ b/tests/ui/privacy/privacy-ufcs.rs @@ -0,0 +1,13 @@ +// Test to ensure private traits are inaccessible with UFCS angle-bracket syntax. + +mod foo { + trait Bar { + fn baz() {} + } + + impl Bar for i32 {} +} + +fn main() { + ::baz(); //~ERROR trait `Bar` is private +} diff --git a/tests/ui/privacy/privacy-ufcs.stderr b/tests/ui/privacy/privacy-ufcs.stderr new file mode 100644 index 000000000..e93a458ce --- /dev/null +++ b/tests/ui/privacy/privacy-ufcs.stderr @@ -0,0 +1,15 @@ +error[E0603]: trait `Bar` is private + --> $DIR/privacy-ufcs.rs:12:20 + | +LL | ::baz(); + | ^^^ private trait + | +note: the trait `Bar` is defined here + --> $DIR/privacy-ufcs.rs:4:5 + | +LL | trait Bar { + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/privacy1-rpass.rs b/tests/ui/privacy/privacy1-rpass.rs new file mode 100644 index 000000000..4e54780da --- /dev/null +++ b/tests/ui/privacy/privacy1-rpass.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub mod test2 { + // This used to generate an ICE (make sure that default functions are + // parented to their trait to find the first private thing as the trait). + + struct B; + trait A { fn foo(&self) {} } + impl A for B {} + + mod tests { + use super::A; + fn foo() { + let a = super::B; + a.foo(); + } + } +} + + +pub fn main() {} diff --git a/tests/ui/privacy/privacy1.rs b/tests/ui/privacy/privacy1.rs new file mode 100644 index 000000000..3c9fa983d --- /dev/null +++ b/tests/ui/privacy/privacy1.rs @@ -0,0 +1,176 @@ +#![feature(lang_items, start, no_core)] +#![no_core] // makes debugging this test *a lot* easier (during resolve) + +#[lang="sized"] +pub trait Sized {} + +#[lang="copy"] +pub trait Copy {} + +#[lang="deref"] +pub trait Deref { + type Target; +} + +#[lang="receiver"] +pub trait Receiver: Deref {} + +impl<'a, T> Deref for &'a T { + type Target = T; +} + +impl<'a, T> Receiver for &'a T {} + +mod bar { + // shouldn't bring in too much + pub use self::glob::*; + + // can't publicly re-export private items + pub use self::baz::{foo, bar}; + + pub struct A; + impl A { + pub fn foo() {} + fn bar() {} + + pub fn foo2(&self) {} + fn bar2(&self) {} + } + + trait B { + fn foo() -> Self; + } + + impl B for isize { fn foo() -> isize { 3 } } + + pub enum Enum { + Pub + } + + mod baz { + pub struct A; + impl A { + pub fn foo() {} + fn bar() {} + + pub fn foo2(&self) {} + fn bar2(&self) {} + } + + pub fn foo() {} + pub fn bar() {} + } + + extern "C" { + fn epriv(); + pub fn epub(); + } + + fn test() { + self::Enum::Pub; + unsafe { + epriv(); + epub(); + } + self::baz::A; + self::baz::A::foo(); + self::baz::A::bar(); //~ ERROR: associated function `bar` is private + self::baz::A.foo2(); + + // this used to cause an ICE in privacy traversal. + super::gpub(); + } + + mod glob { + pub fn gpub() {} + fn gpriv() {} + } +} + +pub fn gpub() {} + +fn lol() { + bar::A; + bar::A::foo(); + bar::A::bar(); //~ ERROR: associated function `bar` is private + bar::A.foo2(); +} + +mod foo { + fn test() { + ::bar::A::foo(); + ::bar::A::bar(); //~ ERROR: associated function `bar` is private + ::bar::A.foo2(); + ::bar::baz::A::foo(); //~ ERROR: module `baz` is private + ::bar::baz::A::bar(); //~ ERROR: module `baz` is private + //~^ ERROR: associated function `bar` is private + ::bar::baz::A.foo2(); //~ ERROR: module `baz` is private + ::bar::baz::A.bar2(); //~ ERROR: module `baz` is private + //~^ ERROR: associated function `bar2` is private + + let _: isize = + ::bar::B::foo(); //~ ERROR: trait `B` is private + ::lol(); + + ::bar::Enum::Pub; + + unsafe { + ::bar::epriv(); //~ ERROR: function `epriv` is private + ::bar::epub(); + } + + ::bar::foo(); + ::bar::bar(); + + ::bar::gpub(); + + ::bar::baz::foo(); //~ ERROR: module `baz` is private + ::bar::baz::bar(); //~ ERROR: module `baz` is private + } + + fn test2() { + use bar::baz::{foo, bar}; + //~^ ERROR: module `baz` is private + //~| ERROR: module `baz` is private + + foo(); + bar(); + } + + fn test3() { + use bar::baz; + //~^ ERROR: module `baz` is private + } + + fn test4() { + use bar::{foo, bar}; + foo(); + bar(); + } + + fn test5() { + use bar; + bar::foo(); + bar::bar(); + } + + impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } } + //~^ ERROR: trait `B` is private +} + +pub mod mytest { + // Even though the inner `A` struct is a publicly exported item (usable from + // external crates through `foo::foo`, it should not be accessible through + // its definition path (which has the private `i` module). + use self::foo::i::A; //~ ERROR: module `i` is private + + pub mod foo { + pub use self::i::A as foo; + + mod i { + pub struct A; + } + } +} + +#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr new file mode 100644 index 000000000..70e6fcb7a --- /dev/null +++ b/tests/ui/privacy/privacy1.stderr @@ -0,0 +1,205 @@ +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:132:18 + | +LL | use bar::baz::{foo, bar}; + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:132:18 + | +LL | use bar::baz::{foo, bar}; + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:141:18 + | +LL | use bar::baz; + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `i` is private + --> $DIR/privacy1.rs:165:20 + | +LL | use self::foo::i::A; + | ^ private module + | +note: the module `i` is defined here + --> $DIR/privacy1.rs:170:9 + | +LL | mod i { + | ^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:104:16 + | +LL | ::bar::baz::A::foo(); + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:105:16 + | +LL | ::bar::baz::A::bar(); + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:107:16 + | +LL | ::bar::baz::A.foo2(); + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:108:16 + | +LL | ::bar::baz::A.bar2(); + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: trait `B` is private + --> $DIR/privacy1.rs:112:16 + | +LL | ::bar::B::foo(); + | ^ private trait + | +note: the trait `B` is defined here + --> $DIR/privacy1.rs:40:5 + | +LL | trait B { + | ^^^^^^^ + +error[E0603]: function `epriv` is private + --> $DIR/privacy1.rs:118:20 + | +LL | ::bar::epriv(); + | ^^^^^ private function + | +note: the function `epriv` is defined here + --> $DIR/privacy1.rs:65:9 + | +LL | fn epriv(); + | ^^^^^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:127:16 + | +LL | ::bar::baz::foo(); + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:128:16 + | +LL | ::bar::baz::bar(); + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:50:5 + | +LL | mod baz { + | ^^^^^^^ + +error[E0603]: trait `B` is private + --> $DIR/privacy1.rs:157:17 + | +LL | impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } } + | ^ private trait + | +note: the trait `B` is defined here + --> $DIR/privacy1.rs:40:5 + | +LL | trait B { + | ^^^^^^^ + +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:77:23 + | +LL | fn bar() {} + | -------- private associated function defined here +... +LL | self::baz::A::bar(); + | ^^^ private associated function + +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:95:13 + | +LL | fn bar() {} + | -------- private associated function defined here +... +LL | bar::A::bar(); + | ^^^ private associated function + +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:102:19 + | +LL | fn bar() {} + | -------- private associated function defined here +... +LL | ::bar::A::bar(); + | ^^^ private associated function + +error[E0624]: associated function `bar` is private + --> $DIR/privacy1.rs:105:24 + | +LL | fn bar() {} + | -------- private associated function defined here +... +LL | ::bar::baz::A::bar(); + | ^^^ private associated function + +error[E0624]: associated function `bar2` is private + --> $DIR/privacy1.rs:108:23 + | +LL | fn bar2(&self) {} + | -------------- private associated function defined here +... +LL | ::bar::baz::A.bar2(); + | ^^^^ private associated function + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0603, E0624. +For more information about an error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/privacy2.rs b/tests/ui/privacy/privacy2.rs new file mode 100644 index 000000000..c8fa436bd --- /dev/null +++ b/tests/ui/privacy/privacy2.rs @@ -0,0 +1,27 @@ +#![feature(start, no_core)] +#![no_core] // makes debugging this test *a lot* easier (during resolve) + +// Test to make sure that globs don't leak in regular `use` statements. + +mod bar { + pub use self::glob::*; + + pub mod glob { + use foo; + } +} + +pub fn foo() {} + +fn test1() { + use bar::foo; + //~^ ERROR unresolved import `bar::foo` [E0432] + //~| no `foo` in `bar` +} + +fn test2() { + use bar::glob::foo; + //~^ ERROR `foo` is private +} + +#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } diff --git a/tests/ui/privacy/privacy2.stderr b/tests/ui/privacy/privacy2.stderr new file mode 100644 index 000000000..882f31465 --- /dev/null +++ b/tests/ui/privacy/privacy2.stderr @@ -0,0 +1,35 @@ +error[E0432]: unresolved import `bar::foo` + --> $DIR/privacy2.rs:17:9 + | +LL | use bar::foo; + | ^^^^^^^^ no `foo` in `bar` + +error[E0603]: function import `foo` is private + --> $DIR/privacy2.rs:23:20 + | +LL | use bar::glob::foo; + | ^^^ private function import + | +note: the function import `foo` is defined here... + --> $DIR/privacy2.rs:10:13 + | +LL | use foo; + | ^^^ +note: ...and refers to the function `foo` which is defined here + --> $DIR/privacy2.rs:14:1 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ consider importing it directly + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0432, E0603. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/privacy/privacy3.rs b/tests/ui/privacy/privacy3.rs new file mode 100644 index 000000000..5a7cd76a9 --- /dev/null +++ b/tests/ui/privacy/privacy3.rs @@ -0,0 +1,27 @@ +#![feature(start, no_core)] +#![no_core] // makes debugging this test *a lot* easier (during resolve) + +// Test to make sure that private items imported through globs remain private +// when they're used. + +mod bar { + pub use self::glob::*; + + mod glob { + fn gpriv() {} + } +} + +pub fn foo() {} + +fn test1() { + use bar::gpriv; + //~^ ERROR unresolved import `bar::gpriv` [E0432] + //~| no `gpriv` in `bar` + + // This should pass because the compiler will insert a fake name binding + // for `gpriv` + gpriv(); +} + +#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } diff --git a/tests/ui/privacy/privacy3.stderr b/tests/ui/privacy/privacy3.stderr new file mode 100644 index 000000000..42ce456d9 --- /dev/null +++ b/tests/ui/privacy/privacy3.stderr @@ -0,0 +1,17 @@ +error[E0432]: unresolved import `bar::gpriv` + --> $DIR/privacy3.rs:18:9 + | +LL | use bar::gpriv; + | ^^^^^^^^^^ no `gpriv` in `bar` + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/privacy/privacy4.rs b/tests/ui/privacy/privacy4.rs new file mode 100644 index 000000000..fa257b800 --- /dev/null +++ b/tests/ui/privacy/privacy4.rs @@ -0,0 +1,25 @@ +#![feature(lang_items, start, no_core)] +#![no_core] // makes debugging this test *a lot* easier (during resolve) + +#[lang = "sized"] pub trait Sized {} +#[lang="copy"] pub trait Copy {} + +// Test to make sure that private items imported through globs remain private +// when they're used. + +mod bar { + pub use self::glob::*; + + mod glob { + fn gpriv() {} + } +} + +pub fn foo() {} + +fn test2() { + use bar::glob::gpriv; //~ ERROR: module `glob` is private + gpriv(); +} + +#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } diff --git a/tests/ui/privacy/privacy4.stderr b/tests/ui/privacy/privacy4.stderr new file mode 100644 index 000000000..7552fa71a --- /dev/null +++ b/tests/ui/privacy/privacy4.stderr @@ -0,0 +1,15 @@ +error[E0603]: module `glob` is private + --> $DIR/privacy4.rs:21:14 + | +LL | use bar::glob::gpriv; + | ^^^^ private module + | +note: the module `glob` is defined here + --> $DIR/privacy4.rs:13:5 + | +LL | mod glob { + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/privacy5.rs b/tests/ui/privacy/privacy5.rs new file mode 100644 index 000000000..3dc26b195 --- /dev/null +++ b/tests/ui/privacy/privacy5.rs @@ -0,0 +1,128 @@ +// aux-build:privacy_tuple_struct.rs + +extern crate privacy_tuple_struct as other; + +mod a { + pub struct A(()); + pub struct B(isize); + pub struct C(pub isize, isize); + pub struct D(pub isize); + + fn test() { + let a = A(()); + let b = B(2); + let c = C(2, 3); + let d = D(4); + + let A(()) = a; + let A(_) = a; + match a { A(()) => {} } + match a { A(_) => {} } + + let B(_) = b; + let B(_b) = b; + match b { B(_) => {} } + match b { B(_b) => {} } + match b { B(1) => {} B(_) => {} } + + let C(_, _) = c; + let C(_a, _) = c; + let C(_, _b) = c; + let C(_a, _b) = c; + match c { C(_, _) => {} } + match c { C(_a, _) => {} } + match c { C(_, _b) => {} } + match c { C(_a, _b) => {} } + + let D(_) = d; + let D(_d) = d; + match d { D(_) => {} } + match d { D(_d) => {} } + match d { D(1) => {} D(_) => {} } + + let a2 = A; + let b2 = B; + let c2 = C; + let d2 = D; + } +} + +fn this_crate() { + let a = a::A(()); //~ ERROR tuple struct constructor `A` is private + let b = a::B(2); //~ ERROR tuple struct constructor `B` is private + let c = a::C(2, 3); //~ ERROR tuple struct constructor `C` is private + let d = a::D(4); + + let a::A(()) = a; //~ ERROR tuple struct constructor `A` is private + let a::A(_) = a; //~ ERROR tuple struct constructor `A` is private + match a { a::A(()) => {} } //~ ERROR tuple struct constructor `A` is private + match a { a::A(_) => {} } //~ ERROR tuple struct constructor `A` is private + + let a::B(_) = b; //~ ERROR tuple struct constructor `B` is private + let a::B(_b) = b; //~ ERROR tuple struct constructor `B` is private + match b { a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + match b { a::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private + match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + //~^ ERROR tuple struct constructor `B` is private + + let a::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private + let a::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private + let a::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private + let a::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private + match c { a::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { a::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { a::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private + match c { a::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private + + let a::D(_) = d; + let a::D(_d) = d; + match d { a::D(_) => {} } + match d { a::D(_d) => {} } + match d { a::D(1) => {} a::D(_) => {} } + + let a2 = a::A; //~ ERROR tuple struct constructor `A` is private + let b2 = a::B; //~ ERROR tuple struct constructor `B` is private + let c2 = a::C; //~ ERROR tuple struct constructor `C` is private + let d2 = a::D; +} + +fn xcrate() { + let a = other::A(()); //~ ERROR tuple struct constructor `A` is private + let b = other::B(2); //~ ERROR tuple struct constructor `B` is private + let c = other::C(2, 3); //~ ERROR tuple struct constructor `C` is private + let d = other::D(4); + + let other::A(()) = a; //~ ERROR tuple struct constructor `A` is private + let other::A(_) = a; //~ ERROR tuple struct constructor `A` is private + match a { other::A(()) => {} } //~ ERROR tuple struct constructor `A` is private + match a { other::A(_) => {} } //~ ERROR tuple struct constructor `A` is private + + let other::B(_) = b; //~ ERROR tuple struct constructor `B` is private + let other::B(_b) = b; //~ ERROR tuple struct constructor `B` is private + match b { other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + match b { other::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private + match b { other::B(1) => {}//~ ERROR tuple struct constructor `B` is private + other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + + let other::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private + let other::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private + let other::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private + let other::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private + match c { other::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { other::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { other::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private + match c { other::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private + + let other::D(_) = d; + let other::D(_d) = d; + match d { other::D(_) => {} } + match d { other::D(_d) => {} } + match d { other::D(1) => {} other::D(_) => {} } + + let a2 = other::A; //~ ERROR tuple struct constructor `A` is private + let b2 = other::B; //~ ERROR tuple struct constructor `B` is private + let c2 = other::C; //~ ERROR tuple struct constructor `C` is private + let d2 = other::D; +} + +fn main() {} diff --git a/tests/ui/privacy/privacy5.stderr b/tests/ui/privacy/privacy5.stderr new file mode 100644 index 000000000..615b0af27 --- /dev/null +++ b/tests/ui/privacy/privacy5.stderr @@ -0,0 +1,867 @@ +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:51:16 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private +... +LL | let a = a::A(()); + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/privacy5.rs:6:5 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub ()); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:52:16 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | let b = a::B(2); + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:53:16 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | let c = a::C(2, 3); + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:56:12 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private +... +LL | let a::A(()) = a; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/privacy5.rs:6:5 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub ()); + | +++ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:57:12 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private +... +LL | let a::A(_) = a; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/privacy5.rs:6:5 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub ()); + | +++ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:58:18 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private +... +LL | match a { a::A(()) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/privacy5.rs:6:5 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub ()); + | +++ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:59:18 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private +... +LL | match a { a::A(_) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/privacy5.rs:6:5 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub ()); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:61:12 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | let a::B(_) = b; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:62:12 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | let a::B(_b) = b; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:63:18 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | match b { a::B(_) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:64:18 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | match b { a::B(_b) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:65:18 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | match b { a::B(1) => {} a::B(_) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:65:32 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | match b { a::B(1) => {} a::B(_) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:68:12 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | let a::C(_, _) = c; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:69:12 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | let a::C(_a, _) = c; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:70:12 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | let a::C(_, _b) = c; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:71:12 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | let a::C(_a, _b) = c; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:72:18 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | match c { a::C(_, _) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:73:18 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | match c { a::C(_a, _) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:74:18 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | match c { a::C(_, _b) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:75:18 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | match c { a::C(_a, _b) => {} } + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:83:17 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private +... +LL | let a2 = a::A; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/privacy5.rs:6:5 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub ()); + | +++ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:84:17 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private +... +LL | let b2 = a::B; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `B` is defined here + --> $DIR/privacy5.rs:7:5 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct B(pub isize); + | +++ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:85:17 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private +... +LL | let c2 = a::C; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `C` is defined here + --> $DIR/privacy5.rs:8:5 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the fields publicly accessible + | +LL | pub struct C(pub isize, pub isize); + | ~~~ +++ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:90:20 + | +LL | let a = other::A(()); + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `A` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:91:20 + | +LL | let b = other::B(2); + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:92:20 + | +LL | let c = other::C(2, 3); + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:95:16 + | +LL | let other::A(()) = a; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `A` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:96:16 + | +LL | let other::A(_) = a; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `A` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:97:22 + | +LL | match a { other::A(()) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `A` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:98:22 + | +LL | match a { other::A(_) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `A` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:100:16 + | +LL | let other::B(_) = b; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:101:16 + | +LL | let other::B(_b) = b; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:102:22 + | +LL | match b { other::B(_) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:103:22 + | +LL | match b { other::B(_b) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:104:22 + | +LL | match b { other::B(1) => {} + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:105:16 + | +LL | other::B(_) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:107:16 + | +LL | let other::C(_, _) = c; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:108:16 + | +LL | let other::C(_a, _) = c; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:109:16 + | +LL | let other::C(_, _b) = c; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:110:16 + | +LL | let other::C(_a, _b) = c; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:111:22 + | +LL | match c { other::C(_, _) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:112:22 + | +LL | match c { other::C(_a, _) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:113:22 + | +LL | match c { other::C(_, _b) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:114:22 + | +LL | match c { other::C(_a, _b) => {} } + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `A` is private + --> $DIR/privacy5.rs:122:21 + | +LL | let a2 = other::A; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 + | +LL | pub struct A(()); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `A` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1 + | +LL | pub struct A(()); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:123:21 + | +LL | let b2 = other::B; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 + | +LL | pub struct B(isize); + | ----- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `B` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1 + | +LL | pub struct B(isize); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `C` is private + --> $DIR/privacy5.rs:124:21 + | +LL | let c2 = other::C; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 + | +LL | pub struct C(pub isize, isize); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `C` is defined here + --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1 + | +LL | pub struct C(pub isize, isize); + | ^^^^^^^^^^^^ + +error: aborting due to 48 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/private-class-field.rs b/tests/ui/privacy/private-class-field.rs new file mode 100644 index 000000000..98e32ee07 --- /dev/null +++ b/tests/ui/privacy/private-class-field.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +struct cat { + meows : usize, + + how_hungry : isize, +} + +impl cat { + pub fn meow_count(&mut self) -> usize { self.meows } +} + +fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } +} + +pub fn main() { + let mut nyan : cat = cat(52, 99); + assert_eq!(nyan.meow_count(), 52); +} diff --git a/tests/ui/privacy/private-field-ty-err.rs b/tests/ui/privacy/private-field-ty-err.rs new file mode 100644 index 000000000..10db60695 --- /dev/null +++ b/tests/ui/privacy/private-field-ty-err.rs @@ -0,0 +1,20 @@ +fn main() { + let x = foo::Foo::default(); + if x.len { + //~^ ERROR field `len` of struct `Foo` is private + println!("foo"); + } +} + +mod foo { + #[derive(Default)] + pub struct Foo { + len: String, + } + + impl Foo { + pub fn len(&self) -> usize { + 42 + } + } +} diff --git a/tests/ui/privacy/private-field-ty-err.stderr b/tests/ui/privacy/private-field-ty-err.stderr new file mode 100644 index 000000000..98ba7856e --- /dev/null +++ b/tests/ui/privacy/private-field-ty-err.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `len` of struct `Foo` is private + --> $DIR/private-field-ty-err.rs:3:10 + | +LL | if x.len { + | ^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/private-impl-method.rs b/tests/ui/privacy/private-impl-method.rs new file mode 100644 index 000000000..f7be6726c --- /dev/null +++ b/tests/ui/privacy/private-impl-method.rs @@ -0,0 +1,21 @@ +mod a { + pub struct Foo { + pub x: isize + } + + impl Foo { + fn foo(&self) {} + } +} + +fn f() { + impl a::Foo { + fn bar(&self) {} // This should be visible outside `f` + } +} + +fn main() { + let s = a::Foo { x: 1 }; + s.bar(); + s.foo(); //~ ERROR associated function `foo` is private +} diff --git a/tests/ui/privacy/private-impl-method.stderr b/tests/ui/privacy/private-impl-method.stderr new file mode 100644 index 000000000..bb54dce7e --- /dev/null +++ b/tests/ui/privacy/private-impl-method.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `foo` is private + --> $DIR/private-impl-method.rs:20:7 + | +LL | fn foo(&self) {} + | ------------- private associated function defined here +... +LL | s.foo(); + | ^^^ private associated function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-in-public-assoc-ty.rs b/tests/ui/privacy/private-in-public-assoc-ty.rs new file mode 100644 index 000000000..fba72c131 --- /dev/null +++ b/tests/ui/privacy/private-in-public-assoc-ty.rs @@ -0,0 +1,52 @@ +// Private types and traits are not allowed in interfaces of associated types. +// This test also ensures that the checks are performed even inside private modules. + +#![feature(associated_type_defaults)] +#![feature(type_alias_impl_trait)] + +mod m { + struct Priv; + trait PrivTr {} + impl PrivTr for Priv {} + pub trait PubTrAux1 {} + pub trait PubTrAux2 { + type A; + } + impl PubTrAux1 for u8 {} + impl PubTrAux2 for u8 { + type A = Priv; + //~^ ERROR private type `Priv` in public interface + } + + // "Private-in-public in associated types is hard error" in RFC 2145 + // applies only to the aliased types, not bounds. + pub trait PubTr { + type Alias1: PrivTr; + //~^ WARN private trait `PrivTr` in public interface + //~| WARN this was previously accepted + type Alias2: PubTrAux1 = u8; + //~^ WARN private type `Priv` in public interface + //~| WARN this was previously accepted + type Alias3: PubTrAux2 = u8; + //~^ WARN private type `Priv` in public interface + //~| WARN this was previously accepted + + type Alias4 = Priv; + //~^ ERROR private type `Priv` in public interface + + type Exist; + fn infer_exist() -> Self::Exist; + } + impl PubTr for u8 { + type Alias1 = Priv; + //~^ ERROR private type `Priv` in public interface + + type Exist = impl PrivTr; + //~^ ERROR private trait `PrivTr` in public interface + fn infer_exist() -> Self::Exist { + Priv + } + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-assoc-ty.stderr b/tests/ui/privacy/private-in-public-assoc-ty.stderr new file mode 100644 index 000000000..a59027d81 --- /dev/null +++ b/tests/ui/privacy/private-in-public-assoc-ty.stderr @@ -0,0 +1,68 @@ +error[E0446]: private type `Priv` in public interface + --> $DIR/private-in-public-assoc-ty.rs:17:9 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A = Priv; + | ^^^^^^ can't leak private type + +warning: private trait `PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-assoc-ty.rs:24:9 + | +LL | type Alias1: PrivTr; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + = note: `#[warn(private_in_public)]` on by default + +warning: private type `Priv` in public interface (error E0446) + --> $DIR/private-in-public-assoc-ty.rs:27:9 + | +LL | type Alias2: PubTrAux1 = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +warning: private type `Priv` in public interface (error E0446) + --> $DIR/private-in-public-assoc-ty.rs:30:9 + | +LL | type Alias3: PubTrAux2 = u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `Priv` in public interface + --> $DIR/private-in-public-assoc-ty.rs:34:9 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type Alias4 = Priv; + | ^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv` in public interface + --> $DIR/private-in-public-assoc-ty.rs:41:9 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type Alias1 = Priv; + | ^^^^^^^^^^^ can't leak private type + +error[E0445]: private trait `PrivTr` in public interface + --> $DIR/private-in-public-assoc-ty.rs:44:9 + | +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private +... +LL | type Exist = impl PrivTr; + | ^^^^^^^^^^ can't leak private trait + +error: aborting due to 4 previous errors; 3 warnings emitted + +Some errors have detailed explanations: E0445, E0446. +For more information about an error, try `rustc --explain E0445`. diff --git a/tests/ui/privacy/private-in-public-expr-pat.rs b/tests/ui/privacy/private-in-public-expr-pat.rs new file mode 100644 index 000000000..5c9ecd13b --- /dev/null +++ b/tests/ui/privacy/private-in-public-expr-pat.rs @@ -0,0 +1,13 @@ +// Patterns and expressions are not interface parts and don't produce private-in-public errors. + +// build-pass (FIXME(62277): could be check-pass?) + +struct Priv1(usize); +struct Priv2; + +pub struct Pub(Priv2); + +pub fn public_expr(_: [u8; Priv1(0).0]) {} // OK +pub fn public_pat(Pub(Priv2): Pub) {} // OK + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-ill-formed.rs b/tests/ui/privacy/private-in-public-ill-formed.rs new file mode 100644 index 000000000..031e2874a --- /dev/null +++ b/tests/ui/privacy/private-in-public-ill-formed.rs @@ -0,0 +1,37 @@ +mod aliases_pub { + struct Priv; + mod m { + pub struct Pub3; + } + + trait PrivTr { + type AssocAlias; + } + impl PrivTr for Priv { + type AssocAlias = m::Pub3; + } + + impl ::AssocAlias { + //~^ ERROR no nominal type found for inherent implementation + pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface + } +} + +mod aliases_priv { + struct Priv; + struct Priv3; + + trait PrivTr { + type AssocAlias; + } + impl PrivTr for Priv { + type AssocAlias = Priv3; + } + + impl ::AssocAlias { + //~^ ERROR no nominal type found for inherent implementation + pub fn f(arg: Priv) {} // OK + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-ill-formed.stderr b/tests/ui/privacy/private-in-public-ill-formed.stderr new file mode 100644 index 000000000..e7c94bc30 --- /dev/null +++ b/tests/ui/privacy/private-in-public-ill-formed.stderr @@ -0,0 +1,19 @@ +error[E0118]: no nominal type found for inherent implementation + --> $DIR/private-in-public-ill-formed.rs:14:10 + | +LL | impl ::AssocAlias { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + +error[E0118]: no nominal type found for inherent implementation + --> $DIR/private-in-public-ill-formed.rs:31:10 + | +LL | impl ::AssocAlias { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type + | + = note: either implement a trait on it or create a newtype to wrap it instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0118`. diff --git a/tests/ui/privacy/private-in-public-lint.rs b/tests/ui/privacy/private-in-public-lint.rs new file mode 100644 index 000000000..8b6e43601 --- /dev/null +++ b/tests/ui/privacy/private-in-public-lint.rs @@ -0,0 +1,19 @@ +mod m1 { + pub struct Pub; + struct Priv; + + impl Pub { + pub fn f() -> Priv {Priv} //~ ERROR private type `m1::Priv` in public interface + } +} + +mod m2 { + pub struct Pub; + struct Priv; + + impl Pub { + pub fn f() -> Priv {Priv} //~ ERROR private type `m2::Priv` in public interface + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-lint.stderr b/tests/ui/privacy/private-in-public-lint.stderr new file mode 100644 index 000000000..1e98e3bed --- /dev/null +++ b/tests/ui/privacy/private-in-public-lint.stderr @@ -0,0 +1,21 @@ +error[E0446]: private type `m1::Priv` in public interface + --> $DIR/private-in-public-lint.rs:6:9 + | +LL | struct Priv; + | ----------- `m1::Priv` declared as private +... +LL | pub fn f() -> Priv {Priv} + | ^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `m2::Priv` in public interface + --> $DIR/private-in-public-lint.rs:15:9 + | +LL | struct Priv; + | ----------- `m2::Priv` declared as private +... +LL | pub fn f() -> Priv {Priv} + | ^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/private-in-public-non-principal-2.rs b/tests/ui/privacy/private-in-public-non-principal-2.rs new file mode 100644 index 000000000..db451d334 --- /dev/null +++ b/tests/ui/privacy/private-in-public-non-principal-2.rs @@ -0,0 +1,14 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +#[allow(private_in_public)] +mod m { + pub trait PubPrincipal {} + auto trait PrivNonPrincipal {} + pub fn leak_dyn_nonprincipal() -> Box { loop {} } +} + +fn main() { + m::leak_dyn_nonprincipal(); + //~^ ERROR trait `PrivNonPrincipal` is private +} diff --git a/tests/ui/privacy/private-in-public-non-principal-2.stderr b/tests/ui/privacy/private-in-public-non-principal-2.stderr new file mode 100644 index 000000000..7cc8bf0de --- /dev/null +++ b/tests/ui/privacy/private-in-public-non-principal-2.stderr @@ -0,0 +1,8 @@ +error: trait `PrivNonPrincipal` is private + --> $DIR/private-in-public-non-principal-2.rs:12:5 + | +LL | m::leak_dyn_nonprincipal(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait + +error: aborting due to previous error + diff --git a/tests/ui/privacy/private-in-public-non-principal.rs b/tests/ui/privacy/private-in-public-non-principal.rs new file mode 100644 index 000000000..ac1d5a9e6 --- /dev/null +++ b/tests/ui/privacy/private-in-public-non-principal.rs @@ -0,0 +1,21 @@ +#![feature(auto_traits)] +#![feature(negative_impls)] + +pub trait PubPrincipal {} +auto trait PrivNonPrincipal {} + +pub fn leak_dyn_nonprincipal() -> Box { loop {} } +//~^ WARN private trait `PrivNonPrincipal` in public interface +//~| WARN this was previously accepted + +#[deny(missing_docs)] +fn container() { + impl dyn PubPrincipal { + pub fn check_doc_lint() {} //~ ERROR missing documentation for an associated function + } + impl dyn PubPrincipal + PrivNonPrincipal { + pub fn check_doc_lint() {} // OK, no missing doc lint + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-non-principal.stderr b/tests/ui/privacy/private-in-public-non-principal.stderr new file mode 100644 index 000000000..de20cada4 --- /dev/null +++ b/tests/ui/privacy/private-in-public-non-principal.stderr @@ -0,0 +1,24 @@ +warning: private trait `PrivNonPrincipal` in public interface (error E0445) + --> $DIR/private-in-public-non-principal.rs:7:1 + | +LL | pub fn leak_dyn_nonprincipal() -> Box { loop {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + = note: `#[warn(private_in_public)]` on by default + +error: missing documentation for an associated function + --> $DIR/private-in-public-non-principal.rs:14:9 + | +LL | pub fn check_doc_lint() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/private-in-public-non-principal.rs:11:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs b/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs new file mode 100644 index 000000000..c7df31529 --- /dev/null +++ b/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs @@ -0,0 +1,27 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(type_alias_impl_trait)] +#![deny(private_in_public)] + +pub type Pub = impl Default; + +#[derive(Default)] +struct Priv; + +fn check() -> Pub { + Priv +} + +pub trait Trait { + type Pub: Default; + fn method() -> Self::Pub; +} + +impl Trait for u8 { + type Pub = impl Default; + fn method() -> Self::Pub { + Priv + } +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs new file mode 100644 index 000000000..0fa1de975 --- /dev/null +++ b/tests/ui/privacy/private-in-public-warn.rs @@ -0,0 +1,280 @@ +// Private types and traits are not allowed in public interfaces. +// This test also ensures that the checks are performed even inside private modules. + +#![feature(associated_type_defaults)] +#![deny(private_in_public)] +#![allow(improper_ctypes)] + +mod types { + struct Priv; + pub struct Pub; + pub trait PubTr { + type Alias; + } + + pub type Alias = Priv; //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + pub enum E { + V1(Priv), //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + V2 { field: Priv }, //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + } + pub trait Tr { + const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + type Alias = Priv; //~ ERROR private type `types::Priv` in public interface + fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + } + extern "C" { + pub static ES: Priv; //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + pub fn ef1(arg: Priv); //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + pub fn ef2() -> Priv; //~ ERROR private type `types::Priv` in public interface + //~^ WARNING hard error + } + impl PubTr for Pub { + type Alias = Priv; //~ ERROR private type `types::Priv` in public interface + } +} + +mod traits { + trait PrivTr {} + pub struct Pub(T); + pub trait PubTr {} + + pub type Alias = T; //~ ERROR private trait `traits::PrivTr` in public interface + //~| WARNING hard error + //~| WARNING bounds on generic parameters are not enforced in type aliases + pub trait Tr1: PrivTr {} //~ ERROR private trait `traits::PrivTr` in public interface + //~^ WARNING hard error + pub trait Tr2 {} //~ ERROR private trait `traits::PrivTr` in public interface + //~^ WARNING hard error + pub trait Tr3 { + type Alias: PrivTr; + //~^ ERROR private trait `traits::PrivTr` in public interface + //~| WARNING hard error + fn f(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface + //~^ WARNING hard error + } + impl Pub {} //~ ERROR private trait `traits::PrivTr` in public interface + //~^ WARNING hard error + impl PubTr for Pub {} // OK, trait impl predicates +} + +mod traits_where { + trait PrivTr {} + pub struct Pub(T); + pub trait PubTr {} + + pub type Alias where T: PrivTr = T; + //~^ ERROR private trait `traits_where::PrivTr` in public interface + //~| WARNING hard error + //~| WARNING where clauses are not enforced in type aliases + pub trait Tr2 where T: PrivTr {} + //~^ ERROR private trait `traits_where::PrivTr` in public interface + //~| WARNING hard error + pub trait Tr3 { + fn f(arg: T) where T: PrivTr {} + //~^ ERROR private trait `traits_where::PrivTr` in public interface + //~| WARNING hard error + } + impl Pub where T: PrivTr {} + //~^ ERROR private trait `traits_where::PrivTr` in public interface + //~| WARNING hard error + impl PubTr for Pub where T: PrivTr {} // OK, trait impl predicates +} + +mod generics { + struct Priv(T); + pub struct Pub(T); + trait PrivTr {} + pub trait PubTr {} + + pub trait Tr1: PrivTr {} + //~^ ERROR private trait `generics::PrivTr` in public interface + //~| WARNING hard error + pub trait Tr2: PubTr {} //~ ERROR private type `generics::Priv` in public interface + //~^ WARNING hard error + pub trait Tr3: PubTr<[Priv; 1]> {} //~ ERROR private type `generics::Priv` in public interface + //~^ WARNING hard error + pub trait Tr4: PubTr> {} //~ ERROR private type `generics::Priv` in public interface + //~^ WARNING hard error +} + +mod impls { + struct Priv; + pub struct Pub; + trait PrivTr { + type Alias; + } + pub trait PubTr { + type Alias; + } + + impl Priv { + pub fn f(arg: Priv) {} // OK + } + impl PrivTr for Priv { + type Alias = Priv; // OK + } + impl PubTr for Priv { + type Alias = Priv; // OK + } + impl PrivTr for Pub { + type Alias = Priv; // OK + } + impl PubTr for Pub { + type Alias = Priv; //~ ERROR private type `impls::Priv` in public interface + } +} + +mod impls_generics { + struct Priv(T); + pub struct Pub(T); + trait PrivTr { + type Alias; + } + pub trait PubTr { + type Alias; + } + + impl Priv { + pub fn f(arg: Priv) {} // OK + } + impl Pub { + pub fn f(arg: Priv) {} // OK + } + impl PrivTr for Priv { + type Alias = Priv; // OK + } + impl PubTr for Priv { + type Alias = Priv; // OK + } + impl PubTr for Priv { + type Alias = Priv; // OK + } + impl PubTr for [Priv; 1] { + type Alias = Priv; // OK + } + impl PubTr for Pub { + type Alias = Priv; // OK + } + impl PrivTr for Pub { + type Alias = Priv; // OK + } + impl PubTr for Pub { + type Alias = Priv; // OK + } +} + +mod aliases_pub { + struct Priv; + mod m { + pub struct Pub1; + pub struct Pub2; + pub struct Pub3; + pub trait PubTr { + type Check = u8; + } + } + + use self::m::Pub1 as PrivUseAlias; + use self::m::PubTr as PrivUseAliasTr; + type PrivAlias = m::Pub2; + trait PrivTr { + type AssocAlias; + } + impl PrivTr for Priv { + type AssocAlias = m::Pub3; + } + + pub fn f1(arg: PrivUseAlias) {} // OK + pub fn f2(arg: PrivAlias) {} // OK + + pub trait Tr1: PrivUseAliasTr {} // OK + pub trait Tr2: PrivUseAliasTr {} // OK + + impl PrivAlias { + pub fn f(arg: Priv) {} //~ ERROR private type `aliases_pub::Priv` in public interface + //~^ WARNING hard error + } + impl PrivUseAliasTr for PrivUseAlias { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for PrivAlias { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for ::AssocAlias { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for Option<::AssocAlias> { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for (::AssocAlias, Priv) { + type Check = Priv; // OK + } + impl PrivUseAliasTr for Option<(::AssocAlias, Priv)> { + type Check = Priv; // OK + } +} + +mod aliases_priv { + struct Priv; + + struct Priv1; + struct Priv2; + struct Priv3; + trait PrivTr1 { + type Check = u8; + } + + use self::Priv1 as PrivUseAlias; + use self::PrivTr1 as PrivUseAliasTr; + type PrivAlias = Priv2; + trait PrivTr { + type AssocAlias; + } + impl PrivTr for Priv { + type AssocAlias = Priv3; + } + + pub trait Tr1: PrivUseAliasTr {} + //~^ ERROR private trait `PrivTr1` in public interface + //~| WARNING hard error + pub trait Tr2: PrivUseAliasTr {} + //~^ ERROR private trait `PrivTr1` in public interface + //~| WARNING hard error + //~| ERROR private type `Priv2` in public interface + //~| WARNING hard error + + impl PrivUseAlias { + pub fn f(arg: Priv) {} // OK + } + impl PrivAlias { + pub fn f(arg: Priv) {} // OK + } + impl PrivUseAliasTr for PrivUseAlias { + type Check = Priv; // OK + } + impl PrivUseAliasTr for PrivAlias { + type Check = Priv; // OK + } + impl PrivUseAliasTr for ::AssocAlias { + type Check = Priv; // OK + } +} + +mod aliases_params { + struct Priv; + type PrivAliasGeneric = T; + type Result = ::std::result::Result; + + pub fn f1(arg: PrivAliasGeneric) {} // OK, not an error +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr new file mode 100644 index 000000000..66f91ce6f --- /dev/null +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -0,0 +1,339 @@ +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:15:5 + | +LL | pub type Alias = Priv; + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 +note: the lint level is defined here + --> $DIR/private-in-public-warn.rs:5:9 + | +LL | #![deny(private_in_public)] + | ^^^^^^^^^^^^^^^^^ + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:18:12 + | +LL | V1(Priv), + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:20:14 + | +LL | V2 { field: Priv }, + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:24:9 + | +LL | const C: Priv = Priv; + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public-warn.rs:26:9 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | type Alias = Priv; + | ^^^^^^^^^^ can't leak private type + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:27:9 + | +LL | fn f1(arg: Priv) {} + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:29:9 + | +LL | fn f2() -> Priv { panic!() } + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:33:9 + | +LL | pub static ES: Priv; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:35:9 + | +LL | pub fn ef1(arg: Priv); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `types::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:37:9 + | +LL | pub fn ef2() -> Priv; + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public-warn.rs:41:9 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | type Alias = Priv; + | ^^^^^^^^^^ can't leak private type + +error: private trait `traits::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:50:5 + | +LL | pub type Alias = T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:53:5 + | +LL | pub trait Tr1: PrivTr {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:55:5 + | +LL | pub trait Tr2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:58:9 + | +LL | type Alias: PrivTr; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:61:9 + | +LL | fn f(arg: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:64:5 + | +LL | impl Pub {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits_where::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:74:5 + | +LL | pub type Alias where T: PrivTr = T; + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits_where::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:78:5 + | +LL | pub trait Tr2 where T: PrivTr {} + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits_where::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:82:9 + | +LL | fn f(arg: T) where T: PrivTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `traits_where::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:86:5 + | +LL | impl Pub where T: PrivTr {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `generics::PrivTr` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:98:5 + | +LL | pub trait Tr1: PrivTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `generics::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:101:5 + | +LL | pub trait Tr2: PubTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `generics::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:103:5 + | +LL | pub trait Tr3: PubTr<[Priv; 1]> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `generics::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:105:5 + | +LL | pub trait Tr4: PubTr> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `impls::Priv` in public interface + --> $DIR/private-in-public-warn.rs:132:9 + | +LL | struct Priv; + | ----------- `impls::Priv` declared as private +... +LL | type Alias = Priv; + | ^^^^^^^^^^ can't leak private type + +error: private type `aliases_pub::Priv` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:203:9 + | +LL | pub fn f(arg: Priv) {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:207:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:210:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:213:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:216:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + +error: private trait `PrivTr1` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:246:5 + | +LL | pub trait Tr1: PrivUseAliasTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private trait `PrivTr1` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:249:5 + | +LL | pub trait Tr2: PrivUseAliasTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: private type `Priv2` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:249:5 + | +LL | pub trait Tr2: PrivUseAliasTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/private-in-public-warn.rs:50:23 + | +LL | pub type Alias = T; + | ^^^^^^ + | + = note: `#[warn(type_alias_bounds)]` on by default +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - pub type Alias = T; +LL + pub type Alias = T; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/private-in-public-warn.rs:74:29 + | +LL | pub type Alias where T: PrivTr = T; + | ^^^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - pub type Alias where T: PrivTr = T; +LL + pub type Alias = T; + | + +error: aborting due to 34 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/private-in-public.rs b/tests/ui/privacy/private-in-public.rs new file mode 100644 index 000000000..dbd1c483f --- /dev/null +++ b/tests/ui/privacy/private-in-public.rs @@ -0,0 +1,148 @@ +// Private types and traits are not allowed in public interfaces. +// This test also ensures that the checks are performed even inside private modules. + +#![feature(associated_type_defaults)] + +mod types { + struct Priv; + pub struct Pub; + pub trait PubTr { + type Alias; + } + + pub const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface + pub static S: Priv = Priv; //~ ERROR private type `types::Priv` in public interface + pub fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface + pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface + pub struct S1(pub Priv); //~ ERROR private type `types::Priv` in public interface + pub struct S2 { pub field: Priv } //~ ERROR private type `types::Priv` in public interface + impl Pub { + pub const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface + pub fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface + pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface + } +} + +mod traits { + trait PrivTr {} + pub struct Pub(T); + pub trait PubTr {} + + pub enum E { V(T) } //~ ERROR private trait `traits::PrivTr` in public interface + pub fn f(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface + pub struct S1(T); //~ ERROR private trait `traits::PrivTr` in public interface + impl Pub { //~ ERROR private trait `traits::PrivTr` in public interface + pub fn f(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface + } +} + +mod traits_where { + trait PrivTr {} + pub struct Pub(T); + pub trait PubTr {} + + pub enum E where T: PrivTr { V(T) } + //~^ ERROR private trait `traits_where::PrivTr` in public interface + pub fn f(arg: T) where T: PrivTr {} + //~^ ERROR private trait `traits_where::PrivTr` in public interface + pub struct S1(T) where T: PrivTr; + //~^ ERROR private trait `traits_where::PrivTr` in public interface + impl Pub where T: PrivTr { + //~^ ERROR private trait `traits_where::PrivTr` in public interface + pub fn f(arg: U) where U: PrivTr {} + //~^ ERROR private trait `traits_where::PrivTr` in public interface + } +} + +mod generics { + struct Priv(T); + pub struct Pub(T); + trait PrivTr {} + pub trait PubTr {} + + pub fn f1(arg: [Priv; 1]) {} //~ ERROR private type `generics::Priv` in public interface + pub fn f2(arg: Pub) {} //~ ERROR private type `generics::Priv` in public interface + pub fn f3(arg: Priv) {} + //~^ ERROR private type `generics::Priv` in public interface +} + +mod impls { + struct Priv; + pub struct Pub; + trait PrivTr { + type Alias; + } + pub trait PubTr { + type Alias; + } + + impl Pub { + pub fn f(arg: Priv) {} //~ ERROR private type `impls::Priv` in public interface + } +} + +mod aliases_pub { + struct Priv; + mod m { + pub struct Pub1; + pub struct Pub2; + pub struct Pub3; + pub trait PubTr { + type Check = u8; + } + } + + use self::m::Pub1 as PrivUseAlias; + use self::m::PubTr as PrivUseAliasTr; + type PrivAlias = m::Pub2; + trait PrivTr { + type Assoc = m::Pub3; + } + impl PrivTr for Priv {} + + // This should be OK, but associated type aliases are not substituted yet + pub fn f3(arg: ::Assoc) {} + //~^ ERROR private trait `aliases_pub::PrivTr` in public interface + //~| ERROR private type `aliases_pub::Priv` in public interface + + impl PrivUseAlias { + pub fn f(arg: Priv) {} //~ ERROR private type `aliases_pub::Priv` in public interface + } +} + +mod aliases_priv { + struct Priv; + + struct Priv1; + struct Priv2; + struct Priv3; + trait PrivTr1 { + type Check = u8; + } + + use self::Priv1 as PrivUseAlias; + use self::PrivTr1 as PrivUseAliasTr; + type PrivAlias = Priv2; + trait PrivTr { + type Assoc = Priv3; + } + impl PrivTr for Priv {} + + pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type `Priv1` in public interface + pub fn f2(arg: PrivAlias) {} //~ ERROR private type `Priv2` in public interface + pub fn f3(arg: ::Assoc) {} + //~^ ERROR private trait `aliases_priv::PrivTr` in public interface + //~| ERROR private type `aliases_priv::Priv` in public interface +} + +mod aliases_params { + struct Priv; + type PrivAliasGeneric = T; + type Result = ::std::result::Result; + + pub fn f2(arg: PrivAliasGeneric) {} + //~^ ERROR private type `aliases_params::Priv` in public interface + pub fn f3(arg: Result) {} //~ ERROR private type `aliases_params::Priv` in public interface +} + +fn main() {} diff --git a/tests/ui/privacy/private-in-public.stderr b/tests/ui/privacy/private-in-public.stderr new file mode 100644 index 000000000..887eebf53 --- /dev/null +++ b/tests/ui/privacy/private-in-public.stderr @@ -0,0 +1,292 @@ +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:13:5 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub const C: Priv = Priv; + | ^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:14:5 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub static S: Priv = Priv; + | ^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:15:5 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub fn f1(arg: Priv) {} + | ^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:16:5 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub fn f2() -> Priv { panic!() } + | ^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:17:19 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub struct S1(pub Priv); + | ^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:18:21 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub struct S2 { pub field: Priv } + | ^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:20:9 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub const C: Priv = Priv; + | ^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:21:9 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub fn f1(arg: Priv) {} + | ^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `types::Priv` in public interface + --> $DIR/private-in-public.rs:22:9 + | +LL | struct Priv; + | ----------- `types::Priv` declared as private +... +LL | pub fn f2() -> Priv { panic!() } + | ^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0445]: private trait `traits::PrivTr` in public interface + --> $DIR/private-in-public.rs:31:5 + | +LL | trait PrivTr {} + | ------------ `traits::PrivTr` declared as private +... +LL | pub enum E { V(T) } + | ^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits::PrivTr` in public interface + --> $DIR/private-in-public.rs:32:5 + | +LL | trait PrivTr {} + | ------------ `traits::PrivTr` declared as private +... +LL | pub fn f(arg: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits::PrivTr` in public interface + --> $DIR/private-in-public.rs:33:5 + | +LL | trait PrivTr {} + | ------------ `traits::PrivTr` declared as private +... +LL | pub struct S1(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits::PrivTr` in public interface + --> $DIR/private-in-public.rs:34:5 + | +LL | trait PrivTr {} + | ------------ `traits::PrivTr` declared as private +... +LL | impl Pub { + | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits::PrivTr` in public interface + --> $DIR/private-in-public.rs:35:9 + | +LL | trait PrivTr {} + | ------------ `traits::PrivTr` declared as private +... +LL | pub fn f(arg: U) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits_where::PrivTr` in public interface + --> $DIR/private-in-public.rs:44:5 + | +LL | trait PrivTr {} + | ------------ `traits_where::PrivTr` declared as private +... +LL | pub enum E where T: PrivTr { V(T) } + | ^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits_where::PrivTr` in public interface + --> $DIR/private-in-public.rs:46:5 + | +LL | trait PrivTr {} + | ------------ `traits_where::PrivTr` declared as private +... +LL | pub fn f(arg: T) where T: PrivTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits_where::PrivTr` in public interface + --> $DIR/private-in-public.rs:48:5 + | +LL | trait PrivTr {} + | ------------ `traits_where::PrivTr` declared as private +... +LL | pub struct S1(T) where T: PrivTr; + | ^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits_where::PrivTr` in public interface + --> $DIR/private-in-public.rs:50:5 + | +LL | trait PrivTr {} + | ------------ `traits_where::PrivTr` declared as private +... +LL | impl Pub where T: PrivTr { + | ^^^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `traits_where::PrivTr` in public interface + --> $DIR/private-in-public.rs:52:9 + | +LL | trait PrivTr {} + | ------------ `traits_where::PrivTr` declared as private +... +LL | pub fn f(arg: U) where U: PrivTr {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0446]: private type `generics::Priv` in public interface + --> $DIR/private-in-public.rs:63:5 + | +LL | struct Priv(T); + | ------------------- `generics::Priv` declared as private +... +LL | pub fn f1(arg: [Priv; 1]) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `generics::Priv` in public interface + --> $DIR/private-in-public.rs:64:5 + | +LL | struct Priv(T); + | ------------------- `generics::Priv` declared as private +... +LL | pub fn f2(arg: Pub) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `generics::Priv` in public interface + --> $DIR/private-in-public.rs:65:5 + | +LL | struct Priv(T); + | ------------------- `generics::Priv` declared as private +... +LL | pub fn f3(arg: Priv) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `impls::Priv` in public interface + --> $DIR/private-in-public.rs:80:9 + | +LL | struct Priv; + | ----------- `impls::Priv` declared as private +... +LL | pub fn f(arg: Priv) {} + | ^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0445]: private trait `aliases_pub::PrivTr` in public interface + --> $DIR/private-in-public.rs:104:5 + | +LL | trait PrivTr { + | ------------ `aliases_pub::PrivTr` declared as private +... +LL | pub fn f3(arg: ::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public.rs:104:5 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | pub fn f3(arg: ::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public.rs:109:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | pub fn f(arg: Priv) {} + | ^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv1` in public interface + --> $DIR/private-in-public.rs:131:5 + | +LL | struct Priv1; + | ------------ `Priv1` declared as private +... +LL | pub fn f1(arg: PrivUseAlias) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv2` in public interface + --> $DIR/private-in-public.rs:132:5 + | +LL | struct Priv2; + | ------------ `Priv2` declared as private +... +LL | pub fn f2(arg: PrivAlias) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0445]: private trait `aliases_priv::PrivTr` in public interface + --> $DIR/private-in-public.rs:133:5 + | +LL | trait PrivTr { + | ------------ `aliases_priv::PrivTr` declared as private +... +LL | pub fn f3(arg: ::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error[E0446]: private type `aliases_priv::Priv` in public interface + --> $DIR/private-in-public.rs:133:5 + | +LL | struct Priv; + | ----------- `aliases_priv::Priv` declared as private +... +LL | pub fn f3(arg: ::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_params::Priv` in public interface + --> $DIR/private-in-public.rs:143:5 + | +LL | struct Priv; + | ----------- `aliases_params::Priv` declared as private +... +LL | pub fn f2(arg: PrivAliasGeneric) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_params::Priv` in public interface + --> $DIR/private-in-public.rs:145:5 + | +LL | struct Priv; + | ----------- `aliases_params::Priv` declared as private +... +LL | pub fn f3(arg: Result) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to 32 previous errors + +Some errors have detailed explanations: E0445, E0446. +For more information about an error, try `rustc --explain E0445`. diff --git a/tests/ui/privacy/private-inferred-type-1.rs b/tests/ui/privacy/private-inferred-type-1.rs new file mode 100644 index 000000000..d633189e3 --- /dev/null +++ b/tests/ui/privacy/private-inferred-type-1.rs @@ -0,0 +1,18 @@ +trait Arr0 { + fn arr0_secret(&self); +} +trait TyParam { + fn ty_param_secret(&self); +} + +mod m { + struct Priv; + + impl ::Arr0 for [Priv; 0] { fn arr0_secret(&self) {} } + impl ::TyParam for Option { fn ty_param_secret(&self) {} } +} + +fn main() { + [].arr0_secret(); //~ ERROR type `Priv` is private + None.ty_param_secret(); //~ ERROR type `Priv` is private +} diff --git a/tests/ui/privacy/private-inferred-type-1.stderr b/tests/ui/privacy/private-inferred-type-1.stderr new file mode 100644 index 000000000..245789f43 --- /dev/null +++ b/tests/ui/privacy/private-inferred-type-1.stderr @@ -0,0 +1,14 @@ +error: type `Priv` is private + --> $DIR/private-inferred-type-1.rs:16:5 + | +LL | [].arr0_secret(); + | ^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type-1.rs:17:5 + | +LL | None.ty_param_secret(); + | ^^^^^^^^^^^^^^^^^^^^^^ private type + +error: aborting due to 2 previous errors + diff --git a/tests/ui/privacy/private-inferred-type-2.rs b/tests/ui/privacy/private-inferred-type-2.rs new file mode 100644 index 000000000..15b263b38 --- /dev/null +++ b/tests/ui/privacy/private-inferred-type-2.rs @@ -0,0 +1,19 @@ +// aux-build:private-inferred-type.rs + +extern crate private_inferred_type as ext; + +mod m { + struct Priv; + pub struct Pub(pub T); + + impl Pub { + pub fn get_priv() -> Priv { Priv } + pub fn static_method() {} + } +} + +fn main() { + m::Pub::get_priv; //~ ERROR type `Priv` is private + m::Pub::static_method; //~ ERROR type `Priv` is private + ext::Pub::static_method; //~ ERROR type `ext::Priv` is private +} diff --git a/tests/ui/privacy/private-inferred-type-2.stderr b/tests/ui/privacy/private-inferred-type-2.stderr new file mode 100644 index 000000000..3a0fc03b4 --- /dev/null +++ b/tests/ui/privacy/private-inferred-type-2.stderr @@ -0,0 +1,20 @@ +error: type `Priv` is private + --> $DIR/private-inferred-type-2.rs:16:5 + | +LL | m::Pub::get_priv; + | ^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type-2.rs:17:5 + | +LL | m::Pub::static_method; + | ^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `ext::Priv` is private + --> $DIR/private-inferred-type-2.rs:18:5 + | +LL | ext::Pub::static_method; + | ^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: aborting due to 3 previous errors + diff --git a/tests/ui/privacy/private-inferred-type-3.rs b/tests/ui/privacy/private-inferred-type-3.rs new file mode 100644 index 000000000..cdbdcf60b --- /dev/null +++ b/tests/ui/privacy/private-inferred-type-3.rs @@ -0,0 +1,17 @@ +// aux-build:private-inferred-type.rs + +// error-pattern:type `fn() {ext::priv_fn}` is private +// error-pattern:static `ext::PRIV_STATIC` is private +// error-pattern:type `ext::PrivEnum` is private +// error-pattern:type `fn() {::method}` is private +// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private +// error-pattern:type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private +// error-pattern:type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private + +#![feature(decl_macro)] + +extern crate private_inferred_type as ext; + +fn main() { + ext::m!(); +} diff --git a/tests/ui/privacy/private-inferred-type-3.stderr b/tests/ui/privacy/private-inferred-type-3.stderr new file mode 100644 index 000000000..42faeb4bf --- /dev/null +++ b/tests/ui/privacy/private-inferred-type-3.stderr @@ -0,0 +1,58 @@ +error: type `fn() {ext::priv_fn}` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private type + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: static `ext::PRIV_STATIC` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private static + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `ext::PrivEnum` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private type + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `fn() {::method}` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private type + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private type + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private type + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private + --> $DIR/private-inferred-type-3.rs:16:5 + | +LL | ext::m!(); + | ^^^^^^^^^ private type + | + = note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/tests/ui/privacy/private-inferred-type.rs b/tests/ui/privacy/private-inferred-type.rs new file mode 100644 index 000000000..e8743dd96 --- /dev/null +++ b/tests/ui/privacy/private-inferred-type.rs @@ -0,0 +1,133 @@ +#![feature(decl_macro)] +#![allow(private_in_public)] + +mod m { + fn priv_fn() {} + static PRIV_STATIC: u8 = 0; + enum PrivEnum { Variant } + pub enum PubEnum { Variant } + trait PrivTrait { fn method() {} } + impl PrivTrait for u8 {} + pub trait PubTrait { fn method() {} } + impl PubTrait for u8 {} + struct PrivTupleStruct(u8); + pub struct PubTupleStruct(u8); + impl PubTupleStruct { fn method() {} } + + #[derive(Clone, Copy)] + struct Priv; + pub type Alias = Priv; + pub struct Pub(pub T); + + impl Pub { + pub fn static_method() {} + pub const INHERENT_ASSOC_CONST: u8 = 0; + } + impl Pub { + pub fn static_method_generic_self() {} + pub const INHERENT_ASSOC_CONST_GENERIC_SELF: u8 = 0; + } + impl Pub { + fn priv_method(&self) {} + pub fn method_with_substs(&self) {} + pub fn method_with_priv_params(&self, _: Priv) {} + } + impl TraitWithAssocConst for Priv {} + impl TraitWithAssocTy for Priv { type AssocTy = u8; } + + pub macro m() { + priv_fn; //~ ERROR type `fn() {priv_fn}` is private + PRIV_STATIC; // OK, not cross-crate + PrivEnum::Variant; //~ ERROR type `PrivEnum` is private + PubEnum::Variant; // OK + ::method; //~ ERROR type `fn() {::method}` is private + ::method; // OK + PrivTupleStruct; + //~^ ERROR type `fn(u8) -> PrivTupleStruct {PrivTupleStruct}` is private + PubTupleStruct; + //~^ ERROR type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private + Pub(0u8).priv_method(); + //~^ ERROR type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private + } + + trait Trait {} + pub trait TraitWithTyParam {} + pub trait TraitWithTyParam2 { fn pub_method() {} } + pub trait TraitWithAssocTy { type AssocTy; } + pub trait TraitWithAssocConst { const TRAIT_ASSOC_CONST: u8 = 0; } + impl Trait for u8 {} + impl TraitWithTyParam for u8 {} + impl TraitWithTyParam2 for u8 {} + impl TraitWithAssocTy for u8 { type AssocTy = Priv; } + //~^ ERROR private type `Priv` in public interface + + pub fn leak_anon1() -> impl Trait + 'static { 0 } + pub fn leak_anon2() -> impl TraitWithTyParam { 0 } + pub fn leak_anon3() -> impl TraitWithAssocTy { 0 } + + pub fn leak_dyn1() -> Box { Box::new(0) } + pub fn leak_dyn2() -> Box> { Box::new(0) } + pub fn leak_dyn3() -> Box> { Box::new(0) } +} + +mod adjust { + // Construct a chain of derefs with a private type in the middle + use std::ops::Deref; + + pub struct S1; + struct S2; + pub type S2Alias = S2; + pub struct S3; + + impl Deref for S1 { + type Target = S2Alias; //~ ERROR private type `S2` in public interface + fn deref(&self) -> &Self::Target { loop {} } + } + impl Deref for S2 { + type Target = S3; + fn deref(&self) -> &Self::Target { loop {} } + } + + impl S3 { + pub fn method_s3(&self) {} + } +} + +fn main() { + let _: m::Alias; //~ ERROR type `Priv` is private + //~^ ERROR type `Priv` is private + let _: ::AssocTy; //~ ERROR type `Priv` is private + m::Alias {}; //~ ERROR type `Priv` is private + m::Pub { 0: m::Alias {} }; //~ ERROR type `Priv` is private + m::Pub { 0: loop {} }; // OK, `m::Pub` is in value context, so it means Pub<_>, not Pub + m::Pub::static_method; //~ ERROR type `Priv` is private + m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `Priv` is private + m::Pub(0u8).method_with_substs::(); //~ ERROR type `Priv` is private + m::Pub(0u8).method_with_priv_params(loop{}); //~ ERROR type `Priv` is private + ::TRAIT_ASSOC_CONST; //~ ERROR type `Priv` is private + >::INHERENT_ASSOC_CONST; //~ ERROR type `Priv` is private + >::INHERENT_ASSOC_CONST_GENERIC_SELF; //~ ERROR type `Priv` is private + >::static_method_generic_self; //~ ERROR type `Priv` is private + use m::TraitWithTyParam2; + u8::pub_method; //~ ERROR type `Priv` is private + + adjust::S1.method_s3(); //~ ERROR type `S2` is private + + m::m!(); + + m::leak_anon1(); //~ ERROR trait `Trait` is private + m::leak_anon2(); //~ ERROR type `Priv` is private + m::leak_anon3(); //~ ERROR type `Priv` is private + + m::leak_dyn1(); //~ ERROR trait `Trait` is private + m::leak_dyn2(); //~ ERROR type `Priv` is private + m::leak_dyn3(); //~ ERROR type `Priv` is private + + // Check that messages are not duplicated for various kinds of assignments + let a = m::Alias {}; //~ ERROR type `Priv` is private + let mut b = a; //~ ERROR type `Priv` is private + b = a; //~ ERROR type `Priv` is private + match a { //~ ERROR type `Priv` is private + _ => {} + } +} diff --git a/tests/ui/privacy/private-inferred-type.stderr b/tests/ui/privacy/private-inferred-type.stderr new file mode 100644 index 000000000..fc3f9ab62 --- /dev/null +++ b/tests/ui/privacy/private-inferred-type.stderr @@ -0,0 +1,237 @@ +error[E0446]: private type `Priv` in public interface + --> $DIR/private-inferred-type.rs:61:36 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; } + | ^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `S2` in public interface + --> $DIR/private-inferred-type.rs:83:9 + | +LL | struct S2; + | --------- `S2` declared as private +... +LL | type Target = S2Alias; + | ^^^^^^^^^^^ can't leak private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:97:9 + | +LL | let _: m::Alias; + | ^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:97:12 + | +LL | let _: m::Alias; + | ^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:99:13 + | +LL | let _: ::AssocTy; + | ^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:100:5 + | +LL | m::Alias {}; + | ^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:101:5 + | +LL | m::Pub { 0: m::Alias {} }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:103:5 + | +LL | m::Pub::static_method; + | ^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:104:5 + | +LL | m::Pub::INHERENT_ASSOC_CONST; + | ^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:105:5 + | +LL | m::Pub(0u8).method_with_substs::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:106:17 + | +LL | m::Pub(0u8).method_with_priv_params(loop{}); + | ^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:107:5 + | +LL | ::TRAIT_ASSOC_CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:108:6 + | +LL | >::INHERENT_ASSOC_CONST; + | ^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:109:5 + | +LL | >::INHERENT_ASSOC_CONST_GENERIC_SELF; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:110:5 + | +LL | >::static_method_generic_self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:112:5 + | +LL | u8::pub_method; + | ^^^^^^^^^^^^^^ private type + +error: type `S2` is private + --> $DIR/private-inferred-type.rs:114:5 + | +LL | adjust::S1.method_s3(); + | ^^^^^^^^^^ private type + +error: type `fn() {priv_fn}` is private + --> $DIR/private-inferred-type.rs:39:9 + | +LL | priv_fn; + | ^^^^^^^ private type +... +LL | m::m!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `PrivEnum` is private + --> $DIR/private-inferred-type.rs:41:9 + | +LL | PrivEnum::Variant; + | ^^^^^^^^^^^^^^^^^ private type +... +LL | m::m!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `fn() {::method}` is private + --> $DIR/private-inferred-type.rs:43:9 + | +LL | ::method; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type +... +LL | m::m!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `fn(u8) -> PrivTupleStruct {PrivTupleStruct}` is private + --> $DIR/private-inferred-type.rs:45:9 + | +LL | PrivTupleStruct; + | ^^^^^^^^^^^^^^^ private type +... +LL | m::m!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private + --> $DIR/private-inferred-type.rs:47:9 + | +LL | PubTupleStruct; + | ^^^^^^^^^^^^^^ private type +... +LL | m::m!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private + --> $DIR/private-inferred-type.rs:49:18 + | +LL | Pub(0u8).priv_method(); + | ^^^^^^^^^^^ private type +... +LL | m::m!(); + | ------- in this macro invocation + | + = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: trait `Trait` is private + --> $DIR/private-inferred-type.rs:118:5 + | +LL | m::leak_anon1(); + | ^^^^^^^^^^^^^^^ private trait + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:119:5 + | +LL | m::leak_anon2(); + | ^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:120:5 + | +LL | m::leak_anon3(); + | ^^^^^^^^^^^^^^^ private type + +error: trait `Trait` is private + --> $DIR/private-inferred-type.rs:122:5 + | +LL | m::leak_dyn1(); + | ^^^^^^^^^^^^^^ private trait + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:123:5 + | +LL | m::leak_dyn2(); + | ^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:124:5 + | +LL | m::leak_dyn3(); + | ^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:127:13 + | +LL | let a = m::Alias {}; + | ^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:128:17 + | +LL | let mut b = a; + | ^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:129:9 + | +LL | b = a; + | ^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type.rs:130:11 + | +LL | match a { + | ^ private type + +error: aborting due to 33 previous errors + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/private-item-simple.rs b/tests/ui/privacy/private-item-simple.rs new file mode 100644 index 000000000..1f718ed92 --- /dev/null +++ b/tests/ui/privacy/private-item-simple.rs @@ -0,0 +1,7 @@ +mod a { + fn f() {} +} + +fn main() { + a::f(); //~ ERROR function `f` is private +} diff --git a/tests/ui/privacy/private-item-simple.stderr b/tests/ui/privacy/private-item-simple.stderr new file mode 100644 index 000000000..e3d90150e --- /dev/null +++ b/tests/ui/privacy/private-item-simple.stderr @@ -0,0 +1,15 @@ +error[E0603]: function `f` is private + --> $DIR/private-item-simple.rs:6:8 + | +LL | a::f(); + | ^ private function + | +note: the function `f` is defined here + --> $DIR/private-item-simple.rs:2:5 + | +LL | fn f() {} + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/privacy/private-method-cross-crate.rs b/tests/ui/privacy/private-method-cross-crate.rs new file mode 100644 index 000000000..ab3bbdfe4 --- /dev/null +++ b/tests/ui/privacy/private-method-cross-crate.rs @@ -0,0 +1,8 @@ +// aux-build:cci_class_5.rs +extern crate cci_class_5; +use cci_class_5::kitties::cat; + +fn main() { + let nyan : cat = cat(52, 99); + nyan.nap(); //~ ERROR associated function `nap` is private +} diff --git a/tests/ui/privacy/private-method-cross-crate.stderr b/tests/ui/privacy/private-method-cross-crate.stderr new file mode 100644 index 000000000..93f6a7f2f --- /dev/null +++ b/tests/ui/privacy/private-method-cross-crate.stderr @@ -0,0 +1,14 @@ +error[E0624]: associated function `nap` is private + --> $DIR/private-method-cross-crate.rs:7:8 + | +LL | nyan.nap(); + | ^^^ private associated function + | + ::: $DIR/auxiliary/cci_class_5.rs:8:9 + | +LL | fn nap(&self) {} + | ------------- private associated function defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-method-inherited.rs b/tests/ui/privacy/private-method-inherited.rs new file mode 100644 index 000000000..2f6454288 --- /dev/null +++ b/tests/ui/privacy/private-method-inherited.rs @@ -0,0 +1,14 @@ +// Tests that inherited visibility applies to methods. + +mod a { + pub struct Foo; + + impl Foo { + fn f(self) {} + } +} + +fn main() { + let x = a::Foo; + x.f(); //~ ERROR associated function `f` is private +} diff --git a/tests/ui/privacy/private-method-inherited.stderr b/tests/ui/privacy/private-method-inherited.stderr new file mode 100644 index 000000000..011a7fee4 --- /dev/null +++ b/tests/ui/privacy/private-method-inherited.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `f` is private + --> $DIR/private-method-inherited.rs:13:7 + | +LL | fn f(self) {} + | ---------- private associated function defined here +... +LL | x.f(); + | ^ private associated function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-method-rpass.rs b/tests/ui/privacy/private-method-rpass.rs new file mode 100644 index 000000000..726944fb2 --- /dev/null +++ b/tests/ui/privacy/private-method-rpass.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct cat { + meows : usize, + + how_hungry : isize, +} + +impl cat { + pub fn play(&mut self) { + self.meows += 1_usize; + self.nap(); + } +} + +impl cat { + fn nap(&mut self) { for _ in 1_usize..10_usize { } } +} + +fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } +} + +pub fn main() { + let mut nyan : cat = cat(52_usize, 99); + nyan.play(); +} diff --git a/tests/ui/privacy/private-method.rs b/tests/ui/privacy/private-method.rs new file mode 100644 index 000000000..76a642cde --- /dev/null +++ b/tests/ui/privacy/private-method.rs @@ -0,0 +1,23 @@ +mod kitties { + pub struct Cat { + meows : usize, + + how_hungry : isize, + } + + impl Cat { + fn nap(&self) {} + } + + pub fn cat(in_x : usize, in_y : isize) -> Cat { + Cat { + meows: in_x, + how_hungry: in_y + } + } +} + +fn main() { + let nyan : kitties::Cat = kitties::cat(52, 99); + nyan.nap(); //~ ERROR associated function `nap` is private +} diff --git a/tests/ui/privacy/private-method.stderr b/tests/ui/privacy/private-method.stderr new file mode 100644 index 000000000..17c7179dc --- /dev/null +++ b/tests/ui/privacy/private-method.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `nap` is private + --> $DIR/private-method.rs:22:8 + | +LL | fn nap(&self) {} + | ------------- private associated function defined here +... +LL | nyan.nap(); + | ^^^ private associated function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/privacy/private-struct-field-cross-crate.rs b/tests/ui/privacy/private-struct-field-cross-crate.rs new file mode 100644 index 000000000..301cd37b7 --- /dev/null +++ b/tests/ui/privacy/private-struct-field-cross-crate.rs @@ -0,0 +1,9 @@ +// aux-build:cci_class.rs +extern crate cci_class; +use cci_class::kitties::cat; + +fn main() { + let nyan : cat = cat(52, 99); + assert_eq!(nyan.meows, 52); + //~^ ERROR field `meows` of struct `cat` is private +} diff --git a/tests/ui/privacy/private-struct-field-cross-crate.stderr b/tests/ui/privacy/private-struct-field-cross-crate.stderr new file mode 100644 index 000000000..40cf3448d --- /dev/null +++ b/tests/ui/privacy/private-struct-field-cross-crate.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `meows` of struct `cat` is private + --> $DIR/private-struct-field-cross-crate.rs:7:19 + | +LL | assert_eq!(nyan.meows, 52); + | ^^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/private-struct-field-ctor.rs b/tests/ui/privacy/private-struct-field-ctor.rs new file mode 100644 index 000000000..56e84a751 --- /dev/null +++ b/tests/ui/privacy/private-struct-field-ctor.rs @@ -0,0 +1,9 @@ +mod a { + pub struct Foo { + x: isize + } +} + +fn main() { + let s = a::Foo { x: 1 }; //~ ERROR field `x` of struct `Foo` is private +} diff --git a/tests/ui/privacy/private-struct-field-ctor.stderr b/tests/ui/privacy/private-struct-field-ctor.stderr new file mode 100644 index 000000000..9dc9db0ea --- /dev/null +++ b/tests/ui/privacy/private-struct-field-ctor.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `x` of struct `Foo` is private + --> $DIR/private-struct-field-ctor.rs:8:22 + | +LL | let s = a::Foo { x: 1 }; + | ^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/private-struct-field-pattern.rs b/tests/ui/privacy/private-struct-field-pattern.rs new file mode 100644 index 000000000..4a766500e --- /dev/null +++ b/tests/ui/privacy/private-struct-field-pattern.rs @@ -0,0 +1,17 @@ +use a::Foo; + +mod a { + pub struct Foo { + x: isize + } + + pub fn make() -> Foo { + Foo { x: 3 } + } +} + +fn main() { + match a::make() { + Foo { x: _ } => {} //~ ERROR field `x` of struct `Foo` is private + } +} diff --git a/tests/ui/privacy/private-struct-field-pattern.stderr b/tests/ui/privacy/private-struct-field-pattern.stderr new file mode 100644 index 000000000..630553036 --- /dev/null +++ b/tests/ui/privacy/private-struct-field-pattern.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `x` of struct `Foo` is private + --> $DIR/private-struct-field-pattern.rs:15:15 + | +LL | Foo { x: _ } => {} + | ^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/private-struct-field.rs b/tests/ui/privacy/private-struct-field.rs new file mode 100644 index 000000000..94cee4eff --- /dev/null +++ b/tests/ui/privacy/private-struct-field.rs @@ -0,0 +1,14 @@ +mod cat { + pub struct Cat { + meows: usize + } + + pub fn new_cat() -> Cat { + Cat { meows: 52 } + } +} + +fn main() { + let nyan = cat::new_cat(); + assert_eq!(nyan.meows, 52); //~ ERROR field `meows` of struct `Cat` is private +} diff --git a/tests/ui/privacy/private-struct-field.stderr b/tests/ui/privacy/private-struct-field.stderr new file mode 100644 index 000000000..facf4e82f --- /dev/null +++ b/tests/ui/privacy/private-struct-field.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `meows` of struct `Cat` is private + --> $DIR/private-struct-field.rs:13:21 + | +LL | assert_eq!(nyan.meows, 52); + | ^^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/private-type-in-interface.rs b/tests/ui/privacy/private-type-in-interface.rs new file mode 100644 index 000000000..7fbdbaf5f --- /dev/null +++ b/tests/ui/privacy/private-type-in-interface.rs @@ -0,0 +1,30 @@ +// aux-build:private-inferred-type.rs + +#![allow(warnings)] + +extern crate private_inferred_type as ext; + +mod m { + struct Priv; + pub type Alias = Priv; + + pub trait Trait { type X; } + impl Trait for Priv { type X = u8; } +} + +fn f(_: m::Alias) {} //~ ERROR type `Priv` is private + //~^ ERROR type `Priv` is private +fn f_ext(_: ext::Alias) {} //~ ERROR type `ext::Priv` is private + //~^ ERROR type `ext::Priv` is private + +trait Tr1 {} +impl m::Alias {} //~ ERROR type `Priv` is private +impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private +type A = ::X; //~ ERROR type `Priv` is private + +trait Tr2 {} +impl Tr2 for u8 {} +fn g() -> impl Tr2 { 0 } //~ ERROR type `Priv` is private +fn g_ext() -> impl Tr2 { 0 } //~ ERROR type `ext::Priv` is private + +fn main() {} diff --git a/tests/ui/privacy/private-type-in-interface.stderr b/tests/ui/privacy/private-type-in-interface.stderr new file mode 100644 index 000000000..4e87caa34 --- /dev/null +++ b/tests/ui/privacy/private-type-in-interface.stderr @@ -0,0 +1,56 @@ +error: type `Priv` is private + --> $DIR/private-type-in-interface.rs:15:9 + | +LL | fn f(_: m::Alias) {} + | ^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-type-in-interface.rs:15:6 + | +LL | fn f(_: m::Alias) {} + | ^ private type + +error: type `ext::Priv` is private + --> $DIR/private-type-in-interface.rs:17:13 + | +LL | fn f_ext(_: ext::Alias) {} + | ^^^^^^^^^^ private type + +error: type `ext::Priv` is private + --> $DIR/private-type-in-interface.rs:17:10 + | +LL | fn f_ext(_: ext::Alias) {} + | ^ private type + +error: type `Priv` is private + --> $DIR/private-type-in-interface.rs:21:6 + | +LL | impl m::Alias {} + | ^^^^^^^^ private type + +error: type `ext::Priv` is private + --> $DIR/private-type-in-interface.rs:22:14 + | +LL | impl Tr1 for ext::Alias {} + | ^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-type-in-interface.rs:23:10 + | +LL | type A = ::X; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-type-in-interface.rs:27:11 + | +LL | fn g() -> impl Tr2 { 0 } + | ^^^^^^^^^^^^^^^^^^ private type + +error: type `ext::Priv` is private + --> $DIR/private-type-in-interface.rs:28:15 + | +LL | fn g_ext() -> impl Tr2 { 0 } + | ^^^^^^^^^^^^^^^^^^^^ private type + +error: aborting due to 9 previous errors + diff --git a/tests/ui/privacy/private-variant-reexport.rs b/tests/ui/privacy/private-variant-reexport.rs new file mode 100644 index 000000000..688284460 --- /dev/null +++ b/tests/ui/privacy/private-variant-reexport.rs @@ -0,0 +1,20 @@ +mod m1 { + pub use ::E::V; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +mod m2 { + pub use ::E::{V}; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +mod m3 { + pub use ::E::V::{self}; //~ ERROR `V` is only public within the crate, and cannot be re-exported outside +} + +#[deny(unused_imports)] +mod m4 { + pub use ::E::*; //~ ERROR glob import doesn't reexport anything +} + +enum E { V } + +fn main() {} diff --git a/tests/ui/privacy/private-variant-reexport.stderr b/tests/ui/privacy/private-variant-reexport.stderr new file mode 100644 index 000000000..78771ee30 --- /dev/null +++ b/tests/ui/privacy/private-variant-reexport.stderr @@ -0,0 +1,48 @@ +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/private-variant-reexport.rs:2:13 + | +LL | pub use ::E::V; + | ^^^^^^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/private-variant-reexport.rs:2:13 + | +LL | pub use ::E::V; + | ^^^^^^ + +error[E0364]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/private-variant-reexport.rs:6:19 + | +LL | pub use ::E::{V}; + | ^ + | +note: consider marking `V` as `pub` in the imported module + --> $DIR/private-variant-reexport.rs:6:19 + | +LL | pub use ::E::{V}; + | ^ + +error[E0365]: `V` is only public within the crate, and cannot be re-exported outside + --> $DIR/private-variant-reexport.rs:10:22 + | +LL | pub use ::E::V::{self}; + | ^^^^ re-export of crate public `V` + | + = note: consider declaring type or module `V` with `pub` + +error: glob import doesn't reexport anything because no candidate is public enough + --> $DIR/private-variant-reexport.rs:15:13 + | +LL | pub use ::E::*; + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/private-variant-reexport.rs:13:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0364, E0365. +For more information about an error, try `rustc --explain E0364`. diff --git a/tests/ui/privacy/pub-extern-privacy.rs b/tests/ui/privacy/pub-extern-privacy.rs new file mode 100644 index 000000000..dbbbe4e3b --- /dev/null +++ b/tests/ui/privacy/pub-extern-privacy.rs @@ -0,0 +1,18 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with + +// pretty-expanded FIXME #23616 + +use std::mem::transmute; + +mod a { + extern "C" { + pub fn free(x: *const u8); + } +} + +pub fn main() { + unsafe { + a::free(transmute(0_usize)); + } +} diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs new file mode 100644 index 000000000..e7afeb84f --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs @@ -0,0 +1,2 @@ +pub struct OtherType; +pub trait OtherTrait {} diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs new file mode 100644 index 000000000..3ebafd953 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/pub_dep.rs @@ -0,0 +1 @@ +pub struct PubType; diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs new file mode 100644 index 000000000..ec8666f93 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -0,0 +1,44 @@ +// aux-crate:priv:priv_dep=priv_dep.rs +// aux-build:pub_dep.rs +// compile-flags: -Zunstable-options +#![deny(exported_private_dependencies)] + +// This crate is a private dependency +extern crate priv_dep; +// This crate is a public dependency +extern crate pub_dep; + +use priv_dep::{OtherTrait, OtherType}; +use pub_dep::PubType; + +// Type from private dependency used in private +// type - this is fine +struct PrivateType { + field: OtherType, +} + +pub struct PublicType { + pub field: OtherType, + //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + priv_field: OtherType, // Private field - this is fine + pub other_field: PubType, // Type from public dependency - this is fine +} + +impl PublicType { + pub fn pub_fn(param: OtherType) {} + //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface + + fn priv_fn(param: OtherType) {} +} + +pub trait MyPubTrait { + type Foo: OtherTrait; +} +//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface + +pub struct AllowedPrivType { + #[allow(exported_private_dependencies)] + pub allowed: OtherType, +} + +fn main() {} diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr new file mode 100644 index 000000000..e62a440d8 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -0,0 +1,26 @@ +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:21:5 + | +LL | pub field: OtherType, + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/pub-priv1.rs:4:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:28:5 + | +LL | pub fn pub_fn(param: OtherType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:35:5 + | +LL | type Foo: OtherTrait; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/privacy/pub-priv-dep/std-pub.rs b/tests/ui/privacy/pub-priv-dep/std-pub.rs new file mode 100644 index 000000000..e25aa93a0 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/std-pub.rs @@ -0,0 +1,12 @@ +// The 'std' crates should always be implicitly public, +// without having to pass any compiler arguments + +// run-pass + +#![deny(exported_private_dependencies)] + +pub struct PublicType { + pub field: Option +} + +fn main() {} diff --git a/tests/ui/privacy/pub-use-xcrate.rs b/tests/ui/privacy/pub-use-xcrate.rs new file mode 100644 index 000000000..e8a6e8cf1 --- /dev/null +++ b/tests/ui/privacy/pub-use-xcrate.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:pub_use_xcrate1.rs +// aux-build:pub_use_xcrate2.rs + +// pretty-expanded FIXME #23616 + +extern crate pub_use_xcrate2; + +use pub_use_xcrate2::Foo; + +pub fn main() { + let _foo: Foo = Foo { + name: 0 + }; +} diff --git a/tests/ui/privacy/pub_use_mods_xcrate_exe.rs b/tests/ui/privacy/pub_use_mods_xcrate_exe.rs new file mode 100644 index 000000000..f163619e7 --- /dev/null +++ b/tests/ui/privacy/pub_use_mods_xcrate_exe.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:pub_use_mods_xcrate.rs + +// pretty-expanded FIXME #23616 + +#![allow(unused_imports)] + +extern crate pub_use_mods_xcrate; +use pub_use_mods_xcrate::a::c; + +pub fn main(){} diff --git a/tests/ui/privacy/reachable-unnameable-items.rs b/tests/ui/privacy/reachable-unnameable-items.rs new file mode 100644 index 000000000..1babe0119 --- /dev/null +++ b/tests/ui/privacy/reachable-unnameable-items.rs @@ -0,0 +1,31 @@ +// run-pass +// needs-unwind +// aux-build:reachable-unnameable-items.rs + +extern crate reachable_unnameable_items; +use reachable_unnameable_items::*; + +fn main() { + let res1 = function_returning_unnameable_type().method_of_unnameable_type1(); + let res2 = CONSTANT_OF_UNNAMEABLE_TYPE.method_of_unnameable_type2(); + let res4 = AliasOfUnnameableType{}.method_of_unnameable_type4(); + let res5 = function_returning_unnameable_type().inherent_method_returning_unnameable_type(). + method_of_unnameable_type5(); + let res6 = function_returning_unnameable_type().trait_method_returning_unnameable_type(). + method_of_unnameable_type6(); + let res7 = STATIC.field_of_unnameable_type.method_of_unnameable_type7(); + let res8 = generic_function::().method_of_unnameable_type8(); + let res_enum = NameableVariant.method_of_unnameable_enum(); + assert_eq!(res1, "Hello1"); + assert_eq!(res2, "Hello2"); + assert_eq!(res4, "Hello4"); + assert_eq!(res5, "Hello5"); + assert_eq!(res6, "Hello6"); + assert_eq!(res7, "Hello7"); + assert_eq!(res8, "Hello8"); + assert_eq!(res_enum, "HelloEnum"); + + let none = None; + function_accepting_unnameable_type(none); + let _guard = std::panic::catch_unwind(|| none.unwrap().method_of_unnameable_type3()); +} diff --git a/tests/ui/privacy/restricted/auxiliary/pub_restricted.rs b/tests/ui/privacy/restricted/auxiliary/pub_restricted.rs new file mode 100644 index 000000000..a4013e6ac --- /dev/null +++ b/tests/ui/privacy/restricted/auxiliary/pub_restricted.rs @@ -0,0 +1,14 @@ +pub(crate) struct Crate; + +#[derive(Default)] +pub struct Universe { + pub x: i32, + pub(crate) y: i32, + pub(crate) z: i32, +} + +impl Universe { + pub fn f(&self) {} + pub(crate) fn g(&self) {} + pub(crate) fn h(&self) {} +} diff --git a/tests/ui/privacy/restricted/lookup-ignores-private.rs b/tests/ui/privacy/restricted/lookup-ignores-private.rs new file mode 100644 index 000000000..240ce1e2b --- /dev/null +++ b/tests/ui/privacy/restricted/lookup-ignores-private.rs @@ -0,0 +1,34 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(warnings)] + +mod foo { + pub use foo::bar::S; + mod bar { + #[derive(Default)] + pub struct S { + pub(in foo) x: i32, + } + impl S { + pub(in foo) fn f(&self) -> i32 { 0 } + } + + pub struct S2 { + pub(crate) x: bool, + } + impl S2 { + pub(crate) fn f(&self) -> bool { false } + } + + impl ::std::ops::Deref for S { + type Target = S2; + fn deref(&self) -> &S2 { unimplemented!() } + } + } +} + + +fn main() { + let s = foo::S::default(); + let _: bool = s.x; + let _: bool = s.f(); +} diff --git a/tests/ui/privacy/restricted/private-in-public.rs b/tests/ui/privacy/restricted/private-in-public.rs new file mode 100644 index 000000000..1e3dbdf73 --- /dev/null +++ b/tests/ui/privacy/restricted/private-in-public.rs @@ -0,0 +1,11 @@ +mod foo { + struct Priv; + mod bar { + use foo::Priv; + pub(super) fn f(_: Priv) {} + pub(crate) fn g(_: Priv) {} //~ ERROR E0446 + pub(crate) fn h(_: Priv) {} //~ ERROR E0446 + } +} + +fn main() { } diff --git a/tests/ui/privacy/restricted/private-in-public.stderr b/tests/ui/privacy/restricted/private-in-public.stderr new file mode 100644 index 000000000..65d996f0f --- /dev/null +++ b/tests/ui/privacy/restricted/private-in-public.stderr @@ -0,0 +1,21 @@ +error[E0446]: private type `Priv` in public interface + --> $DIR/private-in-public.rs:6:9 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | pub(crate) fn g(_: Priv) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv` in public interface + --> $DIR/private-in-public.rs:7:9 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | pub(crate) fn h(_: Priv) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/restricted/relative-2018.rs b/tests/ui/privacy/restricted/relative-2018.rs new file mode 100644 index 000000000..954169a9f --- /dev/null +++ b/tests/ui/privacy/restricted/relative-2018.rs @@ -0,0 +1,13 @@ +// edition:2018 + +mod m { + pub(in crate) struct S1; // OK + pub(in super) struct S2; // OK + pub(in self) struct S3; // OK + pub(in ::core) struct S4; + //~^ ERROR visibilities can only be restricted to ancestor modules + pub(in a::b) struct S5; + //~^ ERROR relative paths are not supported in visibilities in 2018 edition or later +} + +fn main() {} diff --git a/tests/ui/privacy/restricted/relative-2018.stderr b/tests/ui/privacy/restricted/relative-2018.stderr new file mode 100644 index 000000000..dec0d5157 --- /dev/null +++ b/tests/ui/privacy/restricted/relative-2018.stderr @@ -0,0 +1,17 @@ +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/relative-2018.rs:7:12 + | +LL | pub(in ::core) struct S4; + | ^^^^^^ + +error: relative paths are not supported in visibilities in 2018 edition or later + --> $DIR/relative-2018.rs:9:12 + | +LL | pub(in a::b) struct S5; + | ^--- + | | + | help: try: `crate::a::b` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0742`. diff --git a/tests/ui/privacy/restricted/struct-literal-field.rs b/tests/ui/privacy/restricted/struct-literal-field.rs new file mode 100644 index 000000000..9c6104755 --- /dev/null +++ b/tests/ui/privacy/restricted/struct-literal-field.rs @@ -0,0 +1,19 @@ +#![allow(warnings)] + +mod foo { + pub mod bar { + pub struct S { + pub(in foo) x: i32, + } + } + + fn f() { + use foo::bar::S; + S { x: 0 }; // ok + } +} + +fn main() { + use foo::bar::S; + S { x: 0 }; //~ ERROR private +} diff --git a/tests/ui/privacy/restricted/struct-literal-field.stderr b/tests/ui/privacy/restricted/struct-literal-field.stderr new file mode 100644 index 000000000..eee964f02 --- /dev/null +++ b/tests/ui/privacy/restricted/struct-literal-field.stderr @@ -0,0 +1,9 @@ +error[E0451]: field `x` of struct `S` is private + --> $DIR/struct-literal-field.rs:18:9 + | +LL | S { x: 0 }; + | ^^^^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/restricted/test.rs b/tests/ui/privacy/restricted/test.rs new file mode 100644 index 000000000..a8c269378 --- /dev/null +++ b/tests/ui/privacy/restricted/test.rs @@ -0,0 +1,52 @@ +// aux-build:pub_restricted.rs + +#![allow(warnings)] +extern crate pub_restricted; + +mod foo { + pub mod bar { + pub(super) fn f() {} + #[derive(Default)] + pub struct S { + pub(super) x: i32, + } + impl S { + pub(super) fn f(&self) {} + pub(super) fn g() {} + } + } + fn f() { + use foo::bar::S; + pub(self) use foo::bar::f; // ok + pub(super) use foo::bar::f as g; //~ ERROR cannot be re-exported + S::default().x; // ok + S::default().f(); // ok + S::g(); // ok + } +} + +fn f() { + use foo::bar::S; + use foo::bar::f; //~ ERROR private + S::default().x; //~ ERROR private + S::default().f(); //~ ERROR private + S::g(); //~ ERROR private +} + +fn main() { + use pub_restricted::Universe; + use pub_restricted::Crate; //~ ERROR private + + let u = Universe::default(); + let _ = u.x; + let _ = u.y; //~ ERROR private + let _ = u.z; //~ ERROR private + u.f(); + u.g(); //~ ERROR private + u.h(); //~ ERROR private +} + +mod pathological { + pub(in bad::path) mod m1 {} //~ ERROR failed to resolve: maybe a missing crate `bad`? + pub(in foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules +} diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr new file mode 100644 index 000000000..1acd221b4 --- /dev/null +++ b/tests/ui/privacy/restricted/test.stderr @@ -0,0 +1,112 @@ +error[E0433]: failed to resolve: maybe a missing crate `bad`? + --> $DIR/test.rs:50:12 + | +LL | pub(in bad::path) mod m1 {} + | ^^^ maybe a missing crate `bad`? + | + = help: consider adding `extern crate bad` to use the `bad` crate + +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/test.rs:51:12 + | +LL | pub(in foo) mod m2 {} + | ^^^ + +error[E0364]: `f` is private, and cannot be re-exported + --> $DIR/test.rs:21:24 + | +LL | pub(super) use foo::bar::f as g; + | ^^^^^^^^^^^^^^^^ + | +note: consider marking `f` as `pub` in the imported module + --> $DIR/test.rs:21:24 + | +LL | pub(super) use foo::bar::f as g; + | ^^^^^^^^^^^^^^^^ + +error[E0603]: struct `Crate` is private + --> $DIR/test.rs:38:25 + | +LL | use pub_restricted::Crate; + | ^^^^^ private struct + | +note: the struct `Crate` is defined here + --> $DIR/auxiliary/pub_restricted.rs:1:1 + | +LL | pub(crate) struct Crate; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0603]: function `f` is private + --> $DIR/test.rs:30:19 + | +LL | use foo::bar::f; + | ^ private function + | +note: the function `f` is defined here + --> $DIR/test.rs:8:9 + | +LL | pub(super) fn f() {} + | ^^^^^^^^^^^^^^^^^ + +error[E0616]: field `x` of struct `S` is private + --> $DIR/test.rs:31:18 + | +LL | S::default().x; + | ^ private field + +error[E0624]: associated function `f` is private + --> $DIR/test.rs:32:18 + | +LL | pub(super) fn f(&self) {} + | ---------------------- private associated function defined here +... +LL | S::default().f(); + | ^ private associated function + +error[E0624]: associated function `g` is private + --> $DIR/test.rs:33:8 + | +LL | pub(super) fn g() {} + | ----------------- private associated function defined here +... +LL | S::g(); + | ^ private associated function + +error[E0616]: field `y` of struct `Universe` is private + --> $DIR/test.rs:42:15 + | +LL | let _ = u.y; + | ^ private field + +error[E0616]: field `z` of struct `Universe` is private + --> $DIR/test.rs:43:15 + | +LL | let _ = u.z; + | ^ private field + +error[E0624]: associated function `g` is private + --> $DIR/test.rs:45:7 + | +LL | u.g(); + | ^ private associated function + | + ::: $DIR/auxiliary/pub_restricted.rs:12:5 + | +LL | pub(crate) fn g(&self) {} + | ---------------------- private associated function defined here + +error[E0624]: associated function `h` is private + --> $DIR/test.rs:46:7 + | +LL | u.h(); + | ^ private associated function + | + ::: $DIR/auxiliary/pub_restricted.rs:13:5 + | +LL | pub(crate) fn h(&self) {} + | ---------------------- private associated function defined here + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0364, E0433, E0603, E0616, E0624, E0742. +For more information about an error, try `rustc --explain E0364`. diff --git a/tests/ui/privacy/suggest-making-field-public.fixed b/tests/ui/privacy/suggest-making-field-public.fixed new file mode 100644 index 000000000..78e335b3d --- /dev/null +++ b/tests/ui/privacy/suggest-making-field-public.fixed @@ -0,0 +1,15 @@ +// run-rustfix +mod a { + pub struct A(pub String); +} + +mod b { + use crate::a::A; + pub fn x() { + A("".into()); //~ ERROR cannot initialize a tuple struct which contains private fields + } +} +fn main() { + a::A("a".into()); //~ ERROR tuple struct constructor `A` is private + b::x(); +} diff --git a/tests/ui/privacy/suggest-making-field-public.rs b/tests/ui/privacy/suggest-making-field-public.rs new file mode 100644 index 000000000..b65c801d1 --- /dev/null +++ b/tests/ui/privacy/suggest-making-field-public.rs @@ -0,0 +1,15 @@ +// run-rustfix +mod a { + pub struct A(pub(self)String); +} + +mod b { + use crate::a::A; + pub fn x() { + A("".into()); //~ ERROR cannot initialize a tuple struct which contains private fields + } +} +fn main() { + a::A("a".into()); //~ ERROR tuple struct constructor `A` is private + b::x(); +} diff --git a/tests/ui/privacy/suggest-making-field-public.stderr b/tests/ui/privacy/suggest-making-field-public.stderr new file mode 100644 index 000000000..e92e9aae3 --- /dev/null +++ b/tests/ui/privacy/suggest-making-field-public.stderr @@ -0,0 +1,39 @@ +error[E0603]: tuple struct constructor `A` is private + --> $DIR/suggest-making-field-public.rs:13:8 + | +LL | pub struct A(pub(self)String); + | --------------- a constructor is private if any of the fields is private +... +LL | a::A("a".into()); + | ^ private tuple struct constructor + | +note: the tuple struct constructor `A` is defined here + --> $DIR/suggest-making-field-public.rs:3:5 + | +LL | pub struct A(pub(self)String); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct A(pub String); + | ~~~ + +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/suggest-making-field-public.rs:9:9 + | +LL | A("".into()); + | ^ + | +note: constructor is not visible here due to private fields + --> $DIR/suggest-making-field-public.rs:3:18 + | +LL | pub struct A(pub(self)String); + | ^^^^^^^^^^^^^^^ private field +help: consider making the field publicly accessible + | +LL | pub struct A(pub String); + | ~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0603. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/privacy/union-field-privacy-1.rs b/tests/ui/privacy/union-field-privacy-1.rs new file mode 100644 index 000000000..8a84bd86a --- /dev/null +++ b/tests/ui/privacy/union-field-privacy-1.rs @@ -0,0 +1,17 @@ +mod m { + pub union U { + pub a: u8, + pub(super) b: u8, + c: u8, + } +} + +fn main() { unsafe { + let u = m::U { a: 0 }; // OK + let u = m::U { b: 0 }; // OK + let u = m::U { c: 0 }; //~ ERROR field `c` of union `U` is private + + let m::U { a } = u; // OK + let m::U { b } = u; // OK + let m::U { c } = u; //~ ERROR field `c` of union `U` is private +}} diff --git a/tests/ui/privacy/union-field-privacy-1.stderr b/tests/ui/privacy/union-field-privacy-1.stderr new file mode 100644 index 000000000..b1f0b785e --- /dev/null +++ b/tests/ui/privacy/union-field-privacy-1.stderr @@ -0,0 +1,15 @@ +error[E0451]: field `c` of union `U` is private + --> $DIR/union-field-privacy-1.rs:12:20 + | +LL | let u = m::U { c: 0 }; + | ^^^^ private field + +error[E0451]: field `c` of union `U` is private + --> $DIR/union-field-privacy-1.rs:16:16 + | +LL | let m::U { c } = u; + | ^ private field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/privacy/union-field-privacy-2.rs b/tests/ui/privacy/union-field-privacy-2.rs new file mode 100644 index 000000000..f02e0f8a9 --- /dev/null +++ b/tests/ui/privacy/union-field-privacy-2.rs @@ -0,0 +1,15 @@ +mod m { + pub union U { + pub a: u8, + pub(super) b: u8, + c: u8, + } +} + +fn main() { + let u = m::U { a: 10 }; + + let a = u.a; // OK + let b = u.b; // OK + let c = u.c; //~ ERROR field `c` of union `U` is private +} diff --git a/tests/ui/privacy/union-field-privacy-2.stderr b/tests/ui/privacy/union-field-privacy-2.stderr new file mode 100644 index 000000000..bf6a2b625 --- /dev/null +++ b/tests/ui/privacy/union-field-privacy-2.stderr @@ -0,0 +1,9 @@ +error[E0616]: field `c` of union `U` is private + --> $DIR/union-field-privacy-2.rs:14:15 + | +LL | let c = u.c; + | ^ private field + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/privacy/useless-pub.rs b/tests/ui/privacy/useless-pub.rs new file mode 100644 index 000000000..fde7cd5d8 --- /dev/null +++ b/tests/ui/privacy/useless-pub.rs @@ -0,0 +1,16 @@ +struct A { pub i: isize } + +pub trait E { + fn foo(&self); +} + +impl E for A { + pub fn foo(&self) {} //~ ERROR: unnecessary visibility qualifier +} + +enum Foo { + V1 { pub f: i32 }, //~ ERROR unnecessary visibility qualifier + V2(pub i32), //~ ERROR unnecessary visibility qualifier +} + +fn main() {} diff --git a/tests/ui/privacy/useless-pub.stderr b/tests/ui/privacy/useless-pub.stderr new file mode 100644 index 000000000..14c4983ae --- /dev/null +++ b/tests/ui/privacy/useless-pub.stderr @@ -0,0 +1,21 @@ +error[E0449]: unnecessary visibility qualifier + --> $DIR/useless-pub.rs:8:5 + | +LL | pub fn foo(&self) {} + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/useless-pub.rs:12:10 + | +LL | V1 { pub f: i32 }, + | ^^^ `pub` not permitted here because it's implied + +error[E0449]: unnecessary visibility qualifier + --> $DIR/useless-pub.rs:13:8 + | +LL | V2(pub i32), + | ^^^ `pub` not permitted here because it's implied + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs new file mode 100644 index 000000000..66ee9c4bb --- /dev/null +++ b/tests/ui/privacy/where-priv-type.rs @@ -0,0 +1,90 @@ +// priv-in-pub lint tests where the private type appears in the +// `where` clause of a public item + +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + + +struct PrivTy; +trait PrivTr {} +pub struct PubTy; +pub struct PubTyGeneric(T); +pub trait PubTr {} +impl PubTr for PrivTy {} +pub trait PubTrWithAssocTy { type AssocTy; } +impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; } + + +pub struct S +//~^ WARNING private type `PrivTy` in public interface +//~| WARNING hard error +where + PrivTy: +{} + + +pub enum E +//~^ WARNING private type `PrivTy` in public interface +//~| WARNING hard error +where + PrivTy: +{} + + +pub fn f() +//~^ WARNING private type `PrivTy` in public interface +//~| WARNING hard error +where + PrivTy: +{} + + +impl S +//~^ ERROR private type `PrivTy` in public interface +where + PrivTy: +{ + pub fn f() + //~^ WARNING private type `PrivTy` in public interface + //~| WARNING hard error + where + PrivTy: + {} +} + + +impl PubTr for PubTy +where + PrivTy: +{} + + +impl PubTr for PubTyGeneric +where + T: PubTrWithAssocTy +{} + + +pub struct Const; + +pub trait Trait { + type AssocTy; + fn assoc_fn() -> Self::AssocTy; +} + +impl Trait for Const +where + Const<{ my_const_fn(U) }>: , +{ + type AssocTy = Const<{ my_const_fn(U) }>; + //~^ ERROR private type + fn assoc_fn() -> Self::AssocTy { + Const + } +} + +const fn my_const_fn(val: u8) -> u8 { + // body of this function doesn't matter + val +} diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr new file mode 100644 index 000000000..c5fb2cdb0 --- /dev/null +++ b/tests/ui/privacy/where-priv-type.stderr @@ -0,0 +1,66 @@ +warning: private type `PrivTy` in public interface (error E0446) + --> $DIR/where-priv-type.rs:19:1 + | +LL | pub struct S + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + = note: `#[warn(private_in_public)]` on by default + +warning: private type `PrivTy` in public interface (error E0446) + --> $DIR/where-priv-type.rs:27:1 + | +LL | pub enum E + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +warning: private type `PrivTy` in public interface (error E0446) + --> $DIR/where-priv-type.rs:35:1 + | +LL | / pub fn f() +LL | | +LL | | +LL | | where +LL | | PrivTy: + | |___________^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `PrivTy` in public interface + --> $DIR/where-priv-type.rs:43:1 + | +LL | struct PrivTy; + | ------------- `PrivTy` declared as private +... +LL | impl S + | ^^^^^^ can't leak private type + +warning: private type `PrivTy` in public interface (error E0446) + --> $DIR/where-priv-type.rs:48:5 + | +LL | / pub fn f() +LL | | +LL | | +LL | | where +LL | | PrivTy: + | |_______________^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/where-priv-type.rs:80:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + +error: aborting due to 2 previous errors; 4 warnings emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs new file mode 100644 index 000000000..87c211df1 --- /dev/null +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs @@ -0,0 +1,56 @@ +// priv-in-pub lint tests where the private trait bounds a public type + +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + + +struct PrivTy; +trait PrivTr {} +pub struct PubTy; +pub struct PubTyGeneric(T); +pub trait PubTr {} +impl PubTr for PrivTy {} +impl PrivTr for PubTy {} +pub trait PubTrWithAssocTy { type AssocTy; } +impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; } + + +pub struct S +//~^ ERROR private trait `PrivTr` in public interface +where + PubTy: PrivTr +{} + + +pub enum E +//~^ ERROR private trait `PrivTr` in public interface +where + PubTy: PrivTr +{} + + +pub fn f() +//~^ ERROR private trait `PrivTr` in public interface +where + PubTy: PrivTr +{} + + +impl S +//~^ ERROR private trait `PrivTr` in public interface +where + PubTy: PrivTr +{ + pub fn f() + //~^ ERROR private trait `PrivTr` in public interface + where + PubTy: PrivTr + {} +} + + +impl PubTr for PubTy +where + PubTy: PrivTr +{} diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr new file mode 100644 index 000000000..a433cebbb --- /dev/null +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr @@ -0,0 +1,54 @@ +error[E0445]: private trait `PrivTr` in public interface + --> $DIR/where-pub-type-impls-priv-trait.rs:19:1 + | +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private +... +LL | pub struct S + | ^^^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `PrivTr` in public interface + --> $DIR/where-pub-type-impls-priv-trait.rs:26:1 + | +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private +... +LL | pub enum E + | ^^^^^^^^^^ can't leak private trait + +error[E0445]: private trait `PrivTr` in public interface + --> $DIR/where-pub-type-impls-priv-trait.rs:33:1 + | +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private +... +LL | / pub fn f() +LL | | +LL | | where +LL | | PubTy: PrivTr + | |_________________^ can't leak private trait + +error[E0445]: private trait `PrivTr` in public interface + --> $DIR/where-pub-type-impls-priv-trait.rs:40:1 + | +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private +... +LL | impl S + | ^^^^^^ can't leak private trait + +error[E0445]: private trait `PrivTr` in public interface + --> $DIR/where-pub-type-impls-priv-trait.rs:45:5 + | +LL | trait PrivTr {} + | ------------ `PrivTr` declared as private +... +LL | / pub fn f() +LL | | +LL | | where +LL | | PubTy: PrivTr + | |_____________________^ can't leak private trait + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0445`. diff --git a/tests/ui/proc-macro/add-impl.rs b/tests/ui/proc-macro/add-impl.rs new file mode 100644 index 000000000..ff2897a5e --- /dev/null +++ b/tests/ui/proc-macro/add-impl.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:add-impl.rs + +#[macro_use] +extern crate add_impl; + +#[derive(AddImpl)] +struct B; + +fn main() { + B.foo(); + foo(); + bar::foo(); +} diff --git a/tests/ui/proc-macro/allowed-attr-stmt-expr.rs b/tests/ui/proc-macro/allowed-attr-stmt-expr.rs new file mode 100644 index 000000000..25243aeef --- /dev/null +++ b/tests/ui/proc-macro/allowed-attr-stmt-expr.rs @@ -0,0 +1,78 @@ +// aux-build:attr-stmt-expr.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// check-pass + +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] +#![allow(dead_code)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate attr_stmt_expr; +extern crate test_macros; +use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr}; +use test_macros::print_attr; + +// We don't use `std::println` so that we avoid loading hygiene +// information from libstd, which would affect the SyntaxContext ids +macro_rules! my_macro { + ($($tt:tt)*) => { () } +} + + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_my_macro_expr] + my_macro!("{}", string) +} + +macro_rules! make_stmt { + ($stmt:stmt) => { + #[print_attr] + #[rustc_dummy] + $stmt; // This semicolon is *not* passed to the macro, + // since `$stmt` is already a statement. + } +} + +macro_rules! second_make_stmt { + ($stmt:stmt) => { + make_stmt!($stmt); + } +} + +// The macro will see a semicolon here +#[print_attr] +struct ItemWithSemi; + + +fn main() { + make_stmt!(struct Foo {}); + + #[print_attr] + #[expect_let] + let string = "Hello, world!"; + + #[print_attr] + #[expect_my_macro_stmt] + my_macro!("{}", string); + + #[print_attr] + second_make_stmt!(#[allow(dead_code)] struct Bar {}); + + #[print_attr] + #[rustc_dummy] + struct Other {}; + + // The macro also sees a semicolon, + // for consistency with the `ItemWithSemi` case above. + #[print_attr] + #[rustc_dummy] + struct NonBracedStruct; + + #[expect_expr] + print_str("string") +} diff --git a/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout b/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout new file mode 100644 index 000000000..091862de3 --- /dev/null +++ b/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout @@ -0,0 +1,321 @@ +PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:49:1: 49:7 (#0), + }, + Ident { + ident: "ItemWithSemi", + span: $DIR/allowed-attr-stmt-expr.rs:49:8: 49:20 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:49:20: 49:21 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#11), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#11), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#11), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:53:16: 53:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/allowed-attr-stmt-expr.rs:53:23: 53:26 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:53:27: 53:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:56:5: 56:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_let", + span: $DIR/allowed-attr-stmt-expr.rs:56:7: 56:17 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:56:6: 56:18 (#0), + }, + Ident { + ident: "let", + span: $DIR/allowed-attr-stmt-expr.rs:57:5: 57:8 (#0), + }, + Ident { + ident: "string", + span: $DIR/allowed-attr-stmt-expr.rs:57:9: 57:15 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:57:16: 57:17 (#0), + }, + Literal { + kind: Str, + symbol: "Hello, world!", + suffix: None, + span: $DIR/allowed-attr-stmt-expr.rs:57:18: 57:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:57:33: 57:34 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:60:5: 60:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_my_macro_stmt", + span: $DIR/allowed-attr-stmt-expr.rs:60:7: 60:27 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:60:6: 60:28 (#0), + }, + Ident { + ident: "my_macro", + span: $DIR/allowed-attr-stmt-expr.rs:61:5: 61:13 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:61:13: 61:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "{}", + suffix: None, + span: $DIR/allowed-attr-stmt-expr.rs:61:15: 61:19 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:61:19: 61:20 (#0), + }, + Ident { + ident: "string", + span: $DIR/allowed-attr-stmt-expr.rs:61:21: 61:27 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:61:14: 61:28 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:61:28: 61:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_make_stmt", + span: $DIR/allowed-attr-stmt-expr.rs:64:5: 64:21 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:21: 64:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:22: 64:57 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:57: 64:58 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#32), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#32), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#32), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:67:5: 67:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:67:7: 67:18 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:67:6: 67:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:68:5: 68:11 (#0), + }, + Ident { + ident: "Other", + span: $DIR/allowed-attr-stmt-expr.rs:68:12: 68:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:68:18: 68:20 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:73:5: 73:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:73:7: 73:18 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:73:6: 73:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:74:5: 74:11 (#0), + }, + Ident { + ident: "NonBracedStruct", + span: $DIR/allowed-attr-stmt-expr.rs:74:12: 74:27 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:74:27: 74:28 (#0), + }, +] diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs new file mode 100644 index 000000000..6a47e50f6 --- /dev/null +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs @@ -0,0 +1,20 @@ +// aux-build:builtin-attrs.rs +// compile-flags:--test + +#![feature(decl_macro, test)] + +extern crate test; +extern crate builtin_attrs; +use builtin_attrs::{test, bench}; + +#[test] // OK, shadowed +fn test() {} + +#[bench] // OK, shadowed +fn bench(b: &mut test::Bencher) {} + +fn not_main() { + Test; + Bench; + NonExistent; //~ ERROR cannot find value `NonExistent` in this scope +} diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr new file mode 100644 index 000000000..316eb636b --- /dev/null +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `NonExistent` in this scope + --> $DIR/ambiguous-builtin-attrs-test.rs:19:5 + | +LL | NonExistent; + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs.rs b/tests/ui/proc-macro/ambiguous-builtin-attrs.rs new file mode 100644 index 000000000..695ea69c8 --- /dev/null +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -0,0 +1,39 @@ +// edition:2018 +// aux-build:builtin-attrs.rs +#![feature(decl_macro)] //~ ERROR `feature` is ambiguous + +extern crate builtin_attrs; +use builtin_attrs::*; +use builtin_attrs::{bench, test}; + +#[repr(C)] //~ ERROR `repr` is ambiguous +struct S; +#[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous +struct SCond; + +#[test] // OK, shadowed +fn test() {} + +#[bench] // OK, shadowed +fn bench() {} + +fn non_macro_expanded_location<#[repr(C)] T>() { + //~^ ERROR `repr` is ambiguous + //~| ERROR attribute should be applied to a struct, enum, or union + match 0u8 { + #[repr(C)] + //~^ ERROR `repr` is ambiguous + //~| ERROR attribute should be applied to a struct, enum, or union + _ => {} + } +} + +fn main() { + Test; + Bench; + NonExistent; //~ ERROR cannot find value `NonExistent` in this scope +} + +use deny as allow; +#[allow(unused)] //~ ERROR `allow` is ambiguous +fn builtin_renamed() {} diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr b/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr new file mode 100644 index 000000000..0f4ddc065 --- /dev/null +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs.stderr @@ -0,0 +1,115 @@ +error[E0425]: cannot find value `NonExistent` in this scope + --> $DIR/ambiguous-builtin-attrs.rs:34:5 + | +LL | NonExistent; + | ^^^^^^^^^^^ not found in this scope + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:9:3 + | +LL | #[repr(C)] + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:11:19 + | +LL | #[cfg_attr(all(), repr(C))] + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:20:34 + | +LL | fn non_macro_expanded_location<#[repr(C)] T>() { + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `repr` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:24:11 + | +LL | #[repr(C)] + | ^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `repr` could refer to a built-in attribute +note: `repr` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::repr` to refer to this attribute macro unambiguously + +error[E0659]: `allow` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:38:3 + | +LL | #[allow(unused)] + | ^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `allow` could refer to a built-in attribute +note: `allow` could also refer to the built-in attribute imported here + --> $DIR/ambiguous-builtin-attrs.rs:37:5 + | +LL | use deny as allow; + | ^^^^^^^^^^^^^ + = help: use `crate::allow` to refer to this built-in attribute unambiguously + +error[E0659]: `feature` is ambiguous + --> $DIR/ambiguous-builtin-attrs.rs:3:4 + | +LL | #![feature(decl_macro)] + | ^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a builtin attribute + = note: `feature` could refer to a built-in attribute +note: `feature` could also refer to the attribute macro imported here + --> $DIR/ambiguous-builtin-attrs.rs:6:5 + | +LL | use builtin_attrs::*; + | ^^^^^^^^^^^^^^^^ + = help: use `crate::feature` to refer to this attribute macro unambiguously + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/ambiguous-builtin-attrs.rs:20:39 + | +LL | fn non_macro_expanded_location<#[repr(C)] T>() { + | ^ - not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/ambiguous-builtin-attrs.rs:24:16 + | +LL | #[repr(C)] + | ^ +... +LL | _ => {} + | ------- not a struct, enum, or union + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0425, E0517, E0659. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/amputate-span.fixed b/tests/ui/proc-macro/amputate-span.fixed new file mode 100644 index 000000000..1afc3501a --- /dev/null +++ b/tests/ui/proc-macro/amputate-span.fixed @@ -0,0 +1,69 @@ +// aux-build:amputate-span.rs +// run-rustfix +// edition:2018 +// compile-flags: --extern amputate_span + +// This test has been crafted to ensure the following things: +// +// 1. There's a resolution error that prompts the compiler to suggest +// adding a `use` item. +// +// 2. There are no `use` or `extern crate` items in the source +// code. In fact, there is only one item, the `fn main` +// declaration. +// +// 3. The single `fn main` declaration has an attribute attached to it +// that just deletes the first token from the given item. +// +// You need all of these conditions to hold in order to replicate the +// scenario that yielded issue 87613, where the compiler's suggestion +// looks like: +// +// ``` +// help: consider importing this struct +// | +// 47 | hey */ async use std::process::Command; +// | ++++++++++++++++++++++++++ +// ``` +// +// The first condition is necessary to force the compiler issue a +// suggestion. The second condition is necessary to force the +// suggestion to be issued at a span associated with the sole +// `fn`-item of this crate. The third condition is necessary in order +// to yield the weird state where the associated span of the `fn`-item +// does not actually cover all of the original source code of the +// `fn`-item (which is why we are calling it an "amputated" span +// here). +// +// Note that satisfying conditions 2 and 3 requires the use of the +// `--extern` compile flag. +// +// You might ask yourself: What code would do such a thing? The +// answer is: the #[tokio::main] attribute does *exactly* this (as +// well as injecting some other code into the `fn main` that it +// constructs). + +use std::process::Command; + +#[amputate_span::drop_first_token] +/* what the +hey */ async fn main() { + Command::new("git"); //~ ERROR [E0433] +} + +// (The /* ... */ comment in the above is not part of the original +// bug. It is just meant to illustrate one particular facet of the +// original non-ideal behavior, where we were transcribing the +// trailing comment as part of the emitted suggestion, for better or +// for worse.) + +#[allow(dead_code)] +mod inner { + use std::process::Command; + +#[amputate_span::drop_first_token] + /* another interesting + case */ async fn foo() { + Command::new("git"); //~ ERROR [E0433] + } +} diff --git a/tests/ui/proc-macro/amputate-span.rs b/tests/ui/proc-macro/amputate-span.rs new file mode 100644 index 000000000..894a06dd5 --- /dev/null +++ b/tests/ui/proc-macro/amputate-span.rs @@ -0,0 +1,65 @@ +// aux-build:amputate-span.rs +// run-rustfix +// edition:2018 +// compile-flags: --extern amputate_span + +// This test has been crafted to ensure the following things: +// +// 1. There's a resolution error that prompts the compiler to suggest +// adding a `use` item. +// +// 2. There are no `use` or `extern crate` items in the source +// code. In fact, there is only one item, the `fn main` +// declaration. +// +// 3. The single `fn main` declaration has an attribute attached to it +// that just deletes the first token from the given item. +// +// You need all of these conditions to hold in order to replicate the +// scenario that yielded issue 87613, where the compiler's suggestion +// looks like: +// +// ``` +// help: consider importing this struct +// | +// 47 | hey */ async use std::process::Command; +// | ++++++++++++++++++++++++++ +// ``` +// +// The first condition is necessary to force the compiler issue a +// suggestion. The second condition is necessary to force the +// suggestion to be issued at a span associated with the sole +// `fn`-item of this crate. The third condition is necessary in order +// to yield the weird state where the associated span of the `fn`-item +// does not actually cover all of the original source code of the +// `fn`-item (which is why we are calling it an "amputated" span +// here). +// +// Note that satisfying conditions 2 and 3 requires the use of the +// `--extern` compile flag. +// +// You might ask yourself: What code would do such a thing? The +// answer is: the #[tokio::main] attribute does *exactly* this (as +// well as injecting some other code into the `fn main` that it +// constructs). + +#[amputate_span::drop_first_token] +/* what the +hey */ async fn main() { + Command::new("git"); //~ ERROR [E0433] +} + +// (The /* ... */ comment in the above is not part of the original +// bug. It is just meant to illustrate one particular facet of the +// original non-ideal behavior, where we were transcribing the +// trailing comment as part of the emitted suggestion, for better or +// for worse.) + +#[allow(dead_code)] +mod inner { + #[amputate_span::drop_first_token] + /* another interesting + case */ async fn foo() { + Command::new("git"); //~ ERROR [E0433] + } +} diff --git a/tests/ui/proc-macro/amputate-span.stderr b/tests/ui/proc-macro/amputate-span.stderr new file mode 100644 index 000000000..ab4670411 --- /dev/null +++ b/tests/ui/proc-macro/amputate-span.stderr @@ -0,0 +1,25 @@ +error[E0433]: failed to resolve: use of undeclared type `Command` + --> $DIR/amputate-span.rs:49:5 + | +LL | Command::new("git"); + | ^^^^^^^ use of undeclared type `Command` + | +help: consider importing this struct + | +LL | use std::process::Command; + | + +error[E0433]: failed to resolve: use of undeclared type `Command` + --> $DIR/amputate-span.rs:63:9 + | +LL | Command::new("git"); + | ^^^^^^^ use of undeclared type `Command` + | +help: consider importing this struct + | +LL | use std::process::Command; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/proc-macro/append-impl.rs b/tests/ui/proc-macro/append-impl.rs new file mode 100644 index 000000000..a49384013 --- /dev/null +++ b/tests/ui/proc-macro/append-impl.rs @@ -0,0 +1,22 @@ +// run-pass +// aux-build:append-impl.rs + +#![allow(warnings)] + +#[macro_use] +extern crate append_impl; + +trait Append { + fn foo(&self); +} + +#[derive(PartialEq, + Append, + Eq)] +struct A { + inner: u32, +} + +fn main() { + A { inner: 3 }.foo(); +} diff --git a/tests/ui/proc-macro/attr-args.rs b/tests/ui/proc-macro/attr-args.rs new file mode 100644 index 000000000..764f507ab --- /dev/null +++ b/tests/ui/proc-macro/attr-args.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:attr-args.rs + +#![allow(warnings)] + +extern crate attr_args; +use attr_args::{attr_with_args, identity}; + +#[attr_with_args(text = "Hello, world!")] +fn foo() {} + +#[identity(fn main() { assert_eq!(foo(), "Hello, world!"); })] +struct Dummy; diff --git a/tests/ui/proc-macro/attr-cfg.rs b/tests/ui/proc-macro/attr-cfg.rs new file mode 100644 index 000000000..2aed9e2e8 --- /dev/null +++ b/tests/ui/proc-macro/attr-cfg.rs @@ -0,0 +1,27 @@ +// run-pass +// aux-build:attr-cfg.rs +// revisions: foo bar + +extern crate attr_cfg; +use attr_cfg::attr_cfg; + +#[attr_cfg] +fn outer() -> u8 { + #[cfg(foo)] + fn inner() -> u8 { 1 } + + #[cfg(bar)] + fn inner() -> u8 { 2 } + + inner() +} + +#[cfg(foo)] +fn main() { + assert_eq!(outer(), 1); +} + +#[cfg(bar)] +fn main() { + assert_eq!(outer(), 2); +} diff --git a/tests/ui/proc-macro/attr-complex-fn.rs b/tests/ui/proc-macro/attr-complex-fn.rs new file mode 100644 index 000000000..47734c94f --- /dev/null +++ b/tests/ui/proc-macro/attr-complex-fn.rs @@ -0,0 +1,26 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +#![feature(stmt_expr_attributes)] +#![feature(custom_inner_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +trait MyTrait {} +struct MyStruct; + +#[print_attr] +fn foo>>() {} + +impl MyTrait for MyStruct<{true}> { + #![print_attr] + #![rustc_dummy] +} + +fn main() {} diff --git a/tests/ui/proc-macro/attr-complex-fn.stdout b/tests/ui/proc-macro/attr-complex-fn.stdout new file mode 100644 index 000000000..b12eb587f --- /dev/null +++ b/tests/ui/proc-macro/attr-complex-fn.stdout @@ -0,0 +1,171 @@ +PRINT-ATTR INPUT (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >> > () {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/attr-complex-fn.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/attr-complex-fn.rs:19:4: 19:7 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:7: 19:8 (#0), + }, + Ident { + ident: "T", + span: $DIR/attr-complex-fn.rs:19:8: 19:9 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:9: 19:10 (#0), + }, + Ident { + ident: "MyTrait", + span: $DIR/attr-complex-fn.rs:19:11: 19:18 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:18: 19:19 (#0), + }, + Ident { + ident: "MyStruct", + span: $DIR/attr-complex-fn.rs:19:19: 19:27 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:27: 19:28 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/attr-complex-fn.rs:19:30: 19:34 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:19:28: 19:36 (#0), + }, + Punct { + ch: '>', + spacing: Joint, + span: $DIR/attr-complex-fn.rs:19:36: 19:37 (#0), + }, + Punct { + ch: '>', + spacing: Joint, + span: $DIR/attr-complex-fn.rs:19:37: 19:38 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:19:38: 19:39 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/attr-complex-fn.rs:19:39: 19:41 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-complex-fn.rs:19:42: 19:44 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { #! [rustc_dummy] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/attr-complex-fn.rs:21:1: 21:5 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:5: 21:6 (#0), + }, + Ident { + ident: "T", + span: $DIR/attr-complex-fn.rs:21:6: 21:7 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:7: 21:8 (#0), + }, + Ident { + ident: "MyTrait", + span: $DIR/attr-complex-fn.rs:21:9: 21:16 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:16: 21:17 (#0), + }, + Ident { + ident: "T", + span: $DIR/attr-complex-fn.rs:21:17: 21:18 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:18: 21:19 (#0), + }, + Ident { + ident: "for", + span: $DIR/attr-complex-fn.rs:21:20: 21:23 (#0), + }, + Ident { + ident: "MyStruct", + span: $DIR/attr-complex-fn.rs:21:24: 21:32 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:32: 21:33 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/attr-complex-fn.rs:21:34: 21:38 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:21:33: 21:39 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:21:39: 21:40 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/attr-complex-fn.rs:23:5: 23:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-complex-fn.rs:23:6: 23:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-complex-fn.rs:23:8: 23:19 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:23:7: 23:20 (#0), + }, + ], + span: $DIR/attr-complex-fn.rs:21:41: 24:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/attr-invalid-exprs.rs b/tests/ui/proc-macro/attr-invalid-exprs.rs new file mode 100644 index 000000000..9dcffc340 --- /dev/null +++ b/tests/ui/proc-macro/attr-invalid-exprs.rs @@ -0,0 +1,28 @@ +//! Attributes producing expressions in invalid locations + +// aux-build:attr-stmt-expr.rs + +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] + +extern crate attr_stmt_expr; +use attr_stmt_expr::{duplicate, no_output}; + +fn main() { + let _ = #[no_output] "Hello, world!"; + //~^ ERROR expected expression, found end of macro arguments + + let _ = #[duplicate] "Hello, world!"; + //~^ ERROR macro expansion ignores token `,` and any following + + let _ = { + #[no_output] + "Hello, world!" + }; + + let _ = { + #[duplicate] + //~^ ERROR macro expansion ignores token `,` and any following + "Hello, world!" + }; +} diff --git a/tests/ui/proc-macro/attr-invalid-exprs.stderr b/tests/ui/proc-macro/attr-invalid-exprs.stderr new file mode 100644 index 000000000..f96939bb6 --- /dev/null +++ b/tests/ui/proc-macro/attr-invalid-exprs.stderr @@ -0,0 +1,32 @@ +error: expected expression, found end of macro arguments + --> $DIR/attr-invalid-exprs.rs:12:13 + | +LL | let _ = #[no_output] "Hello, world!"; + | ^^^^^^^^^^^^ + +error: macro expansion ignores token `,` and any following + --> $DIR/attr-invalid-exprs.rs:15:13 + | +LL | let _ = #[duplicate] "Hello, world!"; + | ^^^^^^^^^^^^ caused by the macro expansion here + | + = note: the usage of `duplicate!` is likely invalid in expression context +help: you might be missing a semicolon here + | +LL | let _ = #[duplicate]; "Hello, world!"; + | + + +error: macro expansion ignores token `,` and any following + --> $DIR/attr-invalid-exprs.rs:24:9 + | +LL | #[duplicate] + | ^^^^^^^^^^^^ caused by the macro expansion here + | + = note: the usage of `duplicate!` is likely invalid in expression context +help: you might be missing a semicolon here + | +LL | #[duplicate]; + | + + +error: aborting due to 3 previous errors + diff --git a/tests/ui/proc-macro/attr-on-trait.rs b/tests/ui/proc-macro/attr-on-trait.rs new file mode 100644 index 000000000..e0edee630 --- /dev/null +++ b/tests/ui/proc-macro/attr-on-trait.rs @@ -0,0 +1,19 @@ +// run-pass +// aux-build:attr-on-trait.rs + +extern crate attr_on_trait; + +use attr_on_trait::foo; + +trait Foo { + #[foo] + fn foo() {} +} + +impl Foo for i32 { + fn foo(&self) {} +} + +fn main() { + 3i32.foo(); +} diff --git a/tests/ui/proc-macro/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/attr-stmt-expr-rpass.rs new file mode 100644 index 000000000..16b8fabfc --- /dev/null +++ b/tests/ui/proc-macro/attr-stmt-expr-rpass.rs @@ -0,0 +1,36 @@ +// run-pass +// aux-build:attr-stmt-expr-rpass.rs + +#![feature(stmt_expr_attributes, proc_macro_hygiene)] + +extern crate attr_stmt_expr_rpass as attr_stmt_expr; +use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr, + no_output, noop}; + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_print_expr] + println!("{}", string) +} + +fn main() { + #[expect_let] + let string = "Hello, world!"; + + #[expect_print_stmt] + println!("{}", string); + + let _: () = { + #[no_output] + "Hello, world!" + }; + + let _: &'static str = #[noop] "Hello, world!"; + + let _: &'static str = { + #[noop] "Hello, world!" + }; + + #[expect_expr] + print_str("string") +} diff --git a/tests/ui/proc-macro/attr-stmt-expr.rs b/tests/ui/proc-macro/attr-stmt-expr.rs new file mode 100644 index 000000000..0403684cd --- /dev/null +++ b/tests/ui/proc-macro/attr-stmt-expr.rs @@ -0,0 +1,66 @@ +// aux-build:attr-stmt-expr.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![feature(proc_macro_hygiene)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; +extern crate test_macros; +extern crate attr_stmt_expr; + +use test_macros::print_attr; +use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr}; + +// We don't use `std::println` so that we avoid loading hygiene +// information from libstd, which would affect the SyntaxContext ids +macro_rules! my_macro { + ($($tt:tt)*) => { () } +} + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_my_macro_expr] + //~^ ERROR attributes on expressions are experimental + //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + my_macro!("{}", string) +} + +macro_rules! make_stmt { + ($stmt:stmt) => { + #[print_attr] + #[rustc_dummy] + $stmt + } +} + +macro_rules! second_make_stmt { + ($stmt:stmt) => { + make_stmt!($stmt); + } +} + +fn main() { + make_stmt!(struct Foo {}); + + #[print_attr] + #[expect_let] + let string = "Hello, world!"; + + #[print_attr] + #[expect_my_macro_stmt] + my_macro!("{}", string); + + #[print_attr] + second_make_stmt!(#[allow(dead_code)] struct Bar {}); + + #[print_attr] + #[rustc_dummy] + struct Other {} + + #[expect_expr] + //~^ ERROR attributes on expressions are experimental + //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + print_str("string") +} diff --git a/tests/ui/proc-macro/attr-stmt-expr.stderr b/tests/ui/proc-macro/attr-stmt-expr.stderr new file mode 100644 index 000000000..56178259d --- /dev/null +++ b/tests/ui/proc-macro/attr-stmt-expr.stderr @@ -0,0 +1,21 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/attr-stmt-expr.rs:24:5 + | +LL | #[expect_my_macro_expr] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/attr-stmt-expr.rs:62:5 + | +LL | #[expect_expr] + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/attr-stmt-expr.stdout b/tests/ui/proc-macro/attr-stmt-expr.stdout new file mode 100644 index 000000000..f9b2305c7 --- /dev/null +++ b/tests/ui/proc-macro/attr-stmt-expr.stdout @@ -0,0 +1,274 @@ +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#8), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#8), + }, + ], + span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#8), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:45:16: 45:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/attr-stmt-expr.rs:45:23: 45:26 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:45:27: 45:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:48:5: 48:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_let", + span: $DIR/attr-stmt-expr.rs:48:7: 48:17 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:48:6: 48:18 (#0), + }, + Ident { + ident: "let", + span: $DIR/attr-stmt-expr.rs:49:5: 49:8 (#0), + }, + Ident { + ident: "string", + span: $DIR/attr-stmt-expr.rs:49:9: 49:15 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:49:16: 49:17 (#0), + }, + Literal { + kind: Str, + symbol: "Hello, world!", + suffix: None, + span: $DIR/attr-stmt-expr.rs:49:18: 49:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:49:33: 49:34 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:52:5: 52:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_my_macro_stmt", + span: $DIR/attr-stmt-expr.rs:52:7: 52:27 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:52:6: 52:28 (#0), + }, + Ident { + ident: "my_macro", + span: $DIR/attr-stmt-expr.rs:53:5: 53:13 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:53:13: 53:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "{}", + suffix: None, + span: $DIR/attr-stmt-expr.rs:53:15: 53:19 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:53:19: 53:20 (#0), + }, + Ident { + ident: "string", + span: $DIR/attr-stmt-expr.rs:53:21: 53:27 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:53:14: 53:28 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:53:28: 53:29 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_make_stmt", + span: $DIR/attr-stmt-expr.rs:56:5: 56:21 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:21: 56:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:22: 56:57 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:57: 56:58 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#29), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#29), + }, + ], + span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#29), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:59:5: 59:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:59:7: 59:18 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:59:6: 59:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:60:5: 60:11 (#0), + }, + Ident { + ident: "Other", + span: $DIR/attr-stmt-expr.rs:60:12: 60:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:60:18: 60:20 (#0), + }, +] diff --git a/tests/ui/proc-macro/attribute-after-derive.rs b/tests/ui/proc-macro/attribute-after-derive.rs new file mode 100644 index 000000000..0f0f27bff --- /dev/null +++ b/tests/ui/proc-macro/attribute-after-derive.rs @@ -0,0 +1,28 @@ +// Macro attributes are allowed after `#[derive]` and +// `#[derive]` fully configures the item for following attributes. + +// check-pass +// compile-flags: -Z span-debug +// aux-build: test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_attr] +#[derive(Print)] +struct AttributeDerive { + #[cfg(FALSE)] + field: u8, +} + +#[derive(Print)] +#[print_attr] +struct DeriveAttribute { + #[cfg(FALSE)] + field: u8, +} + +fn main() {} diff --git a/tests/ui/proc-macro/attribute-after-derive.stdout b/tests/ui/proc-macro/attribute-after-derive.stdout new file mode 100644 index 000000000..1b17d6047 --- /dev/null +++ b/tests/ui/proc-macro/attribute-after-derive.stdout @@ -0,0 +1,192 @@ +PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "derive", + span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "Print", + span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), + }, + Ident { + ident: "AttributeDerive", + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0), + }, + Ident { + ident: "field", + span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0), + }, + Ident { + ident: "u8", + span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive {} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0), + }, + Ident { + ident: "AttributeDerive", + span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute {} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:22:1: 22:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_attr", + span: $DIR/attribute-after-derive.rs:22:3: 22:13 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:22:2: 22:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0), + }, + Ident { + ident: "DeriveAttribute", + span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:24:5: 24:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/attribute-after-derive.rs:24:7: 24:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:24:10: 24:17 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:24:6: 24:18 (#0), + }, + Ident { + ident: "field", + span: $DIR/attribute-after-derive.rs:25:5: 25:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:25:10: 25:11 (#0), + }, + Ident { + ident: "u8", + span: $DIR/attribute-after-derive.rs:25:12: 25:14 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attribute-after-derive.rs:25:14: 25:15 (#0), + }, + ], + span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/attribute-spans-preserved.rs b/tests/ui/proc-macro/attribute-spans-preserved.rs new file mode 100644 index 000000000..c01fce905 --- /dev/null +++ b/tests/ui/proc-macro/attribute-spans-preserved.rs @@ -0,0 +1,10 @@ +// aux-build:attribute-spans-preserved.rs + +extern crate attribute_spans_preserved as foo; + +use foo::foo; + +#[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types +#[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types +fn main() { +} diff --git a/tests/ui/proc-macro/attribute-spans-preserved.stderr b/tests/ui/proc-macro/attribute-spans-preserved.stderr new file mode 100644 index 000000000..193482a42 --- /dev/null +++ b/tests/ui/proc-macro/attribute-spans-preserved.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/attribute-spans-preserved.rs:7:23 + | +LL | #[ foo ( let y: u32 = "z"; ) ] + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-spans-preserved.rs:8:23 + | +LL | #[ bar { let x: u32 = "y"; } ] + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/attribute-spans-preserved.stdout b/tests/ui/proc-macro/attribute-spans-preserved.stdout new file mode 100644 index 000000000..cf9a97491 --- /dev/null +++ b/tests/ui/proc-macro/attribute-spans-preserved.stdout @@ -0,0 +1 @@ +fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } } diff --git a/tests/ui/proc-macro/attribute-with-error.rs b/tests/ui/proc-macro/attribute-with-error.rs new file mode 100644 index 000000000..aaa6c07dd --- /dev/null +++ b/tests/ui/proc-macro/attribute-with-error.rs @@ -0,0 +1,42 @@ +// aux-build:test-macros.rs + +#![feature(custom_inner_attributes)] + +#[macro_use] +extern crate test_macros; + +#[recollect_attr] +fn test1() { + let a: i32 = "foo"; + //~^ ERROR: mismatched types + let b: i32 = "f'oo"; + //~^ ERROR: mismatched types +} + +fn test2() { + #![recollect_attr] + + // FIXME: should have a type error here and assert it works but it doesn't +} + +trait A { + // FIXME: should have a #[recollect_attr] attribute here and assert that it works + fn foo(&self) { + let a: i32 = "foo"; + //~^ ERROR: mismatched types + } +} + +struct B; + +impl A for B { + #[recollect_attr] + fn foo(&self) { + let a: i32 = "foo"; + //~^ ERROR: mismatched types + } +} + +#[recollect_attr] +fn main() { +} diff --git a/tests/ui/proc-macro/attribute-with-error.stderr b/tests/ui/proc-macro/attribute-with-error.stderr new file mode 100644 index 000000000..7f3a7e670 --- /dev/null +++ b/tests/ui/proc-macro/attribute-with-error.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:10:18 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:12:18 + | +LL | let b: i32 = "f'oo"; + | --- ^^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:25:22 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/attribute-with-error.rs:35:22 + | +LL | let a: i32 = "foo"; + | --- ^^^^^ expected `i32`, found `&str` + | | + | expected due to this + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/attribute.rs b/tests/ui/proc-macro/attribute.rs new file mode 100644 index 000000000..9e40e4d9b --- /dev/null +++ b/tests/ui/proc-macro/attribute.rs @@ -0,0 +1,73 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive] //~ ERROR malformed `proc_macro_derive` attribute +pub fn foo1(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive = ""] //~ ERROR malformed `proc_macro_derive` attribute +pub fn foo2(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d3, a, b)] +//~^ ERROR attribute must have either one or two arguments +pub fn foo3(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d4, attributes(a), b)] +//~^ ERROR attribute must have either one or two arguments +pub fn foo4(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive("a")] +//~^ ERROR: not a meta item +pub fn foo5(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d6 = "")] +//~^ ERROR: must only be one word +pub fn foo6(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(m::d7)] +//~^ ERROR: must only be one word +pub fn foo7(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d8(a))] +//~^ ERROR: must only be one word +pub fn foo8(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(self)] +//~^ ERROR: `self` cannot be a name of derive macro +pub fn foo9(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(PartialEq)] // OK +pub fn foo10(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d11, a)] +//~^ ERROR: second argument must be `attributes` +//~| ERROR: attribute must be of form: `attributes(foo, bar)` +pub fn foo11(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d12, attributes)] +//~^ ERROR: attribute must be of form: `attributes(foo, bar)` +pub fn foo12(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d13, attributes("a"))] +//~^ ERROR: attribute must be a meta item, not a literal +pub fn foo13(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d14, attributes(a = ""))] +//~^ ERROR: attribute must only be a single word +pub fn foo14(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d15, attributes(m::a))] +//~^ ERROR: attribute must only be a single word +pub fn foo15(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d16, attributes(a(b)))] +//~^ ERROR: attribute must only be a single word +pub fn foo16(input: TokenStream) -> TokenStream { input } + +#[proc_macro_derive(d17, attributes(self))] +//~^ ERROR: `self` cannot be a name of derive helper attribute +pub fn foo17(input: TokenStream) -> TokenStream { input } diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr new file mode 100644 index 000000000..3269aaf7f --- /dev/null +++ b/tests/ui/proc-macro/attribute.stderr @@ -0,0 +1,104 @@ +error: malformed `proc_macro_derive` attribute input + --> $DIR/attribute.rs:9:1 + | +LL | #[proc_macro_derive] + | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + +error: malformed `proc_macro_derive` attribute input + --> $DIR/attribute.rs:12:1 + | +LL | #[proc_macro_derive = ""] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:15:1 + | +LL | #[proc_macro_derive(d3, a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute must have either one or two arguments + --> $DIR/attribute.rs:19:1 + | +LL | #[proc_macro_derive(d4, attributes(a), b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: not a meta item + --> $DIR/attribute.rs:23:21 + | +LL | #[proc_macro_derive("a")] + | ^^^ + +error: must only be one word + --> $DIR/attribute.rs:27:21 + | +LL | #[proc_macro_derive(d6 = "")] + | ^^^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:31:21 + | +LL | #[proc_macro_derive(m::d7)] + | ^^^^^ + +error: must only be one word + --> $DIR/attribute.rs:35:21 + | +LL | #[proc_macro_derive(d8(a))] + | ^^^^^ + +error: `self` cannot be a name of derive macro + --> $DIR/attribute.rs:39:21 + | +LL | #[proc_macro_derive(self)] + | ^^^^ + +error: second argument must be `attributes` + --> $DIR/attribute.rs:46:26 + | +LL | #[proc_macro_derive(d11, a)] + | ^ + +error: attribute must be of form: `attributes(foo, bar)` + --> $DIR/attribute.rs:46:26 + | +LL | #[proc_macro_derive(d11, a)] + | ^ + +error: attribute must be of form: `attributes(foo, bar)` + --> $DIR/attribute.rs:51:26 + | +LL | #[proc_macro_derive(d12, attributes)] + | ^^^^^^^^^^ + +error: attribute must be a meta item, not a literal + --> $DIR/attribute.rs:55:37 + | +LL | #[proc_macro_derive(d13, attributes("a"))] + | ^^^ + +error: attribute must only be a single word + --> $DIR/attribute.rs:59:37 + | +LL | #[proc_macro_derive(d14, attributes(a = ""))] + | ^^^^^^ + +error: attribute must only be a single word + --> $DIR/attribute.rs:63:37 + | +LL | #[proc_macro_derive(d15, attributes(m::a))] + | ^^^^ + +error: attribute must only be a single word + --> $DIR/attribute.rs:67:37 + | +LL | #[proc_macro_derive(d16, attributes(a(b)))] + | ^^^^ + +error: `self` cannot be a name of derive helper attribute + --> $DIR/attribute.rs:71:37 + | +LL | #[proc_macro_derive(d17, attributes(self))] + | ^^^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/proc-macro/attributes-included.rs b/tests/ui/proc-macro/attributes-included.rs new file mode 100644 index 000000000..95e8e10a3 --- /dev/null +++ b/tests/ui/proc-macro/attributes-included.rs @@ -0,0 +1,22 @@ +// aux-build:attributes-included.rs +// check-pass + +#![warn(unused)] + +extern crate attributes_included; + +use attributes_included::*; + +#[bar] +#[inline] +/// doc +#[foo] +#[inline] +/// doc +fn foo() { + let a: i32 = "foo"; //~ WARN: unused variable +} + +fn main() { + foo() +} diff --git a/tests/ui/proc-macro/attributes-included.stderr b/tests/ui/proc-macro/attributes-included.stderr new file mode 100644 index 000000000..72c88d5d8 --- /dev/null +++ b/tests/ui/proc-macro/attributes-included.stderr @@ -0,0 +1,15 @@ +warning: unused variable: `a` + --> $DIR/attributes-included.rs:17:9 + | +LL | let a: i32 = "foo"; + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/attributes-included.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/tests/ui/proc-macro/attributes-on-definitions.rs b/tests/ui/proc-macro/attributes-on-definitions.rs new file mode 100644 index 000000000..c0733c8b4 --- /dev/null +++ b/tests/ui/proc-macro/attributes-on-definitions.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:attributes-on-definitions.rs + +#![forbid(unsafe_code)] + +extern crate attributes_on_definitions; + +attributes_on_definitions::with_attrs!(); +//~^ WARN use of deprecated +// No errors about the use of unstable and unsafe code inside the macro. + +fn main() {} diff --git a/tests/ui/proc-macro/attributes-on-definitions.stderr b/tests/ui/proc-macro/attributes-on-definitions.stderr new file mode 100644 index 000000000..c63dd0011 --- /dev/null +++ b/tests/ui/proc-macro/attributes-on-definitions.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated macro `attributes_on_definitions::with_attrs`: test + --> $DIR/attributes-on-definitions.rs:8:1 + | +LL | attributes_on_definitions::with_attrs!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/proc-macro/attributes-on-modules-fail.rs b/tests/ui/proc-macro/attributes-on-modules-fail.rs new file mode 100644 index 000000000..6c30e8f4f --- /dev/null +++ b/tests/ui/proc-macro/attributes-on-modules-fail.rs @@ -0,0 +1,46 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[identity_attr] +mod m { + pub struct X; + + type A = Y; //~ ERROR cannot find type `Y` in this scope +} + +struct Y; +type A = X; //~ ERROR cannot find type `X` in this scope + +#[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s +mod n {} + +#[empty_attr] +mod module; //~ ERROR non-inline modules in proc macro input are unstable + +#[empty_attr] +mod outer { + mod inner; //~ ERROR non-inline modules in proc macro input are unstable + + mod inner_inline {} // OK +} + +#[derive(Empty)] +struct S { + field: [u8; { + #[path = "outer/inner.rs"] + mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner_inline {} // OK + 0 + }] +} + +#[identity_attr] +fn f() { + #[path = "outer/inner.rs"] + mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner_inline {} // OK +} + +fn main() {} diff --git a/tests/ui/proc-macro/attributes-on-modules-fail.stderr b/tests/ui/proc-macro/attributes-on-modules-fail.stderr new file mode 100644 index 000000000..bb6cbb698 --- /dev/null +++ b/tests/ui/proc-macro/attributes-on-modules-fail.stderr @@ -0,0 +1,70 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/attributes-on-modules-fail.rs:16:1 + | +LL | #[derive(Copy)] + | ^^^^^^^^^^^^^^^ not applicable here +LL | mod n {} + | -------- not a `struct`, `enum` or `union` + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:20:1 + | +LL | mod module; + | ^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:24:5 + | +LL | mod inner; + | ^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:33:9 + | +LL | mod inner; + | ^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/attributes-on-modules-fail.rs:42:5 + | +LL | mod inner; + | ^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0412]: cannot find type `Y` in this scope + --> $DIR/attributes-on-modules-fail.rs:10:14 + | +LL | type A = Y; + | ^ not found in this scope + | +help: consider importing this struct + | +LL | use Y; + | + +error[E0412]: cannot find type `X` in this scope + --> $DIR/attributes-on-modules-fail.rs:14:10 + | +LL | type A = X; + | ^ not found in this scope + | +help: consider importing this struct + | +LL | use m::X; + | + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0412, E0658, E0774. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/proc-macro/attributes-on-modules.rs b/tests/ui/proc-macro/attributes-on-modules.rs new file mode 100644 index 000000000..6c73b0bf1 --- /dev/null +++ b/tests/ui/proc-macro/attributes-on-modules.rs @@ -0,0 +1,19 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[identity_attr] +mod m { + pub struct S; +} + +#[identity_attr] +fn f() { + mod m {} +} + +fn main() { + let s = m::S; +} diff --git a/tests/ui/proc-macro/auxiliary/add-impl.rs b/tests/ui/proc-macro/auxiliary/add-impl.rs new file mode 100644 index 000000000..741e64875 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/add-impl.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AddImpl)] +// #[cfg(proc_macro)] +pub fn derive(input: TokenStream) -> TokenStream { + "impl B { + fn foo(&self) {} + } + + fn foo() {} + + mod bar { pub fn foo() {} } + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/amputate-span.rs b/tests/ui/proc-macro/auxiliary/amputate-span.rs new file mode 100644 index 000000000..1a82119ae --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/amputate-span.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn drop_first_token(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.is_empty()); + input.into_iter().skip(1).collect() +} diff --git a/tests/ui/proc-macro/auxiliary/api/cmp.rs b/tests/ui/proc-macro/auxiliary/api/cmp.rs new file mode 100644 index 000000000..5784a6e5d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/api/cmp.rs @@ -0,0 +1,21 @@ +use proc_macro::{LineColumn, Punct, Spacing}; + +pub fn test() { + test_line_column_ord(); + test_punct_eq(); +} + +fn test_line_column_ord() { + let line0_column0 = LineColumn { line: 0, column: 0 }; + let line0_column1 = LineColumn { line: 0, column: 1 }; + let line1_column0 = LineColumn { line: 1, column: 0 }; + assert!(line0_column0 < line0_column1); + assert!(line0_column1 < line1_column0); +} + +fn test_punct_eq() { + let colon_alone = Punct::new(':', Spacing::Alone); + assert_eq!(colon_alone, ':'); + let colon_joint = Punct::new(':', Spacing::Joint); + assert_eq!(colon_joint, ':'); +} diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs new file mode 100644 index 000000000..739c25132 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/api/mod.rs @@ -0,0 +1,24 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "proc_macro_api_tests"] +#![feature(proc_macro_span)] +#![deny(dead_code)] // catch if a test function is never called + +extern crate proc_macro; + +mod cmp; +mod parse; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn run(input: TokenStream) -> TokenStream { + assert!(input.is_empty()); + + cmp::test(); + parse::test(); + + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs new file mode 100644 index 000000000..27391f831 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/api/parse.rs @@ -0,0 +1,55 @@ +// ignore-tidy-linelength + +use proc_macro::Literal; + +pub fn test() { + test_display_literal(); + test_parse_literal(); +} + +fn test_display_literal() { + assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10"); + assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize"); + assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0"); + assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32"); + assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0"); + assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64"); + assert_eq!( + Literal::f64_unsuffixed(1e100).to_string(), + "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", + ); + + assert_eq!( + Literal::string("a \t ⤠' \" \u{1}").to_string(), + "\"a \\t ⤠' \\\" \\u{1}\"", + ); + assert_eq!(Literal::character('a').to_string(), "'a'"); + assert_eq!(Literal::character('\t').to_string(), "'\\t'"); + assert_eq!(Literal::character('â¤').to_string(), "'â¤'"); + assert_eq!(Literal::character('\'').to_string(), "'\\''"); + assert_eq!(Literal::character('"').to_string(), "'\"'"); + assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'"); +} + +fn test_parse_literal() { + assert_eq!("1".parse::().unwrap().to_string(), "1"); + assert_eq!("1.0".parse::().unwrap().to_string(), "1.0"); + assert_eq!("'a'".parse::().unwrap().to_string(), "'a'"); + assert_eq!("\"\n\"".parse::().unwrap().to_string(), "\"\n\""); + assert_eq!("b\"\"".parse::().unwrap().to_string(), "b\"\""); + assert_eq!("r##\"\"##".parse::().unwrap().to_string(), "r##\"\"##"); + assert_eq!("10ulong".parse::().unwrap().to_string(), "10ulong"); + assert_eq!("-10ulong".parse::().unwrap().to_string(), "-10ulong"); + + assert!("true".parse::().is_err()); + assert!(".8".parse::().is_err()); + assert!("0 1".parse::().is_err()); + assert!("'a".parse::().is_err()); + assert!(" 0".parse::().is_err()); + assert!("0 ".parse::().is_err()); + assert!("/* comment */0".parse::().is_err()); + assert!("0/* comment */".parse::().is_err()); + assert!("0// comment".parse::().is_err()); + assert!("- 10".parse::().is_err()); + assert!("-'x'".parse::().is_err()); +} diff --git a/tests/ui/proc-macro/auxiliary/append-impl.rs b/tests/ui/proc-macro/auxiliary/append-impl.rs new file mode 100644 index 000000000..b032b1337 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/append-impl.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Append)] +pub fn derive_a(input: TokenStream) -> TokenStream { + "impl Append for A { + fn foo(&self) {} + } + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/assert-span-pos.rs b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs new file mode 100644 index 000000000..455c5c7c3 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_diagnostic, proc_macro_span)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span}; + +fn lit_span(tt: TokenTree) -> (Span, String) { + match tt { + TokenTree::Literal(..) | + TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()), + _ => panic!("expected a literal in token tree, got: {:?}", tt) + } +} + +#[proc_macro] +pub fn assert_span_pos(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let (sp1, str1) = lit_span(tokens.next().expect("first argument")); + let _ = tokens.next(); + let (_sp2, str2) = lit_span(tokens.next().expect("second argument")); + + let line: usize = str1.parse().unwrap(); + let col: usize = str2.parse().unwrap(); + + let sp1s = sp1.start(); + if (line, col) != (sp1s.line, sp1s.column) { + let msg = format!("line/column mismatch: ({}, {}) != ({}, {})", line, col, + sp1s.line, sp1s.column); + sp1.error(msg).emit(); + } + + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/attr-args.rs b/tests/ui/proc-macro/auxiliary/attr-args.rs new file mode 100644 index 000000000..5f76a4484 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attr-args.rs @@ -0,0 +1,28 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream { + let args = args.to_string(); + + assert_eq!(args, r#"text = "Hello, world!""#); + + let input = input.to_string(); + + assert_eq!(input, "fn foo() {}"); + + r#" + fn foo() -> &'static str { "Hello, world!" } + "#.parse().unwrap() +} + +#[proc_macro_attribute] +pub fn identity(attr_args: TokenStream, _: TokenStream) -> TokenStream { + attr_args +} diff --git a/tests/ui/proc-macro/auxiliary/attr-cfg.rs b/tests/ui/proc-macro/auxiliary/attr-cfg.rs new file mode 100644 index 000000000..2f0054cc1 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attr-cfg.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream { + let input_str = input.to_string(); + + assert_eq!(input_str, "fn outer() -> u8 +{ + #[cfg(foo)] fn inner() -> u8 { 1 } #[cfg(bar)] fn inner() -> u8 { 2 } + inner() +}"); + + input +} diff --git a/tests/ui/proc-macro/auxiliary/attr-on-trait.rs b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs new file mode 100644 index 000000000..3787b8eec --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn foo(attr: TokenStream, item: TokenStream) -> TokenStream { + drop(attr); + assert_eq!(item.to_string(), "fn foo() {}"); + "fn foo(&self);".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs new file mode 100644 index 000000000..5b386b46b --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -0,0 +1,51 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println! (\"{}\", string) ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "print_str(\"string\")"); + item +} + +#[proc_macro_attribute] +pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "println! (\"{}\", string)"); + item +} + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() + +} + +#[proc_macro_attribute] +pub fn noop(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + item +} diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs new file mode 100644 index 000000000..4d6dc06b4 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -0,0 +1,49 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_my_macro_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "my_macro! (\"{}\", string) ;"); + item +} + +#[proc_macro_attribute] +pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "print_str(\"string\")"); + item +} + +#[proc_macro_attribute] +pub fn expect_my_macro_expr(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert_eq!(item.to_string(), "my_macro! (\"{}\", string)"); + item +} + +#[proc_macro_attribute] +pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + format!("{}, {}", item, item).parse().unwrap() +} + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs new file mode 100644 index 000000000..4d3279584 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs @@ -0,0 +1,35 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn foo(attr: TokenStream, f: TokenStream) -> TokenStream { + let mut tokens = f.into_iter(); + assert_eq!(tokens.next().unwrap().to_string(), "#"); + let next_attr = match tokens.next().unwrap() { + TokenTree::Group(g) => g, + _ => panic!(), + }; + + let fn_tok = tokens.next().unwrap(); + let ident_tok = tokens.next().unwrap(); + let args_tok = tokens.next().unwrap(); + let body = tokens.next().unwrap(); + + let new_body = attr.into_iter() + .chain(next_attr.stream().into_iter().skip(1)); + + let tokens = vec![ + fn_tok, + ident_tok, + args_tok, + Group::new(Delimiter::Brace, new_body.collect()).into(), + ].into_iter().collect::(); + println!("{}", tokens); + return tokens +} diff --git a/tests/ui/proc-macro/auxiliary/attributes-included.rs b/tests/ui/proc-macro/auxiliary/attributes-included.rs new file mode 100644 index 000000000..a5eb40b28 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attributes-included.rs @@ -0,0 +1,150 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group}; + +#[proc_macro_attribute] +pub fn foo(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.is_empty()); + let input = input.into_iter().collect::>(); + { + let mut cursor = &input[..]; + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_foo(&mut cursor); + assert!(cursor.is_empty()); + } + fold_stream(input.into_iter().collect()) +} + +#[proc_macro_attribute] +pub fn bar(attr: TokenStream, input: TokenStream) -> TokenStream { + assert!(attr.is_empty()); + let input = input.into_iter().collect::>(); + { + let mut cursor = &input[..]; + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_invoc(&mut cursor); + assert_inline(&mut cursor); + assert_doc(&mut cursor); + assert_foo(&mut cursor); + assert!(cursor.is_empty()); + } + input.into_iter().collect() +} + +fn assert_inline(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'), + _ => panic!("expected '#' char"), + } + match &slice[1] { + TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket), + _ => panic!("expected brackets"), + } + *slice = &slice[2..]; +} + +fn assert_doc(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Punct(tt) => { + assert_eq!(tt.as_char(), '#'); + assert_eq!(tt.spacing(), Spacing::Alone); + } + _ => panic!("expected #"), + } + let inner = match &slice[1] { + TokenTree::Group(tt) => { + assert_eq!(tt.delimiter(), Delimiter::Bracket); + tt.stream() + } + _ => panic!("expected brackets"), + }; + let tokens = inner.into_iter().collect::>(); + let tokens = &tokens[..]; + + if tokens.len() != 3 { + panic!("expected three tokens in doc") + } + + match &tokens[0] { + TokenTree::Ident(tt) => assert_eq!("doc", &*tt.to_string()), + _ => panic!("expected `doc`"), + } + match &tokens[1] { + TokenTree::Punct(tt) => { + assert_eq!(tt.as_char(), '='); + assert_eq!(tt.spacing(), Spacing::Alone); + } + _ => panic!("expected equals"), + } + match tokens[2] { + TokenTree::Literal(_) => {} + _ => panic!("expected literal"), + } + + *slice = &slice[2..]; +} + +fn assert_invoc(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'), + _ => panic!("expected '#' char"), + } + match &slice[1] { + TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket), + _ => panic!("expected brackets"), + } + *slice = &slice[2..]; +} + +fn assert_foo(slice: &mut &[TokenTree]) { + match &slice[0] { + TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "fn"), + _ => panic!("expected fn"), + } + match &slice[1] { + TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "foo"), + _ => panic!("expected foo"), + } + match &slice[2] { + TokenTree::Group(tt) => { + assert_eq!(tt.delimiter(), Delimiter::Parenthesis); + assert!(tt.stream().is_empty()); + } + _ => panic!("expected parens"), + } + match &slice[3] { + TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Brace), + _ => panic!("expected braces"), + } + *slice = &slice[4..]; +} + +fn fold_stream(input: TokenStream) -> TokenStream { + input.into_iter().map(fold_tree).collect() +} + +fn fold_tree(input: TokenTree) -> TokenTree { + match input { + TokenTree::Group(b) => { + TokenTree::Group(Group::new(b.delimiter(), fold_stream(b.stream()))) + } + TokenTree::Punct(b) => TokenTree::Punct(b), + TokenTree::Ident(a) => TokenTree::Ident(a), + TokenTree::Literal(a) => { + if a.to_string() != "\"foo\"" { + TokenTree::Literal(a) + } else { + TokenTree::Literal(Literal::i32_unsuffixed(3)) + } + } + } +} diff --git a/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs new file mode 100644 index 000000000..93a339840 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![feature(allow_internal_unsafe)] +#![feature(allow_internal_unstable)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[allow_internal_unstable(proc_macro_internals)] +#[allow_internal_unsafe] +#[deprecated(since = "1.0.0", note = "test")] +pub fn with_attrs(_: TokenStream) -> TokenStream { + " + extern crate proc_macro; + use ::proc_macro::bridge; + + fn contains_unsafe() { unsafe {} } + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/bang-macro.rs b/tests/ui/proc-macro/auxiliary/bang-macro.rs new file mode 100644 index 000000000..ff0002282 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/bang-macro.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn rewrite(input: TokenStream) -> TokenStream { + let input = input.to_string(); + + assert_eq!(input, r#""Hello, world!""#); + + r#""NOT Hello, world!""#.parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs new file mode 100644 index 000000000..fcaaba602 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn bang_proc_macro2(_: TokenStream) -> TokenStream { + "let x = foobar2;".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/builtin-attrs.rs b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs new file mode 100644 index 000000000..6edafae39 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs @@ -0,0 +1,27 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn feature(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn repr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn test(_: TokenStream, input: TokenStream) -> TokenStream { + "struct Test;".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn bench(_: TokenStream, input: TokenStream) -> TokenStream { + "struct Bench;".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/call-deprecated.rs b/tests/ui/proc-macro/auxiliary/call-deprecated.rs new file mode 100644 index 000000000..2f484809a --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/call-deprecated.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +#[deprecated(since = "1.0.0", note = "test")] +pub fn attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +#[deprecated(since = "1.0.0", note = "test")] +pub fn attr_remove(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/call-site.rs b/tests/ui/proc-macro/auxiliary/call-site.rs new file mode 100644 index 000000000..e64a5a343 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/call-site.rs @@ -0,0 +1,27 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn check(input: TokenStream) -> TokenStream { + // Parsed `x2` can refer to `x2` from `input` + let parsed1: TokenStream = "let x3 = x2;".parse().unwrap(); + // `x3` parsed from one string can refer to `x3` parsed from another string. + let parsed2: TokenStream = "let x4 = x3;".parse().unwrap(); + // Manually assembled `x4` can refer to parsed `x4`. + let manual: Vec = vec![ + Ident::new("let", Span::call_site()).into(), + Ident::new("x5", Span::call_site()).into(), + Punct::new('=', Spacing::Alone).into(), + Ident::new("x4", Span::call_site()).into(), + Punct::new(';', Spacing::Alone).into(), + ]; + input.into_iter().chain(parsed1.into_iter()) + .chain(parsed2.into_iter()) + .chain(manual.into_iter()) + .collect() +} diff --git a/tests/ui/proc-macro/auxiliary/cond_plugin.rs b/tests/ui/proc-macro/auxiliary/cond_plugin.rs new file mode 100644 index 000000000..8d3c4ec23 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/cond_plugin.rs @@ -0,0 +1,38 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn cond(input: TokenStream) -> TokenStream { + let mut conds = Vec::new(); + let mut input = input.into_iter().peekable(); + while let Some(tree) = input.next() { + let cond = match tree { + TokenTree::Group(tt) => tt.stream(), + _ => panic!("Invalid input"), + }; + let mut cond_trees = cond.clone().into_iter(); + let test = cond_trees.next().expect("Unexpected empty condition in `cond!`"); + let rhs = cond_trees.collect::(); + if rhs.is_empty() { + panic!("Invalid macro usage in cond: {}", cond); + } + let is_else = match test { + TokenTree::Ident(ref word) => &*word.to_string() == "else", + _ => false, + }; + conds.push(if is_else || input.peek().is_none() { + quote!({ $rhs }) + } else { + quote!(if $test { $rhs } else) + }); + } + + conds.into_iter().flat_map(|x| x.into_iter()).collect() +} diff --git a/tests/ui/proc-macro/auxiliary/count_compound_ops.rs b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs new file mode 100644 index 000000000..3a656d648 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Spacing, Literal, quote}; + +#[proc_macro] +pub fn count_compound_ops(input: TokenStream) -> TokenStream { + assert_eq!(count_compound_ops_helper(quote!(++ (&&) 4@a)), 3); + let l = Literal::u32_suffixed(count_compound_ops_helper(input)); + TokenTree::from(l).into() +} + +fn count_compound_ops_helper(input: TokenStream) -> u32 { + let mut count = 0; + for token in input { + match &token { + TokenTree::Punct(tt) if tt.spacing() == Spacing::Alone => { + count += 1; + } + TokenTree::Group(tt) => { + count += count_compound_ops_helper(tt.stream()); + } + _ => {} + } + } + count +} diff --git a/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs new file mode 100644 index 000000000..41f73f596 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn foo(a: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[proc_macro_derive(Bar, attributes(custom))] +pub fn bar(a: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/custom-quote.rs b/tests/ui/proc-macro/auxiliary/custom-quote.rs new file mode 100644 index 000000000..3b7811748 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/custom-quote.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic +// ignore-tidy-linelength + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use std::iter::FromIterator; +use std::str::FromStr; +use proc_macro::*; + +#[proc_macro] +pub fn custom_quote(input: TokenStream) -> TokenStream { + let mut tokens: Vec<_> = input.into_iter().collect(); + assert_eq!(tokens.len(), 1, "Unexpected input: {:?}", tokens); + match tokens.pop() { + Some(TokenTree::Ident(ident)) => { + assert_eq!(ident.to_string(), "my_ident"); + + let proc_macro_crate = TokenStream::from_str("::proc_macro").unwrap(); + let quoted_span = proc_macro::quote_span(proc_macro_crate, ident.span()); + let prefix = TokenStream::from_str(r#"let mut ident = proc_macro::Ident::new("my_ident", proc_macro::Span::call_site());"#).unwrap(); + let set_span_method = TokenStream::from_str("ident.set_span").unwrap(); + let set_span_arg = TokenStream::from(TokenTree::Group(Group::new(Delimiter::Parenthesis, quoted_span))); + let suffix = TokenStream::from_str(";proc_macro::TokenStream::from(proc_macro::TokenTree::Ident(ident))").unwrap(); + let full_stream = TokenStream::from_iter([prefix, set_span_method, set_span_arg, suffix]); + full_stream + } + _ => unreachable!() + } +} diff --git a/tests/ui/proc-macro/auxiliary/derive-a.rs b/tests/ui/proc-macro/auxiliary/derive-a.rs new file mode 100644 index 000000000..79a3864bf --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-a.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("struct A ;")); + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-atob.rs b/tests/ui/proc-macro/auxiliary/derive-atob.rs new file mode 100644 index 000000000..207b7fd32 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-atob.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AToB)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert_eq!(input, "struct A ;"); + "struct B;".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs new file mode 100644 index 000000000..e7e9634e0 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo, attributes(foo))] +pub fn derive(input: TokenStream) -> TokenStream { + assert!(!input.to_string().contains("#[cfg(any())]")); + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs new file mode 100644 index 000000000..641a95f78 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(B, attributes(B, C))] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("#[B [arbitrary tokens]]")); + assert!(input.contains("struct B {")); + assert!(input.contains("#[C]")); + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-b.rs b/tests/ui/proc-macro/auxiliary/derive-b.rs new file mode 100644 index 000000000..e7ab6c072 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-b.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(B, attributes(B))] +pub fn derive_b(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-bad.rs b/tests/ui/proc-macro/auxiliary/derive-bad.rs new file mode 100644 index 000000000..90bb9b1ba --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-bad.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn derive_a(_input: TokenStream) -> TokenStream { + "struct A { inner }".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-clona.rs b/tests/ui/proc-macro/auxiliary/derive-clona.rs new file mode 100644 index 000000000..4a35c9d0d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-clona.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Clona)] +pub fn derive_clonea(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-ctod.rs b/tests/ui/proc-macro/auxiliary/derive-ctod.rs new file mode 100644 index 000000000..2efe5a913 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-ctod.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(CToD)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert_eq!(input, "struct C ;"); + "struct D;".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-foo.rs b/tests/ui/proc-macro/auxiliary/derive-foo.rs new file mode 100644 index 000000000..3ea027d4f --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-foo.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(FooWithLongName)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs new file mode 100644 index 000000000..ab532da29 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs @@ -0,0 +1,2 @@ +#[macro_export] +macro_rules! empty_helper { () => () } diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs new file mode 100644 index 000000000..370a1a279 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(same_name, attributes(same_name))] +pub fn derive_a(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs new file mode 100644 index 000000000..41d3a1846 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_derive(GenHelperUse)] +pub fn derive_a(_: TokenStream) -> TokenStream { + " + #[empty_helper] + struct Uwu; + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-nothing.rs b/tests/ui/proc-macro/auxiliary/derive-nothing.rs new file mode 100644 index 000000000..b6d1e133a --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-nothing.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Nothing)] +pub fn nothing(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs new file mode 100644 index 000000000..7598d632c --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AToB)] +pub fn derive1(input: TokenStream) -> TokenStream { + println!("input1: {:?}", input.to_string()); + assert_eq!(input.to_string(), "struct A ;"); + "#[derive(BToC)] struct B;".parse().unwrap() +} + +#[proc_macro_derive(BToC)] +pub fn derive2(input: TokenStream) -> TokenStream { + assert_eq!(input.to_string(), "struct B ;"); + "struct C;".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs new file mode 100644 index 000000000..a6f0eec12 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_derive(A, attributes(b))] +pub fn foo(_x: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-union.rs b/tests/ui/proc-macro/auxiliary/derive-union.rs new file mode 100644 index 000000000..05883170c --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-union.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(UnionTest)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("#[repr(C)]")); + assert!(input.contains("union Test {")); + assert!(input.contains("a : u8,")); + assert!(input.contains("}")); + "".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs new file mode 100644 index 000000000..eac21b049 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Unstable)] +pub fn derive(_input: TokenStream) -> TokenStream { + + " + #[rustc_foo] + fn foo() {} + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable.rs b/tests/ui/proc-macro/auxiliary/derive-unstable.rs new file mode 100644 index 000000000..2ccd3f882 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/derive-unstable.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Unstable)] +pub fn derive(_input: TokenStream) -> TokenStream { + + "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/dollar-crate-external.rs b/tests/ui/proc-macro/auxiliary/dollar-crate-external.rs new file mode 100644 index 000000000..bdcdb7922 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/dollar-crate-external.rs @@ -0,0 +1,22 @@ +pub type S = u8; + +#[macro_export] +macro_rules! external { + () => { + print_bang! { + struct M($crate::S); + } + + #[print_attr] + struct A($crate::S); + + #[derive(Print)] + struct D($crate::S); + }; +} + +#[macro_export] +macro_rules! issue_62325 { () => { + #[print_attr] + struct B(identity!($crate::S)); +}} diff --git a/tests/ui/proc-macro/auxiliary/double.rs b/tests/ui/proc-macro/auxiliary/double.rs new file mode 100644 index 000000000..99eb4e375 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/double.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +// Outputs another copy of the struct. Useful for testing the tokens +// seen by the proc_macro. +#[proc_macro_derive(Double)] +pub fn derive(input: TokenStream) -> TokenStream { + quote!(mod foo { $input }) +} diff --git a/tests/ui/proc-macro/auxiliary/duplicate.rs b/tests/ui/proc-macro/auxiliary/duplicate.rs new file mode 100644 index 000000000..b8f82b46f --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/duplicate.rs @@ -0,0 +1,32 @@ +// force-host +// no-prefer-dynamic + +#![deny(unused)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream { + let mut new_name = Some(attr.into_iter().nth(0).unwrap()); + let mut encountered_idents = 0; + let input = item.to_string(); + let ret = item + .into_iter() + .map(move |token| match token { + TokenTree::Ident(_) if encountered_idents == 1 => { + encountered_idents += 1; + new_name.take().unwrap() + } + TokenTree::Ident(_) => { + encountered_idents += 1; + token + } + _ => token, + }) + .collect::(); + let mut input_again = input.parse::().unwrap(); + input_again.extend(ret); + input_again +} diff --git a/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs new file mode 100644 index 000000000..27c59b805 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs @@ -0,0 +1,20 @@ +// edition:2015 +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive2015)] +pub fn derive_2015(_: TokenStream) -> TokenStream { + " + use import::Path; + + fn check_absolute() { + let x = ::absolute::Path; + } + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/empty-crate.rs b/tests/ui/proc-macro/auxiliary/empty-crate.rs new file mode 100644 index 000000000..1cf7534b2 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/empty-crate.rs @@ -0,0 +1,5 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(unused_variables)] diff --git a/tests/ui/proc-macro/auxiliary/expand-expr.rs b/tests/ui/proc-macro/auxiliary/expand-expr.rs new file mode 100644 index 000000000..1d6ef8a13 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/expand-expr.rs @@ -0,0 +1,166 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(warnings)] +#![feature(proc_macro_expand, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::*; +use std::str::FromStr; + +// Flatten the TokenStream, removing any toplevel `Delimiter::None`s for +// comparison. +fn flatten(ts: TokenStream) -> Vec { + ts.into_iter() + .flat_map(|tt| match &tt { + TokenTree::Group(group) if group.delimiter() == Delimiter::None => { + flatten(group.stream()) + } + _ => vec![tt], + }) + .collect() +} + +// Assert that two TokenStream values are roughly equal to one-another. +fn assert_ts_eq(lhs: &TokenStream, rhs: &TokenStream) { + let ltts = flatten(lhs.clone()); + let rtts = flatten(rhs.clone()); + + if ltts.len() != rtts.len() { + panic!( + "expected the same number of tts ({} == {})\nlhs:\n{:#?}\nrhs:\n{:#?}", + ltts.len(), + rtts.len(), + lhs, + rhs + ) + } + + for (ltt, rtt) in ltts.iter().zip(&rtts) { + match (ltt, rtt) { + (TokenTree::Group(l), TokenTree::Group(r)) => { + assert_eq!( + l.delimiter(), + r.delimiter(), + "expected delimiters to match for {:?} and {:?}", + l, + r + ); + assert_ts_eq(&l.stream(), &r.stream()); + } + (TokenTree::Punct(l), TokenTree::Punct(r)) => assert_eq!( + (l.as_char(), l.spacing()), + (r.as_char(), r.spacing()), + "expected punct to match for {:?} and {:?}", + l, + r + ), + (TokenTree::Ident(l), TokenTree::Ident(r)) => assert_eq!( + l.to_string(), + r.to_string(), + "expected ident to match for {:?} and {:?}", + l, + r + ), + (TokenTree::Literal(l), TokenTree::Literal(r)) => assert_eq!( + l.to_string(), + r.to_string(), + "expected literal to match for {:?} and {:?}", + l, + r + ), + (l, r) => panic!("expected type to match for {:?} and {:?}", l, r), + } + } +} + +#[proc_macro] +pub fn expand_expr_is(input: TokenStream) -> TokenStream { + let mut iter = input.into_iter(); + let mut expected_tts = Vec::new(); + let comma = loop { + match iter.next() { + Some(TokenTree::Punct(p)) if p.as_char() == ',' => break p, + Some(tt) => expected_tts.push(tt), + None => panic!("expected comma"), + } + }; + + // Make sure that `Ident` and `Literal` objects from this proc-macro's + // environment are not invalidated when `expand_expr` recursively invokes + // another macro by taking a local copy, and checking it after the fact. + let pre_expand_span = comma.span(); + let pre_expand_ident = Ident::new("ident", comma.span()); + let pre_expand_literal = Literal::string("literal"); + let pre_expand_call_site = Span::call_site(); + + let expected = expected_tts.into_iter().collect::(); + let expanded = iter.collect::().expand_expr().expect("expand_expr failed"); + assert!( + expected.to_string() == expanded.to_string(), + "assert failed\nexpected: `{}`\nexpanded: `{}`", + expected.to_string(), + expanded.to_string() + ); + + // Also compare the raw tts to make sure they line up. + assert_ts_eq(&expected, &expanded); + + assert!(comma.span().eq(&pre_expand_span), "pre-expansion span is still equal"); + assert_eq!(pre_expand_ident.to_string(), "ident", "pre-expansion identifier is still valid"); + assert_eq!( + pre_expand_literal.to_string(), + "\"literal\"", + "pre-expansion literal is still valid" + ); + assert!(Span::call_site().eq(&pre_expand_call_site), "pre-expansion call-site is still equal"); + + TokenStream::new() +} + +#[proc_macro] +pub fn expand_expr_fail(input: TokenStream) -> TokenStream { + match input.expand_expr() { + Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts), + Err(_) => TokenStream::new(), + } +} + +#[proc_macro] +pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream { + // Check that the passed in `file!()` invocation and a parsed `file!` + // invocation expand to the same literal. + let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string(); + let parse_t = TokenStream::from_str("file!{}") + .unwrap() + .expand_expr() + .expect("expand_expr failed on internal macro") + .to_string(); + assert_eq!(input_t, parse_t); + + // Check that the literal matches `Span::call_site().source_file().path()` + let expect_t = + Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string(); + assert_eq!(input_t, expect_t); + + TokenStream::new() +} + +#[proc_macro] +pub fn recursive_expand(_: TokenStream) -> TokenStream { + // Recursively call until we hit the recursion limit and get an error. + // + // NOTE: This doesn't panic if expansion fails because that'll cause a very + // large number of errors to fill the output. + TokenStream::from_str("recursive_expand!{}") + .unwrap() + .expand_expr() + .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect()) +} + +#[proc_macro] +pub fn echo_pm(input: TokenStream) -> TokenStream { + input +} diff --git a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs new file mode 100644 index 000000000..d779d57af --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(warnings)] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("struct A ;")); + r#" + impl A { + fn a(&self) { + panic!("hello"); + } + } + "#.parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/external-crate-var.rs b/tests/ui/proc-macro/auxiliary/external-crate-var.rs new file mode 100644 index 000000000..4319e9212 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/external-crate-var.rs @@ -0,0 +1,40 @@ +pub struct ExternFoo; + +pub trait ExternTrait { + const CONST: u32; + type Assoc; +} + +impl ExternTrait for ExternFoo { + const CONST: u32 = 0; + type Assoc = ExternFoo; +} + +#[macro_export] +macro_rules! external { () => { + mod bar { + #[derive(Double)] + struct Bar($crate::ExternFoo); + } + + mod qself { + #[derive(Double)] + struct QSelf(<$crate::ExternFoo as $crate::ExternTrait>::Assoc); + } + + mod qself_recurse { + #[derive(Double)] + struct QSelfRecurse(< + <$crate::ExternFoo as $crate::ExternTrait>::Assoc + as $crate::ExternTrait>::Assoc + ); + } + + mod qself_in_const { + #[derive(Double)] + #[repr(u32)] + enum QSelfInConst { + Variant = <$crate::ExternFoo as $crate::ExternTrait>::CONST, + } + } +} } diff --git a/tests/ui/proc-macro/auxiliary/first-second.rs b/tests/ui/proc-macro/auxiliary/first-second.rs new file mode 100644 index 000000000..6331608fb --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/first-second.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Group, Delimiter}; + +#[proc_macro_attribute] +pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream { + let tokens: TokenStream = "#[derive(Second)]".parse().unwrap(); + let wrapped = TokenTree::Group(Group::new(Delimiter::None, item.into_iter().collect())); + tokens.into_iter().chain(std::iter::once(wrapped)).collect() +} + +#[proc_macro_derive(Second)] +pub fn second(item: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs new file mode 100644 index 000000000..d1a1c584f --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs @@ -0,0 +1,25 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn bar(_input: TokenStream) -> TokenStream { + let mut ret = Vec::::new(); + ret.push(Ident::new("static", Span::call_site()).into()); + ret.push(Ident::new("FOO", Span::call_site()).into()); + ret.push(Punct::new(':', Spacing::Alone).into()); + ret.push(Punct::new('&', Spacing::Alone).into()); + ret.push(Punct::new('\'', Spacing::Joint).into()); + ret.push(Ident::new("static", Span::call_site()).into()); + ret.push(Ident::new("i32", Span::call_site()).into()); + ret.push(Punct::new('=', Spacing::Alone).into()); + ret.push(Punct::new('&', Spacing::Alone).into()); + ret.push(Literal::i32_unsuffixed(1).into()); + ret.push(Punct::new(';', Spacing::Alone).into()); + ret.into_iter().collect() +} diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs new file mode 100644 index 000000000..548fefe76 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn gen_macro_rules(_: TokenStream) -> TokenStream { + " + macro_rules! generated {() => { + struct ItemDef; + let local_def = 0; + + ItemUse; // OK + local_use; // ERROR + break 'label_use; // ERROR + + type DollarCrate = $crate::ItemUse; // OK + }} + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs new file mode 100644 index 000000000..d4b67d6b0 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(repro)] +pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream { + "macro_rules! m {()=>{}}".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs new file mode 100644 index 000000000..3f3e12eed --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn dollar_ident(input: TokenStream) -> TokenStream { + let black_hole = input.into_iter().next().unwrap(); + quote! { + $black_hole!($$var); + } +} diff --git a/tests/ui/proc-macro/auxiliary/generate-mod.rs b/tests/ui/proc-macro/auxiliary/generate-mod.rs new file mode 100644 index 000000000..e950f7d62 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/generate-mod.rs @@ -0,0 +1,58 @@ +// run-pass +// force-host +// no-prefer-dynamic +// ignore-pass + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn check(_: TokenStream) -> TokenStream { + " + type Alias = FromOutside; // OK + struct Outer; + mod inner { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = Outer; // `Outer` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn check_attr(_: TokenStream, _: TokenStream) -> TokenStream { + " + type AliasAttr = FromOutside; // OK + struct OuterAttr; + mod inner_attr { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterAttr; // `OuterAttr` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_derive(CheckDerive)] +pub fn check_derive(_: TokenStream) -> TokenStream { + " + type AliasDerive = FromOutside; // OK + struct OuterDerive; + mod inner_derive { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterDerive; // `OuterDerive` shouldn't be available from here + } + ".parse().unwrap() +} + +#[proc_macro_derive(CheckDeriveLint)] +pub fn check_derive_lint(_: TokenStream) -> TokenStream { + " + type AliasDeriveLint = FromOutside; // OK + struct OuterDeriveLint; + #[allow(proc_macro_derive_resolution_fallback)] + mod inner_derive_lint { + type Alias = FromOutside; // `FromOutside` shouldn't be available from here + type Inner = OuterDeriveLint; // `OuterDeriveLint` shouldn't be available from here + } + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example.rs b/tests/ui/proc-macro/auxiliary/hygiene_example.rs new file mode 100644 index 000000000..f7e7e0b57 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/hygiene_example.rs @@ -0,0 +1,7 @@ +extern crate hygiene_example_codegen; + +pub use hygiene_example_codegen::hello; + +pub fn print(string: &str) { + println!("{}", string); +} diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs new file mode 100644 index 000000000..2bd4d3336 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs @@ -0,0 +1,27 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro as proc_macro_renamed; // This does not break `quote!` + +use proc_macro_renamed::{TokenStream, quote}; + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + quote!(hello_helper!($input)) + //^ `hello_helper!` always resolves to the following proc macro, + //| no matter where `hello!` is used. +} + +#[proc_macro] +pub fn hello_helper(input: TokenStream) -> TokenStream { + quote! { + extern crate hygiene_example; // This is never a conflict error + let string = format!("hello {}", $input); + //^ `format!` always resolves to the prelude macro, + //| even if a different `format!` is in scope where `hello!` is used. + hygiene_example::print(&string) + } +} diff --git a/tests/ui/proc-macro/auxiliary/included-file.txt b/tests/ui/proc-macro/auxiliary/included-file.txt new file mode 100644 index 000000000..b4720047d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/included-file.txt @@ -0,0 +1 @@ +Included file contents diff --git a/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs new file mode 100644 index 000000000..518dfd0d6 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs @@ -0,0 +1,28 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_raw_ident)] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn invalid_punct(_: TokenStream) -> TokenStream { + TokenTree::from(Punct::new('`', Spacing::Alone)).into() +} + +#[proc_macro] +pub fn invalid_ident(_: TokenStream) -> TokenStream { + TokenTree::from(Ident::new("*", Span::call_site())).into() +} + +#[proc_macro] +pub fn invalid_raw_ident(_: TokenStream) -> TokenStream { + TokenTree::from(Ident::new_raw("self", Span::call_site())).into() +} + +#[proc_macro] +pub fn lexer_failure(_: TokenStream) -> TokenStream { + "a b ) c".parse().expect("parsing failed without panic") +} diff --git a/tests/ui/proc-macro/auxiliary/is-available.rs b/tests/ui/proc-macro/auxiliary/is-available.rs new file mode 100644 index 000000000..03f5265e3 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/is-available.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Literal, TokenStream, TokenTree}; + +#[proc_macro] +pub fn from_inside_proc_macro(_input: TokenStream) -> TokenStream { + proc_macro::is_available().to_string().parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-104884.rs b/tests/ui/proc-macro/auxiliary/issue-104884.rs new file mode 100644 index 000000000..0de59d005 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-104884.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(AddImpl)] + +pub fn derive(input: TokenStream) -> TokenStream { + "use std::cmp::Ordering; + + impl Ord for PriorityQueue { + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&self.height) + } + } + " + .parse() + .unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-38586.rs b/tests/ui/proc-macro/auxiliary/issue-38586.rs new file mode 100644 index 000000000..f3a19081c --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-38586.rs @@ -0,0 +1,11 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +#[proc_macro_derive(A)] +pub fn derive_a(_: proc_macro::TokenStream) -> proc_macro::TokenStream { + "fn f() { println!(\"{}\", foo); }".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-39889.rs b/tests/ui/proc-macro/auxiliary/issue-39889.rs new file mode 100644 index 000000000..e7af66da7 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-39889.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Issue39889)] +pub fn f(_input: TokenStream) -> TokenStream { + let rules = r#" + macro_rules! id { + ($($tt:tt)*) => { $($tt)* }; + } + "#; + rules.parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-42708.rs b/tests/ui/proc-macro/auxiliary/issue-42708.rs new file mode 100644 index 000000000..dae05204b --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-42708.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Test)] +pub fn derive(_input: TokenStream) -> TokenStream { + "fn f(s: S) { s.x }".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn attr_test(_attr: TokenStream, input: TokenStream) -> TokenStream { + input +} diff --git a/tests/ui/proc-macro/auxiliary/issue-50061.rs b/tests/ui/proc-macro/auxiliary/issue-50061.rs new file mode 100644 index 000000000..f5fe8cabb --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-50061.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn check(_a: TokenStream, b: TokenStream) -> TokenStream { + b.into_iter().collect() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-50493.rs b/tests/ui/proc-macro/auxiliary/issue-50493.rs new file mode 100644 index 000000000..f72024948 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-50493.rs @@ -0,0 +1,21 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive)] +pub fn derive(_: TokenStream) -> TokenStream { + let code = " + fn one(r: Restricted) { + r.field; + } + fn two(r: Restricted) { + r.field; + } + "; + + code.parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-59191.rs b/tests/ui/proc-macro/auxiliary/issue-59191.rs new file mode 100644 index 000000000..d9ee77067 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-59191.rs @@ -0,0 +1,16 @@ +// edition:2018 +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn no_main(_attrs: TokenStream, _input: TokenStream) -> TokenStream { + let new_krate = r#" + fn main() {} + "#; + new_krate.parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-66286.rs b/tests/ui/proc-macro/auxiliary/issue-66286.rs new file mode 100644 index 000000000..6217f1c7e --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-66286.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn vec_ice(_attr: TokenStream, input: TokenStream) -> TokenStream { + // This redundant convert is necessary to reproduce ICE. + input.into_iter().collect() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-75801.rs b/tests/ui/proc-macro/auxiliary/issue-75801.rs new file mode 100644 index 000000000..d6c031d7d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-75801.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn foo(_args: TokenStream, item: TokenStream) -> TokenStream { + item +} diff --git a/tests/ui/proc-macro/auxiliary/issue-79242.rs b/tests/ui/proc-macro/auxiliary/issue-79242.rs new file mode 100644 index 000000000..e586980f0 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-79242.rs @@ -0,0 +1,16 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dummy(input: TokenStream) -> TokenStream { + // Iterate to force internal conversion of nonterminals + // to `proc_macro` structs + for _ in input {} + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-79825.rs b/tests/ui/proc-macro/auxiliary/issue-79825.rs new file mode 100644 index 000000000..930891b1d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-79825.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn assert_input(args: TokenStream, input: TokenStream) -> TokenStream { + assert_eq!(input.to_string(), "trait Alias = Sized ;"); + assert!(args.is_empty()); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-83510.rs b/tests/ui/proc-macro/auxiliary/issue-83510.rs new file mode 100644 index 000000000..1d6ef3914 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-83510.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dance_like_you_want_to_ice(_: TokenStream) -> TokenStream { + r#" + impl Foo { + type Bar = Box<()> + Baz; + } + "# + .parse() + .unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs new file mode 100644 index 000000000..958a8bed9 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +fn compile_error() -> TokenStream { + r#"compile_error!("")"#.parse().unwrap() +} + +#[proc_macro_derive(MyTrait)] +pub fn derive(input: TokenStream) -> TokenStream { + compile_error() +} +#[proc_macro_attribute] +pub fn attribute_macro(_attr: TokenStream, mut input: TokenStream) -> TokenStream { + input.extend(compile_error()); + input +} +#[proc_macro] +pub fn fn_macro(_item: TokenStream) -> TokenStream { + compile_error() +} diff --git a/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs new file mode 100644 index 000000000..4e5d22e6e --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn lifetimes_bang(input: TokenStream) -> TokenStream { + // Roundtrip through token trees + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn lifetimes_attr(_: TokenStream, input: TokenStream) -> TokenStream { + // Roundtrip through AST + input +} + +#[proc_macro_derive(Lifetimes)] +pub fn lifetimes_derive(input: TokenStream) -> TokenStream { + // Roundtrip through a string + format!("mod m {{ {} }}", input).parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/lifetimes.rs b/tests/ui/proc-macro/auxiliary/lifetimes.rs new file mode 100644 index 000000000..212164dd2 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/lifetimes.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn single_quote_alone(_: TokenStream) -> TokenStream { + // `&'a u8`, but the `'` token is not joint + let trees: Vec = vec![ + Punct::new('&', Spacing::Alone).into(), + Punct::new('\'', Spacing::Alone).into(), + Ident::new("a", Span::call_site()).into(), + Ident::new("u8", Span::call_site()).into(), + ]; + trees.into_iter().collect() +} diff --git a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs new file mode 100644 index 000000000..c72306c3d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -0,0 +1,89 @@ +// force-host +// no-prefer-dynamic + +// These are tests for syntax that is accepted by the Rust parser but +// unconditionally rejected semantically after macro expansion. Attribute macros +// are permitted to accept such syntax as long as they replace it with something +// that makes sense to Rust. +// +// We also inspect some of the spans to verify the syntax is not triggering the +// lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081). + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span)] + +extern crate proc_macro; +use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree}; +use std::path::Component; + +// unsafe mod m { +// pub unsafe mod inner; +// } +#[proc_macro_attribute] +pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "mod"); + expect(tokens, "m"); + let tokens = &mut expect_brace(tokens); + expect(tokens, "pub"); + expect(tokens, "unsafe"); + expect(tokens, "mod"); + let ident = expect(tokens, "inner"); + expect(tokens, ";"); + check_useful_span(ident, "unsafe-mod.rs"); + TokenStream::new() +} + +// unsafe extern { +// type T; +// } +#[proc_macro_attribute] +pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "extern"); + let tokens = &mut expect_brace(tokens); + expect(tokens, "type"); + let ident = expect(tokens, "T"); + expect(tokens, ";"); + check_useful_span(ident, "unsafe-foreign-mod.rs"); + TokenStream::new() +} + +// unsafe extern "C++" {} +#[proc_macro_attribute] +pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "unsafe"); + expect(tokens, "extern"); + let abi = expect(tokens, "\"C++\""); + expect_brace(tokens); + check_useful_span(abi, "unsafe-foreign-mod.rs"); + TokenStream::new() +} + +fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree { + match tokens.next() { + Some(token) if token.to_string() == expected => token, + wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected), + } +} + +fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter { + match tokens.next() { + Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => { + group.stream().into_iter() + } + wrong => panic!("unexpected token: {:?}, expected `{{`", wrong), + } +} + +fn check_useful_span(token: TokenTree, expected_filename: &str) { + let span = token.span(); + assert!(span.start().column < span.end().column); + + let source_path = span.source_file().path(); + let filename = source_path.components().last().unwrap(); + assert_eq!(filename, Component::Normal(expected_filename.as_ref())); +} diff --git a/tests/ui/proc-macro/auxiliary/make-macro.rs b/tests/ui/proc-macro/auxiliary/make-macro.rs new file mode 100644 index 000000000..3c851b6de --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/make-macro.rs @@ -0,0 +1,18 @@ +// force-host + +#[macro_export] +macro_rules! make_it { + ($name:ident) => { + #[proc_macro] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Def site: {:?}", Span::def_site()); + println!("Input: {:?}", input); + let new: TokenStream = input.into_iter().map(|mut t| { + t.set_span(Span::def_site()); + t + }).collect(); + println!("Respanned: {:?}", new); + new + } + }; +} diff --git a/tests/ui/proc-macro/auxiliary/meta-delim.rs b/tests/ui/proc-macro/auxiliary/meta-delim.rs new file mode 100644 index 000000000..54e3d7857 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/meta-delim.rs @@ -0,0 +1,12 @@ +macro_rules! produce_it { + ($dollar_one:tt $foo:ident $my_name:ident) => { + #[macro_export] + macro_rules! meta_delim { + ($dollar_one ($dollar_one $my_name:ident)*) => { + stringify!($dollar_one ($dollar_one $my_name)*) + } + } + } +} + +produce_it!($my_name name); diff --git a/tests/ui/proc-macro/auxiliary/meta-macro.rs b/tests/ui/proc-macro/auxiliary/meta-macro.rs new file mode 100644 index 000000000..0a9b9887d --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/meta-macro.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic +// edition:2018 + +#![feature(proc_macro_def_site)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +extern crate make_macro; +use proc_macro::{TokenStream, Span}; + +make_macro::make_it!(print_def_site); + +#[proc_macro] +pub fn dummy(input: TokenStream) -> TokenStream { input } diff --git a/tests/ui/proc-macro/auxiliary/mixed-site-span.rs b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs new file mode 100644 index 000000000..c2a498700 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs @@ -0,0 +1,40 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn proc_macro_rules(input: TokenStream) -> TokenStream { + if input.is_empty() { + let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site())); + let item_def = id("ItemDef"); + let local_def = id("local_def"); + let item_use = id("ItemUse"); + let local_use = id("local_use"); + let mut single_quote = Punct::new('\'', Spacing::Joint); + single_quote.set_span(Span::mixed_site()); + let label_use: TokenStream = [ + TokenTree::from(single_quote), + id("label_use"), + ].iter().cloned().collect(); + quote!( + struct $item_def; + let $local_def = 0; + + $item_use; // OK + $local_use; // ERROR + break $label_use; // ERROR + ) + } else { + let mut dollar_crate = input.into_iter().next().unwrap(); + dollar_crate.set_span(Span::mixed_site()); + quote!( + type A = $dollar_crate::ItemUse; + ) + } +} diff --git a/tests/ui/proc-macro/auxiliary/modify-ast.rs b/tests/ui/proc-macro/auxiliary/modify-ast.rs new file mode 100644 index 000000000..cc582c152 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/modify-ast.rs @@ -0,0 +1,47 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn assert1(_a: TokenStream, b: TokenStream) -> TokenStream { + assert_eq(b.clone(), "pub fn foo() {}".parse().unwrap()); + b +} + +#[proc_macro_derive(Foo, attributes(foo))] +pub fn assert2(a: TokenStream) -> TokenStream { + assert_eq(a, "pub struct MyStructc { _a: i32, }".parse().unwrap()); + TokenStream::new() +} + +fn assert_eq(a: TokenStream, b: TokenStream) { + let mut a = a.into_iter(); + let mut b = b.into_iter(); + for (a, b) in a.by_ref().zip(&mut b) { + match (a, b) { + (TokenTree::Group(a), TokenTree::Group(b)) => { + assert_eq!(a.delimiter(), b.delimiter()); + assert_eq(a.stream(), b.stream()); + } + (TokenTree::Punct(a), TokenTree::Punct(b)) => { + assert_eq!(a.as_char(), b.as_char()); + assert_eq!(a.spacing(), b.spacing()); + } + (TokenTree::Literal(a), TokenTree::Literal(b)) => { + assert_eq!(a.to_string(), b.to_string()); + } + (TokenTree::Ident(a), TokenTree::Ident(b)) => { + assert_eq!(a.to_string(), b.to_string()); + } + (a, b) => panic!("{:?} != {:?}", a, b), + } + } + + assert!(a.next().is_none()); + assert!(b.next().is_none()); +} diff --git a/tests/ui/proc-macro/auxiliary/multiple-derives.rs b/tests/ui/proc-macro/auxiliary/multiple-derives.rs new file mode 100644 index 000000000..e3f6607b2 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/multiple-derives.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +macro_rules! make_derives { + ($($name:ident),*) => { + $( + #[proc_macro_derive($name)] + pub fn $name(input: TokenStream) -> TokenStream { + println!("Derive {}: {}", stringify!($name), input); + TokenStream::new() + } + )* + } +} + +make_derives!(First, Second, Third, Fourth, Fifth); diff --git a/tests/ui/proc-macro/auxiliary/multispan.rs b/tests/ui/proc-macro/auxiliary/multispan.rs new file mode 100644 index 000000000..c05d15643 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/multispan.rs @@ -0,0 +1,37 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + let mut hi_spans = vec![]; + for tree in input { + if let TokenTree::Ident(ref ident) = tree { + if ident.to_string() == "hi" { + hi_spans.push(ident.span()); + } + } + } + + if !hi_spans.is_empty() { + return Err(Span::def_site() + .error("hello to you, too!") + .span_note(hi_spans, "found these 'hi's")); + } + + Ok(()) +} + +#[proc_macro] +pub fn hello(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/negative-token.rs b/tests/ui/proc-macro/auxiliary/negative-token.rs new file mode 100644 index 000000000..8b89f2e37 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/negative-token.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn neg_one(_input: TokenStream) -> TokenStream { + TokenTree::Literal(Literal::i32_suffixed(-1)).into() +} + +#[proc_macro] +pub fn neg_one_float(_input: TokenStream) -> TokenStream { + TokenTree::Literal(Literal::f32_suffixed(-1.0)).into() +} diff --git a/tests/ui/proc-macro/auxiliary/nested-macro-rules.rs b/tests/ui/proc-macro/auxiliary/nested-macro-rules.rs new file mode 100644 index 000000000..27676a5cb --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/nested-macro-rules.rs @@ -0,0 +1,16 @@ +pub struct FirstStruct; + +#[macro_export] +macro_rules! outer_macro { + ($name:ident, $attr_struct_name:ident) => { + #[macro_export] + macro_rules! inner_macro { + ($bang_macro:ident, $attr_macro:ident) => { + $bang_macro!($name); + #[$attr_macro] struct $attr_struct_name {} + } + } + } +} + +outer_macro!(FirstStruct, FirstAttrStruct); diff --git a/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs new file mode 100644 index 000000000..ea5ff4665 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs @@ -0,0 +1,25 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; +use proc_macro::{TokenStream, quote}; + +#[proc_macro_attribute] +pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream { + let recollected: TokenStream = input.into_iter().collect(); + println!("First recollected: {:#?}", recollected); + quote! { + #[second_attr] + $recollected + } +} + +#[proc_macro_attribute] +pub fn second_attr(_: TokenStream, input: TokenStream) -> TokenStream { + let recollected: TokenStream = input.into_iter().collect(); + println!("Second recollected: {:#?}", recollected); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/not-joint.rs b/tests/ui/proc-macro/auxiliary/not-joint.rs new file mode 100644 index 000000000..e6c09f762 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/not-joint.rs @@ -0,0 +1,30 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro] +pub fn tokens(input: TokenStream) -> TokenStream { + assert_nothing_joint(input); + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn nothing(_: TokenStream, input: TokenStream) -> TokenStream { + assert_nothing_joint(input); + TokenStream::new() +} + +fn assert_nothing_joint(s: TokenStream) { + for tt in s { + match tt { + TokenTree::Group(g) => assert_nothing_joint(g.stream()), + TokenTree::Punct(p) => assert_eq!(p.spacing(), Spacing::Alone), + _ => {} + } + } +} diff --git a/tests/ui/proc-macro/auxiliary/parent-source-spans.rs b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs new file mode 100644 index 000000000..594f10883 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs @@ -0,0 +1,43 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_diagnostic, proc_macro_span)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span}; + +fn lit_span(tt: TokenTree) -> (Span, String) { + match tt { + TokenTree::Literal(..) | + TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()), + _ => panic!("expected a literal in token tree, got: {:?}", tt) + } +} + +#[proc_macro] +pub fn parent_source_spans(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let (sp1, str1) = lit_span(tokens.next().expect("first string")); + let _ = tokens.next(); + let (sp2, str2) = lit_span(tokens.next().expect("second string")); + + sp1.error(format!("first final: {}", str1)).emit(); + sp2.error(format!("second final: {}", str2)).emit(); + + if let (Some(p1), Some(p2)) = (sp1.parent(), sp2.parent()) { + p1.error(format!("first parent: {}", str1)).emit(); + p2.error(format!("second parent: {}", str2)).emit(); + + if let (Some(gp1), Some(gp2)) = (p1.parent(), p2.parent()) { + gp1.error(format!("first grandparent: {}", str1)).emit(); + gp2.error(format!("second grandparent: {}", str2)).emit(); + } + } + + sp1.source().error(format!("first source: {}", str1)).emit(); + sp2.source().error(format!("second source: {}", str2)).emit(); + + "ok".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs new file mode 100644 index 000000000..fc15bb9c5 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, Ident, Span}; + +#[proc_macro] +pub fn panic_in_libproc_macro(_: TokenStream) -> TokenStream { + Ident::new("", Span::call_site()); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/raw-ident.rs b/tests/ui/proc-macro/auxiliary/raw-ident.rs new file mode 100644 index 000000000..9daee21aa --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/raw-ident.rs @@ -0,0 +1,35 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, TokenTree, Ident, Punct, Spacing, Span}; + +#[proc_macro] +pub fn make_struct(input: TokenStream) -> TokenStream { + match input.into_iter().next().unwrap() { + TokenTree::Ident(ident) => { + vec![ + TokenTree::Ident(Ident::new("struct", Span::call_site())), + TokenTree::Ident(Ident::new_raw(&ident.to_string(), Span::call_site())), + TokenTree::Punct(Punct::new(';', Spacing::Alone)) + ].into_iter().collect() + } + _ => panic!() + } +} + +#[proc_macro] +pub fn make_bad_struct(input: TokenStream) -> TokenStream { + match input.into_iter().next().unwrap() { + TokenTree::Ident(ident) => { + vec![ + TokenTree::Ident(Ident::new_raw("struct", Span::call_site())), + TokenTree::Ident(Ident::new(&ident.to_string(), Span::call_site())), + TokenTree::Punct(Punct::new(';', Spacing::Alone)) + ].into_iter().collect() + } + _ => panic!() + } +} diff --git a/tests/ui/proc-macro/auxiliary/re-export.rs b/tests/ui/proc-macro/auxiliary/re-export.rs new file mode 100644 index 000000000..e8e9c9d3e --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/re-export.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn cause_ice(_: TokenStream) -> TokenStream { + " + enum IceCause { + Variant, + } + + pub use IceCause::Variant; + ".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/recollect.rs b/tests/ui/proc-macro/auxiliary/recollect.rs new file mode 100644 index 000000000..d4494a5af --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/recollect.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn recollect(tokens: TokenStream) -> TokenStream { + tokens.into_iter().collect() +} diff --git a/tests/ui/proc-macro/auxiliary/resolved-located-at.rs b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs new file mode 100644 index 000000000..db660824f --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs @@ -0,0 +1,31 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_def_site)] +#![feature(proc_macro_diagnostic)] +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn resolve_located_at(input: TokenStream) -> TokenStream { + match &*input.into_iter().collect::>() { + [a, b, ..] => { + // The error is reported at input `a`. + let mut diag = Diagnostic::new(Level::Error, "expected error"); + diag.set_spans(Span::def_site().located_at(a.span())); + diag.emit(); + + // Resolves to `struct S;` at def site, but the error is reported at input `b`. + let s = TokenTree::Ident(Ident::new("S", b.span().resolved_at(Span::def_site()))); + quote!({ + struct S; + + $s + }) + } + _ => panic!("unexpected input"), + } +} diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs new file mode 100644 index 000000000..ad1e770a4 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs @@ -0,0 +1,45 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::*; + +// Re-emits the input tokens by parsing them from strings +#[proc_macro] +pub fn reemit(input: TokenStream) -> TokenStream { + input.to_string().parse().unwrap() +} + +#[proc_macro] +pub fn assert_fake_source_file(input: TokenStream) -> TokenStream { + for tk in input { + let source_file = tk.span().source_file(); + assert!(!source_file.is_real(), "Source file is real: {:?}", source_file); + } + + "".parse().unwrap() +} + +#[proc_macro] +pub fn assert_source_file(input: TokenStream) -> TokenStream { + for tk in input { + let source_file = tk.span().source_file(); + assert!(source_file.is_real(), "Source file is not real: {:?}", source_file); + } + + "".parse().unwrap() +} + +#[proc_macro] +pub fn macro_stringify(input: TokenStream) -> TokenStream { + let mut tokens = input.into_iter(); + let first_span = tokens.next().expect("first token").span(); + let last_span = tokens.last().map(|x| x.span()).unwrap_or(first_span); + let span = first_span.join(last_span).expect("joined span"); + let src = span.source_text().expect("source_text"); + TokenTree::Literal(Literal::string(&src)).into() +} diff --git a/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs new file mode 100644 index 000000000..49292acfe --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs @@ -0,0 +1,49 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_quote)] +#![feature(proc_macro_internals)] // FIXME - this shouldn't be necessary +#![crate_type = "proc-macro"] + +extern crate proc_macro; +extern crate custom_quote; + +use proc_macro::{quote, TokenStream}; + +macro_rules! expand_to_quote { + () => { + quote! { + let bang_error: bool = 25; + } + } +} + +#[proc_macro] +pub fn error_from_bang(_input: TokenStream) -> TokenStream { + expand_to_quote!() +} + +#[proc_macro] +pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { + custom_quote::custom_quote! { + my_ident + } +} + +#[proc_macro_attribute] +pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { + quote! { + struct AttributeError { + field: MissingType + } + } +} + +#[proc_macro_derive(ErrorFromDerive)] +pub fn error_from_derive(_input: TokenStream) -> TokenStream { + quote! { + enum DeriveError { + Variant(OtherMissingType) + } + } +} diff --git a/tests/ui/proc-macro/auxiliary/span-test-macros.rs b/tests/ui/proc-macro/auxiliary/span-test-macros.rs new file mode 100644 index 000000000..9a78f0a89 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/span-test-macros.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! reemit_legacy { + ($($tok:tt)*) => ($($tok)*) +} + +#[macro_export] +macro_rules! say_hello_extern { + ($macname:ident) => ( $macname! { "Hello, world!" }) +} diff --git a/tests/ui/proc-macro/auxiliary/subspan.rs b/tests/ui/proc-macro/auxiliary/subspan.rs new file mode 100644 index 000000000..f92adc040 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/subspan.rs @@ -0,0 +1,38 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + if let Some(TokenTree::Literal(lit)) = input.into_iter().next() { + let mut spans = vec![]; + let string = lit.to_string(); + for hi in string.matches("hi") { + let index = hi.as_ptr() as usize - string.as_ptr() as usize; + let subspan = lit.subspan(index..(index + hi.len())).unwrap(); + spans.push(subspan); + } + + if !spans.is_empty() { + Err(Span::call_site().error("found 'hi's").span_note(spans, "here")) + } else { + Ok(()) + } + } else { + Err(Span::call_site().error("invalid input: expected string literal")) + } +} + +#[proc_macro] +pub fn subspan(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + } + + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/test-macros.rs b/tests/ui/proc-macro/auxiliary/test-macros.rs new file mode 100644 index 000000000..7a46aee46 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/test-macros.rs @@ -0,0 +1,180 @@ +// force-host +// no-prefer-dynamic + +// Proc macros commonly used by tests. +// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::{TokenStream, TokenTree}; + +// Macro that return empty token stream. + +#[proc_macro] +pub fn empty(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_derive(Empty, attributes(empty_helper))] +pub fn empty_derive(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +// Macro that panics. + +#[proc_macro] +pub fn panic_bang(_: TokenStream) -> TokenStream { + panic!("panic-bang"); +} + +#[proc_macro_attribute] +pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream { + panic!("panic-attr"); +} + +#[proc_macro_derive(Panic, attributes(panic_helper))] +pub fn panic_derive(_: TokenStream) -> TokenStream { + panic!("panic-derive"); +} + +// Macros that return the input stream. + +#[proc_macro] +pub fn identity(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(Identity, attributes(identity_helper))] +pub fn identity_derive(input: TokenStream) -> TokenStream { + input +} + +// Macros that iterate and re-collect the input stream. + +#[proc_macro] +pub fn recollect(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_derive(Recollect, attributes(recollect_helper))] +pub fn recollect_derive(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +// Macros that print their input in the original and re-collected forms (if they differ). + +fn print_helper(input: TokenStream, kind: &str) -> TokenStream { + print_helper_ext(input, kind, true) +} + +fn deep_recollect(input: TokenStream) -> TokenStream { + input.into_iter().map(|tree| { + match tree { + TokenTree::Group(group) => { + let inner = deep_recollect(group.stream()); + let mut new_group = TokenTree::Group( + proc_macro::Group::new(group.delimiter(), inner) + ); + new_group.set_span(group.span()); + new_group + } + _ => tree, + } + }).collect() +} + +fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream { + let input_display = format!("{}", input); + let input_debug = format!("{:#?}", input); + let recollected = input.clone().into_iter().collect(); + let recollected_display = format!("{}", recollected); + let recollected_debug = format!("{:#?}", recollected); + + let deep_recollected = deep_recollect(input); + let deep_recollected_display = format!("{}", deep_recollected); + let deep_recollected_debug = format!("{:#?}", deep_recollected); + + + + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); + if recollected_display != input_display { + println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); + } + + if deep_recollected_display != recollected_display { + println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display); + } + + if debug { + println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); + if recollected_debug != input_debug { + println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); + } + if deep_recollected_debug != recollected_debug { + println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug); + } + } + recollected +} + +#[proc_macro] +pub fn print_bang(input: TokenStream) -> TokenStream { + print_helper(input, "BANG") +} + +#[proc_macro] +pub fn print_bang_consume(input: TokenStream) -> TokenStream { + print_helper(input, "BANG"); + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn print_attr(args: TokenStream, input: TokenStream) -> TokenStream { + let debug = match &args.into_iter().collect::>()[..] { + [TokenTree::Ident(ident)] if ident.to_string() == "nodebug" => false, + _ => true, + }; + print_helper_ext(input, "ATTR", debug) +} + +#[proc_macro_attribute] +pub fn print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream { + print_helper(args, "ATTR_ARGS"); + input +} + +#[proc_macro_attribute] +pub fn print_target_and_args(args: TokenStream, input: TokenStream) -> TokenStream { + print_helper(args, "ATTR_ARGS"); + print_helper(input.clone(), "ATTR"); + input +} + +#[proc_macro_attribute] +pub fn print_target_and_args_consume(args: TokenStream, input: TokenStream) -> TokenStream { + print_helper(args, "ATTR_ARGS"); + print_helper(input.clone(), "ATTR"); + TokenStream::new() +} + +#[proc_macro_derive(Print, attributes(print_helper))] +pub fn print_derive(input: TokenStream) -> TokenStream { + print_helper(input, "DERIVE"); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/auxiliary/three-equals.rs b/tests/ui/proc-macro/auxiliary/three-equals.rs new file mode 100644 index 000000000..e740e86e5 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/three-equals.rs @@ -0,0 +1,49 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Span, Diagnostic}; + +fn parse(input: TokenStream) -> Result<(), Diagnostic> { + let mut count = 0; + let mut last_span = Span::def_site(); + for tree in input { + let span = tree.span(); + if count >= 3 { + return Err(span.error(format!("expected EOF, found `{}`.", tree)) + .span_note(last_span, "last good input was here") + .help("input must be: `===`")) + } + + if let TokenTree::Punct(ref tt) = tree { + if tt.as_char() == '=' { + count += 1; + last_span = span; + continue + } + } + return Err(span.error(format!("expected `=`, found `{}`.", tree))); + } + + if count < 3 { + return Err(Span::def_site() + .error(format!("found {} equal signs, need exactly 3", count)) + .help("input must be: `===`")) + } + + Ok(()) +} + +#[proc_macro] +pub fn three_equals(input: TokenStream) -> TokenStream { + if let Err(diag) = parse(input) { + diag.emit(); + return TokenStream::new(); + } + + "3".parse().unwrap() +} diff --git a/tests/ui/proc-macro/auxiliary/weird-hygiene.rs b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs new file mode 100644 index 000000000..338e436df --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs @@ -0,0 +1,48 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, Group}; + +fn find_my_ident(tokens: TokenStream) -> Option { + for token in tokens { + if let TokenTree::Ident(ident) = &token { + if ident.to_string() == "hidden_ident" { + return Some(vec![token].into_iter().collect()) + } + } else if let TokenTree::Group(g) = token { + if let Some(stream) = find_my_ident(g.stream()) { + return Some(stream) + } + } + } + return None; +} + + +#[proc_macro_derive(WeirdDerive)] +pub fn weird_derive(item: TokenStream) -> TokenStream { + let my_ident = find_my_ident(item).expect("Missing 'my_ident'!"); + let tokens: TokenStream = "call_it!();".parse().unwrap(); + let final_call = tokens.into_iter().map(|tree| { + if let TokenTree::Group(g) = tree { + return Group::new(g.delimiter(), my_ident.clone()).into() + } else { + return tree + } + }).collect(); + final_call +} + +#[proc_macro] +pub fn recollect(item: TokenStream) -> TokenStream { + item.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_attr: TokenStream, mut item: TokenStream) -> TokenStream { + item.into_iter().collect() +} diff --git a/tests/ui/proc-macro/bang-macro.rs b/tests/ui/proc-macro/bang-macro.rs new file mode 100644 index 000000000..928107913 --- /dev/null +++ b/tests/ui/proc-macro/bang-macro.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:bang-macro.rs + +extern crate bang_macro; +use bang_macro::rewrite; + +fn main() { + assert_eq!(rewrite!("Hello, world!"), "NOT Hello, world!"); +} diff --git a/tests/ui/proc-macro/break-token-spans.rs b/tests/ui/proc-macro/break-token-spans.rs new file mode 100644 index 000000000..59dc3b504 --- /dev/null +++ b/tests/ui/proc-macro/break-token-spans.rs @@ -0,0 +1,16 @@ +// aux-build:test-macros.rs +// Regression test for issues #68489 and #70987 +// Tests that we properly break tokens in `probably_equal_for_proc_macro` +// See #72306 +// +// Note that the weird spacing in this example is critical +// for testing the issue. + +extern crate test_macros; + +#[test_macros::recollect_attr] +fn repro() { + f :: < Vec < _ > > ( ) ; //~ ERROR cannot find + let a: Option>= true; //~ ERROR mismatched +} +fn main() {} diff --git a/tests/ui/proc-macro/break-token-spans.stderr b/tests/ui/proc-macro/break-token-spans.stderr new file mode 100644 index 000000000..0a0322b8a --- /dev/null +++ b/tests/ui/proc-macro/break-token-spans.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find function `f` in this scope + --> $DIR/break-token-spans.rs:13:5 + | +LL | f :: < Vec < _ > > ( ) ; + | ^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/break-token-spans.rs:14:32 + | +LL | let a: Option>= true; + | ------------------ ^^^^ expected enum `Option`, found `bool` + | | + | expected due to this + | + = note: expected enum `Option>` + found type `bool` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/call-deprecated.rs b/tests/ui/proc-macro/call-deprecated.rs new file mode 100644 index 000000000..cb634671b --- /dev/null +++ b/tests/ui/proc-macro/call-deprecated.rs @@ -0,0 +1,34 @@ +// check-pass +// aux-build:call-deprecated.rs + +extern crate call_deprecated; + +// These first two `#[allow(deprecated)]` attributes +// do nothing, since the AST nodes for `First` and `Second` +// haven't been assigned a `NodeId`. +// See #63221 for a discussion about how we should +// handle the interaction of 'inert' attributes and +// proc-macro attributes. + +#[allow(deprecated)] +#[call_deprecated::attr] //~ WARN use of deprecated macro +struct First; + +#[allow(deprecated)] +#[call_deprecated::attr_remove] //~ WARN use of deprecated macro +struct Second; + +#[allow(deprecated)] +mod bar { + #[allow(deprecated)] + #[call_deprecated::attr] + struct Third; + + #[allow(deprecated)] + #[call_deprecated::attr_remove] + struct Fourth; +} + + +fn main() { +} diff --git a/tests/ui/proc-macro/call-deprecated.stderr b/tests/ui/proc-macro/call-deprecated.stderr new file mode 100644 index 000000000..3506f9a16 --- /dev/null +++ b/tests/ui/proc-macro/call-deprecated.stderr @@ -0,0 +1,16 @@ +warning: use of deprecated macro `call_deprecated::attr`: test + --> $DIR/call-deprecated.rs:14:3 + | +LL | #[call_deprecated::attr] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated macro `call_deprecated::attr_remove`: test + --> $DIR/call-deprecated.rs:18:3 + | +LL | #[call_deprecated::attr_remove] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/proc-macro/call-site.rs b/tests/ui/proc-macro/call-site.rs new file mode 100644 index 000000000..12c77250c --- /dev/null +++ b/tests/ui/proc-macro/call-site.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:call-site.rs + +extern crate call_site; + +fn main() { + let x1 = 10; + call_site::check!(let x2 = x1;); + let x6 = x5; +} diff --git a/tests/ui/proc-macro/capture-macro-rules-invoke.rs b/tests/ui/proc-macro/capture-macro-rules-invoke.rs new file mode 100644 index 000000000..de008a370 --- /dev/null +++ b/tests/ui/proc-macro/capture-macro-rules-invoke.rs @@ -0,0 +1,57 @@ +// aux-build:test-macros.rs +// check-pass +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; +use test_macros::{print_bang, print_bang_consume}; + +macro_rules! test_matchers { + ($expr:expr, $block:block, $stmt:stmt, $ty:ty, $ident:ident, $lifetime:lifetime, + $meta:meta, $path:path, $vis:vis, $tt:tt, $lit:literal) => { + print_bang_consume!($expr, $block, $stmt, $ty, $ident, + $lifetime, $meta, $path, $vis, $tt, $lit) + } +} + +macro_rules! use_expr { + ($expr:expr) => { + print_bang!($expr) + } +} + +macro_rules! use_pat { + ($pat:pat) => { + print_bang!($pat) + } +} + +#[allow(dead_code)] +struct Foo; +impl Foo { + #[allow(dead_code)] + fn use_self(self) { + drop(use_expr!(self)); + test_matchers!( + 1 + 1, + { "a" }, + let a = 1, + String, + my_name, + 'a, + my_val = 30, + std::option::Option, + pub(in some::path), + [ a b c ], + -30 + ); + } + + fn with_pat(use_pat!((a, b)): (u32, u32)) { + let _ = (a, b); + } +} + +fn main() {} diff --git a/tests/ui/proc-macro/capture-macro-rules-invoke.stdout b/tests/ui/proc-macro/capture-macro-rules-invoke.stdout new file mode 100644 index 000000000..b88fbd3e8 --- /dev/null +++ b/tests/ui/proc-macro/capture-macro-rules-invoke.stdout @@ -0,0 +1,324 @@ +PRINT-BANG INPUT (DISPLAY): self +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "self", + span: $DIR/capture-macro-rules-invoke.rs:36:24: 36:28 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:21:21: 21:26 (#4), + }, +] +PRINT-BANG INPUT (DISPLAY): 1 + 1, { "a" }, let a = 1;, String, my_name, 'a, my_val = 30, +std::option::Option, pub(in some::path) , [a b c], -30 +PRINT-BANG RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30, +std :: option :: Option, pub(in some :: path), [a b c], - 30 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:38:13: 38:14 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:38:15: 38:16 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:38:17: 38:18 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:29: 14:34 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:34: 14:35 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "a", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:39:15: 39:18 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:39:13: 39:20 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:36: 14:42 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:42: 14:43 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "let", + span: $DIR/capture-macro-rules-invoke.rs:40:13: 40:16 (#0), + }, + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:40:17: 40:18 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:40:19: 40:20 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:40:21: 40:22 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:44: 14:49 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:49: 14:50 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "String", + span: $DIR/capture-macro-rules-invoke.rs:41:13: 41:19 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:14:51: 14:54 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:54: 14:55 (#8), + }, + Ident { + ident: "my_name", + span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:14:62: 14:63 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: '\'', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:43:13: 43:15 (#0), + }, + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:43:13: 43:15 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:29: 15:38 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:38: 15:39 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "my_val", + span: $DIR/capture-macro-rules-invoke.rs:44:13: 44:19 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:44:20: 44:21 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:44:22: 44:24 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:40: 15:45 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:45: 15:46 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "std", + span: $DIR/capture-macro-rules-invoke.rs:45:13: 45:16 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:17 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:45:17: 45:18 (#0), + }, + Ident { + ident: "option", + span: $DIR/capture-macro-rules-invoke.rs:45:18: 45:24 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:25 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:45:25: 45:26 (#0), + }, + Ident { + ident: "Option", + span: $DIR/capture-macro-rules-invoke.rs:45:26: 45:32 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:47: 15:52 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:52: 15:53 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "pub", + span: $DIR/capture-macro-rules-invoke.rs:46:13: 46:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "in", + span: $DIR/capture-macro-rules-invoke.rs:46:17: 46:19 (#0), + }, + Ident { + ident: "some", + span: $DIR/capture-macro-rules-invoke.rs:46:20: 46:24 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:25 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:46:25: 46:26 (#0), + }, + Ident { + ident: "path", + span: $DIR/capture-macro-rules-invoke.rs:46:26: 46:30 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:46:16: 46:31 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:54: 15:58 (#8), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:58: 15:59 (#8), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:47:15: 47:16 (#0), + }, + Ident { + ident: "b", + span: $DIR/capture-macro-rules-invoke.rs:47:17: 47:18 (#0), + }, + Ident { + ident: "c", + span: $DIR/capture-macro-rules-invoke.rs:47:19: 47:20 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:47:13: 47:22 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:15:63: 15:64 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: '-', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:48:13: 48:14 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/capture-macro-rules-invoke.rs:48:14: 48:16 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:15:65: 15:69 (#8), + }, +] +PRINT-BANG INPUT (DISPLAY): (a, b) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/capture-macro-rules-invoke.rs:52:27: 52:28 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/capture-macro-rules-invoke.rs:52:28: 52:29 (#0), + }, + Ident { + ident: "b", + span: $DIR/capture-macro-rules-invoke.rs:52:30: 52:31 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:52:26: 52:32 (#0), + }, + ], + span: $DIR/capture-macro-rules-invoke.rs:27:21: 27:25 (#12), + }, +] diff --git a/tests/ui/proc-macro/capture-unglued-token.rs b/tests/ui/proc-macro/capture-unglued-token.rs new file mode 100644 index 000000000..727b77977 --- /dev/null +++ b/tests/ui/proc-macro/capture-unglued-token.rs @@ -0,0 +1,20 @@ +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// check-pass + +// Tests that we properly handle parsing a nonterminal +// where we have two consecutive angle brackets (one inside +// the nonterminal, and one outside) + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; +extern crate test_macros; + +macro_rules! trailing_angle { + (Option<$field:ty>) => { + test_macros::print_bang_consume!($field); + } +} + +trailing_angle!(Option>); +fn main() {} diff --git a/tests/ui/proc-macro/capture-unglued-token.stdout b/tests/ui/proc-macro/capture-unglued-token.stdout new file mode 100644 index 000000000..7e6b54033 --- /dev/null +++ b/tests/ui/proc-macro/capture-unglued-token.stdout @@ -0,0 +1,28 @@ +PRINT-BANG INPUT (DISPLAY): Vec +PRINT-BANG RE-COLLECTED (DISPLAY): Vec < u8 > +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "Vec", + span: $DIR/capture-unglued-token.rs:19:24: 19:27 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/capture-unglued-token.rs:19:27: 19:28 (#0), + }, + Ident { + ident: "u8", + span: $DIR/capture-unglued-token.rs:19:28: 19:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/capture-unglued-token.rs:19:30: 19:31 (#0), + }, + ], + span: $DIR/capture-unglued-token.rs:15:42: 15:48 (#4), + }, +] diff --git a/tests/ui/proc-macro/cfg-eval-fail.rs b/tests/ui/proc-macro/cfg-eval-fail.rs new file mode 100644 index 000000000..a259aa2e6 --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval-fail.rs @@ -0,0 +1,7 @@ +#![feature(cfg_eval)] +#![feature(stmt_expr_attributes)] + +fn main() { + let _ = #[cfg_eval] #[cfg(FALSE)] 0; + //~^ ERROR removing an expression is not supported in this position +} diff --git a/tests/ui/proc-macro/cfg-eval-fail.stderr b/tests/ui/proc-macro/cfg-eval-fail.stderr new file mode 100644 index 000000000..df8b6d5f3 --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval-fail.stderr @@ -0,0 +1,8 @@ +error: removing an expression is not supported in this position + --> $DIR/cfg-eval-fail.rs:5:25 + | +LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/cfg-eval-inner.rs b/tests/ui/proc-macro/cfg-eval-inner.rs new file mode 100644 index 000000000..5fd3ca0d1 --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval-inner.rs @@ -0,0 +1,39 @@ +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// check-pass + +#![feature(cfg_eval)] +#![feature(custom_inner_attributes)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +struct Foo(T); + +impl Foo<[u8; { + #![cfg_attr(not(FALSE), rustc_dummy(cursed_inner))] + #![allow(unused)] + struct Inner { + field: [u8; { + #![cfg_attr(not(FALSE), rustc_dummy(another_cursed_inner))] + 1 + }] + } + + 0 +}]> { + #![cfg_eval] + #![print_attr] + #![cfg_attr(not(FALSE), rustc_dummy(evaluated_attr))] + + fn bar() { + #[cfg(FALSE)] let a = 1; + } +} + +fn main() {} diff --git a/tests/ui/proc-macro/cfg-eval-inner.stdout b/tests/ui/proc-macro/cfg-eval-inner.stdout new file mode 100644 index 000000000..9d25def58 --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval-inner.stdout @@ -0,0 +1,247 @@ +PRINT-ATTR INPUT (DISPLAY): impl Foo < +[u8 ; +{ + #! [rustc_dummy(cursed_inner)] #! [allow(unused)] struct Inner + { field : [u8 ; { #! [rustc_dummy(another_cursed_inner)] 1 }] } 0 +}] > { #! [rustc_dummy(evaluated_attr)] fn bar() {} } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/cfg-eval-inner.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/cfg-eval-inner.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/cfg-eval-inner.rs:18:11: 18:13 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:18:13: 18:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:19:29: 19:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "cursed_inner", + span: $DIR/cfg-eval-inner.rs:19:41: 19:53 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:19:40: 19:54 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/cfg-eval-inner.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/cfg-eval-inner.rs:20:8: 20:13 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused", + span: $DIR/cfg-eval-inner.rs:20:14: 20:20 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:20:13: 20:21 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:20:7: 20:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/cfg-eval-inner.rs:21:5: 21:11 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/cfg-eval-inner.rs:21:12: 21:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/cfg-eval-inner.rs:22:9: 22:14 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:22:14: 22:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/cfg-eval-inner.rs:22:17: 22:19 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:22:19: 22:20 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:23:14: 23:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:23:37: 23:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "another_cursed_inner", + span: $DIR/cfg-eval-inner.rs:23:49: 23:69 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:23:48: 23:70 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/cfg-eval-inner.rs:24:13: 24:14 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:22:21: 25:10 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:22:16: 25:11 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:21:18: 26:6 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/cfg-eval-inner.rs:28:5: 28:6 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:18:15: 29:2 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:18:10: 29:3 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:29:3: 29:4 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/cfg-eval-inner.rs:32:6: 32:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval-inner.rs:32:29: 32:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "evaluated_attr", + span: $DIR/cfg-eval-inner.rs:32:41: 32:55 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:32:40: 32:56 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0), + }, + Ident { + ident: "fn", + span: $DIR/cfg-eval-inner.rs:34:5: 34:7 (#0), + }, + Ident { + ident: "bar", + span: $DIR/cfg-eval-inner.rs:34:8: 34:11 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval-inner.rs:34:11: 34:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/cfg-eval-inner.rs:34:14: 36:6 (#0), + }, + ], + span: $DIR/cfg-eval-inner.rs:29:5: 37:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/cfg-eval.rs b/tests/ui/proc-macro/cfg-eval.rs new file mode 100644 index 000000000..fa6d015e4 --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval.rs @@ -0,0 +1,37 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![feature(cfg_eval)] +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[cfg_eval] +#[print_attr] +struct S1 { + #[cfg(FALSE)] + field_false: u8, + #[cfg(all(/*true*/))] + #[cfg_attr(FALSE, unknown_attr)] + #[cfg_attr(all(/*true*/), allow())] + field_true: u8, +} + +#[cfg_eval] +#[cfg(FALSE)] +struct S2 {} + +fn main() { + // Subtle - we need a trailing comma after the '1' - otherwise, `#[cfg_eval]` will + // turn this into `(#[cfg(all())] 1)`, which is a parenthesized expression, not a tuple + // expression. `#[cfg]` is not supported inside parenthesized expressions, so this will + // produce an error when attribute collection runs. + let _ = #[cfg_eval] #[print_attr] #[cfg_attr(not(FALSE), rustc_dummy)] + (#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1,); +} diff --git a/tests/ui/proc-macro/cfg-eval.stdout b/tests/ui/proc-macro/cfg-eval.stdout new file mode 100644 index 000000000..6732caf08 --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval.stdout @@ -0,0 +1,150 @@ +PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/cfg-eval.rs:17:1: 17:7 (#0), + }, + Ident { + ident: "S1", + span: $DIR/cfg-eval.rs:17:8: 17:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:20:5: 20:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/cfg-eval.rs:20:7: 20:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "all", + span: $DIR/cfg-eval.rs:20:11: 20:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval.rs:20:14: 20:24 (#0), + }, + ], + span: $DIR/cfg-eval.rs:20:10: 20:25 (#0), + }, + ], + span: $DIR/cfg-eval.rs:20:6: 20:26 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:22:5: 22:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/cfg-eval.rs:22:31: 22:36 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval.rs:22:36: 22:38 (#0), + }, + ], + span: $DIR/cfg-eval.rs:22:5: 22:6 (#0), + }, + Ident { + ident: "field_true", + span: $DIR/cfg-eval.rs:23:5: 23:15 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/cfg-eval.rs:23:15: 23:16 (#0), + }, + Ident { + ident: "u8", + span: $DIR/cfg-eval.rs:23:17: 23:19 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/cfg-eval.rs:23:19: 23:20 (#0), + }, + ], + span: $DIR/cfg-eval.rs:17:11: 24:2 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] (#[cfg(all())] 1,) +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:35:39: 35:40 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/cfg-eval.rs:35:62: 35:73 (#0), + }, + ], + span: $DIR/cfg-eval.rs:35:39: 35:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/cfg-eval.rs:36:23: 36:24 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/cfg-eval.rs:36:25: 36:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "all", + span: $DIR/cfg-eval.rs:36:29: 36:32 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/cfg-eval.rs:36:32: 36:42 (#0), + }, + ], + span: $DIR/cfg-eval.rs:36:28: 36:43 (#0), + }, + ], + span: $DIR/cfg-eval.rs:36:24: 36:44 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/cfg-eval.rs:36:45: 36:46 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/cfg-eval.rs:36:46: 36:47 (#0), + }, + ], + span: $DIR/cfg-eval.rs:36:5: 36:48 (#0), + }, +] diff --git a/tests/ui/proc-macro/count_compound_ops.rs b/tests/ui/proc-macro/count_compound_ops.rs new file mode 100644 index 000000000..2cb871844 --- /dev/null +++ b/tests/ui/proc-macro/count_compound_ops.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:count_compound_ops.rs + +extern crate count_compound_ops; +use count_compound_ops::count_compound_ops; + +fn main() { + assert_eq!(count_compound_ops!(foo<=>bar << { + // derive_Double outputs secondary copies of each definition + // to test what the proc_macro sees. + mod bar { + #[derive(Double)] + struct Bar($crate::Foo); + } + + mod qself { + #[derive(Double)] + struct QSelf(<::Foo as $crate::Trait>::Assoc); + } + + mod qself_recurse { + #[derive(Double)] + struct QSelfRecurse(<<$crate::Foo as $crate::Trait>::Assoc as $crate::Trait>::Assoc); + } + + mod qself_in_const { + #[derive(Double)] + #[repr(u32)] + enum QSelfInConst { + Variant = <::Foo as $crate::Trait>::CONST, + } + } +} } + +mod local { + local!(); +} + +// and now repeat the above tests, using a macro defined in another crate + +mod external { + external!{} +} + +fn main() {} diff --git a/tests/ui/proc-macro/crt-static.rs b/tests/ui/proc-macro/crt-static.rs new file mode 100644 index 000000000..6103acb7b --- /dev/null +++ b/tests/ui/proc-macro/crt-static.rs @@ -0,0 +1,24 @@ +// Test proc-macro crate can be built without additional RUSTFLAGS +// on musl target +// override -Ctarget-feature=-crt-static from compiletest +// compile-flags: --crate-type proc-macro -Ctarget-feature= +// ignore-wasm32 +// ignore-sgx no support for proc-macro crate type +// build-pass +#![crate_type = "proc-macro"] + +// FIXME: This don't work when crate-type is specified by attribute +// `#![crate_type = "proc-macro"]`, not by `--crate-type=proc-macro` +// command line flag. This is because the list of `cfg` symbols is generated +// before attributes are parsed. See rustc_interface::util::add_configuration +#[cfg(target_feature = "crt-static")] +compile_error!("crt-static is enabled"); + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + input +} diff --git a/tests/ui/proc-macro/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/custom-attr-only-one-derive.rs new file mode 100644 index 000000000..2cd5b4873 --- /dev/null +++ b/tests/ui/proc-macro/custom-attr-only-one-derive.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:custom-attr-only-one-derive.rs + +#![feature(rust_2018_preview)] + +#[macro_use] +extern crate custom_attr_only_one_derive; + +#[derive(Bar, Foo)] +#[custom = "test"] +pub enum A { + B, + C, +} + +fn main() {} diff --git a/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs new file mode 100644 index 000000000..56ad0612f --- /dev/null +++ b/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "macro_dump_debug"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dump_debug(tokens: TokenStream) -> TokenStream { + eprintln!("{:?}", tokens); + eprintln!("{:#?}", tokens); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/debug/dump-debug-span-debug.rs b/tests/ui/proc-macro/debug/dump-debug-span-debug.rs new file mode 100644 index 000000000..102bd6b7b --- /dev/null +++ b/tests/ui/proc-macro/debug/dump-debug-span-debug.rs @@ -0,0 +1,46 @@ +// run-pass +// aux-build:macro-dump-debug.rs +// compile-flags: -Z span-debug + + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + && // joint punct, two-char op + ||> // joint punct, two-char op + one-char op + ||<< // joint punct, two-char op + two-char op + ..= // joint punct, three-char op + <<=! // joint punct, three-char op + one-char-op + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/tests/ui/proc-macro/debug/dump-debug-span-debug.stderr b/tests/ui/proc-macro/debug/dump-debug-span-debug.stderr new file mode 100644 index 000000000..fa65cbbf1 --- /dev/null +++ b/tests/ui/proc-macro/debug/dump-debug-span-debug.stderr @@ -0,0 +1,231 @@ +TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:11:5: 11:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:5: 12:6 (#0) }, Punct { ch: '&', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:13:5: 13:6 (#0) }, Punct { ch: '&', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:13:6: 13:7 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:14:5: 14:6 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:14:7: 14:8 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:15:5: 15:6 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:15:6: 15:7 (#0) }, Punct { ch: '<', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:15:7: 15:8 (#0) }, Punct { ch: '<', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:15:8: 15:9 (#0) }, Punct { ch: '.', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:16:5: 16:6 (#0) }, Punct { ch: '.', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:16:6: 16:7 (#0) }, Punct { ch: '=', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:16:7: 16:8 (#0) }, Punct { ch: '<', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Punct { ch: '<', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:17:6: 17:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:17:7: 17:8 (#0) }, Punct { ch: '!', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:17:8: 17:9 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:18:5: 18:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:19:6: 19:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:27:5: 27:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:28:5: 28:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:29:5: 29:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:30:5: 30:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:39:5: 39:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:40:5: 40:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:41:5: 41:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:42:5: 42:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:43:5: 43:10 (#0) }] +TokenStream [ + Ident { + ident: "ident", + span: $DIR/dump-debug-span-debug.rs:10:5: 10:10 (#0), + }, + Ident { + ident: "r#ident", + span: $DIR/dump-debug-span-debug.rs:11:5: 11:12 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:12:5: 12:6 (#0), + }, + Punct { + ch: '&', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:13:5: 13:6 (#0), + }, + Punct { + ch: '&', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:13:6: 13:7 (#0), + }, + Punct { + ch: '|', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:14:5: 14:6 (#0), + }, + Punct { + ch: '|', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:14:7: 14:8 (#0), + }, + Punct { + ch: '|', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:15:5: 15:6 (#0), + }, + Punct { + ch: '|', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:15:6: 15:7 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:15:7: 15:8 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:15:8: 15:9 (#0), + }, + Punct { + ch: '.', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:16:5: 16:6 (#0), + }, + Punct { + ch: '.', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:16:6: 16:7 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:16:7: 16:8 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:17:6: 17:7 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/dump-debug-span-debug.rs:17:7: 17:8 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/dump-debug-span-debug.rs:17:8: 17:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/dump-debug-span-debug.rs:18:5: 18:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: $DIR/dump-debug-span-debug.rs:19:6: 19:7 (#0), + }, + ], + span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:22:5: 22:6 (#0), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:23:5: 23:8 (#0), + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:24:5: 24:8 (#0), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:25:5: 25:9 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:27:5: 27:13 (#0), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:28:5: 28:11 (#0), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:29:5: 29:15 (#0), + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:30:5: 30:8 (#0), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:34:5: 34:7 (#0), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:35:5: 35:9 (#0), + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:36:5: 36:9 (#0), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:37:5: 37:10 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:39:5: 39:14 (#0), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:40:5: 40:12 (#0), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:41:5: 41:16 (#0), + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:42:5: 42:9 (#0), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: $DIR/dump-debug-span-debug.rs:43:5: 43:10 (#0), + }, +] diff --git a/tests/ui/proc-macro/debug/dump-debug.rs b/tests/ui/proc-macro/debug/dump-debug.rs new file mode 100644 index 000000000..0ed36b690 --- /dev/null +++ b/tests/ui/proc-macro/debug/dump-debug.rs @@ -0,0 +1,40 @@ +// run-pass +// aux-build:macro-dump-debug.rs + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + ==> // joint punct + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/tests/ui/proc-macro/debug/dump-debug.stderr b/tests/ui/proc-macro/debug/dump-debug.stderr new file mode 100644 index 000000000..db422b601 --- /dev/null +++ b/tests/ui/proc-macro/debug/dump-debug.stderr @@ -0,0 +1,166 @@ +TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..204) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(204..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }] +TokenStream [ + Ident { + ident: "ident", + span: #0 bytes(130..135), + }, + Ident { + ident: "r#ident", + span: #0 bytes(151..158), + }, + Punct { + ch: ',', + spacing: Alone, + span: #0 bytes(176..177), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..204), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(204..205), + }, + Punct { + ch: '>', + spacing: Alone, + span: #0 bytes(205..206), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: #0 bytes(230..232), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: #0 bytes(258..259), + }, + ], + span: #0 bytes(257..260), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(315..316), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: #0 bytes(321..324), + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: #0 bytes(329..332), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: #0 bytes(337..341), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: #0 bytes(346..350), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: #0 bytes(355..363), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: #0 bytes(368..374), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: #0 bytes(379..389), + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: #0 bytes(394..397), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: #0 bytes(402..406), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: #0 bytes(437..439), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: #0 bytes(444..448), + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: #0 bytes(453..457), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(462..467), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(472..477), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(482..491), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(496..503), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(508..519), + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: #0 bytes(524..528), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(533..538), + }, +] diff --git a/tests/ui/proc-macro/define-two.rs b/tests/ui/proc-macro/define-two.rs new file mode 100644 index 000000000..b2184eae3 --- /dev/null +++ b/tests/ui/proc-macro/define-two.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(A)] +pub fn foo(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times +pub fn bar(input: TokenStream) -> TokenStream { + input +} diff --git a/tests/ui/proc-macro/define-two.stderr b/tests/ui/proc-macro/define-two.stderr new file mode 100644 index 000000000..bf1bd8427 --- /dev/null +++ b/tests/ui/proc-macro/define-two.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/define-two.rs:15:21 + | +LL | #[proc_macro_derive(A)] + | - previous definition of the macro `A` here +... +LL | #[proc_macro_derive(A)] + | ^ `A` redefined here + | + = note: `A` must be defined only once in the macro namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/proc-macro/derive-attr-cfg.rs b/tests/ui/proc-macro/derive-attr-cfg.rs new file mode 100644 index 000000000..394774628 --- /dev/null +++ b/tests/ui/proc-macro/derive-attr-cfg.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(dead_code)] +// aux-build:derive-attr-cfg.rs + +extern crate derive_attr_cfg; +use derive_attr_cfg::Foo; + +#[derive(Foo)] +#[foo] +struct S { + #[cfg(any())] + x: i32 +} + +fn main() { +} diff --git a/tests/ui/proc-macro/derive-b.rs b/tests/ui/proc-macro/derive-b.rs new file mode 100644 index 000000000..a026c2bd7 --- /dev/null +++ b/tests/ui/proc-macro/derive-b.rs @@ -0,0 +1,19 @@ +// run-pass +// aux-build:derive-b-rpass.rs + +extern crate derive_b_rpass as derive_b; + +#[derive(Debug, PartialEq, derive_b::B, Eq, Copy, Clone)] +#[cfg_attr(all(), B[arbitrary tokens])] +struct B { + #[C] + a: u64 +} + +fn main() { + B { a: 3 }; + assert_eq!(B { a: 3 }, B { a: 3 }); + let b = B { a: 3 }; + let _d = b; + let _e = b; +} diff --git a/tests/ui/proc-macro/derive-bad.rs b/tests/ui/proc-macro/derive-bad.rs new file mode 100644 index 000000000..cb5188b5f --- /dev/null +++ b/tests/ui/proc-macro/derive-bad.rs @@ -0,0 +1,11 @@ +// aux-build:derive-bad.rs + +#[macro_use] +extern crate derive_bad; + +#[derive(A)] +//~^ ERROR proc-macro derive produced unparseable tokens +//~| ERROR expected `:`, found `}` +struct A; //~ ERROR the name `A` is defined multiple times + +fn main() {} diff --git a/tests/ui/proc-macro/derive-bad.stderr b/tests/ui/proc-macro/derive-bad.stderr new file mode 100644 index 000000000..241f99b28 --- /dev/null +++ b/tests/ui/proc-macro/derive-bad.stderr @@ -0,0 +1,31 @@ +error: expected `:`, found `}` + --> $DIR/derive-bad.rs:6:10 + | +LL | #[derive(A)] + | ^ + | | + | expected `:` + | while parsing this struct + | + = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc-macro derive produced unparseable tokens + --> $DIR/derive-bad.rs:6:10 + | +LL | #[derive(A)] + | ^ + +error[E0428]: the name `A` is defined multiple times + --> $DIR/derive-bad.rs:9:1 + | +LL | #[derive(A)] + | - previous definition of the type `A` here +... +LL | struct A; + | ^^^^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/proc-macro/derive-expand-order.rs b/tests/ui/proc-macro/derive-expand-order.rs new file mode 100644 index 000000000..0cf1ceb91 --- /dev/null +++ b/tests/ui/proc-macro/derive-expand-order.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:multiple-derives.rs + +extern crate multiple_derives; + +use multiple_derives::*; + +#[derive(First)] +#[derive(Second)] +#[derive(Third, Fourth)] +#[derive(Fifth)] +pub struct Foo {} + +fn main() {} diff --git a/tests/ui/proc-macro/derive-expand-order.stdout b/tests/ui/proc-macro/derive-expand-order.stdout new file mode 100644 index 000000000..dffbbf149 --- /dev/null +++ b/tests/ui/proc-macro/derive-expand-order.stdout @@ -0,0 +1,5 @@ +Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {} +Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {} +Derive Third: #[derive(Fifth)] pub struct Foo {} +Derive Fourth: #[derive(Fifth)] pub struct Foo {} +Derive Fifth: pub struct Foo {} diff --git a/tests/ui/proc-macro/derive-helper-configured.rs b/tests/ui/proc-macro/derive-helper-configured.rs new file mode 100644 index 000000000..243cf685e --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-configured.rs @@ -0,0 +1,18 @@ +// Derive helpers are resolved successfully inside `cfg_attr`. + +// check-pass +// compile-flats:--cfg TRUE +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[cfg_attr(TRUE, empty_helper)] +#[derive(Empty)] +#[cfg_attr(TRUE, empty_helper)] +struct S { + #[cfg_attr(TRUE, empty_helper)] + field: u8, +} + +fn main() {} diff --git a/tests/ui/proc-macro/derive-helper-legacy-limits.rs b/tests/ui/proc-macro/derive-helper-legacy-limits.rs new file mode 100644 index 000000000..ca904900d --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-legacy-limits.rs @@ -0,0 +1,21 @@ +// Support for legacy derive helpers is limited and heuristic-based +// (that's exactly the reason why they are deprecated). + +// edition:2018 +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +use derive as my_derive; + +#[my_derive(Empty)] +#[empty_helper] // OK +struct S1; + +// Legacy helper detection doesn't see through `derive` renaming. +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +#[my_derive(Empty)] +struct S2; + +fn main() {} diff --git a/tests/ui/proc-macro/derive-helper-legacy-limits.stderr b/tests/ui/proc-macro/derive-helper-legacy-limits.stderr new file mode 100644 index 000000000..186f38a00 --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-legacy-limits.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-legacy-limits.rs:17:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs new file mode 100644 index 000000000..4a7e48eed --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs + +#![dummy] //~ ERROR cannot find attribute `dummy` in this scope + +#[macro_use] +extern crate test_macros; + +#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +struct Foo {} + +fn main() {} diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr new file mode 100644 index 000000000..fd1ed8a3d --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr @@ -0,0 +1,22 @@ +error: cannot find attribute `dummy` in this scope + --> $DIR/derive-helper-legacy-spurious.rs:3:4 + | +LL | #![dummy] + | ^^^^^ + +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/derive-helper-legacy-spurious.rs:8:3 + | +LL | #[derive(Empty)] + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-legacy-spurious.rs:9:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/proc-macro/derive-helper-shadowed.rs b/tests/ui/proc-macro/derive-helper-shadowed.rs new file mode 100644 index 000000000..e299454e0 --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-shadowed.rs @@ -0,0 +1,16 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs +// aux-build:derive-helper-shadowed-2.rs + +#[macro_use] +extern crate test_macros; +#[macro_use(empty_helper)] +extern crate derive_helper_shadowed_2; + +macro_rules! empty_helper { () => () } + +#[derive(Empty)] +#[empty_helper] // OK +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/derive-helper-shadowing-2.rs new file mode 100644 index 000000000..5204d72b9 --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-shadowing-2.rs @@ -0,0 +1,16 @@ +// If a derive macro introduces a helper attribute with the same name as that macro, +// then make sure that it's usable without ambiguities. + +// check-pass +// aux-build:derive-helper-shadowing-2.rs + +#[macro_use] +extern crate derive_helper_shadowing_2; + +#[derive(same_name)] +struct S { + #[same_name] // OK, no ambiguity, derive helpers have highest priority + field: u8, +} + +fn main() {} diff --git a/tests/ui/proc-macro/derive-helper-shadowing.rs b/tests/ui/proc-macro/derive-helper-shadowing.rs new file mode 100644 index 000000000..80d982d25 --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-shadowing.rs @@ -0,0 +1,56 @@ +// edition:2018 +// aux-build:test-macros.rs +// aux-build:derive-helper-shadowing.rs + +#[macro_use] +extern crate test_macros; +#[macro_use] +extern crate derive_helper_shadowing; + +use test_macros::empty_attr as empty_helper; + +macro_rules! gen_helper_use { + () => { + #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope + struct W; + } +} + +#[empty_helper] //~ ERROR `empty_helper` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(Empty)] +struct S { + #[empty_helper] // OK, no ambiguity, derive helpers have highest priority + field: [u8; { + use empty_helper; //~ ERROR `empty_helper` is ambiguous + + #[empty_helper] // OK, no ambiguity, derive helpers have highest priority + struct U; + + mod inner { + // OK, no ambiguity, the non-helper attribute is not in scope here, only the helper. + #[empty_helper] + struct V; + + gen_helper_use!(); + + #[derive(GenHelperUse)] //~ ERROR cannot find attribute `empty_helper` in this scope + struct Owo; + + use empty_helper as renamed; + #[renamed] //~ ERROR cannot use a derive helper attribute through an import + struct Wow; + } + + 0 + }] +} + +// OK, no ambiguity, only the non-helper attribute is in scope. +#[empty_helper] +struct Z; + +fn main() { + let s = S { field: [] }; +} diff --git a/tests/ui/proc-macro/derive-helper-shadowing.stderr b/tests/ui/proc-macro/derive-helper-shadowing.stderr new file mode 100644 index 000000000..de2c27a87 --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-shadowing.stderr @@ -0,0 +1,89 @@ +error: cannot use a derive helper attribute through an import + --> $DIR/derive-helper-shadowing.rs:42:15 + | +LL | #[renamed] + | ^^^^^^^ + | +note: the derive helper attribute imported here + --> $DIR/derive-helper-shadowing.rs:41:17 + | +LL | use empty_helper as renamed; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-shadowing.rs:38:22 + | +LL | #[derive(GenHelperUse)] + | ^^^^^^^^^^^^ + | + = help: consider importing this attribute macro: + empty_helper + = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find attribute `empty_helper` in this scope + --> $DIR/derive-helper-shadowing.rs:14:11 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | gen_helper_use!(); + | ----------------- in this macro invocation + | + = help: consider importing this attribute macro: + crate::empty_helper + = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `empty_helper` is ambiguous + --> $DIR/derive-helper-shadowing.rs:26:13 + | +LL | use empty_helper; + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:22:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:10:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +error[E0659]: `empty_helper` is ambiguous + --> $DIR/derive-helper-shadowing.rs:19:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:22:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:10:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +warning: derive helper attribute is used before it is introduced + --> $DIR/derive-helper-shadowing.rs:19:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | #[derive(Empty)] + | ----- the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + = note: `#[warn(legacy_derive_helpers)]` on by default + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/proc-macro/derive-helper-vs-legacy.rs b/tests/ui/proc-macro/derive-helper-vs-legacy.rs new file mode 100644 index 000000000..98836bcb8 --- /dev/null +++ b/tests/ui/proc-macro/derive-helper-vs-legacy.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Empty)] +#[empty_helper] // OK, this is both derive helper and legacy derive helper +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/derive-in-mod.rs b/tests/ui/proc-macro/derive-in-mod.rs new file mode 100644 index 000000000..8b5d4e9d0 --- /dev/null +++ b/tests/ui/proc-macro/derive-in-mod.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +extern crate test_macros; + +mod inner { + use test_macros::Empty; + + #[derive(Empty)] + struct S; +} + +fn main() {} diff --git a/tests/ui/proc-macro/derive-multiple-with-packed.rs b/tests/ui/proc-macro/derive-multiple-with-packed.rs new file mode 100644 index 000000000..23578aa0e --- /dev/null +++ b/tests/ui/proc-macro/derive-multiple-with-packed.rs @@ -0,0 +1,11 @@ +// check-pass + +#[derive(Clone, Copy)] +#[derive(Debug)] // OK, even if `Copy` is in the different `#[derive]` +#[derive(PartialEq)] // OK too +#[repr(packed)] +struct CacheRecordHeader { + field: u64, +} + +fn main() {} diff --git a/tests/ui/proc-macro/derive-same-struct.rs b/tests/ui/proc-macro/derive-same-struct.rs new file mode 100644 index 000000000..528b0f22a --- /dev/null +++ b/tests/ui/proc-macro/derive-same-struct.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(path_statements)] +#![allow(dead_code)] +// aux-build:derive-same-struct.rs + +#[macro_use] +extern crate derive_same_struct; + +#[derive(AToB)] +struct A; + +fn main() { + C; +} diff --git a/tests/ui/proc-macro/derive-same-struct.stdout b/tests/ui/proc-macro/derive-same-struct.stdout new file mode 100644 index 000000000..7478d9741 --- /dev/null +++ b/tests/ui/proc-macro/derive-same-struct.stdout @@ -0,0 +1 @@ +input1: "struct A ;" diff --git a/tests/ui/proc-macro/derive-still-gated.rs b/tests/ui/proc-macro/derive-still-gated.rs new file mode 100644 index 000000000..3f8d6f071 --- /dev/null +++ b/tests/ui/proc-macro/derive-still-gated.rs @@ -0,0 +1,9 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope +struct A; + +fn main() {} diff --git a/tests/ui/proc-macro/derive-still-gated.stderr b/tests/ui/proc-macro/derive-still-gated.stderr new file mode 100644 index 000000000..99289fdfe --- /dev/null +++ b/tests/ui/proc-macro/derive-still-gated.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `derive_Empty` in this scope + --> $DIR/derive-still-gated.rs:6:3 + | +LL | #[derive_Empty] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/derive-test.rs b/tests/ui/proc-macro/derive-test.rs new file mode 100644 index 000000000..b81e38432 --- /dev/null +++ b/tests/ui/proc-macro/derive-test.rs @@ -0,0 +1,22 @@ +// run-pass +// no-prefer-dynamic +// compile-flags: --test + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +// ``` +// assert!(true); +// ``` +#[proc_macro_derive(Foo)] +pub fn derive_foo(_input: TokenStream) -> TokenStream { + "".parse().unwrap() +} + +#[test] +pub fn test_derive() { + assert!(true); +} diff --git a/tests/ui/proc-macro/derive-two-attrs.rs b/tests/ui/proc-macro/derive-two-attrs.rs new file mode 100644 index 000000000..08225b8e3 --- /dev/null +++ b/tests/ui/proc-macro/derive-two-attrs.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +// aux-build:derive-two-attrs.rs + +extern crate derive_two_attrs as foo; + +use foo::A; + +#[derive(A)] +#[b] +#[b] +struct B; + +fn main() {} diff --git a/tests/ui/proc-macro/derive-union.rs b/tests/ui/proc-macro/derive-union.rs new file mode 100644 index 000000000..e83eee093 --- /dev/null +++ b/tests/ui/proc-macro/derive-union.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(unused_variables)] +// aux-build:derive-union.rs + +#[macro_use] +extern crate derive_union; + +#[repr(C)] +#[derive(UnionTest)] +union Test { + a: u8, +} + +fn main() { + let t = Test { a: 0 }; +} diff --git a/tests/ui/proc-macro/disappearing-resolution.rs b/tests/ui/proc-macro/disappearing-resolution.rs new file mode 100644 index 000000000..50f04b1ea --- /dev/null +++ b/tests/ui/proc-macro/disappearing-resolution.rs @@ -0,0 +1,22 @@ +// Regression test for issue #64803 (initial attribute resolution can disappear later). + +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod m { + use test_macros::Empty; +} +use m::Empty; //~ ERROR derive macro import `Empty` is private + +// To resolve `empty_helper` we need to resolve `Empty`. +// During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`, +// successfully resolve `Empty` from there, and then resolve `empty_helper` as its helper. +// During validation `use m::Empty` introduces a `Res::Err` stub, so `Empty` resolves to it, +// and `empty_helper` can no longer be resolved. +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/disappearing-resolution.stderr b/tests/ui/proc-macro/disappearing-resolution.stderr new file mode 100644 index 000000000..5b969549a --- /dev/null +++ b/tests/ui/proc-macro/disappearing-resolution.stderr @@ -0,0 +1,26 @@ +error: cannot find attribute `empty_helper` in this scope + --> $DIR/disappearing-resolution.rs:18:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error[E0603]: derive macro import `Empty` is private + --> $DIR/disappearing-resolution.rs:11:8 + | +LL | use m::Empty; + | ^^^^^ private derive macro import + | +note: the derive macro import `Empty` is defined here... + --> $DIR/disappearing-resolution.rs:9:9 + | +LL | use test_macros::Empty; + | ^^^^^^^^^^^^^^^^^^ +note: ...and refers to the derive macro `Empty` which is defined here + --> $DIR/auxiliary/test-macros.rs:25:1 + | +LL | pub fn empty_derive(_: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/proc-macro/doc-comment-preserved.rs b/tests/ui/proc-macro/doc-comment-preserved.rs new file mode 100644 index 000000000..ed8ca99bd --- /dev/null +++ b/tests/ui/proc-macro/doc-comment-preserved.rs @@ -0,0 +1,24 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +print_bang! { + +/** +******* +* DOC * +* DOC * +* DOC * +******* +*/ +pub struct S; + +} + +fn main() {} diff --git a/tests/ui/proc-macro/doc-comment-preserved.stdout b/tests/ui/proc-macro/doc-comment-preserved.stdout new file mode 100644 index 000000000..f4160d7da --- /dev/null +++ b/tests/ui/proc-macro/doc-comment-preserved.stdout @@ -0,0 +1,54 @@ +PRINT-BANG INPUT (DISPLAY): /** +******* +* DOC * +* DOC * +* DOC * +******* +*/ + pub struct S ; +PRINT-BANG RE-COLLECTED (DISPLAY): #[doc = "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n"] pub struct S ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Literal { + kind: Str, + symbol: "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n", + suffix: None, + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + ], + span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0), + }, + Ident { + ident: "pub", + span: $DIR/doc-comment-preserved.rs:20:1: 20:4 (#0), + }, + Ident { + ident: "struct", + span: $DIR/doc-comment-preserved.rs:20:5: 20:11 (#0), + }, + Ident { + ident: "S", + span: $DIR/doc-comment-preserved.rs:20:12: 20:13 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/doc-comment-preserved.rs:20:13: 20:14 (#0), + }, +] diff --git a/tests/ui/proc-macro/dollar-crate-issue-101211.rs b/tests/ui/proc-macro/dollar-crate-issue-101211.rs new file mode 100644 index 000000000..fc1acfd32 --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate-issue-101211.rs @@ -0,0 +1,29 @@ +// check-pass +// edition:2021 +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! foo { + ($($path:ident)::*) => ( + test_macros::recollect!( + $($path)::* + ) + ) +} + +macro_rules! baz { + () => ( + foo!($crate::BAR) + ) +} + +pub const BAR: u32 = 19; + +fn main(){ + std::println!("{}", baz!()); +} diff --git a/tests/ui/proc-macro/dollar-crate-issue-57089.rs b/tests/ui/proc-macro/dollar-crate-issue-57089.rs new file mode 100644 index 000000000..27bfa099f --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate-issue-57089.rs @@ -0,0 +1,27 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +type S = u8; + +macro_rules! m { + () => { + print_bang! { + struct M($crate::S); + } + + #[print_attr] + struct A($crate::S); + }; +} + +m!(); + +fn main() {} diff --git a/tests/ui/proc-macro/dollar-crate-issue-57089.stdout b/tests/ui/proc-macro/dollar-crate-issue-57089.stdout new file mode 100644 index 000000000..2622c005d --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -0,0 +1,80 @@ +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate-issue-57089.rs:17:13: 17:19 (#4), + }, + Ident { + ident: "M", + span: $DIR/dollar-crate-issue-57089.rs:17:20: 17:21 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate-issue-57089.rs:17:22: 17:28 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:29 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:17:29: 17:30 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate-issue-57089.rs:17:30: 17:31 (#4), + }, + ], + span: $DIR/dollar-crate-issue-57089.rs:17:21: 17:32 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:17:32: 17:33 (#4), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate-issue-57089.rs:21:9: 21:15 (#4), + }, + Ident { + ident: "A", + span: $DIR/dollar-crate-issue-57089.rs:21:16: 21:17 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate-issue-57089.rs:21:18: 21:24 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:25 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:21:25: 21:26 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate-issue-57089.rs:21:26: 21:27 (#4), + }, + ], + span: $DIR/dollar-crate-issue-57089.rs:21:17: 21:28 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate-issue-57089.rs:21:28: 21:29 (#4), + }, +] diff --git a/tests/ui/proc-macro/dollar-crate-issue-62325.rs b/tests/ui/proc-macro/dollar-crate-issue-62325.rs new file mode 100644 index 000000000..d828fb9fd --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate-issue-62325.rs @@ -0,0 +1,26 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// aux-build:dollar-crate-external.rs + + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; +extern crate dollar_crate_external; + +type S = u8; + +macro_rules! m { () => { + #[print_attr] + struct A(identity!($crate::S)); +}} + +m!(); + +dollar_crate_external::issue_62325!(); + +fn main() {} diff --git a/tests/ui/proc-macro/dollar-crate-issue-62325.stdout b/tests/ui/proc-macro/dollar-crate-issue-62325.stdout new file mode 100644 index 000000000..a91908239 --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -0,0 +1,110 @@ +PRINT-ATTR INPUT (DISPLAY): struct A(identity! ($crate :: S)) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate-issue-62325.rs:19:5: 19:11 (#4), + }, + Ident { + ident: "A", + span: $DIR/dollar-crate-issue-62325.rs:19:12: 19:13 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "identity", + span: $DIR/dollar-crate-issue-62325.rs:19:14: 19:22 (#4), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/dollar-crate-issue-62325.rs:19:22: 19:23 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate-issue-62325.rs:19:24: 19:30 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:31 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate-issue-62325.rs:19:31: 19:32 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate-issue-62325.rs:19:32: 19:33 (#4), + }, + ], + span: $DIR/dollar-crate-issue-62325.rs:19:23: 19:34 (#4), + }, + ], + span: $DIR/dollar-crate-issue-62325.rs:19:13: 19:35 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate-issue-62325.rs:19:35: 19:36 (#4), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct B(identity! ($crate :: S)) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:21:5: 21:11 (#12), + }, + Ident { + ident: "B", + span: $DIR/auxiliary/dollar-crate-external.rs:21:12: 21:13 (#12), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "identity", + span: $DIR/auxiliary/dollar-crate-external.rs:21:14: 21:22 (#12), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:21:22: 21:23 (#12), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:21:24: 21:30 (#12), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:31 (#12), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:21:31: 21:32 (#12), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:21:32: 21:33 (#12), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:21:23: 21:34 (#12), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:21:13: 21:35 (#12), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:21:35: 21:36 (#12), + }, +] diff --git a/tests/ui/proc-macro/dollar-crate.rs b/tests/ui/proc-macro/dollar-crate.rs new file mode 100644 index 000000000..ac27dfa1a --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate.rs @@ -0,0 +1,40 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs +// aux-build:dollar-crate-external.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; +extern crate dollar_crate_external; + +type S = u8; + +mod local { + macro_rules! local { + () => { + print_bang! { + struct M($crate::S); + } + + #[print_attr] + struct A($crate::S); + + #[derive(Print)] + struct D($crate::S); + }; + } + + local!(); +} + +mod external { + use crate::dollar_crate_external; + + dollar_crate_external::external!(); +} + +fn main() {} diff --git a/tests/ui/proc-macro/dollar-crate.stdout b/tests/ui/proc-macro/dollar-crate.stdout new file mode 100644 index 000000000..4e169d47e --- /dev/null +++ b/tests/ui/proc-macro/dollar-crate.stdout @@ -0,0 +1,240 @@ +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate.rs:20:17: 20:23 (#4), + }, + Ident { + ident: "M", + span: $DIR/dollar-crate.rs:20:24: 20:25 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate.rs:20:26: 20:32 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate.rs:20:32: 20:33 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate.rs:20:33: 20:34 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate.rs:20:34: 20:35 (#4), + }, + ], + span: $DIR/dollar-crate.rs:20:25: 20:36 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate.rs:20:36: 20:37 (#4), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate.rs:24:13: 24:19 (#4), + }, + Ident { + ident: "A", + span: $DIR/dollar-crate.rs:24:20: 24:21 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate.rs:24:22: 24:28 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate.rs:24:28: 24:29 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate.rs:24:29: 24:30 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate.rs:24:30: 24:31 (#4), + }, + ], + span: $DIR/dollar-crate.rs:24:21: 24:32 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate.rs:24:32: 24:33 (#4), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ; +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/dollar-crate.rs:27:13: 27:19 (#4), + }, + Ident { + ident: "D", + span: $DIR/dollar-crate.rs:27:20: 27:21 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/dollar-crate.rs:27:22: 27:28 (#4), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/dollar-crate.rs:27:28: 27:29 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/dollar-crate.rs:27:29: 27:30 (#4), + }, + Ident { + ident: "S", + span: $DIR/dollar-crate.rs:27:30: 27:31 (#4), + }, + ], + span: $DIR/dollar-crate.rs:27:21: 27:32 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/dollar-crate.rs:27:32: 27:33 (#4), + }, +] +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:7:13: 7:19 (#15), + }, + Ident { + ident: "M", + span: $DIR/auxiliary/dollar-crate-external.rs:7:20: 7:21 (#15), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:7:22: 7:28 (#15), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:29 (#15), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:7:29: 7:30 (#15), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:7:30: 7:31 (#15), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:7:21: 7:32 (#15), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:7:32: 7:33 (#15), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:11:9: 11:15 (#15), + }, + Ident { + ident: "A", + span: $DIR/auxiliary/dollar-crate-external.rs:11:16: 11:17 (#15), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:11:18: 11:24 (#15), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:25 (#15), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:11:25: 11:26 (#15), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:11:26: 11:27 (#15), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:11:17: 11:28 (#15), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:11:28: 11:29 (#15), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ; +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/dollar-crate-external.rs:14:9: 14:15 (#15), + }, + Ident { + ident: "D", + span: $DIR/auxiliary/dollar-crate-external.rs:14:16: 14:17 (#15), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "$crate", + span: $DIR/auxiliary/dollar-crate-external.rs:14:18: 14:24 (#15), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:25 (#15), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:14:25: 14:26 (#15), + }, + Ident { + ident: "S", + span: $DIR/auxiliary/dollar-crate-external.rs:14:26: 14:27 (#15), + }, + ], + span: $DIR/auxiliary/dollar-crate-external.rs:14:17: 14:28 (#15), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/auxiliary/dollar-crate-external.rs:14:28: 14:29 (#15), + }, +] diff --git a/tests/ui/proc-macro/edition-imports-2018.rs b/tests/ui/proc-macro/edition-imports-2018.rs new file mode 100644 index 000000000..5a77cd4ef --- /dev/null +++ b/tests/ui/proc-macro/edition-imports-2018.rs @@ -0,0 +1,24 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + #[derive(Derive2015)] // OK + struct S; + + fn check() { + Path; + } +} + +fn main() {} diff --git a/tests/ui/proc-macro/empty-crate.rs b/tests/ui/proc-macro/empty-crate.rs new file mode 100644 index 000000000..3e54c9fee --- /dev/null +++ b/tests/ui/proc-macro/empty-crate.rs @@ -0,0 +1,9 @@ +// run-pass + +#![allow(unused_imports)] +// aux-build:empty-crate.rs + +#[macro_use] +extern crate empty_crate; + +fn main() {} diff --git a/tests/ui/proc-macro/empty-where-clause.rs b/tests/ui/proc-macro/empty-where-clause.rs new file mode 100644 index 000000000..719555c09 --- /dev/null +++ b/tests/ui/proc-macro/empty-where-clause.rs @@ -0,0 +1,18 @@ +// aux-build:test-macros.rs + +extern crate test_macros; +use test_macros::recollect_attr; + +#[recollect_attr] +struct FieldStruct where { + field: MissingType1 //~ ERROR cannot find +} + +#[recollect_attr] +struct TupleStruct(MissingType2) where; //~ ERROR cannot find + +enum MyEnum where { + Variant(MissingType3) //~ ERROR cannot find +} + +fn main() {} diff --git a/tests/ui/proc-macro/empty-where-clause.stderr b/tests/ui/proc-macro/empty-where-clause.stderr new file mode 100644 index 000000000..192a2b30f --- /dev/null +++ b/tests/ui/proc-macro/empty-where-clause.stderr @@ -0,0 +1,21 @@ +error[E0412]: cannot find type `MissingType1` in this scope + --> $DIR/empty-where-clause.rs:8:12 + | +LL | field: MissingType1 + | ^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType2` in this scope + --> $DIR/empty-where-clause.rs:12:20 + | +LL | struct TupleStruct(MissingType2) where; + | ^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `MissingType3` in this scope + --> $DIR/empty-where-clause.rs:15:13 + | +LL | Variant(MissingType3) + | ^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/proc-macro/expand-expr.rs b/tests/ui/proc-macro/expand-expr.rs new file mode 100644 index 000000000..700aac41c --- /dev/null +++ b/tests/ui/proc-macro/expand-expr.rs @@ -0,0 +1,134 @@ +// aux-build:expand-expr.rs +// no-remap-src-base: check_expand_expr_file!() fails when enabled. + +#![feature(concat_bytes)] +extern crate expand_expr; + +use expand_expr::{ + check_expand_expr_file, echo_pm, expand_expr_fail, expand_expr_is, recursive_expand, +}; + +// Check builtin macros can be expanded. + +expand_expr_is!(13u32, line!()); +expand_expr_is!(24u32, column!()); + +expand_expr_is!("Hello, World!", concat!("Hello, ", "World", "!")); +expand_expr_is!("int10floats5.3booltrue", concat!("int", 10, "floats", 5.3, "bool", true)); +expand_expr_is!("Hello", concat!(r##"Hello"##)); + +expand_expr_is!("Included file contents\n", include_str!("auxiliary/included-file.txt")); +expand_expr_is!(b"Included file contents\n", include_bytes!("auxiliary/included-file.txt")); + +expand_expr_is!( + "contents: Included file contents\n", + concat!("contents: ", include_str!("auxiliary/included-file.txt")) +); + +expand_expr_is!( + b"contents: Included file contents\n", + concat_bytes!(b"contents: ", include_bytes!("auxiliary/included-file.txt")) +); + +// Correct value is checked for multiple sources. +check_expand_expr_file!(file!()); + +expand_expr_is!("hello", stringify!(hello)); +expand_expr_is!("10 + 20", stringify!(10 + 20)); + +macro_rules! echo_tts { + ($($t:tt)*) => { $($t)* }; //~ ERROR: expected expression, found `$` +} + +macro_rules! echo_lit { + ($l:literal) => { + $l + }; +} + +macro_rules! echo_expr { + ($e:expr) => { + $e + }; +} + +macro_rules! simple_lit { + ($l:literal) => { + expand_expr_is!($l, $l); + expand_expr_is!($l, echo_lit!($l)); + expand_expr_is!($l, echo_expr!($l)); + expand_expr_is!($l, echo_tts!($l)); + expand_expr_is!($l, echo_pm!($l)); + const _: () = { + macro_rules! mac { + () => { + $l + }; + } + expand_expr_is!($l, mac!()); + expand_expr_is!($l, echo_expr!(mac!())); + expand_expr_is!($l, echo_tts!(mac!())); + expand_expr_is!($l, echo_pm!(mac!())); + }; + }; +} + +simple_lit!("Hello, World"); +simple_lit!('c'); +simple_lit!(b'c'); +simple_lit!(10); +simple_lit!(10.0); +simple_lit!(10.0f64); +simple_lit!(-3.14159); +simple_lit!(-3.5e10); +simple_lit!(0xFEED); +simple_lit!(-0xFEED); +simple_lit!(0b0100); +simple_lit!(-0b0100); +simple_lit!("string"); +simple_lit!(r##"raw string"##); +simple_lit!(b"byte string"); +simple_lit!(br##"raw byte string"##); +simple_lit!(true); +simple_lit!(false); + +// Ensure char escapes aren't normalized by expansion +simple_lit!("\u{0}"); +simple_lit!("\0"); +simple_lit!("\x00"); +simple_lit!('\u{0}'); +simple_lit!('\0'); +simple_lit!('\x00'); +simple_lit!(b"\x00"); +simple_lit!(b"\0"); +simple_lit!(b'\x00'); +simple_lit!(b'\0'); + +// Extra tokens after the string literal aren't ignored +expand_expr_fail!("string"; hello); //~ ERROR: expected one of `.`, `?`, or an operator, found `;` + +// Invalid expressions produce errors in addition to returning `Err(())`. +expand_expr_fail!($); //~ ERROR: expected expression, found `$` +expand_expr_fail!(echo_tts!($)); +expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$` + +// We get errors reported and recover during macro expansion if the macro +// doesn't produce a valid expression. +expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following +expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following + +// For now, fail if a non-literal expression is expanded. +expand_expr_fail!(arbitrary_expression() + "etc"); +expand_expr_fail!(echo_tts!(arbitrary_expression() + "etc")); +expand_expr_fail!(echo_expr!(arbitrary_expression() + "etc")); +expand_expr_fail!(echo_pm!(arbitrary_expression() + "etc")); + +const _: u32 = recursive_expand!(); //~ ERROR: recursion limit reached while expanding `recursive_expand!` + +fn main() { + // https://github.com/rust-lang/rust/issues/104414 + match b"Included file contents\n" { + include_bytes!("auxiliary/included-file.txt") => (), + _ => panic!("include_bytes! in pattern"), + } +} diff --git a/tests/ui/proc-macro/expand-expr.stderr b/tests/ui/proc-macro/expand-expr.stderr new file mode 100644 index 000000000..df61e9972 --- /dev/null +++ b/tests/ui/proc-macro/expand-expr.stderr @@ -0,0 +1,59 @@ +error: expected one of `.`, `?`, or an operator, found `;` + --> $DIR/expand-expr.rs:108:27 + | +LL | expand_expr_fail!("string"; hello); + | ^ expected one of `.`, `?`, or an operator + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:111:19 + | +LL | expand_expr_fail!($); + | ^ expected expression + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:40:23 + | +LL | ($($t:tt)*) => { $($t)* }; + | ^^^^ expected expression + +error: expected expression, found `$` + --> $DIR/expand-expr.rs:113:28 + | +LL | expand_expr_fail!(echo_pm!($)); + | ^ expected expression + +error: macro expansion ignores token `hello` and any following + --> $DIR/expand-expr.rs:117:47 + | +LL | expand_expr_is!("string", echo_tts!("string"; hello)); + | --------------------^^^^^- caused by the macro expansion here + | + = note: the usage of `echo_tts!` is likely invalid in expression context +help: you might be missing a semicolon here + | +LL | expand_expr_is!("string", echo_tts!("string"; hello);); + | + + +error: macro expansion ignores token `;` and any following + --> $DIR/expand-expr.rs:118:44 + | +LL | expand_expr_is!("string", echo_pm!("string"; hello)); + | -----------------^------- caused by the macro expansion here + | + = note: the usage of `echo_pm!` is likely invalid in expression context +help: you might be missing a semicolon here + | +LL | expand_expr_is!("string", echo_pm!("string"; hello);); + | + + +error: recursion limit reached while expanding `recursive_expand!` + --> $DIR/expand-expr.rs:126:16 + | +LL | const _: u32 = recursive_expand!(); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`expand_expr`) + = note: this error originates in the macro `recursive_expand` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/tests/ui/proc-macro/expand-to-derive.rs b/tests/ui/proc-macro/expand-to-derive.rs new file mode 100644 index 000000000..ff2876e84 --- /dev/null +++ b/tests/ui/proc-macro/expand-to-derive.rs @@ -0,0 +1,34 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! expand_to_derive { + ($item:item) => { + #[derive(Print)] + struct Foo { + #[cfg(FALSE)] removed: bool, + field: [bool; { + $item + 0 + }] + } + }; +} + +expand_to_derive! { + #[cfg_attr(not(FALSE), rustc_dummy)] + struct Inner { + #[cfg(FALSE)] removed_inner_field: bool, + other_inner_field: u8, + } +} + +fn main() {} diff --git a/tests/ui/proc-macro/expand-to-derive.stdout b/tests/ui/proc-macro/expand-to-derive.stdout new file mode 100644 index 000000000..a6437982a --- /dev/null +++ b/tests/ui/proc-macro/expand-to-derive.stdout @@ -0,0 +1,104 @@ +PRINT-DERIVE INPUT (DISPLAY): struct Foo +{ + field : + [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/expand-to-derive.rs:16:9: 16:15 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/expand-to-derive.rs:16:16: 16:19 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/expand-to-derive.rs:18:13: 18:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/expand-to-derive.rs:18:18: 18:19 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "bool", + span: $DIR/expand-to-derive.rs:18:21: 18:25 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/expand-to-derive.rs:18:25: 18:26 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0), + }, + ], + span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0), + }, + Ident { + ident: "struct", + span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "other_inner_field", + span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0), + }, + Ident { + ident: "u8", + span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0), + }, + ], + span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/expand-to-derive.rs:20:17: 20:18 (#4), + }, + ], + span: $DIR/expand-to-derive.rs:18:27: 21:14 (#4), + }, + ], + span: $DIR/expand-to-derive.rs:18:20: 21:15 (#4), + }, + ], + span: $DIR/expand-to-derive.rs:16:20: 22:10 (#4), + }, +] diff --git a/tests/ui/proc-macro/expand-to-unstable.rs b/tests/ui/proc-macro/expand-to-unstable.rs new file mode 100644 index 000000000..0825c1a8e --- /dev/null +++ b/tests/ui/proc-macro/expand-to-unstable.rs @@ -0,0 +1,14 @@ +// aux-build:derive-unstable.rs + +#![allow(warnings)] + +#[macro_use] +extern crate derive_unstable; + +#[derive(Unstable)] +//~^ ERROR: use of unstable library feature +struct A; + +fn main() { + unsafe { foo(); } +} diff --git a/tests/ui/proc-macro/expand-to-unstable.stderr b/tests/ui/proc-macro/expand-to-unstable.stderr new file mode 100644 index 000000000..b27dcd7e6 --- /dev/null +++ b/tests/ui/proc-macro/expand-to-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library + --> $DIR/expand-to-unstable.rs:8:10 + | +LL | #[derive(Unstable)] + | ^^^^^^^^ + | + = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable + = note: this error originates in the derive macro `Unstable` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/expand-with-a-macro.rs b/tests/ui/proc-macro/expand-with-a-macro.rs new file mode 100644 index 000000000..042a28365 --- /dev/null +++ b/tests/ui/proc-macro/expand-with-a-macro.rs @@ -0,0 +1,20 @@ +// run-pass +// needs-unwind +// aux-build:expand-with-a-macro.rs + + +#![deny(warnings)] + +#[macro_use] +extern crate expand_with_a_macro; + +use std::panic; + +#[derive(A)] +struct A; + +fn main() { + assert!(panic::catch_unwind(|| { + A.a(); + }).is_err()); +} diff --git a/tests/ui/proc-macro/export-macro.rs b/tests/ui/proc-macro/export-macro.rs new file mode 100644 index 000000000..ad69fe5ee --- /dev/null +++ b/tests/ui/proc-macro/export-macro.rs @@ -0,0 +1,11 @@ +// error-pattern: cannot export macro_rules! macros from a `proc-macro` crate + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +#[macro_export] +macro_rules! foo { + ($e:expr) => ($e) +} diff --git a/tests/ui/proc-macro/export-macro.stderr b/tests/ui/proc-macro/export-macro.stderr new file mode 100644 index 000000000..36a6a9bb3 --- /dev/null +++ b/tests/ui/proc-macro/export-macro.stderr @@ -0,0 +1,8 @@ +error: cannot export macro_rules! macros from a `proc-macro` crate type currently + --> $DIR/export-macro.rs:9:1 + | +LL | macro_rules! foo { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/exports.rs b/tests/ui/proc-macro/exports.rs new file mode 100644 index 000000000..a40c15908 --- /dev/null +++ b/tests/ui/proc-macro/exports.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![allow(warnings)] + +pub fn a() {} //~ ERROR: cannot export any items +pub struct B; //~ ERROR: cannot export any items +pub enum C {} //~ ERROR: cannot export any items +pub mod d {} //~ ERROR: cannot export any items + +mod e {} +struct F; +enum G {} +fn h() {} diff --git a/tests/ui/proc-macro/exports.stderr b/tests/ui/proc-macro/exports.stderr new file mode 100644 index 000000000..7b23d08f2 --- /dev/null +++ b/tests/ui/proc-macro/exports.stderr @@ -0,0 +1,26 @@ +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:7:1 + | +LL | pub fn a() {} + | ^^^^^^^^^^ + +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:8:1 + | +LL | pub struct B; + | ^^^^^^^^^^^^^ + +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:9:1 + | +LL | pub enum C {} + | ^^^^^^^^^^ + +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/exports.rs:10:1 + | +LL | pub mod d {} + | ^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs new file mode 100644 index 000000000..d4067a335 --- /dev/null +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs @@ -0,0 +1,37 @@ +// check-pass +// aux-build:test-macros.rs + +#![feature(decl_macro)] +#![feature(stmt_expr_attributes)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro mac { + (expr $expr:expr) => { + #[derive(Print)] + enum E { + V = { let _ = $expr; 0 }, + } + }, + (stmt $stmt:stmt) => { + #[derive(Print)] + enum E { + V = { let _ = { $stmt }; 0 }, + } + }, +} + +const PATH: u8 = 2; + +fn main() { + mac!(expr #[allow(warnings)] 0); + mac!(stmt 0); + mac!(stmt {}); + mac!(stmt PATH); + mac!(stmt 0 + 1); + mac!(stmt PATH + 1); +} diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout new file mode 100644 index 000000000..686d53e88 --- /dev/null +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout @@ -0,0 +1,540 @@ +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0 ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0 ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #4 bytes(299..303), + }, + Ident { + ident: "E", + span: #4 bytes(304..305), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #4 bytes(320..321), + }, + Punct { + ch: '=', + spacing: Alone, + span: #4 bytes(322..323), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #4 bytes(326..329), + }, + Ident { + ident: "_", + span: #4 bytes(330..331), + }, + Punct { + ch: '=', + spacing: Alone, + span: #4 bytes(332..333), + }, + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: #0 bytes(541..542), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: #0 bytes(543..548), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: #0 bytes(549..557), + }, + ], + span: #0 bytes(548..558), + }, + ], + span: #0 bytes(542..559), + }, + Punct { + ch: '#', + spacing: Alone, + span: #0 bytes(541..542), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: #0 bytes(543..548), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: #0 bytes(549..557), + }, + ], + span: #0 bytes(548..558), + }, + ], + span: #0 bytes(542..559), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(560..561), + }, + ], + span: #4 bytes(334..339), + }, + Punct { + ch: ';', + spacing: Alone, + span: #4 bytes(339..340), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #4 bytes(341..342), + }, + ], + span: #4 bytes(324..344), + }, + Punct { + ch: ',', + spacing: Alone, + span: #4 bytes(344..345), + }, + ], + span: #4 bytes(306..355), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #8 bytes(423..427), + }, + Ident { + ident: "E", + span: #8 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #8 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #8 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #8 bytes(450..453), + }, + Ident { + ident: "_", + span: #8 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #8 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(578..579), + }, + ], + span: #8 bytes(460..465), + }, + ], + span: #8 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #8 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #8 bytes(469..470), + }, + ], + span: #8 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #8 bytes(472..473), + }, + ], + span: #8 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #12 bytes(423..427), + }, + Ident { + ident: "E", + span: #12 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #12 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #12 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #12 bytes(450..453), + }, + Ident { + ident: "_", + span: #12 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #12 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: Brace, + stream: TokenStream [], + span: #0 bytes(596..598), + }, + ], + span: #12 bytes(460..465), + }, + ], + span: #12 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #12 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #12 bytes(469..470), + }, + ], + span: #12 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #12 bytes(472..473), + }, + ], + span: #12 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #16 bytes(423..427), + }, + Ident { + ident: "E", + span: #16 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #16 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #16 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #16 bytes(450..453), + }, + Ident { + ident: "_", + span: #16 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #16 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "PATH", + span: #0 bytes(615..619), + }, + ], + span: #16 bytes(460..465), + }, + ], + span: #16 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #16 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #16 bytes(469..470), + }, + ], + span: #16 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #16 bytes(472..473), + }, + ], + span: #16 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #20 bytes(423..427), + }, + Ident { + ident: "E", + span: #20 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #20 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #20 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #20 bytes(450..453), + }, + Ident { + ident: "_", + span: #20 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #20 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(636..637), + }, + Punct { + ch: '+', + spacing: Alone, + span: #0 bytes(638..639), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: #0 bytes(640..641), + }, + ], + span: #20 bytes(460..465), + }, + ], + span: #20 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #20 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #20 bytes(469..470), + }, + ], + span: #20 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #20 bytes(472..473), + }, + ], + span: #20 bytes(430..483), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #24 bytes(423..427), + }, + Ident { + ident: "E", + span: #24 bytes(428..429), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "V", + span: #24 bytes(444..445), + }, + Punct { + ch: '=', + spacing: Alone, + span: #24 bytes(446..447), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: #24 bytes(450..453), + }, + Ident { + ident: "_", + span: #24 bytes(454..455), + }, + Punct { + ch: '=', + spacing: Alone, + span: #24 bytes(456..457), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "PATH", + span: #0 bytes(658..662), + }, + Punct { + ch: '+', + spacing: Alone, + span: #0 bytes(663..664), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: #0 bytes(665..666), + }, + ], + span: #24 bytes(460..465), + }, + ], + span: #24 bytes(458..467), + }, + Punct { + ch: ';', + spacing: Alone, + span: #24 bytes(467..468), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #24 bytes(469..470), + }, + ], + span: #24 bytes(448..472), + }, + Punct { + ch: ',', + spacing: Alone, + span: #24 bytes(472..473), + }, + ], + span: #24 bytes(430..483), + }, +] diff --git a/tests/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/tests/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs new file mode 100644 index 000000000..a6e64e1b1 --- /dev/null +++ b/tests/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs @@ -0,0 +1,7 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +extern crate proc_macro; +use proc_macro::TokenStream; // OK + +fn main() {} diff --git a/tests/ui/proc-macro/gen-lifetime-token.rs b/tests/ui/proc-macro/gen-lifetime-token.rs new file mode 100644 index 000000000..588bd2b76 --- /dev/null +++ b/tests/ui/proc-macro/gen-lifetime-token.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:gen-lifetime-token.rs + +extern crate gen_lifetime_token as bar; + +bar::bar!(); + +fn main() { + let x: &'static i32 = FOO; + assert_eq!(*x, 1); +} diff --git a/tests/ui/proc-macro/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/gen-macro-rules-hygiene.rs new file mode 100644 index 000000000..195bda82e --- /dev/null +++ b/tests/ui/proc-macro/gen-macro-rules-hygiene.rs @@ -0,0 +1,23 @@ +// `macro_rules` items produced by transparent macros have correct hygiene in basic cases. +// Local variables and labels are hygienic, items are not hygienic. +// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro. + +// aux-build:gen-macro-rules-hygiene.rs + +#[macro_use] +extern crate gen_macro_rules_hygiene; + +struct ItemUse; + +gen_macro_rules!(); +//~^ ERROR use of undeclared label `'label_use` +//~| ERROR cannot find value `local_use` in this scope + +fn main() { + 'label_use: loop { + let local_use = 1; + generated!(); + ItemDef; // OK + local_def; //~ ERROR cannot find value `local_def` in this scope + } +} diff --git a/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr b/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr new file mode 100644 index 000000000..df7c4f72e --- /dev/null +++ b/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr @@ -0,0 +1,32 @@ +error[E0426]: use of undeclared label `'label_use` + --> $DIR/gen-macro-rules-hygiene.rs:12:1 + | +LL | gen_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` +... +LL | generated!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_use` in this scope + --> $DIR/gen-macro-rules-hygiene.rs:12:1 + | +LL | gen_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def` +... +LL | generated!(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_def` in this scope + --> $DIR/gen-macro-rules-hygiene.rs:21:9 + | +LL | local_def; + | ^^^^^^^^^ help: a local variable with a similar name exists: `local_use` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0426. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/gen-macro-rules.rs b/tests/ui/proc-macro/gen-macro-rules.rs new file mode 100644 index 000000000..13ad27f93 --- /dev/null +++ b/tests/ui/proc-macro/gen-macro-rules.rs @@ -0,0 +1,13 @@ +// Derive macros can generate `macro_rules` items, regression test for issue #63651. + +// check-pass +// aux-build:gen-macro-rules.rs + +extern crate gen_macro_rules as repro; + +#[derive(repro::repro)] +pub struct S; + +m!(); // OK + +fn main() {} diff --git a/tests/ui/proc-macro/generate-dollar-ident.rs b/tests/ui/proc-macro/generate-dollar-ident.rs new file mode 100644 index 000000000..b838be9fb --- /dev/null +++ b/tests/ui/proc-macro/generate-dollar-ident.rs @@ -0,0 +1,18 @@ +// Proc macros can generate token sequence `$ IDENT` +// without it being recognized as an unknown macro variable. + +// check-pass +// aux-build:generate-dollar-ident.rs + +extern crate generate_dollar_ident; +use generate_dollar_ident::*; + +macro_rules! black_hole { + ($($tt:tt)*) => {}; +} + +black_hole!($var); + +dollar_ident!(black_hole); + +fn main() {} diff --git a/tests/ui/proc-macro/generate-mod.rs b/tests/ui/proc-macro/generate-mod.rs new file mode 100644 index 000000000..471f317ed --- /dev/null +++ b/tests/ui/proc-macro/generate-mod.rs @@ -0,0 +1,33 @@ +// Modules generated by transparent proc macros still acts as barriers for names (issue #50504). + +// aux-build:generate-mod.rs + +extern crate generate_mod; + +struct FromOutside; + +generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `Outer` in this scope + +#[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterAttr` in this scope +struct S; + +#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterDerive` in this scope + //~| WARN this was previously accepted + //~| WARN this was previously accepted +struct Z; + +fn inner_block() { + #[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope + //~| ERROR cannot find type `OuterDerive` in this scope + //~| WARN this was previously accepted + //~| WARN this was previously accepted + struct InnerZ; +} + +#[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed +struct W; + +fn main() {} diff --git a/tests/ui/proc-macro/generate-mod.stderr b/tests/ui/proc-macro/generate-mod.stderr new file mode 100644 index 000000000..db629b5b5 --- /dev/null +++ b/tests/ui/proc-macro/generate-mod.stderr @@ -0,0 +1,164 @@ +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:9:1 + | +LL | generate_mod::check!(); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = help: consider importing this struct: + FromOutside + = note: this error originates in the macro `generate_mod::check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `Outer` in this scope + --> $DIR/generate-mod.rs:9:1 + | +LL | generate_mod::check!(); + | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = help: consider importing this struct: + Outer + = note: this error originates in the macro `generate_mod::check` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:12:1 + | +LL | #[generate_mod::check_attr] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = help: consider importing this struct: + FromOutside + = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `OuterAttr` in this scope + --> $DIR/generate-mod.rs:12:1 + | +LL | #[generate_mod::check_attr] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = help: consider importing this struct: + OuterAttr + = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0412`. +Future incompatibility report: Future breakage diagnostic: +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +error: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default + = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `OuterDeriveLint` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs new file mode 100644 index 000000000..40c42d82f --- /dev/null +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs @@ -0,0 +1,13 @@ +// aux-build:test-macros.rs + +#[macro_use(Empty)] +extern crate test_macros; +use test_macros::empty_attr as empty_helper; + +#[empty_helper] //~ ERROR `empty_helper` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr new file mode 100644 index 000000000..9441cdcc8 --- /dev/null +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr @@ -0,0 +1,35 @@ +error[E0659]: `empty_helper` is ambiguous + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:5:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +warning: derive helper attribute is used before it is introduced + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ +... +LL | #[derive(Empty)] + | ----- the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + = note: `#[warn(legacy_derive_helpers)]` on by default + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import.rs b/tests/ui/proc-macro/helper-attr-blocked-by-import.rs new file mode 100644 index 000000000..2e20a3de6 --- /dev/null +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import.rs @@ -0,0 +1,28 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use(Empty)] +extern crate test_macros; + +use self::one::*; +use self::two::*; + +mod empty_helper {} + +mod one { + use empty_helper; + + #[derive(Empty)] + #[empty_helper] + struct One; +} + +mod two { + use empty_helper; + + #[derive(Empty)] + #[empty_helper] + struct Two; +} + +fn main() {} diff --git a/tests/ui/proc-macro/hygiene_example.rs b/tests/ui/proc-macro/hygiene_example.rs new file mode 100644 index 000000000..346ed1207 --- /dev/null +++ b/tests/ui/proc-macro/hygiene_example.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:hygiene_example_codegen.rs +// aux-build:hygiene_example.rs + +extern crate hygiene_example; +use hygiene_example::hello; + +fn main() { + mod hygiene_example {} // no conflict with `extern crate hygiene_example;` from the proc macro + macro_rules! format { () => {} } // does not interfere with `format!` from the proc macro + macro_rules! hello_helper { () => {} } // similarly does not intefere with the proc macro + + let string = "world"; // no conflict with `string` from the proc macro + hello!(string); + hello!(string); +} diff --git a/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs b/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs new file mode 100644 index 000000000..4efd9e952 --- /dev/null +++ b/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs @@ -0,0 +1,15 @@ +extern crate proc_macro; + +#[proc_macro_derive(Foo)] +//~^ ERROR: only usable with crates of the `proc-macro` crate type +pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream { + a +} + +// Issue #37590 +#[proc_macro_derive(Foo)] +//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions +pub struct Foo { +} + +fn main() {} diff --git a/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr new file mode 100644 index 000000000..c0930ab71 --- /dev/null +++ b/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr @@ -0,0 +1,14 @@ +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/illegal-proc-macro-derive-use.rs:3:1 + | +LL | #[proc_macro_derive(Foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute may only be used on bare functions + --> $DIR/illegal-proc-macro-derive-use.rs:10:1 + | +LL | #[proc_macro_derive(Foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/proc-macro/import.rs b/tests/ui/proc-macro/import.rs new file mode 100644 index 000000000..d1b1ff350 --- /dev/null +++ b/tests/ui/proc-macro/import.rs @@ -0,0 +1,8 @@ +// aux-build:test-macros.rs + +extern crate test_macros; + +use test_macros::empty_derive; +//~^ ERROR: unresolved import `test_macros::empty_derive` + +fn main() {} diff --git a/tests/ui/proc-macro/import.stderr b/tests/ui/proc-macro/import.stderr new file mode 100644 index 000000000..aae621193 --- /dev/null +++ b/tests/ui/proc-macro/import.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `test_macros::empty_derive` + --> $DIR/import.rs:5:5 + | +LL | use test_macros::empty_derive; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ no `empty_derive` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/proc-macro/inert-attribute-order.rs b/tests/ui/proc-macro/inert-attribute-order.rs new file mode 100644 index 000000000..f80796756 --- /dev/null +++ b/tests/ui/proc-macro/inert-attribute-order.rs @@ -0,0 +1,23 @@ +// Order of inert attributes, both built-in and custom is preserved during expansion. + +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +/// 1 +#[rustfmt::attr2] +#[doc = "3"] +#[print_attr(nodebug)] +#[doc = "4"] +#[rustfmt::attr5] +/// 6 +#[print_attr(nodebug)] +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/inert-attribute-order.stdout b/tests/ui/proc-macro/inert-attribute-order.stdout new file mode 100644 index 000000000..cc2155459 --- /dev/null +++ b/tests/ui/proc-macro/inert-attribute-order.stdout @@ -0,0 +1,7 @@ +PRINT-ATTR INPUT (DISPLAY): /// 1 +#[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] #[rustfmt :: attr5] /// 6 +#[print_attr(nodebug)] struct S ; +PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] +#[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S ; +PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] +#[rustfmt :: attr5] #[doc = " 6"] struct S ; diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs new file mode 100644 index 000000000..30c2666df --- /dev/null +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z span-debug +// error-pattern:custom inner attributes are unstable +// error-pattern:inner macro attributes are unstable +// error-pattern:this was previously accepted +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[deny(unused_attributes)] +mod module_with_attrs; +//~^ ERROR non-inline modules in proc macro input are unstable +//~| ERROR custom inner attributes are unstable + +fn main() {} diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr b/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr new file mode 100644 index 000000000..2d357d04d --- /dev/null +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr @@ -0,0 +1,40 @@ +error[E0658]: inner macro attributes are unstable + --> $DIR/module_with_attrs.rs:4:4 + | +LL | #![print_attr] + | ^^^^^^^^^^ + | + = note: see issue #54726 for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error[E0658]: non-inline modules in proc macro input are unstable + --> $DIR/inner-attr-non-inline-mod.rs:14:1 + | +LL | mod module_with_attrs; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom inner attributes are unstable + --> $DIR/inner-attr-non-inline-mod.rs:14:1 + | +LL | mod module_with_attrs; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #54726 for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error: custom inner attributes are unstable + --> $DIR/module_with_attrs.rs:3:4 + | +LL | #![rustfmt::skip] + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + = note: `#[deny(soft_unstable)]` on by default + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout new file mode 100644 index 000000000..6261d82e2 --- /dev/null +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout @@ -0,0 +1,76 @@ +PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "deny", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused_attributes", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Ident { + ident: "mod", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Ident { + ident: "module_with_attrs", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustfmt", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + Ident { + ident: "skip", + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, + ], + span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0), + }, +] diff --git a/tests/ui/proc-macro/inner-attrs.rs b/tests/ui/proc-macro/inner-attrs.rs new file mode 100644 index 000000000..1000c9c75 --- /dev/null +++ b/tests/ui/proc-macro/inner-attrs.rs @@ -0,0 +1,87 @@ +// gate-test-custom_inner_attributes +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs +// edition:2018 + +#![feature(custom_inner_attributes)] +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_target_and_args(first)] +#[print_target_and_args(second)] +fn foo() { + #![print_target_and_args(third)] + #![print_target_and_args(fourth)] +} + +#[print_target_and_args(mod_first)] +#[print_target_and_args(mod_second)] +mod inline_mod { + #![print_target_and_args(mod_third)] + #![print_target_and_args(mod_fourth)] +} + +struct MyStruct { + field: bool +} + +#[derive(Print)] +struct MyDerivePrint { + field: [u8; { + match true { + _ => { + #![cfg_attr(not(FALSE), rustc_dummy(third))] + true + } + }; + 0 + }] +} + +fn bar() { + #[print_target_and_args(tuple_attrs)] ( + 3, 4, { + #![cfg_attr(not(FALSE), rustc_dummy(innermost))] + 5 + } + ); + + #[print_target_and_args(tuple_attrs)] ( + 3, 4, { + #![cfg_attr(not(FALSE), rustc_dummy(innermost))] + 5 + } + ); + + for _ in &[true] { + #![print_attr] //~ ERROR expected non-macro inner attribute + } + + let _ = { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; + + let _ = async { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; + + { + #![print_attr] //~ ERROR expected non-macro inner attribute + }; +} + + +extern { + fn weird_extern() { + #![print_target_and_args_consume(tenth)] + } +} + +fn main() {} diff --git a/tests/ui/proc-macro/inner-attrs.stderr b/tests/ui/proc-macro/inner-attrs.stderr new file mode 100644 index 000000000..a332e143a --- /dev/null +++ b/tests/ui/proc-macro/inner-attrs.stderr @@ -0,0 +1,26 @@ +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:64:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:68:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:72:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: expected non-macro inner attribute, found attribute macro `print_attr` + --> $DIR/inner-attrs.rs:76:12 + | +LL | #![print_attr] + | ^^^^^^^^^^ not a non-macro inner attribute + +error: aborting due to 4 previous errors + diff --git a/tests/ui/proc-macro/inner-attrs.stdout b/tests/ui/proc-macro/inner-attrs.stdout new file mode 100644 index 000000000..ee8adf0b4 --- /dev/null +++ b/tests/ui/proc-macro/inner-attrs.stdout @@ -0,0 +1,956 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): first +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "first", + span: $DIR/inner-attrs.rs:17:25: 17:30 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second)] fn foo() +{ #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:18:1: 18:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:18:3: 18:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/inner-attrs.rs:18:25: 18:31 (#0), + }, + ], + span: $DIR/inner-attrs.rs:18:24: 18:32 (#0), + }, + ], + span: $DIR/inner-attrs.rs:18:2: 18:33 (#0), + }, + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:20:30: 20:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:37 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:21:5: 21:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:21:6: 21:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:21:8: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:29: 21:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:7: 21:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): second +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "second", + span: $DIR/inner-attrs.rs:18:25: 18:31 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() +{ #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:20:30: 20:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:37 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:21:5: 21:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:21:6: 21:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:21:8: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:29: 21:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:7: 21:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): third +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:20:30: 20:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:21:5: 21:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:21:6: 21:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:21:8: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:29: 21:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:7: 21:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): fourth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_first +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_first", + span: $DIR/inner-attrs.rs:24:25: 24:34 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod +{ + #! [print_target_and_args(mod_third)] #! + [print_target_and_args(mod_fourth)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:25:1: 25:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:25:3: 25:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_second", + span: $DIR/inner-attrs.rs:25:25: 25:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:24: 25:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:25:2: 25:37 (#0), + }, + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:27:30: 27:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:28:5: 28:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:28:6: 28:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:28:8: 28:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:29: 28:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:7: 28:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_second +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_second", + span: $DIR/inner-attrs.rs:25:25: 25:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod +{ + #! [print_target_and_args(mod_third)] #! + [print_target_and_args(mod_fourth)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:27:30: 27:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:28:5: 28:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:28:6: 28:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:28:8: 28:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:29: 28:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:7: 28:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:27:30: 27:39 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:28:5: 28:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:28:6: 28:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:28:8: 28:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:29: 28:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:7: 28:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_fourth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint +{ + field : + [u8 ; { match true { _ => { #! [rustc_dummy(third)] true } } ; 0 }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/inner-attrs.rs:36:1: 36:7 (#0), + }, + Ident { + ident: "MyDerivePrint", + span: $DIR/inner-attrs.rs:36:8: 36:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/inner-attrs.rs:37:5: 37:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/inner-attrs.rs:37:10: 37:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/inner-attrs.rs:37:13: 37:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:37:15: 37:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "match", + span: $DIR/inner-attrs.rs:38:9: 38:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/inner-attrs.rs:38:15: 38:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "_", + span: $DIR/inner-attrs.rs:39:13: 39:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/inner-attrs.rs:39:15: 39:16 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/inner-attrs.rs:39:16: 39:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attrs.rs:40:17: 40:18 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:40:18: 40:19 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:40:41: 40:52 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:40:53: 40:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:40:52: 40:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:40:17: 40:18 (#0), + }, + Ident { + ident: "true", + span: $DIR/inner-attrs.rs:41:17: 41:21 (#0), + }, + ], + span: $DIR/inner-attrs.rs:39:18: 42:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:38:20: 43:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:43:10: 43:11 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/inner-attrs.rs:44:9: 44:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:37:17: 45:6 (#0), + }, + ], + span: $DIR/inner-attrs.rs:37:12: 45:7 (#0), + }, + ], + span: $DIR/inner-attrs.rs:36:22: 46:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tuple_attrs", + span: $DIR/inner-attrs.rs:49:29: 49:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/inner-attrs.rs:50:9: 50:10 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:50:10: 50:11 (#0), + }, + Literal { + kind: Integer, + symbol: "4", + suffix: None, + span: $DIR/inner-attrs.rs:50:12: 50:13 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:50:13: 50:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:51:13: 51:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:51:14: 51:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:51:16: 51:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:51:25: 51:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:51:29: 51:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:28: 51:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:51:35: 51:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:51:37: 51:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:51:49: 51:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:48: 51:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:24: 51:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:15: 51:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/inner-attrs.rs:52:13: 52:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:50:15: 53:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:49:43: 54:6 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:54:6: 54:7 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tuple_attrs", + span: $DIR/inner-attrs.rs:56:29: 56:40 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/inner-attrs.rs:57:9: 57:10 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:57:10: 57:11 (#0), + }, + Literal { + kind: Integer, + symbol: "4", + suffix: None, + span: $DIR/inner-attrs.rs:57:12: 57:13 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:57:13: 57:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:58:13: 58:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:58:14: 58:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:58:16: 58:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:58:25: 58:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:58:29: 58:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:58:28: 58:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:58:35: 58:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:58:37: 58:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:58:49: 58:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:58:48: 58:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:58:24: 58:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:58:15: 58:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/inner-attrs.rs:59:13: 59:14 (#0), + }, + ], + span: $DIR/inner-attrs.rs:57:15: 60:10 (#0), + }, + ], + span: $DIR/inner-attrs.rs:56:43: 61:6 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/inner-attrs.rs:61:6: 61:7 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): tenth +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "tenth", + span: $DIR/inner-attrs.rs:83:42: 83:47 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn weird_extern() {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:82:5: 82:7 (#0), + }, + Ident { + ident: "weird_extern", + span: $DIR/inner-attrs.rs:82:8: 82:20 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:82:20: 82:22 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:82:23: 84:6 (#0), + }, +] diff --git a/tests/ui/proc-macro/input-interpolated.rs b/tests/ui/proc-macro/input-interpolated.rs new file mode 100644 index 000000000..5e49e330c --- /dev/null +++ b/tests/ui/proc-macro/input-interpolated.rs @@ -0,0 +1,29 @@ +// Check what token streams proc macros see when interpolated tokens are passed to them as input. + +// check-pass +// edition:2018 +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! pass_ident { + ($i:ident) => { + fn f() { + print_bang!($i); + } + + #[print_attr] + const $i: u8 = 0; + + #[derive(Print)] + struct $i {} + }; +} + +pass_ident!(A); + +fn main() {} diff --git a/tests/ui/proc-macro/input-interpolated.stdout b/tests/ui/proc-macro/input-interpolated.stdout new file mode 100644 index 000000000..34566c780 --- /dev/null +++ b/tests/ui/proc-macro/input-interpolated.stdout @@ -0,0 +1,59 @@ +PRINT-BANG INPUT (DISPLAY): A +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "A", + span: #0 bytes(503..504), + }, +] +PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "const", + span: #4 bytes(416..421), + }, + Ident { + ident: "A", + span: #0 bytes(503..504), + }, + Punct { + ch: ':', + spacing: Alone, + span: #4 bytes(424..425), + }, + Ident { + ident: "u8", + span: #4 bytes(426..428), + }, + Punct { + ch: '=', + spacing: Alone, + span: #4 bytes(429..430), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #4 bytes(431..432), + }, + Punct { + ch: ';', + spacing: Alone, + span: #4 bytes(432..433), + }, +] +PRINT-DERIVE INPUT (DISPLAY): struct A {} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: #4 bytes(468..474), + }, + Ident { + ident: "A", + span: #0 bytes(503..504), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: #4 bytes(478..480), + }, +] diff --git a/tests/ui/proc-macro/invalid-attributes.rs b/tests/ui/proc-macro/invalid-attributes.rs new file mode 100644 index 000000000..6bbe022c6 --- /dev/null +++ b/tests/ui/proc-macro/invalid-attributes.rs @@ -0,0 +1,26 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro = "test"] //~ ERROR malformed `proc_macro` attribute +pub fn a(a: TokenStream) -> TokenStream { a } + +#[proc_macro()] //~ ERROR malformed `proc_macro` attribute +pub fn c(a: TokenStream) -> TokenStream { a } + +#[proc_macro(x)] //~ ERROR malformed `proc_macro` attribute +pub fn d(a: TokenStream) -> TokenStream { a } + +#[proc_macro_attribute = "test"] //~ ERROR malformed `proc_macro_attribute` attribute +pub fn e(_: TokenStream, a: TokenStream) -> TokenStream { a } + +#[proc_macro_attribute()] //~ ERROR malformed `proc_macro_attribute` attribute +pub fn g(_: TokenStream, a: TokenStream) -> TokenStream { a } + +#[proc_macro_attribute(x)] //~ ERROR malformed `proc_macro_attribute` attribute +pub fn h(_: TokenStream, a: TokenStream) -> TokenStream { a } diff --git a/tests/ui/proc-macro/invalid-attributes.stderr b/tests/ui/proc-macro/invalid-attributes.stderr new file mode 100644 index 000000000..fe411fa5e --- /dev/null +++ b/tests/ui/proc-macro/invalid-attributes.stderr @@ -0,0 +1,38 @@ +error: malformed `proc_macro` attribute input + --> $DIR/invalid-attributes.rs:10:1 + | +LL | #[proc_macro = "test"] + | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `proc_macro` attribute input + --> $DIR/invalid-attributes.rs:13:1 + | +LL | #[proc_macro()] + | ^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `proc_macro` attribute input + --> $DIR/invalid-attributes.rs:16:1 + | +LL | #[proc_macro(x)] + | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/invalid-attributes.rs:19:1 + | +LL | #[proc_macro_attribute = "test"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/invalid-attributes.rs:22:1 + | +LL | #[proc_macro_attribute()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + +error: malformed `proc_macro_attribute` attribute input + --> $DIR/invalid-attributes.rs:25:1 + | +LL | #[proc_macro_attribute(x)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/proc-macro/invalid-punct-ident-1.rs b/tests/ui/proc-macro/invalid-punct-ident-1.rs new file mode 100644 index 000000000..9a1802737 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-1.rs @@ -0,0 +1,9 @@ +// aux-build:invalid-punct-ident.rs +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate invalid_punct_ident; + +invalid_punct!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/tests/ui/proc-macro/invalid-punct-ident-1.stderr b/tests/ui/proc-macro/invalid-punct-ident-1.stderr new file mode 100644 index 000000000..78aa84401 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-1.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/invalid-punct-ident-1.rs:7:1 + | +LL | invalid_punct!(); + | ^^^^^^^^^^^^^^^^ + | + = help: message: unsupported character `'`'` + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/invalid-punct-ident-2.rs b/tests/ui/proc-macro/invalid-punct-ident-2.rs new file mode 100644 index 000000000..afb6985e4 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-2.rs @@ -0,0 +1,9 @@ +// aux-build:invalid-punct-ident.rs +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate invalid_punct_ident; + +invalid_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/tests/ui/proc-macro/invalid-punct-ident-2.stderr b/tests/ui/proc-macro/invalid-punct-ident-2.stderr new file mode 100644 index 000000000..66979e756 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-2.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/invalid-punct-ident-2.rs:7:1 + | +LL | invalid_ident!(); + | ^^^^^^^^^^^^^^^^ + | + = help: message: `"*"` is not a valid identifier + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/invalid-punct-ident-3.rs b/tests/ui/proc-macro/invalid-punct-ident-3.rs new file mode 100644 index 000000000..ff83695c5 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-3.rs @@ -0,0 +1,9 @@ +// aux-build:invalid-punct-ident.rs +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate invalid_punct_ident; + +invalid_raw_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/tests/ui/proc-macro/invalid-punct-ident-3.stderr b/tests/ui/proc-macro/invalid-punct-ident-3.stderr new file mode 100644 index 000000000..c096bc8c0 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-3.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/invalid-punct-ident-3.rs:7:1 + | +LL | invalid_raw_ident!(); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: message: `self` cannot be a raw identifier + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/invalid-punct-ident-4.rs b/tests/ui/proc-macro/invalid-punct-ident-4.rs new file mode 100644 index 000000000..2d2774bd1 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-4.rs @@ -0,0 +1,13 @@ +// aux-build:invalid-punct-ident.rs +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate invalid_punct_ident; + +lexer_failure!(); +//~^ ERROR proc macro panicked +//~| ERROR unexpected closing delimiter: `)` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/tests/ui/proc-macro/invalid-punct-ident-4.stderr b/tests/ui/proc-macro/invalid-punct-ident-4.stderr new file mode 100644 index 000000000..ab4116141 --- /dev/null +++ b/tests/ui/proc-macro/invalid-punct-ident-4.stderr @@ -0,0 +1,25 @@ +error: unexpected closing delimiter: `)` + --> $DIR/invalid-punct-ident-4.rs:7:1 + | +LL | lexer_failure!(); + | ^^^^^^^^^^^^^^^^ unexpected closing delimiter + | + = note: this error originates in the macro `lexer_failure` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc macro panicked + --> $DIR/invalid-punct-ident-4.rs:7:1 + | +LL | lexer_failure!(); + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/invalid-punct-ident-4.rs:12:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/is-available.rs b/tests/ui/proc-macro/is-available.rs new file mode 100644 index 000000000..b32bb61b4 --- /dev/null +++ b/tests/ui/proc-macro/is-available.rs @@ -0,0 +1,15 @@ +// run-pass + +extern crate proc_macro; + +// aux-build:is-available.rs +extern crate is_available; + +fn main() { + let a = proc_macro::is_available(); + let b = is_available::from_inside_proc_macro!(); + let c = proc_macro::is_available(); + assert!(!a); + assert!(b); + assert!(!c); +} diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs new file mode 100644 index 000000000..a0d619c45 --- /dev/null +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -0,0 +1,20 @@ +// aux-build:issue-104884.rs + +use std::collections::BinaryHeap; + +#[macro_use] +extern crate issue_104884; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +struct PriorityQueueEntry { + value: T, +} + +#[derive(PartialOrd, AddImpl)] +//~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` +//~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied +//~| ERROR can't compare `T` with `T` + +struct PriorityQueue(BinaryHeap>); + +fn main() {} diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr new file mode 100644 index 000000000..3b2a5e701 --- /dev/null +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -0,0 +1,39 @@ +error[E0277]: can't compare `PriorityQueue` with `PriorityQueue` + --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:10 + | +LL | #[derive(PartialOrd, AddImpl)] + | ^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` + | + = help: the trait `PartialEq` is not implemented for `PriorityQueue` +note: required by a bound in `PartialOrd` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `PriorityQueue: Eq` is not satisfied + --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 + | +LL | #[derive(PartialOrd, AddImpl)] + | ^^^^^^^ the trait `Eq` is not implemented for `PriorityQueue` + | +note: required by a bound in `Ord` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: can't compare `T` with `T` + --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 + | +LL | #[derive(PartialOrd, AddImpl)] + | ^^^^^^^ no implementation for `T < T` and `T > T` + | +note: required for `PriorityQueue` to implement `PartialOrd` + --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:10 + | +LL | #[derive(PartialOrd, AddImpl)] + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `Ord` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `AddImpl` which comes from the expansion of the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/proc-macro/issue-36935.rs b/tests/ui/proc-macro/issue-36935.rs new file mode 100644 index 000000000..03cdfa05e --- /dev/null +++ b/tests/ui/proc-macro/issue-36935.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate test_macros; + +#[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked +struct Baz { + //~^ ERROR the name `Baz` is defined multiple times + a: i32, + b: i32, +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-36935.stderr b/tests/ui/proc-macro/issue-36935.stderr new file mode 100644 index 000000000..122903798 --- /dev/null +++ b/tests/ui/proc-macro/issue-36935.stderr @@ -0,0 +1,22 @@ +error[E0428]: the name `Baz` is defined multiple times + --> $DIR/issue-36935.rs:8:1 + | +LL | struct Baz { + | ^^^^^^^^^^ + | | + | `Baz` redefined here + | previous definition of the type `Baz` here + | + = note: `Baz` must be defined only once in the type namespace of this module + +error: proc-macro derive panicked + --> $DIR/issue-36935.rs:7:20 + | +LL | #[derive(Identity, Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/proc-macro/issue-37788.rs b/tests/ui/proc-macro/issue-37788.rs new file mode 100644 index 000000000..73b1f0d58 --- /dev/null +++ b/tests/ui/proc-macro/issue-37788.rs @@ -0,0 +1,9 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +fn main() { + // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. + std::cell::Cell::new(0) //~ ERROR mismatched types +} diff --git a/tests/ui/proc-macro/issue-37788.stderr b/tests/ui/proc-macro/issue-37788.stderr new file mode 100644 index 000000000..345520d48 --- /dev/null +++ b/tests/ui/proc-macro/issue-37788.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-37788.rs:8:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. +LL | std::cell::Cell::new(0) + | ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found struct `Cell` + | + = note: expected unit type `()` + found struct `Cell<{integer}>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/issue-38586.rs b/tests/ui/proc-macro/issue-38586.rs new file mode 100644 index 000000000..24e88ed93 --- /dev/null +++ b/tests/ui/proc-macro/issue-38586.rs @@ -0,0 +1,9 @@ +// aux-build:issue-38586.rs + +#[macro_use] +extern crate issue_38586; + +#[derive(A)] //~ ERROR `foo` +struct A; + +fn main() {} diff --git a/tests/ui/proc-macro/issue-38586.stderr b/tests/ui/proc-macro/issue-38586.stderr new file mode 100644 index 000000000..ddd0a0874 --- /dev/null +++ b/tests/ui/proc-macro/issue-38586.stderr @@ -0,0 +1,11 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/issue-38586.rs:6:10 + | +LL | #[derive(A)] + | ^ not found in this scope + | + = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/issue-39889.rs b/tests/ui/proc-macro/issue-39889.rs new file mode 100644 index 000000000..69bfb4f3c --- /dev/null +++ b/tests/ui/proc-macro/issue-39889.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(dead_code, unused_macros)] +// aux-build:issue-39889.rs + +extern crate issue_39889; +use issue_39889::Issue39889; + +#[derive(Issue39889)] +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/issue-42708.rs b/tests/ui/proc-macro/issue-42708.rs new file mode 100644 index 000000000..e8f445aaa --- /dev/null +++ b/tests/ui/proc-macro/issue-42708.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:issue-42708.rs + +#![feature(decl_macro)] +#![allow(unused)] + +extern crate issue_42708; + +macro m() { + #[derive(issue_42708::Test)] + struct S { x: () } + + #[issue_42708::attr_test] + struct S2 { x: () } + + #[derive(Clone)] + struct S3 { x: () } + + fn g(s: S, s2: S2, s3: S3) { + (s.x, s2.x, s3.x); + } +} + +m!(); + +fn main() {} diff --git a/tests/ui/proc-macro/issue-50061.rs b/tests/ui/proc-macro/issue-50061.rs new file mode 100644 index 000000000..01c6b80b4 --- /dev/null +++ b/tests/ui/proc-macro/issue-50061.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(path_statements)] +// aux-build:issue-50061.rs + +#![feature(decl_macro)] + +extern crate issue_50061; + +macro inner(any_token $v: tt) { + $v +} + +macro outer($v: tt) { + inner!(any_token $v) +} + +#[issue_50061::check] +fn main() { + //! this doc comment forces roundtrip through a string + let checkit = 0; + outer!(checkit); +} diff --git a/tests/ui/proc-macro/issue-50493.rs b/tests/ui/proc-macro/issue-50493.rs new file mode 100644 index 000000000..ce0e0839f --- /dev/null +++ b/tests/ui/proc-macro/issue-50493.rs @@ -0,0 +1,13 @@ +// aux-build:issue-50493.rs + +#[macro_use] +extern crate issue_50493; + +#[derive(Derive)] +struct Restricted { + pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules +} + +mod restricted {} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-50493.stderr b/tests/ui/proc-macro/issue-50493.stderr new file mode 100644 index 000000000..23e103dbf --- /dev/null +++ b/tests/ui/proc-macro/issue-50493.stderr @@ -0,0 +1,9 @@ +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/issue-50493.rs:8:12 + | +LL | pub(in restricted) field: usize, + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0742`. diff --git a/tests/ui/proc-macro/issue-53481.rs b/tests/ui/proc-macro/issue-53481.rs new file mode 100644 index 000000000..ae10a3baa --- /dev/null +++ b/tests/ui/proc-macro/issue-53481.rs @@ -0,0 +1,22 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod m1 { + use m2::Empty; + + #[derive(Empty)] + struct A {} +} + +mod m2 { + pub type Empty = u8; + + #[derive(Empty)] + #[empty_helper] + struct B {} +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs new file mode 100644 index 000000000..a4161d4fc --- /dev/null +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -0,0 +1,10 @@ +// Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely. +// `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`. + +// edition:2018 +// aux-crate:issue_59191=issue-59191.rs +// error-pattern: requires `sized` lang_item + +#![feature(custom_inner_attributes)] +#![issue_59191::no_main] +#![issue_59191::no_main] diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr new file mode 100644 index 000000000..f7516c7d3 --- /dev/null +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -0,0 +1,4 @@ +error: requires `sized` lang_item + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/issue-66286.rs b/tests/ui/proc-macro/issue-66286.rs new file mode 100644 index 000000000..2a67aeab4 --- /dev/null +++ b/tests/ui/proc-macro/issue-66286.rs @@ -0,0 +1,13 @@ +// aux-build:issue-66286.rs + +// Regression test for #66286. + +extern crate issue_66286; + +#[issue_66286::vec_ice] +pub extern fn foo(_: Vec(u32)) -> u32 { + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait + 0 +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-66286.stderr b/tests/ui/proc-macro/issue-66286.stderr new file mode 100644 index 000000000..fe2464b3b --- /dev/null +++ b/tests/ui/proc-macro/issue-66286.stderr @@ -0,0 +1,14 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-66286.rs:8:22 + | +LL | pub extern fn foo(_: Vec(u32)) -> u32 { + | ^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | pub extern fn foo(_: Vec) -> u32 { + | ~ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs b/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs new file mode 100644 index 000000000..a573c6e1c --- /dev/null +++ b/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// check-pass + +#[macro_use] +extern crate test_macros; + +#[derive(Print)] +enum ProceduralMasqueradeDummyType { + Input +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout new file mode 100644 index 000000000..8cd981e03 --- /dev/null +++ b/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout @@ -0,0 +1,21 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: #0 bytes(100..104), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: #0 bytes(105..134), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: #0 bytes(141..146), + }, + ], + span: #0 bytes(135..148), + }, +] diff --git a/tests/ui/proc-macro/issue-75734-pp-paren.rs b/tests/ui/proc-macro/issue-75734-pp-paren.rs new file mode 100644 index 000000000..faa93787d --- /dev/null +++ b/tests/ui/proc-macro/issue-75734-pp-paren.rs @@ -0,0 +1,26 @@ +// Regression test for issue #75734 +// Ensures that we don't lose tokens when pretty-printing would +// normally insert extra parentheses. + +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! mul_2 { + ($val:expr) => { + print_bang!($val * 2); + }; +} + + +#[print_attr] +fn main() { + &|_: u8| {}; + mul_2!(1 + 1); +} diff --git a/tests/ui/proc-macro/issue-75734-pp-paren.stdout b/tests/ui/proc-macro/issue-75734-pp-paren.stdout new file mode 100644 index 000000000..0fda6654f --- /dev/null +++ b/tests/ui/proc-macro/issue-75734-pp-paren.stdout @@ -0,0 +1,134 @@ +PRINT-ATTR INPUT (DISPLAY): fn main() { & | _ : u8 | {} ; mul_2! (1 + 1) ; } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/issue-75734-pp-paren.rs:23:1: 23:3 (#0), + }, + Ident { + ident: "main", + span: $DIR/issue-75734-pp-paren.rs:23:4: 23:8 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75734-pp-paren.rs:23:8: 23:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '&', + spacing: Joint, + span: $DIR/issue-75734-pp-paren.rs:24:5: 24:6 (#0), + }, + Punct { + ch: '|', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:6: 24:7 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75734-pp-paren.rs:24:7: 24:8 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:8: 24:9 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75734-pp-paren.rs:24:10: 24:12 (#0), + }, + Punct { + ch: '|', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:12: 24:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75734-pp-paren.rs:24:14: 24:16 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:24:16: 24:17 (#0), + }, + Ident { + ident: "mul_2", + span: $DIR/issue-75734-pp-paren.rs:25:5: 25:10 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:10: 25:11 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:12: 25:13 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:14: 25:15 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:16: 25:17 (#0), + }, + ], + span: $DIR/issue-75734-pp-paren.rs:25:11: 25:18 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:18: 25:19 (#0), + }, + ], + span: $DIR/issue-75734-pp-paren.rs:23:11: 26:2 (#0), + }, +] +PRINT-BANG INPUT (DISPLAY): 1 + 1 * 2 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:12: 25:13 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:25:14: 25:15 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:25:16: 25:17 (#0), + }, + ], + span: $DIR/issue-75734-pp-paren.rs:17:21: 17:25 (#7), + }, + Punct { + ch: '*', + spacing: Alone, + span: $DIR/issue-75734-pp-paren.rs:17:26: 17:27 (#7), + }, + Literal { + kind: Integer, + symbol: "2", + suffix: None, + span: $DIR/issue-75734-pp-paren.rs:17:28: 17:29 (#7), + }, +] diff --git a/tests/ui/proc-macro/issue-75801.rs b/tests/ui/proc-macro/issue-75801.rs new file mode 100644 index 000000000..b07cde0fa --- /dev/null +++ b/tests/ui/proc-macro/issue-75801.rs @@ -0,0 +1,19 @@ +// aux-build: issue-75801.rs + +// Regression test for #75801. + +#[macro_use] +extern crate issue_75801; + +macro_rules! foo { + ($arg:expr) => { + #[foo] + fn bar() { + let _bar: u32 = $arg; + } + }; +} + +foo!("baz"); //~ ERROR: mismatched types [E0308] + +fn main() {} diff --git a/tests/ui/proc-macro/issue-75801.stderr b/tests/ui/proc-macro/issue-75801.stderr new file mode 100644 index 000000000..ee0a9bd77 --- /dev/null +++ b/tests/ui/proc-macro/issue-75801.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-75801.rs:17:6 + | +LL | let _bar: u32 = $arg; + | --- expected due to this +... +LL | foo!("baz"); + | ^^^^^ expected `u32`, found `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.rs b/tests/ui/proc-macro/issue-75930-derive-cfg.rs new file mode 100644 index 000000000..ef56e8e02 --- /dev/null +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.rs @@ -0,0 +1,74 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +// Regression test for issue #75930 +// Tests that we cfg-strip all targets before invoking +// a derive macro +// We need '--error-format human' to stop compiletest from +// trying to interpret proc-macro output as JSON messages +// (a pretty-printed struct may cause a line to start with '{' ) +// FIXME: We currently lose spans here (see issue #43081) + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[print_helper(a)] //~ WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[cfg_attr(not(FALSE), allow(dead_code))] +#[print_attr] +#[derive(Print)] +#[print_helper(b)] +struct Foo<#[cfg(FALSE)] A, B> { + #[cfg(FALSE)] first: String, + #[cfg_attr(FALSE, deny(warnings))] second: bool, + third: [u8; { + #[cfg(FALSE)] struct Bar; + #[cfg(not(FALSE))] struct Inner; + #[cfg(FALSE)] let a = 25; + match true { + #[cfg(FALSE)] true => {}, + #[cfg_attr(not(FALSE), allow(warnings))] false => {}, + _ => {} + }; + + #[print_helper(should_be_removed)] + fn removed_fn() { + #![cfg(FALSE)] + } + + #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { + #![cfg(not(FALSE))] + let my_val = true; + } + + enum TupleEnum { + Foo( + #[cfg(FALSE)] u8, + #[cfg(FALSE)] bool, + #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] String, u8 + ) + } + + struct TupleStruct( + #[cfg(FALSE)] String, + #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] bool, + u8 + ); + + fn plain_removed_fn() { + #![cfg_attr(not(FALSE), cfg(FALSE))] + } + + 0 + }], + #[print_helper(d)] + fourth: B +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stderr b/tests/ui/proc-macro/issue-75930-derive-cfg.stderr new file mode 100644 index 000000000..6d1efb0dc --- /dev/null +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stderr @@ -0,0 +1,27 @@ +warning: derive helper attribute is used before it is introduced + --> $DIR/issue-75930-derive-cfg.rs:19:3 + | +LL | #[print_helper(a)] + | ^^^^^^^^^^^^ +... +LL | #[derive(Print)] + | ----- the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + = note: `#[warn(legacy_derive_helpers)]` on by default + +warning: derive helper attribute is used before it is introduced + --> $DIR/issue-75930-derive-cfg.rs:19:3 + | +LL | #[print_helper(a)] + | ^^^^^^^^^^^^ +... +LL | #[derive(Print)] + | ----- the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: 2 warnings emitted + diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout new file mode 100644 index 000000000..83afd0d3e --- /dev/null +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -0,0 +1,1904 @@ +PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] +struct Foo < #[cfg(FALSE)] A, B > +{ + #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second : + bool, third : + [u8 ; + { + #[cfg(FALSE)] struct Bar ; #[cfg(not(FALSE))] struct Inner ; + #[cfg(FALSE)] let a = 25 ; match true + { + #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] + false => {}, _ => {} + } ; #[print_helper(should_be_removed)] fn removed_fn() + { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() + { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { + Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] String, u8) + } struct + TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, + #[cfg(FALSE)] bool, u8) ; fn plain_removed_fn() + { #! [cfg_attr(not(FALSE), cfg(FALSE))] } 0 + }], #[print_helper(d)] fourth : B +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:23:1: 23:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "derive", + span: $DIR/issue-75930-derive-cfg.rs:23:3: 23:9 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "Print", + span: $DIR/issue-75930-derive-cfg.rs:23:10: 23:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:23:9: 23:16 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:23:2: 23:17 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "b", + span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:12: 25:13 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:25:14: 25:17 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:25:18: 25:23 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:17: 25:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:13: 25:25 (#0), + }, + Ident { + ident: "A", + span: $DIR/issue-75930-derive-cfg.rs:25:26: 25:27 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:27: 25:28 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:5: 26:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:26:7: 26:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:26:11: 26:16 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:26:10: 26:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:26:6: 26:18 (#0), + }, + Ident { + ident: "first", + span: $DIR/issue-75930-derive-cfg.rs:26:19: 26:24 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:24: 26:25 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:26:26: 26:32 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:26:32: 26:33 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:5: 27:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:27:7: 27:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:27:16: 27:21 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:21: 27:22 (#0), + }, + Ident { + ident: "deny", + span: $DIR/issue-75930-derive-cfg.rs:27:23: 27:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:27:28: 27:36 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:27: 27:37 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:38 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:27:6: 27:39 (#0), + }, + Ident { + ident: "second", + span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0), + }, + Ident { + ident: "third", + span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:9: 29:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:29:11: 29:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:29:15: 29:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:14: 29:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:29:10: 29:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:29:23: 29:29 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/issue-75930-derive-cfg.rs:29:30: 29:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:29:33: 29:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:9: 31:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:31:11: 31:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:31:15: 31:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:31:14: 31:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:31:10: 31:22 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:31:23: 31:26 (#0), + }, + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:31:27: 31:28 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:29: 31:30 (#0), + }, + Literal { + kind: Integer, + symbol: "25", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:31:31: 31:33 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:31:33: 31:34 (#0), + }, + Ident { + ident: "match", + span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:13: 33:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:33:15: 33:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:33:19: 33:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:33:18: 33:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:33:14: 33:26 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:33:27: 33:31 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:33: 33:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:33:35: 33:37 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:33:37: 33:38 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:34:15: 34:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:34:24: 34:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:34:28: 34:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:27: 34:34 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:34: 34:35 (#0), + }, + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:23: 34:52 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:14: 34:53 (#0), + }, + Ident { + ident: "false", + span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:61 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:61: 34:62 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:16 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:35:16: 35:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:38:9: 38:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:38:11: 38:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "should_be_removed", + span: $DIR/issue-75930-derive-cfg.rs:38:24: 38:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:23: 38:42 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:38:10: 38:43 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:39:9: 39:11 (#0), + }, + Ident { + ident: "removed_fn", + span: $DIR/issue-75930-derive-cfg.rs:39:12: 39:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:39:22: 39:24 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:40:13: 40:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:40:14: 40:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:40:16: 40:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:40:20: 40:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:40:19: 40:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:40:15: 40:27 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:39:25: 41:10 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "c", + span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0), + }, + Ident { + ident: "kept_fn", + span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0), + }, + Ident { + ident: "my_val", + span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0), + }, + Ident { + ident: "enum", + span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0), + }, + Ident { + ident: "TupleEnum", + span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:50:17: 50:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:50:19: 50:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:50:23: 50:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:50:22: 50:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:50:18: 50:30 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:50:31: 50:33 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:50:33: 50:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:51:17: 51:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:51:19: 51:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:51:23: 51:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:51:22: 51:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:51:18: 51:30 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:51:31: 51:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:51:35: 51:36 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:53:17: 53:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:53:19: 53:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:53:23: 53:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:53:22: 53:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:53:18: 53:30 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:53:31: 53:37 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:53:37: 53:38 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0), + }, + Ident { + ident: "TupleStruct", + span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:58:13: 58:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:58:15: 58:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:58:19: 58:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:58:18: 58:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:58:14: 58:26 (#0), + }, + Ident { + ident: "String", + span: $DIR/issue-75930-derive-cfg.rs:58:27: 58:33 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:58:33: 58:34 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:60:13: 60:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:60:15: 60:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:60:19: 60:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:60:18: 60:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:60:14: 60:26 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:60:27: 60:31 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:60:31: 60:32 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:64:9: 64:11 (#0), + }, + Ident { + ident: "plain_removed_fn", + span: $DIR/issue-75930-derive-cfg.rs:64:12: 64:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:64:28: 64:30 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:65:13: 65:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:65:14: 65:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/issue-75930-derive-cfg.rs:65:16: 65:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:65:25: 65:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:65:29: 65:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:28: 65:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:65:35: 65:36 (#0), + }, + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:65:37: 65:40 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:65:41: 65:46 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:40: 65:47 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:24: 65:48 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:65:15: 65:49 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:64:31: 66:10 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "d", + span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0), + }, + Ident { + ident: "fourth", + span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo < B > +{ + second : bool, third : + [u8 ; + { + #[cfg(not(FALSE))] struct Inner ; match true + { #[allow(warnings)] false => {}, _ => {} } ; #[print_helper(c)] + #[cfg(not(FALSE))] fn kept_fn() + { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { Foo(#[cfg(not(FALSE))] i32, u8) } struct + TupleStruct(#[cfg(not(FALSE))] i32, u8) ; 0 + }], #[print_helper(d)] fourth : B +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "b", + span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0), + }, + Punct { + ch: '<', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0), + }, + Ident { + ident: "bool", + span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0), + }, + Ident { + ident: "third", + span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0), + }, + Ident { + ident: "match", + span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "warnings", + span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0), + }, + Ident { + ident: "false", + span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:61 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:61: 34:62 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0), + }, + Ident { + ident: "_", + span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:16 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:35:16: 35:17 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "c", + span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0), + }, + Ident { + ident: "fn", + span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0), + }, + Ident { + ident: "kept_fn", + span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0), + }, + Ident { + ident: "let", + span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0), + }, + Ident { + ident: "my_val", + span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0), + }, + Ident { + ident: "true", + span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0), + }, + Ident { + ident: "enum", + span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0), + }, + Ident { + ident: "TupleEnum", + span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Foo", + span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0), + }, + Ident { + ident: "TupleStruct", + span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg", + span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0), + }, + Ident { + ident: "i32", + span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0), + }, + Ident { + ident: "u8", + span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_helper", + span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "d", + span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0), + }, + Ident { + ident: "fourth", + span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0), + }, + Ident { + ident: "B", + span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0), + }, + ], + span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs b/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs new file mode 100644 index 000000000..7d31de1d2 --- /dev/null +++ b/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs @@ -0,0 +1,16 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// +// Regression test for issue #76182 +// Tests that we properly handle patterns with a leading vert + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; + +#[test_macros::print_attr] +fn main() { + match () { | () => () } +} diff --git a/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout b/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout new file mode 100644 index 000000000..09eb33f7e --- /dev/null +++ b/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout @@ -0,0 +1,62 @@ +PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/issue-76182-leading-vert-pat.rs:14:1: 14:3 (#0), + }, + Ident { + ident: "main", + span: $DIR/issue-76182-leading-vert-pat.rs:14:4: 14:8 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:14:8: 14:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "match", + span: $DIR/issue-76182-leading-vert-pat.rs:15:5: 15:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:15:11: 15:13 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '|', + spacing: Alone, + span: $DIR/issue-76182-leading-vert-pat.rs:15:16: 15:17 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:15:18: 15:20 (#0), + }, + Punct { + ch: '=', + spacing: Joint, + span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:22 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/issue-76182-leading-vert-pat.rs:15:22: 15:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/issue-76182-leading-vert-pat.rs:15:24: 15:26 (#0), + }, + ], + span: $DIR/issue-76182-leading-vert-pat.rs:15:14: 15:28 (#0), + }, + ], + span: $DIR/issue-76182-leading-vert-pat.rs:14:11: 16:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs new file mode 100644 index 000000000..5aefec3ec --- /dev/null +++ b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs @@ -0,0 +1,13 @@ +// aux-build:proc-macro-panic.rs +// edition:2018 +// needs-unwind proc macro panics to report errors + +// Regression test for issue #76270 +// Tests that we don't print an ICE message when a panic +// occurs in libproc-macro (when `-Z proc-macro-backtrace` is not specified) + +extern crate proc_macro_panic; + +proc_macro_panic::panic_in_libproc_macro!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr new file mode 100644 index 000000000..d69de23a4 --- /dev/null +++ b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr @@ -0,0 +1,10 @@ +error: proc macro panicked + --> $DIR/issue-76270-panic-in-libproc-macro.rs:11:1 + | +LL | proc_macro_panic::panic_in_libproc_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: message: `""` is not a valid identifier + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs new file mode 100644 index 000000000..478809324 --- /dev/null +++ b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs @@ -0,0 +1,32 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] extern crate test_macros; + +macro_rules! foo {( + #[fake_attr] + $item:item +) => ( + $item +)} + +macro_rules! outer {($item:item) => ( + print_bang! { // Identity proc-macro + foo! { + #[fake_attr] + $item + } + } +)} +outer! { + mod bar { + //! Foo + } +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout new file mode 100644 index 000000000..60a400a5d --- /dev/null +++ b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout @@ -0,0 +1,87 @@ +PRINT-BANG INPUT (DISPLAY): foo! { #[fake_attr] mod bar { + #![doc = r" Foo"] +} } +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo! { #[fake_attr] mod bar { #! [doc = r" Foo"] } } +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "foo", + span: $DIR/issue-78675-captured-inner-attrs.rs:20:9: 20:12 (#4), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:20:12: 20:13 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:21:13: 21:14 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "fake_attr", + span: $DIR/issue-78675-captured-inner-attrs.rs:21:15: 21:24 (#4), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:21:14: 21:25 (#4), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "mod", + span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 27:8 (#0), + }, + Ident { + ident: "bar", + span: $DIR/issue-78675-captured-inner-attrs.rs:27:9: 27:12 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: " Foo", + suffix: None, + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:27:13: 29:6 (#0), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4), + }, + ], + span: $DIR/issue-78675-captured-inner-attrs.rs:20:14: 23:10 (#4), + }, +] diff --git a/tests/ui/proc-macro/issue-79148.rs b/tests/ui/proc-macro/issue-79148.rs new file mode 100644 index 000000000..3f01187a8 --- /dev/null +++ b/tests/ui/proc-macro/issue-79148.rs @@ -0,0 +1,10 @@ +// aux-build:re-export.rs +// edition:2018 + +extern crate re_export; + +use re_export::cause_ice; + +cause_ice!(); //~ ERROR `Variant` is only public within the crate, and cannot be re-exported outside + +fn main() {} diff --git a/tests/ui/proc-macro/issue-79148.stderr b/tests/ui/proc-macro/issue-79148.stderr new file mode 100644 index 000000000..a3b2de01d --- /dev/null +++ b/tests/ui/proc-macro/issue-79148.stderr @@ -0,0 +1,16 @@ +error[E0364]: `Variant` is only public within the crate, and cannot be re-exported outside + --> $DIR/issue-79148.rs:8:1 + | +LL | cause_ice!(); + | ^^^^^^^^^^^^ + | +note: consider marking `Variant` as `pub` in the imported module + --> $DIR/issue-79148.rs:8:1 + | +LL | cause_ice!(); + | ^^^^^^^^^^^^ + = note: this error originates in the macro `cause_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs b/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs new file mode 100644 index 000000000..b68f19c5d --- /dev/null +++ b/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs @@ -0,0 +1,34 @@ +// check-pass +// aux-build:issue-79242.rs + +// Regression test for issue #79242 +// Tests that compilation time doesn't blow up for a proc-macro +// invocation with deeply nested nonterminals + +#![allow(unused)] + +extern crate issue_79242; + +macro_rules! declare_nats { + ($prev:ty) => {}; + ($prev:ty, $n:literal$(, $tail:literal)*) => { + + issue_79242::dummy! { + $prev + } + + declare_nats!(Option<$prev>$(, $tail)*); + }; + (0, $($n:literal),+) => { + pub struct N0; + declare_nats!(N0, $($n),+); + }; +} + +declare_nats! { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 +} + + +fn main() {} diff --git a/tests/ui/proc-macro/issue-79825.rs b/tests/ui/proc-macro/issue-79825.rs new file mode 100644 index 000000000..f628469ce --- /dev/null +++ b/tests/ui/proc-macro/issue-79825.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:issue-79825.rs +#![feature(trait_alias)] + +extern crate issue_79825; + +#[issue_79825::assert_input] +trait Alias = Sized; + +fn main() {} diff --git a/tests/ui/proc-macro/issue-80760-empty-stmt.rs b/tests/ui/proc-macro/issue-80760-empty-stmt.rs new file mode 100644 index 000000000..86865af0b --- /dev/null +++ b/tests/ui/proc-macro/issue-80760-empty-stmt.rs @@ -0,0 +1,26 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! empty_stmt { + ($s:stmt) => { + print_bang!($s); + + // Currently, all attributes are ignored + // on an empty statement + #[print_attr] + #[rustc_dummy(first)] + #[rustc_dummy(second)] + $s + } +} + +fn main() { + empty_stmt!(;); +} diff --git a/tests/ui/proc-macro/issue-80760-empty-stmt.stdout b/tests/ui/proc-macro/issue-80760-empty-stmt.stdout new file mode 100644 index 000000000..4b7ed8743 --- /dev/null +++ b/tests/ui/proc-macro/issue-80760-empty-stmt.stdout @@ -0,0 +1,14 @@ +PRINT-BANG INPUT (DISPLAY): ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-80760-empty-stmt.rs:25:17: 25:18 (#0), + }, + ], + span: $DIR/issue-80760-empty-stmt.rs:13:21: 13:23 (#4), + }, +] diff --git a/tests/ui/proc-macro/issue-81007-item-attrs.rs b/tests/ui/proc-macro/issue-81007-item-attrs.rs new file mode 100644 index 000000000..ea27d54ee --- /dev/null +++ b/tests/ui/proc-macro/issue-81007-item-attrs.rs @@ -0,0 +1,31 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] extern crate test_macros; + +macro_rules! capture_item { + ($item:item) => { + #[print_attr] + $item + } +} + +capture_item! { + /// A doc comment + struct Foo {} +} + +capture_item! { + #[rustc_dummy] + /// Another comment comment + struct Bar {} +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-81007-item-attrs.stdout b/tests/ui/proc-macro/issue-81007-item-attrs.stdout new file mode 100644 index 000000000..3c001e995 --- /dev/null +++ b/tests/ui/proc-macro/issue-81007-item-attrs.stdout @@ -0,0 +1,99 @@ +PRINT-ATTR INPUT (DISPLAY): #[doc = r" A doc comment"] struct Foo {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: " A doc comment", + suffix: None, + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + ], + span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-81007-item-attrs.rs:22:5: 22:11 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/issue-81007-item-attrs.rs:22:12: 22:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-81007-item-attrs.rs:22:16: 22:18 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[doc = r" Another comment comment"] struct Bar {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:26:5: 26:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/issue-81007-item-attrs.rs:26:7: 26:18 (#0), + }, + ], + span: $DIR/issue-81007-item-attrs.rs:26:6: 26:19 (#0), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "doc", + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Literal { + kind: StrRaw(0), + symbol: " Another comment comment", + suffix: None, + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + ], + span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0), + }, + Ident { + ident: "struct", + span: $DIR/issue-81007-item-attrs.rs:28:5: 28:11 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/issue-81007-item-attrs.rs:28:12: 28:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/issue-81007-item-attrs.rs:28:16: 28:18 (#0), + }, +] diff --git a/tests/ui/proc-macro/issue-81543-item-parse-err.rs b/tests/ui/proc-macro/issue-81543-item-parse-err.rs new file mode 100644 index 000000000..027389556 --- /dev/null +++ b/tests/ui/proc-macro/issue-81543-item-parse-err.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs + +// Regression test for issue #81543 +// Tests that we emit a properly spanned error +// when the output of a proc-macro cannot be parsed +// as the expected AST node kind + +extern crate test_macros; + +test_macros::identity! { + fn 32() {} //~ ERROR expected identifier +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-81543-item-parse-err.stderr b/tests/ui/proc-macro/issue-81543-item-parse-err.stderr new file mode 100644 index 000000000..ca5241760 --- /dev/null +++ b/tests/ui/proc-macro/issue-81543-item-parse-err.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `32` + --> $DIR/issue-81543-item-parse-err.rs:11:8 + | +LL | fn 32() {} + | ^^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/issue-81555.rs b/tests/ui/proc-macro/issue-81555.rs new file mode 100644 index 000000000..693f1f7dc --- /dev/null +++ b/tests/ui/proc-macro/issue-81555.rs @@ -0,0 +1,15 @@ +// check-pass +// aux-build:test-macros.rs +#![feature(stmt_expr_attributes, proc_macro_hygiene)] + +extern crate test_macros; + +use test_macros::identity_attr; + +#[identity_attr] +fn main() { + let _x; + let y = (); + #[identity_attr] + _x = y; +} diff --git a/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs new file mode 100644 index 000000000..25adc5d25 --- /dev/null +++ b/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs @@ -0,0 +1,10 @@ +// Regression test for issue #83469 +// Ensures that we recover from `#[global_alloc]` on an invalid +// stmt without an ICE + +fn outer() { + #[global_allocator] + fn inner() {} //~ ERROR allocators must be statics +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr new file mode 100644 index 000000000..ec0e3c4c7 --- /dev/null +++ b/tests/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr @@ -0,0 +1,8 @@ +error: allocators must be statics + --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5 + | +LL | fn inner() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/issue-83510.rs b/tests/ui/proc-macro/issue-83510.rs new file mode 100644 index 000000000..2b1aec4df --- /dev/null +++ b/tests/ui/proc-macro/issue-83510.rs @@ -0,0 +1,11 @@ +// aux-build: issue-83510.rs + +extern crate issue_83510; + +issue_83510::dance_like_you_want_to_ice!(); +//~^ ERROR: cannot find type `Foo` in this scope +//~| ERROR: expected trait, found struct `Box` +//~| ERROR: cannot find trait `Baz` in this scope +//~| ERROR: inherent associated types are unstable + +fn main() {} diff --git a/tests/ui/proc-macro/issue-83510.stderr b/tests/ui/proc-macro/issue-83510.stderr new file mode 100644 index 000000000..e0628a317 --- /dev/null +++ b/tests/ui/proc-macro/issue-83510.stderr @@ -0,0 +1,38 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0404]: expected trait, found struct `Box` + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait + | + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0405]: cannot find trait `Baz` in this scope + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: inherent associated types are unstable + --> $DIR/issue-83510.rs:5:1 + | +LL | issue_83510::dance_like_you_want_to_ice!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0404, E0405, E0412, E0658. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed new file mode 100644 index 000000000..426a5fa72 --- /dev/null +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// run-rustfix + +#[macro_use] +extern crate test_macros; + +/// Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct + +fn main() {} diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs b/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs new file mode 100644 index 000000000..31e3f3c85 --- /dev/null +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// run-rustfix + +#[macro_use] +extern crate test_macros; + +//! Inner doc comment +//~^ ERROR expected outer doc comment +#[derive(Empty)] +pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct + +fn main() {} diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr new file mode 100644 index 000000000..a92f07522 --- /dev/null +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.stderr @@ -0,0 +1,17 @@ +error[E0753]: expected outer doc comment + --> $DIR/issue-86781-bad-inner-doc.rs:7:1 + | +LL | //! Inner doc comment + | ^^^^^^^^^^^^^^^^^^^^^ +... +LL | pub struct Foo; + | --------------- the inner doc comment doesn't annotate this struct + | +help: to annotate the struct, change the doc comment from inner to outer style + | +LL | /// Inner doc comment + | ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0753`. diff --git a/tests/ui/proc-macro/issue-91800.rs b/tests/ui/proc-macro/issue-91800.rs new file mode 100644 index 000000000..0c1281de4 --- /dev/null +++ b/tests/ui/proc-macro/issue-91800.rs @@ -0,0 +1,16 @@ +// aux-build: issue-91800-macro.rs + +#[macro_use] +extern crate issue_91800_macro; + +#[derive(MyTrait)] +//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon +//~| ERROR proc-macro derive produced unparseable tokens +#[attribute_macro] +//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon +struct MyStruct; + +fn_macro! {} +//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon + +fn main() {} diff --git a/tests/ui/proc-macro/issue-91800.stderr b/tests/ui/proc-macro/issue-91800.stderr new file mode 100644 index 000000000..9c356263a --- /dev/null +++ b/tests/ui/proc-macro/issue-91800.stderr @@ -0,0 +1,56 @@ +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-91800.rs:6:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + | + = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: proc-macro derive produced unparseable tokens + --> $DIR/issue-91800.rs:6:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + +error: + --> $DIR/issue-91800.rs:6:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + | + = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-91800.rs:9:1 + | +LL | #[attribute_macro] + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: + --> $DIR/issue-91800.rs:9:1 + | +LL | #[attribute_macro] + | ^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: macros that expand to items must be delimited with braces or followed by a semicolon + --> $DIR/issue-91800.rs:13:1 + | +LL | fn_macro! {} + | ^^^^^^^^^^^^ + | + = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: + --> $DIR/issue-91800.rs:13:1 + | +LL | fn_macro! {} + | ^^^^^^^^^^^^ + | + = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/tests/ui/proc-macro/item-error.rs b/tests/ui/proc-macro/item-error.rs new file mode 100644 index 000000000..64c203e54 --- /dev/null +++ b/tests/ui/proc-macro/item-error.rs @@ -0,0 +1,15 @@ +// aux-build:derive-b.rs + +#![allow(warnings)] + +#[macro_use] +extern crate derive_b; + +#[derive(B)] +struct A { + a: &u64 +//~^ ERROR: missing lifetime specifier +} + +fn main() { +} diff --git a/tests/ui/proc-macro/item-error.stderr b/tests/ui/proc-macro/item-error.stderr new file mode 100644 index 000000000..b544be6e9 --- /dev/null +++ b/tests/ui/proc-macro/item-error.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/item-error.rs:10:8 + | +LL | a: &u64 + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct A<'a> { +LL ~ a: &'a u64 + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/proc-macro/keep-expr-tokens.rs b/tests/ui/proc-macro/keep-expr-tokens.rs new file mode 100644 index 000000000..0bf889a85 --- /dev/null +++ b/tests/ui/proc-macro/keep-expr-tokens.rs @@ -0,0 +1,24 @@ +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![feature(stmt_expr_attributes)] +#![feature(proc_macro_hygiene)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; + +use test_macros::recollect_attr; + +fn main() { + #[test_macros::recollect_attr] + for item in missing_fn() {} //~ ERROR cannot find + + (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); //~ ERROR cannot + + #[test_macros::print_attr] + #[rustc_dummy] + { 1 +1; } // Don't change the weird spacing of the '+' +} diff --git a/tests/ui/proc-macro/keep-expr-tokens.stderr b/tests/ui/proc-macro/keep-expr-tokens.stderr new file mode 100644 index 000000000..1a1f83cc1 --- /dev/null +++ b/tests/ui/proc-macro/keep-expr-tokens.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `bad` in this scope + --> $DIR/keep-expr-tokens.rs:19:62 + | +LL | (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); + | ^^^ not found in this scope + +error[E0425]: cannot find function `missing_fn` in this scope + --> $DIR/keep-expr-tokens.rs:17:17 + | +LL | for item in missing_fn() {} + | ^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/keep-expr-tokens.stdout b/tests/ui/proc-macro/keep-expr-tokens.stdout new file mode 100644 index 000000000..fcd72a0e0 --- /dev/null +++ b/tests/ui/proc-macro/keep-expr-tokens.stdout @@ -0,0 +1,46 @@ +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 + 1 ; } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:22:5: 22:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/keep-expr-tokens.rs:22:7: 22:18 (#0), + }, + ], + span: $DIR/keep-expr-tokens.rs:22:6: 22:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/keep-expr-tokens.rs:23:7: 23:8 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:23:9: 23:10 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/keep-expr-tokens.rs:23:10: 23:11 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:23:11: 23:12 (#0), + }, + ], + span: $DIR/keep-expr-tokens.rs:23:5: 23:14 (#0), + }, +] diff --git a/tests/ui/proc-macro/lifetimes-rpass.rs b/tests/ui/proc-macro/lifetimes-rpass.rs new file mode 100644 index 000000000..a1d33ddca --- /dev/null +++ b/tests/ui/proc-macro/lifetimes-rpass.rs @@ -0,0 +1,26 @@ +// run-pass + +#![allow(unused_variables)] +// aux-build:lifetimes-rpass.rs + +extern crate lifetimes_rpass as lifetimes; +use lifetimes::*; + +lifetimes_bang! { + fn bang<'a>() -> &'a u8 { &0 } +} + +#[lifetimes_attr] +fn attr<'a>() -> &'a u8 { &1 } + +#[derive(Lifetimes)] +pub struct Lifetimes<'a> { + pub field: &'a u8, +} + +fn main() { + assert_eq!(bang::<'static>(), &0); + assert_eq!(attr::<'static>(), &1); + let l1 = Lifetimes { field: &0 }; + let l2 = m::Lifetimes { field: &1 }; +} diff --git a/tests/ui/proc-macro/lifetimes.rs b/tests/ui/proc-macro/lifetimes.rs new file mode 100644 index 000000000..560569671 --- /dev/null +++ b/tests/ui/proc-macro/lifetimes.rs @@ -0,0 +1,9 @@ +// aux-build:lifetimes.rs + +extern crate lifetimes; + +use lifetimes::*; + +type A = single_quote_alone!(); //~ ERROR expected type, found `'` + +fn main() {} diff --git a/tests/ui/proc-macro/lifetimes.stderr b/tests/ui/proc-macro/lifetimes.stderr new file mode 100644 index 000000000..0c99809ed --- /dev/null +++ b/tests/ui/proc-macro/lifetimes.stderr @@ -0,0 +1,13 @@ +error: expected type, found `'` + --> $DIR/lifetimes.rs:7:10 + | +LL | type A = single_quote_alone!(); + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | expected type + | this macro call doesn't expand to a type + | + = note: this error originates in the macro `single_quote_alone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/lints_in_proc_macros.rs b/tests/ui/proc-macro/lints_in_proc_macros.rs new file mode 100644 index 000000000..377a1f25b --- /dev/null +++ b/tests/ui/proc-macro/lints_in_proc_macros.rs @@ -0,0 +1,14 @@ +// aux-build:bang_proc_macro2.rs + +extern crate bang_proc_macro2; + +use bang_proc_macro2::bang_proc_macro2; + +fn main() { + let foobar = 42; + bang_proc_macro2!(); + //~^ ERROR cannot find value `foobar2` in this scope + //~| HELP a local variable with a similar name exists + //~| SUGGESTION foobar + println!("{}", x); +} diff --git a/tests/ui/proc-macro/lints_in_proc_macros.stderr b/tests/ui/proc-macro/lints_in_proc_macros.stderr new file mode 100644 index 000000000..4dd8be7d9 --- /dev/null +++ b/tests/ui/proc-macro/lints_in_proc_macros.stderr @@ -0,0 +1,11 @@ +error[E0425]: cannot find value `foobar2` in this scope + --> $DIR/lints_in_proc_macros.rs:9:5 + | +LL | bang_proc_macro2!(); + | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar` + | + = note: this error originates in the macro `bang_proc_macro2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/load-panic-backtrace.rs b/tests/ui/proc-macro/load-panic-backtrace.rs new file mode 100644 index 000000000..bcdcb704a --- /dev/null +++ b/tests/ui/proc-macro/load-panic-backtrace.rs @@ -0,0 +1,15 @@ +// aux-build:test-macros.rs +// compile-flags: -Z proc-macro-backtrace +// rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "thread '.*' panicked " -> "" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate test_macros; + +#[derive(Panic)] +//~^ ERROR: proc-macro derive panicked +struct Foo; + +fn main() {} diff --git a/tests/ui/proc-macro/load-panic-backtrace.stderr b/tests/ui/proc-macro/load-panic-backtrace.stderr new file mode 100644 index 000000000..45d4fd1c9 --- /dev/null +++ b/tests/ui/proc-macro/load-panic-backtrace.stderr @@ -0,0 +1,11 @@ +at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5 +error: proc-macro derive panicked + --> $DIR/load-panic-backtrace.rs:11:10 + | +LL | #[derive(Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/load-panic.rs b/tests/ui/proc-macro/load-panic.rs new file mode 100644 index 000000000..6ce88c400 --- /dev/null +++ b/tests/ui/proc-macro/load-panic.rs @@ -0,0 +1,11 @@ +// aux-build:test-macros.rs +// needs-unwind proc macro panics to report errors + +#[macro_use] +extern crate test_macros; + +#[derive(Panic)] +//~^ ERROR: proc-macro derive panicked +struct Foo; + +fn main() {} diff --git a/tests/ui/proc-macro/load-panic.stderr b/tests/ui/proc-macro/load-panic.stderr new file mode 100644 index 000000000..f0d62f690 --- /dev/null +++ b/tests/ui/proc-macro/load-panic.stderr @@ -0,0 +1,10 @@ +error: proc-macro derive panicked + --> $DIR/load-panic.rs:7:10 + | +LL | #[derive(Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/load-two.rs b/tests/ui/proc-macro/load-two.rs new file mode 100644 index 000000000..5ce0e6545 --- /dev/null +++ b/tests/ui/proc-macro/load-two.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(path_statements)] +#![allow(dead_code)] +// aux-build:derive-atob.rs +// aux-build:derive-ctod.rs + +#[macro_use] +extern crate derive_atob; +#[macro_use] +extern crate derive_ctod; + +#[derive(Copy, Clone)] +#[derive(AToB)] +struct A; + +#[derive(CToD)] +struct C; + +fn main() { + B; + D; +} diff --git a/tests/ui/proc-macro/macro-brackets.rs b/tests/ui/proc-macro/macro-brackets.rs new file mode 100644 index 000000000..aa0046f45 --- /dev/null +++ b/tests/ui/proc-macro/macro-brackets.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +macro_rules! id { + ($($t:tt)*) => ($($t)*) +} + +#[identity_attr] +id![static X: u32 = 'a';]; //~ ERROR: mismatched types + + +fn main() {} diff --git a/tests/ui/proc-macro/macro-brackets.stderr b/tests/ui/proc-macro/macro-brackets.stderr new file mode 100644 index 000000000..d35163752 --- /dev/null +++ b/tests/ui/proc-macro/macro-brackets.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/macro-brackets.rs:11:21 + | +LL | id![static X: u32 = 'a';]; + | ^^^ expected `u32`, found `char` + | +help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes + | +LL | id![static X: u32 = 'a' as u32;]; + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/macro-crate-multi-decorator.rs b/tests/ui/proc-macro/macro-crate-multi-decorator.rs new file mode 100644 index 000000000..ec57dec14 --- /dev/null +++ b/tests/ui/proc-macro/macro-crate-multi-decorator.rs @@ -0,0 +1,41 @@ +// The duplicate macro will create a copy of the item with the given identifier. + +// check-pass +// aux-build:duplicate.rs + +#[macro_use] +extern crate duplicate; + +#[duplicate(MyCopy)] +struct MyStruct { + number: i32, +} + +trait TestTrait { + #[duplicate(TestType2)] + type TestType; + + #[duplicate(required_fn2)] + fn required_fn(&self); + + #[duplicate(provided_fn2)] + fn provided_fn(&self) {} +} + +impl TestTrait for MyStruct { + #[duplicate(TestType2)] + type TestType = f64; + + #[duplicate(required_fn2)] + fn required_fn(&self) {} +} + +fn main() { + let s = MyStruct { number: 42 }; + s.required_fn(); + s.required_fn2(); + s.provided_fn(); + s.provided_fn2(); + + let s = MyCopy { number: 42 }; +} diff --git a/tests/ui/proc-macro/macro-namespace-reserved-2.rs b/tests/ui/proc-macro/macro-namespace-reserved-2.rs new file mode 100644 index 000000000..470b22b48 --- /dev/null +++ b/tests/ui/proc-macro/macro-namespace-reserved-2.rs @@ -0,0 +1,57 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn my_macro(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(MyTrait)] +pub fn my_macro_derive(input: TokenStream) -> TokenStream { + input +} + +fn check_bang1() { + my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it +} +fn check_bang2() { + my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope + crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines + //~| ERROR expected macro, found attribute macro `crate::my_macro_attr` +} +fn check_bang3() { + MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope + crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected macro, found derive macro `crate::MyTrait` +} + +#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope +#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected attribute, found macro `crate::my_macro` +fn check_attr1() {} +#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it +fn check_attr2() {} +#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected attribute, found derive macro `MyTrait` +fn check_attr3() {} + +#[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope + //~| ERROR cannot find derive macro `my_macro` in this scope +#[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines + //~| ERROR expected derive macro, found macro `crate::my_macro` +struct CheckDerive1; +#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it + //~| ERROR expected derive macro, found attribute macro `my_macro_attr` +struct CheckDerive2; +#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it +struct CheckDerive3; diff --git a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr new file mode 100644 index 000000000..633a6c6a0 --- /dev/null +++ b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr @@ -0,0 +1,132 @@ +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:25:5 + | +LL | my_macro!(); + | ^^^^^^^^ + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:29:5 + | +LL | crate::my_macro_attr!(); + | ^^^^^^^^^^^^^^^^^^^^ + +error: expected macro, found attribute macro `crate::my_macro_attr` + --> $DIR/macro-namespace-reserved-2.rs:29:5 + | +LL | crate::my_macro_attr!(); + | ^^^^^^^^^^^^^^^^^^^^ not a macro + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:34:5 + | +LL | crate::MyTrait!(); + | ^^^^^^^^^^^^^^ + +error: expected macro, found derive macro `crate::MyTrait` + --> $DIR/macro-namespace-reserved-2.rs:34:5 + | +LL | crate::MyTrait!(); + | ^^^^^^^^^^^^^^ not a macro + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:42:3 + | +LL | #[my_macro_attr] + | ^^^^^^^^^^^^^ + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:44:3 + | +LL | #[MyTrait] + | ^^^^^^^ + +error: expected attribute, found derive macro `MyTrait` + --> $DIR/macro-namespace-reserved-2.rs:44:3 + | +LL | #[MyTrait] + | ^^^^^^^ not an attribute + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:53:10 + | +LL | #[derive(my_macro_attr)] + | ^^^^^^^^^^^^^ + +error: expected derive macro, found attribute macro `my_macro_attr` + --> $DIR/macro-namespace-reserved-2.rs:53:10 + | +LL | #[derive(my_macro_attr)] + | ^^^^^^^^^^^^^ not a derive macro + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:56:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:39:3 + | +LL | #[crate::my_macro] + | ^^^^^^^^^^^^^^^ + +error: expected attribute, found macro `crate::my_macro` + --> $DIR/macro-namespace-reserved-2.rs:39:3 + | +LL | #[crate::my_macro] + | ^^^^^^^^^^^^^^^ not an attribute + +error: can't use a procedural macro from the same crate that defines it + --> $DIR/macro-namespace-reserved-2.rs:50:10 + | +LL | #[derive(crate::my_macro)] + | ^^^^^^^^^^^^^^^ + +error: expected derive macro, found macro `crate::my_macro` + --> $DIR/macro-namespace-reserved-2.rs:50:10 + | +LL | #[derive(crate::my_macro)] + | ^^^^^^^^^^^^^^^ not a derive macro + +error: cannot find macro `my_macro_attr` in this scope + --> $DIR/macro-namespace-reserved-2.rs:28:5 + | +LL | my_macro_attr!(); + | ^^^^^^^^^^^^^ + | + = note: `my_macro_attr` is in scope, but it is an attribute: `#[my_macro_attr]` + +error: cannot find macro `MyTrait` in this scope + --> $DIR/macro-namespace-reserved-2.rs:33:5 + | +LL | MyTrait!(); + | ^^^^^^^ + | + = note: `MyTrait` is in scope, but it is a derive macro: `#[derive(MyTrait)]` + +error: cannot find attribute `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:38:3 + | +LL | #[my_macro] + | ^^^^^^^^ + | + = note: `my_macro` is in scope, but it is a function-like macro + +error: cannot find derive macro `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:48:10 + | +LL | #[derive(my_macro)] + | ^^^^^^^^ + | + = note: `my_macro` is in scope, but it is a function-like macro + +error: cannot find derive macro `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:48:10 + | +LL | #[derive(my_macro)] + | ^^^^^^^^ + | + = note: `my_macro` is in scope, but it is a function-like macro + +error: aborting due to 20 previous errors + diff --git a/tests/ui/proc-macro/macro-namespace-reserved.rs b/tests/ui/proc-macro/macro-namespace-reserved.rs new file mode 100644 index 000000000..60d379e41 --- /dev/null +++ b/tests/ui/proc-macro/macro-namespace-reserved.rs @@ -0,0 +1,38 @@ +// force-host +// no-prefer-dynamic + +#![feature(decl_macro)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn my_macro(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(MyTrait)] +pub fn my_macro_derive(input: TokenStream) -> TokenStream { + input +} + +macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times +macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times +macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times + +#[proc_macro_derive(SameName)] +pub fn foo(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro] +pub fn SameName(input: TokenStream) -> TokenStream { +//~^ ERROR the name `SameName` is defined multiple times + input +} diff --git a/tests/ui/proc-macro/macro-namespace-reserved.stderr b/tests/ui/proc-macro/macro-namespace-reserved.stderr new file mode 100644 index 000000000..f5d589c3a --- /dev/null +++ b/tests/ui/proc-macro/macro-namespace-reserved.stderr @@ -0,0 +1,47 @@ +error[E0428]: the name `my_macro` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:25:1 + | +LL | pub fn my_macro(input: TokenStream) -> TokenStream { + | -------------------------------------------------- previous definition of the macro `my_macro` here +... +LL | macro my_macro() {} + | ^^^^^^^^^^^^^^^^ `my_macro` redefined here + | + = note: `my_macro` must be defined only once in the macro namespace of this module + +error[E0428]: the name `my_macro_attr` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:26:1 + | +LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream { + | ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here +... +LL | macro my_macro_attr() {} + | ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here + | + = note: `my_macro_attr` must be defined only once in the macro namespace of this module + +error[E0428]: the name `MyTrait` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:27:1 + | +LL | #[proc_macro_derive(MyTrait)] + | ------- previous definition of the macro `MyTrait` here +... +LL | macro MyTrait() {} + | ^^^^^^^^^^^^^^^ `MyTrait` redefined here + | + = note: `MyTrait` must be defined only once in the macro namespace of this module + +error[E0428]: the name `SameName` is defined multiple times + --> $DIR/macro-namespace-reserved.rs:35:1 + | +LL | #[proc_macro_derive(SameName)] + | -------- previous definition of the macro `SameName` here +... +LL | pub fn SameName(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here + | + = note: `SameName` must be defined only once in the macro namespace of this module + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/proc-macro/macro-quote-cond.rs b/tests/ui/proc-macro/macro-quote-cond.rs new file mode 100644 index 000000000..48307f4d9 --- /dev/null +++ b/tests/ui/proc-macro/macro-quote-cond.rs @@ -0,0 +1,46 @@ +// run-pass +// aux-build:cond_plugin.rs + +#![allow(unused_parens)] + +extern crate cond_plugin; + +use cond_plugin::cond; + +fn fact(n : i64) -> i64 { + if n == 0 { + 1 + } else { + n * fact(n - 1) + } +} + +fn fact_cond(n : i64) -> i64 { + cond!( + ((n == 0) 1) + (else (n * fact_cond(n-1))) + ) +} + +fn fib(n : i64) -> i64 { + if n == 0 || n == 1 { + 1 + } else { + fib(n-1) + fib(n-2) + } +} + +fn fib_cond(n : i64) -> i64 { + cond!( + ((n == 0) 1) + ((n == 1) 1) + (else (fib_cond(n-1) + fib_cond(n-2))) + ) +} + +fn main() { + assert_eq!(fact(3), fact_cond(3)); + assert_eq!(fact(5), fact_cond(5)); + assert_eq!(fib(5), fib_cond(5)); + assert_eq!(fib(8), fib_cond(8)); +} diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.rs b/tests/ui/proc-macro/macro-rules-derive-cfg.rs new file mode 100644 index 000000000..a221b9578 --- /dev/null +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.rs @@ -0,0 +1,31 @@ +// check-pass +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! produce_it { + ($expr:expr) => { + #[derive(Print)] + struct Foo { + val: [bool; { + let a = #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr; + 0 + }] + } + } +} + +produce_it!(#[cfg_attr(not(FALSE), rustc_dummy(second))] { + #![cfg_attr(not(FALSE), allow(unused))] + 30 +}); + +fn main() {} diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout new file mode 100644 index 000000000..74641058e --- /dev/null +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -0,0 +1,171 @@ +PRINT-DERIVE INPUT (DISPLAY): struct Foo +{ + val : + [bool ; + { + let a = #[rustc_dummy(first)] #[rustc_dummy(second)] + { #! [allow(unused)] 30 } ; 0 + }] +} +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/macro-rules-derive-cfg.rs:17:9: 17:15 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/macro-rules-derive-cfg.rs:17:16: 17:19 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "val", + span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:16 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:18:16: 18:17 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "bool", + span: $DIR/macro-rules-derive-cfg.rs:18:19: 18:23 (#4), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:18:23: 18:24 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "let", + span: $DIR/macro-rules-derive-cfg.rs:19:17: 19:20 (#4), + }, + Ident { + ident: "a", + span: $DIR/macro-rules-derive-cfg.rs:19:21: 19:22 (#4), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:19:23: 19:24 (#4), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:19:48: 19:59 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first", + span: $DIR/macro-rules-derive-cfg.rs:19:60: 19:65 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:19:59: 19:66 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4), + }, + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/macro-rules-derive-cfg.rs:26:36: 26:47 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second", + span: $DIR/macro-rules-derive-cfg.rs:26:48: 26:54 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:26:47: 26:55 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/macro-rules-derive-cfg.rs:27:29: 27:34 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused", + span: $DIR/macro-rules-derive-cfg.rs:27:35: 27:41 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:27:34: 27:42 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0), + }, + Literal { + kind: Integer, + symbol: "30", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:28:5: 28:7 (#0), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:26:58: 29:2 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/macro-rules-derive-cfg.rs:19:74: 19:75 (#4), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/macro-rules-derive-cfg.rs:20:17: 20:18 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:18:25: 21:14 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:18:18: 21:15 (#4), + }, + ], + span: $DIR/macro-rules-derive-cfg.rs:17:20: 22:10 (#4), + }, +] diff --git a/tests/ui/proc-macro/macro-rules-derive.rs b/tests/ui/proc-macro/macro-rules-derive.rs new file mode 100644 index 000000000..e0c40bbc7 --- /dev/null +++ b/tests/ui/proc-macro/macro-rules-derive.rs @@ -0,0 +1,19 @@ +// aux-build:first-second.rs + +extern crate first_second; +use first_second::*; + +macro_rules! produce_it { + ($name:ident) => { + #[first] + struct $name { + field: MissingType //~ ERROR cannot find type + } + } +} + +produce_it!(MyName); + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/proc-macro/macro-rules-derive.stderr b/tests/ui/proc-macro/macro-rules-derive.stderr new file mode 100644 index 000000000..517cbabd5 --- /dev/null +++ b/tests/ui/proc-macro/macro-rules-derive.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/macro-rules-derive.rs:10:20 + | +LL | field: MissingType + | ^^^^^^^^^^^ not found in this scope +... +LL | produce_it!(MyName); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `produce_it` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/proc-macro/macro-use-attr.rs b/tests/ui/proc-macro/macro-use-attr.rs new file mode 100644 index 000000000..b101c09ed --- /dev/null +++ b/tests/ui/proc-macro/macro-use-attr.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[identity_attr] +struct Foo; + +fn main() { + let _ = Foo; +} diff --git a/tests/ui/proc-macro/macro-use-bang.rs b/tests/ui/proc-macro/macro-use-bang.rs new file mode 100644 index 000000000..4a0bf0b2f --- /dev/null +++ b/tests/ui/proc-macro/macro-use-bang.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +fn main() { + identity!(println!("Hello, world!")); +} diff --git a/tests/ui/proc-macro/macros-in-extern-derive.rs b/tests/ui/proc-macro/macros-in-extern-derive.rs new file mode 100644 index 000000000..c8b26b005 --- /dev/null +++ b/tests/ui/proc-macro/macros-in-extern-derive.rs @@ -0,0 +1,6 @@ +extern "C" { + #[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s + fn f(); +} + +fn main() {} diff --git a/tests/ui/proc-macro/macros-in-extern-derive.stderr b/tests/ui/proc-macro/macros-in-extern-derive.stderr new file mode 100644 index 000000000..efd9ff225 --- /dev/null +++ b/tests/ui/proc-macro/macros-in-extern-derive.stderr @@ -0,0 +1,11 @@ +error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s + --> $DIR/macros-in-extern-derive.rs:2:5 + | +LL | #[derive(Copy)] + | ^^^^^^^^^^^^^^^ not applicable here +LL | fn f(); + | ------- not a `struct`, `enum` or `union` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0774`. diff --git a/tests/ui/proc-macro/macros-in-extern.rs b/tests/ui/proc-macro/macros-in-extern.rs new file mode 100644 index 000000000..57e2066d8 --- /dev/null +++ b/tests/ui/proc-macro/macros-in-extern.rs @@ -0,0 +1,24 @@ +// run-pass +// aux-build:test-macros.rs +// ignore-wasm32 + +#[macro_use] +extern crate test_macros; + +fn main() { + assert_eq!(unsafe { rust_get_test_int() }, 1); + assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF); +} + +#[link(name = "rust_test_helpers", kind = "static")] +extern "C" { + #[empty_attr] + fn some_definitely_unknown_symbol_which_should_be_removed(); + + #[identity_attr] + fn rust_get_test_int() -> isize; + + identity!( + fn rust_dbg_extern_identity_u32(arg: u32) -> u32; + ); +} diff --git a/tests/ui/proc-macro/macros-in-type.rs b/tests/ui/proc-macro/macros-in-type.rs new file mode 100644 index 000000000..19ed58ece --- /dev/null +++ b/tests/ui/proc-macro/macros-in-type.rs @@ -0,0 +1,11 @@ +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +const C: identity!(u8) = 10; + +fn main() { + let c: u8 = C; +} diff --git a/tests/ui/proc-macro/meta-delim.rs b/tests/ui/proc-macro/meta-delim.rs new file mode 100644 index 000000000..964291bc6 --- /dev/null +++ b/tests/ui/proc-macro/meta-delim.rs @@ -0,0 +1,12 @@ +// aux-build:meta-delim.rs +// edition:2018 +// run-pass + +// Tests that we can properly deserialize a macro with strange delimiters +// See https://github.com/rust-lang/rust/pull/73569#issuecomment-650860457 + +extern crate meta_delim; + +fn main() { + assert_eq!("a bunch of idents", meta_delim::meta_delim!(a bunch of idents)); +} diff --git a/tests/ui/proc-macro/meta-macro-hygiene.rs b/tests/ui/proc-macro/meta-macro-hygiene.rs new file mode 100644 index 000000000..70b8d8da1 --- /dev/null +++ b/tests/ui/proc-macro/meta-macro-hygiene.rs @@ -0,0 +1,30 @@ +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no +// check-pass +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// +// We don't care about symbol ids, so we set them all to 0 +// in the stdout + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate meta_macro; + +macro_rules! produce_it { + () => { + // `print_def_site!` will respan the `$crate` identifier + // with `Span::def_site()`. This should cause it to resolve + // relative to `meta_macro`, *not* `make_macro` (despite + // the fact that `print_def_site` is produced by a + // `macro_rules!` macro in `make_macro`). + meta_macro::print_def_site!($crate::dummy!()); + } +} + +fn main() { + produce_it!(); +} diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout new file mode 100644 index 000000000..6b7b0c819 --- /dev/null +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -0,0 +1,69 @@ +Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) +Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:44 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:44: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }] +Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }] +#![feature /* 0#0 */(prelude_import)] +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no +// check-pass +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// +// We don't care about symbol ids, so we set them all to 0 +// in the stdout + +#![no_std /* 0#0 */] +#[prelude_import /* 0#1 */] +use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; +#[macro_use /* 0#1 */] +extern crate core /* 0#1 */; +#[macro_use /* 0#1 */] +extern crate compiler_builtins /* 0#1 */; +// Don't load unnecessary hygiene information from std +extern crate std /* 0#0 */; + +extern crate meta_macro /* 0#0 */; + +macro_rules! produce_it + /* + 0#0 + */ { + () => + { + meta_macro :: print_def_site! ($crate :: dummy! ()) ; + // `print_def_site!` will respan the `$crate` identifier + // with `Span::def_site()`. This should cause it to resolve + // relative to `meta_macro`, *not* `make_macro` (despite + // the fact that `print_def_site` is produced by a + // `macro_rules!` macro in `make_macro`). + } +} + +fn main /* 0#0 */() { ; } + +/* +Expansions: +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it") +crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") +crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) + +SyntaxContexts: +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) +#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#6: parent: #4, outer_mark: (crate0::{{expn3}}, Transparent) +#7: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent) +#8: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) +#9: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent) +#10: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +*/ diff --git a/tests/ui/proc-macro/meta-macro.rs b/tests/ui/proc-macro/meta-macro.rs new file mode 100644 index 000000000..dbac90382 --- /dev/null +++ b/tests/ui/proc-macro/meta-macro.rs @@ -0,0 +1,14 @@ +// aux-build:make-macro.rs +// aux-build:meta-macro.rs +// edition:2018 +// compile-flags: -Z span-debug +// run-pass + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate meta_macro; + +fn main() { + meta_macro::print_def_site!(); +} diff --git a/tests/ui/proc-macro/meta-macro.stdout b/tests/ui/proc-macro/meta-macro.stdout new file mode 100644 index 000000000..662682d40 --- /dev/null +++ b/tests/ui/proc-macro/meta-macro.stdout @@ -0,0 +1,3 @@ +Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) +Input: TokenStream [] +Respanned: TokenStream [] diff --git a/tests/ui/proc-macro/mixed-site-span.rs b/tests/ui/proc-macro/mixed-site-span.rs new file mode 100644 index 000000000..008384656 --- /dev/null +++ b/tests/ui/proc-macro/mixed-site-span.rs @@ -0,0 +1,24 @@ +// Proc macros using `mixed_site` spans exhibit usual properties of `macro_rules` hygiene. + +// aux-build:mixed-site-span.rs + +#[macro_use] +extern crate mixed_site_span; + +struct ItemUse; + +fn main() { + 'label_use: loop { + let local_use = 1; + proc_macro_rules!(); + //~^ ERROR use of undeclared label `'label_use` + //~| ERROR cannot find value `local_use` in this scope + ItemDef; // OK + local_def; //~ ERROR cannot find value `local_def` in this scope + } +} + +macro_rules! pass_dollar_crate { + () => (proc_macro_rules!($crate);) //~ ERROR cannot find type `ItemUse` in crate `$crate` +} +pass_dollar_crate!(); diff --git a/tests/ui/proc-macro/mixed-site-span.stderr b/tests/ui/proc-macro/mixed-site-span.stderr new file mode 100644 index 000000000..137860801 --- /dev/null +++ b/tests/ui/proc-macro/mixed-site-span.stderr @@ -0,0 +1,34 @@ +error[E0426]: use of undeclared label `'label_use` + --> $DIR/mixed-site-span.rs:13:9 + | +LL | proc_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` + | + = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_use` in this scope + --> $DIR/mixed-site-span.rs:13:9 + | +LL | proc_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def` + | + = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `local_def` in this scope + --> $DIR/mixed-site-span.rs:17:9 + | +LL | local_def; + | ^^^^^^^^^ help: a local variable with a similar name exists: `local_use` + +error[E0412]: cannot find type `ItemUse` in crate `$crate` + --> $DIR/mixed-site-span.rs:24:1 + | +LL | pass_dollar_crate!(); + | ^^^^^^^^^^^^^^^^^^^^ not found in `$crate` + | + = note: this error originates in the macro `proc_macro_rules` which comes from the expansion of the macro `pass_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0412, E0425, E0426. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/proc-macro/modify-ast.rs b/tests/ui/proc-macro/modify-ast.rs new file mode 100644 index 000000000..ea9bf837c --- /dev/null +++ b/tests/ui/proc-macro/modify-ast.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:modify-ast.rs + +extern crate modify_ast; + +use modify_ast::*; + +#[derive(Foo)] +pub struct MyStructc { + #[cfg_attr(my_cfg, foo)] + _a: i32, +} + +macro_rules! a { + ($i:item) => ($i) +} + +a! { + #[assert1] + pub fn foo() {} +} + +fn main() { + let _a = MyStructc { _a: 0 }; + foo(); +} diff --git a/tests/ui/proc-macro/module.rs b/tests/ui/proc-macro/module.rs new file mode 100644 index 000000000..5777ed899 --- /dev/null +++ b/tests/ui/proc-macro/module.rs @@ -0,0 +1 @@ +// ignore-test diff --git a/tests/ui/proc-macro/module_with_attrs.rs b/tests/ui/proc-macro/module_with_attrs.rs new file mode 100644 index 000000000..63e66a62a --- /dev/null +++ b/tests/ui/proc-macro/module_with_attrs.rs @@ -0,0 +1,4 @@ +// ignore-test + +#![rustfmt::skip] +#![print_attr] diff --git a/tests/ui/proc-macro/multispan.rs b/tests/ui/proc-macro/multispan.rs new file mode 100644 index 000000000..e9e0349f2 --- /dev/null +++ b/tests/ui/proc-macro/multispan.rs @@ -0,0 +1,25 @@ +// aux-build:multispan.rs + +extern crate multispan; + +use multispan::hello; + +fn main() { + // This one emits no error. + hello!(); + + // Exactly one 'hi'. + hello!(hi); //~ ERROR hello to you, too! + + // Now two, back to back. + hello!(hi hi); //~ ERROR hello to you, too! + + // Now three, back to back. + hello!(hi hi hi); //~ ERROR hello to you, too! + + // Now several, with spacing. + hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too! + hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too! + hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too! + hello!(hi good hi and good bye); //~ ERROR hello to you, too! +} diff --git a/tests/ui/proc-macro/multispan.stderr b/tests/ui/proc-macro/multispan.stderr new file mode 100644 index 000000000..0aea02bbd --- /dev/null +++ b/tests/ui/proc-macro/multispan.stderr @@ -0,0 +1,93 @@ +error: hello to you, too! + --> $DIR/multispan.rs:12:5 + | +LL | hello!(hi); + | ^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:12:12 + | +LL | hello!(hi); + | ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:15:5 + | +LL | hello!(hi hi); + | ^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:15:12 + | +LL | hello!(hi hi); + | ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:18:5 + | +LL | hello!(hi hi hi); + | ^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:18:12 + | +LL | hello!(hi hi hi); + | ^^ ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:21:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:21:12 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^ ^^ ^^ ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:22:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:22:12 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^ ^^ ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:23:5 + | +LL | hello!(whoah. hi di hi di ho); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:23:19 + | +LL | hello!(whoah. hi di hi di ho); + | ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: hello to you, too! + --> $DIR/multispan.rs:24:5 + | +LL | hello!(hi good hi and good bye); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: found these 'hi's + --> $DIR/multispan.rs:24:12 + | +LL | hello!(hi good hi and good bye); + | ^^ ^^ + = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 7 previous errors + diff --git a/tests/ui/proc-macro/negative-token.rs b/tests/ui/proc-macro/negative-token.rs new file mode 100644 index 000000000..2ed3cbc08 --- /dev/null +++ b/tests/ui/proc-macro/negative-token.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:negative-token.rs + +extern crate negative_token; + +use negative_token::*; + +fn main() { + assert_eq!(-1, neg_one!()); + assert_eq!(-1.0, neg_one_float!()); +} diff --git a/tests/ui/proc-macro/nested-derive-cfg.rs b/tests/ui/proc-macro/nested-derive-cfg.rs new file mode 100644 index 000000000..53cfbb7c9 --- /dev/null +++ b/tests/ui/proc-macro/nested-derive-cfg.rs @@ -0,0 +1,23 @@ +// compile-flags: -Z span-debug --error-format human +// aux-build:test-macros.rs +// check-pass + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +#[derive(Print)] +struct Foo { + #[cfg(FALSE)] removed: bool, + my_array: [bool; { + struct Inner { + #[cfg(FALSE)] removed_inner_field: u8, + non_removed_inner_field: usize + } + 0 + }] +} + +fn main() {} diff --git a/tests/ui/proc-macro/nested-derive-cfg.stdout b/tests/ui/proc-macro/nested-derive-cfg.stdout new file mode 100644 index 000000000..9a562c971 --- /dev/null +++ b/tests/ui/proc-macro/nested-derive-cfg.stdout @@ -0,0 +1,81 @@ +PRINT-DERIVE INPUT (DISPLAY): struct Foo +{ my_array : [bool ; { struct Inner { non_removed_inner_field : usize } 0 }] } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/nested-derive-cfg.rs:12:1: 12:7 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/nested-derive-cfg.rs:12:8: 12:11 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "my_array", + span: $DIR/nested-derive-cfg.rs:14:5: 14:13 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nested-derive-cfg.rs:14:13: 14:14 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "bool", + span: $DIR/nested-derive-cfg.rs:14:16: 14:20 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/nested-derive-cfg.rs:14:20: 14:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "struct", + span: $DIR/nested-derive-cfg.rs:15:9: 15:15 (#0), + }, + Ident { + ident: "Inner", + span: $DIR/nested-derive-cfg.rs:15:16: 15:21 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "non_removed_inner_field", + span: $DIR/nested-derive-cfg.rs:17:13: 17:36 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nested-derive-cfg.rs:17:36: 17:37 (#0), + }, + Ident { + ident: "usize", + span: $DIR/nested-derive-cfg.rs:17:38: 17:43 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:15:22: 18:10 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/nested-derive-cfg.rs:19:9: 19:10 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:14:22: 20:6 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:14:15: 20:7 (#0), + }, + ], + span: $DIR/nested-derive-cfg.rs:12:12: 21:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/nested-item-spans.rs b/tests/ui/proc-macro/nested-item-spans.rs new file mode 100644 index 000000000..63da170d0 --- /dev/null +++ b/tests/ui/proc-macro/nested-item-spans.rs @@ -0,0 +1,23 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[recollect_attr] +fn another() { + fn bar() { + let x: u32 = "x"; //~ ERROR: mismatched types + } + + bar(); +} + +fn main() { + #[recollect_attr] + fn bar() { + let x: u32 = "x"; //~ ERROR: mismatched types + } + + bar(); + another(); +} diff --git a/tests/ui/proc-macro/nested-item-spans.stderr b/tests/ui/proc-macro/nested-item-spans.stderr new file mode 100644 index 000000000..44b338fa6 --- /dev/null +++ b/tests/ui/proc-macro/nested-item-spans.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/nested-item-spans.rs:9:22 + | +LL | let x: u32 = "x"; + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/nested-item-spans.rs:18:22 + | +LL | let x: u32 = "x"; + | --- ^^^ expected `u32`, found `&str` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/nested-macro-rules.rs b/tests/ui/proc-macro/nested-macro-rules.rs new file mode 100644 index 000000000..25ffcfad7 --- /dev/null +++ b/tests/ui/proc-macro/nested-macro-rules.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:nested-macro-rules.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug -Z macro-backtrace +// edition:2018 + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate nested_macro_rules; +extern crate test_macros; + +use test_macros::{print_bang, print_attr}; + +use nested_macro_rules::FirstStruct; +struct SecondStruct; + +fn main() { + nested_macro_rules::inner_macro!(print_bang, print_attr); + + nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); + inner_macro!(print_bang, print_attr); +} diff --git a/tests/ui/proc-macro/nested-macro-rules.stdout b/tests/ui/proc-macro/nested-macro-rules.stdout new file mode 100644 index 000000000..311139040 --- /dev/null +++ b/tests/ui/proc-macro/nested-macro-rules.stdout @@ -0,0 +1,46 @@ +PRINT-BANG INPUT (DISPLAY): FirstStruct +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "FirstStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:16:14: 16:25 (#7), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#6), + }, + Ident { + ident: "FirstAttrStruct", + span: $DIR/auxiliary/nested-macro-rules.rs:16:27: 16:42 (#7), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#6), + }, +] +PRINT-BANG INPUT (DISPLAY): SecondStruct +PRINT-BANG INPUT (DEBUG): TokenStream [ + Ident { + ident: "SecondStruct", + span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15), + }, + Ident { + ident: "SecondAttrStruct", + span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#15), + }, +] diff --git a/tests/ui/proc-macro/nested-nonterminal-tokens.rs b/tests/ui/proc-macro/nested-nonterminal-tokens.rs new file mode 100644 index 000000000..04d34e21c --- /dev/null +++ b/tests/ui/proc-macro/nested-nonterminal-tokens.rs @@ -0,0 +1,26 @@ +// check-pass +// edition:2018 +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +// Tests that we properly pass tokens to proc-macro when nested +// nonterminals are involved. + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + + +macro_rules! wrap { + (first, $e:expr) => { wrap!(second, $e + 1) }; + (second, $e:expr) => { wrap!(third, $e + 2) }; + (third, $e:expr) => { + print_bang!($e + 3) + }; +} + +fn main() { + let _ = wrap!(first, 0); +} diff --git a/tests/ui/proc-macro/nested-nonterminal-tokens.stdout b/tests/ui/proc-macro/nested-nonterminal-tokens.stdout new file mode 100644 index 000000000..a3d24dd26 --- /dev/null +++ b/tests/ui/proc-macro/nested-nonterminal-tokens.stdout @@ -0,0 +1,60 @@ +PRINT-BANG INPUT (DISPLAY): 0 + 1 + 2 + 3 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:25:26: 25:27 (#0), + }, + ], + span: $DIR/nested-nonterminal-tokens.rs:17:41: 17:43 (#4), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nested-nonterminal-tokens.rs:17:44: 17:45 (#4), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:17:46: 17:47 (#4), + }, + ], + span: $DIR/nested-nonterminal-tokens.rs:18:41: 18:43 (#5), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nested-nonterminal-tokens.rs:18:44: 18:45 (#5), + }, + Literal { + kind: Integer, + symbol: "2", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:18:46: 18:47 (#5), + }, + ], + span: $DIR/nested-nonterminal-tokens.rs:20:21: 20:23 (#6), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nested-nonterminal-tokens.rs:20:24: 20:25 (#6), + }, + Literal { + kind: Integer, + symbol: "3", + suffix: None, + span: $DIR/nested-nonterminal-tokens.rs:20:26: 20:27 (#6), + }, +] diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs new file mode 100644 index 000000000..a8a8fa4e1 --- /dev/null +++ b/tests/ui/proc-macro/no-macro-use-attr.rs @@ -0,0 +1,10 @@ +// aux-build:test-macros.rs + +#![feature(rustc_attrs)] +#![warn(unused_extern_crates)] + +extern crate test_macros; +//~^ WARN unused extern crate + +#[rustc_error] +fn main() {} //~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/proc-macro/no-macro-use-attr.stderr b/tests/ui/proc-macro/no-macro-use-attr.stderr new file mode 100644 index 000000000..a9e5256a0 --- /dev/null +++ b/tests/ui/proc-macro/no-macro-use-attr.stderr @@ -0,0 +1,20 @@ +warning: unused extern crate + --> $DIR/no-macro-use-attr.rs:6:1 + | +LL | extern crate test_macros; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/no-macro-use-attr.rs:4:9 + | +LL | #![warn(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: fatal error triggered by #[rustc_error] + --> $DIR/no-macro-use-attr.rs:10:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/proc-macro/no-missing-docs.rs b/tests/ui/proc-macro/no-missing-docs.rs new file mode 100644 index 000000000..e1e821858 --- /dev/null +++ b/tests/ui/proc-macro/no-missing-docs.rs @@ -0,0 +1,16 @@ +//! Verify that the `decls` module implicitly added by the compiler does not cause `missing_docs` +//! warnings. + +// build-pass (FIXME(62277): could be check-pass?) +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(missing_docs)] + +extern crate proc_macro; +use proc_macro::*; + +/// Foo1. +#[proc_macro] +pub fn foo1(input: TokenStream) -> TokenStream { input } diff --git a/tests/ui/proc-macro/nodelim-groups.rs b/tests/ui/proc-macro/nodelim-groups.rs new file mode 100644 index 000000000..ec3019902 --- /dev/null +++ b/tests/ui/proc-macro/nodelim-groups.rs @@ -0,0 +1,22 @@ +// run-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// edition:2018 +// +// Tests the pretty-printing behavior of inserting `Invisible`-delimited groups + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; +use test_macros::print_bang_consume; + +macro_rules! expand_it { + (($val1:expr) ($val2:expr)) => { expand_it!($val1 + $val2) }; + ($val:expr) => { print_bang_consume!("hi" $val (1 + 1)) }; +} + +fn main() { + expand_it!(1 + (25) + 1); + expand_it!(("hello".len()) ("world".len())); +} diff --git a/tests/ui/proc-macro/nodelim-groups.stdout b/tests/ui/proc-macro/nodelim-groups.stdout new file mode 100644 index 000000000..6b410f0bf --- /dev/null +++ b/tests/ui/proc-macro/nodelim-groups.stdout @@ -0,0 +1,167 @@ +PRINT-BANG INPUT (DISPLAY): "hi" 1 + (25) + 1 (1 + 1) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Literal { + kind: Str, + symbol: "hi", + suffix: None, + span: $DIR/nodelim-groups.rs:16:42: 16:46 (#4), + }, + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:20:16: 20:17 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:20:18: 20:19 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "25", + suffix: None, + span: $DIR/nodelim-groups.rs:20:21: 20:23 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:20:20: 20:24 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:20:25: 20:26 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:20:27: 20:28 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:16:47: 16:51 (#4), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:53: 16:54 (#4), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:16:55: 16:56 (#4), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:57: 16:58 (#4), + }, + ], + span: $DIR/nodelim-groups.rs:16:52: 16:59 (#4), + }, +] +PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1) +PRINT-BANG INPUT (DEBUG): TokenStream [ + Literal { + kind: Str, + symbol: "hi", + suffix: None, + span: $DIR/nodelim-groups.rs:16:42: 16:46 (#9), + }, + Group { + delimiter: None, + stream: TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "hello", + suffix: None, + span: $DIR/nodelim-groups.rs:21:17: 21:24 (#0), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/nodelim-groups.rs:21:24: 21:25 (#0), + }, + Ident { + ident: "len", + span: $DIR/nodelim-groups.rs:21:25: 21:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nodelim-groups.rs:21:28: 21:30 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:15:49: 15:54 (#8), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:15:55: 15:56 (#8), + }, + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "world", + suffix: None, + span: $DIR/nodelim-groups.rs:21:33: 21:40 (#0), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/nodelim-groups.rs:21:40: 21:41 (#0), + }, + Ident { + ident: "len", + span: $DIR/nodelim-groups.rs:21:41: 21:44 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nodelim-groups.rs:21:44: 21:46 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:15:57: 15:62 (#8), + }, + ], + span: $DIR/nodelim-groups.rs:16:47: 16:51 (#9), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:53: 16:54 (#9), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/nodelim-groups.rs:16:55: 16:56 (#9), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/nodelim-groups.rs:16:57: 16:58 (#9), + }, + ], + span: $DIR/nodelim-groups.rs:16:52: 16:59 (#9), + }, +] diff --git a/tests/ui/proc-macro/non-root.rs b/tests/ui/proc-macro/non-root.rs new file mode 100644 index 000000000..a7c4ac00a --- /dev/null +++ b/tests/ui/proc-macro/non-root.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +fn foo(arg: TokenStream) -> TokenStream { + #[proc_macro] + pub fn foo(arg: TokenStream) -> TokenStream { arg } + //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root of the crate + + arg +} diff --git a/tests/ui/proc-macro/non-root.stderr b/tests/ui/proc-macro/non-root.stderr new file mode 100644 index 000000000..90f94b677 --- /dev/null +++ b/tests/ui/proc-macro/non-root.stderr @@ -0,0 +1,8 @@ +error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate + --> $DIR/non-root.rs:11:5 + | +LL | pub fn foo(arg: TokenStream) -> TokenStream { arg } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/nonterminal-expansion.rs b/tests/ui/proc-macro/nonterminal-expansion.rs new file mode 100644 index 000000000..e62155871 --- /dev/null +++ b/tests/ui/proc-macro/nonterminal-expansion.rs @@ -0,0 +1,37 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:test-macros.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! pass_nonterminal { + ($line:expr) => { + #[print_attr_args(a, $line, b)] + struct S; + }; +} + +// `line!()` is not expanded before it's passed to the proc macro. +pass_nonterminal!(line!()); + +// Test case from #43860. + +#[macro_export] +macro_rules! use_contract { + ($name: ident, $path: expr) => { + #[derive(Empty)] + #[empty_helper(path = $path)] // OK + pub struct $name { + api: T, + contract: C, + } + }; +} + +use_contract!(ContractName, file!()); + +fn main() {} diff --git a/tests/ui/proc-macro/nonterminal-expansion.stdout b/tests/ui/proc-macro/nonterminal-expansion.stdout new file mode 100644 index 000000000..4d884348f --- /dev/null +++ b/tests/ui/proc-macro/nonterminal-expansion.stdout @@ -0,0 +1,42 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): a, line!(), b +PRINT-ATTR_ARGS RE-COLLECTED (DISPLAY): a, line! (), b +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "a", + span: $DIR/nonterminal-expansion.rs:13:27: 13:28 (#4), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/nonterminal-expansion.rs:13:28: 13:29 (#4), + }, + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "line", + span: $DIR/nonterminal-expansion.rs:19:19: 19:23 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/nonterminal-expansion.rs:19:23: 19:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/nonterminal-expansion.rs:19:24: 19:26 (#0), + }, + ], + span: $DIR/nonterminal-expansion.rs:13:30: 13:35 (#4), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/nonterminal-expansion.rs:13:35: 13:36 (#4), + }, + Ident { + ident: "b", + span: $DIR/nonterminal-expansion.rs:13:37: 13:38 (#4), + }, +] diff --git a/tests/ui/proc-macro/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/nonterminal-recollect-attr.rs new file mode 100644 index 000000000..79c4ad4cd --- /dev/null +++ b/tests/ui/proc-macro/nonterminal-recollect-attr.rs @@ -0,0 +1,21 @@ +// check-pass +// compile-flags: -Z span-debug +// aux-build:nonterminal-recollect-attr.rs + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate nonterminal_recollect_attr; +use nonterminal_recollect_attr::*; + +macro_rules! my_macro { + ($v:ident) => { + #[first_attr] + $v struct Foo { + field: u8 + } + } +} + +my_macro!(pub); +fn main() {} diff --git a/tests/ui/proc-macro/nonterminal-recollect-attr.stdout b/tests/ui/proc-macro/nonterminal-recollect-attr.stdout new file mode 100644 index 000000000..6824395ae --- /dev/null +++ b/tests/ui/proc-macro/nonterminal-recollect-attr.stdout @@ -0,0 +1,66 @@ +First recollected: TokenStream [ + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4), + }, + Ident { + ident: "u8", + span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4), + }, +] +Second recollected: TokenStream [ + Ident { + ident: "pub", + span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0), + }, + Ident { + ident: "struct", + span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4), + }, + Ident { + ident: "Foo", + span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "field", + span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4), + }, + Ident { + ident: "u8", + span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4), + }, + ], + span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4), + }, +] diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.rs b/tests/ui/proc-macro/nonterminal-token-hygiene.rs new file mode 100644 index 000000000..fa52a975b --- /dev/null +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.rs @@ -0,0 +1,34 @@ +// Make sure that marks from declarative macros are applied to tokens in nonterminal. + +// check-pass +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene +// compile-flags: -Z trim-diagnostic-paths=no +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// aux-build:test-macros.rs + +#![feature(decl_macro)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! outer { + ($item:item) => { + macro inner() { + print_bang! { $item } + } + + inner!(); + }; +} + +struct S; + +outer! { + struct S; // OK, not a duplicate definition of `S` +} + +fn main() {} diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout new file mode 100644 index 000000000..c08e53081 --- /dev/null +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -0,0 +1,92 @@ +PRINT-BANG INPUT (DISPLAY): struct S; +PRINT-BANG RE-COLLECTED (DISPLAY): struct S ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Ident { + ident: "struct", + span: $DIR/nonterminal-token-hygiene.rs:31:5: 31:11 (#5), + }, + Ident { + ident: "S", + span: $DIR/nonterminal-token-hygiene.rs:31:12: 31:13 (#5), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/nonterminal-token-hygiene.rs:31:13: 31:14 (#5), + }, + ], + span: $DIR/nonterminal-token-hygiene.rs:21:27: 21:32 (#6), + }, +] +#![feature /* 0#0 */(prelude_import)] +#![no_std /* 0#0 */] +// Make sure that marks from declarative macros are applied to tokens in nonterminal. + +// check-pass +// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene +// compile-flags: -Z trim-diagnostic-paths=no +// normalize-stdout-test "\d+#" -> "0#" +// normalize-stdout-test "expn\d{3,}" -> "expnNNN" +// aux-build:test-macros.rs + +#![feature /* 0#0 */(decl_macro)] + +#![no_std /* 0#0 */] +#[prelude_import /* 0#1 */] +use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; +#[macro_use /* 0#1 */] +extern crate core /* 0#2 */; +#[macro_use /* 0#1 */] +extern crate compiler_builtins /* 0#2 */; +// Don't load unnecessary hygiene information from std +extern crate std /* 0#0 */; + +#[macro_use /* 0#0 */] +extern crate test_macros /* 0#0 */; + +macro_rules! outer + /* + 0#0 + */ { + ($item : item) => + { + macro inner() { print_bang! { $item } } inner! () ; + + } ; +} + +struct S /* 0#0 */; +macro inner /* 0#4 */ { () => { print_bang! { struct S; } } } + +struct S /* 0#5 */; +// OK, not a duplicate definition of `S` + +fn main /* 0#0 */() {} + +/* +Expansions: +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) +crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer") +crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner") +crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive") +crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include") +crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports) + +SyntaxContexts: +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) +#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque) +#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) +#6: parent: #4, outer_mark: (crate0::{{expn3}}, Opaque) +#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) +#8: parent: #6, outer_mark: (crate0::{{expn4}}, Transparent) +#9: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +*/ diff --git a/tests/ui/proc-macro/not-joint.rs b/tests/ui/proc-macro/not-joint.rs new file mode 100644 index 000000000..30da2811e --- /dev/null +++ b/tests/ui/proc-macro/not-joint.rs @@ -0,0 +1,24 @@ +// run-pass +// aux-build:not-joint.rs + +extern crate not_joint as bar; +use bar::{tokens, nothing}; + +tokens![< -]; + +#[nothing] +a![< -]; + +#[nothing] +b!{< -} + +#[nothing] +c!(< -); + +#[nothing] +fn foo() { + //! dox + let x = 2 < - 3; +} + +fn main() {} diff --git a/tests/ui/proc-macro/out-of-line-mod.rs b/tests/ui/proc-macro/out-of-line-mod.rs new file mode 100644 index 000000000..658ed6c18 --- /dev/null +++ b/tests/ui/proc-macro/out-of-line-mod.rs @@ -0,0 +1,13 @@ +// Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818). + +// check-pass +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod outer { + identity! { mod inner; } +} + +fn main() {} diff --git a/tests/ui/proc-macro/outer/inner.rs b/tests/ui/proc-macro/outer/inner.rs new file mode 100644 index 000000000..5777ed899 --- /dev/null +++ b/tests/ui/proc-macro/outer/inner.rs @@ -0,0 +1 @@ +// ignore-test diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs new file mode 100644 index 000000000..ad312a875 --- /dev/null +++ b/tests/ui/proc-macro/panic-abort.rs @@ -0,0 +1,4 @@ +// error-pattern: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic +// compile-flags: --crate-type proc-macro -Cpanic=abort +// force-host +// check-pass diff --git a/tests/ui/proc-macro/panic-abort.stderr b/tests/ui/proc-macro/panic-abort.stderr new file mode 100644 index 000000000..a6e18614f --- /dev/null +++ b/tests/ui/proc-macro/panic-abort.stderr @@ -0,0 +1,4 @@ +warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic + +warning: 1 warning emitted + diff --git a/tests/ui/proc-macro/parent-source-spans.rs b/tests/ui/proc-macro/parent-source-spans.rs new file mode 100644 index 000000000..354657db4 --- /dev/null +++ b/tests/ui/proc-macro/parent-source-spans.rs @@ -0,0 +1,53 @@ +// aux-build:parent-source-spans.rs + +#![feature(decl_macro)] + +extern crate parent_source_spans; + +use parent_source_spans::parent_source_spans; + +macro one($a:expr, $b:expr) { + two!($a, $b); + //~^ ERROR first parent: "hello" + //~| ERROR second parent: "world" +} + +macro two($a:expr, $b:expr) { + three!($a, $b); + //~^ ERROR first final: "hello" + //~| ERROR second final: "world" + //~| ERROR first final: "yay" + //~| ERROR second final: "rust" +} + +// forwarding tokens directly doesn't create a new source chain +macro three($($tokens:tt)*) { + four!($($tokens)*); +} + +macro four($($tokens:tt)*) { + parent_source_spans!($($tokens)*); + //~^ ERROR cannot find value `ok` in this scope + //~| ERROR cannot find value `ok` in this scope + //~| ERROR cannot find value `ok` in this scope +} + +fn main() { + one!("hello", "world"); + //~^ ERROR first grandparent: "hello" + //~| ERROR second grandparent: "world" + //~| ERROR first source: "hello" + //~| ERROR second source: "world" + + two!("yay", "rust"); + //~^ ERROR first parent: "yay" + //~| ERROR second parent: "rust" + //~| ERROR first source: "yay" + //~| ERROR second source: "rust" + + three!("hip", "hop"); + //~^ ERROR first final: "hip" + //~| ERROR second final: "hop" + //~| ERROR first source: "hip" + //~| ERROR second source: "hop" +} diff --git a/tests/ui/proc-macro/parent-source-spans.stderr b/tests/ui/proc-macro/parent-source-spans.stderr new file mode 100644 index 000000000..a3b27fd7b --- /dev/null +++ b/tests/ui/proc-macro/parent-source-spans.stderr @@ -0,0 +1,183 @@ +error: first final: "hello" + --> $DIR/parent-source-spans.rs:16:12 + | +LL | three!($a, $b); + | ^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: second final: "world" + --> $DIR/parent-source-spans.rs:16:16 + | +LL | three!($a, $b); + | ^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: first parent: "hello" + --> $DIR/parent-source-spans.rs:10:5 + | +LL | two!($a, $b); + | ^^^^^^^^^^^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: second parent: "world" + --> $DIR/parent-source-spans.rs:10:5 + | +LL | two!($a, $b); + | ^^^^^^^^^^^^ +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: first grandparent: "hello" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: second grandparent: "world" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: first source: "hello" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: second source: "world" + --> $DIR/parent-source-spans.rs:36:5 + | +LL | one!("hello", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: first final: "yay" + --> $DIR/parent-source-spans.rs:16:12 + | +LL | three!($a, $b); + | ^^ +... +LL | two!("yay", "rust"); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: second final: "rust" + --> $DIR/parent-source-spans.rs:16:16 + | +LL | three!($a, $b); + | ^^ +... +LL | two!("yay", "rust"); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: first parent: "yay" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: second parent: "rust" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: first source: "yay" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: second source: "rust" + --> $DIR/parent-source-spans.rs:42:5 + | +LL | two!("yay", "rust"); + | ^^^^^^^^^^^^^^^^^^^ + +error: first final: "hip" + --> $DIR/parent-source-spans.rs:48:12 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error: second final: "hop" + --> $DIR/parent-source-spans.rs:48:19 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error: first source: "hip" + --> $DIR/parent-source-spans.rs:48:12 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error: second source: "hop" + --> $DIR/parent-source-spans.rs:48:19 + | +LL | three!("hip", "hop"); + | ^^^^^ + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:29:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` +... +LL | one!("hello", "world"); + | ---------------------- in this macro invocation + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: similarly named tuple variant `Ok` defined here + | + = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:29:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` +... +LL | two!("yay", "rust"); + | ------------------- in this macro invocation + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: similarly named tuple variant `Ok` defined here + | + = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:29:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok` +... +LL | three!("hip", "hop"); + | -------------------- in this macro invocation + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: similarly named tuple variant `Ok` defined here + | + = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/proc-macro/pretty-print-hack-hide.rs b/tests/ui/proc-macro/pretty-print-hack-hide.rs new file mode 100644 index 000000000..f53e8fe82 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-hide.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// check-pass + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] extern crate test_macros; + +include!("pretty-print-hack/rental-0.5.6/src/lib.rs"); + +fn main() {} diff --git a/tests/ui/proc-macro/pretty-print-hack-hide.stdout b/tests/ui/proc-macro/pretty-print-hack-hide.stdout new file mode 100644 index 000000000..ea796bb26 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-hide.stdout @@ -0,0 +1,21 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr new file mode 100644 index 000000000..873054927 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr @@ -0,0 +1,179 @@ +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: aborting due to 8 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stdout b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout new file mode 100644 index 000000000..3d793d2a0 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout @@ -0,0 +1,44 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr new file mode 100644 index 000000000..873054927 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr @@ -0,0 +1,179 @@ +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: aborting due to 8 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout new file mode 100644 index 000000000..3d793d2a0 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout @@ -0,0 +1,44 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs new file mode 100644 index 000000000..24a389c45 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.rs @@ -0,0 +1,20 @@ +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// revisions: local remapped +// [local] no-remap-src-base: The hack should work regardless of remapping. +// [remapped] remap-src-base + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] extern crate test_macros; + +mod first { + include!("pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs"); +} + +mod second { + include!("pretty-print-hack/rental-0.5.5/src/lib.rs"); +} + +fn main() {} diff --git a/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs new file mode 100644 index 000000000..9501980fa --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs @@ -0,0 +1,14 @@ +// ignore-test + +#[derive(Print)] +enum ProceduralMasqueradeDummyType { +//~^ ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously + Input +} diff --git a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs new file mode 100644 index 000000000..9501980fa --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs @@ -0,0 +1,14 @@ +// ignore-test + +#[derive(Print)] +enum ProceduralMasqueradeDummyType { +//~^ ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously + Input +} diff --git a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs new file mode 100644 index 000000000..9501980fa --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs @@ -0,0 +1,14 @@ +// ignore-test + +#[derive(Print)] +enum ProceduralMasqueradeDummyType { +//~^ ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously +//~| ERROR using +//~| WARN this was previously + Input +} diff --git a/tests/ui/proc-macro/pretty-print-tts.rs b/tests/ui/proc-macro/pretty-print-tts.rs new file mode 100644 index 000000000..ffe2a7415 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-tts.rs @@ -0,0 +1,20 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +// Tests the pretty-printing behavior of various (unparsed) tokens +print_bang_consume!({ + #![rustc_dummy] + let a = "hello".len(); + matches!(a, 5); +}); + +fn main() {} diff --git a/tests/ui/proc-macro/pretty-print-tts.stdout b/tests/ui/proc-macro/pretty-print-tts.stdout new file mode 100644 index 000000000..f52e97a86 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-tts.stdout @@ -0,0 +1,102 @@ +PRINT-BANG INPUT (DISPLAY): { #! [rustc_dummy] let a = "hello".len() ; matches! (a, 5) ; } +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/pretty-print-tts.rs:15:5: 15:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:15:6: 15:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/pretty-print-tts.rs:15:8: 15:19 (#0), + }, + ], + span: $DIR/pretty-print-tts.rs:15:7: 15:20 (#0), + }, + Ident { + ident: "let", + span: $DIR/pretty-print-tts.rs:16:5: 16:8 (#0), + }, + Ident { + ident: "a", + span: $DIR/pretty-print-tts.rs:16:9: 16:10 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:16:11: 16:12 (#0), + }, + Literal { + kind: Str, + symbol: "hello", + suffix: None, + span: $DIR/pretty-print-tts.rs:16:13: 16:20 (#0), + }, + Punct { + ch: '.', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:16:20: 16:21 (#0), + }, + Ident { + ident: "len", + span: $DIR/pretty-print-tts.rs:16:21: 16:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/pretty-print-tts.rs:16:24: 16:26 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:16:26: 16:27 (#0), + }, + Ident { + ident: "matches", + span: $DIR/pretty-print-tts.rs:17:5: 17:12 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:17:12: 17:13 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "a", + span: $DIR/pretty-print-tts.rs:17:14: 17:15 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:17:15: 17:16 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, + span: $DIR/pretty-print-tts.rs:17:17: 17:18 (#0), + }, + ], + span: $DIR/pretty-print-tts.rs:17:13: 17:19 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/pretty-print-tts.rs:17:19: 17:20 (#0), + }, + ], + span: $DIR/pretty-print-tts.rs:14:21: 18:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/proc-macro-attributes.rs b/tests/ui/proc-macro/proc-macro-attributes.rs new file mode 100644 index 000000000..8d96381b9 --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-attributes.rs @@ -0,0 +1,22 @@ +// aux-build:derive-b.rs + +#[macro_use] +extern crate derive_b; + +#[B] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[C] //~ ERROR cannot find attribute `C` in this scope +#[B(D)] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[B(E = "foo")] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous + //~| WARN derive helper attribute is used before it is introduced + //~| WARN this was previously accepted +#[derive(B)] +struct B; + +fn main() {} diff --git a/tests/ui/proc-macro/proc-macro-attributes.stderr b/tests/ui/proc-macro/proc-macro-attributes.stderr new file mode 100644 index 000000000..140d87906 --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-attributes.stderr @@ -0,0 +1,130 @@ +error: cannot find attribute `C` in this scope + --> $DIR/proc-macro-attributes.rs:9:3 + | +LL | #[C] + | ^ help: a derive helper attribute with a similar name exists: `B` + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:6:3 + | +LL | #[B] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:10:3 + | +LL | #[B(D)] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:13:3 + | +LL | #[B(E = "foo")] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous + --> $DIR/proc-macro-attributes.rs:16:3 + | +LL | #[B(arbitrary tokens)] + | ^ ambiguous name + | + = note: ambiguous because of a name conflict with a derive helper attribute +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:19:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:3:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:6:3 + | +LL | #[B] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + = note: `#[warn(legacy_derive_helpers)]` on by default + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:10:3 + | +LL | #[B(D)] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:13:3 + | +LL | #[B(E = "foo")] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +warning: derive helper attribute is used before it is introduced + --> $DIR/proc-macro-attributes.rs:16:3 + | +LL | #[B(arbitrary tokens)] + | ^ +... +LL | #[derive(B)] + | - the attribute is introduced here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #79202 + +error: aborting due to 5 previous errors; 4 warnings emitted + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/proc-macro/proc-macro-deprecated-attr.rs b/tests/ui/proc-macro/proc-macro-deprecated-attr.rs new file mode 100644 index 000000000..f1144a4a5 --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-deprecated-attr.rs @@ -0,0 +1,16 @@ +// check-pass +// force-host +// no-prefer-dynamic + +#![deny(deprecated)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[deprecated(since = "1.0.0", note = "test")] +pub fn test_compile_without_warning_with_deprecated(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/ui/proc-macro/proc-macro-gates.rs b/tests/ui/proc-macro/proc-macro-gates.rs new file mode 100644 index 000000000..e2cf4e739 --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-gates.rs @@ -0,0 +1,53 @@ +// aux-build:test-macros.rs +// gate-test-proc_macro_hygiene + +#![feature(stmt_expr_attributes)] + +#[macro_use] +extern crate test_macros; + +fn _test_inner() { + #![empty_attr] //~ ERROR: inner macro attributes are unstable +} + +mod _test2_inner { + #![empty_attr] //~ ERROR: inner macro attributes are unstable +} + +#[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported +fn _test3() {} + +fn attrs() { + // Statement, item + #[empty_attr] // OK + struct S; + + // Statement, macro + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements + println!(); + + // Statement, semi + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements + S; + + // Statement, local + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements + let _x = 2; + + // Expr + let _x = #[identity_attr] 2; //~ ERROR: custom attributes cannot be applied to expressions + + // Opt expr + let _x = [#[identity_attr] 2]; //~ ERROR: custom attributes cannot be applied to expressions + + // Expr macro + let _x = #[identity_attr] println!(); + //~^ ERROR: custom attributes cannot be applied to expressions +} + +fn test_case() { + #![test] //~ ERROR inner macro attributes are unstable + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/tests/ui/proc-macro/proc-macro-gates.stderr b/tests/ui/proc-macro/proc-macro-gates.stderr new file mode 100644 index 000000000..3feb9b829 --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-gates.stderr @@ -0,0 +1,91 @@ +error[E0658]: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:10:8 + | +LL | #![empty_attr] + | ^^^^^^^^^^ + | + = note: see issue #54726 for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error[E0658]: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:14:8 + | +LL | #![empty_attr] + | ^^^^^^^^^^ + | + = note: see issue #54726 for more information + = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable + +error: key-value macro attributes are not supported + --> $DIR/proc-macro-gates.rs:17:1 + | +LL | #[empty_attr = "y"] + | ^^^^^^^^^^^^^^^^^^^ + +error[E0658]: custom attributes cannot be applied to statements + --> $DIR/proc-macro-gates.rs:26:5 + | +LL | #[empty_attr] + | ^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to statements + --> $DIR/proc-macro-gates.rs:30:5 + | +LL | #[empty_attr] + | ^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to statements + --> $DIR/proc-macro-gates.rs:34:5 + | +LL | #[empty_attr] + | ^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions + --> $DIR/proc-macro-gates.rs:38:14 + | +LL | let _x = #[identity_attr] 2; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions + --> $DIR/proc-macro-gates.rs:41:15 + | +LL | let _x = [#[identity_attr] 2]; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error[E0658]: custom attributes cannot be applied to expressions + --> $DIR/proc-macro-gates.rs:44:14 + | +LL | let _x = #[identity_attr] println!(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #54727 for more information + = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable + +error: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:49:8 + | +LL | #![test] + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + = note: `#[deny(soft_unstable)]` on by default + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/proc-macro/proc-macro-gates2.rs b/tests/ui/proc-macro/proc-macro-gates2.rs new file mode 100644 index 000000000..38fbd4733 --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-gates2.rs @@ -0,0 +1,24 @@ +// aux-build:test-macros.rs + +#![feature(stmt_expr_attributes)] + +#[macro_use] +extern crate test_macros; + +// NB. these errors aren't the best errors right now, but they're definitely +// intended to be errors. Somehow using a custom attribute in these positions +// should either require a feature gate or not be allowed on stable. + +fn _test6<#[empty_attr] T>() {} +//~^ ERROR: expected non-macro attribute, found attribute macro + +fn _test7() { + match 1 { + #[empty_attr] //~ ERROR: expected non-macro attribute, found attribute macro + 0 => {} + _ => {} + } +} + +fn main() { +} diff --git a/tests/ui/proc-macro/proc-macro-gates2.stderr b/tests/ui/proc-macro/proc-macro-gates2.stderr new file mode 100644 index 000000000..64df34e7c --- /dev/null +++ b/tests/ui/proc-macro/proc-macro-gates2.stderr @@ -0,0 +1,14 @@ +error: expected non-macro attribute, found attribute macro `empty_attr` + --> $DIR/proc-macro-gates2.rs:12:13 + | +LL | fn _test6<#[empty_attr] T>() {} + | ^^^^^^^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `empty_attr` + --> $DIR/proc-macro-gates2.rs:17:11 + | +LL | #[empty_attr] + | ^^^^^^^^^^ not a non-macro attribute + +error: aborting due to 2 previous errors + diff --git a/tests/ui/proc-macro/pub-at-crate-root.rs b/tests/ui/proc-macro/pub-at-crate-root.rs new file mode 100644 index 000000000..54cf333a4 --- /dev/null +++ b/tests/ui/proc-macro/pub-at-crate-root.rs @@ -0,0 +1,22 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +pub mod a { //~ `proc-macro` crate types currently cannot export any items + use proc_macro::TokenStream; + + #[proc_macro_derive(B)] + pub fn bar(a: TokenStream) -> TokenStream { + //~^ ERROR: must currently reside in the root of the crate + a + } +} + +#[proc_macro_derive(B)] +fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { +//~^ ERROR: functions tagged with `#[proc_macro_derive]` must be `pub` + a +} diff --git a/tests/ui/proc-macro/pub-at-crate-root.stderr b/tests/ui/proc-macro/pub-at-crate-root.stderr new file mode 100644 index 000000000..2e7536a0c --- /dev/null +++ b/tests/ui/proc-macro/pub-at-crate-root.stderr @@ -0,0 +1,20 @@ +error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + --> $DIR/pub-at-crate-root.rs:8:1 + | +LL | pub mod a { + | ^^^^^^^^^ + +error: functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate + --> $DIR/pub-at-crate-root.rs:12:5 + | +LL | pub fn bar(a: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions tagged with `#[proc_macro_derive]` must be `pub` + --> $DIR/pub-at-crate-root.rs:19:1 + | +LL | fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/proc-macro/quote-debug.rs b/tests/ui/proc-macro/quote-debug.rs new file mode 100644 index 000000000..e0304a014 --- /dev/null +++ b/tests/ui/proc-macro/quote-debug.rs @@ -0,0 +1,18 @@ +// check-pass +// force-host +// no-prefer-dynamic +// compile-flags: -Z unpretty=expanded +// +// This file is not actually used as a proc-macro - instead, +// it's just used to show the output of the `quote!` macro + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +fn main() { + proc_macro::quote! { + let hello = "world"; + } +} diff --git a/tests/ui/proc-macro/quote-debug.stdout b/tests/ui/proc-macro/quote-debug.stdout new file mode 100644 index 000000000..9f64a1e06 --- /dev/null +++ b/tests/ui/proc-macro/quote-debug.stdout @@ -0,0 +1,48 @@ +#![feature(prelude_import)] +#![no_std] +// check-pass +// force-host +// no-prefer-dynamic +// compile-flags: -Z unpretty=expanded +// +// This file is not actually used as a proc-macro - instead, +// it's just used to show the output of the `quote!` macro + +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +extern crate proc_macro; + +fn main() { + [crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("let", + crate::Span::recover_proc_macro_span(0)))), + crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello", + crate::Span::recover_proc_macro_span(1)))), + crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=', + crate::Spacing::Alone))), + crate::TokenStream::from(crate::TokenTree::Literal({ + let mut iter = + "\"world\"".parse::().unwrap().into_iter(); + if let (Some(crate::TokenTree::Literal(mut lit)), None) = + (iter.next(), iter.next()) { + lit.set_span(crate::Span::recover_proc_macro_span(2)); + lit + } else { + ::core::panicking::panic("internal error: entered unreachable code") + } + })), + crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';', + crate::Spacing::Alone)))].iter().cloned().collect::() +} +const _: () = + { + extern crate proc_macro; + #[rustc_proc_macro_decls] + #[used] + #[allow(deprecated)] + static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[]; + }; diff --git a/tests/ui/proc-macro/raw-ident.rs b/tests/ui/proc-macro/raw-ident.rs new file mode 100644 index 000000000..03cb45714 --- /dev/null +++ b/tests/ui/proc-macro/raw-ident.rs @@ -0,0 +1,16 @@ +// aux-build:raw-ident.rs + +#[macro_use] extern crate raw_ident; + +fn main() { + make_struct!(fn); + make_struct!(Foo); + make_struct!(await); + + r#fn; + r#Foo; + Foo; + r#await; + + make_bad_struct!(S); //~ ERROR expected one of +} diff --git a/tests/ui/proc-macro/raw-ident.stderr b/tests/ui/proc-macro/raw-ident.stderr new file mode 100644 index 000000000..905a5f946 --- /dev/null +++ b/tests/ui/proc-macro/raw-ident.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `S` + --> $DIR/raw-ident.rs:15:5 + | +LL | make_bad_struct!(S); + | ^^^^^^^^^^^^^^^^^^^ expected one of 8 possible tokens + | + = note: this error originates in the macro `make_bad_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/reserved-macro-names.rs b/tests/ui/proc-macro/reserved-macro-names.rs new file mode 100644 index 000000000..c5e71a87d --- /dev/null +++ b/tests/ui/proc-macro/reserved-macro-names.rs @@ -0,0 +1,19 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro_attribute] +pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream { + //~^ ERROR name `cfg` is reserved in attribute namespace + input +} + +#[proc_macro_attribute] +pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream { + //~^ ERROR name `cfg_attr` is reserved in attribute namespace + input +} diff --git a/tests/ui/proc-macro/reserved-macro-names.stderr b/tests/ui/proc-macro/reserved-macro-names.stderr new file mode 100644 index 000000000..39bdd03be --- /dev/null +++ b/tests/ui/proc-macro/reserved-macro-names.stderr @@ -0,0 +1,14 @@ +error: name `cfg` is reserved in attribute namespace + --> $DIR/reserved-macro-names.rs:10:8 + | +LL | pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream { + | ^^^ + +error: name `cfg_attr` is reserved in attribute namespace + --> $DIR/reserved-macro-names.rs:16:8 + | +LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream { + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/proc-macro/resolve-error.rs b/tests/ui/proc-macro/resolve-error.rs new file mode 100644 index 000000000..ad8a5bbb0 --- /dev/null +++ b/tests/ui/proc-macro/resolve-error.rs @@ -0,0 +1,62 @@ +// aux-build:derive-foo.rs +// aux-build:derive-clona.rs +// aux-build:test-macros.rs + +#[macro_use] +extern crate derive_foo; +#[macro_use] +extern crate derive_clona; +extern crate test_macros; + +use test_macros::empty as bang_proc_macro; +use test_macros::empty_attr as attr_proc_macro; + +macro_rules! FooWithLongNam { + () => {} +} + +macro_rules! attr_proc_mac { + () => {} +} + +#[derive(FooWithLongNan)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct Foo; + +// Interpreted as an unstable custom attribute +#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope +struct Bar; + +// Interpreted as an unstable custom attribute +#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope +struct Asdf; + +#[derive(Dlone)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct A; + +#[derive(Dlona)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct B; + +#[derive(attr_proc_macra)] +//~^ ERROR cannot find +//~| ERROR cannot find +struct C; + +fn main() { + FooWithLongNama!(); + //~^ ERROR cannot find + + attr_proc_macra!(); + //~^ ERROR cannot find + + Dlona!(); + //~^ ERROR cannot find + + bang_proc_macrp!(); + //~^ ERROR cannot find +} diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr new file mode 100644 index 000000000..3c3f24d0f --- /dev/null +++ b/tests/ui/proc-macro/resolve-error.stderr @@ -0,0 +1,128 @@ +error: cannot find macro `bang_proc_macrp` in this scope + --> $DIR/resolve-error.rs:60:5 + | +LL | bang_proc_macrp!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` + | + ::: $DIR/auxiliary/test-macros.rs:15:1 + | +LL | pub fn empty(_: TokenStream) -> TokenStream { + | ------------------------------------------- similarly named macro `bang_proc_macro` defined here + +error: cannot find macro `Dlona` in this scope + --> $DIR/resolve-error.rs:57:5 + | +LL | Dlona!(); + | ^^^^^ + +error: cannot find macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:54:5 + | +LL | macro_rules! attr_proc_mac { + | -------------------------- similarly named macro `attr_proc_mac` defined here +... +LL | attr_proc_macra!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac` + +error: cannot find macro `FooWithLongNama` in this scope + --> $DIR/resolve-error.rs:51:5 + | +LL | macro_rules! FooWithLongNam { + | --------------------------- similarly named macro `FooWithLongNam` defined here +... +LL | FooWithLongNama!(); + | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam` + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:45:10 + | +LL | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find derive macro `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:45:10 + | +LL | #[derive(attr_proc_macra)] + | ^^^^^^^^^^^^^^^ + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:40:10 + | +LL | #[derive(Dlona)] + | ^^^^^ help: a derive macro with a similar name exists: `Clona` + | + ::: $DIR/auxiliary/derive-clona.rs:11:1 + | +LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { + | ------------------------------------------------------- similarly named derive macro `Clona` defined here + +error: cannot find derive macro `Dlona` in this scope + --> $DIR/resolve-error.rs:40:10 + | +LL | #[derive(Dlona)] + | ^^^^^ help: a derive macro with a similar name exists: `Clona` + | + ::: $DIR/auxiliary/derive-clona.rs:11:1 + | +LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { + | ------------------------------------------------------- similarly named derive macro `Clona` defined here + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:35:10 + | +LL | #[derive(Dlone)] + | ^^^^^ help: a derive macro with a similar name exists: `Clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | + = note: similarly named derive macro `Clone` defined here + +error: cannot find derive macro `Dlone` in this scope + --> $DIR/resolve-error.rs:35:10 + | +LL | #[derive(Dlone)] + | ^^^^^ help: a derive macro with a similar name exists: `Clone` + --> $SRC_DIR/core/src/clone.rs:LL:COL + | + = note: similarly named derive macro `Clone` defined here + +error: cannot find attribute `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:32:3 + | +LL | #[FooWithLongNan] + | ^^^^^^^^^^^^^^ + +error: cannot find attribute `attr_proc_macra` in this scope + --> $DIR/resolve-error.rs:28:3 + | +LL | #[attr_proc_macra] + | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` + | + ::: $DIR/auxiliary/test-macros.rs:20:1 + | +LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here + +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:22:10 + | +LL | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` + | + ::: $DIR/auxiliary/derive-foo.rs:11:1 + | +LL | pub fn derive_foo(input: TokenStream) -> TokenStream { + | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here + +error: cannot find derive macro `FooWithLongNan` in this scope + --> $DIR/resolve-error.rs:22:10 + | +LL | #[derive(FooWithLongNan)] + | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` + | + ::: $DIR/auxiliary/derive-foo.rs:11:1 + | +LL | pub fn derive_foo(input: TokenStream) -> TokenStream { + | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here + +error: aborting due to 14 previous errors + diff --git a/tests/ui/proc-macro/resolved-located-at.rs b/tests/ui/proc-macro/resolved-located-at.rs new file mode 100644 index 000000000..b785573f2 --- /dev/null +++ b/tests/ui/proc-macro/resolved-located-at.rs @@ -0,0 +1,10 @@ +// aux-build:resolved-located-at.rs + +#[macro_use] +extern crate resolved_located_at; + +fn main() { + resolve_located_at!(a b) + //~^ ERROR expected error + //~| ERROR mismatched types +} diff --git a/tests/ui/proc-macro/resolved-located-at.stderr b/tests/ui/proc-macro/resolved-located-at.stderr new file mode 100644 index 000000000..422820e9d --- /dev/null +++ b/tests/ui/proc-macro/resolved-located-at.stderr @@ -0,0 +1,21 @@ +error: expected error + --> $DIR/resolved-located-at.rs:7:25 + | +LL | resolve_located_at!(a b) + | ^ + | + = note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/resolved-located-at.rs:7:27 + | +LL | fn main() { + | - expected `()` because of default return type +LL | resolve_located_at!(a b) + | ^ expected `()`, found struct `S` + | + = note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/shadow.rs b/tests/ui/proc-macro/shadow.rs new file mode 100644 index 000000000..61959594c --- /dev/null +++ b/tests/ui/proc-macro/shadow.rs @@ -0,0 +1,8 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; +#[macro_use] +extern crate test_macros; //~ ERROR the name `test_macros` is defined multiple times + +fn main() {} diff --git a/tests/ui/proc-macro/shadow.stderr b/tests/ui/proc-macro/shadow.stderr new file mode 100644 index 000000000..e7d95cc83 --- /dev/null +++ b/tests/ui/proc-macro/shadow.stderr @@ -0,0 +1,14 @@ +error[E0259]: the name `test_macros` is defined multiple times + --> $DIR/shadow.rs:6:1 + | +LL | extern crate test_macros; + | ------------------------- previous import of the extern crate `test_macros` here +LL | #[macro_use] +LL | extern crate test_macros; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `test_macros` reimported here + | + = note: `test_macros` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/proc-macro/signature.rs b/tests/ui/proc-macro/signature.rs new file mode 100644 index 000000000..230223825 --- /dev/null +++ b/tests/ui/proc-macro/signature.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![allow(warnings)] + +extern crate proc_macro; + +#[proc_macro_derive(A)] +pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { + //~^ ERROR: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn + loop {} +} diff --git a/tests/ui/proc-macro/signature.stderr b/tests/ui/proc-macro/signature.stderr new file mode 100644 index 000000000..79f2001da --- /dev/null +++ b/tests/ui/proc-macro/signature.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}` + --> $DIR/signature.rs:10:1 + | +LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 { +LL | | +LL | | loop {} +LL | | } + | | ^ + | | | + | |_call the function in a closure: `|| unsafe { /* code */ }` + | required by a bound introduced by this call + | + = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `ProcMacro::custom_derive` + --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/proc-macro/smoke.rs b/tests/ui/proc-macro/smoke.rs new file mode 100644 index 000000000..04625559b --- /dev/null +++ b/tests/ui/proc-macro/smoke.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(path_statements)] +// aux-build:derive-a.rs + +#[macro_use] +extern crate derive_a; + +#[derive(Debug, PartialEq, A, Eq, Copy, Clone)] +struct A; + +fn main() { + A; + assert_eq!(A, A); + A.clone(); + let a = A; + let _c = a; + let _d = a; +} diff --git a/tests/ui/proc-macro/span-absolute-posititions.rs b/tests/ui/proc-macro/span-absolute-posititions.rs new file mode 100644 index 000000000..6d70fe611 --- /dev/null +++ b/tests/ui/proc-macro/span-absolute-posititions.rs @@ -0,0 +1,24 @@ +// aux-build:assert-span-pos.rs +// ignore-tidy-tab +extern crate assert_span_pos; + +assert_span_pos::assert_span_pos!(5, 35); + +// Test space indentation + assert_span_pos::assert_span_pos!(8, 39); +// Test tab indentation + assert_span_pos::assert_span_pos!(10, 36); + +// Two tests to ensure the promise of the docs that the column is the number +// of UTF-8 bytes instead of some other number like number of code points. + +// Test that multi byte UTF-8 characters indeed count as multiple bytes +/*🌈*/assert_span_pos::assert_span_pos!(16, 40); +// Test with a complete grapheme cluster +/*ðŸ³ï¸â€ðŸŒˆ*/assert_span_pos::assert_span_pos!(18, 43); + +// Test that the macro actually emits an error on a mismatch: +assert_span_pos::assert_span_pos!(0, 35); //~ ERROR line/column mismatch: (0, 35) != (21, 35) +assert_span_pos::assert_span_pos!(22, 0); //~ ERROR line/column mismatch: (22, 0) != (22, 35) + +fn main() {} diff --git a/tests/ui/proc-macro/span-absolute-posititions.stderr b/tests/ui/proc-macro/span-absolute-posititions.stderr new file mode 100644 index 000000000..6aca44a6b --- /dev/null +++ b/tests/ui/proc-macro/span-absolute-posititions.stderr @@ -0,0 +1,14 @@ +error: line/column mismatch: (0, 35) != (21, 35) + --> $DIR/span-absolute-posititions.rs:21:35 + | +LL | assert_span_pos::assert_span_pos!(0, 35); + | ^ + +error: line/column mismatch: (22, 0) != (22, 35) + --> $DIR/span-absolute-posititions.rs:22:35 + | +LL | assert_span_pos::assert_span_pos!(22, 0); + | ^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs new file mode 100644 index 000000000..3f04ba866 --- /dev/null +++ b/tests/ui/proc-macro/span-api-tests.rs @@ -0,0 +1,62 @@ +// run-pass +// ignore-pretty +// aux-build:span-api-tests.rs +// aux-build:span-test-macros.rs +// compile-flags: -Ztranslate-remapped-path-to-local-path=yes + +#[macro_use] +extern crate span_test_macros; + +extern crate span_api_tests; + +// FIXME(69775): Investigate `assert_fake_source_file`. + +use span_api_tests::{reemit, assert_source_file, macro_stringify}; + +macro_rules! say_hello { + ($macname:ident) => ( $macname! { "Hello, world!" }) +} + +assert_source_file! { "Hello, world!" } + +say_hello! { assert_source_file } + +reemit_legacy! { + assert_source_file! { "Hello, world!" } +} + +say_hello_extern! { assert_source_file } + +reemit! { + assert_source_file! { "Hello, world!" } +} + +fn main() { + let s = macro_stringify!(Hello, world!); + assert_eq!(s, "Hello, world!"); + assert_eq!(macro_stringify!(Hello, world!), "Hello, world!"); + assert_eq!(reemit_legacy!(macro_stringify!(Hello, world!)), "Hello, world!"); + reemit_legacy!(assert_eq!(macro_stringify!(Hello, world!), "Hello, world!")); + // reemit change the span to be that of the call site + assert_eq!( + reemit!(macro_stringify!(Hello, world!)), + "reemit!(macro_stringify!(Hello, world!))" + ); + let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r))"; + reemit!(assert_eq!(macro_stringify!(Hello, world!), r)); + + assert_eq!(macro_stringify!( + Hello, + world! + ), "Hello,\n world!"); + + assert_eq!(macro_stringify!(Hello, /*world */ !), "Hello, /*world */ !"); + assert_eq!(macro_stringify!( + Hello, + // comment + world! + ), "Hello,\n // comment\n world!"); + + assert_eq!(say_hello! { macro_stringify }, "\"Hello, world!\""); + assert_eq!(say_hello_extern! { macro_stringify }, "\"Hello, world!\""); +} diff --git a/tests/ui/proc-macro/span-from-proc-macro.rs b/tests/ui/proc-macro/span-from-proc-macro.rs new file mode 100644 index 000000000..ecff2d725 --- /dev/null +++ b/tests/ui/proc-macro/span-from-proc-macro.rs @@ -0,0 +1,17 @@ +// aux-build:custom-quote.rs +// aux-build:span-from-proc-macro.rs +// compile-flags: -Z macro-backtrace + +#[macro_use] +extern crate span_from_proc_macro; + +#[error_from_attribute] //~ ERROR cannot find type `MissingType` +struct ShouldBeRemoved; + +#[derive(ErrorFromDerive)] //~ ERROR cannot find type `OtherMissingType` +struct Kept; + +fn main() { + error_from_bang!(); //~ ERROR mismatched types + other_error_from_bang!(); //~ ERROR cannot find value `my_ident` +} diff --git a/tests/ui/proc-macro/span-from-proc-macro.stderr b/tests/ui/proc-macro/span-from-proc-macro.stderr new file mode 100644 index 000000000..7beed505a --- /dev/null +++ b/tests/ui/proc-macro/span-from-proc-macro.stderr @@ -0,0 +1,62 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/auxiliary/span-from-proc-macro.rs:37:20 + | +LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { + | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]` +... +LL | field: MissingType + | ^^^^^^^^^^^ not found in this scope + | + ::: $DIR/span-from-proc-macro.rs:8:1 + | +LL | #[error_from_attribute] + | ----------------------- in this procedural macro expansion + +error[E0412]: cannot find type `OtherMissingType` in this scope + --> $DIR/auxiliary/span-from-proc-macro.rs:46:21 + | +LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream { + | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]` +... +LL | Variant(OtherMissingType) + | ^^^^^^^^^^^^^^^^ not found in this scope + | + ::: $DIR/span-from-proc-macro.rs:11:10 + | +LL | #[derive(ErrorFromDerive)] + | --------------- in this derive macro expansion + +error[E0425]: cannot find value `my_ident` in this scope + --> $DIR/auxiliary/span-from-proc-macro.rs:29:9 + | +LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { + | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!` +LL | custom_quote::custom_quote! { +LL | my_ident + | ^^^^^^^^ not found in this scope + | + ::: $DIR/span-from-proc-macro.rs:16:5 + | +LL | other_error_from_bang!(); + | ------------------------ in this macro invocation + +error[E0308]: mismatched types + --> $DIR/auxiliary/span-from-proc-macro.rs:16:36 + | +LL | let bang_error: bool = 25; + | ---- ^^ expected `bool`, found integer + | | + | expected due to this +... +LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream { + | ---------------------------------------------------------- in this expansion of `error_from_bang!` + | + ::: $DIR/span-from-proc-macro.rs:15:5 + | +LL | error_from_bang!(); + | ------------------ in this macro invocation + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0412, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/span-preservation.rs b/tests/ui/proc-macro/span-preservation.rs new file mode 100644 index 000000000..0c7358655 --- /dev/null +++ b/tests/ui/proc-macro/span-preservation.rs @@ -0,0 +1,57 @@ +// For each of these, we should get the appropriate type mismatch error message, +// and the function should be echoed. + +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[recollect_attr] +fn a() { + let x: usize = "hello"; //~ ERROR mismatched types +} + +#[recollect_attr] +fn b(x: Option) -> usize { + match x { + Some(x) => { return x }, //~ ERROR mismatched types + None => 10 + } +} + +#[recollect_attr] +fn c() { + struct Foo { + a: usize + } + + struct Bar { + a: usize, + b: usize + } + + let x = Foo { a: 10isize }; //~ ERROR mismatched types + let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b` +} + +#[recollect_attr] +extern "C" fn bar() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "C" fn baz() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "Rust" fn rust_abi() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "\x43" fn c_abi_escaped() { + 0 //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/proc-macro/span-preservation.stderr b/tests/ui/proc-macro/span-preservation.stderr new file mode 100644 index 000000000..66c68be2f --- /dev/null +++ b/tests/ui/proc-macro/span-preservation.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:11:20 + | +LL | let x: usize = "hello"; + | ----- ^^^^^^^ expected `usize`, found `&str` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:17:29 + | +LL | fn b(x: Option) -> usize { + | ----- expected `usize` because of return type +LL | match x { +LL | Some(x) => { return x }, + | ^ expected `usize`, found `isize` + | +help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit + | +LL | Some(x) => { return x.try_into().unwrap() }, + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:33:22 + | +LL | let x = Foo { a: 10isize }; + | ^^^^^^^ expected `usize`, found `isize` + +error[E0560]: struct `Foo` has no field named `b` + --> $DIR/span-preservation.rs:34:26 + | +LL | let y = Foo { a: 10, b: 10isize }; + | ^ `Foo` does not have this field + | + = note: available fields are: `a` + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:39:5 + | +LL | extern "C" fn bar() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:44:5 + | +LL | extern "C" fn baz() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:49:5 + | +LL | extern "Rust" fn rust_abi() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:54:5 + | +LL | extern "\x43" fn c_abi_escaped() { + | - help: try adding a return type: `-> i32` +LL | 0 + | ^ expected `()`, found integer + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/proc-macro/struct-field-macro.rs b/tests/ui/proc-macro/struct-field-macro.rs new file mode 100644 index 000000000..460f4d9f7 --- /dev/null +++ b/tests/ui/proc-macro/struct-field-macro.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(dead_code)] +// aux-build:derive-nothing.rs + +#[macro_use] +extern crate derive_nothing; + +macro_rules! int { + () => { i32 } +} + +#[derive(Nothing)] +struct S { + x: int!(), +} + +fn main() {} diff --git a/tests/ui/proc-macro/subspan.rs b/tests/ui/proc-macro/subspan.rs new file mode 100644 index 000000000..a4187f9e7 --- /dev/null +++ b/tests/ui/proc-macro/subspan.rs @@ -0,0 +1,26 @@ +// aux-build:subspan.rs + +extern crate subspan; + +use subspan::subspan; + +// This one emits no error. +subspan!(""); + +// Exactly one 'hi'. +subspan!("hi"); //~ ERROR found 'hi's + +// Now two, back to back. +subspan!("hihi"); //~ ERROR found 'hi's + +// Now three, back to back. +subspan!("hihihi"); //~ ERROR found 'hi's + +// Now several, with spacing. +subspan!("why I hide? hi!"); //~ ERROR found 'hi's +subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's +subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's +subspan!("how are you this evening"); //~ ERROR found 'hi's +subspan!("this is highly eradic"); //~ ERROR found 'hi's + +fn main() { } diff --git a/tests/ui/proc-macro/subspan.stderr b/tests/ui/proc-macro/subspan.stderr new file mode 100644 index 000000000..b5dacba0e --- /dev/null +++ b/tests/ui/proc-macro/subspan.stderr @@ -0,0 +1,106 @@ +error: found 'hi's + --> $DIR/subspan.rs:11:1 + | +LL | subspan!("hi"); + | ^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:11:11 + | +LL | subspan!("hi"); + | ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:14:1 + | +LL | subspan!("hihi"); + | ^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:14:11 + | +LL | subspan!("hihi"); + | ^^^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:17:1 + | +LL | subspan!("hihihi"); + | ^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:17:11 + | +LL | subspan!("hihihi"); + | ^^^^^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:20:1 + | +LL | subspan!("why I hide? hi!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:20:17 + | +LL | subspan!("why I hide? hi!"); + | ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:21:1 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:21:16 + | +LL | subspan!("hey, hi, hidy, hidy, hi hi"); + | ^^ ^^ ^^ ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:22:1 + | +LL | subspan!("this is a hi, and this is another hi"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:22:12 + | +LL | subspan!("this is a hi, and this is another hi"); + | ^^ ^^ ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:23:1 + | +LL | subspan!("how are you this evening"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:23:24 + | +LL | subspan!("how are you this evening"); + | ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: found 'hi's + --> $DIR/subspan.rs:24:1 + | +LL | subspan!("this is highly eradic"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: here + --> $DIR/subspan.rs:24:12 + | +LL | subspan!("this is highly eradic"); + | ^^ ^^ + = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + diff --git a/tests/ui/proc-macro/test.rs b/tests/ui/proc-macro/test.rs new file mode 100644 index 000000000..c96aa7317 --- /dev/null +++ b/tests/ui/proc-macro/test.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:api/mod.rs + +//! This is for everything that *would* be a #[test] inside of libproc_macro, +//! except for the fact that proc_macro objects are not capable of existing +//! inside of an ordinary Rust test execution, only inside a macro. + +extern crate proc_macro_api_tests; + +proc_macro_api_tests::run!(); + +fn main() {} diff --git a/tests/ui/proc-macro/three-equals.rs b/tests/ui/proc-macro/three-equals.rs new file mode 100644 index 000000000..21b137c99 --- /dev/null +++ b/tests/ui/proc-macro/three-equals.rs @@ -0,0 +1,25 @@ +// aux-build:three-equals.rs + +extern crate three_equals; + +use three_equals::three_equals; + +fn main() { + // This one is okay. + three_equals!(===); + + // Need exactly three equals. + three_equals!(==); //~ ERROR found 2 equal signs, need exactly 3 + + // Need exactly three equals. + three_equals!(=====); //~ ERROR expected EOF + + // Only equals accepted. + three_equals!(abc); //~ ERROR expected `=` + + // Only equals accepted. + three_equals!(!!); //~ ERROR expected `=` + + // Only three characters expected. + three_equals!(===a); //~ ERROR expected EOF +} diff --git a/tests/ui/proc-macro/three-equals.stderr b/tests/ui/proc-macro/three-equals.stderr new file mode 100644 index 000000000..9cdb2a21b --- /dev/null +++ b/tests/ui/proc-macro/three-equals.stderr @@ -0,0 +1,49 @@ +error: found 2 equal signs, need exactly 3 + --> $DIR/three-equals.rs:12:5 + | +LL | three_equals!(==); + | ^^^^^^^^^^^^^^^^^ + | + = help: input must be: `===` + = note: this error originates in the macro `three_equals` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected EOF, found `=`. + --> $DIR/three-equals.rs:15:22 + | +LL | three_equals!(=====); + | ^ + | +note: last good input was here + --> $DIR/three-equals.rs:15:21 + | +LL | three_equals!(=====); + | ^ + = help: input must be: `===` + +error: expected `=`, found `abc`. + --> $DIR/three-equals.rs:18:19 + | +LL | three_equals!(abc); + | ^^^ + +error: expected `=`, found `!`. + --> $DIR/three-equals.rs:21:19 + | +LL | three_equals!(!!); + | ^ + +error: expected EOF, found `a`. + --> $DIR/three-equals.rs:24:22 + | +LL | three_equals!(===a); + | ^ + | +note: last good input was here + --> $DIR/three-equals.rs:24:21 + | +LL | three_equals!(===a); + | ^ + = help: input must be: `===` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/proc-macro/trailing-plus.rs b/tests/ui/proc-macro/trailing-plus.rs new file mode 100644 index 000000000..4f61de47d --- /dev/null +++ b/tests/ui/proc-macro/trailing-plus.rs @@ -0,0 +1,14 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; + +#[test_macros::print_attr] +fn foo() where T: Copy + { +} + +fn main() {} diff --git a/tests/ui/proc-macro/trailing-plus.stdout b/tests/ui/proc-macro/trailing-plus.stdout new file mode 100644 index 000000000..b90057cd6 --- /dev/null +++ b/tests/ui/proc-macro/trailing-plus.stdout @@ -0,0 +1,57 @@ +PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/trailing-plus.rs:11:1: 11:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/trailing-plus.rs:11:4: 11:7 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:7: 11:8 (#0), + }, + Ident { + ident: "T", + span: $DIR/trailing-plus.rs:11:8: 11:9 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:9: 11:10 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/trailing-plus.rs:11:10: 11:12 (#0), + }, + Ident { + ident: "where", + span: $DIR/trailing-plus.rs:11:13: 11:18 (#0), + }, + Ident { + ident: "T", + span: $DIR/trailing-plus.rs:11:19: 11:20 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:20: 11:21 (#0), + }, + Ident { + ident: "Copy", + span: $DIR/trailing-plus.rs:11:22: 11:26 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/trailing-plus.rs:11:27: 11:28 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/trailing-plus.rs:11:29: 12:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/trait-fn-args-2015.rs b/tests/ui/proc-macro/trait-fn-args-2015.rs new file mode 100644 index 000000000..6b8df78a0 --- /dev/null +++ b/tests/ui/proc-macro/trait-fn-args-2015.rs @@ -0,0 +1,16 @@ +// Unnamed arguments in trait functions can be passed through proc macros on 2015 edition. + +// check-pass +// aux-build:test-macros.rs + +#![allow(anonymous_parameters)] + +#[macro_use] +extern crate test_macros; + +trait Tr { + #[identity_attr] + fn method(u8); +} + +fn main() {} diff --git a/tests/ui/proc-macro/two-crate-types-1.rs b/tests/ui/proc-macro/two-crate-types-1.rs new file mode 100644 index 000000000..80bfd357f --- /dev/null +++ b/tests/ui/proc-macro/two-crate-types-1.rs @@ -0,0 +1,7 @@ +// error-pattern: cannot mix `proc-macro` crate type with others + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_type = "rlib"] diff --git a/tests/ui/proc-macro/two-crate-types-1.stderr b/tests/ui/proc-macro/two-crate-types-1.stderr new file mode 100644 index 000000000..deaba1cf2 --- /dev/null +++ b/tests/ui/proc-macro/two-crate-types-1.stderr @@ -0,0 +1,4 @@ +error: cannot mix `proc-macro` crate type with others + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/two-crate-types-2.rs b/tests/ui/proc-macro/two-crate-types-2.rs new file mode 100644 index 000000000..39cbf7d3b --- /dev/null +++ b/tests/ui/proc-macro/two-crate-types-2.rs @@ -0,0 +1,3 @@ +// error-pattern: cannot mix `proc-macro` crate type with others +// compile-flags: --crate-type rlib --crate-type proc-macro +// force-host diff --git a/tests/ui/proc-macro/two-crate-types-2.stderr b/tests/ui/proc-macro/two-crate-types-2.stderr new file mode 100644 index 000000000..deaba1cf2 --- /dev/null +++ b/tests/ui/proc-macro/two-crate-types-2.stderr @@ -0,0 +1,4 @@ +error: cannot mix `proc-macro` crate type with others + +error: aborting due to previous error + diff --git a/tests/ui/proc-macro/unsafe-foreign-mod.rs b/tests/ui/proc-macro/unsafe-foreign-mod.rs new file mode 100644 index 000000000..7bdfa93c2 --- /dev/null +++ b/tests/ui/proc-macro/unsafe-foreign-mod.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_unsafe_foreign_mod] +unsafe extern { + type T; +} + +#[macro_only_syntax::expect_unsafe_extern_cpp_mod] +unsafe extern "C++" {} + +fn main() {} diff --git a/tests/ui/proc-macro/unsafe-mod.rs b/tests/ui/proc-macro/unsafe-mod.rs new file mode 100644 index 000000000..8ff6e352c --- /dev/null +++ b/tests/ui/proc-macro/unsafe-mod.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +#![feature(proc_macro_hygiene)] + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_unsafe_mod] +unsafe mod m { + pub unsafe mod inner; +} + +fn main() {} diff --git a/tests/ui/proc-macro/visibility-path.rs b/tests/ui/proc-macro/visibility-path.rs new file mode 100644 index 000000000..a73430db2 --- /dev/null +++ b/tests/ui/proc-macro/visibility-path.rs @@ -0,0 +1,25 @@ +// Proc macro defined with `pub(path)` doesn't ICEs due to resolving the `path` (issue #68921). + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub(self) fn outer(input: TokenStream) -> TokenStream { + //~^ ERROR functions tagged with `#[proc_macro]` must be `pub` + input +} + +mod m { + use proc_macro::*; + + #[proc_macro] + pub(super) fn inner(input: TokenStream) -> TokenStream { + //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root + input + } +} diff --git a/tests/ui/proc-macro/visibility-path.stderr b/tests/ui/proc-macro/visibility-path.stderr new file mode 100644 index 000000000..1a73cc196 --- /dev/null +++ b/tests/ui/proc-macro/visibility-path.stderr @@ -0,0 +1,14 @@ +error: functions tagged with `#[proc_macro]` must be `pub` + --> $DIR/visibility-path.rs:12:1 + | +LL | pub(self) fn outer(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate + --> $DIR/visibility-path.rs:21:5 + | +LL | pub(super) fn inner(input: TokenStream) -> TokenStream { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/proc-macro/weird-braces.rs b/tests/ui/proc-macro/weird-braces.rs new file mode 100644 index 000000000..b9a7e08f9 --- /dev/null +++ b/tests/ui/proc-macro/weird-braces.rs @@ -0,0 +1,23 @@ +// aux-build:test-macros.rs +// check-pass +// compile-flags: -Z span-debug + +#![feature(custom_inner_attributes)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate test_macros; +use test_macros::{print_target_and_args}; + +struct Foo; +trait Bar {} + +#[print_target_and_args(first_outer)] +#[print_target_and_args(second_outer)] +impl Bar<{1 > 0}> for Foo<{true}> { + #![print_target_and_args(first_inner)] + #![print_target_and_args(second_inner)] +} + +fn main() {} diff --git a/tests/ui/proc-macro/weird-braces.stdout b/tests/ui/proc-macro/weird-braces.stdout new file mode 100644 index 000000000..9bf562217 --- /dev/null +++ b/tests/ui/proc-macro/weird-braces.stdout @@ -0,0 +1,524 @@ +PRINT-ATTR_ARGS INPUT (DISPLAY): first_outer +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "first_outer", + span: $DIR/weird-braces.rs:16:25: 16:36 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second_outer)] impl Bar < { 1 > 0 } > for Foo < +{ true } > +{ + #! [print_target_and_args(first_inner)] #! + [print_target_and_args(second_inner)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/weird-braces.rs:17:1: 17:2 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:17:3: 17:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_outer", + span: $DIR/weird-braces.rs:17:25: 17:37 (#0), + }, + ], + span: $DIR/weird-braces.rs:17:24: 17:38 (#0), + }, + ], + span: $DIR/weird-braces.rs:17:2: 17:39 (#0), + }, + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:19:8: 19:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first_inner", + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:29: 19:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:7: 19:43 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): second_outer +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_outer", + span: $DIR/weird-braces.rs:17:25: 17:37 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > +{ + #! [print_target_and_args(first_inner)] #! + [print_target_and_args(second_inner)] +} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:19:5: 19:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:19:6: 19:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:19:8: 19:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "first_inner", + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:29: 19:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:19:7: 19:43 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): first_inner +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "first_inner", + span: $DIR/weird-braces.rs:19:30: 19:41 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > +{ #! [print_target_and_args(second_inner)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/weird-braces.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/weird-braces.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/weird-braces.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:29: 20:43 (#0), + }, + ], + span: $DIR/weird-braces.rs:20:7: 20:44 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): second_inner +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_inner", + span: $DIR/weird-braces.rs:20:30: 20:42 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > {} +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "impl", + span: $DIR/weird-braces.rs:18:1: 18:5 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/weird-braces.rs:18:6: 18:9 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:9: 18:10 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/weird-braces.rs:18:11: 18:12 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:13: 18:14 (#0), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: $DIR/weird-braces.rs:18:15: 18:16 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:10: 18:17 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:17: 18:18 (#0), + }, + Ident { + ident: "for", + span: $DIR/weird-braces.rs:18:19: 18:22 (#0), + }, + Ident { + ident: "Foo", + span: $DIR/weird-braces.rs:18:23: 18:26 (#0), + }, + Punct { + ch: '<', + spacing: Alone, + span: $DIR/weird-braces.rs:18:26: 18:27 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "true", + span: $DIR/weird-braces.rs:18:28: 18:32 (#0), + }, + ], + span: $DIR/weird-braces.rs:18:27: 18:33 (#0), + }, + Punct { + ch: '>', + spacing: Alone, + span: $DIR/weird-braces.rs:18:33: 18:34 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/weird-braces.rs:18:35: 21:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/weird-hygiene.rs b/tests/ui/proc-macro/weird-hygiene.rs new file mode 100644 index 000000000..7ba3f98a7 --- /dev/null +++ b/tests/ui/proc-macro/weird-hygiene.rs @@ -0,0 +1,46 @@ +// aux-build:weird-hygiene.rs + +#![feature(stmt_expr_attributes)] +#![feature(proc_macro_hygiene)] + +extern crate weird_hygiene; +use weird_hygiene::*; + +macro_rules! other { + ($tokens:expr) => { + macro_rules! call_it { + ($outer_ident:ident) => { + macro_rules! inner { + () => { + $outer_ident; + } + } + } + } + + #[derive(WeirdDerive)] + enum MyEnum { + Value = (stringify!($tokens + hidden_ident), 1).1 //~ ERROR cannot find + } + + inner!(); + } +} + +macro_rules! invoke_it { + ($token:expr) => { + #[recollect_attr] { + $token; + hidden_ident //~ ERROR cannot find + } + } +} + +fn main() { + // `other` and `invoke_it` are both macro_rules! macros, + // so it should be impossible for them to ever see `hidden_ident`, + // even if they invoke a proc macro. + let hidden_ident = "Hello1"; + other!(50); + invoke_it!(25); +} diff --git a/tests/ui/proc-macro/weird-hygiene.stderr b/tests/ui/proc-macro/weird-hygiene.stderr new file mode 100644 index 000000000..256e68e89 --- /dev/null +++ b/tests/ui/proc-macro/weird-hygiene.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find value `hidden_ident` in this scope + --> $DIR/weird-hygiene.rs:23:43 + | +LL | Value = (stringify!($tokens + hidden_ident), 1).1 + | ^^^^^^^^^^^^ not found in this scope +... +LL | other!(50); + | ---------- in this macro invocation + | + = note: this error originates in the macro `inner` which comes from the expansion of the macro `other` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `hidden_ident` in this scope + --> $DIR/weird-hygiene.rs:34:13 + | +LL | hidden_ident + | ^^^^^^^^^^^^ not found in this scope +... +LL | invoke_it!(25); + | -------------- in this macro invocation + | + = note: this error originates in the macro `invoke_it` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/process-termination/process-termination-blocking-io.rs b/tests/ui/process-termination/process-termination-blocking-io.rs new file mode 100644 index 000000000..b2dab5c93 --- /dev/null +++ b/tests/ui/process-termination/process-termination-blocking-io.rs @@ -0,0 +1,19 @@ +// program should terminate even if a thread is blocked on I/O. +// https://github.com/fortanix/rust-sgx/issues/109 + +// run-pass +// ignore-emscripten no threads support + +use std::{net::TcpListener, sync::mpsc, thread}; + +fn main() { + let (tx, rx) = mpsc::channel(); + thread::spawn(move || { + let listen = TcpListener::bind("127.0.0.1:0").unwrap(); + tx.send(()).unwrap(); + while let Ok(_) = listen.accept() {} + }); + rx.recv().unwrap(); + for _ in 0..3 { thread::yield_now(); } + println!("Exiting main thread"); +} diff --git a/tests/ui/process-termination/process-termination-simple.rs b/tests/ui/process-termination/process-termination-simple.rs new file mode 100644 index 000000000..8f2e5b94c --- /dev/null +++ b/tests/ui/process-termination/process-termination-simple.rs @@ -0,0 +1,13 @@ +// program should terminate when std::process::exit is called from any thread + +// run-pass +// ignore-emscripten no threads support + +use std::{process, thread}; + +fn main() { + let h = thread::spawn(|| { + process::exit(0); + }); + let _ = h.join(); +} diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs new file mode 100644 index 000000000..d0e97bf01 --- /dev/null +++ b/tests/ui/process/core-run-destroy.rs @@ -0,0 +1,88 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(stable_features)] +#![allow(deprecated)] +#![allow(unused_imports)] +// compile-flags:--test +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-vxworks no 'cat' and 'sleep' +// ignore-fuchsia no 'cat' + +// N.B., these tests kill child processes. Valgrind sees these children as leaking +// memory, which makes for some *confusing* logs. That's why these are here +// instead of in std. + +#![feature(rustc_private, duration)] + +extern crate libc; + +use std::process::{self, Command, Child, Output, Stdio}; +use std::str; +use std::sync::mpsc::channel; +use std::thread; +use std::time::Duration; + +macro_rules! t { + ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("error: {}", e) }) +} + +#[test] +fn test_destroy_once() { + let mut p = sleeper(); + t!(p.kill()); +} + +#[cfg(unix)] +pub fn sleeper() -> Child { + t!(Command::new("sleep").arg("1000").spawn()) +} +#[cfg(windows)] +pub fn sleeper() -> Child { + // There's a `timeout` command on windows, but it doesn't like having + // its output piped, so instead just ping ourselves a few times with + // gaps in between so we're sure this process is alive for awhile + t!(Command::new("ping").arg("127.0.0.1").arg("-n").arg("1000").spawn()) +} + +#[test] +fn test_destroy_twice() { + let mut p = sleeper(); + t!(p.kill()); // this shouldn't crash... + let _ = p.kill(); // ...and nor should this (and nor should the destructor) +} + +#[test] +fn test_destroy_actually_kills() { + let cmd = if cfg!(windows) { + "cmd" + } else if cfg!(target_os = "android") { + "/system/bin/cat" + } else { + "cat" + }; + + // this process will stay alive indefinitely trying to read from stdin + let mut p = t!(Command::new(cmd) + .stdin(Stdio::piped()) + .spawn()); + + t!(p.kill()); + + // Don't let this test time out, this should be quick + let (tx, rx) = channel(); + thread::spawn(move|| { + thread::sleep_ms(1000); + if rx.try_recv().is_err() { + process::exit(1); + } + }); + let code = t!(p.wait()).code(); + if cfg!(windows) { + assert!(code.is_some()); + } else { + assert!(code.is_none()); + } + tx.send(()); +} diff --git a/tests/ui/process/fds-are-cloexec.rs b/tests/ui/process/fds-are-cloexec.rs new file mode 100644 index 000000000..4482b7032 --- /dev/null +++ b/tests/ui/process/fds-are-cloexec.rs @@ -0,0 +1,82 @@ +// run-pass +// ignore-windows +// ignore-android +// ignore-emscripten no processes +// ignore-haiku +// ignore-sgx no processes + +#![feature(rustc_private)] + +extern crate libc; + +use std::env; +use std::fs::File; +use std::io; +use std::net::{TcpListener, TcpStream, UdpSocket}; +use std::os::unix::prelude::*; +use std::process::{Command, Stdio}; +use std::thread; + +fn main() { + let args = env::args().collect::>(); + if args.len() == 1 { + parent() + } else { + child(&args) + } +} + +fn parent() { + let file = File::open(env::current_exe().unwrap()).unwrap(); + let tcp1 = TcpListener::bind("127.0.0.1:0").unwrap(); + let tcp2 = tcp1.try_clone().unwrap(); + let addr = tcp1.local_addr().unwrap(); + let t = thread::spawn(move || TcpStream::connect(addr).unwrap()); + let tcp3 = tcp1.accept().unwrap().0; + let tcp4 = t.join().unwrap(); + let tcp5 = tcp3.try_clone().unwrap(); + let tcp6 = tcp4.try_clone().unwrap(); + let udp1 = UdpSocket::bind("127.0.0.1:0").unwrap(); + let udp2 = udp1.try_clone().unwrap(); + + let mut child = Command::new(env::args().next().unwrap()) + .arg("100") + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn().unwrap(); + let pipe1 = child.stdin.take().unwrap(); + let pipe2 = child.stdout.take().unwrap(); + let pipe3 = child.stderr.take().unwrap(); + + + let status = Command::new(env::args().next().unwrap()) + .arg(file.as_raw_fd().to_string()) + .arg(tcp1.as_raw_fd().to_string()) + .arg(tcp2.as_raw_fd().to_string()) + .arg(tcp3.as_raw_fd().to_string()) + .arg(tcp4.as_raw_fd().to_string()) + .arg(tcp5.as_raw_fd().to_string()) + .arg(tcp6.as_raw_fd().to_string()) + .arg(udp1.as_raw_fd().to_string()) + .arg(udp2.as_raw_fd().to_string()) + .arg(pipe1.as_raw_fd().to_string()) + .arg(pipe2.as_raw_fd().to_string()) + .arg(pipe3.as_raw_fd().to_string()) + .status() + .unwrap(); + assert!(status.success()); + child.wait().unwrap(); +} + +fn child(args: &[String]) { + let mut b = [0u8; 2]; + for arg in &args[1..] { + let fd: libc::c_int = arg.parse().unwrap(); + unsafe { + assert_eq!(libc::read(fd, b.as_mut_ptr() as *mut _, 2), -1); + assert_eq!(io::Error::last_os_error().raw_os_error(), + Some(libc::EBADF)); + } + } +} diff --git a/tests/ui/process/issue-13304.rs b/tests/ui/process/issue-13304.rs new file mode 100644 index 000000000..b10f6d572 --- /dev/null +++ b/tests/ui/process/issue-13304.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_mut)] +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::io::prelude::*; +use std::io; +use std::process::{Command, Stdio}; +use std::str; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + child(); + } else { + parent(); + } +} + +fn parent() { + let args: Vec = env::args().collect(); + let mut p = Command::new(&args[0]).arg("child") + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) + .spawn().unwrap(); + p.stdin.as_mut().unwrap().write_all(b"test1\ntest2\ntest3").unwrap(); + let out = p.wait_with_output().unwrap(); + assert!(out.status.success()); + let s = str::from_utf8(&out.stdout).unwrap(); + assert_eq!(s, "test1\ntest2\ntest3\n"); +} + +fn child() { + let mut stdin = io::stdin(); + for line in stdin.lock().lines() { + println!("{}", line.unwrap()); + } +} diff --git a/tests/ui/process/issue-14456.rs b/tests/ui/process/issue-14456.rs new file mode 100644 index 000000000..52a56eb77 --- /dev/null +++ b/tests/ui/process/issue-14456.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(unused_mut)] +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::io::prelude::*; +use std::io; +use std::process::{Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + return child() + } + + test(); +} + +fn child() { + writeln!(&mut io::stdout(), "foo").unwrap(); + writeln!(&mut io::stderr(), "bar").unwrap(); + let mut stdin = io::stdin(); + let mut s = String::new(); + stdin.lock().read_line(&mut s).unwrap(); + assert_eq!(s.len(), 0); +} + +fn test() { + let args: Vec = env::args().collect(); + let mut p = Command::new(&args[0]).arg("child") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn().unwrap(); + assert!(p.wait().unwrap().success()); +} diff --git a/tests/ui/process/issue-14940.rs b/tests/ui/process/issue-14940.rs new file mode 100644 index 000000000..98a4af0c4 --- /dev/null +++ b/tests/ui/process/issue-14940.rs @@ -0,0 +1,19 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::process::Command; +use std::io::{self, Write}; + +fn main() { + let mut args = env::args(); + if args.len() > 1 { + let mut out = io::stdout(); + out.write(&['a' as u8; 128 * 1024]).unwrap(); + } else { + let out = Command::new(&args.next().unwrap()).arg("child").output(); + let out = out.unwrap(); + assert!(out.status.success()); + } +} diff --git a/tests/ui/process/issue-16272.rs b/tests/ui/process/issue-16272.rs new file mode 100644 index 000000000..5cf3fd949 --- /dev/null +++ b/tests/ui/process/issue-16272.rs @@ -0,0 +1,23 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::process::Command; +use std::env; + +fn main() { + let len = env::args().len(); + + if len == 1 { + test(); + } else { + assert_eq!(len, 3); + } +} + +fn test() { + let status = Command::new(&env::current_exe().unwrap()) + .arg("foo").arg("") + .status().unwrap(); + assert!(status.success()); +} diff --git a/tests/ui/process/issue-20091.rs b/tests/ui/process/issue-20091.rs new file mode 100644 index 000000000..86cc79d6b --- /dev/null +++ b/tests/ui/process/issue-20091.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(stable_features)] + +// ignore-emscripten no processes +// ignore-sgx no processes + +#![feature(os)] + +#[cfg(unix)] +fn main() { + use std::process::Command; + use std::env; + use std::os::unix::prelude::*; + use std::ffi::OsStr; + + if env::args().len() == 1 { + assert!(Command::new(&env::current_exe().unwrap()) + .arg(::from_bytes(b"\xff")) + .status().unwrap().success()) + } +} + +#[cfg(windows)] +fn main() {} diff --git a/tests/ui/process/multi-panic.rs b/tests/ui/process/multi-panic.rs new file mode 100644 index 000000000..a1887c218 --- /dev/null +++ b/tests/ui/process/multi-panic.rs @@ -0,0 +1,38 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// needs-unwind + +fn check_for_no_backtrace(test: std::process::Output) { + assert!(!test.status.success()); + let err = String::from_utf8_lossy(&test.stderr); + let mut it = err.lines(); + + assert_eq!(it.next().map(|l| l.starts_with("thread '' panicked at")), Some(true)); + assert_eq!(it.next(), Some("note: run with `RUST_BACKTRACE=1` \ + environment variable to display a backtrace")); + assert_eq!(it.next().map(|l| l.starts_with("thread 'main' panicked at")), Some(true)); + assert_eq!(it.next(), None); +} + +fn main() { + let args: Vec = std::env::args().collect(); + if args.len() > 1 && args[1] == "run_test" { + let _ = std::thread::spawn(|| { + panic!(); + }).join(); + + panic!(); + } else { + let test = std::process::Command::new(&args[0]).arg("run_test") + .env_remove("RUST_BACKTRACE") + .output() + .unwrap(); + check_for_no_backtrace(test); + let test = std::process::Command::new(&args[0]).arg("run_test") + .env("RUST_BACKTRACE","0") + .output() + .unwrap(); + check_for_no_backtrace(test); + } +} diff --git a/tests/ui/process/no-stdio.rs b/tests/ui/process/no-stdio.rs new file mode 100644 index 000000000..24985386a --- /dev/null +++ b/tests/ui/process/no-stdio.rs @@ -0,0 +1,139 @@ +// run-pass +// ignore-android +// ignore-emscripten no processes +// ignore-sgx no processes +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![feature(rustc_private)] + +extern crate libc; + +use std::process::{Command, Stdio}; +use std::env; +use std::io::{self, Read, Write}; + +#[cfg(unix)] +unsafe fn without_stdio R>(f: F) -> R { + let doit = |a| { + let r = libc::dup(a); + assert!(r >= 0); + return r + }; + let a = doit(0); + let b = doit(1); + let c = doit(2); + + assert!(libc::close(0) >= 0); + assert!(libc::close(1) >= 0); + assert!(libc::close(2) >= 0); + + let r = f(); + + assert!(libc::dup2(a, 0) >= 0); + assert!(libc::dup2(b, 1) >= 0); + assert!(libc::dup2(c, 2) >= 0); + + return r +} + +#[cfg(unix)] +fn assert_fd_is_valid(fd: libc::c_int) { + if unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 } { + panic!("file descriptor {} is not valid: {}", fd, io::Error::last_os_error()); + } +} + +#[cfg(windows)] +fn assert_fd_is_valid(_fd: libc::c_int) {} + +#[cfg(windows)] +unsafe fn without_stdio R>(f: F) -> R { + type DWORD = u32; + type HANDLE = *mut u8; + type BOOL = i32; + + const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; + const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE; + + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn SetStdHandle(which: DWORD, handle: HANDLE) -> BOOL; + } + + let doit = |id| { + let handle = GetStdHandle(id); + assert!(handle != INVALID_HANDLE_VALUE); + assert!(SetStdHandle(id, INVALID_HANDLE_VALUE) != 0); + return handle + }; + + let a = doit(STD_INPUT_HANDLE); + let b = doit(STD_OUTPUT_HANDLE); + let c = doit(STD_ERROR_HANDLE); + + let r = f(); + + let doit = |id, handle| { + assert!(SetStdHandle(id, handle) != 0); + }; + doit(STD_INPUT_HANDLE, a); + doit(STD_OUTPUT_HANDLE, b); + doit(STD_ERROR_HANDLE, c); + + return r +} + +fn main() { + if env::args().len() > 1 { + // Writing to stdout & stderr should not panic. + println!("test"); + assert!(io::stdout().write(b"test\n").is_ok()); + assert!(io::stderr().write(b"test\n").is_ok()); + + // Stdin should be at EOF. + assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0); + + // Standard file descriptors should be valid on UNIX: + assert_fd_is_valid(0); + assert_fd_is_valid(1); + assert_fd_is_valid(2); + return + } + + // First, make sure reads/writes without stdio work if stdio itself is + // missing. + let (a, b, c) = unsafe { + without_stdio(|| { + let a = io::stdout().write(b"test\n"); + let b = io::stderr().write(b"test\n"); + let c = io::stdin().read(&mut [0; 10]); + + (a, b, c) + }) + }; + + assert_eq!(a.unwrap(), 5); + assert_eq!(b.unwrap(), 5); + assert_eq!(c.unwrap(), 0); + + // Second, spawn a child and do some work with "null" descriptors to make + // sure it's ok + let me = env::current_exe().unwrap(); + let status = Command::new(&me) + .arg("next") + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status().unwrap(); + assert!(status.success(), "{} isn't a success", status); + + // Finally, close everything then spawn a child to make sure everything is + // *still* ok. + let status = unsafe { + without_stdio(|| Command::new(&me).arg("next").status()) + }.unwrap(); + assert!(status.success(), "{} isn't a success", status); +} diff --git a/tests/ui/process/nofile-limit.rs b/tests/ui/process/nofile-limit.rs new file mode 100644 index 000000000..3ddf8d6ef --- /dev/null +++ b/tests/ui/process/nofile-limit.rs @@ -0,0 +1,46 @@ +// Check that statically linked binary executes successfully +// with RLIMIT_NOFILE resource lowered to zero. Regression +// test for issue #96621. +// +// run-pass +// dont-check-compiler-stderr +// only-linux +// no-prefer-dynamic +// compile-flags: -Ctarget-feature=+crt-static -Crpath=no -Crelocation-model=static +#![feature(exit_status_error)] +#![feature(rustc_private)] +extern crate libc; + +use std::os::unix::process::CommandExt; +use std::process::Command; + +fn main() { + let mut args = std::env::args(); + let this = args.next().unwrap(); + match args.next().as_deref() { + None => { + let mut cmd = Command::new(this); + cmd.arg("Ok!"); + unsafe { + cmd.pre_exec(|| { + let rlim = libc::rlimit { + rlim_cur: 0, + rlim_max: 0, + }; + if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) == -1 { + Err(std::io::Error::last_os_error()) + } else { + Ok(()) + } + }) + }; + let output = cmd.output().unwrap(); + println!("{:?}", output); + output.status.exit_ok().unwrap(); + assert!(output.stdout.starts_with(b"Ok!")); + } + Some(word) => { + println!("{}", word); + } + } +} diff --git a/tests/ui/process/process-envs.rs b/tests/ui/process/process-envs.rs new file mode 100644 index 000000000..f3a469791 --- /dev/null +++ b/tests/ui/process/process-envs.rs @@ -0,0 +1,54 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-vxworks no 'env' +// ignore-fuchsia no 'env' + +use std::process::Command; +use std::env; +use std::collections::HashMap; + +#[cfg(all(unix, not(target_os="android")))] +pub fn env_cmd() -> Command { + Command::new("env") +} +#[cfg(target_os="android")] +pub fn env_cmd() -> Command { + let mut cmd = Command::new("/system/bin/sh"); + cmd.arg("-c").arg("set"); + cmd +} + +#[cfg(windows)] +pub fn env_cmd() -> Command { + let mut cmd = Command::new("cmd"); + cmd.arg("/c").arg("set"); + cmd +} + +fn main() { + // save original environment + let old_env = env::var_os("RUN_TEST_NEW_ENV"); + + env::set_var("RUN_TEST_NEW_ENV", "123"); + + // create filtered environment vector + let filtered_env : HashMap = + env::vars().filter(|&(ref k, _)| k == "PATH").collect(); + + let mut cmd = env_cmd(); + cmd.env_clear(); + cmd.envs(&filtered_env); + + // restore original environment + match old_env { + None => env::remove_var("RUN_TEST_NEW_ENV"), + Some(val) => env::set_var("RUN_TEST_NEW_ENV", &val) + } + + let result = cmd.output().unwrap(); + let output = String::from_utf8_lossy(&result.stdout); + + assert!(!output.contains("RUN_TEST_NEW_ENV"), + "found RUN_TEST_NEW_ENV inside of:\n\n{}", output); +} diff --git a/tests/ui/process/process-exit.rs b/tests/ui/process/process-exit.rs new file mode 100644 index 000000000..d193e073e --- /dev/null +++ b/tests/ui/process/process-exit.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_imports)] +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::process::{self, Command, Stdio}; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + child(); + } else { + parent(); + } +} + +fn parent() { + let args: Vec = env::args().collect(); + let status = Command::new(&args[0]).arg("child").status().unwrap(); + assert_eq!(status.code(), Some(2)); +} + +fn child() -> i32 { + process::exit(2); +} diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs new file mode 100644 index 000000000..da2683121 --- /dev/null +++ b/tests/ui/process/process-panic-after-fork.rs @@ -0,0 +1,197 @@ +// run-pass +// no-prefer-dynamic +// ignore-wasm32-bare no libc +// ignore-windows +// ignore-sgx no libc +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia no fork + +#![feature(rustc_private)] +#![feature(never_type)] +#![feature(panic_always_abort)] + +extern crate libc; + +use std::alloc::{GlobalAlloc, Layout}; +use std::fmt; +use std::panic::{self, panic_any}; +use std::os::unix::process::{CommandExt, ExitStatusExt}; +use std::process::{self, Command, ExitStatus}; +use std::sync::atomic::{AtomicU32, Ordering}; + +use libc::c_int; + +/// This stunt allocator allows us to spot heap allocations in the child. +struct PidChecking { + parent: A, + require_pid: AtomicU32, +} + +#[global_allocator] +static ALLOCATOR: PidChecking = PidChecking { + parent: std::alloc::System, + require_pid: AtomicU32::new(0), +}; + +impl PidChecking { + fn engage(&self) { + let parent_pid = process::id(); + eprintln!("engaging allocator trap, parent pid={}", parent_pid); + self.require_pid.store(parent_pid, Ordering::Release); + } + fn check(&self) { + let require_pid = self.require_pid.load(Ordering::Acquire); + if require_pid != 0 { + let actual_pid = process::id(); + if require_pid != actual_pid { + unsafe { + libc::raise(libc::SIGUSR1); + } + } + } + } +} + +unsafe impl GlobalAlloc for PidChecking { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + self.check(); + self.parent.alloc(layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + self.check(); + self.parent.dealloc(ptr, layout) + } + + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + self.check(); + self.parent.alloc_zeroed(layout) + } + + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + self.check(); + self.parent.realloc(ptr, layout, new_size) + } +} + +fn expect_aborted(status: ExitStatus) { + dbg!(status); + let signal = status.signal().expect("expected child process to die of signal"); + + #[cfg(not(target_os = "android"))] + assert!(signal == libc::SIGABRT || signal == libc::SIGILL || signal == libc::SIGTRAP); + + #[cfg(target_os = "android")] + { + assert!(signal == libc::SIGABRT || signal == libc::SIGSEGV); + + if signal == libc::SIGSEGV { + // Pre-KitKat versions of Android signal an abort() with SIGSEGV at address 0xdeadbaad + // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc + // + // This behavior was changed in KitKat to send a standard SIGABRT signal. + // See: https://r.android.com/60341 + // + // Additional checks performed: + // 1. Find last tombstone (similar to coredump but in text format) from the + // same executable (path) as we are (must be because of usage of fork): + // This ensures that we look into the correct tombstone. + // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad. + // 3. libc::abort call is in one of top two functions on callstack. + // The last two steps distinguish between a normal SIGSEGV and one caused + // by libc::abort. + + let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap(); + let exe_string = format!(">>> {this_exe} <<<"); + let tombstone = (0..100) + .map(|n| format!("/data/tombstones/tombstone_{n:02}")) + .filter(|f| std::path::Path::new(&f).exists()) + .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file")) + .filter(|f| f.contains(&exe_string)) + .last() + .expect("no tombstone found"); + + println!("Content of tombstone:\n{tombstone}"); + + assert!(tombstone + .contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad")); + let abort_on_top = tombstone + .lines() + .skip_while(|l| !l.contains("backtrace:")) + .skip(1) + .take_while(|l| l.starts_with(" #")) + .take(2) + .any(|f| f.contains("/system/lib/libc.so (abort")); + assert!(abort_on_top); + } + } +} + +fn main() { + ALLOCATOR.engage(); + + fn run(do_panic: &dyn Fn()) -> ExitStatus { + let child = unsafe { libc::fork() }; + assert!(child >= 0); + if child == 0 { + panic::always_abort(); + do_panic(); + process::exit(0); + } + let mut status: c_int = 0; + let got = unsafe { libc::waitpid(child, &mut status, 0) }; + assert_eq!(got, child); + let status = ExitStatus::from_raw(status.into()); + status + } + + fn one(do_panic: &dyn Fn()) { + let status = run(do_panic); + expect_aborted(status); + } + + one(&|| panic!()); + one(&|| panic!("some message")); + one(&|| panic!("message with argument: {}", 42)); + + #[derive(Debug)] + struct Wotsit { } + one(&|| panic_any(Wotsit { })); + + let mut c = Command::new("echo"); + unsafe { + c.pre_exec(|| panic!("{}", "crash now!")); + } + let st = c.status().expect("failed to get command status"); + expect_aborted(st); + + struct DisplayWithHeap; + impl fmt::Display for DisplayWithHeap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + let s = vec![0; 100]; + let s = std::hint::black_box(s); + write!(f, "{:?}", s) + } + } + + // Some panics in the stdlib that we want not to allocate, as + // otherwise these facilities become impossible to use in the + // child after fork, which is really quite awkward. + + one(&|| { None::.unwrap(); }); + one(&|| { None::.expect("unwrapped a none"); }); + one(&|| { std::str::from_utf8(b"\xff").unwrap(); }); + one(&|| { + let x = [0, 1, 2, 3]; + let y = x[std::hint::black_box(4)]; + let _z = std::hint::black_box(y); + }); + + // Finally, check that our stunt allocator can actually catch an allocation after fork. + // ie, that our test is effective. + + let status = run(&|| panic!("allocating to display... {}", DisplayWithHeap)); + dbg!(status); + assert_eq!(status.signal(), Some(libc::SIGUSR1)); +} diff --git a/tests/ui/process/process-remove-from-env.rs b/tests/ui/process/process-remove-from-env.rs new file mode 100644 index 000000000..ad027d685 --- /dev/null +++ b/tests/ui/process/process-remove-from-env.rs @@ -0,0 +1,48 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-vxworks no 'env' +// ignore-fuchsia no 'env' + +use std::process::Command; +use std::env; + +#[cfg(all(unix, not(target_os="android")))] +pub fn env_cmd() -> Command { + Command::new("env") +} +#[cfg(target_os="android")] +pub fn env_cmd() -> Command { + let mut cmd = Command::new("/system/bin/sh"); + cmd.arg("-c").arg("set"); + cmd +} + +#[cfg(windows)] +pub fn env_cmd() -> Command { + let mut cmd = Command::new("cmd"); + cmd.arg("/c").arg("set"); + cmd +} + +fn main() { + // save original environment + let old_env = env::var_os("RUN_TEST_NEW_ENV"); + + env::set_var("RUN_TEST_NEW_ENV", "123"); + + let mut cmd = env_cmd(); + cmd.env_remove("RUN_TEST_NEW_ENV"); + + // restore original environment + match old_env { + None => env::remove_var("RUN_TEST_NEW_ENV"), + Some(val) => env::set_var("RUN_TEST_NEW_ENV", &val) + } + + let result = cmd.output().unwrap(); + let output = String::from_utf8_lossy(&result.stdout); + + assert!(!output.contains("RUN_TEST_NEW_ENV"), + "found RUN_TEST_NEW_ENV inside of:\n\n{}", output); +} diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs new file mode 100644 index 000000000..107eba45d --- /dev/null +++ b/tests/ui/process/process-sigpipe.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(unused_imports)] +#![allow(deprecated)] + +// ignore-android since the dynamic linker sets a SIGPIPE handler (to do +// a crash report) so inheritance is moot on the entire platform + +// libstd ignores SIGPIPE, and other libraries may set signal masks. +// Make sure that these behaviors don't get inherited to children +// spawned via std::process, since they're needed for traditional UNIX +// filter behavior. This test checks that `yes | head` terminates +// (instead of running forever), and that it does not print an error +// message about a broken pipe. + +// ignore-emscripten no threads support +// ignore-vxworks no 'sh' +// ignore-fuchsia no 'sh' + +use std::process; +use std::thread; + +#[cfg(unix)] +fn main() { + // Just in case `yes` doesn't check for EPIPE... + thread::spawn(|| { + thread::sleep_ms(5000); + process::exit(1); + }); + let output = process::Command::new("sh").arg("-c").arg("yes | head").output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.len() == 0); +} + +#[cfg(not(unix))] +fn main() { + // Not worried about signal masks on other platforms +} diff --git a/tests/ui/process/process-spawn-nonexistent.rs b/tests/ui/process/process-spawn-nonexistent.rs new file mode 100644 index 000000000..9dd608986 --- /dev/null +++ b/tests/ui/process/process-spawn-nonexistent.rs @@ -0,0 +1,17 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia ErrorKind not translated + +use std::io::ErrorKind; +use std::process::Command; + +fn main() { + let result = Command::new("nonexistent").spawn().unwrap_err().kind(); + + assert!(matches!( + result, + // Under WSL with appendWindowsPath=true, this fails with PermissionDenied + ErrorKind::NotFound | ErrorKind::PermissionDenied + )); +} diff --git a/tests/ui/process/process-spawn-with-unicode-params.rs b/tests/ui/process/process-spawn-with-unicode-params.rs new file mode 100644 index 000000000..16dba6292 --- /dev/null +++ b/tests/ui/process/process-spawn-with-unicode-params.rs @@ -0,0 +1,77 @@ +// run-pass +// no-prefer-dynamic + +// The test copies itself into a subdirectory with a non-ASCII name and then +// runs it as a child process within the subdirectory. The parent process +// also adds an environment variable and an argument, both containing +// non-ASCII characters. The child process ensures all the strings are +// intact. + +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia Filesystem manipulation privileged + +use std::io::prelude::*; +use std::io; +use std::fs; +use std::process::Command; +use std::env; +use std::path::Path; + +fn main() { + let my_args = env::args().collect::>(); + let my_cwd = env::current_dir().unwrap(); + let my_env = env::vars().collect::>(); + let my_path = env::current_exe().unwrap(); + let my_dir = my_path.parent().unwrap(); + let my_ext = my_path.extension().and_then(|s| s.to_str()).unwrap_or(""); + + // some non-ASCII characters + let blah = "\u{3c0}\u{42f}\u{97f3}\u{e6}\u{221e}"; + + let child_name = "child"; + let child_dir = format!("process-spawn-with-unicode-params-{}", blah); + + // parameters sent to child / expected to be received from parent + let arg = blah; + let cwd = my_dir.join(&child_dir); + let env = ("RUST_TEST_PROC_SPAWN_UNICODE".to_string(), blah.to_string()); + + // am I the parent or the child? + if my_args.len() == 1 { // parent + + let child_filestem = Path::new(child_name); + let child_filename = child_filestem.with_extension(my_ext); + let child_path = cwd.join(&child_filename); + + // make a separate directory for the child + let _ = fs::create_dir(&cwd); + fs::copy(&my_path, &child_path).unwrap(); + + // run child + let p = Command::new(&child_path) + .arg(arg) + .current_dir(&cwd) + .env(&env.0, &env.1) + .spawn().unwrap().wait_with_output().unwrap(); + + // display the output + io::stdout().write_all(&p.stdout).unwrap(); + io::stderr().write_all(&p.stderr).unwrap(); + + // make sure the child succeeded + assert!(p.status.success()); + + } else { // child + + // check working directory (don't try to compare with `cwd` here!) + assert!(my_cwd.ends_with(&child_dir)); + + // check arguments + assert_eq!(&*my_args[1], arg); + + // check environment variable + assert!(my_env.contains(&env)); + + }; +} diff --git a/tests/ui/process/process-status-inherits-stdin.rs b/tests/ui/process/process-status-inherits-stdin.rs new file mode 100644 index 000000000..7719dd9ad --- /dev/null +++ b/tests/ui/process/process-status-inherits-stdin.rs @@ -0,0 +1,35 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::io; +use std::io::Write; +use std::process::{Command, Stdio}; + +fn main() { + let mut args = env::args(); + let me = args.next().unwrap(); + let arg = args.next(); + match arg.as_ref().map(|s| &s[..]) { + None => { + let mut s = Command::new(&me) + .arg("a1") + .stdin(Stdio::piped()) + .spawn() + .unwrap(); + s.stdin.take().unwrap().write_all(b"foo\n").unwrap(); + let s = s.wait().unwrap(); + assert!(s.success()); + } + Some("a1") => { + let s = Command::new(&me).arg("a2").status().unwrap(); + assert!(s.success()); + } + Some(..) => { + let mut s = String::new(); + io::stdin().read_line(&mut s).unwrap(); + assert_eq!(s, "foo\n"); + } + } +} diff --git a/tests/ui/process/signal-exit-status.rs b/tests/ui/process/signal-exit-status.rs new file mode 100644 index 000000000..9519ed7b4 --- /dev/null +++ b/tests/ui/process/signal-exit-status.rs @@ -0,0 +1,19 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-windows +// ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#58590) + +use std::env; +use std::process::Command; + +pub fn main() { + let args: Vec = env::args().collect(); + if args.len() >= 2 && args[1] == "signal" { + // Raise a segfault. + unsafe { *(1 as *mut isize) = 0; } + } else { + let status = Command::new(&args[0]).arg("signal").status().unwrap(); + assert!(status.code().is_none()); + } +} diff --git a/tests/ui/process/sigpipe-should-be-ignored.rs b/tests/ui/process/sigpipe-should-be-ignored.rs new file mode 100644 index 000000000..144eeca23 --- /dev/null +++ b/tests/ui/process/sigpipe-should-be-ignored.rs @@ -0,0 +1,33 @@ +// run-pass + +#![allow(unused_must_use)] +// Be sure that when a SIGPIPE would have been received that the entire process +// doesn't die in a ball of fire, but rather it's gracefully handled. + +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::io::prelude::*; +use std::io; +use std::process::{Command, Stdio}; + +fn test() { + let _ = io::stdin().read_line(&mut String::new()); + io::stdout().write(&[1]); + assert!(io::stdout().flush().is_err()); +} + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "test" { + return test(); + } + + let mut p = Command::new(&args[0]) + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) + .arg("test").spawn().unwrap(); + drop(p.stdout.take()); + assert!(p.wait().unwrap().success()); +} diff --git a/tests/ui/process/tls-exit-status.rs b/tests/ui/process/tls-exit-status.rs new file mode 100644 index 000000000..6296e5042 --- /dev/null +++ b/tests/ui/process/tls-exit-status.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:nonzero +// exec-env:RUST_NEWRT=1 +// ignore-emscripten no processes + +use std::env; + +fn main() { + env::args(); + panic!("please have a nonzero exit status"); +} diff --git a/tests/ui/process/try-wait.rs b/tests/ui/process/try-wait.rs new file mode 100644 index 000000000..692197210 --- /dev/null +++ b/tests/ui/process/try-wait.rs @@ -0,0 +1,60 @@ +// run-pass + +#![allow(stable_features)] +// ignore-emscripten no processes +// ignore-sgx no processes + +#![feature(process_try_wait)] + +use std::env; +use std::process::Command; +use std::thread; +use std::time::Duration; + +fn main() { + let args = env::args().collect::>(); + if args.len() != 1 { + match &args[1][..] { + "sleep" => thread::sleep(Duration::new(1_000, 0)), + _ => {} + } + return + } + + let mut me = Command::new(env::current_exe().unwrap()) + .arg("sleep") + .spawn() + .unwrap(); + let maybe_status = me.try_wait().unwrap(); + assert!(maybe_status.is_none()); + let maybe_status = me.try_wait().unwrap(); + assert!(maybe_status.is_none()); + + me.kill().unwrap(); + me.wait().unwrap(); + + let status = me.try_wait().unwrap().unwrap(); + assert!(!status.success()); + let status = me.try_wait().unwrap().unwrap(); + assert!(!status.success()); + + let mut me = Command::new(env::current_exe().unwrap()) + .arg("return-quickly") + .spawn() + .unwrap(); + loop { + match me.try_wait() { + Ok(Some(res)) => { + assert!(res.success()); + break + } + Ok(None) => { + thread::sleep(Duration::from_millis(1)); + } + Err(e) => panic!("error in try_wait: {}", e), + } + } + + let status = me.try_wait().unwrap().unwrap(); + assert!(status.success()); +} diff --git a/tests/ui/project-cache-issue-31849.rs b/tests/ui/project-cache-issue-31849.rs new file mode 100644 index 000000000..07fb6abae --- /dev/null +++ b/tests/ui/project-cache-issue-31849.rs @@ -0,0 +1,65 @@ +// run-pass +// Regression test for #31849: the problem here was actually a performance +// cliff, but I'm adding the test for reference. + +pub trait Upcast { + fn upcast(self) -> T; +} + +impl Upcast<(T1, T2)> for (S1,S2) + where S1: Upcast, + S2: Upcast, +{ + fn upcast(self) -> (T1, T2) { (self.0.upcast(), self.1.upcast()) } +} + +impl Upcast<()> for () +{ + fn upcast(self) -> () { () } +} + +pub trait ToStatic { + type Static: 'static; + fn to_static(self) -> Self::Static where Self: Sized; +} + +impl ToStatic for (T, U) + where T: ToStatic, + U: ToStatic +{ + type Static = (T::Static, U::Static); + fn to_static(self) -> Self::Static { (self.0.to_static(), self.1.to_static()) } +} + +impl ToStatic for () +{ + type Static = (); + fn to_static(self) -> () { () } +} + + +trait Factory { + type Output; + fn build(&self) -> Self::Output; +} + +impl Factory for (S, T) + where S: Factory, + T: Factory, + S::Output: ToStatic, + ::Static: Upcast, +{ + type Output = (S::Output, T::Output); + fn build(&self) -> Self::Output { (self.0.build().to_static().upcast(), self.1.build()) } +} + +impl Factory for () { + type Output = (); + fn build(&self) -> Self::Output { () } +} + +fn main() { + // More parens, more time. + let it = ((((((((((),()),()),()),()),()),()),()),()),()); + it.build(); +} diff --git a/tests/ui/ptr-coercion-rpass.rs b/tests/ui/ptr-coercion-rpass.rs new file mode 100644 index 000000000..1c3ce3303 --- /dev/null +++ b/tests/ui/ptr-coercion-rpass.rs @@ -0,0 +1,30 @@ +// run-pass + +#![allow(unused_variables)] +// Test coercions between pointers which don't do anything fancy like unsizing. + +// pretty-expanded FIXME #23616 + +pub fn main() { + // &mut -> & + let x: &mut isize = &mut 42; + let x: &isize = x; + + let x: &isize = &mut 42; + + // & -> *const + let x: &isize = &42; + let x: *const isize = x; + + let x: *const isize = &42; + + // &mut -> *const + let x: &mut isize = &mut 42; + let x: *const isize = x; + + let x: *const isize = &mut 42; + + // *mut -> *const + let x: *mut isize = &mut 42; + let x: *const isize = x; +} diff --git a/tests/ui/ptr-coercion.rs b/tests/ui/ptr-coercion.rs new file mode 100644 index 000000000..193899034 --- /dev/null +++ b/tests/ui/ptr-coercion.rs @@ -0,0 +1,23 @@ +// Test coercions between pointers which don't do anything fancy like unsizing. +// These are testing that we don't lose mutability when converting to raw pointers. + +pub fn main() { + // *const -> *mut + let x: *const isize = &42; + let x: *mut isize = x; //~ ERROR mismatched types + //~| expected raw pointer `*mut isize` + //~| found raw pointer `*const isize` + //~| types differ in mutability + + // & -> *mut + let x: *mut isize = &42; //~ ERROR mismatched types + //~| expected raw pointer `*mut isize` + //~| found reference `&isize` + //~| types differ in mutability + + let x: *const isize = &42; + let x: *mut isize = x; //~ ERROR mismatched types + //~| expected raw pointer `*mut isize` + //~| found raw pointer `*const isize` + //~| types differ in mutability +} diff --git a/tests/ui/ptr-coercion.stderr b/tests/ui/ptr-coercion.stderr new file mode 100644 index 000000000..29b7e5da8 --- /dev/null +++ b/tests/ui/ptr-coercion.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/ptr-coercion.rs:7:25 + | +LL | let x: *mut isize = x; + | ---------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut isize` + found raw pointer `*const isize` + +error[E0308]: mismatched types + --> $DIR/ptr-coercion.rs:13:25 + | +LL | let x: *mut isize = &42; + | ---------- ^^^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut isize` + found reference `&isize` + +error[E0308]: mismatched types + --> $DIR/ptr-coercion.rs:19:25 + | +LL | let x: *mut isize = x; + | ---------- ^ types differ in mutability + | | + | expected due to this + | + = note: expected raw pointer `*mut isize` + found raw pointer `*const isize` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/ptr_ops/issue-80309-safe.rs b/tests/ui/ptr_ops/issue-80309-safe.rs new file mode 100644 index 000000000..8a4ff1669 --- /dev/null +++ b/tests/ui/ptr_ops/issue-80309-safe.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -O + +// Regression test for issue #80309 + +pub fn zero(x: usize) -> usize { + std::ptr::null::().wrapping_add(x) as usize - x +} +pub fn qux(x: &[i8]) -> i8 { + x[zero(x.as_ptr() as usize)] +} + +fn main() { + let z = vec![42, 43]; + println!("{}", qux(&z)); +} diff --git a/tests/ui/ptr_ops/issue-80309.rs b/tests/ui/ptr_ops/issue-80309.rs new file mode 100644 index 000000000..c13ce3c9c --- /dev/null +++ b/tests/ui/ptr_ops/issue-80309.rs @@ -0,0 +1,13 @@ +// run-pass +// compile-flags: -O + +// Regression test for issue #80309 + +pub unsafe fn foo(x: *const i8) -> i8 { + *x.wrapping_sub(x as _).wrapping_add(x as _) +} + +fn main() { + let x = 42; + println!("{}", unsafe { foo(&x) }); +} diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs new file mode 100644 index 000000000..67f888c5e --- /dev/null +++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs @@ -0,0 +1,28 @@ +#![allow(non_camel_case_types)] // genus is always capitalized + +pub(crate) struct Snail; +//~^ NOTE `Snail` declared as private + +mod sea { + pub(super) struct Turtle; + //~^ NOTE `Turtle` declared as crate-private +} + +struct Tortoise; +//~^ NOTE `Tortoise` declared as private + +pub struct Shell { + pub(crate) creature: T, +} + +pub type Helix_pomatia = Shell; +//~^ ERROR private type `Snail` in public interface +//~| NOTE can't leak private type +pub type Dermochelys_coriacea = Shell; +//~^ ERROR crate-private type `Turtle` in public interface +//~| NOTE can't leak crate-private type +pub type Testudo_graeca = Shell; +//~^ ERROR private type `Tortoise` in public interface +//~| NOTE can't leak private type + +fn main() {} diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr new file mode 100644 index 000000000..39d4f5ac8 --- /dev/null +++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr @@ -0,0 +1,30 @@ +error[E0446]: private type `Snail` in public interface + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:18:1 + | +LL | pub(crate) struct Snail; + | ----------------------- `Snail` declared as private +... +LL | pub type Helix_pomatia = Shell; + | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error[E0446]: crate-private type `Turtle` in public interface + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:21:1 + | +LL | pub(super) struct Turtle; + | ------------------------ `Turtle` declared as crate-private +... +LL | pub type Dermochelys_coriacea = Shell; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-private type + +error[E0446]: private type `Tortoise` in public interface + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:24:1 + | +LL | struct Tortoise; + | --------------- `Tortoise` declared as private +... +LL | pub type Testudo_graeca = Shell; + | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/pub/pub-ident-fn-2.fixed b/tests/ui/pub/pub-ident-fn-2.fixed new file mode 100644 index 000000000..afd75a41f --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-2.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +pub fn foo(_s: usize) { bar() } +//~^ ERROR missing `fn` for function definition + +fn bar() {} + +fn main() { + foo(2); +} diff --git a/tests/ui/pub/pub-ident-fn-2.rs b/tests/ui/pub/pub-ident-fn-2.rs new file mode 100644 index 000000000..e7b86a909 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-2.rs @@ -0,0 +1,10 @@ +// run-rustfix + +pub foo(_s: usize) { bar() } +//~^ ERROR missing `fn` for function definition + +fn bar() {} + +fn main() { + foo(2); +} diff --git a/tests/ui/pub/pub-ident-fn-2.stderr b/tests/ui/pub/pub-ident-fn-2.stderr new file mode 100644 index 000000000..b5b667b41 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-2.stderr @@ -0,0 +1,13 @@ +error: missing `fn` for function definition + --> $DIR/pub-ident-fn-2.rs:3:4 + | +LL | pub foo(_s: usize) { bar() } + | ^ + | +help: add `fn` here to parse `foo` as a public function + | +LL | pub fn foo(_s: usize) { bar() } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-fn-3.rs b/tests/ui/pub/pub-ident-fn-3.rs new file mode 100644 index 000000000..fdbea7cf4 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-3.rs @@ -0,0 +1,8 @@ +// #60115 + +mod foo { + pub bar(); + //~^ ERROR missing `fn` or `struct` for function or struct definition +} + +fn main() {} diff --git a/tests/ui/pub/pub-ident-fn-3.stderr b/tests/ui/pub/pub-ident-fn-3.stderr new file mode 100644 index 000000000..6d3d4e592 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-3.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for function or struct definition + --> $DIR/pub-ident-fn-3.rs:4:8 + | +LL | pub bar(); + | ---^--- help: if you meant to call a macro, try: `bar!` + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-fn-or-struct-2.rs b/tests/ui/pub/pub-ident-fn-or-struct-2.rs new file mode 100644 index 000000000..8f67cdd29 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-or-struct-2.rs @@ -0,0 +1,4 @@ +pub S(); +//~^ ERROR missing `fn` or `struct` for function or struct definition + +fn main() {} diff --git a/tests/ui/pub/pub-ident-fn-or-struct-2.stderr b/tests/ui/pub/pub-ident-fn-or-struct-2.stderr new file mode 100644 index 000000000..047e66b18 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-or-struct-2.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for function or struct definition + --> $DIR/pub-ident-fn-or-struct-2.rs:1:4 + | +LL | pub S(); + | ---^- help: if you meant to call a macro, try: `S!` + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-fn-or-struct.rs b/tests/ui/pub/pub-ident-fn-or-struct.rs new file mode 100644 index 000000000..832831d29 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-or-struct.rs @@ -0,0 +1,4 @@ +pub S (foo) bar +//~^ ERROR missing `fn` or `struct` for function or struct definition + +fn main() {} diff --git a/tests/ui/pub/pub-ident-fn-or-struct.stderr b/tests/ui/pub/pub-ident-fn-or-struct.stderr new file mode 100644 index 000000000..c4a196eb2 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-or-struct.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for function or struct definition + --> $DIR/pub-ident-fn-or-struct.rs:1:4 + | +LL | pub S (foo) bar + | ---^- help: if you meant to call a macro, try: `S!` + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime-2.rs b/tests/ui/pub/pub-ident-fn-with-lifetime-2.rs new file mode 100644 index 000000000..1ee8c84f1 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-with-lifetime-2.rs @@ -0,0 +1,6 @@ +pub bar<'a>(&self, _s: &'a usize) -> bool { true } +//~^ ERROR missing `fn` for method definition + +fn main() { + bar(2); +} diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr b/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr new file mode 100644 index 000000000..6a9aeaf4a --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-with-lifetime-2.stderr @@ -0,0 +1,13 @@ +error: missing `fn` for method definition + --> $DIR/pub-ident-fn-with-lifetime-2.rs:1:4 + | +LL | pub bar<'a>(&self, _s: &'a usize) -> bool { true } + | ^^^ + | +help: add `fn` here to parse `bar` as a public method + | +LL | pub fn bar<'a>(&self, _s: &'a usize) -> bool { true } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.fixed b/tests/ui/pub/pub-ident-fn-with-lifetime.fixed new file mode 100644 index 000000000..e510ace5f --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-with-lifetime.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn foo<'a>(_s: &'a usize) -> bool { true } +//~^ ERROR missing `fn` for function definition + +fn main() { + foo(&2); +} diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.rs b/tests/ui/pub/pub-ident-fn-with-lifetime.rs new file mode 100644 index 000000000..63e6eca15 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-with-lifetime.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub foo<'a>(_s: &'a usize) -> bool { true } +//~^ ERROR missing `fn` for function definition + +fn main() { + foo(&2); +} diff --git a/tests/ui/pub/pub-ident-fn-with-lifetime.stderr b/tests/ui/pub/pub-ident-fn-with-lifetime.stderr new file mode 100644 index 000000000..c1ca0136b --- /dev/null +++ b/tests/ui/pub/pub-ident-fn-with-lifetime.stderr @@ -0,0 +1,13 @@ +error: missing `fn` for function definition + --> $DIR/pub-ident-fn-with-lifetime.rs:3:4 + | +LL | pub foo<'a>(_s: &'a usize) -> bool { true } + | ^^^ + | +help: add `fn` here to parse `foo` as a public function + | +LL | pub fn foo<'a>(_s: &'a usize) -> bool { true } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-fn.fixed b/tests/ui/pub/pub-ident-fn.fixed new file mode 100644 index 000000000..65ed8c7b4 --- /dev/null +++ b/tests/ui/pub/pub-ident-fn.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn foo(_s: usize) -> bool { true } +//~^ ERROR missing `fn` for function definition + +fn main() { + foo(2); +} diff --git a/tests/ui/pub/pub-ident-fn.rs b/tests/ui/pub/pub-ident-fn.rs new file mode 100644 index 000000000..2fe4d34fb --- /dev/null +++ b/tests/ui/pub/pub-ident-fn.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub foo(_s: usize) -> bool { true } +//~^ ERROR missing `fn` for function definition + +fn main() { + foo(2); +} diff --git a/tests/ui/pub/pub-ident-fn.stderr b/tests/ui/pub/pub-ident-fn.stderr new file mode 100644 index 000000000..cb94c48ad --- /dev/null +++ b/tests/ui/pub/pub-ident-fn.stderr @@ -0,0 +1,13 @@ +error: missing `fn` for function definition + --> $DIR/pub-ident-fn.rs:3:4 + | +LL | pub foo(_s: usize) -> bool { true } + | ^^^ + | +help: add `fn` here to parse `foo` as a public function + | +LL | pub fn foo(_s: usize) -> bool { true } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-struct-with-lifetime.rs b/tests/ui/pub/pub-ident-struct-with-lifetime.rs new file mode 100644 index 000000000..2feb02660 --- /dev/null +++ b/tests/ui/pub/pub-ident-struct-with-lifetime.rs @@ -0,0 +1,4 @@ +pub S<'a> { +//~^ ERROR missing `struct` for struct definition +} +fn main() {} diff --git a/tests/ui/pub/pub-ident-struct-with-lifetime.stderr b/tests/ui/pub/pub-ident-struct-with-lifetime.stderr new file mode 100644 index 000000000..562b68e35 --- /dev/null +++ b/tests/ui/pub/pub-ident-struct-with-lifetime.stderr @@ -0,0 +1,13 @@ +error: missing `struct` for struct definition + --> $DIR/pub-ident-struct-with-lifetime.rs:1:4 + | +LL | pub S<'a> { + | ^ + | +help: add `struct` here to parse `S` as a public struct + | +LL | pub struct S<'a> { + | ++++++ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-struct.fixed b/tests/ui/pub/pub-ident-struct.fixed new file mode 100644 index 000000000..58cde8fd6 --- /dev/null +++ b/tests/ui/pub/pub-ident-struct.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +pub struct S { +//~^ ERROR missing `struct` for struct definition +} +fn main() {} diff --git a/tests/ui/pub/pub-ident-struct.rs b/tests/ui/pub/pub-ident-struct.rs new file mode 100644 index 000000000..3930e556e --- /dev/null +++ b/tests/ui/pub/pub-ident-struct.rs @@ -0,0 +1,6 @@ +// run-rustfix + +pub S { +//~^ ERROR missing `struct` for struct definition +} +fn main() {} diff --git a/tests/ui/pub/pub-ident-struct.stderr b/tests/ui/pub/pub-ident-struct.stderr new file mode 100644 index 000000000..d3a378786 --- /dev/null +++ b/tests/ui/pub/pub-ident-struct.stderr @@ -0,0 +1,13 @@ +error: missing `struct` for struct definition + --> $DIR/pub-ident-struct.rs:3:4 + | +LL | pub S { + | ^ + | +help: add `struct` here to parse `S` as a public struct + | +LL | pub struct S { + | ++++++ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-ident-with-lifetime-incomplete.rs b/tests/ui/pub/pub-ident-with-lifetime-incomplete.rs new file mode 100644 index 000000000..c86a9f2fd --- /dev/null +++ b/tests/ui/pub/pub-ident-with-lifetime-incomplete.rs @@ -0,0 +1,5 @@ +fn main() { +} + +pub foo<'a> +//~^ ERROR missing `fn` or `struct` for function or struct definition diff --git a/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr b/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr new file mode 100644 index 000000000..0e0b12705 --- /dev/null +++ b/tests/ui/pub/pub-ident-with-lifetime-incomplete.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for function or struct definition + --> $DIR/pub-ident-with-lifetime-incomplete.rs:4:4 + | +LL | pub foo<'a> + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.rs b/tests/ui/pub/pub-reexport-priv-extern-crate.rs new file mode 100644 index 000000000..dd5cd420f --- /dev/null +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.rs @@ -0,0 +1,20 @@ +extern crate core; +pub use core as reexported_core; //~ ERROR `core` is private, and cannot be re-exported + //~^ WARN this was previously accepted + +mod foo1 { + extern crate core; +} + +mod foo2 { + use foo1::core; //~ ERROR crate import `core` is private + pub mod bar { + extern crate core; + } +} + +mod baz { + pub use foo2::bar::core; //~ ERROR crate import `core` is private +} + +fn main() {} diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr new file mode 100644 index 000000000..c7fadc6f9 --- /dev/null +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr @@ -0,0 +1,37 @@ +error[E0603]: crate import `core` is private + --> $DIR/pub-reexport-priv-extern-crate.rs:10:15 + | +LL | use foo1::core; + | ^^^^ private crate import + | +note: the crate import `core` is defined here + --> $DIR/pub-reexport-priv-extern-crate.rs:6:5 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ + +error[E0603]: crate import `core` is private + --> $DIR/pub-reexport-priv-extern-crate.rs:17:24 + | +LL | pub use foo2::bar::core; + | ^^^^ private crate import + | +note: the crate import `core` is defined here + --> $DIR/pub-reexport-priv-extern-crate.rs:12:9 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ + +error: extern crate `core` is private, and cannot be re-exported (error E0365), consider declaring with `pub` + --> $DIR/pub-reexport-priv-extern-crate.rs:2:9 + | +LL | pub use core as reexported_core; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + = note: `#[deny(pub_use_of_private_extern_crate)]` on by default + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/pub/pub-restricted-error-fn.rs b/tests/ui/pub/pub-restricted-error-fn.rs new file mode 100644 index 000000000..fc1aeae2b --- /dev/null +++ b/tests/ui/pub/pub-restricted-error-fn.rs @@ -0,0 +1,2 @@ +pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` is not followed by an item +//~^ ERROR expected item, found `(` diff --git a/tests/ui/pub/pub-restricted-error-fn.stderr b/tests/ui/pub/pub-restricted-error-fn.stderr new file mode 100644 index 000000000..0511a821a --- /dev/null +++ b/tests/ui/pub/pub-restricted-error-fn.stderr @@ -0,0 +1,16 @@ +error: visibility `pub(crate)` is not followed by an item + --> $DIR/pub-restricted-error-fn.rs:1:1 + | +LL | pub(crate) () fn foo() {} + | ^^^^^^^^^^ the visibility + | + = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}` + +error: expected item, found `(` + --> $DIR/pub-restricted-error-fn.rs:1:12 + | +LL | pub(crate) () fn foo() {} + | ^ expected item + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pub/pub-restricted-error.rs b/tests/ui/pub/pub-restricted-error.rs new file mode 100644 index 000000000..60fce3f51 --- /dev/null +++ b/tests/ui/pub/pub-restricted-error.rs @@ -0,0 +1,7 @@ +struct Bar(pub(())); + +struct Foo { + pub(crate) () foo: usize, //~ ERROR expected identifier +} + +fn main() {} diff --git a/tests/ui/pub/pub-restricted-error.stderr b/tests/ui/pub/pub-restricted-error.stderr new file mode 100644 index 000000000..b47328f34 --- /dev/null +++ b/tests/ui/pub/pub-restricted-error.stderr @@ -0,0 +1,10 @@ +error: expected identifier, found `(` + --> $DIR/pub-restricted-error.rs:4:16 + | +LL | struct Foo { + | --- while parsing this struct +LL | pub(crate) () foo: usize, + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-restricted-non-path.rs b/tests/ui/pub/pub-restricted-non-path.rs new file mode 100644 index 000000000..bdad18dbe --- /dev/null +++ b/tests/ui/pub/pub-restricted-non-path.rs @@ -0,0 +1,5 @@ +#![feature(pub_restricted)] + +pub (.) fn afn() {} //~ ERROR expected identifier + +fn main() {} diff --git a/tests/ui/pub/pub-restricted-non-path.stderr b/tests/ui/pub/pub-restricted-non-path.stderr new file mode 100644 index 000000000..e0ea50621 --- /dev/null +++ b/tests/ui/pub/pub-restricted-non-path.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `.` + --> $DIR/pub-restricted-non-path.rs:3:6 + | +LL | pub (.) fn afn() {} + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/pub/pub-restricted.rs b/tests/ui/pub/pub-restricted.rs new file mode 100644 index 000000000..bcd21082f --- /dev/null +++ b/tests/ui/pub/pub-restricted.rs @@ -0,0 +1,31 @@ +mod a {} + +pub (a) fn afn() {} //~ incorrect visibility restriction +pub (b) fn bfn() {} //~ incorrect visibility restriction +pub (crate::a) fn cfn() {} //~ incorrect visibility restriction + +pub fn privfn() {} +mod x { + mod y { + pub (in x) fn foo() {} + pub (super) fn bar() {} + pub (crate) fn qux() {} + } +} + +mod y { + struct Foo { + pub (crate) c: usize, + pub (super) s: usize, + valid_private: usize, + pub (in y) valid_in_x: usize, + pub (a) invalid: usize, //~ incorrect visibility restriction + pub (in x) non_parent_invalid: usize, //~ ERROR visibilities can only be restricted + } +} + +fn main() {} + +// test multichar names +mod xyz {} +pub (xyz) fn xyz() {} //~ incorrect visibility restriction diff --git a/tests/ui/pub/pub-restricted.stderr b/tests/ui/pub/pub-restricted.stderr new file mode 100644 index 000000000..4694530e5 --- /dev/null +++ b/tests/ui/pub/pub-restricted.stderr @@ -0,0 +1,65 @@ +error[E0704]: incorrect visibility restriction + --> $DIR/pub-restricted.rs:3:6 + | +LL | pub (a) fn afn() {} + | ^ help: make this visible only to module `a` with `in`: `in a` + | + = help: some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path + +error[E0704]: incorrect visibility restriction + --> $DIR/pub-restricted.rs:4:6 + | +LL | pub (b) fn bfn() {} + | ^ help: make this visible only to module `b` with `in`: `in b` + | + = help: some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path + +error[E0704]: incorrect visibility restriction + --> $DIR/pub-restricted.rs:5:6 + | +LL | pub (crate::a) fn cfn() {} + | ^^^^^^^^ help: make this visible only to module `crate::a` with `in`: `in crate::a` + | + = help: some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path + +error[E0704]: incorrect visibility restriction + --> $DIR/pub-restricted.rs:22:14 + | +LL | pub (a) invalid: usize, + | ^ help: make this visible only to module `a` with `in`: `in a` + | + = help: some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path + +error[E0704]: incorrect visibility restriction + --> $DIR/pub-restricted.rs:31:6 + | +LL | pub (xyz) fn xyz() {} + | ^^^ help: make this visible only to module `xyz` with `in`: `in xyz` + | + = help: some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path + +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/pub-restricted.rs:23:17 + | +LL | pub (in x) non_parent_invalid: usize, + | ^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0704, E0742. +For more information about an error, try `rustc --explain E0704`. diff --git a/tests/ui/qualified/qualified-path-params-2.rs b/tests/ui/qualified/qualified-path-params-2.rs new file mode 100644 index 000000000..d0cc1fa3d --- /dev/null +++ b/tests/ui/qualified/qualified-path-params-2.rs @@ -0,0 +1,21 @@ +// Check that qualified paths with type parameters +// fail during type checking and not during parsing + +struct S; + +trait Tr { + type A; +} + +impl Tr for S { + type A = S; +} + +impl S { + fn f() {} +} + +type A = ::A::f; +//~^ ERROR ambiguous associated type + +fn main() {} diff --git a/tests/ui/qualified/qualified-path-params-2.stderr b/tests/ui/qualified/qualified-path-params-2.stderr new file mode 100644 index 000000000..b6cf19b82 --- /dev/null +++ b/tests/ui/qualified/qualified-path-params-2.stderr @@ -0,0 +1,14 @@ +error[E0223]: ambiguous associated type + --> $DIR/qualified-path-params-2.rs:18:10 + | +LL | type A = ::A::f; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `f` implemented for `::A`, you could use the fully-qualified path + | +LL | type A = <::A as Example>::f; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/qualified/qualified-path-params.rs b/tests/ui/qualified/qualified-path-params.rs new file mode 100644 index 000000000..e8a95a460 --- /dev/null +++ b/tests/ui/qualified/qualified-path-params.rs @@ -0,0 +1,25 @@ +// Check that qualified paths with type parameters +// fail during type checking and not during parsing + +struct S; + +trait Tr { + type A; +} + +impl Tr for S { + type A = S; +} + +impl S { + fn f() {} +} + +fn main() { + match 10 { + ::A::f:: => {} + //~^ ERROR expected unit struct, unit variant or constant, found associated function + 0 ..= ::A::f:: => {} + //~^ ERROR only `char` and numeric types are allowed in range + } +} diff --git a/tests/ui/qualified/qualified-path-params.stderr b/tests/ui/qualified/qualified-path-params.stderr new file mode 100644 index 000000000..a49ed6c8f --- /dev/null +++ b/tests/ui/qualified/qualified-path-params.stderr @@ -0,0 +1,18 @@ +error[E0533]: expected unit struct, unit variant or constant, found associated function `<::A>::f` + --> $DIR/qualified-path-params.rs:20:9 + | +LL | ::A::f:: => {} + | ^^^^^^^^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/qualified-path-params.rs:22:15 + | +LL | 0 ..= ::A::f:: => {} + | - ^^^^^^^^^^^^^^^^^^^^^ this is of type `fn() {S::f::}` but it should be `char` or numeric + | | + | this is of type `{integer}` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0029, E0533. +For more information about an error, try `rustc --explain E0029`. diff --git a/tests/ui/query-system/fn-sig-cycle-arity.rs b/tests/ui/query-system/fn-sig-cycle-arity.rs new file mode 100644 index 000000000..7a9b8469c --- /dev/null +++ b/tests/ui/query-system/fn-sig-cycle-arity.rs @@ -0,0 +1,8 @@ +trait Dancer { + fn dance(&self) -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + self.dance() + } +} + +fn main() {} diff --git a/tests/ui/query-system/fn-sig-cycle-arity.stderr b/tests/ui/query-system/fn-sig-cycle-arity.stderr new file mode 100644 index 000000000..67e0c2545 --- /dev/null +++ b/tests/ui/query-system/fn-sig-cycle-arity.stderr @@ -0,0 +1,9 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/fn-sig-cycle-arity.rs:2:24 + | +LL | fn dance(&self) -> _ { + | ^ not allowed in type signatures + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/query-system/issue-83479.rs b/tests/ui/query-system/issue-83479.rs new file mode 100644 index 000000000..32676dfe9 --- /dev/null +++ b/tests/ui/query-system/issue-83479.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +type PairCoupledTypes: Trait< + //~^ ERROR: bounds on `type`s in this context have no effect + //~| ERROR: cannot find trait `Trait` in this scope + [u32; { + static FOO: usize; //~ ERROR: free static item without body + }], +> = impl Trait< + //~^ ERROR: cannot find trait `Trait` in this scope + [u32; { + static FOO: usize; //~ ERROR: free static item without body + }], +>; + +fn main() {} diff --git a/tests/ui/query-system/issue-83479.stderr b/tests/ui/query-system/issue-83479.stderr new file mode 100644 index 000000000..7cb41f5cb --- /dev/null +++ b/tests/ui/query-system/issue-83479.stderr @@ -0,0 +1,44 @@ +error: bounds on `type`s in this context have no effect + --> $DIR/issue-83479.rs:3:24 + | +LL | type PairCoupledTypes: Trait< + | ________________________^ +LL | | +LL | | +LL | | [u32; { +LL | | static FOO: usize; +LL | | }], +LL | | > = impl Trait< + | |_^ + +error: free static item without body + --> $DIR/issue-83479.rs:7:9 + | +LL | static FOO: usize; + | ^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/issue-83479.rs:12:9 + | +LL | static FOO: usize; + | ^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/issue-83479.rs:3:24 + | +LL | type PairCoupledTypes: Trait< + | ^^^^^ not found in this scope + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/issue-83479.rs:9:10 + | +LL | > = impl Trait< + | ^^^^^ not found in this scope + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/query-system/query_depth.rs b/tests/ui/query-system/query_depth.rs new file mode 100644 index 000000000..e600c1c08 --- /dev/null +++ b/tests/ui/query-system/query_depth.rs @@ -0,0 +1,31 @@ +// build-fail + +#![recursion_limit = "64"] +type Byte = Option + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> + >>>> >>>> +>>>> >>>>; + +fn main() { +//~^ ERROR: queries overflow the depth limit! + println!("{}", std::mem::size_of::()); +} diff --git a/tests/ui/query-system/query_depth.stderr b/tests/ui/query-system/query_depth.stderr new file mode 100644 index 000000000..43a18b4e0 --- /dev/null +++ b/tests/ui/query-system/query_depth.stderr @@ -0,0 +1,11 @@ +error: queries overflow the depth limit! + --> $DIR/query_depth.rs:28:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`) + = note: query depth increased by 66 when computing layout of `core::option::Option>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + +error: aborting due to previous error + diff --git a/tests/ui/query-visibility.rs b/tests/ui/query-visibility.rs new file mode 100644 index 000000000..09a289d85 --- /dev/null +++ b/tests/ui/query-visibility.rs @@ -0,0 +1,9 @@ +// check-pass +// Check that it doesn't panic when `Input` gets its visibility checked. + +#![crate_type = "lib"] + +pub trait Layer< + /// Hello. + Input, +> {} diff --git a/tests/ui/range/exclusive-range-patterns-2021.rs b/tests/ui/range/exclusive-range-patterns-2021.rs new file mode 100644 index 000000000..de69c9bf2 --- /dev/null +++ b/tests/ui/range/exclusive-range-patterns-2021.rs @@ -0,0 +1,14 @@ +// edition:2021 + +fn main() { + let n = 2; + match n { + 0...3 => {} + //~^ ERROR `...` range patterns are deprecated + 4...10 => {} + //~^ ERROR `...` range patterns are deprecated + (11...100) => {} + //~^ ERROR `...` range patterns are deprecated + _ => {} + } +} diff --git a/tests/ui/range/exclusive-range-patterns-2021.stderr b/tests/ui/range/exclusive-range-patterns-2021.stderr new file mode 100644 index 000000000..a96743704 --- /dev/null +++ b/tests/ui/range/exclusive-range-patterns-2021.stderr @@ -0,0 +1,27 @@ +error[E0783]: `...` range patterns are deprecated + --> $DIR/exclusive-range-patterns-2021.rs:6:9 + | +LL | 0...3 => {} + | ^---^ + | | + | help: use `..=` for an inclusive range + +error[E0783]: `...` range patterns are deprecated + --> $DIR/exclusive-range-patterns-2021.rs:8:9 + | +LL | 4...10 => {} + | ^---^^ + | | + | help: use `..=` for an inclusive range + +error[E0783]: `...` range patterns are deprecated + --> $DIR/exclusive-range-patterns-2021.rs:10:10 + | +LL | (11...100) => {} + | ^^---^^^ + | | + | help: use `..=` for an inclusive range + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0783`. diff --git a/tests/ui/range/issue-54505-no-literals.fixed b/tests/ui/range/issue-54505-no-literals.fixed new file mode 100644 index 000000000..4d8f67182 --- /dev/null +++ b/tests/ui/range/issue-54505-no-literals.fixed @@ -0,0 +1,75 @@ +// run-rustfix + +// Regression test for changes introduced while fixing #54505 + +// This test uses non-literals for Ranges +// (expecting no parens with borrow suggestion) + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(&std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::Range { start: 0, end: 1 } + + take_range(&::std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 } + + take_range(&std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFrom { start: 1 } + + take_range(&::std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFrom { start: 1 } + + take_range(&std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFull {} + + take_range(&::std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFull {} + + take_range(&std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1) + + take_range(&::std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1) + + take_range(&std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeTo { end: 5 } + + take_range(&::std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeTo { end: 5 } + + take_range(&std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 } + + take_range(&::std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 } +} diff --git a/tests/ui/range/issue-54505-no-literals.rs b/tests/ui/range/issue-54505-no-literals.rs new file mode 100644 index 000000000..dc21dcbc2 --- /dev/null +++ b/tests/ui/range/issue-54505-no-literals.rs @@ -0,0 +1,75 @@ +// run-rustfix + +// Regression test for changes introduced while fixing #54505 + +// This test uses non-literals for Ranges +// (expecting no parens with borrow suggestion) + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::Range { start: 0, end: 1 } + + take_range(::std::ops::Range { start: 0, end: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::Range { start: 0, end: 1 } + + take_range(std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFrom { start: 1 } + + take_range(::std::ops::RangeFrom { start: 1 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFrom { start: 1 } + + take_range(std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeFull {} + + take_range(::std::ops::RangeFull {}); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeFull {} + + take_range(std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeInclusive::new(0, 1) + + take_range(::std::ops::RangeInclusive::new(0, 1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeInclusive::new(0, 1) + + take_range(std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeTo { end: 5 } + + take_range(::std::ops::RangeTo { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeTo { end: 5 } + + take_range(std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &std::ops::RangeToInclusive { end: 5 } + + take_range(::std::ops::RangeToInclusive { end: 5 }); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &::std::ops::RangeToInclusive { end: 5 } +} diff --git a/tests/ui/range/issue-54505-no-literals.stderr b/tests/ui/range/issue-54505-no-literals.stderr new file mode 100644 index 000000000..070dc8445 --- /dev/null +++ b/tests/ui/range/issue-54505-no-literals.stderr @@ -0,0 +1,219 @@ +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:16:16 + | +LL | take_range(std::ops::Range { start: 0, end: 1 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `Range` + | | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `std::ops::Range<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:21:16 + | +LL | take_range(::std::ops::Range { start: 0, end: 1 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `Range` + | | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `std::ops::Range<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:26:16 + | +LL | take_range(std::ops::RangeFrom { start: 1 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeFrom` + | | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFrom<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:31:16 + | +LL | take_range(::std::ops::RangeFrom { start: 1 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeFrom` + | | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFrom<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:36:16 + | +LL | take_range(std::ops::RangeFull {}); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeFull` + | | help: consider borrowing here: `&std::ops::RangeFull {}` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFull` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:41:16 + | +LL | take_range(::std::ops::RangeFull {}); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeFull` + | | help: consider borrowing here: `&::std::ops::RangeFull {}` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFull` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:46:16 + | +LL | take_range(std::ops::RangeInclusive::new(0, 1)); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeInclusive` + | | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:51:16 + | +LL | take_range(::std::ops::RangeInclusive::new(0, 1)); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeInclusive` + | | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:56:16 + | +LL | take_range(std::ops::RangeTo { end: 5 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeTo` + | | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeTo<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:61:16 + | +LL | take_range(::std::ops::RangeTo { end: 5 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeTo` + | | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeTo<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:66:16 + | +LL | take_range(std::ops::RangeToInclusive { end: 5 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeToInclusive` + | | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeToInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-literals.rs:71:16 + | +LL | take_range(::std::ops::RangeToInclusive { end: 5 }); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected reference, found struct `RangeToInclusive` + | | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeToInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-literals.rs:12:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/range/issue-54505-no-std.rs b/tests/ui/range/issue-54505-no-std.rs new file mode 100644 index 000000000..9f378b483 --- /dev/null +++ b/tests/ui/range/issue-54505-no-std.rs @@ -0,0 +1,58 @@ +// Regression test for #54505 - range borrowing suggestion had +// incorrect syntax (missing parentheses). + +// This test doesn't use std +// (so all Ranges resolve to core::ops::Range...) + +#![no_std] +#![feature(lang_items)] + +use core::ops::RangeBounds; + +#[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))] +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} +#[cfg(target_os = "emscripten")] +#[lang = "eh_catch_typeinfo"] +static EH_CATCH_TYPEINFO: u8 = 0; + +#[panic_handler] +fn panic_handler() {} +//~^ ERROR return type should be `!` +//~| ERROR function should have one argument + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(0..1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..1) + + take_range(1..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(1..) + + take_range(..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..) + + take_range(0..=1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..=1) + + take_range(..5); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..5) + + take_range(..=42); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..=42) +} diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr new file mode 100644 index 000000000..9fb0e54a8 --- /dev/null +++ b/tests/ui/range/issue-54505-no-std.stderr @@ -0,0 +1,123 @@ +error: return type should be `!` + --> $DIR/issue-54505-no-std.rs:20:20 + | +LL | fn panic_handler() {} + | ^ + +error: function should have one argument + --> $DIR/issue-54505-no-std.rs:20:1 + | +LL | fn panic_handler() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:29:16 + | +LL | take_range(0..1); + | ---------- ^^^^ + | | | + | | expected reference, found struct `Range` + | | help: consider borrowing here: `&(0..1)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `Range<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-std.rs:25:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:34:16 + | +LL | take_range(1..); + | ---------- ^^^ + | | | + | | expected reference, found struct `RangeFrom` + | | help: consider borrowing here: `&(1..)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFrom<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-std.rs:25:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:39:16 + | +LL | take_range(..); + | ---------- ^^ + | | | + | | expected reference, found struct `RangeFull` + | | help: consider borrowing here: `&(..)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFull` +note: function defined here + --> $DIR/issue-54505-no-std.rs:25:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:44:16 + | +LL | take_range(0..=1); + | ---------- ^^^^^ + | | | + | | expected reference, found struct `RangeInclusive` + | | help: consider borrowing here: `&(0..=1)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-std.rs:25:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:49:16 + | +LL | take_range(..5); + | ---------- ^^^ + | | | + | | expected reference, found struct `RangeTo` + | | help: consider borrowing here: `&(..5)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeTo<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-std.rs:25:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505-no-std.rs:54:16 + | +LL | take_range(..=42); + | ---------- ^^^^^ + | | | + | | expected reference, found struct `RangeToInclusive` + | | help: consider borrowing here: `&(..=42)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeToInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505-no-std.rs:25:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/range/issue-54505.fixed b/tests/ui/range/issue-54505.fixed new file mode 100644 index 000000000..f8298c0b5 --- /dev/null +++ b/tests/ui/range/issue-54505.fixed @@ -0,0 +1,43 @@ +// run-rustfix + +// Regression test for #54505 - range borrowing suggestion had +// incorrect syntax (missing parentheses). + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(&(0..1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..1) + + take_range(&(1..)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(1..) + + take_range(&(..)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..) + + take_range(&(0..=1)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..=1) + + take_range(&(..5)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..5) + + take_range(&(..=42)); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..=42) +} diff --git a/tests/ui/range/issue-54505.rs b/tests/ui/range/issue-54505.rs new file mode 100644 index 000000000..03673252d --- /dev/null +++ b/tests/ui/range/issue-54505.rs @@ -0,0 +1,43 @@ +// run-rustfix + +// Regression test for #54505 - range borrowing suggestion had +// incorrect syntax (missing parentheses). + +use std::ops::RangeBounds; + + +// take a reference to any built-in range +fn take_range(_r: &impl RangeBounds) {} + + +fn main() { + take_range(0..1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..1) + + take_range(1..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(1..) + + take_range(..); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..) + + take_range(0..=1); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(0..=1) + + take_range(..5); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..5) + + take_range(..=42); + //~^ ERROR mismatched types [E0308] + //~| HELP consider borrowing here + //~| SUGGESTION &(..=42) +} diff --git a/tests/ui/range/issue-54505.stderr b/tests/ui/range/issue-54505.stderr new file mode 100644 index 000000000..9eec16940 --- /dev/null +++ b/tests/ui/range/issue-54505.stderr @@ -0,0 +1,111 @@ +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:14:16 + | +LL | take_range(0..1); + | ---------- ^^^^ + | | | + | | expected reference, found struct `Range` + | | help: consider borrowing here: `&(0..1)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `std::ops::Range<{integer}>` +note: function defined here + --> $DIR/issue-54505.rs:10:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:19:16 + | +LL | take_range(1..); + | ---------- ^^^ + | | | + | | expected reference, found struct `RangeFrom` + | | help: consider borrowing here: `&(1..)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFrom<{integer}>` +note: function defined here + --> $DIR/issue-54505.rs:10:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:24:16 + | +LL | take_range(..); + | ---------- ^^ + | | | + | | expected reference, found struct `RangeFull` + | | help: consider borrowing here: `&(..)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeFull` +note: function defined here + --> $DIR/issue-54505.rs:10:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:29:16 + | +LL | take_range(0..=1); + | ---------- ^^^^^ + | | | + | | expected reference, found struct `RangeInclusive` + | | help: consider borrowing here: `&(0..=1)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505.rs:10:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:34:16 + | +LL | take_range(..5); + | ---------- ^^^ + | | | + | | expected reference, found struct `RangeTo` + | | help: consider borrowing here: `&(..5)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeTo<{integer}>` +note: function defined here + --> $DIR/issue-54505.rs:10:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error[E0308]: mismatched types + --> $DIR/issue-54505.rs:39:16 + | +LL | take_range(..=42); + | ---------- ^^^^^ + | | | + | | expected reference, found struct `RangeToInclusive` + | | help: consider borrowing here: `&(..=42)` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `RangeToInclusive<{integer}>` +note: function defined here + --> $DIR/issue-54505.rs:10:4 + | +LL | fn take_range(_r: &impl RangeBounds) {} + | ^^^^^^^^^^ ------------------------- + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/range/issue-73553-misinterp-range-literal.rs b/tests/ui/range/issue-73553-misinterp-range-literal.rs new file mode 100644 index 000000000..e65dba0a0 --- /dev/null +++ b/tests/ui/range/issue-73553-misinterp-range-literal.rs @@ -0,0 +1,16 @@ +type Range = std::ops::Range; + +fn demo(r: &Range) { + println!("{:?}", r); +} + +fn tell(x: usize) -> usize { + x +} + +fn main() { + demo(tell(1)..tell(10)); + //~^ ERROR mismatched types + demo(1..10); + //~^ ERROR mismatched types +} diff --git a/tests/ui/range/issue-73553-misinterp-range-literal.stderr b/tests/ui/range/issue-73553-misinterp-range-literal.stderr new file mode 100644 index 000000000..d08d9b134 --- /dev/null +++ b/tests/ui/range/issue-73553-misinterp-range-literal.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/issue-73553-misinterp-range-literal.rs:12:10 + | +LL | demo(tell(1)..tell(10)); + | ---- ^^^^^^^^^^^^^^^^^ + | | | + | | expected `&Range`, found struct `Range` + | | help: consider borrowing here: `&(tell(1)..tell(10))` + | arguments to this function are incorrect + | + = note: expected reference `&std::ops::Range` + found struct `std::ops::Range` +note: function defined here + --> $DIR/issue-73553-misinterp-range-literal.rs:3:4 + | +LL | fn demo(r: &Range) { + | ^^^^ --------- + +error[E0308]: mismatched types + --> $DIR/issue-73553-misinterp-range-literal.rs:14:10 + | +LL | demo(1..10); + | ---- ^^^^^ + | | | + | | expected `&Range`, found struct `Range` + | | help: consider borrowing here: `&(1..10)` + | arguments to this function are incorrect + | + = note: expected reference `&std::ops::Range` + found struct `std::ops::Range<{integer}>` +note: function defined here + --> $DIR/issue-73553-misinterp-range-literal.rs:3:4 + | +LL | fn demo(r: &Range) { + | ^^^^ --------- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/range/range-1.rs b/tests/ui/range/range-1.rs new file mode 100644 index 000000000..192426fe2 --- /dev/null +++ b/tests/ui/range/range-1.rs @@ -0,0 +1,16 @@ +// Test range syntax - type errors. + +pub fn main() { + // Mixed types. + let _ = 0u32..10i32; + //~^ ERROR mismatched types + + // Bool => does not implement iterator. + for i in false..true {} + //~^ ERROR `bool: Step` is not satisfied + + // Unsized type. + let arr: &[_] = &[1, 2, 3]; + let range = *arr..; + //~^ ERROR the size for values of type +} diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr new file mode 100644 index 000000000..395639036 --- /dev/null +++ b/tests/ui/range/range-1.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/range-1.rs:5:19 + | +LL | let _ = 0u32..10i32; + | ^^^^^ expected `u32`, found `i32` + +error[E0277]: the trait bound `bool: Step` is not satisfied + --> $DIR/range-1.rs:9:14 + | +LL | for i in false..true {} + | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` + | + = help: the following other types implement trait `Step`: + char + i128 + i16 + i32 + i64 + i8 + isize + u128 + and 5 others + = note: required for `std::ops::Range` to implement `Iterator` + = note: required for `std::ops::Range` to implement `IntoIterator` + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/range-1.rs:14:17 + | +LL | let range = *arr..; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by a bound in `RangeFrom` + --> $SRC_DIR/core/src/ops/range.rs:LL:COL + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/range/range-inclusive-pattern-precedence.fixed b/tests/ui/range/range-inclusive-pattern-precedence.fixed new file mode 100644 index 000000000..38104bab7 --- /dev/null +++ b/tests/ui/range/range-inclusive-pattern-precedence.fixed @@ -0,0 +1,21 @@ +// In expression, `&a..=b` is treated as `(&a)..=(b)` and `box a..=b` is +// `(box a)..=(b)`. In a pattern, however, `&a..=b` means `&(a..=b)`. This may +// lead to confusion. + +// run-rustfix + +#![warn(ellipsis_inclusive_range_patterns)] + +pub fn main() { + match &12 { + &(0..=9) => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + //~| HELP use `..=` for an inclusive range + &(10..=15) => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~| HELP add parentheses to clarify the precedence + &(16..=20) => {} + _ => {} + } +} diff --git a/tests/ui/range/range-inclusive-pattern-precedence.rs b/tests/ui/range/range-inclusive-pattern-precedence.rs new file mode 100644 index 000000000..b294e436f --- /dev/null +++ b/tests/ui/range/range-inclusive-pattern-precedence.rs @@ -0,0 +1,21 @@ +// In expression, `&a..=b` is treated as `(&a)..=(b)` and `box a..=b` is +// `(box a)..=(b)`. In a pattern, however, `&a..=b` means `&(a..=b)`. This may +// lead to confusion. + +// run-rustfix + +#![warn(ellipsis_inclusive_range_patterns)] + +pub fn main() { + match &12 { + &0...9 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + //~| HELP use `..=` for an inclusive range + &10..=15 => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~| HELP add parentheses to clarify the precedence + &(16..=20) => {} + _ => {} + } +} diff --git a/tests/ui/range/range-inclusive-pattern-precedence.stderr b/tests/ui/range/range-inclusive-pattern-precedence.stderr new file mode 100644 index 000000000..f6788d034 --- /dev/null +++ b/tests/ui/range/range-inclusive-pattern-precedence.stderr @@ -0,0 +1,22 @@ +error: the range pattern here has ambiguous interpretation + --> $DIR/range-inclusive-pattern-precedence.rs:15:10 + | +LL | &10..=15 => {} + | ^^^^^^^ help: add parentheses to clarify the precedence: `(10..=15)` + +warning: `...` range patterns are deprecated + --> $DIR/range-inclusive-pattern-precedence.rs:11:9 + | +LL | &0...9 => {} + | ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/range-inclusive-pattern-precedence.rs:7:9 + | +LL | #![warn(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/range/range-inclusive-pattern-precedence2.rs b/tests/ui/range/range-inclusive-pattern-precedence2.rs new file mode 100644 index 000000000..bede9c579 --- /dev/null +++ b/tests/ui/range/range-inclusive-pattern-precedence2.rs @@ -0,0 +1,20 @@ +// We are going to disallow `&a..=b` and `box a..=b` in a pattern. However, the +// older ... syntax is still allowed as a stability guarantee. + +#![feature(box_patterns)] +#![warn(ellipsis_inclusive_range_patterns)] + +fn main() { + match Box::new(12) { + // FIXME: can we add suggestions like `&(0..=9)`? + box 0...9 => {} + //~^ WARN `...` range patterns are deprecated + //~| WARN this is accepted in the current edition + //~| HELP use `..=` for an inclusive range + box 10..=15 => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~^^ HELP add parentheses to clarify the precedence + box (16..=20) => {} + _ => {} + } +} diff --git a/tests/ui/range/range-inclusive-pattern-precedence2.stderr b/tests/ui/range/range-inclusive-pattern-precedence2.stderr new file mode 100644 index 000000000..bb4e3a13a --- /dev/null +++ b/tests/ui/range/range-inclusive-pattern-precedence2.stderr @@ -0,0 +1,22 @@ +error: the range pattern here has ambiguous interpretation + --> $DIR/range-inclusive-pattern-precedence2.rs:14:13 + | +LL | box 10..=15 => {} + | ^^^^^^^ help: add parentheses to clarify the precedence: `(10..=15)` + +warning: `...` range patterns are deprecated + --> $DIR/range-inclusive-pattern-precedence2.rs:10:14 + | +LL | box 0...9 => {} + | ^^^ help: use `..=` for an inclusive range + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/range-inclusive-pattern-precedence2.rs:5:9 + | +LL | #![warn(ellipsis_inclusive_range_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs new file mode 100644 index 000000000..d02caff1f --- /dev/null +++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs @@ -0,0 +1,13 @@ +#![feature(exclusive_range_pattern)] +#![allow(unreachable_patterns)] +fn main() { + match 0u8 { + 251..257 => {} + //~^ ERROR literal out of range + //~| ERROR literal out of range + 251..=256 => {} + //~^ ERROR literal out of range + //~| ERROR literal out of range + _ => {} + } +} diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr new file mode 100644 index 000000000..7b8309b9b --- /dev/null +++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr @@ -0,0 +1,26 @@ +error: literal out of range for `u8` + --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:5:14 + | +LL | 251..257 => {} + | ^^^ this value doesn't fit in `u8` whose maximum value is `255` + +error: literal out of range for `u8` + --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:8:15 + | +LL | 251..=256 => {} + | ^^^ this value doesn't fit in `u8` whose maximum value is `255` + +error: literal out of range for `u8` + --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:5:14 + | +LL | 251..257 => {} + | ^^^ this value doesn't fit in `u8` whose maximum value is `255` + +error: literal out of range for `u8` + --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:8:15 + | +LL | 251..=256 => {} + | ^^^ this value doesn't fit in `u8` whose maximum value is `255` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/range/range_traits-1.rs b/tests/ui/range/range_traits-1.rs new file mode 100644 index 000000000..e28e47435 --- /dev/null +++ b/tests/ui/range/range_traits-1.rs @@ -0,0 +1,25 @@ +use std::ops::*; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +struct AllTheRanges { + a: Range, + //~^ ERROR can't compare + //~| ERROR Ord + b: RangeTo, + //~^ ERROR can't compare + //~| ERROR Ord + c: RangeFrom, + //~^ ERROR can't compare + //~| ERROR Ord + d: RangeFull, + //~^ ERROR can't compare + //~| ERROR Ord + e: RangeInclusive, + //~^ ERROR can't compare + //~| ERROR Ord + f: RangeToInclusive, + //~^ ERROR can't compare + //~| ERROR Ord +} + +fn main() {} diff --git a/tests/ui/range/range_traits-1.stderr b/tests/ui/range/range_traits-1.stderr new file mode 100644 index 000000000..617afc995 --- /dev/null +++ b/tests/ui/range/range_traits-1.stderr @@ -0,0 +1,141 @@ +error[E0277]: can't compare `std::ops::Range` with `std::ops::Range` + --> $DIR/range_traits-1.rs:5:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +LL | struct AllTheRanges { +LL | a: Range, + | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range < std::ops::Range` and `std::ops::Range > std::ops::Range` + | + = help: the trait `PartialOrd` is not implemented for `std::ops::Range` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: can't compare `std::ops::RangeTo` with `std::ops::RangeTo` + --> $DIR/range_traits-1.rs:8:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... +LL | b: RangeTo, + | ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo < std::ops::RangeTo` and `std::ops::RangeTo > std::ops::RangeTo` + | + = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: can't compare `std::ops::RangeFrom` with `std::ops::RangeFrom` + --> $DIR/range_traits-1.rs:11:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... +LL | c: RangeFrom, + | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom < std::ops::RangeFrom` and `std::ops::RangeFrom > std::ops::RangeFrom` + | + = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull` + --> $DIR/range_traits-1.rs:14:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... +LL | d: RangeFull, + | ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull` + | + = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: can't compare `std::ops::RangeInclusive` with `std::ops::RangeInclusive` + --> $DIR/range_traits-1.rs:17:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... +LL | e: RangeInclusive, + | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive < std::ops::RangeInclusive` and `std::ops::RangeInclusive > std::ops::RangeInclusive` + | + = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: can't compare `std::ops::RangeToInclusive` with `std::ops::RangeToInclusive` + --> $DIR/range_traits-1.rs:20:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | ---------- in this derive macro expansion +... +LL | f: RangeToInclusive, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive < std::ops::RangeToInclusive` and `std::ops::RangeToInclusive > std::ops::RangeToInclusive` + | + = help: the trait `PartialOrd` is not implemented for `std::ops::RangeToInclusive` + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `std::ops::Range: Ord` is not satisfied + --> $DIR/range_traits-1.rs:5:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +LL | struct AllTheRanges { +LL | a: Range, + | ^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::Range` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `std::ops::RangeTo: Ord` is not satisfied + --> $DIR/range_traits-1.rs:8:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... +LL | b: RangeTo, + | ^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeTo` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `std::ops::RangeFrom: Ord` is not satisfied + --> $DIR/range_traits-1.rs:11:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... +LL | c: RangeFrom, + | ^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFrom` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `std::ops::RangeFull: Ord` is not satisfied + --> $DIR/range_traits-1.rs:14:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... +LL | d: RangeFull, + | ^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFull` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `std::ops::RangeInclusive: Ord` is not satisfied + --> $DIR/range_traits-1.rs:17:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... +LL | e: RangeInclusive, + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeInclusive` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `std::ops::RangeToInclusive: Ord` is not satisfied + --> $DIR/range_traits-1.rs:20:5 + | +LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] + | --- in this derive macro expansion +... +LL | f: RangeToInclusive, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeToInclusive` + | + = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/range/range_traits-2.rs b/tests/ui/range/range_traits-2.rs new file mode 100644 index 000000000..234d7a64d --- /dev/null +++ b/tests/ui/range/range_traits-2.rs @@ -0,0 +1,6 @@ +use std::ops::*; + +#[derive(Copy, Clone)] //~ ERROR Copy +struct R(Range); + +fn main() {} diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr new file mode 100644 index 000000000..61facba53 --- /dev/null +++ b/tests/ui/range/range_traits-2.stderr @@ -0,0 +1,13 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/range_traits-2.rs:3:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ +LL | struct R(Range); + | ------------ this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/range/range_traits-3.rs b/tests/ui/range/range_traits-3.rs new file mode 100644 index 000000000..2d597cce5 --- /dev/null +++ b/tests/ui/range/range_traits-3.rs @@ -0,0 +1,6 @@ +use std::ops::*; + +#[derive(Copy, Clone)] //~ ERROR Copy +struct R(RangeFrom); + +fn main() {} diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr new file mode 100644 index 000000000..e54d17b32 --- /dev/null +++ b/tests/ui/range/range_traits-3.stderr @@ -0,0 +1,13 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/range_traits-3.rs:3:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ +LL | struct R(RangeFrom); + | ---------------- this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/range/range_traits-4.rs b/tests/ui/range/range_traits-4.rs new file mode 100644 index 000000000..b8e88559b --- /dev/null +++ b/tests/ui/range/range_traits-4.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) + +use std::ops::*; + +#[derive(Copy, Clone)] +struct R(RangeTo); + + +fn main() {} diff --git a/tests/ui/range/range_traits-5.rs b/tests/ui/range/range_traits-5.rs new file mode 100644 index 000000000..4aec7a415 --- /dev/null +++ b/tests/ui/range/range_traits-5.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) + +use std::ops::*; + +#[derive(Copy, Clone)] +struct R(RangeFull); + + +fn main() {} diff --git a/tests/ui/range/range_traits-6.rs b/tests/ui/range/range_traits-6.rs new file mode 100644 index 000000000..bce106bbf --- /dev/null +++ b/tests/ui/range/range_traits-6.rs @@ -0,0 +1,6 @@ +use std::ops::*; + +#[derive(Copy, Clone)] //~ ERROR Copy +struct R(RangeInclusive); + +fn main() {} diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr new file mode 100644 index 000000000..addc525f1 --- /dev/null +++ b/tests/ui/range/range_traits-6.stderr @@ -0,0 +1,13 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/range_traits-6.rs:3:10 + | +LL | #[derive(Copy, Clone)] + | ^^^^ +LL | struct R(RangeInclusive); + | --------------------- this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/range/range_traits-7.rs b/tests/ui/range/range_traits-7.rs new file mode 100644 index 000000000..c7b310562 --- /dev/null +++ b/tests/ui/range/range_traits-7.rs @@ -0,0 +1,9 @@ +// build-pass (FIXME(62277): could be check-pass?) + +use std::ops::*; + +#[derive(Copy, Clone)] +struct R(RangeToInclusive); + + +fn main() {} diff --git a/tests/ui/range_inclusive.rs b/tests/ui/range_inclusive.rs new file mode 100644 index 000000000..c9107d24e --- /dev/null +++ b/tests/ui/range_inclusive.rs @@ -0,0 +1,121 @@ +// run-pass +// Test inclusive range syntax. +#![allow(unused_braces)] +#![allow(unused_comparisons)] + +use std::ops::RangeToInclusive; + +fn foo() -> isize { 42 } + +// Test that range syntax works in return statements +pub fn return_range_to() -> RangeToInclusive { return ..=1; } + +#[derive(Debug)] +struct P(#[allow(unused_tuple_struct_fields)] u8); + +pub fn main() { + let mut count = 0; + for i in 0_usize..=10 { + assert!(i >= 0 && i <= 10); + count += i; + } + assert_eq!(count, 55); + + let mut count = 0; + let range = 0_usize..=10; + for i in range { + assert!(i >= 0 && i <= 10); + count += i; + } + assert_eq!(count, 55); + + let mut count = 0; + for i in (0_usize..=10).step_by(2) { + assert!(i >= 0 && i <= 10 && i % 2 == 0); + count += i; + } + assert_eq!(count, 30); + + let _ = 0_usize..=4+4-3; + let _ = 0..=foo(); + + let _ = { &42..=&100 }; // references to literals are OK + let _ = ..=42_usize; + + // Test we can use two different types with a common supertype. + let x = &42; + { + let y = 42; + let _ = x..=&y; + } + + // test collection indexing + let vec = (0..=10).collect::>(); + let slice: &[_] = &*vec; + let string = String::from("hello world"); + let stir = "hello world"; + + assert_eq!(&vec[3..=6], &[3, 4, 5, 6]); + assert_eq!(&vec[ ..=6], &[0, 1, 2, 3, 4, 5, 6]); + + assert_eq!(&slice[3..=6], &[3, 4, 5, 6]); + assert_eq!(&slice[ ..=6], &[0, 1, 2, 3, 4, 5, 6]); + + assert_eq!(&string[3..=6], "lo w"); + assert_eq!(&string[ ..=6], "hello w"); + + assert_eq!(&stir[3..=6], "lo w"); + assert_eq!(&stir[ ..=6], "hello w"); + + // test the size hints and emptying + let mut long = 0..=255u8; + let mut short = 42..=42u8; + assert_eq!(long.size_hint(), (256, Some(256))); + assert_eq!(short.size_hint(), (1, Some(1))); + long.next(); + short.next(); + assert_eq!(long.size_hint(), (255, Some(255))); + assert_eq!(short.size_hint(), (0, Some(0))); + assert!(short.is_empty()); + + assert_eq!(long.len(), 255); + assert_eq!(short.len(), 0); + + // test iterating backwards + assert_eq!(long.next_back(), Some(255)); + assert_eq!(long.next_back(), Some(254)); + assert_eq!(long.next_back(), Some(253)); + assert_eq!(long.next(), Some(1)); + assert_eq!(long.next(), Some(2)); + assert_eq!(long.next_back(), Some(252)); + for i in 3..=251 { + assert_eq!(long.next(), Some(i)); + } + assert!(long.is_empty()); + + // check underflow + let mut narrow = 1..=0; + assert_eq!(narrow.next_back(), None); + assert!(narrow.is_empty()); + let mut zero = 0u8..=0; + assert_eq!(zero.next_back(), Some(0)); + assert_eq!(zero.next_back(), None); + assert!(zero.is_empty()); + let mut high = 255u8..=255; + assert_eq!(high.next_back(), Some(255)); + assert_eq!(high.next_back(), None); + assert!(high.is_empty()); + + // what happens if you have a nonsense range? + let mut nonsense = 10..=5; + assert_eq!(nonsense.next(), None); + assert!(nonsense.is_empty()); + + // output + assert_eq!(format!("{:?}", 0..=10), "0..=10"); + assert_eq!(format!("{:?}", ..=10), "..=10"); + assert_eq!(format!("{:?}", 9..=6), "9..=6"); + + // ensure that constructing a RangeInclusive does not need PartialOrd bound + assert_eq!(format!("{:?}", P(1)..=P(2)), "P(1)..=P(2)"); +} diff --git a/tests/ui/raw-ref-op/feature-raw-ref-op.rs b/tests/ui/raw-ref-op/feature-raw-ref-op.rs new file mode 100644 index 000000000..0a44b1cde --- /dev/null +++ b/tests/ui/raw-ref-op/feature-raw-ref-op.rs @@ -0,0 +1,21 @@ +// gate-test-raw_ref_op + +macro_rules! is_expr { + ($e:expr) => {} +} + +is_expr!(&raw const a); //~ ERROR raw address of syntax is experimental +is_expr!(&raw mut a); //~ ERROR raw address of syntax is experimental + +#[cfg(FALSE)] +fn cfgd_out() { + let mut a = 0; + &raw const a; //~ ERROR raw address of syntax is experimental + &raw mut a; //~ ERROR raw address of syntax is experimental +} + +fn main() { + let mut y = 123; + let x = &raw const y; //~ ERROR raw address of syntax is experimental + let x = &raw mut y; //~ ERROR raw address of syntax is experimental +} diff --git a/tests/ui/raw-ref-op/feature-raw-ref-op.stderr b/tests/ui/raw-ref-op/feature-raw-ref-op.stderr new file mode 100644 index 000000000..1e5fd84ff --- /dev/null +++ b/tests/ui/raw-ref-op/feature-raw-ref-op.stderr @@ -0,0 +1,57 @@ +error[E0658]: raw address of syntax is experimental + --> $DIR/feature-raw-ref-op.rs:13:5 + | +LL | &raw const a; + | ^^^^^^^^^^ + | + = note: see issue #64490 for more information + = help: add `#![feature(raw_ref_op)]` to the crate attributes to enable + +error[E0658]: raw address of syntax is experimental + --> $DIR/feature-raw-ref-op.rs:14:5 + | +LL | &raw mut a; + | ^^^^^^^^ + | + = note: see issue #64490 for more information + = help: add `#![feature(raw_ref_op)]` to the crate attributes to enable + +error[E0658]: raw address of syntax is experimental + --> $DIR/feature-raw-ref-op.rs:19:13 + | +LL | let x = &raw const y; + | ^^^^^^^^^^ + | + = note: see issue #64490 for more information + = help: add `#![feature(raw_ref_op)]` to the crate attributes to enable + +error[E0658]: raw address of syntax is experimental + --> $DIR/feature-raw-ref-op.rs:20:13 + | +LL | let x = &raw mut y; + | ^^^^^^^^ + | + = note: see issue #64490 for more information + = help: add `#![feature(raw_ref_op)]` to the crate attributes to enable + +error[E0658]: raw address of syntax is experimental + --> $DIR/feature-raw-ref-op.rs:7:10 + | +LL | is_expr!(&raw const a); + | ^^^^^^^^^^ + | + = note: see issue #64490 for more information + = help: add `#![feature(raw_ref_op)]` to the crate attributes to enable + +error[E0658]: raw address of syntax is experimental + --> $DIR/feature-raw-ref-op.rs:8:10 + | +LL | is_expr!(&raw mut a); + | ^^^^^^^^ + | + = note: see issue #64490 for more information + = help: add `#![feature(raw_ref_op)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/raw-ref-op/raw-ref-op.rs b/tests/ui/raw-ref-op/raw-ref-op.rs new file mode 100644 index 000000000..0c6e23a00 --- /dev/null +++ b/tests/ui/raw-ref-op/raw-ref-op.rs @@ -0,0 +1,13 @@ +// run-pass + +#![feature(raw_ref_op)] + +fn main() { + let mut x = 123; + let c_p = &raw const x; + let m_p = &raw mut x; + let i_r = &x; + assert!(c_p == i_r); + assert!(c_p == m_p); + unsafe { assert!(*c_p == *i_r ); } +} diff --git a/tests/ui/raw-ref-op/raw-ref-temp-deref.rs b/tests/ui/raw-ref-op/raw-ref-temp-deref.rs new file mode 100644 index 000000000..2e075a1b9 --- /dev/null +++ b/tests/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -0,0 +1,24 @@ +// check-pass +// Check that taking the address of a place that contains a dereference is +// allowed. +#![feature(raw_ref_op, type_ascription)] + +const PAIR_REF: &(i32, i64) = &(1, 2); + +const ARRAY_REF: &[i32; 2] = &[3, 4]; +const SLICE_REF: &[i32] = &[5, 6]; + +fn main() { + // These are all OK, we're not taking the address of the temporary + let deref_ref = &raw const *PAIR_REF; + let field_deref_ref = &raw const PAIR_REF.0; + let deref_ref = &raw const *ARRAY_REF; + let index_deref_ref = &raw const ARRAY_REF[0]; + let deref_ref = &raw const *SLICE_REF; + let index_deref_ref = &raw const SLICE_REF[1]; + + let x = 0; + let ascribe_ref = &raw const type_ascribe!(x, i32); + let ascribe_deref = &raw const type_ascribe!(*ARRAY_REF, [i32; 2]); + let ascribe_index_deref = &raw const type_ascribe!(ARRAY_REF[0], i32); +} diff --git a/tests/ui/raw-ref-op/raw-ref-temp.rs b/tests/ui/raw-ref-op/raw-ref-temp.rs new file mode 100644 index 000000000..10e47cb34 --- /dev/null +++ b/tests/ui/raw-ref-op/raw-ref-temp.rs @@ -0,0 +1,31 @@ +// Ensure that we don't allow taking the address of temporary values +#![feature(raw_ref_op, type_ascription)] + +const FOUR: u64 = 4; + +const PAIR: (i32, i64) = (1, 2); + +const ARRAY: [i32; 2] = [1, 2]; + +fn main() { + let ref_expr = &raw const 2; //~ ERROR cannot take address + let mut_ref_expr = &raw mut 3; //~ ERROR cannot take address + let ref_const = &raw const FOUR; //~ ERROR cannot take address + let mut_ref_const = &raw mut FOUR; //~ ERROR cannot take address + + let field_ref_expr = &raw const (1, 2).0; //~ ERROR cannot take address + let mut_field_ref_expr = &raw mut (1, 2).0; //~ ERROR cannot take address + let field_ref = &raw const PAIR.0; //~ ERROR cannot take address + let mut_field_ref = &raw mut PAIR.0; //~ ERROR cannot take address + + let index_ref_expr = &raw const [1, 2][0]; //~ ERROR cannot take address + let mut_index_ref_expr = &raw mut [1, 2][0]; //~ ERROR cannot take address + let index_ref = &raw const ARRAY[0]; //~ ERROR cannot take address + let mut_index_ref = &raw mut ARRAY[1]; //~ ERROR cannot take address + + let ref_ascribe = &raw const type_ascribe!(2, i32); //~ ERROR cannot take address + let mut_ref_ascribe = &raw mut type_ascribe!(3, i32); //~ ERROR cannot take address + + let ascribe_field_ref = &raw const type_ascribe!(PAIR.0, i32); //~ ERROR cannot take address + let ascribe_index_ref = &raw mut type_ascribe!(ARRAY[0], i32); //~ ERROR cannot take address +} diff --git a/tests/ui/raw-ref-op/raw-ref-temp.stderr b/tests/ui/raw-ref-op/raw-ref-temp.stderr new file mode 100644 index 000000000..b96661625 --- /dev/null +++ b/tests/ui/raw-ref-op/raw-ref-temp.stderr @@ -0,0 +1,99 @@ +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:11:31 + | +LL | let ref_expr = &raw const 2; + | ^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:12:33 + | +LL | let mut_ref_expr = &raw mut 3; + | ^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:13:32 + | +LL | let ref_const = &raw const FOUR; + | ^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:14:34 + | +LL | let mut_ref_const = &raw mut FOUR; + | ^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:16:37 + | +LL | let field_ref_expr = &raw const (1, 2).0; + | ^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:17:39 + | +LL | let mut_field_ref_expr = &raw mut (1, 2).0; + | ^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:18:32 + | +LL | let field_ref = &raw const PAIR.0; + | ^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:19:34 + | +LL | let mut_field_ref = &raw mut PAIR.0; + | ^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:21:37 + | +LL | let index_ref_expr = &raw const [1, 2][0]; + | ^^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:22:39 + | +LL | let mut_index_ref_expr = &raw mut [1, 2][0]; + | ^^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:23:32 + | +LL | let index_ref = &raw const ARRAY[0]; + | ^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:24:34 + | +LL | let mut_index_ref = &raw mut ARRAY[1]; + | ^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:26:34 + | +LL | let ref_ascribe = &raw const type_ascribe!(2, i32); + | ^^^^^^^^^^^^^^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:27:36 + | +LL | let mut_ref_ascribe = &raw mut type_ascribe!(3, i32); + | ^^^^^^^^^^^^^^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:29:40 + | +LL | let ascribe_field_ref = &raw const type_ascribe!(PAIR.0, i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp.rs:30:38 + | +LL | let ascribe_index_ref = &raw mut type_ascribe!(ARRAY[0], i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0745`. diff --git a/tests/ui/raw-ref-op/unusual_locations.rs b/tests/ui/raw-ref-op/unusual_locations.rs new file mode 100644 index 000000000..6bf37408a --- /dev/null +++ b/tests/ui/raw-ref-op/unusual_locations.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(raw_ref_op)] + +const USES_PTR: () = { let u = (); &raw const u; }; +static ALSO_USES_PTR: () = { let u = (); &raw const u; }; + +fn main() { + let x: [i32; { let u = 2; let x = &raw const u; 4 }] + = [2; { let v = 3; let y = &raw const v; 4 }]; + let mut one = 1; + let two = 2; + if &raw const one == &raw mut one { + match &raw const two { + _ => {} + } + } + let three = 3; + let mut four = 4; + println!("{:p}", &raw const three); + unsafe { &raw mut four; } +} diff --git a/tests/ui/raw-str.rs b/tests/ui/raw-str.rs new file mode 100644 index 000000000..0916dddbb Binary files /dev/null and b/tests/ui/raw-str.rs differ diff --git a/tests/ui/reachable-unnameable-type-alias.rs b/tests/ui/reachable-unnameable-type-alias.rs new file mode 100644 index 000000000..461355f87 --- /dev/null +++ b/tests/ui/reachable-unnameable-type-alias.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(staged_api)] +#![stable(feature = "a", since = "b")] + +mod inner_private_module { + // UnnameableTypeAlias isn't marked as reachable, so no stability annotation is required here + pub type UnnameableTypeAlias = u8; +} + +#[stable(feature = "a", since = "b")] +pub fn f() -> inner_private_module::UnnameableTypeAlias { + 0 +} + +fn main() {} diff --git a/tests/ui/reachable/README.md b/tests/ui/reachable/README.md new file mode 100644 index 000000000..8bed5fba7 --- /dev/null +++ b/tests/ui/reachable/README.md @@ -0,0 +1,7 @@ +A variety of tests around reachability. These tests in general check +two things: + +- that we get unreachable code warnings in reasonable locations; +- that we permit coercions **into** `!` from expressions which + diverge, where an expression "diverges" if it must execute some + subexpression of type `!`, or it has type `!` itself. diff --git a/tests/ui/reachable/auxiliary/issue-11225-1.rs b/tests/ui/reachable/auxiliary/issue-11225-1.rs new file mode 100644 index 000000000..2c6f899a0 --- /dev/null +++ b/tests/ui/reachable/auxiliary/issue-11225-1.rs @@ -0,0 +1,18 @@ +mod inner { + pub trait Trait { + fn f(&self) { f(); } + fn f_ufcs(&self) { f_ufcs(); } + } + + impl Trait for isize {} + + fn f() {} + fn f_ufcs() {} +} + +pub fn foo(t: T) { + t.f(); +} +pub fn foo_ufcs(t: T) { + T::f_ufcs(&t); +} diff --git a/tests/ui/reachable/auxiliary/issue-11225-2.rs b/tests/ui/reachable/auxiliary/issue-11225-2.rs new file mode 100644 index 000000000..4381f0a4e --- /dev/null +++ b/tests/ui/reachable/auxiliary/issue-11225-2.rs @@ -0,0 +1,28 @@ +use inner::Trait; + +mod inner { + pub struct Foo; + pub trait Trait { + fn f(&self); + fn f_ufcs(&self); + } + + impl Trait for Foo { + fn f(&self) { } + fn f_ufcs(&self) { } + } +} + +pub trait Outer { + fn foo(&self, t: T) { t.f(); } + fn foo_ufcs(&self, t: T) { T::f(&t); } +} + +impl Outer for isize {} + +pub fn foo(t: T) { + t.foo(inner::Foo); +} +pub fn foo_ufcs(t: T) { + T::foo_ufcs(&t, inner::Foo) +} diff --git a/tests/ui/reachable/auxiliary/issue-11225-3.rs b/tests/ui/reachable/auxiliary/issue-11225-3.rs new file mode 100644 index 000000000..266e42a10 --- /dev/null +++ b/tests/ui/reachable/auxiliary/issue-11225-3.rs @@ -0,0 +1,28 @@ +trait PrivateTrait { + fn private_trait_method(&self); + fn private_trait_method_ufcs(&self); +} + +struct PrivateStruct; + +impl PrivateStruct { + fn private_inherent_method(&self) { } + fn private_inherent_method_ufcs(&self) { } +} + +impl PrivateTrait for PrivateStruct { + fn private_trait_method(&self) { } + fn private_trait_method_ufcs(&self) { } +} + +#[inline] +pub fn public_inlinable_function() { + PrivateStruct.private_trait_method(); + PrivateStruct.private_inherent_method(); +} + +#[inline] +pub fn public_inlinable_function_ufcs() { + PrivateStruct::private_trait_method(&PrivateStruct); + PrivateStruct::private_inherent_method(&PrivateStruct); +} diff --git a/tests/ui/reachable/auxiliary/unreachable_variant.rs b/tests/ui/reachable/auxiliary/unreachable_variant.rs new file mode 100644 index 000000000..4e94a4b5e --- /dev/null +++ b/tests/ui/reachable/auxiliary/unreachable_variant.rs @@ -0,0 +1,5 @@ +mod super_sekrit { + pub enum sooper_sekrit { + quux, baz + } +} diff --git a/tests/ui/reachable/expr_add.rs b/tests/ui/reachable/expr_add.rs new file mode 100644 index 000000000..b45e5daf4 --- /dev/null +++ b/tests/ui/reachable/expr_add.rs @@ -0,0 +1,18 @@ +#![feature(never_type)] +#![allow(unused_variables)] +#![deny(unreachable_code)] + +use std::ops; + +struct Foo; + +impl ops::Add for Foo { + type Output = !; + fn add(self, rhs: !) -> ! { + unimplemented!() + } +} + +fn main() { + let x = Foo + return; //~ ERROR unreachable +} diff --git a/tests/ui/reachable/expr_add.stderr b/tests/ui/reachable/expr_add.stderr new file mode 100644 index 000000000..692bd20f5 --- /dev/null +++ b/tests/ui/reachable/expr_add.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_add.rs:17:13 + | +LL | let x = Foo + return; + | ^^^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_add.rs:3:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_again.rs b/tests/ui/reachable/expr_again.rs new file mode 100644 index 000000000..604932133 --- /dev/null +++ b/tests/ui/reachable/expr_again.rs @@ -0,0 +1,11 @@ +#![allow(unused_variables)] + +#![deny(unreachable_code)] + +fn main() { + let x = loop { + continue; + println!("hi"); + //~^ ERROR unreachable statement + }; +} diff --git a/tests/ui/reachable/expr_again.stderr b/tests/ui/reachable/expr_again.stderr new file mode 100644 index 000000000..a3c54e135 --- /dev/null +++ b/tests/ui/reachable/expr_again.stderr @@ -0,0 +1,17 @@ +error: unreachable statement + --> $DIR/expr_again.rs:8:9 + | +LL | continue; + | -------- any code following this expression is unreachable +LL | println!("hi"); + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/expr_again.rs:3:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_andand.rs b/tests/ui/reachable/expr_andand.rs new file mode 100644 index 000000000..d37eb0a3b --- /dev/null +++ b/tests/ui/reachable/expr_andand.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(unused_variables)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo() { + // No error here. + let x = false && (return); + println!("I am not dead."); +} + +fn main() { } diff --git a/tests/ui/reachable/expr_array.rs b/tests/ui/reachable/expr_array.rs new file mode 100644 index 000000000..e6bdb9705 --- /dev/null +++ b/tests/ui/reachable/expr_array.rs @@ -0,0 +1,17 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(type_ascription)] + +fn a() { + // the `22` is unreachable: + let x: [usize; 2] = [return, 22]; //~ ERROR unreachable +} + +fn b() { + // the array is unreachable: + let x: [usize; 2] = [22, return]; //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_array.stderr b/tests/ui/reachable/expr_array.stderr new file mode 100644 index 000000000..e144d7184 --- /dev/null +++ b/tests/ui/reachable/expr_array.stderr @@ -0,0 +1,25 @@ +error: unreachable expression + --> $DIR/expr_array.rs:9:34 + | +LL | let x: [usize; 2] = [return, 22]; + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable + | +note: the lint level is defined here + --> $DIR/expr_array.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable expression + --> $DIR/expr_array.rs:14:25 + | +LL | let x: [usize; 2] = [22, return]; + | ^^^^^------^ + | | | + | | any code following this expression is unreachable + | unreachable expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_assign.rs b/tests/ui/reachable/expr_assign.rs new file mode 100644 index 000000000..e547f75e2 --- /dev/null +++ b/tests/ui/reachable/expr_assign.rs @@ -0,0 +1,29 @@ +#![feature(never_type)] +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo() { + // No error here. + let x; + x = return; //~ ERROR unreachable +} + +fn bar() { + use std::ptr; + let p: *mut ! = ptr::null_mut::(); + unsafe { + // Here we consider the `return` unreachable because + // "evaluating" the `*p` has type `!`. This is somewhat + // dubious, I suppose. + *p = return; //~ ERROR unreachable + } +} + +fn baz() { + let mut i = 0; + *{return; &mut i} = 22; //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_assign.stderr b/tests/ui/reachable/expr_assign.stderr new file mode 100644 index 000000000..c51156b3f --- /dev/null +++ b/tests/ui/reachable/expr_assign.stderr @@ -0,0 +1,33 @@ +error: unreachable expression + --> $DIR/expr_assign.rs:10:5 + | +LL | x = return; + | ^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_assign.rs:5:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable expression + --> $DIR/expr_assign.rs:20:14 + | +LL | *p = return; + | -- ^^^^^^ unreachable expression + | | + | any code following this expression is unreachable + +error: unreachable expression + --> $DIR/expr_assign.rs:26:15 + | +LL | *{return; &mut i} = 22; + | ------ ^^^^^^ unreachable expression + | | + | any code following this expression is unreachable + +error: aborting due to 3 previous errors + diff --git a/tests/ui/reachable/expr_block.rs b/tests/ui/reachable/expr_block.rs new file mode 100644 index 000000000..136bccce8 --- /dev/null +++ b/tests/ui/reachable/expr_block.rs @@ -0,0 +1,31 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn a() { + // Here the tail expression is considered unreachable: + let x = { + return; + 22 //~ ERROR unreachable + }; +} + +fn b() { + // Here the `x` assignment is considered unreachable, not the block: + let x = { + return; + }; +} + +fn c() { + // Here the `println!` is unreachable: + let x = { + return; + println!("foo"); + //~^ ERROR unreachable statement + 22 + }; +} + +fn main() { } diff --git a/tests/ui/reachable/expr_block.stderr b/tests/ui/reachable/expr_block.stderr new file mode 100644 index 000000000..d5f248a24 --- /dev/null +++ b/tests/ui/reachable/expr_block.stderr @@ -0,0 +1,26 @@ +error: unreachable expression + --> $DIR/expr_block.rs:10:9 + | +LL | return; + | ------ any code following this expression is unreachable +LL | 22 + | ^^ unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_block.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable statement + --> $DIR/expr_block.rs:25:9 + | +LL | return; + | ------ any code following this expression is unreachable +LL | println!("foo"); + | ^^^^^^^^^^^^^^^ unreachable statement + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_box.rs b/tests/ui/reachable/expr_box.rs new file mode 100644 index 000000000..00328ea01 --- /dev/null +++ b/tests/ui/reachable/expr_box.rs @@ -0,0 +1,8 @@ +#![feature(box_syntax)] +#![allow(unused_variables)] +#![deny(unreachable_code)] + +fn main() { + let x = box return; //~ ERROR unreachable + println!("hi"); +} diff --git a/tests/ui/reachable/expr_box.stderr b/tests/ui/reachable/expr_box.stderr new file mode 100644 index 000000000..ea6472cbe --- /dev/null +++ b/tests/ui/reachable/expr_box.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_box.rs:6:13 + | +LL | let x = box return; + | ^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_box.rs:3:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_call.rs b/tests/ui/reachable/expr_call.rs new file mode 100644 index 000000000..1eaa96c3c --- /dev/null +++ b/tests/ui/reachable/expr_call.rs @@ -0,0 +1,21 @@ +#![feature(never_type)] +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo(x: !, y: usize) { } + +fn bar(x: !) { } + +fn a() { + // the `22` is unreachable: + foo(return, 22); //~ ERROR unreachable +} + +fn b() { + // the call is unreachable: + bar(return); //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_call.stderr b/tests/ui/reachable/expr_call.stderr new file mode 100644 index 000000000..a5ad9a329 --- /dev/null +++ b/tests/ui/reachable/expr_call.stderr @@ -0,0 +1,24 @@ +error: unreachable expression + --> $DIR/expr_call.rs:13:17 + | +LL | foo(return, 22); + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable + | +note: the lint level is defined here + --> $DIR/expr_call.rs:5:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable call + --> $DIR/expr_call.rs:18:5 + | +LL | bar(return); + | ^^^ ------ any code following this expression is unreachable + | | + | unreachable call + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_cast.rs b/tests/ui/reachable/expr_cast.rs new file mode 100644 index 000000000..e8e477ea4 --- /dev/null +++ b/tests/ui/reachable/expr_cast.rs @@ -0,0 +1,13 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(never_type, type_ascription)] + +fn a() { + // the cast is unreachable: + let x = {return} as !; //~ ERROR unreachable + //~| ERROR non-primitive cast +} + +fn main() { } diff --git a/tests/ui/reachable/expr_cast.stderr b/tests/ui/reachable/expr_cast.stderr new file mode 100644 index 000000000..6643f1784 --- /dev/null +++ b/tests/ui/reachable/expr_cast.stderr @@ -0,0 +1,24 @@ +error: unreachable expression + --> $DIR/expr_cast.rs:9:13 + | +LL | let x = {return} as !; + | ^------^^^^^^ + | || + | |any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_cast.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error[E0605]: non-primitive cast: `()` as `!` + --> $DIR/expr_cast.rs:9:13 + | +LL | let x = {return} as !; + | ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/reachable/expr_if.rs b/tests/ui/reachable/expr_if.rs new file mode 100644 index 000000000..3c04eaf48 --- /dev/null +++ b/tests/ui/reachable/expr_if.rs @@ -0,0 +1,31 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo() { + if {return} { //~ ERROR unreachable block in `if` + println!("Hello, world!"); + } +} + +fn bar() { + if {true} { + return; + } + println!("I am not dead."); +} + +fn baz() { + if {true} { + return; + } else { + return; + } + // As the next action to be taken after the if arms, we should + // report the `println!` as unreachable: + println!("But I am."); + //~^ ERROR unreachable statement +} + +fn main() { } diff --git a/tests/ui/reachable/expr_if.stderr b/tests/ui/reachable/expr_if.stderr new file mode 100644 index 000000000..ebd0b5a3e --- /dev/null +++ b/tests/ui/reachable/expr_if.stderr @@ -0,0 +1,30 @@ +error: unreachable block in `if` or `while` expression + --> $DIR/expr_if.rs:7:17 + | +LL | if {return} { + | _________------__^ + | | | + | | any code following this expression is unreachable +LL | | println!("Hello, world!"); +LL | | } + | |_____^ unreachable block in `if` or `while` expression + | +note: the lint level is defined here + --> $DIR/expr_if.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable statement + --> $DIR/expr_if.rs:27:5 + | +LL | return; + | ------ any code following this expression is unreachable +... +LL | println!("But I am."); + | ^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_loop.rs b/tests/ui/reachable/expr_loop.rs new file mode 100644 index 000000000..7eab6f7bb --- /dev/null +++ b/tests/ui/reachable/expr_loop.rs @@ -0,0 +1,36 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn a() { + loop { return; } + println!("I am dead."); + //~^ ERROR unreachable statement +} + +fn b() { + loop { + break; + } + println!("I am not dead."); +} + +fn c() { + loop { return; } + println!("I am dead."); + //~^ ERROR unreachable statement +} + +fn d() { + 'outer: loop { loop { break 'outer; } } + println!("I am not dead."); +} + +fn e() { + loop { 'middle: loop { loop { break 'middle; } } } + println!("I am dead."); + //~^ ERROR unreachable statement +} + +fn main() { } diff --git a/tests/ui/reachable/expr_loop.stderr b/tests/ui/reachable/expr_loop.stderr new file mode 100644 index 000000000..918584686 --- /dev/null +++ b/tests/ui/reachable/expr_loop.stderr @@ -0,0 +1,37 @@ +error: unreachable statement + --> $DIR/expr_loop.rs:8:5 + | +LL | loop { return; } + | ------ any code following this expression is unreachable +LL | println!("I am dead."); + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/expr_loop.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unreachable statement + --> $DIR/expr_loop.rs:21:5 + | +LL | loop { return; } + | ------ any code following this expression is unreachable +LL | println!("I am dead."); + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unreachable statement + --> $DIR/expr_loop.rs:32:5 + | +LL | loop { 'middle: loop { loop { break 'middle; } } } + | -------------------------------------------------- any code following this expression is unreachable +LL | println!("I am dead."); + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/reachable/expr_match.rs b/tests/ui/reachable/expr_match.rs new file mode 100644 index 000000000..2fd26b54e --- /dev/null +++ b/tests/ui/reachable/expr_match.rs @@ -0,0 +1,39 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn b() { + match () { () => return } + println!("I am dead"); + //~^ ERROR unreachable statement +} + +fn c() { + match () { () if false => return, () => () } + println!("I am not dead"); +} + +fn d() { + match () { () if false => return, () => return } + println!("I am dead"); + //~^ ERROR unreachable statement +} + +fn e() { + // Here the compiler fails to figure out that the `println` is dead. + match () { () if return => (), () => return } + println!("I am dead"); +} + +fn f() { + match Some(()) { None => (), Some(()) => return } + println!("I am not dead"); +} + +fn g() { + match Some(()) { None => return, Some(()) => () } + println!("I am not dead"); +} + +fn main() { } diff --git a/tests/ui/reachable/expr_match.stderr b/tests/ui/reachable/expr_match.stderr new file mode 100644 index 000000000..d15208609 --- /dev/null +++ b/tests/ui/reachable/expr_match.stderr @@ -0,0 +1,27 @@ +error: unreachable statement + --> $DIR/expr_match.rs:8:5 + | +LL | match () { () => return } + | ------------------------- any code following this `match` expression is unreachable, as all arms diverge +LL | println!("I am dead"); + | ^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/expr_match.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unreachable statement + --> $DIR/expr_match.rs:19:5 + | +LL | match () { () if false => return, () => return } + | ------------------------------------------------ any code following this `match` expression is unreachable, as all arms diverge +LL | println!("I am dead"); + | ^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_method.rs b/tests/ui/reachable/expr_method.rs new file mode 100644 index 000000000..d917df05b --- /dev/null +++ b/tests/ui/reachable/expr_method.rs @@ -0,0 +1,24 @@ +#![feature(never_type)] +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +struct Foo; + +impl Foo { + fn foo(&self, x: !, y: usize) { } + fn bar(&self, x: !) { } +} + +fn a() { + // the `22` is unreachable: + Foo.foo(return, 22); //~ ERROR unreachable +} + +fn b() { + // the call is unreachable: + Foo.bar(return); //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_method.stderr b/tests/ui/reachable/expr_method.stderr new file mode 100644 index 000000000..41c3b8a39 --- /dev/null +++ b/tests/ui/reachable/expr_method.stderr @@ -0,0 +1,24 @@ +error: unreachable expression + --> $DIR/expr_method.rs:16:21 + | +LL | Foo.foo(return, 22); + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable + | +note: the lint level is defined here + --> $DIR/expr_method.rs:5:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable call + --> $DIR/expr_method.rs:21:9 + | +LL | Foo.bar(return); + | ^^^ ------ any code following this expression is unreachable + | | + | unreachable call + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_oror.rs b/tests/ui/reachable/expr_oror.rs new file mode 100644 index 000000000..e95062de4 --- /dev/null +++ b/tests/ui/reachable/expr_oror.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(unused_variables)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo() { + let x = false || (return); + println!("I am not dead."); +} + +fn main() { } diff --git a/tests/ui/reachable/expr_repeat.rs b/tests/ui/reachable/expr_repeat.rs new file mode 100644 index 000000000..0fd13c6cb --- /dev/null +++ b/tests/ui/reachable/expr_repeat.rs @@ -0,0 +1,12 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(type_ascription)] + +fn a() { + // the repeat is unreachable: + let x: [usize; 2] = [return; 2]; //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_repeat.stderr b/tests/ui/reachable/expr_repeat.stderr new file mode 100644 index 000000000..defa87046 --- /dev/null +++ b/tests/ui/reachable/expr_repeat.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_repeat.rs:9:25 + | +LL | let x: [usize; 2] = [return; 2]; + | ^------^^^^ + | || + | |any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_repeat.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_return.rs b/tests/ui/reachable/expr_return.rs new file mode 100644 index 000000000..0fc43f450 --- /dev/null +++ b/tests/ui/reachable/expr_return.rs @@ -0,0 +1,13 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(type_ascription)] + +fn a() { + // Here we issue that the "2nd-innermost" return is unreachable, + // but we stop there. + let x = {return {return {return;}}}; //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_return.stderr b/tests/ui/reachable/expr_return.stderr new file mode 100644 index 000000000..e1bef80ae --- /dev/null +++ b/tests/ui/reachable/expr_return.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_return.rs:10:22 + | +LL | let x = {return {return {return;}}}; + | ^^^^^^^^------^^ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_return.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_return_in_macro.rs b/tests/ui/reachable/expr_return_in_macro.rs new file mode 100644 index 000000000..4e57618bf --- /dev/null +++ b/tests/ui/reachable/expr_return_in_macro.rs @@ -0,0 +1,15 @@ +// Tests that we generate nice error messages +// when an expression is unreachble due to control +// flow inside of a macro expansion. +#![deny(unreachable_code)] + +macro_rules! early_return { + () => { + return () + } +} + +fn main() { + return early_return!(); + //~^ ERROR unreachable expression +} diff --git a/tests/ui/reachable/expr_return_in_macro.stderr b/tests/ui/reachable/expr_return_in_macro.stderr new file mode 100644 index 000000000..3c562a7ee --- /dev/null +++ b/tests/ui/reachable/expr_return_in_macro.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_return_in_macro.rs:13:5 + | +LL | return () + | --------- any code following this expression is unreachable +... +LL | return early_return!(); + | ^^^^^^^^^^^^^^^^^^^^^^ unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_return_in_macro.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_struct.rs b/tests/ui/reachable/expr_struct.rs new file mode 100644 index 000000000..31ab40582 --- /dev/null +++ b/tests/ui/reachable/expr_struct.rs @@ -0,0 +1,32 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(type_ascription)] + +struct Foo { + a: usize, + b: usize, +} + +fn a() { + // struct expr is unreachable: + let x = Foo { a: 22, b: 33, ..return }; //~ ERROR unreachable +} + +fn b() { + // the `33` is unreachable: + let x = Foo { a: return, b: 33, ..return }; //~ ERROR unreachable +} + +fn c() { + // the `..return` is unreachable: + let x = Foo { a: 22, b: return, ..return }; //~ ERROR unreachable +} + +fn d() { + // the struct expr is unreachable: + let x = Foo { a: 22, b: return }; //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_struct.stderr b/tests/ui/reachable/expr_struct.stderr new file mode 100644 index 000000000..36b070456 --- /dev/null +++ b/tests/ui/reachable/expr_struct.stderr @@ -0,0 +1,42 @@ +error: unreachable expression + --> $DIR/expr_struct.rs:14:13 + | +LL | let x = Foo { a: 22, b: 33, ..return }; + | ^^^^^^^^^^^^^^^^^^^^^^------^^ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_struct.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable expression + --> $DIR/expr_struct.rs:19:33 + | +LL | let x = Foo { a: return, b: 33, ..return }; + | ------ ^^ unreachable expression + | | + | any code following this expression is unreachable + +error: unreachable expression + --> $DIR/expr_struct.rs:24:39 + | +LL | let x = Foo { a: 22, b: return, ..return }; + | ------ ^^^^^^ unreachable expression + | | + | any code following this expression is unreachable + +error: unreachable expression + --> $DIR/expr_struct.rs:29:13 + | +LL | let x = Foo { a: 22, b: return }; + | ^^^^^^^^^^^^^^^^------^^ + | | | + | | any code following this expression is unreachable + | unreachable expression + +error: aborting due to 4 previous errors + diff --git a/tests/ui/reachable/expr_tup.rs b/tests/ui/reachable/expr_tup.rs new file mode 100644 index 000000000..90d4382e2 --- /dev/null +++ b/tests/ui/reachable/expr_tup.rs @@ -0,0 +1,17 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(type_ascription)] + +fn a() { + // the `2` is unreachable: + let x: (usize, usize) = (return, 2); //~ ERROR unreachable +} + +fn b() { + // the tuple is unreachable: + let x: (usize, usize) = (2, return); //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_tup.stderr b/tests/ui/reachable/expr_tup.stderr new file mode 100644 index 000000000..5ea6bf4ab --- /dev/null +++ b/tests/ui/reachable/expr_tup.stderr @@ -0,0 +1,25 @@ +error: unreachable expression + --> $DIR/expr_tup.rs:9:38 + | +LL | let x: (usize, usize) = (return, 2); + | ------ ^ unreachable expression + | | + | any code following this expression is unreachable + | +note: the lint level is defined here + --> $DIR/expr_tup.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable expression + --> $DIR/expr_tup.rs:14:29 + | +LL | let x: (usize, usize) = (2, return); + | ^^^^------^ + | | | + | | any code following this expression is unreachable + | unreachable expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/expr_type.rs b/tests/ui/reachable/expr_type.rs new file mode 100644 index 000000000..1ceb2f859 --- /dev/null +++ b/tests/ui/reachable/expr_type.rs @@ -0,0 +1,12 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] +#![feature(never_type, type_ascription)] + +fn a() { + // the cast is unreachable: + let x = type_ascribe!({return}, !); //~ ERROR unreachable +} + +fn main() { } diff --git a/tests/ui/reachable/expr_type.stderr b/tests/ui/reachable/expr_type.stderr new file mode 100644 index 000000000..3cb4a32e0 --- /dev/null +++ b/tests/ui/reachable/expr_type.stderr @@ -0,0 +1,17 @@ +error: unreachable expression + --> $DIR/expr_type.rs:9:13 + | +LL | let x = type_ascribe!({return}, !); + | ^^^^^^^^^^^^^^^------^^^^^ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_type.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/expr_unary.rs b/tests/ui/reachable/expr_unary.rs new file mode 100644 index 000000000..190c7447d --- /dev/null +++ b/tests/ui/reachable/expr_unary.rs @@ -0,0 +1,12 @@ +#![feature(never_type)] +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo() { + let x: ! = * { return; }; //~ ERROR unreachable + //~| ERROR type `!` cannot be dereferenced +} + +fn main() { } diff --git a/tests/ui/reachable/expr_unary.stderr b/tests/ui/reachable/expr_unary.stderr new file mode 100644 index 000000000..0a763087c --- /dev/null +++ b/tests/ui/reachable/expr_unary.stderr @@ -0,0 +1,24 @@ +error[E0614]: type `!` cannot be dereferenced + --> $DIR/expr_unary.rs:8:16 + | +LL | let x: ! = * { return; }; + | ^^^^^^^^^^^^^ + +error: unreachable expression + --> $DIR/expr_unary.rs:8:16 + | +LL | let x: ! = * { return; }; + | ^^^^------^^^ + | | | + | | any code following this expression is unreachable + | unreachable expression + | +note: the lint level is defined here + --> $DIR/expr_unary.rs:5:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0614`. diff --git a/tests/ui/reachable/expr_while.rs b/tests/ui/reachable/expr_while.rs new file mode 100644 index 000000000..5005f3833 --- /dev/null +++ b/tests/ui/reachable/expr_while.rs @@ -0,0 +1,29 @@ +#![allow(unused_variables)] +#![allow(unused_assignments)] +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn foo() { + while {return} { + //~^ ERROR unreachable block in `if` + println!("Hello, world!"); + } +} + +fn bar() { + while {true} { + return; + } + println!("I am not dead."); +} + +fn baz() { + // Here, we cite the `while` loop as dead. + while {return} { + //~^ ERROR unreachable block in `if` + println!("I am dead."); + } + println!("I am, too."); +} + +fn main() { } diff --git a/tests/ui/reachable/expr_while.stderr b/tests/ui/reachable/expr_while.stderr new file mode 100644 index 000000000..b1859f619 --- /dev/null +++ b/tests/ui/reachable/expr_while.stderr @@ -0,0 +1,32 @@ +error: unreachable block in `if` or `while` expression + --> $DIR/expr_while.rs:7:20 + | +LL | while {return} { + | ____________------__^ + | | | + | | any code following this expression is unreachable +LL | | +LL | | println!("Hello, world!"); +LL | | } + | |_____^ unreachable block in `if` or `while` expression + | +note: the lint level is defined here + --> $DIR/expr_while.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable block in `if` or `while` expression + --> $DIR/expr_while.rs:22:20 + | +LL | while {return} { + | ____________------__^ + | | | + | | any code following this expression is unreachable +LL | | +LL | | println!("I am dead."); +LL | | } + | |_____^ unreachable block in `if` or `while` expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/issue-11225-1.rs b/tests/ui/reachable/issue-11225-1.rs new file mode 100644 index 000000000..d1f2ea5e7 --- /dev/null +++ b/tests/ui/reachable/issue-11225-1.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-11225-1.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_11225_1 as foo; + +pub fn main() { + foo::foo(1); + foo::foo_ufcs(1); +} diff --git a/tests/ui/reachable/issue-11225-2.rs b/tests/ui/reachable/issue-11225-2.rs new file mode 100644 index 000000000..d41c75443 --- /dev/null +++ b/tests/ui/reachable/issue-11225-2.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-11225-2.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_11225_2 as foo; + +pub fn main() { + foo::foo(1); + foo::foo_ufcs(1); +} diff --git a/tests/ui/reachable/issue-11225-3.rs b/tests/ui/reachable/issue-11225-3.rs new file mode 100644 index 000000000..e69496baa --- /dev/null +++ b/tests/ui/reachable/issue-11225-3.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:issue-11225-3.rs + +// pretty-expanded FIXME #23616 + +extern crate issue_11225_3; + +pub fn main() { + issue_11225_3::public_inlinable_function(); + issue_11225_3::public_inlinable_function_ufcs(); +} diff --git a/tests/ui/reachable/unreachable-arm.rs b/tests/ui/reachable/unreachable-arm.rs new file mode 100644 index 000000000..3277bf0d5 --- /dev/null +++ b/tests/ui/reachable/unreachable-arm.rs @@ -0,0 +1,14 @@ +#![feature(box_patterns)] + +#![allow(dead_code)] +#![deny(unreachable_patterns)] + +enum Foo { A(Box, isize), B(usize), } + +fn main() { + match Foo::B(1) { + Foo::B(_) | Foo::A(box _, 1) => { } + Foo::A(_, 1) => { } //~ ERROR unreachable pattern + _ => { } + } +} diff --git a/tests/ui/reachable/unreachable-arm.stderr b/tests/ui/reachable/unreachable-arm.stderr new file mode 100644 index 000000000..1cbea8288 --- /dev/null +++ b/tests/ui/reachable/unreachable-arm.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/unreachable-arm.rs:11:9 + | +LL | Foo::A(_, 1) => { } + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unreachable-arm.rs:4:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/unreachable-code-ret.rs b/tests/ui/reachable/unreachable-code-ret.rs new file mode 100644 index 000000000..fad35794f --- /dev/null +++ b/tests/ui/reachable/unreachable-code-ret.rs @@ -0,0 +1,8 @@ +// error-pattern: unreachable statement + +#![deny(unreachable_code)] + +fn main() { + return; + println!("Paul is dead"); +} diff --git a/tests/ui/reachable/unreachable-code-ret.stderr b/tests/ui/reachable/unreachable-code-ret.stderr new file mode 100644 index 000000000..263a1b5a9 --- /dev/null +++ b/tests/ui/reachable/unreachable-code-ret.stderr @@ -0,0 +1,17 @@ +error: unreachable statement + --> $DIR/unreachable-code-ret.rs:7:5 + | +LL | return; + | ------ any code following this expression is unreachable +LL | println!("Paul is dead"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/unreachable-code-ret.rs:3:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/reachable/unreachable-code.rs b/tests/ui/reachable/unreachable-code.rs new file mode 100644 index 000000000..ad0dc8a8b --- /dev/null +++ b/tests/ui/reachable/unreachable-code.rs @@ -0,0 +1,8 @@ +#![deny(unreachable_code)] +#![allow(unused_variables)] + +fn main() { + loop{} + + let a = 3; //~ ERROR: unreachable statement +} diff --git a/tests/ui/reachable/unreachable-code.stderr b/tests/ui/reachable/unreachable-code.stderr new file mode 100644 index 000000000..cb1b760c2 --- /dev/null +++ b/tests/ui/reachable/unreachable-code.stderr @@ -0,0 +1,17 @@ +error: unreachable statement + --> $DIR/unreachable-code.rs:7:3 + | +LL | loop{} + | ------ any code following this expression is unreachable +LL | +LL | let a = 3; + | ^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/unreachable-code.rs:1:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/unreachable-in-call.rs b/tests/ui/reachable/unreachable-in-call.rs new file mode 100644 index 000000000..dd94e79f4 --- /dev/null +++ b/tests/ui/reachable/unreachable-in-call.rs @@ -0,0 +1,22 @@ +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn diverge() -> ! { panic!() } + +fn get_u8() -> u8 { + 1 +} +fn call(_: u8, _: u8) { + +} +fn diverge_first() { + call(diverge(), + get_u8()); //~ ERROR unreachable expression +} +fn diverge_second() { + call( //~ ERROR unreachable call + get_u8(), + diverge()); +} + +fn main() {} diff --git a/tests/ui/reachable/unreachable-in-call.stderr b/tests/ui/reachable/unreachable-in-call.stderr new file mode 100644 index 000000000..cdfa79bf8 --- /dev/null +++ b/tests/ui/reachable/unreachable-in-call.stderr @@ -0,0 +1,25 @@ +error: unreachable expression + --> $DIR/unreachable-in-call.rs:14:10 + | +LL | call(diverge(), + | --------- any code following this expression is unreachable +LL | get_u8()); + | ^^^^^^^^ unreachable expression + | +note: the lint level is defined here + --> $DIR/unreachable-in-call.rs:2:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable call + --> $DIR/unreachable-in-call.rs:17:5 + | +LL | call( + | ^^^^ unreachable call +LL | get_u8(), +LL | diverge()); + | --------- any code following this expression is unreachable + +error: aborting due to 2 previous errors + diff --git a/tests/ui/reachable/unreachable-loop-patterns.rs b/tests/ui/reachable/unreachable-loop-patterns.rs new file mode 100644 index 000000000..e9cef5f47 --- /dev/null +++ b/tests/ui/reachable/unreachable-loop-patterns.rs @@ -0,0 +1,20 @@ +#![feature(never_type, never_type_fallback)] +#![feature(exhaustive_patterns)] + +#![allow(unreachable_code)] +#![deny(unreachable_patterns)] + +enum Void {} + +impl Iterator for Void { + type Item = Void; + + fn next(&mut self) -> Option { + None + } +} + +fn main() { + for _ in unimplemented!() as Void {} + //~^ ERROR unreachable pattern +} diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr new file mode 100644 index 000000000..80ffa5d73 --- /dev/null +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/unreachable-loop-patterns.rs:18:9 + | +LL | for _ in unimplemented!() as Void {} + | ^ + | +note: the lint level is defined here + --> $DIR/unreachable-loop-patterns.rs:5:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/reachable/unreachable-try-pattern.rs b/tests/ui/reachable/unreachable-try-pattern.rs new file mode 100644 index 000000000..23360e73f --- /dev/null +++ b/tests/ui/reachable/unreachable-try-pattern.rs @@ -0,0 +1,41 @@ +// check-pass +#![feature(never_type, exhaustive_patterns)] +#![warn(unreachable_code)] +#![warn(unreachable_patterns)] + +enum Void {} + +impl From for i32 { + fn from(v: Void) -> i32 { + match v {} + } +} + +fn bar(x: Result) -> Result { + x? +} + +fn foo(x: Result) -> Result { + let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; + //~^ WARN unreachable pattern + //~| WARN unreachable expression + Ok(y) +} + +fn qux(x: Result) -> Result { + Ok(x?) +} + +fn vom(x: Result) -> Result { + let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; + //~^ WARN unreachable pattern + Ok(y) +} + + +fn main() { + let _ = bar(Err(123)); + let _ = foo(Err(123)); + let _ = qux(Ok(123)); + let _ = vom(Ok(123)); +} diff --git a/tests/ui/reachable/unreachable-try-pattern.stderr b/tests/ui/reachable/unreachable-try-pattern.stderr new file mode 100644 index 000000000..8f3e23119 --- /dev/null +++ b/tests/ui/reachable/unreachable-try-pattern.stderr @@ -0,0 +1,35 @@ +warning: unreachable expression + --> $DIR/unreachable-try-pattern.rs:19:36 + | +LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; + | -^^^^^^^ + | | + | unreachable expression + | any code following this expression is unreachable + | +note: the lint level is defined here + --> $DIR/unreachable-try-pattern.rs:3:9 + | +LL | #![warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unreachable pattern + --> $DIR/unreachable-try-pattern.rs:19:24 + | +LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/unreachable-try-pattern.rs:4:9 + | +LL | #![warn(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: unreachable pattern + --> $DIR/unreachable-try-pattern.rs:30:40 + | +LL | let y = (match x { Ok(n) => Ok(n), Err(e) => Err(e) })?; + | ^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/reachable/unreachable-variant.rs b/tests/ui/reachable/unreachable-variant.rs new file mode 100644 index 000000000..008c2d476 --- /dev/null +++ b/tests/ui/reachable/unreachable-variant.rs @@ -0,0 +1,7 @@ +// aux-build:unreachable_variant.rs + +extern crate unreachable_variant as other; + +fn main() { + let _x = other::super_sekrit::sooper_sekrit::baz; //~ ERROR is private +} diff --git a/tests/ui/reachable/unreachable-variant.stderr b/tests/ui/reachable/unreachable-variant.stderr new file mode 100644 index 000000000..6c27a2756 --- /dev/null +++ b/tests/ui/reachable/unreachable-variant.stderr @@ -0,0 +1,15 @@ +error[E0603]: module `super_sekrit` is private + --> $DIR/unreachable-variant.rs:6:21 + | +LL | let _x = other::super_sekrit::sooper_sekrit::baz; + | ^^^^^^^^^^^^ private module + | +note: the module `super_sekrit` is defined here + --> $DIR/auxiliary/unreachable_variant.rs:1:1 + | +LL | mod super_sekrit { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/reachable/unwarned-match-on-never.rs b/tests/ui/reachable/unwarned-match-on-never.rs new file mode 100644 index 000000000..71f8fe3a7 --- /dev/null +++ b/tests/ui/reachable/unwarned-match-on-never.rs @@ -0,0 +1,24 @@ +#![deny(unreachable_code)] +#![allow(dead_code)] + +#![feature(never_type)] + +fn foo(x: !) -> bool { + // Explicit matches on the never type are unwarned. + match x {} + // But matches in unreachable code are warned. + match x {} //~ ERROR unreachable expression +} + +fn bar() { + match (return) { + () => () //~ ERROR unreachable arm + } +} + +fn main() { + return; + match () { //~ ERROR unreachable expression + () => (), + } +} diff --git a/tests/ui/reachable/unwarned-match-on-never.stderr b/tests/ui/reachable/unwarned-match-on-never.stderr new file mode 100644 index 000000000..a296d2a05 --- /dev/null +++ b/tests/ui/reachable/unwarned-match-on-never.stderr @@ -0,0 +1,35 @@ +error: unreachable expression + --> $DIR/unwarned-match-on-never.rs:10:5 + | +LL | match x {} + | - any code following this expression is unreachable +LL | // But matches in unreachable code are warned. +LL | match x {} + | ^^^^^^^^^^ unreachable expression + | +note: the lint level is defined here + --> $DIR/unwarned-match-on-never.rs:1:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: unreachable arm + --> $DIR/unwarned-match-on-never.rs:15:15 + | +LL | match (return) { + | -------- any code following this expression is unreachable +LL | () => () + | ^^ unreachable arm + +error: unreachable expression + --> $DIR/unwarned-match-on-never.rs:21:5 + | +LL | return; + | ------ any code following this expression is unreachable +LL | / match () { +LL | | () => (), +LL | | } + | |_____^ unreachable expression + +error: aborting due to 3 previous errors + diff --git a/tests/ui/realloc-16687.rs b/tests/ui/realloc-16687.rs new file mode 100644 index 000000000..92d98c16c --- /dev/null +++ b/tests/ui/realloc-16687.rs @@ -0,0 +1,188 @@ +// run-pass +// alloc::heap::reallocate test. +// +// Ideally this would be revised to use no_std, but for now it serves +// well enough to reproduce (and illustrate) the bug from #16687. + +#![feature(allocator_api)] +#![feature(slice_ptr_get)] + +use std::alloc::{handle_alloc_error, Allocator, Global, Layout}; +use std::ptr::{self, NonNull}; + +fn main() { + unsafe { + assert!(test_triangle()); + } +} + +unsafe fn test_triangle() -> bool { + static COUNT: usize = 16; + let mut ascend = vec![ptr::null_mut(); COUNT]; + let ascend = &mut *ascend; + static ALIGN: usize = 1; + + // Checks that `ascend` forms triangle of ascending size formed + // from pairs of rows (where each pair of rows is equally sized), + // and the elements of the triangle match their row-pair index. + unsafe fn sanity_check(ascend: &[*mut u8]) { + for i in 0..COUNT / 2 { + let (p0, p1, size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); + for j in 0..size { + assert_eq!(*p0.add(j), i as u8); + assert_eq!(*p1.add(j), i as u8); + } + } + } + + static PRINT: bool = false; + + unsafe fn allocate(layout: Layout) -> *mut u8 { + if PRINT { + println!("allocate({:?})", layout); + } + + let ptr = Global.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + + if PRINT { + println!("allocate({:?}) = {:?}", layout, ptr); + } + + ptr.as_mut_ptr() + } + + unsafe fn deallocate(ptr: *mut u8, layout: Layout) { + if PRINT { + println!("deallocate({:?}, {:?}", ptr, layout); + } + + Global.deallocate(NonNull::new_unchecked(ptr), layout); + } + + unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 { + if PRINT { + println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new); + } + + let memory = if new.size() > old.size() { + Global.grow(NonNull::new_unchecked(ptr), old, new) + } else { + Global.shrink(NonNull::new_unchecked(ptr), old, new) + }; + + let ptr = memory.unwrap_or_else(|_| handle_alloc_error(new)); + + if PRINT { + println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", ptr, old, new, ptr); + } + ptr.as_mut_ptr() + } + + fn idx_to_size(i: usize) -> usize { + (i + 1) * 10 + } + + // Allocate pairs of rows that form a triangle shape. (Hope is + // that at least two rows will be allocated near each other, so + // that we trigger the bug (a buffer overrun) in an observable + // way.) + for i in 0..COUNT / 2 { + let size = idx_to_size(i); + ascend[2 * i] = allocate(Layout::from_size_align(size, ALIGN).unwrap()); + ascend[2 * i + 1] = allocate(Layout::from_size_align(size, ALIGN).unwrap()); + } + + // Initialize each pair of rows to distinct value. + for i in 0..COUNT / 2 { + let (p0, p1, size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); + for j in 0..size { + *p0.add(j) = i as u8; + *p1.add(j) = i as u8; + } + } + + sanity_check(&*ascend); + test_1(ascend); // triangle -> square + test_2(ascend); // square -> triangle + test_3(ascend); // triangle -> square + test_4(ascend); // square -> triangle + + for i in 0..COUNT / 2 { + let size = idx_to_size(i); + deallocate(ascend[2 * i], Layout::from_size_align(size, ALIGN).unwrap()); + deallocate(ascend[2 * i + 1], Layout::from_size_align(size, ALIGN).unwrap()); + } + + return true; + + // Test 1: turn the triangle into a square (in terms of + // allocation; initialized portion remains a triangle) by + // realloc'ing each row from top to bottom, and checking all the + // rows as we go. + unsafe fn test_1(ascend: &mut [*mut u8]) { + let new_size = idx_to_size(COUNT - 1); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); + for i in 0..COUNT / 2 { + let (p0, p1, old_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); + assert!(old_size < new_size); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); + + ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); + sanity_check(&*ascend); + + ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); + sanity_check(&*ascend); + } + } + + // Test 2: turn the square back into a triangle, top to bottom. + unsafe fn test_2(ascend: &mut [*mut u8]) { + let old_size = idx_to_size(COUNT - 1); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); + for i in 0..COUNT / 2 { + let (p0, p1, new_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); + assert!(new_size < old_size); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); + + ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); + sanity_check(&*ascend); + + ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); + sanity_check(&*ascend); + } + } + + // Test 3: turn triangle into a square, bottom to top. + unsafe fn test_3(ascend: &mut [*mut u8]) { + let new_size = idx_to_size(COUNT - 1); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); + for i in (0..COUNT / 2).rev() { + let (p0, p1, old_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); + assert!(old_size < new_size); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); + + ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); + sanity_check(&*ascend); + + ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); + sanity_check(&*ascend); + } + } + + // Test 4: turn the square back into a triangle, bottom to top. + unsafe fn test_4(ascend: &mut [*mut u8]) { + let old_size = idx_to_size(COUNT - 1); + let old = Layout::from_size_align(old_size, ALIGN).unwrap(); + for i in (0..COUNT / 2).rev() { + let (p0, p1, new_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i)); + assert!(new_size < old_size); + let new = Layout::from_size_align(new_size, ALIGN).unwrap(); + + ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone()); + sanity_check(&*ascend); + + ascend[2 * i] = reallocate(p0, old.clone(), new.clone()); + sanity_check(&*ascend); + } + } +} diff --git a/tests/ui/reassign-ref-mut.rs b/tests/ui/reassign-ref-mut.rs new file mode 100644 index 000000000..d6d41e959 --- /dev/null +++ b/tests/ui/reassign-ref-mut.rs @@ -0,0 +1,16 @@ +// Tests how we behave when the user attempts to mutate an immutable +// binding that was introduced by either `ref` or `ref mut` +// patterns. +// +// Such bindings cannot be made mutable via the mere addition of the +// `mut` keyword, and thus we want to check that the compiler does not +// suggest doing so. + +fn main() { + let (mut one_two, mut three_four) = ((1, 2), (3, 4)); + let &mut (ref a, ref mut b) = &mut one_two; + a = &three_four.0; + //~^ ERROR cannot assign twice to immutable variable `a` [E0384] + b = &mut three_four.1; + //~^ ERROR cannot assign twice to immutable variable `b` [E0384] +} diff --git a/tests/ui/reassign-ref-mut.stderr b/tests/ui/reassign-ref-mut.stderr new file mode 100644 index 000000000..e623578e0 --- /dev/null +++ b/tests/ui/reassign-ref-mut.stderr @@ -0,0 +1,20 @@ +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/reassign-ref-mut.rs:12:5 + | +LL | let &mut (ref a, ref mut b) = &mut one_two; + | ----- first assignment to `a` +LL | a = &three_four.0; + | ^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `b` + --> $DIR/reassign-ref-mut.rs:14:5 + | +LL | let &mut (ref a, ref mut b) = &mut one_two; + | --------- first assignment to `b` +... +LL | b = &mut three_four.1; + | ^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/recursion/auxiliary/recursive_reexports.rs b/tests/ui/recursion/auxiliary/recursive_reexports.rs new file mode 100644 index 000000000..f98fa7100 --- /dev/null +++ b/tests/ui/recursion/auxiliary/recursive_reexports.rs @@ -0,0 +1,3 @@ +pub mod foo { + pub use foo; +} diff --git a/tests/ui/recursion/instantiable.rs b/tests/ui/recursion/instantiable.rs new file mode 100644 index 000000000..ad0cf3f4a --- /dev/null +++ b/tests/ui/recursion/instantiable.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +use std::ptr; + +// check that we do not report a type like this as uninstantiable, +// even though it would be if the nxt field had type @foo: +struct foo(X); + +struct X { x: usize, nxt: *const foo } + +pub fn main() { + let _x = foo(X {x: 0, nxt: ptr::null()}); +} diff --git a/tests/ui/recursion/issue-26548-recursion-via-normalize.rs b/tests/ui/recursion/issue-26548-recursion-via-normalize.rs new file mode 100644 index 000000000..91958dffc --- /dev/null +++ b/tests/ui/recursion/issue-26548-recursion-via-normalize.rs @@ -0,0 +1,17 @@ +//~ ERROR cycle detected when computing layout of `core::option::Option` +//~| NOTE ...which requires computing layout of `S`... +//~| NOTE ...which requires computing layout of `core::option::Option<::It>`... +//~| NOTE ...which again requires computing layout of `core::option::Option`, completing the cycle +//~| NOTE cycle used when computing layout of `core::option::Option<::It>` + +trait Mirror { + type It: ?Sized; +} +impl Mirror for T { + type It = Self; +} +struct S(Option<::It>); + +fn main() { + let _s = S(None); +} diff --git a/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr b/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr new file mode 100644 index 000000000..a75097cdb --- /dev/null +++ b/tests/ui/recursion/issue-26548-recursion-via-normalize.stderr @@ -0,0 +1,10 @@ +error[E0391]: cycle detected when computing layout of `core::option::Option` + | + = note: ...which requires computing layout of `S`... + = note: ...which requires computing layout of `core::option::Option<::It>`... + = note: ...which again requires computing layout of `core::option::Option`, completing the cycle + = note: cycle used when computing layout of `core::option::Option<::It>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr new file mode 100644 index 000000000..4b4fc4fb7 --- /dev/null +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `std::ptr::drop_in_place::))` + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | pub unsafe fn drop_in_place(to_drop: *mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `std::ptr::drop_in_place` defined here + --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL + | +LL | pub unsafe fn drop_in_place(to_drop: *mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion.polonius/issue-38591-non-regular-dropck-recursion.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs new file mode 100644 index 000000000..c9e93174e --- /dev/null +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -0,0 +1,16 @@ +// `S` is infinitely recursing so it's not possible to generate a finite +// drop impl (ignoring polymorphization). +// +// Dropck should therefore detect that this is the case and eagerly error. + +struct S { + t: T, + s: Box>, +} + +fn f(x: S) {} //~ ERROR overflow while adding drop-check rules for S + +fn main() { + // Force instantiation. + f as fn(_); +} diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr new file mode 100644 index 000000000..002dfe115 --- /dev/null +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -0,0 +1,11 @@ +error[E0320]: overflow while adding drop-check rules for S + --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11:6 + | +LL | fn f(x: S) {} + | ^ + | + = note: overflowed on S + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0320`. diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs new file mode 100644 index 000000000..38353d161 --- /dev/null +++ b/tests/ui/recursion/issue-83150.rs @@ -0,0 +1,13 @@ +// build-fail +// compile-flags: -Copt-level=0 +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" +//~^^^ ERROR overflow evaluating the requirement + +fn main() { + let mut iter = 0u8..1; + func(&mut iter) +} + +fn func>(iter: &mut T) { //~ WARN function cannot return without recursing + func(&mut iter.map(|x| x + 1)) +} diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr new file mode 100644 index 000000000..dde8ad1b6 --- /dev/null +++ b/tests/ui/recursion/issue-83150.stderr @@ -0,0 +1,20 @@ +warning: function cannot return without recursing + --> $DIR/issue-83150.rs:11:1 + | +LL | fn func>(iter: &mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | func(&mut iter.map(|x| x + 1)) + | ------------------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator` + = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt' + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/recursion/issue-86784.rs b/tests/ui/recursion/issue-86784.rs new file mode 100644 index 000000000..34f4aaedb --- /dev/null +++ b/tests/ui/recursion/issue-86784.rs @@ -0,0 +1,2597 @@ +// build-pass + +fn main() { + let _temp_1 = 0; + let _temp_2 = 0; + let _temp_3 = 0; + let _temp_4 = 0; + let _temp_5 = 0; + let _temp_6 = 0; + let _temp_7 = 0; + let _temp_8 = 0; + let _temp_9 = 0; + let _temp_10 = 0; + let _temp_11 = 0; + let _temp_12 = 0; + let _temp_13 = 0; + let _temp_14 = 0; + let _temp_15 = 0; + let _temp_16 = 0; + let _temp_17 = 0; + let _temp_18 = 0; + let _temp_19 = 0; + let _temp_20 = 0; + let _temp_21 = 0; + let _temp_22 = 0; + let _temp_23 = 0; + let _temp_24 = 0; + let _temp_25 = 0; + let _temp_26 = 0; + let _temp_27 = 0; + let _temp_28 = 0; + let _temp_29 = 0; + let _temp_30 = 0; + let _temp_31 = 0; + let _temp_32 = 0; + let _temp_33 = 0; + let _temp_34 = 0; + let _temp_35 = 0; + let _temp_36 = 0; + let _temp_37 = 0; + let _temp_38 = 0; + let _temp_39 = 0; + let _temp_40 = 0; + let _temp_41 = 0; + let _temp_42 = 0; + let _temp_43 = 0; + let _temp_44 = 0; + let _temp_45 = 0; + let _temp_46 = 0; + let _temp_47 = 0; + let _temp_48 = 0; + let _temp_49 = 0; + let _temp_50 = 0; + let _temp_51 = 0; + let _temp_52 = 0; + let _temp_53 = 0; + let _temp_54 = 0; + let _temp_55 = 0; + let _temp_56 = 0; + let _temp_57 = 0; + let _temp_58 = 0; + let _temp_59 = 0; + let _temp_60 = 0; + let _temp_61 = 0; + let _temp_62 = 0; + let _temp_63 = 0; + let _temp_64 = 0; + let _temp_65 = 0; + let _temp_66 = 0; + let _temp_67 = 0; + let _temp_68 = 0; + let _temp_69 = 0; + let _temp_70 = 0; + let _temp_71 = 0; + let _temp_72 = 0; + let _temp_73 = 0; + let _temp_74 = 0; + let _temp_75 = 0; + let _temp_76 = 0; + let _temp_77 = 0; + let _temp_78 = 0; + let _temp_79 = 0; + let _temp_80 = 0; + let _temp_81 = 0; + let _temp_82 = 0; + let _temp_83 = 0; + let _temp_84 = 0; + let _temp_85 = 0; + let _temp_86 = 0; + let _temp_87 = 0; + let _temp_88 = 0; + let _temp_89 = 0; + let _temp_90 = 0; + let _temp_91 = 0; + let _temp_92 = 0; + let _temp_93 = 0; + let _temp_94 = 0; + let _temp_95 = 0; + let _temp_96 = 0; + let _temp_97 = 0; + let _temp_98 = 0; + let _temp_99 = 0; + let _temp_100 = 0; + let _temp_101 = 0; + let _temp_102 = 0; + let _temp_103 = 0; + let _temp_104 = 0; + let _temp_105 = 0; + let _temp_106 = 0; + let _temp_107 = 0; + let _temp_108 = 0; + let _temp_109 = 0; + let _temp_110 = 0; + let _temp_111 = 0; + let _temp_112 = 0; + let _temp_113 = 0; + let _temp_114 = 0; + let _temp_115 = 0; + let _temp_116 = 0; + let _temp_117 = 0; + let _temp_118 = 0; + let _temp_119 = 0; + let _temp_120 = 0; + let _temp_121 = 0; + let _temp_122 = 0; + let _temp_123 = 0; + let _temp_124 = 0; + let _temp_125 = 0; + let _temp_126 = 0; + let _temp_127 = 0; + let _temp_128 = 0; + let _temp_129 = 0; + let _temp_130 = 0; + let _temp_131 = 0; + let _temp_132 = 0; + let _temp_133 = 0; + let _temp_134 = 0; + let _temp_135 = 0; + let _temp_136 = 0; + let _temp_137 = 0; + let _temp_138 = 0; + let _temp_139 = 0; + let _temp_140 = 0; + let _temp_141 = 0; + let _temp_142 = 0; + let _temp_143 = 0; + let _temp_144 = 0; + let _temp_145 = 0; + let _temp_146 = 0; + let _temp_147 = 0; + let _temp_148 = 0; + let _temp_149 = 0; + let _temp_150 = 0; + let _temp_151 = 0; + let _temp_152 = 0; + let _temp_153 = 0; + let _temp_154 = 0; + let _temp_155 = 0; + let _temp_156 = 0; + let _temp_157 = 0; + let _temp_158 = 0; + let _temp_159 = 0; + let _temp_160 = 0; + let _temp_161 = 0; + let _temp_162 = 0; + let _temp_163 = 0; + let _temp_164 = 0; + let _temp_165 = 0; + let _temp_166 = 0; + let _temp_167 = 0; + let _temp_168 = 0; + let _temp_169 = 0; + let _temp_170 = 0; + let _temp_171 = 0; + let _temp_172 = 0; + let _temp_173 = 0; + let _temp_174 = 0; + let _temp_175 = 0; + let _temp_176 = 0; + let _temp_177 = 0; + let _temp_178 = 0; + let _temp_179 = 0; + let _temp_180 = 0; + let _temp_181 = 0; + let _temp_182 = 0; + let _temp_183 = 0; + let _temp_184 = 0; + let _temp_185 = 0; + let _temp_186 = 0; + let _temp_187 = 0; + let _temp_188 = 0; + let _temp_189 = 0; + let _temp_190 = 0; + let _temp_191 = 0; + let _temp_192 = 0; + let _temp_193 = 0; + let _temp_194 = 0; + let _temp_195 = 0; + let _temp_196 = 0; + let _temp_197 = 0; + let _temp_198 = 0; + let _temp_199 = 0; + let _temp_200 = 0; + let _temp_201 = 0; + let _temp_202 = 0; + let _temp_203 = 0; + let _temp_204 = 0; + let _temp_205 = 0; + let _temp_206 = 0; + let _temp_207 = 0; + let _temp_208 = 0; + let _temp_209 = 0; + let _temp_210 = 0; + let _temp_211 = 0; + let _temp_212 = 0; + let _temp_213 = 0; + let _temp_214 = 0; + let _temp_215 = 0; + let _temp_216 = 0; + let _temp_217 = 0; + let _temp_218 = 0; + let _temp_219 = 0; + let _temp_220 = 0; + let _temp_221 = 0; + let _temp_222 = 0; + let _temp_223 = 0; + let _temp_224 = 0; + let _temp_225 = 0; + let _temp_226 = 0; + let _temp_227 = 0; + let _temp_228 = 0; + let _temp_229 = 0; + let _temp_230 = 0; + let _temp_231 = 0; + let _temp_232 = 0; + let _temp_233 = 0; + let _temp_234 = 0; + let _temp_235 = 0; + let _temp_236 = 0; + let _temp_237 = 0; + let _temp_238 = 0; + let _temp_239 = 0; + let _temp_240 = 0; + let _temp_241 = 0; + let _temp_242 = 0; + let _temp_243 = 0; + let _temp_244 = 0; + let _temp_245 = 0; + let _temp_246 = 0; + let _temp_247 = 0; + let _temp_248 = 0; + let _temp_249 = 0; + let _temp_250 = 0; + let _temp_251 = 0; + let _temp_252 = 0; + let _temp_253 = 0; + let _temp_254 = 0; + let _temp_255 = 0; + let _temp_256 = 0; + let _temp_257 = 0; + let _temp_258 = 0; + let _temp_259 = 0; + let _temp_260 = 0; + let _temp_261 = 0; + let _temp_262 = 0; + let _temp_263 = 0; + let _temp_264 = 0; + let _temp_265 = 0; + let _temp_266 = 0; + let _temp_267 = 0; + let _temp_268 = 0; + let _temp_269 = 0; + let _temp_270 = 0; + let _temp_271 = 0; + let _temp_272 = 0; + let _temp_273 = 0; + let _temp_274 = 0; + let _temp_275 = 0; + let _temp_276 = 0; + let _temp_277 = 0; + let _temp_278 = 0; + let _temp_279 = 0; + let _temp_280 = 0; + let _temp_281 = 0; + let _temp_282 = 0; + let _temp_283 = 0; + let _temp_284 = 0; + let _temp_285 = 0; + let _temp_286 = 0; + let _temp_287 = 0; + let _temp_288 = 0; + let _temp_289 = 0; + let _temp_290 = 0; + let _temp_291 = 0; + let _temp_292 = 0; + let _temp_293 = 0; + let _temp_294 = 0; + let _temp_295 = 0; + let _temp_296 = 0; + let _temp_297 = 0; + let _temp_298 = 0; + let _temp_299 = 0; + let _temp_300 = 0; + let _temp_301 = 0; + let _temp_302 = 0; + let _temp_303 = 0; + let _temp_304 = 0; + let _temp_305 = 0; + let _temp_306 = 0; + let _temp_307 = 0; + let _temp_308 = 0; + let _temp_309 = 0; + let _temp_310 = 0; + let _temp_311 = 0; + let _temp_312 = 0; + let _temp_313 = 0; + let _temp_314 = 0; + let _temp_315 = 0; + let _temp_316 = 0; + let _temp_317 = 0; + let _temp_318 = 0; + let _temp_319 = 0; + let _temp_320 = 0; + let _temp_321 = 0; + let _temp_322 = 0; + let _temp_323 = 0; + let _temp_324 = 0; + let _temp_325 = 0; + let _temp_326 = 0; + let _temp_327 = 0; + let _temp_328 = 0; + let _temp_329 = 0; + let _temp_330 = 0; + let _temp_331 = 0; + let _temp_332 = 0; + let _temp_333 = 0; + let _temp_334 = 0; + let _temp_335 = 0; + let _temp_336 = 0; + let _temp_337 = 0; + let _temp_338 = 0; + let _temp_339 = 0; + let _temp_340 = 0; + let _temp_341 = 0; + let _temp_342 = 0; + let _temp_343 = 0; + let _temp_344 = 0; + let _temp_345 = 0; + let _temp_346 = 0; + let _temp_347 = 0; + let _temp_348 = 0; + let _temp_349 = 0; + let _temp_350 = 0; + let _temp_351 = 0; + let _temp_352 = 0; + let _temp_353 = 0; + let _temp_354 = 0; + let _temp_355 = 0; + let _temp_356 = 0; + let _temp_357 = 0; + let _temp_358 = 0; + let _temp_359 = 0; + let _temp_360 = 0; + let _temp_361 = 0; + let _temp_362 = 0; + let _temp_363 = 0; + let _temp_364 = 0; + let _temp_365 = 0; + let _temp_366 = 0; + let _temp_367 = 0; + let _temp_368 = 0; + let _temp_369 = 0; + let _temp_370 = 0; + let _temp_371 = 0; + let _temp_372 = 0; + let _temp_373 = 0; + let _temp_374 = 0; + let _temp_375 = 0; + let _temp_376 = 0; + let _temp_377 = 0; + let _temp_378 = 0; + let _temp_379 = 0; + let _temp_380 = 0; + let _temp_381 = 0; + let _temp_382 = 0; + let _temp_383 = 0; + let _temp_384 = 0; + let _temp_385 = 0; + let _temp_386 = 0; + let _temp_387 = 0; + let _temp_388 = 0; + let _temp_389 = 0; + let _temp_390 = 0; + let _temp_391 = 0; + let _temp_392 = 0; + let _temp_393 = 0; + let _temp_394 = 0; + let _temp_395 = 0; + let _temp_396 = 0; + let _temp_397 = 0; + let _temp_398 = 0; + let _temp_399 = 0; + let _temp_400 = 0; + let _temp_401 = 0; + let _temp_402 = 0; + let _temp_403 = 0; + let _temp_404 = 0; + let _temp_405 = 0; + let _temp_406 = 0; + let _temp_407 = 0; + let _temp_408 = 0; + let _temp_409 = 0; + let _temp_410 = 0; + let _temp_411 = 0; + let _temp_412 = 0; + let _temp_413 = 0; + let _temp_414 = 0; + let _temp_415 = 0; + let _temp_416 = 0; + let _temp_417 = 0; + let _temp_418 = 0; + let _temp_419 = 0; + let _temp_420 = 0; + let _temp_421 = 0; + let _temp_422 = 0; + let _temp_423 = 0; + let _temp_424 = 0; + let _temp_425 = 0; + let _temp_426 = 0; + let _temp_427 = 0; + let _temp_428 = 0; + let _temp_429 = 0; + let _temp_430 = 0; + let _temp_431 = 0; + let _temp_432 = 0; + let _temp_433 = 0; + let _temp_434 = 0; + let _temp_435 = 0; + let _temp_436 = 0; + let _temp_437 = 0; + let _temp_438 = 0; + let _temp_439 = 0; + let _temp_440 = 0; + let _temp_441 = 0; + let _temp_442 = 0; + let _temp_443 = 0; + let _temp_444 = 0; + let _temp_445 = 0; + let _temp_446 = 0; + let _temp_447 = 0; + let _temp_448 = 0; + let _temp_449 = 0; + let _temp_450 = 0; + let _temp_451 = 0; + let _temp_452 = 0; + let _temp_453 = 0; + let _temp_454 = 0; + let _temp_455 = 0; + let _temp_456 = 0; + let _temp_457 = 0; + let _temp_458 = 0; + let _temp_459 = 0; + let _temp_460 = 0; + let _temp_461 = 0; + let _temp_462 = 0; + let _temp_463 = 0; + let _temp_464 = 0; + let _temp_465 = 0; + let _temp_466 = 0; + let _temp_467 = 0; + let _temp_468 = 0; + let _temp_469 = 0; + let _temp_470 = 0; + let _temp_471 = 0; + let _temp_472 = 0; + let _temp_473 = 0; + let _temp_474 = 0; + let _temp_475 = 0; + let _temp_476 = 0; + let _temp_477 = 0; + let _temp_478 = 0; + let _temp_479 = 0; + let _temp_480 = 0; + let _temp_481 = 0; + let _temp_482 = 0; + let _temp_483 = 0; + let _temp_484 = 0; + let _temp_485 = 0; + let _temp_486 = 0; + let _temp_487 = 0; + let _temp_488 = 0; + let _temp_489 = 0; + let _temp_490 = 0; + let _temp_491 = 0; + let _temp_492 = 0; + let _temp_493 = 0; + let _temp_494 = 0; + let _temp_495 = 0; + let _temp_496 = 0; + let _temp_497 = 0; + let _temp_498 = 0; + let _temp_499 = 0; + let _temp_500 = 0; + let _temp_501 = 0; + let _temp_502 = 0; + let _temp_503 = 0; + let _temp_504 = 0; + let _temp_505 = 0; + let _temp_506 = 0; + let _temp_507 = 0; + let _temp_508 = 0; + let _temp_509 = 0; + let _temp_510 = 0; + let _temp_511 = 0; + let _temp_512 = 0; + let _temp_513 = 0; + let _temp_514 = 0; + let _temp_515 = 0; + let _temp_516 = 0; + let _temp_517 = 0; + let _temp_518 = 0; + let _temp_519 = 0; + let _temp_520 = 0; + let _temp_521 = 0; + let _temp_522 = 0; + let _temp_523 = 0; + let _temp_524 = 0; + let _temp_525 = 0; + let _temp_526 = 0; + let _temp_527 = 0; + let _temp_528 = 0; + let _temp_529 = 0; + let _temp_530 = 0; + let _temp_531 = 0; + let _temp_532 = 0; + let _temp_533 = 0; + let _temp_534 = 0; + let _temp_535 = 0; + let _temp_536 = 0; + let _temp_537 = 0; + let _temp_538 = 0; + let _temp_539 = 0; + let _temp_540 = 0; + let _temp_541 = 0; + let _temp_542 = 0; + let _temp_543 = 0; + let _temp_544 = 0; + let _temp_545 = 0; + let _temp_546 = 0; + let _temp_547 = 0; + let _temp_548 = 0; + let _temp_549 = 0; + let _temp_550 = 0; + let _temp_551 = 0; + let _temp_552 = 0; + let _temp_553 = 0; + let _temp_554 = 0; + let _temp_555 = 0; + let _temp_556 = 0; + let _temp_557 = 0; + let _temp_558 = 0; + let _temp_559 = 0; + let _temp_560 = 0; + let _temp_561 = 0; + let _temp_562 = 0; + let _temp_563 = 0; + let _temp_564 = 0; + let _temp_565 = 0; + let _temp_566 = 0; + let _temp_567 = 0; + let _temp_568 = 0; + let _temp_569 = 0; + let _temp_570 = 0; + let _temp_571 = 0; + let _temp_572 = 0; + let _temp_573 = 0; + let _temp_574 = 0; + let _temp_575 = 0; + let _temp_576 = 0; + let _temp_577 = 0; + let _temp_578 = 0; + let _temp_579 = 0; + let _temp_580 = 0; + let _temp_581 = 0; + let _temp_582 = 0; + let _temp_583 = 0; + let _temp_584 = 0; + let _temp_585 = 0; + let _temp_586 = 0; + let _temp_587 = 0; + let _temp_588 = 0; + let _temp_589 = 0; + let _temp_590 = 0; + let _temp_591 = 0; + let _temp_592 = 0; + let _temp_593 = 0; + let _temp_594 = 0; + let _temp_595 = 0; + let _temp_596 = 0; + let _temp_597 = 0; + let _temp_598 = 0; + let _temp_599 = 0; + let _temp_600 = 0; + let _temp_601 = 0; + let _temp_602 = 0; + let _temp_603 = 0; + let _temp_604 = 0; + let _temp_605 = 0; + let _temp_606 = 0; + let _temp_607 = 0; + let _temp_608 = 0; + let _temp_609 = 0; + let _temp_610 = 0; + let _temp_611 = 0; + let _temp_612 = 0; + let _temp_613 = 0; + let _temp_614 = 0; + let _temp_615 = 0; + let _temp_616 = 0; + let _temp_617 = 0; + let _temp_618 = 0; + let _temp_619 = 0; + let _temp_620 = 0; + let _temp_621 = 0; + let _temp_622 = 0; + let _temp_623 = 0; + let _temp_624 = 0; + let _temp_625 = 0; + let _temp_626 = 0; + let _temp_627 = 0; + let _temp_628 = 0; + let _temp_629 = 0; + let _temp_630 = 0; + let _temp_631 = 0; + let _temp_632 = 0; + let _temp_633 = 0; + let _temp_634 = 0; + let _temp_635 = 0; + let _temp_636 = 0; + let _temp_637 = 0; + let _temp_638 = 0; + let _temp_639 = 0; + let _temp_640 = 0; + let _temp_641 = 0; + let _temp_642 = 0; + let _temp_643 = 0; + let _temp_644 = 0; + let _temp_645 = 0; + let _temp_646 = 0; + let _temp_647 = 0; + let _temp_648 = 0; + let _temp_649 = 0; + let _temp_650 = 0; + let _temp_651 = 0; + let _temp_652 = 0; + let _temp_653 = 0; + let _temp_654 = 0; + let _temp_655 = 0; + let _temp_656 = 0; + let _temp_657 = 0; + let _temp_658 = 0; + let _temp_659 = 0; + let _temp_660 = 0; + let _temp_661 = 0; + let _temp_662 = 0; + let _temp_663 = 0; + let _temp_664 = 0; + let _temp_665 = 0; + let _temp_666 = 0; + let _temp_667 = 0; + let _temp_668 = 0; + let _temp_669 = 0; + let _temp_670 = 0; + let _temp_671 = 0; + let _temp_672 = 0; + let _temp_673 = 0; + let _temp_674 = 0; + let _temp_675 = 0; + let _temp_676 = 0; + let _temp_677 = 0; + let _temp_678 = 0; + let _temp_679 = 0; + let _temp_680 = 0; + let _temp_681 = 0; + let _temp_682 = 0; + let _temp_683 = 0; + let _temp_684 = 0; + let _temp_685 = 0; + let _temp_686 = 0; + let _temp_687 = 0; + let _temp_688 = 0; + let _temp_689 = 0; + let _temp_690 = 0; + let _temp_691 = 0; + let _temp_692 = 0; + let _temp_693 = 0; + let _temp_694 = 0; + let _temp_695 = 0; + let _temp_696 = 0; + let _temp_697 = 0; + let _temp_698 = 0; + let _temp_699 = 0; + let _temp_700 = 0; + let _temp_701 = 0; + let _temp_702 = 0; + let _temp_703 = 0; + let _temp_704 = 0; + let _temp_705 = 0; + let _temp_706 = 0; + let _temp_707 = 0; + let _temp_708 = 0; + let _temp_709 = 0; + let _temp_710 = 0; + let _temp_711 = 0; + let _temp_712 = 0; + let _temp_713 = 0; + let _temp_714 = 0; + let _temp_715 = 0; + let _temp_716 = 0; + let _temp_717 = 0; + let _temp_718 = 0; + let _temp_719 = 0; + let _temp_720 = 0; + let _temp_721 = 0; + let _temp_722 = 0; + let _temp_723 = 0; + let _temp_724 = 0; + let _temp_725 = 0; + let _temp_726 = 0; + let _temp_727 = 0; + let _temp_728 = 0; + let _temp_729 = 0; + let _temp_730 = 0; + let _temp_731 = 0; + let _temp_732 = 0; + let _temp_733 = 0; + let _temp_734 = 0; + let _temp_735 = 0; + let _temp_736 = 0; + let _temp_737 = 0; + let _temp_738 = 0; + let _temp_739 = 0; + let _temp_740 = 0; + let _temp_741 = 0; + let _temp_742 = 0; + let _temp_743 = 0; + let _temp_744 = 0; + let _temp_745 = 0; + let _temp_746 = 0; + let _temp_747 = 0; + let _temp_748 = 0; + let _temp_749 = 0; + let _temp_750 = 0; + let _temp_751 = 0; + let _temp_752 = 0; + let _temp_753 = 0; + let _temp_754 = 0; + let _temp_755 = 0; + let _temp_756 = 0; + let _temp_757 = 0; + let _temp_758 = 0; + let _temp_759 = 0; + let _temp_760 = 0; + let _temp_761 = 0; + let _temp_762 = 0; + let _temp_763 = 0; + let _temp_764 = 0; + let _temp_765 = 0; + let _temp_766 = 0; + let _temp_767 = 0; + let _temp_768 = 0; + let _temp_769 = 0; + let _temp_770 = 0; + let _temp_771 = 0; + let _temp_772 = 0; + let _temp_773 = 0; + let _temp_774 = 0; + let _temp_775 = 0; + let _temp_776 = 0; + let _temp_777 = 0; + let _temp_778 = 0; + let _temp_779 = 0; + let _temp_780 = 0; + let _temp_781 = 0; + let _temp_782 = 0; + let _temp_783 = 0; + let _temp_784 = 0; + let _temp_785 = 0; + let _temp_786 = 0; + let _temp_787 = 0; + let _temp_788 = 0; + let _temp_789 = 0; + let _temp_790 = 0; + let _temp_791 = 0; + let _temp_792 = 0; + let _temp_793 = 0; + let _temp_794 = 0; + let _temp_795 = 0; + let _temp_796 = 0; + let _temp_797 = 0; + let _temp_798 = 0; + let _temp_799 = 0; + let _temp_800 = 0; + let _temp_801 = 0; + let _temp_802 = 0; + let _temp_803 = 0; + let _temp_804 = 0; + let _temp_805 = 0; + let _temp_806 = 0; + let _temp_807 = 0; + let _temp_808 = 0; + let _temp_809 = 0; + let _temp_810 = 0; + let _temp_811 = 0; + let _temp_812 = 0; + let _temp_813 = 0; + let _temp_814 = 0; + let _temp_815 = 0; + let _temp_816 = 0; + let _temp_817 = 0; + let _temp_818 = 0; + let _temp_819 = 0; + let _temp_820 = 0; + let _temp_821 = 0; + let _temp_822 = 0; + let _temp_823 = 0; + let _temp_824 = 0; + let _temp_825 = 0; + let _temp_826 = 0; + let _temp_827 = 0; + let _temp_828 = 0; + let _temp_829 = 0; + let _temp_830 = 0; + let _temp_831 = 0; + let _temp_832 = 0; + let _temp_833 = 0; + let _temp_834 = 0; + let _temp_835 = 0; + let _temp_836 = 0; + let _temp_837 = 0; + let _temp_838 = 0; + let _temp_839 = 0; + let _temp_840 = 0; + let _temp_841 = 0; + let _temp_842 = 0; + let _temp_843 = 0; + let _temp_844 = 0; + let _temp_845 = 0; + let _temp_846 = 0; + let _temp_847 = 0; + let _temp_848 = 0; + let _temp_849 = 0; + let _temp_850 = 0; + let _temp_851 = 0; + let _temp_852 = 0; + let _temp_853 = 0; + let _temp_854 = 0; + let _temp_855 = 0; + let _temp_856 = 0; + let _temp_857 = 0; + let _temp_858 = 0; + let _temp_859 = 0; + let _temp_860 = 0; + let _temp_861 = 0; + let _temp_862 = 0; + let _temp_863 = 0; + let _temp_864 = 0; + let _temp_865 = 0; + let _temp_866 = 0; + let _temp_867 = 0; + let _temp_868 = 0; + let _temp_869 = 0; + let _temp_870 = 0; + let _temp_871 = 0; + let _temp_872 = 0; + let _temp_873 = 0; + let _temp_874 = 0; + let _temp_875 = 0; + let _temp_876 = 0; + let _temp_877 = 0; + let _temp_878 = 0; + let _temp_879 = 0; + let _temp_880 = 0; + let _temp_881 = 0; + let _temp_882 = 0; + let _temp_883 = 0; + let _temp_884 = 0; + let _temp_885 = 0; + let _temp_886 = 0; + let _temp_887 = 0; + let _temp_888 = 0; + let _temp_889 = 0; + let _temp_890 = 0; + let _temp_891 = 0; + let _temp_892 = 0; + let _temp_893 = 0; + let _temp_894 = 0; + let _temp_895 = 0; + let _temp_896 = 0; + let _temp_897 = 0; + let _temp_898 = 0; + let _temp_899 = 0; + let _temp_900 = 0; + let _temp_901 = 0; + let _temp_902 = 0; + let _temp_903 = 0; + let _temp_904 = 0; + let _temp_905 = 0; + let _temp_906 = 0; + let _temp_907 = 0; + let _temp_908 = 0; + let _temp_909 = 0; + let _temp_910 = 0; + let _temp_911 = 0; + let _temp_912 = 0; + let _temp_913 = 0; + let _temp_914 = 0; + let _temp_915 = 0; + let _temp_916 = 0; + let _temp_917 = 0; + let _temp_918 = 0; + let _temp_919 = 0; + let _temp_920 = 0; + let _temp_921 = 0; + let _temp_922 = 0; + let _temp_923 = 0; + let _temp_924 = 0; + let _temp_925 = 0; + let _temp_926 = 0; + let _temp_927 = 0; + let _temp_928 = 0; + let _temp_929 = 0; + let _temp_930 = 0; + let _temp_931 = 0; + let _temp_932 = 0; + let _temp_933 = 0; + let _temp_934 = 0; + let _temp_935 = 0; + let _temp_936 = 0; + let _temp_937 = 0; + let _temp_938 = 0; + let _temp_939 = 0; + let _temp_940 = 0; + let _temp_941 = 0; + let _temp_942 = 0; + let _temp_943 = 0; + let _temp_944 = 0; + let _temp_945 = 0; + let _temp_946 = 0; + let _temp_947 = 0; + let _temp_948 = 0; + let _temp_949 = 0; + let _temp_950 = 0; + let _temp_951 = 0; + let _temp_952 = 0; + let _temp_953 = 0; + let _temp_954 = 0; + let _temp_955 = 0; + let _temp_956 = 0; + let _temp_957 = 0; + let _temp_958 = 0; + let _temp_959 = 0; + let _temp_960 = 0; + let _temp_961 = 0; + let _temp_962 = 0; + let _temp_963 = 0; + let _temp_964 = 0; + let _temp_965 = 0; + let _temp_966 = 0; + let _temp_967 = 0; + let _temp_968 = 0; + let _temp_969 = 0; + let _temp_970 = 0; + let _temp_971 = 0; + let _temp_972 = 0; + let _temp_973 = 0; + let _temp_974 = 0; + let _temp_975 = 0; + let _temp_976 = 0; + let _temp_977 = 0; + let _temp_978 = 0; + let _temp_979 = 0; + let _temp_980 = 0; + let _temp_981 = 0; + let _temp_982 = 0; + let _temp_983 = 0; + let _temp_984 = 0; + let _temp_985 = 0; + let _temp_986 = 0; + let _temp_987 = 0; + let _temp_988 = 0; + let _temp_989 = 0; + let _temp_990 = 0; + let _temp_991 = 0; + let _temp_992 = 0; + let _temp_993 = 0; + let _temp_994 = 0; + let _temp_995 = 0; + let _temp_996 = 0; + let _temp_997 = 0; + let _temp_998 = 0; + let _temp_999 = 0; + let _temp_1000 = 0; + let _temp_1001 = 0; + let _temp_1002 = 0; + let _temp_1003 = 0; + let _temp_1004 = 0; + let _temp_1005 = 0; + let _temp_1006 = 0; + let _temp_1007 = 0; + let _temp_1008 = 0; + let _temp_1009 = 0; + let _temp_1010 = 0; + let _temp_1011 = 0; + let _temp_1012 = 0; + let _temp_1013 = 0; + let _temp_1014 = 0; + let _temp_1015 = 0; + let _temp_1016 = 0; + let _temp_1017 = 0; + let _temp_1018 = 0; + let _temp_1019 = 0; + let _temp_1020 = 0; + let _temp_1021 = 0; + let _temp_1022 = 0; + let _temp_1023 = 0; + let _temp_1024 = 0; + let _temp_1025 = 0; + let _temp_1026 = 0; + let _temp_1027 = 0; + let _temp_1028 = 0; + let _temp_1029 = 0; + let _temp_1030 = 0; + let _temp_1031 = 0; + let _temp_1032 = 0; + let _temp_1033 = 0; + let _temp_1034 = 0; + let _temp_1035 = 0; + let _temp_1036 = 0; + let _temp_1037 = 0; + let _temp_1038 = 0; + let _temp_1039 = 0; + let _temp_1040 = 0; + let _temp_1041 = 0; + let _temp_1042 = 0; + let _temp_1043 = 0; + let _temp_1044 = 0; + let _temp_1045 = 0; + let _temp_1046 = 0; + let _temp_1047 = 0; + let _temp_1048 = 0; + let _temp_1049 = 0; + let _temp_1050 = 0; + let _temp_1051 = 0; + let _temp_1052 = 0; + let _temp_1053 = 0; + let _temp_1054 = 0; + let _temp_1055 = 0; + let _temp_1056 = 0; + let _temp_1057 = 0; + let _temp_1058 = 0; + let _temp_1059 = 0; + let _temp_1060 = 0; + let _temp_1061 = 0; + let _temp_1062 = 0; + let _temp_1063 = 0; + let _temp_1064 = 0; + let _temp_1065 = 0; + let _temp_1066 = 0; + let _temp_1067 = 0; + let _temp_1068 = 0; + let _temp_1069 = 0; + let _temp_1070 = 0; + let _temp_1071 = 0; + let _temp_1072 = 0; + let _temp_1073 = 0; + let _temp_1074 = 0; + let _temp_1075 = 0; + let _temp_1076 = 0; + let _temp_1077 = 0; + let _temp_1078 = 0; + let _temp_1079 = 0; + let _temp_1080 = 0; + let _temp_1081 = 0; + let _temp_1082 = 0; + let _temp_1083 = 0; + let _temp_1084 = 0; + let _temp_1085 = 0; + let _temp_1086 = 0; + let _temp_1087 = 0; + let _temp_1088 = 0; + let _temp_1089 = 0; + let _temp_1090 = 0; + let _temp_1091 = 0; + let _temp_1092 = 0; + let _temp_1093 = 0; + let _temp_1094 = 0; + let _temp_1095 = 0; + let _temp_1096 = 0; + let _temp_1097 = 0; + let _temp_1098 = 0; + let _temp_1099 = 0; + let _temp_1100 = 0; + let _temp_1101 = 0; + let _temp_1102 = 0; + let _temp_1103 = 0; + let _temp_1104 = 0; + let _temp_1105 = 0; + let _temp_1106 = 0; + let _temp_1107 = 0; + let _temp_1108 = 0; + let _temp_1109 = 0; + let _temp_1110 = 0; + let _temp_1111 = 0; + let _temp_1112 = 0; + let _temp_1113 = 0; + let _temp_1114 = 0; + let _temp_1115 = 0; + let _temp_1116 = 0; + let _temp_1117 = 0; + let _temp_1118 = 0; + let _temp_1119 = 0; + let _temp_1120 = 0; + let _temp_1121 = 0; + let _temp_1122 = 0; + let _temp_1123 = 0; + let _temp_1124 = 0; + let _temp_1125 = 0; + let _temp_1126 = 0; + let _temp_1127 = 0; + let _temp_1128 = 0; + let _temp_1129 = 0; + let _temp_1130 = 0; + let _temp_1131 = 0; + let _temp_1132 = 0; + let _temp_1133 = 0; + let _temp_1134 = 0; + let _temp_1135 = 0; + let _temp_1136 = 0; + let _temp_1137 = 0; + let _temp_1138 = 0; + let _temp_1139 = 0; + let _temp_1140 = 0; + let _temp_1141 = 0; + let _temp_1142 = 0; + let _temp_1143 = 0; + let _temp_1144 = 0; + let _temp_1145 = 0; + let _temp_1146 = 0; + let _temp_1147 = 0; + let _temp_1148 = 0; + let _temp_1149 = 0; + let _temp_1150 = 0; + let _temp_1151 = 0; + let _temp_1152 = 0; + let _temp_1153 = 0; + let _temp_1154 = 0; + let _temp_1155 = 0; + let _temp_1156 = 0; + let _temp_1157 = 0; + let _temp_1158 = 0; + let _temp_1159 = 0; + let _temp_1160 = 0; + let _temp_1161 = 0; + let _temp_1162 = 0; + let _temp_1163 = 0; + let _temp_1164 = 0; + let _temp_1165 = 0; + let _temp_1166 = 0; + let _temp_1167 = 0; + let _temp_1168 = 0; + let _temp_1169 = 0; + let _temp_1170 = 0; + let _temp_1171 = 0; + let _temp_1172 = 0; + let _temp_1173 = 0; + let _temp_1174 = 0; + let _temp_1175 = 0; + let _temp_1176 = 0; + let _temp_1177 = 0; + let _temp_1178 = 0; + let _temp_1179 = 0; + let _temp_1180 = 0; + let _temp_1181 = 0; + let _temp_1182 = 0; + let _temp_1183 = 0; + let _temp_1184 = 0; + let _temp_1185 = 0; + let _temp_1186 = 0; + let _temp_1187 = 0; + let _temp_1188 = 0; + let _temp_1189 = 0; + let _temp_1190 = 0; + let _temp_1191 = 0; + let _temp_1192 = 0; + let _temp_1193 = 0; + let _temp_1194 = 0; + let _temp_1195 = 0; + let _temp_1196 = 0; + let _temp_1197 = 0; + let _temp_1198 = 0; + let _temp_1199 = 0; + let _temp_1200 = 0; + let _temp_1201 = 0; + let _temp_1202 = 0; + let _temp_1203 = 0; + let _temp_1204 = 0; + let _temp_1205 = 0; + let _temp_1206 = 0; + let _temp_1207 = 0; + let _temp_1208 = 0; + let _temp_1209 = 0; + let _temp_1210 = 0; + let _temp_1211 = 0; + let _temp_1212 = 0; + let _temp_1213 = 0; + let _temp_1214 = 0; + let _temp_1215 = 0; + let _temp_1216 = 0; + let _temp_1217 = 0; + let _temp_1218 = 0; + let _temp_1219 = 0; + let _temp_1220 = 0; + let _temp_1221 = 0; + let _temp_1222 = 0; + let _temp_1223 = 0; + let _temp_1224 = 0; + let _temp_1225 = 0; + let _temp_1226 = 0; + let _temp_1227 = 0; + let _temp_1228 = 0; + let _temp_1229 = 0; + let _temp_1230 = 0; + let _temp_1231 = 0; + let _temp_1232 = 0; + let _temp_1233 = 0; + let _temp_1234 = 0; + let _temp_1235 = 0; + let _temp_1236 = 0; + let _temp_1237 = 0; + let _temp_1238 = 0; + let _temp_1239 = 0; + let _temp_1240 = 0; + let _temp_1241 = 0; + let _temp_1242 = 0; + let _temp_1243 = 0; + let _temp_1244 = 0; + let _temp_1245 = 0; + let _temp_1246 = 0; + let _temp_1247 = 0; + let _temp_1248 = 0; + let _temp_1249 = 0; + let _temp_1250 = 0; + let _temp_1251 = 0; + let _temp_1252 = 0; + let _temp_1253 = 0; + let _temp_1254 = 0; + let _temp_1255 = 0; + let _temp_1256 = 0; + let _temp_1257 = 0; + let _temp_1258 = 0; + let _temp_1259 = 0; + let _temp_1260 = 0; + let _temp_1261 = 0; + let _temp_1262 = 0; + let _temp_1263 = 0; + let _temp_1264 = 0; + let _temp_1265 = 0; + let _temp_1266 = 0; + let _temp_1267 = 0; + let _temp_1268 = 0; + let _temp_1269 = 0; + let _temp_1270 = 0; + let _temp_1271 = 0; + let _temp_1272 = 0; + let _temp_1273 = 0; + let _temp_1274 = 0; + let _temp_1275 = 0; + let _temp_1276 = 0; + let _temp_1277 = 0; + let _temp_1278 = 0; + let _temp_1279 = 0; + let _temp_1280 = 0; + let _temp_1281 = 0; + let _temp_1282 = 0; + let _temp_1283 = 0; + let _temp_1284 = 0; + let _temp_1285 = 0; + let _temp_1286 = 0; + let _temp_1287 = 0; + let _temp_1288 = 0; + let _temp_1289 = 0; + let _temp_1290 = 0; + let _temp_1291 = 0; + let _temp_1292 = 0; + let _temp_1293 = 0; + let _temp_1294 = 0; + let _temp_1295 = 0; + let _temp_1296 = 0; + let _temp_1297 = 0; + let _temp_1298 = 0; + let _temp_1299 = 0; + let _temp_1300 = 0; + let _temp_1301 = 0; + let _temp_1302 = 0; + let _temp_1303 = 0; + let _temp_1304 = 0; + let _temp_1305 = 0; + let _temp_1306 = 0; + let _temp_1307 = 0; + let _temp_1308 = 0; + let _temp_1309 = 0; + let _temp_1310 = 0; + let _temp_1311 = 0; + let _temp_1312 = 0; + let _temp_1313 = 0; + let _temp_1314 = 0; + let _temp_1315 = 0; + let _temp_1316 = 0; + let _temp_1317 = 0; + let _temp_1318 = 0; + let _temp_1319 = 0; + let _temp_1320 = 0; + let _temp_1321 = 0; + let _temp_1322 = 0; + let _temp_1323 = 0; + let _temp_1324 = 0; + let _temp_1325 = 0; + let _temp_1326 = 0; + let _temp_1327 = 0; + let _temp_1328 = 0; + let _temp_1329 = 0; + let _temp_1330 = 0; + let _temp_1331 = 0; + let _temp_1332 = 0; + let _temp_1333 = 0; + let _temp_1334 = 0; + let _temp_1335 = 0; + let _temp_1336 = 0; + let _temp_1337 = 0; + let _temp_1338 = 0; + let _temp_1339 = 0; + let _temp_1340 = 0; + let _temp_1341 = 0; + let _temp_1342 = 0; + let _temp_1343 = 0; + let _temp_1344 = 0; + let _temp_1345 = 0; + let _temp_1346 = 0; + let _temp_1347 = 0; + let _temp_1348 = 0; + let _temp_1349 = 0; + let _temp_1350 = 0; + let _temp_1351 = 0; + let _temp_1352 = 0; + let _temp_1353 = 0; + let _temp_1354 = 0; + let _temp_1355 = 0; + let _temp_1356 = 0; + let _temp_1357 = 0; + let _temp_1358 = 0; + let _temp_1359 = 0; + let _temp_1360 = 0; + let _temp_1361 = 0; + let _temp_1362 = 0; + let _temp_1363 = 0; + let _temp_1364 = 0; + let _temp_1365 = 0; + let _temp_1366 = 0; + let _temp_1367 = 0; + let _temp_1368 = 0; + let _temp_1369 = 0; + let _temp_1370 = 0; + let _temp_1371 = 0; + let _temp_1372 = 0; + let _temp_1373 = 0; + let _temp_1374 = 0; + let _temp_1375 = 0; + let _temp_1376 = 0; + let _temp_1377 = 0; + let _temp_1378 = 0; + let _temp_1379 = 0; + let _temp_1380 = 0; + let _temp_1381 = 0; + let _temp_1382 = 0; + let _temp_1383 = 0; + let _temp_1384 = 0; + let _temp_1385 = 0; + let _temp_1386 = 0; + let _temp_1387 = 0; + let _temp_1388 = 0; + let _temp_1389 = 0; + let _temp_1390 = 0; + let _temp_1391 = 0; + let _temp_1392 = 0; + let _temp_1393 = 0; + let _temp_1394 = 0; + let _temp_1395 = 0; + let _temp_1396 = 0; + let _temp_1397 = 0; + let _temp_1398 = 0; + let _temp_1399 = 0; + let _temp_1400 = 0; + let _temp_1401 = 0; + let _temp_1402 = 0; + let _temp_1403 = 0; + let _temp_1404 = 0; + let _temp_1405 = 0; + let _temp_1406 = 0; + let _temp_1407 = 0; + let _temp_1408 = 0; + let _temp_1409 = 0; + let _temp_1410 = 0; + let _temp_1411 = 0; + let _temp_1412 = 0; + let _temp_1413 = 0; + let _temp_1414 = 0; + let _temp_1415 = 0; + let _temp_1416 = 0; + let _temp_1417 = 0; + let _temp_1418 = 0; + let _temp_1419 = 0; + let _temp_1420 = 0; + let _temp_1421 = 0; + let _temp_1422 = 0; + let _temp_1423 = 0; + let _temp_1424 = 0; + let _temp_1425 = 0; + let _temp_1426 = 0; + let _temp_1427 = 0; + let _temp_1428 = 0; + let _temp_1429 = 0; + let _temp_1430 = 0; + let _temp_1431 = 0; + let _temp_1432 = 0; + let _temp_1433 = 0; + let _temp_1434 = 0; + let _temp_1435 = 0; + let _temp_1436 = 0; + let _temp_1437 = 0; + let _temp_1438 = 0; + let _temp_1439 = 0; + let _temp_1440 = 0; + let _temp_1441 = 0; + let _temp_1442 = 0; + let _temp_1443 = 0; + let _temp_1444 = 0; + let _temp_1445 = 0; + let _temp_1446 = 0; + let _temp_1447 = 0; + let _temp_1448 = 0; + let _temp_1449 = 0; + let _temp_1450 = 0; + let _temp_1451 = 0; + let _temp_1452 = 0; + let _temp_1453 = 0; + let _temp_1454 = 0; + let _temp_1455 = 0; + let _temp_1456 = 0; + let _temp_1457 = 0; + let _temp_1458 = 0; + let _temp_1459 = 0; + let _temp_1460 = 0; + let _temp_1461 = 0; + let _temp_1462 = 0; + let _temp_1463 = 0; + let _temp_1464 = 0; + let _temp_1465 = 0; + let _temp_1466 = 0; + let _temp_1467 = 0; + let _temp_1468 = 0; + let _temp_1469 = 0; + let _temp_1470 = 0; + let _temp_1471 = 0; + let _temp_1472 = 0; + let _temp_1473 = 0; + let _temp_1474 = 0; + let _temp_1475 = 0; + let _temp_1476 = 0; + let _temp_1477 = 0; + let _temp_1478 = 0; + let _temp_1479 = 0; + let _temp_1480 = 0; + let _temp_1481 = 0; + let _temp_1482 = 0; + let _temp_1483 = 0; + let _temp_1484 = 0; + let _temp_1485 = 0; + let _temp_1486 = 0; + let _temp_1487 = 0; + let _temp_1488 = 0; + let _temp_1489 = 0; + let _temp_1490 = 0; + let _temp_1491 = 0; + let _temp_1492 = 0; + let _temp_1493 = 0; + let _temp_1494 = 0; + let _temp_1495 = 0; + let _temp_1496 = 0; + let _temp_1497 = 0; + let _temp_1498 = 0; + let _temp_1499 = 0; + let _temp_1500 = 0; + let _temp_1501 = 0; + let _temp_1502 = 0; + let _temp_1503 = 0; + let _temp_1504 = 0; + let _temp_1505 = 0; + let _temp_1506 = 0; + let _temp_1507 = 0; + let _temp_1508 = 0; + let _temp_1509 = 0; + let _temp_1510 = 0; + let _temp_1511 = 0; + let _temp_1512 = 0; + let _temp_1513 = 0; + let _temp_1514 = 0; + let _temp_1515 = 0; + let _temp_1516 = 0; + let _temp_1517 = 0; + let _temp_1518 = 0; + let _temp_1519 = 0; + let _temp_1520 = 0; + let _temp_1521 = 0; + let _temp_1522 = 0; + let _temp_1523 = 0; + let _temp_1524 = 0; + let _temp_1525 = 0; + let _temp_1526 = 0; + let _temp_1527 = 0; + let _temp_1528 = 0; + let _temp_1529 = 0; + let _temp_1530 = 0; + let _temp_1531 = 0; + let _temp_1532 = 0; + let _temp_1533 = 0; + let _temp_1534 = 0; + let _temp_1535 = 0; + let _temp_1536 = 0; + let _temp_1537 = 0; + let _temp_1538 = 0; + let _temp_1539 = 0; + let _temp_1540 = 0; + let _temp_1541 = 0; + let _temp_1542 = 0; + let _temp_1543 = 0; + let _temp_1544 = 0; + let _temp_1545 = 0; + let _temp_1546 = 0; + let _temp_1547 = 0; + let _temp_1548 = 0; + let _temp_1549 = 0; + let _temp_1550 = 0; + let _temp_1551 = 0; + let _temp_1552 = 0; + let _temp_1553 = 0; + let _temp_1554 = 0; + let _temp_1555 = 0; + let _temp_1556 = 0; + let _temp_1557 = 0; + let _temp_1558 = 0; + let _temp_1559 = 0; + let _temp_1560 = 0; + let _temp_1561 = 0; + let _temp_1562 = 0; + let _temp_1563 = 0; + let _temp_1564 = 0; + let _temp_1565 = 0; + let _temp_1566 = 0; + let _temp_1567 = 0; + let _temp_1568 = 0; + let _temp_1569 = 0; + let _temp_1570 = 0; + let _temp_1571 = 0; + let _temp_1572 = 0; + let _temp_1573 = 0; + let _temp_1574 = 0; + let _temp_1575 = 0; + let _temp_1576 = 0; + let _temp_1577 = 0; + let _temp_1578 = 0; + let _temp_1579 = 0; + let _temp_1580 = 0; + let _temp_1581 = 0; + let _temp_1582 = 0; + let _temp_1583 = 0; + let _temp_1584 = 0; + let _temp_1585 = 0; + let _temp_1586 = 0; + let _temp_1587 = 0; + let _temp_1588 = 0; + let _temp_1589 = 0; + let _temp_1590 = 0; + let _temp_1591 = 0; + let _temp_1592 = 0; + let _temp_1593 = 0; + let _temp_1594 = 0; + let _temp_1595 = 0; + let _temp_1596 = 0; + let _temp_1597 = 0; + let _temp_1598 = 0; + let _temp_1599 = 0; + let _temp_1600 = 0; + let _temp_1601 = 0; + let _temp_1602 = 0; + let _temp_1603 = 0; + let _temp_1604 = 0; + let _temp_1605 = 0; + let _temp_1606 = 0; + let _temp_1607 = 0; + let _temp_1608 = 0; + let _temp_1609 = 0; + let _temp_1610 = 0; + let _temp_1611 = 0; + let _temp_1612 = 0; + let _temp_1613 = 0; + let _temp_1614 = 0; + let _temp_1615 = 0; + let _temp_1616 = 0; + let _temp_1617 = 0; + let _temp_1618 = 0; + let _temp_1619 = 0; + let _temp_1620 = 0; + let _temp_1621 = 0; + let _temp_1622 = 0; + let _temp_1623 = 0; + let _temp_1624 = 0; + let _temp_1625 = 0; + let _temp_1626 = 0; + let _temp_1627 = 0; + let _temp_1628 = 0; + let _temp_1629 = 0; + let _temp_1630 = 0; + let _temp_1631 = 0; + let _temp_1632 = 0; + let _temp_1633 = 0; + let _temp_1634 = 0; + let _temp_1635 = 0; + let _temp_1636 = 0; + let _temp_1637 = 0; + let _temp_1638 = 0; + let _temp_1639 = 0; + let _temp_1640 = 0; + let _temp_1641 = 0; + let _temp_1642 = 0; + let _temp_1643 = 0; + let _temp_1644 = 0; + let _temp_1645 = 0; + let _temp_1646 = 0; + let _temp_1647 = 0; + let _temp_1648 = 0; + let _temp_1649 = 0; + let _temp_1650 = 0; + let _temp_1651 = 0; + let _temp_1652 = 0; + let _temp_1653 = 0; + let _temp_1654 = 0; + let _temp_1655 = 0; + let _temp_1656 = 0; + let _temp_1657 = 0; + let _temp_1658 = 0; + let _temp_1659 = 0; + let _temp_1660 = 0; + let _temp_1661 = 0; + let _temp_1662 = 0; + let _temp_1663 = 0; + let _temp_1664 = 0; + let _temp_1665 = 0; + let _temp_1666 = 0; + let _temp_1667 = 0; + let _temp_1668 = 0; + let _temp_1669 = 0; + let _temp_1670 = 0; + let _temp_1671 = 0; + let _temp_1672 = 0; + let _temp_1673 = 0; + let _temp_1674 = 0; + let _temp_1675 = 0; + let _temp_1676 = 0; + let _temp_1677 = 0; + let _temp_1678 = 0; + let _temp_1679 = 0; + let _temp_1680 = 0; + let _temp_1681 = 0; + let _temp_1682 = 0; + let _temp_1683 = 0; + let _temp_1684 = 0; + let _temp_1685 = 0; + let _temp_1686 = 0; + let _temp_1687 = 0; + let _temp_1688 = 0; + let _temp_1689 = 0; + let _temp_1690 = 0; + let _temp_1691 = 0; + let _temp_1692 = 0; + let _temp_1693 = 0; + let _temp_1694 = 0; + let _temp_1695 = 0; + let _temp_1696 = 0; + let _temp_1697 = 0; + let _temp_1698 = 0; + let _temp_1699 = 0; + let _temp_1700 = 0; + let _temp_1701 = 0; + let _temp_1702 = 0; + let _temp_1703 = 0; + let _temp_1704 = 0; + let _temp_1705 = 0; + let _temp_1706 = 0; + let _temp_1707 = 0; + let _temp_1708 = 0; + let _temp_1709 = 0; + let _temp_1710 = 0; + let _temp_1711 = 0; + let _temp_1712 = 0; + let _temp_1713 = 0; + let _temp_1714 = 0; + let _temp_1715 = 0; + let _temp_1716 = 0; + let _temp_1717 = 0; + let _temp_1718 = 0; + let _temp_1719 = 0; + let _temp_1720 = 0; + let _temp_1721 = 0; + let _temp_1722 = 0; + let _temp_1723 = 0; + let _temp_1724 = 0; + let _temp_1725 = 0; + let _temp_1726 = 0; + let _temp_1727 = 0; + let _temp_1728 = 0; + let _temp_1729 = 0; + let _temp_1730 = 0; + let _temp_1731 = 0; + let _temp_1732 = 0; + let _temp_1733 = 0; + let _temp_1734 = 0; + let _temp_1735 = 0; + let _temp_1736 = 0; + let _temp_1737 = 0; + let _temp_1738 = 0; + let _temp_1739 = 0; + let _temp_1740 = 0; + let _temp_1741 = 0; + let _temp_1742 = 0; + let _temp_1743 = 0; + let _temp_1744 = 0; + let _temp_1745 = 0; + let _temp_1746 = 0; + let _temp_1747 = 0; + let _temp_1748 = 0; + let _temp_1749 = 0; + let _temp_1750 = 0; + let _temp_1751 = 0; + let _temp_1752 = 0; + let _temp_1753 = 0; + let _temp_1754 = 0; + let _temp_1755 = 0; + let _temp_1756 = 0; + let _temp_1757 = 0; + let _temp_1758 = 0; + let _temp_1759 = 0; + let _temp_1760 = 0; + let _temp_1761 = 0; + let _temp_1762 = 0; + let _temp_1763 = 0; + let _temp_1764 = 0; + let _temp_1765 = 0; + let _temp_1766 = 0; + let _temp_1767 = 0; + let _temp_1768 = 0; + let _temp_1769 = 0; + let _temp_1770 = 0; + let _temp_1771 = 0; + let _temp_1772 = 0; + let _temp_1773 = 0; + let _temp_1774 = 0; + let _temp_1775 = 0; + let _temp_1776 = 0; + let _temp_1777 = 0; + let _temp_1778 = 0; + let _temp_1779 = 0; + let _temp_1780 = 0; + let _temp_1781 = 0; + let _temp_1782 = 0; + let _temp_1783 = 0; + let _temp_1784 = 0; + let _temp_1785 = 0; + let _temp_1786 = 0; + let _temp_1787 = 0; + let _temp_1788 = 0; + let _temp_1789 = 0; + let _temp_1790 = 0; + let _temp_1791 = 0; + let _temp_1792 = 0; + let _temp_1793 = 0; + let _temp_1794 = 0; + let _temp_1795 = 0; + let _temp_1796 = 0; + let _temp_1797 = 0; + let _temp_1798 = 0; + let _temp_1799 = 0; + let _temp_1800 = 0; + let _temp_1801 = 0; + let _temp_1802 = 0; + let _temp_1803 = 0; + let _temp_1804 = 0; + let _temp_1805 = 0; + let _temp_1806 = 0; + let _temp_1807 = 0; + let _temp_1808 = 0; + let _temp_1809 = 0; + let _temp_1810 = 0; + let _temp_1811 = 0; + let _temp_1812 = 0; + let _temp_1813 = 0; + let _temp_1814 = 0; + let _temp_1815 = 0; + let _temp_1816 = 0; + let _temp_1817 = 0; + let _temp_1818 = 0; + let _temp_1819 = 0; + let _temp_1820 = 0; + let _temp_1821 = 0; + let _temp_1822 = 0; + let _temp_1823 = 0; + let _temp_1824 = 0; + let _temp_1825 = 0; + let _temp_1826 = 0; + let _temp_1827 = 0; + let _temp_1828 = 0; + let _temp_1829 = 0; + let _temp_1830 = 0; + let _temp_1831 = 0; + let _temp_1832 = 0; + let _temp_1833 = 0; + let _temp_1834 = 0; + let _temp_1835 = 0; + let _temp_1836 = 0; + let _temp_1837 = 0; + let _temp_1838 = 0; + let _temp_1839 = 0; + let _temp_1840 = 0; + let _temp_1841 = 0; + let _temp_1842 = 0; + let _temp_1843 = 0; + let _temp_1844 = 0; + let _temp_1845 = 0; + let _temp_1846 = 0; + let _temp_1847 = 0; + let _temp_1848 = 0; + let _temp_1849 = 0; + let _temp_1850 = 0; + let _temp_1851 = 0; + let _temp_1852 = 0; + let _temp_1853 = 0; + let _temp_1854 = 0; + let _temp_1855 = 0; + let _temp_1856 = 0; + let _temp_1857 = 0; + let _temp_1858 = 0; + let _temp_1859 = 0; + let _temp_1860 = 0; + let _temp_1861 = 0; + let _temp_1862 = 0; + let _temp_1863 = 0; + let _temp_1864 = 0; + let _temp_1865 = 0; + let _temp_1866 = 0; + let _temp_1867 = 0; + let _temp_1868 = 0; + let _temp_1869 = 0; + let _temp_1870 = 0; + let _temp_1871 = 0; + let _temp_1872 = 0; + let _temp_1873 = 0; + let _temp_1874 = 0; + let _temp_1875 = 0; + let _temp_1876 = 0; + let _temp_1877 = 0; + let _temp_1878 = 0; + let _temp_1879 = 0; + let _temp_1880 = 0; + let _temp_1881 = 0; + let _temp_1882 = 0; + let _temp_1883 = 0; + let _temp_1884 = 0; + let _temp_1885 = 0; + let _temp_1886 = 0; + let _temp_1887 = 0; + let _temp_1888 = 0; + let _temp_1889 = 0; + let _temp_1890 = 0; + let _temp_1891 = 0; + let _temp_1892 = 0; + let _temp_1893 = 0; + let _temp_1894 = 0; + let _temp_1895 = 0; + let _temp_1896 = 0; + let _temp_1897 = 0; + let _temp_1898 = 0; + let _temp_1899 = 0; + let _temp_1900 = 0; + let _temp_1901 = 0; + let _temp_1902 = 0; + let _temp_1903 = 0; + let _temp_1904 = 0; + let _temp_1905 = 0; + let _temp_1906 = 0; + let _temp_1907 = 0; + let _temp_1908 = 0; + let _temp_1909 = 0; + let _temp_1910 = 0; + let _temp_1911 = 0; + let _temp_1912 = 0; + let _temp_1913 = 0; + let _temp_1914 = 0; + let _temp_1915 = 0; + let _temp_1916 = 0; + let _temp_1917 = 0; + let _temp_1918 = 0; + let _temp_1919 = 0; + let _temp_1920 = 0; + let _temp_1921 = 0; + let _temp_1922 = 0; + let _temp_1923 = 0; + let _temp_1924 = 0; + let _temp_1925 = 0; + let _temp_1926 = 0; + let _temp_1927 = 0; + let _temp_1928 = 0; + let _temp_1929 = 0; + let _temp_1930 = 0; + let _temp_1931 = 0; + let _temp_1932 = 0; + let _temp_1933 = 0; + let _temp_1934 = 0; + let _temp_1935 = 0; + let _temp_1936 = 0; + let _temp_1937 = 0; + let _temp_1938 = 0; + let _temp_1939 = 0; + let _temp_1940 = 0; + let _temp_1941 = 0; + let _temp_1942 = 0; + let _temp_1943 = 0; + let _temp_1944 = 0; + let _temp_1945 = 0; + let _temp_1946 = 0; + let _temp_1947 = 0; + let _temp_1948 = 0; + let _temp_1949 = 0; + let _temp_1950 = 0; + let _temp_1951 = 0; + let _temp_1952 = 0; + let _temp_1953 = 0; + let _temp_1954 = 0; + let _temp_1955 = 0; + let _temp_1956 = 0; + let _temp_1957 = 0; + let _temp_1958 = 0; + let _temp_1959 = 0; + let _temp_1960 = 0; + let _temp_1961 = 0; + let _temp_1962 = 0; + let _temp_1963 = 0; + let _temp_1964 = 0; + let _temp_1965 = 0; + let _temp_1966 = 0; + let _temp_1967 = 0; + let _temp_1968 = 0; + let _temp_1969 = 0; + let _temp_1970 = 0; + let _temp_1971 = 0; + let _temp_1972 = 0; + let _temp_1973 = 0; + let _temp_1974 = 0; + let _temp_1975 = 0; + let _temp_1976 = 0; + let _temp_1977 = 0; + let _temp_1978 = 0; + let _temp_1979 = 0; + let _temp_1980 = 0; + let _temp_1981 = 0; + let _temp_1982 = 0; + let _temp_1983 = 0; + let _temp_1984 = 0; + let _temp_1985 = 0; + let _temp_1986 = 0; + let _temp_1987 = 0; + let _temp_1988 = 0; + let _temp_1989 = 0; + let _temp_1990 = 0; + let _temp_1991 = 0; + let _temp_1992 = 0; + let _temp_1993 = 0; + let _temp_1994 = 0; + let _temp_1995 = 0; + let _temp_1996 = 0; + let _temp_1997 = 0; + let _temp_1998 = 0; + let _temp_1999 = 0; + let _temp_2000 = 0; + let _temp_2001 = 0; + let _temp_2002 = 0; + let _temp_2003 = 0; + let _temp_2004 = 0; + let _temp_2005 = 0; + let _temp_2006 = 0; + let _temp_2007 = 0; + let _temp_2008 = 0; + let _temp_2009 = 0; + let _temp_2010 = 0; + let _temp_2011 = 0; + let _temp_2012 = 0; + let _temp_2013 = 0; + let _temp_2014 = 0; + let _temp_2015 = 0; + let _temp_2016 = 0; + let _temp_2017 = 0; + let _temp_2018 = 0; + let _temp_2019 = 0; + let _temp_2020 = 0; + let _temp_2021 = 0; + let _temp_2022 = 0; + let _temp_2023 = 0; + let _temp_2024 = 0; + let _temp_2025 = 0; + let _temp_2026 = 0; + let _temp_2027 = 0; + let _temp_2028 = 0; + let _temp_2029 = 0; + let _temp_2030 = 0; + let _temp_2031 = 0; + let _temp_2032 = 0; + let _temp_2033 = 0; + let _temp_2034 = 0; + let _temp_2035 = 0; + let _temp_2036 = 0; + let _temp_2037 = 0; + let _temp_2038 = 0; + let _temp_2039 = 0; + let _temp_2040 = 0; + let _temp_2041 = 0; + let _temp_2042 = 0; + let _temp_2043 = 0; + let _temp_2044 = 0; + let _temp_2045 = 0; + let _temp_2046 = 0; + let _temp_2047 = 0; + let _temp_2048 = 0; + let _temp_2049 = 0; + let _temp_2050 = 0; + let _temp_2051 = 0; + let _temp_2052 = 0; + let _temp_2053 = 0; + let _temp_2054 = 0; + let _temp_2055 = 0; + let _temp_2056 = 0; + let _temp_2057 = 0; + let _temp_2058 = 0; + let _temp_2059 = 0; + let _temp_2060 = 0; + let _temp_2061 = 0; + let _temp_2062 = 0; + let _temp_2063 = 0; + let _temp_2064 = 0; + let _temp_2065 = 0; + let _temp_2066 = 0; + let _temp_2067 = 0; + let _temp_2068 = 0; + let _temp_2069 = 0; + let _temp_2070 = 0; + let _temp_2071 = 0; + let _temp_2072 = 0; + let _temp_2073 = 0; + let _temp_2074 = 0; + let _temp_2075 = 0; + let _temp_2076 = 0; + let _temp_2077 = 0; + let _temp_2078 = 0; + let _temp_2079 = 0; + let _temp_2080 = 0; + let _temp_2081 = 0; + let _temp_2082 = 0; + let _temp_2083 = 0; + let _temp_2084 = 0; + let _temp_2085 = 0; + let _temp_2086 = 0; + let _temp_2087 = 0; + let _temp_2088 = 0; + let _temp_2089 = 0; + let _temp_2090 = 0; + let _temp_2091 = 0; + let _temp_2092 = 0; + let _temp_2093 = 0; + let _temp_2094 = 0; + let _temp_2095 = 0; + let _temp_2096 = 0; + let _temp_2097 = 0; + let _temp_2098 = 0; + let _temp_2099 = 0; + let _temp_2100 = 0; + let _temp_2101 = 0; + let _temp_2102 = 0; + let _temp_2103 = 0; + let _temp_2104 = 0; + let _temp_2105 = 0; + let _temp_2106 = 0; + let _temp_2107 = 0; + let _temp_2108 = 0; + let _temp_2109 = 0; + let _temp_2110 = 0; + let _temp_2111 = 0; + let _temp_2112 = 0; + let _temp_2113 = 0; + let _temp_2114 = 0; + let _temp_2115 = 0; + let _temp_2116 = 0; + let _temp_2117 = 0; + let _temp_2118 = 0; + let _temp_2119 = 0; + let _temp_2120 = 0; + let _temp_2121 = 0; + let _temp_2122 = 0; + let _temp_2123 = 0; + let _temp_2124 = 0; + let _temp_2125 = 0; + let _temp_2126 = 0; + let _temp_2127 = 0; + let _temp_2128 = 0; + let _temp_2129 = 0; + let _temp_2130 = 0; + let _temp_2131 = 0; + let _temp_2132 = 0; + let _temp_2133 = 0; + let _temp_2134 = 0; + let _temp_2135 = 0; + let _temp_2136 = 0; + let _temp_2137 = 0; + let _temp_2138 = 0; + let _temp_2139 = 0; + let _temp_2140 = 0; + let _temp_2141 = 0; + let _temp_2142 = 0; + let _temp_2143 = 0; + let _temp_2144 = 0; + let _temp_2145 = 0; + let _temp_2146 = 0; + let _temp_2147 = 0; + let _temp_2148 = 0; + let _temp_2149 = 0; + let _temp_2150 = 0; + let _temp_2151 = 0; + let _temp_2152 = 0; + let _temp_2153 = 0; + let _temp_2154 = 0; + let _temp_2155 = 0; + let _temp_2156 = 0; + let _temp_2157 = 0; + let _temp_2158 = 0; + let _temp_2159 = 0; + let _temp_2160 = 0; + let _temp_2161 = 0; + let _temp_2162 = 0; + let _temp_2163 = 0; + let _temp_2164 = 0; + let _temp_2165 = 0; + let _temp_2166 = 0; + let _temp_2167 = 0; + let _temp_2168 = 0; + let _temp_2169 = 0; + let _temp_2170 = 0; + let _temp_2171 = 0; + let _temp_2172 = 0; + let _temp_2173 = 0; + let _temp_2174 = 0; + let _temp_2175 = 0; + let _temp_2176 = 0; + let _temp_2177 = 0; + let _temp_2178 = 0; + let _temp_2179 = 0; + let _temp_2180 = 0; + let _temp_2181 = 0; + let _temp_2182 = 0; + let _temp_2183 = 0; + let _temp_2184 = 0; + let _temp_2185 = 0; + let _temp_2186 = 0; + let _temp_2187 = 0; + let _temp_2188 = 0; + let _temp_2189 = 0; + let _temp_2190 = 0; + let _temp_2191 = 0; + let _temp_2192 = 0; + let _temp_2193 = 0; + let _temp_2194 = 0; + let _temp_2195 = 0; + let _temp_2196 = 0; + let _temp_2197 = 0; + let _temp_2198 = 0; + let _temp_2199 = 0; + let _temp_2200 = 0; + let _temp_2201 = 0; + let _temp_2202 = 0; + let _temp_2203 = 0; + let _temp_2204 = 0; + let _temp_2205 = 0; + let _temp_2206 = 0; + let _temp_2207 = 0; + let _temp_2208 = 0; + let _temp_2209 = 0; + let _temp_2210 = 0; + let _temp_2211 = 0; + let _temp_2212 = 0; + let _temp_2213 = 0; + let _temp_2214 = 0; + let _temp_2215 = 0; + let _temp_2216 = 0; + let _temp_2217 = 0; + let _temp_2218 = 0; + let _temp_2219 = 0; + let _temp_2220 = 0; + let _temp_2221 = 0; + let _temp_2222 = 0; + let _temp_2223 = 0; + let _temp_2224 = 0; + let _temp_2225 = 0; + let _temp_2226 = 0; + let _temp_2227 = 0; + let _temp_2228 = 0; + let _temp_2229 = 0; + let _temp_2230 = 0; + let _temp_2231 = 0; + let _temp_2232 = 0; + let _temp_2233 = 0; + let _temp_2234 = 0; + let _temp_2235 = 0; + let _temp_2236 = 0; + let _temp_2237 = 0; + let _temp_2238 = 0; + let _temp_2239 = 0; + let _temp_2240 = 0; + let _temp_2241 = 0; + let _temp_2242 = 0; + let _temp_2243 = 0; + let _temp_2244 = 0; + let _temp_2245 = 0; + let _temp_2246 = 0; + let _temp_2247 = 0; + let _temp_2248 = 0; + let _temp_2249 = 0; + let _temp_2250 = 0; + let _temp_2251 = 0; + let _temp_2252 = 0; + let _temp_2253 = 0; + let _temp_2254 = 0; + let _temp_2255 = 0; + let _temp_2256 = 0; + let _temp_2257 = 0; + let _temp_2258 = 0; + let _temp_2259 = 0; + let _temp_2260 = 0; + let _temp_2261 = 0; + let _temp_2262 = 0; + let _temp_2263 = 0; + let _temp_2264 = 0; + let _temp_2265 = 0; + let _temp_2266 = 0; + let _temp_2267 = 0; + let _temp_2268 = 0; + let _temp_2269 = 0; + let _temp_2270 = 0; + let _temp_2271 = 0; + let _temp_2272 = 0; + let _temp_2273 = 0; + let _temp_2274 = 0; + let _temp_2275 = 0; + let _temp_2276 = 0; + let _temp_2277 = 0; + let _temp_2278 = 0; + let _temp_2279 = 0; + let _temp_2280 = 0; + let _temp_2281 = 0; + let _temp_2282 = 0; + let _temp_2283 = 0; + let _temp_2284 = 0; + let _temp_2285 = 0; + let _temp_2286 = 0; + let _temp_2287 = 0; + let _temp_2288 = 0; + let _temp_2289 = 0; + let _temp_2290 = 0; + let _temp_2291 = 0; + let _temp_2292 = 0; + let _temp_2293 = 0; + let _temp_2294 = 0; + let _temp_2295 = 0; + let _temp_2296 = 0; + let _temp_2297 = 0; + let _temp_2298 = 0; + let _temp_2299 = 0; + let _temp_2300 = 0; + let _temp_2301 = 0; + let _temp_2302 = 0; + let _temp_2303 = 0; + let _temp_2304 = 0; + let _temp_2305 = 0; + let _temp_2306 = 0; + let _temp_2307 = 0; + let _temp_2308 = 0; + let _temp_2309 = 0; + let _temp_2310 = 0; + let _temp_2311 = 0; + let _temp_2312 = 0; + let _temp_2313 = 0; + let _temp_2314 = 0; + let _temp_2315 = 0; + let _temp_2316 = 0; + let _temp_2317 = 0; + let _temp_2318 = 0; + let _temp_2319 = 0; + let _temp_2320 = 0; + let _temp_2321 = 0; + let _temp_2322 = 0; + let _temp_2323 = 0; + let _temp_2324 = 0; + let _temp_2325 = 0; + let _temp_2326 = 0; + let _temp_2327 = 0; + let _temp_2328 = 0; + let _temp_2329 = 0; + let _temp_2330 = 0; + let _temp_2331 = 0; + let _temp_2332 = 0; + let _temp_2333 = 0; + let _temp_2334 = 0; + let _temp_2335 = 0; + let _temp_2336 = 0; + let _temp_2337 = 0; + let _temp_2338 = 0; + let _temp_2339 = 0; + let _temp_2340 = 0; + let _temp_2341 = 0; + let _temp_2342 = 0; + let _temp_2343 = 0; + let _temp_2344 = 0; + let _temp_2345 = 0; + let _temp_2346 = 0; + let _temp_2347 = 0; + let _temp_2348 = 0; + let _temp_2349 = 0; + let _temp_2350 = 0; + let _temp_2351 = 0; + let _temp_2352 = 0; + let _temp_2353 = 0; + let _temp_2354 = 0; + let _temp_2355 = 0; + let _temp_2356 = 0; + let _temp_2357 = 0; + let _temp_2358 = 0; + let _temp_2359 = 0; + let _temp_2360 = 0; + let _temp_2361 = 0; + let _temp_2362 = 0; + let _temp_2363 = 0; + let _temp_2364 = 0; + let _temp_2365 = 0; + let _temp_2366 = 0; + let _temp_2367 = 0; + let _temp_2368 = 0; + let _temp_2369 = 0; + let _temp_2370 = 0; + let _temp_2371 = 0; + let _temp_2372 = 0; + let _temp_2373 = 0; + let _temp_2374 = 0; + let _temp_2375 = 0; + let _temp_2376 = 0; + let _temp_2377 = 0; + let _temp_2378 = 0; + let _temp_2379 = 0; + let _temp_2380 = 0; + let _temp_2381 = 0; + let _temp_2382 = 0; + let _temp_2383 = 0; + let _temp_2384 = 0; + let _temp_2385 = 0; + let _temp_2386 = 0; + let _temp_2387 = 0; + let _temp_2388 = 0; + let _temp_2389 = 0; + let _temp_2390 = 0; + let _temp_2391 = 0; + let _temp_2392 = 0; + let _temp_2393 = 0; + let _temp_2394 = 0; + let _temp_2395 = 0; + let _temp_2396 = 0; + let _temp_2397 = 0; + let _temp_2398 = 0; + let _temp_2399 = 0; + let _temp_2400 = 0; + let _temp_2401 = 0; + let _temp_2402 = 0; + let _temp_2403 = 0; + let _temp_2404 = 0; + let _temp_2405 = 0; + let _temp_2406 = 0; + let _temp_2407 = 0; + let _temp_2408 = 0; + let _temp_2409 = 0; + let _temp_2410 = 0; + let _temp_2411 = 0; + let _temp_2412 = 0; + let _temp_2413 = 0; + let _temp_2414 = 0; + let _temp_2415 = 0; + let _temp_2416 = 0; + let _temp_2417 = 0; + let _temp_2418 = 0; + let _temp_2419 = 0; + let _temp_2420 = 0; + let _temp_2421 = 0; + let _temp_2422 = 0; + let _temp_2423 = 0; + let _temp_2424 = 0; + let _temp_2425 = 0; + let _temp_2426 = 0; + let _temp_2427 = 0; + let _temp_2428 = 0; + let _temp_2429 = 0; + let _temp_2430 = 0; + let _temp_2431 = 0; + let _temp_2432 = 0; + let _temp_2433 = 0; + let _temp_2434 = 0; + let _temp_2435 = 0; + let _temp_2436 = 0; + let _temp_2437 = 0; + let _temp_2438 = 0; + let _temp_2439 = 0; + let _temp_2440 = 0; + let _temp_2441 = 0; + let _temp_2442 = 0; + let _temp_2443 = 0; + let _temp_2444 = 0; + let _temp_2445 = 0; + let _temp_2446 = 0; + let _temp_2447 = 0; + let _temp_2448 = 0; + let _temp_2449 = 0; + let _temp_2450 = 0; + let _temp_2451 = 0; + let _temp_2452 = 0; + let _temp_2453 = 0; + let _temp_2454 = 0; + let _temp_2455 = 0; + let _temp_2456 = 0; + let _temp_2457 = 0; + let _temp_2458 = 0; + let _temp_2459 = 0; + let _temp_2460 = 0; + let _temp_2461 = 0; + let _temp_2462 = 0; + let _temp_2463 = 0; + let _temp_2464 = 0; + let _temp_2465 = 0; + let _temp_2466 = 0; + let _temp_2467 = 0; + let _temp_2468 = 0; + let _temp_2469 = 0; + let _temp_2470 = 0; + let _temp_2471 = 0; + let _temp_2472 = 0; + let _temp_2473 = 0; + let _temp_2474 = 0; + let _temp_2475 = 0; + let _temp_2476 = 0; + let _temp_2477 = 0; + let _temp_2478 = 0; + let _temp_2479 = 0; + let _temp_2480 = 0; + let _temp_2481 = 0; + let _temp_2482 = 0; + let _temp_2483 = 0; + let _temp_2484 = 0; + let _temp_2485 = 0; + let _temp_2486 = 0; + let _temp_2487 = 0; + let _temp_2488 = 0; + let _temp_2489 = 0; + let _temp_2490 = 0; + let _temp_2491 = 0; + let _temp_2492 = 0; + let _temp_2493 = 0; + let _temp_2494 = 0; + let _temp_2495 = 0; + let _temp_2496 = 0; + let _temp_2497 = 0; + let _temp_2498 = 0; + let _temp_2499 = 0; + let _temp_2500 = 0; + let _temp_2501 = 0; + let _temp_2502 = 0; + let _temp_2503 = 0; + let _temp_2504 = 0; + let _temp_2505 = 0; + let _temp_2506 = 0; + let _temp_2507 = 0; + let _temp_2508 = 0; + let _temp_2509 = 0; + let _temp_2510 = 0; + let _temp_2511 = 0; + let _temp_2512 = 0; + let _temp_2513 = 0; + let _temp_2514 = 0; + let _temp_2515 = 0; + let _temp_2516 = 0; + let _temp_2517 = 0; + let _temp_2518 = 0; + let _temp_2519 = 0; + let _temp_2520 = 0; + let _temp_2521 = 0; + let _temp_2522 = 0; + let _temp_2523 = 0; + let _temp_2524 = 0; + let _temp_2525 = 0; + let _temp_2526 = 0; + let _temp_2527 = 0; + let _temp_2528 = 0; + let _temp_2529 = 0; + let _temp_2530 = 0; + let _temp_2531 = 0; + let _temp_2532 = 0; + let _temp_2533 = 0; + let _temp_2534 = 0; + let _temp_2535 = 0; + let _temp_2536 = 0; + let _temp_2537 = 0; + let _temp_2538 = 0; + let _temp_2539 = 0; + let _temp_2540 = 0; + let _temp_2541 = 0; + let _temp_2542 = 0; + let _temp_2543 = 0; + let _temp_2544 = 0; + let _temp_2545 = 0; + let _temp_2546 = 0; + let _temp_2547 = 0; + let _temp_2548 = 0; + let _temp_2549 = 0; + let _temp_2550 = 0; + let _temp_2551 = 0; + let _temp_2552 = 0; + let _temp_2553 = 0; + let _temp_2554 = 0; + let _temp_2555 = 0; + let _temp_2556 = 0; + let _temp_2557 = 0; + let _temp_2558 = 0; + let _temp_2559 = 0; + let _temp_2560 = 0; + let _temp_2561 = 0; + let _temp_2562 = 0; + let _temp_2563 = 0; + let _temp_2564 = 0; + let _temp_2565 = 0; + let _temp_2566 = 0; + let _temp_2567 = 0; + let _temp_2568 = 0; + let _temp_2569 = 0; + let _temp_2570 = 0; + let _temp_2571 = 0; + let _temp_2572 = 0; + let _temp_2573 = 0; + let _temp_2574 = 0; + let _temp_2575 = 0; + let _temp_2576 = 0; + let _temp_2577 = 0; + let _temp_2578 = 0; + let _temp_2579 = 0; + let _temp_2580 = 0; + let _temp_2581 = 0; + let _temp_2582 = 0; + let _temp_2583 = 0; + let _temp_2584 = 0; + let _temp_2585 = 0; + let _temp_2586 = 0; + let _temp_2587 = 0; + let _temp_2588 = 0; + let _temp_2589 = 0; + let _temp_2590 = 0; + let _temp_2591 = 0; + let _temp_2592 = 0; + let _temp_2593 = 0; +} diff --git a/tests/ui/recursion/issue-95134.rs b/tests/ui/recursion/issue-95134.rs new file mode 100644 index 000000000..fdc4d5369 --- /dev/null +++ b/tests/ui/recursion/issue-95134.rs @@ -0,0 +1,30 @@ +// build-fail +// known-bug: #95134 +// compile-flags: -Copt-level=0 +// failure-status: 101 +// dont-check-compiler-stderr + +pub fn encode_num(n: u32, mut writer: Writer) -> Result<(), Writer::Error> { + if n > 15 { + encode_num(n / 16, &mut writer)?; + } + Ok(()) +} + +pub trait ExampleWriter { + type Error; +} + +impl<'a, T: ExampleWriter> ExampleWriter for &'a mut T { + type Error = T::Error; +} + +struct EmptyWriter; + +impl ExampleWriter for EmptyWriter { + type Error = (); +} + +fn main() { + encode_num(69, &mut EmptyWriter).unwrap(); +} diff --git a/tests/ui/recursion/recursion.polonius.stderr b/tests/ui/recursion/recursion.polonius.stderr new file mode 100644 index 000000000..c727fe551 --- /dev/null +++ b/tests/ui/recursion/recursion.polonius.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `test::>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/recursion.rs:18:11 + | +LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `test` defined here + --> $DIR/recursion.rs:16:1 + | +LL | fn test (n:isize, i:isize, first:T, second:T) ->isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion.polonius/recursion.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/recursion/recursion.rs b/tests/ui/recursion/recursion.rs new file mode 100644 index 000000000..b3ba0ec3a --- /dev/null +++ b/tests/ui/recursion/recursion.rs @@ -0,0 +1,25 @@ +// build-fail +// compile-flags:-C overflow-checks=off +// normalize-stderr-test: ".nll/" -> "/" + +enum Nil {NilValue} +struct Cons {head:isize, tail:T} +trait Dot {fn dot(&self, other:Self) -> isize;} +impl Dot for Nil { + fn dot(&self, _:Nil) -> isize {0} +} +impl Dot for Cons { + fn dot(&self, other:Cons) -> isize { + self.head * other.head + self.tail.dot(other.tail) + } +} +fn test (n:isize, i:isize, first:T, second:T) ->isize { + match n { 0 => {first.dot(second)} + _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} + //~^ ERROR recursion limit + } +} +pub fn main() { + let n = test(1, 0, Nil::NilValue, Nil::NilValue); + println!("{}", n); +} diff --git a/tests/ui/recursion/recursion.stderr b/tests/ui/recursion/recursion.stderr new file mode 100644 index 000000000..cf0809537 --- /dev/null +++ b/tests/ui/recursion/recursion.stderr @@ -0,0 +1,15 @@ +error: reached the recursion limit while instantiating `test::>>>>>` + --> $DIR/recursion.rs:18:11 + | +LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `test` defined here + --> $DIR/recursion.rs:16:1 + | +LL | fn test (n:isize, i:isize, first:T, second:T) ->isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion/recursion.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/recursion/recursive-enum.rs b/tests/ui/recursion/recursive-enum.rs new file mode 100644 index 000000000..32e707607 --- /dev/null +++ b/tests/ui/recursion/recursive-enum.rs @@ -0,0 +1,4 @@ +enum List { Cons(T, List), Nil } +//~^ ERROR recursive type `List` has infinite size + +fn main() {} diff --git a/tests/ui/recursion/recursive-enum.stderr b/tests/ui/recursion/recursive-enum.stderr new file mode 100644 index 000000000..d662d1022 --- /dev/null +++ b/tests/ui/recursion/recursive-enum.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `List` has infinite size + --> $DIR/recursive-enum.rs:1:1 + | +LL | enum List { Cons(T, List), Nil } + | ^^^^^^^^^^^^ ------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | enum List { Cons(T, Box>), Nil } + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/recursion/recursive-reexports.rs b/tests/ui/recursion/recursive-reexports.rs new file mode 100644 index 000000000..0e17f2251 --- /dev/null +++ b/tests/ui/recursion/recursive-reexports.rs @@ -0,0 +1,7 @@ +// aux-build:recursive_reexports.rs + +extern crate recursive_reexports; + +fn f() -> recursive_reexports::S {} //~ ERROR cannot find type `S` in crate `recursive_reexports` + +fn main() {} diff --git a/tests/ui/recursion/recursive-reexports.stderr b/tests/ui/recursion/recursive-reexports.stderr new file mode 100644 index 000000000..f39d0a0d5 --- /dev/null +++ b/tests/ui/recursion/recursive-reexports.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `S` in crate `recursive_reexports` + --> $DIR/recursive-reexports.rs:5:32 + | +LL | fn f() -> recursive_reexports::S {} + | ^ not found in `recursive_reexports` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/recursion/recursive-requirements.rs b/tests/ui/recursion/recursive-requirements.rs new file mode 100644 index 000000000..9cfbee5f1 --- /dev/null +++ b/tests/ui/recursion/recursive-requirements.rs @@ -0,0 +1,19 @@ +use std::marker::PhantomData; + +struct AssertSync(PhantomData); + +pub struct Foo { + bar: *const Bar, + phantom: PhantomData, +} + +pub struct Bar { + foo: *const Foo, + phantom: PhantomData, +} + +fn main() { + let _: AssertSync = unimplemented!(); + //~^ ERROR E0277 + //~| ERROR E0277 +} diff --git a/tests/ui/recursion/recursive-requirements.stderr b/tests/ui/recursion/recursive-requirements.stderr new file mode 100644 index 000000000..8ee154ce5 --- /dev/null +++ b/tests/ui/recursion/recursive-requirements.stderr @@ -0,0 +1,45 @@ +error[E0277]: `*const Bar` cannot be shared between threads safely + --> $DIR/recursive-requirements.rs:16:12 + | +LL | let _: AssertSync = unimplemented!(); + | ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely + | + = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar` +note: required because it appears within the type `Foo` + --> $DIR/recursive-requirements.rs:5:12 + | +LL | pub struct Foo { + | ^^^ +note: required by a bound in `AssertSync` + --> $DIR/recursive-requirements.rs:3:22 + | +LL | struct AssertSync(PhantomData); + | ^^^^ required by this bound in `AssertSync` + +error[E0277]: `*const Foo` cannot be shared between threads safely + --> $DIR/recursive-requirements.rs:16:12 + | +LL | let _: AssertSync = unimplemented!(); + | ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely + | + = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo` +note: required because it appears within the type `Bar` + --> $DIR/recursive-requirements.rs:10:12 + | +LL | pub struct Bar { + | ^^^ + = note: required because it appears within the type `PhantomData` +note: required because it appears within the type `Foo` + --> $DIR/recursive-requirements.rs:5:12 + | +LL | pub struct Foo { + | ^^^ +note: required by a bound in `AssertSync` + --> $DIR/recursive-requirements.rs:3:22 + | +LL | struct AssertSync(PhantomData); + | ^^^^ required by this bound in `AssertSync` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/recursion/recursive-static-definition.rs b/tests/ui/recursion/recursive-static-definition.rs new file mode 100644 index 000000000..f59ef7316 --- /dev/null +++ b/tests/ui/recursion/recursive-static-definition.rs @@ -0,0 +1,4 @@ +pub static FOO: u32 = FOO; +//~^ ERROR cycle detected when const-evaluating + checking `FOO` + +fn main() {} diff --git a/tests/ui/recursion/recursive-static-definition.stderr b/tests/ui/recursion/recursive-static-definition.stderr new file mode 100644 index 000000000..135976145 --- /dev/null +++ b/tests/ui/recursion/recursive-static-definition.stderr @@ -0,0 +1,24 @@ +error[E0391]: cycle detected when const-evaluating + checking `FOO` + --> $DIR/recursive-static-definition.rs:1:1 + | +LL | pub static FOO: u32 = FOO; + | ^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... + --> $DIR/recursive-static-definition.rs:1:23 + | +LL | pub static FOO: u32 = FOO; + | ^^^ + = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle +note: cycle used when linting top-level module + --> $DIR/recursive-static-definition.rs:1:1 + | +LL | / pub static FOO: u32 = FOO; +LL | | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/recursion/recursive-types-are-not-uninhabited.rs b/tests/ui/recursion/recursive-types-are-not-uninhabited.rs new file mode 100644 index 000000000..448930363 --- /dev/null +++ b/tests/ui/recursion/recursive-types-are-not-uninhabited.rs @@ -0,0 +1,13 @@ +struct R<'a> { + r: &'a R<'a>, +} + +fn foo(res: Result) -> u32 { + let Ok(x) = res; + //~^ ERROR refutable pattern + x +} + +fn main() { + foo(Ok(23)); +} diff --git a/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr new file mode 100644 index 000000000..1b4d80d90 --- /dev/null +++ b/tests/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -0,0 +1,17 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/recursive-types-are-not-uninhabited.rs:6:9 + | +LL | let Ok(x) = res; + | ^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result>` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(x) = res else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/recursion_limit/empty.rs b/tests/ui/recursion_limit/empty.rs new file mode 100644 index 000000000..59dae106c --- /dev/null +++ b/tests/ui/recursion_limit/empty.rs @@ -0,0 +1,8 @@ +// Test the parse error for an empty recursion_limit + +#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer + //~| `limit` must be a non-negative integer + //~| ERROR `limit` must be a non-negative integer + //~| `limit` must be a non-negative integer + +fn main() {} diff --git a/tests/ui/recursion_limit/empty.stderr b/tests/ui/recursion_limit/empty.stderr new file mode 100644 index 000000000..cb5c0c35a --- /dev/null +++ b/tests/ui/recursion_limit/empty.stderr @@ -0,0 +1,18 @@ +error: `limit` must be a non-negative integer + --> $DIR/empty.rs:3:1 + | +LL | #![recursion_limit = ""] + | ^^^^^^^^^^^^^^^^^^^^^--^ + | | + | `limit` must be a non-negative integer + +error: `limit` must be a non-negative integer + --> $DIR/empty.rs:3:1 + | +LL | #![recursion_limit = ""] + | ^^^^^^^^^^^^^^^^^^^^^--^ + | | + | `limit` must be a non-negative integer + +error: aborting due to 2 previous errors + diff --git a/tests/ui/recursion_limit/invalid_digit.rs b/tests/ui/recursion_limit/invalid_digit.rs new file mode 100644 index 000000000..03df3e7a9 --- /dev/null +++ b/tests/ui/recursion_limit/invalid_digit.rs @@ -0,0 +1,7 @@ +// Test the parse error for an invalid digit in recursion_limit + +#![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer + //~| not a valid integer + //~| ERROR `limit` must be a non-negative integer + //~| not a valid integer +fn main() {} diff --git a/tests/ui/recursion_limit/invalid_digit.stderr b/tests/ui/recursion_limit/invalid_digit.stderr new file mode 100644 index 000000000..4dc93ad5f --- /dev/null +++ b/tests/ui/recursion_limit/invalid_digit.stderr @@ -0,0 +1,18 @@ +error: `limit` must be a non-negative integer + --> $DIR/invalid_digit.rs:3:1 + | +LL | #![recursion_limit = "-100"] + | ^^^^^^^^^^^^^^^^^^^^^------^ + | | + | not a valid integer + +error: `limit` must be a non-negative integer + --> $DIR/invalid_digit.rs:3:1 + | +LL | #![recursion_limit = "-100"] + | ^^^^^^^^^^^^^^^^^^^^^------^ + | | + | not a valid integer + +error: aborting due to 2 previous errors + diff --git a/tests/ui/recursion_limit/invalid_digit_type.rs b/tests/ui/recursion_limit/invalid_digit_type.rs new file mode 100644 index 000000000..e408109b3 --- /dev/null +++ b/tests/ui/recursion_limit/invalid_digit_type.rs @@ -0,0 +1,3 @@ +#![recursion_limit = 123] //~ ERROR malformed `recursion_limit` attribute + +fn main() {} diff --git a/tests/ui/recursion_limit/invalid_digit_type.stderr b/tests/ui/recursion_limit/invalid_digit_type.stderr new file mode 100644 index 000000000..6d1409bb3 --- /dev/null +++ b/tests/ui/recursion_limit/invalid_digit_type.stderr @@ -0,0 +1,8 @@ +error: malformed `recursion_limit` attribute input + --> $DIR/invalid_digit_type.rs:1:1 + | +LL | #![recursion_limit = 123] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + +error: aborting due to previous error + diff --git a/tests/ui/recursion_limit/invalid_macro.rs b/tests/ui/recursion_limit/invalid_macro.rs new file mode 100644 index 000000000..7db67a8d1 --- /dev/null +++ b/tests/ui/recursion_limit/invalid_macro.rs @@ -0,0 +1,7 @@ +#![recursion_limit = foo!()] //~ ERROR malformed `recursion_limit` attribute + +macro_rules! foo { + () => {"128"}; +} + +fn main() {} diff --git a/tests/ui/recursion_limit/invalid_macro.stderr b/tests/ui/recursion_limit/invalid_macro.stderr new file mode 100644 index 000000000..0189e99da --- /dev/null +++ b/tests/ui/recursion_limit/invalid_macro.stderr @@ -0,0 +1,8 @@ +error: malformed `recursion_limit` attribute input + --> $DIR/invalid_macro.rs:1:1 + | +LL | #![recursion_limit = foo!()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + +error: aborting due to previous error + diff --git a/tests/ui/recursion_limit/no-value.rs b/tests/ui/recursion_limit/no-value.rs new file mode 100644 index 000000000..2202e5b77 --- /dev/null +++ b/tests/ui/recursion_limit/no-value.rs @@ -0,0 +1,6 @@ +// Test the parse error for no value provided to recursion_limit + +#![recursion_limit] +//~^ ERROR malformed `recursion_limit` attribute input + +fn main() {} diff --git a/tests/ui/recursion_limit/no-value.stderr b/tests/ui/recursion_limit/no-value.stderr new file mode 100644 index 000000000..35ac2c4cd --- /dev/null +++ b/tests/ui/recursion_limit/no-value.stderr @@ -0,0 +1,8 @@ +error: malformed `recursion_limit` attribute input + --> $DIR/no-value.rs:3:1 + | +LL | #![recursion_limit] + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + +error: aborting due to previous error + diff --git a/tests/ui/recursion_limit/overflow.rs b/tests/ui/recursion_limit/overflow.rs new file mode 100644 index 000000000..c733ba6b9 --- /dev/null +++ b/tests/ui/recursion_limit/overflow.rs @@ -0,0 +1,9 @@ +// Test the parse error for an overflowing recursion_limit + +#![recursion_limit = "999999999999999999999999"] +//~^ ERROR `limit` must be a non-negative integer +//~| `limit` is too large +//~| ERROR `limit` must be a non-negative integer +//~| `limit` is too large + +fn main() {} diff --git a/tests/ui/recursion_limit/overflow.stderr b/tests/ui/recursion_limit/overflow.stderr new file mode 100644 index 000000000..2f622d28b --- /dev/null +++ b/tests/ui/recursion_limit/overflow.stderr @@ -0,0 +1,18 @@ +error: `limit` must be a non-negative integer + --> $DIR/overflow.rs:3:1 + | +LL | #![recursion_limit = "999999999999999999999999"] + | ^^^^^^^^^^^^^^^^^^^^^--------------------------^ + | | + | `limit` is too large + +error: `limit` must be a non-negative integer + --> $DIR/overflow.rs:3:1 + | +LL | #![recursion_limit = "999999999999999999999999"] + | ^^^^^^^^^^^^^^^^^^^^^--------------------------^ + | | + | `limit` is too large + +error: aborting due to 2 previous errors + diff --git a/tests/ui/recursion_limit/zero-overflow.rs b/tests/ui/recursion_limit/zero-overflow.rs new file mode 100644 index 000000000..77bd81856 --- /dev/null +++ b/tests/ui/recursion_limit/zero-overflow.rs @@ -0,0 +1,7 @@ +//~ ERROR overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome> +//~| HELP consider increasing the recursion limit +// build-fail + +#![recursion_limit = "0"] + +fn main() {} diff --git a/tests/ui/recursion_limit/zero-overflow.stderr b/tests/ui/recursion_limit/zero-overflow.stderr new file mode 100644 index 000000000..9007ec0d7 --- /dev/null +++ b/tests/ui/recursion_limit/zero-overflow.stderr @@ -0,0 +1,7 @@ +error[E0275]: overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero_overflow`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/recursion_limit/zero.rs b/tests/ui/recursion_limit/zero.rs new file mode 100644 index 000000000..3a2d904cb --- /dev/null +++ b/tests/ui/recursion_limit/zero.rs @@ -0,0 +1,12 @@ +// Test that a `limit` of 0 is valid + +#![recursion_limit = "0"] + +macro_rules! test { + () => {}; + ($tt:tt) => { test!(); }; +} + +test!(test); //~ ERROR recursion limit reached while expanding `test!` + +fn main() {} diff --git a/tests/ui/recursion_limit/zero.stderr b/tests/ui/recursion_limit/zero.stderr new file mode 100644 index 000000000..b43565909 --- /dev/null +++ b/tests/ui/recursion_limit/zero.stderr @@ -0,0 +1,10 @@ +error: recursion limit reached while expanding `test!` + --> $DIR/zero.rs:10:1 + | +LL | test!(test); + | ^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero`) + +error: aborting due to previous error + diff --git a/tests/ui/reexport-test-harness-main.rs b/tests/ui/reexport-test-harness-main.rs new file mode 100644 index 000000000..2582975e2 --- /dev/null +++ b/tests/ui/reexport-test-harness-main.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags:--test + +#![reexport_test_harness_main = "test_main"] + +#[cfg(test)] +fn _unused() { + // should resolve to the entry point function the --test harness + // creates. + test_main(); +} diff --git a/tests/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs b/tests/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs new file mode 100644 index 000000000..ce2a3a7db --- /dev/null +++ b/tests/ui/regions/auxiliary/rbmtp_cross_crate_lib.rs @@ -0,0 +1,32 @@ +// Check that method bounds declared on traits/impls in a cross-crate +// scenario work. This is the library portion of the test. + +pub enum MaybeOwned<'a> { + Owned(isize), + Borrowed(&'a isize) +} + +pub struct Inv<'a> { // invariant w/r/t 'a + x: &'a mut &'a isize +} + +// I encountered a bug at some point with encoding the IntoMaybeOwned +// trait, so I'll use that as the template for this test. +pub trait IntoMaybeOwned<'a> { + fn into_maybe_owned(self) -> MaybeOwned<'a>; + + // Note: without this `into_inv` method, the trait is + // contravariant w/r/t `'a`, since if you look strictly at the + // interface, it only returns `'a`. This complicates the + // downstream test since it wants invariance to force an error. + // Hence we add this method. + fn into_inv(self) -> Inv<'a>; + + fn bigger_region<'b:'a>(self, b: Inv<'b>); +} + +impl<'a> IntoMaybeOwned<'a> for Inv<'a> { + fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() } + fn into_inv(self) -> Inv<'a> { panic!() } + fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() } +} diff --git a/tests/ui/regions/closure-in-projection-issue-97405.rs b/tests/ui/regions/closure-in-projection-issue-97405.rs new file mode 100644 index 000000000..e567d5c27 --- /dev/null +++ b/tests/ui/regions/closure-in-projection-issue-97405.rs @@ -0,0 +1,32 @@ +// Regression test for #97405. +// In `good_generic_fn` the param `T` ends up in the substs of closures/generators, +// but we should be able to prove ` as Iterator>::Item: 'static` without +// requiring `T: 'static` + +// edition:2018 +// check-fail + +fn opaque(_: F) -> impl Iterator { b"".iter() } + +fn assert_static(_: T) {} + +fn good_generic_fn() { + // Previously, proving ` as Iterator>::Item: 'static` + // used to require `T: 'static`. + assert_static(opaque(async {}).next()); + assert_static(opaque(|| {}).next()); + assert_static(opaque(opaque(async {}).next()).next()); +} + + +// This should fail because `T` ends up in the upvars of the closure. +fn bad_generic_fn(t: T) { + assert_static(opaque(async move { t; }).next()); + //~^ ERROR the associated type `::Item` may not live long enough + assert_static(opaque(move || { t; }).next()); + //~^ ERROR the associated type `::Item` may not live long enough + assert_static(opaque(opaque(async move { t; }).next()).next()); + //~^ ERROR the associated type `::Item` may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/closure-in-projection-issue-97405.stderr b/tests/ui/regions/closure-in-projection-issue-97405.stderr new file mode 100644 index 000000000..c08f1059e --- /dev/null +++ b/tests/ui/regions/closure-in-projection-issue-97405.stderr @@ -0,0 +1,30 @@ +error[E0310]: the associated type `::Item` may not live long enough + --> $DIR/closure-in-projection-issue-97405.rs:24:5 + | +LL | assert_static(opaque(async move { t; }).next()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error[E0310]: the associated type `::Item` may not live long enough + --> $DIR/closure-in-projection-issue-97405.rs:26:5 + | +LL | assert_static(opaque(move || { t; }).next()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error[E0310]: the associated type `::Item` may not live long enough + --> $DIR/closure-in-projection-issue-97405.rs:28:5 + | +LL | assert_static(opaque(opaque(async move { t; }).next()).next()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.rs b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.rs new file mode 100644 index 000000000..a1e801e39 --- /dev/null +++ b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.rs @@ -0,0 +1,12 @@ +pub trait T {} + +struct S<'a>(&'a ()); + +impl<'a> T for S<'a> {} + +fn foo() -> impl T { + let x = (); + S(&x) //~ ERROR `x` does not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr new file mode 100644 index 000000000..6ea238f30 --- /dev/null +++ b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr @@ -0,0 +1,14 @@ +error[E0597]: `x` does not live long enough + --> $DIR/do-not-suggest-adding-bound-to-opaque-type.rs:9:7 + | +LL | S(&x) + | --^^- + | | | + | | borrowed value does not live long enough + | opaque type requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/forall-wf-ref-reflexive.rs b/tests/ui/regions/forall-wf-ref-reflexive.rs new file mode 100644 index 000000000..9c37d72d5 --- /dev/null +++ b/tests/ui/regions/forall-wf-ref-reflexive.rs @@ -0,0 +1,18 @@ +// Test that we consider `for<'a> &'a T: 'a` to be sufficient to prove +// that `for<'a> &'a T: 'a`. +// +// FIXME. Except we don't! + +#![allow(warnings)] + +fn self_wf2() +where + for<'a> &'a T: 'a, +{ + self_wf2::(); + //~^ ERROR `T` does not live long enough + // + // FIXME. This ought to be accepted, presumably. +} + +fn main() {} diff --git a/tests/ui/regions/forall-wf-ref-reflexive.stderr b/tests/ui/regions/forall-wf-ref-reflexive.stderr new file mode 100644 index 000000000..3d059ccec --- /dev/null +++ b/tests/ui/regions/forall-wf-ref-reflexive.stderr @@ -0,0 +1,8 @@ +error: `T` does not live long enough + --> $DIR/forall-wf-ref-reflexive.rs:12:5 + | +LL | self_wf2::(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/regions/forall-wf-reflexive.rs b/tests/ui/regions/forall-wf-reflexive.rs new file mode 100644 index 000000000..8e6b8224b --- /dev/null +++ b/tests/ui/regions/forall-wf-reflexive.rs @@ -0,0 +1,15 @@ +// Test that we consider `for<'a> T: 'a` to be sufficient to prove +// that `for<'a> T: 'a`. +// +// check-pass + +#![allow(warnings)] + +fn self_wf1() +where + for<'a> T: 'a, +{ + self_wf1::(); +} + +fn main() {} diff --git a/tests/ui/regions/init-res-into-things.rs b/tests/ui/regions/init-res-into-things.rs new file mode 100644 index 000000000..7f416262d --- /dev/null +++ b/tests/ui/regions/init-res-into-things.rs @@ -0,0 +1,81 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +use std::cell::Cell; + +// Resources can't be copied, but storing into data structures counts +// as a move unless the stored thing is used afterwards. + +struct r<'a> { + i: &'a Cell, +} + +struct BoxR<'a> { x: r<'a> } + +impl<'a> Drop for r<'a> { + fn drop(&mut self) { + self.i.set(self.i.get() + 1) + } +} + +fn r(i: &Cell) -> r { + r { + i: i + } +} + +fn test_rec() { + let i = &Cell::new(0); + { + let _a = BoxR {x: r(i)}; + } + assert_eq!(i.get(), 1); +} + +fn test_tag() { + enum t<'a> { + t0(r<'a>), + } + + let i = &Cell::new(0); + { + let _a = t::t0(r(i)); + } + assert_eq!(i.get(), 1); +} + +fn test_tup() { + let i = &Cell::new(0); + { + let _a = (r(i), 0); + } + assert_eq!(i.get(), 1); +} + +fn test_unique() { + let i = &Cell::new(0); + { + let _a: Box<_> = Box::new(r(i)); + } + assert_eq!(i.get(), 1); +} + +fn test_unique_rec() { + let i = &Cell::new(0); + { + let _a: Box<_> = Box::new(BoxR { + x: r(i) + }); + } + assert_eq!(i.get(), 1); +} + +pub fn main() { + test_rec(); + test_tag(); + test_tup(); + test_unique(); + test_unique_rec(); +} diff --git a/tests/ui/regions/issue-101280.rs b/tests/ui/regions/issue-101280.rs new file mode 100644 index 000000000..29f158366 --- /dev/null +++ b/tests/ui/regions/issue-101280.rs @@ -0,0 +1,10 @@ +use std::cell::Cell; + +type Ty = for<'r> fn(Cell<(&'r i32, &'r i32)>); + +fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/regions/issue-101280.stderr b/tests/ui/regions/issue-101280.stderr new file mode 100644 index 000000000..320d008ae --- /dev/null +++ b/tests/ui/regions/issue-101280.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-101280.rs:6:5 + | +LL | fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty { + | -- expected `for<'r> fn(Cell<(&'r i32, &'r i32)>)` because of return type +LL | f + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)` + found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/issue-102374.rs b/tests/ui/regions/issue-102374.rs new file mode 100644 index 000000000..fd71248d9 --- /dev/null +++ b/tests/ui/regions/issue-102374.rs @@ -0,0 +1,21 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" +use std::cell::Cell; + +#[rustfmt::skip] +fn f( + f: for<'a, 'b, 'c, 'd, 'e, 'f, 'g, + 'h, 'i, 'j, 'k, 'l, 'm, 'n, + 'o, 'p, 'q, 'r, 's, 't, 'u, + 'v, 'w, 'x, 'y, 'z, 'z0> + fn(Cell<(& i32, &'a i32, &'b i32, &'c i32, &'d i32, + &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, + &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, + &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, + &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, + &'y i32, &'z i32, &'z0 i32)>), +) -> i32 { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/regions/issue-102374.stderr b/tests/ui/regions/issue-102374.stderr new file mode 100644 index 000000000..157850693 --- /dev/null +++ b/tests/ui/regions/issue-102374.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-102374.rs:17:5 + | +LL | ) -> i32 { + | --- expected `i32` because of return type +LL | f + | ^ expected `i32`, found fn pointer + | + = note: expected type `i32` + found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)` + the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt' + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/issue-102392.rs b/tests/ui/regions/issue-102392.rs new file mode 100644 index 000000000..87cc1a8e7 --- /dev/null +++ b/tests/ui/regions/issue-102392.rs @@ -0,0 +1,6 @@ +fn g(f: for<'a> fn(fn(&str, &'a str))) -> bool { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/regions/issue-102392.stderr b/tests/ui/regions/issue-102392.stderr new file mode 100644 index 000000000..56f4c0c5d --- /dev/null +++ b/tests/ui/regions/issue-102392.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-102392.rs:2:5 + | +LL | fn g(f: for<'a> fn(fn(&str, &'a str))) -> bool { + | ---- expected `bool` because of return type +LL | f + | ^ expected `bool`, found fn pointer + | + = note: expected type `bool` + found fn pointer `for<'a> fn(for<'b> fn(&'b str, &'a str))` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/issue-11612.rs b/tests/ui/regions/issue-11612.rs new file mode 100644 index 000000000..9f7f1cc6f --- /dev/null +++ b/tests/ui/regions/issue-11612.rs @@ -0,0 +1,24 @@ +// check-pass +#![allow(dead_code)] +// #11612 +// We weren't updating the auto adjustments with all the resolved +// type information after type check. + +// pretty-expanded FIXME #23616 + +trait A { fn dummy(&self) { } } + +struct B<'a, T:'a> { + f: &'a T +} + +impl<'a, T> A for B<'a, T> {} + +fn foo(_: &dyn A) {} + +fn bar(b: &B) { + foo(b); // Coercion should work + foo(b as &dyn A); // Explicit cast should work as well +} + +fn main() {} diff --git a/tests/ui/regions/issue-12470.rs b/tests/ui/regions/issue-12470.rs new file mode 100644 index 000000000..d8f2abb0c --- /dev/null +++ b/tests/ui/regions/issue-12470.rs @@ -0,0 +1,34 @@ +trait X { + fn get_i(&self) -> isize; +} + + + + +struct B { + i: isize +} + +impl X for B { + fn get_i(&self) -> isize { + self.i + } +} + +struct A<'a> { + p: &'a (dyn X + 'a) +} + +fn make_a<'a>(p: &'a dyn X) -> A<'a> { + A { p: p } +} + +fn make_make_a<'a>() -> A<'a> { + let b: Box = Box::new(B { i: 1 }); + let bb: &B = &*b; + make_a(bb) //~ ERROR cannot return value referencing local data `*b` +} + +fn main() { + let _a = make_make_a(); +} diff --git a/tests/ui/regions/issue-12470.stderr b/tests/ui/regions/issue-12470.stderr new file mode 100644 index 000000000..c97e59195 --- /dev/null +++ b/tests/ui/regions/issue-12470.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing local data `*b` + --> $DIR/issue-12470.rs:29:5 + | +LL | let bb: &B = &*b; + | --- `*b` is borrowed here +LL | make_a(bb) + | ^^^^^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/issue-21520.rs b/tests/ui/regions/issue-21520.rs new file mode 100644 index 000000000..ab4ac7237 --- /dev/null +++ b/tests/ui/regions/issue-21520.rs @@ -0,0 +1,22 @@ +// check-pass +#![allow(dead_code)] +// Test that the requirement (in `Bar`) that `T::Bar : 'static` does +// not wind up propagating to `T`. + +// pretty-expanded FIXME #23616 + +pub trait Foo { + type Bar; + + fn foo(&self) -> Self; +} + +pub struct Static(T); + +struct Bar + where T::Bar : 'static +{ + x: Static> +} + +fn main() { } diff --git a/tests/ui/regions/issue-24085.rs b/tests/ui/regions/issue-24085.rs new file mode 100644 index 000000000..86e94beb7 --- /dev/null +++ b/tests/ui/regions/issue-24085.rs @@ -0,0 +1,19 @@ +// check-pass +#![allow(dead_code)] +// Regression test for #24085. Errors were occurring in region +// inference due to the requirement that `'a:b'`, which was getting +// incorrectly codegened in connection with the closure below. + +#[derive(Copy,Clone)] +struct Path<'a:'b, 'b> { + x: &'a i32, + tail: Option<&'b Path<'a, 'b>> +} + +#[allow(dead_code, unconditional_recursion)] +fn foo<'a,'b,F>(p: Path<'a, 'b>, mut f: F) + where F: for<'c> FnMut(Path<'a, 'c>) { + foo(p, |x| f(x)) +} + +fn main() { } diff --git a/tests/ui/regions/issue-26448-1.rs b/tests/ui/regions/issue-26448-1.rs new file mode 100644 index 000000000..7d2d75bf2 --- /dev/null +++ b/tests/ui/regions/issue-26448-1.rs @@ -0,0 +1,13 @@ +// run-pass + +pub trait Foo { + fn foo(self) -> T; +} + +impl<'a, T> Foo for &'a str where &'a str: Into { + fn foo(self) -> T { + panic!(); + } +} + +fn main() {} diff --git a/tests/ui/regions/issue-26448-2.rs b/tests/ui/regions/issue-26448-2.rs new file mode 100644 index 000000000..c60e06c3c --- /dev/null +++ b/tests/ui/regions/issue-26448-2.rs @@ -0,0 +1,21 @@ +// check-pass + +pub struct Bar { + items: Vec<&'static str>, + inner: T, +} + +pub trait IntoBar { + fn into_bar(self) -> Bar; +} + +impl<'a, T> IntoBar for &'a str where &'a str: Into { + fn into_bar(self) -> Bar { + Bar { + items: Vec::new(), + inner: self.into(), + } + } +} + +fn main() {} diff --git a/tests/ui/regions/issue-26448-3.rs b/tests/ui/regions/issue-26448-3.rs new file mode 100644 index 000000000..d48022c09 --- /dev/null +++ b/tests/ui/regions/issue-26448-3.rs @@ -0,0 +1,25 @@ +// check-pass + +pub struct Item { + _inner: &'static str, +} + +pub struct Bar { + items: Vec, + inner: T, +} + +pub trait IntoBar { + fn into_bar(self) -> Bar; +} + +impl<'a, T> IntoBar for &'a str where &'a str: Into { + fn into_bar(self) -> Bar { + Bar { + items: Vec::new(), + inner: self.into(), + } + } +} + +fn main() {} diff --git a/tests/ui/regions/issue-2718.rs b/tests/ui/regions/issue-2718.rs new file mode 100644 index 000000000..6449337ee --- /dev/null +++ b/tests/ui/regions/issue-2718.rs @@ -0,0 +1,327 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_unsafe)] +#![allow(unused_imports)] +#![allow(non_camel_case_types)] + +pub type Task = isize; + +// tjc: I don't know why +pub mod pipes { + use self::state::{empty, full, blocked, terminated}; + use super::Task; + use std::mem::{forget, transmute}; + use std::mem::{replace, swap}; + use std::mem; + use std::thread; + use std::marker::Send; + + pub struct Stuff { + state: state, + blocked_task: Option, + payload: Option + } + + #[derive(PartialEq, Debug)] + #[repr(isize)] + pub enum state { + empty, + full, + blocked, + terminated + } + + pub struct packet { + state: state, + blocked_task: Option, + payload: Option + } + + unsafe impl Send for packet {} + + pub fn packet() -> *const packet { + unsafe { + let p: *const packet = mem::transmute(Box::new(Stuff{ + state: empty, + blocked_task: None::, + payload: None:: + })); + p + } + } + + mod rusti { + pub fn atomic_xchg(_dst: &mut isize, _src: isize) -> isize { panic!(); } + pub fn atomic_xchg_acq(_dst: &mut isize, _src: isize) -> isize { panic!(); } + pub fn atomic_xchg_rel(_dst: &mut isize, _src: isize) -> isize { panic!(); } + } + + // We should consider moving this to ::std::unsafe, although I + // suspect graydon would want us to use void pointers instead. + pub unsafe fn uniquify(x: *const T) -> Box { + mem::transmute(x) + } + + pub fn swap_state_acq(dst: &mut state, src: state) -> state { + unsafe { + transmute(rusti::atomic_xchg_acq(transmute(dst), src as isize)) + } + } + + pub fn swap_state_rel(dst: &mut state, src: state) -> state { + unsafe { + transmute(rusti::atomic_xchg_rel(transmute(dst), src as isize)) + } + } + + pub fn send(mut p: send_packet, payload: T) { + let p = p.unwrap(); + let mut p = unsafe { uniquify(p) }; + assert!((*p).payload.is_none()); + (*p).payload = Some(payload); + let old_state = swap_state_rel(&mut (*p).state, full); + match old_state { + empty => { + // Yay, fastpath. + + // The receiver will eventually clean this up. + unsafe { forget(p); } + } + full => { panic!("duplicate send") } + blocked => { + + // The receiver will eventually clean this up. + unsafe { forget(p); } + } + terminated => { + // The receiver will never receive this. Rely on drop_glue + // to clean everything up. + } + } + } + + pub fn recv(mut p: recv_packet) -> Option { + let p = p.unwrap(); + let mut p = unsafe { uniquify(p) }; + loop { + let old_state = swap_state_acq(&mut (*p).state, + blocked); + match old_state { + empty | blocked => { thread::yield_now(); } + full => { + let payload = replace(&mut p.payload, None); + return Some(payload.unwrap()) + } + terminated => { + assert_eq!(old_state, terminated); + return None; + } + } + } + } + + pub fn sender_terminate(p: *const packet) { + let mut p = unsafe { uniquify(p) }; + match swap_state_rel(&mut (*p).state, terminated) { + empty | blocked => { + // The receiver will eventually clean up. + unsafe { forget(p) } + } + full => { + // This is impossible + panic!("you dun goofed") + } + terminated => { + // I have to clean up, use drop_glue + } + } + } + + pub fn receiver_terminate(p: *const packet) { + let mut p = unsafe { uniquify(p) }; + match swap_state_rel(&mut (*p).state, terminated) { + empty => { + // the sender will clean up + unsafe { forget(p) } + } + blocked => { + // this shouldn't happen. + panic!("terminating a blocked packet") + } + terminated | full => { + // I have to clean up, use drop_glue + } + } + } + + pub struct send_packet { + p: Option<*const packet>, + } + + impl Drop for send_packet { + fn drop(&mut self) { + unsafe { + if self.p != None { + let self_p: &mut Option<*const packet> = + mem::transmute(&mut self.p); + let p = replace(self_p, None); + sender_terminate(p.unwrap()) + } + } + } + } + + impl send_packet { + pub fn unwrap(&mut self) -> *const packet { + replace(&mut self.p, None).unwrap() + } + } + + pub fn send_packet(p: *const packet) -> send_packet { + send_packet { + p: Some(p) + } + } + + pub struct recv_packet { + p: Option<*const packet>, + } + + impl Drop for recv_packet { + fn drop(&mut self) { + unsafe { + if self.p != None { + let self_p: &mut Option<*const packet> = + mem::transmute(&mut self.p); + let p = replace(self_p, None); + receiver_terminate(p.unwrap()) + } + } + } + } + + impl recv_packet { + pub fn unwrap(&mut self) -> *const packet { + replace(&mut self.p, None).unwrap() + } + } + + pub fn recv_packet(p: *const packet) -> recv_packet { + recv_packet { + p: Some(p) + } + } + + pub fn entangle() -> (send_packet, recv_packet) { + let p = packet(); + (send_packet(p), recv_packet(p)) + } +} + +pub mod pingpong { + use std::mem; + + pub struct ping(::pipes::send_packet); + + unsafe impl Send for ping {} + + pub struct pong(::pipes::send_packet); + + unsafe impl Send for pong {} + + pub fn liberate_ping(p: ping) -> ::pipes::send_packet { + unsafe { + let _addr : *const ::pipes::send_packet = match &p { + &ping(ref x) => { mem::transmute(x) } + }; + panic!() + } + } + + pub fn liberate_pong(p: pong) -> ::pipes::send_packet { + unsafe { + let _addr : *const ::pipes::send_packet = match &p { + &pong(ref x) => { mem::transmute(x) } + }; + panic!() + } + } + + pub fn init() -> (client::ping, server::ping) { + ::pipes::entangle() + } + + pub mod client { + use pingpong; + + pub type ping = ::pipes::send_packet; + pub type pong = ::pipes::recv_packet; + + pub fn do_ping(c: ping) -> pong { + let (sp, rp) = ::pipes::entangle(); + + ::pipes::send(c, pingpong::ping(sp)); + rp + } + + pub fn do_pong(c: pong) -> (ping, ()) { + let packet = ::pipes::recv(c); + if packet.is_none() { + panic!("sender closed the connection") + } + (pingpong::liberate_pong(packet.unwrap()), ()) + } + } + + pub mod server { + use pingpong; + + pub type ping = ::pipes::recv_packet; + pub type pong = ::pipes::send_packet; + + pub fn do_ping(c: ping) -> (pong, ()) { + let packet = ::pipes::recv(c); + if packet.is_none() { + panic!("sender closed the connection") + } + (pingpong::liberate_ping(packet.unwrap()), ()) + } + + pub fn do_pong(c: pong) -> ping { + let (sp, rp) = ::pipes::entangle(); + ::pipes::send(c, pingpong::pong(sp)); + rp + } + } +} + +fn client(chan: pingpong::client::ping) { + let chan = pingpong::client::do_ping(chan); + println!("Sent ping"); + let (_chan, _data) = pingpong::client::do_pong(chan); + println!("Received pong"); +} + +fn server(chan: pingpong::server::ping) { + let (chan, _data) = pingpong::server::do_ping(chan); + println!("Received ping"); + let _chan = pingpong::server::do_pong(chan); + println!("Sent pong"); +} + +pub fn main() { + /* +// Commented out because of option::get error + + let (client_, server_) = pingpong::init(); + + task::spawn {|client_| + let client__ = client_.take(); + client(client__); + }; + task::spawn {|server_| + let server__ = server_.take(); + server(server_ËŠ); + }; + */ +} diff --git a/tests/ui/regions/issue-28848.rs b/tests/ui/regions/issue-28848.rs new file mode 100644 index 000000000..0eb3d89c5 --- /dev/null +++ b/tests/ui/regions/issue-28848.rs @@ -0,0 +1,14 @@ +struct Foo<'a, 'b: 'a>(&'a &'b ()); + +impl<'a, 'b> Foo<'a, 'b> { + fn xmute(a: &'b ()) -> &'a () { + unreachable!() + } +} + +pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { + Foo::<'a, 'b>::xmute(u) + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/issue-28848.stderr b/tests/ui/regions/issue-28848.stderr new file mode 100644 index 000000000..a29dac4c9 --- /dev/null +++ b/tests/ui/regions/issue-28848.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/issue-28848.rs:10:5 + | +LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | Foo::<'a, 'b>::xmute(u) + | ^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/regions/issue-5243.rs b/tests/ui/regions/issue-5243.rs new file mode 100644 index 000000000..c511d45f0 --- /dev/null +++ b/tests/ui/regions/issue-5243.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// Check that merely having lifetime parameters is not +// enough for codegen to consider this as non-monomorphic, +// which led to various assertions and failures in turn. + +// pretty-expanded FIXME #23616 + +struct S<'a> { + v: &'a isize +} + +fn f<'lt>(_s: &'lt S<'lt>) {} + +pub fn main() { + f(& S { v: &42 }); +} diff --git a/tests/ui/regions/issue-56537-closure-uses-region-from-container.rs b/tests/ui/regions/issue-56537-closure-uses-region-from-container.rs new file mode 100644 index 000000000..a8f7a41c4 --- /dev/null +++ b/tests/ui/regions/issue-56537-closure-uses-region-from-container.rs @@ -0,0 +1,67 @@ +// This is a collection of examples where a function's formal +// parameter has an explicit lifetime and a closure within that +// function returns that formal parameter. The closure's return type, +// to be correctly inferred, needs to include the lifetime introduced +// by the function. +// +// This works today, which precludes changing things so that closures +// follow the same lifetime-elision rules used elsewhere. See +// rust-lang/rust#56537 + +// check-pass + +fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x| { p }; // no type annotation at all + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x| -> &str { p }; // type annotation on the return type + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x| -> &'w str { p }; // type+region annotation on return type + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_arg_type_ret_type_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x: &str| -> &str { p }; // type annotation on arg and return types + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn willy_arg_type_ret_region_annot<'w>(p: &'w str, q: &str) -> &'w str { + let free_dumb = |_x: &str| -> &'w str { p }; // fully annotated + let hello = format!("Hello"); + free_dumb(&hello) +} + +fn main() { + let world = format!("World"); + let w1: &str = { + let hello = format!("He11o"); + willy_no_annot(&world, &hello) + }; + let w2: &str = { + let hello = format!("He22o"); + willy_ret_type_annot(&world, &hello) + }; + let w3: &str = { + let hello = format!("He33o"); + willy_ret_region_annot(&world, &hello) + }; + let w4: &str = { + let hello = format!("He44o"); + willy_arg_type_ret_type_annot(&world, &hello) + }; + let w5: &str = { + let hello = format!("He55o"); + willy_arg_type_ret_region_annot(&world, &hello) + }; + assert_eq!((w1, w2, w3, w4, w5), + ("World","World","World","World","World")); +} diff --git a/tests/ui/regions/issue-6157.rs b/tests/ui/regions/issue-6157.rs new file mode 100644 index 000000000..b7a44ed86 --- /dev/null +++ b/tests/ui/regions/issue-6157.rs @@ -0,0 +1,23 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait OpInt { fn call(&mut self, _: isize, _: isize) -> isize; } + +impl OpInt for F where F: FnMut(isize, isize) -> isize { + fn call(&mut self, a:isize, b:isize) -> isize { + (*self)(a, b) + } +} + +fn squarei<'a>(x: isize, op: &'a mut dyn OpInt) -> isize { op.call(x, x) } + +fn muli(x:isize, y:isize) -> isize { x * y } + +pub fn main() { + let mut f = |x, y| muli(x, y); + { + let g = &mut f; + let h = g as &mut dyn OpInt; + squarei(3, h); + } +} diff --git a/tests/ui/regions/issue-72051-member-region-hang.rs b/tests/ui/regions/issue-72051-member-region-hang.rs new file mode 100644 index 000000000..b7340b79d --- /dev/null +++ b/tests/ui/regions/issue-72051-member-region-hang.rs @@ -0,0 +1,7 @@ +// Regression test for #72051, hang when resolving regions. + +// check-pass +// edition:2018 + +pub async fn query<'a>(_: &(), _: &(), _: (&(dyn std::any::Any + 'a),) ) {} +fn main() {} diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr new file mode 100644 index 000000000..7f232e4a7 --- /dev/null +++ b/tests/ui/regions/issue-78262.base.stderr @@ -0,0 +1,14 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/issue-78262.rs:12:26 + | +LL | let f = |x: &dyn TT| x.func(); + | - - ^^^^^^^^ + | | | | + | | | `x` escapes the closure body here + | | | argument requires that `'1` must outlive `'static` + | | let's call the lifetime of this reference `'1` + | `x` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr new file mode 100644 index 000000000..7f232e4a7 --- /dev/null +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -0,0 +1,14 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/issue-78262.rs:12:26 + | +LL | let f = |x: &dyn TT| x.func(); + | - - ^^^^^^^^ + | | | | + | | | `x` escapes the closure body here + | | | argument requires that `'1` must outlive `'static` + | | let's call the lifetime of this reference `'1` + | `x` is a reference that is only valid in the closure body + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/issue-78262.rs b/tests/ui/regions/issue-78262.rs new file mode 100644 index 000000000..642dbd7f8 --- /dev/null +++ b/tests/ui/regions/issue-78262.rs @@ -0,0 +1,15 @@ +// revisions: base polonius +// ignore-compare-mode-polonius +// [polonius] compile-flags: -Z polonius + +trait TT {} + +impl dyn TT { + fn func(&self) {} +} + +fn main() { + let f = |x: &dyn TT| x.func(); + //[base]~^ ERROR: borrowed data escapes outside of closure + //[polonius]~^^ ERROR: borrowed data escapes outside of closure +} diff --git a/tests/ui/regions/outlives-with-missing.rs b/tests/ui/regions/outlives-with-missing.rs new file mode 100644 index 000000000..29d89718b --- /dev/null +++ b/tests/ui/regions/outlives-with-missing.rs @@ -0,0 +1,16 @@ +trait HandlerFamily { + type Target; +} + +struct HandlerWrapper(H); + +impl HandlerWrapper { + pub fn set_handler(&self, handler: &H::Target) + where + T: Send + Sync + 'static, + //~^ ERROR cannot find type `T` in this scope + { + } +} + +fn main() {} diff --git a/tests/ui/regions/outlives-with-missing.stderr b/tests/ui/regions/outlives-with-missing.stderr new file mode 100644 index 000000000..e204c9187 --- /dev/null +++ b/tests/ui/regions/outlives-with-missing.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/outlives-with-missing.rs:10:9 + | +LL | impl HandlerWrapper { + | - similarly named type parameter `H` defined here +... +LL | T: Send + Sync + 'static, + | ^ help: a type parameter with a similar name exists: `H` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/regions/owned-implies-static.rs b/tests/ui/regions/owned-implies-static.rs new file mode 100644 index 000000000..2efa8cc02 --- /dev/null +++ b/tests/ui/regions/owned-implies-static.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f(_x: T) {} + +pub fn main() { + f(Box::new(5)); +} diff --git a/tests/ui/regions/rcvr-borrowed-to-region.rs b/tests/ui/regions/rcvr-borrowed-to-region.rs new file mode 100644 index 000000000..7f32b8b91 --- /dev/null +++ b/tests/ui/regions/rcvr-borrowed-to-region.rs @@ -0,0 +1,28 @@ +// run-pass + +#![allow(non_camel_case_types)] + +trait get { + fn get(self) -> isize; +} + +// Note: impl on a slice; we're checking that the pointers below +// correctly get borrowed to `&`. (similar to impling for `isize`, with +// `&self` instead of `self`.) +impl<'a> get for &'a isize { + fn get(self) -> isize { + return *self; + } +} + +pub fn main() { + let x: Box<_> = 6.into(); + let y = x.get(); + println!("y={}", y); + assert_eq!(y, 6); + + let x = &6; + let y = x.get(); + println!("y={}", y); + assert_eq!(y, 6); +} diff --git a/tests/ui/regions/region-borrow-params-issue-29793-big.rs b/tests/ui/regions/region-borrow-params-issue-29793-big.rs new file mode 100644 index 000000000..83b1a6eab --- /dev/null +++ b/tests/ui/regions/region-borrow-params-issue-29793-big.rs @@ -0,0 +1,74 @@ +// Issue #29793, big regression test: do not let borrows of +// parameters to ever be returned (expanded with exploration of +// variations). +// +// This is the version of the test that actually exposed unsound +// behavior (because the improperly accepted closure was actually +// able to be invoked). + +struct WrapA(Option); + +impl WrapA { + fn new() -> WrapA { + WrapA(None) + } + fn set(mut self, f: F) -> Self { + self.0 = Some(f); + self + } +} + +struct WrapB(Option); + +impl WrapB { + fn new() -> WrapB { + WrapB(None) + } + fn set(mut self, f: F) -> Self { + self.0 = Some(f); + self + } +} + +trait DoStuff : Sized { + fn handle(self); +} + +impl DoStuff for WrapA + where F: FnMut(usize, usize) -> T, T: DoStuff { + fn handle(mut self) { + if let Some(ref mut f) = self.0 { + let x = f(1, 2); + let _foo = [0usize; 16]; + x.handle(); + } + } + } + +impl DoStuff for WrapB where F: FnMut(bool) -> usize { + fn handle(mut self) { + if let Some(ref mut f) = self.0 { + println!("{}", f(true)); + } + } +} + +impl WrapA + where F: FnMut(usize, usize) -> T, T: DoStuff { + fn handle_ref(&mut self) { + if let Some(ref mut f) = self.0 { + let x = f(1, 2); + } + } + } + +fn main() { + let mut w = WrapA::new().set(|x: usize, y: usize| { + WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + //~^ ERROR closure may outlive the current function + //~| ERROR closure may outlive the current function + }); + + w.handle(); // This works + // w.handle_ref(); // This doesn't +} diff --git a/tests/ui/regions/region-borrow-params-issue-29793-big.stderr b/tests/ui/regions/region-borrow-params-issue-29793-big.stderr new file mode 100644 index 000000000..561dd64b4 --- /dev/null +++ b/tests/ui/regions/region-borrow-params-issue-29793-big.stderr @@ -0,0 +1,39 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-big.rs:67:26 + | +LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-big.rs:67:9 + | +LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-big.rs:67:26 + | +LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-big.rs:67:9 + | +LL | WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | WrapB::new().set(move |t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`) + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/regions/region-borrow-params-issue-29793-small.rs b/tests/ui/regions/region-borrow-params-issue-29793-small.rs new file mode 100644 index 000000000..5f1c2ed08 --- /dev/null +++ b/tests/ui/regions/region-borrow-params-issue-29793-small.rs @@ -0,0 +1,212 @@ +// Issue #29793, small regression tests: do not let borrows of +// parameters to ever be returned (expanded with exploration of +// variations). + +// CLOSURES + +fn escaping_borrow_of_closure_params_1() { + let g = |x: usize, y:usize| { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + return f; + }; + + // We delberately do not call `g`; this small version of the test, + // after adding such a call, was (properly) rejected even when the + // system still suffered from issue #29793. + + // g(10, 20)(true); +} + +fn escaping_borrow_of_closure_params_2() { + let g = |x: usize, y:usize| { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + f + }; + + // (we don't call `g`; see above) +} + +fn move_of_closure_params() { + let g = |x: usize, y:usize| { + let f = move |t: bool| if t { x } else { y }; + f; + }; + // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) + (g(1,2)); +} + +fn ok_borrow_of_fn_params(a: usize, b:usize) { + let g = |x: usize, y:usize| { + let f = |t: bool| if t { a } else { b }; + return f; + }; + // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) + (g(1,2))(true); +} + +// TOP-LEVEL FN'S + +fn escaping_borrow_of_fn_params_1() { + fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + return Box::new(f); + }; + + // (we don't call `g`; see above) +} + +fn escaping_borrow_of_fn_params_2() { + fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + Box::new(f) + }; + + // (we don't call `g`; see above) +} + +fn move_of_fn_params() { + fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { + let f = move |t: bool| if t { x } else { y }; + return Box::new(f); + }; + // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) + (g(1,2))(true); +} + +// INHERENT METHODS + +fn escaping_borrow_of_method_params_1() { + struct S; + impl S { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + return Box::new(f); + } + } + + // (we don't call `g`; see above) +} + +fn escaping_borrow_of_method_params_2() { + struct S; + impl S { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + Box::new(f) + } + } + // (we don't call `g`; see above) +} + +fn move_of_method_params() { + struct S; + impl S { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = move |t: bool| if t { x } else { y }; + return Box::new(f); + } + } + // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) + (S.g(1,2))(true); +} + +// TRAIT IMPL METHODS + +fn escaping_borrow_of_trait_impl_params_1() { + trait T { fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a>; } + struct S; + impl T for S { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + return Box::new(f); + } + } + + // (we don't call `g`; see above) +} + +fn escaping_borrow_of_trait_impl_params_2() { + trait T { fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a>; } + struct S; + impl T for S { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + Box::new(f) + } + } + // (we don't call `g`; see above) +} + +fn move_of_trait_impl_params() { + trait T { fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a>; } + struct S; + impl T for S { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = move |t: bool| if t { x } else { y }; + return Box::new(f); + } + } + // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) + (S.g(1,2))(true); +} + +// TRAIT DEFAULT METHODS + +fn escaping_borrow_of_trait_default_params_1() { + struct S; + trait T { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + return Box::new(f); + } + } + impl T for S {} + // (we don't call `g`; see above) +} + +fn escaping_borrow_of_trait_default_params_2() { + struct S; + trait T { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + //~^ ERROR E0373 + //~| ERROR E0373 + Box::new(f) + } + } + impl T for S {} + // (we don't call `g`; see above) +} + +fn move_of_trait_default_params() { + struct S; + trait T { + fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { + let f = move |t: bool| if t { x } else { y }; + return Box::new(f); + } + } + impl T for S {} + // (this code is fine, so lets go ahead and ensure rustc accepts call of `g`) + (S.g(1,2))(true); +} + +fn main() { } diff --git a/tests/ui/regions/region-borrow-params-issue-29793-small.stderr b/tests/ui/regions/region-borrow-params-issue-29793-small.stderr new file mode 100644 index 000000000..e446f2a00 --- /dev/null +++ b/tests/ui/regions/region-borrow-params-issue-29793-small.stderr @@ -0,0 +1,363 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:9:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:12:16 + | +LL | return f; + | ^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:9:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:12:16 + | +LL | return f; + | ^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:24:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:27:9 + | +LL | f + | ^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:24:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:27:9 + | +LL | f + | ^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:55:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:58:16 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:55:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:58:16 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:66:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:69:9 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:66:17 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:69:9 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:90:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:93:20 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:90:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:93:20 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:104:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:107:13 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:104:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:107:13 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:132:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:135:20 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:132:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:135:20 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:147:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:150:13 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:147:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:150:13 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:175:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:178:20 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:175:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:178:20 + | +LL | return Box::new(f); + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:189:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:192:13 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `y`, which is owned by the current function + --> $DIR/region-borrow-params-issue-29793-small.rs:189:21 + | +LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ^^^^^^^^^ - `y` is borrowed here + | | + | may outlive borrowed value `y` + | +note: closure is returned here + --> $DIR/region-borrow-params-issue-29793-small.rs:192:13 + | +LL | Box::new(f) + | ^^^^^^^^^^^ +help: to force the closure to take ownership of `y` (and any other referenced variables), use the `move` keyword + | +LL | let f = move |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) + | ++++ + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/regions/region-bound-extra-bound-in-inherent-impl.rs b/tests/ui/regions/region-bound-extra-bound-in-inherent-impl.rs new file mode 100644 index 000000000..72d82da45 --- /dev/null +++ b/tests/ui/regions/region-bound-extra-bound-in-inherent-impl.rs @@ -0,0 +1,16 @@ +// Test related to #22779. In this case, the impl is an inherent impl, +// so it doesn't have to match any trait, so no error results. + +// check-pass +#![allow(dead_code)] + +struct MySlice<'a, T:'a>(&'a mut [T]); + +impl<'a, T> MySlice<'a, T> { + fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { + &mut self.0[..] + } +} + + +fn main() { } diff --git a/tests/ui/regions/region-bound-on-closure-outlives-call.rs b/tests/ui/regions/region-bound-on-closure-outlives-call.rs new file mode 100644 index 000000000..1311d5121 --- /dev/null +++ b/tests/ui/regions/region-bound-on-closure-outlives-call.rs @@ -0,0 +1,6 @@ +fn call_rec(mut f: F) -> usize where F: FnMut(usize) -> usize { + //~^ WARN function cannot return without recursing + (|x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f` +} + +fn main() {} diff --git a/tests/ui/regions/region-bound-on-closure-outlives-call.stderr b/tests/ui/regions/region-bound-on-closure-outlives-call.stderr new file mode 100644 index 000000000..ea43dde11 --- /dev/null +++ b/tests/ui/regions/region-bound-on-closure-outlives-call.stderr @@ -0,0 +1,24 @@ +warning: function cannot return without recursing + --> $DIR/region-bound-on-closure-outlives-call.rs:1:1 + | +LL | fn call_rec(mut f: F) -> usize where F: FnMut(usize) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | (|x| f(x))(call_rec(f)) + | ----------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0505]: cannot move out of `f` because it is borrowed + --> $DIR/region-bound-on-closure-outlives-call.rs:3:25 + | +LL | (|x| f(x))(call_rec(f)) + | --- - ^ move out of `f` occurs here + | | | + | | borrow occurs due to use in closure + | borrow of `f` occurs here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs b/tests/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs new file mode 100644 index 000000000..68056370c --- /dev/null +++ b/tests/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs @@ -0,0 +1,17 @@ +// Test related to #22779, but where the `'a:'b` relation +// appears in the trait too. No error here. + +// check-pass + +trait Tr<'a, T> { + fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b; +} + +impl<'a, T> Tr<'a, T> for &'a mut [T] { + fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { + &mut self[..] + } +} + + +fn main() { } diff --git a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.rs b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.rs new file mode 100644 index 000000000..40d2b740b --- /dev/null +++ b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.rs @@ -0,0 +1,36 @@ +// Test related to when a region bound is required to be specified. + +trait IsStatic : 'static { } +trait IsSend : Send { } +trait Is<'a> : 'a { } +trait Is2<'a> : 'a { } +trait SomeTrait { } + +// Bounds on object types: + +struct Foo<'a,'b,'c> { //~ ERROR parameter `'c` is never used + // All of these are ok, because we can derive exactly one bound: + a: Box, + b: Box>, + c: Box>, + d: Box, + e: Box+Send>, // we can derive two bounds, but one is 'static, so ok + f: Box, // OK, defaults to 'static due to RFC 599. + g: Box, + + z: Box+'b+'c>, + //~^ ERROR only a single explicit lifetime bound is permitted + //~| ERROR lifetime bound not satisfied +} + +fn test< + 'a, + 'b, + A:IsStatic, + B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type. + C:'b+Is<'a>+Is2<'b>, + D:Is<'a>+Is2<'static>, + E:'a+'b // OK in a parameter, but not an object type. +>() { } + +fn main() { } diff --git a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr new file mode 100644 index 000000000..2ec2ca49b --- /dev/null +++ b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -0,0 +1,35 @@ +error[E0226]: only a single explicit lifetime bound is permitted + --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:26 + | +LL | z: Box+'b+'c>, + | ^^ + +error[E0478]: lifetime bound not satisfied + --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:8 + | +LL | z: Box+'b+'c>, + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'b` as defined here + --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15 + | +LL | struct Foo<'a,'b,'c> { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined here + --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12 + | +LL | struct Foo<'a,'b,'c> { + | ^^ + +error[E0392]: parameter `'c` is never used + --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18 + | +LL | struct Foo<'a,'b,'c> { + | ^^ unused parameter + | + = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0226, E0392, E0478. +For more information about an error, try `rustc --explain E0226`. diff --git a/tests/ui/regions/region-invariant-static-error-reporting.rs b/tests/ui/regions/region-invariant-static-error-reporting.rs new file mode 100644 index 000000000..c8288b592 --- /dev/null +++ b/tests/ui/regions/region-invariant-static-error-reporting.rs @@ -0,0 +1,21 @@ +// This test checks that the error messages you get for this example +// at least mention `'a` and `'static`. The precise messages can drift +// over time, but this test used to exhibit some pretty bogus messages +// that were not remotely helpful. + +// error-pattern:argument requires that `'a` must outlive `'static` + +struct Invariant<'a>(Option<&'a mut &'a mut ()>); + +fn mk_static() -> Invariant<'static> { Invariant(None) } + +fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { + let bad = if x.is_some() { + x.unwrap() //~ ERROR borrowed data escapes outside of function [E0521] + } else { + mk_static() + }; + f(bad); +} + +fn main() {} diff --git a/tests/ui/regions/region-invariant-static-error-reporting.stderr b/tests/ui/regions/region-invariant-static-error-reporting.stderr new file mode 100644 index 000000000..2ad39b000 --- /dev/null +++ b/tests/ui/regions/region-invariant-static-error-reporting.stderr @@ -0,0 +1,21 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/region-invariant-static-error-reporting.rs:14:9 + | +LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | let bad = if x.is_some() { +LL | x.unwrap() + | ^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs new file mode 100644 index 000000000..d364c4677 --- /dev/null +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs @@ -0,0 +1,30 @@ +fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a { + // Note: this is legal because of the `'b:'a` declaration. + *x = *y; +} + +fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + // Illegal now because there is no `'b:'a` declaration. + *x = *y; +} + +fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + // Here we try to call `foo` but do not know that `'a` and `'b` are + // related as required. + a(x, y); +} + +fn d() { + // 'a and 'b are early bound in the function `a` because they appear + // inconstraints: + let _: fn(&mut &isize, &mut &isize) = a; + //~^ ERROR mismatched types [E0308] +} + +fn e() { + // 'a and 'b are late bound in the function `b` because there are + // no constraints: + let _: fn(&mut &isize, &mut &isize) = b; +} + +fn main() { } diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr new file mode 100644 index 000000000..3b62c7b61 --- /dev/null +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 + | +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` + found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs new file mode 100644 index 000000000..60dafdd52 --- /dev/null +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -0,0 +1,32 @@ +fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where 'b: 'a + 'c { + // Note: this is legal because of the `'b:'a` declaration. + *x = *y; + *z = *y; +} + +fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + // Illegal now because there is no `'b:'a` declaration. + *x = *y; + *z = *y; +} + +fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + // Here we try to call `foo` but do not know that `'a` and `'b` are + // related as required. + a(x, y, z); +} + +fn d() { + // 'a and 'b are early bound in the function `a` because they appear + // inconstraints: + let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + //~^ ERROR E0308 +} + +fn e() { + // 'a and 'b are late bound in the function `b` because there are + // no constraints: + let _: fn(&mut &isize, &mut &isize, &mut &isize) = b; +} + +fn main() { } diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr new file mode 100644 index 000000000..8a18a234b --- /dev/null +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)` + found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-object-lifetime-1.rs b/tests/ui/regions/region-object-lifetime-1.rs new file mode 100644 index 000000000..ddf3be690 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-1.rs @@ -0,0 +1,18 @@ +// Various tests related to testing how region inference works +// with respect to the object receivers. + +// check-pass +#![allow(warnings)] + +trait Foo { + fn borrowed<'a>(&'a self) -> &'a (); +} + +// Here the receiver and return value all have the same lifetime, +// so no error results. +fn borrowed_receiver_same_lifetime<'a>(x: &'a Foo) -> &'a () { + x.borrowed() +} + + +fn main() {} diff --git a/tests/ui/regions/region-object-lifetime-2.rs b/tests/ui/regions/region-object-lifetime-2.rs new file mode 100644 index 000000000..cfdb8fefe --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-2.rs @@ -0,0 +1,14 @@ +// Various tests related to testing how region inference works +// with respect to the object receivers. + +trait Foo { + fn borrowed<'a>(&'a self) -> &'a (); +} + +// Borrowed receiver but two distinct lifetimes, we get an error. +fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { + x.borrowed() + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/region-object-lifetime-2.stderr b/tests/ui/regions/region-object-lifetime-2.stderr new file mode 100644 index 000000000..d95289f3f --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-2.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-2.rs:10:5 + | +LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x.borrowed() + | ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/region-object-lifetime-3.rs b/tests/ui/regions/region-object-lifetime-3.rs new file mode 100644 index 000000000..0536fa2a2 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-3.rs @@ -0,0 +1,18 @@ +// Various tests related to testing how region inference works +// with respect to the object receivers. + +// check-pass +#![allow(warnings)] + +trait Foo { + fn borrowed<'a>(&'a self) -> &'a (); +} + +// Borrowed receiver with two distinct lifetimes, but we know that +// 'b:'a, hence &'a () is permitted. +fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () { + x.borrowed() +} + + +fn main() {} diff --git a/tests/ui/regions/region-object-lifetime-4.rs b/tests/ui/regions/region-object-lifetime-4.rs new file mode 100644 index 000000000..8f42df831 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-4.rs @@ -0,0 +1,16 @@ +// Various tests related to testing how region inference works +// with respect to the object receivers. + +trait Foo { + fn borrowed<'a>(&'a self) -> &'a (); +} + +// Here we have two distinct lifetimes, but we try to return a pointer +// with the longer lifetime when (from the signature) we only know +// that it lives as long as the shorter lifetime. Therefore, error. +fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { + x.borrowed() + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/region-object-lifetime-4.stderr b/tests/ui/regions/region-object-lifetime-4.stderr new file mode 100644 index 000000000..fda66a241 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-4.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-4.rs:12:5 + | +LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x.borrowed() + | ^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/region-object-lifetime-5.rs b/tests/ui/regions/region-object-lifetime-5.rs new file mode 100644 index 000000000..ad3593671 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-5.rs @@ -0,0 +1,14 @@ +// Various tests related to testing how region inference works +// with respect to the object receivers. + +trait Foo { + fn borrowed<'a>(&'a self) -> &'a (); +} + +// Here, the object is bounded by an anonymous lifetime and returned +// as `&'static`, so you get an error. +fn owned_receiver(x: Box) -> &'static () { + x.borrowed() //~ ERROR cannot return reference to local data `*x` +} + +fn main() {} diff --git a/tests/ui/regions/region-object-lifetime-5.stderr b/tests/ui/regions/region-object-lifetime-5.stderr new file mode 100644 index 000000000..b82b58c7a --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-5.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to local data `*x` + --> $DIR/region-object-lifetime-5.rs:11:5 + | +LL | x.borrowed() + | ^^^^^^^^^^^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/region-object-lifetime-in-coercion.rs b/tests/ui/regions/region-object-lifetime-in-coercion.rs new file mode 100644 index 000000000..95708de04 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-in-coercion.rs @@ -0,0 +1,34 @@ +// Test that attempts to implicitly coerce a value into an +// object respect the lifetime bound on the object type. + +trait Foo {} +impl<'a> Foo for &'a [u8] {} + +fn a(v: &[u8]) -> Box { + let x: Box = Box::new(v); + //~^ ERROR lifetime may not live long enough + x +} + +fn b(v: &[u8]) -> Box { + Box::new(v) + //~^ ERROR lifetime may not live long enough +} + +fn c(v: &[u8]) -> Box { + // same as previous case due to RFC 599 + + Box::new(v) + //~^ ERROR lifetime may not live long enough +} + +fn d<'a,'b>(v: &'a [u8]) -> Box { + Box::new(v) + //~^ ERROR lifetime may not live long enough +} + +fn e<'a:'b,'b>(v: &'a [u8]) -> Box { + Box::new(v) // OK, thanks to 'a:'b +} + +fn main() { } diff --git a/tests/ui/regions/region-object-lifetime-in-coercion.stderr b/tests/ui/regions/region-object-lifetime-in-coercion.stderr new file mode 100644 index 000000000..b5bb08c73 --- /dev/null +++ b/tests/ui/regions/region-object-lifetime-in-coercion.stderr @@ -0,0 +1,62 @@ +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:8:12 + | +LL | fn a(v: &[u8]) -> Box { + | - let's call the lifetime of this reference `'1` +LL | let x: Box = Box::new(v); + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` + | +LL | fn a(v: &[u8]) -> Box { + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn a(v: &'static [u8]) -> Box { + | ~~~~~~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:14:5 + | +LL | fn b(v: &[u8]) -> Box { + | - let's call the lifetime of this reference `'1` +LL | Box::new(v) + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` + | +LL | fn b(v: &[u8]) -> Box { + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn b(v: &'static [u8]) -> Box { + | ~~~~~~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:21:5 + | +LL | fn c(v: &[u8]) -> Box { + | - let's call the lifetime of this reference `'1` +... +LL | Box::new(v) + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound + | +LL | fn c(v: &[u8]) -> Box { + | ++++ + +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:26:5 + | +LL | fn d<'a,'b>(v: &'a [u8]) -> Box { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | Box::new(v) + | ^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/regions/regions-addr-of-arg.rs b/tests/ui/regions/regions-addr-of-arg.rs new file mode 100644 index 000000000..1805141c4 --- /dev/null +++ b/tests/ui/regions/regions-addr-of-arg.rs @@ -0,0 +1,17 @@ +// Check that taking the address of an argument yields a lifetime +// bounded by the current function call. + +fn foo(a: isize) { + let _p: &'static isize = &a; //~ ERROR `a` does not live long enough +} + +fn bar(a: isize) { + let _q: &isize = &a; +} + +fn zed<'a>(a: isize) -> &'a isize { + &a //~ ERROR cannot return reference to function parameter `a` +} + +fn main() { +} diff --git a/tests/ui/regions/regions-addr-of-arg.stderr b/tests/ui/regions/regions-addr-of-arg.stderr new file mode 100644 index 000000000..e77289287 --- /dev/null +++ b/tests/ui/regions/regions-addr-of-arg.stderr @@ -0,0 +1,20 @@ +error[E0597]: `a` does not live long enough + --> $DIR/regions-addr-of-arg.rs:5:30 + | +LL | let _p: &'static isize = &a; + | -------------- ^^ borrowed value does not live long enough + | | + | type annotation requires that `a` is borrowed for `'static` +LL | } + | - `a` dropped here while still borrowed + +error[E0515]: cannot return reference to function parameter `a` + --> $DIR/regions-addr-of-arg.rs:13:5 + | +LL | &a + | ^^ returns a reference to data owned by the current function + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0515, E0597. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-addr-of-interior-of-unique-box.rs b/tests/ui/regions/regions-addr-of-interior-of-unique-box.rs new file mode 100644 index 000000000..4221ebfdf --- /dev/null +++ b/tests/ui/regions/regions-addr-of-interior-of-unique-box.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +struct Point { + x: isize, + y: isize +} + +struct Character { + pos: Box, +} + +fn get_x(x: &Character) -> &isize { + // interesting case because the scope of this + // borrow of the unique pointer is in fact + // larger than the fn itself + return &x.pos.x; +} + +pub fn main() { +} diff --git a/tests/ui/regions/regions-addr-of-ret.rs b/tests/ui/regions/regions-addr-of-ret.rs new file mode 100644 index 000000000..e5dcd6db0 --- /dev/null +++ b/tests/ui/regions/regions-addr-of-ret.rs @@ -0,0 +1,9 @@ +// run-pass +fn f(x: &isize) -> &isize { + return &*x; +} + +pub fn main() { + let three = &3; + println!("{}", *f(three)); +} diff --git a/tests/ui/regions/regions-addr-of-self.rs b/tests/ui/regions/regions-addr-of-self.rs new file mode 100644 index 000000000..23647182f --- /dev/null +++ b/tests/ui/regions/regions-addr-of-self.rs @@ -0,0 +1,28 @@ +struct Dog { + cats_chased: usize, +} + +impl Dog { + pub fn chase_cat(&mut self) { + let p: &'static mut usize = &mut self.cats_chased; + //~^ ERROR lifetime may not live long enough + *p += 1; + } + + pub fn chase_cat_2(&mut self) { + let p: &mut usize = &mut self.cats_chased; + *p += 1; + } +} + +fn dog() -> Dog { + Dog { + cats_chased: 0 + } +} + +fn main() { + let mut d = dog(); + d.chase_cat(); + println!("cats_chased: {}", d.cats_chased); +} diff --git a/tests/ui/regions/regions-addr-of-self.stderr b/tests/ui/regions/regions-addr-of-self.stderr new file mode 100644 index 000000000..3d7aac74b --- /dev/null +++ b/tests/ui/regions/regions-addr-of-self.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/regions-addr-of-self.rs:7:16 + | +LL | pub fn chase_cat(&mut self) { + | - let's call the lifetime of this reference `'1` +LL | let p: &'static mut usize = &mut self.cats_chased; + | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-addr-of-upvar-self.rs b/tests/ui/regions/regions-addr-of-upvar-self.rs new file mode 100644 index 000000000..171eca32e --- /dev/null +++ b/tests/ui/regions/regions-addr-of-upvar-self.rs @@ -0,0 +1,18 @@ +struct Dog { + food: usize, +} + +impl Dog { + pub fn chase_cat(&mut self) { + let _f = || { + let p: &'static mut usize = &mut self.food; + //~^ ERROR lifetime may not live long enough + //~^^ ERROR lifetime may not live long enough + //~^^^ ERROR E0597 + *p = 3; + }; + } +} + +fn main() { +} diff --git a/tests/ui/regions/regions-addr-of-upvar-self.stderr b/tests/ui/regions/regions-addr-of-upvar-self.stderr new file mode 100644 index 000000000..c16a6f858 --- /dev/null +++ b/tests/ui/regions/regions-addr-of-upvar-self.stderr @@ -0,0 +1,35 @@ +error: lifetime may not live long enough + --> $DIR/regions-addr-of-upvar-self.rs:8:20 + | +LL | let _f = || { + | -- lifetime `'1` represents this closure's body +LL | let p: &'static mut usize = &mut self.food; + | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure + +error: lifetime may not live long enough + --> $DIR/regions-addr-of-upvar-self.rs:8:20 + | +LL | pub fn chase_cat(&mut self) { + | - let's call the lifetime of this reference `'1` +LL | let _f = || { +LL | let p: &'static mut usize = &mut self.food; + | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` + +error[E0597]: `self` does not live long enough + --> $DIR/regions-addr-of-upvar-self.rs:8:46 + | +LL | let _f = || { + | -- value captured here +LL | let p: &'static mut usize = &mut self.food; + | ------------------ ^^^^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `self` is borrowed for `'static` +... +LL | } + | - `self` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-adjusted-lvalue-op.rs b/tests/ui/regions/regions-adjusted-lvalue-op.rs new file mode 100644 index 000000000..5aa5a3ecb --- /dev/null +++ b/tests/ui/regions/regions-adjusted-lvalue-op.rs @@ -0,0 +1,16 @@ +// check that we link regions in mutable place ops correctly - issue #41774 + +struct Data(i32); + +trait OhNo { + fn oh_no(&mut self, other: &Vec) { loop {} } +} + +impl OhNo for Data {} +impl OhNo for [Data] {} + +fn main() { + let mut v = vec![Data(0)]; + v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because + (*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because +} diff --git a/tests/ui/regions/regions-adjusted-lvalue-op.stderr b/tests/ui/regions/regions-adjusted-lvalue-op.stderr new file mode 100644 index 000000000..2c5563444 --- /dev/null +++ b/tests/ui/regions/regions-adjusted-lvalue-op.stderr @@ -0,0 +1,21 @@ +error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable + --> $DIR/regions-adjusted-lvalue-op.rs:14:16 + | +LL | v[0].oh_no(&v); + | - ----- ^^ immutable borrow occurs here + | | | + | | mutable borrow later used by call + | mutable borrow occurs here + +error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable + --> $DIR/regions-adjusted-lvalue-op.rs:15:16 + | +LL | (*v).oh_no(&v); + | - ----- ^^ immutable borrow occurs here + | | | + | | mutable borrow later used by call + | mutable borrow occurs here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs new file mode 100644 index 000000000..eb6e66818 --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs @@ -0,0 +1,41 @@ +// Test that we are imposing the requirement that every associated +// type of a bound that appears in the where clause on a struct must +// outlive the location in which the type appears, even when the +// associted type is in a supertype. Issue #22246. + +#![allow(dead_code)] + +pub trait TheTrait { + type TheAssocType; +} + +pub trait TheSubTrait : TheTrait { +} + +pub struct TheType<'b> { + m: [fn(&'b()); 0] +} + +impl<'b> TheTrait for TheType<'b> { + type TheAssocType = &'b (); +} + +impl<'b> TheSubTrait for TheType<'b> { +} + +pub struct WithAssoc { + m: [T; 0] +} + +fn with_assoc<'a,'b>() { + // For this type to be valid, the rules require that all + // associated types of traits that appear in `WithAssoc` must + // outlive 'a. In this case, that means TheType<'b>::TheAssocType, + // which is &'b (), must outlive 'a. + + let _: &'a WithAssoc> = loop { }; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr b/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr new file mode 100644 index 000000000..2a2625203 --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:36:12 + | +LL | fn with_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'a WithAssoc> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs b/tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs new file mode 100644 index 000000000..575dfafe1 --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -0,0 +1,24 @@ +// Test that the compiler checks that arbitrary region bounds declared +// in the trait must be satisfied on the impl. Issue #20890. + +trait Foo<'a> { + type Value: 'a; + fn dummy(&'a self) {} +} + +impl<'a> Foo<'a> for &'a i16 { + // OK. + type Value = &'a i32; +} + +impl<'a> Foo<'static> for &'a i32 { + type Value = &'a i32; + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime +} + +impl<'a, 'b> Foo<'b> for &'a i64 { + type Value = &'a i32; + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime +} + +fn main() {} diff --git a/tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr new file mode 100644 index 000000000..ac6154139 --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -0,0 +1,27 @@ +error[E0477]: the type `&'a i32` does not fulfill the required lifetime + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:15:18 + | +LL | type Value = &'a i32; + | ^^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:5:17 + | +LL | type Value: 'a; + | ^^ + +error[E0477]: the type `&'a i32` does not fulfill the required lifetime + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:20:18 + | +LL | type Value = &'a i32; + | ^^^^^^^ + | +note: type must outlive the lifetime `'b` as defined here as required by this binding + --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:10 + | +LL | impl<'a, 'b> Foo<'b> for &'a i64 { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/regions/regions-assoc-type-region-bound.rs b/tests/ui/regions/regions-assoc-type-region-bound.rs new file mode 100644 index 000000000..cbb7d1726 --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-region-bound.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +// Test that the compiler considers the 'a bound declared in the +// trait. Issue #20890. + +// pretty-expanded FIXME #23616 + +trait Foo<'a> { + type Value: 'a; + + fn get(&self) -> &'a Self::Value; +} + +fn takes_foo<'a,F: Foo<'a>>(f: &'a F) { + // This call would be illegal, because it results in &'a F::Value, + // and the only way we know that `F::Value : 'a` is because of the + // trait declaration. + + f.get(); +} + +fn main() { } diff --git a/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs b/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs new file mode 100644 index 000000000..00100e0e9 --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -0,0 +1,19 @@ +// Test that the compiler checks that the 'static bound declared in +// the trait must be satisfied on the impl. Issue #20890. + +trait Foo { + type Value: 'static; + fn dummy(&self) {} +} + +impl<'a> Foo for &'a i32 { + type Value = &'a i32; + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime +} + +impl<'a> Foo for i32 { + // OK. + type Value = i32; +} + +fn main() {} diff --git a/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr new file mode 100644 index 000000000..a96f5612f --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -0,0 +1,15 @@ +error[E0477]: the type `&'a i32` does not fulfill the required lifetime + --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:10:18 + | +LL | type Value = &'a i32; + | ^^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:5:17 + | +LL | type Value: 'static; + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/regions/regions-assoc-type-static-bound.rs b/tests/ui/regions/regions-assoc-type-static-bound.rs new file mode 100644 index 000000000..1458787ea --- /dev/null +++ b/tests/ui/regions/regions-assoc-type-static-bound.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +// Test that the compiler considers the 'static bound declared in the +// trait. Issue #20890. + +// pretty-expanded FIXME #23616 + +trait Foo { + type Value: 'static; + fn dummy(&self) { } +} + +fn require_static() {} + +fn takes_foo() { + require_static::() +} + +fn main() { } diff --git a/tests/ui/regions/regions-borrow-at.rs b/tests/ui/regions/regions-borrow-at.rs new file mode 100644 index 000000000..152abe109 --- /dev/null +++ b/tests/ui/regions/regions-borrow-at.rs @@ -0,0 +1,12 @@ +// run-pass + +fn foo(x: &usize) -> usize { + *x +} + +pub fn main() { + let p: Box<_> = Box::new(22); + let r = foo(&*p); + println!("r={}", r); + assert_eq!(r, 22); +} diff --git a/tests/ui/regions/regions-borrow-evec-fixed.rs b/tests/ui/regions/regions-borrow-evec-fixed.rs new file mode 100644 index 000000000..ed828312b --- /dev/null +++ b/tests/ui/regions/regions-borrow-evec-fixed.rs @@ -0,0 +1,10 @@ +// run-pass + +fn foo(x: &[isize]) -> isize { + x[0] +} + +pub fn main() { + let p = &[1,2,3,4,5]; + assert_eq!(foo(p), 1); +} diff --git a/tests/ui/regions/regions-borrow-evec-uniq.rs b/tests/ui/regions/regions-borrow-evec-uniq.rs new file mode 100644 index 000000000..bbf7ba79e --- /dev/null +++ b/tests/ui/regions/regions-borrow-evec-uniq.rs @@ -0,0 +1,16 @@ +// run-pass + + +fn foo(x: &[isize]) -> isize { + x[0] +} + +pub fn main() { + let p = vec![1,2,3,4,5]; + let r = foo(&p); + assert_eq!(r, 1); + + let p = vec![5,4,3,2,1]; + let r = foo(&p); + assert_eq!(r, 5); +} diff --git a/tests/ui/regions/regions-borrow-uniq.rs b/tests/ui/regions/regions-borrow-uniq.rs new file mode 100644 index 000000000..adc6b1939 --- /dev/null +++ b/tests/ui/regions/regions-borrow-uniq.rs @@ -0,0 +1,11 @@ +// run-pass + +fn foo(x: &usize) -> usize { + *x +} + +pub fn main() { + let p: Box<_> = Box::new(3); + let r = foo(&*p); + assert_eq!(r, 3); +} diff --git a/tests/ui/regions/regions-bot.rs b/tests/ui/regions/regions-bot.rs new file mode 100644 index 000000000..580162936 --- /dev/null +++ b/tests/ui/regions/regions-bot.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// A very limited test of the "bottom" region + + +fn produce_static() -> &'static T { panic!(); } + +fn foo(_x: &T) -> &usize { produce_static() } + +pub fn main() { +} diff --git a/tests/ui/regions/regions-bound-lists-feature-gate-2.rs b/tests/ui/regions/regions-bound-lists-feature-gate-2.rs new file mode 100644 index 000000000..2c7503799 --- /dev/null +++ b/tests/ui/regions/regions-bound-lists-feature-gate-2.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(stable_features)] + +#![feature(issue_5723_bootstrap)] + +trait Foo { + fn dummy(&self) { } +} + +fn foo<'a, 'b, 'c:'a+'b, 'd>() { +} + +pub fn main() { } diff --git a/tests/ui/regions/regions-bound-lists-feature-gate.rs b/tests/ui/regions/regions-bound-lists-feature-gate.rs new file mode 100644 index 000000000..3815498f8 --- /dev/null +++ b/tests/ui/regions/regions-bound-lists-feature-gate.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(stable_features)] + +#![feature(issue_5723_bootstrap)] + +trait Foo { + fn dummy(&self) { } +} + +fn foo<'a>(x: Box) { +} + +fn bar<'a, T: 'a>() { +} + +pub fn main() { } diff --git a/tests/ui/regions/regions-bounded-by-trait-requiring-static.rs b/tests/ui/regions/regions-bounded-by-trait-requiring-static.rs new file mode 100644 index 000000000..7d02a4619 --- /dev/null +++ b/tests/ui/regions/regions-bounded-by-trait-requiring-static.rs @@ -0,0 +1,69 @@ +// Test which of the builtin types are considered sendable. The tests +// in this file all test region bound and lifetime violations that are +// detected during type check. + +trait Dummy : 'static { } +fn assert_send() { } + +// lifetime pointers with 'static lifetime are ok + +fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) { + assert_send::<&'static isize>(); + assert_send::<&'static str>(); + assert_send::<&'static [isize]>(); + + // whether or not they are mutable + assert_send::<&'static mut isize>(); +} + +// otherwise lifetime pointers are not ok + +fn param_not_ok<'a>(x: &'a isize) { + assert_send::<&'a isize>(); + //~^ ERROR lifetime may not live long enough +} + +fn param_not_ok1<'a>(_: &'a isize) { + assert_send::<&'a str>(); + //~^ ERROR lifetime may not live long enough +} + +fn param_not_ok2<'a>(_: &'a isize) { + assert_send::<&'a [isize]>(); + //~^ ERROR lifetime may not live long enough +} + +// boxes are ok + +fn box_ok() { + assert_send::>(); + assert_send::(); + assert_send::>(); +} + +// but not if they own a bad thing + +fn box_with_region_not_ok<'a>() { + assert_send::>(); + //~^ ERROR lifetime may not live long enough +} + +// raw pointers are ok unless they point at unsendable things + +fn unsafe_ok1<'a>(_: &'a isize) { + assert_send::<*const isize>(); + assert_send::<*mut isize>(); +} + +fn unsafe_ok2<'a>(_: &'a isize) { + assert_send::<*const &'a isize>(); + //~^ ERROR lifetime may not live long enough +} + +fn unsafe_ok3<'a>(_: &'a isize) { + assert_send::<*mut &'a isize>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-bounded-by-trait-requiring-static.stderr b/tests/ui/regions/regions-bounded-by-trait-requiring-static.stderr new file mode 100644 index 000000000..eea68cc8f --- /dev/null +++ b/tests/ui/regions/regions-bounded-by-trait-requiring-static.stderr @@ -0,0 +1,50 @@ +error: lifetime may not live long enough + --> $DIR/regions-bounded-by-trait-requiring-static.rs:22:5 + | +LL | fn param_not_ok<'a>(x: &'a isize) { + | -- lifetime `'a` defined here +LL | assert_send::<&'a isize>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/regions-bounded-by-trait-requiring-static.rs:27:5 + | +LL | fn param_not_ok1<'a>(_: &'a isize) { + | -- lifetime `'a` defined here +LL | assert_send::<&'a str>(); + | ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/regions-bounded-by-trait-requiring-static.rs:32:5 + | +LL | fn param_not_ok2<'a>(_: &'a isize) { + | -- lifetime `'a` defined here +LL | assert_send::<&'a [isize]>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/regions-bounded-by-trait-requiring-static.rs:47:5 + | +LL | fn box_with_region_not_ok<'a>() { + | -- lifetime `'a` defined here +LL | assert_send::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/regions-bounded-by-trait-requiring-static.rs:59:5 + | +LL | fn unsafe_ok2<'a>(_: &'a isize) { + | -- lifetime `'a` defined here +LL | assert_send::<*const &'a isize>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/regions-bounded-by-trait-requiring-static.rs:64:5 + | +LL | fn unsafe_ok3<'a>(_: &'a isize) { + | -- lifetime `'a` defined here +LL | assert_send::<*mut &'a isize>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs b/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs new file mode 100644 index 000000000..c014b2ccf --- /dev/null +++ b/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.rs @@ -0,0 +1,24 @@ +// aux-build:rbmtp_cross_crate_lib.rs + +// Check explicit region bounds on methods in the cross crate case. + +extern crate rbmtp_cross_crate_lib as lib; + +use lib::Inv; +use lib::MaybeOwned; +use lib::IntoMaybeOwned; + +fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) { + // Exercise a code path I found to be buggy. We were not encoding + // the region parameters from the receiver correctly on trait + // methods. + f.into_maybe_owned(); +} + +fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) { + // Here the value provided for 'y is 'y, and hence 'y:'x does not hold. + a.bigger_region(b) + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr b/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr new file mode 100644 index 000000000..6193bf02f --- /dev/null +++ b/tests/ui/regions/regions-bounded-method-type-parameters-cross-crate.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/regions-bounded-method-type-parameters-cross-crate.rs:20:5 + | +LL | fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) { + | -- -- lifetime `'y` defined here + | | + | lifetime `'x` defined here +LL | // Here the value provided for 'y is 'y, and hence 'y:'x does not hold. +LL | a.bigger_region(b) + | ^^^^^^^^^^^^^^^^^^ argument requires that `'y` must outlive `'x` + | + = help: consider adding the following bound: `'y: 'x` + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs b/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs new file mode 100644 index 000000000..5548cb915 --- /dev/null +++ b/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.rs @@ -0,0 +1,29 @@ +// Check that explicit region bounds are allowed on the various +// nominal types (but not on other types) and that they are type +// checked. + +struct Inv<'a> { // invariant w/r/t 'a + x: &'a mut &'a isize +} + +trait Foo<'x> { + fn method<'y:'x>(self, y: Inv<'y>); +} + +fn caller1<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { + // Here the value provided for 'y is 'a, and hence 'a:'a holds. + f.method(a); +} + +fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { + // Here the value provided for 'y is 'b, and hence 'b:'a does not hold. + f.method(b); + //~^ ERROR lifetime may not live long enough +} + +fn caller3<'a,'b:'a,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { + // Here the value provided for 'y is 'b, and hence 'b:'a holds. + f.method(b); +} + +fn main() { } diff --git a/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr b/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr new file mode 100644 index 000000000..0e0086be9 --- /dev/null +++ b/tests/ui/regions/regions-bounded-method-type-parameters-trait-bound.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5 + | +LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold. +LL | f.method(b); + | ^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Inv<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-bounded-method-type-parameters.rs b/tests/ui/regions/regions-bounded-method-type-parameters.rs new file mode 100644 index 000000000..56e750003 --- /dev/null +++ b/tests/ui/regions/regions-bounded-method-type-parameters.rs @@ -0,0 +1,16 @@ +// Check that explicit region bounds are allowed on the various +// nominal types (but not on other types) and that they are type +// checked. + +struct Foo; + +impl Foo { + fn some_method(self) { } +} + +fn caller<'a>(x: &isize) { + Foo.some_method::<&'a isize>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-bounded-method-type-parameters.stderr b/tests/ui/regions/regions-bounded-method-type-parameters.stderr new file mode 100644 index 000000000..b6d7b8aac --- /dev/null +++ b/tests/ui/regions/regions-bounded-method-type-parameters.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/regions-bounded-method-type-parameters.rs:12:9 + | +LL | fn caller<'a>(x: &isize) { + | -- lifetime `'a` defined here +LL | Foo.some_method::<&'a isize>(); + | ^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-bounds.rs b/tests/ui/regions/regions-bounds.rs new file mode 100644 index 000000000..fd4d75ab6 --- /dev/null +++ b/tests/ui/regions/regions-bounds.rs @@ -0,0 +1,18 @@ +// Check that explicit region bounds are allowed on the various +// nominal types (but not on other types) and that they are type +// checked. + +struct TupleStruct<'a>(&'a isize); +struct Struct<'a> { x:&'a isize } + +fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { + return e; + //~^ ERROR lifetime may not live long enough +} + +fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { + return e; + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-bounds.stderr b/tests/ui/regions/regions-bounds.stderr new file mode 100644 index 000000000..430909e54 --- /dev/null +++ b/tests/ui/regions/regions-bounds.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/regions-bounds.rs:9:12 + | +LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | return e; + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/regions-bounds.rs:14:12 + | +LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | return e; + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/regions/regions-close-associated-type-into-object.rs b/tests/ui/regions/regions-close-associated-type-into-object.rs new file mode 100644 index 000000000..428477e24 --- /dev/null +++ b/tests/ui/regions/regions-close-associated-type-into-object.rs @@ -0,0 +1,71 @@ +trait X {} + + + +trait Iter { + type Item: X; + + fn into_item(self) -> Self::Item; + fn as_item(&self) -> &Self::Item; +} + +fn bad1(v: T) -> Box +{ + let item = v.into_item(); + Box::new(item) //~ ERROR associated type `::Item` may not live long enough +} + +fn bad2(v: T) -> Box + where Box : X +{ + let item: Box<_> = Box::new(v.into_item()); + Box::new(item) //~ ERROR associated type `::Item` may not live long enough +} + +fn bad3<'a, T: Iter>(v: T) -> Box +{ + let item = v.into_item(); + Box::new(item) //~ ERROR associated type `::Item` may not live long enough +} + +fn bad4<'a, T: Iter>(v: T) -> Box + where Box : X +{ + let item: Box<_> = Box::new(v.into_item()); + Box::new(item) //~ ERROR associated type `::Item` may not live long enough +} + +fn ok1<'a, T: Iter>(v: T) -> Box + where T::Item : 'a +{ + let item = v.into_item(); + Box::new(item) // OK, T::Item : 'a is declared +} + +fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box + where T::Item : Clone +{ + let item = Clone::clone(w); + Box::new(item) // OK, T::Item : 'a is implied +} + +fn ok3<'a, T: Iter>(v: &'a T) -> Box + where T::Item : Clone + 'a +{ + let item = Clone::clone(v.as_item()); + Box::new(item) // OK, T::Item : 'a was declared +} + +fn meh1<'a, T: Iter>(v: &'a T) -> Box + where T::Item : Clone +{ + // This case is kind of interesting. It's the same as `ok3` but + // without the explicit declaration. This is valid because `T: 'a + // => T::Item: 'a`, and the former we can deduce from our argument + // of type `&'a T`. + + let item = Clone::clone(v.as_item()); + Box::new(item) +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-associated-type-into-object.stderr b/tests/ui/regions/regions-close-associated-type-into-object.stderr new file mode 100644 index 000000000..f7dcaa9d9 --- /dev/null +++ b/tests/ui/regions/regions-close-associated-type-into-object.stderr @@ -0,0 +1,40 @@ +error[E0310]: the associated type `::Item` may not live long enough + --> $DIR/regions-close-associated-type-into-object.rs:15:5 + | +LL | Box::new(item) + | ^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error[E0310]: the associated type `::Item` may not live long enough + --> $DIR/regions-close-associated-type-into-object.rs:22:5 + | +LL | Box::new(item) + | ^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'static`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/regions-close-associated-type-into-object.rs:28:5 + | +LL | Box::new(item) + | ^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'a`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error[E0309]: the associated type `::Item` may not live long enough + --> $DIR/regions-close-associated-type-into-object.rs:35:5 + | +LL | Box::new(item) + | ^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `::Item: 'a`... + = note: ...so that the type `::Item` will meet its required lifetime bounds + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0309, E0310. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-close-object-into-object-1.rs b/tests/ui/regions/regions-close-object-into-object-1.rs new file mode 100644 index 000000000..2dc33d567 --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-1.rs @@ -0,0 +1,15 @@ +#![allow(warnings)] + +trait A { } + +struct B<'a, T:'a>(&'a (A+'a)); + +trait X { } + +impl<'a, T> X for B<'a, T> {} + +fn f<'a, T:'static, U>(v: Box+'static>) -> Box { + Box::new(B(&*v)) as Box //~ ERROR cannot return value referencing local data `*v` +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-object-into-object-1.stderr b/tests/ui/regions/regions-close-object-into-object-1.stderr new file mode 100644 index 000000000..5bfaeb295 --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-1.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local data `*v` + --> $DIR/regions-close-object-into-object-1.rs:12:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-close-object-into-object-2.rs b/tests/ui/regions/regions-close-object-into-object-2.rs new file mode 100644 index 000000000..6960af72c --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-2.rs @@ -0,0 +1,14 @@ +trait A { } + +struct B<'a, T:'a>(&'a (dyn A + 'a)); + +trait X { } +impl<'a, T> X for B<'a, T> {} + +fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + Box::new(B(&*v)) as Box + //~^ ERROR lifetime may not live long enough + //~| ERROR cannot return value referencing local data `*v` [E0515] +} + +fn main() { } diff --git a/tests/ui/regions/regions-close-object-into-object-2.stderr b/tests/ui/regions/regions-close-object-into-object-2.stderr new file mode 100644 index 000000000..aacb5ea4e --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-2.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/regions-close-object-into-object-2.rs:9:5 + | +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | -- lifetime `'a` defined here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` + | +LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn g<'a, T: 'static>(v: Box<(dyn A + 'static)>) -> Box { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0515]: cannot return value referencing local data `*v` + --> $DIR/regions-close-object-into-object-2.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-close-object-into-object-3.rs b/tests/ui/regions/regions-close-object-into-object-3.rs new file mode 100644 index 000000000..78d93b0ec --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-3.rs @@ -0,0 +1,14 @@ +#![allow(warnings)] + +trait A { } + +struct B<'a, T:'a>(&'a (A+'a)); + +trait X { } +impl<'a, T> X for B<'a, T> {} + +fn h<'a, T, U:'static>(v: Box+'static>) -> Box { + Box::new(B(&*v)) as Box //~ ERROR cannot return value referencing local data `*v` +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-object-into-object-3.stderr b/tests/ui/regions/regions-close-object-into-object-3.stderr new file mode 100644 index 000000000..9f92c40e1 --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-3.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local data `*v` + --> $DIR/regions-close-object-into-object-3.rs:11:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-close-object-into-object-4.rs b/tests/ui/regions/regions-close-object-into-object-4.rs new file mode 100644 index 000000000..3bbad9cbf --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-4.rs @@ -0,0 +1,19 @@ +trait A { } + +struct B<'a, T:'a>(&'a (dyn A + 'a)); + +trait X { } +impl<'a, T> X for B<'a, T> {} + +fn i<'a, T, U>(v: Box+'a>) -> Box { + Box::new(B(&*v)) as Box + //~^ ERROR the parameter type `U` may not live long enough [E0310] + //~| ERROR the parameter type `U` may not live long enough [E0310] + //~| ERROR the parameter type `U` may not live long enough [E0310] + //~| ERROR lifetime may not live long enough + //~| ERROR cannot return value referencing local data `*v` [E0515] + //~| ERROR the parameter type `U` may not live long enough [E0310] + +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-object-into-object-4.stderr b/tests/ui/regions/regions-close-object-into-object-4.stderr new file mode 100644 index 000000000..7a9f1ab00 --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-4.stderr @@ -0,0 +1,74 @@ +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { + | +++++++++ + +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { + | +++++++++ + +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { + | +++++++++ + +error: lifetime may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | -- lifetime `'a` defined here +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v` + | +LL | fn i<'a, T, U>(v: Box+'a>) -> Box { + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn i<'a, T, U>(v: Box<(dyn A + 'static)>) -> Box { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0515]: cannot return value referencing local data `*v` + --> $DIR/regions-close-object-into-object-4.rs:9:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here + | returns a value referencing data owned by the current function + +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/regions-close-object-into-object-4.rs:9:14 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^ ...so that the type `U` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn i<'a, T, U: 'static>(v: Box+'a>) -> Box { + | +++++++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0310, E0515. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/regions/regions-close-object-into-object-5.rs b/tests/ui/regions/regions-close-object-into-object-5.rs new file mode 100644 index 000000000..d534c3749 --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-5.rs @@ -0,0 +1,25 @@ +#![allow(warnings)] + + +trait A +{ + fn get(&self) -> T { panic!() } +} + +struct B<'a, T: 'a>(&'a (A + 'a)); + +trait X { fn foo(&self) {} } + +impl<'a, T> X for B<'a, T> {} + +fn f<'a, T, U>(v: Box + 'static>) -> Box { + // oh dear! + Box::new(B(&*v)) as Box + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough + //~| ERROR cannot return value referencing local data `*v` [E0515] +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-object-into-object-5.stderr b/tests/ui/regions/regions-close-object-into-object-5.stderr new file mode 100644 index 000000000..311e8868c --- /dev/null +++ b/tests/ui/regions/regions-close-object-into-object-5.stderr @@ -0,0 +1,57 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { + | +++++++++ + +error[E0515]: cannot return value referencing local data `*v` + --> $DIR/regions-close-object-into-object-5.rs:17:5 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^ + | | | + | | `*v` is borrowed here + | returns a value referencing data owned by the current function + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-object-into-object-5.rs:17:14 + | +LL | Box::new(B(&*v)) as Box + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn f<'a, T: 'static, U>(v: Box + 'static>) -> Box { + | +++++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0310, E0515. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/regions/regions-close-over-type-parameter-1.rs b/tests/ui/regions/regions-close-over-type-parameter-1.rs new file mode 100644 index 000000000..610f75745 --- /dev/null +++ b/tests/ui/regions/regions-close-over-type-parameter-1.rs @@ -0,0 +1,24 @@ +// Test for what happens when a type parameter `A` is closed over into +// an object. This should yield errors unless `A` (and the object) +// both have suitable bounds. + +trait SomeTrait { + fn get(&self) -> isize; +} + + +fn make_object1(v: A) -> Box { + Box::new(v) as Box + //~^ ERROR the parameter type `A` may not live long enough +} + +fn make_object2<'a, A: SomeTrait + 'a>(v: A) -> Box { + Box::new(v) as Box +} + +fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box { + Box::new(v) as Box + //~^ ERROR the parameter type `A` may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-over-type-parameter-1.stderr b/tests/ui/regions/regions-close-over-type-parameter-1.stderr new file mode 100644 index 000000000..b7b557d7a --- /dev/null +++ b/tests/ui/regions/regions-close-over-type-parameter-1.stderr @@ -0,0 +1,26 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/regions-close-over-type-parameter-1.rs:11:5 + | +LL | Box::new(v) as Box + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn make_object1(v: A) -> Box { + | +++++++++ + +error[E0309]: the parameter type `A` may not live long enough + --> $DIR/regions-close-over-type-parameter-1.rs:20:5 + | +LL | Box::new(v) as Box + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn make_object3<'a, 'b, A: SomeTrait + 'a + 'b>(v: A) -> Box { + | ++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0309, E0310. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-close-over-type-parameter-multiple.rs b/tests/ui/regions/regions-close-over-type-parameter-multiple.rs new file mode 100644 index 000000000..e032a94c3 --- /dev/null +++ b/tests/ui/regions/regions-close-over-type-parameter-multiple.rs @@ -0,0 +1,24 @@ +// Various tests where we over type parameters with multiple lifetime +// bounds. + +trait SomeTrait { fn get(&self) -> isize; } + + +fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b... + Box::new(v) as Box // ...hence this type is safe. +} + +fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b... + Box::new(v) as Box // ...hence this type is safe. +} + +fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b...but not 'c. + Box::new(v) as Box + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr b/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr new file mode 100644 index 000000000..baa0506d0 --- /dev/null +++ b/tests/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-close-over-type-parameter-multiple.rs:19:5 + | +LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +LL | // A outlives 'a AND 'b...but not 'c. +LL | Box::new(v) as Box + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'c` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'c` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-close-over-type-parameter-successfully.rs b/tests/ui/regions/regions-close-over-type-parameter-successfully.rs new file mode 100644 index 000000000..48aad9481 --- /dev/null +++ b/tests/ui/regions/regions-close-over-type-parameter-successfully.rs @@ -0,0 +1,21 @@ +// run-pass +// A test where we (successfully) close over a reference into +// an object. + +trait SomeTrait { fn get(&self) -> isize; } + +impl<'a> SomeTrait for &'a isize { + fn get(&self) -> isize { + **self + } +} + +fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box { + Box::new(v) as Box +} + +fn main() { + let i: isize = 22; + let obj = make_object(&i); + assert_eq!(22, obj.get()); +} diff --git a/tests/ui/regions/regions-close-param-into-object.rs b/tests/ui/regions/regions-close-param-into-object.rs new file mode 100644 index 000000000..2760e5eed --- /dev/null +++ b/tests/ui/regions/regions-close-param-into-object.rs @@ -0,0 +1,27 @@ +trait X { fn foo(&self) {} } + +fn p1(v: T) -> Box + where T : X +{ + Box::new(v) //~ ERROR parameter type `T` may not live long enough +} + +fn p2(v: Box) -> Box + where Box : X +{ + Box::new(v) //~ ERROR parameter type `T` may not live long enough +} + +fn p3<'a,T>(v: T) -> Box + where T : X +{ + Box::new(v) //~ ERROR parameter type `T` may not live long enough +} + +fn p4<'a,T>(v: Box) -> Box + where Box : X +{ + Box::new(v) //~ ERROR parameter type `T` may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-close-param-into-object.stderr b/tests/ui/regions/regions-close-param-into-object.stderr new file mode 100644 index 000000000..9162be5b9 --- /dev/null +++ b/tests/ui/regions/regions-close-param-into-object.stderr @@ -0,0 +1,48 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-param-into-object.rs:6:5 + | +LL | Box::new(v) + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | where T : X + 'static + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/regions-close-param-into-object.rs:12:5 + | +LL | Box::new(v) + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn p2(v: Box) -> Box + | +++++++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-close-param-into-object.rs:18:5 + | +LL | Box::new(v) + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | where T : X + 'a + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-close-param-into-object.rs:24:5 + | +LL | Box::new(v) + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn p4<'a,T: 'a>(v: Box) -> Box + | ++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0309, E0310. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-copy-closure.rs b/tests/ui/regions/regions-copy-closure.rs new file mode 100644 index 000000000..436400797 --- /dev/null +++ b/tests/ui/regions/regions-copy-closure.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(non_camel_case_types)] + +struct closure_box<'a> { + cl: Box, +} + +fn box_it<'a>(x: Box) -> closure_box<'a> { + closure_box {cl: x} +} + +pub fn main() { + let mut i = 3; + assert_eq!(i, 3); + { + let cl = || i += 1; + let mut cl_box = box_it(Box::new(cl)); + (cl_box.cl)(); + } + assert_eq!(i, 4); +} diff --git a/tests/ui/regions/regions-creating-enums.rs b/tests/ui/regions/regions-creating-enums.rs new file mode 100644 index 000000000..6ed68f803 --- /dev/null +++ b/tests/ui/regions/regions-creating-enums.rs @@ -0,0 +1,33 @@ +enum Ast<'a> { + Num(usize), + Add(&'a Ast<'a>, &'a Ast<'a>) +} + +fn build() { + let x = Ast::Num(3); + let y = Ast::Num(4); + let z = Ast::Add(&x, &y); + compute(&z); +} + +fn compute(x: &Ast) -> usize { + match *x { + Ast::Num(x) => { x } + Ast::Add(x, y) => { compute(x) + compute(y) } + } +} + +fn map_nums<'a,'b, F>(x: &Ast, f: &mut F) -> &'a Ast<'b> where F: FnMut(usize) -> usize { + match *x { + Ast::Num(x) => { + return &Ast::Num((*f)(x)); //~ ERROR cannot return reference to temporary value + } + Ast::Add(x, y) => { + let m_x = map_nums(x, f); + let m_y = map_nums(y, f); + return &Ast::Add(m_x, m_y); //~ ERROR cannot return reference to temporary value + } + } +} + +fn main() {} diff --git a/tests/ui/regions/regions-creating-enums.stderr b/tests/ui/regions/regions-creating-enums.stderr new file mode 100644 index 000000000..a95d84629 --- /dev/null +++ b/tests/ui/regions/regions-creating-enums.stderr @@ -0,0 +1,21 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/regions-creating-enums.rs:23:16 + | +LL | return &Ast::Num((*f)(x)); + | ^----------------- + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error[E0515]: cannot return reference to temporary value + --> $DIR/regions-creating-enums.rs:28:16 + | +LL | return &Ast::Add(m_x, m_y); + | ^------------------ + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-creating-enums2.rs b/tests/ui/regions/regions-creating-enums2.rs new file mode 100644 index 000000000..7b16fb1a8 --- /dev/null +++ b/tests/ui/regions/regions-creating-enums2.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum ast<'a> { + num(usize), + add(&'a ast<'a>, &'a ast<'a>) +} + +fn mk_add_ok<'r>(x: &'r ast<'r>, y: &'r ast<'r>) -> ast<'r> { + ast::add(x, y) +} + +pub fn main() { +} diff --git a/tests/ui/regions/regions-creating-enums3.rs b/tests/ui/regions/regions-creating-enums3.rs new file mode 100644 index 000000000..39dbb3d8a --- /dev/null +++ b/tests/ui/regions/regions-creating-enums3.rs @@ -0,0 +1,12 @@ +enum Ast<'a> { + Num(usize), + Add(&'a Ast<'a>, &'a Ast<'a>) +} + +fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> { + Ast::Add(x, y) + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-creating-enums3.stderr b/tests/ui/regions/regions-creating-enums3.stderr new file mode 100644 index 000000000..41d609b56 --- /dev/null +++ b/tests/ui/regions/regions-creating-enums3.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-creating-enums3.rs:7:5 + | +LL | fn mk_add_bad1<'a,'b>(x: &'a Ast<'a>, y: &'b Ast<'b>) -> Ast<'a> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | Ast::Add(x, y) + | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-creating-enums4.rs b/tests/ui/regions/regions-creating-enums4.rs new file mode 100644 index 000000000..c9eab08cb --- /dev/null +++ b/tests/ui/regions/regions-creating-enums4.rs @@ -0,0 +1,12 @@ +enum Ast<'a> { + Num(usize), + Add(&'a Ast<'a>, &'a Ast<'a>) +} + +fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { + Ast::Add(x, y) + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-creating-enums4.stderr b/tests/ui/regions/regions-creating-enums4.stderr new file mode 100644 index 000000000..91cf57e09 --- /dev/null +++ b/tests/ui/regions/regions-creating-enums4.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-creating-enums4.rs:7:5 + | +LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | Ast::Add(x, y) + | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-creating-enums5.rs b/tests/ui/regions/regions-creating-enums5.rs new file mode 100644 index 000000000..ad3d9748b --- /dev/null +++ b/tests/ui/regions/regions-creating-enums5.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum ast<'a> { + num(usize), + add(&'a ast<'a>, &'a ast<'a>) +} + +fn mk_add_ok<'a>(x: &'a ast<'a>, y: &'a ast<'a>, _z: &ast) -> ast<'a> { + ast::add(x, y) +} + +pub fn main() { +} diff --git a/tests/ui/regions/regions-debruijn-of-object.rs b/tests/ui/regions/regions-debruijn-of-object.rs new file mode 100644 index 000000000..0b5510489 --- /dev/null +++ b/tests/ui/regions/regions-debruijn-of-object.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct ctxt<'tcx> { + x: &'tcx i32 +} + +trait AstConv<'tcx> { + fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>; +} + +fn foo(conv: &dyn AstConv) { } + +fn bar<'tcx>(conv: &dyn AstConv<'tcx>) { + foo(conv) +} + +fn main() { } diff --git a/tests/ui/regions/regions-dependent-addr-of.rs b/tests/ui/regions/regions-dependent-addr-of.rs new file mode 100644 index 000000000..a6cb56e31 --- /dev/null +++ b/tests/ui/regions/regions-dependent-addr-of.rs @@ -0,0 +1,112 @@ +// run-pass +// Test lifetimes are linked properly when we create dependent region pointers. +// Issue #3148. + +#![feature(box_patterns)] + +struct A { + value: B +} + +struct B { + v1: isize, + v2: [isize; 3], + v3: Vec , + v4: C, + v5: Box, + v6: Option +} + +#[derive(Copy, Clone)] +struct C { + f: isize +} + +fn get_v1(a: &A) -> &isize { + // Region inferencer must deduce that &v < L2 < L1 + let foo = &a.value; // L1 + &foo.v1 // L2 +} + +fn get_v2(a: &A, i: usize) -> &isize { + let foo = &a.value; + &foo.v2[i] +} + +fn get_v3(a: &A, i: usize) -> &isize { + let foo = &a.value; + &foo.v3[i] +} + +fn get_v4(a: &A, _i: usize) -> &isize { + let foo = &a.value; + &foo.v4.f +} + +fn get_v5(a: &A, _i: usize) -> &isize { + let foo = &a.value; + &foo.v5.f +} + +fn get_v6_a(a: &A, _i: usize) -> &isize { + match a.value.v6 { + Some(ref v) => &v.f, + None => panic!() + } +} + +fn get_v6_b(a: &A, _i: usize) -> &isize { + match *a { + A { value: B { v6: Some(ref v), .. } } => &v.f, + _ => panic!() + } +} + +fn get_v6_c(a: &A, _i: usize) -> &isize { + match a { + &A { value: B { v6: Some(ref v), .. } } => &v.f, + _ => panic!() + } +} + +fn get_v5_ref(a: &A, _i: usize) -> &isize { + match &a.value { + &B {v5: box C {f: ref v}, ..} => v + } +} + +pub fn main() { + let a = A {value: B {v1: 22, + v2: [23, 24, 25], + v3: vec![26, 27, 28], + v4: C { f: 29 }, + v5: Box::new(C { f: 30 }), + v6: Some(C { f: 31 })}}; + + let p = get_v1(&a); + assert_eq!(*p, a.value.v1); + + let p = get_v2(&a, 1); + assert_eq!(*p, a.value.v2[1]); + + let p = get_v3(&a, 1); + assert_eq!(*p, a.value.v3[1]); + + let p = get_v4(&a, 1); + assert_eq!(*p, a.value.v4.f); + + let p = get_v5(&a, 1); + assert_eq!(*p, a.value.v5.f); + + let p = get_v6_a(&a, 1); + assert_eq!(*p, a.value.v6.unwrap().f); + + let p = get_v6_b(&a, 1); + assert_eq!(*p, a.value.v6.unwrap().f); + + let p = get_v6_c(&a, 1); + assert_eq!(*p, a.value.v6.unwrap().f); + + let p = get_v5_ref(&a, 1); + assert_eq!(*p, a.value.v5.f); +} diff --git a/tests/ui/regions/regions-dependent-autofn.rs b/tests/ui/regions/regions-dependent-autofn.rs new file mode 100644 index 000000000..246dbb556 --- /dev/null +++ b/tests/ui/regions/regions-dependent-autofn.rs @@ -0,0 +1,15 @@ +// run-pass +// Test lifetimes are linked properly when we autoslice a vector. +// Issue #3148. + +// pretty-expanded FIXME #23616 + +fn subslice(v: F) -> F where F: FnOnce() { v } + +fn both(v: F) -> F where F: FnOnce() { + subslice(subslice(v)) +} + +pub fn main() { + both(main); +} diff --git a/tests/ui/regions/regions-dependent-autoslice.rs b/tests/ui/regions/regions-dependent-autoslice.rs new file mode 100644 index 000000000..4c5b35ec4 --- /dev/null +++ b/tests/ui/regions/regions-dependent-autoslice.rs @@ -0,0 +1,14 @@ +// run-pass +// Test lifetimes are linked properly when we autoslice a vector. +// Issue #3148. + +fn subslice1<'r>(v: &'r [usize]) -> &'r [usize] { v } + +fn both<'r>(v: &'r [usize]) -> &'r [usize] { + subslice1(subslice1(v)) +} + +pub fn main() { + let v = vec![1,2,3]; + both(&v); +} diff --git a/tests/ui/regions/regions-dependent-let-ref.rs b/tests/ui/regions/regions-dependent-let-ref.rs new file mode 100644 index 000000000..94e3df4b3 --- /dev/null +++ b/tests/ui/regions/regions-dependent-let-ref.rs @@ -0,0 +1,12 @@ +// run-pass +// Test lifetimes are linked properly when we take reference +// to interior. + +// pretty-expanded FIXME #23616 + +struct Foo(isize); +pub fn main() { + // Here the lifetime of the `&` should be at least the + // block, since a ref binding is created to the interior. + let &Foo(ref _x) = &Foo(3); +} diff --git a/tests/ui/regions/regions-early-bound-error-method.rs b/tests/ui/regions/regions-early-bound-error-method.rs new file mode 100644 index 000000000..7edcc677d --- /dev/null +++ b/tests/ui/regions/regions-early-bound-error-method.rs @@ -0,0 +1,26 @@ +// Tests that you can use a fn lifetime parameter as part of +// the value for a type parameter in a bound. + +trait GetRef<'a> { + fn get(&self) -> &'a isize; +} + +struct Box<'a> { + t: &'a isize +} + +impl<'a> GetRef<'a> for Box<'a> { + fn get(&self) -> &'a isize { + self.t + } +} + +impl<'a> Box<'a> { + fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { + g2.get() + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { +} diff --git a/tests/ui/regions/regions-early-bound-error-method.stderr b/tests/ui/regions/regions-early-bound-error-method.stderr new file mode 100644 index 000000000..7f10c051f --- /dev/null +++ b/tests/ui/regions/regions-early-bound-error-method.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-early-bound-error-method.rs:20:9 + | +LL | impl<'a> Box<'a> { + | -- lifetime `'a` defined here +LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { + | -- lifetime `'b` defined here +LL | g2.get() + | ^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-early-bound-error.rs b/tests/ui/regions/regions-early-bound-error.rs new file mode 100644 index 000000000..98a69c24f --- /dev/null +++ b/tests/ui/regions/regions-early-bound-error.rs @@ -0,0 +1,24 @@ +// Tests that you can use a fn lifetime parameter as part of +// the value for a type parameter in a bound. + +trait GetRef<'a, T> { + fn get(&self) -> &'a T; +} + +struct Box<'a, T:'a> { + t: &'a T +} + +impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> { + fn get(&self) -> &'a T { + self.t + } +} + +fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { + g1.get() + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-early-bound-error.stderr b/tests/ui/regions/regions-early-bound-error.stderr new file mode 100644 index 000000000..eb4cd5ca7 --- /dev/null +++ b/tests/ui/regions/regions-early-bound-error.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-early-bound-error.rs:19:5 + | +LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | g1.get() + | ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs b/tests/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs new file mode 100644 index 000000000..fe50a7dd1 --- /dev/null +++ b/tests/ui/regions/regions-early-bound-lifetime-in-assoc-fn.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(unused_imports)] +// Test that we are able to compile calls to associated fns like +// `decode()` where the bound on the `Self` parameter references a +// lifetime parameter of the trait. This example indicates why trait +// lifetime parameters must be early bound in the type of the +// associated item. + +// pretty-expanded FIXME #23616 + +use std::marker; + +pub enum Value<'v> { + A(&'v str), + B, +} + +pub trait Decoder<'v> { + fn read(&mut self) -> Value<'v>; +} + +pub trait Decodable<'v, D: Decoder<'v>> { + fn decode(d: &mut D) -> Self; +} + +impl<'v, D: Decoder<'v>> Decodable<'v, D> for () { + fn decode(d: &mut D) -> () { + match d.read() { + Value::A(..) => (), + Value::B => Decodable::decode(d), + } + } +} + +pub fn main() { } diff --git a/tests/ui/regions/regions-early-bound-trait-param.rs b/tests/ui/regions/regions-early-bound-trait-param.rs new file mode 100644 index 000000000..a28bd14ba --- /dev/null +++ b/tests/ui/regions/regions-early-bound-trait-param.rs @@ -0,0 +1,132 @@ +// run-pass +// Tests that you can use an early-bound lifetime parameter as +// on of the generic parameters in a trait. + +trait Trait<'a> { + fn long(&'a self) -> isize; + fn short<'b>(&'b self) -> isize; +} + +fn poly_invoke<'c, T: Trait<'c>>(x: &'c T) -> (isize, isize) { + let l = x.long(); + let s = x.short(); + (l,s) +} + +fn object_invoke1<'d>(x: &'d dyn Trait<'d>) -> (isize, isize) { + let l = x.long(); + let s = x.short(); + (l,s) +} + +struct Struct1<'e> { + f: &'e (dyn Trait<'e>+'e) +} + +fn field_invoke1<'f, 'g>(x: &'g Struct1<'f>) -> (isize,isize) { + let l = x.f.long(); + let s = x.f.short(); + (l,s) +} + +struct Struct2<'h, 'i:'h> { + f: &'h (dyn Trait<'i>+'h) +} + +fn object_invoke2<'j, 'k>(x: &'k dyn Trait<'j>) -> isize { + x.short() +} + +fn field_invoke2<'l, 'm, 'n>(x: &'n Struct2<'l,'m>) -> isize { + x.f.short() +} + +trait MakerTrait { + fn mk() -> Self; +} + +fn make_val() -> T { + MakerTrait::mk() +} + +trait RefMakerTrait<'q> { + fn mk(_: Self) -> &'q Self; +} + +fn make_ref<'r, T:RefMakerTrait<'r>>(t:T) -> &'r T { + RefMakerTrait::mk(t) +} + +impl<'s> Trait<'s> for (isize,isize) { + fn long(&'s self) -> isize { + let &(x,_) = self; + x + } + fn short<'b>(&'b self) -> isize { + let &(_,y) = self; + y + } +} + +impl<'t> MakerTrait for Box+'static> { + fn mk() -> Box+'static> { + let tup: Box<(isize, isize)> = Box::new((4,5)); + tup as Box + } +} + +enum List<'l> { + Cons(isize, &'l List<'l>), + Null +} + +impl<'l> List<'l> { + fn car<'m>(&'m self) -> isize { + match self { + &List::Cons(car, _) => car, + &List::Null => panic!(), + } + } + fn cdr<'n>(&'n self) -> &'l List<'l> { + match self { + &List::Cons(_, cdr) => cdr, + &List::Null => panic!(), + } + } +} + +impl<'t> RefMakerTrait<'t> for List<'t> { + fn mk(l:List<'t>) -> &'t List<'t> { + l.cdr() + } +} + +pub fn main() { + let t = (2,3); + let o = &t as &dyn Trait; + let s1 = Struct1 { f: o }; + let s2 = Struct2 { f: o }; + assert_eq!(poly_invoke(&t), (2,3)); + assert_eq!(object_invoke1(&t), (2,3)); + assert_eq!(field_invoke1(&s1), (2,3)); + assert_eq!(object_invoke2(&t), 3); + assert_eq!(field_invoke2(&s2), 3); + + let m : Box = make_val(); + // assert_eq!(object_invoke1(&*m), (4,5)); + // ~~~~~~~~~~~~~~~~~~~ + // this call yields a compilation error; see ui/span/dropck-object-cycle.rs + // for details. + assert_eq!(object_invoke2(&*m), 5); + + // The RefMakerTrait above is pretty strange (i.e., it is strange + // to consume a value of type T and return a &T). Easiest thing + // that came to my mind: consume a cell of a linked list and + // return a reference to the list it points to. + let l0 = List::Null; + let l1 = List::Cons(1, &l0); + let l2 = List::Cons(2, &l1); + let rl1 = &l1; + let r = make_ref(l2); + assert_eq!(rl1.car(), r.car()); +} diff --git a/tests/ui/regions/regions-early-bound-used-in-bound-method.rs b/tests/ui/regions/regions-early-bound-used-in-bound-method.rs new file mode 100644 index 000000000..a778dae1e --- /dev/null +++ b/tests/ui/regions/regions-early-bound-used-in-bound-method.rs @@ -0,0 +1,30 @@ +// run-pass +// Tests that you can use a fn lifetime parameter as part of +// the value for a type parameter in a bound. + + +trait GetRef<'a> { + fn get(&self) -> &'a isize; +} + +#[derive(Copy, Clone)] +struct Box<'a> { + t: &'a isize +} + +impl<'a> GetRef<'a> for Box<'a> { + fn get(&self) -> &'a isize { + self.t + } +} + +impl<'a> Box<'a> { + fn add<'b,G:GetRef<'b>>(&self, g2: G) -> isize { + *self.t + *g2.get() + } +} + +pub fn main() { + let b1 = Box { t: &3 }; + assert_eq!(b1.add(b1), 6); +} diff --git a/tests/ui/regions/regions-early-bound-used-in-bound.rs b/tests/ui/regions/regions-early-bound-used-in-bound.rs new file mode 100644 index 000000000..6ccc99e84 --- /dev/null +++ b/tests/ui/regions/regions-early-bound-used-in-bound.rs @@ -0,0 +1,28 @@ +// run-pass +// Tests that you can use a fn lifetime parameter as part of +// the value for a type parameter in a bound. + + +trait GetRef<'a, T> { + fn get(&self) -> &'a T; +} + +#[derive(Copy, Clone)] +struct Box<'a, T:'a> { + t: &'a T +} + +impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> { + fn get(&self) -> &'a T { + self.t + } +} + +fn add<'a,G:GetRef<'a, isize>>(g1: G, g2: G) -> isize { + *g1.get() + *g2.get() +} + +pub fn main() { + let b1 = Box { t: &3 }; + assert_eq!(add(b1, b1), 6); +} diff --git a/tests/ui/regions/regions-early-bound-used-in-type-param.rs b/tests/ui/regions/regions-early-bound-used-in-type-param.rs new file mode 100644 index 000000000..d58c17ad9 --- /dev/null +++ b/tests/ui/regions/regions-early-bound-used-in-type-param.rs @@ -0,0 +1,28 @@ +// run-pass +// Tests that you can use a fn lifetime parameter as part of +// the value for a type parameter in a bound. + + +trait Get { + fn get(&self) -> T; +} + +#[derive(Copy, Clone)] +struct Box { + t: T +} + +impl Get for Box { + fn get(&self) -> T { + self.t.clone() + } +} + +fn add<'a,G:Get<&'a isize>>(g1: G, g2: G) -> isize { + *g1.get() + *g2.get() +} + +pub fn main() { + let b1 = Box { t: &3 }; + assert_eq!(add(b1, b1), 6); +} diff --git a/tests/ui/regions/regions-escape-into-other-fn.rs b/tests/ui/regions/regions-escape-into-other-fn.rs new file mode 100644 index 000000000..65f4c1b6a --- /dev/null +++ b/tests/ui/regions/regions-escape-into-other-fn.rs @@ -0,0 +1,8 @@ +// run-pass +fn foo(x: &usize) -> &usize { x } +fn bar(x: &usize) -> usize { *x } + +pub fn main() { + let p: Box<_> = Box::new(3); + assert_eq!(bar(foo(&*p)), 3); +} diff --git a/tests/ui/regions/regions-escape-method.rs b/tests/ui/regions/regions-escape-method.rs new file mode 100644 index 000000000..69c01ae69 --- /dev/null +++ b/tests/ui/regions/regions-escape-method.rs @@ -0,0 +1,16 @@ +// Test a method call where the parameter `B` would (illegally) be +// inferred to a region bound in the method argument. If this program +// were accepted, then the closure passed to `s.f` could escape its +// argument. + +struct S; + +impl S { + fn f(&self, _: F) where F: FnOnce(&i32) -> B { + } +} + +fn main() { + let s = S; + s.f(|p| p) //~ ERROR lifetime may not live long enough +} diff --git a/tests/ui/regions/regions-escape-method.stderr b/tests/ui/regions/regions-escape-method.stderr new file mode 100644 index 000000000..9f425125b --- /dev/null +++ b/tests/ui/regions/regions-escape-method.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-escape-method.rs:15:13 + | +LL | s.f(|p| p) + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 i32 + | has type `&'1 i32` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-escape-via-trait-or-not.rs b/tests/ui/regions/regions-escape-via-trait-or-not.rs new file mode 100644 index 000000000..ac0e56de4 --- /dev/null +++ b/tests/ui/regions/regions-escape-via-trait-or-not.rs @@ -0,0 +1,22 @@ +#![allow(dead_code)] + +trait Deref { + fn get(self) -> isize; +} + +impl<'a> Deref for &'a isize { + fn get(self) -> isize { + *self + } +} + +fn with(f: F) -> isize where F: FnOnce(&isize) -> R { + f(&3).get() +} + +fn return_it() -> isize { + with(|o| o) //~ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-escape-via-trait-or-not.stderr b/tests/ui/regions/regions-escape-via-trait-or-not.stderr new file mode 100644 index 000000000..cae6c33ac --- /dev/null +++ b/tests/ui/regions/regions-escape-via-trait-or-not.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-escape-via-trait-or-not.rs:18:14 + | +LL | with(|o| o) + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 isize + | has type `&'1 isize` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-expl-self.rs b/tests/ui/regions/regions-expl-self.rs new file mode 100644 index 000000000..f7315d628 --- /dev/null +++ b/tests/ui/regions/regions-expl-self.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// Test that you can insert an explicit lifetime in explicit self. + +// pretty-expanded FIXME #23616 + +struct Foo { + f: usize +} + +impl Foo { + pub fn foo<'a>(&'a self) {} +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-fn-subtyping-2.rs b/tests/ui/regions/regions-fn-subtyping-2.rs new file mode 100644 index 000000000..83949ddba --- /dev/null +++ b/tests/ui/regions/regions-fn-subtyping-2.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +// Issue #2263. + +// Here, `f` is a function that takes a pointer `x` and a function +// `g`, where `g` requires its argument `y` to be in the same region +// that `x` is in. +// pretty-expanded FIXME #23616 + +fn has_same_region(f: Box FnMut(&'a isize, Box)>) { + // `f` should be the type that `wants_same_region` wants, but + // right now the compiler complains that it isn't. + wants_same_region(f); +} + +fn wants_same_region(_f: Box FnMut(&'b isize, Box)>) { +} + +pub fn main() { +} diff --git a/tests/ui/regions/regions-fn-subtyping-return-static-fail.rs b/tests/ui/regions/regions-fn-subtyping-return-static-fail.rs new file mode 100644 index 000000000..539221b5a --- /dev/null +++ b/tests/ui/regions/regions-fn-subtyping-return-static-fail.rs @@ -0,0 +1,51 @@ +// In this fn, the type `F` is a function that takes a reference to a +// struct and returns another reference with the same lifetime. +// +// Meanwhile, the bare fn `foo` takes a reference to a struct with +// *ANY* lifetime and returns a reference with the 'static lifetime. +// This can safely be considered to be an instance of `F` because all +// lifetimes are sublifetimes of 'static. + +#![allow(dead_code)] +#![allow(unused_variables)] + +struct S; + +// Given 'cx, return 'cx +type F = for<'cx> fn(&'cx S) -> &'cx S; +fn want_F(f: F) {} + +// Given anything, return 'static +type G = for<'cx> fn(&'cx S) -> &'static S; +fn want_G(f: G) {} + +// Should meet both. +fn foo(x: &S) -> &'static S { + panic!() +} + +// Should meet both. +fn bar<'a, 'b>(x: &'a S) -> &'b S { + panic!() +} + +// Meets F, but not G. +fn baz(x: &S) -> &S { + panic!() +} + +fn supply_F() { + want_F(foo); + + want_F(bar); + + want_F(baz); +} + +fn supply_G() { + want_G(foo); + want_G(bar); + want_G(baz); //~ ERROR mismatched types +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr b/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr new file mode 100644 index 000000000..8d82ff958 --- /dev/null +++ b/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 + | +LL | want_G(baz); + | ------ ^^^ one type is more general than the other + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` + found fn item `for<'a> fn(&'a S) -> &'a S {baz}` +note: function defined here + --> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4 + | +LL | fn want_G(f: G) {} + | ^^^^^^ ---- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-fn-subtyping-return-static.rs b/tests/ui/regions/regions-fn-subtyping-return-static.rs new file mode 100644 index 000000000..de14d5ba8 --- /dev/null +++ b/tests/ui/regions/regions-fn-subtyping-return-static.rs @@ -0,0 +1,48 @@ +// In this fn, the type `F` is a function that takes a reference to a +// struct and returns another reference with the same lifetime. +// +// Meanwhile, the bare fn `foo` takes a reference to a struct with +// *ANY* lifetime and returns a reference with the 'static lifetime. +// This can safely be considered to be an instance of `F` because all +// lifetimes are sublifetimes of 'static. +// +// check-pass + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_snake_case)] + +struct S; + +// Given 'cx, return 'cx +type F = for<'cx> fn(&'cx S) -> &'cx S; +fn want_F(f: F) {} + +// Given anything, return 'static +type G = for<'cx> fn(&'cx S) -> &'static S; +fn want_G(f: G) {} + +// Should meet both. +fn foo(x: &S) -> &'static S { + panic!() +} + +// Should meet both. +fn bar<'a, 'b>(x: &'a S) -> &'b S { + panic!() +} + +// Meets F, but not G. +fn baz(x: &S) -> &S { + panic!() +} + +fn supply_F() { + want_F(foo); + + want_F(bar); + + want_F(baz); +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-fn-subtyping.rs b/tests/ui/regions/regions-fn-subtyping.rs new file mode 100644 index 000000000..9570359c6 --- /dev/null +++ b/tests/ui/regions/regions-fn-subtyping.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +// Issue #2263. + +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +// Should pass region checking. +fn ok(f: Box) { + // Here, g is a function that can accept a usize pointer with + // lifetime r, and f is a function that can accept a usize pointer + // with any lifetime. The assignment g = f should be OK (i.e., + // f's type should be a subtype of g's type), because f can be + // used in any context that expects g's type. But this currently + // fails. + let mut g: Box FnMut(&'r usize)> = Box::new(|x| { }); + g = f; +} + +// This version is the same as above, except that here, g's type is +// inferred. +fn ok_inferred(f: Box) { + let mut g: Box FnMut(&'r usize)> = Box::new(|_| {}); + g = f; +} + +pub fn main() { +} diff --git a/tests/ui/regions/regions-free-region-ordering-callee-4.rs b/tests/ui/regions/regions-free-region-ordering-callee-4.rs new file mode 100644 index 000000000..de58dd0b1 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-callee-4.rs @@ -0,0 +1,11 @@ +// Tests that callees correctly infer an ordering between free regions +// that appear in their parameter list. See also +// regions-free-region-ordering-caller.rs + +fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { + //~^ ERROR reference has a longer lifetime than the data it references + // Do not infer ordering from closure argument types. + let z: Option<&'a &'b usize> = None; +} + +fn main() {} diff --git a/tests/ui/regions/regions-free-region-ordering-callee-4.stderr b/tests/ui/regions/regions-free-region-ordering-callee-4.stderr new file mode 100644 index 000000000..1df7ca0e3 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-callee-4.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references + --> $DIR/regions-free-region-ordering-callee-4.rs:5:68 + | +LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regions-free-region-ordering-callee-4.rs:5:14 + | +LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regions-free-region-ordering-callee-4.rs:5:18 + | +LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/regions/regions-free-region-ordering-callee.rs b/tests/ui/regions/regions-free-region-ordering-callee.rs new file mode 100644 index 000000000..8158e81e1 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-callee.rs @@ -0,0 +1,30 @@ +// Tests that callees correctly infer an ordering between free regions +// that appear in their parameter list. See also +// regions-free-region-ordering-caller.rs + +fn ordering1<'a, 'b>(x: &'a &'b usize) -> &'a usize { + // It is safe to assume that 'a <= 'b due to the type of x + let y: &'b usize = &**x; + return y; +} + +fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize { + // However, it is not safe to assume that 'b <= 'a + &*y + //~^ ERROR lifetime may not live long enough +} + +fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize { + // Do not infer an ordering from the return value. + let z: &'b usize = &*x; + //~^ ERROR lifetime may not live long enough + panic!(); +} + +// see regions-free-region-ordering-callee-4.rs + +fn ordering5<'a, 'b>(a: &'a usize, b: &'b usize, x: Option<&'a &'b usize>) { + let z: Option<&'a &'b usize> = None; +} + +fn main() {} diff --git a/tests/ui/regions/regions-free-region-ordering-callee.stderr b/tests/ui/regions/regions-free-region-ordering-callee.stderr new file mode 100644 index 000000000..a1b46a692 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-callee.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/regions-free-region-ordering-callee.rs:13:5 + | +LL | fn ordering2<'a, 'b>(x: &'a &'b usize, y: &'a usize) -> &'b usize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // However, it is not safe to assume that 'b <= 'a +LL | &*y + | ^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/regions-free-region-ordering-callee.rs:19:12 + | +LL | fn ordering3<'a, 'b>(x: &'a usize, y: &'b usize) -> &'a &'b usize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Do not infer an ordering from the return value. +LL | let z: &'b usize = &*x; + | ^^^^^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/regions/regions-free-region-ordering-caller.rs b/tests/ui/regions/regions-free-region-ordering-caller.rs new file mode 100644 index 000000000..2e83c3258 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-caller.rs @@ -0,0 +1,23 @@ +// Test various ways to construct a pointer with a longer lifetime +// than the thing it points at and ensure that they result in +// errors. See also regions-free-region-ordering-callee.rs + +struct Paramd<'a> { x: &'a usize } + +fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + let z: Option<&'b &'a usize> = None; + //~^ ERROR lifetime may not live long enough +} + +fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + let y: Paramd<'a> = Paramd { x: a }; + let z: Option<&'b Paramd<'a>> = None; + //~^ ERROR lifetime may not live long enough +} + +fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + let z: Option<&'a &'b usize> = None; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-free-region-ordering-caller.stderr b/tests/ui/regions/regions-free-region-ordering-caller.stderr new file mode 100644 index 000000000..cdf70d2a5 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-caller.stderr @@ -0,0 +1,39 @@ +error: lifetime may not live long enough + --> $DIR/regions-free-region-ordering-caller.rs:8:12 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let z: Option<&'b &'a usize> = None; + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/regions-free-region-ordering-caller.rs:14:12 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let y: Paramd<'a> = Paramd { x: a }; +LL | let z: Option<&'b Paramd<'a>> = None; + | ^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/regions-free-region-ordering-caller.rs:19:12 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let z: Option<&'a &'b usize> = None; + | ^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/regions/regions-free-region-ordering-caller1.rs b/tests/ui/regions/regions-free-region-ordering-caller1.rs new file mode 100644 index 000000000..f32455616 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-caller1.rs @@ -0,0 +1,14 @@ +// Test various ways to construct a pointer with a longer lifetime +// than the thing it points at and ensure that they result in +// errors. See also regions-free-region-ordering-callee.rs + +fn call1<'a>(x: &'a usize) { + // Test that creating a pointer like + // &'a &'z usize requires that 'a <= 'z: + let y: usize = 3; + let z: &'a & usize = &(&y); + //~^ ERROR temporary value dropped while borrowed + //~^^ ERROR `y` does not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-free-region-ordering-caller1.stderr b/tests/ui/regions/regions-free-region-ordering-caller1.stderr new file mode 100644 index 000000000..8ef7e2253 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-caller1.stderr @@ -0,0 +1,32 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/regions-free-region-ordering-caller1.rs:9:27 + | +LL | fn call1<'a>(x: &'a usize) { + | -- lifetime `'a` defined here +... +LL | let z: &'a & usize = &(&y); + | ----------- ^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'a` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0597]: `y` does not live long enough + --> $DIR/regions-free-region-ordering-caller1.rs:9:27 + | +LL | fn call1<'a>(x: &'a usize) { + | -- lifetime `'a` defined here +... +LL | let z: &'a & usize = &(&y); + | ----------- ^^^^ borrowed value does not live long enough + | | + | type annotation requires that `y` is borrowed for `'a` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-free-region-ordering-incorrect.rs b/tests/ui/regions/regions-free-region-ordering-incorrect.rs new file mode 100644 index 000000000..1aee6e876 --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-incorrect.rs @@ -0,0 +1,22 @@ +// Test that free regions ordering only goes one way. That is, +// we have `&'a Node<'b, T>`, which implies that `'a <= 'b`, +// but not `'b <= 'a`. Hence, returning `&self.val` (which has lifetime +// `'a`) where `'b` is expected yields an error. +// +// This test began its life as a test for issue #4325. + +struct Node<'b, T: 'b> { + val: T, + next: Option<&'b Node<'b, T>> +} + +impl<'b, T> Node<'b, T> { + fn get<'a>(&'a self) -> &'b T { + match self.next { //~ ERROR lifetime may not live long enough + Some(ref next) => next.get(), + None => &self.val + } + } +} + +fn main() {} diff --git a/tests/ui/regions/regions-free-region-ordering-incorrect.stderr b/tests/ui/regions/regions-free-region-ordering-incorrect.stderr new file mode 100644 index 000000000..f7c75033c --- /dev/null +++ b/tests/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/regions-free-region-ordering-incorrect.rs:15:9 + | +LL | impl<'b, T> Node<'b, T> { + | -- lifetime `'b` defined here +LL | fn get<'a>(&'a self) -> &'b T { + | -- lifetime `'a` defined here +LL | / match self.next { +LL | | Some(ref next) => next.get(), +LL | | None => &self.val +LL | | } + | |_________^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs new file mode 100644 index 000000000..7c2e1aeee --- /dev/null +++ b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// Test that we recognize that if you have +// +// 'a : 'static +// +// then +// +// 'a : 'b + +fn test<'a,'b>(x: &'a i32) -> &'b i32 + where 'a: 'static //~ WARN unnecessary lifetime parameter `'a` +{ + x +} + +fn main() { } diff --git a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr new file mode 100644 index 000000000..70ed418d5 --- /dev/null +++ b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr @@ -0,0 +1,10 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:12:11 + | +LL | where 'a: 'static + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: 1 warning emitted + diff --git a/tests/ui/regions/regions-glb-free-free.rs b/tests/ui/regions/regions-glb-free-free.rs new file mode 100644 index 000000000..0370a5192 --- /dev/null +++ b/tests/ui/regions/regions-glb-free-free.rs @@ -0,0 +1,29 @@ +mod argparse { + pub struct Flag<'a> { + name: &'a str, + pub desc: &'a str, + max_count: usize, + value: usize + } + + pub fn flag<'r>(name: &'r str, desc: &'r str) -> Flag<'r> { + Flag { name: name, desc: desc, max_count: 1, value: 0 } + } + + impl<'a> Flag<'a> { + pub fn set_desc(self, s: &str) -> Flag<'a> { + Flag { //~ ERROR explicit lifetime required in the type of `s` [E0621] + name: self.name, + desc: s, + max_count: self.max_count, + value: self.value + } + } + } +} + +fn main () { + let f : argparse::Flag = argparse::flag("flag", "My flag"); + let updated_flag = f.set_desc("My new flag"); + assert_eq!(updated_flag.desc, "My new flag"); +} diff --git a/tests/ui/regions/regions-glb-free-free.stderr b/tests/ui/regions/regions-glb-free-free.stderr new file mode 100644 index 000000000..575037a0a --- /dev/null +++ b/tests/ui/regions/regions-glb-free-free.stderr @@ -0,0 +1,16 @@ +error[E0621]: explicit lifetime required in the type of `s` + --> $DIR/regions-glb-free-free.rs:15:13 + | +LL | pub fn set_desc(self, s: &str) -> Flag<'a> { + | ---- help: add explicit lifetime `'a` to the type of `s`: `&'a str` +LL | / Flag { +LL | | name: self.name, +LL | | desc: s, +LL | | max_count: self.max_count, +LL | | value: self.value +LL | | } + | |_____________^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-1.rs b/tests/ui/regions/regions-implied-bounds-projection-gap-1.rs new file mode 100644 index 000000000..38fc9c462 --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-1.rs @@ -0,0 +1,30 @@ +// Illustrates the "projection gap": in this test, even though we know +// that `T::Foo: 'x`, that does not tell us that `T: 'x`, because +// there might be other ways for the caller of `func` to show that +// `T::Foo: 'x` holds (e.g., where-clause). + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) +{ + wf::<&'x T>(); + //~^ ERROR the parameter type `T` may not live long enough +} + +fn caller2<'x, T:Trait1<'x>>(t: &'x T) +{ + wf::<&'x T::Foo>(); // OK +} + +fn caller3<'x, T:Trait1<'x>>(t: &'x T::Foo) +{ + wf::<&'x T::Foo>(); // OK +} + +fn main() { } diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr new file mode 100644 index 000000000..7c9f40556 --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-1.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:5 + | +LL | wf::<&'x T>(); + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn func<'x, T:Trait1<'x> + 'x>(t: &'x T::Foo) + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-2.rs b/tests/ui/regions/regions-implied-bounds-projection-gap-2.rs new file mode 100644 index 000000000..a481a9cc5 --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-2.rs @@ -0,0 +1,23 @@ +// Along with the other tests in this series, illustrates the +// "projection gap": in this test, we know that `T: 'x`, and that is +// enough to conclude that `T::Foo: 'x`. + +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T) +{ + wf::<&'x T::Foo>(); +} + + +fn main() { } diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-3.rs b/tests/ui/regions/regions-implied-bounds-projection-gap-3.rs new file mode 100644 index 000000000..a627cbbd8 --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-3.rs @@ -0,0 +1,23 @@ +// Along with the other tests in this series, illustrates the +// "projection gap": in this test, we know that `T::Foo: 'x`, and that +// is (naturally) enough to conclude that `T::Foo: 'x`. + +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) +{ + wf::<&'x T::Foo>(); +} + + +fn main() { } diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-4.rs b/tests/ui/regions/regions-implied-bounds-projection-gap-4.rs new file mode 100644 index 000000000..5158c2893 --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-4.rs @@ -0,0 +1,23 @@ +// Along with the other tests in this series, illustrates the +// "projection gap": in this test, we know that `T: 'x`, and that +// is (naturally) enough to conclude that `T: 'x`. + +// check-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Trait1<'x> { + type Foo; +} + +// calling this fn should trigger a check that the type argument +// supplied is well-formed. +fn wf() { } + +fn func<'x, T:Trait1<'x>>(t: &'x T) +{ + wf::<&'x T>(); +} + + +fn main() { } diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs new file mode 100644 index 000000000..110635203 --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs @@ -0,0 +1,27 @@ +// The "projection gap" is particularly "fun" around higher-ranked +// projections. This is because the current code is hard-coded to say +// that a projection that contains escaping regions, like `>::Foo` where `'z` is bound, can only be found to +// outlive a region if all components that appear free (`'y`, where) +// outlive that region. However, we DON'T add those components to the +// implied bounds set, but rather we treat projections with escaping +// regions as opaque entities, just like projections without escaping +// regions. + +trait Trait1 { } + +trait Trait2<'a, 'b> { + type Foo; +} + +// As a side-effect of the conservative process above, the type of +// this argument `t` is not automatically considered well-formed, +// since for it to be WF, we would need to know that `'y: 'x`, but we +// do not infer that. +fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) + //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied +{ +} + +fn main() { } diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr new file mode 100644 index 000000000..3fd39810d --- /dev/null +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49 + | +LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1 + | +LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) +LL | | +LL | | +LL | | { +LL | | } + | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) + | ++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/regions/regions-in-enums-anon.rs b/tests/ui/regions/regions-in-enums-anon.rs new file mode 100644 index 000000000..da65cb791 --- /dev/null +++ b/tests/ui/regions/regions-in-enums-anon.rs @@ -0,0 +1,7 @@ +// Test that anonymous lifetimes are not permitted in enum declarations + +enum Foo { + Bar(&isize) //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/regions/regions-in-enums-anon.stderr b/tests/ui/regions/regions-in-enums-anon.stderr new file mode 100644 index 000000000..ed547aa9c --- /dev/null +++ b/tests/ui/regions/regions-in-enums-anon.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/regions-in-enums-anon.rs:4:9 + | +LL | Bar(&isize) + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ enum Foo<'a> { +LL ~ Bar(&'a isize) + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/regions/regions-in-enums.rs b/tests/ui/regions/regions-in-enums.rs new file mode 100644 index 000000000..8cf553a0f --- /dev/null +++ b/tests/ui/regions/regions-in-enums.rs @@ -0,0 +1,20 @@ +// Test that lifetimes must be declared for use on enums. +// See also regions-undeclared.rs + +enum Yes0<'lt> { + X3(&'lt usize) +} + +enum Yes1<'a> { + X4(&'a usize) +} + +enum No0 { + X5(&'foo usize) //~ ERROR use of undeclared lifetime name `'foo` +} + +enum No1 { + X6(&'a usize) //~ ERROR use of undeclared lifetime name `'a` +} + +fn main() {} diff --git a/tests/ui/regions/regions-in-enums.stderr b/tests/ui/regions/regions-in-enums.stderr new file mode 100644 index 000000000..665376532 --- /dev/null +++ b/tests/ui/regions/regions-in-enums.stderr @@ -0,0 +1,19 @@ +error[E0261]: use of undeclared lifetime name `'foo` + --> $DIR/regions-in-enums.rs:13:9 + | +LL | enum No0 { + | - help: consider introducing lifetime `'foo` here: `<'foo>` +LL | X5(&'foo usize) + | ^^^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-in-enums.rs:17:9 + | +LL | enum No1 { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | X6(&'a usize) + | ^^ undeclared lifetime + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/regions/regions-in-structs-anon.rs b/tests/ui/regions/regions-in-structs-anon.rs new file mode 100644 index 000000000..7cb2ce0db --- /dev/null +++ b/tests/ui/regions/regions-in-structs-anon.rs @@ -0,0 +1,7 @@ +// Test that anonymous lifetimes are not permitted in struct declarations + +struct Foo { + x: &isize //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/regions/regions-in-structs-anon.stderr b/tests/ui/regions/regions-in-structs-anon.stderr new file mode 100644 index 000000000..992d25c9f --- /dev/null +++ b/tests/ui/regions/regions-in-structs-anon.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/regions-in-structs-anon.rs:4:8 + | +LL | x: &isize + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct Foo<'a> { +LL ~ x: &'a isize + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/regions/regions-in-structs.rs b/tests/ui/regions/regions-in-structs.rs new file mode 100644 index 000000000..71f718ba2 --- /dev/null +++ b/tests/ui/regions/regions-in-structs.rs @@ -0,0 +1,15 @@ +struct Yes1<'a> { + x: &'a usize, +} + +struct Yes2<'a> { + x: &'a usize, +} + +struct StructDecl { + a: &'a isize, //~ ERROR use of undeclared lifetime name `'a` + b: &'a isize, //~ ERROR use of undeclared lifetime name `'a` +} + + +fn main() {} diff --git a/tests/ui/regions/regions-in-structs.stderr b/tests/ui/regions/regions-in-structs.stderr new file mode 100644 index 000000000..5dfdc2ee9 --- /dev/null +++ b/tests/ui/regions/regions-in-structs.stderr @@ -0,0 +1,20 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-in-structs.rs:10:9 + | +LL | struct StructDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | a: &'a isize, + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-in-structs.rs:11:9 + | +LL | struct StructDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | a: &'a isize, +LL | b: &'a isize, + | ^^ undeclared lifetime + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/regions/regions-infer-at-fn-not-param.rs b/tests/ui/regions/regions-infer-at-fn-not-param.rs new file mode 100644 index 000000000..fb9c5d5c2 --- /dev/null +++ b/tests/ui/regions/regions-infer-at-fn-not-param.rs @@ -0,0 +1,19 @@ +struct Parameterized1<'a> { + g: Box +} + +struct NotParameterized1 { + g: Box +} + +struct NotParameterized2 { + g: Box +} + +fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p } +//~^ ERROR explicit lifetime required in the type of `p` + +fn take3(p: NotParameterized1) -> NotParameterized1 { p } +fn take4(p: NotParameterized2) -> NotParameterized2 { p } + +fn main() {} diff --git a/tests/ui/regions/regions-infer-at-fn-not-param.stderr b/tests/ui/regions/regions-infer-at-fn-not-param.stderr new file mode 100644 index 000000000..8cfc44f6a --- /dev/null +++ b/tests/ui/regions/regions-infer-at-fn-not-param.stderr @@ -0,0 +1,11 @@ +error[E0621]: explicit lifetime required in the type of `p` + --> $DIR/regions-infer-at-fn-not-param.rs:13:57 + | +LL | fn take1<'a>(p: Parameterized1) -> Parameterized1<'a> { p } + | -------------- ^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `p`: `Parameterized1<'a>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/regions/regions-infer-borrow-scope-addr-of.rs b/tests/ui/regions/regions-infer-borrow-scope-addr-of.rs new file mode 100644 index 000000000..5d8ad932e --- /dev/null +++ b/tests/ui/regions/regions-infer-borrow-scope-addr-of.rs @@ -0,0 +1,23 @@ +// run-pass + +use std::mem::swap; + +pub fn main() { + let mut x = 4; + + for i in 0_usize..3 { + // ensure that the borrow in this alt + // does not interfere with the swap + // below. note that it would it you + // naively borrowed &x for the lifetime + // of the variable x, as we once did + match i { + i => { + let y = &x; + assert!(i < *y); + } + } + let mut y = 4; + swap(&mut y, &mut x); + } +} diff --git a/tests/ui/regions/regions-infer-borrow-scope-too-big.rs b/tests/ui/regions/regions-infer-borrow-scope-too-big.rs new file mode 100644 index 000000000..250b41da5 --- /dev/null +++ b/tests/ui/regions/regions-infer-borrow-scope-too-big.rs @@ -0,0 +1,16 @@ +struct Point { + x: isize, + y: isize, +} + +fn x_coord<'r>(p: &'r Point) -> &'r isize { + return &p.x; +} + +fn foo<'a>(p: Box) -> &'a isize { + let xc = x_coord(&*p); + assert_eq!(*xc, 3); + return xc; //~ ERROR cannot return value referencing local data `*p` +} + +fn main() {} diff --git a/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr b/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr new file mode 100644 index 000000000..2c7a6e8b5 --- /dev/null +++ b/tests/ui/regions/regions-infer-borrow-scope-too-big.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local data `*p` + --> $DIR/regions-infer-borrow-scope-too-big.rs:13:12 + | +LL | let xc = x_coord(&*p); + | --- `*p` is borrowed here +LL | assert_eq!(*xc, 3); +LL | return xc; + | ^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-infer-borrow-scope-view.rs b/tests/ui/regions/regions-infer-borrow-scope-view.rs new file mode 100644 index 000000000..349b52044 --- /dev/null +++ b/tests/ui/regions/regions-infer-borrow-scope-view.rs @@ -0,0 +1,11 @@ +// run-pass + + +fn view(x: &[T]) -> &[T] {x} + +pub fn main() { + let v = vec![1, 2, 3]; + let x = view(&v); + let y = view(x); + assert!((v[0] == x[0]) && (v[0] == y[0])); +} diff --git a/tests/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs b/tests/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs new file mode 100644 index 000000000..dca26742d --- /dev/null +++ b/tests/ui/regions/regions-infer-borrow-scope-within-loop-ok.rs @@ -0,0 +1,12 @@ +// run-pass + +fn borrow(x: &T) -> &T {x} + +pub fn main() { + let x: Box<_> = Box::new(3); + loop { + let y = borrow(&*x); + assert_eq!(*x, *y); + break; + } +} diff --git a/tests/ui/regions/regions-infer-borrow-scope.rs b/tests/ui/regions/regions-infer-borrow-scope.rs new file mode 100644 index 000000000..b4a050bf1 --- /dev/null +++ b/tests/ui/regions/regions-infer-borrow-scope.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] + +struct Point {x: isize, y: isize} + +fn x_coord(p: &Point) -> &isize { + return &p.x; +} + +pub fn main() { + let p: Box<_> = Box::new(Point {x: 3, y: 4}); + let xc = x_coord(&*p); + assert_eq!(*xc, 3); +} diff --git a/tests/ui/regions/regions-infer-bound-from-trait-self.rs b/tests/ui/regions/regions-infer-bound-from-trait-self.rs new file mode 100644 index 000000000..d15bfffe9 --- /dev/null +++ b/tests/ui/regions/regions-infer-bound-from-trait-self.rs @@ -0,0 +1,51 @@ +// Test that we can derive lifetime bounds on `Self` from trait +// inheritance. + +trait Static : 'static { } + +trait Is<'a> : 'a { } + +struct Inv<'a> { + x: Option<&'a mut &'a isize> +} + +fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { } + +// In these case, `Self` inherits `'static`. + +trait InheritsFromStatic : Sized + 'static { + fn foo1<'a>(self, x: Inv<'a>) { + check_bound(x, self) + } +} +trait InheritsFromStaticIndirectly : Sized + Static { + fn foo1<'a>(self, x: Inv<'a>) { + check_bound(x, self) + } +} + + +// In these case, `Self` inherits `'a`. + +trait InheritsFromIs<'a> : Sized + 'a { + fn foo(self, x: Inv<'a>) { + check_bound(x, self) + } +} + +trait InheritsFromIsIndirectly<'a> : Sized + Is<'a> { + fn foo(self, x: Inv<'a>) { + check_bound(x, self) + } +} + +// In this case, `Self` inherits nothing. + +trait InheritsFromNothing<'a> : Sized { + fn foo(self, x: Inv<'a>) { + check_bound(x, self) + //~^ ERROR parameter type `Self` may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-infer-bound-from-trait-self.stderr b/tests/ui/regions/regions-infer-bound-from-trait-self.stderr new file mode 100644 index 000000000..e88f79a3a --- /dev/null +++ b/tests/ui/regions/regions-infer-bound-from-trait-self.stderr @@ -0,0 +1,12 @@ +error[E0309]: the parameter type `Self` may not live long enough + --> $DIR/regions-infer-bound-from-trait-self.rs:46:9 + | +LL | check_bound(x, self) + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `Self: 'a`... + = note: ...so that the type `Self` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-infer-bound-from-trait.rs b/tests/ui/regions/regions-infer-bound-from-trait.rs new file mode 100644 index 000000000..610452182 --- /dev/null +++ b/tests/ui/regions/regions-infer-bound-from-trait.rs @@ -0,0 +1,40 @@ +// Test that we can derive lifetime bounds on type parameters +// from trait inheritance. + +trait Static : 'static { } + +trait Is<'a> : 'a { } + +struct Inv<'a> { + x: Option<&'a mut &'a isize> +} + +fn check_bound<'a,A:'a>(x: Inv<'a>, a: A) { } + +// In all of these cases, we can derive a bound for A that is longer +// than 'a based on the trait bound of A: + +fn foo1<'a,A:Static>(x: Inv<'a>, a: A) { + check_bound(x, a) +} + +fn foo2<'a,A:Static>(x: Inv<'static>, a: A) { + check_bound(x, a) +} + +fn foo3<'a,A:Is<'a>>(x: Inv<'a>, a: A) { + check_bound(x, a) +} + +// In these cases, there is no trait bound, so we cannot derive any +// bound for A and we get an error: + +fn bar1<'a,A>(x: Inv<'a>, a: A) { + check_bound(x, a) //~ ERROR parameter type `A` may not live long enough +} + +fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) { + check_bound(x, a) //~ ERROR parameter type `A` may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-infer-bound-from-trait.stderr b/tests/ui/regions/regions-infer-bound-from-trait.stderr new file mode 100644 index 000000000..3ee71543d --- /dev/null +++ b/tests/ui/regions/regions-infer-bound-from-trait.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `A` may not live long enough + --> $DIR/regions-infer-bound-from-trait.rs:33:5 + | +LL | check_bound(x, a) + | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn bar1<'a,A: 'a>(x: Inv<'a>, a: A) { + | ++++ + +error[E0309]: the parameter type `A` may not live long enough + --> $DIR/regions-infer-bound-from-trait.rs:37:5 + | +LL | check_bound(x, a) + | ^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn bar2<'a,'b,A:Is<'b> + 'a>(x: Inv<'a>, y: Inv<'b>, a: A) { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/regions/regions-infer-call-2.rs b/tests/ui/regions/regions-infer-call-2.rs new file mode 100644 index 000000000..a288d2e4d --- /dev/null +++ b/tests/ui/regions/regions-infer-call-2.rs @@ -0,0 +1,15 @@ +// run-pass + +fn takes_two(x: &isize, y: &isize) -> isize { *x + *y } + +fn with(f: F) -> T where F: FnOnce(&isize) -> T { + f(&20) +} + +fn has_one<'a>(x: &'a isize) -> isize { + with(|y| takes_two(x, y)) +} + +pub fn main() { + assert_eq!(has_one(&2), 22); +} diff --git a/tests/ui/regions/regions-infer-call-3.rs b/tests/ui/regions/regions-infer-call-3.rs new file mode 100644 index 000000000..063ec8428 --- /dev/null +++ b/tests/ui/regions/regions-infer-call-3.rs @@ -0,0 +1,14 @@ +fn select<'r>(x: &'r isize, y: &'r isize) -> &'r isize { x } + +fn with(f: F) -> T where F: FnOnce(&isize) -> T { + f(&20) +} + +fn manip<'a>(x: &'a isize) -> isize { + let z = with(|y| { select(x, y) }); + //~^ ERROR lifetime may not live long enough + *z +} + +fn main() { +} diff --git a/tests/ui/regions/regions-infer-call-3.stderr b/tests/ui/regions/regions-infer-call-3.stderr new file mode 100644 index 000000000..ca51555a0 --- /dev/null +++ b/tests/ui/regions/regions-infer-call-3.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-call-3.rs:8:24 + | +LL | let z = with(|y| { select(x, y) }); + | -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 isize + | has type `&'1 isize` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-call.rs b/tests/ui/regions/regions-infer-call.rs new file mode 100644 index 000000000..248f9e923 --- /dev/null +++ b/tests/ui/regions/regions-infer-call.rs @@ -0,0 +1,11 @@ +// run-pass + +fn takes_two(x: &isize, y: &isize) -> isize { *x + *y } + +fn has_two<'a,'b>(x: &'a isize, y: &'b isize) -> isize { + takes_two(x, y) +} + +pub fn main() { + assert_eq!(has_two(&20, &2), 22); +} diff --git a/tests/ui/regions/regions-infer-contravariance-due-to-decl.rs b/tests/ui/regions/regions-infer-contravariance-due-to-decl.rs new file mode 100644 index 000000000..fbc0cec56 --- /dev/null +++ b/tests/ui/regions/regions-infer-contravariance-due-to-decl.rs @@ -0,0 +1,29 @@ +// Test that a type which is contravariant with respect to its region +// parameter yields an error when used in a covariant way. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +use std::marker; + +// This is contravariant with respect to 'a, meaning that +// Contravariant<'foo> <: Contravariant<'static> because +// 'foo <= 'static +struct Contravariant<'a> { + marker: marker::PhantomData<&'a()> +} + +fn use_<'short,'long>(c: Contravariant<'short>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + + // Test whether Contravariant<'short> <: Contravariant<'long>. Since + // 'short <= 'long, this would be true if the Contravariant type were + // covariant with respect to its parameter 'a. + + let _: Contravariant<'long> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr b/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr new file mode 100644 index 000000000..94b80852d --- /dev/null +++ b/tests/ui/regions/regions-infer-contravariance-due-to-decl.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-contravariance-due-to-decl.rs:25:12 + | +LL | fn use_<'short,'long>(c: Contravariant<'short>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: Contravariant<'long> = c; + | ^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-contravariance-due-to-ret.rs b/tests/ui/regions/regions-infer-contravariance-due-to-ret.rs new file mode 100644 index 000000000..fbd895015 --- /dev/null +++ b/tests/ui/regions/regions-infer-contravariance-due-to-ret.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(non_camel_case_types)] + + +struct boxed_int<'a> { + f: &'a isize, +} + +fn max<'r>(bi: &'r boxed_int, f: &'r isize) -> isize { + if *bi.f > *f {*bi.f} else {*f} +} + +fn with(bi: &boxed_int) -> isize { + let i = 22; + max(bi, &i) +} + +pub fn main() { + let g = 21; + let foo = boxed_int { f: &g }; + assert_eq!(with(&foo), 22); +} diff --git a/tests/ui/regions/regions-infer-covariance-due-to-decl.rs b/tests/ui/regions/regions-infer-covariance-due-to-decl.rs new file mode 100644 index 000000000..03c0e436e --- /dev/null +++ b/tests/ui/regions/regions-infer-covariance-due-to-decl.rs @@ -0,0 +1,26 @@ +// Test that a type which is covariant with respect to its region +// parameter yields an error when used in a contravariant way. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +use std::marker; + +struct Covariant<'a> { + marker: marker::PhantomData +} + +fn use_<'short,'long>(c: Covariant<'long>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + + // Test whether Covariant<'long> <: Covariant<'short>. Since + // 'short <= 'long, this would be true if the Covariant type were + // contravariant with respect to its parameter 'a. + + let _: Covariant<'short> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr b/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr new file mode 100644 index 000000000..f44a0fad5 --- /dev/null +++ b/tests/ui/regions/regions-infer-covariance-due-to-decl.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-covariance-due-to-decl.rs:22:12 + | +LL | fn use_<'short,'long>(c: Covariant<'long>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: Covariant<'short> = c; + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-invariance-due-to-decl.rs b/tests/ui/regions/regions-infer-invariance-due-to-decl.rs new file mode 100644 index 000000000..102abc0e0 --- /dev/null +++ b/tests/ui/regions/regions-infer-invariance-due-to-decl.rs @@ -0,0 +1,17 @@ +use std::marker; + +struct Invariant<'a> { + marker: marker::PhantomData<*mut &'a()> +} + +fn to_same_lifetime<'r>(b_isize: Invariant<'r>) { + let bj: Invariant<'r> = b_isize; +} + +fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { + b_isize + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr b/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr new file mode 100644 index 000000000..c8c7808e0 --- /dev/null +++ b/tests/ui/regions/regions-infer-invariance-due-to-decl.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-invariance-due-to-decl.rs:12:5 + | +LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { + | -- lifetime `'r` defined here +LL | b_isize + | ^^^^^^^ returning this value requires that `'r` must outlive `'static` + | + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.rs b/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.rs new file mode 100644 index 000000000..c1fb41bd9 --- /dev/null +++ b/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.rs @@ -0,0 +1,15 @@ +struct Invariant<'a> { + f: Box, +} + +fn to_same_lifetime<'r>(b_isize: Invariant<'r>) { + let bj: Invariant<'r> = b_isize; +} + +fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { + b_isize + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr new file mode 100644 index 000000000..1165011c1 --- /dev/null +++ b/tests/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:10:5 + | +LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { + | -- lifetime `'r` defined here +LL | b_isize + | ^^^^^^^ returning this value requires that `'r` must outlive `'static` + | + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.rs b/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.rs new file mode 100644 index 000000000..1078f77a0 --- /dev/null +++ b/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.rs @@ -0,0 +1,15 @@ +struct Invariant<'a> { + f: Box *mut &'a isize + 'static>, +} + +fn to_same_lifetime<'r>(b_isize: Invariant<'r>) { + let bj: Invariant<'r> = b_isize; +} + +fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { + b_isize + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr new file mode 100644 index 000000000..f3973a93b --- /dev/null +++ b/tests/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:10:5 + | +LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { + | -- lifetime `'r` defined here +LL | b_isize + | ^^^^^^^ returning this value requires that `'r` must outlive `'static` + | + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-not-param.rs b/tests/ui/regions/regions-infer-not-param.rs new file mode 100644 index 000000000..c3766bce1 --- /dev/null +++ b/tests/ui/regions/regions-infer-not-param.rs @@ -0,0 +1,24 @@ +struct Direct<'a> { + f: &'a isize +} + +struct Indirect1 { + // Here the lifetime parameter of direct is bound by the fn() + g: Box +} + +struct Indirect2<'a> { + // But here it is set to 'a + g: Box) + 'static> +} + +fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } +//~^ ERROR lifetime may not live long enough + +fn take_indirect1(p: Indirect1) -> Indirect1 { p } + +fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } +//~^ ERROR lifetime may not live long enough +//~| ERROR lifetime may not live long enough + +fn main() {} diff --git a/tests/ui/regions/regions-infer-not-param.stderr b/tests/ui/regions/regions-infer-not-param.stderr new file mode 100644 index 000000000..d12f07a77 --- /dev/null +++ b/tests/ui/regions/regions-infer-not-param.stderr @@ -0,0 +1,40 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-not-param.rs:15:54 + | +LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } + | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | | + | lifetime `'a` defined here + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/regions-infer-not-param.rs:20:63 + | +LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } + | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | | + | lifetime `'a` defined here + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Indirect2<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Indirect2<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/regions-infer-not-param.rs:20:63 + | +LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } + | -- -- lifetime `'b` defined here ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | | + | lifetime `'a` defined here + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Indirect2<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Indirect2<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +help: `'b` and `'a` must be the same: replace one with the other + +error: aborting due to 3 previous errors + diff --git a/tests/ui/regions/regions-infer-paramd-indirect.rs b/tests/ui/regions/regions-infer-paramd-indirect.rs new file mode 100644 index 000000000..978c84e53 --- /dev/null +++ b/tests/ui/regions/regions-infer-paramd-indirect.rs @@ -0,0 +1,27 @@ +// Check that we correctly infer that b and c must be region +// parameterized because they reference a which requires a region. + +type A<'a> = &'a isize; +type B<'a> = Box>; + +struct C<'a> { + f: Box> +} + +trait SetF<'a> { + fn set_f_ok(&mut self, b: Box>); + fn set_f_bad(&mut self, b: Box); +} + +impl<'a> SetF<'a> for C<'a> { + fn set_f_ok(&mut self, b: Box>) { + self.f = b; + } + + fn set_f_bad(&mut self, b: Box) { + self.f = b; + //~^ ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/tests/ui/regions/regions-infer-paramd-indirect.stderr b/tests/ui/regions/regions-infer-paramd-indirect.stderr new file mode 100644 index 000000000..afabdc1de --- /dev/null +++ b/tests/ui/regions/regions-infer-paramd-indirect.stderr @@ -0,0 +1,13 @@ +error: lifetime may not live long enough + --> $DIR/regions-infer-paramd-indirect.rs:22:9 + | +LL | impl<'a> SetF<'a> for C<'a> { + | -- lifetime `'a` defined here +... +LL | fn set_f_bad(&mut self, b: Box) { + | - has type `Box>` +LL | self.f = b; + | ^^^^^^ assignment requires that `'1` must outlive `'a` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-infer-proc-static-upvar.rs b/tests/ui/regions/regions-infer-proc-static-upvar.rs new file mode 100644 index 000000000..5a64aa734 --- /dev/null +++ b/tests/ui/regions/regions-infer-proc-static-upvar.rs @@ -0,0 +1,24 @@ +// Test that, when a variable of type `&T` is captured inside a proc, +// we correctly infer/require that its lifetime is 'static. + +fn foo(_p: F) { } + +static i: isize = 3; + +fn capture_local() { + let x = 3; + let y = &x; //~ ERROR `x` does not live long enough + foo(move|| { + let _a = *y; + }); +} + +fn capture_static() { + // Legal because &i can have static lifetime: + let y = &i; + foo(move|| { + let _a = *y; + }); +} + +fn main() { } diff --git a/tests/ui/regions/regions-infer-proc-static-upvar.stderr b/tests/ui/regions/regions-infer-proc-static-upvar.stderr new file mode 100644 index 000000000..803d0d744 --- /dev/null +++ b/tests/ui/regions/regions-infer-proc-static-upvar.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/regions-infer-proc-static-upvar.rs:10:13 + | +LL | let y = &x; + | ^^ borrowed value does not live long enough +LL | / foo(move|| { +LL | | let _a = *y; +LL | | }); + | |______- argument requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs b/tests/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs new file mode 100644 index 000000000..31a48b4ad --- /dev/null +++ b/tests/ui/regions/regions-infer-reborrow-ref-mut-recurse.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// Test an edge case in region inference: the lifetime of the borrow +// of `*x` must be extended to at least 'a. + +// pretty-expanded FIXME #23616 + +fn foo<'a,'b>(x: &'a &'b mut isize) -> &'a isize { + let y = &*x; // should be inferred to have type &'a &'b mut isize... + + // ...because if we inferred, say, &'x &'b mut isize where 'x <= 'a, + // this reborrow would be illegal: + &**y +} + +pub fn main() { + /* Just want to know that it compiles. */ +} diff --git a/tests/ui/regions/regions-infer-region-in-fn-but-not-type.rs b/tests/ui/regions/regions-infer-region-in-fn-but-not-type.rs new file mode 100644 index 000000000..6aa5d8217 --- /dev/null +++ b/tests/ui/regions/regions-infer-region-in-fn-but-not-type.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_camel_case_types)] + + +// check that the &isize here does not cause us to think that `foo` +// contains region pointers +// pretty-expanded FIXME #23616 + +struct foo(Box); + +fn take_foo(x: T) {} + +fn have_foo(f: foo) { + take_foo(f); +} + +fn main() {} diff --git a/tests/ui/regions/regions-infer-static-from-proc.rs b/tests/ui/regions/regions-infer-static-from-proc.rs new file mode 100644 index 000000000..39501e2d6 --- /dev/null +++ b/tests/ui/regions/regions-infer-static-from-proc.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// Check that the 'static bound on a proc influences lifetimes of +// region variables contained within (otherwise, region inference will +// give `x` a very short lifetime). + +// pretty-expanded FIXME #23616 + +static i: usize = 3; +fn foo(_: F) {} +fn read(_: usize) { } +pub fn main() { + let x = &i; + foo(move|| { + read(*x); + }); +} diff --git a/tests/ui/regions/regions-issue-21422.rs b/tests/ui/regions/regions-issue-21422.rs new file mode 100644 index 000000000..198b71466 --- /dev/null +++ b/tests/ui/regions/regions-issue-21422.rs @@ -0,0 +1,18 @@ +// run-pass +// Regression test for issue #21422, which was related to failing to +// add inference constraints that the operands of a binary operator +// should outlive the binary operation itself. + +// pretty-expanded FIXME #23616 + +pub struct P<'a> { + _ptr: *const &'a u8, +} + +impl <'a> PartialEq for P<'a> { + fn eq(&self, other: &P<'a>) -> bool { + (self as *const _) == (other as *const _) + } +} + +fn main() {} diff --git a/tests/ui/regions/regions-issue-22246.rs b/tests/ui/regions/regions-issue-22246.rs new file mode 100644 index 000000000..085883367 --- /dev/null +++ b/tests/ui/regions/regions-issue-22246.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(unused_imports)] +// Regression test for issue #22246 -- we should be able to deduce +// that `&'a B::Owned` implies that `B::Owned : 'a`. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::ops::Deref; + +pub trait ToOwned: Sized { + type Owned: Borrow; + fn to_owned(&self) -> Self::Owned; +} + +pub trait Borrow { + fn borrow(&self) -> &Borrowed; +} + +pub struct Foo { + owned: B::Owned +} + +fn foo(this: &Foo) -> &B { + this.owned.borrow() +} + +fn main() { } diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs new file mode 100644 index 000000000..177f52fa7 --- /dev/null +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -0,0 +1,30 @@ +fn a<'a, 'b:'a>(x: &mut &'a isize, y: &mut &'b isize) { + // Note: this is legal because of the `'b:'a` declaration. + *x = *y; +} + +fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + // Illegal now because there is no `'b:'a` declaration. + *x = *y; +} + +fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + // Here we try to call `foo` but do not know that `'a` and `'b` are + // related as required. + a(x, y); +} + +fn d() { + // 'a and 'b are early bound in the function `a` because they appear + // inconstraints: + let _: fn(&mut &isize, &mut &isize) = a; + //~^ ERROR mismatched types [E0308] +} + +fn e() { + // 'a and 'b are late bound in the function `b` because there are + // no constraints: + let _: fn(&mut &isize, &mut &isize) = b; +} + +fn main() { } diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr new file mode 100644 index 000000000..17a901943 --- /dev/null +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 + | +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` + found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-lifetime-nonfree-late-bound.rs b/tests/ui/regions/regions-lifetime-nonfree-late-bound.rs new file mode 100644 index 000000000..3852a14d9 --- /dev/null +++ b/tests/ui/regions/regions-lifetime-nonfree-late-bound.rs @@ -0,0 +1,33 @@ +// run-pass +// This is a regression test for the ICE from issue #10846. +// +// The original issue causing the ICE: the LUB-computations during +// type inference were encountering late-bound lifetimes, and +// asserting that such lifetimes should have already been substituted +// with a concrete lifetime. +// +// However, those encounters were occurring within the lexical scope +// of the binding for the late-bound lifetime; that is, the late-bound +// lifetimes were perfectly valid. The core problem was that the type +// folding code was over-zealously passing back all lifetimes when +// doing region-folding, when really all clients of the region-folding +// case only want to see FREE lifetime variables, not bound ones. + +// pretty-expanded FIXME #23616 + +pub fn main() { + fn explicit() { + fn test(_x: Option>) where F: FnMut(Box FnMut(&'a isize)>) {} + test(Some(Box::new(|_f: Box FnMut(&'a isize)>| {}))); + } + + // The code below is shorthand for the code above (and more likely + // to represent what one encounters in practice). + fn implicit() { + fn test(_x: Option>) where F: FnMut(Box) {} + test(Some(Box::new(|_f: Box| {}))); + } + + explicit(); + implicit(); +} diff --git a/tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs b/tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs new file mode 100644 index 000000000..1b25294c7 --- /dev/null +++ b/tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.rs @@ -0,0 +1,26 @@ +// This tests verifies that unary structs and enum variants +// are treated as rvalues and their lifetime is not bounded to +// the static scope. + +fn id(x: T) -> T { x } + +struct Test; + +enum MyEnum { + Variant1 +} + +fn structLifetime<'a>() -> &'a Test { + let testValue = &id(Test); + testValue + //~^ ERROR cannot return value referencing temporary value +} + +fn variantLifetime<'a>() -> &'a MyEnum { + let testValue = &id(MyEnum::Variant1); + testValue + //~^ ERROR cannot return value referencing temporary value +} + + +fn main() {} diff --git a/tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr b/tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr new file mode 100644 index 000000000..b4bf2ab31 --- /dev/null +++ b/tests/ui/regions/regions-lifetime-of-struct-or-enum-variant.stderr @@ -0,0 +1,19 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:15:3 + | +LL | let testValue = &id(Test); + | -------- temporary value created here +LL | testValue + | ^^^^^^^^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/regions-lifetime-of-struct-or-enum-variant.rs:21:3 + | +LL | let testValue = &id(MyEnum::Variant1); + | -------------------- temporary value created here +LL | testValue + | ^^^^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs b/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs new file mode 100644 index 000000000..b6a89e29e --- /dev/null +++ b/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +// This test verifies that temporary lifetime is correctly computed +// for static objects in enclosing scopes. + + +use std::cmp::PartialEq; + +fn f(o: &mut Option) { + assert_eq!(*o, None); +} + +pub fn main() { + mod t { + enum E {V=1, A=0} + static C: E = E::V; + } + + f::(&mut None); +} diff --git a/tests/ui/regions/regions-link-fn-args.rs b/tests/ui/regions/regions-link-fn-args.rs new file mode 100644 index 000000000..231407b22 --- /dev/null +++ b/tests/ui/regions/regions-link-fn-args.rs @@ -0,0 +1,15 @@ +// run-pass +// Test that region inference correctly links up the regions when a +// `ref` borrow occurs inside a fn argument. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +fn with<'a, F>(_: F) where F: FnOnce(&'a Vec) -> &'a Vec { } + +fn foo() { + with(|&ref ints| ints); +} + +fn main() { } diff --git a/tests/ui/regions/regions-lub-ref-ref-rc.rs b/tests/ui/regions/regions-lub-ref-ref-rc.rs new file mode 100644 index 000000000..96c71b084 --- /dev/null +++ b/tests/ui/regions/regions-lub-ref-ref-rc.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +// Test a corner case of LUB coercion. In this case, one arm of the +// match requires a deref coercion and the other doesn't, and there +// is an extra `&` on the `rc`. We want to be sure that the lifetime +// assigned to this `&rc` value is not `'a` but something smaller. In +// other words, the type from `rc` is `&'a Rc` and the type +// from `&rc` should be `&'x &'a Rc`, where `'x` is something +// small. + +use std::rc::Rc; + +#[derive(Clone)] +enum Cached<'mir> { + Ref(&'mir String), + Owned(Rc), +} + +impl<'mir> Cached<'mir> { + fn get_ref<'a>(&'a self) -> &'a String { + match *self { + Cached::Ref(r) => r, + Cached::Owned(ref rc) => &rc, + } + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-mock-codegen.rs b/tests/ui/regions/regions-mock-codegen.rs new file mode 100644 index 000000000..9d0ca76e4 --- /dev/null +++ b/tests/ui/regions/regions-mock-codegen.rs @@ -0,0 +1,54 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +// pretty-expanded FIXME #23616 +#![feature(allocator_api)] + +use std::alloc::{handle_alloc_error, Allocator, Global, Layout}; +use std::ptr::NonNull; + +struct arena(()); + +struct Bcx<'a> { + fcx: &'a Fcx<'a>, +} + +struct Fcx<'a> { + arena: &'a arena, + ccx: &'a Ccx, +} + +struct Ccx { + x: isize, +} + +fn allocate(_bcx: &arena) -> &Bcx<'_> { + unsafe { + let layout = Layout::new::(); + let ptr = Global.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + &*(ptr.as_ptr() as *const _) + } +} + +fn h<'a>(bcx: &'a Bcx<'a>) -> &'a Bcx<'a> { + return allocate(bcx.fcx.arena); +} + +fn g(fcx: &Fcx) { + let bcx = Bcx { fcx }; + let bcx2 = h(&bcx); + unsafe { + Global.deallocate(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::()); + } +} + +fn f(ccx: &Ccx) { + let a = arena(()); + let fcx = Fcx { arena: &a, ccx }; + return g(&fcx); +} + +pub fn main() { + let ccx = Ccx { x: 0 }; + f(&ccx); +} diff --git a/tests/ui/regions/regions-name-duplicated.rs b/tests/ui/regions/regions-name-duplicated.rs new file mode 100644 index 000000000..f6616591a --- /dev/null +++ b/tests/ui/regions/regions-name-duplicated.rs @@ -0,0 +1,6 @@ +struct Foo<'a, 'a> { + //~^ ERROR the name `'a` is already used for a generic parameter + x: &'a isize, +} + +fn main() {} diff --git a/tests/ui/regions/regions-name-duplicated.stderr b/tests/ui/regions/regions-name-duplicated.stderr new file mode 100644 index 000000000..cef73c18d --- /dev/null +++ b/tests/ui/regions/regions-name-duplicated.stderr @@ -0,0 +1,11 @@ +error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters + --> $DIR/regions-name-duplicated.rs:1:16 + | +LL | struct Foo<'a, 'a> { + | -- ^^ already used + | | + | first use of `'a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/regions/regions-name-static.rs b/tests/ui/regions/regions-name-static.rs new file mode 100644 index 000000000..da316c6ef --- /dev/null +++ b/tests/ui/regions/regions-name-static.rs @@ -0,0 +1,6 @@ +struct Foo<'static> { + //~^ ERROR invalid lifetime parameter name: `'static` + x: &'static isize, +} + +fn main() {} diff --git a/tests/ui/regions/regions-name-static.stderr b/tests/ui/regions/regions-name-static.stderr new file mode 100644 index 000000000..4b7026e65 --- /dev/null +++ b/tests/ui/regions/regions-name-static.stderr @@ -0,0 +1,9 @@ +error[E0262]: invalid lifetime parameter name: `'static` + --> $DIR/regions-name-static.rs:1:12 + | +LL | struct Foo<'static> { + | ^^^^^^^ 'static is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0262`. diff --git a/tests/ui/regions/regions-name-undeclared.rs b/tests/ui/regions/regions-name-undeclared.rs new file mode 100644 index 000000000..7b6ede193 --- /dev/null +++ b/tests/ui/regions/regions-name-undeclared.rs @@ -0,0 +1,58 @@ +// edition:2018 +// Check that lifetime resolver enforces the lifetime name scoping +// rules correctly in various scenarios. + +struct Foo<'a> { + x: &'a isize +} + +impl<'a> Foo<'a> { + // &'a is inherited: + fn m1(&self, arg: &'a isize) { } + fn m2(&'a self) { } + fn m3(&self, arg: Foo<'a>) { } + + // &'b is not: + fn m4(&self, arg: &'b isize) { } //~ ERROR undeclared lifetime + fn m5(&'b self) { } //~ ERROR undeclared lifetime + fn m6(&self, arg: Foo<'b>) { } //~ ERROR undeclared lifetime +} + +fn bar<'a>(x: &'a isize) { + // &'a is visible to code: + let y: &'a isize = x; + + // &'a is not visible to *items*: + type X = Option<&'a isize>; //~ ERROR can't use generic parameters from outer item + enum E { + E1(&'a isize) //~ ERROR can't use generic parameters from outer item + } + struct S { + f: &'a isize //~ ERROR can't use generic parameters from outer item + } + fn f(a: &'a isize) { } //~ ERROR can't use generic parameters from outer item + + // &'a CAN be declared on functions and used then: + fn g<'a>(a: &'a isize) { } // OK + fn h(a: Box FnOnce(&'a isize)>) { } // OK +} + +// Test nesting of lifetimes in fn type declarations +fn fn_types(a: &'a isize, //~ ERROR undeclared lifetime + b: Box FnOnce(&'a isize, + &'b isize, //~ ERROR undeclared lifetime + Box FnOnce(&'a isize, + &'b isize)>, + &'b isize)>, //~ ERROR undeclared lifetime + c: &'a isize) //~ ERROR undeclared lifetime +{ +} + +struct Bug {} +impl Bug { + async fn buggy(&self) -> &'a str { //~ ERROR use of undeclared lifetime name `'a` + todo!() + } +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-name-undeclared.stderr b/tests/ui/regions/regions-name-undeclared.stderr new file mode 100644 index 000000000..532603de5 --- /dev/null +++ b/tests/ui/regions/regions-name-undeclared.stderr @@ -0,0 +1,156 @@ +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/regions-name-undeclared.rs:16:24 + | +LL | fn m4(&self, arg: &'b isize) { } + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | fn m4<'b>(&self, arg: &'b isize) { } + | ++++ +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> Foo<'a> { + | +++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/regions-name-undeclared.rs:17:12 + | +LL | fn m5(&'b self) { } + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | fn m5<'b>(&'b self) { } + | ++++ +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> Foo<'a> { + | +++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/regions-name-undeclared.rs:18:27 + | +LL | fn m6(&self, arg: Foo<'b>) { } + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | fn m6<'b>(&self, arg: Foo<'b>) { } + | ++++ +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> Foo<'a> { + | +++ + +error[E0401]: can't use generic parameters from outer item + --> $DIR/regions-name-undeclared.rs:26:22 + | +LL | fn bar<'a>(x: &'a isize) { + | -- lifetime parameter from outer item +... +LL | type X = Option<&'a isize>; + | - ^^ use of generic parameter from outer item + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0401]: can't use generic parameters from outer item + --> $DIR/regions-name-undeclared.rs:28:13 + | +LL | fn bar<'a>(x: &'a isize) { + | -- lifetime parameter from outer item +... +LL | enum E { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | E1(&'a isize) + | ^^ use of generic parameter from outer item + +error[E0401]: can't use generic parameters from outer item + --> $DIR/regions-name-undeclared.rs:31:13 + | +LL | fn bar<'a>(x: &'a isize) { + | -- lifetime parameter from outer item +... +LL | struct S { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | f: &'a isize + | ^^ use of generic parameter from outer item + +error[E0401]: can't use generic parameters from outer item + --> $DIR/regions-name-undeclared.rs:33:14 + | +LL | fn bar<'a>(x: &'a isize) { + | -- lifetime parameter from outer item +... +LL | fn f(a: &'a isize) { } + | - ^^ use of generic parameter from outer item + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-name-undeclared.rs:41:17 + | +LL | fn fn_types(a: &'a isize, + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/regions-name-undeclared.rs:43:36 + | +LL | ... &'b isize, + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | b: Box FnOnce(&'a isize, + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn fn_types<'b>(a: &'a isize, + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/regions-name-undeclared.rs:46:36 + | +LL | ... &'b isize)>, + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | b: Box FnOnce(&'a isize, + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn fn_types<'b>(a: &'a isize, + | ++++ + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-name-undeclared.rs:47:17 + | +LL | fn fn_types(a: &'a isize, + | - help: consider introducing lifetime `'a` here: `<'a>` +... +LL | c: &'a isize) + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-name-undeclared.rs:53:31 + | +LL | async fn buggy(&self) -> &'a str { + | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | async fn buggy<'a>(&self) -> &'a str { + | ++++ +help: consider introducing lifetime `'a` here + | +LL | impl<'a> Bug { + | ++++ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0261, E0401. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/regions/regions-nested-fns-2.rs b/tests/ui/regions/regions-nested-fns-2.rs new file mode 100644 index 000000000..3b3e26c45 --- /dev/null +++ b/tests/ui/regions/regions-nested-fns-2.rs @@ -0,0 +1,12 @@ +fn ignore(_f: F) where F: for<'z> FnOnce(&'z isize) -> &'z isize {} + +fn nested() { + let y = 3; + ignore( + |z| { + if false { &y } else { z } + //~^ ERROR `y` does not live long enough + }); +} + +fn main() {} diff --git a/tests/ui/regions/regions-nested-fns-2.stderr b/tests/ui/regions/regions-nested-fns-2.stderr new file mode 100644 index 000000000..43c8d1272 --- /dev/null +++ b/tests/ui/regions/regions-nested-fns-2.stderr @@ -0,0 +1,17 @@ +error[E0597]: `y` does not live long enough + --> $DIR/regions-nested-fns-2.rs:7:25 + | +LL | |z| { + | --- value captured here +LL | if false { &y } else { z } + | -^ + | || + | |borrowed value does not live long enough + | returning this value requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-nested-fns.rs b/tests/ui/regions/regions-nested-fns.rs new file mode 100644 index 000000000..d9698ced3 --- /dev/null +++ b/tests/ui/regions/regions-nested-fns.rs @@ -0,0 +1,24 @@ +fn ignore(t: T) {} + +fn nested<'x>(x: &'x isize) { + let y = 3; + let mut ay = &y; + //~^ ERROR `y` does not live long enough [E0597] + + ignore:: FnMut(&'z isize)>>(Box::new(|z| { + ay = x; + ay = &y; + //~^ ERROR `y` does not live long enough + ay = z; + //~^ ERROR borrowed data escapes outside of closure [E0521] + })); + + ignore::< Box FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { + if false { return x; } + //~^ ERROR lifetime may not live long enough + if false { return ay; } + return z; + })); +} + +fn main() {} diff --git a/tests/ui/regions/regions-nested-fns.stderr b/tests/ui/regions/regions-nested-fns.stderr new file mode 100644 index 000000000..bb2740310 --- /dev/null +++ b/tests/ui/regions/regions-nested-fns.stderr @@ -0,0 +1,52 @@ +error[E0521]: borrowed data escapes outside of closure + --> $DIR/regions-nested-fns.rs:12:9 + | +LL | let mut ay = &y; + | ------ `ay` declared here, outside of the closure body +... +LL | ignore:: FnMut(&'z isize)>>(Box::new(|z| { + | - `z` is a reference that is only valid in the closure body +... +LL | ay = z; + | ^^^^^^ `z` escapes the closure body here + +error[E0597]: `y` does not live long enough + --> $DIR/regions-nested-fns.rs:5:18 + | +LL | let mut ay = &y; + | ^^ borrowed value does not live long enough +... +LL | if false { return ay; } + | -- returning this value requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/regions-nested-fns.rs:10:15 + | +LL | ignore:: FnMut(&'z isize)>>(Box::new(|z| { + | --- value captured here +LL | ay = x; +LL | ay = &y; + | ^ borrowed value does not live long enough +... +LL | if false { return ay; } + | -- returning this value requires that `y` is borrowed for `'static` +... +LL | } + | - `y` dropped here while still borrowed + +error: lifetime may not live long enough + --> $DIR/regions-nested-fns.rs:17:27 + | +LL | fn nested<'x>(x: &'x isize) { + | -- lifetime `'x` defined here +... +LL | if false { return x; } + | ^ returning this value requires that `'x` must outlive `'static` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0521, E0597. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/regions-no-bound-in-argument-cleanup.rs b/tests/ui/regions/regions-no-bound-in-argument-cleanup.rs new file mode 100644 index 000000000..aafab5d86 --- /dev/null +++ b/tests/ui/regions/regions-no-bound-in-argument-cleanup.rs @@ -0,0 +1,24 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::marker; + +pub struct Foo(marker::PhantomData); + +impl Iterator for Foo { + type Item = T; + + fn next(&mut self) -> Option { + None + } +} + +impl Drop for Foo { + fn drop(&mut self) { + self.next(); + } +} + +pub fn foo<'a>(_: Foo<&'a ()>) {} + +pub fn main() {} diff --git a/tests/ui/regions/regions-no-variance-from-fn-generics.rs b/tests/ui/regions/regions-no-variance-from-fn-generics.rs new file mode 100644 index 000000000..76706a827 --- /dev/null +++ b/tests/ui/regions/regions-no-variance-from-fn-generics.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(unused_variables)] +// Issue #12856: a lifetime formal binding introduced by a generic fn +// should not upset the variance inference for actual occurrences of +// that lifetime in type expressions. + + +pub trait HasLife<'a> { + fn dummy(&'a self) { } // just to induce a variance on 'a +} + +trait UseLife01 { + fn refs<'a, H: HasLife<'a>>(&'a self) -> H; +} + +trait UseLife02 { + fn refs<'a, T: 'a, H: HasType<&'a T>>(&'a self) -> H; +} + + +pub trait HasType +{ + fn dummy(&self, t: T) -> T { panic!() } +} + + +trait UseLife03 { + fn refs<'a, H: HasType<&'a T>>(&'a self) -> H where T: 'a; +} + + +// (The functions below were not actually a problem observed during +// fixing of #12856; they just seem like natural tests to put in to +// cover a couple more points in the testing space) + +pub fn top_refs_1<'a, H: HasLife<'a>>(_s: &'a ()) -> H { + unimplemented!() +} + +pub fn top_refs_2<'a, T: 'a, H: HasType<&'a T>>(_s: &'a ()) -> H { + unimplemented!() +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-normalize-in-where-clause-list.rs b/tests/ui/regions/regions-normalize-in-where-clause-list.rs new file mode 100644 index 000000000..389f82e79 --- /dev/null +++ b/tests/ui/regions/regions-normalize-in-where-clause-list.rs @@ -0,0 +1,31 @@ +// Test that we are able to normalize in the list of where-clauses, +// even if `'a: 'b` is required. + +trait Project<'a, 'b> { + type Item; +} + +impl<'a, 'b> Project<'a, 'b> for () +where + 'a: 'b, +{ + type Item = (); +} + +// No error here, we have 'a: 'b. We used to report an error here +// though, see https://github.com/rust-lang/rust/issues/45937. +fn foo<'a: 'b, 'b>() +where + <() as Project<'a, 'b>>::Item: Eq, +{ +} + +// Here we get an error: we need `'a: 'b`. +fn bar<'a, 'b>() +//~^ ERROR cannot infer +where + <() as Project<'a, 'b>>::Item: Eq, +{ +} + +fn main() {} diff --git a/tests/ui/regions/regions-normalize-in-where-clause-list.stderr b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr new file mode 100644 index 000000000..567283729 --- /dev/null +++ b/tests/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 + | +LL | fn bar<'a, 'b>() + | ^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:8 + | +LL | fn bar<'a, 'b>() + | ^^ +note: ...but the lifetime must also be valid for the lifetime `'b` as defined here... + --> $DIR/regions-normalize-in-where-clause-list.rs:24:12 + | +LL | fn bar<'a, 'b>() + | ^^ +note: ...so that the types are compatible + --> $DIR/regions-normalize-in-where-clause-list.rs:24:4 + | +LL | fn bar<'a, 'b>() + | ^^^ + = note: expected `Project<'a, 'b>` + found `Project<'_, '_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/regions/regions-nullary-variant.rs b/tests/ui/regions/regions-nullary-variant.rs new file mode 100644 index 000000000..82470af82 --- /dev/null +++ b/tests/ui/regions/regions-nullary-variant.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum roption<'a> { + a, b(&'a usize) +} + +fn mk(cond: bool, ptr: &usize) -> roption { + if cond {roption::a} else {roption::b(ptr)} +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs b/tests/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs new file mode 100644 index 000000000..15deaba56 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod rev_variant_struct_region { + struct Foo<'a> { + x: fn(&'a i32), + } + enum Bar<'a,'b> { + V(&'a Foo<'b>) + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-enum-region.rs b/tests/ui/regions/regions-outlives-nominal-type-enum-region.rs new file mode 100644 index 000000000..7767c13c8 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-enum-region.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_struct_region { + struct Foo<'a> { + x: &'a i32, + } + enum Bar<'a,'b> { + V(&'a Foo<'b>) + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs b/tests/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs new file mode 100644 index 000000000..374159942 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_struct_type { + struct Foo { + x: fn(T) + } + enum Bar<'a,'b> { + V(&'a Foo<&'b i32>) + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-enum-type.rs b/tests/ui/regions/regions-outlives-nominal-type-enum-type.rs new file mode 100644 index 000000000..2e7f198d8 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-enum-type.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_struct_type { + struct Foo { + x: T + } + enum Bar<'a,'b> { + V(&'a Foo<&'b i32>) + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs b/tests/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs new file mode 100644 index 000000000..45155c721 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod rev_variant_struct_region { + struct Foo<'a> { + x: fn(&'a i32), + } + struct Bar<'a,'b> { + f: &'a Foo<'b> + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-struct-region.rs b/tests/ui/regions/regions-outlives-nominal-type-struct-region.rs new file mode 100644 index 000000000..bba8b2445 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-struct-region.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_struct_region { + struct Foo<'a> { + x: &'a i32, + } + struct Bar<'a,'b> { + f: &'a Foo<'b> + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs b/tests/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs new file mode 100644 index 000000000..220d2e83c --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod rev_variant_struct_type { + struct Foo { + x: fn(T) + } + struct Bar<'a,'b> { + f: &'a Foo<&'b i32> + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-nominal-type-struct-type.rs b/tests/ui/regions/regions-outlives-nominal-type-struct-type.rs new file mode 100644 index 000000000..9ddcdb649 --- /dev/null +++ b/tests/ui/regions/regions-outlives-nominal-type-struct-type.rs @@ -0,0 +1,20 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + +// check-pass + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +mod variant_struct_type { + struct Foo { + x: T + } + struct Bar<'a,'b> { + f: &'a Foo<&'b i32> + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-projection-container-hrtb.rs b/tests/ui/regions/regions-outlives-projection-container-hrtb.rs new file mode 100644 index 000000000..152eed5ac --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-container-hrtb.rs @@ -0,0 +1,52 @@ +// Test that structs with higher-ranked where clauses don't generate +// "outlives" requirements. Issue #22246. + +#![allow(dead_code)] + +pub trait TheTrait<'b> { + type TheAssocType; +} + +pub struct TheType<'b> { + m: [fn(&'b()); 0] +} + +impl<'a,'b> TheTrait<'a> for TheType<'b> { + type TheAssocType = &'b (); +} + +pub struct WithHrAssoc + where for<'a> T : TheTrait<'a> +{ + m: [T; 0] +} + +fn with_assoc<'a,'b>() { + // We get an error because 'b:'a does not hold: + + let _: &'a WithHrAssoc> = loop { }; + //~^ ERROR lifetime may not live long enough +} + +pub trait TheSubTrait : for<'a> TheTrait<'a> { +} + +impl<'b> TheSubTrait for TheType<'b> { } + +pub struct WithHrAssocSub + where T : TheSubTrait +{ + m: [T; 0] +} + +fn with_assoc_sub<'a,'b>() { + // The error here is just because `'b:'a` must hold for the type + // below to be well-formed, it is not related to the HR relation. + + let _: &'a WithHrAssocSub> = loop { }; + //~^ ERROR lifetime may not live long enough +} + + +fn main() { +} diff --git a/tests/ui/regions/regions-outlives-projection-container-hrtb.stderr b/tests/ui/regions/regions-outlives-projection-container-hrtb.stderr new file mode 100644 index 000000000..6a7c908fa --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-container-hrtb.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:12 + | +LL | fn with_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'a WithHrAssoc> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:12 + | +LL | fn with_assoc_sub<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'a WithHrAssocSub> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/regions/regions-outlives-projection-container-wc.rs b/tests/ui/regions/regions-outlives-projection-container-wc.rs new file mode 100644 index 000000000..4fda7774b --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-container-wc.rs @@ -0,0 +1,35 @@ +// Test that we are imposing the requirement that every associated +// type of a bound that appears in the where clause on a struct must +// outlive the location in which the type appears, even when the +// constraint is in a where clause not a bound. Issue #22246. + +#![allow(dead_code)] + +pub trait TheTrait { + type TheAssocType; +} + +pub struct TheType<'b> { + m: [fn(&'b()); 0] +} + +impl<'b> TheTrait for TheType<'b> { + type TheAssocType = &'b (); +} + +pub struct WithAssoc where T : TheTrait { + m: [T; 0] +} + +fn with_assoc<'a,'b>() { + // For this type to be valid, the rules require that all + // associated types of traits that appear in `WithAssoc` must + // outlive 'a. In this case, that means TheType<'b>::TheAssocType, + // which is &'b (), must outlive 'a. + + let _: &'a WithAssoc> = loop { }; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-outlives-projection-container-wc.stderr b/tests/ui/regions/regions-outlives-projection-container-wc.stderr new file mode 100644 index 000000000..eba2a0d58 --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-container-wc.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container-wc.rs:30:12 + | +LL | fn with_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'a WithAssoc> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-outlives-projection-container.rs b/tests/ui/regions/regions-outlives-projection-container.rs new file mode 100644 index 000000000..7b9829cf8 --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-container.rs @@ -0,0 +1,77 @@ +// Test that we are imposing the requirement that every associated +// type of a bound that appears in the where clause on a struct must +// outlive the location in which the type appears. Issue #22246. + +#![allow(dead_code)] +#![feature(rustc_attrs)] + +pub trait TheTrait { + type TheAssocType; +} + +pub struct TheType<'b> { + m: [fn(&'b()); 0] +} + +impl<'b> TheTrait for TheType<'b> { + type TheAssocType = &'b (); +} + +pub struct WithAssoc { + m: [T; 0] +} + +pub struct WithoutAssoc { + m: [T; 0] +} + +fn with_assoc<'a,'b>() { + // For this type to be valid, the rules require that all + // associated types of traits that appear in `WithAssoc` must + // outlive 'a. In this case, that means TheType<'b>::TheAssocType, + // which is &'b (), must outlive 'a. + + // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if + // `_x` is changed to `_` + let _x: &'a WithAssoc> = loop { }; + //~^ ERROR lifetime may not live long enough +} + +fn with_assoc1<'a,'b>() where 'b : 'a { + // For this type to be valid, the rules require that all + // associated types of traits that appear in `WithAssoc` must + // outlive 'a. In this case, that means TheType<'b>::TheAssocType, + // which is &'b (), must outlive 'a, so 'b : 'a must hold, and + // that is in the where clauses, so we're fine. + + let _x: &'a WithAssoc> = loop { }; +} + +fn without_assoc<'a,'b>() { + // Here there are no associated types but there is a requirement + // that `'b:'a` holds because the `'b` appears in `TheType<'b>`. + + let _x: &'a WithoutAssoc> = loop { }; + //~^ ERROR lifetime may not live long enough +} + +fn call_with_assoc<'a,'b>() { + // As `with_assoc`, but just checking that we impose the same rule + // on the value supplied for the type argument, even when there is + // no data. + + call::<&'a WithAssoc>>(); + //~^ ERROR lifetime may not live long enough +} + +fn call_without_assoc<'a,'b>() { + // As `without_assoc`, but in a distinct scenario. + + call::<&'a WithoutAssoc>>(); + //~^ ERROR lifetime may not live long enough +} + +fn call() { } + +fn main() { +} diff --git a/tests/ui/regions/regions-outlives-projection-container.stderr b/tests/ui/regions/regions-outlives-projection-container.stderr new file mode 100644 index 000000000..d20a2f06a --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-container.stderr @@ -0,0 +1,54 @@ +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container.rs:36:13 + | +LL | fn with_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _x: &'a WithAssoc> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container.rs:54:13 + | +LL | fn without_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _x: &'a WithoutAssoc> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container.rs:63:5 + | +LL | fn call_with_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | call::<&'a WithAssoc>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-outlives-projection-container.rs:70:5 + | +LL | fn call_without_assoc<'a,'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | call::<&'a WithoutAssoc>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/regions/regions-outlives-projection-hrtype.rs b/tests/ui/regions/regions-outlives-projection-hrtype.rs new file mode 100644 index 000000000..5f9700df1 --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-hrtype.rs @@ -0,0 +1,26 @@ +// Test for the outlives relation when applied to a projection on a +// type with bound regions. In this case, we are checking that +// ` fn(&'r T) as TheTrait>::TheType: 'a` If we're not +// careful, we could wind up with a constraint that `'r:'a`, but since +// `'r` is bound, that leads to badness. This test checks that +// everything works. + +// check-pass +#![allow(dead_code)] + +trait TheTrait { + type TheType; +} + +fn wf() { } + +type FnType = for<'r> fn(&'r T); + +fn foo<'a,'b,T>() + where FnType: TheTrait +{ + wf::< as TheTrait>::TheType >(); +} + + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-projection-trait-def.rs b/tests/ui/regions/regions-outlives-projection-trait-def.rs new file mode 100644 index 000000000..5c37a585a --- /dev/null +++ b/tests/ui/regions/regions-outlives-projection-trait-def.rs @@ -0,0 +1,21 @@ +// Test that `>::Type: 'b`, where `trait Foo<'a> { Type: +// 'a; }`, does not require that `F: 'b`. + +// check-pass +#![allow(dead_code)] + +trait SomeTrait<'a> { + type Type: 'a; +} + +impl<'a: 'c, 'c, T> SomeTrait<'a> for &'c T where T: SomeTrait<'a> { + type Type = >::Type; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~ + // | + // Note that this type must outlive 'a, due to the trait + // definition. If we fall back to OutlivesProjectionComponents + // here, then we would require that `T:'a`, which is too strong. +} + + +fn main() { } diff --git a/tests/ui/regions/regions-outlives-scalar.rs b/tests/ui/regions/regions-outlives-scalar.rs new file mode 100644 index 000000000..ce34ffcc8 --- /dev/null +++ b/tests/ui/regions/regions-outlives-scalar.rs @@ -0,0 +1,13 @@ +// Test that scalar values outlive all regions. +// Rule OutlivesScalar from RFC 1214. + +// check-pass +#![allow(dead_code)] + +struct Foo<'a> { + x: &'a i32, + y: &'static i32 +} + + +fn main() { } diff --git a/tests/ui/regions/regions-params.rs b/tests/ui/regions/regions-params.rs new file mode 100644 index 000000000..04f3b8eaf --- /dev/null +++ b/tests/ui/regions/regions-params.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_parens)] + + +fn region_identity(x: &usize) -> &usize { x } + +fn apply(t: T, f: F) -> T where F: FnOnce(T) -> T { f(t) } + +fn parameterized(x: &usize) -> usize { + let z = apply(x, ({|y| + region_identity(y) + })); + *z +} + +pub fn main() { + let x = 3; + assert_eq!(parameterized(&x), 3); +} diff --git a/tests/ui/regions/regions-pattern-typing-issue-19552.rs b/tests/ui/regions/regions-pattern-typing-issue-19552.rs new file mode 100644 index 000000000..a64ab1c85 --- /dev/null +++ b/tests/ui/regions/regions-pattern-typing-issue-19552.rs @@ -0,0 +1,8 @@ +fn assert_static(_t: T) {} + +fn main() { + let line = String::new(); + match [&*line] { //~ ERROR `line` does not live long enough + [ word ] => { assert_static(word); } + } +} diff --git a/tests/ui/regions/regions-pattern-typing-issue-19552.stderr b/tests/ui/regions/regions-pattern-typing-issue-19552.stderr new file mode 100644 index 000000000..f77d94a24 --- /dev/null +++ b/tests/ui/regions/regions-pattern-typing-issue-19552.stderr @@ -0,0 +1,14 @@ +error[E0597]: `line` does not live long enough + --> $DIR/regions-pattern-typing-issue-19552.rs:5:14 + | +LL | match [&*line] { + | ^^^^ borrowed value does not live long enough +LL | [ word ] => { assert_static(word); } + | ------------------- argument requires that `line` is borrowed for `'static` +LL | } +LL | } + | - `line` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-pattern-typing-issue-19997.rs b/tests/ui/regions/regions-pattern-typing-issue-19997.rs new file mode 100644 index 000000000..39190697f --- /dev/null +++ b/tests/ui/regions/regions-pattern-typing-issue-19997.rs @@ -0,0 +1,11 @@ +fn main() { + let a0 = 0; + let f = 1; + let mut a1 = &a0; + match (&a1,) { + (&ref b0,) => { + a1 = &f; //~ ERROR cannot assign to `a1` because it is borrowed + drop(b0); + } + } +} diff --git a/tests/ui/regions/regions-pattern-typing-issue-19997.stderr b/tests/ui/regions/regions-pattern-typing-issue-19997.stderr new file mode 100644 index 000000000..ae60e3c0d --- /dev/null +++ b/tests/ui/regions/regions-pattern-typing-issue-19997.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `a1` because it is borrowed + --> $DIR/regions-pattern-typing-issue-19997.rs:7:13 + | +LL | match (&a1,) { + | --- borrow of `a1` occurs here +LL | (&ref b0,) => { +LL | a1 = &f; + | ^^^^^^^ assignment to borrowed `a1` occurs here +LL | drop(b0); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/regions/regions-proc-bound-capture.rs b/tests/ui/regions/regions-proc-bound-capture.rs new file mode 100644 index 000000000..f79d9dc90 --- /dev/null +++ b/tests/ui/regions/regions-proc-bound-capture.rs @@ -0,0 +1,13 @@ +fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> { + // This is legal, because the region bound on `proc` + // states that it captures `x`. + Box::new(move|| { *x }) +} + +fn static_proc(x: &isize) -> Box (isize) + 'static> { + // This is illegal, because the region bound on `proc` is 'static. + Box::new(move || { *x }) + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-proc-bound-capture.stderr b/tests/ui/regions/regions-proc-bound-capture.stderr new file mode 100644 index 000000000..60c5246e2 --- /dev/null +++ b/tests/ui/regions/regions-proc-bound-capture.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/regions-proc-bound-capture.rs:9:5 + | +LL | fn static_proc(x: &isize) -> Box (isize) + 'static> { + | - let's call the lifetime of this reference `'1` +LL | // This is illegal, because the region bound on `proc` is 'static. +LL | Box::new(move || { *x }) + | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn static_proc(x: &isize) -> Box (isize) + '_> { + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> { + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-reassign-let-bound-pointer.rs b/tests/ui/regions/regions-reassign-let-bound-pointer.rs new file mode 100644 index 000000000..948b11e0f --- /dev/null +++ b/tests/ui/regions/regions-reassign-let-bound-pointer.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] +// Check that the type checker permits us to reassign `z` which +// started out with a longer lifetime and was reassigned to a shorter +// one (it should infer to be the intersection). + +// pretty-expanded FIXME #23616 + +fn foo(x: &isize) { + let a = 1; + let mut z = x; + z = &a; +} + +pub fn main() { + foo(&1); +} diff --git a/tests/ui/regions/regions-reassign-match-bound-pointer.rs b/tests/ui/regions/regions-reassign-match-bound-pointer.rs new file mode 100644 index 000000000..ca52659c4 --- /dev/null +++ b/tests/ui/regions/regions-reassign-match-bound-pointer.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] +// Check that the type checker permits us to reassign `z` which +// started out with a longer lifetime and was reassigned to a shorter +// one (it should infer to be the intersection). + +// pretty-expanded FIXME #23616 + +fn foo(x: &isize) { + let a = 1; + match x { + mut z => { + z = &a; + } + } +} + +pub fn main() { + foo(&1); +} diff --git a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs new file mode 100644 index 000000000..57871b098 --- /dev/null +++ b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.rs @@ -0,0 +1,9 @@ +// Issue #8624. Test for reborrowing with 3 levels, not just two. + +fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize { + &mut ***p + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr new file mode 100644 index 000000000..dc905d076 --- /dev/null +++ b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref-mut-ref.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-reborrow-from-shorter-mut-ref-mut-ref.rs:4:5 + | +LL | fn copy_borrowed_ptr<'a, 'b, 'c>(p: &'a mut &'b mut &'c mut isize) -> &'b mut isize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | &mut ***p + | ^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.rs b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.rs new file mode 100644 index 000000000..88cc54650 --- /dev/null +++ b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.rs @@ -0,0 +1,16 @@ +// Issue #8624. Tests that reborrowing the contents of an `&'b mut` +// pointer which is backed by another `&'a mut` can only be done +// for `'a` (which must be a sublifetime of `'b`). + +fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize { + &mut **p + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let mut x = 1; + let mut y = &mut x; + let z = copy_borrowed_ptr(&mut y); + *y += 1; + *z += 1; +} diff --git a/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr new file mode 100644 index 000000000..c98ec4774 --- /dev/null +++ b/tests/ui/regions/regions-reborrow-from-shorter-mut-ref.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/regions-reborrow-from-shorter-mut-ref.rs:6:5 + | +LL | fn copy_borrowed_ptr<'a, 'b>(p: &'a mut &'b mut isize) -> &'b mut isize { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | &mut **p + | ^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-ref-in-fn-arg.rs b/tests/ui/regions/regions-ref-in-fn-arg.rs new file mode 100644 index 000000000..3df529c9f --- /dev/null +++ b/tests/ui/regions/regions-ref-in-fn-arg.rs @@ -0,0 +1,14 @@ +#![feature(box_patterns)] + + +fn arg_item(box ref x: Box) -> &'static isize { + x //~ ERROR cannot return value referencing function parameter +} + +fn with(f: F) -> R where F: FnOnce(Box) -> R { f(Box::new(3)) } + +fn arg_closure() -> &'static isize { + with(|box ref x| x) //~ ERROR cannot return value referencing function parameter +} + +fn main() {} diff --git a/tests/ui/regions/regions-ref-in-fn-arg.stderr b/tests/ui/regions/regions-ref-in-fn-arg.stderr new file mode 100644 index 000000000..ccba6c59b --- /dev/null +++ b/tests/ui/regions/regions-ref-in-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0515]: cannot return value referencing function parameter + --> $DIR/regions-ref-in-fn-arg.rs:5:5 + | +LL | fn arg_item(box ref x: Box) -> &'static isize { + | --------- function parameter borrowed here +LL | x + | ^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing function parameter + --> $DIR/regions-ref-in-fn-arg.rs:11:22 + | +LL | with(|box ref x| x) + | --------- ^ returns a value referencing data owned by the current function + | | + | function parameter borrowed here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-refcell.rs b/tests/ui/regions/regions-refcell.rs new file mode 100644 index 000000000..39ad0c53f --- /dev/null +++ b/tests/ui/regions/regions-refcell.rs @@ -0,0 +1,45 @@ +// run-pass +// This is a regression test for something that only came up while +// attempting to bootstrap librustc with new destructor lifetime +// semantics. + + +use std::collections::HashMap; +use std::cell::RefCell; + +// This version does not yet work (associated type issues)... +#[cfg(cannot_use_this_yet)] +fn foo<'a>(map: RefCell>) { + let one = [1]; + assert_eq!(map.borrow().get("one"), Some(&one[..])); +} + +#[cfg(cannot_use_this_yet_either)] +// ... and this version does not work (the lifetime of `one` is +// supposed to match the lifetime `'a`) ... +fn foo<'a>(map: RefCell>) { + let one = [1]; + assert_eq!(map.borrow().get("one"), Some(&&one[..])); +} + +#[cfg(all(not(cannot_use_this_yet),not(cannot_use_this_yet_either)))] +fn foo<'a>(map: RefCell>) { + // ...so instead we walk through the trivial slice and make sure + // it contains the element we expect. + + for (i, &x) in map.borrow().get("one").unwrap().iter().enumerate() { + assert_eq!((i, x), (0, 1)); + } +} + +fn main() { + let zer = [0]; + let one = [1]; + let two = [2]; + let mut map = HashMap::new(); + map.insert("zero", &zer[..]); + map.insert("one", &one[..]); + map.insert("two", &two[..]); + let map = RefCell::new(map); + foo(map); +} diff --git a/tests/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs b/tests/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs new file mode 100644 index 000000000..b1bdb813a --- /dev/null +++ b/tests/ui/regions/regions-relate-bound-regions-on-closures-to-inference-variables.rs @@ -0,0 +1,57 @@ +// run-pass +#![allow(dead_code)] +// Test that this fairly specialized, but also reasonable, pattern +// typechecks. The pattern involves regions bound in closures that +// wind up related to inference variables. +// +// NB. Changes to the region implementations have broken this pattern +// a few times, but it happens to be used in the compiler so those +// changes were caught. However, those uses in the compiler could +// easily get changed or refactored away in the future. + +struct Ctxt<'tcx> { + x: &'tcx Vec +} + +struct Foo<'a,'tcx:'a> { + cx: &'a Ctxt<'tcx>, +} + +impl<'a,'tcx> Foo<'a,'tcx> { + fn bother(&mut self) -> isize { + self.elaborate_bounds(Box::new(|this| { + // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`, + // where `'f0` and `'f1` are fresh, free regions that + // result from the bound regions on the closure, and `'2` + // is a region inference variable created by the call. Due + // to the constraints on the type, we find that `'_2 : 'f1 + // + 'f2` must hold (and can be assumed by the callee). + // Region inference has to do some clever stuff to avoid + // inferring `'_2` to be `'static` in this case, because + // it is created outside the closure but then related to + // regions bound by the closure itself. See the + // `region_constraints.rs` file (and the `givens` field, in + // particular) for more details. + this.foo() + })) + } + + fn foo(&mut self) -> isize { + 22 + } + + fn elaborate_bounds( + &mut self, + mut mk_cand: Box FnMut(&mut Foo<'b, 'tcx>) -> isize>) + -> isize + { + mk_cand(self) + } +} + +fn main() { + let v = vec![]; + let cx = Ctxt { x: &v }; + let mut foo = Foo { cx: &cx }; + assert_eq!(foo.bother(), 22); // just so the code is not dead, basically +} diff --git a/tests/ui/regions/regions-ret-borrowed-1.rs b/tests/ui/regions/regions-ret-borrowed-1.rs new file mode 100644 index 000000000..54630caff --- /dev/null +++ b/tests/ui/regions/regions-ret-borrowed-1.rs @@ -0,0 +1,17 @@ +// Similar to regions-ret-borrowed.rs, but using a named lifetime. At +// some point regions-ret-borrowed reported an error but this file did +// not, due to special hardcoding around the anonymous region. + +fn with(f: F) -> R where F: for<'a> FnOnce(&'a isize) -> R { + f(&3) +} + +fn return_it<'a>() -> &'a isize { + with(|o| o) + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let x = return_it(); + println!("foo={}", *x); +} diff --git a/tests/ui/regions/regions-ret-borrowed-1.stderr b/tests/ui/regions/regions-ret-borrowed-1.stderr new file mode 100644 index 000000000..0784e894e --- /dev/null +++ b/tests/ui/regions/regions-ret-borrowed-1.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-ret-borrowed-1.rs:10:14 + | +LL | with(|o| o) + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 isize + | has type `&'1 isize` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-ret-borrowed.rs b/tests/ui/regions/regions-ret-borrowed.rs new file mode 100644 index 000000000..bdb0341c9 --- /dev/null +++ b/tests/ui/regions/regions-ret-borrowed.rs @@ -0,0 +1,20 @@ +// Ensure that you cannot use generic types to return a region outside +// of its bound. Here, in the `return_it()` fn, we call with() but +// with R bound to &isize from the return_it. Meanwhile, with() +// provides a value that is only good within its own stack frame. This +// used to successfully compile because we failed to account for the +// fact that fn(x: &isize) rebound the region &. + +fn with(f: F) -> R where F: FnOnce(&isize) -> R { + f(&3) +} + +fn return_it<'a>() -> &'a isize { + with(|o| o) + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let x = return_it(); + println!("foo={}", *x); +} diff --git a/tests/ui/regions/regions-ret-borrowed.stderr b/tests/ui/regions/regions-ret-borrowed.stderr new file mode 100644 index 000000000..d9be5ef89 --- /dev/null +++ b/tests/ui/regions/regions-ret-borrowed.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/regions-ret-borrowed.rs:13:14 + | +LL | with(|o| o) + | -- ^ returning this value requires that `'1` must outlive `'2` + | || + | |return type of closure is &'2 isize + | has type `&'1 isize` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-ret.rs b/tests/ui/regions/regions-ret.rs new file mode 100644 index 000000000..580545ef8 --- /dev/null +++ b/tests/ui/regions/regions-ret.rs @@ -0,0 +1,8 @@ +fn id(x: T) -> T { x } + +fn f(_x: &isize) -> &isize { + return &id(3); //~ ERROR cannot return reference to temporary value +} + +fn main() { +} diff --git a/tests/ui/regions/regions-ret.stderr b/tests/ui/regions/regions-ret.stderr new file mode 100644 index 000000000..0e4875ac9 --- /dev/null +++ b/tests/ui/regions/regions-ret.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/regions-ret.rs:4:12 + | +LL | return &id(3); + | ^----- + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-return-interior-of-option.rs b/tests/ui/regions/regions-return-interior-of-option.rs new file mode 100644 index 000000000..2dc91ec84 --- /dev/null +++ b/tests/ui/regions/regions-return-interior-of-option.rs @@ -0,0 +1,24 @@ +// run-pass + +fn get(opt: &Option) -> &T { + match *opt { + Some(ref v) => v, + None => panic!("none") + } +} + +pub fn main() { + let mut x = Some(23); + + { + let y = get(&x); + assert_eq!(*y, 23); + } + + x = Some(24); + + { + let y = get(&x); + assert_eq!(*y, 24); + } +} diff --git a/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.rs b/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.rs new file mode 100644 index 000000000..86e759f08 --- /dev/null +++ b/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.rs @@ -0,0 +1,11 @@ +// Test that closures cannot subvert aliasing restrictions + +fn main() { + // Unboxed closure case + { + let mut x = 0; + let mut f = || &mut x; //~ ERROR captured variable cannot escape `FnMut` closure body + let x = f(); + let y = f(); + } +} diff --git a/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr new file mode 100644 index 000000000..b087e03b4 --- /dev/null +++ b/tests/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -0,0 +1,17 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24 + | +LL | let mut x = 0; + | ----- variable defined here +LL | let mut f = || &mut x; + | - ^^^^^- + | | | | + | | | variable captured here + | | returns a reference to a captured variable which escapes the closure body + | inferred to be a `FnMut` closure + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-return-stack-allocated-vec.rs b/tests/ui/regions/regions-return-stack-allocated-vec.rs new file mode 100644 index 000000000..97fbdbf46 --- /dev/null +++ b/tests/ui/regions/regions-return-stack-allocated-vec.rs @@ -0,0 +1,10 @@ +// Test that we cannot return a stack allocated slice + +fn function(x: isize) -> &'static [isize] { + &[x] //~ ERROR cannot return reference to temporary value +} + +fn main() { + let x = function(1); + let y = x[0]; +} diff --git a/tests/ui/regions/regions-return-stack-allocated-vec.stderr b/tests/ui/regions/regions-return-stack-allocated-vec.stderr new file mode 100644 index 000000000..9d87fe266 --- /dev/null +++ b/tests/ui/regions/regions-return-stack-allocated-vec.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return reference to temporary value + --> $DIR/regions-return-stack-allocated-vec.rs:4:5 + | +LL | &[x] + | ^--- + | || + | |temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-scope-chain-example.rs b/tests/ui/regions/regions-scope-chain-example.rs new file mode 100644 index 000000000..2beb20add --- /dev/null +++ b/tests/ui/regions/regions-scope-chain-example.rs @@ -0,0 +1,43 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// This is an example where the older inference algorithm failed. The +// specifics of why it failed are somewhat, but not entirely, tailed +// to the algorithm. Ultimately the problem is that when computing the +// mutual supertype of both sides of the `if` it would be faced with a +// choice of tightening bounds or unifying variables and it took the +// wrong path. The new algorithm avoids this problem and hence this +// example typechecks correctly. + +// pretty-expanded FIXME #23616 + +enum ScopeChain<'a> { + Link(Scope<'a>), + End +} + +type Scope<'a> = &'a ScopeChain<'a>; + +struct OuterContext; + +struct Context<'a> { + foo: &'a OuterContext +} + +impl<'a> Context<'a> { + fn foo(&mut self, scope: Scope) { + let link = if 1 < 2 { + let l = ScopeChain::Link(scope); + self.take_scope(&l); + l + } else { + ScopeChain::Link(scope) + }; + self.take_scope(&link); + } + + fn take_scope(&mut self, x: Scope) { + } +} + +fn main() { } diff --git a/tests/ui/regions/regions-self-impls.rs b/tests/ui/regions/regions-self-impls.rs new file mode 100644 index 000000000..80b88568e --- /dev/null +++ b/tests/ui/regions/regions-self-impls.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(non_camel_case_types)] + +struct Clam<'a> { + chowder: &'a isize +} + +trait get_chowder<'a> { + fn get_chowder(&self) -> &'a isize; +} + +impl<'a> get_chowder<'a> for Clam<'a> { + fn get_chowder(&self) -> &'a isize { return self.chowder; } +} + +pub fn main() { + let clam = Clam { chowder: &3 }; + println!("{}", *clam.get_chowder()); + clam.get_chowder(); +} diff --git a/tests/ui/regions/regions-self-in-enums.rs b/tests/ui/regions/regions-self-in-enums.rs new file mode 100644 index 000000000..c2e4b2ff1 --- /dev/null +++ b/tests/ui/regions/regions-self-in-enums.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + +enum int_wrapper<'a> { + int_wrapper_ctor(&'a isize) +} + +pub fn main() { + let x = 3; + let y = int_wrapper::int_wrapper_ctor(&x); + let mut z : &isize; + match y { + int_wrapper::int_wrapper_ctor(zz) => { z = zz; } + } + println!("{}", *z); +} diff --git a/tests/ui/regions/regions-simple.rs b/tests/ui/regions/regions-simple.rs new file mode 100644 index 000000000..fff1b47f5 --- /dev/null +++ b/tests/ui/regions/regions-simple.rs @@ -0,0 +1,7 @@ +// run-pass +pub fn main() { + let mut x: isize = 3; + let y: &mut isize = &mut x; + *y = 5; + println!("{}", *y); +} diff --git a/tests/ui/regions/regions-static-bound-rpass.rs b/tests/ui/regions/regions-static-bound-rpass.rs new file mode 100644 index 000000000..25232b455 --- /dev/null +++ b/tests/ui/regions/regions-static-bound-rpass.rs @@ -0,0 +1,26 @@ +// run-pass + +fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a () + where 'a: 'static { t } +//~^ WARN unnecessary lifetime parameter `'a` + +fn static_id<'a>(t: &'a ()) -> &'static () + where 'a: 'static { t } +//~^ WARN unnecessary lifetime parameter `'a` + +fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () + where 'a: 'b, 'b: 'static { t } +//~^ WARN unnecessary lifetime parameter `'b` + +fn ref_id<'a>(t: &'a ()) -> &'a () where 'static: 'a { t } + +static UNIT: () = (); + +fn main() +{ + let mut val : &'static () = &UNIT; + invariant_id(&mut val); + static_id(val); + static_id_indirect(val); + ref_id(val); +} diff --git a/tests/ui/regions/regions-static-bound-rpass.stderr b/tests/ui/regions/regions-static-bound-rpass.stderr new file mode 100644 index 000000000..9355a409d --- /dev/null +++ b/tests/ui/regions/regions-static-bound-rpass.stderr @@ -0,0 +1,26 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/regions-static-bound-rpass.rs:4:11 + | +LL | where 'a: 'static { t } + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/regions-static-bound-rpass.rs:8:11 + | +LL | where 'a: 'static { t } + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'b` + --> $DIR/regions-static-bound-rpass.rs:12:19 + | +LL | where 'a: 'b, 'b: 'static { t } + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'b` + +warning: 3 warnings emitted + diff --git a/tests/ui/regions/regions-static-bound.rs b/tests/ui/regions/regions-static-bound.rs new file mode 100644 index 000000000..4d2455470 --- /dev/null +++ b/tests/ui/regions/regions-static-bound.rs @@ -0,0 +1,21 @@ +fn static_id<'a,'b>(t: &'a ()) -> &'static () + where 'a: 'static { t } +//~^ WARN unnecessary lifetime parameter `'a` + +fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () + where 'a: 'b, 'b: 'static { t } +//~^ WARN unnecessary lifetime parameter `'b` + +fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { + t + //~^ ERROR lifetime may not live long enough +} + +fn error(u: &(), v: &()) { + static_id(&u); + //~^ ERROR borrowed data escapes outside of function [E0521] + static_id_indirect(&v); + //~^ ERROR borrowed data escapes outside of function [E0521] +} + +fn main() {} diff --git a/tests/ui/regions/regions-static-bound.stderr b/tests/ui/regions/regions-static-bound.stderr new file mode 100644 index 000000000..2886ec3ea --- /dev/null +++ b/tests/ui/regions/regions-static-bound.stderr @@ -0,0 +1,54 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/regions-static-bound.rs:2:11 + | +LL | where 'a: 'static { t } + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'b` + --> $DIR/regions-static-bound.rs:6:19 + | +LL | where 'a: 'b, 'b: 'static { t } + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'b` + +error: lifetime may not live long enough + --> $DIR/regions-static-bound.rs:10:5 + | +LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { + | -- lifetime `'a` defined here +LL | t + | ^ returning this value requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/regions-static-bound.rs:15:5 + | +LL | fn error(u: &(), v: &()) { + | - - let's call the lifetime of this reference `'1` + | | + | `u` is a reference that is only valid in the function body +LL | static_id(&u); + | ^^^^^^^^^^^^^ + | | + | `u` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/regions-static-bound.rs:17:5 + | +LL | fn error(u: &(), v: &()) { + | - - let's call the lifetime of this reference `'2` + | | + | `v` is a reference that is only valid in the function body +... +LL | static_id_indirect(&v); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `v` escapes the function body here + | argument requires that `'2` must outlive `'static` + +error: aborting due to 3 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/regions-static-closure.rs b/tests/ui/regions/regions-static-closure.rs new file mode 100644 index 000000000..09cd56220 --- /dev/null +++ b/tests/ui/regions/regions-static-closure.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(non_camel_case_types)] + +struct closure_box<'a> { + cl: Box, +} + +fn box_it<'a>(x: Box) -> closure_box<'a> { + closure_box {cl: x} +} + +fn call_static_closure(mut cl: closure_box<'static>) { + (cl.cl)(); +} + +pub fn main() { + let cl_box = box_it(Box::new(|| println!("Hello, world!"))); + call_static_closure(cl_box); +} diff --git a/tests/ui/regions/regions-steal-closure.rs b/tests/ui/regions/regions-steal-closure.rs new file mode 100644 index 000000000..83e93522c --- /dev/null +++ b/tests/ui/regions/regions-steal-closure.rs @@ -0,0 +1,17 @@ +#![feature(fn_traits)] + +struct ClosureBox<'a> { + cl: Box, +} + +fn box_it<'r>(x: Box) -> ClosureBox<'r> { + ClosureBox {cl: x} +} + +fn main() { + let mut cl_box = { + let mut i = 3; + box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough + }; + cl_box.cl.call_mut(()); +} diff --git a/tests/ui/regions/regions-steal-closure.stderr b/tests/ui/regions/regions-steal-closure.stderr new file mode 100644 index 000000000..5b0efaf95 --- /dev/null +++ b/tests/ui/regions/regions-steal-closure.stderr @@ -0,0 +1,16 @@ +error[E0597]: `i` does not live long enough + --> $DIR/regions-steal-closure.rs:14:28 + | +LL | let mut cl_box = { + | ---------- borrow later stored here +LL | let mut i = 3; +LL | box_it(Box::new(|| i += 1)) + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | }; + | - `i` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/regions/regions-trait-1.rs b/tests/ui/regions/regions-trait-1.rs new file mode 100644 index 000000000..b6dab1c32 --- /dev/null +++ b/tests/ui/regions/regions-trait-1.rs @@ -0,0 +1,33 @@ +// check-pass + +struct Ctxt { + v: usize, +} + +trait GetCtxt { + // Here the `&` is bound in the method definition: + fn get_ctxt(&self) -> &Ctxt; +} + +struct HasCtxt<'a> { + c: &'a Ctxt, +} + +impl<'a> GetCtxt for HasCtxt<'a> { + // Ok: Have implied bound of WF(&'b HasCtxt<'a>) + // so know 'a: 'b + // so know &'a Ctxt <: &'b Ctxt + fn get_ctxt<'b>(&'b self) -> &'a Ctxt { + self.c + } +} + +fn get_v(gc: Box) -> usize { + gc.get_ctxt().v +} + +fn main() { + let ctxt = Ctxt { v: 22 }; + let hc = HasCtxt { c: &ctxt }; + assert_eq!(get_v(Box::new(hc) as Box), 22); +} diff --git a/tests/ui/regions/regions-trait-object-1.rs b/tests/ui/regions/regions-trait-object-1.rs new file mode 100644 index 000000000..e2520d978 --- /dev/null +++ b/tests/ui/regions/regions-trait-object-1.rs @@ -0,0 +1,35 @@ +// run-pass +// This is a regression test for something that only came up while +// attempting to bootstrap librustc_ast; it is adapted from +// `rustc_ast::ext::tt::generic_extension`. + + +pub struct E<'a> { + pub f: &'a u8, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b u8 { self.f } +} + +pub struct P<'c> { + pub g: &'c u8, +} +pub trait M { + fn n(&self) -> u8; +} +impl<'d> M for P<'d> { + fn n(&self) -> u8 { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return Box::new(p) as Box; + } +} + +fn main() { + let w = E { f: &10 }; + let o = extension(&w); + assert_eq!(o.n(), 10); +} diff --git a/tests/ui/regions/regions-trait-object-subtyping.rs b/tests/ui/regions/regions-trait-object-subtyping.rs new file mode 100644 index 000000000..1d7a766de --- /dev/null +++ b/tests/ui/regions/regions-trait-object-subtyping.rs @@ -0,0 +1,26 @@ +trait Dummy { fn dummy(&self); } + +fn foo1<'a:'b,'b>(x: &'a mut (dyn Dummy+'a)) -> &'b mut (dyn Dummy+'b) { + // Here, we are able to coerce + x +} + +fn foo2<'a:'b,'b>(x: &'b mut (dyn Dummy+'a)) -> &'b mut (dyn Dummy+'b) { + // Here, we are able to coerce + x +} + +fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { + // Without knowing 'a:'b, we can't coerce + x + //~^ ERROR lifetime may not live long enough +} + +struct Wrapper(T); +fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { + // We can't coerce because it is packed in `Wrapper` + x + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-trait-object-subtyping.stderr b/tests/ui/regions/regions-trait-object-subtyping.stderr new file mode 100644 index 000000000..1b3a116d5 --- /dev/null +++ b/tests/ui/regions/regions-trait-object-subtyping.stderr @@ -0,0 +1,34 @@ +error: lifetime may not live long enough + --> $DIR/regions-trait-object-subtyping.rs:15:5 + | +LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Without knowing 'a:'b, we can't coerce +LL | x + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to `dyn Dummy` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/regions-trait-object-subtyping.rs:22:5 + | +LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // We can't coerce because it is packed in `Wrapper` +LL | x + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `dyn Dummy` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 2 previous errors + diff --git a/tests/ui/regions/regions-trait-variance.rs b/tests/ui/regions/regions-trait-variance.rs new file mode 100644 index 000000000..94ffb85c9 --- /dev/null +++ b/tests/ui/regions/regions-trait-variance.rs @@ -0,0 +1,44 @@ +// Issue #12470. + +trait X { + fn get_i(&self) -> isize; +} + +struct B { + i: isize +} + +impl X for B { + fn get_i(&self) -> isize { + self.i + } +} + +impl Drop for B { + fn drop(&mut self) { + println!("drop"); + } +} + +struct A<'r> { + p: &'r (dyn X + 'r) +} + +fn make_a(p: &dyn X) -> A { + A{p:p} +} + +fn make_make_a<'a>() -> A<'a> { + + let b: Box = Box::new(B { + i: 1, + }); + + let bb: &B = &*b; + make_a(bb) //~ ERROR cannot return value referencing local data `*b` +} + +fn main() { + let a = make_make_a(); + println!("{}", a.p.get_i()); +} diff --git a/tests/ui/regions/regions-trait-variance.stderr b/tests/ui/regions/regions-trait-variance.stderr new file mode 100644 index 000000000..56c9f89e1 --- /dev/null +++ b/tests/ui/regions/regions-trait-variance.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing local data `*b` + --> $DIR/regions-trait-variance.rs:38:5 + | +LL | let bb: &B = &*b; + | --- `*b` is borrowed here +LL | make_a(bb) + | ^^^^^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/regions/regions-undeclared.rs b/tests/ui/regions/regions-undeclared.rs new file mode 100644 index 000000000..1edd998aa --- /dev/null +++ b/tests/ui/regions/regions-undeclared.rs @@ -0,0 +1,13 @@ +static c_x: &'blk isize = &22; //~ ERROR use of undeclared lifetime name `'blk` + +enum EnumDecl { + Foo(&'a isize), //~ ERROR use of undeclared lifetime name `'a` + Bar(&'a isize), //~ ERROR use of undeclared lifetime name `'a` +} + +fn fnDecl(x: &'a isize, //~ ERROR use of undeclared lifetime name `'a` + y: &'a isize) //~ ERROR use of undeclared lifetime name `'a` +{} + +fn main() { +} diff --git a/tests/ui/regions/regions-undeclared.stderr b/tests/ui/regions/regions-undeclared.stderr new file mode 100644 index 000000000..6bfde5524 --- /dev/null +++ b/tests/ui/regions/regions-undeclared.stderr @@ -0,0 +1,42 @@ +error[E0261]: use of undeclared lifetime name `'blk` + --> $DIR/regions-undeclared.rs:1:14 + | +LL | static c_x: &'blk isize = &22; + | ^^^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-undeclared.rs:4:10 + | +LL | enum EnumDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | Foo(&'a isize), + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-undeclared.rs:5:10 + | +LL | enum EnumDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | Foo(&'a isize), +LL | Bar(&'a isize), + | ^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-undeclared.rs:8:15 + | +LL | fn fnDecl(x: &'a isize, + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` + +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/regions-undeclared.rs:9:15 + | +LL | fn fnDecl(x: &'a isize, + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | y: &'a isize) + | ^^ undeclared lifetime + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/regions/regions-var-type-out-of-scope.rs b/tests/ui/regions/regions-var-type-out-of-scope.rs new file mode 100644 index 000000000..aba55e9df --- /dev/null +++ b/tests/ui/regions/regions-var-type-out-of-scope.rs @@ -0,0 +1,14 @@ +fn id(x: T) -> T { x } + +fn foo(cond: bool) { + // Here we will infer a type that uses the + // region of the if stmt then block: + let mut x; + + if cond { + x = &id(3); //~ ERROR temporary value dropped while borrowed + assert_eq!(*x, 3); + } +} + +fn main() {} diff --git a/tests/ui/regions/regions-var-type-out-of-scope.stderr b/tests/ui/regions/regions-var-type-out-of-scope.stderr new file mode 100644 index 000000000..c32bbe0ee --- /dev/null +++ b/tests/ui/regions/regions-var-type-out-of-scope.stderr @@ -0,0 +1,15 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/regions-var-type-out-of-scope.rs:9:14 + | +LL | x = &id(3); + | ^^^^^- temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | assert_eq!(*x, 3); + | ----------------- borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/regions/regions-variance-contravariant-use-contravariant.rs b/tests/ui/regions/regions-variance-contravariant-use-contravariant.rs new file mode 100644 index 000000000..e63778670 --- /dev/null +++ b/tests/ui/regions/regions-variance-contravariant-use-contravariant.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that a type which is contravariant with respect to its region +// parameter compiles successfully when used in a contravariant way. +// +// Note: see ui/variance/variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +// pretty-expanded FIXME #23616 + +struct Contravariant<'a> { + f: &'a isize +} + +fn use_<'a>(c: Contravariant<'a>) { + let x = 3; + + // 'b winds up being inferred to this call. + // Contravariant<'a> <: Contravariant<'call> is true + // if 'call <= 'a, which is true, so no error. + collapse(&x, c); + + fn collapse<'b>(x: &'b isize, c: Contravariant<'b>) { } +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs b/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs new file mode 100644 index 000000000..f23ca537f --- /dev/null +++ b/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.rs @@ -0,0 +1,29 @@ +// Test that a type which is covariant with respect to its region +// parameter yields an error when used in a contravariant way. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +// `S` is contravariant with respect to both parameters. +struct S<'a, 'b> { + f: &'a isize, + g: &'b isize, +} + +fn use_<'short,'long>(c: S<'long, 'short>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + + let _: S<'long, 'short> = c; // OK + let _: S<'short, 'short> = c; // OK + + // Test whether S<_,'short> <: S<_,'long>. Since + // 'short <= 'long, this would be true if the Contravariant type were + // covariant with respect to its parameter 'a. + + let _: S<'long, 'long> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr b/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr new file mode 100644 index 000000000..5352be430 --- /dev/null +++ b/tests/ui/regions/regions-variance-contravariant-use-covariant-in-second-position.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-variance-contravariant-use-covariant-in-second-position.rs:25:12 + | +LL | fn use_<'short,'long>(c: S<'long, 'short>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: S<'long, 'long> = c; + | ^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-variance-contravariant-use-covariant.rs b/tests/ui/regions/regions-variance-contravariant-use-covariant.rs new file mode 100644 index 000000000..c73577cb3 --- /dev/null +++ b/tests/ui/regions/regions-variance-contravariant-use-covariant.rs @@ -0,0 +1,27 @@ +// Test that a type which is covariant with respect to its region +// parameter yields an error when used in a contravariant way. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +// This is contravariant with respect to 'a, meaning that +// Contravariant<'long> <: Contravariant<'short> iff +// 'short <= 'long +struct Contravariant<'a> { + f: &'a isize +} + +fn use_<'short,'long>(c: Contravariant<'short>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + + // Test whether Contravariant<'short> <: Contravariant<'long>. Since + // 'short <= 'long, this would be true if the Contravariant type were + // covariant with respect to its parameter 'a. + + let _: Contravariant<'long> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr b/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr new file mode 100644 index 000000000..22c9b915b --- /dev/null +++ b/tests/ui/regions/regions-variance-contravariant-use-covariant.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-variance-contravariant-use-covariant.rs:23:12 + | +LL | fn use_<'short,'long>(c: Contravariant<'short>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: Contravariant<'long> = c; + | ^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-variance-covariant-use-contravariant.rs b/tests/ui/regions/regions-variance-covariant-use-contravariant.rs new file mode 100644 index 000000000..a2183b491 --- /dev/null +++ b/tests/ui/regions/regions-variance-covariant-use-contravariant.rs @@ -0,0 +1,27 @@ +// Test that a type which is covariant with respect to its region +// parameter yields an error when used in a contravariant way. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +// This is covariant with respect to 'a, meaning that +// Covariant<'foo> <: Covariant<'static> because +// 'foo <= 'static +struct Covariant<'a> { + f: extern "Rust" fn(&'a isize) +} + +fn use_<'short,'long>(c: Covariant<'long>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + + // Test whether Covariant<'long> <: Covariant<'short>. Since + // 'short <= 'long, this would be true if the Covariant type were + // contravariant with respect to its parameter 'a. + + let _: Covariant<'short> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr b/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr new file mode 100644 index 000000000..a07181ad5 --- /dev/null +++ b/tests/ui/regions/regions-variance-covariant-use-contravariant.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-variance-covariant-use-contravariant.rs:23:12 + | +LL | fn use_<'short,'long>(c: Covariant<'long>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: Covariant<'short> = c; + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-variance-covariant-use-covariant.rs b/tests/ui/regions/regions-variance-covariant-use-covariant.rs new file mode 100644 index 000000000..c5c80ce54 --- /dev/null +++ b/tests/ui/regions/regions-variance-covariant-use-covariant.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +// Test that a type which is covariant with respect to its region +// parameter is successful when used in a covariant way. +// +// Note: see ui/variance/variance-regions-*.rs for the tests that +// check that the variance inference works in the first place. + +// This is covariant with respect to 'a, meaning that +// Covariant<'foo> <: Covariant<'static> because +// 'foo <= 'static +// pretty-expanded FIXME #23616 + +struct Covariant<'a> { + f: extern "Rust" fn(&'a isize) +} + +fn use_<'a>(c: Covariant<'a>) { + // OK Because Covariant<'a> <: Covariant<'static> iff 'a <= 'static + let _: Covariant<'static> = c; +} + +pub fn main() {} diff --git a/tests/ui/regions/regions-variance-invariant-use-contravariant.rs b/tests/ui/regions/regions-variance-invariant-use-contravariant.rs new file mode 100644 index 000000000..a81aaa9c7 --- /dev/null +++ b/tests/ui/regions/regions-variance-invariant-use-contravariant.rs @@ -0,0 +1,24 @@ +// Test that an invariant region parameter used in a contravariant way +// yields an error. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +struct Invariant<'a> { + f: &'a mut &'a isize +} + +fn use_<'short,'long>(c: Invariant<'long>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + + // Test whether Invariant<'long> <: Invariant<'short>. Since + // 'short <= 'long, this would be true if the Invariant type were + // contravariant with respect to its parameter 'a. + + let _: Invariant<'short> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr b/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr new file mode 100644 index 000000000..b35a2cb90 --- /dev/null +++ b/tests/ui/regions/regions-variance-invariant-use-contravariant.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/regions-variance-invariant-use-contravariant.rs:20:12 + | +LL | fn use_<'short,'long>(c: Invariant<'long>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: Invariant<'short> = c; + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-variance-invariant-use-covariant.rs b/tests/ui/regions/regions-variance-invariant-use-covariant.rs new file mode 100644 index 000000000..ab6a82ee7 --- /dev/null +++ b/tests/ui/regions/regions-variance-invariant-use-covariant.rs @@ -0,0 +1,21 @@ +// Test that a type which is invariant with respect to its region +// parameter used in a covariant way yields an error. +// +// Note: see variance-regions-*.rs for the tests that check that the +// variance inference works in the first place. + +struct Invariant<'a> { + f: &'a mut &'a isize +} + +fn use_<'b>(c: Invariant<'b>) { + + // For this assignment to be legal, Invariant<'b> <: Invariant<'static>. + // Since 'b <= 'static, this would be true if Invariant were covariant + // with respect to its parameter 'a. + + let _: Invariant<'static> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/regions/regions-variance-invariant-use-covariant.stderr b/tests/ui/regions/regions-variance-invariant-use-covariant.stderr new file mode 100644 index 000000000..761e78d17 --- /dev/null +++ b/tests/ui/regions/regions-variance-invariant-use-covariant.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/regions-variance-invariant-use-covariant.rs:17:12 + | +LL | fn use_<'b>(c: Invariant<'b>) { + | -- lifetime `'b` defined here +... +LL | let _: Invariant<'static> = c; + | ^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'static` + | + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/regions/regions-wf-trait-object.rs b/tests/ui/regions/regions-wf-trait-object.rs new file mode 100644 index 000000000..d0053b202 --- /dev/null +++ b/tests/ui/regions/regions-wf-trait-object.rs @@ -0,0 +1,10 @@ +// Check that the explicit lifetime bound (`'b`, in this example) must +// outlive all the superbound from the trait (`'a`, in this example). + +trait TheTrait<'t>: 't { } + +struct Foo<'a,'b> { + x: Box+'b> //~ ERROR E0478 +} + +fn main() { } diff --git a/tests/ui/regions/regions-wf-trait-object.stderr b/tests/ui/regions/regions-wf-trait-object.stderr new file mode 100644 index 000000000..f6006ca04 --- /dev/null +++ b/tests/ui/regions/regions-wf-trait-object.stderr @@ -0,0 +1,20 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/regions-wf-trait-object.rs:7:8 + | +LL | x: Box+'b> + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'b` as defined here + --> $DIR/regions-wf-trait-object.rs:6:15 + | +LL | struct Foo<'a,'b> { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined here + --> $DIR/regions-wf-trait-object.rs:6:12 + | +LL | struct Foo<'a,'b> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs b/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs new file mode 100644 index 000000000..a65c17e0e --- /dev/null +++ b/tests/ui/regions/type-param-outlives-reempty-issue-74429-2.rs @@ -0,0 +1,66 @@ +// Regression test for #74429, where we didn't think that a type parameter +// outlived `ReEmpty`. + +// check-pass + +use std::marker::PhantomData; +use std::ptr::NonNull; + +pub unsafe trait RawData { + type Elem; +} + +unsafe impl RawData for OwnedRepr { + type Elem = A; +} + +unsafe impl<'a, A> RawData for ViewRepr<&'a A> { + type Elem = A; +} + +pub struct OwnedRepr { + ptr: PhantomData, +} + +// these Copy impls are not necessary for the repro, but allow the code to compile without error +// on 1.44.1 +#[derive(Copy, Clone)] +pub struct ViewRepr { + life: PhantomData, +} + +#[derive(Copy, Clone)] +pub struct ArrayBase +where + S: RawData, +{ + ptr: NonNull, +} + +pub type Array = ArrayBase>; + +pub type ArrayView<'a, A> = ArrayBase>; + +impl ArrayBase +where + S: RawData, +{ + pub fn index_axis(&self) -> ArrayView<'_, A> { + unimplemented!() + } + + pub fn axis_iter<'a>(&'a self) -> std::iter::Empty<&'a A> { + unimplemented!() + } +} + +pub fn x(a: Array) { + // drop just avoids a must_use warning + drop((0..1).filter(|_| true)); + let y = a.index_axis(); + a.axis_iter().for_each(|_| { + drop(y); + }); +} + +fn main() {} diff --git a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs new file mode 100644 index 000000000..d463f311c --- /dev/null +++ b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs @@ -0,0 +1,35 @@ +// Regression test for #74429, where we didn't think that a type parameter +// outlived `ReEmpty`. + +// check-pass + +use std::marker::PhantomData; + +fn apply(_: T, _: F) {} + +#[derive(Clone, Copy)] +struct Invariant { + t: T, + p: PhantomData T>, +} + +fn verify_reempty(x: T) { + // r is inferred to have type `Invariant<&ReEmpty(U0) T>` + let r = Invariant { t: &x, p: PhantomData }; + // Creates a new universe, all variables from now on are in `U1`, say. + let _: fn(&()) = |_| {}; + // Closure parameter is of type `&ReEmpty(U1) T`, so the closure has an implied + // bound of `T: ReEmpty(U1)` + apply(&x, |_| { + // Requires `typeof(r)` is well-formed, i.e. `T: ReEmpty(U0)`. If we + // only have the implied bound from the closure parameter to use this + // requires `ReEmpty(U1): ReEmpty(U0)`, which isn't true so we reported + // an error. + // + // This doesn't happen any more because we ensure that `T: ReEmpty(U0)` + // is an implicit bound for all type parameters. + drop(r); + }); +} + +fn main() {} diff --git a/tests/ui/regions/wf-bound-region-in-object-type.rs b/tests/ui/regions/wf-bound-region-in-object-type.rs new file mode 100644 index 000000000..7c4dd3ec8 --- /dev/null +++ b/tests/ui/regions/wf-bound-region-in-object-type.rs @@ -0,0 +1,22 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that the `wf` checker properly handles bound regions in object +// types. Compiling this code used to trigger an ICE. + +// pretty-expanded FIXME #23616 + +pub struct Context<'tcx> { + vec: &'tcx Vec +} + +pub type Cmd<'a> = &'a isize; + +pub type DecodeInlinedItem<'a> = + Box FnMut(Cmd, &Context<'tcx>) -> Result<&'tcx isize, ()> + 'a>; + +fn foo(d: DecodeInlinedItem) { +} + +fn main() { } diff --git a/tests/ui/reify-intrinsic.rs b/tests/ui/reify-intrinsic.rs new file mode 100644 index 000000000..9eb2f7240 --- /dev/null +++ b/tests/ui/reify-intrinsic.rs @@ -0,0 +1,23 @@ +// check-fail + +#![feature(core_intrinsics, intrinsics)] + +fn a() { + let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + //~^ ERROR cannot coerce +} + +fn b() { + let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + //~^ ERROR casting +} + +fn c() { + let _ = [ + std::intrinsics::likely, + std::intrinsics::unlikely, + //~^ ERROR cannot coerce + ]; +} + +fn main() {} diff --git a/tests/ui/reify-intrinsic.stderr b/tests/ui/reify-intrinsic.stderr new file mode 100644 index 000000000..f78f1d822 --- /dev/null +++ b/tests/ui/reify-intrinsic.stderr @@ -0,0 +1,33 @@ +error[E0308]: cannot coerce intrinsics to function pointers + --> $DIR/reify-intrinsic.rs:6:64 + | +LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + | ------------------------------------------------- ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers + | | + | expected due to this + | + = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` + found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid + --> $DIR/reify-intrinsic.rs:11:13 + | +LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: cannot coerce intrinsics to function pointers + --> $DIR/reify-intrinsic.rs:18:9 + | +LL | std::intrinsics::unlikely, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers + | + = note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}` + found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}` + = note: different `fn` items always have unique types, even if their signatures are the same + = help: change the expected type to be function pointer `extern "rust-intrinsic" fn(bool) -> bool` + = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `likely as extern "rust-intrinsic" fn(bool) -> bool` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0606. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/removing-extern-crate.fixed b/tests/ui/removing-extern-crate.fixed new file mode 100644 index 000000000..8dbd0395b --- /dev/null +++ b/tests/ui/removing-extern-crate.fixed @@ -0,0 +1,16 @@ +// edition:2018 +// aux-build:removing-extern-crate.rs +// run-rustfix +// check-pass + +#![warn(rust_2018_idioms)] + + //~ WARNING unused extern crate + //~ WARNING unused extern crate + +mod another { + //~ WARNING unused extern crate + //~ WARNING unused extern crate +} + +fn main() {} diff --git a/tests/ui/removing-extern-crate.rs b/tests/ui/removing-extern-crate.rs new file mode 100644 index 000000000..465e1360c --- /dev/null +++ b/tests/ui/removing-extern-crate.rs @@ -0,0 +1,16 @@ +// edition:2018 +// aux-build:removing-extern-crate.rs +// run-rustfix +// check-pass + +#![warn(rust_2018_idioms)] + +extern crate removing_extern_crate as foo; //~ WARNING unused extern crate +extern crate core; //~ WARNING unused extern crate + +mod another { + extern crate removing_extern_crate as foo; //~ WARNING unused extern crate + extern crate core; //~ WARNING unused extern crate +} + +fn main() {} diff --git a/tests/ui/removing-extern-crate.stderr b/tests/ui/removing-extern-crate.stderr new file mode 100644 index 000000000..4dddf160c --- /dev/null +++ b/tests/ui/removing-extern-crate.stderr @@ -0,0 +1,33 @@ +warning: unused extern crate + --> $DIR/removing-extern-crate.rs:8:1 + | +LL | extern crate removing_extern_crate as foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/removing-extern-crate.rs:6:9 + | +LL | #![warn(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]` + +warning: unused extern crate + --> $DIR/removing-extern-crate.rs:9:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ help: remove it + +warning: unused extern crate + --> $DIR/removing-extern-crate.rs:12:5 + | +LL | extern crate removing_extern_crate as foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +warning: unused extern crate + --> $DIR/removing-extern-crate.rs:13:5 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ help: remove it + +warning: 4 warnings emitted + diff --git a/tests/ui/repeat-expr/infer.rs b/tests/ui/repeat-expr/infer.rs new file mode 100644 index 000000000..8197713b9 --- /dev/null +++ b/tests/ui/repeat-expr/infer.rs @@ -0,0 +1,16 @@ +// check-pass + +#[derive(Clone, Default)] +struct MaybeCopy(T); + +impl Copy for MaybeCopy {} + +fn is_copy(x: T) { + println!("{}", std::any::type_name::()); +} + +fn main() { + is_copy(MaybeCopy::default()); + [MaybeCopy::default(); 13]; + // didn't work, because `Copy` was only checked in the mir +} diff --git a/tests/ui/repeat-expr/repeat-expr-in-static.rs b/tests/ui/repeat-expr/repeat-expr-in-static.rs new file mode 100644 index 000000000..0b8953793 --- /dev/null +++ b/tests/ui/repeat-expr/repeat-expr-in-static.rs @@ -0,0 +1,8 @@ +// run-pass + +static FOO: [isize; 4] = [32; 4]; +static BAR: [isize; 4] = [32, 32, 32, 32]; + +pub fn main() { + assert_eq!(FOO, BAR); +} diff --git a/tests/ui/repeat-expr/repeat-to-run-dtor-twice.rs b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.rs new file mode 100644 index 000000000..0cd8eceef --- /dev/null +++ b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.rs @@ -0,0 +1,19 @@ +// Tests that one can't run a destructor twice with the repeated vector +// literal syntax. + +struct Foo { + x: isize, + +} + +impl Drop for Foo { + fn drop(&mut self) { + println!("Goodbye!"); + } +} + +fn main() { + let a = Foo { x: 3 }; + let _ = [ a; 5 ]; + //~^ ERROR the trait bound `Foo: Copy` is not satisfied [E0277] +} diff --git a/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr new file mode 100644 index 000000000..36b936163 --- /dev/null +++ b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Foo: Copy` is not satisfied + --> $DIR/repeat-to-run-dtor-twice.rs:17:15 + | +LL | let _ = [ a; 5 ]; + | ^ the trait `Copy` is not implemented for `Foo` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider annotating `Foo` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/repeat-expr/repeat_count.rs b/tests/ui/repeat-expr/repeat_count.rs new file mode 100644 index 000000000..96abff4ab --- /dev/null +++ b/tests/ui/repeat-expr/repeat_count.rs @@ -0,0 +1,34 @@ +// Regression test for issue #3645 + +fn main() { + let n = 1; + let a = [0; n]; + //~^ ERROR attempt to use a non-constant value in a constant [E0435] + let b = [0; ()]; + //~^ ERROR mismatched types + //~| expected `usize`, found `()` + let c = [0; true]; + //~^ ERROR mismatched types + //~| expected `usize`, found `bool` + let d = [0; 0.5]; + //~^ ERROR mismatched types + //~| expected `usize`, found floating-point number + let e = [0; "foo"]; + //~^ ERROR mismatched types + //~| expected `usize`, found `&str` + let f = [0; -4_isize]; + //~^ ERROR mismatched types + //~| expected `usize`, found `isize` + let f = [0_usize; -1_isize]; + //~^ ERROR mismatched types + //~| expected `usize`, found `isize` + let f = [0; 4u8]; + //~^ ERROR mismatched types + //~| expected `usize`, found `u8` + struct G { + g: (), + } + let g = [0; G { g: () }]; + //~^ ERROR mismatched types + //~| expected `usize`, found struct `G` +} diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr new file mode 100644 index 000000000..e222c141f --- /dev/null +++ b/tests/ui/repeat-expr/repeat_count.stderr @@ -0,0 +1,69 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/repeat_count.rs:5:17 + | +LL | let n = 1; + | ----- help: consider using `const` instead of `let`: `const n` +LL | let a = [0; n]; + | ^ non-constant value + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:7:17 + | +LL | let b = [0; ()]; + | ^^ expected `usize`, found `()` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:10:17 + | +LL | let c = [0; true]; + | ^^^^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:13:17 + | +LL | let d = [0; 0.5]; + | ^^^ expected `usize`, found floating-point number + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:16:17 + | +LL | let e = [0; "foo"]; + | ^^^^^ expected `usize`, found `&str` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:31:17 + | +LL | let g = [0; G { g: () }]; + | ^^^^^^^^^^^ expected `usize`, found struct `G` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:19:17 + | +LL | let f = [0; -4_isize]; + | ^^^^^^^^ expected `usize`, found `isize` + | + = note: `-4_isize` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:22:23 + | +LL | let f = [0_usize; -1_isize]; + | ^^^^^^^^ expected `usize`, found `isize` + | + = note: `-1_isize` cannot fit into type `usize` + +error[E0308]: mismatched types + --> $DIR/repeat_count.rs:25:17 + | +LL | let f = [0; 4u8]; + | ^^^ expected `usize`, found `u8` + | +help: change the type of the numeric literal from `u8` to `usize` + | +LL | let f = [0; 4usize]; + | ~~~~~ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0435. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/repr/align-with-extern-c-fn.rs b/tests/ui/repr/align-with-extern-c-fn.rs new file mode 100644 index 000000000..9e490e27a --- /dev/null +++ b/tests/ui/repr/align-with-extern-c-fn.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(stable_features)] +#![allow(unused_variables)] + +// #45662 + +#![feature(repr_align)] + +#[repr(align(16))] +pub struct A(#[allow(unused_tuple_struct_fields)] i64); + +#[allow(improper_ctypes_definitions)] +pub extern "C" fn foo(x: A) {} + +fn main() { + foo(A(0)); +} diff --git a/tests/ui/repr/aligned_enum_cast.rs b/tests/ui/repr/aligned_enum_cast.rs new file mode 100644 index 000000000..1ddf12717 --- /dev/null +++ b/tests/ui/repr/aligned_enum_cast.rs @@ -0,0 +1,25 @@ +// run-pass +// allows aligned custom discriminant enums to cast into other types +// See the issue #92464 for more info +#[allow(dead_code)] +#[repr(align(8))] +enum Aligned { + Zero = 0, + One = 1, +} + +fn main() { + let aligned = Aligned::Zero; + let fo = aligned as u8; + println!("foo {}", fo); + assert_eq!(fo, 0); + println!("{}", tou8(Aligned::Zero)); + assert_eq!(tou8(Aligned::Zero), 0); +} + +#[inline(never)] +fn tou8(al: Aligned) -> u8 { + // Cast behind a function call so ConstProp does not see it + // (so that we can test codegen). + al as u8 +} diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs new file mode 100644 index 000000000..8965decc3 --- /dev/null +++ b/tests/ui/repr/attr-usage-repr.rs @@ -0,0 +1,33 @@ +#![feature(repr_simd)] + +#[repr(C)] //~ ERROR: attribute should be applied to a struct, enum, or union +fn f() {} + +#[repr(C)] +struct SExtern(f64, f64); + +#[repr(packed)] +struct SPacked(f64, f64); + +#[repr(simd)] +struct SSimd(f64, f64); + +#[repr(i8)] //~ ERROR: attribute should be applied to an enum +struct SInt(f64, f64); + +#[repr(C)] +enum EExtern { A, B } + +#[repr(align(8))] +enum EAlign { A, B } + +#[repr(packed)] //~ ERROR: attribute should be applied to a struct +enum EPacked { A, B } + +#[repr(simd)] //~ ERROR: attribute should be applied to a struct +enum ESimd { A, B } + +#[repr(i8)] +enum EInt { A, B } + +fn main() {} diff --git a/tests/ui/repr/attr-usage-repr.stderr b/tests/ui/repr/attr-usage-repr.stderr new file mode 100644 index 000000000..42f65625a --- /dev/null +++ b/tests/ui/repr/attr-usage-repr.stderr @@ -0,0 +1,35 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/attr-usage-repr.rs:3:8 + | +LL | #[repr(C)] + | ^ +LL | fn f() {} + | --------- not a struct, enum, or union + +error[E0517]: attribute should be applied to an enum + --> $DIR/attr-usage-repr.rs:15:8 + | +LL | #[repr(i8)] + | ^^ +LL | struct SInt(f64, f64); + | ---------------------- not an enum + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/attr-usage-repr.rs:24:8 + | +LL | #[repr(packed)] + | ^^^^^^ +LL | enum EPacked { A, B } + | --------------------- not a struct or union + +error[E0517]: attribute should be applied to a struct + --> $DIR/attr-usage-repr.rs:27:8 + | +LL | #[repr(simd)] + | ^^^^ +LL | enum ESimd { A, B } + | ------------------- not a struct + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs b/tests/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs new file mode 100644 index 000000000..4bf6b54fe --- /dev/null +++ b/tests/ui/repr/auxiliary/repr-transparent-non-exhaustive.rs @@ -0,0 +1,18 @@ +#![crate_type = "lib"] + +pub struct Private { _priv: () } + +#[non_exhaustive] +pub struct NonExhaustive {} + +#[non_exhaustive] +pub enum NonExhaustiveEnum {} + +pub enum NonExhaustiveVariant { + #[non_exhaustive] + A, +} + +pub struct ExternalIndirection { + pub x: T, +} diff --git a/tests/ui/repr/invalid_repr_list_help.rs b/tests/ui/repr/invalid_repr_list_help.rs new file mode 100644 index 000000000..c32098453 --- /dev/null +++ b/tests/ui/repr/invalid_repr_list_help.rs @@ -0,0 +1,17 @@ +#![crate_type = "lib"] + +#[repr(uwu)] //~ERROR: unrecognized representation hint +pub struct OwO; + +#[repr(uwu = "a")] //~ERROR: unrecognized representation hint +pub struct OwO2(i32); + +#[repr(uwu(4))] //~ERROR: unrecognized representation hint +pub struct OwO3 { + x: i32, +} + +#[repr(uwu, u8)] //~ERROR: unrecognized representation hint +pub enum OwO4 { + UwU = 1, +} diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr new file mode 100644 index 000000000..2acd56d9a --- /dev/null +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -0,0 +1,35 @@ +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:3:8 + | +LL | #[repr(uwu)] + | ^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:6:8 + | +LL | #[repr(uwu = "a")] + | ^^^^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:9:8 + | +LL | #[repr(uwu(4))] + | ^^^^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error[E0552]: unrecognized representation hint + --> $DIR/invalid_repr_list_help.rs:14:8 + | +LL | #[repr(uwu, u8)] + | ^^^ + | + = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0552`. diff --git a/tests/ui/repr/issue-83505-repr-simd.rs b/tests/ui/repr/issue-83505-repr-simd.rs new file mode 100644 index 000000000..280b771d0 --- /dev/null +++ b/tests/ui/repr/issue-83505-repr-simd.rs @@ -0,0 +1,10 @@ +// Regression test for the ICE described in #83505. + +#![crate_type="lib"] + +#[repr(simd)] +//~^ ERROR: attribute should be applied to a struct [E0517] +//~| ERROR: unsupported representation for zero-variant enum [E0084] +enum Es {} +static CLs: Es; +//~^ ERROR: free static item without body diff --git a/tests/ui/repr/issue-83505-repr-simd.stderr b/tests/ui/repr/issue-83505-repr-simd.stderr new file mode 100644 index 000000000..df99baaf5 --- /dev/null +++ b/tests/ui/repr/issue-83505-repr-simd.stderr @@ -0,0 +1,30 @@ +error: free static item without body + --> $DIR/issue-83505-repr-simd.rs:9:1 + | +LL | static CLs: Es; + | ^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error[E0517]: attribute should be applied to a struct + --> $DIR/issue-83505-repr-simd.rs:5:8 + | +LL | #[repr(simd)] + | ^^^^ +... +LL | enum Es {} + | ---------- not a struct + +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/issue-83505-repr-simd.rs:5:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ +... +LL | enum Es {} + | ------- zero-variant enum + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0084, E0517. +For more information about an error, try `rustc --explain E0084`. diff --git a/tests/ui/repr/issue-83921-ice.rs b/tests/ui/repr/issue-83921-ice.rs new file mode 100644 index 000000000..70583eb9b --- /dev/null +++ b/tests/ui/repr/issue-83921-ice.rs @@ -0,0 +1,34 @@ +// Regression test for various ICEs inspired by +// https://github.com/rust-lang/rust/issues/83921#issuecomment-814640734 + +// compile-flags: -Zdeduplicate-diagnostics=yes + +#[repr(packed())] +//~^ ERROR: incorrect `repr(packed)` attribute format +struct S1; + +#[repr(align)] +//~^ ERROR: invalid `repr(align)` attribute +struct S2; + +#[repr(align(2, 4))] +//~^ ERROR: incorrect `repr(align)` attribute format +struct S3; + +#[repr(align())] +//~^ ERROR: incorrect `repr(align)` attribute format +struct S4; + +#[repr(i8())] +//~^ ERROR: invalid representation hint +enum E1 { A, B } + +#[repr(u32(42))] +//~^ ERROR: invalid representation hint +enum E2 { A, B } + +#[repr(i64 = 2)] +//~^ ERROR: invalid representation hint +enum E3 { A, B } + +fn main() {} diff --git a/tests/ui/repr/issue-83921-ice.stderr b/tests/ui/repr/issue-83921-ice.stderr new file mode 100644 index 000000000..32c450410 --- /dev/null +++ b/tests/ui/repr/issue-83921-ice.stderr @@ -0,0 +1,46 @@ +error[E0552]: incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all + --> $DIR/issue-83921-ice.rs:6:8 + | +LL | #[repr(packed())] + | ^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: `align` needs an argument + --> $DIR/issue-83921-ice.rs:10:8 + | +LL | #[repr(align)] + | ^^^^^ help: supply an argument here: `align(...)` + +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/issue-83921-ice.rs:14:8 + | +LL | #[repr(align(2, 4))] + | ^^^^^^^^^^^ + +error[E0693]: incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses + --> $DIR/issue-83921-ice.rs:18:8 + | +LL | #[repr(align())] + | ^^^^^^^ + +error[E0552]: invalid representation hint: `i8` does not take a parenthesized argument list + --> $DIR/issue-83921-ice.rs:22:8 + | +LL | #[repr(i8())] + | ^^^^ + +error[E0552]: invalid representation hint: `u32` does not take a parenthesized argument list + --> $DIR/issue-83921-ice.rs:26:8 + | +LL | #[repr(u32(42))] + | ^^^^^^^ + +error[E0552]: invalid representation hint: `i64` does not take a value + --> $DIR/issue-83921-ice.rs:30:8 + | +LL | #[repr(i64 = 2)] + | ^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0552, E0589, E0693. +For more information about an error, try `rustc --explain E0552`. diff --git a/tests/ui/repr/repr-align-assign.fixed b/tests/ui/repr/repr-align-assign.fixed new file mode 100644 index 000000000..59ca22e97 --- /dev/null +++ b/tests/ui/repr/repr-align-assign.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +#![allow(dead_code)] + +#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct A(u64); + +#[repr(align(8))] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct B(u64); + +fn main() {} diff --git a/tests/ui/repr/repr-align-assign.rs b/tests/ui/repr/repr-align-assign.rs new file mode 100644 index 000000000..6b7799297 --- /dev/null +++ b/tests/ui/repr/repr-align-assign.rs @@ -0,0 +1,13 @@ +// run-rustfix + +#![allow(dead_code)] + +#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct A(u64); + +#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format + //~| ERROR incorrect `repr(align)` attribute format +struct B(u64); + +fn main() {} diff --git a/tests/ui/repr/repr-align-assign.stderr b/tests/ui/repr/repr-align-assign.stderr new file mode 100644 index 000000000..b878ae0d1 --- /dev/null +++ b/tests/ui/repr/repr-align-assign.stderr @@ -0,0 +1,27 @@ +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/repr-align-assign.rs:5:8 + | +LL | #[repr(align=8)] + | ^^^^^^^ help: use parentheses instead: `align(8)` + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/repr-align-assign.rs:9:8 + | +LL | #[repr(align="8")] + | ^^^^^^^^^ help: use parentheses instead: `align(8)` + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/repr-align-assign.rs:5:8 + | +LL | #[repr(align=8)] + | ^^^^^^^ help: use parentheses instead: `align(8)` + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/repr-align-assign.rs:9:8 + | +LL | #[repr(align="8")] + | ^^^^^^^^^ help: use parentheses instead: `align(8)` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0693`. diff --git a/tests/ui/repr/repr-align.rs b/tests/ui/repr/repr-align.rs new file mode 100644 index 000000000..58ecf9a51 --- /dev/null +++ b/tests/ui/repr/repr-align.rs @@ -0,0 +1,33 @@ +#![allow(dead_code)] + +#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer + //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer +struct S0(i32); + +#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two + //~| ERROR: invalid `repr(align)` attribute: not a power of two +struct S1(i32); + +#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 + //~| ERROR: invalid `repr(align)` attribute: larger than 2^29 +struct S2(i32); + +#[repr(align(536870912))] // ok: this is the largest accepted alignment +struct S3(i32); + +#[repr(align(16.0))] //~ ERROR: invalid `repr(align)` attribute: not an unsuffixed integer + //~| ERROR: invalid `repr(align)` attribute: not an unsuffixed integer +enum E0 { A, B } + +#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two + //~| ERROR: invalid `repr(align)` attribute: not a power of two +enum E1 { A, B } + +#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 + //~| ERROR: invalid `repr(align)` attribute: larger than 2^29 +enum E2 { A, B } + +#[repr(align(536870912))] // ok: this is the largest accepted alignment +enum E3 { A, B } + +fn main() {} diff --git a/tests/ui/repr/repr-align.stderr b/tests/ui/repr/repr-align.stderr new file mode 100644 index 000000000..900a811bb --- /dev/null +++ b/tests/ui/repr/repr-align.stderr @@ -0,0 +1,75 @@ +error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer + --> $DIR/repr-align.rs:3:8 + | +LL | #[repr(align(16.0))] + | ^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not a power of two + --> $DIR/repr-align.rs:7:8 + | +LL | #[repr(align(15))] + | ^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> $DIR/repr-align.rs:11:8 + | +LL | #[repr(align(4294967296))] + | ^^^^^^^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer + --> $DIR/repr-align.rs:18:8 + | +LL | #[repr(align(16.0))] + | ^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not a power of two + --> $DIR/repr-align.rs:22:8 + | +LL | #[repr(align(15))] + | ^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> $DIR/repr-align.rs:26:8 + | +LL | #[repr(align(4294967296))] + | ^^^^^^^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer + --> $DIR/repr-align.rs:3:8 + | +LL | #[repr(align(16.0))] + | ^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not a power of two + --> $DIR/repr-align.rs:7:8 + | +LL | #[repr(align(15))] + | ^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> $DIR/repr-align.rs:11:8 + | +LL | #[repr(align(4294967296))] + | ^^^^^^^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not an unsuffixed integer + --> $DIR/repr-align.rs:18:8 + | +LL | #[repr(align(16.0))] + | ^^^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: not a power of two + --> $DIR/repr-align.rs:22:8 + | +LL | #[repr(align(15))] + | ^^^^^^^^^ + +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> $DIR/repr-align.rs:26:8 + | +LL | #[repr(align(4294967296))] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0589`. diff --git a/tests/ui/repr/repr-disallow-on-variant.rs b/tests/ui/repr/repr-disallow-on-variant.rs new file mode 100644 index 000000000..d9bd0b0e3 --- /dev/null +++ b/tests/ui/repr/repr-disallow-on-variant.rs @@ -0,0 +1,9 @@ +struct Test; + +enum Foo { + #[repr(u8)] + //~^ ERROR attribute should be applied to an enum + Variant, +} + +fn main() {} diff --git a/tests/ui/repr/repr-disallow-on-variant.stderr b/tests/ui/repr/repr-disallow-on-variant.stderr new file mode 100644 index 000000000..f7e4dcc9d --- /dev/null +++ b/tests/ui/repr/repr-disallow-on-variant.stderr @@ -0,0 +1,12 @@ +error[E0517]: attribute should be applied to an enum + --> $DIR/repr-disallow-on-variant.rs:4:12 + | +LL | #[repr(u8)] + | ^^ +LL | +LL | Variant, + | ------- not an enum + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/repr/repr-packed-contains-align.rs b/tests/ui/repr/repr-packed-contains-align.rs new file mode 100644 index 000000000..bef5c7d8c --- /dev/null +++ b/tests/ui/repr/repr-packed-contains-align.rs @@ -0,0 +1,53 @@ +#![allow(dead_code)] + +#[repr(align(16))] +#[derive(Clone, Copy)] +struct SA(i32); + +#[derive(Clone, Copy)] +struct SB(SA); + +#[repr(align(16))] +#[derive(Clone, Copy)] +union UA { + i: i32 +} + +#[derive(Clone, Copy)] +union UB { + a: UA +} + +#[repr(packed)] +struct SC(SA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + +#[repr(packed)] +struct SD(SB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + +#[repr(packed)] +struct SE(UA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + +#[repr(packed)] +struct SF(UB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + +#[repr(packed)] +union UC { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + a: UA +} + +#[repr(packed)] +union UD { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + n: UB +} + +#[repr(packed)] +union UE { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + a: SA +} + +#[repr(packed)] +union UF { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type + n: SB +} + +fn main() {} diff --git a/tests/ui/repr/repr-packed-contains-align.stderr b/tests/ui/repr/repr-packed-contains-align.stderr new file mode 100644 index 000000000..4c3a960ca --- /dev/null +++ b/tests/ui/repr/repr-packed-contains-align.stderr @@ -0,0 +1,139 @@ +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:22:1 + | +LL | struct SC(SA); + | ^^^^^^^^^ + | +note: `SA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:5:1 + | +LL | struct SA(i32); + | ^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:25:1 + | +LL | struct SD(SB); + | ^^^^^^^^^ + | +note: `SA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:5:1 + | +LL | struct SA(i32); + | ^^^^^^^^^ +note: `SD` contains a field of type `SB` + --> $DIR/repr-packed-contains-align.rs:25:11 + | +LL | struct SD(SB); + | ^^ +note: ...which contains a field of type `SA` + --> $DIR/repr-packed-contains-align.rs:8:11 + | +LL | struct SB(SA); + | ^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:28:1 + | +LL | struct SE(UA); + | ^^^^^^^^^ + | +note: `UA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:12:1 + | +LL | union UA { + | ^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:31:1 + | +LL | struct SF(UB); + | ^^^^^^^^^ + | +note: `UA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:12:1 + | +LL | union UA { + | ^^^^^^^^ +note: `SF` contains a field of type `UB` + --> $DIR/repr-packed-contains-align.rs:31:11 + | +LL | struct SF(UB); + | ^^ +note: ...which contains a field of type `UA` + --> $DIR/repr-packed-contains-align.rs:18:5 + | +LL | a: UA + | ^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:34:1 + | +LL | union UC { + | ^^^^^^^^ + | +note: `UA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:12:1 + | +LL | union UA { + | ^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:39:1 + | +LL | union UD { + | ^^^^^^^^ + | +note: `UA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:12:1 + | +LL | union UA { + | ^^^^^^^^ +note: `UD` contains a field of type `UB` + --> $DIR/repr-packed-contains-align.rs:40:5 + | +LL | n: UB + | ^ +note: ...which contains a field of type `UA` + --> $DIR/repr-packed-contains-align.rs:18:5 + | +LL | a: UA + | ^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:44:1 + | +LL | union UE { + | ^^^^^^^^ + | +note: `SA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:5:1 + | +LL | struct SA(i32); + | ^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:49:1 + | +LL | union UF { + | ^^^^^^^^ + | +note: `SA` has a `#[repr(align)]` attribute + --> $DIR/repr-packed-contains-align.rs:5:1 + | +LL | struct SA(i32); + | ^^^^^^^^^ +note: `UF` contains a field of type `SB` + --> $DIR/repr-packed-contains-align.rs:50:5 + | +LL | n: SB + | ^ +note: ...which contains a field of type `SA` + --> $DIR/repr-packed-contains-align.rs:8:11 + | +LL | struct SB(SA); + | ^^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0588`. diff --git a/tests/ui/repr/repr-transparent-issue-87496.rs b/tests/ui/repr/repr-transparent-issue-87496.rs new file mode 100644 index 000000000..a4dd45c63 --- /dev/null +++ b/tests/ui/repr/repr-transparent-issue-87496.rs @@ -0,0 +1,12 @@ +// Regression test for the ICE described in #87496. + +// check-pass + +#[repr(transparent)] +struct TransparentCustomZst(()); +extern "C" { + fn good17(p: TransparentCustomZst); + //~^ WARNING: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe +} + +fn main() {} diff --git a/tests/ui/repr/repr-transparent-issue-87496.stderr b/tests/ui/repr/repr-transparent-issue-87496.stderr new file mode 100644 index 000000000..aee31212b --- /dev/null +++ b/tests/ui/repr/repr-transparent-issue-87496.stderr @@ -0,0 +1,16 @@ +warning: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe + --> $DIR/repr-transparent-issue-87496.rs:8:18 + | +LL | fn good17(p: TransparentCustomZst); + | ^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: this struct contains only zero-sized fields +note: the type is defined here + --> $DIR/repr-transparent-issue-87496.rs:6:1 + | +LL | struct TransparentCustomZst(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(improper_ctypes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/repr/repr-transparent-non-exhaustive.rs b/tests/ui/repr/repr-transparent-non-exhaustive.rs new file mode 100644 index 000000000..506f1dcf3 --- /dev/null +++ b/tests/ui/repr/repr-transparent-non-exhaustive.rs @@ -0,0 +1,96 @@ +#![deny(repr_transparent_external_private_fields)] + +// aux-build: repr-transparent-non-exhaustive.rs +extern crate repr_transparent_non_exhaustive; + +use repr_transparent_non_exhaustive::{ + Private, + NonExhaustive, + NonExhaustiveEnum, + NonExhaustiveVariant, + ExternalIndirection, +}; + +pub struct InternalPrivate { + _priv: (), +} + +#[non_exhaustive] +pub struct InternalNonExhaustive; + +pub struct InternalIndirection { + x: T, +} + +pub type Sized = i32; + +#[repr(transparent)] +pub struct T1(Sized, InternalPrivate); +#[repr(transparent)] +pub struct T2(Sized, InternalNonExhaustive); +#[repr(transparent)] +pub struct T3(Sized, InternalIndirection<(InternalPrivate, InternalNonExhaustive)>); +#[repr(transparent)] +pub struct T4(Sized, ExternalIndirection<(InternalPrivate, InternalNonExhaustive)>); + +#[repr(transparent)] +pub struct T5(Sized, Private); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T6(Sized, NonExhaustive); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T7(Sized, NonExhaustiveEnum); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T8(Sized, NonExhaustiveVariant); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T9(Sized, InternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T10(Sized, InternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T11(Sized, InternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T12(Sized, InternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T13(Sized, ExternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T14(Sized, ExternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T15(Sized, ExternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +#[repr(transparent)] +pub struct T16(Sized, ExternalIndirection); +//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types +//~| WARN this was previously accepted by the compiler + +fn main() {} diff --git a/tests/ui/repr/repr-transparent-non-exhaustive.stderr b/tests/ui/repr/repr-transparent-non-exhaustive.stderr new file mode 100644 index 000000000..16edf59c7 --- /dev/null +++ b/tests/ui/repr/repr-transparent-non-exhaustive.stderr @@ -0,0 +1,127 @@ +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:37:22 + | +LL | pub struct T5(Sized, Private); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. +note: the lint level is defined here + --> $DIR/repr-transparent-non-exhaustive.rs:1:9 + | +LL | #![deny(repr_transparent_external_private_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:42:22 + | +LL | pub struct T6(Sized, NonExhaustive); + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:47:22 + | +LL | pub struct T7(Sized, NonExhaustiveEnum); + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:52:22 + | +LL | pub struct T8(Sized, NonExhaustiveVariant); + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:57:22 + | +LL | pub struct T9(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:62:23 + | +LL | pub struct T10(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:67:23 + | +LL | pub struct T11(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:72:23 + | +LL | pub struct T12(Sized, InternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:77:23 + | +LL | pub struct T13(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:82:23 + | +LL | pub struct T14(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:87:23 + | +LL | pub struct T15(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types + --> $DIR/repr-transparent-non-exhaustive.rs:92:23 + | +LL | pub struct T16(Sized, ExternalIndirection); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #78586 + = note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future. + +error: aborting due to 12 previous errors + diff --git a/tests/ui/repr/repr-transparent-other-items.rs b/tests/ui/repr/repr-transparent-other-items.rs new file mode 100644 index 000000000..e537e3e1a --- /dev/null +++ b/tests/ui/repr/repr-transparent-other-items.rs @@ -0,0 +1,9 @@ +// See also repr-transparent.rs + +#[repr(transparent)] //~ ERROR should be applied to a struct +fn cant_repr_this() {} + +#[repr(transparent)] //~ ERROR should be applied to a struct +static CANT_REPR_THIS: u32 = 0; + +fn main() {} diff --git a/tests/ui/repr/repr-transparent-other-items.stderr b/tests/ui/repr/repr-transparent-other-items.stderr new file mode 100644 index 000000000..14e6f13e1 --- /dev/null +++ b/tests/ui/repr/repr-transparent-other-items.stderr @@ -0,0 +1,19 @@ +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/repr-transparent-other-items.rs:3:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +LL | fn cant_repr_this() {} + | ---------------------- not a struct, enum, or union + +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/repr-transparent-other-items.rs:6:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +LL | static CANT_REPR_THIS: u32 = 0; + | ------------------------------- not a struct, enum, or union + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/repr/repr-transparent-other-reprs.rs b/tests/ui/repr/repr-transparent-other-reprs.rs new file mode 100644 index 000000000..0cd0edf32 --- /dev/null +++ b/tests/ui/repr/repr-transparent-other-reprs.rs @@ -0,0 +1,18 @@ +// See also repr-transparent.rs + +#[repr(transparent, C)] //~ ERROR cannot have other repr +struct TransparentPlusC { + ptr: *const u8 +} + +#[repr(transparent, packed)] //~ ERROR cannot have other repr +struct TransparentPlusPacked(*const u8); + +#[repr(transparent, align(2))] //~ ERROR cannot have other repr +struct TransparentPlusAlign(u8); + +#[repr(transparent)] //~ ERROR cannot have other repr +#[repr(C)] +struct SeparateAttributes(*mut u8); + +fn main() {} diff --git a/tests/ui/repr/repr-transparent-other-reprs.stderr b/tests/ui/repr/repr-transparent-other-reprs.stderr new file mode 100644 index 000000000..d92c35811 --- /dev/null +++ b/tests/ui/repr/repr-transparent-other-reprs.stderr @@ -0,0 +1,29 @@ +error[E0692]: transparent struct cannot have other repr hints + --> $DIR/repr-transparent-other-reprs.rs:3:8 + | +LL | #[repr(transparent, C)] + | ^^^^^^^^^^^ ^ + +error[E0692]: transparent struct cannot have other repr hints + --> $DIR/repr-transparent-other-reprs.rs:8:8 + | +LL | #[repr(transparent, packed)] + | ^^^^^^^^^^^ ^^^^^^ + +error[E0692]: transparent struct cannot have other repr hints + --> $DIR/repr-transparent-other-reprs.rs:11:8 + | +LL | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ + +error[E0692]: transparent struct cannot have other repr hints + --> $DIR/repr-transparent-other-reprs.rs:14:8 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^ +LL | #[repr(C)] + | ^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0692`. diff --git a/tests/ui/repr/repr-transparent.rs b/tests/ui/repr/repr-transparent.rs new file mode 100644 index 000000000..8c9d1639c --- /dev/null +++ b/tests/ui/repr/repr-transparent.rs @@ -0,0 +1,90 @@ +// This file tests repr(transparent)-related errors reported during typeck. Other errors +// that are reported earlier and therefore preempt these are tested in: +// - repr-transparent-other-reprs.rs +// - repr-transparent-other-items.rs + +#![feature(transparent_unions)] + +use std::marker::PhantomData; + +#[repr(transparent)] +struct NoFields; + +#[repr(transparent)] +struct ContainsOnlyZst(()); + +#[repr(transparent)] +struct ContainsOnlyZstArray([bool; 0]); + +#[repr(transparent)] +struct ContainsMultipleZst(PhantomData<*const i32>, NoFields); + +#[repr(transparent)] +struct ContainsZstAndNonZst((), [i32; 2]); + +#[repr(transparent)] +struct MultipleNonZst(u8, u8); //~ ERROR needs at most one non-zero-sized field + +trait Mirror { type It: ?Sized; } +impl Mirror for T { type It = Self; } + +#[repr(transparent)] +pub struct StructWithProjection(f32, ::It); +//~^ ERROR needs at most one non-zero-sized field + +#[repr(transparent)] +struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1 + +#[repr(align(32))] +struct ZstAlign32(PhantomData); + +#[repr(transparent)] +struct GenericAlign(ZstAlign32, u32); //~ ERROR alignment larger than 1 + +#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum +enum Void {} //~ ERROR transparent enum needs exactly one variant, but has 0 + +#[repr(transparent)] +enum FieldlessEnum { + Foo, +} + +#[repr(transparent)] +enum UnitFieldEnum { + Foo(()), +} + +#[repr(transparent)] +enum TooManyFieldsEnum { + Foo(u32, String), +} +//~^^^ ERROR transparent enum needs at most one non-zero-sized field, but has 2 + +#[repr(transparent)] +enum MultipleVariants { //~ ERROR transparent enum needs exactly one variant, but has 2 + Foo(String), + Bar, +} + +#[repr(transparent)] +enum NontrivialAlignZstEnum { + Foo(u32, [u16; 0]), //~ ERROR alignment larger than 1 +} + +#[repr(transparent)] +enum GenericAlignEnum { + Foo { bar: ZstAlign32, baz: u32 } //~ ERROR alignment larger than 1 +} + +#[repr(transparent)] +union UnitUnion { + u: (), +} + +#[repr(transparent)] +union TooManyFields { //~ ERROR transparent union needs at most one non-zero-sized field, but has 2 + u: u32, + s: i32 +} + +fn main() {} diff --git a/tests/ui/repr/repr-transparent.stderr b/tests/ui/repr/repr-transparent.stderr new file mode 100644 index 000000000..f1c570b95 --- /dev/null +++ b/tests/ui/repr/repr-transparent.stderr @@ -0,0 +1,90 @@ +error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:26:1 + | +LL | struct MultipleNonZst(u8, u8); + | ^^^^^^^^^^^^^^^^^^^^^ -- -- this field is non-zero-sized + | | | + | | this field is non-zero-sized + | needs at most one non-zero-sized field, but has 2 + +error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:32:1 + | +LL | pub struct StructWithProjection(f32, ::It); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --- ------------------- this field is non-zero-sized + | | | + | | this field is non-zero-sized + | needs at most one non-zero-sized field, but has 2 + +error[E0691]: zero-sized field in transparent struct has alignment larger than 1 + --> $DIR/repr-transparent.rs:36:32 + | +LL | struct NontrivialAlignZst(u32, [u16; 0]); + | ^^^^^^^^ has alignment larger than 1 + +error[E0691]: zero-sized field in transparent struct has alignment larger than 1 + --> $DIR/repr-transparent.rs:42:24 + | +LL | struct GenericAlign(ZstAlign32, u32); + | ^^^^^^^^^^^^^ has alignment larger than 1 + +error[E0084]: unsupported representation for zero-variant enum + --> $DIR/repr-transparent.rs:44:1 + | +LL | #[repr(transparent)] + | ^^^^^^^^^^^^^^^^^^^^ +LL | enum Void {} + | --------- zero-variant enum + +error[E0731]: transparent enum needs exactly one variant, but has 0 + --> $DIR/repr-transparent.rs:45:1 + | +LL | enum Void {} + | ^^^^^^^^^ needs exactly one variant, but has 0 + +error[E0690]: the variant of a transparent enum needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:58:1 + | +LL | enum TooManyFieldsEnum { + | ^^^^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2 +LL | Foo(u32, String), + | --- ------ this field is non-zero-sized + | | + | this field is non-zero-sized + +error[E0731]: transparent enum needs exactly one variant, but has 2 + --> $DIR/repr-transparent.rs:64:1 + | +LL | enum MultipleVariants { + | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 +LL | Foo(String), + | --- +LL | Bar, + | --- too many variants in `MultipleVariants` + +error[E0691]: zero-sized field in transparent enum has alignment larger than 1 + --> $DIR/repr-transparent.rs:71:14 + | +LL | Foo(u32, [u16; 0]), + | ^^^^^^^^ has alignment larger than 1 + +error[E0691]: zero-sized field in transparent enum has alignment larger than 1 + --> $DIR/repr-transparent.rs:76:11 + | +LL | Foo { bar: ZstAlign32, baz: u32 } + | ^^^^^^^^^^^^^^^^^^ has alignment larger than 1 + +error[E0690]: transparent union needs at most one non-zero-sized field, but has 2 + --> $DIR/repr-transparent.rs:85:1 + | +LL | union TooManyFields { + | ^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2 +LL | u: u32, + | ------ this field is non-zero-sized +LL | s: i32 + | ------ this field is non-zero-sized + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0084, E0690, E0691, E0731. +For more information about an error, try `rustc --explain E0084`. diff --git a/tests/ui/repr/repr.rs b/tests/ui/repr/repr.rs new file mode 100644 index 000000000..564d67326 --- /dev/null +++ b/tests/ui/repr/repr.rs @@ -0,0 +1,13 @@ +#[repr] //~ ERROR malformed `repr` attribute +struct _A {} + +#[repr = "B"] //~ ERROR malformed `repr` attribute +struct _B {} + +#[repr = "C"] //~ ERROR malformed `repr` attribute +struct _C {} + +#[repr(C)] +struct _D {} + +fn main() {} diff --git a/tests/ui/repr/repr.stderr b/tests/ui/repr/repr.stderr new file mode 100644 index 000000000..e0bec6663 --- /dev/null +++ b/tests/ui/repr/repr.stderr @@ -0,0 +1,20 @@ +error: malformed `repr` attribute input + --> $DIR/repr.rs:1:1 + | +LL | #[repr] + | ^^^^^^^ help: must be of the form: `#[repr(C)]` + +error: malformed `repr` attribute input + --> $DIR/repr.rs:4:1 + | +LL | #[repr = "B"] + | ^^^^^^^^^^^^^ help: must be of the form: `#[repr(C)]` + +error: malformed `repr` attribute input + --> $DIR/repr.rs:7:1 + | +LL | #[repr = "C"] + | ^^^^^^^^^^^^^ help: must be of the form: `#[repr(C)]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/repr/repr_c_int_align.rs b/tests/ui/repr/repr_c_int_align.rs new file mode 100644 index 000000000..fdd14fc2d --- /dev/null +++ b/tests/ui/repr/repr_c_int_align.rs @@ -0,0 +1,46 @@ +// run-pass +// compile-flags: -O + +#![allow(dead_code)] + +#[repr(C, u8)] +enum ReprCu8 { + A(u16), + B, +} + +#[repr(u8)] +enum Repru8 { + A(u16), + B, +} + +#[repr(C)] +struct ReprC { + tag: u8, + padding: u8, + payload: u16, +} + +fn main() { + // Test `repr(C, u8)`. + let r1 = ReprC { tag: 0, padding: 0, payload: 0 }; + let r2 = ReprC { tag: 0, padding: 1, payload: 1 }; + + let t1: &ReprCu8 = unsafe { std::mem::transmute(&r1) }; + let t2: &ReprCu8 = unsafe { std::mem::transmute(&r2) }; + + match (t1, t2) { + (ReprCu8::A(_), ReprCu8::A(_)) => (), + _ => assert!(false) + }; + + // Test `repr(u8)`. + let t1: &Repru8 = unsafe { std::mem::transmute(&r1) }; + let t2: &Repru8 = unsafe { std::mem::transmute(&r2) }; + + match (t1, t2) { + (Repru8::A(_), Repru8::A(_)) => (), + _ => assert!(false) + }; +} diff --git a/tests/ui/repr/transparent-enum-too-many-variants.rs b/tests/ui/repr/transparent-enum-too-many-variants.rs new file mode 100644 index 000000000..0dd4b4e68 --- /dev/null +++ b/tests/ui/repr/transparent-enum-too-many-variants.rs @@ -0,0 +1,10 @@ +use std::mem::size_of; + +#[repr(transparent)] +enum Foo { //~ ERROR E0731 + A(u8), B(u8), +} + +fn main() { + println!("Foo: {}", size_of::()); +} diff --git a/tests/ui/repr/transparent-enum-too-many-variants.stderr b/tests/ui/repr/transparent-enum-too-many-variants.stderr new file mode 100644 index 000000000..fb44757ef --- /dev/null +++ b/tests/ui/repr/transparent-enum-too-many-variants.stderr @@ -0,0 +1,11 @@ +error[E0731]: transparent enum needs exactly one variant, but has 2 + --> $DIR/transparent-enum-too-many-variants.rs:4:1 + | +LL | enum Foo { + | ^^^^^^^^ needs exactly one variant, but has 2 +LL | A(u8), B(u8), + | - - too many variants in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0731`. diff --git a/tests/ui/reserved/reserved-attr-on-macro.rs b/tests/ui/reserved/reserved-attr-on-macro.rs new file mode 100644 index 000000000..2630db0d0 --- /dev/null +++ b/tests/ui/reserved/reserved-attr-on-macro.rs @@ -0,0 +1,11 @@ +#[rustc_attribute_should_be_reserved] +//~^ ERROR cannot find attribute `rustc_attribute_should_be_reserved` in this scope +//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler + +macro_rules! foo { + () => (()); +} + +fn main() { + foo!(); //~ ERROR cannot determine resolution for the macro `foo` +} diff --git a/tests/ui/reserved/reserved-attr-on-macro.stderr b/tests/ui/reserved/reserved-attr-on-macro.stderr new file mode 100644 index 000000000..e55b58bef --- /dev/null +++ b/tests/ui/reserved/reserved-attr-on-macro.stderr @@ -0,0 +1,22 @@ +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/reserved-attr-on-macro.rs:1:3 + | +LL | #[rustc_attribute_should_be_reserved] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot determine resolution for the macro `foo` + --> $DIR/reserved-attr-on-macro.rs:10:5 + | +LL | foo!(); + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope + --> $DIR/reserved-attr-on-macro.rs:1:3 + | +LL | #[rustc_attribute_should_be_reserved] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/reserved/reserved-become.rs b/tests/ui/reserved/reserved-become.rs new file mode 100644 index 000000000..56645255e --- /dev/null +++ b/tests/ui/reserved/reserved-become.rs @@ -0,0 +1,4 @@ +fn main() { + let become = 0; + //~^ ERROR expected identifier, found reserved keyword `become` +} diff --git a/tests/ui/reserved/reserved-become.stderr b/tests/ui/reserved/reserved-become.stderr new file mode 100644 index 000000000..0703b76d6 --- /dev/null +++ b/tests/ui/reserved/reserved-become.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `become` + --> $DIR/reserved-become.rs:2:9 + | +LL | let become = 0; + | ^^^^^^ expected identifier, found reserved keyword + | +help: escape `become` to use it as an identifier + | +LL | let r#become = 0; + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/resolve/associated-fn-called-as-fn.rs b/tests/ui/resolve/associated-fn-called-as-fn.rs new file mode 100644 index 000000000..f31f3d67b --- /dev/null +++ b/tests/ui/resolve/associated-fn-called-as-fn.rs @@ -0,0 +1,32 @@ +struct S; +impl Foo for S { + fn parse(s:&str) { + for c in s.chars() { + match c { + '0'..='9' => collect_primary(&c), //~ ERROR cannot find function `collect_primary` + //~^ HELP you might have meant to call the associated function + '+' | '-' => println!("We got a sign: {}", c), + _ => println!("Not a number!") + } + } + } +} +trait Foo { + fn collect_primary(ch:&char) { } + fn parse(s:&str); +} +trait Bar { + fn collect_primary(ch:&char) { } + fn parse(s:&str) { + for c in s.chars() { + match c { + '0'..='9' => collect_primary(&c), //~ ERROR cannot find function `collect_primary` + //~^ HELP you might have meant to call the associated function + '+' | '-' => println!("We got a sign: {}", c), + _ => println!("Not a number!") + } + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/associated-fn-called-as-fn.stderr b/tests/ui/resolve/associated-fn-called-as-fn.stderr new file mode 100644 index 000000000..fbdea30d5 --- /dev/null +++ b/tests/ui/resolve/associated-fn-called-as-fn.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find function `collect_primary` in this scope + --> $DIR/associated-fn-called-as-fn.rs:6:30 + | +LL | '0'..='9' => collect_primary(&c), + | ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary` + +error[E0425]: cannot find function `collect_primary` in this scope + --> $DIR/associated-fn-called-as-fn.rs:23:30 + | +LL | '0'..='9' => collect_primary(&c), + | ^^^^^^^^^^^^^^^ help: you might have meant to call the associated function: `Self::collect_primary` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo.rs b/tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo.rs new file mode 100644 index 000000000..cf769f31b --- /dev/null +++ b/tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo.rs @@ -0,0 +1,3 @@ +#![crate_type="lib"] + +pub const X: () = (); diff --git a/tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo2.rs b/tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo2.rs new file mode 100644 index 000000000..81c16ede9 --- /dev/null +++ b/tests/ui/resolve/auxiliary/blind-item-mixed-crate-use-item-foo2.rs @@ -0,0 +1,3 @@ +#![crate_type="lib"] + +pub const Y: () = (); diff --git a/tests/ui/resolve/auxiliary/extern-prelude-vec.rs b/tests/ui/resolve/auxiliary/extern-prelude-vec.rs new file mode 100644 index 000000000..a643c8889 --- /dev/null +++ b/tests/ui/resolve/auxiliary/extern-prelude-vec.rs @@ -0,0 +1,3 @@ +#![crate_name = "Vec"] + +pub fn new(arg1: f32, arg2: ()) {} diff --git a/tests/ui/resolve/auxiliary/extern-prelude.rs b/tests/ui/resolve/auxiliary/extern-prelude.rs new file mode 100644 index 000000000..2fdfd85a1 --- /dev/null +++ b/tests/ui/resolve/auxiliary/extern-prelude.rs @@ -0,0 +1,5 @@ +pub struct S; + +impl S { + pub fn external(&self) {} +} diff --git a/tests/ui/resolve/auxiliary/issue-19452-aux.rs b/tests/ui/resolve/auxiliary/issue-19452-aux.rs new file mode 100644 index 000000000..9c7bcec51 --- /dev/null +++ b/tests/ui/resolve/auxiliary/issue-19452-aux.rs @@ -0,0 +1,3 @@ +pub enum Homura { + Madoka { age: u32 } +} diff --git a/tests/ui/resolve/auxiliary/issue-21221-3.rs b/tests/ui/resolve/auxiliary/issue-21221-3.rs new file mode 100644 index 000000000..176c23180 --- /dev/null +++ b/tests/ui/resolve/auxiliary/issue-21221-3.rs @@ -0,0 +1,19 @@ +// testing whether the lookup mechanism picks up types +// defined in the outside crate + +#![crate_type="lib"] + +pub mod outer { + // should suggest this + pub trait OuterTrait {} + + // should not suggest this since the module is private + mod private_module { + pub trait OuterTrait {} + } + + // should not suggest since the trait is private + pub mod public_module { + trait OuterTrait {} + } +} diff --git a/tests/ui/resolve/auxiliary/issue-21221-4.rs b/tests/ui/resolve/auxiliary/issue-21221-4.rs new file mode 100644 index 000000000..5e0d6cbdf --- /dev/null +++ b/tests/ui/resolve/auxiliary/issue-21221-4.rs @@ -0,0 +1,12 @@ +// testing whether the lookup mechanism picks up types +// defined in the outside crate + +#![crate_type="lib"] + +mod foo { + // should not be suggested => foo is private + pub trait T {} +} + +// should be suggested +pub use foo::T; diff --git a/tests/ui/resolve/auxiliary/issue-30535.rs b/tests/ui/resolve/auxiliary/issue-30535.rs new file mode 100644 index 000000000..3608d4a2f --- /dev/null +++ b/tests/ui/resolve/auxiliary/issue-30535.rs @@ -0,0 +1,5 @@ +#![crate_type="lib"] + +pub enum Foo { + FooV { data: () } +} diff --git a/tests/ui/resolve/auxiliary/issue-3907.rs b/tests/ui/resolve/auxiliary/issue-3907.rs new file mode 100644 index 000000000..5dc502930 --- /dev/null +++ b/tests/ui/resolve/auxiliary/issue-3907.rs @@ -0,0 +1,3 @@ +pub trait Foo { + fn bar(); +} diff --git a/tests/ui/resolve/auxiliary/issue-80079.rs b/tests/ui/resolve/auxiliary/issue-80079.rs new file mode 100644 index 000000000..190ca75ab --- /dev/null +++ b/tests/ui/resolve/auxiliary/issue-80079.rs @@ -0,0 +1,18 @@ +#![crate_type = "lib"] + +pub mod public { + use private_import; + + // should not be suggested since it is private + struct Foo; + + mod private_module { + // should not be suggested since it is private + pub struct Foo; + } +} + +mod private_import { + // should not be suggested since it is private + pub struct Foo; +} diff --git a/tests/ui/resolve/auxiliary/namespaced_enums.rs b/tests/ui/resolve/auxiliary/namespaced_enums.rs new file mode 100644 index 000000000..d3548c76c --- /dev/null +++ b/tests/ui/resolve/auxiliary/namespaced_enums.rs @@ -0,0 +1,10 @@ +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} + pub fn bar(&self) {} +} diff --git a/tests/ui/resolve/auxiliary/privacy-struct-ctor.rs b/tests/ui/resolve/auxiliary/privacy-struct-ctor.rs new file mode 100644 index 000000000..6d0bc7285 --- /dev/null +++ b/tests/ui/resolve/auxiliary/privacy-struct-ctor.rs @@ -0,0 +1,9 @@ +pub mod m { + pub struct S(u8); + + pub mod n { + pub(in m) struct Z(pub(in m::n) u8); + } +} + +pub use m::S; diff --git a/tests/ui/resolve/bad-env-capture.rs b/tests/ui/resolve/bad-env-capture.rs new file mode 100644 index 000000000..83fd2544f --- /dev/null +++ b/tests/ui/resolve/bad-env-capture.rs @@ -0,0 +1,6 @@ +// error-pattern: can't capture dynamic environment in a fn item +fn foo() { + let x: isize; + fn bar() { log(debug, x); } +} +fn main() { foo(); } diff --git a/tests/ui/resolve/bad-env-capture.stderr b/tests/ui/resolve/bad-env-capture.stderr new file mode 100644 index 000000000..59b1fabfd --- /dev/null +++ b/tests/ui/resolve/bad-env-capture.stderr @@ -0,0 +1,24 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/bad-env-capture.rs:4:27 + | +LL | fn bar() { log(debug, x); } + | ^ + | + = help: use the `|| { ... }` closure form instead + +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-env-capture.rs:4:20 + | +LL | fn bar() { log(debug, x); } + | ^^^^^ not found in this scope + +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-env-capture.rs:4:16 + | +LL | fn bar() { log(debug, x); } + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0434. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/bad-env-capture2.rs b/tests/ui/resolve/bad-env-capture2.rs new file mode 100644 index 000000000..b04569c9d --- /dev/null +++ b/tests/ui/resolve/bad-env-capture2.rs @@ -0,0 +1,5 @@ +// error-pattern: can't capture dynamic environment in a fn item +fn foo(x: isize) { + fn bar() { log(debug, x); } +} +fn main() { foo(2); } diff --git a/tests/ui/resolve/bad-env-capture2.stderr b/tests/ui/resolve/bad-env-capture2.stderr new file mode 100644 index 000000000..811c259de --- /dev/null +++ b/tests/ui/resolve/bad-env-capture2.stderr @@ -0,0 +1,24 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/bad-env-capture2.rs:3:27 + | +LL | fn bar() { log(debug, x); } + | ^ + | + = help: use the `|| { ... }` closure form instead + +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-env-capture2.rs:3:20 + | +LL | fn bar() { log(debug, x); } + | ^^^^^ not found in this scope + +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-env-capture2.rs:3:16 + | +LL | fn bar() { log(debug, x); } + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0434. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/bad-env-capture3.rs b/tests/ui/resolve/bad-env-capture3.rs new file mode 100644 index 000000000..62f12fd1a --- /dev/null +++ b/tests/ui/resolve/bad-env-capture3.rs @@ -0,0 +1,8 @@ +// error-pattern: can't capture dynamic environment in a fn item +fn foo(x: isize) { + fn mth() { + fn bar() { log(debug, x); } + } +} + +fn main() { foo(2); } diff --git a/tests/ui/resolve/bad-env-capture3.stderr b/tests/ui/resolve/bad-env-capture3.stderr new file mode 100644 index 000000000..eab37fde9 --- /dev/null +++ b/tests/ui/resolve/bad-env-capture3.stderr @@ -0,0 +1,24 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/bad-env-capture3.rs:4:31 + | +LL | fn bar() { log(debug, x); } + | ^ + | + = help: use the `|| { ... }` closure form instead + +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-env-capture3.rs:4:24 + | +LL | fn bar() { log(debug, x); } + | ^^^^^ not found in this scope + +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-env-capture3.rs:4:20 + | +LL | fn bar() { log(debug, x); } + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0434. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/bad-expr-path.rs b/tests/ui/resolve/bad-expr-path.rs new file mode 100644 index 000000000..31fc9cf2c --- /dev/null +++ b/tests/ui/resolve/bad-expr-path.rs @@ -0,0 +1,8 @@ +mod m1 {} + +fn main(arguments: Vec) { //~ ERROR `main` function has wrong type + log(debug, m1::arguments); + //~^ ERROR cannot find function `log` in this scope + //~| ERROR cannot find value `debug` in this scope + //~| ERROR cannot find value `arguments` in module `m1` +} diff --git a/tests/ui/resolve/bad-expr-path.stderr b/tests/ui/resolve/bad-expr-path.stderr new file mode 100644 index 000000000..8261e8e53 --- /dev/null +++ b/tests/ui/resolve/bad-expr-path.stderr @@ -0,0 +1,31 @@ +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-expr-path.rs:4:9 + | +LL | log(debug, m1::arguments); + | ^^^^^ not found in this scope + +error[E0425]: cannot find value `arguments` in module `m1` + --> $DIR/bad-expr-path.rs:4:20 + | +LL | log(debug, m1::arguments); + | ^^^^^^^^^ not found in `m1` + +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-expr-path.rs:4:5 + | +LL | log(debug, m1::arguments); + | ^^^ not found in this scope + +error[E0580]: `main` function has wrong type + --> $DIR/bad-expr-path.rs:3:1 + | +LL | fn main(arguments: Vec) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `fn()` + found fn pointer `fn(Vec)` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0425, E0580. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/bad-expr-path2.rs b/tests/ui/resolve/bad-expr-path2.rs new file mode 100644 index 000000000..eb88edb90 --- /dev/null +++ b/tests/ui/resolve/bad-expr-path2.rs @@ -0,0 +1,10 @@ +mod m1 { + pub mod arguments {} +} + +fn main(arguments: Vec) { //~ ERROR `main` function has wrong type + log(debug, m1::arguments); + //~^ ERROR cannot find function `log` in this scope + //~| ERROR cannot find value `debug` in this scope + //~| ERROR expected value, found module `m1::arguments` +} diff --git a/tests/ui/resolve/bad-expr-path2.stderr b/tests/ui/resolve/bad-expr-path2.stderr new file mode 100644 index 000000000..6e11296d9 --- /dev/null +++ b/tests/ui/resolve/bad-expr-path2.stderr @@ -0,0 +1,31 @@ +error[E0425]: cannot find value `debug` in this scope + --> $DIR/bad-expr-path2.rs:6:9 + | +LL | log(debug, m1::arguments); + | ^^^^^ not found in this scope + +error[E0423]: expected value, found module `m1::arguments` + --> $DIR/bad-expr-path2.rs:6:16 + | +LL | log(debug, m1::arguments); + | ^^^^^^^^^^^^^ not a value + +error[E0425]: cannot find function `log` in this scope + --> $DIR/bad-expr-path2.rs:6:5 + | +LL | log(debug, m1::arguments); + | ^^^ not found in this scope + +error[E0580]: `main` function has wrong type + --> $DIR/bad-expr-path2.rs:5:1 + | +LL | fn main(arguments: Vec) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected fn pointer `fn()` + found fn pointer `fn(Vec)` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0423, E0425, E0580. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/bad-module.rs b/tests/ui/resolve/bad-module.rs new file mode 100644 index 000000000..b23e97c2c --- /dev/null +++ b/tests/ui/resolve/bad-module.rs @@ -0,0 +1,7 @@ +fn main() { + let foo = thing::len(Vec::new()); + //~^ ERROR failed to resolve: use of undeclared crate or module `thing` + + let foo = foo::bar::baz(); + //~^ ERROR failed to resolve: use of undeclared crate or module `foo` +} diff --git a/tests/ui/resolve/bad-module.stderr b/tests/ui/resolve/bad-module.stderr new file mode 100644 index 000000000..558760c67 --- /dev/null +++ b/tests/ui/resolve/bad-module.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `foo` + --> $DIR/bad-module.rs:5:15 + | +LL | let foo = foo::bar::baz(); + | ^^^ use of undeclared crate or module `foo` + +error[E0433]: failed to resolve: use of undeclared crate or module `thing` + --> $DIR/bad-module.rs:2:15 + | +LL | let foo = thing::len(Vec::new()); + | ^^^^^ use of undeclared crate or module `thing` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/bad-type-env-capture.rs b/tests/ui/resolve/bad-type-env-capture.rs new file mode 100644 index 000000000..53dfb1313 --- /dev/null +++ b/tests/ui/resolve/bad-type-env-capture.rs @@ -0,0 +1,4 @@ +fn foo() { + fn bar(b: T) { } //~ ERROR can't use generic parameters from outer +} +fn main() { } diff --git a/tests/ui/resolve/bad-type-env-capture.stderr b/tests/ui/resolve/bad-type-env-capture.stderr new file mode 100644 index 000000000..b6282c2d0 --- /dev/null +++ b/tests/ui/resolve/bad-type-env-capture.stderr @@ -0,0 +1,13 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/bad-type-env-capture.rs:2:15 + | +LL | fn foo() { + | - type parameter from outer function +LL | fn bar(b: T) { } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/blind-item-local-shadow.rs b/tests/ui/resolve/blind-item-local-shadow.rs new file mode 100644 index 000000000..942aeb6fd --- /dev/null +++ b/tests/ui/resolve/blind-item-local-shadow.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_imports)] +mod bar { + pub fn foo() -> bool { true } +} + +fn main() { + let foo = || false; + use bar::foo; + assert_eq!(foo(), false); +} diff --git a/tests/ui/resolve/blind-item-mixed-crate-use-item.rs b/tests/ui/resolve/blind-item-mixed-crate-use-item.rs new file mode 100644 index 000000000..36d8ab151 --- /dev/null +++ b/tests/ui/resolve/blind-item-mixed-crate-use-item.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:blind-item-mixed-crate-use-item-foo.rs +// aux-build:blind-item-mixed-crate-use-item-foo2.rs + +// pretty-expanded FIXME #23616 + +mod m { + pub fn f(_: T, _: (), _: ()) { } + pub fn g(_: T, _: (), _: ()) { } +} + +const BAR: () = (); +struct Data; +use m::f; +extern crate blind_item_mixed_crate_use_item_foo as foo; + +fn main() { + const BAR2: () = (); + struct Data2; + use m::g; + + extern crate blind_item_mixed_crate_use_item_foo2 as foo2; + + f(Data, BAR, foo::X); + g(Data2, BAR2, foo2::Y); +} diff --git a/tests/ui/resolve/blind-item-mixed-use-item.rs b/tests/ui/resolve/blind-item-mixed-use-item.rs new file mode 100644 index 000000000..4a3905496 --- /dev/null +++ b/tests/ui/resolve/blind-item-mixed-use-item.rs @@ -0,0 +1,20 @@ +// run-pass +// pretty-expanded FIXME #23616 + +mod m { + pub fn f(_: T, _: ()) { } + pub fn g(_: T, _: ()) { } +} + +const BAR: () = (); +struct Data; +use m::f; + +fn main() { + const BAR2: () = (); + struct Data2; + use m::g; + + f(Data, BAR); + g(Data2, BAR2); +} diff --git a/tests/ui/resolve/block-with-trait-parent.rs b/tests/ui/resolve/block-with-trait-parent.rs new file mode 100644 index 000000000..bc86f94e9 --- /dev/null +++ b/tests/ui/resolve/block-with-trait-parent.rs @@ -0,0 +1,14 @@ +// check-pass + +trait Trait { + fn method(&self) { + // Items inside a block turn it into a module internally. + struct S; + impl Trait for S {} + + // OK, `Trait` is in scope here from method resolution point of view. + S.method(); + } +} + +fn main() {} diff --git a/tests/ui/resolve/crate-called-as-function.rs b/tests/ui/resolve/crate-called-as-function.rs new file mode 100644 index 000000000..e8f52c0c0 --- /dev/null +++ b/tests/ui/resolve/crate-called-as-function.rs @@ -0,0 +1,3 @@ +fn main() { + ::foo() //~ cannot find external crate `foo` in the crate root +} diff --git a/tests/ui/resolve/crate-called-as-function.stderr b/tests/ui/resolve/crate-called-as-function.stderr new file mode 100644 index 000000000..eb42349af --- /dev/null +++ b/tests/ui/resolve/crate-called-as-function.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find external crate `foo` in the crate root + --> $DIR/crate-called-as-function.rs:2:7 + | +LL | ::foo() + | ^^^ not found in the crate root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/crate-in-paths.rs b/tests/ui/resolve/crate-in-paths.rs new file mode 100644 index 000000000..7ebd25918 --- /dev/null +++ b/tests/ui/resolve/crate-in-paths.rs @@ -0,0 +1,10 @@ +// edition:2018 + +mod bar { + pub(crate) struct Foo; +} + +fn main() { + Foo; + //~^ ERROR cannot find value `Foo` in this scope [E0425] +} diff --git a/tests/ui/resolve/crate-in-paths.stderr b/tests/ui/resolve/crate-in-paths.stderr new file mode 100644 index 000000000..b7cf49507 --- /dev/null +++ b/tests/ui/resolve/crate-in-paths.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/crate-in-paths.rs:8:5 + | +LL | Foo; + | ^^^ not found in this scope + | +help: consider importing this unit struct + | +LL | use crate::bar::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/editions-crate-root-2015.rs b/tests/ui/resolve/editions-crate-root-2015.rs new file mode 100644 index 000000000..4c890e3ae --- /dev/null +++ b/tests/ui/resolve/editions-crate-root-2015.rs @@ -0,0 +1,21 @@ +// edition:2015 + +mod inner { + fn global_inner(_: ::nonexistant::Foo) { + //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`? + } + fn crate_inner(_: crate::nonexistant::Foo) { + //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`? + } + + fn bare_global(_: ::nonexistant) { + //~^ ERROR cannot find type `nonexistant` in the crate root + } + fn bare_crate(_: crate::nonexistant) { + //~^ ERROR cannot find type `nonexistant` in the crate root + } +} + +fn main() { + +} diff --git a/tests/ui/resolve/editions-crate-root-2015.stderr b/tests/ui/resolve/editions-crate-root-2015.stderr new file mode 100644 index 000000000..00cdd0c58 --- /dev/null +++ b/tests/ui/resolve/editions-crate-root-2015.stderr @@ -0,0 +1,32 @@ +error[E0433]: failed to resolve: maybe a missing crate `nonexistant`? + --> $DIR/editions-crate-root-2015.rs:4:26 + | +LL | fn global_inner(_: ::nonexistant::Foo) { + | ^^^^^^^^^^^ maybe a missing crate `nonexistant`? + | + = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate + +error[E0433]: failed to resolve: maybe a missing crate `nonexistant`? + --> $DIR/editions-crate-root-2015.rs:7:30 + | +LL | fn crate_inner(_: crate::nonexistant::Foo) { + | ^^^^^^^^^^^ maybe a missing crate `nonexistant`? + | + = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate + +error[E0412]: cannot find type `nonexistant` in the crate root + --> $DIR/editions-crate-root-2015.rs:11:25 + | +LL | fn bare_global(_: ::nonexistant) { + | ^^^^^^^^^^^ not found in the crate root + +error[E0412]: cannot find type `nonexistant` in the crate root + --> $DIR/editions-crate-root-2015.rs:14:29 + | +LL | fn bare_crate(_: crate::nonexistant) { + | ^^^^^^^^^^^ not found in the crate root + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0412, E0433. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/editions-crate-root-2018.rs b/tests/ui/resolve/editions-crate-root-2018.rs new file mode 100644 index 000000000..61e4329bb --- /dev/null +++ b/tests/ui/resolve/editions-crate-root-2018.rs @@ -0,0 +1,21 @@ +// edition:2018 + +mod inner { + fn global_inner(_: ::nonexistant::Foo) { + //~^ ERROR failed to resolve: could not find `nonexistant` in the list of imported crates + } + fn crate_inner(_: crate::nonexistant::Foo) { + //~^ ERROR failed to resolve: could not find `nonexistant` in the crate root + } + + fn bare_global(_: ::nonexistant) { + //~^ ERROR cannot find crate `nonexistant` in the list of imported crates + } + fn bare_crate(_: crate::nonexistant) { + //~^ ERROR cannot find type `nonexistant` in the crate root + } +} + +fn main() { + +} diff --git a/tests/ui/resolve/editions-crate-root-2018.stderr b/tests/ui/resolve/editions-crate-root-2018.stderr new file mode 100644 index 000000000..967a5a2fc --- /dev/null +++ b/tests/ui/resolve/editions-crate-root-2018.stderr @@ -0,0 +1,28 @@ +error[E0433]: failed to resolve: could not find `nonexistant` in the list of imported crates + --> $DIR/editions-crate-root-2018.rs:4:26 + | +LL | fn global_inner(_: ::nonexistant::Foo) { + | ^^^^^^^^^^^ could not find `nonexistant` in the list of imported crates + +error[E0433]: failed to resolve: could not find `nonexistant` in the crate root + --> $DIR/editions-crate-root-2018.rs:7:30 + | +LL | fn crate_inner(_: crate::nonexistant::Foo) { + | ^^^^^^^^^^^ could not find `nonexistant` in the crate root + +error[E0412]: cannot find crate `nonexistant` in the list of imported crates + --> $DIR/editions-crate-root-2018.rs:11:25 + | +LL | fn bare_global(_: ::nonexistant) { + | ^^^^^^^^^^^ not found in the list of imported crates + +error[E0412]: cannot find type `nonexistant` in the crate root + --> $DIR/editions-crate-root-2018.rs:14:29 + | +LL | fn bare_crate(_: crate::nonexistant) { + | ^^^^^^^^^^^ not found in the crate root + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0412, E0433. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/enums-are-namespaced-xc.rs b/tests/ui/resolve/enums-are-namespaced-xc.rs new file mode 100644 index 000000000..dfc16d6ce --- /dev/null +++ b/tests/ui/resolve/enums-are-namespaced-xc.rs @@ -0,0 +1,11 @@ +// aux-build:namespaced_enums.rs +extern crate namespaced_enums; + +fn main() { + let _ = namespaced_enums::A; + //~^ ERROR cannot find value `A` + let _ = namespaced_enums::B(10); + //~^ ERROR cannot find function, tuple struct or tuple variant `B` + let _ = namespaced_enums::C { a: 10 }; + //~^ ERROR cannot find struct, variant or union type `C` +} diff --git a/tests/ui/resolve/enums-are-namespaced-xc.stderr b/tests/ui/resolve/enums-are-namespaced-xc.stderr new file mode 100644 index 000000000..6448e596d --- /dev/null +++ b/tests/ui/resolve/enums-are-namespaced-xc.stderr @@ -0,0 +1,52 @@ +error[E0425]: cannot find value `A` in crate `namespaced_enums` + --> $DIR/enums-are-namespaced-xc.rs:5:31 + | +LL | let _ = namespaced_enums::A; + | ^ not found in `namespaced_enums` + | +help: consider importing this unit variant + | +LL | use namespaced_enums::Foo::A; + | +help: if you import `A`, refer to it directly + | +LL - let _ = namespaced_enums::A; +LL + let _ = A; + | + +error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate `namespaced_enums` + --> $DIR/enums-are-namespaced-xc.rs:7:31 + | +LL | let _ = namespaced_enums::B(10); + | ^ not found in `namespaced_enums` + | +help: consider importing this tuple variant + | +LL | use namespaced_enums::Foo::B; + | +help: if you import `B`, refer to it directly + | +LL - let _ = namespaced_enums::B(10); +LL + let _ = B(10); + | + +error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced_enums` + --> $DIR/enums-are-namespaced-xc.rs:9:31 + | +LL | let _ = namespaced_enums::C { a: 10 }; + | ^ not found in `namespaced_enums` + | +help: consider importing this variant + | +LL | use namespaced_enums::Foo::C; + | +help: if you import `C`, refer to it directly + | +LL - let _ = namespaced_enums::C { a: 10 }; +LL + let _ = C { a: 10 }; + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0422, E0425. +For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/resolve/enums-pats-not-idents.rs b/tests/ui/resolve/enums-pats-not-idents.rs new file mode 100644 index 000000000..5b918eef6 --- /dev/null +++ b/tests/ui/resolve/enums-pats-not-idents.rs @@ -0,0 +1,3 @@ +fn main() { + let a(1) = 13; //~ ERROR cannot find tuple struct or tuple variant `a` in this scope +} diff --git a/tests/ui/resolve/enums-pats-not-idents.stderr b/tests/ui/resolve/enums-pats-not-idents.stderr new file mode 100644 index 000000000..072b88716 --- /dev/null +++ b/tests/ui/resolve/enums-pats-not-idents.stderr @@ -0,0 +1,9 @@ +error[E0531]: cannot find tuple struct or tuple variant `a` in this scope + --> $DIR/enums-pats-not-idents.rs:2:9 + | +LL | let a(1) = 13; + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0531`. diff --git a/tests/ui/resolve/export-fully-qualified.rs b/tests/ui/resolve/export-fully-qualified.rs new file mode 100644 index 000000000..4e73a2c54 --- /dev/null +++ b/tests/ui/resolve/export-fully-qualified.rs @@ -0,0 +1,11 @@ +// In this test baz isn't resolved when called as foo.baz even though +// it's called from inside foo. This is somewhat surprising and may +// want to change eventually. + +mod foo { + pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `foo` + + fn baz() { } +} + +fn main() { } diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr new file mode 100644 index 000000000..7ee352e12 --- /dev/null +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `foo` + --> $DIR/export-fully-qualified.rs:6:20 + | +LL | pub fn bar() { foo::baz(); } + | ^^^ use of undeclared crate or module `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/extern-prelude-fail.rs b/tests/ui/resolve/extern-prelude-fail.rs new file mode 100644 index 000000000..7d387025a --- /dev/null +++ b/tests/ui/resolve/extern-prelude-fail.rs @@ -0,0 +1,9 @@ +// compile-flags:--extern extern_prelude +// aux-build:extern-prelude.rs + +// Extern prelude names are not available by absolute paths + +fn main() { + use extern_prelude::S; //~ ERROR unresolved import `extern_prelude` + let s = ::extern_prelude::S; //~ ERROR failed to resolve +} diff --git a/tests/ui/resolve/extern-prelude-fail.stderr b/tests/ui/resolve/extern-prelude-fail.stderr new file mode 100644 index 000000000..a1591914b --- /dev/null +++ b/tests/ui/resolve/extern-prelude-fail.stderr @@ -0,0 +1,20 @@ +error[E0432]: unresolved import `extern_prelude` + --> $DIR/extern-prelude-fail.rs:7:9 + | +LL | use extern_prelude::S; + | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? + | + = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate + +error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`? + --> $DIR/extern-prelude-fail.rs:8:15 + | +LL | let s = ::extern_prelude::S; + | ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`? + | + = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/resolve/extern-prelude.rs b/tests/ui/resolve/extern-prelude.rs new file mode 100644 index 000000000..50fed6034 --- /dev/null +++ b/tests/ui/resolve/extern-prelude.rs @@ -0,0 +1,31 @@ +// build-pass (FIXME(62277): could be check-pass?) +// compile-flags:--extern extern_prelude --extern Vec +// aux-build:extern-prelude.rs +// aux-build:extern-prelude-vec.rs + +fn basic() { + // It works + let s = extern_prelude::S; + s.external(); +} + +fn shadow_mod() { + // Local module shadows `extern_prelude` from extern prelude + mod extern_prelude { + pub struct S; + + impl S { + pub fn internal(&self) {} + } + } + + let s = extern_prelude::S; + s.internal(); // OK +} + +fn shadow_prelude() { + // Extern prelude shadows standard library prelude + let x = Vec::new(0f32, ()); // OK +} + +fn main() {} diff --git a/tests/ui/resolve/filter-intrinsics.rs b/tests/ui/resolve/filter-intrinsics.rs new file mode 100644 index 000000000..c0956ef85 --- /dev/null +++ b/tests/ui/resolve/filter-intrinsics.rs @@ -0,0 +1,10 @@ +fn main() { + // Should suggest only `std::mem::size_of` + let _ = size_of::(); + //~^ ERROR cannot find + + // Should suggest `std::intrinsics::fabsf64`, + // since there is no non-intrinsic to suggest. + let _ = fabsf64(1.0); + //~^ ERROR cannot find +} diff --git a/tests/ui/resolve/filter-intrinsics.stderr b/tests/ui/resolve/filter-intrinsics.stderr new file mode 100644 index 000000000..955070891 --- /dev/null +++ b/tests/ui/resolve/filter-intrinsics.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find function `size_of` in this scope + --> $DIR/filter-intrinsics.rs:3:13 + | +LL | let _ = size_of::(); + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::size_of; + | + +error[E0425]: cannot find function `fabsf64` in this scope + --> $DIR/filter-intrinsics.rs:8:13 + | +LL | let _ = fabsf64(1.0); + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::intrinsics::fabsf64; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/impl-items-vis-unresolved.rs b/tests/ui/resolve/impl-items-vis-unresolved.rs new file mode 100644 index 000000000..1494c1cf9 --- /dev/null +++ b/tests/ui/resolve/impl-items-vis-unresolved.rs @@ -0,0 +1,26 @@ +// Visibilities on impl items expanded from macros are resolved (issue #64705). + +macro_rules! perftools_inline { + ($($item:tt)*) => ( + $($item)* + ); +} + +mod state { + pub struct RawFloatState; + impl RawFloatState { + perftools_inline! { + pub(super) fn new() {} // OK + } + } +} + +pub struct RawFloatState; +impl RawFloatState { + perftools_inline! { + pub(super) fn new() {} + //~^ ERROR failed to resolve: there are too many leading `super` keywords + } +} + +fn main() {} diff --git a/tests/ui/resolve/impl-items-vis-unresolved.stderr b/tests/ui/resolve/impl-items-vis-unresolved.stderr new file mode 100644 index 000000000..f2293d28e --- /dev/null +++ b/tests/ui/resolve/impl-items-vis-unresolved.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/impl-items-vis-unresolved.rs:21:13 + | +LL | pub(super) fn new() {} + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-100365.rs b/tests/ui/resolve/issue-100365.rs new file mode 100644 index 000000000..1d8835036 --- /dev/null +++ b/tests/ui/resolve/issue-100365.rs @@ -0,0 +1,50 @@ +fn main() { + let addr = Into::.into([127, 0, 0, 1]); + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator + + let _ = Into.into(()); + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator + + let _ = Into::<()>.into; + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator +} + +macro_rules! Trait { + () => { + ::std::iter::Iterator + //~^ ERROR expected value, found trait `std::iter::Iterator` + //~| ERROR expected value, found trait `std::iter::Iterator` + }; +} + +macro_rules! create { + () => { + Into::.into("") + //~^ ERROR expected value, found trait `Into` + //~| HELP use the path separator + }; +} + +fn interaction_with_macros() { + // + // Note that if the receiver is a macro call, we do not want to suggest to replace + // `.` with `::` as that would be a syntax error. + // Since the receiver is a trait and not a type, we cannot suggest to surround + // it with angle brackets. It would be interpreted as a trait object type void of + // `dyn` which is most likely not what the user intended to write. + // `<_ as Trait!()>::` is also not an option as it's equally syntactically invalid. + // + + Trait!().map(std::convert::identity); // no `help` here! + + Trait!().map; // no `help` here! + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(); +} diff --git a/tests/ui/resolve/issue-100365.stderr b/tests/ui/resolve/issue-100365.stderr new file mode 100644 index 000000000..372d77266 --- /dev/null +++ b/tests/ui/resolve/issue-100365.stderr @@ -0,0 +1,54 @@ +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:2:16 + | +LL | let addr = Into::.into([127, 0, 0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:6:13 + | +LL | let _ = Into.into(()); + | ^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:10:13 + | +LL | let _ = Into::<()>.into; + | ^^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found trait `std::iter::Iterator` + --> $DIR/issue-100365.rs:17:9 + | +LL | ::std::iter::Iterator + | ^^^^^^^^^^^^^^^^^^^^^ not a value +... +LL | Trait!().map(std::convert::identity); // no `help` here! + | -------- in this macro invocation + | + = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found trait `std::iter::Iterator` + --> $DIR/issue-100365.rs:17:9 + | +LL | ::std::iter::Iterator + | ^^^^^^^^^^^^^^^^^^^^^ not a value +... +LL | Trait!().map; // no `help` here! + | -------- in this macro invocation + | + = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found trait `Into` + --> $DIR/issue-100365.rs:25:9 + | +LL | Into::.into("") + | ^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(); + | --------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-101749-2.rs b/tests/ui/resolve/issue-101749-2.rs new file mode 100644 index 000000000..4d3d46944 --- /dev/null +++ b/tests/ui/resolve/issue-101749-2.rs @@ -0,0 +1,16 @@ +struct Rectangle { + width: i32, + height: i32, +} +impl Rectangle { + fn new(width: i32, height: i32) -> Self { + Self { width, height } + } +} + +fn main() { + let rect = Rectangle::new(3, 4); + // `area` is not implemented for `Rectangle`, so this should not suggest + let _ = rect::area(); + //~^ ERROR failed to resolve: use of undeclared crate or module `rect` +} diff --git a/tests/ui/resolve/issue-101749-2.stderr b/tests/ui/resolve/issue-101749-2.stderr new file mode 100644 index 000000000..370d4b145 --- /dev/null +++ b/tests/ui/resolve/issue-101749-2.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `rect` + --> $DIR/issue-101749-2.rs:14:13 + | +LL | let _ = rect::area(); + | ^^^^ use of undeclared crate or module `rect` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-101749.fixed b/tests/ui/resolve/issue-101749.fixed new file mode 100644 index 000000000..3e5544296 --- /dev/null +++ b/tests/ui/resolve/issue-101749.fixed @@ -0,0 +1,19 @@ +// run-rustfix +struct Rectangle { + width: i32, + height: i32, +} +impl Rectangle { + fn new(width: i32, height: i32) -> Self { + Self { width, height } + } + fn area(&self) -> i32 { + self.height * self.width + } +} + +fn main() { + let rect = Rectangle::new(3, 4); + let _ = rect.area(); + //~^ ERROR failed to resolve: use of undeclared crate or module `rect` +} diff --git a/tests/ui/resolve/issue-101749.rs b/tests/ui/resolve/issue-101749.rs new file mode 100644 index 000000000..fd67ccab6 --- /dev/null +++ b/tests/ui/resolve/issue-101749.rs @@ -0,0 +1,19 @@ +// run-rustfix +struct Rectangle { + width: i32, + height: i32, +} +impl Rectangle { + fn new(width: i32, height: i32) -> Self { + Self { width, height } + } + fn area(&self) -> i32 { + self.height * self.width + } +} + +fn main() { + let rect = Rectangle::new(3, 4); + let _ = rect::area(); + //~^ ERROR failed to resolve: use of undeclared crate or module `rect` +} diff --git a/tests/ui/resolve/issue-101749.stderr b/tests/ui/resolve/issue-101749.stderr new file mode 100644 index 000000000..dd29d7fc0 --- /dev/null +++ b/tests/ui/resolve/issue-101749.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `rect` + --> $DIR/issue-101749.rs:17:13 + | +LL | let _ = rect::area(); + | ^^^^ use of undeclared crate or module `rect` + | +help: you may have meant to call an instance method + | +LL | let _ = rect.area(); + | ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-10200.rs b/tests/ui/resolve/issue-10200.rs new file mode 100644 index 000000000..fe36a7e00 --- /dev/null +++ b/tests/ui/resolve/issue-10200.rs @@ -0,0 +1,9 @@ +struct Foo(bool); +fn foo(_: usize) -> Foo { Foo(false) } + +fn main() { + match Foo(true) { + foo(x) //~ ERROR expected tuple struct or tuple variant, found function `foo` + => () + } +} diff --git a/tests/ui/resolve/issue-10200.stderr b/tests/ui/resolve/issue-10200.stderr new file mode 100644 index 000000000..e60489f5b --- /dev/null +++ b/tests/ui/resolve/issue-10200.stderr @@ -0,0 +1,12 @@ +error[E0532]: expected tuple struct or tuple variant, found function `foo` + --> $DIR/issue-10200.rs:6:9 + | +LL | struct Foo(bool); + | ----------------- similarly named tuple struct `Foo` defined here +... +LL | foo(x) + | ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/resolve/issue-102946.rs b/tests/ui/resolve/issue-102946.rs new file mode 100644 index 000000000..c6feca6f3 --- /dev/null +++ b/tests/ui/resolve/issue-102946.rs @@ -0,0 +1,7 @@ +impl Error for str::Utf8Error { + //~^ ERROR cannot find trait `Error` in this scope + //~| ERROR ambiguous associated type + fn description(&self) {} +} + +fn main() {} diff --git a/tests/ui/resolve/issue-102946.stderr b/tests/ui/resolve/issue-102946.stderr new file mode 100644 index 000000000..65be0258e --- /dev/null +++ b/tests/ui/resolve/issue-102946.stderr @@ -0,0 +1,26 @@ +error[E0405]: cannot find trait `Error` in this scope + --> $DIR/issue-102946.rs:1:6 + | +LL | impl Error for str::Utf8Error { + | ^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::error::Error; + | + +error[E0223]: ambiguous associated type + --> $DIR/issue-102946.rs:1:16 + | +LL | impl Error for str::Utf8Error { + | ^^^^^^^^^^^^^^ + | +help: you are looking for the module in `std`, not the primitive type + | +LL | impl Error for std::str::Utf8Error { + | +++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0223, E0405. +For more information about an error, try `rustc --explain E0223`. diff --git a/tests/ui/resolve/issue-103202.rs b/tests/ui/resolve/issue-103202.rs new file mode 100644 index 000000000..469d9d7c8 --- /dev/null +++ b/tests/ui/resolve/issue-103202.rs @@ -0,0 +1,7 @@ +struct S {} + +impl S { + fn f(self: &S::x) {} //~ ERROR ambiguous associated type +} + +fn main() {} diff --git a/tests/ui/resolve/issue-103202.stderr b/tests/ui/resolve/issue-103202.stderr new file mode 100644 index 000000000..d4d141fb0 --- /dev/null +++ b/tests/ui/resolve/issue-103202.stderr @@ -0,0 +1,14 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-103202.rs:4:17 + | +LL | fn f(self: &S::x) {} + | ^^^^ + | +help: if there were a trait named `Example` with associated type `x` implemented for `S`, you could use the fully-qualified path + | +LL | fn f(self: &::x) {} + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/resolve/issue-103474.rs b/tests/ui/resolve/issue-103474.rs new file mode 100644 index 000000000..14f2259e1 --- /dev/null +++ b/tests/ui/resolve/issue-103474.rs @@ -0,0 +1,28 @@ +struct S {} +impl S { + fn first(&self) {} + + fn second(&self) { + first() + //~^ ERROR cannot find function `first` in this scope + } + + fn third(&self) { + no_method_err() + //~^ ERROR cannot find function `no_method_err` in this scope + } +} + +// https://github.com/rust-lang/rust/pull/103531#discussion_r1004728080 +struct Foo { + i: i32, +} + +impl Foo { + fn needs_self() { + this.i + //~^ ERROR cannot find value `this` in this scope + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-103474.stderr b/tests/ui/resolve/issue-103474.stderr new file mode 100644 index 000000000..415d23155 --- /dev/null +++ b/tests/ui/resolve/issue-103474.stderr @@ -0,0 +1,35 @@ +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-103474.rs:23:9 + | +LL | this.i + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.i + | ~~~~ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn needs_self(&self) { + | +++++ + +error[E0425]: cannot find function `first` in this scope + --> $DIR/issue-103474.rs:6:9 + | +LL | first() + | ^^^^^ not found in this scope + | +help: consider using the associated function + | +LL | self.first() + | +++++ + +error[E0425]: cannot find function `no_method_err` in this scope + --> $DIR/issue-103474.rs:11:9 + | +LL | no_method_err() + | ^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-104700-inner_scope.rs b/tests/ui/resolve/issue-104700-inner_scope.rs new file mode 100644 index 000000000..e8f28c113 --- /dev/null +++ b/tests/ui/resolve/issue-104700-inner_scope.rs @@ -0,0 +1,11 @@ +fn main() { + let foo = 1; + { + let bar = 2; + let test_func = |x| x > 3; + } + if bar == 2 { //~ ERROR cannot find value + println!("yes"); + } + test_func(1); //~ ERROR cannot find function +} diff --git a/tests/ui/resolve/issue-104700-inner_scope.stderr b/tests/ui/resolve/issue-104700-inner_scope.stderr new file mode 100644 index 000000000..051b234fc --- /dev/null +++ b/tests/ui/resolve/issue-104700-inner_scope.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/issue-104700-inner_scope.rs:7:8 + | +LL | if bar == 2 { + | ^^^ + | +help: the binding `bar` is available in a different scope in the same function + --> $DIR/issue-104700-inner_scope.rs:4:13 + | +LL | let bar = 2; + | ^^^ + +error[E0425]: cannot find function `test_func` in this scope + --> $DIR/issue-104700-inner_scope.rs:10:5 + | +LL | test_func(1); + | ^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-105069.rs b/tests/ui/resolve/issue-105069.rs new file mode 100644 index 000000000..73455cf77 --- /dev/null +++ b/tests/ui/resolve/issue-105069.rs @@ -0,0 +1,11 @@ +use self::A::*; +use V; //~ ERROR `V` is ambiguous +use self::B::*; +enum A { + V +} +enum B { + V +} + +fn main() {} diff --git a/tests/ui/resolve/issue-105069.stderr b/tests/ui/resolve/issue-105069.stderr new file mode 100644 index 000000000..1e6c9c6e2 --- /dev/null +++ b/tests/ui/resolve/issue-105069.stderr @@ -0,0 +1,21 @@ +error[E0659]: `V` is ambiguous + --> $DIR/issue-105069.rs:2:5 + | +LL | use V; + | ^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `V` could refer to the variant imported here + --> $DIR/issue-105069.rs:1:5 + | +LL | use self::A::*; + | ^^^^^^^^^^ +note: `V` could also refer to the variant imported here + --> $DIR/issue-105069.rs:3:5 + | +LL | use self::B::*; + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/resolve/issue-12796.rs b/tests/ui/resolve/issue-12796.rs new file mode 100644 index 000000000..942d6b9a5 --- /dev/null +++ b/tests/ui/resolve/issue-12796.rs @@ -0,0 +1,9 @@ +trait Trait { + fn outer(&self) { + fn inner(_: &Self) { + //~^ ERROR can't use generic parameters from outer function + } + } +} + +fn main() { } diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr new file mode 100644 index 000000000..a01fd2d65 --- /dev/null +++ b/tests/ui/resolve/issue-12796.stderr @@ -0,0 +1,12 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-12796.rs:3:22 + | +LL | fn inner(_: &Self) { + | ^^^^ + | | + | use of generic parameter from outer function + | can't use `Self` here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-14254.rs b/tests/ui/resolve/issue-14254.rs new file mode 100644 index 000000000..78add29ca --- /dev/null +++ b/tests/ui/resolve/issue-14254.rs @@ -0,0 +1,105 @@ +trait Foo { + fn bar(&self); + fn baz(&self) { } + fn bah(_: Option<&Self>) { } +} + +struct BarTy { + x : isize, + y : f64, +} + +impl BarTy { + fn a() {} + fn b(&self) {} +} + +impl Foo for *const BarTy { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + a; + //~^ ERROR cannot find value `a` + } +} + +impl<'a> Foo for &'a BarTy { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + x; + //~^ ERROR cannot find value `x` + y; + //~^ ERROR cannot find value `y` + a; + //~^ ERROR cannot find value `a` + bah; + //~^ ERROR cannot find value `bah` + b; + //~^ ERROR cannot find value `b` + } +} + +impl<'a> Foo for &'a mut BarTy { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + x; + //~^ ERROR cannot find value `x` + y; + //~^ ERROR cannot find value `y` + a; + //~^ ERROR cannot find value `a` + bah; + //~^ ERROR cannot find value `bah` + b; + //~^ ERROR cannot find value `b` + } +} + +impl Foo for Box { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + } +} + +impl Foo for *const isize { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + } +} + +impl<'a> Foo for &'a isize { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + } +} + +impl<'a> Foo for &'a mut isize { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + } +} + +impl Foo for Box { + fn bar(&self) { + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-14254.stderr b/tests/ui/resolve/issue-14254.stderr new file mode 100644 index 000000000..690a40f7e --- /dev/null +++ b/tests/ui/resolve/issue-14254.stderr @@ -0,0 +1,182 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-14254.rs:21:9 + | +LL | a; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-14254.rs:30:9 + | +LL | x; + | ^ help: you might have meant to use the available field: `self.x` + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-14254.rs:32:9 + | +LL | y; + | ^ help: you might have meant to use the available field: `self.y` + +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-14254.rs:34:9 + | +LL | a; + | ^ not found in this scope + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:36:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find value `b` in this scope + --> $DIR/issue-14254.rs:38:9 + | +LL | b; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-14254.rs:47:9 + | +LL | x; + | ^ help: you might have meant to use the available field: `self.x` + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-14254.rs:49:9 + | +LL | y; + | ^ help: you might have meant to use the available field: `self.y` + +error[E0425]: cannot find value `a` in this scope + --> $DIR/issue-14254.rs:51:9 + | +LL | a; + | ^ not found in this scope + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:53:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find value `b` in this scope + --> $DIR/issue-14254.rs:55:9 + | +LL | b; + | ^ not found in this scope + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:64:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:73:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:82:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:91:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/issue-14254.rs:100:9 + | +LL | bah; + | ^^^ + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:19:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:28:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:45:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:62:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:71:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:80:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:89:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/issue-14254.rs:98:9 + | +LL | baz(); + | ^^^ help: you might have meant to call the method: `self.baz` + +error: aborting due to 24 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-16058.rs b/tests/ui/resolve/issue-16058.rs new file mode 100644 index 000000000..048aaf65f --- /dev/null +++ b/tests/ui/resolve/issue-16058.rs @@ -0,0 +1,18 @@ +// ignore-sgx std::os::fortanix_sgx::usercalls::raw::Result changes compiler suggestions + +pub struct GslResult { + pub val: f64, + pub err: f64 +} + +impl GslResult { + pub fn new() -> GslResult { + Result { +//~^ ERROR expected struct, variant or union type, found enum `Result` + val: 0f64, + err: 0f64 + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-16058.stderr b/tests/ui/resolve/issue-16058.stderr new file mode 100644 index 000000000..c47d22cef --- /dev/null +++ b/tests/ui/resolve/issue-16058.stderr @@ -0,0 +1,18 @@ +error[E0574]: expected struct, variant or union type, found enum `Result` + --> $DIR/issue-16058.rs:10:9 + | +LL | Result { + | ^^^^^^ not a struct, variant or union type + | +help: consider importing one of these items instead + | +LL | use std::fmt::Result; + | +LL | use std::io::Result; + | +LL | use std::thread::Result; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/resolve/issue-17518.rs b/tests/ui/resolve/issue-17518.rs new file mode 100644 index 000000000..edaebc812 --- /dev/null +++ b/tests/ui/resolve/issue-17518.rs @@ -0,0 +1,7 @@ +enum SomeEnum { + E +} + +fn main() { + E { name: "foobar" }; //~ ERROR cannot find struct, variant or union type `E` +} diff --git a/tests/ui/resolve/issue-17518.stderr b/tests/ui/resolve/issue-17518.stderr new file mode 100644 index 000000000..034d0d01b --- /dev/null +++ b/tests/ui/resolve/issue-17518.stderr @@ -0,0 +1,14 @@ +error[E0422]: cannot find struct, variant or union type `E` in this scope + --> $DIR/issue-17518.rs:6:5 + | +LL | E { name: "foobar" }; + | ^ not found in this scope + | +help: consider importing this variant + | +LL | use SomeEnum::E; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/resolve/issue-18252.rs b/tests/ui/resolve/issue-18252.rs new file mode 100644 index 000000000..f6ebe2920 --- /dev/null +++ b/tests/ui/resolve/issue-18252.rs @@ -0,0 +1,8 @@ +enum Foo { + Variant { x: usize } +} + +fn main() { + let f = Foo::Variant(42); + //~^ ERROR expected value, found struct variant `Foo::Variant` +} diff --git a/tests/ui/resolve/issue-18252.stderr b/tests/ui/resolve/issue-18252.stderr new file mode 100644 index 000000000..d9006c0a6 --- /dev/null +++ b/tests/ui/resolve/issue-18252.stderr @@ -0,0 +1,9 @@ +error[E0533]: expected value, found struct variant `Foo::Variant` + --> $DIR/issue-18252.rs:6:13 + | +LL | let f = Foo::Variant(42); + | ^^^^^^^^^^^^ not a value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/resolve/issue-19452.rs b/tests/ui/resolve/issue-19452.rs new file mode 100644 index 000000000..1d3aa49ea --- /dev/null +++ b/tests/ui/resolve/issue-19452.rs @@ -0,0 +1,15 @@ +// aux-build:issue-19452-aux.rs + +extern crate issue_19452_aux; + +enum Homura { + Madoka { age: u32 } +} + +fn main() { + let homura = Homura::Madoka; + //~^ ERROR expected value, found struct variant `Homura::Madoka` + + let homura = issue_19452_aux::Homura::Madoka; + //~^ ERROR expected value, found struct variant `issue_19452_aux::Homura::Madoka` +} diff --git a/tests/ui/resolve/issue-19452.stderr b/tests/ui/resolve/issue-19452.stderr new file mode 100644 index 000000000..eff89241f --- /dev/null +++ b/tests/ui/resolve/issue-19452.stderr @@ -0,0 +1,15 @@ +error[E0533]: expected value, found struct variant `Homura::Madoka` + --> $DIR/issue-19452.rs:10:18 + | +LL | let homura = Homura::Madoka; + | ^^^^^^^^^^^^^^ not a value + +error[E0533]: expected value, found struct variant `issue_19452_aux::Homura::Madoka` + --> $DIR/issue-19452.rs:13:18 + | +LL | let homura = issue_19452_aux::Homura::Madoka; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a value + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/resolve/issue-21221-1.rs b/tests/ui/resolve/issue-21221-1.rs new file mode 100644 index 000000000..b180624d2 --- /dev/null +++ b/tests/ui/resolve/issue-21221-1.rs @@ -0,0 +1,75 @@ +mod mul1 { + pub trait Mul {} +} + +mod mul2 { + pub trait Mul {} +} + +mod mul3 { + enum Mul { + Yes, + No + } +} + +mod mul4 { + type Mul = String; +} + +mod mul5 { + struct Mul{ + left_term: u32, + right_term: u32 + } +} + +#[derive(Debug)] +struct Foo; + +// When we comment the next line: +//use mul1::Mul; + +// BEFORE, we got the following error for the `impl` below: +// error: use of undeclared trait name `Mul` [E0405] +// AFTER, we get this message: +// error: trait `Mul` is not in scope. +// help: ... +// help: you can import several candidates into scope (`use ...;`): +// help: `mul1::Mul` +// help: `mul2::Mul` +// help: `std::ops::Mul` + +impl Mul for Foo { +//~^ ERROR cannot find trait `Mul` +} + +// BEFORE, we got: +// error: use of undeclared type name `Mul` [E0412] +// AFTER, we get: +// error: type name `Mul` is not in scope. Maybe you meant: +// help: ... +// help: you can import several candidates into scope (`use ...;`): +// help: `mul1::Mul` +// help: `mul2::Mul` +// help: `mul3::Mul` +// help: `mul4::Mul` +// help: and 2 other candidates +fn getMul() -> Mul { +//~^ ERROR cannot find type `Mul` +} + +// Let's also test what happens if the trait doesn't exist: +impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo { +//~^ ERROR cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` +} + +// Let's also test what happens if there's just one alternative: +impl Div for Foo { +//~^ ERROR cannot find trait `Div` +} + +fn main() { + let foo = Foo(); + println!("Hello, {:?}!", foo); +} diff --git a/tests/ui/resolve/issue-21221-1.stderr b/tests/ui/resolve/issue-21221-1.stderr new file mode 100644 index 000000000..538eeead9 --- /dev/null +++ b/tests/ui/resolve/issue-21221-1.stderr @@ -0,0 +1,51 @@ +error[E0405]: cannot find trait `Mul` in this scope + --> $DIR/issue-21221-1.rs:43:6 + | +LL | impl Mul for Foo { + | ^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use mul1::Mul; + | +LL | use mul2::Mul; + | +LL | use std::ops::Mul; + | + +error[E0412]: cannot find type `Mul` in this scope + --> $DIR/issue-21221-1.rs:58:16 + | +LL | fn getMul() -> Mul { + | ^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use mul1::Mul; + | +LL | use mul2::Mul; + | +LL | use std::ops::Mul; + | + +error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope + --> $DIR/issue-21221-1.rs:63:6 + | +LL | impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `Div` in this scope + --> $DIR/issue-21221-1.rs:68:6 + | +LL | impl Div for Foo { + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::ops::Div; + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0405, E0412. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-21221-2.rs b/tests/ui/resolve/issue-21221-2.rs new file mode 100644 index 000000000..dc13e46cb --- /dev/null +++ b/tests/ui/resolve/issue-21221-2.rs @@ -0,0 +1,21 @@ +pub mod foo { + pub mod bar { + // note: trait T is not public, but being in the current + // crate, it's fine to show it, since the programmer can + // decide to make it public based on the suggestion ... + pub trait T {} + } + // imports should be ignored: + use self::bar::T; +} + +pub mod baz { + pub use foo; + pub use std::ops::{Mul as T}; +} + +struct Foo; +impl T for Foo { } +//~^ ERROR cannot find trait `T` + +fn main() {} diff --git a/tests/ui/resolve/issue-21221-2.stderr b/tests/ui/resolve/issue-21221-2.stderr new file mode 100644 index 000000000..d4fd7cb12 --- /dev/null +++ b/tests/ui/resolve/issue-21221-2.stderr @@ -0,0 +1,16 @@ +error[E0405]: cannot find trait `T` in this scope + --> $DIR/issue-21221-2.rs:18:6 + | +LL | impl T for Foo { } + | ^ not found in this scope + | +help: consider importing one of these items + | +LL | use baz::T; + | +LL | use foo::bar::T; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-21221-3.rs b/tests/ui/resolve/issue-21221-3.rs new file mode 100644 index 000000000..f0c0a9fd6 --- /dev/null +++ b/tests/ui/resolve/issue-21221-3.rs @@ -0,0 +1,19 @@ +// testing whether the lookup mechanism picks up types +// defined in the outside crate + +// aux-build:issue-21221-3.rs + +extern crate issue_21221_3; + +struct Foo; + +// NOTE: This shows only traits accessible from the current +// crate, thus the two private entities: +// `issue_21221_3::outer::private_module::OuterTrait` and +// `issue_21221_3::outer::public_module::OuterTrait` +// are hidden from the view. +impl OuterTrait for Foo {} +//~^ ERROR cannot find trait `OuterTrait` +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/resolve/issue-21221-3.stderr b/tests/ui/resolve/issue-21221-3.stderr new file mode 100644 index 000000000..f12e5b09b --- /dev/null +++ b/tests/ui/resolve/issue-21221-3.stderr @@ -0,0 +1,14 @@ +error[E0405]: cannot find trait `OuterTrait` in this scope + --> $DIR/issue-21221-3.rs:15:6 + | +LL | impl OuterTrait for Foo {} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use issue_21221_3::outer::OuterTrait; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-21221-4.rs b/tests/ui/resolve/issue-21221-4.rs new file mode 100644 index 000000000..88d5bd06c --- /dev/null +++ b/tests/ui/resolve/issue-21221-4.rs @@ -0,0 +1,15 @@ +// testing whether the lookup mechanism picks up types +// defined in the outside crate + +// aux-build:issue-21221-4.rs + +extern crate issue_21221_4; + +struct Foo; + +impl T for Foo {} +//~^ ERROR cannot find trait `T` + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/resolve/issue-21221-4.stderr b/tests/ui/resolve/issue-21221-4.stderr new file mode 100644 index 000000000..fc15444d0 --- /dev/null +++ b/tests/ui/resolve/issue-21221-4.stderr @@ -0,0 +1,14 @@ +error[E0405]: cannot find trait `T` in this scope + --> $DIR/issue-21221-4.rs:10:6 + | +LL | impl T for Foo {} + | ^ not found in this scope + | +help: consider importing this trait + | +LL | use issue_21221_4::T; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/issue-22692.rs b/tests/ui/resolve/issue-22692.rs new file mode 100644 index 000000000..31a762614 --- /dev/null +++ b/tests/ui/resolve/issue-22692.rs @@ -0,0 +1,60 @@ +fn main() { + let _ = String.new(); + //~^ ERROR expected value, found struct `String` + //~| HELP use the path separator + + let _ = String.default; + //~^ ERROR expected value, found struct `String` + //~| HELP use the path separator + + let _ = Vec::<()>.with_capacity(1); + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator +} + +macro_rules! Type { + () => { + ::std::cell::Cell + //~^ ERROR expected value, found struct `std::cell::Cell` + //~| ERROR expected value, found struct `std::cell::Cell` + //~| ERROR expected value, found struct `std::cell::Cell` + }; +} + +macro_rules! create { + (type method) => { + Vec.new() + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + }; + (type field) => { + Vec.new + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + }; + (macro method) => { + Type!().new(0) + //~^ HELP use the path separator + }; +} + +fn interaction_with_macros() { + // + // Verify that we do not only suggest to replace `.` with `::` if the receiver is a + // macro call but that we also correctly suggest to surround it with angle brackets. + // + + Type!().get(); + //~^ HELP use the path separator + + Type! {}.get; + //~^ HELP use the path separator + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(type method); + let _ = create!(type field); + let _ = create!(macro method); +} diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/issue-22692.stderr new file mode 100644 index 000000000..6962aa161 --- /dev/null +++ b/tests/ui/resolve/issue-22692.stderr @@ -0,0 +1,88 @@ +error[E0423]: expected value, found struct `String` + --> $DIR/issue-22692.rs:2:13 + | +LL | let _ = String.new(); + | ^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found struct `String` + --> $DIR/issue-22692.rs:6:13 + | +LL | let _ = String.default; + | ^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-22692.rs:10:13 + | +LL | let _ = Vec::<()>.with_capacity(1); + | ^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/issue-22692.rs:17:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | Type!().get(); + | ------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | ::get(); + | ~~~~~~~~~~~ + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/issue-22692.rs:17:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | Type! {}.get; + | -------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | ::get; + | ~~~~~~~~~~~~ + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-22692.rs:26:9 + | +LL | Vec.new() + | ^^^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(type method); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-22692.rs:31:9 + | +LL | Vec.new + | ^^^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(type field); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/issue-22692.rs:17:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | let _ = create!(macro method); + | --------------------- in this macro invocation + | + = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | ::new(0) + | ~~~~~~~~~~~ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-2330.rs b/tests/ui/resolve/issue-2330.rs new file mode 100644 index 000000000..4560caba0 --- /dev/null +++ b/tests/ui/resolve/issue-2330.rs @@ -0,0 +1,13 @@ +enum Chan { } + +trait Channel { + fn send(&self, v: T); +} + +// `Chan` is not a trait, it's an enum +impl Chan for isize { //~ ERROR expected trait, found enum `Chan` + fn send(&self, v: isize) { panic!() } +} + +fn main() { +} diff --git a/tests/ui/resolve/issue-2330.stderr b/tests/ui/resolve/issue-2330.stderr new file mode 100644 index 000000000..877cf68b5 --- /dev/null +++ b/tests/ui/resolve/issue-2330.stderr @@ -0,0 +1,9 @@ +error[E0404]: expected trait, found enum `Chan` + --> $DIR/issue-2330.rs:8:6 + | +LL | impl Chan for isize { + | ^^^^ not a trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/issue-23305.rs b/tests/ui/resolve/issue-23305.rs new file mode 100644 index 000000000..6d7fe7c50 --- /dev/null +++ b/tests/ui/resolve/issue-23305.rs @@ -0,0 +1,8 @@ +pub trait ToNbt { + fn new(val: T) -> Self; +} + +impl dyn ToNbt {} +//~^ ERROR `Self` is not valid in the self type of an impl block + +fn main() {} diff --git a/tests/ui/resolve/issue-23305.stderr b/tests/ui/resolve/issue-23305.stderr new file mode 100644 index 000000000..aad1b583a --- /dev/null +++ b/tests/ui/resolve/issue-23305.stderr @@ -0,0 +1,10 @@ +error: `Self` is not valid in the self type of an impl block + --> $DIR/issue-23305.rs:5:16 + | +LL | impl dyn ToNbt {} + | ^^^^ + | + = note: replace `Self` with a different type + +error: aborting due to previous error + diff --git a/tests/ui/resolve/issue-2356.rs b/tests/ui/resolve/issue-2356.rs new file mode 100644 index 000000000..fe9bf4d44 --- /dev/null +++ b/tests/ui/resolve/issue-2356.rs @@ -0,0 +1,94 @@ +trait Groom { + fn shave(other: usize); +} + +pub struct Cat { + whiskers: isize, +} + +pub enum MaybeDog { + Dog, + NoDog +} + +impl MaybeDog { + fn bark() { + // If this provides a suggestion, it's a bug as MaybeDog doesn't impl Groom + shave(); + //~^ ERROR cannot find function `shave` + } +} + +impl Clone for Cat { + fn clone(&self) -> Self { + clone(); + //~^ ERROR cannot find function `clone` + loop {} + } +} +impl Default for Cat { + fn default() -> Self { + default(); + //~^ ERROR cannot find function `default` in this scope [E0425] + loop {} + } +} + +impl Groom for Cat { + fn shave(other: usize) { + whiskers -= other; + //~^ ERROR cannot find value `whiskers` + shave(4); + //~^ ERROR cannot find function `shave` + purr(); + //~^ ERROR cannot find function `purr` + } +} + +impl Cat { + fn static_method() {} + + fn purr_louder() { + static_method(); + //~^ ERROR cannot find function `static_method` + purr(); + //~^ ERROR cannot find function `purr` + purr(); + //~^ ERROR cannot find function `purr` + purr(); + //~^ ERROR cannot find function `purr` + } +} + +impl Cat { + fn meow() { + if self.whiskers > 3 { + //~^ ERROR expected value, found module `self` + println!("MEOW"); + } + } + + fn purr(&self) { + grow_older(); + //~^ ERROR cannot find function `grow_older` + shave(); + //~^ ERROR cannot find function `shave` + } + + fn burn_whiskers(&mut self) { + whiskers = 0; + //~^ ERROR cannot find value `whiskers` + } + + pub fn grow_older(other:usize) { + whiskers = 4; + //~^ ERROR cannot find value `whiskers` + purr_louder(); + //~^ ERROR cannot find function `purr_louder` + } +} + +fn main() { + self += 1; + //~^ ERROR expected value, found module `self` +} diff --git a/tests/ui/resolve/issue-2356.stderr b/tests/ui/resolve/issue-2356.stderr new file mode 100644 index 000000000..36f3da7c9 --- /dev/null +++ b/tests/ui/resolve/issue-2356.stderr @@ -0,0 +1,134 @@ +error[E0425]: cannot find function `default` in this scope + --> $DIR/issue-2356.rs:31:5 + | +LL | default(); + | ^^^^^^^ + | +help: you might have meant to call the associated function + | +LL | Self::default(); + | ~~~~~~~~~~~~~ +help: consider importing this function + | +LL | use std::default::default; + | + +error[E0425]: cannot find value `whiskers` in this scope + --> $DIR/issue-2356.rs:39:5 + | +LL | whiskers -= other; + | ^^^^^^^^ a field by this name exists in `Self` + +error[E0424]: expected value, found module `self` + --> $DIR/issue-2356.rs:65:8 + | +LL | fn meow() { + | ---- this function doesn't have a `self` parameter +LL | if self.whiskers > 3 { + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn meow(&self) { + | +++++ + +error[E0425]: cannot find value `whiskers` in this scope + --> $DIR/issue-2356.rs:79:5 + | +LL | whiskers = 0; + | ^^^^^^^^ help: you might have meant to use the available field: `self.whiskers` + +error[E0425]: cannot find value `whiskers` in this scope + --> $DIR/issue-2356.rs:84:5 + | +LL | whiskers = 4; + | ^^^^^^^^ a field by this name exists in `Self` + +error[E0424]: expected value, found module `self` + --> $DIR/issue-2356.rs:92:5 + | +LL | fn main() { + | ---- this function can't have a `self` parameter +LL | self += 1; + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + +error[E0425]: cannot find function `shave` in this scope + --> $DIR/issue-2356.rs:17:5 + | +LL | shave(); + | ^^^^^ not found in this scope + +error[E0425]: cannot find function `clone` in this scope + --> $DIR/issue-2356.rs:24:5 + | +LL | clone(); + | ^^^^^ help: you might have meant to call the method: `self.clone` + +error[E0425]: cannot find function `shave` in this scope + --> $DIR/issue-2356.rs:41:5 + | +LL | shave(4); + | ^^^^^ help: you might have meant to call the associated function: `Self::shave` + +error[E0425]: cannot find function `purr` in this scope + --> $DIR/issue-2356.rs:43:5 + | +LL | purr(); + | ^^^^ not found in this scope + +error[E0425]: cannot find function `static_method` in this scope + --> $DIR/issue-2356.rs:52:9 + | +LL | static_method(); + | ^^^^^^^^^^^^^ not found in this scope + | +help: consider using the associated function + | +LL | Self::static_method(); + | ++++++ + +error[E0425]: cannot find function `purr` in this scope + --> $DIR/issue-2356.rs:54:9 + | +LL | purr(); + | ^^^^ not found in this scope + +error[E0425]: cannot find function `purr` in this scope + --> $DIR/issue-2356.rs:56:9 + | +LL | purr(); + | ^^^^ not found in this scope + +error[E0425]: cannot find function `purr` in this scope + --> $DIR/issue-2356.rs:58:9 + | +LL | purr(); + | ^^^^ not found in this scope + +error[E0425]: cannot find function `grow_older` in this scope + --> $DIR/issue-2356.rs:72:5 + | +LL | grow_older(); + | ^^^^^^^^^^ not found in this scope + | +help: consider using the associated function + | +LL | Self::grow_older(); + | ++++++ + +error[E0425]: cannot find function `shave` in this scope + --> $DIR/issue-2356.rs:74:5 + | +LL | shave(); + | ^^^^^ not found in this scope + +error[E0425]: cannot find function `purr_louder` in this scope + --> $DIR/issue-2356.rs:86:5 + | +LL | purr_louder(); + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0424, E0425. +For more information about an error, try `rustc --explain E0424`. diff --git a/tests/ui/resolve/issue-23716.rs b/tests/ui/resolve/issue-23716.rs new file mode 100644 index 000000000..e9139c0aa --- /dev/null +++ b/tests/ui/resolve/issue-23716.rs @@ -0,0 +1,17 @@ +static foo: i32 = 0; + +fn bar(foo: i32) {} +//~^ ERROR function parameters cannot shadow statics +//~| cannot be named the same as a static + +mod submod { + pub static answer: i32 = 42; +} + +use self::submod::answer; + +fn question(answer: i32) {} +//~^ ERROR function parameters cannot shadow statics +//~| cannot be named the same as a static +fn main() { +} diff --git a/tests/ui/resolve/issue-23716.stderr b/tests/ui/resolve/issue-23716.stderr new file mode 100644 index 000000000..8b89c350c --- /dev/null +++ b/tests/ui/resolve/issue-23716.stderr @@ -0,0 +1,21 @@ +error[E0530]: function parameters cannot shadow statics + --> $DIR/issue-23716.rs:3:8 + | +LL | static foo: i32 = 0; + | -------------------- the static `foo` is defined here +LL | +LL | fn bar(foo: i32) {} + | ^^^ cannot be named the same as a static + +error[E0530]: function parameters cannot shadow statics + --> $DIR/issue-23716.rs:13:13 + | +LL | use self::submod::answer; + | -------------------- the static `answer` is imported here +LL | +LL | fn question(answer: i32) {} + | ^^^^^^ cannot be named the same as a static + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/resolve/issue-24968.rs b/tests/ui/resolve/issue-24968.rs new file mode 100644 index 000000000..19e16abce --- /dev/null +++ b/tests/ui/resolve/issue-24968.rs @@ -0,0 +1,30 @@ +// Also includes more Self usages per #93796 + +fn foo(_: Self) { +//~^ ERROR cannot find type `Self` +} + +fn foo2() { + let x: Self; + //~^ ERROR cannot find type `Self` +} + +type Foo +where + Self: Clone, +//~^ ERROR cannot find type `Self` += Vec; + +const FOO: Self = 0; +//~^ ERROR cannot find type `Self` + +const FOO2: u32 = Self::bar(); +//~^ ERROR failed to resolve: `Self` + +static FOO_S: Self = 0; +//~^ ERROR cannot find type `Self` + +static FOO_S2: u32 = Self::bar(); +//~^ ERROR failed to resolve: `Self` + +fn main() {} diff --git a/tests/ui/resolve/issue-24968.stderr b/tests/ui/resolve/issue-24968.stderr new file mode 100644 index 000000000..82f5a1d5b --- /dev/null +++ b/tests/ui/resolve/issue-24968.stderr @@ -0,0 +1,57 @@ +error[E0411]: cannot find type `Self` in this scope + --> $DIR/issue-24968.rs:3:11 + | +LL | fn foo(_: Self) { + | --- ^^^^ `Self` is only available in impls, traits, and type definitions + | | + | `Self` not allowed in a function + +error[E0411]: cannot find type `Self` in this scope + --> $DIR/issue-24968.rs:8:12 + | +LL | fn foo2() { + | ---- `Self` not allowed in a function +LL | let x: Self; + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0411]: cannot find type `Self` in this scope + --> $DIR/issue-24968.rs:14:5 + | +LL | type Foo + | --- `Self` not allowed in a type alias +LL | where +LL | Self: Clone, + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0411]: cannot find type `Self` in this scope + --> $DIR/issue-24968.rs:18:12 + | +LL | const FOO: Self = 0; + | --- ^^^^ `Self` is only available in impls, traits, and type definitions + | | + | `Self` not allowed in a constant item + +error[E0411]: cannot find type `Self` in this scope + --> $DIR/issue-24968.rs:24:15 + | +LL | static FOO_S: Self = 0; + | ----- ^^^^ `Self` is only available in impls, traits, and type definitions + | | + | `Self` not allowed in a static item + +error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions + --> $DIR/issue-24968.rs:21:19 + | +LL | const FOO2: u32 = Self::bar(); + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions + --> $DIR/issue-24968.rs:27:22 + | +LL | static FOO_S2: u32 = Self::bar(); + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0411, E0433. +For more information about an error, try `rustc --explain E0411`. diff --git a/tests/ui/resolve/issue-26545.rs b/tests/ui/resolve/issue-26545.rs new file mode 100644 index 000000000..5652ee747 --- /dev/null +++ b/tests/ui/resolve/issue-26545.rs @@ -0,0 +1,12 @@ +mod foo { + pub struct B(pub ()); +} + +mod baz { + fn foo() { + B(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `B` in this scope [E0425] + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-26545.stderr b/tests/ui/resolve/issue-26545.stderr new file mode 100644 index 000000000..d3c866925 --- /dev/null +++ b/tests/ui/resolve/issue-26545.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function, tuple struct or tuple variant `B` in this scope + --> $DIR/issue-26545.rs:7:9 + | +LL | B(()); + | ^ not found in this scope + | +help: consider importing this tuple struct + | +LL | use foo::B; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-3021-c.rs b/tests/ui/resolve/issue-3021-c.rs new file mode 100644 index 000000000..94ed1fdf7 --- /dev/null +++ b/tests/ui/resolve/issue-3021-c.rs @@ -0,0 +1,9 @@ +fn siphash() { + + trait U { + fn g(&self, x: T) -> T; //~ ERROR can't use generic parameters from outer function + //~^ ERROR can't use generic parameters from outer function + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-3021-c.stderr b/tests/ui/resolve/issue-3021-c.stderr new file mode 100644 index 000000000..5176efc3a --- /dev/null +++ b/tests/ui/resolve/issue-3021-c.stderr @@ -0,0 +1,25 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-3021-c.rs:4:24 + | +LL | fn siphash() { + | - type parameter from outer function +LL | +LL | trait U { + | - help: try using a local generic parameter instead: `` +LL | fn g(&self, x: T) -> T; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-3021-c.rs:4:30 + | +LL | fn siphash() { + | - type parameter from outer function +LL | +LL | trait U { + | - help: try using a local generic parameter instead: `` +LL | fn g(&self, x: T) -> T; + | ^ use of generic parameter from outer function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-3021.rs b/tests/ui/resolve/issue-3021.rs new file mode 100644 index 000000000..a672261f8 --- /dev/null +++ b/tests/ui/resolve/issue-3021.rs @@ -0,0 +1,18 @@ +trait SipHash { + fn reset(&self); +} + +fn siphash(k0 : u64) { + struct SipState { + v0: u64, + } + + impl SipHash for SipState { + fn reset(&self) { + self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment + } + } + panic!(); +} + +fn main() {} diff --git a/tests/ui/resolve/issue-3021.stderr b/tests/ui/resolve/issue-3021.stderr new file mode 100644 index 000000000..d5b015eec --- /dev/null +++ b/tests/ui/resolve/issue-3021.stderr @@ -0,0 +1,11 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/issue-3021.rs:12:22 + | +LL | self.v0 = k0 ^ 0x736f6d6570736575; + | ^^ + | + = help: use the `|| { ... }` closure form instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/resolve/issue-30535.rs b/tests/ui/resolve/issue-30535.rs new file mode 100644 index 000000000..d48f00d5a --- /dev/null +++ b/tests/ui/resolve/issue-30535.rs @@ -0,0 +1,9 @@ +// aux-build:issue-30535.rs + +extern crate issue_30535 as foo; + +fn bar( + _: foo::Foo::FooV //~ ERROR expected type, found variant `foo::Foo::FooV` +) {} + +fn main() {} diff --git a/tests/ui/resolve/issue-30535.stderr b/tests/ui/resolve/issue-30535.stderr new file mode 100644 index 000000000..e3692934b --- /dev/null +++ b/tests/ui/resolve/issue-30535.stderr @@ -0,0 +1,12 @@ +error[E0573]: expected type, found variant `foo::Foo::FooV` + --> $DIR/issue-30535.rs:6:8 + | +LL | _: foo::Foo::FooV + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `foo::Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/resolve/issue-31845.rs b/tests/ui/resolve/issue-31845.rs new file mode 100644 index 000000000..f6dc11502 --- /dev/null +++ b/tests/ui/resolve/issue-31845.rs @@ -0,0 +1,12 @@ +// Checks lexical scopes cannot see through normal module boundaries + +fn f() { + fn g() {} + mod foo { + fn h() { + g(); //~ ERROR cannot find function `g` in this scope + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-31845.stderr b/tests/ui/resolve/issue-31845.stderr new file mode 100644 index 000000000..562819385 --- /dev/null +++ b/tests/ui/resolve/issue-31845.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `g` in this scope + --> $DIR/issue-31845.rs:7:12 + | +LL | g(); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-33876.rs b/tests/ui/resolve/issue-33876.rs new file mode 100644 index 000000000..e233ec631 --- /dev/null +++ b/tests/ui/resolve/issue-33876.rs @@ -0,0 +1,12 @@ +use std::any::Any; + +struct Foo; + +trait Bar {} + +impl Bar for Foo {} + +fn main() { + let any: &dyn Any = &Bar; //~ ERROR expected value, found trait `Bar` + if any.is::() { println!("u32"); } +} diff --git a/tests/ui/resolve/issue-33876.stderr b/tests/ui/resolve/issue-33876.stderr new file mode 100644 index 000000000..52308f2a7 --- /dev/null +++ b/tests/ui/resolve/issue-33876.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected value, found trait `Bar` + --> $DIR/issue-33876.rs:10:26 + | +LL | let any: &dyn Any = &Bar; + | ^^^ not a value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-35675.rs b/tests/ui/resolve/issue-35675.rs new file mode 100644 index 000000000..683761667 --- /dev/null +++ b/tests/ui/resolve/issue-35675.rs @@ -0,0 +1,42 @@ +// these two HELPs are actually in a new line between this line and the `enum Fruit` line +enum Fruit { + Apple(i64), + Orange(i64), +} + +fn should_return_fruit() -> Apple { + //~^ ERROR cannot find type `Apple` in this scope + Apple(5) + //~^ ERROR cannot find function, tuple struct or tuple variant `Apple` in this scope +} + +fn should_return_fruit_too() -> Fruit::Apple { + //~^ ERROR expected type, found variant `Fruit::Apple` + Apple(5) + //~^ ERROR cannot find function, tuple struct or tuple variant `Apple` in this scope +} + +fn foo() -> Ok { + //~^ ERROR expected type, found variant `Ok` + Ok(()) +} + +fn bar() -> Variant3 { + //~^ ERROR cannot find type `Variant3` in this scope +} + +fn qux() -> Some { + //~^ ERROR expected type, found variant `Some` + Some(1) +} + +fn main() {} + +mod x { + pub enum Enum { + Variant1, + Variant2(), + Variant3(usize), + Variant4 {}, + } +} diff --git a/tests/ui/resolve/issue-35675.stderr b/tests/ui/resolve/issue-35675.stderr new file mode 100644 index 000000000..4a06196d5 --- /dev/null +++ b/tests/ui/resolve/issue-35675.stderr @@ -0,0 +1,75 @@ +error[E0412]: cannot find type `Apple` in this scope + --> $DIR/issue-35675.rs:7:29 + | +LL | fn should_return_fruit() -> Apple { + | ^^^^^ not found in this scope + | +help: there is an enum variant `Fruit::Apple`; try using the variant's enum + | +LL | fn should_return_fruit() -> Fruit { + | ~~~~~ + +error[E0425]: cannot find function, tuple struct or tuple variant `Apple` in this scope + --> $DIR/issue-35675.rs:9:5 + | +LL | Apple(5) + | ^^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL | use Fruit::Apple; + | + +error[E0573]: expected type, found variant `Fruit::Apple` + --> $DIR/issue-35675.rs:13:33 + | +LL | fn should_return_fruit_too() -> Fruit::Apple { + | ^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Fruit` + +error[E0425]: cannot find function, tuple struct or tuple variant `Apple` in this scope + --> $DIR/issue-35675.rs:15:5 + | +LL | Apple(5) + | ^^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL | use Fruit::Apple; + | + +error[E0573]: expected type, found variant `Ok` + --> $DIR/issue-35675.rs:19:13 + | +LL | fn foo() -> Ok { + | ^^ + | | + | not a type + | help: try using the variant's enum: `std::result::Result` + +error[E0412]: cannot find type `Variant3` in this scope + --> $DIR/issue-35675.rs:24:13 + | +LL | fn bar() -> Variant3 { + | ^^^^^^^^ not found in this scope + | +help: there is an enum variant `x::Enum::Variant3`; try using the variant's enum + | +LL | fn bar() -> x::Enum { + | ~~~~~~~ + +error[E0573]: expected type, found variant `Some` + --> $DIR/issue-35675.rs:28:13 + | +LL | fn qux() -> Some { + | ^^^^ + | | + | not a type + | help: try using the variant's enum: `std::option::Option` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0412, E0425, E0573. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/issue-3907-2.rs b/tests/ui/resolve/issue-3907-2.rs new file mode 100644 index 000000000..46f145e63 --- /dev/null +++ b/tests/ui/resolve/issue-3907-2.rs @@ -0,0 +1,14 @@ +// aux-build:issue-3907.rs + +extern crate issue_3907; + +type Foo = dyn issue_3907::Foo + 'static; + +struct S { + name: isize +} + +fn bar(_x: Foo) {} +//~^ ERROR E0038 + +fn main() {} diff --git a/tests/ui/resolve/issue-3907-2.stderr b/tests/ui/resolve/issue-3907-2.stderr new file mode 100644 index 000000000..782cfeec4 --- /dev/null +++ b/tests/ui/resolve/issue-3907-2.stderr @@ -0,0 +1,15 @@ +error[E0038]: the trait `issue_3907::Foo` cannot be made into an object + --> $DIR/issue-3907-2.rs:11:12 + | +LL | fn bar(_x: Foo) {} + | ^^^ `issue_3907::Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/auxiliary/issue-3907.rs:2:8 + | +LL | fn bar(); + | ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/resolve/issue-3907.rs b/tests/ui/resolve/issue-3907.rs new file mode 100644 index 000000000..6211de427 --- /dev/null +++ b/tests/ui/resolve/issue-3907.rs @@ -0,0 +1,20 @@ +// aux-build:issue-3907.rs + +extern crate issue_3907; + +type Foo = dyn issue_3907::Foo; + +struct S { + name: isize +} + +impl Foo for S { //~ ERROR expected trait, found type alias `Foo` + fn bar() { } +} + +fn main() { + let s = S { + name: 0 + }; + s.bar(); +} diff --git a/tests/ui/resolve/issue-3907.stderr b/tests/ui/resolve/issue-3907.stderr new file mode 100644 index 000000000..6fc61cae8 --- /dev/null +++ b/tests/ui/resolve/issue-3907.stderr @@ -0,0 +1,18 @@ +error[E0404]: expected trait, found type alias `Foo` + --> $DIR/issue-3907.rs:11:6 + | +LL | impl Foo for S { + | ^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait Foo = dyn issue_3907::Foo; + | +help: consider importing this trait instead + | +LL | use issue_3907::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/issue-39226.rs b/tests/ui/resolve/issue-39226.rs new file mode 100644 index 000000000..0f784f02b --- /dev/null +++ b/tests/ui/resolve/issue-39226.rs @@ -0,0 +1,14 @@ +struct Handle {} + +struct Something { + handle: Handle +} + +fn main() { + let handle: Handle = Handle {}; + + let s: Something = Something { + handle: Handle + //~^ ERROR expected value, found struct `Handle` + }; +} diff --git a/tests/ui/resolve/issue-39226.stderr b/tests/ui/resolve/issue-39226.stderr new file mode 100644 index 000000000..5045ec6c3 --- /dev/null +++ b/tests/ui/resolve/issue-39226.stderr @@ -0,0 +1,21 @@ +error[E0423]: expected value, found struct `Handle` + --> $DIR/issue-39226.rs:11:17 + | +LL | struct Handle {} + | ---------------- `Handle` defined here +... +LL | handle: Handle + | ^^^^^^ + | +help: use struct literal syntax instead + | +LL | handle: Handle {} + | ~~~~~~~~~ +help: a local variable with a similar name exists + | +LL | handle: handle + | ~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-39559-2.rs b/tests/ui/resolve/issue-39559-2.rs new file mode 100644 index 000000000..07d3a82b1 --- /dev/null +++ b/tests/ui/resolve/issue-39559-2.rs @@ -0,0 +1,18 @@ +trait Dim { + fn dim() -> usize; +} + +enum Dim3 {} + +impl Dim for Dim3 { + fn dim() -> usize { + 3 + } +} + +fn main() { + let array: [usize; Dim3::dim()] + //~^ ERROR E0015 + = [0; Dim3::dim()]; + //~^ ERROR E0015 +} diff --git a/tests/ui/resolve/issue-39559-2.stderr b/tests/ui/resolve/issue-39559-2.stderr new file mode 100644 index 000000000..e9d8eb083 --- /dev/null +++ b/tests/ui/resolve/issue-39559-2.stderr @@ -0,0 +1,21 @@ +error[E0015]: cannot call non-const fn `::dim` in constants + --> $DIR/issue-39559-2.rs:14:24 + | +LL | let array: [usize; Dim3::dim()] + | ^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `::dim` in constants + --> $DIR/issue-39559-2.rs:16:15 + | +LL | = [0; Dim3::dim()]; + | ^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/resolve/issue-39559.rs b/tests/ui/resolve/issue-39559.rs new file mode 100644 index 000000000..58d259407 --- /dev/null +++ b/tests/ui/resolve/issue-39559.rs @@ -0,0 +1,19 @@ +trait Dim { + fn dim() -> usize; +} + +enum Dim3 {} + +impl Dim for Dim3 { + fn dim() -> usize { + 3 + } +} + +pub struct Vector { + entries: [T; D::dim()], + //~^ ERROR generic parameters may not be used + _dummy: D, +} + +fn main() {} diff --git a/tests/ui/resolve/issue-39559.stderr b/tests/ui/resolve/issue-39559.stderr new file mode 100644 index 000000000..7626f827f --- /dev/null +++ b/tests/ui/resolve/issue-39559.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-39559.rs:14:18 + | +LL | entries: [T; D::dim()], + | ^^^^^^ cannot perform const operation using `D` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/resolve/issue-42944.rs b/tests/ui/resolve/issue-42944.rs new file mode 100644 index 000000000..7e439c10b --- /dev/null +++ b/tests/ui/resolve/issue-42944.rs @@ -0,0 +1,21 @@ +mod foo { + pub struct Bx(pub(in crate::foo) ()); +} + +mod bar { + use foo::Bx; + + fn foo() { + Bx(()); + //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423] + } +} + +mod baz { + fn foo() { + Bx(()); + //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425] + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-42944.stderr b/tests/ui/resolve/issue-42944.stderr new file mode 100644 index 000000000..4ffa9402c --- /dev/null +++ b/tests/ui/resolve/issue-42944.stderr @@ -0,0 +1,32 @@ +error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope + --> $DIR/issue-42944.rs:16:9 + | +LL | Bx(()); + | ^^ not found in this scope + | +note: tuple struct `foo::Bx` exists but is inaccessible + --> $DIR/issue-42944.rs:2:5 + | +LL | pub struct Bx(pub(in crate::foo) ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible + +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/issue-42944.rs:9:9 + | +LL | Bx(()); + | ^^ + | +note: constructor is not visible here due to private fields + --> $DIR/issue-42944.rs:2:19 + | +LL | pub struct Bx(pub(in crate::foo) ()); + | ^^^^^^^^^^^^^^^^^^^^^ private field +help: consider making the field publicly accessible + | +LL | pub struct Bx(pub ()); + | ~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0425. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-49074.rs b/tests/ui/resolve/issue-49074.rs new file mode 100644 index 000000000..752bb345b --- /dev/null +++ b/tests/ui/resolve/issue-49074.rs @@ -0,0 +1,13 @@ +// Check that unknown attribute error is shown even if there are unresolved macros. + +#[marco_use] // typo +//~^ ERROR cannot find attribute `marco_use` in this scope +mod foo { + macro_rules! bar { + () => (); + } +} + +fn main() { + bar!(); //~ ERROR cannot find macro `bar` in this scope +} diff --git a/tests/ui/resolve/issue-49074.stderr b/tests/ui/resolve/issue-49074.stderr new file mode 100644 index 000000000..bbfeb4ea9 --- /dev/null +++ b/tests/ui/resolve/issue-49074.stderr @@ -0,0 +1,16 @@ +error: cannot find macro `bar` in this scope + --> $DIR/issue-49074.rs:12:4 + | +LL | bar!(); + | ^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: cannot find attribute `marco_use` in this scope + --> $DIR/issue-49074.rs:3:3 + | +LL | #[marco_use] // typo + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/resolve/issue-5035-2.rs b/tests/ui/resolve/issue-5035-2.rs new file mode 100644 index 000000000..b831bb4be --- /dev/null +++ b/tests/ui/resolve/issue-5035-2.rs @@ -0,0 +1,7 @@ +trait I {} +type K = dyn I + 'static; + +fn foo(_x: K) {} +//~^ ERROR the size for values of type + +fn main() {} diff --git a/tests/ui/resolve/issue-5035-2.stderr b/tests/ui/resolve/issue-5035-2.stderr new file mode 100644 index 000000000..558e6b7b1 --- /dev/null +++ b/tests/ui/resolve/issue-5035-2.stderr @@ -0,0 +1,20 @@ +error[E0277]: the size for values of type `(dyn I + 'static)` cannot be known at compilation time + --> $DIR/issue-5035-2.rs:4:8 + | +LL | fn foo(_x: K) {} + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn I + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn foo(_x: impl K) {} + | ++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(_x: &K) {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/resolve/issue-5035.rs b/tests/ui/resolve/issue-5035.rs new file mode 100644 index 000000000..49fa312f9 --- /dev/null +++ b/tests/ui/resolve/issue-5035.rs @@ -0,0 +1,9 @@ +trait I {} +type K = dyn I; +impl K for isize {} //~ ERROR expected trait, found type alias `K` + +use ImportError; //~ ERROR unresolved import `ImportError` [E0432] + //~^ no `ImportError` in the root +impl ImportError for () {} // check that this is not an additional error (cf. issue #35142) + +fn main() {} diff --git a/tests/ui/resolve/issue-5035.stderr b/tests/ui/resolve/issue-5035.stderr new file mode 100644 index 000000000..32b972b21 --- /dev/null +++ b/tests/ui/resolve/issue-5035.stderr @@ -0,0 +1,28 @@ +error[E0432]: unresolved import `ImportError` + --> $DIR/issue-5035.rs:5:5 + | +LL | use ImportError; + | ^^^^^^^^^^^ no `ImportError` in the root + +error[E0404]: expected trait, found type alias `K` + --> $DIR/issue-5035.rs:3:6 + | +LL | trait I {} + | ------- similarly named trait `I` defined here +LL | type K = dyn I; +LL | impl K for isize {} + | ^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait K = dyn I; + | +help: a trait with a similar name exists + | +LL | impl I for isize {} + | ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0404, E0432. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/issue-50599.rs b/tests/ui/resolve/issue-50599.rs new file mode 100644 index 000000000..72238a591 --- /dev/null +++ b/tests/ui/resolve/issue-50599.rs @@ -0,0 +1,6 @@ +fn main() { + const N: u32 = 1_000; + const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value + let mut digits = [0u32; M]; + //~^ constant +} diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr new file mode 100644 index 000000000..b07482c83 --- /dev/null +++ b/tests/ui/resolve/issue-50599.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `LOG10_2` in module `std::f64` + --> $DIR/issue-50599.rs:3:48 + | +LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; + | ^^^^^^^ not found in `std::f64` + | +help: consider importing one of these items + | +LL | use std::f32::consts::LOG10_2; + | +LL | use std::f64::consts::LOG10_2; + | +help: if you import `LOG10_2`, refer to it directly + | +LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; +LL + const M: usize = (f64::from(N) * LOG10_2) as usize; + | + +note: erroneous constant used + --> $DIR/issue-50599.rs:4:29 + | +LL | let mut digits = [0u32; M]; + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-5099.rs b/tests/ui/resolve/issue-5099.rs new file mode 100644 index 000000000..b5abccb4b --- /dev/null +++ b/tests/ui/resolve/issue-5099.rs @@ -0,0 +1,13 @@ +trait B { + fn a() -> A { + this.a //~ ERROR cannot find value `this` in this scope + } + fn b(x: i32) { + this.b(x); //~ ERROR cannot find value `this` in this scope + } + fn c() { + let _ = || this.a; //~ ERROR cannot find value `this` in this scope + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-5099.stderr b/tests/ui/resolve/issue-5099.stderr new file mode 100644 index 000000000..e9b2a9c4d --- /dev/null +++ b/tests/ui/resolve/issue-5099.stderr @@ -0,0 +1,48 @@ +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-5099.rs:3:9 + | +LL | this.a + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.a + | ~~~~ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn a(&self) -> A { + | +++++ + +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-5099.rs:6:9 + | +LL | this.b(x); + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.b(x); + | ~~~~ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn b(&self, x: i32) { + | ++++++ + +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-5099.rs:9:20 + | +LL | let _ = || this.a; + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | let _ = || self.a; + | ~~~~ +help: if you meant to use `self`, you are also missing a `self` receiver argument + | +LL | fn c(&self) { + | +++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-54379.rs b/tests/ui/resolve/issue-54379.rs new file mode 100644 index 000000000..807c54393 --- /dev/null +++ b/tests/ui/resolve/issue-54379.rs @@ -0,0 +1,14 @@ +struct MyStruct { + pub s1: Option, +} + +fn main() { + let thing = MyStruct { s1: None }; + + match thing { + MyStruct { .., Some(_) } => {}, + //~^ ERROR expected `,` + //~| ERROR expected `}`, found `,` + _ => {} + } +} diff --git a/tests/ui/resolve/issue-54379.stderr b/tests/ui/resolve/issue-54379.stderr new file mode 100644 index 000000000..750727273 --- /dev/null +++ b/tests/ui/resolve/issue-54379.stderr @@ -0,0 +1,19 @@ +error: expected `}`, found `,` + --> $DIR/issue-54379.rs:9:22 + | +LL | MyStruct { .., Some(_) } => {}, + | --^ + | | | + | | expected `}` + | `..` must be at the end and cannot have a trailing comma + +error: expected `,` + --> $DIR/issue-54379.rs:9:28 + | +LL | MyStruct { .., Some(_) } => {}, + | -------- ^ + | | + | while parsing the fields for this pattern + +error: aborting due to 2 previous errors + diff --git a/tests/ui/resolve/issue-55673.rs b/tests/ui/resolve/issue-55673.rs new file mode 100644 index 000000000..0436bd397 --- /dev/null +++ b/tests/ui/resolve/issue-55673.rs @@ -0,0 +1,12 @@ +trait Foo { + type Bar; +} + +fn foo() +where + T::Baa: std::fmt::Debug, + //~^ ERROR associated type `Baa` not found for `T` +{ +} + +fn main() {} diff --git a/tests/ui/resolve/issue-55673.stderr b/tests/ui/resolve/issue-55673.stderr new file mode 100644 index 000000000..39318f959 --- /dev/null +++ b/tests/ui/resolve/issue-55673.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Baa` not found for `T` + --> $DIR/issue-55673.rs:7:8 + | +LL | T::Baa: std::fmt::Debug, + | ^^^ there is a similarly named associated type `Bar` in the trait `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/resolve/issue-57523.rs b/tests/ui/resolve/issue-57523.rs new file mode 100644 index 000000000..976238cc3 --- /dev/null +++ b/tests/ui/resolve/issue-57523.rs @@ -0,0 +1,21 @@ +// check-pass + +struct S(u8); + +impl S { + fn method1() -> Self { + Self(0) + } +} + +macro_rules! define_method { () => { + impl S { + fn method2() -> Self { + Self(0) // OK + } + } +}} + +define_method!(); + +fn main() {} diff --git a/tests/ui/resolve/issue-5927.rs b/tests/ui/resolve/issue-5927.rs new file mode 100644 index 000000000..14f95827b --- /dev/null +++ b/tests/ui/resolve/issue-5927.rs @@ -0,0 +1,7 @@ +fn main() { + let z = match 3 { + x(1) => x(1) //~ ERROR cannot find tuple struct or tuple variant `x` in this scope + //~^ ERROR cannot find function `x` in this scope + }; + assert!(z == 3); +} diff --git a/tests/ui/resolve/issue-5927.stderr b/tests/ui/resolve/issue-5927.stderr new file mode 100644 index 000000000..d6cd6853d --- /dev/null +++ b/tests/ui/resolve/issue-5927.stderr @@ -0,0 +1,16 @@ +error[E0531]: cannot find tuple struct or tuple variant `x` in this scope + --> $DIR/issue-5927.rs:3:9 + | +LL | x(1) => x(1) + | ^ not found in this scope + +error[E0425]: cannot find function `x` in this scope + --> $DIR/issue-5927.rs:3:17 + | +LL | x(1) => x(1) + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0531. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-60057.rs b/tests/ui/resolve/issue-60057.rs new file mode 100644 index 000000000..b52343ada --- /dev/null +++ b/tests/ui/resolve/issue-60057.rs @@ -0,0 +1,19 @@ +struct A { + banana: u8, +} + +impl A { + fn new(peach: u8) -> A { + A { + banana: banana //~ ERROR cannot find value `banana` in this scope + } + } + + fn foo(&self, peach: u8) -> A { + A { + banana: banana //~ ERROR cannot find value `banana` in this scope + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-60057.stderr b/tests/ui/resolve/issue-60057.stderr new file mode 100644 index 000000000..4d915fcd9 --- /dev/null +++ b/tests/ui/resolve/issue-60057.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `banana` in this scope + --> $DIR/issue-60057.rs:8:21 + | +LL | banana: banana + | ^^^^^^ a field by this name exists in `Self` + +error[E0425]: cannot find value `banana` in this scope + --> $DIR/issue-60057.rs:14:21 + | +LL | banana: banana + | ^^^^^^ help: you might have meant to use the available field: `self.banana` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs b/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs new file mode 100644 index 000000000..ce45f630e --- /dev/null +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.rs @@ -0,0 +1,10 @@ +unsafe fn foo() { + extern "C" { + static baz: *const A; + //~^ ERROR can't use generic parameters from outer function + } + + let bar: *const u64 = core::mem::transmute(&baz); +} + +fn main() { } diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr new file mode 100644 index 000000000..6bbf76dd1 --- /dev/null +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -0,0 +1,12 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65025-extern-static-parent-generics.rs:3:28 + | +LL | unsafe fn foo() { + | - type parameter from outer function +LL | extern "C" { +LL | static baz: *const A; + | ^ use of generic parameter from outer function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.rs b/tests/ui/resolve/issue-65035-static-with-parent-generics.rs new file mode 100644 index 000000000..f96c04841 --- /dev/null +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.rs @@ -0,0 +1,26 @@ +fn f() { + extern "C" { + static a: *const T; + //~^ ERROR can't use generic parameters from outer function + } +} + +fn g() { + static a: *const T = Default::default(); + //~^ ERROR can't use generic parameters from outer function +} + +fn h() { + extern "C" { + static a: [u8; N]; + //~^ ERROR can't use generic parameters from outer function + } +} + +fn i() { + static a: [u8; N] = [0; N]; + //~^ ERROR can't use generic parameters from outer function + //~| ERROR can't use generic parameters from outer function +} + +fn main() {} diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr new file mode 100644 index 000000000..7ed572f80 --- /dev/null +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -0,0 +1,45 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:3:26 + | +LL | fn f() { + | - type parameter from outer function +LL | extern "C" { +LL | static a: *const T; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:9:22 + | +LL | fn g() { + | - type parameter from outer function +LL | static a: *const T = Default::default(); + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:15:24 + | +LL | fn h() { + | - const parameter from outer function +LL | extern "C" { +LL | static a: [u8; N]; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:21:20 + | +LL | fn i() { + | - const parameter from outer function +LL | static a: [u8; N] = [0; N]; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:21:29 + | +LL | fn i() { + | - const parameter from outer function +LL | static a: [u8; N] = [0; N]; + | ^ use of generic parameter from outer function + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-6702.rs b/tests/ui/resolve/issue-6702.rs new file mode 100644 index 000000000..954dc36f3 --- /dev/null +++ b/tests/ui/resolve/issue-6702.rs @@ -0,0 +1,9 @@ +struct Monster { + damage: isize +} + + +fn main() { + let _m = Monster(); + //~^ ERROR expected function, tuple struct or tuple variant, found struct `Monster` +} diff --git a/tests/ui/resolve/issue-6702.stderr b/tests/ui/resolve/issue-6702.stderr new file mode 100644 index 000000000..a118f9419 --- /dev/null +++ b/tests/ui/resolve/issue-6702.stderr @@ -0,0 +1,14 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `Monster` + --> $DIR/issue-6702.rs:7:14 + | +LL | / struct Monster { +LL | | damage: isize +LL | | } + | |_- `Monster` defined here +... +LL | let _m = Monster(); + | ^^^^^^^^^ help: use struct literal syntax instead: `Monster { damage: val }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs b/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs new file mode 100644 index 000000000..c377ecea9 --- /dev/null +++ b/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs @@ -0,0 +1,6 @@ +fn main() {} + +trait Foo { + fn fn_with_type_named_same_as_local_in_param(b: b); + //~^ ERROR cannot find type `b` in this scope [E0412] +} diff --git a/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr b/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr new file mode 100644 index 000000000..109409d27 --- /dev/null +++ b/tests/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `b` in this scope + --> $DIR/issue-69401-trait-fn-no-body-ty-local.rs:4:53 + | +LL | fn fn_with_type_named_same_as_local_in_param(b: b); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs b/tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs new file mode 100644 index 000000000..49462f52f --- /dev/null +++ b/tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.rs @@ -0,0 +1,19 @@ +// edition:2018 + +async fn free(); //~ ERROR without a body + +struct A; +impl A { + async fn inherent(); //~ ERROR without body +} + +trait B { + async fn associated(); + //~^ ERROR cannot be declared `async` +} +impl B for A { + async fn associated(); //~ ERROR without body + //~^ ERROR cannot be declared `async` +} + +fn main() {} diff --git a/tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr new file mode 100644 index 000000000..1354abb4f --- /dev/null +++ b/tests/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -0,0 +1,53 @@ +error: free function without a body + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:3:1 + | +LL | async fn free(); + | ^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: associated function in `impl` without body + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:7:5 + | +LL | async fn inherent(); + | ^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: associated function in `impl` without body + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 + | +LL | async fn associated(); + | ^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:11:5 + | +LL | async fn associated(); + | -----^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5 + | +LL | async fn associated(); + | -----^^^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0706`. diff --git a/tests/ui/resolve/issue-73427.rs b/tests/ui/resolve/issue-73427.rs new file mode 100644 index 000000000..5c2459a59 --- /dev/null +++ b/tests/ui/resolve/issue-73427.rs @@ -0,0 +1,50 @@ +enum A { + StructWithFields { x: () }, + TupleWithFields(()), + Struct {}, + Tuple(), + Unit, +} + +enum B { + StructWithFields { x: () }, + TupleWithFields(()), +} + +enum C { + StructWithFields { x: () }, + TupleWithFields(()), + Unit, +} + +enum D { + TupleWithFields(()), + Unit, +} + +enum E { + TupleWithFields(()), +} + +fn main() { + // Only variants without fields are suggested (and others mentioned in a note) where an enum + // is used rather than a variant. + + A.foo(); + //~^ ERROR expected value, found enum `A` + B.foo(); + //~^ ERROR expected value, found enum `B` + C.foo(); + //~^ ERROR expected value, found enum `C` + D.foo(); + //~^ ERROR expected value, found enum `D` + E.foo(); + //~^ ERROR expected value, found enum `E` + + // Only tuple variants are suggested in calls or tuple struct pattern matching. + + let x = A(3); + //~^ ERROR expected function, tuple struct or tuple variant, found enum `A` + if let A(3) = x { } + //~^ ERROR expected tuple struct or tuple variant, found enum `A` +} diff --git a/tests/ui/resolve/issue-73427.stderr b/tests/ui/resolve/issue-73427.stderr new file mode 100644 index 000000000..4af5f29d8 --- /dev/null +++ b/tests/ui/resolve/issue-73427.stderr @@ -0,0 +1,168 @@ +error[E0423]: expected value, found enum `A` + --> $DIR/issue-73427.rs:33:5 + | +LL | A.foo(); + | ^ + | +note: the enum is defined here + --> $DIR/issue-73427.rs:1:1 + | +LL | / enum A { +LL | | StructWithFields { x: () }, +LL | | TupleWithFields(()), +LL | | Struct {}, +LL | | Tuple(), +LL | | Unit, +LL | | } + | |_^ +help: you might have meant to use one of the following enum variants + | +LL | (A::Tuple()).foo(); + | ~~~~~~~~~~~~ +LL | A::Unit.foo(); + | ~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | (A::TupleWithFields(/* fields */)).foo(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0423]: expected value, found enum `B` + --> $DIR/issue-73427.rs:35:5 + | +LL | B.foo(); + | ^ help: the following enum variant is available: `(B::TupleWithFields(/* fields */))` + | +note: the enum is defined here + --> $DIR/issue-73427.rs:9:1 + | +LL | / enum B { +LL | | StructWithFields { x: () }, +LL | | TupleWithFields(()), +LL | | } + | |_^ + +error[E0423]: expected value, found enum `C` + --> $DIR/issue-73427.rs:37:5 + | +LL | C.foo(); + | ^ + | +note: the enum is defined here + --> $DIR/issue-73427.rs:14:1 + | +LL | / enum C { +LL | | StructWithFields { x: () }, +LL | | TupleWithFields(()), +LL | | Unit, +LL | | } + | |_^ +help: you might have meant to use the following enum variant + | +LL | C::Unit.foo(); + | ~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | (C::TupleWithFields(/* fields */)).foo(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0423]: expected value, found enum `D` + --> $DIR/issue-73427.rs:39:5 + | +LL | D.foo(); + | ^ + | +note: the enum is defined here + --> $DIR/issue-73427.rs:20:1 + | +LL | / enum D { +LL | | TupleWithFields(()), +LL | | Unit, +LL | | } + | |_^ +help: you might have meant to use the following enum variant + | +LL | D::Unit.foo(); + | ~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | (D::TupleWithFields(/* fields */)).foo(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0423]: expected value, found enum `E` + --> $DIR/issue-73427.rs:41:5 + | +LL | E.foo(); + | ^ + | +note: the enum is defined here + --> $DIR/issue-73427.rs:25:1 + | +LL | / enum E { +LL | | TupleWithFields(()), +LL | | } + | |_^ +help: the following enum variant is available + | +LL | (E::TupleWithFields(/* fields */)).foo(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: consider importing one of these items instead + | +LL | use std::f32::consts::E; + | +LL | use std::f64::consts::E; + | + +error[E0532]: expected tuple struct or tuple variant, found enum `A` + --> $DIR/issue-73427.rs:48:12 + | +LL | if let A(3) = x { } + | ^ + | + = help: you might have meant to match against the enum's non-tuple variant +note: the enum is defined here + --> $DIR/issue-73427.rs:1:1 + | +LL | / enum A { +LL | | StructWithFields { x: () }, +LL | | TupleWithFields(()), +LL | | Struct {}, +LL | | Tuple(), +LL | | Unit, +LL | | } + | |_^ +help: try to match against one of the enum's variants + | +LL | if let A::Tuple(3) = x { } + | ~~~~~~~~ +LL | if let A::TupleWithFields(3) = x { } + | ~~~~~~~~~~~~~~~~~~ + +error[E0423]: expected function, tuple struct or tuple variant, found enum `A` + --> $DIR/issue-73427.rs:46:13 + | +LL | let x = A(3); + | ^ + | + = help: you might have meant to construct the enum's non-tuple variant +note: the enum is defined here + --> $DIR/issue-73427.rs:1:1 + | +LL | / enum A { +LL | | StructWithFields { x: () }, +LL | | TupleWithFields(()), +LL | | Struct {}, +LL | | Tuple(), +LL | | Unit, +LL | | } + | |_^ +help: try to construct one of the enum's variants + | +LL | let x = A::Tuple(3); + | ~~~~~~~~ +LL | let x = A::TupleWithFields(3); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0423, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-80079.rs b/tests/ui/resolve/issue-80079.rs new file mode 100644 index 000000000..4795ed062 --- /dev/null +++ b/tests/ui/resolve/issue-80079.rs @@ -0,0 +1,12 @@ +// aux-build:issue-80079.rs + +// using a module from another crate should not cause errors to suggest private +// items in that module + +extern crate issue_80079; + +use issue_80079::public; + +fn main() { + let _ = Foo; //~ ERROR cannot find value `Foo` in this scope +} diff --git a/tests/ui/resolve/issue-80079.stderr b/tests/ui/resolve/issue-80079.stderr new file mode 100644 index 000000000..93e8c0341 --- /dev/null +++ b/tests/ui/resolve/issue-80079.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/issue-80079.rs:11:13 + | +LL | let _ = Foo; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/issue-81508.rs b/tests/ui/resolve/issue-81508.rs new file mode 100644 index 000000000..23605cd2f --- /dev/null +++ b/tests/ui/resolve/issue-81508.rs @@ -0,0 +1,22 @@ +// Confusing diagnostic when using variable as a type: +// +// Previous warnings indicate Foo is not used, when in fact it is +// used improperly as a variable or constant. New warning points +// out user may be trying to use variable as a type. Test demonstrates +// cases for both local variable and const. + +fn main() { + let Baz: &str = ""; + + println!("{}", Baz::Bar); //~ ERROR: failed to resolve: use of undeclared type `Baz` +} + +#[allow(non_upper_case_globals)] +pub const Foo: &str = ""; + +mod submod { + use super::Foo; + fn function() { + println!("{}", Foo::Bar); //~ ERROR: failed to resolve: use of undeclared type `Foo` + } +} diff --git a/tests/ui/resolve/issue-81508.stderr b/tests/ui/resolve/issue-81508.stderr new file mode 100644 index 000000000..7258174ba --- /dev/null +++ b/tests/ui/resolve/issue-81508.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared type `Baz` + --> $DIR/issue-81508.rs:11:20 + | +LL | let Baz: &str = ""; + | --- help: `Baz` is defined here, but is not a type +LL | +LL | println!("{}", Baz::Bar); + | ^^^ use of undeclared type `Baz` + +error[E0433]: failed to resolve: use of undeclared type `Foo` + --> $DIR/issue-81508.rs:20:24 + | +LL | use super::Foo; + | ---------- help: `Foo` is defined here, but is not a type +LL | fn function() { +LL | println!("{}", Foo::Bar); + | ^^^ use of undeclared type `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-82156.rs b/tests/ui/resolve/issue-82156.rs new file mode 100644 index 000000000..6215259e4 --- /dev/null +++ b/tests/ui/resolve/issue-82156.rs @@ -0,0 +1,3 @@ +fn main() { + super(); //~ ERROR failed to resolve: there are too many leading `super` keywords +} diff --git a/tests/ui/resolve/issue-82156.stderr b/tests/ui/resolve/issue-82156.stderr new file mode 100644 index 000000000..d53599dcc --- /dev/null +++ b/tests/ui/resolve/issue-82156.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/issue-82156.rs:2:5 + | +LL | super(); + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-82865.rs b/tests/ui/resolve/issue-82865.rs new file mode 100644 index 000000000..07d88c413 --- /dev/null +++ b/tests/ui/resolve/issue-82865.rs @@ -0,0 +1,13 @@ +// Regression test for #82865. + +#![feature(decl_macro)] + +use x::y::z; //~ ERROR: failed to resolve: maybe a missing crate `x`? + +macro mac () { + Box::z //~ ERROR: no function or associated item +} + +fn main() { + mac!(); +} diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr new file mode 100644 index 000000000..730fd6d60 --- /dev/null +++ b/tests/ui/resolve/issue-82865.stderr @@ -0,0 +1,23 @@ +error[E0433]: failed to resolve: maybe a missing crate `x`? + --> $DIR/issue-82865.rs:5:5 + | +LL | use x::y::z; + | ^ maybe a missing crate `x`? + | + = help: consider adding `extern crate x` to use the `x` crate + +error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope + --> $DIR/issue-82865.rs:8:10 + | +LL | Box::z + | ^ function or associated item not found in `Box<_, _>` +... +LL | mac!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/issue-85348.rs b/tests/ui/resolve/issue-85348.rs new file mode 100644 index 000000000..3a33c1934 --- /dev/null +++ b/tests/ui/resolve/issue-85348.rs @@ -0,0 +1,12 @@ +// Checks whether shadowing a const parameter leads to an ICE (#85348). + +impl ArrayWindowsExample { +//~^ ERROR: cannot find type `ArrayWindowsExample` in this scope [E0412] + fn next() { + let mut N; + //~^ ERROR: let bindings cannot shadow const parameters [E0530] + //~| ERROR: type annotations needed [E0282] + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-85348.stderr b/tests/ui/resolve/issue-85348.stderr new file mode 100644 index 000000000..42b43f825 --- /dev/null +++ b/tests/ui/resolve/issue-85348.stderr @@ -0,0 +1,30 @@ +error[E0530]: let bindings cannot shadow const parameters + --> $DIR/issue-85348.rs:6:17 + | +LL | impl ArrayWindowsExample { + | - the const parameter `N` is defined here +... +LL | let mut N; + | ^ cannot be named the same as a const parameter + +error[E0412]: cannot find type `ArrayWindowsExample` in this scope + --> $DIR/issue-85348.rs:3:22 + | +LL | impl ArrayWindowsExample { + | ^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0282]: type annotations needed + --> $DIR/issue-85348.rs:6:13 + | +LL | let mut N; + | ^^^^^ + | +help: consider giving `N` an explicit type + | +LL | let mut N: /* Type */; + | ++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0282, E0412, E0530. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/resolve/issue-85671.rs b/tests/ui/resolve/issue-85671.rs new file mode 100644 index 000000000..337ec307e --- /dev/null +++ b/tests/ui/resolve/issue-85671.rs @@ -0,0 +1,37 @@ +// check-pass + +// Some trait with a function that returns a slice: +pub trait AsSlice { + type Element; + fn as_slice(&self) -> &[Self::Element]; +} + +// Some type +pub struct A(Cont); + +// Here we say that if A wraps a slice, then it implements AsSlice +impl<'a, Element> AsSlice for A<&'a [Element]> { + type Element = Element; + fn as_slice(&self) -> &[Self::Element] { + self.0 + } +} + +impl A { + // We want this function to work + pub fn failing(&self) + where + Self: AsSlice, + { + self.as_ref_a().as_ref_a(); + } + + pub fn as_ref_a(&self) -> A<&[::Element]> + where + Self: AsSlice, + { + A(self.as_slice()) + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-88472.rs b/tests/ui/resolve/issue-88472.rs new file mode 100644 index 000000000..6bf7caedd --- /dev/null +++ b/tests/ui/resolve/issue-88472.rs @@ -0,0 +1,38 @@ +// Regression test for #88472, where a suggestion was issued to +// import an inaccessible struct. + +#![warn(unused_imports)] +//~^ NOTE: the lint level is defined here + +mod a { + struct Foo; + //~^ NOTE: struct `a::Foo` exists but is inaccessible + //~| NOTE: not accessible +} + +mod b { + use crate::a::*; + //~^ WARNING: unused import + type Bar = Foo; + //~^ ERROR: cannot find type `Foo` in this scope [E0412] + //~| NOTE: not found in this scope +} + +mod c { + enum Eee {} + //~^ NOTE: these enums exist but are inaccessible + //~| NOTE: `c::Eee`: not accessible + + mod d { + enum Eee {} + //~^ NOTE: `c::d::Eee`: not accessible + } +} + +mod e { + type Baz = Eee; + //~^ ERROR: cannot find type `Eee` in this scope [E0412] + //~| NOTE: not found in this scope +} + +fn main() {} diff --git a/tests/ui/resolve/issue-88472.stderr b/tests/ui/resolve/issue-88472.stderr new file mode 100644 index 000000000..8431fc977 --- /dev/null +++ b/tests/ui/resolve/issue-88472.stderr @@ -0,0 +1,42 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/issue-88472.rs:16:16 + | +LL | type Bar = Foo; + | ^^^ not found in this scope + | +note: struct `a::Foo` exists but is inaccessible + --> $DIR/issue-88472.rs:8:5 + | +LL | struct Foo; + | ^^^^^^^^^^^ not accessible + +error[E0412]: cannot find type `Eee` in this scope + --> $DIR/issue-88472.rs:33:16 + | +LL | type Baz = Eee; + | ^^^ not found in this scope + | +note: these enums exist but are inaccessible + --> $DIR/issue-88472.rs:22:5 + | +LL | enum Eee {} + | ^^^^^^^^ `c::Eee`: not accessible +... +LL | enum Eee {} + | ^^^^^^^^ `c::d::Eee`: not accessible + +warning: unused import: `crate::a::*` + --> $DIR/issue-88472.rs:14:9 + | +LL | use crate::a::*; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-88472.rs:4:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/issue-90113.rs b/tests/ui/resolve/issue-90113.rs new file mode 100644 index 000000000..f6658b45e --- /dev/null +++ b/tests/ui/resolve/issue-90113.rs @@ -0,0 +1,21 @@ +mod list { + pub use self::List::Cons; + + pub enum List { + Cons(T, Box>), + } +} + +mod alias { + use crate::list::List; + + pub type Foo = List; +} + +fn foo(l: crate::alias::Foo) { + match l { + Cons(..) => {} //~ ERROR: cannot find tuple struct or tuple variant `Cons` in this scope + } +} + +fn main() {} diff --git a/tests/ui/resolve/issue-90113.stderr b/tests/ui/resolve/issue-90113.stderr new file mode 100644 index 000000000..1b7872057 --- /dev/null +++ b/tests/ui/resolve/issue-90113.stderr @@ -0,0 +1,14 @@ +error[E0531]: cannot find tuple struct or tuple variant `Cons` in this scope + --> $DIR/issue-90113.rs:17:9 + | +LL | Cons(..) => {} + | ^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL | use list::List::Cons; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0531`. diff --git a/tests/ui/resolve/levenshtein.rs b/tests/ui/resolve/levenshtein.rs new file mode 100644 index 000000000..a6f471625 --- /dev/null +++ b/tests/ui/resolve/levenshtein.rs @@ -0,0 +1,31 @@ +const MAX_ITEM: usize = 10; + +fn foo_bar() {} + +fn foo(c: esize) {} // Misspelled primitive type name. +//~^ ERROR cannot find + +enum Bar { } + +type A = Baz; // Misspelled type name. +//~^ ERROR cannot find +type B = Opiton; // Misspelled type name from the prelude. +//~^ ERROR cannot find + +mod m { + type A = Baz; // No suggestion here, Bar is not visible + //~^ ERROR cannot find + + pub struct First; + pub struct Second; +} + +fn main() { + let v = [0u32; MAXITEM]; // Misspelled constant name. + //~^ ERROR cannot find + foobar(); // Misspelled function name. + //~^ ERROR cannot find + let b: m::first = m::second; // Misspelled item in module. + //~^ ERROR cannot find + //~| ERROR cannot find +} diff --git a/tests/ui/resolve/levenshtein.stderr b/tests/ui/resolve/levenshtein.stderr new file mode 100644 index 000000000..cf4782101 --- /dev/null +++ b/tests/ui/resolve/levenshtein.stderr @@ -0,0 +1,70 @@ +error[E0412]: cannot find type `esize` in this scope + --> $DIR/levenshtein.rs:5:11 + | +LL | fn foo(c: esize) {} // Misspelled primitive type name. + | ^^^^^ help: a builtin type with a similar name exists: `isize` + +error[E0412]: cannot find type `Baz` in this scope + --> $DIR/levenshtein.rs:10:10 + | +LL | enum Bar { } + | -------- similarly named enum `Bar` defined here +LL | +LL | type A = Baz; // Misspelled type name. + | ^^^ help: an enum with a similar name exists: `Bar` + +error[E0412]: cannot find type `Opiton` in this scope + --> $DIR/levenshtein.rs:12:10 + | +LL | type B = Opiton; // Misspelled type name from the prelude. + | ^^^^^^ help: an enum with a similar name exists: `Option` + --> $SRC_DIR/core/src/option.rs:LL:COL + | + = note: similarly named enum `Option` defined here + +error[E0412]: cannot find type `Baz` in this scope + --> $DIR/levenshtein.rs:16:14 + | +LL | type A = Baz; // No suggestion here, Bar is not visible + | ^^^ not found in this scope + +error[E0425]: cannot find value `MAXITEM` in this scope + --> $DIR/levenshtein.rs:24:20 + | +LL | const MAX_ITEM: usize = 10; + | --------------------------- similarly named constant `MAX_ITEM` defined here +... +LL | let v = [0u32; MAXITEM]; // Misspelled constant name. + | ^^^^^^^ help: a constant with a similar name exists: `MAX_ITEM` + +error[E0412]: cannot find type `first` in module `m` + --> $DIR/levenshtein.rs:28:15 + | +LL | pub struct First; + | ----------------- similarly named struct `First` defined here +... +LL | let b: m::first = m::second; // Misspelled item in module. + | ^^^^^ help: a struct with a similar name exists (notice the capitalization): `First` + +error[E0425]: cannot find value `second` in module `m` + --> $DIR/levenshtein.rs:28:26 + | +LL | pub struct Second; + | ------------------ similarly named unit struct `Second` defined here +... +LL | let b: m::first = m::second; // Misspelled item in module. + | ^^^^^^ help: a unit struct with a similar name exists (notice the capitalization): `Second` + +error[E0425]: cannot find function `foobar` in this scope + --> $DIR/levenshtein.rs:26:5 + | +LL | fn foo_bar() {} + | ------------ similarly named function `foo_bar` defined here +... +LL | foobar(); // Misspelled function name. + | ^^^^^^ help: a function with a similar name exists: `foo_bar` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/macro-determinacy-non-module.rs b/tests/ui/resolve/macro-determinacy-non-module.rs new file mode 100644 index 000000000..3215e0cd3 --- /dev/null +++ b/tests/ui/resolve/macro-determinacy-non-module.rs @@ -0,0 +1,7 @@ +// check-pass + +use std as line; + +const C: u32 = line!(); + +fn main() {} diff --git a/tests/ui/resolve/missing-in-namespace.rs b/tests/ui/resolve/missing-in-namespace.rs new file mode 100644 index 000000000..e1dedb072 --- /dev/null +++ b/tests/ui/resolve/missing-in-namespace.rs @@ -0,0 +1,4 @@ +fn main() { + let _map = std::hahmap::HashMap::new(); + //~^ ERROR failed to resolve: could not find `hahmap` in `std +} diff --git a/tests/ui/resolve/missing-in-namespace.stderr b/tests/ui/resolve/missing-in-namespace.stderr new file mode 100644 index 000000000..fc925ba3b --- /dev/null +++ b/tests/ui/resolve/missing-in-namespace.stderr @@ -0,0 +1,19 @@ +error[E0433]: failed to resolve: could not find `hahmap` in `std` + --> $DIR/missing-in-namespace.rs:2:21 + | +LL | let _map = std::hahmap::HashMap::new(); + | ^^^^^^ could not find `hahmap` in `std` + | +help: consider importing this struct + | +LL | use std::collections::HashMap; + | +help: if you import `HashMap`, refer to it directly + | +LL - let _map = std::hahmap::HashMap::new(); +LL + let _map = HashMap::new(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/name-clash-nullary.rs b/tests/ui/resolve/name-clash-nullary.rs new file mode 100644 index 000000000..b5f5e1214 --- /dev/null +++ b/tests/ui/resolve/name-clash-nullary.rs @@ -0,0 +1,3 @@ +fn main() { + let None: isize = 42; //~ ERROR mismatched types +} diff --git a/tests/ui/resolve/name-clash-nullary.stderr b/tests/ui/resolve/name-clash-nullary.stderr new file mode 100644 index 000000000..76c4b5914 --- /dev/null +++ b/tests/ui/resolve/name-clash-nullary.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/name-clash-nullary.rs:2:7 + | +LL | let None: isize = 42; + | ^^^^ ----- expected due to this + | | + | expected `isize`, found enum `Option` + | + = note: expected type `isize` + found enum `Option<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/name-collision-in-trait-fn-sig.rs b/tests/ui/resolve/name-collision-in-trait-fn-sig.rs new file mode 100644 index 000000000..fba4ffa1c --- /dev/null +++ b/tests/ui/resolve/name-collision-in-trait-fn-sig.rs @@ -0,0 +1,11 @@ +// check-pass +// This is currently stable behavior, which was almost accidentally made an +// error in #102161 since there is no test exercising it. I am not sure if +// this _should_ be the desired behavior, but at least we should know if it +// changes. + +fn main() {} + +trait Foo { + fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32); +} diff --git a/tests/ui/resolve/no-implicit-prelude-nested.rs b/tests/ui/resolve/no-implicit-prelude-nested.rs new file mode 100644 index 000000000..c314967da --- /dev/null +++ b/tests/ui/resolve/no-implicit-prelude-nested.rs @@ -0,0 +1,54 @@ +// Test that things from the prelude aren't in scope. Use many of them +// so that renaming some things won't magically make this test fail +// for the wrong reason (e.g., if `Add` changes to `Addition`, and +// `no_implicit_prelude` stops working, then the `impl Add` will still +// fail with the same error message). + +#[no_implicit_prelude] +mod foo { + mod baz { + struct Test; + impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope + impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone` + impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope + impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope + impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope + + fn foo() { + drop(2) //~ ERROR cannot find function `drop` in this scope + } + } + + struct Test; + impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope + impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone` + impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope + impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope + impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope + + fn foo() { + drop(2) //~ ERROR cannot find function `drop` in this scope + } +} + +fn qux() { + #[no_implicit_prelude] + mod qux_inner { + struct Test; + impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope + impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone` + impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope + impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope + impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope + + fn foo() { + drop(2) //~ ERROR cannot find function `drop` in this scope + } + } +} + + +fn main() { + // these should work fine + drop(2) +} diff --git a/tests/ui/resolve/no-implicit-prelude-nested.stderr b/tests/ui/resolve/no-implicit-prelude-nested.stderr new file mode 100644 index 000000000..198b630c5 --- /dev/null +++ b/tests/ui/resolve/no-implicit-prelude-nested.stderr @@ -0,0 +1,187 @@ +error[E0405]: cannot find trait `Add` in this scope + --> $DIR/no-implicit-prelude-nested.rs:11:14 + | +LL | impl Add for Test {} + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::ops::Add; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-implicit-prelude-nested.rs:12:14 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-implicit-prelude-nested.rs:13:14 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-implicit-prelude-nested.rs:14:14 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0405]: cannot find trait `Writer` in this scope + --> $DIR/no-implicit-prelude-nested.rs:15:14 + | +LL | impl Writer for Test {} + | ^^^^^^ not found in this scope + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-implicit-prelude-nested.rs:18:13 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error[E0405]: cannot find trait `Add` in this scope + --> $DIR/no-implicit-prelude-nested.rs:23:10 + | +LL | impl Add for Test {} + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::ops::Add; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-implicit-prelude-nested.rs:24:10 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-implicit-prelude-nested.rs:25:10 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-implicit-prelude-nested.rs:26:10 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0405]: cannot find trait `Writer` in this scope + --> $DIR/no-implicit-prelude-nested.rs:27:10 + | +LL | impl Writer for Test {} + | ^^^^^^ not found in this scope + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-implicit-prelude-nested.rs:30:9 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error[E0405]: cannot find trait `Add` in this scope + --> $DIR/no-implicit-prelude-nested.rs:38:14 + | +LL | impl Add for Test {} + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::ops::Add; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-implicit-prelude-nested.rs:39:14 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-implicit-prelude-nested.rs:40:14 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-implicit-prelude-nested.rs:41:14 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0405]: cannot find trait `Writer` in this scope + --> $DIR/no-implicit-prelude-nested.rs:42:14 + | +LL | impl Writer for Test {} + | ^^^^^^ not found in this scope + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-implicit-prelude-nested.rs:45:13 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0404, E0405, E0425. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/no-implicit-prelude.rs b/tests/ui/resolve/no-implicit-prelude.rs new file mode 100644 index 000000000..4b0ca4d52 --- /dev/null +++ b/tests/ui/resolve/no-implicit-prelude.rs @@ -0,0 +1,18 @@ +#![no_implicit_prelude] + +// Test that things from the prelude aren't in scope. Use many of them +// so that renaming some things won't magically make this test fail +// for the wrong reason (e.g., if `Add` changes to `Addition`, and +// `no_implicit_prelude` stops working, then the `impl Add` will still +// fail with the same error message). + +struct Test; +impl Add for Test {} //~ ERROR cannot find trait `Add` in this scope +impl Clone for Test {} //~ ERROR expected trait, found derive macro `Clone` +impl Iterator for Test {} //~ ERROR cannot find trait `Iterator` in this scope +impl ToString for Test {} //~ ERROR cannot find trait `ToString` in this scope +impl Writer for Test {} //~ ERROR cannot find trait `Writer` in this scope + +fn main() { + drop(2) //~ ERROR cannot find function `drop` in this scope +} diff --git a/tests/ui/resolve/no-implicit-prelude.stderr b/tests/ui/resolve/no-implicit-prelude.stderr new file mode 100644 index 000000000..36a9b65b7 --- /dev/null +++ b/tests/ui/resolve/no-implicit-prelude.stderr @@ -0,0 +1,65 @@ +error[E0405]: cannot find trait `Add` in this scope + --> $DIR/no-implicit-prelude.rs:10:6 + | +LL | impl Add for Test {} + | ^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::ops::Add; + | + +error[E0404]: expected trait, found derive macro `Clone` + --> $DIR/no-implicit-prelude.rs:11:6 + | +LL | impl Clone for Test {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::clone::Clone; + | + +error[E0405]: cannot find trait `Iterator` in this scope + --> $DIR/no-implicit-prelude.rs:12:6 + | +LL | impl Iterator for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::iter::Iterator; + | + +error[E0405]: cannot find trait `ToString` in this scope + --> $DIR/no-implicit-prelude.rs:13:6 + | +LL | impl ToString for Test {} + | ^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use std::string::ToString; + | + +error[E0405]: cannot find trait `Writer` in this scope + --> $DIR/no-implicit-prelude.rs:14:6 + | +LL | impl Writer for Test {} + | ^^^^^^ not found in this scope + +error[E0425]: cannot find function `drop` in this scope + --> $DIR/no-implicit-prelude.rs:17:5 + | +LL | drop(2) + | ^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::drop; + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0404, E0405, E0425. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/no-std-1.rs b/tests/ui/resolve/no-std-1.rs new file mode 100644 index 000000000..5b59e9b4e --- /dev/null +++ b/tests/ui/resolve/no-std-1.rs @@ -0,0 +1,10 @@ +// run-pass + +#![no_std] + +extern crate std; + +fn main() { + let a = Some("foo"); + a.unwrap(); +} diff --git a/tests/ui/resolve/no-std-2.rs b/tests/ui/resolve/no-std-2.rs new file mode 100644 index 000000000..487d41649 --- /dev/null +++ b/tests/ui/resolve/no-std-2.rs @@ -0,0 +1,10 @@ +// run-pass + +#![no_std] + +extern crate std; + +fn main() { + let a = core::option::Option::Some("foo"); + a.unwrap(); +} diff --git a/tests/ui/resolve/no-std-3.rs b/tests/ui/resolve/no-std-3.rs new file mode 100644 index 000000000..f6c4ed579 --- /dev/null +++ b/tests/ui/resolve/no-std-3.rs @@ -0,0 +1,17 @@ +// run-pass + +#![no_std] + +extern crate std; + +mod foo { + pub fn test() -> Option { + Some(2) + } +} + +fn main() { + let a = core::option::Option::Some("foo"); + a.unwrap(); + foo::test().unwrap(); +} diff --git a/tests/ui/resolve/pathless-extern-ok.rs b/tests/ui/resolve/pathless-extern-ok.rs new file mode 100644 index 000000000..0ffa5eb89 --- /dev/null +++ b/tests/ui/resolve/pathless-extern-ok.rs @@ -0,0 +1,9 @@ +// edition:2018 +// compile-flags:--extern alloc +// build-pass + +// Test that `--extern alloc` will load from the sysroot without error. + +fn main() { + let _: Vec = alloc::vec::Vec::new(); +} diff --git a/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.rs b/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.rs new file mode 100644 index 000000000..bd496875e --- /dev/null +++ b/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.rs @@ -0,0 +1,21 @@ +trait Foo { + fn foo(&self, name: T) -> usize; +} + +struct Bar { + baz: Baz, +} + +struct Baz { + num: usize, +} + +impl Foo for Bar { + fn foo(&self, _name: Baz) -> usize { + match self.baz { + Baz { num } => num, //~ ERROR expected struct, variant or union type, found type parameter `Baz` + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr b/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr new file mode 100644 index 000000000..5790e425c --- /dev/null +++ b/tests/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr @@ -0,0 +1,15 @@ +error[E0574]: expected struct, variant or union type, found type parameter `Baz` + --> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13 + | +LL | struct Baz { + | --- you might have meant to refer to this struct +... +LL | impl Foo for Bar { + | --- found this type parameter +... +LL | Baz { num } => num, + | ^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/resolve/privacy-enum-ctor.rs b/tests/ui/resolve/privacy-enum-ctor.rs new file mode 100644 index 000000000..f0d2cf8c0 --- /dev/null +++ b/tests/ui/resolve/privacy-enum-ctor.rs @@ -0,0 +1,71 @@ +mod m { + pub enum E { + Fn(u8), + Struct { + s: u8, + }, + Unit, + } + + pub mod n { + pub(in m) enum Z { + Fn(u8), + Struct { + s: u8, + }, + Unit, + } + } + + use m::n::Z; // OK, only the type is imported + + fn f() { + n::Z; + //~^ ERROR expected value, found enum `n::Z` + Z; + //~^ ERROR expected value, found enum `Z` + let _: Z = Z::Fn; + //~^ ERROR mismatched types + let _: Z = Z::Struct; + //~^ ERROR expected value, found struct variant `Z::Struct` + let _ = Z::Unit(); + //~^ ERROR expected function, found enum variant `Z::Unit` + let _ = Z::Unit {}; + // This is ok, it is equivalent to not having braces + } +} + +use m::E; // OK, only the type is imported + +fn main() { + let _: E = m::E; + //~^ ERROR expected value, found enum `m::E` + let _: E = m::E::Fn; + //~^ ERROR mismatched types + let _: E = m::E::Struct; + //~^ ERROR expected value, found struct variant `m::E::Struct` + let _: E = m::E::Unit(); + //~^ ERROR expected function, found enum variant `m::E::Unit` + let _: E = E; + //~^ ERROR expected value, found enum `E` + let _: E = E::Fn; + //~^ ERROR mismatched types + let _: E = E::Struct; + //~^ ERROR expected value, found struct variant `E::Struct` + let _: E = E::Unit(); + //~^ ERROR expected function, found enum variant `E::Unit` + let _: Z = m::n::Z; + //~^ ERROR cannot find type `Z` in this scope + //~| ERROR expected value, found enum `m::n::Z` + //~| ERROR enum `Z` is private + let _: Z = m::n::Z::Fn; + //~^ ERROR cannot find type `Z` in this scope + //~| ERROR enum `Z` is private + let _: Z = m::n::Z::Struct; + //~^ ERROR cannot find type `Z` in this scope + //~| ERROR expected value, found struct variant `m::n::Z::Struct` + //~| ERROR enum `Z` is private + let _: Z = m::n::Z::Unit {}; + //~^ ERROR cannot find type `Z` in this scope + //~| ERROR enum `Z` is private +} diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr new file mode 100644 index 000000000..a24fe4d23 --- /dev/null +++ b/tests/ui/resolve/privacy-enum-ctor.stderr @@ -0,0 +1,395 @@ +error[E0423]: expected value, found enum `n::Z` + --> $DIR/privacy-enum-ctor.rs:23:9 + | +LL | n::Z; + | ^^^^ + | +note: the enum is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | / pub(in m) enum Z { +LL | | Fn(u8), +LL | | Struct { +LL | | s: u8, +LL | | }, +LL | | Unit, +LL | | } + | |_________^ +help: you might have meant to use the following enum variant + | +LL | m::Z::Unit; + | ~~~~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | (m::Z::Fn(/* fields */)); + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0423]: expected value, found enum `Z` + --> $DIR/privacy-enum-ctor.rs:25:9 + | +LL | Z; + | ^ + | +note: the enum is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | / pub(in m) enum Z { +LL | | Fn(u8), +LL | | Struct { +LL | | s: u8, +LL | | }, +LL | | Unit, +LL | | } + | |_________^ +help: you might have meant to use the following enum variant + | +LL | m::Z::Unit; + | ~~~~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | (m::Z::Fn(/* fields */)); + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0423]: expected value, found enum `m::E` + --> $DIR/privacy-enum-ctor.rs:41:16 + | +LL | fn f() { + | ------ similarly named function `f` defined here +... +LL | let _: E = m::E; + | ^^^^ + | +note: the enum is defined here + --> $DIR/privacy-enum-ctor.rs:2:5 + | +LL | / pub enum E { +LL | | Fn(u8), +LL | | Struct { +LL | | s: u8, +LL | | }, +LL | | Unit, +LL | | } + | |_____^ +help: you might have meant to use the following enum variant + | +LL | let _: E = E::Unit; + | ~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | let _: E = (E::Fn(/* fields */)); + | ~~~~~~~~~~~~~~~~~~~~~ +help: a function with a similar name exists + | +LL | let _: E = m::f; + | ~ +help: consider importing one of these items instead + | +LL | use std::f32::consts::E; + | +LL | use std::f64::consts::E; + | +help: if you import `E`, refer to it directly + | +LL - let _: E = m::E; +LL + let _: E = E; + | + +error[E0423]: expected value, found enum `E` + --> $DIR/privacy-enum-ctor.rs:49:16 + | +LL | let _: E = E; + | ^ + | +note: the enum is defined here + --> $DIR/privacy-enum-ctor.rs:2:5 + | +LL | / pub enum E { +LL | | Fn(u8), +LL | | Struct { +LL | | s: u8, +LL | | }, +LL | | Unit, +LL | | } + | |_____^ +help: you might have meant to use the following enum variant + | +LL | let _: E = E::Unit; + | ~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | let _: E = (E::Fn(/* fields */)); + | ~~~~~~~~~~~~~~~~~~~~~ +help: consider importing one of these items instead + | +LL | use std::f32::consts::E; + | +LL | use std::f64::consts::E; + | + +error[E0412]: cannot find type `Z` in this scope + --> $DIR/privacy-enum-ctor.rs:57:12 + | +LL | pub enum E { + | ---------- similarly named enum `E` defined here +... +LL | let _: Z = m::n::Z; + | ^ help: an enum with a similar name exists: `E` + | +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible + +error[E0423]: expected value, found enum `m::n::Z` + --> $DIR/privacy-enum-ctor.rs:57:16 + | +LL | let _: Z = m::n::Z; + | ^^^^^^^ + | +note: the enum is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | / pub(in m) enum Z { +LL | | Fn(u8), +LL | | Struct { +LL | | s: u8, +LL | | }, +LL | | Unit, +LL | | } + | |_________^ +help: you might have meant to use the following enum variant + | +LL | let _: Z = m::Z::Unit; + | ~~~~~~~~~~ +help: alternatively, the following enum variant is available + | +LL | let _: Z = (m::Z::Fn(/* fields */)); + | ~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0412]: cannot find type `Z` in this scope + --> $DIR/privacy-enum-ctor.rs:61:12 + | +LL | pub enum E { + | ---------- similarly named enum `E` defined here +... +LL | let _: Z = m::n::Z::Fn; + | ^ help: an enum with a similar name exists: `E` + | +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible + +error[E0412]: cannot find type `Z` in this scope + --> $DIR/privacy-enum-ctor.rs:64:12 + | +LL | pub enum E { + | ---------- similarly named enum `E` defined here +... +LL | let _: Z = m::n::Z::Struct; + | ^ help: an enum with a similar name exists: `E` + | +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible + +error[E0412]: cannot find type `Z` in this scope + --> $DIR/privacy-enum-ctor.rs:68:12 + | +LL | pub enum E { + | ---------- similarly named enum `E` defined here +... +LL | let _: Z = m::n::Z::Unit {}; + | ^ help: an enum with a similar name exists: `E` + | +note: enum `m::Z` exists but is inaccessible + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ not accessible + +error[E0603]: enum `Z` is private + --> $DIR/privacy-enum-ctor.rs:57:22 + | +LL | let _: Z = m::n::Z; + | ^ private enum + | +note: the enum `Z` is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ + +error[E0603]: enum `Z` is private + --> $DIR/privacy-enum-ctor.rs:61:22 + | +LL | let _: Z = m::n::Z::Fn; + | ^ private enum + | +note: the enum `Z` is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ + +error[E0603]: enum `Z` is private + --> $DIR/privacy-enum-ctor.rs:64:22 + | +LL | let _: Z = m::n::Z::Struct; + | ^ private enum + | +note: the enum `Z` is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ + +error[E0603]: enum `Z` is private + --> $DIR/privacy-enum-ctor.rs:68:22 + | +LL | let _: Z = m::n::Z::Unit {}; + | ^ private enum + | +note: the enum `Z` is defined here + --> $DIR/privacy-enum-ctor.rs:11:9 + | +LL | pub(in m) enum Z { + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/privacy-enum-ctor.rs:27:20 + | +LL | Fn(u8), + | -- `Fn` defines an enum variant constructor here, which should be called +... +LL | let _: Z = Z::Fn; + | - ^^^^^ expected enum `Z`, found enum constructor + | | + | expected due to this + | + = note: expected enum `Z` + found enum constructor `fn(u8) -> Z {Z::Fn}` +help: use parentheses to construct this tuple variant + | +LL | let _: Z = Z::Fn(/* u8 */); + | ++++++++++ + +error[E0533]: expected value, found struct variant `Z::Struct` + --> $DIR/privacy-enum-ctor.rs:29:20 + | +LL | let _: Z = Z::Struct; + | ^^^^^^^^^ not a value + +error[E0618]: expected function, found enum variant `Z::Unit` + --> $DIR/privacy-enum-ctor.rs:31:17 + | +LL | Unit, + | ---- enum variant `Z::Unit` defined here +... +LL | let _ = Z::Unit(); + | ^^^^^^^-- + | | + | call expression requires function + | +help: `Z::Unit` is a unit enum variant, and does not take parentheses to be constructed + | +LL - let _ = Z::Unit(); +LL + let _ = Z::Unit; + | + +error[E0308]: mismatched types + --> $DIR/privacy-enum-ctor.rs:43:16 + | +LL | Fn(u8), + | -- `Fn` defines an enum variant constructor here, which should be called +... +LL | let _: E = m::E::Fn; + | - ^^^^^^^^ expected enum `E`, found enum constructor + | | + | expected due to this + | + = note: expected enum `E` + found enum constructor `fn(u8) -> E {E::Fn}` +help: use parentheses to construct this tuple variant + | +LL | let _: E = m::E::Fn(/* u8 */); + | ++++++++++ + +error[E0533]: expected value, found struct variant `m::E::Struct` + --> $DIR/privacy-enum-ctor.rs:45:16 + | +LL | let _: E = m::E::Struct; + | ^^^^^^^^^^^^ not a value + +error[E0618]: expected function, found enum variant `m::E::Unit` + --> $DIR/privacy-enum-ctor.rs:47:16 + | +LL | Unit, + | ---- enum variant `m::E::Unit` defined here +... +LL | let _: E = m::E::Unit(); + | ^^^^^^^^^^-- + | | + | call expression requires function + | +help: `m::E::Unit` is a unit enum variant, and does not take parentheses to be constructed + | +LL - let _: E = m::E::Unit(); +LL + let _: E = m::E::Unit; + | + +error[E0308]: mismatched types + --> $DIR/privacy-enum-ctor.rs:51:16 + | +LL | Fn(u8), + | -- `Fn` defines an enum variant constructor here, which should be called +... +LL | let _: E = E::Fn; + | - ^^^^^ expected enum `E`, found enum constructor + | | + | expected due to this + | + = note: expected enum `E` + found enum constructor `fn(u8) -> E {E::Fn}` +help: use parentheses to construct this tuple variant + | +LL | let _: E = E::Fn(/* u8 */); + | ++++++++++ + +error[E0533]: expected value, found struct variant `E::Struct` + --> $DIR/privacy-enum-ctor.rs:53:16 + | +LL | let _: E = E::Struct; + | ^^^^^^^^^ not a value + +error[E0618]: expected function, found enum variant `E::Unit` + --> $DIR/privacy-enum-ctor.rs:55:16 + | +LL | Unit, + | ---- enum variant `E::Unit` defined here +... +LL | let _: E = E::Unit(); + | ^^^^^^^-- + | | + | call expression requires function + | +help: `E::Unit` is a unit enum variant, and does not take parentheses to be constructed + | +LL - let _: E = E::Unit(); +LL + let _: E = E::Unit; + | + +error[E0533]: expected value, found struct variant `m::n::Z::Struct` + --> $DIR/privacy-enum-ctor.rs:64:16 + | +LL | let _: Z = m::n::Z::Struct; + | ^^^^^^^^^^^^^^^ not a value + +error: aborting due to 23 previous errors + +Some errors have detailed explanations: E0308, E0412, E0423, E0533, E0603, E0618. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/privacy-struct-ctor.rs b/tests/ui/resolve/privacy-struct-ctor.rs new file mode 100644 index 000000000..0eecc7f8c --- /dev/null +++ b/tests/ui/resolve/privacy-struct-ctor.rs @@ -0,0 +1,47 @@ +// aux-build:privacy-struct-ctor.rs + +extern crate privacy_struct_ctor as xcrate; + +mod m { + pub struct S(u8); + pub struct S2 { + s: u8 + } + + pub mod n { + pub(in m) struct Z(pub(in m::n) u8); + } + + use m::n::Z; // OK, only the type is imported + + fn f() { + n::Z; + //~^ ERROR tuple struct constructor `Z` is private + Z; + //~^ ERROR expected value, found struct `Z` + } +} + +use m::S; // OK, only the type is imported +use m::S2; // OK, only the type is imported + +fn main() { + m::S; + //~^ ERROR tuple struct constructor `S` is private + let _: S = m::S(2); + //~^ ERROR tuple struct constructor `S` is private + S; + //~^ ERROR expected value, found struct `S` + m::n::Z; + //~^ ERROR tuple struct constructor `Z` is private + + S2; + //~^ ERROR expected value, found struct `S2` + + xcrate::m::S; + //~^ ERROR tuple struct constructor `S` is private + xcrate::S; + //~^ ERROR expected value, found struct `xcrate::S` + xcrate::m::n::Z; + //~^ ERROR tuple struct constructor `Z` is private +} diff --git a/tests/ui/resolve/privacy-struct-ctor.stderr b/tests/ui/resolve/privacy-struct-ctor.stderr new file mode 100644 index 000000000..c1fcaaf05 --- /dev/null +++ b/tests/ui/resolve/privacy-struct-ctor.stderr @@ -0,0 +1,155 @@ +error[E0423]: expected value, found struct `Z` + --> $DIR/privacy-struct-ctor.rs:20:9 + | +LL | pub struct S(u8); + | ----------------- similarly named tuple struct `S` defined here +... +LL | Z; + | ^ + | | + | constructor is not visible here due to private fields + | help: a tuple struct with a similar name exists: `S` + +error[E0423]: expected value, found struct `S` + --> $DIR/privacy-struct-ctor.rs:33:5 + | +LL | S; + | ^ constructor is not visible here due to private fields + +error[E0423]: expected value, found struct `S2` + --> $DIR/privacy-struct-ctor.rs:38:5 + | +LL | / pub struct S2 { +LL | | s: u8 +LL | | } + | |_____- `S2` defined here +... +LL | S2; + | ^^ help: use struct literal syntax instead: `S2 { s: val }` + +error[E0423]: expected value, found struct `xcrate::S` + --> $DIR/privacy-struct-ctor.rs:43:5 + | +LL | xcrate::S; + | ^^^^^^^^^ constructor is not visible here due to private fields + | +note: tuple struct `m::S` exists but is inaccessible + --> $DIR/privacy-struct-ctor.rs:6:5 + | +LL | pub struct S(u8); + | ^^^^^^^^^^^^^^^^^ not accessible + +error[E0603]: tuple struct constructor `Z` is private + --> $DIR/privacy-struct-ctor.rs:18:12 + | +LL | pub(in m) struct Z(pub(in m::n) u8); + | --------------- a constructor is private if any of the fields is private +... +LL | n::Z; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `Z` is defined here + --> $DIR/privacy-struct-ctor.rs:12:9 + | +LL | pub(in m) struct Z(pub(in m::n) u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub(in m) struct Z(pub u8); + | ~~~ + +error[E0603]: tuple struct constructor `S` is private + --> $DIR/privacy-struct-ctor.rs:29:8 + | +LL | pub struct S(u8); + | -- a constructor is private if any of the fields is private +... +LL | m::S; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `S` is defined here + --> $DIR/privacy-struct-ctor.rs:6:5 + | +LL | pub struct S(u8); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct S(pub u8); + | +++ + +error[E0603]: tuple struct constructor `S` is private + --> $DIR/privacy-struct-ctor.rs:31:19 + | +LL | pub struct S(u8); + | -- a constructor is private if any of the fields is private +... +LL | let _: S = m::S(2); + | ^ private tuple struct constructor + | +note: the tuple struct constructor `S` is defined here + --> $DIR/privacy-struct-ctor.rs:6:5 + | +LL | pub struct S(u8); + | ^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub struct S(pub u8); + | +++ + +error[E0603]: tuple struct constructor `Z` is private + --> $DIR/privacy-struct-ctor.rs:35:11 + | +LL | pub(in m) struct Z(pub(in m::n) u8); + | --------------- a constructor is private if any of the fields is private +... +LL | m::n::Z; + | ^ private tuple struct constructor + | +note: the tuple struct constructor `Z` is defined here + --> $DIR/privacy-struct-ctor.rs:12:9 + | +LL | pub(in m) struct Z(pub(in m::n) u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider making the field publicly accessible + | +LL | pub(in m) struct Z(pub u8); + | ~~~ + +error[E0603]: tuple struct constructor `S` is private + --> $DIR/privacy-struct-ctor.rs:41:16 + | +LL | xcrate::m::S; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18 + | +LL | pub struct S(u8); + | -- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `S` is defined here + --> $DIR/auxiliary/privacy-struct-ctor.rs:2:5 + | +LL | pub struct S(u8); + | ^^^^^^^^^^^^ + +error[E0603]: tuple struct constructor `Z` is private + --> $DIR/privacy-struct-ctor.rs:45:19 + | +LL | xcrate::m::n::Z; + | ^ private tuple struct constructor + | + ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28 + | +LL | pub(in m) struct Z(pub(in m::n) u8); + | --------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `Z` is defined here + --> $DIR/auxiliary/privacy-struct-ctor.rs:5:9 + | +LL | pub(in m) struct Z(pub(in m::n) u8); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0423, E0603. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/raw-ident-in-path.rs b/tests/ui/resolve/raw-ident-in-path.rs new file mode 100644 index 000000000..7f1163beb --- /dev/null +++ b/tests/ui/resolve/raw-ident-in-path.rs @@ -0,0 +1,5 @@ +// Regression test for issue #63882. + +type A = crate::r#break; //~ ERROR cannot find type `r#break` in the crate root + +fn main() {} diff --git a/tests/ui/resolve/raw-ident-in-path.stderr b/tests/ui/resolve/raw-ident-in-path.stderr new file mode 100644 index 000000000..771dacbbb --- /dev/null +++ b/tests/ui/resolve/raw-ident-in-path.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `r#break` in the crate root + --> $DIR/raw-ident-in-path.rs:3:17 + | +LL | type A = crate::r#break; + | ^^^^^^^ not found in the crate root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/resolve-assoc-suggestions.rs b/tests/ui/resolve/resolve-assoc-suggestions.rs new file mode 100644 index 000000000..ee9bce60c --- /dev/null +++ b/tests/ui/resolve/resolve-assoc-suggestions.rs @@ -0,0 +1,39 @@ +// Make sure associated items are recommended only in appropriate contexts. + +struct S { + field: u8, +} + +trait Tr { + fn method(&self); + type Type; +} + +impl Tr for S { + type Type = u8; + + fn method(&self) { + let _: field; + //~^ ERROR cannot find type `field` + let field(..); + //~^ ERROR cannot find tuple struct or tuple variant `field` + field; + //~^ ERROR cannot find value `field` + + let _: Type; + //~^ ERROR cannot find type `Type` + let Type(..); + //~^ ERROR cannot find tuple struct or tuple variant `Type` + Type; + //~^ ERROR cannot find value `Type` + + let _: method; + //~^ ERROR cannot find type `method` + let method(..); + //~^ ERROR cannot find tuple struct or tuple variant `method` + method; + //~^ ERROR cannot find value `method` + } +} + +fn main() {} diff --git a/tests/ui/resolve/resolve-assoc-suggestions.stderr b/tests/ui/resolve/resolve-assoc-suggestions.stderr new file mode 100644 index 000000000..8def9aa20 --- /dev/null +++ b/tests/ui/resolve/resolve-assoc-suggestions.stderr @@ -0,0 +1,58 @@ +error[E0412]: cannot find type `field` in this scope + --> $DIR/resolve-assoc-suggestions.rs:16:16 + | +LL | let _: field; + | ^^^^^ not found in this scope + +error[E0531]: cannot find tuple struct or tuple variant `field` in this scope + --> $DIR/resolve-assoc-suggestions.rs:18:13 + | +LL | let field(..); + | ^^^^^ not found in this scope + +error[E0425]: cannot find value `field` in this scope + --> $DIR/resolve-assoc-suggestions.rs:20:9 + | +LL | field; + | ^^^^^ help: you might have meant to use the available field: `self.field` + +error[E0412]: cannot find type `Type` in this scope + --> $DIR/resolve-assoc-suggestions.rs:23:16 + | +LL | let _: Type; + | ^^^^ help: you might have meant to use the associated type: `Self::Type` + +error[E0531]: cannot find tuple struct or tuple variant `Type` in this scope + --> $DIR/resolve-assoc-suggestions.rs:25:13 + | +LL | let Type(..); + | ^^^^ not found in this scope + +error[E0425]: cannot find value `Type` in this scope + --> $DIR/resolve-assoc-suggestions.rs:27:9 + | +LL | Type; + | ^^^^ not found in this scope + +error[E0412]: cannot find type `method` in this scope + --> $DIR/resolve-assoc-suggestions.rs:30:16 + | +LL | let _: method; + | ^^^^^^ not found in this scope + +error[E0531]: cannot find tuple struct or tuple variant `method` in this scope + --> $DIR/resolve-assoc-suggestions.rs:32:13 + | +LL | let method(..); + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `method` in this scope + --> $DIR/resolve-assoc-suggestions.rs:34:9 + | +LL | method; + | ^^^^^^ help: you might have meant to refer to the method: `self.method` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0412, E0425, E0531. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/resolve-bad-import-prefix.rs b/tests/ui/resolve/resolve-bad-import-prefix.rs new file mode 100644 index 000000000..325c69b43 --- /dev/null +++ b/tests/ui/resolve/resolve-bad-import-prefix.rs @@ -0,0 +1,14 @@ +mod m {} +enum E {} +struct S; +trait Tr {} + +use {}; // OK +use ::{}; // OK +use m::{}; // OK +use E::{}; // OK +use S::{}; // FIXME, this and `use S::{self};` should be an error +use Tr::{}; // FIXME, this and `use Tr::{self};` should be an error +use Nonexistent::{}; //~ ERROR unresolved import `Nonexistent` + +fn main () {} diff --git a/tests/ui/resolve/resolve-bad-import-prefix.stderr b/tests/ui/resolve/resolve-bad-import-prefix.stderr new file mode 100644 index 000000000..852b9c6af --- /dev/null +++ b/tests/ui/resolve/resolve-bad-import-prefix.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `Nonexistent` + --> $DIR/resolve-bad-import-prefix.rs:12:5 + | +LL | use Nonexistent::{}; + | ^^^^^^^^^^^^^^^ no `Nonexistent` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/resolve/resolve-bad-visibility.rs b/tests/ui/resolve/resolve-bad-visibility.rs new file mode 100644 index 000000000..7d48bb97b --- /dev/null +++ b/tests/ui/resolve/resolve-bad-visibility.rs @@ -0,0 +1,15 @@ +enum E {} +trait Tr {} + +pub(in E) struct S; //~ ERROR expected module, found enum `E` +pub(in Tr) struct Z; //~ ERROR expected module, found trait `Tr` +pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules +pub(in nonexistent) struct G; //~ ERROR failed to resolve +pub(in too_soon) struct H; //~ ERROR failed to resolve + +// Visibilities are resolved eagerly without waiting for modules becoming fully populated. +// Visibilities can only use ancestor modules legally which are always available in time, +// so the worst thing that can happen due to eager resolution is a suboptimal error message. +mod too_soon {} + +fn main () {} diff --git a/tests/ui/resolve/resolve-bad-visibility.stderr b/tests/ui/resolve/resolve-bad-visibility.stderr new file mode 100644 index 000000000..2ac41b875 --- /dev/null +++ b/tests/ui/resolve/resolve-bad-visibility.stderr @@ -0,0 +1,38 @@ +error[E0577]: expected module, found enum `E` + --> $DIR/resolve-bad-visibility.rs:4:8 + | +LL | pub(in E) struct S; + | ^ not a module + +error[E0577]: expected module, found trait `Tr` + --> $DIR/resolve-bad-visibility.rs:5:8 + | +LL | pub(in Tr) struct Z; + | ^^ not a module + +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/resolve-bad-visibility.rs:6:8 + | +LL | pub(in std::vec) struct F; + | ^^^^^^^^ + +error[E0433]: failed to resolve: maybe a missing crate `nonexistent`? + --> $DIR/resolve-bad-visibility.rs:7:8 + | +LL | pub(in nonexistent) struct G; + | ^^^^^^^^^^^ maybe a missing crate `nonexistent`? + | + = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate + +error[E0433]: failed to resolve: maybe a missing crate `too_soon`? + --> $DIR/resolve-bad-visibility.rs:8:8 + | +LL | pub(in too_soon) struct H; + | ^^^^^^^^ maybe a missing crate `too_soon`? + | + = help: consider adding `extern crate too_soon` to use the `too_soon` crate + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0433, E0577, E0742. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs b/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs new file mode 100644 index 000000000..3cb6ab52e --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs @@ -0,0 +1,4 @@ +extern crate std; +//~^ ERROR the name `std` is defined multiple times + +fn main(){} diff --git a/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr new file mode 100644 index 000000000..ea6cb9eb0 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr @@ -0,0 +1,11 @@ +error[E0259]: the name `std` is defined multiple times + | + = note: `std` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | extern crate std as other_std; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.rs b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.rs new file mode 100644 index 000000000..10772e7a4 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.rs @@ -0,0 +1,4 @@ +use std::slice as std; //~ ERROR the name `std` is defined multiple times + +fn main() { +} diff --git a/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr new file mode 100644 index 000000000..abf068a1f --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-import-vs-extern-crate.stderr @@ -0,0 +1,15 @@ +error[E0254]: the name `std` is defined multiple times + --> $DIR/resolve-conflict-import-vs-extern-crate.rs:1:5 + | +LL | use std::slice as std; + | ^^^^^^^^^^^^^^^^^ `std` reimported here + | + = note: `std` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::slice as other_std; + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/resolve/resolve-conflict-import-vs-import.fixed b/tests/ui/resolve/resolve-conflict-import-vs-import.fixed new file mode 100644 index 000000000..e429513b5 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-import-vs-import.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#[allow(unused_imports)] +use std::mem::transmute; + +//~^ ERROR the name `transmute` is defined multiple times + +fn main() { +} diff --git a/tests/ui/resolve/resolve-conflict-import-vs-import.rs b/tests/ui/resolve/resolve-conflict-import-vs-import.rs new file mode 100644 index 000000000..43853117a --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-import-vs-import.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#[allow(unused_imports)] +use std::mem::transmute; +use std::mem::transmute; +//~^ ERROR the name `transmute` is defined multiple times + +fn main() { +} diff --git a/tests/ui/resolve/resolve-conflict-import-vs-import.stderr b/tests/ui/resolve/resolve-conflict-import-vs-import.stderr new file mode 100644 index 000000000..632be50f4 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-import-vs-import.stderr @@ -0,0 +1,13 @@ +error[E0252]: the name `transmute` is defined multiple times + --> $DIR/resolve-conflict-import-vs-import.rs:5:5 + | +LL | use std::mem::transmute; + | ------------------- previous import of the value `transmute` here +LL | use std::mem::transmute; + | ^^^^^^^^^^^^^^^^^^^ `transmute` reimported here + | + = note: `transmute` must be defined only once in the value namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.rs b/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.rs new file mode 100644 index 000000000..122606249 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.rs @@ -0,0 +1,5 @@ +fn std() {} +mod std {} //~ ERROR the name `std` is defined multiple times + +fn main() { +} diff --git a/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr b/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr new file mode 100644 index 000000000..7b9fb6c63 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-item-vs-extern-crate.stderr @@ -0,0 +1,11 @@ +error[E0260]: the name `std` is defined multiple times + --> $DIR/resolve-conflict-item-vs-extern-crate.rs:2:1 + | +LL | mod std {} + | ^^^^^^^ `std` redefined here + | + = note: `std` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0260`. diff --git a/tests/ui/resolve/resolve-conflict-item-vs-import.rs b/tests/ui/resolve/resolve-conflict-item-vs-import.rs new file mode 100644 index 000000000..4308c7a27 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-item-vs-import.rs @@ -0,0 +1,8 @@ +use std::mem::transmute; + +fn transmute() {} +//~^ ERROR the name `transmute` is defined multiple times +//~| `transmute` redefined here +//~| `transmute` must be defined only once in the value namespace of this module +fn main() { +} diff --git a/tests/ui/resolve/resolve-conflict-item-vs-import.stderr b/tests/ui/resolve/resolve-conflict-item-vs-import.stderr new file mode 100644 index 000000000..5e5c9f6b3 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-item-vs-import.stderr @@ -0,0 +1,18 @@ +error[E0255]: the name `transmute` is defined multiple times + --> $DIR/resolve-conflict-item-vs-import.rs:3:1 + | +LL | use std::mem::transmute; + | ------------------- previous import of the value `transmute` here +LL | +LL | fn transmute() {} + | ^^^^^^^^^^^^^^ `transmute` redefined here + | + = note: `transmute` must be defined only once in the value namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::mem::transmute as other_transmute; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/resolve/resolve-conflict-type-vs-import.rs b/tests/ui/resolve/resolve-conflict-type-vs-import.rs new file mode 100644 index 000000000..3abce8396 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-type-vs-import.rs @@ -0,0 +1,7 @@ +use std::slice::Iter; + +struct Iter; +//~^ ERROR the name `Iter` is defined multiple times + +fn main() { +} diff --git a/tests/ui/resolve/resolve-conflict-type-vs-import.stderr b/tests/ui/resolve/resolve-conflict-type-vs-import.stderr new file mode 100644 index 000000000..198ef1031 --- /dev/null +++ b/tests/ui/resolve/resolve-conflict-type-vs-import.stderr @@ -0,0 +1,18 @@ +error[E0255]: the name `Iter` is defined multiple times + --> $DIR/resolve-conflict-type-vs-import.rs:3:1 + | +LL | use std::slice::Iter; + | ---------------- previous import of the type `Iter` here +LL | +LL | struct Iter; + | ^^^^^^^^^^^^ `Iter` redefined here + | + = note: `Iter` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | use std::slice::Iter as OtherIter; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/resolve/resolve-hint-macro.fixed b/tests/ui/resolve/resolve-hint-macro.fixed new file mode 100644 index 000000000..54e016084 --- /dev/null +++ b/tests/ui/resolve/resolve-hint-macro.fixed @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + assert_eq!(1, 1); + //~^ ERROR expected function, found macro `assert_eq` + assert_eq! { 1, 1 }; + //~^ ERROR expected struct, variant or union type, found macro `assert_eq` + //~| ERROR expected identifier, found `1` + //~| ERROR expected identifier, found `1` + assert![true]; + //~^ ERROR expected value, found macro `assert` +} diff --git a/tests/ui/resolve/resolve-hint-macro.rs b/tests/ui/resolve/resolve-hint-macro.rs new file mode 100644 index 000000000..f16e8c075 --- /dev/null +++ b/tests/ui/resolve/resolve-hint-macro.rs @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + assert_eq(1, 1); + //~^ ERROR expected function, found macro `assert_eq` + assert_eq { 1, 1 }; + //~^ ERROR expected struct, variant or union type, found macro `assert_eq` + //~| ERROR expected identifier, found `1` + //~| ERROR expected identifier, found `1` + assert[true]; + //~^ ERROR expected value, found macro `assert` +} diff --git a/tests/ui/resolve/resolve-hint-macro.stderr b/tests/ui/resolve/resolve-hint-macro.stderr new file mode 100644 index 000000000..1e7ab48ef --- /dev/null +++ b/tests/ui/resolve/resolve-hint-macro.stderr @@ -0,0 +1,53 @@ +error: expected identifier, found `1` + --> $DIR/resolve-hint-macro.rs:5:17 + | +LL | assert_eq { 1, 1 }; + | --------- ^ expected identifier + | | + | while parsing this struct + +error: expected identifier, found `1` + --> $DIR/resolve-hint-macro.rs:5:20 + | +LL | assert_eq { 1, 1 }; + | --------- ^ expected identifier + | | + | while parsing this struct + +error[E0574]: expected struct, variant or union type, found macro `assert_eq` + --> $DIR/resolve-hint-macro.rs:5:5 + | +LL | assert_eq { 1, 1 }; + | ^^^^^^^^^ not a struct, variant or union type + | +help: use `!` to invoke the macro + | +LL | assert_eq! { 1, 1 }; + | + + +error[E0423]: expected value, found macro `assert` + --> $DIR/resolve-hint-macro.rs:9:5 + | +LL | assert[true]; + | ^^^^^^ not a value + | +help: use `!` to invoke the macro + | +LL | assert![true]; + | + + +error[E0423]: expected function, found macro `assert_eq` + --> $DIR/resolve-hint-macro.rs:3:5 + | +LL | assert_eq(1, 1); + | ^^^^^^^^^ not a function + | +help: use `!` to invoke the macro + | +LL | assert_eq!(1, 1); + | + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0423, E0574. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/resolve-inconsistent-binding-mode.rs b/tests/ui/resolve/resolve-inconsistent-binding-mode.rs new file mode 100644 index 000000000..43e9378b7 --- /dev/null +++ b/tests/ui/resolve/resolve-inconsistent-binding-mode.rs @@ -0,0 +1,41 @@ +enum Opts { + A(isize), + B(isize), + C(isize), +} + +fn matcher1(x: Opts) { + match x { + Opts::A(ref i) | Opts::B(i) => {} + //~^ ERROR variable `i` is bound inconsistently + //~^^ ERROR mismatched types + Opts::C(_) => {} + } +} + +fn matcher2(x: Opts) { + match x { + Opts::A(ref i) | Opts::B(i) => {} + //~^ ERROR variable `i` is bound inconsistently + //~^^ ERROR mismatched types + Opts::C(_) => {} + } +} + +fn matcher4(x: Opts) { + match x { + Opts::A(ref mut i) | Opts::B(ref i) => {} + //~^ ERROR variable `i` is bound inconsistently + //~^^ ERROR mismatched types + Opts::C(_) => {} + } +} + +fn matcher5(x: Opts) { + match x { + Opts::A(ref i) | Opts::B(ref i) => {} + Opts::C(_) => {} + } +} + +fn main() {} diff --git a/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr b/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr new file mode 100644 index 000000000..c805c9eb1 --- /dev/null +++ b/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr @@ -0,0 +1,72 @@ +error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-binding-mode.rs:9:34 + | +LL | Opts::A(ref i) | Opts::B(i) => {} + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-binding-mode.rs:18:34 + | +LL | Opts::A(ref i) | Opts::B(i) => {} + | - ^ bound in different ways + | | + | first binding + +error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-binding-mode.rs:27:42 + | +LL | Opts::A(ref mut i) | Opts::B(ref i) => {} + | - first binding ^ bound in different ways + +error[E0308]: mismatched types + --> $DIR/resolve-inconsistent-binding-mode.rs:9:34 + | +LL | match x { + | - this expression has type `Opts` +LL | Opts::A(ref i) | Opts::B(i) => {} + | ----- ^ expected `&isize`, found `isize` + | | + | first introduced with type `&isize` here + | + = note: in the same arm, a binding must have the same type in all alternatives +help: consider adding `ref` + | +LL | Opts::A(ref i) | Opts::B(ref i) => {} + | +++ + +error[E0308]: mismatched types + --> $DIR/resolve-inconsistent-binding-mode.rs:18:34 + | +LL | match x { + | - this expression has type `Opts` +LL | Opts::A(ref i) | Opts::B(i) => {} + | ----- ^ expected `&isize`, found `isize` + | | + | first introduced with type `&isize` here + | + = note: in the same arm, a binding must have the same type in all alternatives +help: consider adding `ref` + | +LL | Opts::A(ref i) | Opts::B(ref i) => {} + | +++ + +error[E0308]: mismatched types + --> $DIR/resolve-inconsistent-binding-mode.rs:27:38 + | +LL | match x { + | - this expression has type `Opts` +LL | Opts::A(ref mut i) | Opts::B(ref i) => {} + | --------- ^^^^^ types differ in mutability + | | + | first introduced with type `&mut isize` here + | + = note: expected mutable reference `&mut isize` + found reference `&isize` + = note: in the same arm, a binding must have the same type in all alternatives + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/resolve-inconsistent-names.rs b/tests/ui/resolve/resolve-inconsistent-names.rs new file mode 100644 index 000000000..9a40b2034 --- /dev/null +++ b/tests/ui/resolve/resolve-inconsistent-names.rs @@ -0,0 +1,36 @@ +#![allow(non_camel_case_types)] + +enum E { A, B, c } + +pub mod m { + const CONST1: usize = 10; + pub const Const2: usize = 20; +} + +fn main() { + let y = 1; + match y { + a | b => {} //~ ERROR variable `a` is not bound in all patterns + //~| ERROR variable `b` is not bound in all patterns + } + + let x = (E::A, E::B); + match x { + (A, B) | (ref B, c) | (c, A) => () + //~^ ERROR variable `A` is not bound in all patterns + //~| ERROR variable `B` is not bound in all patterns + //~| ERROR variable `B` is bound inconsistently + //~| ERROR mismatched types + //~| ERROR variable `c` is not bound in all patterns + //~| HELP if you meant to match on unit variant `E::A`, use the full path in the pattern + //~| HELP consider removing `ref` + } + + let z = (10, 20); + match z { + (CONST1, _) | (_, Const2) => () + //~^ ERROR variable `CONST1` is not bound in all patterns + //~| ERROR variable `Const2` is not bound in all patterns + //~| HELP if you meant to match on constant `m::Const2`, use the full path in the pattern + } +} diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr new file mode 100644 index 000000000..773c9f6cd --- /dev/null +++ b/tests/ui/resolve/resolve-inconsistent-names.stderr @@ -0,0 +1,104 @@ +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:13:12 + | +LL | a | b => {} + | - ^ pattern doesn't bind `a` + | | + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:13:8 + | +LL | a | b => {} + | ^ - variable not in all patterns + | | + | pattern doesn't bind `b` + +error[E0408]: variable `A` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:19:18 + | +LL | (A, B) | (ref B, c) | (c, A) => () + | - ^^^^^^^^^^ - variable not in all patterns + | | | + | | pattern doesn't bind `A` + | variable not in all patterns + | +help: if you meant to match on unit variant `E::A`, use the full path in the pattern + | +LL | (E::A, B) | (ref B, c) | (c, A) => () + | ~~~~ + +error[E0408]: variable `B` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:19:31 + | +LL | (A, B) | (ref B, c) | (c, A) => () + | - - ^^^^^^ pattern doesn't bind `B` + | | | + | | variable not in all patterns + | variable not in all patterns + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:19:9 + | +LL | (A, B) | (ref B, c) | (c, A) => () + | ^^^^^^ - - variable not in all patterns + | | | + | | variable not in all patterns + | pattern doesn't bind `c` + +error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-names.rs:19:23 + | +LL | (A, B) | (ref B, c) | (c, A) => () + | - ^ bound in different ways + | | + | first binding + +error[E0408]: variable `CONST1` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:31:23 + | +LL | (CONST1, _) | (_, Const2) => () + | ------ ^^^^^^^^^^^ pattern doesn't bind `CONST1` + | | + | variable not in all patterns + | +note: you might have meant to match on constant `m::CONST1`, which exists but is inaccessible + --> $DIR/resolve-inconsistent-names.rs:6:5 + | +LL | const CONST1: usize = 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible + +error[E0408]: variable `Const2` is not bound in all patterns + --> $DIR/resolve-inconsistent-names.rs:31:9 + | +LL | (CONST1, _) | (_, Const2) => () + | ^^^^^^^^^^^ ------ variable not in all patterns + | | + | pattern doesn't bind `Const2` + | +help: if you meant to match on constant `m::Const2`, use the full path in the pattern + | +LL | (CONST1, _) | (_, m::Const2) => () + | ~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/resolve-inconsistent-names.rs:19:19 + | +LL | match x { + | - this expression has type `(E, E)` +LL | (A, B) | (ref B, c) | (c, A) => () + | - ^^^^^ expected enum `E`, found `&E` + | | + | first introduced with type `E` here + | + = note: in the same arm, a binding must have the same type in all alternatives +help: consider removing `ref` + | +LL - (A, B) | (ref B, c) | (c, A) => () +LL + (A, B) | (B, c) | (c, A) => () + | + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0408, E0409. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/resolve-issue-2428.rs b/tests/ui/resolve/resolve-issue-2428.rs new file mode 100644 index 000000000..5f3473e9f --- /dev/null +++ b/tests/ui/resolve/resolve-issue-2428.rs @@ -0,0 +1,8 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +const foo: isize = 4 >> 1; +enum bs { thing = foo } +pub fn main() { assert_eq!(bs::thing as isize, foo); } diff --git a/tests/ui/resolve/resolve-label.rs b/tests/ui/resolve/resolve-label.rs new file mode 100644 index 000000000..ac5410cd3 --- /dev/null +++ b/tests/ui/resolve/resolve-label.rs @@ -0,0 +1,13 @@ +fn f() { + 'l: loop { + fn g() { + loop { + break 'l; //~ ERROR use of unreachable label + } + } + } + + loop { 'w: while break 'w { } } +} + +fn main() {} diff --git a/tests/ui/resolve/resolve-label.stderr b/tests/ui/resolve/resolve-label.stderr new file mode 100644 index 000000000..5729348ef --- /dev/null +++ b/tests/ui/resolve/resolve-label.stderr @@ -0,0 +1,14 @@ +error[E0767]: use of unreachable label `'l` + --> $DIR/resolve-label.rs:5:23 + | +LL | 'l: loop { + | -- unreachable label defined here +... +LL | break 'l; + | ^^ unreachable label `'l` + | + = note: labels are unreachable through functions, closures, async blocks and modules + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0767`. diff --git a/tests/ui/resolve/resolve-primitive-fallback.rs b/tests/ui/resolve/resolve-primitive-fallback.rs new file mode 100644 index 000000000..05cabd9e3 --- /dev/null +++ b/tests/ui/resolve/resolve-primitive-fallback.rs @@ -0,0 +1,10 @@ +fn main() { + // Make sure primitive type fallback doesn't work in value namespace + std::mem::size_of(u16); + //~^ ERROR expected value, found builtin type `u16` + //~| ERROR function takes 0 arguments but 1 argument was supplied + + // Make sure primitive type fallback doesn't work with global paths + let _: ::u8; + //~^ ERROR cannot find type `u8` in the crate root +} diff --git a/tests/ui/resolve/resolve-primitive-fallback.stderr b/tests/ui/resolve/resolve-primitive-fallback.stderr new file mode 100644 index 000000000..964302e92 --- /dev/null +++ b/tests/ui/resolve/resolve-primitive-fallback.stderr @@ -0,0 +1,39 @@ +error[E0423]: expected value, found builtin type `u16` + --> $DIR/resolve-primitive-fallback.rs:3:23 + | +LL | std::mem::size_of(u16); + | ^^^ not a value + +error[E0412]: cannot find type `u8` in the crate root + --> $DIR/resolve-primitive-fallback.rs:8:14 + | +LL | let _: ::u8; + | ^^ not found in the crate root + | +help: consider importing this builtin type + | +LL | use std::primitive::u8; + | +help: if you import `u8`, refer to it directly + | +LL - let _: ::u8; +LL + let _: u8; + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/resolve-primitive-fallback.rs:3:5 + | +LL | std::mem::size_of(u16); + | ^^^^^^^^^^^^^^^^^ --- argument unexpected + | +note: function defined here + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: remove the extra argument + | +LL | std::mem::size_of(); + | ~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0061, E0412, E0423. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/resolve/resolve-pseudo-shadowing.rs b/tests/ui/resolve/resolve-pseudo-shadowing.rs new file mode 100644 index 000000000..85c684ca0 --- /dev/null +++ b/tests/ui/resolve/resolve-pseudo-shadowing.rs @@ -0,0 +1,11 @@ +// run-pass +// check that type parameters can't "shadow" qualified paths. + +fn check(_c: Clone) { + fn check2() { + let _ = <() as std::clone::Clone>::clone(&()); + } + check2(); +} + +fn main() { check(()); } diff --git a/tests/ui/resolve/resolve-self-in-impl-2.rs b/tests/ui/resolve/resolve-self-in-impl-2.rs new file mode 100644 index 000000000..f586760c8 --- /dev/null +++ b/tests/ui/resolve/resolve-self-in-impl-2.rs @@ -0,0 +1,7 @@ +struct S(T); +trait Tr {} + +impl Self for S {} //~ ERROR expected trait, found self type `Self` +impl Self::N for S {} //~ ERROR cannot find trait `N` in `Self` + +fn main() {} diff --git a/tests/ui/resolve/resolve-self-in-impl-2.stderr b/tests/ui/resolve/resolve-self-in-impl-2.stderr new file mode 100644 index 000000000..3791fe90a --- /dev/null +++ b/tests/ui/resolve/resolve-self-in-impl-2.stderr @@ -0,0 +1,16 @@ +error[E0411]: expected trait, found self type `Self` + --> $DIR/resolve-self-in-impl-2.rs:4:6 + | +LL | impl Self for S {} + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0405]: cannot find trait `N` in `Self` + --> $DIR/resolve-self-in-impl-2.rs:5:12 + | +LL | impl Self::N for S {} + | ^ not found in `Self` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0405, E0411. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/resolve-self-in-impl.rs b/tests/ui/resolve/resolve-self-in-impl.rs new file mode 100644 index 000000000..d0872d1b7 --- /dev/null +++ b/tests/ui/resolve/resolve-self-in-impl.rs @@ -0,0 +1,21 @@ +#![feature(associated_type_defaults)] + +struct S(T); +trait Tr { + type A = (); +} + +impl Tr for S {} // OK +impl> Tr for S {} // OK +impl Tr for S where Self: Copy {} // OK +impl Tr for S where S: Copy {} // OK +impl Tr for S where Self::A: Copy {} // OK + +impl Tr for Self {} //~ ERROR `Self` is not valid in the self type of an impl block +impl Tr for S {} //~ ERROR `Self` is not valid in the self type of an impl block +impl Self {} //~ ERROR `Self` is not valid in the self type of an impl block +impl S {} //~ ERROR `Self` is not valid in the self type of an impl block +impl (Self, Self) {} //~ ERROR `Self` is not valid in the self type of an impl block +impl Tr for S {} //~ ERROR cycle detected + +fn main() {} diff --git a/tests/ui/resolve/resolve-self-in-impl.stderr b/tests/ui/resolve/resolve-self-in-impl.stderr new file mode 100644 index 000000000..b3042d413 --- /dev/null +++ b/tests/ui/resolve/resolve-self-in-impl.stderr @@ -0,0 +1,62 @@ +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:16:6 + | +LL | impl Self {} + | ^^^^ + | + = note: replace `Self` with a different type + +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:17:8 + | +LL | impl S {} + | ^^^^ + | + = note: replace `Self` with a different type + +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:18:7 + | +LL | impl (Self, Self) {} + | ^^^^ ^^^^ + | + = note: replace `Self` with a different type + +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:14:13 + | +LL | impl Tr for Self {} + | ^^^^ + | + = note: replace `Self` with a different type + +error: `Self` is not valid in the self type of an impl block + --> $DIR/resolve-self-in-impl.rs:15:15 + | +LL | impl Tr for S {} + | ^^^^ + | + = note: replace `Self` with a different type + +error[E0391]: cycle detected when computing trait implemented by `` + --> $DIR/resolve-self-in-impl.rs:19:1 + | +LL | impl Tr for S {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...which immediately requires computing trait implemented by `` again +note: cycle used when collecting item types in top-level module + --> $DIR/resolve-self-in-impl.rs:1:1 + | +LL | / #![feature(associated_type_defaults)] +LL | | +LL | | struct S(T); +LL | | trait Tr { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/resolve/resolve-speculative-adjustment.rs b/tests/ui/resolve/resolve-speculative-adjustment.rs new file mode 100644 index 000000000..81f757829 --- /dev/null +++ b/tests/ui/resolve/resolve-speculative-adjustment.rs @@ -0,0 +1,30 @@ +// Make sure speculative path resolution works properly when resolution +// adjustment happens and no extra errors is reported. + +struct S { + field: u8, +} + +trait Tr { + fn method(&self); +} + +impl Tr for S { + fn method(&self) { + fn g() { + // Speculative resolution of `Self` and `self` silently fails, + // "did you mean" messages are not printed. + field; + //~^ ERROR cannot find value `field` + method(); + //~^ ERROR cannot find function `method` + } + + field; + //~^ ERROR cannot find value `field` + method(); + //~^ ERROR cannot find function `method` + } +} + +fn main() {} diff --git a/tests/ui/resolve/resolve-speculative-adjustment.stderr b/tests/ui/resolve/resolve-speculative-adjustment.stderr new file mode 100644 index 000000000..be11a7ebe --- /dev/null +++ b/tests/ui/resolve/resolve-speculative-adjustment.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `field` in this scope + --> $DIR/resolve-speculative-adjustment.rs:17:13 + | +LL | field; + | ^^^^^ not found in this scope + +error[E0425]: cannot find value `field` in this scope + --> $DIR/resolve-speculative-adjustment.rs:23:9 + | +LL | field; + | ^^^^^ help: you might have meant to use the available field: `self.field` + +error[E0425]: cannot find function `method` in this scope + --> $DIR/resolve-speculative-adjustment.rs:25:9 + | +LL | method(); + | ^^^^^^ help: you might have meant to call the method: `self.method` + +error[E0425]: cannot find function `method` in this scope + --> $DIR/resolve-speculative-adjustment.rs:19:13 + | +LL | method(); + | ^^^^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs b/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs new file mode 100644 index 000000000..c77a66524 --- /dev/null +++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.rs @@ -0,0 +1,35 @@ +// Issue #14603: Check for references to type parameters from the +// outer scope (in this case, the trait) used on items in an inner +// scope (in this case, the enum). + +trait TraitA { + fn outer(&self) { + enum Foo { + Variance(A) + //~^ ERROR can't use generic parameters from outer function + } + } +} + +trait TraitB { + fn outer(&self) { + struct Foo(A); + //~^ ERROR can't use generic parameters from outer function + } +} + +trait TraitC { + fn outer(&self) { + struct Foo { a: A } + //~^ ERROR can't use generic parameters from outer function + } +} + +trait TraitD { + fn outer(&self) { + fn foo(a: A) { } + //~^ ERROR can't use generic parameters from outer function + } +} + +fn main() { } diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr new file mode 100644 index 000000000..0a6d1cc3b --- /dev/null +++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr @@ -0,0 +1,47 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/resolve-type-param-in-item-in-trait.rs:8:22 + | +LL | trait TraitA { + | - type parameter from outer function +LL | fn outer(&self) { +LL | enum Foo { + | - help: try using a local generic parameter instead: `A,` +LL | Variance(A) + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/resolve-type-param-in-item-in-trait.rs:16:23 + | +LL | trait TraitB { + | - type parameter from outer function +LL | fn outer(&self) { +LL | struct Foo(A); + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `A,` + +error[E0401]: can't use generic parameters from outer function + --> $DIR/resolve-type-param-in-item-in-trait.rs:23:28 + | +LL | trait TraitC { + | - type parameter from outer function +LL | fn outer(&self) { +LL | struct Foo { a: A } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `A,` + +error[E0401]: can't use generic parameters from outer function + --> $DIR/resolve-type-param-in-item-in-trait.rs:30:22 + | +LL | trait TraitD { + | - type parameter from outer function +LL | fn outer(&self) { +LL | fn foo(a: A) { } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `A,` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/resolve-unknown-trait.rs b/tests/ui/resolve/resolve-unknown-trait.rs new file mode 100644 index 000000000..290893bbb --- /dev/null +++ b/tests/ui/resolve/resolve-unknown-trait.rs @@ -0,0 +1,10 @@ +trait NewTrait : SomeNonExistentTrait {} +//~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope + +impl SomeNonExistentTrait for isize {} +//~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope + +fn f() {} +//~^ ERROR cannot find trait `SomeNonExistentTrait` in this scope + +fn main() {} diff --git a/tests/ui/resolve/resolve-unknown-trait.stderr b/tests/ui/resolve/resolve-unknown-trait.stderr new file mode 100644 index 000000000..e19cfe617 --- /dev/null +++ b/tests/ui/resolve/resolve-unknown-trait.stderr @@ -0,0 +1,21 @@ +error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope + --> $DIR/resolve-unknown-trait.rs:1:18 + | +LL | trait NewTrait : SomeNonExistentTrait {} + | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope + --> $DIR/resolve-unknown-trait.rs:4:6 + | +LL | impl SomeNonExistentTrait for isize {} + | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0405]: cannot find trait `SomeNonExistentTrait` in this scope + --> $DIR/resolve-unknown-trait.rs:7:8 + | +LL | fn f() {} + | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/resolve-variant-assoc-item.rs b/tests/ui/resolve/resolve-variant-assoc-item.rs new file mode 100644 index 000000000..db4fedfb0 --- /dev/null +++ b/tests/ui/resolve/resolve-variant-assoc-item.rs @@ -0,0 +1,7 @@ +enum E { V } +use E::V; + +fn main() { + E::V::associated_item; //~ ERROR failed to resolve: `V` is a variant, not a module + V::associated_item; //~ ERROR failed to resolve: `V` is a variant, not a module +} diff --git a/tests/ui/resolve/resolve-variant-assoc-item.stderr b/tests/ui/resolve/resolve-variant-assoc-item.stderr new file mode 100644 index 000000000..4be101996 --- /dev/null +++ b/tests/ui/resolve/resolve-variant-assoc-item.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: `V` is a variant, not a module + --> $DIR/resolve-variant-assoc-item.rs:5:8 + | +LL | E::V::associated_item; + | ^ `V` is a variant, not a module + +error[E0433]: failed to resolve: `V` is a variant, not a module + --> $DIR/resolve-variant-assoc-item.rs:6:5 + | +LL | V::associated_item; + | ^ `V` is a variant, not a module + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/shadow-const-param.rs b/tests/ui/resolve/shadow-const-param.rs new file mode 100644 index 000000000..c435c16dc --- /dev/null +++ b/tests/ui/resolve/shadow-const-param.rs @@ -0,0 +1,20 @@ +// Checks that const parameters cannot be shadowed with fresh bindings +// even in syntactically unambiguous contexts. See +// https://github.com/rust-lang/rust/issues/33118#issuecomment-233962221 + +fn foo(i: i32) -> bool { + match i { + N @ _ => true, + //~^ ERROR: match bindings cannot shadow const parameters [E0530] + } +} + +fn bar(i: i32) -> bool { + let N @ _ = 0; + //~^ ERROR: let bindings cannot shadow const parameters [E0530] + match i { + N @ _ => true, + } +} + +fn main() {} diff --git a/tests/ui/resolve/shadow-const-param.stderr b/tests/ui/resolve/shadow-const-param.stderr new file mode 100644 index 000000000..fbd0d8110 --- /dev/null +++ b/tests/ui/resolve/shadow-const-param.stderr @@ -0,0 +1,20 @@ +error[E0530]: match bindings cannot shadow const parameters + --> $DIR/shadow-const-param.rs:7:9 + | +LL | fn foo(i: i32) -> bool { + | - the const parameter `N` is defined here +LL | match i { +LL | N @ _ => true, + | ^ cannot be named the same as a const parameter + +error[E0530]: let bindings cannot shadow const parameters + --> $DIR/shadow-const-param.rs:13:9 + | +LL | fn bar(i: i32) -> bool { + | - the const parameter `N` is defined here +LL | let N @ _ = 0; + | ^ cannot be named the same as a const parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/resolve/suggest-path-for-tuple-struct.rs b/tests/ui/resolve/suggest-path-for-tuple-struct.rs new file mode 100644 index 000000000..c8bc3e79f --- /dev/null +++ b/tests/ui/resolve/suggest-path-for-tuple-struct.rs @@ -0,0 +1,26 @@ +mod module { + pub struct SomeTupleStruct(u8); + pub struct SomeRegularStruct { + foo: u8 + } + + impl SomeTupleStruct { + pub fn new() -> Self { + Self(0) + } + } + impl SomeRegularStruct { + pub fn new() -> Self { + Self { foo: 0 } + } + } +} + +use module::{SomeTupleStruct, SomeRegularStruct}; + +fn main() { + let _ = SomeTupleStruct.new(); + //~^ ERROR expected value, found struct `SomeTupleStruct` + let _ = SomeRegularStruct.new(); + //~^ ERROR expected value, found struct `SomeRegularStruct` +} diff --git a/tests/ui/resolve/suggest-path-for-tuple-struct.stderr b/tests/ui/resolve/suggest-path-for-tuple-struct.stderr new file mode 100644 index 000000000..4764cf2db --- /dev/null +++ b/tests/ui/resolve/suggest-path-for-tuple-struct.stderr @@ -0,0 +1,15 @@ +error[E0423]: expected value, found struct `SomeTupleStruct` + --> $DIR/suggest-path-for-tuple-struct.rs:22:13 + | +LL | let _ = SomeTupleStruct.new(); + | ^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found struct `SomeRegularStruct` + --> $DIR/suggest-path-for-tuple-struct.rs:24:13 + | +LL | let _ = SomeRegularStruct.new(); + | ^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.rs b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.rs new file mode 100644 index 000000000..d5d6b13d6 --- /dev/null +++ b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.rs @@ -0,0 +1,111 @@ +// Beginners write `mod.item` when they should write `mod::item`. +// This tests that we suggest the latter when we encounter the former. + +pub mod a { + pub const I: i32 = 1; + + pub fn f() -> i32 { 2 } + + pub mod b { + pub const J: i32 = 3; + + pub fn g() -> i32 { 4 } + } +} + +fn h1() -> i32 { + a.I + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator +} + +fn h2() -> i32 { + a.g() + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator +} + +fn h3() -> i32 { + a.b.J + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator +} + +fn h4() -> i32 { + a::b.J + //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists + //~| HELP use the path separator +} + +fn h5() { + a.b.f(); + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator + let v = Vec::new(); + v.push(a::b); + //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists +} + +fn h6() -> i32 { + a::b.f() + //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists + //~| HELP use the path separator +} + +fn h7() { + a::b + //~^ ERROR expected value, found module `a::b` + //~| HELP a constant with a similar name exists +} + +fn h8() -> i32 { + a::b() + //~^ ERROR expected function, found module `a::b` + //~| HELP a constant with a similar name exists +} + +macro_rules! module { + () => { + a + //~^ ERROR expected value, found module `a` + //~| ERROR expected value, found module `a` + }; +} + +macro_rules! create { + (method) => { + a.f() + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator + }; + (field) => { + a.f + //~^ ERROR expected value, found module `a` + //~| HELP use the path separator + }; +} + +fn h9() { + // + // Note that if the receiver is a macro call, we do not want to suggest to replace + // `.` with `::` as that would be a syntax error. + // Since the receiver is a module and not a type, we cannot suggest to surround + // it with angle brackets. + // + + module!().g::<()>(); // no `help` here! + + module!().g; // no `help` here! + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(method); + let _ = create!(field); +} + +fn main() {} diff --git a/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr new file mode 100644 index 000000000..a4ce0deeb --- /dev/null +++ b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -0,0 +1,140 @@ +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5 + | +LL | a.I + | ^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:23:5 + | +LL | a.g() + | ^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:29:5 + | +LL | a.b.J + | ^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found module `a::b` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:35:5 + | +LL | pub const I: i32 = 1; + | --------------------- similarly named constant `I` defined here +... +LL | a::b.J + | ^^^^ + | +help: use the path separator to refer to an item + | +LL | a::b::J + | ~~ +help: a constant with a similar name exists + | +LL | a::I.J + | ~ + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:42:5 + | +LL | a.b.f(); + | ^- help: use the path separator to refer to an item: `::` + +error[E0423]: expected value, found module `a::b` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:46:12 + | +LL | pub const I: i32 = 1; + | --------------------- similarly named constant `I` defined here +... +LL | v.push(a::b); + | ^^^- + | | + | help: a constant with a similar name exists: `I` + +error[E0423]: expected value, found module `a::b` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:52:5 + | +LL | pub const I: i32 = 1; + | --------------------- similarly named constant `I` defined here +... +LL | a::b.f() + | ^^^^ + | +help: use the path separator to refer to an item + | +LL | a::b::f() + | ~~ +help: a constant with a similar name exists + | +LL | a::I.f() + | ~ + +error[E0423]: expected value, found module `a::b` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:59:5 + | +LL | pub const I: i32 = 1; + | --------------------- similarly named constant `I` defined here +... +LL | a::b + | ^^^- + | | + | help: a constant with a similar name exists: `I` + +error[E0423]: expected function, found module `a::b` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:65:5 + | +LL | pub const I: i32 = 1; + | --------------------- similarly named constant `I` defined here +... +LL | a::b() + | ^^^- + | | + | help: a constant with a similar name exists: `I` + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9 + | +LL | a + | ^ not a value +... +LL | module!().g::<()>(); // no `help` here! + | --------- in this macro invocation + | + = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9 + | +LL | a + | ^ not a value +... +LL | module!().g; // no `help` here! + | --------- in this macro invocation + | + = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9 + | +LL | a.f() + | ^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(method); + | --------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0423]: expected value, found module `a` + --> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9 + | +LL | a.f + | ^- help: use the path separator to refer to an item: `::` +... +LL | let _ = create!(field); + | -------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/token-error-correct-2.rs b/tests/ui/resolve/token-error-correct-2.rs new file mode 100644 index 000000000..f7c7d908c --- /dev/null +++ b/tests/ui/resolve/token-error-correct-2.rs @@ -0,0 +1,7 @@ +// Test that we do some basic error correction in the tokeniser (and don't ICE). + +fn main() { + if foo { + //~^ ERROR: cannot find value `foo` + ) //~ ERROR: mismatched closing delimiter: `)` +} diff --git a/tests/ui/resolve/token-error-correct-2.stderr b/tests/ui/resolve/token-error-correct-2.stderr new file mode 100644 index 000000000..cca9f2dc8 --- /dev/null +++ b/tests/ui/resolve/token-error-correct-2.stderr @@ -0,0 +1,18 @@ +error: mismatched closing delimiter: `)` + --> $DIR/token-error-correct-2.rs:4:12 + | +LL | if foo { + | ^ unclosed delimiter +LL | +LL | ) + | ^ mismatched closing delimiter + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/token-error-correct-2.rs:4:8 + | +LL | if foo { + | ^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/token-error-correct-3.rs b/tests/ui/resolve/token-error-correct-3.rs new file mode 100644 index 000000000..52934085f --- /dev/null +++ b/tests/ui/resolve/token-error-correct-3.rs @@ -0,0 +1,25 @@ +// Test that we do some basic error correction in the tokeniser (and don't spew +// too many bogus errors). + +pub mod raw { + use std::{io, fs}; + use std::path::Path; + + pub fn ensure_dir_exists, F: FnOnce(&Path)>(path: P, + callback: F) + -> io::Result { + if !is_directory(path.as_ref()) { + //~^ ERROR cannot find function `is_directory` + callback(path.as_ref(); + //~^ ERROR expected one of + fs::create_dir_all(path.as_ref()).map(|()| true) + } else { + //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + Ok(false); + } + + panic!(); + } +} + +fn main() {} diff --git a/tests/ui/resolve/token-error-correct-3.stderr b/tests/ui/resolve/token-error-correct-3.stderr new file mode 100644 index 000000000..77c87c784 --- /dev/null +++ b/tests/ui/resolve/token-error-correct-3.stderr @@ -0,0 +1,25 @@ +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` + --> $DIR/token-error-correct-3.rs:13:21 + | +LL | callback(path.as_ref(); + | ^ ^ help: `)` may belong here + | | + | unclosed delimiter + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + --> $DIR/token-error-correct-3.rs:16:9 + | +LL | fs::create_dir_all(path.as_ref()).map(|()| true) + | - expected one of `.`, `;`, `?`, `}`, or an operator +LL | } else { + | ^ unexpected token + +error[E0425]: cannot find function `is_directory` in this scope + --> $DIR/token-error-correct-3.rs:11:13 + | +LL | if !is_directory(path.as_ref()) { + | ^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/token-error-correct-4.fixed b/tests/ui/resolve/token-error-correct-4.fixed new file mode 100644 index 000000000..064b9e74e --- /dev/null +++ b/tests/ui/resolve/token-error-correct-4.fixed @@ -0,0 +1,10 @@ +// run-rustfix +// Test that we do some basic error correction in the tokeniser and apply suggestions. + +fn setsuna(_: ()) {} + +fn kazusa() {} + +fn main() { + setsuna(kazusa()); //~ ERROR: expected one of +} //~ ERROR: expected expression diff --git a/tests/ui/resolve/token-error-correct-4.rs b/tests/ui/resolve/token-error-correct-4.rs new file mode 100644 index 000000000..5e31d71e7 --- /dev/null +++ b/tests/ui/resolve/token-error-correct-4.rs @@ -0,0 +1,10 @@ +// run-rustfix +// Test that we do some basic error correction in the tokeniser and apply suggestions. + +fn setsuna(_: ()) {} + +fn kazusa() {} + +fn main() { + setsuna(kazusa(); //~ ERROR: expected one of +} //~ ERROR: expected expression diff --git a/tests/ui/resolve/token-error-correct-4.stderr b/tests/ui/resolve/token-error-correct-4.stderr new file mode 100644 index 000000000..81e5a1336 --- /dev/null +++ b/tests/ui/resolve/token-error-correct-4.stderr @@ -0,0 +1,16 @@ +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` + --> $DIR/token-error-correct-4.rs:9:12 + | +LL | setsuna(kazusa(); + | ^ ^ help: `)` may belong here + | | + | unclosed delimiter + +error: expected expression, found `)` + --> $DIR/token-error-correct-4.rs:10:1 + | +LL | } + | ^ expected expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/resolve/token-error-correct.rs b/tests/ui/resolve/token-error-correct.rs new file mode 100644 index 000000000..4f74df0bf --- /dev/null +++ b/tests/ui/resolve/token-error-correct.rs @@ -0,0 +1,9 @@ +// Test that we do some basic error correction in the tokeniser. + +fn main() { + foo(bar(; + //~^ ERROR cannot find function `bar` in this scope +} +//~^ ERROR: mismatched closing delimiter: `}` + +fn foo(_: usize) {} diff --git a/tests/ui/resolve/token-error-correct.stderr b/tests/ui/resolve/token-error-correct.stderr new file mode 100644 index 000000000..ca0c4c18a --- /dev/null +++ b/tests/ui/resolve/token-error-correct.stderr @@ -0,0 +1,20 @@ +error: mismatched closing delimiter: `}` + --> $DIR/token-error-correct.rs:4:12 + | +LL | fn main() { + | - closing delimiter possibly meant for this +LL | foo(bar(; + | ^ unclosed delimiter +LL | +LL | } + | ^ mismatched closing delimiter + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/token-error-correct.rs:4:9 + | +LL | foo(bar(; + | ^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/tuple-struct-alias.rs b/tests/ui/resolve/tuple-struct-alias.rs new file mode 100644 index 000000000..298e7e479 --- /dev/null +++ b/tests/ui/resolve/tuple-struct-alias.rs @@ -0,0 +1,9 @@ +struct S(u8, u16); +type A = S; + +fn main() { + let s = A(0, 1); //~ ERROR expected function + match s { + A(..) => {} //~ ERROR expected tuple struct or tuple variant + } +} diff --git a/tests/ui/resolve/tuple-struct-alias.stderr b/tests/ui/resolve/tuple-struct-alias.stderr new file mode 100644 index 000000000..a739ea43e --- /dev/null +++ b/tests/ui/resolve/tuple-struct-alias.stderr @@ -0,0 +1,26 @@ +error[E0532]: expected tuple struct or tuple variant, found type alias `A` + --> $DIR/tuple-struct-alias.rs:7:9 + | +LL | struct S(u8, u16); + | ------------------ similarly named tuple struct `S` defined here +... +LL | A(..) => {} + | ^ help: a tuple struct with a similar name exists: `S` + | + = note: can't use a type alias as a constructor + +error[E0423]: expected function, tuple struct or tuple variant, found type alias `A` + --> $DIR/tuple-struct-alias.rs:5:13 + | +LL | struct S(u8, u16); + | ------------------ similarly named tuple struct `S` defined here +... +LL | let s = A(0, 1); + | ^ help: a tuple struct with a similar name exists: `S` + | + = note: can't use a type alias as a constructor + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs new file mode 100644 index 000000000..ecd3f5881 --- /dev/null +++ b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs @@ -0,0 +1,46 @@ +struct A { + config: String, +} + +impl A { + fn new(cofig: String) -> Self { + Self { config } //~ Error cannot find value `config` in this scope + } + + fn do_something(cofig: String) { + println!("{config}"); //~ Error cannot find value `config` in this scope + } + + fn self_is_available(self, cofig: String) { + println!("{config}"); //~ Error cannot find value `config` in this scope + } +} + +trait B { + const BAR: u32 = 3; + type Baz; + fn bar(&self); + fn baz(&self) {} + fn bah() {} +} + +impl B for Box { + type Baz = String; + fn bar(&self) { + // let baz = 3; + baz(); + //~^ ERROR cannot find function `baz` + bah; + //~^ ERROR cannot find value `bah` + BAR; + //~^ ERROR cannot find value `BAR` in this scope + let foo: Baz = "".to_string(); + //~^ ERROR cannot find type `Baz` in this scope + } +} + +fn ba() {} +const BARR: u32 = 3; +type Bar = String; + +fn main() {} diff --git a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr new file mode 100644 index 000000000..f32e0404e --- /dev/null +++ b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr @@ -0,0 +1,109 @@ +error[E0425]: cannot find value `config` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:7:16 + | +LL | Self { config } + | ^^^^^^ + | | + | a field by this name exists in `Self` + | help: a local variable with a similar name exists: `cofig` + +error[E0425]: cannot find value `config` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:11:20 + | +LL | println!("{config}"); + | ^^^^^^ + | | + | a field by this name exists in `Self` + | help: a local variable with a similar name exists: `cofig` + +error[E0425]: cannot find value `config` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:15:20 + | +LL | println!("{config}"); + | ^^^^^^ + | +help: you might have meant to use the available field + | +LL | println!("{self.config}"); + | ~~~~~~~~~~~ +help: a local variable with a similar name exists + | +LL | println!("{cofig}"); + | ~~~~~ + +error[E0425]: cannot find value `bah` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:33:9 + | +LL | bah; + | ^^^ +... +LL | fn ba() {} + | ------- similarly named function `ba` defined here + | +help: you might have meant to refer to the associated function + | +LL | Self::bah; + | ~~~~~~~~~ +help: a function with a similar name exists + | +LL | ba; + | ~~ + +error[E0425]: cannot find value `BAR` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:35:9 + | +LL | BAR; + | ^^^ +... +LL | const BARR: u32 = 3; + | -------------------- similarly named constant `BARR` defined here + | +help: you might have meant to use the associated `const` + | +LL | Self::BAR; + | ~~~~~~~~~ +help: a constant with a similar name exists + | +LL | BARR; + | ~~~~ + +error[E0412]: cannot find type `Baz` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:37:18 + | +LL | let foo: Baz = "".to_string(); + | ^^^ +... +LL | type Bar = String; + | ------------------ similarly named type alias `Bar` defined here + | +help: you might have meant to use the associated type + | +LL | let foo: Self::Baz = "".to_string(); + | ~~~~~~~~~ +help: a type alias with a similar name exists + | +LL | let foo: Bar = "".to_string(); + | ~~~ + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:31:9 + | +LL | baz(); + | ^^^ +... +LL | fn ba() {} + | ------- similarly named function `ba` defined here + | +help: you might have meant to call the method + | +LL | self.baz(); + | ~~~~~~~~ +help: a function with a similar name exists + | +LL | ba(); + | ~~ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs b/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs new file mode 100644 index 000000000..3ce17a14f --- /dev/null +++ b/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs @@ -0,0 +1,42 @@ +struct Struct; +//~^ NOTE function or associated item `fob` not found for this struct + +impl Struct { + fn foo() { } +} + +mod module { + fn foo() { } + + struct Struct; + + impl Struct { + fn foo() { } + } +} + +trait Trait { + fn foo(); +} + +fn main() { + Struct::fob(); + //~^ ERROR no function or associated item named `fob` found for struct `Struct` in the current scope + //~| NOTE function or associated item not found in `Struct` + + Struc::foo(); + //~^ ERROR failed to resolve: use of undeclared type `Struc` + //~| NOTE use of undeclared type `Struc` + + modul::foo(); + //~^ ERROR failed to resolve: use of undeclared crate or module `modul` + //~| NOTE use of undeclared crate or module `modul` + + module::Struc::foo(); + //~^ ERROR failed to resolve: could not find `Struc` in `module` + //~| NOTE could not find `Struc` in `module` + + Trai::foo(); + //~^ ERROR failed to resolve: use of undeclared type `Trai` + //~| NOTE use of undeclared type `Trai` +} diff --git a/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr b/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr new file mode 100644 index 000000000..89b69e140 --- /dev/null +++ b/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr @@ -0,0 +1,54 @@ +error[E0433]: failed to resolve: could not find `Struc` in `module` + --> $DIR/typo-suggestion-mistyped-in-path.rs:35:13 + | +LL | module::Struc::foo(); + | ^^^^^ + | | + | could not find `Struc` in `module` + | help: a struct with a similar name exists: `Struct` + +error[E0599]: no function or associated item named `fob` found for struct `Struct` in the current scope + --> $DIR/typo-suggestion-mistyped-in-path.rs:23:13 + | +LL | struct Struct; + | ------------- function or associated item `fob` not found for this struct +... +LL | Struct::fob(); + | ^^^ + | | + | function or associated item not found in `Struct` + | help: there is an associated function with a similar name: `foo` + +error[E0433]: failed to resolve: use of undeclared type `Struc` + --> $DIR/typo-suggestion-mistyped-in-path.rs:27:5 + | +LL | Struc::foo(); + | ^^^^^ + | | + | use of undeclared type `Struc` + | help: a struct with a similar name exists: `Struct` + +error[E0433]: failed to resolve: use of undeclared crate or module `modul` + --> $DIR/typo-suggestion-mistyped-in-path.rs:31:5 + | +LL | modul::foo(); + | ^^^^^ use of undeclared crate or module `modul` + | +help: there is a crate or module with a similar name + | +LL | module::foo(); + | ~~~~~~ + +error[E0433]: failed to resolve: use of undeclared type `Trai` + --> $DIR/typo-suggestion-mistyped-in-path.rs:39:5 + | +LL | Trai::foo(); + | ^^^^ + | | + | use of undeclared type `Trai` + | help: a trait with a similar name exists: `Trait` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/typo-suggestion-named-underscore.rs b/tests/ui/resolve/typo-suggestion-named-underscore.rs new file mode 100644 index 000000000..a2b05db03 --- /dev/null +++ b/tests/ui/resolve/typo-suggestion-named-underscore.rs @@ -0,0 +1,14 @@ +const _: () = (); + +fn main() { + a // Shouldn't suggest underscore + //~^ ERROR: cannot find value `a` in this scope +} + +trait Unknown {} + +#[allow(unused_imports)] +use Unknown as _; + +fn foo(x: T) {} // Shouldn't suggest underscore +//~^ ERROR: cannot find trait `A` in this scope diff --git a/tests/ui/resolve/typo-suggestion-named-underscore.stderr b/tests/ui/resolve/typo-suggestion-named-underscore.stderr new file mode 100644 index 000000000..65d1b084a --- /dev/null +++ b/tests/ui/resolve/typo-suggestion-named-underscore.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/typo-suggestion-named-underscore.rs:4:5 + | +LL | a // Shouldn't suggest underscore + | ^ not found in this scope + +error[E0405]: cannot find trait `A` in this scope + --> $DIR/typo-suggestion-named-underscore.rs:13:11 + | +LL | fn foo(x: T) {} // Shouldn't suggest underscore + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0405, E0425. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs b/tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs new file mode 100644 index 000000000..87f9ce097 --- /dev/null +++ b/tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.rs @@ -0,0 +1,9 @@ +fn f isize>(x: F) {} +//~^ ERROR cannot find trait `Nonexist` + +type Typedef = isize; + +fn g isize>(x: F) {} +//~^ ERROR expected trait, found type alias `Typedef` + +fn main() {} diff --git a/tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr new file mode 100644 index 000000000..8addc0303 --- /dev/null +++ b/tests/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr @@ -0,0 +1,21 @@ +error[E0405]: cannot find trait `Nonexist` in this scope + --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:1:8 + | +LL | fn f isize>(x: F) {} + | ^^^^^^^^ not found in this scope + +error[E0404]: expected trait, found type alias `Typedef` + --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:6:8 + | +LL | fn g isize>(x: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait Typedef = isize; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0404, E0405. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/unresolved_static_type_field.rs b/tests/ui/resolve/unresolved_static_type_field.rs new file mode 100644 index 000000000..494ad083f --- /dev/null +++ b/tests/ui/resolve/unresolved_static_type_field.rs @@ -0,0 +1,14 @@ +fn f(_: bool) {} + +struct Foo { + cx: bool, +} + +impl Foo { + fn bar() { + f(cx); + //~^ ERROR cannot find value `cx` in this scope + } +} + +fn main() {} diff --git a/tests/ui/resolve/unresolved_static_type_field.stderr b/tests/ui/resolve/unresolved_static_type_field.stderr new file mode 100644 index 000000000..06926b53d --- /dev/null +++ b/tests/ui/resolve/unresolved_static_type_field.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `cx` in this scope + --> $DIR/unresolved_static_type_field.rs:9:11 + | +LL | f(cx); + | ^^ a field by this name exists in `Self` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs new file mode 100644 index 000000000..eccb315fe --- /dev/null +++ b/tests/ui/resolve/use-self-in-inner-fn.rs @@ -0,0 +1,14 @@ +struct A; + +impl A { +//~^ NOTE `Self` type implicitly declared here, by this `impl` + fn banana(&mut self) { + fn peach(this: &Self) { + //~^ ERROR can't use generic parameters from outer function + //~| NOTE use of generic parameter from outer function + //~| NOTE use a type here instead + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr new file mode 100644 index 000000000..966093499 --- /dev/null +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -0,0 +1,15 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/use-self-in-inner-fn.rs:6:25 + | +LL | impl A { + | ---- `Self` type implicitly declared here, by this `impl` +... +LL | fn peach(this: &Self) { + | ^^^^ + | | + | use of generic parameter from outer function + | use a type here instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/use_suggestion.rs b/tests/ui/resolve/use_suggestion.rs new file mode 100644 index 000000000..8c9bc6d76 --- /dev/null +++ b/tests/ui/resolve/use_suggestion.rs @@ -0,0 +1,7 @@ +fn main() { + let x1 = HashMap::new(); //~ ERROR failed to resolve + let x2 = GooMap::new(); //~ ERROR failed to resolve + + let y1: HashMap; //~ ERROR cannot find type + let y2: GooMap; //~ ERROR cannot find type +} diff --git a/tests/ui/resolve/use_suggestion.stderr b/tests/ui/resolve/use_suggestion.stderr new file mode 100644 index 000000000..54ad85383 --- /dev/null +++ b/tests/ui/resolve/use_suggestion.stderr @@ -0,0 +1,38 @@ +error[E0433]: failed to resolve: use of undeclared type `HashMap` + --> $DIR/use_suggestion.rs:2:14 + | +LL | let x1 = HashMap::new(); + | ^^^^^^^ use of undeclared type `HashMap` + | +help: consider importing this struct + | +LL | use std::collections::HashMap; + | + +error[E0412]: cannot find type `HashMap` in this scope + --> $DIR/use_suggestion.rs:5:13 + | +LL | let y1: HashMap; + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::collections::HashMap; + | + +error[E0412]: cannot find type `GooMap` in this scope + --> $DIR/use_suggestion.rs:6:13 + | +LL | let y2: GooMap; + | ^^^^^^ not found in this scope + +error[E0433]: failed to resolve: use of undeclared type `GooMap` + --> $DIR/use_suggestion.rs:3:14 + | +LL | let x2 = GooMap::new(); + | ^^^^^^ use of undeclared type `GooMap` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0412, E0433. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/use_suggestion_placement.fixed b/tests/ui/resolve/use_suggestion_placement.fixed new file mode 100644 index 000000000..d1686f7fd --- /dev/null +++ b/tests/ui/resolve/use_suggestion_placement.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +use m::A; + +use std::collections::HashMap; + +macro_rules! y { + () => {} +} + +mod m { + pub const A: i32 = 0; +} + +mod foo { + use std::path::Path; + +#[derive(Debug)] + pub struct Foo; + + // test whether the use suggestion isn't + // placed into the expansion of `#[derive(Debug)] + type Bar = Path; //~ ERROR cannot find +} + +fn main() { + y!(); + let _ = A; //~ ERROR cannot find + foo(); +} + +fn foo() { + type Dict = HashMap; //~ ERROR cannot find +} diff --git a/tests/ui/resolve/use_suggestion_placement.rs b/tests/ui/resolve/use_suggestion_placement.rs new file mode 100644 index 000000000..5be91f270 --- /dev/null +++ b/tests/ui/resolve/use_suggestion_placement.rs @@ -0,0 +1,29 @@ +// run-rustfix +#![allow(dead_code)] + +macro_rules! y { + () => {} +} + +mod m { + pub const A: i32 = 0; +} + +mod foo { + #[derive(Debug)] + pub struct Foo; + + // test whether the use suggestion isn't + // placed into the expansion of `#[derive(Debug)] + type Bar = Path; //~ ERROR cannot find +} + +fn main() { + y!(); + let _ = A; //~ ERROR cannot find + foo(); +} + +fn foo() { + type Dict = HashMap; //~ ERROR cannot find +} diff --git a/tests/ui/resolve/use_suggestion_placement.stderr b/tests/ui/resolve/use_suggestion_placement.stderr new file mode 100644 index 000000000..0aadd82f6 --- /dev/null +++ b/tests/ui/resolve/use_suggestion_placement.stderr @@ -0,0 +1,37 @@ +error[E0412]: cannot find type `Path` in this scope + --> $DIR/use_suggestion_placement.rs:18:16 + | +LL | type Bar = Path; + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::path::Path; + | + +error[E0425]: cannot find value `A` in this scope + --> $DIR/use_suggestion_placement.rs:23:13 + | +LL | let _ = A; + | ^ not found in this scope + | +help: consider importing this constant + | +LL | use m::A; + | + +error[E0412]: cannot find type `HashMap` in this scope + --> $DIR/use_suggestion_placement.rs:28:23 + | +LL | type Dict = HashMap; + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::collections::HashMap; + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/resolve/visibility-indeterminate.rs b/tests/ui/resolve/visibility-indeterminate.rs new file mode 100644 index 000000000..0e1142db3 --- /dev/null +++ b/tests/ui/resolve/visibility-indeterminate.rs @@ -0,0 +1,7 @@ +// edition:2018 + +foo!(); //~ ERROR cannot find macro `foo` in this scope + +pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility + +fn main() {} diff --git a/tests/ui/resolve/visibility-indeterminate.stderr b/tests/ui/resolve/visibility-indeterminate.stderr new file mode 100644 index 000000000..84d82ce85 --- /dev/null +++ b/tests/ui/resolve/visibility-indeterminate.stderr @@ -0,0 +1,15 @@ +error[E0578]: cannot determine resolution for the visibility + --> $DIR/visibility-indeterminate.rs:5:8 + | +LL | pub(in ::bar) struct Baz {} + | ^^^^^ + +error: cannot find macro `foo` in this scope + --> $DIR/visibility-indeterminate.rs:3:1 + | +LL | foo!(); + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0578`. diff --git a/tests/ui/resource-assign-is-not-copy.rs b/tests/ui/resource-assign-is-not-copy.rs new file mode 100644 index 000000000..c1de139a9 --- /dev/null +++ b/tests/ui/resource-assign-is-not-copy.rs @@ -0,0 +1,33 @@ +// run-pass + +#![allow(non_camel_case_types)] +use std::cell::Cell; + +#[derive(Debug)] +struct r<'a> { + i: &'a Cell, +} + +impl<'a> Drop for r<'a> { + fn drop(&mut self) { + self.i.set(self.i.get() + 1); + } +} + +fn r(i: &Cell) -> r { + r { + i: i + } +} + +pub fn main() { + let i = &Cell::new(0); + // Even though these look like copies, they are guaranteed not to be + { + let a = r(i); + let b = (a, 10); + let (c, _d) = b; + println!("{:?}", c); + } + assert_eq!(i.get(), 1); +} diff --git a/tests/ui/resource-destruct.rs b/tests/ui/resource-destruct.rs new file mode 100644 index 000000000..c4756a21a --- /dev/null +++ b/tests/ui/resource-destruct.rs @@ -0,0 +1,31 @@ +// run-pass + +#![allow(non_camel_case_types)] +use std::cell::Cell; + +struct shrinky_pointer<'a> { + i: &'a Cell, +} + +impl<'a> Drop for shrinky_pointer<'a> { + fn drop(&mut self) { + println!("Hello!"); self.i.set(self.i.get() - 1); + } +} + +impl<'a> shrinky_pointer<'a> { + pub fn look_at(&self) -> isize { return self.i.get(); } +} + +fn shrinky_pointer(i: &Cell) -> shrinky_pointer { + shrinky_pointer { + i: i + } +} + +pub fn main() { + let my_total = &Cell::new(10); + { let pt = shrinky_pointer(my_total); assert_eq!(pt.look_at(), 10); } + println!("my_total = {}", my_total.get()); + assert_eq!(my_total.get(), 9); +} diff --git a/tests/ui/ret-bang.rs b/tests/ui/ret-bang.rs new file mode 100644 index 000000000..6618992e0 --- /dev/null +++ b/tests/ui/ret-bang.rs @@ -0,0 +1,13 @@ +// run-pass + +fn my_err(s: String) -> ! { println!("{}", s); panic!(); } + +fn okay(i: usize) -> isize { + if i == 3 { + my_err("I don't like three".to_string()); + } else { + return 42; + } +} + +pub fn main() { okay(4); } diff --git a/tests/ui/ret-non-nil.rs b/tests/ui/ret-non-nil.rs new file mode 100644 index 000000000..86c02bf38 --- /dev/null +++ b/tests/ui/ret-non-nil.rs @@ -0,0 +1,7 @@ +// error-pattern: `return;` in a function whose return type is not `()` + +fn f() { return; } + +fn g() -> isize { return; } + +fn main() { f(); g(); } diff --git a/tests/ui/ret-non-nil.stderr b/tests/ui/ret-non-nil.stderr new file mode 100644 index 000000000..2029c6d9d --- /dev/null +++ b/tests/ui/ret-non-nil.stderr @@ -0,0 +1,11 @@ +error[E0069]: `return;` in a function whose return type is not `()` + --> $DIR/ret-non-nil.rs:5:19 + | +LL | fn g() -> isize { return; } + | ----- ^^^^^^ return type is not `()` + | | + | expected `isize` because of this return type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0069`. diff --git a/tests/ui/return-disjoint-regions.rs b/tests/ui/return-disjoint-regions.rs new file mode 100644 index 000000000..d0feb3b65 --- /dev/null +++ b/tests/ui/return-disjoint-regions.rs @@ -0,0 +1,7 @@ +// See https://github.com/rust-lang/rust/pull/67911#issuecomment-576023915 +fn f<'a, 'b>(x: i32) -> (&'a i32, &'b i32) { + let y = &x; + (y, y) //~ ERROR cannot return +} + +fn main() {} diff --git a/tests/ui/return-disjoint-regions.stderr b/tests/ui/return-disjoint-regions.stderr new file mode 100644 index 000000000..ed1592988 --- /dev/null +++ b/tests/ui/return-disjoint-regions.stderr @@ -0,0 +1,11 @@ +error[E0515]: cannot return value referencing function parameter `x` + --> $DIR/return-disjoint-regions.rs:4:5 + | +LL | let y = &x; + | -- `x` is borrowed here +LL | (y, y) + | ^^^^^^ returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/return-nil.rs b/tests/ui/return-nil.rs new file mode 100644 index 000000000..fd5203ff0 --- /dev/null +++ b/tests/ui/return-nil.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f() { let x: () = (); return x; } + +pub fn main() { let _x = f(); } diff --git a/tests/ui/return/issue-64620.rs b/tests/ui/return/issue-64620.rs new file mode 100644 index 000000000..a62e5bf8d --- /dev/null +++ b/tests/ui/return/issue-64620.rs @@ -0,0 +1,5 @@ +enum Bug { + V1 = return [0][0] //~ERROR return statement outside of function body +} + +fn main() {} diff --git a/tests/ui/return/issue-64620.stderr b/tests/ui/return/issue-64620.stderr new file mode 100644 index 000000000..f40ac4de3 --- /dev/null +++ b/tests/ui/return/issue-64620.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-64620.rs:2:10 + | +LL | V1 = return [0][0] + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/return/issue-82612-return-mutable-reference.rs b/tests/ui/return/issue-82612-return-mutable-reference.rs new file mode 100644 index 000000000..db0d08ddb --- /dev/null +++ b/tests/ui/return/issue-82612-return-mutable-reference.rs @@ -0,0 +1,24 @@ +// Regression test for #82612. + +use std::marker::PhantomData; + +pub trait SparseSetIndex { + fn sparse_set_index(&self) -> usize; +} +pub struct SparseArray { + values: Vec>, + marker: PhantomData, +} + +impl SparseArray { + pub fn get_or_insert_with(&mut self, index: I, func: impl FnOnce() -> V) -> &mut V { + let index = index.sparse_set_index(); + if index < self.values.len() { + let value = unsafe { self.values.get_unchecked_mut(index) }; + value.get_or_insert_with(func) //~ ERROR mismatched types + } + unsafe { self.values.get_unchecked_mut(index).as_mut().unwrap() } + } +} + +fn main() {} diff --git a/tests/ui/return/issue-82612-return-mutable-reference.stderr b/tests/ui/return/issue-82612-return-mutable-reference.stderr new file mode 100644 index 000000000..eb2322d51 --- /dev/null +++ b/tests/ui/return/issue-82612-return-mutable-reference.stderr @@ -0,0 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/issue-82612-return-mutable-reference.rs:18:13 + | +LL | / if index < self.values.len() { +LL | | let value = unsafe { self.values.get_unchecked_mut(index) }; +LL | | value.get_or_insert_with(func) + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&mut V` +LL | | } + | |_________- expected this to be `()` + | + = note: expected unit type `()` + found mutable reference `&mut V` +help: consider using a semicolon here + | +LL | value.get_or_insert_with(func); + | + +help: consider using a semicolon here + | +LL | }; + | + +help: you might have meant to return this value + | +LL | return value.get_or_insert_with(func); + | ++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/issue-86188-return-not-in-fn-body.rs b/tests/ui/return/issue-86188-return-not-in-fn-body.rs new file mode 100644 index 000000000..4f076fa06 --- /dev/null +++ b/tests/ui/return/issue-86188-return-not-in-fn-body.rs @@ -0,0 +1,41 @@ +// Due to a compiler bug, if a return occurs outside of a function body +// (e.g. in an AnonConst body), the return value expression would not be +// type-checked, leading to an ICE. This test checks that the ICE no +// longer happens, and that an appropriate error message is issued that +// also explains why the return is considered "outside of a function body" +// if it seems to be inside one, as in the main function below. + +const C: [(); 42] = { + [(); return || { + //~^ ERROR: return statement outside of function body [E0572] + let tx; + }] +}; + +struct S {} +trait Tr { + fn foo(); + fn bar() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} +impl Tr for S { + fn foo() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} + +fn main() { +//~^ NOTE: ...not the enclosing function body + [(); return || { + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + let tx; + }]; +} diff --git a/tests/ui/return/issue-86188-return-not-in-fn-body.stderr b/tests/ui/return/issue-86188-return-not-in-fn-body.stderr new file mode 100644 index 000000000..4f938670e --- /dev/null +++ b/tests/ui/return/issue-86188-return-not-in-fn-body.stderr @@ -0,0 +1,52 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:9:10 + | +LL | [(); return || { + | __________^ +LL | | +LL | | let tx; +LL | | }] + | |_____^ + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:20:14 + | +LL | / fn bar() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:28:14 + | +LL | / fn foo() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:36:10 + | +LL | / fn main() { +LL | | +LL | | [(); return || { + | | __________^ +LL | || +LL | || +LL | || let tx; +LL | || }]; + | ||_____^ the return is part of this body... +LL | | } + | |__- ...not the enclosing function body + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/return/return-from-diverging.rs b/tests/ui/return/return-from-diverging.rs new file mode 100644 index 000000000..2ee48e7bc --- /dev/null +++ b/tests/ui/return/return-from-diverging.rs @@ -0,0 +1,8 @@ +// Test that return another type in place of ! raises a type mismatch. + +fn fail() -> ! { + return "wow"; //~ ERROR mismatched types +} + +fn main() { +} diff --git a/tests/ui/return/return-from-diverging.stderr b/tests/ui/return/return-from-diverging.stderr new file mode 100644 index 000000000..0c1fb4d9c --- /dev/null +++ b/tests/ui/return/return-from-diverging.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/return-from-diverging.rs:4:12 + | +LL | fn fail() -> ! { + | - expected `!` because of return type +LL | return "wow"; + | ^^^^^ expected `!`, found `&str` + | + = note: expected type `!` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-impl-trait-bad.rs b/tests/ui/return/return-impl-trait-bad.rs new file mode 100644 index 000000000..e3f6ddb9a --- /dev/null +++ b/tests/ui/return/return-impl-trait-bad.rs @@ -0,0 +1,31 @@ +trait Trait {} +impl Trait for () {} + +fn bad_echo(_t: T) -> T { + "this should not suggest impl Trait" //~ ERROR mismatched types +} + +fn bad_echo_2(_t: T) -> T { + "this will not suggest it, because that would probably be wrong" //~ ERROR mismatched types +} + +fn other_bounds_bad() -> T +where + T: Send, + Option: Send, +{ + "don't suggest this, because Option places additional constraints" //~ ERROR mismatched types +} + +// FIXME: implement this check +trait GenericTrait {} + +fn used_in_trait() -> T +where + T: Send, + (): GenericTrait, +{ + "don't suggest this, because the generic param is used in the bound." //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/return/return-impl-trait-bad.stderr b/tests/ui/return/return-impl-trait-bad.stderr new file mode 100644 index 000000000..237b85ee6 --- /dev/null +++ b/tests/ui/return/return-impl-trait-bad.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/return-impl-trait-bad.rs:5:5 + | +LL | fn bad_echo(_t: T) -> T { + | - - expected `T` because of return type + | | + | this type parameter +LL | "this should not suggest impl Trait" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` + | + = note: expected type parameter `T` + found reference `&'static str` + +error[E0308]: mismatched types + --> $DIR/return-impl-trait-bad.rs:9:5 + | +LL | fn bad_echo_2(_t: T) -> T { + | - - expected `T` because of return type + | | + | this type parameter +LL | "this will not suggest it, because that would probably be wrong" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` + | + = note: expected type parameter `T` + found reference `&'static str` + +error[E0308]: mismatched types + --> $DIR/return-impl-trait-bad.rs:17:5 + | +LL | fn other_bounds_bad() -> T + | - - expected `T` because of return type + | | + | this type parameter +... +LL | "don't suggest this, because Option places additional constraints" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` + | + = note: expected type parameter `T` + found reference `&'static str` + +error[E0308]: mismatched types + --> $DIR/return-impl-trait-bad.rs:28:5 + | +LL | fn used_in_trait() -> T + | - - + | | | + | | expected `T` because of return type + | | help: consider using an impl return type: `impl Send` + | this type parameter +... +LL | "don't suggest this, because the generic param is used in the bound." + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found `&str` + | + = note: expected type parameter `T` + found reference `&'static str` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-impl-trait.fixed b/tests/ui/return/return-impl-trait.fixed new file mode 100644 index 000000000..ff2b02f73 --- /dev/null +++ b/tests/ui/return/return-impl-trait.fixed @@ -0,0 +1,30 @@ +// run-rustfix + +trait Trait {} +impl Trait for () {} + +// this works +fn foo() -> impl Trait { + () +} + +fn bar() -> impl Trait + std::marker::Sync + Send +where + T: Send, +{ + () //~ ERROR mismatched types +} + +fn other_bounds() -> impl Trait +where + T: Trait, + Vec: Clone, +{ + () //~ ERROR mismatched types +} + +fn main() { + foo(); + bar::<()>(); + other_bounds::<()>(); +} diff --git a/tests/ui/return/return-impl-trait.rs b/tests/ui/return/return-impl-trait.rs new file mode 100644 index 000000000..e905d712f --- /dev/null +++ b/tests/ui/return/return-impl-trait.rs @@ -0,0 +1,30 @@ +// run-rustfix + +trait Trait {} +impl Trait for () {} + +// this works +fn foo() -> impl Trait { + () +} + +fn bar() -> T +where + T: Send, +{ + () //~ ERROR mismatched types +} + +fn other_bounds() -> T +where + T: Trait, + Vec: Clone, +{ + () //~ ERROR mismatched types +} + +fn main() { + foo(); + bar::<()>(); + other_bounds::<()>(); +} diff --git a/tests/ui/return/return-impl-trait.stderr b/tests/ui/return/return-impl-trait.stderr new file mode 100644 index 000000000..43d40972f --- /dev/null +++ b/tests/ui/return/return-impl-trait.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/return-impl-trait.rs:15:5 + | +LL | fn bar() -> T + | - - + | | | + | | expected `T` because of return type + | this type parameter help: consider using an impl return type: `impl Trait + std::marker::Sync + Send` +... +LL | () + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/return-impl-trait.rs:23:5 + | +LL | fn other_bounds() -> T + | - - + | | | + | | expected `T` because of return type + | | help: consider using an impl return type: `impl Trait` + | this type parameter +... +LL | () + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-match-array-const.rs b/tests/ui/return/return-match-array-const.rs new file mode 100644 index 000000000..b619a4d57 --- /dev/null +++ b/tests/ui/return/return-match-array-const.rs @@ -0,0 +1,19 @@ +fn main() { +//~^ NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body +//~| NOTE: not the enclosing function body + [(); return match 0 { n => n }]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + + [(); return match 0 { 0 => 0 }]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + + [(); return match () { 'a' => 0, _ => 0 }]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + //~| ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found `char` + //~| NOTE: this expression has type `()` +} diff --git a/tests/ui/return/return-match-array-const.stderr b/tests/ui/return/return-match-array-const.stderr new file mode 100644 index 000000000..85a733adf --- /dev/null +++ b/tests/ui/return/return-match-array-const.stderr @@ -0,0 +1,56 @@ +error[E0572]: return statement outside of function body + --> $DIR/return-match-array-const.rs:5:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +LL | | [(); return match 0 { n => n }]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/return-match-array-const.rs:9:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return match 0 { 0 => 0 }]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/return-match-array-const.rs:13:10 + | +LL | / fn main() { +LL | | +LL | | +LL | | +... | +LL | | [(); return match () { 'a' => 0, _ => 0 }]; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the return is part of this body... +... | +LL | | +LL | | } + | |_- ...not the enclosing function body + +error[E0308]: mismatched types + --> $DIR/return-match-array-const.rs:13:28 + | +LL | [(); return match () { 'a' => 0, _ => 0 }]; + | -- ^^^ expected `()`, found `char` + | | + | this expression has type `()` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0572. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-type.rs b/tests/ui/return/return-type.rs new file mode 100644 index 000000000..9f951ee0d --- /dev/null +++ b/tests/ui/return/return-type.rs @@ -0,0 +1,14 @@ +struct S { + t: T, +} + +fn foo(x: T) -> S { + S { t: x } +} + +fn bar() { + foo(4 as usize) + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/return/return-type.stderr b/tests/ui/return/return-type.stderr new file mode 100644 index 000000000..5af136e60 --- /dev/null +++ b/tests/ui/return/return-type.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/return-type.rs:10:5 + | +LL | foo(4 as usize) + | ^^^^^^^^^^^^^^^ expected `()`, found struct `S` + | + = note: expected unit type `()` + found struct `S` +help: consider using a semicolon here + | +LL | foo(4 as usize); + | + +help: try adding a return type + | +LL | fn bar() -> S { + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/return/return-unit-from-diverging.rs b/tests/ui/return/return-unit-from-diverging.rs new file mode 100644 index 000000000..48417599b --- /dev/null +++ b/tests/ui/return/return-unit-from-diverging.rs @@ -0,0 +1,9 @@ +// Test that we get the usual error that we'd get for any other return type and not something about +// diverging functions not being able to return. + +fn fail() -> ! { + return; //~ ERROR in a function whose return type is not +} + +fn main() { +} diff --git a/tests/ui/return/return-unit-from-diverging.stderr b/tests/ui/return/return-unit-from-diverging.stderr new file mode 100644 index 000000000..befc57563 --- /dev/null +++ b/tests/ui/return/return-unit-from-diverging.stderr @@ -0,0 +1,11 @@ +error[E0069]: `return;` in a function whose return type is not `()` + --> $DIR/return-unit-from-diverging.rs:5:5 + | +LL | fn fail() -> ! { + | - expected `!` because of this return type +LL | return; + | ^^^^^^ return type is not `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0069`. diff --git a/tests/ui/return/tail-expr-as-potential-return.rs b/tests/ui/return/tail-expr-as-potential-return.rs new file mode 100644 index 000000000..f46e088b8 --- /dev/null +++ b/tests/ui/return/tail-expr-as-potential-return.rs @@ -0,0 +1,47 @@ +// > Suggest `return`ing tail expressions that match return type +// > +// > Some newcomers are confused by the behavior of tail expressions, +// > interpreting that "leaving out the `;` makes it the return value". +// > To help them go in the right direction, suggest using `return` instead +// > when applicable. +// (original commit description for this test) +// +// This test was amended to also serve as a regression test for #92308, where +// this suggestion would not trigger with async functions. +// +// edition:2018 + +fn main() { +} + +fn foo(x: bool) -> Result { + if x { + Err(42) //~ ERROR mismatched types + //| HELP you might have meant to return this value + } + Ok(42.0) +} + +async fn bar(x: bool) -> Result { + if x { + Err(42) //~ ERROR mismatched types + //| HELP you might have meant to return this value + } + Ok(42.0) +} + +trait Identity { + type Out; +} + +impl Identity for T { + type Out = T; +} + +async fn foo2() -> i32 { + if true { + 1i32 //~ ERROR mismatched types + //| HELP you might have meant to return this value + } + 0 +} diff --git a/tests/ui/return/tail-expr-as-potential-return.stderr b/tests/ui/return/tail-expr-as-potential-return.stderr new file mode 100644 index 000000000..9183b4599 --- /dev/null +++ b/tests/ui/return/tail-expr-as-potential-return.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/tail-expr-as-potential-return.rs:27:9 + | +LL | / if x { +LL | | Err(42) + | | ^^^^^^^ expected `()`, found enum `Result` +LL | | //| HELP you might have meant to return this value +LL | | } + | |_____- expected this to be `()` + | + = note: expected unit type `()` + found enum `Result<_, {integer}>` +help: you might have meant to return this value + | +LL | return Err(42); + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/tail-expr-as-potential-return.rs:43:9 + | +LL | / if true { +LL | | 1i32 + | | ^^^^ expected `()`, found `i32` +LL | | //| HELP you might have meant to return this value +LL | | } + | |_____- expected this to be `()` + | +help: you might have meant to return this value + | +LL | return 1i32; + | ++++++ + + +error[E0308]: mismatched types + --> $DIR/tail-expr-as-potential-return.rs:19:9 + | +LL | / if x { +LL | | Err(42) + | | ^^^^^^^ expected `()`, found enum `Result` +LL | | //| HELP you might have meant to return this value +LL | | } + | |_____- expected this to be `()` + | + = note: expected unit type `()` + found enum `Result<_, {integer}>` +help: you might have meant to return this value + | +LL | return Err(42); + | ++++++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/tests/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs new file mode 100644 index 000000000..1e086160f --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs @@ -0,0 +1,19 @@ +// Adaptation of existing ui test (from way back in +// rust-lang/rust#2329), that starts passing with this feature in +// place. + +// run-pass + +use std::sync::mpsc::channel; + +fn main() { + let (tx, rx) = channel(); + let x = Some(rx); + tx.send(false).unwrap(); + tx.send(false).unwrap(); + match x { + Some(z) if z.recv().unwrap() => { panic!() }, + Some(z) => { assert!(!z.recv().unwrap()); }, + None => panic!() + } +} diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs b/tests/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs new file mode 100644 index 000000000..3161d6fbb --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/former-E0008-now-pass.rs @@ -0,0 +1,11 @@ +// This test used to emit E0008 but now passed since `bind_by_move_pattern_guards` +// have been stabilized. + +// check-pass + +fn main() { + match Some("hi".to_string()) { + Some(s) if s.len() == 0 => {}, + _ => {}, + } +} diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs new file mode 100644 index 000000000..b716fc870 --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs @@ -0,0 +1,43 @@ +// run-pass + +struct A { a: Box } + +impl A { + fn get(&self) -> i32 { *self.a } +} + +fn foo(n: i32) -> i32 { + let x = A { a: Box::new(n) }; + let y = match x { + A { a: v } if *v == 42 => v, + _ => Box::new(0), + }; + *y +} + +fn bar(n: i32) -> i32 { + let x = A { a: Box::new(n) }; + let y = match x { + A { a: v } if x.get() == 42 => v, + _ => Box::new(0), + }; + *y +} + +fn baz(n: i32) -> i32 { + let x = A { a: Box::new(n) }; + let y = match x { + A { a: v } if *v.clone() == 42 => v, + _ => Box::new(0), + }; + *y +} + +fn main() { + assert_eq!(foo(107), 0); + assert_eq!(foo(42), 42); + assert_eq!(bar(107), 0); + assert_eq!(bar(42), 42); + assert_eq!(baz(107), 0); + assert_eq!(baz(42), 42); +} diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs new file mode 100644 index 000000000..6f0d2b045 --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs @@ -0,0 +1,24 @@ +#![feature(if_let_guard)] + +enum VecWrapper { A(Vec) } + +fn if_guard(x: VecWrapper) -> usize { + match x { + VecWrapper::A(v) if { drop(v); false } => 1, + //~^ ERROR cannot move out of `v` in pattern guard + VecWrapper::A(v) => v.len() + } +} + +fn if_let_guard(x: VecWrapper) -> usize { + match x { + VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1, + //~^ ERROR cannot move out of `v` in pattern guard + VecWrapper::A(v) => v.len() + } +} + +fn main() { + if_guard(VecWrapper::A(vec![107])); + if_let_guard(VecWrapper::A(vec![107])); +} diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr new file mode 100644 index 000000000..a749361bf --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr @@ -0,0 +1,19 @@ +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-across-arms.rs:7:36 + | +LL | VecWrapper::A(v) if { drop(v); false } => 1, + | ^ move occurs because `v` has type `Vec`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-across-arms.rs:15:51 + | +LL | VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1, + | ^ move occurs because `v` has type `Vec`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs new file mode 100644 index 000000000..827335f6a --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs @@ -0,0 +1,26 @@ +#![feature(if_let_guard)] + +struct A { a: Box } + +fn if_guard(n: i32) { + let x = A { a: Box::new(n) }; + let _y = match x { + A { a: v } if { drop(v); true } => v, + //~^ ERROR cannot move out of `v` in pattern guard + _ => Box::new(0), + }; +} + +fn if_let_guard(n: i32) { + let x = A { a: Box::new(n) }; + let _y = match x { + A { a: v } if let Some(()) = { drop(v); Some(()) } => v, + //~^ ERROR cannot move out of `v` in pattern guard + _ => Box::new(0), + }; +} + +fn main() { + if_guard(107); + if_let_guard(107); +} diff --git a/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr new file mode 100644 index 000000000..9285492b2 --- /dev/null +++ b/tests/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr @@ -0,0 +1,19 @@ +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30 + | +LL | A { a: v } if { drop(v); true } => v, + | ^ move occurs because `v` has type `Box`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45 + | +LL | A { a: v } if let Some(()) = { drop(v); Some(()) } => v, + | ^ move occurs because `v` has type `Box`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs new file mode 100644 index 000000000..1914e1554 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs @@ -0,0 +1,26 @@ +// Test explores how `#[structral_match]` behaves in tandem with +// `*const` and `*mut` pointers. + +// run-pass + +#![warn(pointer_structural_match)] + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive +// (which doesn't matter here because `<*const T>::eq` won't recur on `T`). +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapEmbedded(*const NoDerive); + +const WRAP_UNSAFE_EMBEDDED: WrapEmbedded = WrapEmbedded(std::ptr::null()); + +fn main() { + match WRAP_UNSAFE_EMBEDDED { + WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); } + _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs new file mode 100644 index 000000000..e713b003b --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs @@ -0,0 +1,26 @@ +// Test explores how `#[structral_match]` behaves in tandem with +// `*const` and `*mut` pointers. + +// run-pass + +#![warn(pointer_structural_match)] + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive +// (which doesn't matter here because `<*const T>::eq` won't recur on `T`). +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapParam(*const X); + +const WRAP_UNSAFE_PARAM: WrapParam = WrapParam(std::ptr::null()); + +fn main() { + match WRAP_UNSAFE_PARAM { + WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); } + _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs new file mode 100644 index 000000000..04da14c54 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs @@ -0,0 +1,26 @@ +// Test explores how `#[structral_match]` behaves in tandem with +// `*const` and `*mut` pointers. + +// run-pass + +#![warn(pointer_structural_match)] + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive +// (which doesn't matter here because `<*const T>::eq` won't recur on `T`). +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapEmbedded(*const NoDerive); + +const WRAP_UNSAFE_EMBEDDED: & &WrapEmbedded = & &WrapEmbedded(std::ptr::null()); + +fn main() { + match WRAP_UNSAFE_EMBEDDED { + WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); } + _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs new file mode 100644 index 000000000..8313c25e7 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs @@ -0,0 +1,26 @@ +// Test explores how `#[structral_match]` behaves in tandem with +// `*const` and `*mut` pointers. + +// run-pass + +#![warn(pointer_structural_match)] + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive +// (which doesn't matter here because `<*const T>::eq` won't recur on `T`). +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapParam(*const X); + +const WRAP_UNSAFE_PARAM: & &WrapParam = & &WrapParam(std::ptr::null()); + +fn main() { + match WRAP_UNSAFE_PARAM { + WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); } + _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs new file mode 100644 index 000000000..dca8aaef1 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs @@ -0,0 +1,59 @@ +// rust-lang/rust#62614: we want to allow matching on constants of types that +// have non-structural-match variants, *if* the constant itself does not use +// any such variant. + +// NOTE: for now, deliberately leaving the lint `indirect_structural_match` set +// to its default, so that we will not issue a diangostic even if +// rust-lang/rust#62614 remains an open issue. + +// run-pass + +struct Sum(u32, u32); + +impl PartialEq for Sum { + fn eq(&self, other: &Self) -> bool { self.0 + self.1 == other.0 + other.1 } +} + +impl Eq for Sum { } + +#[derive(PartialEq, Eq)] +enum Eek { + TheConst, + UnusedByTheConst(Sum) +} + +const THE_CONST: Eek = Eek::TheConst; +const SUM_THREE: Eek = Eek::UnusedByTheConst(Sum(3,0)); + +const EEK_ZERO: &[Eek] = &[]; +const EEK_ONE: &[Eek] = &[THE_CONST]; + +pub fn main() { + match Eek::UnusedByTheConst(Sum(1,2)) { + ref sum if sum == &SUM_THREE => { println!("Hello 0"); } + _ => { println!("Gbye"); } + } + + match Eek::TheConst { + THE_CONST => { println!("Hello 1"); } + _ => { println!("Gbye"); } + } + + + match & &Eek::TheConst { + & & THE_CONST => { println!("Hello 2"); } + _ => { println!("Gbye"); } + } + + match & & &[][..] { + & & EEK_ZERO => { println!("Hello 3"); } + & & EEK_ONE => { println!("Gbye"); } + _ => { println!("Gbye"); } + } + + match & & &[Eek::TheConst][..] { + & & EEK_ZERO => { println!("Gby"); } + & & EEK_ONE => { println!("Hello 4"); } + _ => { println!("Gbye"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs new file mode 100644 index 000000000..7623839fd --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs @@ -0,0 +1,26 @@ +// This is part of a set of tests exploring the different ways a +// structural-match ADT might try to hold a +// non-structural-match in hidden manner that lets matches +// through that we had intended to reject. +// +// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339 + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapInline(NoDerive); + +const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0)); + +fn main() { + match WRAP_DIRECT_INLINE { + WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); } + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => { println!("WRAP_DIRECT_INLINE did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr new file mode 100644 index 000000000..c73a6cf13 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9 + | +LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs new file mode 100644 index 000000000..93022a23d --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs @@ -0,0 +1,26 @@ +// This is part of a set of tests exploring the different ways a +// structural-match ADT might try to hold a +// non-structural-match in hidden manner that lets matches +// through that we had intended to reject. +// +// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339 +#![warn(indirect_structural_match)] +struct NoDerive(i32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapParam(T); + +const WRAP_DIRECT_PARAM: WrapParam = WrapParam(NoDerive(0)); + +fn main() { + match WRAP_DIRECT_PARAM { + WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); } + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => { println!("WRAP_DIRECT_PARAM did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr new file mode 100644 index 000000000..6fdf9db89 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9 + | +LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs new file mode 100644 index 000000000..894739ff7 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs @@ -0,0 +1,29 @@ +// This is part of a set of tests exploring the different ways a +// structural-match ADT might try to hold a +// non-structural-match in hidden manner that lets matches +// through that we had intended to reject. +// +// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339 +#![warn(indirect_structural_match)] +// run-pass + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapInline<'a>(&'a &'a NoDerive); + +const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0)); + +fn main() { + match WRAP_DOUBLY_INDIRECT_INLINE { + WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr new file mode 100644 index 000000000..10dd635ff --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -0,0 +1,16 @@ +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs new file mode 100644 index 000000000..1699dae46 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs @@ -0,0 +1,29 @@ +// This is part of a set of tests exploring the different ways a +// structural-match ADT might try to hold a +// non-structural-match in hidden manner that lets matches +// through that we had intended to reject. +// +// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339 +#![warn(indirect_structural_match)] +// run-pass + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapParam<'a, T>(&'a &'a T); + +const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam = & &WrapParam(& & NoDerive(0)); + +fn main() { + match WRAP_DOUBLY_INDIRECT_PARAM { + WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr new file mode 100644 index 000000000..66aecbc4f --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -0,0 +1,16 @@ +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs new file mode 100644 index 000000000..2672bdd9e --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs @@ -0,0 +1,29 @@ +// This is part of a set of tests exploring the different ways a +// structural-match ADT might try to hold a +// non-structural-match in hidden manner that lets matches +// through that we had intended to reject. +// +// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339 +#![warn(indirect_structural_match)] +// run-pass + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapInline(NoDerive); + +const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0)); + +fn main() { + match WRAP_INDIRECT_INLINE { + WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr new file mode 100644 index 000000000..ee92954a6 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -0,0 +1,16 @@ +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9 + | +LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs new file mode 100644 index 000000000..3489995ae --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs @@ -0,0 +1,29 @@ +// This is part of a set of tests exploring the different ways a +// structural-match ADT might try to hold a +// non-structural-match in hidden manner that lets matches +// through that we had intended to reject. +// +// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339 +#![warn(indirect_structural_match)] +// run-pass + +struct NoDerive(#[allow(unused_tuple_struct_fields)] i32); + +// This impl makes NoDerive irreflexive. +impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } + +impl Eq for NoDerive { } + +#[derive(PartialEq, Eq)] +struct WrapParam(T); + +const WRAP_INDIRECT_PARAM: & &WrapParam = & &WrapParam(NoDerive(0)); + +fn main() { + match WRAP_INDIRECT_PARAM { + WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr new file mode 100644 index 000000000..f0c492d6a --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -0,0 +1,16 @@ +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9 + | +LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr new file mode 100644 index 000000000..bd2940479 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'structural_match' + --> $DIR/feature-gate.rs:29:6 + | +LL | impl std::marker::StructuralPartialEq for Foo { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31434 for more information + = help: add `#![feature(structural_match)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'structural_match' + --> $DIR/feature-gate.rs:31:6 + | +LL | impl std::marker::StructuralEq for Foo { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31434 for more information + = help: add `#![feature(structural_match)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs new file mode 100644 index 000000000..ee6674097 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs @@ -0,0 +1,39 @@ +// Test that use of structural-match traits is only permitted with a feature gate, +// and that if a feature gate is supplied, it permits the type to be +// used in a match. + +// revisions: with_gate no_gate + +// gate-test-structural_match + +#![allow(unused)] +#![feature(rustc_attrs)] +#![cfg_attr(with_gate, feature(structural_match))] + + +struct Foo { + x: u32 +} + +const FOO: Foo = Foo { x: 0 }; + +#[rustc_error] +fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error] + let y = Foo { x: 1 }; + match y { + FOO => { } + _ => { } + } +} + +impl std::marker::StructuralPartialEq for Foo { } +//[no_gate]~^ ERROR use of unstable library feature 'structural_match' +impl std::marker::StructuralEq for Foo { } +//[no_gate]~^ ERROR use of unstable library feature 'structural_match' + +impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.x == other.x + } +} +impl Eq for Foo { } diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr new file mode 100644 index 000000000..623fd585a --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate.rs:21:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs new file mode 100644 index 000000000..2b3fbd2a4 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs @@ -0,0 +1,135 @@ +// run-pass + +// This file checks that fn ptrs are considered structurally matchable. +// See also rust-lang/rust#63479. + +fn main() { + let mut count = 0; + + // A type which is not structurally matchable: + struct NotSM; + + // And one that is: + #[derive(PartialEq, Eq)] + struct SM; + + fn trivial() {} + + fn sm_to(_: SM) {} + fn not_sm_to(_: NotSM) {} + fn to_sm() -> SM { SM } + fn to_not_sm() -> NotSM { NotSM } + + // To recreate the scenario of interest in #63479, we need to add + // a ref-level-of-indirection so that we descend into the type. + + fn r_sm_to(_: &SM) {} + fn r_not_sm_to(_: &NotSM) {} + fn r_to_r_sm(_: &()) -> &SM { &SM } + fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM } + + #[derive(PartialEq, Eq)] + struct Wrap(T); + + // In the code below, we put the match input into a local so that + // we can assign it an explicit type that is an fn ptr instead of + // a singleton type of the fn itself that the type inference would + // otherwise assign. + + // Check that fn() is structural-match + const CFN1: Wrap = Wrap(trivial); + let input: Wrap = Wrap(trivial); + match Wrap(input) { + Wrap(CFN1) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(T) is structural-match when T is too. + const CFN2: Wrap = Wrap(sm_to); + let input: Wrap = Wrap(sm_to); + match Wrap(input) { + Wrap(CFN2) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> T is structural-match when T is too. + const CFN3: Wrap SM> = Wrap(to_sm); + let input: Wrap SM> = Wrap(to_sm); + match Wrap(input) { + Wrap(CFN3) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(T) is structural-match even if T is not. + const CFN4: Wrap = Wrap(not_sm_to); + let input: Wrap = Wrap(not_sm_to); + match Wrap(input) { + Wrap(CFN4) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> T is structural-match even if T is not. + const CFN5: Wrap NotSM> = Wrap(to_not_sm); + let input: Wrap NotSM> = Wrap(to_not_sm); + match Wrap(input) { + Wrap(CFN5) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(&T) is structural-match when T is too. + const CFN6: Wrap = Wrap(r_sm_to); + let input: Wrap = Wrap(r_sm_to); + match Wrap(input) { + Wrap(CFN6) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> &T is structural-match when T is too. + const CFN7: Wrap &SM> = Wrap(r_to_r_sm); + let input: Wrap &SM> = Wrap(r_to_r_sm); + match Wrap(input) { + Wrap(CFN7) => count += 1, + Wrap(_) => {} + }; + + // Check that fn(T) is structural-match even if T is not. + const CFN8: Wrap = Wrap(r_not_sm_to); + let input: Wrap = Wrap(r_not_sm_to); + match Wrap(input) { + Wrap(CFN8) => count += 1, + Wrap(_) => {} + }; + + // Check that fn() -> T is structural-match even if T is not. + const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); + let input: Wrap &NotSM> = Wrap(r_to_r_not_sm); + match Wrap(input) { + Wrap(CFN9) => count += 1, + Wrap(_) => {} + }; + + // Check that a type which has fn ptrs is structural-match. + #[derive(PartialEq, Eq)] + struct Foo { + alpha: fn(NotSM), + beta: fn() -> NotSM, + gamma: fn(SM), + delta: fn() -> SM, + } + + const CFOO: Foo = Foo { + alpha: not_sm_to, + beta: to_not_sm, + gamma: sm_to, + delta: to_sm, + }; + + let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm }; + match input { + CFOO => count += 1, + Foo { .. } => {} + }; + + // Final count must be 10 now if all + assert_eq!(count, 10); +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs new file mode 100644 index 000000000..2a915d61e --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs @@ -0,0 +1,19 @@ +// Issue 61188 pointed out a case where we hit an ICE during code gen: +// the compiler assumed that `PartialEq` was always implemented on any +// use of a `const` item in a pattern context, but the pre-existing +// structural-match checking was too shallow +// (see rust-lang/rust#62307), and so we hit cases where we were +// trying to dispatch to `PartialEq` on types that did not implement +// that trait. + +struct B(i32); + +const A: &[B] = &[]; + +pub fn main() { + match &[][..] { + A => (), + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => (), + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr new file mode 100644 index 000000000..0bf369fa8 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9 + | +LL | A => (), + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs new file mode 100644 index 000000000..46d8ee3b6 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs @@ -0,0 +1,43 @@ +// RFC 1445 introduced `#[structural_match]`; this attribute must +// appear on the `struct`/`enum` definition for any `const` used in a +// pattern. +// +// This is our (forever-unstable) way to mark a datatype as having a +// `PartialEq` implementation that is equivalent to recursion over its +// substructure. This avoids (at least in the short term) any need to +// resolve the question of what semantics is used for such matching. +// (See RFC 1445 for more details and discussion.) + +// Issue 62307 pointed out a case where the structural-match checking +// was too shallow. +#![warn(indirect_structural_match, nontrivial_structural_match)] +// run-pass + +#[derive(Debug)] +struct B(i32); + +// Overriding `PartialEq` to use this strange notion of "equality" exposes +// whether `match` is using structural-equality or method-dispatch +// under the hood, which is the antithesis of rust-lang/rfcs#1445 +impl PartialEq for B { + fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 } +} + +fn main() { + const RR_B0: & & B = & & B(0); + const RR_B1: & & B = & & B(1); + + match RR_B0 { + RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + _ => { } + } + + match RR_B1 { + RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } + //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]` + //~| WARN this was previously accepted + _ => { } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr new file mode 100644 index 000000000..955ab4b54 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -0,0 +1,25 @@ +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9 + | +LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match, nontrivial_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9 + | +LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 2 warnings emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs new file mode 100644 index 000000000..567685950 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs @@ -0,0 +1,40 @@ +// run-pass + +// The actual regression test from #63479. (Including this because my +// first draft at fn-ptr-is-structurally-matchable.rs failed to actually +// cover the case this hit; I've since expanded it accordingly, but the +// experience left me wary of leaving this regression test out.) + +#![warn(pointer_structural_match)] + +#[derive(Eq)] +struct A { + a: i64 +} + +impl PartialEq for A { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) + } +} + +type Fn = fn(&[A]); + +fn my_fn(_args: &[A]) { + println!("hello world"); +} + +const TEST: Fn = my_fn; + +struct B(Fn); + +fn main() { + let s = B(my_fn); + match s { + B(TEST) => println!("matched"), + //~^ WARN pointers in patterns behave unpredictably + //~| WARN this was previously accepted by the compiler but is being phased out + _ => panic!("didn't match") + }; +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr new file mode 100644 index 000000000..d6afc0255 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -0,0 +1,16 @@ +warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:35:7 + | +LL | B(TEST) => println!("matched"), + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs new file mode 100644 index 000000000..0260caa82 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs @@ -0,0 +1,21 @@ +// Matching against NaN should result in a warning + +#![allow(unused)] +#![deny(illegal_floating_point_literal_pattern)] + +const NAN: f64 = f64::NAN; + +fn main() { + let x = NAN; + match x { + NAN => {}, //~ ERROR floating-point types cannot be used + //~| WARN this was previously accepted by the compiler but is being phased out + _ => {}, + }; + + match [x, 1.0] { + [NAN, _] => {}, //~ ERROR floating-point types cannot be used + //~| WARN this was previously accepted by the compiler but is being phased out + _ => {}, + }; +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr new file mode 100644 index 000000000..f37255d08 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr @@ -0,0 +1,25 @@ +error: floating-point types cannot be used in patterns + --> $DIR/issue-6804.rs:11:9 + | +LL | NAN => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 +note: the lint level is defined here + --> $DIR/issue-6804.rs:4:9 + | +LL | #![deny(illegal_floating_point_literal_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: floating-point types cannot be used in patterns + --> $DIR/issue-6804.rs:17:10 + | +LL | [NAN, _] => {}, + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs new file mode 100644 index 000000000..7ba0f3a9e --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs @@ -0,0 +1,17 @@ +// Pre-existing behavior has been to reject patterns with consts +// denoting non-empty arrays of non-`Eq` types, but *accept* empty +// arrays of such types. +// +// See rust-lang/rust#62336. + +// run-pass + +#[derive(PartialEq, Debug)] +struct B(i32); + +fn main() { + const FOO: [B; 0] = []; + match [] { + FOO => { } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs new file mode 100644 index 000000000..59a22c337 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs @@ -0,0 +1,23 @@ +#[derive(PartialEq)] +struct Foo { + x: u32 +} + +const FOO: Foo = Foo { x: 0 }; + +fn main() { + let y = Foo { x: 1 }; + match y { + FOO => { } + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => { } + } + + let x = 0.0; + match x { + f32::INFINITY => { } + //~^ WARNING floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler but is being phased out + _ => { } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr new file mode 100644 index 000000000..616ed9e48 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr @@ -0,0 +1,18 @@ +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/match-forbidden-without-eq.rs:11:9 + | +LL | FOO => { } + | ^^^ + +warning: floating-point types cannot be used in patterns + --> $DIR/match-forbidden-without-eq.rs:18:9 + | +LL | f32::INFINITY => { } + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 + = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs new file mode 100644 index 000000000..151a475c9 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs @@ -0,0 +1,19 @@ +// Issue 62307 pointed out a case where the structural-match checking +// was too shallow. +// +// Here we check similar behavior for non-empty arrays of types that +// do not derive `Eq`. +// +// (Current behavior for empty arrays differs and thus is not tested +// here; see rust-lang/rust#62336.) + +#[derive(PartialEq, Debug)] +struct B(i32); + +fn main() { + const FOO: [B; 1] = [B(0)]; + match [B(1)] { + FOO => { } + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr new file mode 100644 index 000000000..371f8a0aa --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9 + | +LL | FOO => { } + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs new file mode 100644 index 000000000..a8deb8a75 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs @@ -0,0 +1,21 @@ +#[derive(Eq)] +struct Foo { + x: u32 +} + +impl PartialEq for Foo { + fn eq(&self, _: &Foo) -> bool { + false // ha ha! + } +} + +const FOO: Foo = Foo { x: 0 }; + +fn main() { + let y = Foo { x: 1 }; + match y { + FOO => { } + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + _ => { } + } +} diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr new file mode 100644 index 000000000..4157cf652 --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9 + | +LL | FOO => { } + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs new file mode 100644 index 000000000..50f91420c --- /dev/null +++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs @@ -0,0 +1,53 @@ +// run-pass + +// This file checks that `PhantomData` is considered structurally matchable. + +use std::marker::PhantomData; + +fn main() { + let mut count = 0; + + // A type which is not structurally matchable: + struct NotSM; + + // And one that is: + #[derive(PartialEq, Eq)] + struct SM; + + // Check that SM is structural-match: + const CSM: SM = SM; + match SM { + CSM => count += 1, + }; + + // Check that PhantomData is structural-match even if T is not. + const CPD1: PhantomData = PhantomData; + match PhantomData { + CPD1 => count += 1, + }; + + // Check that PhantomData is structural-match when T is. + const CPD2: PhantomData = PhantomData; + match PhantomData { + CPD2 => count += 1, + }; + + // Check that a type which has a PhantomData is structural-match. + #[derive(PartialEq, Eq, Default)] + struct Foo { + alpha: PhantomData, + beta: PhantomData, + } + + const CFOO: Foo = Foo { + alpha: PhantomData, + beta: PhantomData, + }; + + match Foo::default() { + CFOO => count += 1, + }; + + // Final count must be 4 now if all + assert_eq!(count, 4); +} diff --git a/tests/ui/rfc-1717-dllimport/missing-link-attr.rs b/tests/ui/rfc-1717-dllimport/missing-link-attr.rs new file mode 100644 index 000000000..b46d85160 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/missing-link-attr.rs @@ -0,0 +1,4 @@ +// compile-flags: -l foo:bar +// error-pattern: renaming of the library `foo` was specified + +#![crate_type = "lib"] diff --git a/tests/ui/rfc-1717-dllimport/missing-link-attr.stderr b/tests/ui/rfc-1717-dllimport/missing-link-attr.stderr new file mode 100644 index 000000000..d4410e147 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/missing-link-attr.stderr @@ -0,0 +1,4 @@ +error: renaming of the library `foo` was specified, however this crate contains no `#[link(...)]` attributes referencing this library + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1717-dllimport/multiple-renames.rs b/tests/ui/rfc-1717-dllimport/multiple-renames.rs new file mode 100644 index 000000000..106f196b4 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/multiple-renames.rs @@ -0,0 +1,7 @@ +// compile-flags: -l foo:bar -l foo:baz +// error-pattern: multiple renamings were specified for library + +#![crate_type = "lib"] + +#[link(name = "foo")] +extern "C" {} diff --git a/tests/ui/rfc-1717-dllimport/multiple-renames.stderr b/tests/ui/rfc-1717-dllimport/multiple-renames.stderr new file mode 100644 index 000000000..a6fec9c4e --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/multiple-renames.stderr @@ -0,0 +1,4 @@ +error: multiple renamings were specified for library `foo` + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1717-dllimport/rename-modifiers.rs b/tests/ui/rfc-1717-dllimport/rename-modifiers.rs new file mode 100644 index 000000000..30f4db718 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/rename-modifiers.rs @@ -0,0 +1,9 @@ +// compile-flags: -l dylib=foo:bar +// error-pattern: overriding linking modifiers from command line is not supported + +#![feature(native_link_modifiers_as_needed)] + +#![crate_type = "lib"] + +#[link(name = "foo", kind = "dylib", modifiers = "-as-needed")] +extern "C" {} diff --git a/tests/ui/rfc-1717-dllimport/rename-modifiers.stderr b/tests/ui/rfc-1717-dllimport/rename-modifiers.stderr new file mode 100644 index 000000000..bee639bf2 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/rename-modifiers.stderr @@ -0,0 +1,8 @@ +error: overriding linking modifiers from command line is not supported + --> $DIR/rename-modifiers.rs:9:1 + | +LL | extern "C" {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1717-dllimport/rename-to-empty.rs b/tests/ui/rfc-1717-dllimport/rename-to-empty.rs new file mode 100644 index 000000000..9356c4129 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/rename-to-empty.rs @@ -0,0 +1,7 @@ +// compile-flags: -l foo: +// error-pattern: an empty renaming target was specified for library + +#![crate_type = "lib"] + +#[link(name = "foo")] +extern "C" {} diff --git a/tests/ui/rfc-1717-dllimport/rename-to-empty.stderr b/tests/ui/rfc-1717-dllimport/rename-to-empty.stderr new file mode 100644 index 000000000..aca839d80 --- /dev/null +++ b/tests/ui/rfc-1717-dllimport/rename-to-empty.stderr @@ -0,0 +1,4 @@ +error: an empty renaming target was specified for library `foo` + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-1.rs b/tests/ui/rfc-1937-termination-trait/issue-103052-1.rs new file mode 100644 index 000000000..a75c91cc9 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/issue-103052-1.rs @@ -0,0 +1,11 @@ +// Check that we don't blindly emit a diagnostic claiming that "`main` has an invalid return type" +// if we encounter a type that doesn't implement `std::process::Termination` and is not actually +// the return type of the program entry `main`. + +fn receive(_: impl std::process::Termination) {} + +struct Something; + +fn main() { + receive(Something); //~ ERROR the trait bound `Something: Termination` is not satisfied +} diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-1.stderr b/tests/ui/rfc-1937-termination-trait/issue-103052-1.stderr new file mode 100644 index 000000000..409dede1a --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/issue-103052-1.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Something: Termination` is not satisfied + --> $DIR/issue-103052-1.rs:10:13 + | +LL | receive(Something); + | ------- ^^^^^^^^^ the trait `Termination` is not implemented for `Something` + | | + | required by a bound introduced by this call + | +note: required by a bound in `receive` + --> $DIR/issue-103052-1.rs:5:20 + | +LL | fn receive(_: impl std::process::Termination) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `receive` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs new file mode 100644 index 000000000..fa9182b6d --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/issue-103052-2.rs @@ -0,0 +1,18 @@ +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +mod child { + trait Main { + fn main() -> impl std::process::Termination; + } + + struct Something; + + impl Main for () { + fn main() -> Something { //~ ERROR the trait bound `Something: Termination` is not satisfied + Something + } + } +} + +fn main() {} diff --git a/tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr new file mode 100644 index 000000000..a700c72ea --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/issue-103052-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Something: Termination` is not satisfied + --> $DIR/issue-103052-2.rs:12:22 + | +LL | fn main() -> Something { + | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` + | +note: required by a bound in `Main::main::{opaque#0}` + --> $DIR/issue-103052-2.rs:6:27 + | +LL | fn main() -> impl std::process::Termination; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs new file mode 100644 index 000000000..10dc6115d --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs @@ -0,0 +1,11 @@ +// run-fail +// error-pattern:returned Box from main() +// failure-status: 1 +// ignore-emscripten no processes + +use std::error::Error; +use std::io; + +fn main() -> Result<(), Box> { + Err(Box::new(io::Error::new(io::ErrorKind::Other, "returned Box from main()"))) +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-for-never.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-for-never.rs new file mode 100644 index 000000000..faf2526c8 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-for-never.rs @@ -0,0 +1,7 @@ +// run-fail +// error-pattern:oh, dear +// ignore-emscripten no processes + +fn main() -> ! { + panic!("oh, dear"); +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs new file mode 100644 index 000000000..6a625fb05 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:returned Box from main() +// failure-status: 1 +// ignore-emscripten no processes + +use std::io::{Error, ErrorKind}; + +fn main() -> Result<(), Box> { + Err(Box::new(Error::new(ErrorKind::Other, "returned Box from main()"))) +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-for-str.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-for-str.rs new file mode 100644 index 000000000..94f16c6fd --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-for-str.rs @@ -0,0 +1,8 @@ +// run-fail +// error-pattern: An error message for you +// failure-status: 1 +// ignore-emscripten no processes + +fn main() -> Result<(), &'static str> { + Err("An error message for you") +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs new file mode 100644 index 000000000..3b60cbc57 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs @@ -0,0 +1,3 @@ +// Tests that an `impl Trait` that is not `impl Termination` will not work. +fn main() -> impl Copy { } +//~^ ERROR `main` has invalid return type `impl Copy` diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr b/tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr new file mode 100644 index 000000000..5ee6d127e --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `impl Copy` + --> $DIR/termination-trait-impl-trait.rs:2:14 + | +LL | fn main() -> impl Copy { } + | ^^^^^^^^^ `main` can only return types that implement `Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs new file mode 100644 index 000000000..96808a3ed --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs @@ -0,0 +1,15 @@ +// compile-flags: --test + +#![feature(test)] + +extern crate test; +use std::num::ParseIntError; +use test::Bencher; + +#[test] +#[should_panic] +fn not_a_num() -> Result<(), ParseIntError> { + //~^ ERROR functions using `#[should_panic]` must return `()` + let _: u32 = "abc".parse()?; + Ok(()) +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr b/tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr new file mode 100644 index 000000000..7f6749fc9 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr @@ -0,0 +1,12 @@ +error: functions using `#[should_panic]` must return `()` + --> $DIR/termination-trait-in-test-should-panic.rs:11:1 + | +LL | / fn not_a_num() -> Result<(), ParseIntError> { +LL | | +LL | | let _: u32 = "abc".parse()?; +LL | | Ok(()) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs new file mode 100644 index 000000000..43888cece --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -0,0 +1,28 @@ +// compile-flags: --test +// run-pass +// needs-unwind + + +#![feature(test)] + +extern crate test; +use std::num::ParseIntError; +use test::Bencher; + +#[test] +fn is_a_num() -> Result<(), ParseIntError> { + let _: u32 = "22".parse()?; + Ok(()) +} + +#[bench] +fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> { + Ok(()) +} + +#[bench] +#[should_panic] +fn test_a_neg_bench(_: &mut Bencher) -> Result<(), ParseIntError> { + let _: u32 = "abc".parse()?; + Ok(()) +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs new file mode 100644 index 000000000..10f7d2215 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.rs @@ -0,0 +1,6 @@ +fn main() -> i32 { +//~^ ERROR `main` has invalid return type `i32` +//~| NOTE `main` can only return types that implement `Termination` +//~| HELP consider using `()`, or a `Result` + 0 +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr b/tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr new file mode 100644 index 000000000..53779d365 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-main-i32.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `i32` + --> $DIR/termination-trait-main-i32.rs:1:14 + | +LL | fn main() -> i32 { + | ^^^ `main` can only return types that implement `Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs new file mode 100644 index 000000000..687d5f144 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs @@ -0,0 +1,3 @@ +fn main() -> char { //~ ERROR + ' ' +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr new file mode 100644 index 000000000..bc8fd92ce --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `char` + --> $DIR/termination-trait-main-wrong-type.rs:1:14 + | +LL | fn main() -> char { + | ^^^^ `main` can only return types that implement `Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs new file mode 100644 index 000000000..4c6168abb --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.rs @@ -0,0 +1,5 @@ +struct ReturnType {} + +fn main() -> ReturnType { //~ ERROR `main` has invalid return type `ReturnType` + ReturnType {} +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr b/tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr new file mode 100644 index 000000000..cb329548d --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-not-satisfied.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `ReturnType` + --> $DIR/termination-trait-not-satisfied.rs:3:14 + | +LL | fn main() -> ReturnType { + | ^^^^^^^^^^ `main` can only return types that implement `Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs b/tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs new file mode 100644 index 000000000..193a523ae --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs @@ -0,0 +1,8 @@ +// compile-flags: --test + +use std::num::ParseFloatError; + +#[test] +fn can_parse_zero_as_f32() -> Result { //~ ERROR + "0".parse() +} diff --git a/tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr new file mode 100644 index 000000000..a19750cc7 --- /dev/null +++ b/tests/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `f32: Termination` is not satisfied + --> $DIR/termination-trait-test-wrong-type.rs:6:31 + | +LL | #[test] + | ------- in this procedural macro expansion +LL | fn can_parse_zero_as_f32() -> Result { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32` + | + = note: required for `Result` to implement `Termination` +note: required by a bound in `assert_test_result` + --> $SRC_DIR/test/src/lib.rs:LL:COL + = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs b/tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs new file mode 100644 index 000000000..54ab9f0ad --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs @@ -0,0 +1,24 @@ +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct Foo { +} + +impl Foo { + fn get(&self) -> Option<&Result> { + None + } + + fn mutate(&mut self) { } +} + +fn main() { + let mut foo = Foo { }; + + // foo.get() returns type Option<&Result>, so + // using `string` keeps borrow of `foo` alive. Hence calling + // `foo.mutate()` should be an error. + while let Some(Ok(string)) = foo.get() { + foo.mutate(); + //~^ ERROR cannot borrow `foo` as mutable + println!("foo={:?}", *string); + } +} diff --git a/tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr b/tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr new file mode 100644 index 000000000..b7c0b0bb6 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr @@ -0,0 +1,14 @@ +error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-issue-49631.rs:20:9 + | +LL | while let Some(Ok(string)) = foo.get() { + | --------- immutable borrow occurs here +LL | foo.mutate(); + | ^^^^^^^^^^^^ mutable borrow occurs here +LL | +LL | println!("foo={:?}", *string); + | ------- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/rfc-2005-default-binding-mode/const.rs b/tests/ui/rfc-2005-default-binding-mode/const.rs new file mode 100644 index 000000000..93df88040 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/const.rs @@ -0,0 +1,17 @@ +// FIXME(tschottdorf): this test should pass. + +#[derive(PartialEq, Eq)] +struct Foo { + bar: i32, +} + +const FOO: Foo = Foo{bar: 5}; + +fn main() { + let f = Foo{bar:6}; + + match &f { + FOO => {}, //~ ERROR mismatched types + _ => panic!(), + } +} diff --git a/tests/ui/rfc-2005-default-binding-mode/const.stderr b/tests/ui/rfc-2005-default-binding-mode/const.stderr new file mode 100644 index 000000000..0f5671254 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/const.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/const.rs:14:9 + | +LL | const FOO: Foo = Foo{bar: 5}; + | -------------- constant defined here +... +LL | match &f { + | -- this expression has type `&Foo` +LL | FOO => {}, + | ^^^ + | | + | expected `&Foo`, found struct `Foo` + | `FOO` is interpreted as a constant, not a new binding + | help: introduce a new binding instead: `other_foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-2005-default-binding-mode/enum.rs b/tests/ui/rfc-2005-default-binding-mode/enum.rs new file mode 100644 index 000000000..4e57769d6 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/enum.rs @@ -0,0 +1,22 @@ +enum Wrapper { + Wrap(i32), +} + +use Wrapper::Wrap; + +pub fn main() { + let Wrap(x) = &Wrap(3); + *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference + + + if let Some(x) = &Some(3) { + *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference + } else { + panic!(); + } + + while let Some(x) = &Some(3) { + *x += 1; //~ ERROR cannot assign to `*x`, which is behind a `&` reference + break; + } +} diff --git a/tests/ui/rfc-2005-default-binding-mode/enum.stderr b/tests/ui/rfc-2005-default-binding-mode/enum.stderr new file mode 100644 index 000000000..21e3d3d27 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/enum.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/enum.rs:9:5 + | +LL | *x += 1; + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/enum.rs:13:9 + | +LL | *x += 1; + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*x`, which is behind a `&` reference + --> $DIR/enum.rs:19:9 + | +LL | *x += 1; + | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/rfc-2005-default-binding-mode/explicit-mut.rs b/tests/ui/rfc-2005-default-binding-mode/explicit-mut.rs new file mode 100644 index 000000000..b8fde2208 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/explicit-mut.rs @@ -0,0 +1,28 @@ +// Verify the binding mode shifts - only when no `&` are auto-dereferenced is the +// final default binding mode mutable. + +fn main() { + match &&Some(5i32) { + Some(n) => { + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference + let _ = n; + } + None => {}, + }; + + match &mut &Some(5i32) { + Some(n) => { + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference + let _ = n; + } + None => {}, + }; + + match &&mut Some(5i32) { + Some(n) => { + *n += 1; //~ ERROR cannot assign to `*n`, which is behind a `&` reference + let _ = n; + } + None => {}, + }; +} diff --git a/tests/ui/rfc-2005-default-binding-mode/explicit-mut.stderr b/tests/ui/rfc-2005-default-binding-mode/explicit-mut.stderr new file mode 100644 index 000000000..c3f64f65a --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/explicit-mut.stderr @@ -0,0 +1,21 @@ +error[E0594]: cannot assign to `*n`, which is behind a `&` reference + --> $DIR/explicit-mut.rs:7:13 + | +LL | *n += 1; + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*n`, which is behind a `&` reference + --> $DIR/explicit-mut.rs:15:13 + | +LL | *n += 1; + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*n`, which is behind a `&` reference + --> $DIR/explicit-mut.rs:23:13 + | +LL | *n += 1; + | ^^^^^^^ `n` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/rfc-2005-default-binding-mode/for.rs b/tests/ui/rfc-2005-default-binding-mode/for.rs new file mode 100644 index 000000000..d6c5a13b1 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/for.rs @@ -0,0 +1,9 @@ +struct Foo {} + +pub fn main() { + let mut tups = vec![(Foo {}, Foo {})]; + // The below desugars to &(ref n, mut m). + for (n, mut m) in &tups { + //~^ ERROR cannot move out of a shared reference + } +} diff --git a/tests/ui/rfc-2005-default-binding-mode/for.stderr b/tests/ui/rfc-2005-default-binding-mode/for.stderr new file mode 100644 index 000000000..07991af6e --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/for.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/for.rs:6:23 + | +LL | for (n, mut m) in &tups { + | ----- ^^^^^ + | | + | data moved here + | move occurs because `m` has type `Foo`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | for (n, ref mut m) in &tups { + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/rfc-2005-default-binding-mode/issue-44912-or.rs b/tests/ui/rfc-2005-default-binding-mode/issue-44912-or.rs new file mode 100644 index 000000000..b4a0d8145 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/issue-44912-or.rs @@ -0,0 +1,10 @@ +// FIXME(tschottdorf): This should compile. See #44912. + +pub fn main() { + let x = &Some((3, 3)); + let _: &i32 = match x { + Some((x, 3)) | &Some((ref x, 5)) => x, + //~^ ERROR is bound inconsistently + _ => &5i32, + }; +} diff --git a/tests/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr b/tests/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr new file mode 100644 index 000000000..e1e1bf7f6 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr @@ -0,0 +1,9 @@ +error[E0409]: variable `x` is bound inconsistently across alternatives separated by `|` + --> $DIR/issue-44912-or.rs:6:35 + | +LL | Some((x, 3)) | &Some((ref x, 5)) => x, + | - first binding ^ bound in different ways + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0409`. diff --git a/tests/ui/rfc-2005-default-binding-mode/lit.rs b/tests/ui/rfc-2005-default-binding-mode/lit.rs new file mode 100644 index 000000000..ce79cfbdc --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/lit.rs @@ -0,0 +1,24 @@ +// FIXME(tschottdorf): we want these to compile, but they don't. + +fn with_str() { + let s: &'static str = "abc"; + + match &s { + "abc" => true, //~ ERROR mismatched types + _ => panic!(), + }; +} + +fn with_bytes() { + let s: &'static [u8] = b"abc"; + + match &s { + b"abc" => true, //~ ERROR mismatched types + _ => panic!(), + }; +} + +pub fn main() { + with_str(); + with_bytes(); +} diff --git a/tests/ui/rfc-2005-default-binding-mode/lit.stderr b/tests/ui/rfc-2005-default-binding-mode/lit.stderr new file mode 100644 index 000000000..11bc170cd --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/lit.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/lit.rs:7:13 + | +LL | match &s { + | -- this expression has type `&&str` +LL | "abc" => true, + | ^^^^^ expected `&str`, found `str` + | + = note: expected reference `&&str` + found reference `&'static str` + +error[E0308]: mismatched types + --> $DIR/lit.rs:16:9 + | +LL | match &s { + | -- this expression has type `&&[u8]` +LL | b"abc" => true, + | ^^^^^^ expected `&[u8]`, found array `[u8; 3]` + | + = note: expected reference `&&[u8]` + found reference `&'static [u8; 3]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-2005-default-binding-mode/no-double-error.rs b/tests/ui/rfc-2005-default-binding-mode/no-double-error.rs new file mode 100644 index 000000000..46fdfd678 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/no-double-error.rs @@ -0,0 +1,11 @@ +// Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs +// the error below would be reported twice (once when checking +// for a non-ref pattern, once when processing the pattern). + +fn main() { + let foo = 22; + match foo { + u32::XXX => { } //~ ERROR no associated item named + _ => { } + } +} diff --git a/tests/ui/rfc-2005-default-binding-mode/no-double-error.stderr b/tests/ui/rfc-2005-default-binding-mode/no-double-error.stderr new file mode 100644 index 000000000..c672acee0 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/no-double-error.stderr @@ -0,0 +1,9 @@ +error[E0599]: no associated item named `XXX` found for type `u32` in the current scope + --> $DIR/no-double-error.rs:8:14 + | +LL | u32::XXX => { } + | ^^^ associated item not found in `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rfc-2005-default-binding-mode/slice.rs b/tests/ui/rfc-2005-default-binding-mode/slice.rs new file mode 100644 index 000000000..363a0e3e6 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/slice.rs @@ -0,0 +1,7 @@ +pub fn main() { + let sl: &[u8] = b"foo"; + + match sl { //~ ERROR non-exhaustive patterns + [first, remainder @ ..] => {}, + }; +} diff --git a/tests/ui/rfc-2005-default-binding-mode/slice.stderr b/tests/ui/rfc-2005-default-binding-mode/slice.stderr new file mode 100644 index 000000000..60c1f5420 --- /dev/null +++ b/tests/ui/rfc-2005-default-binding-mode/slice.stderr @@ -0,0 +1,16 @@ +error[E0004]: non-exhaustive patterns: `&[]` not covered + --> $DIR/slice.rs:4:11 + | +LL | match sl { + | ^^ pattern `&[]` not covered + | + = note: the matched value is of type `&[u8]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [first, remainder @ ..] => {} +LL ~ &[] => todo!(), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs new file mode 100644 index 000000000..cb2b585ab --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs @@ -0,0 +1,44 @@ +#![crate_type = "rlib"] + +#[non_exhaustive] +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 }, +} + +#[non_exhaustive] +pub enum NestedNonExhaustive { + A(NonExhaustiveEnum), + B, + C, +} + +#[non_exhaustive] +pub enum EmptyNonExhaustiveEnum {} + +pub enum VariantNonExhaustive { + #[non_exhaustive] + Bar { + x: u32, + y: u64, + }, + Baz(u32, u16), +} + +#[non_exhaustive] +pub enum NonExhaustiveSingleVariant { + A(bool), +} + +#[repr(u8)] +pub enum FieldLessWithNonExhaustiveVariant { + A, + B, + #[non_exhaustive] + C, +} + +impl Default for FieldLessWithNonExhaustiveVariant { + fn default() -> Self { Self::A } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs new file mode 100644 index 000000000..5f86db86d --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs @@ -0,0 +1,8 @@ +#[non_exhaustive] +pub enum NonExhaustiveMonovariant { + Variant(u32), +} + +pub enum ExhaustiveMonovariant { + Variant(u32), +} diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs new file mode 100644 index 000000000..78db6b170 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs @@ -0,0 +1,41 @@ +#[derive(Default)] +#[non_exhaustive] +pub struct NormalStruct { + pub first_field: u16, + pub second_field: u16, +} + +#[non_exhaustive] +pub struct UnitStruct; + +#[non_exhaustive] +pub struct TupleStruct(pub u16, pub u16); + +#[derive(Debug)] +#[non_exhaustive] +pub struct FunctionalRecord { + pub first_field: u16, + pub second_field: u16, + pub third_field: bool, +} + +impl Default for FunctionalRecord { + fn default() -> FunctionalRecord { + FunctionalRecord { first_field: 640, second_field: 480, third_field: false } + } +} + +#[derive(Default)] +#[non_exhaustive] +pub struct NestedStruct { + pub foo: u16, + pub bar: NormalStruct, +} + +#[derive(Default)] +#[non_exhaustive] +pub struct MixedVisFields { + pub a: u16, + pub b: bool, + pub(crate) foo: bool, +} diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs new file mode 100644 index 000000000..11df44461 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs @@ -0,0 +1,60 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub enum UnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub enum OnlyUnstableEnum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable2, +} + +impl OnlyUnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new() -> Self { + Self::Unstable + } +} + +#[derive(Default)] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable: bool, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable2: usize, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub struct OnlyUnstableStruct { + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable2: bool, +} + +impl OnlyUnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new() -> Self { + Self { + unstable: 0, + unstable2: false, + } + } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs new file mode 100644 index 000000000..02672d545 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] + +pub enum NonExhaustiveVariants { + #[non_exhaustive] Unit, + #[non_exhaustive] Tuple(u32), + #[non_exhaustive] Struct { field: u32 } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs new file mode 100644 index 000000000..be775b37f --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs @@ -0,0 +1,42 @@ +// Test that the borrow checker doesn't consider checking an exhaustive pattern +// as an access. + +// check-pass + +// aux-build:monovariants.rs +extern crate monovariants; + +use monovariants::ExhaustiveMonovariant; + +enum Local { + Variant(u32), +} + +#[non_exhaustive] +enum LocalNonExhaustive { + Variant(u32), +} + +fn main() { + let mut x = ExhaustiveMonovariant::Variant(1); + let y = &mut x; + match x { + ExhaustiveMonovariant::Variant(_) => {}, + _ => {}, + } + drop(y); + let mut x = Local::Variant(1); + let y = &mut x; + match x { + Local::Variant(_) => {}, + _ => {}, + } + drop(y); + let mut x = LocalNonExhaustive::Variant(1); + let y = &mut x; + match x { + LocalNonExhaustive::Variant(_) => {}, + _ => {}, + } + drop(y); +} diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs new file mode 100644 index 000000000..2ad92b794 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs @@ -0,0 +1,18 @@ +// Test that the borrow checker considers `#[non_exhaustive]` when checking +// whether a match contains a discriminant read. + +// aux-build:monovariants.rs +extern crate monovariants; + +use monovariants::NonExhaustiveMonovariant; + +fn main() { + let mut x = NonExhaustiveMonovariant::Variant(1); + let y = &mut x; + match x { + //~^ ERROR cannot use `x` because it was mutably borrowed + NonExhaustiveMonovariant::Variant(_) => {}, + _ => {}, + } + drop(y); +} diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr new file mode 100644 index 000000000..de730ce10 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr @@ -0,0 +1,14 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-non-exhaustive.rs:12:11 + | +LL | let y = &mut x; + | ------ borrow of `x` occurs here +LL | match x { + | ^ use of borrowed `x` +... +LL | drop(y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs new file mode 100644 index 000000000..5dce8180f --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs @@ -0,0 +1,11 @@ +// aux-build:enums.rs + +extern crate enums; + +use enums::FieldLessWithNonExhaustiveVariant; + +fn main() { + let e = FieldLessWithNonExhaustiveVariant::default(); + let d = e as u8; //~ ERROR casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid [E0606] + assert_eq!(d, 0); +} diff --git a/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr new file mode 100644 index 000000000..a61dcf839 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr @@ -0,0 +1,11 @@ +error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid + --> $DIR/enum-as-cast.rs:9:13 + | +LL | let d = e as u8; + | ^^^^^^^ + | + = note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/rfc-2008-non-exhaustive/enum.rs b/tests/ui/rfc-2008-non-exhaustive/enum.rs new file mode 100644 index 000000000..9d2855f5c --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum.rs @@ -0,0 +1,69 @@ +// aux-build:enums.rs +extern crate enums; + +use enums::{EmptyNonExhaustiveEnum, NonExhaustiveEnum}; + +fn empty(x: EmptyNonExhaustiveEnum) { + match x {} //~ ERROR type `EmptyNonExhaustiveEnum` is non-empty + match x { + _ => {}, // ok + } +} + +fn main() { + let enum_unit = NonExhaustiveEnum::Unit; + + match enum_unit { + //~^ ERROR non-exhaustive patterns: `_` not covered [E0004] + NonExhaustiveEnum::Unit => "first", + NonExhaustiveEnum::Tuple(_) => "second", + NonExhaustiveEnum::Struct { .. } => "third" + }; + + match enum_unit {}; + //~^ ERROR non-exhaustive patterns: `_` not covered [E0004] + + // Everything below this is expected to compile successfully. + + let enum_unit = NonExhaustiveEnum::Unit; + + match enum_unit { + NonExhaustiveEnum::Unit => 1, + NonExhaustiveEnum::Tuple(_) => 2, + // This particular arm tests that an enum marked as non-exhaustive + // will not error if its variants are matched exhaustively. + NonExhaustiveEnum::Struct { field } => field, + _ => 0 // no error with wildcard + }; + + match enum_unit { + _ => "no error with only wildcard" + }; + + // #53549: Check that variant constructors can still be called normally. + match NonExhaustiveEnum::Unit { + NonExhaustiveEnum::Unit => {}, + _ => {} + }; + + match NonExhaustiveEnum::Tuple(2) { + NonExhaustiveEnum::Tuple(2) => {}, + _ => {} + }; + + match (NonExhaustiveEnum::Unit {}) { + NonExhaustiveEnum::Unit {} => {}, + _ => {} + }; + + match (NonExhaustiveEnum::Tuple { 0: 2 }) { + NonExhaustiveEnum::Tuple { 0: 2 } => {}, + _ => {} + }; + + match (NonExhaustiveEnum::Struct { field: 2 }) { + NonExhaustiveEnum::Struct { field: 2 } => {}, + _ => {} + }; + +} diff --git a/tests/ui/rfc-2008-non-exhaustive/enum.stderr b/tests/ui/rfc-2008-non-exhaustive/enum.stderr new file mode 100644 index 000000000..872cb9b8b --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum.stderr @@ -0,0 +1,59 @@ +error[E0004]: non-exhaustive patterns: type `EmptyNonExhaustiveEnum` is non-empty + --> $DIR/enum.rs:7:11 + | +LL | match x {} + | ^ + | +note: `EmptyNonExhaustiveEnum` defined here + --> $DIR/auxiliary/enums.rs:18:1 + | +LL | pub enum EmptyNonExhaustiveEnum {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `EmptyNonExhaustiveEnum`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/enum.rs:16:11 + | +LL | match enum_unit { + | ^^^^^^^^^ pattern `_` not covered + | +note: `NonExhaustiveEnum` defined here + --> $DIR/auxiliary/enums.rs:4:1 + | +LL | pub enum NonExhaustiveEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ NonExhaustiveEnum::Struct { .. } => "third", +LL + _ => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/enum.rs:23:11 + | +LL | match enum_unit {}; + | ^^^^^^^^^ pattern `_` not covered + | +note: `NonExhaustiveEnum` defined here + --> $DIR/auxiliary/enums.rs:4:1 + | +LL | pub enum NonExhaustiveEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ match enum_unit { +LL + _ => todo!(), +LL ~ }; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs new file mode 100644 index 000000000..54e42917f --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs @@ -0,0 +1,18 @@ +// run-pass + +#[non_exhaustive] +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 } +} + +fn main() { + let enum_unit = NonExhaustiveEnum::Unit; + + match enum_unit { + NonExhaustiveEnum::Unit => "first", + NonExhaustiveEnum::Tuple(_) => "second", + NonExhaustiveEnum::Struct { .. } => "third", + }; +} diff --git a/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs new file mode 100644 index 000000000..69a283c31 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs @@ -0,0 +1,37 @@ +#![deny(unreachable_patterns)] + +#[non_exhaustive] +pub enum NonExhaustiveEnum { + Unit, + //~^ not covered + Tuple(u32), + //~^ not covered + Struct { field: u32 } + //~^ not covered +} + +pub enum NormalEnum { + Unit, + //~^ not covered + Tuple(u32), + //~^ not covered + Struct { field: u32 } + //~^ not covered +} + +#[non_exhaustive] +pub enum EmptyNonExhaustiveEnum {} + +fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) { + match x {} + match x { + _ => {} //~ ERROR unreachable pattern + } +} + +fn main() { + match NonExhaustiveEnum::Unit {} + //~^ ERROR `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered [E0004] + match NormalEnum::Unit {} + //~^ ERROR `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered [E0004] +} diff --git a/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr new file mode 100644 index 000000000..de1bf8be8 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -0,0 +1,69 @@ +error: unreachable pattern + --> $DIR/enum_same_crate_empty_match.rs:28:9 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/enum_same_crate_empty_match.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0004]: non-exhaustive patterns: `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered + --> $DIR/enum_same_crate_empty_match.rs:33:11 + | +LL | match NonExhaustiveEnum::Unit {} + | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered + | +note: `NonExhaustiveEnum` defined here + --> $DIR/enum_same_crate_empty_match.rs:5:5 + | +LL | pub enum NonExhaustiveEnum { + | ----------------- +LL | Unit, + | ^^^^ not covered +LL | +LL | Tuple(u32), + | ^^^^^ not covered +LL | +LL | Struct { field: u32 } + | ^^^^^^ not covered + = note: the matched value is of type `NonExhaustiveEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match NonExhaustiveEnum::Unit { +LL + NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_) | NonExhaustiveEnum::Struct { .. } => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered + --> $DIR/enum_same_crate_empty_match.rs:35:11 + | +LL | match NormalEnum::Unit {} + | ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered + | +note: `NormalEnum` defined here + --> $DIR/enum_same_crate_empty_match.rs:14:5 + | +LL | pub enum NormalEnum { + | ---------- +LL | Unit, + | ^^^^ not covered +LL | +LL | Tuple(u32), + | ^^^^^ not covered +LL | +LL | Struct { field: u32 } + | ^^^^^^ not covered + = note: the matched value is of type `NormalEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match NormalEnum::Unit { +LL + NormalEnum::Unit | NormalEnum::Tuple(_) | NormalEnum::Struct { .. } => todo!(), +LL + } + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs new file mode 100644 index 000000000..d6251fcb7 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs @@ -0,0 +1,29 @@ +#[non_exhaustive] +#[repr(C)] +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 } +} + +#[non_exhaustive] +#[repr(C)] +pub struct NormalStruct { + pub first_field: u16, + pub second_field: u16, +} + +#[non_exhaustive] +#[repr(C)] +pub struct UnitStruct; + +#[non_exhaustive] +#[repr(C)] +pub struct TupleStruct (pub u16, pub u16); + +#[repr(C)] +pub enum NonExhaustiveVariants { + #[non_exhaustive] Unit, + #[non_exhaustive] Tuple(u32), + #[non_exhaustive] Struct { field: u32 } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs new file mode 100644 index 000000000..15c0c695f --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs @@ -0,0 +1,24 @@ +// aux-build:types.rs +#![deny(improper_ctypes)] + +extern crate types; + +// This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered +// improper. + +use types::{NonExhaustiveEnum, NonExhaustiveVariants, NormalStruct, TupleStruct, UnitStruct}; + +extern "C" { + pub fn non_exhaustive_enum(_: NonExhaustiveEnum); + //~^ ERROR `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe + pub fn non_exhaustive_normal_struct(_: NormalStruct); + //~^ ERROR `extern` block uses type `NormalStruct`, which is not FFI-safe + pub fn non_exhaustive_unit_struct(_: UnitStruct); + //~^ ERROR `extern` block uses type `UnitStruct`, which is not FFI-safe + pub fn non_exhaustive_tuple_struct(_: TupleStruct); + //~^ ERROR `extern` block uses type `TupleStruct`, which is not FFI-safe + pub fn non_exhaustive_variant(_: NonExhaustiveVariants); + //~^ ERROR `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr new file mode 100644 index 000000000..43c8e1015 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr @@ -0,0 +1,47 @@ +error: `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:12:35 + | +LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum); + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: this enum is non-exhaustive +note: the lint level is defined here + --> $DIR/extern_crate_improper.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: `extern` block uses type `NormalStruct`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:14:44 + | +LL | pub fn non_exhaustive_normal_struct(_: NormalStruct); + | ^^^^^^^^^^^^ not FFI-safe + | + = note: this struct is non-exhaustive + +error: `extern` block uses type `UnitStruct`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:16:42 + | +LL | pub fn non_exhaustive_unit_struct(_: UnitStruct); + | ^^^^^^^^^^ not FFI-safe + | + = note: this struct is non-exhaustive + +error: `extern` block uses type `TupleStruct`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:18:43 + | +LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct); + | ^^^^^^^^^^^ not FFI-safe + | + = note: this struct is non-exhaustive + +error: `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:20:38 + | +LL | pub fn non_exhaustive_variant(_: NonExhaustiveVariants); + | ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: this enum has non-exhaustive variants + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs new file mode 100644 index 000000000..fe4ae345d --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs @@ -0,0 +1,48 @@ +// check-pass +#![deny(improper_ctypes)] + +// This test checks that non-exhaustive types with `#[repr(C)]` are considered proper within +// the defining crate. + +#[non_exhaustive] +#[repr(C)] +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 }, +} + +#[non_exhaustive] +#[repr(C)] +pub struct NormalStruct { + pub first_field: u16, + pub second_field: u16, +} + +#[non_exhaustive] +#[repr(C)] +pub struct UnitStruct; + +#[non_exhaustive] +#[repr(C)] +pub struct TupleStruct(pub u16, pub u16); + +#[repr(C)] +pub enum NonExhaustiveVariants { + #[non_exhaustive] + Unit, + #[non_exhaustive] + Tuple(u32), + #[non_exhaustive] + Struct { field: u32 }, +} + +extern "C" { + // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway. + pub fn non_exhaustive_enum(_: NonExhaustiveEnum); + pub fn non_exhaustive_normal_struct(_: NormalStruct); + pub fn non_exhaustive_tuple_struct(_: TupleStruct); + pub fn non_exhaustive_variant(_: NonExhaustiveVariants); +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs new file mode 100644 index 000000000..143f9a300 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs @@ -0,0 +1,16 @@ +#[non_exhaustive(anything)] +//~^ ERROR malformed `non_exhaustive` attribute +struct Foo; + +#[non_exhaustive] +//~^ ERROR attribute should be applied to a struct or enum [E0701] +trait Bar { } + +#[non_exhaustive] +//~^ ERROR attribute should be applied to a struct or enum [E0701] +union Baz { + f1: u16, + f2: u16 +} + +fn main() { } diff --git a/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr new file mode 100644 index 000000000..136cd763b --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr @@ -0,0 +1,30 @@ +error: malformed `non_exhaustive` attribute input + --> $DIR/invalid-attribute.rs:1:1 + | +LL | #[non_exhaustive(anything)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]` + +error[E0701]: attribute should be applied to a struct or enum + --> $DIR/invalid-attribute.rs:5:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | trait Bar { } + | ------------- not a struct or enum + +error[E0701]: attribute should be applied to a struct or enum + --> $DIR/invalid-attribute.rs:9:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ +LL | +LL | / union Baz { +LL | | f1: u16, +LL | | f2: u16 +LL | | } + | |_- not a struct or enum + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0701`. diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs new file mode 100644 index 000000000..d8f07bb8f --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -0,0 +1,187 @@ +// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly. + +#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)] + +// aux-build:enums.rs +extern crate enums; +// aux-build:unstable.rs +extern crate unstable; +// aux-build:structs.rs +extern crate structs; + +use enums::{ + EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant, + VariantNonExhaustive, +}; +use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct}; +use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct}; + +#[non_exhaustive] +#[derive(Default)] +pub struct Foo { + a: u8, + b: usize, + c: String, +} + +#[non_exhaustive] +pub enum Bar { + A, + B, + C, +} + +fn main() { + let enumeration = Bar::A; + + // Ok: this is a crate local non_exhaustive enum + match enumeration { + Bar::A => {} + Bar::B => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + let non_enum = NonExhaustiveEnum::Unit; + + // Ok: without the attribute + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + match non_enum { + NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + let x = 5; + match non_enum { + NonExhaustiveEnum::Unit if x > 10 => {} + NonExhaustiveEnum::Tuple(_) => {} + NonExhaustiveEnum::Struct { .. } => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: all covered and not `unreachable-patterns` + #[deny(unreachable_patterns)] + match non_enum { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + NonExhaustiveEnum::Struct { .. } => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match NestedNonExhaustive::B { + NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {} + NestedNonExhaustive::A(_) => {} + NestedNonExhaustive::B => {} + _ => {} + } + //~^^ some variants are not matched explicitly + //~^^^^^ some variants are not matched explicitly + + #[warn(non_exhaustive_omitted_patterns)] + match VariantNonExhaustive::Baz(1, 2) { + VariantNonExhaustive::Baz(_, _) => {} + VariantNonExhaustive::Bar { x, .. } => {} + } + //~^^ some fields are not explicitly listed + + #[warn(non_exhaustive_omitted_patterns)] + let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); + //~^ some fields are not explicitly listed + + // Ok: this is local + #[warn(non_exhaustive_omitted_patterns)] + let Foo { a, b, .. } = Foo::default(); + + #[warn(non_exhaustive_omitted_patterns)] + let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); + //~^ some fields are not explicitly listed + //~^^ some fields are not explicitly listed + + // Ok: this tests https://github.com/rust-lang/rust/issues/89382 + #[warn(non_exhaustive_omitted_patterns)] + let MixedVisFields { a, b, .. } = MixedVisFields::default(); + + // Ok: because this only has 1 variant + #[deny(non_exhaustive_omitted_patterns)] + match NonExhaustiveSingleVariant::A(true) { + NonExhaustiveSingleVariant::A(true) => {} + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match NonExhaustiveSingleVariant::A(true) { + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: we don't lint on `if let` expressions + #[deny(non_exhaustive_omitted_patterns)] + if let NonExhaustiveEnum::Tuple(_) = non_enum {} + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: the feature is on and all variants are matched + #[deny(non_exhaustive_omitted_patterns)] + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + UnstableEnum::Unstable => {} + _ => {} + } + + // Ok: the feature is on and both variants are matched + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::Unstable { + OnlyUnstableEnum::Unstable => {} + OnlyUnstableEnum::Unstable2 => {} + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::Unstable { + OnlyUnstableEnum::Unstable => {} + _ => {} + } + //~^^ some variants are not matched explicitly + + #[warn(non_exhaustive_omitted_patterns)] + let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); + //~^ some fields are not explicitly listed + + // OK: both unstable fields are matched with feature on + #[warn(non_exhaustive_omitted_patterns)] + let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new(); + + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + //~^ some fields are not explicitly listed + + // OK: both unstable and stable fields are matched with feature on + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default(); +} diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr new file mode 100644 index 000000000..996bd4a12 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -0,0 +1,188 @@ +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:102:9 + | +LL | VariantNonExhaustive::Bar { x, .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:99:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:107:9 + | +LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:106:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:115:29 + | +LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:114:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:115:9 + | +LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:173:9 + | +LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:172:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:181:9 + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:180:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:58:9 + | +LL | _ => {} + | ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:57:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:65:9 + | +LL | _ => {} + | ^ pattern `NonExhaustiveEnum::Tuple(_)` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:64:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:75:9 + | +LL | _ => {} + | ^ pattern `NonExhaustiveEnum::Unit` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:74:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:92:32 + | +LL | NestedNonExhaustive::A(_) => {} + | ^ patterns `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:89:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:94:9 + | +LL | _ => {} + | ^ pattern `NestedNonExhaustive::C` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:132:9 + | +LL | _ => {} + | ^ pattern `NonExhaustiveSingleVariant::A(_)` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:130:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:144:9 + | +LL | _ => {} + | ^ pattern `UnstableEnum::Unstable` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:143:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:168:9 + | +LL | _ => {} + | ^ pattern `OnlyUnstableEnum::Unstable2` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:165:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors; 6 warnings emitted + diff --git a/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs new file mode 100644 index 000000000..82ee68687 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs @@ -0,0 +1,45 @@ +// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly with variants +// marked stable and unstable. + +#![feature(non_exhaustive_omitted_patterns_lint)] + +// aux-build:unstable.rs +extern crate unstable; + +use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct}; + +fn main() { + // OK: this matches all the stable variants + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: although this is a bit odd, we don't have anything to report + // since there is no stable variants and the feature is off + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::new() { + _ => {} + } + + // Ok: Same as the above enum (no fields can be matched on) + #[warn(non_exhaustive_omitted_patterns)] + let OnlyUnstableStruct { .. } = OnlyUnstableStruct::new(); + + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, .. } = UnstableStruct::default(); + //~^ some fields are not explicitly listed + + // OK: stable field is matched + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); +} diff --git a/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr new file mode 100644 index 000000000..f38368590 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr @@ -0,0 +1,30 @@ +warning: some fields are not explicitly listed + --> $DIR/stable-omitted-patterns.rs:39:9 + | +LL | let UnstableStruct { stable, .. } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `stable2` not listed + | + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/stable-omitted-patterns.rs:38:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/stable-omitted-patterns.rs:23:9 + | +LL | _ => {} + | ^ pattern `UnstableEnum::Stable2` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/stable-omitted-patterns.rs:22:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.rs b/tests/ui/rfc-2008-non-exhaustive/struct.rs new file mode 100644 index 000000000..07e093c15 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/struct.rs @@ -0,0 +1,49 @@ +// aux-build:structs.rs +extern crate structs; + +use structs::{NormalStruct, UnitStruct, TupleStruct, FunctionalRecord}; + +fn main() { + let fr = FunctionalRecord { + //~^ ERROR cannot create non-exhaustive struct + first_field: 1920, + second_field: 1080, + ..FunctionalRecord::default() + }; + + let ns = NormalStruct { first_field: 640, second_field: 480 }; + //~^ ERROR cannot create non-exhaustive struct + + let NormalStruct { first_field, second_field } = ns; + //~^ ERROR `..` required with struct marked as non-exhaustive + + let ts = TupleStruct(640, 480); + //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423] + + let ts_explicit = structs::TupleStruct(640, 480); + //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603] + + let TupleStruct { 0: first_field, 1: second_field } = ts; + //~^ ERROR `..` required with struct marked as non-exhaustive + + let us = UnitStruct; + //~^ ERROR expected value, found struct `UnitStruct` [E0423] + + let us_explicit = structs::UnitStruct; + //~^ ERROR unit struct `UnitStruct` is private [E0603] + + let UnitStruct { } = us; + //~^ ERROR `..` required with struct marked as non-exhaustive +} + +// Everything below this is expected to compile successfully. + +// We only test matching here as we cannot create non-exhaustive +// structs from another crate. ie. they'll never pass in run-pass tests. +fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) { + let NormalStruct { first_field, second_field, .. } = ns; + + let TupleStruct { 0: first, 1: second, .. } = ts; + + let UnitStruct { .. } = us; +} diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr new file mode 100644 index 000000000..2cb9ba0d1 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr @@ -0,0 +1,96 @@ +error[E0423]: expected value, found struct `UnitStruct` + --> $DIR/struct.rs:29:14 + | +LL | let us = UnitStruct; + | ^^^^^^^^^^ constructor is not visible here due to private fields + +error[E0603]: tuple struct constructor `TupleStruct` is private + --> $DIR/struct.rs:23:32 + | +LL | let ts_explicit = structs::TupleStruct(640, 480); + | ^^^^^^^^^^^ private tuple struct constructor + | + ::: $DIR/auxiliary/structs.rs:12:24 + | +LL | pub struct TupleStruct(pub u16, pub u16); + | ---------------- a constructor is private if any of the fields is private + | +note: the tuple struct constructor `TupleStruct` is defined here + --> $DIR/auxiliary/structs.rs:12:1 + | +LL | pub struct TupleStruct(pub u16, pub u16); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0603]: unit struct `UnitStruct` is private + --> $DIR/struct.rs:32:32 + | +LL | let us_explicit = structs::UnitStruct; + | ^^^^^^^^^^ private unit struct + | +note: the unit struct `UnitStruct` is defined here + --> $DIR/auxiliary/structs.rs:9:1 + | +LL | pub struct UnitStruct; + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0639]: cannot create non-exhaustive struct using struct expression + --> $DIR/struct.rs:7:14 + | +LL | let fr = FunctionalRecord { + | ______________^ +LL | | +LL | | first_field: 1920, +LL | | second_field: 1080, +LL | | ..FunctionalRecord::default() +LL | | }; + | |_____^ + +error[E0639]: cannot create non-exhaustive struct using struct expression + --> $DIR/struct.rs:14:14 + | +LL | let ns = NormalStruct { first_field: 640, second_field: 480 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0638]: `..` required with struct marked as non-exhaustive + --> $DIR/struct.rs:17:9 + | +LL | let NormalStruct { first_field, second_field } = ns; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let NormalStruct { first_field, second_field , .. } = ns; + | ~~~~~~ + +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/struct.rs:20:14 + | +LL | let ts = TupleStruct(640, 480); + | ^^^^^^^^^^^ + +error[E0638]: `..` required with struct marked as non-exhaustive + --> $DIR/struct.rs:26:9 + | +LL | let TupleStruct { 0: first_field, 1: second_field } = ts; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts; + | ~~~~~~ + +error[E0638]: `..` required with struct marked as non-exhaustive + --> $DIR/struct.rs:35:9 + | +LL | let UnitStruct { } = us; + | ^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let UnitStruct { .. } = us; + | ~~~~ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0423, E0603, E0638, E0639. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs new file mode 100644 index 000000000..5f76b0cb2 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs @@ -0,0 +1,32 @@ +// run-pass + +#![allow(unused_variables)] + +#[non_exhaustive] +pub struct NormalStruct { + pub first_field: u16, + pub second_field: u16, +} + +#[non_exhaustive] +pub struct UnitStruct; + +#[non_exhaustive] +pub struct TupleStruct (pub u16, pub u16); + +fn main() { + let ns = NormalStruct { first_field: 640, second_field: 480 }; + + let NormalStruct { first_field, second_field } = ns; + + let ts = TupleStruct { 0: 340, 1: 480 }; + let ts_constructor = TupleStruct(340, 480); + + let TupleStruct { 0: first, 1: second } = ts; + let TupleStruct(first, second) = ts_constructor; + + let us = UnitStruct {}; + let us_constructor = UnitStruct; + + let UnitStruct { } = us; +} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs new file mode 100644 index 000000000..a2735d4cb --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs @@ -0,0 +1,32 @@ +#![crate_type = "rlib"] +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs new file mode 100644 index 000000000..80b9dc4c1 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs @@ -0,0 +1,38 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +// This test checks that uninhabited non-exhaustive types cannot coerce to any type, as the never +// type can. + +struct A; + +fn can_coerce_never_type_to_anything(x: !) -> A { + x +} + +fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + x //~ ERROR mismatched types +} + +fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + x //~ ERROR mismatched types +} + +fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + x //~ ERROR mismatched types +} + +fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + x //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr new file mode 100644 index 000000000..f8ed156b5 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/coercions.rs:23:5 + | +LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedEnum` + +error[E0308]: mismatched types + --> $DIR/coercions.rs:27:5 + | +LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedTupleStruct` + +error[E0308]: mismatched types + --> $DIR/coercions.rs:31:5 + | +LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedStruct` + +error[E0308]: mismatched types + --> $DIR/coercions.rs:35:5 + | +LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedVariants` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs new file mode 100644 index 000000000..6b911dd98 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs @@ -0,0 +1,45 @@ +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +struct A; + +// This test checks that uninhabited non-exhaustive types defined in the same crate cannot coerce +// to any type, as the never type can. + +fn can_coerce_never_type_to_anything(x: !) -> A { + x +} + +fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + x //~ ERROR mismatched types +} + +fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + x //~ ERROR mismatched types +} + +fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + x //~ ERROR mismatched types +} + +fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + x //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr new file mode 100644 index 000000000..fd2c56974 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/coercions_same_crate.rs:30:5 + | +LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedEnum` + +error[E0308]: mismatched types + --> $DIR/coercions_same_crate.rs:34:5 + | +LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedTupleStruct` + +error[E0308]: mismatched types + --> $DIR/coercions_same_crate.rs:38:5 + | +LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedStruct` + +error[E0308]: mismatched types + --> $DIR/coercions_same_crate.rs:42:5 + | +LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedVariants` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs new file mode 100644 index 000000000..98a7fdbc5 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs @@ -0,0 +1,36 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + IndirectUninhabitedEnum, + IndirectUninhabitedStruct, + IndirectUninhabitedTupleStruct, + IndirectUninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from an extern crate will not compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr new file mode 100644 index 000000000..66e93291c --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -0,0 +1,79 @@ +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty + --> $DIR/indirect_match.rs:19:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedEnum` defined here + --> $DIR/auxiliary/uninhabited.rs:26:1 + | +LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty + --> $DIR/indirect_match.rs:23:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:28:1 + | +LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty + --> $DIR/indirect_match.rs:27:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedTupleStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:30:1 + | +LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedTupleStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty + --> $DIR/indirect_match.rs:33:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedVariants` defined here + --> $DIR/auxiliary/uninhabited.rs:32:1 + | +LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs new file mode 100644 index 000000000..8f090fe88 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs @@ -0,0 +1,51 @@ +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from the defining crate will not compile without `#![feature(exhaustive_patterns)]`. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr new file mode 100644 index 000000000..c12190541 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr @@ -0,0 +1,79 @@ +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty + --> $DIR/indirect_match_same_crate.rs:34:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedEnum` defined here + --> $DIR/indirect_match_same_crate.rs:20:12 + | +LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty + --> $DIR/indirect_match_same_crate.rs:38:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedStruct` defined here + --> $DIR/indirect_match_same_crate.rs:22:12 + | +LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty + --> $DIR/indirect_match_same_crate.rs:42:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedTupleStruct` defined here + --> $DIR/indirect_match_same_crate.rs:24:12 + | +LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedTupleStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty + --> $DIR/indirect_match_same_crate.rs:48:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedVariants` defined here + --> $DIR/indirect_match_same_crate.rs:26:12 + | +LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs new file mode 100644 index 000000000..be86519ec --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs @@ -0,0 +1,40 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + IndirectUninhabitedEnum, + IndirectUninhabitedStruct, + IndirectUninhabitedTupleStruct, + IndirectUninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from an extern crate will not compile. In particular, this enables the +// `exhaustive_patterns` feature as this can change the branch used in the compiler to determine +// this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr new file mode 100644 index 000000000..ef97c1fa1 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr @@ -0,0 +1,79 @@ +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:23:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedEnum` defined here + --> $DIR/auxiliary/uninhabited.rs:26:1 + | +LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedEnum` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:28:1 + | +LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedTupleStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:30:1 + | +LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedTupleStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11 + | +LL | match x {} + | ^ + | +note: `IndirectUninhabitedVariants` defined here + --> $DIR/auxiliary/uninhabited.rs:32:1 + | +LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `IndirectUninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs new file mode 100644 index 000000000..60289aa78 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs @@ -0,0 +1,57 @@ +// check-pass + +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. +// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs new file mode 100644 index 000000000..230ac7529 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs @@ -0,0 +1,21 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::PartiallyInhabitedVariants; + +// This test checks a redundant/useless pattern of a non-exhaustive enum/variant is still +// warned against. + +pub fn foo(x: PartiallyInhabitedVariants) { + match x { + PartiallyInhabitedVariants::Struct { .. } => {}, + PartiallyInhabitedVariants::Struct { .. } => {}, + //~^ ERROR unreachable pattern + _ => {}, + } +} + +fn main() { } diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr new file mode 100644 index 000000000..f39e6ee29 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/issue-65157-repeated-match-arm.rs:15:9 + | +LL | PartiallyInhabitedVariants::Struct { .. } => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-65157-repeated-match-arm.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs new file mode 100644 index 000000000..e54098d4d --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs @@ -0,0 +1,34 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate +// will not compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr new file mode 100644 index 000000000..a9c54af04 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -0,0 +1,83 @@ +error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty + --> $DIR/match.rs:19:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedEnum` defined here + --> $DIR/auxiliary/uninhabited.rs:5:1 + | +LL | pub enum UninhabitedEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty + --> $DIR/match.rs:23:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:9:1 + | +LL | pub struct UninhabitedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty + --> $DIR/match.rs:27:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedTupleStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:14:1 + | +LL | pub struct UninhabitedTupleStruct(!); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedTupleStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered + --> $DIR/match.rs:31:11 + | +LL | match x {} + | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered + | +note: `UninhabitedVariants` defined here + --> $DIR/auxiliary/uninhabited.rs:17:23 + | +LL | pub enum UninhabitedVariants { + | ---------------------------- +LL | #[non_exhaustive] Tuple(!), + | ^^^^^ not covered +LL | #[non_exhaustive] Struct { x: ! } + | ^^^^^^ not covered + = note: the matched value is of type `UninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match x { +LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), +LL ~ } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs new file mode 100644 index 000000000..ebbdfba15 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs @@ -0,0 +1,41 @@ +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr new file mode 100644 index 000000000..ec2a2f6f0 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -0,0 +1,64 @@ +error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty + --> $DIR/match_same_crate.rs:30:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedStruct` defined here + --> $DIR/match_same_crate.rs:8:12 + | +LL | pub struct UninhabitedStruct { + | ^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty + --> $DIR/match_same_crate.rs:34:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedTupleStruct` defined here + --> $DIR/match_same_crate.rs:13:12 + | +LL | pub struct UninhabitedTupleStruct(!); + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedTupleStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered + --> $DIR/match_same_crate.rs:38:11 + | +LL | match x {} + | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered + | +note: `UninhabitedVariants` defined here + --> $DIR/match_same_crate.rs:16:23 + | +LL | pub enum UninhabitedVariants { + | ------------------- +LL | #[non_exhaustive] Tuple(!), + | ^^^^^ not covered +LL | #[non_exhaustive] Struct { x: ! } + | ^^^^^^ not covered + = note: the matched value is of type `UninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match x { +LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), +LL ~ } + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs new file mode 100644 index 000000000..900dfff65 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs @@ -0,0 +1,37 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate +// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr new file mode 100644 index 000000000..b6b777ec5 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -0,0 +1,83 @@ +error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:22:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedEnum` defined here + --> $DIR/auxiliary/uninhabited.rs:5:1 + | +LL | pub enum UninhabitedEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:26:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:9:1 + | +LL | pub struct UninhabitedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:30:11 + | +LL | match x {} + | ^ + | +note: `UninhabitedTupleStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:14:1 + | +LL | pub struct UninhabitedTupleStruct(!); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `UninhabitedTupleStruct` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered + --> $DIR/match_with_exhaustive_patterns.rs:34:11 + | +LL | match x {} + | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered + | +note: `UninhabitedVariants` defined here + --> $DIR/auxiliary/uninhabited.rs:17:23 + | +LL | pub enum UninhabitedVariants { + | ---------------------------- +LL | #[non_exhaustive] Tuple(!), + | ^^^^^ not covered +LL | #[non_exhaustive] Struct { x: ! } + | ^^^^^^ not covered + = note: the matched value is of type `UninhabitedVariants` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match x { +LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), +LL ~ } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs new file mode 100644 index 000000000..de5530485 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs @@ -0,0 +1,47 @@ +// check-pass + +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. +// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} +} + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs new file mode 100644 index 000000000..221b5cf6b --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs @@ -0,0 +1,59 @@ +// aux-build:uninhabited.rs +// build-pass (FIXME(62277): could be check-pass?) +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] + +extern crate uninhabited; + +use uninhabited::{ + PartiallyInhabitedVariants, + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are not considered uninhabited from extern crates. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), // This line would normally error. + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), // This line would normally error. + None => (), + } + + // This line would normally error. + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { + } + + while let Some(_x) = uninhabited_struct() { // This line would normally error. + } + + while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs new file mode 100644 index 000000000..ffc496a97 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs @@ -0,0 +1,70 @@ +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are still considered uninhabited. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + //~^ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern + } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr new file mode 100644 index 000000000..8bfd6e91f --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -0,0 +1,38 @@ +error: unreachable pattern + --> $DIR/patterns_same_crate.rs:52:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/patterns_same_crate.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/patterns_same_crate.rs:57:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/patterns_same_crate.rs:61:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/patterns_same_crate.rs:65:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/patterns_same_crate.rs:68:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.rs b/tests/ui/rfc-2008-non-exhaustive/variant.rs new file mode 100644 index 000000000..bc346aea5 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/variant.rs @@ -0,0 +1,33 @@ +// aux-build:variants.rs + +extern crate variants; + +use variants::NonExhaustiveVariants; + +fn main() { + let variant_struct = NonExhaustiveVariants::Struct { field: 640 }; + //~^ ERROR cannot create non-exhaustive variant + + let variant_tuple = NonExhaustiveVariants::Tuple(640); + //~^ ERROR tuple variant `Tuple` is private [E0603] + + let variant_unit = NonExhaustiveVariants::Unit; + //~^ ERROR unit variant `Unit` is private [E0603] + + match variant_struct { + NonExhaustiveVariants::Unit => "", + //~^ ERROR unit variant `Unit` is private [E0603] + NonExhaustiveVariants::Tuple(fe_tpl) => "", + //~^ ERROR tuple variant `Tuple` is private [E0603] + NonExhaustiveVariants::Struct { field } => "" + //~^ ERROR `..` required with variant marked as non-exhaustive + }; + + if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { + //~^ ERROR tuple variant `Tuple` is private [E0603] + } + + if let NonExhaustiveVariants::Struct { field } = variant_struct { + //~^ ERROR `..` required with variant marked as non-exhaustive + } +} diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr new file mode 100644 index 000000000..720b7b119 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr @@ -0,0 +1,92 @@ +error[E0603]: tuple variant `Tuple` is private + --> $DIR/variant.rs:11:48 + | +LL | let variant_tuple = NonExhaustiveVariants::Tuple(640); + | ^^^^^ private tuple variant + | +note: the tuple variant `Tuple` is defined here + --> $DIR/auxiliary/variants.rs:5:23 + | +LL | #[non_exhaustive] Tuple(u32), + | ^^^^^ + +error[E0603]: unit variant `Unit` is private + --> $DIR/variant.rs:14:47 + | +LL | let variant_unit = NonExhaustiveVariants::Unit; + | ^^^^ private unit variant + | +note: the unit variant `Unit` is defined here + --> $DIR/auxiliary/variants.rs:4:23 + | +LL | #[non_exhaustive] Unit, + | ^^^^ + +error[E0603]: unit variant `Unit` is private + --> $DIR/variant.rs:18:32 + | +LL | NonExhaustiveVariants::Unit => "", + | ^^^^ private unit variant + | +note: the unit variant `Unit` is defined here + --> $DIR/auxiliary/variants.rs:4:23 + | +LL | #[non_exhaustive] Unit, + | ^^^^ + +error[E0603]: tuple variant `Tuple` is private + --> $DIR/variant.rs:20:32 + | +LL | NonExhaustiveVariants::Tuple(fe_tpl) => "", + | ^^^^^ private tuple variant + | +note: the tuple variant `Tuple` is defined here + --> $DIR/auxiliary/variants.rs:5:23 + | +LL | #[non_exhaustive] Tuple(u32), + | ^^^^^ + +error[E0603]: tuple variant `Tuple` is private + --> $DIR/variant.rs:26:35 + | +LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { + | ^^^^^ private tuple variant + | +note: the tuple variant `Tuple` is defined here + --> $DIR/auxiliary/variants.rs:5:23 + | +LL | #[non_exhaustive] Tuple(u32), + | ^^^^^ + +error[E0639]: cannot create non-exhaustive variant using struct expression + --> $DIR/variant.rs:8:26 + | +LL | let variant_struct = NonExhaustiveVariants::Struct { field: 640 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0638]: `..` required with variant marked as non-exhaustive + --> $DIR/variant.rs:22:9 + | +LL | NonExhaustiveVariants::Struct { field } => "" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | NonExhaustiveVariants::Struct { field , .. } => "" + | ~~~~~~ + +error[E0638]: `..` required with variant marked as non-exhaustive + --> $DIR/variant.rs:30:12 + | +LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct { + | ~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0603, E0638, E0639. +For more information about an error, try `rustc --explain E0603`. diff --git a/tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs b/tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs new file mode 100644 index 000000000..dacaf489a --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:variants.rs + +extern crate variants; + +const S: u8 = 0; + +// OK, `Struct` in value namespace is crate-private, so it's filtered away +// and there's no conflict with the previously defined `const S`. +use variants::NonExhaustiveVariants::Struct as S; + +fn main() {} diff --git a/tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs new file mode 100644 index 000000000..5f2816ec6 --- /dev/null +++ b/tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs @@ -0,0 +1,18 @@ +// run-pass + +pub enum NonExhaustiveVariants { + #[non_exhaustive] Unit, + #[non_exhaustive] Tuple(u32), + #[non_exhaustive] Struct { field: u32 } +} + +fn main() { + let variant_tuple = NonExhaustiveVariants::Tuple(340); + let _variant_struct = NonExhaustiveVariants::Struct { field: 340 }; + + match variant_tuple { + NonExhaustiveVariants::Unit => "", + NonExhaustiveVariants::Tuple(_fe_tpl) => "", + NonExhaustiveVariants::Struct { field: _ } => "" + }; +} diff --git a/tests/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs new file mode 100644 index 000000000..fa04f4b12 --- /dev/null +++ b/tests/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs @@ -0,0 +1,23 @@ +// Check that we if we get ahold of an object unsafe trait +// object with auto traits and lifetimes, we can downcast it +// +// check-pass + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { + t +} + +fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) + -> &'b (dyn Trait + 't) +where + 'a: 'b, + 't: 'a + 'b, +{ + t +} + +fn main() {} diff --git a/tests/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs new file mode 100644 index 000000000..721890db4 --- /dev/null +++ b/tests/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -0,0 +1,66 @@ +// Check that we can manually implement an object-unsafe trait for its trait object. + +// run-pass + +#![feature(object_safe_for_dispatch)] + +trait Bad { + fn stat() -> char { + 'A' + } + fn virt(&self) -> char { + 'B' + } + fn indirect(&self) -> char { + Self::stat() + } +} + +trait Good { + fn good_virt(&self) -> char { + panic!() + } + fn good_indirect(&self) -> char { + panic!() + } +} + +impl<'a> Bad for dyn Bad + 'a { + fn stat() -> char { + 'C' + } + fn virt(&self) -> char { + 'D' + } +} + +struct Struct {} + +impl Bad for Struct {} + +impl Good for Struct {} + +fn main() { + let s = Struct {}; + + let mut res = String::new(); + + // Directly call static. + res.push(Struct::stat()); // "A" + res.push(::stat()); // "AC" + + let good: &dyn Good = &s; + + // These look similar enough... + let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; + + // Call virtual. + res.push(s.virt()); // "ACB" + res.push(bad.virt()); // "ACBD" + + // Indirectly call static. + res.push(s.indirect()); // "ACBDA" + res.push(bad.indirect()); // "ACBDAC" + + assert_eq!(&res, "ACBDAC"); +} diff --git a/tests/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs new file mode 100644 index 000000000..df97d2c13 --- /dev/null +++ b/tests/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs @@ -0,0 +1,37 @@ +// Check that we can statically dispatch methods for object +// unsafe trait objects, directly and indirectly +// +// check-pass + +#![feature(object_safe_for_dispatch)] + +trait Statics { + fn plain() {} + fn generic() {} +} + +trait Trait: Sized {} + +impl<'a> Statics for dyn Trait + 'a {} + +fn static_poly() { + T::plain(); + T::generic::(); +} + +fn inferred_poly(t: &T) { + static_poly::(); + T::plain(); + T::generic::(); +} + +fn call(t: &dyn Trait) { + static_poly::(); + inferred_poly(t); +} + +fn main() { + static_poly::(); + ::plain(); + ::generic::() +} diff --git a/tests/ui/rfc-2091-track-caller/call-chain.rs b/tests/ui/rfc-2091-track-caller/call-chain.rs new file mode 100644 index 000000000..28b3f76c9 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/call-chain.rs @@ -0,0 +1,30 @@ +// run-pass +// revisions: default mir-opt +//[default] compile-flags: -Zinline-mir=no +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +use std::panic::Location; + +struct Foo; + +impl Foo { + #[inline(always)] + #[track_caller] + fn check_loc(&self, line: u32, col: u32) -> &Self { + let loc = Location::caller(); + assert_eq!(loc.file(), file!(), "file mismatch"); + assert_eq!(loc.line(), line, "line mismatch"); + assert_eq!(loc.column(), col, "column mismatch"); + self + } +} + +fn main() { + // Tests that when `Location::caller` is used in a method chain, + // it points to the start of the correct call (the first character after the dot) + // instead of to the very first expression in the chain + let foo = Foo; + foo. + check_loc(line!(), 9).check_loc(line!(), 31) + .check_loc(line!(), 10); +} diff --git a/tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs b/tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs new file mode 100644 index 000000000..a3bed707e --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.rs @@ -0,0 +1,32 @@ +// Ensure that a `#[track_caller]` function, returning `caller_location()`, +// which coerced (to a function pointer) and called, inside a `const fn`, +// in turn called, results in the same output irrespective of whether +// we're in a const or runtime context. + +// run-pass +// compile-flags: -Z unleash-the-miri-inside-of-you + +#![feature(core_intrinsics, const_caller_location)] + +type L = &'static std::panic::Location<'static>; + +#[track_caller] +const fn attributed() -> L { + std::intrinsics::caller_location() +} + +const fn calling_attributed() -> L { + // We need `-Z unleash-the-miri-inside-of-you` for this as we don't have `const fn` pointers. + let ptr: fn() -> L = attributed; + ptr() +} + +fn main() { + const CONSTANT: L = calling_attributed(); + let runtime = calling_attributed(); + + assert_eq!( + (runtime.file(), runtime.line(), runtime.column()), + (CONSTANT.file(), CONSTANT.line(), CONSTANT.column()), + ); +} diff --git a/tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr b/tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr new file mode 100644 index 000000000..cf8ca5771 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr @@ -0,0 +1,10 @@ +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5 + | +LL | ptr() + | ^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-2091-track-caller/caller-location-intrinsic.rs b/tests/ui/rfc-2091-track-caller/caller-location-intrinsic.rs new file mode 100644 index 000000000..e5754d355 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/caller-location-intrinsic.rs @@ -0,0 +1,27 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +#[inline(never)] +#[track_caller] +fn codegen_caller_loc() -> &'static core::panic::Location<'static> { + core::panic::Location::caller() +} + +macro_rules! caller_location_from_macro { + () => (codegen_caller_loc()); +} + +fn main() { + let loc = codegen_caller_loc(); + assert_eq!(loc.file(), file!()); + assert_eq!(loc.line(), 16); + assert_eq!(loc.column(), 15); + + // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, + // i.e. point to where the macro was invoked, instead of the macro itself. + let loc2 = caller_location_from_macro!(); + assert_eq!(loc2.file(), file!()); + assert_eq!(loc2.line(), 23); + assert_eq!(loc2.column(), 16); +} diff --git a/tests/ui/rfc-2091-track-caller/const-caller-location.rs b/tests/ui/rfc-2091-track-caller/const-caller-location.rs new file mode 100644 index 000000000..6e15cf3fe --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/const-caller-location.rs @@ -0,0 +1,43 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +#![feature(const_caller_location)] + +use std::panic::Location; + +const LOCATION: &Location = Location::caller(); + +const TRACKED: &Location = tracked(); +#[track_caller] +const fn tracked() -> &'static Location <'static> { + Location::caller() +} + +const NESTED: &Location = nested_location(); +const fn nested_location() -> &'static Location<'static> { + Location::caller() +} + +const CONTAINED: &Location = contained(); +const fn contained() -> &'static Location<'static> { + tracked() +} + +fn main() { + assert_eq!(LOCATION.file(), file!()); + assert_eq!(LOCATION.line(), 9); + assert_eq!(LOCATION.column(), 29); + + assert_eq!(TRACKED.file(), file!()); + assert_eq!(TRACKED.line(), 11); + assert_eq!(TRACKED.column(), 28); + + assert_eq!(NESTED.file(), file!()); + assert_eq!(NESTED.line(), 19); + assert_eq!(NESTED.column(), 5); + + assert_eq!(CONTAINED.file(), file!()); + assert_eq!(CONTAINED.line(), 24); + assert_eq!(CONTAINED.column(), 5); +} diff --git a/tests/ui/rfc-2091-track-caller/diverging-caller-location.rs b/tests/ui/rfc-2091-track-caller/diverging-caller-location.rs new file mode 100644 index 000000000..668111955 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/diverging-caller-location.rs @@ -0,0 +1,17 @@ +// run-fail + +//! This test ensures that `#[track_caller]` can be applied directly to diverging functions, as +//! the tracking issue says: https://github.com/rust-lang/rust/issues/47809#issue-292138490. +//! Because the annotated function must diverge and a panic keeps that faster than an infinite loop, +//! we don't inspect the location returned -- it would be difficult to distinguish between the +//! explicit panic and a failed assertion. That it compiles and runs is enough for this one. + +#[track_caller] +fn doesnt_return() -> ! { + let _location = core::panic::Location::caller(); + panic!("huzzah"); +} + +fn main() { + doesnt_return(); +} diff --git a/tests/ui/rfc-2091-track-caller/error-odd-syntax.rs b/tests/ui/rfc-2091-track-caller/error-odd-syntax.rs new file mode 100644 index 000000000..6f4290e2a --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -0,0 +1,5 @@ +#[track_caller(1)] +fn f() {} +//~^^ ERROR malformed `track_caller` attribute input + +fn main() {} diff --git a/tests/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/tests/ui/rfc-2091-track-caller/error-odd-syntax.stderr new file mode 100644 index 000000000..e7ddf8df4 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -0,0 +1,8 @@ +error: malformed `track_caller` attribute input + --> $DIR/error-odd-syntax.rs:1:1 + | +LL | #[track_caller(1)] + | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/tests/ui/rfc-2091-track-caller/error-with-invalid-abi.rs new file mode 100644 index 000000000..074e1ceb7 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -0,0 +1,11 @@ +#[track_caller] +extern "C" fn f() {} +//~^^ ERROR `#[track_caller]` requires Rust ABI + +extern "C" { + #[track_caller] + fn g(); + //~^^ ERROR `#[track_caller]` requires Rust ABI +} + +fn main() {} diff --git a/tests/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/tests/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr new file mode 100644 index 000000000..bcc0c8170 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -0,0 +1,15 @@ +error[E0737]: `#[track_caller]` requires Rust ABI + --> $DIR/error-with-invalid-abi.rs:1:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error[E0737]: `#[track_caller]` requires Rust ABI + --> $DIR/error-with-invalid-abi.rs:6:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0737`. diff --git a/tests/ui/rfc-2091-track-caller/error-with-main.rs b/tests/ui/rfc-2091-track-caller/error-with-main.rs new file mode 100644 index 000000000..b2ea31bb5 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-main.rs @@ -0,0 +1,4 @@ +#[track_caller] //~ ERROR `main` function is not allowed to be +fn main() { + panic!("{}: oh no", std::panic::Location::caller()); +} diff --git a/tests/ui/rfc-2091-track-caller/error-with-main.stderr b/tests/ui/rfc-2091-track-caller/error-with-main.stderr new file mode 100644 index 000000000..7e2ec3524 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-main.stderr @@ -0,0 +1,10 @@ +error: `main` function is not allowed to be `#[track_caller]` + --> $DIR/error-with-main.rs:1:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | fn main() { + | --------- `main` function is not allowed to be `#[track_caller]` + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfc-2091-track-caller/error-with-naked.rs new file mode 100644 index 000000000..43e33cbb1 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-naked.rs @@ -0,0 +1,24 @@ +// needs-asm-support +#![feature(naked_functions)] + +use std::arch::asm; + +#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` +//~^ ERROR `#[track_caller]` requires Rust ABI +#[naked] +extern "C" fn f() { + asm!("", options(noreturn)); +} + +struct S; + +impl S { + #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]` + //~^ ERROR `#[track_caller]` requires Rust ABI + #[naked] + extern "C" fn g() { + asm!("", options(noreturn)); + } +} + +fn main() {} diff --git a/tests/ui/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfc-2091-track-caller/error-with-naked.stderr new file mode 100644 index 000000000..3f7d0df42 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -0,0 +1,28 @@ +error[E0736]: cannot use `#[track_caller]` with `#[naked]` + --> $DIR/error-with-naked.rs:6:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error[E0736]: cannot use `#[track_caller]` with `#[naked]` + --> $DIR/error-with-naked.rs:16:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error[E0737]: `#[track_caller]` requires Rust ABI + --> $DIR/error-with-naked.rs:6:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error[E0737]: `#[track_caller]` requires Rust ABI + --> $DIR/error-with-naked.rs:16:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0736, E0737. +For more information about an error, try `rustc --explain E0736`. diff --git a/tests/ui/rfc-2091-track-caller/error-with-start.rs b/tests/ui/rfc-2091-track-caller/error-with-start.rs new file mode 100644 index 000000000..0cab47170 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-start.rs @@ -0,0 +1,7 @@ +#![feature(start)] + +#[start] +#[track_caller] //~ ERROR `start` is not allowed to be `#[track_caller]` +fn start(_argc: isize, _argv: *const *const u8) -> isize { + panic!("{}: oh no", std::panic::Location::caller()); +} diff --git a/tests/ui/rfc-2091-track-caller/error-with-start.stderr b/tests/ui/rfc-2091-track-caller/error-with-start.stderr new file mode 100644 index 000000000..454c98ff9 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/error-with-start.stderr @@ -0,0 +1,10 @@ +error: `start` is not allowed to be `#[track_caller]` + --> $DIR/error-with-start.rs:4:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { + | -------------------------------------------------------- `start` is not allowed to be `#[track_caller]` + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2091-track-caller/intrinsic-wrapper.rs b/tests/ui/rfc-2091-track-caller/intrinsic-wrapper.rs new file mode 100644 index 000000000..87e52881c --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/intrinsic-wrapper.rs @@ -0,0 +1,21 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +macro_rules! caller_location_from_macro { + () => (core::panic::Location::caller()); +} + +fn main() { + let loc = core::panic::Location::caller(); + assert_eq!(loc.file(), file!()); + assert_eq!(loc.line(), 10); + assert_eq!(loc.column(), 15); + + // `Location::caller()` in a macro should behave similarly to `file!` and `line!`, + // i.e. point to where the macro was invoked, instead of the macro itself. + let loc2 = caller_location_from_macro!(); + assert_eq!(loc2.file(), file!()); + assert_eq!(loc2.line(), 17); + assert_eq!(loc2.column(), 16); +} diff --git a/tests/ui/rfc-2091-track-caller/macro-declaration.rs b/tests/ui/rfc-2091-track-caller/macro-declaration.rs new file mode 100644 index 000000000..6ca09fac8 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/macro-declaration.rs @@ -0,0 +1,10 @@ +// check-pass + +// See https://github.com/rust-lang/rust/issues/95151 +#[track_caller] +macro_rules! _foo { + () => {}; +} + +fn main() { +} diff --git a/tests/ui/rfc-2091-track-caller/only-for-fns.rs b/tests/ui/rfc-2091-track-caller/only-for-fns.rs new file mode 100644 index 000000000..2d2b01b6f --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/only-for-fns.rs @@ -0,0 +1,5 @@ +#[track_caller] +struct S; +//~^^ ERROR attribute should be applied to a function definition + +fn main() {} diff --git a/tests/ui/rfc-2091-track-caller/only-for-fns.stderr b/tests/ui/rfc-2091-track-caller/only-for-fns.stderr new file mode 100644 index 000000000..b36597bde --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -0,0 +1,11 @@ +error[E0739]: attribute should be applied to a function definition + --> $DIR/only-for-fns.rs:1:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | struct S; + | --------- not a function definition + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0739`. diff --git a/tests/ui/rfc-2091-track-caller/pass.rs b/tests/ui/rfc-2091-track-caller/pass.rs new file mode 100644 index 000000000..1b13ea3e9 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/pass.rs @@ -0,0 +1,10 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +#[track_caller] +fn f() {} + +fn main() { + f(); +} diff --git a/tests/ui/rfc-2091-track-caller/std-panic-locations.rs b/tests/ui/rfc-2091-track-caller/std-panic-locations.rs new file mode 100644 index 000000000..f11456250 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/std-panic-locations.rs @@ -0,0 +1,64 @@ +// run-pass +// needs-unwind +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +#![allow(unconditional_panic)] + +//! Test that panic locations for `#[track_caller]` functions in std have the correct +//! location reported. + +use std::cell::RefCell; +use std::collections::{BTreeMap, HashMap, VecDeque}; +use std::ops::{Index, IndexMut}; +use std::panic::{AssertUnwindSafe, UnwindSafe}; + +fn main() { + // inspect the `PanicInfo` we receive to ensure the right file is the source + std::panic::set_hook(Box::new(|info| { + let actual = info.location().unwrap(); + if actual.file() != file!() { + eprintln!("expected a location in the test file, found {:?}", actual); + panic!(); + } + })); + + fn assert_panicked(f: impl FnOnce() + UnwindSafe) { + std::panic::catch_unwind(f).unwrap_err(); + } + + let nope: Option<()> = None; + assert_panicked(|| nope.unwrap()); + assert_panicked(|| nope.expect("")); + + let oops: Result<(), ()> = Err(()); + assert_panicked(|| oops.unwrap()); + assert_panicked(|| oops.expect("")); + + let fine: Result<(), ()> = Ok(()); + assert_panicked(|| fine.unwrap_err()); + assert_panicked(|| fine.expect_err("")); + + let mut small = [0]; // the implementation backing str, vec, etc + assert_panicked(move || { small.index(1); }); + assert_panicked(move || { small[1]; }); + assert_panicked(move || { small.index_mut(1); }); + assert_panicked(move || { small[1] += 1; }); + + let sorted: BTreeMap = Default::default(); + assert_panicked(|| { sorted.index(&false); }); + assert_panicked(|| { sorted[&false]; }); + + let unsorted: HashMap = Default::default(); + assert_panicked(|| { unsorted.index(&false); }); + assert_panicked(|| { unsorted[&false]; }); + + let weirdo: VecDeque<()> = Default::default(); + assert_panicked(|| { weirdo.index(1); }); + assert_panicked(|| { weirdo[1]; }); + + let refcell: RefCell<()> = Default::default(); + let _conflicting = refcell.borrow_mut(); + assert_panicked(AssertUnwindSafe(|| { refcell.borrow(); })); + assert_panicked(AssertUnwindSafe(|| { refcell.borrow_mut(); })); +} diff --git a/tests/ui/rfc-2091-track-caller/track-caller-attribute.rs b/tests/ui/rfc-2091-track-caller/track-caller-attribute.rs new file mode 100644 index 000000000..9d28eb9de --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/track-caller-attribute.rs @@ -0,0 +1,40 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +use std::panic::Location; + +#[track_caller] +fn tracked() -> &'static Location<'static> { + Location::caller() +} + +fn nested_intrinsic() -> &'static Location<'static> { + Location::caller() +} + +fn nested_tracked() -> &'static Location<'static> { + tracked() +} + +fn main() { + let location = Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), 21); + assert_eq!(location.column(), 20); + + let tracked = tracked(); + assert_eq!(tracked.file(), file!()); + assert_eq!(tracked.line(), 26); + assert_eq!(tracked.column(), 19); + + let nested = nested_intrinsic(); + assert_eq!(nested.file(), file!()); + assert_eq!(nested.line(), 13); + assert_eq!(nested.column(), 5); + + let contained = nested_tracked(); + assert_eq!(contained.file(), file!()); + assert_eq!(contained.line(), 17); + assert_eq!(contained.column(), 5); +} diff --git a/tests/ui/rfc-2091-track-caller/track-caller-ffi.rs b/tests/ui/rfc-2091-track-caller/track-caller-ffi.rs new file mode 100644 index 000000000..5115f687c --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/track-caller-ffi.rs @@ -0,0 +1,48 @@ +// run-pass + +use std::panic::Location; + +extern "Rust" { + #[track_caller] + fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>; + fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static>; +} + +fn rust_track_caller_ffi_test_nested_tracked() -> &'static Location<'static> { + unsafe { rust_track_caller_ffi_test_tracked() } +} + +mod provides { + use std::panic::Location; + #[track_caller] // UB if we did not have this! + #[no_mangle] + fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static> { + Location::caller() + } + #[no_mangle] + fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static> { + Location::caller() + } +} + +fn main() { + let location = Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), 29); + assert_eq!(location.column(), 20); + + let tracked = unsafe { rust_track_caller_ffi_test_tracked() }; + assert_eq!(tracked.file(), file!()); + assert_eq!(tracked.line(), 34); + assert_eq!(tracked.column(), 28); + + let untracked = unsafe { rust_track_caller_ffi_test_untracked() }; + assert_eq!(untracked.file(), file!()); + assert_eq!(untracked.line(), 24); + assert_eq!(untracked.column(), 9); + + let contained = rust_track_caller_ffi_test_nested_tracked(); + assert_eq!(contained.file(), file!()); + assert_eq!(contained.line(), 12); + assert_eq!(contained.column(), 14); +} diff --git a/tests/ui/rfc-2091-track-caller/tracked-closure.rs b/tests/ui/rfc-2091-track-caller/tracked-closure.rs new file mode 100644 index 000000000..670c423a7 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/tracked-closure.rs @@ -0,0 +1,154 @@ +// run-pass + +#![feature(stmt_expr_attributes)] +#![feature(closure_track_caller)] +#![feature(generator_trait)] +#![feature(generators)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; +use std::panic::Location; + +type Loc = &'static Location<'static>; + +#[track_caller] +fn mono_invoke_fn (&'static str, bool, Loc)>( + val: &F +) -> (&'static str, bool, Loc) { + val("from_mono", false) +} + +#[track_caller] +fn mono_invoke_fn_once (&'static str, bool, Loc)>( + val: F +) -> (&'static str, bool, Loc) { + val("from_mono", false) +} + +#[track_caller] +fn dyn_invoke_fn_mut( + val: &mut dyn FnMut(&'static str, bool) -> (&'static str, bool, Loc) +) -> (&'static str, bool, Loc) { + val("from_dyn", false) +} + +#[track_caller] +fn dyn_invoke_fn_once( + val: Box (&'static str, bool, Loc)> +) -> (&'static str, bool, Loc) { + val("from_dyn", false) +} + + +fn test_closure() { + let mut track_closure = #[track_caller] |first: &'static str, second: bool| { + (first, second, Location::caller()) + }; + let (first_arg, first_bool, first_loc) = track_closure("first_arg", true); + let first_line = line!() - 1; + assert_eq!(first_arg, "first_arg"); + assert_eq!(first_bool, true); + assert_eq!(first_loc.file(), file!()); + assert_eq!(first_loc.line(), first_line); + assert_eq!(first_loc.column(), 46); + + let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_mut(&mut track_closure); + assert_eq!(dyn_arg, "from_dyn"); + assert_eq!(dyn_bool, false); + // `FnMut::call_mut` does not have `#[track_caller]`, + // so this will not match + assert_ne!(dyn_loc.file(), file!()); + + let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_once(Box::new(track_closure)); + assert_eq!(dyn_arg, "from_dyn"); + assert_eq!(dyn_bool, false); + // `FnOnce::call_once` does not have `#[track_caller]` + // so this will not match + assert_ne!(dyn_loc.file(), file!()); + + + let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn(&track_closure); + let mono_line = line!() - 1; + assert_eq!(mono_arg, "from_mono"); + assert_eq!(mono_bool, false); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 43); + + let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn_once(track_closure); + let mono_line = line!() - 1; + assert_eq!(mono_arg, "from_mono"); + assert_eq!(mono_bool, false); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 43); + + let non_tracked_caller = || Location::caller(); + let non_tracked_line = line!() - 1; // This is the line of the closure, not its caller + let non_tracked_loc = non_tracked_caller(); + assert_eq!(non_tracked_loc.file(), file!()); + assert_eq!(non_tracked_loc.line(), non_tracked_line); + assert_eq!(non_tracked_loc.column(), 33); +} + + +#[track_caller] +fn mono_generator>( + val: Pin<&mut F> +) -> (&'static str, String, Loc) { + match val.resume("Mono".to_string()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!() + } +} + +#[track_caller] +fn dyn_generator( + val: Pin<&mut dyn Generator> +) -> (&'static str, String, Loc) { + match val.resume("Dyn".to_string()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!() + } +} + +fn test_generator() { + let generator = #[track_caller] |arg: String| { + yield ("first", arg.clone(), Location::caller()); + yield ("second", arg.clone(), Location::caller()); + }; + + let mut pinned = Box::pin(generator); + let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut()); + assert_eq!(dyn_ret, "first"); + assert_eq!(dyn_arg, "Dyn".to_string()); + // The `Generator` trait does not have `#[track_caller]` on `resume`, so + // this will not match. + assert_ne!(dyn_loc.file(), file!()); + + + let (mono_ret, mono_arg, mono_loc) = mono_generator(pinned.as_mut()); + let mono_line = line!() - 1; + assert_eq!(mono_ret, "second"); + // The generator ignores the argument to the second `resume` call + assert_eq!(mono_arg, "Dyn".to_string()); + assert_eq!(mono_loc.file(), file!()); + assert_eq!(mono_loc.line(), mono_line); + assert_eq!(mono_loc.column(), 42); + + let non_tracked_generator = || { yield Location::caller(); }; + let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller + let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) { + GeneratorState::Yielded(val) => val, + _ => unreachable!() + }; + assert_eq!(non_tracked_loc.file(), file!()); + assert_eq!(non_tracked_loc.line(), non_tracked_line); + assert_eq!(non_tracked_loc.column(), 44); + +} + +fn main() { + test_closure(); + test_generator(); +} diff --git a/tests/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/tests/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs new file mode 100644 index 000000000..658812578 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs @@ -0,0 +1,62 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +fn pass_to_ptr_call(f: fn(T), x: T) { + f(x); +} + +#[track_caller] +fn tracked_unit(_: ()) { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); +} + +trait Trait { + fn trait_tracked_unit(_: ()); +} + +impl Trait for () { + #[track_caller] + fn trait_tracked_unit(_: ()) { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); + } +} + +trait TrackedTrait { + #[track_caller] + fn trait_tracked_unit_default(_: ()) { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); + } +} + +impl TrackedTrait for () {} + +trait BlanketTrackedTrait { + #[track_caller] + fn tracked_blanket(_: ()); +} + +impl BlanketTrackedTrait for () { + fn tracked_blanket(_: ()) { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); + } +} + +fn main() { + pass_to_ptr_call(tracked_unit, ()); + pass_to_ptr_call(<() as Trait>::trait_tracked_unit, ()); + pass_to_ptr_call(<() as TrackedTrait>::trait_tracked_unit_default, ()); + pass_to_ptr_call(<() as BlanketTrackedTrait>::tracked_blanket, ()); +} diff --git a/tests/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/tests/ui/rfc-2091-track-caller/tracked-fn-ptr.rs new file mode 100644 index 000000000..8bb4dd288 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/tracked-fn-ptr.rs @@ -0,0 +1,62 @@ +// run-pass +// revisions: default mir-opt +//[mir-opt] compile-flags: -Zmir-opt-level=4 + +fn ptr_call(f: fn()) { + f(); +} + +#[track_caller] +fn tracked() { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); +} + +trait Trait { + fn trait_tracked(); +} + +impl Trait for () { + #[track_caller] + fn trait_tracked() { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); + } +} + +trait TrackedTrait { + #[track_caller] + fn trait_tracked_default() { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); + } +} + +impl TrackedTrait for () {} + +trait TraitBlanketTracked { + #[track_caller] + fn tracked_blanket(); +} + +impl TraitBlanketTracked for () { + fn tracked_blanket() { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); + } +} + +fn main() { + ptr_call(tracked); + ptr_call(<() as Trait>::trait_tracked); + ptr_call(<() as TrackedTrait>::trait_tracked_default); + ptr_call(<() as TraitBlanketTracked>::tracked_blanket); +} diff --git a/tests/ui/rfc-2091-track-caller/tracked-trait-impls.rs b/tests/ui/rfc-2091-track-caller/tracked-trait-impls.rs new file mode 100644 index 000000000..4db4c29e5 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/tracked-trait-impls.rs @@ -0,0 +1,77 @@ +// run-pass + +macro_rules! assert_expansion_site_is_tracked { + () => {{ + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_ne!(location.line(), line!(), "line should be outside this fn"); + }} +} + +trait Tracked { + fn local_tracked(&self); + + #[track_caller] + fn blanket_tracked(&self); + + #[track_caller] + fn default_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +impl Tracked for () { + #[track_caller] + fn local_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn blanket_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +impl Tracked for bool { + #[track_caller] + fn local_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn blanket_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn default_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +impl Tracked for u8 { + #[track_caller] + fn local_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + fn blanket_tracked(&self) { + assert_expansion_site_is_tracked!(); + } + + #[track_caller] + fn default_tracked(&self) { + assert_expansion_site_is_tracked!(); + } +} + +fn main() { + ().local_tracked(); + ().default_tracked(); + ().blanket_tracked(); + + true.local_tracked(); + true.default_tracked(); + true.blanket_tracked(); + + 0u8.local_tracked(); + 0u8.default_tracked(); + 0u8.blanket_tracked(); +} diff --git a/tests/ui/rfc-2091-track-caller/tracked-trait-obj.rs b/tests/ui/rfc-2091-track-caller/tracked-trait-obj.rs new file mode 100644 index 000000000..06883a857 --- /dev/null +++ b/tests/ui/rfc-2091-track-caller/tracked-trait-obj.rs @@ -0,0 +1,61 @@ +// run-pass + +trait Tracked { + #[track_caller] + fn track_caller_trait_method(&self, line: u32, col: u32) { + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + // The trait method definition is annotated with `#[track_caller]`, + // so caller location information will work through a method + // call on a trait object + assert_eq!(location.line(), line, "Bad line"); + assert_eq!(location.column(), col, "Bad col"); + } + + fn track_caller_not_on_trait_method(&self); + + #[track_caller] + fn track_caller_through_self(self: Box, line: u32, col: u32); +} + +impl Tracked for () { + // We have `#[track_caller]` on the implementation of the method, + // but not on the definition of the method in the trait. Therefore, + // caller location information will *not* work through a method call + // on a trait object. Instead, we will get the location of this method + #[track_caller] + fn track_caller_not_on_trait_method(&self) { + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), line!() - 3); + assert_eq!(location.column(), 5); + } + + // We don't have a `#[track_caller]` attribute, but + // `#[track_caller]` is present on the trait definition, + // so we'll still get location information + fn track_caller_through_self(self: Box, line: u32, col: u32) { + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + // The trait method definition is annotated with `#[track_caller]`, + // so caller location information will work through a method + // call on a trait object + assert_eq!(location.line(), line, "Bad line"); + assert_eq!(location.column(), col, "Bad col"); + } +} + +fn main() { + let tracked: &dyn Tracked = &(); + // The column is the start of 'track_caller_trait_method' + tracked.track_caller_trait_method(line!(), 13); + + const TRACKED: &dyn Tracked = &(); + // The column is the start of 'track_caller_trait_method' + TRACKED.track_caller_trait_method(line!(), 13); + TRACKED.track_caller_not_on_trait_method(); + + // The column is the start of `track_caller_through_self` + let boxed: Box = Box::new(()); + boxed.track_caller_through_self(line!(), 11); +} diff --git a/tests/ui/rfc-2093-infer-outlives/cross-crate.rs b/tests/ui/rfc-2093-infer-outlives/cross-crate.rs new file mode 100644 index 000000000..a9bfeabf1 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/cross-crate.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'a, T> { //~ ERROR rustc_outlives + bar: std::slice::IterMut<'a, T> +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/cross-crate.stderr b/tests/ui/rfc-2093-infer-outlives/cross-crate.stderr new file mode 100644 index 000000000..76300cce5 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/cross-crate.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/cross-crate.rs:4:1 + | +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/dont-infer-static.rs b/tests/ui/rfc-2093-infer-outlives/dont-infer-static.rs new file mode 100644 index 000000000..d3940b13b --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/dont-infer-static.rs @@ -0,0 +1,12 @@ +/* + * We don't infer `T: 'static` outlives relationships. + */ + +struct Foo { + bar: Bar //~ ERROR the parameter type `U` may not live long enough [E0310] +} +struct Bar { + x: T, +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/tests/ui/rfc-2093-infer-outlives/dont-infer-static.stderr new file mode 100644 index 000000000..0c388f5fe --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -0,0 +1,19 @@ +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/dont-infer-static.rs:6:10 + | +LL | bar: Bar + | ^^^^^^ ...so that the type `U` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/dont-infer-static.rs:8:15 + | +LL | struct Bar { + | ^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | struct Foo { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/rfc-2093-infer-outlives/enum.rs b/tests/ui/rfc-2093-infer-outlives/enum.rs new file mode 100644 index 000000000..71d2d3222 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/enum.rs @@ -0,0 +1,27 @@ +#![feature(rustc_attrs)] + +// Needs an explicit where clause stating outlives condition. (RFC 2093) + +// Type T needs to outlive lifetime 'a. +#[rustc_outlives] +enum Foo<'a, T> { //~ ERROR rustc_outlives + One(Bar<'a, T>) +} + +// Type U needs to outlive lifetime 'b +#[rustc_outlives] +struct Bar<'b, U> { //~ ERROR rustc_outlives + field2: &'b U +} + +// Type K needs to outlive lifetime 'c. +#[rustc_outlives] +enum Ying<'c, K> { //~ ERROR rustc_outlives + One(&'c Yang) +} + +struct Yang { + field2: V +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/enum.stderr b/tests/ui/rfc-2093-infer-outlives/enum.stderr new file mode 100644 index 000000000..b6ce2450e --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/enum.stderr @@ -0,0 +1,26 @@ +error: rustc_outlives + --> $DIR/enum.rs:7:1 + | +LL | enum Foo<'a, T> { + | ^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: rustc_outlives + --> $DIR/enum.rs:13:1 + | +LL | struct Bar<'b, U> { + | ^^^^^^^^^^^^^^^^^ + | + = note: U: 'b + +error: rustc_outlives + --> $DIR/enum.rs:19:1 + | +LL | enum Ying<'c, K> { + | ^^^^^^^^^^^^^^^^ + | + = note: K: 'c + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-dyn.rs b/tests/ui/rfc-2093-infer-outlives/explicit-dyn.rs new file mode 100644 index 000000000..419fb0a0e --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-dyn.rs @@ -0,0 +1,12 @@ +#![feature(rustc_attrs)] + +trait Trait<'x, T> where T: 'x { +} + +#[rustc_outlives] +struct Foo<'a, A> //~ ERROR rustc_outlives +{ + foo: Box> +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-dyn.stderr b/tests/ui/rfc-2093-infer-outlives/explicit-dyn.stderr new file mode 100644 index 000000000..595a5c280 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-dyn.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/explicit-dyn.rs:7:1 + | +LL | struct Foo<'a, A> + | ^^^^^^^^^^^^^^^^^ + | + = note: A: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-enum.rs b/tests/ui/rfc-2093-infer-outlives/explicit-enum.rs new file mode 100644 index 000000000..c330c27fe --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-enum.rs @@ -0,0 +1,13 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +enum Foo<'a, U> { //~ ERROR rustc_outlives + One(Bar<'a, U>) +} + +struct Bar<'x, T> where T: 'x { + x: &'x (), + y: T, +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-enum.stderr b/tests/ui/rfc-2093-infer-outlives/explicit-enum.stderr new file mode 100644 index 000000000..3059f95ae --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-enum.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/explicit-enum.rs:4:1 + | +LL | enum Foo<'a, U> { + | ^^^^^^^^^^^^^^^ + | + = note: U: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-projection.rs b/tests/ui/rfc-2093-infer-outlives/explicit-projection.rs new file mode 100644 index 000000000..00b895288 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-projection.rs @@ -0,0 +1,13 @@ +#![feature(rustc_attrs)] + +trait Trait<'x, T> where T: 'x { + type Type; +} + +#[rustc_outlives] +struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives +{ + foo: >::Type +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-projection.stderr b/tests/ui/rfc-2093-infer-outlives/explicit-projection.stderr new file mode 100644 index 000000000..589e95899 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-projection.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/explicit-projection.rs:8:1 + | +LL | struct Foo<'a, A, B> where A: Trait<'a, B> + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: B: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-struct.rs b/tests/ui/rfc-2093-infer-outlives/explicit-struct.rs new file mode 100644 index 000000000..3d5e610b9 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-struct.rs @@ -0,0 +1,13 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'b, U> { //~ ERROR rustc_outlives + bar: Bar<'b, U> +} + +struct Bar<'a, T> where T: 'a { + x: &'a (), + y: T, +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-struct.stderr b/tests/ui/rfc-2093-infer-outlives/explicit-struct.stderr new file mode 100644 index 000000000..9912e36b2 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-struct.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/explicit-struct.rs:4:1 + | +LL | struct Foo<'b, U> { + | ^^^^^^^^^^^^^^^^^ + | + = note: U: 'b + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-union.rs b/tests/ui/rfc-2093-infer-outlives/explicit-union.rs new file mode 100644 index 000000000..871208b5b --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-union.rs @@ -0,0 +1,14 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +union Foo<'b, U: Copy> { //~ ERROR rustc_outlives + bar: Bar<'b, U> +} + +#[derive(Clone, Copy)] +union Bar<'a, T: Copy> where T: 'a { + x: &'a (), + y: T, +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/explicit-union.stderr b/tests/ui/rfc-2093-infer-outlives/explicit-union.stderr new file mode 100644 index 000000000..16b64bdc2 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/explicit-union.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/explicit-union.rs:4:1 + | +LL | union Foo<'b, U: Copy> { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: U: 'b + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/issue-54467.rs b/tests/ui/rfc-2093-infer-outlives/issue-54467.rs new file mode 100644 index 000000000..c712f15e3 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/issue-54467.rs @@ -0,0 +1,17 @@ +// Regression test for #54467: +// +// Here, the trait object has an "inferred outlives" requirement that +// `>::Item: 'a`; but since we don't know what +// `Self` is, we were (incorrectly) messing things up, leading to +// strange errors. This test ensures that we do not give compilation +// errors. +// +// check-pass + +trait MyIterator<'a>: Iterator where Self::Item: 'a { } + +struct MyStruct<'a, A> { + item: Box> +} + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/nested-enum.rs b/tests/ui/rfc-2093-infer-outlives/nested-enum.rs new file mode 100644 index 000000000..0cd706e7a --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-enum.rs @@ -0,0 +1,13 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +enum Foo<'a, T> { //~ ERROR rustc_outlives + + One(Bar<'a, T>) +} + +struct Bar<'b, U> { + field2: &'b U +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/nested-enum.stderr b/tests/ui/rfc-2093-infer-outlives/nested-enum.stderr new file mode 100644 index 000000000..4350e6e8b --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-enum.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/nested-enum.rs:4:1 + | +LL | enum Foo<'a, T> { + | ^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/nested-regions.rs b/tests/ui/rfc-2093-infer-outlives/nested-regions.rs new file mode 100644 index 000000000..a01c50681 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-regions.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives + x: &'a &'b T +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/nested-regions.stderr b/tests/ui/rfc-2093-infer-outlives/nested-regions.stderr new file mode 100644 index 000000000..c08add7ed --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-regions.stderr @@ -0,0 +1,12 @@ +error: rustc_outlives + --> $DIR/nested-regions.rs:4:1 + | +LL | struct Foo<'a, 'b, T> { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: 'b: 'a + = note: T: 'a + = note: T: 'b + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/nested-structs.rs b/tests/ui/rfc-2093-infer-outlives/nested-structs.rs new file mode 100644 index 000000000..ac6817d22 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-structs.rs @@ -0,0 +1,12 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'a, T> { //~ ERROR rustc_outlives + field1: Bar<'a, T> +} + +struct Bar<'b, U> { + field2: &'b U +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/nested-structs.stderr b/tests/ui/rfc-2093-infer-outlives/nested-structs.stderr new file mode 100644 index 000000000..769555234 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-structs.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/nested-structs.rs:4:1 + | +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/nested-union.rs b/tests/ui/rfc-2093-infer-outlives/nested-union.rs new file mode 100644 index 000000000..27ebd0b54 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-union.rs @@ -0,0 +1,14 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +union Foo<'a, T: Copy> { //~ ERROR rustc_outlives + field1: Bar<'a, T> +} + +// Type U needs to outlive lifetime 'b +#[derive(Clone, Copy)] +union Bar<'b, U: Copy> { + field2: &'b U +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/nested-union.stderr b/tests/ui/rfc-2093-infer-outlives/nested-union.stderr new file mode 100644 index 000000000..a785c63ce --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/nested-union.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/nested-union.rs:4:1 + | +LL | union Foo<'a, T: Copy> { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/privacy.rs b/tests/ui/rfc-2093-infer-outlives/privacy.rs new file mode 100644 index 000000000..180f5ac6c --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/privacy.rs @@ -0,0 +1,20 @@ +// Test that we do not get a privacy error here. Initially, we did, +// because we inferred an outlives predciate of ` as +// Private>::Out: 'a`, but the private trait is -- well -- private, +// and hence it was not something that a pub trait could refer to. +// +// run-pass + +#![allow(dead_code)] + +pub struct Foo<'a> { + field: Option<&'a as Private>::Out> +} + +trait Private { + type Out: ?Sized; +} + +impl Private for T { type Out = Self; } + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/projection.rs b/tests/ui/rfc-2093-infer-outlives/projection.rs new file mode 100644 index 000000000..411c86da1 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/projection.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives + bar: &'a T::Item +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/projection.stderr b/tests/ui/rfc-2093-infer-outlives/projection.stderr new file mode 100644 index 000000000..d9342013f --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/projection.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/projection.rs:4:1 + | +LL | struct Foo<'a, T: Iterator> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ::Item: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/reference.rs b/tests/ui/rfc-2093-infer-outlives/reference.rs new file mode 100644 index 000000000..a48a3315a --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/reference.rs @@ -0,0 +1,8 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'a, T> { //~ ERROR rustc_outlives + bar: &'a T, +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/reference.stderr b/tests/ui/rfc-2093-infer-outlives/reference.stderr new file mode 100644 index 000000000..508114357 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/reference.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/reference.rs:4:1 + | +LL | struct Foo<'a, T> { + | ^^^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs new file mode 100644 index 000000000..8b491ee4e --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.rs @@ -0,0 +1,39 @@ +// Various examples of structs whose fields are not well-formed. + +#![allow(dead_code)] + +trait Dummy<'a> { + type Out; +} +impl<'a, T> Dummy<'a> for T +where + T: 'a, +{ + type Out = (); +} +type RequireOutlives<'a, T> = >::Out; + +enum Ref1<'a, T> { + Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough +} + +enum Ref2<'a, T> { + Ref2Variant1, + Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough +} + +enum RefOk<'a, T: 'a> { + RefOkVariant1(&'a T), +} + +// This is now well formed. RFC 2093 +enum RefIndirect<'a, T> { + RefIndirectVariant1(isize, RefOk<'a, T>), +} + +enum RefDouble<'a, 'b, T> { + RefDoubleVariant1(&'a RequireOutlives<'b, T>), + //~^ the parameter type `T` may not live long enough [E0309] +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr new file mode 100644 index 000000000..2c660b285 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -0,0 +1,36 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-enum-not-wf.rs:17:18 + | +LL | Ref1Variant1(RequireOutlives<'a, T>), + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | enum Ref1<'a, T: 'a> { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-enum-not-wf.rs:22:25 + | +LL | Ref2Variant2(isize, RequireOutlives<'a, T>), + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | enum Ref2<'a, T: 'a> { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-enum-not-wf.rs:35:23 + | +LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | enum RefDouble<'a, 'b, T: 'b> { + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs new file mode 100644 index 000000000..36b024d2e --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.rs @@ -0,0 +1,22 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + + +#![allow(dead_code)] + +mod rev_variant_struct_region { + struct Foo<'a> { + x: fn(&'a i32), + } + trait Trait<'a, 'b> { + type Out; + } + impl<'a, 'b> Trait<'a, 'b> for usize { + type Out = &'a Foo<'b>; //~ ERROR reference has a longer lifetime + } +} + + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr new file mode 100644 index 000000000..5dff4c8ff --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:20 + | +LL | type Out = &'a Foo<'b>; + | ^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:14 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs new file mode 100644 index 000000000..47a38f7c4 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.rs @@ -0,0 +1,22 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + + +#![allow(dead_code)] + +mod variant_struct_region { + struct Foo<'a> { + x: &'a i32, + } + trait Trait<'a, 'b> { + type Out; + } + impl<'a, 'b> Trait<'a, 'b> for usize { + type Out = &'a Foo<'b>; //~ ERROR reference has a longer lifetime + } +} + + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr new file mode 100644 index 000000000..975776cdd --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-nominal-type-region.rs:17:20 + | +LL | type Out = &'a Foo<'b>; + | ^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regions-outlives-nominal-type-region.rs:16:10 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regions-outlives-nominal-type-region.rs:16:14 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs new file mode 100644 index 000000000..083ba8948 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.rs @@ -0,0 +1,22 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + + +#![allow(dead_code)] + +mod variant_struct_type { + struct Foo { + x: fn(T) + } + trait Trait<'a, 'b> { + type Out; + } + impl<'a, 'b> Trait<'a, 'b> for usize { + type Out = &'a Foo<&'b i32>; //~ ERROR reference has a longer lifetime + } +} + + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr new file mode 100644 index 000000000..be05ecec0 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:20 + | +LL | type Out = &'a Foo<&'b i32>; + | ^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:14 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs new file mode 100644 index 000000000..f3e4e39ac --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.rs @@ -0,0 +1,22 @@ +// Test that a nominal type (like `Foo<'a>`) outlives `'b` if its +// arguments (like `'a`) outlive `'b`. +// +// Rule OutlivesNominalType from RFC 1214. + + +#![allow(dead_code)] + +mod variant_struct_type { + struct Foo { + x: T + } + trait Trait<'a, 'b> { + type Out; + } + impl<'a, 'b> Trait<'a, 'b> for usize { + type Out = &'a Foo<&'b i32>; //~ ERROR reference has a longer lifetime + } +} + + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr new file mode 100644 index 000000000..4ba1778d6 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-nominal-type-type.rs:17:20 + | +LL | type Out = &'a Foo<&'b i32>; + | ^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regions-outlives-nominal-type-type.rs:16:10 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regions-outlives-nominal-type-type.rs:16:14 + | +LL | impl<'a, 'b> Trait<'a, 'b> for usize { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs b/tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs new file mode 100644 index 000000000..552c6cf00 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.rs @@ -0,0 +1,28 @@ +// Various examples of structs whose fields are not well-formed. + +#![allow(dead_code)] + +trait Trait<'a, T> { + type Out; +} +trait Trait1<'a, 'b, T> { + type Out; +} + +impl<'a, T> Trait<'a, T> for usize { + type Out = &'a T; //~ ERROR `T` may not live long enough +} + +struct RefOk<'a, T:'a> { + field: &'a T +} + +impl<'a, T> Trait<'a, T> for u32 { + type Out = RefOk<'a, T>; //~ ERROR `T` may not live long enough +} + +impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { + type Out = &'a &'b T; //~ ERROR reference has a longer lifetime than the data +} + +fn main() { } diff --git a/tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr new file mode 100644 index 000000000..34ff1362c --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -0,0 +1,48 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-struct-not-wf.rs:13:16 + | +LL | type Out = &'a T; + | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a, T> for usize { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regions-struct-not-wf.rs:21:16 + | +LL | type Out = RefOk<'a, T>; + | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/regions-struct-not-wf.rs:16:20 + | +LL | struct RefOk<'a, T:'a> { + | ^^ +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a, T> for u32 { + | ++++ + +error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references + --> $DIR/regions-struct-not-wf.rs:25:16 + | +LL | type Out = &'a &'b T; + | ^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regions-struct-not-wf.rs:24:6 + | +LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regions-struct-not-wf.rs:24:10 + | +LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { + | ^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0309, E0491. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/rfc-2093-infer-outlives/self-dyn.rs b/tests/ui/rfc-2093-infer-outlives/self-dyn.rs new file mode 100644 index 000000000..c53d6c18f --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/self-dyn.rs @@ -0,0 +1,13 @@ +#![feature(rustc_attrs)] + +trait Trait<'x, 's, T> where T: 'x, + 's: { +} + +#[rustc_outlives] +struct Foo<'a, 'b, A> //~ ERROR rustc_outlives +{ + foo: Box> +} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/self-dyn.stderr b/tests/ui/rfc-2093-infer-outlives/self-dyn.stderr new file mode 100644 index 000000000..9c836b190 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/self-dyn.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/self-dyn.rs:8:1 + | +LL | struct Foo<'a, 'b, A> + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: A: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2093-infer-outlives/self-structs.rs b/tests/ui/rfc-2093-infer-outlives/self-structs.rs new file mode 100644 index 000000000..8f2d29d6f --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/self-structs.rs @@ -0,0 +1,13 @@ +#![feature(rustc_attrs)] + +#[rustc_outlives] +struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives + field1: dyn Bar<'a, 'b, T> +} + +trait Bar<'x, 's, U> + where U: 'x, + Self:'s +{} + +fn main() {} diff --git a/tests/ui/rfc-2093-infer-outlives/self-structs.stderr b/tests/ui/rfc-2093-infer-outlives/self-structs.stderr new file mode 100644 index 000000000..2b4625f77 --- /dev/null +++ b/tests/ui/rfc-2093-infer-outlives/self-structs.stderr @@ -0,0 +1,10 @@ +error: rustc_outlives + --> $DIR/self-structs.rs:4:1 + | +LL | struct Foo<'a, 'b, T> { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: T: 'a + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs b/tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs new file mode 100644 index 000000000..79f6b0dfe --- /dev/null +++ b/tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs @@ -0,0 +1,11 @@ +struct S; + +pub mod m { + fn f() { + let s = ::m::crate::S; //~ ERROR failed to resolve + let s1 = ::crate::S; //~ ERROR failed to resolve + let s2 = crate::S; // no error + } +} + +fn main() {} diff --git a/tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr b/tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr new file mode 100644 index 000000000..7e7ee3ce0 --- /dev/null +++ b/tests/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: `crate` in paths can only be used in start position + --> $DIR/crate-path-non-absolute.rs:5:22 + | +LL | let s = ::m::crate::S; + | ^^^^^ `crate` in paths can only be used in start position + +error[E0433]: failed to resolve: global paths cannot start with `crate` + --> $DIR/crate-path-non-absolute.rs:6:20 + | +LL | let s1 = ::crate::S; + | ^^^^^ global paths cannot start with `crate` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs b/tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs new file mode 100644 index 000000000..019ef8e9d --- /dev/null +++ b/tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs @@ -0,0 +1,4 @@ +fn main() { + let crate = 0; + //~^ ERROR expected unit struct, unit variant or constant, found module `crate` +} diff --git a/tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr b/tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr new file mode 100644 index 000000000..c39a70f66 --- /dev/null +++ b/tests/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr @@ -0,0 +1,9 @@ +error[E0532]: expected unit struct, unit variant or constant, found module `crate` + --> $DIR/keyword-crate-as-identifier.rs:2:9 + | +LL | let crate = 0; + | ^^^^^ not a unit struct, unit variant or constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/tests/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs b/tests/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs new file mode 100644 index 000000000..c4d444764 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/auxiliary/xcrate.rs @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub struct S; + +#[derive(Debug)] +pub struct Z; diff --git a/tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs new file mode 100644 index 000000000..9c0e0bef4 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.rs @@ -0,0 +1,5 @@ +// edition:2018 + +use xcrate::S; //~ ERROR unresolved import `xcrate` + +fn main() {} diff --git a/tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr new file mode 100644 index 000000000..818915721 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-1.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `xcrate` + --> $DIR/non-existent-1.rs:3:5 + | +LL | use xcrate::S; + | ^^^^^^ use of undeclared crate or module `xcrate` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs new file mode 100644 index 000000000..def60feb5 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.rs @@ -0,0 +1,6 @@ +// edition:2018 + +fn main() { + let s = ::xcrate::S; + //~^ ERROR failed to resolve: could not find `xcrate` in the list of imported crates +} diff --git a/tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr new file mode 100644 index 000000000..7df4f06d1 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-2.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: could not find `xcrate` in the list of imported crates + --> $DIR/non-existent-2.rs:4:15 + | +LL | let s = ::xcrate::S; + | ^^^^^^ could not find `xcrate` in the list of imported crates + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs new file mode 100644 index 000000000..486159c0e --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.rs @@ -0,0 +1,5 @@ +// edition:2018 + +use ycrate; //~ ERROR unresolved import `ycrate` + +fn main() {} diff --git a/tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr new file mode 100644 index 000000000..bd6778cf3 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/non-existent-3.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `ycrate` + --> $DIR/non-existent-3.rs:3:5 + | +LL | use ycrate; + | ^^^^^^ no external crate `ycrate` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rfc-2126-extern-absolute-paths/not-allowed.rs b/tests/ui/rfc-2126-extern-absolute-paths/not-allowed.rs new file mode 100644 index 000000000..acb4bbebe --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/not-allowed.rs @@ -0,0 +1,9 @@ +// edition:2018 + +// Tests that arbitrary crates (other than `core`, `std` and `meta`) +// aren't allowed without `--extern`, even if they're in the sysroot. +use alloc; //~ ERROR unresolved import `alloc` +use test; // OK, imports the built-in attribute macro `#[test]`, but not the `test` crate. +use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate. + +fn main() {} diff --git a/tests/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr b/tests/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr new file mode 100644 index 000000000..122e8fd35 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr @@ -0,0 +1,16 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/not-allowed.rs:5:5 + | +LL | use alloc; + | ^^^^^ no external crate `alloc` + | +help: consider importing one of these items instead + | +LL | use core::alloc; + | ~~~~~~~~~~~ +LL | use std::alloc; + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rfc-2126-extern-absolute-paths/single-segment.rs b/tests/ui/rfc-2126-extern-absolute-paths/single-segment.rs new file mode 100644 index 000000000..72e50d78b --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/single-segment.rs @@ -0,0 +1,11 @@ +// aux-build:xcrate.rs +// compile-flags:--extern xcrate +// edition:2018 + +use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;` +use *; //~ ERROR cannot glob-import all possible crates + +fn main() { + let s = ::xcrate; //~ ERROR expected value, found crate `xcrate` + //~^ NOTE not a value +} diff --git a/tests/ui/rfc-2126-extern-absolute-paths/single-segment.stderr b/tests/ui/rfc-2126-extern-absolute-paths/single-segment.stderr new file mode 100644 index 000000000..253cc1bc5 --- /dev/null +++ b/tests/ui/rfc-2126-extern-absolute-paths/single-segment.stderr @@ -0,0 +1,21 @@ +error: crate root imports need to be explicitly named: `use crate as name;` + --> $DIR/single-segment.rs:5:5 + | +LL | use crate; + | ^^^^^ + +error: cannot glob-import all possible crates + --> $DIR/single-segment.rs:6:5 + | +LL | use *; + | ^ + +error[E0423]: expected value, found crate `xcrate` + --> $DIR/single-segment.rs:9:13 + | +LL | let s = ::xcrate; + | ^^^^^^^^ not a value + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/rfc-2294-if-let-guard/bindings.rs b/tests/ui/rfc-2294-if-let-guard/bindings.rs new file mode 100644 index 000000000..1f32e4af1 --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/bindings.rs @@ -0,0 +1,9 @@ +#![feature(if_let_guard)] + +fn main() { + match Some(None) { + Some(x) if let Some(y) = x => (x, y), + _ => y, //~ ERROR cannot find value `y` + } + y //~ ERROR cannot find value `y` +} diff --git a/tests/ui/rfc-2294-if-let-guard/bindings.stderr b/tests/ui/rfc-2294-if-let-guard/bindings.stderr new file mode 100644 index 000000000..2463b7f3e --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/bindings.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `y` in this scope + --> $DIR/bindings.rs:6:14 + | +LL | _ => y, + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/bindings.rs:8:5 + | +LL | y + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfc-2294-if-let-guard/feature-gate.rs new file mode 100644 index 000000000..f0105e08e --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/feature-gate.rs @@ -0,0 +1,84 @@ +// gate-test-if_let_guard + +use std::ops::Range; + +fn _if_let_guard() { + match () { + () if let 0 = 1 => {} + //~^ ERROR `if let` guards are experimental + + () if (let 0 = 1) => {} + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + + () if (((let 0 = 1))) => {} + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + + () if true && let 0 = 1 => {} + //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable + + () if let 0 = 1 && true => {} + //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable + + () if (let 0 = 1) && true => {} + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + + () if true && (let 0 = 1) => {} + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + + () if (let 0 = 1) && (let 0 = 1) => {} + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + + () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + + () if let Range { start: _, end: _ } = (true..true) && false => {} + //~^ ERROR `if let` guards are experimental + //~| ERROR `let` expressions in this position are unstable + + _ => {} + } +} + +fn _macros() { + macro_rules! use_expr { + ($e:expr) => { + match () { + () if $e => {} + _ => {} + } + } + } + use_expr!((let 0 = 1 && 0 == 0)); + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + use_expr!((let 0 = 1)); + //~^ ERROR `let` expressions in this position are unstable + //~| ERROR expected expression, found `let` statement + match () { + #[cfg(FALSE)] + () if let 0 = 1 => {} + //~^ ERROR `if let` guards are experimental + _ => {} + } + use_expr!(let 0 = 1); + //~^ ERROR no rules expected the token `let` +} + +fn main() {} diff --git a/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr new file mode 100644 index 000000000..96fe11911 --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/feature-gate.stderr @@ -0,0 +1,288 @@ +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:10:16 + | +LL | () if (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:14:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:26:16 + | +LL | () if (let 0 = 1) && true => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:30:24 + | +LL | () if true && (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:34:16 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:34:31 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:40:42 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:40:55 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:40:68 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:68:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:71:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + +error: no rules expected the token `let` + --> $DIR/feature-gate.rs:80:15 + | +LL | macro_rules! use_expr { + | --------------------- when calling this macro +... +LL | use_expr!(let 0 = 1); + | ^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> $DIR/feature-gate.rs:61:10 + | +LL | ($e:expr) => { + | ^^^^^^^ + +error[E0658]: `if let` guards are experimental + --> $DIR/feature-gate.rs:7:12 + | +LL | () if let 0 = 1 => {} + | ^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `if let` guards are experimental + --> $DIR/feature-gate.rs:18:12 + | +LL | () if true && let 0 = 1 => {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `if let` guards are experimental + --> $DIR/feature-gate.rs:22:12 + | +LL | () if let 0 = 1 && true => {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `if let` guards are experimental + --> $DIR/feature-gate.rs:40:12 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `if let` guards are experimental + --> $DIR/feature-gate.rs:51:12 + | +LL | () if let Range { start: _, end: _ } = (true..true) && false => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `if let` guards are experimental + --> $DIR/feature-gate.rs:76:12 + | +LL | () if let 0 = 1 => {} + | ^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:10:16 + | +LL | () if (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:14:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:18:23 + | +LL | () if true && let 0 = 1 => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:22:15 + | +LL | () if let 0 = 1 && true => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:26:16 + | +LL | () if (let 0 = 1) && true => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:30:24 + | +LL | () if true && (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:34:16 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:34:31 + | +LL | () if (let 0 = 1) && (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:15 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:28 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:42 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:55 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:40:68 + | +LL | () if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) => {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:51:15 + | +LL | () if let Range { start: _, end: _ } = (true..true) && false => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:68:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:71:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 34 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2294-if-let-guard/run-pass.rs b/tests/ui/rfc-2294-if-let-guard/run-pass.rs new file mode 100644 index 000000000..a303a0d1f --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/run-pass.rs @@ -0,0 +1,40 @@ +// run-pass + +#![feature(if_let_guard)] + +enum Foo { + Bar, + Baz, + Qux(u8), +} + +fn bar(x: bool) -> Foo { + if x { Foo::Baz } else { Foo::Bar } +} + +fn baz(x: u8) -> Foo { + if x % 2 == 0 { Foo::Bar } else { Foo::Baz } +} + +fn qux(x: u8) -> Foo { + Foo::Qux(x.rotate_left(1)) +} + +fn main() { + match Some((true, 3)) { + Some((x, _)) if let Foo::Bar = bar(x) => panic!(), + Some((_, x)) if let Foo::Baz = baz(x) => {}, + _ => panic!(), + } + match Some(42) { + Some(x) if let Foo::Qux(y) = qux(x) => assert_eq!(y, 84), + _ => panic!(), + } + + // issue #88015 + #[allow(irrefutable_let_patterns)] + match () { + () | () if let x = 42 => assert_eq!(x, 42), + _ => panic!() + } +} diff --git a/tests/ui/rfc-2294-if-let-guard/typeck.rs b/tests/ui/rfc-2294-if-let-guard/typeck.rs new file mode 100644 index 000000000..ad178dfa4 --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/typeck.rs @@ -0,0 +1,15 @@ +#![feature(if_let_guard)] + +fn ok() -> Result, ()> { + Ok(Some(true)) +} + +fn main() { + match ok() { + Ok(x) if let Err(_) = x => {}, + //~^ ERROR mismatched types + Ok(x) if let 0 = x => {}, + //~^ ERROR mismatched types + _ => {} + } +} diff --git a/tests/ui/rfc-2294-if-let-guard/typeck.stderr b/tests/ui/rfc-2294-if-let-guard/typeck.stderr new file mode 100644 index 000000000..dd1f4826f --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/typeck.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/typeck.rs:9:22 + | +LL | Ok(x) if let Err(_) = x => {}, + | ^^^^^^ - this expression has type `Option` + | | + | expected enum `Option`, found enum `Result` + | + = note: expected enum `Option` + found enum `Result<_, _>` + +error[E0308]: mismatched types + --> $DIR/typeck.rs:11:22 + | +LL | Ok(x) if let 0 = x => {}, + | ^ - this expression has type `Option` + | | + | expected enum `Option`, found integer + | + = note: expected enum `Option` + found type `{integer}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-2294-if-let-guard/warns.rs b/tests/ui/rfc-2294-if-let-guard/warns.rs new file mode 100644 index 000000000..3ad1a50c6 --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/warns.rs @@ -0,0 +1,21 @@ +#![feature(if_let_guard)] + +#[deny(irrefutable_let_patterns)] +fn irrefutable_let_guard() { + match Some(()) { + Some(x) if let () = x => {} + //~^ ERROR irrefutable `if let` guard + _ => {} + } +} + +#[deny(unreachable_patterns)] +fn unreachable_pattern() { + match Some(()) { + x if let None | None = x => {} + //~^ ERROR unreachable pattern + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/rfc-2294-if-let-guard/warns.stderr b/tests/ui/rfc-2294-if-let-guard/warns.stderr new file mode 100644 index 000000000..75f22ac8d --- /dev/null +++ b/tests/ui/rfc-2294-if-let-guard/warns.stderr @@ -0,0 +1,28 @@ +error: irrefutable `if let` guard pattern + --> $DIR/warns.rs:6:24 + | +LL | Some(x) if let () = x => {} + | ^^ + | + = note: this pattern will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm +note: the lint level is defined here + --> $DIR/warns.rs:3:8 + | +LL | #[deny(irrefutable_let_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/warns.rs:15:25 + | +LL | x if let None | None = x => {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/warns.rs:12:8 + | +LL | #[deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2306/convert-id-const-with-gate.rs b/tests/ui/rfc-2306/convert-id-const-with-gate.rs new file mode 100644 index 000000000..762dfbe48 --- /dev/null +++ b/tests/ui/rfc-2306/convert-id-const-with-gate.rs @@ -0,0 +1,7 @@ +// This test should pass since 'identity' is const fn. + +// build-pass (FIXME(62277): could be check-pass?) + +fn main() { + const _FOO: u8 = ::std::convert::identity(42u8); +} diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs new file mode 100644 index 000000000..04d924a9a --- /dev/null +++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs @@ -0,0 +1,67 @@ +// run-pass +// check-run-results + +// Tests ensuring that `dbg!(expr)` has the expected run-time behavior. +// as well as some compile time properties we expect. + +#[derive(Copy, Clone, Debug)] +struct Unit; + +#[derive(Copy, Clone, Debug, PartialEq)] +struct Point { + x: T, + y: T, +} + +#[derive(Debug, PartialEq)] +struct NoCopy(usize); + +fn main() { + let a: Unit = dbg!(Unit); + let _: Unit = dbg!(a); + // We can move `a` because it's Copy. + drop(a); + + // `Point` will be faithfully formatted according to `{:#?}`. + let a = Point { x: 42, y: 24 }; + let b: Point = dbg!(Point { x: 42, y: 24 }); // test stringify!(..) + let c: Point = dbg!(b); + // Identity conversion: + assert_eq!(a, b); + assert_eq!(a, c); + // We can move `b` because it's Copy. + drop(b); + + // Without parameters works as expected. + let _: () = dbg!(); + + // Test that we can borrow and that successive applications is still identity. + let a = NoCopy(1337); + let b: &NoCopy = dbg!(dbg!(&a)); + assert_eq!(&a, b); + + // Test involving lifetimes of temporaries: + fn f<'a>(x: &'a u8) -> &'a u8 { x } + let a: &u8 = dbg!(f(&42)); + assert_eq!(a, &42); + + // Test side effects: + let mut foo = 41; + assert_eq!(7331, dbg!({ + foo += 1; + eprintln!("before"); + 7331 + })); + assert_eq!(foo, 42); + + // Test trailing comma: + assert_eq!(("Yeah",), dbg!(("Yeah",))); + + // Test multiple arguments: + assert_eq!((1u8, 2u32), dbg!(1, + 2)); + + // Test multiple arguments + trailing comma: + assert_eq!((1u8, 2u32, "Yeah"), dbg!(1u8, 2u32, + "Yeah",)); +} diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr new file mode 100644 index 000000000..49d72158e --- /dev/null +++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr @@ -0,0 +1,28 @@ +[$DIR/dbg-macro-expected-behavior.rs:20] Unit = Unit +[$DIR/dbg-macro-expected-behavior.rs:21] a = Unit +[$DIR/dbg-macro-expected-behavior.rs:27] Point { x: 42, y: 24 } = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:28] b = Point { + x: 42, + y: 24, +} +[$DIR/dbg-macro-expected-behavior.rs:36] +[$DIR/dbg-macro-expected-behavior.rs:40] &a = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:40] dbg!(& a) = NoCopy( + 1337, +) +[$DIR/dbg-macro-expected-behavior.rs:45] f(&42) = 42 +before +[$DIR/dbg-macro-expected-behavior.rs:50] { foo += 1; eprintln!("before"); 7331 } = 7331 +[$DIR/dbg-macro-expected-behavior.rs:58] ("Yeah",) = ( + "Yeah", +) +[$DIR/dbg-macro-expected-behavior.rs:61] 1 = 1 +[$DIR/dbg-macro-expected-behavior.rs:61] 2 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] 1u8 = 1 +[$DIR/dbg-macro-expected-behavior.rs:65] 2u32 = 2 +[$DIR/dbg-macro-expected-behavior.rs:65] "Yeah" = "Yeah" diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs b/tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs new file mode 100644 index 000000000..9f3c567b6 --- /dev/null +++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.rs @@ -0,0 +1,10 @@ +// Test ensuring that `dbg!(expr)` will take ownership of the argument. + +#[derive(Debug)] +struct NoCopy(usize); + +fn main() { + let a = NoCopy(0); + let _ = dbg!(a); + let _ = dbg!(a); //~ ERROR use of moved value +} diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr new file mode 100644 index 000000000..e97fdcce1 --- /dev/null +++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `a` + --> $DIR/dbg-macro-move-semantics.rs:9:18 + | +LL | let a = NoCopy(0); + | - move occurs because `a` has type `NoCopy`, which does not implement the `Copy` trait +LL | let _ = dbg!(a); + | ------- value moved here +LL | let _ = dbg!(a); + | ^ value used here after move + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs b/tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs new file mode 100644 index 000000000..f2fb62d76 --- /dev/null +++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.rs @@ -0,0 +1,7 @@ +// Test ensuring that `dbg!(expr)` requires the passed type to implement `Debug`. + +struct NotDebug; + +fn main() { + let _: NotDebug = dbg!(NotDebug); //~ ERROR `NotDebug` doesn't implement `Debug` +} diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr new file mode 100644 index 000000000..d8b5a9e63 --- /dev/null +++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -0,0 +1,17 @@ +error[E0277]: `NotDebug` doesn't implement `Debug` + --> $DIR/dbg-macro-requires-debug.rs:6:23 + | +LL | let _: NotDebug = dbg!(NotDebug); + | ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `NotDebug` + = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `NotDebug` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs b/tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs new file mode 100644 index 000000000..5053c115b --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs @@ -0,0 +1,21 @@ +#![feature(do_not_recommend)] + +pub trait Foo { +} + +impl Foo for i32 { +} + +pub trait Bar { +} + +#[do_not_recommend] +impl Bar for T { +} + +fn stuff(_: T) {} + +fn main() { + stuff(1u8); + //~^ the trait bound `u8: Foo` is not satisfied +} diff --git a/tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr new file mode 100644 index 000000000..a3e559054 --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `u8: Foo` is not satisfied + --> $DIR/feature-gate-do_not_recommend.rs:19:11 + | +LL | stuff(1u8); + | ----- ^^^ the trait `Foo` is not implemented for `u8` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo` is implemented for `i32` +note: required for `u8` to implement `Bar` + --> $DIR/feature-gate-do_not_recommend.rs:13:14 + | +LL | impl Bar for T { + | --- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `stuff` + --> $DIR/feature-gate-do_not_recommend.rs:16:13 + | +LL | fn stuff(_: T) {} + | ^^^ required by this bound in `stuff` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs new file mode 100644 index 000000000..91863f5e4 --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs @@ -0,0 +1,45 @@ +#![feature(do_not_recommend)] + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +const CONST: () = (); + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +static Static: () = (); + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +type Type = (); + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +enum Enum { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +extern { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +fn fun() { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +struct Struct { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +trait Trait { +} + +#[do_not_recommend] +impl Trait for i32 { +} + +fn main() { +} diff --git a/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr new file mode 100644 index 000000000..01ebc23c8 --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr @@ -0,0 +1,50 @@ +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:3:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:7:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:11:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:15:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:20:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:25:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:30:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:35:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs new file mode 100644 index 000000000..f0c5c222e --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs @@ -0,0 +1,10 @@ +trait Foo { +} + +#[do_not_recommend] +//~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature +impl Foo for i32 { +} + +fn main() { +} diff --git a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr new file mode 100644 index 000000000..1597e5be4 --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature + --> $DIR/unstable-feature.rs:4:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51992 for more information + = help: add `#![feature(do_not_recommend)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs b/tests/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs new file mode 100644 index 000000000..e373b6438 --- /dev/null +++ b/tests/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs @@ -0,0 +1 @@ +pub trait Foo {} diff --git a/tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs new file mode 100644 index 000000000..c07ba54af --- /dev/null +++ b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs @@ -0,0 +1,3 @@ +extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг` + +fn main() {} diff --git a/tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr new file mode 100644 index 000000000..a8f3abe59 --- /dev/null +++ b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr @@ -0,0 +1,8 @@ +error: cannot load a crate with a non-ascii name `ьаг` + --> $DIR/crate_name_nonascii_forbidden-1.rs:1:1 + | +LL | extern crate ьаг; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs new file mode 100644 index 000000000..f8e033937 --- /dev/null +++ b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs @@ -0,0 +1,6 @@ +// compile-flags:--extern му_Ñгате +// edition:2018 + +use му_Ñгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_Ñгате` + +fn main() {} diff --git a/tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr new file mode 100644 index 000000000..05fc4fb22 --- /dev/null +++ b/tests/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr @@ -0,0 +1,8 @@ +error: cannot load a crate with a non-ascii name `му_Ñгате` + --> $DIR/crate_name_nonascii_forbidden-2.rs:4:5 + | +LL | use му_Ñгате::baz; + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2457/extern_block_nonascii_forbidden.rs b/tests/ui/rfc-2457/extern_block_nonascii_forbidden.rs new file mode 100644 index 000000000..ad6825404 --- /dev/null +++ b/tests/ui/rfc-2457/extern_block_nonascii_forbidden.rs @@ -0,0 +1,9 @@ +#![feature(extern_types)] + +extern "C" { + type 一; //~ items in `extern` blocks cannot use non-ascii identifiers + fn 二(); //~ items in `extern` blocks cannot use non-ascii identifiers + static 三: usize; //~ items in `extern` blocks cannot use non-ascii identifiers +} + +fn main() {} diff --git a/tests/ui/rfc-2457/extern_block_nonascii_forbidden.stderr b/tests/ui/rfc-2457/extern_block_nonascii_forbidden.stderr new file mode 100644 index 000000000..ca1b8a6e7 --- /dev/null +++ b/tests/ui/rfc-2457/extern_block_nonascii_forbidden.stderr @@ -0,0 +1,34 @@ +error: items in `extern` blocks cannot use non-ascii identifiers + --> $DIR/extern_block_nonascii_forbidden.rs:4:10 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | type 一; + | ^^ + | + = note: this limitation may be lifted in the future; see issue #83942 for more information + +error: items in `extern` blocks cannot use non-ascii identifiers + --> $DIR/extern_block_nonascii_forbidden.rs:5:8 + | +LL | extern "C" { + | ---------- in this `extern` block +LL | type 一; +LL | fn 二(); + | ^^ + | + = note: this limitation may be lifted in the future; see issue #83942 for more information + +error: items in `extern` blocks cannot use non-ascii identifiers + --> $DIR/extern_block_nonascii_forbidden.rs:6:12 + | +LL | extern "C" { + | ---------- in this `extern` block +... +LL | static 三: usize; + | ^^ + | + = note: this limitation may be lifted in the future; see issue #83942 for more information + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rfc-2457/idents-normalized.rs b/tests/ui/rfc-2457/idents-normalized.rs new file mode 100644 index 000000000..1023fee37 --- /dev/null +++ b/tests/ui/rfc-2457/idents-normalized.rs @@ -0,0 +1,7 @@ +// check-pass + +struct Résumé; // ['LATIN SMALL LETTER E WITH ACUTE'] + +fn main() { + let _ = ReÌsumeÌ; // ['LATIN SMALL LETTER E', 'COMBINING ACUTE ACCENT'] +} diff --git a/tests/ui/rfc-2457/mod_file_nonascii_forbidden.rs b/tests/ui/rfc-2457/mod_file_nonascii_forbidden.rs new file mode 100644 index 000000000..e949e2319 --- /dev/null +++ b/tests/ui/rfc-2457/mod_file_nonascii_forbidden.rs @@ -0,0 +1,4 @@ +mod řųśť; //~ trying to load file for +//~^ file not found for + +fn main() {} diff --git a/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr b/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr new file mode 100644 index 000000000..dd0dac95e --- /dev/null +++ b/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr @@ -0,0 +1,20 @@ +error[E0583]: file not found for module `řųśť` + --> $DIR/mod_file_nonascii_forbidden.rs:1:1 + | +LL | mod řųśť; + | ^^^^^^^^^ + | + = help: to create the module `řųśť`, create file "$DIR/řųśť.rs" or "$DIR/řųśť/mod.rs" + +error[E0754]: trying to load file for module `řųśť` with non-ascii identifier name + --> $DIR/mod_file_nonascii_forbidden.rs:1:5 + | +LL | mod řųśť; + | ^^^^ + | + = help: consider using `#[path]` attribute to specify filesystem path + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0583, E0754. +For more information about an error, try `rustc --explain E0583`. diff --git a/tests/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs b/tests/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs new file mode 100644 index 000000000..94327846d --- /dev/null +++ b/tests/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs @@ -0,0 +1,6 @@ +// check-pass + +#[path="auxiliary/mod_file_nonascii_with_path_allowed-aux.rs"] +mod řųśť; + +fn main() {} diff --git a/tests/ui/rfc-2457/mod_inline_nonascii_allowed.rs b/tests/ui/rfc-2457/mod_inline_nonascii_allowed.rs new file mode 100644 index 000000000..e1d836b7c --- /dev/null +++ b/tests/ui/rfc-2457/mod_inline_nonascii_allowed.rs @@ -0,0 +1,7 @@ +// check-pass + +mod řųśť { + const IS_GREAT: bool = true; +} + +fn main() {} diff --git a/tests/ui/rfc-2457/no_mangle_nonascii_forbidden.rs b/tests/ui/rfc-2457/no_mangle_nonascii_forbidden.rs new file mode 100644 index 000000000..f4c126a6e --- /dev/null +++ b/tests/ui/rfc-2457/no_mangle_nonascii_forbidden.rs @@ -0,0 +1,20 @@ +#[no_mangle] +pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier + +pub struct Foo; + +impl Foo { + #[no_mangle] + pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier +} + +trait Bar { + fn řųśť(); +} + +impl Bar for Foo { + #[no_mangle] + fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier +} + +fn main() {} diff --git a/tests/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr b/tests/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr new file mode 100644 index 000000000..459d5d6b5 --- /dev/null +++ b/tests/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr @@ -0,0 +1,21 @@ +error[E0754]: `#[no_mangle]` requires ASCII identifier + --> $DIR/no_mangle_nonascii_forbidden.rs:2:1 + | +LL | pub fn řųśť() {} + | ^^^^^^^^^^^^^ + +error[E0754]: `#[no_mangle]` requires ASCII identifier + --> $DIR/no_mangle_nonascii_forbidden.rs:8:5 + | +LL | pub fn řųśť() {} + | ^^^^^^^^^^^^^ + +error[E0754]: `#[no_mangle]` requires ASCII identifier + --> $DIR/no_mangle_nonascii_forbidden.rs:17:5 + | +LL | fn řųśť() {} + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0754`. diff --git a/tests/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs b/tests/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs new file mode 100644 index 000000000..d851fac8e --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/ast-lowering-does-not-wrap-let-chains.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(let_chains)] +#![allow(irrefutable_let_patterns)] + +fn main() { + let first = Some(1); + let second = Some(2); + let mut n = 0; + if let x = first && let y = second && 1 == 1 { + assert_eq!(x, first); + assert_eq!(y, second); + n = 1; + } + assert_eq!(n, 1); +} diff --git a/tests/ui/rfc-2497-if-let-chains/ast-pretty-check.rs b/tests/ui/rfc-2497-if-let-chains/ast-pretty-check.rs new file mode 100644 index 000000000..69bc189dd --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/ast-pretty-check.rs @@ -0,0 +1,6 @@ +// check-pass +// compile-flags: -Z unpretty=expanded + +fn main() { + if let 0 = 1 {} +} diff --git a/tests/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout b/tests/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout new file mode 100644 index 000000000..e737ef26e --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout @@ -0,0 +1,10 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// check-pass +// compile-flags: -Z unpretty=expanded + +fn main() { if let 0 = 1 {} } diff --git a/tests/ui/rfc-2497-if-let-chains/chains-without-let.rs b/tests/ui/rfc-2497-if-let-chains/chains-without-let.rs new file mode 100644 index 000000000..e0dded152 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/chains-without-let.rs @@ -0,0 +1,20 @@ +fn and_chain() { + let z; + if true && { z = 3; true} && z == 3 {} + //~^ ERROR E0381 +} + +fn and_chain_2() { + let z; + true && { z = 3; true} && z == 3; + //~^ ERROR E0381 +} + +fn or_chain() { + let z; + if false || { z = 3; false} || z == 3 {} + //~^ ERROR E0381 +} + +fn main() { +} diff --git a/tests/ui/rfc-2497-if-let-chains/chains-without-let.stderr b/tests/ui/rfc-2497-if-let-chains/chains-without-let.stderr new file mode 100644 index 000000000..30d5a6779 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/chains-without-let.stderr @@ -0,0 +1,33 @@ +error[E0381]: used binding `z` is possibly-uninitialized + --> $DIR/chains-without-let.rs:3:34 + | +LL | let z; + | - binding declared here but left uninitialized +LL | if true && { z = 3; true} && z == 3 {} + | ----- ^ `z` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions + +error[E0381]: used binding `z` is possibly-uninitialized + --> $DIR/chains-without-let.rs:9:31 + | +LL | let z; + | - binding declared here but left uninitialized +LL | true && { z = 3; true} && z == 3; + | ----- ^ `z` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions + +error[E0381]: used binding `z` is possibly-uninitialized + --> $DIR/chains-without-let.rs:15:36 + | +LL | let z; + | - binding declared here but left uninitialized +LL | if false || { z = 3; false} || z == 3 {} + | ----- ^ `z` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfc-2497-if-let-chains/disallowed-positions.rs new file mode 100644 index 000000000..2a9a5472b --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -0,0 +1,480 @@ +// Here we test that `lowering` behaves correctly wrt. `let $pats = $expr` expressions. +// +// We want to make sure that `let` is banned in situations other than: +// +// expr = +// | ... +// | "if" expr_with_let block {"else" block}? +// | {label ":"}? while" expr_with_let block +// ; +// +// expr_with_let = +// | "let" top_pats "=" expr +// | expr_with_let "&&" expr_with_let +// | "(" expr_with_let ")" +// | expr +// ; +// +// To that end, we check some positions which is not part of the language above. + +#![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. + +#![allow(irrefutable_let_patterns)] + +use std::ops::Range; + +fn main() {} + +fn _if() { + if (let 0 = 1) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + if (((let 0 = 1))) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + if (let 0 = 1) && true {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + if true && (let 0 = 1) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + if (let 0 = 1) && (let 0 = 1) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + + if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement +} + +fn _while() { + while (let 0 = 1) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + while (((let 0 = 1))) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + while (let 0 = 1) && true {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + while true && (let 0 = 1) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + while (let 0 = 1) && (let 0 = 1) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + + while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement +} + +fn _macros() { + macro_rules! use_expr { + ($e:expr) => { + if $e {} + while $e {} + } + } + use_expr!((let 0 = 1 && 0 == 0)); + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + use_expr!((let 0 = 1)); + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement +} + +fn nested_within_if_expr() { + if &let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + if !let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if *let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR type `bool` cannot be dereferenced + //~| ERROR expected expression, found `let` statement + if -let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR cannot apply unary operator `-` to type `bool` + //~| ERROR expected expression, found `let` statement + + fn _check_try_binds_tighter() -> Result<(), ()> { + if let 0 = 0? {} + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + Ok(()) + } + if (let 0 = 0)? {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR the `?` operator can only be used in a function that returns `Result` + //~| ERROR expected expression, found `let` statement + + if true || let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if true && (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + if true || (true && let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + let mut x = true; + if x = let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + if true..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + if ..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + if (let 0 = 0).. {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + // Binds as `(let ... = true)..true &&/|| false`. + if let Range { start: _, end: _ } = true..true && false {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + if let Range { start: _, end: _ } = true..true || false {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + + // Binds as `(let Range { start: F, end } = F)..(|| true)`. + const F: fn() -> bool = || true; + if let Range { start: F, end } = F..|| true {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + + // Binds as `(let Range { start: true, end } = t)..(&&false)`. + let t = &&true; + if let Range { start: true, end } = t..&&false {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + + if let true = let true = true {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement +} + +fn nested_within_while_expr() { + while &let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + while !let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while *let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR type `bool` cannot be dereferenced + //~| ERROR expected expression, found `let` statement + while -let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR cannot apply unary operator `-` to type `bool` + //~| ERROR expected expression, found `let` statement + + fn _check_try_binds_tighter() -> Result<(), ()> { + while let 0 = 0? {} + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + Ok(()) + } + while (let 0 = 0)? {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR the `?` operator can only be used in a function that returns `Result` + //~| ERROR expected expression, found `let` statement + + while true || let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while true && (true || let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + while true || (true && let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + let mut x = true; + while x = let 0 = 0 {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + while true..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + while ..(let 0 = 0) {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + while (let 0 = 0).. {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + // Binds as `(let ... = true)..true &&/|| false`. + while let Range { start: _, end: _ } = true..true && false {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + while let Range { start: _, end: _ } = true..true || false {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + + // Binds as `(let Range { start: F, end } = F)..(|| true)`. + const F: fn() -> bool = || true; + while let Range { start: F, end } = F..|| true {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + + // Binds as `(let Range { start: true, end } = t)..(&&false)`. + let t = &&true; + while let Range { start: true, end } = t..&&false {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + + while let true = let true = true {} + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement +} + +fn not_error_because_clarified_intent() { + if let Range { start: _, end: _ } = (true..true || false) { } + + if let Range { start: _, end: _ } = (true..true && false) { } + + while let Range { start: _, end: _ } = (true..true || false) { } + + while let Range { start: _, end: _ } = (true..true && false) { } +} + +fn outside_if_and_while_expr() { + &let 0 = 0; + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + !let 0 = 0; + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + *let 0 = 0; + //~^ ERROR `let` expressions are not supported here + //~| ERROR type `bool` cannot be dereferenced + //~| ERROR expected expression, found `let` statement + -let 0 = 0; + //~^ ERROR `let` expressions are not supported here + //~| ERROR cannot apply unary operator `-` to type `bool` + //~| ERROR expected expression, found `let` statement + + fn _check_try_binds_tighter() -> Result<(), ()> { + let 0 = 0?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + Ok(()) + } + (let 0 = 0)?; + //~^ ERROR `let` expressions are not supported here + //~| ERROR the `?` operator can only be used in a function that returns `Result` + //~| ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR expected expression, found `let` statement + + true || let 0 = 0; + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + (true || let 0 = 0); + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + true && (true || let 0 = 0); + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + let mut x = true; + x = let 0 = 0; + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + true..(let 0 = 0); + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + ..(let 0 = 0); + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + (let 0 = 0)..; + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + + (let Range { start: _, end: _ } = true..true || false); + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + + (let true = let true = true); + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + + { + #[cfg(FALSE)] + let x = true && let y = 1; + //~^ ERROR expected expression, found `let` statement + } + + #[cfg(FALSE)] + { + [1, 2, 3][let _ = ()] + //~^ ERROR expected expression, found `let` statement + } + + // Check function tail position. + &let 0 = 0 + //~^ ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement +} + +// Let's make sure that `let` inside const generic arguments are considered. +fn inside_const_generic_arguments() { + struct A; + impl A<{B}> { const O: u32 = 5; } + + if let A::<{ + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + }>::O = 5 {} + + while let A::<{ + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + }>::O = 5 {} + + if A::<{ + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + }>::O == 5 {} + + // In the cases above we have `ExprKind::Block` to help us out. + // Below however, we would not have a block and so an implementation might go + // from visiting expressions to types without banning `let` expressions down the tree. + // This tests ensures that we are not caught by surprise should the parser + // admit non-IDENT expressions in const generic arguments. + + if A::< + true && let 1 = 1 + //~^ ERROR `let` expressions are not supported here + //~| ERROR expressions must be enclosed in braces + //~| ERROR expected expression, found `let` statement + >::O == 5 {} +} + +fn with_parenthesis() { + let opt = Some(Some(1i32)); + + if (let Some(a) = opt && true) { + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + } + + if (let Some(a) = opt) && true { + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + } + if (let Some(a) = opt) && (let Some(b) = a) { + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + } + if let Some(a) = opt && (true && true) { + } + + if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + } + if (let Some(a) = opt && (let Some(b) = a)) && true { + //~^ ERROR `let` expressions are not supported here + //~| ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + } + if (let Some(a) = opt && (true)) && true { + //~^ ERROR `let` expressions are not supported here + //~| ERROR expected expression, found `let` statement + } + + if (true && (true)) && let Some(a) = opt { + } + if (true) && let Some(a) = opt { + } + if true && let Some(a) = opt { + } + + let fun = || true; + if let true = (true && fun()) && (true) { + } + + #[cfg(FALSE)] + let x = (true && let y = 1); + //~^ ERROR expected expression, found `let` statement + + #[cfg(FALSE)] + { + ([1, 2, 3][let _ = ()]) + //~^ ERROR expected expression, found `let` statement + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr new file mode 100644 index 000000000..3028f8dbd --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -0,0 +1,1911 @@ +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:29:9 + | +LL | if (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:33:11 + | +LL | if (((let 0 = 1))) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:37:9 + | +LL | if (let 0 = 1) && true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:45:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:45:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:51:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:51:48 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:51:61 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:61:12 + | +LL | while (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:65:14 + | +LL | while (((let 0 = 1))) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:69:12 + | +LL | while (let 0 = 1) && true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:73:20 + | +LL | while true && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:77:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:77:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:83:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:83:51 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:83:64 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:110:9 + | +LL | if &let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:115:9 + | +LL | if !let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:118:9 + | +LL | if *let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:122:9 + | +LL | if -let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:132:9 + | +LL | if (let 0 = 0)? {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:138:16 + | +LL | if true || let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:141:17 + | +LL | if (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:144:25 + | +LL | if true && (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:147:25 + | +LL | if true || (true && let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:152:12 + | +LL | if x = let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:157:15 + | +LL | if true..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:161:11 + | +LL | if ..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:165:9 + | +LL | if (let 0 = 0).. {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:196:19 + | +LL | if let true = let true = true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:202:12 + | +LL | while &let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:207:12 + | +LL | while !let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:210:12 + | +LL | while *let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:214:12 + | +LL | while -let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:224:12 + | +LL | while (let 0 = 0)? {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:230:19 + | +LL | while true || let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:233:20 + | +LL | while (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:236:28 + | +LL | while true && (true || let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:239:28 + | +LL | while true || (true && let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:244:15 + | +LL | while x = let 0 = 0 {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:249:18 + | +LL | while true..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:253:14 + | +LL | while ..(let 0 = 0) {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:257:12 + | +LL | while (let 0 = 0).. {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:288:22 + | +LL | while let true = let true = true {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:304:6 + | +LL | &let 0 = 0; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:308:6 + | +LL | !let 0 = 0; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:311:6 + | +LL | *let 0 = 0; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:315:6 + | +LL | -let 0 = 0; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:325:6 + | +LL | (let 0 = 0)?; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:331:13 + | +LL | true || let 0 = 0; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:334:14 + | +LL | (true || let 0 = 0); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:337:22 + | +LL | true && (true || let 0 = 0); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:342:9 + | +LL | x = let 0 = 0; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:346:12 + | +LL | true..(let 0 = 0); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:349:8 + | +LL | ..(let 0 = 0); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:352:6 + | +LL | (let 0 = 0)..; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:356:6 + | +LL | (let Range { start: _, end: _ } = true..true || false); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:361:6 + | +LL | (let true = let true = true); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:361:17 + | +LL | (let true = let true = true); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:368:25 + | +LL | let x = true && let y = 1; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:374:19 + | +LL | [1, 2, 3][let _ = ()] + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:379:6 + | +LL | &let 0 = 0 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:391:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:397:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:403:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:415:17 + | +LL | true && let 1 = 1 + | ^^^ + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/disallowed-positions.rs:415:9 + | +LL | true && let 1 = 1 + | ^^^^^^^^^^^^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | { true && let 1 = 1 } + | + + + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:425:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:430:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:434:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:434:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:443:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:443:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:449:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:449:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:455:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:472:22 + | +LL | let x = (true && let y = 1); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:477:20 + | +LL | ([1, 2, 3][let _ = ()]) + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:99:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:103:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:29:9 + | +LL | if (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:29:9 + | +LL | if (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:33:11 + | +LL | if (((let 0 = 1))) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:33:11 + | +LL | if (((let 0 = 1))) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:37:9 + | +LL | if (let 0 = 1) && true {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:37:9 + | +LL | if (let 0 = 1) && true {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:45:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:45:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:45:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:45:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:51:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:51:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:51:48 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:51:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:51:61 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:51:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:61:12 + | +LL | while (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:61:12 + | +LL | while (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:65:14 + | +LL | while (((let 0 = 1))) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:65:14 + | +LL | while (((let 0 = 1))) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:69:12 + | +LL | while (let 0 = 1) && true {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:69:12 + | +LL | while (let 0 = 1) && true {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:73:20 + | +LL | while true && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:73:20 + | +LL | while true && (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:77:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:77:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:77:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:77:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:83:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:83:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:83:51 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:83:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:83:64 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:83:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:99:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:99:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:99:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:99:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:103:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:103:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:103:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:103:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:110:9 + | +LL | if &let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:115:9 + | +LL | if !let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:118:9 + | +LL | if *let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:122:9 + | +LL | if -let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:132:9 + | +LL | if (let 0 = 0)? {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:132:9 + | +LL | if (let 0 = 0)? {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:138:16 + | +LL | if true || let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:138:13 + | +LL | if true || let 0 = 0 {} + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:141:17 + | +LL | if (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:141:14 + | +LL | if (true || let 0 = 0) {} + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:144:25 + | +LL | if true && (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:144:22 + | +LL | if true && (true || let 0 = 0) {} + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:147:25 + | +LL | if true || (true && let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:147:17 + | +LL | if true || (true && let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:152:12 + | +LL | if x = let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:157:15 + | +LL | if true..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:157:15 + | +LL | if true..(let 0 = 0) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:161:11 + | +LL | if ..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:161:11 + | +LL | if ..(let 0 = 0) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:165:9 + | +LL | if (let 0 = 0).. {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:165:9 + | +LL | if (let 0 = 0).. {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:171:8 + | +LL | if let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:175:8 + | +LL | if let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:182:8 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:190:8 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:196:19 + | +LL | if let true = let true = true {} + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:202:12 + | +LL | while &let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:207:12 + | +LL | while !let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:210:12 + | +LL | while *let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:214:12 + | +LL | while -let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:224:12 + | +LL | while (let 0 = 0)? {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:224:12 + | +LL | while (let 0 = 0)? {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:230:19 + | +LL | while true || let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:230:16 + | +LL | while true || let 0 = 0 {} + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:233:20 + | +LL | while (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:233:17 + | +LL | while (true || let 0 = 0) {} + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:236:28 + | +LL | while true && (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:236:25 + | +LL | while true && (true || let 0 = 0) {} + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:239:28 + | +LL | while true || (true && let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:239:20 + | +LL | while true || (true && let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:244:15 + | +LL | while x = let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:249:18 + | +LL | while true..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:249:18 + | +LL | while true..(let 0 = 0) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:253:14 + | +LL | while ..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:253:14 + | +LL | while ..(let 0 = 0) {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:257:12 + | +LL | while (let 0 = 0).. {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:257:12 + | +LL | while (let 0 = 0).. {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:263:11 + | +LL | while let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:267:11 + | +LL | while let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:274:11 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:282:11 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:288:22 + | +LL | while let true = let true = true {} + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:304:6 + | +LL | &let 0 = 0; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:308:6 + | +LL | !let 0 = 0; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:311:6 + | +LL | *let 0 = 0; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:315:6 + | +LL | -let 0 = 0; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:325:6 + | +LL | (let 0 = 0)?; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:325:6 + | +LL | (let 0 = 0)?; + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:331:13 + | +LL | true || let 0 = 0; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:331:10 + | +LL | true || let 0 = 0; + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:334:14 + | +LL | (true || let 0 = 0); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:334:11 + | +LL | (true || let 0 = 0); + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:337:22 + | +LL | true && (true || let 0 = 0); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:337:19 + | +LL | true && (true || let 0 = 0); + | ^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:342:9 + | +LL | x = let 0 = 0; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:346:12 + | +LL | true..(let 0 = 0); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:346:12 + | +LL | true..(let 0 = 0); + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:349:8 + | +LL | ..(let 0 = 0); + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:349:8 + | +LL | ..(let 0 = 0); + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:352:6 + | +LL | (let 0 = 0)..; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:352:6 + | +LL | (let 0 = 0)..; + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:356:6 + | +LL | (let Range { start: _, end: _ } = true..true || false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:361:6 + | +LL | (let true = let true = true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:361:6 + | +LL | (let true = let true = true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:379:6 + | +LL | &let 0 = 0 + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:391:17 + | +LL | true && let 1 = 1 + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:397:17 + | +LL | true && let 1 = 1 + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:403:17 + | +LL | true && let 1 = 1 + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:415:17 + | +LL | true && let 1 = 1 + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:425:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:425:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:430:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:430:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:434:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:434:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:434:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:434:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:443:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:443:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:443:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:443:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:449:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:449:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:449:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:449:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/disallowed-positions.rs:455:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:455:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:110:8 + | +LL | if &let 0 = 0 {} + | ^^^^^^^^^^ expected `bool`, found `&bool` + | +help: consider removing the borrow + | +LL - if &let 0 = 0 {} +LL + if let 0 = 0 {} + | + +error[E0614]: type `bool` cannot be dereferenced + --> $DIR/disallowed-positions.rs:118:8 + | +LL | if *let 0 = 0 {} + | ^^^^^^^^^^ + +error[E0600]: cannot apply unary operator `-` to type `bool` + --> $DIR/disallowed-positions.rs:122:8 + | +LL | if -let 0 = 0 {} + | ^^^^^^^^^^ cannot apply unary operator `-` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:132:8 + | +LL | if (let 0 = 0)? {} + | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` + | + = help: the trait `Try` is not implemented for `bool` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/disallowed-positions.rs:132:19 + | +LL | fn nested_within_if_expr() { + | -------------------------- this function should return `Result` or `Option` to accept `?` +... +LL | if (let 0 = 0)? {} + | ^ cannot use the `?` operator in a function that returns `()` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:152:8 + | +LL | if x = let 0 = 0 {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if x == let 0 = 0 {} + | + + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:157:8 + | +LL | if true..(let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:161:8 + | +LL | if ..(let 0 = 0) {} + | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` + | + = note: expected type `bool` + found struct `RangeTo` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:165:8 + | +LL | if (let 0 = 0).. {} + | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` + | + = note: expected type `bool` + found struct `RangeFrom` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:171:12 + | +LL | if let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:171:8 + | +LL | if let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:175:12 + | +LL | if let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:175:8 + | +LL | if let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:182:12 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` + | | + | expected fn pointer, found struct `Range` + | + = note: expected fn pointer `fn() -> bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:182:41 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^ expected `bool`, found closure + | + = note: expected type `bool` + found closure `[closure@$DIR/disallowed-positions.rs:182:41: 182:43]` +help: use parentheses to call this closure + | +LL | if let Range { start: F, end } = F..(|| true)() {} + | + +++ + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:182:8 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:190:12 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:190:44 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^ expected `bool`, found `&&bool` + | +help: consider removing the `&&` + | +LL - if let Range { start: true, end } = t..&&false {} +LL + if let Range { start: true, end } = t..false {} + | + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:190:8 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:128:20 + | +LL | if let 0 = 0? {} + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the trait `Try` is not implemented for `{integer}` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:202:11 + | +LL | while &let 0 = 0 {} + | ^^^^^^^^^^ expected `bool`, found `&bool` + | +help: consider removing the borrow + | +LL - while &let 0 = 0 {} +LL + while let 0 = 0 {} + | + +error[E0614]: type `bool` cannot be dereferenced + --> $DIR/disallowed-positions.rs:210:11 + | +LL | while *let 0 = 0 {} + | ^^^^^^^^^^ + +error[E0600]: cannot apply unary operator `-` to type `bool` + --> $DIR/disallowed-positions.rs:214:11 + | +LL | while -let 0 = 0 {} + | ^^^^^^^^^^ cannot apply unary operator `-` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:224:11 + | +LL | while (let 0 = 0)? {} + | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` + | + = help: the trait `Try` is not implemented for `bool` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/disallowed-positions.rs:224:22 + | +LL | fn nested_within_while_expr() { + | ----------------------------- this function should return `Result` or `Option` to accept `?` +... +LL | while (let 0 = 0)? {} + | ^ cannot use the `?` operator in a function that returns `()` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:244:11 + | +LL | while x = let 0 = 0 {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | while x == let 0 = 0 {} + | + + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:249:11 + | +LL | while true..(let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:253:11 + | +LL | while ..(let 0 = 0) {} + | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo` + | + = note: expected type `bool` + found struct `RangeTo` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:257:11 + | +LL | while (let 0 = 0).. {} + | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom` + | + = note: expected type `bool` + found struct `RangeFrom` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:263:15 + | +LL | while let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:263:11 + | +LL | while let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:267:15 + | +LL | while let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:267:11 + | +LL | while let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:274:15 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` + | | + | expected fn pointer, found struct `Range` + | + = note: expected fn pointer `fn() -> bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:274:44 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^ expected `bool`, found closure + | + = note: expected type `bool` + found closure `[closure@$DIR/disallowed-positions.rs:274:44: 274:46]` +help: use parentheses to call this closure + | +LL | while let Range { start: F, end } = F..(|| true)() {} + | + +++ + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:274:11 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:282:15 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:282:47 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^ expected `bool`, found `&&bool` + | +help: consider removing the `&&` + | +LL - while let Range { start: true, end } = t..&&false {} +LL + while let Range { start: true, end } = t..false {} + | + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:282:11 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:220:23 + | +LL | while let 0 = 0? {} + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the trait `Try` is not implemented for `{integer}` + +error[E0614]: type `bool` cannot be dereferenced + --> $DIR/disallowed-positions.rs:311:5 + | +LL | *let 0 = 0; + | ^^^^^^^^^^ + +error[E0600]: cannot apply unary operator `-` to type `bool` + --> $DIR/disallowed-positions.rs:315:5 + | +LL | -let 0 = 0; + | ^^^^^^^^^^ cannot apply unary operator `-` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:325:5 + | +LL | (let 0 = 0)?; + | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` + | + = help: the trait `Try` is not implemented for `bool` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/disallowed-positions.rs:325:16 + | +LL | fn outside_if_and_while_expr() { + | ------------------------------ this function should return `Result` or `Option` to accept `?` +... +LL | (let 0 = 0)?; + | ^ cannot use the `?` operator in a function that returns `()` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:356:10 + | +LL | (let Range { start: _, end: _ } = true..true || false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found struct `Range` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:379:5 + | +LL | fn outside_if_and_while_expr() { + | - help: try adding a return type: `-> &bool` +... +LL | &let 0 = 0 + | ^^^^^^^^^^ expected `()`, found `&bool` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:321:17 + | +LL | let 0 = 0?; + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the trait `Try` is not implemented for `{integer}` + +error: aborting due to 215 previous errors + +Some errors have detailed explanations: E0277, E0308, E0600, E0614. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs new file mode 100644 index 000000000..2a6c14435 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs @@ -0,0 +1,55 @@ +#![feature(let_chains)] + +fn main() { + let opt = Some(1i32); + + let Some(n) = opt else { + return; + }; + let Some(n) = opt && n == 1 else { + //~^ ERROR a `&&` expression cannot be directly assigned in `let...else` + //~| ERROR mismatched types + //~| ERROR mismatched types + return; + }; + let Some(n) = opt && let another = n else { + //~^ ERROR a `&&` expression cannot be directly assigned in `let...else` + //~| ERROR `let` expressions are not supported here + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR expected expression, found `let` statement + return; + }; + + if let Some(n) = opt else { + //~^ ERROR this `if` expression is missing a block after the condition + return; + }; + if let Some(n) = opt && n == 1 else { + //~^ ERROR this `if` expression is missing a block after the condition + return; + }; + if let Some(n) = opt && let another = n else { + //~^ ERROR this `if` expression is missing a block after the condition + return; + }; + + { + while let Some(n) = opt else { + //~^ ERROR expected `{`, found keyword `else` + return; + }; + } + { + while let Some(n) = opt && n == 1 else { + //~^ ERROR expected `{`, found keyword `else` + return; + }; + } + { + while let Some(n) = opt && let another = n else { + //~^ ERROR expected `{`, found keyword `else` + return; + }; + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr new file mode 100644 index 000000000..498a112fa --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr @@ -0,0 +1,142 @@ +error: a `&&` expression cannot be directly assigned in `let...else` + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19 + | +LL | let Some(n) = opt && n == 1 else { + | ^^^^^^^^^^^^^ + | +help: wrap the expression in parentheses + | +LL | let Some(n) = (opt && n == 1) else { + | + + + +error: expected expression, found `let` statement + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26 + | +LL | let Some(n) = opt && let another = n else { + | ^^^ + +error: a `&&` expression cannot be directly assigned in `let...else` + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19 + | +LL | let Some(n) = opt && let another = n else { + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: wrap the expression in parentheses + | +LL | let Some(n) = (opt && let another = n) else { + | + + + +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:5 + | +LL | if let Some(n) = opt else { + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:25 + | +LL | if let Some(n) = opt else { + | ^ + +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5 + | +LL | if let Some(n) = opt && n == 1 else { + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:35 + | +LL | if let Some(n) = opt && n == 1 else { + | ^ + +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:5 + | +LL | if let Some(n) = opt && let another = n else { + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:44 + | +LL | if let Some(n) = opt && let another = n else { + | ^ + +error: expected `{`, found keyword `else` + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:38:33 + | +LL | while let Some(n) = opt else { + | ----- ----------------- ^^^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + +error: expected `{`, found keyword `else` + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:44:43 + | +LL | while let Some(n) = opt && n == 1 else { + | ----- --------------------------- ^^^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + +error: expected `{`, found keyword `else` + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:50:52 + | +LL | while let Some(n) = opt && let another = n else { + | ----- ------------------------------------ ^^^^ expected `{` + | | | + | | this `while` condition successfully parsed + | while parsing the body of this `while` expression + +error: `let` expressions are not supported here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26 + | +LL | let Some(n) = opt && let another = n else { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0308]: mismatched types + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19 + | +LL | let Some(n) = opt && n == 1 else { + | ^^^ expected `bool`, found enum `Option` + | + = note: expected type `bool` + found enum `Option` + +error[E0308]: mismatched types + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:9 + | +LL | let Some(n) = opt && n == 1 else { + | ^^^^^^^ ------------- this expression has type `bool` + | | + | expected `bool`, found enum `Option` + | + = note: expected type `bool` + found enum `Option<_>` + +error[E0308]: mismatched types + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19 + | +LL | let Some(n) = opt && let another = n else { + | ^^^ expected `bool`, found enum `Option` + | + = note: expected type `bool` + found enum `Option` + +error[E0308]: mismatched types + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:9 + | +LL | let Some(n) = opt && let another = n else { + | ^^^^^^^ ---------------------- this expression has type `bool` + | | + | expected `bool`, found enum `Option` + | + = note: expected type `bool` + found enum `Option<_>` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfc-2497-if-let-chains/feature-gate.rs new file mode 100644 index 000000000..2b407ef51 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/feature-gate.rs @@ -0,0 +1,62 @@ +// gate-test-let_chains + +// Here we test feature gating for ´let_chains`. +// See `disallowed-positions.rs` for the grammar +// defining the language for gated allowed positions. + +#![allow(irrefutable_let_patterns)] + +use std::ops::Range; + +fn _if() { + if let 0 = 1 {} // Stable! + + if true && let 0 = 1 {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let 0 = 1 && true {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let Range { start: _, end: _ } = (true..true) && false {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + if let 1 = 1 && let true = { true } && false { + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR `let` expressions in this position are unstable [E0658] + } +} + +fn _while() { + while let 0 = 1 {} // Stable! + + while true && let 0 = 1 {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + while let 0 = 1 && true {} + //~^ ERROR `let` expressions in this position are unstable [E0658] + + while let Range { start: _, end: _ } = (true..true) && false {} + //~^ ERROR `let` expressions in this position are unstable [E0658] +} + +fn _macros() { + macro_rules! noop_expr { ($e:expr) => {}; } + + noop_expr!((let 0 = 1)); + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR expected expression, found `let` statement + + macro_rules! use_expr { + ($e:expr) => { + if $e {} + while $e {} + } + } + #[cfg(FALSE)] (let 0 = 1); + //~^ ERROR `let` expressions in this position are unstable [E0658] + //~| ERROR expected expression, found `let` statement + use_expr!(let 0 = 1); + //~^ ERROR no rules expected the token `let` +} + +fn main() {} diff --git a/tests/ui/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfc-2497-if-let-chains/feature-gate.stderr new file mode 100644 index 000000000..7a43b71fc --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/feature-gate.stderr @@ -0,0 +1,120 @@ +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:55:20 + | +LL | #[cfg(FALSE)] (let 0 = 1); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/feature-gate.rs:45:17 + | +LL | noop_expr!((let 0 = 1)); + | ^^^ + +error: no rules expected the token `let` + --> $DIR/feature-gate.rs:58:15 + | +LL | macro_rules! use_expr { + | --------------------- when calling this macro +... +LL | use_expr!(let 0 = 1); + | ^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> $DIR/feature-gate.rs:50:10 + | +LL | ($e:expr) => { + | ^^^^^^^ + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:14:16 + | +LL | if true && let 0 = 1 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:17:8 + | +LL | if let 0 = 1 && true {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:20:8 + | +LL | if let Range { start: _, end: _ } = (true..true) && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:23:8 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:23:21 + | +LL | if let 1 = 1 && let true = { true } && false { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:32:19 + | +LL | while true && let 0 = 1 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:35:11 + | +LL | while let 0 = 1 && true {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:38:11 + | +LL | while let Range { start: _, end: _ } = (true..true) && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:55:20 + | +LL | #[cfg(FALSE)] (let 0 = 1); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/feature-gate.rs:45:17 + | +LL | noop_expr!((let 0 = 1)); + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs new file mode 100644 index 000000000..a942d1f4c --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs @@ -0,0 +1,45 @@ +#![feature(let_chains)] + +fn main() { + let _opt = Some(1i32); + + #[cfg(FALSE)] + { + let _ = &&let Some(x) = Some(42); + //~^ ERROR expected expression, found `let` statement + } + #[cfg(FALSE)] + { + if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { + //~^ ERROR expected expression, found `let` statement + //~| ERROR expected expression, found `let` statement + true + } + } + + #[cfg(FALSE)] + { + if let Some(elem) = _opt && { + [1, 2, 3][let _ = ()]; + //~^ ERROR expected expression, found `let` statement + true + } { + } + } + + #[cfg(FALSE)] + { + if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { + //~^ ERROR expected expression, found `let` statement + true + } + } + #[cfg(FALSE)] + { + if let a = 1 && { + let x = let y = 1; + //~^ ERROR expected expression, found `let` statement + } { + } + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr b/tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr new file mode 100644 index 000000000..d1ce83c72 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.stderr @@ -0,0 +1,38 @@ +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:8:19 + | +LL | let _ = &&let Some(x) = Some(42); + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:13:47 + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:13:57 + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:23:23 + | +LL | [1, 2, 3][let _ = ()]; + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:32:47 + | +LL | if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/invalid-let-in-a-valid-let-context.rs:40:21 + | +LL | let x = let y = 1; + | ^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/tests/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr new file mode 100644 index 000000000..be4a52315 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr @@ -0,0 +1,115 @@ +error: leading irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:13:8 + | +LL | if let first = &opt && let Some(ref second) = first && let None = second.start {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it outside of the construct +note: the lint level is defined here + --> $DIR/irrefutable-lets.rs:6:30 + | +LL | #![cfg_attr(disallowed, deny(irrefutable_let_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: irrefutable `if let` patterns + --> $DIR/irrefutable-lets.rs:19:8 + | +LL | if let first = &opt && let (a, b) = (1, 2) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: these patterns will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + +error: leading irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:22:8 + | +LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it outside of the construct + +error: trailing irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:22:87 + | +LL | if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {} + | ^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it into the body + +error: trailing irrefutable patterns in let chain + --> $DIR/irrefutable-lets.rs:26:37 + | +LL | if let Some(ref first) = opt && let second = first && let _third = second {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: these patterns will always match + = help: consider moving them into the body + +error: leading irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:29:8 + | +LL | if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it outside of the construct + +error: leading irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:32:8 + | +LL | if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it outside of the construct + +error: leading irrefutable pattern in let chain + --> $DIR/irrefutable-lets.rs:35:8 + | +LL | if let first = &opt && let None = Some(1) {} + | ^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match + = help: consider moving it outside of the construct + +error: irrefutable `if let` guard patterns + --> $DIR/irrefutable-lets.rs:44:28 + | +LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: these patterns will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm + +error: trailing irrefutable patterns in let chain + --> $DIR/irrefutable-lets.rs:59:16 + | +LL | && let v = local_end && let w = v => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: these patterns will always match + = help: consider moving them into the body + +error: irrefutable `while let` patterns + --> $DIR/irrefutable-lets.rs:68:11 + | +LL | while let first = &opt && let (a, b) = (1, 2) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: these patterns will always match, so the loop will never exit + = help: consider instead using a `loop { ... }` with a `let` inside it + +error: trailing irrefutable patterns in let chain + --> $DIR/irrefutable-lets.rs:71:40 + | +LL | while let Some(ref first) = opt && let second = first && let _third = second {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: these patterns will always match + = help: consider moving them into the body + +error: aborting due to 12 previous errors + diff --git a/tests/ui/rfc-2497-if-let-chains/irrefutable-lets.rs b/tests/ui/rfc-2497-if-let-chains/irrefutable-lets.rs new file mode 100644 index 000000000..9afb6853b --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/irrefutable-lets.rs @@ -0,0 +1,78 @@ +// revisions: allowed disallowed +//[allowed] check-pass + +#![feature(if_let_guard, let_chains)] +#![cfg_attr(allowed, allow(irrefutable_let_patterns))] +#![cfg_attr(disallowed, deny(irrefutable_let_patterns))] + +use std::ops::Range; + +fn main() { + let opt = Some(None..Some(1)); + + if let first = &opt && let Some(ref second) = first && let None = second.start {} + //[disallowed]~^ ERROR leading irrefutable pattern in let chain + + // No lint as the irrefutable pattern is surrounded by other stuff + if 4 * 2 == 0 && let first = &opt && let Some(ref second) = first && let None = second.start {} + + if let first = &opt && let (a, b) = (1, 2) {} + //[disallowed]~^ ERROR irrefutable `if let` patterns + + if let first = &opt && let Some(ref second) = first && let None = second.start && let v = 0 {} + //[disallowed]~^ ERROR leading irrefutable pattern in let chain + //[disallowed]~^^ ERROR trailing irrefutable pattern in let chain + + if let Some(ref first) = opt && let second = first && let _third = second {} + //[disallowed]~^ ERROR trailing irrefutable patterns in let chain + + if let Range { start: local_start, end: _ } = (None..Some(1)) && let None = local_start {} + //[disallowed]~^ ERROR leading irrefutable pattern in let chain + + if let (a, b, c) = (Some(1), Some(1), Some(1)) && let None = Some(1) {} + //[disallowed]~^ ERROR leading irrefutable pattern in let chain + + if let first = &opt && let None = Some(1) {} + //[disallowed]~^ ERROR leading irrefutable pattern in let chain + + if let Some(ref first) = opt + && let Range { start: local_start, end: _ } = first + && let None = local_start { + } + + match opt { + Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {}, + //[disallowed]~^ ERROR irrefutable `if let` guard patterns + _ => {} + } + + // No error about leading irrefutable patterns: the expr on the rhs might + // use the bindings created by the match. + match opt { + Some(ref first) if let Range { start: local_start, end: _ } = first + && let None = local_start => {}, + _ => {} + } + + match opt { + Some(ref first) if let Range { start: Some(_), end: local_end } = first + && let v = local_end && let w = v => {}, + //[disallowed]~^ ERROR trailing irrefutable patterns in let chain + _ => {} + } + + // No error, despite the prefix being irrefutable: moving out could change the behaviour, + // due to possible side effects of the operation. + while let first = &opt && let Some(ref second) = first && let None = second.start {} + + while let first = &opt && let (a, b) = (1, 2) {} + //[disallowed]~^ ERROR irrefutable `while let` patterns + + while let Some(ref first) = opt && let second = first && let _third = second {} + //[disallowed]~^ ERROR trailing irrefutable patterns in let chain + + while let Some(ref first) = opt + && let Range { start: local_start, end: _ } = first + && let None = local_start { + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/issue-88498.rs b/tests/ui/rfc-2497-if-let-chains/issue-88498.rs new file mode 100644 index 000000000..3eb8a9ad0 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/issue-88498.rs @@ -0,0 +1,16 @@ +// check-pass + +pub enum UnOp { + Not(Vec<()>), +} + +pub fn foo() { + if let Some(x) = None { + match x { + UnOp::Not(_) => {} + } + } +} + +fn main() { +} diff --git a/tests/ui/rfc-2497-if-let-chains/issue-90722.rs b/tests/ui/rfc-2497-if-let-chains/issue-90722.rs new file mode 100644 index 000000000..6b7d88356 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/issue-90722.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(let_chains)] + +fn main() { + let x = Some(vec!["test"]); + + if let Some(v) = x && v.is_empty() { + println!("x == Some([])"); + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/issue-92145.rs b/tests/ui/rfc-2497-if-let-chains/issue-92145.rs new file mode 100644 index 000000000..7c7e31f4d --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/issue-92145.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(let_chains)] + +fn main() { + let opt = Some("foo bar"); + + if true && let Some(x) = opt { + println!("{}", x); + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/issue-93150.rs b/tests/ui/rfc-2497-if-let-chains/issue-93150.rs new file mode 100644 index 000000000..f90b9ab0d --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/issue-93150.rs @@ -0,0 +1,8 @@ +fn main() { + match true { + _ if let true = true && true => {} + //~^ ERROR `if let` guards are + //~| ERROR `let` expressions in this + _ => {} + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/issue-93150.stderr b/tests/ui/rfc-2497-if-let-chains/issue-93150.stderr new file mode 100644 index 000000000..b25f299a2 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/issue-93150.stderr @@ -0,0 +1,22 @@ +error[E0658]: `if let` guards are experimental + --> $DIR/issue-93150.rs:3:11 + | +LL | _ if let true = true && true => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #51114 for more information + = help: add `#![feature(if_let_guard)]` to the crate attributes to enable + = help: you can write `if matches!(, )` instead of `if let = ` + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-93150.rs:3:14 + | +LL | _ if let true = true && true => {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2497-if-let-chains/issue-99938.rs b/tests/ui/rfc-2497-if-let-chains/issue-99938.rs new file mode 100644 index 000000000..bd81ce0b1 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/issue-99938.rs @@ -0,0 +1,31 @@ +// compile-flags: -Zvalidate-mir -C opt-level=3 +// build-pass +#![feature(let_chains)] +struct TupleIter> { + inner: I, +} + +impl> Iterator for TupleIter { + type Item = (T, T, T); + + fn next(&mut self) -> Option { + let inner = &mut self.inner; + + if let Some(first) = inner.next() + && let Some(second) = inner.next() + && let Some(third) = inner.next() + { + Some((first, second, third)) + } else { + None + } + } +} + +fn main() { + let vec: Vec = Vec::new(); + let mut tup_iter = TupleIter { + inner: vec.into_iter(), + }; + tup_iter.next(); +} diff --git a/tests/ui/rfc-2497-if-let-chains/no-double-assigments.rs b/tests/ui/rfc-2497-if-let-chains/no-double-assigments.rs new file mode 100644 index 000000000..6b91c455e --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/no-double-assigments.rs @@ -0,0 +1,9 @@ +// check-pass + +fn main() { + loop { + // [1][0] should leave top scope + if true && [1][0] == 1 && true { + } + } +} diff --git a/tests/ui/rfc-2497-if-let-chains/protect-precedences.rs b/tests/ui/rfc-2497-if-let-chains/protect-precedences.rs new file mode 100644 index 000000000..fcc09b159 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/protect-precedences.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(irrefutable_let_patterns)] + +fn main() { + let x: bool; + // This should associate as: `(x = (true && false));`. + x = true && false; + assert!(!x); + + fn _f1() -> bool { + // Should associate as `(let _ = (return (true && false)))`. + if let _ = return true && false {}; + //~^ WARNING unreachable block in `if` + } + assert!(!_f1()); +} diff --git a/tests/ui/rfc-2497-if-let-chains/protect-precedences.stderr b/tests/ui/rfc-2497-if-let-chains/protect-precedences.stderr new file mode 100644 index 000000000..24b35a2ab --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/protect-precedences.stderr @@ -0,0 +1,12 @@ +warning: unreachable block in `if` or `while` expression + --> $DIR/protect-precedences.rs:13:41 + | +LL | if let _ = return true && false {}; + | -------------------- ^^ unreachable block in `if` or `while` expression + | | + | any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfc-2497-if-let-chains/then-else-blocks.rs b/tests/ui/rfc-2497-if-let-chains/then-else-blocks.rs new file mode 100644 index 000000000..e061174f6 --- /dev/null +++ b/tests/ui/rfc-2497-if-let-chains/then-else-blocks.rs @@ -0,0 +1,49 @@ +// run-pass + +#![feature(if_let_guard, let_chains)] + +fn check_if_let(opt: Option>>, value: i32) -> bool { + if let Some(first) = opt + && let Some(second) = first + && let Some(third) = second + && third == value + { + true + } + else { + false + } +} + +fn check_let_guard(opt: Option>>, value: i32) -> bool { + match opt { + Some(first) if let Some(second) = first && let Some(third) = second && third == value => { + true + } + _ => { + false + } + } +} + +fn check_while_let(opt: Option>>, value: i32) -> bool { + while let Some(first) = opt + && let Some(second) = first + && let Some(third) = second + && third == value + { + return true; + } + false +} + +fn main() { + assert_eq!(check_if_let(Some(Some(Some(1))), 1), true); + assert_eq!(check_if_let(Some(Some(Some(1))), 9), false); + + assert_eq!(check_let_guard(Some(Some(Some(1))), 1), true); + assert_eq!(check_let_guard(Some(Some(Some(1))), 9), false); + + assert_eq!(check_while_let(Some(Some(Some(1))), 1), true); + assert_eq!(check_while_let(Some(Some(Some(1))), 9), false); +} diff --git a/tests/ui/rfc-2565-param-attrs/attr-without-param.rs b/tests/ui/rfc-2565-param-attrs/attr-without-param.rs new file mode 100644 index 000000000..eeb2191ba --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/attr-without-param.rs @@ -0,0 +1,16 @@ +#[cfg(FALSE)] +impl S { + fn f(#[attr]) {} //~ ERROR expected parameter name, found `)` +} + +#[cfg(FALSE)] +impl T for S { + fn f(#[attr]) {} //~ ERROR expected parameter name, found `)` +} + +#[cfg(FALSE)] +trait T { + fn f(#[attr]); //~ ERROR expected argument name, found `)` +} + +fn main() {} diff --git a/tests/ui/rfc-2565-param-attrs/attr-without-param.stderr b/tests/ui/rfc-2565-param-attrs/attr-without-param.stderr new file mode 100644 index 000000000..26dff4d4b --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/attr-without-param.stderr @@ -0,0 +1,20 @@ +error: expected parameter name, found `)` + --> $DIR/attr-without-param.rs:3:17 + | +LL | fn f(#[attr]) {} + | ^ expected parameter name + +error: expected parameter name, found `)` + --> $DIR/attr-without-param.rs:8:17 + | +LL | fn f(#[attr]) {} + | ^ expected parameter name + +error: expected argument name, found `)` + --> $DIR/attr-without-param.rs:13:17 + | +LL | fn f(#[attr]); + | ^ expected argument name + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/tests/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs new file mode 100644 index 000000000..b62cf3120 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/auxiliary/ident-mac.rs @@ -0,0 +1,11 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn id(_: TokenStream, input: TokenStream) -> TokenStream { input } diff --git a/tests/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/tests/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs new file mode 100644 index 000000000..82c4120b4 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs @@ -0,0 +1,43 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +macro_rules! checker { + ($attr_name:ident, $expected:literal) => { + #[proc_macro_attribute] + pub fn $attr_name(attr: TokenStream, input: TokenStream) -> TokenStream { + assert_eq!(input.to_string(), $expected); + TokenStream::new() + } + } +} + +checker!(attr_extern, r#"extern "C" { fn ffi(#[a1] arg1 : i32, #[a2] ...) ; }"#); +checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1 : i32, #[a1] mut args : ...) {}"#); +checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...) ;"); +checker!(attr_free, "fn free(#[a1] arg1 : u8) { let lam = | #[a2] W(x), #[a3] y | () ; }"); +checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1 : u8) {}"); +checker!(attr_inherent_2, "fn inherent2(#[a1] & self, #[a2] arg1 : u8) {}"); +checker!(attr_inherent_3, "fn inherent3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) {}"); +checker!(attr_inherent_4, "fn inherent4 < 'a > (#[a1] self : Box < Self >, #[a2] arg1 : u8) {}"); +checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) {}"); +checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1 : u8) ;"); +checker!(attr_trait_2, "fn trait2(#[a1] & self, #[a2] arg1 : u8) ;"); +checker!(attr_trait_3, "fn trait3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) ;"); +checker!(attr_trait_4, r#"fn trait4 < 'a > +(#[a1] self : Box < Self >, #[a2] arg1 : u8, #[a3] Vec < u8 >) ;"#); +checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) ;"); +checker!(rename_params, r#"impl Foo +{ + fn hello(#[angery(true)] a : i32, #[a2] b : i32, #[what = "how"] c : u32) + {} fn + hello2(#[a1] #[a2] a : i32, #[what = "how"] b : i32, #[angery(true)] c : + u32) {} fn + hello_self(#[a1] #[a2] & self, #[a1] #[a2] a : i32, #[what = "how"] b : + i32, #[angery(true)] c : u32) {} +}"#); diff --git a/tests/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs b/tests/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs new file mode 100644 index 000000000..670303906 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs @@ -0,0 +1,21 @@ +// aux-build:param-attrs.rs + +// check-pass + +extern crate param_attrs; + +use param_attrs::rename_params; + +#[rename_params(send_help)] +impl Foo { + fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) {} + fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, #[angery(true)] c: u32) {} + fn hello_self( + #[a1] #[a2] &self, + #[a1] #[a2] a: i32, + #[what = "how"] b: i32, + #[angery(true)] c: u32 + ) {} +} + +fn main() {} diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-2018.rs b/tests/ui/rfc-2565-param-attrs/param-attrs-2018.rs new file mode 100644 index 000000000..a6f693bd5 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-2018.rs @@ -0,0 +1,6 @@ +// edition:2018 + +trait Trait2015 { fn foo(#[allow(C)] i32); } +//~^ ERROR expected one of `:`, `@`, or `|`, found `)` + +fn main() {} diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/tests/ui/rfc-2565-param-attrs/param-attrs-2018.stderr new file mode 100644 index 000000000..593821bf9 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -0,0 +1,22 @@ +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/param-attrs-2018.rs:3:41 + | +LL | trait Trait2015 { fn foo(#[allow(C)] i32); } + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); } + | +++++ +help: if this is a parameter name, give it a type + | +LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); } + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-allowed.rs b/tests/ui/rfc-2565-param-attrs/param-attrs-allowed.rs new file mode 100644 index 000000000..a547d09d0 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-allowed.rs @@ -0,0 +1,101 @@ +// check-pass +// compile-flags: --cfg something + +#![deny(unused_mut)] + +extern "C" { + fn ffi( + #[allow(unused_mut)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[forbid(unused_mut)] d: i32, + #[deny(unused_mut)] #[warn(unused_mut)] ... + ); +} + +type FnType = fn( + #[allow(unused_mut)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[forbid(unused_mut)] d: i32, + #[deny(unused_mut)] #[warn(unused_mut)] e: i32 +); + +pub fn foo( + #[allow(unused_mut)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[forbid(unused_mut)] d: i32, + #[deny(unused_mut)] #[warn(unused_mut)] _e: i32 +) {} + +// self + +struct SelfStruct {} +impl SelfStruct { + fn foo( + #[allow(unused_mut)] self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(unused_mut)] b: i32, + ) {} +} + +struct RefStruct {} +impl RefStruct { + fn foo( + #[allow(unused_mut)] &self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(unused_mut)] b: i32, + ) {} +} +trait RefTrait { + fn foo( + #[forbid(unused_mut)] &self, + #[warn(unused_mut)] a: i32 + ) {} +} +impl RefTrait for RefStruct { + fn foo( + #[forbid(unused_mut)] &self, + #[warn(unused_mut)] a: i32 + ) {} +} + +// Box + +struct BoxSelfStruct {} +impl BoxSelfStruct { + fn foo( + #[allow(unused_mut)] self: Box, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(unused_mut)] b: i32, + ) {} +} +trait BoxSelfTrait { + fn foo( + #[forbid(unused_mut)] self: Box, + #[warn(unused_mut)] a: i32 + ) {} +} +impl BoxSelfTrait for BoxSelfStruct { + fn foo( + #[forbid(unused_mut)] self: Box, + #[warn(unused_mut)] a: i32 + ) {} +} + +fn main() { + let _: unsafe extern "C" fn(_, _, _, ...) = ffi; + let _: fn(_, _, _, _) = foo; + let _: FnType = |_, _, _, _| {}; + let c = | + #[allow(unused_mut)] a: u32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(unused_mut)] c: i32, + | {}; + let _ = c(1, 2); +} diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs new file mode 100644 index 000000000..151659e35 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs @@ -0,0 +1,174 @@ +extern "C" { + fn ffi( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ); +} + +type FnType = fn( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: u32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters +); + +pub fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: u32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters +) {} + +struct SelfStruct {} +impl SelfStruct { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ) {} + + fn issue_64682_associated_fn( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ) {} +} + +struct RefStruct {} +impl RefStruct { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + &self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ) {} +} +trait RefTrait { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + &self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ) {} + + fn issue_64682_associated_fn( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ) {} +} + +impl RefTrait for RefStruct { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + &self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + ) {} +} + +fn main() { + let _ = | + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: u32, + //~^ ERROR expected non-macro attribute, found attribute macro + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32 + //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + | {}; +} diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr new file mode 100644 index 000000000..7573e39d8 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr @@ -0,0 +1,386 @@ +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:5:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:21:7 + | +LL | #[test] a: u32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:36:7 + | +LL | #[test] a: u32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:56:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:71:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:92:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:111:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:126:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:146:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:163:11 + | +LL | #[test] a: u32, + | ^^^^ not a non-macro attribute + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:3:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:7:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:9:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:11:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:13:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:19:5 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:23:5 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:25:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:27:5 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:29:5 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:34:5 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:38:5 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:40:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:42:5 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:44:5 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:51:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:54:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:58:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:60:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:62:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:64:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:69:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:73:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:75:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:77:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:79:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:87:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:90:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:94:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:96:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:98:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:100:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:106:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:109:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:113:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:115:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:117:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:119:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:124:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:128:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:130:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:132:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:134:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:141:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:144:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:148:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:150:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:152:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:154:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:161:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:165:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:167:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:169:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:171:9 + | +LL | #[no_mangle] b: i32 + | ^^^^^^^^^^^^ + +error: aborting due to 64 previous errors + diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.rs b/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.rs new file mode 100644 index 000000000..a4d9d32b5 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.rs @@ -0,0 +1,121 @@ +// compile-flags: --cfg something +// edition:2018 + +#![feature(async_closure)] +#![deny(unused_variables)] + +extern "C" { + fn ffi( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[cfg_attr(nothing, cfg(nothing))] ... + ); +} + +type FnType = fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(nothing, cfg(nothing))] c: i32, + #[cfg_attr(something, cfg(nothing))] d: i32, +); + +async fn foo_async( + #[cfg(something)] a: i32, + //~^ ERROR unused variable: `a` + #[cfg(nothing)] b: i32, +) {} +fn foo( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, +) {} + +struct RefStruct {} +impl RefStruct { + async fn bar_async( + &self, + #[cfg(something)] a: i32, + //~^ ERROR unused variable: `a` + #[cfg(nothing)] b: i32, + ) {} + fn bar( + &self, + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} + fn issue_64682_associated_fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} +} +trait RefTrait { + fn bar( + &self, + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} + fn issue_64682_associated_fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} +} +impl RefTrait for RefStruct { + fn bar( + &self, + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} + fn issue_64682_associated_fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} +} + +fn main() { + let _: unsafe extern "C" fn(_, ...) = ffi; + let _: fn(_, _) = foo; + let _: FnType = |_, _| {}; + let a = async move | + #[cfg(something)] a: i32, + //~^ ERROR unused variable: `a` + #[cfg(nothing)] b: i32, + | {}; + let c = | + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` + #[cfg_attr(something, cfg(nothing))] d: i32, + | {}; + let _ = a(1); + let _ = c(1, 2); +} diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr new file mode 100644 index 000000000..6d18d295c --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -0,0 +1,122 @@ +error: unused variable: `a` + --> $DIR/param-attrs-cfg.rs:24:23 + | +LL | #[cfg(something)] a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + | +note: the lint level is defined here + --> $DIR/param-attrs-cfg.rs:5:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:30:23 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:32:40 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `a` + --> $DIR/param-attrs-cfg.rs:41:27 + | +LL | #[cfg(something)] a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:48:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:50:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:56:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:58:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:67:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:69:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:75:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:77:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:86:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:88:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:94:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:96:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: unused variable: `a` + --> $DIR/param-attrs-cfg.rs:107:27 + | +LL | #[cfg(something)] a: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_a` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:113:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:115:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: if this is intentional, prefix it with an underscore: `_c` + +error: aborting due to 19 previous errors + diff --git a/tests/ui/rfc-2565-param-attrs/param-attrs-pretty.rs b/tests/ui/rfc-2565-param-attrs/param-attrs-pretty.rs new file mode 100644 index 000000000..1183ac65b --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/param-attrs-pretty.rs @@ -0,0 +1,61 @@ +// aux-build:param-attrs.rs + +// check-pass + +#![feature(c_variadic)] + +extern crate param_attrs; + +use param_attrs::*; + +struct W(u8); + +#[attr_extern] +extern "C" { fn ffi(#[a1] arg1: i32, #[a2] ...); } + +#[attr_extern_cvar] +unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) {} + +#[attr_alias] +type Alias = fn(#[a1] u8, #[a2] ...); + +#[attr_free] +fn free(#[a1] arg1: u8) { + let lam = |#[a2] W(x), #[a3] y| (); +} + +impl W { + #[attr_inherent_1] + fn inherent1(#[a1] self, #[a2] arg1: u8) {} + + #[attr_inherent_2] + fn inherent2(#[a1] &self, #[a2] arg1: u8) {} + + #[attr_inherent_3] + fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) {} + + #[attr_inherent_4] + fn inherent4<'a>(#[a1] self: Box, #[a2] arg1: u8) {} + + #[attr_inherent_issue_64682] + fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) {} +} + +trait A { + #[attr_trait_1] + fn trait1(#[a1] self, #[a2] arg1: u8); + + #[attr_trait_2] + fn trait2(#[a1] &self, #[a2] arg1: u8); + + #[attr_trait_3] + fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8); + + #[attr_trait_4] + fn trait4<'a>(#[a1] self: Box, #[a2] arg1: u8, #[a3] Vec); + + #[attr_trait_issue_64682] + fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8); +} + +fn main() {} diff --git a/tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs new file mode 100644 index 000000000..54f2f451b --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -0,0 +1,66 @@ +// aux-build:ident-mac.rs + +#![feature(c_variadic)] +#![allow(anonymous_parameters)] + +extern crate ident_mac; +use ident_mac::id; + +struct W(u8); + +extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } +//~^ ERROR expected non-macro attribute, found attribute macro +//~| ERROR expected non-macro attribute, found attribute macro + +unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} +//~^ ERROR expected non-macro attribute, found attribute macro + +type Alias = extern "C" fn(#[id] u8, #[id] ...); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + +fn free(#[id] arg1: u8) { + //~^ ERROR expected non-macro attribute, found attribute macro + let lam = |#[id] W(x), #[id] y: usize| (); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro +} + +impl W { + fn inherent1(#[id] self, #[id] arg1: u8) {} + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn inherent2(#[id] &self, #[id] arg1: u8) {} + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro +} + +trait A { + fn trait1(#[id] self, #[id] arg1: u8); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn trait2(#[id] &self, #[id] arg1: u8); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro + fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); + //~^ ERROR expected non-macro attribute, found attribute macro + //~| ERROR expected non-macro attribute, found attribute macro +} + +fn main() {} diff --git a/tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr new file mode 100644 index 000000000..e74d05d49 --- /dev/null +++ b/tests/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr @@ -0,0 +1,176 @@ +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:11:23 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:11:40 + | +LL | extern "C" { fn ffi(#[id] arg1: i32, #[id] ...); } + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:15:40 + | +LL | unsafe extern "C" fn cvar(arg1: i32, #[id] mut args: ...) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:18:30 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:18:40 + | +LL | type Alias = extern "C" fn(#[id] u8, #[id] ...); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:22:11 + | +LL | fn free(#[id] arg1: u8) { + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:24:18 + | +LL | let lam = |#[id] W(x), #[id] y: usize| (); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:24:30 + | +LL | let lam = |#[id] W(x), #[id] y: usize| (); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:30:20 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:30:32 + | +LL | fn inherent1(#[id] self, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:33:20 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:33:33 + | +LL | fn inherent2(#[id] &self, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:36:24 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:36:44 + | +LL | fn inherent3<'a>(#[id] &'a mut self, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:39:24 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:39:47 + | +LL | fn inherent4<'a>(#[id] self: Box, #[id] arg1: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:42:40 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:42:56 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8) {} + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:48:17 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:48:29 + | +LL | fn trait1(#[id] self, #[id] arg1: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:51:17 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:51:30 + | +LL | fn trait2(#[id] &self, #[id] arg1: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:54:21 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:54:41 + | +LL | fn trait3<'a>(#[id] &'a mut self, #[id] arg1: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:57:21 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:57:44 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:57:60 + | +LL | fn trait4<'a>(#[id] self: Box, #[id] arg1: u8, #[id] Vec); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:61:40 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); + | ^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `id` + --> $DIR/proc-macro-cannot-be-used.rs:61:56 + | +LL | fn issue_64682_associated_fn<'a>(#[id] arg1: u8, #[id] arg2: u8); + | ^^ not a non-macro attribute + +error: aborting due to 29 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs new file mode 100644 index 000000000..22d57f8be --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs @@ -0,0 +1,9 @@ +// only-windows +// only-x86 +#![feature(raw_dylib)] + +#[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] +//~^ ERROR import name type must be of the form `import_name_type = "string"` +extern "C" { } + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr new file mode 100644 index 000000000..0e95fec29 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr @@ -0,0 +1,8 @@ +error: import name type must be of the form `import_name_type = "string"` + --> $DIR/import-name-type-invalid-format.rs:5:42 + | +LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs new file mode 100644 index 000000000..7ccb0082f --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs @@ -0,0 +1,10 @@ +// ignore-tidy-linelength +// only-windows +// only-x86 +#![feature(raw_dylib)] + +#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] +//~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute +extern "C" { } + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr new file mode 100644 index 000000000..7c0e0be91 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr @@ -0,0 +1,8 @@ +error: multiple `import_name_type` arguments in a single `#[link]` attribute + --> $DIR/import-name-type-multiple.rs:6:74 + | +LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs new file mode 100644 index 000000000..f728a578d --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs @@ -0,0 +1,9 @@ +// only-windows +// only-x86 +#![feature(raw_dylib)] + +#[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] +//~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated +extern "C" { } + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr new file mode 100644 index 000000000..2b299f2fe --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr @@ -0,0 +1,8 @@ +error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated + --> $DIR/import-name-type-unknown-value.rs:5:42 + | +LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs new file mode 100644 index 000000000..ae9207864 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs @@ -0,0 +1,17 @@ +// only-windows +// only-x86 +#![feature(raw_dylib)] + +#[link(name = "foo", import_name_type = "decorated")] +//~^ ERROR import name type can only be used with link kind `raw-dylib` +extern "C" { } + +#[link(name = "bar", kind = "static", import_name_type = "decorated")] +//~^ ERROR import name type can only be used with link kind `raw-dylib` +extern "C" { } + +// Specifying `import_name_type` before `kind` shouldn't raise an error. +#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")] +extern "C" { } + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr new file mode 100644 index 000000000..5898cd875 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr @@ -0,0 +1,14 @@ +error: import name type can only be used with link kind `raw-dylib` + --> $DIR/import-name-type-unsupported-link-kind.rs:5:22 + | +LL | #[link(name = "foo", import_name_type = "decorated")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: import name type can only be used with link kind `raw-dylib` + --> $DIR/import-name-type-unsupported-link-kind.rs:9:39 + | +LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.rs new file mode 100644 index 000000000..346ea18a8 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.rs @@ -0,0 +1,7 @@ +// only-windows +// ignore-x86 +#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] +//~^ ERROR import name type is only supported on x86 +extern "C" { } + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.stderr new file mode 100644 index 000000000..b56449299 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-x86-only.stderr @@ -0,0 +1,8 @@ +error: import name type is only supported on x86 + --> $DIR/import-name-type-x86-only.rs:3:42 + | +LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs new file mode 100644 index 000000000..1a128c87a --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs @@ -0,0 +1,15 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name="foo")] +extern "C" { + #[link_name="foo"] + #[link_ordinal(42)] + //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]` + fn foo(); + #[link_name="foo"] + #[link_ordinal(5)] + //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]` + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr new file mode 100644 index 000000000..481a06d27 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr @@ -0,0 +1,14 @@ +error: cannot use `#[link_name]` with `#[link_ordinal]` + --> $DIR/link-ordinal-and-name.rs:6:5 + | +LL | #[link_ordinal(42)] + | ^^^^^^^^^^^^^^^^^^^ + +error: cannot use `#[link_name]` with `#[link_ordinal]` + --> $DIR/link-ordinal-and-name.rs:10:5 + | +LL | #[link_ordinal(5)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs new file mode 100644 index 000000000..7c8da050c --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs @@ -0,0 +1,13 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name = "foo")] +extern "C" { + #[link_ordinal("JustMonika")] + //~^ ERROR illegal ordinal format in `link_ordinal` + fn foo(); + #[link_ordinal("JustMonika")] + //~^ ERROR illegal ordinal format in `link_ordinal` + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr new file mode 100644 index 000000000..55cdcad75 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr @@ -0,0 +1,18 @@ +error: illegal ordinal format in `link_ordinal` + --> $DIR/link-ordinal-invalid-format.rs:5:5 + | +LL | #[link_ordinal("JustMonika")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: an unsuffixed integer value, e.g., `1`, is expected + +error: illegal ordinal format in `link_ordinal` + --> $DIR/link-ordinal-invalid-format.rs:8:5 + | +LL | #[link_ordinal("JustMonika")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: an unsuffixed integer value, e.g., `1`, is expected + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs new file mode 100644 index 000000000..9feed3941 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs @@ -0,0 +1,13 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name = "foo")] +extern "C" { + #[link_ordinal()] + //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + fn foo(); + #[link_ordinal()] + //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr new file mode 100644 index 000000000..853cdad8c --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr @@ -0,0 +1,18 @@ +error: incorrect number of arguments to `#[link_ordinal]` + --> $DIR/link-ordinal-missing-argument.rs:5:5 + | +LL | #[link_ordinal()] + | ^^^^^^^^^^^^^^^^^ + | + = note: the attribute requires exactly one argument + +error: incorrect number of arguments to `#[link_ordinal]` + --> $DIR/link-ordinal-missing-argument.rs:8:5 + | +LL | #[link_ordinal()] + | ^^^^^^^^^^^^^^^^^ + | + = note: the attribute requires exactly one argument + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs new file mode 100644 index 000000000..631c363d4 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs @@ -0,0 +1,14 @@ +// only-windows +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name = "foo", kind = "raw-dylib")] +extern "C" { + #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes + #[link_ordinal(2)] + fn foo(); + #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes + #[link_ordinal(2)] + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr new file mode 100644 index 000000000..c0453d2bf --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr @@ -0,0 +1,26 @@ +error: multiple `link_ordinal` attributes + --> $DIR/link-ordinal-multiple.rs:6:5 + | +LL | #[link_ordinal(1)] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/link-ordinal-multiple.rs:7:5 + | +LL | #[link_ordinal(2)] + | ^^^^^^^^^^^^^^^^^^ + +error: multiple `link_ordinal` attributes + --> $DIR/link-ordinal-multiple.rs:9:5 + | +LL | #[link_ordinal(1)] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/link-ordinal-multiple.rs:10:5 + | +LL | #[link_ordinal(2)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs new file mode 100644 index 000000000..54e614164 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs @@ -0,0 +1,24 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link_ordinal(123)] +//~^ ERROR attribute should be applied to a foreign function or static +struct Foo {} + +#[link_ordinal(123)] +//~^ ERROR attribute should be applied to a foreign function or static +fn test() {} + +#[link_ordinal(42)] +//~^ ERROR attribute should be applied to a foreign function or static +static mut imported_val: i32 = 123; + +#[link(name = "exporter", kind = "raw-dylib")] +extern { + #[link_ordinal(13)] + fn imported_function(); + + #[link_ordinal(42)] + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr new file mode 100644 index 000000000..ec4104fbe --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr @@ -0,0 +1,20 @@ +error: attribute should be applied to a foreign function or static + --> $DIR/link-ordinal-not-foreign-fn.rs:3:1 + | +LL | #[link_ordinal(123)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: attribute should be applied to a foreign function or static + --> $DIR/link-ordinal-not-foreign-fn.rs:7:1 + | +LL | #[link_ordinal(123)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: attribute should be applied to a foreign function or static + --> $DIR/link-ordinal-not-foreign-fn.rs:11:1 + | +LL | #[link_ordinal(42)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs new file mode 100644 index 000000000..46731581e --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs @@ -0,0 +1,13 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name = "foo")] +extern "C" { + #[link_ordinal(72436)] + //~^ ERROR ordinal value in `link_ordinal` is too large: `72436` + fn foo(); + #[link_ordinal(72436)] + //~^ ERROR ordinal value in `link_ordinal` is too large: `72436` + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr new file mode 100644 index 000000000..fef6de6ae --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr @@ -0,0 +1,18 @@ +error: ordinal value in `link_ordinal` is too large: `72436` + --> $DIR/link-ordinal-too-large.rs:5:5 + | +LL | #[link_ordinal(72436)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the value may not exceed `u16::MAX` + +error: ordinal value in `link_ordinal` is too large: `72436` + --> $DIR/link-ordinal-too-large.rs:8:5 + | +LL | #[link_ordinal(72436)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the value may not exceed `u16::MAX` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs new file mode 100644 index 000000000..71e0ac9f3 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs @@ -0,0 +1,13 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name = "foo")] +extern "C" { + #[link_ordinal(3, 4)] + //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + fn foo(); + #[link_ordinal(3, 4)] + //~^ ERROR incorrect number of arguments to `#[link_ordinal]` + static mut imported_variable: i32; +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr new file mode 100644 index 000000000..7e0fcd845 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr @@ -0,0 +1,18 @@ +error: incorrect number of arguments to `#[link_ordinal]` + --> $DIR/link-ordinal-too-many-arguments.rs:5:5 + | +LL | #[link_ordinal(3, 4)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the attribute requires exactly one argument + +error: incorrect number of arguments to `#[link_ordinal]` + --> $DIR/link-ordinal-too-many-arguments.rs:8:5 + | +LL | #[link_ordinal(3, 4)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the attribute requires exactly one argument + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs new file mode 100644 index 000000000..329c93fc1 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs @@ -0,0 +1,17 @@ +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] + +#[link(name = "foo")] +extern "C" { + #[link_ordinal(3)] + //~^ ERROR `#[link_ordinal]` is only supported if link kind is `raw-dylib` + fn foo(); +} + +#[link(name = "bar", kind = "static")] +extern "C" { + #[link_ordinal(3)] + //~^ ERROR `#[link_ordinal]` is only supported if link kind is `raw-dylib` + fn bar(); +} + +fn main() {} diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr new file mode 100644 index 000000000..5fbffbda5 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr @@ -0,0 +1,14 @@ +error: `#[link_ordinal]` is only supported if link kind is `raw-dylib` + --> $DIR/link-ordinal-unsupported-link-kind.rs:5:5 + | +LL | #[link_ordinal(3)] + | ^^^^^^^^^^^^^^^^^^ + +error: `#[link_ordinal]` is only supported if link kind is `raw-dylib` + --> $DIR/link-ordinal-unsupported-link-kind.rs:12:5 + | +LL | #[link_ordinal(3)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs new file mode 100644 index 000000000..6542faad2 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs @@ -0,0 +1,19 @@ +// only-x86 +// only-windows +// compile-flags: --crate-type lib --emit link +#![allow(clashing_extern_declarations)] +#![feature(raw_dylib)] +#[link(name = "foo", kind = "raw-dylib")] +extern "C" { + fn f(x: i32); +} + +pub fn lib_main() { + #[link(name = "foo", kind = "raw-dylib")] + extern "stdcall" { + fn f(x: i32); + //~^ ERROR multiple declarations of external function `f` from library `foo.dll` have different calling conventions + } + + unsafe { f(42); } +} diff --git a/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr new file mode 100644 index 000000000..c6808bec7 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr @@ -0,0 +1,8 @@ +error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions + --> $DIR/multiple-declarations.rs:14:9 + | +LL | fn f(x: i32); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs new file mode 100644 index 000000000..4efffbd53 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs @@ -0,0 +1,6 @@ +// ignore-windows +// compile-flags: --crate-type lib +#![cfg_attr(target_arch = "x86", feature(raw_dylib))] +#[link(name = "foo", kind = "raw-dylib")] +//~^ ERROR: link kind `raw-dylib` is only supported on Windows targets +extern "C" {} diff --git a/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr new file mode 100644 index 000000000..14e791f1f --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr @@ -0,0 +1,9 @@ +error[E0455]: link kind `raw-dylib` is only supported on Windows targets + --> $DIR/raw-dylib-windows-only.rs:4:29 + | +LL | #[link(name = "foo", kind = "raw-dylib")] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0455`. diff --git a/tests/ui/rfc-2627-raw-dylib/unsupported-abi.rs b/tests/ui/rfc-2627-raw-dylib/unsupported-abi.rs new file mode 100644 index 000000000..2f5a23e47 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/unsupported-abi.rs @@ -0,0 +1,12 @@ +// only-x86_64 +// only-windows +// compile-flags: --crate-type lib --emit link +#[link(name = "foo", kind = "raw-dylib")] +extern "stdcall" { + fn f(x: i32); + //~^ ERROR ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture +} + +pub fn lib_main() { + unsafe { f(42); } +} diff --git a/tests/ui/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/rfc-2627-raw-dylib/unsupported-abi.stderr new file mode 100644 index 000000000..f8265ae69 --- /dev/null +++ b/tests/ui/rfc-2627-raw-dylib/unsupported-abi.stderr @@ -0,0 +1,8 @@ +error: ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture + --> $DIR/unsupported-abi.rs:6:5 + | +LL | fn f(x: i32); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs new file mode 100644 index 000000000..780a510c5 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs @@ -0,0 +1,14 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + type Assoc: ~const Foo; + fn foo() {} +} + +const fn foo() { + ::Assoc::foo(); +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfc-2632-const-trait-impl/assoc-type.rs new file mode 100644 index 000000000..7d9dae52c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -0,0 +1,32 @@ +#![feature(const_trait_impl)] + +struct NonConstAdd(i32); + +impl std::ops::Add for NonConstAdd { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + NonConstAdd(self.0 + rhs.0) + } +} + +#[const_trait] +trait Foo { + type Bar: ~const std::ops::Add; +} + +impl const Foo for NonConstAdd { + type Bar = NonConstAdd; + //~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts +} + +#[const_trait] +trait Baz { + type Qux: std::ops::Add; +} + +impl const Baz for NonConstAdd { + type Qux = NonConstAdd; // OK +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr new file mode 100644 index 000000000..89177b0f1 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -0,0 +1,21 @@ +error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts + --> $DIR/assoc-type.rs:19:16 + | +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` + | + = help: the trait `~const Add` is not implemented for `NonConstAdd` +note: the trait `Add` is implemented for `NonConstAdd`, but that implementation is not `const` + --> $DIR/assoc-type.rs:19:16 + | +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^ +note: required by a bound in `Foo::Bar` + --> $DIR/assoc-type.rs:15:15 + | +LL | type Bar: ~const std::ops::Add; + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs new file mode 100644 index 000000000..01ac74fef --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.rs @@ -0,0 +1,10 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait A { + #[const_trait] //~ ERROR attribute should be applied + fn foo(self); +} + +#[const_trait] //~ ERROR attribute should be applied +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr new file mode 100644 index 000000000..b18f33218 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/attr-misuse.stderr @@ -0,0 +1,14 @@ +error: attribute should be applied to a trait + --> $DIR/attr-misuse.rs:9:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + +error: attribute should be applied to a trait + --> $DIR/attr-misuse.rs:5:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs b/tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs new file mode 100644 index 000000000..e73082c11 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/auxiliary/cross-crate.rs @@ -0,0 +1,23 @@ +#![feature(const_trait_impl)] + +#[const_trait] +pub trait MyTrait { + fn defaulted_func(&self) {} + fn func(self); +} + +pub struct NonConst; + +impl MyTrait for NonConst { + fn func(self) { + + } +} + +pub struct Const; + +impl const MyTrait for Const { + fn func(self) { + + } +} diff --git a/tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs new file mode 100644 index 000000000..589e3f024 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs @@ -0,0 +1,19 @@ +#![feature(const_trait_impl)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +#[const_trait] +pub trait MyTrait { + #[stable(feature = "rust1", since = "1.0.0")] + fn func(); +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Unstable; + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "unstable", issue = "none")] +impl const MyTrait for Unstable { + fn func() {} +} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs new file mode 100644 index 000000000..dd9933974 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -0,0 +1,29 @@ +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Plus { + fn plus(self, rhs: Self) -> Self; +} + +impl const Plus for i32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Plus for u32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +pub const fn add_i32(a: i32, b: i32) -> i32 { + a.plus(b) // ok +} + +pub const fn add_u32(a: u32, b: u32) -> u32 { + a.plus(b) + //~^ ERROR the trait bound +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr new file mode 100644 index 000000000..7350909ba --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u32: ~const Plus` is not satisfied + --> $DIR/call-const-trait-method-fail.rs:25:7 + | +LL | a.plus(b) + | ^^^^ the trait `~const Plus` is not implemented for `u32` + | +note: the trait `Plus` is implemented for `u32`, but that implementation is not `const` + --> $DIR/call-const-trait-method-fail.rs:25:7 + | +LL | a.plus(b) + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs new file mode 100644 index 000000000..b64161b6a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs @@ -0,0 +1,43 @@ +// run-pass + +#![feature(const_trait_impl)] + +struct Int(i32); + +impl const std::ops::Add for Int { + type Output = Int; + + fn add(self, rhs: Self) -> Self { + Int(self.0.plus(rhs.0)) + } +} + +impl const PartialEq for Int { + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +#[const_trait] +pub trait Plus { + fn plus(self, rhs: Self) -> Self; +} + +impl const Plus for i32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +pub const fn add_i32(a: i32, b: i32) -> i32 { + a.plus(b) +} + +const ADD_INT: Int = Int(1i32) + Int(2i32); + +fn main() { + assert!(ADD_INT == Int(3i32)); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs new file mode 100644 index 000000000..50c465790 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait MyPartialEq { + fn eq(&self, other: &Self) -> bool; +} + +impl const MyPartialEq for T { + fn eq(&self, other: &Self) -> bool { + PartialEq::eq(self, other) + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs new file mode 100644 index 000000000..b00ff1f2f --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-chain.rs @@ -0,0 +1,28 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +// check-pass + +#![feature(const_trait_impl)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } +} + +const fn equals_self(t: &T) -> bool { + *t == *t +} + +const fn equals_self_wrapper(t: &T) -> bool { + equals_self(t) +} + +pub const EQ: bool = equals_self_wrapper(&S); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs new file mode 100644 index 000000000..c8ded0fa7 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(const_trait_impl)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } +} + +// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const +// bound. +const fn equals_self(t: &T) -> bool { + *t == *t +} + +trait A: PartialEq {} +impl A for T {} + +const fn equals_self2(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S) && equals_self2(&S); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs new file mode 100644 index 000000000..2bc5ee512 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -0,0 +1,8 @@ +#![feature(const_trait_impl)] + +pub const fn equals_self(t: &T) -> bool { + *t == *t + //~^ ERROR can't compare +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr new file mode 100644 index 000000000..31e6dbdab --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr @@ -0,0 +1,15 @@ +error[E0277]: can't compare `T` with `_` in const contexts + --> $DIR/call-generic-method-fail.rs:4:8 + | +LL | *t == *t + | ^^ no implementation for `T == _` + | +note: the trait `PartialEq<_>` is implemented for `T`, but that implementation is not `const` + --> $DIR/call-generic-method-fail.rs:4:8 + | +LL | *t == *t + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs new file mode 100644 index 000000000..e197c8b73 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs @@ -0,0 +1,17 @@ +// check-pass + +struct S; + +impl PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self(t: &T) -> bool { + true +} + +pub const EQ: bool = equals_self(&S); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs new file mode 100644 index 000000000..414a8c87d --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs @@ -0,0 +1,26 @@ +#![feature(const_trait_impl)] + +struct S; + +#[const_trait] +trait Foo { + fn eq(&self, _: &Self) -> bool; +} + +impl Foo for S { + fn eq(&self, _: &S) -> bool { + true + } +} + +const fn equals_self(t: &T) -> bool { + true +} + +// Calling `equals_self` with something that has a non-const impl should throw an error, despite +// it not using the impl. + +pub const EQ: bool = equals_self(&S); +//~^ ERROR + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr new file mode 100644 index 000000000..706f52343 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `S: ~const Foo` is not satisfied + --> $DIR/call-generic-method-nonconst.rs:23:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ----------- ^^ the trait `~const Foo` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: the trait `Foo` is implemented for `S`, but that implementation is not `const` + --> $DIR/call-generic-method-nonconst.rs:23:34 + | +LL | pub const EQ: bool = equals_self(&S); + | ^^ +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:16:25 + | +LL | const fn equals_self(t: &T) -> bool { + | ^^^^^^^^^^ required by this bound in `equals_self` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs new file mode 100644 index 000000000..40565d1b7 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call-generic-method-pass.rs @@ -0,0 +1,24 @@ +//! Basic test for calling methods on generic type parameters in `const fn`. + +// check-pass + +#![feature(const_trait_impl)] + +struct S; + +impl const PartialEq for S { + fn eq(&self, _: &S) -> bool { + true + } + fn ne(&self, other: &S) -> bool { + !self.eq(other) + } +} + +const fn equals_self(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/call.rs b/tests/ui/rfc-2632-const-trait-impl/call.rs new file mode 100644 index 000000000..5f48c2353 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/call.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(const_closures, const_trait_impl)] +#![allow(incomplete_features)] + +pub const _: () = { + assert!((const || true)()); +}; + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs new file mode 100644 index 000000000..f66d63da6 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs @@ -0,0 +1,31 @@ +#![feature(const_trait_impl)] + +pub struct Int(i32); + +impl const std::ops::Add for i32 { + //~^ ERROR only traits defined in the current crate can be implemented for primitive types + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl std::ops::Add for Int { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +impl const std::ops::Add for Int { + //~^ ERROR conflicting implementations of trait + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr new file mode 100644 index 000000000..36a09add4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -0,0 +1,25 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/const-and-non-const-impl.rs:5:1 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^-------------^^^^^--- + | | | | + | | | `i32` is not defined in the current crate + | | `i32` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0119]: conflicting implementations of trait `Add` for type `Int` + --> $DIR/const-and-non-const-impl.rs:22:1 + | +LL | impl std::ops::Add for Int { + | -------------------------- first implementation here +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0117, E0119. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs new file mode 100644 index 000000000..52984fb6b --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl)] + +struct S; +#[const_trait] +trait T { + fn foo(); +} + +fn non_const() {} + +impl const T for S { + fn foo() { non_const() } + //~^ ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr new file mode 100644 index 000000000..c8783de4c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `non_const` in constant functions + --> $DIR/const-check-fns-in-const-impl.rs:12:16 + | +LL | fn foo() { non_const() } + | ^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs new file mode 100644 index 000000000..b5f19e40c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs @@ -0,0 +1,19 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); +//~^ ERROR: the trait bound + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr new file mode 100644 index 000000000..4470e287c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied in `fn(()) -> i32 {<() as Tr>::a}` + --> $DIR/const-closure-trait-method-fail.rs:16:42 + | +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ------------------ ^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/const-closure-trait-method-fail.rs:16:42 + | +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ^^^^^ + = note: required because it appears within the type `fn(()) -> i32 {<() as Tr>::a}` +note: required by a bound in `need_const_closure` + --> $DIR/const-closure-trait-method-fail.rs:12:32 + | +LL | const fn need_const_closure i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `need_const_closure` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs new file mode 100644 index 000000000..3e6d19088 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl const Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closures.rs b/tests/ui/rfc-2632-const-trait-impl/const-closures.rs new file mode 100644 index 000000000..755d85398 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-closures.rs @@ -0,0 +1,30 @@ +// run-pass + +#![feature(const_trait_impl)] + +const fn answer_p1(f: &F) -> u8 + where + F: ~const FnOnce() -> u8, + F: ~const FnMut() -> u8, + F: ~const Fn() -> u8, +{ + f() * 7 +} + +const fn three() -> u8 { + 3 +} + +const fn answer_p2() -> u8 { + answer_p1(&three) +} + +const fn answer u8>(f: &F) -> u8 { + f() + f() +} + +const ANSWER: u8 = answer(&answer_p2); + +fn main() { + assert_eq!(ANSWER, 42) +} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs new file mode 100644 index 000000000..140a06a73 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs @@ -0,0 +1,29 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait ConstDefaultFn: Sized { + fn b(self); + + fn a(self) { + self.b(); + } +} + +struct NonConstImpl; +struct ConstImpl; + +impl ConstDefaultFn for NonConstImpl { + fn b(self) {} +} + +impl const ConstDefaultFn for ConstImpl { + fn b(self) {} +} + +const fn test() { + NonConstImpl.a(); + //~^ ERROR the trait bound + ConstImpl.a(); +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr new file mode 100644 index 000000000..f9d0d1f78 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied + --> $DIR/const-default-method-bodies.rs:24:18 + | +LL | NonConstImpl.a(); + | ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl` + | +note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const` + --> $DIR/const-default-method-bodies.rs:24:5 + | +LL | NonConstImpl.a(); + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs new file mode 100644 index 000000000..948f0efbc --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-bound.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(const_precise_live_drops)] + +use std::marker::Destruct; + +const fn foo(res: Result) -> Option where E: ~const Destruct { + match res { + Ok(t) => Some(t), + Err(_e) => None, + } +} + +pub struct Foo(T); + +const fn baz(res: Result, Foo>) -> Option> +where + T: ~const Destruct, + E: ~const Destruct, +{ + foo(res) +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr new file mode 100644 index 000000000..796c0d388 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -0,0 +1,99 @@ +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:44:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop` + | + = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:35:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &NonTrivialDrop, + | + +LL | &mut NonTrivialDrop, + | ++++ + +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:46:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop` + | +note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:46:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `ConstImplWithDropGlue` + --> $DIR/const-drop-fail.rs:16:8 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:35:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied + --> $DIR/const-drop-fail.rs:48:47 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop` + | | + | required by a bound introduced by this call + | +note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:48:47 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^ +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied + --> $DIR/const-drop-fail.rs:48:5 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop` + | +note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:48:5 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not + --> $DIR/const-drop-fail.rs:55:9 + | +LL | impl const Drop for ConstDropImplWithNonConstBounds { + | ^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/const-drop-fail.rs:53:1 + | +LL | struct ConstDropImplWithNonConstBounds(PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0367. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs new file mode 100644 index 000000000..d36c7f81c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.rs @@ -0,0 +1,62 @@ +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::{Destruct, PhantomData}; + +struct NonTrivialDrop; + +impl Drop for NonTrivialDrop { + fn drop(&mut self) { + println!("Non trivial drop"); + } +} + +struct ConstImplWithDropGlue(NonTrivialDrop); + +impl const Drop for ConstImplWithDropGlue { + fn drop(&mut self) {} +} + +#[const_trait] +trait A { fn a() { } } + +impl A for NonTrivialDrop {} + +struct ConstDropImplWithBounds(PhantomData); + +impl const Drop for ConstDropImplWithBounds { + fn drop(&mut self) { + T::a(); + } +} + +const fn check(_: T) {} + +macro_rules! check_all { + ($($exp:expr),*$(,)?) => {$( + const _: () = check($exp); + )*}; +} + +check_all! { + NonTrivialDrop, + //~^ ERROR can't drop + ConstImplWithDropGlue(NonTrivialDrop), + //~^ ERROR can't drop + ConstDropImplWithBounds::(PhantomData), + //~^ ERROR the trait bound + //~| ERROR the trait bound +} + +struct ConstDropImplWithNonConstBounds(PhantomData); + +impl const Drop for ConstDropImplWithNonConstBounds { +//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not + fn drop(&mut self) { + T::a(); + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr new file mode 100644 index 000000000..796c0d388 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -0,0 +1,99 @@ +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:44:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop` + | + = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:35:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &NonTrivialDrop, + | + +LL | &mut NonTrivialDrop, + | ++++ + +error[E0277]: can't drop `NonTrivialDrop` in const contexts + --> $DIR/const-drop-fail.rs:46:5 + | +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call +... +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop` + | +note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:46:5 + | +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `ConstImplWithDropGlue` + --> $DIR/const-drop-fail.rs:16:8 + | +LL | struct ConstImplWithDropGlue(NonTrivialDrop); + | ^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:35:19 + | +LL | const fn check(_: T) {} + | ^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied + --> $DIR/const-drop-fail.rs:48:47 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop` + | | + | required by a bound introduced by this call + | +note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:48:47 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^ +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied + --> $DIR/const-drop-fail.rs:48:5 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop` + | +note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const` + --> $DIR/const-drop-fail.rs:48:5 + | +LL | ConstDropImplWithBounds::(PhantomData), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:27:35 + | +LL | struct ConstDropImplWithBounds(PhantomData); + | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds` + +error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not + --> $DIR/const-drop-fail.rs:55:9 + | +LL | impl const Drop for ConstDropImplWithNonConstBounds { + | ^^^^^^^^ + | +note: the implementor must specify the same requirement + --> $DIR/const-drop-fail.rs:53:1 + | +LL | struct ConstDropImplWithNonConstBounds(PhantomData); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0367. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfc-2632-const-trait-impl/const-drop.rs new file mode 100644 index 000000000..b0fc3adf9 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-drop.rs @@ -0,0 +1,113 @@ +// run-pass +// revisions: stock precise +#![feature(const_trait_impl)] +#![feature(const_mut_refs)] +#![feature(never_type)] +#![cfg_attr(precise, feature(const_precise_live_drops))] + +use std::marker::Destruct; + +struct S<'a>(&'a mut u8); + +impl<'a> const Drop for S<'a> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +const fn a(_: T) {} + +const fn b() -> u8 { + let mut c = 0; + let _ = S(&mut c); + a(S(&mut c)); + c +} + +const C: u8 = b(); + +macro_rules! implements_const_drop { + ($($exp:expr),*$(,)?) => { + $( + const _: () = a($exp); + )* + } +} + +#[allow(dead_code)] +mod t { + pub struct Foo; + pub enum Bar { A } + pub fn foo() {} + pub struct ConstDrop; + + impl const Drop for ConstDrop { + fn drop(&mut self) {} + } + + pub struct HasConstDrop(pub ConstDrop); + pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize); + + #[const_trait] + pub trait SomeTrait { + fn foo(); + } + impl const SomeTrait for () { + fn foo() {} + } + // non-const impl + impl SomeTrait for i32 { + fn foo() {} + } + + pub struct ConstDropWithBound(pub core::marker::PhantomData); + + impl const Drop for ConstDropWithBound { + fn drop(&mut self) { + T::foo(); + } + } + + pub struct ConstDropWithNonconstBound(pub core::marker::PhantomData); + + impl const Drop for ConstDropWithNonconstBound { + fn drop(&mut self) { + // Note: we DON'T use the `T: SomeTrait` bound + } + } +} + +use t::*; + +implements_const_drop! { + 1u8, + 2, + 3.0, + Foo, + Bar::A, + foo, + ConstDrop, + HasConstDrop(ConstDrop), + TrivialFields(1, 2, 3, 4), + &1, + &1 as *const i32, + ConstDropWithBound::<()>, + ConstDropWithNonconstBound::, + Result::::Ok(1), +} + +fn main() { + struct HasDropGlue(#[allow(unused_tuple_struct_fields)] Box); + struct HasDropImpl; + impl Drop for HasDropImpl { + fn drop(&mut self) { + println!("not trivial drop"); + } + } + + // These types should pass because ~const in a non-const context should have no effect. + a(HasDropGlue(Box::new(0))); + a(HasDropImpl); + + assert_eq!(C, 2); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs new file mode 100644 index 000000000..bed4e9fd1 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.rs @@ -0,0 +1,12 @@ +#![feature(const_trait_impl)] + +struct Foo; + +const impl Foo { //~ ERROR: expected identifier, found keyword + fn bar() {} +} + +fn main() { + // shouldn't error here because we shouldn't have been able to recover above + Foo::bar(); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr new file mode 100644 index 000000000..603f6b7d2 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-norecover.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-norecover.rs:5:7 + | +LL | const impl Foo { + | ^^^^ expected identifier, found keyword + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs new file mode 100644 index 000000000..837124db0 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo {} + +const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword + +#[const_trait] +trait Bar {} + +const impl Bar for T {} //~ ERROR: expected identifier, found keyword + +const fn still_implements() {} + +const _: () = still_implements::(); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr new file mode 100644 index 000000000..7217fc855 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-recovery.rs:6:7 + | +LL | const impl Foo for i32 {} + | ^^^^ expected identifier, found keyword + | +help: you might have meant to write a const trait impl + | +LL - const impl Foo for i32 {} +LL + impl const Foo for i32 {} + | + +error: expected identifier, found keyword `impl` + --> $DIR/const-impl-recovery.rs:11:7 + | +LL | const impl Bar for T {} + | ^^^^ expected identifier, found keyword + | +help: you might have meant to write a const trait impl + | +LL - const impl Bar for T {} +LL + impl const Bar for T {} + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs new file mode 100644 index 000000000..2b4963991 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs @@ -0,0 +1,9 @@ +#![feature(const_trait_impl)] + +pub trait A {} +//~^ HELP: mark `A` as const + +impl const A for () {} +//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]` + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr new file mode 100644 index 000000000..478adcf3e --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr @@ -0,0 +1,14 @@ +error: const `impl` for trait `A` which is not marked with `#[const_trait]` + --> $DIR/const-impl-requires-const-trait.rs:6:12 + | +LL | pub trait A {} + | - help: mark `A` as const: `#[const_trait]` +... +LL | impl const A for () {} + | ^ + | + = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: adding a non-const method body in the future would be a breaking change + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs b/tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs new file mode 100644 index 000000000..0622f96e7 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const-impl-trait.rs @@ -0,0 +1,55 @@ +// check-pass +#![allow(incomplete_features)] +#![feature( + associated_type_bounds, + const_trait_impl, + const_cmp, + return_position_impl_trait_in_trait, +)] + +use std::marker::Destruct; + +const fn cmp(a: &impl ~const PartialEq) -> bool { + a == a +} + +const fn wrap(x: impl ~const PartialEq + ~const Destruct) + -> impl ~const PartialEq + ~const Destruct +{ + x +} + +#[const_trait] +trait Foo { + fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; +} + +impl const Foo for () { + fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + 123 + } +} + +const _: () = { + assert!(cmp(&0xDEADBEEFu32)); + assert!(cmp(&())); + assert!(wrap(123) == wrap(123)); + assert!(wrap(123) != wrap(456)); + let x = <() as Foo>::huh(); + assert!(x == x); +}; + +#[const_trait] +trait T {} +struct S; +impl const T for S {} + +const fn rpit() -> impl ~const T { S } + +const fn apit(_: impl ~const T + ~const Destruct) {} + +const fn rpit_assoc_bound() -> impl IntoIterator { Some(S) } + +const fn apit_assoc_bound(_: impl IntoIterator + ~const Destruct) {} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs new file mode 100644 index 000000000..348ca0ab1 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs @@ -0,0 +1,4 @@ +#[derive_const(Default)] //~ ERROR use of unstable library feature +pub struct S; + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr new file mode 100644 index 000000000..cc9bdd271 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'derive_const' + --> $DIR/derive-const-gate.rs:1:3 + | +LL | #[derive_const(Default)] + | ^^^^^^^^^^^^ + | + = help: add `#![feature(derive_const)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs new file mode 100644 index 000000000..92843a8a2 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs @@ -0,0 +1,13 @@ +#![feature(derive_const)] + +pub struct A; + +impl Default for A { + fn default() -> A { A } +} + +#[derive_const(Default)] +pub struct S(A); +//~^ cannot call non-const fn + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr new file mode 100644 index 000000000..96e0c78b9 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const fn `::default` in constant functions + --> $DIR/derive-const-non-const-type.rs:10:14 + | +LL | #[derive_const(Default)] + | ------- in this derive macro expansion +LL | pub struct S(A); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs new file mode 100644 index 000000000..d1fbeac85 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] + +pub struct A; + +impl const Default for A { + fn default() -> A { A } +} + +impl const PartialEq for A { + fn eq(&self, _: &A) -> bool { true } +} + +#[derive_const(Default, PartialEq)] +pub struct S((), A); + +const _: () = assert!(S((), A) == S::default()); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs b/tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs new file mode 100644 index 000000000..bde8bf20f --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate-default-method-body-is-const.rs @@ -0,0 +1,18 @@ +// This tests that `const_trait` default methods can +// be called from a const context when used across crates. +// +// check-pass + +#![feature(const_trait_impl)] + +// aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +const _: () = { + Const.func(); + Const.defaulted_func(); +}; + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr new file mode 100644 index 000000000..633b7cc25 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied + --> $DIR/cross-crate.rs:17:14 + | +LL | NonConst.func(); + | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | +note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` + --> $DIR/cross-crate.rs:17:5 + | +LL | NonConst.func(); + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.rs b/tests/ui/rfc-2632-const-trait-impl/cross-crate.rs new file mode 100644 index 000000000..6df47022c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -0,0 +1,24 @@ +// revisions: stock gated stocknc gatednc +// [gated] check-pass +#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))] + +// aux-build: cross-crate.rs +extern crate cross_crate; + +use cross_crate::*; + +fn non_const_context() { + NonConst.func(); + Const.func(); +} + +const fn const_context() { + #[cfg(any(stocknc, gatednc))] + NonConst.func(); + //[stocknc]~^ ERROR: the trait bound + //[gatednc]~^^ ERROR: the trait bound + Const.func(); + //[stock]~^ ERROR: cannot call +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr new file mode 100644 index 000000000..22f13a741 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn `::func` in constant functions + --> $DIR/cross-crate.rs:20:11 + | +LL | Const.func(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr new file mode 100644 index 000000000..9e97d3f11 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied + --> $DIR/cross-crate.rs:17:14 + | +LL | NonConst.func(); + | ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst` + | +note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const` + --> $DIR/cross-crate.rs:17:5 + | +LL | NonConst.func(); + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs new file mode 100644 index 000000000..96acdc300 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr {} +impl Tr for () {} + +const fn foo() where T: ~const Tr {} + +#[const_trait] +pub trait Foo { + fn foo() { + foo::<()>(); + //~^ ERROR the trait bound `(): ~const Tr` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr new file mode 100644 index 000000000..a244ab10c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied + --> $DIR/default-method-body-is-const-body-checking.rs:12:15 + | +LL | foo::<()>(); + | ^^ the trait `~const Tr` is not implemented for `()` + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/default-method-body-is-const-body-checking.rs:12:15 + | +LL | foo::<()>(); + | ^^ +note: required by a bound in `foo` + --> $DIR/default-method-body-is-const-body-checking.rs:7:28 + | +LL | const fn foo() where T: ~const Tr {} + | ^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs new file mode 100644 index 000000000..f70ecbc37 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs @@ -0,0 +1,15 @@ +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Tr { + fn a(&self) {} + + fn b(&self) { + ().a() + //~^ ERROR the trait bound + } +} + +impl Tr for () {} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr new file mode 100644 index 000000000..21ecddaff --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied + --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 + | +LL | ().a() + | ^ the trait `~const Tr` is not implemented for `()` + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9 + | +LL | ().a() + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs new file mode 100644 index 000000000..1b45cd9aa --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs @@ -0,0 +1,17 @@ +// check-pass + +// This was an ICE, because the compiler ensures the +// function to be const when performing const checking, +// but functions marked with the attribute are not const +// *and* subject to const checking. + +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![stable(since = "1", feature = "foo")] + +#[const_trait] +trait Tr { + fn a() {} +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr new file mode 100644 index 000000000..4c630d33c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate.rs:14:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/feature-gate.rs b/tests/ui/rfc-2632-const-trait-impl/feature-gate.rs new file mode 100644 index 000000000..0b409fbaa --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/feature-gate.rs @@ -0,0 +1,14 @@ +// revisions: stock gated +// gate-test-const_trait_impl + +#![cfg_attr(gated, feature(const_trait_impl))] +#![feature(rustc_attrs)] + +struct S; +#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder +trait T {} +impl const T for S {} +//[stock]~^ ERROR const trait impls are experimental + +#[rustc_error] +fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr new file mode 100644 index 000000000..0e938c1c5 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -0,0 +1,21 @@ +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:10:6 + | +LL | impl const T for S {} + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future. + --> $DIR/feature-gate.rs:8:1 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2632-const-trait-impl/gate.rs b/tests/ui/rfc-2632-const-trait-impl/gate.rs new file mode 100644 index 000000000..f2cd26c91 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/gate.rs @@ -0,0 +1,5 @@ +// gate-test-const_closures +fn main() { + (const || {})(); + //~^ ERROR: const closures are experimental +} diff --git a/tests/ui/rfc-2632-const-trait-impl/gate.stderr b/tests/ui/rfc-2632-const-trait-impl/gate.stderr new file mode 100644 index 000000000..30edc4127 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: const closures are experimental + --> $DIR/gate.rs:3:6 + | +LL | (const || {})(); + | ^^^^^^^^^^^ + | + = note: see issue #106003 for more information + = help: add `#![feature(const_closures)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2632-const-trait-impl/generic-bound.rs b/tests/ui/rfc-2632-const-trait-impl/generic-bound.rs new file mode 100644 index 000000000..5495b531c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/generic-bound.rs @@ -0,0 +1,30 @@ +// run-pass + +#![feature(const_trait_impl)] + +use std::marker::PhantomData; + +struct S(PhantomData); + +impl Copy for S {} +impl Clone for S { + fn clone(&self) -> Self { + S(PhantomData) + } +} + +impl const std::ops::Add for S { + type Output = Self; + + fn add(self, _: Self) -> Self { + S(std::marker::PhantomData) + } +} + +const fn twice(arg: S) -> S { + arg + arg +} + +fn main() { + let _ = twice(S(PhantomData::)); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs new file mode 100644 index 000000000..337c73340 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.rs @@ -0,0 +1,17 @@ +// Regression test for #69615. + +#![feature(const_trait_impl)] + +#[const_trait] +pub trait MyTrait { + fn method(&self) -> Option<()>; +} + +impl const MyTrait for () { + fn method(&self) -> Option<()> { + Some(())?; //~ ERROR `?` is not allowed in a `const fn` + None + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr new file mode 100644 index 000000000..6d2be1daa --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -0,0 +1,12 @@ +error[E0658]: `?` is not allowed in a `const fn` + --> $DIR/hir-const-check.rs:12:9 + | +LL | Some(())?; + | ^^^^^^^^^ + | + = note: see issue #74935 for more information + = help: add `#![feature(const_try)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs new file mode 100644 index 000000000..05b26465c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs @@ -0,0 +1,9 @@ +#![feature(const_trait_impl)] + +struct S; +trait T {} + +impl ~const T for S {} +//~^ ERROR expected a trait, found type + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr new file mode 100644 index 000000000..0a91719e1 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr @@ -0,0 +1,8 @@ +error: expected a trait, found type + --> $DIR/impl-tilde-const-trait.rs:6:6 + | +LL | impl ~const T for S {} + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs new file mode 100644 index 000000000..6df9696f2 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs @@ -0,0 +1,17 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn req(&self); + + fn default() {} +} + +struct S; + +impl const Tr for u16 { + fn default() {} +} //~^^ ERROR not all trait items implemented + + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr new file mode 100644 index 000000000..6c6ca9f5d --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `req` + --> $DIR/impl-with-default-fn-fail.rs:12:1 + | +LL | fn req(&self); + | -------------- `req` from trait +... +LL | impl const Tr for u16 { + | ^^^^^^^^^^^^^^^^^^^^^ missing `req` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs new file mode 100644 index 000000000..ae81421e9 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn req(&self); + + fn default() {} +} + +impl const Tr for u8 { + fn req(&self) {} +} + +macro_rules! impl_tr { + ($ty: ty) => { + impl const Tr for $ty { + fn req(&self) {} + } + } +} + +impl_tr!(u64); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs new file mode 100644 index 000000000..f8ac793e4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs @@ -0,0 +1,22 @@ +// check-pass +#![feature(const_trait_impl)] + +struct S; + +#[const_trait] +trait A {} +#[const_trait] +trait B {} + +impl const A for S {} +impl const B for S {} + +impl S { + const fn a() where T: ~const B { + + } +} + +const _: () = S::a::(); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs new file mode 100644 index 000000000..afd0d137b --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.rs @@ -0,0 +1,13 @@ +#![feature(const_trait_impl)] +#![allow(bare_trait_objects)] + +struct S; +trait T {} + +impl const S {} +//~^ ERROR inherent impls cannot be `const` + +impl const T {} +//~^ ERROR inherent impls cannot be `const` + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr new file mode 100644 index 000000000..8c5562703 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/inherent-impl.stderr @@ -0,0 +1,22 @@ +error: inherent impls cannot be `const` + --> $DIR/inherent-impl.rs:7:12 + | +LL | impl const S {} + | ----- ^ inherent impl for this type + | | + | `const` because of this + | + = note: only trait implementations may be annotated with `const` + +error: inherent impls cannot be `const` + --> $DIR/inherent-impl.rs:10:12 + | +LL | impl const T {} + | ----- ^ inherent impl for this type + | | + | `const` because of this + | + = note: only trait implementations may be annotated with `const` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-100222.rs b/tests/ui/rfc-2632-const-trait-impl/issue-100222.rs new file mode 100644 index 000000000..9f3f38ad4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-100222.rs @@ -0,0 +1,39 @@ +// revisions: nn ny yn yy +// check-pass +#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)] + +#[cfg_attr(any(yn, yy), const_trait)] +pub trait Index { + type Output; +} + +#[cfg_attr(any(ny, yy), const_trait)] +pub trait IndexMut where Self: Index { + const C: ::Output; + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output; +} + +impl Index for () { type Output = (); } + +#[cfg(not(any(nn, yn)))] +impl const IndexMut for <() as Index>::Output { + const C: ::Output = (); + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output + where ::Output:, + {} +} + +#[cfg(any(nn, yn))] +impl IndexMut for <() as Index>::Output { + const C: ::Output = (); + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output + where ::Output:, + {} +} + +const C: <() as Index>::Output = (); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102156.rs b/tests/ui/rfc-2632-const-trait-impl/issue-102156.rs new file mode 100644 index 000000000..fe4e91081 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-102156.rs @@ -0,0 +1,15 @@ +#![feature(allocator_api)] +#![feature(const_trait_impl)] + +use core::convert::{From, TryFrom}; +//~^ ERROR +//~| ERROR + +use std::pin::Pin; +use std::alloc::Allocator; +impl const From> for Pin> +where + A: 'static, +{} + +pub fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr new file mode 100644 index 000000000..8bf00eaff --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-102156.stderr @@ -0,0 +1,19 @@ +error[E0433]: failed to resolve: maybe a missing crate `core`? + --> $DIR/issue-102156.rs:4:5 + | +LL | use core::convert::{From, TryFrom}; + | ^^^^ maybe a missing crate `core`? + | + = help: consider adding `extern crate core` to use the `core` crate + +error[E0433]: failed to resolve: maybe a missing crate `core`? + --> $DIR/issue-102156.rs:4:5 + | +LL | use core::convert::{From, TryFrom}; + | ^^^^ maybe a missing crate `core`? + | + = help: consider adding `extern crate core` to use the `core` crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102985.rs b/tests/ui/rfc-2632-const-trait-impl/issue-102985.rs new file mode 100644 index 000000000..07d3f51ed --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-102985.rs @@ -0,0 +1,12 @@ +#![feature(const_trait_impl)] + +struct Bug { + inner: [(); match || 1 { + n => n(), + //~^ ERROR the trait bound + //~| ERROR the trait bound + //~| ERROR cannot call non-const closure in constants + }], +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr new file mode 100644 index 000000000..b98ccbe5d --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-102985.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const` + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ + = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }` + +error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]` + | + = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]` +note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const` + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ + = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }` + +error[E0015]: cannot call non-const closure in constants + --> $DIR/issue-102985.rs:5:14 + | +LL | n => n(), + | ^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-103677.rs b/tests/ui/rfc-2632-const-trait-impl/issue-103677.rs new file mode 100644 index 000000000..d81724a36 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-103677.rs @@ -0,0 +1,5 @@ +// check-pass + +const _: fn(&String) = |s| { &*s as &str; }; + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-79450.rs b/tests/ui/rfc-2632-const-trait-impl/issue-79450.rs new file mode 100644 index 000000000..b604c65d7 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-79450.rs @@ -0,0 +1,20 @@ +#![feature(const_fmt_arguments_new)] +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn req(&self); + + fn prov(&self) { + println!("lul"); //~ ERROR: cannot call non-const fn `_print` in constant functions + self.req(); + } +} + +struct S; + +impl const Tr for S { + fn req(&self) {} +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr new file mode 100644 index 000000000..082c0333f --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-79450.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn `_print` in constant functions + --> $DIR/issue-79450.rs:9:9 + | +LL | println!("lul"); + | ^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-88155.rs b/tests/ui/rfc-2632-const-trait-impl/issue-88155.rs new file mode 100644 index 000000000..b132c395a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-88155.rs @@ -0,0 +1,13 @@ +#![feature(const_trait_impl)] + +pub trait A { + fn assoc() -> bool; +} + +pub const fn foo() -> bool { + T::assoc() + //~^ ERROR the trait bound + //~| ERROR cannot call non-const fn +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr new file mode 100644 index 000000000..955923505 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-88155.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: ~const A` is not satisfied + --> $DIR/issue-88155.rs:8:5 + | +LL | T::assoc() + | ^^^^^^^^^^ the trait `~const A` is not implemented for `T` + | +note: the trait `A` is implemented for `T`, but that implementation is not `const` + --> $DIR/issue-88155.rs:8:5 + | +LL | T::assoc() + | ^^^^^^^^^^ + +error[E0015]: cannot call non-const fn `::assoc` in constant functions + --> $DIR/issue-88155.rs:8:5 + | +LL | T::assoc() + | ^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-90052.rs b/tests/ui/rfc-2632-const-trait-impl/issue-90052.rs new file mode 100644 index 000000000..21ddf4ab4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-90052.rs @@ -0,0 +1,9 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Bar {} + +fn foo() where T: ~const Bar {} +//~^ ERROR `~const` is not allowed + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr b/tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr new file mode 100644 index 000000000..b2a936537 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-90052.stderr @@ -0,0 +1,14 @@ +error: `~const` is not allowed here + --> $DIR/issue-90052.rs:6:22 + | +LL | fn foo() where T: ~const Bar {} + | ^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/issue-90052.rs:6:4 + | +LL | fn foo() where T: ~const Bar {} + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-92111.rs b/tests/ui/rfc-2632-const-trait-impl/issue-92111.rs new file mode 100644 index 000000000..96a3e386e --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-92111.rs @@ -0,0 +1,23 @@ +// Regression test for #92111. +// +// check-pass + +#![feature(const_trait_impl)] + +use std::marker::Destruct; + +pub trait Tr {} + +#[allow(drop_bounds)] +impl Tr for T {} + +#[derive(Debug)] +pub struct S(i32); + +impl Tr for S {} + +const fn a(t: T) {} + +fn main() { + a(S(0)); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs new file mode 100644 index 000000000..4d3469653 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs @@ -0,0 +1,15 @@ +// Regression test for #92230. +// +// check-pass + +#![feature(const_trait_impl)] + +#[const_trait] +pub trait Super {} +#[const_trait] +pub trait Sub: Super {} + +impl const Super for &A where A: ~const Super {} +impl const Sub for &A where A: ~const Sub {} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs new file mode 100644 index 000000000..a85113600 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(const_trait_impl, once_cell)] + +use std::sync::LazyLock; + +static EXTERN_FLAGS: LazyLock = LazyLock::new(|| { + let x = || String::new(); + x() +}); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs b/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs new file mode 100644 index 000000000..cd8bb5963 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.rs @@ -0,0 +1,15 @@ +#![feature(const_closures, const_trait_impl)] +#![allow(incomplete_features)] + +trait Foo { + fn foo(&self); +} + +impl Foo for () { + fn foo(&self) {} +} + +fn main() { + (const || { (()).foo() })(); + //~^ ERROR: cannot call non-const fn +} diff --git a/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr new file mode 100644 index 000000000..979d7febb --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/non-const-op-const-closure-non-const-outer.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions + --> $DIR/non-const-op-const-closure-non-const-outer.rs:13:22 + | +LL | (const || { (()).foo() })(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs new file mode 100644 index 000000000..1a4509b18 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Convert { + fn to(self) -> T; +} + +impl const Convert for A where B: ~const From { + fn to(self) -> B { + B::from(self) + } +} + +const FOO: fn() -> String = || "foo".to(); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs new file mode 100644 index 000000000..3ac909924 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -0,0 +1,46 @@ +// Tests that trait bounds on specializing trait impls must be `~const` if the +// same bound is present on the default impl and is `~const` there. + +#![feature(const_trait_impl)] +#![feature(rustc_attrs)] +#![feature(min_specialization)] + +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +#[const_trait] +trait Bar {} + +// bgr360: I was only able to exercise the code path that raises the +// "missing ~const qualifier" error by making this base impl non-const, even +// though that doesn't really make sense to do. As seen below, if the base impl +// is made const, rustc fails earlier with an overlapping impl failure. +impl Bar for T +where + T: ~const Foo, +{} + +impl Bar for T +where + T: Foo, //~ ERROR missing `~const` qualifier + T: Specialize, +{} + +#[const_trait] +trait Baz {} + +impl const Baz for T +where + T: ~const Foo, +{} + +impl const Baz for T //~ ERROR conflicting implementations of trait `Baz` +where + T: Foo, + T: Specialize, +{} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr new file mode 100644 index 000000000..4aea19794 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -0,0 +1,18 @@ +error: missing `~const` qualifier for specialization + --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:8 + | +LL | T: Foo, + | ^^^ + +error[E0119]: conflicting implementations of trait `Baz` + --> $DIR/const-default-bound-non-const-specialized-bound.rs:40:1 + | +LL | impl const Baz for T + | ----------------------- first implementation here +... +LL | impl const Baz for T + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs new file mode 100644 index 000000000..9ddea427c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs @@ -0,0 +1,39 @@ +// Tests that a const default trait impl can be specialized by another const +// trait impl and that the specializing impl will be used during const-eval. + +// run-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +const fn get_value() -> u32 { + T::value() +} + +impl const Value for T { + default fn value() -> u32 { + 0 + } +} + +struct FortyTwo; + +impl const Value for FortyTwo { + fn value() -> u32 { + 42 + } +} + +const ZERO: u32 = get_value::<()>(); + +const FORTY_TWO: u32 = get_value::(); + +fn main() { + assert_eq!(ZERO, 0); + assert_eq!(FORTY_TWO, 42); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs new file mode 100644 index 000000000..a3bb9b3f9 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.rs @@ -0,0 +1,26 @@ +// Tests that specializing trait impls must be at least as const as the default impl. + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +impl const Value for T { + default fn value() -> u32 { + 0 + } +} + +struct FortyTwo; + +impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl + fn value() -> u32 { + println!("You can't do that (constly)"); + 42 + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr new file mode 100644 index 000000000..247668047 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/const-default-impl-non-const-specialized-impl.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on const impl with non-const impl + --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 + | +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs new file mode 100644 index 000000000..2aac0a2b4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/default-keyword.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Foo { + fn foo(); +} + +impl const Foo for u32 { + default fn foo() {} +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs new file mode 100644 index 000000000..9c2c2cf16 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs @@ -0,0 +1,37 @@ +// Tests that `~const` trait bounds can be used to specialize const trait impls. + +// check-pass + +#![feature(const_trait_impl)] +#![feature(rustc_attrs)] +#![feature(min_specialization)] + +#[const_trait] +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +impl const Foo for T {} + +impl const Foo for T +where + T: ~const Specialize, +{} + +#[const_trait] +trait Bar {} + +impl const Bar for T +where + T: ~const Foo, +{} + +impl const Bar for T +where + T: ~const Foo, + T: ~const Specialize, +{} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs new file mode 100644 index 000000000..1e6b1c651 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs @@ -0,0 +1,45 @@ +// Tests that `T: ~const Foo` in a specializing impl is treated as equivalent to +// `T: Foo` in the default impl for the purposes of specialization (i.e., it +// does not think that the user is attempting to specialize on trait `Foo`). + +// check-pass + +#![feature(rustc_attrs)] +#![feature(min_specialization)] +#![feature(const_trait_impl)] + +#[rustc_specialization_trait] +trait Specialize {} + +#[const_trait] +trait Foo {} + +#[const_trait] +trait Bar {} + +impl Bar for T +where + T: Foo, +{} + +impl const Bar for T +where + T: ~const Foo, + T: Specialize, +{} + +#[const_trait] +trait Baz {} + +impl const Baz for T +where + T: Foo, +{} + +impl const Baz for T +where + T: ~const Foo, + T: Specialize, +{} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs new file mode 100644 index 000000000..35aa52fbd --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs @@ -0,0 +1,39 @@ +// Tests that a non-const default impl can be specialized by a const trait impl, +// but that the default impl cannot be used in a const context. + +// run-pass + +#![feature(const_trait_impl)] +#![feature(min_specialization)] + +#[const_trait] +trait Value { + fn value() -> u32; +} + +const fn get_value() -> u32 { + T::value() +} + +impl Value for T { + default fn value() -> u32 { + println!("You can't do that (constly)"); + 0 + } +} + +struct FortyTwo; + +impl const Value for FortyTwo { + fn value() -> u32 { + 42 + } +} + +fn main() { + let zero = get_value::<()>(); + assert_eq!(zero, 0); + + const FORTY_TWO: u32 = get_value::(); + assert_eq!(FORTY_TWO, 42); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs new file mode 100644 index 000000000..633543700 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs @@ -0,0 +1,31 @@ +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub trait Sup {} + +impl const Sup for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl A for T { + default fn a() -> u32 { + 2 + } +} + +impl const A for T { + fn a() -> u32 { + 3 + } +} + +const fn generic() { + ::a(); + //~^ ERROR: the trait bound `T: ~const Sup` is not satisfied +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr new file mode 100644 index 000000000..8923416f4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: ~const Sup` is not satisfied + --> $DIR/specializing-constness-2.rs:27:5 + | +LL | ::a(); + | ^^^^^^^^^^^^^ the trait `~const Sup` is not implemented for `T` + | +note: required for `T` to implement `~const A` + --> $DIR/specializing-constness-2.rs:20:37 + | +LL | impl const A for T { + | ---------- ^ ^ + | | + | unsatisfied trait bound introduced here +help: consider further restricting this bound + | +LL | const fn generic() { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs new file mode 100644 index 000000000..9ab170f09 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.rs @@ -0,0 +1,28 @@ +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub trait Sup {} + +impl const Sup for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl const A for T { + default fn a() -> u32 { + 2 + } +} + +impl A for T { +//~^ ERROR: cannot specialize +//~| ERROR: missing `~const` qualifier + fn a() -> u32 { + 3 + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr new file mode 100644 index 000000000..843fc6ce8 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/specializing-constness.stderr @@ -0,0 +1,14 @@ +error: cannot specialize on const impl with non-const impl + --> $DIR/specializing-constness.rs:20:1 + | +LL | impl A for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing `~const` qualifier for specialization + --> $DIR/specializing-constness.rs:20:9 + | +LL | impl A for T { + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs new file mode 100644 index 000000000..fc0d82727 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.rs @@ -0,0 +1,16 @@ +// aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +// Const stability has no impact on usage in non-const contexts. +fn non_const_context() { + Unstable::func(); +} + +const fn stable_const_context() { + Unstable::func(); + //~^ ERROR cannot call non-const fn `::func` in constant functions +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr new file mode 100644 index 000000000..d7aa0d95c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/staged-api-user-crate.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn `::func` in constant functions + --> $DIR/staged-api-user-crate.rs:12:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfc-2632-const-trait-impl/staged-api.rs new file mode 100644 index 000000000..1d79f5adf --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/staged-api.rs @@ -0,0 +1,63 @@ +// revisions: stable unstable + +#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. +#![feature(const_trait_impl)] +#![feature(staged_api)] +#![stable(feature = "rust1", since = "1.0.0")] + +// aux-build: staged-api.rs +extern crate staged_api; + +use staged_api::*; + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Foo; + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))] +impl const MyTrait for Foo { + //[stable]~^ ERROR trait implementations cannot be const stable yet + fn func() {} +} + +// Const stability has no impact on usage in non-const contexts. +fn non_const_context() { + Unstable::func(); + Foo::func(); +} + +#[unstable(feature = "none", issue = "none")] +const fn const_context() { + Unstable::func(); + // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is + // not const-stable. + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + // ^ fails, because the `foo` feature is not active +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))] +pub const fn const_context_not_const_stable() { + //[stable]~^ ERROR function has missing const stability attribute + Unstable::func(); + // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is + // not const-stable. + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + // ^ fails, because the `foo` feature is not active +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "cheese", since = "1.0.0")] +const fn stable_const_context() { + Unstable::func(); + //[unstable]~^ ERROR not yet stable as a const fn + Foo::func(); + //[unstable]~^ ERROR not yet stable as a const fn + const_context_not_const_stable() + //[unstable]~^ ERROR not yet stable as a const fn +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr new file mode 100644 index 000000000..a1aca762e --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -0,0 +1,25 @@ +error: trait implementations cannot be const stable yet + --> $DIR/staged-api.rs:19:1 + | +LL | / impl const MyTrait for Foo { +LL | | +LL | | fn func() {} +LL | | } + | |_^ + | + = note: see issue #67792 for more information + +error: function has missing const stability attribute + --> $DIR/staged-api.rs:42:1 + | +LL | / pub const fn const_context_not_const_stable() { +LL | | +LL | | Unstable::func(); +LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is +... | +LL | | // ^ fails, because the `foo` feature is not active +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr new file mode 100644 index 000000000..c38d1a81a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -0,0 +1,42 @@ +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:35:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:47:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: add `#![feature(foo)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:55:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:57:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: `const_context_not_const_stable` is not yet stable as a const fn + --> $DIR/staged-api.rs:59:5 + | +LL | const_context_not_const_stable() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs b/tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs new file mode 100644 index 000000000..4520a3696 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs @@ -0,0 +1,18 @@ +// check-pass +pub struct S T = fn() -> T> { + f: F, + x: Option, +} + +impl T> S { + pub const fn new(f: F) -> Self { + Self { f, x: None } + } +} + +#[derive(Default)] +pub struct Foo; + +static LOCKED_CALLSITES: S = S::new(Default::default); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs new file mode 100644 index 000000000..2f54c09e3 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.rs @@ -0,0 +1,21 @@ +// This tests feature gates for const impls in the standard library. + +// revisions: stock gated +//[gated] run-pass + +#![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] + +fn non_const_context() -> Vec { + Default::default() +} + +const fn const_context() -> Vec { + Default::default() + //[stock]~^ ERROR cannot call non-const fn +} + +fn main() { + const VAL: Vec = const_context(); + + assert_eq!(VAL, non_const_context()); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr new file mode 100644 index 000000000..6a3396401 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn ` as Default>::default` in constant functions + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr new file mode 100644 index 000000000..d4f42b787 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -0,0 +1,8 @@ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:11:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr new file mode 100644 index 000000000..d4f42b787 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -0,0 +1,8 @@ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:11:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs new file mode 100644 index 000000000..d183efde2 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -0,0 +1,19 @@ +#![feature(const_trait_impl)] + +// revisions: yy yn ny nn + +#[cfg_attr(any(yy, yn), const_trait)] +trait Foo { + fn a(&self); +} + +#[cfg_attr(any(yy, ny), const_trait)] +trait Bar: ~const Foo {} +//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` + +const fn foo(x: &T) { + x.a(); + //[yn,yy]~^ ERROR the trait bound +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr new file mode 100644 index 000000000..13fc719f2 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: ~const Foo` is not satisfied + --> $DIR/super-traits-fail-2.rs:15:7 + | +LL | x.a(); + | ^ the trait `~const Foo` is not implemented for `T` + | +note: the trait `Foo` is implemented for `T`, but that implementation is not `const` + --> $DIR/super-traits-fail-2.rs:15:5 + | +LL | x.a(); + | ^ +help: consider further restricting this bound + | +LL | const fn foo(x: &T) { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr new file mode 100644 index 000000000..13fc719f2 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: ~const Foo` is not satisfied + --> $DIR/super-traits-fail-2.rs:15:7 + | +LL | x.a(); + | ^ the trait `~const Foo` is not implemented for `T` + | +note: the trait `Foo` is implemented for `T`, but that implementation is not `const` + --> $DIR/super-traits-fail-2.rs:15:5 + | +LL | x.a(); + | ^ +help: consider further restricting this bound + | +LL | const fn foo(x: &T) { + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr new file mode 100644 index 000000000..d433e1cfa --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -0,0 +1,14 @@ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:15:24 + | +LL | const fn foo(x: &T) { + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr new file mode 100644 index 000000000..2a7e8e00b --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -0,0 +1,8 @@ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs new file mode 100644 index 000000000..70d2936d3 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -0,0 +1,20 @@ +#![feature(const_trait_impl)] + +// revisions: yy yn ny nn +//[yy] check-pass + +#[cfg_attr(any(yy, yn), const_trait)] +trait Foo { + fn a(&self); +} + +#[cfg_attr(any(yy, ny), const_trait)] +trait Bar: ~const Foo {} +//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` + +const fn foo(x: &T) { + //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` + x.a(); +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr new file mode 100644 index 000000000..e5978c12a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -0,0 +1,8 @@ +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:15:24 + | +LL | const fn foo(x: &T) { + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs new file mode 100644 index 000000000..3e2b81368 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.rs @@ -0,0 +1,18 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn a(&self); +} +#[const_trait] +trait Bar: ~const Foo {} + +struct S; +impl Foo for S { + fn a(&self) {} +} + +impl const Bar for S {} +//~^ ERROR the trait bound + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr new file mode 100644 index 000000000..bf12ef1ca --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `S: ~const Foo` is not satisfied + --> $DIR/super-traits-fail.rs:15:20 + | +LL | impl const Bar for S {} + | ^ the trait `~const Foo` is not implemented for `S` + | +note: the trait `Foo` is implemented for `S`, but that implementation is not `const` + --> $DIR/super-traits-fail.rs:15:20 + | +LL | impl const Bar for S {} + | ^ +note: required by a bound in `Bar` + --> $DIR/super-traits-fail.rs:8:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ required by this bound in `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits.rs new file mode 100644 index 000000000..df96f6fb4 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn a(&self); +} + +#[const_trait] +trait Bar: ~const Foo {} + +struct S; +impl const Foo for S { + fn a(&self) {} +} + +impl const Bar for S {} + +const fn foo(t: &T) { + t.a(); +} + +const _: () = foo(&S); + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/syntax.rs b/tests/ui/rfc-2632-const-trait-impl/syntax.rs new file mode 100644 index 000000000..7ac2458e3 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/syntax.rs @@ -0,0 +1,8 @@ +// compile-flags: -Z parse-only +// check-pass + +#![feature(const_trait_bound_opt_out)] +#![feature(const_trait_impl)] + +// For now, this parses since an error does not occur until AST lowering. +impl ~const T {} diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs new file mode 100644 index 000000000..78a64b901 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs @@ -0,0 +1,34 @@ +#![feature(const_trait_impl)] +#![feature(generic_arg_infer)] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + fn add(self) -> Foo<{ A::add(N) }> { + Foo + } +} + +#[const_trait] +trait Add42 { + fn add(a: usize) -> usize; +} + +impl const Add42 for () { + fn add(a: usize) -> usize { + a + 42 + } +} + +fn bar(_: Foo) -> Foo<{ A::add(N) }> { + //~^ ERROR `~const` is not allowed here + Foo +} + +fn main() { + let foo = Foo::<0>; + let foo = bar::<(), _>(foo); + let _foo = bar::<(), _>(foo); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr new file mode 100644 index 000000000..aae72f36e --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr @@ -0,0 +1,14 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-and-const-params.rs:25:11 + | +LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-and-const-params.rs:25:4 + | +LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs new file mode 100644 index 000000000..95f7aaba0 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -0,0 +1,7 @@ +#![feature(const_trait_impl)] +#![feature(associated_type_bounds)] + +struct TildeQuestion(std::marker::PhantomData); +//~^ ERROR `~const` and `?` are mutually exclusive + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr new file mode 100644 index 000000000..d20f146df --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -0,0 +1,8 @@ +error: `~const` and `?` are mutually exclusive + --> $DIR/tilde-const-invalid-places.rs:4:25 + | +LL | struct TildeQuestion(std::marker::PhantomData); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs new file mode 100644 index 000000000..9b3c2cf2a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs @@ -0,0 +1,9 @@ +// compile-flags: -Z parse-only +// check-pass + +#![feature(const_trait_impl)] + +struct S< + T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add, + T: ~const ?for<'a: 'b> m::Trait<'a>, +>; diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs new file mode 100644 index 000000000..06e4ede8b --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z parse-only + +#![feature(const_trait_impl)] + +struct S; +//~^ ERROR expected identifier, found `~` diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr new file mode 100644 index 000000000..928d23e8a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde-twice.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `~` + --> $DIR/tilde-twice.rs:5:20 + | +LL | struct S; + | ^ expected identifier + +error: aborting due to previous error + diff --git a/tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs new file mode 100644 index 000000000..285cef571 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs @@ -0,0 +1,17 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn foo(&self) {} +} + +struct Bar(T); + +impl Bar { + const fn foo(&self) { + self.0.foo() + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs b/tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs new file mode 100644 index 000000000..334fc4cb8 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-default-body-stability.rs @@ -0,0 +1,50 @@ +// check-pass + +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![feature(const_t_try)] +#![feature(const_try)] +#![feature(try_trait_v2)] + +#![stable(feature = "foo", since = "1.0")] + +use std::ops::{ControlFlow, FromResidual, Try}; + +#[stable(feature = "foo", since = "1.0")] +pub struct T; + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const Try for T { + type Output = T; + type Residual = T; + + fn from_output(t: T) -> T { + t + } + + fn branch(self) -> ControlFlow { + ControlFlow::Continue(self) + } +} + +#[stable(feature = "foo", since = "1.0")] +#[rustc_const_unstable(feature = "const_t_try", issue = "none")] +impl const FromResidual for T { + fn from_residual(t: T) -> T { + t + } +} + +#[stable(feature = "foo", since = "1.0")] +#[const_trait] +pub trait Tr { + #[stable(feature = "foo", since = "1.0")] + fn bar() -> T { + T? + // Should be allowed. + // Must enable unstable features to call this trait fn in const contexts. + } +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs new file mode 100644 index 000000000..bfe98b98c --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs @@ -0,0 +1,31 @@ +// Like trait-where-clause.rs, but we are calling from a const context. +// Checking the validity of traits' where clauses happen at a later stage. +// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a +// test is not enough. +#![feature(const_trait_impl)] + +#[const_trait] +trait Bar {} + +#[const_trait] +trait Foo { + fn a(); + fn b() where Self: ~const Bar; + fn c(); +} + +const fn test1() { + T::a(); + T::b(); + //~^ ERROR the trait bound + T::c::(); + //~^ ERROR the trait bound +} + +const fn test2() { + T::a(); + T::b(); + T::c::(); +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr new file mode 100644 index 000000000..f2846b6a6 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause-const.rs:19:5 + | +LL | T::b(); + | ^^^^^^ the trait `~const Bar` is not implemented for `T` + | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause-const.rs:19:5 + | +LL | T::b(); + | ^^^^^^ +help: consider further restricting this bound + | +LL | const fn test1() { + | ++++++++++++ + +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause-const.rs:21:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T` + | +note: the trait `Bar` is implemented for `T`, but that implementation is not `const` + --> $DIR/trait-where-clause-const.rs:21:5 + | +LL | T::c::(); + | ^^^^^^^^^^^ +help: consider further restricting this bound + | +LL | const fn test1() { + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs new file mode 100644 index 000000000..4b8b00406 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -0,0 +1,41 @@ +// run-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Bar { + fn bar() -> u8; +} + +#[const_trait] +trait Foo { + fn foo() -> u8 where Self: ~const Bar { + ::bar() * 6 + } +} + +struct NonConst; +struct Const; + +impl Bar for NonConst { + fn bar() -> u8 { + 3 + } +} + +impl Foo for NonConst {} + +impl const Bar for Const { + fn bar() -> u8 { + 4 + } +} + +impl const Foo for Const {} + +fn main() { + const ANS1: u8 = Const::foo(); + let ans2 = NonConst::foo(); + + assert_eq!(ANS1 + ans2, 42); +} diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs new file mode 100644 index 000000000..3b028ac48 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Foo { + fn bar() where Self: ~const Foo; +} + +struct S; + +impl Foo for S { + fn bar() {} +} + +fn baz() { + T::bar(); +} + +const fn qux() { + T::bar(); +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs new file mode 100644 index 000000000..85ca5fc90 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.rs @@ -0,0 +1,26 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Bar {} + +trait Foo { + fn a(); + fn b() where Self: ~const Bar; + fn c(); +} + +fn test1() { + T::a(); + T::b(); + //~^ ERROR the trait bound + T::c::(); + //~^ ERROR the trait bound +} + +fn test2() { + T::a(); + T::b(); + T::c::(); +} + +fn main() {} diff --git a/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr new file mode 100644 index 000000000..11f0c4016 --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:14:5 + | +LL | T::b(); + | ^^^^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause.rs:8:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ required by this bound in `Foo::b` +help: consider further restricting this bound + | +LL | fn test1() { + | +++++ + +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/trait-where-clause.rs:16:12 + | +LL | T::c::(); + | ^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause.rs:9:13 + | +LL | fn c(); + | ^^^^^^^^^^ required by this bound in `Foo::c` +help: consider further restricting this bound + | +LL | fn test1() { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfc-2632-const-trait-impl/without-tilde.rs b/tests/ui/rfc-2632-const-trait-impl/without-tilde.rs new file mode 100644 index 000000000..d63381b5f --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/without-tilde.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z parse-only + +#![feature(const_trait_impl)] + +struct S; +//~^ ERROR const bounds must start with `~` diff --git a/tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr new file mode 100644 index 000000000..31300354a --- /dev/null +++ b/tests/ui/rfc-2632-const-trait-impl/without-tilde.stderr @@ -0,0 +1,10 @@ +error: const bounds must start with `~` + --> $DIR/without-tilde.rs:5:13 + | +LL | struct S; + | -^^^^ + | | + | help: add `~`: `~` + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-1014-2.rs b/tests/ui/rfcs/rfc-1014-2.rs new file mode 100644 index 000000000..7dd65701f --- /dev/null +++ b/tests/ui/rfcs/rfc-1014-2.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] + +#![feature(rustc_private)] + +extern crate libc; + +type DWORD = u32; +type HANDLE = *mut u8; +type BOOL = i32; + +#[cfg(windows)] +extern "system" { + fn SetStdHandle(nStdHandle: DWORD, nHandle: HANDLE) -> BOOL; +} + +#[cfg(windows)] +fn close_stdout() { + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + unsafe { SetStdHandle(STD_OUTPUT_HANDLE, 0 as HANDLE); } +} + +#[cfg(windows)] +fn main() { + close_stdout(); + println!("hello"); + println!("world"); +} + +#[cfg(not(windows))] +fn main() {} diff --git a/tests/ui/rfcs/rfc-1014.rs b/tests/ui/rfcs/rfc-1014.rs new file mode 100644 index 000000000..c454dfa4e --- /dev/null +++ b/tests/ui/rfcs/rfc-1014.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +// ignore-wasm32-bare no libc +// ignore-sgx no libc + +#![feature(rustc_private)] + +extern crate libc; + +type DWORD = u32; +type HANDLE = *mut u8; + +#[cfg(windows)] +extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn CloseHandle(handle: HANDLE) -> i32; +} + +#[cfg(windows)] +fn close_stdout() { + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + unsafe { CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE)); } +} + +#[cfg(not(windows))] +fn close_stdout() { + unsafe { libc::close(1); } +} + +fn main() { + close_stdout(); + println!("hello"); + println!("world"); +} diff --git a/tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs b/tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs new file mode 100644 index 000000000..329fadb15 --- /dev/null +++ b/tests/ui/rfcs/rfc-1789-as-cell/from-mut.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(as_array_of_cells)] + +use std::cell::Cell; + +fn main() { + let slice: &mut [i32] = &mut [1, 2, 3]; + let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); + let slice_cell: &[Cell] = cell_slice.as_slice_of_cells(); + + assert_eq!(slice_cell.len(), 3); + + let mut array: [i32; 3] = [1, 2, 3]; + let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array); + let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); + + array_cell[0].set(99); + assert_eq!(array, [99, 2, 3]); +} diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs new file mode 100644 index 000000000..e98582cbc --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs @@ -0,0 +1,6 @@ +// run-pass +use std::error::Error; + +fn main() -> Result<(), Box> { + Ok(()) +} diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs new file mode 100644 index 000000000..bac695d4e --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-empty.rs @@ -0,0 +1,2 @@ +// run-pass +fn main() {} diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs new file mode 100644 index 000000000..6d4c15620 --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-exitcode.rs @@ -0,0 +1,7 @@ +// run-pass + +use std::process::ExitCode; + +fn main() -> ExitCode { + ExitCode::SUCCESS +} diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs new file mode 100644 index 000000000..c06a135dc --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs @@ -0,0 +1,3 @@ +// run-pass + +fn main() -> impl std::process::Termination { } diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs new file mode 100644 index 000000000..b0e932e1f --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs @@ -0,0 +1,6 @@ +// run-pass +use std::io::Error; + +fn main() -> Result<(), Box> { + Ok(()) +} diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs new file mode 100644 index 000000000..30f36c244 --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result.rs @@ -0,0 +1,6 @@ +// run-pass +use std::io::Error; + +fn main() -> Result<(), Error> { + Ok(()) +} diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs new file mode 100644 index 000000000..f0591c38c --- /dev/null +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str.rs @@ -0,0 +1,4 @@ +// run-pass +fn main() -> Result<(), &'static str> { + Ok(()) +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs new file mode 100644 index 000000000..0d1cded36 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unreachable_patterns)] +#![feature(box_patterns)] + +struct Foo{} + +pub fn main() { + let b = Box::new(Foo{}); + let box f = &b; + let _: &Foo = f; + + match &&&b { + box f => { + let _: &Foo = f; + }, + _ => panic!(), + } +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs new file mode 100644 index 000000000..d5bca6a24 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs @@ -0,0 +1,40 @@ +// run-pass +const CONST_REF: &[u8; 3] = b"foo"; + +trait Foo { + const CONST_REF_DEFAULT: &'static [u8; 3] = b"bar"; + const CONST_REF: &'static [u8; 3]; +} + +impl Foo for i32 { + const CONST_REF: &'static [u8; 3] = b"jjj"; +} + +impl Foo for i64 { + const CONST_REF_DEFAULT: &'static [u8; 3] = b"ggg"; + const CONST_REF: &'static [u8; 3] = b"fff"; +} + +// Check that (associated and free) const references are not mistaken for a +// non-reference pattern (in which case they would be auto-dereferenced, making +// the types mismatched). + +fn const_ref() -> bool { + let f = b"foo"; + match f { + CONST_REF => true, + _ => false, + } +} + +fn associated_const_ref() -> bool { + match (b"bar", b"jjj", b"ggg", b"fff") { + (i32::CONST_REF_DEFAULT, i32::CONST_REF, i64::CONST_REF_DEFAULT, i64::CONST_REF) => true, + _ => false, + } +} + +pub fn main() { + assert!(const_ref()); + assert!(associated_const_ref()); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs new file mode 100644 index 000000000..52fbb90ed --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs @@ -0,0 +1,45 @@ +// run-pass +enum Wrapper { + Wrap(i32), +} + +use Wrapper::Wrap; + +pub fn main() { + let Wrap(x) = &Wrap(3); + println!("{}", *x); + + let Wrap(x) = &mut Wrap(3); + println!("{}", *x); + + if let Some(x) = &Some(3) { + println!("{}", *x); + } else { + panic!(); + } + + if let Some(x) = &mut Some(3) { + println!("{}", *x); + } else { + panic!(); + } + + if let Some(x) = &mut Some(3) { + *x += 1; + } else { + panic!(); + } + + while let Some(x) = &Some(3) { + println!("{}", *x); + break; + } + while let Some(x) = &mut Some(3) { + println!("{}", *x); + break; + } + while let Some(x) = &mut Some(3) { + *x += 1; + break; + } +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs new file mode 100644 index 000000000..a5a24a806 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs @@ -0,0 +1,20 @@ +// run-pass +pub fn main() { + let mut tups = vec![(0u8, 1u8)]; + + for (n, m) in &tups { + let _: &u8 = n; + let _: &u8 = m; + } + + for (n, m) in &mut tups { + *n += 1; + *m += 2; + } + + assert_eq!(tups, vec![(1u8, 3u8)]); + + for (n, m) in tups { + println!("{} {}", m, n); + } +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs new file mode 100644 index 000000000..0207f607b --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs @@ -0,0 +1,249 @@ +// run-pass +#![allow(unused_variables)] +fn some_or_wildcard(r: &Option, b: &i32) { + let _: &i32 = match r { + Some(a) => a, + _ => b, + }; +} + +fn none_or_wildcard(r: &Option, b: &i32) { + let _: &i32 = match r { + None => b, + _ => b, + }; +} + +fn some_or_ref_none(r: &Option, b: &i32) { + let _: &i32 = match r { + Some(a) => a, + &None => b, + }; +} + +fn ref_some_or_none(r: &Option, b: &i32) { + let _: &i32 = match r { + &Some(ref a) => a, + None => b, + }; +} + +fn some_or_self(r: &Option) { + let _: &Option = match r { + Some(n) => { + let _: &i32 = n; + r + }, + x => x, + }; +} + +fn multiple_deref(r: &&&&&Option) { + let _: i32 = match r { + Some(a) => *a, + None => 5, + }; +} + +fn match_with_or() { + // FIXME(tschottdorf): #44912. + // + // let x = &Some((3, 3)); + // let _: &i32 = match x { + // Some((x, 3)) | &Some((ref x, 5)) => x, + // _ => &5i32, + // }; +} + +fn nested_mixed() { + match (&Some(5), &Some(6)) { + (Some(a), &Some(mut b)) => { + // Here, the `a` will be `&i32`, because in the first half of the tuple + // we hit a non-reference pattern and shift into `ref` mode. + // + // In the second half of the tuple there's no non-reference pattern, + // so `b` will be `i32` (bound with `move` mode). Moreover, `b` is + // mutable. + let _: &i32 = a; + b = 7; + let _: i32 = b; + }, + _ => {}, + }; +} + +fn nested_mixed_multiple_deref_1() { + let x = (1, &Some(5)); + let y = &Some(x); + match y { + Some((a, Some(b))) => { + let _: &i32 = a; + let _: &i32 = b; + }, + _ => {}, + }; +} + +fn nested_mixed_multiple_deref_2() { + let x = &Some(5); + let y = &x; + match y { + Some(z) => { + let _: &i32 = z; + }, + _ => {}, + } +} + +fn new_mutable_reference() { + let mut x = &mut Some(5); + match &mut x { + Some(y) => { + *y = 5; + }, + None => { }, + } + + match &mut x { + Some(y) => { + println!("{}", *y); + }, + None => {}, + } +} + +fn let_implicit_ref_binding() { + struct Foo(i32); + + // Note that these rules apply to any pattern matching + // whether it be in a `match` or a `let`. + // For example, `x` here is a `ref` binding: + let Foo(x) = &Foo(3); + let _: &i32 = x; +} + +fn explicit_mut_binding() { + match &Some(5i32) { + Some(mut n) => { + n += 1; + let _ = n; + } + None => {}, + }; + + match &mut Some(5i32) { + Some(n) => { + *n += 1; + let _ = n; + } + None => {}, + }; + + match &mut &mut Some(5i32) { + Some(n) => { + let _: &mut i32 = n; + } + None => {}, + }; +} + +fn tuple_mut_and_mut_mut() { + match (Some(5i32), &Some(5i32)) { + (Some(n), Some(m)) => { + // `n` and `m` are bound as immutable references. Make new references from them to + // assert that. + let r = n; + let _ = r; + let q = m; + let _ = q; + + // Assert the types. Note that we use `n` and `m` here which would fail had they been + // moved due to the assignments above. + let _: i32 = n; + let _: &i32 = m; + } + (_, _) => {}, + }; + + match (&Some(5i32), &&Some(5i32)) { + (Some(n), Some(m)) => { + let _: &i32 = n; + let _: &i32 = m; + } + (_, _) => {}, + }; + + match &mut &mut (Some(5i32), Some(5i32)) { + (Some(n), Some(m)) => { + // Dereferenced through &mut &mut, so a mutable binding results. + let _: &mut i32 = n; + let _: &mut i32 = m; + } + (_, _) => {}, + }; + + match (&mut Some(5i32), &mut &mut Some(5i32)) { + (Some(n), Some(m)) => { + let _: &mut i32 = n; + let _: &mut i32 = m; + } + (_, _) => {}, + }; +} + +fn min_mir_embedded_type() { + // The reduced invocation that an ICE was diagnosed with (was consuming + // adjustments in wrong order). + match (0u8, &&Some(5i32)) { + (_, Some(m)) => { + let _: &i32 = m; + } + (_, _) => {}, + }; +} + +fn no_autoderef() { + // Binding. + let x = &3; + println!("{}", *x); + + // Wildcard. + let _ = &3; + + // Constant of generic type (string) + const Y: &'static str = "foo"; + assert_eq!(0, match "foo" { + Y => 0, + _ => 1, + }); + + // Reference pattern. + let &x = &3; +} + +pub fn main() { + let r: &Option = &Some(3); + let b = &4i32; + + none_or_wildcard(r, b); + some_or_wildcard(r, b); + some_or_ref_none(r, b); + ref_some_or_none(r, b); + + some_or_self(r); + multiple_deref(&&&&r); + match_with_or(); + + nested_mixed(); + nested_mixed_multiple_deref_1(); + nested_mixed_multiple_deref_2(); + + new_mutable_reference(); + explicit_mut_binding(); + tuple_mut_and_mut_mut(); + min_mir_embedded_type(); + + let_implicit_ref_binding(); + + no_autoderef(); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs new file mode 100644 index 000000000..937975359 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +fn with_u8() { + let s = 5u8; + let r = match &s { + 4 => false, + 5 => true, + _ => false, + }; + assert!(r); +} + +// A string literal isn't mistaken for a non-ref pattern (in which case we'd +// deref `s` and mess things up). +fn with_str() { + let s: &'static str = "abc"; + match s { + "abc" => true, + _ => panic!(), + }; +} + +// Ditto with byte strings. +fn with_bytes() { + let s: &'static [u8] = b"abc"; + match s { + b"abc" => true, + _ => panic!(), + }; +} + +pub fn main() { + with_str(); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs new file mode 100644 index 000000000..f8abd1b96 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs @@ -0,0 +1,9 @@ +// run-pass +pub fn main() { + let i = 5; + match &&&&i { + 1 ..= 3 => panic!(), + 4 ..= 8 => {}, + _ => panic!(), + } +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs new file mode 100644 index 000000000..b74e45c93 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs @@ -0,0 +1,16 @@ +// run-pass +fn foo<'a, 'b>(x: &'a &'b Option) -> &'a u32 { + let x: &'a &'a Option = x; + match x { + Some(r) => { + let _: &u32 = r; + r + }, + &None => panic!(), + } +} + +pub fn main() { + let x = Some(5); + foo(&&x); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs new file mode 100644 index 000000000..3b9d07610 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs @@ -0,0 +1,14 @@ +// run-pass +// Test that we "reset" the mode as we pass through a `&` pattern. +// +// cc #46688 + +fn surprise(x: i32) { + assert_eq!(x, 2); +} + +fn main() { + let x = &(1, &2); + let (_, &b) = x; + surprise(b); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs new file mode 100644 index 000000000..33229a205 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs @@ -0,0 +1,25 @@ +// run-pass + +fn slice_pat() { + let sl: &[u8] = b"foo"; + + match sl { + [first, remainder @ ..] => { + let _: &u8 = first; + assert_eq!(first, &b'f'); + assert_eq!(remainder, b"oo"); + } + [] => panic!(), + } +} + +fn slice_pat_omission() { + match &[0, 1, 2] { + [..] => {} + }; +} + +fn main() { + slice_pat(); + slice_pat_omission(); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs new file mode 100644 index 000000000..5a00e5b68 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs @@ -0,0 +1,22 @@ +// run-pass +#[derive(Debug, PartialEq)] +struct Foo { + x: u8, +} + +pub fn main() { + let mut foo = Foo { + x: 1, + }; + + match &mut foo { + Foo{x: n} => { + *n += 1; + }, + }; + + assert_eq!(foo, Foo{x: 2}); + + let Foo{x: n} = &foo; + assert_eq!(*n, 2); +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs new file mode 100644 index 000000000..0cf9ba1b4 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +enum Foo { + Bar(Option, (), (), Vec), + Baz, +} + +pub fn main() { + let foo = Foo::Bar(Some(1), (), (), vec![2, 3]); + + match &foo { + Foo::Baz => panic!(), + Foo::Bar(None, ..) => panic!(), + Foo::Bar(Some(n), .., v) => { + assert_eq!((*v).len(), 2); + assert_eq!(*n, 1); + } + } +} diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs new file mode 100644 index 000000000..4c22aa2d7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs @@ -0,0 +1,12 @@ +// run-pass +pub fn main() { + let foo = (Some(1), (), (), vec![2, 3]); + + match &foo { + (Some(n), .., v) => { + assert_eq!((*v).len(), 2); + assert_eq!(*n, 1); + } + (None, (), (), ..) => panic!(), + } +} diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs new file mode 100644 index 000000000..d359067f6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/attr.rs @@ -0,0 +1,15 @@ +// run-pass +use std::mem; + +#[r#repr(r#C, r#packed)] +struct Test { + a: bool, b: u64 +} + +#[r#derive(r#Debug)] +struct Test2(#[allow(unused_tuple_struct_fields)] u32); + +pub fn main() { + assert_eq!(mem::size_of::(), 9); + assert_eq!("Test2(123)", format!("{:?}", Test2(123))); +} diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs new file mode 100644 index 000000000..f2fe59668 --- /dev/null +++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/basic.rs @@ -0,0 +1,20 @@ +// run-pass +fn r#fn(r#match: u32) -> u32 { + r#match +} + +pub fn main() { + let r#struct = 1; + assert_eq!(1, r#struct); + + let foo = 2; + assert_eq!(2, r#foo); + + let r#bar = 3; + assert_eq!(3, bar); + + assert_eq!(4, r#fn(4)); + + let r#true = false; + assert_eq!(r#true, false); +} diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs new file mode 100644 index 000000000..466522517 --- /dev/null +++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/items.rs @@ -0,0 +1,32 @@ +// run-pass +#[derive(Debug, PartialEq, Eq)] +struct IntWrapper(u32); + +#[derive(Debug, Ord, PartialOrd, PartialEq, Eq, Hash, Copy, Clone, Default)] +struct HasKeywordField { + r#struct: u32, +} + +struct Generic(T); + +trait Trait { + fn r#trait(&self) -> u32; +} +impl Trait for Generic { + fn r#trait(&self) -> u32 { + self.0 + } +} + +pub fn main() { + assert_eq!(IntWrapper(1), r#IntWrapper(1)); + + match IntWrapper(2) { + r#IntWrapper(r#struct) => assert_eq!(2, r#struct), + } + + assert_eq!("HasKeywordField { struct: 3 }", format!("{:?}", HasKeywordField { r#struct: 3 })); + + assert_eq!(4, Generic(4).0); + assert_eq!(5, Generic(5).r#trait()); +} diff --git a/tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs b/tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs new file mode 100644 index 000000000..0ab7e17f8 --- /dev/null +++ b/tests/ui/rfcs/rfc-2151-raw-identifiers/macros.rs @@ -0,0 +1,38 @@ +// run-pass +#![feature(decl_macro)] + +macro_rules! r#struct { + ($r#struct:expr) => { $r#struct } +} + +macro_rules! old_macro { + ($a:expr) => {$a} +} + +macro r#decl_macro($r#fn:expr) { + $r#fn +} + +macro passthrough($id:ident) { + $id +} + +macro_rules! test_pat_match { + (a) => { 6 }; + (r#a) => { 7 }; +} + +pub fn main() { + r#println!("{struct}", r#struct = 1); + assert_eq!(2, r#struct!(2)); + assert_eq!(3, r#old_macro!(3)); + assert_eq!(4, decl_macro!(4)); + + let r#match = 5; + assert_eq!(5, passthrough!(r#match)); + + assert_eq!("r#struct", stringify!(r#struct)); + + assert_eq!(6, test_pat_match!(a)); + assert_eq!(7, test_pat_match!(r#a)); +} diff --git a/tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs b/tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs new file mode 100644 index 000000000..22f04c58f --- /dev/null +++ b/tests/ui/rfcs/rfc-2175-or-if-while-let/basic.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] + +enum E { + V(u8), + U(u8), + W, +} +use E::*; + +fn main() { + let mut e = V(10); + + if let V(x) | U(x) = e { + assert_eq!(x, 10); + } + while let V(x) | U(x) = e { + assert_eq!(x, 10); + e = W; + } + + // Accept leading `|`: + + let mut e = V(10); + + if let | V(x) | U(x) = e { + assert_eq!(x, 10); + } + while let | V(x) | U(x) = e { + assert_eq!(x, 10); + e = W; + } +} diff --git a/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs b/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs new file mode 100644 index 000000000..1ec20c500 --- /dev/null +++ b/tests/ui/rfcs/rfc-2302-self-struct-ctor.rs @@ -0,0 +1,127 @@ +// run-pass + +#![allow(dead_code)] + +use std::fmt::Display; + +struct ST1(i32, i32); + +impl ST1 { + fn new() -> Self { + ST1(0, 1) + } + + fn ctor() -> Self { + Self(1,2) // Self as a constructor + } + + fn pattern(self) { + match self { + Self(x, y) => println!("{} {}", x, y), // Self as a pattern + } + } +} + +struct ST2(T); // With type parameter + +impl ST2 where T: Display { + + fn ctor(v: T) -> Self { + Self(v) + } + + fn pattern(&self) { + match self { + Self(ref v) => println!("{}", v), + } + } +} + +struct ST3<'a>(&'a i32); // With lifetime parameter + +impl<'a> ST3<'a> { + + fn ctor(v: &'a i32) -> Self { + Self(v) + } + + fn pattern(self) { + let Self(ref v) = self; + println!("{}", v); + } +} + +struct ST4(usize); + +impl ST4 { + fn map(opt: Option) -> Option { + opt.map(Self) // use `Self` as a function passed somewhere + } +} + +struct ST5; // unit struct + +impl ST5 { + fn ctor() -> Self { + Self // `Self` as a unit struct value + } + + fn pattern(self) -> Self { + match self { + Self => Self, // `Self` as a unit struct value for matching + } + } +} + +struct ST6(i32); +type T = ST6; +impl T { + fn ctor() -> Self { + ST6(1) + } + + fn type_alias(self) { + let Self(_x) = match self { Self(x) => Self(x) }; + let _opt: Option = Some(0).map(Self); + } +} + +struct ST7(T1, T2); + +impl ST7 { + + fn ctor() -> Self { + Self(1, 2) + } + + fn pattern(self) -> Self { + match self { + Self(x, y) => Self(x, y), + } + } +} + +fn main() { + let v1 = ST1::ctor(); + v1.pattern(); + + let v2 = ST2::ctor(10); + v2.pattern(); + + let local = 42; + let v3 = ST3::ctor(&local); + v3.pattern(); + + let v4 = Some(1usize); + let _ = ST4::map(v4); + + let v5 = ST5::ctor(); + v5.pattern(); + + let v6 = ST6::ctor(); + v6.type_alias(); + + let v7 = ST7::::ctor(); + let r = v7.pattern(); + println!("{} {}", r.0, r.1) +} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs new file mode 100644 index 000000000..e0842bfa4 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs @@ -0,0 +1,52 @@ +// Tests the new rules added by RFC 2396, including: +// - applying `#[target_feature]` to safe functions is allowed +// - calling functions with `#[target_feature]` is allowed in +// functions which have (at least) the same features +// - calling functions with `#[target_feature]` is allowed in +// unsafe contexts +// - functions with `#[target_feature]` can coerce to unsafe fn pointers + +// check-pass +// only-x86_64 +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(target_feature_11)] + +#[target_feature(enable = "sse2")] +const fn sse2() {} + +#[cfg(target_feature = "sse2")] +const SSE2_ONLY: () = unsafe { + sse2(); +}; + +#[target_feature(enable = "sse2")] +fn also_sse2() { + sse2(); +} + +#[target_feature(enable = "sse2")] +#[target_feature(enable = "avx")] +fn sse2_and_avx() { + sse2(); +} + +struct Foo; + +impl Foo { + #[target_feature(enable = "sse2")] + fn sse2(&self) { + sse2(); + } +} + +fn main() { + if cfg!(target_feature = "sse2") { + unsafe { + sse2(); + Foo.sse2(); + } + } + let sse2_ptr: unsafe fn() = sse2; +} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs new file mode 100644 index 000000000..a59d7c2d7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs @@ -0,0 +1,20 @@ +// Tests #73631: closures inherit `#[target_feature]` annotations + +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable="avx")] +fn also_use_avx() { + println!("Hello from AVX") +} + +#[target_feature(enable="avx")] +fn use_avx() -> Box { + Box::new(|| also_use_avx()) +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs new file mode 100644 index 000000000..975d7a1f6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.rs @@ -0,0 +1,6 @@ +// only-x86_64 + +#[target_feature(enable = "sse2")] //~ ERROR can only be applied to `unsafe` functions +fn foo() {} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr new file mode 100644 index 000000000..18917fd25 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/feature-gate-target_feature_11.stderr @@ -0,0 +1,14 @@ +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/feature-gate-target_feature_11.rs:3:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() {} + | -------- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr new file mode 100644 index 000000000..cf5815df5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/fn-ptr.rs:11:21 + | +LL | #[target_feature(enable = "sse2")] + | ---------------------------------- `#[target_feature]` added here +... +LL | let foo: fn() = foo; + | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers + | | + | expected due to this + | + = note: expected fn pointer `fn()` + found fn item `fn() {foo}` + = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs new file mode 100644 index 000000000..c95d4a08e --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs @@ -0,0 +1,12 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "sse2")] +fn foo() {} + +fn main() { + let foo: fn() = foo; //~ ERROR mismatched types +} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr new file mode 100644 index 000000000..cf5815df5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/fn-ptr.rs:11:21 + | +LL | #[target_feature(enable = "sse2")] + | ---------------------------------- `#[target_feature]` added here +... +LL | let foo: fn() = foo; + | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers + | | + | expected due to this + | + = note: expected fn pointer `fn()` + found fn item `fn() {foo}` + = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs new file mode 100644 index 000000000..43bda4962 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -0,0 +1,34 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "avx")] +fn foo() {} + +#[target_feature(enable = "avx")] +unsafe fn foo_unsafe() {} + +fn call(f: impl Fn()) { + f() +} + +fn call_mut(f: impl FnMut()) { + f() +} + +fn call_once(f: impl FnOnce()) { + f() +} + +fn main() { + call(foo); //~ ERROR expected a `Fn<()>` closure, found `fn() {foo}` + call_mut(foo); //~ ERROR expected a `FnMut<()>` closure, found `fn() {foo}` + call_once(foo); //~ ERROR expected a `FnOnce<()>` closure, found `fn() {foo}` + + call(foo_unsafe); + //~^ ERROR expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + call_mut(foo_unsafe); + //~^ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + call_once(foo_unsafe); + //~^ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` +} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr new file mode 100644 index 000000000..fc7bf2277 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -0,0 +1,105 @@ +error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:24:10 + | +LL | call(foo); + | ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` + = note: `#[target_feature]` functions do not implement the `Fn` traits +note: required by a bound in `call` + --> $DIR/fn-traits.rs:11:17 + | +LL | fn call(f: impl Fn()) { + | ^^^^ required by this bound in `call` + +error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:25:14 + | +LL | call_mut(foo); + | -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` + = note: `#[target_feature]` functions do not implement the `Fn` traits +note: required by a bound in `call_mut` + --> $DIR/fn-traits.rs:15:21 + | +LL | fn call_mut(f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` + +error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}` + --> $DIR/fn-traits.rs:26:15 + | +LL | call_once(foo); + | --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}` + = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` + = note: `#[target_feature]` functions do not implement the `Fn` traits +note: required by a bound in `call_once` + --> $DIR/fn-traits.rs:19:22 + | +LL | fn call_once(f: impl FnOnce()) { + | ^^^^^^^^ required by this bound in `call_once` + +error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}` + --> $DIR/fn-traits.rs:28:10 + | +LL | call(foo_unsafe); + | ---- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` + = note: `#[target_feature]` functions do not implement the `Fn` traits +note: required by a bound in `call` + --> $DIR/fn-traits.rs:11:17 + | +LL | fn call(f: impl Fn()) { + | ^^^^ required by this bound in `call` + +error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}` + --> $DIR/fn-traits.rs:30:14 + | +LL | call_mut(foo_unsafe); + | -------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` + = note: `#[target_feature]` functions do not implement the `Fn` traits +note: required by a bound in `call_mut` + --> $DIR/fn-traits.rs:15:21 + | +LL | fn call_mut(f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` + +error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}` + --> $DIR/fn-traits.rs:32:15 + | +LL | call_once(foo_unsafe); + | --------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` + = note: `#[target_feature]` functions do not implement the `Fn` traits +note: required by a bound in `call_once` + --> $DIR/fn-traits.rs:19:22 + | +LL | fn call_once(f: impl FnOnce()) { + | ^^^^^^^^ required by this bound in `call_once` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs new file mode 100644 index 000000000..033dcdfc0 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(target_feature_11)] + +struct S(T) +where + [T; (|| {}, 1).1]: Copy; + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr new file mode 100644 index 000000000..0ef7b8b09 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr @@ -0,0 +1,83 @@ +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:23:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:26:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:29:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:36:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:39:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:46:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:49:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:52:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:60:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:65:18 + | +LL | const name: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs new file mode 100644 index 000000000..cebc6f947 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -0,0 +1,69 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +// only-x86_64 + +#![feature(target_feature_11)] + +#[target_feature(enable = "sse2")] +const fn sse2() {} + +#[target_feature(enable = "avx")] +#[target_feature(enable = "bmi2")] +fn avx_bmi2() {} + +struct Quux; + +impl Quux { + #[target_feature(enable = "avx")] + #[target_feature(enable = "bmi2")] + fn avx_bmi2(&self) {} +} + +fn foo() { + sse2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe + avx_bmi2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe + Quux.avx_bmi2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe +} + +#[target_feature(enable = "sse2")] +fn bar() { + avx_bmi2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe + Quux.avx_bmi2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe +} + +#[target_feature(enable = "avx")] +fn baz() { + sse2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe + avx_bmi2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe + Quux.avx_bmi2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe +} + +#[target_feature(enable = "avx")] +#[target_feature(enable = "bmi2")] +fn qux() { + sse2(); + //[mir]~^ ERROR call to function with `#[target_feature]` is unsafe + //[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe +} + +const name: () = sse2(); +//[mir]~^ ERROR call to function with `#[target_feature]` is unsafe +//[thir]~^^ ERROR call to function `sse2` with `#[target_feature]` is unsafe + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr new file mode 100644 index 000000000..c75ac6e8b --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr @@ -0,0 +1,83 @@ +error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:23:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:26:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:29:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:36:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:39:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:46:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:49:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:52:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:60:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:65:18 + | +LL | const name: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs new file mode 100644 index 000000000..7314fa8cc --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs @@ -0,0 +1,21 @@ +// only-x86_64 + +#![feature(target_feature_11)] + +trait Foo { + fn foo(&self); + unsafe fn unsf_foo(&self); +} + +struct Bar; + +impl Foo for Bar { + #[target_feature(enable = "sse2")] + //~^ ERROR cannot be applied to safe trait method + fn foo(&self) {} + + #[target_feature(enable = "sse2")] + unsafe fn unsf_foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr new file mode 100644 index 000000000..07d6e0900 --- /dev/null +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr @@ -0,0 +1,11 @@ +error: `#[target_feature(..)]` cannot be applied to safe trait method + --> $DIR/trait-impl.rs:13:5 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method +LL | +LL | fn foo(&self) {} + | ------------- not an `unsafe` function + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs b/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs new file mode 100644 index 000000000..6d7bca4da --- /dev/null +++ b/tests/ui/rfcs/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that removed keywords are allowed as identifiers. +fn main () { + let offsetof = (); + let alignof = (); + let sizeof = (); + let pure = (); +} + +fn offsetof() {} +fn alignof() {} +fn sizeof() {} +fn pure() {} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs new file mode 100644 index 000000000..75e48bf4a --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +use std::any::Any; + +struct Foo { + a: A, + b: Box, + c: Box, +} + +struct B; +struct C; + +fn main() { + let y = Foo:: { + a: 0, + b: Box::new(B), + ..Foo { + a: 0, + b: Box::new(B), + // C needs to be told to coerce to `Box` + c: Box::new(C), + } + }; +} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs new file mode 100644 index 000000000..1e8b99ba5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.rs @@ -0,0 +1,29 @@ +// gate-test-type_changing_struct_update + +#[derive(Debug)] +struct Machine { + state: S, + common_field1: &'static str, + common_field2: i32, +} +#[derive(Debug)] +struct State1; +#[derive(Debug, PartialEq)] +struct State2; + +fn update_to_state2() { + let m1: Machine = Machine { + state: State1, + common_field1: "hello", + common_field2: 2, + }; + let m2: Machine = Machine { + state: State2, + ..m1 + //~^ ERROR type changing struct updating is experimental [E0658] + //~| ERROR mismatched types [E0308] + }; + assert_eq!(State2, m2.state); +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr new file mode 100644 index 000000000..2217b8c04 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr @@ -0,0 +1,22 @@ +error[E0658]: type changing struct updating is experimental + --> $DIR/feature-gate.rs:22:11 + | +LL | ..m1 + | ^^ + | + = note: see issue #86555 for more information + = help: add `#![feature(type_changing_struct_update)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/feature-gate.rs:22:11 + | +LL | ..m1 + | ^^ expected struct `State2`, found struct `State1` + | + = note: expected struct `Machine` + found struct `Machine` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs new file mode 100644 index 000000000..f1a54ee58 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs @@ -0,0 +1,12 @@ +#[derive(Clone)] +struct P { + x: T, + y: f64, +} + +impl P { + fn y(&self, y: f64) -> Self { P{y, .. self.clone() } } + //~^ mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr new file mode 100644 index 000000000..5957ea7c9 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-92010-trait-bound-not-satisfied.rs:8:43 + | +LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } } + | ^^^^^^^^^^^^ expected struct `P`, found `&P` + | + = note: expected struct `P` + found reference `&P` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs new file mode 100644 index 000000000..3dfbef0ee --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +use std::borrow::Cow; +use std::marker::PhantomData; + +#[derive(Default)] +struct NonGeneric { + field1: usize, +} + +#[derive(Default)] +struct Generic { + field1: T, + field2: U, +} + +#[derive(Default)] +struct MoreGeneric<'a, const N: usize> { + // If only `for [u32; N]: Default`... + field1: PhantomData<[u32; N]>, + field2: Cow<'a, str>, +} + +fn main() { + let default1 = NonGeneric { ..Default::default() }; + let default2: Generic = Generic { ..Default::default() }; + let default3: MoreGeneric<'static, 12> = MoreGeneric { ..Default::default() }; +} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs new file mode 100644 index 000000000..df2fef55d --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs @@ -0,0 +1,43 @@ +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +#[derive(Clone)] +struct Machine<'a, S> { + state: S, + lt_str: &'a str, + common_field: i32, +} + +#[derive(Clone)] +struct State1; +#[derive(Clone)] +struct State2; + +fn update_to_state2() { + let s = String::from("hello"); + let m1: Machine = Machine { + state: State1, + lt_str: &s, + //~^ ERROR `s` does not live long enough [E0597] + // FIXME: The error here actually comes from line 34. The + // span of the error message should be corrected to line 34 + common_field: 2, + }; + // update lifetime + let m3: Machine<'static, State1> = Machine { + lt_str: "hello, too", + ..m1.clone() + }; + // update lifetime and type + let m4: Machine<'static, State2> = Machine { + state: State2, + lt_str: "hello, again", + ..m1.clone() + }; + // updating to `static should fail. + let m2: Machine<'static, State1> = Machine { + ..m1 + }; +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr new file mode 100644 index 000000000..5f93ad6e0 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr @@ -0,0 +1,15 @@ +error[E0597]: `s` does not live long enough + --> $DIR/lifetime-update.rs:20:17 + | +LL | lt_str: &s, + | ^^ borrowed value does not live long enough +... +LL | let m2: Machine<'static, State1> = Machine { + | ------------------------ type annotation requires that `s` is borrowed for `'static` +... +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs new file mode 100644 index 000000000..dae1241d3 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs @@ -0,0 +1,56 @@ +#![feature(type_changing_struct_update)] +#![allow(incomplete_features)] + +struct Machine<'a, S, M> { + state: S, + message: M, + lt_str: &'a str, + common_field: i32, +} + +struct State1; +struct State2; + +struct Message1; +struct Message2; + +fn update() { + let m1: Machine = Machine { + state: State1, + message: Message1, + lt_str: "hello", + common_field: 2, + }; + // single type update + let m2: Machine = Machine { + state: State2, + ..m1 + }; + // multiple type update + let m3: Machine = Machine { + state: State2, + message: Message2, + ..m1 + }; +} + +fn fail_update() { + let m1: Machine = Machine { + state: 3.2, + message: 6.4, + lt_str: "hello", + common_field: 2, + }; + // single type update fail + let m2: Machine = Machine { + ..m1 + //~^ ERROR mismatched types [E0308] + }; + // multiple type update fail + let m3 = Machine:: { + ..m1 + //~^ ERROR mismatched types [E0308] + }; +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr new file mode 100644 index 000000000..6f31b1a96 --- /dev/null +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:46:11 + | +LL | ..m1 + | ^^ expected `i32`, found `f64` + | + = note: expected struct `Machine<'_, i32, _>` + found struct `Machine<'_, f64, _>` + +error[E0308]: mismatched types + --> $DIR/type-generic-update.rs:51:11 + | +LL | ..m1 + | ^^ expected `i32`, found `f64` + | + = note: expected struct `Machine<'_, i32, i32>` + found struct `Machine<'_, f64, f64>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs b/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs new file mode 100644 index 000000000..17174e22c --- /dev/null +++ b/tests/ui/rfcs/rfc1445/eq-allows-match-on-ty-in-macro.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +macro_rules! foo { + (#[$attr:meta] $x:ident) => { + #[$attr] + struct $x { + x: u32 + } + } +} + +foo! { #[derive(PartialEq, Eq)] Foo } + +const FOO: Foo = Foo { x: 0 }; + +fn main() { + let y = Foo { x: 1 }; + match y { + FOO => { } + _ => { } + } +} diff --git a/tests/ui/rfcs/rfc1445/eq-allows-match.rs b/tests/ui/rfcs/rfc1445/eq-allows-match.rs new file mode 100644 index 000000000..405a69c94 --- /dev/null +++ b/tests/ui/rfcs/rfc1445/eq-allows-match.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] + +#[derive(PartialEq, Eq)] +struct Foo { + x: u32 +} + +const FOO: Foo = Foo { x: 0 }; + +fn main() { + let y = Foo { x: 1 }; + match y { + FOO => { } + _ => { } + } +} diff --git a/tests/ui/rfcs/rfc1623-2.rs b/tests/ui/rfcs/rfc1623-2.rs new file mode 100644 index 000000000..c0e13a5f5 --- /dev/null +++ b/tests/ui/rfcs/rfc1623-2.rs @@ -0,0 +1,99 @@ +#![allow(dead_code)] + +fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { + a +} + +// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs` +static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = + &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); + +struct SomeStruct<'x, 'y, 'z: 'x> { + foo: &'x Foo<'z>, + bar: &'x Bar<'z>, + f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>, +} + +// Without this, the wf-check will fail early so we'll never see the +// error in SOME_STRUCT's body. +unsafe impl<'x, 'y, 'z: 'x> Sync for SomeStruct<'x, 'y, 'z> {} + +fn id(t: T) -> T { + t +} + +static SOME_STRUCT: &SomeStruct = &SomeStruct { + foo: &Foo { bools: &[false, true] }, + bar: &Bar { bools: &[true, true] }, + f: &id, + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough +}; + +// very simple test for a 'static static with default lifetime +static STATIC_STR: &'static str = "&'static str"; +const CONST_STR: &'static str = "&'static str"; + +// this should be the same as without default: +static EXPLICIT_STATIC_STR: &'static str = "&'static str"; +const EXPLICIT_CONST_STR: &'static str = "&'static str"; + +// a function that elides to an unbound lifetime for both in- and output +fn id_u8_slice(arg: &[u8]) -> &[u8] { + arg +} + +// one with a function, argument elided +static STATIC_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); +const CONST_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); + +// this should be the same as without elision +static STATIC_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); +const CONST_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); + +// another function that elides, each to a different unbound lifetime +fn multi_args(a: &u8, b: &u8, c: &u8) {} + +static STATIC_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); +const CONST_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); + +struct Foo<'a> { + bools: &'a [bool], +} + +static STATIC_FOO: Foo<'static> = Foo { bools: &[true, false] }; +const CONST_FOO: Foo<'static> = Foo { bools: &[true, false] }; + +type Bar<'a> = Foo<'a>; + +static STATIC_BAR: Bar<'static> = Bar { bools: &[true, false] }; +const CONST_BAR: Bar<'static> = Bar { bools: &[true, false] }; + +type Baz<'a> = fn(&'a [u8]) -> Option; + +fn baz(e: &[u8]) -> Option { + e.first().map(|x| *x) +} + +static STATIC_BAZ: &'static Baz<'static> = &(baz as Baz); +const CONST_BAZ: &'static Baz<'static> = &(baz as Baz); + +static BYTES: &'static [u8] = &[1, 2, 3]; + +fn main() { + let x = &[1u8, 2, 3]; + let y = x; + + // this works, so lifetime < `'static` is valid + assert_eq!(Some(1), STATIC_BAZ(y)); + assert_eq!(Some(1), CONST_BAZ(y)); + + let y = &[1u8, 2, 3]; + + STATIC_BAZ(BYTES); // BYTES has static lifetime + CONST_BAZ(y); // interestingly this does not get reported +} diff --git a/tests/ui/rfcs/rfc1623-2.stderr b/tests/ui/rfcs/rfc1623-2.stderr new file mode 100644 index 000000000..d183eaaa6 --- /dev/null +++ b/tests/ui/rfcs/rfc1623-2.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/rfc1623-2.rs:28:8 + | +LL | f: &id, + | ^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` + found trait `Fn<(&Foo<'_>,)>` + +error[E0308]: mismatched types + --> $DIR/rfc1623-2.rs:28:8 + | +LL | f: &id, + | ^^^ one type is more general than the other + | + = note: expected trait `for<'a, 'b> Fn<(&'a Foo<'b>,)>` + found trait `Fn<(&Foo<'_>,)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/rfc1623-2.rs:28:8 + | +LL | f: &id, + | ^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'b>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/rfc1623-2.rs:28:8 + | +LL | f: &id, + | ^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&'a Foo<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc1623-3.rs b/tests/ui/rfcs/rfc1623-3.rs new file mode 100644 index 000000000..26fa6fdb5 --- /dev/null +++ b/tests/ui/rfcs/rfc1623-3.rs @@ -0,0 +1,14 @@ +#![allow(dead_code)] + +fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { + a +} + +// the boundaries of elision +static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = +//~^ ERROR missing lifetime specifier [E0106] + &(non_elidable as fn(&u8, &u8) -> &u8); + //~^ ERROR missing lifetime specifier [E0106] + //~| ERROR non-primitive cast + +fn main() {} diff --git a/tests/ui/rfcs/rfc1623-3.stderr b/tests/ui/rfcs/rfc1623-3.stderr new file mode 100644 index 000000000..77fc3f041 --- /dev/null +++ b/tests/ui/rfcs/rfc1623-3.stderr @@ -0,0 +1,35 @@ +error[E0106]: missing lifetime specifier + --> $DIR/rfc1623-3.rs:8:42 + | +LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = + | --- --- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = + | +++++++ ++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/rfc1623-3.rs:10:39 + | +LL | &(non_elidable as fn(&u8, &u8) -> &u8); + | --- --- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider making the type lifetime-generic with a new `'a` lifetime + | +LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); + | +++++++ ++ ++ ++ + +error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8` + --> $DIR/rfc1623-3.rs:10:6 + | +LL | &(non_elidable as fn(&u8, &u8) -> &u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0605. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/rfcs/rfc1623.rs b/tests/ui/rfcs/rfc1623.rs new file mode 100644 index 000000000..adaf25c6b --- /dev/null +++ b/tests/ui/rfcs/rfc1623.rs @@ -0,0 +1,75 @@ +// run-pass +#![allow(unused_variables)] +#![allow(non_upper_case_globals)] + +#![allow(dead_code)] + +// very simple test for a 'static static with default lifetime +static STATIC_STR: &str = "&'static str"; +const CONST_STR: &str = "&'static str"; + +// this should be the same as without default: +static EXPLICIT_STATIC_STR: &'static str = "&'static str"; +const EXPLICIT_CONST_STR: &'static str = "&'static str"; + +// a function that elides to an unbound lifetime for both in- and output +fn id_u8_slice(arg: &[u8]) -> &[u8] { + arg +} + +// one with a function, argument elided +static STATIC_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); +const CONST_SIMPLE_FN: &fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]); + +// this should be the same as without elision +static STATIC_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); +const CONST_NON_ELIDED_fN: &for<'a> fn(&'a [u8]) -> &'a [u8] = + &(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]); + +// another function that elides, each to a different unbound lifetime +fn multi_args(a: &u8, b: &u8, c: &u8) {} + +static STATIC_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); +const CONST_MULTI_FN: &fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8)); + +struct Foo<'a> { + bools: &'a [bool], +} + +static STATIC_FOO: Foo = Foo { bools: &[true, false] }; +const CONST_FOO: Foo = Foo { bools: &[true, false] }; + +type Bar<'a> = Foo<'a>; + +static STATIC_BAR: Bar = Bar { bools: &[true, false] }; +const CONST_BAR: Bar = Bar { bools: &[true, false] }; + +type Baz<'a> = fn(&'a [u8]) -> Option; + +fn baz(e: &[u8]) -> Option { + e.first().map(|x| *x) +} + +static STATIC_BAZ: &Baz = &(baz as Baz); +const CONST_BAZ: &Baz = &(baz as Baz); + +static BYTES: &[u8] = &[1, 2, 3]; + +fn main() { + // make sure that the lifetime is actually elided (and not defaulted) + let x = &[1u8, 2, 3]; + STATIC_SIMPLE_FN(x); + CONST_SIMPLE_FN(x); + + STATIC_BAZ(BYTES); // neees static lifetime + CONST_BAZ(BYTES); + + // make sure this works with different lifetimes + let a = &1; + { + let b = &2; + let c = &3; + CONST_MULTI_FN(a, b, c); + } +} diff --git a/tests/ui/rfcs/rfc1717/library-override.rs b/tests/ui/rfcs/rfc1717/library-override.rs new file mode 100644 index 000000000..014ccac31 --- /dev/null +++ b/tests/ui/rfcs/rfc1717/library-override.rs @@ -0,0 +1,14 @@ +// run-pass +// ignore-wasm32-bare no libc to test ffi with +// compile-flags: -lstatic=wronglibrary:rust_test_helpers + +#[link(name = "wronglibrary", kind = "dylib")] +extern "C" { + pub fn rust_dbg_extern_identity_u32(x: u32) -> u32; +} + +fn main() { + unsafe { + rust_dbg_extern_identity_u32(42); + } +} diff --git a/tests/ui/rfcs/rfc1857-drop-order.rs b/tests/ui/rfcs/rfc1857-drop-order.rs new file mode 100644 index 000000000..4c4816c2f --- /dev/null +++ b/tests/ui/rfcs/rfc1857-drop-order.rs @@ -0,0 +1,224 @@ +// run-pass +// needs-unwind + +#![allow(dead_code, unreachable_code)] + +use std::cell::RefCell; +use std::rc::Rc; +use std::panic::{self, AssertUnwindSafe, UnwindSafe}; + +// This struct is used to record the order in which elements are dropped +struct PushOnDrop { + vec: Rc>>, + val: u32 +} + +impl PushOnDrop { + fn new(val: u32, vec: Rc>>) -> PushOnDrop { + PushOnDrop { vec, val } + } +} + +impl Drop for PushOnDrop { + fn drop(&mut self) { + self.vec.borrow_mut().push(self.val) + } +} + +impl UnwindSafe for PushOnDrop { } + +// Structs +struct TestStruct { + x: PushOnDrop, + y: PushOnDrop, + z: PushOnDrop +} + +// Tuple structs +struct TestTupleStruct(PushOnDrop, PushOnDrop, PushOnDrop); + +// Enum variants +enum TestEnum { + Tuple(PushOnDrop, PushOnDrop, PushOnDrop), + Struct { x: PushOnDrop, y: PushOnDrop, z: PushOnDrop } +} + +fn test_drop_tuple() { + // Tuple fields are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple = (PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone())); + drop(test_tuple); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Panic during construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + (PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is caught :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_struct() { + // Struct fields are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_struct = TestStruct { + x: PushOnDrop::new(1, dropped_fields.clone()), + y: PushOnDrop::new(2, dropped_fields.clone()), + z: PushOnDrop::new(3, dropped_fields.clone()), + }; + drop(test_struct); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for tuple structs + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple_struct = TestTupleStruct(PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())); + drop(test_tuple_struct); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during struct construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestStruct { + x: PushOnDrop::new(2, cloned.clone()), + y: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is caught :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Test with different initialization order + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestStruct { + y: PushOnDrop::new(2, cloned.clone()), + x: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is caught :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for tuple structs + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestTupleStruct(PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is caught :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_enum() { + // Enum variants are dropped in the same order they are declared + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_struct_enum = TestEnum::Struct { + x: PushOnDrop::new(1, dropped_fields.clone()), + y: PushOnDrop::new(2, dropped_fields.clone()), + z: PushOnDrop::new(3, dropped_fields.clone()) + }; + drop(test_struct_enum); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for tuple enum variants + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let test_tuple_enum = TestEnum::Tuple(PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())); + drop(test_tuple_enum); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during enum construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Struct { + x: PushOnDrop::new(2, cloned.clone()), + y: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is caught :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // Test with different initialization order + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Struct { + y: PushOnDrop::new(2, cloned.clone()), + x: PushOnDrop::new(1, cloned.clone()), + z: panic!("this panic is caught :D") + }; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for tuple enum variants + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + TestEnum::Tuple(PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is caught :D")); + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn test_drop_list() { + // Elements in a Vec are dropped in the same order they are pushed + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let xs = vec![PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())]; + drop(xs); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // The same holds for arrays + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let xs = [PushOnDrop::new(1, dropped_fields.clone()), + PushOnDrop::new(2, dropped_fields.clone()), + PushOnDrop::new(3, dropped_fields.clone())]; + drop(xs); + assert_eq!(*dropped_fields.borrow(), &[1, 2, 3]); + + // Panic during vec construction means that fields are treated as local variables + // Therefore they are dropped in reverse order of initialization + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + vec![ + PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is caught :D") + ]; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); + + // The same holds for arrays + let dropped_fields = Rc::new(RefCell::new(Vec::new())); + let cloned = AssertUnwindSafe(dropped_fields.clone()); + panic::catch_unwind(|| { + [ + PushOnDrop::new(2, cloned.clone()), + PushOnDrop::new(1, cloned.clone()), + panic!("this panic is caught :D") + ]; + }).err().unwrap(); + assert_eq!(*dropped_fields.borrow(), &[1, 2]); +} + +fn main() { + test_drop_tuple(); + test_drop_struct(); + test_drop_enum(); + test_drop_list(); +} diff --git a/tests/ui/rmeta/auxiliary/rmeta-meta.rs b/tests/ui/rmeta/auxiliary/rmeta-meta.rs new file mode 100644 index 000000000..6d8ed95bd --- /dev/null +++ b/tests/ui/rmeta/auxiliary/rmeta-meta.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic +// compile-flags: --emit=metadata + +#![crate_type="rlib"] + +pub struct Foo { + pub field: i32, +} diff --git a/tests/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs b/tests/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs new file mode 100644 index 000000000..f5e8c3d2a --- /dev/null +++ b/tests/ui/rmeta/auxiliary/rmeta-rlib-rpass.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![crate_type="rlib"] +#![crate_name="rmeta_aux"] + +pub struct Foo { + pub field: i32, +} diff --git a/tests/ui/rmeta/auxiliary/rmeta-rlib.rs b/tests/ui/rmeta/auxiliary/rmeta-rlib.rs new file mode 100644 index 000000000..4a05710db --- /dev/null +++ b/tests/ui/rmeta/auxiliary/rmeta-rlib.rs @@ -0,0 +1,5 @@ +#![crate_type="rlib"] + +pub struct Foo { + pub field: i32, +} diff --git a/tests/ui/rmeta/auxiliary/rmeta-rmeta.rs b/tests/ui/rmeta/auxiliary/rmeta-rmeta.rs new file mode 100644 index 000000000..4a6d055a8 --- /dev/null +++ b/tests/ui/rmeta/auxiliary/rmeta-rmeta.rs @@ -0,0 +1,9 @@ +// no-prefer-dynamic +// compile-flags: --emit=metadata + +#![crate_type="rlib"] +#![crate_name="rmeta_aux"] + +pub struct Foo { + pub field2: i32, +} diff --git a/tests/ui/rmeta/emit-artifact-notifications.polonius.stderr b/tests/ui/rmeta/emit-artifact-notifications.polonius.stderr new file mode 100644 index 000000000..255c7b370 --- /dev/null +++ b/tests/ui/rmeta/emit-artifact-notifications.polonius.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications.polonius/libemit_artifact_notifications.rmeta","emit":"metadata"} diff --git a/tests/ui/rmeta/emit-artifact-notifications.rs b/tests/ui/rmeta/emit-artifact-notifications.rs new file mode 100644 index 000000000..984a7fabb --- /dev/null +++ b/tests/ui/rmeta/emit-artifact-notifications.rs @@ -0,0 +1,8 @@ +// compile-flags:--emit=metadata --error-format=json --json artifacts +// build-pass +// ignore-pass +// ^-- needed because `--pass check` does not emit the output needed. + +// A very basic test for the emission of artifact notifications in JSON output. + +fn main() {} diff --git a/tests/ui/rmeta/emit-artifact-notifications.stderr b/tests/ui/rmeta/emit-artifact-notifications.stderr new file mode 100644 index 000000000..b2f0aa757 --- /dev/null +++ b/tests/ui/rmeta/emit-artifact-notifications.stderr @@ -0,0 +1 @@ +{"artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"} diff --git a/tests/ui/rmeta/emit-metadata-obj.rs b/tests/ui/rmeta/emit-metadata-obj.rs new file mode 100644 index 000000000..334c7cc5b --- /dev/null +++ b/tests/ui/rmeta/emit-metadata-obj.rs @@ -0,0 +1,7 @@ +// compile-flags:--emit=metadata,obj +// build-pass + +// A test for the emission of metadata + obj and other metadata + non-link +// combinations. See issue #81117. + +fn main() {} diff --git a/tests/ui/rmeta/rmeta-lib-pass.rs b/tests/ui/rmeta/rmeta-lib-pass.rs new file mode 100644 index 000000000..fdd0516e4 --- /dev/null +++ b/tests/ui/rmeta/rmeta-lib-pass.rs @@ -0,0 +1,14 @@ +// compile-flags: --emit=metadata +// aux-build:rmeta-rlib.rs +// no-prefer-dynamic +// build-pass (FIXME(62277): could be check-pass?) + +// Check that building a metadata crate works with a dependent, rlib crate. +// This is a cfail test since there is no executable to run. + +extern crate rmeta_rlib; +use rmeta_rlib::Foo; + +pub fn main() { + let _ = Foo { field: 42 }; +} diff --git a/tests/ui/rmeta/rmeta-pass.rs b/tests/ui/rmeta/rmeta-pass.rs new file mode 100644 index 000000000..4f0db23f4 --- /dev/null +++ b/tests/ui/rmeta/rmeta-pass.rs @@ -0,0 +1,15 @@ +// compile-flags: --emit=metadata +// aux-build:rmeta-meta.rs +// no-prefer-dynamic +// build-pass (FIXME(62277): could be check-pass?) + +// Check that building a metadata crate works with a dependent, metadata-only +// crate. +// This is a cfail test since there is no executable to run. + +extern crate rmeta_meta; +use rmeta_meta::Foo; + +pub fn main() { + let _ = Foo { field: 42 }; +} diff --git a/tests/ui/rmeta/rmeta-priv-warn.rs b/tests/ui/rmeta/rmeta-priv-warn.rs new file mode 100644 index 000000000..430c1f06f --- /dev/null +++ b/tests/ui/rmeta/rmeta-priv-warn.rs @@ -0,0 +1,11 @@ +// compile-flags: --emit=metadata +// no-prefer-dynamic +// build-pass (FIXME(62277): could be check-pass?) + +#[deny(warnings)] + +// Test that we don't get warnings for non-pub main when only emitting metadata. +// (#38273) + +fn main() { +} diff --git a/tests/ui/rmeta/rmeta-rpass.rs b/tests/ui/rmeta/rmeta-rpass.rs new file mode 100644 index 000000000..173a6a394 --- /dev/null +++ b/tests/ui/rmeta/rmeta-rpass.rs @@ -0,0 +1,18 @@ +// run-pass +// Test that using rlibs and rmeta dep crates work together. Specifically, that +// there can be both an rmeta and an rlib file and rustc will prefer the rmeta +// file. +// +// This behavior is simply making sure this doesn't accidentally change; in this +// case we want to make sure that the rlib isn't being used as that would cause +// bugs in -Zbinary-dep-depinfo (see #68298). + +// aux-build:rmeta-rmeta.rs +// aux-build:rmeta-rlib-rpass.rs + +extern crate rmeta_aux; +use rmeta_aux::Foo; + +pub fn main() { + let _ = Foo { field2: 42 }; +} diff --git a/tests/ui/rmeta/rmeta.rs b/tests/ui/rmeta/rmeta.rs new file mode 100644 index 000000000..63ed23650 --- /dev/null +++ b/tests/ui/rmeta/rmeta.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic +// compile-flags: --emit=metadata + +// Check that building a metadata crate finds an error. + +fn main() { + let _ = Foo; //~ ERROR cannot find value `Foo` in this scope +} diff --git a/tests/ui/rmeta/rmeta.stderr b/tests/ui/rmeta/rmeta.stderr new file mode 100644 index 000000000..d15caeb66 --- /dev/null +++ b/tests/ui/rmeta/rmeta.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/rmeta.rs:7:13 + | +LL | let _ = Foo; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/rmeta/rmeta_lib.rs b/tests/ui/rmeta/rmeta_lib.rs new file mode 100644 index 000000000..fa6826450 --- /dev/null +++ b/tests/ui/rmeta/rmeta_lib.rs @@ -0,0 +1,14 @@ +// build-fail +// aux-build:rmeta-meta.rs +// no-prefer-dynamic +// error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found + +// Check that building a non-metadata crate fails if a dependent crate is +// metadata-only. + +extern crate rmeta_meta; +use rmeta_meta::Foo; + +fn main() { + let _ = Foo { field: 42 }; +} diff --git a/tests/ui/rmeta/rmeta_lib.stderr b/tests/ui/rmeta/rmeta_lib.stderr new file mode 100644 index 000000000..8a9179cca --- /dev/null +++ b/tests/ui/rmeta/rmeta_lib.stderr @@ -0,0 +1,4 @@ +error: crate `rmeta_meta` required to be available in rlib format, but was not found in this form + +error: aborting due to previous error + diff --git a/tests/ui/rmeta/rmeta_meta_main.rs b/tests/ui/rmeta/rmeta_meta_main.rs new file mode 100644 index 000000000..839f350d7 --- /dev/null +++ b/tests/ui/rmeta/rmeta_meta_main.rs @@ -0,0 +1,14 @@ +// compile-flags: --emit=metadata +// aux-build:rmeta-meta.rs +// no-prefer-dynamic + +// Check that building a metadata crate finds an error with a dependent, +// metadata-only crate. + + +extern crate rmeta_meta; +use rmeta_meta::Foo; + +fn main() { + let _ = Foo { field2: 42 }; //~ ERROR struct `Foo` has no field named `field2` +} diff --git a/tests/ui/rmeta/rmeta_meta_main.stderr b/tests/ui/rmeta/rmeta_meta_main.stderr new file mode 100644 index 000000000..0c6ed9afd --- /dev/null +++ b/tests/ui/rmeta/rmeta_meta_main.stderr @@ -0,0 +1,9 @@ +error[E0560]: struct `Foo` has no field named `field2` + --> $DIR/rmeta_meta_main.rs:13:19 + | +LL | let _ = Foo { field2: 42 }; + | ^^^^^^ help: a field with a similar name exists: `field` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/runtime/atomic-print.rs b/tests/ui/runtime/atomic-print.rs new file mode 100644 index 000000000..fe5791053 --- /dev/null +++ b/tests/ui/runtime/atomic-print.rs @@ -0,0 +1,45 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(deprecated)] +// ignore-emscripten no threads support +// ignore-sgx no processes + +use std::{env, fmt, process, sync, thread}; + +struct SlowFmt(u32); +impl fmt::Debug for SlowFmt { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + thread::sleep_ms(3); + self.0.fmt(f) + } +} + +fn do_print(x: u32) { + let x = SlowFmt(x); + println!("{:?}{:?}{:?}{:?}{:?}", x, x, x, x, x); +} + +fn main(){ + if env::args().count() == 2 { + let barrier = sync::Arc::new(sync::Barrier::new(2)); + let tbarrier = barrier.clone(); + let t = thread::spawn(move || { + tbarrier.wait(); + do_print(1); + }); + barrier.wait(); + do_print(2); + t.join(); + } else { + let this = env::args().next().unwrap(); + let output = process::Command::new(this).arg("-").output().unwrap(); + for line in String::from_utf8(output.stdout).unwrap().lines() { + match line.chars().next().unwrap() { + '1' => assert_eq!(line, "11111"), + '2' => assert_eq!(line, "22222"), + chr => panic!("unexpected character {:?}", chr) + } + } + } +} diff --git a/tests/ui/runtime/backtrace-debuginfo-aux.rs b/tests/ui/runtime/backtrace-debuginfo-aux.rs new file mode 100644 index 000000000..1411bcf89 --- /dev/null +++ b/tests/ui/runtime/backtrace-debuginfo-aux.rs @@ -0,0 +1,14 @@ +// run-pass +// ignore-test: not a test, used by backtrace-debuginfo.rs to test file!() + +#[inline(never)] +pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { + f((file!(), line!())) +} + +// We emit the wrong location for the caller here when inlined on MSVC +#[cfg_attr(not(target_env = "msvc"), inline(always))] +#[cfg_attr(target_env = "msvc", inline(never))] +pub fn callback_inlined(f: F) where F: FnOnce((&'static str, u32)) { + f((file!(), line!())) +} diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs new file mode 100644 index 000000000..8b5466b6c --- /dev/null +++ b/tests/ui/runtime/backtrace-debuginfo.rs @@ -0,0 +1,190 @@ +// run-pass +// We disable tail merging here because it can't preserve debuginfo and thus +// potentially breaks the backtraces. Also, subtle changes can decide whether +// tail merging succeeds, so the test might work today but fail tomorrow due to a +// seemingly completely unrelated change. +// Unfortunately, LLVM has no "disable" option for this, so we have to set +// "enable" to 0 instead. + +// compile-flags:-g -Copt-level=0 -Cllvm-args=-enable-tail-merge=0 +// compile-flags:-Cforce-frame-pointers=yes +// compile-flags:-Cstrip=none +// ignore-pretty issue #37195 +// ignore-emscripten spawning processes is not supported +// ignore-sgx no processes +// ignore-fuchsia Backtrace not symbolized, trace different line alignment + +use std::env; + +#[path = "backtrace-debuginfo-aux.rs"] mod aux; + +macro_rules! pos { + () => ((file!(), line!())) +} + +macro_rules! dump_and_die { + ($($pos:expr),*) => ({ + // FIXME(#18285): we cannot include the current position because + // the macro span takes over the last frame's file/line. + // + // You might also be wondering why a major platform, + // i686-pc-windows-msvc, is located in here. Some of the saga can be + // found on #62897, but the tl;dr; is that it appears that if the + // standard library doesn't have debug information or frame pointers, + // which it doesn't by default on the test builders, then the stack + // walking routines in dbghelp will randomly terminate the stack trace + // in libstd without going further. Presumably the addition of frame + // pointers and/or debuginfo fixes this since tests always work with + // nightly compilers (which have debuginfo). In general though this test + // is replicated in rust-lang/backtrace-rs and has extensive coverage + // there, even on i686-pc-windows-msvc. We do the best we can in + // rust-lang/rust to test it as well, but sometimes we just gotta keep + // landing PRs. + if cfg!(any(target_os = "android", + all(target_os = "linux", target_arch = "arm"), + all(target_env = "msvc", target_arch = "x86"), + target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd")) { + // skip these platforms as this support isn't implemented yet. + } else { + dump_filelines(&[$($pos),*]); + panic!(); + } + }) +} + +// we can't use a function as it will alter the backtrace +macro_rules! check { + ($counter:expr; $($pos:expr),*) => ({ + if *$counter == 0 { + dump_and_die!($($pos),*) + } else { + *$counter -= 1; + } + }) +} + +type Pos = (&'static str, u32); + +// this goes to stdout and each line has to be occurred +// in the following backtrace to stderr with a correct order. +fn dump_filelines(filelines: &[Pos]) { + for &(file, line) in filelines.iter().rev() { + // extract a basename + let basename = file.split(&['/', '\\'][..]).last().unwrap(); + println!("{}:{}", basename, line); + } +} + +#[inline(never)] +fn inner(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { + check!(counter; main_pos, outer_pos); + check!(counter; main_pos, outer_pos); + let inner_pos = pos!(); aux::callback(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); aux::callback_inlined(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); +} + +// We emit the wrong location for the caller here when inlined on MSVC +#[cfg_attr(not(target_env = "msvc"), inline(always))] +#[cfg_attr(target_env = "msvc", inline(never))] +fn inner_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos) { + check!(counter; main_pos, outer_pos); + check!(counter; main_pos, outer_pos); + + // Again, disable inlining for MSVC. + #[cfg_attr(not(target_env = "msvc"), inline(always))] + #[cfg_attr(target_env = "msvc", inline(never))] + fn inner_further_inlined(counter: &mut i32, main_pos: Pos, outer_pos: Pos, inner_pos: Pos) { + check!(counter; main_pos, outer_pos, inner_pos); + } + inner_further_inlined(counter, main_pos, outer_pos, pos!()); + + let inner_pos = pos!(); aux::callback(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); + let inner_pos = pos!(); aux::callback_inlined(|aux_pos| { + check!(counter; main_pos, outer_pos, inner_pos, aux_pos); + }); + + // this tests a distinction between two independent calls to the inlined function. + // (un)fortunately, LLVM somehow merges two consecutive such calls into one node. + inner_further_inlined(counter, main_pos, outer_pos, pos!()); +} + +#[inline(never)] +fn outer(mut counter: i32, main_pos: Pos) { + inner(&mut counter, main_pos, pos!()); + inner_inlined(&mut counter, main_pos, pos!()); +} + +fn check_trace(output: &str, error: &str) -> Result<(), String> { + // reverse the position list so we can start with the last item (which was the first line) + let mut remaining: Vec<&str> = output.lines().map(|s| s.trim()).rev().collect(); + + if !error.contains("stack backtrace") { + return Err(format!("no backtrace found in stderr:\n{}", error)) + } + for line in error.lines() { + if !remaining.is_empty() && line.contains(remaining.last().unwrap()) { + remaining.pop(); + } + } + if !remaining.is_empty() { + return Err(format!("trace does not match position list\n\ + still need to find {:?}\n\n\ + --- stdout\n{}\n\ + --- stderr\n{}", + remaining, output, error)) + } + Ok(()) +} + +fn run_test(me: &str) { + use std::str; + use std::process::Command; + + let mut i = 0; + let mut errors = Vec::new(); + loop { + let out = Command::new(me) + .env("RUST_BACKTRACE", "full") + .arg(i.to_string()).output().unwrap(); + let output = str::from_utf8(&out.stdout).unwrap(); + let error = str::from_utf8(&out.stderr).unwrap(); + if out.status.success() { + assert!(output.contains("done."), "bad output for successful run: {}", output); + break; + } else { + if let Err(e) = check_trace(output, error) { + errors.push(e); + } + } + i += 1; + } + if errors.len() > 0 { + for error in errors { + println!("---------------------------------------"); + println!("{}", error); + } + + panic!("found some errors"); + } +} + +#[inline(never)] +fn main() { + let args: Vec = env::args().collect(); + if args.len() >= 2 { + let case = args[1].parse().unwrap(); + eprintln!("test case {}", case); + outer(case, pos!()); + println!("done."); + } else { + run_test(&args[0]); + } +} diff --git a/tests/ui/runtime/native-print-no-runtime.rs b/tests/ui/runtime/native-print-no-runtime.rs new file mode 100644 index 000000000..f17c9fa6c --- /dev/null +++ b/tests/ui/runtime/native-print-no-runtime.rs @@ -0,0 +1,9 @@ +// run-pass + +#![feature(start)] + +#[start] +pub fn main(_: isize, _: *const *const u8) -> isize { + println!("hello"); + 0 +} diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs new file mode 100644 index 000000000..6873abc49 --- /dev/null +++ b/tests/ui/runtime/out-of-stack.rs @@ -0,0 +1,88 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(unconditional_recursion)] +// ignore-android: FIXME (#20004) +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590) + +#![feature(core_intrinsics)] +#![feature(rustc_private)] + +#[cfg(unix)] +extern crate libc; + +use std::env; +use std::process::Command; +use std::thread; + +// Inlining to avoid llvm turning the recursive functions into tail calls, +// which doesn't consume stack. +#[inline(always)] +pub fn black_box(dummy: T) { std::intrinsics::black_box(dummy); } + +fn silent_recurse() { + let buf = [0u8; 1000]; + black_box(buf); + silent_recurse(); +} + +fn loud_recurse() { + println!("hello!"); + loud_recurse(); + black_box(()); // don't optimize this into a tail call. please. +} + +#[cfg(unix)] +fn check_status(status: std::process::ExitStatus) +{ + use std::os::unix::process::ExitStatusExt; + + assert!(!status.success()); + assert_eq!(status.signal(), Some(libc::SIGABRT)); +} + +#[cfg(not(unix))] +fn check_status(status: std::process::ExitStatus) +{ + assert!(!status.success()); +} + + +fn main() { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "silent" { + silent_recurse(); + } else if args.len() > 1 && args[1] == "loud" { + loud_recurse(); + } else if args.len() > 1 && args[1] == "silent-thread" { + thread::spawn(silent_recurse).join(); + } else if args.len() > 1 && args[1] == "loud-thread" { + thread::spawn(loud_recurse).join(); + } else { + let mut modes = vec![ + "silent-thread", + "loud-thread", + ]; + + // On linux it looks like the main thread can sometimes grow its stack + // basically without bounds, so we only test the child thread cases + // there. + if !cfg!(target_os = "linux") { + modes.push("silent"); + modes.push("loud"); + } + for mode in modes { + println!("testing: {}", mode); + + let silent = Command::new(&args[0]).arg(mode).output().unwrap(); + + check_status(silent.status); + + let error = String::from_utf8_lossy(&silent.stderr); + assert!(error.contains("has overflowed its stack"), + "missing overflow message: {}", error); + } + } +} diff --git a/tests/ui/runtime/rt-explody-panic-payloads.rs b/tests/ui/runtime/rt-explody-panic-payloads.rs new file mode 100644 index 000000000..755d3df42 --- /dev/null +++ b/tests/ui/runtime/rt-explody-panic-payloads.rs @@ -0,0 +1,33 @@ +// run-pass +// needs-unwind +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::process::Command; + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + std::panic::panic_any(Bomb); + } +} + +fn main() { + let args = env::args().collect::>(); + let output = match &args[..] { + [me] => Command::new(&me).arg("plant the").output(), + [..] => std::panic::panic_any(Bomb), + }.expect("running the command should have succeeded"); + println!("{:#?}", output); + let stderr = std::str::from_utf8(&output.stderr); + assert!(stderr + .map(|v| { + // When running inside QEMU user-mode emulation, there will be an extra message printed + // by QEMU in the stderr whenever a core dump happens. Remove it before the check. + v.strip_suffix("qemu: uncaught target signal 6 (Aborted) - core dumped\n").unwrap_or(v) + }) + .map(|v| { v.ends_with("fatal runtime error: drop of the panic payload panicked\n") }) + .unwrap_or(false)); +} diff --git a/tests/ui/runtime/running-with-no-runtime.rs b/tests/ui/runtime/running-with-no-runtime.rs new file mode 100644 index 000000000..c575a6bec --- /dev/null +++ b/tests/ui/runtime/running-with-no-runtime.rs @@ -0,0 +1,52 @@ +// run-pass +// ignore-emscripten spawning processes is not supported +// ignore-sgx no processes +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![feature(start)] + +use std::ffi::CStr; +use std::process::{Command, Output}; +use std::panic; +use std::str; + +#[start] +fn start(argc: isize, argv: *const *const u8) -> isize { + if argc > 1 { + unsafe { + match **argv.offset(1) as char { + '1' => {} + '2' => println!("foo"), + '3' => assert!(panic::catch_unwind(|| {}).is_ok()), + '4' => assert!(panic::catch_unwind(|| panic!()).is_err()), + '5' => assert!(Command::new("test").spawn().is_err()), + _ => panic!() + } + } + return 0 + } + + let args = unsafe { + (0..argc as usize).map(|i| { + let ptr = *argv.add(i) as *const _; + CStr::from_ptr(ptr).to_bytes().to_vec() + }).collect::>() + }; + let me = String::from_utf8(args[0].to_vec()).unwrap(); + + pass(Command::new(&me).arg("1").output().unwrap()); + pass(Command::new(&me).arg("2").output().unwrap()); + pass(Command::new(&me).arg("3").output().unwrap()); + pass(Command::new(&me).arg("4").output().unwrap()); + pass(Command::new(&me).arg("5").output().unwrap()); + + 0 +} + +fn pass(output: Output) { + if !output.status.success() { + println!("{:?}", str::from_utf8(&output.stdout)); + println!("{:?}", str::from_utf8(&output.stderr)); + } +} diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs new file mode 100644 index 000000000..8a6d73895 --- /dev/null +++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs @@ -0,0 +1,37 @@ +// run-pass +// Previously memory for alternate signal stack have been unmapped during +// main thread exit while still being in use by signal handlers. This test +// triggers this situation by sending signal from atexit handler. +// +// ignore-wasm32-bare no libc +// ignore-windows +// ignore-sgx no libc +// ignore-vxworks no SIGWINCH in user space + +#![feature(rustc_private)] +extern crate libc; + +use libc::*; + +unsafe extern "C" fn signal_handler(signum: c_int, _: *mut siginfo_t, _: *mut c_void) { + assert_eq!(signum, SIGWINCH); +} + +extern "C" fn send_signal() { + unsafe { + raise(SIGWINCH); + } +} + +fn main() { + unsafe { + // Install signal handler that runs on alternate signal stack. + let mut action: sigaction = std::mem::zeroed(); + action.sa_flags = (SA_ONSTACK | SA_SIGINFO) as _; + action.sa_sigaction = signal_handler as sighandler_t; + sigaction(SIGWINCH, &action, std::ptr::null_mut()); + + // Send SIGWINCH on exit. + atexit(send_signal); + } +} diff --git a/tests/ui/runtime/stdout-during-shutdown.rs b/tests/ui/runtime/stdout-during-shutdown.rs new file mode 100644 index 000000000..a6cf812ca --- /dev/null +++ b/tests/ui/runtime/stdout-during-shutdown.rs @@ -0,0 +1,19 @@ +// run-pass +// check-run-results +// ignore-emscripten + +// Emscripten doesn't flush its own stdout buffers on exit, which would fail +// this test. So this test is disabled on this platform. +// See https://emscripten.org/docs/getting_started/FAQ.html#what-does-exiting-the-runtime-mean-why-don-t-atexit-s-run + +#![feature(rustc_private)] + +extern crate libc; + +fn main() { + extern "C" fn bye() { + print!(", world!"); + } + unsafe { libc::atexit(bye) }; + print!("hello"); +} diff --git a/tests/ui/runtime/stdout-during-shutdown.run.stdout b/tests/ui/runtime/stdout-during-shutdown.run.stdout new file mode 100644 index 000000000..30f51a3fb --- /dev/null +++ b/tests/ui/runtime/stdout-during-shutdown.run.stdout @@ -0,0 +1 @@ +hello, world! \ No newline at end of file diff --git a/tests/ui/rust-2018/async-ident-allowed.rs b/tests/ui/rust-2018/async-ident-allowed.rs new file mode 100644 index 000000000..8efcfbb70 --- /dev/null +++ b/tests/ui/rust-2018/async-ident-allowed.rs @@ -0,0 +1,11 @@ +// edition:2015 + +#![deny(rust_2018_compatibility)] + +// Don't make a suggestion for a raw identifier replacement unless raw +// identifiers are enabled. + +fn main() { + let async = 3; //~ ERROR: is a keyword + //~^ WARN this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/async-ident-allowed.stderr b/tests/ui/rust-2018/async-ident-allowed.stderr new file mode 100644 index 000000000..992b29750 --- /dev/null +++ b/tests/ui/rust-2018/async-ident-allowed.stderr @@ -0,0 +1,17 @@ +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident-allowed.rs:9:9 + | +LL | let async = 3; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/async-ident-allowed.rs:3:9 + | +LL | #![deny(rust_2018_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]` + +error: aborting due to previous error + diff --git a/tests/ui/rust-2018/async-ident.fixed b/tests/ui/rust-2018/async-ident.fixed new file mode 100644 index 000000000..e909c7907 --- /dev/null +++ b/tests/ui/rust-2018/async-ident.fixed @@ -0,0 +1,79 @@ +#![allow(dead_code, unused_variables, unused_macro_rules, bad_style)] +#![deny(keyword_idents)] + +// edition:2015 +// run-rustfix + +fn r#async() {} //~ ERROR async +//~^ WARN this is accepted in the current edition + +macro_rules! foo { + ($foo:ident) => {}; + ($r#async:expr, r#async) => {}; + //~^ ERROR async + //~| ERROR async + //~| WARN this is accepted in the current edition + //~| WARN this is accepted in the current edition +} + +foo!(r#async); + //~^ ERROR async + //~| WARN this is accepted in the current edition + +mod dont_lint_raw { + fn r#async() {} +} + +mod async_trait { + trait r#async {} + //~^ ERROR async + //~| WARN this is accepted in the current edition + struct MyStruct; + impl r#async for MyStruct {} + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +mod async_static { + static r#async: u32 = 0; + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +mod async_const { + const r#async: u32 = 0; + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +struct Foo; +impl Foo { fn r#async() {} } + //~^ ERROR async + //~| WARN this is accepted in the current edition + +fn main() { + struct r#async {} + //~^ ERROR async + //~| WARN this is accepted in the current edition + let r#async: r#async = r#async {}; + //~^ ERROR async + //~| WARN this is accepted in the current edition + //~| ERROR async + //~| WARN this is accepted in the current edition + //~| ERROR async + //~| WARN this is accepted in the current edition +} + +#[macro_export] +macro_rules! produces_async { + () => (pub fn r#async() {}) + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +#[macro_export] +macro_rules! consumes_async { + (r#async) => (1) + //~^ ERROR async + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/async-ident.rs b/tests/ui/rust-2018/async-ident.rs new file mode 100644 index 000000000..2bfbc3871 --- /dev/null +++ b/tests/ui/rust-2018/async-ident.rs @@ -0,0 +1,79 @@ +#![allow(dead_code, unused_variables, unused_macro_rules, bad_style)] +#![deny(keyword_idents)] + +// edition:2015 +// run-rustfix + +fn async() {} //~ ERROR async +//~^ WARN this is accepted in the current edition + +macro_rules! foo { + ($foo:ident) => {}; + ($async:expr, async) => {}; + //~^ ERROR async + //~| ERROR async + //~| WARN this is accepted in the current edition + //~| WARN this is accepted in the current edition +} + +foo!(async); + //~^ ERROR async + //~| WARN this is accepted in the current edition + +mod dont_lint_raw { + fn r#async() {} +} + +mod async_trait { + trait async {} + //~^ ERROR async + //~| WARN this is accepted in the current edition + struct MyStruct; + impl async for MyStruct {} + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +mod async_static { + static async: u32 = 0; + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +mod async_const { + const async: u32 = 0; + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +struct Foo; +impl Foo { fn async() {} } + //~^ ERROR async + //~| WARN this is accepted in the current edition + +fn main() { + struct async {} + //~^ ERROR async + //~| WARN this is accepted in the current edition + let async: async = async {}; + //~^ ERROR async + //~| WARN this is accepted in the current edition + //~| ERROR async + //~| WARN this is accepted in the current edition + //~| ERROR async + //~| WARN this is accepted in the current edition +} + +#[macro_export] +macro_rules! produces_async { + () => (pub fn async() {}) + //~^ ERROR async + //~| WARN this is accepted in the current edition +} + +#[macro_export] +macro_rules! consumes_async { + (async) => (1) + //~^ ERROR async + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/async-ident.stderr b/tests/ui/rust-2018/async-ident.stderr new file mode 100644 index 000000000..d15250c54 --- /dev/null +++ b/tests/ui/rust-2018/async-ident.stderr @@ -0,0 +1,142 @@ +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:7:4 + | +LL | fn async() {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/async-ident.rs:2:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:12:7 + | +LL | ($async:expr, async) => {}; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:12:19 + | +LL | ($async:expr, async) => {}; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:19:6 + | +LL | foo!(async); + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:28:11 + | +LL | trait async {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:32:10 + | +LL | impl async for MyStruct {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:38:12 + | +LL | static async: u32 = 0; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:44:11 + | +LL | const async: u32 = 0; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:50:15 + | +LL | impl Foo { fn async() {} } + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:55:12 + | +LL | struct async {} + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:58:9 + | +LL | let async: async = async {}; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:58:16 + | +LL | let async: async = async {}; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:58:24 + | +LL | let async: async = async {}; + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:69:19 + | +LL | () => (pub fn async() {}) + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: `async` is a keyword in the 2018 edition + --> $DIR/async-ident.rs:76:6 + | +LL | (async) => (1) + | ^^^^^ help: you can use a raw identifier to stay compatible: `r#async` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +error: aborting due to 15 previous errors + diff --git a/tests/ui/rust-2018/auxiliary/baz.rs b/tests/ui/rust-2018/auxiliary/baz.rs new file mode 100644 index 000000000..b317c8a45 --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/baz.rs @@ -0,0 +1,5 @@ +// This file is used as part of the local-path-suggestions.rs test. + +pub mod foobar { + pub struct Baz; +} diff --git a/tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs new file mode 100644 index 000000000..d45fa10f0 --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs @@ -0,0 +1,6 @@ +pub fn foo() {} + +#[macro_export] +macro_rules! gimme_a { + ($($mac:tt)*) => { $($mac)* { 'a } } +} diff --git a/tests/ui/rust-2018/auxiliary/edition-lint-paths.rs b/tests/ui/rust-2018/auxiliary/edition-lint-paths.rs new file mode 100644 index 000000000..dd22df89e --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/edition-lint-paths.rs @@ -0,0 +1,12 @@ +pub fn foo() {} + +#[macro_export] +macro_rules! macro_2015 { + () => { + use edition_lint_paths as other_name; + use edition_lint_paths::foo as other_foo; + fn check_macro_2015() { + ::edition_lint_paths::foo(); + } + } +} diff --git a/tests/ui/rust-2018/auxiliary/macro-use-warned-against.rs b/tests/ui/rust-2018/auxiliary/macro-use-warned-against.rs new file mode 100644 index 000000000..b497c74e6 --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/macro-use-warned-against.rs @@ -0,0 +1,2 @@ +#[macro_export] +macro_rules! foo { () => () } diff --git a/tests/ui/rust-2018/auxiliary/macro-use-warned-against2.rs b/tests/ui/rust-2018/auxiliary/macro-use-warned-against2.rs new file mode 100644 index 000000000..d11c69f81 --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/macro-use-warned-against2.rs @@ -0,0 +1 @@ +// intentionally empty diff --git a/tests/ui/rust-2018/auxiliary/remove-extern-crate.rs b/tests/ui/rust-2018/auxiliary/remove-extern-crate.rs new file mode 100644 index 000000000..890af683a --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/remove-extern-crate.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! foo { + () => () +} + +#[macro_export] +macro_rules! bar { + () => () +} diff --git a/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs new file mode 100644 index 000000000..7472443dc --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs @@ -0,0 +1,13 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn foo(_attr: TokenStream, _f: TokenStream) -> TokenStream { + "pub fn foo() -> ::Foo { ::Foo }".parse().unwrap() +} diff --git a/tests/ui/rust-2018/auxiliary/trait-import-suggestions.rs b/tests/ui/rust-2018/auxiliary/trait-import-suggestions.rs new file mode 100644 index 000000000..d356f3294 --- /dev/null +++ b/tests/ui/rust-2018/auxiliary/trait-import-suggestions.rs @@ -0,0 +1,5 @@ +pub trait Baz { + fn baz(&self) { } +} + +impl Baz for u32 { } diff --git a/tests/ui/rust-2018/dyn-keyword.fixed b/tests/ui/rust-2018/dyn-keyword.fixed new file mode 100644 index 000000000..044824cbb --- /dev/null +++ b/tests/ui/rust-2018/dyn-keyword.fixed @@ -0,0 +1,10 @@ +// edition:2015 +// run-rustfix + +#![allow(unused_variables)] +#![deny(keyword_idents)] + +fn main() { + let r#dyn = (); //~ ERROR dyn + //~^ WARN this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/dyn-keyword.rs b/tests/ui/rust-2018/dyn-keyword.rs new file mode 100644 index 000000000..5989cfa1c --- /dev/null +++ b/tests/ui/rust-2018/dyn-keyword.rs @@ -0,0 +1,10 @@ +// edition:2015 +// run-rustfix + +#![allow(unused_variables)] +#![deny(keyword_idents)] + +fn main() { + let dyn = (); //~ ERROR dyn + //~^ WARN this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/dyn-keyword.stderr b/tests/ui/rust-2018/dyn-keyword.stderr new file mode 100644 index 000000000..b6f5b10cf --- /dev/null +++ b/tests/ui/rust-2018/dyn-keyword.stderr @@ -0,0 +1,16 @@ +error: `dyn` is a keyword in the 2018 edition + --> $DIR/dyn-keyword.rs:8:9 + | +LL | let dyn = (); + | ^^^ help: you can use a raw identifier to stay compatible: `r#dyn` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/dyn-keyword.rs:5:9 + | +LL | #![deny(keyword_idents)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rust-2018/dyn-trait-compatibility.rs b/tests/ui/rust-2018/dyn-trait-compatibility.rs new file mode 100644 index 000000000..377c85fef --- /dev/null +++ b/tests/ui/rust-2018/dyn-trait-compatibility.rs @@ -0,0 +1,8 @@ +// edition:2018 + +type A0 = dyn; +type A1 = dyn::dyn; //~ERROR expected identifier, found keyword `dyn` +type A2 = dyn; //~ERROR expected identifier, found `<` +type A3 = dyn<::dyn>; + +fn main() {} diff --git a/tests/ui/rust-2018/dyn-trait-compatibility.stderr b/tests/ui/rust-2018/dyn-trait-compatibility.stderr new file mode 100644 index 000000000..cf4d6c19c --- /dev/null +++ b/tests/ui/rust-2018/dyn-trait-compatibility.stderr @@ -0,0 +1,19 @@ +error: expected identifier, found keyword `dyn` + --> $DIR/dyn-trait-compatibility.rs:4:16 + | +LL | type A1 = dyn::dyn; + | ^^^ expected identifier, found keyword + | +help: escape `dyn` to use it as an identifier + | +LL | type A1 = dyn::r#dyn; + | ++ + +error: expected identifier, found `<` + --> $DIR/dyn-trait-compatibility.rs:5:14 + | +LL | type A2 = dyn; + | ^ expected identifier + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed new file mode 100644 index 000000000..85d106bc1 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed @@ -0,0 +1,26 @@ +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +mod foo { + pub(crate) trait Foo { + type Bar; + } + + pub(crate) struct Baz {} + + impl Foo for Baz { + type Bar = (); + } +} + +fn main() { + let _: ::Bar = (); + //~^ ERROR absolute paths must start with + //~| this is accepted in the current edition + + let _: ::Bar = (); + //~^ ERROR absolute paths must start with + //~| this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs new file mode 100644 index 000000000..9ff3c2e5f --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs @@ -0,0 +1,26 @@ +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +mod foo { + pub(crate) trait Foo { + type Bar; + } + + pub(crate) struct Baz {} + + impl Foo for Baz { + type Bar = (); + } +} + +fn main() { + let _: ::Bar = (); + //~^ ERROR absolute paths must start with + //~| this is accepted in the current edition + + let _: <::foo::Baz as foo::Foo>::Bar = (); + //~^ ERROR absolute paths must start with + //~| this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr new file mode 100644 index 000000000..e1709db09 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr @@ -0,0 +1,25 @@ +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-fully-qualified-paths.rs:19:25 + | +LL | let _: ::Bar = (); + | ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 +note: the lint level is defined here + --> $DIR/edition-lint-fully-qualified-paths.rs:4:9 + | +LL | #![deny(absolute_paths_not_starting_with_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-fully-qualified-paths.rs:23:13 + | +LL | let _: <::foo::Baz as foo::Foo>::Bar = (); + | ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed new file mode 100644 index 000000000..8cdb08e81 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed @@ -0,0 +1,137 @@ +// edition:2018 +// aux-build:edition-lint-infer-outlives-macro.rs +// run-rustfix + +#![deny(explicit_outlives_requirements)] +#![allow(dead_code)] + +#[macro_use] +extern crate edition_lint_infer_outlives_macro; + +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. +macro_rules! make_foo { + ($a:tt) => { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { + foo: &$a &'b (), + } + } +} + +gimme_a! {make_foo!} + +struct Bar<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +struct BarWhere<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs new file mode 100644 index 000000000..647906c2d --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs @@ -0,0 +1,137 @@ +// edition:2018 +// aux-build:edition-lint-infer-outlives-macro.rs +// run-rustfix + +#![deny(explicit_outlives_requirements)] +#![allow(dead_code)] + +#[macro_use] +extern crate edition_lint_infer_outlives_macro; + +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. +macro_rules! make_foo { + ($a:tt) => { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { + foo: &$a &'b (), + } + } +} + +gimme_a! {make_foo!} + +struct Bar<'a, 'b: 'a> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +struct BarWhere<'a, 'b> where 'b: 'a { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b: 'a>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b: 'a>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr new file mode 100644 index 000000000..734ae6879 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr @@ -0,0 +1,110 @@ +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:27:18 + | +LL | struct Bar<'a, 'b: 'a> { + | ^^^^ help: remove this bound + | +note: the lint level is defined here + --> $DIR/edition-lint-infer-outlives-macro.rs:5:9 + | +LL | #![deny(explicit_outlives_requirements)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:32:24 + | +LL | struct BarWhere<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:41:30 + | +LL | struct Foo<'a, 'b: 'a>(&'a &'b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:43:44 + | +LL | struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:45:61 + | +LL | struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:55:30 + | +LL | struct Foo<'a, $b: 'a>(&'a &$b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:57:44 + | +LL | struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:59:61 + | +LL | struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:114:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:126:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:128:50 + | +LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:130:61 + | +LL | struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: aborting due to 12 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs new file mode 100644 index 000000000..0b3de0df2 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs @@ -0,0 +1,368 @@ +#![allow(unused)] +#![deny(explicit_outlives_requirements)] + + +// These examples should live in edition-lint-infer-outlives.rs, but are split +// into this separate file because they can't be `rustfix`'d (and thus, can't +// be part of a `run-rustfix` test file) until rust-lang-nursery/rustfix#141 +// is solved + +mod structs { + use std::fmt::Debug; + + struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> + where U: 'a + Debug + 'b, 'b: 'a + //~^ ERROR outlives requirements can be inferred + { + tee: T, + yoo: &'a &'b U + } +} + +mod tuple_structs { + use std::fmt::Debug; + + struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T>(&'a &'b T) where T: 'a + Debug + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug>(&'a T, &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b>(&'a T, &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + Debug + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b + Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: Debug + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereAyYooWhereBeeIsDebug<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: 'b + Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereAyYooWhereIsDebugBee<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: Debug + 'b; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereAyTeeWhereAyIsDebugBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'a + Debug + 'b; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereAyTeeYooWhereAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U) + where U: 'a + Debug + 'b, 'b: 'a; + //~^ ERROR outlives requirements can be inferred +} + +mod enums { + use std::fmt::Debug; + + enum TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, }, + W(&'a &'b U), + } + + enum TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T, yoo: &'b U }, + W, + } + + enum TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + V(&'a T, &'b U), + W, + } + + enum TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W(&'b U), + } + + enum TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a T, &'b U), + W, + } + + enum TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W(&'b U) + } + + enum TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T, yoo: &'b U }, + W, + } + + enum TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a T, &'b U), + W, + } + + enum BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W, + } + + enum BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a &'b U), + } + + enum BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + } +} + +mod unions { + use std::fmt::Debug; + + union TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: &'b U + } + + union BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } +} + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr new file mode 100644 index 000000000..251d74094 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr @@ -0,0 +1,823 @@ +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:13:47 + | +LL | struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { + | ^^^^^ ^^^^^ + | +note: the lint level is defined here + --> $DIR/edition-lint-infer-outlives-multispan.rs:2:9 + | +LL | #![deny(explicit_outlives_requirements)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove these bounds + | +LL - struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { +LL + struct TeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:18:61 + | +LL | struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { +LL + struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:23:53 + | +LL | struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { +LL + struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:29:48 + | +LL | struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { +LL + struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:35:48 + | +LL | struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { +LL + struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:41:46 + | +LL | struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { + | ^^^^ ^^^^^^^^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { +LL + struct TeeOutlivesAyYooWhereBee<'a, 'b, T, U> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:47:67 + | +LL | struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { +LL + struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:53:53 + | +LL | struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { +LL + struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:59:53 + | +LL | struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { +LL + struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:65:69 + | +LL | struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { +LL + struct TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:71:69 + | +LL | struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { +LL + struct TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:77:38 + | +LL | struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { + | ^^^^ ^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { +LL + struct BeeOutlivesAyTeeBee<'a, 'b, T> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:82:40 + | +LL | struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { + | ^^^^ ^^^^^^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { +LL + struct BeeOutlivesAyTeeAyBee<'a, 'b, T> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:87:55 + | +LL | struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { +LL + struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:92:68 + | +LL | struct BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { + | ^^^^^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { +LL + struct BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:97:58 + | +LL | struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { +LL + struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:104:18 + | +LL | where U: 'a + Debug + 'b, 'b: 'a + | ^^^^^ ^^^^^ ^^^^^^ + | +help: remove these bounds + | +LL - where U: 'a + Debug + 'b, 'b: 'a +LL + where U: Debug, + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:115:47 + | +LL | struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b>(&'a &'b T); + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b>(&'a &'b T); +LL + struct TeeOutlivesAyIsDebugBee<'a, 'b, T: Debug>(&'a &'b T); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:118:72 + | +LL | struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T>(&'a &'b T) where T: 'a + Debug + 'b; + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T>(&'a &'b T) where T: 'a + Debug + 'b; +LL + struct TeeWhereOutlivesAyIsDebugBee<'a, 'b, T>(&'a &'b T) where T: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:121:53 + | +LL | struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b>(T, &'a &'b U); + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b>(T, &'a &'b U); +LL + struct TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug>(T, &'a &'b U); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:124:48 + | +LL | struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug>(&'a T, &'b U); + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug>(&'a T, &'b U); +LL + struct TeeOutlivesAyYooBeeIsDebug<'a, 'b, T, U: Debug>(&'a T, &'b U); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:127:48 + | +LL | struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b>(&'a T, &'b U); + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b>(&'a T, &'b U); +LL + struct TeeOutlivesAyYooIsDebugBee<'a, 'b, T, U: Debug>(&'a T, &'b U); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:130:46 + | +LL | struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b; + | ^^^^ ^^^^^^^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b; +LL + struct TeeOutlivesAyYooWhereBee<'a, 'b, T, U>(&'a T, &'b U) ; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:133:81 + | +LL | struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + Debug + 'b; + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + Debug + 'b; +LL + struct TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U>(T, &'a &'b U) where U: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:136:53 + | +LL | struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b + Debug; + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: 'b + Debug; +LL + struct TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U>(&'a T, &'b U) where U: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:139:53 + | +LL | struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: Debug + 'b; + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U>(&'a T, &'b U) where U: Debug + 'b; +LL + struct TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U>(&'a T, &'b U) where U: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:142:75 + | +LL | struct TeeWhereAyYooWhereBeeIsDebug<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: 'b + Debug; + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeWhereAyYooWhereBeeIsDebug<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: 'b + Debug; +LL + struct TeeWhereAyYooWhereBeeIsDebug<'a, 'b, T, U>(&'a T, &'b U) where U: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:145:75 + | +LL | struct TeeWhereAyYooWhereIsDebugBee<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: Debug + 'b; + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct TeeWhereAyYooWhereIsDebugBee<'a, 'b, T, U>(&'a T, &'b U) where T: 'a, U: Debug + 'b; +LL + struct TeeWhereAyYooWhereIsDebugBee<'a, 'b, T, U>(&'a T, &'b U) where U: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:148:38 + | +LL | struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b>(&'a &'b T); + | ^^^^ ^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b>(&'a &'b T); +LL + struct BeeOutlivesAyTeeBee<'a, 'b, T>(&'a &'b T); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:151:40 + | +LL | struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b>(&'a &'b T); + | ^^^^ ^^^^^^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b>(&'a &'b T); +LL + struct BeeOutlivesAyTeeAyBee<'a, 'b, T>(&'a &'b T); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:154:55 + | +LL | struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b>(&'a &'b T); + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b>(&'a &'b T); +LL + struct BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b, T: Debug>(&'a &'b T); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:157:71 + | +LL | struct BeeWhereAyTeeWhereAyIsDebugBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'a + Debug + 'b; + | ^^^^^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct BeeWhereAyTeeWhereAyIsDebugBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'a + Debug + 'b; +LL + struct BeeWhereAyTeeWhereAyIsDebugBee<'a, 'b, T>(&'a &'b T) where T: Debug; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:160:58 + | +LL | struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b>(T, &'a &'b U); + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b>(T, &'a &'b U); +LL + struct BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug>(T, &'a &'b U); + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:164:18 + | +LL | where U: 'a + Debug + 'b, 'b: 'a; + | ^^^^^ ^^^^^ ^^^^^^ + | +help: remove these bounds + | +LL - where U: 'a + Debug + 'b, 'b: 'a; +LL + where U: Debug, ; + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:171:45 + | +LL | enum TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { +LL + enum TeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:176:59 + | +LL | enum TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { +LL + enum TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:181:51 + | +LL | enum TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { +LL + enum TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:187:46 + | +LL | enum TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { +LL + enum TeeOutlivesAyYooBeeIsDebug<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:193:46 + | +LL | enum TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { +LL + enum TeeOutlivesAyYooIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:199:44 + | +LL | enum TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { + | ^^^^ ^^^^^^^^^^^^ + | +help: remove these bounds + | +LL - enum TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { +LL + enum TeeOutlivesAyYooWhereBee<'a, 'b, T, U> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:205:65 + | +LL | enum TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { +LL + enum TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:211:51 + | +LL | enum TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { +LL + enum TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:217:51 + | +LL | enum TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { +LL + enum TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:223:67 + | +LL | enum TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { +LL + enum TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:229:67 + | +LL | enum TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { +LL + enum TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:235:36 + | +LL | enum BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { + | ^^^^ ^^^^ + | +help: remove these bounds + | +LL - enum BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { +LL + enum BeeOutlivesAyTeeBee<'a, 'b, T> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:240:38 + | +LL | enum BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { + | ^^^^ ^^^^^^^^^ + | +help: remove these bounds + | +LL - enum BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { +LL + enum BeeOutlivesAyTeeAyBee<'a, 'b, T> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:246:53 + | +LL | enum BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { +LL + enum BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:251:66 + | +LL | enum BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { + | ^^^^^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { +LL + enum BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:256:56 + | +LL | enum BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - enum BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { +LL + enum BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:262:75 + | +LL | enum BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a { + | ^^^^^ ^^^^^ ^^^^^^ + | +help: remove these bounds + | +LL - enum BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a { +LL + enum BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug, { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:271:46 + | +LL | union TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeOutlivesAyIsDebugBee<'a, 'b, T: 'a + Debug + 'b> { +LL + union TeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:276:60 + | +LL | union TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: 'a + Debug + 'b { +LL + union TeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:281:52 + | +LL | union TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: 'a + Debug + 'b> { +LL + union TeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:287:47 + | +LL | union TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeOutlivesAyYooBeeIsDebug<'a, 'b, T: 'a, U: 'b + Debug> { +LL + union TeeOutlivesAyYooBeeIsDebug<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:293:47 + | +LL | union TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeOutlivesAyYooIsDebugBee<'a, 'b, T: 'a, U: Debug + 'b> { +LL + union TeeOutlivesAyYooIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:299:45 + | +LL | union TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { + | ^^^^ ^^^^^^^^^^^^ + | +help: remove these bounds + | +LL - union TeeOutlivesAyYooWhereBee<'a, 'b, T: 'a, U> where U: 'b { +LL + union TeeOutlivesAyYooWhereBee<'a, 'b, T, U> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:305:66 + | +LL | union TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { + | ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b { +LL + union TeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:311:52 + | +LL | union TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T: 'a, U> where U: 'b + Debug { +LL + union TeeOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:317:52 + | +LL | union TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { + | ^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T: 'a, U> where U: Debug + 'b { +LL + union TeeOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:323:68 + | +LL | union TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where T: 'a, U: 'b + Debug { +LL + union TeeWhereOutlivesAyYooWhereBeeIsDebug<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:329:68 + | +LL | union TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { + | ^^^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where T: 'a, U: Debug + 'b { +LL + union TeeWhereOutlivesAyYooWhereIsDebugBee<'a, 'b, T, U> where U: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:335:37 + | +LL | union BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { + | ^^^^ ^^^^ + | +help: remove these bounds + | +LL - union BeeOutlivesAyTeeBee<'a, 'b: 'a, T: 'b> { +LL + union BeeOutlivesAyTeeBee<'a, 'b, T> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:340:39 + | +LL | union BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { + | ^^^^ ^^^^^^^^^ + | +help: remove these bounds + | +LL - union BeeOutlivesAyTeeAyBee<'a, 'b: 'a, T: 'a + 'b> { +LL + union BeeOutlivesAyTeeAyBee<'a, 'b, T> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:345:54 + | +LL | union BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b: 'a, T: 'a + Debug + 'b> { +LL + union BeeOutlivesAyTeeOutlivesAyIsDebugBee<'a, 'b, T: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:350:67 + | +LL | union BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { + | ^^^^^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where 'b: 'a, T: 'a + Debug + 'b { +LL + union BeeWhereAyTeeWhereOutlivesAyIsDebugBee<'a, 'b, T> where T: Debug { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:355:57 + | +LL | union BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { + | ^^^^ ^^^^^ ^^^^^ + | +help: remove these bounds + | +LL - union BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b: 'a, T, U: 'a + Debug + 'b> { +LL + union BeeOutlivesAyTeeYooOutlivesAyIsDebugBee<'a, 'b, T, U: Debug> { + | + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-multispan.rs:361:76 + | +LL | union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a { + | ^^^^^ ^^^^^ ^^^^^^ + | +help: remove these bounds + | +LL - union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: 'a + Debug + 'b, 'b: 'a { +LL + union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug, { + | + +error: aborting due to 68 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed b/tests/ui/rust-2018/edition-lint-infer-outlives.fixed new file mode 100644 index 000000000..13645244d --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives.fixed @@ -0,0 +1,795 @@ +// run-rustfix + +#![allow(unused)] +#![deny(explicit_outlives_requirements)] + +// Programmatically generated examples! +// +// Exercise outlives bounds for each of the following parameter/position +// combinations— +// +// • one generic parameter (T) bound inline +// • one parameter (T) with a where clause +// • two parameters (T and U), both bound inline +// • two parameters (T and U), one bound inline, one with a where clause +// • two parameters (T and U), both with where clauses +// +// —and for every permutation of 1 or 2 lifetimes to outlive and 0 or 1 trait +// bounds distributed among said parameters (subject to no where clause being +// empty and the struct having at least one lifetime). +// +// —and for each of tuple structs, enums and unions. + +mod structs { + use std::fmt::Debug; + + struct TeeOutlivesAy<'a, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeOutlivesAyIsDebug<'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeIsDebugOutlivesAy<'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeOutlivesAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereOutlivesAy<'a, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeWhereOutlivesAyIsDebug<'a, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeWhereOutlivesAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeYooOutlivesAy<'a, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooOutlivesAyIsDebug<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeOutlivesAyYooIsDebug<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: U + } + + struct TeeYooOutlivesAyBee<'a, 'b, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: U + } + + struct TeeYooWhereOutlivesAy<'a, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: U + } + + struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: U + } + + struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: U + } + + struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: U + } + + struct BeeOutlivesAy<'a, 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + struct BeeWhereOutlivesAy<'a, 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + struct BeeOutlivesAyTee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeOutlivesAyTeeDebug<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } +} + +mod tuple_structs { + use std::fmt::Debug; + + struct TeeOutlivesAy<'a, T>(&'a T); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyIsDebug<'a, T: Debug>(&'a T); + //~^ ERROR outlives requirements can be inferred + + struct TeeIsDebugOutlivesAy<'a, T: Debug>(&'a T); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBee<'a, 'b, T>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: Debug>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAy<'a, T>(&'a T) ; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyIsDebug<'a, T>(&'a T) where T: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereIsDebugOutlivesAy<'a, T>(&'a T) where T: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyBee<'a, 'b, T>(&'a &'b T) ; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T>(&'a &'b T) where T: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T>(&'a &'b T) where T: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAy<'a, T, U>(T, &'a U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyIsDebug<'a, T, U: Debug>(T, &'a U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug>(T, &'a U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooIsDebug<'a, T, U: Debug>(&'a T, U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: Debug>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T, U: Debug>(&'a &'b T, U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAy<'a, T, U>(T, &'a U) ; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyIsDebug<'a, T, U>(T, &'a U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereIsDebugOutlivesAy<'a, T, U>(T, &'a U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooWhereIsDebug<'a, T, U>(&'a T, U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U) ; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U>(T, &'a &'b U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U>(&'a &'b T, U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U>(&'a T, U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereAyBeeYooWhereIsDebug<'a, 'b, T, U>(&'a &'b T, U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAy<'a, 'b>(&'a &'b ()); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAy<'a, 'b>(&'a &'b ()) ; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTee<'a, 'b, T>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTee<'a, 'b, T>(&'a &'b T) ; + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T>(&'a &'b T) ; + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T>(&'a &'b T) ; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTeeDebug<'a, 'b, T: Debug>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T>(&'a &'b T) where T: Debug; + //~^ ERROR outlives requirements can be inferred +} + +mod enums { + use std::fmt::Debug; + + enum TeeOutlivesAy<'a, T> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + } + + enum TeeOutlivesAyIsDebug<'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + V(&'a T), + } + + enum TeeIsDebugOutlivesAy<'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W, + } + + enum TeeOutlivesAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum TeeOutlivesAyBeeIsDebug<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum TeeWhereOutlivesAy<'a, T> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W, + } + + enum TeeWhereOutlivesAyIsDebug<'a, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a T), + W, + } + + enum TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + } + + enum TeeWhereOutlivesAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W, + } + + enum TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum TeeYooOutlivesAy<'a, T, U> { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a U), + } + + enum TeeYooOutlivesAyIsDebug<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a U }, + W, + } + + enum TeeYooIsDebugOutlivesAy<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V(T, &'a U), + W, + } + + enum TeeOutlivesAyYooIsDebug<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W(U), + } + + enum TeeYooOutlivesAyBee<'a, 'b, T, U> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V(T, &'a &'b U), + W, + } + + enum TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeOutlivesAyBeeYooIsDebug<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T, U), + W, + } + + enum TeeYooWhereOutlivesAy<'a, T, U> { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a U), + } + + enum TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a U }, + W, + } + + enum TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V(T, &'a U), + W, + } + + enum TeeOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W(U), + } + + enum TeeYooWhereOutlivesAyBee<'a, 'b, T, U> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V(T, &'a &'b U), + W, + } + + enum TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a &'b U), + } + + enum TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T, yoo: U }, + W, + } + + enum TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a T, U), + W, + } + + enum TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W(U), + } + + enum BeeOutlivesAy<'a, 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b () }, + } + + enum BeeWhereOutlivesAy<'a, 'b> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b ()), + } + + enum BeeOutlivesAyTee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W, + } + + enum BeeWhereOutlivesAyTee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum BeeOutlivesAyTeeDebug<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } +} + +mod unions { + use std::fmt::Debug; + + union TeeOutlivesAy<'a, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeOutlivesAyIsDebug<'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeIsDebugOutlivesAy<'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeOutlivesAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeOutlivesAyBeeIsDebug<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereOutlivesAy<'a, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeWhereOutlivesAyIsDebug<'a, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeWhereOutlivesAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeYooOutlivesAy<'a, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooOutlivesAyIsDebug<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooIsDebugOutlivesAy<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeOutlivesAyYooIsDebug<'a, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: *const U + } + + union TeeYooOutlivesAyBee<'a, 'b, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeOutlivesAyBeeYooIsDebug<'a, 'b, T, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: *const U + } + + union TeeYooWhereOutlivesAy<'a, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: *const U + } + + union TeeYooWhereOutlivesAyBee<'a, 'b, T, U> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: *const U + } + + union TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: *const U + } + + union TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: *const U + } + + union BeeOutlivesAy<'a, 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + union BeeWhereOutlivesAy<'a, 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + union BeeOutlivesAyTee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeOutlivesAyTeeDebug<'a, 'b, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } +} + + +// But outlives inference for 'static lifetimes is under a separate +// feature-gate for now +// (https://github.com/rust-lang/rust/issues/44493#issuecomment-407846046). +struct StaticRef { + field: &'static T +} + + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.rs b/tests/ui/rust-2018/edition-lint-infer-outlives.rs new file mode 100644 index 000000000..d9486ba66 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives.rs @@ -0,0 +1,795 @@ +// run-rustfix + +#![allow(unused)] +#![deny(explicit_outlives_requirements)] + +// Programmatically generated examples! +// +// Exercise outlives bounds for each of the following parameter/position +// combinations— +// +// • one generic parameter (T) bound inline +// • one parameter (T) with a where clause +// • two parameters (T and U), both bound inline +// • two parameters (T and U), one bound inline, one with a where clause +// • two parameters (T and U), both with where clauses +// +// —and for every permutation of 1 or 2 lifetimes to outlive and 0 or 1 trait +// bounds distributed among said parameters (subject to no where clause being +// empty and the struct having at least one lifetime). +// +// —and for each of tuple structs, enums and unions. + +mod structs { + use std::fmt::Debug; + + struct TeeOutlivesAy<'a, T: 'a> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereOutlivesAy<'a, T> where T: 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + struct TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + struct TeeYooOutlivesAy<'a, T, U: 'a> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: U + } + + struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: U + } + + struct TeeYooWhereOutlivesAy<'a, T, U> where U: 'a { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a U + } + + struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: U + } + + struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: T, + yoo: &'a &'b U + } + + struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: U + } + + struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: U + } + + struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: U + } + + struct BeeOutlivesAy<'a, 'b: 'a> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + struct BeeWhereOutlivesAy<'a, 'b> where 'b: 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + struct BeeOutlivesAyTee<'a, 'b: 'a, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTee<'a, 'b, T> where 'b: 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> where 'b: 'a, T: 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> where 'b: 'a, T: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + struct BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } +} + +mod tuple_structs { + use std::fmt::Debug; + + struct TeeOutlivesAy<'a, T: 'a>(&'a T); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug>(&'a T); + //~^ ERROR outlives requirements can be inferred + + struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a>(&'a T); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAy<'a, T>(&'a T) where T: 'a; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyIsDebug<'a, T>(&'a T) where T: 'a + Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereIsDebugOutlivesAy<'a, T>(&'a T) where T: Debug + 'a; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyBee<'a, 'b, T>(&'a &'b T) where T: 'a + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T>(&'a &'b T) where T: 'a + 'b + Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T>(&'a &'b T) where T: Debug + 'a + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAy<'a, T, U: 'a>(T, &'a U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug>(T, &'a U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a>(T, &'a U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug>(&'a T, U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b>(T, &'a &'b U); + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug>(&'a &'b T, U); + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAy<'a, T, U>(T, &'a U) where U: 'a; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyIsDebug<'a, T, U>(T, &'a U) where U: 'a + Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereIsDebugOutlivesAy<'a, T, U>(T, &'a U) where U: Debug + 'a; + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U>(&'a T, U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + 'b + Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U) where U: Debug + 'a + 'b; + //~^ ERROR outlives requirements can be inferred + + struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U>(&'a &'b T, U) where U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U>(&'a T, U) where T: 'a, U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct TeeWhereAyBeeYooWhereIsDebug<'a, 'b, T, U>(&'a &'b T, U) where T: 'a + 'b, U: Debug; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAy<'a, 'b: 'a>(&'a &'b ()); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAy<'a, 'b>(&'a &'b ()) where 'b: 'a; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTee<'a, 'b: 'a, T>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTee<'a, 'b, T>(&'a &'b T) where 'b: 'a; + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'b; + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'a + 'b; + //~^ ERROR outlives requirements can be inferred + + struct BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug>(&'a &'b T); + //~^ ERROR outlives requirements can be inferred + + struct BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: Debug; + //~^ ERROR outlives requirements can be inferred +} + +mod enums { + use std::fmt::Debug; + + enum TeeOutlivesAy<'a, T: 'a> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + } + + enum TeeOutlivesAyIsDebug<'a, T: 'a + Debug> { + //~^ ERROR outlives requirements can be inferred + V(&'a T), + } + + enum TeeIsDebugOutlivesAy<'a, T: Debug + 'a> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W, + } + + enum TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum TeeWhereOutlivesAy<'a, T> where T: 'a { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W, + } + + enum TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a T), + W, + } + + enum TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + } + + enum TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W, + } + + enum TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum TeeYooOutlivesAy<'a, T, U: 'a> { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a U), + } + + enum TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a U }, + W, + } + + enum TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> { + //~^ ERROR outlives requirements can be inferred + V(T, &'a U), + W, + } + + enum TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W(U), + } + + enum TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + V(T, &'a &'b U), + W, + } + + enum TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T, U), + W, + } + + enum TeeYooWhereOutlivesAy<'a, T, U> where U: 'a { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a U), + } + + enum TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a U }, + W, + } + + enum TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a { + //~^ ERROR outlives requirements can be inferred + V(T, &'a U), + W, + } + + enum TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a T }, + W(U), + } + + enum TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + V { tee: T, yoo: &'a &'b U }, + W, + } + + enum TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug { + //~^ ERROR outlives requirements can be inferred + V(T, &'a &'b U), + W, + } + + enum TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b { + //~^ ERROR outlives requirements can be inferred + V { tee: T }, + W(&'a &'b U), + } + + enum TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T, yoo: U }, + W, + } + + enum TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a T, U), + W, + } + + enum TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W(U), + } + + enum BeeOutlivesAy<'a, 'b: 'a> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b () }, + } + + enum BeeWhereOutlivesAy<'a, 'b> where 'b: 'a { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b ()), + } + + enum BeeOutlivesAyTee<'a, 'b: 'a, T> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + W, + } + + enum BeeWhereOutlivesAyTee<'a, 'b, T> where 'b: 'a { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> where 'b: 'a, T: 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } + + enum BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> where 'b: 'a, T: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + W, + } + + enum BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + V { tee: &'a &'b T }, + } + + enum BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug { + //~^ ERROR outlives requirements can be inferred + V(&'a &'b T), + } +} + +mod unions { + use std::fmt::Debug; + + union TeeOutlivesAy<'a, T: 'a> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeOutlivesAyIsDebug<'a, T: 'a + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeIsDebugOutlivesAy<'a, T: Debug + 'a> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereOutlivesAy<'a, T> where T: 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a T + } + + union TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T + } + + union TeeYooOutlivesAy<'a, T, U: 'a> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: *const U + } + + union TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: *const U + } + + union TeeYooWhereOutlivesAy<'a, T, U> where U: 'a { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a U + } + + union TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: *const U + } + + union TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: *const T, + yoo: &'a &'b U + } + + union TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: *const U + } + + union TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a T, + yoo: *const U + } + + union TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + yoo: *const U + } + + union BeeOutlivesAy<'a, 'b: 'a> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + union BeeWhereOutlivesAy<'a, 'b> where 'b: 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b (), + } + + union BeeOutlivesAyTee<'a, 'b: 'a, T> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTee<'a, 'b, T> where 'b: 'a { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> where 'b: 'a, T: 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> where 'b: 'a, T: 'a + 'b { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug> { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } + + union BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug { + //~^ ERROR outlives requirements can be inferred + tee: &'a &'b T, + } +} + + +// But outlives inference for 'static lifetimes is under a separate +// feature-gate for now +// (https://github.com/rust-lang/rust/issues/44493#issuecomment-407846046). +struct StaticRef { + field: &'static T +} + + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives.stderr new file mode 100644 index 000000000..faa9f21e3 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-infer-outlives.stderr @@ -0,0 +1,920 @@ +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:26:31 + | +LL | struct TeeOutlivesAy<'a, T: 'a> { + | ^^^^ help: remove this bound + | +note: the lint level is defined here + --> $DIR/edition-lint-infer-outlives.rs:4:9 + | +LL | #![deny(explicit_outlives_requirements)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:31:40 + | +LL | struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:36:45 + | +LL | struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:41:38 + | +LL | struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:46:47 + | +LL | struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:51:52 + | +LL | struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:56:37 + | +LL | struct TeeWhereOutlivesAy<'a, T> where T: 'a { + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:61:54 + | +LL | struct TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:66:59 + | +LL | struct TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:71:44 + | +LL | struct TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b { + | ^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:76:61 + | +LL | struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:81:66 + | +LL | struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:86:37 + | +LL | struct TeeYooOutlivesAy<'a, T, U: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:92:46 + | +LL | struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:98:51 + | +LL | struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:104:41 + | +LL | struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:110:44 + | +LL | struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:116:53 + | +LL | struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:122:58 + | +LL | struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:128:48 + | +LL | struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:134:43 + | +LL | struct TeeYooWhereOutlivesAy<'a, T, U> where U: 'a { + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:140:60 + | +LL | struct TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:146:65 + | +LL | struct TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:152:46 + | +LL | struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:158:50 + | +LL | struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b { + | ^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:164:67 + | +LL | struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:170:72 + | +LL | struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:176:53 + | +LL | struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:182:62 + | +LL | struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug { + | ^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:188:69 + | +LL | struct TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug { + | ^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:194:32 + | +LL | struct BeeOutlivesAy<'a, 'b: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:199:38 + | +LL | struct BeeWhereOutlivesAy<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:204:35 + | +LL | struct BeeOutlivesAyTee<'a, 'b: 'a, T> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:209:44 + | +LL | struct BeeWhereOutlivesAyTee<'a, 'b, T> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:214:52 + | +LL | struct BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> where 'b: 'a, T: 'b { + | ^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:219:54 + | +LL | struct BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> where 'b: 'a, T: 'a + 'b { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:224:40 + | +LL | struct BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:229:61 + | +LL | struct BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug { + | ^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:238:31 + | +LL | struct TeeOutlivesAy<'a, T: 'a>(&'a T); + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:241:40 + | +LL | struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug>(&'a T); + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:244:45 + | +LL | struct TeeIsDebugOutlivesAy<'a, T: Debug + 'a>(&'a T); + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:247:38 + | +LL | struct TeeOutlivesAyBee<'a, 'b, T: 'a + 'b>(&'a &'b T); + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:250:47 + | +LL | struct TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug>(&'a &'b T); + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:253:52 + | +LL | struct TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b>(&'a &'b T); + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:256:45 + | +LL | struct TeeWhereOutlivesAy<'a, T>(&'a T) where T: 'a; + | ^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:259:61 + | +LL | struct TeeWhereOutlivesAyIsDebug<'a, T>(&'a T) where T: 'a + Debug; + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:262:66 + | +LL | struct TeeWhereIsDebugOutlivesAy<'a, T>(&'a T) where T: Debug + 'a; + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:265:56 + | +LL | struct TeeWhereOutlivesAyBee<'a, 'b, T>(&'a &'b T) where T: 'a + 'b; + | ^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:268:72 + | +LL | struct TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T>(&'a &'b T) where T: 'a + 'b + Debug; + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:271:77 + | +LL | struct TeeWhereIsDebugOutlivesAyBee<'a, 'b, T>(&'a &'b T) where T: Debug + 'a + 'b; + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:274:37 + | +LL | struct TeeYooOutlivesAy<'a, T, U: 'a>(T, &'a U); + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:277:46 + | +LL | struct TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug>(T, &'a U); + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:280:51 + | +LL | struct TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a>(T, &'a U); + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:283:41 + | +LL | struct TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug>(&'a T, U); + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:286:44 + | +LL | struct TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b>(T, &'a &'b U); + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:289:53 + | +LL | struct TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug>(T, &'a &'b U); + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:292:58 + | +LL | struct TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b>(T, &'a &'b U); + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:295:48 + | +LL | struct TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug>(&'a &'b T, U); + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:298:54 + | +LL | struct TeeYooWhereOutlivesAy<'a, T, U>(T, &'a U) where U: 'a; + | ^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:301:70 + | +LL | struct TeeYooWhereOutlivesAyIsDebug<'a, T, U>(T, &'a U) where U: 'a + Debug; + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:304:75 + | +LL | struct TeeYooWhereIsDebugOutlivesAy<'a, T, U>(T, &'a U) where U: Debug + 'a; + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:307:46 + | +LL | struct TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U>(&'a T, U) where U: Debug; + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:310:65 + | +LL | struct TeeYooWhereOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + 'b; + | ^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:313:81 + | +LL | struct TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U>(T, &'a &'b U) where U: 'a + 'b + Debug; + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:316:86 + | +LL | struct TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U>(T, &'a &'b U) where U: Debug + 'a + 'b; + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:319:53 + | +LL | struct TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U>(&'a &'b T, U) where U: Debug; + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:322:72 + | +LL | struct TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U>(&'a T, U) where T: 'a, U: Debug; + | ^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:325:75 + | +LL | struct TeeWhereAyBeeYooWhereIsDebug<'a, 'b, T, U>(&'a &'b T, U) where T: 'a + 'b, U: Debug; + | ^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:328:32 + | +LL | struct BeeOutlivesAy<'a, 'b: 'a>(&'a &'b ()); + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:331:51 + | +LL | struct BeeWhereOutlivesAy<'a, 'b>(&'a &'b ()) where 'b: 'a; + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:334:35 + | +LL | struct BeeOutlivesAyTee<'a, 'b: 'a, T>(&'a &'b T); + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:337:56 + | +LL | struct BeeWhereOutlivesAyTee<'a, 'b, T>(&'a &'b T) where 'b: 'a; + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:340:64 + | +LL | struct BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'b; + | ^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:343:66 + | +LL | struct BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:346:40 + | +LL | struct BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug>(&'a &'b T); + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:349:72 + | +LL | struct BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T>(&'a &'b T) where 'b: 'a, T: Debug; + | ^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:356:29 + | +LL | enum TeeOutlivesAy<'a, T: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:361:38 + | +LL | enum TeeOutlivesAyIsDebug<'a, T: 'a + Debug> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:366:43 + | +LL | enum TeeIsDebugOutlivesAy<'a, T: Debug + 'a> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:372:36 + | +LL | enum TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:378:45 + | +LL | enum TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:383:50 + | +LL | enum TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:388:35 + | +LL | enum TeeWhereOutlivesAy<'a, T> where T: 'a { + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:394:52 + | +LL | enum TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:400:57 + | +LL | enum TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:405:42 + | +LL | enum TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b { + | ^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:410:59 + | +LL | enum TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:416:64 + | +LL | enum TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:422:35 + | +LL | enum TeeYooOutlivesAy<'a, T, U: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:428:44 + | +LL | enum TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:434:49 + | +LL | enum TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:440:39 + | +LL | enum TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:446:42 + | +LL | enum TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:452:51 + | +LL | enum TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:458:56 + | +LL | enum TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:464:46 + | +LL | enum TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:470:41 + | +LL | enum TeeYooWhereOutlivesAy<'a, T, U> where U: 'a { + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:476:58 + | +LL | enum TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:482:63 + | +LL | enum TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:488:44 + | +LL | enum TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:494:48 + | +LL | enum TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b { + | ^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:500:65 + | +LL | enum TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:506:70 + | +LL | enum TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:512:51 + | +LL | enum TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:518:60 + | +LL | enum TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug { + | ^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:524:67 + | +LL | enum TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug { + | ^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:530:30 + | +LL | enum BeeOutlivesAy<'a, 'b: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:535:36 + | +LL | enum BeeWhereOutlivesAy<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:540:33 + | +LL | enum BeeOutlivesAyTee<'a, 'b: 'a, T> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:546:42 + | +LL | enum BeeWhereOutlivesAyTee<'a, 'b, T> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:552:50 + | +LL | enum BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> where 'b: 'a, T: 'b { + | ^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:557:52 + | +LL | enum BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> where 'b: 'a, T: 'a + 'b { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:563:38 + | +LL | enum BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:568:59 + | +LL | enum BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug { + | ^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:577:30 + | +LL | union TeeOutlivesAy<'a, T: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:582:39 + | +LL | union TeeOutlivesAyIsDebug<'a, T: 'a + Debug> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:587:44 + | +LL | union TeeIsDebugOutlivesAy<'a, T: Debug + 'a> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:592:37 + | +LL | union TeeOutlivesAyBee<'a, 'b, T: 'a + 'b> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:597:46 + | +LL | union TeeOutlivesAyBeeIsDebug<'a, 'b, T: 'a + 'b + Debug> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:602:51 + | +LL | union TeeIsDebugOutlivesAyBee<'a, 'b, T: Debug + 'a + 'b> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:607:36 + | +LL | union TeeWhereOutlivesAy<'a, T> where T: 'a { + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:612:53 + | +LL | union TeeWhereOutlivesAyIsDebug<'a, T> where T: 'a + Debug { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:617:58 + | +LL | union TeeWhereIsDebugOutlivesAy<'a, T> where T: Debug + 'a { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:622:43 + | +LL | union TeeWhereOutlivesAyBee<'a, 'b, T> where T: 'a + 'b { + | ^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:627:60 + | +LL | union TeeWhereOutlivesAyBeeIsDebug<'a, 'b, T> where T: 'a + 'b + Debug { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:632:65 + | +LL | union TeeWhereIsDebugOutlivesAyBee<'a, 'b, T> where T: Debug + 'a + 'b { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:637:36 + | +LL | union TeeYooOutlivesAy<'a, T, U: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:643:45 + | +LL | union TeeYooOutlivesAyIsDebug<'a, T, U: 'a + Debug> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:649:50 + | +LL | union TeeYooIsDebugOutlivesAy<'a, T, U: Debug + 'a> { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:655:40 + | +LL | union TeeOutlivesAyYooIsDebug<'a, T: 'a, U: Debug> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:661:43 + | +LL | union TeeYooOutlivesAyBee<'a, 'b, T, U: 'a + 'b> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:667:52 + | +LL | union TeeYooOutlivesAyBeeIsDebug<'a, 'b, T, U: 'a + 'b + Debug> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:673:57 + | +LL | union TeeYooIsDebugOutlivesAyBee<'a, 'b, T, U: Debug + 'a + 'b> { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:679:47 + | +LL | union TeeOutlivesAyBeeYooIsDebug<'a, 'b, T: 'a + 'b, U: Debug> { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:685:42 + | +LL | union TeeYooWhereOutlivesAy<'a, T, U> where U: 'a { + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:691:59 + | +LL | union TeeYooWhereOutlivesAyIsDebug<'a, T, U> where U: 'a + Debug { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:697:64 + | +LL | union TeeYooWhereIsDebugOutlivesAy<'a, T, U> where U: Debug + 'a { + | ^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:703:45 + | +LL | union TeeOutlivesAyYooWhereIsDebug<'a, T: 'a, U> where U: Debug { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:709:49 + | +LL | union TeeYooWhereOutlivesAyBee<'a, 'b, T, U> where U: 'a + 'b { + | ^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:715:66 + | +LL | union TeeYooWhereOutlivesAyBeeIsDebug<'a, 'b, T, U> where U: 'a + 'b + Debug { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:721:71 + | +LL | union TeeYooWhereIsDebugOutlivesAyBee<'a, 'b, T, U> where U: Debug + 'a + 'b { + | ^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:727:52 + | +LL | union TeeOutlivesAyBeeYooWhereIsDebug<'a, 'b, T: 'a + 'b, U> where U: Debug { + | ^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:733:61 + | +LL | union TeeWhereOutlivesAyYooWhereIsDebug<'a, T, U> where T: 'a, U: Debug { + | ^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:739:68 + | +LL | union TeeWhereOutlivesAyBeeYooWhereIsDebug<'a, 'b, T, U> where T: 'a + 'b, U: Debug { + | ^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:745:31 + | +LL | union BeeOutlivesAy<'a, 'b: 'a> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:750:37 + | +LL | union BeeWhereOutlivesAy<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:755:34 + | +LL | union BeeOutlivesAyTee<'a, 'b: 'a, T> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:760:43 + | +LL | union BeeWhereOutlivesAyTee<'a, 'b, T> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:765:51 + | +LL | union BeeWhereOutlivesAyTeeWhereBee<'a, 'b, T> where 'b: 'a, T: 'b { + | ^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:770:53 + | +LL | union BeeWhereOutlivesAyTeeWhereAyBee<'a, 'b, T> where 'b: 'a, T: 'a + 'b { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these bounds + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:775:39 + | +LL | union BeeOutlivesAyTeeDebug<'a, 'b: 'a, T: Debug> { + | ^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives.rs:780:60 + | +LL | union BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug { + | ^^^^^^^^ help: remove this bound + +error: aborting due to 152 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed b/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed new file mode 100644 index 000000000..f25d46ce3 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed @@ -0,0 +1,34 @@ +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] +#![allow(unused_imports)] +#![allow(dead_code)] + +pub(crate) mod foo { + pub(crate) mod bar { + pub(crate) mod baz { } + pub(crate) mod baz1 { } + + pub(crate) struct XX; + } +} + +use crate::foo::{bar::{baz::{}}}; +//~^ ERROR absolute paths must start with +//~| WARN this is accepted in the current edition + +use crate::foo::{bar::{XX, baz::{}}}; +//~^ ERROR absolute paths must start with +//~| WARN this is accepted in the current edition +//~| ERROR absolute paths must start with +//~| WARN this is accepted in the current edition + +use crate::foo::{bar::{baz::{}, baz1::{}}}; +//~^ ERROR absolute paths must start with +//~| WARN this is accepted in the current edition +//~| ERROR absolute paths must start with +//~| WARN this is accepted in the current edition + +fn main() { +} diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs b/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs new file mode 100644 index 000000000..9be1680c1 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] +#![allow(unused_imports)] +#![allow(dead_code)] + +pub(crate) mod foo { + pub(crate) mod bar { + pub(crate) mod baz { } + pub(crate) mod baz1 { } + + pub(crate) struct XX; + } +} + +use foo::{bar::{baz::{}}}; +//~^ ERROR absolute paths must start with +//~| WARN this is accepted in the current edition + +use foo::{bar::{XX, baz::{}}}; +//~^ ERROR absolute paths must start with +//~| WARN this is accepted in the current edition +//~| ERROR absolute paths must start with +//~| WARN this is accepted in the current edition + +use foo::{bar::{baz::{}, baz1::{}}}; +//~^ ERROR absolute paths must start with +//~| WARN this is accepted in the current edition +//~| ERROR absolute paths must start with +//~| WARN this is accepted in the current edition + +fn main() { +} diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr new file mode 100644 index 000000000..8769cbb35 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr @@ -0,0 +1,52 @@ +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-empty-paths.rs:17:5 + | +LL | use foo::{bar::{baz::{}}}; + | ^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}}}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 +note: the lint level is defined here + --> $DIR/edition-lint-nested-empty-paths.rs:4:9 + | +LL | #![deny(absolute_paths_not_starting_with_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-empty-paths.rs:21:5 + | +LL | use foo::{bar::{XX, baz::{}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-empty-paths.rs:21:5 + | +LL | use foo::{bar::{XX, baz::{}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-empty-paths.rs:27:5 + | +LL | use foo::{bar::{baz::{}, baz1::{}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-empty-paths.rs:27:5 + | +LL | use foo::{bar::{baz::{}, baz1::{}}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.fixed b/tests/ui/rust-2018/edition-lint-nested-paths.fixed new file mode 100644 index 000000000..a04937ae8 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-nested-paths.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +use crate::foo::{a, b}; +//~^ ERROR absolute paths must start with +//~| this is accepted in the current edition +//~| ERROR absolute paths must start with +//~| this is accepted in the current edition + +mod foo { + pub(crate) fn a() {} + pub(crate) fn b() {} + pub(crate) fn c() {} +} + +fn main() { + a(); + b(); + + { + use crate::foo::{self as x, c}; + //~^ ERROR absolute paths must start with + //~| this is accepted in the current edition + //~| ERROR absolute paths must start with + //~| this is accepted in the current edition + x::a(); + c(); + } +} diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.rs b/tests/ui/rust-2018/edition-lint-nested-paths.rs new file mode 100644 index 000000000..e622a8e24 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-nested-paths.rs @@ -0,0 +1,31 @@ +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +use foo::{a, b}; +//~^ ERROR absolute paths must start with +//~| this is accepted in the current edition +//~| ERROR absolute paths must start with +//~| this is accepted in the current edition + +mod foo { + pub(crate) fn a() {} + pub(crate) fn b() {} + pub(crate) fn c() {} +} + +fn main() { + a(); + b(); + + { + use foo::{self as x, c}; + //~^ ERROR absolute paths must start with + //~| this is accepted in the current edition + //~| ERROR absolute paths must start with + //~| this is accepted in the current edition + x::a(); + c(); + } +} diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-paths.stderr new file mode 100644 index 000000000..354a6fe32 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-nested-paths.stderr @@ -0,0 +1,43 @@ +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-paths.rs:6:5 + | +LL | use foo::{a, b}; + | ^^^^^^^^^^^ help: use `crate`: `crate::foo::{a, b}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 +note: the lint level is defined here + --> $DIR/edition-lint-nested-paths.rs:4:9 + | +LL | #![deny(absolute_paths_not_starting_with_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-paths.rs:6:5 + | +LL | use foo::{a, b}; + | ^^^^^^^^^^^ help: use `crate`: `crate::foo::{a, b}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-paths.rs:23:13 + | +LL | use foo::{self as x, c}; + | ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-nested-paths.rs:23:13 + | +LL | use foo::{self as x, c}; + | ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: aborting due to 4 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-paths-2018.rs b/tests/ui/rust-2018/edition-lint-paths-2018.rs new file mode 100644 index 000000000..2005d8f4d --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-paths-2018.rs @@ -0,0 +1,10 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 +// compile-flags:--extern edition_lint_paths +// aux-build:edition-lint-paths.rs + +#![deny(absolute_paths_not_starting_with_crate)] + +edition_lint_paths::macro_2015!(); // OK + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-paths.fixed b/tests/ui/rust-2018/edition-lint-paths.fixed new file mode 100644 index 000000000..47f82c51d --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-paths.fixed @@ -0,0 +1,77 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] +#![allow(unused)] + +extern crate edition_lint_paths; + +pub mod foo { + use edition_lint_paths; + use crate::bar::Bar; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + + use super::bar::Bar2; + use crate::bar::Bar3; + + use crate::bar; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + + use crate::bar as something_else; + + use crate::{main, Bar as SomethingElse}; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + //~| ERROR absolute + //~| WARN this is accepted in the current edition + //~| ERROR absolute + //~| WARN this is accepted in the current edition + + use crate::{main as another_main, Bar as SomethingElse2}; + + pub fn test() {} + + pub trait SomeTrait {} +} + +use crate::bar::Bar; +//~^ ERROR absolute +//~| WARN this is accepted in the current edition + +pub mod bar { + use edition_lint_paths as foo; + pub struct Bar; + pub type Bar2 = Bar; + pub type Bar3 = Bar; +} + +mod baz { + use crate::*; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition +} + +impl crate::foo::SomeTrait for u32 {} +//~^ ERROR absolute +//~| WARN this is accepted in the current edition + +fn main() { + let x = crate::bar::Bar; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + + let x = bar::Bar; + let x = crate::bar::Bar; + let x = self::bar::Bar; + foo::test(); + + { + use edition_lint_paths as bar; + edition_lint_paths::foo(); + bar::foo(); + ::edition_lint_paths::foo(); + } +} diff --git a/tests/ui/rust-2018/edition-lint-paths.rs b/tests/ui/rust-2018/edition-lint-paths.rs new file mode 100644 index 000000000..e278983da --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-paths.rs @@ -0,0 +1,77 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] +#![allow(unused)] + +extern crate edition_lint_paths; + +pub mod foo { + use edition_lint_paths; + use bar::Bar; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + + use super::bar::Bar2; + use crate::bar::Bar3; + + use bar; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + + use crate::bar as something_else; + + use {main, Bar as SomethingElse}; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + //~| ERROR absolute + //~| WARN this is accepted in the current edition + //~| ERROR absolute + //~| WARN this is accepted in the current edition + + use crate::{main as another_main, Bar as SomethingElse2}; + + pub fn test() {} + + pub trait SomeTrait {} +} + +use bar::Bar; +//~^ ERROR absolute +//~| WARN this is accepted in the current edition + +pub mod bar { + use edition_lint_paths as foo; + pub struct Bar; + pub type Bar2 = Bar; + pub type Bar3 = Bar; +} + +mod baz { + use *; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition +} + +impl ::foo::SomeTrait for u32 {} +//~^ ERROR absolute +//~| WARN this is accepted in the current edition + +fn main() { + let x = ::bar::Bar; + //~^ ERROR absolute + //~| WARN this is accepted in the current edition + + let x = bar::Bar; + let x = crate::bar::Bar; + let x = self::bar::Bar; + foo::test(); + + { + use edition_lint_paths as bar; + edition_lint_paths::foo(); + bar::foo(); + ::edition_lint_paths::foo(); + } +} diff --git a/tests/ui/rust-2018/edition-lint-paths.stderr b/tests/ui/rust-2018/edition-lint-paths.stderr new file mode 100644 index 000000000..42652be94 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-paths.stderr @@ -0,0 +1,88 @@ +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:12:9 + | +LL | use bar::Bar; + | ^^^^^^^^ help: use `crate`: `crate::bar::Bar` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 +note: the lint level is defined here + --> $DIR/edition-lint-paths.rs:5:9 + | +LL | #![deny(absolute_paths_not_starting_with_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:19:9 + | +LL | use bar; + | ^^^ help: use `crate`: `crate::bar` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:25:9 + | +LL | use {main, Bar as SomethingElse}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:25:9 + | +LL | use {main, Bar as SomethingElse}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:25:9 + | +LL | use {main, Bar as SomethingElse}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:40:5 + | +LL | use bar::Bar; + | ^^^^^^^^ help: use `crate`: `crate::bar::Bar` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:52:9 + | +LL | use *; + | ^ help: use `crate`: `crate::*` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:57:6 + | +LL | impl ::foo::SomeTrait for u32 {} + | ^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::SomeTrait` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-paths.rs:62:13 + | +LL | let x = ::bar::Bar; + | ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 + +error: aborting due to 9 previous errors + diff --git a/tests/ui/rust-2018/edition-lint-uninferable-outlives.rs b/tests/ui/rust-2018/edition-lint-uninferable-outlives.rs new file mode 100644 index 000000000..950ad1f50 --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-uninferable-outlives.rs @@ -0,0 +1,30 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(unused)] +#![deny(explicit_outlives_requirements)] + +// A case where we can't infer the outlives requirement. Example copied from +// RFC 2093. +// (https://rust-lang.github.io/rfcs/2093-infer-outlives.html +// #where-explicit-annotations-would-still-be-required) + + +trait MakeRef<'a> { + type Type; +} + +impl<'a, T> MakeRef<'a> for Vec + where T: 'a // still required +{ + type Type = &'a T; +} + + +struct Foo<'a, T> + where T: 'a // still required, not inferred from `field` +{ + field: as MakeRef<'a>>::Type +} + + +fn main() {} diff --git a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed new file mode 100644 index 000000000..e51ce5d1d --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed @@ -0,0 +1,28 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--extern edition_lint_paths +// edition:2018 + +// The "normal case". Ideally we would remove the `extern crate` here, +// but we don't. + +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + + +//~^ ERROR unused extern crate + +// Shouldn't suggest changing to `use`, as `bar` +// would no longer be added to the prelude which could cause +// compilation errors for imports that use `bar` in other +// modules. See #57672. +extern crate edition_lint_paths as bar; + +fn main() { + // This is not considered to *use* the `extern crate` in Rust 2018: + use edition_lint_paths::foo; + foo(); + + // But this should be a use of the (renamed) crate: + crate::bar::foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.rs new file mode 100644 index 000000000..debbf085d --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.rs @@ -0,0 +1,28 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--extern edition_lint_paths +// edition:2018 + +// The "normal case". Ideally we would remove the `extern crate` here, +// but we don't. + +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + +extern crate edition_lint_paths; +//~^ ERROR unused extern crate + +// Shouldn't suggest changing to `use`, as `bar` +// would no longer be added to the prelude which could cause +// compilation errors for imports that use `bar` in other +// modules. See #57672. +extern crate edition_lint_paths as bar; + +fn main() { + // This is not considered to *use* the `extern crate` in Rust 2018: + use edition_lint_paths::foo; + foo(); + + // But this should be a use of the (renamed) crate: + crate::bar::foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr new file mode 100644 index 000000000..bb50ec3f5 --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -0,0 +1,15 @@ +error: unused extern crate + --> $DIR/extern-crate-idiomatic-in-2018.rs:12:1 + | +LL | extern crate edition_lint_paths; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/extern-crate-idiomatic-in-2018.rs:9:9 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(unused_extern_crates)]` implied by `#[deny(rust_2018_idioms)]` + +error: aborting due to previous error + diff --git a/tests/ui/rust-2018/extern-crate-idiomatic.fixed b/tests/ui/rust-2018/extern-crate-idiomatic.fixed new file mode 100644 index 000000000..3111b1dab --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-idiomatic.fixed @@ -0,0 +1,18 @@ +// run-pass +// aux-build:edition-lint-paths.rs +// compile-flags:--extern edition_lint_paths +// run-rustfix + +// The "normal case". Ideally we would remove the `extern crate` here, +// but we don't. + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +extern crate edition_lint_paths; + +use edition_lint_paths::foo; + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-idiomatic.rs b/tests/ui/rust-2018/extern-crate-idiomatic.rs new file mode 100644 index 000000000..3111b1dab --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-idiomatic.rs @@ -0,0 +1,18 @@ +// run-pass +// aux-build:edition-lint-paths.rs +// compile-flags:--extern edition_lint_paths +// run-rustfix + +// The "normal case". Ideally we would remove the `extern crate` here, +// but we don't. + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +extern crate edition_lint_paths; + +use edition_lint_paths::foo; + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed new file mode 100644 index 000000000..11b9a67ed --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed @@ -0,0 +1,17 @@ +// run-pass +// aux-build:edition-lint-paths.rs +// run-rustfix + +// Oddball: `edition_lint_paths` is accessed via this `self` path +// rather than being accessed directly. Unless we rewrite that path, +// we can't drop the extern crate. + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +extern crate edition_lint_paths; +use self::edition_lint_paths::foo; + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs new file mode 100644 index 000000000..11b9a67ed --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:edition-lint-paths.rs +// run-rustfix + +// Oddball: `edition_lint_paths` is accessed via this `self` path +// rather than being accessed directly. Unless we rewrite that path, +// we can't drop the extern crate. + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +extern crate edition_lint_paths; +use self::edition_lint_paths::foo; + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-rename.fixed b/tests/ui/rust-2018/extern-crate-rename.fixed new file mode 100644 index 000000000..ea832ef3e --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-rename.fixed @@ -0,0 +1,18 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix + +// Oddball: crate is renamed, making it harder for us to rewrite +// paths. We don't (and we leave the `extern crate` in place). + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +extern crate edition_lint_paths as my_crate; + +use crate::my_crate::foo; +//~^ ERROR absolute paths must start +//~| WARNING this is accepted in the current edition + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-rename.rs b/tests/ui/rust-2018/extern-crate-rename.rs new file mode 100644 index 000000000..b1f617dd8 --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-rename.rs @@ -0,0 +1,18 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix + +// Oddball: crate is renamed, making it harder for us to rewrite +// paths. We don't (and we leave the `extern crate` in place). + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +extern crate edition_lint_paths as my_crate; + +use my_crate::foo; +//~^ ERROR absolute paths must start +//~| WARNING this is accepted in the current edition + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-rename.stderr b/tests/ui/rust-2018/extern-crate-rename.stderr new file mode 100644 index 000000000..eb040f5de --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-rename.stderr @@ -0,0 +1,16 @@ +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/extern-crate-rename.rs:12:5 + | +LL | use my_crate::foo; + | ^^^^^^^^^^^^^ help: use `crate`: `crate::my_crate::foo` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 +note: the lint level is defined here + --> $DIR/extern-crate-rename.rs:8:9 + | +LL | #![deny(absolute_paths_not_starting_with_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rust-2018/extern-crate-submod.fixed b/tests/ui/rust-2018/extern-crate-submod.fixed new file mode 100644 index 000000000..9b0b0dd8e --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-submod.fixed @@ -0,0 +1,25 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix + +// Oddball: extern crate appears in a submodule, making it harder for +// us to rewrite paths. We don't (and we leave the `extern crate` in +// place). + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +mod m { + // Because this extern crate does not appear at the root, we + // ignore it altogether. + pub extern crate edition_lint_paths; +} + +// And we don't being smart about paths like this, even though you +// *could* rewrite it to `use edition_lint_paths::foo` +use crate::m::edition_lint_paths::foo; +//~^ ERROR absolute paths must start +//~| WARNING this is accepted in the current edition + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-submod.rs b/tests/ui/rust-2018/extern-crate-submod.rs new file mode 100644 index 000000000..dfce9128c --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-submod.rs @@ -0,0 +1,25 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix + +// Oddball: extern crate appears in a submodule, making it harder for +// us to rewrite paths. We don't (and we leave the `extern crate` in +// place). + +#![feature(rust_2018_preview)] +#![deny(absolute_paths_not_starting_with_crate)] + +mod m { + // Because this extern crate does not appear at the root, we + // ignore it altogether. + pub extern crate edition_lint_paths; +} + +// And we don't being smart about paths like this, even though you +// *could* rewrite it to `use edition_lint_paths::foo` +use m::edition_lint_paths::foo; +//~^ ERROR absolute paths must start +//~| WARNING this is accepted in the current edition + +fn main() { + foo(); +} diff --git a/tests/ui/rust-2018/extern-crate-submod.stderr b/tests/ui/rust-2018/extern-crate-submod.stderr new file mode 100644 index 000000000..1a9aa7578 --- /dev/null +++ b/tests/ui/rust-2018/extern-crate-submod.stderr @@ -0,0 +1,16 @@ +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/extern-crate-submod.rs:19:5 + | +LL | use m::edition_lint_paths::foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::m::edition_lint_paths::foo` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 +note: the lint level is defined here + --> $DIR/extern-crate-submod.rs:9:9 + | +LL | #![deny(absolute_paths_not_starting_with_crate)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rust-2018/future-proofing-locals.rs b/tests/ui/rust-2018/future-proofing-locals.rs new file mode 100644 index 000000000..2c388cf37 --- /dev/null +++ b/tests/ui/rust-2018/future-proofing-locals.rs @@ -0,0 +1,50 @@ +// edition:2018 + +#![allow(non_camel_case_types)] +#![allow(unused_imports)] + +mod T { + pub struct U; +} +mod x { + pub struct y; +} + +fn type_param() { + use T as _; //~ ERROR imports cannot refer to type parameters + use T::U; //~ ERROR imports cannot refer to type parameters + use T::*; //~ ERROR imports cannot refer to type parameters +} + +fn self_import() { + use T; //~ ERROR imports cannot refer to type parameters +} + +fn let_binding() { + let x = 10; + + use x as _; //~ ERROR imports cannot refer to local variables + use x::y; // OK + use x::*; // OK +} + +fn param_binding(x: u8) { + use x; //~ ERROR imports cannot refer to local variables +} + +fn match_binding() { + match 0 { + x => { + use x; //~ ERROR imports cannot refer to local variables + } + } +} + +fn nested() { + let x = 10; + + use {T as _, x}; //~ ERROR imports cannot refer to type parameters + //~| ERROR imports cannot refer to local variables +} + +fn main() {} diff --git a/tests/ui/rust-2018/future-proofing-locals.stderr b/tests/ui/rust-2018/future-proofing-locals.stderr new file mode 100644 index 000000000..7021489a6 --- /dev/null +++ b/tests/ui/rust-2018/future-proofing-locals.stderr @@ -0,0 +1,56 @@ +error: imports cannot refer to type parameters + --> $DIR/future-proofing-locals.rs:14:9 + | +LL | use T as _; + | ^ + +error: imports cannot refer to type parameters + --> $DIR/future-proofing-locals.rs:15:9 + | +LL | use T::U; + | ^ + +error: imports cannot refer to type parameters + --> $DIR/future-proofing-locals.rs:16:9 + | +LL | use T::*; + | ^ + +error: imports cannot refer to type parameters + --> $DIR/future-proofing-locals.rs:20:9 + | +LL | use T; + | ^ + +error: imports cannot refer to local variables + --> $DIR/future-proofing-locals.rs:26:9 + | +LL | use x as _; + | ^ + +error: imports cannot refer to local variables + --> $DIR/future-proofing-locals.rs:32:9 + | +LL | use x; + | ^ + +error: imports cannot refer to local variables + --> $DIR/future-proofing-locals.rs:38:17 + | +LL | use x; + | ^ + +error: imports cannot refer to type parameters + --> $DIR/future-proofing-locals.rs:46:10 + | +LL | use {T as _, x}; + | ^ + +error: imports cannot refer to local variables + --> $DIR/future-proofing-locals.rs:46:18 + | +LL | use {T as _, x}; + | ^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/rust-2018/issue-51008-1.rs b/tests/ui/rust-2018/issue-51008-1.rs new file mode 100644 index 000000000..8ae5e8278 --- /dev/null +++ b/tests/ui/rust-2018/issue-51008-1.rs @@ -0,0 +1,15 @@ +// Regression test for #51008 -- the anonymous lifetime in `&i32` was +// being incorrectly considered part of the "elided lifetimes" from +// the impl. +// +// run-pass + +#![feature(rust_2018_preview)] + +trait A { + +} + +impl A for F where F: PartialEq { } + +fn main() {} diff --git a/tests/ui/rust-2018/issue-51008.rs b/tests/ui/rust-2018/issue-51008.rs new file mode 100644 index 000000000..b62609e32 --- /dev/null +++ b/tests/ui/rust-2018/issue-51008.rs @@ -0,0 +1,15 @@ +// Regression test for #51008 -- the anonymous lifetime in `&i32` was +// being incorrectly considered part of the "elided lifetimes" from +// the impl. +// +// run-pass + +#![feature(rust_2018_preview)] + +trait A { + +} + +impl A for F where F: FnOnce(&i32) {} + +fn main() {} diff --git a/tests/ui/rust-2018/issue-52202-use-suggestions.rs b/tests/ui/rust-2018/issue-52202-use-suggestions.rs new file mode 100644 index 000000000..1c0426808 --- /dev/null +++ b/tests/ui/rust-2018/issue-52202-use-suggestions.rs @@ -0,0 +1,13 @@ +// edition:2018 + +// The local `use` suggestion should start with `crate::` (but the +// standard-library suggestions should not, obviously). + +mod plumbing { + pub struct Drain; +} + +fn main() { + let _d = Drain {}; + //~^ ERROR cannot find struct, variant or union type `Drain` in this scope +} diff --git a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr new file mode 100644 index 000000000..38cd9713d --- /dev/null +++ b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr @@ -0,0 +1,21 @@ +error[E0422]: cannot find struct, variant or union type `Drain` in this scope + --> $DIR/issue-52202-use-suggestions.rs:11:14 + | +LL | let _d = Drain {}; + | ^^^^^ not found in this scope + | +help: consider importing one of these items + | +LL | use crate::plumbing::Drain; + | +LL | use std::collections::binary_heap::Drain; + | +LL | use std::collections::hash_map::Drain; + | +LL | use std::collections::hash_set::Drain; + | + and 3 other candidates + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/rust-2018/issue-54006.rs b/tests/ui/rust-2018/issue-54006.rs new file mode 100644 index 000000000..a7a4770fc --- /dev/null +++ b/tests/ui/rust-2018/issue-54006.rs @@ -0,0 +1,13 @@ +// edition:2018 + +#![no_std] +#![crate_type = "lib"] + +use alloc::vec; +//~^ ERROR unresolved import `alloc` + +pub fn foo() { + let mut xs = vec![]; + //~^ ERROR cannot determine resolution for the macro `vec` + xs.push(0); +} diff --git a/tests/ui/rust-2018/issue-54006.stderr b/tests/ui/rust-2018/issue-54006.stderr new file mode 100644 index 000000000..1978138a6 --- /dev/null +++ b/tests/ui/rust-2018/issue-54006.stderr @@ -0,0 +1,17 @@ +error[E0432]: unresolved import `alloc` + --> $DIR/issue-54006.rs:6:5 + | +LL | use alloc::vec; + | ^^^^^ help: a similar path exists: `core::alloc` + +error: cannot determine resolution for the macro `vec` + --> $DIR/issue-54006.rs:10:18 + | +LL | let mut xs = vec![]; + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed new file mode 100644 index 000000000..d59243800 --- /dev/null +++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed @@ -0,0 +1,14 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--extern edition_lint_paths --cfg blandiloquence +// edition:2018 + +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + +// The suggestion span should include the attribute. + + +//~^ ERROR unused extern crate + +fn main() {} diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs new file mode 100644 index 000000000..a948baee5 --- /dev/null +++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs @@ -0,0 +1,15 @@ +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--extern edition_lint_paths --cfg blandiloquence +// edition:2018 + +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + +// The suggestion span should include the attribute. + +#[cfg(blandiloquence)] //~ HELP remove it +extern crate edition_lint_paths; +//~^ ERROR unused extern crate + +fn main() {} diff --git a/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr new file mode 100644 index 000000000..2ef97e7f2 --- /dev/null +++ b/tests/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr @@ -0,0 +1,18 @@ +error: unused extern crate + --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:12:1 + | +LL | / #[cfg(blandiloquence)] +LL | | extern crate edition_lint_paths; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | |________________________________| + | help: remove it + | +note: the lint level is defined here + --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:6:9 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: `#[deny(unused_extern_crates)]` implied by `#[deny(rust_2018_idioms)]` + +error: aborting due to previous error + diff --git a/tests/ui/rust-2018/local-path-suggestions-2015.rs b/tests/ui/rust-2018/local-path-suggestions-2015.rs new file mode 100644 index 000000000..32e9c0c33 --- /dev/null +++ b/tests/ui/rust-2018/local-path-suggestions-2015.rs @@ -0,0 +1,26 @@ +// aux-build:baz.rs +// compile-flags:--extern baz +// edition:2015 + +// This test exists to demonstrate the behaviour of the import suggestions +// from the `local-path-suggestions-2018.rs` test when not using the 2018 edition. + +extern crate baz as aux_baz; + +mod foo { + pub type Bar = u32; +} + +mod baz { + use foo::Bar; + + fn baz() { + let x: Bar = 22; + } +} + +use foo::Bar; + +use foobar::Baz; //~ ERROR unresolved import `foobar` + +fn main() { } diff --git a/tests/ui/rust-2018/local-path-suggestions-2015.stderr b/tests/ui/rust-2018/local-path-suggestions-2015.stderr new file mode 100644 index 000000000..666864a18 --- /dev/null +++ b/tests/ui/rust-2018/local-path-suggestions-2015.stderr @@ -0,0 +1,12 @@ +error[E0432]: unresolved import `foobar` + --> $DIR/local-path-suggestions-2015.rs:24:5 + | +LL | use foobar::Baz; + | ^^^^^^ + | | + | unresolved import + | help: a similar path exists: `aux_baz::foobar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/local-path-suggestions-2018.rs b/tests/ui/rust-2018/local-path-suggestions-2018.rs new file mode 100644 index 000000000..5eafbb2c2 --- /dev/null +++ b/tests/ui/rust-2018/local-path-suggestions-2018.rs @@ -0,0 +1,21 @@ +// aux-build:baz.rs +// compile-flags:--extern baz +// edition:2018 + +mod foo { + pub type Bar = u32; +} + +mod bazz { + use foo::Bar; //~ ERROR unresolved import `foo` + + fn baz() { + let x: Bar = 22; + } +} + +use foo::Bar; + +use foobar::Baz; //~ ERROR unresolved import `foobar` + +fn main() { } diff --git a/tests/ui/rust-2018/local-path-suggestions-2018.stderr b/tests/ui/rust-2018/local-path-suggestions-2018.stderr new file mode 100644 index 000000000..40f3d6bf1 --- /dev/null +++ b/tests/ui/rust-2018/local-path-suggestions-2018.stderr @@ -0,0 +1,17 @@ +error[E0432]: unresolved import `foo` + --> $DIR/local-path-suggestions-2018.rs:10:9 + | +LL | use foo::Bar; + | ^^^ help: a similar path exists: `crate::foo` + | + = note: `use` statements changed in Rust 2018; read more at + +error[E0432]: unresolved import `foobar` + --> $DIR/local-path-suggestions-2018.rs:19:5 + | +LL | use foobar::Baz; + | ^^^^^^ help: a similar path exists: `baz::foobar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/macro-use-warned-against.rs b/tests/ui/rust-2018/macro-use-warned-against.rs new file mode 100644 index 000000000..72f2868e0 --- /dev/null +++ b/tests/ui/rust-2018/macro-use-warned-against.rs @@ -0,0 +1,14 @@ +// aux-build:macro-use-warned-against.rs +// aux-build:macro-use-warned-against2.rs +// check-pass + +#![warn(macro_use_extern_crate, unused)] + +#[macro_use] //~ WARN should be replaced at use sites with a `use` item +extern crate macro_use_warned_against; +#[macro_use] //~ WARN unused `#[macro_use]` +extern crate macro_use_warned_against2; + +fn main() { + foo!(); +} diff --git a/tests/ui/rust-2018/macro-use-warned-against.stderr b/tests/ui/rust-2018/macro-use-warned-against.stderr new file mode 100644 index 000000000..6b46f002e --- /dev/null +++ b/tests/ui/rust-2018/macro-use-warned-against.stderr @@ -0,0 +1,27 @@ +warning: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead + --> $DIR/macro-use-warned-against.rs:7:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/macro-use-warned-against.rs:5:9 + | +LL | #![warn(macro_use_extern_crate, unused)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused `#[macro_use]` import + --> $DIR/macro-use-warned-against.rs:9:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/macro-use-warned-against.rs:5:33 + | +LL | #![warn(macro_use_extern_crate, unused)] + | ^^^^^^ + = note: `#[warn(unused_imports)]` implied by `#[warn(unused)]` + +warning: 2 warnings emitted + diff --git a/tests/ui/rust-2018/proc-macro-crate-in-paths.rs b/tests/ui/rust-2018/proc-macro-crate-in-paths.rs new file mode 100644 index 000000000..2d4cb6514 --- /dev/null +++ b/tests/ui/rust-2018/proc-macro-crate-in-paths.rs @@ -0,0 +1,16 @@ +// build-pass (FIXME(62277): could be check-pass?) +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![deny(rust_2018_compatibility)] +#![feature(rust_2018_preview)] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Template, attributes(template))] +pub fn derive_template(input: TokenStream) -> TokenStream { + input +} diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed new file mode 100644 index 000000000..832632268 --- /dev/null +++ b/tests/ui/rust-2018/remove-extern-crate.fixed @@ -0,0 +1,39 @@ +// run-rustfix +// edition:2018 +// check-pass +// aux-build:remove-extern-crate.rs +// compile-flags:--extern remove_extern_crate + +#![warn(rust_2018_idioms)] + + //~ WARNING unused extern crate +// Shouldn't suggest changing to `use`, as `another_name` +// would no longer be added to the prelude which could cause +// compilation errors for imports that use `another_name` in other +// modules. See #57672. +extern crate core as another_name; +use remove_extern_crate; +#[macro_use] +extern crate remove_extern_crate as something_else; + +// Shouldn't suggest changing to `use`, as the `alloc` +// crate is not in the extern prelude - see #54381. +extern crate alloc; + +fn main() { + another_name::mem::drop(3); + another::foo(); + remove_extern_crate::foo!(); + bar!(); + alloc::vec![5]; +} + +mod another { + use core; //~ WARNING `extern crate` is not idiomatic + use remove_extern_crate; + + pub fn foo() { + core::mem::drop(4); + remove_extern_crate::foo!(); + } +} diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs new file mode 100644 index 000000000..bbb84cd46 --- /dev/null +++ b/tests/ui/rust-2018/remove-extern-crate.rs @@ -0,0 +1,39 @@ +// run-rustfix +// edition:2018 +// check-pass +// aux-build:remove-extern-crate.rs +// compile-flags:--extern remove_extern_crate + +#![warn(rust_2018_idioms)] + +extern crate core; //~ WARNING unused extern crate +// Shouldn't suggest changing to `use`, as `another_name` +// would no longer be added to the prelude which could cause +// compilation errors for imports that use `another_name` in other +// modules. See #57672. +extern crate core as another_name; +use remove_extern_crate; +#[macro_use] +extern crate remove_extern_crate as something_else; + +// Shouldn't suggest changing to `use`, as the `alloc` +// crate is not in the extern prelude - see #54381. +extern crate alloc; + +fn main() { + another_name::mem::drop(3); + another::foo(); + remove_extern_crate::foo!(); + bar!(); + alloc::vec![5]; +} + +mod another { + extern crate core; //~ WARNING `extern crate` is not idiomatic + use remove_extern_crate; + + pub fn foo() { + core::mem::drop(4); + remove_extern_crate::foo!(); + } +} diff --git a/tests/ui/rust-2018/remove-extern-crate.stderr b/tests/ui/rust-2018/remove-extern-crate.stderr new file mode 100644 index 000000000..bde4c1808 --- /dev/null +++ b/tests/ui/rust-2018/remove-extern-crate.stderr @@ -0,0 +1,21 @@ +warning: unused extern crate + --> $DIR/remove-extern-crate.rs:9:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ help: remove it + | +note: the lint level is defined here + --> $DIR/remove-extern-crate.rs:7:9 + | +LL | #![warn(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]` + +warning: `extern crate` is not idiomatic in the new edition + --> $DIR/remove-extern-crate.rs:32:5 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ help: convert it to a `use` + +warning: 2 warnings emitted + diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed new file mode 100644 index 000000000..f5afbad9f --- /dev/null +++ b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed @@ -0,0 +1,23 @@ +// aux-build:suggestions-not-always-applicable.rs +// edition:2015 +// run-rustfix +// rustfix-only-machine-applicable +// check-pass + +#![feature(rust_2018_preview)] +#![warn(rust_2018_compatibility)] + +extern crate suggestions_not_always_applicable as foo; + +pub struct Foo; + +mod test { + use crate::foo::foo; + + #[foo] + fn main() {} +} + +fn main() { + test::foo(); +} diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/suggestions-not-always-applicable.rs new file mode 100644 index 000000000..f5afbad9f --- /dev/null +++ b/tests/ui/rust-2018/suggestions-not-always-applicable.rs @@ -0,0 +1,23 @@ +// aux-build:suggestions-not-always-applicable.rs +// edition:2015 +// run-rustfix +// rustfix-only-machine-applicable +// check-pass + +#![feature(rust_2018_preview)] +#![warn(rust_2018_compatibility)] + +extern crate suggestions_not_always_applicable as foo; + +pub struct Foo; + +mod test { + use crate::foo::foo; + + #[foo] + fn main() {} +} + +fn main() { + test::foo(); +} diff --git a/tests/ui/rust-2018/trait-import-suggestions.rs b/tests/ui/rust-2018/trait-import-suggestions.rs new file mode 100644 index 000000000..9c67c3f4b --- /dev/null +++ b/tests/ui/rust-2018/trait-import-suggestions.rs @@ -0,0 +1,31 @@ +// edition:2018 +// aux-build:trait-import-suggestions.rs +// compile-flags:--extern trait-import-suggestions + +mod foo { + mod foobar { + pub(crate) trait Foobar { + fn foobar(&self) { } + } + + impl Foobar for u32 { } + } + + pub(crate) trait Bar { + fn bar(&self) { } + } + + impl Bar for u32 { } + + fn in_foo() { + let x: u32 = 22; + x.foobar(); //~ ERROR no method named `foobar` + } +} + +fn main() { + let x: u32 = 22; + x.bar(); //~ ERROR no method named `bar` + x.baz(); //~ ERROR no method named `baz` + let y = u32::from_str("33"); //~ ERROR no function or associated item named `from_str` +} diff --git a/tests/ui/rust-2018/trait-import-suggestions.stderr b/tests/ui/rust-2018/trait-import-suggestions.stderr new file mode 100644 index 000000000..6454b6045 --- /dev/null +++ b/tests/ui/rust-2018/trait-import-suggestions.stderr @@ -0,0 +1,55 @@ +error[E0599]: no method named `foobar` found for type `u32` in the current scope + --> $DIR/trait-import-suggestions.rs:22:11 + | +LL | fn foobar(&self) { } + | ------ the method is available for `u32` here +... +LL | x.foobar(); + | ^^^^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use crate::foo::foobar::Foobar; + | + +error[E0599]: no method named `bar` found for type `u32` in the current scope + --> $DIR/trait-import-suggestions.rs:28:7 + | +LL | fn bar(&self) { } + | --- the method is available for `u32` here +... +LL | x.bar(); + | ^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use crate::foo::Bar; + | + +error[E0599]: no method named `baz` found for type `u32` in the current scope + --> $DIR/trait-import-suggestions.rs:29:7 + | +LL | x.baz(); + | ^^^ method not found in `u32` + +error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope + --> $DIR/trait-import-suggestions.rs:30:18 + | +LL | let y = u32::from_str("33"); + | ^^^^^^^^ function or associated item not found in `u32` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::str::FromStr; + | +help: there is an associated function with a similar name + | +LL | let y = u32::from_str_radix("33"); + | ~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rust-2018/try-ident.fixed b/tests/ui/rust-2018/try-ident.fixed new file mode 100644 index 000000000..985348665 --- /dev/null +++ b/tests/ui/rust-2018/try-ident.fixed @@ -0,0 +1,15 @@ +// run-rustfix +// check-pass + +#![warn(rust_2018_compatibility)] + +fn main() { + r#try(); + //~^ WARNING `try` is a keyword in the 2018 edition + //~| WARNING this is accepted in the current edition +} + +fn r#try() { + //~^ WARNING `try` is a keyword in the 2018 edition + //~| WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/try-ident.rs b/tests/ui/rust-2018/try-ident.rs new file mode 100644 index 000000000..2c02b7596 --- /dev/null +++ b/tests/ui/rust-2018/try-ident.rs @@ -0,0 +1,15 @@ +// run-rustfix +// check-pass + +#![warn(rust_2018_compatibility)] + +fn main() { + try(); + //~^ WARNING `try` is a keyword in the 2018 edition + //~| WARNING this is accepted in the current edition +} + +fn try() { + //~^ WARNING `try` is a keyword in the 2018 edition + //~| WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2018/try-ident.stderr b/tests/ui/rust-2018/try-ident.stderr new file mode 100644 index 000000000..74015ac9d --- /dev/null +++ b/tests/ui/rust-2018/try-ident.stderr @@ -0,0 +1,26 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/try-ident.rs:7:5 + | +LL | try(); + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/try-ident.rs:4:9 + | +LL | #![warn(rust_2018_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]` + +warning: `try` is a keyword in the 2018 edition + --> $DIR/try-ident.rs:12:4 + | +LL | fn try() { + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 + +warning: 2 warnings emitted + diff --git a/tests/ui/rust-2018/try-macro.fixed b/tests/ui/rust-2018/try-macro.fixed new file mode 100644 index 000000000..3308870f6 --- /dev/null +++ b/tests/ui/rust-2018/try-macro.fixed @@ -0,0 +1,18 @@ +// Test that `try!` macros are rewritten. + +// run-rustfix +// check-pass + +#![warn(rust_2018_compatibility)] +#![allow(dead_code)] +#![allow(deprecated)] + +fn foo() -> Result { + let x: Result = Ok(22); + r#try!(x); + //~^ WARNING `try` is a keyword in the 2018 edition + //~| WARNING this is accepted in the current edition + Ok(44) +} + +fn main() {} diff --git a/tests/ui/rust-2018/try-macro.rs b/tests/ui/rust-2018/try-macro.rs new file mode 100644 index 000000000..69e87a1ff --- /dev/null +++ b/tests/ui/rust-2018/try-macro.rs @@ -0,0 +1,18 @@ +// Test that `try!` macros are rewritten. + +// run-rustfix +// check-pass + +#![warn(rust_2018_compatibility)] +#![allow(dead_code)] +#![allow(deprecated)] + +fn foo() -> Result { + let x: Result = Ok(22); + try!(x); + //~^ WARNING `try` is a keyword in the 2018 edition + //~| WARNING this is accepted in the current edition + Ok(44) +} + +fn main() {} diff --git a/tests/ui/rust-2018/try-macro.stderr b/tests/ui/rust-2018/try-macro.stderr new file mode 100644 index 000000000..760378f09 --- /dev/null +++ b/tests/ui/rust-2018/try-macro.stderr @@ -0,0 +1,17 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/try-macro.rs:12:5 + | +LL | try!(x); + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #49716 +note: the lint level is defined here + --> $DIR/try-macro.rs:6:9 + | +LL | #![warn(rust_2018_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]` + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs new file mode 100644 index 000000000..678b4774d --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs @@ -0,0 +1,21 @@ +// edition:2018 + +// This test is similar to `ambiguity-macros.rs`, but nested in a module. + +#![allow(non_camel_case_types)] + +mod foo { + pub use std::io; + //~^ ERROR `std` is ambiguous + + macro_rules! m { + () => { + mod std { + pub struct io; + } + } + } + m!(); +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr new file mode 100644 index 000000000..7e008d465 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr @@ -0,0 +1,25 @@ +error[E0659]: `std` is ambiguous + --> $DIR/ambiguity-macros-nested.rs:8:13 + | +LL | pub use std::io; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `std` could refer to a built-in crate + = help: use `::std` to refer to this crate unambiguously +note: `std` could also refer to the module defined here + --> $DIR/ambiguity-macros-nested.rs:13:13 + | +LL | / mod std { +LL | | pub struct io; +LL | | } + | |_____________^ +... +LL | m!(); + | ---- in this macro invocation + = help: use `self::std` to refer to this module unambiguously + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.rs b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.rs new file mode 100644 index 000000000..56ea726d7 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.rs @@ -0,0 +1,19 @@ +// edition:2018 + +// This test is similar to `ambiguity.rs`, but with macros defining local items. + +#![allow(non_camel_case_types)] + +use std::io; +//~^ ERROR `std` is ambiguous + +macro_rules! m { + () => { + mod std { + pub struct io; + } + } +} +m!(); + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr new file mode 100644 index 000000000..771d2c10c --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -0,0 +1,25 @@ +error[E0659]: `std` is ambiguous + --> $DIR/ambiguity-macros.rs:7:5 + | +LL | use std::io; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `std` could refer to a built-in crate + = help: use `::std` to refer to this crate unambiguously +note: `std` could also refer to the module defined here + --> $DIR/ambiguity-macros.rs:12:9 + | +LL | / mod std { +LL | | pub struct io; +LL | | } + | |_________^ +... +LL | m!(); + | ---- in this macro invocation + = help: use `crate::std` to refer to this module unambiguously + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs new file mode 100644 index 000000000..50c8fc822 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.rs @@ -0,0 +1,16 @@ +// edition:2018 + +// This test is similar to `ambiguity.rs`, but nested in a module. + +#![allow(non_camel_case_types)] + +mod foo { + pub use std::io; + //~^ ERROR `std` is ambiguous + + mod std { + pub struct io; + } +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr new file mode 100644 index 000000000..defb16f79 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-nested.stderr @@ -0,0 +1,21 @@ +error[E0659]: `std` is ambiguous + --> $DIR/ambiguity-nested.rs:8:13 + | +LL | pub use std::io; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `std` could refer to a built-in crate + = help: use `::std` to refer to this crate unambiguously +note: `std` could also refer to the module defined here + --> $DIR/ambiguity-nested.rs:11:5 + | +LL | / mod std { +LL | | pub struct io; +LL | | } + | |_____^ + = help: use `self::std` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity.rs b/tests/ui/rust-2018/uniform-paths/ambiguity.rs new file mode 100644 index 000000000..60f77a1c6 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity.rs @@ -0,0 +1,12 @@ +// edition:2018 + +#![allow(non_camel_case_types)] + +use std::io; +//~^ ERROR `std` is ambiguous + +mod std { + pub struct io; +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity.stderr new file mode 100644 index 000000000..2d735c7e3 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/ambiguity.stderr @@ -0,0 +1,21 @@ +error[E0659]: `std` is ambiguous + --> $DIR/ambiguity.rs:5:5 + | +LL | use std::io; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `std` could refer to a built-in crate + = help: use `::std` to refer to this crate unambiguously +note: `std` could also refer to the module defined here + --> $DIR/ambiguity.rs:8:1 + | +LL | / mod std { +LL | | pub struct io; +LL | | } + | |_^ + = help: use `crate::std` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs b/tests/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs new file mode 100644 index 000000000..4aa5d1870 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/auxiliary/cross-crate.rs @@ -0,0 +1,5 @@ +// edition:2018 + +pub use ignore as built_in_attr; +pub use u8 as built_in_type; +pub use rustfmt as tool_mod; diff --git a/tests/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs new file mode 100644 index 000000000..1ce9841c1 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs @@ -0,0 +1 @@ +pub trait Trait { fn no_op(&self); } diff --git a/tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs new file mode 100644 index 000000000..db723075f --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs @@ -0,0 +1 @@ +pub extern crate core; diff --git a/tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs new file mode 100644 index 000000000..bc010a3dd --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs @@ -0,0 +1 @@ +// Nothing here diff --git a/tests/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs new file mode 100644 index 000000000..8fd2d77be --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs @@ -0,0 +1,3 @@ +pub trait Deserialize { + fn deserialize(); +} diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs new file mode 100644 index 000000000..3f5897901 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.rs @@ -0,0 +1,20 @@ +// edition:2018 + +mod my { + pub mod sub { + pub fn bar() {} + } +} + +mod sub { + pub fn bar() {} +} + +fn foo() { + use my::sub; + { + use sub::bar; //~ ERROR `sub` is ambiguous + } +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr new file mode 100644 index 000000000..3d45a8140 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr @@ -0,0 +1,24 @@ +error[E0659]: `sub` is ambiguous + --> $DIR/block-scoped-shadow-nested.rs:16:13 + | +LL | use sub::bar; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `sub` could refer to the module imported here + --> $DIR/block-scoped-shadow-nested.rs:14:9 + | +LL | use my::sub; + | ^^^^^^^ +note: `sub` could also refer to the module defined here + --> $DIR/block-scoped-shadow-nested.rs:9:1 + | +LL | / mod sub { +LL | | pub fn bar() {} +LL | | } + | |_^ + = help: use `crate::sub` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs new file mode 100644 index 000000000..828ee4fe4 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.rs @@ -0,0 +1,21 @@ +// edition:2018 + +#![allow(non_camel_case_types)] + +enum Foo {} + +struct std; + +fn main() { + enum Foo { A, B } + use Foo::*; + //~^ ERROR `Foo` is ambiguous + + let _ = (A, B); + + fn std() {} + enum std {} + use std as foo; + //~^ ERROR `std` is ambiguous + //~| ERROR `std` is ambiguous +} diff --git a/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr new file mode 100644 index 000000000..b068312ce --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr @@ -0,0 +1,60 @@ +error[E0659]: `Foo` is ambiguous + --> $DIR/block-scoped-shadow.rs:11:9 + | +LL | use Foo::*; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `Foo` could refer to the enum defined here + --> $DIR/block-scoped-shadow.rs:10:5 + | +LL | enum Foo { A, B } + | ^^^^^^^^^^^^^^^^^ +note: `Foo` could also refer to the enum defined here + --> $DIR/block-scoped-shadow.rs:5:1 + | +LL | enum Foo {} + | ^^^^^^^^^^^ + = help: use `crate::Foo` to refer to this enum unambiguously + +error[E0659]: `std` is ambiguous + --> $DIR/block-scoped-shadow.rs:18:9 + | +LL | use std as foo; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `std` could refer to the enum defined here + --> $DIR/block-scoped-shadow.rs:17:5 + | +LL | enum std {} + | ^^^^^^^^^^^ +note: `std` could also refer to the struct defined here + --> $DIR/block-scoped-shadow.rs:7:1 + | +LL | struct std; + | ^^^^^^^^^^^ + = help: use `crate::std` to refer to this struct unambiguously + +error[E0659]: `std` is ambiguous + --> $DIR/block-scoped-shadow.rs:18:9 + | +LL | use std as foo; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `std` could refer to the function defined here + --> $DIR/block-scoped-shadow.rs:16:5 + | +LL | fn std() {} + | ^^^^^^^^^^^ +note: `std` could also refer to the unit struct defined here + --> $DIR/block-scoped-shadow.rs:7:1 + | +LL | struct std; + | ^^^^^^^^^^^ + = help: use `crate::std` to refer to this unit struct unambiguously + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/cross-crate.rs b/tests/ui/rust-2018/uniform-paths/cross-crate.rs new file mode 100644 index 000000000..0ca7fa37a --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/cross-crate.rs @@ -0,0 +1,12 @@ +// edition:2018 +// aux-build:cross-crate.rs + +extern crate cross_crate; +use cross_crate::*; + +#[built_in_attr] //~ ERROR cannot use a built-in attribute through an import +#[tool_mod::skip] //~ ERROR cannot use a tool module through an import + //~| ERROR cannot use a tool module through an import +fn main() { + let _: built_in_type; // OK +} diff --git a/tests/ui/rust-2018/uniform-paths/cross-crate.stderr b/tests/ui/rust-2018/uniform-paths/cross-crate.stderr new file mode 100644 index 000000000..45f77a0c9 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/cross-crate.stderr @@ -0,0 +1,38 @@ +error: cannot use a built-in attribute through an import + --> $DIR/cross-crate.rs:7:3 + | +LL | #[built_in_attr] + | ^^^^^^^^^^^^^ + | +note: the built-in attribute imported here + --> $DIR/cross-crate.rs:5:5 + | +LL | use cross_crate::*; + | ^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/cross-crate.rs:8:3 + | +LL | #[tool_mod::skip] + | ^^^^^^^^ + | +note: the tool module imported here + --> $DIR/cross-crate.rs:5:5 + | +LL | use cross_crate::*; + | ^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/cross-crate.rs:8:3 + | +LL | #[tool_mod::skip] + | ^^^^^^^^ + | +note: the tool module imported here + --> $DIR/cross-crate.rs:5:5 + | +LL | use cross_crate::*; + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rust-2018/uniform-paths/deadlock.rs b/tests/ui/rust-2018/uniform-paths/deadlock.rs new file mode 100644 index 000000000..2427bde6d --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/deadlock.rs @@ -0,0 +1,8 @@ +// edition:2018 +// compile-flags:--extern foo --extern bar + +use bar::foo; //~ ERROR can't find crate for `bar` +use foo::bar; //~ ERROR can't find crate for `foo` +//~^^ ERROR unresolved imports `bar::foo`, `foo::bar` + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/deadlock.stderr b/tests/ui/rust-2018/uniform-paths/deadlock.stderr new file mode 100644 index 000000000..8b9863948 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/deadlock.stderr @@ -0,0 +1,24 @@ +error[E0463]: can't find crate for `bar` + --> $DIR/deadlock.rs:4:5 + | +LL | use bar::foo; + | ^^^ can't find crate + +error[E0463]: can't find crate for `foo` + --> $DIR/deadlock.rs:5:5 + | +LL | use foo::bar; + | ^^^ can't find crate + +error[E0432]: unresolved imports `bar::foo`, `foo::bar` + --> $DIR/deadlock.rs:4:5 + | +LL | use bar::foo; + | ^^^^^^^^ +LL | use foo::bar; + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0432, E0463. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/uniform-paths/fn-local-enum.rs b/tests/ui/rust-2018/uniform-paths/fn-local-enum.rs new file mode 100644 index 000000000..c6525869b --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/fn-local-enum.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +fn main() { + enum E { A, B, C } + + use E::*; + match A { + A => {} + B => {} + C => {} + } +} diff --git a/tests/ui/rust-2018/uniform-paths/from-decl-macro.rs b/tests/ui/rust-2018/uniform-paths/from-decl-macro.rs new file mode 100644 index 000000000..9af520a07 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/from-decl-macro.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +#![feature(decl_macro)] + +macro check() { + ::std::vec::Vec::::new() +} + +fn main() { + check!(); +} diff --git a/tests/ui/rust-2018/uniform-paths/issue-54253.rs b/tests/ui/rust-2018/uniform-paths/issue-54253.rs new file mode 100644 index 000000000..7db469945 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-54253.rs @@ -0,0 +1,17 @@ +// edition:2018 + +// Dummy import that previously introduced uniform path canaries. +use std; + +// fn version() -> &'static str {""} + +mod foo { + // Error wasn't reported, despite `version` being commented out above. + use crate::version; //~ ERROR unresolved import `crate::version` + + fn bar() { + version(); + } +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/issue-54253.stderr b/tests/ui/rust-2018/uniform-paths/issue-54253.stderr new file mode 100644 index 000000000..adde63590 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-54253.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `crate::version` + --> $DIR/issue-54253.rs:10:9 + | +LL | use crate::version; + | ^^^^^^^^^^^^^^ no `version` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/uniform-paths/issue-55779.rs b/tests/ui/rust-2018/uniform-paths/issue-55779.rs new file mode 100644 index 000000000..0af17a89b --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-55779.rs @@ -0,0 +1,29 @@ +// run-pass +// edition:2018 +// aux-crate:issue_55779_extern_trait=issue-55779-extern-trait.rs + +use issue_55779_extern_trait::Trait; + +struct Local; +struct Helper; + +impl Trait for Local { + fn no_op(&self) + { + // (Unused) extern crate declaration necessary to reproduce bug + extern crate issue_55779_extern_trait; + + // This one works + // impl Trait for Helper { fn no_op(&self) { } } + + // This one infinite-loops + const _IMPL_SERIALIZE_FOR_HELPER: () = { + // (extern crate can also appear here to reproduce bug, + // as in originating example from serde) + impl Trait for Helper { fn no_op(&self) { } } + }; + + } +} + +fn main() { } diff --git a/tests/ui/rust-2018/uniform-paths/issue-56596-2.rs b/tests/ui/rust-2018/uniform-paths/issue-56596-2.rs new file mode 100644 index 000000000..9ea7e496d --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-56596-2.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2018 +// compile-flags: --extern issue_56596_2 +// aux-build:issue-56596-2.rs + +mod m { + use core::any; + pub use issue_56596_2::*; +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/issue-56596.rs b/tests/ui/rust-2018/uniform-paths/issue-56596.rs new file mode 100644 index 000000000..ec5bb656a --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-56596.rs @@ -0,0 +1,12 @@ +// edition:2018 +// compile-flags: --extern issue_56596 +// aux-build:issue-56596.rs + +mod m { + pub mod issue_56596 {} +} + +use m::*; +use issue_56596; //~ ERROR `issue_56596` is ambiguous + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/issue-56596.stderr b/tests/ui/rust-2018/uniform-paths/issue-56596.stderr new file mode 100644 index 000000000..8b8ab26dc --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-56596.stderr @@ -0,0 +1,19 @@ +error[E0659]: `issue_56596` is ambiguous + --> $DIR/issue-56596.rs:10:5 + | +LL | use issue_56596; + | ^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources + = note: `issue_56596` could refer to a crate passed with `--extern` + = help: use `::issue_56596` to refer to this crate unambiguously +note: `issue_56596` could also refer to the module imported here + --> $DIR/issue-56596.rs:9:5 + | +LL | use m::*; + | ^^^^ + = help: use `crate::issue_56596` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/rust-2018/uniform-paths/issue-87932.rs b/tests/ui/rust-2018/uniform-paths/issue-87932.rs new file mode 100644 index 000000000..70a641d8a --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-87932.rs @@ -0,0 +1,15 @@ +// edition:2018 +// aux-crate:issue_87932_a=issue-87932-a.rs + +pub struct A {} + +impl issue_87932_a::Deserialize for A { + fn deserialize() { + extern crate issue_87932_a as _a; + } +} + +fn main() { + A::deserialize(); + //~^ ERROR no function or associated item named `deserialize` found for struct `A` +} diff --git a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr new file mode 100644 index 000000000..b52720ae3 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -0,0 +1,18 @@ +error[E0599]: no function or associated item named `deserialize` found for struct `A` in the current scope + --> $DIR/issue-87932.rs:13:8 + | +LL | pub struct A {} + | ------------ function or associated item `deserialize` not found for this struct +... +LL | A::deserialize(); + | ^^^^^^^^^^^ function or associated item not found in `A` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use ::deserialize::_a::Deserialize; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rust-2018/uniform-paths/macro-rules.rs b/tests/ui/rust-2018/uniform-paths/macro-rules.rs new file mode 100644 index 000000000..2d9a6a9a9 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/macro-rules.rs @@ -0,0 +1,43 @@ +// edition:2018 + +#![feature(decl_macro)] + +mod m1 { + // Non-exported legacy macros are treated as `pub(crate)`. + macro_rules! legacy_macro { () => () } + + use legacy_macro as _; // OK + pub(crate) use legacy_macro as _; // OK + pub use legacy_macro as _; //~ ERROR `legacy_macro` is only public within the crate, and cannot be re-exported outside +} + +mod m2 { + macro_rules! legacy_macro { () => () } + + #[allow(non_camel_case_types)] + type legacy_macro = u8; + + // Legacy macro imports don't prevent names from other namespaces from being imported. + use legacy_macro as _; // OK +} + +mod m3 { + macro legacy_macro() {} + + fn f() { + macro_rules! legacy_macro { () => () } + + // Legacy macro imports create ambiguities with other names in the same namespace. + use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous + } +} + +mod exported { + // Exported legacy macros are treated as `pub`. + #[macro_export] + macro_rules! legacy_macro { () => () } + + pub use legacy_macro as _; // OK +} + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/macro-rules.stderr b/tests/ui/rust-2018/uniform-paths/macro-rules.stderr new file mode 100644 index 000000000..9f8c928c3 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/macro-rules.stderr @@ -0,0 +1,35 @@ +error[E0364]: `legacy_macro` is only public within the crate, and cannot be re-exported outside + --> $DIR/macro-rules.rs:11:13 + | +LL | pub use legacy_macro as _; + | ^^^^^^^^^^^^^^^^^ + | +help: consider adding a `#[macro_export]` to the macro in the imported module + --> $DIR/macro-rules.rs:7:5 + | +LL | macro_rules! legacy_macro { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0659]: `legacy_macro` is ambiguous + --> $DIR/macro-rules.rs:31:13 + | +LL | use legacy_macro as _; + | ^^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of multiple potential import sources +note: `legacy_macro` could refer to the macro defined here + --> $DIR/macro-rules.rs:28:9 + | +LL | macro_rules! legacy_macro { () => () } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `legacy_macro` could also refer to the macro defined here + --> $DIR/macro-rules.rs:25:5 + | +LL | macro legacy_macro() {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::legacy_macro` to refer to this macro unambiguously + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0364, E0659. +For more information about an error, try `rustc --explain E0364`. diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail-2.rs b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.rs new file mode 100644 index 000000000..44da71de0 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.rs @@ -0,0 +1,21 @@ +// edition:2018 + +// Built-in attribute +use inline as imported_inline; +mod builtin { + pub use inline as imported_inline; +} + +// Tool module +use rustfmt as imported_rustfmt; +mod tool_mod { + pub use rustfmt as imported_rustfmt; +} + +#[imported_inline] //~ ERROR cannot use a built-in attribute through an import +#[builtin::imported_inline] //~ ERROR cannot use a built-in attribute through an import +#[imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import + //~| ERROR cannot use a tool module through an import +#[tool_mod::imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import + //~| ERROR cannot use a tool module through an import +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr new file mode 100644 index 000000000..908bb4985 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/prelude-fail-2.stderr @@ -0,0 +1,68 @@ +error: cannot use a built-in attribute through an import + --> $DIR/prelude-fail-2.rs:15:3 + | +LL | #[imported_inline] + | ^^^^^^^^^^^^^^^ + | +note: the built-in attribute imported here + --> $DIR/prelude-fail-2.rs:4:5 + | +LL | use inline as imported_inline; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a built-in attribute through an import + --> $DIR/prelude-fail-2.rs:16:3 + | +LL | #[builtin::imported_inline] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/prelude-fail-2.rs:17:3 + | +LL | #[imported_rustfmt::skip] + | ^^^^^^^^^^^^^^^^ + | +note: the tool module imported here + --> $DIR/prelude-fail-2.rs:10:5 + | +LL | use rustfmt as imported_rustfmt; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/prelude-fail-2.rs:19:13 + | +LL | #[tool_mod::imported_rustfmt::skip] + | ^^^^^^^^^^^^^^^^ + | +note: the tool module imported here + --> $DIR/prelude-fail-2.rs:12:13 + | +LL | pub use rustfmt as imported_rustfmt; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/prelude-fail-2.rs:17:3 + | +LL | #[imported_rustfmt::skip] + | ^^^^^^^^^^^^^^^^ + | +note: the tool module imported here + --> $DIR/prelude-fail-2.rs:10:5 + | +LL | use rustfmt as imported_rustfmt; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot use a tool module through an import + --> $DIR/prelude-fail-2.rs:19:13 + | +LL | #[tool_mod::imported_rustfmt::skip] + | ^^^^^^^^^^^^^^^^ + | +note: the tool module imported here + --> $DIR/prelude-fail-2.rs:12:13 + | +LL | pub use rustfmt as imported_rustfmt; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail.rs b/tests/ui/rust-2018/uniform-paths/prelude-fail.rs new file mode 100644 index 000000000..48c33d720 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/prelude-fail.rs @@ -0,0 +1,6 @@ +// edition:2018 + +// Tool attribute +use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt` + +fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr b/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr new file mode 100644 index 000000000..97d4c7367 --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/prelude-fail.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `rustfmt` + --> $DIR/prelude-fail.rs:4:5 + | +LL | use rustfmt::skip as imported_rustfmt_skip; + | ^^^^^^^ `rustfmt` is a tool module, not a module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2018/uniform-paths/prelude.rs b/tests/ui/rust-2018/uniform-paths/prelude.rs new file mode 100644 index 000000000..65763614c --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/prelude.rs @@ -0,0 +1,22 @@ +// build-pass (FIXME(62277): could be check-pass?) +// edition:2018 + +// Macro imported with `#[macro_use] extern crate` +use vec as imported_vec; + +// Standard library prelude +use Vec as ImportedVec; + +// Built-in type +use u8 as imported_u8; + +// Built-in macro +use env as env_imported; + +type A = imported_u8; + +fn main() { + imported_vec![0]; + ImportedVec::::new(); + env_imported!("PATH"); +} diff --git a/tests/ui/rust-2018/uniform-paths/redundant.rs b/tests/ui/rust-2018/uniform-paths/redundant.rs new file mode 100644 index 000000000..fd7fc7fbd --- /dev/null +++ b/tests/ui/rust-2018/uniform-paths/redundant.rs @@ -0,0 +1,20 @@ +// run-pass +// edition:2018 + +use std; +use std::io; + +mod foo { + pub use std as my_std; +} + +mod bar { + pub use std::{self}; +} + +fn main() { + let _ = io::stdout(); + let _ = self::std::io::stdout(); + let _ = foo::my_std::io::stdout(); + let _ = bar::std::io::stdout(); +} diff --git a/tests/ui/rust-2018/unresolved-asterisk-imports.rs b/tests/ui/rust-2018/unresolved-asterisk-imports.rs new file mode 100644 index 000000000..ad1064570 --- /dev/null +++ b/tests/ui/rust-2018/unresolved-asterisk-imports.rs @@ -0,0 +1,6 @@ +// edition:2018 + +use not_existing_crate::*; //~ ERROR unresolved import `not_existing_crate +use std as foo; + +fn main() {} diff --git a/tests/ui/rust-2018/unresolved-asterisk-imports.stderr b/tests/ui/rust-2018/unresolved-asterisk-imports.stderr new file mode 100644 index 000000000..09e9edc63 --- /dev/null +++ b/tests/ui/rust-2018/unresolved-asterisk-imports.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `not_existing_crate` + --> $DIR/unresolved-asterisk-imports.rs:3:5 + | +LL | use not_existing_crate::*; + | ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `not_existing_crate` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/rust-2021/array-into-iter-ambiguous.fixed b/tests/ui/rust-2021/array-into-iter-ambiguous.fixed new file mode 100644 index 000000000..76f661bae --- /dev/null +++ b/tests/ui/rust-2021/array-into-iter-ambiguous.fixed @@ -0,0 +1,27 @@ +// See https://github.com/rust-lang/rust/issues/88475 +// run-rustfix +// edition:2018 +// check-pass +#![warn(array_into_iter)] +#![allow(unused)] + +struct FooIter; + +trait MyIntoIter { + fn into_iter(self) -> FooIter; +} + +impl MyIntoIter for [T; N] { + fn into_iter(self) -> FooIter { + FooIter + } +} + +struct Point; + +pub fn main() { + let points: [Point; 1] = [Point]; + let y = MyIntoIter::into_iter(points); + //~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021 + //~| WARNING this changes meaning in Rust 2021 +} diff --git a/tests/ui/rust-2021/array-into-iter-ambiguous.rs b/tests/ui/rust-2021/array-into-iter-ambiguous.rs new file mode 100644 index 000000000..83fbf8f6c --- /dev/null +++ b/tests/ui/rust-2021/array-into-iter-ambiguous.rs @@ -0,0 +1,27 @@ +// See https://github.com/rust-lang/rust/issues/88475 +// run-rustfix +// edition:2018 +// check-pass +#![warn(array_into_iter)] +#![allow(unused)] + +struct FooIter; + +trait MyIntoIter { + fn into_iter(self) -> FooIter; +} + +impl MyIntoIter for [T; N] { + fn into_iter(self) -> FooIter { + FooIter + } +} + +struct Point; + +pub fn main() { + let points: [Point; 1] = [Point]; + let y = points.into_iter(); + //~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021 + //~| WARNING this changes meaning in Rust 2021 +} diff --git a/tests/ui/rust-2021/array-into-iter-ambiguous.stderr b/tests/ui/rust-2021/array-into-iter-ambiguous.stderr new file mode 100644 index 000000000..2a724bd30 --- /dev/null +++ b/tests/ui/rust-2021/array-into-iter-ambiguous.stderr @@ -0,0 +1,16 @@ +warning: trait method `into_iter` will become ambiguous in Rust 2021 + --> $DIR/array-into-iter-ambiguous.rs:24:13 + | +LL | let y = points.into_iter(); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyIntoIter::into_iter(points)` + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see +note: the lint level is defined here + --> $DIR/array-into-iter-ambiguous.rs:5:9 + | +LL | #![warn(array_into_iter)] + | ^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs new file mode 100644 index 000000000..eb301e5e1 --- /dev/null +++ b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs @@ -0,0 +1,25 @@ +// force-host +// edition:2018 +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_integer_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#123").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_char_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#'a'").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs new file mode 100644 index 000000000..691bfdc15 --- /dev/null +++ b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs @@ -0,0 +1,25 @@ +// force-host +// edition:2021 +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_integer_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#123").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_char_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#'a'").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_prefixed_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("hey#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed b/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed new file mode 100644 index 000000000..a1b6f5b16 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed @@ -0,0 +1,30 @@ +// See https://github.com/rust-lang/rust/issues/88470 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +pub trait PyTryFrom<'v, T>: Sized { + fn try_from(value: V) -> Result<&'v Self, T>; +} + +pub trait PyTryInto: Sized { + fn try_into(&self) -> Result<&T, i32>; +} + +struct Foo; + +impl PyTryInto for Foo +where + U: for<'v> PyTryFrom<'v, i32>, +{ + fn try_into(&self) -> Result<&U, i32> { + >::try_from(self) + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + } +} + +fn main() {} diff --git a/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs b/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs new file mode 100644 index 000000000..142ba5520 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs @@ -0,0 +1,30 @@ +// See https://github.com/rust-lang/rust/issues/88470 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +pub trait PyTryFrom<'v, T>: Sized { + fn try_from(value: V) -> Result<&'v Self, T>; +} + +pub trait PyTryInto: Sized { + fn try_into(&self) -> Result<&T, i32>; +} + +struct Foo; + +impl PyTryInto for Foo +where + U: for<'v> PyTryFrom<'v, i32>, +{ + fn try_into(&self) -> Result<&U, i32> { + U::try_from(self) + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + } +} + +fn main() {} diff --git a/tests/ui/rust-2021/future-prelude-collision-generic-trait.stderr b/tests/ui/rust-2021/future-prelude-collision-generic-trait.stderr new file mode 100644 index 000000000..f38da132b --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-generic-trait.stderr @@ -0,0 +1,16 @@ +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic-trait.rs:24:9 + | +LL | U::try_from(self) + | ^^^^^^^^^^^ help: disambiguate the associated function: `>::try_from` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-prelude-collision-generic-trait.rs:5:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2021/future-prelude-collision-generic.fixed b/tests/ui/rust-2021/future-prelude-collision-generic.fixed new file mode 100644 index 000000000..1bb9ba377 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-generic.fixed @@ -0,0 +1,37 @@ +// test for https://github.com/rust-lang/rust/issues/86940 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +struct Generic<'a, U>(&'a U); + +trait MyFromIter { + fn from_iter(_: i32) -> Self; +} + +impl MyFromIter for Generic<'static, i32> { + fn from_iter(_: i32) -> Self { + todo!() + } +} + +impl std::iter::FromIterator for Generic<'static, i32> { + fn from_iter>(_: T) -> Self { + todo!() + } +} + +fn main() { + as MyFromIter>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + as MyFromIter>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + as MyFromIter>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) +} diff --git a/tests/ui/rust-2021/future-prelude-collision-generic.rs b/tests/ui/rust-2021/future-prelude-collision-generic.rs new file mode 100644 index 000000000..d7f8affc6 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-generic.rs @@ -0,0 +1,37 @@ +// test for https://github.com/rust-lang/rust/issues/86940 +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +struct Generic<'a, U>(&'a U); + +trait MyFromIter { + fn from_iter(_: i32) -> Self; +} + +impl MyFromIter for Generic<'static, i32> { + fn from_iter(_: i32) -> Self { + todo!() + } +} + +impl std::iter::FromIterator for Generic<'static, i32> { + fn from_iter>(_: T) -> Self { + todo!() + } +} + +fn main() { + Generic::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + Generic::<'static, i32>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) + Generic::<'_, _>::from_iter(1); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~| this is accepted in the current edition (Rust 2018) +} diff --git a/tests/ui/rust-2021/future-prelude-collision-generic.stderr b/tests/ui/rust-2021/future-prelude-collision-generic.stderr new file mode 100644 index 000000000..9893b3eba --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-generic.stderr @@ -0,0 +1,34 @@ +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic.rs:28:5 + | +LL | Generic::from_iter(1); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-prelude-collision-generic.rs:5:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic.rs:31:5 + | +LL | Generic::<'static, i32>::from_iter(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-generic.rs:34:5 + | +LL | Generic::<'_, _>::from_iter(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyFromIter>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: 3 warnings emitted + diff --git a/tests/ui/rust-2021/future-prelude-collision-imported.fixed b/tests/ui/rust-2021/future-prelude-collision-imported.fixed new file mode 100644 index 000000000..15ccff749 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-imported.fixed @@ -0,0 +1,70 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +mod m { + pub trait TryIntoU32 { + fn try_into(self) -> Result; + } + + impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } + } + + pub trait AnotherTrick {} +} + +mod a { + use crate::m::TryIntoU32; + + fn main() { + // In this case, we can just use `TryIntoU32` + let _: u32 = TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod b { + use crate::m::AnotherTrick as TryIntoU32; + use crate::m::TryIntoU32 as _; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `crate::m::TryIntoU32` (with which it was imported). + let _: u32 = crate::m::TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod c { + use super::m::TryIntoU32 as _; + use crate::m::AnotherTrick as TryIntoU32; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `super::m::TryIntoU32` (with which it was imported). + let _: u32 = super::m::TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod d { + use super::m::*; + + fn main() { + // See https://github.com/rust-lang/rust/issues/88471 + let _: u32 = TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +fn main() {} diff --git a/tests/ui/rust-2021/future-prelude-collision-imported.rs b/tests/ui/rust-2021/future-prelude-collision-imported.rs new file mode 100644 index 000000000..cdffcaf75 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-imported.rs @@ -0,0 +1,70 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +mod m { + pub trait TryIntoU32 { + fn try_into(self) -> Result; + } + + impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } + } + + pub trait AnotherTrick {} +} + +mod a { + use crate::m::TryIntoU32; + + fn main() { + // In this case, we can just use `TryIntoU32` + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod b { + use crate::m::AnotherTrick as TryIntoU32; + use crate::m::TryIntoU32 as _; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `crate::m::TryIntoU32` (with which it was imported). + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod c { + use super::m::TryIntoU32 as _; + use crate::m::AnotherTrick as TryIntoU32; + + fn main() { + // In this case, a `TryIntoU32::try_into` rewrite will not work, and we need to use + // the path `super::m::TryIntoU32` (with which it was imported). + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +mod d { + use super::m::*; + + fn main() { + // See https://github.com/rust-lang/rust/issues/88471 + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + } +} + +fn main() {} diff --git a/tests/ui/rust-2021/future-prelude-collision-imported.stderr b/tests/ui/rust-2021/future-prelude-collision-imported.stderr new file mode 100644 index 000000000..c1d72d0df --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-imported.stderr @@ -0,0 +1,43 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:27:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-prelude-collision-imported.rs:4:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:40:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `crate::m::TryIntoU32::try_into(3u8)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:53:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `super::m::TryIntoU32::try_into(3u8)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-imported.rs:64:22 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: 4 warnings emitted + diff --git a/tests/ui/rust-2021/future-prelude-collision-macros.fixed b/tests/ui/rust-2021/future-prelude-collision-macros.fixed new file mode 100644 index 000000000..a97dc176e --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-macros.fixed @@ -0,0 +1,45 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(unreachable_code)] + +macro_rules! foo { + () => {{ + 123; + S + }}; +} + +trait MyTry { + fn try_into(self, _: u8); +} + +struct S; + +impl MyTry for S { + fn try_into(self, _: u8) {} +} + +trait TryFromU8: Sized { + fn try_from(_: u8); +} + +impl TryFromU8 for u32 { + fn try_from(_: u8) {} +} + +macro_rules! bar { + () => { + u32 + }; +} + +fn main() { + MyTry::try_into(foo!(), todo!()); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition + ::try_from(0); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2021/future-prelude-collision-macros.rs b/tests/ui/rust-2021/future-prelude-collision-macros.rs new file mode 100644 index 000000000..82484b5b3 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-macros.rs @@ -0,0 +1,45 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] +#![allow(unreachable_code)] + +macro_rules! foo { + () => {{ + 123; + S + }}; +} + +trait MyTry { + fn try_into(self, _: u8); +} + +struct S; + +impl MyTry for S { + fn try_into(self, _: u8) {} +} + +trait TryFromU8: Sized { + fn try_from(_: u8); +} + +impl TryFromU8 for u32 { + fn try_from(_: u8) {} +} + +macro_rules! bar { + () => { + u32 + }; +} + +fn main() { + foo!().try_into(todo!()); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition + ::try_from(0); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2021/future-prelude-collision-macros.stderr b/tests/ui/rust-2021/future-prelude-collision-macros.stderr new file mode 100644 index 000000000..4d4a07699 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-macros.stderr @@ -0,0 +1,25 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-macros.rs:39:5 + | +LL | foo!().try_into(todo!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyTry::try_into(foo!(), todo!())` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-prelude-collision-macros.rs:4:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-macros.rs:42:5 + | +LL | ::try_from(0); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `::try_from` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: 2 warnings emitted + diff --git a/tests/ui/rust-2021/future-prelude-collision-shadow.rs b/tests/ui/rust-2021/future-prelude-collision-shadow.rs new file mode 100644 index 000000000..27891a8d1 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-shadow.rs @@ -0,0 +1,32 @@ +// edition:2018 +#![warn(rust_2021_prelude_collisions)] +#![allow(dead_code)] +#![allow(unused_imports)] + +mod m { + pub trait TryIntoU32 { + fn try_into(self) -> Result; + } + + impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } + } + + pub trait AnotherTrick {} +} + +mod d { + use crate::m::AnotherTrick as TryIntoU32; + use crate::m::*; + + fn main() { + // Here, `TryIntoU32` is imported but shadowed, but in that case we don't permit its methods + // to be available. + let _: u32 = 3u8.try_into().unwrap(); + //~^ ERROR no method named `try_into` found for type `u8` in the current scope + } +} + +fn main() {} diff --git a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr new file mode 100644 index 000000000..3d21b735a --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `try_into` found for type `u8` in the current scope + --> $DIR/future-prelude-collision-shadow.rs:27:26 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^ method not found in `u8` + | + = help: items from traits can only be used if the trait is in scope + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use crate::m::TryIntoU32; + | +LL | use std::convert::TryInto; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/rust-2021/future-prelude-collision-turbofish.fixed b/tests/ui/rust-2021/future-prelude-collision-turbofish.fixed new file mode 100644 index 000000000..3e76fced7 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-turbofish.fixed @@ -0,0 +1,28 @@ +// See https://github.com/rust-lang/rust/issues/88442 +// run-rustfix +// edition:2018 +// check-pass +#![allow(unused)] +#![warn(rust_2021_prelude_collisions)] + +trait AnnotatableTryInto { + fn try_into(self) -> Result + where Self: std::convert::TryInto { + std::convert::TryInto::try_into(self) + } +} + +impl AnnotatableTryInto for T where T: From {} + +fn main() -> Result<(), &'static str> { + let x: u64 = 1; + AnnotatableTryInto::try_into::(x).or(Err("foo"))?.checked_sub(1); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + + AnnotatableTryInto::try_into::(x).or(Err("foo"))?; + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + + Ok(()) +} diff --git a/tests/ui/rust-2021/future-prelude-collision-turbofish.rs b/tests/ui/rust-2021/future-prelude-collision-turbofish.rs new file mode 100644 index 000000000..abb292ef9 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-turbofish.rs @@ -0,0 +1,28 @@ +// See https://github.com/rust-lang/rust/issues/88442 +// run-rustfix +// edition:2018 +// check-pass +#![allow(unused)] +#![warn(rust_2021_prelude_collisions)] + +trait AnnotatableTryInto { + fn try_into(self) -> Result + where Self: std::convert::TryInto { + std::convert::TryInto::try_into(self) + } +} + +impl AnnotatableTryInto for T where T: From {} + +fn main() -> Result<(), &'static str> { + let x: u64 = 1; + x.try_into::().or(Err("foo"))?.checked_sub(1); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + + x.try_into::().or(Err("foo"))?; + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + + Ok(()) +} diff --git a/tests/ui/rust-2021/future-prelude-collision-turbofish.stderr b/tests/ui/rust-2021/future-prelude-collision-turbofish.stderr new file mode 100644 index 000000000..c0ef80fd8 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-turbofish.stderr @@ -0,0 +1,25 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-turbofish.rs:19:5 + | +LL | x.try_into::().or(Err("foo"))?.checked_sub(1); + | ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::(x)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-prelude-collision-turbofish.rs:6:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision-turbofish.rs:23:5 + | +LL | x.try_into::().or(Err("foo"))?; + | ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::(x)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: 2 warnings emitted + diff --git a/tests/ui/rust-2021/future-prelude-collision-unneeded.rs b/tests/ui/rust-2021/future-prelude-collision-unneeded.rs new file mode 100644 index 000000000..247d5884b --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision-unneeded.rs @@ -0,0 +1,60 @@ +// edition:2018 +// check-pass +#![allow(unused)] +#![deny(rust_2021_prelude_collisions)] + +struct S; + +impl S { + fn try_into(self) -> S { + S + } +} + +struct X; + +trait Hey { + fn from_iter(_: i32) -> Self; +} + +impl Hey for X { + fn from_iter(_: i32) -> Self { + X + } +} + +struct Y(T); + +impl Hey for Y { + fn from_iter(_: i32) -> Self { + Y(0) + } +} + +struct Z(T); + +impl Hey for Z { + fn from_iter(_: i32) -> Self { + Z(0) + } +} + +impl std::iter::FromIterator for Z { + fn from_iter>(_: T) -> Self { + todo!() + } +} + +fn main() { + // See https://github.com/rust-lang/rust/issues/86633 + let s = S; + let s2 = s.try_into(); + + // Check that we do not issue suggestions for types that do not implement `FromIter`. + // + // See https://github.com/rust-lang/rust/issues/86902 + X::from_iter(1); + Y::from_iter(1); + Y::::from_iter(1); + Z::::from_iter(1); +} diff --git a/tests/ui/rust-2021/future-prelude-collision.fixed b/tests/ui/rust-2021/future-prelude-collision.fixed new file mode 100644 index 000000000..43b0ec1c3 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision.fixed @@ -0,0 +1,98 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(self) -> Result; +} + +impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } +} + +// needed for autoref test +impl TryIntoU32 for &f32 { + fn try_into(self) -> Result { + Ok(*self as u32) + } +} + +trait TryFromU8: Sized { + fn try_from(x: u8) -> Result; +} + +impl TryFromU8 for u32 { + fn try_from(x: u8) -> Result { + Ok(x as u32) + } +} + +impl TryIntoU32 for *const u16 { + fn try_into(self) -> Result { + Ok(unsafe { *self } as u32) + } +} + +trait FromByteIterator { + fn from_iter(iter: T) -> Self + where + T: Iterator; +} + +impl FromByteIterator for Vec { + fn from_iter(iter: T) -> Self + where + T: Iterator, + { + iter.collect() + } +} + +fn main() { + // test dot-call that will break in 2021 edition + let _: u32 = TryIntoU32::try_into(3u8).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test associated function call that will break in 2021 edition + let _ = ::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test reverse turbofish too + let _ = as FromByteIterator>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter()); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // negative testing lint (this line should *not* emit a warning) + let _: u32 = TryFromU8::try_from(3u8).unwrap(); + + // test type omission + let _: u32 = <_ as TryFromU8>::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoderef + let _: u32 = TryIntoU32::try_into(*(&3u8)).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoref + let _: u32 = TryIntoU32::try_into(&3.0).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + let mut data = 3u16; + let mut_ptr = std::ptr::addr_of_mut!(data); + let _: u32 = TryIntoU32::try_into(mut_ptr as *const _).unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + type U32Alias = u32; + let _ = ::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2021/future-prelude-collision.rs b/tests/ui/rust-2021/future-prelude-collision.rs new file mode 100644 index 000000000..4c7a47ffb --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision.rs @@ -0,0 +1,98 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(self) -> Result; +} + +impl TryIntoU32 for u8 { + fn try_into(self) -> Result { + Ok(self as u32) + } +} + +// needed for autoref test +impl TryIntoU32 for &f32 { + fn try_into(self) -> Result { + Ok(*self as u32) + } +} + +trait TryFromU8: Sized { + fn try_from(x: u8) -> Result; +} + +impl TryFromU8 for u32 { + fn try_from(x: u8) -> Result { + Ok(x as u32) + } +} + +impl TryIntoU32 for *const u16 { + fn try_into(self) -> Result { + Ok(unsafe { *self } as u32) + } +} + +trait FromByteIterator { + fn from_iter(iter: T) -> Self + where + T: Iterator; +} + +impl FromByteIterator for Vec { + fn from_iter(iter: T) -> Self + where + T: Iterator, + { + iter.collect() + } +} + +fn main() { + // test dot-call that will break in 2021 edition + let _: u32 = 3u8.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test associated function call that will break in 2021 edition + let _ = u32::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test reverse turbofish too + let _ = >::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter()); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // negative testing lint (this line should *not* emit a warning) + let _: u32 = TryFromU8::try_from(3u8).unwrap(); + + // test type omission + let _: u32 = <_>::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoderef + let _: u32 = (&3u8).try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + // test autoref + let _: u32 = 3.0.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + let mut data = 3u16; + let mut_ptr = std::ptr::addr_of_mut!(data); + let _: u32 = mut_ptr.try_into().unwrap(); + //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition + + type U32Alias = u32; + let _ = U32Alias::try_from(3u8).unwrap(); + //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2021/future-prelude-collision.stderr b/tests/ui/rust-2021/future-prelude-collision.stderr new file mode 100644 index 000000000..cae113ff7 --- /dev/null +++ b/tests/ui/rust-2021/future-prelude-collision.stderr @@ -0,0 +1,79 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:56:18 + | +LL | let _: u32 = 3u8.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-prelude-collision.rs:4:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:61:13 + | +LL | let _ = u32::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^ help: disambiguate the associated function: `::try_from` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:66:13 + | +LL | let _ = >::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter()); + | ^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as FromByteIterator>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:74:18 + | +LL | let _: u32 = <_>::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^ help: disambiguate the associated function: `<_ as TryFromU8>::try_from` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:79:18 + | +LL | let _: u32 = (&3u8).try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(*(&3u8))` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:84:18 + | +LL | let _: u32 = 3.0.try_into().unwrap(); + | ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(&3.0)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:90:18 + | +LL | let _: u32 = mut_ptr.try_into().unwrap(); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: trait-associated function `try_from` will become ambiguous in Rust 2021 + --> $DIR/future-prelude-collision.rs:95:13 + | +LL | let _ = U32Alias::try_from(3u8).unwrap(); + | ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `::try_from` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + +warning: 8 warnings emitted + diff --git a/tests/ui/rust-2021/generic-type-collision.fixed b/tests/ui/rust-2021/generic-type-collision.fixed new file mode 100644 index 000000000..feba7d19b --- /dev/null +++ b/tests/ui/rust-2021/generic-type-collision.fixed @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +// edition 2018 +#![warn(rust_2021_prelude_collisions)] + +trait MyTrait { + fn from_iter(x: Option); +} + +impl MyTrait<()> for Vec { + fn from_iter(_: Option<()>) {} +} + +fn main() { + as MyTrait<_>>::from_iter(None); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2021/generic-type-collision.rs b/tests/ui/rust-2021/generic-type-collision.rs new file mode 100644 index 000000000..335e7e520 --- /dev/null +++ b/tests/ui/rust-2021/generic-type-collision.rs @@ -0,0 +1,18 @@ +// check-pass +// run-rustfix +// edition 2018 +#![warn(rust_2021_prelude_collisions)] + +trait MyTrait { + fn from_iter(x: Option); +} + +impl MyTrait<()> for Vec { + fn from_iter(_: Option<()>) {} +} + +fn main() { + >::from_iter(None); + //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 + //~^^ WARNING this is accepted in the current edition +} diff --git a/tests/ui/rust-2021/generic-type-collision.stderr b/tests/ui/rust-2021/generic-type-collision.stderr new file mode 100644 index 000000000..1ec61044f --- /dev/null +++ b/tests/ui/rust-2021/generic-type-collision.stderr @@ -0,0 +1,16 @@ +warning: trait-associated function `from_iter` will become ambiguous in Rust 2021 + --> $DIR/generic-type-collision.rs:15:5 + | +LL | >::from_iter(None); + | ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: ` as MyTrait<_>>::from_iter` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/generic-type-collision.rs:4:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2021/inherent-dyn-collision.fixed b/tests/ui/rust-2021/inherent-dyn-collision.fixed new file mode 100644 index 000000000..5789a9039 --- /dev/null +++ b/tests/ui/rust-2021/inherent-dyn-collision.fixed @@ -0,0 +1,53 @@ +// Test case where the method we want is an inherent method on a +// dyn Trait. In that case, the fix is to insert `*` on the receiver. +// +// check-pass +// run-rustfix +// edition:2018 + +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(&self) -> Result; +} + +impl TryIntoU32 for u8 { + // note: &self + fn try_into(&self) -> Result { + Ok(22) + } +} + +mod inner { + use super::get_dyn_trait; + + // note: this does nothing, but is copying from ffishim's problem of + // having a struct of the same name as the trait in-scope, while *also* + // implementing the trait for that struct but **without** importing the + // trait itself into scope + struct TryIntoU32; + + impl super::TryIntoU32 for TryIntoU32 { + fn try_into(&self) -> Result { + Ok(0) + } + } + + // this is where the gross part happens. since `get_dyn_trait` returns + // a Box, it can still call the method for `dyn Trait` without + // `Trait` being in-scope. it might even be possible to make the trait itself + // entirely unreference-able from the callsite? + pub fn test() -> u32 { + (&*get_dyn_trait()).try_into().unwrap() + //~^ WARNING trait method `try_into` will become ambiguous + //~| WARNING this is accepted in the current edition + } +} + +fn get_dyn_trait() -> Box { + Box::new(3u8) as Box +} + +fn main() { + dbg!(inner::test()); +} diff --git a/tests/ui/rust-2021/inherent-dyn-collision.rs b/tests/ui/rust-2021/inherent-dyn-collision.rs new file mode 100644 index 000000000..a3893c033 --- /dev/null +++ b/tests/ui/rust-2021/inherent-dyn-collision.rs @@ -0,0 +1,53 @@ +// Test case where the method we want is an inherent method on a +// dyn Trait. In that case, the fix is to insert `*` on the receiver. +// +// check-pass +// run-rustfix +// edition:2018 + +#![warn(rust_2021_prelude_collisions)] + +trait TryIntoU32 { + fn try_into(&self) -> Result; +} + +impl TryIntoU32 for u8 { + // note: &self + fn try_into(&self) -> Result { + Ok(22) + } +} + +mod inner { + use super::get_dyn_trait; + + // note: this does nothing, but is copying from ffishim's problem of + // having a struct of the same name as the trait in-scope, while *also* + // implementing the trait for that struct but **without** importing the + // trait itself into scope + struct TryIntoU32; + + impl super::TryIntoU32 for TryIntoU32 { + fn try_into(&self) -> Result { + Ok(0) + } + } + + // this is where the gross part happens. since `get_dyn_trait` returns + // a Box, it can still call the method for `dyn Trait` without + // `Trait` being in-scope. it might even be possible to make the trait itself + // entirely unreference-able from the callsite? + pub fn test() -> u32 { + get_dyn_trait().try_into().unwrap() + //~^ WARNING trait method `try_into` will become ambiguous + //~| WARNING this is accepted in the current edition + } +} + +fn get_dyn_trait() -> Box { + Box::new(3u8) as Box +} + +fn main() { + dbg!(inner::test()); +} diff --git a/tests/ui/rust-2021/inherent-dyn-collision.stderr b/tests/ui/rust-2021/inherent-dyn-collision.stderr new file mode 100644 index 000000000..f5905574a --- /dev/null +++ b/tests/ui/rust-2021/inherent-dyn-collision.stderr @@ -0,0 +1,16 @@ +warning: trait method `try_into` will become ambiguous in Rust 2021 + --> $DIR/inherent-dyn-collision.rs:41:9 + | +LL | get_dyn_trait().try_into().unwrap() + | ^^^^^^^^^^^^^^^ help: disambiguate the method call: `(&*get_dyn_trait())` + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/inherent-dyn-collision.rs:8:9 + | +LL | #![warn(rust_2021_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2021/inherent-method-collision.rs b/tests/ui/rust-2021/inherent-method-collision.rs new file mode 100644 index 000000000..507105207 --- /dev/null +++ b/tests/ui/rust-2021/inherent-method-collision.rs @@ -0,0 +1,15 @@ +// Test that we do NOT warn for inherent methods invoked via `T::` form. +// +// check-pass + +#![deny(rust_2021_prelude_collisions)] + +pub struct MySeq {} + +impl MySeq { + pub fn from_iter(_: impl IntoIterator) {} +} + +fn main() { + MySeq::from_iter(Some(22)); +} diff --git a/tests/ui/rust-2021/panic.rs b/tests/ui/rust-2021/panic.rs new file mode 100644 index 000000000..394fc3c8f --- /dev/null +++ b/tests/ui/rust-2021/panic.rs @@ -0,0 +1,24 @@ +// edition:2021 + +fn main() { + debug_assert!(false, 123); + //~^ ERROR must be a string literal + assert!(false, 123); + //~^ ERROR must be a string literal + panic!(false, 123); + //~^ ERROR must be a string literal + + std::debug_assert!(false, 123); + //~^ ERROR must be a string literal + std::assert!(false, 123); + //~^ ERROR must be a string literal + std::panic!(false, 123); + //~^ ERROR must be a string literal + + core::debug_assert!(false, 123); + //~^ ERROR must be a string literal + core::assert!(false, 123); + //~^ ERROR must be a string literal + core::panic!(false, 123); + //~^ ERROR must be a string literal +} diff --git a/tests/ui/rust-2021/panic.stderr b/tests/ui/rust-2021/panic.stderr new file mode 100644 index 000000000..40b62d279 --- /dev/null +++ b/tests/ui/rust-2021/panic.stderr @@ -0,0 +1,101 @@ +error: format argument must be a string literal + --> $DIR/panic.rs:4:26 + | +LL | debug_assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | debug_assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:6:20 + | +LL | assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:8:12 + | +LL | panic!(false, 123); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | panic!("{} {}", false, 123); + | ++++++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:11:31 + | +LL | std::debug_assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | std::debug_assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:13:25 + | +LL | std::assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | std::assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:15:17 + | +LL | std::panic!(false, 123); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | std::panic!("{} {}", false, 123); + | ++++++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:18:32 + | +LL | core::debug_assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | core::debug_assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:20:26 + | +LL | core::assert!(false, 123); + | ^^^ + | +help: you might be missing a string literal to format with + | +LL | core::assert!(false, "{}", 123); + | +++++ + +error: format argument must be a string literal + --> $DIR/panic.rs:22:18 + | +LL | core::panic!(false, 123); + | ^^^^^ + | +help: you might be missing a string literal to format with + | +LL | core::panic!("{} {}", false, 123); + | ++++++++ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/rust-2021/prelude2021.rs b/tests/ui/rust-2021/prelude2021.rs new file mode 100644 index 000000000..a63b6fcf2 --- /dev/null +++ b/tests/ui/rust-2021/prelude2021.rs @@ -0,0 +1,6 @@ +// check-pass +// edition:2021 + +fn main() { + let _: u16 = 123i32.try_into().unwrap(); +} diff --git a/tests/ui/rust-2021/reserved-prefixes-migration.fixed b/tests/ui/rust-2021/reserved-prefixes-migration.fixed new file mode 100644 index 000000000..eed2f313a --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes-migration.fixed @@ -0,0 +1,38 @@ +// check-pass +// run-rustfix +// edition:2018 + +#![warn(rust_2021_prefixes_incompatible_syntax)] + +macro_rules! m2 { + ($a:tt $b:tt) => {}; +} + +macro_rules! m3 { + ($a:tt $b:tt $c:tt) => {}; +} + +fn main() { + m2!(z "hey"); + //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m2!(prefix "hey"); + //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey #123); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey #hey); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} + +macro_rules! quote { + (# name = # kind # value) => {}; +} + +quote! { + #name = #kind #value + //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} diff --git a/tests/ui/rust-2021/reserved-prefixes-migration.rs b/tests/ui/rust-2021/reserved-prefixes-migration.rs new file mode 100644 index 000000000..0565db793 --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes-migration.rs @@ -0,0 +1,38 @@ +// check-pass +// run-rustfix +// edition:2018 + +#![warn(rust_2021_prefixes_incompatible_syntax)] + +macro_rules! m2 { + ($a:tt $b:tt) => {}; +} + +macro_rules! m3 { + ($a:tt $b:tt $c:tt) => {}; +} + +fn main() { + m2!(z"hey"); + //~^ WARNING prefix `z` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m2!(prefix"hey"); + //~^ WARNING prefix `prefix` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey#123); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 + m3!(hey#hey); + //~^ WARNING prefix `hey` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} + +macro_rules! quote { + (# name = # kind # value) => {}; +} + +quote! { + #name = #kind#value + //~^ WARNING prefix `kind` is unknown [rust_2021_prefixes_incompatible_syntax] + //~| WARNING hard error in Rust 2021 +} diff --git a/tests/ui/rust-2021/reserved-prefixes-migration.stderr b/tests/ui/rust-2021/reserved-prefixes-migration.stderr new file mode 100644 index 000000000..20914d1b9 --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes-migration.stderr @@ -0,0 +1,72 @@ +warning: prefix `z` is unknown + --> $DIR/reserved-prefixes-migration.rs:16:9 + | +LL | m2!(z"hey"); + | ^ unknown prefix + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/reserved-prefixes-migration.rs:5:9 + | +LL | #![warn(rust_2021_prefixes_incompatible_syntax)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m2!(z "hey"); + | + + +warning: prefix `prefix` is unknown + --> $DIR/reserved-prefixes-migration.rs:19:9 + | +LL | m2!(prefix"hey"); + | ^^^^^^ unknown prefix + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m2!(prefix "hey"); + | + + +warning: prefix `hey` is unknown + --> $DIR/reserved-prefixes-migration.rs:22:9 + | +LL | m3!(hey#123); + | ^^^ unknown prefix + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m3!(hey #123); + | + + +warning: prefix `hey` is unknown + --> $DIR/reserved-prefixes-migration.rs:25:9 + | +LL | m3!(hey#hey); + | ^^^ unknown prefix + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | m3!(hey #hey); + | + + +warning: prefix `kind` is unknown + --> $DIR/reserved-prefixes-migration.rs:35:14 + | +LL | #name = #kind#value + | ^^^^ unknown prefix + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see +help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + | +LL | #name = #kind #value + | + + +warning: 5 warnings emitted + diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs new file mode 100644 index 000000000..74f206606 --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs @@ -0,0 +1,21 @@ +// edition:2018 +// aux-build:reserved-prefixes-macro-2018.rs +// aux-build:reserved-prefixes-macro-2021.rs + +extern crate reserved_prefixes_macro_2018 as m2018; +extern crate reserved_prefixes_macro_2021 as m2021; + +fn main() { + // Ok: + m2018::number_of_tokens_in_a_prefixed_integer_literal!(); + m2018::number_of_tokens_in_a_prefixed_char_literal!(); + m2018::number_of_tokens_in_a_prefixed_string_literal!(); + + // Error, even though *this* crate is 2018: + m2021::number_of_tokens_in_a_prefixed_integer_literal!(); + //~^ ERROR prefix `hey` is unknown + m2021::number_of_tokens_in_a_prefixed_char_literal!(); + //~^ ERROR prefix `hey` is unknown + m2021::number_of_tokens_in_a_prefixed_string_literal!(); + //~^ ERROR prefix `hey` is unknown +} diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro-2.stderr b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.stderr new file mode 100644 index 000000000..ae7c5d60c --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.stderr @@ -0,0 +1,29 @@ +error: prefix `hey` is unknown + --> $DIR/reserved-prefixes-via-macro-2.rs:15:5 + | +LL | m2021::number_of_tokens_in_a_prefixed_integer_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 + = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_integer_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: prefix `hey` is unknown + --> $DIR/reserved-prefixes-via-macro-2.rs:17:5 + | +LL | m2021::number_of_tokens_in_a_prefixed_char_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 + = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_char_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: prefix `hey` is unknown + --> $DIR/reserved-prefixes-via-macro-2.rs:19:5 + | +LL | m2021::number_of_tokens_in_a_prefixed_string_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 + = note: this error originates in the macro `m2021::number_of_tokens_in_a_prefixed_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro.rs b/tests/ui/rust-2021/reserved-prefixes-via-macro.rs new file mode 100644 index 000000000..110b6d64c --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro.rs @@ -0,0 +1,12 @@ +// run-pass +// edition:2021 +// aux-build:reserved-prefixes-macro-2018.rs + +extern crate reserved_prefixes_macro_2018 as m2018; + +fn main() { + // Ok, even though *this* crate is 2021: + assert_eq!(m2018::number_of_tokens_in_a_prefixed_integer_literal!(), 3); + assert_eq!(m2018::number_of_tokens_in_a_prefixed_char_literal!(), 3); + assert_eq!(m2018::number_of_tokens_in_a_prefixed_string_literal!(), 3); +} diff --git a/tests/ui/rust-2021/reserved-prefixes.rs b/tests/ui/rust-2021/reserved-prefixes.rs new file mode 100644 index 000000000..1994f25b6 --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes.rs @@ -0,0 +1,36 @@ +// edition:2021 + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +fn main() { + demo3!(foo#bar); //~ ERROR prefix `foo` is unknown + demo2!(foo"bar"); //~ ERROR prefix `foo` is unknown + demo2!(foo'b'); //~ ERROR prefix `foo` is unknown + + demo2!(foo'b); //~ ERROR prefix `foo` is unknown + demo3!(foo# bar); //~ ERROR prefix `foo` is unknown + demo4!(foo#! bar); //~ ERROR prefix `foo` is unknown + demo4!(foo## bar); //~ ERROR prefix `foo` is unknown + + demo4!(foo#bar#); + //~^ ERROR prefix `foo` is unknown + //~| ERROR prefix `bar` is unknown + + demo3!(foo # bar); + demo3!(foo #bar); + demo4!(foo!#bar); + demo4!(foo ##bar); + + demo3!(r"foo"#bar); + demo3!(r#foo#bar); +} diff --git a/tests/ui/rust-2021/reserved-prefixes.stderr b/tests/ui/rust-2021/reserved-prefixes.stderr new file mode 100644 index 000000000..807d6d98b --- /dev/null +++ b/tests/ui/rust-2021/reserved-prefixes.stderr @@ -0,0 +1,110 @@ +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:16:12 + | +LL | demo3!(foo#bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo3!(foo #bar); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:17:12 + | +LL | demo2!(foo"bar"); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(foo "bar"); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:18:12 + | +LL | demo2!(foo'b'); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(foo 'b'); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:20:12 + | +LL | demo2!(foo'b); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(foo 'b); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:21:12 + | +LL | demo3!(foo# bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo3!(foo # bar); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:22:12 + | +LL | demo4!(foo#! bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo #! bar); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:23:12 + | +LL | demo4!(foo## bar); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo ## bar); + | + + +error: prefix `foo` is unknown + --> $DIR/reserved-prefixes.rs:25:12 + | +LL | demo4!(foo#bar#); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo #bar#); + | + + +error: prefix `bar` is unknown + --> $DIR/reserved-prefixes.rs:25:16 + | +LL | demo4!(foo#bar#); + | ^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(foo#bar #); + | + + +error: aborting due to 9 previous errors + diff --git a/tests/ui/rustc-error.rs b/tests/ui/rustc-error.rs new file mode 100644 index 000000000..69d57948f --- /dev/null +++ b/tests/ui/rustc-error.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_error] +fn main() { + //~^ ERROR fatal error triggered by #[rustc_error] +} diff --git a/tests/ui/rustc-error.stderr b/tests/ui/rustc-error.stderr new file mode 100644 index 000000000..de27e9b8f --- /dev/null +++ b/tests/ui/rustc-error.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/rustc-error.rs:4:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rustc-rust-log.rs b/tests/ui/rustc-rust-log.rs new file mode 100644 index 000000000..52e7dcf44 --- /dev/null +++ b/tests/ui/rustc-rust-log.rs @@ -0,0 +1,11 @@ +// run-pass +// This test is just checking that we won't ICE if logging is turned +// on; don't bother trying to compare that (copious) output. +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr +// compile-flags: --error-format human +// aux-build: rustc-rust-log-aux.rs +// rustc-env:RUSTC_LOG=debug + +fn main() {} diff --git a/tests/ui/rustdoc/README.md b/tests/ui/rustdoc/README.md new file mode 100644 index 000000000..1c98ab038 --- /dev/null +++ b/tests/ui/rustdoc/README.md @@ -0,0 +1,3 @@ +This directory is for tests that have to do with rustdoc, but test the behavior +of rustc. For example, rustc should not warn that an attribute rustdoc uses is +unknown. diff --git a/tests/ui/rustdoc/cfg-rustdoc.rs b/tests/ui/rustdoc/cfg-rustdoc.rs new file mode 100644 index 000000000..dd8e1ed97 --- /dev/null +++ b/tests/ui/rustdoc/cfg-rustdoc.rs @@ -0,0 +1,6 @@ +#[cfg(doc)] +pub struct Foo; + +fn main() { + let f = Foo; //~ ERROR +} diff --git a/tests/ui/rustdoc/cfg-rustdoc.stderr b/tests/ui/rustdoc/cfg-rustdoc.stderr new file mode 100644 index 000000000..c687d1869 --- /dev/null +++ b/tests/ui/rustdoc/cfg-rustdoc.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `Foo` in this scope + --> $DIR/cfg-rustdoc.rs:5:13 + | +LL | let f = Foo; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/rustdoc/check-doc-alias-attr-location.rs b/tests/ui/rustdoc/check-doc-alias-attr-location.rs new file mode 100644 index 000000000..10609e5d8 --- /dev/null +++ b/tests/ui/rustdoc/check-doc-alias-attr-location.rs @@ -0,0 +1,32 @@ +#![crate_type = "lib"] + +pub struct Bar; +pub trait Foo { + type X; + fn foo(x: u32) -> Self::X; +} + +#[doc(alias = "foo")] //~ ERROR +extern "C" {} + +#[doc(alias = "bar")] //~ ERROR +impl Bar { + #[doc(alias = "const")] + const A: u32 = 0; +} + +#[doc(alias = "foobar")] //~ ERROR +impl Foo for Bar { + #[doc(alias = "assoc")] //~ ERROR + type X = i32; + fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X { + //~^ ERROR + #[doc(alias = "stmt")] //~ ERROR + let x = 0; + #[doc(alias = "expr")] //~ ERROR + match x { + #[doc(alias = "arm")] //~ ERROR + _ => 0 + } + } +} diff --git a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr new file mode 100644 index 000000000..23c93a4ed --- /dev/null +++ b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr @@ -0,0 +1,50 @@ +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/check-doc-alias-attr-location.rs:22:12 + | +LL | fn foo(#[doc(alias = "qux")] _x: u32) -> Self::X { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on foreign module + --> $DIR/check-doc-alias-attr-location.rs:9:7 + | +LL | #[doc(alias = "foo")] + | ^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on implementation block + --> $DIR/check-doc-alias-attr-location.rs:12:7 + | +LL | #[doc(alias = "bar")] + | ^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on implementation block + --> $DIR/check-doc-alias-attr-location.rs:18:7 + | +LL | #[doc(alias = "foobar")] + | ^^^^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block + --> $DIR/check-doc-alias-attr-location.rs:20:11 + | +LL | #[doc(alias = "assoc")] + | ^^^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on statement + --> $DIR/check-doc-alias-attr-location.rs:24:15 + | +LL | #[doc(alias = "stmt")] + | ^^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on expression + --> $DIR/check-doc-alias-attr-location.rs:26:15 + | +LL | #[doc(alias = "expr")] + | ^^^^^^^^^^^^^^ + +error: `#[doc(alias = "...")]` isn't allowed on match arm + --> $DIR/check-doc-alias-attr-location.rs:28:19 + | +LL | #[doc(alias = "arm")] + | ^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rustdoc/check-doc-alias-attr.rs b/tests/ui/rustdoc/check-doc-alias-attr.rs new file mode 100644 index 000000000..719b98604 --- /dev/null +++ b/tests/ui/rustdoc/check-doc-alias-attr.rs @@ -0,0 +1,28 @@ +#![crate_type = "lib"] + +#[doc(alias = "foo")] // ok! +#[doc(alias("bar", "baz"))] // ok! +pub struct Bar; + +#[doc(alias)] //~ ERROR +#[doc(alias = 0)] //~ ERROR +#[doc(alias = "\"")] //~ ERROR +#[doc(alias = "\n")] //~ ERROR +#[doc(alias = " +")] //~^ ERROR +#[doc(alias = "\t")] //~ ERROR +#[doc(alias = " hello")] //~ ERROR +#[doc(alias = "hello ")] //~ ERROR +#[doc(alias = "")] //~ ERROR +pub struct Foo; + +#[doc(alias(0))] //~ ERROR +#[doc(alias("\""))] //~ ERROR +#[doc(alias("\n"))] //~ ERROR +#[doc(alias(" +"))] //~^ ERROR +#[doc(alias("\t"))] //~ ERROR +#[doc(alias(" hello"))] //~ ERROR +#[doc(alias("hello "))] //~ ERROR +#[doc(alias(""))] //~ ERROR +pub struct Foo2; diff --git a/tests/ui/rustdoc/check-doc-alias-attr.stderr b/tests/ui/rustdoc/check-doc-alias-attr.stderr new file mode 100644 index 000000000..250568be3 --- /dev/null +++ b/tests/ui/rustdoc/check-doc-alias-attr.stderr @@ -0,0 +1,108 @@ +error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]` + --> $DIR/check-doc-alias-attr.rs:7:7 + | +LL | #[doc(alias)] + | ^^^^^ + +error: doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]` + --> $DIR/check-doc-alias-attr.rs:8:7 + | +LL | #[doc(alias = 0)] + | ^^^^^^^^^ + +error: '"' character isn't allowed in `#[doc(alias = "...")]` + --> $DIR/check-doc-alias-attr.rs:9:15 + | +LL | #[doc(alias = "\"")] + | ^^^^ + +error: '\n' character isn't allowed in `#[doc(alias = "...")]` + --> $DIR/check-doc-alias-attr.rs:10:15 + | +LL | #[doc(alias = "\n")] + | ^^^^ + +error: '\n' character isn't allowed in `#[doc(alias = "...")]` + --> $DIR/check-doc-alias-attr.rs:11:15 + | +LL | #[doc(alias = " + | _______________^ +LL | | ")] + | |_^ + +error: '\t' character isn't allowed in `#[doc(alias = "...")]` + --> $DIR/check-doc-alias-attr.rs:13:15 + | +LL | #[doc(alias = "\t")] + | ^^^^ + +error: `#[doc(alias = "...")]` cannot start or end with ' ' + --> $DIR/check-doc-alias-attr.rs:14:15 + | +LL | #[doc(alias = " hello")] + | ^^^^^^^^ + +error: `#[doc(alias = "...")]` cannot start or end with ' ' + --> $DIR/check-doc-alias-attr.rs:15:15 + | +LL | #[doc(alias = "hello ")] + | ^^^^^^^^ + +error: `#[doc(alias = "...")]` attribute cannot have empty value + --> $DIR/check-doc-alias-attr.rs:16:15 + | +LL | #[doc(alias = "")] + | ^^ + +error: `#[doc(alias("a"))]` expects string literals + --> $DIR/check-doc-alias-attr.rs:19:13 + | +LL | #[doc(alias(0))] + | ^ + +error: '"' character isn't allowed in `#[doc(alias("..."))]` + --> $DIR/check-doc-alias-attr.rs:20:13 + | +LL | #[doc(alias("\""))] + | ^^^^ + +error: '\n' character isn't allowed in `#[doc(alias("..."))]` + --> $DIR/check-doc-alias-attr.rs:21:13 + | +LL | #[doc(alias("\n"))] + | ^^^^ + +error: '\n' character isn't allowed in `#[doc(alias("..."))]` + --> $DIR/check-doc-alias-attr.rs:22:13 + | +LL | #[doc(alias(" + | _____________^ +LL | | "))] + | |_^ + +error: '\t' character isn't allowed in `#[doc(alias("..."))]` + --> $DIR/check-doc-alias-attr.rs:24:13 + | +LL | #[doc(alias("\t"))] + | ^^^^ + +error: `#[doc(alias("..."))]` cannot start or end with ' ' + --> $DIR/check-doc-alias-attr.rs:25:13 + | +LL | #[doc(alias(" hello"))] + | ^^^^^^^^ + +error: `#[doc(alias("..."))]` cannot start or end with ' ' + --> $DIR/check-doc-alias-attr.rs:26:13 + | +LL | #[doc(alias("hello "))] + | ^^^^^^^^ + +error: `#[doc(alias("..."))]` attribute cannot have empty value + --> $DIR/check-doc-alias-attr.rs:27:13 + | +LL | #[doc(alias(""))] + | ^^ + +error: aborting due to 17 previous errors + diff --git a/tests/ui/rustdoc/deny-invalid-doc-attrs.rs b/tests/ui/rustdoc/deny-invalid-doc-attrs.rs new file mode 100644 index 000000000..02e9c6791 --- /dev/null +++ b/tests/ui/rustdoc/deny-invalid-doc-attrs.rs @@ -0,0 +1,7 @@ +#![deny(invalid_doc_attributes)] +//~^ NOTE defined here +#![doc(x)] +//~^ ERROR unknown `doc` attribute `x` +//~| WARNING will become a hard error +//~| NOTE see issue #82730 +fn main() {} diff --git a/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr b/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr new file mode 100644 index 000000000..e9a4c1dd5 --- /dev/null +++ b/tests/ui/rustdoc/deny-invalid-doc-attrs.stderr @@ -0,0 +1,16 @@ +error: unknown `doc` attribute `x` + --> $DIR/deny-invalid-doc-attrs.rs:3:8 + | +LL | #![doc(x)] + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 +note: the lint level is defined here + --> $DIR/deny-invalid-doc-attrs.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rustdoc/doc-alias-crate-level.rs b/tests/ui/rustdoc/doc-alias-crate-level.rs new file mode 100644 index 000000000..c7783aae5 --- /dev/null +++ b/tests/ui/rustdoc/doc-alias-crate-level.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zdeduplicate-diagnostics=no + +#![crate_type = "lib"] + +#![doc(alias = "not working!")] //~ ERROR + +#[doc(alias = "shouldn't work!")] //~ ERROR +pub struct Foo; diff --git a/tests/ui/rustdoc/doc-alias-crate-level.stderr b/tests/ui/rustdoc/doc-alias-crate-level.stderr new file mode 100644 index 000000000..bd32609ad --- /dev/null +++ b/tests/ui/rustdoc/doc-alias-crate-level.stderr @@ -0,0 +1,14 @@ +error: '\'' character isn't allowed in `#[doc(alias = "...")]` + --> $DIR/doc-alias-crate-level.rs:7:15 + | +LL | #[doc(alias = "shouldn't work!")] + | ^^^^^^^^^^^^^^^^^ + +error: `#![doc(alias = "...")]` isn't allowed as a crate-level attribute + --> $DIR/doc-alias-crate-level.rs:5:8 + | +LL | #![doc(alias = "not working!")] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rustdoc/doc-alias-same-name.rs b/tests/ui/rustdoc/doc-alias-same-name.rs new file mode 100644 index 000000000..da97c2676 --- /dev/null +++ b/tests/ui/rustdoc/doc-alias-same-name.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +#[doc(alias = "Foo")] //~ ERROR +pub struct Foo; diff --git a/tests/ui/rustdoc/doc-alias-same-name.stderr b/tests/ui/rustdoc/doc-alias-same-name.stderr new file mode 100644 index 000000000..5ba09a2ea --- /dev/null +++ b/tests/ui/rustdoc/doc-alias-same-name.stderr @@ -0,0 +1,8 @@ +error: `#[doc(alias = "...")]` is the same as the item's name + --> $DIR/doc-alias-same-name.rs:3:7 + | +LL | #[doc(alias = "Foo")] + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rustdoc/doc-inline-extern-crate.rs b/tests/ui/rustdoc/doc-inline-extern-crate.rs new file mode 100644 index 000000000..0eb4c1490 --- /dev/null +++ b/tests/ui/rustdoc/doc-inline-extern-crate.rs @@ -0,0 +1,9 @@ +#[doc(inline)] +//~^ ERROR conflicting +#[doc(no_inline)] +pub extern crate core; + +// no warning +pub extern crate alloc; + +fn main() {} diff --git a/tests/ui/rustdoc/doc-inline-extern-crate.stderr b/tests/ui/rustdoc/doc-inline-extern-crate.stderr new file mode 100644 index 000000000..41518295b --- /dev/null +++ b/tests/ui/rustdoc/doc-inline-extern-crate.stderr @@ -0,0 +1,13 @@ +error: conflicting doc inlining attributes + --> $DIR/doc-inline-extern-crate.rs:1:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +LL | +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +error: aborting due to previous error + diff --git a/tests/ui/rustdoc/doc-test-attr-pass.rs b/tests/ui/rustdoc/doc-test-attr-pass.rs new file mode 100644 index 000000000..7884addd1 --- /dev/null +++ b/tests/ui/rustdoc/doc-test-attr-pass.rs @@ -0,0 +1,9 @@ +// check-pass + +#![crate_type = "lib"] +#![deny(invalid_doc_attributes)] +#![doc(test(no_crate_inject))] +#![doc(test(attr(deny(warnings))))] +#![doc(test())] + +pub fn foo() {} diff --git a/tests/ui/rustdoc/doc-test-attr.rs b/tests/ui/rustdoc/doc-test-attr.rs new file mode 100644 index 000000000..46178ad86 --- /dev/null +++ b/tests/ui/rustdoc/doc-test-attr.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![deny(invalid_doc_attributes)] + +#![doc(test)] +//~^ ERROR `#[doc(test(...)]` takes a list of attributes +//~^^ WARN this was previously accepted by the compiler +#![doc(test = "hello")] +//~^ ERROR `#[doc(test(...)]` takes a list of attributes +//~^^ WARN this was previously accepted by the compiler +#![doc(test(a))] +//~^ ERROR unknown `doc(test)` attribute `a` +//~^^ WARN this was previously accepted by the compiler + +pub fn foo() {} diff --git a/tests/ui/rustdoc/doc-test-attr.stderr b/tests/ui/rustdoc/doc-test-attr.stderr new file mode 100644 index 000000000..5e6014954 --- /dev/null +++ b/tests/ui/rustdoc/doc-test-attr.stderr @@ -0,0 +1,34 @@ +error: `#[doc(test(...)]` takes a list of attributes + --> $DIR/doc-test-attr.rs:4:8 + | +LL | #![doc(test)] + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 +note: the lint level is defined here + --> $DIR/doc-test-attr.rs:2:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[doc(test(...)]` takes a list of attributes + --> $DIR/doc-test-attr.rs:7:8 + | +LL | #![doc(test = "hello")] + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: unknown `doc(test)` attribute `a` + --> $DIR/doc-test-attr.rs:10:13 + | +LL | #![doc(test(a))] + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rustdoc/doc_keyword.rs b/tests/ui/rustdoc/doc_keyword.rs new file mode 100644 index 000000000..68a8802b2 --- /dev/null +++ b/tests/ui/rustdoc/doc_keyword.rs @@ -0,0 +1,20 @@ +#![crate_type = "lib"] +#![feature(rustdoc_internals)] + +#![doc(keyword = "hello")] //~ ERROR + +#[doc(keyword = "hell")] //~ ERROR +mod foo { + fn hell() {} +} + +#[doc(keyword = "hall")] //~ ERROR +fn foo() {} + + +// Regression test for the ICE described in #83512. +trait Foo { + #[doc(keyword = "match")] + //~^ ERROR: `#[doc(keyword = "...")]` should be used on modules + fn quux() {} +} diff --git a/tests/ui/rustdoc/doc_keyword.stderr b/tests/ui/rustdoc/doc_keyword.stderr new file mode 100644 index 000000000..a1d0e4ffc --- /dev/null +++ b/tests/ui/rustdoc/doc_keyword.stderr @@ -0,0 +1,26 @@ +error: `#[doc(keyword = "...")]` should be used on empty modules + --> $DIR/doc_keyword.rs:6:7 + | +LL | #[doc(keyword = "hell")] + | ^^^^^^^^^^^^^^^^ + +error: `#[doc(keyword = "...")]` should be used on modules + --> $DIR/doc_keyword.rs:11:7 + | +LL | #[doc(keyword = "hall")] + | ^^^^^^^^^^^^^^^^ + +error: `#[doc(keyword = "...")]` should be used on modules + --> $DIR/doc_keyword.rs:17:11 + | +LL | #[doc(keyword = "match")] + | ^^^^^^^^^^^^^^^^^ + +error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute + --> $DIR/doc_keyword.rs:4:8 + | +LL | #![doc(keyword = "hello")] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/rustdoc/duplicate_doc_alias.rs b/tests/ui/rustdoc/duplicate_doc_alias.rs new file mode 100644 index 000000000..a564ab645 --- /dev/null +++ b/tests/ui/rustdoc/duplicate_doc_alias.rs @@ -0,0 +1,9 @@ +#![deny(unused_attributes)] + +#[doc(alias = "A")] +#[doc(alias = "A")] //~ ERROR +#[doc(alias = "B")] +#[doc(alias("B"))] //~ ERROR +pub struct Foo; + +fn main() {} diff --git a/tests/ui/rustdoc/duplicate_doc_alias.stderr b/tests/ui/rustdoc/duplicate_doc_alias.stderr new file mode 100644 index 000000000..4b2dd1f8e --- /dev/null +++ b/tests/ui/rustdoc/duplicate_doc_alias.stderr @@ -0,0 +1,24 @@ +error: doc alias is duplicated + --> $DIR/duplicate_doc_alias.rs:4:7 + | +LL | #[doc(alias = "A")] + | ----------- first defined here +LL | #[doc(alias = "A")] + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/duplicate_doc_alias.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: doc alias is duplicated + --> $DIR/duplicate_doc_alias.rs:6:13 + | +LL | #[doc(alias = "B")] + | ----------- first defined here +LL | #[doc(alias("B"))] + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rustdoc/feature-gate-doc_primitive.rs b/tests/ui/rustdoc/feature-gate-doc_primitive.rs new file mode 100644 index 000000000..18e99e72f --- /dev/null +++ b/tests/ui/rustdoc/feature-gate-doc_primitive.rs @@ -0,0 +1,8 @@ +// check-pass +#[doc(primitive = "usize")] +//~^ WARNING `doc(primitive)` should never have been stable +//~| WARNING hard error in a future release +/// Some docs +mod usize {} + +fn main() {} diff --git a/tests/ui/rustdoc/feature-gate-doc_primitive.stderr b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr new file mode 100644 index 000000000..194b2d87d --- /dev/null +++ b/tests/ui/rustdoc/feature-gate-doc_primitive.stderr @@ -0,0 +1,12 @@ +warning: `doc(primitive)` should never have been stable + --> $DIR/feature-gate-doc_primitive.rs:2:7 + | +LL | #[doc(primitive = "usize")] + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82730 + = note: `#[warn(invalid_doc_attributes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rustdoc/hidden-doc-associated-item.rs b/tests/ui/rustdoc/hidden-doc-associated-item.rs new file mode 100644 index 000000000..d431f9e89 --- /dev/null +++ b/tests/ui/rustdoc/hidden-doc-associated-item.rs @@ -0,0 +1,15 @@ +// check-pass +// See issue #85526. +// This test should produce no warnings. + +#![deny(missing_docs)] +//! Crate docs + +#[doc(hidden)] +pub struct Foo; + +impl Foo { + pub fn bar() {} +} + +fn main() {} diff --git a/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs b/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs new file mode 100644 index 000000000..739c624d0 --- /dev/null +++ b/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs @@ -0,0 +1,5 @@ +#![feature(doc_keyword)] //~ ERROR +#![feature(doc_primitive)] //~ ERROR +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr b/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr new file mode 100644 index 000000000..d0979ce97 --- /dev/null +++ b/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr @@ -0,0 +1,19 @@ +error[E0557]: feature has been removed + --> $DIR/renamed-features-rustdoc_internals.rs:1:12 + | +LL | #![feature(doc_keyword)] + | ^^^^^^^^^^^ feature has been removed + | + = note: merged into `#![feature(rustdoc_internals)]` + +error[E0557]: feature has been removed + --> $DIR/renamed-features-rustdoc_internals.rs:2:12 + | +LL | #![feature(doc_primitive)] + | ^^^^^^^^^^^^^ feature has been removed + | + = note: merged into `#![feature(rustdoc_internals)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/rustdoc/unterminated-doc-comment.rs b/tests/ui/rustdoc/unterminated-doc-comment.rs new file mode 100644 index 000000000..82546fe73 --- /dev/null +++ b/tests/ui/rustdoc/unterminated-doc-comment.rs @@ -0,0 +1 @@ +/*! //~ ERROR E0758 diff --git a/tests/ui/rustdoc/unterminated-doc-comment.stderr b/tests/ui/rustdoc/unterminated-doc-comment.stderr new file mode 100644 index 000000000..2d5e53797 --- /dev/null +++ b/tests/ui/rustdoc/unterminated-doc-comment.stderr @@ -0,0 +1,9 @@ +error[E0758]: unterminated block doc-comment + --> $DIR/unterminated-doc-comment.rs:1:1 + | +LL | /*! + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0758`. diff --git a/tests/ui/sanitize/address.rs b/tests/ui/sanitize/address.rs new file mode 100644 index 000000000..5b2cea875 --- /dev/null +++ b/tests/ui/sanitize/address.rs @@ -0,0 +1,18 @@ +// needs-sanitizer-support +// needs-sanitizer-address +// +// compile-flags: -Z sanitizer=address -O -g +// +// run-fail +// error-pattern: AddressSanitizer: stack-buffer-overflow +// error-pattern: 'xs' (line 13) <== Memory access at offset + +use std::hint::black_box; + +fn main() { + let xs = [0, 1, 2, 3]; + // Avoid optimizing everything out. + let xs = black_box(xs.as_ptr()); + let code = unsafe { *xs.offset(4) }; + std::process::exit(code); +} diff --git a/tests/ui/sanitize/badfree.rs b/tests/ui/sanitize/badfree.rs new file mode 100644 index 000000000..095a6f469 --- /dev/null +++ b/tests/ui/sanitize/badfree.rs @@ -0,0 +1,19 @@ +// needs-sanitizer-support +// needs-sanitizer-address +// +// compile-flags: -Z sanitizer=address -O +// +// run-fail +// error-pattern: AddressSanitizer: SEGV + +use std::ffi::c_void; + +extern "C" { + fn free(ptr: *mut c_void); +} + +fn main() { + unsafe { + free(1 as *mut c_void); + } +} diff --git a/tests/ui/sanitize/cfg.rs b/tests/ui/sanitize/cfg.rs new file mode 100644 index 000000000..79dfe58f0 --- /dev/null +++ b/tests/ui/sanitize/cfg.rs @@ -0,0 +1,28 @@ +// Verifies that when compiling with -Zsanitizer=option, +// the `#[cfg(sanitize = "option")]` attribute is configured. + +// needs-sanitizer-support +// needs-sanitizer-address +// needs-sanitizer-leak +// needs-sanitizer-memory +// needs-sanitizer-thread +// check-pass +// revisions: address leak memory thread +//[address]compile-flags: -Zsanitizer=address --cfg address +//[leak]compile-flags: -Zsanitizer=leak --cfg leak +//[memory]compile-flags: -Zsanitizer=memory --cfg memory +//[thread]compile-flags: -Zsanitizer=thread --cfg thread + +#![feature(cfg_sanitize)] + +#[cfg(all(sanitize = "address", address))] +fn main() {} + +#[cfg(all(sanitize = "leak", leak))] +fn main() {} + +#[cfg(all(sanitize = "memory", memory))] +fn main() {} + +#[cfg(all(sanitize = "thread", thread))] +fn main() {} diff --git a/tests/ui/sanitize/crt-static.rs b/tests/ui/sanitize/crt-static.rs new file mode 100644 index 000000000..7a6b9eda3 --- /dev/null +++ b/tests/ui/sanitize/crt-static.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z sanitizer=address -C target-feature=+crt-static --target x86_64-unknown-linux-gnu +// needs-llvm-components: x86 + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/sanitize/crt-static.stderr b/tests/ui/sanitize/crt-static.stderr new file mode 100644 index 000000000..9f74235fe --- /dev/null +++ b/tests/ui/sanitize/crt-static.stderr @@ -0,0 +1,4 @@ +error: sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` + +error: aborting due to previous error + diff --git a/tests/ui/sanitize/hwaddress.rs b/tests/ui/sanitize/hwaddress.rs new file mode 100644 index 000000000..f9b37a155 --- /dev/null +++ b/tests/ui/sanitize/hwaddress.rs @@ -0,0 +1,21 @@ +// needs-sanitizer-support +// needs-sanitizer-hwaddress +// +// FIXME(#83706): this test triggers errors on aarch64-gnu +// ignore-aarch64-unknown-linux-gnu +// +// FIXME(#83989): codegen-units=1 triggers linker errors on aarch64-gnu +// compile-flags: -Z sanitizer=hwaddress -O -g -C codegen-units=16 +// +// run-fail +// error-pattern: HWAddressSanitizer: tag-mismatch + +use std::hint::black_box; + +fn main() { + let xs = vec![0, 1, 2, 3]; + // Avoid optimizing everything out. + let xs = black_box(xs.as_ptr()); + let code = unsafe { *xs.offset(4) }; + std::process::exit(code); +} diff --git a/tests/ui/sanitize/incompatible.rs b/tests/ui/sanitize/incompatible.rs new file mode 100644 index 000000000..bcafc2891 --- /dev/null +++ b/tests/ui/sanitize/incompatible.rs @@ -0,0 +1,7 @@ +// compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu +// needs-llvm-components: x86 +// error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/sanitize/incompatible.stderr b/tests/ui/sanitize/incompatible.stderr new file mode 100644 index 000000000..f86db41ba --- /dev/null +++ b/tests/ui/sanitize/incompatible.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory` + +error: aborting due to previous error + diff --git a/tests/ui/sanitize/inline-always.rs b/tests/ui/sanitize/inline-always.rs new file mode 100644 index 000000000..52dc55781 --- /dev/null +++ b/tests/ui/sanitize/inline-always.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(no_sanitize)] + +#[inline(always)] +//~^ NOTE inlining requested here +#[no_sanitize(address)] +//~^ WARN will have no effect after inlining +//~| NOTE on by default +fn x() { +} + +fn main() { + x() +} diff --git a/tests/ui/sanitize/inline-always.stderr b/tests/ui/sanitize/inline-always.stderr new file mode 100644 index 000000000..74fba3c0e --- /dev/null +++ b/tests/ui/sanitize/inline-always.stderr @@ -0,0 +1,15 @@ +warning: `no_sanitize` will have no effect after inlining + --> $DIR/inline-always.rs:7:1 + | +LL | #[no_sanitize(address)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: inlining requested here + --> $DIR/inline-always.rs:5:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[warn(inline_no_sanitize)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/sanitize/issue-72154-lifetime-markers.rs b/tests/ui/sanitize/issue-72154-lifetime-markers.rs new file mode 100644 index 000000000..b2e182238 --- /dev/null +++ b/tests/ui/sanitize/issue-72154-lifetime-markers.rs @@ -0,0 +1,31 @@ +// Regression test for issue 72154, where the use of AddressSanitizer enabled +// emission of lifetime markers during codegen, while at the same time asking +// always inliner pass not to insert them. This eventually lead to a +// miscompilation which was subsequently detected by AddressSanitizer as UB. +// +// needs-sanitizer-support +// needs-sanitizer-address +// +// compile-flags: -Copt-level=0 -Zsanitizer=address +// run-pass + +pub struct Wrap { + pub t: [usize; 1] +} + +impl Wrap { + #[inline(always)] + pub fn new(t: [usize; 1]) -> Self { + Wrap { t } + } +} + +#[inline(always)] +pub fn assume_init() -> [usize; 1] { + [1234] +} + +fn main() { + let x: [usize; 1] = assume_init(); + Wrap::new(x); +} diff --git a/tests/ui/sanitize/leak.rs b/tests/ui/sanitize/leak.rs new file mode 100644 index 000000000..cbb44ae8a --- /dev/null +++ b/tests/ui/sanitize/leak.rs @@ -0,0 +1,19 @@ +// needs-sanitizer-support +// needs-sanitizer-leak +// +// compile-flags: -Z sanitizer=leak -O +// +// run-fail +// error-pattern: LeakSanitizer: detected memory leaks + +use std::hint::black_box; +use std::mem; + +fn main() { + for _ in 0..10 { + let xs = vec![1, 2, 3]; + // Prevent compiler from removing the memory allocation. + let xs = black_box(xs); + mem::forget(xs); + } +} diff --git a/tests/ui/sanitize/memory-eager.rs b/tests/ui/sanitize/memory-eager.rs new file mode 100644 index 000000000..0018c2f75 --- /dev/null +++ b/tests/ui/sanitize/memory-eager.rs @@ -0,0 +1,37 @@ +// needs-sanitizer-support +// needs-sanitizer-memory +// min-llvm-version: 14.0.0 +// +// revisions: unoptimized optimized +// +// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O +// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins +// +// run-fail +// error-pattern: MemorySanitizer: use-of-uninitialized-value +// error-pattern: Uninitialized value was created by an allocation +// error-pattern: in the stack frame +// +// This test case intentionally limits the usage of the std, +// since it will be linked with an uninstrumented version of it. + +#![feature(core_intrinsics)] +#![feature(start)] + +use std::hint::black_box; +use std::mem::MaybeUninit; + +#[inline(never)] +#[no_mangle] +#[allow(invalid_value)] +fn random() -> char { + let r = unsafe { MaybeUninit::uninit().assume_init() }; + // Avoid optimizing everything out. + black_box(r) +} + +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + random(); + 0 +} diff --git a/tests/ui/sanitize/memory-passing.rs b/tests/ui/sanitize/memory-passing.rs new file mode 100644 index 000000000..6d9b70ad6 --- /dev/null +++ b/tests/ui/sanitize/memory-passing.rs @@ -0,0 +1,32 @@ +// needs-sanitizer-support +// needs-sanitizer-memory +// +// revisions: unoptimized optimized +// +// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O +// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins +// +// run-pass +// +// This test case intentionally limits the usage of the std, +// since it will be linked with an uninstrumented version of it. + +#![feature(core_intrinsics)] +#![feature(start)] +#![allow(invalid_value)] + +use std::hint::black_box; + +fn calling_black_box_on_zst_ok() { + // It's OK to call black_box on a value of a zero-sized type, even if its + // underlying the memory location is uninitialized. For non-zero-sized types, + // this would be an MSAN error. + let zst = (); + black_box(zst); +} + +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + calling_black_box_on_zst_ok(); + 0 +} diff --git a/tests/ui/sanitize/memory.rs b/tests/ui/sanitize/memory.rs new file mode 100644 index 000000000..1a9ac3a4f --- /dev/null +++ b/tests/ui/sanitize/memory.rs @@ -0,0 +1,46 @@ +// needs-sanitizer-support +// needs-sanitizer-memory +// +// revisions: unoptimized optimized +// +// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O +// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins +// +// run-fail +// error-pattern: MemorySanitizer: use-of-uninitialized-value +// error-pattern: Uninitialized value was created by an allocation +// error-pattern: in the stack frame +// +// This test case intentionally limits the usage of the std, +// since it will be linked with an uninstrumented version of it. + +#![feature(core_intrinsics)] +#![feature(start)] +#![allow(invalid_value)] + +use std::hint::black_box; +use std::mem::MaybeUninit; + +#[inline(never)] +#[no_mangle] +fn random() -> [isize; 32] { + let r = MaybeUninit::uninit(); + // Avoid optimizing everything out. + unsafe { std::intrinsics::volatile_load(r.as_ptr()) } +} + +#[inline(never)] +#[no_mangle] +fn xor(a: &[isize]) -> isize { + let mut s = 0; + for i in 0..a.len() { + s = s ^ a[i]; + } + s +} + +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + let r = black_box(random as fn() -> [isize; 32])(); + xor(&r) +} diff --git a/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs new file mode 100644 index 000000000..33e18e355 --- /dev/null +++ b/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -0,0 +1,26 @@ +// Regression test for sanitizer function instrumentation passes not +// being run when compiling with new LLVM pass manager and ThinLTO. +// Note: The issue occurred only on non-zero opt-level. +// +// needs-sanitizer-support +// needs-sanitizer-address +// +// no-prefer-dynamic +// revisions: opt0 opt1 +// compile-flags: -Zsanitizer=address -Clto=thin +//[opt0]compile-flags: -Copt-level=0 +//[opt1]compile-flags: -Copt-level=1 +// run-fail +// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope + +static mut P: *mut usize = std::ptr::null_mut(); + +fn main() { + unsafe { + { + let mut x = 0; + P = &mut x; + } + std::ptr::write_volatile(P, 123); + } +} diff --git a/tests/ui/sanitize/thread.rs b/tests/ui/sanitize/thread.rs new file mode 100644 index 000000000..c70cf5acc --- /dev/null +++ b/tests/ui/sanitize/thread.rs @@ -0,0 +1,57 @@ +// Verifies that ThreadSanitizer is able to detect a data race in heap allocated +// memory block. +// +// Test case minimizes the use of the standard library to avoid its ambiguous +// status with respect to instrumentation (it could vary depending on whatever +// a function call is inlined or not). +// +// The conflicting data access is de-facto synchronized with a special TSAN +// barrier, which does not introduce synchronization from TSAN perspective, but +// is necessary to make the test robust. Without the barrier data race detection +// would occasionally fail, making test flaky. +// +// needs-sanitizer-support +// needs-sanitizer-thread +// +// compile-flags: -Z sanitizer=thread -O +// +// run-fail +// error-pattern: WARNING: ThreadSanitizer: data race +// error-pattern: Location is heap block of size 4 +// error-pattern: allocated by main thread + +#![feature(raw_ref_op)] +#![feature(rustc_private)] +extern crate libc; + +use std::mem; +use std::ptr; + +static mut BARRIER: u64 = 0; + +extern "C" { + fn __tsan_testonly_barrier_init(barrier: *mut u64, count: u32); + fn __tsan_testonly_barrier_wait(barrier: *mut u64); +} + +extern "C" fn start(c: *mut libc::c_void) -> *mut libc::c_void { + unsafe { + let c: *mut u32 = c.cast(); + *c += 1; + __tsan_testonly_barrier_wait(&raw mut BARRIER); + ptr::null_mut() + } +} + +fn main() { + unsafe { + __tsan_testonly_barrier_init(&raw mut BARRIER, 2); + let c: *mut u32 = Box::into_raw(Box::new(1)); + let mut t: libc::pthread_t = mem::zeroed(); + libc::pthread_create(&mut t, ptr::null(), start, c.cast()); + __tsan_testonly_barrier_wait(&raw mut BARRIER); + *c += 1; + libc::pthread_join(t, ptr::null_mut()); + Box::from_raw(c); + } +} diff --git a/tests/ui/sanitize/unsupported-target.rs b/tests/ui/sanitize/unsupported-target.rs new file mode 100644 index 000000000..9f29c7635 --- /dev/null +++ b/tests/ui/sanitize/unsupported-target.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu +// needs-llvm-components: x86 +// error-pattern: error: leak sanitizer is not supported for this target +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/sanitize/unsupported-target.stderr b/tests/ui/sanitize/unsupported-target.stderr new file mode 100644 index 000000000..9bb840502 --- /dev/null +++ b/tests/ui/sanitize/unsupported-target.stderr @@ -0,0 +1,4 @@ +error: leak sanitizer is not supported for this target + +error: aborting due to previous error + diff --git a/tests/ui/sanitize/use-after-scope.rs b/tests/ui/sanitize/use-after-scope.rs new file mode 100644 index 000000000..30be2ae6f --- /dev/null +++ b/tests/ui/sanitize/use-after-scope.rs @@ -0,0 +1,18 @@ +// needs-sanitizer-support +// needs-sanitizer-address +// +// compile-flags: -Zsanitizer=address +// run-fail +// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope + +static mut P: *mut usize = std::ptr::null_mut(); + +fn main() { + unsafe { + { + let mut x = 0; + P = &mut x; + } + std::ptr::write_volatile(P, 123); + } +} diff --git a/tests/ui/save-analysis/emit-notifications.polonius.stderr b/tests/ui/save-analysis/emit-notifications.polonius.stderr new file mode 100644 index 000000000..a1a1b8c63 --- /dev/null +++ b/tests/ui/save-analysis/emit-notifications.polonius.stderr @@ -0,0 +1,2 @@ +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/save-analysis/libemit_notifications.json","emit":"save-analysis"} +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/libemit_notifications.rlib","emit":"link"} diff --git a/tests/ui/save-analysis/emit-notifications.rs b/tests/ui/save-analysis/emit-notifications.rs new file mode 100644 index 000000000..9179944a6 --- /dev/null +++ b/tests/ui/save-analysis/emit-notifications.rs @@ -0,0 +1,7 @@ +// build-pass (FIXME(62277): could be check-pass?) +// compile-flags: -Zsave-analysis --json artifacts +// compile-flags: --crate-type rlib --error-format=json +// ignore-pass +// ^-- needed because otherwise, the .stderr file changes with --pass check + +pub fn foo() {} diff --git a/tests/ui/save-analysis/emit-notifications.stderr b/tests/ui/save-analysis/emit-notifications.stderr new file mode 100644 index 000000000..e16f60f8b --- /dev/null +++ b/tests/ui/save-analysis/emit-notifications.stderr @@ -0,0 +1,2 @@ +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/save-analysis/libemit_notifications.json","emit":"save-analysis"} +{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/libemit_notifications.rlib","emit":"link"} diff --git a/tests/ui/save-analysis/issue-26459.rs b/tests/ui/save-analysis/issue-26459.rs new file mode 100644 index 000000000..2ba05a0a4 --- /dev/null +++ b/tests/ui/save-analysis/issue-26459.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zsave-analysis + +fn main() { + match 'a' { + char{ch} => true + //~^ ERROR expected struct, variant or union type, found builtin type `char` + }; +} diff --git a/tests/ui/save-analysis/issue-26459.stderr b/tests/ui/save-analysis/issue-26459.stderr new file mode 100644 index 000000000..9f594990c --- /dev/null +++ b/tests/ui/save-analysis/issue-26459.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found builtin type `char` + --> $DIR/issue-26459.rs:5:9 + | +LL | char{ch} => true + | ^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/save-analysis/issue-37323.rs b/tests/ui/save-analysis/issue-37323.rs new file mode 100644 index 000000000..55f5c5a95 --- /dev/null +++ b/tests/ui/save-analysis/issue-37323.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Zsave-analysis + +#![feature(rustc_attrs)] +#![allow(warnings)] + +#[derive(Debug)] +struct Point { +} + +struct NestedA<'a, 'b> { + x: &'a NestedB<'b> +} + +struct NestedB<'a> { + x: &'a i32, +} + +fn main() { +} diff --git a/tests/ui/save-analysis/issue-59134-0.rs b/tests/ui/save-analysis/issue-59134-0.rs new file mode 100644 index 000000000..a0871ca18 --- /dev/null +++ b/tests/ui/save-analysis/issue-59134-0.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zsave-analysis + +// Check that this doesn't ICE when processing associated const (field expr). + +pub fn f() { + trait Trait {} + impl dyn Trait { + const FLAG: u32 = bogus.field; //~ ERROR cannot find value `bogus` + } +} + +fn main() {} diff --git a/tests/ui/save-analysis/issue-59134-0.stderr b/tests/ui/save-analysis/issue-59134-0.stderr new file mode 100644 index 000000000..4e9b2e6fd --- /dev/null +++ b/tests/ui/save-analysis/issue-59134-0.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `bogus` in this scope + --> $DIR/issue-59134-0.rs:8:27 + | +LL | const FLAG: u32 = bogus.field; + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/save-analysis/issue-59134-1.rs b/tests/ui/save-analysis/issue-59134-1.rs new file mode 100644 index 000000000..3cb629777 --- /dev/null +++ b/tests/ui/save-analysis/issue-59134-1.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zsave-analysis + +// Check that this doesn't ICE when processing associated const (type). + +fn func() { + trait Trait { + type MyType; + const CONST: Self::MyType = bogus.field; //~ ERROR cannot find value `bogus` + } +} + +fn main() {} diff --git a/tests/ui/save-analysis/issue-59134-1.stderr b/tests/ui/save-analysis/issue-59134-1.stderr new file mode 100644 index 000000000..bdc335eaa --- /dev/null +++ b/tests/ui/save-analysis/issue-59134-1.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `bogus` in this scope + --> $DIR/issue-59134-1.rs:8:37 + | +LL | const CONST: Self::MyType = bogus.field; + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/save-analysis/issue-63663.rs b/tests/ui/save-analysis/issue-63663.rs new file mode 100644 index 000000000..92e85884f --- /dev/null +++ b/tests/ui/save-analysis/issue-63663.rs @@ -0,0 +1,28 @@ +// check-pass +// compile-flags: -Zsave-analysis + +pub trait Trait { + type Assoc; +} + +pub struct A; + +trait Generic {} +impl Generic for () {} + +// Don't ICE when resolving type paths in return type `impl Trait` +fn assoc_in_opaque_type_bounds() -> impl Generic {} + +// Check that this doesn't ICE when processing associated const in formal +// argument and return type of functions defined inside function/method scope. +pub fn func() { + fn _inner1(_: U::Assoc) {} + fn _inner2() -> U::Assoc { unimplemented!() } + + impl A { + fn _inner1(self, _: U::Assoc) {} + fn _inner2(self) -> U::Assoc { unimplemented!() } + } +} + +fn main() {} diff --git a/tests/ui/save-analysis/issue-64659.rs b/tests/ui/save-analysis/issue-64659.rs new file mode 100644 index 000000000..a3d88a203 --- /dev/null +++ b/tests/ui/save-analysis/issue-64659.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Zsave-analysis + +trait Trait { type Assoc; } + +fn main() { + struct Data { + x: T::Assoc, + } +} diff --git a/tests/ui/save-analysis/issue-65411.rs b/tests/ui/save-analysis/issue-65411.rs new file mode 100644 index 000000000..9e58b8da5 --- /dev/null +++ b/tests/ui/save-analysis/issue-65411.rs @@ -0,0 +1,15 @@ +// check-pass +// compile-flags: -Zsave-analysis + +trait Trait { type Assoc; } +trait GenericTrait {} +struct Wrapper { b: B } + +fn func() { + // Processing associated path in impl block definition inside a function + // body does not ICE + impl GenericTrait for Wrapper {} +} + + +fn main() {} diff --git a/tests/ui/save-analysis/issue-65590.rs b/tests/ui/save-analysis/issue-65590.rs new file mode 100644 index 000000000..27874f865 --- /dev/null +++ b/tests/ui/save-analysis/issue-65590.rs @@ -0,0 +1,21 @@ +// check-pass +// compile-flags: -Zsave-analysis +// edition:2018 + +// Async desugaring for return types in (associated) functions introduces a +// separate definition internally, which we need to take into account +// (or else we ICE). +trait Trait { type Assoc; } +struct Struct; + +async fn foobar() -> T::Assoc { + unimplemented!() +} + +impl Struct { + async fn foo(&self) -> T::Assoc { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/save-analysis/issue-68621.rs b/tests/ui/save-analysis/issue-68621.rs new file mode 100644 index 000000000..30479580f --- /dev/null +++ b/tests/ui/save-analysis/issue-68621.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zsave-analysis + +#![feature(type_alias_impl_trait)] + +trait Trait {} + +trait Service { + type Future: Trait; +} + +struct Struct; + +impl Service for Struct { + type Future = impl Trait; //~ ERROR: unconstrained opaque type +} + +fn main() {} diff --git a/tests/ui/save-analysis/issue-68621.stderr b/tests/ui/save-analysis/issue-68621.stderr new file mode 100644 index 000000000..4452ee791 --- /dev/null +++ b/tests/ui/save-analysis/issue-68621.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/issue-68621.rs:14:19 + | +LL | type Future = impl Trait; + | ^^^^^^^^^^ + | + = note: `Future` must be used in combination with a concrete type within the same impl + +error: aborting due to previous error + diff --git a/tests/ui/save-analysis/issue-72267.rs b/tests/ui/save-analysis/issue-72267.rs new file mode 100644 index 000000000..eea0a7fea --- /dev/null +++ b/tests/ui/save-analysis/issue-72267.rs @@ -0,0 +1,7 @@ +// compile-flags: -Z save-analysis + +fn main() { + let _: Box<(dyn ?Sized)>; + //~^ ERROR `?Trait` is not permitted in trait object types + //~| ERROR at least one trait is required for an object type +} diff --git a/tests/ui/save-analysis/issue-72267.stderr b/tests/ui/save-analysis/issue-72267.stderr new file mode 100644 index 000000000..76fc6c57c --- /dev/null +++ b/tests/ui/save-analysis/issue-72267.stderr @@ -0,0 +1,15 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/issue-72267.rs:4:21 + | +LL | let _: Box<(dyn ?Sized)>; + | ^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-72267.rs:4:17 + | +LL | let _: Box<(dyn ?Sized)>; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/save-analysis/issue-73020.rs b/tests/ui/save-analysis/issue-73020.rs new file mode 100644 index 000000000..87ce09336 --- /dev/null +++ b/tests/ui/save-analysis/issue-73020.rs @@ -0,0 +1,5 @@ +// compile-flags: -Zsave-analysis +use {self}; //~ ERROR E0431 + +fn main () { +} diff --git a/tests/ui/save-analysis/issue-73020.stderr b/tests/ui/save-analysis/issue-73020.stderr new file mode 100644 index 000000000..5bb3aae99 --- /dev/null +++ b/tests/ui/save-analysis/issue-73020.stderr @@ -0,0 +1,9 @@ +error[E0431]: `self` import can only appear in an import list with a non-empty prefix + --> $DIR/issue-73020.rs:2:6 + | +LL | use {self}; + | ^^^^ can only appear in an import list with a non-empty prefix + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0431`. diff --git a/tests/ui/save-analysis/issue-73022.rs b/tests/ui/save-analysis/issue-73022.rs new file mode 100644 index 000000000..9ad89a319 --- /dev/null +++ b/tests/ui/save-analysis/issue-73022.rs @@ -0,0 +1,13 @@ +// build-pass +// compile-flags: -Zsave-analysis +enum Enum2 { + Variant8 { _field: bool }, +} + +impl Enum2 { + fn new_variant8() -> Enum2 { + Self::Variant8 { _field: true } + } +} + +fn main() {} diff --git a/tests/ui/save-analysis/issue-89066.rs b/tests/ui/save-analysis/issue-89066.rs new file mode 100644 index 000000000..c65e2d73f --- /dev/null +++ b/tests/ui/save-analysis/issue-89066.rs @@ -0,0 +1,28 @@ +// compile-flags: -Zsave-analysis + +// Check that this does not ICE. +// Stolen from tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs + +#![feature(generic_arg_infer)] + +struct All<'a, T, const N: usize> { + v: &'a T, +} + +struct BadInfer<_>; +//~^ ERROR expected identifier +//~| ERROR parameter `_` is never used + +fn all_fn<'a, T, const N: usize>() {} + +fn bad_infer_fn<_>() {} +//~^ ERROR expected identifier + + +fn main() { + let a: All<_, _, _>; + //~^ ERROR this struct takes 2 generic arguments but 3 generic arguments were supplied + all_fn(); + let v: [u8; _]; + let v: [u8; 10] = [0; _]; +} diff --git a/tests/ui/save-analysis/issue-89066.stderr b/tests/ui/save-analysis/issue-89066.stderr new file mode 100644 index 000000000..5ef04936e --- /dev/null +++ b/tests/ui/save-analysis/issue-89066.stderr @@ -0,0 +1,39 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-89066.rs:12:17 + | +LL | struct BadInfer<_>; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/issue-89066.rs:18:17 + | +LL | fn bad_infer_fn<_>() {} + | ^ expected identifier, found reserved identifier + +error[E0392]: parameter `_` is never used + --> $DIR/issue-89066.rs:12:17 + | +LL | struct BadInfer<_>; + | ^ unused parameter + | + = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `_` to be a const parameter, use `const _: usize` instead + +error[E0107]: this struct takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/issue-89066.rs:23:10 + | +LL | let a: All<_, _, _>; + | ^^^ - help: remove this generic argument + | | + | expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `T`, `N` + --> $DIR/issue-89066.rs:8:8 + | +LL | struct All<'a, T, const N: usize> { + | ^^^ - -------------- + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0392. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr new file mode 100644 index 000000000..0ec0d4be5 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr @@ -0,0 +1,39 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:32 + | +LL | fn foo(self: &Rc) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + | +LL | fn foo(self: &Rc) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + = note: required for `Rc` to implement `CoerceUnsized>` + = note: required by cast to type `Rc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr new file mode 100644 index 000000000..b494b448e --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr @@ -0,0 +1,22 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + | +LL | fn foo(self: &Rc) -> usize; + | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn foo(self: &Rc) -> usize; + | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + = note: required for `Rc` to implement `CoerceUnsized>` + = note: required by cast to type `Rc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-not-object-safe.rs new file mode 100644 index 000000000..40e8df339 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.rs @@ -0,0 +1,44 @@ +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + +use std::rc::Rc; + +trait Foo { + fn foo(self: &Rc) -> usize; +} + +trait Bar { + fn foo(self: &Rc) -> usize where Self: Sized; + fn bar(self: Rc) -> usize; +} + +impl Foo for usize { + fn foo(self: &Rc) -> usize { + **self + } +} + +impl Bar for usize { + fn foo(self: &Rc) -> usize { + **self + } + + fn bar(self: Rc) -> usize { + *self + } +} + +fn make_foo() { + let x = Rc::new(5usize) as Rc; + //[curr]~^ ERROR E0038 + //[curr]~| ERROR E0038 + //[object_safe_for_dispatch]~^^^ ERROR E0038 +} + +fn make_bar() { + let x = Rc::new(5usize) as Rc; + x.bar(); +} + +fn main() {} diff --git a/tests/ui/self/arbitrary_self_types_nested.rs b/tests/ui/self/arbitrary_self_types_nested.rs new file mode 100644 index 000000000..680196fbb --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_nested.rs @@ -0,0 +1,36 @@ +// run-pass + +use { + std::{ + rc::Rc, + sync::Arc, + }, +}; + +#[derive(Default)] +struct Ty; + +trait Trait { + fn receive_trait(self: &Arc>>) -> u32; +} + +const TRAIT_MAGIC: u32 = 42; +const INHERENT_MAGIC: u32 = 1995; + +impl Trait for Ty { + fn receive_trait(self: &Arc>>) -> u32 { + TRAIT_MAGIC + } +} + +impl Ty { + fn receive_inherent(self: &Arc>>) -> u32 { + INHERENT_MAGIC + } +} + +fn main() { + let ty = >>>::default(); + assert_eq!(TRAIT_MAGIC, ty.receive_trait()); + assert_eq!(INHERENT_MAGIC, ty.receive_inherent()); +} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime-async.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime-async.rs new file mode 100644 index 000000000..f3474bc1f --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime-async.rs @@ -0,0 +1,35 @@ +// check-pass +// edition:2018 + +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct Foo; + +impl Foo { + async fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self } + + async fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self } + + async fn pin_pin_pin_ref(self: Pin>>) -> Pin>> { self } + + async fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias = Pin; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } +} + +// FIXME(Centril): extend with the rest of the non-`async fn` test +// when we allow `async fn`s inside traits and trait implementations. + +fn main() { + let mut foo = Foo; + { Pin::new(&foo).pin_ref() }; + { Pin::new(&mut foo).pin_mut() }; + { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() }; + { Pin::new(&foo).pin_ref_impl_trait() }; +} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime.rs new file mode 100644 index 000000000..300201388 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime.rs @@ -0,0 +1,60 @@ +// check-pass + +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct Foo; + +impl Foo { + fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self } + + fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self } + + fn pin_pin_pin_ref(self: Pin>>) -> Pin>> { self } + + fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias = Pin; +impl Foo { + fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } +} + +struct Bar { + field1: T, + field2: U, +} + +impl Bar { + fn fields(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) { + let this = self.get_mut(); + (Pin::new(&mut this.field1), Pin::new(&mut this.field2)) + } +} + +trait AsyncBufRead { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) + -> Poll>; +} + +struct Baz(Vec); + +impl AsyncBufRead for Baz { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) + -> Poll> + { + Poll::Ready(Ok(&self.get_mut().0)) + } +} + +fn main() { + let mut foo = Foo; + { Pin::new(&foo).pin_ref() }; + { Pin::new(&mut foo).pin_mut() }; + { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() }; + { Pin::new(&foo).pin_ref_impl_trait() }; + let mut bar = Bar { field1: 0u8, field2: 1u8 }; + { Pin::new(&mut bar).fields() }; +} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs new file mode 100644 index 000000000..a1e7f4aa8 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -0,0 +1,14 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR: captures lifetime that does not appear in bounds +} + +fn main() { + { Pin::new(&Foo).f() }; +} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr new file mode 100644 index 000000000..eb3d3e4a6 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `impl Clone` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ----- ^^^^^^^^ + | | + | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here + | +help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs new file mode 100644 index 000000000..4db2fa7dc --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs @@ -0,0 +1,12 @@ +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR: captures lifetime that does not appear in bounds +} + +fn main() { + { Pin::new(&Foo).f() }; +} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr new file mode 100644 index 000000000..2c0b2a0d9 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `impl Clone` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 + | +LL | fn f(self: Pin<&Self>) -> impl Clone { self } + | ----- ^^^^ + | | + | hidden type `Pin<&Foo>` captures the anonymous lifetime defined here + | +help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs new file mode 100644 index 000000000..a2b7f0805 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs @@ -0,0 +1,21 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + //~^ lifetime may not live long enough + + async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + //~^ lifetime may not live long enough +} + +type Alias = Pin; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + //~^ lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr new file mode 100644 index 000000000..6180e1e0f --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -0,0 +1,39 @@ +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75 + | +LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | -- - ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | | | + | | let's call the lifetime of this reference `'1` + | lifetime `'a` defined here + +error: aborting due to 3 previous errors + diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs new file mode 100644 index 000000000..f1a3fb018 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs @@ -0,0 +1,19 @@ +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + //~^ lifetime may not live long enough + + fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + //~^ lifetime may not live long enough +} + +type Alias = Pin; +impl Foo { + fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + //~^ lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr new file mode 100644 index 000000000..fccee5d43 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr @@ -0,0 +1,38 @@ +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46 + | +LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:9:69 + | +LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58 + | +LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | -- ---- has type `Pin<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | | + | lifetime `'a` defined here + +error: aborting due to 3 previous errors + diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs new file mode 100644 index 000000000..65fec3bec --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -0,0 +1,68 @@ +// run-pass +#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] +#![feature(rustc_attrs)] + +use std::{ + ops::{Deref, CoerceUnsized, DispatchFromDyn}, + marker::Unsize, +}; + +struct Ptr(Box); + +impl Deref for Ptr { + type Target = T; + + fn deref(&self) -> &T { + &*self.0 + } +} + +impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} +impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} + +struct Wrapper(T); + +impl Deref for Wrapper { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl, U> CoerceUnsized> for Wrapper {} +impl, U> DispatchFromDyn> for Wrapper {} + + +trait Trait { + // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable + // without unsized_locals), but wrappers arond `Self` currently are not. + // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented + // fn wrapper(self: Wrapper) -> i32; + fn ptr_wrapper(self: Ptr>) -> i32; + fn wrapper_ptr(self: Wrapper>) -> i32; + fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; +} + +impl Trait for i32 { + fn ptr_wrapper(self: Ptr>) -> i32 { + **self + } + fn wrapper_ptr(self: Wrapper>) -> i32 { + **self + } + fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32 { + ***self + } +} + +fn main() { + let pw = Ptr(Box::new(Wrapper(5))) as Ptr>; + assert_eq!(pw.ptr_wrapper(), 5); + + let wp = Wrapper(Ptr(Box::new(6))) as Wrapper>; + assert_eq!(wp.wrapper_ptr(), 6); + + let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper>>; + assert_eq!(wpw.wrapper_ptr_wrapper(), 7); +} diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs new file mode 100644 index 000000000..0eab7617f --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs @@ -0,0 +1,28 @@ +// run-pass +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +struct Foo(String); + +impl Foo { + unsafe fn foo(self: *const Self) -> *const str { + (*self).0.as_ref() + } + + fn complicated_1(self: *const Rc) -> &'static str { + "Foo::complicated_1" + } + + unsafe fn complicated_2(self: Rc<*const Self>) -> *const str { + (**self).0.as_ref() + } +} + +fn main() { + let foo = Foo("abc123".into()); + assert_eq!("abc123", unsafe { &*(&foo as *const Foo).foo() }); + assert_eq!("Foo::complicated_1", std::ptr::null::>().complicated_1()); + let rc = Rc::new(&foo as *const Foo); + assert_eq!("abc123", unsafe { &*rc.complicated_2()}); +} diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs new file mode 100644 index 000000000..0a9370e6f --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs @@ -0,0 +1,61 @@ +// run-pass +#![feature(arbitrary_self_types)] + +use std::ptr; + +trait Foo { + fn foo(self: *const Self) -> &'static str; + + unsafe fn bar(self: *const Self) -> i64; + + unsafe fn complicated(self: *const *const Self) -> i64 where Self: Sized { + (*self).bar() + } +} + +impl Foo for i32 { + fn foo(self: *const Self) -> &'static str { + "I'm an i32!" + } + + unsafe fn bar(self: *const Self) -> i64 { + *self as i64 + } +} + +impl Foo for u32 { + fn foo(self: *const Self) -> &'static str { + "I'm a u32!" + } + + unsafe fn bar(self: *const Self) -> i64 { + *self as i64 + } +} + +fn main() { + let null_i32 = ptr::null::() as *const dyn Foo; + let null_u32 = ptr::null::() as *const dyn Foo; + + assert_eq!("I'm an i32!", null_i32.foo()); + assert_eq!("I'm a u32!", null_u32.foo()); + + let valid_i32 = 5i32; + let valid_i32_thin = &valid_i32 as *const i32; + assert_eq!("I'm an i32!", valid_i32_thin.foo()); + assert_eq!(5, unsafe { valid_i32_thin.bar() }); + assert_eq!(5, unsafe { (&valid_i32_thin as *const *const i32).complicated() }); + let valid_i32_fat = valid_i32_thin as *const dyn Foo; + assert_eq!("I'm an i32!", valid_i32_fat.foo()); + assert_eq!(5, unsafe { valid_i32_fat.bar() }); + + let valid_u32 = 18u32; + let valid_u32_thin = &valid_u32 as *const u32; + assert_eq!("I'm a u32!", valid_u32_thin.foo()); + assert_eq!(18, unsafe { valid_u32_thin.bar() }); + assert_eq!(18, unsafe { (&valid_u32_thin as *const *const u32).complicated() }); + let valid_u32_fat = valid_u32_thin as *const dyn Foo; + assert_eq!("I'm a u32!", valid_u32_fat.foo()); + assert_eq!(18, unsafe { valid_u32_fat.bar() }); + +} diff --git a/tests/ui/self/arbitrary_self_types_silly.rs b/tests/ui/self/arbitrary_self_types_silly.rs new file mode 100644 index 000000000..fb5f9012b --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_silly.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(arbitrary_self_types)] + +struct Foo; +struct Bar; + +impl std::ops::Deref for Bar { + type Target = Foo; + + fn deref(&self) -> &Foo { + &Foo + } +} + +impl Foo { + fn bar(self: Bar) -> i32 { 3 } +} + +fn main() { + assert_eq!(3, Bar.bar()); +} diff --git a/tests/ui/self/arbitrary_self_types_stdlib_pointers.rs b/tests/ui/self/arbitrary_self_types_stdlib_pointers.rs new file mode 100644 index 000000000..29563fbbd --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_stdlib_pointers.rs @@ -0,0 +1,54 @@ +// run-pass +#![feature(arbitrary_self_types)] +#![feature(rustc_attrs)] + +use std::{ + rc::Rc, + sync::Arc, + pin::Pin, +}; + +trait Trait { + fn by_rc(self: Rc) -> i64; + fn by_arc(self: Arc) -> i64; + fn by_pin_mut(self: Pin<&mut Self>) -> i64; + fn by_pin_box(self: Pin>) -> i64; + fn by_pin_pin_pin_ref(self: Pin>>) -> i64; +} + +impl Trait for i64 { + fn by_rc(self: Rc) -> i64 { + *self + } + fn by_arc(self: Arc) -> i64 { + *self + } + fn by_pin_mut(self: Pin<&mut Self>) -> i64 { + *self + } + fn by_pin_box(self: Pin>) -> i64 { + *self + } + fn by_pin_pin_pin_ref(self: Pin>>) -> i64 { + *self + } +} + +fn main() { + let rc = Rc::new(1i64) as Rc; + assert_eq!(1, rc.by_rc()); + + let arc = Arc::new(2i64) as Arc; + assert_eq!(2, arc.by_arc()); + + let mut value = 3i64; + let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>; + assert_eq!(3, pin_mut.by_pin_mut()); + + let pin_box = Into::>>::into(Box::new(4i64)) as Pin>; + assert_eq!(4, pin_box.by_pin_box()); + + let value = 5i64; + let pin_pin_pin_ref = Pin::new(Pin::new(Pin::new(&value))) as Pin>>; + assert_eq!(5, pin_pin_pin_ref.by_pin_pin_pin_ref()); +} diff --git a/tests/ui/self/arbitrary_self_types_struct.rs b/tests/ui/self/arbitrary_self_types_struct.rs new file mode 100644 index 000000000..905ad83b6 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_struct.rs @@ -0,0 +1,24 @@ +// run-pass + +use std::rc::Rc; + +struct Foo { + x: i32, + y: i32, +} + +impl Foo { + fn x(self: &Rc) -> i32 { + self.x + } + + fn y(self: Rc) -> i32 { + self.y + } +} + +fn main() { + let foo = Rc::new(Foo {x: 3, y: 4}); + assert_eq!(3, foo.x()); + assert_eq!(4, foo.y()); +} diff --git a/tests/ui/self/arbitrary_self_types_trait.rs b/tests/ui/self/arbitrary_self_types_trait.rs new file mode 100644 index 000000000..973c7cae8 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_trait.rs @@ -0,0 +1,19 @@ +// run-pass + +use std::rc::Rc; + +trait Trait { + fn trait_method<'a>(self: &'a Box>) -> &'a [i32]; +} + +impl Trait for Vec { + fn trait_method<'a>(self: &'a Box>) -> &'a [i32] { + &***self + } +} + +fn main() { + let v = vec![1,2,3]; + + assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method()); +} diff --git a/tests/ui/self/arbitrary_self_types_unsized_struct.rs b/tests/ui/self/arbitrary_self_types_unsized_struct.rs new file mode 100644 index 000000000..d43f31328 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_unsized_struct.rs @@ -0,0 +1,16 @@ +// run-pass + +use std::rc::Rc; + +struct Foo(T); + +impl Foo<[u8]> { + fn len(self: Rc) -> usize { + self.0.len() + } +} + +fn main() { + let rc = Rc::new(Foo([1u8,2,3])) as Rc>; + assert_eq!(3, rc.len()); +} diff --git a/tests/ui/self/auxiliary/explicit_self_xcrate.rs b/tests/ui/self/auxiliary/explicit_self_xcrate.rs new file mode 100644 index 000000000..25cdfa909 --- /dev/null +++ b/tests/ui/self/auxiliary/explicit_self_xcrate.rs @@ -0,0 +1,15 @@ +pub trait Foo { + #[inline(always)] + fn f(&self); +} + +pub struct Bar { + pub x: String +} + +impl Foo for Bar { + #[inline(always)] + fn f(&self) { + println!("{}", (*self).x); + } +} diff --git a/tests/ui/self/builtin-superkinds-self-type.rs b/tests/ui/self/builtin-superkinds-self-type.rs new file mode 100644 index 000000000..c56542bb4 --- /dev/null +++ b/tests/ui/self/builtin-superkinds-self-type.rs @@ -0,0 +1,20 @@ +// run-pass +// Tests the ability for the Self type in default methods to use +// capabilities granted by builtin kinds as supertraits. + + +use std::sync::mpsc::{Sender, channel}; + +trait Foo : Send + Sized + 'static { + fn foo(self, tx: Sender) { + tx.send(self).unwrap(); + } +} + +impl Foo for T { } + +pub fn main() { + let (tx, rx) = channel(); + 1193182.foo(tx); + assert_eq!(rx.recv().unwrap(), 1193182); +} diff --git a/tests/ui/self/by-value-self-in-mut-slot.rs b/tests/ui/self/by-value-self-in-mut-slot.rs new file mode 100644 index 000000000..267afd1dc --- /dev/null +++ b/tests/ui/self/by-value-self-in-mut-slot.rs @@ -0,0 +1,22 @@ +// run-pass + +struct X { + a: isize +} + +trait Changer { + fn change(self) -> Self; +} + +impl Changer for X { + fn change(mut self) -> X { + self.a = 55; + self + } +} + +pub fn main() { + let x = X { a: 32 }; + let new_x = x.change(); + assert_eq!(new_x.a, 55); +} diff --git a/tests/ui/self/class-missing-self.rs b/tests/ui/self/class-missing-self.rs new file mode 100644 index 000000000..8ad347d20 --- /dev/null +++ b/tests/ui/self/class-missing-self.rs @@ -0,0 +1,16 @@ +struct Cat { + meows : usize, +} + +impl Cat { + fn sleep(&self) { loop{} } + fn meow(&self) { + println!("Meow"); + meows += 1; //~ ERROR cannot find value `meows` in this scope + sleep(); //~ ERROR cannot find function `sleep` in this + } + +} + + + fn main() { } diff --git a/tests/ui/self/class-missing-self.stderr b/tests/ui/self/class-missing-self.stderr new file mode 100644 index 000000000..063c3f013 --- /dev/null +++ b/tests/ui/self/class-missing-self.stderr @@ -0,0 +1,24 @@ +error[E0425]: cannot find value `meows` in this scope + --> $DIR/class-missing-self.rs:9:7 + | +LL | meows += 1; + | ^^^^^ help: you might have meant to use the available field: `self.meows` + +error[E0425]: cannot find function `sleep` in this scope + --> $DIR/class-missing-self.rs:10:7 + | +LL | sleep(); + | ^^^^^ not found in this scope + | +help: consider using the associated function + | +LL | self.sleep(); + | +++++ +help: consider importing this function + | +LL | use std::thread::sleep; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/self/elision/README.md b/tests/ui/self/elision/README.md new file mode 100644 index 000000000..3bd7a6c00 --- /dev/null +++ b/tests/ui/self/elision/README.md @@ -0,0 +1,75 @@ +Test cases intended to document behavior and try to exhaustively +explore the combinations. + +## Confidence + +These tests are not yet considered 100% normative, in that some +aspects of the current behavior are not desirable. This is expressed +in the "confidence" field in the following table. Values: + +| Confidence | Interpretation | +| --- | --- | +| 100% | this will remain recommended behavior | +| 75% | unclear whether we will continue to accept this | +| 50% | this will likely be deprecated but remain valid | +| 25% | this could change in the future | +| 0% | this is definitely bogus and will likely change in the future in *some* way | + +## Tests + +| Test file | `Self` type | Pattern | Current elision behavior | Confidence | +| --- | --- | --- | --- | --- | +| `self.rs` | `Struct` | `Self` | ignore `self` parameter | 100% | +| `struct.rs` | `Struct` | `Struct` | ignore `self` parameter | 100% | +| `alias.rs` | `Struct` | `Alias` | ignore `self` parameter | 100% | +| `ref-self.rs` | `Struct` | `&Self` | take lifetime from `&Self` | 100% | +| `ref-mut-self.rs` | `Struct` | `&mut Self` | take lifetime from `&mut Self` | 100% | +| `ref-struct.rs` | `Struct` | `&Struct` | take lifetime from `&Self` | 50% | +| `ref-mut-struct.rs` | `Struct` | `&mut Struct` | take lifetime from `&mut Self` | 50% | +| `ref-alias.rs` | `Struct` | `&Alias` | ignore `Alias` | 0% | +| `ref-mut-alias.rs` | `Struct` | `&mut Alias` | ignore `Alias` | 0% | +| `lt-self.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 25% | +| `lt-struct.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% | +| `lt-alias.rs` | `Alias<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% | +| `lt-ref-self.rs` | `Struct<'a>` | `&Self` | take lifetime from `&Self` | 75% | + +In each case, we test the following patterns: + +- `self: XXX` +- `self: Box` +- `self: Pin` +- `self: Box>` +- `self: Box>` + +In the non-reference cases, `Pin` causes errors so we substitute `Rc`. + +### `async fn` + +For each of the tests above we also check that `async fn` behaves as an `fn` would. +These tests are in files named `*-async.rs`. + +Legends: +- ✓ ⟹ Yes / Pass +- X ⟹ No +- α ⟹ lifetime mismatch +- β ⟹ cannot infer an appropriate lifetime +- γ ⟹ missing lifetime specifier + +| `async` file | Pass? | Conforms to `fn`? | How does it diverge?
`fn` ⟶ `async fn` | +| --- | --- | --- | --- | +| `self-async.rs` | ✓ | ✓ | N/A | +| `struct-async.rs`| ✓ | ✓ | N/A | +| `alias-async.rs`| ✓ | ✓ | N/A | +| `assoc-async.rs`| ✓ | ✓ | N/A | +| `ref-self-async.rs` | X | ✓ | N/A | +| `ref-mut-self-async.rs` | X | ✓ | N/A | +| `ref-struct-async.rs` | X | ✓ | N/A | +| `ref-mut-struct-async.rs` | X | ✓ | N/A | +| `ref-alias-async.rs` | ✓ | ✓ | N/A | +| `ref-assoc-async.rs` | ✓ | ✓ | N/A | +| `ref-mut-alias-async.rs` | ✓ | ✓ | N/A | +| `lt-self-async.rs` | ✓ | ✓ | N/A +| `lt-struct-async.rs` | ✓ | ✓ | N/A +| `lt-alias-async.rs` | ✓ | ✓ | N/A +| `lt-assoc-async.rs` | ✓ | ✓ | N/A +| `lt-ref-self-async.rs` | X | ✓ | N/A | diff --git a/tests/ui/self/elision/alias-async.rs b/tests/ui/self/elision/alias-async.rs new file mode 100644 index 000000000..7c0dd0686 --- /dev/null +++ b/tests/ui/self/elision/alias-async.rs @@ -0,0 +1,36 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn alias(self: Alias, f: &u32) -> &u32 { + f + } + + async fn box_Alias(self: Box, f: &u32) -> &u32 { + f + } + + async fn rc_Alias(self: Rc, f: &u32) -> &u32 { + f + } + + async fn box_box_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/alias.rs b/tests/ui/self/elision/alias.rs new file mode 100644 index 000000000..0c801d702 --- /dev/null +++ b/tests/ui/self/elision/alias.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + fn alias(self: Alias, f: &u32) -> &u32 { + f + } + + fn box_Alias(self: Box, f: &u32) -> &u32 { + f + } + + fn rc_Alias(self: Rc, f: &u32) -> &u32 { + f + } + + fn box_box_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + fn box_rc_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/assoc-async.rs b/tests/ui/self/elision/assoc-async.rs new file mode 100644 index 000000000..363b7fc2a --- /dev/null +++ b/tests/ui/self/elision/assoc-async.rs @@ -0,0 +1,40 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn assoc(self: ::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_AssocType(self: Box<::AssocType>, f: &u32) -> &u32 { + f + } + + async fn rc_AssocType(self: Rc<::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/assoc.rs b/tests/ui/self/elision/assoc.rs new file mode 100644 index 000000000..fa39a2b47 --- /dev/null +++ b/tests/ui/self/elision/assoc.rs @@ -0,0 +1,39 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + fn assoc(self: ::AssocType, f: &u32) -> &u32 { + f + } + + fn box_AssocType(self: Box<::AssocType>, f: &u32) -> &u32 { + f + } + + fn rc_AssocType(self: Rc<::AssocType>, f: &u32) -> &u32 { + f + } + + fn box_box_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } + + fn box_rc_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-alias-async.rs b/tests/ui/self/elision/lt-alias-async.rs new file mode 100644 index 000000000..3a6f8471e --- /dev/null +++ b/tests/ui/self/elision/lt-alias-async.rs @@ -0,0 +1,38 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +type Alias<'a> = Struct<'a>; + +impl<'a> Alias<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Alias(self: Box>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Alias(self: Rc>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Alias(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-alias.rs b/tests/ui/self/elision/lt-alias.rs new file mode 100644 index 000000000..bbba88e4e --- /dev/null +++ b/tests/ui/self/elision/lt-alias.rs @@ -0,0 +1,37 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +type Alias<'a> = Struct<'a>; + +impl<'a> Alias<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 { + f + } + + fn take_Box_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Alias(self: Box>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Alias(self: Rc>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Alias(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-assoc-async.rs b/tests/ui/self/elision/lt-assoc-async.rs new file mode 100644 index 000000000..0d3ff630d --- /dev/null +++ b/tests/ui/self/elision/lt-assoc-async.rs @@ -0,0 +1,50 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Trait for Struct<'a> { + type AssocType = Self; +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_AssocType(self: as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn take_Box_AssocType(self: Box< as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_AssocType( + self: Box as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } + + async fn take_Rc_AssocType(self: Rc< as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_AssocType( + self: Box as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-assoc.rs b/tests/ui/self/elision/lt-assoc.rs new file mode 100644 index 000000000..8f3543135 --- /dev/null +++ b/tests/ui/self/elision/lt-assoc.rs @@ -0,0 +1,43 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Trait for Struct<'a> { + type AssocType = Self; +} + +impl<'a> Struct<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_AssocType(self: as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + fn take_Box_AssocType(self: Box< as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_AssocType(self: Box as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_AssocType(self: Rc< as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_AssocType(self: Box as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-ref-self-async.rs b/tests/ui/self/elision/lt-ref-self-async.rs new file mode 100644 index 000000000..a2325ba7f --- /dev/null +++ b/tests/ui/self/elision/lt-ref-self-async.rs @@ -0,0 +1,45 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct<'a> { data: &'a u32 } + +impl<'a> Struct<'a> { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-ref-self-async.stderr b/tests/ui/self/elision/lt-ref-self-async.stderr new file mode 100644 index 000000000..787afd4dc --- /dev/null +++ b/tests/ui/self/elision/lt-ref-self-async.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:13:9 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:20:9 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:25:9 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:30:9 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:35:9 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:40:9 + | +LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/self/elision/lt-ref-self.rs b/tests/ui/self/elision/lt-ref-self.rs new file mode 100644 index 000000000..d37ed5acb --- /dev/null +++ b/tests/ui/self/elision/lt-ref-self.rs @@ -0,0 +1,43 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct<'a> { data: &'a u32 } + +impl<'a> Struct<'a> { + // Test using `&self` sugar: + + fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-ref-self.stderr b/tests/ui/self/elision/lt-ref-self.stderr new file mode 100644 index 000000000..49af638e4 --- /dev/null +++ b/tests/ui/self/elision/lt-ref-self.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:11:9 + | +LL | fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:18:9 + | +LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:23:9 + | +LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:28:9 + | +LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:33:9 + | +LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/lt-ref-self.rs:38:9 + | +LL | fn box_pin_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/self/elision/lt-self-async.rs b/tests/ui/self/elision/lt-self-async.rs new file mode 100644 index 000000000..4cedaf79d --- /dev/null +++ b/tests/ui/self/elision/lt-self-async.rs @@ -0,0 +1,49 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; +use std::rc::Rc; + +struct Struct<'a> { + x: &'a u32 +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box>, f: &u32) -> &u32 { + f + } + + // N/A + //fn take_Pin_Self(self: Pin, f: &u32) -> &u32 { + // f + //} + + // N/A + //fn take_Box_Pin_Self(self: Box>, f: &u32) -> &u32 { + // f + //} +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-self.rs b/tests/ui/self/elision/lt-self.rs new file mode 100644 index 000000000..cf74f892b --- /dev/null +++ b/tests/ui/self/elision/lt-self.rs @@ -0,0 +1,48 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; +use std::rc::Rc; + +struct Struct<'a> { + x: &'a u32 +} + +impl<'a> Struct<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + fn take_Box_Self(self: Box, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Self(self: Box>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Self(self: Rc, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Self(self: Box>, f: &u32) -> &u32 { + f + } + + // N/A + //fn take_Pin_Self(self: Pin, f: &u32) -> &u32 { + // f + //} + + // N/A + //fn take_Box_Pin_Self(self: Box>, f: &u32) -> &u32 { + // f + //} +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-struct-async.rs b/tests/ui/self/elision/lt-struct-async.rs new file mode 100644 index 000000000..abbee7fdf --- /dev/null +++ b/tests/ui/self/elision/lt-struct-async.rs @@ -0,0 +1,36 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Struct(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Struct(self: Box>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Struct(self: Rc>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Struct(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/lt-struct.rs b/tests/ui/self/elision/lt-struct.rs new file mode 100644 index 000000000..799c6c079 --- /dev/null +++ b/tests/ui/self/elision/lt-struct.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Struct<'a> { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 { + f + } + + fn take_Box_Struct(self: Box>, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Struct(self: Box>>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Struct(self: Rc>, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Struct(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/multiple-ref-self-async.rs b/tests/ui/self/elision/multiple-ref-self-async.rs new file mode 100644 index 000000000..be073c6ed --- /dev/null +++ b/tests/ui/self/elision/multiple-ref-self-async.rs @@ -0,0 +1,44 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap(T, PhantomData

); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using multiple `&Self`: + + async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { + f + } + + async fn box_wrap_ref_Self_ref_Self(self: Box>, f: &u32) -> &u32 { + f + } + + async fn pin_wrap_ref_Self_ref_Self(self: Pin>, f: &u32) -> &u32 { + f + } + + async fn box_box_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/multiple-ref-self.rs b/tests/ui/self/elision/multiple-ref-self.rs new file mode 100644 index 000000000..f39613d0c --- /dev/null +++ b/tests/ui/self/elision/multiple-ref-self.rs @@ -0,0 +1,43 @@ +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap(T, PhantomData

); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using multiple `&Self`: + + fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { + f + } + + fn box_wrap_ref_Self_ref_Self(self: Box>, f: &u32) -> &u32 { + f + } + + fn pin_wrap_ref_Self_ref_Self(self: Pin>, f: &u32) -> &u32 { + f + } + + fn box_box_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { + f + } + + fn box_pin_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-alias-async.rs b/tests/ui/self/elision/ref-alias-async.rs new file mode 100644 index 000000000..15f16525b --- /dev/null +++ b/tests/ui/self/elision/ref-alias-async.rs @@ -0,0 +1,39 @@ +// edition:2018 +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + // + // FIXME. We currently fail to recognize this as the self type, which + // feels like a bug. + + async fn ref_Alias(self: &Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-alias.rs b/tests/ui/self/elision/ref-alias.rs new file mode 100644 index 000000000..341f5b52d --- /dev/null +++ b/tests/ui/self/elision/ref-alias.rs @@ -0,0 +1,38 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + // + // FIXME. We currently fail to recognize this as the self type, which + // feels like a bug. + + fn ref_Alias(self: &Alias, f: &u32) -> &u32 { + f + } + + fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 { + f + } + + fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 { + f + } + + fn box_box_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + fn box_pin_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-assoc-async.rs b/tests/ui/self/elision/ref-assoc-async.rs new file mode 100644 index 000000000..ad10d8ba4 --- /dev/null +++ b/tests/ui/self/elision/ref-assoc-async.rs @@ -0,0 +1,40 @@ +// edition:2018 +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn ref_AssocType(self: &::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_ref_AssocType(self: Box<&::AssocType>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_AssocType(self: Pin<&::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-assoc.rs b/tests/ui/self/elision/ref-assoc.rs new file mode 100644 index 000000000..2f02cb5f3 --- /dev/null +++ b/tests/ui/self/elision/ref-assoc.rs @@ -0,0 +1,39 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + fn ref_AssocType(self: &::AssocType, f: &u32) -> &u32 { + f + } + + fn box_ref_AssocType(self: Box<&::AssocType>, f: &u32) -> &u32 { + f + } + + fn pin_ref_AssocType(self: Pin<&::AssocType>, f: &u32) -> &u32 { + f + } + + fn box_box_ref_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } + + fn box_pin_ref_AssocType(self: Box::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-alias-async.rs b/tests/ui/self/elision/ref-mut-alias-async.rs new file mode 100644 index 000000000..2c3f971d2 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-alias-async.rs @@ -0,0 +1,36 @@ +// edition:2018 +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-alias.rs b/tests/ui/self/elision/ref-mut-alias.rs new file mode 100644 index 000000000..ce1ab3ffc --- /dev/null +++ b/tests/ui/self/elision/ref-mut-alias.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 { + f + } + + fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 { + f + } + + fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 { + f + } + + fn box_box_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } + + fn box_pin_ref_Alias(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-self-async.rs b/tests/ui/self/elision/ref-mut-self-async.rs new file mode 100644 index 000000000..e07bc8564 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-self-async.rs @@ -0,0 +1,45 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut self` sugar: + + async fn ref_self(&mut self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&mut Self` explicitly: + + async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-self-async.stderr b/tests/ui/self/elision/ref-mut-self-async.stderr new file mode 100644 index 000000000..dff50aee9 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-self-async.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:13:9 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:20:9 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:25:9 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:30:9 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:35:9 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:40:9 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/self/elision/ref-mut-self.rs b/tests/ui/self/elision/ref-mut-self.rs new file mode 100644 index 000000000..bb82e6be7 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-self.rs @@ -0,0 +1,43 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut self` sugar: + + fn ref_self(&mut self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&mut Self` explicitly: + + fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-self.stderr b/tests/ui/self/elision/ref-mut-self.stderr new file mode 100644 index 000000000..ccf183016 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-self.stderr @@ -0,0 +1,92 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:11:9 + | +LL | fn ref_self(&mut self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:18:9 + | +LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:23:9 + | +LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:28:9 + | +LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:33:9 + | +LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-self.rs:38:9 + | +LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/self/elision/ref-mut-struct-async.rs b/tests/ui/self/elision/ref-mut-struct-async.rs new file mode 100644 index 000000000..392bf1d6b --- /dev/null +++ b/tests/ui/self/elision/ref-mut-struct-async.rs @@ -0,0 +1,38 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut Struct` explicitly: + + async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-struct-async.stderr b/tests/ui/self/elision/ref-mut-struct-async.stderr new file mode 100644 index 000000000..5b7ad026f --- /dev/null +++ b/tests/ui/self/elision/ref-mut-struct-async.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:13:9 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:18:9 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:23:9 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:28:9 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:33:9 + | +LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/self/elision/ref-mut-struct.rs b/tests/ui/self/elision/ref-mut-struct.rs new file mode 100644 index 000000000..ca8bd8da1 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-struct.rs @@ -0,0 +1,36 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut Struct` explicitly: + + fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-mut-struct.stderr b/tests/ui/self/elision/ref-mut-struct.stderr new file mode 100644 index 000000000..b9c71e843 --- /dev/null +++ b/tests/ui/self/elision/ref-mut-struct.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:11:9 + | +LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:16:9 + | +LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:21:9 + | +LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:26:9 + | +LL | fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct.rs:31:9 + | +LL | fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/self/elision/ref-self-async.rs b/tests/ui/self/elision/ref-self-async.rs new file mode 100644 index 000000000..b0133ec1b --- /dev/null +++ b/tests/ui/self/elision/ref-self-async.rs @@ -0,0 +1,60 @@ +// edition:2018 + +#![allow(non_snake_case)] +#![feature(arbitrary_self_types)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap(T, PhantomData

); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-self-async.stderr b/tests/ui/self/elision/ref-self-async.stderr new file mode 100644 index 000000000..26ef9779b --- /dev/null +++ b/tests/ui/self/elision/ref-self-async.stderr @@ -0,0 +1,107 @@ +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:23:9 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:30:9 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:35:9 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:40:9 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:45:9 + | +LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:50:9 + | +LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:55:9 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 { + | ++++ ++ ++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/self/elision/ref-self.rs b/tests/ui/self/elision/ref-self.rs new file mode 100644 index 000000000..dd07fe1b0 --- /dev/null +++ b/tests/ui/self/elision/ref-self.rs @@ -0,0 +1,58 @@ +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap(T, PhantomData

); + +impl Deref for Wrap { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using `&self` sugar: + + fn ref_self(&self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + // Test using `&Self` explicitly: + + fn ref_Self(self: &Self, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-self.stderr b/tests/ui/self/elision/ref-self.stderr new file mode 100644 index 000000000..32448f3a6 --- /dev/null +++ b/tests/ui/self/elision/ref-self.stderr @@ -0,0 +1,107 @@ +error: lifetime may not live long enough + --> $DIR/ref-self.rs:21:9 + | +LL | fn ref_self(&self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:28:9 + | +LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:33:9 + | +LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:38:9 + | +LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:43:9 + | +LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:48:9 + | +LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-self.rs:53:9 + | +LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 { + | ++++ ++ ++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/self/elision/ref-struct-async.rs b/tests/ui/self/elision/ref-struct-async.rs new file mode 100644 index 000000000..0be748745 --- /dev/null +++ b/tests/ui/self/elision/ref-struct-async.rs @@ -0,0 +1,38 @@ +// edition:2018 + +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&Struct` explicitly: + + async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-struct-async.stderr b/tests/ui/self/elision/ref-struct-async.stderr new file mode 100644 index 000000000..edb5c54ab --- /dev/null +++ b/tests/ui/self/elision/ref-struct-async.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:13:9 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:18:9 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:23:9 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:28:9 + | +LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:33:9 + | +LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | async fn box_pin_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/self/elision/ref-struct.rs b/tests/ui/self/elision/ref-struct.rs new file mode 100644 index 000000000..13a42cd1a --- /dev/null +++ b/tests/ui/self/elision/ref-struct.rs @@ -0,0 +1,36 @@ +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&Struct` explicitly: + + fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } + + fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + f + //~^ ERROR lifetime may not live long enough + } +} + +fn main() { } diff --git a/tests/ui/self/elision/ref-struct.stderr b/tests/ui/self/elision/ref-struct.stderr new file mode 100644 index 000000000..4492ed4aa --- /dev/null +++ b/tests/ui/self/elision/ref-struct.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:11:9 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:16:9 + | +LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:21:9 + | +LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:26:9 + | +LL | fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/ref-struct.rs:31:9 + | +LL | fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | f + | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter and update trait if needed + | +LL | fn box_pin_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { + | ++++ ++ ++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/self/elision/self-async.rs b/tests/ui/self/elision/self-async.rs new file mode 100644 index 000000000..eb01cfc97 --- /dev/null +++ b/tests/ui/self/elision/self-async.rs @@ -0,0 +1,36 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/self.rs b/tests/ui/self/elision/self.rs new file mode 100644 index 000000000..574b7e7c9 --- /dev/null +++ b/tests/ui/self/elision/self.rs @@ -0,0 +1,35 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + fn take_self(self, f: &u32) -> &u32 { + f + } + + fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + fn take_Box_Self(self: Box, f: &u32) -> &u32 { + f + } + + fn take_Box_Box_Self(self: Box>, f: &u32) -> &u32 { + f + } + + fn take_Rc_Self(self: Rc, f: &u32) -> &u32 { + f + } + + fn take_Box_Rc_Self(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/struct-async.rs b/tests/ui/self/elision/struct-async.rs new file mode 100644 index 000000000..e018e0daf --- /dev/null +++ b/tests/ui/self/elision/struct-async.rs @@ -0,0 +1,32 @@ +// check-pass +// edition:2018 + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn ref_Struct(self: Struct, f: &u32) -> &u32 { + f + } + + async fn box_Struct(self: Box, f: &u32) -> &u32 { + f + } + + async fn rc_Struct(self: Rc, f: &u32) -> &u32 { + f + } + + async fn box_box_Struct(self: Box>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Struct(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/elision/struct.rs b/tests/ui/self/elision/struct.rs new file mode 100644 index 000000000..d1ac99d13 --- /dev/null +++ b/tests/ui/self/elision/struct.rs @@ -0,0 +1,31 @@ +// check-pass + +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + fn ref_Struct(self: Struct, f: &u32) -> &u32 { + f + } + + fn box_Struct(self: Box, f: &u32) -> &u32 { + f + } + + fn rc_Struct(self: Rc, f: &u32) -> &u32 { + f + } + + fn box_box_Struct(self: Box>, f: &u32) -> &u32 { + f + } + + fn box_rc_Struct(self: Box>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/tests/ui/self/explicit-self-closures.rs b/tests/ui/self/explicit-self-closures.rs new file mode 100644 index 000000000..b409dfd7a --- /dev/null +++ b/tests/ui/self/explicit-self-closures.rs @@ -0,0 +1,17 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +// Test to make sure that explicit self params work inside closures + +// pretty-expanded FIXME #23616 + +struct Box { + x: usize +} + +impl Box { + pub fn set_many(&mut self, xs: &[usize]) { + for x in xs { self.x = *x; } + } +} + +pub fn main() {} diff --git a/tests/ui/self/explicit-self-generic.rs b/tests/ui/self/explicit-self-generic.rs new file mode 100644 index 000000000..8f6bed3b0 --- /dev/null +++ b/tests/ui/self/explicit-self-generic.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct LM { resize_at: usize, size: usize } + +enum HashMap { + HashMap_(LM, Vec<(K,V)>) +} + +fn linear_map() -> HashMap { + HashMap::HashMap_(LM{ + resize_at: 32, + size: 0}, Vec::new()) +} + +impl HashMap { + pub fn len(&mut self) -> usize { + match *self { + HashMap::HashMap_(ref l, _) => l.size + } + } +} + +pub fn main() { + let mut m: Box<_> = Box::new(linear_map::<(),()>()); + assert_eq!(m.len(), 0); +} diff --git a/tests/ui/self/explicit-self-objects-uniq.rs b/tests/ui/self/explicit-self-objects-uniq.rs new file mode 100644 index 000000000..250ea12e5 --- /dev/null +++ b/tests/ui/self/explicit-self-objects-uniq.rs @@ -0,0 +1,21 @@ +// run-pass + +trait Foo { + fn f(self: Box); +} + +struct S { + x: isize +} + +impl Foo for S { + fn f(self: Box) { + assert_eq!(self.x, 3); + } +} + +pub fn main() { + let x = Box::new(S { x: 3 }); + let y = x as Box; + y.f(); +} diff --git a/tests/ui/self/explicit-self.rs b/tests/ui/self/explicit-self.rs new file mode 100644 index 000000000..873c3621a --- /dev/null +++ b/tests/ui/self/explicit-self.rs @@ -0,0 +1,71 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +static tau: f64 = 2.0*3.14159265358979323; + +struct Point {x: f64, y: f64} +struct Size {w: f64, h: f64} +enum shape { + circle(Point, f64), + rectangle(Point, Size) +} + + +fn compute_area(shape: &shape) -> f64 { + match *shape { + shape::circle(_, radius) => 0.5 * tau * radius * radius, + shape::rectangle(_, ref size) => size.w * size.h + } +} + +impl shape { + // self is in the implicit self region + pub fn select<'r, T>(&self, threshold: f64, a: &'r T, b: &'r T) + -> &'r T { + if compute_area(self) > threshold {a} else {b} + } +} + +fn select_based_on_unit_circle<'r, T>( + threshold: f64, a: &'r T, b: &'r T) -> &'r T { + + let shape = &shape::circle(Point{x: 0.0, y: 0.0}, 1.0); + shape.select(threshold, a, b) +} + +#[derive(Clone)] +struct thing { + x: A +} + +#[derive(Clone)] +struct A { + a: isize +} + +fn thing(x: A) -> thing { + thing { + x: x + } +} + +impl thing { + pub fn bar(self: Box) -> isize { self.x.a } + pub fn quux(&self) -> isize { self.x.a } + pub fn baz<'a>(&'a self) -> &'a A { &self.x } + pub fn spam(self) -> isize { self.x.a } +} + +trait Nus { fn f(&self); } +impl Nus for thing { fn f(&self) {} } + +pub fn main() { + let y: Box<_> = Box::new(thing(A {a: 10})); + assert_eq!(y.clone().bar(), 10); + assert_eq!(y.quux(), 10); + + let z = thing(A {a: 11}); + assert_eq!(z.spam(), 11); +} diff --git a/tests/ui/self/explicit_self_xcrate_exe.rs b/tests/ui/self/explicit_self_xcrate_exe.rs new file mode 100644 index 000000000..c3796f73a --- /dev/null +++ b/tests/ui/self/explicit_self_xcrate_exe.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:explicit_self_xcrate.rs + +// pretty-expanded FIXME #23616 + +extern crate explicit_self_xcrate; +use explicit_self_xcrate::{Foo, Bar}; + +pub fn main() { + let x = Bar { x: "hello".to_string() }; + x.f(); +} diff --git a/tests/ui/self/issue-61882-2.rs b/tests/ui/self/issue-61882-2.rs new file mode 100644 index 000000000..1209b54bc --- /dev/null +++ b/tests/ui/self/issue-61882-2.rs @@ -0,0 +1,11 @@ +struct A(T); + +impl A<&'static u8> { + fn f() { + let x = 0; + Self(&x); + //~^ ERROR `x` does not live long enough + } +} + +fn main() {} diff --git a/tests/ui/self/issue-61882-2.stderr b/tests/ui/self/issue-61882-2.stderr new file mode 100644 index 000000000..0b8e134c9 --- /dev/null +++ b/tests/ui/self/issue-61882-2.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-61882-2.rs:6:14 + | +LL | Self(&x); + | ^^ + | | + | borrowed value does not live long enough + | this usage requires that `x` is borrowed for `'static` +LL | +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/self/issue-61882.rs b/tests/ui/self/issue-61882.rs new file mode 100644 index 000000000..013398b45 --- /dev/null +++ b/tests/ui/self/issue-61882.rs @@ -0,0 +1,9 @@ +struct A(T); + +impl A { + const B: A = Self(0); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/self/issue-61882.stderr b/tests/ui/self/issue-61882.stderr new file mode 100644 index 000000000..dd7194dc2 --- /dev/null +++ b/tests/ui/self/issue-61882.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:27 + | +LL | const B: A = Self(0); + | ---- ^ expected `bool`, found integer + | | + | arguments to this function are incorrect + | +note: tuple struct defined here + --> $DIR/issue-61882.rs:1:8 + | +LL | struct A(T); + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-61882.rs:4:22 + | +LL | const B: A = Self(0); + | ^^^^^^^ expected `u8`, found `bool` + | + = note: expected struct `A` + found struct `A` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/self/move-self.rs b/tests/ui/self/move-self.rs new file mode 100644 index 000000000..66032780b --- /dev/null +++ b/tests/ui/self/move-self.rs @@ -0,0 +1,19 @@ +// run-pass +struct S { + x: String +} + +impl S { + pub fn foo(self) { + self.bar(); + } + + pub fn bar(self) { + println!("{}", self.x); + } +} + +pub fn main() { + let x = S { x: "Hello!".to_string() }; + x.foo(); +} diff --git a/tests/ui/self/object-safety-sized-self-by-value-self.rs b/tests/ui/self/object-safety-sized-self-by-value-self.rs new file mode 100644 index 000000000..43b1d8b91 --- /dev/null +++ b/tests/ui/self/object-safety-sized-self-by-value-self.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_mut)] +// Check that a trait is still object-safe (and usable) if it has +// methods with by-value self so long as they require `Self : Sized`. + + +trait Counter { + fn tick(&mut self) -> u32; + fn get(self) -> u32 where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn get(self) -> u32 where Self : Sized { self.c } +} + +fn tick1(mut c: C) -> u32 { + tick2(&mut c); + c.get() +} + +fn tick2(c: &mut dyn Counter) { + tick3(c); +} + +fn tick3(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + let value = tick1(c); + assert_eq!(value, 2); +} diff --git a/tests/ui/self/object-safety-sized-self-generic-method.rs b/tests/ui/self/object-safety-sized-self-generic-method.rs new file mode 100644 index 000000000..e0b0526a3 --- /dev/null +++ b/tests/ui/self/object-safety-sized-self-generic-method.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_variables)] +// Check that a trait is still object-safe (and usable) if it has +// generic methods so long as they require `Self : Sized`. + + +trait Counter { + fn tick(&mut self) -> u32; + fn with(&self, f: F) where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn with(&self, f: F) { f(self.c); } +} + +fn tick1(c: &mut C) { + tick2(c); + c.with(|i| ()); +} + +fn tick2(c: &mut dyn Counter) { + tick3(c); +} + +fn tick3(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + tick1(&mut c); + assert_eq!(c.tick(), 3); +} diff --git a/tests/ui/self/object-safety-sized-self-return-Self.rs b/tests/ui/self/object-safety-sized-self-return-Self.rs new file mode 100644 index 000000000..222c75439 --- /dev/null +++ b/tests/ui/self/object-safety-sized-self-return-Self.rs @@ -0,0 +1,39 @@ +// run-pass +// Check that a trait is still object-safe (and usable) if it has +// methods that return `Self` so long as they require `Self : Sized`. + + +trait Counter { + fn new() -> Self where Self : Sized; + fn tick(&mut self) -> u32; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn new() -> CCounter { CCounter { c: 0 } } + fn tick(&mut self) -> u32 { self.c += 1; self.c } +} + +fn preticked() -> C { + let mut c: C = Counter::new(); + tick(&mut c); + c +} + +fn tick(c: &mut dyn Counter) { + tick_generic(c); +} + +fn tick_generic(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = preticked::(); + tick(&mut c); + assert_eq!(c.tick(), 5); +} diff --git a/tests/ui/self/objects-owned-object-owned-method.rs b/tests/ui/self/objects-owned-object-owned-method.rs new file mode 100644 index 000000000..15677a518 --- /dev/null +++ b/tests/ui/self/objects-owned-object-owned-method.rs @@ -0,0 +1,23 @@ +// run-pass +// Test invoked `&self` methods on owned objects where the values +// closed over contain managed values. This implies that the boxes +// will have headers that must be skipped over. + +trait FooTrait { + fn foo(self: Box) -> usize; +} + +struct BarStruct { + x: usize +} + +impl FooTrait for BarStruct { + fn foo(self: Box) -> usize { + self.x + } +} + +pub fn main() { + let foo = Box::new(BarStruct{ x: 22 }) as Box; + assert_eq!(22, foo.foo()); +} diff --git a/tests/ui/self/point-at-arbitrary-self-type-method.rs b/tests/ui/self/point-at-arbitrary-self-type-method.rs new file mode 100644 index 000000000..0f7deeaca --- /dev/null +++ b/tests/ui/self/point-at-arbitrary-self-type-method.rs @@ -0,0 +1,9 @@ +struct A; + +impl A { + fn foo(self: Box) {} +} + +fn main() { + A.foo(); //~ ERROR E0599 +} diff --git a/tests/ui/self/point-at-arbitrary-self-type-method.stderr b/tests/ui/self/point-at-arbitrary-self-type-method.stderr new file mode 100644 index 000000000..3c7cccfc9 --- /dev/null +++ b/tests/ui/self/point-at-arbitrary-self-type-method.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `foo` found for struct `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-method.rs:8:7 + | +LL | struct A; + | -------- method `foo` not found for this struct +... +LL | fn foo(self: Box) {} + | --- the method is available for `Box` here +... +LL | A.foo(); + | ^^^ method not found in `A` + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(A).foo(); + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/self/point-at-arbitrary-self-type-trait-method.rs b/tests/ui/self/point-at-arbitrary-self-type-trait-method.rs new file mode 100644 index 000000000..53d992771 --- /dev/null +++ b/tests/ui/self/point-at-arbitrary-self-type-trait-method.rs @@ -0,0 +1,10 @@ +trait B { fn foo(self: Box); } +struct A; + +impl B for A { + fn foo(self: Box) {} +} + +fn main() { + A.foo() //~ ERROR E0599 +} diff --git a/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr new file mode 100644 index 000000000..366c14f76 --- /dev/null +++ b/tests/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `foo` found for struct `A` in the current scope + --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 + | +LL | trait B { fn foo(self: Box); } + | --- --------- the method might not be found because of this arbitrary self type + | | + | the method is available for `Box` here +LL | struct A; + | -------- method `foo` not found for this struct +... +LL | A.foo() + | ^^^ method not found in `A` + | +help: consider wrapping the receiver expression with the appropriate type + | +LL | Box::new(A).foo() + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/self/self-impl-2.rs b/tests/ui/self/self-impl-2.rs new file mode 100644 index 000000000..7eed3f056 --- /dev/null +++ b/tests/ui/self/self-impl-2.rs @@ -0,0 +1,68 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that we can use `Self` types in impls in the expected way. + +// pretty-expanded FIXME #23616 + +struct Foo; + +// Test uses on inherent impl. +impl Foo { + fn foo(_x: Self, _y: &Self, _z: Box) -> Self { + Foo + } + + fn baz() { + // Test that Self cannot be shadowed. + type Foo = i32; + // There is no empty method on i32. + Self::empty(); + + let _: Self = Foo; + } + + fn empty() {} +} + +// Test uses when implementing a trait and with a type parameter. +pub struct Baz { + pub f: X, +} + +trait SuperBar { + type SuperQux; +} + +trait Bar: SuperBar { + type Qux; + + fn bar(x: Self, y: &Self, z: Box, _: Self::SuperQux) -> Self; + fn dummy(&self, x: X) { } +} + +impl SuperBar for Box> { + type SuperQux = bool; +} + +impl Bar for Box> { + type Qux = i32; + + fn bar(_x: Self, _y: &Self, _z: Box, _: Self::SuperQux) -> Self { + let _: Self::Qux = 42; + let _: >::Qux = 42; + + let _: Self::SuperQux = true; + let _: ::SuperQux = true; + + Box::new(Baz { f: 42 }) + } +} + +fn main() { + let _: Foo = Foo::foo(Foo, &Foo, Box::new(Foo)); + let _: Box> = Bar::bar(Box::new(Baz { f: 42 }), + &Box::new(Baz { f: 42 }), + Box::new(Box::new(Baz { f: 42 })), + true); +} diff --git a/tests/ui/self/self-impl.rs b/tests/ui/self/self-impl.rs new file mode 100644 index 000000000..ed250ce52 --- /dev/null +++ b/tests/ui/self/self-impl.rs @@ -0,0 +1,30 @@ +// Test that unsupported uses of `Self` in impls don't crash + +struct Bar; + +trait Foo { + type Baz; +} + +trait SuperFoo { + type SuperBaz; +} + +impl Foo for Bar { + type Baz = bool; +} + +impl SuperFoo for Bar { + type SuperBaz = bool; +} + +impl Bar { + fn f() { + let _: ::Baz = true; + //~^ ERROR ambiguous associated type + let _: Self::Baz = true; + //~^ ERROR ambiguous associated type + } +} + +fn main() {} diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr new file mode 100644 index 000000000..36372b644 --- /dev/null +++ b/tests/ui/self/self-impl.stderr @@ -0,0 +1,15 @@ +error[E0223]: ambiguous associated type + --> $DIR/self-impl.rs:23:16 + | +LL | let _: ::Baz = true; + | ^^^^^^^^^^^ help: use the fully-qualified path: `::Baz` + +error[E0223]: ambiguous associated type + --> $DIR/self-impl.rs:25:16 + | +LL | let _: Self::Baz = true; + | ^^^^^^^^^ help: use the fully-qualified path: `::Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/self/self-in-mut-slot-default-method.rs b/tests/ui/self/self-in-mut-slot-default-method.rs new file mode 100644 index 000000000..45e122c8d --- /dev/null +++ b/tests/ui/self/self-in-mut-slot-default-method.rs @@ -0,0 +1,35 @@ +// run-pass + +struct X { + a: isize +} + +trait Changer : Sized { + fn change(mut self) -> Self { + self.set_to(55); + self + } + + fn change_again(mut self: Box) -> Box { + self.set_to(45); + self + } + + fn set_to(&mut self, a: isize); +} + +impl Changer for X { + fn set_to(&mut self, a: isize) { + self.a = a; + } +} + +pub fn main() { + let x = X { a: 32 }; + let new_x = x.change(); + assert_eq!(new_x.a, 55); + + let x: Box<_> = Box::new(new_x); + let new_x = x.change_again(); + assert_eq!(new_x.a, 45); +} diff --git a/tests/ui/self/self-in-mut-slot-immediate-value.rs b/tests/ui/self/self-in-mut-slot-immediate-value.rs new file mode 100644 index 000000000..60865304f --- /dev/null +++ b/tests/ui/self/self-in-mut-slot-immediate-value.rs @@ -0,0 +1,23 @@ +// run-pass +// Assert that `mut self` on an immediate value doesn't +// allow mutating the original - issue #10615. + + +#[derive(Copy, Clone)] +struct Value { + n: isize +} + +impl Value { + fn squared(mut self) -> Value { + self.n *= self.n; + self + } +} + +pub fn main() { + let x = Value { n: 3 }; + let y = x.squared(); + assert_eq!(x.n, 3); + assert_eq!(y.n, 9); +} diff --git a/tests/ui/self/self-in-typedefs.rs b/tests/ui/self/self-in-typedefs.rs new file mode 100644 index 000000000..81e557d53 --- /dev/null +++ b/tests/ui/self/self-in-typedefs.rs @@ -0,0 +1,38 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] + +use std::mem::ManuallyDrop; + +enum A<'a, T: 'a> +where + Self: Send, T: PartialEq +{ + Foo(&'a Self), + Bar(T), +} + +struct B<'a, T: 'a> +where + Self: Send, T: PartialEq +{ + foo: &'a Self, + bar: T, +} + +union C<'a, T: 'a> +where + Self: Send, T: PartialEq +{ + foo: &'a Self, + bar: ManuallyDrop, +} + +union D<'a, T: 'a> +where + Self: Send, T: PartialEq + Copy +{ + foo: &'a Self, + bar: T, +} + +fn main() {} diff --git a/tests/ui/self/self-infer.rs b/tests/ui/self/self-infer.rs new file mode 100644 index 000000000..9839b8880 --- /dev/null +++ b/tests/ui/self/self-infer.rs @@ -0,0 +1,8 @@ +struct S; + +impl S { + fn f(self: _) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn g(self: &_) {} //~ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +fn main() {} diff --git a/tests/ui/self/self-infer.stderr b/tests/ui/self/self-infer.stderr new file mode 100644 index 000000000..4f9e3f21d --- /dev/null +++ b/tests/ui/self/self-infer.stderr @@ -0,0 +1,25 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/self-infer.rs:4:16 + | +LL | fn f(self: _) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn f(self: T) {} + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/self-infer.rs:5:17 + | +LL | fn g(self: &_) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn g(self: &T) {} + | +++ ~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/self/self-re-assign.rs b/tests/ui/self/self-re-assign.rs new file mode 100644 index 000000000..9595ebf96 --- /dev/null +++ b/tests/ui/self/self-re-assign.rs @@ -0,0 +1,17 @@ +// run-pass +// Ensure assigning an owned or managed variable to itself works. In particular, +// that we do not glue_drop before we glue_take (#3290). + +#![allow(dead_code)] + +use std::rc::Rc; + +pub fn main() { + let mut x: Box<_> = Box::new(3); + x = x; + assert_eq!(*x, 3); + + let mut x = Rc::new(3); + x = x; + assert_eq!(*x, 3); +} diff --git a/tests/ui/self/self-shadowing-import.rs b/tests/ui/self/self-shadowing-import.rs new file mode 100644 index 000000000..1d60c6c22 --- /dev/null +++ b/tests/ui/self/self-shadowing-import.rs @@ -0,0 +1,16 @@ +// run-pass + +mod a { + pub mod b { + pub mod a { + pub fn foo() -> isize { return 1; } + } + } +} + +mod c { + use a::b::a; + pub fn bar() { assert_eq!(a::foo(), 1); } +} + +pub fn main() { c::bar(); } diff --git a/tests/ui/self/self-type-param.rs b/tests/ui/self/self-type-param.rs new file mode 100644 index 000000000..5eb8c3622 --- /dev/null +++ b/tests/ui/self/self-type-param.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait MyTrait { + fn f(&self) -> Self; +} + +struct S { + x: isize +} + +impl MyTrait for S { + fn f(&self) -> S { + S { x: 3 } + } +} + +pub fn main() {} diff --git a/tests/ui/self/self-vs-path-ambiguity.rs b/tests/ui/self/self-vs-path-ambiguity.rs new file mode 100644 index 000000000..5a06d56c8 --- /dev/null +++ b/tests/ui/self/self-vs-path-ambiguity.rs @@ -0,0 +1,12 @@ +// Check that `self::foo` is parsed as a general pattern and not a self argument. + +struct S; + +impl S { + fn f(self::S: S) {} + fn g(&self::S: &S) {} + fn h(&mut self::S: &mut S) {} + fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern +} + +fn main() {} diff --git a/tests/ui/self/self-vs-path-ambiguity.stderr b/tests/ui/self/self-vs-path-ambiguity.stderr new file mode 100644 index 000000000..2beef50cd --- /dev/null +++ b/tests/ui/self/self-vs-path-ambiguity.stderr @@ -0,0 +1,8 @@ +error: unexpected lifetime `'a` in pattern + --> $DIR/self-vs-path-ambiguity.rs:9:11 + | +LL | fn i(&'a self::S: &S) {} + | ^^ help: remove the lifetime + +error: aborting due to previous error + diff --git a/tests/ui/self/self_lifetime-async.rs b/tests/ui/self/self_lifetime-async.rs new file mode 100644 index 000000000..c3c6e5658 --- /dev/null +++ b/tests/ui/self/self_lifetime-async.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } +} + +type Alias = Foo<'static>; +impl Alias { + async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } +} + +fn main() {} diff --git a/tests/ui/self/self_lifetime.rs b/tests/ui/self/self_lifetime.rs new file mode 100644 index 000000000..f04bd83ab --- /dev/null +++ b/tests/ui/self/self_lifetime.rs @@ -0,0 +1,15 @@ +// check-pass + +// https://github.com/rust-lang/rust/pull/60944#issuecomment-495346120 + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } +} + +type Alias = Foo<'static>; +impl Alias { + fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } +} + +fn main() {} diff --git a/tests/ui/self/self_type_keyword-2.rs b/tests/ui/self/self_type_keyword-2.rs new file mode 100644 index 000000000..cfb87f518 --- /dev/null +++ b/tests/ui/self/self_type_keyword-2.rs @@ -0,0 +1,13 @@ +use self::Self as Foo; //~ ERROR unresolved import `self::Self` + +pub fn main() { + let Self = 5; + //~^ ERROR cannot find unit struct, unit variant or constant `Self` in this scope + + match 15 { + Self => (), + //~^ ERROR cannot find unit struct, unit variant or constant `Self` in this scope + Foo { x: Self } => (), + //~^ ERROR cannot find unit struct, unit variant or constant `Self` in this scope + } +} diff --git a/tests/ui/self/self_type_keyword-2.stderr b/tests/ui/self/self_type_keyword-2.stderr new file mode 100644 index 000000000..4e931f91f --- /dev/null +++ b/tests/ui/self/self_type_keyword-2.stderr @@ -0,0 +1,28 @@ +error[E0432]: unresolved import `self::Self` + --> $DIR/self_type_keyword-2.rs:1:5 + | +LL | use self::Self as Foo; + | ^^^^^^^^^^^^^^^^^ no `Self` in the root + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword-2.rs:4:9 + | +LL | let Self = 5; + | ^^^^ not found in this scope + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword-2.rs:8:9 + | +LL | Self => (), + | ^^^^ not found in this scope + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword-2.rs:10:18 + | +LL | Foo { x: Self } => (), + | ^^^^ not found in this scope + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0531. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/self/self_type_keyword.rs b/tests/ui/self/self_type_keyword.rs new file mode 100644 index 000000000..b42bf8eea --- /dev/null +++ b/tests/ui/self/self_type_keyword.rs @@ -0,0 +1,41 @@ +mod foo { + struct Self; + //~^ ERROR expected identifier, found keyword `Self` +} + +struct Bar<'Self>; +//~^ ERROR lifetimes cannot use keyword names +//~| ERROR parameter `'Self` is never used + +struct Foo; + +pub fn main() { + match 15 { + ref Self => (), + //~^ ERROR expected identifier, found keyword `Self` + mut Self => (), + //~^ ERROR `mut` must be followed by a named binding + //~| ERROR cannot find unit struct, unit variant or constant `Self` + ref mut Self => (), + //~^ ERROR expected identifier, found keyword `Self` + Self!() => (), + //~^ ERROR cannot find macro `Self` in this scope + Foo { Self } => (), + //~^ ERROR expected identifier, found keyword `Self` + } +} + +mod m1 { + extern crate core as Self; + //~^ ERROR expected identifier, found keyword `Self` +} + +mod m2 { + use std::option::Option as Self; + //~^ ERROR expected identifier, found keyword `Self` +} + +mod m3 { + trait Self {} + //~^ ERROR expected identifier, found keyword `Self` +} diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr new file mode 100644 index 000000000..aca08d811 --- /dev/null +++ b/tests/ui/self/self_type_keyword.stderr @@ -0,0 +1,86 @@ +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:2:10 + | +LL | struct Self; + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:14:13 + | +LL | ref Self => (), + | ^^^^ expected identifier, found keyword + +error: `mut` must be followed by a named binding + --> $DIR/self_type_keyword.rs:16:9 + | +LL | mut Self => (), + | ^^^^^^^^ help: remove the `mut` prefix: `Self` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:19:17 + | +LL | ref mut Self => (), + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:23:15 + | +LL | Foo { Self } => (), + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:29:26 + | +LL | extern crate core as Self; + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:34:32 + | +LL | use std::option::Option as Self; + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:39:11 + | +LL | trait Self {} + | ^^^^ expected identifier, found keyword + +error: lifetimes cannot use keyword names + --> $DIR/self_type_keyword.rs:6:12 + | +LL | struct Bar<'Self>; + | ^^^^^ + +error: cannot find macro `Self` in this scope + --> $DIR/self_type_keyword.rs:21:9 + | +LL | Self!() => (), + | ^^^^ + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword.rs:16:13 + | +LL | mut Self => (), + | ^^^^ not found in this scope + | +note: unit struct `foo::Self` exists but is inaccessible + --> $DIR/self_type_keyword.rs:2:3 + | +LL | struct Self; + | ^^^^^^^^^^^^ not accessible + +error[E0392]: parameter `'Self` is never used + --> $DIR/self_type_keyword.rs:6:12 + | +LL | struct Bar<'Self>; + | ^^^^^ unused parameter + | + = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0392, E0531. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/self/string-self-append.rs b/tests/ui/self/string-self-append.rs new file mode 100644 index 000000000..e63dc0090 --- /dev/null +++ b/tests/ui/self/string-self-append.rs @@ -0,0 +1,14 @@ +// run-pass +pub fn main() { + // Make sure we properly handle repeated self-appends. + let mut a: String = "A".to_string(); + let mut i = 20; + let mut expected_len = 1; + while i > 0 { + println!("{}", a.len()); + assert_eq!(a.len(), expected_len); + a = format!("{}{}", a, a); + i -= 1; + expected_len *= 2; + } +} diff --git a/tests/ui/self/suggest-self-2.rs b/tests/ui/self/suggest-self-2.rs new file mode 100644 index 000000000..1e001827e --- /dev/null +++ b/tests/ui/self/suggest-self-2.rs @@ -0,0 +1,25 @@ +struct Foo {} + +impl Foo { + fn foo(&self) { + bar(self); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(&&self, 102); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(&mut self, 102, &"str"); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP try calling `bar` as a method + + bar(); + //~^ ERROR cannot find function `bar` in this scope + + self.bar(); + //~^ ERROR no method named `bar` found for reference + } +} + +fn main() {} diff --git a/tests/ui/self/suggest-self-2.stderr b/tests/ui/self/suggest-self-2.stderr new file mode 100644 index 000000000..4bd025ea0 --- /dev/null +++ b/tests/ui/self/suggest-self-2.stderr @@ -0,0 +1,40 @@ +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:5:9 + | +LL | bar(self); + | ^^^------ + | | + | help: try calling `bar` as a method: `self.bar()` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:9:9 + | +LL | bar(&&self, 102); + | ^^^------------- + | | + | help: try calling `bar` as a method: `self.bar(102)` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:13:9 + | +LL | bar(&mut self, 102, &"str"); + | ^^^------------------------ + | | + | help: try calling `bar` as a method: `self.bar(102, &"str")` + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/suggest-self-2.rs:17:9 + | +LL | bar(); + | ^^^ not found in this scope + +error[E0599]: no method named `bar` found for reference `&Foo` in the current scope + --> $DIR/suggest-self-2.rs:20:14 + | +LL | self.bar(); + | ^^^ method not found in `&Foo` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/self/suggest-self.rs b/tests/ui/self/suggest-self.rs new file mode 100644 index 000000000..1cc17116e --- /dev/null +++ b/tests/ui/self/suggest-self.rs @@ -0,0 +1,41 @@ +struct Foo { + x: i32, +} + +impl Foo { + fn this1(&self) -> i32 { + let this = self; + let a = 1; + this.x + } + + fn this2(&self) -> i32 { + let a = Foo { + x: 2 + }; + let this = a; + this.x + } + + fn foo(&self) -> i32 { + this.x + //~^ ERROR cannot find value `this` in this scope + } + + fn bar(&self) -> i32 { + this.foo() + //~^ ERROR cannot find value `this` in this scope + } + + fn baz(&self) -> i32 { + my.bar() + //~^ ERROR cannot find value `my` in this scope + } +} + +fn main() { + let this = vec![1, 2, 3]; + let my = vec![1, 2, 3]; + let len = this.len(); + let len = my.len(); +} diff --git a/tests/ui/self/suggest-self.stderr b/tests/ui/self/suggest-self.stderr new file mode 100644 index 000000000..0d38b9d87 --- /dev/null +++ b/tests/ui/self/suggest-self.stderr @@ -0,0 +1,30 @@ +error[E0425]: cannot find value `this` in this scope + --> $DIR/suggest-self.rs:21:9 + | +LL | this.x + | ^^^^ + | | + | not found in this scope + | help: you might have meant to use `self` here instead + +error[E0425]: cannot find value `this` in this scope + --> $DIR/suggest-self.rs:26:9 + | +LL | this.foo() + | ^^^^ + | | + | not found in this scope + | help: you might have meant to use `self` here instead + +error[E0425]: cannot find value `my` in this scope + --> $DIR/suggest-self.rs:31:9 + | +LL | my.bar() + | ^^ + | | + | not found in this scope + | help: you might have meant to use `self` here instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/self/ufcs-explicit-self.rs b/tests/ui/self/ufcs-explicit-self.rs new file mode 100644 index 000000000..d83af14d3 --- /dev/null +++ b/tests/ui/self/ufcs-explicit-self.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(dead_code)] + +#[derive(Copy, Clone)] +struct Foo { + f: isize, +} + +impl Foo { + fn foo(self: Foo, x: isize) -> isize { + self.f + x + } + fn bar(self: &Foo, x: isize) -> isize { + self.f + x + } + fn baz(self: Box, x: isize) -> isize { + self.f + x + } +} + +#[derive(Copy, Clone)] +struct Bar { + f: T, +} + +impl Bar { + fn foo(self: Bar, x: isize) -> isize { + x + } + fn bar<'a>(self: &'a Bar, x: isize) -> isize { + x + } + fn baz(self: Bar, x: isize) -> isize { + x + } +} + +fn main() { + let foo: Box<_> = Box::new(Foo { + f: 1, + }); + println!("{} {} {}", foo.foo(2), foo.bar(2), foo.baz(2)); + let bar: Box<_> = Box::new(Bar { + f: 1, + }); + println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); + let bar: Box> = bar; + println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2)); +} diff --git a/tests/ui/self/uniq-self-in-mut-slot.rs b/tests/ui/self/uniq-self-in-mut-slot.rs new file mode 100644 index 000000000..71e57d8c1 --- /dev/null +++ b/tests/ui/self/uniq-self-in-mut-slot.rs @@ -0,0 +1,22 @@ +// run-pass + +struct X { + a: isize +} + +trait Changer { + fn change(self: Box) -> Box; +} + +impl Changer for X { + fn change(mut self: Box) -> Box { + self.a = 55; + self + } +} + +pub fn main() { + let x: Box<_> = Box::new(X { a: 32 }); + let new_x = x.change(); + assert_eq!(new_x.a, 55); +} diff --git a/tests/ui/self/where-for-self.rs b/tests/ui/self/where-for-self.rs new file mode 100644 index 000000000..76c592dc4 --- /dev/null +++ b/tests/ui/self/where-for-self.rs @@ -0,0 +1,51 @@ +// run-pass +// Test that we can quantify lifetimes outside a constraint (i.e., including +// the self type) in a where clause. + + +static mut COUNT: u32 = 1; + +trait Bar<'a> { + fn bar(&self); +} + +trait Baz<'a> +{ + fn baz(&self); +} + +impl<'a, 'b> Bar<'b> for &'a u32 { + fn bar(&self) { + unsafe { COUNT *= 2; } + } +} + +impl<'a, 'b> Baz<'b> for &'a u32 { + fn baz(&self) { + unsafe { COUNT *= 3; } + } +} + +// Test we can use the syntax for HRL including the self type. +fn foo1(x: &T) + where for<'a, 'b> &'a T: Bar<'b> +{ + x.bar() +} + +// Test we can quantify multiple bounds (i.e., the precedence is sensible). +fn foo2(x: &T) + where for<'a, 'b> &'a T: Bar<'b> + Baz<'b> +{ + x.baz(); + x.bar() +} + +fn main() { + let x = 42; + foo1(&x); + foo2(&x); + unsafe { + assert_eq!(COUNT, 12); + } +} diff --git a/tests/ui/sepcomp/auxiliary/sepcomp-extern-lib.rs b/tests/ui/sepcomp/auxiliary/sepcomp-extern-lib.rs new file mode 100644 index 000000000..73fb5e8f3 --- /dev/null +++ b/tests/ui/sepcomp/auxiliary/sepcomp-extern-lib.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn foo() -> usize { + 1234 +} diff --git a/tests/ui/sepcomp/auxiliary/sepcomp_cci_lib.rs b/tests/ui/sepcomp/auxiliary/sepcomp_cci_lib.rs new file mode 100644 index 000000000..64e34a56d --- /dev/null +++ b/tests/ui/sepcomp/auxiliary/sepcomp_cci_lib.rs @@ -0,0 +1,6 @@ +#[inline] +pub fn cci_fn() -> usize { + 1200 +} + +pub const CCI_CONST: usize = 34; diff --git a/tests/ui/sepcomp/auxiliary/sepcomp_lib.rs b/tests/ui/sepcomp/auxiliary/sepcomp_lib.rs new file mode 100644 index 000000000..1536228c2 --- /dev/null +++ b/tests/ui/sepcomp/auxiliary/sepcomp_lib.rs @@ -0,0 +1,21 @@ +// compile-flags: -C codegen-units=3 --crate-type=rlib,dylib -g + +pub mod a { + pub fn one() -> usize { + 1 + } +} + +pub mod b { + pub fn two() -> usize { + 2 + } +} + +pub mod c { + use a::one; + use b::two; + pub fn three() -> usize { + one() + two() + } +} diff --git a/tests/ui/sepcomp/sepcomp-cci.rs b/tests/ui/sepcomp/sepcomp-cci.rs new file mode 100644 index 000000000..02bbab30e --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-cci.rs @@ -0,0 +1,33 @@ +// run-pass +// compile-flags: -C codegen-units=3 +// aux-build:sepcomp_cci_lib.rs + +// Test accessing cross-crate inlined items from multiple compilation units. + + +extern crate sepcomp_cci_lib; +use sepcomp_cci_lib::{cci_fn, CCI_CONST}; + +fn call1() -> usize { + cci_fn() + CCI_CONST +} + +mod a { + use sepcomp_cci_lib::{cci_fn, CCI_CONST}; + pub fn call2() -> usize { + cci_fn() + CCI_CONST + } +} + +mod b { + use sepcomp_cci_lib::{cci_fn, CCI_CONST}; + pub fn call3() -> usize { + cci_fn() + CCI_CONST + } +} + +fn main() { + assert_eq!(call1(), 1234); + assert_eq!(a::call2(), 1234); + assert_eq!(b::call3(), 1234); +} diff --git a/tests/ui/sepcomp/sepcomp-extern.rs b/tests/ui/sepcomp/sepcomp-extern.rs new file mode 100644 index 000000000..6323bf664 --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-extern.rs @@ -0,0 +1,33 @@ +// run-pass +// compile-flags: -C codegen-units=3 +// aux-build:sepcomp-extern-lib.rs + +// Test accessing external items from multiple compilation units. + +extern crate sepcomp_extern_lib; + +extern "C" { + fn foo() -> usize; +} + +fn call1() -> usize { + unsafe { foo() } +} + +mod a { + pub fn call2() -> usize { + unsafe { ::foo() } + } +} + +mod b { + pub fn call3() -> usize { + unsafe { ::foo() } + } +} + +fn main() { + assert_eq!(call1(), 1234); + assert_eq!(a::call2(), 1234); + assert_eq!(b::call3(), 1234); +} diff --git a/tests/ui/sepcomp/sepcomp-fns-backwards.rs b/tests/ui/sepcomp/sepcomp-fns-backwards.rs new file mode 100644 index 000000000..f56769e2b --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-fns-backwards.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: -C codegen-units=3 + +// Test references to items that haven't been codegened yet. + +// Generate some code in the first compilation unit before declaring any +// modules. This ensures that the first module doesn't go into the same +// compilation unit as the top-level module. + +fn pad() -> usize { 0 } + +mod b { + pub fn three() -> usize { + ::one() + ::a::two() + } +} + +mod a { + pub fn two() -> usize { + ::one() + ::one() + } +} + +fn one() -> usize { + 1 +} + +fn main() { + assert_eq!(one(), 1); + assert_eq!(a::two(), 2); + assert_eq!(b::three(), 3); +} diff --git a/tests/ui/sepcomp/sepcomp-fns.rs b/tests/ui/sepcomp/sepcomp-fns.rs new file mode 100644 index 000000000..a432c8960 --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-fns.rs @@ -0,0 +1,30 @@ +// run-pass +// compile-flags: -C codegen-units=3 + +// Test basic separate compilation functionality. The functions should be able +// to call each other even though they will be placed in different compilation +// units. + +// Generate some code in the first compilation unit before declaring any +// modules. This ensures that the first module doesn't go into the same +// compilation unit as the top-level module. + +fn one() -> usize { 1 } + +mod a { + pub fn two() -> usize { + ::one() + ::one() + } +} + +mod b { + pub fn three() -> usize { + ::one() + ::a::two() + } +} + +fn main() { + assert_eq!(one(), 1); + assert_eq!(a::two(), 2); + assert_eq!(b::three(), 3); +} diff --git a/tests/ui/sepcomp/sepcomp-lib-lto.rs b/tests/ui/sepcomp/sepcomp-lib-lto.rs new file mode 100644 index 000000000..51a572899 --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-lib-lto.rs @@ -0,0 +1,19 @@ +// run-pass +// Check that we can use `-C lto` when linking against libraries that were +// separately compiled. + +// aux-build:sepcomp_lib.rs +// compile-flags: -C lto -g +// ignore-asmjs wasm2js does not support source maps yet +// no-prefer-dynamic + +extern crate sepcomp_lib; +use sepcomp_lib::a::one; +use sepcomp_lib::b::two; +use sepcomp_lib::c::three; + +fn main() { + assert_eq!(one(), 1); + assert_eq!(two(), 2); + assert_eq!(three(), 3); +} diff --git a/tests/ui/sepcomp/sepcomp-lib.rs b/tests/ui/sepcomp/sepcomp-lib.rs new file mode 100644 index 000000000..728dc078b --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-lib.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:sepcomp_lib.rs + +// Test linking against a library built with -C codegen-units > 1 + + +extern crate sepcomp_lib; +use sepcomp_lib::a::one; +use sepcomp_lib::b::two; +use sepcomp_lib::c::three; + +fn main() { + assert_eq!(one(), 1); + assert_eq!(two(), 2); + assert_eq!(three(), 3); +} diff --git a/tests/ui/sepcomp/sepcomp-statics.rs b/tests/ui/sepcomp/sepcomp-statics.rs new file mode 100644 index 000000000..5457c8a0a --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-statics.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: -C codegen-units=3 + +// Test references to static items across compilation units. + + +fn pad() -> usize { 0 } + +const ONE: usize = 1; + +mod b { + // Separate compilation always switches to the LLVM module with the fewest + // instructions. Make sure we have some instructions in this module so + // that `a` and `b` don't go into the same compilation unit. + fn pad() -> usize { 0 } + + pub static THREE: usize = ::ONE + ::a::TWO; +} + +mod a { + fn pad() -> usize { 0 } + + pub const TWO: usize = ::ONE + ::ONE; +} + +fn main() { + assert_eq!(ONE, 1); + assert_eq!(a::TWO, 2); + assert_eq!(b::THREE, 3); +} diff --git a/tests/ui/sepcomp/sepcomp-unwind.rs b/tests/ui/sepcomp/sepcomp-unwind.rs new file mode 100644 index 000000000..a59e25a27 --- /dev/null +++ b/tests/ui/sepcomp/sepcomp-unwind.rs @@ -0,0 +1,35 @@ +// run-pass +// needs-unwind +#![allow(dead_code)] +// compile-flags: -C codegen-units=3 +// ignore-emscripten no threads support + +// Test unwinding through multiple compilation units. + +// According to acrichto, in the distant past `ld -r` (which is used during +// linking when codegen-units > 1) was known to produce object files with +// damaged unwinding tables. This may be related to GNU binutils bug #6893 +// ("Partial linking results in corrupt .eh_frame_hdr"), but I'm not certain. +// In any case, this test should let us know if enabling parallel codegen ever +// breaks unwinding. + + +use std::thread; + +fn pad() -> usize { 0 } + +mod a { + pub fn f() { + panic!(); + } +} + +mod b { + pub fn g() { + ::a::f(); + } +} + +fn main() { + thread::spawn(move|| { ::b::g() }).join().unwrap_err(); +} diff --git a/tests/ui/seq-args.rs b/tests/ui/seq-args.rs new file mode 100644 index 000000000..a5ebeecd3 --- /dev/null +++ b/tests/ui/seq-args.rs @@ -0,0 +1,13 @@ +fn main() { + trait Seq { } + + impl Seq for Vec { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + /* ... */ + } + + impl Seq for u32 { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + /* Treat the integer as a sequence of bits */ + } +} diff --git a/tests/ui/seq-args.stderr b/tests/ui/seq-args.stderr new file mode 100644 index 000000000..c404d9574 --- /dev/null +++ b/tests/ui/seq-args.stderr @@ -0,0 +1,31 @@ +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/seq-args.rs:4:13 + | +LL | impl Seq for Vec { + | ^^^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/seq-args.rs:2:11 + | +LL | trait Seq { } + | ^^^ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/seq-args.rs:9:10 + | +LL | impl Seq for u32 { + | ^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/seq-args.rs:2:11 + | +LL | trait Seq { } + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/shadow-bool.rs b/tests/ui/shadow-bool.rs new file mode 100644 index 000000000..f290a329e --- /dev/null +++ b/tests/ui/shadow-bool.rs @@ -0,0 +1,18 @@ +// check-pass + +mod bar { + pub trait QueryId { + const SOME_PROPERTY: bool; + } +} + +use bar::QueryId; + +#[allow(non_camel_case_types)] +pub struct bool; + +impl QueryId for bool { + const SOME_PROPERTY: core::primitive::bool = true; +} + +fn main() {} diff --git a/tests/ui/shadowed-use-visibility.rs b/tests/ui/shadowed-use-visibility.rs new file mode 100644 index 000000000..350fbfeae --- /dev/null +++ b/tests/ui/shadowed-use-visibility.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(unused_imports)] +mod foo { + pub fn f() {} + + pub use self::f as bar; + use foo as bar; +} + +fn main() { + foo::bar(); +} diff --git a/tests/ui/shadowed/shadowed-lifetime.rs b/tests/ui/shadowed/shadowed-lifetime.rs new file mode 100644 index 000000000..9487b4f4e --- /dev/null +++ b/tests/ui/shadowed/shadowed-lifetime.rs @@ -0,0 +1,24 @@ +// Test that shadowed lifetimes generate an error. + +struct Foo<'a>(&'a isize); + +impl<'a> Foo<'a> { + fn shadow_in_method<'a>(&'a self) -> &'a isize { + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope + self.0 + } + + fn shadow_in_type<'b>(&'b self) -> &'b isize { + let x: for<'b> fn(&'b isize) = panic!(); + //~^ ERROR lifetime name `'b` shadows a lifetime name that is already in scope + self.0 + } + + fn not_shadow_in_item<'b>(&'b self) { + struct Bar<'a, 'b>(&'a isize, &'b isize); // not a shadow, separate item + fn foo<'a, 'b>(x: &'a isize, y: &'b isize) { } // same + } +} + +fn main() { +} diff --git a/tests/ui/shadowed/shadowed-lifetime.stderr b/tests/ui/shadowed/shadowed-lifetime.stderr new file mode 100644 index 000000000..68cc505d3 --- /dev/null +++ b/tests/ui/shadowed/shadowed-lifetime.stderr @@ -0,0 +1,19 @@ +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowed-lifetime.rs:6:25 + | +LL | impl<'a> Foo<'a> { + | -- first declared here +LL | fn shadow_in_method<'a>(&'a self) -> &'a isize { + | ^^ lifetime `'a` already in scope + +error[E0496]: lifetime name `'b` shadows a lifetime name that is already in scope + --> $DIR/shadowed-lifetime.rs:12:20 + | +LL | fn shadow_in_type<'b>(&'b self) -> &'b isize { + | -- first declared here +LL | let x: for<'b> fn(&'b isize) = panic!(); + | ^^ lifetime `'b` already in scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0496`. diff --git a/tests/ui/shadowed/shadowed-trait-methods.rs b/tests/ui/shadowed/shadowed-trait-methods.rs new file mode 100644 index 000000000..f9c25d979 --- /dev/null +++ b/tests/ui/shadowed/shadowed-trait-methods.rs @@ -0,0 +1,14 @@ +// Test that methods from shadowed traits cannot be used + +mod foo { + pub trait T { fn f(&self) {} } + impl T for () {} +} + +mod bar { pub use foo::T; } + +fn main() { + pub use bar::*; + struct T; + ().f() //~ ERROR no method +} diff --git a/tests/ui/shadowed/shadowed-trait-methods.stderr b/tests/ui/shadowed/shadowed-trait-methods.stderr new file mode 100644 index 000000000..c3b9084af --- /dev/null +++ b/tests/ui/shadowed/shadowed-trait-methods.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `f` found for unit type `()` in the current scope + --> $DIR/shadowed-trait-methods.rs:13:8 + | +LL | pub trait T { fn f(&self) {} } + | - the method is available for `()` here +... +LL | ().f() + | ^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use foo::T; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/shadowed/shadowed-type-parameter.rs b/tests/ui/shadowed/shadowed-type-parameter.rs new file mode 100644 index 000000000..66fd68a9f --- /dev/null +++ b/tests/ui/shadowed/shadowed-type-parameter.rs @@ -0,0 +1,30 @@ +// Test that shadowed lifetimes generate an error. + + +struct Foo(T); + + +impl Foo { + fn shadow_in_method(&self) {} + //~^ ERROR the name `T` is already used + + fn not_shadow_in_item(&self) { + struct Bar(T,U); // not a shadow, separate item + fn foo() {} // same + } +} + +trait Bar { + fn dummy(&self) -> T; + + fn shadow_in_required(&self); + //~^ ERROR the name `T` is already used + + fn shadow_in_provided(&self) {} + //~^ ERROR the name `T` is already used + + fn not_shadow_in_required(&self); + fn not_shadow_in_provided(&self) {} +} + +fn main() {} diff --git a/tests/ui/shadowed/shadowed-type-parameter.stderr b/tests/ui/shadowed/shadowed-type-parameter.stderr new file mode 100644 index 000000000..0ea82f983 --- /dev/null +++ b/tests/ui/shadowed/shadowed-type-parameter.stderr @@ -0,0 +1,29 @@ +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed-type-parameter.rs:8:25 + | +LL | impl Foo { + | - first use of `T` +LL | fn shadow_in_method(&self) {} + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed-type-parameter.rs:20:27 + | +LL | trait Bar { + | - first use of `T` +... +LL | fn shadow_in_required(&self); + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed-type-parameter.rs:23:27 + | +LL | trait Bar { + | - first use of `T` +... +LL | fn shadow_in_provided(&self) {} + | ^ already used + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/shadowed/shadowed-use-visibility.rs b/tests/ui/shadowed/shadowed-use-visibility.rs new file mode 100644 index 000000000..6b801972f --- /dev/null +++ b/tests/ui/shadowed/shadowed-use-visibility.rs @@ -0,0 +1,16 @@ +mod foo { + pub fn f() {} + + use foo as bar; + pub use self::f as bar; +} + +mod bar { + use foo::bar::f as g; //~ ERROR module import `bar` is private + + use foo as f; + pub use foo::*; +} + +use bar::f::f; //~ ERROR module import `f` is private +fn main() {} diff --git a/tests/ui/shadowed/shadowed-use-visibility.stderr b/tests/ui/shadowed/shadowed-use-visibility.stderr new file mode 100644 index 000000000..1a642ae6e --- /dev/null +++ b/tests/ui/shadowed/shadowed-use-visibility.stderr @@ -0,0 +1,37 @@ +error[E0603]: module import `bar` is private + --> $DIR/shadowed-use-visibility.rs:9:14 + | +LL | use foo::bar::f as g; + | ^^^ private module import + | +note: the module import `bar` is defined here... + --> $DIR/shadowed-use-visibility.rs:4:9 + | +LL | use foo as bar; + | ^^^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/shadowed-use-visibility.rs:1:1 + | +LL | mod foo { + | ^^^^^^^ + +error[E0603]: module import `f` is private + --> $DIR/shadowed-use-visibility.rs:15:10 + | +LL | use bar::f::f; + | ^ private module import + | +note: the module import `f` is defined here... + --> $DIR/shadowed-use-visibility.rs:11:9 + | +LL | use foo as f; + | ^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/shadowed-use-visibility.rs:1:1 + | +LL | mod foo { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/shadowed/shadowing-in-the-same-pattern.rs b/tests/ui/shadowed/shadowing-in-the-same-pattern.rs new file mode 100644 index 000000000..f5872f9fb --- /dev/null +++ b/tests/ui/shadowed/shadowing-in-the-same-pattern.rs @@ -0,0 +1,7 @@ +// Test for issue #14581. + +fn f((a, a): (isize, isize)) {} //~ ERROR identifier `a` is bound more than once + +fn main() { + let (a, a) = (1, 1); //~ ERROR identifier `a` is bound more than once +} diff --git a/tests/ui/shadowed/shadowing-in-the-same-pattern.stderr b/tests/ui/shadowed/shadowing-in-the-same-pattern.stderr new file mode 100644 index 000000000..1c51653db --- /dev/null +++ b/tests/ui/shadowed/shadowing-in-the-same-pattern.stderr @@ -0,0 +1,16 @@ +error[E0415]: identifier `a` is bound more than once in this parameter list + --> $DIR/shadowing-in-the-same-pattern.rs:3:10 + | +LL | fn f((a, a): (isize, isize)) {} + | ^ used as parameter more than once + +error[E0416]: identifier `a` is bound more than once in the same pattern + --> $DIR/shadowing-in-the-same-pattern.rs:6:13 + | +LL | let (a, a) = (1, 1); + | ^ used in a pattern more than once + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0415, E0416. +For more information about an error, try `rustc --explain E0415`. diff --git a/tests/ui/short-error-format.rs b/tests/ui/short-error-format.rs new file mode 100644 index 000000000..acba4674a --- /dev/null +++ b/tests/ui/short-error-format.rs @@ -0,0 +1,9 @@ +// compile-flags: --error-format=short + +fn foo(_: u32) {} + +fn main() { + foo("Bonjour".to_owned()); + let x = 0u32; + x.salut(); +} diff --git a/tests/ui/short-error-format.stderr b/tests/ui/short-error-format.stderr new file mode 100644 index 000000000..8a22d673b --- /dev/null +++ b/tests/ui/short-error-format.stderr @@ -0,0 +1,3 @@ +$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types +$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope +error: aborting due to 2 previous errors diff --git a/tests/ui/simd/array-trait.rs b/tests/ui/simd/array-trait.rs new file mode 100644 index 000000000..45c10b378 --- /dev/null +++ b/tests/ui/simd/array-trait.rs @@ -0,0 +1,41 @@ +// Figuring out the size of a vector type that depends on traits doesn't ICE + +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +#![feature(repr_simd, platform_intrinsics, generic_const_exprs)] +#![allow(non_camel_case_types, incomplete_features)] + +pub trait Simd { + type Lane: Clone + Copy; + const SIZE: usize; +} + +pub struct i32x4; +impl Simd for i32x4 { + type Lane = i32; + const SIZE: usize = 4; +} + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct T([S::Lane; S::SIZE]); +//~^ ERROR unconstrained generic constant + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, y: E) -> T; + fn simd_extract(x: T, idx: u32) -> E; +} + +pub fn main() { + let mut t = T::([0; 4]); + unsafe { + for i in 0_i32..4 { + t = simd_insert(t, i as u32, i); + } + for i in 0_i32..4 { + assert_eq!(i, simd_extract(t, i as u32)); + } + } +} diff --git a/tests/ui/simd/array-trait.stderr b/tests/ui/simd/array-trait.stderr new file mode 100644 index 000000000..765215c39 --- /dev/null +++ b/tests/ui/simd/array-trait.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/array-trait.rs:23:23 + | +LL | pub struct T([S::Lane; S::SIZE]); + | ^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); S::SIZE]:` + +error: aborting due to previous error + diff --git a/tests/ui/simd/array-type.rs b/tests/ui/simd/array-type.rs new file mode 100644 index 000000000..7d66395a3 --- /dev/null +++ b/tests/ui/simd/array-type.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct S([i32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct T([i32; N]); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, y: E) -> T; + fn simd_extract(x: T, idx: u32) -> E; +} + +pub fn main() { + let mut s = S([0; 4]); + + unsafe { + for i in 0_i32..4 { + s = simd_insert(s, i as u32, i); + } + for i in 0_i32..4 { + assert_eq!(i, simd_extract(s, i as u32)); + } + } + + let mut t = T::<4>([0; 4]); + unsafe { + for i in 0_i32..4 { + t = simd_insert(t, i as u32, i); + } + for i in 0_i32..4 { + assert_eq!(i, simd_extract(t, i as u32)); + } + } +} diff --git a/tests/ui/simd/generics.rs b/tests/ui/simd/generics.rs new file mode 100644 index 000000000..fa9d35ee4 --- /dev/null +++ b/tests/ui/simd/generics.rs @@ -0,0 +1,85 @@ +// run-pass +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics)] + +use std::ops; + +#[repr(simd)] +#[derive(Copy, Clone)] +struct f32x4(f32, f32, f32, f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct A([f32; N]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct B([T; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct C([T; N]); + + +extern "platform-intrinsic" { + fn simd_add(x: T, y: T) -> T; +} + +fn add>(lhs: T, rhs: T) -> T { + lhs + rhs +} + +impl ops::Add for f32x4 { + type Output = f32x4; + + fn add(self, rhs: f32x4) -> f32x4 { + unsafe { simd_add(self, rhs) } + } +} + +impl ops::Add for A<4> { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + unsafe { simd_add(self, rhs) } + } +} + +impl ops::Add for B { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + unsafe { simd_add(self, rhs) } + } +} + +impl ops::Add for C { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + unsafe { simd_add(self, rhs) } + } +} + + +pub fn main() { + let x = [1.0f32, 2.0f32, 3.0f32, 4.0f32]; + let y = [2.0f32, 4.0f32, 6.0f32, 8.0f32]; + + // lame-o + let a = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); + let f32x4(a0, a1, a2, a3) = add(a, a); + assert_eq!(a0, 2.0f32); + assert_eq!(a1, 4.0f32); + assert_eq!(a2, 6.0f32); + assert_eq!(a3, 8.0f32); + + let a = A(x); + assert_eq!(add(a, a).0, y); + + let b = B(x); + assert_eq!(add(b, b).0, y); + + let c = C(x); + assert_eq!(add(c, c).0, y); +} diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs new file mode 100644 index 000000000..7a4f74665 --- /dev/null +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -0,0 +1,114 @@ +// run-pass +// ignore-emscripten +// ignore-android + +// FIXME: this test fails on arm-android because the NDK version 14 is too old. +// It needs at least version 18. We disable it on all android build bots because +// there is no way in compile-test to disable it for an (arch,os) pair. + +// Test that the simd floating-point math intrinsics produce correct results. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fsqrt(x: T) -> T; + fn simd_fabs(x: T) -> T; + fn simd_fsin(x: T) -> T; + fn simd_fcos(x: T) -> T; + fn simd_fexp(x: T) -> T; + fn simd_fexp2(x: T) -> T; + fn simd_fma(x: T, y: T, z: T) -> T; + fn simd_flog(x: T) -> T; + fn simd_flog10(x: T) -> T; + fn simd_flog2(x: T) -> T; + fn simd_fpow(x: T, y: T) -> T; + fn simd_fpowi(x: T, y: i32) -> T; + + // rounding functions + fn simd_ceil(x: T) -> T; + fn simd_floor(x: T) -> T; + fn simd_round(x: T) -> T; + fn simd_trunc(x: T) -> T; +} + +macro_rules! assert_approx_eq_f32 { + ($a:expr, $b:expr) => ({ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, + "{} is not approximately equal to {}", *a, *b); + }) +} +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => ({ + let a = $a; + let b = $b; + assert_approx_eq_f32!(a.0, b.0); + assert_approx_eq_f32!(a.1, b.1); + assert_approx_eq_f32!(a.2, b.2); + assert_approx_eq_f32!(a.3, b.3); + }) +} + +fn main() { + let x = f32x4(1.0, 1.0, 1.0, 1.0); + let y = f32x4(-1.0, -1.0, -1.0, -1.0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + let h = f32x4(0.5, 0.5, 0.5, 0.5); + + unsafe { + let r = simd_fabs(y); + assert_approx_eq!(x, r); + + let r = simd_fcos(z); + assert_approx_eq!(x, r); + + let r = simd_fexp(z); + assert_approx_eq!(x, r); + + let r = simd_fexp2(z); + assert_approx_eq!(x, r); + + let r = simd_fma(x, h, h); + assert_approx_eq!(x, r); + + let r = simd_fsqrt(x); + assert_approx_eq!(x, r); + + let r = simd_flog(x); + assert_approx_eq!(z, r); + + let r = simd_flog2(x); + assert_approx_eq!(z, r); + + let r = simd_flog10(x); + assert_approx_eq!(z, r); + + let r = simd_fpow(h, x); + assert_approx_eq!(h, r); + + let r = simd_fpowi(h, 1); + assert_approx_eq!(h, r); + + let r = simd_fsin(z); + assert_approx_eq!(z, r); + + // rounding functions + let r = simd_floor(h); + assert_eq!(z, r); + + let r = simd_ceil(h); + assert_eq!(x, r); + + let r = simd_round(h); + assert_eq!(x, r); + + let r = simd_trunc(h); + assert_eq!(z, r); + } +} diff --git a/tests/ui/simd/intrinsic/float-minmax-pass.rs b/tests/ui/simd/intrinsic/float-minmax-pass.rs new file mode 100644 index 000000000..d79be61f9 --- /dev/null +++ b/tests/ui/simd/intrinsic/float-minmax-pass.rs @@ -0,0 +1,52 @@ +// run-pass +// ignore-emscripten + +// Test that the simd_f{min,max} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_fmin(x: T, y: T) -> T; + fn simd_fmax(x: T, y: T) -> T; +} + +fn main() { + let x = f32x4(1.0, 2.0, 3.0, 4.0); + let y = f32x4(2.0, 1.0, 4.0, 3.0); + + #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] + let nan = f32::NAN; + // MIPS hardware treats f32::NAN as SNAN. Clear the signaling bit. + // See https://github.com/rust-lang/rust/issues/52746. + #[cfg(any(target_arch = "mips", target_arch = "mips64"))] + let nan = f32::from_bits(f32::NAN.to_bits() - 1); + + let n = f32x4(nan, nan, nan, nan); + + unsafe { + let min0 = simd_fmin(x, y); + let min1 = simd_fmin(y, x); + assert_eq!(min0, min1); + let e = f32x4(1.0, 1.0, 3.0, 3.0); + assert_eq!(min0, e); + let minn = simd_fmin(x, n); + assert_eq!(minn, x); + let minn = simd_fmin(y, n); + assert_eq!(minn, y); + + let max0 = simd_fmax(x, y); + let max1 = simd_fmax(y, x); + assert_eq!(max0, max1); + let e = f32x4(2.0, 2.0, 4.0, 4.0); + assert_eq!(max0, e); + let maxn = simd_fmax(x, n); + assert_eq!(maxn, x); + let maxn = simd_fmax(y, n); + assert_eq!(maxn, y); + } +} diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs new file mode 100644 index 000000000..3576eed71 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs @@ -0,0 +1,103 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_add(x: T, y: T) -> T; + fn simd_sub(x: T, y: T) -> T; + fn simd_mul(x: T, y: T) -> T; + fn simd_div(x: T, y: T) -> T; + fn simd_rem(x: T, y: T) -> T; + fn simd_shl(x: T, y: T) -> T; + fn simd_shr(x: T, y: T) -> T; + fn simd_and(x: T, y: T) -> T; + fn simd_or(x: T, y: T) -> T; + fn simd_xor(x: T, y: T) -> T; + + fn simd_neg(x: T) -> T; +} + +fn main() { + let x = i32x4(0, 0, 0, 0); + let y = u32x4(0, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_add(x, x); + simd_add(y, y); + simd_add(z, z); + simd_sub(x, x); + simd_sub(y, y); + simd_sub(z, z); + simd_mul(x, x); + simd_mul(y, y); + simd_mul(z, z); + simd_div(x, x); + simd_div(y, y); + simd_div(z, z); + simd_rem(x, x); + simd_rem(y, y); + simd_rem(z, z); + + simd_shl(x, x); + simd_shl(y, y); + simd_shr(x, x); + simd_shr(y, y); + simd_and(x, x); + simd_and(y, y); + simd_or(x, x); + simd_or(y, y); + simd_xor(x, x); + simd_xor(y, y); + + simd_neg(x); + simd_neg(z); + + + simd_add(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_sub(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_mul(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_div(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_shl(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_shr(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_and(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_or(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_xor(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + + simd_neg(0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + + + simd_shl(z, z); +//~^ ERROR unsupported operation on `f32x4` with element `f32` + simd_shr(z, z); +//~^ ERROR unsupported operation on `f32x4` with element `f32` + simd_and(z, z); +//~^ ERROR unsupported operation on `f32x4` with element `f32` + simd_or(z, z); +//~^ ERROR unsupported operation on `f32x4` with element `f32` + simd_xor(z, z); +//~^ ERROR unsupported operation on `f32x4` with element `f32` + } +} diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr b/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr new file mode 100644 index 000000000..0f0a7ea66 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr @@ -0,0 +1,93 @@ +error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:69:9 + | +LL | simd_add(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:71:9 + | +LL | simd_sub(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:73:9 + | +LL | simd_mul(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:75:9 + | +LL | simd_div(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:77:9 + | +LL | simd_shl(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:79:9 + | +LL | simd_shr(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:81:9 + | +LL | simd_and(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:83:9 + | +LL | simd_or(0, 0); + | ^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:85:9 + | +LL | simd_xor(0, 0); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_neg` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-arithmetic-2.rs:88:9 + | +LL | simd_neg(0); + | ^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32` + --> $DIR/generic-arithmetic-2.rs:92:9 + | +LL | simd_shl(z, z); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32` + --> $DIR/generic-arithmetic-2.rs:94:9 + | +LL | simd_shr(z, z); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32` + --> $DIR/generic-arithmetic-2.rs:96:9 + | +LL | simd_and(z, z); + | ^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32` + --> $DIR/generic-arithmetic-2.rs:98:9 + | +LL | simd_or(z, z); + | ^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32` + --> $DIR/generic-arithmetic-2.rs:100:9 + | +LL | simd_xor(z, z); + | ^^^^^^^^^^^^^^ + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs new file mode 100644 index 000000000..c507b8d31 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs @@ -0,0 +1,136 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-emscripten FIXME(#45351) hits an LLVM assert + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct U32([u32; N]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +macro_rules! all_eq { + ($a: expr, $b: expr) => {{ + let a = $a; + let b = $b; + assert!(a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3); + }} +} + +macro_rules! all_eq_ { + ($a: expr, $b: expr) => {{ + let a = $a; + let b = $b; + assert!(a.0 == b.0); + }} +} + + +extern "platform-intrinsic" { + fn simd_add(x: T, y: T) -> T; + fn simd_sub(x: T, y: T) -> T; + fn simd_mul(x: T, y: T) -> T; + fn simd_div(x: T, y: T) -> T; + fn simd_rem(x: T, y: T) -> T; + fn simd_shl(x: T, y: T) -> T; + fn simd_shr(x: T, y: T) -> T; + fn simd_and(x: T, y: T) -> T; + fn simd_or(x: T, y: T) -> T; + fn simd_xor(x: T, y: T) -> T; + + fn simd_neg(x: T) -> T; +} + +fn main() { + let x1 = i32x4(1, 2, 3, 4); + let y1 = U32::<4>([1, 2, 3, 4]); + let z1 = f32x4(1.0, 2.0, 3.0, 4.0); + let x2 = i32x4(2, 3, 4, 5); + let y2 = U32::<4>([2, 3, 4, 5]); + let z2 = f32x4(2.0, 3.0, 4.0, 5.0); + + unsafe { + all_eq!(simd_add(x1, x2), i32x4(3, 5, 7, 9)); + all_eq!(simd_add(x2, x1), i32x4(3, 5, 7, 9)); + all_eq_!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); + all_eq_!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); + all_eq!(simd_add(z1, z2), f32x4(3.0, 5.0, 7.0, 9.0)); + all_eq!(simd_add(z2, z1), f32x4(3.0, 5.0, 7.0, 9.0)); + + all_eq!(simd_mul(x1, x2), i32x4(2, 6, 12, 20)); + all_eq!(simd_mul(x2, x1), i32x4(2, 6, 12, 20)); + all_eq_!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); + all_eq_!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); + all_eq!(simd_mul(z1, z2), f32x4(2.0, 6.0, 12.0, 20.0)); + all_eq!(simd_mul(z2, z1), f32x4(2.0, 6.0, 12.0, 20.0)); + + all_eq!(simd_sub(x2, x1), i32x4(1, 1, 1, 1)); + all_eq!(simd_sub(x1, x2), i32x4(-1, -1, -1, -1)); + all_eq_!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); + all_eq_!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); + all_eq!(simd_sub(z2, z1), f32x4(1.0, 1.0, 1.0, 1.0)); + all_eq!(simd_sub(z1, z2), f32x4(-1.0, -1.0, -1.0, -1.0)); + + all_eq!(simd_div(x1, x1), i32x4(1, 1, 1, 1)); + all_eq!(simd_div(i32x4(2, 4, 6, 8), i32x4(2, 2, 2, 2)), x1); + all_eq_!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); + all_eq_!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); + all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0)); + all_eq!(simd_div(z1, z2), f32x4(1.0/2.0, 2.0/3.0, 3.0/4.0, 4.0/5.0)); + all_eq!(simd_div(z2, z1), f32x4(2.0/1.0, 3.0/2.0, 4.0/3.0, 5.0/4.0)); + + all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0)); + all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1)); + all_eq_!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); + all_eq_!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); + all_eq!(simd_rem(z1, z1), f32x4(0.0, 0.0, 0.0, 0.0)); + all_eq!(simd_rem(z1, z2), z1); + all_eq!(simd_rem(z2, z1), f32x4(0.0, 1.0, 1.0, 1.0)); + + all_eq!(simd_shl(x1, x2), i32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5)); + all_eq!(simd_shl(x2, x1), i32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4)); + all_eq_!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq_!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + + // test right-shift by assuming left-shift is correct + all_eq!(simd_shr(simd_shl(x1, x2), x2), x1); + all_eq!(simd_shr(simd_shl(x2, x1), x1), x2); + all_eq_!(simd_shr(simd_shl(y1, y2), y2), y1); + all_eq_!(simd_shr(simd_shl(y2, y1), y1), y2); + + // ensure we get logical vs. arithmetic shifts correct + let (a, b, c, d) = (-12, -123, -1234, -12345); + all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4)); + all_eq_!(simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1), + U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4])); + + all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4)); + all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4)); + all_eq_!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); + all_eq_!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); + + all_eq!(simd_or(x1, x2), i32x4(3, 3, 7, 5)); + all_eq!(simd_or(x2, x1), i32x4(3, 3, 7, 5)); + all_eq_!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); + all_eq_!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); + + all_eq!(simd_xor(x1, x2), i32x4(3, 1, 7, 1)); + all_eq!(simd_xor(x2, x1), i32x4(3, 1, 7, 1)); + all_eq_!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); + all_eq_!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); + + all_eq!(simd_neg(x1), i32x4(-1, -2, -3, -4)); + all_eq!(simd_neg(x2), i32x4(-2, -3, -4, -5)); + all_eq!(simd_neg(z1), f32x4(-1.0, -2.0, -3.0, -4.0)); + all_eq!(simd_neg(z2), f32x4(-2.0, -3.0, -4.0, -5.0)); + + } +} diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs new file mode 100644 index 000000000..9736d1b96 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs @@ -0,0 +1,38 @@ +// build-fail +// ignore-emscripten +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct x4(pub T, pub T, pub T, pub T); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_saturating_add(x: T, y: T) -> T; + fn simd_saturating_sub(x: T, y: T) -> T; +} + +fn main() { + let x = i32x4(0, 0, 0, 0); + let y = x4(0_usize, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_saturating_add(x, x); + simd_saturating_add(y, y); + simd_saturating_sub(x, x); + simd_saturating_sub(y, y); + + simd_saturating_add(z, z); + //~^ ERROR expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type + simd_saturating_sub(z, z); + //~^ ERROR expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type + } +} diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr new file mode 100644 index 000000000..f349cb565 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr @@ -0,0 +1,15 @@ +error[E0511]: invalid monomorphization of `simd_saturating_add` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type + --> $DIR/generic-arithmetic-saturating-2.rs:33:9 + | +LL | simd_saturating_add(z, z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_saturating_sub` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type + --> $DIR/generic-arithmetic-saturating-2.rs:35:9 + | +LL | simd_saturating_sub(z, z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs new file mode 100644 index 000000000..c11d14b99 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs @@ -0,0 +1,91 @@ +// run-pass +// ignore-emscripten + +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct I32([i32; N]); + +extern "platform-intrinsic" { + fn simd_saturating_add(x: T, y: T) -> T; + fn simd_saturating_sub(x: T, y: T) -> T; +} + +fn main() { + // unsigned + { + const M: u32 = u32::MAX; + + let a = u32x4(1, 2, 3, 4); + let b = u32x4(2, 4, 6, 8); + let m = u32x4(M, M, M, M); + let m1 = u32x4(M - 1, M - 1, M - 1, M - 1); + let z = u32x4(0, 0, 0, 0); + + unsafe { + assert_eq!(simd_saturating_add(z, z), z); + assert_eq!(simd_saturating_add(z, a), a); + assert_eq!(simd_saturating_add(b, z), b); + assert_eq!(simd_saturating_add(a, a), b); + assert_eq!(simd_saturating_add(a, m), m); + assert_eq!(simd_saturating_add(m, b), m); + assert_eq!(simd_saturating_add(m1, a), m); + + assert_eq!(simd_saturating_sub(b, z), b); + assert_eq!(simd_saturating_sub(b, a), a); + assert_eq!(simd_saturating_sub(a, a), z); + assert_eq!(simd_saturating_sub(a, b), z); + assert_eq!(simd_saturating_sub(a, m1), z); + assert_eq!(simd_saturating_sub(b, m1), z); + } + } + + // signed + { + const MIN: i32 = i32::MIN; + const MAX: i32 = i32::MAX; + + let a = I32::<4>([1, 2, 3, 4]); + let b = I32::<4>([2, 4, 6, 8]); + let c = I32::<4>([-1, -2, -3, -4]); + let d = I32::<4>([-2, -4, -6, -8]); + + let max = I32::<4>([MAX, MAX, MAX, MAX]); + let max1 = I32::<4>([MAX - 1, MAX - 1, MAX - 1, MAX - 1]); + let min = I32::<4>([MIN, MIN, MIN, MIN]); + let min1 = I32::<4>([MIN + 1, MIN + 1, MIN + 1, MIN + 1]); + + let z = I32::<4>([0, 0, 0, 0]); + + unsafe { + assert_eq!(simd_saturating_add(z, z).0, z.0); + assert_eq!(simd_saturating_add(z, a).0, a.0); + assert_eq!(simd_saturating_add(b, z).0, b.0); + assert_eq!(simd_saturating_add(a, a).0, b.0); + assert_eq!(simd_saturating_add(a, max).0, max.0); + assert_eq!(simd_saturating_add(max, b).0, max.0); + assert_eq!(simd_saturating_add(max1, a).0, max.0); + assert_eq!(simd_saturating_add(min1, z).0, min1.0); + assert_eq!(simd_saturating_add(min, z).0, min.0); + assert_eq!(simd_saturating_add(min1, c).0, min.0); + assert_eq!(simd_saturating_add(min, c).0, min.0); + assert_eq!(simd_saturating_add(min1, d).0, min.0); + assert_eq!(simd_saturating_add(min, d).0, min.0); + + assert_eq!(simd_saturating_sub(b, z).0, b.0); + assert_eq!(simd_saturating_sub(b, a).0, a.0); + assert_eq!(simd_saturating_sub(a, a).0, z.0); + assert_eq!(simd_saturating_sub(a, b).0, c.0); + assert_eq!(simd_saturating_sub(z, max).0, min1.0); + assert_eq!(simd_saturating_sub(min1, z).0, min1.0); + assert_eq!(simd_saturating_sub(min1, a).0, min.0); + assert_eq!(simd_saturating_sub(min1, b).0, min.0); + } + } +} diff --git a/tests/ui/simd/intrinsic/generic-as.rs b/tests/ui/simd/intrinsic/generic-as.rs new file mode 100644 index 000000000..a975190a2 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-as.rs @@ -0,0 +1,48 @@ +// run-pass + +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_as(x: T) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct V([T; 2]); + +fn main() { + unsafe { + let u = V::([u32::MIN, u32::MAX]); + let i: V = simd_as(u); + assert_eq!(i.0[0], u.0[0] as i16); + assert_eq!(i.0[1], u.0[1] as i16); + } + + unsafe { + let f = V::([f32::MIN, f32::MAX]); + let i: V = simd_as(f); + assert_eq!(i.0[0], f.0[0] as i16); + assert_eq!(i.0[1], f.0[1] as i16); + } + + unsafe { + let f = V::([f32::MIN, f32::MAX]); + let u: V = simd_as(f); + assert_eq!(u.0[0], f.0[0] as u8); + assert_eq!(u.0[1], f.0[1] as u8); + } + + unsafe { + let f = V::([f64::MIN, f64::MAX]); + let i: V = simd_as(f); + assert_eq!(i.0[0], f.0[0] as isize); + assert_eq!(i.0[1], f.0[1] as isize); + } + + unsafe { + let f = V::([f64::MIN, f64::MAX]); + let u: V = simd_as(f); + assert_eq!(u.0[0], f.0[0] as usize); + assert_eq!(u.0[1], f.0[1] as usize); + } +} diff --git a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs new file mode 100644 index 000000000..8c436841b --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs @@ -0,0 +1,62 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-emscripten +// ignore-endian-big behavior of simd_bitmask is endian-specific + +// Test that the simd_bitmask intrinsic produces correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u8x4(pub u8, pub u8, pub u8, pub u8); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct Tx4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_bitmask(x: T) -> U; +} + +fn main() { + let z = u32x4(0, 0, 0, 0); + let ez = 0_u8; + + let o = u32x4(!0, !0, !0, !0); + let eo = 0b_1111_u8; + + let m0 = u32x4(!0, 0, !0, 0); + let e0 = 0b_0000_0101_u8; + + // Check that the MSB is extracted: + let m = u8x4(0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111); + let e = 0b_1101; + + // Check usize / isize + let msize: Tx4 = Tx4(usize::MAX, 0, usize::MAX, usize::MAX); + + unsafe { + let r: u8 = simd_bitmask(z); + assert_eq!(r, ez); + + let r: u8 = simd_bitmask(o); + assert_eq!(r, eo); + + let r: u8 = simd_bitmask(m0); + assert_eq!(r, e0); + + let r: u8 = simd_bitmask(m); + assert_eq!(r, e); + + let r: u8 = simd_bitmask(msize); + assert_eq!(r, e); + + } +} diff --git a/tests/ui/simd/intrinsic/generic-bitmask.rs b/tests/ui/simd/intrinsic/generic-bitmask.rs new file mode 100644 index 000000000..9a23dae77 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-bitmask.rs @@ -0,0 +1,69 @@ +// build-fail + +// Test that the simd_bitmask intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x2([u32; 2]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4([u32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x8([u8; 8]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x16([u8; 16]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x32([u8; 32]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x64([u8; 64]); + +extern "platform-intrinsic" { + fn simd_bitmask(x: T) -> U; +} + +fn main() { + let m2 = u32x2([0; 2]); + let m4 = u32x4([0; 4]); + let m8 = u8x8([0; 8]); + let m16 = u8x16([0; 16]); + let m32 = u8x32([0; 32]); + let m64 = u8x64([0; 64]); + + unsafe { + let _: u8 = simd_bitmask(m2); + let _: u8 = simd_bitmask(m4); + let _: u8 = simd_bitmask(m8); + let _: u16 = simd_bitmask(m16); + let _: u32 = simd_bitmask(m32); + let _: u64 = simd_bitmask(m64); + + let _: u16 = simd_bitmask(m2); + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic + + let _: u16 = simd_bitmask(m8); + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic + + let _: u32 = simd_bitmask(m16); + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic + + let _: u64 = simd_bitmask(m32); + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic + + let _: u128 = simd_bitmask(m64); + //~^ ERROR invalid monomorphization of `simd_bitmask` intrinsic + + } +} diff --git a/tests/ui/simd/intrinsic/generic-bitmask.stderr b/tests/ui/simd/intrinsic/generic-bitmask.stderr new file mode 100644 index 000000000..0de3f8eea --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-bitmask.stderr @@ -0,0 +1,33 @@ +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]` + --> $DIR/generic-bitmask.rs:53:22 + | +LL | let _: u16 = simd_bitmask(m2); + | ^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]` + --> $DIR/generic-bitmask.rs:56:22 + | +LL | let _: u16 = simd_bitmask(m8); + | ^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u32`, expected `u16` or `[u8; 2]` + --> $DIR/generic-bitmask.rs:59:22 + | +LL | let _: u32 = simd_bitmask(m16); + | ^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u64`, expected `u32` or `[u8; 4]` + --> $DIR/generic-bitmask.rs:62:22 + | +LL | let _: u64 = simd_bitmask(m32); + | ^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u128`, expected `u64` or `[u8; 8]` + --> $DIR/generic-bitmask.rs:65:23 + | +LL | let _: u128 = simd_bitmask(m64); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-cast-pass.rs b/tests/ui/simd/intrinsic/generic-cast-pass.rs new file mode 100644 index 000000000..15f232e2c --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-cast-pass.rs @@ -0,0 +1,121 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten FIXME(#45351) hits an LLVM assert + +#![feature(repr_simd, platform_intrinsics, concat_idents, test)] +#![allow(non_camel_case_types)] + +extern crate test; + +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct i8x4(i8, i8, i8, i8); + +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct u32x4(u32, u32, u32, u32); +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct u8x4(u8, u8, u8, u8); + +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct f32x4(f32, f32, f32, f32); + +#[repr(simd)] +#[derive(PartialEq, Debug)] +struct f64x4(f64, f64, f64, f64); + + +extern "platform-intrinsic" { + fn simd_cast(x: T) -> U; +} + +const A: i32 = -1234567; +const B: i32 = 12345678; +const C: i32 = -123456789; +const D: i32 = 1234567890; + +trait Foo { + fn is_float() -> bool { false } + fn in_range(x: i32) -> bool; +} +impl Foo for i32 { + fn in_range(_: i32) -> bool { true } +} +impl Foo for i8 { + fn in_range(x: i32) -> bool { -128 <= x && x < 128 } +} +impl Foo for u32 { + fn in_range(x: i32) -> bool { 0 <= x } +} +impl Foo for u8 { + fn in_range(x: i32) -> bool { 0 <= x && x < 128 } +} +impl Foo for f32 { + fn is_float() -> bool { true } + fn in_range(_: i32) -> bool { true } +} +impl Foo for f64 { + fn is_float() -> bool { true } + fn in_range(_: i32) -> bool { true } +} + +fn main() { + macro_rules! test { + ($from: ident, $to: ident) => {{ + // force the casts to actually happen, or else LLVM/rustc + // may fold them and get slightly different results. + let (a, b, c, d) = test::black_box((A as $from, B as $from, C as $from, D as $from)); + // the SIMD vectors are all FOOx4, so we can concat_idents + // so we don't have to pass in the extra args to the macro + let mut from = simd_cast(concat_idents!($from, x4)(a, b, c, d)); + let mut to = concat_idents!($to, x4)(a as $to, + b as $to, + c as $to, + d as $to); + // assist type inference, it needs to know what `from` is + // for the `if` statements. + to == from; + + // there are platform differences for some out of range + // casts, so we just normalize such things: it's OK for + // "invalid" calculations to result in nonsense answers. + // (e.g., negative float to unsigned integer goes through a + // library routine on the default i686 platforms, and the + // implementation of that routine differs on e.g., Linux + // vs. macOS, resulting in different answers.) + if $from::is_float() { + if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; } + if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; } + if !$to::in_range(C) { from.2 = 0 as $to; to.2 = 0 as $to; } + if !$to::in_range(D) { from.3 = 0 as $to; to.3 = 0 as $to; } + } + + assert!(to == from, + "{} -> {} ({:?} != {:?})", stringify!($from), stringify!($to), + from, to); + }} + } + macro_rules! tests { + (: $($to: ident),*) => { () }; + // repeating the list twice is easier than writing a cartesian + // product macro + ($from: ident $(, $from_: ident)*: $($to: ident),*) => { + fn $from() { unsafe { $( test!($from, $to); )* } } + tests!($($from_),*: $($to),*) + }; + ($($types: ident),*) => {{ + tests!($($types),* : $($types),*); + $($types();)* + }} + } + + // test various combinations, including truncation, + // signed/unsigned extension, and floating point casts. + tests!(i32, i8, u32, u8, f32); + tests!(i32, u32, f32, f64) +} diff --git a/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs b/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs new file mode 100644 index 000000000..b9382310d --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_cast(x: T) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct V([T; 4]); + +fn main() { + let u = V::([0, 1, 2, 3]); + let uu32: V = unsafe { simd_cast(u) }; + let ui64: V = unsafe { simd_cast(u) }; + + for (u, (uu32, ui64)) in u.0.iter().zip(uu32.0.iter().zip(ui64.0.iter())) { + assert_eq!(*u as u32, *uu32); + assert_eq!(*u as i64, *ui64); + } +} diff --git a/tests/ui/simd/intrinsic/generic-cast.rs b/tests/ui/simd/intrinsic/generic-cast.rs new file mode 100644 index 000000000..4f4fa06b0 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-cast.rs @@ -0,0 +1,43 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i32x8(i32, i32, i32, i32, + i32, i32, i32, i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct f32x4(f32, f32, f32, f32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct f32x8(f32, f32, f32, f32, + f32, f32, f32, f32); + + +extern "platform-intrinsic" { + fn simd_cast(x: T) -> U; +} + +fn main() { + let x = i32x4(0, 0, 0, 0); + + unsafe { + simd_cast::(0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_cast::(0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_cast::(x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + simd_cast::<_, i32x8>(x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 + } +} diff --git a/tests/ui/simd/intrinsic/generic-cast.stderr b/tests/ui/simd/intrinsic/generic-cast.stderr new file mode 100644 index 000000000..2226bbbe1 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-cast.stderr @@ -0,0 +1,27 @@ +error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-cast.rs:34:9 + | +LL | simd_cast::(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-cast.rs:36:9 + | +LL | simd_cast::(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-cast.rs:38:9 + | +LL | simd_cast::(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 + --> $DIR/generic-cast.rs:40:9 + | +LL | simd_cast::<_, i32x8>(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-comparison-pass.rs b/tests/ui/simd/intrinsic/generic-comparison-pass.rs new file mode 100644 index 000000000..da5c42a1a --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-comparison-pass.rs @@ -0,0 +1,106 @@ +// run-pass +// ignore-emscripten FIXME(#45351) hits an LLVM assert +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![feature(repr_simd, platform_intrinsics, concat_idents)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +#[derive(Copy, Clone)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); +#[repr(simd)] +#[derive(Copy, Clone)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +extern "platform-intrinsic" { + fn simd_eq(x: T, y: T) -> U; + fn simd_ne(x: T, y: T) -> U; + fn simd_lt(x: T, y: T) -> U; + fn simd_le(x: T, y: T) -> U; + fn simd_gt(x: T, y: T) -> U; + fn simd_ge(x: T, y: T) -> U; +} + +macro_rules! cmp { + ($method: ident($lhs: expr, $rhs: expr)) => {{ + let lhs = $lhs; + let rhs = $rhs; + let e: u32x4 = concat_idents!(simd_, $method)($lhs, $rhs); + // assume the scalar version is correct/the behaviour we want. + assert!((e.0 != 0) == lhs.0 .$method(&rhs.0)); + assert!((e.1 != 0) == lhs.1 .$method(&rhs.1)); + assert!((e.2 != 0) == lhs.2 .$method(&rhs.2)); + assert!((e.3 != 0) == lhs.3 .$method(&rhs.3)); + }} +} +macro_rules! tests { + ($($lhs: ident, $rhs: ident;)*) => {{ + $( + (|| { + cmp!(eq($lhs, $rhs)); + cmp!(ne($lhs, $rhs)); + + // test both directions + cmp!(lt($lhs, $rhs)); + cmp!(lt($rhs, $lhs)); + + cmp!(le($lhs, $rhs)); + cmp!(le($rhs, $lhs)); + + cmp!(gt($lhs, $rhs)); + cmp!(gt($rhs, $lhs)); + + cmp!(ge($lhs, $rhs)); + cmp!(ge($rhs, $lhs)); + })(); + )* + }} +} +fn main() { + // 13 vs. -100 tests that we get signed vs. unsigned comparisons + // correct (i32: 13 > -100, u32: 13 < -100). let i1 = i32x4(10, -11, 12, 13); + let i1 = i32x4(10, -11, 12, 13); + let i2 = i32x4(5, -5, 20, -100); + let i3 = i32x4(10, -11, 20, -100); + + let u1 = u32x4(10, !11+1, 12, 13); + let u2 = u32x4(5, !5+1, 20, !100+1); + let u3 = u32x4(10, !11+1, 20, !100+1); + + let f1 = f32x4(10.0, -11.0, 12.0, 13.0); + let f2 = f32x4(5.0, -5.0, 20.0, -100.0); + let f3 = f32x4(10.0, -11.0, 20.0, -100.0); + + unsafe { + tests! { + i1, i1; + u1, u1; + f1, f1; + + i1, i2; + u1, u2; + f1, f2; + + i1, i3; + u1, u3; + f1, f3; + } + } + + // NAN comparisons are special: + // -11 (*) 13 + // -5 -100 (*) + let f4 = f32x4(f32::NAN, f1.1, f32::NAN, f2.3); + + unsafe { + tests! { + f1, f4; + f2, f4; + f4, f4; + } + } +} diff --git a/tests/ui/simd/intrinsic/generic-comparison.rs b/tests/ui/simd/intrinsic/generic-comparison.rs new file mode 100644 index 000000000..3cd38042f --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-comparison.rs @@ -0,0 +1,67 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i16x8(i16, i16, i16, i16, + i16, i16, i16, i16); + +extern "platform-intrinsic" { + fn simd_eq(x: T, y: T) -> U; + fn simd_ne(x: T, y: T) -> U; + fn simd_lt(x: T, y: T) -> U; + fn simd_le(x: T, y: T) -> U; + fn simd_gt(x: T, y: T) -> U; + fn simd_ge(x: T, y: T) -> U; +} + +fn main() { + let x = i32x4(0, 0, 0, 0); + + unsafe { + simd_eq::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_ne::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_lt::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_le::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_gt::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_ge::(0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + + simd_eq::<_, i32>(x, x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + simd_ne::<_, i32>(x, x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + simd_lt::<_, i32>(x, x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + simd_le::<_, i32>(x, x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + simd_gt::<_, i32>(x, x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + simd_ge::<_, i32>(x, x); + //~^ ERROR expected SIMD return type, found non-SIMD `i32` + + simd_eq::<_, i16x8>(x, x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + simd_ne::<_, i16x8>(x, x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + simd_lt::<_, i16x8>(x, x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + simd_le::<_, i16x8>(x, x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + simd_gt::<_, i16x8>(x, x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + simd_ge::<_, i16x8>(x, x); +//~^ ERROR return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + } +} diff --git a/tests/ui/simd/intrinsic/generic-comparison.stderr b/tests/ui/simd/intrinsic/generic-comparison.stderr new file mode 100644 index 000000000..0eae2688b --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-comparison.stderr @@ -0,0 +1,111 @@ +error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:28:9 + | +LL | simd_eq::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:30:9 + | +LL | simd_ne::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:32:9 + | +LL | simd_lt::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:34:9 + | +LL | simd_le::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:36:9 + | +LL | simd_gt::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:38:9 + | +LL | simd_ge::(0, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:41:9 + | +LL | simd_eq::<_, i32>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:43:9 + | +LL | simd_ne::<_, i32>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:45:9 + | +LL | simd_lt::<_, i32>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:47:9 + | +LL | simd_le::<_, i32>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:49:9 + | +LL | simd_gt::<_, i32>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32` + --> $DIR/generic-comparison.rs:51:9 + | +LL | simd_ge::<_, i32>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + --> $DIR/generic-comparison.rs:54:9 + | +LL | simd_eq::<_, i16x8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + --> $DIR/generic-comparison.rs:56:9 + | +LL | simd_ne::<_, i16x8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + --> $DIR/generic-comparison.rs:58:9 + | +LL | simd_lt::<_, i16x8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + --> $DIR/generic-comparison.rs:60:9 + | +LL | simd_le::<_, i16x8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + --> $DIR/generic-comparison.rs:62:9 + | +LL | simd_gt::<_, i16x8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 + --> $DIR/generic-comparison.rs:64:9 + | +LL | simd_ge::<_, i16x8>(x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs new file mode 100644 index 000000000..3c913c0ad --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -0,0 +1,102 @@ +// run-pass +// ignore-emscripten FIXME(#45351) hits an LLVM assert + +#![feature(repr_simd, platform_intrinsics)] +#![feature(inline_const)] + +#[repr(simd)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +struct i32x2(i32, i32); +#[repr(simd)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[allow(non_camel_case_types)] +struct i32x8(i32, i32, i32, i32, + i32, i32, i32, i32); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, y: E) -> T; + fn simd_extract(x: T, idx: u32) -> E; + + fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; + fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; +} + +macro_rules! all_eq { + ($a: expr, $b: expr) => {{ + let a = $a; + let b = $b; + // type inference works better with the concrete type on the + // left, but humans work better with the expected on the + // right. + assert!(b == a, + "{:?} != {:?}", a, b); + }} +} + +fn main() { + let x2 = i32x2(20, 21); + let x4 = i32x4(40, 41, 42, 43); + let x8 = i32x8(80, 81, 82, 83, 84, 85, 86, 87); + unsafe { + all_eq!(simd_insert(x2, 0, 100), i32x2(100, 21)); + all_eq!(simd_insert(x2, 1, 100), i32x2(20, 100)); + + all_eq!(simd_insert(x4, 0, 100), i32x4(100, 41, 42, 43)); + all_eq!(simd_insert(x4, 1, 100), i32x4(40, 100, 42, 43)); + all_eq!(simd_insert(x4, 2, 100), i32x4(40, 41, 100, 43)); + all_eq!(simd_insert(x4, 3, 100), i32x4(40, 41, 42, 100)); + + all_eq!(simd_insert(x8, 0, 100), i32x8(100, 81, 82, 83, 84, 85, 86, 87)); + all_eq!(simd_insert(x8, 1, 100), i32x8(80, 100, 82, 83, 84, 85, 86, 87)); + all_eq!(simd_insert(x8, 2, 100), i32x8(80, 81, 100, 83, 84, 85, 86, 87)); + all_eq!(simd_insert(x8, 3, 100), i32x8(80, 81, 82, 100, 84, 85, 86, 87)); + all_eq!(simd_insert(x8, 4, 100), i32x8(80, 81, 82, 83, 100, 85, 86, 87)); + all_eq!(simd_insert(x8, 5, 100), i32x8(80, 81, 82, 83, 84, 100, 86, 87)); + all_eq!(simd_insert(x8, 6, 100), i32x8(80, 81, 82, 83, 84, 85, 100, 87)); + all_eq!(simd_insert(x8, 7, 100), i32x8(80, 81, 82, 83, 84, 85, 86, 100)); + + all_eq!(simd_extract(x2, 0), 20); + all_eq!(simd_extract(x2, 1), 21); + + all_eq!(simd_extract(x4, 0), 40); + all_eq!(simd_extract(x4, 1), 41); + all_eq!(simd_extract(x4, 2), 42); + all_eq!(simd_extract(x4, 3), 43); + + all_eq!(simd_extract(x8, 0), 80); + all_eq!(simd_extract(x8, 1), 81); + all_eq!(simd_extract(x8, 2), 82); + all_eq!(simd_extract(x8, 3), 83); + all_eq!(simd_extract(x8, 4), 84); + all_eq!(simd_extract(x8, 5), 85); + all_eq!(simd_extract(x8, 6), 86); + all_eq!(simd_extract(x8, 7), 87); + } + + let y2 = i32x2(120, 121); + let y4 = i32x4(140, 141, 142, 143); + let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); + unsafe { + all_eq!(simd_shuffle2(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); + all_eq!(simd_shuffle4(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); + all_eq!(simd_shuffle8(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), + i32x8(121, 20, 21, 120, 21, 120, 121, 20)); + + all_eq!(simd_shuffle2(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); + all_eq!(simd_shuffle4(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); + all_eq!(simd_shuffle8(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), + i32x8(143, 42, 141, 40, 43, 142, 140, 41)); + + all_eq!(simd_shuffle2(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); + all_eq!(simd_shuffle4(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); + all_eq!(simd_shuffle8(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), + i32x8(183, 85, 187, 80, 83, 180, 184, 81)); + } + +} diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs new file mode 100644 index 000000000..abde69163 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -0,0 +1,77 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics, rustc_attrs)] + +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i32x2(i32, i32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct i32x8(i32, i32, i32, i32, + i32, i32, i32, i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct f32x2(f32, f32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct f32x4(f32, f32, f32, f32); +#[repr(simd)] +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +struct f32x8(f32, f32, f32, f32, + f32, f32, f32, f32); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, y: E) -> T; + fn simd_extract(x: T, idx: u32) -> E; + + fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; + fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; +} + +fn main() { + let x = i32x4(0, 0, 0, 0); + + unsafe { + simd_insert(0, 0, 0); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + simd_insert(x, 0, 1.0); + //~^ ERROR expected inserted type `i32` (element of input `i32x4`), found `f64` + simd_extract::<_, f32>(x, 0); + //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32` + + const IDX2: [u32; 2] = [0; 2]; + simd_shuffle2::(0, 0, IDX2); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + const IDX4: [u32; 4] = [0; 4]; + simd_shuffle4::(0, 0, IDX4); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + const IDX8: [u32; 8] = [0; 8]; + simd_shuffle8::(0, 0, IDX8); + //~^ ERROR expected SIMD input type, found non-SIMD `i32` + + simd_shuffle2::<_, f32x2>(x, x, IDX2); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + simd_shuffle4::<_, f32x4>(x, x, IDX4); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` + simd_shuffle8::<_, f32x8>(x, x, IDX8); +//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + + simd_shuffle2::<_, i32x8>(x, x, IDX2); + //~^ ERROR expected return type of length 2, found `i32x8` with length 8 + simd_shuffle4::<_, i32x8>(x, x, IDX4); + //~^ ERROR expected return type of length 4, found `i32x8` with length 8 + simd_shuffle8::<_, i32x2>(x, x, IDX8); + //~^ ERROR expected return type of length 8, found `i32x2` with length 2 + } +} diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr new file mode 100644 index 000000000..5b423f704 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -0,0 +1,75 @@ +error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:46:9 + | +LL | simd_insert(0, 0, 0); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` + --> $DIR/generic-elements.rs:48:9 + | +LL | simd_insert(x, 0, 1.0); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` + --> $DIR/generic-elements.rs:50:9 + | +LL | simd_extract::<_, f32>(x, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:54:9 + | +LL | simd_shuffle2::(0, 0, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:57:9 + | +LL | simd_shuffle4::(0, 0, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:60:9 + | +LL | simd_shuffle8::(0, 0, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + --> $DIR/generic-elements.rs:63:9 + | +LL | simd_shuffle2::<_, f32x2>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` + --> $DIR/generic-elements.rs:65:9 + | +LL | simd_shuffle4::<_, f32x4>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` + --> $DIR/generic-elements.rs:67:9 + | +LL | simd_shuffle8::<_, f32x8>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:70:9 + | +LL | simd_shuffle2::<_, i32x8>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:72:9 + | +LL | simd_shuffle4::<_, i32x8>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2 + --> $DIR/generic-elements.rs:74:9 + | +LL | simd_shuffle8::<_, i32x2>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-gather-pass.rs b/tests/ui/simd/intrinsic/generic-gather-pass.rs new file mode 100644 index 000000000..805caebe5 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-gather-pass.rs @@ -0,0 +1,141 @@ +// run-pass +// ignore-emscripten + +// Test that the simd_{gather,scatter} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct x4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_gather(x: T, y: U, z: V) -> T; + fn simd_scatter(x: T, y: U, z: V) -> (); +} + +fn main() { + let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; + + let default = x4(-3_f32, -3., -3., -3.); + let s_strided = x4(0_f32, 2., -3., 6.); + let mask = x4(-1_i32, -1, 0, -1); + + // reading from *const + unsafe { + let pointer = &x[0] as *const f32; + let pointers = x4( + pointer.offset(0) as *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // reading from *mut + unsafe { + let pointer = &mut x[0] as *mut f32; + let pointers = x4( + pointer.offset(0) as *mut f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // writing to *mut + unsafe { + let pointer = &mut x[0] as *mut f32; + let pointers = x4( + pointer.offset(0) as *mut f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let values = x4(42_f32, 43_f32, 44_f32, 45_f32); + simd_scatter(values, pointers, mask); + + assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); + } + + // test modifying array of *const f32 + let mut y = [ + &x[0] as *const f32, + &x[1] as *const f32, + &x[2] as *const f32, + &x[3] as *const f32, + &x[4] as *const f32, + &x[5] as *const f32, + &x[6] as *const f32, + &x[7] as *const f32 + ]; + + let default = x4(y[0], y[0], y[0], y[0]); + let s_strided = x4(y[0], y[2], y[0], y[6]); + + // reading from *const + unsafe { + let pointer = &y[0] as *const *const f32; + let pointers = x4( + pointer.offset(0) as *const *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // reading from *mut + unsafe { + let pointer = &mut y[0] as *mut *const f32; + let pointers = x4( + pointer.offset(0) as *mut *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // writing to *mut + unsafe { + let pointer = &mut y[0] as *mut *const f32; + let pointers = x4( + pointer.offset(0) as *mut *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ); + + let values = x4(y[7], y[6], y[5], y[1]); + simd_scatter(values, pointers, mask); + + let s = [ + &x[7] as *const f32, + &x[1] as *const f32, + &x[6] as *const f32, + &x[3] as *const f32, + &x[4] as *const f32, + &x[5] as *const f32, + &x[1] as *const f32, + &x[7] as *const f32 + ]; + assert_eq!(y, s); + } +} diff --git a/tests/ui/simd/intrinsic/generic-reduction-pass.rs b/tests/ui/simd/intrinsic/generic-reduction-pass.rs new file mode 100644 index 000000000..4a54afee8 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-reduction-pass.rs @@ -0,0 +1,155 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-emscripten + +// Test that the simd_reduce_{op} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +extern "platform-intrinsic" { + fn simd_reduce_add_unordered(x: T) -> U; + fn simd_reduce_mul_unordered(x: T) -> U; + fn simd_reduce_add_ordered(x: T, acc: U) -> U; + fn simd_reduce_mul_ordered(x: T, acc: U) -> U; + fn simd_reduce_min(x: T) -> U; + fn simd_reduce_max(x: T) -> U; + fn simd_reduce_min_nanless(x: T) -> U; + fn simd_reduce_max_nanless(x: T) -> U; + fn simd_reduce_and(x: T) -> U; + fn simd_reduce_or(x: T) -> U; + fn simd_reduce_xor(x: T) -> U; + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +fn main() { + unsafe { + let x = i32x4(1, -2, 3, 4); + let r: i32 = simd_reduce_add_unordered(x); + assert_eq!(r, 6_i32); + let r: i32 = simd_reduce_mul_unordered(x); + assert_eq!(r, -24_i32); + let r: i32 = simd_reduce_add_ordered(x, -1); + assert_eq!(r, 5_i32); + let r: i32 = simd_reduce_mul_ordered(x, -1); + assert_eq!(r, 24_i32); + + let r: i32 = simd_reduce_min(x); + assert_eq!(r, -2_i32); + let r: i32 = simd_reduce_max(x); + assert_eq!(r, 4_i32); + + let x = i32x4(-1, -1, -1, -1); + let r: i32 = simd_reduce_and(x); + assert_eq!(r, -1_i32); + let r: i32 = simd_reduce_or(x); + assert_eq!(r, -1_i32); + let r: i32 = simd_reduce_xor(x); + assert_eq!(r, 0_i32); + + let x = i32x4(-1, -1, 0, -1); + let r: i32 = simd_reduce_and(x); + assert_eq!(r, 0_i32); + let r: i32 = simd_reduce_or(x); + assert_eq!(r, -1_i32); + let r: i32 = simd_reduce_xor(x); + assert_eq!(r, -1_i32); + } + + unsafe { + let x = u32x4(1, 2, 3, 4); + let r: u32 = simd_reduce_add_unordered(x); + assert_eq!(r, 10_u32); + let r: u32 = simd_reduce_mul_unordered(x); + assert_eq!(r, 24_u32); + let r: u32 = simd_reduce_add_ordered(x, 1); + assert_eq!(r, 11_u32); + let r: u32 = simd_reduce_mul_ordered(x, 2); + assert_eq!(r, 48_u32); + + let r: u32 = simd_reduce_min(x); + assert_eq!(r, 1_u32); + let r: u32 = simd_reduce_max(x); + assert_eq!(r, 4_u32); + + let t = u32::MAX; + let x = u32x4(t, t, t, t); + let r: u32 = simd_reduce_and(x); + assert_eq!(r, t); + let r: u32 = simd_reduce_or(x); + assert_eq!(r, t); + let r: u32 = simd_reduce_xor(x); + assert_eq!(r, 0_u32); + + let x = u32x4(t, t, 0, t); + let r: u32 = simd_reduce_and(x); + assert_eq!(r, 0_u32); + let r: u32 = simd_reduce_or(x); + assert_eq!(r, t); + let r: u32 = simd_reduce_xor(x); + assert_eq!(r, t); + } + + unsafe { + let x = f32x4(1., -2., 3., 4.); + let r: f32 = simd_reduce_add_unordered(x); + assert_eq!(r, 6_f32); + let r: f32 = simd_reduce_mul_unordered(x); + assert_eq!(r, -24_f32); + let r: f32 = simd_reduce_add_ordered(x, 0.); + assert_eq!(r, 6_f32); + let r: f32 = simd_reduce_mul_ordered(x, 1.); + assert_eq!(r, -24_f32); + let r: f32 = simd_reduce_add_ordered(x, 1.); + assert_eq!(r, 7_f32); + let r: f32 = simd_reduce_mul_ordered(x, 2.); + assert_eq!(r, -48_f32); + + let r: f32 = simd_reduce_min(x); + assert_eq!(r, -2_f32); + let r: f32 = simd_reduce_max(x); + assert_eq!(r, 4_f32); + let r: f32 = simd_reduce_min_nanless(x); + assert_eq!(r, -2_f32); + let r: f32 = simd_reduce_max_nanless(x); + assert_eq!(r, 4_f32); + } + + unsafe { + let x = b8x4(!0, !0, !0, !0); + let r: bool = simd_reduce_all(x); + assert_eq!(r, true); + let r: bool = simd_reduce_any(x); + assert_eq!(r, true); + + let x = b8x4(!0, !0, 0, !0); + let r: bool = simd_reduce_all(x); + assert_eq!(r, false); + let r: bool = simd_reduce_any(x); + assert_eq!(r, true); + + let x = b8x4(0, 0, 0, 0); + let r: bool = simd_reduce_all(x); + assert_eq!(r, false); + let r: bool = simd_reduce_any(x); + assert_eq!(r, false); + } +} diff --git a/tests/ui/simd/intrinsic/generic-reduction.rs b/tests/ui/simd/intrinsic/generic-reduction.rs new file mode 100644 index 000000000..ede4b26d1 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-reduction.rs @@ -0,0 +1,58 @@ +// build-fail +// ignore-emscripten + +// Test that the simd_reduce_{op} intrinsics produce ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + + +extern "platform-intrinsic" { + fn simd_reduce_add_ordered(x: T, y: U) -> U; + fn simd_reduce_mul_ordered(x: T, y: U) -> U; + fn simd_reduce_and(x: T) -> U; + fn simd_reduce_or(x: T) -> U; + fn simd_reduce_xor(x: T) -> U; + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +fn main() { + let x = u32x4(0, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_reduce_add_ordered(z, 0); + //~^ ERROR expected return type `f32` (element of input `f32x4`), found `i32` + simd_reduce_mul_ordered(z, 1); + //~^ ERROR expected return type `f32` (element of input `f32x4`), found `i32` + + let _: f32 = simd_reduce_and(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + let _: f32 = simd_reduce_or(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + let _: f32 = simd_reduce_xor(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + + let _: f32 = simd_reduce_and(z); + //~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` + let _: f32 = simd_reduce_or(z); + //~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` + let _: f32 = simd_reduce_xor(z); + //~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` + + let _: bool = simd_reduce_all(z); + //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` + let _: bool = simd_reduce_any(z); + //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` + } +} diff --git a/tests/ui/simd/intrinsic/generic-reduction.stderr b/tests/ui/simd/intrinsic/generic-reduction.stderr new file mode 100644 index 000000000..1028faf69 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-reduction.stderr @@ -0,0 +1,63 @@ +error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` + --> $DIR/generic-reduction.rs:34:9 + | +LL | simd_reduce_add_ordered(z, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` + --> $DIR/generic-reduction.rs:36:9 + | +LL | simd_reduce_mul_ordered(z, 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` + --> $DIR/generic-reduction.rs:39:22 + | +LL | let _: f32 = simd_reduce_and(x); + | ^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` + --> $DIR/generic-reduction.rs:41:22 + | +LL | let _: f32 = simd_reduce_or(x); + | ^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` + --> $DIR/generic-reduction.rs:43:22 + | +LL | let _: f32 = simd_reduce_xor(x); + | ^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` + --> $DIR/generic-reduction.rs:46:22 + | +LL | let _: f32 = simd_reduce_and(z); + | ^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` + --> $DIR/generic-reduction.rs:48:22 + | +LL | let _: f32 = simd_reduce_or(z); + | ^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` + --> $DIR/generic-reduction.rs:50:22 + | +LL | let _: f32 = simd_reduce_xor(z); + | ^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_all` intrinsic: unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` + --> $DIR/generic-reduction.rs:53:23 + | +LL | let _: bool = simd_reduce_all(z); + | ^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_reduce_any` intrinsic: unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` + --> $DIR/generic-reduction.rs:55:23 + | +LL | let _: bool = simd_reduce_any(z); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-select-pass.rs b/tests/ui/simd/intrinsic/generic-select-pass.rs new file mode 100644 index 000000000..b850cf975 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-select-pass.rs @@ -0,0 +1,195 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-emscripten +// ignore-endian-big behavior of simd_select_bitmask is endian-specific + +// Test that the simd_select intrinsics produces correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +extern "platform-intrinsic" { + fn simd_select(x: T, a: U, b: U) -> U; + fn simd_select_bitmask(x: T, a: U, b: U) -> U; +} + +fn main() { + let m0 = b8x4(!0, !0, !0, !0); + let m1 = b8x4(0, 0, 0, 0); + let m2 = b8x4(!0, !0, 0, 0); + let m3 = b8x4(0, 0, !0, !0); + let m4 = b8x4(!0, 0, !0, 0); + + unsafe { + let a = i32x4(1, -2, 3, 4); + let b = i32x4(5, 6, -7, 8); + + let r: i32x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: i32x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: i32x4 = simd_select(m2, a, b); + let e = i32x4(1, -2, -7, 8); + assert_eq!(r, e); + + let r: i32x4 = simd_select(m3, a, b); + let e = i32x4(5, 6, 3, 4); + assert_eq!(r, e); + + let r: i32x4 = simd_select(m4, a, b); + let e = i32x4(1, 6, 3, 8); + assert_eq!(r, e); + } + + unsafe { + let a = u32x4(1, 2, 3, 4); + let b = u32x4(5, 6, 7, 8); + + let r: u32x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: u32x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: u32x4 = simd_select(m2, a, b); + let e = u32x4(1, 2, 7, 8); + assert_eq!(r, e); + + let r: u32x4 = simd_select(m3, a, b); + let e = u32x4(5, 6, 3, 4); + assert_eq!(r, e); + + let r: u32x4 = simd_select(m4, a, b); + let e = u32x4(1, 6, 3, 8); + assert_eq!(r, e); + } + + unsafe { + let a = f32x4(1., 2., 3., 4.); + let b = f32x4(5., 6., 7., 8.); + + let r: f32x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: f32x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: f32x4 = simd_select(m2, a, b); + let e = f32x4(1., 2., 7., 8.); + assert_eq!(r, e); + + let r: f32x4 = simd_select(m3, a, b); + let e = f32x4(5., 6., 3., 4.); + assert_eq!(r, e); + + let r: f32x4 = simd_select(m4, a, b); + let e = f32x4(1., 6., 3., 8.); + assert_eq!(r, e); + } + + unsafe { + let t = !0 as i8; + let f = 0 as i8; + let a = b8x4(t, f, t, f); + let b = b8x4(f, f, f, t); + + let r: b8x4 = simd_select(m0, a, b); + let e = a; + assert_eq!(r, e); + + let r: b8x4 = simd_select(m1, a, b); + let e = b; + assert_eq!(r, e); + + let r: b8x4 = simd_select(m2, a, b); + let e = b8x4(t, f, f, t); + assert_eq!(r, e); + + let r: b8x4 = simd_select(m3, a, b); + let e = b8x4(f, f, t, f); + assert_eq!(r, e); + + let r: b8x4 = simd_select(m4, a, b); + let e = b8x4(t, f, t, t); + assert_eq!(r, e); + } + + unsafe { + let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7); + let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15); + + let r: u32x8 = simd_select_bitmask(0u8, a, b); + let e = b; + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0xffu8, a, b); + let e = a; + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b); + let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15); + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b); + let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7); + assert_eq!(r, e); + + let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b); + let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7); + assert_eq!(r, e); + } + + unsafe { + let a = u32x4(0, 1, 2, 3); + let b = u32x4(4, 5, 6, 7); + + let r: u32x4 = simd_select_bitmask(0u8, a, b); + let e = b; + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0xfu8, a, b); + let e = a; + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0b0101u8, a, b); + let e = u32x4(0, 5, 2, 7); + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0b1010u8, a, b); + let e = u32x4(4, 1, 6, 3); + assert_eq!(r, e); + + let r: u32x4 = simd_select_bitmask(0b1100u8, a, b); + let e = u32x4(4, 5, 2, 3); + assert_eq!(r, e); + } +} diff --git a/tests/ui/simd/intrinsic/generic-select.rs b/tests/ui/simd/intrinsic/generic-select.rs new file mode 100644 index 000000000..248e82ea2 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-select.rs @@ -0,0 +1,63 @@ +// build-fail + +// Test that the simd_select intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq)] +struct b8x8(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8); + +extern "platform-intrinsic" { + fn simd_select(x: T, a: U, b: U) -> U; + fn simd_select_bitmask(x: T, a: U, b: U) -> U; +} + +fn main() { + let m4 = b8x4(0, 0, 0, 0); + let m8 = b8x8(0, 0, 0, 0, 0, 0, 0, 0); + let x = u32x4(0, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_select(m4, x, x); + + simd_select(m8, x, x); + //~^ ERROR mismatched lengths: mask length `8` != other vector length `4` + + simd_select(x, x, x); + //~^ ERROR mask element type is `u32`, expected `i_` + + simd_select(z, z, z); + //~^ ERROR mask element type is `f32`, expected `i_` + + simd_select(m4, 0u32, 1u32); + //~^ ERROR found non-SIMD `u32` + + simd_select_bitmask(0u16, x, x); + //~^ ERROR invalid bitmask `u16`, expected `u8` or `[u8; 1]` + + simd_select_bitmask(0u8, 1u32, 2u32); + //~^ ERROR found non-SIMD `u32` + + simd_select_bitmask(0.0f32, x, x); + //~^ ERROR invalid bitmask `f32`, expected `u8` or `[u8; 1]` + + simd_select_bitmask("x", x, x); + //~^ ERROR invalid bitmask `&str`, expected `u8` or `[u8; 1]` + } +} diff --git a/tests/ui/simd/intrinsic/generic-select.stderr b/tests/ui/simd/intrinsic/generic-select.stderr new file mode 100644 index 000000000..d576f1bc7 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-select.stderr @@ -0,0 +1,51 @@ +error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4` + --> $DIR/generic-select.rs:39:9 + | +LL | simd_select(m8, x, x); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_` + --> $DIR/generic-select.rs:42:9 + | +LL | simd_select(x, x, x); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_` + --> $DIR/generic-select.rs:45:9 + | +LL | simd_select(z, z, z); + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32` + --> $DIR/generic-select.rs:48:9 + | +LL | simd_select(m4, 0u32, 1u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `u16`, expected `u8` or `[u8; 1]` + --> $DIR/generic-select.rs:51:9 + | +LL | simd_select_bitmask(0u16, x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32` + --> $DIR/generic-select.rs:54:9 + | +LL | simd_select_bitmask(0u8, 1u32, 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `f32`, expected `u8` or `[u8; 1]` + --> $DIR/generic-select.rs:57:9 + | +LL | simd_select_bitmask(0.0f32, x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `&str`, expected `u8` or `[u8; 1]` + --> $DIR/generic-select.rs:60:9 + | +LL | simd_select_bitmask("x", x, x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/generic-shuffle.rs b/tests/ui/simd/intrinsic/generic-shuffle.rs new file mode 100644 index 000000000..9611780ac --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-shuffle.rs @@ -0,0 +1,33 @@ +// build-fail + +// Test that the simd_shuffle intrinsic produces ok-ish error +// messages when misused. + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct Simd([T; N]); + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +fn main() { + const I: [u32; 2] = [0; 2]; + const I2: [f32; 2] = [0.; 2]; + let v = Simd::([0; 4]); + + unsafe { + let _: Simd = simd_shuffle(v, v, I); + + let _: Simd = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + + let _: Simd = simd_shuffle(v, v, I2); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } +} diff --git a/tests/ui/simd/intrinsic/generic-shuffle.stderr b/tests/ui/simd/intrinsic/generic-shuffle.stderr new file mode 100644 index 000000000..81e641612 --- /dev/null +++ b/tests/ui/simd/intrinsic/generic-shuffle.stderr @@ -0,0 +1,21 @@ +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4 + --> $DIR/generic-shuffle.rs:24:31 + | +LL | let _: Simd = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32` + --> $DIR/generic-shuffle.rs:27:31 + | +LL | let _: Simd = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]` + --> $DIR/generic-shuffle.rs:30:31 + | +LL | let _: Simd = simd_shuffle(v, v, I2); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs new file mode 100644 index 000000000..7221b3ab7 --- /dev/null +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -0,0 +1,26 @@ +// This used to cause an ICE for an internal index out of range due to simd_shuffle_indices being +// passed the wrong Instance, causing issues with inlining. See #67557. +// +// run-pass +// compile-flags: -Zmir-opt-level=4 +#![feature(platform_intrinsics, repr_simd)] + +extern "platform-intrinsic" { + fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; +} + +#[repr(simd)] +#[derive(Debug, PartialEq)] +struct Simd2(u8, u8); + +fn main() { + unsafe { + let _: Simd2 = inline_me(); + } +} + +#[inline(always)] +unsafe fn inline_me() -> Simd2 { + const IDX: [u32; 2] = [0, 3]; + simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) +} diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs new file mode 100644 index 000000000..0d1542709 --- /dev/null +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -0,0 +1,42 @@ +// This used to cause assert_10_13 to unexpectingly fail, due to simd_shuffle_indices being passed +// the wrong Instance, causing issues with inlining. See #67557. +// +// run-pass +// compile-flags: -Zmir-opt-level=4 +#![feature(platform_intrinsics, repr_simd)] + +extern "platform-intrinsic" { + fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; +} + +#[repr(simd)] +#[derive(Debug, PartialEq)] +struct Simd2(u8, u8); + +fn main() { + unsafe { + const IDX: [u32; 2] = [0, 1]; + let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX); + let a_res: Simd2 = inline_me(); + + assert_10_11(p_res); + assert_10_13(a_res); + } +} + +#[inline(never)] +fn assert_10_11(x: Simd2) { + assert_eq!(x, Simd2(10, 11)); +} + +#[inline(never)] +fn assert_10_13(x: Simd2) { + assert_eq!(x, Simd2(10, 13)); +} + + +#[inline(always)] +unsafe fn inline_me() -> Simd2 { + const IDX: [u32; 2] = [0, 3]; + simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) +} diff --git a/tests/ui/simd/intrinsic/issue-85855.rs b/tests/ui/simd/intrinsic/issue-85855.rs new file mode 100644 index 000000000..f276fbd66 --- /dev/null +++ b/tests/ui/simd/intrinsic/issue-85855.rs @@ -0,0 +1,19 @@ +// Check that appropriate errors are reported if an intrinsic is defined +// with the wrong number of generic lifetime/type/const parameters, and +// that no ICE occurs in these cases. + +#![feature(platform_intrinsics)] +#![crate_type="lib"] + +extern "platform-intrinsic" { + fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of lifetime parameters + + fn simd_add<'a, T>(x: T, y: T) -> T; + + fn simd_sub(x: T, y: U); + //~^ ERROR: intrinsic has wrong number of type parameters + + fn simd_mul(x: T, y: T); + //~^ ERROR: intrinsic has wrong number of const parameters +} diff --git a/tests/ui/simd/intrinsic/issue-85855.stderr b/tests/ui/simd/intrinsic/issue-85855.stderr new file mode 100644 index 000000000..fb2f1fbc5 --- /dev/null +++ b/tests/ui/simd/intrinsic/issue-85855.stderr @@ -0,0 +1,21 @@ +error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:9:27 + | +LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + | ^^^^^^^^^^^ expected 0 lifetime parameters + +error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 + --> $DIR/issue-85855.rs:14:16 + | +LL | fn simd_sub(x: T, y: U); + | ^^^^^^ expected 1 type parameter + +error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 + --> $DIR/issue-85855.rs:17:16 + | +LL | fn simd_mul(x: T, y: T); + | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0094`. diff --git a/tests/ui/simd/intrinsic/ptr-cast.rs b/tests/ui/simd/intrinsic/ptr-cast.rs new file mode 100644 index 000000000..1d13720bc --- /dev/null +++ b/tests/ui/simd/intrinsic/ptr-cast.rs @@ -0,0 +1,33 @@ +// run-pass + +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_cast_ptr(x: T) -> U; + fn simd_expose_addr(x: T) -> U; + fn simd_from_exposed_addr(x: T) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct V([T; 2]); + +fn main() { + unsafe { + let mut foo = 4i8; + let ptr = &mut foo as *mut i8; + + let ptrs = V::<*mut i8>([ptr, core::ptr::null_mut()]); + + // change constness and type + let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs); + + let exposed_addr: V = simd_expose_addr(const_ptrs); + + let from_exposed_addr: V<*mut i8> = simd_from_exposed_addr(exposed_addr); + + assert!(const_ptrs.0 == [ptr as *const u8, core::ptr::null()]); + assert!(exposed_addr.0 == [ptr as usize, 0]); + assert!(from_exposed_addr.0 == ptrs.0); + } +} diff --git a/tests/ui/simd/issue-17170.rs b/tests/ui/simd/issue-17170.rs new file mode 100644 index 000000000..8d70dacdc --- /dev/null +++ b/tests/ui/simd/issue-17170.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(repr_simd)] + +#[repr(simd)] +struct T(f64, f64, f64); + +static X: T = T(0.0, 0.0, 0.0); + +fn main() { + let _ = X; +} diff --git a/tests/ui/simd/issue-32947.rs b/tests/ui/simd/issue-32947.rs new file mode 100644 index 000000000..b07def21e --- /dev/null +++ b/tests/ui/simd/issue-32947.rs @@ -0,0 +1,24 @@ +// run-pass +// ignore-emscripten FIXME(#45351) + +#![feature(repr_simd, test)] + +extern crate test; + +#[repr(simd)] +pub struct Mu64(pub u64, pub u64, pub u64, pub u64); + +fn main() { + // This ensures an unaligned pointer even in optimized builds, though LLVM + // gets enough type information to actually not mess things up in that case, + // but at the time of writing this, it's enough to trigger the bug in + // non-optimized builds + unsafe { + let memory = &mut [0u64; 8] as *mut _ as *mut u8; + let misaligned_ptr: &mut [u8; 32] = { + std::mem::transmute(memory.offset(1)) + }; + *misaligned_ptr = std::mem::transmute(Mu64(1, 1, 1, 1)); + test::black_box(memory); + } +} diff --git a/tests/ui/simd/issue-39720.rs b/tests/ui/simd/issue-39720.rs new file mode 100644 index 000000000..8cf841f93 --- /dev/null +++ b/tests/ui/simd/issue-39720.rs @@ -0,0 +1,22 @@ +// run-pass +// ignore-emscripten FIXME(#45351) + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone, Debug)] +pub struct Char3(pub i8, pub i8, pub i8); + +#[repr(simd)] +#[derive(Copy, Clone, Debug)] +pub struct Short3(pub i16, pub i16, pub i16); + +extern "platform-intrinsic" { + fn simd_cast(x: T) -> U; +} + +fn main() { + let cast: Short3 = unsafe { simd_cast(Char3(10, -3, -9)) }; + + println!("{:?}", cast); +} diff --git a/tests/ui/simd/issue-85915-simd-ptrs.rs b/tests/ui/simd/issue-85915-simd-ptrs.rs new file mode 100644 index 000000000..6fe415545 --- /dev/null +++ b/tests/ui/simd/issue-85915-simd-ptrs.rs @@ -0,0 +1,67 @@ +// run-pass +// ignore-emscripten + +// Short form of the generic gather/scatter tests, +// verifying simd([*const T; N]) and simd([*mut T; N]) pass typeck and work. +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct cptrx4([*const T; 4]); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct mptrx4([*mut T; 4]); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct f32x4([f32; 4]); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct i32x4([i32; 4]); + +extern "platform-intrinsic" { + fn simd_gather(x: T, y: U, z: V) -> T; + fn simd_scatter(x: T, y: U, z: V) -> (); +} + +fn main() { + let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; + + let default = f32x4([-3_f32, -3., -3., -3.]); + let s_strided = f32x4([0_f32, 2., -3., 6.]); + let mask = i32x4([-1_i32, -1, 0, -1]); + + // reading from *const + unsafe { + let pointer = &x as *const f32; + let pointers = cptrx4([ + pointer.offset(0) as *const f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ]); + + let r_strided = simd_gather(default, pointers, mask); + + assert_eq!(r_strided, s_strided); + } + + // writing to *mut + unsafe { + let pointer = &mut x as *mut f32; + let pointers = mptrx4([ + pointer.offset(0) as *mut f32, + pointer.offset(2), + pointer.offset(4), + pointer.offset(6) + ]); + + let values = f32x4([42_f32, 43_f32, 44_f32, 45_f32]); + simd_scatter(values, pointers, mask); + + assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); + } +} diff --git a/tests/ui/simd/issue-89193.rs b/tests/ui/simd/issue-89193.rs new file mode 100644 index 000000000..79c4e6a31 --- /dev/null +++ b/tests/ui/simd/issue-89193.rs @@ -0,0 +1,51 @@ +// run-pass + +// Test that simd gather instructions on slice of usize don't cause crash +// See issue #89183 - https://github.com/rust-lang/rust/issues/89193 + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct x4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_gather(x: T, y: U, z: V) -> T; +} + +fn main() { + let x: [usize; 4] = [10, 11, 12, 13]; + let default = x4(0_usize, 1, 2, 3); + let mask = x4(1_i32, 1, 1, 1); + let expected = x4(10_usize, 11, 12, 13); + + unsafe { + let pointer = &x[0] as *const usize; + let pointers = x4( + pointer.offset(0) as *const usize, + pointer.offset(1), + pointer.offset(2), + pointer.offset(3) + ); + let result = simd_gather(default, pointers, mask); + assert_eq!(result, expected); + } + + // and again for isize + let x: [isize; 4] = [10, 11, 12, 13]; + let default = x4(0_isize, 1, 2, 3); + let expected = x4(10_isize, 11, 12, 13); + + unsafe { + let pointer = &x[0] as *const isize; + let pointers = x4( + pointer.offset(0) as *const isize, + pointer.offset(1), + pointer.offset(2), + pointer.offset(3) + ); + let result = simd_gather(default, pointers, mask); + assert_eq!(result, expected); + } +} diff --git a/tests/ui/simd/libm_no_std_cant_float.rs b/tests/ui/simd/libm_no_std_cant_float.rs new file mode 100644 index 000000000..50ac8e208 --- /dev/null +++ b/tests/ui/simd/libm_no_std_cant_float.rs @@ -0,0 +1,22 @@ +#![crate_type = "rlib"] +#![no_std] +#![feature(portable_simd)] +use core::simd::f32x4; +use core::simd::SimdFloat; + +// For SIMD float ops, the LLIR version which is used to implement the portable +// forms of them may become calls to math.h AKA libm. So, we can't guarantee +// we can compile them for #![no_std] crates. +// Someday we may solve this. +// Until then, this test at least guarantees these functions require std. +fn guarantee_no_std_nolibm_calls() -> f32x4 { + let x = f32x4::from_array([0.1, 0.5, 0.6, -1.5]); + let x2 = x + x; + let _xc = x.ceil(); //~ ERROR E0599 + let _xf = x.floor(); //~ ERROR E0599 + let _xr = x.round(); //~ ERROR E0599 + let _xt = x.trunc(); //~ ERROR E0599 + let _xfma = x.mul_add(x, x); //~ ERROR E0599 + let _xsqrt = x.sqrt(); //~ ERROR E0599 + x2.abs() * x2 +} diff --git a/tests/ui/simd/libm_no_std_cant_float.stderr b/tests/ui/simd/libm_no_std_cant_float.stderr new file mode 100644 index 000000000..97e0b7efe --- /dev/null +++ b/tests/ui/simd/libm_no_std_cant_float.stderr @@ -0,0 +1,39 @@ +error[E0599]: no method named `ceil` found for struct `Simd` in the current scope + --> $DIR/libm_no_std_cant_float.rs:15:17 + | +LL | let _xc = x.ceil(); + | ^^^^ method not found in `Simd` + +error[E0599]: no method named `floor` found for struct `Simd` in the current scope + --> $DIR/libm_no_std_cant_float.rs:16:17 + | +LL | let _xf = x.floor(); + | ^^^^^ method not found in `Simd` + +error[E0599]: no method named `round` found for struct `Simd` in the current scope + --> $DIR/libm_no_std_cant_float.rs:17:17 + | +LL | let _xr = x.round(); + | ^^^^^ method not found in `Simd` + +error[E0599]: no method named `trunc` found for struct `Simd` in the current scope + --> $DIR/libm_no_std_cant_float.rs:18:17 + | +LL | let _xt = x.trunc(); + | ^^^^^ method not found in `Simd` + +error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope + --> $DIR/libm_no_std_cant_float.rs:19:19 + | +LL | let _xfma = x.mul_add(x, x); + | ^^^^^^^ method not found in `Simd` + +error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope + --> $DIR/libm_no_std_cant_float.rs:20:20 + | +LL | let _xsqrt = x.sqrt(); + | ^^^^ method not found in `Simd` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/simd/libm_std_can_float.rs b/tests/ui/simd/libm_std_can_float.rs new file mode 100644 index 000000000..1c520856e --- /dev/null +++ b/tests/ui/simd/libm_std_can_float.rs @@ -0,0 +1,23 @@ +// run-pass + +// This is the converse of the other libm test. +#![feature(portable_simd)] +use std::simd::f32x4; +use std::simd::{SimdFloat, StdFloat}; + +// For SIMD float ops, the LLIR version which is used to implement the portable +// forms of them may become calls to math.h AKA libm. So, we can't guarantee +// we can compile them for #![no_std] crates. +// +// However, we can expose some of these ops via an extension trait. +fn main() { + let x = f32x4::from_array([0.1, 0.5, 0.6, -1.5]); + let x2 = x + x; + let _xc = x.ceil(); + let _xf = x.floor(); + let _xr = x.round(); + let _xt = x.trunc(); + let _xfma = x.mul_add(x, x); + let _xsqrt = x.sqrt(); + let _ = x2.abs() * x2; +} diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs new file mode 100644 index 000000000..2467baa08 --- /dev/null +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -0,0 +1,40 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd([T; N]); + +trait Shuffle { + const I: [u32; N]; + + unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd { + simd_shuffle(a, b, Self::I) + } +} + +fn main() { + struct I1; + impl Shuffle<4> for I1 { + const I: [u32; 4] = [0, 2, 4, 6]; + } + + struct I2; + impl Shuffle<2> for I2 { + const I: [u32; 2] = [1, 5]; + } + + let a = Simd::([0, 1, 2, 3]); + let b = Simd::([4, 5, 6, 7]); + unsafe { + let x: Simd = I1.shuffle(a, b); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd = I2.shuffle(a, b); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/tests/ui/simd/portable-intrinsics-arent-exposed.rs b/tests/ui/simd/portable-intrinsics-arent-exposed.rs new file mode 100644 index 000000000..667c8b67b --- /dev/null +++ b/tests/ui/simd/portable-intrinsics-arent-exposed.rs @@ -0,0 +1,9 @@ +// May not matter, since people can use them with a nightly feature. +// However this tests to guarantee they don't leak out via portable_simd, +// and thus don't accidentally get stabilized. +use core::simd::intrinsics; //~ERROR E0433 +use std::simd::intrinsics; //~ERROR E0432 + +fn main() { + () +} diff --git a/tests/ui/simd/portable-intrinsics-arent-exposed.stderr b/tests/ui/simd/portable-intrinsics-arent-exposed.stderr new file mode 100644 index 000000000..f8b3e6d65 --- /dev/null +++ b/tests/ui/simd/portable-intrinsics-arent-exposed.stderr @@ -0,0 +1,23 @@ +error[E0433]: failed to resolve: maybe a missing crate `core`? + --> $DIR/portable-intrinsics-arent-exposed.rs:4:5 + | +LL | use core::simd::intrinsics; + | ^^^^ maybe a missing crate `core`? + | + = help: consider adding `extern crate core` to use the `core` crate + +error[E0432]: unresolved import `std::simd::intrinsics` + --> $DIR/portable-intrinsics-arent-exposed.rs:5:5 + | +LL | use std::simd::intrinsics; + | ^^^^^^^^^^^^^^^^^^^^^ no `intrinsics` in `simd` + | +help: consider importing this module instead + | +LL | use std::intrinsics; + | ~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.rs b/tests/ui/simd/shuffle-not-out-of-bounds.rs new file mode 100644 index 000000000..0dee3a0e8 --- /dev/null +++ b/tests/ui/simd/shuffle-not-out-of-bounds.rs @@ -0,0 +1,87 @@ +// build-fail +#![allow(non_camel_case_types)] +#![feature(repr_simd, platform_intrinsics)] + +// Test for #73542 to verify out-of-bounds shuffle vectors do not compile. + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x2([u8; 2]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x4([u8; 4]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x8([u8; 8]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x16([u8; 16]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x32([u8; 32]); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u8x64([u8; 64]); + +extern "platform-intrinsic" { + pub fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + pub fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; + pub fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; + pub fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; + pub fn simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U; + pub fn simd_shuffle64(x: T, y: T, idx: [u32; 64]) -> U; +} + +// Test vectors by lane size. Since LLVM does not distinguish between a shuffle +// over two f32s and a shuffle over two u64s, or any other such combination, +// it is not necessary to test every possible vector, only lane counts. +macro_rules! test_shuffle_lanes { + ($n:literal, $x:ident, $y:ident) => { + unsafe { + let shuffle: $x = { + const ARR: [u32; $n] = { + let mut arr = [0; $n]; + arr[0] = $n * 2; + arr + }; + let mut n: u8 = $n; + let vals = [0; $n].map(|_| { n = n - 1; n }); + let vec1 = $x(vals); + let vec2 = $x(vals); + $y(vec1, vec2, ARR) + }; + } + } +} +//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle2` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle4` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle8` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle16` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle32` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle64` intrinsic +// Because the test is mostly embedded in a macro, all the errors have the same origin point. +// And unfortunately, standard comments, as in the UI test harness, disappear in macros! + +fn main() { + test_shuffle_lanes!(2, u8x2, simd_shuffle2); + test_shuffle_lanes!(4, u8x4, simd_shuffle4); + test_shuffle_lanes!(8, u8x8, simd_shuffle8); + test_shuffle_lanes!(16, u8x16, simd_shuffle16); + test_shuffle_lanes!(32, u8x32, simd_shuffle32); + test_shuffle_lanes!(64, u8x64, simd_shuffle64); + + extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; + } + let v = u8x2([0, 0]); + const I: [u32; 2] = [4, 4]; + unsafe { + let _: u8x2 = simd_shuffle(v, v, I); + //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic + } +} diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.stderr b/tests/ui/simd/shuffle-not-out-of-bounds.stderr new file mode 100644 index 000000000..415f04d93 --- /dev/null +++ b/tests/ui/simd/shuffle-not-out-of-bounds.stderr @@ -0,0 +1,75 @@ +error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 + | +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ +... +LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2); + | ------------------------------------------- in this macro invocation + | + = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8) + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 + | +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ +... +LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4); + | ------------------------------------------- in this macro invocation + | + = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16) + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 + | +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ +... +LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8); + | ------------------------------------------- in this macro invocation + | + = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0511]: invalid monomorphization of `simd_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32) + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 + | +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ +... +LL | test_shuffle_lanes!(16, u8x16, simd_shuffle16); + | ---------------------------------------------- in this macro invocation + | + = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0511]: invalid monomorphization of `simd_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64) + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 + | +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ +... +LL | test_shuffle_lanes!(32, u8x32, simd_shuffle32); + | ---------------------------------------------- in this macro invocation + | + = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0511]: invalid monomorphization of `simd_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128) + --> $DIR/shuffle-not-out-of-bounds.rs:56:21 + | +LL | $y(vec1, vec2, ARR) + | ^^^^^^^^^^^^^^^^^^^ +... +LL | test_shuffle_lanes!(64, u8x64, simd_shuffle64); + | ---------------------------------------------- in this macro invocation + | + = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:84:23 + | +LL | let _: u8x2 = simd_shuffle(v, v, I); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs new file mode 100644 index 000000000..3592adfdc --- /dev/null +++ b/tests/ui/simd/shuffle.rs @@ -0,0 +1,24 @@ +//run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_shuffle(a: T, b: T, i: I) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + const I1: [u32; 4] = [0, 2, 4, 6]; + const I2: [u32; 2] = [1, 5]; + let a = Simd::([0, 1, 2, 3]); + let b = Simd::([4, 5, 6, 7]); + unsafe { + let x: Simd = simd_shuffle(a, b, I1); + assert_eq!(x.0, [0, 2, 4, 6]); + + let y: Simd = simd_shuffle(a, b, I2); + assert_eq!(y.0, [1, 5]); + } +} diff --git a/tests/ui/simd/simd-bitmask.rs b/tests/ui/simd/simd-bitmask.rs new file mode 100644 index 000000000..14ee2e741 --- /dev/null +++ b/tests/ui/simd/simd-bitmask.rs @@ -0,0 +1,52 @@ +//run-pass +//ignore-endian-big behavior of simd_select_bitmask is endian-specific +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_bitmask(v: T) -> U; + fn simd_select_bitmask(m: T, a: U, b: U) -> U; +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + unsafe { + let v = Simd::([-1, 0, -1, 0]); + let i: u8 = simd_bitmask(v); + let a: [u8; 1] = simd_bitmask(v); + + assert_eq!(i, 0b0101); + assert_eq!(a, [0b0101]); + + let v = Simd::([0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0]); + let i: u16 = simd_bitmask(v); + let a: [u8; 2] = simd_bitmask(v); + + assert_eq!(i, 0b0101000000001100); + assert_eq!(a, [0b1100, 0b01010000]); + } + + unsafe { + let a = Simd::([0, 1, 2, 3, 4, 5, 6, 7]); + let b = Simd::([8, 9, 10, 11, 12, 13, 14, 15]); + let e = [0, 9, 2, 11, 12, 13, 14, 15]; + + let r = simd_select_bitmask(0b0101u8, a, b); + assert_eq!(r.0, e); + + let r = simd_select_bitmask([0b0101u8], a, b); + assert_eq!(r.0, e); + + let a = Simd::([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let b = Simd::([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); + let e = [16, 17, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 12, 29, 14, 31]; + + let r = simd_select_bitmask(0b0101000000001100u16, a, b); + assert_eq!(r.0, e); + + let r = simd_select_bitmask([0b1100u8, 0b01010000u8], a, b); + assert_eq!(r.0, e); + } +} diff --git a/tests/ui/simd/size-align.rs b/tests/ui/simd/size-align.rs new file mode 100644 index 000000000..0afa49472 --- /dev/null +++ b/tests/ui/simd/size-align.rs @@ -0,0 +1,53 @@ +// run-pass +#![allow(deprecated)] + + +#![feature(repr_simd)] +#![allow(non_camel_case_types)] + +use std::mem; + +/// `T` should satisfy `size_of T (mod min_align_of T) === 0` to be stored at `Vec` properly +/// Please consult the issue #20460 +fn check() { + assert_eq!(mem::size_of::() % mem::min_align_of::(), 0); + assert_eq!(mem::size_of::() % mem::min_align_of::(), 0); + assert_eq!(mem::size_of::() % mem::min_align_of::(), 0); +} + +#[repr(simd)] +struct U8([u8; N]); + +#[repr(simd)] +struct I16([i16; N]); + +#[repr(simd)] +struct F32([f32; N]); + +#[repr(simd)] +struct Usize([usize; N]); + +#[repr(simd)] +struct Isize([isize; N]); + +fn main() { + check::>(); + check::>(); + check::>(); + + check::>(); + check::>(); + check::>(); + + check::>(); + check::>(); + check::>(); + + check::>(); + check::>(); + check::>(); + + check::>(); + check::>(); + check::>(); +} diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs new file mode 100644 index 000000000..5dd163715 --- /dev/null +++ b/tests/ui/simd/target-feature-mixup.rs @@ -0,0 +1,186 @@ +// run-pass +#![allow(unused_variables)] +#![allow(stable_features)] +#![allow(overflowing_literals)] + +// ignore-emscripten +// ignore-sgx no processes +// ignore-fuchsia must translate zircon signal to SIGILL, FIXME (#58590) + +#![feature(repr_simd, target_feature, cfg_target_feature)] +#![feature(avx512_target_feature)] + +use std::process::{Command, ExitStatus}; +use std::env; + +fn main() { + if let Some(level) = env::args().nth(1) { + return test::main(&level) + } + + let me = env::current_exe().unwrap(); + for level in ["sse", "avx", "avx512"].iter() { + let status = Command::new(&me).arg(level).status().unwrap(); + if status.success() { + println!("success with {}", level); + continue + } + + // We don't actually know if our computer has the requisite target features + // for the test below. Testing for that will get added to libstd later so + // for now just assume sigill means this is a machine that can't run this test. + if is_sigill(status) { + println!("sigill with {}, assuming spurious", level); + continue + } + panic!("invalid status at {}: {}", level, status); + } +} + +#[cfg(unix)] +fn is_sigill(status: ExitStatus) -> bool { + use std::os::unix::prelude::*; + status.signal() == Some(4) +} + +#[cfg(windows)] +fn is_sigill(status: ExitStatus) -> bool { + status.code() == Some(0xc000001d) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +#[allow(nonstandard_style)] +mod test { + // An SSE type + #[repr(simd)] + #[derive(PartialEq, Debug, Clone, Copy)] + struct __m128i(u64, u64); + + // An AVX type + #[repr(simd)] + #[derive(PartialEq, Debug, Clone, Copy)] + struct __m256i(u64, u64, u64, u64); + + // An AVX-512 type + #[repr(simd)] + #[derive(PartialEq, Debug, Clone, Copy)] + struct __m512i(u64, u64, u64, u64, u64, u64, u64, u64); + + pub fn main(level: &str) { + unsafe { + main_normal(level); + main_sse(level); + if level == "sse" { + return + } + main_avx(level); + if level == "avx" { + return + } + main_avx512(level); + } + } + + macro_rules! mains { + ($( + $(#[$attr:meta])* + unsafe fn $main:ident(level: &str) { + ... + } + )*) => ($( + $(#[$attr])* + unsafe fn $main(level: &str) { + let m128 = __m128i(1, 2); + let m256 = __m256i(3, 4, 5, 6); + let m512 = __m512i(7, 8, 9, 10, 11, 12, 13, 14); + assert_eq!(id_sse_128(m128), m128); + assert_eq!(id_sse_256(m256), m256); + assert_eq!(id_sse_512(m512), m512); + + if level == "sse" { + return + } + assert_eq!(id_avx_128(m128), m128); + assert_eq!(id_avx_256(m256), m256); + assert_eq!(id_avx_512(m512), m512); + + if level == "avx" { + return + } + assert_eq!(id_avx512_128(m128), m128); + assert_eq!(id_avx512_256(m256), m256); + assert_eq!(id_avx512_512(m512), m512); + } + )*) + } + + mains! { + unsafe fn main_normal(level: &str) { ... } + #[target_feature(enable = "sse2")] + unsafe fn main_sse(level: &str) { ... } + #[target_feature(enable = "avx")] + unsafe fn main_avx(level: &str) { ... } + #[target_feature(enable = "avx512bw")] + unsafe fn main_avx512(level: &str) { ... } + } + + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_128(a: __m128i) -> __m128i { + assert_eq!(a, __m128i(1, 2)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_256(a: __m256i) -> __m256i { + assert_eq!(a, __m256i(3, 4, 5, 6)); + a.clone() + } + + #[target_feature(enable = "sse2")] + unsafe fn id_sse_512(a: __m512i) -> __m512i { + assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_128(a: __m128i) -> __m128i { + assert_eq!(a, __m128i(1, 2)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_256(a: __m256i) -> __m256i { + assert_eq!(a, __m256i(3, 4, 5, 6)); + a.clone() + } + + #[target_feature(enable = "avx")] + unsafe fn id_avx_512(a: __m512i) -> __m512i { + assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_128(a: __m128i) -> __m128i { + assert_eq!(a, __m128i(1, 2)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_256(a: __m256i) -> __m256i { + assert_eq!(a, __m256i(3, 4, 5, 6)); + a.clone() + } + + #[target_feature(enable = "avx512bw")] + unsafe fn id_avx512_512(a: __m512i) -> __m512i { + assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + a.clone() + } +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +mod test { + pub fn main(level: &str) {} +} diff --git a/tests/ui/simd/type-generic-monomorphisation-empty.rs b/tests/ui/simd/type-generic-monomorphisation-empty.rs new file mode 100644 index 000000000..2bf6641e9 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-empty.rs @@ -0,0 +1,12 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + +// error-pattern:monomorphising SIMD type `Simd<0>` of zero length + +#[repr(simd)] +struct Simd([f32; N]); + +fn main() { + let _ = Simd::<0>([]); +} diff --git a/tests/ui/simd/type-generic-monomorphisation-empty.stderr b/tests/ui/simd/type-generic-monomorphisation-empty.stderr new file mode 100644 index 000000000..b334b1f4b --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-empty.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd<0>` of zero length + +error: aborting due to previous error + diff --git a/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs new file mode 100644 index 000000000..ae321c974 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs @@ -0,0 +1,23 @@ +// run-pass +// ignore-emscripten + +#![feature(extern_types)] +#![feature(repr_simd)] + +use std::ptr::NonNull; + +extern { + type Extern; +} + +#[repr(simd)] +struct S(T); + +#[inline(never)] +fn identity(v: T) -> T { + v +} + +fn main() { + let _v: S<[Option>; 4]> = identity(S([None; 4])); +} diff --git a/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs b/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs new file mode 100644 index 000000000..0bc73b155 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-non-primitive.rs @@ -0,0 +1,14 @@ +// build-fail + +#![feature(repr_simd)] + +struct E; + +// error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` + +#[repr(simd)] +struct S([T; 4]); + +fn main() { + let _v: Option> = None; +} diff --git a/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr b/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr new file mode 100644 index 000000000..9e8f06b82 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-non-primitive.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `E` + +error: aborting due to previous error + diff --git a/tests/ui/simd/type-generic-monomorphisation-oversized.rs b/tests/ui/simd/type-generic-monomorphisation-oversized.rs new file mode 100644 index 000000000..a7dc482f3 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-oversized.rs @@ -0,0 +1,12 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + +// error-pattern:monomorphising SIMD type `Simd<65536>` of length greater than 32768 + +#[repr(simd)] +struct Simd([f32; N]); + +fn main() { + let _ = Simd::<65536>([0.; 65536]); +} diff --git a/tests/ui/simd/type-generic-monomorphisation-oversized.stderr b/tests/ui/simd/type-generic-monomorphisation-oversized.stderr new file mode 100644 index 000000000..a2dba1222 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-oversized.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd<65536>` of length greater than 32768 + +error: aborting due to previous error + diff --git a/tests/ui/simd/type-generic-monomorphisation-power-of-two.rs b/tests/ui/simd/type-generic-monomorphisation-power-of-two.rs new file mode 100644 index 000000000..9b645d363 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-power-of-two.rs @@ -0,0 +1,10 @@ +// run-pass + +#![feature(repr_simd, platform_intrinsics)] + +#[repr(simd)] +struct Simd([f32; N]); + +fn main() { + let _ = Simd::<3>([0.; 3]); +} diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs new file mode 100644 index 000000000..3e02b08ce --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs @@ -0,0 +1,12 @@ +// build-fail + +#![feature(repr_simd)] + +// error-pattern:monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` + +#[repr(simd)] +struct S(T); + +fn main() { + let _v: Option> = None; +} diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr new file mode 100644 index 000000000..3888e7a0f --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` + +error: aborting due to previous error + diff --git a/tests/ui/simd/type-generic-monomorphisation.rs b/tests/ui/simd/type-generic-monomorphisation.rs new file mode 100644 index 000000000..12f9d65d7 --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation.rs @@ -0,0 +1,14 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + + +// error-pattern:monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` + +struct X(Vec); +#[repr(simd)] +struct Simd2(T, T); + +fn main() { + let _ = Simd2(X(vec![]), X(vec![])); +} diff --git a/tests/ui/simd/type-generic-monomorphisation.stderr b/tests/ui/simd/type-generic-monomorphisation.stderr new file mode 100644 index 000000000..7f23893ac --- /dev/null +++ b/tests/ui/simd/type-generic-monomorphisation.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd2` with a non-primitive-scalar (integer/float/pointer) element type `X` + +error: aborting due to previous error + diff --git a/tests/ui/simd/type-len.rs b/tests/ui/simd/type-len.rs new file mode 100644 index 000000000..d82c70b8d --- /dev/null +++ b/tests/ui/simd/type-len.rs @@ -0,0 +1,39 @@ +#![feature(repr_simd)] +#![allow(non_camel_case_types)] + + +#[repr(simd)] +struct empty; //~ ERROR SIMD vector cannot be empty + +#[repr(simd)] +struct empty2([f32; 0]); //~ ERROR SIMD vector cannot be empty + +#[repr(simd)] +struct pow2([f32; 7]); + +#[repr(simd)] +struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous + +struct Foo; + +#[repr(simd)] +struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type + +#[repr(simd)] +struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type + +#[repr(simd)] +struct TooBig([f32; 65536]); //~ ERROR SIMD vector cannot have more than 32768 elements + +#[repr(simd)] +struct JustRight([u128; 32768]); + +#[repr(simd)] +struct RGBA { + r: f32, + g: f32, + b: f32, + a: f32 +} + +fn main() {} diff --git a/tests/ui/simd/type-len.stderr b/tests/ui/simd/type-len.stderr new file mode 100644 index 000000000..2a6bd1b0f --- /dev/null +++ b/tests/ui/simd/type-len.stderr @@ -0,0 +1,40 @@ +error[E0075]: SIMD vector cannot be empty + --> $DIR/type-len.rs:6:1 + | +LL | struct empty; + | ^^^^^^^^^^^^ + +error[E0075]: SIMD vector cannot be empty + --> $DIR/type-len.rs:9:1 + | +LL | struct empty2([f32; 0]); + | ^^^^^^^^^^^^^ + +error[E0076]: SIMD vector should be homogeneous + --> $DIR/type-len.rs:15:1 + | +LL | struct i64f64(i64, f64); + | ^^^^^^^^^^^^^ SIMD elements must have the same type + +error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type + --> $DIR/type-len.rs:20:1 + | +LL | struct FooV(Foo, Foo); + | ^^^^^^^^^^^ + +error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type + --> $DIR/type-len.rs:23:1 + | +LL | struct FooV2([Foo; 2]); + | ^^^^^^^^^^^^ + +error[E0075]: SIMD vector cannot have more than 32768 elements + --> $DIR/type-len.rs:26:1 + | +LL | struct TooBig([f32; 65536]); + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0075, E0076, E0077. +For more information about an error, try `rustc --explain E0075`. diff --git a/tests/ui/simd/type-wide-ptr.rs b/tests/ui/simd/type-wide-ptr.rs new file mode 100644 index 000000000..88f62a07e --- /dev/null +++ b/tests/ui/simd/type-wide-ptr.rs @@ -0,0 +1,12 @@ +// build-fail + +#![feature(repr_simd)] + +// error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` + +#[repr(simd)] +struct S([*mut [u8]; 4]); + +fn main() { + let _v: Option = None; +} diff --git a/tests/ui/simd/type-wide-ptr.stderr b/tests/ui/simd/type-wide-ptr.stderr new file mode 100644 index 000000000..51d3c0050 --- /dev/null +++ b/tests/ui/simd/type-wide-ptr.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` + +error: aborting due to previous error + diff --git a/tests/ui/simd/wasm-simd-indirect.rs b/tests/ui/simd/wasm-simd-indirect.rs new file mode 100644 index 000000000..88f92fce2 --- /dev/null +++ b/tests/ui/simd/wasm-simd-indirect.rs @@ -0,0 +1,31 @@ +// build-pass + +#[cfg(target_arch = "wasm32")] +fn main() { + unsafe { + a::api_with_simd_feature(); + } +} + +#[cfg(target_arch = "wasm32")] +mod a { + use std::arch::wasm32::*; + + #[target_feature(enable = "simd128")] + pub unsafe fn api_with_simd_feature() { + crate::b::api_takes_v128(u64x2(0, 1)); + } +} + +#[cfg(target_arch = "wasm32")] +mod b { + use std::arch::wasm32::*; + + #[inline(never)] + pub fn api_takes_v128(a: v128) -> v128 { + a + } +} + +#[cfg(not(target_arch = "wasm32"))] +fn main() {} diff --git a/tests/ui/simple_global_asm.rs b/tests/ui/simple_global_asm.rs new file mode 100644 index 000000000..3c69379ff --- /dev/null +++ b/tests/ui/simple_global_asm.rs @@ -0,0 +1,29 @@ +// run-pass + +#![feature(naked_functions)] +#![allow(dead_code)] + +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +core::arch::global_asm!( + r#" + .global foo + .global _foo +foo: +_foo: + ret +"# +); + +extern "C" { + fn foo(); +} + +#[cfg(any(target_arch = "x86_64", target_arch = "x86"))] +fn main() { + unsafe { + foo(); + } +} + +#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))] +fn main() {} diff --git a/tests/ui/single-use-lifetime/derive-eq.rs b/tests/ui/single-use-lifetime/derive-eq.rs new file mode 100644 index 000000000..e5bdfc55d --- /dev/null +++ b/tests/ui/single-use-lifetime/derive-eq.rs @@ -0,0 +1,11 @@ +// check-pass + +#![deny(single_use_lifetimes)] + +#[derive(PartialEq, Eq)] +struct Foo<'a, T> { + /// a reference to the underlying secret data that will be derefed + pub data: &'a mut T, +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/fn-types.rs b/tests/ui/single-use-lifetime/fn-types.rs new file mode 100644 index 000000000..018535f64 --- /dev/null +++ b/tests/ui/single-use-lifetime/fn-types.rs @@ -0,0 +1,16 @@ +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// Test that we DO warn when lifetime name is used only +// once in a fn argument. + +struct Foo { + a: for<'a> fn(&'a u32), //~ ERROR `'a` only used once + b: for<'a> fn(&'a u32, &'a u32), // OK, used twice. + c: for<'a> fn(&'a u32) -> &'a u32, // OK, used twice. + d: for<'a> fn() -> &'a u32, // OK, used only in return type. + //~^ ERROR return type references lifetime `'a`, which is not constrained by the fn input types +} + +fn main() { } diff --git a/tests/ui/single-use-lifetime/fn-types.stderr b/tests/ui/single-use-lifetime/fn-types.stderr new file mode 100644 index 000000000..55959def4 --- /dev/null +++ b/tests/ui/single-use-lifetime/fn-types.stderr @@ -0,0 +1,28 @@ +error: lifetime parameter `'a` only used once + --> $DIR/fn-types.rs:9:10 + | +LL | a: for<'a> fn(&'a u32), + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/fn-types.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - a: for<'a> fn(&'a u32), +LL + a: fn(&u32), + | + +error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types + --> $DIR/fn-types.rs:12:22 + | +LL | d: for<'a> fn() -> &'a u32, // OK, used only in return type. + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0581`. diff --git a/tests/ui/single-use-lifetime/issue-104440.rs b/tests/ui/single-use-lifetime/issue-104440.rs new file mode 100644 index 000000000..0795e9530 --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-104440.rs @@ -0,0 +1,100 @@ +#![feature(decl_macro, rustc_attrs)] +#![deny(single_use_lifetimes)] + +mod type_params { + macro m($T:ident) { + fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) { + (t1.clone(), t2 == t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($T:ident) { + fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn h(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($T:ident) { + fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + fn k(t1: $T, t2: T) -> (T, $T) { + (t1.clone(), t2.clone()) + } + } + + m!(T); + n!(T); + p!(T); +} + +mod lifetime_params { + macro m($a:lifetime) { + fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { //~ ERROR lifetime parameter `'a` only used once + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($a:lifetime) { + fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($a:lifetime) { + fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) { + (t1, t2) + } + } + + m!('a); //~ ERROR lifetime parameter `'a` only used once + n!('a); + p!('a); +} + +mod const_params { + macro m($C:ident) { + fn f(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "semitransparent"] + macro n($C:ident) { + fn g(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn h(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + #[rustc_macro_transparency = "transparent"] + macro p($C:ident) { + fn j(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + fn k(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) { + (t1, t2) + } + } + + m!(C); + n!(C); + p!(C); +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/issue-104440.stderr b/tests/ui/single-use-lifetime/issue-104440.stderr new file mode 100644 index 000000000..54ded31dc --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-104440.stderr @@ -0,0 +1,28 @@ +error: lifetime parameter `'a` only used once + --> $DIR/issue-104440.rs:63:8 + | +LL | m!('a); + | ^^ + | | + | this lifetime... + | ...is used only here + | +note: the lint level is defined here + --> $DIR/issue-104440.rs:2:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: lifetime parameter `'a` only used once + --> $DIR/issue-104440.rs:38:30 + | +LL | fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) { + | ^^ this lifetime... -- ...is used only here +... +LL | m!('a); + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/single-use-lifetime/one-use-in-fn-argument.rs b/tests/ui/single-use-lifetime/one-use-in-fn-argument.rs new file mode 100644 index 000000000..7919ef820 --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-fn-argument.rs @@ -0,0 +1,33 @@ +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// Test that we DO warn when lifetime name is used only +// once in a fn argument. + +fn a<'a>(x: &'a u32) { //~ ERROR `'a` only used once + //~^ HELP elide the single-use lifetime +} + +struct Single<'a> { x: &'a u32 } +struct Double<'a, 'b> { f: &'a &'b u32 } + +fn center<'m>(_: Single<'m>) {} //~ ERROR `'m` only used once +//~^ HELP elide the single-use lifetime +fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f } //~ ERROR `'y` only used once +//~^ HELP elide the single-use lifetime +fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f } //~ ERROR `'x` only used once +//~^ HELP elide the single-use lifetime + +pub trait Tfv<'a> {} + +// Do NOT lint in an HRTB. +pub fn g Tfv<'a>>() {} + +// Do NOT lint for trait bounds. +pub fn h<'a, S>(_: S) +where + S: Tfv<'a>, +{} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr new file mode 100644 index 000000000..93f16f5ba --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-fn-argument.stderr @@ -0,0 +1,59 @@ +error: lifetime parameter `'a` only used once + --> $DIR/one-use-in-fn-argument.rs:8:6 + | +LL | fn a<'a>(x: &'a u32) { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/one-use-in-fn-argument.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - fn a<'a>(x: &'a u32) { +LL + fn a(x: &u32) { + | + +error: lifetime parameter `'m` only used once + --> $DIR/one-use-in-fn-argument.rs:15:11 + | +LL | fn center<'m>(_: Single<'m>) {} + | ^^ -- ...is used only here + | | + | this lifetime... + | +help: elide the single-use lifetime + | +LL - fn center<'m>(_: Single<'m>) {} +LL + fn center(_: Single<'_>) {} + | + +error: lifetime parameter `'y` only used once + --> $DIR/one-use-in-fn-argument.rs:17:13 + | +LL | fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f } + | ^^ this lifetime... -- ...is used only here + | +help: elide the single-use lifetime + | +LL - fn left<'x, 'y>(foo: Double<'x, 'y>) -> &'x u32 { foo.f } +LL + fn left<'x>(foo: Double<'x, '_>) -> &'x u32 { foo.f } + | + +error: lifetime parameter `'x` only used once + --> $DIR/one-use-in-fn-argument.rs:19:10 + | +LL | fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f } + | ^^ this lifetime... -- ...is used only here + | +help: elide the single-use lifetime + | +LL - fn right<'x, 'y>(foo: Double<'x, 'y>) -> &'y u32 { foo.f } +LL + fn right<'y>(foo: Double<'_, 'y>) -> &'y u32 { foo.f } + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/single-use-lifetime/one-use-in-fn-return.rs b/tests/ui/single-use-lifetime/one-use-in-fn-return.rs new file mode 100644 index 000000000..1ade01eed --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-fn-return.rs @@ -0,0 +1,23 @@ +// Test that we DO NOT warn when lifetime name is used only +// once in a fn return type -- using `'_` is not legal there, +// as it must refer back to an argument. +// +// (Normally, using `'static` would be preferred, but there are +// times when that is not what you want.) + +// check-pass + +#![deny(single_use_lifetimes)] + +// OK: used only in return type +fn b<'a>() -> &'a u32 { + &22 +} + +pub trait Tfv<'a> {} +impl Tfv<'_> for () {} + +// Do NOT lint if used in return type. +pub fn i<'a>() -> impl Tfv<'a> {} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs new file mode 100644 index 000000000..64f1c9118 --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.rs @@ -0,0 +1,22 @@ +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// Test that we DO warn for a lifetime used only once in an impl, and that we +// don't warn for the anonymous lifetime. + +struct Foo<'f> { + data: &'f u32 +} + +impl<'f> Foo<'f> { //~ ERROR `'f` only used once + fn inherent_a(&self) { + } +} + +impl Foo<'_> { + fn inherent_b(&self) {} +} + + +fn main() { } diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr new file mode 100644 index 000000000..94129560f --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-impl-header.stderr @@ -0,0 +1,21 @@ +error: lifetime parameter `'f` only used once + --> $DIR/one-use-in-inherent-impl-header.rs:12:6 + | +LL | impl<'f> Foo<'f> { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/one-use-in-inherent-impl-header.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - impl<'f> Foo<'f> { +LL + impl Foo<'_> { + | + +error: aborting due to previous error + diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs new file mode 100644 index 000000000..eecd715ef --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.rs @@ -0,0 +1,18 @@ +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// Test that we DO warn for a lifetime used only once in an inherent method. + +struct Foo<'f> { + data: &'f u32 +} + +impl<'f> Foo<'f> { //~ ERROR `'f` only used once + //~^ HELP elide the single-use lifetime + fn inherent_a<'a>(&self, data: &'a u32) { //~ ERROR `'a` only used once + //~^ HELP elide the single-use lifetime + } +} + +fn main() { } diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr new file mode 100644 index 000000000..39507785b --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-argument.stderr @@ -0,0 +1,35 @@ +error: lifetime parameter `'f` only used once + --> $DIR/one-use-in-inherent-method-argument.rs:11:6 + | +LL | impl<'f> Foo<'f> { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/one-use-in-inherent-method-argument.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - impl<'f> Foo<'f> { +LL + impl Foo<'_> { + | + +error: lifetime parameter `'a` only used once + --> $DIR/one-use-in-inherent-method-argument.rs:13:19 + | +LL | fn inherent_a<'a>(&self, data: &'a u32) { + | ^^ -- ...is used only here + | | + | this lifetime... + | +help: elide the single-use lifetime + | +LL - fn inherent_a<'a>(&self, data: &'a u32) { +LL + fn inherent_a(&self, data: &u32) { + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs new file mode 100644 index 000000000..c5938f4a1 --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.rs @@ -0,0 +1,18 @@ +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// Test that we DO NOT warn for a lifetime used just once in a return type, +// where that return type is in an inherent method. + +struct Foo<'f> { + data: &'f u32 +} + +impl<'f> Foo<'f> { //~ ERROR `'f` only used once + fn inherent_a<'a>(&self) -> &'a u32 { // OK for 'a + &22 + } +} + +fn main() { } diff --git a/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr new file mode 100644 index 000000000..69578fe2f --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-inherent-method-return.stderr @@ -0,0 +1,21 @@ +error: lifetime parameter `'f` only used once + --> $DIR/one-use-in-inherent-method-return.rs:12:6 + | +LL | impl<'f> Foo<'f> { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/one-use-in-inherent-method-return.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - impl<'f> Foo<'f> { +LL + impl Foo<'_> { + | + +error: aborting due to previous error + diff --git a/tests/ui/single-use-lifetime/one-use-in-struct.rs b/tests/ui/single-use-lifetime/one-use-in-struct.rs new file mode 100644 index 000000000..9cad942e7 --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-struct.rs @@ -0,0 +1,28 @@ +// Test that we do not warn for named lifetimes in structs, +// even when they are only used once (since to not use a named +// lifetime is illegal!) +// +// check-pass + +// Use forbid to verify that `automatically_derived` is handled correctly. +#![forbid(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'f> { + data: &'f u32, +} + +enum Bar<'f> { + Data(&'f u32), +} + +trait Baz<'f> {} + +// `Derive`d impls shouldn't trigger a warning, either (Issue #53738). +#[derive(Debug)] +struct Quux<'a> { + priors: &'a u32, +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs new file mode 100644 index 000000000..1848fc91c --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.rs @@ -0,0 +1,26 @@ +// Test that we DO warn for a lifetime on an impl used only in `&self` +// in a trait method. + +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'f> { + data: &'f u32 +} + +impl<'f> Iterator for Foo<'f> { + type Item = &'f u32; + + fn next<'g>(&'g mut self) -> Option { //~ ERROR `'g` only used once + //~^ HELP elide the single-use lifetime + None + } +} + +trait Bar<'a> { + // But we should not warn here. + fn bar(x: Foo<'a>); +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr new file mode 100644 index 000000000..1a6e8310d --- /dev/null +++ b/tests/ui/single-use-lifetime/one-use-in-trait-method-argument.stderr @@ -0,0 +1,21 @@ +error: lifetime parameter `'g` only used once + --> $DIR/one-use-in-trait-method-argument.rs:15:13 + | +LL | fn next<'g>(&'g mut self) -> Option { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/one-use-in-trait-method-argument.rs:4:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - fn next<'g>(&'g mut self) -> Option { +LL + fn next(&mut self) -> Option { + | + +error: aborting due to previous error + diff --git a/tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs b/tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs new file mode 100644 index 000000000..f80f3f63c --- /dev/null +++ b/tests/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs @@ -0,0 +1,15 @@ +// Test that we DO NOT warn when lifetime name is used in +// both the argument and return. +// +// check-pass + +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// OK: used twice +fn c<'a>(x: &'a u32) -> &'a u32 { + &22 +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs b/tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs new file mode 100644 index 000000000..51724ebf8 --- /dev/null +++ b/tests/ui/single-use-lifetime/two-uses-in-fn-arguments.rs @@ -0,0 +1,16 @@ +// Test that we DO NOT warn when lifetime name is used multiple +// arguments, or more than once in a single argument. +// +// check-pass + +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +// OK: used twice +fn c<'a>(x: &'a u32, y: &'a u32) {} + +// OK: used twice +fn d<'a>(x: (&'a u32, &'a u32)) {} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs b/tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs new file mode 100644 index 000000000..125a395db --- /dev/null +++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs @@ -0,0 +1,17 @@ +// Test that we DO NOT warn for a lifetime used twice in an impl. +// +// check-pass + +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'f> { + data: &'f u32, +} + +impl<'f> Foo<'f> { + fn inherent_a(&self, data: &'f u32) {} +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs new file mode 100644 index 000000000..06ab6cdbf --- /dev/null +++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.rs @@ -0,0 +1,18 @@ +// Test that we DO NOT warn for a lifetime used twice in an impl method and +// header. + +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'f> { + data: &'f u32 +} + +impl<'f> Foo<'f> { //~ ERROR `'f` only used once + fn inherent_a<'a>(&self, data: &'a u32) -> &'a u32{ + data + } +} + +fn main() { } diff --git a/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr new file mode 100644 index 000000000..4794566ea --- /dev/null +++ b/tests/ui/single-use-lifetime/two-uses-in-inherent-method-argument-and-return.stderr @@ -0,0 +1,21 @@ +error: lifetime parameter `'f` only used once + --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:12:6 + | +LL | impl<'f> Foo<'f> { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/two-uses-in-inherent-method-argument-and-return.rs:4:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - impl<'f> Foo<'f> { +LL + impl Foo<'_> { + | + +error: aborting due to previous error + diff --git a/tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs b/tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs new file mode 100644 index 000000000..16431a39f --- /dev/null +++ b/tests/ui/single-use-lifetime/two-uses-in-trait-impl.rs @@ -0,0 +1,22 @@ +// Test that we DO NOT warn for a lifetime on an impl used in both +// header and in an associated type. +// +// check-pass + +#![deny(single_use_lifetimes)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Foo<'f> { + data: &'f u32, +} + +impl<'f> Iterator for Foo<'f> { + type Item = &'f u32; + + fn next(&mut self) -> Option { + None + } +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/zero-uses-in-fn.fixed b/tests/ui/single-use-lifetime/zero-uses-in-fn.fixed new file mode 100644 index 000000000..0f26a975a --- /dev/null +++ b/tests/ui/single-use-lifetime/zero-uses-in-fn.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +// Test that we DO warn when lifetime name is not used at all. + +#![deny(unused_lifetimes)] +#![allow(dead_code, unused_variables)] + +fn september() {} +//~^ ERROR lifetime parameter `'a` never used +//~| HELP elide the unused lifetime + +fn october<'b, T>(s: &'b T) -> &'b T { + //~^ ERROR lifetime parameter `'a` never used + //~| HELP elide the unused lifetime + s +} + +fn november<'a>(s: &'a str) -> &'a str { + //~^ ERROR lifetime parameter `'b` never used + //~| HELP elide the unused lifetime + s +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/zero-uses-in-fn.rs b/tests/ui/single-use-lifetime/zero-uses-in-fn.rs new file mode 100644 index 000000000..7f9504fe5 --- /dev/null +++ b/tests/ui/single-use-lifetime/zero-uses-in-fn.rs @@ -0,0 +1,24 @@ +// run-rustfix + +// Test that we DO warn when lifetime name is not used at all. + +#![deny(unused_lifetimes)] +#![allow(dead_code, unused_variables)] + +fn september<'a>() {} +//~^ ERROR lifetime parameter `'a` never used +//~| HELP elide the unused lifetime + +fn october<'a, 'b, T>(s: &'b T) -> &'b T { + //~^ ERROR lifetime parameter `'a` never used + //~| HELP elide the unused lifetime + s +} + +fn november<'a, 'b>(s: &'a str) -> &'a str { + //~^ ERROR lifetime parameter `'b` never used + //~| HELP elide the unused lifetime + s +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/zero-uses-in-fn.stderr b/tests/ui/single-use-lifetime/zero-uses-in-fn.stderr new file mode 100644 index 000000000..59c0164e3 --- /dev/null +++ b/tests/ui/single-use-lifetime/zero-uses-in-fn.stderr @@ -0,0 +1,30 @@ +error: lifetime parameter `'a` never used + --> $DIR/zero-uses-in-fn.rs:8:14 + | +LL | fn september<'a>() {} + | -^^- help: elide the unused lifetime + | +note: the lint level is defined here + --> $DIR/zero-uses-in-fn.rs:5:9 + | +LL | #![deny(unused_lifetimes)] + | ^^^^^^^^^^^^^^^^ + +error: lifetime parameter `'a` never used + --> $DIR/zero-uses-in-fn.rs:12:12 + | +LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T { + | ^^-- + | | + | help: elide the unused lifetime + +error: lifetime parameter `'b` never used + --> $DIR/zero-uses-in-fn.rs:18:17 + | +LL | fn november<'a, 'b>(s: &'a str) -> &'a str { + | --^^ + | | + | help: elide the unused lifetime + +error: aborting due to 3 previous errors + diff --git a/tests/ui/single-use-lifetime/zero-uses-in-impl.rs b/tests/ui/single-use-lifetime/zero-uses-in-impl.rs new file mode 100644 index 000000000..54803e1d2 --- /dev/null +++ b/tests/ui/single-use-lifetime/zero-uses-in-impl.rs @@ -0,0 +1,10 @@ +// Test that we DO warn when lifetime name is not used at all. + +#![deny(unused_lifetimes)] +#![allow(dead_code, unused_variables)] + +struct Foo {} + +impl<'a> Foo {} //~ ERROR `'a` never used + +fn main() {} diff --git a/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr b/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr new file mode 100644 index 000000000..b6e42d3e7 --- /dev/null +++ b/tests/ui/single-use-lifetime/zero-uses-in-impl.stderr @@ -0,0 +1,14 @@ +error: lifetime parameter `'a` never used + --> $DIR/zero-uses-in-impl.rs:8:6 + | +LL | impl<'a> Foo {} + | -^^- help: elide the unused lifetime + | +note: the lint level is defined here + --> $DIR/zero-uses-in-impl.rs:3:9 + | +LL | #![deny(unused_lifetimes)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/sized-borrowed-pointer.rs b/tests/ui/sized-borrowed-pointer.rs new file mode 100644 index 000000000..319b80269 --- /dev/null +++ b/tests/ui/sized-borrowed-pointer.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(dead_code)] +// Possibly-dynamic size of typaram should be cleared at pointer boundary. + +// pretty-expanded FIXME #23616 + +fn bar() { } +fn foo() { bar::<&T>() } +pub fn main() { } diff --git a/tests/ui/sized-cycle-note.rs b/tests/ui/sized-cycle-note.rs new file mode 100644 index 000000000..766a5fa0d --- /dev/null +++ b/tests/ui/sized-cycle-note.rs @@ -0,0 +1,7 @@ +struct Baz { q: Option } +//~^ ERROR recursive types `Baz` and `Foo` have infinite size +struct Foo { q: Option } + +impl Foo { fn bar(&self) {} } + +fn main() {} diff --git a/tests/ui/sized-cycle-note.stderr b/tests/ui/sized-cycle-note.stderr new file mode 100644 index 000000000..06c87b61f --- /dev/null +++ b/tests/ui/sized-cycle-note.stderr @@ -0,0 +1,19 @@ +error[E0072]: recursive types `Baz` and `Foo` have infinite size + --> $DIR/sized-cycle-note.rs:1:1 + | +LL | struct Baz { q: Option } + | ^^^^^^^^^^ --- recursive without indirection +LL | +LL | struct Foo { q: Option } + | ^^^^^^^^^^ --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ struct Baz { q: Option> } +LL | +LL ~ struct Foo { q: Option> } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/sized-owned-pointer.rs b/tests/ui/sized-owned-pointer.rs new file mode 100644 index 000000000..2abf0a1e0 --- /dev/null +++ b/tests/ui/sized-owned-pointer.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(dead_code)] +// Possibly-dynamic size of typaram should be cleared at pointer boundary. + + +// pretty-expanded FIXME #23616 + +fn bar() { } +fn foo() { bar::>() } +pub fn main() { } diff --git a/tests/ui/sized/coinductive-1-gat.rs b/tests/ui/sized/coinductive-1-gat.rs new file mode 100644 index 000000000..cdf70920f --- /dev/null +++ b/tests/ui/sized/coinductive-1-gat.rs @@ -0,0 +1,14 @@ +// check-pass +struct Node(C::Assoc::); + +trait Trait { + type Assoc; +} + +impl Trait for Vec<()> { + type Assoc = Vec; +} + +fn main() { + let _ = Node::>(Vec::new()); +} diff --git a/tests/ui/sized/coinductive-1.rs b/tests/ui/sized/coinductive-1.rs new file mode 100644 index 000000000..7bcd0f1fd --- /dev/null +++ b/tests/ui/sized/coinductive-1.rs @@ -0,0 +1,14 @@ +// check-pass +struct Node>(C::Assoc); + +trait Trait { + type Assoc; +} + +impl Trait for Vec<()> { + type Assoc = Vec; +} + +fn main() { + let _ = Node::>(Vec::new()); +} diff --git a/tests/ui/sized/coinductive-2.rs b/tests/ui/sized/coinductive-2.rs new file mode 100644 index 000000000..212274d2e --- /dev/null +++ b/tests/ui/sized/coinductive-2.rs @@ -0,0 +1,28 @@ +// run-pass +struct Node> { + _children: C::Collection, +} + +trait CollectionFactory { + type Collection; +} + +impl CollectionFactory for Vec<()> { + type Collection = Vec; +} + +trait Collection: Sized { + fn push(&mut self, v: T); +} + +impl Collection for Vec { + fn push(&mut self, v: T) { + self.push(v) + } +} + +fn main() { + let _ = Node::> { + _children: Vec::new(), + }; +} diff --git a/tests/ui/sized/recursive-type-1.rs b/tests/ui/sized/recursive-type-1.rs new file mode 100644 index 000000000..cd6805967 --- /dev/null +++ b/tests/ui/sized/recursive-type-1.rs @@ -0,0 +1,10 @@ +// check-pass +trait A { type Assoc; } + +impl A for () { + // FIXME: it would be nice for this to at least cause a warning. + type Assoc = Foo<()>; +} +struct Foo(T::Assoc); + +fn main() {} diff --git a/tests/ui/sized/recursive-type-2.rs b/tests/ui/sized/recursive-type-2.rs new file mode 100644 index 000000000..7d95417a6 --- /dev/null +++ b/tests/ui/sized/recursive-type-2.rs @@ -0,0 +1,13 @@ +// build-fail +//~^ ERROR cycle detected when computing layout of `Foo<()>` + +trait A { type Assoc: ?Sized; } + +impl A for () { + type Assoc = Foo<()>; +} +struct Foo(T::Assoc); + +fn main() { + let x: Foo<()>; +} diff --git a/tests/ui/sized/recursive-type-2.stderr b/tests/ui/sized/recursive-type-2.stderr new file mode 100644 index 000000000..d0e6e9db0 --- /dev/null +++ b/tests/ui/sized/recursive-type-2.stderr @@ -0,0 +1,13 @@ +error[E0391]: cycle detected when computing layout of `Foo<()>` + | + = note: ...which requires computing layout of `<() as A>::Assoc`... + = note: ...which again requires computing layout of `Foo<()>`, completing the cycle +note: cycle used when elaborating drops for `main` + --> $DIR/recursive-type-2.rs:11:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/slightly-nice-generic-literal-messages.rs b/tests/ui/slightly-nice-generic-literal-messages.rs new file mode 100644 index 000000000..a48598ce8 --- /dev/null +++ b/tests/ui/slightly-nice-generic-literal-messages.rs @@ -0,0 +1,14 @@ +use std::marker; + +struct Foo(T, marker::PhantomData); + +fn main() { + match Foo(1.1, marker::PhantomData) { + 1 => {} + //~^ ERROR mismatched types + //~| expected struct `Foo<{float}, _>` + //~| found type `{integer}` + //~| expected struct `Foo`, found integer + } + +} diff --git a/tests/ui/slightly-nice-generic-literal-messages.stderr b/tests/ui/slightly-nice-generic-literal-messages.stderr new file mode 100644 index 000000000..14f01f0eb --- /dev/null +++ b/tests/ui/slightly-nice-generic-literal-messages.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/slightly-nice-generic-literal-messages.rs:7:9 + | +LL | match Foo(1.1, marker::PhantomData) { + | ----------------------------- this expression has type `Foo<{float}, _>` +LL | 1 => {} + | ^ expected struct `Foo`, found integer + | + = note: expected struct `Foo<{float}, _>` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/E0046.rs b/tests/ui/span/E0046.rs new file mode 100644 index 000000000..961109892 --- /dev/null +++ b/tests/ui/span/E0046.rs @@ -0,0 +1,11 @@ +trait Foo { + fn foo(); +} + +struct Bar; + +impl Foo for Bar {} +//~^ ERROR E0046 + +fn main() { +} diff --git a/tests/ui/span/E0046.stderr b/tests/ui/span/E0046.stderr new file mode 100644 index 000000000..1323524f2 --- /dev/null +++ b/tests/ui/span/E0046.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `foo` + --> $DIR/E0046.rs:7:1 + | +LL | fn foo(); + | --------- `foo` from trait +... +LL | impl Foo for Bar {} + | ^^^^^^^^^^^^^^^^ missing `foo` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/E0072.rs b/tests/ui/span/E0072.rs new file mode 100644 index 000000000..bc284cdcb --- /dev/null +++ b/tests/ui/span/E0072.rs @@ -0,0 +1,7 @@ +struct ListNode { //~ ERROR has infinite size + head: u8, + tail: Option, +} + +fn main() { +} diff --git a/tests/ui/span/E0072.stderr b/tests/ui/span/E0072.stderr new file mode 100644 index 000000000..20f2e0df0 --- /dev/null +++ b/tests/ui/span/E0072.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `ListNode` has infinite size + --> $DIR/E0072.rs:1:1 + | +LL | struct ListNode { + | ^^^^^^^^^^^^^^^ +LL | head: u8, +LL | tail: Option, + | -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | tail: Option>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs new file mode 100644 index 000000000..174de8cdd --- /dev/null +++ b/tests/ui/span/E0204.rs @@ -0,0 +1,26 @@ +struct Foo { + foo: Vec, +} + +impl Copy for Foo { } //~ ERROR may not be implemented for this type + +#[derive(Copy)] //~ ERROR may not be implemented for this type +struct Foo2<'a> { + ty: &'a mut bool, +} + +enum EFoo { + Bar { x: Vec }, + Baz, +} + +impl Copy for EFoo { } //~ ERROR may not be implemented for this type + +#[derive(Copy)] //~ ERROR may not be implemented for this type +enum EFoo2<'a> { + Bar(&'a mut bool), + Baz, +} + +fn main() { +} diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr new file mode 100644 index 000000000..0b2166eed --- /dev/null +++ b/tests/ui/span/E0204.stderr @@ -0,0 +1,43 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:5:15 + | +LL | foo: Vec, + | ------------- this field does not implement `Copy` +... +LL | impl Copy for Foo { } + | ^^^ + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:7:10 + | +LL | #[derive(Copy)] + | ^^^^ +LL | struct Foo2<'a> { +LL | ty: &'a mut bool, + | ---------------- this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:17:15 + | +LL | Bar { x: Vec }, + | ----------- this field does not implement `Copy` +... +LL | impl Copy for EFoo { } + | ^^^^ + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/E0204.rs:19:10 + | +LL | #[derive(Copy)] + | ^^^^ +LL | enum EFoo2<'a> { +LL | Bar(&'a mut bool), + | ------------ this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/span/E0493.rs b/tests/ui/span/E0493.rs new file mode 100644 index 000000000..625da25a7 --- /dev/null +++ b/tests/ui/span/E0493.rs @@ -0,0 +1,21 @@ +struct Foo { + a: u32 +} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +struct Bar { + a: u32 +} + +impl Drop for Bar { + fn drop(&mut self) {} +} + +const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; +//~^ ERROR destructor of + +fn main() { +} diff --git a/tests/ui/span/E0493.stderr b/tests/ui/span/E0493.stderr new file mode 100644 index 000000000..9db627562 --- /dev/null +++ b/tests/ui/span/E0493.stderr @@ -0,0 +1,11 @@ +error[E0493]: destructor of `(Foo, Foo)` cannot be evaluated at compile-time + --> $DIR/E0493.rs:17:17 + | +LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/span/E0535.rs b/tests/ui/span/E0535.rs new file mode 100644 index 000000000..e26334e9b --- /dev/null +++ b/tests/ui/span/E0535.rs @@ -0,0 +1,6 @@ +#[inline(unknown)] //~ ERROR E0535 +pub fn something() {} + +fn main() { + something(); +} diff --git a/tests/ui/span/E0535.stderr b/tests/ui/span/E0535.stderr new file mode 100644 index 000000000..b1411bc43 --- /dev/null +++ b/tests/ui/span/E0535.stderr @@ -0,0 +1,11 @@ +error[E0535]: invalid argument + --> $DIR/E0535.rs:1:10 + | +LL | #[inline(unknown)] + | ^^^^^^^ + | + = help: valid inline arguments are `always` and `never` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0535`. diff --git a/tests/ui/span/E0536.rs b/tests/ui/span/E0536.rs new file mode 100644 index 000000000..72de7b6f4 --- /dev/null +++ b/tests/ui/span/E0536.rs @@ -0,0 +1,4 @@ +#[cfg(not())] //~ ERROR E0536 +pub fn something() {} + +pub fn main() {} diff --git a/tests/ui/span/E0536.stderr b/tests/ui/span/E0536.stderr new file mode 100644 index 000000000..820b0d744 --- /dev/null +++ b/tests/ui/span/E0536.stderr @@ -0,0 +1,9 @@ +error[E0536]: expected 1 cfg-pattern + --> $DIR/E0536.rs:1:7 + | +LL | #[cfg(not())] + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0536`. diff --git a/tests/ui/span/E0537.rs b/tests/ui/span/E0537.rs new file mode 100644 index 000000000..4088a9ae5 --- /dev/null +++ b/tests/ui/span/E0537.rs @@ -0,0 +1,4 @@ +#[cfg(unknown())] //~ ERROR E0537 +pub fn something() {} + +pub fn main() {} diff --git a/tests/ui/span/E0537.stderr b/tests/ui/span/E0537.stderr new file mode 100644 index 000000000..5478c3fbc --- /dev/null +++ b/tests/ui/span/E0537.stderr @@ -0,0 +1,9 @@ +error[E0537]: invalid predicate `unknown` + --> $DIR/E0537.rs:1:7 + | +LL | #[cfg(unknown())] + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0537`. diff --git a/tests/ui/span/auxiliary/transitive_dep_three.rs b/tests/ui/span/auxiliary/transitive_dep_three.rs new file mode 100644 index 000000000..99b51625a --- /dev/null +++ b/tests/ui/span/auxiliary/transitive_dep_three.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! define_parse_error { + () => { + #[macro_export] + macro_rules! parse_error { + () => { parse error } + } + } +} diff --git a/tests/ui/span/auxiliary/transitive_dep_two.rs b/tests/ui/span/auxiliary/transitive_dep_two.rs new file mode 100644 index 000000000..5110c4276 --- /dev/null +++ b/tests/ui/span/auxiliary/transitive_dep_two.rs @@ -0,0 +1,3 @@ +extern crate transitive_dep_three; + +transitive_dep_three::define_parse_error!(); diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs new file mode 100644 index 000000000..76a1d12ea --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.rs @@ -0,0 +1,142 @@ +// Test how overloaded deref interacts with borrows when DerefMut +// is implemented. + +use std::ops::{Deref, DerefMut}; + +struct Own { + value: *mut T +} + +impl Deref for Own { + type Target = T; + + fn deref(&self) -> &T { + unsafe { &*self.value } + } +} + +impl DerefMut for Own { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.value } + } +} + +struct Point { + x: isize, + y: isize +} + +impl Point { + fn get(&self) -> (isize, isize) { + (self.x, self.y) + } + + fn set(&mut self, x: isize, y: isize) { + self.x = x; + self.y = y; + } + + fn x_ref(&self) -> &isize { + &self.x + } + + fn y_mut(&mut self) -> &mut isize { + &mut self.y + } +} + +fn deref_imm_field(x: Own) { + let __isize = &x.y; +} + +fn deref_mut_field1(x: Own) { + let __isize = &mut x.y; //~ ERROR cannot borrow +} + +fn deref_mut_field2(mut x: Own) { + let __isize = &mut x.y; +} + +fn deref_extend_field(x: &Own) -> &isize { + &x.y +} + +fn deref_extend_mut_field1(x: &Own) -> &mut isize { + &mut x.y //~ ERROR cannot borrow +} + +fn deref_extend_mut_field2(x: &mut Own) -> &mut isize { + &mut x.y +} + +fn deref_extend_mut_field3(x: &mut Own) { + // Hmm, this is unfortunate, because with box it would work, + // but it's presently the expected outcome. See `deref_extend_mut_field4` + // for the workaround. + + let _x = &mut x.x; + let _y = &mut x.y; //~ ERROR cannot borrow + use_mut(_x); +} +fn deref_extend_mut_field4<'a>(x: &'a mut Own) { + let p = &mut **x; + let _x = &mut p.x; + let _y = &mut p.y; +} + +fn assign_field1<'a>(x: Own) { + x.y = 3; //~ ERROR cannot borrow +} + +fn assign_field2<'a>(x: &'a Own) { + x.y = 3; //~ ERROR cannot borrow +} + +fn assign_field3<'a>(x: &'a mut Own) { + x.y = 3; +} + +fn assign_field4<'a>(x: &'a mut Own) { + let _p: &mut Point = &mut **x; + x.y = 3; //~ ERROR cannot borrow + use_mut(_p); +} +fn deref_imm_method(x: Own) { + let __isize = x.get(); +} + +fn deref_mut_method1(x: Own) { + x.set(0, 0); //~ ERROR cannot borrow +} + +fn deref_mut_method2(mut x: Own) { + x.set(0, 0); +} + +fn deref_extend_method(x: &Own) -> &isize { + x.x_ref() +} + +fn deref_extend_mut_method1(x: &Own) -> &mut isize { + x.y_mut() //~ ERROR cannot borrow +} + +fn deref_extend_mut_method2(x: &mut Own) -> &mut isize { + x.y_mut() +} + +fn assign_method1<'a>(x: Own) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +fn assign_method2<'a>(x: &'a Own) { + *x.y_mut() = 3; //~ ERROR cannot borrow +} + +fn assign_method3<'a>(x: &'a mut Own) { + *x.y_mut() = 3; +} + +pub fn main() {} + +fn use_mut(_: &mut T) {} diff --git a/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr new file mode 100644 index 000000000..570328fc2 --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -0,0 +1,112 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24 + | +LL | let __isize = &mut x.y; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_field1(mut x: Own) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10 + | +LL | &mut x.y + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_field1(x: &mut Own) -> &mut isize { + | ~~~~~~~~~~~~~~~ + +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:78:19 + | +LL | let _x = &mut x.x; + | - first mutable borrow occurs here +LL | let _y = &mut x.y; + | ^ second mutable borrow occurs here +LL | use_mut(_x); + | -- first borrow later used here + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5 + | +LL | x.y = 3; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_field1<'a>(mut x: Own) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5 + | +LL | x.y = 3; + | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_field2<'a>(x: &'a mut Own) { + | ~~~~~~~~~~~~~~~~~~ + +error[E0499]: cannot borrow `*x` as mutable more than once at a time + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:101:5 + | +LL | let _p: &mut Point = &mut **x; + | -- first mutable borrow occurs here +LL | x.y = 3; + | ^ second mutable borrow occurs here +LL | use_mut(_p); + | -- first borrow later used here + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5 + | +LL | x.set(0, 0); + | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_method1(mut x: Own) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5 + | +LL | x.y_mut() + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_method1(x: &mut Own) -> &mut isize { + | ~~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_method1<'a>(mut x: Own) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6 + | +LL | *x.y_mut() = 3; + | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_method2<'a>(x: &'a mut Own) { + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0499, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs new file mode 100644 index 000000000..8d43d5da4 --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.rs @@ -0,0 +1,60 @@ +// Test how overloaded deref interacts with borrows when DerefMut +// is implemented. + +use std::ops::{Deref, DerefMut}; + +struct Own { + value: *mut T +} + +impl Deref for Own { + type Target = T; + + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.value } + } +} + +impl DerefMut for Own { + fn deref_mut<'a>(&'a mut self) -> &'a mut T { + unsafe { &mut *self.value } + } +} + +fn deref_imm(x: Own) { + let __isize = &*x; +} + +fn deref_mut1(x: Own) { + let __isize = &mut *x; //~ ERROR cannot borrow +} + +fn deref_mut2(mut x: Own) { + let __isize = &mut *x; +} + +fn deref_extend<'a>(x: &'a Own) -> &'a isize { + &**x +} + +fn deref_extend_mut1<'a>(x: &'a Own) -> &'a mut isize { + &mut **x //~ ERROR cannot borrow +} + +fn deref_extend_mut2<'a>(x: &'a mut Own) -> &'a mut isize { + &mut **x +} + +fn assign1<'a>(x: Own) { + *x = 3; //~ ERROR cannot borrow +} + +fn assign2<'a>(x: &'a Own) { + **x = 3; //~ ERROR cannot borrow +} + +fn assign3<'a>(x: &'a mut Own) { + **x = 3; +} + +pub fn main() {} diff --git a/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr new file mode 100644 index 000000000..3fed7b3f4 --- /dev/null +++ b/tests/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -0,0 +1,47 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25 + | +LL | let __isize = &mut *x; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut1(mut x: Own) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11 + | +LL | &mut **x + | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut1<'a>(x: &'a mut Own) -> &'a mut isize { + | ~~~~~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6 + | +LL | *x = 3; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign1<'a>(mut x: Own) { + | +++ + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6 + | +LL | **x = 3; + | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign2<'a>(x: &'a mut Own) { + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs b/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs new file mode 100644 index 000000000..938fdaf11 --- /dev/null +++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -0,0 +1,62 @@ +#![feature(fn_traits)] + +// Ensure that invoking a closure counts as a unique immutable borrow + +type Fn<'a> = Box; + +struct Test<'a> { + f: Box +} + +fn call(mut f: F) where F: FnMut(Fn) { + f(Box::new(|| { + //~^ ERROR: cannot borrow `f` as mutable more than once + f((Box::new(|| {}))) + })); +} + +fn test1() { + call(|mut a| { + a.call_mut(()); + }); +} + +fn test2(f: &F) where F: FnMut() { + (*f)(); + //~^ ERROR cannot borrow `*f` as mutable, as it is behind a `&` reference +} + +fn test3(f: &mut F) where F: FnMut() { + (*f)(); +} + +fn test4(f: &Test) { + f.f.call_mut(()) + //~^ ERROR: cannot borrow `f.f` as mutable, as it is behind a `&` reference +} + +fn test5(f: &mut Test) { + f.f.call_mut(()) +} + +fn test6() { + let mut f = || {}; + (|| { + f(); + })(); +} + +fn test7() { + fn foo(_: F) where F: FnMut(Box, isize) {} + let s = String::new(); // Capture to make f !Copy + let mut f = move |g: Box, b: isize| { + let _ = s.len(); + }; + f(Box::new(|a| { + //~^ ERROR cannot move out of `f` because it is borrowed + foo(f); + //~^ ERROR cannot move out of `f`, a captured variable in an `FnMut` closure + }), 3); +} + +fn main() {} diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr new file mode 100644 index 000000000..48b42bc78 --- /dev/null +++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -0,0 +1,61 @@ +error[E0499]: cannot borrow `f` as mutable more than once at a time + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:12:16 + | +LL | f(Box::new(|| { + | - ^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call +LL | +LL | f((Box::new(|| {}))) + | - second borrow occurs due to use of `f` in closure + +error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:25:5 + | +LL | (*f)(); + | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test2(f: &mut F) where F: FnMut() { + | ~~~~~~ + +error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5 + | +LL | f.f.call_mut(()) + | ^^^^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test4(f: &mut Test<'_>) { + | ~~~~~~~~~~~~~ + +error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 + | +LL | let mut f = move |g: Box, b: isize| { + | ----- captured outer variable +... +LL | f(Box::new(|a| { + | --- captured by this `FnMut` closure +LL | +LL | foo(f); + | ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58]`, which does not implement the `Copy` trait + +error[E0505]: cannot move out of `f` because it is borrowed + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16 + | +LL | f(Box::new(|a| { + | - ^^^ move out of `f` occurs here + | | + | borrow of `f` occurs here +LL | +LL | foo(f); + | - move occurs due to use in closure + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0499, E0505, E0507, E0596. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs b/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs new file mode 100644 index 000000000..caf2d2a55 --- /dev/null +++ b/tests/ui/span/borrowck-call-method-from-mut-aliasable.rs @@ -0,0 +1,21 @@ +struct Foo { + x: isize, +} + +impl Foo { + pub fn f(&self) {} + pub fn h(&mut self) {} +} + +fn a(x: &mut Foo) { + x.f(); + x.h(); +} + +fn b(x: &Foo) { + x.f(); + x.h(); //~ ERROR cannot borrow +} + +fn main() { +} diff --git a/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr new file mode 100644 index 000000000..2a842f5a2 --- /dev/null +++ b/tests/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5 + | +LL | x.h(); + | ^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn b(x: &mut Foo) { + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-fn-in-const-b.rs b/tests/ui/span/borrowck-fn-in-const-b.rs new file mode 100644 index 000000000..822083efe --- /dev/null +++ b/tests/ui/span/borrowck-fn-in-const-b.rs @@ -0,0 +1,14 @@ +// Check that we check fns appearing in constant declarations. +// Issue #22382. + +// How about mutating an immutable vector? +const MUTATE: fn(&Vec) = { + fn broken(x: &Vec) { + x.push(format!("this is broken")); + //~^ ERROR cannot borrow + } + broken +}; + +fn main() { +} diff --git a/tests/ui/span/borrowck-fn-in-const-b.stderr b/tests/ui/span/borrowck-fn-in-const-b.stderr new file mode 100644 index 000000000..1df19deb1 --- /dev/null +++ b/tests/ui/span/borrowck-fn-in-const-b.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-fn-in-const-b.rs:7:9 + | +LL | x.push(format!("this is broken")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn broken(x: &mut Vec) { + | ~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.rs b/tests/ui/span/borrowck-let-suggestion-suffixes.rs new file mode 100644 index 000000000..18abfb5c3 --- /dev/null +++ b/tests/ui/span/borrowck-let-suggestion-suffixes.rs @@ -0,0 +1,59 @@ +fn id(x: T) -> T { x } + +fn f() { + let old = ['o']; // statement 0 + let mut v1 = Vec::new(); // statement 1 + + let mut v2 = Vec::new(); // statement 2 + + { + let young = ['y']; // statement 3 + + v2.push(&young[0]); // statement 4 + //~^ ERROR `young[_]` does not live long enough + //~| NOTE borrowed value does not live long enough + } //~ NOTE `young[_]` dropped here while still borrowed + + let mut v3 = Vec::new(); // statement 5 + + v3.push(&id('x')); // statement 6 + //~^ ERROR temporary value dropped while borrowed + //~| NOTE creates a temporary value which is freed while still in use + //~| NOTE temporary value is freed at the end of this statement + //~| HELP consider using a `let` binding to create a longer lived value + + { + + let mut v4 = Vec::new(); // (sub) statement 0 + + v4.push(&id('y')); + //~^ ERROR temporary value dropped while borrowed + //~| NOTE creates a temporary value which is freed while still in use + //~| NOTE temporary value is freed at the end of this statement + //~| NOTE consider using a `let` binding to create a longer lived value + v4.use_ref(); + //~^ NOTE borrow later used here + } // (statement 7) + + let mut v5 = Vec::new(); // statement 8 + + v5.push(&id('z')); + //~^ ERROR temporary value dropped while borrowed + //~| NOTE creates a temporary value which is freed while still in use + //~| NOTE temporary value is freed at the end of this statement + //~| HELP consider using a `let` binding to create a longer lived value + + v1.push(&old[0]); + + (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + //~^ NOTE borrow later used here + //~| NOTE borrow later used here + //~| NOTE borrow later used here +} + +fn main() { + f(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.stderr b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr new file mode 100644 index 000000000..2dc29a78d --- /dev/null +++ b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -0,0 +1,63 @@ +error[E0597]: `young[_]` does not live long enough + --> $DIR/borrowck-let-suggestion-suffixes.rs:12:17 + | +LL | v2.push(&young[0]); // statement 4 + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - `young[_]` dropped here while still borrowed +... +LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + | -- borrow later used here + +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion-suffixes.rs:19:14 + | +LL | v3.push(&id('x')); // statement 6 + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id('x'); +LL ~ v3.push(&binding); // statement 6 + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion-suffixes.rs:29:18 + | +LL | v4.push(&id('y')); + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | v4.use_ref(); + | ------------ borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-let-suggestion-suffixes.rs:40:14 + | +LL | v5.push(&id('z')); + | ^^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref(); + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id('z'); +LL ~ v5.push(&binding); + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0597, E0716. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/span/borrowck-object-mutability.rs b/tests/ui/span/borrowck-object-mutability.rs new file mode 100644 index 000000000..f5adc2cc1 --- /dev/null +++ b/tests/ui/span/borrowck-object-mutability.rs @@ -0,0 +1,26 @@ +trait Foo { + fn borrowed(&self); + fn borrowed_mut(&mut self); +} + +fn borrowed_receiver(x: &dyn Foo) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn borrowed_mut_receiver(x: &mut dyn Foo) { + x.borrowed(); + x.borrowed_mut(); +} + +fn owned_receiver(x: Box) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn mut_owned_receiver(mut x: Box) { + x.borrowed(); + x.borrowed_mut(); +} + +fn main() {} diff --git a/tests/ui/span/borrowck-object-mutability.stderr b/tests/ui/span/borrowck-object-mutability.stderr new file mode 100644 index 000000000..b6517e0b3 --- /dev/null +++ b/tests/ui/span/borrowck-object-mutability.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrowck-object-mutability.rs:8:5 + | +LL | x.borrowed_mut(); + | ^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrowed_receiver(x: &mut dyn Foo) { + | ~~~~~~~~~~~~ + +error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable + --> $DIR/borrowck-object-mutability.rs:18:5 + | +LL | x.borrowed_mut(); + | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn owned_receiver(mut x: Box) { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/borrowck-ref-into-rvalue.fixed b/tests/ui/span/borrowck-ref-into-rvalue.fixed new file mode 100644 index 000000000..51f65e534 --- /dev/null +++ b/tests/ui/span/borrowck-ref-into-rvalue.fixed @@ -0,0 +1,13 @@ +// run-rustfix +fn main() { + let msg; + let binding = Some("Hello".to_string()); + match binding { + //~^ ERROR temporary value dropped while borrowed + Some(ref m) => { + msg = m; + }, + None => { panic!() } + } + println!("{}", *msg); +} diff --git a/tests/ui/span/borrowck-ref-into-rvalue.rs b/tests/ui/span/borrowck-ref-into-rvalue.rs new file mode 100644 index 000000000..7b09fad92 --- /dev/null +++ b/tests/ui/span/borrowck-ref-into-rvalue.rs @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + let msg; + match Some("Hello".to_string()) { + //~^ ERROR temporary value dropped while borrowed + Some(ref m) => { + msg = m; + }, + None => { panic!() } + } + println!("{}", *msg); +} diff --git a/tests/ui/span/borrowck-ref-into-rvalue.stderr b/tests/ui/span/borrowck-ref-into-rvalue.stderr new file mode 100644 index 000000000..25e344fed --- /dev/null +++ b/tests/ui/span/borrowck-ref-into-rvalue.stderr @@ -0,0 +1,20 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/borrowck-ref-into-rvalue.rs:4:11 + | +LL | match Some("Hello".to_string()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | println!("{}", *msg); + | ---- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Some("Hello".to_string()); +LL ~ match binding { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/coerce-suggestions.rs b/tests/ui/span/coerce-suggestions.rs new file mode 100644 index 000000000..7920ae0b2 --- /dev/null +++ b/tests/ui/span/coerce-suggestions.rs @@ -0,0 +1,23 @@ +fn test(_x: &mut String) {} + +fn test2(_x: &mut i32) {} + + +fn main() { + let x: usize = String::new(); + //~^ ERROR E0308 + let x: &str = String::new(); + //~^ ERROR E0308 + let y = String::new(); + test(&y); + //~^ ERROR E0308 + test2(&y); + //~^ ERROR E0308 + let f; + f = Box::new(f); + //~^ ERROR E0308 + + let s = &mut String::new(); + s = format!("foo"); + //~^ ERROR E0308 +} diff --git a/tests/ui/span/coerce-suggestions.stderr b/tests/ui/span/coerce-suggestions.stderr new file mode 100644 index 000000000..db784d5fe --- /dev/null +++ b/tests/ui/span/coerce-suggestions.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:7:20 + | +LL | let x: usize = String::new(); + | ----- ^^^^^^^^^^^^^ expected `usize`, found struct `String` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:9:19 + | +LL | let x: &str = String::new(); + | ---- ^^^^^^^^^^^^^ + | | | + | | expected `&str`, found struct `String` + | | help: consider borrowing here: `&String::new()` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:12:10 + | +LL | test(&y); + | ---- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut String` + found reference `&String` +note: function defined here + --> $DIR/coerce-suggestions.rs:1:4 + | +LL | fn test(_x: &mut String) {} + | ^^^^ --------------- + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:14:11 + | +LL | test2(&y); + | ----- ^^ types differ in mutability + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut i32` + found reference `&String` +note: function defined here + --> $DIR/coerce-suggestions.rs:3:4 + | +LL | fn test2(_x: &mut i32) {} + | ^^^^^ ------------ + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:17:9 + | +LL | f = Box::new(f); + | ^^^^^^^^^^^ cyclic type of infinite size + | +help: consider unboxing the value + | +LL | f = *Box::new(f); + | + + +error[E0308]: mismatched types + --> $DIR/coerce-suggestions.rs:21:9 + | +LL | s = format!("foo"); + | ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String` + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/destructor-restrictions.rs b/tests/ui/span/destructor-restrictions.rs new file mode 100644 index 000000000..7fb348a14 --- /dev/null +++ b/tests/ui/span/destructor-restrictions.rs @@ -0,0 +1,11 @@ +// Tests the new destructor semantics. + +use std::cell::RefCell; + +fn main() { + let b = { + let a = Box::new(RefCell::new(4)); + *a.borrow() + 1 + }; //~^ ERROR `*a` does not live long enough + println!("{}", b); +} diff --git a/tests/ui/span/destructor-restrictions.stderr b/tests/ui/span/destructor-restrictions.stderr new file mode 100644 index 000000000..53c940462 --- /dev/null +++ b/tests/ui/span/destructor-restrictions.stderr @@ -0,0 +1,23 @@ +error[E0597]: `*a` does not live long enough + --> $DIR/destructor-restrictions.rs:8:10 + | +LL | *a.borrow() + 1 + | ^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, i32>` + | | + | `*a` dropped here while still borrowed + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = *a.borrow() + 1; x + | +++++++ +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs new file mode 100644 index 000000000..4559da91e --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs @@ -0,0 +1,18 @@ +// compile-flags: -Wrust-2021-incompatible-closure-captures + +pub struct A {} + +impl A { + async fn create(path: impl AsRef) { //~ ERROR `async fn` is not permitted in Rust 2015 + //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + ; + crate(move || {} ).await //~ ERROR expected function, found module `crate` + } +} + +trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015 +//~^ ERROR functions in traits cannot be declared `async` +//~| ERROR cannot find type `T` in this scope +//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures] + +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr new file mode 100644 index 000000000..df1cafdb7 --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr @@ -0,0 +1,95 @@ +error: this file contains an unclosed delimiter + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53 + | +LL | trait C{async fn new(val: T) {} + | - unclosed delimiter +... +LL | + | ^ + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5 + | +LL | async fn create(path: impl AsRef) { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0412]: cannot find type `T` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27 + | +LL | pub struct A {} + | ------------ similarly named struct `A` defined here +... +LL | trait C{async fn new(val: T) {} + | ^ help: a struct with a similar name exists: `A` + +error[E0706]: functions in traits cannot be declared `async` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9 + | +LL | trait C{async fn new(val: T) {} + | -----^^^^^^^^^^^^^^^ + | | + | `async` because of this + | + = note: `async` trait functions are not currently supported + = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait + = note: see issue #91611 for more information + = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable + +error[E0423]: expected function, found module `crate` + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5 + | +LL | crate(move || {} ).await + | ^^^^^ not a function + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57 + | +LL | async fn create(path: impl AsRef) { + | _____________________----_____________________________-__^ + | | | | + | | | in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure + | | in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect +LL | | +LL | | ; +LL | | crate(move || {} ).await +LL | | } + | |_____^ + | + = note: for more information, see + = note: requested on the command line with `-W rust-2021-incompatible-closure-captures` +help: add a dummy let to cause `path` to be fully captured + | +LL | async fn create(path: impl AsRef) { let _ = &path; + | ++++++++++++++ + +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30 + | +LL | trait C{async fn new(val: T) {} + | --- - ^^ + | | | + | | in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure + | in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect + | + = note: for more information, see +help: add a dummy let to cause `val` to be fully captured + | +LL | trait C{async fn new(val: T) { let _ = &val;} + | +++++++++++++ + +error: aborting due to 6 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0412, E0423, E0670, E0706. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs new file mode 100644 index 000000000..a776e5089 --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs @@ -0,0 +1,15 @@ +// compile-flags -Wrust-2021-incompatible-closure-captures + +fn main() {} + +pub(crate) struct Numberer {} + +impl Numberer { + pub(crate) async fn new( + //~^ ERROR `async fn` is not permitted in Rust 2015 + interval: Duration, + //~^ ERROR cannot find type `Duration` in this scope + ) -> Numberer { + Numberer {} + } +} diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr new file mode 100644 index 000000000..37b2f4138 --- /dev/null +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr @@ -0,0 +1,24 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:8:16 + | +LL | pub(crate) async fn new( + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0412]: cannot find type `Duration` in this scope + --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:10:19 + | +LL | interval: Duration, + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::time::Duration; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0412, E0670. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/span/dropck-object-cycle.rs b/tests/ui/span/dropck-object-cycle.rs new file mode 100644 index 000000000..a26123d52 --- /dev/null +++ b/tests/ui/span/dropck-object-cycle.rs @@ -0,0 +1,47 @@ +// This test used to be part of a run-pass test, but revised outlives +// rule means that it no longer compiles. + +#![allow(unused_variables)] + +trait Trait<'a> { + fn long(&'a self) -> isize; + fn short<'b>(&'b self) -> isize; +} + +fn object_invoke1<'d>(x: &'d dyn Trait<'d>) -> (isize, isize) { loop { } } + +trait MakerTrait { + fn mk() -> Self; +} + +fn make_val() -> T { + MakerTrait::mk() +} + +impl<'t> MakerTrait for Box+'static> { + fn mk() -> Box+'static> { loop { } } +} + +pub fn main() { + let m : Box = make_val(); + assert_eq!(object_invoke1(&*m), (4,5)); + //~^ ERROR `*m` does not live long enough + + // the problem here is that the full type of `m` is + // + // Box+'static> + // + // Here `'m` must be exactly the lifetime of the variable `m`. + // This is because of two requirements: + // 1. First, the basic type rules require that the + // type of `m`'s value outlives the lifetime of `m`. This puts a lower + // bound `'m`. + // + // 2. Meanwhile, the signature of `object_invoke1` requires that + // we create a reference of type `&'d Trait<'d>` for some `'d`. + // `'d` cannot outlive `'m`, so that forces the lifetime to be `'m`. + // + // This then conflicts with the dropck rules, which require that + // the type of `m` *strictly outlives* `'m`. Hence we get an + // error. +} diff --git a/tests/ui/span/dropck-object-cycle.stderr b/tests/ui/span/dropck-object-cycle.stderr new file mode 100644 index 000000000..229d17e1c --- /dev/null +++ b/tests/ui/span/dropck-object-cycle.stderr @@ -0,0 +1,15 @@ +error[E0597]: `*m` does not live long enough + --> $DIR/dropck-object-cycle.rs:27:31 + | +LL | assert_eq!(object_invoke1(&*m), (4,5)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `*m` dropped here while still borrowed + | borrow might be used here, when `m` is dropped and runs the destructor for type `Box>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_arr_cycle_checked.rs b/tests/ui/span/dropck_arr_cycle_checked.rs new file mode 100644 index 000000000..a14db5ff0 --- /dev/null +++ b/tests/ui/span/dropck_arr_cycle_checked.rs @@ -0,0 +1,106 @@ +// Reject mixing cyclic structure and Drop when using fixed length +// arrays. +// +// (Compare against ui/span/dropck_vec_cycle_checked.rs) + + + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId { + v: T +} + +#[allow(non_snake_case)] +fn CheckId(t: T) -> CheckId { CheckId{ v: t } } + +impl Drop for CheckId { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +#[derive(Debug)] +struct B<'a> { + id: Id, + a: [CheckId>>>; 2] +} + +impl<'a> HasId for Cell>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(b) => b.id.count(), + } + } +} + +impl<'a> B<'a> { + fn new() -> B<'a> { + B { id: Id::new(), a: [CheckId(Cell::new(None)), CheckId(Cell::new(None))] } + } +} + +fn f() { + let (b1, b2, b3); + b1 = B::new(); + b2 = B::new(); + b3 = B::new(); + b1.a[0].v.set(Some(&b2)); + //~^ ERROR `b2` does not live long enough + b1.a[1].v.set(Some(&b3)); + //~^ ERROR `b3` does not live long enough + b2.a[0].v.set(Some(&b2)); + b2.a[1].v.set(Some(&b3)); + b3.a[0].v.set(Some(&b1)); + //~^ ERROR `b1` does not live long enough + b3.a[1].v.set(Some(&b2)); +} + +fn main() { + f(); +} diff --git a/tests/ui/span/dropck_arr_cycle_checked.stderr b/tests/ui/span/dropck_arr_cycle_checked.stderr new file mode 100644 index 000000000..068c779ae --- /dev/null +++ b/tests/ui/span/dropck_arr_cycle_checked.stderr @@ -0,0 +1,43 @@ +error[E0597]: `b2` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:93:24 + | +LL | b1.a[0].v.set(Some(&b2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `b2` dropped here while still borrowed + | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `b3` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:95:24 + | +LL | b1.a[1].v.set(Some(&b3)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `b3` dropped here while still borrowed + | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `b1` does not live long enough + --> $DIR/dropck_arr_cycle_checked.rs:99:24 + | +LL | b3.a[0].v.set(Some(&b1)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `b1` dropped here while still borrowed + | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_direct_cycle_with_drop.rs b/tests/ui/span/dropck_direct_cycle_with_drop.rs new file mode 100644 index 000000000..14d6e6654 --- /dev/null +++ b/tests/ui/span/dropck_direct_cycle_with_drop.rs @@ -0,0 +1,44 @@ +// A simple example of an unsound mixing of cyclic structure and Drop. +// +// Each `D` has a name and an optional reference to another `D` +// sibling, but also implements a drop method that prints out its own +// name as well as the name of its sibling. +// +// By setting up a cyclic structure, the drop code cannot possibly +// work. Therefore this code must be rejected. +// +// (As it turns out, essentially any attempt to install a sibling here +// will be rejected, regardless of whether it forms a cyclic +// structure or not. This is because the use of the same lifetime +// `'a` in `&'a D<'a>` cannot be satisfied when `D<'a>` implements +// `Drop`.) + +use std::cell::Cell; + +struct D<'a> { + name: String, + p: Cell>>, +} + +impl<'a> D<'a> { + fn new(name: String) -> D<'a> { D { name: name, p: Cell::new(None) } } +} + +impl<'a> Drop for D<'a> { + fn drop(&mut self) { + println!("dropping {} whose sibling is {:?}", + self.name, self.p.get().map(|d| &d.name)); + } +} + +fn g() { + let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2"))); + d1.p.set(Some(&d2)); + //~^ ERROR `d2` does not live long enough + d2.p.set(Some(&d1)); + //~^ ERROR `d1` does not live long enough +} + +fn main() { + g(); +} diff --git a/tests/ui/span/dropck_direct_cycle_with_drop.stderr b/tests/ui/span/dropck_direct_cycle_with_drop.stderr new file mode 100644 index 000000000..07ae138ac --- /dev/null +++ b/tests/ui/span/dropck_direct_cycle_with_drop.stderr @@ -0,0 +1,29 @@ +error[E0597]: `d2` does not live long enough + --> $DIR/dropck_direct_cycle_with_drop.rs:36:19 + | +LL | d1.p.set(Some(&d2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `d2` dropped here while still borrowed + | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `d1` does not live long enough + --> $DIR/dropck_direct_cycle_with_drop.rs:38:19 + | +LL | d2.p.set(Some(&d1)); + | ^^^ borrowed value does not live long enough +LL | +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_misc_variants.rs b/tests/ui/span/dropck_misc_variants.rs new file mode 100644 index 000000000..5818a94bc --- /dev/null +++ b/tests/ui/span/dropck_misc_variants.rs @@ -0,0 +1,37 @@ +// check that dropck does the right thing with misc. Ty variants + +use std::fmt; +struct NoisyDrop(T); +impl Drop for NoisyDrop { + fn drop(&mut self) { + let _ = vec!["0wned"]; + println!("dropping {:?}", self.0) + } +} + +trait Associator { + type As; +} +impl Associator for T { + type As = NoisyDrop; +} +struct Wrap(::As); + +fn projection() { + let (_w, bomb); + bomb = vec![""]; + _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); +} +//~^^ ERROR `bomb` does not live long enough + +fn closure() { + let (_w,v); + v = vec![""]; + _w = { + let u = NoisyDrop(&v); + //~^ ERROR `v` does not live long enough + move || u.0.len() + }; +} + +fn main() { closure(); projection() } diff --git a/tests/ui/span/dropck_misc_variants.stderr b/tests/ui/span/dropck_misc_variants.stderr new file mode 100644 index 000000000..76e90574c --- /dev/null +++ b/tests/ui/span/dropck_misc_variants.stderr @@ -0,0 +1,30 @@ +error[E0597]: `bomb` does not live long enough + --> $DIR/dropck_misc_variants.rs:23:36 + | +LL | _w = Wrap::<&[&str]>(NoisyDrop(&bomb)); + | ^^^^^ borrowed value does not live long enough +LL | } + | - + | | + | `bomb` dropped here while still borrowed + | borrow might be used here, when `_w` is dropped and runs the destructor for type `Wrap<&[&str]>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `v` does not live long enough + --> $DIR/dropck_misc_variants.rs:31:27 + | +LL | let u = NoisyDrop(&v); + | ^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `v` dropped here while still borrowed + | borrow might be used here, when `_w` is dropped and runs the destructor for closure + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/dropck_vec_cycle_checked.rs b/tests/ui/span/dropck_vec_cycle_checked.rs new file mode 100644 index 000000000..c5d21507d --- /dev/null +++ b/tests/ui/span/dropck_vec_cycle_checked.rs @@ -0,0 +1,111 @@ +// Reject mixing cyclic structure and Drop when using Vec. +// +// (Compare against ui/span/dropck_arr_cycle_checked.rs) + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId { + v: T +} + +#[allow(non_snake_case)] +fn CheckId(t: T) -> CheckId { CheckId{ v: t } } + +impl Drop for CheckId { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +#[derive(Debug)] +struct C<'a> { + id: Id, + v: Vec>>>>, +} + +impl<'a> HasId for Cell>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(c) => c.id.count(), + } + } +} + +impl<'a> C<'a> { + fn new() -> C<'a> { + C { id: Id::new(), v: Vec::new() } + } +} + +fn f() { + let (mut c1, mut c2, mut c3); + c1 = C::new(); + c2 = C::new(); + c3 = C::new(); + + c1.v.push(CheckId(Cell::new(None))); + c1.v.push(CheckId(Cell::new(None))); + c2.v.push(CheckId(Cell::new(None))); + c2.v.push(CheckId(Cell::new(None))); + c3.v.push(CheckId(Cell::new(None))); + c3.v.push(CheckId(Cell::new(None))); + + c1.v[0].v.set(Some(&c2)); + //~^ ERROR `c2` does not live long enough + c1.v[1].v.set(Some(&c3)); + //~^ ERROR `c3` does not live long enough + c2.v[0].v.set(Some(&c2)); + c2.v[1].v.set(Some(&c3)); + c3.v[0].v.set(Some(&c1)); + //~^ ERROR `c1` does not live long enough + c3.v[1].v.set(Some(&c2)); +} + +fn main() { + f(); +} diff --git a/tests/ui/span/dropck_vec_cycle_checked.stderr b/tests/ui/span/dropck_vec_cycle_checked.stderr new file mode 100644 index 000000000..7ff991c0c --- /dev/null +++ b/tests/ui/span/dropck_vec_cycle_checked.stderr @@ -0,0 +1,43 @@ +error[E0597]: `c2` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:98:24 + | +LL | c1.v[0].v.set(Some(&c2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c2` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c3` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:100:24 + | +LL | c1.v[1].v.set(Some(&c3)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c3` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c1` does not live long enough + --> $DIR/dropck_vec_cycle_checked.rs:104:24 + | +LL | c3.v[0].v.set(Some(&c1)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c1` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/gated-features-attr-spans.rs b/tests/ui/span/gated-features-attr-spans.rs new file mode 100644 index 000000000..69511ab8e --- /dev/null +++ b/tests/ui/span/gated-features-attr-spans.rs @@ -0,0 +1,7 @@ +#[repr(simd)] //~ ERROR are experimental +struct Coord { + x: u32, + y: u32, +} + +fn main() {} diff --git a/tests/ui/span/gated-features-attr-spans.stderr b/tests/ui/span/gated-features-attr-spans.stderr new file mode 100644 index 000000000..c8b8f346b --- /dev/null +++ b/tests/ui/span/gated-features-attr-spans.stderr @@ -0,0 +1,12 @@ +error[E0658]: SIMD types are experimental and possibly buggy + --> $DIR/gated-features-attr-spans.rs:1:1 + | +LL | #[repr(simd)] + | ^^^^^^^^^^^^^ + | + = note: see issue #27731 for more information + = help: add `#![feature(repr_simd)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/span/impl-wrong-item-for-trait.rs b/tests/ui/span/impl-wrong-item-for-trait.rs new file mode 100644 index 000000000..bf3358686 --- /dev/null +++ b/tests/ui/span/impl-wrong-item-for-trait.rs @@ -0,0 +1,38 @@ +use std::fmt::Debug; + +trait Foo { + fn bar(&self); + const MY_CONST: u32; +} + +pub struct FooConstForMethod; + +impl Foo for FooConstForMethod { + //~^ ERROR E0046 + const bar: u64 = 1; + //~^ ERROR E0323 + const MY_CONST: u32 = 1; +} + +pub struct FooMethodForConst; + +impl Foo for FooMethodForConst { + //~^ ERROR E0046 + fn bar(&self) {} + fn MY_CONST() {} + //~^ ERROR E0324 +} + +pub struct FooTypeForMethod; + +impl Foo for FooTypeForMethod { + //~^ ERROR E0046 + type bar = u64; + //~^ ERROR E0325 + const MY_CONST: u32 = 1; +} + +impl Debug for FooTypeForMethod {} +//~^ ERROR E0046 + +fn main() {} diff --git a/tests/ui/span/impl-wrong-item-for-trait.stderr b/tests/ui/span/impl-wrong-item-for-trait.stderr new file mode 100644 index 000000000..f919092f9 --- /dev/null +++ b/tests/ui/span/impl-wrong-item-for-trait.stderr @@ -0,0 +1,66 @@ +error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo` + --> $DIR/impl-wrong-item-for-trait.rs:12:5 + | +LL | fn bar(&self); + | -------------- item in trait +... +LL | const bar: u64 = 1; + | ^^^^^^^^^^^^^^^^^^^ does not match trait + +error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo` + --> $DIR/impl-wrong-item-for-trait.rs:22:5 + | +LL | const MY_CONST: u32; + | -------------------- item in trait +... +LL | fn MY_CONST() {} + | ^^^^^^^^^^^^^^^^ does not match trait + +error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo` + --> $DIR/impl-wrong-item-for-trait.rs:30:5 + | +LL | fn bar(&self); + | -------------- item in trait +... +LL | type bar = u64; + | ^^^^^^^^^^^^^^^ does not match trait + +error[E0046]: not all trait items implemented, missing: `bar` + --> $DIR/impl-wrong-item-for-trait.rs:10:1 + | +LL | fn bar(&self); + | -------------- `bar` from trait +... +LL | impl Foo for FooConstForMethod { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `MY_CONST` + --> $DIR/impl-wrong-item-for-trait.rs:19:1 + | +LL | const MY_CONST: u32; + | ------------------- `MY_CONST` from trait +... +LL | impl Foo for FooMethodForConst { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `MY_CONST` in implementation + +error[E0046]: not all trait items implemented, missing: `bar` + --> $DIR/impl-wrong-item-for-trait.rs:28:1 + | +LL | fn bar(&self); + | -------------- `bar` from trait +... +LL | impl Foo for FooTypeForMethod { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `fmt` + --> $DIR/impl-wrong-item-for-trait.rs:35:1 + | +LL | impl Debug for FooTypeForMethod {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `fmt` in implementation + | + = help: implement the missing item: `fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0046, E0323, E0324, E0325. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/span/import-ty-params.rs b/tests/ui/span/import-ty-params.rs new file mode 100644 index 000000000..313cd227b --- /dev/null +++ b/tests/ui/span/import-ty-params.rs @@ -0,0 +1,23 @@ +mod a { + pub mod b { + pub mod c { + pub struct S(T); + } + } +} + +macro_rules! import { + ($p: path) => (use $p;); +} + +fn f1() { + import! { a::b::c::S } //~ ERROR unexpected generic arguments in path +} +fn f2() { + import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path +} +fn f3() { + import! { a::b<>::c::S<> } //~ ERROR unexpected generic arguments in path +} + +fn main() {} diff --git a/tests/ui/span/import-ty-params.stderr b/tests/ui/span/import-ty-params.stderr new file mode 100644 index 000000000..701cd0c04 --- /dev/null +++ b/tests/ui/span/import-ty-params.stderr @@ -0,0 +1,20 @@ +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:14:25 + | +LL | import! { a::b::c::S } + | ^^^^ + +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:17:25 + | +LL | import! { a::b::c::S<> } + | ^^ + +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:20:19 + | +LL | import! { a::b<>::c::S<> } + | ^^ ^^^^ ^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/span/issue-11925.rs b/tests/ui/span/issue-11925.rs new file mode 100644 index 000000000..cac9fd5bf --- /dev/null +++ b/tests/ui/span/issue-11925.rs @@ -0,0 +1,13 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_once>(f: F) -> F { f } + +fn main() { + let r = { + let x: Box<_> = Box::new(42); + let f = to_fn_once(move|| &x); //~ ERROR cannot return reference to local data `x` + f() + }; + + drop(r); +} diff --git a/tests/ui/span/issue-11925.stderr b/tests/ui/span/issue-11925.stderr new file mode 100644 index 000000000..1d317fc33 --- /dev/null +++ b/tests/ui/span/issue-11925.stderr @@ -0,0 +1,9 @@ +error[E0515]: cannot return reference to local data `x` + --> $DIR/issue-11925.rs:8:35 + | +LL | let f = to_fn_once(move|| &x); + | ^^ returns a reference to data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/span/issue-15480.fixed b/tests/ui/span/issue-15480.fixed new file mode 100644 index 000000000..e6d1a4dd3 --- /dev/null +++ b/tests/ui/span/issue-15480.fixed @@ -0,0 +1,14 @@ +// run-rustfix +fn id(x: T) -> T { x } + +fn main() { + let binding = id(3); + let v = vec![ + &binding + ]; + //~^^ ERROR temporary value dropped while borrowed + + for &&x in &v { + println!("{}", x + 3); + } +} diff --git a/tests/ui/span/issue-15480.rs b/tests/ui/span/issue-15480.rs new file mode 100644 index 000000000..916ce4b1e --- /dev/null +++ b/tests/ui/span/issue-15480.rs @@ -0,0 +1,13 @@ +// run-rustfix +fn id(x: T) -> T { x } + +fn main() { + let v = vec![ + &id(3) + ]; + //~^^ ERROR temporary value dropped while borrowed + + for &&x in &v { + println!("{}", x + 3); + } +} diff --git a/tests/ui/span/issue-15480.stderr b/tests/ui/span/issue-15480.stderr new file mode 100644 index 000000000..d9cce2254 --- /dev/null +++ b/tests/ui/span/issue-15480.stderr @@ -0,0 +1,21 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-15480.rs:6:10 + | +LL | &id(3) + | ^^^^^ creates a temporary value which is freed while still in use +LL | ]; + | - temporary value is freed at the end of this statement +... +LL | for &&x in &v { + | -- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = id(3); +LL ~ let v = vec![ +LL ~ &binding + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs new file mode 100644 index 000000000..a92ea4ddc --- /dev/null +++ b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.rs @@ -0,0 +1,28 @@ +// This is just checking that we still reject code where temp values +// are borrowing values for longer than they will be around. +// +// Compare to run-pass/issue-23338-params-outlive-temps-of-body.rs + +use std::cell::RefCell; + +fn foo(x: RefCell) -> String { + let y = x; + y.borrow().clone() +} +//~^^ ERROR `y` does not live long enough + +fn foo2(x: RefCell) -> String { + let ret = { + let y = x; + y.borrow().clone() + }; + //~^^ ERROR `y` does not live long enough + ret +} + +fn main() { + let r = RefCell::new(format!("data")); + assert_eq!(foo(r), "data"); + let r = RefCell::new(format!("data")); + assert_eq!(foo2(r), "data"); +} diff --git a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr new file mode 100644 index 000000000..3c2022748 --- /dev/null +++ b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr @@ -0,0 +1,44 @@ +error[E0597]: `y` does not live long enough + --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:10:5 + | +LL | y.borrow().clone() + | ^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | } + | - + | | + | `y` dropped here while still borrowed + | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, String>` + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = y.borrow().clone(); x + | +++++++ +++ + +error[E0597]: `y` does not live long enough + --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:17:9 + | +LL | y.borrow().clone() + | ^^^^^^^^^^ + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, String>` + | | + | `y` dropped here while still borrowed + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = y.borrow().clone(); x + | +++++++ +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-23729.rs b/tests/ui/span/issue-23729.rs new file mode 100644 index 000000000..ca33f9c77 --- /dev/null +++ b/tests/ui/span/issue-23729.rs @@ -0,0 +1,33 @@ +// Regression test for #23729 + +fn main() { + let fib = { + struct Recurrence { + mem: [u64; 2], + pos: usize, + } + + impl Iterator for Recurrence { + //~^ ERROR E0046 + #[inline] + fn next(&mut self) -> Option { + if self.pos < 2 { + let next_val = self.mem[self.pos]; + self.pos += 1; + Some(next_val) + } else { + let next_val = self.mem[0] + self.mem[1]; + self.mem[0] = self.mem[1]; + self.mem[1] = next_val; + Some(next_val) + } + } + } + + Recurrence { mem: [0, 1], pos: 0 } + }; + + for e in fib.take(10) { + println!("{}", e) + } +} diff --git a/tests/ui/span/issue-23729.stderr b/tests/ui/span/issue-23729.stderr new file mode 100644 index 000000000..f88ce6c88 --- /dev/null +++ b/tests/ui/span/issue-23729.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `Item` + --> $DIR/issue-23729.rs:10:9 + | +LL | impl Iterator for Recurrence { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation + | + = help: implement the missing item: `type Item = Type;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs new file mode 100644 index 000000000..6b065bf6c --- /dev/null +++ b/tests/ui/span/issue-23827.rs @@ -0,0 +1,33 @@ +// Regression test for #23827 + +#![feature(fn_traits, unboxed_closures)] + +pub struct Prototype { + pub target: u32 +} + +trait Component { + fn apply(self, e: u32); +} + +impl Fn<(C,)> for Prototype { + extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype { + comp.apply(self.target); + *self + } +} + +impl FnMut<(C,)> for Prototype { + extern "rust-call" fn call_mut(&mut self, (comp,): (C,)) -> Prototype { + Fn::call(*&self, (comp,)) + } +} + +impl FnOnce<(C,)> for Prototype { + //~^ ERROR E0046 + extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype { + Fn::call(&self, (comp,)) + } +} + +fn main() {} diff --git a/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr new file mode 100644 index 000000000..46a820f1b --- /dev/null +++ b/tests/ui/span/issue-23827.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `Output` + --> $DIR/issue-23827.rs:26:1 + | +LL | impl FnOnce<(C,)> for Prototype { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation + | + = help: implement the missing item: `type Output = Type;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-24356.rs b/tests/ui/span/issue-24356.rs new file mode 100644 index 000000000..7ec05aab2 --- /dev/null +++ b/tests/ui/span/issue-24356.rs @@ -0,0 +1,27 @@ +// Regression test for #24356 + +fn main() { + { + use std::ops::Deref; + + struct Thing(i8); + + /* + // Correct impl + impl Deref for Thing { + type Target = i8; + fn deref(&self) -> &i8 { &self.0 } + } + */ + + // Causes ICE + impl Deref for Thing { + //~^ ERROR E0046 + fn deref(&self) -> i8 { self.0 } + } + + let thing = Thing(72); + + *thing + }; +} diff --git a/tests/ui/span/issue-24356.stderr b/tests/ui/span/issue-24356.stderr new file mode 100644 index 000000000..a1f9b2550 --- /dev/null +++ b/tests/ui/span/issue-24356.stderr @@ -0,0 +1,11 @@ +error[E0046]: not all trait items implemented, missing: `Target` + --> $DIR/issue-24356.rs:18:9 + | +LL | impl Deref for Thing { + | ^^^^^^^^^^^^^^^^^^^^ missing `Target` in implementation + | + = help: implement the missing item: `type Target = Type;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/span/issue-24690.rs b/tests/ui/span/issue-24690.rs new file mode 100644 index 000000000..2b7349c55 --- /dev/null +++ b/tests/ui/span/issue-24690.rs @@ -0,0 +1,16 @@ +//! A test to ensure that helpful `note` messages aren't emitted more often +//! than necessary. + +// check-pass + +// Although there are three warnings, we should only get two "lint level defined +// here" notes pointing at the `warnings` span, one for each error type. +#![warn(unused)] + + +fn main() { + let theTwo = 2; //~ WARN should have a snake case name + let theOtherTwo = 2; //~ WARN should have a snake case name + //~^ WARN unused variable + println!("{}", theTwo); +} diff --git a/tests/ui/span/issue-24690.stderr b/tests/ui/span/issue-24690.stderr new file mode 100644 index 000000000..73e166e64 --- /dev/null +++ b/tests/ui/span/issue-24690.stderr @@ -0,0 +1,29 @@ +warning: unused variable: `theOtherTwo` + --> $DIR/issue-24690.rs:13:9 + | +LL | let theOtherTwo = 2; + | ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_theOtherTwo` + | +note: the lint level is defined here + --> $DIR/issue-24690.rs:8:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: variable `theTwo` should have a snake case name + --> $DIR/issue-24690.rs:12:9 + | +LL | let theTwo = 2; + | ^^^^^^ help: convert the identifier to snake case: `the_two` + | + = note: `#[warn(non_snake_case)]` on by default + +warning: variable `theOtherTwo` should have a snake case name + --> $DIR/issue-24690.rs:13:9 + | +LL | let theOtherTwo = 2; + | ^^^^^^^^^^^ help: convert the identifier to snake case: `the_other_two` + +warning: 3 warnings emitted + diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs new file mode 100644 index 000000000..9c772052f --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.rs @@ -0,0 +1,37 @@ +// Check that child trait who only has items via its *parent* trait +// does cause dropck to inject extra region constraints. + +#![allow(non_camel_case_types)] + +trait Parent { fn foo(&self); } +trait Child: Parent { } + +impl Parent for i32 { fn foo(&self) { } } +impl<'a> Parent for &'a D_Child { + fn foo(&self) { + println!("accessing child value: {}", self.0); + } +} + +impl Child for i32 { } +impl<'a> Child for &'a D_Child { } + +struct D_Child(T); +impl Drop for D_Child { fn drop(&mut self) { self.0.foo() } } + +fn f_child() { + // `_d` and `d1` are assigned the *same* lifetime by region inference ... + let (_d, d1); + + d1 = D_Child(1); + // ... we store a reference to `d1` within `_d` ... + _d = D_Child(&d1); + //~^ ERROR `d1` does not live long enough + + // ... dropck *should* complain, because Drop of _d could (and + // does) access the already dropped `d1` via the `foo` method. +} + +fn main() { + f_child(); +} diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr new file mode 100644 index 000000000..809e60a8c --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr @@ -0,0 +1,17 @@ +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:28:18 + | +LL | _d = D_Child(&d1); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_Child` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-24805-dropck-trait-has-items.rs b/tests/ui/span/issue-24805-dropck-trait-has-items.rs new file mode 100644 index 000000000..b5c410cd3 --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-trait-has-items.rs @@ -0,0 +1,57 @@ +// Check that traits with various kinds of associated items cause +// dropck to inject extra region constraints. + +#![allow(non_camel_case_types)] + +trait HasSelfMethod { fn m1(&self) { } } +trait HasMethodWithSelfArg { fn m2(x: &Self) { } } +trait HasType { type Something; } + +impl HasSelfMethod for i32 { } +impl HasMethodWithSelfArg for i32 { } +impl HasType for i32 { type Something = (); } + +impl<'a,T> HasSelfMethod for &'a T { } +impl<'a,T> HasMethodWithSelfArg for &'a T { } +impl<'a,T> HasType for &'a T { type Something = (); } + +// e.g., `impl_drop!(Send, D_Send)` expands to: +// ```rust +// struct D_Send(T); +// impl Drop for D_Send { fn drop(&mut self) { } } +// ``` +macro_rules! impl_drop { + ($Bound:ident, $Id:ident) => { + struct $Id(T); + impl Drop for $Id { fn drop(&mut self) { } } + } +} + +impl_drop!{HasSelfMethod, D_HasSelfMethod} +impl_drop!{HasMethodWithSelfArg, D_HasMethodWithSelfArg} +impl_drop!{HasType, D_HasType} + +fn f_sm() { + let (_d, d1); + d1 = D_HasSelfMethod(1); + _d = D_HasSelfMethod(&d1); +} +//~^^ ERROR `d1` does not live long enough +fn f_mwsa() { + let (_d, d1); + d1 = D_HasMethodWithSelfArg(1); + _d = D_HasMethodWithSelfArg(&d1); +} +//~^^ ERROR `d1` does not live long enough +fn f_t() { + let (_d, d1); + d1 = D_HasType(1); + _d = D_HasType(&d1); +} +//~^^ ERROR `d1` does not live long enough + +fn main() { + f_sm(); + f_mwsa(); + f_t(); +} diff --git a/tests/ui/span/issue-24805-dropck-trait-has-items.stderr b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr new file mode 100644 index 000000000..2e2170669 --- /dev/null +++ b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr @@ -0,0 +1,42 @@ +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-trait-has-items.rs:37:26 + | +LL | _d = D_HasSelfMethod(&d1); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasSelfMethod` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-trait-has-items.rs:43:33 + | +LL | _d = D_HasMethodWithSelfArg(&d1); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasMethodWithSelfArg` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24805-dropck-trait-has-items.rs:49:20 + | +LL | _d = D_HasType(&d1); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasType` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-24895-copy-clone-dropck.rs b/tests/ui/span/issue-24895-copy-clone-dropck.rs new file mode 100644 index 000000000..904cd8f67 --- /dev/null +++ b/tests/ui/span/issue-24895-copy-clone-dropck.rs @@ -0,0 +1,29 @@ +// Check that one cannot subvert Drop Check rule via a user-defined +// Clone implementation. + +#![allow(unused_variables, unused_assignments)] + +struct D(T, &'static str); + +#[derive(Copy)] +struct S<'a>(&'a D, &'static str); +impl<'a> Clone for S<'a> { + fn clone(&self) -> S<'a> { + println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0); + S(self.0, self.1) + } +} + +impl Drop for D { + fn drop(&mut self) { + println!("calling Drop for {}", self.1); + let _call = self.0.clone(); + } +} + +fn main() { + let (d2, d1); + d1 = D(34, "d1"); + d2 = D(S(&d1, "inner"), "d2"); +} +//~^^ ERROR `d1` does not live long enough diff --git a/tests/ui/span/issue-24895-copy-clone-dropck.stderr b/tests/ui/span/issue-24895-copy-clone-dropck.stderr new file mode 100644 index 000000000..18a3dc9e6 --- /dev/null +++ b/tests/ui/span/issue-24895-copy-clone-dropck.stderr @@ -0,0 +1,16 @@ +error[E0597]: `d1` does not live long enough + --> $DIR/issue-24895-copy-clone-dropck.rs:27:14 + | +LL | d2 = D(S(&d1, "inner"), "d2"); + | ^^^ borrowed value does not live long enough +LL | } + | - + | | + | `d1` dropped here while still borrowed + | borrow might be used here, when `d2` is dropped and runs the `Drop` code for type `D` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-25199.rs b/tests/ui/span/issue-25199.rs new file mode 100644 index 000000000..dbc3b1900 --- /dev/null +++ b/tests/ui/span/issue-25199.rs @@ -0,0 +1,74 @@ +// Regression test for Issue 25199: Check that one cannot hide a +// destructor's access to borrowed data behind a boxed trait object. +// +// Prior to fixing Issue 25199, this example was able to be compiled +// with rustc, and thus when you ran it, you would see the `Drop` impl +// for `Test` accessing state that had already been dropping (which is +// marked explicitly here with checking code within the `Drop` impl +// for `VecHolder`, but in the general case could just do unsound +// things like accessing memory that has been freed). +// +// Note that I would have liked to encode my go-to example of cyclic +// structure that accesses its neighbors in drop (and thus is +// fundamentally unsound) via this trick, but the closest I was able +// to come was dropck_trait_cycle_checked.rs, which is not quite as +// "good" as this regression test because the encoding of that example +// was forced to attach a lifetime to the trait definition itself +// (`trait Obj<'a>`) while *this* example is solely + +use std::cell::RefCell; + +trait Obj { } + +struct VecHolder { + v: Vec<(bool, &'static str)>, +} + +impl Drop for VecHolder { + fn drop(&mut self) { + println!("Dropping Vec"); + self.v[30].0 = false; + self.v[30].1 = "invalid access: VecHolder dropped already"; + } +} + +struct Container<'a> { + v: VecHolder, + d: RefCell>>, +} + +impl<'a> Container<'a> { + fn new() -> Container<'a> { + Container { + d: RefCell::new(Vec::new()), + v: VecHolder { + v: vec![(true, "valid"); 100] + } + } + } + + fn store(&'a self, val: T) { + self.d.borrow_mut().push(Box::new(val)); + } +} + +struct Test<'a> { + test: &'a Container<'a>, +} + +impl<'a> Obj for Test<'a> { } +impl<'a> Drop for Test<'a> { + fn drop(&mut self) { + for e in &self.test.v.v { + assert!(e.0, e.1); + } + } +} + +fn main() { + let container = Container::new(); + let test = Test{test: &container}; + //~^ ERROR `container` does not live long enough + println!("container.v[30]: {:?}", container.v.v[30]); + container.store(test); +} diff --git a/tests/ui/span/issue-25199.stderr b/tests/ui/span/issue-25199.stderr new file mode 100644 index 000000000..d70a4afc1 --- /dev/null +++ b/tests/ui/span/issue-25199.stderr @@ -0,0 +1,15 @@ +error[E0597]: `container` does not live long enough + --> $DIR/issue-25199.rs:70:27 + | +LL | let test = Test{test: &container}; + | ^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `container` dropped here while still borrowed + | borrow might be used here, when `container` is dropped and runs the destructor for type `Container<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-26656.rs b/tests/ui/span/issue-26656.rs new file mode 100644 index 000000000..cde68da18 --- /dev/null +++ b/tests/ui/span/issue-26656.rs @@ -0,0 +1,42 @@ +// Issue #26656: Verify that trait objects cannot bypass dropck. + +// Using this instead of Fn etc. to take HRTB out of the equation. +trait Trigger { fn fire(&self, b: &mut B); } +impl Trigger for () { + fn fire(&self, b: &mut B) { + b.push(); + } +} + +// Still unsound Zook +trait Button { fn push(&self); } +struct Zook { button: B, trigger: Box+'static> } + +impl Drop for Zook { + fn drop(&mut self) { + self.trigger.fire(&mut self.button); + } +} + +// AND +struct Bomb { usable: bool } +impl Drop for Bomb { fn drop(&mut self) { self.usable = false; } } +impl Bomb { fn activate(&self) { assert!(self.usable) } } + +enum B<'a> { HarmlessButton, BigRedButton(&'a Bomb) } +impl<'a> Button for B<'a> { + fn push(&self) { + if let B::BigRedButton(borrowed) = *self { + borrowed.activate(); + } + } +} + +fn main() { + let (mut zook, ticking); + zook = Zook { button: B::HarmlessButton, + trigger: Box::new(()) }; + ticking = Bomb { usable: true }; + zook.button = B::BigRedButton(&ticking); +} +//~^^ ERROR `ticking` does not live long enough diff --git a/tests/ui/span/issue-26656.stderr b/tests/ui/span/issue-26656.stderr new file mode 100644 index 000000000..1e939c484 --- /dev/null +++ b/tests/ui/span/issue-26656.stderr @@ -0,0 +1,16 @@ +error[E0597]: `ticking` does not live long enough + --> $DIR/issue-26656.rs:40:35 + | +LL | zook.button = B::BigRedButton(&ticking); + | ^^^^^^^^ borrowed value does not live long enough +LL | } + | - + | | + | `ticking` dropped here while still borrowed + | borrow might be used here, when `zook` is dropped and runs the `Drop` code for type `Zook` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-27522.rs b/tests/ui/span/issue-27522.rs new file mode 100644 index 000000000..7a0cfb679 --- /dev/null +++ b/tests/ui/span/issue-27522.rs @@ -0,0 +1,9 @@ +// Point at correct span for self type + +struct SomeType {} + +trait Foo { + fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type +} + +fn main() {} diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr new file mode 100644 index 000000000..8a254a968 --- /dev/null +++ b/tests/ui/span/issue-27522.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid `self` parameter type: &SomeType + --> $DIR/issue-27522.rs:6:22 + | +LL | fn handler(self: &SomeType); + | ^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/span/issue-29106.rs b/tests/ui/span/issue-29106.rs new file mode 100644 index 000000000..1be8d4cba --- /dev/null +++ b/tests/ui/span/issue-29106.rs @@ -0,0 +1,26 @@ +use std::rc::Rc; +use std::sync::Arc; + +struct Foo<'a>(&'a String); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + println!("{:?}", self.0); + } +} + +fn main() { + { + let (y, x); + x = "alive".to_string(); + y = Arc::new(Foo(&x)); + } + //~^^ ERROR `x` does not live long enough + + { + let (y, x); + x = "alive".to_string(); + y = Rc::new(Foo(&x)); + } + //~^^ ERROR `x` does not live long enough +} diff --git a/tests/ui/span/issue-29106.stderr b/tests/ui/span/issue-29106.stderr new file mode 100644 index 000000000..71fbd60ee --- /dev/null +++ b/tests/ui/span/issue-29106.stderr @@ -0,0 +1,29 @@ +error[E0597]: `x` does not live long enough + --> $DIR/issue-29106.rs:16:26 + | +LL | y = Arc::new(Foo(&x)); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `y` is dropped and runs the `Drop` code for type `Arc` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `x` does not live long enough + --> $DIR/issue-29106.rs:23:25 + | +LL | y = Rc::new(Foo(&x)); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `y` is dropped and runs the `Drop` code for type `Rc` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-29595.rs b/tests/ui/span/issue-29595.rs new file mode 100644 index 000000000..87d7c4cfd --- /dev/null +++ b/tests/ui/span/issue-29595.rs @@ -0,0 +1,7 @@ +trait Tr { + const C: Self; +} + +fn main() { + let a: u8 = Tr::C; //~ ERROR the trait bound `u8: Tr` is not satisfied +} diff --git a/tests/ui/span/issue-29595.stderr b/tests/ui/span/issue-29595.stderr new file mode 100644 index 000000000..92445e407 --- /dev/null +++ b/tests/ui/span/issue-29595.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `u8: Tr` is not satisfied + --> $DIR/issue-29595.rs:6:17 + | +LL | let a: u8 = Tr::C; + | ^^^^^ the trait `Tr` is not implemented for `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/issue-33884.rs b/tests/ui/span/issue-33884.rs new file mode 100644 index 000000000..5d927a5ac --- /dev/null +++ b/tests/ui/span/issue-33884.rs @@ -0,0 +1,18 @@ +use std::net::TcpListener; +use std::net::TcpStream; +use std::io::{self, Read, Write}; + +fn handle_client(stream: TcpStream) -> io::Result<()> { + stream.write_fmt(format!("message received")) + //~^ ERROR mismatched types +} + +fn main() { + if let Ok(listener) = TcpListener::bind("127.0.0.1:8080") { + for incoming in listener.incoming() { + if let Ok(stream) = incoming { + handle_client(stream); + } + } + } +} diff --git a/tests/ui/span/issue-33884.stderr b/tests/ui/span/issue-33884.stderr new file mode 100644 index 000000000..aee153085 --- /dev/null +++ b/tests/ui/span/issue-33884.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-33884.rs:6:22 + | +LL | stream.write_fmt(format!("message received")) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String` + | + = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/issue-34264.rs b/tests/ui/span/issue-34264.rs new file mode 100644 index 000000000..9227ee482 --- /dev/null +++ b/tests/ui/span/issue-34264.rs @@ -0,0 +1,11 @@ +fn foo(Option, String) {} //~ ERROR expected one of +//~^ ERROR expected one of +fn bar(x, y: usize) {} //~ ERROR expected one of + +fn main() { + foo(Some(42), 2); + foo(Some(42), 2, ""); //~ ERROR function takes + bar("", ""); //~ ERROR mismatched types + bar(1, 2); + bar(1, 2, 3); //~ ERROR function takes +} diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr new file mode 100644 index 000000000..15179954a --- /dev/null +++ b/tests/ui/span/issue-34264.stderr @@ -0,0 +1,102 @@ +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/issue-34264.rs:1:14 + | +LL | fn foo(Option, String) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo(self: Option, String) {} + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo(_: Option, String) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/issue-34264.rs:1:27 + | +LL | fn foo(Option, String) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn foo(Option, String: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo(Option, _: String) {} + | ++ + +error: expected one of `:`, `@`, or `|`, found `,` + --> $DIR/issue-34264.rs:3:9 + | +LL | fn bar(x, y: usize) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn bar(self: x, y: usize) {} + | +++++ +help: if this is a parameter name, give it a type + | +LL | fn bar(x: TypeName, y: usize) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn bar(_: x, y: usize) {} + | ++ + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/issue-34264.rs:7:5 + | +LL | foo(Some(42), 2, ""); + | ^^^ -- argument of type `&'static str` unexpected + | +note: function defined here + --> $DIR/issue-34264.rs:1:4 + | +LL | fn foo(Option, String) {} + | ^^^ ----------- ------ +help: remove the extra argument + | +LL | foo(Some(42), 2); + | ~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/issue-34264.rs:8:13 + | +LL | bar("", ""); + | --- ^^ expected `usize`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-34264.rs:3:4 + | +LL | fn bar(x, y: usize) {} + | ^^^ -------- + +error[E0061]: this function takes 2 arguments but 3 arguments were supplied + --> $DIR/issue-34264.rs:10:5 + | +LL | bar(1, 2, 3); + | ^^^ - argument of type `{integer}` unexpected + | +note: function defined here + --> $DIR/issue-34264.rs:3:4 + | +LL | fn bar(x, y: usize) {} + | ^^^ - -------- +help: remove the extra argument + | +LL | bar(1, 2); + | ~~~~~~ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/span/issue-35987.rs b/tests/ui/span/issue-35987.rs new file mode 100644 index 000000000..3a6e6ffe2 --- /dev/null +++ b/tests/ui/span/issue-35987.rs @@ -0,0 +1,14 @@ +struct Foo(T); + +use std::ops::Add; + +impl Add for Foo { +//~^ ERROR expected trait, found type parameter + type Output = usize; + + fn add(self, rhs: Self) -> Self::Output { + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr new file mode 100644 index 000000000..057d40ac0 --- /dev/null +++ b/tests/ui/span/issue-35987.stderr @@ -0,0 +1,19 @@ +error[E0404]: expected trait, found type parameter `Add` + --> $DIR/issue-35987.rs:5:21 + | +LL | use std::ops::Add; + | --- you might have meant to refer to this trait +LL | +LL | impl Add for Foo { + | --- ^^^ not a trait + | | + | found this type parameter + | +help: consider importing this trait instead + | +LL | use std::ops::Add; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/span/issue-36537.rs b/tests/ui/span/issue-36537.rs new file mode 100644 index 000000000..a5546ccbb --- /dev/null +++ b/tests/ui/span/issue-36537.rs @@ -0,0 +1,14 @@ +fn main() { + let p; + { + let a = 42; + p = &a; + //~^ ERROR `a` does not live long enough + + } + p.use_ref(); + +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/issue-36537.stderr b/tests/ui/span/issue-36537.stderr new file mode 100644 index 000000000..79a0ebaeb --- /dev/null +++ b/tests/ui/span/issue-36537.stderr @@ -0,0 +1,14 @@ +error[E0597]: `a` does not live long enough + --> $DIR/issue-36537.rs:5:13 + | +LL | p = &a; + | ^^ borrowed value does not live long enough +... +LL | } + | - `a` dropped here while still borrowed +LL | p.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-37767.rs b/tests/ui/span/issue-37767.rs new file mode 100644 index 000000000..9e34c2c1f --- /dev/null +++ b/tests/ui/span/issue-37767.rs @@ -0,0 +1,41 @@ +trait A { + fn foo(&mut self) {} +} + +trait B : A { + fn foo(&mut self) {} +} + +fn bar(a: &T) { + a.foo() //~ ERROR multiple applicable items +} + +trait C { + fn foo(&self) {} +} + +trait D : C { + fn foo(&self) {} +} + +fn quz(a: &T) { + a.foo() //~ ERROR multiple applicable items +} + +trait E : Sized { + fn foo(self) {} +} + +trait F : E { + fn foo(self) {} +} + +fn foo(a: T) { + a.foo() //~ ERROR multiple applicable items +} + +fn pass(a: &T) { + a.foo() +} + +fn main() {} diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr new file mode 100644 index 000000000..f7732847a --- /dev/null +++ b/tests/ui/span/issue-37767.stderr @@ -0,0 +1,78 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/issue-37767.rs:10:7 + | +LL | a.foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `A` + --> $DIR/issue-37767.rs:2:5 + | +LL | fn foo(&mut self) {} + | ^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `B` + --> $DIR/issue-37767.rs:6:5 + | +LL | fn foo(&mut self) {} + | ^^^^^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | A::foo(&a) + | ~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | B::foo(&a) + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/issue-37767.rs:22:7 + | +LL | a.foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `C` + --> $DIR/issue-37767.rs:14:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `D` + --> $DIR/issue-37767.rs:18:5 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | C::foo(&a) + | ~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | D::foo(&a) + | ~~~~~~~~~~ + +error[E0034]: multiple applicable items in scope + --> $DIR/issue-37767.rs:34:7 + | +LL | a.foo() + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in the trait `E` + --> $DIR/issue-37767.rs:26:5 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +note: candidate #2 is defined in the trait `F` + --> $DIR/issue-37767.rs:30:5 + | +LL | fn foo(self) {} + | ^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | E::foo(a) + | ~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | F::foo(a) + | ~~~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/span/issue-39018.rs b/tests/ui/span/issue-39018.rs new file mode 100644 index 000000000..b6db4008d --- /dev/null +++ b/tests/ui/span/issue-39018.rs @@ -0,0 +1,38 @@ +pub fn main() { + let x = "Hello " + "World!"; + //~^ ERROR cannot add + + // Make sure that the span outputs a warning + // for not having an implementation for std::ops::Add + // that won't output for the above string concatenation + let y = World::Hello + World::Goodbye; + //~^ ERROR cannot add + + let x = "Hello " + "World!".to_owned(); + //~^ ERROR cannot add +} + +enum World { + Hello, + Goodbye, +} + +fn foo() { + let a = String::new(); + let b = String::new(); + let c = ""; + let d = ""; + let e = &a; + let _ = &a + &b; //~ ERROR cannot add + let _ = &a + b; //~ ERROR cannot add + let _ = a + &b; // ok + let _ = a + b; //~ ERROR mismatched types + let _ = e + b; //~ ERROR cannot add + let _ = e + &b; //~ ERROR cannot add + let _ = e + d; //~ ERROR cannot add + let _ = e + &d; //~ ERROR cannot add + let _ = &c + &d; //~ ERROR cannot add + let _ = &c + d; //~ ERROR cannot add + let _ = c + &d; //~ ERROR cannot add + let _ = c + d; //~ ERROR cannot add +} diff --git a/tests/ui/span/issue-39018.stderr b/tests/ui/span/issue-39018.stderr new file mode 100644 index 000000000..5d4d692b2 --- /dev/null +++ b/tests/ui/span/issue-39018.stderr @@ -0,0 +1,194 @@ +error[E0369]: cannot add `&str` to `&str` + --> $DIR/issue-39018.rs:2:22 + | +LL | let x = "Hello " + "World!"; + | -------- ^ -------- &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let x = "Hello ".to_owned() + "World!"; + | +++++++++++ + +error[E0369]: cannot add `World` to `World` + --> $DIR/issue-39018.rs:8:26 + | +LL | let y = World::Hello + World::Goodbye; + | ------------ ^ -------------- World + | | + | World + | +note: an implementation of `Add<_>` might be missing for `World` + --> $DIR/issue-39018.rs:15:1 + | +LL | enum World { + | ^^^^^^^^^^ must implement `Add<_>` +note: the trait `Add` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0369]: cannot add `String` to `&str` + --> $DIR/issue-39018.rs:11:22 + | +LL | let x = "Hello " + "World!".to_owned(); + | -------- ^ ------------------- String + | | | + | | `+` cannot be used to concatenate a `&str` with a `String` + | &str + | +help: create an owned `String` on the left and add a borrow on the right + | +LL | let x = "Hello ".to_owned() + &"World!".to_owned(); + | +++++++++++ + + +error[E0369]: cannot add `&String` to `&String` + --> $DIR/issue-39018.rs:26:16 + | +LL | let _ = &a + &b; + | -- ^ -- &String + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: remove the borrow to obtain an owned `String` + | +LL - let _ = &a + &b; +LL + let _ = a + &b; + | + +error[E0369]: cannot add `String` to `&String` + --> $DIR/issue-39018.rs:27:16 + | +LL | let _ = &a + b; + | -- ^ - String + | | | + | | `+` cannot be used to concatenate a `&str` with a `String` + | &String + | +help: remove the borrow on the left and add one on the right + | +LL - let _ = &a + b; +LL + let _ = a + &b; + | + +error[E0308]: mismatched types + --> $DIR/issue-39018.rs:29:17 + | +LL | let _ = a + b; + | ^ + | | + | expected `&str`, found struct `String` + | help: consider borrowing here: `&b` + +error[E0369]: cannot add `String` to `&String` + --> $DIR/issue-39018.rs:30:15 + | +LL | let _ = e + b; + | - ^ - String + | | | + | | `+` cannot be used to concatenate a `&str` with a `String` + | &String + | +help: create an owned `String` on the left and add a borrow on the right + | +LL | let _ = e.to_owned() + &b; + | +++++++++++ + + +error[E0369]: cannot add `&String` to `&String` + --> $DIR/issue-39018.rs:31:15 + | +LL | let _ = e + &b; + | - ^ -- &String + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + &b; + | +++++++++++ + +error[E0369]: cannot add `&str` to `&String` + --> $DIR/issue-39018.rs:32:15 + | +LL | let _ = e + d; + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + d; + | +++++++++++ + +error[E0369]: cannot add `&&str` to `&String` + --> $DIR/issue-39018.rs:33:15 + | +LL | let _ = e + &d; + | - ^ -- &&str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = e.to_owned() + &d; + | +++++++++++ + +error[E0369]: cannot add `&&str` to `&&str` + --> $DIR/issue-39018.rs:34:16 + | +LL | let _ = &c + &d; + | -- ^ -- &&str + | | + | &&str + +error[E0369]: cannot add `&str` to `&&str` + --> $DIR/issue-39018.rs:35:16 + | +LL | let _ = &c + d; + | -- ^ - &str + | | + | &&str + +error[E0369]: cannot add `&&str` to `&str` + --> $DIR/issue-39018.rs:36:15 + | +LL | let _ = c + &d; + | - ^ -- &&str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = c.to_owned() + &d; + | +++++++++++ + +error[E0369]: cannot add `&str` to `&str` + --> $DIR/issue-39018.rs:37:15 + | +LL | let _ = c + d; + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &str + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let _ = c.to_owned() + d; + | +++++++++++ + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/span/issue-39698.rs b/tests/ui/span/issue-39698.rs new file mode 100644 index 000000000..1079bae2c --- /dev/null +++ b/tests/ui/span/issue-39698.rs @@ -0,0 +1,16 @@ +enum T { + T1(i32, i32), + T2(i32, i32), + T3(i32), + T4(i32), +} + +fn main() { + match T::T1(123, 456) { + T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + //~^ ERROR is not bound in all patterns + //~| ERROR is not bound in all patterns + //~| ERROR is not bound in all patterns + //~| ERROR is not bound in all patterns + } +} diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr new file mode 100644 index 000000000..25c35fd54 --- /dev/null +++ b/tests/ui/span/issue-39698.stderr @@ -0,0 +1,43 @@ +error[E0408]: variable `d` is not bound in all patterns + --> $DIR/issue-39698.rs:10:37 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `d` + | | | | + | | | pattern doesn't bind `d` + | | variable not in all patterns + | variable not in all patterns + +error[E0408]: variable `a` is not bound in all patterns + --> $DIR/issue-39698.rs:10:23 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - ^^^^^^^^^^^ ^^^^^^^^ - variable not in all patterns + | | | | + | | | pattern doesn't bind `a` + | | pattern doesn't bind `a` + | variable not in all patterns + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/issue-39698.rs:10:9 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | ^^^^^^^^^^^ - ^^^^^^^^ ^^^^^^^^ pattern doesn't bind `b` + | | | | + | | | pattern doesn't bind `b` + | | variable not in all patterns + | pattern doesn't bind `b` + +error[E0408]: variable `c` is not bound in all patterns + --> $DIR/issue-39698.rs:10:9 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | ^^^^^^^^^^^ ^^^^^^^^^^^ - ^^^^^^^^ pattern doesn't bind `c` + | | | | + | | | variable not in all patterns + | | pattern doesn't bind `c` + | pattern doesn't bind `c` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0408`. diff --git a/tests/ui/span/issue-40157.rs b/tests/ui/span/issue-40157.rs new file mode 100644 index 000000000..03ad21ae7 --- /dev/null +++ b/tests/ui/span/issue-40157.rs @@ -0,0 +1,4 @@ +fn main () { + {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });} + //~^ ERROR does not live long enough +} diff --git a/tests/ui/span/issue-40157.stderr b/tests/ui/span/issue-40157.stderr new file mode 100644 index 000000000..57f80214a --- /dev/null +++ b/tests/ui/span/issue-40157.stderr @@ -0,0 +1,13 @@ +error[E0597]: `foo` does not live long enough + --> $DIR/issue-40157.rs:2:53 + | +LL | {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });} + | ------------------------^^^^^^^^^^-- + | | | | + | | | `foo` dropped here while still borrowed + | | borrowed value does not live long enough + | borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr new file mode 100644 index 000000000..2b1789908 --- /dev/null +++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -0,0 +1,27 @@ +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 + | +LL | let x: Option<_> = None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | x.unwrap().method_that_could_exist_on_some_type(); + | ---------- type must be known at this point + | +help: consider specifying the generic argument + | +LL | let x: Option<_> = None::; + | +++++ + +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 + | +LL | .sum::<_>() + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | .sum::<_>() + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr new file mode 100644 index 000000000..d93d54e87 --- /dev/null +++ b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -0,0 +1,27 @@ +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 + | +LL | let x: Option<_> = None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | x.unwrap().method_that_could_exist_on_some_type(); + | ---------- type must be known at this point + | +help: consider specifying the generic argument + | +LL | let x: Option<_> = None::; + | +++++ + +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 + | +LL | .sum::<_>() + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | .sum::() + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.rs b/tests/ui/span/issue-42234-unknown-receiver-type.rs new file mode 100644 index 000000000..fd5312120 --- /dev/null +++ b/tests/ui/span/issue-42234-unknown-receiver-type.rs @@ -0,0 +1,19 @@ +// revisions: full generic_arg +#![cfg_attr(generic_arg, feature(generic_arg_infer))] + +// When the type of a method call's receiver is unknown, the span should point +// to the receiver (and not the entire call, as was previously the case before +// the fix of which this tests). + +fn shines_a_beacon_through_the_darkness() { + let x: Option<_> = None; //~ ERROR type annotations needed + x.unwrap().method_that_could_exist_on_some_type(); +} + +fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { + data.iter() + .sum::<_>() //~ ERROR type annotations needed + .to_string() +} + +fn main() {} diff --git a/tests/ui/span/issue-43927-non-ADT-derive.rs b/tests/ui/span/issue-43927-non-ADT-derive.rs new file mode 100644 index 000000000..935bfa001 --- /dev/null +++ b/tests/ui/span/issue-43927-non-ADT-derive.rs @@ -0,0 +1,6 @@ +#![derive(Debug, PartialEq, Eq)] // should be an outer attribute! +//~^ ERROR cannot determine resolution for the attribute macro `derive` +//~^^ ERROR `derive` attribute cannot be used at crate level +struct DerivedOn; + +fn main() {} diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr new file mode 100644 index 000000000..e3ae37e36 --- /dev/null +++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr @@ -0,0 +1,21 @@ +error: cannot determine resolution for the attribute macro `derive` + --> $DIR/issue-43927-non-ADT-derive.rs:1:4 + | +LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ^^^^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: `derive` attribute cannot be used at crate level + --> $DIR/issue-43927-non-ADT-derive.rs:1:1 + | +LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: perhaps you meant to use an outer attribute + | +LL | #[derive(Debug, PartialEq, Eq)] // should be an outer attribute! + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/span/issue-71363.rs b/tests/ui/span/issue-71363.rs new file mode 100644 index 000000000..8014f3796 --- /dev/null +++ b/tests/ui/span/issue-71363.rs @@ -0,0 +1,19 @@ +// compile-flags: -Z ui-testing=no + +struct MyError; +impl std::error::Error for MyError {} +//~^ ERROR: `MyError` doesn't implement `std::fmt::Display` +//~| ERROR: `MyError` doesn't implement `Debug` + +fn main() {} + +// This test relies on library/std/src/error.rs *not* being included in the error message, so that +// we can test whether a file not included in the error message affects it (more specifically +// whether the line number of the excluded file affects the indentation of the other line numbers). +// +// To test this we're simulating a remap of the rust src base (so that library/std/src/error.rs +// does not point to a local file) *and* we're disabling the code to try mapping a remapped path to +// a local file (which would defeat the purpose of the former flag). +// +// Note that this comment is at the bottom of the file intentionally, as we need the line number of +// the impl to be lower than 10. diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr new file mode 100644 index 000000000..cb5cc3202 --- /dev/null +++ b/tests/ui/span/issue-71363.stderr @@ -0,0 +1,29 @@ +error[E0277]: `MyError` doesn't implement `std::fmt::Display` + --> $DIR/issue-71363.rs:4:28 + | +4 | impl std::error::Error for MyError {} + | ^^^^^^^ `MyError` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `MyError` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `std::error::Error` + --> $SRC_DIR/core/src/error.rs:LL:COL + +error[E0277]: `MyError` doesn't implement `Debug` + --> $DIR/issue-71363.rs:4:28 + | +4 | impl std::error::Error for MyError {} + | ^^^^^^^ `MyError` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `MyError` + = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError` +note: required by a bound in `std::error::Error` + --> $SRC_DIR/core/src/error.rs:LL:COL +help: consider annotating `MyError` with `#[derive(Debug)]` + | +3 | #[derive(Debug)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/issue-81800.rs b/tests/ui/span/issue-81800.rs new file mode 100644 index 000000000..6ac66fdcb --- /dev/null +++ b/tests/ui/span/issue-81800.rs @@ -0,0 +1,2 @@ +fn xË‚- //~ ERROR: unknown start of token + //~^ ERROR: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-` diff --git a/tests/ui/span/issue-81800.stderr b/tests/ui/span/issue-81800.stderr new file mode 100644 index 000000000..86c64573b --- /dev/null +++ b/tests/ui/span/issue-81800.stderr @@ -0,0 +1,19 @@ +error: unknown start of token: \u{2c2} + --> $DIR/issue-81800.rs:1:5 + | +LL | fn xË‚- + | ^ + | +help: Unicode character 'Ë‚' (Modifier Letter Left Arrowhead) looks like '<' (Less-Than Sign), but it is not + | +LL | fn x<- + | ~ + +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-` + --> $DIR/issue-81800.rs:1:6 + | +LL | fn xË‚- + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + +error: aborting due to 2 previous errors + diff --git a/tests/ui/span/issue28498-reject-ex1.rs b/tests/ui/span/issue28498-reject-ex1.rs new file mode 100644 index 000000000..4d1b41255 --- /dev/null +++ b/tests/ui/span/issue28498-reject-ex1.rs @@ -0,0 +1,37 @@ +// Example taken from RFC 1238 text + +// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +// #examples-of-code-that-will-start-to-be-rejected + +// Compare against test/run-pass/issue28498-must-work-ex2.rs + +use std::cell::Cell; + +struct Concrete<'a>(u32, Cell>>); + +struct Foo { data: Vec } + +fn potentially_specialized_wrt_t(t: &T) { + // Hypothetical code that does one thing for generic T and then is + // specialized for T == Concrete (and the specialized form can + // then access a reference held in concrete tuple). + // + // (We don't have specialization yet, but we want to allow for it + // in the future.) +} + +impl Drop for Foo { + fn drop(&mut self) { + potentially_specialized_wrt_t(&self.data[0]) + } +} + +fn main() { + let mut foo = Foo { data: Vec::new() }; + foo.data.push(Concrete(0, Cell::new(None))); + foo.data.push(Concrete(0, Cell::new(None))); + + foo.data[0].1.set(Some(&foo.data[1])); + //~^ ERROR borrow may still be in use when destructor runs + foo.data[1].1.set(Some(&foo.data[0])); +} diff --git a/tests/ui/span/issue28498-reject-ex1.stderr b/tests/ui/span/issue28498-reject-ex1.stderr new file mode 100644 index 000000000..86e2d8c56 --- /dev/null +++ b/tests/ui/span/issue28498-reject-ex1.stderr @@ -0,0 +1,17 @@ +error[E0713]: borrow may still be in use when destructor runs + --> $DIR/issue28498-reject-ex1.rs:34:29 + | +LL | foo.data[0].1.set(Some(&foo.data[1])); + | ^^^^^^^^ +... +LL | } + | - + | | + | here, drop of `foo` needs exclusive access to `foo.data`, because the type `Foo>` implements the `Drop` trait + | borrow might be used here, when `foo` is dropped and runs the `Drop` code for type `Foo` + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/span/issue28498-reject-lifetime-param.rs b/tests/ui/span/issue28498-reject-lifetime-param.rs new file mode 100644 index 000000000..1e7190157 --- /dev/null +++ b/tests/ui/span/issue28498-reject-lifetime-param.rs @@ -0,0 +1,36 @@ +// Demonstrate that having a lifetime param causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo<'a>(u32, &'a ScribbleOnDrop); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + // Use of `may_dangle` is unsound, because destructor accesses borrowed data + // in `self.1` and we must force that to strictly outlive `self`. + println!("Dropping Foo({}, {:?})", self.0, self.1); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); // OK + foo1 = Foo(1, &first_dropped); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/span/issue28498-reject-lifetime-param.stderr b/tests/ui/span/issue28498-reject-lifetime-param.stderr new file mode 100644 index 000000000..3119ddd03 --- /dev/null +++ b/tests/ui/span/issue28498-reject-lifetime-param.stderr @@ -0,0 +1,17 @@ +error[E0597]: `first_dropped` does not live long enough + --> $DIR/issue28498-reject-lifetime-param.rs:32:19 + | +LL | foo1 = Foo(1, &first_dropped); + | ^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `first_dropped` dropped here while still borrowed + | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-passed-to-fn.rs b/tests/ui/span/issue28498-reject-passed-to-fn.rs new file mode 100644 index 000000000..dcd2e9ad4 --- /dev/null +++ b/tests/ui/span/issue28498-reject-passed-to-fn.rs @@ -0,0 +1,38 @@ +// Demonstrate that a type param in negative position causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo(u32, T, Box fn(&'r T) -> String>); + +impl Drop for Foo { + fn drop(&mut self) { + // Use of `may_dangle` is unsound, because we pass `T` to the callback in `self.2` + // below, and thus potentially read from borrowed data. + println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1)); + } +} + +fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) } + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped, Box::new(callback)); // OK + foo1 = Foo(1, &first_dropped, Box::new(callback)); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/span/issue28498-reject-passed-to-fn.stderr b/tests/ui/span/issue28498-reject-passed-to-fn.stderr new file mode 100644 index 000000000..60e8a648c --- /dev/null +++ b/tests/ui/span/issue28498-reject-passed-to-fn.stderr @@ -0,0 +1,17 @@ +error[E0597]: `first_dropped` does not live long enough + --> $DIR/issue28498-reject-passed-to-fn.rs:34:19 + | +LL | foo1 = Foo(1, &first_dropped, Box::new(callback)); + | ^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `first_dropped` dropped here while still borrowed + | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/issue28498-reject-trait-bound.rs b/tests/ui/span/issue28498-reject-trait-bound.rs new file mode 100644 index 000000000..444cebb19 --- /dev/null +++ b/tests/ui/span/issue28498-reject-trait-bound.rs @@ -0,0 +1,38 @@ +// Demonstrate that having a trait bound causes dropck to reject code +// that might indirectly access previously dropped value. +// +// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs + +use std::fmt; + +#[derive(Debug)] +struct ScribbleOnDrop(String); + +impl Drop for ScribbleOnDrop { + fn drop(&mut self) { + self.0 = format!("DROPPED"); + } +} + +struct Foo(u32, T); + +impl Drop for Foo { + fn drop(&mut self) { + // Use of `may_dangle` is unsound, because we access `T` fmt method when we pass + // `self.1` below, and thus potentially read from borrowed data. + println!("Dropping Foo({}, {:?})", self.0, self.1); + } +} + +fn main() { + let (last_dropped, foo0); + let (foo1, first_dropped); + + last_dropped = ScribbleOnDrop(format!("last")); + first_dropped = ScribbleOnDrop(format!("first")); + foo0 = Foo(0, &last_dropped); // OK + foo1 = Foo(1, &first_dropped); + //~^ ERROR `first_dropped` does not live long enough + + println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1); +} diff --git a/tests/ui/span/issue28498-reject-trait-bound.stderr b/tests/ui/span/issue28498-reject-trait-bound.stderr new file mode 100644 index 000000000..22e4a8205 --- /dev/null +++ b/tests/ui/span/issue28498-reject-trait-bound.stderr @@ -0,0 +1,17 @@ +error[E0597]: `first_dropped` does not live long enough + --> $DIR/issue28498-reject-trait-bound.rs:34:19 + | +LL | foo1 = Foo(1, &first_dropped); + | ^^^^^^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `first_dropped` dropped here while still borrowed + | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/lint-unused-unsafe-thir.rs b/tests/ui/span/lint-unused-unsafe-thir.rs new file mode 100644 index 000000000..adb72c26b --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe-thir.rs @@ -0,0 +1,61 @@ +// FIXME: This file is tracking old lint behavior that's still unchanged in the +// unstable -Zthir-unsafeck implementation. See lint-unused-unsafe.rs for more details. +// +// Exercise the unused_unsafe attribute in some positive and negative cases + +// compile-flags: -Zthir-unsafeck + +#![allow(dead_code)] +#![deny(unused_unsafe)] + + +mod foo { + extern "C" { + pub fn bar(); + } +} + +fn callback(_f: F) -> T where F: FnOnce() -> T { panic!() } +unsafe fn unsf() {} + +fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } +fn bad6() { + unsafe { // don't put the warning here + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} +unsafe fn bad7() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} + +unsafe fn good0() { unsf() } +fn good1() { unsafe { unsf() } } +fn good2() { + /* bug uncovered when implementing warning about unused unsafe blocks. Be + sure that when purity is inherited that the source of the unsafe-ness + is tracked correctly */ + unsafe { + unsafe fn what() -> Vec { panic!() } + + callback(|| { + what(); + }); + } +} + +unsafe fn good3() { foo::bar() } +fn good4() { unsafe { foo::bar() } } + +#[allow(unused_unsafe)] fn allowed() { unsafe {} } + +fn main() {} diff --git a/tests/ui/span/lint-unused-unsafe-thir.stderr b/tests/ui/span/lint-unused-unsafe-thir.stderr new file mode 100644 index 000000000..3bcbb7597 --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe-thir.stderr @@ -0,0 +1,50 @@ +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:21:13 + | +LL | fn bad1() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe-thir.rs:9:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:22:13 + | +LL | fn bad2() { unsafe { bad1() } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:23:20 + | +LL | unsafe fn bad3() { unsafe {} } + | ---------------- ^^^^^^ unnecessary `unsafe` block + | | + | because it's nested under this `unsafe` fn + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:24:13 + | +LL | fn bad4() { unsafe { callback(||{}) } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:28:9 + | +LL | unsafe { // don't put the warning here + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe-thir.rs:35:9 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 6 previous errors + diff --git a/tests/ui/span/lint-unused-unsafe.mir.stderr b/tests/ui/span/lint-unused-unsafe.mir.stderr new file mode 100644 index 000000000..d8412908c --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe.mir.stderr @@ -0,0 +1,1402 @@ +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:26:13 + | +LL | fn bad1() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:14:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:27:13 + | +LL | fn bad2() { unsafe { bad1() } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:28:20 + | +LL | unsafe fn bad3() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:29:13 + | +LL | fn bad4() { unsafe { callback(||{}) } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:32:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:39:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:74:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:83:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:84:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:85:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:90:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:100:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:101:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:102:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:112:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:110:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:113:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:114:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:124:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:134:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:135:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:136:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:142:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:153:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:154:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:155:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:166:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:164:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:167:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:168:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:178:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:188:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:189:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:190:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:196:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:207:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:208:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:209:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:220:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:218:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:221:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:222:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:242:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:255:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:268:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:286:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:295:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:296:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:297:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:302:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:312:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:313:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:314:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:324:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:322:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:325:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:326:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:336:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:346:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:347:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:348:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:354:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:365:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:366:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:367:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:378:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:376:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:379:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:380:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:390:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:400:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:401:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:402:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:408:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:419:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:420:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:421:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:432:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:430:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:433:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:434:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:454:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:467:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:480:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:499:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:508:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:509:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:510:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:515:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:525:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:526:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:527:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:537:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:535:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:538:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:539:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:549:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:559:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:560:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:561:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:567:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:578:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:579:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:580:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:591:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:589:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:592:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:593:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:603:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:613:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:614:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:615:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:621:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:632:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:633:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:634:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:645:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:643:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:646:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:647:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:667:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:680:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:693:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:711:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:721:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:722:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:723:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:729:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:740:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:741:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:742:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:753:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:751:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:754:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:755:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:765:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:775:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:776:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:777:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:783:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:794:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:795:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:796:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:807:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:805:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:808:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:809:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:829:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:842:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:855:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:869:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:879:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:880:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:881:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:887:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:898:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:899:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:900:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:911:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:909:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:912:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:913:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:923:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:933:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:934:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:935:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:941:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:952:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:953:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:954:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:965:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:963:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:966:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:967:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:987:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1000:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1013:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1059:29 + | +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1066:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = async { unsf() }; +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1067:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1068:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1073:29 + | +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1080:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = async { unsf() }; +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1081:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1082:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1092:22 + | +LL | let _x: [(); unsafe { 0 }] = []; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1096:22 + | +LL | let _x: [(); unsafe { unsafe { size() } }] = []; + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 174 previous errors + diff --git a/tests/ui/span/lint-unused-unsafe.rs b/tests/ui/span/lint-unused-unsafe.rs new file mode 100644 index 000000000..5d042768b --- /dev/null +++ b/tests/ui/span/lint-unused-unsafe.rs @@ -0,0 +1,1100 @@ +// Exercise the unused_unsafe attribute in some positive and negative cases + + +// edition:2018 + +// revisions: mir + +// FIXME: Adapt -Zthir-unsafeck to behave the same as the mir version after #93678, +// then delete lint-unused-unsafe-thir.rs, and go back to using the settings below +// // revisions: mir thir +// // [thir]compile-flags: -Zthir-unsafeck + +#![allow(dead_code)] +#![deny(unused_unsafe)] + + +mod foo { + extern "C" { + pub fn bar(); + } +} + +fn callback(_f: F) -> T where F: FnOnce() -> T { panic!() } +unsafe fn unsf() {} + +fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } +fn bad6() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { // don't put the warning here + unsf() + } + } +} +unsafe fn bad7() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { + unsf() + } + } +} + +unsafe fn good0() { unsf() } +fn good1() { unsafe { unsf() } } +fn good2() { + /* bug uncovered when implementing warning about unused unsafe blocks. Be + sure that when purity is inherited that the source of the unsafe-ness + is tracked correctly */ + unsafe { + unsafe fn what() -> Vec { panic!() } + + callback(|| { + what(); + }); + } +} + +unsafe fn good3() { foo::bar() } +fn good4() { unsafe { foo::bar() } } + +#[allow(unused_unsafe)] fn allowed() { unsafe {} } + +fn main() {} + +mod additional_tests { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + fn multi_level_unused() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + fn granularity() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + fn top_level_used() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + unsf(); + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + } + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } +} + +// the same set of tests, with closures everywhere +mod additional_tests_closures { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + fn multi_level_unused() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + fn granularity() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + fn top_level_used() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } +} + +// the same set of tests, with closures everywhere +// and closures on the unsafe fn calls +mod additional_tests_even_more_closures { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + fn multi_level_unused() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + fn granularity() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + fn top_level_used() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + let _ = || unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + } +} + +mod item_likes { + unsafe fn unsf() {} + + struct S; + impl S { + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + } + + trait T { + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + } +} + +mod additional_tests_extra { + unsafe fn unsf() {} + + // multiple uses with different `unsafe_op_in_unsafe_fn` in the same closure + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + let _ = || { + unsf(); + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[warn(unsafe_op_in_unsafe_fn)] + unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() { + unsafe { + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + + async unsafe fn async_blocks() { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + }}; + let _ = async { unsafe { + let _ = async { unsf() }; + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + } + #[allow(unsafe_op_in_unsafe_fn)] + { + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + }}; + let _ = async { unsafe { + let _ = async { unsf() }; + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + } + } + + fn used_unsafe_in_const() { + let _x: [(); unsafe { size() }] = []; + } + + fn unused_unsafe_in_const_1() { + let _x: [(); unsafe { 0 }] = []; //~ ERROR: unnecessary `unsafe` block + } + + fn unused_unsafe_in_const_2() { + let _x: [(); unsafe { unsafe { size() } }] = []; //~ ERROR: unnecessary `unsafe` block + } + + const unsafe fn size() -> usize { 0 } +} diff --git a/tests/ui/span/macro-span-replacement.rs b/tests/ui/span/macro-span-replacement.rs new file mode 100644 index 000000000..66973c58d --- /dev/null +++ b/tests/ui/span/macro-span-replacement.rs @@ -0,0 +1,13 @@ +// check-pass + +#![warn(unused)] + +macro_rules! m { + ($a:tt $b:tt) => { + $b $a; //~ WARN struct `S` is never constructed + } +} + +fn main() { + m!(S struct); +} diff --git a/tests/ui/span/macro-span-replacement.stderr b/tests/ui/span/macro-span-replacement.stderr new file mode 100644 index 000000000..5dd563428 --- /dev/null +++ b/tests/ui/span/macro-span-replacement.stderr @@ -0,0 +1,19 @@ +warning: struct `S` is never constructed + --> $DIR/macro-span-replacement.rs:7:12 + | +LL | $b $a; + | ^^ +... +LL | m!(S struct); + | ------------ in this macro invocation + | +note: the lint level is defined here + --> $DIR/macro-span-replacement.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` + = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/span/macro-ty-params.rs b/tests/ui/span/macro-ty-params.rs new file mode 100644 index 000000000..cf28b0255 --- /dev/null +++ b/tests/ui/span/macro-ty-params.rs @@ -0,0 +1,15 @@ +macro_rules! m { + ($p1: path) => { + #[derive($p1)] struct U; + } +} + +macro_rules! foo { () => () } + +fn main() { + foo::!(); //~ ERROR generic arguments in macro path + foo::<>!(); //~ ERROR generic arguments in macro path + m!(Default<>); + //~^ ERROR unexpected generic arguments in path + //~^^ ERROR generic arguments in macro path +} diff --git a/tests/ui/span/macro-ty-params.stderr b/tests/ui/span/macro-ty-params.stderr new file mode 100644 index 000000000..7023ef8cd --- /dev/null +++ b/tests/ui/span/macro-ty-params.stderr @@ -0,0 +1,26 @@ +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:10:10 + | +LL | foo::!(); + | ^^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:11:10 + | +LL | foo::<>!(); + | ^^ + +error: unexpected generic arguments in path + --> $DIR/macro-ty-params.rs:12:15 + | +LL | m!(Default<>); + | ^^ + +error: generic arguments in macro path + --> $DIR/macro-ty-params.rs:12:15 + | +LL | m!(Default<>); + | ^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/span/method-and-field-eager-resolution.rs b/tests/ui/span/method-and-field-eager-resolution.rs new file mode 100644 index 000000000..a0f0d8810 --- /dev/null +++ b/tests/ui/span/method-and-field-eager-resolution.rs @@ -0,0 +1,15 @@ +// Test that spans get only base in eager type resolution (structurally_resolve_type). + +fn main() { + let mut x = Default::default(); + //~^ ERROR type annotations needed + x.0; + x = 1; +} + +fn foo() { + let mut x = Default::default(); + //~^ ERROR type annotations needed + x[0]; + x = 1; +} diff --git a/tests/ui/span/method-and-field-eager-resolution.stderr b/tests/ui/span/method-and-field-eager-resolution.stderr new file mode 100644 index 000000000..f6efbe40b --- /dev/null +++ b/tests/ui/span/method-and-field-eager-resolution.stderr @@ -0,0 +1,31 @@ +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:4:9 + | +LL | let mut x = Default::default(); + | ^^^^^ +LL | +LL | x.0; + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let mut x: /* Type */ = Default::default(); + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:11:9 + | +LL | let mut x = Default::default(); + | ^^^^^ +LL | +LL | x[0]; + | - type must be known at this point + | +help: consider giving `x` an explicit type + | +LL | let mut x: /* Type */ = Default::default(); + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/missing-unit-argument.rs b/tests/ui/span/missing-unit-argument.rs new file mode 100644 index 000000000..db96ae223 --- /dev/null +++ b/tests/ui/span/missing-unit-argument.rs @@ -0,0 +1,17 @@ +fn foo(():(), ():()) {} +fn bar(():()) {} + +struct S; +impl S { + fn baz(self, (): ()) { } + fn generic(self, _: T) { } +} + +fn main() { + let _: Result<(), String> = Ok(); //~ ERROR this enum variant takes + foo(); //~ ERROR function takes + foo(()); //~ ERROR function takes + bar(); //~ ERROR function takes + S.baz(); //~ ERROR this method takes + S.generic::<()>(); //~ ERROR this method takes +} diff --git a/tests/ui/span/missing-unit-argument.stderr b/tests/ui/span/missing-unit-argument.stderr new file mode 100644 index 000000000..ef4d732b5 --- /dev/null +++ b/tests/ui/span/missing-unit-argument.stderr @@ -0,0 +1,96 @@ +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:11:33 + | +LL | let _: Result<(), String> = Ok(); + | ^^-- an argument of type `()` is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL +help: provide the argument + | +LL | let _: Result<(), String> = Ok(()); + | ~~~~ + +error[E0061]: this function takes 2 arguments but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:12:5 + | +LL | foo(); + | ^^^-- two arguments of type `()` and `()` are missing + | +note: function defined here + --> $DIR/missing-unit-argument.rs:1:4 + | +LL | fn foo(():(), ():()) {} + | ^^^ ----- ----- +help: provide the arguments + | +LL | foo((), ()); + | ~~~~~~~~ + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/missing-unit-argument.rs:13:5 + | +LL | foo(()); + | ^^^---- an argument of type `()` is missing + | +note: function defined here + --> $DIR/missing-unit-argument.rs:1:4 + | +LL | fn foo(():(), ():()) {} + | ^^^ ----- ----- +help: provide the argument + | +LL | foo((), ()); + | ~~~~~~~~ + +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:14:5 + | +LL | bar(); + | ^^^-- an argument of type `()` is missing + | +note: function defined here + --> $DIR/missing-unit-argument.rs:2:4 + | +LL | fn bar(():()) {} + | ^^^ ----- +help: provide the argument + | +LL | bar(()); + | ~~~~ + +error[E0061]: this method takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:15:7 + | +LL | S.baz(); + | ^^^-- an argument of type `()` is missing + | +note: associated function defined here + --> $DIR/missing-unit-argument.rs:6:8 + | +LL | fn baz(self, (): ()) { } + | ^^^ ------ +help: provide the argument + | +LL | S.baz(()); + | ~~~~ + +error[E0061]: this method takes 1 argument but 0 arguments were supplied + --> $DIR/missing-unit-argument.rs:16:7 + | +LL | S.generic::<()>(); + | ^^^^^^^^^^^^^-- an argument of type `()` is missing + | +note: associated function defined here + --> $DIR/missing-unit-argument.rs:7:8 + | +LL | fn generic(self, _: T) { } + | ^^^^^^^ ---- +help: provide the argument + | +LL | S.generic::<()>(()); + | ~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/span/move-closure.rs b/tests/ui/span/move-closure.rs new file mode 100644 index 000000000..bdd7951b3 --- /dev/null +++ b/tests/ui/span/move-closure.rs @@ -0,0 +1,6 @@ +// Regression test for issue #24986 +// Make sure that the span of a closure marked `move` begins at the `move` keyword. + +fn main() { + let x: () = move || (); //~ ERROR mismatched types +} diff --git a/tests/ui/span/move-closure.stderr b/tests/ui/span/move-closure.stderr new file mode 100644 index 000000000..dcc607896 --- /dev/null +++ b/tests/ui/span/move-closure.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/move-closure.rs:5:17 + | +LL | let x: () = move || (); + | -- ^^^^^^^^^^ expected `()`, found closure + | | + | expected due to this + | + = note: expected unit type `()` + found closure `[closure@$DIR/move-closure.rs:5:17: 5:24]` +help: use parentheses to call this closure + | +LL | let x: () = (move || ())(); + | + +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/span/multiline-span-E0072.rs b/tests/ui/span/multiline-span-E0072.rs new file mode 100644 index 000000000..728b47d65 --- /dev/null +++ b/tests/ui/span/multiline-span-E0072.rs @@ -0,0 +1,10 @@ +// It should just use the entire body instead of pointing at the next two lines +struct //~ ERROR has infinite size +ListNode +{ + head: u8, + tail: Option, +} + +fn main() { +} diff --git a/tests/ui/span/multiline-span-E0072.stderr b/tests/ui/span/multiline-span-E0072.stderr new file mode 100644 index 000000000..fc2f6e662 --- /dev/null +++ b/tests/ui/span/multiline-span-E0072.stderr @@ -0,0 +1,18 @@ +error[E0072]: recursive type `ListNode` has infinite size + --> $DIR/multiline-span-E0072.rs:2:1 + | +LL | / struct +LL | | ListNode + | |________^ +... +LL | tail: Option, + | -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | tail: Option>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/multiline-span-simple.rs b/tests/ui/span/multiline-span-simple.rs new file mode 100644 index 000000000..204a7f6b1 --- /dev/null +++ b/tests/ui/span/multiline-span-simple.rs @@ -0,0 +1,20 @@ +fn foo(a: u32, b: u32) { + a + b; +} + +fn bar(a: u32, b: u32) { + a + b; +} + +fn main() { + let x = 1; + let y = 2; + let z = 3; + foo(1 as u32 + //~ ERROR cannot add `()` to `u32` + + bar(x, + + y), + + z) +} diff --git a/tests/ui/span/multiline-span-simple.stderr b/tests/ui/span/multiline-span-simple.stderr new file mode 100644 index 000000000..b44df962a --- /dev/null +++ b/tests/ui/span/multiline-span-simple.stderr @@ -0,0 +1,16 @@ +error[E0277]: cannot add `()` to `u32` + --> $DIR/multiline-span-simple.rs:13:18 + | +LL | foo(1 as u32 + + | ^ no implementation for `u32 + ()` + | + = help: the trait `Add<()>` is not implemented for `u32` + = help: the following other types implement trait `Add`: + <&'a u32 as Add> + <&u32 as Add<&u32>> + > + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/span/multispan-import-lint.rs b/tests/ui/span/multispan-import-lint.rs new file mode 100644 index 000000000..3ce7f2ce3 --- /dev/null +++ b/tests/ui/span/multispan-import-lint.rs @@ -0,0 +1,10 @@ +// check-pass + +#![warn(unused)] + +use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; +//~^ WARN unused imports + +fn main() { + let _ = min(1, 2); +} diff --git a/tests/ui/span/multispan-import-lint.stderr b/tests/ui/span/multispan-import-lint.stderr new file mode 100644 index 000000000..4a955d1b3 --- /dev/null +++ b/tests/ui/span/multispan-import-lint.stderr @@ -0,0 +1,15 @@ +warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` + --> $DIR/multispan-import-lint.rs:5:16 + | +LL | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; + | ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/multispan-import-lint.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_imports)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/tests/ui/span/mut-arg-hint.rs b/tests/ui/span/mut-arg-hint.rs new file mode 100644 index 000000000..d7ff1f0de --- /dev/null +++ b/tests/ui/span/mut-arg-hint.rs @@ -0,0 +1,22 @@ +trait B { + fn foo(mut a: &String) { + a.push_str("bar"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference + } +} + +pub fn foo<'a>(mut a: &'a String) { + a.push_str("foo"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference +} + +struct A {} + +impl A { + pub fn foo(mut a: &String) { + a.push_str("foo"); //~ ERROR cannot borrow `*a` as mutable, as it is behind a `&` reference + } +} + +fn main() { + foo(&"a".to_string()); + A::foo(&"a".to_string()); +} diff --git a/tests/ui/span/mut-arg-hint.stderr b/tests/ui/span/mut-arg-hint.stderr new file mode 100644 index 000000000..96ce4d5bc --- /dev/null +++ b/tests/ui/span/mut-arg-hint.stderr @@ -0,0 +1,36 @@ +error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference + --> $DIR/mut-arg-hint.rs:3:9 + | +LL | a.push_str("bar"); + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ + +error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference + --> $DIR/mut-arg-hint.rs:8:5 + | +LL | a.push_str("foo"); + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo<'a>(mut a: &'a mut String) { + | ~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference + --> $DIR/mut-arg-hint.rs:15:9 + | +LL | a.push_str("foo"); + | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.rs b/tests/ui/span/mut-ptr-cant-outlive-ref.rs new file mode 100644 index 000000000..b8c752d73 --- /dev/null +++ b/tests/ui/span/mut-ptr-cant-outlive-ref.rs @@ -0,0 +1,15 @@ +use std::cell::RefCell; + +fn main() { + let m = RefCell::new(0); + let p; + { + let b = m.borrow(); + p = &*b; + } + //~^^ ERROR `b` does not live long enough + p.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.stderr b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr new file mode 100644 index 000000000..4d976a7bb --- /dev/null +++ b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr @@ -0,0 +1,14 @@ +error[E0597]: `b` does not live long enough + --> $DIR/mut-ptr-cant-outlive-ref.rs:8:15 + | +LL | p = &*b; + | ^ borrowed value does not live long enough +LL | } + | - `b` dropped here while still borrowed +LL | +LL | p.use_ref(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/non-existing-module-import.rs b/tests/ui/span/non-existing-module-import.rs new file mode 100644 index 000000000..d2ce7ec4f --- /dev/null +++ b/tests/ui/span/non-existing-module-import.rs @@ -0,0 +1,3 @@ +use std::bar::{foo1, foo2}; //~ ERROR unresolved import + +fn main() {} diff --git a/tests/ui/span/non-existing-module-import.stderr b/tests/ui/span/non-existing-module-import.stderr new file mode 100644 index 000000000..25c099590 --- /dev/null +++ b/tests/ui/span/non-existing-module-import.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `std::bar` + --> $DIR/non-existing-module-import.rs:1:10 + | +LL | use std::bar::{foo1, foo2}; + | ^^^ could not find `bar` in `std` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/span/pub-struct-field.rs b/tests/ui/span/pub-struct-field.rs new file mode 100644 index 000000000..e149b9dbf --- /dev/null +++ b/tests/ui/span/pub-struct-field.rs @@ -0,0 +1,10 @@ +// Regression test for issue #26083 and #35435 +// Test that span for public struct fields start at `pub` + +struct Foo { + bar: u8, + pub bar: u8, //~ ERROR is already declared + pub(crate) bar: u8, //~ ERROR is already declared +} + +fn main() {} diff --git a/tests/ui/span/pub-struct-field.stderr b/tests/ui/span/pub-struct-field.stderr new file mode 100644 index 000000000..065340f44 --- /dev/null +++ b/tests/ui/span/pub-struct-field.stderr @@ -0,0 +1,20 @@ +error[E0124]: field `bar` is already declared + --> $DIR/pub-struct-field.rs:6:5 + | +LL | bar: u8, + | ------- `bar` first declared here +LL | pub bar: u8, + | ^^^^^^^^^^^ field already declared + +error[E0124]: field `bar` is already declared + --> $DIR/pub-struct-field.rs:7:5 + | +LL | bar: u8, + | ------- `bar` first declared here +LL | pub bar: u8, +LL | pub(crate) bar: u8, + | ^^^^^^^^^^^^^^^^^^ field already declared + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/span/range-2.rs b/tests/ui/span/range-2.rs new file mode 100644 index 000000000..c4bb16f44 --- /dev/null +++ b/tests/ui/span/range-2.rs @@ -0,0 +1,15 @@ +// Test range syntax - borrow errors. +#![feature(rustc_attrs)] +pub fn main() { #![rustc_error] // rust-lang/rust#49855 + let r = { + let a = 42; + let b = 42; + &a..&b + }; + //~^^ ERROR `a` does not live long enough + //~| ERROR `b` does not live long enough + r.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/range-2.stderr b/tests/ui/span/range-2.stderr new file mode 100644 index 000000000..8ca8156b0 --- /dev/null +++ b/tests/ui/span/range-2.stderr @@ -0,0 +1,25 @@ +error[E0597]: `a` does not live long enough + --> $DIR/range-2.rs:7:9 + | +LL | let r = { + | - borrow later stored here +... +LL | &a..&b + | ^^ borrowed value does not live long enough +LL | }; + | - `a` dropped here while still borrowed + +error[E0597]: `b` does not live long enough + --> $DIR/range-2.rs:7:13 + | +LL | let r = { + | - borrow later stored here +... +LL | &a..&b + | ^^ borrowed value does not live long enough +LL | }; + | - `b` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/recursive-type-field.rs b/tests/ui/span/recursive-type-field.rs new file mode 100644 index 000000000..bd4c43534 --- /dev/null +++ b/tests/ui/span/recursive-type-field.rs @@ -0,0 +1,18 @@ +use std::rc::Rc; + +struct Foo<'a> { //~ ERROR recursive types `Foo` and `Bar` have infinite size + bar: Bar<'a>, + b: Rc>, +} + +struct Bar<'a> { + y: (Foo<'a>, Foo<'a>), + z: Option>, + a: &'a Foo<'a>, + c: &'a [Bar<'a>], + d: [Bar<'a>; 1], + e: Foo<'a>, + x: Bar<'a>, +} + +fn main() {} diff --git a/tests/ui/span/recursive-type-field.stderr b/tests/ui/span/recursive-type-field.stderr new file mode 100644 index 000000000..10af4c36b --- /dev/null +++ b/tests/ui/span/recursive-type-field.stderr @@ -0,0 +1,27 @@ +error[E0072]: recursive types `Foo` and `Bar` have infinite size + --> $DIR/recursive-type-field.rs:3:1 + | +LL | struct Foo<'a> { + | ^^^^^^^^^^^^^^ +LL | bar: Bar<'a>, + | ------- recursive without indirection +... +LL | struct Bar<'a> { + | ^^^^^^^^^^^^^^ +LL | y: (Foo<'a>, Foo<'a>), + | ------- ------- recursive without indirection + | | + | recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ bar: Box>, +LL | b: Rc>, + ... +LL | struct Bar<'a> { +LL ~ y: (Box>, Box>), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.rs b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs new file mode 100644 index 000000000..60ccaa872 --- /dev/null +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.rs @@ -0,0 +1,16 @@ +#![feature(rustc_attrs)] +use std::ops::FnMut; + +fn main() { #![rustc_error] // rust-lang/rust#49855 + let mut f; + { + let c = 1; + let c_ref = &c; + //~^ ERROR `c` does not live long enough + f = move |a: isize, b: isize| { a + b + *c_ref }; + } + f.use_mut(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr new file mode 100644 index 000000000..0b985de60 --- /dev/null +++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr @@ -0,0 +1,14 @@ +error[E0597]: `c` does not live long enough + --> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21 + | +LL | let c_ref = &c; + | ^^ borrowed value does not live long enough +... +LL | } + | - `c` dropped here while still borrowed +LL | f.use_mut(); + | ----------- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs new file mode 100644 index 000000000..16b4cc258 --- /dev/null +++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.rs @@ -0,0 +1,16 @@ +fn id(x: T) -> T { x } + +trait Foo { } + +impl<'a> Foo for &'a isize { } + +fn main() { + + let blah; + + { + let ss: &isize = &id(1); + //~^ ERROR temporary value dropped while borrowed + blah = Box::new(ss) as Box; + } +} diff --git a/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr new file mode 100644 index 000000000..81e858fa0 --- /dev/null +++ b/tests/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -0,0 +1,16 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:12:27 + | +LL | let ss: &isize = &id(1); + | ^^^^^ creates a temporary value which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | } + | - borrow might be used here, when `blah` is dropped and runs the destructor for type `Box` + | + = note: consider using a `let` binding to create a longer lived value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/regions-close-over-type-parameter-2.rs b/tests/ui/span/regions-close-over-type-parameter-2.rs new file mode 100644 index 000000000..aca3972cb --- /dev/null +++ b/tests/ui/span/regions-close-over-type-parameter-2.rs @@ -0,0 +1,27 @@ +// Test for what happens when a type parameter `A` is closed over into +// an object. This should yield errors unless `A` (and the object) +// both have suitable bounds. + +trait Foo { fn get(&self); } + +impl Foo for A { + fn get(&self) { + } +} + +fn repeater3<'a,A:'a>(v: A) -> Box { + Box::new(v) as Box +} + +fn main() { + + // Error results because the type of is inferred to be + // ~Repeat<&'blk isize> where blk is the lifetime of the block below. + + let _ = { + let tmp0 = 3; + let tmp1 = &tmp0; + repeater3(tmp1) + }; + //~^^^ ERROR `tmp0` does not live long enough +} diff --git a/tests/ui/span/regions-close-over-type-parameter-2.stderr b/tests/ui/span/regions-close-over-type-parameter-2.stderr new file mode 100644 index 000000000..2e584d9a8 --- /dev/null +++ b/tests/ui/span/regions-close-over-type-parameter-2.stderr @@ -0,0 +1,13 @@ +error[E0597]: `tmp0` does not live long enough + --> $DIR/regions-close-over-type-parameter-2.rs:23:20 + | +LL | let tmp1 = &tmp0; + | ^^^^^ borrowed value does not live long enough +LL | repeater3(tmp1) + | --------------- borrow later captured here by trait object +LL | }; + | - `tmp0` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-escape-loop-via-variable.rs b/tests/ui/span/regions-escape-loop-via-variable.rs new file mode 100644 index 000000000..ad468896b --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-variable.rs @@ -0,0 +1,14 @@ +fn main() { + let x = 3; + + // Here, the variable `p` gets inferred to a type with a lifetime + // of the loop body. The regionck then determines that this type + // is invalid. + let mut p = &x; + + loop { + let x = 1 + *p; + p = &x; + } + //~^^ ERROR `x` does not live long enough +} diff --git a/tests/ui/span/regions-escape-loop-via-variable.stderr b/tests/ui/span/regions-escape-loop-via-variable.stderr new file mode 100644 index 000000000..42df66852 --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-variable.stderr @@ -0,0 +1,13 @@ +error[E0597]: `x` does not live long enough + --> $DIR/regions-escape-loop-via-variable.rs:11:13 + | +LL | let x = 1 + *p; + | -- borrow later used here +LL | p = &x; + | ^^ borrowed value does not live long enough +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/regions-escape-loop-via-vec.rs b/tests/ui/span/regions-escape-loop-via-vec.rs new file mode 100644 index 000000000..1fceb0969 --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-vec.rs @@ -0,0 +1,13 @@ +// The type of `y` ends up getting inferred to the type of the block. +fn broken() { + let mut x = 3; + let mut _y = vec![&mut x]; + while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed + let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed + _y.push(&mut z); + //~^ ERROR `z` does not live long enough + x += 1; //~ ERROR cannot use `x` because it was mutably borrowed + } +} + +fn main() { } diff --git a/tests/ui/span/regions-escape-loop-via-vec.stderr b/tests/ui/span/regions-escape-loop-via-vec.stderr new file mode 100644 index 000000000..2b6493077 --- /dev/null +++ b/tests/ui/span/regions-escape-loop-via-vec.stderr @@ -0,0 +1,50 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/regions-escape-loop-via-vec.rs:5:11 + | +LL | let mut _y = vec![&mut x]; + | ------ borrow of `x` occurs here +LL | while x < 10 { + | ^ use of borrowed `x` +LL | let mut z = x; +LL | _y.push(&mut z); + | --------------- borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/regions-escape-loop-via-vec.rs:6:21 + | +LL | let mut _y = vec![&mut x]; + | ------ borrow of `x` occurs here +LL | while x < 10 { +LL | let mut z = x; + | ^ use of borrowed `x` +LL | _y.push(&mut z); + | --------------- borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/regions-escape-loop-via-vec.rs:7:17 + | +LL | _y.push(&mut z); + | --------^^^^^^- + | | | + | | borrowed value does not live long enough + | borrow later used here +... +LL | } + | - `z` dropped here while still borrowed + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/regions-escape-loop-via-vec.rs:9:9 + | +LL | let mut _y = vec![&mut x]; + | ------ borrow of `x` occurs here +... +LL | _y.push(&mut z); + | --------------- borrow later used here +LL | +LL | x += 1; + | ^^^^^^ use of borrowed `x` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0503, E0597. +For more information about an error, try `rustc --explain E0503`. diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.rs b/tests/ui/span/regions-infer-borrow-scope-within-loop.rs new file mode 100644 index 000000000..3b20285b1 --- /dev/null +++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.rs @@ -0,0 +1,22 @@ +fn borrow(x: &T) -> &T {x} + +fn foo(mut cond: C, mut make_box: M) where + C: FnMut() -> bool, + M: FnMut() -> Box, +{ + let mut y: &isize; + loop { + let x = make_box(); + + // Here we complain because the resulting region + // of this borrow is the fn body as a whole. + y = borrow(&*x); + //~^ ERROR `*x` does not live long enough + + assert_eq!(*x, *y); + if cond() { break; } + } + assert!(*y != 0); +} + +fn main() {} diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr new file mode 100644 index 000000000..fd67c65c4 --- /dev/null +++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr @@ -0,0 +1,14 @@ +error[E0597]: `*x` does not live long enough + --> $DIR/regions-infer-borrow-scope-within-loop.rs:13:20 + | +LL | y = borrow(&*x); + | ^^^ borrowed value does not live long enough +... +LL | } + | - `*x` dropped here while still borrowed +LL | assert!(*y != 0); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.rs b/tests/ui/span/send-is-not-static-ensures-scoping.rs new file mode 100644 index 000000000..2aecc2a7e --- /dev/null +++ b/tests/ui/span/send-is-not-static-ensures-scoping.rs @@ -0,0 +1,26 @@ +struct Guard<'a> { + f: Box, +} + +fn scoped<'a, F: Fn() + Send + 'a>(f: F) -> Guard<'a> { + Guard { f: Box::new(f) } +} + +impl<'a> Guard<'a> { + fn join(self) {} +} + +fn main() { + let bad = { + let x = 1; + let y = &x; + //~^ ERROR `x` does not live long enough + + scoped(|| { + let _z = y; + //~^ ERROR `y` does not live long enough + }) + }; + + bad.join(); +} diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.stderr b/tests/ui/span/send-is-not-static-ensures-scoping.stderr new file mode 100644 index 000000000..65d10c130 --- /dev/null +++ b/tests/ui/span/send-is-not-static-ensures-scoping.stderr @@ -0,0 +1,29 @@ +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-ensures-scoping.rs:16:17 + | +LL | let bad = { + | --- borrow later stored here +LL | let x = 1; +LL | let y = &x; + | ^^ borrowed value does not live long enough +... +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `y` does not live long enough + --> $DIR/send-is-not-static-ensures-scoping.rs:20:22 + | +LL | let bad = { + | --- borrow later stored here +... +LL | scoped(|| { + | -- value captured here +LL | let _z = y; + | ^ borrowed value does not live long enough +... +LL | }; + | - `y` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/send-is-not-static-std-sync-2.rs b/tests/ui/span/send-is-not-static-std-sync-2.rs new file mode 100644 index 000000000..38746d4cb --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync-2.rs @@ -0,0 +1,39 @@ +// basic tests to see that certain "obvious" errors are caught by +// these types no longer requiring `'static` (RFC 458) + +#![allow(dead_code)] + +use std::sync::{Mutex, RwLock, mpsc}; + +fn mutex() { + let lock = { + let x = 1; + Mutex::new(&x) + }; + //~^^ ERROR `x` does not live long enough + + let _dangling = *lock.lock().unwrap(); +} + +fn rwlock() { + let lock = { + let x = 1; + RwLock::new(&x) + }; + //~^^ ERROR `x` does not live long enough + let _dangling = *lock.read().unwrap(); +} + +fn channel() { + let (_tx, rx) = { + let x = 1; + let (tx, rx) = mpsc::channel(); + let _ = tx.send(&x); + (tx, rx) + }; + //~^^^ ERROR `x` does not live long enough + + let _dangling = rx.recv(); +} + +fn main() {} diff --git a/tests/ui/span/send-is-not-static-std-sync-2.stderr b/tests/ui/span/send-is-not-static-std-sync-2.stderr new file mode 100644 index 000000000..bcd07e116 --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync-2.stderr @@ -0,0 +1,37 @@ +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-std-sync-2.rs:11:20 + | +LL | let lock = { + | ---- borrow later stored here +LL | let x = 1; +LL | Mutex::new(&x) + | ^^ borrowed value does not live long enough +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-std-sync-2.rs:21:21 + | +LL | let lock = { + | ---- borrow later stored here +LL | let x = 1; +LL | RwLock::new(&x) + | ^^ borrowed value does not live long enough +LL | }; + | - `x` dropped here while still borrowed + +error[E0597]: `x` does not live long enough + --> $DIR/send-is-not-static-std-sync-2.rs:31:25 + | +LL | let (_tx, rx) = { + | --- borrow later used here +... +LL | let _ = tx.send(&x); + | ^^ borrowed value does not live long enough +LL | (tx, rx) +LL | }; + | - `x` dropped here while still borrowed + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/send-is-not-static-std-sync.rs b/tests/ui/span/send-is-not-static-std-sync.rs new file mode 100644 index 000000000..f8ab5243c --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync.rs @@ -0,0 +1,55 @@ +// basic tests to see that certain "obvious" errors are caught by +// these types no longer requiring `'static` (RFC 458) + +#![allow(dead_code)] + +use std::sync::{Mutex, RwLock, mpsc}; + +fn mutex() { + let x = 1; + let y = Box::new(1); + let lock = Mutex::new(&x); + *lock.lock().unwrap() = &*y; + drop(y); //~ ERROR cannot move out + { + let z = 2; + *lock.lock().unwrap() = &z; + } + //~^^ ERROR `z` does not live long enough + lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use) +} + +fn rwlock() { + let x = 1; + let y = Box::new(1); + let lock = RwLock::new(&x); + *lock.write().unwrap() = &*y; + drop(y); //~ ERROR cannot move out + { + let z = 2; + *lock.write().unwrap() = &z; + } + //~^^ ERROR `z` does not live long enough + lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use) +} + +fn channel() { + let x = 1; + let y = Box::new(1); + let (tx, rx) = mpsc::channel(); + + tx.send(&x).unwrap(); + tx.send(&*y); + drop(y); //~ ERROR cannot move out + { + let z = 2; + tx.send(&z).unwrap(); + } + //~^^ ERROR `z` does not live long enough + // (channels lack #[may_dangle], thus their dtors are implicit uses of `z`) +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/send-is-not-static-std-sync.stderr b/tests/ui/span/send-is-not-static-std-sync.stderr new file mode 100644 index 000000000..5d493a3e4 --- /dev/null +++ b/tests/ui/span/send-is-not-static-std-sync.stderr @@ -0,0 +1,72 @@ +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/send-is-not-static-std-sync.rs:13:10 + | +LL | *lock.lock().unwrap() = &*y; + | --- borrow of `*y` occurs here +LL | drop(y); + | ^ move out of `y` occurs here +... +LL | *lock.lock().unwrap() = &z; + | ----------- borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/send-is-not-static-std-sync.rs:16:33 + | +LL | *lock.lock().unwrap() = &z; + | ^^ borrowed value does not live long enough +LL | } + | - `z` dropped here while still borrowed +LL | +LL | lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z` => needs explicit use) + | -------------- borrow later used here + +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/send-is-not-static-std-sync.rs:27:10 + | +LL | *lock.write().unwrap() = &*y; + | --- borrow of `*y` occurs here +LL | drop(y); + | ^ move out of `y` occurs here +... +LL | *lock.write().unwrap() = &z; + | ------------ borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/send-is-not-static-std-sync.rs:30:34 + | +LL | *lock.write().unwrap() = &z; + | ^^ borrowed value does not live long enough +LL | } + | - `z` dropped here while still borrowed +LL | +LL | lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z` => needs explicit use) + | -------------- borrow later used here + +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/send-is-not-static-std-sync.rs:43:10 + | +LL | tx.send(&*y); + | --- borrow of `*y` occurs here +LL | drop(y); + | ^ move out of `y` occurs here +... +LL | tx.send(&z).unwrap(); + | ----------- borrow later used here + +error[E0597]: `z` does not live long enough + --> $DIR/send-is-not-static-std-sync.rs:46:17 + | +LL | tx.send(&z).unwrap(); + | ^^ borrowed value does not live long enough +LL | } + | - `z` dropped here while still borrowed +... +LL | } + | - borrow might be used here, when `tx` is dropped and runs the `Drop` code for type `Sender` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0505, E0597. +For more information about an error, try `rustc --explain E0505`. diff --git a/tests/ui/span/slice-borrow.rs b/tests/ui/span/slice-borrow.rs new file mode 100644 index 000000000..38cd7acbd --- /dev/null +++ b/tests/ui/span/slice-borrow.rs @@ -0,0 +1,14 @@ +// Test slicing expressions doesn't defeat the borrow checker. + +fn main() { + let y; + { + let x: &[isize] = &vec![1, 2, 3, 4, 5]; + //~^ ERROR temporary value dropped while borrowed + y = &x[1..]; + } + y.use_ref(); +} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/tests/ui/span/slice-borrow.stderr b/tests/ui/span/slice-borrow.stderr new file mode 100644 index 000000000..b70bf69d6 --- /dev/null +++ b/tests/ui/span/slice-borrow.stderr @@ -0,0 +1,17 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/slice-borrow.rs:6:28 + | +LL | let x: &[isize] = &vec![1, 2, 3, 4, 5]; + | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use +... +LL | } + | - temporary value is freed at the end of this statement +LL | y.use_ref(); + | ----------- borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/span/suggestion-non-ascii.rs b/tests/ui/span/suggestion-non-ascii.rs new file mode 100644 index 000000000..914efd85a --- /dev/null +++ b/tests/ui/span/suggestion-non-ascii.rs @@ -0,0 +1,4 @@ +fn main() { + let tup = (1,); + println!("☃{}", tup[0]); //~ ERROR cannot index into a value of type +} diff --git a/tests/ui/span/suggestion-non-ascii.stderr b/tests/ui/span/suggestion-non-ascii.stderr new file mode 100644 index 000000000..b14632d4e --- /dev/null +++ b/tests/ui/span/suggestion-non-ascii.stderr @@ -0,0 +1,9 @@ +error[E0608]: cannot index into a value of type `({integer},)` + --> $DIR/suggestion-non-ascii.rs:3:21 + | +LL | println!("☃{}", tup[0]); + | ^^^^^^ help: to access tuple elements, use: `tup.0` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0608`. diff --git a/tests/ui/span/transitive-dep-span.rs b/tests/ui/span/transitive-dep-span.rs new file mode 100644 index 000000000..2d46f74ad --- /dev/null +++ b/tests/ui/span/transitive-dep-span.rs @@ -0,0 +1,15 @@ +// Tests that we properly serialize/deserialize spans from transitive dependencies +// (e.g. imported SourceFiles) +// +// The order of these next lines is important, since we need +// transitive_dep_two.rs to be able to reference transitive_dep_three.rs +// +// aux-build: transitive_dep_three.rs +// aux-build: transitive_dep_two.rs +// compile-flags: -Z macro-backtrace + +extern crate transitive_dep_two; + +transitive_dep_two::parse_error!(); //~ ERROR expected one of + +fn main() {} diff --git a/tests/ui/span/transitive-dep-span.stderr b/tests/ui/span/transitive-dep-span.stderr new file mode 100644 index 000000000..4dc3e5721 --- /dev/null +++ b/tests/ui/span/transitive-dep-span.stderr @@ -0,0 +1,18 @@ +error: expected one of `!` or `::`, found `error` + --> $DIR/auxiliary/transitive_dep_three.rs:6:27 + | +LL | macro_rules! parse_error { + | ------------------------ in this expansion of `transitive_dep_two::parse_error!` +LL | () => { parse error } + | ^^^^^ expected one of `!` or `::` + | + ::: $DIR/transitive-dep-span.rs:13:1 + | +LL | transitive_dep_two::parse_error!(); + | ---------------------------------- + | | + | in this macro invocation + | in this macro invocation + +error: aborting due to previous error + diff --git a/tests/ui/span/type-annotations-needed-expr.rs b/tests/ui/span/type-annotations-needed-expr.rs new file mode 100644 index 000000000..f64dab4d7 --- /dev/null +++ b/tests/ui/span/type-annotations-needed-expr.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = (vec![1,2,3]).into_iter().sum() as f64; //~ ERROR E0282 +} diff --git a/tests/ui/span/type-annotations-needed-expr.stderr b/tests/ui/span/type-annotations-needed-expr.stderr new file mode 100644 index 000000000..9dff6c64d --- /dev/null +++ b/tests/ui/span/type-annotations-needed-expr.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/type-annotations-needed-expr.rs:2:39 + | +LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | let _ = (vec![1,2,3]).into_iter().sum::() as f64; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/span/type-binding.rs b/tests/ui/span/type-binding.rs new file mode 100644 index 000000000..32016e127 --- /dev/null +++ b/tests/ui/span/type-binding.rs @@ -0,0 +1,9 @@ +// Regression test for issue #28158 +// Test the type binding span doesn't include >> + +use std::ops::Deref; + +fn homura>(_: T) {} +//~^ ERROR not found + +fn main() {} diff --git a/tests/ui/span/type-binding.stderr b/tests/ui/span/type-binding.stderr new file mode 100644 index 000000000..cb0aefe06 --- /dev/null +++ b/tests/ui/span/type-binding.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Trget` not found for `Deref` + --> $DIR/type-binding.rs:6:20 + | +LL | fn homura>(_: T) {} + | ^^^^^ help: there is an associated type with a similar name: `Target` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/span/typo-suggestion.rs b/tests/ui/span/typo-suggestion.rs new file mode 100644 index 000000000..e9d7bc65e --- /dev/null +++ b/tests/ui/span/typo-suggestion.rs @@ -0,0 +1,9 @@ +fn main() { + let foo = 1; + + // `foo` shouldn't be suggested, it is too dissimilar from `bar`. + println!("Hello {}", bar); //~ ERROR cannot find value + + // But this is close enough. + println!("Hello {}", fob); //~ ERROR cannot find value +} diff --git a/tests/ui/span/typo-suggestion.stderr b/tests/ui/span/typo-suggestion.stderr new file mode 100644 index 000000000..61d4e0611 --- /dev/null +++ b/tests/ui/span/typo-suggestion.stderr @@ -0,0 +1,15 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/typo-suggestion.rs:5:26 + | +LL | println!("Hello {}", bar); + | ^^^ not found in this scope + +error[E0425]: cannot find value `fob` in this scope + --> $DIR/typo-suggestion.rs:8:26 + | +LL | println!("Hello {}", fob); + | ^^^ help: a local variable with a similar name exists: `foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/span/unused-warning-point-at-identifier.rs b/tests/ui/span/unused-warning-point-at-identifier.rs new file mode 100644 index 000000000..af4834503 --- /dev/null +++ b/tests/ui/span/unused-warning-point-at-identifier.rs @@ -0,0 +1,30 @@ +// run-pass + +#![warn(unused)] + +enum Enum { //~ WARN enum `Enum` is never used + A, + B, + C, + D, +} + +struct Struct { //~ WARN struct `Struct` is never constructed + a: usize, + b: usize, + c: usize, + d: usize, +} + +fn func() -> usize { //~ WARN function `func` is never used + 3 +} + +fn +func_complete_span() //~ WARN function `func_complete_span` is never used +-> usize +{ + 3 +} + +fn main() {} diff --git a/tests/ui/span/unused-warning-point-at-identifier.stderr b/tests/ui/span/unused-warning-point-at-identifier.stderr new file mode 100644 index 000000000..c2cb56231 --- /dev/null +++ b/tests/ui/span/unused-warning-point-at-identifier.stderr @@ -0,0 +1,33 @@ +warning: enum `Enum` is never used + --> $DIR/unused-warning-point-at-identifier.rs:5:6 + | +LL | enum Enum { + | ^^^^ + | +note: the lint level is defined here + --> $DIR/unused-warning-point-at-identifier.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` + +warning: struct `Struct` is never constructed + --> $DIR/unused-warning-point-at-identifier.rs:12:8 + | +LL | struct Struct { + | ^^^^^^ + +warning: function `func` is never used + --> $DIR/unused-warning-point-at-identifier.rs:19:4 + | +LL | fn func() -> usize { + | ^^^^ + +warning: function `func_complete_span` is never used + --> $DIR/unused-warning-point-at-identifier.rs:24:1 + | +LL | func_complete_span() + | ^^^^^^^^^^^^^^^^^^ + +warning: 4 warnings emitted + diff --git a/tests/ui/span/vec-must-not-hide-type-from-dropck.rs b/tests/ui/span/vec-must-not-hide-type-from-dropck.rs new file mode 100644 index 000000000..9bfbfab06 --- /dev/null +++ b/tests/ui/span/vec-must-not-hide-type-from-dropck.rs @@ -0,0 +1,125 @@ +// Checking that `Vec` cannot hide lifetimes within `T` when `T` +// implements `Drop` and might access methods of values that have +// since been deallocated. +// +// In this case, the values in question hold (non-zero) unique-ids +// that zero themselves out when dropped, and are wrapped in another +// type with a destructor that asserts that the ids it references are +// indeed non-zero (i.e., effectively checking that the id's are not +// dropped while there are still any outstanding references). +// +// However, the values in question are also formed into a +// cyclic-structure, ensuring that there is no way for all of the +// conditions above to be satisfied, meaning that if the dropck is +// sound, it should reject this code. + + + +use std::cell::Cell; +use id::Id; + +mod s { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static S_COUNT: AtomicUsize = AtomicUsize::new(0); + + /// generates globally unique count (global across the current + /// process, that is) + pub fn next_count() -> usize { + S_COUNT.fetch_add(1, Ordering::SeqCst) + 1 + } +} + +mod id { + use s; + + /// Id represents a globally unique identifier (global across the + /// current process, that is). When dropped, it automatically + /// clears its `count` field, but leaves `orig_count` untouched, + /// so that if there are subsequent (erroneous) invocations of its + /// method (which is unsound), we can observe it by seeing that + /// the `count` is 0 while the `orig_count` is non-zero. + #[derive(Debug)] + pub struct Id { + orig_count: usize, + count: usize, + } + + impl Id { + /// Creates an `Id` with a globally unique count. + pub fn new() -> Id { + let c = s::next_count(); + println!("building Id {}", c); + Id { orig_count: c, count: c } + } + /// returns the `count` of self; should be non-zero if + /// everything is working. + pub fn count(&self) -> usize { + println!("Id::count on {} returns {}", self.orig_count, self.count); + self.count + } + } + + impl Drop for Id { + fn drop(&mut self) { + println!("dropping Id {}", self.count); + self.count = 0; + } + } +} + +trait HasId { + fn count(&self) -> usize; +} + +#[derive(Debug)] +struct CheckId { + v: T +} + +#[allow(non_snake_case)] +fn CheckId(t: T) -> CheckId { CheckId{ v: t } } + +impl Drop for CheckId { + fn drop(&mut self) { + assert!(self.v.count() > 0); + } +} + +#[derive(Debug)] +struct C<'a> { + id: Id, + v: Vec>>>>, +} + +impl<'a> HasId for Cell>> { + fn count(&self) -> usize { + match self.get() { + None => 1, + Some(c) => c.id.count(), + } + } +} + +impl<'a> C<'a> { + fn new() -> C<'a> { + C { id: Id::new(), v: Vec::new() } + } +} + +fn f() { + let (mut c1, mut c2); + c1 = C::new(); + c2 = C::new(); + + c1.v.push(CheckId(Cell::new(None))); + c2.v.push(CheckId(Cell::new(None))); + c1.v[0].v.set(Some(&c2)); + //~^ ERROR `c2` does not live long enough + c2.v[0].v.set(Some(&c1)); + //~^ ERROR `c1` does not live long enough +} + +fn main() { + f(); +} diff --git a/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr new file mode 100644 index 000000000..f87c32d1a --- /dev/null +++ b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr @@ -0,0 +1,29 @@ +error[E0597]: `c2` does not live long enough + --> $DIR/vec-must-not-hide-type-from-dropck.rs:117:24 + | +LL | c1.v[0].v.set(Some(&c2)); + | ^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `c2` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `c1` does not live long enough + --> $DIR/vec-must-not-hide-type-from-dropck.rs:119:24 + | +LL | c2.v[0].v.set(Some(&c1)); + | ^^^ borrowed value does not live long enough +LL | +LL | } + | - + | | + | `c1` dropped here while still borrowed + | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/vec_refs_data_with_early_death.rs b/tests/ui/span/vec_refs_data_with_early_death.rs new file mode 100644 index 000000000..c23c52115 --- /dev/null +++ b/tests/ui/span/vec_refs_data_with_early_death.rs @@ -0,0 +1,33 @@ +// This test is a simple example of code that violates the dropck +// rules: it pushes `&x` and `&y` into a bag (with dtor), but the +// referenced data will be dropped before the bag is. + + + + + + + +fn main() { + let mut v = Bag::new(); + + let x: i8 = 3; + let y: i8 = 4; + + v.push(&x); + //~^ ERROR `x` does not live long enough + v.push(&y); + //~^ ERROR `y` does not live long enough + + assert_eq!(v.0, [&3, &4]); +} + +//`Vec` is #[may_dangle] w.r.t. `T`; putting a bag over its head +// forces borrowck to treat dropping the bag as a potential use. +struct Bag(Vec); +impl Drop for Bag { fn drop(&mut self) { } } + +impl Bag { + fn new() -> Self { Bag(Vec::new()) } + fn push(&mut self, t: T) { self.0.push(t); } +} diff --git a/tests/ui/span/vec_refs_data_with_early_death.stderr b/tests/ui/span/vec_refs_data_with_early_death.stderr new file mode 100644 index 000000000..684e78453 --- /dev/null +++ b/tests/ui/span/vec_refs_data_with_early_death.stderr @@ -0,0 +1,31 @@ +error[E0597]: `x` does not live long enough + --> $DIR/vec_refs_data_with_early_death.rs:17:12 + | +LL | v.push(&x); + | ^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `x` dropped here while still borrowed + | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag` + | + = note: values in a scope are dropped in the opposite order they are defined + +error[E0597]: `y` does not live long enough + --> $DIR/vec_refs_data_with_early_death.rs:19:12 + | +LL | v.push(&y); + | ^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `y` dropped here while still borrowed + | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag` + | + = note: values in a scope are dropped in the opposite order they are defined + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/span/visibility-ty-params.rs b/tests/ui/span/visibility-ty-params.rs new file mode 100644 index 000000000..d77febe0a --- /dev/null +++ b/tests/ui/span/visibility-ty-params.rs @@ -0,0 +1,13 @@ +macro_rules! m { + ($p: path) => (pub(in $p) struct Z;) +} + +struct S(T); +m!{ S } //~ ERROR unexpected generic arguments in path + //~| ERROR expected module, found struct `S` + +mod m { + m!{ m<> } //~ ERROR unexpected generic arguments in path +} + +fn main() {} diff --git a/tests/ui/span/visibility-ty-params.stderr b/tests/ui/span/visibility-ty-params.stderr new file mode 100644 index 000000000..067893fd2 --- /dev/null +++ b/tests/ui/span/visibility-ty-params.stderr @@ -0,0 +1,21 @@ +error: unexpected generic arguments in path + --> $DIR/visibility-ty-params.rs:6:6 + | +LL | m!{ S } + | ^^^^ + +error[E0577]: expected module, found struct `S` + --> $DIR/visibility-ty-params.rs:6:5 + | +LL | m!{ S } + | ^^^^^ not a module + +error: unexpected generic arguments in path + --> $DIR/visibility-ty-params.rs:10:10 + | +LL | m!{ m<> } + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0577`. diff --git a/tests/ui/span/wf-method-late-bound-regions.rs b/tests/ui/span/wf-method-late-bound-regions.rs new file mode 100644 index 000000000..ca9f73d0a --- /dev/null +++ b/tests/ui/span/wf-method-late-bound-regions.rs @@ -0,0 +1,24 @@ +// A method's receiver must be well-formed, even if it has late-bound regions. +// Because of this, a method's substs being well-formed does not imply that +// the method's implied bounds are met. + +struct Foo<'b>(Option<&'b ()>); + +trait Bar<'b> { + fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32; +} + +impl<'b> Bar<'b> for Foo<'b> { + fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u } +} + +fn main() { + let f = Foo(None); + let f2 = f; + let dangling = { + let pointer = Box::new(42); + f2.xmute(&pointer) + }; + //~^^ ERROR `pointer` does not live long enough + println!("{}", dangling); +} diff --git a/tests/ui/span/wf-method-late-bound-regions.stderr b/tests/ui/span/wf-method-late-bound-regions.stderr new file mode 100644 index 000000000..6b0b00820 --- /dev/null +++ b/tests/ui/span/wf-method-late-bound-regions.stderr @@ -0,0 +1,14 @@ +error[E0597]: `pointer` does not live long enough + --> $DIR/wf-method-late-bound-regions.rs:20:18 + | +LL | let dangling = { + | -------- borrow later stored here +LL | let pointer = Box::new(42); +LL | f2.xmute(&pointer) + | ^^^^^^^^ borrowed value does not live long enough +LL | }; + | - `pointer` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/specialization/README-rpass.md b/tests/ui/specialization/README-rpass.md new file mode 100644 index 000000000..c1486ce1e --- /dev/null +++ b/tests/ui/specialization/README-rpass.md @@ -0,0 +1,37 @@ +Tests that specialization is working correctly: + +- Dispatch + - [On methods](specialization-basics.rs), includes: + - Specialization via adding a trait bound + - Including both remote and local traits + - Specialization via pure structure (e.g. `(T, U)` vs `(T, T)`) + - Specialization via concrete types vs unknown types + - In top level of the trait reference + - Embedded within another type (`Vec` vs `Vec`) + - [Specialization based on super trait relationships](specialization-supertraits.rs) + - [On assoc fns](specialization-assoc-fns.rs) + - [Ensure that impl order doesn't matter](specialization-out-of-order.rs) + +- Item inheritance + - [Correct default cascading for methods](specialization-default-methods.rs) + - Inheritance works across impls with varying generics + - [With projections](specialization-translate-projections.rs) + - [With projections that involve input types](specialization-translate-projections-with-params.rs) + +- Normalization issues + - [Non-default assoc types can be projected](specialization-projection.rs) + - Including non-specialized cases + - Including specialized cases + - [Specialized Impls can happen on projections](specialization-on-projection.rs) + - [Projections and aliases play well together](specialization-projection-alias.rs) + - [Projections involving specialization allowed in the trait ref for impls, and overlap can still be determined](specialization-overlap-projection.rs) + - Only works for the simple case where the most specialized impl directly + provides a non-`default` associated type + +- Across crates + - [For traits defined in upstream crate](specialization-allowed-cross-crate.rs) + - [Full method dispatch tests, drawing from upstream crate](specialization-cross-crate.rs) + - Including *additional* local specializations + - [Full method dispatch tests, *without* turning on specialization in local crate](specialization-cross-crate-no-gate.rs) + - [Test that defaults cascade correctly from upstream crates](specialization-cross-crate-defaults.rs) + - Including *additional* local use of defaults diff --git a/tests/ui/specialization/README.md b/tests/ui/specialization/README.md new file mode 100644 index 000000000..f2b4bf946 --- /dev/null +++ b/tests/ui/specialization/README.md @@ -0,0 +1,21 @@ +This directory contains the test for incorrect usage of specialization that +should lead to compile failure. Those tests break down into a few categories: + +- Feature gating + - [On use of the `default` keyword](specialization-feature-gate-default.rs) + - [On overlapping impls](specialization-feature-gate-overlap.rs) + +- Overlap checking with specialization enabled + - [Basic overlap scenarios](specialization-overlap.rs) + - Includes purely structural overlap + - Includes purely trait-based overlap + - Includes mix + - [Overlap with differing polarity](specialization-overlap-negative.rs) + +- [Attempt to specialize without using `default`](specialization-no-default.rs) + +- [Attempt to change impl polarity in a specialization](specialization-polarity.rs) + +- Attempt to rely on projection of a `default` type + - [Rely on it externally in both generic and monomorphic contexts](specialization-default-projection.rs) + - [Rely on it both within an impl and outside it](specialization-default-types.rs) diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs new file mode 100644 index 000000000..fc39b553a --- /dev/null +++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs @@ -0,0 +1,25 @@ +// run-pass + +// Make sure we don't crash with a cycle error during coherence. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Trait { + type Assoc; +} + +impl Trait for Vec { + default type Assoc = (); +} + +impl Trait for Vec { + type Assoc = u8; +} + +impl Trait for String { + type Assoc = (); +} + +impl Trait< as Trait>::Assoc> for String {} + +fn main() {} diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.stderr b/tests/ui/specialization/assoc-ty-graph-cycle.stderr new file mode 100644 index 000000000..f5529c24d --- /dev/null +++ b/tests/ui/specialization/assoc-ty-graph-cycle.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/assoc-ty-graph-cycle.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/auxiliary/cross_crates_defaults.rs b/tests/ui/specialization/auxiliary/cross_crates_defaults.rs new file mode 100644 index 000000000..1e5555355 --- /dev/null +++ b/tests/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -0,0 +1,40 @@ +#![feature(specialization)] + +// First, test only use of explicit `default` items: + +pub trait Foo { + fn foo(&self) -> bool; +} + +impl Foo for T { + default fn foo(&self) -> bool { false } +} + +impl Foo for i32 {} + +impl Foo for i64 { + fn foo(&self) -> bool { true } +} + +// Next, test mixture of explicit `default` and provided methods: + +pub trait Bar { + fn bar(&self) -> i32 { 0 } +} + +impl Bar for T { + default fn bar(&self) -> i32 { 0 } +} + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl Bar for Vec { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec {} +impl Bar for Vec { + fn bar(&self) -> i32 { 3 } +} diff --git a/tests/ui/specialization/auxiliary/go_trait.rs b/tests/ui/specialization/auxiliary/go_trait.rs new file mode 100644 index 000000000..aa0ec2289 --- /dev/null +++ b/tests/ui/specialization/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once(this: G, arg: isize) { + this.go_once(arg) +} + +impl GoMut for G + where G : Go +{ + default fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +impl GoOnce for G + where G : GoMut +{ + default fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/specialization/auxiliary/specialization_cross_crate.rs b/tests/ui/specialization/auxiliary/specialization_cross_crate.rs new file mode 100644 index 000000000..8caa8524f --- /dev/null +++ b/tests/ui/specialization/auxiliary/specialization_cross_crate.rs @@ -0,0 +1,72 @@ +#![feature(specialization)] + +pub trait Foo { + fn foo(&self) -> &'static str; +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl Foo for (T, T) { + default fn foo(&self) -> &'static str { + "generic uniform pair" + } +} + +impl Foo for (u8, u32) { + default fn foo(&self) -> &'static str { + "(u8, u32)" + } +} + +impl Foo for (u8, u8) { + default fn foo(&self) -> &'static str { + "(u8, u8)" + } +} + +impl Foo for Vec { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec { + fn foo(&self) -> &'static str { + "Vec" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +pub trait MyMarker {} +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} diff --git a/tests/ui/specialization/const_trait_impl.rs b/tests/ui/specialization/const_trait_impl.rs new file mode 100644 index 000000000..05ba4c8d4 --- /dev/null +++ b/tests/ui/specialization/const_trait_impl.rs @@ -0,0 +1,55 @@ +// check-pass +#![feature(const_trait_impl, min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +#[const_trait] +pub unsafe trait Sup { + fn foo() -> u32; +} + +#[rustc_specialization_trait] +#[const_trait] +pub unsafe trait Sub: ~const Sup {} + +unsafe impl const Sup for u8 { + default fn foo() -> u32 { + 1 + } +} + +unsafe impl const Sup for () { + fn foo() -> u32 { + 42 + } +} + +unsafe impl const Sub for () {} + +#[const_trait] +pub trait A { + fn a() -> u32; +} + +impl const A for T { + default fn a() -> u32 { + 2 + } +} + +impl const A for T { + default fn a() -> u32 { + 3 + } +} + +impl const A for T { + fn a() -> u32 { + T::foo() + } +} + +const _: () = assert!(<()>::a() == 42); +const _: () = assert!(::a() == 3); +const _: () = assert!(::a() == 2); + +fn main() {} diff --git a/tests/ui/specialization/cross-crate-defaults.rs b/tests/ui/specialization/cross-crate-defaults.rs new file mode 100644 index 000000000..fc28d0c81 --- /dev/null +++ b/tests/ui/specialization/cross-crate-defaults.rs @@ -0,0 +1,41 @@ +// run-pass + +// aux-build:cross_crates_defaults.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate cross_crates_defaults; + +use cross_crates_defaults::*; + +struct LocalDefault; +struct LocalOverride; + +impl Foo for LocalDefault {} + +impl Foo for LocalOverride { + fn foo(&self) -> bool { true } +} + +fn test_foo() { + assert!(!0i8.foo()); + assert!(!0i32.foo()); + assert!(0i64.foo()); + + assert!(!LocalDefault.foo()); + assert!(LocalOverride.foo()); +} + +fn test_bar() { + assert!(0u8.bar() == 0); + assert!(0i32.bar() == 1); + assert!("hello".bar() == 0); + assert!(vec![()].bar() == 2); + assert!(vec![0i32].bar() == 2); + assert!(vec![0i64].bar() == 3); +} + +fn main() { + test_foo(); + test_bar(); +} diff --git a/tests/ui/specialization/cross-crate-defaults.stderr b/tests/ui/specialization/cross-crate-defaults.stderr new file mode 100644 index 000000000..ee5c77a76 --- /dev/null +++ b/tests/ui/specialization/cross-crate-defaults.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/cross-crate-defaults.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/default-associated-type-bound-1.rs b/tests/ui/specialization/default-associated-type-bound-1.rs new file mode 100644 index 000000000..c043114b5 --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-1.rs @@ -0,0 +1,24 @@ +// Check that we check that default associated types satisfy the required +// bounds on them. + +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U: Clone; + fn unsafe_clone(&self, x: Option<&Self::U>) { + x.cloned(); + } +} + +// We cannot normalize `::U` to `str` here, because the default could +// be overridden. The error here must therefore be found by a method other than +// normalization. +impl X for T { + default type U = str; + //~^ ERROR the trait bound `str: Clone` is not satisfied +} + +pub fn main() { + 1.unsafe_clone(None); +} diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr new file mode 100644 index 000000000..e498187c0 --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-1.stderr @@ -0,0 +1,26 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-associated-type-bound-1.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/default-associated-type-bound-1.rs:18:22 + | +LL | default type U = str; + | ^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `X::U` + --> $DIR/default-associated-type-bound-1.rs:8:13 + | +LL | type U: Clone; + | ^^^^^ required by this bound in `X::U` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-associated-type-bound-2.rs b/tests/ui/specialization/default-associated-type-bound-2.rs new file mode 100644 index 000000000..0a21b1f09 --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-2.rs @@ -0,0 +1,22 @@ +// Check that generic predicates are also checked for default associated types. +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U: PartialEq; + fn unsafe_compare(x: Option, y: Option) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl X for T { + default type U = &'static B; + //~^ ERROR can't compare `&'static B` with `B` +} + +pub fn main() { + >::unsafe_compare(None, None); +} diff --git a/tests/ui/specialization/default-associated-type-bound-2.stderr b/tests/ui/specialization/default-associated-type-bound-2.stderr new file mode 100644 index 000000000..4dbe251ed --- /dev/null +++ b/tests/ui/specialization/default-associated-type-bound-2.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-associated-type-bound-2.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `&'static B` with `B` + --> $DIR/default-associated-type-bound-2.rs:16:22 + | +LL | default type U = &'static B; + | ^^^^^^^^^^ no implementation for `&'static B == B` + | + = help: the trait `PartialEq` is not implemented for `&'static B` +note: required by a bound in `X::U` + --> $DIR/default-associated-type-bound-2.rs:6:13 + | +LL | type U: PartialEq; + | ^^^^^^^^^^^^ required by this bound in `X::U` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | impl X for T where &'static B: PartialEq { + | ++++++++++++++++++++++++++++++ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/default-generic-associated-type-bound.rs b/tests/ui/specialization/default-generic-associated-type-bound.rs new file mode 100644 index 000000000..31a0685d0 --- /dev/null +++ b/tests/ui/specialization/default-generic-associated-type-bound.rs @@ -0,0 +1,25 @@ +// Check that default generics associated types are validated. + +#![feature(specialization)] +//~^ WARNING `specialization` is incomplete + +trait X { + type U<'a>: PartialEq<&'a Self> where Self: 'a; + fn unsafe_compare<'b>(x: Option>, y: Option<&'b Self>) { + match (x, y) { + (Some(a), Some(b)) => a == b, + _ => false, + }; + } +} + +impl X for T { + default type U<'a> = &'a T; + //~^ ERROR can't compare `T` with `T` +} + +struct NotComparable; + +pub fn main() { + ::unsafe_compare(None, None); +} diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr new file mode 100644 index 000000000..c597eed37 --- /dev/null +++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-generic-associated-type-bound.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: can't compare `T` with `T` + --> $DIR/default-generic-associated-type-bound.rs:17:26 + | +LL | default type U<'a> = &'a T; + | ^^^^^ no implementation for `T == T` + | + = note: required for `&'a T` to implement `PartialEq` +note: required by a bound in `X::U` + --> $DIR/default-generic-associated-type-bound.rs:7:17 + | +LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U` +help: consider further restricting this bound + | +LL | impl X for T { + | +++++++++++++++++++++ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs new file mode 100644 index 000000000..5d67160eb --- /dev/null +++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// aux-build:go_trait.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr new file mode 100644 index 000000000..02f13d461 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/allowed-cross-crate.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs b/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs new file mode 100644 index 000000000..c065593b4 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once(this: G, arg: isize) { + this.go_once(arg) +} + +default impl GoMut for G + where G : Go +{ + fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +default impl GoOnce for G + where G : GoMut +{ + fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs new file mode 100644 index 000000000..13258ac8c --- /dev/null +++ b/tests/ui/specialization/defaultimpl/out-of-order.rs @@ -0,0 +1,19 @@ +// run-pass + +// Test that you can list the more specific impl before the more general one. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + type Out; +} + +impl Foo for bool { + type Out = (); +} + +default impl Foo for T { + type Out = bool; +} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/out-of-order.stderr b/tests/ui/specialization/defaultimpl/out-of-order.stderr new file mode 100644 index 000000000..2cf1ac909 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/out-of-order.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/out-of-order.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs new file mode 100644 index 000000000..0add4d551 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs @@ -0,0 +1,25 @@ +// run-pass + +// Test that impls on projected self types can resolve overlap, even when the +// projections involve specialization, so long as the associated type is +// provided by the most specialized impl. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Assoc { + type Output; +} + +default impl Assoc for T { + type Output = bool; +} + +impl Assoc for u8 { type Output = u8; } +impl Assoc for u16 { type Output = u16; } + +trait Foo {} +impl Foo for u32 {} +impl Foo for ::Output {} +impl Foo for ::Output {} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.stderr b/tests/ui/specialization/defaultimpl/overlap-projection.stderr new file mode 100644 index 000000000..75fdfafd9 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/overlap-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-projection.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/projection.rs b/tests/ui/specialization/defaultimpl/projection.rs new file mode 100644 index 000000000..f19c55b04 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/projection.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Make sure we *can* project non-defaulted associated types +// cf ui/specialization/specialization-default-projection.rs + +// First, do so without any use of specialization + +trait Foo { + type Assoc; +} + +impl Foo for T { + type Assoc = (); +} + +fn generic_foo() -> ::Assoc { + () +} + +// Next, allow for one layer of specialization + +trait Bar { + type Assoc; +} + +default impl Bar for T { + type Assoc = (); +} + +impl Bar for T { + type Assoc = u8; +} + +fn generic_bar_clone() -> ::Assoc { + 0u8 +} + +fn main() { +} diff --git a/tests/ui/specialization/defaultimpl/projection.stderr b/tests/ui/specialization/defaultimpl/projection.stderr new file mode 100644 index 000000000..cc3fe8237 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs new file mode 100644 index 000000000..89158b65a --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.rs @@ -0,0 +1,11 @@ +// Check that specialization must be ungated to use the `default` keyword + +trait Foo { + fn foo(&self); +} + +default impl Foo for T { //~ ERROR specialization is unstable + fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr new file mode 100644 index 000000000..64e14f580 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-feature-gate-default.stderr @@ -0,0 +1,14 @@ +error[E0658]: specialization is unstable + --> $DIR/specialization-feature-gate-default.rs:7:1 + | +LL | / default impl Foo for T { +LL | | fn foo(&self) {} +LL | | } + | |_^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs new file mode 100644 index 000000000..661724eef --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs @@ -0,0 +1,77 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Check a number of scenarios in which one impl tries to override another, +// without correctly using `default`. + +// Test 1: one layer of specialization, multiple methods, missing `default` + +trait Foo { + fn foo(&self); + fn bar(&self); +} + +impl Foo for T { + fn foo(&self) {} + fn bar(&self) {} +} + +impl Foo for u8 {} +impl Foo for u16 { + fn foo(&self) {} //~ ERROR E0520 +} +impl Foo for u32 { + fn bar(&self) {} //~ ERROR E0520 +} + +// Test 2: one layer of specialization, missing `default` on associated type + +trait Bar { + type T; +} + +impl Bar for T { + type T = u8; +} + +impl Bar for u8 { + type T = (); //~ ERROR E0520 +} + +// Test 3a: multiple layers of specialization, missing interior `default` + +trait Baz { + fn baz(&self); +} + +default impl Baz for T { + fn baz(&self) {} +} + +impl Baz for T { + fn baz(&self) {} +} + +impl Baz for i32 { + fn baz(&self) {} //~ ERROR E0520 +} + +// Test 3b: multiple layers of specialization, missing interior `default`, +// redundant `default` in bottom layer. + +trait Redundant { + fn redundant(&self); +} + +default impl Redundant for T { + fn redundant(&self) {} +} + +impl Redundant for T { + fn redundant(&self) {} +} + +default impl Redundant for i32 { + fn redundant(&self) {} //~ ERROR E0520 +} + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr new file mode 100644 index 000000000..770be2af2 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -0,0 +1,68 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-no-default.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:20:5 + | +LL | impl Foo for T { + | ----------------- parent `impl` is here +... +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:23:5 + | +LL | impl Foo for T { + | ----------------- parent `impl` is here +... +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` + | + = note: to specialize, `bar` in the parent `impl` must be marked `default` + +error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:37:5 + | +LL | impl Bar for T { + | ----------------- parent `impl` is here +... +LL | type T = (); + | ^^^^^^^^^^^^ cannot specialize default item `T` + | + = note: to specialize, `T` in the parent `impl` must be marked `default` + +error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:55:5 + | +LL | impl Baz for T { + | ------------------------ parent `impl` is here +... +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` + | + = note: to specialize, `baz` in the parent `impl` must be marked `default` + +error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:74:5 + | +LL | impl Redundant for T { + | ------------------------------ parent `impl` is here +... +LL | fn redundant(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` + | + = note: to specialize, `redundant` in the parent `impl` must be marked `default` + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs new file mode 100644 index 000000000..89fef5b5e --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs @@ -0,0 +1,34 @@ +// run-pass + +// Tests that we can combine a default impl that supplies one method with a +// full impl that supplies the other, and they can invoke one another. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; + fn foo_three(&self) -> &'static str; +} + +struct MyStruct; + +default impl Foo for T { + fn foo_one(&self) -> &'static str { + self.foo_three() + } +} + +impl Foo for MyStruct { + fn foo_two(&self) -> &'static str { + self.foo_one() + } + + fn foo_three(&self) -> &'static str { + "generic" + } +} + +fn main() { + assert!(MyStruct.foo_two() == "generic"); +} diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr new file mode 100644 index 000000000..407c1ab77 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs new file mode 100644 index 000000000..3c5414469 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -0,0 +1,23 @@ +// Tests that default impls do not have to supply all items but regular impls do. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; +} + +struct MyStruct; + +default impl Foo for T { + fn foo_one(&self) -> &'static str { + "generic" + } +} + +impl Foo for MyStruct {} +//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046] + +fn main() { + println!("{}", MyStruct.foo_one()); +} diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr new file mode 100644 index 000000000..f19975060 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr @@ -0,0 +1,22 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-item-not-implemented.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0046]: not all trait items implemented, missing: `foo_two` + --> $DIR/specialization-trait-item-not-implemented.rs:18:1 + | +LL | fn foo_two(&self) -> &'static str; + | ---------------------------------- `foo_two` from trait +... +LL | impl Foo for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs new file mode 100644 index 000000000..6834d5736 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs @@ -0,0 +1,24 @@ +// Tests that: +// - default impls do not have to supply all items and +// - a default impl does not count as an impl (in this case, an incomplete default impl). + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; +} + +struct MyStruct; + +default impl Foo for T { + fn foo_one(&self) -> &'static str { + "generic" + } +} + + +fn main() { + println!("{}", MyStruct.foo_one()); + //~^ ERROR the method +} diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr new file mode 100644 index 000000000..37788612f --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -0,0 +1,44 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-trait-not-implemented.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied + --> $DIR/specialization-trait-not-implemented.rs:22:29 + | +LL | struct MyStruct; + | --------------- + | | + | method `foo_one` not found for this struct + | doesn't satisfy `MyStruct: Foo` +... +LL | println!("{}", MyStruct.foo_one()); + | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds + | +note: trait bound `MyStruct: Foo` was not satisfied + --> $DIR/specialization-trait-not-implemented.rs:14:1 + | +LL | default impl Foo for T { + | ^^^^^^^^^^^^^^^^---^^^^^- + | | + | unsatisfied trait bound introduced here +note: the trait `Foo` must be implemented + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | trait Foo { + | ^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo_one`, perhaps you need to implement it + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs new file mode 100644 index 000000000..eb18d6eaa --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs @@ -0,0 +1,10 @@ +// Tests that a default impl still has to have a WF trait ref. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo<'a, T: Eq + 'a> { } + +default impl Foo<'static, U> for () {} +//~^ ERROR the trait bound `U: Eq` is not satisfied + +fn main(){} diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr new file mode 100644 index 000000000..e78016034 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -0,0 +1,29 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-wfcheck.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `U: Eq` is not satisfied + --> $DIR/specialization-wfcheck.rs:7:17 + | +LL | default impl Foo<'static, U> for () {} + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `U` + | +note: required by a bound in `Foo` + --> $DIR/specialization-wfcheck.rs:5:18 + | +LL | trait Foo<'a, T: Eq + 'a> { } + | ^^ required by this bound in `Foo` +help: consider restricting type parameter `U` + | +LL | default impl Foo<'static, U> for () {} + | ++++++++++++++ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs new file mode 100644 index 000000000..8558a1efb --- /dev/null +++ b/tests/ui/specialization/defaultimpl/validation.rs @@ -0,0 +1,16 @@ +#![feature(negative_impls)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +struct S; +struct Z; + +default impl S {} //~ ERROR inherent impls cannot be `default` + +default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default +default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default + //~^ ERROR negative impls cannot be default impls + +trait Tr {} +default impl !Tr for S {} //~ ERROR negative impls cannot be default impls + +fn main() {} diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr new file mode 100644 index 000000000..eb6dc9355 --- /dev/null +++ b/tests/ui/specialization/defaultimpl/validation.stderr @@ -0,0 +1,51 @@ +error: inherent impls cannot be `default` + --> $DIR/validation.rs:7:14 + | +LL | default impl S {} + | ------- ^ inherent impl for this type + | | + | `default` because of this + | + = note: only trait implementations may be annotated with `default` + +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/validation.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error: impls of auto traits cannot be default + --> $DIR/validation.rs:9:21 + | +LL | default unsafe impl Send for S {} + | ------- ^^^^ auto trait + | | + | default because of this + +error: impls of auto traits cannot be default + --> $DIR/validation.rs:10:15 + | +LL | default impl !Send for Z {} + | ------- ^^^^ auto trait + | | + | default because of this + +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:10:1 + | +LL | default impl !Send for Z {} + | ^^^^^^^ ^ + +error[E0750]: negative impls cannot be default impls + --> $DIR/validation.rs:14:1 + | +LL | default impl !Tr for S {} + | ^^^^^^^ ^ + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0750`. diff --git a/tests/ui/specialization/issue-33017.rs b/tests/ui/specialization/issue-33017.rs new file mode 100644 index 000000000..8dbadf58d --- /dev/null +++ b/tests/ui/specialization/issue-33017.rs @@ -0,0 +1,45 @@ +// Test to ensure that trait bounds are properly +// checked on specializable associated types + +#![allow(incomplete_features)] +#![feature(specialization)] + +trait UncheckedCopy: Sized { + type Output: From + Copy + Into; +} + +impl UncheckedCopy for T { + default type Output = Self; + //~^ ERROR: the trait bound `T: Copy` is not satisfied +} + +fn unchecked_copy(other: &T::Output) -> T { + (*other).into() +} + +fn bug(origin: String) { + // Turn the String into it's Output type... + // Which we can just do by `.into()`, the assoc type states `From`. + let origin_output = origin.into(); + + // Make a copy of String::Output, which is a String... + let mut copy: String = unchecked_copy::(&origin_output); + + // Turn the Output type into a String again, + // Which we can just do by `.into()`, the assoc type states `Into`. + let mut origin: String = origin_output.into(); + + // assert both Strings use the same buffer. + assert_eq!(copy.as_ptr(), origin.as_ptr()); + + // Any use of the copy we made becomes invalid, + drop(origin); + + // OH NO! UB UB UB UB! + copy.push_str(" world!"); + println!("{}", copy); +} + +fn main() { + bug(String::from("hello")); +} diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr new file mode 100644 index 000000000..78e94cec2 --- /dev/null +++ b/tests/ui/specialization/issue-33017.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-33017.rs:12:27 + | +LL | default type Output = Self; + | ^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/issue-33017.rs:8:31 + | +LL | type Output: From + Copy + Into; + | ^^^^ required by this bound in `UncheckedCopy::Output` +help: consider restricting type parameter `T` + | +LL | impl UncheckedCopy for T { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-35376.rs b/tests/ui/specialization/issue-35376.rs new file mode 100644 index 000000000..cc35213b9 --- /dev/null +++ b/tests/ui/specialization/issue-35376.rs @@ -0,0 +1,43 @@ +// check-pass +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +fn main() {} + +pub trait Alpha { } + +pub trait Beta { + type Event; +} + +pub trait Delta { + type Handle; + fn process(&self); +} + +pub struct Parent(A, T); + +impl Delta for Parent +where A: Alpha, + T: Delta, + T::Handle: Beta::Event> { + type Handle = Handle; + default fn process(&self) { + unimplemented!() + } +} + +impl Delta for Parent +where A: Alpha + Alpha, + T: Delta, + T::Handle: Beta::Event> { + fn process(&self) { + unimplemented!() + } +} + +pub struct Handle; + +impl Beta for Handle { + type Event = (); +} diff --git a/tests/ui/specialization/issue-35376.stderr b/tests/ui/specialization/issue-35376.stderr new file mode 100644 index 000000000..6c4167f3f --- /dev/null +++ b/tests/ui/specialization/issue-35376.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-35376.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-36804.rs b/tests/ui/specialization/issue-36804.rs new file mode 100644 index 000000000..89350602f --- /dev/null +++ b/tests/ui/specialization/issue-36804.rs @@ -0,0 +1,35 @@ +// check-pass +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +pub struct Cloned(I); + +impl<'a, I, T: 'a> Iterator for Cloned +where + I: Iterator, + T: Clone, +{ + type Item = T; + + fn next(&mut self) -> Option { + unimplemented!() + } + + default fn count(self) -> usize where Self: Sized { + self.fold(0, |cnt, _| cnt + 1) + } +} + +impl<'a, I, T: 'a> Iterator for Cloned +where + I: Iterator, + T: Copy, +{ + fn count(self) -> usize { + unimplemented!() + } +} + +fn main() { + let a = [1,2,3,4]; + Cloned(a.iter()).count(); +} diff --git a/tests/ui/specialization/issue-36804.stderr b/tests/ui/specialization/issue-36804.stderr new file mode 100644 index 000000000..c2113b25f --- /dev/null +++ b/tests/ui/specialization/issue-36804.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-36804.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-38091-2.rs b/tests/ui/specialization/issue-38091-2.rs new file mode 100644 index 000000000..9ed0b240d --- /dev/null +++ b/tests/ui/specialization/issue-38091-2.rs @@ -0,0 +1,28 @@ +// build-fail +//~^ ERROR overflow evaluating the requirement `i32: Check` + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Iterate<'a> { + type Ty: Valid; + fn iterate(self); +} +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ + default type Ty = (); + default fn iterate(self) {} +} + +trait Check {} +impl<'a, T> Check for T where >::Ty: Valid {} + +trait Valid {} + +impl Valid for () {} + +fn main() { + Iterate::iterate(0); +} diff --git a/tests/ui/specialization/issue-38091-2.stderr b/tests/ui/specialization/issue-38091-2.stderr new file mode 100644 index 000000000..5a05f9c27 --- /dev/null +++ b/tests/ui/specialization/issue-38091-2.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091-2.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0275]: overflow evaluating the requirement `i32: Check` + | +note: required for `i32` to implement `Iterate<'_>` + --> $DIR/issue-38091-2.rs:11:13 + | +LL | impl<'a, T> Iterate<'a> for T + | ^^^^^^^^^^^ ^ +LL | where +LL | T: Check, + | ----- unsatisfied trait bound introduced here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-38091.rs b/tests/ui/specialization/issue-38091.rs new file mode 100644 index 000000000..5b398368a --- /dev/null +++ b/tests/ui/specialization/issue-38091.rs @@ -0,0 +1,24 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Iterate<'a> { + type Ty: Valid; + fn iterate(self); +} +impl<'a, T> Iterate<'a> for T +where + T: Check, +{ + default type Ty = (); + //~^ ERROR the trait bound `(): Valid` is not satisfied + default fn iterate(self) {} +} + +trait Check {} +impl<'a, T> Check for T where >::Ty: Valid {} + +trait Valid {} + +fn main() { + Iterate::iterate(0); +} diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr new file mode 100644 index 000000000..f2210a407 --- /dev/null +++ b/tests/ui/specialization/issue-38091.stderr @@ -0,0 +1,25 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-38091.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `(): Valid` is not satisfied + --> $DIR/issue-38091.rs:12:23 + | +LL | default type Ty = (); + | ^^ the trait `Valid` is not implemented for `()` + | +note: required by a bound in `Iterate::Ty` + --> $DIR/issue-38091.rs:5:14 + | +LL | type Ty: Valid; + | ^^^^^ required by this bound in `Iterate::Ty` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-39448.rs b/tests/ui/specialization/issue-39448.rs new file mode 100644 index 000000000..a15c4bd6b --- /dev/null +++ b/tests/ui/specialization/issue-39448.rs @@ -0,0 +1,50 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Regression test for a specialization-related ICE (#39448). + +trait A: Sized { + fn foo(self, _: Self) -> Self { + self + } +} + +impl A for u8 {} +impl A for u16 {} + +impl FromA for u16 { + fn from(x: u8) -> u16 { + x as u16 + } +} + +trait FromA { + fn from(t: T) -> Self; +} + +impl> FromA for U { + default fn from(x: T) -> Self { + ToA::to(x) + } +} + +trait ToA { + fn to(self) -> T; +} + +impl ToA for T +where + U: FromA, +{ + fn to(self) -> U { + U::from(self) + } +} + +#[allow(dead_code)] +fn foo(x: T, y: U) -> U { + x.foo(y.to()).to() //~ ERROR overflow evaluating the requirement +} + +fn main() { + let z = foo(8u8, 1u16); +} diff --git a/tests/ui/specialization/issue-39448.stderr b/tests/ui/specialization/issue-39448.stderr new file mode 100644 index 000000000..9ce51d113 --- /dev/null +++ b/tests/ui/specialization/issue-39448.stderr @@ -0,0 +1,35 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-39448.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0275]: overflow evaluating the requirement `T: FromA` + --> $DIR/issue-39448.rs:45:13 + | +LL | x.foo(y.to()).to() + | ^^ + | +note: required for `T` to implement `FromA` + --> $DIR/issue-39448.rs:24:29 + | +LL | impl> FromA for U { + | -------- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `U` to implement `ToA` + --> $DIR/issue-39448.rs:34:12 + | +LL | impl ToA for T + | ^^^^^^ ^ +LL | where +LL | U: FromA, + | -------- unsatisfied trait bound introduced here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-39618.rs b/tests/ui/specialization/issue-39618.rs new file mode 100644 index 000000000..72630ee9c --- /dev/null +++ b/tests/ui/specialization/issue-39618.rs @@ -0,0 +1,27 @@ +// Regression test for #39618, shouldn't crash. +// FIXME(JohnTitor): Centril pointed out this looks suspicions, we should revisit here. +// More context: https://github.com/rust-lang/rust/pull/69192#discussion_r379846796 + +// check-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn foo(&self); +} + +trait Bar { + fn bar(&self); +} + +impl Bar for T where T: Foo { + fn bar(&self) {} +} + +impl Foo for T where T: Bar { + fn foo(&self) {} +} + +impl Foo for u64 {} + +fn main() {} diff --git a/tests/ui/specialization/issue-39618.stderr b/tests/ui/specialization/issue-39618.stderr new file mode 100644 index 000000000..19de60c7c --- /dev/null +++ b/tests/ui/specialization/issue-39618.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-39618.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-43037.current.stderr b/tests/ui/specialization/issue-43037.current.stderr new file mode 100644 index 000000000..26db9d7c9 --- /dev/null +++ b/tests/ui/specialization/issue-43037.current.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/issue-43037.rs:19:6 + | +LL | impl From< as Z>::Assoc> for T {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/specialization/issue-43037.negative.stderr b/tests/ui/specialization/issue-43037.negative.stderr new file mode 100644 index 000000000..26db9d7c9 --- /dev/null +++ b/tests/ui/specialization/issue-43037.negative.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/issue-43037.rs:19:6 + | +LL | impl From< as Z>::Assoc> for T {} + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/specialization/issue-43037.rs b/tests/ui/specialization/issue-43037.rs new file mode 100644 index 000000000..a1e3f998b --- /dev/null +++ b/tests/ui/specialization/issue-43037.rs @@ -0,0 +1,22 @@ +// revisions: current negative +#![feature(specialization)] +#![cfg_attr(negative, feature(with_negative_coherence))] +#![allow(incomplete_features)] + +trait X {} +trait Y: X {} +trait Z { + type Assoc: Y; +} +struct A(T); + +impl Y for T where T: X {} +impl Z for A { + type Assoc = T; +} + +// this impl is invalid, but causes an ICE anyway +impl From< as Z>::Assoc> for T {} +//~^ ERROR type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + +fn main() {} diff --git a/tests/ui/specialization/issue-44861.rs b/tests/ui/specialization/issue-44861.rs new file mode 100644 index 000000000..79d9b9490 --- /dev/null +++ b/tests/ui/specialization/issue-44861.rs @@ -0,0 +1,40 @@ +#![crate_type = "lib"] +#![feature(specialization)] +#![feature(unsize, coerce_unsized)] +#![allow(incomplete_features)] + +use std::ops::CoerceUnsized; + +pub struct SmartassPtr(A::Data); + +pub trait Smartass { + type Data; + type Data2: CoerceUnsized<*const [u8]>; +} + +pub trait MaybeObjectSafe {} + +impl MaybeObjectSafe for () {} + +impl Smartass for T { + type Data = ::Data2; + default type Data2 = (); + //~^ ERROR: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied +} + +impl Smartass for () { + type Data2 = *const [u8; 1]; +} + +impl Smartass for dyn MaybeObjectSafe { + type Data = *const [u8]; + type Data2 = *const [u8; 0]; +} + +impl CoerceUnsized> for SmartassPtr + where ::Data: std::ops::CoerceUnsized<::Data> +{} + +pub fn conv(s: SmartassPtr<()>) -> SmartassPtr { + s +} diff --git a/tests/ui/specialization/issue-44861.stderr b/tests/ui/specialization/issue-44861.stderr new file mode 100644 index 000000000..1941d40fe --- /dev/null +++ b/tests/ui/specialization/issue-44861.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): CoerceUnsized<*const [u8]>` is not satisfied + --> $DIR/issue-44861.rs:21:26 + | +LL | default type Data2 = (); + | ^^ the trait `CoerceUnsized<*const [u8]>` is not implemented for `()` + | +note: required by a bound in `Smartass::Data2` + --> $DIR/issue-44861.rs:12:17 + | +LL | type Data2: CoerceUnsized<*const [u8]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Smartass::Data2` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-45814.current.stderr b/tests/ui/specialization/issue-45814.current.stderr new file mode 100644 index 000000000..5013559b8 --- /dev/null +++ b/tests/ui/specialization/issue-45814.current.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `T: Trait<_>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`) +note: required for `T` to implement `Trait<_>` + --> $DIR/issue-45814.rs:9:20 + | +LL | default impl Trait for U {} + | ^^^^^^^^ ^ + = note: 128 redundant requirements hidden + = note: required for `T` to implement `Trait<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-45814.negative.stderr b/tests/ui/specialization/issue-45814.negative.stderr new file mode 100644 index 000000000..5013559b8 --- /dev/null +++ b/tests/ui/specialization/issue-45814.negative.stderr @@ -0,0 +1,14 @@ +error[E0275]: overflow evaluating the requirement `T: Trait<_>` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`) +note: required for `T` to implement `Trait<_>` + --> $DIR/issue-45814.rs:9:20 + | +LL | default impl Trait for U {} + | ^^^^^^^^ ^ + = note: 128 redundant requirements hidden + = note: required for `T` to implement `Trait<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/issue-45814.rs b/tests/ui/specialization/issue-45814.rs new file mode 100644 index 000000000..fce236390 --- /dev/null +++ b/tests/ui/specialization/issue-45814.rs @@ -0,0 +1,13 @@ +//~ ERROR overflow evaluating the requirement `T: Trait<_>` +// revisions: current negative +#![feature(specialization)] +#![cfg_attr(negative, feature(with_negative_coherence))] +#![allow(incomplete_features)] + +pub trait Trait {} + +default impl Trait for U {} + +impl Trait<::Item> for T {} + +fn main() {} diff --git a/tests/ui/specialization/issue-50452-fail.rs b/tests/ui/specialization/issue-50452-fail.rs new file mode 100644 index 000000000..fe21e9b6e --- /dev/null +++ b/tests/ui/specialization/issue-50452-fail.rs @@ -0,0 +1,21 @@ +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +pub trait Foo { + fn foo(); +} + +impl Foo for i32 {} +impl Foo for i64 { + fn foo() {} + //~^ERROR `foo` specializes an item from a parent `impl` +} +impl Foo for T { + fn foo() {} +} + +fn main() { + i32::foo(); + i64::foo(); + u8::foo(); +} diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr new file mode 100644 index 000000000..5c136adc4 --- /dev/null +++ b/tests/ui/specialization/issue-50452-fail.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50452-fail.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/issue-50452-fail.rs:10:5 + | +LL | fn foo() {} + | ^^^^^^^^^^^ cannot specialize default item `foo` +... +LL | impl Foo for T { + | ----------------- parent `impl` is here + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/issue-50452.rs b/tests/ui/specialization/issue-50452.rs new file mode 100644 index 000000000..29fc12066 --- /dev/null +++ b/tests/ui/specialization/issue-50452.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +pub trait Foo { + fn foo(); +} + +impl Foo for i32 {} +impl Foo for i64 {} +impl Foo for T { + fn foo() {} +} + +fn main() { + i32::foo(); + i64::foo(); + u8::foo(); +} diff --git a/tests/ui/specialization/issue-50452.stderr b/tests/ui/specialization/issue-50452.stderr new file mode 100644 index 000000000..48cab9dcd --- /dev/null +++ b/tests/ui/specialization/issue-50452.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50452.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-51892.rs b/tests/ui/specialization/issue-51892.rs new file mode 100644 index 000000000..5c0625414 --- /dev/null +++ b/tests/ui/specialization/issue-51892.rs @@ -0,0 +1,18 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(specialization)] + +pub trait Trait { + type Type; +} + +impl Trait for T { + default type Type = [u8; 1]; +} + +impl Trait for *const T { + type Type = [u8; std::mem::size_of::<::Type>()]; + //~^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/specialization/issue-51892.stderr b/tests/ui/specialization/issue-51892.stderr new file mode 100644 index 000000000..cb46db836 --- /dev/null +++ b/tests/ui/specialization/issue-51892.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-51892.rs:14:17 + | +LL | type Type = [u8; std::mem::size_of::<::Type>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<::Type>()]:` + +error: aborting due to previous error + diff --git a/tests/ui/specialization/issue-52050.rs b/tests/ui/specialization/issue-52050.rs new file mode 100644 index 000000000..804658702 --- /dev/null +++ b/tests/ui/specialization/issue-52050.rs @@ -0,0 +1,32 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Regression test for #52050: when inserting the blanket impl `I` +// into the tree, we had to replace the child node for `Foo`, which +// led to the structure of the tree being messed up. + +use std::iter::Iterator; + +trait IntoPyDictPointer { } + +struct Foo { } + +impl Iterator for Foo { + type Item = (); + fn next(&mut self) -> Option<()> { + None + } +} + +impl IntoPyDictPointer for Foo { } + +impl IntoPyDictPointer for I +where + I: Iterator, +{ +} + +impl IntoPyDictPointer for () //~ ERROR conflicting implementations +{ +} + +fn main() { } diff --git a/tests/ui/specialization/issue-52050.stderr b/tests/ui/specialization/issue-52050.stderr new file mode 100644 index 000000000..c263fe467 --- /dev/null +++ b/tests/ui/specialization/issue-52050.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-52050.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()` + --> $DIR/issue-52050.rs:28:1 + | +LL | impl IntoPyDictPointer for I + | ------------------------------- first implementation here +... +LL | impl IntoPyDictPointer for () + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/issue-59435.rs b/tests/ui/specialization/issue-59435.rs new file mode 100644 index 000000000..323900256 --- /dev/null +++ b/tests/ui/specialization/issue-59435.rs @@ -0,0 +1,17 @@ +#![feature(specialization)] +#![allow(incomplete_features)] + +struct MyStruct {} + +trait MyTrait { + type MyType: Default; +} + +impl MyTrait for i32 { + default type MyType = MyStruct; + //~^ ERROR: the trait bound `MyStruct: Default` is not satisfied +} + +fn main() { + let _x: ::MyType = ::MyType::default(); +} diff --git a/tests/ui/specialization/issue-59435.stderr b/tests/ui/specialization/issue-59435.stderr new file mode 100644 index 000000000..211459406 --- /dev/null +++ b/tests/ui/specialization/issue-59435.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `MyStruct: Default` is not satisfied + --> $DIR/issue-59435.rs:11:27 + | +LL | default type MyType = MyStruct; + | ^^^^^^^^ the trait `Default` is not implemented for `MyStruct` + | +note: required by a bound in `MyTrait::MyType` + --> $DIR/issue-59435.rs:7:18 + | +LL | type MyType: Default; + | ^^^^^^^ required by this bound in `MyTrait::MyType` +help: consider annotating `MyStruct` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/issue-63716-parse-async.rs b/tests/ui/specialization/issue-63716-parse-async.rs new file mode 100644 index 000000000..10f185c33 --- /dev/null +++ b/tests/ui/specialization/issue-63716-parse-async.rs @@ -0,0 +1,14 @@ +// Ensure that `default async fn` will parse. +// See issue #63716 for details. + +// check-pass +// edition:2018 + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +fn main() {} + +#[cfg(FALSE)] +impl Foo for Bar { + default async fn baz() {} +} diff --git a/tests/ui/specialization/issue-63716-parse-async.stderr b/tests/ui/specialization/issue-63716-parse-async.stderr new file mode 100644 index 000000000..a00572da8 --- /dev/null +++ b/tests/ui/specialization/issue-63716-parse-async.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-63716-parse-async.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.rs b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs new file mode 100644 index 000000000..d11ec7983 --- /dev/null +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.rs @@ -0,0 +1,23 @@ +// A regression test for #68830. This checks we don't emit +// a verbose `conflicting implementations` error. + +#![feature(specialization)] +#![allow(incomplete_features)] + +struct BadStruct { + err: MissingType //~ ERROR: cannot find type `MissingType` in this scope +} + +trait MyTrait { + fn foo(); +} + +impl MyTrait for D { + default fn foo() {} +} + +impl MyTrait for BadStruct { + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr new file mode 100644 index 000000000..833f61dca --- /dev/null +++ b/tests/ui/specialization/issue-68830-spurious-diagnostics.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/issue-68830-spurious-diagnostics.rs:8:10 + | +LL | err: MissingType + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/specialization/issue-70442.rs b/tests/ui/specialization/issue-70442.rs new file mode 100644 index 000000000..d41b5355c --- /dev/null +++ b/tests/ui/specialization/issue-70442.rs @@ -0,0 +1,23 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// check-pass + +trait Trait { + type Assoc; +} + +impl Trait for T { + default type Assoc = bool; +} + +// This impl inherits the `Assoc` definition from above and "locks it in", or finalizes it, making +// child impls unable to further specialize it. However, since the specialization graph didn't +// correctly track this, we would refuse to project `Assoc` from this impl, even though that should +// happen for items that are final. +impl Trait for () {} + +fn foo>() {} + +fn main() { + foo::<()>(); // `<() as Trait>::Assoc` is normalized to `bool` correctly +} diff --git a/tests/ui/specialization/issue-70442.stderr b/tests/ui/specialization/issue-70442.stderr new file mode 100644 index 000000000..aa72c3286 --- /dev/null +++ b/tests/ui/specialization/issue-70442.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-70442.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs new file mode 100644 index 000000000..6ec0d261d --- /dev/null +++ b/tests/ui/specialization/min_specialization/auxiliary/specialization-trait.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +pub trait SpecTrait { + fn method(&self); +} diff --git a/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs new file mode 100644 index 000000000..03cab00b0 --- /dev/null +++ b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.rs @@ -0,0 +1,32 @@ +// Test that associated types in trait objects are not considered to be +// constrained. + +#![feature(min_specialization)] + +trait Specializable { + fn f(); +} + +trait B { + type Y; +} + +trait C { + type Y; +} + +impl Specializable for A { + default fn f() {} +} + +impl<'a, T> Specializable for dyn B + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +impl<'a, T> Specializable for dyn C + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr new file mode 100644 index 000000000..db5558f16 --- /dev/null +++ b/tests/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr @@ -0,0 +1,14 @@ +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:22:1 + | +LL | impl<'a, T> Specializable for dyn B + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:27:1 + | +LL | impl<'a, T> Specializable for dyn C + 'a { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs b/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs new file mode 100644 index 000000000..77a64320d --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.rs @@ -0,0 +1,7 @@ +#![feature(min_specialization)] + +trait Trait {} +impl Trait for NonExistent {} +//~^ ERROR cannot find type `NonExistent` in this scope + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr new file mode 100644 index 000000000..b032ccbe5 --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl-on-nonexisting.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `NonExistent` in this scope + --> $DIR/impl-on-nonexisting.rs:4:16 + | +LL | impl Trait for NonExistent {} + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.rs b/tests/ui/specialization/min_specialization/impl_specialization_trait.rs new file mode 100644 index 000000000..723ed71c3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.rs @@ -0,0 +1,16 @@ +// Check that specialization traits can't be implemented without a feature. + +// gate-test-min_specialization + +// aux-build:specialization-trait.rs + +extern crate specialization_trait; + +struct A {} + +impl specialization_trait::SpecTrait for A { + //~^ ERROR implementing `rustc_specialization_trait` traits is unstable + fn method(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr new file mode 100644 index 000000000..934103d49 --- /dev/null +++ b/tests/ui/specialization/min_specialization/impl_specialization_trait.stderr @@ -0,0 +1,10 @@ +error: implementing `rustc_specialization_trait` traits is unstable + --> $DIR/impl_specialization_trait.rs:11:1 + | +LL | impl specialization_trait::SpecTrait for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(min_specialization)]` to the crate attributes to enable + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs new file mode 100644 index 000000000..98d7f9194 --- /dev/null +++ b/tests/ui/specialization/min_specialization/implcit-well-formed-bounds.rs @@ -0,0 +1,30 @@ +// Test that specializing on the well-formed predicates of the trait and +// self-type of an impl is allowed. + +// check-pass + +#![feature(min_specialization)] + +struct OrdOnly(T); + +trait SpecTrait { + fn f(); +} + +impl SpecTrait for T { + default fn f() {} +} + +impl SpecTrait<()> for OrdOnly { + fn f() {} +} + +impl SpecTrait> for () { + fn f() {} +} + +impl SpecTrait<(OrdOnly, OrdOnly)> for &[OrdOnly] { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/issue-79224.rs b/tests/ui/specialization/min_specialization/issue-79224.rs new file mode 100644 index 000000000..104bddd07 --- /dev/null +++ b/tests/ui/specialization/min_specialization/issue-79224.rs @@ -0,0 +1,26 @@ +#![feature(min_specialization)] +use std::fmt::{self, Display}; + +pub enum Cow<'a, B: ?Sized + 'a, O = ::Owned> +where + B: ToOwned, +{ + Borrowed(&'a B), + Owned(O), +} + +impl ToString for Cow<'_, str> { + fn to_string(&self) -> String { + String::new() + } +} + +impl Display for Cow<'_, B> { + //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] + write!(f, "foo") + } +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr new file mode 100644 index 000000000..505baa23c --- /dev/null +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `B: Clone` is not satisfied + --> $DIR/issue-79224.rs:18:29 + | +LL | impl Display for Cow<'_, B> { + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | + = note: required for `B` to implement `ToOwned` +help: consider further restricting this bound + | +LL | impl Display for Cow<'_, B> { + | +++++++++++++++++++ + +error[E0277]: the trait bound `B: Clone` is not satisfied + --> $DIR/issue-79224.rs:20:12 + | +LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + | ^^^^^ the trait `Clone` is not implemented for `B` + | + = note: required for `B` to implement `ToOwned` +help: consider further restricting this bound + | +LL | impl Display for Cow<'_, B> { + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.rs b/tests/ui/specialization/min_specialization/repeated_projection_type.rs new file mode 100644 index 000000000..f21f39f06 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeated_projection_type.rs @@ -0,0 +1,24 @@ +// Test that projection bounds can't be specialized on. + +#![feature(min_specialization)] + +trait X { + fn f(); +} +trait Id { + type This; +} +impl Id for T { + type This = T; +} + +impl X for T { + default fn f() {} +} + +impl> X for V { + //~^ ERROR cannot specialize on + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/repeated_projection_type.stderr b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr new file mode 100644 index 000000000..a751ba793 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on associated type `::This == (I,)` + --> $DIR/repeated_projection_type.rs:19:15 + | +LL | impl> X for V { + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.rs b/tests/ui/specialization/min_specialization/repeating_lifetimes.rs new file mode 100644 index 000000000..49bfacec0 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.rs @@ -0,0 +1,19 @@ +// Test that directly specializing on repeated lifetime parameters is not +// allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl<'a> X for (&'a u8, &'a u8) { + //~^ ERROR specializing impl repeats parameter `'a` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr new file mode 100644 index 000000000..16dccb10b --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_lifetimes.stderr @@ -0,0 +1,8 @@ +error: specializing impl repeats parameter `'a` + --> $DIR/repeating_lifetimes.rs:14:1 + | +LL | impl<'a> X for (&'a u8, &'a u8) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/repeating_param.rs b/tests/ui/specialization/min_specialization/repeating_param.rs new file mode 100644 index 000000000..5a1c97fd3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_param.rs @@ -0,0 +1,17 @@ +// Test that specializing on two type parameters being equal is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} +impl X for (T, T) { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/repeating_param.stderr b/tests/ui/specialization/min_specialization/repeating_param.stderr new file mode 100644 index 000000000..5e6adf723 --- /dev/null +++ b/tests/ui/specialization/min_specialization/repeating_param.stderr @@ -0,0 +1,8 @@ +error: specializing impl repeats parameter `T` + --> $DIR/repeating_param.rs:12:1 + | +LL | impl X for (T, T) { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/spec-iter.rs b/tests/ui/specialization/min_specialization/spec-iter.rs new file mode 100644 index 000000000..e17e9dd5f --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-iter.rs @@ -0,0 +1,20 @@ +// Check that we can specialize on a concrete iterator type. This requires us +// to consider which parameters in the parent impl are constrained. + +// check-pass + +#![feature(min_specialization)] + +trait SpecFromIter { + fn f(&self); +} + +impl<'a, T: 'a, I: Iterator> SpecFromIter for I { + default fn f(&self) {} +} + +impl<'a, T> SpecFromIter for std::slice::Iter<'a, T> { + fn f(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs new file mode 100644 index 000000000..3bb2480e9 --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.rs @@ -0,0 +1,29 @@ +// Check that supertraits cannot be used to work around min_specialization +// limitations. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +trait HasMethod { + fn method(&self); +} + +#[rustc_unsafe_specialization_marker] +trait Marker: HasMethod {} + +trait Spec { + fn spec_me(&self); +} + +impl Spec for T { + default fn spec_me(&self) {} +} + +impl Spec for T { + //~^ ERROR cannot specialize on trait `HasMethod` + fn spec_me(&self) { + self.method(); + } +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr new file mode 100644 index 000000000..ba9d6bbe3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-marker-supertraits.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `HasMethod` + --> $DIR/spec-marker-supertraits.rs:22:9 + | +LL | impl Spec for T { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/spec-reference.rs b/tests/ui/specialization/min_specialization/spec-reference.rs new file mode 100644 index 000000000..377889e2c --- /dev/null +++ b/tests/ui/specialization/min_specialization/spec-reference.rs @@ -0,0 +1,19 @@ +// Check that lifetime parameters are allowed in specializing impls. + +// check-pass + +#![feature(min_specialization)] + +trait MySpecTrait { + fn f(); +} + +impl MySpecTrait for T { + default fn f() {} +} + +impl<'a, T: ?Sized> MySpecTrait for &'a T { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_marker.rs b/tests/ui/specialization/min_specialization/specialization_marker.rs new file mode 100644 index 000000000..93462d02e --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_marker.rs @@ -0,0 +1,17 @@ +// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits. + +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker { + fn f(); + //~^ ERROR marker traits +} + +#[rustc_unsafe_specialization_marker] +trait SpecMarker2 { + type X; + //~^ ERROR marker traits +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_marker.stderr b/tests/ui/specialization/min_specialization/specialization_marker.stderr new file mode 100644 index 000000000..b47c14f3c --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_marker.stderr @@ -0,0 +1,15 @@ +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:7:5 + | +LL | fn f(); + | ^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:13:5 + | +LL | type X; + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0714`. diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.rs b/tests/ui/specialization/min_specialization/specialization_super_trait.rs new file mode 100644 index 000000000..145f376ed --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_super_trait.rs @@ -0,0 +1,18 @@ +// Test that supertraits can't be assumed in impls of +// `rustc_specialization_trait`, as such impls would +// allow specializing on the supertrait. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker: Default { + fn f(); +} + +impl SpecMarker for T { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_super_trait.stderr b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr new file mode 100644 index 000000000..e93578662 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `Default` + --> $DIR/specialization_super_trait.rs:13:9 + | +LL | impl SpecMarker for T { + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/specialization_trait.rs b/tests/ui/specialization/min_specialization/specialization_trait.rs new file mode 100644 index 000000000..d597278d2 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_trait.rs @@ -0,0 +1,26 @@ +// Test that `rustc_specialization_trait` requires always applicable impls. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker { + fn f(); +} + +impl SpecMarker for &'static u8 { + //~^ ERROR cannot specialize + fn f() {} +} + +impl SpecMarker for (T, T) { + //~^ ERROR specializing impl + fn f() {} +} + +impl SpecMarker for [T] { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialization_trait.stderr b/tests/ui/specialization/min_specialization/specialization_trait.stderr new file mode 100644 index 000000000..bc87ae0f8 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialization_trait.stderr @@ -0,0 +1,20 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialization_trait.rs:11:1 + | +LL | impl SpecMarker for &'static u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: specializing impl repeats parameter `T` + --> $DIR/specialization_trait.rs:16:1 + | +LL | impl SpecMarker for (T, T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot specialize on trait `Clone` + --> $DIR/specialization_trait.rs:21:9 + | +LL | impl SpecMarker for [T] { + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/specialization/min_specialization/specialize_on_marker.rs b/tests/ui/specialization/min_specialization/specialize_on_marker.rs new file mode 100644 index 000000000..4219bd13b --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_marker.rs @@ -0,0 +1,24 @@ +// Test that specializing on a `rustc_unsafe_specialization_marker` trait is +// allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker {} + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl X for T { + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs new file mode 100644 index 000000000..abbab5c23 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_spec_trait.rs @@ -0,0 +1,27 @@ +// Test that specializing on a `rustc_specialization_trait` trait is allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecTrait { + fn g(&self); +} + +trait X { + fn f(&self); +} + +impl X for T { + default fn f(&self) {} +} + +impl X for T { + fn f(&self) { + self.g(); + } +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.rs b/tests/ui/specialization/min_specialization/specialize_on_static.rs new file mode 100644 index 000000000..dd1b05401 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_static.rs @@ -0,0 +1,18 @@ +// Test that directly specializing on `'static` is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for &'_ T { + default fn f() {} +} + +impl X for &'static u8 { + //~^ ERROR cannot specialize on `'static` lifetime + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_static.stderr b/tests/ui/specialization/min_specialization/specialize_on_static.stderr new file mode 100644 index 000000000..9a16798f1 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_static.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialize_on_static.rs:13:1 + | +LL | impl X for &'static u8 { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.rs b/tests/ui/specialization/min_specialization/specialize_on_trait.rs new file mode 100644 index 000000000..0588442c3 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_trait.rs @@ -0,0 +1,20 @@ +// Test that specializing on a trait is not allowed in general. + +#![feature(min_specialization)] + +trait SpecMarker {} + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl X for T { + //~^ ERROR cannot specialize on trait `SpecMarker` + fn f() {} +} + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/specialize_on_trait.stderr b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr new file mode 100644 index 000000000..7b79c7eb4 --- /dev/null +++ b/tests/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -0,0 +1,8 @@ +error: cannot specialize on trait `SpecMarker` + --> $DIR/specialize_on_trait.rs:15:9 + | +LL | impl X for T { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/specialization/non-defaulted-item-fail.rs b/tests/ui/specialization/non-defaulted-item-fail.rs new file mode 100644 index 000000000..b7d6ac829 --- /dev/null +++ b/tests/ui/specialization/non-defaulted-item-fail.rs @@ -0,0 +1,54 @@ +#![feature(specialization, associated_type_defaults)] +//~^ WARN the feature `specialization` is incomplete + +// Test that attempting to override a non-default method or one not in the +// parent impl causes an error. + +trait Foo { + type Ty = (); + const CONST: u8 = 123; + fn foo(&self) -> bool { true } +} + +// Specialization tree for Foo: +// +// Box Vec +// / \ / \ +// Box Box Vec<()> Vec + +impl Foo for Box { + type Ty = bool; + const CONST: u8 = 0; + fn foo(&self) -> bool { false } +} + +// Allowed +impl Foo for Box {} + +// Can't override a non-`default` fn +impl Foo for Box { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + fn foo(&self) -> bool { true } +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + + +// Doesn't mention the item = provided body/value is used and the method is final. +impl Foo for Vec {} + +// Allowed +impl Foo for Vec<()> {} + +impl Foo for Vec { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + fn foo(&self) -> bool { true } +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + +fn main() {} diff --git a/tests/ui/specialization/non-defaulted-item-fail.stderr b/tests/ui/specialization/non-defaulted-item-fail.stderr new file mode 100644 index 000000000..faa14555a --- /dev/null +++ b/tests/ui/specialization/non-defaulted-item-fail.stderr @@ -0,0 +1,79 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-defaulted-item-fail.rs:1:12 + | +LL | #![feature(specialization, associated_type_defaults)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:30:5 + | +LL | impl Foo for Box { + | ---------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:32:5 + | +LL | impl Foo for Box { + | ---------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:34:5 + | +LL | impl Foo for Box { + | ---------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:46:5 + | +LL | impl Foo for Vec {} + | ---------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:48:5 + | +LL | impl Foo for Vec {} + | ---------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:50:5 + | +LL | impl Foo for Vec {} + | ---------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to 6 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs b/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs new file mode 100644 index 000000000..923dec892 --- /dev/null +++ b/tests/ui/specialization/soundness/partial_eq_range_inclusive.rs @@ -0,0 +1,35 @@ +// run-pass + +use std::cell::RefCell; +use std::cmp::Ordering; + +struct Evil<'a, 'b> { + values: RefCell>, + to_insert: &'b String, +} + +impl<'a, 'b> PartialEq for Evil<'a, 'b> { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl<'a> PartialOrd for Evil<'a, 'a> { + fn partial_cmp(&self, _other: &Self) -> Option { + self.values.borrow_mut().push(self.to_insert); + None + } +} + +fn main() { + let e; + let values; + { + let to_insert = String::from("Hello, world!"); + e = Evil { values: RefCell::new(Vec::new()), to_insert: &to_insert }; + let range = &e..=&e; + let _ = range == range; + values = e.values; + } + assert_eq!(*values.borrow(), Vec::<&str>::new()); +} diff --git a/tests/ui/specialization/soundness/partial_ord_slice.rs b/tests/ui/specialization/soundness/partial_ord_slice.rs new file mode 100644 index 000000000..b9e80a48d --- /dev/null +++ b/tests/ui/specialization/soundness/partial_ord_slice.rs @@ -0,0 +1,42 @@ +// Check that we aren't using unsound specialization in slice comparisons. + +// run-pass + +use std::cell::Cell; +use std::cmp::Ordering; + +struct Evil<'a, 'b>(Cell<(&'a [i32], &'b [i32])>); + +impl PartialEq for Evil<'_, '_> { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Eq for Evil<'_, '_> {} + +impl PartialOrd for Evil<'_, '_> { + fn partial_cmp(&self, _other: &Self) -> Option { + Some(Ordering::Equal) + } +} + +impl<'a> Ord for Evil<'a, 'a> { + fn cmp(&self, _other: &Self) -> Ordering { + let (a, b) = self.0.get(); + self.0.set((b, a)); + Ordering::Equal + } +} + +fn main() { + let x = &[1, 2, 3, 4]; + let u = { + let a = Box::new([7, 8, 9, 10]); + let y = [Evil(Cell::new((x, &*a)))]; + let _ = &y[..] <= &y[..]; + let [Evil(c)] = y; + c.get().0 + }; + assert_eq!(u, &[1, 2, 3, 4]); +} diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.rs b/tests/ui/specialization/specialization-allowed-cross-crate.rs new file mode 100644 index 000000000..5d67160eb --- /dev/null +++ b/tests/ui/specialization/specialization-allowed-cross-crate.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// aux-build:go_trait.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.stderr b/tests/ui/specialization/specialization-allowed-cross-crate.stderr new file mode 100644 index 000000000..3eea4a53b --- /dev/null +++ b/tests/ui/specialization/specialization-allowed-cross-crate.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-allowed-cross-crate.rs:8:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-assoc-fns.rs b/tests/ui/specialization/specialization-assoc-fns.rs new file mode 100644 index 000000000..cbfcb4719 --- /dev/null +++ b/tests/ui/specialization/specialization-assoc-fns.rs @@ -0,0 +1,29 @@ +// run-pass + +// Test that non-method associated functions can be specialized + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + fn mk() -> Self; +} + +impl Foo for T { + default fn mk() -> T { + T::default() + } +} + +impl Foo for Vec { + fn mk() -> Vec { + vec![0] + } +} + +fn main() { + let v1: Vec = Foo::mk(); + let v2: Vec = Foo::mk(); + + assert!(v1.len() == 0); + assert!(v2.len() == 1); +} diff --git a/tests/ui/specialization/specialization-assoc-fns.stderr b/tests/ui/specialization/specialization-assoc-fns.stderr new file mode 100644 index 000000000..69f7cece7 --- /dev/null +++ b/tests/ui/specialization/specialization-assoc-fns.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-assoc-fns.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-basics.rs b/tests/ui/specialization/specialization-basics.rs new file mode 100644 index 000000000..721c934db --- /dev/null +++ b/tests/ui/specialization/specialization-basics.rs @@ -0,0 +1,98 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Tests a variety of basic specialization scenarios and method +// dispatch for them. + +trait Foo { + fn foo(&self) -> &'static str; +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl Foo for (T, T) { + default fn foo(&self) -> &'static str { + "generic uniform pair" + } +} + +impl Foo for (u8, u32) { + default fn foo(&self) -> &'static str { + "(u8, u32)" + } +} + +impl Foo for (u8, u8) { + default fn foo(&self) -> &'static str { + "(u8, u8)" + } +} + +impl Foo for Vec { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec { + fn foo(&self) -> &'static str { + "Vec" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +struct NotClone; + +trait MyMarker {} +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +fn main() { + assert!(NotClone.foo() == "generic"); + assert!(0u8.foo() == "generic Clone"); + assert!(vec![NotClone].foo() == "generic"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); + assert!(MarkedAndClone.foo() == "generic Clone + MyMarker"); +} diff --git a/tests/ui/specialization/specialization-basics.stderr b/tests/ui/specialization/specialization-basics.stderr new file mode 100644 index 000000000..7714d4af4 --- /dev/null +++ b/tests/ui/specialization/specialization-basics.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-basics.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-cross-crate-no-gate.rs b/tests/ui/specialization/specialization-cross-crate-no-gate.rs new file mode 100644 index 000000000..f744b16de --- /dev/null +++ b/tests/ui/specialization/specialization-cross-crate-no-gate.rs @@ -0,0 +1,21 @@ +// run-pass + +// Test that specialization works even if only the upstream crate enables it + +// aux-build:specialization_cross_crate.rs + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +fn main() { + assert!(0u8.foo() == "generic Clone"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); +} diff --git a/tests/ui/specialization/specialization-cross-crate.rs b/tests/ui/specialization/specialization-cross-crate.rs new file mode 100644 index 000000000..d9381d661 --- /dev/null +++ b/tests/ui/specialization/specialization-cross-crate.rs @@ -0,0 +1,50 @@ +// run-pass + +// aux-build:specialization_cross_crate.rs + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +struct NotClone; + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +struct MyType(#[allow(unused_tuple_struct_fields)] T); +impl Foo for MyType { + default fn foo(&self) -> &'static str { + "generic MyType" + } +} + +impl Foo for MyType { + fn foo(&self) -> &'static str { + "MyType" + } +} + +struct MyOtherType; +impl Foo for MyOtherType {} + +fn main() { + assert!(NotClone.foo() == "generic"); + assert!(0u8.foo() == "generic Clone"); + assert!(vec![NotClone].foo() == "generic"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); + assert!(MarkedAndClone.foo() == "generic Clone + MyMarker"); + + assert!(MyType(()).foo() == "generic MyType"); + assert!(MyType(0u8).foo() == "MyType"); + assert!(MyOtherType.foo() == "generic"); +} diff --git a/tests/ui/specialization/specialization-cross-crate.stderr b/tests/ui/specialization/specialization-cross-crate.stderr new file mode 100644 index 000000000..06818bb56 --- /dev/null +++ b/tests/ui/specialization/specialization-cross-crate.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-cross-crate.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-default-methods.rs b/tests/ui/specialization/specialization-default-methods.rs new file mode 100644 index 000000000..dcf68afa9 --- /dev/null +++ b/tests/ui/specialization/specialization-default-methods.rs @@ -0,0 +1,87 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Test that default methods are cascaded correctly + +// First, test only use of explicit `default` items: + +trait Foo { + fn foo(&self) -> bool; +} + +// Specialization tree for Foo: +// +// T +// / \ +// i32 i64 + +impl Foo for T { + default fn foo(&self) -> bool { false } +} + +impl Foo for i32 {} + +impl Foo for i64 { + fn foo(&self) -> bool { true } +} + +fn test_foo() { + assert!(!0i8.foo()); + assert!(!0i32.foo()); + assert!(0i64.foo()); +} + +// Next, test mixture of explicit `default` and provided methods: + +trait Bar { + fn bar(&self) -> i32 { 0 } +} + +// Specialization tree for Bar. +// Uses of $ designate that method is provided +// +// $Bar (the trait) +// | +// T +// /|\ +// / | \ +// / | \ +// / | \ +// / | \ +// / | \ +// $i32 &str $Vec +// /\ +// / \ +// Vec $Vec + +impl Bar for T { + default fn bar(&self) -> i32 { 0 } +} + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl Bar for Vec { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec {} +impl Bar for Vec { + fn bar(&self) -> i32 { 3 } +} + +fn test_bar() { + assert!(0u8.bar() == 0); + assert!(0i32.bar() == 1); + assert!("hello".bar() == 0); + assert!(vec![()].bar() == 2); + assert!(vec![0i32].bar() == 2); + assert!(vec![0i64].bar() == 3); +} + +fn main() { + test_foo(); + test_bar(); +} diff --git a/tests/ui/specialization/specialization-default-methods.stderr b/tests/ui/specialization/specialization-default-methods.stderr new file mode 100644 index 000000000..d78d30bd8 --- /dev/null +++ b/tests/ui/specialization/specialization-default-methods.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-methods.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-default-projection.rs b/tests/ui/specialization/specialization-default-projection.rs new file mode 100644 index 000000000..7f3ae9512 --- /dev/null +++ b/tests/ui/specialization/specialization-default-projection.rs @@ -0,0 +1,36 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Make sure we can't project defaulted associated types + +trait Foo { + type Assoc; +} + +impl Foo for T { + default type Assoc = (); +} + +impl Foo for u8 { + type Assoc = String; +} + +fn generic() -> ::Assoc { + // `T` could be some downstream crate type that specializes (or, + // for that matter, `u8`). + + () //~ ERROR mismatched types +} + +fn monomorphic() -> () { + // Even though we know that `()` is not specialized in a + // downstream crate, typeck refuses to project here. + + generic::<()>() //~ ERROR mismatched types +} + +fn main() { + // No error here, we CAN project from `u8`, as there is no `default` + // in that impl. + let s: String = generic::(); + println!("{}", s); // bad news if this all compiles +} diff --git a/tests/ui/specialization/specialization-default-projection.stderr b/tests/ui/specialization/specialization-default-projection.stderr new file mode 100644 index 000000000..b8b81876d --- /dev/null +++ b/tests/ui/specialization/specialization-default-projection.stderr @@ -0,0 +1,43 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-projection.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/specialization-default-projection.rs:21:5 + | +LL | fn generic() -> ::Assoc { + | ----------------- expected `::Assoc` because of return type +... +LL | () + | ^^ expected associated type, found `()` + | + = note: expected associated type `::Assoc` + found unit type `()` + = help: consider constraining the associated type `::Assoc` to `()` or calling a method that returns `::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0308]: mismatched types + --> $DIR/specialization-default-projection.rs:28:5 + | +LL | fn monomorphic() -> () { + | -- expected `()` because of return type +... +LL | generic::<()>() + | ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `<() as Foo>::Assoc` + = help: consider constraining the associated type `<() as Foo>::Assoc` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/specialization-default-types.rs b/tests/ui/specialization/specialization-default-types.rs new file mode 100644 index 000000000..346471f11 --- /dev/null +++ b/tests/ui/specialization/specialization-default-types.rs @@ -0,0 +1,35 @@ +// It should not be possible to use the concrete value of a defaulted +// associated type in the impl defining it -- otherwise, what happens +// if it's overridden? + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Example { + type Output; + fn generate(self) -> Self::Output; +} + +impl Example for T { + default type Output = Box; + default fn generate(self) -> Self::Output { + Box::new(self) //~ ERROR mismatched types + } +} + +impl Example for bool { + type Output = bool; + fn generate(self) -> bool { self } +} + +fn trouble(t: T) -> Box { + Example::generate(t) //~ ERROR mismatched types +} + +fn weaponize() -> bool { + let b: Box = trouble(true); + *b +} + +fn main() { + weaponize(); +} diff --git a/tests/ui/specialization/specialization-default-types.stderr b/tests/ui/specialization/specialization-default-types.stderr new file mode 100644 index 000000000..61a556a93 --- /dev/null +++ b/tests/ui/specialization/specialization-default-types.stderr @@ -0,0 +1,39 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-default-types.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/specialization-default-types.rs:15:9 + | +LL | default type Output = Box; + | ----------------------------- expected this associated type +LL | default fn generate(self) -> Self::Output { + | ------------ expected `::Output` because of return type +LL | Box::new(self) + | ^^^^^^^^^^^^^^ expected associated type, found struct `Box` + | + = note: expected associated type `::Output` + found struct `Box` + +error[E0308]: mismatched types + --> $DIR/specialization-default-types.rs:25:5 + | +LL | fn trouble(t: T) -> Box { + | ------ expected `Box` because of return type +LL | Example::generate(t) + | ^^^^^^^^^^^^^^^^^^^^ expected struct `Box`, found associated type + | + = note: expected struct `Box` + found associated type `::Output` + = help: consider constraining the associated type `::Output` to `Box` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/specialization-feature-gate-default.rs b/tests/ui/specialization/specialization-feature-gate-default.rs new file mode 100644 index 000000000..8bad3ac0a --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-default.rs @@ -0,0 +1,13 @@ +// Check that specialization must be ungated to use the `default` keyword + +// gate-test-specialization + +trait Foo { + fn foo(&self); +} + +impl Foo for T { + default fn foo(&self) {} //~ ERROR specialization is unstable +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr new file mode 100644 index 000000000..42dbb200c --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-default.stderr @@ -0,0 +1,12 @@ +error[E0658]: specialization is unstable + --> $DIR/specialization-feature-gate-default.rs:10:5 + | +LL | default fn foo(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.rs b/tests/ui/specialization/specialization-feature-gate-overlap.rs new file mode 100644 index 000000000..b83c84ab8 --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-overlap.rs @@ -0,0 +1,17 @@ +// Check that writing an overlapping impl is not allow unless specialization is ungated. + +// gate-test-specialization + +trait Foo { + fn foo(&self); +} + +impl Foo for T { + fn foo(&self) {} +} + +impl Foo for u8 { //~ ERROR E0119 + fn foo(&self) {} +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-overlap.stderr b/tests/ui/specialization/specialization-feature-gate-overlap.stderr new file mode 100644 index 000000000..9157ad0d4 --- /dev/null +++ b/tests/ui/specialization/specialization-feature-gate-overlap.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `u8` + --> $DIR/specialization-feature-gate-overlap.rs:13:1 + | +LL | impl Foo for T { + | ----------------- first implementation here +... +LL | impl Foo for u8 { + | ^^^^^^^^^^^^^^^ conflicting implementation for `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-no-default.rs b/tests/ui/specialization/specialization-no-default.rs new file mode 100644 index 000000000..ae739b235 --- /dev/null +++ b/tests/ui/specialization/specialization-no-default.rs @@ -0,0 +1,77 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Check a number of scenarios in which one impl tries to override another, +// without correctly using `default`. + +// Test 1: one layer of specialization, multiple methods, missing `default` + +trait Foo { + fn foo(&self); + fn bar(&self); +} + +impl Foo for T { + fn foo(&self) {} + fn bar(&self) {} +} + +impl Foo for u8 {} +impl Foo for u16 { + fn foo(&self) {} //~ ERROR E0520 +} +impl Foo for u32 { + fn bar(&self) {} //~ ERROR E0520 +} + +// Test 2: one layer of specialization, missing `default` on associated type + +trait Bar { + type T; +} + +impl Bar for T { + type T = u8; +} + +impl Bar for u8 { + type T = (); //~ ERROR E0520 +} + +// Test 3a: multiple layers of specialization, missing interior `default` + +trait Baz { + fn baz(&self); +} + +impl Baz for T { + default fn baz(&self) {} +} + +impl Baz for T { + fn baz(&self) {} +} + +impl Baz for i32 { + fn baz(&self) {} //~ ERROR E0520 +} + +// Test 3b: multiple layers of specialization, missing interior `default`, +// redundant `default` in bottom layer. + +trait Redundant { + fn redundant(&self); +} + +impl Redundant for T { + default fn redundant(&self) {} +} + +impl Redundant for T { + fn redundant(&self) {} +} + +impl Redundant for i32 { + default fn redundant(&self) {} //~ ERROR E0520 +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-no-default.stderr b/tests/ui/specialization/specialization-no-default.stderr new file mode 100644 index 000000000..842cec9c7 --- /dev/null +++ b/tests/ui/specialization/specialization-no-default.stderr @@ -0,0 +1,68 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-no-default.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:20:5 + | +LL | impl Foo for T { + | ----------------- parent `impl` is here +... +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:23:5 + | +LL | impl Foo for T { + | ----------------- parent `impl` is here +... +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar` + | + = note: to specialize, `bar` in the parent `impl` must be marked `default` + +error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:37:5 + | +LL | impl Bar for T { + | ----------------- parent `impl` is here +... +LL | type T = (); + | ^^^^^^^^^^^^ cannot specialize default item `T` + | + = note: to specialize, `T` in the parent `impl` must be marked `default` + +error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:55:5 + | +LL | impl Baz for T { + | ------------------------ parent `impl` is here +... +LL | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz` + | + = note: to specialize, `baz` in the parent `impl` must be marked `default` + +error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-no-default.rs:74:5 + | +LL | impl Redundant for T { + | ------------------------------ parent `impl` is here +... +LL | default fn redundant(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant` + | + = note: to specialize, `redundant` in the parent `impl` must be marked `default` + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0520`. diff --git a/tests/ui/specialization/specialization-on-projection.rs b/tests/ui/specialization/specialization-on-projection.rs new file mode 100644 index 000000000..be8dcc423 --- /dev/null +++ b/tests/ui/specialization/specialization-on-projection.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Ensure that specialization works for impls defined directly on a projection + +trait Foo {} + +trait Assoc { + type Item; +} + +impl Foo for T {} + +struct Struct; + +impl Assoc for Struct { + type Item = u8; +} + +impl Foo for Struct {} + +fn main() {} diff --git a/tests/ui/specialization/specialization-on-projection.stderr b/tests/ui/specialization/specialization-on-projection.stderr new file mode 100644 index 000000000..00fc7ffc5 --- /dev/null +++ b/tests/ui/specialization/specialization-on-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-on-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs new file mode 100644 index 000000000..cb7563e27 --- /dev/null +++ b/tests/ui/specialization/specialization-out-of-order.rs @@ -0,0 +1,19 @@ +// run-pass + +// Test that you can list the more specific impl before the more general one. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { + type Out; +} + +impl Foo for bool { + type Out = (); +} + +impl Foo for T { + default type Out = bool; +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-out-of-order.stderr b/tests/ui/specialization/specialization-out-of-order.stderr new file mode 100644 index 000000000..b524e00f0 --- /dev/null +++ b/tests/ui/specialization/specialization-out-of-order.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-out-of-order.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-overlap-hygiene.rs b/tests/ui/specialization/specialization-overlap-hygiene.rs new file mode 100644 index 000000000..93e7c8325 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-hygiene.rs @@ -0,0 +1,23 @@ +#![feature(decl_macro)] + +struct X; + +macro_rules! define_f_legacy { () => { + fn f() {} +}} +macro define_g_modern() { + fn g() {} +} + +impl X { + fn f() {} //~ ERROR duplicate definitions with name `f` + fn g() {} // OK +} +impl X { + define_f_legacy!(); +} +impl X { + define_g_modern!(); +} + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-hygiene.stderr b/tests/ui/specialization/specialization-overlap-hygiene.stderr new file mode 100644 index 000000000..81efd46cc --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-hygiene.stderr @@ -0,0 +1,12 @@ +error[E0592]: duplicate definitions with name `f` + --> $DIR/specialization-overlap-hygiene.rs:13:4 + | +LL | fn f() {} + | ------ other definition for `f` +... +LL | fn f() {} + | ^^^^^^ duplicate definitions for `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/specialization/specialization-overlap-negative.rs b/tests/ui/specialization/specialization-overlap-negative.rs new file mode 100644 index 000000000..550d37082 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-negative.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait MyTrait {} + +struct TestType(::std::marker::PhantomData); + +unsafe impl Send for TestType {} +impl !Send for TestType {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr new file mode 100644 index 000000000..1fe4869ff --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-negative.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-negative.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`: + --> $DIR/specialization-overlap-negative.rs:9:1 + | +LL | unsafe impl Send for TestType {} + | ------------------------------------------ positive implementation here +LL | impl !Send for TestType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs new file mode 100644 index 000000000..b07efb2a5 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -0,0 +1,25 @@ +// run-pass + +// Test that impls on projected self types can resolve overlap, even when the +// projections involve specialization, so long as the associated type is +// provided by the most specialized impl. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Assoc { + type Output; +} + +impl Assoc for T { + default type Output = bool; +} + +impl Assoc for u8 { type Output = u8; } +impl Assoc for u16 { type Output = u16; } + +trait Foo {} +impl Foo for u32 {} +impl Foo for ::Output {} +impl Foo for ::Output {} + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr new file mode 100644 index 000000000..708c0817f --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-projection.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-overlap.rs b/tests/ui/specialization/specialization-overlap.rs new file mode 100644 index 000000000..6bee22ceb --- /dev/null +++ b/tests/ui/specialization/specialization-overlap.rs @@ -0,0 +1,19 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Foo { fn foo() {} } +impl Foo for T {} +impl Foo for Vec {} //~ ERROR E0119 + +trait Bar { fn bar() {} } +impl Bar for (T, u8) {} +impl Bar for (u8, T) {} //~ ERROR E0119 + +trait Baz { fn baz() {} } +impl Baz for u8 {} +impl Baz for T {} //~ ERROR E0119 + +trait Qux { fn qux() {} } +impl Qux for T {} +impl Qux for T {} //~ ERROR E0119 + +fn main() {} diff --git a/tests/ui/specialization/specialization-overlap.stderr b/tests/ui/specialization/specialization-overlap.stderr new file mode 100644 index 000000000..098bf4a70 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap.stderr @@ -0,0 +1,45 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `Vec<_>` + --> $DIR/specialization-overlap.rs:5:1 + | +LL | impl Foo for T {} + | ------------------------ first implementation here +LL | impl Foo for Vec {} + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Vec<_>` + +error[E0119]: conflicting implementations of trait `Bar` for type `(u8, u8)` + --> $DIR/specialization-overlap.rs:9:1 + | +LL | impl Bar for (T, u8) {} + | ----------------------- first implementation here +LL | impl Bar for (u8, T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u8, u8)` + +error[E0119]: conflicting implementations of trait `Baz` for type `u8` + --> $DIR/specialization-overlap.rs:13:1 + | +LL | impl Baz for u8 {} + | --------------------- first implementation here +LL | impl Baz for T {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u8` + +error[E0119]: conflicting implementations of trait `Qux` + --> $DIR/specialization-overlap.rs:17:1 + | +LL | impl Qux for T {} + | ------------------------ first implementation here +LL | impl Qux for T {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-polarity.rs b/tests/ui/specialization/specialization-polarity.rs new file mode 100644 index 000000000..b3cd8255b --- /dev/null +++ b/tests/ui/specialization/specialization-polarity.rs @@ -0,0 +1,17 @@ +// Make sure specialization cannot change impl polarity + +#![feature(auto_traits)] +#![feature(negative_impls)] +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +auto trait Foo {} + +impl Foo for T {} +impl !Foo for u8 {} //~ ERROR E0751 + +auto trait Bar {} + +impl !Bar for T {} +impl Bar for u8 {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/specialization/specialization-polarity.stderr b/tests/ui/specialization/specialization-polarity.stderr new file mode 100644 index 000000000..f287018ba --- /dev/null +++ b/tests/ui/specialization/specialization-polarity.stderr @@ -0,0 +1,29 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-polarity.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`: + --> $DIR/specialization-polarity.rs:10:1 + | +LL | impl Foo for T {} + | ----------------- positive implementation here +LL | impl !Foo for u8 {} + | ^^^^^^^^^^^^^^^^ negative implementation here + +error[E0751]: found both positive and negative implementation of trait `Bar` for type `u8`: + --> $DIR/specialization-polarity.rs:15:1 + | +LL | impl !Bar for T {} + | ------------------ negative implementation here +LL | impl Bar for u8 {} + | ^^^^^^^^^^^^^^^ positive implementation here + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/specialization/specialization-projection-alias.rs b/tests/ui/specialization/specialization-projection-alias.rs new file mode 100644 index 000000000..f1f0b47bb --- /dev/null +++ b/tests/ui/specialization/specialization-projection-alias.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Regression test for ICE when combining specialized associated types and type +// aliases + +trait Id_ { + type Out; +} + +type Id = ::Out; + +impl Id_ for T { + default type Out = T; +} + +fn test_proection() { + let x: Id = panic!(); +} + +fn main() { + +} diff --git a/tests/ui/specialization/specialization-projection-alias.stderr b/tests/ui/specialization/specialization-projection-alias.stderr new file mode 100644 index 000000000..c94d9ed07 --- /dev/null +++ b/tests/ui/specialization/specialization-projection-alias.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-projection-alias.rs:5:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-projection.rs b/tests/ui/specialization/specialization-projection.rs new file mode 100644 index 000000000..78afe7a94 --- /dev/null +++ b/tests/ui/specialization/specialization-projection.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Make sure we *can* project non-defaulted associated types +// cf ui/specialization/specialization-default-projection.rs + +// First, do so without any use of specialization + +trait Foo { + type Assoc; +} + +impl Foo for T { + type Assoc = (); +} + +fn generic_foo() -> ::Assoc { + () +} + +// Next, allow for one layer of specialization + +trait Bar { + type Assoc; +} + +impl Bar for T { + default type Assoc = (); +} + +impl Bar for T { + type Assoc = u8; +} + +fn generic_bar_clone() -> ::Assoc { + 0u8 +} + +fn main() { +} diff --git a/tests/ui/specialization/specialization-projection.stderr b/tests/ui/specialization/specialization-projection.stderr new file mode 100644 index 000000000..bfc4e0a0f --- /dev/null +++ b/tests/ui/specialization/specialization-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs new file mode 100644 index 000000000..fb85d8019 --- /dev/null +++ b/tests/ui/specialization/specialization-supertraits.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +// Test that you can specialize via an explicit trait hierarchy + +// FIXME: this doesn't work yet... + +trait Parent {} +trait Child: Parent {} + +trait Foo {} + +impl Foo for T {} +impl Foo for T {} + +fn main() {} diff --git a/tests/ui/specialization/specialization-supertraits.stderr b/tests/ui/specialization/specialization-supertraits.stderr new file mode 100644 index 000000000..e716bc215 --- /dev/null +++ b/tests/ui/specialization/specialization-supertraits.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-supertraits.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs new file mode 100644 index 000000000..904aeaa08 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs @@ -0,0 +1,33 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Iterator { + fn next(&self); +} + +trait WithAssoc { + type Item; +} + +impl<'a> WithAssoc for &'a () { + type Item = &'a u32; +} + +struct Cloned(#[allow(unused_tuple_struct_fields)] I); + +impl<'a, I, T: 'a> Iterator for Cloned + where I: WithAssoc, T: Clone +{ + fn next(&self) {} +} + +impl<'a, I, T: 'a> Iterator for Cloned + where I: WithAssoc, T: Copy +{ + +} + +fn main() { + Cloned(&()).next(); +} diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr new file mode 100644 index 000000000..c7aad3c0f --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.rs b/tests/ui/specialization/specialization-translate-projections-with-params.rs new file mode 100644 index 000000000..62d63590a --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-params.rs @@ -0,0 +1,32 @@ +// run-pass + +// Ensure that provided items are inherited properly even when impls vary in +// type parameters *and* rely on projections, and the type parameters are input +// types on the trait. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Trait { + fn convert(&self) -> T; +} +trait WithAssoc { + type Item; + fn as_item(&self) -> &Self::Item; +} + +impl Trait for T where T: WithAssoc, U: Clone { + fn convert(&self) -> U { + self.as_item().clone() + } +} + +impl WithAssoc for u8 { + type Item = u8; + fn as_item(&self) -> &u8 { self } +} + +impl Trait for u8 {} + +fn main() { + assert!(3u8.convert() == 3u8); +} diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.stderr b/tests/ui/specialization/specialization-translate-projections-with-params.stderr new file mode 100644 index 000000000..1c4fd9325 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections-with-params.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections-with-params.rs:7:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/specialization-translate-projections.rs b/tests/ui/specialization/specialization-translate-projections.rs new file mode 100644 index 000000000..92ea9e2b8 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections.rs @@ -0,0 +1,33 @@ +// run-pass + +// Ensure that provided items are inherited properly even when impls vary in +// type parameters *and* rely on projections. + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +use std::convert::Into; + +trait Trait { + fn to_u8(&self) -> u8; +} +trait WithAssoc { + type Item; + fn to_item(&self) -> Self::Item; +} + +impl Trait for T where T: WithAssoc, U: Into { + fn to_u8(&self) -> u8 { + self.to_item().into() + } +} + +impl WithAssoc for u8 { + type Item = u8; + fn to_item(&self) -> u8 { *self } +} + +impl Trait for u8 {} + +fn main() { + assert!(3u8.to_u8() == 3u8); +} diff --git a/tests/ui/specialization/specialization-translate-projections.stderr b/tests/ui/specialization/specialization-translate-projections.stderr new file mode 100644 index 000000000..22bbb12a0 --- /dev/null +++ b/tests/ui/specialization/specialization-translate-projections.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-translate-projections.rs:6:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/transmute-specialization.rs b/tests/ui/specialization/transmute-specialization.rs new file mode 100644 index 000000000..499334d98 --- /dev/null +++ b/tests/ui/specialization/transmute-specialization.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Specializable { type Output; } + +impl Specializable for T { + default type Output = u16; +} + +fn main() { + unsafe { + std::mem::transmute::::Output>(0); + } +} diff --git a/tests/ui/specialization/transmute-specialization.stderr b/tests/ui/specialization/transmute-specialization.stderr new file mode 100644 index 000000000..b1c26d7da --- /dev/null +++ b/tests/ui/specialization/transmute-specialization.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/transmute-specialization.rs:3:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/sse2.rs b/tests/ui/sse2.rs new file mode 100644 index 000000000..172f40798 --- /dev/null +++ b/tests/ui/sse2.rs @@ -0,0 +1,25 @@ +// run-pass + +#![allow(stable_features)] +#![feature(cfg_target_feature)] + +use std::env; + +fn main() { + match env::var("TARGET") { + Ok(s) => { + // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled + if s.contains("i586") { + return + } + } + Err(_) => return, + } + if cfg!(any(target_arch = "x86", target_arch = "x86_64")) { + assert!(cfg!(target_feature = "sse2"), + "SSE2 was not detected as available on an x86 platform"); + } + // check a negative case too -- allowed on x86, but not enabled by default + assert!(cfg!(not(target_feature = "avx2")), + "AVX2 shouldn't be detected as available by default on any platform"); +} diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs new file mode 100644 index 000000000..f8bbe90cf --- /dev/null +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] +extern crate core; + +// Known accidental stabilizations with no known users, slated for un-stabilization +// fully stable @ core::char::UNICODE_VERSION +use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature 'unicode_internals' + +// Known accidental stabilizations with known users +// fully stable @ core::mem::transmute +use core::intrinsics::transmute; // depended upon by rand_core diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr new file mode 100644 index 000000000..ff733822c --- /dev/null +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unicode_internals' + --> $DIR/accidental-stable-in-unstable.rs:6:5 + | +LL | use core::unicode::UNICODE_VERSION; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unicode_internals)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/allow-unstable-reexport.rs b/tests/ui/stability-attribute/allow-unstable-reexport.rs new file mode 100644 index 000000000..937913954 --- /dev/null +++ b/tests/ui/stability-attribute/allow-unstable-reexport.rs @@ -0,0 +1,30 @@ +// Allow an unstable re-export without requiring a feature gate. +// #94972 + +// aux-build:lint-stability.rs +// aux-build:lint-stability-reexport.rs +#![feature(staged_api)] +#![stable(feature = "lint_stability", since = "1.0.0")] + +extern crate lint_stability; +extern crate lint_stability_reexport; + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub use lint_stability::unstable; + +// We want to confirm that using a re-export through another crate behaves +// the same way as using an item directly +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub use lint_stability_reexport::unstable_text; + +// Ensure items which aren't marked as unstable can't re-export unstable items +#[stable(feature = "lint_stability", since = "1.0.0")] +pub use lint_stability::unstable as unstable2; +//~^ ERROR use of unstable library feature 'unstable_test_feature' + +fn main() { + // Since we didn't enable the feature in this crate, we still can't + // use these items, even though they're in scope from the `use`s which are now allowed. + unstable(); //~ ERROR use of unstable library feature 'unstable_test_feature' + unstable_text(); //~ ERROR use of unstable library feature 'unstable_test_feature' +} diff --git a/tests/ui/stability-attribute/allow-unstable-reexport.stderr b/tests/ui/stability-attribute/allow-unstable-reexport.stderr new file mode 100644 index 000000000..a11da9dc8 --- /dev/null +++ b/tests/ui/stability-attribute/allow-unstable-reexport.stderr @@ -0,0 +1,27 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/allow-unstable-reexport.rs:22:9 + | +LL | pub use lint_stability::unstable as unstable2; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/allow-unstable-reexport.rs:28:5 + | +LL | unstable(); + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': text + --> $DIR/allow-unstable-reexport.rs:29:5 + | +LL | unstable_text(); + | ^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs new file mode 100644 index 000000000..ff0228e4d --- /dev/null +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -0,0 +1,9 @@ +// Test for new `#[rustc_allowed_through_unstable_modules]` attribute +// +// aux-build:allowed-through-unstable-core.rs +#![crate_type = "lib"] + +extern crate allowed_through_unstable_core; + +use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; +use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature 'unstable_test_feature' diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr new file mode 100644 index 000000000..132c00b89 --- /dev/null +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/allowed-through-unstable.rs:9:5 + | +LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs new file mode 100644 index 000000000..b597009a3 --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(rustc_attrs)] +#![stable(feature = "stable_test_feature", since = "1.2.0")] + +#[unstable(feature = "unstable_test_feature", issue = "1")] +pub mod unstable_module { + #[stable(feature = "stable_test_feature", since = "1.2.0")] + #[rustc_allowed_through_unstable_modules] + pub trait OldStableTraitAllowedThoughUnstable {} + + #[stable(feature = "stable_test_feature", since = "1.2.0")] + pub trait NewStableTraitNotAllowedThroughUnstable {} +} diff --git a/tests/ui/stability-attribute/auxiliary/ctor-stability.rs b/tests/ui/stability-attribute/auxiliary/ctor-stability.rs new file mode 100644 index 000000000..74c6023d7 --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/ctor-stability.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "none", since = "1.0")] + +#[stable(feature = "none", since = "1.0")] +pub enum Foo { + A, +} diff --git a/tests/ui/stability-attribute/auxiliary/default_body.rs b/tests/ui/stability-attribute/auxiliary/default_body.rs new file mode 100644 index 000000000..3a177419d --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/default_body.rs @@ -0,0 +1,29 @@ +#![crate_type = "lib"] +#![feature(staged_api, rustc_attrs)] +#![stable(feature = "stable_feature", since = "1.0.0")] + +#[stable(feature = "stable_feature", since = "1.0.0")] +pub trait JustTrait { + #[stable(feature = "stable_feature", since = "1.0.0")] + #[rustc_default_body_unstable(feature = "constant_default_body", issue = "none")] + const CONSTANT: usize = 0; + + #[rustc_default_body_unstable(feature = "fun_default_body", issue = "none")] + #[stable(feature = "stable_feature", since = "1.0.0")] + fn fun() {} +} + +#[rustc_must_implement_one_of(eq, neq)] +#[stable(feature = "stable_feature", since = "1.0.0")] +pub trait Equal { + #[rustc_default_body_unstable(feature = "eq_default_body", issue = "none")] + #[stable(feature = "stable_feature", since = "1.0.0")] + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + #[stable(feature = "stable_feature", since = "1.0.0")] + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} diff --git a/tests/ui/stability-attribute/auxiliary/lint-stability-reexport.rs b/tests/ui/stability-attribute/auxiliary/lint-stability-reexport.rs new file mode 100644 index 000000000..9884731d5 --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/lint-stability-reexport.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "lint_stability", since = "1.0.0")] + +extern crate lint_stability; + +// Re-exporting without enabling the feature "unstable_test_feature" in this crate +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub use lint_stability::unstable_text; diff --git a/tests/ui/stability-attribute/auxiliary/lint-stability.rs b/tests/ui/stability-attribute/auxiliary/lint-stability.rs new file mode 100644 index 000000000..99c29dcdd --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/lint-stability.rs @@ -0,0 +1,188 @@ +#![crate_name="lint_stability"] +#![crate_type = "lib"] +#![feature(staged_api)] +#![feature(associated_type_defaults)] +#![stable(feature = "lint_stability", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated() {} +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_text() {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "99.99.99", note = "text")] +pub fn deprecated_future() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_unstable() {} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub fn deprecated_unstable_text() {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub fn unstable() {} +#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] +pub fn unstable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable() {} +#[stable(feature = "rust1", since = "1.0.0")] +pub fn stable_text() {} + +#[stable(feature = "rust1", since = "1.0.0")] +pub struct MethodTester; + +impl MethodTester { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + pub fn method_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub fn method_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + pub fn method_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + pub fn method_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated(&self) {} + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + fn trait_deprecated_unstable_text(&self) {} + + #[unstable(feature = "unstable_test_feature", issue = "none")] + fn trait_unstable(&self) {} + #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")] + fn trait_unstable_text(&self) {} + + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable(&self) {} + #[stable(feature = "rust1", since = "1.0.0")] + fn trait_stable_text(&self) {} +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait TraitWithAssociatedTypes { + #[unstable(feature = "unstable_test_feature", issue = "none")] + type TypeUnstable = u8; + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + type TypeDeprecated = u8; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +impl Trait for MethodTester {} + +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub trait UnstableTrait { fn dummy(&self) { } } + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub trait DeprecatedTrait { + #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { } +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize +} +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub enum UnstableEnum {} +#[stable(feature = "rust1", since = "1.0.0")] +pub enum StableEnum {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableUnitStruct; +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableUnitStruct; +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableUnitStruct; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + #[deprecated(since = "1.0.0", note = "text")] + DeprecatedUnstableVariant, + #[unstable(feature = "unstable_test_feature", issue = "none")] + UnstableVariant, + + #[stable(feature = "rust1", since = "1.0.0")] + StableVariant, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +#[deprecated(since = "1.0.0", note = "text")] +pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[unstable(feature = "unstable_test_feature", issue = "none")] +pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); +#[stable(feature = "rust1", since = "1.0.0")] +pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test { + () => (deprecated()); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg { + ($func:expr) => ($func); +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[macro_export] +macro_rules! macro_test_arg_nested { + ($func:ident) => (macro_test_arg!($func())); +} diff --git a/tests/ui/stability-attribute/auxiliary/stability-attribute-implies.rs b/tests/ui/stability-attribute/auxiliary/stability-attribute-implies.rs new file mode 100644 index 000000000..468be1bc1 --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/stability-attribute-implies.rs @@ -0,0 +1,8 @@ +#![feature(staged_api)] +#![stable(feature = "stability_attribute_implies", since = "1.0.0")] + +#[stable(feature = "foo", since = "1.62.0")] +pub fn foo() {} + +#[unstable(feature = "foobar", issue = "1", implied_by = "foo")] +pub fn foobar() {} diff --git a/tests/ui/stability-attribute/auxiliary/stability_attribute_issue.rs b/tests/ui/stability-attribute/auxiliary/stability_attribute_issue.rs new file mode 100644 index 000000000..4e5333289 --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/stability_attribute_issue.rs @@ -0,0 +1,9 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.2.0")] + + +#[unstable(feature = "unstable_test_feature", issue = "1")] +pub fn unstable() {} + +#[unstable(feature = "unstable_test_feature", reason = "message", issue = "2")] +pub fn unstable_msg() {} diff --git a/tests/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs b/tests/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs new file mode 100644 index 000000000..e45b00f99 --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/stable-in-unstable-core.rs @@ -0,0 +1,8 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.2.0")] + +#[unstable(feature = "unstable_test_feature", issue = "1")] +pub mod new_unstable_module { + #[stable(feature = "stable_test_feature", since = "1.2.0")] + pub trait OldTrait {} +} diff --git a/tests/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs b/tests/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs new file mode 100644 index 000000000..28ad8c28d --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/stable-in-unstable-std.rs @@ -0,0 +1,11 @@ +#![feature(staged_api)] +#![feature(unstable_test_feature)] +#![stable(feature = "stable_test_feature", since = "1.2.0")] + +extern crate stable_in_unstable_core; + +#[stable(feature = "stable_test_feature", since = "1.2.0")] +pub mod old_stable_module { + #[stable(feature = "stable_test_feature", since = "1.2.0")] + pub use stable_in_unstable_core::new_unstable_module::OldTrait; +} diff --git a/tests/ui/stability-attribute/auxiliary/unstable_generic_param.rs b/tests/ui/stability-attribute/auxiliary/unstable_generic_param.rs new file mode 100644 index 000000000..1d6a6bd4e --- /dev/null +++ b/tests/ui/stability-attribute/auxiliary/unstable_generic_param.rs @@ -0,0 +1,229 @@ +#![crate_type = "lib"] +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait1<#[unstable(feature = "unstable_default", issue = "none")] T = ()> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + fn foo() -> T; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait2<#[unstable(feature = "unstable_default", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + fn foo() -> T; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Trait3 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + fn foo() -> T; +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct1<#[unstable(feature = "unstable_default", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: T, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct2 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: T, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct3 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field1: A, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field2: B, +} + +#[deprecated(since = "1.1.0", note = "test")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct4 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: A, +} + +#[deprecated(since = "1.1.0", note = "test")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct5<#[unstable(feature = "unstable_default", issue = "none")] A = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: A, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Struct6<#[unstable(feature = "unstable_default6", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub field: T, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT1: Struct1 = Struct1 { field: 1 }; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT2: Struct2 = Struct2 { field: 1 }; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT3: Struct3 = Struct3 { field1: 1, field2: 2 }; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT4: Struct4 = Struct4 { field: 1 }; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const STRUCT5: Struct5 = Struct5 { field: 1 }; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum1<#[unstable(feature = "unstable_default", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Some(#[stable(feature = "stable_test_feature", since = "1.0.0")] T), + #[stable(feature = "stable_test_feature", since = "1.0.0")] + None, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum2 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Some(#[stable(feature = "stable_test_feature", since = "1.0.0")] T), + #[stable(feature = "stable_test_feature", since = "1.0.0")] + None, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum3 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Ok(#[stable(feature = "stable_test_feature", since = "1.0.0")] T), + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Err(#[stable(feature = "stable_test_feature", since = "1.0.0")] E), +} + +#[deprecated(since = "1.1.0", note = "test")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum4 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Some(#[stable(feature = "stable_test_feature", since = "1.0.0")] T), + #[stable(feature = "stable_test_feature", since = "1.0.0")] + None, +} + +#[deprecated(since = "1.1.0", note = "test")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum5<#[unstable(feature = "unstable_default", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Some(#[stable(feature = "stable_test_feature", since = "1.0.0")] T), + #[stable(feature = "stable_test_feature", since = "1.0.0")] + None, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Enum6<#[unstable(feature = "unstable_default6", issue = "none")] T = usize> { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Some(#[stable(feature = "stable_test_feature", since = "1.0.0")] T), + #[stable(feature = "stable_test_feature", since = "1.0.0")] + None, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ENUM1: Enum1 = Enum1::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ENUM2: Enum2 = Enum2::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ENUM3: Enum3 = Enum3::Ok(1); +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ENUM3B: Enum3 = Enum3::Err(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ENUM4: Enum4 = Enum4::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ENUM5: Enum5 = Enum5::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub type Alias1<#[unstable(feature = "unstable_default", issue = "none")] T = usize> = Option; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub type Alias2 = Option; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub type Alias3 = + Result; + +#[deprecated(since = "1.1.0", note = "test")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub type Alias4 = Option; + +#[deprecated(since = "1.1.0", note = "test")] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub type Alias5<#[unstable(feature = "unstable_default", issue = "none")] T = usize> = Option; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub type Alias6<#[unstable(feature = "unstable_default6", issue = "none")] T = usize> = Option; + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ALIAS1: Alias1 = Alias1::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ALIAS2: Alias2 = Alias2::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ALIAS3: Alias3 = Alias3::Ok(1); +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ALIAS3B: Alias3 = Alias3::Err(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ALIAS4: Alias4 = Alias4::Some(1); + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub const ALIAS5: Alias5 = Alias5::Some(1); + + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub trait Alloc {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct System {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +impl Alloc for System {} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Box1 { + ptr: *mut T, + alloc: A, +} + +impl Box1 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new(mut t: T) -> Self { + unsafe { Self { ptr: &mut t, alloc: System {} } } + } +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Box2 { + ptr: *mut T, + alloc: A, +} + +impl Box2 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new(mut t: T) -> Self { + Self { ptr: &mut t, alloc: System {} } + } +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct Box3 { + ptr: *mut T, +} + +impl Box3 { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new(mut t: T) -> Self { + Self { ptr: &mut t } + } +} diff --git a/tests/ui/stability-attribute/ctor-stability.rs b/tests/ui/stability-attribute/ctor-stability.rs new file mode 100644 index 000000000..fcab0cb10 --- /dev/null +++ b/tests/ui/stability-attribute/ctor-stability.rs @@ -0,0 +1,8 @@ +// aux-build:ctor-stability.rs +// check-pass + +extern crate ctor_stability; + +fn main() { + let _ = ctor_stability::Foo::A; +} diff --git a/tests/ui/stability-attribute/default-body-stability-err.rs b/tests/ui/stability-attribute/default-body-stability-err.rs new file mode 100644 index 000000000..ecb281bcc --- /dev/null +++ b/tests/ui/stability-attribute/default-body-stability-err.rs @@ -0,0 +1,19 @@ +// aux-build:default_body.rs +#![crate_type = "lib"] + +extern crate default_body; + +use default_body::{Equal, JustTrait}; + +struct Type; + +impl JustTrait for Type {} +//~^ ERROR not all trait items implemented, missing: `CONSTANT` [E0046] +//~| ERROR not all trait items implemented, missing: `fun` [E0046] + +impl Equal for Type { + //~^ ERROR not all trait items implemented, missing: `eq` [E0046] + fn neq(&self, other: &Self) -> bool { + false + } +} diff --git a/tests/ui/stability-attribute/default-body-stability-err.stderr b/tests/ui/stability-attribute/default-body-stability-err.stderr new file mode 100644 index 000000000..ef666f30f --- /dev/null +++ b/tests/ui/stability-attribute/default-body-stability-err.stderr @@ -0,0 +1,38 @@ +error[E0046]: not all trait items implemented, missing: `CONSTANT` + --> $DIR/default-body-stability-err.rs:10:1 + | +LL | impl JustTrait for Type {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: default implementation of `CONSTANT` is unstable + = note: use of unstable library feature 'constant_default_body' + = help: add `#![feature(constant_default_body)]` to the crate attributes to enable + +error[E0046]: not all trait items implemented, missing: `fun` + --> $DIR/default-body-stability-err.rs:10:1 + | +LL | impl JustTrait for Type {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: default implementation of `fun` is unstable + = note: use of unstable library feature 'fun_default_body' + = help: add `#![feature(fun_default_body)]` to the crate attributes to enable + +error[E0046]: not all trait items implemented, missing: `eq` + --> $DIR/default-body-stability-err.rs:14:1 + | +LL | / impl Equal for Type { +LL | | +LL | | fn neq(&self, other: &Self) -> bool { +LL | | false +LL | | } +LL | | } + | |_^ + | + = note: default implementation of `eq` is unstable + = note: use of unstable library feature 'eq_default_body' + = help: add `#![feature(eq_default_body)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/stability-attribute/default-body-stability-ok-enables.rs b/tests/ui/stability-attribute/default-body-stability-ok-enables.rs new file mode 100644 index 000000000..bdc7522f4 --- /dev/null +++ b/tests/ui/stability-attribute/default-body-stability-ok-enables.rs @@ -0,0 +1,18 @@ +// check-pass +// aux-build:default_body.rs +#![crate_type = "lib"] +#![feature(fun_default_body, eq_default_body, constant_default_body)] + +extern crate default_body; + +use default_body::{Equal, JustTrait}; + +struct Type; + +impl JustTrait for Type {} + +impl Equal for Type { + fn neq(&self, other: &Self) -> bool { + false + } +} diff --git a/tests/ui/stability-attribute/default-body-stability-ok-impls.rs b/tests/ui/stability-attribute/default-body-stability-ok-impls.rs new file mode 100644 index 000000000..e1f5c0170 --- /dev/null +++ b/tests/ui/stability-attribute/default-body-stability-ok-impls.rs @@ -0,0 +1,21 @@ +// check-pass +// aux-build:default_body.rs +#![crate_type = "lib"] + +extern crate default_body; + +use default_body::{Equal, JustTrait}; + +struct Type; + +impl JustTrait for Type { + const CONSTANT: usize = 1; + + fn fun() {} +} + +impl Equal for Type { + fn eq(&self, other: &Self) -> bool { + false + } +} diff --git a/tests/ui/stability-attribute/generics-default-stability-trait.rs b/tests/ui/stability-attribute/generics-default-stability-trait.rs new file mode 100644 index 000000000..d436088e4 --- /dev/null +++ b/tests/ui/stability-attribute/generics-default-stability-trait.rs @@ -0,0 +1,33 @@ +// aux-build:unstable_generic_param.rs +#![feature(unstable_default6)] + +extern crate unstable_generic_param; + +use unstable_generic_param::*; + +struct R; + +impl Trait1 for S { + fn foo() -> () { () } // ok +} + +struct S; + +impl Trait1 for S { //~ ERROR use of unstable library feature 'unstable_default' + fn foo() -> usize { 0 } +} + +impl Trait1 for S { //~ ERROR use of unstable library feature 'unstable_default' + fn foo() -> isize { 0 } +} + +impl Trait2 for S { //~ ERROR use of unstable library feature 'unstable_default' + fn foo() -> usize { 0 } +} + +impl Trait3 for S { + fn foo() -> usize { 0 } // ok +} + +fn main() { +} diff --git a/tests/ui/stability-attribute/generics-default-stability-trait.stderr b/tests/ui/stability-attribute/generics-default-stability-trait.stderr new file mode 100644 index 000000000..03e61b78e --- /dev/null +++ b/tests/ui/stability-attribute/generics-default-stability-trait.stderr @@ -0,0 +1,27 @@ +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability-trait.rs:16:13 + | +LL | impl Trait1 for S { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability-trait.rs:20:13 + | +LL | impl Trait1 for S { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability-trait.rs:24:13 + | +LL | impl Trait2 for S { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/generics-default-stability-where.rs b/tests/ui/stability-attribute/generics-default-stability-where.rs new file mode 100644 index 000000000..4afbca262 --- /dev/null +++ b/tests/ui/stability-attribute/generics-default-stability-where.rs @@ -0,0 +1,11 @@ +// aux-build:unstable_generic_param.rs + +extern crate unstable_generic_param; + +use unstable_generic_param::*; + +impl Trait3 for T where T: Trait2 { //~ ERROR use of unstable library feature 'unstable_default' + fn foo() -> usize { T::foo() } +} + +fn main() {} diff --git a/tests/ui/stability-attribute/generics-default-stability-where.stderr b/tests/ui/stability-attribute/generics-default-stability-where.stderr new file mode 100644 index 000000000..61253adc8 --- /dev/null +++ b/tests/ui/stability-attribute/generics-default-stability-where.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability-where.rs:7:45 + | +LL | impl Trait3 for T where T: Trait2 { + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/generics-default-stability.rs b/tests/ui/stability-attribute/generics-default-stability.rs new file mode 100644 index 000000000..300cc34d6 --- /dev/null +++ b/tests/ui/stability-attribute/generics-default-stability.rs @@ -0,0 +1,251 @@ +// aux-build:unstable_generic_param.rs +#![feature(unstable_default6)] + +extern crate unstable_generic_param; + +use unstable_generic_param::*; + +struct R; + +impl Trait1 for S { + fn foo() -> () { () } // ok +} + +struct S; + +impl Trait3 for S { + fn foo() -> usize { 0 } // ok +} + +fn main() { + let _ = S; + + let _: Struct1 = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + + let _ = STRUCT1; // ok + let _: Struct1 = STRUCT1; // ok + let _: Struct1 = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct1 = Struct1 { field: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + + // Instability is not enforced for generic type parameters used in public fields. + // Note how the unstable type default `usize` leaks, + // and can be used without the 'unstable_default' feature. + let _ = STRUCT1.field; + let _ = Struct1 { field: 1 }; + let _ = Struct1 { field: () }; + let _ = Struct1 { field: 1isize }; + let _: Struct1 = Struct1 { field: 1 }; + let _: usize = STRUCT1.field; + let _ = STRUCT1.field + 1; + let _ = STRUCT1.field + 1usize; + + let _ = Struct2 { field: 1 }; // ok + let _: Struct2 = Struct2 { field: 1 }; // ok + let _: Struct2 = Struct2 { field: 1 }; // ok + + let _ = STRUCT2; + let _: Struct2 = STRUCT2; // ok + let _: Struct2 = STRUCT2; // ok + let _: Struct2 = Struct2 { field: 0 }; // ok + let _ = STRUCT2.field; // ok + let _: usize = STRUCT2.field; // ok + let _ = STRUCT2.field + 1; // ok + let _ = STRUCT2.field + 1usize; // ok + + let _ = STRUCT3; + let _: Struct3 = STRUCT3; // ok + let _: Struct3 = STRUCT3; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct3 = STRUCT3; // ok + let _: Struct3 = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + let _: Struct3 = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + let _ = STRUCT3.field1; // ok + let _: isize = STRUCT3.field1; // ok + let _ = STRUCT3.field1 + 1; // ok + // Note the aforementioned leak. + let _: usize = STRUCT3.field2; // ok + let _: Struct3 = Struct3 { field1: 0, field2: 0 }; // ok + let _ = STRUCT3.field2 + 1; // ok + let _ = STRUCT3.field2 + 1usize; // ok + + let _ = STRUCT4; + let _: Struct4 = Struct4 { field: 1 }; + //~^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^^ use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] + let _ = STRUCT4; + let _: Struct4 = STRUCT4; //~ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + let _: Struct4 = STRUCT4; //~ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + let _: Struct4 = Struct4 { field: 0 }; + //~^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^^ use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] + + let _ = STRUCT5; + let _: Struct5 = Struct5 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] + let _ = STRUCT5; + let _: Struct5 = STRUCT5; //~ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + let _: Struct5 = STRUCT5; //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + let _: Struct5 = Struct5 { field: 0 }; //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] + + let _: Struct6 = Struct6 { field: 1 }; // ok + let _: Struct6 = Struct6 { field: 0 }; // ok + + let _: Alias1 = Alias1::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + + let _ = ALIAS1; // ok + let _: Alias1 = ALIAS1; // ok + let _: Alias1 = ALIAS1; //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias1 = Alias1::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + + // Instability is not enforced for generic type parameters used in public fields. + // Note how the unstable type default `usize` leaks, + // and can be used without the 'unstable_default' feature. + let _ = Alias1::Some(1); + let _ = Alias1::Some(()); + let _ = Alias1::Some(1isize); + let _: Alias1 = Alias1::Some(1); + let _: usize = ALIAS1.unwrap(); + let _ = ALIAS1.unwrap() + 1; + let _ = ALIAS1.unwrap() + 1usize; + + let _ = Alias2::Some(1); // ok + let _: Alias2 = Alias2::Some(1); // ok + let _: Alias2 = Alias2::Some(1); // ok + + let _ = ALIAS2; + let _: Alias2 = ALIAS2; // ok + let _: Alias2 = ALIAS2; // ok + let _: Alias2 = Alias2::Some(0); // ok + let _ = ALIAS2.unwrap(); // ok + let _: usize = ALIAS2.unwrap(); // ok + let _ = ALIAS2.unwrap() + 1; // ok + let _ = ALIAS2.unwrap() + 1usize; // ok + + let _ = ALIAS3; + let _: Alias3 = ALIAS3; // ok + let _: Alias3 = ALIAS3; //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias3 = ALIAS3; // ok + let _: Alias3 = Alias3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Alias3 = Alias3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' + let _ = ALIAS3.unwrap(); // ok + let _: isize = ALIAS3.unwrap(); // ok + let _ = ALIAS3.unwrap() + 1; // ok + // Note the aforementioned leak. + let _: usize = ALIAS3B.unwrap_err(); // ok + let _: Alias3 = Alias3::Err(0); // ok + let _ = ALIAS3B.unwrap_err() + 1; // ok + let _ = ALIAS3B.unwrap_err() + 1usize; // ok + + let _ = ALIAS4; + let _: Alias4 = Alias4::Some(1); + //~^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + //~^^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + let _ = ALIAS4; + let _: Alias4 = ALIAS4; //~ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + let _: Alias4 = ALIAS4; //~ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + let _: Alias4 = Alias4::Some(0); + //~^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + //~^^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + + let _ = ALIAS5; + let _: Alias5 = Alias5::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + let _ = ALIAS5; + let _: Alias5 = ALIAS5; //~ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + let _: Alias5 = ALIAS5; //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + let _: Alias5 = Alias5::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + + let _: Alias6 = Alias6::Some(1); // ok + let _: Alias6 = Alias6::Some(0); // ok + + let _: Enum1 = Enum1::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + + let _ = ENUM1; // ok + let _: Enum1 = ENUM1; // ok + let _: Enum1 = ENUM1; //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum1 = Enum1::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + + // Instability is not enforced for generic type parameters used in public fields. + // Note how the unstable type default `usize` leaks, + // and can be used without the 'unstable_default' feature. + let _ = Enum1::Some(1); + let _ = Enum1::Some(()); + let _ = Enum1::Some(1isize); + let _: Enum1 = Enum1::Some(1); + if let Enum1::Some(x) = ENUM1 {let _: usize = x;} + if let Enum1::Some(x) = ENUM1 {let _ = x + 1;} + if let Enum1::Some(x) = ENUM1 {let _ = x + 1usize;} + + let _ = Enum2::Some(1); // ok + let _: Enum2 = Enum2::Some(1); // ok + let _: Enum2 = Enum2::Some(1); // ok + + let _ = ENUM2; + let _: Enum2 = ENUM2; // ok + let _: Enum2 = ENUM2; // ok + let _: Enum2 = Enum2::Some(0); // ok + if let Enum2::Some(x) = ENUM2 {let _ = x;} // ok + if let Enum2::Some(x) = ENUM2 {let _: usize = x;} // ok + if let Enum2::Some(x) = ENUM2 {let _ = x + 1;} // ok + if let Enum2::Some(x) = ENUM2 {let _ = x + 1usize;} // ok + + let _ = ENUM3; + let _: Enum3 = ENUM3; // ok + let _: Enum3 = ENUM3; //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum3 = ENUM3; // ok + let _: Enum3 = Enum3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' + let _: Enum3 = Enum3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default' + if let Enum3::Ok(x) = ENUM3 {let _ = x;} // ok + if let Enum3::Ok(x) = ENUM3 {let _: isize = x;} // ok + if let Enum3::Ok(x) = ENUM3 {let _ = x + 1;} // ok + // Note the aforementioned leak. + if let Enum3::Err(x) = ENUM3B {let _: usize = x;} // ok + let _: Enum3 = Enum3::Err(0); // ok + if let Enum3::Err(x) = ENUM3B {let _ = x + 1;} // ok + if let Enum3::Err(x) = ENUM3B {let _ = x + 1usize;} // ok + + let _ = ENUM4; + let _: Enum4 = Enum4::Some(1); + //~^ use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test [deprecated] + //~^^ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + let _ = ENUM4; + let _: Enum4 = ENUM4; //~ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + let _: Enum4 = ENUM4; //~ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + let _: Enum4 = Enum4::Some(0); + //~^ use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test [deprecated] + //~^^ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + + let _ = ENUM5; + let _: Enum5 = Enum5::Some(1); //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] + //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + let _ = ENUM5; + let _: Enum5 = ENUM5; //~ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + let _: Enum5 = ENUM5; //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + let _: Enum5 = Enum5::Some(0); //~ ERROR use of unstable library feature 'unstable_default' + //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] + //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + + let _: Enum6 = Enum6::Some(1); // ok + let _: Enum6 = Enum6::Some(0); // ok + + let _: Box1 = Box1::new(1); //~ ERROR use of unstable library feature 'box_alloc_param' + let _: Box1 = Box1::new(1); // ok + + let _: Box2 = Box2::new(1); // ok + let _: Box2 = Box2::new(1); // ok + + let _: Box3 = Box3::new(1); // ok +} diff --git a/tests/ui/stability-attribute/generics-default-stability.stderr b/tests/ui/stability-attribute/generics-default-stability.stderr new file mode 100644 index 000000000..e094a10c8 --- /dev/null +++ b/tests/ui/stability-attribute/generics-default-stability.stderr @@ -0,0 +1,469 @@ +warning: use of deprecated struct `unstable_generic_param::Struct4`: test + --> $DIR/generics-default-stability.rs:71:29 + | +LL | let _: Struct4 = Struct4 { field: 1 }; + | ^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated struct `unstable_generic_param::Struct4`: test + --> $DIR/generics-default-stability.rs:71:12 + | +LL | let _: Struct4 = Struct4 { field: 1 }; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct4`: test + --> $DIR/generics-default-stability.rs:76:12 + | +LL | let _: Struct4 = STRUCT4; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct4`: test + --> $DIR/generics-default-stability.rs:77:12 + | +LL | let _: Struct4 = STRUCT4; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct4`: test + --> $DIR/generics-default-stability.rs:78:29 + | +LL | let _: Struct4 = Struct4 { field: 0 }; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct4`: test + --> $DIR/generics-default-stability.rs:78:12 + | +LL | let _: Struct4 = Struct4 { field: 0 }; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct5`: test + --> $DIR/generics-default-stability.rs:84:29 + | +LL | let _: Struct5 = Struct5 { field: 1 }; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct5`: test + --> $DIR/generics-default-stability.rs:84:12 + | +LL | let _: Struct5 = Struct5 { field: 1 }; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct5`: test + --> $DIR/generics-default-stability.rs:89:12 + | +LL | let _: Struct5 = STRUCT5; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct5`: test + --> $DIR/generics-default-stability.rs:90:12 + | +LL | let _: Struct5 = STRUCT5; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct5`: test + --> $DIR/generics-default-stability.rs:92:29 + | +LL | let _: Struct5 = Struct5 { field: 0 }; + | ^^^^^^^ + +warning: use of deprecated struct `unstable_generic_param::Struct5`: test + --> $DIR/generics-default-stability.rs:92:12 + | +LL | let _: Struct5 = Struct5 { field: 0 }; + | ^^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias4`: test + --> $DIR/generics-default-stability.rs:147:28 + | +LL | let _: Alias4 = Alias4::Some(1); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias4`: test + --> $DIR/generics-default-stability.rs:147:12 + | +LL | let _: Alias4 = Alias4::Some(1); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias4`: test + --> $DIR/generics-default-stability.rs:151:12 + | +LL | let _: Alias4 = ALIAS4; + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias4`: test + --> $DIR/generics-default-stability.rs:152:12 + | +LL | let _: Alias4 = ALIAS4; + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias4`: test + --> $DIR/generics-default-stability.rs:153:28 + | +LL | let _: Alias4 = Alias4::Some(0); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias4`: test + --> $DIR/generics-default-stability.rs:153:12 + | +LL | let _: Alias4 = Alias4::Some(0); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias5`: test + --> $DIR/generics-default-stability.rs:158:28 + | +LL | let _: Alias5 = Alias5::Some(1); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias5`: test + --> $DIR/generics-default-stability.rs:158:12 + | +LL | let _: Alias5 = Alias5::Some(1); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias5`: test + --> $DIR/generics-default-stability.rs:162:12 + | +LL | let _: Alias5 = ALIAS5; + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias5`: test + --> $DIR/generics-default-stability.rs:163:12 + | +LL | let _: Alias5 = ALIAS5; + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias5`: test + --> $DIR/generics-default-stability.rs:165:28 + | +LL | let _: Alias5 = Alias5::Some(0); + | ^^^^^^ + +warning: use of deprecated type alias `unstable_generic_param::Alias5`: test + --> $DIR/generics-default-stability.rs:165:12 + | +LL | let _: Alias5 = Alias5::Some(0); + | ^^^^^^ + +warning: use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test + --> $DIR/generics-default-stability.rs:219:34 + | +LL | let _: Enum4 = Enum4::Some(1); + | ^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum4`: test + --> $DIR/generics-default-stability.rs:219:12 + | +LL | let _: Enum4 = Enum4::Some(1); + | ^^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum4`: test + --> $DIR/generics-default-stability.rs:223:12 + | +LL | let _: Enum4 = ENUM4; + | ^^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum4`: test + --> $DIR/generics-default-stability.rs:224:12 + | +LL | let _: Enum4 = ENUM4; + | ^^^^^ + +warning: use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test + --> $DIR/generics-default-stability.rs:225:34 + | +LL | let _: Enum4 = Enum4::Some(0); + | ^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum4`: test + --> $DIR/generics-default-stability.rs:225:12 + | +LL | let _: Enum4 = Enum4::Some(0); + | ^^^^^ + +warning: use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test + --> $DIR/generics-default-stability.rs:230:34 + | +LL | let _: Enum5 = Enum5::Some(1); + | ^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum5`: test + --> $DIR/generics-default-stability.rs:230:12 + | +LL | let _: Enum5 = Enum5::Some(1); + | ^^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum5`: test + --> $DIR/generics-default-stability.rs:234:12 + | +LL | let _: Enum5 = ENUM5; + | ^^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum5`: test + --> $DIR/generics-default-stability.rs:235:12 + | +LL | let _: Enum5 = ENUM5; + | ^^^^^ + +warning: use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test + --> $DIR/generics-default-stability.rs:237:34 + | +LL | let _: Enum5 = Enum5::Some(0); + | ^^^^ + +warning: use of deprecated enum `unstable_generic_param::Enum5`: test + --> $DIR/generics-default-stability.rs:237:12 + | +LL | let _: Enum5 = Enum5::Some(0); + | ^^^^^ + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:23:20 + | +LL | let _: Struct1 = Struct1 { field: 1 }; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:27:20 + | +LL | let _: Struct1 = STRUCT1; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:28:20 + | +LL | let _: Struct1 = Struct1 { field: 0 }; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:57:27 + | +LL | let _: Struct3 = STRUCT3; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:59:27 + | +LL | let _: Struct3 = Struct3 { field1: 0, field2: 0 }; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:60:27 + | +LL | let _: Struct3 = Struct3 { field1: 0, field2: 0 }; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:84:20 + | +LL | let _: Struct5 = Struct5 { field: 1 }; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:90:20 + | +LL | let _: Struct5 = STRUCT5; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:92:20 + | +LL | let _: Struct5 = Struct5 { field: 0 }; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:100:19 + | +LL | let _: Alias1 = Alias1::Some(1); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:104:19 + | +LL | let _: Alias1 = ALIAS1; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:105:19 + | +LL | let _: Alias1 = Alias1::Some(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:133:26 + | +LL | let _: Alias3 = ALIAS3; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:135:26 + | +LL | let _: Alias3 = Alias3::Ok(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:136:26 + | +LL | let _: Alias3 = Alias3::Ok(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:158:19 + | +LL | let _: Alias5 = Alias5::Some(1); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:163:19 + | +LL | let _: Alias5 = ALIAS5; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:165:19 + | +LL | let _: Alias5 = Alias5::Some(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:172:18 + | +LL | let _: Enum1 = Enum1::Some(1); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:176:18 + | +LL | let _: Enum1 = ENUM1; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:177:18 + | +LL | let _: Enum1 = Enum1::Some(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:205:25 + | +LL | let _: Enum3 = ENUM3; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:207:25 + | +LL | let _: Enum3 = Enum3::Ok(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:208:25 + | +LL | let _: Enum3 = Enum3::Ok(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:230:18 + | +LL | let _: Enum5 = Enum5::Some(1); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:235:18 + | +LL | let _: Enum5 = ENUM5; + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_default' + --> $DIR/generics-default-stability.rs:237:18 + | +LL | let _: Enum5 = Enum5::Some(0); + | ^^^^^ + | + = help: add `#![feature(unstable_default)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'box_alloc_param' + --> $DIR/generics-default-stability.rs:244:24 + | +LL | let _: Box1 = Box1::new(1); + | ^^^^^^ + | + = help: add `#![feature(box_alloc_param)]` to the crate attributes to enable + +warning: use of deprecated field `unstable_generic_param::Struct4::field`: test + --> $DIR/generics-default-stability.rs:71:39 + | +LL | let _: Struct4 = Struct4 { field: 1 }; + | ^^^^^^^^ + +warning: use of deprecated field `unstable_generic_param::Struct4::field`: test + --> $DIR/generics-default-stability.rs:78:39 + | +LL | let _: Struct4 = Struct4 { field: 0 }; + | ^^^^^^^^ + +warning: use of deprecated field `unstable_generic_param::Struct5::field`: test + --> $DIR/generics-default-stability.rs:84:39 + | +LL | let _: Struct5 = Struct5 { field: 1 }; + | ^^^^^^^^ + +warning: use of deprecated field `unstable_generic_param::Struct5::field`: test + --> $DIR/generics-default-stability.rs:92:39 + | +LL | let _: Struct5 = Struct5 { field: 0 }; + | ^^^^^^^^ + +error: aborting due to 28 previous errors; 40 warnings emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/issue-106589.rs b/tests/ui/stability-attribute/issue-106589.rs new file mode 100644 index 000000000..3cad9a3d2 --- /dev/null +++ b/tests/ui/stability-attribute/issue-106589.rs @@ -0,0 +1,10 @@ +// #![feature(staged_api)] // note: `staged_api` not enabled + +#![stable(feature = "foo", since = "1.0.0")] +//~^ ERROR stability attributes may not be used outside of the standard library + +#[unstable(feature = "foo", issue = "none")] +//~^ ERROR stability attributes may not be used outside of the standard library +fn foo_unstable() {} + +fn main() {} diff --git a/tests/ui/stability-attribute/issue-106589.stderr b/tests/ui/stability-attribute/issue-106589.stderr new file mode 100644 index 000000000..ccf3f7164 --- /dev/null +++ b/tests/ui/stability-attribute/issue-106589.stderr @@ -0,0 +1,15 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-106589.rs:6:1 + | +LL | #[unstable(feature = "foo", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/issue-106589.rs:3:1 + | +LL | #![stable(feature = "foo", since = "1.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/stability-attribute/issue-28075.rs b/tests/ui/stability-attribute/issue-28075.rs new file mode 100644 index 000000000..6b4ea46f3 --- /dev/null +++ b/tests/ui/stability-attribute/issue-28075.rs @@ -0,0 +1,13 @@ +// Unstable entities should be caught in import lists + +// aux-build:lint-stability.rs + +#![allow(warnings)] + +extern crate lint_stability; + +use lint_stability::{unstable, deprecated}; +//~^ ERROR use of unstable library feature 'unstable_test_feature' + +fn main() { +} diff --git a/tests/ui/stability-attribute/issue-28075.stderr b/tests/ui/stability-attribute/issue-28075.stderr new file mode 100644 index 000000000..7e53bb544 --- /dev/null +++ b/tests/ui/stability-attribute/issue-28075.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/issue-28075.rs:9:22 + | +LL | use lint_stability::{unstable, deprecated}; + | ^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/issue-28388-3.rs b/tests/ui/stability-attribute/issue-28388-3.rs new file mode 100644 index 000000000..7ba993501 --- /dev/null +++ b/tests/ui/stability-attribute/issue-28388-3.rs @@ -0,0 +1,11 @@ +// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc. + +// aux-build:lint-stability.rs + +extern crate lint_stability; + +use lint_stability::UnstableEnum::{}; +//~^ ERROR use of unstable library feature 'unstable_test_feature' +use lint_stability::StableEnum::{}; // OK + +fn main() {} diff --git a/tests/ui/stability-attribute/issue-28388-3.stderr b/tests/ui/stability-attribute/issue-28388-3.stderr new file mode 100644 index 000000000..d2e46683b --- /dev/null +++ b/tests/ui/stability-attribute/issue-28388-3.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/issue-28388-3.rs:7:5 + | +LL | use lint_stability::UnstableEnum::{}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs new file mode 100644 index 000000000..b9eee9922 --- /dev/null +++ b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs @@ -0,0 +1,17 @@ +// check-pass +// +// Regression test for issue #99286 +// Tests that stabilized intrinsics are accessible +// through 'std::intrinsics', even though the module +// is unstable. + +#![allow(unused_imports)] +#![allow(deprecated)] + +use std::intrinsics::drop_in_place as _; +use std::intrinsics::copy_nonoverlapping as _; +use std::intrinsics::copy as _; +use std::intrinsics::write_bytes as _; +use std::intrinsics::{drop_in_place, copy_nonoverlapping, copy, write_bytes}; + +fn main() {} diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs new file mode 100644 index 000000000..6eff899bf --- /dev/null +++ b/tests/ui/stability-attribute/missing-const-stability.rs @@ -0,0 +1,33 @@ +#![feature(staged_api)] +#![feature(const_trait_impl)] +#![stable(feature = "stable", since = "1.0.0")] + +#[stable(feature = "stable", since = "1.0.0")] +pub const fn foo() {} //~ ERROR function has missing const stability attribute + +#[unstable(feature = "unstable", issue = "none")] +pub const fn bar() {} // ok because function is unstable + +#[stable(feature = "stable", since = "1.0.0")] +pub struct Foo; +impl Foo { + #[stable(feature = "stable", since = "1.0.0")] + pub const fn foo() {} //~ ERROR associated function has missing const stability attribute + + #[unstable(feature = "unstable", issue = "none")] + pub const fn bar() {} // ok because function is unstable +} + +#[stable(feature = "stable", since = "1.0.0")] +#[const_trait] +pub trait Bar { + #[stable(feature = "stable", since = "1.0.0")] + fn fun(); +} +#[stable(feature = "stable", since = "1.0.0")] +impl const Bar for Foo { + //~^ ERROR implementation has missing const stability attribute + fn fun() {} +} + +fn main() {} diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr new file mode 100644 index 000000000..4cfbe1528 --- /dev/null +++ b/tests/ui/stability-attribute/missing-const-stability.stderr @@ -0,0 +1,23 @@ +error: function has missing const stability attribute + --> $DIR/missing-const-stability.rs:6:1 + | +LL | pub const fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: implementation has missing const stability attribute + --> $DIR/missing-const-stability.rs:28:1 + | +LL | / impl const Bar for Foo { +LL | | +LL | | fn fun() {} +LL | | } + | |_^ + +error: associated function has missing const stability attribute + --> $DIR/missing-const-stability.rs:15:5 + | +LL | pub const fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.rs b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.rs new file mode 100644 index 000000000..38faa2469 --- /dev/null +++ b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.rs @@ -0,0 +1,4 @@ +#![feature(staged_api)] +//~^ ERROR module has missing stability attribute + +fn main() {} diff --git a/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr new file mode 100644 index 000000000..c7ade234d --- /dev/null +++ b/tests/ui/stability-attribute/missing-stability-attr-at-top-level.stderr @@ -0,0 +1,11 @@ +error: module has missing stability attribute + --> $DIR/missing-stability-attr-at-top-level.rs:1:1 + | +LL | / #![feature(staged_api)] +LL | | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + diff --git a/tests/ui/stability-attribute/stability-attribute-implies-missing.rs b/tests/ui/stability-attribute/stability-attribute-implies-missing.rs new file mode 100644 index 000000000..613878536 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-missing.rs @@ -0,0 +1,10 @@ +#![feature(staged_api)] +#![stable(feature = "stability_attribute_implies", since = "1.0.0")] + +// Tests that `implied_by = "bar"` results in an error being emitted if `bar` does not exist. + +#[unstable(feature = "foobar", issue = "1", implied_by = "bar")] +//~^ ERROR feature `bar` implying `foobar` does not exist +pub fn foobar() {} + +fn main() {} diff --git a/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr new file mode 100644 index 000000000..ff1856f17 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-missing.stderr @@ -0,0 +1,8 @@ +error: feature `bar` implying `foobar` does not exist + --> $DIR/stability-attribute-implies-missing.rs:6:1 + | +LL | #[unstable(feature = "foobar", issue = "1", implied_by = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs new file mode 100644 index 000000000..947f9f73e --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs @@ -0,0 +1,13 @@ +// aux-build:stability-attribute-implies.rs + +// Tests that despite the `foobar` feature being implied by now-stable feature `foo`, if `foobar` +// isn't allowed in this crate then an error will be emitted. + +extern crate stability_attribute_implies; +use stability_attribute_implies::{foo, foobar}; +//~^ ERROR use of unstable library feature 'foobar' + +fn main() { + foo(); // no error - stable + foobar(); //~ ERROR use of unstable library feature 'foobar' +} diff --git a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr new file mode 100644 index 000000000..c2331f676 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'foobar' + --> $DIR/stability-attribute-implies-no-feature.rs:7:40 + | +LL | use stability_attribute_implies::{foo, foobar}; + | ^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(foobar)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'foobar' + --> $DIR/stability-attribute-implies-no-feature.rs:12:5 + | +LL | foobar(); + | ^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(foobar)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/stability-attribute-implies-using-stable.rs b/tests/ui/stability-attribute/stability-attribute-implies-using-stable.rs new file mode 100644 index 000000000..1a2d8e271 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-using-stable.rs @@ -0,0 +1,15 @@ +// aux-build:stability-attribute-implies.rs +#![deny(stable_features)] +#![feature(foo)] +//~^ ERROR the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar` + +// Tests that the use of `implied_by` in the `#[unstable]` attribute results in a diagnostic +// mentioning partial stabilization, and that given the implied unstable feature is unused (there +// is no `foobar` call), that the compiler suggests removing the flag. + +extern crate stability_attribute_implies; +use stability_attribute_implies::foo; + +fn main() { + foo(); +} diff --git a/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr b/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr new file mode 100644 index 000000000..c9b3f07cc --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-using-stable.stderr @@ -0,0 +1,22 @@ +error: the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar` + --> $DIR/stability-attribute-implies-using-stable.rs:3:12 + | +LL | #![feature(foo)] + | ^^^ + | +note: the lint level is defined here + --> $DIR/stability-attribute-implies-using-stable.rs:2:9 + | +LL | #![deny(stable_features)] + | ^^^^^^^^^^^^^^^ +help: if you are using features which are still unstable, change to using `foobar` + | +LL | #![feature(foobar)] + | ~~~~~~ +help: if you are using features which are now stable, remove this line + | +LL - #![feature(foo)] + | + +error: aborting due to previous error + diff --git a/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.rs b/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.rs new file mode 100644 index 000000000..3c73c5abf --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.rs @@ -0,0 +1,17 @@ +// aux-build:stability-attribute-implies.rs +#![deny(stable_features)] +#![feature(foo)] +//~^ ERROR the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar` + +// Tests that the use of `implied_by` in the `#[unstable]` attribute results in a diagnostic +// mentioning partial stabilization and that given the implied unstable feature is used (there is a +// `foobar` call), that the compiler suggests changing to that feature and doesn't error about its +// use. + +extern crate stability_attribute_implies; +use stability_attribute_implies::{foo, foobar}; + +fn main() { + foo(); + foobar(); // no error! +} diff --git a/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr b/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr new file mode 100644 index 000000000..9a5c7ef5a --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-implies-using-unstable.stderr @@ -0,0 +1,22 @@ +error: the feature `foo` has been partially stabilized since 1.62.0 and is succeeded by the feature `foobar` + --> $DIR/stability-attribute-implies-using-unstable.rs:3:12 + | +LL | #![feature(foo)] + | ^^^ + | +note: the lint level is defined here + --> $DIR/stability-attribute-implies-using-unstable.rs:2:9 + | +LL | #![deny(stable_features)] + | ^^^^^^^^^^^^^^^ +help: if you are using features which are still unstable, change to using `foobar` + | +LL | #![feature(foobar)] + | ~~~~~~ +help: if you are using features which are now stable, remove this line + | +LL - #![feature(foo)] + | + +error: aborting due to previous error + diff --git a/tests/ui/stability-attribute/stability-attribute-issue-43027.rs b/tests/ui/stability-attribute/stability-attribute-issue-43027.rs new file mode 100644 index 000000000..3f4fdfd01 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-issue-43027.rs @@ -0,0 +1,15 @@ +// check-pass +#![feature(staged_api)] +#![stable(feature = "test", since = "0")] + +#[stable(feature = "test", since = "0")] +pub struct A(pub T); + +#[stable(feature = "test", since = "0")] +pub struct B(#[stable(feature = "test", since = "0")] pub T); + +fn main() { + // Make sure the field is used to fill the stability cache + A(0).0; + B(0).0; +} diff --git a/tests/ui/stability-attribute/stability-attribute-issue.rs b/tests/ui/stability-attribute/stability-attribute-issue.rs new file mode 100644 index 000000000..cda1aff13 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-issue.rs @@ -0,0 +1,12 @@ +// aux-build:stability_attribute_issue.rs +#![deny(deprecated)] + +extern crate stability_attribute_issue; +use stability_attribute_issue::*; + +fn main() { + unstable(); + //~^ ERROR use of unstable library feature 'unstable_test_feature' + unstable_msg(); + //~^ ERROR use of unstable library feature 'unstable_test_feature': message +} diff --git a/tests/ui/stability-attribute/stability-attribute-issue.stderr b/tests/ui/stability-attribute/stability-attribute-issue.stderr new file mode 100644 index 000000000..df4aec7e5 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-issue.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stability-attribute-issue.rs:8:5 + | +LL | unstable(); + | ^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature': message + --> $DIR/stability-attribute-issue.rs:10:5 + | +LL | unstable_msg(); + | ^^^^^^^^^^^^ + | + = note: see issue #2 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs b/tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs new file mode 100644 index 000000000..f61acc8aa --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.rs @@ -0,0 +1,5 @@ +// compile-flags:-Zforce-unstable-if-unmarked + +#[unstable()] //~ ERROR: stability attributes may not be used +#[stable()] //~ ERROR: stability attributes may not be used +fn main() {} diff --git a/tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr b/tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr new file mode 100644 index 000000000..45d965ea0 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr @@ -0,0 +1,15 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/stability-attribute-non-staged-force-unstable.rs:3:1 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/stability-attribute-non-staged-force-unstable.rs:4:1 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/stability-attribute/stability-attribute-non-staged.rs b/tests/ui/stability-attribute/stability-attribute-non-staged.rs new file mode 100644 index 000000000..4015f2f97 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-non-staged.rs @@ -0,0 +1,3 @@ +#[unstable()] //~ ERROR: stability attributes may not be used +#[stable()] //~ ERROR: stability attributes may not be used +fn main() {} diff --git a/tests/ui/stability-attribute/stability-attribute-non-staged.stderr b/tests/ui/stability-attribute/stability-attribute-non-staged.stderr new file mode 100644 index 000000000..391f3c274 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-non-staged.stderr @@ -0,0 +1,15 @@ +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/stability-attribute-non-staged.rs:1:1 + | +LL | #[unstable()] + | ^^^^^^^^^^^^^ + +error[E0734]: stability attributes may not be used outside of the standard library + --> $DIR/stability-attribute-non-staged.rs:2:1 + | +LL | #[stable()] + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0734`. diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-2.rs b/tests/ui/stability-attribute/stability-attribute-sanity-2.rs new file mode 100644 index 000000000..de3ea4eac --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity-2.rs @@ -0,0 +1,17 @@ +// More checks that stability attributes are used correctly + +#![feature(staged_api)] + +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "a", feature = "b", since = "1.0.0")] //~ ERROR multiple 'feature' items +fn f1() { } + +#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR unknown meta item 'sinse' +fn f2() { } + +#[unstable(feature = "a", issue = "no")] +//~^ ERROR `issue` must be a non-zero numeric string or "none" +fn f3() { } + +fn main() { } diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr new file mode 100644 index 000000000..8dbcc6c97 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity-2.stderr @@ -0,0 +1,24 @@ +error[E0538]: multiple 'feature' items + --> $DIR/stability-attribute-sanity-2.rs:7:25 + | +LL | #[stable(feature = "a", feature = "b", since = "1.0.0")] + | ^^^^^^^^^^^^^ + +error[E0541]: unknown meta item 'sinse' + --> $DIR/stability-attribute-sanity-2.rs:10:25 + | +LL | #[stable(feature = "a", sinse = "1.0.0")] + | ^^^^^^^^^^^^^^^ expected one of `feature`, `since` + +error[E0545]: `issue` must be a non-zero numeric string or "none" + --> $DIR/stability-attribute-sanity-2.rs:13:27 + | +LL | #[unstable(feature = "a", issue = "no")] + | ^^^^^^^^---- + | | + | invalid digit found in string + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0538, E0541, E0545. +For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-3.rs b/tests/ui/stability-attribute/stability-attribute-sanity-3.rs new file mode 100644 index 000000000..13ef3d3f5 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity-3.rs @@ -0,0 +1,12 @@ +// More checks that stability attributes are used correctly + +#![feature(staged_api)] + +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[macro_export] +macro_rules! mac { //~ ERROR macro has missing stability attribute + () => () +} + +fn main() { } diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr new file mode 100644 index 000000000..b1c56ef22 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity-3.stderr @@ -0,0 +1,10 @@ +error: macro has missing stability attribute + --> $DIR/stability-attribute-sanity-3.rs:8:1 + | +LL | / macro_rules! mac { +LL | | () => () +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-4.rs b/tests/ui/stability-attribute/stability-attribute-sanity-4.rs new file mode 100644 index 000000000..64f996352 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity-4.rs @@ -0,0 +1,29 @@ +// Various checks that stability attributes are used correctly, per RFC 507 + +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +mod bogus_attribute_types_2 { + #[unstable] //~ ERROR malformed `unstable` attribute + fn f1() { } + + #[unstable = "b"] //~ ERROR malformed `unstable` attribute + fn f2() { } + + #[stable] //~ ERROR malformed `stable` attribute + fn f3() { } + + #[stable = "a"] //~ ERROR malformed `stable` attribute + fn f4() { } + + #[stable(feature = "a", since = "b")] + #[deprecated] //~ ERROR missing 'since' + fn f5() { } + + #[stable(feature = "a", since = "b")] + #[deprecated = "a"] //~ ERROR missing 'since' + fn f6() { } +} + +fn main() { } diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr b/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr new file mode 100644 index 000000000..a76f5be1e --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity-4.stderr @@ -0,0 +1,39 @@ +error: malformed `unstable` attribute input + --> $DIR/stability-attribute-sanity-4.rs:8:5 + | +LL | #[unstable] + | ^^^^^^^^^^^ help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` + +error: malformed `unstable` attribute input + --> $DIR/stability-attribute-sanity-4.rs:11:5 + | +LL | #[unstable = "b"] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unstable(feature = "name", reason = "...", issue = "N")]` + +error: malformed `stable` attribute input + --> $DIR/stability-attribute-sanity-4.rs:14:5 + | +LL | #[stable] + | ^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]` + +error: malformed `stable` attribute input + --> $DIR/stability-attribute-sanity-4.rs:17:5 + | +LL | #[stable = "a"] + | ^^^^^^^^^^^^^^^ help: must be of the form: `#[stable(feature = "name", since = "version")]` + +error[E0542]: missing 'since' + --> $DIR/stability-attribute-sanity-4.rs:21:5 + | +LL | #[deprecated] + | ^^^^^^^^^^^^^ + +error[E0542]: missing 'since' + --> $DIR/stability-attribute-sanity-4.rs:25:5 + | +LL | #[deprecated = "a"] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0542`. diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.rs b/tests/ui/stability-attribute/stability-attribute-sanity.rs new file mode 100644 index 000000000..cc30e6ab9 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity.rs @@ -0,0 +1,76 @@ +// Various checks that stability attributes are used correctly, per RFC 507 + +#![feature(staged_api)] + +#![stable(feature = "rust1", since = "1.0.0")] + +mod bogus_attribute_types_1 { + #[stable(feature = "a", since = "b", reason)] //~ ERROR unknown meta item 'reason' [E0541] + fn f1() { } + + #[stable(feature = "a", since)] //~ ERROR incorrect meta item [E0539] + fn f2() { } + + #[stable(feature, since = "a")] //~ ERROR incorrect meta item [E0539] + fn f3() { } + + #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item [E0539] + fn f5() { } + + #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item [E0539] + fn f6() { } +} + +mod missing_feature_names { + #[unstable(issue = "none")] //~ ERROR missing 'feature' [E0546] + fn f1() { } + + #[unstable(feature = "b")] //~ ERROR missing 'issue' [E0547] + fn f2() { } + + #[stable(since = "a")] //~ ERROR missing 'feature' [E0546] + fn f3() { } +} + +mod missing_version { + #[stable(feature = "a")] //~ ERROR missing 'since' [E0542] + fn f1() { } + + #[stable(feature = "a", since = "b")] + #[deprecated(note = "a")] //~ ERROR missing 'since' [E0542] + fn f2() { } + + #[stable(feature = "a", since = "b")] + #[deprecated(since = "a")] //~ ERROR missing 'note' [E0543] + fn f3() { } +} + +#[unstable(feature = "b", issue = "none")] +#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544] +fn multiple1() { } + +#[unstable(feature = "b", issue = "none")] +#[unstable(feature = "b", issue = "none")] //~ ERROR multiple stability levels [E0544] +fn multiple2() { } + +#[stable(feature = "a", since = "b")] +#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544] +fn multiple3() { } + +#[stable(feature = "a", since = "b")] //~ ERROR invalid stability version found +#[deprecated(since = "b", note = "text")] +#[deprecated(since = "b", note = "text")] //~ ERROR multiple `deprecated` attributes +#[rustc_const_unstable(feature = "c", issue = "none")] +#[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels +pub const fn multiple4() { } + +#[stable(feature = "a", since = "1.0.0")] //~ ERROR invalid deprecation version found +//~^ ERROR feature `a` is declared stable since 1.0.0 +#[deprecated(since = "invalid", note = "text")] +fn invalid_deprecation_version() {} + +#[deprecated(since = "a", note = "text")] +fn deprecated_without_unstable_or_stable() { } +//~^^ ERROR deprecated attribute must be paired with either stable or unstable attribute + +fn main() { } diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.stderr b/tests/ui/stability-attribute/stability-attribute-sanity.stderr new file mode 100644 index 000000000..89a8425f5 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-sanity.stderr @@ -0,0 +1,136 @@ +error: multiple `deprecated` attributes + --> $DIR/stability-attribute-sanity.rs:62:1 + | +LL | #[deprecated(since = "b", note = "text")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/stability-attribute-sanity.rs:61:1 + | +LL | #[deprecated(since = "b", note = "text")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0541]: unknown meta item 'reason' + --> $DIR/stability-attribute-sanity.rs:8:42 + | +LL | #[stable(feature = "a", since = "b", reason)] + | ^^^^^^ expected one of `feature`, `since` + +error[E0539]: incorrect meta item + --> $DIR/stability-attribute-sanity.rs:11:29 + | +LL | #[stable(feature = "a", since)] + | ^^^^^ + +error[E0539]: incorrect meta item + --> $DIR/stability-attribute-sanity.rs:14:14 + | +LL | #[stable(feature, since = "a")] + | ^^^^^^^ + +error[E0539]: incorrect meta item + --> $DIR/stability-attribute-sanity.rs:17:29 + | +LL | #[stable(feature = "a", since(b))] + | ^^^^^^^^ + +error[E0539]: incorrect meta item + --> $DIR/stability-attribute-sanity.rs:20:14 + | +LL | #[stable(feature(b), since = "a")] + | ^^^^^^^^^^ + +error[E0546]: missing 'feature' + --> $DIR/stability-attribute-sanity.rs:25:5 + | +LL | #[unstable(issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0547]: missing 'issue' + --> $DIR/stability-attribute-sanity.rs:28:5 + | +LL | #[unstable(feature = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0546]: missing 'feature' + --> $DIR/stability-attribute-sanity.rs:31:5 + | +LL | #[stable(since = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0542]: missing 'since' + --> $DIR/stability-attribute-sanity.rs:36:5 + | +LL | #[stable(feature = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0542]: missing 'since' + --> $DIR/stability-attribute-sanity.rs:40:5 + | +LL | #[deprecated(note = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0543]: missing 'note' + --> $DIR/stability-attribute-sanity.rs:44:5 + | +LL | #[deprecated(since = "a")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0544]: multiple stability levels + --> $DIR/stability-attribute-sanity.rs:49:1 + | +LL | #[stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0544]: multiple stability levels + --> $DIR/stability-attribute-sanity.rs:53:1 + | +LL | #[unstable(feature = "b", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0544]: multiple stability levels + --> $DIR/stability-attribute-sanity.rs:57:1 + | +LL | #[stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0544]: multiple stability levels + --> $DIR/stability-attribute-sanity.rs:64:1 + | +LL | #[rustc_const_unstable(feature = "d", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: invalid stability version found + --> $DIR/stability-attribute-sanity.rs:60:1 + | +LL | #[stable(feature = "a", since = "b")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid stability version +... +LL | pub const fn multiple4() { } + | ---------------------------- the stability attribute annotates this item + +error: invalid deprecation version found + --> $DIR/stability-attribute-sanity.rs:67:1 + | +LL | #[stable(feature = "a", since = "1.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid deprecation version +... +LL | fn invalid_deprecation_version() {} + | ----------------------------------- the stability attribute annotates this item + +error[E0549]: deprecated attribute must be paired with either stable or unstable attribute + --> $DIR/stability-attribute-sanity.rs:72:1 + | +LL | #[deprecated(since = "a", note = "text")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0711]: feature `a` is declared stable since 1.0.0, but was previously declared stable since b + --> $DIR/stability-attribute-sanity.rs:67:1 + | +LL | #[stable(feature = "a", since = "1.0.0")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0539, E0541, E0542, E0543, E0544, E0546, E0547, E0549, E0711. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/stability-attribute/stability-attribute-trait-impl.rs b/tests/ui/stability-attribute/stability-attribute-trait-impl.rs new file mode 100644 index 000000000..0c771ae87 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-trait-impl.rs @@ -0,0 +1,43 @@ +#![feature(staged_api, never_type, c_unwind)] +//~^ ERROR module has missing stability attribute + +#[stable(feature = "a", since = "1")] +struct StableType; + +#[unstable(feature = "b", issue = "none")] +struct UnstableType; + +#[stable(feature = "c", since = "1")] +trait StableTrait {} + +#[unstable(feature = "d", issue = "none")] +trait UnstableTrait {} + +#[unstable(feature = "e", issue = "none")] +impl UnstableTrait for UnstableType {} + +#[unstable(feature = "f", issue = "none")] +impl StableTrait for UnstableType {} + +#[unstable(feature = "g", issue = "none")] +impl UnstableTrait for StableType {} + +#[unstable(feature = "h", issue = "none")] +impl StableTrait for ! {} + +// Note: If C-unwind is stabilized, switch this to another (unstable) ABI. +#[unstable(feature = "i", issue = "none")] +impl StableTrait for extern "C-unwind" fn() {} + +#[unstable(feature = "j", issue = "none")] +//~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl] +impl StableTrait for StableType {} + +#[unstable(feature = "k", issue = "none")] +//~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl] +impl StableTrait for fn() -> ! {} + +#[unstable(feature = "l", issue = "none")] +impl StableTrait for fn() -> UnstableType {} + +fn main() {} diff --git a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr new file mode 100644 index 000000000..b91a1d2e1 --- /dev/null +++ b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr @@ -0,0 +1,31 @@ +error: an `#[unstable]` annotation here has no effect + --> $DIR/stability-attribute-trait-impl.rs:32:1 + | +LL | #[unstable(feature = "j", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #55436 for more information + = note: `#[deny(ineffective_unstable_trait_impl)]` on by default + +error: an `#[unstable]` annotation here has no effect + --> $DIR/stability-attribute-trait-impl.rs:36:1 + | +LL | #[unstable(feature = "k", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #55436 for more information + +error: module has missing stability attribute + --> $DIR/stability-attribute-trait-impl.rs:1:1 + | +LL | / #![feature(staged_api, never_type, c_unwind)] +LL | | +LL | | +LL | | #[stable(feature = "a", since = "1")] +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/stability-attribute/stability-in-private-module.rs b/tests/ui/stability-attribute/stability-in-private-module.rs new file mode 100644 index 000000000..f12e9198b --- /dev/null +++ b/tests/ui/stability-attribute/stability-in-private-module.rs @@ -0,0 +1,4 @@ +fn main() { + let _ = std::thread::thread_info::current_thread(); + //~^ERROR module `thread_info` is private +} diff --git a/tests/ui/stability-attribute/stability-in-private-module.stderr b/tests/ui/stability-attribute/stability-in-private-module.stderr new file mode 100644 index 000000000..2f02a2496 --- /dev/null +++ b/tests/ui/stability-attribute/stability-in-private-module.stderr @@ -0,0 +1,12 @@ +error[E0603]: module `thread_info` is private + --> $DIR/stability-in-private-module.rs:2:26 + | +LL | let _ = std::thread::thread_info::current_thread(); + | ^^^^^^^^^^^ private module + | +note: the module `thread_info` is defined here + --> $SRC_DIR/std/src/thread/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/stability-attribute/stable-in-unstable.rs b/tests/ui/stability-attribute/stable-in-unstable.rs new file mode 100644 index 000000000..226367c39 --- /dev/null +++ b/tests/ui/stability-attribute/stable-in-unstable.rs @@ -0,0 +1,54 @@ +// This test is meant to test that we can have a stable item in an unstable module, and that +// calling that item through the unstable module is unstable, but that re-exporting it from another +// crate in a stable module is fine. +// +// This is necessary to support moving items from `std` into `core` or `alloc` unstably while still +// exporting the original stable interface in `std`, such as moving `Error` into `core`. +// +// aux-build:stable-in-unstable-core.rs +// aux-build:stable-in-unstable-std.rs +#![crate_type = "lib"] + +extern crate stable_in_unstable_core; +extern crate stable_in_unstable_std; + +mod isolated1 { + use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature 'unstable_test_feature' + use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature' +} + +mod isolated2 { + use stable_in_unstable_std::old_stable_module::OldTrait; + + struct LocalType; + + impl OldTrait for LocalType {} +} + +mod isolated3 { + use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature' + + struct LocalType; + + impl OldTrait for LocalType {} +} + +mod isolated4 { + struct LocalType; + + impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature 'unstable_test_feature' +} + +mod isolated5 { + struct LocalType; + + impl stable_in_unstable_std::old_stable_module::OldTrait for LocalType {} +} + +mod isolated6 { + use stable_in_unstable_core::new_unstable_module::{OldTrait}; //~ ERROR use of unstable library feature 'unstable_test_feature' +} + +mod isolated7 { + use stable_in_unstable_core::new_unstable_module::*; //~ ERROR use of unstable library feature 'unstable_test_feature' +} diff --git a/tests/ui/stability-attribute/stable-in-unstable.stderr b/tests/ui/stability-attribute/stable-in-unstable.stderr new file mode 100644 index 000000000..b5e3e5f12 --- /dev/null +++ b/tests/ui/stability-attribute/stable-in-unstable.stderr @@ -0,0 +1,57 @@ +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stable-in-unstable.rs:16:9 + | +LL | use stable_in_unstable_core::new_unstable_module; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stable-in-unstable.rs:17:9 + | +LL | use stable_in_unstable_core::new_unstable_module::OldTrait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stable-in-unstable.rs:29:9 + | +LL | use stable_in_unstable_core::new_unstable_module::OldTrait; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stable-in-unstable.rs:39:10 + | +LL | impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stable-in-unstable.rs:49:56 + | +LL | use stable_in_unstable_core::new_unstable_module::{OldTrait}; + | ^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'unstable_test_feature' + --> $DIR/stable-in-unstable.rs:53:9 + | +LL | use stable_in_unstable_core::new_unstable_module::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs new file mode 100644 index 000000000..fac52ab77 --- /dev/null +++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs @@ -0,0 +1,9 @@ +fn main() { + let _: Vec = vec![]; //~ ERROR use of unstable library feature 'allocator_api' + #[rustfmt::skip] + let _: Vec< + String, + _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api' + let _ = Vec::::new(); //~ ERROR use of unstable library feature 'allocator_api' + let _boxed: Box = Box::new(10); //~ ERROR use of unstable library feature 'allocator_api' +} diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr new file mode 100644 index 000000000..41e5787b8 --- /dev/null +++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr @@ -0,0 +1,49 @@ +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:2:20 + | +LL | let _: Vec = vec![]; + | ----^ + | | + | help: consider wrapping the inner types in tuple: `(u8, _)` + | + = note: see issue #32838 for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:6:9 + | +LL | _> = vec![]; + | ^ + | + = note: see issue #32838 for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable +help: consider wrapping the inner types in tuple + | +LL ~ let _: Vec<( +LL + String, +LL ~ _)> = vec![]; + | + +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:8:26 + | +LL | let _boxed: Box = Box::new(10); + | ^ + | + = note: see issue #32838 for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'allocator_api' + --> $DIR/suggest-vec-allocator-api.rs:7:24 + | +LL | let _ = Vec::::new(); + | -----^ + | | + | help: consider wrapping the inner types in tuple: `(u16, _)` + | + = note: see issue #32838 for more information + = help: add `#![feature(allocator_api)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/stable-addr-of.rs b/tests/ui/stable-addr-of.rs new file mode 100644 index 000000000..99839166e --- /dev/null +++ b/tests/ui/stable-addr-of.rs @@ -0,0 +1,8 @@ +// run-pass +// Issue #2040 + + +pub fn main() { + let foo: isize = 1; + assert_eq!(&foo as *const isize, &foo as *const isize); +} diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr b/tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr new file mode 100644 index 000000000..548877155 --- /dev/null +++ b/tests/ui/stack-protector/warn-stack-protector-unsupported.all.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=all` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr b/tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr new file mode 100644 index 000000000..f7a1ee39f --- /dev/null +++ b/tests/ui/stack-protector/warn-stack-protector-unsupported.basic.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=basic` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.rs b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs new file mode 100644 index 000000000..6df5d3cd5 --- /dev/null +++ b/tests/ui/stack-protector/warn-stack-protector-unsupported.rs @@ -0,0 +1,19 @@ +// build-pass +// revisions: all strong basic +// compile-flags: --target nvptx64-nvidia-cuda +// needs-llvm-components: nvptx +// [all] compile-flags: -Z stack-protector=all +// [strong] compile-flags: -Z stack-protector=strong +// [basic] compile-flags: -Z stack-protector=basic + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn main(){} diff --git a/tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr b/tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr new file mode 100644 index 000000000..ccc2f9f2c --- /dev/null +++ b/tests/ui/stack-protector/warn-stack-protector-unsupported.strong.stderr @@ -0,0 +1,4 @@ +warning: `-Z stack-protector=strong` is not supported for target nvptx64-nvidia-cuda and will be ignored + +warning: 1 warning emitted + diff --git a/tests/ui/static/auxiliary/extern-statics.rs b/tests/ui/static/auxiliary/extern-statics.rs new file mode 100644 index 000000000..c090bc79f --- /dev/null +++ b/tests/ui/static/auxiliary/extern-statics.rs @@ -0,0 +1,4 @@ +extern "C" { + pub static XA: u8; + pub static mut XB: u8; +} diff --git a/tests/ui/static/auxiliary/issue_24843.rs b/tests/ui/static/auxiliary/issue_24843.rs new file mode 100644 index 000000000..6ca04f860 --- /dev/null +++ b/tests/ui/static/auxiliary/issue_24843.rs @@ -0,0 +1 @@ +pub static TEST_STR: &'static str = "Hello world"; diff --git a/tests/ui/static/auxiliary/nested_item.rs b/tests/ui/static/auxiliary/nested_item.rs new file mode 100644 index 000000000..9db9d19d6 --- /dev/null +++ b/tests/ui/static/auxiliary/nested_item.rs @@ -0,0 +1,30 @@ +// original problem +pub fn foo() -> isize { + { + static foo: isize = 2; + foo + } +} + +// issue 8134 +struct Foo; +impl Foo { + pub fn foo(&self) { + static X: usize = 1; + } +} + +// issue 8134 +pub struct Parser(T); +impl> Parser { + fn in_doctype(&mut self) { + static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E']; + } +} + +struct Bar; +impl Foo { + pub fn bar(&self) { + static X: usize = 1; + } +} diff --git a/tests/ui/static/auxiliary/static-priv-by-default.rs b/tests/ui/static/auxiliary/static-priv-by-default.rs new file mode 100644 index 000000000..41f368f46 --- /dev/null +++ b/tests/ui/static/auxiliary/static-priv-by-default.rs @@ -0,0 +1,27 @@ +// aux-build:static_priv_by_default.rs + +extern crate static_priv_by_default; + +mod child { + pub mod childs_child { + static private: isize = 0; + pub static public: isize = 0; + } +} + +fn foo(_: isize) {} + +fn full_ref() { + foo(static_priv_by_default::private); //~ ERROR: static `private` is private + foo(static_priv_by_default::public); + foo(child::childs_child::private); //~ ERROR: static `private` is private + foo(child::childs_child::public); +} + +fn medium_ref() { + use child::childs_child; + foo(childs_child::private); //~ ERROR: static `private` is private + foo(childs_child::public); +} + +fn main() {} diff --git a/tests/ui/static/auxiliary/static_priv_by_default.rs b/tests/ui/static/auxiliary/static_priv_by_default.rs new file mode 100644 index 000000000..39f912066 --- /dev/null +++ b/tests/ui/static/auxiliary/static_priv_by_default.rs @@ -0,0 +1,51 @@ +#![crate_type = "lib"] + +static private: isize = 0; +pub static public: isize = 0; + +pub struct A(()); + +impl A { + fn foo() {} +} + +mod foo { + pub static a: isize = 0; + pub fn b() {} + pub struct c; + pub enum d {} + pub type e = isize; + + pub struct A(()); + + impl A { + fn foo() {} + } + + // these are public so the parent can re-export them. + pub static reexported_a: isize = 0; + pub fn reexported_b() {} + pub struct reexported_c; + pub enum reexported_d {} + pub type reexported_e = isize; +} + +pub mod bar { + pub use foo::reexported_a as e; + pub use foo::reexported_b as f; + pub use foo::reexported_c as g; + pub use foo::reexported_d as h; + pub use foo::reexported_e as i; +} + +pub static a: isize = 0; +pub fn b() {} +pub struct c; +pub enum d {} +pub type e = isize; + +static j: isize = 0; +fn k() {} +struct l; +enum m {} +type n = isize; diff --git a/tests/ui/static/bad-const-type.rs b/tests/ui/static/bad-const-type.rs new file mode 100644 index 000000000..934ee353d --- /dev/null +++ b/tests/ui/static/bad-const-type.rs @@ -0,0 +1,4 @@ +static i: String = 10; +//~^ ERROR mismatched types +//~| expected struct `String`, found integer +fn main() { println!("{}", i); } diff --git a/tests/ui/static/bad-const-type.stderr b/tests/ui/static/bad-const-type.stderr new file mode 100644 index 000000000..dcc1ee07c --- /dev/null +++ b/tests/ui/static/bad-const-type.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/bad-const-type.rs:1:20 + | +LL | static i: String = 10; + | ^^- help: try using a conversion method: `.to_string()` + | | + | expected struct `String`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/issue-18118-2.rs b/tests/ui/static/issue-18118-2.rs new file mode 100644 index 000000000..f712a2eed --- /dev/null +++ b/tests/ui/static/issue-18118-2.rs @@ -0,0 +1,6 @@ +pub fn main() { + const z: &'static isize = { + static p: isize = 3; + &p //~ ERROR constants cannot refer to statics + }; +} diff --git a/tests/ui/static/issue-18118-2.stderr b/tests/ui/static/issue-18118-2.stderr new file mode 100644 index 000000000..4fc3ca78f --- /dev/null +++ b/tests/ui/static/issue-18118-2.stderr @@ -0,0 +1,11 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/issue-18118-2.rs:4:10 + | +LL | &p + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0013`. diff --git a/tests/ui/static/issue-18118.rs b/tests/ui/static/issue-18118.rs new file mode 100644 index 000000000..f58a3de28 --- /dev/null +++ b/tests/ui/static/issue-18118.rs @@ -0,0 +1,6 @@ +pub fn main() { + const z: &'static isize = { + let p = 3; + &p //~ ERROR `p` does not live long enough + }; +} diff --git a/tests/ui/static/issue-18118.stderr b/tests/ui/static/issue-18118.stderr new file mode 100644 index 000000000..49798a148 --- /dev/null +++ b/tests/ui/static/issue-18118.stderr @@ -0,0 +1,14 @@ +error[E0597]: `p` does not live long enough + --> $DIR/issue-18118.rs:4:9 + | +LL | &p + | ^^ + | | + | borrowed value does not live long enough + | using this value as a constant requires that `p` is borrowed for `'static` +LL | }; + | - `p` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/static/issue-24843.rs b/tests/ui/static/issue-24843.rs new file mode 100644 index 000000000..0b3397e21 --- /dev/null +++ b/tests/ui/static/issue-24843.rs @@ -0,0 +1,8 @@ +// aux-build: issue_24843.rs +// check-pass + +extern crate issue_24843; + +static _TEST_STR_2: &'static str = &issue_24843::TEST_STR; + +fn main() {} diff --git a/tests/ui/static/issue-34194.rs b/tests/ui/static/issue-34194.rs new file mode 100644 index 000000000..6dce556e9 --- /dev/null +++ b/tests/ui/static/issue-34194.rs @@ -0,0 +1,11 @@ +// build-pass +#![allow(dead_code)] + +struct A { + a: &'static (), +} + +static B: &'static A = &A { a: &() }; +static C: &'static A = &B; + +fn main() {} diff --git a/tests/ui/static/issue-5216.rs b/tests/ui/static/issue-5216.rs new file mode 100644 index 000000000..4072a57cb --- /dev/null +++ b/tests/ui/static/issue-5216.rs @@ -0,0 +1,10 @@ +fn f() { } +struct S(Box); +pub static C: S = S(f); //~ ERROR mismatched types + + +fn g() { } +type T = Box; +pub static D: T = g; //~ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/static/issue-5216.stderr b/tests/ui/static/issue-5216.stderr new file mode 100644 index 000000000..1afff28f0 --- /dev/null +++ b/tests/ui/static/issue-5216.stderr @@ -0,0 +1,28 @@ +error[E0308]: mismatched types + --> $DIR/issue-5216.rs:3:21 + | +LL | pub static C: S = S(f); + | - ^ expected struct `Box`, found fn item + | | + | arguments to this struct are incorrect + | + = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>` + found fn item `fn() {f}` +note: tuple struct defined here + --> $DIR/issue-5216.rs:2:8 + | +LL | struct S(Box); + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-5216.rs:8:19 + | +LL | pub static D: T = g; + | ^ expected struct `Box`, found fn item + | + = note: expected struct `Box<(dyn FnMut() + Sync + 'static)>` + found fn item `fn() {g}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/nested_item_main.rs b/tests/ui/static/nested_item_main.rs new file mode 100644 index 000000000..2fe00aede --- /dev/null +++ b/tests/ui/static/nested_item_main.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:nested_item.rs + + +extern crate nested_item; + +pub fn main() { + assert_eq!(2, nested_item::foo::<()>()); + assert_eq!(2, nested_item::foo::()); +} diff --git a/tests/ui/static/refer-to-other-statics-by-value.rs b/tests/ui/static/refer-to-other-statics-by-value.rs new file mode 100644 index 000000000..90f1980f8 --- /dev/null +++ b/tests/ui/static/refer-to-other-statics-by-value.rs @@ -0,0 +1,8 @@ +// run-pass + +static A: usize = 42; +static B: usize = A; + +fn main() { + assert_eq!(B, 42); +} diff --git a/tests/ui/static/safe-extern-statics-mut.mir.stderr b/tests/ui/static/safe-extern-statics-mut.mir.stderr new file mode 100644 index 000000000..cec5f9d9c --- /dev/null +++ b/tests/ui/static/safe-extern-statics-mut.mir.stderr @@ -0,0 +1,35 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:13:13 + | +LL | let b = B; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:14:14 + | +LL | let rb = &B; + | ^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:15:14 + | +LL | let xb = XB; + | ^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:16:15 + | +LL | let xrb = &XB; + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/safe-extern-statics-mut.rs b/tests/ui/static/safe-extern-statics-mut.rs new file mode 100644 index 000000000..389a4589a --- /dev/null +++ b/tests/ui/static/safe-extern-statics-mut.rs @@ -0,0 +1,17 @@ +// aux-build:extern-statics.rs +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +extern crate extern_statics; +use extern_statics::*; + +extern "C" { + static mut B: u8; +} + +fn main() { + let b = B; //~ ERROR use of mutable static is unsafe + let rb = &B; //~ ERROR use of mutable static is unsafe + let xb = XB; //~ ERROR use of mutable static is unsafe + let xrb = &XB; //~ ERROR use of mutable static is unsafe +} diff --git a/tests/ui/static/safe-extern-statics-mut.thir.stderr b/tests/ui/static/safe-extern-statics-mut.thir.stderr new file mode 100644 index 000000000..8e6d2805a --- /dev/null +++ b/tests/ui/static/safe-extern-statics-mut.thir.stderr @@ -0,0 +1,35 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:13:13 + | +LL | let b = B; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:14:15 + | +LL | let rb = &B; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:15:14 + | +LL | let xb = XB; + | ^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics-mut.rs:16:16 + | +LL | let xrb = &XB; + | ^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/safe-extern-statics.mir.stderr b/tests/ui/static/safe-extern-statics.mir.stderr new file mode 100644 index 000000000..102abd081 --- /dev/null +++ b/tests/ui/static/safe-extern-statics.mir.stderr @@ -0,0 +1,35 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:13:13 + | +LL | let a = A; + | ^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:14:14 + | +LL | let ra = &A; + | ^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:15:14 + | +LL | let xa = XA; + | ^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:16:15 + | +LL | let xra = &XA; + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/safe-extern-statics.rs b/tests/ui/static/safe-extern-statics.rs new file mode 100644 index 000000000..0aa90c442 --- /dev/null +++ b/tests/ui/static/safe-extern-statics.rs @@ -0,0 +1,17 @@ +// aux-build:extern-statics.rs +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +extern crate extern_statics; +use extern_statics::*; + +extern "C" { + static A: u8; +} + +fn main() { + let a = A; //~ ERROR use of extern static is unsafe + let ra = &A; //~ ERROR use of extern static is unsafe + let xa = XA; //~ ERROR use of extern static is unsafe + let xra = &XA; //~ ERROR use of extern static is unsafe +} diff --git a/tests/ui/static/safe-extern-statics.thir.stderr b/tests/ui/static/safe-extern-statics.thir.stderr new file mode 100644 index 000000000..7fd2182c4 --- /dev/null +++ b/tests/ui/static/safe-extern-statics.thir.stderr @@ -0,0 +1,35 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:13:13 + | +LL | let a = A; + | ^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:14:15 + | +LL | let ra = &A; + | ^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:15:14 + | +LL | let xa = XA; + | ^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/safe-extern-statics.rs:16:16 + | +LL | let xra = &XA; + | ^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/static-closures.rs b/tests/ui/static/static-closures.rs new file mode 100644 index 000000000..1bd518d6f --- /dev/null +++ b/tests/ui/static/static-closures.rs @@ -0,0 +1,4 @@ +fn main() { + static || {}; + //~^ ERROR closures cannot be static +} diff --git a/tests/ui/static/static-closures.stderr b/tests/ui/static/static-closures.stderr new file mode 100644 index 000000000..99235e26e --- /dev/null +++ b/tests/ui/static/static-closures.stderr @@ -0,0 +1,9 @@ +error[E0697]: closures cannot be static + --> $DIR/static-closures.rs:2:5 + | +LL | static || {}; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0697`. diff --git a/tests/ui/static/static-drop-scope.rs b/tests/ui/static/static-drop-scope.rs new file mode 100644 index 000000000..34afa9873 --- /dev/null +++ b/tests/ui/static/static-drop-scope.rs @@ -0,0 +1,37 @@ +struct WithDtor; + +impl Drop for WithDtor { + fn drop(&mut self) {} +} + +static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); +//~^ ERROR destructor of +//~| ERROR temporary value dropped while borrowed + +const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); +//~^ ERROR destructor of +//~| ERROR temporary value dropped while borrowed + +static EARLY_DROP_S: i32 = (WithDtor, 0).1; +//~^ ERROR destructor of + +const EARLY_DROP_C: i32 = (WithDtor, 0).1; +//~^ ERROR destructor of + +const fn const_drop(_: T) {} +//~^ ERROR destructor of + +const fn const_drop2(x: T) { + (x, ()).1 + //~^ ERROR destructor of +} + +const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; +//~^ ERROR destructor of + +const HELPER: Option = Some(WithDtor); + +const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; +//~^ ERROR destructor of + +fn main () {} diff --git a/tests/ui/static/static-drop-scope.stderr b/tests/ui/static/static-drop-scope.stderr new file mode 100644 index 000000000..cedcb7367 --- /dev/null +++ b/tests/ui/static/static-drop-scope.stderr @@ -0,0 +1,89 @@ +error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:7:60 + | +LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); + | ^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in statics + +error[E0716]: temporary value dropped while borrowed + --> $DIR/static-drop-scope.rs:7:60 + | +LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); + | ------^^^^^^^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:11:59 + | +LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); + | ^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0716]: temporary value dropped while borrowed + --> $DIR/static-drop-scope.rs:11:59 + | +LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); + | ------^^^^^^^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:15:28 + | +LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in statics + +error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:18:27 + | +LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:21:24 + | +LL | const fn const_drop(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:25:5 + | +LL | (x, ()).1 + | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions +LL | +LL | } + | - value is dropped here + +error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:29:34 + | +LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; + | ^^^^^^^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time + --> $DIR/static-drop-scope.rs:34:43 + | +LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; + | ^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/static/static-extern-type.rs b/tests/ui/static/static-extern-type.rs new file mode 100644 index 000000000..4fa48fa13 --- /dev/null +++ b/tests/ui/static/static-extern-type.rs @@ -0,0 +1,27 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![feature(extern_types)] + +pub mod a { + extern "C" { + pub type StartFn; + pub static start: StartFn; + } +} + +pub mod b { + #[repr(transparent)] + pub struct TransparentType(::a::StartFn); + extern "C" { + pub static start: TransparentType; + } +} + +pub mod c { + #[repr(C)] + pub struct CType(u32, ::b::TransparentType); + extern "C" { + pub static start: CType; + } +} + +fn main() {} diff --git a/tests/ui/static/static-items-cant-move.rs b/tests/ui/static/static-items-cant-move.rs new file mode 100644 index 000000000..3e7aaa0b0 --- /dev/null +++ b/tests/ui/static/static-items-cant-move.rs @@ -0,0 +1,19 @@ +// Verifies that static items can't be moved + +struct B; + +struct Foo { + foo: isize, + b: B, +} + +static BAR: Foo = Foo { foo: 5, b: B }; + + +fn test(f: Foo) { + let _f = Foo{foo: 4, ..f}; +} + +fn main() { + test(BAR); //~ ERROR cannot move out of static item +} diff --git a/tests/ui/static/static-items-cant-move.stderr b/tests/ui/static/static-items-cant-move.stderr new file mode 100644 index 000000000..235e9ee9b --- /dev/null +++ b/tests/ui/static/static-items-cant-move.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of static item `BAR` + --> $DIR/static-items-cant-move.rs:18:10 + | +LL | test(BAR); + | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/static/static-lifetime-bound.rs b/tests/ui/static/static-lifetime-bound.rs new file mode 100644 index 000000000..b5da91ec3 --- /dev/null +++ b/tests/ui/static/static-lifetime-bound.rs @@ -0,0 +1,6 @@ +fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a` + +fn main() { + let x = 0; + f(&x); //~ERROR does not live long enough +} diff --git a/tests/ui/static/static-lifetime-bound.stderr b/tests/ui/static/static-lifetime-bound.stderr new file mode 100644 index 000000000..ef07a8931 --- /dev/null +++ b/tests/ui/static/static-lifetime-bound.stderr @@ -0,0 +1,22 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/static-lifetime-bound.rs:1:6 + | +LL | fn f<'a: 'static>(_: &'a i32) {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error[E0597]: `x` does not live long enough + --> $DIR/static-lifetime-bound.rs:5:7 + | +LL | f(&x); + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/static/static-lifetime.rs b/tests/ui/static/static-lifetime.rs new file mode 100644 index 000000000..ce1eeb610 --- /dev/null +++ b/tests/ui/static/static-lifetime.rs @@ -0,0 +1,6 @@ +pub trait Arbitrary: Sized + 'static {} + +impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound + +fn main() { +} diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr new file mode 100644 index 000000000..4af3370c7 --- /dev/null +++ b/tests/ui/static/static-lifetime.stderr @@ -0,0 +1,16 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/static-lifetime.rs:3:20 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/static-lifetime.rs:3:6 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0478`. diff --git a/tests/ui/static/static-method-privacy.rs b/tests/ui/static/static-method-privacy.rs new file mode 100644 index 000000000..9ee59b320 --- /dev/null +++ b/tests/ui/static/static-method-privacy.rs @@ -0,0 +1,10 @@ +mod a { + pub struct S; + impl S { + fn new() -> S { S } + } +} + +fn main() { + let _ = a::S::new(); //~ ERROR associated function `new` is private +} diff --git a/tests/ui/static/static-method-privacy.stderr b/tests/ui/static/static-method-privacy.stderr new file mode 100644 index 000000000..4be1b22fc --- /dev/null +++ b/tests/ui/static/static-method-privacy.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `new` is private + --> $DIR/static-method-privacy.rs:9:19 + | +LL | fn new() -> S { S } + | ------------- private associated function defined here +... +LL | let _ = a::S::new(); + | ^^^ private associated function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/static/static-mut-bad-types.rs b/tests/ui/static/static-mut-bad-types.rs new file mode 100644 index 000000000..8a98b1b7f --- /dev/null +++ b/tests/ui/static/static-mut-bad-types.rs @@ -0,0 +1,7 @@ +static mut a: isize = 3; + +fn main() { + unsafe { + a = true; //~ ERROR: mismatched types + } +} diff --git a/tests/ui/static/static-mut-bad-types.stderr b/tests/ui/static/static-mut-bad-types.stderr new file mode 100644 index 000000000..983e1026f --- /dev/null +++ b/tests/ui/static/static-mut-bad-types.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/static-mut-bad-types.rs:5:13 + | +LL | static mut a: isize = 3; + | ----- expected due to this type +... +LL | a = true; + | ^^^^ expected `isize`, found `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/static-mut-foreign-requires-unsafe.mir.stderr b/tests/ui/static/static-mut-foreign-requires-unsafe.mir.stderr new file mode 100644 index 000000000..a4659bc87 --- /dev/null +++ b/tests/ui/static/static-mut-foreign-requires-unsafe.mir.stderr @@ -0,0 +1,27 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-foreign-requires-unsafe.rs:9:5 + | +LL | a += 3; + | ^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-foreign-requires-unsafe.rs:10:5 + | +LL | a = 4; + | ^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-foreign-requires-unsafe.rs:11:14 + | +LL | let _b = a; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/static-mut-foreign-requires-unsafe.rs b/tests/ui/static/static-mut-foreign-requires-unsafe.rs new file mode 100644 index 000000000..4f96acb33 --- /dev/null +++ b/tests/ui/static/static-mut-foreign-requires-unsafe.rs @@ -0,0 +1,12 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +extern "C" { + static mut a: i32; +} + +fn main() { + a += 3; //~ ERROR: requires unsafe + a = 4; //~ ERROR: requires unsafe + let _b = a; //~ ERROR: requires unsafe +} diff --git a/tests/ui/static/static-mut-foreign-requires-unsafe.thir.stderr b/tests/ui/static/static-mut-foreign-requires-unsafe.thir.stderr new file mode 100644 index 000000000..2c62d4d8f --- /dev/null +++ b/tests/ui/static/static-mut-foreign-requires-unsafe.thir.stderr @@ -0,0 +1,27 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-foreign-requires-unsafe.rs:9:5 + | +LL | a += 3; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-foreign-requires-unsafe.rs:10:5 + | +LL | a = 4; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-foreign-requires-unsafe.rs:11:14 + | +LL | let _b = a; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/static-mut-not-constant.rs b/tests/ui/static/static-mut-not-constant.rs new file mode 100644 index 000000000..2091fffd4 --- /dev/null +++ b/tests/ui/static/static-mut-not-constant.rs @@ -0,0 +1,6 @@ +#![feature(box_syntax)] + +static mut a: Box = box 3; +//~^ ERROR allocations are not allowed in statics + +fn main() {} diff --git a/tests/ui/static/static-mut-not-constant.stderr b/tests/ui/static/static-mut-not-constant.stderr new file mode 100644 index 000000000..a0fa24515 --- /dev/null +++ b/tests/ui/static/static-mut-not-constant.stderr @@ -0,0 +1,9 @@ +error[E0010]: allocations are not allowed in statics + --> $DIR/static-mut-not-constant.rs:3:28 + | +LL | static mut a: Box = box 3; + | ^^^^^ allocation not allowed in statics + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0010`. diff --git a/tests/ui/static/static-mut-not-pat.rs b/tests/ui/static/static-mut-not-pat.rs new file mode 100644 index 000000000..ce5ae164c --- /dev/null +++ b/tests/ui/static/static-mut-not-pat.rs @@ -0,0 +1,43 @@ +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +static mut a: isize = 3; + +fn main() { + // If they can't be matched against, then it's possible to capture the same + // name as a variable, hence this should be an unreachable pattern situation + // instead of spitting out a custom error about some identifier collisions + // (we should allow shadowing) + match 4 { + a => {} //~ ERROR match bindings cannot shadow statics + _ => {} + } +} + +struct NewBool(bool); +enum Direction { + North, + East, + South, + West +} +const NEW_FALSE: NewBool = NewBool(false); +struct Foo { + bar: Option, + baz: NewBool +} + +static mut STATIC_MUT_FOO: Foo = Foo { bar: Some(Direction::West), baz: NEW_FALSE }; + +fn mutable_statics() { + match (Foo { bar: Some(Direction::North), baz: NewBool(true) }) { + Foo { bar: None, baz: NewBool(true) } => (), + STATIC_MUT_FOO => (), + //~^ ERROR match bindings cannot shadow statics + Foo { bar: Some(Direction::South), .. } => (), + Foo { bar: Some(EAST), .. } => (), + Foo { bar: Some(Direction::North), baz: NewBool(true) } => (), + Foo { bar: Some(EAST), baz: NewBool(false) } => () + } +} diff --git a/tests/ui/static/static-mut-not-pat.stderr b/tests/ui/static/static-mut-not-pat.stderr new file mode 100644 index 000000000..33c1cd6a5 --- /dev/null +++ b/tests/ui/static/static-mut-not-pat.stderr @@ -0,0 +1,21 @@ +error[E0530]: match bindings cannot shadow statics + --> $DIR/static-mut-not-pat.rs:13:9 + | +LL | static mut a: isize = 3; + | ------------------------ the static `a` is defined here +... +LL | a => {} + | ^ cannot be named the same as a static + +error[E0530]: match bindings cannot shadow statics + --> $DIR/static-mut-not-pat.rs:36:9 + | +LL | static mut STATIC_MUT_FOO: Foo = Foo { bar: Some(Direction::West), baz: NEW_FALSE }; + | ------------------------------------------------------------------------------------ the static `STATIC_MUT_FOO` is defined here +... +LL | STATIC_MUT_FOO => (), + | ^^^^^^^^^^^^^^ cannot be named the same as a static + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0530`. diff --git a/tests/ui/static/static-mut-requires-unsafe.mir.stderr b/tests/ui/static/static-mut-requires-unsafe.mir.stderr new file mode 100644 index 000000000..0d4ce056f --- /dev/null +++ b/tests/ui/static/static-mut-requires-unsafe.mir.stderr @@ -0,0 +1,27 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-requires-unsafe.rs:7:5 + | +LL | a += 3; + | ^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-requires-unsafe.rs:8:5 + | +LL | a = 4; + | ^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-requires-unsafe.rs:9:14 + | +LL | let _b = a; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/static-mut-requires-unsafe.rs b/tests/ui/static/static-mut-requires-unsafe.rs new file mode 100644 index 000000000..ea3ba0950 --- /dev/null +++ b/tests/ui/static/static-mut-requires-unsafe.rs @@ -0,0 +1,10 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +static mut a: isize = 3; + +fn main() { + a += 3; //~ ERROR: requires unsafe + a = 4; //~ ERROR: requires unsafe + let _b = a; //~ ERROR: requires unsafe +} diff --git a/tests/ui/static/static-mut-requires-unsafe.thir.stderr b/tests/ui/static/static-mut-requires-unsafe.thir.stderr new file mode 100644 index 000000000..1a1cf1427 --- /dev/null +++ b/tests/ui/static/static-mut-requires-unsafe.thir.stderr @@ -0,0 +1,27 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-requires-unsafe.rs:7:5 + | +LL | a += 3; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-requires-unsafe.rs:8:5 + | +LL | a = 4; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/static-mut-requires-unsafe.rs:9:14 + | +LL | let _b = a; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/static-priv-by-default2.rs b/tests/ui/static/static-priv-by-default2.rs new file mode 100644 index 000000000..bbbdb253b --- /dev/null +++ b/tests/ui/static/static-priv-by-default2.rs @@ -0,0 +1,30 @@ +// aux-build:static_priv_by_default.rs + +extern crate static_priv_by_default; + +mod child { + pub mod childs_child { + static private: isize = 0; + pub static public: isize = 0; + } +} + +fn foo(_: T) {} + +fn test1() { + use child::childs_child::private; + //~^ ERROR: static `private` is private + use child::childs_child::public; + + foo(private); +} + +fn test2() { + use static_priv_by_default::private; + //~^ ERROR: static `private` is private + use static_priv_by_default::public; + + foo(private); +} + +fn main() {} diff --git a/tests/ui/static/static-priv-by-default2.stderr b/tests/ui/static/static-priv-by-default2.stderr new file mode 100644 index 000000000..b14e096d6 --- /dev/null +++ b/tests/ui/static/static-priv-by-default2.stderr @@ -0,0 +1,27 @@ +error[E0603]: static `private` is private + --> $DIR/static-priv-by-default2.rs:15:30 + | +LL | use child::childs_child::private; + | ^^^^^^^ private static + | +note: the static `private` is defined here + --> $DIR/static-priv-by-default2.rs:7:9 + | +LL | static private: isize = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0603]: static `private` is private + --> $DIR/static-priv-by-default2.rs:23:33 + | +LL | use static_priv_by_default::private; + | ^^^^^^^ private static + | +note: the static `private` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:3:1 + | +LL | static private: isize = 0; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/static/static-reference-to-fn-1.rs b/tests/ui/static/static-reference-to-fn-1.rs new file mode 100644 index 000000000..c15634dbf --- /dev/null +++ b/tests/ui/static/static-reference-to-fn-1.rs @@ -0,0 +1,24 @@ +struct A<'a> { + func: &'a fn() -> Option +} + +impl<'a> A<'a> { + fn call(&self) -> Option { + (*self.func)() + } +} + +fn foo() -> Option { + None +} + +fn create() -> A<'static> { + A { + func: &foo, //~ ERROR mismatched types + } +} + +fn main() { + let a = create(); + a.call(); +} diff --git a/tests/ui/static/static-reference-to-fn-1.stderr b/tests/ui/static/static-reference-to-fn-1.stderr new file mode 100644 index 000000000..67b478bdb --- /dev/null +++ b/tests/ui/static/static-reference-to-fn-1.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/static-reference-to-fn-1.rs:17:15 + | +LL | func: &foo, + | ^^^^ expected fn pointer, found fn item + | + = note: expected reference `&fn() -> Option` + found reference `&fn() -> Option {foo}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/static/static-reference-to-fn-2.rs b/tests/ui/static/static-reference-to-fn-2.rs new file mode 100644 index 000000000..6693667c0 --- /dev/null +++ b/tests/ui/static/static-reference-to-fn-2.rs @@ -0,0 +1,54 @@ +fn id(x: T) -> T { x } + +struct StateMachineIter<'a> { + statefn: &'a StateMachineFunc<'a> +} + +type StateMachineFunc<'a> = fn(&mut StateMachineIter<'a>) -> Option<&'static str>; + +impl<'a> Iterator for StateMachineIter<'a> { + type Item = &'static str; + + fn next(&mut self) -> Option<&'static str> { + return (*self.statefn)(self); + } +} + +fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { + self_.statefn = &id(state2 as StateMachineFunc); + //~^ ERROR temporary value dropped while borrowed + return Some("state1"); +} + +fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { + self_.statefn = &id(state3 as StateMachineFunc); + //~^ ERROR temporary value dropped while borrowed + return Some("state2"); +} + +fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { + self_.statefn = &id(finished as StateMachineFunc); + //~^ ERROR temporary value dropped while borrowed + return Some("state3"); +} + +fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> { + return None; +} + +fn state_iter() -> StateMachineIter<'static> { + StateMachineIter { + //~^ ERROR cannot return value referencing temporary value + statefn: &id(state1 as StateMachineFunc) + } +} + + +fn main() { + let mut it = state_iter(); + println!("{:?}",it.next()); + println!("{:?}",it.next()); + println!("{:?}",it.next()); + println!("{:?}",it.next()); + println!("{:?}",it.next()); +} diff --git a/tests/ui/static/static-reference-to-fn-2.stderr b/tests/ui/static/static-reference-to-fn-2.stderr new file mode 100644 index 000000000..133d8ec2e --- /dev/null +++ b/tests/ui/static/static-reference-to-fn-2.stderr @@ -0,0 +1,49 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/static-reference-to-fn-2.rs:18:22 + | +LL | fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { + | ----- has type `&mut StateMachineIter<'1>` +LL | self_.statefn = &id(state2 as StateMachineFunc); + | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | assignment requires that borrow lasts for `'1` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/static-reference-to-fn-2.rs:24:22 + | +LL | fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { + | ----- has type `&mut StateMachineIter<'1>` +LL | self_.statefn = &id(state3 as StateMachineFunc); + | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | assignment requires that borrow lasts for `'1` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/static-reference-to-fn-2.rs:30:22 + | +LL | fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { + | ----- has type `&mut StateMachineIter<'1>` +LL | self_.statefn = &id(finished as StateMachineFunc); + | -----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | assignment requires that borrow lasts for `'1` + +error[E0515]: cannot return value referencing temporary value + --> $DIR/static-reference-to-fn-2.rs:40:5 + | +LL | / StateMachineIter { +LL | | +LL | | statefn: &id(state1 as StateMachineFunc) + | | ------------------------------ temporary value created here +LL | | } + | |_____^ returns a value referencing data owned by the current function + | + = help: use `.collect()` to allocate the iterator + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0515, E0716. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/static/static-region-bound.rs b/tests/ui/static/static-region-bound.rs new file mode 100644 index 000000000..d70706e57 --- /dev/null +++ b/tests/ui/static/static-region-bound.rs @@ -0,0 +1,12 @@ +fn id(x: T) -> T { x } + +fn f(_: T) {} + +fn main() { + + let x: Box<_> = Box::new(3); + f(x); + + let x = &id(3); //~ ERROR temporary value dropped while borrowed + f(x); +} diff --git a/tests/ui/static/static-region-bound.stderr b/tests/ui/static/static-region-bound.stderr new file mode 100644 index 000000000..1a607e3c0 --- /dev/null +++ b/tests/ui/static/static-region-bound.stderr @@ -0,0 +1,13 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/static-region-bound.rs:10:14 + | +LL | let x = &id(3); + | ^^^^^ creates a temporary value which is freed while still in use +LL | f(x); + | ---- argument requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/static/static-vec-repeat-not-constant.rs b/tests/ui/static/static-vec-repeat-not-constant.rs new file mode 100644 index 000000000..61c87b144 --- /dev/null +++ b/tests/ui/static/static-vec-repeat-not-constant.rs @@ -0,0 +1,6 @@ +fn foo() -> isize { 23 } + +static a: [isize; 2] = [foo(); 2]; +//~^ ERROR: E0015 + +fn main() {} diff --git a/tests/ui/static/static-vec-repeat-not-constant.stderr b/tests/ui/static/static-vec-repeat-not-constant.stderr new file mode 100644 index 000000000..dec012318 --- /dev/null +++ b/tests/ui/static/static-vec-repeat-not-constant.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const fn `foo` in statics + --> $DIR/static-vec-repeat-not-constant.rs:3:25 + | +LL | static a: [isize; 2] = [foo(); 2]; + | ^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/static/static_sized_requirement.rs b/tests/ui/static/static_sized_requirement.rs new file mode 100644 index 000000000..3943b2608 --- /dev/null +++ b/tests/ui/static/static_sized_requirement.rs @@ -0,0 +1,12 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(no_core, lang_items)] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +extern "C" { + pub static A: u32; +} diff --git a/tests/ui/static/thread-local-in-ctfe.rs b/tests/ui/static/thread-local-in-ctfe.rs new file mode 100644 index 000000000..547e5445a --- /dev/null +++ b/tests/ui/static/thread-local-in-ctfe.rs @@ -0,0 +1,23 @@ +#![feature(thread_local)] + +#[thread_local] +static A: u32 = 1; + +static B: u32 = A; +//~^ ERROR thread-local statics cannot be accessed at compile-time + +static C: &u32 = &A; +//~^ ERROR thread-local statics cannot be accessed at compile-time + +const D: u32 = A; +//~^ ERROR thread-local statics cannot be accessed at compile-time + +const E: &u32 = &A; +//~^ ERROR thread-local statics cannot be accessed at compile-time + +const fn f() -> u32 { + A + //~^ ERROR thread-local statics cannot be accessed at compile-time +} + +fn main() {} diff --git a/tests/ui/static/thread-local-in-ctfe.stderr b/tests/ui/static/thread-local-in-ctfe.stderr new file mode 100644 index 000000000..fd9676046 --- /dev/null +++ b/tests/ui/static/thread-local-in-ctfe.stderr @@ -0,0 +1,33 @@ +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-in-ctfe.rs:6:17 + | +LL | static B: u32 = A; + | ^ + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-in-ctfe.rs:9:19 + | +LL | static C: &u32 = &A; + | ^ + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-in-ctfe.rs:12:16 + | +LL | const D: u32 = A; + | ^ + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-in-ctfe.rs:15:18 + | +LL | const E: &u32 = &A; + | ^ + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-in-ctfe.rs:19:5 + | +LL | A + | ^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0625`. diff --git a/tests/ui/statics/auxiliary/static-function-pointer-aux.rs b/tests/ui/statics/auxiliary/static-function-pointer-aux.rs new file mode 100644 index 000000000..4dfc25764 --- /dev/null +++ b/tests/ui/statics/auxiliary/static-function-pointer-aux.rs @@ -0,0 +1,4 @@ +pub fn f(x: isize) -> isize { -x } + +pub static F: fn(isize) -> isize = f; +pub static mut MutF: fn(isize) -> isize = f; diff --git a/tests/ui/statics/auxiliary/static-methods-crate.rs b/tests/ui/statics/auxiliary/static-methods-crate.rs new file mode 100644 index 000000000..7ff3bc0dd --- /dev/null +++ b/tests/ui/statics/auxiliary/static-methods-crate.rs @@ -0,0 +1,29 @@ +#![crate_name="static_methods_crate"] +#![crate_type = "lib"] + +pub trait read: Sized { + fn readMaybe(s: String) -> Option; +} + +impl read for isize { + fn readMaybe(s: String) -> Option { + s.parse().ok() + } +} + +impl read for bool { + fn readMaybe(s: String) -> Option { + match &*s { + "true" => Some(true), + "false" => Some(false), + _ => None + } + } +} + +pub fn read(s: String) -> T { + match read::readMaybe(s) { + Some(x) => x, + _ => panic!("read panicked!") + } +} diff --git a/tests/ui/statics/auxiliary/static_fn_inline_xc_aux.rs b/tests/ui/statics/auxiliary/static_fn_inline_xc_aux.rs new file mode 100644 index 000000000..8d0f7f61c --- /dev/null +++ b/tests/ui/statics/auxiliary/static_fn_inline_xc_aux.rs @@ -0,0 +1,12 @@ +pub mod num { + pub trait Num2 { + fn from_int2(n: isize) -> Self; + } +} + +pub mod f64 { + impl ::num::Num2 for f64 { + #[inline] + fn from_int2(n: isize) -> f64 { return n as f64; } + } +} diff --git a/tests/ui/statics/auxiliary/static_fn_trait_xc_aux.rs b/tests/ui/statics/auxiliary/static_fn_trait_xc_aux.rs new file mode 100644 index 000000000..b8aed2c5f --- /dev/null +++ b/tests/ui/statics/auxiliary/static_fn_trait_xc_aux.rs @@ -0,0 +1,11 @@ +pub mod num { + pub trait Num2 { + fn from_int2(n: isize) -> Self; + } +} + +pub mod f64 { + impl ::num::Num2 for f64 { + fn from_int2(n: isize) -> f64 { return n as f64; } + } +} diff --git a/tests/ui/statics/auxiliary/static_mut_xc.rs b/tests/ui/statics/auxiliary/static_mut_xc.rs new file mode 100644 index 000000000..264a2243a --- /dev/null +++ b/tests/ui/statics/auxiliary/static_mut_xc.rs @@ -0,0 +1 @@ +pub static mut a: isize = 3; diff --git a/tests/ui/statics/issue-14227.mir.stderr b/tests/ui/statics/issue-14227.mir.stderr new file mode 100644 index 000000000..8e7a2514d --- /dev/null +++ b/tests/ui/statics/issue-14227.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-14227.rs:7:21 + | +LL | static CRASH: u32 = symbol; + | ^^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/statics/issue-14227.rs b/tests/ui/statics/issue-14227.rs new file mode 100644 index 000000000..5f866ec90 --- /dev/null +++ b/tests/ui/statics/issue-14227.rs @@ -0,0 +1,10 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +extern "C" { + pub static symbol: u32; +} +static CRASH: u32 = symbol; +//~^ ERROR use of extern static is unsafe and requires + +fn main() {} diff --git a/tests/ui/statics/issue-14227.thir.stderr b/tests/ui/statics/issue-14227.thir.stderr new file mode 100644 index 000000000..8e7a2514d --- /dev/null +++ b/tests/ui/statics/issue-14227.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-14227.rs:7:21 + | +LL | static CRASH: u32 = symbol; + | ^^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/statics/issue-15261.rs b/tests/ui/statics/issue-15261.rs new file mode 100644 index 000000000..ec413f6d1 --- /dev/null +++ b/tests/ui/statics/issue-15261.rs @@ -0,0 +1,11 @@ +// build-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +// pretty-expanded FIXME #23616 + +static mut n_mut: usize = 0; + +static n: &'static usize = unsafe{ &n_mut }; + +fn main() {} diff --git a/tests/ui/statics/issue-17233.rs b/tests/ui/statics/issue-17233.rs new file mode 100644 index 000000000..54a12fdf8 --- /dev/null +++ b/tests/ui/statics/issue-17233.rs @@ -0,0 +1,17 @@ +// run-pass + +const X1: &'static [u8] = &[b'1']; +const X2: &'static [u8] = b"1"; +const X3: &'static [u8; 1] = &[b'1']; +const X4: &'static [u8; 1] = b"1"; + +static Y1: u8 = X1[0]; +static Y2: u8 = X2[0]; +static Y3: u8 = X3[0]; +static Y4: u8 = X4[0]; + +fn main() { + assert_eq!(Y1, Y2); + assert_eq!(Y1, Y3); + assert_eq!(Y1, Y4); +} diff --git a/tests/ui/statics/issue-17718-static-sync.rs b/tests/ui/statics/issue-17718-static-sync.rs new file mode 100644 index 000000000..6f278d76b --- /dev/null +++ b/tests/ui/statics/issue-17718-static-sync.rs @@ -0,0 +1,12 @@ +#![feature(negative_impls)] + +use std::marker::Sync; + +struct Foo; +impl !Sync for Foo {} + +static FOO: usize = 3; +static BAR: Foo = Foo; +//~^ ERROR: `Foo` cannot be shared between threads safely [E0277] + +fn main() {} diff --git a/tests/ui/statics/issue-17718-static-sync.stderr b/tests/ui/statics/issue-17718-static-sync.stderr new file mode 100644 index 000000000..bc6e45e59 --- /dev/null +++ b/tests/ui/statics/issue-17718-static-sync.stderr @@ -0,0 +1,12 @@ +error[E0277]: `Foo` cannot be shared between threads safely + --> $DIR/issue-17718-static-sync.rs:9:13 + | +LL | static BAR: Foo = Foo; + | ^^^ `Foo` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Foo` + = note: shared static variables must have a type that implements `Sync` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/statics/issue-17718-static-unsafe-interior.rs b/tests/ui/statics/issue-17718-static-unsafe-interior.rs new file mode 100644 index 000000000..65a8713ba --- /dev/null +++ b/tests/ui/statics/issue-17718-static-unsafe-interior.rs @@ -0,0 +1,52 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] +// pretty-expanded FIXME #23616 + +use std::marker; +use std::cell::UnsafeCell; + +struct MyUnsafePack(UnsafeCell); + +unsafe impl Sync for MyUnsafePack {} + +struct MyUnsafe { + value: MyUnsafePack +} + +impl MyUnsafe { + fn forbidden(&self) {} +} + +unsafe impl Sync for MyUnsafe {} + +enum UnsafeEnum { + VariantSafe, + VariantUnsafe(UnsafeCell) +} + +unsafe impl Sync for UnsafeEnum {} + +static STATIC1: UnsafeEnum = UnsafeEnum::VariantSafe; + +static STATIC2: MyUnsafePack = MyUnsafePack(UnsafeCell::new(1)); +const CONST: MyUnsafePack = MyUnsafePack(UnsafeCell::new(1)); +static STATIC3: MyUnsafe = MyUnsafe{value: CONST}; + +static STATIC4: &'static MyUnsafePack = &STATIC2; + +struct Wrap { + value: T +} + +unsafe impl Sync for Wrap {} + +static UNSAFE: MyUnsafePack = MyUnsafePack(UnsafeCell::new(2)); +static WRAPPED_UNSAFE: Wrap<&'static MyUnsafePack> = Wrap { value: &UNSAFE }; + +fn main() { + let a = &STATIC1; + + STATIC3.forbidden() +} diff --git a/tests/ui/statics/issue-44373-2.rs b/tests/ui/statics/issue-44373-2.rs new file mode 100644 index 000000000..194ce1dca --- /dev/null +++ b/tests/ui/statics/issue-44373-2.rs @@ -0,0 +1,11 @@ +// check-pass +#![allow(dead_code)] + +struct Foo(bool); + +struct Container(&'static [&'static Foo]); + +static FOO: Foo = Foo(true); +static CONTAINER: Container = Container(&[&FOO]); + +fn main() {} diff --git a/tests/ui/statics/issue-44373.rs b/tests/ui/statics/issue-44373.rs new file mode 100644 index 000000000..0d011d096 --- /dev/null +++ b/tests/ui/statics/issue-44373.rs @@ -0,0 +1,5 @@ +static FOO: u32 = 50; + +fn main() { + let _val: &'static [&'static u32] = &[&FOO]; //~ ERROR temporary value dropped while borrowed +} diff --git a/tests/ui/statics/issue-44373.stderr b/tests/ui/statics/issue-44373.stderr new file mode 100644 index 000000000..2d29dec88 --- /dev/null +++ b/tests/ui/statics/issue-44373.stderr @@ -0,0 +1,13 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-44373.rs:4:42 + | +LL | let _val: &'static [&'static u32] = &[&FOO]; + | ----------------------- ^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/statics/issue-91050-1.rs b/tests/ui/statics/issue-91050-1.rs new file mode 100644 index 000000000..403a41462 --- /dev/null +++ b/tests/ui/statics/issue-91050-1.rs @@ -0,0 +1,34 @@ +// build-pass +// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes + +// This test declares globals by the same name with different types, which +// caused problems because Module::getOrInsertGlobal would return a Constant* +// bitcast instead of a GlobalVariable* that could access linkage/visibility. +// In alt builds with LLVM assertions this would fail: +// +// rustc: /checkout/src/llvm-project/llvm/include/llvm/Support/Casting.h:269: +// typename cast_retty::ret_type llvm::cast(Y *) [X = llvm::GlobalValue, Y = llvm::Value]: +// Assertion `isa(Val) && "cast() argument of incompatible type!"' failed. +// +// In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!" + +pub mod before { + #[no_mangle] + pub static GLOBAL1: [u8; 1] = [1]; +} + +pub mod inner { + extern "C" { + pub static GLOBAL1: u8; + pub static GLOBAL2: u8; + } + + pub fn call() { + drop(unsafe { (GLOBAL1, GLOBAL2) }); + } +} + +pub mod after { + #[no_mangle] + pub static GLOBAL2: [u8; 1] = [2]; +} diff --git a/tests/ui/statics/issue-91050-2.rs b/tests/ui/statics/issue-91050-2.rs new file mode 100644 index 000000000..2ff954d15 --- /dev/null +++ b/tests/ui/statics/issue-91050-2.rs @@ -0,0 +1,24 @@ +// build-pass +// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes + +// This is a variant of issue-91050-1.rs -- see there for an explanation. + +pub mod before { + extern "C" { + pub static GLOBAL1: [u8; 1]; + } + + pub unsafe fn do_something_with_array() -> u8 { + GLOBAL1[0] + } +} + +pub mod inner { + extern "C" { + pub static GLOBAL1: u8; + } + + pub unsafe fn call() -> u8 { + GLOBAL1 + 42 + } +} diff --git a/tests/ui/statics/static-fn-inline-xc.rs b/tests/ui/statics/static-fn-inline-xc.rs new file mode 100644 index 000000000..a400b9c8d --- /dev/null +++ b/tests/ui/statics/static-fn-inline-xc.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:static_fn_inline_xc_aux.rs + +// pretty-expanded FIXME #23616 + +extern crate static_fn_inline_xc_aux as mycore; + +use mycore::num; + +pub fn main() { + let _1: f64 = num::Num2::from_int2(1); +} diff --git a/tests/ui/statics/static-fn-trait-xc.rs b/tests/ui/statics/static-fn-trait-xc.rs new file mode 100644 index 000000000..1d3126128 --- /dev/null +++ b/tests/ui/statics/static-fn-trait-xc.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:static_fn_trait_xc_aux.rs + +// pretty-expanded FIXME #23616 + +extern crate static_fn_trait_xc_aux as mycore; + +use mycore::num; + +pub fn main() { + let _1: f64 = num::Num2::from_int2(1); +} diff --git a/tests/ui/statics/static-function-pointer-xc.rs b/tests/ui/statics/static-function-pointer-xc.rs new file mode 100644 index 000000000..2d063a751 --- /dev/null +++ b/tests/ui/statics/static-function-pointer-xc.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:static-function-pointer-aux.rs + +extern crate static_function_pointer_aux as aux; + +fn f(x: isize) -> isize { x } + +pub fn main() { + assert_eq!(aux::F(42), -42); + unsafe { + assert_eq!(aux::MutF(42), -42); + aux::MutF = f; + assert_eq!(aux::MutF(42), 42); + aux::MutF = aux::f; + assert_eq!(aux::MutF(42), -42); + } +} diff --git a/tests/ui/statics/static-function-pointer.rs b/tests/ui/statics/static-function-pointer.rs new file mode 100644 index 000000000..6c52dfecd --- /dev/null +++ b/tests/ui/statics/static-function-pointer.rs @@ -0,0 +1,16 @@ +// run-pass + +fn f(x: isize) -> isize { x } +fn g(x: isize) -> isize { 2 * x } + +static F: fn(isize) -> isize = f; +static mut G: fn(isize) -> isize = f; + +pub fn main() { + assert_eq!(F(42), 42); + unsafe { + assert_eq!(G(42), 42); + G = g; + assert_eq!(G(42), 84); + } +} diff --git a/tests/ui/statics/static-impl.rs b/tests/ui/statics/static-impl.rs new file mode 100644 index 000000000..e7bdb38ee --- /dev/null +++ b/tests/ui/statics/static-impl.rs @@ -0,0 +1,66 @@ +// run-pass +#![allow(non_camel_case_types)] + + + + +pub trait plus { + fn plus(&self) -> isize; +} + +mod a { + use plus; + impl plus for usize { fn plus(&self) -> isize { *self as isize + 20 } } +} + +mod b { + use plus; + impl plus for String { fn plus(&self) -> isize { 200 } } +} + +trait uint_utils { + fn str(&self) -> String; + fn multi(&self, f: F) where F: FnMut(usize); +} + +impl uint_utils for usize { + fn str(&self) -> String { + self.to_string() + } + fn multi(&self, mut f: F) where F: FnMut(usize) { + let mut c = 0_usize; + while c < *self { f(c); c += 1_usize; } + } +} + +trait vec_utils { + fn length_(&self, ) -> usize; + fn iter_(&self, f: F) where F: FnMut(&T); + fn map_(&self, f: F) -> Vec where F: FnMut(&T) -> U; +} + +impl vec_utils for Vec { + fn length_(&self) -> usize { self.len() } + fn iter_(&self, mut f: F) where F: FnMut(&T) { for x in self { f(x); } } + fn map_(&self, mut f: F) -> Vec where F: FnMut(&T) -> U { + let mut r = Vec::new(); + for elt in self { + r.push(f(elt)); + } + r + } +} + +pub fn main() { + assert_eq!(10_usize.plus(), 30); + assert_eq!(("hi".to_string()).plus(), 200); + + assert_eq!((vec![1]).length_().str(), "1".to_string()); + let vect = vec![3, 4].map_(|a| *a + 4); + assert_eq!(vect[0], 7); + let vect = (vec![3, 4]).map_::(|a| *a as usize + 4_usize); + assert_eq!(vect[0], 7_usize); + let mut x = 0_usize; + 10_usize.multi(|_n| x += 2_usize ); + assert_eq!(x, 20_usize); +} diff --git a/tests/ui/statics/static-method-in-trait-with-tps-intracrate.rs b/tests/ui/statics/static-method-in-trait-with-tps-intracrate.rs new file mode 100644 index 000000000..cd3ccfee0 --- /dev/null +++ b/tests/ui/statics/static-method-in-trait-with-tps-intracrate.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] + +trait Deserializer { + fn read_int(&self) -> isize; +} + +trait Deserializable { + fn deserialize(d: &D) -> Self; +} + +impl Deserializable for isize { + fn deserialize(d: &D) -> isize { + return d.read_int(); + } +} + +struct FromThinAir { dummy: () } + +impl Deserializer for FromThinAir { + fn read_int(&self) -> isize { 22 } +} + +pub fn main() { + let d = FromThinAir { dummy: () }; + let i: isize = Deserializable::deserialize(&d); + assert_eq!(i, 22); +} diff --git a/tests/ui/statics/static-method-xcrate.rs b/tests/ui/statics/static-method-xcrate.rs new file mode 100644 index 000000000..1d1cb3810 --- /dev/null +++ b/tests/ui/statics/static-method-xcrate.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:static-methods-crate.rs + +extern crate static_methods_crate; + +use static_methods_crate::read; + +pub fn main() { + let result: isize = read("5".to_string()); + assert_eq!(result, 5); + assert_eq!(read::readMaybe("false".to_string()), Some(false)); + assert_eq!(read::readMaybe("foo".to_string()), None::); +} diff --git a/tests/ui/statics/static-methods-in-traits.rs b/tests/ui/statics/static-methods-in-traits.rs new file mode 100644 index 000000000..ff76d4e4a --- /dev/null +++ b/tests/ui/statics/static-methods-in-traits.rs @@ -0,0 +1,26 @@ +// run-pass + +mod a { + pub trait Foo { + fn foo() -> Self; + } + + impl Foo for isize { + fn foo() -> isize { + 3 + } + } + + impl Foo for usize { + fn foo() -> usize { + 5 + } + } +} + +pub fn main() { + let x: isize = a::Foo::foo(); + let y: usize = a::Foo::foo(); + assert_eq!(x, 3); + assert_eq!(y, 5); +} diff --git a/tests/ui/statics/static-methods-in-traits2.rs b/tests/ui/statics/static-methods-in-traits2.rs new file mode 100644 index 000000000..2c43ff6a7 --- /dev/null +++ b/tests/ui/statics/static-methods-in-traits2.rs @@ -0,0 +1,22 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait Number: NumConv { + fn from(n: T) -> Self; +} + +impl Number for f64 { + fn from(n: T) -> f64 { n.to_float() } +} + +pub trait NumConv { + fn to_float(&self) -> f64; +} + +impl NumConv for f64 { + fn to_float(&self) -> f64 { *self } +} + +pub fn main() { + let _: f64 = Number::from(0.0f64); +} diff --git a/tests/ui/statics/static-mut-xc.rs b/tests/ui/statics/static-mut-xc.rs new file mode 100644 index 000000000..1d172d26a --- /dev/null +++ b/tests/ui/statics/static-mut-xc.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +// aux-build:static_mut_xc.rs + + +extern crate static_mut_xc; + +unsafe fn static_bound(_: &'static isize) {} + +fn static_bound_set(a: &'static mut isize) { + *a = 3; +} + +unsafe fn run() { + assert_eq!(static_mut_xc::a, 3); + static_mut_xc::a = 4; + assert_eq!(static_mut_xc::a, 4); + static_mut_xc::a += 1; + assert_eq!(static_mut_xc::a, 5); + static_mut_xc::a *= 3; + assert_eq!(static_mut_xc::a, 15); + static_mut_xc::a = -3; + assert_eq!(static_mut_xc::a, -3); + static_bound(&static_mut_xc::a); + static_bound_set(&mut static_mut_xc::a); +} + +pub fn main() { + unsafe { run() } +} + +pub mod inner { + pub static mut a: isize = 4; +} diff --git a/tests/ui/statics/static-promotion.rs b/tests/ui/statics/static-promotion.rs new file mode 100644 index 000000000..b9eff4691 --- /dev/null +++ b/tests/ui/statics/static-promotion.rs @@ -0,0 +1,34 @@ +// run-pass + +// Use of global static variables in literal values should be allowed for +// promotion. +// This test is to demonstrate the issue raised in +// https://github.com/rust-lang/rust/issues/70584 + +// Literal values were previously promoted into local static values when +// other global static variables are used. + +struct A(&'static T); +struct B { + x: &'static T, +} +static STR: &'static [u8] = b"hi"; +static C: A>> = { + A(&B { + x: &B { x: STR }, + }) +}; + +pub struct Slice(&'static [i32]); + +static CONTENT: i32 = 42; +pub static CONTENT_MAP: Slice = Slice(&[CONTENT]); + +pub static FOO: (i32, i32) = (42, 43); +pub static CONTENT_MAP2: Slice = Slice(&[FOO.0]); + +fn main() { + assert_eq!(b"hi", C.0.x.x); + assert_eq!(&[42], CONTENT_MAP.0); + assert_eq!(&[42], CONTENT_MAP2.0); +} diff --git a/tests/ui/statics/static-recursive.rs b/tests/ui/statics/static-recursive.rs new file mode 100644 index 000000000..95dadc81f --- /dev/null +++ b/tests/ui/statics/static-recursive.rs @@ -0,0 +1,36 @@ +// run-pass +static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; + +struct StaticDoubleLinked { + prev: &'static StaticDoubleLinked, + next: &'static StaticDoubleLinked, + data: i32, + head: bool +} + +static L1: StaticDoubleLinked = StaticDoubleLinked{prev: &L3, next: &L2, data: 1, head: true}; +static L2: StaticDoubleLinked = StaticDoubleLinked{prev: &L1, next: &L3, data: 2, head: false}; +static L3: StaticDoubleLinked = StaticDoubleLinked{prev: &L2, next: &L1, data: 3, head: false}; + + +pub fn main() { + unsafe { assert_eq!(S, *(S as *const *const u8)); } + + let mut test_vec = Vec::new(); + let mut cur = &L1; + loop { + test_vec.push(cur.data); + cur = cur.next; + if cur.head { break } + } + assert_eq!(&test_vec, &[1,2,3]); + + let mut test_vec = Vec::new(); + let mut cur = &L1; + loop { + cur = cur.prev; + test_vec.push(cur.data); + if cur.head { break } + } + assert_eq!(&test_vec, &[3,2,1]); +} diff --git a/tests/ui/statics/uninhabited-static.rs b/tests/ui/statics/uninhabited-static.rs new file mode 100644 index 000000000..f5c6f4443 --- /dev/null +++ b/tests/ui/statics/uninhabited-static.rs @@ -0,0 +1,21 @@ +#![feature(never_type)] +#![deny(uninhabited_static)] + +enum Void {} +extern { + static VOID: Void; //~ ERROR static of uninhabited type + //~| WARN: previously accepted + static NEVER: !; //~ ERROR static of uninhabited type + //~| WARN: previously accepted +} + +static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type +//~| WARN: previously accepted +//~| ERROR could not evaluate static initializer +//~| WARN: type `Void` does not permit zero-initialization +static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type +//~| WARN: previously accepted +//~| ERROR could not evaluate static initializer +//~| WARN: type `Void` does not permit zero-initialization + +fn main() {} diff --git a/tests/ui/statics/uninhabited-static.stderr b/tests/ui/statics/uninhabited-static.stderr new file mode 100644 index 000000000..ef794bb36 --- /dev/null +++ b/tests/ui/statics/uninhabited-static.stderr @@ -0,0 +1,91 @@ +error: static of uninhabited type + --> $DIR/uninhabited-static.rs:6:5 + | +LL | static VOID: Void; + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #74840 + = note: uninhabited statics cannot be initialized, and any access would be an immediate error +note: the lint level is defined here + --> $DIR/uninhabited-static.rs:2:9 + | +LL | #![deny(uninhabited_static)] + | ^^^^^^^^^^^^^^^^^^ + +error: static of uninhabited type + --> $DIR/uninhabited-static.rs:8:5 + | +LL | static NEVER: !; + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #74840 + = note: uninhabited statics cannot be initialized, and any access would be an immediate error + +error: static of uninhabited type + --> $DIR/uninhabited-static.rs:12:1 + | +LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #74840 + = note: uninhabited statics cannot be initialized, and any access would be an immediate error + +error: static of uninhabited type + --> $DIR/uninhabited-static.rs:16:1 + | +LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #74840 + = note: uninhabited statics cannot be initialized, and any access would be an immediate error + +error[E0080]: could not evaluate static initializer + --> $DIR/uninhabited-static.rs:12:31 + | +LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + +warning: the type `Void` does not permit zero-initialization + --> $DIR/uninhabited-static.rs:12:31 + | +LL | static VOID2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/uninhabited-static.rs:4:1 + | +LL | enum Void {} + | ^^^^^^^^^ + = note: `#[warn(invalid_value)]` on by default + +error[E0080]: could not evaluate static initializer + --> $DIR/uninhabited-static.rs:16:32 + | +LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type + +warning: the type `Void` does not permit zero-initialization + --> $DIR/uninhabited-static.rs:16:32 + | +LL | static NEVER2: Void = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | +note: enums with no inhabited variants have no valid value + --> $DIR/uninhabited-static.rs:4:1 + | +LL | enum Void {} + | ^^^^^^^^^ + +error: aborting due to 6 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs new file mode 100644 index 000000000..0b89d0b16 --- /dev/null +++ b/tests/ui/stats/hir-stats.rs @@ -0,0 +1,42 @@ +// check-pass +// compile-flags: -Zhir-stats +// only-x86_64 +// ignore-stage1 FIXME: remove after next bootstrap bump + +// The aim here is to include at least one of every different type of top-level +// AST/HIR node reported by `-Zhir-stats`. + +#![allow(dead_code)] + +use std::arch::asm; +use std::fmt::Debug; +use std::ffi::c_void; + +extern "C" { fn f(p: *mut c_void); } + +/// An enum. +enum E<'a, T: Copy> { A { t: T }, B(&'a u32) } + +trait Go { + type G: Debug; + fn go(self) -> u32; +} + +impl<'a, T: Copy> Go for E<'a, T> { + type G = bool; + fn go(self) -> u32 { + 99 + } +} + +fn f2(t: T) where T: Debug {} + +fn main() { + let x = E::A { t: 3 }; + match x { + E::A { .. } => {} + _ => {} + } + + unsafe { asm!("mov rdi, 1"); } +} diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr new file mode 100644 index 000000000..7d9ff2dfb --- /dev/null +++ b/tests/ui/stats/hir-stats.stderr @@ -0,0 +1,178 @@ +ast-stats-1 PRE EXPANSION AST STATS +ast-stats-1 Name Accumulated Size Count Item Size +ast-stats-1 ---------------------------------------------------------------- +ast-stats-1 ExprField 48 ( 0.6%) 1 48 +ast-stats-1 GenericArgs 56 ( 0.8%) 1 56 +ast-stats-1 - AngleBracketed 56 ( 0.8%) 1 +ast-stats-1 Crate 56 ( 0.8%) 1 56 +ast-stats-1 Attribute 64 ( 0.9%) 2 32 +ast-stats-1 - Normal 32 ( 0.4%) 1 +ast-stats-1 - DocComment 32 ( 0.4%) 1 +ast-stats-1 Local 72 ( 1.0%) 1 72 +ast-stats-1 WherePredicate 72 ( 1.0%) 1 72 +ast-stats-1 - BoundPredicate 72 ( 1.0%) 1 +ast-stats-1 Arm 96 ( 1.3%) 2 48 +ast-stats-1 ForeignItem 96 ( 1.3%) 1 96 +ast-stats-1 - Fn 96 ( 1.3%) 1 +ast-stats-1 FieldDef 160 ( 2.2%) 2 80 +ast-stats-1 Stmt 160 ( 2.2%) 5 32 +ast-stats-1 - Local 32 ( 0.4%) 1 +ast-stats-1 - MacCall 32 ( 0.4%) 1 +ast-stats-1 - Expr 96 ( 1.3%) 3 +ast-stats-1 Param 160 ( 2.2%) 4 40 +ast-stats-1 FnDecl 200 ( 2.7%) 5 40 +ast-stats-1 Variant 240 ( 3.2%) 2 120 +ast-stats-1 GenericBound 288 ( 3.9%) 4 72 +ast-stats-1 - Trait 288 ( 3.9%) 4 +ast-stats-1 Block 288 ( 3.9%) 6 48 +ast-stats-1 AssocItem 416 ( 5.6%) 4 104 +ast-stats-1 - Type 208 ( 2.8%) 2 +ast-stats-1 - Fn 208 ( 2.8%) 2 +ast-stats-1 GenericParam 480 ( 6.5%) 5 96 +ast-stats-1 Expr 576 ( 7.8%) 8 72 +ast-stats-1 - Path 72 ( 1.0%) 1 +ast-stats-1 - Match 72 ( 1.0%) 1 +ast-stats-1 - Struct 72 ( 1.0%) 1 +ast-stats-1 - Lit 144 ( 1.9%) 2 +ast-stats-1 - Block 216 ( 2.9%) 3 +ast-stats-1 Pat 616 ( 8.3%) 7 88 +ast-stats-1 - Struct 88 ( 1.2%) 1 +ast-stats-1 - Wild 88 ( 1.2%) 1 +ast-stats-1 - Ident 440 ( 5.9%) 5 +ast-stats-1 PathSegment 720 ( 9.7%) 30 24 +ast-stats-1 Ty 896 (12.1%) 14 64 +ast-stats-1 - Ptr 64 ( 0.9%) 1 +ast-stats-1 - Ref 64 ( 0.9%) 1 +ast-stats-1 - ImplicitSelf 128 ( 1.7%) 2 +ast-stats-1 - Path 640 ( 8.6%) 10 +ast-stats-1 Item 1_656 (22.3%) 9 184 +ast-stats-1 - Trait 184 ( 2.5%) 1 +ast-stats-1 - Enum 184 ( 2.5%) 1 +ast-stats-1 - ForeignMod 184 ( 2.5%) 1 +ast-stats-1 - Impl 184 ( 2.5%) 1 +ast-stats-1 - Fn 368 ( 5.0%) 2 +ast-stats-1 - Use 552 ( 7.4%) 3 +ast-stats-1 ---------------------------------------------------------------- +ast-stats-1 Total 7_416 +ast-stats-1 +ast-stats-2 POST EXPANSION AST STATS +ast-stats-2 Name Accumulated Size Count Item Size +ast-stats-2 ---------------------------------------------------------------- +ast-stats-2 ExprField 48 ( 0.6%) 1 48 +ast-stats-2 GenericArgs 56 ( 0.7%) 1 56 +ast-stats-2 - AngleBracketed 56 ( 0.7%) 1 +ast-stats-2 Crate 56 ( 0.7%) 1 56 +ast-stats-2 Local 72 ( 0.9%) 1 72 +ast-stats-2 WherePredicate 72 ( 0.9%) 1 72 +ast-stats-2 - BoundPredicate 72 ( 0.9%) 1 +ast-stats-2 Arm 96 ( 1.2%) 2 48 +ast-stats-2 ForeignItem 96 ( 1.2%) 1 96 +ast-stats-2 - Fn 96 ( 1.2%) 1 +ast-stats-2 InlineAsm 120 ( 1.5%) 1 120 +ast-stats-2 Attribute 128 ( 1.6%) 4 32 +ast-stats-2 - DocComment 32 ( 0.4%) 1 +ast-stats-2 - Normal 96 ( 1.2%) 3 +ast-stats-2 FieldDef 160 ( 2.0%) 2 80 +ast-stats-2 Stmt 160 ( 2.0%) 5 32 +ast-stats-2 - Local 32 ( 0.4%) 1 +ast-stats-2 - Semi 32 ( 0.4%) 1 +ast-stats-2 - Expr 96 ( 1.2%) 3 +ast-stats-2 Param 160 ( 2.0%) 4 40 +ast-stats-2 FnDecl 200 ( 2.5%) 5 40 +ast-stats-2 Variant 240 ( 3.0%) 2 120 +ast-stats-2 GenericBound 288 ( 3.6%) 4 72 +ast-stats-2 - Trait 288 ( 3.6%) 4 +ast-stats-2 Block 288 ( 3.6%) 6 48 +ast-stats-2 AssocItem 416 ( 5.1%) 4 104 +ast-stats-2 - Type 208 ( 2.6%) 2 +ast-stats-2 - Fn 208 ( 2.6%) 2 +ast-stats-2 GenericParam 480 ( 5.9%) 5 96 +ast-stats-2 Pat 616 ( 7.6%) 7 88 +ast-stats-2 - Struct 88 ( 1.1%) 1 +ast-stats-2 - Wild 88 ( 1.1%) 1 +ast-stats-2 - Ident 440 ( 5.4%) 5 +ast-stats-2 Expr 648 ( 8.0%) 9 72 +ast-stats-2 - Path 72 ( 0.9%) 1 +ast-stats-2 - Match 72 ( 0.9%) 1 +ast-stats-2 - Struct 72 ( 0.9%) 1 +ast-stats-2 - InlineAsm 72 ( 0.9%) 1 +ast-stats-2 - Lit 144 ( 1.8%) 2 +ast-stats-2 - Block 216 ( 2.7%) 3 +ast-stats-2 PathSegment 792 ( 9.8%) 33 24 +ast-stats-2 Ty 896 (11.0%) 14 64 +ast-stats-2 - Ptr 64 ( 0.8%) 1 +ast-stats-2 - Ref 64 ( 0.8%) 1 +ast-stats-2 - ImplicitSelf 128 ( 1.6%) 2 +ast-stats-2 - Path 640 ( 7.9%) 10 +ast-stats-2 Item 2_024 (25.0%) 11 184 +ast-stats-2 - Trait 184 ( 2.3%) 1 +ast-stats-2 - Enum 184 ( 2.3%) 1 +ast-stats-2 - ExternCrate 184 ( 2.3%) 1 +ast-stats-2 - ForeignMod 184 ( 2.3%) 1 +ast-stats-2 - Impl 184 ( 2.3%) 1 +ast-stats-2 - Fn 368 ( 4.5%) 2 +ast-stats-2 - Use 736 ( 9.1%) 4 +ast-stats-2 ---------------------------------------------------------------- +ast-stats-2 Total 8_112 +ast-stats-2 +hir-stats HIR STATS +hir-stats Name Accumulated Size Count Item Size +hir-stats ---------------------------------------------------------------- +hir-stats ForeignItemRef 24 ( 0.3%) 1 24 +hir-stats Lifetime 24 ( 0.3%) 1 24 +hir-stats Mod 32 ( 0.4%) 1 32 +hir-stats ExprField 40 ( 0.4%) 1 40 +hir-stats TraitItemRef 56 ( 0.6%) 2 28 +hir-stats Local 64 ( 0.7%) 1 64 +hir-stats Param 64 ( 0.7%) 2 32 +hir-stats InlineAsm 72 ( 0.8%) 1 72 +hir-stats ImplItemRef 72 ( 0.8%) 2 36 +hir-stats Body 96 ( 1.1%) 3 32 +hir-stats FieldDef 96 ( 1.1%) 2 48 +hir-stats Arm 96 ( 1.1%) 2 48 +hir-stats Stmt 96 ( 1.1%) 3 32 +hir-stats - Local 32 ( 0.4%) 1 +hir-stats - Semi 32 ( 0.4%) 1 +hir-stats - Expr 32 ( 0.4%) 1 +hir-stats FnDecl 120 ( 1.3%) 3 40 +hir-stats Attribute 128 ( 1.4%) 4 32 +hir-stats GenericArg 128 ( 1.4%) 4 32 +hir-stats - Type 32 ( 0.4%) 1 +hir-stats - Lifetime 96 ( 1.1%) 3 +hir-stats GenericArgs 144 ( 1.6%) 3 48 +hir-stats Variant 176 ( 1.9%) 2 88 +hir-stats GenericBound 192 ( 2.1%) 4 48 +hir-stats - Trait 192 ( 2.1%) 4 +hir-stats WherePredicate 192 ( 2.1%) 3 64 +hir-stats - BoundPredicate 192 ( 2.1%) 3 +hir-stats Block 288 ( 3.2%) 6 48 +hir-stats Pat 360 ( 4.0%) 5 72 +hir-stats - Wild 72 ( 0.8%) 1 +hir-stats - Struct 72 ( 0.8%) 1 +hir-stats - Binding 216 ( 2.4%) 3 +hir-stats GenericParam 400 ( 4.4%) 5 80 +hir-stats Generics 560 ( 6.2%) 10 56 +hir-stats Ty 720 ( 8.0%) 15 48 +hir-stats - Ptr 48 ( 0.5%) 1 +hir-stats - Ref 48 ( 0.5%) 1 +hir-stats - Path 624 ( 6.9%) 13 +hir-stats Expr 768 ( 8.5%) 12 64 +hir-stats - Path 64 ( 0.7%) 1 +hir-stats - Struct 64 ( 0.7%) 1 +hir-stats - Match 64 ( 0.7%) 1 +hir-stats - InlineAsm 64 ( 0.7%) 1 +hir-stats - Lit 128 ( 1.4%) 2 +hir-stats - Block 384 ( 4.2%) 6 +hir-stats Item 880 ( 9.7%) 11 80 +hir-stats - Trait 80 ( 0.9%) 1 +hir-stats - Enum 80 ( 0.9%) 1 +hir-stats - ExternCrate 80 ( 0.9%) 1 +hir-stats - ForeignMod 80 ( 0.9%) 1 +hir-stats - Impl 80 ( 0.9%) 1 +hir-stats - Fn 160 ( 1.8%) 2 +hir-stats - Use 320 ( 3.5%) 4 +hir-stats Path 1_240 (13.7%) 31 40 +hir-stats PathSegment 1_920 (21.2%) 40 48 +hir-stats ---------------------------------------------------------------- +hir-stats Total 9_048 +hir-stats diff --git a/tests/ui/std-backtrace.rs b/tests/ui/std-backtrace.rs new file mode 100644 index 000000000..59574b471 --- /dev/null +++ b/tests/ui/std-backtrace.rs @@ -0,0 +1,74 @@ +// run-pass +// ignore-android FIXME #17520 +// ignore-emscripten spawning processes is not supported +// ignore-openbsd no support for libbacktrace without filename +// ignore-sgx no processes +// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test +// ignore-fuchsia Backtraces not symbolized +// compile-flags:-g +// compile-flags:-Cstrip=none + +use std::env; +use std::process::Command; +use std::str; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() >= 2 && args[1] == "force" { + println!("stack backtrace:\n{}", std::backtrace::Backtrace::force_capture()); + } else if args.len() >= 2 { + println!("stack backtrace:\n{}", std::backtrace::Backtrace::capture()); + } else { + runtest(&args[0]); + println!("test ok"); + } +} + +fn runtest(me: &str) { + env::remove_var("RUST_BACKTRACE"); + env::remove_var("RUST_LIB_BACKTRACE"); + + let p = Command::new(me).arg("a").env("RUST_BACKTRACE", "1").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); + assert!(String::from_utf8_lossy(&p.stdout).contains("backtrace::main")); + + let p = Command::new(me).arg("a").env("RUST_BACKTRACE", "0").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n")); + + let p = Command::new(me).arg("a").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n")); + + let p = Command::new(me) + .arg("a") + .env("RUST_LIB_BACKTRACE", "1") + .env("RUST_BACKTRACE", "1") + .output() + .unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); + + let p = Command::new(me) + .arg("a") + .env("RUST_LIB_BACKTRACE", "0") + .env("RUST_BACKTRACE", "1") + .output() + .unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("disabled backtrace\n")); + + let p = Command::new(me) + .arg("force") + .env("RUST_LIB_BACKTRACE", "0") + .env("RUST_BACKTRACE", "0") + .output() + .unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); + + let p = Command::new(me).arg("force").output().unwrap(); + assert!(p.status.success()); + assert!(String::from_utf8_lossy(&p.stdout).contains("stack backtrace:\n")); +} diff --git a/tests/ui/std-uncopyable-atomics.rs b/tests/ui/std-uncopyable-atomics.rs new file mode 100644 index 000000000..d85864eca --- /dev/null +++ b/tests/ui/std-uncopyable-atomics.rs @@ -0,0 +1,16 @@ +// Issue #8380 + + +use std::sync::atomic::*; +use std::ptr; + +fn main() { + let x = AtomicBool::new(false); + let x = *&x; //~ ERROR: cannot move out of a shared reference + let x = AtomicIsize::new(0); + let x = *&x; //~ ERROR: cannot move out of a shared reference + let x = AtomicUsize::new(0); + let x = *&x; //~ ERROR: cannot move out of a shared reference + let x: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + let x = *&x; //~ ERROR: cannot move out of a shared reference +} diff --git a/tests/ui/std-uncopyable-atomics.stderr b/tests/ui/std-uncopyable-atomics.stderr new file mode 100644 index 000000000..8c5d0b960 --- /dev/null +++ b/tests/ui/std-uncopyable-atomics.stderr @@ -0,0 +1,51 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/std-uncopyable-atomics.rs:9:13 + | +LL | let x = *&x; + | ^^^ move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let x = *&x; +LL + let x = &x; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/std-uncopyable-atomics.rs:11:13 + | +LL | let x = *&x; + | ^^^ move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let x = *&x; +LL + let x = &x; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/std-uncopyable-atomics.rs:13:13 + | +LL | let x = *&x; + | ^^^ move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let x = *&x; +LL + let x = &x; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/std-uncopyable-atomics.rs:15:13 + | +LL | let x = *&x; + | ^^^ move occurs because value has type `std::sync::atomic::AtomicPtr`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let x = *&x; +LL + let x = &x; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/stdio-is-blocking.rs b/tests/ui/stdio-is-blocking.rs new file mode 100644 index 000000000..4b67dbf79 --- /dev/null +++ b/tests/ui/stdio-is-blocking.rs @@ -0,0 +1,84 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::env; +use std::io::prelude::*; +use std::process::Command; +use std::thread; + +const THREADS: usize = 20; +const WRITES: usize = 100; +const WRITE_SIZE: usize = 1024 * 32; + +fn main() { + let args = env::args().collect::>(); + if args.len() == 1 { + parent(); + } else { + child(); + } +} + +fn parent() { + let me = env::current_exe().unwrap(); + let mut cmd = Command::new(me); + cmd.arg("run-the-test"); + let output = cmd.output().unwrap(); + assert!(output.status.success()); + assert_eq!(output.stderr.len(), 0); + assert_eq!(output.stdout.len(), WRITES * THREADS * WRITE_SIZE); + for byte in output.stdout.iter() { + assert_eq!(*byte, b'a'); + } +} + +fn child() { + let threads = (0..THREADS).map(|_| { + thread::spawn(|| { + let buf = [b'a'; WRITE_SIZE]; + for _ in 0..WRITES { + write_all(&buf); + } + }) + }).collect::>(); + + for thread in threads { + thread.join().unwrap(); + } +} + +#[cfg(unix)] +fn write_all(buf: &[u8]) { + use std::fs::File; + use std::mem; + use std::os::unix::prelude::*; + + let mut file = unsafe { File::from_raw_fd(1) }; + let res = file.write_all(buf); + mem::forget(file); + res.unwrap(); +} + +#[cfg(windows)] +fn write_all(buf: &[u8]) { + use std::fs::File; + use std::mem; + use std::os::windows::raw::*; + use std::os::windows::prelude::*; + + const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32; + + extern "system" { + fn GetStdHandle(handle: u32) -> HANDLE; + } + + let mut file = unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + assert!(!handle.is_null()); + File::from_raw_handle(handle) + }; + let res = file.write_all(buf); + mem::forget(file); + res.unwrap(); +} diff --git a/tests/ui/stdlib-unit-tests/builtin-clone.rs b/tests/ui/stdlib-unit-tests/builtin-clone.rs new file mode 100644 index 000000000..0874d5bc3 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/builtin-clone.rs @@ -0,0 +1,45 @@ +// run-pass +// Test that `Clone` is correctly implemented for builtin types. +// Also test that cloning an array or a tuple is done right, i.e. +// each component is cloned. + +fn test_clone(arg: T) { + let _ = arg.clone(); +} + +fn foo() { } + +#[derive(Debug, PartialEq, Eq)] +struct S(i32); + +impl Clone for S { + fn clone(&self) -> Self { + S(self.0 + 1) + } +} + +fn main() { + test_clone(foo); + test_clone([1; 56]); + test_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + + let a = [S(0), S(1), S(2)]; + let b = [S(1), S(2), S(3)]; + assert_eq!(b, a.clone()); + + let a = ( + (S(1), S(0)), + ( + (S(0), S(0), S(1)), + S(0) + ) + ); + let b = ( + (S(2), S(1)), + ( + (S(1), S(1), S(2)), + S(1) + ) + ); + assert_eq!(b, a.clone()); +} diff --git a/tests/ui/stdlib-unit-tests/eq-multidispatch.rs b/tests/ui/stdlib-unit-tests/eq-multidispatch.rs new file mode 100644 index 000000000..69d83f496 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/eq-multidispatch.rs @@ -0,0 +1,30 @@ +// run-pass + +#[derive(PartialEq, Debug)] +struct Bar; +#[derive(Debug)] +struct Baz; +#[derive(Debug)] +struct Foo; +#[derive(Debug)] +struct Fu; + +impl PartialEq for Baz { fn eq(&self, _: &Baz) -> bool { true } } + +impl PartialEq for Foo { fn eq(&self, _: &Fu) -> bool { true } } +impl PartialEq for Fu { fn eq(&self, _: &Foo) -> bool { true } } + +impl PartialEq for Foo { fn eq(&self, _: &Bar) -> bool { false } } +impl PartialEq for Bar { fn eq(&self, _: &Foo) -> bool { false } } + +fn main() { + assert!(Bar != Foo); + assert!(Foo != Bar); + + assert_eq!(Bar, Bar); + + assert_eq!(Baz, Baz); + + assert_eq!(Foo, Fu); + assert_eq!(Fu, Foo); +} diff --git a/tests/ui/stdlib-unit-tests/issue-21058.rs b/tests/ui/stdlib-unit-tests/issue-21058.rs new file mode 100644 index 000000000..6facf0b2d --- /dev/null +++ b/tests/ui/stdlib-unit-tests/issue-21058.rs @@ -0,0 +1,64 @@ +// run-pass +#![allow(dead_code)] + +use std::fmt::Debug; + +struct NT(str); +struct DST { a: u32, b: str } + +macro_rules! check { + (val: $ty_of:expr, $expected:expr) => { + assert_eq!(type_name_of_val($ty_of), $expected); + }; + ($ty:ty, $expected:expr) => { + assert_eq!(std::any::type_name::<$ty>(), $expected); + }; +} + +fn main() { + // type_name should support unsized types + check!([u8], "[u8]"); + check!(str, "str"); + check!(dyn Send, "dyn core::marker::Send"); + check!(NT, "issue_21058::NT"); + check!(DST, "issue_21058::DST"); + check!(&i32, "&i32"); + check!(&'static i32, "&i32"); + check!((i32, u32), "(i32, u32)"); + check!(val: foo(), "issue_21058::Foo"); + check!(val: Foo::new, "issue_21058::Foo::new"); + check!(val: + ::fmt, + "::fmt" + ); + check!(val: || {}, "issue_21058::main::{{closure}}"); + bar::(); +} + +trait Trait { + type Assoc; +} + +impl Trait for i32 { + type Assoc = String; +} + +fn bar() { + check!(T::Assoc, "alloc::string::String"); + check!(T, "i32"); +} + +fn type_name_of_val(_: T) -> &'static str { + std::any::type_name::() +} + +#[derive(Debug)] +struct Foo; + +impl Foo { + fn new() -> Self { Foo } +} + +fn foo() -> impl Debug { + Foo +} diff --git a/tests/ui/stdlib-unit-tests/istr.rs b/tests/ui/stdlib-unit-tests/istr.rs new file mode 100644 index 000000000..dca6d40d5 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/istr.rs @@ -0,0 +1,53 @@ +// run-pass + +use std::string::String; + +fn test_stack_assign() { + let s: String = "a".to_string(); + println!("{}", s.clone()); + let t: String = "a".to_string(); + assert_eq!(s, t); + let u: String = "b".to_string(); + assert!((s != u)); +} + +fn test_heap_lit() { "a big string".to_string(); } + +fn test_heap_assign() { + let s: String = "a big ol' string".to_string(); + let t: String = "a big ol' string".to_string(); + assert_eq!(s, t); + let u: String = "a bad ol' string".to_string(); + assert!((s != u)); +} + +fn test_heap_log() { + let s = "a big ol' string".to_string(); + println!("{}", s); +} + +fn test_append() { + let mut s = String::new(); + s.push_str("a"); + assert_eq!(s, "a"); + + let mut s = String::from("a"); + s.push_str("b"); + println!("{}", s.clone()); + assert_eq!(s, "ab"); + + let mut s = String::from("c"); + s.push_str("offee"); + assert_eq!(s, "coffee"); + + s.push_str("&tea"); + assert_eq!(s, "coffee&tea"); +} + +pub fn main() { + test_stack_assign(); + test_heap_lit(); + test_heap_assign(); + test_heap_log(); + test_append(); +} diff --git a/tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs b/tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs new file mode 100644 index 000000000..c5a40edbe --- /dev/null +++ b/tests/ui/stdlib-unit-tests/log-knows-the-names-of-variants-in-std.rs @@ -0,0 +1,27 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#[derive(Clone, Debug)] +enum foo { + a(usize), + b(String), +} + +fn check_log(exp: String, v: T) { + assert_eq!(exp, format!("{:?}", v)); +} + +pub fn main() { + let mut x = Some(foo::a(22)); + let exp = "Some(a(22))".to_string(); + let act = format!("{:?}", x); + assert_eq!(act, exp); + check_log(exp, x); + + x = None; + let exp = "None".to_string(); + let act = format!("{:?}", x); + assert_eq!(act, exp); + check_log(exp, x); +} diff --git a/tests/ui/stdlib-unit-tests/matches2021.rs b/tests/ui/stdlib-unit-tests/matches2021.rs new file mode 100644 index 000000000..9143a8cdd --- /dev/null +++ b/tests/ui/stdlib-unit-tests/matches2021.rs @@ -0,0 +1,13 @@ +// run-pass +// edition:2021 + +// regression test for https://github.com/rust-lang/rust/pull/85678 + +#![feature(assert_matches)] + +use std::assert_matches::assert_matches; + +fn main() { + assert!(matches!((), ())); + assert_matches!((), ()); +} diff --git a/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs b/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs new file mode 100644 index 000000000..9100bfbde --- /dev/null +++ b/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs @@ -0,0 +1,64 @@ +// run-pass + +use std::fmt::Debug; +use std::cmp::{self, PartialOrd, Ordering}; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct Foo { + n: u8, + name: &'static str +} + +impl PartialOrd for Foo { + fn partial_cmp(&self, other: &Foo) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Foo { + fn cmp(&self, other: &Foo) -> Ordering { + self.n.cmp(&other.n) + } +} + +fn main() { + let a = Foo { n: 4, name: "a" }; + let b = Foo { n: 4, name: "b" }; + let c = Foo { n: 8, name: "c" }; + let d = Foo { n: 8, name: "d" }; + let e = Foo { n: 22, name: "e" }; + let f = Foo { n: 22, name: "f" }; + + let data = [a, b, c, d, e, f]; + + // `min` should return the left when the values are equal + assert_eq!(data.iter().min(), Some(&a)); + assert_eq!(data.iter().min_by_key(|a| a.n), Some(&a)); + assert_eq!(cmp::min(a, b), a); + assert_eq!(cmp::min(b, a), b); + + // `max` should return the right when the values are equal + assert_eq!(data.iter().max(), Some(&f)); + assert_eq!(data.iter().max_by_key(|a| a.n), Some(&f)); + assert_eq!(cmp::max(e, f), f); + assert_eq!(cmp::max(f, e), e); + + let mut presorted = data.to_vec(); + presorted.sort(); + assert_stable(&presorted); + + let mut presorted = data.to_vec(); + presorted.sort_by(|a, b| a.cmp(b)); + assert_stable(&presorted); + + // Assert that sorted and min/max are the same + fn assert_stable(presorted: &[T]) { + for slice in presorted.windows(2) { + let a = &slice[0]; + let b = &slice[1]; + + assert_eq!(a, cmp::min(a, b)); + assert_eq!(b, cmp::max(a, b)); + } + } +} diff --git a/tests/ui/stdlib-unit-tests/not-sync.rs b/tests/ui/stdlib-unit-tests/not-sync.rs new file mode 100644 index 000000000..f4648994f --- /dev/null +++ b/tests/ui/stdlib-unit-tests/not-sync.rs @@ -0,0 +1,22 @@ +use std::cell::{Cell, RefCell}; +use std::rc::{Rc, Weak}; +use std::sync::mpsc::{Receiver, Sender}; + +fn test() {} + +fn main() { + test::>(); + //~^ ERROR `Cell` cannot be shared between threads safely [E0277] + test::>(); + //~^ ERROR `RefCell` cannot be shared between threads safely [E0277] + + test::>(); + //~^ ERROR `Rc` cannot be shared between threads safely [E0277] + test::>(); + //~^ ERROR `std::rc::Weak` cannot be shared between threads safely [E0277] + + test::>(); + //~^ ERROR `std::sync::mpsc::Receiver` cannot be shared between threads safely [E0277] + test::>(); + //~^ ERROR `Sender` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/stdlib-unit-tests/not-sync.stderr b/tests/ui/stdlib-unit-tests/not-sync.stderr new file mode 100644 index 000000000..1ee358ba8 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/not-sync.stderr @@ -0,0 +1,81 @@ +error[E0277]: `Cell` cannot be shared between threads safely + --> $DIR/not-sync.rs:8:12 + | +LL | test::>(); + | ^^^^^^^^^ `Cell` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Cell` +note: required by a bound in `test` + --> $DIR/not-sync.rs:5:12 + | +LL | fn test() {} + | ^^^^ required by this bound in `test` + +error[E0277]: `RefCell` cannot be shared between threads safely + --> $DIR/not-sync.rs:10:12 + | +LL | test::>(); + | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `RefCell` +note: required by a bound in `test` + --> $DIR/not-sync.rs:5:12 + | +LL | fn test() {} + | ^^^^ required by this bound in `test` + +error[E0277]: `Rc` cannot be shared between threads safely + --> $DIR/not-sync.rs:13:12 + | +LL | test::>(); + | ^^^^^^^ `Rc` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Rc` +note: required by a bound in `test` + --> $DIR/not-sync.rs:5:12 + | +LL | fn test() {} + | ^^^^ required by this bound in `test` + +error[E0277]: `std::rc::Weak` cannot be shared between threads safely + --> $DIR/not-sync.rs:15:12 + | +LL | test::>(); + | ^^^^^^^^^ `std::rc::Weak` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `std::rc::Weak` +note: required by a bound in `test` + --> $DIR/not-sync.rs:5:12 + | +LL | fn test() {} + | ^^^^ required by this bound in `test` + +error[E0277]: `std::sync::mpsc::Receiver` cannot be shared between threads safely + --> $DIR/not-sync.rs:18:12 + | +LL | test::>(); + | ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver` +note: required by a bound in `test` + --> $DIR/not-sync.rs:5:12 + | +LL | fn test() {} + | ^^^^ required by this bound in `test` + +error[E0277]: `Sender` cannot be shared between threads safely + --> $DIR/not-sync.rs:20:12 + | +LL | test::>(); + | ^^^^^^^^^^^ `Sender` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Sender` +note: required by a bound in `test` + --> $DIR/not-sync.rs:5:12 + | +LL | fn test() {} + | ^^^^ required by this bound in `test` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs new file mode 100644 index 000000000..6b0b09c98 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs @@ -0,0 +1,119 @@ +// run-pass +// check raw fat pointer ops + +use std::mem; + +fn assert_inorder(a: &[T]) { + for i in 0..a.len() { + for j in 0..a.len() { + if i < j { + assert!(a[i] < a[j]); + assert!(a[i] <= a[j]); + assert!(!(a[i] == a[j])); + assert!(a[i] != a[j]); + assert!(!(a[i] >= a[j])); + assert!(!(a[i] > a[j])); + } else if i == j { + assert!(!(a[i] < a[j])); + assert!(a[i] <= a[j]); + assert!(a[i] == a[j]); + assert!(!(a[i] != a[j])); + assert!(a[i] >= a[j]); + assert!(!(a[i] > a[j])); + } else { + assert!(!(a[i] < a[j])); + assert!(!(a[i] <= a[j])); + assert!(!(a[i] == a[j])); + assert!(a[i] != a[j]); + assert!(a[i] >= a[j]); + assert!(a[i] > a[j]); + } + } + } +} + +trait Foo { fn foo(&self) -> usize; } +impl Foo for T { + fn foo(&self) -> usize { + mem::size_of::() + } +} + +#[allow(unused_tuple_struct_fields)] +struct S(u32, T); + +fn main() { + let mut array = [0,1,2,3,4]; + let mut array2 = [5,6,7,8,9]; + + // fat ptr comparison: addr then extra + + // check ordering for arrays + let mut ptrs: Vec<*const [u8]> = vec![ + &array[0..0], &array[0..1], &array, &array[1..] + ]; + + let array_addr = &array as *const [u8] as *const u8 as usize; + let array2_addr = &array2 as *const [u8] as *const u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &array2); + } else { + ptrs.push(&array2); + } + assert_inorder(&ptrs); + + // check ordering for mut arrays + let mut ptrs: Vec<*mut [u8]> = vec![ + &mut array[0..0], &mut array[0..1], &mut array, &mut array[1..] + ]; + + let array_addr = &mut array as *mut [u8] as *mut u8 as usize; + let array2_addr = &mut array2 as *mut [u8] as *mut u8 as usize; + if array2_addr < array_addr { + ptrs.insert(0, &mut array2); + } else { + ptrs.push(&mut array2); + } + assert_inorder(&ptrs); + + let mut u8_ = (0u8, 1u8); + let mut u32_ = (4u32, 5u32); + + // check ordering for ptrs + let buf: &mut [*const dyn Foo] = &mut [ + &u8_, &u8_.0, + &u32_, &u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf); + + // check ordering for mut ptrs + let buf: &mut [*mut dyn Foo] = &mut [ + &mut u8_, &mut u8_.0, + &mut u32_, &mut u32_.0, + ]; + buf.sort_by(|u,v| { + let u : [*const (); 2] = unsafe { mem::transmute(*u) }; + let v : [*const (); 2] = unsafe { mem::transmute(*v) }; + u.cmp(&v) + }); + assert_inorder(buf); + + // check ordering for structs containing arrays + let ss: (S<[u8; 2]>, + S<[u8; 3]>, + S<[u8; 2]>) = ( + S(7, [8, 9]), + S(10, [11, 12, 13]), + S(4, [5, 6]) + ); + assert_inorder(&[ + &ss.0 as *const S<[u8]>, + &ss.1 as *const S<[u8]>, + &ss.2 as *const S<[u8]> + ]); +} diff --git a/tests/ui/stdlib-unit-tests/seq-compare.rs b/tests/ui/stdlib-unit-tests/seq-compare.rs new file mode 100644 index 000000000..4078326b5 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/seq-compare.rs @@ -0,0 +1,16 @@ +// run-pass + +pub fn main() { + assert!(("hello".to_string() < "hellr".to_string())); + assert!(("hello ".to_string() > "hello".to_string())); + assert!(("hello".to_string() != "there".to_string())); + assert!((vec![1, 2, 3, 4] > vec![1, 2, 3])); + assert!((vec![1, 2, 3] < vec![1, 2, 3, 4])); + assert!((vec![1, 2, 4, 4] > vec![1, 2, 3, 4])); + assert!((vec![1, 2, 3, 4] < vec![1, 2, 4, 4])); + assert!((vec![1, 2, 3] <= vec![1, 2, 3])); + assert!((vec![1, 2, 3] <= vec![1, 2, 3, 3])); + assert!((vec![1, 2, 3, 4] > vec![1, 2, 3])); + assert_eq!(vec![1, 2, 3], vec![1, 2, 3]); + assert!((vec![1, 2, 3] != vec![1, 1, 3])); +} diff --git a/tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs b/tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs new file mode 100644 index 000000000..f73e7e1c3 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/volatile-fat-ptr.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(stable_features)] +#![feature(volatile)] +use std::ptr::{read_volatile, write_volatile}; + +fn main() { + let mut x: &'static str = "test"; + unsafe { + let a = read_volatile(&x); + assert_eq!(a, "test"); + write_volatile(&mut x, "foo"); + assert_eq!(x, "foo"); + } +} diff --git a/tests/ui/stmt_expr_attrs_no_feature.rs b/tests/ui/stmt_expr_attrs_no_feature.rs new file mode 100644 index 000000000..627c97da0 --- /dev/null +++ b/tests/ui/stmt_expr_attrs_no_feature.rs @@ -0,0 +1,141 @@ +#![feature(rustc_attrs)] + +macro_rules! stmt_mac { + () => { + fn b() {} + } +} + +fn main() { + #[rustc_dummy] + fn a() {} + + // Bug: built-in attrs like `rustc_dummy` are not gated on blocks, but other attrs are. + #[rustfmt::skip] //~ ERROR attributes on expressions are experimental + { + + } + + #[rustc_dummy] + 5; + + #[rustc_dummy] + stmt_mac!(); +} + +// Check that cfg works right + +#[cfg(unset)] +fn c() { + #[rustc_dummy] + 5; +} + +#[cfg(not(unset))] +fn j() { + #[rustc_dummy] + 5; +} + +#[cfg_attr(not(unset), cfg(unset))] +fn d() { + #[rustc_dummy] + 8; +} + +#[cfg_attr(not(unset), cfg(not(unset)))] +fn i() { + #[rustc_dummy] + 8; +} + +// check that macro expansion and cfg works right + +macro_rules! item_mac { + ($e:ident) => { + fn $e() { + #[rustc_dummy] + 42; + + #[cfg(unset)] + fn f() { + #[rustc_dummy] + 5; + } + + #[cfg(not(unset))] + fn k() { + #[rustc_dummy] + 5; + } + + #[cfg_attr(not(unset), cfg(unset))] + fn g() { + #[rustc_dummy] + 8; + } + + #[cfg_attr(not(unset), cfg(not(unset)))] + fn h() { + #[rustc_dummy] + 8; + } + + } + } +} + +item_mac!(e); + +// check that the gate visitor works right: + +extern "C" { + #[cfg(unset)] + fn x(a: [u8; #[rustc_dummy] 5]); + fn y(a: [u8; #[rustc_dummy] 5]); //~ ERROR attributes on expressions are experimental +} + +struct Foo; +impl Foo { + #[cfg(unset)] + const X: u8 = #[rustc_dummy] 5; + const Y: u8 = #[rustc_dummy] 5; //~ ERROR attributes on expressions are experimental +} + +trait Bar { + #[cfg(unset)] + const X: [u8; #[rustc_dummy] 5]; + const Y: [u8; #[rustc_dummy] 5]; //~ ERROR attributes on expressions are experimental +} + +struct Joyce { + #[cfg(unset)] + field: [u8; #[rustc_dummy] 5], + field2: [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental +} + +struct Walky( + #[cfg(unset)] [u8; #[rustc_dummy] 5], + [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental +); + +enum Mike { + Happy( + #[cfg(unset)] [u8; #[rustc_dummy] 5], + [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental + ), + Angry { + #[cfg(unset)] + field: [u8; #[rustc_dummy] 5], + field2: [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental + } +} + +fn pat() { + match 5 { + #[cfg(unset)] + 5 => #[rustc_dummy] (), + 6 => #[rustc_dummy] (), //~ ERROR attributes on expressions are experimental + _ => (), + } +} diff --git a/tests/ui/stmt_expr_attrs_no_feature.stderr b/tests/ui/stmt_expr_attrs_no_feature.stderr new file mode 100644 index 000000000..dc06521fe --- /dev/null +++ b/tests/ui/stmt_expr_attrs_no_feature.stderr @@ -0,0 +1,84 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:14:5 + | +LL | #[rustfmt::skip] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:95:18 + | +LL | fn y(a: [u8; #[rustc_dummy] 5]); + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:102:19 + | +LL | const Y: u8 = #[rustc_dummy] 5; + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:108:19 + | +LL | const Y: [u8; #[rustc_dummy] 5]; + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:114:18 + | +LL | field2: [u8; #[rustc_dummy] 5] + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:119:10 + | +LL | [u8; #[rustc_dummy] 5] + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:125:14 + | +LL | [u8; #[rustc_dummy] 5] + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:130:22 + | +LL | field2: [u8; #[rustc_dummy] 5] + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt_expr_attrs_no_feature.rs:138:14 + | +LL | 6 => #[rustc_dummy] (), + | ^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/str/str-array-assignment.rs b/tests/ui/str/str-array-assignment.rs new file mode 100644 index 000000000..323eefb38 --- /dev/null +++ b/tests/ui/str/str-array-assignment.rs @@ -0,0 +1,11 @@ +fn main() { + let s = "abc"; + let t = if true { s[..2] } else { s }; + //~^ ERROR `if` and `else` have incompatible types + let u: &str = if true { s[..2] } else { s }; + //~^ ERROR mismatched types + let v = s[..2]; + //~^ ERROR the size for values of type + let w: &str = s[..2]; + //~^ ERROR mismatched types +} diff --git a/tests/ui/str/str-array-assignment.stderr b/tests/ui/str/str-array-assignment.stderr new file mode 100644 index 000000000..c23400a1d --- /dev/null +++ b/tests/ui/str/str-array-assignment.stderr @@ -0,0 +1,45 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/str-array-assignment.rs:3:37 + | +LL | let t = if true { s[..2] } else { s }; + | ------ ^ expected `str`, found `&str` + | | + | expected because of this + +error[E0308]: mismatched types + --> $DIR/str-array-assignment.rs:5:27 + | +LL | let u: &str = if true { s[..2] } else { s }; + | ^^^^^^ + | | + | expected `&str`, found `str` + | help: consider borrowing here: `&s[..2]` + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/str-array-assignment.rs:7:7 + | +LL | let v = s[..2]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let v = &s[..2]; + | + + +error[E0308]: mismatched types + --> $DIR/str-array-assignment.rs:9:17 + | +LL | let w: &str = s[..2]; + | ---- ^^^^^^ + | | | + | | expected `&str`, found `str` + | | help: consider borrowing here: `&s[..2]` + | expected due to this + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/str/str-as-char.fixed b/tests/ui/str/str-as-char.fixed new file mode 100644 index 000000000..42bbef839 --- /dev/null +++ b/tests/ui/str/str-as-char.fixed @@ -0,0 +1,5 @@ +// run-rustfix + +fn main() { + println!("â—â—"); //~ ERROR character literal may only contain one codepoint +} diff --git a/tests/ui/str/str-as-char.rs b/tests/ui/str/str-as-char.rs new file mode 100644 index 000000000..09b9dfc59 --- /dev/null +++ b/tests/ui/str/str-as-char.rs @@ -0,0 +1,5 @@ +// run-rustfix + +fn main() { + println!('â—â—'); //~ ERROR character literal may only contain one codepoint +} diff --git a/tests/ui/str/str-as-char.stderr b/tests/ui/str/str-as-char.stderr new file mode 100644 index 000000000..c3cb488e3 --- /dev/null +++ b/tests/ui/str/str-as-char.stderr @@ -0,0 +1,13 @@ +error: character literal may only contain one codepoint + --> $DIR/str-as-char.rs:4:14 + | +LL | println!('â—â—'); + | ^^^^ + | +help: if you meant to write a `str` literal, use double quotes + | +LL | println!("â—â—"); + | ~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/str/str-concat-on-double-ref.rs b/tests/ui/str/str-concat-on-double-ref.rs new file mode 100644 index 000000000..e68210d53 --- /dev/null +++ b/tests/ui/str/str-concat-on-double-ref.rs @@ -0,0 +1,7 @@ +fn main() { + let a: &String = &"1".to_owned(); + let b: &str = &"2"; + let c = a + b; + //~^ ERROR cannot add `&str` to `&String` + println!("{:?}", c); +} diff --git a/tests/ui/str/str-concat-on-double-ref.stderr b/tests/ui/str/str-concat-on-double-ref.stderr new file mode 100644 index 000000000..bd354679f --- /dev/null +++ b/tests/ui/str/str-concat-on-double-ref.stderr @@ -0,0 +1,18 @@ +error[E0369]: cannot add `&str` to `&String` + --> $DIR/str-concat-on-double-ref.rs:4:15 + | +LL | let c = a + b; + | - ^ - &str + | | | + | | `+` cannot be used to concatenate two `&str` strings + | &String + | + = note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + | +LL | let c = a.to_owned() + b; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/str/str-escape.rs b/tests/ui/str/str-escape.rs new file mode 100644 index 000000000..0264632fd --- /dev/null +++ b/tests/ui/str/str-escape.rs @@ -0,0 +1,11 @@ +// check-pass +fn main() { + let s = "\ + + "; + //~^^^ WARNING multiple lines skipped by escaped newline + let s = "foo\ +   bar + "; + //~^^^ WARNING non-ASCII whitespace symbol '\u{a0}' is not skipped +} diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr new file mode 100644 index 000000000..b2501f1a2 --- /dev/null +++ b/tests/ui/str/str-escape.stderr @@ -0,0 +1,21 @@ +warning: multiple lines skipped by escaped newline + --> $DIR/str-escape.rs:3:14 + | +LL | let s = "\ + | ______________^ +LL | | +LL | | "; + | |_____________^ skipping everything up to and including this point + +warning: non-ASCII whitespace symbol '\u{a0}' is not skipped + --> $DIR/str-escape.rs:7:17 + | +LL | let s = "foo\ + | _________________^ +LL | |   bar + | | ^ non-ASCII whitespace symbol '\u{a0}' is not skipped + | |___| + | + +warning: 2 warnings emitted + diff --git a/tests/ui/str/str-idx.rs b/tests/ui/str/str-idx.rs new file mode 100644 index 000000000..1b32ed553 --- /dev/null +++ b/tests/ui/str/str-idx.rs @@ -0,0 +1,7 @@ +pub fn main() { + let s: &str = "hello"; + let _: u8 = s[4]; //~ ERROR the type `str` cannot be indexed by `{integer}` + let _ = s.get(4); //~ ERROR the type `str` cannot be indexed by `{integer}` + let _ = s.get_unchecked(4); //~ ERROR the type `str` cannot be indexed by `{integer}` + let _: u8 = s['c']; //~ ERROR the type `str` cannot be indexed by `char` +} diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr new file mode 100644 index 000000000..cb1a6fcac --- /dev/null +++ b/tests/ui/str/str-idx.stderr @@ -0,0 +1,54 @@ +error[E0277]: the type `str` cannot be indexed by `{integer}` + --> $DIR/str-idx.rs:3:19 + | +LL | let _: u8 = s[4]; + | ^ string indices are ranges of `usize` + | + = help: the trait `SliceIndex` is not implemented for `{integer}` + = note: you can use `.chars().nth()` or `.bytes().nth()` + for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `str` to implement `Index<{integer}>` + +error[E0277]: the type `str` cannot be indexed by `{integer}` + --> $DIR/str-idx.rs:4:19 + | +LL | let _ = s.get(4); + | --- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call + | + = help: the trait `SliceIndex` is not implemented for `{integer}` + = note: you can use `.chars().nth()` or `.bytes().nth()` + for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` +note: required by a bound in `core::str::::get` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + +error[E0277]: the type `str` cannot be indexed by `{integer}` + --> $DIR/str-idx.rs:5:29 + | +LL | let _ = s.get_unchecked(4); + | ------------- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call + | + = help: the trait `SliceIndex` is not implemented for `{integer}` + = note: you can use `.chars().nth()` or `.bytes().nth()` + for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` +note: required by a bound in `core::str::::get_unchecked` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + +error[E0277]: the type `str` cannot be indexed by `char` + --> $DIR/str-idx.rs:6:19 + | +LL | let _: u8 = s['c']; + | ^^^ string indices are ranges of `usize` + | + = help: the trait `SliceIndex` is not implemented for `char` + = note: required for `str` to implement `Index` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/str/str-lit-type-mismatch.rs b/tests/ui/str/str-lit-type-mismatch.rs new file mode 100644 index 000000000..12637c7b9 --- /dev/null +++ b/tests/ui/str/str-lit-type-mismatch.rs @@ -0,0 +1,5 @@ +fn main() { + let x: &[u8] = "foo"; //~ ERROR mismatched types + let y: &[u8; 4] = "baaa"; //~ ERROR mismatched types + let z: &str = b"foo"; //~ ERROR mismatched types +} diff --git a/tests/ui/str/str-lit-type-mismatch.stderr b/tests/ui/str/str-lit-type-mismatch.stderr new file mode 100644 index 000000000..6b56cd6f3 --- /dev/null +++ b/tests/ui/str/str-lit-type-mismatch.stderr @@ -0,0 +1,49 @@ +error[E0308]: mismatched types + --> $DIR/str-lit-type-mismatch.rs:2:20 + | +LL | let x: &[u8] = "foo"; + | ----- ^^^^^ expected slice `[u8]`, found `str` + | | + | expected due to this + | + = note: expected reference `&[u8]` + found reference `&'static str` +help: consider adding a leading `b` + | +LL | let x: &[u8] = b"foo"; + | + + +error[E0308]: mismatched types + --> $DIR/str-lit-type-mismatch.rs:3:23 + | +LL | let y: &[u8; 4] = "baaa"; + | -------- ^^^^^^ expected array `[u8; 4]`, found `str` + | | + | expected due to this + | + = note: expected reference `&[u8; 4]` + found reference `&'static str` +help: consider adding a leading `b` + | +LL | let y: &[u8; 4] = b"baaa"; + | + + +error[E0308]: mismatched types + --> $DIR/str-lit-type-mismatch.rs:4:19 + | +LL | let z: &str = b"foo"; + | ---- ^^^^^^ expected `str`, found array `[u8; 3]` + | | + | expected due to this + | + = note: expected reference `&str` + found reference `&'static [u8; 3]` +help: consider removing the leading `b` + | +LL - let z: &str = b"foo"; +LL + let z: &str = "foo"; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/str/str-mut-idx.rs b/tests/ui/str/str-mut-idx.rs new file mode 100644 index 000000000..575a9eae8 --- /dev/null +++ b/tests/ui/str/str-mut-idx.rs @@ -0,0 +1,17 @@ +fn bot() -> T { loop {} } + +fn mutate(s: &mut str) { + s[1..2] = bot(); + //~^ ERROR the size for values of type + //~| ERROR the size for values of type + s[1usize] = bot(); + //~^ ERROR the type `str` cannot be indexed by `usize` + s.get_mut(1); + //~^ ERROR the type `str` cannot be indexed by `{integer}` + s.get_unchecked_mut(1); + //~^ ERROR the type `str` cannot be indexed by `{integer}` + s['c']; + //~^ ERROR the type `str` cannot be indexed by `char` +} + +pub fn main() {} diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr new file mode 100644 index 000000000..ca4b86ba3 --- /dev/null +++ b/tests/ui/str/str-mut-idx.stderr @@ -0,0 +1,78 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/str-mut-idx.rs:4:15 + | +LL | s[1..2] = bot(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `bot` + --> $DIR/str-mut-idx.rs:1:8 + | +LL | fn bot() -> T { loop {} } + | ^ required by this bound in `bot` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn bot() -> T { loop {} } + | ++++++++ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/str-mut-idx.rs:4:5 + | +LL | s[1..2] = bot(); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the left-hand-side of an assignment must have a statically known size + +error[E0277]: the type `str` cannot be indexed by `usize` + --> $DIR/str-mut-idx.rs:7:7 + | +LL | s[1usize] = bot(); + | ^^^^^^ string indices are ranges of `usize` + | + = help: the trait `SliceIndex` is not implemented for `usize` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `str` to implement `Index` + +error[E0277]: the type `str` cannot be indexed by `{integer}` + --> $DIR/str-mut-idx.rs:9:15 + | +LL | s.get_mut(1); + | ------- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call + | + = help: the trait `SliceIndex` is not implemented for `{integer}` + = note: you can use `.chars().nth()` or `.bytes().nth()` + for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` +note: required by a bound in `core::str::::get_mut` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + +error[E0277]: the type `str` cannot be indexed by `{integer}` + --> $DIR/str-mut-idx.rs:11:25 + | +LL | s.get_unchecked_mut(1); + | ----------------- ^ string indices are ranges of `usize` + | | + | required by a bound introduced by this call + | + = help: the trait `SliceIndex` is not implemented for `{integer}` + = note: you can use `.chars().nth()` or `.bytes().nth()` + for more information, see chapter 8 in The Book: + = help: the trait `SliceIndex<[T]>` is implemented for `usize` +note: required by a bound in `core::str::::get_unchecked_mut` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL + +error[E0277]: the type `str` cannot be indexed by `char` + --> $DIR/str-mut-idx.rs:13:7 + | +LL | s['c']; + | ^^^ string indices are ranges of `usize` + | + = help: the trait `SliceIndex` is not implemented for `char` + = note: required for `str` to implement `Index` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/str/str-overrun.rs b/tests/ui/str/str-overrun.rs new file mode 100644 index 000000000..a3ec89413 --- /dev/null +++ b/tests/ui/str/str-overrun.rs @@ -0,0 +1,10 @@ +// run-fail +// error-pattern:index out of bounds: the len is 5 but the index is 5 +// ignore-emscripten no processes + +fn main() { + let s: String = "hello".to_string(); + + // Bounds-check panic. + assert_eq!(s.as_bytes()[5], 0x0 as u8); +} diff --git a/tests/ui/string-box-error.rs b/tests/ui/string-box-error.rs new file mode 100644 index 000000000..11a5bd07c --- /dev/null +++ b/tests/ui/string-box-error.rs @@ -0,0 +1,12 @@ +// run-pass +// Ensure that both `Box` and `Box` can be +// obtained from `String`. + +use std::error::Error; + +fn main() { + let _err1: Box = From::from("test".to_string()); + let _err2: Box = From::from("test".to_string()); + let _err3: Box = From::from("test"); + let _err4: Box = From::from("test"); +} diff --git a/tests/ui/struct-ctor-mangling.rs b/tests/ui/struct-ctor-mangling.rs new file mode 100644 index 000000000..ba6abbf03 --- /dev/null +++ b/tests/ui/struct-ctor-mangling.rs @@ -0,0 +1,14 @@ +// run-pass + +fn size_of_val(_: &T) -> usize { + std::mem::size_of::() +} + +struct Foo(#[allow(unused_tuple_struct_fields)] i64); + +// Test that the (symbol) mangling of `Foo` (the `struct` type) and that of +// `typeof Foo` (the function type of the `struct` constructor) don't collide. +fn main() { + size_of_val(&Foo(0)); + size_of_val(&Foo); +} diff --git a/tests/ui/structs-enums/align-enum.rs b/tests/ui/structs-enums/align-enum.rs new file mode 100644 index 000000000..fa872caa3 --- /dev/null +++ b/tests/ui/structs-enums/align-enum.rs @@ -0,0 +1,54 @@ +// run-pass +#![allow(dead_code)] + +use std::mem; + +// Raising alignment +#[repr(align(16))] +enum Align16 { + Foo { foo: u32 }, + Bar { bar: u32 }, +} + +// Raise alignment by maximum +#[repr(align(1), align(16))] +#[repr(align(32))] +#[repr(align(4))] +enum Align32 { + Foo, + Bar, +} + +// Not reducing alignment +#[repr(align(4))] +enum AlsoAlign16 { + Foo { limb_with_align16: Align16 }, + Bar, +} + +// No niche for discriminant when used as limb +#[repr(align(16))] +struct NoNiche16(u64, u64); + +// Discriminant will require extra space, but enum needs to stay compatible +// with alignment 16 +#[repr(align(1))] +enum AnotherAlign16 { + Foo { limb_with_noniche16: NoNiche16 }, + Bar, + Baz, +} + +fn main() { + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 16); + + assert_eq!(mem::align_of::(), 32); + assert_eq!(mem::size_of::(), 32); + + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 16); + + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 32); +} diff --git a/tests/ui/structs-enums/align-struct.rs b/tests/ui/structs-enums/align-struct.rs new file mode 100644 index 000000000..f5418e754 --- /dev/null +++ b/tests/ui/structs-enums/align-struct.rs @@ -0,0 +1,244 @@ +// run-pass +#![allow(dead_code)] + +use std::mem; + +// Raising alignment +#[repr(align(16))] +#[derive(Clone, Copy, Debug)] +struct Align16(i32); + +// Lowering has no effect +#[repr(align(1))] +struct Align1(i32); + +// Multiple attributes take the max +#[repr(align(4))] +#[repr(align(16))] +#[repr(align(8))] +struct AlignMany(i32); + +// Raising alignment may not alter size. +#[repr(align(8))] +#[allow(dead_code)] +struct Align8Many { + a: i32, + b: i32, + c: i32, + d: u8, +} + +enum Enum { + #[allow(dead_code)] + A(i32), + B(Align16) +} + +// Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test +#[repr(C)] +struct Nested { + a: i32, + b: i32, + c: Align16, + d: i8, +} + +#[repr(packed)] +struct Packed(i32); + +#[repr(align(16))] +struct AlignContainsPacked { + a: Packed, + b: Packed, +} + +#[repr(C, packed(4))] +struct Packed4C { + a: u32, + b: u64, +} + +#[repr(align(16))] +struct AlignContainsPacked4C { + a: Packed4C, + b: u64, +} + +// The align limit was originally smaller (2^15). +// Check that it works with big numbers. +#[repr(align(0x10000))] +struct AlignLarge { + stuff: [u8; 0x10000], +} + +union UnionContainsAlign { + a: Align16, + b: f32 +} + +impl Align16 { + // return aligned type + pub fn new(i: i32) -> Align16 { + Align16(i) + } + // pass aligned type + pub fn consume(a: Align16) -> i32 { + a.0 + } +} + +const CONST_ALIGN16: Align16 = Align16(7); +static STATIC_ALIGN16: Align16 = Align16(8); + +// Check the actual address is aligned +fn is_aligned_to(p: &T, align: usize) -> bool { + let addr = p as *const T as usize; + (addr & (align - 1)) == 0 +} + +pub fn main() { + // check alignment and size by type and value + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 16); + + let a = Align16(7); + assert_eq!(a.0, 7); + assert_eq!(mem::align_of_val(&a), 16); + assert_eq!(mem::size_of_val(&a), 16); + + assert!(is_aligned_to(&a, 16)); + + // lowering should have no effect + assert_eq!(mem::align_of::(), 4); + assert_eq!(mem::size_of::(), 4); + let a = Align1(7); + assert_eq!(a.0, 7); + assert_eq!(mem::align_of_val(&a), 4); + assert_eq!(mem::size_of_val(&a), 4); + assert!(is_aligned_to(&a, 4)); + + // when multiple attributes are specified the max should be used + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 16); + let a = AlignMany(7); + assert_eq!(a.0, 7); + assert_eq!(mem::align_of_val(&a), 16); + assert_eq!(mem::size_of_val(&a), 16); + assert!(is_aligned_to(&a, 16)); + + // raising alignment should not reduce size + assert_eq!(mem::align_of::(), 8); + assert_eq!(mem::size_of::(), 16); + let a = Align8Many { a: 1, b: 2, c: 3, d: 4 }; + assert_eq!(a.a, 1); + assert_eq!(mem::align_of_val(&a), 8); + assert_eq!(mem::size_of_val(&a), 16); + assert!(is_aligned_to(&a, 8)); + + // return type + let a = Align16::new(1); + assert_eq!(mem::align_of_val(&a), 16); + assert_eq!(mem::size_of_val(&a), 16); + assert_eq!(a.0, 1); + assert!(is_aligned_to(&a, 16)); + assert_eq!(Align16::consume(a), 1); + + // check const alignment, size and value + assert_eq!(mem::align_of_val(&CONST_ALIGN16), 16); + assert_eq!(mem::size_of_val(&CONST_ALIGN16), 16); + assert_eq!(CONST_ALIGN16.0, 7); + assert!(is_aligned_to(&CONST_ALIGN16, 16)); + + // check global static alignment, size and value + assert_eq!(mem::align_of_val(&STATIC_ALIGN16), 16); + assert_eq!(mem::size_of_val(&STATIC_ALIGN16), 16); + assert_eq!(STATIC_ALIGN16.0, 8); + assert!(is_aligned_to(&STATIC_ALIGN16, 16)); + + // Note that the size of Nested may change if struct field re-ordering is enabled + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 48); + let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4}; + assert_eq!(mem::align_of_val(&a), 16); + assert_eq!(mem::align_of_val(&a.b), 4); + assert_eq!(mem::align_of_val(&a.c), 16); + assert_eq!(mem::size_of_val(&a), 48); + assert!(is_aligned_to(&a, 16)); + // check the correct fields are indexed + assert_eq!(a.a, 1); + assert_eq!(a.b, 2); + assert_eq!(a.c.0, 3); + assert_eq!(a.d, 4); + + // enum should be aligned to max alignment + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::align_of_val(&Enum::B(Align16(0))), 16); + let e = Enum::B(Align16(15)); + match e { + Enum::B(ref a) => { + assert_eq!(a.0, 15); + assert_eq!(mem::align_of_val(a), 16); + assert_eq!(mem::size_of_val(a), 16); + }, + _ => () + } + assert!(is_aligned_to(&e, 16)); + + // check union alignment + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 16); + let u = UnionContainsAlign { a: Align16(10) }; + unsafe { + assert_eq!(mem::align_of_val(&u.a), 16); + assert_eq!(mem::size_of_val(&u.a), 16); + assert_eq!(u.a.0, 10); + let UnionContainsAlign { a } = u; + assert_eq!(a.0, 10); + } + + // arrays of aligned elements should also be aligned + assert_eq!(mem::align_of::<[Align16;2]>(), 16); + assert_eq!(mem::size_of::<[Align16;2]>(), 32); + + let a = [Align16(0), Align16(1)]; + assert_eq!(mem::align_of_val(&a[0]), 16); + assert_eq!(mem::align_of_val(&a[1]), 16); + assert!(is_aligned_to(&a, 16)); + + // check heap value is aligned + assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16); + + // check heap array is aligned + let a = vec!(Align16(0), Align16(1)); + assert_eq!(mem::align_of_val(&a[0]), 16); + assert_eq!(mem::align_of_val(&a[1]), 16); + + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 16); + let a = AlignContainsPacked { a: Packed(1), b: Packed(2) }; + assert_eq!(mem::align_of_val(&a), 16); + assert_eq!(mem::align_of_val(&a.a), 1); + assert_eq!(mem::align_of_val(&a.b), 1); + assert_eq!(mem::size_of_val(&a), 16); + assert!(is_aligned_to(&a, 16)); + + assert_eq!(mem::align_of::(), 16); + assert_eq!(mem::size_of::(), 32); + let a = AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }, b: 3 }; + assert_eq!(mem::align_of_val(&a), 16); + assert_eq!(mem::align_of_val(&a.a), 4); + assert_eq!(mem::align_of_val(&a.b), mem::align_of::()); + assert_eq!(mem::size_of_val(&a), 32); + assert!(is_aligned_to(&a, 16)); + + let mut large = Box::new(AlignLarge { + stuff: [0; 0x10000], + }); + large.stuff[0] = 132; + *large.stuff.last_mut().unwrap() = 102; + assert_eq!(large.stuff[0], 132); + assert_eq!(large.stuff.last(), Some(&102)); + assert_eq!(mem::align_of::(), 0x10000); + assert_eq!(mem::align_of_val(&*large), 0x10000); + assert!(is_aligned_to(&*large, 0x10000)); +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class.rs b/tests/ui/structs-enums/auxiliary/cci_class.rs new file mode 100644 index 000000000..de2945d74 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class.rs @@ -0,0 +1,14 @@ +pub mod kitties { + pub struct cat { + meows : usize, + + pub how_hungry : isize, + } + + pub fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } + } +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_2.rs b/tests/ui/structs-enums/auxiliary/cci_class_2.rs new file mode 100644 index 000000000..c3de3150e --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class_2.rs @@ -0,0 +1,19 @@ +pub mod kitties { + pub struct cat { + meows : usize, + + pub how_hungry : isize, + + } + + impl cat { + pub fn speak(&self) {} + } + + pub fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } + } +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_3.rs b/tests/ui/structs-enums/auxiliary/cci_class_3.rs new file mode 100644 index 000000000..fb7fad0b5 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class_3.rs @@ -0,0 +1,19 @@ +pub mod kitties { + pub struct cat { + meows : usize, + + pub how_hungry : isize, + } + + impl cat { + pub fn speak(&mut self) { self.meows += 1; } + pub fn meow_count(&mut self) -> usize { self.meows } + } + + pub fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } + } +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_4.rs b/tests/ui/structs-enums/auxiliary/cci_class_4.rs new file mode 100644 index 000000000..85aa3bc8c --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class_4.rs @@ -0,0 +1,41 @@ +pub mod kitties { + pub struct cat { + meows : usize, + + pub how_hungry : isize, + pub name : String, + } + + impl cat { + pub fn speak(&mut self) { self.meow(); } + + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } else { + println!("Not hungry!"); + return false; + } + } + } + + impl cat { + pub fn meow(&mut self) { + println!("Meow"); + self.meows += 1; + if self.meows % 5 == 0 { + self.how_hungry += 1; + } + } + } + + pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } + } +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_6.rs b/tests/ui/structs-enums/auxiliary/cci_class_6.rs new file mode 100644 index 000000000..35f93d0c6 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class_6.rs @@ -0,0 +1,25 @@ +pub mod kitties { + + pub struct cat { + info : Vec , + meows : usize, + + pub how_hungry : isize, + } + + impl cat { + pub fn speak(&mut self, stuff: Vec ) { + self.meows += stuff.len(); + } + + pub fn meow_count(&mut self) -> usize { self.meows } + } + + pub fn cat(in_x : usize, in_y : isize, in_info: Vec ) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + info: in_info + } + } +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_cast.rs b/tests/ui/structs-enums/auxiliary/cci_class_cast.rs new file mode 100644 index 000000000..dfc3c56dd --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class_cast.rs @@ -0,0 +1,50 @@ +pub mod kitty { + use std::fmt; + + pub struct cat { + meows : usize, + pub how_hungry : isize, + pub name : String, + } + + impl fmt::Display for cat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) + } + } + + impl cat { + fn meow(&mut self) { + println!("Meow"); + self.meows += 1; + if self.meows % 5 == 0 { + self.how_hungry += 1; + } + } + + } + + impl cat { + pub fn speak(&mut self) { self.meow(); } + + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } + else { + println!("Not hungry!"); + return false; + } + } + } + + pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } + } +} diff --git a/tests/ui/structs-enums/auxiliary/cci_class_trait.rs b/tests/ui/structs-enums/auxiliary/cci_class_trait.rs new file mode 100644 index 000000000..2d02b591c --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/cci_class_trait.rs @@ -0,0 +1,5 @@ +pub mod animals { + pub trait noisy { + fn speak(&mut self); + } +} diff --git a/tests/ui/structs-enums/auxiliary/empty-struct.rs b/tests/ui/structs-enums/auxiliary/empty-struct.rs new file mode 100644 index 000000000..93275e714 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/empty-struct.rs @@ -0,0 +1,9 @@ +pub struct XEmpty1 {} +pub struct XEmpty2; +pub struct XEmpty7(); + +pub enum XE { + XEmpty3 {}, + XEmpty4, + XEmpty6(), +} diff --git a/tests/ui/structs-enums/auxiliary/namespaced_enum_emulate_flat.rs b/tests/ui/structs-enums/auxiliary/namespaced_enum_emulate_flat.rs new file mode 100644 index 000000000..55e6b34ac --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/namespaced_enum_emulate_flat.rs @@ -0,0 +1,25 @@ +pub use Foo::*; + +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} +} + +pub mod nest { + pub use self::Bar::*; + + pub enum Bar { + D, + E(isize), + F { a: isize }, + } + + impl Bar { + pub fn foo() {} + } +} diff --git a/tests/ui/structs-enums/auxiliary/namespaced_enums.rs b/tests/ui/structs-enums/auxiliary/namespaced_enums.rs new file mode 100644 index 000000000..d3548c76c --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/namespaced_enums.rs @@ -0,0 +1,10 @@ +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} + pub fn bar(&self) {} +} diff --git a/tests/ui/structs-enums/auxiliary/newtype_struct_xc.rs b/tests/ui/structs-enums/auxiliary/newtype_struct_xc.rs new file mode 100644 index 000000000..9d1e0742e --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/newtype_struct_xc.rs @@ -0,0 +1,3 @@ +#![crate_type="lib"] + +pub struct Au(pub isize); diff --git a/tests/ui/structs-enums/auxiliary/struct_destructuring_cross_crate.rs b/tests/ui/structs-enums/auxiliary/struct_destructuring_cross_crate.rs new file mode 100644 index 000000000..3665ae7e8 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/struct_destructuring_cross_crate.rs @@ -0,0 +1,6 @@ +#![crate_type="lib"] + +pub struct S { + pub x: isize, + pub y: isize, +} diff --git a/tests/ui/structs-enums/auxiliary/struct_variant_xc_aux.rs b/tests/ui/structs-enums/auxiliary/struct_variant_xc_aux.rs new file mode 100644 index 000000000..e919df611 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/struct_variant_xc_aux.rs @@ -0,0 +1,8 @@ +#![crate_name="struct_variant_xc_aux"] +#![crate_type = "lib"] + +#[derive(Copy, Clone)] +pub enum Enum { + Variant(u8), + StructVariant { arg: u8 } +} diff --git a/tests/ui/structs-enums/auxiliary/xcrate_struct_aliases.rs b/tests/ui/structs-enums/auxiliary/xcrate_struct_aliases.rs new file mode 100644 index 000000000..bc8879aa3 --- /dev/null +++ b/tests/ui/structs-enums/auxiliary/xcrate_struct_aliases.rs @@ -0,0 +1,6 @@ +pub struct S { + pub x: isize, + pub y: isize, +} + +pub type S2 = S; diff --git a/tests/ui/structs-enums/borrow-tuple-fields.rs b/tests/ui/structs-enums/borrow-tuple-fields.rs new file mode 100644 index 000000000..b1d8f9164 --- /dev/null +++ b/tests/ui/structs-enums/borrow-tuple-fields.rs @@ -0,0 +1,38 @@ +// run-pass + +struct Foo(isize, isize); + +fn main() { + let x = (1, 2); + let a = &x.0; + let b = &x.0; + assert_eq!(*a, 1); + assert_eq!(*b, 1); + + let mut x = (1, 2); + { + let a = &x.0; + let b = &mut x.1; + *b = 5; + assert_eq!(*a, 1); + } + assert_eq!(x.0, 1); + assert_eq!(x.1, 5); + + + let x = Foo(1, 2); + let a = &x.0; + let b = &x.0; + assert_eq!(*a, 1); + assert_eq!(*b, 1); + + let mut x = Foo(1, 2); + { + let a = &x.0; + let b = &mut x.1; + *b = 5; + assert_eq!(*a, 1); + } + assert_eq!(x.0, 1); + assert_eq!(x.1, 5); +} diff --git a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs b/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs new file mode 100644 index 000000000..f870096fd --- /dev/null +++ b/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs @@ -0,0 +1,18 @@ +// run-pass +// aux-build:cci_class_cast.rs + +extern crate cci_class_cast; + +use std::string::ToString; +use cci_class_cast::kitty::cat; + +fn print_out(thing: Box, expected: String) { + let actual = (*thing).to_string(); + println!("{}", actual); + assert_eq!(actual.to_string(), expected); +} + +pub fn main() { + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; + print_out(nyan, "nyan".to_string()); +} diff --git a/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs b/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs new file mode 100644 index 000000000..ca35a615d --- /dev/null +++ b/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs @@ -0,0 +1,94 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +trait noisy { + fn speak(&mut self) -> isize; +} + +struct dog { + barks: usize, + + volume: isize, +} + +impl dog { + fn bark(&mut self) -> isize { + println!("Woof {} {}", self.barks, self.volume); + self.barks += 1_usize; + if self.barks % 3_usize == 0_usize { + self.volume += 1; + } + if self.barks % 10_usize == 0_usize { + self.volume -= 2; + } + println!("Grrr {} {}", self.barks, self.volume); + self.volume + } +} + +impl noisy for dog { + fn speak(&mut self) -> isize { + self.bark() + } +} + +fn dog() -> dog { + dog { + volume: 0, + barks: 0_usize + } +} + +#[derive(Clone)] +struct cat { + meows: usize, + + how_hungry: isize, + name: String, +} + +impl noisy for cat { + fn speak(&mut self) -> isize { + self.meow() as isize + } +} + +impl cat { + pub fn meow_count(&self) -> usize { + self.meows + } +} + +impl cat { + fn meow(&mut self) -> usize { + println!("Meow"); + self.meows += 1_usize; + if self.meows % 5_usize == 0_usize { + self.how_hungry += 1; + } + self.meows + } +} + +fn cat(in_x: usize, in_y: isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } +} + + +fn annoy_neighbors(critter: &mut dyn noisy) { + for _i in 0_usize..10 { critter.speak(); } +} + +pub fn main() { + let mut nyan: cat = cat(0_usize, 2, "nyan".to_string()); + let mut whitefang: dog = dog(); + annoy_neighbors(&mut nyan); + annoy_neighbors(&mut whitefang); + assert_eq!(nyan.meow_count(), 10_usize); + assert_eq!(whitefang.volume, 1); +} diff --git a/tests/ui/structs-enums/class-cast-to-trait.rs b/tests/ui/structs-enums/class-cast-to-trait.rs new file mode 100644 index 000000000..1019bb300 --- /dev/null +++ b/tests/ui/structs-enums/class-cast-to-trait.rs @@ -0,0 +1,60 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + +// ignore-freebsd FIXME fails on BSD + + +trait noisy { + fn speak(&mut self); +} + +struct cat { + meows: usize, + how_hungry: isize, + name: String, +} + +impl noisy for cat { + fn speak(&mut self) { self.meow(); } +} + +impl cat { + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } + else { + println!("Not hungry!"); + return false; + } + } +} + +impl cat { + fn meow(&mut self) { + println!("Meow"); + self.meows += 1; + if self.meows % 5 == 0 { + self.how_hungry += 1; + } + } +} + +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } +} + + +pub fn main() { + let mut nyan = cat(0, 2, "nyan".to_string()); + let mut nyan: &mut dyn noisy = &mut nyan; + nyan.speak(); +} diff --git a/tests/ui/structs-enums/class-dtor.rs b/tests/ui/structs-enums/class-dtor.rs new file mode 100644 index 000000000..583a5e240 --- /dev/null +++ b/tests/ui/structs-enums/class-dtor.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct cat { + done : extern "C" fn(usize), + meows : usize, +} + +impl Drop for cat { + fn drop(&mut self) { + (self.done)(self.meows); + } +} + +fn cat(done: extern "C" fn(usize)) -> cat { + cat { + meows: 0, + done: done + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/class-exports.rs b/tests/ui/structs-enums/class-exports.rs new file mode 100644 index 000000000..ee20887cb --- /dev/null +++ b/tests/ui/structs-enums/class-exports.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +/* Test that exporting a class also exports its + public fields and methods */ + +use kitty::cat; + +mod kitty { + pub struct cat { + meows: usize, + name: String, + } + + impl cat { + pub fn get_name(&self) -> String { self.name.clone() } + } + + pub fn cat(in_name: String) -> cat { + cat { + name: in_name, + meows: 0 + } + } +} + +pub fn main() { + assert_eq!(cat("Spreckles".to_string()).get_name(), + "Spreckles".to_string()); +} diff --git a/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs b/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs new file mode 100644 index 000000000..5e7830296 --- /dev/null +++ b/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs @@ -0,0 +1,107 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +use std::cmp; + +#[derive(Copy, Clone, Debug)] +enum cat_type { tuxedo, tabby, tortoiseshell } + +impl cmp::PartialEq for cat_type { + fn eq(&self, other: &cat_type) -> bool { + ((*self) as usize) == ((*other) as usize) + } + fn ne(&self, other: &cat_type) -> bool { !(*self).eq(other) } +} + +// Very silly -- this just returns the value of the name field +// for any isize value that's less than the meows field + +// ok: T should be in scope when resolving the trait ref for map +struct cat { + // Yes, you can have negative meows + meows : isize, + + how_hungry : isize, + name : T, +} + +impl cat { + pub fn speak(&mut self) { self.meow(); } + + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } else { + println!("Not hungry!"); + return false; + } + } + fn len(&self) -> usize { self.meows as usize } + fn is_empty(&self) -> bool { self.meows == 0 } + fn clear(&mut self) {} + fn contains_key(&self, k: &isize) -> bool { *k <= self.meows } + + fn find(&self, k: &isize) -> Option<&T> { + if *k <= self.meows { + Some(&self.name) + } else { + None + } + } + fn insert(&mut self, k: isize, _: T) -> bool { + self.meows += k; + true + } + + fn find_mut(&mut self, _k: &isize) -> Option<&mut T> { panic!() } + + fn remove(&mut self, k: &isize) -> bool { + if self.find(k).is_some() { + self.meows -= *k; true + } else { + false + } + } + + fn pop(&mut self, _k: &isize) -> Option { panic!() } + + fn swap(&mut self, _k: isize, _v: T) -> Option { panic!() } +} + +impl cat { + pub fn get(&self, k: &isize) -> &T { + match self.find(k) { + Some(v) => { v } + None => { panic!("epic fail"); } + } + } + + pub fn new(in_x: isize, in_y: isize, in_name: T) -> cat { + cat{meows: in_x, how_hungry: in_y, name: in_name } + } +} + +impl cat { + fn meow(&mut self) { + self.meows += 1; + println!("Meow {}", self.meows); + if self.meows % 5 == 0 { + self.how_hungry += 1; + } + } +} + +pub fn main() { + let mut nyan: cat = cat::new(0, 2, "nyan".to_string()); + for _ in 1_usize..5 { nyan.speak(); } + assert_eq!(*nyan.find(&1).unwrap(), "nyan".to_string()); + assert_eq!(nyan.find(&10), None); + let mut spotty: cat = cat::new(2, 57, cat_type::tuxedo); + for _ in 0_usize..6 { spotty.speak(); } + assert_eq!(spotty.len(), 8); + assert!((spotty.contains_key(&2))); + assert_eq!(spotty.get(&3), &cat_type::tuxedo); +} diff --git a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs b/tests/ui/structs-enums/class-implement-trait-cross-crate.rs new file mode 100644 index 000000000..31b795175 --- /dev/null +++ b/tests/ui/structs-enums/class-implement-trait-cross-crate.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// aux-build:cci_class_trait.rs +extern crate cci_class_trait; +use cci_class_trait::animals::noisy; + +struct cat { + meows: usize, + + how_hungry : isize, + name : String, +} + +impl cat { + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } + else { + println!("Not hungry!"); + return false; + } + } +} + +impl noisy for cat { + fn speak(&mut self) { self.meow(); } +} + +impl cat { + fn meow(&mut self) { + println!("Meow"); + self.meows += 1_usize; + if self.meows % 5_usize == 0_usize { + self.how_hungry += 1; + } + } +} + +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } +} + + +pub fn main() { + let mut nyan = cat(0_usize, 2, "nyan".to_string()); + nyan.eat(); + assert!((!nyan.eat())); + for _ in 1_usize..10_usize { nyan.speak(); }; + assert!((nyan.eat())); +} diff --git a/tests/ui/structs-enums/class-implement-traits.rs b/tests/ui/structs-enums/class-implement-traits.rs new file mode 100644 index 000000000..732aa146c --- /dev/null +++ b/tests/ui/structs-enums/class-implement-traits.rs @@ -0,0 +1,64 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +trait noisy { + fn speak(&mut self); +} + +#[derive(Clone)] +struct cat { + meows : usize, + + how_hungry : isize, + name : String, +} + +impl cat { + fn meow(&mut self) { + println!("Meow"); + self.meows += 1_usize; + if self.meows % 5_usize == 0_usize { + self.how_hungry += 1; + } + } +} + +impl cat { + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } else { + println!("Not hungry!"); + return false; + } + } +} + +impl noisy for cat { + fn speak(&mut self) { self.meow(); } +} + +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name.clone() + } +} + + +fn make_speak(mut c: C) { + c.speak(); +} + +pub fn main() { + let mut nyan = cat(0_usize, 2, "nyan".to_string()); + nyan.eat(); + assert!((!nyan.eat())); + for _ in 1_usize..10_usize { + make_speak(nyan.clone()); + } +} diff --git a/tests/ui/structs-enums/class-method-cross-crate.rs b/tests/ui/structs-enums/class-method-cross-crate.rs new file mode 100644 index 000000000..519f0685f --- /dev/null +++ b/tests/ui/structs-enums/class-method-cross-crate.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:cci_class_2.rs + +extern crate cci_class_2; +use cci_class_2::kitties::cat; + +pub fn main() { + let nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.speak(); +} diff --git a/tests/ui/structs-enums/class-methods-cross-crate.rs b/tests/ui/structs-enums/class-methods-cross-crate.rs new file mode 100644 index 000000000..c342af313 --- /dev/null +++ b/tests/ui/structs-enums/class-methods-cross-crate.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:cci_class_3.rs + +extern crate cci_class_3; +use cci_class_3::kitties::cat; + +pub fn main() { + let mut nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.speak(); + assert_eq!(nyan.meow_count(), 53); +} diff --git a/tests/ui/structs-enums/class-methods.rs b/tests/ui/structs-enums/class-methods.rs new file mode 100644 index 000000000..83f4a5fd3 --- /dev/null +++ b/tests/ui/structs-enums/class-methods.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(non_camel_case_types)] + + +struct cat { + meows : usize, + + how_hungry : isize, +} + +impl cat { + pub fn speak(&mut self) { self.meows += 1; } + pub fn meow_count(&mut self) -> usize { self.meows } +} + +fn cat(in_x: usize, in_y: isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } +} + +pub fn main() { + let mut nyan: cat = cat(52, 99); + let kitty = cat(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.speak(); + assert_eq!(nyan.meow_count(), 53); +} diff --git a/tests/ui/structs-enums/class-poly-methods-cross-crate.rs b/tests/ui/structs-enums/class-poly-methods-cross-crate.rs new file mode 100644 index 000000000..0307ba78d --- /dev/null +++ b/tests/ui/structs-enums/class-poly-methods-cross-crate.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:cci_class_6.rs + +extern crate cci_class_6; +use cci_class_6::kitties::cat; + +pub fn main() { + let mut nyan : cat = cat::(52_usize, 99, vec!['p']); + let mut kitty = cat(1000_usize, 2, vec!["tabby".to_string()]); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.speak(vec![1_usize,2_usize,3_usize]); + assert_eq!(nyan.meow_count(), 55_usize); + kitty.speak(vec!["meow".to_string(), "mew".to_string(), "purr".to_string(), "chirp".to_string()]); + assert_eq!(kitty.meow_count(), 1004_usize); +} diff --git a/tests/ui/structs-enums/class-poly-methods.rs b/tests/ui/structs-enums/class-poly-methods.rs new file mode 100644 index 000000000..da2870b58 --- /dev/null +++ b/tests/ui/structs-enums/class-poly-methods.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +struct cat { + info : Vec , + meows : usize, + + how_hungry : isize, +} + +impl cat { + pub fn speak(&mut self, stuff: Vec ) { + self.meows += stuff.len(); + } + pub fn meow_count(&mut self) -> usize { self.meows } +} + +fn cat(in_x : usize, in_y : isize, in_info: Vec ) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + info: in_info + } +} + +pub fn main() { + let mut nyan : cat = cat::(52, 99, vec![9]); + let mut kitty = cat(1000, 2, vec!["tabby".to_string()]); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.speak(vec![1,2,3]); + assert_eq!(nyan.meow_count(), 55); + kitty.speak(vec!["meow".to_string(), "mew".to_string(), "purr".to_string(), "chirp".to_string()]); + assert_eq!(kitty.meow_count(), 1004); +} diff --git a/tests/ui/structs-enums/class-separate-impl.rs b/tests/ui/structs-enums/class-separate-impl.rs new file mode 100644 index 000000000..3d6da1cc2 --- /dev/null +++ b/tests/ui/structs-enums/class-separate-impl.rs @@ -0,0 +1,63 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +use std::fmt; + +struct cat { + meows : usize, + + how_hungry : isize, + name : String, +} + +impl cat { + pub fn speak(&mut self) { self.meow(); } + + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } + else { + println!("Not hungry!"); + return false; + } + } +} + +impl cat { + fn meow(&mut self) { + println!("Meow"); + self.meows += 1; + if self.meows % 5 == 0 { + self.how_hungry += 1; + } + } +} + +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } +} + +impl fmt::Display for cat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name) + } +} + +fn print_out(thing: Box, expected: String) { + let actual = (*thing).to_string(); + println!("{}", actual); + assert_eq!(actual.to_string(), expected); +} + +pub fn main() { + let nyan: Box = Box::new(cat(0, 2, "nyan".to_string())) as Box; + print_out(nyan, "nyan".to_string()); +} diff --git a/tests/ui/structs-enums/class-str-field.rs b/tests/ui/structs-enums/class-str-field.rs new file mode 100644 index 000000000..a3dc66aab --- /dev/null +++ b/tests/ui/structs-enums/class-str-field.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +struct cat { + + name : String, + +} + +fn cat(in_name: String) -> cat { + cat { + name: in_name + } +} + +pub fn main() { + let _nyan = cat("nyan".to_string()); +} diff --git a/tests/ui/structs-enums/class-typarams.rs b/tests/ui/structs-enums/class-typarams.rs new file mode 100644 index 000000000..4b2d4b12e --- /dev/null +++ b/tests/ui/structs-enums/class-typarams.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomData; + +struct cat { + meows : usize, + how_hungry : isize, + m: PhantomData +} + +impl cat { + pub fn speak(&mut self) { self.meows += 1; } + pub fn meow_count(&mut self) -> usize { self.meows } +} + +fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + m: PhantomData + } +} + + +pub fn main() { + let _nyan : cat = cat::(52, 99); + // let mut kitty = cat(1000, 2); +} diff --git a/tests/ui/structs-enums/classes-cross-crate.rs b/tests/ui/structs-enums/classes-cross-crate.rs new file mode 100644 index 000000000..ca362c7a7 --- /dev/null +++ b/tests/ui/structs-enums/classes-cross-crate.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:cci_class_4.rs + +extern crate cci_class_4; +use cci_class_4::kitties::cat; + +pub fn main() { + let mut nyan = cat(0_usize, 2, "nyan".to_string()); + nyan.eat(); + assert!((!nyan.eat())); + for _ in 1_usize..10_usize { nyan.speak(); }; + assert!((nyan.eat())); +} diff --git a/tests/ui/structs-enums/classes-self-referential.rs b/tests/ui/structs-enums/classes-self-referential.rs new file mode 100644 index 000000000..27d6ebf2c --- /dev/null +++ b/tests/ui/structs-enums/classes-self-referential.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +// pretty-expanded FIXME #23616 + +struct kitten { + cat: Option, +} + +fn kitten(cat: Option) -> kitten { + kitten { + cat: cat + } +} + +type cat = Box; + +pub fn main() {} diff --git a/tests/ui/structs-enums/classes-simple-cross-crate.rs b/tests/ui/structs-enums/classes-simple-cross-crate.rs new file mode 100644 index 000000000..6ff0970c0 --- /dev/null +++ b/tests/ui/structs-enums/classes-simple-cross-crate.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:cci_class.rs + +extern crate cci_class; +use cci_class::kitties::cat; + +pub fn main() { + let nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); +} diff --git a/tests/ui/structs-enums/classes-simple-method.rs b/tests/ui/structs-enums/classes-simple-method.rs new file mode 100644 index 000000000..f3d98337d --- /dev/null +++ b/tests/ui/structs-enums/classes-simple-method.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +struct cat { + meows : usize, + + how_hungry : isize, +} + +impl cat { + pub fn speak(&mut self) {} +} + +fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } +} + +pub fn main() { + let mut nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); + nyan.speak(); +} diff --git a/tests/ui/structs-enums/classes-simple.rs b/tests/ui/structs-enums/classes-simple.rs new file mode 100644 index 000000000..568fbb29f --- /dev/null +++ b/tests/ui/structs-enums/classes-simple.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +struct cat { + meows : usize, + + how_hungry : isize, +} + +fn cat(in_x : usize, in_y : isize) -> cat { + cat { + meows: in_x, + how_hungry: in_y + } +} + +pub fn main() { + let nyan : cat = cat(52, 99); + let kitty = cat(1000, 2); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); +} diff --git a/tests/ui/structs-enums/classes.rs b/tests/ui/structs-enums/classes.rs new file mode 100644 index 000000000..51d84b909 --- /dev/null +++ b/tests/ui/structs-enums/classes.rs @@ -0,0 +1,51 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +struct cat { + meows : usize, + + how_hungry : isize, + name : String, +} + +impl cat { + pub fn speak(&mut self) { self.meow(); } + + pub fn eat(&mut self) -> bool { + if self.how_hungry > 0 { + println!("OM NOM NOM"); + self.how_hungry -= 2; + return true; + } else { + println!("Not hungry!"); + return false; + } + } +} + +impl cat { + fn meow(&mut self) { + println!("Meow"); + self.meows += 1_usize; + if self.meows % 5_usize == 0_usize { + self.how_hungry += 1; + } + } +} + +fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } +} + +pub fn main() { + let mut nyan = cat(0_usize, 2, "nyan".to_string()); + nyan.eat(); + assert!((!nyan.eat())); + for _ in 1_usize..10_usize { nyan.speak(); }; + assert!((nyan.eat())); +} diff --git a/tests/ui/structs-enums/codegen-tag-static-padding.rs b/tests/ui/structs-enums/codegen-tag-static-padding.rs new file mode 100644 index 000000000..8aa087c01 --- /dev/null +++ b/tests/ui/structs-enums/codegen-tag-static-padding.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// Issue #13186 + +// For simplicity of explanations assuming code is compiled for x86_64 +// Linux ABI. + +// Size of TestOption is 16, and alignment of TestOption is 8. +// Size of u8 is 1, and alignment of u8 is 1. +// So size of Request is 24, and alignment of Request must be 8: +// the maximum alignment of its fields. +// Last 7 bytes of Request struct are not occupied by any fields. + + + +enum TestOption { + TestNone, + TestSome(T), +} + +pub struct Request { + foo: TestOption, + bar: u8, +} + +fn default_instance() -> &'static Request { + static instance: Request = Request { + // LLVM does not allow to specify alignment of expressions, thus + // alignment of `foo` in constant is 1, not 8. + foo: TestOption::TestNone, + bar: 17, + // Space after last field is not occupied by any data, but it is + // reserved to make struct aligned properly. If compiler does + // not insert padding after last field when emitting constant, + // size of struct may be not equal to size of struct, and + // compiler crashes in internal assertion check. + }; + &instance +} + +fn non_default_instance() -> &'static Request { + static instance: Request = Request { + foo: TestOption::TestSome(0x1020304050607080), + bar: 19, + }; + &instance +} + +pub fn main() { + match default_instance() { + &Request { foo: TestOption::TestNone, bar: 17 } => {}, + _ => panic!(), + }; + match non_default_instance() { + &Request { foo: TestOption::TestSome(0x1020304050607080), bar: 19 } => {}, + _ => panic!(), + }; +} diff --git a/tests/ui/structs-enums/compare-generic-enums.rs b/tests/ui/structs-enums/compare-generic-enums.rs new file mode 100644 index 000000000..84f953b1f --- /dev/null +++ b/tests/ui/structs-enums/compare-generic-enums.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_camel_case_types)] + + +type an_int = isize; + +fn cmp(x: Option, y: Option) -> bool { + x == y +} + +pub fn main() { + assert!(!cmp(Some(3), None)); + assert!(!cmp(Some(3), Some(4))); + assert!(cmp(Some(3), Some(3))); + assert!(cmp(None, None)); +} diff --git a/tests/ui/structs-enums/cross-crate-newtype-struct-pat.rs b/tests/ui/structs-enums/cross-crate-newtype-struct-pat.rs new file mode 100644 index 000000000..eabffc161 --- /dev/null +++ b/tests/ui/structs-enums/cross-crate-newtype-struct-pat.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:newtype_struct_xc.rs + + +extern crate newtype_struct_xc; + +pub fn main() { + let x = newtype_struct_xc::Au(21); + match x { + newtype_struct_xc::Au(n) => assert_eq!(n, 21) + } +} diff --git a/tests/ui/structs-enums/discrim-explicit-23030.rs b/tests/ui/structs-enums/discrim-explicit-23030.rs new file mode 100644 index 000000000..e17025e9e --- /dev/null +++ b/tests/ui/structs-enums/discrim-explicit-23030.rs @@ -0,0 +1,145 @@ +// run-pass +// Issue 23030: Workaround overflowing discriminant +// with explicit assignments. + +// See also ui/discrim/discrim-overflow.rs, which shows what +// happens if you leave the OhNo explicit cases out here. + +fn f_i8() { + #[repr(i8)] + enum A { + Ok = i8::MAX - 1, + Ok2, + OhNo = i8::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i8; + assert_eq!(z, 0); +} + +fn f_u8() { + #[repr(u8)] + enum A { + Ok = u8::MAX - 1, + Ok2, + OhNo = u8::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i16() { + #[repr(i16)] + enum A { + Ok = i16::MAX - 1, + Ok2, + OhNo = i16::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i16; + assert_eq!(z, 0); +} + +fn f_u16() { + #[repr(u16)] + enum A { + Ok = u16::MAX - 1, + Ok2, + OhNo = u16::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i32() { + #[repr(i32)] + enum A { + Ok = i32::MAX - 1, + Ok2, + OhNo = i32::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i32; + assert_eq!(z, 0); +} + +fn f_u32() { + #[repr(u32)] + enum A { + Ok = u32::MAX - 1, + Ok2, + OhNo = u32::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_i64() { + #[repr(i64)] + enum A { + Ok = i64::MAX - 1, + Ok2, + OhNo = i64::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as i64; + assert_eq!(z, 0); +} + +fn f_u64() { + #[repr(u64)] + enum A { + Ok = u64::MAX - 1, + Ok2, + OhNo = u64::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn f_isize() { + #[repr(isize)] + enum A { + Ok = isize::MAX - 1, + Ok2, + OhNo = isize::MIN, + NotTheEnd = -1, + Zero, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); + let z = (A::NotTheEnd, A::Zero).1 as isize; + assert_eq!(z, 0); +} + +fn f_usize() { + #[repr(usize)] + enum A { + Ok = usize::MAX - 1, + Ok2, + OhNo = usize::MIN, + } + + let _x = (A::Ok, A::Ok2, A::OhNo); +} + +fn main() { + f_i8(); f_u8(); + f_i16(); f_u16(); + f_i32(); f_u32(); + f_i64(); f_u64(); + + f_isize(); f_usize(); +} diff --git a/tests/ui/structs-enums/empty-struct-braces.rs b/tests/ui/structs-enums/empty-struct-braces.rs new file mode 100644 index 000000000..0663687c9 --- /dev/null +++ b/tests/ui/structs-enums/empty-struct-braces.rs @@ -0,0 +1,213 @@ +// run-pass +#![allow(unused_variables)] +#![allow(non_upper_case_globals)] + +// Empty struct defined with braces add names into type namespace +// Empty struct defined without braces add names into both type and value namespaces + +// aux-build:empty-struct.rs + +extern crate empty_struct; +use empty_struct::*; + +struct Empty1 {} +struct Empty2; +struct Empty7(); + +#[derive(PartialEq, Eq)] +struct Empty3 {} + +const Empty3: Empty3 = Empty3 {}; + +enum E { + Empty4 {}, + Empty5, + Empty6(), +} + +fn local() { + let e1: Empty1 = Empty1 {}; + let e2: Empty2 = Empty2 {}; + let e2: Empty2 = Empty2; + let e3: Empty3 = Empty3 {}; + let e3: Empty3 = Empty3; + let e4: E = E::Empty4 {}; + let e5: E = E::Empty5 {}; + let e5: E = E::Empty5; + let e6: E = E::Empty6 {}; + let e6: E = E::Empty6(); + let ctor6: fn() -> E = E::Empty6; + let e7: Empty7 = Empty7 {}; + let e7: Empty7 = Empty7(); + let ctor7: fn() -> Empty7 = Empty7; + + match e1 { + Empty1 {} => {} + } + match e2 { + Empty2 {} => {} + } + match e3 { + Empty3 {} => {} + } + match e4 { + E::Empty4 {} => {} + _ => {} + } + match e5 { + E::Empty5 {} => {} + _ => {} + } + match e6 { + E::Empty6 {} => {} + _ => {} + } + match e7 { + Empty7 {} => {} + } + + match e1 { + Empty1 { .. } => {} + } + match e2 { + Empty2 { .. } => {} + } + match e3 { + Empty3 { .. } => {} + } + match e4 { + E::Empty4 { .. } => {} + _ => {} + } + match e5 { + E::Empty5 { .. } => {} + _ => {} + } + match e6 { + E::Empty6 { .. } => {} + _ => {} + } + match e7 { + Empty7 { .. } => {} + } + + match e2 { + Empty2 => {} + } + match e3 { + Empty3 => {} + } + match e5 { + E::Empty5 => {} + _ => {} + } + match e6 { + E::Empty6() => {} + _ => {} + } + match e6 { + E::Empty6(..) => {} + _ => {} + } + match e7 { + Empty7() => {} + } + match e7 { + Empty7(..) => {} + } + + let e11: Empty1 = Empty1 { ..e1 }; + let e22: Empty2 = Empty2 { ..e2 }; + let e33: Empty3 = Empty3 { ..e3 }; + let e77: Empty7 = Empty7 { ..e7 }; +} + +fn xcrate() { + let e1: XEmpty1 = XEmpty1 {}; + let e2: XEmpty2 = XEmpty2 {}; + let e2: XEmpty2 = XEmpty2; + let e3: XE = XE::XEmpty3 {}; + let e4: XE = XE::XEmpty4 {}; + let e4: XE = XE::XEmpty4; + let e6: XE = XE::XEmpty6 {}; + let e6: XE = XE::XEmpty6(); + let ctor6: fn() -> XE = XE::XEmpty6; + let e7: XEmpty7 = XEmpty7 {}; + let e7: XEmpty7 = XEmpty7(); + let ctor7: fn() -> XEmpty7 = XEmpty7; + + match e1 { + XEmpty1 {} => {} + } + match e2 { + XEmpty2 {} => {} + } + match e3 { + XE::XEmpty3 {} => {} + _ => {} + } + match e4 { + XE::XEmpty4 {} => {} + _ => {} + } + match e6 { + XE::XEmpty6 {} => {} + _ => {} + } + match e7 { + XEmpty7 {} => {} + } + + match e1 { + XEmpty1 { .. } => {} + } + match e2 { + XEmpty2 { .. } => {} + } + match e3 { + XE::XEmpty3 { .. } => {} + _ => {} + } + match e4 { + XE::XEmpty4 { .. } => {} + _ => {} + } + match e6 { + XE::XEmpty6 { .. } => {} + _ => {} + } + match e7 { + XEmpty7 { .. } => {} + } + + match e2 { + XEmpty2 => {} + } + match e4 { + XE::XEmpty4 => {} + _ => {} + } + match e6 { + XE::XEmpty6() => {} + _ => {} + } + match e6 { + XE::XEmpty6(..) => {} + _ => {} + } + match e7 { + XEmpty7() => {} + } + match e7 { + XEmpty7(..) => {} + } + + let e11: XEmpty1 = XEmpty1 { ..e1 }; + let e22: XEmpty2 = XEmpty2 { ..e2 }; + let e77: XEmpty7 = XEmpty7 { ..e7 }; +} + +fn main() { + local(); + xcrate(); +} diff --git a/tests/ui/structs-enums/empty-tag.rs b/tests/ui/structs-enums/empty-tag.rs new file mode 100644 index 000000000..271ab72c7 --- /dev/null +++ b/tests/ui/structs-enums/empty-tag.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_braces)] +#![allow(non_camel_case_types)] + +#[derive(Copy, Clone, Debug)] +enum chan { chan_t, } + +impl PartialEq for chan { + fn eq(&self, other: &chan) -> bool { + ((*self) as usize) == ((*other) as usize) + } + fn ne(&self, other: &chan) -> bool { !(*self).eq(other) } +} + +fn wrapper3(i: chan) { + assert_eq!(i, chan::chan_t); +} + +pub fn main() { + let wrapped = {||wrapper3(chan::chan_t)}; + wrapped(); +} diff --git a/tests/ui/structs-enums/enum-alignment.rs b/tests/ui/structs-enums/enum-alignment.rs new file mode 100644 index 000000000..108dfe2e6 --- /dev/null +++ b/tests/ui/structs-enums/enum-alignment.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +#![allow(deprecated)] + +use std::mem; + +fn addr_of(ptr: &T) -> usize { + ptr as *const T as usize +} + +fn is_aligned(ptr: &T) -> bool { + unsafe { + let addr: usize = mem::transmute(ptr); + (addr % mem::min_align_of::()) == 0 + } +} + +pub fn main() { + let x = Some(0u64); + match x { + None => panic!(), + Some(ref y) => assert!(is_aligned(y)) + } +} diff --git a/tests/ui/structs-enums/enum-clike-ffi-as-int.rs b/tests/ui/structs-enums/enum-clike-ffi-as-int.rs new file mode 100644 index 000000000..e2b2b43de --- /dev/null +++ b/tests/ui/structs-enums/enum-clike-ffi-as-int.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] + +/*! + * C-like enums have to be represented as LLVM ints, not wrapped in a + * struct, because it's important for the FFI that they interoperate + * with C integers/enums, and the ABI can treat structs differently. + * For example, on i686-linux-gnu, a struct return value is passed by + * storing to a hidden out parameter, whereas an integer would be + * returned in a register. + * + * This test just checks that the ABIs for the enum and the plain + * integer are compatible, rather than actually calling C code. + * The unused parameter to `foo` is to increase the likelihood of + * crashing if something goes wrong here. + */ + +#[repr(u32)] +enum Foo { + A = 0, + B = 23 +} + +#[inline(never)] +extern "C" fn foo(_x: usize) -> Foo { Foo::B } + +pub fn main() { + unsafe { + let f: extern "C" fn(usize) -> u32 = + ::std::mem::transmute(foo as extern "C" fn(usize) -> Foo); + assert_eq!(f(0xDEADBEEF), Foo::B as u32); + } +} diff --git a/tests/ui/structs-enums/enum-discr.rs b/tests/ui/structs-enums/enum-discr.rs new file mode 100644 index 000000000..bdd6df82d --- /dev/null +++ b/tests/ui/structs-enums/enum-discr.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +enum Animal { + Cat = 0, + Dog = 1, + Horse = 2, + Snake = 3, +} + +enum Hero { + Batman = -1, + Superman = -2, + Ironman = -3, + Spiderman = -4 +} + +pub fn main() { + let pet: Animal = Animal::Snake; + let hero: Hero = Hero::Superman; + assert_eq!(pet as usize, 3); + assert_eq!(hero as isize, -2); +} diff --git a/tests/ui/structs-enums/enum-discrim-autosizing.rs b/tests/ui/structs-enums/enum-discrim-autosizing.rs new file mode 100644 index 000000000..f68fdda60 --- /dev/null +++ b/tests/ui/structs-enums/enum-discrim-autosizing.rs @@ -0,0 +1,53 @@ +// run-pass +#![allow(dead_code)] +#![allow(overflowing_literals)] + +use std::mem::size_of; + +enum Ei8 { + Ai8 = -1, + Bi8 = 0 +} + +enum Eu8 { + Au8 = 0, + Bu8 = 0x80 +} + +enum Ei16 { + Ai16 = -1, + Bi16 = 0x80 +} + +enum Eu16 { + Au16 = 0, + Bu16 = 0x8000 +} + +enum Ei32 { + Ai32 = -1, + Bi32 = 0x8000 +} + +enum Eu32 { + Au32 = 0, + Bu32 = 0x8000_0000 +} + +enum Ei64 { + Ai64 = -1, + Bi64 = 0x8000_0000 +} + +pub fn main() { + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), 2); + assert_eq!(size_of::(), 2); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + #[cfg(target_pointer_width = "64")] + assert_eq!(size_of::(), 8); + #[cfg(target_pointer_width = "32")] + assert_eq!(size_of::(), 4); +} diff --git a/tests/ui/structs-enums/enum-discrim-manual-sizing.rs b/tests/ui/structs-enums/enum-discrim-manual-sizing.rs new file mode 100644 index 000000000..c8b362c99 --- /dev/null +++ b/tests/ui/structs-enums/enum-discrim-manual-sizing.rs @@ -0,0 +1,111 @@ +// run-pass +#![allow(dead_code)] + +use std::mem::{size_of, align_of}; + +#[repr(i8)] +enum Ei8 { + Ai8 = 0, + Bi8 = 1 +} + +#[repr(u8)] +enum Eu8 { + Au8 = 0, + Bu8 = 1 +} + +#[repr(i16)] +enum Ei16 { + Ai16 = 0, + Bi16 = 1 +} + +#[repr(u16)] +enum Eu16 { + Au16 = 0, + Bu16 = 1 +} + +#[repr(i32)] +enum Ei32 { + Ai32 = 0, + Bi32 = 1 +} + +#[repr(u32)] +enum Eu32 { + Au32 = 0, + Bu32 = 1 +} + +#[repr(i64)] +enum Ei64 { + Ai64 = 0, + Bi64 = 1 +} + +#[repr(u64)] +enum Eu64 { + Au64 = 0, + Bu64 = 1 +} + +#[repr(isize)] +enum Eint { + Aint = 0, + Bint = 1 +} + +#[repr(usize)] +enum Euint { + Auint = 0, + Buint = 1 +} + +#[repr(u8)] +enum Eu8NonCLike { + _None, + _Some(T), +} + +#[repr(i64)] +enum Ei64NonCLike { + _None, + _Some(T), +} + +#[repr(u64)] +enum Eu64NonCLike { + _None, + _Some(T), +} + +pub fn main() { + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), 2); + assert_eq!(size_of::(), 2); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::>(), 1); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>(), 8); + let u8_expected_size = round_up(9, align_of::>()); + assert_eq!(size_of::>(), u8_expected_size); + let array_expected_size = round_up(28, align_of::>()); + assert_eq!(size_of::>(), array_expected_size); + assert_eq!(size_of::>(), 32); + + assert_eq!(align_of::(), align_of::()); + assert_eq!(align_of::>(), align_of::()); +} + +// Rounds x up to the next multiple of a +fn round_up(x: usize, a: usize) -> usize { + ((x + (a - 1)) / a) * a +} diff --git a/tests/ui/structs-enums/enum-discrim-range-overflow.rs b/tests/ui/structs-enums/enum-discrim-range-overflow.rs new file mode 100644 index 000000000..9c4c61e68 --- /dev/null +++ b/tests/ui/structs-enums/enum-discrim-range-overflow.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(overflowing_literals)] + +// pretty-expanded FIXME #23616 + +pub enum E64 { + H64 = 0x7FFF_FFFF_FFFF_FFFF, + L64 = 0x8000_0000_0000_0000 +} +pub enum E32 { + H32 = 0x7FFF_FFFF, + L32 = 0x8000_0000 +} + +pub fn f(e64: E64, e32: E32) -> (bool,bool) { + (match e64 { + E64::H64 => true, + E64::L64 => false + }, + match e32 { + E32::H32 => true, + E32::L32 => false + }) +} + +pub fn main() { } diff --git a/tests/ui/structs-enums/enum-discrim-width-stuff.rs b/tests/ui/structs-enums/enum-discrim-width-stuff.rs new file mode 100644 index 000000000..f278ae2d0 --- /dev/null +++ b/tests/ui/structs-enums/enum-discrim-width-stuff.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(overflowing_literals)] +#![allow(dead_code)] + +macro_rules! check { + ($m:ident, $t:ty, $v:expr) => {{ + mod $m { + use std::mem::size_of; + #[derive(Copy, Clone, Debug)] + enum E { + V = $v, + A = 0 + } + static C: E = E::V; + pub fn check() { + assert_eq!(size_of::(), size_of::<$t>()); + assert_eq!(E::V as $t, $v as $t); + assert_eq!(C as $t, $v as $t); + assert_eq!(format!("{:?}", E::V), "V".to_string()); + assert_eq!(format!("{:?}", C), "V".to_string()); + } + } + $m::check(); + }} +} + +pub fn main() { + check!(a, u8, 0x17); + check!(b, u8, 0xe8); + check!(c, u16, 0x1727); + check!(d, u16, 0xe8d8); + check!(e, u32, 0x17273747); + check!(f, u32, 0xe8d8c8b8); + + check!(z, i8, 0x17); + check!(y, i8, -0x17); + check!(x, i16, 0x1727); + check!(w, i16, -0x1727); + check!(v, i32, 0x17273747); + check!(u, i32, -0x17273747); + + enum Simple { A, B } + assert_eq!(::std::mem::size_of::(), 1); +} diff --git a/tests/ui/structs-enums/enum-disr-val-pretty.rs b/tests/ui/structs-enums/enum-disr-val-pretty.rs new file mode 100644 index 000000000..ef1333e0e --- /dev/null +++ b/tests/ui/structs-enums/enum-disr-val-pretty.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(non_camel_case_types)] +// pp-exact + + +enum color { red = 1, green, blue, imaginary = -1, } + +pub fn main() { + test_color(color::red, 1, "red".to_string()); + test_color(color::green, 2, "green".to_string()); + test_color(color::blue, 3, "blue".to_string()); + test_color(color::imaginary, -1, "imaginary".to_string()); +} + +fn test_color(color: color, val: isize, _name: String) { + assert_eq!(color as isize , val); +} diff --git a/tests/ui/structs-enums/enum-export-inheritance.rs b/tests/ui/structs-enums/enum-export-inheritance.rs new file mode 100644 index 000000000..6a36a004a --- /dev/null +++ b/tests/ui/structs-enums/enum-export-inheritance.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +mod a { + pub enum Foo { + Bar, + Baz, + Boo + } +} + +pub fn main() { + let _x = a::Foo::Bar; +} diff --git a/tests/ui/structs-enums/enum-layout-optimization.rs b/tests/ui/structs-enums/enum-layout-optimization.rs new file mode 100644 index 000000000..05d297906 --- /dev/null +++ b/tests/ui/structs-enums/enum-layout-optimization.rs @@ -0,0 +1,50 @@ +// run-pass +// Test that we will do various size optimizations to enum layout, but +// *not* if `#[repr(u8)]` or `#[repr(C)]` is passed. See also #40029. + +#![allow(dead_code)] + +use std::mem; + +enum Nullable { + Alive(T), + Dropped, +} + +#[repr(u8)] +enum NullableU8 { + Alive(T), + Dropped, +} + +#[repr(C)] +enum NullableC { + Alive(T), + Dropped, +} + +struct StructNewtype(T); + +#[repr(C)] +struct StructNewtypeC(T); + +enum EnumNewtype { Variant(T) } + +#[repr(u8)] +enum EnumNewtypeU8 { Variant(T) } + +#[repr(C)] +enum EnumNewtypeC { Variant(T) } + +fn main() { + assert!(mem::size_of::>() == mem::size_of::>>()); + assert!(mem::size_of::>() < mem::size_of::>>()); + assert!(mem::size_of::>() < mem::size_of::>>()); + + assert!(mem::size_of::() == mem::size_of::>()); + assert!(mem::size_of::() == mem::size_of::>()); + + assert!(mem::size_of::() == mem::size_of::>()); + assert!(mem::size_of::() < mem::size_of::>()); + assert!(mem::size_of::() < mem::size_of::>()); +} diff --git a/tests/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs b/tests/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs new file mode 100644 index 000000000..7d15d607d --- /dev/null +++ b/tests/ui/structs-enums/enum-non-c-like-repr-c-and-int.rs @@ -0,0 +1,173 @@ +// run-pass +// This test deserializes an enum in-place by transmuting to a union that +// should have the same layout, and manipulating the tag and payloads +// independently. This verifies that `repr(some_int)` has a stable representation, +// and that we don't miscompile these kinds of manipulations. + +use std::time::Duration; +use std::mem; + +#[repr(C, u8)] +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum MyEnum { + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offsets of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct +} + +#[repr(C)] +struct MyEnumRepr { + tag: MyEnumTag, + payload: MyEnumPayload, +} + +#[repr(C)] +#[allow(non_snake_case)] +union MyEnumPayload { + A: MyEnumVariantA, + B: MyEnumVariantB, + D: MyEnumVariantD, + E: MyEnumVariantE, +} + +#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); + +fn main() { + let result: Vec> = vec![ + Ok(MyEnum::A(17)), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), + Ok(MyEnum::C), + Err(()), + Ok(MyEnum::D(Some(407))), + Ok(MyEnum::D(None)), + Ok(MyEnum::E(Duration::from_secs(100))), + Err(()), + ]; + + // Binary serialized version of the above (little-endian) + let input: Vec = vec![ + 0, 17, 0, 0, 0, + 1, 206, 121, 4, 78, + 2, + 8, /* invalid tag value */ + 3, 0, 151, 1, 0, 0, + 3, 1, + 4, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* incomplete value */ + ]; + + let mut output = vec![]; + let mut buf = &input[..]; + + unsafe { + // This should be safe, because we don't match on it unless it's fully formed, + // and it doesn't have a destructor. + // + // MyEnum is repr(C, u8) so it is guaranteed to have a separate discriminant and each + // variant can be zero initialized. + let mut dest: MyEnum = mem::zeroed(); + while buf.len() > 0 { + match parse_my_enum(&mut dest, &mut buf) { + Ok(()) => output.push(Ok(dest)), + Err(()) => output.push(Err(())), + } + } + } + + assert_eq!(output, result); +} + +fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { + unsafe { + // Should be correct to do this transmute. + let dest: &'a mut MyEnumRepr = mem::transmute(dest); + let tag = read_u8(buf)?; + + dest.tag = match tag { + 0 => MyEnumTag::A, + 1 => MyEnumTag::B, + 2 => MyEnumTag::C, + 3 => MyEnumTag::D, + 4 => MyEnumTag::E, + _ => return Err(()), + }; + + match dest.tag { + MyEnumTag::A => { + dest.payload.A.0 = read_u32_le(buf)?; + } + MyEnumTag::B => { + dest.payload.B.x = read_u8(buf)?; + dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; + } + MyEnumTag::C => { + /* do nothing */ + } + MyEnumTag::D => { + let is_some = read_u8(buf)? == 0; + if is_some { + dest.payload.D.0 = Some(read_u32_le(buf)?); + } else { + dest.payload.D.0 = None; + } + } + MyEnumTag::E => { + let secs = read_u64_le(buf)?; + let nanos = read_u32_le(buf)?; + dest.payload.E.0 = Duration::new(secs, nanos); + } + } + Ok(()) + } +} + + + +// reader helpers + +fn read_u64_le(buf: &mut &[u8]) -> Result { + if buf.len() < 8 { return Err(()) } + let val = (buf[0] as u64) << 0 + | (buf[1] as u64) << 8 + | (buf[2] as u64) << 16 + | (buf[3] as u64) << 24 + | (buf[4] as u64) << 32 + | (buf[5] as u64) << 40 + | (buf[6] as u64) << 48 + | (buf[7] as u64) << 56; + *buf = &buf[8..]; + Ok(val) +} + +fn read_u32_le(buf: &mut &[u8]) -> Result { + if buf.len() < 4 { return Err(()) } + let val = (buf[0] as u32) << 0 + | (buf[1] as u32) << 8 + | (buf[2] as u32) << 16 + | (buf[3] as u32) << 24; + *buf = &buf[4..]; + Ok(val) +} + +fn read_u16_le(buf: &mut &[u8]) -> Result { + if buf.len() < 2 { return Err(()) } + let val = (buf[0] as u16) << 0 + | (buf[1] as u16) << 8; + *buf = &buf[2..]; + Ok(val) +} + +fn read_u8(buf: &mut &[u8]) -> Result { + if buf.len() < 1 { return Err(()) } + let val = buf[0]; + *buf = &buf[1..]; + Ok(val) +} diff --git a/tests/ui/structs-enums/enum-non-c-like-repr-c.rs b/tests/ui/structs-enums/enum-non-c-like-repr-c.rs new file mode 100644 index 000000000..fc9efdeca --- /dev/null +++ b/tests/ui/structs-enums/enum-non-c-like-repr-c.rs @@ -0,0 +1,174 @@ +// run-pass +// This test deserializes an enum in-place by transmuting to a union that +// should have the same layout, and manipulating the tag and payloads +// independently. This verifies that `repr(some_int)` has a stable representation, +// and that we don't miscompile these kinds of manipulations. + +use std::time::Duration; +use std::mem; + +#[repr(C)] +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum MyEnum { + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct +} + +#[repr(C)] +struct MyEnumRepr { + tag: MyEnumTag, + payload: MyEnumPayload, +} + +#[repr(C)] +#[allow(non_snake_case)] +union MyEnumPayload { + A: MyEnumVariantA, + B: MyEnumVariantB, + D: MyEnumVariantD, + E: MyEnumVariantE, +} + +#[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); + +fn main() { + let result: Vec> = vec![ + Ok(MyEnum::A(17)), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), + Ok(MyEnum::C), + Err(()), + Ok(MyEnum::D(Some(407))), + Ok(MyEnum::D(None)), + Ok(MyEnum::E(Duration::from_secs(100))), + Err(()), + ]; + + // Binary serialized version of the above (little-endian) + let input: Vec = vec![ + 0, 17, 0, 0, 0, + 1, 206, 121, 4, 78, + 2, + 8, /* invalid tag value */ + 3, 0, 151, 1, 0, 0, + 3, 1, + 4, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* incomplete value */ + ]; + + let mut output = vec![]; + let mut buf = &input[..]; + + unsafe { + // This should be safe, because we don't match on it unless it's fully formed, + // and it doesn't have a destructor. + // + // Furthermore, there are no types within MyEnum which cannot be initialized with zero, + // specifically, though padding and such are present, there are no references or similar + // types. + let mut dest: MyEnum = mem::zeroed(); + while buf.len() > 0 { + match parse_my_enum(&mut dest, &mut buf) { + Ok(()) => output.push(Ok(dest)), + Err(()) => output.push(Err(())), + } + } + } + + assert_eq!(output, result); +} + +fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { + unsafe { + // Should be correct to do this transmute. + let dest: &'a mut MyEnumRepr = mem::transmute(dest); + let tag = read_u8(buf)?; + + dest.tag = match tag { + 0 => MyEnumTag::A, + 1 => MyEnumTag::B, + 2 => MyEnumTag::C, + 3 => MyEnumTag::D, + 4 => MyEnumTag::E, + _ => return Err(()), + }; + + match dest.tag { + MyEnumTag::A => { + dest.payload.A.0 = read_u32_le(buf)?; + } + MyEnumTag::B => { + dest.payload.B.x = read_u8(buf)?; + dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; + } + MyEnumTag::C => { + /* do nothing */ + } + MyEnumTag::D => { + let is_some = read_u8(buf)? == 0; + if is_some { + dest.payload.D.0 = Some(read_u32_le(buf)?); + } else { + dest.payload.D.0 = None; + } + } + MyEnumTag::E => { + let secs = read_u64_le(buf)?; + let nanos = read_u32_le(buf)?; + dest.payload.E.0 = Duration::new(secs, nanos); + } + } + Ok(()) + } +} + + + +// reader helpers + +fn read_u64_le(buf: &mut &[u8]) -> Result { + if buf.len() < 8 { return Err(()) } + let val = (buf[0] as u64) << 0 + | (buf[1] as u64) << 8 + | (buf[2] as u64) << 16 + | (buf[3] as u64) << 24 + | (buf[4] as u64) << 32 + | (buf[5] as u64) << 40 + | (buf[6] as u64) << 48 + | (buf[7] as u64) << 56; + *buf = &buf[8..]; + Ok(val) +} + +fn read_u32_le(buf: &mut &[u8]) -> Result { + if buf.len() < 4 { return Err(()) } + let val = (buf[0] as u32) << 0 + | (buf[1] as u32) << 8 + | (buf[2] as u32) << 16 + | (buf[3] as u32) << 24; + *buf = &buf[4..]; + Ok(val) +} + +fn read_u16_le(buf: &mut &[u8]) -> Result { + if buf.len() < 2 { return Err(()) } + let val = (buf[0] as u16) << 0 + | (buf[1] as u16) << 8; + *buf = &buf[2..]; + Ok(val) +} + +fn read_u8(buf: &mut &[u8]) -> Result { + if buf.len() < 1 { return Err(()) } + let val = buf[0]; + *buf = &buf[1..]; + Ok(val) +} diff --git a/tests/ui/structs-enums/enum-non-c-like-repr-int.rs b/tests/ui/structs-enums/enum-non-c-like-repr-int.rs new file mode 100644 index 000000000..f9e96c1a0 --- /dev/null +++ b/tests/ui/structs-enums/enum-non-c-like-repr-int.rs @@ -0,0 +1,169 @@ +// run-pass +// This test deserializes an enum in-place by transmuting to a union that +// should have the same layout, and manipulating the tag and payloads +// independently. This verifies that `repr(some_int)` has a stable representation, +// and that we don't miscompile these kinds of manipulations. + +use std::time::Duration; +use std::mem; + +#[repr(u8)] +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum MyEnum { + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct +} + +#[allow(non_snake_case)] +#[repr(C)] +union MyEnumRepr { + A: MyEnumVariantA, + B: MyEnumVariantB, + C: MyEnumVariantC, + D: MyEnumVariantD, + E: MyEnumVariantE, +} + +#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option); +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration); + +fn main() { + let result: Vec> = vec![ + Ok(MyEnum::A(17)), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), + Ok(MyEnum::C), + Err(()), + Ok(MyEnum::D(Some(407))), + Ok(MyEnum::D(None)), + Ok(MyEnum::E(Duration::from_secs(100))), + Err(()), + ]; + + // Binary serialized version of the above (little-endian) + let input: Vec = vec![ + 0, 17, 0, 0, 0, + 1, 206, 121, 4, 78, + 2, + 8, /* invalid tag value */ + 3, 0, 151, 1, 0, 0, + 3, 1, + 4, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* incomplete value */ + ]; + + let mut output = vec![]; + let mut buf = &input[..]; + + unsafe { + // This should be safe, because we don't match on it unless it's fully formed, + // and it doesn't have a destructor. + // + // MyEnum is repr(u8) so it is guaranteed to have a separate discriminant and each variant + // can be zero initialized. + let mut dest: MyEnum = mem::zeroed(); + while buf.len() > 0 { + match parse_my_enum(&mut dest, &mut buf) { + Ok(()) => output.push(Ok(dest)), + Err(()) => output.push(Err(())), + } + } + } + + assert_eq!(output, result); +} + +fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { + unsafe { + // Should be correct to do this transmute. + let dest: &'a mut MyEnumRepr = mem::transmute(dest); + let tag = read_u8(buf)?; + + dest.A.0 = match tag { + 0 => MyEnumTag::A, + 1 => MyEnumTag::B, + 2 => MyEnumTag::C, + 3 => MyEnumTag::D, + 4 => MyEnumTag::E, + _ => return Err(()), + }; + + match dest.B.tag { + MyEnumTag::A => { + dest.A.1 = read_u32_le(buf)?; + } + MyEnumTag::B => { + dest.B.x = read_u8(buf)?; + dest.B.y = read_u16_le(buf)? as i16; + dest.B.z = read_u8(buf)?; + } + MyEnumTag::C => { + /* do nothing */ + } + MyEnumTag::D => { + let is_some = read_u8(buf)? == 0; + if is_some { + dest.D.1 = Some(read_u32_le(buf)?); + } else { + dest.D.1 = None; + } + } + MyEnumTag::E => { + let secs = read_u64_le(buf)?; + let nanos = read_u32_le(buf)?; + dest.E.1 = Duration::new(secs, nanos); + } + } + Ok(()) + } +} + + + +// reader helpers + +fn read_u64_le(buf: &mut &[u8]) -> Result { + if buf.len() < 8 { return Err(()) } + let val = (buf[0] as u64) << 0 + | (buf[1] as u64) << 8 + | (buf[2] as u64) << 16 + | (buf[3] as u64) << 24 + | (buf[4] as u64) << 32 + | (buf[5] as u64) << 40 + | (buf[6] as u64) << 48 + | (buf[7] as u64) << 56; + *buf = &buf[8..]; + Ok(val) +} + +fn read_u32_le(buf: &mut &[u8]) -> Result { + if buf.len() < 4 { return Err(()) } + let val = (buf[0] as u32) << 0 + | (buf[1] as u32) << 8 + | (buf[2] as u32) << 16 + | (buf[3] as u32) << 24; + *buf = &buf[4..]; + Ok(val) +} + +fn read_u16_le(buf: &mut &[u8]) -> Result { + if buf.len() < 2 { return Err(()) } + let val = (buf[0] as u16) << 0 + | (buf[1] as u16) << 8; + *buf = &buf[2..]; + Ok(val) +} + +fn read_u8(buf: &mut &[u8]) -> Result { + if buf.len() < 1 { return Err(()) } + let val = buf[0]; + *buf = &buf[1..]; + Ok(val) +} diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.rs b/tests/ui/structs-enums/enum-null-pointer-opt.rs new file mode 100644 index 000000000..85fa1eac2 --- /dev/null +++ b/tests/ui/structs-enums/enum-null-pointer-opt.rs @@ -0,0 +1,74 @@ +// run-pass +#![feature(transparent_unions)] + +use std::mem::size_of; +use std::num::NonZeroUsize; +use std::ptr::NonNull; +use std::rc::Rc; +use std::sync::Arc; + +trait Trait { fn dummy(&self) { } } +trait Mirror { type Image; } +impl Mirror for T { type Image = T; } +struct ParamTypeStruct(#[allow(unused_tuple_struct_fields)] T); +struct AssocTypeStruct(#[allow(unused_tuple_struct_fields)] ::Image); +#[repr(transparent)] +union MaybeUninitUnion { + _value: T, + _uninit: (), +} + +fn main() { + // Functions + assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::(), size_of::>()); + + // Slices - &str / &[T] / &mut [T] + assert_eq!(size_of::<&str>(), size_of::>()); + assert_eq!(size_of::<&[isize]>(), size_of::>()); + assert_eq!(size_of::<&mut [isize]>(), size_of::>()); + + // Traits - Box / &Trait / &mut Trait + assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::<&dyn Trait>(), size_of::>()); + assert_eq!(size_of::<&mut dyn Trait>(), size_of::>()); + + // Pointers - Box + assert_eq!(size_of::>(), size_of::>>()); + + // The optimization can't apply to raw pointers or unions with a ZST field. + assert!(size_of::>() != size_of::<*const isize>()); + assert!(Some(std::ptr::null::()).is_some()); // Can't collapse None to null + assert_ne!(size_of::(), size_of::>>()); + assert_ne!(size_of::<&str>(), size_of::>>()); + assert_ne!(size_of::>(), size_of::>>>()); + + struct Foo { + _a: Box + } + struct Bar(#[allow(unused_tuple_struct_fields)] Box); + + // Should apply through structs + assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::(), size_of::>()); + // and tuples + assert_eq!(size_of::<(u8, Box)>(), size_of::)>>()); + // and fixed-size arrays + assert_eq!(size_of::<[Box; 1]>(), size_of::; 1]>>()); + + // Should apply to NonZero + assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::>(), size_of::>>()); + + // Should apply to types that use NonZero internally + assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); + assert_eq!(size_of::>(), size_of::>>()); + + // Should apply to types that have NonZero transitively + assert_eq!(size_of::(), size_of::>()); + + // Should apply to types where the pointer is substituted + assert_eq!(size_of::<&u8>(), size_of::>>()); + assert_eq!(size_of::<&u8>(), size_of::>>()); +} diff --git a/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs b/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs new file mode 100644 index 000000000..ae267e798 --- /dev/null +++ b/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::result::Result; +use std::result::Result::Ok; + +static C: Result<(), Box> = Ok(()); + +// This is because of yet another bad assertion (ICE) about the null side of a nullable enum. +// So we won't actually compile if the bug is present, but we check the value in main anyway. + +pub fn main() { + assert!(C.is_ok()); +} diff --git a/tests/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs b/tests/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs new file mode 100644 index 000000000..a05cf8b93 --- /dev/null +++ b/tests/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs @@ -0,0 +1,16 @@ +// run-pass + +/*! + * This is a regression test for a bug in LLVM, fixed in upstream r179587, + * where the switch instructions generated for destructuring enums + * represented with nullable pointers could be misoptimized in some cases. + */ + +enum List { Nil, Cons(X, #[allow(unused_tuple_struct_fields)] Box>) } +pub fn main() { + match List::Cons(10, Box::new(List::Nil)) { + List::Cons(10, _) => {} + List::Nil => {} + _ => panic!() + } +} diff --git a/tests/ui/structs-enums/enum-univariant-repr.rs b/tests/ui/structs-enums/enum-univariant-repr.rs new file mode 100644 index 000000000..1e0f67887 --- /dev/null +++ b/tests/ui/structs-enums/enum-univariant-repr.rs @@ -0,0 +1,51 @@ +// run-pass + +use std::mem; + +// Univariant C-like enum +#[repr(i32)] +enum Univariant { + X = 17 +} + +#[repr(u16)] +enum UnivariantWithoutDescr { + Y +} + +#[repr(u8)] +enum UnivariantWithData { + Z(u8), +} + +pub fn main() { + { + assert_eq!(4, mem::size_of::()); + assert_eq!(17, Univariant::X as i32); + + let enums: &[Univariant] = + &[Univariant::X, Univariant::X, Univariant::X]; + let ints: &[i32] = unsafe { mem::transmute(enums) }; + // check it has the same memory layout as i32 + assert_eq!(&[17, 17, 17], ints); + } + + { + assert_eq!(2, mem::size_of::()); + let descr = UnivariantWithoutDescr::Y as u16; + + let enums: &[UnivariantWithoutDescr] = + &[UnivariantWithoutDescr::Y, UnivariantWithoutDescr::Y, UnivariantWithoutDescr::Y]; + let ints: &[u16] = unsafe { mem::transmute(enums) }; + // check it has the same memory layout as u16 + assert_eq!(&[descr, descr, descr], ints); + } + + { + assert_eq!(2, mem::size_of::()); + + match UnivariantWithData::Z(4) { + UnivariantWithData::Z(x) => assert_eq!(x, 4), + } + } +} diff --git a/tests/ui/structs-enums/enum-variants.rs b/tests/ui/structs-enums/enum-variants.rs new file mode 100644 index 000000000..9ac5aae72 --- /dev/null +++ b/tests/ui/structs-enums/enum-variants.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +enum Animal { + Dog (String, f64), + Cat { name: String, weight: f64 } +} + +pub fn main() { + let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); + a = Animal::Cat{ name: "Spotty".to_string(), weight: 2.7 }; + // permuting the fields should work too + let _c = Animal::Cat { weight: 3.1, name: "Spreckles".to_string() }; +} diff --git a/tests/ui/structs-enums/enum-vec-initializer.rs b/tests/ui/structs-enums/enum-vec-initializer.rs new file mode 100644 index 000000000..42ee8ba97 --- /dev/null +++ b/tests/ui/structs-enums/enum-vec-initializer.rs @@ -0,0 +1,17 @@ +// run-pass +// pretty-expanded FIXME #23616 + +enum Flopsy { + Bunny = 2 +} + +const BAR:usize = Flopsy::Bunny as usize; +const BAR2:usize = BAR; + +pub fn main() { + let _v = [0; Flopsy::Bunny as usize]; + let _v = [0; BAR]; + let _v = [0; BAR2]; + const BAR3:usize = BAR2; + let _v = [0; BAR3]; +} diff --git a/tests/ui/structs-enums/export-abstract-tag.rs b/tests/ui/structs-enums/export-abstract-tag.rs new file mode 100644 index 000000000..76ac73321 --- /dev/null +++ b/tests/ui/structs-enums/export-abstract-tag.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(non_camel_case_types)] + +// We can export tags without exporting the variants to create a simple +// sort of ADT. + +// pretty-expanded FIXME #23616 + +mod foo { + pub enum t { t1, } + + pub fn f() -> t { return t::t1; } +} + +pub fn main() { let _v: foo::t = foo::f(); } diff --git a/tests/ui/structs-enums/export-tag-variant.rs b/tests/ui/structs-enums/export-tag-variant.rs new file mode 100644 index 000000000..52e0aba09 --- /dev/null +++ b/tests/ui/structs-enums/export-tag-variant.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(non_camel_case_types)] +// pretty-expanded FIXME #23616 + +mod foo { + pub enum t { t1, } +} + +pub fn main() { let _v = foo::t::t1; } diff --git a/tests/ui/structs-enums/expr-if-struct.rs b/tests/ui/structs-enums/expr-if-struct.rs new file mode 100644 index 000000000..e62d47c6f --- /dev/null +++ b/tests/ui/structs-enums/expr-if-struct.rs @@ -0,0 +1,32 @@ +// run-pass +#![allow(non_camel_case_types)] + + + + +// Tests for if as expressions returning nominal types + +#[derive(Copy, Clone)] +struct I { i: isize } + +fn test_rec() { + let rs = if true { I {i: 100} } else { I {i: 101} }; + assert_eq!(rs.i, 100); +} + +#[derive(Copy, Clone, Debug)] +enum mood { happy, sad, } + +impl PartialEq for mood { + fn eq(&self, other: &mood) -> bool { + ((*self) as usize) == ((*other) as usize) + } + fn ne(&self, other: &mood) -> bool { !(*self).eq(other) } +} + +fn test_tag() { + let rs = if true { mood::happy } else { mood::sad }; + assert_eq!(rs, mood::happy); +} + +pub fn main() { test_rec(); test_tag(); } diff --git a/tests/ui/structs-enums/expr-match-struct.rs b/tests/ui/structs-enums/expr-match-struct.rs new file mode 100644 index 000000000..f0e8d8972 --- /dev/null +++ b/tests/ui/structs-enums/expr-match-struct.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(non_camel_case_types)] + + + + +// Tests for match as expressions resulting in struct types +#[derive(Copy, Clone)] +struct R { i: isize } + +fn test_rec() { + let rs = match true { true => R {i: 100}, _ => panic!() }; + assert_eq!(rs.i, 100); +} + +#[derive(Copy, Clone, Debug)] +enum mood { happy, sad, } + +impl PartialEq for mood { + fn eq(&self, other: &mood) -> bool { + ((*self) as usize) == ((*other) as usize) + } + fn ne(&self, other: &mood) -> bool { !(*self).eq(other) } +} + +fn test_tag() { + let rs = match true { true => { mood::happy } false => { mood::sad } }; + assert_eq!(rs, mood::happy); +} + +pub fn main() { test_rec(); test_tag(); } diff --git a/tests/ui/structs-enums/field-destruction-order.rs b/tests/ui/structs-enums/field-destruction-order.rs new file mode 100644 index 000000000..a75a742d9 --- /dev/null +++ b/tests/ui/structs-enums/field-destruction-order.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_upper_case_globals)] + +// In theory, it doesn't matter what order destructors are run in for rust +// because we have explicit ownership of values meaning that there's no need to +// run one before another. With unsafe code, however, there may be a safe +// interface which relies on fields having their destructors run in a particular +// order. At the time of this writing, std::rt::sched::Scheduler is an example +// of a structure which contains unsafe handles to FFI-like types, and the +// destruction order of the fields matters in the sense that some handles need +// to get destroyed before others. +// +// In C++, destruction order happens bottom-to-top in order of field +// declarations, but we currently run them top-to-bottom. I don't think the +// order really matters that much as long as we define what it is. + + +struct A; +struct B; +struct C { + a: A, + b: B, +} + +static mut hit: bool = false; + +impl Drop for A { + fn drop(&mut self) { + unsafe { + assert!(!hit); + hit = true; + } + } +} + +impl Drop for B { + fn drop(&mut self) { + unsafe { + assert!(hit); + } + } +} + +pub fn main() { + let _c = C { a: A, b: B }; +} diff --git a/tests/ui/structs-enums/foreign-struct.rs b/tests/ui/structs-enums/foreign-struct.rs new file mode 100644 index 000000000..00a23b354 --- /dev/null +++ b/tests/ui/structs-enums/foreign-struct.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// Passing enums by value + +// pretty-expanded FIXME #23616 + +pub enum void {} + +mod bindgen { + use super::void; + + extern "C" { + pub fn printf(v: void); + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/functional-struct-upd.rs b/tests/ui/structs-enums/functional-struct-upd.rs new file mode 100644 index 000000000..68ff73a08 --- /dev/null +++ b/tests/ui/structs-enums/functional-struct-upd.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] + +#[derive(Debug)] +struct Foo { + x: isize, + y: isize +} + +pub fn main() { + let a = Foo { x: 1, y: 2 }; + let c = Foo { x: 4, .. a}; + println!("{:?}", c); +} diff --git a/tests/ui/structs-enums/issue-1701.rs b/tests/ui/structs-enums/issue-1701.rs new file mode 100644 index 000000000..bae32a777 --- /dev/null +++ b/tests/ui/structs-enums/issue-1701.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +enum pattern { tabby, tortoiseshell, calico } +enum breed { beagle, rottweiler, pug } +type name = String; +enum ear_kind { lop, upright } +enum animal { cat(pattern), dog(breed), rabbit(name, ear_kind), tiger } + +fn noise(a: animal) -> Option { + match a { + animal::cat(..) => { Some("meow".to_string()) } + animal::dog(..) => { Some("woof".to_string()) } + animal::rabbit(..) => { None } + animal::tiger => { Some("roar".to_string()) } + } +} + +pub fn main() { + assert_eq!(noise(animal::cat(pattern::tabby)), Some("meow".to_string())); + assert_eq!(noise(animal::dog(breed::pug)), Some("woof".to_string())); + assert_eq!(noise(animal::rabbit("Hilbert".to_string(), ear_kind::upright)), None); + assert_eq!(noise(animal::tiger), Some("roar".to_string())); +} diff --git a/tests/ui/structs-enums/issue-2718-a.rs b/tests/ui/structs-enums/issue-2718-a.rs new file mode 100644 index 000000000..6c4915845 --- /dev/null +++ b/tests/ui/structs-enums/issue-2718-a.rs @@ -0,0 +1,12 @@ +pub struct SendPacket { + p: T +} + +mod pingpong { + use SendPacket; + pub type Ping = SendPacket; + pub struct Pong(SendPacket); + //~^ ERROR recursive type `Pong` has infinite size +} + +fn main() {} diff --git a/tests/ui/structs-enums/issue-2718-a.stderr b/tests/ui/structs-enums/issue-2718-a.stderr new file mode 100644 index 000000000..7ea620f38 --- /dev/null +++ b/tests/ui/structs-enums/issue-2718-a.stderr @@ -0,0 +1,14 @@ +error[E0072]: recursive type `Pong` has infinite size + --> $DIR/issue-2718-a.rs:8:5 + | +LL | pub struct Pong(SendPacket); + | ^^^^^^^^^^^^^^^ ---------------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | pub struct Pong(Box>); + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/issue-38002.rs b/tests/ui/structs-enums/issue-38002.rs new file mode 100644 index 000000000..fdb31fc44 --- /dev/null +++ b/tests/ui/structs-enums/issue-38002.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +// Check that constant ADTs are codegened OK, part k of N. + +enum Bar { + C +} + +enum Foo { + A {}, + B { + y: usize, + z: Bar + }, +} + +const LIST: [(usize, Foo); 2] = [ + (51, Foo::B { y: 42, z: Bar::C }), + (52, Foo::B { y: 45, z: Bar::C }), +]; + +pub fn main() { + match LIST { + [ + (51, Foo::B { y: 42, z: Bar::C }), + (52, Foo::B { y: 45, z: Bar::C }) + ] => {} + _ => { + // I would want to print the enum here, but if + // the discriminant is garbage this causes an + // `unreachable` and silent process exit. + panic!("trivial match failed") + } + } +} diff --git a/tests/ui/structs-enums/issue-50731.rs b/tests/ui/structs-enums/issue-50731.rs new file mode 100644 index 000000000..209c1e127 --- /dev/null +++ b/tests/ui/structs-enums/issue-50731.rs @@ -0,0 +1,6 @@ +// run-pass +enum Void {} +fn foo(_: Result<(Void, u32), (Void, String)>) {} +fn main() { + let _: fn(_) = foo; +} diff --git a/tests/ui/structs-enums/ivec-tag.rs b/tests/ui/structs-enums/ivec-tag.rs new file mode 100644 index 000000000..c39368a2b --- /dev/null +++ b/tests/ui/structs-enums/ivec-tag.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +fn producer(tx: &Sender>) { + tx.send( + vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13]).unwrap(); +} + +pub fn main() { + let (tx, rx) = channel::>(); + let prod = thread::spawn(move|| { + producer(&tx) + }); + + let _data: Vec = rx.recv().unwrap(); + prod.join(); +} diff --git a/tests/ui/structs-enums/module-qualified-struct-destructure.rs b/tests/ui/structs-enums/module-qualified-struct-destructure.rs new file mode 100644 index 000000000..57be37cdf --- /dev/null +++ b/tests/ui/structs-enums/module-qualified-struct-destructure.rs @@ -0,0 +1,14 @@ +// run-pass +// pretty-expanded FIXME #23616 + +mod m { + pub struct S { + pub x: isize, + pub y: isize + } +} + +pub fn main() { + let x = m::S { x: 1, y: 2 }; + let m::S { x: _a, y: _b } = x; +} diff --git a/tests/ui/structs-enums/multiple-reprs.rs b/tests/ui/structs-enums/multiple-reprs.rs new file mode 100644 index 000000000..4be503a0e --- /dev/null +++ b/tests/ui/structs-enums/multiple-reprs.rs @@ -0,0 +1,82 @@ +// run-pass + +#![allow(dead_code)] + +use std::mem::{size_of, align_of}; +use std::os::raw::c_int; + +// The two enums that follow are designed so that bugs trigger layout optimization. +// Specifically, if either of the following reprs used here is not detected by the compiler, +// then the sizes will be wrong. + +#[repr(C, u8)] +enum E1 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +#[repr(u8, C)] +enum E2 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +// Check that repr(int) and repr(C) are in fact different from the above + +#[repr(u8)] +enum E3 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +#[repr(u16)] +enum E4 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +#[repr(u32)] +enum E5 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +#[repr(u64)] +enum E6 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +#[repr(C)] +enum E7 { + A(u8, u16, u8), + B(u8, u16, u8) +} + +// From pr 37429 + +#[repr(C,packed)] +pub struct p0f_api_query { + pub magic: u32, + pub addr_type: u8, + pub addr: [u8; 16], +} + +pub fn main() { + assert_eq!(size_of::(), 8); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::(), 6); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::(), align_size(10, align_of::())); + assert_eq!(size_of::(), align_size(14, align_of::())); + assert_eq!(size_of::(), align_size(6 + size_of::(), align_of::())); + assert_eq!(size_of::(), 21); +} + +fn align_size(size: usize, align: usize) -> usize { + if size % align != 0 { + size + (align - (size % align)) + } else { + size + } +} diff --git a/tests/ui/structs-enums/namespaced-enum-emulate-flat-xc.rs b/tests/ui/structs-enums/namespaced-enum-emulate-flat-xc.rs new file mode 100644 index 000000000..30cf64582 --- /dev/null +++ b/tests/ui/structs-enums/namespaced-enum-emulate-flat-xc.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(non_camel_case_types)] + +// aux-build:namespaced_enum_emulate_flat.rs + +// pretty-expanded FIXME #23616 + +extern crate namespaced_enum_emulate_flat; + +use namespaced_enum_emulate_flat::{Foo, A, B, C}; +use namespaced_enum_emulate_flat::nest::{Bar, D, E, F}; + +fn _f(f: Foo) { + match f { + A | B(_) | C { .. } => {} + } +} + +fn _f2(f: Bar) { + match f { + D | E(_) | F { .. } => {} + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs b/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs new file mode 100644 index 000000000..f6c395059 --- /dev/null +++ b/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub use Foo::*; +use nest::{Bar, D, E, F}; + +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} +} + +fn _f(f: Foo) { + match f { + A | B(_) | C { .. } => {} + } +} + +mod nest { + pub use self::Bar::*; + + pub enum Bar { + D, + E(isize), + F { a: isize }, + } + + impl Bar { + pub fn foo() {} + } +} + +fn _f2(f: Bar) { + match f { + D | E(_) | F { .. } => {} + } +} + +fn main() {} diff --git a/tests/ui/structs-enums/namespaced-enum-glob-import-xcrate.rs b/tests/ui/structs-enums/namespaced-enum-glob-import-xcrate.rs new file mode 100644 index 000000000..d2ccadea0 --- /dev/null +++ b/tests/ui/structs-enums/namespaced-enum-glob-import-xcrate.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:namespaced_enums.rs + +// pretty-expanded FIXME #23616 + +extern crate namespaced_enums; + +fn _f(f: namespaced_enums::Foo) { + use namespaced_enums::Foo::*; + + match f { + A | B(_) | C { .. } => {} + } +} + +mod m { + pub use namespaced_enums::Foo::*; +} + +fn _f2(f: namespaced_enums::Foo) { + match f { + m::A | m::B(_) | m::C { .. } => {} + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/namespaced-enum-glob-import.rs b/tests/ui/structs-enums/namespaced-enum-glob-import.rs new file mode 100644 index 000000000..f36ac69dc --- /dev/null +++ b/tests/ui/structs-enums/namespaced-enum-glob-import.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +mod m2 { + pub enum Foo { + A, + B(isize), + C { a: isize }, + } + + impl Foo { + pub fn foo() {} + } +} + +mod m { + pub use m2::Foo::*; +} + +fn _f(f: m2::Foo) { + use m2::Foo::*; + + match f { + A | B(_) | C { .. } => {} + } +} + +fn _f2(f: m2::Foo) { + match f { + m::A | m::B(_) | m::C { .. } => {} + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/namespaced-enums-xcrate.rs b/tests/ui/structs-enums/namespaced-enums-xcrate.rs new file mode 100644 index 000000000..5e10c3ec1 --- /dev/null +++ b/tests/ui/structs-enums/namespaced-enums-xcrate.rs @@ -0,0 +1,16 @@ +// run-pass +// aux-build:namespaced_enums.rs + +// pretty-expanded FIXME #23616 + +extern crate namespaced_enums; + +use namespaced_enums::Foo; + +fn _foo (f: Foo) { + match f { + Foo::A | Foo::B(_) | Foo::C { .. } => {} + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/namespaced-enums.rs b/tests/ui/structs-enums/namespaced-enums.rs new file mode 100644 index 000000000..6a2602501 --- /dev/null +++ b/tests/ui/structs-enums/namespaced-enums.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +enum Foo { + A, + B(isize), + C { a: isize }, +} + +fn _foo (f: Foo) { + match f { + Foo::A | Foo::B(_) | Foo::C { .. } => {} + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/nested-enum-same-names.rs b/tests/ui/structs-enums/nested-enum-same-names.rs new file mode 100644 index 000000000..111b9ba94 --- /dev/null +++ b/tests/ui/structs-enums/nested-enum-same-names.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +/* + +#7770 ICE with sibling methods containing same-name-enum containing + same-name-member + +If you have two methods in an impl block, each containing an enum +(with the same name), each containing at least one value with the same +name, rustc gives the same LLVM symbol for the two of them and fails, +as it does not include the method name in the symbol name. + +*/ + +pub struct Foo; +impl Foo { + pub fn foo() { + enum Panic { Common } + } + pub fn bar() { + enum Panic { Common } + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/newtype-struct-drop-run.rs b/tests/ui/structs-enums/newtype-struct-drop-run.rs new file mode 100644 index 000000000..0754f3187 --- /dev/null +++ b/tests/ui/structs-enums/newtype-struct-drop-run.rs @@ -0,0 +1,21 @@ +// run-pass +// Make sure the destructor is run for newtype structs. + +use std::cell::Cell; + +struct Foo<'a>(&'a Cell); + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + let Foo(i) = *self; + i.set(23); + } +} + +pub fn main() { + let y = &Cell::new(32); + { + let _x = Foo(y); + } + assert_eq!(y.get(), 23); +} diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs new file mode 100644 index 000000000..f73b492df --- /dev/null +++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_unsafe)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +pub struct Fd(u32); + +fn foo(a: u32) {} + +impl Drop for Fd { + fn drop(&mut self) { + unsafe { + let Fd(s) = *self; + foo(s); + } + } +} + +pub fn main() { +} diff --git a/tests/ui/structs-enums/newtype-struct-xc-2.rs b/tests/ui/structs-enums/newtype-struct-xc-2.rs new file mode 100644 index 000000000..40837321b --- /dev/null +++ b/tests/ui/structs-enums/newtype-struct-xc-2.rs @@ -0,0 +1,15 @@ +// run-pass +// aux-build:newtype_struct_xc.rs + +// pretty-expanded FIXME #23616 + +extern crate newtype_struct_xc; +use newtype_struct_xc::Au; + +fn f() -> Au { + Au(2) +} + +pub fn main() { + let _ = f(); +} diff --git a/tests/ui/structs-enums/newtype-struct-xc.rs b/tests/ui/structs-enums/newtype-struct-xc.rs new file mode 100644 index 000000000..0c6466d97 --- /dev/null +++ b/tests/ui/structs-enums/newtype-struct-xc.rs @@ -0,0 +1,10 @@ +// run-pass +// aux-build:newtype_struct_xc.rs + +// pretty-expanded FIXME #23616 + +extern crate newtype_struct_xc; + +pub fn main() { + let _ = newtype_struct_xc::Au(2); +} diff --git a/tests/ui/structs-enums/nonzero-enum.rs b/tests/ui/structs-enums/nonzero-enum.rs new file mode 100644 index 000000000..15b571be5 --- /dev/null +++ b/tests/ui/structs-enums/nonzero-enum.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +use std::mem::size_of; + +enum E { + A = 1, + B = 2, + C = 3, +} + +struct S { + a: u16, + b: u8, + e: E, +} + +fn main() { + assert_eq!(size_of::(), 1); + assert_eq!(size_of::>(), 1); + assert_eq!(size_of::>(), 1); + assert_eq!(size_of::>(), size_of::()); + let enone = None::; + let esome = Some(E::A); + if let Some(..) = enone { + panic!(); + } + if let None = esome { + panic!(); + } +} diff --git a/tests/ui/structs-enums/numeric-fields.rs b/tests/ui/structs-enums/numeric-fields.rs new file mode 100644 index 000000000..6ff3afc38 --- /dev/null +++ b/tests/ui/structs-enums/numeric-fields.rs @@ -0,0 +1,12 @@ +// run-pass +struct S(u8, u16); + +fn main() { + let s = S{1: 10, 0: 11}; + match s { + S{0: a, 1: b, ..} => { + assert_eq!(a, 11); + assert_eq!(b, 10); + } + } +} diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs new file mode 100644 index 000000000..ee704198d --- /dev/null +++ b/tests/ui/structs-enums/rec-align-u32.rs @@ -0,0 +1,57 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_unsafe)] +// Issue #2303 + +#![feature(intrinsics)] + +use std::mem; + +mod rusti { + extern "rust-intrinsic" { + pub fn pref_align_of() -> usize; + #[rustc_safe_intrinsic] + pub fn min_align_of() -> usize; + } +} + +// This is the type with the questionable alignment +#[derive(Debug)] +struct Inner { + c64: u32 +} + +// This is the type that contains the type with the +// questionable alignment, for testing +#[derive(Debug)] +struct Outer { + c8: u8, + t: Inner +} + +mod m { + pub fn align() -> usize { 4 } + pub fn size() -> usize { 8 } +} + +pub fn main() { + unsafe { + let x = Outer {c8: 22, t: Inner {c64: 44}}; + + // Send it through the shape code + let y = format!("{:?}", x); + + println!("align inner = {:?}", rusti::min_align_of::()); + println!("size outer = {:?}", mem::size_of::()); + println!("y = {:?}", y); + + // per clang/gcc the alignment of `inner` is 4 on x86. + assert_eq!(rusti::min_align_of::(), m::align()); + + // per clang/gcc the size of `outer` should be 12 + // because `inner`s alignment was 4. + assert_eq!(mem::size_of::(), m::size()); + + assert_eq!(y, "Outer { c8: 22, t: Inner { c64: 44 } }".to_string()); + } +} diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs new file mode 100644 index 000000000..40ede9705 --- /dev/null +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -0,0 +1,97 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_unsafe)] +// ignore-wasm32-bare seems unimportant to test + +// Issue #2303 + +#![feature(intrinsics)] + +use std::mem; + +mod rusti { + extern "rust-intrinsic" { + pub fn pref_align_of() -> usize; + #[rustc_safe_intrinsic] + pub fn min_align_of() -> usize; + } +} + +// This is the type with the questionable alignment +#[derive(Debug)] +struct Inner { + c64: u64 +} + +// This is the type that contains the type with the +// questionable alignment, for testing +#[derive(Debug)] +struct Outer { + c8: u8, + t: Inner +} + + +#[cfg(any(target_os = "android", + target_os = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "illumos", + target_os = "linux", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "vxworks"))] +mod m { + #[cfg(target_arch = "x86")] + pub mod m { + pub fn align() -> usize { 4 } + pub fn size() -> usize { 12 } + } + + #[cfg(not(target_arch = "x86"))] + pub mod m { + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } + } +} + +#[cfg(target_env = "sgx")] +mod m { + #[cfg(target_arch = "x86_64")] + pub mod m { + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } + } +} + +#[cfg(target_os = "windows")] +mod m { + pub mod m { + pub fn align() -> usize { 8 } + pub fn size() -> usize { 16 } + } +} + +pub fn main() { + unsafe { + let x = Outer {c8: 22, t: Inner {c64: 44}}; + + let y = format!("{:?}", x); + + println!("align inner = {:?}", rusti::min_align_of::()); + println!("size outer = {:?}", mem::size_of::()); + println!("y = {:?}", y); + + // per clang/gcc the alignment of `Inner` is 4 on x86. + assert_eq!(rusti::min_align_of::(), m::m::align()); + + // per clang/gcc the size of `Outer` should be 12 + // because `Inner`s alignment was 4. + assert_eq!(mem::size_of::(), m::m::size()); + + assert_eq!(y, "Outer { c8: 22, t: Inner { c64: 44 } }".to_string()); + } +} diff --git a/tests/ui/structs-enums/rec-auto.rs b/tests/ui/structs-enums/rec-auto.rs new file mode 100644 index 000000000..c2ef13ede --- /dev/null +++ b/tests/ui/structs-enums/rec-auto.rs @@ -0,0 +1,14 @@ +// run-pass + + + + +// Issue #50. + +struct X { foo: String, bar: String } + +pub fn main() { + let x = X {foo: "hello".to_string(), bar: "world".to_string()}; + println!("{}", x.foo.clone()); + println!("{}", x.bar.clone()); +} diff --git a/tests/ui/structs-enums/rec-extend.rs b/tests/ui/structs-enums/rec-extend.rs new file mode 100644 index 000000000..4c91cd185 --- /dev/null +++ b/tests/ui/structs-enums/rec-extend.rs @@ -0,0 +1,18 @@ +// run-pass + + + + +struct Point {x: isize, y: isize} + +pub fn main() { + let origin: Point = Point {x: 0, y: 0}; + let right: Point = Point {x: origin.x + 10,.. origin}; + let up: Point = Point {y: origin.y + 10,.. origin}; + assert_eq!(origin.x, 0); + assert_eq!(origin.y, 0); + assert_eq!(right.x, 10); + assert_eq!(right.y, 0); + assert_eq!(up.x, 0); + assert_eq!(up.y, 10); +} diff --git a/tests/ui/structs-enums/rec-tup.rs b/tests/ui/structs-enums/rec-tup.rs new file mode 100644 index 000000000..b85d28fdf --- /dev/null +++ b/tests/ui/structs-enums/rec-tup.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(non_camel_case_types)] + + +#[derive(Copy, Clone)] +struct Point {x: isize, y: isize} + +type rect = (Point, Point); + +fn fst(r: rect) -> Point { let (fst, _) = r; return fst; } +fn snd(r: rect) -> Point { let (_, snd) = r; return snd; } + +fn f(r: rect, x1: isize, y1: isize, x2: isize, y2: isize) { + assert_eq!(fst(r).x, x1); + assert_eq!(fst(r).y, y1); + assert_eq!(snd(r).x, x2); + assert_eq!(snd(r).y, y2); +} + +pub fn main() { + let r: rect = (Point {x: 10, y: 20}, Point {x: 11, y: 22}); + assert_eq!(fst(r).x, 10); + assert_eq!(fst(r).y, 20); + assert_eq!(snd(r).x, 11); + assert_eq!(snd(r).y, 22); + let r2 = r; + let x: isize = fst(r2).x; + assert_eq!(x, 10); + f(r, 10, 20, 11, 22); + f(r2, 10, 20, 11, 22); +} diff --git a/tests/ui/structs-enums/rec.rs b/tests/ui/structs-enums/rec.rs new file mode 100644 index 000000000..82c84ebd6 --- /dev/null +++ b/tests/ui/structs-enums/rec.rs @@ -0,0 +1,24 @@ +// run-pass + +#[derive(Copy, Clone)] +struct Rect {x: isize, y: isize, w: isize, h: isize} + +fn f(r: Rect, x: isize, y: isize, w: isize, h: isize) { + assert_eq!(r.x, x); + assert_eq!(r.y, y); + assert_eq!(r.w, w); + assert_eq!(r.h, h); +} + +pub fn main() { + let r: Rect = Rect {x: 10, y: 20, w: 100, h: 200}; + assert_eq!(r.x, 10); + assert_eq!(r.y, 20); + assert_eq!(r.w, 100); + assert_eq!(r.h, 200); + let r2: Rect = r; + let x: isize = r2.x; + assert_eq!(x, 10); + f(r, 10, 20, 100, 200); + f(r2, 10, 20, 100, 200); +} diff --git a/tests/ui/structs-enums/record-pat.rs b/tests/ui/structs-enums/record-pat.rs new file mode 100644 index 000000000..1acaf2a32 --- /dev/null +++ b/tests/ui/structs-enums/record-pat.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(non_shorthand_field_patterns)] + +enum t1 { a(isize), b(usize), } +struct T2 {x: t1, y: isize} +enum t3 { c(T2, usize), } + +fn m(input: t3) -> isize { + match input { + t3::c(T2 {x: t1::a(m), ..}, _) => { return m; } + t3::c(T2 {x: t1::b(m), y: y}, z) => { return ((m + z) as isize) + y; } + } +} + +pub fn main() { + assert_eq!(m(t3::c(T2 {x: t1::a(10), y: 5}, 4)), 10); + assert_eq!(m(t3::c(T2 {x: t1::b(10), y: 5}, 4)), 19); +} diff --git a/tests/ui/structs-enums/resource-in-struct.rs b/tests/ui/structs-enums/resource-in-struct.rs new file mode 100644 index 000000000..9613ca62a --- /dev/null +++ b/tests/ui/structs-enums/resource-in-struct.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Ensures that class dtors run if the object is inside an enum +// variant + +use std::cell::Cell; + +type closable<'a> = &'a Cell; + +struct close_res<'a> { + i: closable<'a>, + +} + +impl<'a> Drop for close_res<'a> { + fn drop(&mut self) { + self.i.set(false); + } +} + +fn close_res(i: closable) -> close_res { + close_res { + i: i + } +} + +enum option { none, some(#[allow(unused_tuple_struct_fields)] T), } + +fn sink(_res: option) { } + +pub fn main() { + let c = &Cell::new(true); + sink(option::none); + sink(option::some(close_res(c))); + assert!(!c.get()); +} diff --git a/tests/ui/structs-enums/simple-generic-tag.rs b/tests/ui/structs-enums/simple-generic-tag.rs new file mode 100644 index 000000000..dbd2834d4 --- /dev/null +++ b/tests/ui/structs-enums/simple-generic-tag.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + + +// pretty-expanded FIXME #23616 + +enum clam { a(T), } + +pub fn main() { } diff --git a/tests/ui/structs-enums/simple-match-generic-tag.rs b/tests/ui/structs-enums/simple-match-generic-tag.rs new file mode 100644 index 000000000..762fd49ad --- /dev/null +++ b/tests/ui/structs-enums/simple-match-generic-tag.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +enum opt { none, some(T) } + +pub fn main() { + let x = opt::none::; + match x { + opt::none:: => { println!("hello world"); } + opt::some(_) => { } + } +} diff --git a/tests/ui/structs-enums/small-enum-range-edge.rs b/tests/ui/structs-enums/small-enum-range-edge.rs new file mode 100644 index 000000000..306129479 --- /dev/null +++ b/tests/ui/structs-enums/small-enum-range-edge.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// Tests the range assertion wraparound case when reading discriminants. + +#[repr(u8)] +#[derive(Copy, Clone)] +enum Eu { Lu = 0, Hu = 255 } + +static CLu: Eu = Eu::Lu; +static CHu: Eu = Eu::Hu; + +#[repr(i8)] +#[derive(Copy, Clone)] +enum Es { Ls = -128, Hs = 127 } + +static CLs: Es = Es::Ls; +static CHs: Es = Es::Hs; + +pub fn main() { + assert_eq!((Eu::Hu as u8).wrapping_add(1), Eu::Lu as u8); + assert_eq!((Es::Hs as i8).wrapping_add(1), Es::Ls as i8); + assert_eq!(CLu as u8, Eu::Lu as u8); + assert_eq!(CHu as u8, Eu::Hu as u8); + assert_eq!(CLs as i8, Es::Ls as i8); + assert_eq!(CHs as i8, Es::Hs as i8); +} diff --git a/tests/ui/structs-enums/small-enums-with-fields.rs b/tests/ui/structs-enums/small-enums-with-fields.rs new file mode 100644 index 000000000..565ec1bd4 --- /dev/null +++ b/tests/ui/structs-enums/small-enums-with-fields.rs @@ -0,0 +1,33 @@ +// run-pass +use std::mem::size_of; + +#[derive(PartialEq, Debug)] +enum Either { Left(T), Right(U) } + +macro_rules! check { + ($t:ty, $sz:expr, $($e:expr, $s:expr),*) => {{ + assert_eq!(size_of::<$t>(), $sz); + $({ + static S: $t = $e; + let v: $t = $e; + assert_eq!(S, v); + assert_eq!(format!("{:?}", v), $s); + assert_eq!(format!("{:?}", S), $s); + });* + }} +} + +pub fn main() { + check!(Option, 2, + None, "None", + Some(129), "Some(129)"); + check!(Option, 4, + None, "None", + Some(-20000), "Some(-20000)"); + check!(Either, 2, + Either::Left(132), "Left(132)", + Either::Right(-32), "Right(-32)"); + check!(Either, 4, + Either::Left(132), "Left(132)", + Either::Right(-20000), "Right(-20000)"); +} diff --git a/tests/ui/structs-enums/struct-aliases-xcrate.rs b/tests/ui/structs-enums/struct-aliases-xcrate.rs new file mode 100644 index 000000000..ffe7b22f8 --- /dev/null +++ b/tests/ui/structs-enums/struct-aliases-xcrate.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_imports)] +#![allow(non_shorthand_field_patterns)] + +// aux-build:xcrate_struct_aliases.rs + +extern crate xcrate_struct_aliases; + +use xcrate_struct_aliases::{S, S2}; + +fn main() { + let s = S2 { + x: 1, + y: 2, + }; + match s { + S2 { + x: x, + y: y + } => { + assert_eq!(x, 1); + assert_eq!(y, 2); + } + } +} diff --git a/tests/ui/structs-enums/struct-aliases.rs b/tests/ui/structs-enums/struct-aliases.rs new file mode 100644 index 000000000..b7aeed7bc --- /dev/null +++ b/tests/ui/structs-enums/struct-aliases.rs @@ -0,0 +1,64 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +use std::mem; + +struct S { + x: isize, + y: isize, +} + +type S2 = S; + +struct S3 { + x: U, + y: V +} + +type S4 = S3; + +fn main() { + let s = S2 { + x: 1, + y: 2, + }; + match s { + S2 { + x: x, + y: y + } => { + assert_eq!(x, 1); + assert_eq!(y, 2); + } + } + // check that generics can be specified from the pattern + let s = S4 { + x: 4, + y: 'a' + }; + match s { + S4:: { + x: x, + y: y + } => { + assert_eq!(x, 4); + assert_eq!(y, 'a'); + assert_eq!(mem::size_of_val(&x), 1); + } + }; + // check that generics can be specified from the constructor + let s = S4:: { + x: 5, + y: 'b' + }; + match s { + S4 { + x: x, + y: y + } => { + assert_eq!(x, 5); + assert_eq!(y, 'b'); + assert_eq!(mem::size_of_val(&x), 2); + } + }; +} diff --git a/tests/ui/structs-enums/struct-destructuring-cross-crate.rs b/tests/ui/structs-enums/struct-destructuring-cross-crate.rs new file mode 100644 index 000000000..19e0a0bbd --- /dev/null +++ b/tests/ui/structs-enums/struct-destructuring-cross-crate.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:struct_destructuring_cross_crate.rs + + +extern crate struct_destructuring_cross_crate; + +pub fn main() { + let x = struct_destructuring_cross_crate::S { x: 1, y: 2 }; + let struct_destructuring_cross_crate::S { x: a, y: b } = x; + assert_eq!(a, 1); + assert_eq!(b, 2); +} diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs new file mode 100644 index 000000000..c30b8a1e1 --- /dev/null +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs @@ -0,0 +1,12 @@ +enum Foo { + Bar { bar: bool }, + Other, +} + +fn main() { + let foo = Some(Foo::Other); + + if let Some(Foo::Bar {_}) = foo {} + //~^ ERROR expected identifier, found reserved identifier `_` + //~| ERROR pattern does not mention field `bar` [E0027] +} diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr new file mode 100644 index 000000000..16f751444 --- /dev/null +++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr @@ -0,0 +1,24 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27 + | +LL | if let Some(Foo::Bar {_}) = foo {} + | ^ expected identifier, found reserved identifier + +error[E0027]: pattern does not mention field `bar` + --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17 + | +LL | if let Some(Foo::Bar {_}) = foo {} + | ^^^^^^^^^^^^ missing field `bar` + | +help: include the missing field in the pattern + | +LL | if let Some(Foo::Bar {_, bar }) = foo {} + | ~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | if let Some(Foo::Bar {_, .. }) = foo {} + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/structs-enums/struct-field-shorthand.rs b/tests/ui/structs-enums/struct-field-shorthand.rs new file mode 100644 index 000000000..ed650c683 --- /dev/null +++ b/tests/ui/structs-enums/struct-field-shorthand.rs @@ -0,0 +1,26 @@ +// run-pass +struct Foo { + x: i32, + y: bool, + z: i32 +} + +struct Bar { + x: i32 +} + +pub fn main() { + let (x, y, z) = (1, true, 2); + let a = Foo { x, y: y, z }; + assert_eq!(a.x, x); + assert_eq!(a.y, y); + assert_eq!(a.z, z); + + let b = Bar { x, }; + assert_eq!(b.x, x); + + let c = Foo { z, y, x }; + assert_eq!(c.x, x); + assert_eq!(c.y, y); + assert_eq!(c.z, z); +} diff --git a/tests/ui/structs-enums/struct-like-variant-construct.rs b/tests/ui/structs-enums/struct-like-variant-construct.rs new file mode 100644 index 000000000..60fc7ce39 --- /dev/null +++ b/tests/ui/structs-enums/struct-like-variant-construct.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +enum Foo { + Bar { + a: isize, + b: isize + }, + Baz { + c: f64, + d: f64 + } +} + +pub fn main() { + let _x = Foo::Bar { a: 2, b: 3 }; +} diff --git a/tests/ui/structs-enums/struct-like-variant-match.rs b/tests/ui/structs-enums/struct-like-variant-match.rs new file mode 100644 index 000000000..ade1a6970 --- /dev/null +++ b/tests/ui/structs-enums/struct-like-variant-match.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +enum Foo { + Bar { + x: isize, + y: isize + }, + Baz { + x: f64, + y: f64 + } +} + +fn f(x: &Foo) { + match *x { + Foo::Baz { x: x, y: y } => { + assert_eq!(x, 1.0); + assert_eq!(y, 2.0); + } + Foo::Bar { y: y, x: x } => { + assert_eq!(x, 1); + assert_eq!(y, 2); + } + } +} + +pub fn main() { + let x = Foo::Bar { x: 1, y: 2 }; + f(&x); + let y = Foo::Baz { x: 1.0, y: 2.0 }; + f(&y); +} diff --git a/tests/ui/structs-enums/struct-lit-functional-no-fields.rs b/tests/ui/structs-enums/struct-lit-functional-no-fields.rs new file mode 100644 index 000000000..f19604e95 --- /dev/null +++ b/tests/ui/structs-enums/struct-lit-functional-no-fields.rs @@ -0,0 +1,26 @@ +// run-pass +#[derive(Debug,PartialEq,Clone)] +struct Foo { + bar: T, + baz: T +} + +pub fn main() { + let foo = Foo { + bar: 0, + baz: 1 + }; + + let foo_ = foo.clone(); + let foo = Foo { ..foo }; + assert_eq!(foo, foo_); + + let foo = Foo { + bar: "one".to_string(), + baz: "two".to_string() + }; + + let foo_ = foo.clone(); + let foo = Foo { ..foo }; + assert_eq!(foo, foo_); +} diff --git a/tests/ui/structs-enums/struct-literal-dtor.rs b/tests/ui/structs-enums/struct-literal-dtor.rs new file mode 100644 index 000000000..6d1b1dfb9 --- /dev/null +++ b/tests/ui/structs-enums/struct-literal-dtor.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_camel_case_types)] + +struct foo { + x: String, +} + +impl Drop for foo { + fn drop(&mut self) { + println!("{}", self.x); + } +} + +pub fn main() { + let _z = foo { + x: "Hello".to_string() + }; +} diff --git a/tests/ui/structs-enums/struct-new-as-field-name.rs b/tests/ui/structs-enums/struct-new-as-field-name.rs new file mode 100644 index 000000000..641fc3c58 --- /dev/null +++ b/tests/ui/structs-enums/struct-new-as-field-name.rs @@ -0,0 +1,10 @@ +// run-pass + +struct Foo { + new: isize, +} + +pub fn main() { + let foo = Foo{ new: 3 }; + assert_eq!(foo.new, 3); +} diff --git a/tests/ui/structs-enums/struct-order-of-eval-1.rs b/tests/ui/structs-enums/struct-order-of-eval-1.rs new file mode 100644 index 000000000..f3fe99538 --- /dev/null +++ b/tests/ui/structs-enums/struct-order-of-eval-1.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +struct S { f0: String, f1: isize } + +pub fn main() { + let s = "Hello, world!".to_string(); + let s = S { + f0: s.to_string(), + ..S { + f0: s, + f1: 23 + } + }; + assert_eq!(s.f0, "Hello, world!"); +} diff --git a/tests/ui/structs-enums/struct-order-of-eval-2.rs b/tests/ui/structs-enums/struct-order-of-eval-2.rs new file mode 100644 index 000000000..a4e0edc97 --- /dev/null +++ b/tests/ui/structs-enums/struct-order-of-eval-2.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] + +struct S { + f0: String, + f1: String, +} + +pub fn main() { + let s = "Hello, world!".to_string(); + let s = S { + f1: s.to_string(), + f0: s + }; + assert_eq!(s.f0, "Hello, world!"); +} diff --git a/tests/ui/structs-enums/struct-order-of-eval-3.rs b/tests/ui/structs-enums/struct-order-of-eval-3.rs new file mode 100644 index 000000000..60887f8d0 --- /dev/null +++ b/tests/ui/structs-enums/struct-order-of-eval-3.rs @@ -0,0 +1,37 @@ +// run-pass +// Checks that functional-record-update order-of-eval is as expected +// even when no Drop-implementations are involved. + +use std::sync::atomic::{Ordering, AtomicUsize}; + +struct W { wrapped: u32 } +struct S { f0: W, _f1: i32 } + +pub fn main() { + const VAL: u32 = 0x89AB_CDEF; + let w = W { wrapped: VAL }; + let s = S { + f0: { event(0x01); W { wrapped: w.wrapped + 1 } }, + ..S { + f0: { event(0x02); w}, + _f1: 23 + } + }; + assert_eq!(s.f0.wrapped, VAL + 1); + let actual = event_log(); + let expect = 0x01_02; + assert!(expect == actual, + "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} + +static LOG: AtomicUsize = AtomicUsize::new(0); + +fn event_log() -> usize { + LOG.load(Ordering::SeqCst) +} + +fn event(tag: u8) { + let old_log = LOG.load(Ordering::SeqCst); + let new_log = (old_log << 8) + tag as usize; + LOG.store(new_log, Ordering::SeqCst); +} diff --git a/tests/ui/structs-enums/struct-order-of-eval-4.rs b/tests/ui/structs-enums/struct-order-of-eval-4.rs new file mode 100644 index 000000000..547df6318 --- /dev/null +++ b/tests/ui/structs-enums/struct-order-of-eval-4.rs @@ -0,0 +1,34 @@ +// run-pass +// Checks that struct-literal expression order-of-eval is as expected +// even when no Drop-implementations are involved. + +use std::sync::atomic::{Ordering, AtomicUsize}; + +struct W { wrapped: u32 } +struct S { f0: W, _f1: i32 } + +pub fn main() { + const VAL: u32 = 0x89AB_CDEF; + let w = W { wrapped: VAL }; + let s = S { + _f1: { event(0x01); 23 }, + f0: { event(0x02); w }, + }; + assert_eq!(s.f0.wrapped, VAL); + let actual = event_log(); + let expect = 0x01_02; + assert!(expect == actual, + "expect: 0x{:x} actual: 0x{:x}", expect, actual); +} + +static LOG: AtomicUsize = AtomicUsize::new(0); + +fn event_log() -> usize { + LOG.load(Ordering::SeqCst) +} + +fn event(tag: u8) { + let old_log = LOG.load(Ordering::SeqCst); + let new_log = (old_log << 8) + tag as usize; + LOG.store(new_log, Ordering::SeqCst); +} diff --git a/tests/ui/structs-enums/struct-partial-move-1.rs b/tests/ui/structs-enums/struct-partial-move-1.rs new file mode 100644 index 000000000..c15701593 --- /dev/null +++ b/tests/ui/structs-enums/struct-partial-move-1.rs @@ -0,0 +1,21 @@ +// run-pass +#[derive(PartialEq, Debug)] +pub struct Partial { x: T, y: T } + +#[derive(PartialEq, Debug)] +struct S { val: isize } +impl S { fn new(v: isize) -> S { S { val: v } } } +impl Drop for S { fn drop(&mut self) { } } + +pub fn f((b1, b2): (T, T), mut f: F) -> Partial where F: FnMut(T) -> T { + let p = Partial { x: b1, y: b2 }; + + // Move of `p` is legal even though we are also moving `p.y`; the + // `..p` moves all fields *except* `p.y` in this context. + Partial { y: f(p.y), ..p } +} + +pub fn main() { + let p = f((S::new(3), S::new(4)), |S { val: z }| S::new(z+1)); + assert_eq!(p, Partial { x: S::new(3), y: S::new(5) }); +} diff --git a/tests/ui/structs-enums/struct-partial-move-2.rs b/tests/ui/structs-enums/struct-partial-move-2.rs new file mode 100644 index 000000000..4315e5c29 --- /dev/null +++ b/tests/ui/structs-enums/struct-partial-move-2.rs @@ -0,0 +1,28 @@ +// run-pass +#[derive(PartialEq, Debug)] +pub struct Partial { x: T, y: T } + +#[derive(PartialEq, Debug)] +struct S { val: isize } +impl S { fn new(v: isize) -> S { S { val: v } } } +impl Drop for S { fn drop(&mut self) { } } + +pub type Two = (Partial, Partial); + +pub fn f((b1, b2): (T, T), (b3, b4): (T, T), mut f: F) -> Two where F: FnMut(T) -> T { + let p = Partial { x: b1, y: b2 }; + let q = Partial { x: b3, y: b4 }; + + // Move of `q` is legal even though we have already moved `q.y`; + // the `..q` moves all fields *except* `q.y` in this context. + // Likewise, the move of `p.x` is legal for similar reasons. + (Partial { x: f(q.y), ..p }, Partial { y: f(p.x), ..q }) +} + +pub fn main() { + let two = f((S::new(1), S::new(3)), + (S::new(5), S::new(7)), + |S { val: z }| S::new(z+1)); + assert_eq!(two, (Partial { x: S::new(8), y: S::new(3) }, + Partial { x: S::new(5), y: S::new(2) })); +} diff --git a/tests/ui/structs-enums/struct-path-associated-type.rs b/tests/ui/structs-enums/struct-path-associated-type.rs new file mode 100644 index 000000000..2235dfe4b --- /dev/null +++ b/tests/ui/structs-enums/struct-path-associated-type.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +struct S { + a: T, + b: U, +} + +trait Tr { + type A; +} +impl Tr for u8 { + type A = S; +} + +fn f>>() { + let s = T::A { a: 0, b: 1 }; + match s { + T::A { a, b } => { + assert_eq!(a, 0); + assert_eq!(b, 1); + } + } +} + +fn main() { + f::(); +} diff --git a/tests/ui/structs-enums/struct-path-self.rs b/tests/ui/structs-enums/struct-path-self.rs new file mode 100644 index 000000000..e7a59858f --- /dev/null +++ b/tests/ui/structs-enums/struct-path-self.rs @@ -0,0 +1,45 @@ +// run-pass +use std::ops::Add; + +struct S { + a: T, + b: U, +} + +trait Tr { + fn f(&self) -> Self; +} + +impl, U: Default> Tr for S { + fn f(&self) -> Self { + let s = Self { a: Default::default(), b: Default::default() }; + match s { + Self { a, b } => Self { a: a + 1, b: b } + } + } +} + +impl> S { + fn g(&self) -> Self { + let s = Self { a: Default::default(), b: Default::default() }; + match s { + Self { a, b } => Self { a: a, b: b + 1 } + } + } +} + +impl S { + fn new() -> Self { + Self { a: 0, b: 1 } + } +} + +fn main() { + let s0 = S::new(); + let s1 = s0.f(); + assert_eq!(s1.a, 1); + assert_eq!(s1.b, 0); + let s2 = s0.g(); + assert_eq!(s2.a, 0); + assert_eq!(s2.b, 1); +} diff --git a/tests/ui/structs-enums/struct-pattern-matching.rs b/tests/ui/structs-enums/struct-pattern-matching.rs new file mode 100644 index 000000000..89361bf24 --- /dev/null +++ b/tests/ui/structs-enums/struct-pattern-matching.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize, +} + +pub fn main() { + let a = Foo { x: 1, y: 2 }; + match a { + Foo { x: x, y: y } => println!("yes, {}, {}", x, y) + } + + match a { + Foo { .. } => () + } +} diff --git a/tests/ui/structs-enums/struct-rec/issue-74224.rs b/tests/ui/structs-enums/struct-rec/issue-74224.rs new file mode 100644 index 000000000..f3b72c5df --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-74224.rs @@ -0,0 +1,11 @@ +struct A { +//~^ ERROR recursive type `A` has infinite size + x: T, + y: A>, +} + +struct B { + z: A +} + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/issue-74224.stderr b/tests/ui/structs-enums/struct-rec/issue-74224.stderr new file mode 100644 index 000000000..f1d50bc8a --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-74224.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `A` has infinite size + --> $DIR/issue-74224.rs:1:1 + | +LL | struct A { + | ^^^^^^^^^^^ +... +LL | y: A>, + | ------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | y: Box>>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/issue-84611.rs b/tests/ui/structs-enums/struct-rec/issue-84611.rs new file mode 100644 index 000000000..4c356af3e --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-84611.rs @@ -0,0 +1,11 @@ +struct Foo { +//~^ ERROR recursive type `Foo` has infinite size + x: Foo<[T; 1]>, + y: T, +} + +struct Bar { + x: Foo, +} + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/issue-84611.stderr b/tests/ui/structs-enums/struct-rec/issue-84611.stderr new file mode 100644 index 000000000..536f54e3e --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/issue-84611.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/issue-84611.rs:1:1 + | +LL | struct Foo { + | ^^^^^^^^^^^^^ +LL | +LL | x: Foo<[T; 1]>, + | ----------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | x: Box>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.rs b/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.rs new file mode 100644 index 000000000..3bfce8b4f --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.rs @@ -0,0 +1,21 @@ +struct A { +//~^ ERROR recursive types `A` and `B` have infinite size + x: T, + y: B, +} + +struct B { + z: A +} + +struct C { +//~^ ERROR recursive types `C` and `D` have infinite size + x: T, + y: Option>>, +} + +struct D { + z: Option>>, +} + +fn main() {} diff --git a/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr b/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr new file mode 100644 index 000000000..881bc2819 --- /dev/null +++ b/tests/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr @@ -0,0 +1,49 @@ +error[E0072]: recursive types `A` and `B` have infinite size + --> $DIR/mutual-struct-recursion.rs:1:1 + | +LL | struct A { + | ^^^^^^^^^^^ +... +LL | y: B, + | ---- recursive without indirection +... +LL | struct B { + | ^^^^^^^^^^^ +LL | z: A + | ---- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ y: Box>, +LL | } +LL | +LL | struct B { +LL ~ z: Box> + | + +error[E0072]: recursive types `C` and `D` have infinite size + --> $DIR/mutual-struct-recursion.rs:11:1 + | +LL | struct C { + | ^^^^^^^^^^^ +... +LL | y: Option>>, + | ---- recursive without indirection +... +LL | struct D { + | ^^^^^^^^^^^ +LL | z: Option>>, + | ---- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ y: Option>>>, +LL | } +LL | +LL | struct D { +LL ~ z: Option>>>, + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/struct-variant-field-visibility.rs b/tests/ui/structs-enums/struct-variant-field-visibility.rs new file mode 100644 index 000000000..7896c829a --- /dev/null +++ b/tests/ui/structs-enums/struct-variant-field-visibility.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +mod foo { + pub enum Foo { + Bar { a: isize } + } +} + +fn f(f: foo::Foo) { + match f { + foo::Foo::Bar { a: _a } => {} + } +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/struct_variant_xc.rs b/tests/ui/structs-enums/struct_variant_xc.rs new file mode 100644 index 000000000..9c8d1a69a --- /dev/null +++ b/tests/ui/structs-enums/struct_variant_xc.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:struct_variant_xc_aux.rs +// pretty-expanded FIXME #23616 + +extern crate struct_variant_xc_aux; + +use struct_variant_xc_aux::Enum::StructVariant; + +pub fn main() { + let _ = StructVariant { arg: 1 }; +} diff --git a/tests/ui/structs-enums/struct_variant_xc_match.rs b/tests/ui/structs-enums/struct_variant_xc_match.rs new file mode 100644 index 000000000..5358d13fa --- /dev/null +++ b/tests/ui/structs-enums/struct_variant_xc_match.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:struct_variant_xc_aux.rs + +extern crate struct_variant_xc_aux; + +use struct_variant_xc_aux::Enum::{StructVariant, Variant}; + +pub fn main() { + let arg = match (StructVariant { arg: 42 }) { + Variant(_) => unreachable!(), + StructVariant { arg } => arg + }; + assert_eq!(arg, 42); +} diff --git a/tests/ui/structs-enums/tag-align-dyn-u64.rs b/tests/ui/structs-enums/tag-align-dyn-u64.rs new file mode 100644 index 000000000..3f7a5e3e5 --- /dev/null +++ b/tests/ui/structs-enums/tag-align-dyn-u64.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +#![allow(deprecated)] + +use std::mem; + +enum Tag { + Tag2(A) +} + +struct Rec { + c8: u8, + t: Tag +} + +fn mk_rec() -> Rec { + return Rec { c8:0, t:Tag::Tag2(0) }; +} + +fn is_u64_aligned(u: &Tag) -> bool { + let p: usize = unsafe { mem::transmute(u) }; + let u64_align = std::mem::min_align_of::(); + return (p & (u64_align - 1)) == 0; +} + +pub fn main() { + let x = mk_rec(); + assert!(is_u64_aligned(&x.t)); +} diff --git a/tests/ui/structs-enums/tag-align-dyn-variants.rs b/tests/ui/structs-enums/tag-align-dyn-variants.rs new file mode 100644 index 000000000..4d075b04c --- /dev/null +++ b/tests/ui/structs-enums/tag-align-dyn-variants.rs @@ -0,0 +1,67 @@ +// run-pass +#![allow(dead_code)] +#![allow(deprecated)] +#![allow(non_snake_case)] + +use std::mem; + +enum Tag { + VarA(A), + VarB(B), +} + +struct Rec { + chA: u8, + tA: Tag, + chB: u8, + tB: Tag, +} + +fn mk_rec(a: A, b: B) -> Rec { + Rec { chA:0, tA:Tag::VarA(a), chB:1, tB:Tag::VarB(b) } +} + +fn is_aligned(amnt: usize, u: &A) -> bool { + let p: usize = unsafe { mem::transmute(u) }; + return (p & (amnt-1)) == 0; +} + +fn variant_data_is_aligned(amnt: usize, u: &Tag) -> bool { + match u { + &Tag::VarA(ref a) => is_aligned(amnt, a), + &Tag::VarB(ref b) => is_aligned(amnt, b) + } +} + +pub fn main() { + let u64_align = std::mem::min_align_of::(); + let x = mk_rec(22u64, 23u64); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(u64_align, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(u64_align, &x.tB)); + + let x = mk_rec(22u64, 23u32); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(u64_align, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(4, &x.tB)); + + let x = mk_rec(22u32, 23u64); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(4, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(u64_align, &x.tB)); + + let x = mk_rec(22u32, 23u32); + assert!(is_aligned(4, &x.tA)); + assert!(variant_data_is_aligned(4, &x.tA)); + assert!(is_aligned(4, &x.tB)); + assert!(variant_data_is_aligned(4, &x.tB)); + + let x = mk_rec(22f64, 23f64); + assert!(is_aligned(u64_align, &x.tA)); + assert!(variant_data_is_aligned(u64_align, &x.tA)); + assert!(is_aligned(u64_align, &x.tB)); + assert!(variant_data_is_aligned(u64_align, &x.tB)); +} diff --git a/tests/ui/structs-enums/tag-align-shape.rs b/tests/ui/structs-enums/tag-align-shape.rs new file mode 100644 index 000000000..ce5995823 --- /dev/null +++ b/tests/ui/structs-enums/tag-align-shape.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +#[derive(Debug)] +enum a_tag { + a_tag_var(u64) +} + +#[derive(Debug)] +struct t_rec { + c8: u8, + t: a_tag +} + +pub fn main() { + let x = t_rec {c8: 22, t: a_tag::a_tag_var(44)}; + let y = format!("{:?}", x); + println!("y = {:?}", y); + assert_eq!(y, "t_rec { c8: 22, t: a_tag_var(44) }".to_string()); +} diff --git a/tests/ui/structs-enums/tag-align-u64.rs b/tests/ui/structs-enums/tag-align-u64.rs new file mode 100644 index 000000000..684b27cd0 --- /dev/null +++ b/tests/ui/structs-enums/tag-align-u64.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +#![allow(deprecated)] + +use std::mem; + +enum Tag { + TagInner(u64) +} + +struct Rec { + c8: u8, + t: Tag +} + +fn mk_rec() -> Rec { + return Rec { c8:0, t:Tag::TagInner(0) }; +} + +fn is_u64_aligned(u: &Tag) -> bool { + let p: usize = unsafe { mem::transmute(u) }; + let u64_align = std::mem::min_align_of::(); + return (p & (u64_align - 1)) == 0; +} + +pub fn main() { + let x = mk_rec(); + assert!(is_u64_aligned(&x.t)); +} diff --git a/tests/ui/structs-enums/tag-disr-val-shape.rs b/tests/ui/structs-enums/tag-disr-val-shape.rs new file mode 100644 index 000000000..51052626c --- /dev/null +++ b/tests/ui/structs-enums/tag-disr-val-shape.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +#[derive(Debug)] +enum color { + red = 0xff0000, + green = 0x00ff00, + blue = 0x0000ff, + black = 0x000000, + white = 0xFFFFFF, +} + +pub fn main() { + let act = format!("{:?}", color::red); + println!("{}", act); + assert_eq!("red".to_string(), act); + assert_eq!("green".to_string(), format!("{:?}", color::green)); + assert_eq!("white".to_string(), format!("{:?}", color::white)); +} diff --git a/tests/ui/structs-enums/tag-exports.rs b/tests/ui/structs-enums/tag-exports.rs new file mode 100644 index 000000000..1bcb7d35d --- /dev/null +++ b/tests/ui/structs-enums/tag-exports.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +use alder::*; + +mod alder { + pub enum burnside { couch, davis } + pub enum everett { flanders, glisan, hoyt } + pub enum irving { johnson, kearney, lovejoy } + pub enum marshall { northrup, overton } +} + +pub fn main() { + let _pettygrove: burnside = burnside::couch; + let _quimby: everett = everett::flanders; + let _raleigh: irving = irving::johnson; + let _savier: marshall; +} diff --git a/tests/ui/structs-enums/tag-in-block.rs b/tests/ui/structs-enums/tag-in-block.rs new file mode 100644 index 000000000..03d4dd9b0 --- /dev/null +++ b/tests/ui/structs-enums/tag-in-block.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + + +// pretty-expanded FIXME #23616 + +fn foo() { + fn zed(_z: bar) { } + enum bar { nil, } + fn baz() { zed(bar::nil); } +} + +pub fn main() { } diff --git a/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs b/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs new file mode 100644 index 000000000..3f59db383 --- /dev/null +++ b/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum color { + red = 1, + blue = 2, +} + +pub fn main() {} diff --git a/tests/ui/structs-enums/tag-variant-disr-val.rs b/tests/ui/structs-enums/tag-variant-disr-val.rs new file mode 100644 index 000000000..297d85c58 --- /dev/null +++ b/tests/ui/structs-enums/tag-variant-disr-val.rs @@ -0,0 +1,66 @@ +// run-pass +#![allow(non_camel_case_types)] + +use color::{red, green, blue, black, white, imaginary, purple, orange}; + +#[derive(Copy, Clone)] +enum color { + red = 0xff0000, + green = 0x00ff00, + blue = 0x0000ff, + black = 0x000000, + white = 0xFFFFFF, + imaginary = -1, + purple = 1 << 1, + orange = 8 >> 1 +} + +impl PartialEq for color { + fn eq(&self, other: &color) -> bool { + ((*self) as usize) == ((*other) as usize) + } + fn ne(&self, other: &color) -> bool { !(*self).eq(other) } +} + +pub fn main() { + test_color(red, 0xff0000, "red".to_string()); + test_color(green, 0x00ff00, "green".to_string()); + test_color(blue, 0x0000ff, "blue".to_string()); + test_color(black, 0x000000, "black".to_string()); + test_color(white, 0xFFFFFF, "white".to_string()); + test_color(imaginary, -1, "imaginary".to_string()); + test_color(purple, 2, "purple".to_string()); + test_color(orange, 4, "orange".to_string()); +} + +fn test_color(color: color, val: isize, name: String) { + //assert_eq!(unsafe::transmute(color), val); + assert_eq!(color as isize, val); + assert_eq!(get_color_alt(color), name); + assert_eq!(get_color_if(color), name); +} + +fn get_color_alt(color: color) -> String { + match color { + red => {"red".to_string()} + green => {"green".to_string()} + blue => {"blue".to_string()} + black => {"black".to_string()} + white => {"white".to_string()} + imaginary => {"imaginary".to_string()} + purple => {"purple".to_string()} + orange => {"orange".to_string()} + } +} + +fn get_color_if(color: color) -> String { + if color == red {"red".to_string()} + else if color == green {"green".to_string()} + else if color == blue {"blue".to_string()} + else if color == black {"black".to_string()} + else if color == white {"white".to_string()} + else if color == imaginary {"imaginary".to_string()} + else if color == purple {"purple".to_string()} + else if color == orange {"orange".to_string()} + else {"unknown".to_string()} +} diff --git a/tests/ui/structs-enums/tag.rs b/tests/ui/structs-enums/tag.rs new file mode 100644 index 000000000..5fcd64b7c --- /dev/null +++ b/tests/ui/structs-enums/tag.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_parens)] +#![allow(non_camel_case_types)] + + +enum colour { red(isize, isize), green, } + +impl PartialEq for colour { + fn eq(&self, other: &colour) -> bool { + match *self { + colour::red(a0, b0) => { + match (*other) { + colour::red(a1, b1) => a0 == a1 && b0 == b1, + colour::green => false, + } + } + colour::green => { + match (*other) { + colour::red(..) => false, + colour::green => true + } + } + } + } + fn ne(&self, other: &colour) -> bool { !(*self).eq(other) } +} + +fn f() { let x = colour::red(1, 2); let y = colour::green; assert!((x != y)); } + +pub fn main() { f(); } diff --git a/tests/ui/structs-enums/tuple-struct-construct.rs b/tests/ui/structs-enums/tuple-struct-construct.rs new file mode 100644 index 000000000..fbf97e6b2 --- /dev/null +++ b/tests/ui/structs-enums/tuple-struct-construct.rs @@ -0,0 +1,9 @@ +// run-pass +#[allow(unused_tuple_struct_fields)] +#[derive(Debug)] +struct Foo(isize, isize); + +pub fn main() { + let x = Foo(1, 2); + println!("{:?}", x); +} diff --git a/tests/ui/structs-enums/tuple-struct-constructor-pointer.rs b/tests/ui/structs-enums/tuple-struct-constructor-pointer.rs new file mode 100644 index 000000000..23f065163 --- /dev/null +++ b/tests/ui/structs-enums/tuple-struct-constructor-pointer.rs @@ -0,0 +1,12 @@ +// run-pass +#[derive(PartialEq, Debug)] +struct Foo(isize); +#[derive(PartialEq, Debug)] +struct Bar(isize, isize); + +pub fn main() { + let f: fn(isize) -> Foo = Foo; + let g: fn(isize, isize) -> Bar = Bar; + assert_eq!(f(42), Foo(42)); + assert_eq!(g(4, 7), Bar(4, 7)); +} diff --git a/tests/ui/structs-enums/tuple-struct-destructuring.rs b/tests/ui/structs-enums/tuple-struct-destructuring.rs new file mode 100644 index 000000000..dff87ead0 --- /dev/null +++ b/tests/ui/structs-enums/tuple-struct-destructuring.rs @@ -0,0 +1,10 @@ +// run-pass +struct Foo(isize, isize); + +pub fn main() { + let x = Foo(1, 2); + let Foo(y, z) = x; + println!("{} {}", y, z); + assert_eq!(y, 1); + assert_eq!(z, 2); +} diff --git a/tests/ui/structs-enums/tuple-struct-matching.rs b/tests/ui/structs-enums/tuple-struct-matching.rs new file mode 100644 index 000000000..432be1d1f --- /dev/null +++ b/tests/ui/structs-enums/tuple-struct-matching.rs @@ -0,0 +1,13 @@ +// run-pass +struct Foo(isize, isize); + +pub fn main() { + let x = Foo(1, 2); + match x { + Foo(a, b) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + println!("{} {}", a, b); + } + } +} diff --git a/tests/ui/structs-enums/tuple-struct-trivial.rs b/tests/ui/structs-enums/tuple-struct-trivial.rs new file mode 100644 index 000000000..c8651fd29 --- /dev/null +++ b/tests/ui/structs-enums/tuple-struct-trivial.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct Foo(isize, isize, isize); + +pub fn main() { +} diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs new file mode 100644 index 000000000..63e2f3150 --- /dev/null +++ b/tests/ui/structs-enums/type-sizes.rs @@ -0,0 +1,273 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![feature(never_type)] +#![feature(pointer_is_aligned)] + +use std::mem::size_of; +use std::num::NonZeroU8; + +struct t {a: u8, b: i8} +struct u {a: u8, b: i8, c: u8} +struct v {a: u8, b: i8, c: v2, d: u32} +struct v2 {u: char, v: u8} +struct w {a: isize, b: ()} +struct x {a: isize, b: (), c: ()} +struct y {x: isize} + +enum e1 { + a(u8, u32), b(u32), c +} +enum e2 { + a(u32), b +} + +#[repr(C, u8)] +enum e3 { + a([u16; 0], u8), b +} + +struct ReorderedStruct { + a: u8, + b: u16, + c: u8 +} + +enum ReorderedEnum { + A(u8, u16, u8), + B(u8, u16, u8), +} + +enum ReorderedEnum2 { + A(u8, u32, u8), + B(u16, u8, u16, u8), + + // 0x100 niche variants. + _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0A, _0B, _0C, _0D, _0E, _0F, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1A, _1B, _1C, _1D, _1E, _1F, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2A, _2B, _2C, _2D, _2E, _2F, + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3A, _3B, _3C, _3D, _3E, _3F, + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4A, _4B, _4C, _4D, _4E, _4F, + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5A, _5B, _5C, _5D, _5E, _5F, + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6A, _6B, _6C, _6D, _6E, _6F, + _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7A, _7B, _7C, _7D, _7E, _7F, + _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8A, _8B, _8C, _8D, _8E, _8F, + _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9A, _9B, _9C, _9D, _9E, _9F, + _A0, _A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8, _A9, _AA, _AB, _AC, _AD, _AE, _AF, + _B0, _B1, _B2, _B3, _B4, _B5, _B6, _B7, _B8, _B9, _BA, _BB, _BC, _BD, _BE, _BF, + _C0, _C1, _C2, _C3, _C4, _C5, _C6, _C7, _C8, _C9, _CA, _CB, _CC, _CD, _CE, _CF, + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7, _D8, _D9, _DA, _DB, _DC, _DD, _DE, _DF, + _E0, _E1, _E2, _E3, _E4, _E5, _E6, _E7, _E8, _E9, _EA, _EB, _EC, _ED, _EE, _EF, + _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF, +} + +enum EnumEmpty {} + +enum EnumSingle1 { + A, +} + +enum EnumSingle2 { + A = 42 as isize, +} + +enum EnumSingle3 { + A, + B(!), +} + +#[repr(u8)] +enum EnumSingle4 { + A, +} + +#[repr(u8)] +enum EnumSingle5 { + A = 42 as u8, +} + +enum EnumWithMaybeUninhabitedVariant { + A(&'static ()), + B(&'static (), T), + C, +} + +enum NicheFilledEnumWithAbsentVariant { + A(&'static ()), + B((), !), + C, +} + +enum Option2 { + Some(A, B), + None +} + +// Two layouts are considered for `CanBeNicheFilledButShouldnt`: +// Niche-filling: +// { u32 (4 bytes), NonZeroU8 + tag in niche (1 byte), padding (3 bytes) } +// Tagged: +// { tag (1 byte), NonZeroU8 (1 byte), padding (2 bytes), u32 (4 bytes) } +// Both are the same size (due to padding), +// but the tagged layout is better as the tag creates a niche with 254 invalid values, +// allowing types like `Option>` to fit into 8 bytes. +pub enum CanBeNicheFilledButShouldnt { + A(NonZeroU8, u32), + B +} +pub enum AlwaysTaggedBecauseItHasNoNiche { + A(u8, u32), + B +} + +pub enum NicheFilledMultipleFields { + A(bool, u8), + B(u8), + C(u8), + D(bool), + E, + F, + G, +} + +struct BoolInTheMiddle(std::num::NonZeroU16, bool, u8); + +enum NicheWithData { + A, + B([u16; 5]), + Largest { a1: u32, a2: BoolInTheMiddle, a3: u32 }, + C, + D(u32, u32), +} + +// A type with almost 2^16 invalid values. +#[repr(u16)] +pub enum NicheU16 { + _0, +} + +pub enum EnumManyVariant { + Dataful(u8, X), + + // 0x100 niche variants. + _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0A, _0B, _0C, _0D, _0E, _0F, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1A, _1B, _1C, _1D, _1E, _1F, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2A, _2B, _2C, _2D, _2E, _2F, + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3A, _3B, _3C, _3D, _3E, _3F, + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4A, _4B, _4C, _4D, _4E, _4F, + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5A, _5B, _5C, _5D, _5E, _5F, + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6A, _6B, _6C, _6D, _6E, _6F, + _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7A, _7B, _7C, _7D, _7E, _7F, + _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8A, _8B, _8C, _8D, _8E, _8F, + _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9A, _9B, _9C, _9D, _9E, _9F, + _A0, _A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8, _A9, _AA, _AB, _AC, _AD, _AE, _AF, + _B0, _B1, _B2, _B3, _B4, _B5, _B6, _B7, _B8, _B9, _BA, _BB, _BC, _BD, _BE, _BF, + _C0, _C1, _C2, _C3, _C4, _C5, _C6, _C7, _C8, _C9, _CA, _CB, _CC, _CD, _CE, _CF, + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7, _D8, _D9, _DA, _DB, _DC, _DD, _DE, _DF, + _E0, _E1, _E2, _E3, _E4, _E5, _E6, _E7, _E8, _E9, _EA, _EB, _EC, _ED, _EE, _EF, + _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF, +} + +struct Reorder4 { + a: u32, + b: u8, + ary: [u8; 4], +} + +struct Reorder2 { + a: u16, + b: u8, + ary: [u8; 6], +} + +pub fn main() { + assert_eq!(size_of::(), 1 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 1 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 2 as usize); + assert_eq!(size_of::(), 3 as usize); + // Alignment causes padding before the char and the u32. + + assert_eq!(size_of::(), + 16 as usize); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + + // Make sure enum types are the appropriate size, mostly + // around ensuring alignment is handled properly + + assert_eq!(size_of::(), 8 as usize); + assert_eq!(size_of::(), 8 as usize); + assert_eq!(size_of::(), 4 as usize); + assert_eq!(size_of::(), 4); + assert_eq!(size_of::(), 6); + assert_eq!(size_of::(), 8); + + + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), 1); + + assert_eq!(size_of::>(), + size_of::>()); + assert_eq!(size_of::(), size_of::<&'static ()>()); + + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + assert_eq!(size_of::>>(), size_of::<(bool, &())>()); + + assert_eq!(size_of::(), 8); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>>(), 8); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>>(), 8); + + assert_eq!(size_of::(), 2); + assert_eq!(size_of::>(), 2); + assert_eq!(size_of::>>(), 2); + + struct S1{ a: u16, b: std::num::NonZeroU16, c: u16, d: u8, e: u32, f: u64, g:[u8;2] } + assert_eq!(size_of::(), 24); + assert_eq!(size_of::>(), 24); + + assert_eq!(size_of::(), 12); + assert_eq!(size_of::>(), 12); + assert_eq!(size_of::>>(), 12); + assert_eq!( + size_of::>>>(), + size_of::<(&(), NicheWithData)>() + ); + + pub enum FillPadding { A(std::num::NonZeroU8, u32), B } + assert_eq!(size_of::(), 8); + assert_eq!(size_of::>(), 8); + assert_eq!(size_of::>>(), 8); + + assert_eq!(size_of::>(), 4); + assert_eq!(size_of::>>(), 4); + assert_eq!(size_of::>(), 4); + + assert_eq!(size_of::>(), 6); + assert_eq!(size_of::>(), 4); + assert_eq!(size_of::>>(), 4); + assert_eq!(size_of::>>(), 6); + assert_eq!(size_of::>>(), 6); + + + let v = Reorder4 {a: 0, b: 0, ary: [0; 4]}; + assert_eq!(size_of::(), 12); + assert!((&v.ary).as_ptr().is_aligned_to(4), "[u8; 4] should group with align-4 fields"); + let v = Reorder2 {a: 0, b: 0, ary: [0; 6]}; + assert_eq!(size_of::(), 10); + assert!((&v.ary).as_ptr().is_aligned_to(2), "[u8; 6] should group with align-2 fields"); +} diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs new file mode 100644 index 000000000..b24effe5a --- /dev/null +++ b/tests/ui/structs-enums/uninstantiable-struct.rs @@ -0,0 +1,4 @@ +// run-pass +pub struct Z(#[allow(unused_tuple_struct_fields)] &'static Z); + +pub fn main() {} diff --git a/tests/ui/structs-enums/unit-like-struct-drop-run.rs b/tests/ui/structs-enums/unit-like-struct-drop-run.rs new file mode 100644 index 000000000..1e9c269a4 --- /dev/null +++ b/tests/ui/structs-enums/unit-like-struct-drop-run.rs @@ -0,0 +1,24 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +// Make sure the destructor is run for unit-like structs. + +use std::thread; + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + panic!("This panic should happen."); + } +} + +pub fn main() { + let x = thread::spawn(move|| { + let _b = Foo; + }).join(); + + let s = x.unwrap_err().downcast::<&'static str>().unwrap(); + assert_eq!(&**s, "This panic should happen."); +} diff --git a/tests/ui/structs-enums/unit-like-struct.rs b/tests/ui/structs-enums/unit-like-struct.rs new file mode 100644 index 000000000..636ec9926 --- /dev/null +++ b/tests/ui/structs-enums/unit-like-struct.rs @@ -0,0 +1,9 @@ +// run-pass +struct Foo; + +pub fn main() { + let x: Foo = Foo; + match x { + Foo => { println!("hi"); } + } +} diff --git a/tests/ui/structs-enums/variant-structs-trivial.rs b/tests/ui/structs-enums/variant-structs-trivial.rs new file mode 100644 index 000000000..31fa610a6 --- /dev/null +++ b/tests/ui/structs-enums/variant-structs-trivial.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +enum Foo { + Bar { x: isize }, + Baz { y: isize } +} + +pub fn main() { } diff --git a/tests/ui/structs/auxiliary/struct_field_privacy.rs b/tests/ui/structs/auxiliary/struct_field_privacy.rs new file mode 100644 index 000000000..9765af1a7 --- /dev/null +++ b/tests/ui/structs/auxiliary/struct_field_privacy.rs @@ -0,0 +1,9 @@ +pub struct A { + a: isize, + pub b: isize, +} + +pub struct B { + pub a: isize, + b: isize, +} diff --git a/tests/ui/structs/auxiliary/struct_variant_privacy.rs b/tests/ui/structs/auxiliary/struct_variant_privacy.rs new file mode 100644 index 000000000..425ec0e96 --- /dev/null +++ b/tests/ui/structs/auxiliary/struct_variant_privacy.rs @@ -0,0 +1,3 @@ +enum Bar { + Baz { a: isize } +} diff --git a/tests/ui/structs/incomplete-fn-in-struct-definition.rs b/tests/ui/structs/incomplete-fn-in-struct-definition.rs new file mode 100644 index 000000000..cd8a79ba6 --- /dev/null +++ b/tests/ui/structs/incomplete-fn-in-struct-definition.rs @@ -0,0 +1,5 @@ +fn main() {} + +struct S { + fn: u8 //~ ERROR expected identifier, found keyword `fn` +} diff --git a/tests/ui/structs/incomplete-fn-in-struct-definition.stderr b/tests/ui/structs/incomplete-fn-in-struct-definition.stderr new file mode 100644 index 000000000..0d12ba9c9 --- /dev/null +++ b/tests/ui/structs/incomplete-fn-in-struct-definition.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found keyword `fn` + --> $DIR/incomplete-fn-in-struct-definition.rs:4:5 + | +LL | struct S { + | - while parsing this struct +LL | fn: u8 + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | r#fn: u8 + | ++ + +error: aborting due to previous error + diff --git a/tests/ui/structs/issue-80853.rs b/tests/ui/structs/issue-80853.rs new file mode 100644 index 000000000..242d0af95 --- /dev/null +++ b/tests/ui/structs/issue-80853.rs @@ -0,0 +1,7 @@ +struct S; + +fn repro_ref(thing: S) { + thing(); //~ ERROR expected function, found `S` +} + +fn main() {} diff --git a/tests/ui/structs/issue-80853.stderr b/tests/ui/structs/issue-80853.stderr new file mode 100644 index 000000000..1c7d52b6d --- /dev/null +++ b/tests/ui/structs/issue-80853.stderr @@ -0,0 +1,13 @@ +error[E0618]: expected function, found `S` + --> $DIR/issue-80853.rs:4:5 + | +LL | fn repro_ref(thing: S) { + | ----- `thing` has type `S` +LL | thing(); + | ^^^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/structs/large-records.rs b/tests/ui/structs/large-records.rs new file mode 100644 index 000000000..7f850a94e --- /dev/null +++ b/tests/ui/structs/large-records.rs @@ -0,0 +1,38 @@ +// run-pass + +#![allow(dead_code)] + + + + +// pretty-expanded FIXME #23616 + +struct Large {a: isize, + b: isize, + c: isize, + d: isize, + e: isize, + f: isize, + g: isize, + h: isize, + i: isize, + j: isize, + k: isize, + l: isize} +fn f() { + let _foo: Large = + Large {a: 0, + b: 0, + c: 0, + d: 0, + e: 0, + f: 0, + g: 0, + h: 0, + i: 0, + j: 0, + k: 0, + l: 0}; +} + +pub fn main() { f(); } diff --git a/tests/ui/structs/multi-line-fru-suggestion.rs b/tests/ui/structs/multi-line-fru-suggestion.rs new file mode 100644 index 000000000..7b2b13914 --- /dev/null +++ b/tests/ui/structs/multi-line-fru-suggestion.rs @@ -0,0 +1,22 @@ +#[derive(Default)] +struct Inner { + a: u8, + b: u8, +} + +#[derive(Default)] +struct Outer { + inner: Inner, + defaulted: u8, +} + +fn main(){ + Outer { + //~^ ERROR missing field `defaulted` in initializer of `Outer` + inner: Inner { + a: 1, + b: 2, + } + ..Default::default() + }; +} diff --git a/tests/ui/structs/multi-line-fru-suggestion.stderr b/tests/ui/structs/multi-line-fru-suggestion.stderr new file mode 100644 index 000000000..8bbd3ace7 --- /dev/null +++ b/tests/ui/structs/multi-line-fru-suggestion.stderr @@ -0,0 +1,25 @@ +error[E0063]: missing field `defaulted` in initializer of `Outer` + --> $DIR/multi-line-fru-suggestion.rs:14:5 + | +LL | Outer { + | ^^^^^ missing `defaulted` + | +note: this expression may have been misinterpreted as a `..` range expression + --> $DIR/multi-line-fru-suggestion.rs:16:16 + | +LL | inner: Inner { + | ________________^ +LL | | a: 1, +LL | | b: 2, +LL | | } + | |_________^ this expression does not end in a comma... +LL | ..Default::default() + | ^^^^^^^^^^^^^^^^^^^^ ... so this is interpreted as a `..` range expression, instead of functional record update syntax +help: to set the remaining fields from `Default::default()`, separate the last named field with a comma + | +LL | }, + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/rhs-type.rs b/tests/ui/structs/rhs-type.rs new file mode 100644 index 000000000..c48e7c08e --- /dev/null +++ b/tests/ui/structs/rhs-type.rs @@ -0,0 +1,18 @@ +// Tests that codegen treats the rhs of pth's decl +// as a _|_-typed thing, not a str-typed thing + +// run-fail +// error-pattern:bye +// ignore-emscripten no processes + +#![allow(unreachable_code)] +#![allow(unused_variables)] + +struct T { + t: String, +} + +fn main() { + let pth = panic!("bye"); + let _rs: T = T { t: pth }; +} diff --git a/tests/ui/structs/struct-base-wrong-type.rs b/tests/ui/structs/struct-base-wrong-type.rs new file mode 100644 index 000000000..b64c6b499 --- /dev/null +++ b/tests/ui/structs/struct-base-wrong-type.rs @@ -0,0 +1,14 @@ +// Check that `base` in `Fru { field: expr, ..base }` must have right type. + +struct Foo { a: isize, b: isize } +struct Bar { x: isize } + +static bar: Bar = Bar { x: 5 }; +static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types +static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types + +fn main() { + let b = Bar { x: 5 }; + let f = Foo { a: 2, ..b }; //~ ERROR mismatched types + let f__isize = Foo { a: 2, ..4 }; //~ ERROR mismatched types +} diff --git a/tests/ui/structs/struct-base-wrong-type.stderr b/tests/ui/structs/struct-base-wrong-type.stderr new file mode 100644 index 000000000..b039ce2cc --- /dev/null +++ b/tests/ui/structs/struct-base-wrong-type.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/struct-base-wrong-type.rs:7:33 + | +LL | static foo: Foo = Foo { a: 2, ..bar }; + | ^^^ expected struct `Foo`, found struct `Bar` + +error[E0308]: mismatched types + --> $DIR/struct-base-wrong-type.rs:8:35 + | +LL | static foo_i: Foo = Foo { a: 2, ..4 }; + | ^ expected struct `Foo`, found integer + +error[E0308]: mismatched types + --> $DIR/struct-base-wrong-type.rs:12:27 + | +LL | let f = Foo { a: 2, ..b }; + | ^ expected struct `Foo`, found struct `Bar` + +error[E0308]: mismatched types + --> $DIR/struct-base-wrong-type.rs:13:34 + | +LL | let f__isize = Foo { a: 2, ..4 }; + | ^ expected struct `Foo`, found integer + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/structs/struct-duplicate-comma.fixed b/tests/ui/structs/struct-duplicate-comma.fixed new file mode 100644 index 000000000..c804cf57a --- /dev/null +++ b/tests/ui/structs/struct-duplicate-comma.fixed @@ -0,0 +1,15 @@ +// run-rustfix +// Issue #50974 + +pub struct Foo { + pub a: u8, + pub b: u8 +} + +fn main() { + let _ = Foo { + a: 0, + //~^ ERROR expected identifier + b: 42 + }; +} diff --git a/tests/ui/structs/struct-duplicate-comma.rs b/tests/ui/structs/struct-duplicate-comma.rs new file mode 100644 index 000000000..db2e7cb3d --- /dev/null +++ b/tests/ui/structs/struct-duplicate-comma.rs @@ -0,0 +1,15 @@ +// run-rustfix +// Issue #50974 + +pub struct Foo { + pub a: u8, + pub b: u8 +} + +fn main() { + let _ = Foo { + a: 0,, + //~^ ERROR expected identifier + b: 42 + }; +} diff --git a/tests/ui/structs/struct-duplicate-comma.stderr b/tests/ui/structs/struct-duplicate-comma.stderr new file mode 100644 index 000000000..834b3c5c1 --- /dev/null +++ b/tests/ui/structs/struct-duplicate-comma.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found `,` + --> $DIR/struct-duplicate-comma.rs:11:14 + | +LL | let _ = Foo { + | --- while parsing this struct +LL | a: 0,, + | ^ + | | + | expected identifier + | help: remove this comma + +error: aborting due to previous error + diff --git a/tests/ui/structs/struct-field-cfg.rs b/tests/ui/structs/struct-field-cfg.rs new file mode 100644 index 000000000..42cab8ab9 --- /dev/null +++ b/tests/ui/structs/struct-field-cfg.rs @@ -0,0 +1,18 @@ +struct Foo { + present: (), +} + +fn main() { + let foo = Foo { #[cfg(all())] present: () }; + let _ = Foo { #[cfg(any())] present: () }; + //~^ ERROR missing field `present` in initializer of `Foo` + let _ = Foo { present: (), #[cfg(any())] absent: () }; + let _ = Foo { present: (), #[cfg(all())] absent: () }; + //~^ ERROR struct `Foo` has no field named `absent` + let Foo { #[cfg(all())] present: () } = foo; + let Foo { #[cfg(any())] present: () } = foo; + //~^ ERROR pattern does not mention field `present` + let Foo { present: (), #[cfg(any())] absent: () } = foo; + let Foo { present: (), #[cfg(all())] absent: () } = foo; + //~^ ERROR struct `Foo` does not have a field named `absent` +} diff --git a/tests/ui/structs/struct-field-cfg.stderr b/tests/ui/structs/struct-field-cfg.stderr new file mode 100644 index 000000000..5ec47c093 --- /dev/null +++ b/tests/ui/structs/struct-field-cfg.stderr @@ -0,0 +1,39 @@ +error[E0063]: missing field `present` in initializer of `Foo` + --> $DIR/struct-field-cfg.rs:7:13 + | +LL | let _ = Foo { #[cfg(any())] present: () }; + | ^^^ missing `present` + +error[E0560]: struct `Foo` has no field named `absent` + --> $DIR/struct-field-cfg.rs:10:46 + | +LL | let _ = Foo { present: (), #[cfg(all())] absent: () }; + | ^^^^^^ `Foo` does not have this field + | + = note: available fields are: `present` + +error[E0027]: pattern does not mention field `present` + --> $DIR/struct-field-cfg.rs:13:9 + | +LL | let Foo { #[cfg(any())] present: () } = foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `present` + | +help: include the missing field in the pattern + | +LL | let Foo { present } = foo; + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let Foo { .. } = foo; + | ~~~~~~ + +error[E0026]: struct `Foo` does not have a field named `absent` + --> $DIR/struct-field-cfg.rs:16:42 + | +LL | let Foo { present: (), #[cfg(all())] absent: () } = foo; + | ^^^^^^ struct `Foo` does not have this field + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0026, E0027, E0063, E0560. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/structs/struct-field-init-syntax.rs b/tests/ui/structs/struct-field-init-syntax.rs new file mode 100644 index 000000000..161f7e93a --- /dev/null +++ b/tests/ui/structs/struct-field-init-syntax.rs @@ -0,0 +1,20 @@ +// issue #41834 + +#[derive(Default)] +struct Foo { + one: u8, +} + +fn main() { + let foo = Foo { + one: 111, + ..Foo::default(), + //~^ ERROR cannot use a comma after the base struct + }; + + let foo = Foo { + ..Foo::default(), + //~^ ERROR cannot use a comma after the base struct + one: 111, + }; +} diff --git a/tests/ui/structs/struct-field-init-syntax.stderr b/tests/ui/structs/struct-field-init-syntax.stderr new file mode 100644 index 000000000..0b72c5cf7 --- /dev/null +++ b/tests/ui/structs/struct-field-init-syntax.stderr @@ -0,0 +1,18 @@ +error: cannot use a comma after the base struct + --> $DIR/struct-field-init-syntax.rs:11:9 + | +LL | ..Foo::default(), + | ^^^^^^^^^^^^^^^^- help: remove this comma + | + = note: the base struct must always be the last field + +error: cannot use a comma after the base struct + --> $DIR/struct-field-init-syntax.rs:16:9 + | +LL | ..Foo::default(), + | ^^^^^^^^^^^^^^^^- help: remove this comma + | + = note: the base struct must always be the last field + +error: aborting due to 2 previous errors + diff --git a/tests/ui/structs/struct-field-privacy.rs b/tests/ui/structs/struct-field-privacy.rs new file mode 100644 index 000000000..898ca475c --- /dev/null +++ b/tests/ui/structs/struct-field-privacy.rs @@ -0,0 +1,38 @@ +// aux-build:struct_field_privacy.rs + +extern crate struct_field_privacy as xc; + +struct A { + a: isize, +} + +mod inner { + pub struct A { + a: isize, + pub b: isize, + } + pub struct B { + pub a: isize, + b: isize, + } + pub struct Z(pub isize, isize); +} + +fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B, z: inner::Z) { + a.a; + b.a; //~ ERROR: field `a` of struct `inner::A` is private + b.b; + c.a; + c.b; //~ ERROR: field `b` of struct `inner::B` is private + + d.a; //~ ERROR: field `a` of struct `xc::A` is private + d.b; + + e.a; + e.b; //~ ERROR: field `b` of struct `xc::B` is private + + z.0; + z.1; //~ ERROR: field `1` of struct `Z` is private +} + +fn main() {} diff --git a/tests/ui/structs/struct-field-privacy.stderr b/tests/ui/structs/struct-field-privacy.stderr new file mode 100644 index 000000000..ee83e0d6c --- /dev/null +++ b/tests/ui/structs/struct-field-privacy.stderr @@ -0,0 +1,33 @@ +error[E0616]: field `a` of struct `inner::A` is private + --> $DIR/struct-field-privacy.rs:23:7 + | +LL | b.a; + | ^ private field + +error[E0616]: field `b` of struct `inner::B` is private + --> $DIR/struct-field-privacy.rs:26:7 + | +LL | c.b; + | ^ private field + +error[E0616]: field `a` of struct `xc::A` is private + --> $DIR/struct-field-privacy.rs:28:7 + | +LL | d.a; + | ^ private field + +error[E0616]: field `b` of struct `xc::B` is private + --> $DIR/struct-field-privacy.rs:32:7 + | +LL | e.b; + | ^ private field + +error[E0616]: field `1` of struct `Z` is private + --> $DIR/struct-field-privacy.rs:35:7 + | +LL | z.1; + | ^ private field + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/structs/struct-fields-decl-dupe.rs b/tests/ui/structs/struct-fields-decl-dupe.rs new file mode 100644 index 000000000..6ddf3d976 --- /dev/null +++ b/tests/ui/structs/struct-fields-decl-dupe.rs @@ -0,0 +1,8 @@ +struct BuildData { + foo: isize, + foo: isize, + //~^ ERROR field `foo` is already declared [E0124] +} + +fn main() { +} diff --git a/tests/ui/structs/struct-fields-decl-dupe.stderr b/tests/ui/structs/struct-fields-decl-dupe.stderr new file mode 100644 index 000000000..d7ce9bb89 --- /dev/null +++ b/tests/ui/structs/struct-fields-decl-dupe.stderr @@ -0,0 +1,11 @@ +error[E0124]: field `foo` is already declared + --> $DIR/struct-fields-decl-dupe.rs:3:5 + | +LL | foo: isize, + | ---------- `foo` first declared here +LL | foo: isize, + | ^^^^^^^^^^ field already declared + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/structs/struct-fields-dupe.rs b/tests/ui/structs/struct-fields-dupe.rs new file mode 100644 index 000000000..2fa25a335 --- /dev/null +++ b/tests/ui/structs/struct-fields-dupe.rs @@ -0,0 +1,10 @@ +struct BuildData { + foo: isize, +} + +fn main() { + let foo = BuildData { + foo: 0, + foo: 0 //~ ERROR field `foo` specified more than once + }; +} diff --git a/tests/ui/structs/struct-fields-dupe.stderr b/tests/ui/structs/struct-fields-dupe.stderr new file mode 100644 index 000000000..aaf2533dc --- /dev/null +++ b/tests/ui/structs/struct-fields-dupe.stderr @@ -0,0 +1,11 @@ +error[E0062]: field `foo` specified more than once + --> $DIR/struct-fields-dupe.rs:8:9 + | +LL | foo: 0, + | ------ first use of `foo` +LL | foo: 0 + | ^^^ used more than once + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0062`. diff --git a/tests/ui/structs/struct-fields-hints-no-dupe.rs b/tests/ui/structs/struct-fields-hints-no-dupe.rs new file mode 100644 index 000000000..987cf726f --- /dev/null +++ b/tests/ui/structs/struct-fields-hints-no-dupe.rs @@ -0,0 +1,14 @@ +struct A { + foo : i32, + car : i32, + barr : i32 +} + +fn main() { + let a = A { + foo : 5, + bar : 42, + //~^ ERROR struct `A` has no field named `bar` + car : 9, + }; +} diff --git a/tests/ui/structs/struct-fields-hints-no-dupe.stderr b/tests/ui/structs/struct-fields-hints-no-dupe.stderr new file mode 100644 index 000000000..1a88f2693 --- /dev/null +++ b/tests/ui/structs/struct-fields-hints-no-dupe.stderr @@ -0,0 +1,9 @@ +error[E0560]: struct `A` has no field named `bar` + --> $DIR/struct-fields-hints-no-dupe.rs:10:9 + | +LL | bar : 42, + | ^^^ help: a field with a similar name exists: `barr` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-hints.rs b/tests/ui/structs/struct-fields-hints.rs new file mode 100644 index 000000000..08df0930e --- /dev/null +++ b/tests/ui/structs/struct-fields-hints.rs @@ -0,0 +1,13 @@ +struct A { + foo : i32, + car : i32, + barr : i32 +} + +fn main() { + let a = A { + foo : 5, + bar : 42, + //~^ ERROR struct `A` has no field named `bar` + }; +} diff --git a/tests/ui/structs/struct-fields-hints.stderr b/tests/ui/structs/struct-fields-hints.stderr new file mode 100644 index 000000000..3b8a2b5c7 --- /dev/null +++ b/tests/ui/structs/struct-fields-hints.stderr @@ -0,0 +1,9 @@ +error[E0560]: struct `A` has no field named `bar` + --> $DIR/struct-fields-hints.rs:10:9 + | +LL | bar : 42, + | ^^^ help: a field with a similar name exists: `car` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-missing.rs b/tests/ui/structs/struct-fields-missing.rs new file mode 100644 index 000000000..0c7919d02 --- /dev/null +++ b/tests/ui/structs/struct-fields-missing.rs @@ -0,0 +1,10 @@ +struct BuildData { + foo: isize, + bar: Box, +} + +fn main() { + let foo = BuildData { //~ ERROR missing field `bar` in initializer of `BuildData` + foo: 0 + }; +} diff --git a/tests/ui/structs/struct-fields-missing.stderr b/tests/ui/structs/struct-fields-missing.stderr new file mode 100644 index 000000000..b3e42a948 --- /dev/null +++ b/tests/ui/structs/struct-fields-missing.stderr @@ -0,0 +1,9 @@ +error[E0063]: missing field `bar` in initializer of `BuildData` + --> $DIR/struct-fields-missing.rs:7:15 + | +LL | let foo = BuildData { + | ^^^^^^^^^ missing `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/struct-fields-shorthand-unresolved.rs b/tests/ui/structs/struct-fields-shorthand-unresolved.rs new file mode 100644 index 000000000..caad14916 --- /dev/null +++ b/tests/ui/structs/struct-fields-shorthand-unresolved.rs @@ -0,0 +1,12 @@ +struct Foo { + x: i32, + y: i32 +} + +fn main() { + let x = 0; + let foo = Foo { + x, + y //~ ERROR cannot find value `y` in this scope + }; +} diff --git a/tests/ui/structs/struct-fields-shorthand-unresolved.stderr b/tests/ui/structs/struct-fields-shorthand-unresolved.stderr new file mode 100644 index 000000000..09fc4f7ee --- /dev/null +++ b/tests/ui/structs/struct-fields-shorthand-unresolved.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `y` in this scope + --> $DIR/struct-fields-shorthand-unresolved.rs:10:9 + | +LL | y + | ^ help: a local variable with a similar name exists: `x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/structs/struct-fields-shorthand.rs b/tests/ui/structs/struct-fields-shorthand.rs new file mode 100644 index 000000000..1bdcc8315 --- /dev/null +++ b/tests/ui/structs/struct-fields-shorthand.rs @@ -0,0 +1,11 @@ +struct Foo { + x: i32, + y: i32 +} + +fn main() { + let (x, y, z) = (0, 1, 2); + let foo = Foo { + x, y, z //~ ERROR struct `Foo` has no field named `z` + }; +} diff --git a/tests/ui/structs/struct-fields-shorthand.stderr b/tests/ui/structs/struct-fields-shorthand.stderr new file mode 100644 index 000000000..a285a3921 --- /dev/null +++ b/tests/ui/structs/struct-fields-shorthand.stderr @@ -0,0 +1,11 @@ +error[E0560]: struct `Foo` has no field named `z` + --> $DIR/struct-fields-shorthand.rs:9:15 + | +LL | x, y, z + | ^ `Foo` does not have this field + | + = note: available fields are: `x`, `y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-too-many.rs b/tests/ui/structs/struct-fields-too-many.rs new file mode 100644 index 000000000..8be8dcbf1 --- /dev/null +++ b/tests/ui/structs/struct-fields-too-many.rs @@ -0,0 +1,11 @@ +struct BuildData { + foo: isize, +} + +fn main() { + let foo = BuildData { + foo: 0, + bar: 0 + //~^ ERROR struct `BuildData` has no field named `bar` + }; +} diff --git a/tests/ui/structs/struct-fields-too-many.stderr b/tests/ui/structs/struct-fields-too-many.stderr new file mode 100644 index 000000000..a1b7a7a31 --- /dev/null +++ b/tests/ui/structs/struct-fields-too-many.stderr @@ -0,0 +1,11 @@ +error[E0560]: struct `BuildData` has no field named `bar` + --> $DIR/struct-fields-too-many.rs:8:9 + | +LL | bar: 0 + | ^^^ `BuildData` does not have this field + | + = note: available fields are: `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/struct-fields-typo.rs b/tests/ui/structs/struct-fields-typo.rs new file mode 100644 index 000000000..0e9b2ae51 --- /dev/null +++ b/tests/ui/structs/struct-fields-typo.rs @@ -0,0 +1,15 @@ +struct BuildData { + foo: isize, + bar: f32 +} + +fn main() { + let foo = BuildData { + foo: 0, + bar: 0.5, + }; + let x = foo.baa; //~ ERROR no field `baa` on type `BuildData` + //~| HELP a field with a similar name exists + //~| SUGGESTION bar + println!("{}", x); +} diff --git a/tests/ui/structs/struct-fields-typo.stderr b/tests/ui/structs/struct-fields-typo.stderr new file mode 100644 index 000000000..6949a0a4a --- /dev/null +++ b/tests/ui/structs/struct-fields-typo.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `baa` on type `BuildData` + --> $DIR/struct-fields-typo.rs:11:17 + | +LL | let x = foo.baa; + | ^^^ help: a field with a similar name exists: `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/structs/struct-fn-in-definition.rs b/tests/ui/structs/struct-fn-in-definition.rs new file mode 100644 index 000000000..7f48f55fe --- /dev/null +++ b/tests/ui/structs/struct-fn-in-definition.rs @@ -0,0 +1,34 @@ +// It might be intuitive for a user coming from languages like Java +// to declare a method directly in a struct's definition. Make sure +// rustc can give a helpful suggestion. +// Suggested in issue #76421 + +struct S { + field: usize, + + fn foo() {} + //~^ ERROR functions are not allowed in struct definitions + //~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks + //~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information +} + +union U { + variant: usize, + + fn foo() {} + //~^ ERROR functions are not allowed in union definitions + //~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks + //~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information +} + +enum E { + Variant, + + fn foo() {} + //~^ ERROR functions are not allowed in enum definitions + //~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks + //~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information + //~| HELP enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` +} + +fn main() {} diff --git a/tests/ui/structs/struct-fn-in-definition.stderr b/tests/ui/structs/struct-fn-in-definition.stderr new file mode 100644 index 000000000..439c86ec2 --- /dev/null +++ b/tests/ui/structs/struct-fn-in-definition.stderr @@ -0,0 +1,39 @@ +error: functions are not allowed in struct definitions + --> $DIR/struct-fn-in-definition.rs:9:5 + | +LL | struct S { + | - while parsing this struct +... +LL | fn foo() {} + | ^^^^^^^^^^^ + | + = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks + = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information + +error: functions are not allowed in union definitions + --> $DIR/struct-fn-in-definition.rs:18:5 + | +LL | union U { + | - while parsing this union +... +LL | fn foo() {} + | ^^^^^^^^^^^ + | + = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks + = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information + +error: functions are not allowed in enum definitions + --> $DIR/struct-fn-in-definition.rs:27:5 + | +LL | enum E { + | - while parsing this enum +... +LL | fn foo() {} + | ^^^^^^^^^^^ + | + = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks + = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/structs/struct-missing-comma.fixed b/tests/ui/structs/struct-missing-comma.fixed new file mode 100644 index 000000000..a28179ba2 --- /dev/null +++ b/tests/ui/structs/struct-missing-comma.fixed @@ -0,0 +1,12 @@ +// Issue #50636 +// run-rustfix + +pub struct S { + pub foo: u32, //~ expected `,`, or `}`, found keyword `pub` + // ~^ HELP try adding a comma: ',' + pub bar: u32 +} + +fn main() { + let _ = S { foo: 5, bar: 6 }; +} diff --git a/tests/ui/structs/struct-missing-comma.rs b/tests/ui/structs/struct-missing-comma.rs new file mode 100644 index 000000000..b6d6c9b8f --- /dev/null +++ b/tests/ui/structs/struct-missing-comma.rs @@ -0,0 +1,12 @@ +// Issue #50636 +// run-rustfix + +pub struct S { + pub foo: u32 //~ expected `,`, or `}`, found keyword `pub` + // ~^ HELP try adding a comma: ',' + pub bar: u32 +} + +fn main() { + let _ = S { foo: 5, bar: 6 }; +} diff --git a/tests/ui/structs/struct-missing-comma.stderr b/tests/ui/structs/struct-missing-comma.stderr new file mode 100644 index 000000000..eceec65e7 --- /dev/null +++ b/tests/ui/structs/struct-missing-comma.stderr @@ -0,0 +1,8 @@ +error: expected `,`, or `}`, found keyword `pub` + --> $DIR/struct-missing-comma.rs:5:17 + | +LL | pub foo: u32 + | ^ help: try adding a comma: `,` + +error: aborting due to previous error + diff --git a/tests/ui/structs/struct-pat-derived-error.rs b/tests/ui/structs/struct-pat-derived-error.rs new file mode 100644 index 000000000..f49a8ff8b --- /dev/null +++ b/tests/ui/structs/struct-pat-derived-error.rs @@ -0,0 +1,14 @@ +struct A { + b: usize, + c: usize +} + +impl A { + fn foo(&self) { + let A { x, y } = self.d; //~ ERROR no field `d` on type `&A` + //~^ ERROR struct `A` does not have fields named `x`, `y` + //~| ERROR pattern does not mention fields `b`, `c` + } +} + +fn main() {} diff --git a/tests/ui/structs/struct-pat-derived-error.stderr b/tests/ui/structs/struct-pat-derived-error.stderr new file mode 100644 index 000000000..a91e47657 --- /dev/null +++ b/tests/ui/structs/struct-pat-derived-error.stderr @@ -0,0 +1,31 @@ +error[E0609]: no field `d` on type `&A` + --> $DIR/struct-pat-derived-error.rs:8:31 + | +LL | let A { x, y } = self.d; + | ^ help: a field with a similar name exists: `b` + +error[E0026]: struct `A` does not have fields named `x`, `y` + --> $DIR/struct-pat-derived-error.rs:8:17 + | +LL | let A { x, y } = self.d; + | ^ ^ struct `A` does not have these fields + +error[E0027]: pattern does not mention fields `b`, `c` + --> $DIR/struct-pat-derived-error.rs:8:13 + | +LL | let A { x, y } = self.d; + | ^^^^^^^^^^ missing fields `b`, `c` + | +help: include the missing fields in the pattern + | +LL | let A { x, y, b, c } = self.d; + | ~~~~~~~~ +help: if you don't care about these missing fields, you can explicitly ignore them + | +LL | let A { x, y, .. } = self.d; + | ~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0026, E0027, E0609. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/structs/struct-path-alias-bounds.rs b/tests/ui/structs/struct-path-alias-bounds.rs new file mode 100644 index 000000000..1e2c4b836 --- /dev/null +++ b/tests/ui/structs/struct-path-alias-bounds.rs @@ -0,0 +1,11 @@ +// issue #36286 + +struct S { a: T } + +struct NoClone; +type A = S; + +fn main() { + let s = A { a: NoClone }; + //~^ ERROR the trait bound `NoClone: Clone` is not satisfied +} diff --git a/tests/ui/structs/struct-path-alias-bounds.stderr b/tests/ui/structs/struct-path-alias-bounds.stderr new file mode 100644 index 000000000..266291f62 --- /dev/null +++ b/tests/ui/structs/struct-path-alias-bounds.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `NoClone: Clone` is not satisfied + --> $DIR/struct-path-alias-bounds.rs:9:13 + | +LL | let s = A { a: NoClone }; + | ^ the trait `Clone` is not implemented for `NoClone` + | +note: required by a bound in `S` + --> $DIR/struct-path-alias-bounds.rs:3:13 + | +LL | struct S { a: T } + | ^^^^^ required by this bound in `S` +help: consider annotating `NoClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/structs/struct-path-associated-type.rs b/tests/ui/structs/struct-path-associated-type.rs new file mode 100644 index 000000000..2dd7174a9 --- /dev/null +++ b/tests/ui/structs/struct-path-associated-type.rs @@ -0,0 +1,37 @@ +struct S; + +trait Tr { + type A; +} + +impl Tr for S { + type A = S; +} + +fn f() { + let s = T::A {}; + //~^ ERROR expected struct, variant or union type, found associated type + let z = T::A:: {}; + //~^ ERROR expected struct, variant or union type, found associated type + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied + match S { + T::A {} => {} + //~^ ERROR expected struct, variant or union type, found associated type + } +} + +fn g>() { + let s = T::A {}; // OK + let z = T::A:: {}; //~ ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied + match S { + T::A {} => {} // OK + } +} + +fn main() { + let s = S::A {}; //~ ERROR ambiguous associated type + let z = S::A:: {}; //~ ERROR ambiguous associated type + match S { + S::A {} => {} //~ ERROR ambiguous associated type + } +} diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr new file mode 100644 index 000000000..ca5f0b7e2 --- /dev/null +++ b/tests/ui/structs/struct-path-associated-type.stderr @@ -0,0 +1,68 @@ +error[E0071]: expected struct, variant or union type, found associated type + --> $DIR/struct-path-associated-type.rs:12:13 + | +LL | let s = T::A {}; + | ^^^^ not a struct + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/struct-path-associated-type.rs:14:16 + | +LL | let z = T::A:: {}; + | ^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/struct-path-associated-type.rs:4:10 + | +LL | type A; + | ^ + +error[E0071]: expected struct, variant or union type, found associated type + --> $DIR/struct-path-associated-type.rs:14:13 + | +LL | let z = T::A:: {}; + | ^^^^ not a struct + +error[E0071]: expected struct, variant or union type, found associated type + --> $DIR/struct-path-associated-type.rs:18:9 + | +LL | T::A {} => {} + | ^^^^ not a struct + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/struct-path-associated-type.rs:25:16 + | +LL | let z = T::A:: {}; + | ^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/struct-path-associated-type.rs:4:10 + | +LL | type A; + | ^ + +error[E0223]: ambiguous associated type + --> $DIR/struct-path-associated-type.rs:32:13 + | +LL | let s = S::A {}; + | ^^^^ help: use the fully-qualified path: `::A` + +error[E0223]: ambiguous associated type + --> $DIR/struct-path-associated-type.rs:33:13 + | +LL | let z = S::A:: {}; + | ^^^^ help: use the fully-qualified path: `::A` + +error[E0223]: ambiguous associated type + --> $DIR/struct-path-associated-type.rs:35:9 + | +LL | S::A {} => {} + | ^^^^ help: use the fully-qualified path: `::A` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0071, E0107, E0223. +For more information about an error, try `rustc --explain E0071`. diff --git a/tests/ui/structs/struct-path-self-type-mismatch.rs b/tests/ui/structs/struct-path-self-type-mismatch.rs new file mode 100644 index 000000000..c0c557eca --- /dev/null +++ b/tests/ui/structs/struct-path-self-type-mismatch.rs @@ -0,0 +1,21 @@ +struct Foo { inner: A } + +trait Bar { fn bar(); } + +impl Bar for Foo { + fn bar() { + Self { inner: 1.5f32 }; //~ ERROR mismatched types + } +} + +impl Foo { + fn new(u: U) -> Foo { + Self { + //~^ ERROR mismatched types + inner: u + //~^ ERROR mismatched types + } + } +} + +fn main() {} diff --git a/tests/ui/structs/struct-path-self-type-mismatch.stderr b/tests/ui/structs/struct-path-self-type-mismatch.stderr new file mode 100644 index 000000000..b55a2cbf7 --- /dev/null +++ b/tests/ui/structs/struct-path-self-type-mismatch.stderr @@ -0,0 +1,46 @@ +error[E0308]: mismatched types + --> $DIR/struct-path-self-type-mismatch.rs:7:23 + | +LL | Self { inner: 1.5f32 }; + | ^^^^^^ expected `i32`, found `f32` + +error[E0308]: mismatched types + --> $DIR/struct-path-self-type-mismatch.rs:15:20 + | +LL | impl Foo { + | - expected type parameter +LL | fn new(u: U) -> Foo { + | - found type parameter +... +LL | inner: u + | ^ expected type parameter `T`, found type parameter `U` + | + = note: expected type parameter `T` + found type parameter `U` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error[E0308]: mismatched types + --> $DIR/struct-path-self-type-mismatch.rs:13:9 + | +LL | impl Foo { + | - found type parameter +LL | fn new(u: U) -> Foo { + | - ------ expected `Foo` because of return type + | | + | expected type parameter +LL | / Self { +LL | | +LL | | inner: u +LL | | +LL | | } + | |_________^ expected type parameter `U`, found type parameter `T` + | + = note: expected struct `Foo` + found struct `Foo` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/structs/struct-path-self.rs b/tests/ui/structs/struct-path-self.rs new file mode 100644 index 000000000..6e529c7ed --- /dev/null +++ b/tests/ui/structs/struct-path-self.rs @@ -0,0 +1,37 @@ +struct S; + +trait Tr { + fn f() { + let s = Self {}; + //~^ ERROR expected struct, variant or union type, found type parameter + let z = Self:: {}; + //~^ ERROR expected struct, variant or union type, found type parameter + //~| ERROR type arguments are not allowed on self type + match s { + Self { .. } => {} + //~^ ERROR expected struct, variant or union type, found type parameter + } + } +} + +impl Tr for S { + fn f() { + let s = Self {}; // OK + let z = Self:: {}; //~ ERROR type arguments are not allowed on self type + match s { + Self { .. } => {} // OK + } + } +} + +impl S { + fn g() { + let s = Self {}; // OK + let z = Self:: {}; //~ ERROR type arguments are not allowed on self type + match s { + Self { .. } => {} // OK + } + } +} + +fn main() {} diff --git a/tests/ui/structs/struct-path-self.stderr b/tests/ui/structs/struct-path-self.stderr new file mode 100644 index 000000000..c2a8623f9 --- /dev/null +++ b/tests/ui/structs/struct-path-self.stderr @@ -0,0 +1,80 @@ +error[E0071]: expected struct, variant or union type, found type parameter `Self` + --> $DIR/struct-path-self.rs:5:17 + | +LL | let s = Self {}; + | ^^^^ not a struct + +error[E0109]: type arguments are not allowed on self type + --> $DIR/struct-path-self.rs:7:24 + | +LL | let z = Self:: {}; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +help: the `Self` type doesn't accept type parameters + | +LL - let z = Self:: {}; +LL + let z = Self {}; + | + +error[E0071]: expected struct, variant or union type, found type parameter `Self` + --> $DIR/struct-path-self.rs:7:17 + | +LL | let z = Self:: {}; + | ^^^^^^^^^^ not a struct + +error[E0071]: expected struct, variant or union type, found type parameter `Self` + --> $DIR/struct-path-self.rs:11:13 + | +LL | Self { .. } => {} + | ^^^^ not a struct + +error[E0109]: type arguments are not allowed on self type + --> $DIR/struct-path-self.rs:20:24 + | +LL | let z = Self:: {}; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `S` + --> $DIR/struct-path-self.rs:1:8 + | +LL | struct S; + | ^ `Self` corresponds to this type, which doesn't have generic parameters +... +LL | impl Tr for S { + | ------------- `Self` is on type `S` in this `impl` +help: the `Self` type doesn't accept type parameters + | +LL - let z = Self:: {}; +LL + let z = Self {}; + | + +error[E0109]: type arguments are not allowed on self type + --> $DIR/struct-path-self.rs:30:24 + | +LL | let z = Self:: {}; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `S` + --> $DIR/struct-path-self.rs:1:8 + | +LL | struct S; + | ^ `Self` corresponds to this type, which doesn't have generic parameters +... +LL | impl S { + | ------ `Self` is on type `S` in this `impl` +help: the `Self` type doesn't accept type parameters + | +LL - let z = Self:: {}; +LL + let z = Self {}; + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0071, E0109. +For more information about an error, try `rustc --explain E0071`. diff --git a/tests/ui/structs/struct-record-suggestion.fixed b/tests/ui/structs/struct-record-suggestion.fixed new file mode 100644 index 000000000..d93a62185 --- /dev/null +++ b/tests/ui/structs/struct-record-suggestion.fixed @@ -0,0 +1,33 @@ +// run-rustfix +#[derive(Debug, Default, Eq, PartialEq)] +struct A { + b: u32, + c: u64, + d: usize, +} + +fn a() { + let q = A { c: 5, ..Default::default() }; + //~^ ERROR missing fields + //~| HELP separate the last named field with a comma + let r = A { c: 5, ..Default::default() }; + assert_eq!(q, r); +} + +#[derive(Debug, Default, Eq, PartialEq)] +struct B { + b: u32, +} + +fn b() { + let q = B { b: 1, ..Default::default() }; + //~^ ERROR mismatched types + //~| HELP separate the last named field with a comma + let r = B { b: 1 }; + assert_eq!(q, r); +} + +fn main() { + a(); + b(); +} diff --git a/tests/ui/structs/struct-record-suggestion.rs b/tests/ui/structs/struct-record-suggestion.rs new file mode 100644 index 000000000..f0fd1c94e --- /dev/null +++ b/tests/ui/structs/struct-record-suggestion.rs @@ -0,0 +1,33 @@ +// run-rustfix +#[derive(Debug, Default, Eq, PartialEq)] +struct A { + b: u32, + c: u64, + d: usize, +} + +fn a() { + let q = A { c: 5..Default::default() }; + //~^ ERROR missing fields + //~| HELP separate the last named field with a comma + let r = A { c: 5, ..Default::default() }; + assert_eq!(q, r); +} + +#[derive(Debug, Default, Eq, PartialEq)] +struct B { + b: u32, +} + +fn b() { + let q = B { b: 1..Default::default() }; + //~^ ERROR mismatched types + //~| HELP separate the last named field with a comma + let r = B { b: 1 }; + assert_eq!(q, r); +} + +fn main() { + a(); + b(); +} diff --git a/tests/ui/structs/struct-record-suggestion.stderr b/tests/ui/structs/struct-record-suggestion.stderr new file mode 100644 index 000000000..9b751d1b6 --- /dev/null +++ b/tests/ui/structs/struct-record-suggestion.stderr @@ -0,0 +1,38 @@ +error[E0063]: missing fields `b` and `d` in initializer of `A` + --> $DIR/struct-record-suggestion.rs:10:13 + | +LL | let q = A { c: 5..Default::default() }; + | ^ missing `b` and `d` + | +note: this expression may have been misinterpreted as a `..` range expression + --> $DIR/struct-record-suggestion.rs:10:20 + | +LL | let q = A { c: 5..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ +help: to set the remaining fields from `Default::default()`, separate the last named field with a comma + | +LL | let q = A { c: 5, ..Default::default() }; + | + + +error[E0308]: mismatched types + --> $DIR/struct-record-suggestion.rs:23:20 + | +LL | let q = B { b: 1..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `Range` + | + = note: expected type `u32` + found struct `std::ops::Range<{integer}>` +note: this expression may have been misinterpreted as a `..` range expression + --> $DIR/struct-record-suggestion.rs:23:20 + | +LL | let q = B { b: 1..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ +help: to set the remaining fields from `Default::default()`, separate the last named field with a comma + | +LL | let q = B { b: 1, ..Default::default() }; + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0063, E0308. +For more information about an error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/struct-tuple-field-names.rs b/tests/ui/structs/struct-tuple-field-names.rs new file mode 100644 index 000000000..7bd54af1d --- /dev/null +++ b/tests/ui/structs/struct-tuple-field-names.rs @@ -0,0 +1,15 @@ +struct S(i32, f32); +enum E { + S(i32, f32), +} +fn main() { + let x = E::S(1, 2.2); + match x { + E::S { 0, 1 } => {} + //~^ ERROR tuple variant `E::S` written as struct variant [E0769] + } + let y = S(1, 2.2); + match y { + S { } => {} //~ ERROR: tuple variant `S` written as struct variant [E0769] + } +} diff --git a/tests/ui/structs/struct-tuple-field-names.stderr b/tests/ui/structs/struct-tuple-field-names.stderr new file mode 100644 index 000000000..5494c29a6 --- /dev/null +++ b/tests/ui/structs/struct-tuple-field-names.stderr @@ -0,0 +1,25 @@ +error[E0769]: tuple variant `E::S` written as struct variant + --> $DIR/struct-tuple-field-names.rs:8:9 + | +LL | E::S { 0, 1 } => {} + | ^^^^^^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | E::S(_, _) => {} + | ~~~~~~ + +error[E0769]: tuple variant `S` written as struct variant + --> $DIR/struct-tuple-field-names.rs:13:9 + | +LL | S { } => {} + | ^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | S(_, _) => {} + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/structs/struct-variant-privacy-xc.rs b/tests/ui/structs/struct-variant-privacy-xc.rs new file mode 100644 index 000000000..763ab9527 --- /dev/null +++ b/tests/ui/structs/struct-variant-privacy-xc.rs @@ -0,0 +1,11 @@ +// aux-build:struct_variant_privacy.rs +extern crate struct_variant_privacy; + +fn f(b: struct_variant_privacy::Bar) { + //~^ ERROR enum `Bar` is private + match b { + struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private + } +} + +fn main() {} diff --git a/tests/ui/structs/struct-variant-privacy-xc.stderr b/tests/ui/structs/struct-variant-privacy-xc.stderr new file mode 100644 index 000000000..1c1caaef8 --- /dev/null +++ b/tests/ui/structs/struct-variant-privacy-xc.stderr @@ -0,0 +1,27 @@ +error[E0603]: enum `Bar` is private + --> $DIR/struct-variant-privacy-xc.rs:4:33 + | +LL | fn f(b: struct_variant_privacy::Bar) { + | ^^^ private enum + | +note: the enum `Bar` is defined here + --> $DIR/auxiliary/struct_variant_privacy.rs:1:1 + | +LL | enum Bar { + | ^^^^^^^^ + +error[E0603]: enum `Bar` is private + --> $DIR/struct-variant-privacy-xc.rs:7:33 + | +LL | struct_variant_privacy::Bar::Baz { a: _a } => {} + | ^^^ private enum + | +note: the enum `Bar` is defined here + --> $DIR/auxiliary/struct_variant_privacy.rs:1:1 + | +LL | enum Bar { + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/structs/struct-variant-privacy.rs b/tests/ui/structs/struct-variant-privacy.rs new file mode 100644 index 000000000..fcdf9a22b --- /dev/null +++ b/tests/ui/structs/struct-variant-privacy.rs @@ -0,0 +1,14 @@ +mod foo { + enum Bar { + Baz { a: isize }, + } +} + +fn f(b: foo::Bar) { + //~^ ERROR enum `Bar` is private + match b { + foo::Bar::Baz { a: _a } => {} //~ ERROR enum `Bar` is private + } +} + +fn main() {} diff --git a/tests/ui/structs/struct-variant-privacy.stderr b/tests/ui/structs/struct-variant-privacy.stderr new file mode 100644 index 000000000..eafd26c71 --- /dev/null +++ b/tests/ui/structs/struct-variant-privacy.stderr @@ -0,0 +1,27 @@ +error[E0603]: enum `Bar` is private + --> $DIR/struct-variant-privacy.rs:7:14 + | +LL | fn f(b: foo::Bar) { + | ^^^ private enum + | +note: the enum `Bar` is defined here + --> $DIR/struct-variant-privacy.rs:2:5 + | +LL | enum Bar { + | ^^^^^^^^ + +error[E0603]: enum `Bar` is private + --> $DIR/struct-variant-privacy.rs:10:14 + | +LL | foo::Bar::Baz { a: _a } => {} + | ^^^ private enum + | +note: the enum `Bar` is defined here + --> $DIR/struct-variant-privacy.rs:2:5 + | +LL | enum Bar { + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/structs/structure-constructor-type-mismatch.rs b/tests/ui/structs/structure-constructor-type-mismatch.rs new file mode 100644 index 000000000..a03ef590c --- /dev/null +++ b/tests/ui/structs/structure-constructor-type-mismatch.rs @@ -0,0 +1,73 @@ +struct Point { + x: T, + y: T, +} + +type PointF = Point; + +struct Pair { + x: T, + y: U, +} + +type PairF = Pair; + +fn main() { + let pt = PointF { + x: 1, + //~^ ERROR mismatched types + //~| expected `f32`, found integer + y: 2, + //~^ ERROR mismatched types + //~| expected `f32`, found integer + }; + + let pt2 = Point:: { + x: 3, + //~^ ERROR mismatched types + //~| expected `f32`, found integer + y: 4, + //~^ ERROR mismatched types + //~| expected `f32`, found integer + }; + + let pair = PairF { + x: 5, + //~^ ERROR mismatched types + //~| expected `f32`, found integer + y: 6, + }; + + let pair2 = PairF:: { + x: 7, + //~^ ERROR mismatched types + //~| expected `f32`, found integer + y: 8, + }; + + let pt3 = PointF:: { //~ ERROR this type alias takes 0 generic arguments but 1 generic argument + x: 9, //~ ERROR mismatched types + y: 10, //~ ERROR mismatched types + }; + + match (Point { x: 1, y: 2 }) { + PointF:: { .. } => {} //~ ERROR this type alias takes 0 generic arguments but 1 generic argument + //~^ ERROR mismatched types + } + + match (Point { x: 1, y: 2 }) { + PointF { .. } => {} //~ ERROR mismatched types + } + + match (Point { x: 1.0, y: 2.0 }) { + PointF { .. } => {} // ok + } + + match (Pair { x: 1, y: 2 }) { + PairF:: { .. } => {} //~ ERROR mismatched types + } + + match (Pair { x: 1.0, y: 2 }) { + PairF:: { .. } => {} // ok + } +} diff --git a/tests/ui/structs/structure-constructor-type-mismatch.stderr b/tests/ui/structs/structure-constructor-type-mismatch.stderr new file mode 100644 index 000000000..3d64fc601 --- /dev/null +++ b/tests/ui/structs/structure-constructor-type-mismatch.stderr @@ -0,0 +1,137 @@ +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:17:12 + | +LL | x: 1, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `1.0` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:20:12 + | +LL | y: 2, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `2.0` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:26:12 + | +LL | x: 3, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `3.0` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:29:12 + | +LL | y: 4, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `4.0` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:35:12 + | +LL | x: 5, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `5.0` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:42:12 + | +LL | x: 7, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `7.0` + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/structure-constructor-type-mismatch.rs:48:15 + | +LL | let pt3 = PointF:: { + | ^^^^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/structure-constructor-type-mismatch.rs:6:6 + | +LL | type PointF = Point; + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:49:12 + | +LL | x: 9, + | ^ + | | + | expected `f32`, found integer + | help: use a float literal: `9.0` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:50:12 + | +LL | y: 10, + | ^^ + | | + | expected `f32`, found integer + | help: use a float literal: `10.0` + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/structure-constructor-type-mismatch.rs:54:9 + | +LL | PointF:: { .. } => {} + | ^^^^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/structure-constructor-type-mismatch.rs:6:6 + | +LL | type PointF = Point; + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:54:9 + | +LL | match (Point { x: 1, y: 2 }) { + | ---------------------- this expression has type `Point<{integer}>` +LL | PointF:: { .. } => {} + | ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32` + | + = note: expected struct `Point<{integer}>` + found struct `Point` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:59:9 + | +LL | match (Point { x: 1, y: 2 }) { + | ---------------------- this expression has type `Point<{integer}>` +LL | PointF { .. } => {} + | ^^^^^^^^^^^^^ expected integer, found `f32` + | + = note: expected struct `Point<{integer}>` + found struct `Point` + +error[E0308]: mismatched types + --> $DIR/structure-constructor-type-mismatch.rs:67:9 + | +LL | match (Pair { x: 1, y: 2 }) { + | --------------------- this expression has type `Pair<{integer}, {integer}>` +LL | PairF:: { .. } => {} + | ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32` + | + = note: expected struct `Pair<{integer}, {integer}>` + found struct `Pair` + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0107, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/structs/suggest-private-fields.rs b/tests/ui/structs/suggest-private-fields.rs new file mode 100644 index 000000000..8267a82fe --- /dev/null +++ b/tests/ui/structs/suggest-private-fields.rs @@ -0,0 +1,27 @@ +// aux-build:struct_field_privacy.rs + +extern crate struct_field_privacy as xc; + +use xc::B; + +struct A { + pub a: u32, + b: u32, +} + +fn main () { + // external crate struct + let k = B { + aa: 20, + //~^ ERROR struct `B` has no field named `aa` + bb: 20, + //~^ ERROR struct `B` has no field named `bb` + }; + // local crate struct + let l = A { + aa: 20, + //~^ ERROR struct `A` has no field named `aa` + bb: 20, + //~^ ERROR struct `A` has no field named `bb` + }; +} diff --git a/tests/ui/structs/suggest-private-fields.stderr b/tests/ui/structs/suggest-private-fields.stderr new file mode 100644 index 000000000..d628bd162 --- /dev/null +++ b/tests/ui/structs/suggest-private-fields.stderr @@ -0,0 +1,29 @@ +error[E0560]: struct `B` has no field named `aa` + --> $DIR/suggest-private-fields.rs:15:9 + | +LL | aa: 20, + | ^^ help: a field with a similar name exists: `a` + +error[E0560]: struct `B` has no field named `bb` + --> $DIR/suggest-private-fields.rs:17:9 + | +LL | bb: 20, + | ^^ `B` does not have this field + | + = note: available fields are: `a` + +error[E0560]: struct `A` has no field named `aa` + --> $DIR/suggest-private-fields.rs:22:9 + | +LL | aa: 20, + | ^^ help: a field with a similar name exists: `a` + +error[E0560]: struct `A` has no field named `bb` + --> $DIR/suggest-private-fields.rs:24:9 + | +LL | bb: 20, + | ^^ help: a field with a similar name exists: `b` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0560`. diff --git a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs new file mode 100644 index 000000000..dd2fe7973 --- /dev/null +++ b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs @@ -0,0 +1,28 @@ +enum Foo { + Bar { a: u8, b: i8, c: u8 }, + Baz { a: f32 }, + None, +} + +fn main() { + let foo = Foo::None; + match foo { + Foo::Bar { a, aa: 1, c } => (), + //~^ ERROR variant `Foo::Bar` does not have a field named `aa` [E0026] + //~| ERROR pattern does not mention field `b` [E0027] + Foo::Baz { bb: 1.0 } => (), + //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026] + //~| ERROR pattern does not mention field `a` [E0027] + _ => (), + } + + match foo { + Foo::Bar { a, aa: "", c } => (), + //~^ ERROR variant `Foo::Bar` does not have a field named `aa` [E0026] + //~| ERROR pattern does not mention field `b` [E0027] + Foo::Baz { bb: "" } => (), + //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026] + //~| pattern does not mention field `a` [E0027] + _ => (), + } +} diff --git a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr new file mode 100644 index 000000000..e8503f540 --- /dev/null +++ b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr @@ -0,0 +1,94 @@ +error[E0026]: variant `Foo::Bar` does not have a field named `aa` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:10:23 + | +LL | Foo::Bar { a, aa: 1, c } => (), + | ^^ + | | + | variant `Foo::Bar` does not have this field + | help: `Foo::Bar` has a field named `b` + +error[E0027]: pattern does not mention field `b` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:10:9 + | +LL | Foo::Bar { a, aa: 1, c } => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `b` + | +help: include the missing field in the pattern + | +LL | Foo::Bar { a, aa: 1, c, b } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Bar { a, aa: 1, c, .. } => (), + | ~~~~~~ + +error[E0026]: variant `Foo::Baz` does not have a field named `bb` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:13:20 + | +LL | Foo::Baz { bb: 1.0 } => (), + | ^^ + | | + | variant `Foo::Baz` does not have this field + | help: `Foo::Baz` has a field named `a` + +error[E0027]: pattern does not mention field `a` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:13:9 + | +LL | Foo::Baz { bb: 1.0 } => (), + | ^^^^^^^^^^^^^^^^^^^^ missing field `a` + | +help: include the missing field in the pattern + | +LL | Foo::Baz { bb: 1.0, a } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Baz { bb: 1.0, .. } => (), + | ~~~~~~ + +error[E0026]: variant `Foo::Bar` does not have a field named `aa` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:20:23 + | +LL | Foo::Bar { a, aa: "", c } => (), + | ^^ variant `Foo::Bar` does not have this field + +error[E0027]: pattern does not mention field `b` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:20:9 + | +LL | Foo::Bar { a, aa: "", c } => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `b` + | +help: include the missing field in the pattern + | +LL | Foo::Bar { a, aa: "", c, b } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Bar { a, aa: "", c, .. } => (), + | ~~~~~~ + +error[E0026]: variant `Foo::Baz` does not have a field named `bb` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:23:20 + | +LL | Foo::Baz { bb: "" } => (), + | ^^ variant `Foo::Baz` does not have this field + +error[E0027]: pattern does not mention field `a` + --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:23:9 + | +LL | Foo::Baz { bb: "" } => (), + | ^^^^^^^^^^^^^^^^^^^ missing field `a` + | +help: include the missing field in the pattern + | +LL | Foo::Baz { bb: "", a } => (), + | ~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | Foo::Baz { bb: "", .. } => (), + | ~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0026, E0027. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/structs/unresolved-struct-with-fru.rs b/tests/ui/structs/unresolved-struct-with-fru.rs new file mode 100644 index 000000000..c9fdca457 --- /dev/null +++ b/tests/ui/structs/unresolved-struct-with-fru.rs @@ -0,0 +1,12 @@ +struct S { + a: u32, +} + +fn main() { + let s1 = S { a: 1 }; + + let _ = || { + let s2 = Oops { a: 2, ..s1 }; + //~^ ERROR cannot find struct, variant or union type `Oops` in this scope + }; +} diff --git a/tests/ui/structs/unresolved-struct-with-fru.stderr b/tests/ui/structs/unresolved-struct-with-fru.stderr new file mode 100644 index 000000000..a5796a222 --- /dev/null +++ b/tests/ui/structs/unresolved-struct-with-fru.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `Oops` in this scope + --> $DIR/unresolved-struct-with-fru.rs:9:18 + | +LL | let s2 = Oops { a: 2, ..s1 }; + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. diff --git a/tests/ui/suggestions/abi-typo.fixed b/tests/ui/suggestions/abi-typo.fixed new file mode 100644 index 000000000..04d265865 --- /dev/null +++ b/tests/ui/suggestions/abi-typo.fixed @@ -0,0 +1,6 @@ +// run-rustfix +extern "cdecl" fn cdedl() {} //~ ERROR invalid ABI + +fn main() { + cdedl(); +} diff --git a/tests/ui/suggestions/abi-typo.rs b/tests/ui/suggestions/abi-typo.rs new file mode 100644 index 000000000..6d80db522 --- /dev/null +++ b/tests/ui/suggestions/abi-typo.rs @@ -0,0 +1,6 @@ +// run-rustfix +extern "cdedl" fn cdedl() {} //~ ERROR invalid ABI + +fn main() { + cdedl(); +} diff --git a/tests/ui/suggestions/abi-typo.stderr b/tests/ui/suggestions/abi-typo.stderr new file mode 100644 index 000000000..67a84f119 --- /dev/null +++ b/tests/ui/suggestions/abi-typo.stderr @@ -0,0 +1,14 @@ +error[E0703]: invalid ABI: found `cdedl` + --> $DIR/abi-typo.rs:2:8 + | +LL | extern "cdedl" fn cdedl() {} + | ^^^^^^^ + | | + | invalid ABI + | help: did you mean: `"cdecl"` + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs new file mode 100644 index 000000000..ef64d799b --- /dev/null +++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.rs @@ -0,0 +1,28 @@ +trait Trait { + fn func1() -> Struct1; //~ ERROR E0277 + fn func2<'a>() -> Struct2<'a, Self>; //~ ERROR E0277 + fn func3() -> Struct3; //~ ERROR E0277 + fn func4() -> Struct4; //~ ERROR E0277 +} + +struct Struct1{ + _t: std::marker::PhantomData<*const T>, +} +struct Struct2<'a, T>{ + _t: &'a T, +} +struct Struct3{ + _t: T, +} + +struct X(T); + +struct Struct4{ + _t: X, +} + +struct Struct5{ + _t: X, //~ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr new file mode 100644 index 000000000..b77c8c7fd --- /dev/null +++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -0,0 +1,112 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:25:9 + | +LL | struct Struct5{ + | - this type parameter needs to be `std::marker::Sized` +LL | _t: X, + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `X` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X(T); + | ^ required by this bound in `X` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 + | +LL | struct X(T); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Struct5{ +LL + struct Struct5{ + | + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:2:19 + | +LL | fn func1() -> Struct1; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct1` + --> $DIR/adt-param-with-implicit-sized-bound.rs:8:16 + | +LL | struct Struct1{ + | ^ required by this bound in `Struct1` +help: consider further restricting `Self` + | +LL | fn func1() -> Struct1 where Self: Sized; + | +++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct1{ + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:3:23 + | +LL | fn func2<'a>() -> Struct2<'a, Self>; + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct2` + --> $DIR/adt-param-with-implicit-sized-bound.rs:11:20 + | +LL | struct Struct2<'a, T>{ + | ^ required by this bound in `Struct2` +help: consider further restricting `Self` + | +LL | fn func2<'a>() -> Struct2<'a, Self> where Self: Sized; + | +++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct2<'a, T: ?Sized>{ + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:4:19 + | +LL | fn func3() -> Struct3; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct3` + --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 + | +LL | struct Struct3{ + | ^ required by this bound in `Struct3` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 + | +LL | struct Struct3{ + | ^ this could be changed to `T: ?Sized`... +LL | _t: T, + | - ...if indirection were used here: `Box` +help: consider further restricting `Self` + | +LL | fn func3() -> Struct3 where Self: Sized; + | +++++++++++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/adt-param-with-implicit-sized-bound.rs:5:19 + | +LL | fn func4() -> Struct4; + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Struct4` + --> $DIR/adt-param-with-implicit-sized-bound.rs:20:16 + | +LL | struct Struct4{ + | ^ required by this bound in `Struct4` +help: consider further restricting `Self` + | +LL | fn func4() -> Struct4 where Self: Sized; + | +++++++++++++++++ +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Struct4{ + | ++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.rs b/tests/ui/suggestions/args-instead-of-tuple-errors.rs new file mode 100644 index 000000000..f5931a1ba --- /dev/null +++ b/tests/ui/suggestions/args-instead-of-tuple-errors.rs @@ -0,0 +1,22 @@ +// Ensure we don't suggest tuple-wrapping when we'd end up with a type error + +fn main() { + // we shouldn't suggest to fix these - `2` isn't a `bool` + + let _: Option<(i32, bool)> = Some(1, 2); + //~^ ERROR this enum variant takes 1 argument but 2 arguments were supplied + int_bool(1, 2); + //~^ ERROR function takes 1 argument but 2 arguments were supplied + + let _: Option<(i8,)> = Some(); + //~^ ERROR this enum variant takes 1 argument but 0 arguments were supplied + + let _: Option<(i32,)> = Some(5_usize); + //~^ ERROR mismatched types + + let _: Option<(i32,)> = Some((5_usize)); + //~^ ERROR mismatched types +} + +fn int_bool(_: (i32, bool)) { +} diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr new file mode 100644 index 000000000..bc097bf6e --- /dev/null +++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -0,0 +1,107 @@ +error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple-errors.rs:6:34 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^^^^ - argument of type `{integer}` unexpected + | +note: expected tuple, found integer + --> $DIR/args-instead-of-tuple-errors.rs:6:39 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^ + = note: expected tuple `(i32, bool)` + found type `{integer}` +help: the type constructed contains `{integer}` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:6:34 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^^^^^-^^^^ + | | + | this argument influences the type of `Some` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: remove the extra argument + | +LL | let _: Option<(i32, bool)> = Some(/* (i32, bool) */); + | ~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple-errors.rs:8:5 + | +LL | int_bool(1, 2); + | ^^^^^^^^ - argument of type `{integer}` unexpected + | +note: expected tuple, found integer + --> $DIR/args-instead-of-tuple-errors.rs:8:14 + | +LL | int_bool(1, 2); + | ^ + = note: expected tuple `(i32, bool)` + found type `{integer}` +note: function defined here + --> $DIR/args-instead-of-tuple-errors.rs:21:4 + | +LL | fn int_bool(_: (i32, bool)) { + | ^^^^^^^^ -------------- +help: remove the extra argument + | +LL | int_bool(/* (i32, bool) */); + | ~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/args-instead-of-tuple-errors.rs:11:28 + | +LL | let _: Option<(i8,)> = Some(); + | ^^^^-- an argument of type `(i8,)` is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: provide the argument + | +LL | let _: Option<(i8,)> = Some(/* (i8,) */); + | ~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple-errors.rs:14:34 + | +LL | let _: Option<(i32,)> = Some(5_usize); + | ---- ^^^^^^^ expected tuple, found `usize` + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `usize` +help: the type constructed contains `usize` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:14:29 + | +LL | let _: Option<(i32,)> = Some(5_usize); + | ^^^^^-------^ + | | + | this argument influences the type of `Some` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple-errors.rs:17:34 + | +LL | let _: Option<(i32,)> = Some((5_usize)); + | ---- ^^^^^^^^^ expected tuple, found `usize` + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `usize` +help: the type constructed contains `usize` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:17:29 + | +LL | let _: Option<(i32,)> = Some((5_usize)); + | ^^^^^---------^ + | | + | this argument influences the type of `Some` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/suggestions/args-instead-of-tuple.fixed b/tests/ui/suggestions/args-instead-of-tuple.fixed new file mode 100644 index 000000000..f913995d7 --- /dev/null +++ b/tests/ui/suggestions/args-instead-of-tuple.fixed @@ -0,0 +1,33 @@ +// Test suggesting tuples where bare arguments may have been passed +// See issue #86481 for details. + +// run-rustfix + +fn main() { + let _: Result<(i32, i8), ()> = Ok((1, 2)); + //~^ ERROR enum variant takes 1 argument but 2 arguments were supplied + let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi")); + //~^ ERROR enum variant takes 1 argument but 3 arguments were supplied + let _: Option<()> = Some(()); + //~^ ERROR enum variant takes 1 argument but 0 arguments were supplied + + let _: Option<(i32,)> = Some((3,)); + //~^ ERROR mismatched types + + let _: Option<(i32,)> = Some((3,)); + //~^ ERROR mismatched types + + two_ints((1, 2)); //~ ERROR function takes 1 argument + + with_generic((3, 4)); //~ ERROR function takes 1 argument +} + +fn two_ints(_: (i32, i32)) { +} + +fn with_generic((a, b): (i32, T)) { + if false { + // test generics/bound handling + with_generic((a, b)); //~ ERROR function takes 1 argument + } +} diff --git a/tests/ui/suggestions/args-instead-of-tuple.rs b/tests/ui/suggestions/args-instead-of-tuple.rs new file mode 100644 index 000000000..1c65407b3 --- /dev/null +++ b/tests/ui/suggestions/args-instead-of-tuple.rs @@ -0,0 +1,33 @@ +// Test suggesting tuples where bare arguments may have been passed +// See issue #86481 for details. + +// run-rustfix + +fn main() { + let _: Result<(i32, i8), ()> = Ok(1, 2); + //~^ ERROR enum variant takes 1 argument but 2 arguments were supplied + let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi"); + //~^ ERROR enum variant takes 1 argument but 3 arguments were supplied + let _: Option<()> = Some(); + //~^ ERROR enum variant takes 1 argument but 0 arguments were supplied + + let _: Option<(i32,)> = Some(3); + //~^ ERROR mismatched types + + let _: Option<(i32,)> = Some((3)); + //~^ ERROR mismatched types + + two_ints(1, 2); //~ ERROR function takes 1 argument + + with_generic(3, 4); //~ ERROR function takes 1 argument +} + +fn two_ints(_: (i32, i32)) { +} + +fn with_generic((a, b): (i32, T)) { + if false { + // test generics/bound handling + with_generic(a, b); //~ ERROR function takes 1 argument + } +} diff --git a/tests/ui/suggestions/args-instead-of-tuple.stderr b/tests/ui/suggestions/args-instead-of-tuple.stderr new file mode 100644 index 000000000..3ed9dbf4a --- /dev/null +++ b/tests/ui/suggestions/args-instead-of-tuple.stderr @@ -0,0 +1,125 @@ +error[E0061]: enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:7:36 + | +LL | let _: Result<(i32, i8), ()> = Ok(1, 2); + | ^^ + | +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL +help: wrap these arguments in parentheses to construct a tuple + | +LL | let _: Result<(i32, i8), ()> = Ok((1, 2)); + | + + + +error[E0061]: enum variant takes 1 argument but 3 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:9:46 + | +LL | let _: Option<(i32, i8, &'static str)> = Some(1, 2, "hi"); + | ^^^^ + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: wrap these arguments in parentheses to construct a tuple + | +LL | let _: Option<(i32, i8, &'static str)> = Some((1, 2, "hi")); + | + + + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:11:25 + | +LL | let _: Option<()> = Some(); + | ^^^^-- an argument of type `()` is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: provide the argument + | +LL | let _: Option<()> = Some(()); + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple.rs:14:34 + | +LL | let _: Option<(i32,)> = Some(3); + | ---- ^ expected tuple, found integer + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `{integer}` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: use a trailing comma to create a tuple with one element + | +LL | let _: Option<(i32,)> = Some((3,)); + | + ++ + +error[E0308]: mismatched types + --> $DIR/args-instead-of-tuple.rs:17:34 + | +LL | let _: Option<(i32,)> = Some((3)); + | ---- ^^^ expected tuple, found integer + | | + | arguments to this enum variant are incorrect + | + = note: expected tuple `(i32,)` + found type `{integer}` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: use a trailing comma to create a tuple with one element + | +LL | let _: Option<(i32,)> = Some((3,)); + | + + +error[E0061]: function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:20:5 + | +LL | two_ints(1, 2); + | ^^^^^^^^ + | +note: function defined here + --> $DIR/args-instead-of-tuple.rs:25:4 + | +LL | fn two_ints(_: (i32, i32)) { + | ^^^^^^^^ ------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | two_ints((1, 2)); + | + + + +error[E0061]: function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:22:5 + | +LL | with_generic(3, 4); + | ^^^^^^^^^^^^ + | +note: function defined here + --> $DIR/args-instead-of-tuple.rs:28:4 + | +LL | fn with_generic((a, b): (i32, T)) { + | ^^^^^^^^^^^^ ---------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | with_generic((3, 4)); + | + + + +error[E0061]: function takes 1 argument but 2 arguments were supplied + --> $DIR/args-instead-of-tuple.rs:31:9 + | +LL | with_generic(a, b); + | ^^^^^^^^^^^^ + | +note: function defined here + --> $DIR/args-instead-of-tuple.rs:28:4 + | +LL | fn with_generic((a, b): (i32, T)) { + | ^^^^^^^^^^^^ ---------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | with_generic((a, b)); + | + + + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/suggestions/as-ref-2.rs b/tests/ui/suggestions/as-ref-2.rs new file mode 100644 index 000000000..b22f409b4 --- /dev/null +++ b/tests/ui/suggestions/as-ref-2.rs @@ -0,0 +1,11 @@ +struct Struct; + +fn bar(_: &Struct) -> Struct { + Struct +} + +fn main() { + let foo = Some(Struct); + let _x: Option = foo.map(|s| bar(&s)); + let _y = foo; //~ERROR use of moved value: `foo` +} diff --git a/tests/ui/suggestions/as-ref-2.stderr b/tests/ui/suggestions/as-ref-2.stderr new file mode 100644 index 000000000..e2129b450 --- /dev/null +++ b/tests/ui/suggestions/as-ref-2.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/as-ref-2.rs:10:14 + | +LL | let foo = Some(Struct); + | --- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait +LL | let _x: Option = foo.map(|s| bar(&s)); + | --- ---------------- `foo` moved due to this method call + | | + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents +LL | let _y = foo; + | ^^^ value used here after move + | +note: `Option::::map` takes ownership of the receiver `self`, which moves `foo` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/suggestions/as-ref.rs b/tests/ui/suggestions/as-ref.rs new file mode 100644 index 000000000..a05353441 --- /dev/null +++ b/tests/ui/suggestions/as-ref.rs @@ -0,0 +1,27 @@ +struct Foo; + +fn takes_ref(_: &Foo) {} + +fn main() { + let ref opt = Some(Foo); + opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let ref opt: Result<_, ()> = Ok(Foo); + opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + opt.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let x: &Option = &Some(3); + let y: Option<&usize> = x; //~ ERROR mismatched types [E0308] + let x: &Result = &Ok(3); + let y: Result<&usize, &usize> = x; + //~^ ERROR mismatched types [E0308] + // note: do not suggest because of `E: usize` + let x: &Result = &Ok(3); + let y: Result<&usize, usize> = x; //~ ERROR mismatched types [E0308] + + let multiple_ref_opt = &&Some(Foo); + multiple_ref_opt.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + multiple_ref_opt.and_then(|arg| Some(takes_ref(arg))); //~ ERROR mismatched types [E0308] + let multiple_ref_result = &&Ok(Foo); + multiple_ref_result.map(|arg| takes_ref(arg)); //~ ERROR mismatched types [E0308] + multiple_ref_result.and_then(|arg| Ok(takes_ref(arg))); //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/suggestions/as-ref.stderr b/tests/ui/suggestions/as-ref.stderr new file mode 100644 index 000000000..deafa9f48 --- /dev/null +++ b/tests/ui/suggestions/as-ref.stderr @@ -0,0 +1,162 @@ +error[E0308]: mismatched types + --> $DIR/as-ref.rs:7:29 + | +LL | opt.map(|arg| takes_ref(arg)); + | --- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().map` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:8:39 + | +LL | opt.and_then(|arg| Some(takes_ref(arg))); + | -------- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().and_then` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:10:29 + | +LL | opt.map(|arg| takes_ref(arg)); + | --- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().map` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:11:37 + | +LL | opt.and_then(|arg| Ok(takes_ref(arg))); + | -------- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().and_then` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:13:29 + | +LL | let y: Option<&usize> = x; + | -------------- ^ + | | | + | | expected enum `Option`, found `&Option` + | | help: you can convert from `&Option` to `Option<&T>` using `.as_ref()`: `x.as_ref()` + | expected due to this + | + = note: expected enum `Option<&usize>` + found reference `&Option` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:15:37 + | +LL | let y: Result<&usize, &usize> = x; + | ---------------------- ^ expected enum `Result`, found reference + | | + | expected due to this + | + = note: expected enum `Result<&usize, &usize>` + found reference `&Result` +help: you can convert from `&Result` to `Result<&T, &E>` using `.as_ref()` + | +LL | let y: Result<&usize, &usize> = x.as_ref(); + | ~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:19:36 + | +LL | let y: Result<&usize, usize> = x; + | --------------------- ^ expected enum `Result`, found reference + | | + | expected due to this + | + = note: expected enum `Result<&usize, usize>` + found reference `&Result` + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:22:42 + | +LL | multiple_ref_opt.map(|arg| takes_ref(arg)); + | --- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().map` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:23:52 + | +LL | multiple_ref_opt.and_then(|arg| Some(takes_ref(arg))); + | -------- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().and_then` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:25:45 + | +LL | multiple_ref_result.map(|arg| takes_ref(arg)); + | --- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().map` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error[E0308]: mismatched types + --> $DIR/as-ref.rs:26:53 + | +LL | multiple_ref_result.and_then(|arg| Ok(takes_ref(arg))); + | -------- --------- ^^^ expected `&Foo`, found struct `Foo` + | | | + | | arguments to this function are incorrect + | help: consider using `as_ref` instead: `as_ref().and_then` + | +note: function defined here + --> $DIR/as-ref.rs:3:4 + | +LL | fn takes_ref(_: &Foo) {} + | ^^^^^^^^^ ------- + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/assoc-const-as-field.rs b/tests/ui/suggestions/assoc-const-as-field.rs new file mode 100644 index 000000000..678b58936 --- /dev/null +++ b/tests/ui/suggestions/assoc-const-as-field.rs @@ -0,0 +1,13 @@ +pub mod Mod { + pub struct Foo {} + impl Foo { + pub const BAR: usize = 42; + } +} + +fn foo(_: usize) {} + +fn main() { + foo(Mod::Foo.Bar); + //~^ ERROR expected value, found +} diff --git a/tests/ui/suggestions/assoc-const-as-field.stderr b/tests/ui/suggestions/assoc-const-as-field.stderr new file mode 100644 index 000000000..78e5634b2 --- /dev/null +++ b/tests/ui/suggestions/assoc-const-as-field.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected value, found struct `Mod::Foo` + --> $DIR/assoc-const-as-field.rs:11:9 + | +LL | foo(Mod::Foo.Bar); + | ^^^^^^^^- help: use the path separator to refer to an item: `::` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/suggestions/assoc-const-as-fn.rs b/tests/ui/suggestions/assoc-const-as-fn.rs new file mode 100644 index 000000000..4b4595dd5 --- /dev/null +++ b/tests/ui/suggestions/assoc-const-as-fn.rs @@ -0,0 +1,18 @@ +unsafe fn pointer(v: usize, w: u32) {} + +pub trait UniformScalar {} +impl UniformScalar for u32 {} + +pub trait GlUniformScalar: UniformScalar { + const FACTORY: unsafe fn(usize, Self) -> (); +} +impl GlUniformScalar for u32 { + const FACTORY: unsafe fn(usize, Self) -> () = pointer; +} + +pub fn foo(value: T) { + ::FACTORY(1, value); + //~^ ERROR the trait bound `T: GlUniformScalar` is not satisfied +} + +fn main() {} diff --git a/tests/ui/suggestions/assoc-const-as-fn.stderr b/tests/ui/suggestions/assoc-const-as-fn.stderr new file mode 100644 index 000000000..3b6e947c5 --- /dev/null +++ b/tests/ui/suggestions/assoc-const-as-fn.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied + --> $DIR/assoc-const-as-fn.rs:14:40 + | +LL | ::FACTORY(1, value); + | ------------------------------- ^^^^^ the trait `GlUniformScalar` is not implemented for `T` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | pub fn foo(value: T) { + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.rs b/tests/ui/suggestions/assoc-ct-for-assoc-method.rs new file mode 100644 index 000000000..fe2227769 --- /dev/null +++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.rs @@ -0,0 +1,25 @@ +struct MyS; + +impl MyS { + const FOO: i32 = 1; + fn foo() -> MyS { + MyS + } +} + +fn main() { + let x: i32 = MyS::foo; + //~^ ERROR mismatched types + //~| HELP try referring to the + + let z: i32 = i32::max; + //~^ ERROR mismatched types + //~| HELP try referring to the + + // This example is still broken though... This is a hard suggestion to make, + // because we don't have access to the associated const probing code to make + // this suggestion where it's emitted, i.e. in trait selection. + let y: i32 = i32::max - 42; + //~^ ERROR cannot subtract + //~| HELP use parentheses +} diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr new file mode 100644 index 000000000..afef38f12 --- /dev/null +++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/assoc-ct-for-assoc-method.rs:11:18 + | +LL | let x: i32 = MyS::foo; + | --- ^^^^^^^^ expected `i32`, found fn item + | | + | expected due to this + | + = note: expected type `i32` + found fn item `fn() -> MyS {MyS::foo}` +help: try referring to the associated const `FOO` instead + | +LL | let x: i32 = MyS::FOO; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/assoc-ct-for-assoc-method.rs:15:18 + | +LL | let z: i32 = i32::max; + | --- ^^^^^^^^ expected `i32`, found fn item + | | + | expected due to this + | + = note: expected type `i32` + found fn item `fn(i32, i32) -> i32 {::max}` +help: try referring to the associated const `MAX` instead + | +LL | let z: i32 = i32::MAX; + | ~~~ + +error[E0369]: cannot subtract `{integer}` from `fn(i32, i32) -> i32 {::max}` + --> $DIR/assoc-ct-for-assoc-method.rs:22:27 + | +LL | let y: i32 = i32::max - 42; + | -------- ^ -- {integer} + | | + | fn(i32, i32) -> i32 {::max} + | +help: use parentheses to call this associated function + | +LL | let y: i32 = i32::max(/* i32 */, /* i32 */) - 42; + | ++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/assoc-type-in-method-return.rs b/tests/ui/suggestions/assoc-type-in-method-return.rs new file mode 100644 index 000000000..9bde65998 --- /dev/null +++ b/tests/ui/suggestions/assoc-type-in-method-return.rs @@ -0,0 +1,7 @@ +trait A { + type Bla; + fn to_bla(&self) -> Bla; + //~^ ERROR cannot find type `Bla` in this scope +} + +fn main() {} diff --git a/tests/ui/suggestions/assoc-type-in-method-return.stderr b/tests/ui/suggestions/assoc-type-in-method-return.stderr new file mode 100644 index 000000000..202e4a16e --- /dev/null +++ b/tests/ui/suggestions/assoc-type-in-method-return.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Bla` in this scope + --> $DIR/assoc-type-in-method-return.rs:3:25 + | +LL | fn to_bla(&self) -> Bla; + | ^^^ help: you might have meant to use the associated type: `Self::Bla` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/suggestions/assoc_fn_without_self.rs b/tests/ui/suggestions/assoc_fn_without_self.rs new file mode 100644 index 000000000..778d98477 --- /dev/null +++ b/tests/ui/suggestions/assoc_fn_without_self.rs @@ -0,0 +1,20 @@ +fn main() {} + +struct S; + +impl S { + fn foo() {} + + fn bar(&self) {} + + fn baz(a: u8, b: u8) {} + + fn b() { + fn c() { + foo(); //~ ERROR cannot find function `foo` in this scope + } + foo(); //~ ERROR cannot find function `foo` in this scope + bar(); //~ ERROR cannot find function `bar` in this scope + baz(2, 3); //~ ERROR cannot find function `baz` in this scope + } +} diff --git a/tests/ui/suggestions/assoc_fn_without_self.stderr b/tests/ui/suggestions/assoc_fn_without_self.stderr new file mode 100644 index 000000000..febdd6733 --- /dev/null +++ b/tests/ui/suggestions/assoc_fn_without_self.stderr @@ -0,0 +1,42 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/assoc_fn_without_self.rs:16:9 + | +LL | foo(); + | ^^^ not found in this scope + | +help: consider using the associated function + | +LL | Self::foo(); + | ++++++ + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/assoc_fn_without_self.rs:17:9 + | +LL | bar(); + | ^^^ not found in this scope + | +help: consider using the associated function + | +LL | self.bar(); + | +++++ + +error[E0425]: cannot find function `baz` in this scope + --> $DIR/assoc_fn_without_self.rs:18:9 + | +LL | baz(2, 3); + | ^^^ not found in this scope + | +help: consider using the associated function + | +LL | Self::baz(2, 3); + | ++++++ + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/assoc_fn_without_self.rs:14:13 + | +LL | foo(); + | ^^^ not found in this scope + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 000000000..156162c90 --- /dev/null +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,13 @@ +// edition:2018 +#![feature(async_closure)] +use std::future::Future; + +async fn foo() {} + +fn bar(f: impl Future) {} + +fn main() { + bar(foo); //~ERROR E0277 + let async_closure = async || (); + bar(async_closure); //~ERROR E0277 +} diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 000000000..8ed62f854 --- /dev/null +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,43 @@ +error[E0277]: `fn() -> impl Future {foo}` is not a future + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9 + | +LL | bar(foo); + | --- ^^^ `fn() -> impl Future {foo}` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for fn item `fn() -> impl Future {foo}` + = note: fn() -> impl Future {foo} must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `bar` + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 + | +LL | fn bar(f: impl Future) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` +help: use parentheses to call this function + | +LL | bar(foo()); + | ++ + +error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 + | +LL | bar(async_closure); + | --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future + | | + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` + = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `bar` + --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 + | +LL | fn bar(f: impl Future) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` +help: use parentheses to call this closure + | +LL | bar(async_closure()); + | ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/attribute-typos.rs b/tests/ui/suggestions/attribute-typos.rs new file mode 100644 index 000000000..7c8231bbb --- /dev/null +++ b/tests/ui/suggestions/attribute-typos.rs @@ -0,0 +1,11 @@ +#[deprcated] //~ ERROR cannot find attribute `deprcated` in this scope +fn foo() {} + +#[tests] //~ ERROR cannot find attribute `tests` in this scope +fn bar() {} + +#[rustc_err] +//~^ ERROR cannot find attribute `rustc_err` in this scope +//~| ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler + +fn main() {} diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr new file mode 100644 index 000000000..b871c9b45 --- /dev/null +++ b/tests/ui/suggestions/attribute-typos.stderr @@ -0,0 +1,29 @@ +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/attribute-typos.rs:7:3 + | +LL | #[rustc_err] + | ^^^^^^^^^ + +error: cannot find attribute `rustc_err` in this scope + --> $DIR/attribute-typos.rs:7:3 + | +LL | #[rustc_err] + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `rustc_error` + +error: cannot find attribute `tests` in this scope + --> $DIR/attribute-typos.rs:4:3 + | +LL | #[tests] + | ^^^^^ help: an attribute macro with a similar name exists: `test` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + | + = note: similarly named attribute macro `test` defined here + +error: cannot find attribute `deprcated` in this scope + --> $DIR/attribute-typos.rs:1:3 + | +LL | #[deprcated] + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/suggestions/auxiliary/foo.rs b/tests/ui/suggestions/auxiliary/foo.rs new file mode 100644 index 000000000..e90bbef6d --- /dev/null +++ b/tests/ui/suggestions/auxiliary/foo.rs @@ -0,0 +1,3 @@ +//! Contains a struct with almost the same name as itself, to trigger Levenshtein suggestions. + +pub struct Foo; diff --git a/tests/ui/suggestions/auxiliary/issue-61963-1.rs b/tests/ui/suggestions/auxiliary/issue-61963-1.rs new file mode 100644 index 000000000..6c2df7e84 --- /dev/null +++ b/tests/ui/suggestions/auxiliary/issue-61963-1.rs @@ -0,0 +1,40 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, TokenStream, TokenTree}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_derive(DomObject)] +pub fn expand_token_stream(input: TokenStream) -> TokenStream { + // Construct a dummy span - `#0 bytes(0..0)` - which is present in the input because + // of the specially crafted generated tokens in the `attribute-crate` proc-macro. + let dummy_span = input.clone().into_iter().nth(0).unwrap().span(); + + // Define what the macro would output if constructed properly from the source using syn/quote. + let output: TokenStream = "impl Bar for ((), Qux >) { } + impl Bar for ((), Box) { }".parse().unwrap(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust token spans to match the original crate (which would use `quote`). Some of the + // generated tokens point to the dummy span. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut().skip(2) { + token.set_span(dummy_span); + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/tests/ui/suggestions/auxiliary/issue-61963.rs b/tests/ui/suggestions/auxiliary/issue-61963.rs new file mode 100644 index 000000000..e86f1610a --- /dev/null +++ b/tests/ui/suggestions/auxiliary/issue-61963.rs @@ -0,0 +1,41 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream}; + +// This macro exists as part of a reproduction of #61963 but without using quote/syn/proc_macro2. + +#[proc_macro_attribute] +pub fn dom_struct(_: TokenStream, input: TokenStream) -> TokenStream { + // Construct the expected output tokens - the input but with a `#[derive(DomObject)]` applied. + let attributes: TokenStream = + "#[derive(DomObject)]".to_string().parse().unwrap(); + let output: TokenStream = attributes.into_iter() + .chain(input.into_iter()).collect(); + + let mut tokens: Vec<_> = output.into_iter().collect(); + // Adjust the spacing of `>` tokens to match what `quote` would produce. + for token in tokens.iter_mut() { + if let TokenTree::Group(group) = token { + let mut tokens: Vec<_> = group.stream().into_iter().collect(); + for token in tokens.iter_mut() { + if let TokenTree::Punct(p) = token { + if p.as_char() == '>' { + *p = Punct::new('>', Spacing::Alone); + } + } + } + + let mut stream = TokenStream::new(); + stream.extend(tokens); + *group = Group::new(group.delimiter(), stream); + } + } + + let mut output = TokenStream::new(); + output.extend(tokens); + output +} diff --git a/tests/ui/suggestions/auxiliary/issue-81839.rs b/tests/ui/suggestions/auxiliary/issue-81839.rs new file mode 100644 index 000000000..5683c45ad --- /dev/null +++ b/tests/ui/suggestions/auxiliary/issue-81839.rs @@ -0,0 +1,9 @@ +// edition:2018 + +pub struct Test {} + +impl Test { + pub async fn answer_str(&self, _s: &str) -> Test { + Test {} + } +} diff --git a/tests/ui/suggestions/auxiliary/meow.rs b/tests/ui/suggestions/auxiliary/meow.rs new file mode 100644 index 000000000..115df70a6 --- /dev/null +++ b/tests/ui/suggestions/auxiliary/meow.rs @@ -0,0 +1,11 @@ +pub trait Meow { + fn meow(&self) {} +} + +pub struct GlobalMeow; + +impl Meow for GlobalMeow {} + +pub(crate) struct PrivateMeow; + +impl Meow for PrivateMeow {} diff --git a/tests/ui/suggestions/auxiliary/not-object-safe.rs b/tests/ui/suggestions/auxiliary/not-object-safe.rs new file mode 100644 index 000000000..7c9829b82 --- /dev/null +++ b/tests/ui/suggestions/auxiliary/not-object-safe.rs @@ -0,0 +1,6 @@ +use std::sync::Arc; + +pub trait A { + fn f(); + fn f2(self: &Arc); +} diff --git a/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs new file mode 100644 index 000000000..d71747f96 --- /dev/null +++ b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs @@ -0,0 +1,18 @@ +// force-host +// no-prefer-dynamic +#![crate_type = "proc-macro"] +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, TokenStream}; + +#[proc_macro_attribute] +pub fn hello(_: TokenStream, _: TokenStream) -> TokenStream { + quote!( + fn f(_: &mut i32) {} + fn g() { + f(123); + } + ) +} diff --git a/tests/ui/suggestions/bad-hex-float-lit.rs b/tests/ui/suggestions/bad-hex-float-lit.rs new file mode 100644 index 000000000..cd6fdbde9 --- /dev/null +++ b/tests/ui/suggestions/bad-hex-float-lit.rs @@ -0,0 +1,13 @@ +fn main() { + let _f: f32 = 0xAAf32; + //~^ ERROR mismatched types + //~| HELP rewrite this + + let _f: f32 = 0xAB_f32; + //~^ ERROR mismatched types + //~| HELP rewrite this + + let _f: f64 = 0xFF_f64; + //~^ ERROR mismatched types + //~| HELP rewrite this +} diff --git a/tests/ui/suggestions/bad-hex-float-lit.stderr b/tests/ui/suggestions/bad-hex-float-lit.stderr new file mode 100644 index 000000000..bc09abb1a --- /dev/null +++ b/tests/ui/suggestions/bad-hex-float-lit.stderr @@ -0,0 +1,48 @@ +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:2:19 + | +LL | let _f: f32 = 0xAAf32; + | --- ^^^^^^^ expected `f32`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f32 = 0xAA as f32; + | ~~~~~~~~~~~ +LL | let _f: f32 = 170_f32; + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:6:19 + | +LL | let _f: f32 = 0xAB_f32; + | --- ^^^^^^^^ expected `f32`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f32 = 0xAB as f32; + | ~~~~~~~~~~~ +LL | let _f: f32 = 171_f32; + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:10:19 + | +LL | let _f: f64 = 0xFF_f64; + | --- ^^^^^^^^ expected `f64`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f64 = 0xFF as f64; + | ~~~~~~~~~~~ +LL | let _f: f64 = 255_f64; + | ~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/bool_typo_err_suggest.rs b/tests/ui/suggestions/bool_typo_err_suggest.rs new file mode 100644 index 000000000..deab0fb05 --- /dev/null +++ b/tests/ui/suggestions/bool_typo_err_suggest.rs @@ -0,0 +1,12 @@ +// Suggest the boolean value instead of emit a generic error that the value +// True is not in the scope. + +fn main() { + let x = True; + //~^ ERROR cannot find value `True` in this scope + //~| HELP you may want to use a bool value instead + + let y = False; + //~^ ERROR cannot find value `False` in this scope + //~| HELP you may want to use a bool value instead +} diff --git a/tests/ui/suggestions/bool_typo_err_suggest.stderr b/tests/ui/suggestions/bool_typo_err_suggest.stderr new file mode 100644 index 000000000..52bde07ca --- /dev/null +++ b/tests/ui/suggestions/bool_typo_err_suggest.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find value `True` in this scope + --> $DIR/bool_typo_err_suggest.rs:5:13 + | +LL | let x = True; + | ^^^^ not found in this scope + | +help: you may want to use a bool value instead + | +LL | let x = true; + | ~~~~ + +error[E0425]: cannot find value `False` in this scope + --> $DIR/bool_typo_err_suggest.rs:9:13 + | +LL | let y = False; + | ^^^^^ not found in this scope + | +help: you may want to use a bool value instead + | +LL | let y = false; + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/borrow-for-loop-head.rs b/tests/ui/suggestions/borrow-for-loop-head.rs new file mode 100644 index 000000000..c2bda55e5 --- /dev/null +++ b/tests/ui/suggestions/borrow-for-loop-head.rs @@ -0,0 +1,10 @@ +fn main() { + let a = vec![1, 2, 3]; + for i in &a { + for j in a { + //~^ ERROR cannot move out of `a` because it is borrowed + //~| ERROR use of moved value: `a` + println!("{} * {} = {}", i, j, i * j); + } + } +} diff --git a/tests/ui/suggestions/borrow-for-loop-head.stderr b/tests/ui/suggestions/borrow-for-loop-head.stderr new file mode 100644 index 000000000..cbdb94877 --- /dev/null +++ b/tests/ui/suggestions/borrow-for-loop-head.stderr @@ -0,0 +1,29 @@ +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/borrow-for-loop-head.rs:4:18 + | +LL | for i in &a { + | -- borrow of `a` occurs here +LL | for j in a { + | ^ move out of `a` occurs here + +error[E0382]: use of moved value: `a` + --> $DIR/borrow-for-loop-head.rs:4:18 + | +LL | let a = vec![1, 2, 3]; + | - move occurs because `a` has type `Vec`, which does not implement the `Copy` trait +LL | for i in &a { + | ----------- inside of this loop +LL | for j in a { + | ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop + | +note: `into_iter` takes ownership of the receiver `self`, which moves `a` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider iterating over a slice of the `Vec`'s content to avoid moving into the `for` loop + | +LL | for j in &a { + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/suggestions/bound-suggestions.fixed b/tests/ui/suggestions/bound-suggestions.fixed new file mode 100644 index 000000000..17a019c69 --- /dev/null +++ b/tests/ui/suggestions/bound-suggestions.fixed @@ -0,0 +1,68 @@ +// run-rustfix + +#[allow(unused)] +use std::fmt::Debug; +// Rustfix should add this, or use `std::fmt::Debug` instead. + +#[allow(dead_code)] +fn test_impl(t: impl Sized + std::fmt::Debug) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds_where(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { + println!("{:?} {:?}", x, y); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound_where(x: X) where X: Sized + std::fmt::Debug { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Sized { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +trait Foo: Sized { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bar: std::fmt::Display + Sized { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Baz: Sized where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Qux: Sized where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bat: std::fmt::Display + Sized { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +fn main() { } diff --git a/tests/ui/suggestions/bound-suggestions.rs b/tests/ui/suggestions/bound-suggestions.rs new file mode 100644 index 000000000..86f708d42 --- /dev/null +++ b/tests/ui/suggestions/bound-suggestions.rs @@ -0,0 +1,68 @@ +// run-rustfix + +#[allow(unused)] +use std::fmt::Debug; +// Rustfix should add this, or use `std::fmt::Debug` instead. + +#[allow(dead_code)] +fn test_impl(t: impl Sized) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound(t: T) { + println!("{:?}", t); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_no_bounds_where(x: X, y: Y) where X: std::fmt::Debug, { + println!("{:?} {:?}", x, y); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_one_bound_where(x: X) where X: Sized { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +#[allow(dead_code)] +fn test_many_bounds_where(x: X) where X: Sized, X: Sized { + println!("{:?}", x); + //~^ ERROR doesn't implement +} + +trait Foo { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bar: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Baz where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Qux where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bat: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +fn main() { } diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr new file mode 100644 index 000000000..cd27947f0 --- /dev/null +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -0,0 +1,140 @@ +error[E0277]: `impl Sized` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:9:22 + | +LL | println!("{:?}", t); + | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_impl(t: impl Sized + std::fmt::Debug) { + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:15:22 + | +LL | println!("{:?}", t); + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | fn test_no_bounds(t: T) { + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:21:22 + | +LL | println!("{:?}", t); + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_one_bound(t: T) { + | +++++++++++++++++ + +error[E0277]: `Y` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:27:30 + | +LL | println!("{:?} {:?}", x, y); + | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting type parameter `Y` + | +LL | fn test_no_bounds_where(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { + | ~~~~~~~~~~~~~~~~~~~~ + +error[E0277]: `X` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:33:22 + | +LL | println!("{:?}", x); + | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_one_bound_where(x: X) where X: Sized + std::fmt::Debug { + | +++++++++++++++++ + +error[E0277]: `X` doesn't implement `Debug` + --> $DIR/bound-suggestions.rs:39:22 + | +LL | println!("{:?}", x); + | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Sized { + | +++++++++++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:44:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider further restricting `Self` + | +LL | trait Foo: Sized { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:49:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider further restricting `Self` + | +LL | trait Bar: std::fmt::Display + Sized { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:54:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider further restricting `Self` + | +LL | trait Baz: Sized where Self: std::fmt::Display { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:59:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider further restricting `Self` + | +LL | trait Qux: Sized where Self: std::fmt::Display { + | +++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:64:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider further restricting `Self` + | +LL | trait Bat: std::fmt::Display + Sized { + | +++++++ + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/box-future-wrong-output.rs b/tests/ui/suggestions/box-future-wrong-output.rs new file mode 100644 index 000000000..d49819fcb --- /dev/null +++ b/tests/ui/suggestions/box-future-wrong-output.rs @@ -0,0 +1,22 @@ +// Issue #72117 +// edition:2018 + +use core::future::Future; +use core::pin::Pin; + +pub type BoxFuture<'a, T> = Pin + Send + 'a>>; + +impl FutureExt for T where T: Future {} +trait FutureExt: Future { + fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> + where + Self: Sized + Send + 'a, + { + Box::pin(self) + } +} + +fn main() { + let _: BoxFuture<'static, bool> = async {}.boxed(); + //~^ ERROR: mismatched types +} diff --git a/tests/ui/suggestions/box-future-wrong-output.stderr b/tests/ui/suggestions/box-future-wrong-output.stderr new file mode 100644 index 000000000..e0c57af25 --- /dev/null +++ b/tests/ui/suggestions/box-future-wrong-output.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/box-future-wrong-output.rs:20:39 + | +LL | let _: BoxFuture<'static, bool> = async {}.boxed(); + | ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | | + | expected due to this + | + = note: expected struct `Pin + Send + 'static)>>` + found struct `Pin + Send>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/boxed-variant-field.rs b/tests/ui/suggestions/boxed-variant-field.rs new file mode 100644 index 000000000..6050963c4 --- /dev/null +++ b/tests/ui/suggestions/boxed-variant-field.rs @@ -0,0 +1,15 @@ +enum Ty { + Unit, + List(Box), +} + +fn foo(x: Ty) -> Ty { + match x { + Ty::Unit => Ty::Unit, + Ty::List(elem) => foo(elem), + //~^ ERROR mismatched types + //~| HELP consider unboxing the value + } +} + +fn main() {} diff --git a/tests/ui/suggestions/boxed-variant-field.stderr b/tests/ui/suggestions/boxed-variant-field.stderr new file mode 100644 index 000000000..9ae36a06a --- /dev/null +++ b/tests/ui/suggestions/boxed-variant-field.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/boxed-variant-field.rs:9:31 + | +LL | Ty::List(elem) => foo(elem), + | --- ^^^^ expected enum `Ty`, found struct `Box` + | | + | arguments to this function are incorrect + | + = note: expected enum `Ty` + found struct `Box` +note: function defined here + --> $DIR/boxed-variant-field.rs:6:4 + | +LL | fn foo(x: Ty) -> Ty { + | ^^^ ----- +help: consider unboxing the value + | +LL | Ty::List(elem) => foo(*elem), + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/call-boxed.rs b/tests/ui/suggestions/call-boxed.rs new file mode 100644 index 000000000..d19e4596a --- /dev/null +++ b/tests/ui/suggestions/call-boxed.rs @@ -0,0 +1,7 @@ +fn main() { + let mut x = 1i32; + let y = Box::new(|| 1); + x = y; + //~^ ERROR mismatched types + //~| HELP use parentheses to call this closure +} diff --git a/tests/ui/suggestions/call-boxed.stderr b/tests/ui/suggestions/call-boxed.stderr new file mode 100644 index 000000000..9b619ac9a --- /dev/null +++ b/tests/ui/suggestions/call-boxed.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/call-boxed.rs:4:9 + | +LL | let mut x = 1i32; + | ---- expected due to this value +LL | let y = Box::new(|| 1); + | -- the found closure +LL | x = y; + | ^ expected `i32`, found struct `Box` + | + = note: expected type `i32` + found struct `Box<[closure@$DIR/call-boxed.rs:3:22: 3:24]>` +help: use parentheses to call this closure + | +LL | x = y(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/call-on-missing.rs b/tests/ui/suggestions/call-on-missing.rs new file mode 100644 index 000000000..25ced84dd --- /dev/null +++ b/tests/ui/suggestions/call-on-missing.rs @@ -0,0 +1,39 @@ +struct Foo { i: i32 } + +impl Foo { + fn bar(&self) {} +} + +fn foo() -> Foo { + Foo { i: 1 } +} + +fn main() { + foo.bar(); + //~^ ERROR no method named `bar` + //~| HELP use parentheses to call this function + + foo.i; + //~^ ERROR no field `i` + //~| HELP use parentheses to call this function + + let callable = Box::new(|| Foo { i: 1 }) as Box Foo>; + + callable.bar(); + //~^ ERROR no method named `bar` + //~| HELP use parentheses to call this trait object + + callable.i; + //~^ ERROR no field `i` + //~| HELP use parentheses to call this trait object +} + +fn type_param Foo>(t: T) { + t.bar(); + //~^ ERROR no method named `bar` + //~| HELP use parentheses to call this type parameter + + t.i; + //~^ ERROR no field `i` + //~| HELP use parentheses to call this type parameter +} diff --git a/tests/ui/suggestions/call-on-missing.stderr b/tests/ui/suggestions/call-on-missing.stderr new file mode 100644 index 000000000..ca9abc7e9 --- /dev/null +++ b/tests/ui/suggestions/call-on-missing.stderr @@ -0,0 +1,75 @@ +error[E0599]: no method named `bar` found for fn item `fn() -> Foo {foo}` in the current scope + --> $DIR/call-on-missing.rs:12:9 + | +LL | foo.bar(); + | ^^^ method not found in `fn() -> Foo {foo}` + | +help: use parentheses to call this function + | +LL | foo().bar(); + | ++ + +error[E0609]: no field `i` on type `fn() -> Foo {foo}` + --> $DIR/call-on-missing.rs:16:9 + | +LL | foo.i; + | ^ + | +help: use parentheses to call this function + | +LL | foo().i; + | ++ + +error[E0599]: no method named `bar` found for struct `Box Foo>` in the current scope + --> $DIR/call-on-missing.rs:22:14 + | +LL | callable.bar(); + | ^^^ method not found in `Box Foo>` + | +help: use parentheses to call this trait object + | +LL | callable().bar(); + | ++ + +error[E0609]: no field `i` on type `Box Foo>` + --> $DIR/call-on-missing.rs:26:14 + | +LL | callable.i; + | ^ unknown field + | +help: use parentheses to call this trait object + | +LL | callable().i; + | ++ + +error[E0599]: no method named `bar` found for type parameter `T` in the current scope + --> $DIR/call-on-missing.rs:32:7 + | +LL | fn type_param Foo>(t: T) { + | - method `bar` not found for this type parameter +LL | t.bar(); + | ^^^ method not found in `T` + | +help: use parentheses to call this type parameter + | +LL | t().bar(); + | ++ + +error[E0609]: no field `i` on type `T` + --> $DIR/call-on-missing.rs:36:7 + | +LL | fn type_param Foo>(t: T) { + | - type parameter 'T' declared here +... +LL | t.i; + | ^ + | +help: use parentheses to call this type parameter + | +LL | t().i; + | ++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0599, E0609. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/call-on-unimplemented-ctor.rs b/tests/ui/suggestions/call-on-unimplemented-ctor.rs new file mode 100644 index 000000000..5f811044e --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-ctor.rs @@ -0,0 +1,17 @@ +fn main() { + insert_resource(Marker); + insert_resource(Time); + //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied + //~| HELP use parentheses to construct this tuple struct +} + +trait Resource {} + +fn insert_resource(resource: R) {} + +struct Marker; +impl Resource for Marker {} + +struct Time(u32); + +impl Resource for Time {} diff --git a/tests/ui/suggestions/call-on-unimplemented-ctor.stderr b/tests/ui/suggestions/call-on-unimplemented-ctor.stderr new file mode 100644 index 000000000..58612cbfb --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-ctor.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied + --> $DIR/call-on-unimplemented-ctor.rs:3:21 + | +LL | insert_resource(Time); + | --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `insert_resource` + --> $DIR/call-on-unimplemented-ctor.rs:10:23 + | +LL | fn insert_resource(resource: R) {} + | ^^^^^^^^ required by this bound in `insert_resource` +help: use parentheses to construct this tuple struct + | +LL | insert_resource(Time(/* u32 */)); + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs new file mode 100644 index 000000000..86490c724 --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.rs @@ -0,0 +1,15 @@ +struct Foo; + +trait Bar {} + +impl Bar for Foo {} + +fn needs_bar(_: T) {} + +fn blah(f: fn() -> Foo) { + needs_bar(f); + //~^ ERROR the trait bound `fn() -> Foo: Bar` is not satisfied + //~| HELP use parentheses to call this function pointer +} + +fn main() {} diff --git a/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr new file mode 100644 index 000000000..167f7e592 --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-fn-ptr.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `fn() -> Foo: Bar` is not satisfied + --> $DIR/call-on-unimplemented-fn-ptr.rs:10:15 + | +LL | needs_bar(f); + | --------- ^ the trait `Bar` is not implemented for `fn() -> Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `needs_bar` + --> $DIR/call-on-unimplemented-fn-ptr.rs:7:17 + | +LL | fn needs_bar(_: T) {} + | ^^^ required by this bound in `needs_bar` +help: use parentheses to call this function pointer + | +LL | needs_bar(f()); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs new file mode 100644 index 000000000..9021dd752 --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs @@ -0,0 +1,13 @@ +trait Foo {} + +impl Foo for i32 {} + +fn needs_foo(_: impl Foo) {} + +fn test(x: &Box i32>) { + needs_foo(x); + //~^ ERROR the trait bound + //~| HELP use parentheses to call this trait object +} + +fn main() {} diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr new file mode 100644 index 000000000..90f44cce0 --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&Box i32>: Foo` is not satisfied + --> $DIR/call-on-unimplemented-with-autoderef.rs:8:15 + | +LL | needs_foo(x); + | --------- ^ the trait `Foo` is not implemented for `&Box i32>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `needs_foo` + --> $DIR/call-on-unimplemented-with-autoderef.rs:5:22 + | +LL | fn needs_foo(_: impl Foo) {} + | ^^^ required by this bound in `needs_foo` +help: use parentheses to call this trait object + | +LL | needs_foo(x()); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.rs b/tests/ui/suggestions/chain-method-call-mutation-in-place.rs new file mode 100644 index 000000000..cb92ab87a --- /dev/null +++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.rs @@ -0,0 +1,4 @@ +fn main() {} +fn foo(mut s: String) -> String { + s.push_str("asdf") //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr new file mode 100644 index 000000000..965dbb967 --- /dev/null +++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/chain-method-call-mutation-in-place.rs:3:5 + | +LL | fn foo(mut s: String) -> String { + | ------ expected `String` because of return type +LL | s.push_str("asdf") + | ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `()` + | +note: method `push_str` modifies its receiver in-place + --> $DIR/chain-method-call-mutation-in-place.rs:3:7 + | +LL | s.push_str("asdf") + | - ^^^^^^^^ this call modifies `s` in-place + | | + | you probably want to use this value after calling the method... + = note: ...instead of the `()` output of method `push_str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed new file mode 100644 index 000000000..4f9e93a47 --- /dev/null +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.fixed @@ -0,0 +1,16 @@ +// run-rustfix +fn wat(t: &T) -> T { + t.clone() //~ ERROR E0308 +} + +#[derive(Clone)] +struct Foo; + +fn wut(t: &Foo) -> Foo { + t.clone() //~ ERROR E0308 +} + +fn main() { + wat(&42); + wut(&Foo); +} diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs new file mode 100644 index 000000000..89b077d67 --- /dev/null +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.rs @@ -0,0 +1,15 @@ +// run-rustfix +fn wat(t: &T) -> T { + t.clone() //~ ERROR E0308 +} + +struct Foo; + +fn wut(t: &Foo) -> Foo { + t.clone() //~ ERROR E0308 +} + +fn main() { + wat(&42); + wut(&Foo); +} diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr new file mode 100644 index 000000000..26ab515d9 --- /dev/null +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5 + | +LL | fn wat(t: &T) -> T { + | - - expected `T` because of return type + | | + | this type parameter +LL | t.clone() + | ^^^^^^^^^ expected type parameter `T`, found `&T` + | + = note: expected type parameter `T` + found reference `&T` +note: `T` does not implement `Clone`, so `&T` was cloned instead + --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5 + | +LL | t.clone() + | ^ +help: consider restricting type parameter `T` + | +LL | fn wat(t: &T) -> T { + | +++++++ + +error[E0308]: mismatched types + --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5 + | +LL | fn wut(t: &Foo) -> Foo { + | --- expected `Foo` because of return type +LL | t.clone() + | ^^^^^^^^^ expected struct `Foo`, found `&Foo` + | +note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead + --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5 + | +LL | t.clone() + | ^ +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/const-in-struct-pat.rs b/tests/ui/suggestions/const-in-struct-pat.rs new file mode 100644 index 000000000..1cbba9354 --- /dev/null +++ b/tests/ui/suggestions/const-in-struct-pat.rs @@ -0,0 +1,11 @@ +#[allow(non_camel_case_types)] +struct foo; +struct Thing { + foo: String, +} + +fn example(t: Thing) { + let Thing { foo } = t; //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/const-in-struct-pat.stderr b/tests/ui/suggestions/const-in-struct-pat.stderr new file mode 100644 index 000000000..c8b93f3dc --- /dev/null +++ b/tests/ui/suggestions/const-in-struct-pat.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/const-in-struct-pat.rs:8:17 + | +LL | struct foo; + | ---------- unit struct defined here +... +LL | let Thing { foo } = t; + | ^^^ - this expression has type `Thing` + | | + | expected struct `String`, found struct `foo` + | `foo` is interpreted as a unit struct, not a new binding + | +help: bind the struct field to a different name instead + | +LL | let Thing { foo: other_foo } = t; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/const-no-type.rs b/tests/ui/suggestions/const-no-type.rs new file mode 100644 index 000000000..c6fdcdadb --- /dev/null +++ b/tests/ui/suggestions/const-no-type.rs @@ -0,0 +1,51 @@ +// In the cases below, the type is missing from the `const` and `static` items. +// +// Here, we test that we: +// +// a) Perform parser recovery. +// +// b) Emit a diagnostic with the actual inferred type to RHS of `=` as the suggestion. + +fn main() {} + +// These will not reach typeck: + +#[cfg(FALSE)] +const C2 = 42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the item +//~| SUGGESTION : + +#[cfg(FALSE)] +static S2 = "abc"; +//~^ ERROR missing type for `static` item +//~| HELP provide a type for the item +//~| SUGGESTION : + +#[cfg(FALSE)] +static mut SM2 = "abc"; +//~^ ERROR missing type for `static mut` item +//~| HELP provide a type for the item +//~| SUGGESTION : + +// These will, so the diagnostics should be stolen by typeck: + +const C = 42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the constant +//~| SUGGESTION : i32 + +const D = &&42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the constant +//~| SUGGESTION : &&i32 + +static S = Vec::::new(); +//~^ ERROR missing type for `static` item +//~| HELP provide a type for the static variable +//~| SUGGESTION : Vec + +static mut SM = "abc"; +//~^ ERROR missing type for `static mut` item +//~| HELP provide a type for the static variable +//~| SUGGESTION : &str diff --git a/tests/ui/suggestions/const-no-type.stderr b/tests/ui/suggestions/const-no-type.stderr new file mode 100644 index 000000000..bd703992f --- /dev/null +++ b/tests/ui/suggestions/const-no-type.stderr @@ -0,0 +1,44 @@ +error: missing type for `const` item + --> $DIR/const-no-type.rs:33:8 + | +LL | const C = 42; + | ^ help: provide a type for the constant: `: i32` + +error: missing type for `const` item + --> $DIR/const-no-type.rs:38:8 + | +LL | const D = &&42; + | ^ help: provide a type for the constant: `: &&i32` + +error: missing type for `static` item + --> $DIR/const-no-type.rs:43:9 + | +LL | static S = Vec::::new(); + | ^ help: provide a type for the static variable: `: Vec` + +error: missing type for `static mut` item + --> $DIR/const-no-type.rs:48:14 + | +LL | static mut SM = "abc"; + | ^ help: provide a type for the static variable: `: &str` + +error: missing type for `const` item + --> $DIR/const-no-type.rs:14:9 + | +LL | const C2 = 42; + | ^ help: provide a type for the item: `: ` + +error: missing type for `static` item + --> $DIR/const-no-type.rs:20:10 + | +LL | static S2 = "abc"; + | ^ help: provide a type for the item: `: ` + +error: missing type for `static mut` item + --> $DIR/const-no-type.rs:26:15 + | +LL | static mut SM2 = "abc"; + | ^ help: provide a type for the item: `: ` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs new file mode 100644 index 000000000..15f08486f --- /dev/null +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs @@ -0,0 +1,11 @@ +fn main() { + let A = 3; + //~^ ERROR refutable pattern in local binding + //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + //~| HELP introduce a variable instead + //~| SUGGESTION a_var + + const A: i32 = 2; + //~^ constant defined here +} diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr new file mode 100644 index 000000000..1c1cab25f --- /dev/null +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -0,0 +1,18 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 + | +LL | let A = 3; + | ^ + | | + | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered + | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + | help: introduce a variable instead: `a_var` +... +LL | const A: i32 = 2; + | ------------ constant defined here + | + = note: the matched value is of type `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/suggestions/constrain-suggest-ice.rs b/tests/ui/suggestions/constrain-suggest-ice.rs new file mode 100644 index 000000000..69b874bed --- /dev/null +++ b/tests/ui/suggestions/constrain-suggest-ice.rs @@ -0,0 +1,11 @@ +struct Bug{ //~ ERROR parameter `S` is never used [E0392] + A: [(); { + let x: [u8; Self::W] = [0; Self::W]; //~ ERROR generic `Self` types are currently not permitted in anonymous constants + //~^ ERROR generic `Self` types are currently not permitted in anonymous constants + //~^^ ERROR the size for values of type `S` cannot be known at compilation time [E0277] + F //~ ERROR cannot find value `F` in this scope [E0425] + } +} //~ ERROR mismatched closing delimiter: `}` +//~^ ERROR mismatched closing delimiter: `}` + +fn main() {} diff --git a/tests/ui/suggestions/constrain-suggest-ice.stderr b/tests/ui/suggestions/constrain-suggest-ice.stderr new file mode 100644 index 000000000..2af7c2f69 --- /dev/null +++ b/tests/ui/suggestions/constrain-suggest-ice.stderr @@ -0,0 +1,72 @@ +error: mismatched closing delimiter: `}` + --> $DIR/constrain-suggest-ice.rs:2:8 + | +LL | struct Bug{ + | - closing delimiter possibly meant for this +LL | A: [(); { + | ^ unclosed delimiter +... +LL | } + | ^ mismatched closing delimiter + +error: mismatched closing delimiter: `}` + --> $DIR/constrain-suggest-ice.rs:2:8 + | +LL | struct Bug{ + | - closing delimiter possibly meant for this +LL | A: [(); { + | ^ unclosed delimiter +... +LL | } + | ^ mismatched closing delimiter + +error[E0425]: cannot find value `F` in this scope + --> $DIR/constrain-suggest-ice.rs:6:9 + | +LL | F + | ^ help: a local variable with a similar name exists: `x` + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/constrain-suggest-ice.rs:3:21 + | +LL | let x: [u8; Self::W] = [0; Self::W]; + | ^^^^ + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/constrain-suggest-ice.rs:3:36 + | +LL | let x: [u8; Self::W] = [0; Self::W]; + | ^^^^ + +error[E0277]: the size for values of type `S` cannot be known at compilation time + --> $DIR/constrain-suggest-ice.rs:3:36 + | +LL | struct Bug{ + | - this type parameter needs to be `std::marker::Sized` +LL | A: [(); { +LL | let x: [u8; Self::W] = [0; Self::W]; + | ^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Bug` + --> $DIR/constrain-suggest-ice.rs:1:12 + | +LL | struct Bug{ + | ^ required by this bound in `Bug` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Bug{ + | ++++++++ + +error[E0392]: parameter `S` is never used + --> $DIR/constrain-suggest-ice.rs:1:12 + | +LL | struct Bug{ + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0392, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/constrain-trait.fixed b/tests/ui/suggestions/constrain-trait.fixed new file mode 100644 index 000000000..f292f27f0 --- /dev/null +++ b/tests/ui/suggestions/constrain-trait.fixed @@ -0,0 +1,47 @@ +// run-rustfix +// check-only + +#[derive(Debug)] +struct Demo { + a: String +} + +trait GetString { + fn get_a(&self) -> &String; +} + +trait UseString: std::fmt::Debug + GetString { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +trait UseString2: GetString { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +impl GetString for Demo { + fn get_a(&self) -> &String { + &self.a + } +} + +impl UseString for Demo {} +impl UseString2 for Demo {} + + +#[cfg(test)] +mod tests { + use crate::{Demo, UseString}; + + #[test] + fn it_works() { + let d = Demo { a: "test".to_string() }; + d.use_string(); + } +} + + +fn main() {} diff --git a/tests/ui/suggestions/constrain-trait.rs b/tests/ui/suggestions/constrain-trait.rs new file mode 100644 index 000000000..99ccf7a7f --- /dev/null +++ b/tests/ui/suggestions/constrain-trait.rs @@ -0,0 +1,47 @@ +// run-rustfix +// check-only + +#[derive(Debug)] +struct Demo { + a: String +} + +trait GetString { + fn get_a(&self) -> &String; +} + +trait UseString: std::fmt::Debug { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +trait UseString2 { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found + } +} + +impl GetString for Demo { + fn get_a(&self) -> &String { + &self.a + } +} + +impl UseString for Demo {} +impl UseString2 for Demo {} + + +#[cfg(test)] +mod tests { + use crate::{Demo, UseString}; + + #[test] + fn it_works() { + let d = Demo { a: "test".to_string() }; + d.use_string(); + } +} + + +fn main() {} diff --git a/tests/ui/suggestions/constrain-trait.stderr b/tests/ui/suggestions/constrain-trait.stderr new file mode 100644 index 000000000..a26f86917 --- /dev/null +++ b/tests/ui/suggestions/constrain-trait.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `get_a` found for reference `&Self` in the current scope + --> $DIR/constrain-trait.rs:15:31 + | +LL | println!("{:?}", self.get_a()); + | ^^^^^ method not found in `&Self` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `get_a`, perhaps you need to add another supertrait for it: + | +LL | trait UseString: std::fmt::Debug + GetString { + | +++++++++++ + +error[E0599]: no method named `get_a` found for reference `&Self` in the current scope + --> $DIR/constrain-trait.rs:21:31 + | +LL | println!("{:?}", self.get_a()); + | ^^^^^ method not found in `&Self` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `get_a`, perhaps you need to add a supertrait for it: + | +LL | trait UseString2: GetString { + | +++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/copied-and-cloned.fixed b/tests/ui/suggestions/copied-and-cloned.fixed new file mode 100644 index 000000000..f801403fe --- /dev/null +++ b/tests/ui/suggestions/copied-and-cloned.fixed @@ -0,0 +1,23 @@ +// run-rustfix + +fn expect(_: T) {} + +fn main() { + let x = Some(&()); + expect::>(x.copied()); + //~^ ERROR mismatched types + //~| HELP use `Option::copied` to copy the value inside the `Option` + let x = Ok(&()); + expect::>(x.copied()); + //~^ ERROR mismatched types + //~| HELP use `Result::copied` to copy the value inside the `Result` + let s = String::new(); + let x = Some(&s); + expect::>(x.cloned()); + //~^ ERROR mismatched types + //~| HELP use `Option::cloned` to clone the value inside the `Option` + let x = Ok(&s); + expect::>(x.cloned()); + //~^ ERROR mismatched types + //~| HELP use `Result::cloned` to clone the value inside the `Result` +} diff --git a/tests/ui/suggestions/copied-and-cloned.rs b/tests/ui/suggestions/copied-and-cloned.rs new file mode 100644 index 000000000..640450b76 --- /dev/null +++ b/tests/ui/suggestions/copied-and-cloned.rs @@ -0,0 +1,23 @@ +// run-rustfix + +fn expect(_: T) {} + +fn main() { + let x = Some(&()); + expect::>(x); + //~^ ERROR mismatched types + //~| HELP use `Option::copied` to copy the value inside the `Option` + let x = Ok(&()); + expect::>(x); + //~^ ERROR mismatched types + //~| HELP use `Result::copied` to copy the value inside the `Result` + let s = String::new(); + let x = Some(&s); + expect::>(x); + //~^ ERROR mismatched types + //~| HELP use `Option::cloned` to clone the value inside the `Option` + let x = Ok(&s); + expect::>(x); + //~^ ERROR mismatched types + //~| HELP use `Result::cloned` to clone the value inside the `Result` +} diff --git a/tests/ui/suggestions/copied-and-cloned.stderr b/tests/ui/suggestions/copied-and-cloned.stderr new file mode 100644 index 000000000..a6336281b --- /dev/null +++ b/tests/ui/suggestions/copied-and-cloned.stderr @@ -0,0 +1,83 @@ +error[E0308]: mismatched types + --> $DIR/copied-and-cloned.rs:7:26 + | +LL | expect::>(x); + | -------------------- ^ expected `()`, found `&()` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<()>` + found enum `Option<&()>` +note: function defined here + --> $DIR/copied-and-cloned.rs:3:4 + | +LL | fn expect(_: T) {} + | ^^^^^^ ---- +help: use `Option::copied` to copy the value inside the `Option` + | +LL | expect::>(x.copied()); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/copied-and-cloned.rs:11:30 + | +LL | expect::>(x); + | ------------------------ ^ expected `()`, found `&()` + | | + | arguments to this function are incorrect + | + = note: expected enum `Result<(), ()>` + found enum `Result<&(), _>` +note: function defined here + --> $DIR/copied-and-cloned.rs:3:4 + | +LL | fn expect(_: T) {} + | ^^^^^^ ---- +help: use `Result::copied` to copy the value inside the `Result` + | +LL | expect::>(x.copied()); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/copied-and-cloned.rs:16:30 + | +LL | expect::>(x); + | ------------------------ ^ expected struct `String`, found `&String` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option` + found enum `Option<&String>` +note: function defined here + --> $DIR/copied-and-cloned.rs:3:4 + | +LL | fn expect(_: T) {} + | ^^^^^^ ---- +help: use `Option::cloned` to clone the value inside the `Option` + | +LL | expect::>(x.cloned()); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/copied-and-cloned.rs:20:34 + | +LL | expect::>(x); + | ---------------------------- ^ expected struct `String`, found `&String` + | | + | arguments to this function are incorrect + | + = note: expected enum `Result` + found enum `Result<&String, _>` +note: function defined here + --> $DIR/copied-and-cloned.rs:3:4 + | +LL | fn expect(_: T) {} + | ^^^^^^ ---- +help: use `Result::cloned` to clone the value inside the `Result` + | +LL | expect::>(x.cloned()); + | +++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.rs b/tests/ui/suggestions/core-std-import-order-issue-83564.rs new file mode 100644 index 000000000..b7fe5af7b --- /dev/null +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.rs @@ -0,0 +1,10 @@ +// edition:2018 + +// This is a regression test for #83564. +// For some reason, Rust 2018 or higher is required to reproduce the bug. + +fn main() { + //~^ HELP consider importing one of these items + let _x = NonZeroU32::new(5).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type `NonZeroU32` +} diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.stderr new file mode 100644 index 000000000..e4e1fc591 --- /dev/null +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.stderr @@ -0,0 +1,16 @@ +error[E0433]: failed to resolve: use of undeclared type `NonZeroU32` + --> $DIR/core-std-import-order-issue-83564.rs:8:14 + | +LL | let _x = NonZeroU32::new(5).unwrap(); + | ^^^^^^^^^^ use of undeclared type `NonZeroU32` + | +help: consider importing one of these items + | +LL | use core::num::NonZeroU32; + | +LL | use std::num::NonZeroU32; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/count2len.rs b/tests/ui/suggestions/count2len.rs new file mode 100644 index 000000000..f11a789ef --- /dev/null +++ b/tests/ui/suggestions/count2len.rs @@ -0,0 +1,8 @@ +fn main() { + let slice = [1,2,3,4]; + let vec = vec![1,2,3,4]; + + slice.count(); //~ERROR: E0599 + vec.count(); //~ERROR: E0599 + vec.as_slice().count(); //~ERROR: E0599 +} diff --git a/tests/ui/suggestions/count2len.stderr b/tests/ui/suggestions/count2len.stderr new file mode 100644 index 000000000..6394a84dd --- /dev/null +++ b/tests/ui/suggestions/count2len.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `count` found for array `[{integer}; 4]` in the current scope + --> $DIR/count2len.rs:5:11 + | +LL | slice.count(); + | ^^^^^ + | | + | method cannot be called on `[{integer}; 4]` due to unsatisfied trait bounds + | help: consider using `len` instead + | + = note: `count` is defined on `Iterator`, which `[{integer}; 4]` does not implement + +error[E0599]: no method named `count` found for struct `Vec<{integer}>` in the current scope + --> $DIR/count2len.rs:6:9 + | +LL | vec.count(); + | ^^^^^ + | | + | method cannot be called on `Vec<{integer}>` due to unsatisfied trait bounds + | help: consider using `len` instead + | + = note: `count` is defined on `Iterator`, which `Vec<{integer}>` does not implement + +error[E0599]: no method named `count` found for reference `&[{integer}]` in the current scope + --> $DIR/count2len.rs:7:20 + | +LL | vec.as_slice().count(); + | ^^^^^ + | | + | method cannot be called on `&[{integer}]` due to unsatisfied trait bounds + | help: consider using `len` instead + | + = note: `count` is defined on `Iterator`, which `&[{integer}]` does not implement + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/crate-or-module-typo.rs b/tests/ui/suggestions/crate-or-module-typo.rs new file mode 100644 index 000000000..2471b11c6 --- /dev/null +++ b/tests/ui/suggestions/crate-or-module-typo.rs @@ -0,0 +1,17 @@ +// edition:2018 + +use st::cell::Cell; //~ ERROR failed to resolve: use of undeclared crate or module `st` + +mod bar { + pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `bar` + + fn baz() {} +} + +use bas::bar; //~ ERROR unresolved import `bas` + +struct Foo { + bar: st::cell::Cell //~ ERROR failed to resolve: use of undeclared crate or module `st` +} + +fn main() {} diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr new file mode 100644 index 000000000..98b88b4fb --- /dev/null +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -0,0 +1,43 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `st` + --> $DIR/crate-or-module-typo.rs:3:5 + | +LL | use st::cell::Cell; + | ^^ use of undeclared crate or module `st` + | +help: there is a crate or module with a similar name + | +LL | use std::cell::Cell; + | ~~~ + +error[E0432]: unresolved import `bas` + --> $DIR/crate-or-module-typo.rs:11:5 + | +LL | use bas::bar; + | ^^^ use of undeclared crate or module `bas` + | +help: there is a crate or module with a similar name + | +LL | use bar::bar; + | ~~~ + +error[E0433]: failed to resolve: use of undeclared crate or module `st` + --> $DIR/crate-or-module-typo.rs:14:10 + | +LL | bar: st::cell::Cell + | ^^ use of undeclared crate or module `st` + | +help: there is a crate or module with a similar name + | +LL | bar: std::cell::Cell + | ~~~ + +error[E0433]: failed to resolve: use of undeclared crate or module `bar` + --> $DIR/crate-or-module-typo.rs:6:20 + | +LL | pub fn bar() { bar::baz(); } + | ^^^ use of undeclared crate or module `bar` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/suggestions/deref-path-method.rs b/tests/ui/suggestions/deref-path-method.rs new file mode 100644 index 000000000..0281cdb6b --- /dev/null +++ b/tests/ui/suggestions/deref-path-method.rs @@ -0,0 +1,6 @@ +fn main() { + let vec = Vec::new(); + Vec::contains(&vec, &0); + //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope + //~| HELP the function `contains` is implemented on `[_]` +} diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr new file mode 100644 index 000000000..1cc37d611 --- /dev/null +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -0,0 +1,14 @@ +error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope + --> $DIR/deref-path-method.rs:3:10 + | +LL | Vec::contains(&vec, &0); + | ^^^^^^^^ function or associated item not found in `Vec<_, _>` + | +help: the function `contains` is implemented on `[_]` + | +LL | <[_]>::contains(&vec, &0); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed new file mode 100644 index 000000000..f07784d53 --- /dev/null +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -0,0 +1,18 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/79076 + +use std::cmp::PartialEq; + +#[derive(Clone, Eq)] //~ ERROR [E0277] +pub struct Struct(T); + +impl PartialEq for Struct +where + U: Into> + Clone +{ + fn eq(&self, _other: &U) -> bool { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs new file mode 100644 index 000000000..15c0d4659 --- /dev/null +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -0,0 +1,18 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/79076 + +use std::cmp::PartialEq; + +#[derive(Clone, Eq)] //~ ERROR [E0277] +pub struct Struct(T); + +impl PartialEq for Struct +where + U: Into> + Clone +{ + fn eq(&self, _other: &U) -> bool { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr new file mode 100644 index 000000000..9d843c251 --- /dev/null +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/derive-clone-for-eq.rs:6:17 + | +LL | #[derive(Clone, Eq)] + | ^^ the trait `Clone` is not implemented for `T` + | +note: required for `Struct` to implement `PartialEq` + --> $DIR/derive-clone-for-eq.rs:9:19 + | +LL | impl PartialEq for Struct + | ----- ^^^^^^^^^^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | pub struct Struct(T); + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.rs b/tests/ui/suggestions/derive-macro-missing-bounds.rs new file mode 100644 index 000000000..56c218f97 --- /dev/null +++ b/tests/ui/suggestions/derive-macro-missing-bounds.rs @@ -0,0 +1,89 @@ +mod a { + use std::fmt::{Debug, Formatter, Result}; + struct Inner(T); + + impl Debug for Inner<()> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer(Inner); //~ ERROR `a::Inner` doesn't implement `Debug` +} + +mod b { + use std::fmt::{Debug, Formatter, Result}; + struct Inner(T); + + impl Debug for Inner { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer(Inner); +} + +mod c { + use std::fmt::{Debug, Formatter, Result}; + struct Inner(T); + trait Trait {} + + impl Debug for Inner { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer(Inner); //~ ERROR the trait bound `T: c::Trait` is not satisfied +} + +mod d { + use std::fmt::{Debug, Formatter, Result}; + struct Inner(T); + trait Trait {} + + impl Debug for Inner where T: Debug, T: Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer(Inner); //~ ERROR the trait bound `T: d::Trait` is not satisfied +} + +mod e { + use std::fmt::{Debug, Formatter, Result}; + struct Inner(T); + trait Trait {} + + impl Debug for Inner where T: Debug + Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer(Inner); //~ ERROR the trait bound `T: e::Trait` is not satisfied +} + +mod f { + use std::fmt::{Debug, Formatter, Result}; + struct Inner(T); + trait Trait {} + + impl Debug for Inner where T: Trait { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + todo!() + } + } + + #[derive(Debug)] + struct Outer(Inner); //~ ERROR the trait bound `T: f::Trait` is not satisfied +} + +fn main() {} diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr new file mode 100644 index 000000000..79036279d --- /dev/null +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -0,0 +1,113 @@ +error[E0277]: `a::Inner` doesn't implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:12:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer(Inner); + | ^^^^^^^^ `a::Inner` cannot be formatted using `{:?}` + | + = help: the trait `Debug` is not implemented for `a::Inner` + = note: add `#[derive(Debug)]` to `a::Inner` or manually `impl Debug for a::Inner` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `a::Inner` with `#[derive(Debug)]` + | +LL | #[derive(Debug)] + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | struct Outer(Inner) where a::Inner: Debug; + | ++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: c::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:41:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer(Inner); + | ^^^^^^^^ the trait `c::Trait` is not implemented for `T` + | +note: required for `c::Inner` to implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:34:28 + | +LL | impl Debug for Inner { + | ----- ^^^^^ ^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&c::Inner` to implement `Debug` + = note: required for the cast from `&c::Inner` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer(Inner); + | ++++++++++ + +error[E0277]: the trait bound `T: d::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:56:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer(Inner); + | ^^^^^^^^ the trait `d::Trait` is not implemented for `T` + | +note: required for `d::Inner` to implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:49:13 + | +LL | impl Debug for Inner where T: Debug, T: Trait { + | ^^^^^ ^^^^^^^^ ----- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&d::Inner` to implement `Debug` + = note: required for the cast from `&d::Inner` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer(Inner); + | ++++++++++ + +error[E0277]: the trait bound `T: e::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:71:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer(Inner); + | ^^^^^^^^ the trait `e::Trait` is not implemented for `T` + | +note: required for `e::Inner` to implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:64:13 + | +LL | impl Debug for Inner where T: Debug + Trait { + | ^^^^^ ^^^^^^^^ ----- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&e::Inner` to implement `Debug` + = note: required for the cast from `&e::Inner` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer(Inner); + | ++++++++++ + +error[E0277]: the trait bound `T: f::Trait` is not satisfied + --> $DIR/derive-macro-missing-bounds.rs:86:21 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct Outer(Inner); + | ^^^^^^^^ the trait `f::Trait` is not implemented for `T` + | +note: required for `f::Inner` to implement `Debug` + --> $DIR/derive-macro-missing-bounds.rs:79:20 + | +LL | impl Debug for Inner where T: Trait { + | ^^^^^ ^^^^^^^^ ----- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&f::Inner` to implement `Debug` + = note: required for the cast from `&f::Inner` to the object type `dyn Debug` + = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | struct Outer(Inner); + | ++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/derive-trait-for-method-call.rs b/tests/ui/suggestions/derive-trait-for-method-call.rs new file mode 100644 index 000000000..25043da52 --- /dev/null +++ b/tests/ui/suggestions/derive-trait-for-method-call.rs @@ -0,0 +1,44 @@ +use std::time::Instant; + +enum Enum { + First +} + +#[derive(Clone)] +enum CloneEnum { + First +} + +struct Struct { +} + +#[derive(Clone)] +struct CloneStruct { +} + +struct Foo (X, Y); +impl Foo { + fn test(&self) -> (X, Y) { + (self.0, self.1) + } +} + +fn test1() { + let x = Foo(Enum::First, CloneEnum::First); + let y = x.test(); + //~^the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] +} + +fn test2() { + let x = Foo(Struct{}, CloneStruct{}); + let y = x.test(); + //~^the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] +} + +fn test3() { + let x = Foo(Vec::::new(), Instant::now()); + let y = x.test(); + //~^the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied [E0599] +} + +fn main() {} diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr new file mode 100644 index 000000000..924b26a8c --- /dev/null +++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr @@ -0,0 +1,105 @@ +error[E0599]: the method `test` exists for struct `Foo`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:28:15 + | +LL | enum Enum { + | --------- + | | + | doesn't satisfy `Enum: Clone` + | doesn't satisfy `Enum: Default` +... +LL | enum CloneEnum { + | -------------- doesn't satisfy `CloneEnum: Default` +... +LL | struct Foo (X, Y); + | ---------------- method `test` not found for this struct +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `CloneEnum: Default` + `Enum: Clone` + `Enum: Default` + --> $DIR/derive-trait-for-method-call.rs:20:9 + | +LL | impl Foo { + | ^^^^^ ^^^^^^^ ^^^^^^^ --------- + | | | | + | | | unsatisfied trait bound introduced here + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here +note: the trait `Default` must be implemented + --> $SRC_DIR/core/src/default.rs:LL:COL +help: consider annotating `Enum` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0599]: the method `test` exists for struct `Foo`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:34:15 + | +LL | struct Struct { + | ------------- + | | + | doesn't satisfy `Struct: Clone` + | doesn't satisfy `Struct: Default` +... +LL | struct CloneStruct { + | ------------------ doesn't satisfy `CloneStruct: Default` +... +LL | struct Foo (X, Y); + | ---------------- method `test` not found for this struct +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `CloneStruct: Default` + `Struct: Clone` + `Struct: Default` + --> $DIR/derive-trait-for-method-call.rs:20:9 + | +LL | impl Foo { + | ^^^^^ ^^^^^^^ ^^^^^^^ --------- + | | | | + | | | unsatisfied trait bound introduced here + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here +help: consider annotating `CloneStruct` with `#[derive(Default)]` + | +LL | #[derive(Default)] + | +help: consider annotating `Struct` with `#[derive(Clone, Default)]` + | +LL | #[derive(Clone, Default)] + | + +error[E0599]: the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied + --> $DIR/derive-trait-for-method-call.rs:40:15 + | +LL | struct Foo (X, Y); + | ---------------- method `test` not found for this struct +... +LL | let y = x.test(); + | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds + --> $SRC_DIR/std/src/time.rs:LL:COL + | + = note: doesn't satisfy `Instant: Default` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | + = note: doesn't satisfy `Vec: Clone` + | +note: the following trait bounds were not satisfied: + `Instant: Default` + `Vec: Clone` + --> $DIR/derive-trait-for-method-call.rs:20:9 + | +LL | impl Foo { + | ^^^^^ ^^^^^^^ --------- + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs new file mode 100644 index 000000000..a25be862a --- /dev/null +++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.rs @@ -0,0 +1,5 @@ +use std::result; +impl result { //~ ERROR expected type, found module `result` + fn into_future() -> Err {} //~ ERROR expected type, found variant `Err` +} +fn main() {} diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr new file mode 100644 index 000000000..0cd6267b3 --- /dev/null +++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr @@ -0,0 +1,18 @@ +error[E0573]: expected type, found module `result` + --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:2:6 + | +LL | impl result { + | ^^^^^^ help: an enum with a similar name exists: `Result` + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: similarly named enum `Result` defined here + +error[E0573]: expected type, found variant `Err` + --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:3:25 + | +LL | fn into_future() -> Err {} + | ^^^ not a type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs new file mode 100644 index 000000000..ef1c09d21 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.rs @@ -0,0 +1,14 @@ +fn warn(_: &str) {} + +macro_rules! intrinsic_match { + ($intrinsic:expr) => { + warn(format!("unsupported intrinsic {}", $intrinsic)); + //~^ ERROR mismatched types + }; +} + +fn main() { + intrinsic_match! { + "abc" + }; +} diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr new file mode 100644 index 000000000..5dc4e6444 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:11:5 + | +LL | / intrinsic_match! { +LL | | "abc" +LL | | }; + | |_____^ expected `&str`, found struct `String` + | + = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs new file mode 100644 index 000000000..15e0af1de --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +extern crate core; + +pub mod __private { + #[doc(hidden)] + pub use core::option::Option::{self, None, Some}; +} diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs new file mode 100644 index 000000000..5a5079d82 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +extern crate core; + +#[doc(hidden)] +pub mod __private { + pub use core::option::Option::{self, None, Some}; +} diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs new file mode 100644 index 000000000..38dabc9d7 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs @@ -0,0 +1,10 @@ +// aux-build:hidden-child.rs + +// FIXME(compiler-errors): This currently suggests the wrong thing. +// UI test exists to track the problem. + +extern crate hidden_child; + +fn main() { + let x: Option = 1i32; //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr new file mode 100644 index 000000000..67f4ac08d --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/hidden-child.rs:9:26 + | +LL | let x: Option = 1i32; + | ----------- ^^^^ expected enum `Option`, found `i32` + | | + | expected due to this + | + = note: expected enum `Option` + found type `i32` +help: try wrapping the expression in `hidden_child::__private::Some` + | +LL | let x: Option = hidden_child::__private::Some(1i32); + | ++++++++++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs new file mode 100644 index 000000000..4d96d6c16 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs @@ -0,0 +1,7 @@ +// aux-build:hidden-parent.rs + +extern crate hidden_parent; + +fn main() { + let x: Option = 1i32; //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr new file mode 100644 index 000000000..d92b81279 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/hidden-parent.rs:6:26 + | +LL | let x: Option = 1i32; + | ----------- ^^^^ expected enum `Option`, found `i32` + | | + | expected due to this + | + = note: expected enum `Option` + found type `i32` +help: try wrapping the expression in `Some` + | +LL | let x: Option = Some(1i32); + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs new file mode 100644 index 000000000..acb897571 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/96834 +// +// This test case verifies that rustc does not make an unhelpful suggestion: +// +// help: consider wrapping the receiver expression with the appropriate type +// | +// 14 | Pin::new(&mut a).set(0, 3); +// | +++++++++++++ + +// +// We can tell that it isn't helpful, because `Pin::set` takes two parameters (including +// the receiver), but the function call on line 14 supplies three. +fn main() { + let mut a = [0u8; 1]; + a.set(0, 3); //~ERROR +} diff --git a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr new file mode 100644 index 000000000..c66da3ea6 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `set` found for array `[u8; 1]` in the current scope + --> $DIR/dont-suggest-pin-array-dot-set.rs:14:7 + | +LL | a.set(0, 3); + | ^^^ help: there is a method with a similar name: `get` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs new file mode 100644 index 000000000..e19d497f2 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs @@ -0,0 +1,131 @@ +#[derive(Clone)] +enum Either { + One(X), + Two(X), +} + +#[derive(Clone)] +struct X(Y); + +#[derive(Clone)] +struct Y; + + +pub fn main() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let r = &e; + let rm = &mut Either::One(X(Y)); + + let x = X(Y); + let mut xm = X(Y); + + let s = &x; + let sm = &mut X(Y); + + let ve = vec![Either::One(X(Y))]; + + let vr = &ve; + let vrm = &mut vec![Either::One(X(Y))]; + + let vx = vec![X(Y)]; + + let vs = &vx; + let vsm = &mut vec![X(Y)]; + + // test for duplicate suggestions + + let &(X(_t), X(_u)) = &(x.clone(), x.clone()); + //~^ ERROR cannot move + //~| HELP consider removing the borrow + if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the borrow + while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the borrow + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the borrow + &(Either::Two(_t), Either::One(_u)) => (), + //~^ HELP consider removing the borrow + _ => (), + } + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) + //~^ HELP consider removing the borrow + | &(Either::Two(_t), Either::One(_u)) => (), + // FIXME: would really like a suggestion here too + _ => (), + } + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the borrow + &(Either::Two(ref _t), Either::One(ref _u)) => (), + _ => (), + } + match &(e.clone(), e.clone()) { + //~^ ERROR cannot move + &(Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the borrow + (Either::Two(_t), Either::One(_u)) => (), + _ => (), + } + fn f5(&(X(_t), X(_u)): &(X, X)) { } + //~^ ERROR cannot move + //~| HELP consider removing the borrow + + let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone()); + //~^ ERROR cannot move + //~| HELP consider removing the mutable borrow + if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the mutable borrow + while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + //~^ ERROR cannot move + //~| HELP consider removing the mutable borrow + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the mutable borrow + &mut (Either::Two(_t), Either::One(_u)) => (), + //~^ HELP consider removing the mutable borrow + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) + //~^ HELP consider removing the mutable borrow + | &mut (Either::Two(_t), Either::One(_u)) => (), + // FIXME: would really like a suggestion here too + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the mutable borrow + &mut (Either::Two(ref _t), Either::One(ref _u)) => (), + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the mutable borrow + &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (), + _ => (), + } + match &mut (em.clone(), em.clone()) { + //~^ ERROR cannot move + &mut (Either::One(_t), Either::Two(_u)) => (), + //~^ HELP consider removing the mutable borrow + (Either::Two(_t), Either::One(_u)) => (), + _ => (), + } + fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { } + //~^ ERROR cannot move + //~| HELP consider removing the mutable borrow +} diff --git a/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr new file mode 100644 index 000000000..b96b3713f --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr @@ -0,0 +1,309 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:39:27 + | +LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone()); + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - let &(X(_t), X(_u)) = &(x.clone(), x.clone()); +LL + let (X(_t), X(_u)) = &(x.clone(), x.clone()); + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:42:50 + | +LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } +LL + if let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:45:53 + | +LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } +LL + while let (Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { } + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:48:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here +LL | +LL | &(Either::Two(_t), Either::One(_u)) => (), + | -- ...and here -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - &(Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | +help: consider removing the borrow + | +LL - &(Either::Two(_t), Either::One(_u)) => (), +LL + (Either::Two(_t), Either::One(_u)) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:56:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - &(Either::One(_t), Either::Two(_u)) +LL + (Either::One(_t), Either::Two(_u)) + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:64:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - &(Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:71:11 + | +LL | match &(e.clone(), e.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &(Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - &(Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:82:31 + | +LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone()); + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone()); +LL + let (X(_t), X(_u)) = &mut (xm.clone(), xm.clone()); + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:85:54 + | +LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } +LL + if let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:88:57 + | +LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } +LL + while let (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { } + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:91:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here +LL | +LL | &mut (Either::Two(_t), Either::One(_u)) => (), + | -- ...and here -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut (Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | +help: consider removing the mutable borrow + | +LL - &mut (Either::Two(_t), Either::One(_u)) => (), +LL + (Either::Two(_t), Either::One(_u)) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:99:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut (Either::One(_t), Either::Two(_u)) +LL + (Either::One(_t), Either::Two(_u)) + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:107:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut (Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:114:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut (Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:121:11 + | +LL | match &mut (em.clone(), em.clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | &mut (Either::One(_t), Either::Two(_u)) => (), + | -- -- ...and here + | | + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut (Either::One(_t), Either::Two(_u)) => (), +LL + (Either::One(_t), Either::Two(_u)) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/duplicate-suggestions.rs:78:11 + | +LL | fn f5(&(X(_t), X(_u)): &(X, X)) { } + | ^^^^--^^^^^--^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the borrow + | +LL - fn f5(&(X(_t), X(_u)): &(X, X)) { } +LL + fn f5((X(_t), X(_u)): &(X, X)) { } + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/duplicate-suggestions.rs:128:11 + | +LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { } + | ^^^^^^^^--^^^^^--^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { } +LL + fn f6((X(_t), X(_u)): &mut (X, X)) { } + | + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs new file mode 100644 index 000000000..44eac3691 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.rs @@ -0,0 +1,138 @@ +#[derive(Clone)] +enum Either { + One(X), + Two(X), +} + +#[derive(Clone)] +struct X(Y); + +#[derive(Clone)] +struct Y; + +fn consume_fn(_f: F) { } + +fn consume_fnmut(_f: F) { } + +pub fn main() { } + +fn move_into_fn() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let x = X(Y); + + // move into Fn + + consume_fn(|| { + let X(_t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + if let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + while let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) + | Either::Two(_t) => (), + } + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(mut _t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + if let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + while let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(mut _t) + | Either::Two(mut _t) => (), + } + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(mut _t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + }); +} + +fn move_into_fnmut() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let x = X(Y); + + // move into FnMut + + consume_fnmut(|| { + let X(_t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + if let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + while let Either::One(_t) = e { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) + | Either::Two(_t) => (), + } + match e { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(mut _t) = x; + //~^ ERROR cannot move + //~| HELP consider borrowing here + if let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + while let Either::One(mut _t) = em { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(mut _t) + | Either::Two(mut _t) => (), + } + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(mut _t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + match em { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(mut _t) => (), + Either::Two(ref mut _t) => (), + // FIXME: should suggest removing `ref` too + } + }); +} diff --git a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr new file mode 100644 index 000000000..edda2cbc7 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -0,0 +1,448 @@ +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:28:21 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +LL | let X(_t) = x; + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let X(_t) = &x; + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:31:34 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | if let Either::One(_t) = e { } + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | if let Either::One(_t) = &e { } + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:34:37 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | while let Either::One(_t) = e { } + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | while let Either::One(_t) = &e { } + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:37:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match e { + | ^ +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &e { + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:43:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match e { + | ^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &e { + | + + +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:51:25 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | let X(mut _t) = x; + | ------ ^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let X(mut _t) = &x; + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:54:38 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | if let Either::One(mut _t) = em { } + | ------ ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | if let Either::One(mut _t) = &em { } + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:57:41 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | while let Either::One(mut _t) = em { } + | ------ ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | while let Either::One(mut _t) = &em { } + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:60:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match em { + | ^^ +... +LL | Either::One(mut _t) + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &em { + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure + --> $DIR/move-into-closure.rs:66:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fn(|| { + | -- captured by this `Fn` closure +... +LL | match em { + | ^^ +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &em { + | + + +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:85:21 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +LL | let X(_t) = x; + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let X(_t) = &x; + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:88:34 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | if let Either::One(_t) = e { } + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | if let Either::One(_t) = &e { } + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:91:37 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | while let Either::One(_t) = e { } + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | while let Either::One(_t) = &e { } + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:94:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match e { + | ^ +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &e { + | + + +error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:100:15 + | +LL | let e = Either::One(X(Y)); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match e { + | ^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &e { + | + + +error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:108:25 + | +LL | let x = X(Y); + | - captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | let X(mut _t) = x; + | ------ ^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let X(mut _t) = &x; + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:111:38 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | if let Either::One(mut _t) = em { } + | ------ ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | if let Either::One(mut _t) = &em { } + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:114:41 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | while let Either::One(mut _t) = em { } + | ------ ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | while let Either::One(mut _t) = &em { } + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:117:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ +... +LL | Either::One(mut _t) + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &em { + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:123:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &em { + | + + +error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure + --> $DIR/move-into-closure.rs:130:15 + | +LL | let mut em = Either::One(X(Y)); + | ------ captured outer variable +... +LL | consume_fnmut(|| { + | -- captured by this `FnMut` closure +... +LL | match em { + | ^^ +... +LL | Either::One(mut _t) => (), + | ------ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &em { + | + + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.rs b/tests/ui/suggestions/dont-suggest-ref/simple.rs new file mode 100644 index 000000000..1e40e60a1 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ref/simple.rs @@ -0,0 +1,336 @@ +#[derive(Clone)] +enum Either { + One(X), + Two(X), +} + +#[derive(Clone)] +struct X(Y); + +#[derive(Clone)] +struct Y; + +pub fn main() { + let e = Either::One(X(Y)); + let mut em = Either::One(X(Y)); + + let r = &e; + let rm = &mut Either::One(X(Y)); + + let x = X(Y); + let mut xm = X(Y); + + let s = &x; + let sm = &mut X(Y); + + let ve = vec![Either::One(X(Y))]; + + let vr = &ve; + let vrm = &mut vec![Either::One(X(Y))]; + + let vx = vec![X(Y)]; + + let vs = &vx; + let vsm = &mut vec![X(Y)]; + + // move from Either/X place + + let X(_t) = *s; + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + if let Either::One(_t) = *r { } + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + while let Either::One(_t) = *r { } + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + match *r { + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + Either::One(_t) + | Either::Two(_t) => (), + } + match *r { + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(_t) = *sm; + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + if let Either::One(_t) = *rm { } + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + while let Either::One(_t) = *rm { } + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + match *rm { + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + Either::One(_t) + | Either::Two(_t) => (), + } + match *rm { + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + match *rm { + //~^ ERROR cannot move + //~| HELP consider removing the dereference here + Either::One(_t) => (), + Either::Two(ref mut _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(_t) = vs[0]; + //~^ ERROR cannot move + //~| HELP consider borrowing here + if let Either::One(_t) = vr[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + while let Either::One(_t) = vr[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + match vr[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) + | Either::Two(_t) => (), + } + match vr[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + + let X(_t) = vsm[0]; + //~^ ERROR cannot move + //~| HELP consider borrowing here + if let Either::One(_t) = vrm[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + while let Either::One(_t) = vrm[0] { } + //~^ ERROR cannot move + //~| HELP consider borrowing here + match vrm[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) + | Either::Two(_t) => (), + } + match vrm[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) => (), + Either::Two(ref _t) => (), + // FIXME: should suggest removing `ref` too + } + match vrm[0] { + //~^ ERROR cannot move + //~| HELP consider borrowing here + Either::One(_t) => (), + Either::Two(ref mut _t) => (), + // FIXME: should suggest removing `ref` too + } + + // move from &Either/&X place + + let &X(_t) = s; + //~^ ERROR cannot move + //~| HELP consider removing + if let &Either::One(_t) = r { } + //~^ ERROR cannot move + //~| HELP consider removing + while let &Either::One(_t) = r { } + //~^ ERROR cannot move + //~| HELP consider removing + match r { + //~^ ERROR cannot move + &Either::One(_t) + //~^ HELP consider removing + | &Either::Two(_t) => (), + // FIXME: would really like a suggestion here too + } + match r { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing + &Either::Two(ref _t) => (), + } + match r { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing + Either::Two(_t) => (), + } + fn f1(&X(_t): &X) { } + //~^ ERROR cannot move + //~| HELP consider removing + + let &mut X(_t) = sm; + //~^ ERROR cannot move + //~| HELP consider removing + if let &mut Either::One(_t) = rm { } + //~^ ERROR cannot move + //~| HELP consider removing + while let &mut Either::One(_t) = rm { } + //~^ ERROR cannot move + //~| HELP consider removing + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + &mut Either::Two(_t) => (), + //~^ HELP consider removing + } + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + &mut Either::Two(ref _t) => (), + } + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + &mut Either::Two(ref mut _t) => (), + } + match rm { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + Either::Two(_t) => (), + } + fn f2(&mut X(_t): &mut X) { } + //~^ ERROR cannot move + //~| HELP consider removing + + // move from tuple of &Either/&X + + // FIXME: These should have suggestions. + + let (&X(_t),) = (&x.clone(),); + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + if let (&Either::One(_t),) = (&e.clone(),) { } + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + while let (&Either::One(_t),) = (&e.clone(),) { } + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + match (&e.clone(),) { + //~^ ERROR cannot move + (&Either::One(_t),) + //~^ HELP consider borrowing the pattern binding + | (&Either::Two(_t),) => (), + } + fn f3((&X(_t),): (&X,)) { } + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + + let (&mut X(_t),) = (&mut xm.clone(),); + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + if let (&mut Either::One(_t),) = (&mut em.clone(),) { } + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + while let (&mut Either::One(_t),) = (&mut em.clone(),) { } + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + match (&mut em.clone(),) { + //~^ ERROR cannot move + (&mut Either::One(_t),) => (), + //~^ HELP consider borrowing the pattern binding + (&mut Either::Two(_t),) => (), + //~^ HELP consider borrowing the pattern binding + } + fn f4((&mut X(_t),): (&mut X,)) { } + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + + // move from &Either/&X value + + let &X(_t) = &x; + //~^ ERROR cannot move + //~| HELP consider removing + if let &Either::One(_t) = &e { } + //~^ ERROR cannot move + //~| HELP consider removing + while let &Either::One(_t) = &e { } + //~^ ERROR cannot move + //~| HELP consider removing + match &e { + //~^ ERROR cannot move + &Either::One(_t) + //~^ HELP consider removing + | &Either::Two(_t) => (), + // FIXME: would really like a suggestion here too + } + match &e { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing + &Either::Two(ref _t) => (), + } + match &e { + //~^ ERROR cannot move + &Either::One(_t) => (), + //~^ HELP consider removing + Either::Two(_t) => (), + } + + let &mut X(_t) = &mut xm; + //~^ ERROR cannot move + //~| HELP consider removing + if let &mut Either::One(_t) = &mut em { } + //~^ ERROR cannot move + //~| HELP consider removing + while let &mut Either::One(_t) = &mut em { } + //~^ ERROR cannot move + //~| HELP consider removing + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) + //~^ HELP consider removing + | &mut Either::Two(_t) => (), + // FIXME: would really like a suggestion here too + } + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + &mut Either::Two(ref _t) => (), + } + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + &mut Either::Two(ref mut _t) => (), + } + match &mut em { + //~^ ERROR cannot move + &mut Either::One(_t) => (), + //~^ HELP consider removing + Either::Two(_t) => (), + } +} + +struct Testing { + a: Option +} + +fn testing(a: &Testing) { + let Some(_s) = a.a else { + //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding + return; + }; +} diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.stderr b/tests/ui/suggestions/dont-suggest-ref/simple.stderr new file mode 100644 index 000000000..526326524 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ref/simple.stderr @@ -0,0 +1,985 @@ +error[E0507]: cannot move out of `s` which is behind a shared reference + --> $DIR/simple.rs:38:17 + | +LL | let X(_t) = *s; + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let X(_t) = *s; +LL + let X(_t) = s; + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:41:30 + | +LL | if let Either::One(_t) = *r { } + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - if let Either::One(_t) = *r { } +LL + if let Either::One(_t) = r { } + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:44:33 + | +LL | while let Either::One(_t) = *r { } + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - while let Either::One(_t) = *r { } +LL + while let Either::One(_t) = r { } + | + +error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference + --> $DIR/simple.rs:47:11 + | +LL | match *r { + | ^^ +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *r { +LL + match r { + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:53:11 + | +LL | match *r { + | ^^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *r { +LL + match r { + | + +error[E0507]: cannot move out of `sm` which is behind a mutable reference + --> $DIR/simple.rs:61:17 + | +LL | let X(_t) = *sm; + | -- ^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - let X(_t) = *sm; +LL + let X(_t) = sm; + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:64:30 + | +LL | if let Either::One(_t) = *rm { } + | -- ^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - if let Either::One(_t) = *rm { } +LL + if let Either::One(_t) = rm { } + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:67:33 + | +LL | while let Either::One(_t) = *rm { } + | -- ^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - while let Either::One(_t) = *rm { } +LL + while let Either::One(_t) = rm { } + | + +error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference + --> $DIR/simple.rs:70:11 + | +LL | match *rm { + | ^^^ +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *rm { +LL + match rm { + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:76:11 + | +LL | match *rm { + | ^^^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *rm { +LL + match rm { + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:83:11 + | +LL | match *rm { + | ^^^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the dereference here + | +LL - match *rm { +LL + match rm { + | + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:91:17 + | +LL | let X(_t) = vs[0]; + | -- ^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let X(_t) = &vs[0]; + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:94:30 + | +LL | if let Either::One(_t) = vr[0] { } + | -- ^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | if let Either::One(_t) = &vr[0] { } + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:97:33 + | +LL | while let Either::One(_t) = vr[0] { } + | -- ^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | while let Either::One(_t) = &vr[0] { } + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:100:11 + | +LL | match vr[0] { + | ^^^^^ +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &vr[0] { + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:106:11 + | +LL | match vr[0] { + | ^^^^^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &vr[0] { + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:114:17 + | +LL | let X(_t) = vsm[0]; + | -- ^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let X(_t) = &vsm[0]; + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:117:30 + | +LL | if let Either::One(_t) = vrm[0] { } + | -- ^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | if let Either::One(_t) = &vrm[0] { } + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:120:33 + | +LL | while let Either::One(_t) = vrm[0] { } + | -- ^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | while let Either::One(_t) = &vrm[0] { } + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:123:11 + | +LL | match vrm[0] { + | ^^^^^^ +... +LL | Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &vrm[0] { + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:129:11 + | +LL | match vrm[0] { + | ^^^^^^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &vrm[0] { + | + + +error[E0507]: cannot move out of index of `Vec` + --> $DIR/simple.rs:136:11 + | +LL | match vrm[0] { + | ^^^^^^ +... +LL | Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | match &vrm[0] { + | + + +error[E0507]: cannot move out of `s` which is behind a shared reference + --> $DIR/simple.rs:146:18 + | +LL | let &X(_t) = s; + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - let &X(_t) = s; +LL + let X(_t) = s; + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:149:31 + | +LL | if let &Either::One(_t) = r { } + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - if let &Either::One(_t) = r { } +LL + if let Either::One(_t) = r { } + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:152:34 + | +LL | while let &Either::One(_t) = r { } + | -- ^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - while let &Either::One(_t) = r { } +LL + while let Either::One(_t) = r { } + | + +error[E0507]: cannot move out of `r` as enum variant `Two` which is behind a shared reference + --> $DIR/simple.rs:155:11 + | +LL | match r { + | ^ +LL | +LL | &Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Either::One(_t) +LL + Either::One(_t) + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:162:11 + | +LL | match r { + | ^ +LL | +LL | &Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference + --> $DIR/simple.rs:168:11 + | +LL | match r { + | ^ +LL | +LL | &Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of `sm` which is behind a mutable reference + --> $DIR/simple.rs:178:22 + | +LL | let &mut X(_t) = sm; + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - let &mut X(_t) = sm; +LL + let X(_t) = sm; + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:181:35 + | +LL | if let &mut Either::One(_t) = rm { } + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - if let &mut Either::One(_t) = rm { } +LL + if let Either::One(_t) = rm { } + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:184:38 + | +LL | while let &mut Either::One(_t) = rm { } + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - while let &mut Either::One(_t) = rm { } +LL + while let Either::One(_t) = rm { } + | + +error[E0507]: cannot move out of `rm` as enum variant `Two` which is behind a mutable reference + --> $DIR/simple.rs:187:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -- data moved here +LL | +LL | &mut Either::Two(_t) => (), + | -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | +help: consider removing the mutable borrow + | +LL - &mut Either::Two(_t) => (), +LL + Either::Two(_t) => (), + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:194:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:200:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference + --> $DIR/simple.rs:206:11 + | +LL | match rm { + | ^^ +LL | +LL | &mut Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:220:21 + | +LL | let (&X(_t),) = (&x.clone(),); + | -- ^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (&X(ref _t),) = (&x.clone(),); + | +++ + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:223:34 + | +LL | if let (&Either::One(_t),) = (&e.clone(),) { } + | -- ^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let (&Either::One(ref _t),) = (&e.clone(),) { } + | +++ + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:226:37 + | +LL | while let (&Either::One(_t),) = (&e.clone(),) { } + | -- ^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | while let (&Either::One(ref _t),) = (&e.clone(),) { } + | +++ + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:229:11 + | +LL | match (&e.clone(),) { + | ^^^^^^^^^^^^^ +LL | +LL | (&Either::One(_t),) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (&Either::One(ref _t),) + | +++ + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:239:25 + | +LL | let (&mut X(_t),) = (&mut xm.clone(),); + | -- ^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (&mut X(ref _t),) = (&mut xm.clone(),); + | +++ + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:242:38 + | +LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { } + | -- ^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { } + | +++ + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:245:41 + | +LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { } + | -- ^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { } + | +++ + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:248:11 + | +LL | match (&mut em.clone(),) { + | ^^^^^^^^^^^^^^^^^^ +LL | +LL | (&mut Either::One(_t),) => (), + | -- data moved here +LL | +LL | (&mut Either::Two(_t),) => (), + | -- ...and here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | (&mut Either::One(ref _t),) => (), + | +++ +help: consider borrowing the pattern binding + | +LL | (&mut Either::Two(ref _t),) => (), + | +++ + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:261:18 + | +LL | let &X(_t) = &x; + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - let &X(_t) = &x; +LL + let X(_t) = &x; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:264:31 + | +LL | if let &Either::One(_t) = &e { } + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - if let &Either::One(_t) = &e { } +LL + if let Either::One(_t) = &e { } + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:267:34 + | +LL | while let &Either::One(_t) = &e { } + | -- ^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - while let &Either::One(_t) = &e { } +LL + while let Either::One(_t) = &e { } + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:270:11 + | +LL | match &e { + | ^^ +LL | +LL | &Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Either::One(_t) +LL + Either::One(_t) + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:277:11 + | +LL | match &e { + | ^^ +LL | +LL | &Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:283:11 + | +LL | match &e { + | ^^ +LL | +LL | &Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - &Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:290:22 + | +LL | let &mut X(_t) = &mut xm; + | -- ^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - let &mut X(_t) = &mut xm; +LL + let X(_t) = &mut xm; + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:293:35 + | +LL | if let &mut Either::One(_t) = &mut em { } + | -- ^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - if let &mut Either::One(_t) = &mut em { } +LL + if let Either::One(_t) = &mut em { } + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:296:38 + | +LL | while let &mut Either::One(_t) = &mut em { } + | -- ^^^^^^^ + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - while let &mut Either::One(_t) = &mut em { } +LL + while let Either::One(_t) = &mut em { } + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:299:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) +LL + Either::One(_t) + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:306:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:312:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:318:11 + | +LL | match &mut em { + | ^^^^^^^ +LL | +LL | &mut Either::One(_t) => (), + | -- + | | + | data moved here + | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - &mut Either::One(_t) => (), +LL + Either::One(_t) => (), + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:174:11 + | +LL | fn f1(&X(_t): &X) { } + | ^^^--^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - fn f1(&X(_t): &X) { } +LL + fn f1(X(_t): &X) { } + | + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:212:11 + | +LL | fn f2(&mut X(_t): &mut X) { } + | ^^^^^^^--^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider removing the mutable borrow + | +LL - fn f2(&mut X(_t): &mut X) { } +LL + fn f2(X(_t): &mut X) { } + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/simple.rs:235:11 + | +LL | fn f3((&X(_t),): (&X,)) { } + | ^^^^--^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | fn f3((&X(ref _t),): (&X,)) { } + | +++ + +error[E0507]: cannot move out of a mutable reference + --> $DIR/simple.rs:255:11 + | +LL | fn f4((&mut X(_t),): (&mut X,)) { } + | ^^^^^^^^--^^^ + | | + | data moved here + | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | fn f4((&mut X(ref _t),): (&mut X,)) { } + | +++ + +error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference + --> $DIR/simple.rs:331:20 + | +LL | let Some(_s) = a.a else { + | -- ^^^ + | | + | data moved here + | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let Some(ref _s) = a.a else { + | +++ + +error: aborting due to 61 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/dont-suggest-try_into-in-macros.rs b/tests/ui/suggestions/dont-suggest-try_into-in-macros.rs new file mode 100644 index 000000000..d625199c9 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-try_into-in-macros.rs @@ -0,0 +1,3 @@ +fn main() { + assert_eq!(10u64, 10usize); //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr new file mode 100644 index 000000000..bc6342004 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-try_into-in-macros.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-try_into-in-macros.rs:2:5 + | +LL | assert_eq!(10u64, 10usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected `u64`, found `usize` + | expected because this is `u64` + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/dont-suggest-ufcs-for-const.rs b/tests/ui/suggestions/dont-suggest-ufcs-for-const.rs new file mode 100644 index 000000000..06cf243f1 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ufcs-for-const.rs @@ -0,0 +1,4 @@ +fn main() { + 1_u32.MAX(); + //~^ ERROR no method named `MAX` found for type `u32` in the current scope +} diff --git a/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr b/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr new file mode 100644 index 000000000..0d9543e0b --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-ufcs-for-const.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `MAX` found for type `u32` in the current scope + --> $DIR/dont-suggest-ufcs-for-const.rs:2:11 + | +LL | 1_u32.MAX(); + | ^^^ method not found in `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/dont-try-removing-the-field.rs b/tests/ui/suggestions/dont-try-removing-the-field.rs new file mode 100644 index 000000000..948aa2b94 --- /dev/null +++ b/tests/ui/suggestions/dont-try-removing-the-field.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(dead_code)] + +struct Foo { + foo: i32, + bar: i32, + baz: (), +} + +fn use_foo(x: Foo) -> (i32, i32) { + let Foo { foo, bar, baz } = x; //~ WARNING unused variable: `baz` + //~| help: try ignoring the field + return (foo, bar); +} + +fn main() {} diff --git a/tests/ui/suggestions/dont-try-removing-the-field.stderr b/tests/ui/suggestions/dont-try-removing-the-field.stderr new file mode 100644 index 000000000..263171a4a --- /dev/null +++ b/tests/ui/suggestions/dont-try-removing-the-field.stderr @@ -0,0 +1,10 @@ +warning: unused variable: `baz` + --> $DIR/dont-try-removing-the-field.rs:12:25 + | +LL | let Foo { foo, bar, baz } = x; + | ^^^ help: try ignoring the field: `baz: _` + | + = note: `#[warn(unused_variables)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs new file mode 100644 index 000000000..baa2128eb --- /dev/null +++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs @@ -0,0 +1,21 @@ +mod banana { + //~^ HELP the following traits are implemented but not in scope + pub struct Chaenomeles; + + pub trait Apple { + fn pick(&self) {} + } + impl Apple for Chaenomeles {} + + pub trait Peach { + fn pick(&self, a: &mut ()) {} + } + impl Peach for Box {} + impl Peach for Chaenomeles {} +} + +fn main() { + banana::Chaenomeles.pick() + //~^ ERROR no method named + //~| HELP items from traits can only be used if the trait is in scope +} diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr new file mode 100644 index 000000000..4658ecb3a --- /dev/null +++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope + --> $DIR/dont-wrap-ambiguous-receivers.rs:18:25 + | +LL | pub struct Chaenomeles; + | ---------------------- method `pick` not found for this struct +... +LL | banana::Chaenomeles.pick() + | ^^^^ method not found in `Chaenomeles` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use banana::Apple; + | +LL | use banana::Peach; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed new file mode 100644 index 000000000..6499c92bc --- /dev/null +++ b/tests/ui/suggestions/enum-method-probe.fixed @@ -0,0 +1,59 @@ +// compile-flags: --edition=2021 +// run-rustfix + +#![allow(unused)] + +struct Foo; + +impl Foo { + fn get(&self) -> u8 { + 42 + } +} + +fn test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +async fn async_test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +fn test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.expect("REASON").get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +async fn async_test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.expect("REASON").get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +fn test_option_in_option() -> Option<()> { + let res: Option<_> = Some(Foo); + res?.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP use the `?` operator + Some(()) +} + +fn test_option_in_unit_return() { + let res: Option<_> = Some(Foo); + res.expect("REASON").get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None` +} + +fn main() {} diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs new file mode 100644 index 000000000..18ea8ed8a --- /dev/null +++ b/tests/ui/suggestions/enum-method-probe.rs @@ -0,0 +1,59 @@ +// compile-flags: --edition=2021 +// run-rustfix + +#![allow(unused)] + +struct Foo; + +impl Foo { + fn get(&self) -> u8 { + 42 + } +} + +fn test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +async fn async_test_result_in_result() -> Result<(), ()> { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP use the `?` operator + Ok(()) +} + +fn test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +async fn async_test_result_in_unit_return() { + let res: Result<_, ()> = Ok(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Result` in the current scope + //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` +} + +fn test_option_in_option() -> Option<()> { + let res: Option<_> = Some(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP use the `?` operator + Some(()) +} + +fn test_option_in_unit_return() { + let res: Option<_> = Some(Foo); + res.get(); + //~^ ERROR no method named `get` found for enum `Option` in the current scope + //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None` +} + +fn main() {} diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr new file mode 100644 index 000000000..6ed14984f --- /dev/null +++ b/tests/ui/suggestions/enum-method-probe.stderr @@ -0,0 +1,99 @@ +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:24:9 + | +LL | res.get(); + | ^^^ method not found in `Result` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:39:9 + | +LL | res.get(); + | ^^^ method not found in `Result` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:16:9 + | +LL | res.get(); + | ^^^ method not found in `Result` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating a `Result::Err` value to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Result` in the current scope + --> $DIR/enum-method-probe.rs:32:9 + | +LL | res.get(); + | ^^^ method not found in `Result` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error[E0599]: no method named `get` found for enum `Option` in the current scope + --> $DIR/enum-method-probe.rs:46:9 + | +LL | res.get(); + | ^^^ method not found in `Option` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: use the `?` operator to extract the `Foo` value, propagating an `Option::None` value to the caller + | +LL | res?.get(); + | + + +error[E0599]: no method named `get` found for enum `Option` in the current scope + --> $DIR/enum-method-probe.rs:54:9 + | +LL | res.get(); + | ^^^ method not found in `Option` + | +note: the method `get` exists on the type `Foo` + --> $DIR/enum-method-probe.rs:9:5 + | +LL | fn get(&self) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ +help: consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None` + | +LL | res.expect("REASON").get(); + | +++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/enum-variant-arg-mismatch.rs b/tests/ui/suggestions/enum-variant-arg-mismatch.rs new file mode 100644 index 000000000..8de5bae92 --- /dev/null +++ b/tests/ui/suggestions/enum-variant-arg-mismatch.rs @@ -0,0 +1,10 @@ +pub enum Sexpr<'a> { + Ident(&'a str), +} + +fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {} + +fn main() { + map(Sexpr::Ident); + //~^ ERROR type mismatch in function arguments +} diff --git a/tests/ui/suggestions/enum-variant-arg-mismatch.stderr b/tests/ui/suggestions/enum-variant-arg-mismatch.stderr new file mode 100644 index 000000000..f76019b70 --- /dev/null +++ b/tests/ui/suggestions/enum-variant-arg-mismatch.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in function arguments + --> $DIR/enum-variant-arg-mismatch.rs:8:9 + | +LL | Ident(&'a str), + | ----- found signature defined here +... +LL | map(Sexpr::Ident); + | --- ^^^^^^^^^^^^ expected due to this + | | + | required by a bound introduced by this call + | + = note: expected function signature `fn(String) -> _` + found function signature `fn(&str) -> _` +note: required by a bound in `map` + --> $DIR/enum-variant-arg-mismatch.rs:5:15 + | +LL | fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs new file mode 100644 index 000000000..7e9c5492d --- /dev/null +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.rs @@ -0,0 +1,33 @@ +// edition:2018 +#![allow(dead_code)] +use std::future::Future; +use std::pin::Pin; + +type BoxFuture<'a, T> = Pin + Send + 'a>>; +// ^^^^^^^^^ This would come from the `futures` crate in real code. + +fn foo + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + // We could instead use an `async` block, but this way we have no std spans. + x //~ ERROR mismatched types +} + +fn bar + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + Box::new(x) //~ ERROR mismatched types +} + +fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + Pin::new(x) //~ ERROR mismatched types + //~^ ERROR E0277 +} + +fn qux + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + Pin::new(Box::new(x)) //~ ERROR E0277 +} + +fn zap() -> BoxFuture<'static, i32> { + async { //~ ERROR mismatched types + 42 + } +} + +fn main() {} diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr new file mode 100644 index 000000000..b1e04dab8 --- /dev/null +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -0,0 +1,94 @@ +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:11:5 + | +LL | fn foo + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + | - this type parameter ----------------------- expected `Pin + Send + 'static)>>` because of return type +LL | // We could instead use an `async` block, but this way we have no std spans. +LL | x + | ^ expected struct `Pin`, found type parameter `F` + | + = note: expected struct `Pin + Send + 'static)>>` + found type parameter `F` +help: you need to pin and box this expression + | +LL | Box::pin(x) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:15:5 + | +LL | fn bar + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + | ----------------------- expected `Pin + Send + 'static)>>` because of return type +LL | Box::new(x) + | ^^^^^^^^^^^ expected struct `Pin`, found struct `Box` + | + = note: expected struct `Pin + Send + 'static)>>` + found struct `Box` + = help: use `Box::pin` + +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14 + | +LL | fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { + | - this type parameter +LL | Pin::new(x) + | -------- ^ expected struct `Box`, found type parameter `F` + | | + | arguments to this function are incorrect + | help: use `Box::pin` to pin and box this expression: `Box::pin` + | + = note: expected struct `Box + Send>` + found type parameter `F` +note: associated function defined here + --> $SRC_DIR/core/src/pin.rs:LL:COL + +error[E0277]: `dyn Future + Send` cannot be unpinned + --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14 + | +LL | Pin::new(x) + | -------- ^ the trait `Unpin` is not implemented for `dyn Future + Send` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `Pin::

::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + +error[E0277]: `dyn Future + Send` cannot be unpinned + --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14 + | +LL | Pin::new(Box::new(x)) + | -------- ^^^^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future + Send` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `Pin::

::new` + --> $SRC_DIR/core/src/pin.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/expected-boxed-future-isnt-pinned.rs:28:5 + | +LL | / async { +LL | | 42 +LL | | } + | | ^ + | | | + | |_____expected struct `Pin`, found `async` block + | arguments to this function are incorrect + | + = note: expected struct `Pin + Send>>` + found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]` +note: function defined here + --> $SRC_DIR/core/src/future/mod.rs:LL:COL +help: you need to pin and box this expression + | +LL ~ Box::pin(async { +LL | 42 +LL ~ }) + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/field-access-considering-privacy.rs b/tests/ui/suggestions/field-access-considering-privacy.rs new file mode 100644 index 000000000..3de06b214 --- /dev/null +++ b/tests/ui/suggestions/field-access-considering-privacy.rs @@ -0,0 +1,35 @@ +use a::TyCtxt; + +mod a { + use std::ops::Deref; + pub struct TyCtxt<'tcx> { + gcx: &'tcx GlobalCtxt<'tcx>, + } + + impl<'tcx> Deref for TyCtxt<'tcx> { + type Target = &'tcx GlobalCtxt<'tcx>; + + fn deref(&self) -> &Self::Target { + &self.gcx + } + } + + pub struct GlobalCtxt<'tcx> { + pub sess: &'tcx Session, + _t: &'tcx (), + } + + pub struct Session { + pub opts: (), + } +} + +mod b { + fn foo<'tcx>(tcx: crate::TyCtxt<'tcx>) { + tcx.opts; + //~^ ERROR no field `opts` on type `TyCtxt<'tcx>` + //~| HELP one of the expressions' fields has a field of the same name + } +} + +fn main() {} diff --git a/tests/ui/suggestions/field-access-considering-privacy.stderr b/tests/ui/suggestions/field-access-considering-privacy.stderr new file mode 100644 index 000000000..cbf6f3d10 --- /dev/null +++ b/tests/ui/suggestions/field-access-considering-privacy.stderr @@ -0,0 +1,14 @@ +error[E0609]: no field `opts` on type `TyCtxt<'tcx>` + --> $DIR/field-access-considering-privacy.rs:29:13 + | +LL | tcx.opts; + | ^^^^ unknown field + | +help: one of the expressions' fields has a field of the same name + | +LL | tcx.sess.opts; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/field-access.fixed b/tests/ui/suggestions/field-access.fixed new file mode 100644 index 000000000..ed9aef6e3 --- /dev/null +++ b/tests/ui/suggestions/field-access.fixed @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct A { + b: B, +} + +enum B { + Fst, + Snd, +} + +union Foo { + bar: u32, + qux: f32, +} + +fn main() { + let a = A { b: B::Fst }; + if let B::Fst = a.b {}; //~ ERROR mismatched types [E0308] + //~^ HELP you might have meant to use field `b` whose type is `B` + match a.b { + //~^ HELP you might have meant to use field `b` whose type is `B` + //~| HELP you might have meant to use field `b` whose type is `B` + B::Fst => (), //~ ERROR mismatched types [E0308] + B::Snd => (), //~ ERROR mismatched types [E0308] + } + + let foo = Foo { bar: 42 }; + match unsafe { foo.bar } { + //~^ HELP you might have meant to use field `bar` whose type is `u32` + 1u32 => (), //~ ERROR mismatched types [E0308] + _ => (), + } +} diff --git a/tests/ui/suggestions/field-access.rs b/tests/ui/suggestions/field-access.rs new file mode 100644 index 000000000..d80488e8a --- /dev/null +++ b/tests/ui/suggestions/field-access.rs @@ -0,0 +1,35 @@ +// run-rustfix +#![allow(dead_code)] + +struct A { + b: B, +} + +enum B { + Fst, + Snd, +} + +union Foo { + bar: u32, + qux: f32, +} + +fn main() { + let a = A { b: B::Fst }; + if let B::Fst = a {}; //~ ERROR mismatched types [E0308] + //~^ HELP you might have meant to use field `b` whose type is `B` + match a { + //~^ HELP you might have meant to use field `b` whose type is `B` + //~| HELP you might have meant to use field `b` whose type is `B` + B::Fst => (), //~ ERROR mismatched types [E0308] + B::Snd => (), //~ ERROR mismatched types [E0308] + } + + let foo = Foo { bar: 42 }; + match foo { + //~^ HELP you might have meant to use field `bar` whose type is `u32` + 1u32 => (), //~ ERROR mismatched types [E0308] + _ => (), + } +} diff --git a/tests/ui/suggestions/field-access.stderr b/tests/ui/suggestions/field-access.stderr new file mode 100644 index 000000000..b9f0f788b --- /dev/null +++ b/tests/ui/suggestions/field-access.stderr @@ -0,0 +1,67 @@ +error[E0308]: mismatched types + --> $DIR/field-access.rs:20:12 + | +LL | Fst, + | --- unit variant defined here +... +LL | if let B::Fst = a {}; + | ^^^^^^ - this expression has type `A` + | | + | expected struct `A`, found enum `B` + | +help: you might have meant to use field `b` whose type is `B` + | +LL | if let B::Fst = a.b {}; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/field-access.rs:25:9 + | +LL | Fst, + | --- unit variant defined here +... +LL | match a { + | - this expression has type `A` +... +LL | B::Fst => (), + | ^^^^^^ expected struct `A`, found enum `B` + | +help: you might have meant to use field `b` whose type is `B` + | +LL | match a.b { + | ~~~ + +error[E0308]: mismatched types + --> $DIR/field-access.rs:26:9 + | +LL | Snd, + | --- unit variant defined here +... +LL | match a { + | - this expression has type `A` +... +LL | B::Snd => (), + | ^^^^^^ expected struct `A`, found enum `B` + | +help: you might have meant to use field `b` whose type is `B` + | +LL | match a.b { + | ~~~ + +error[E0308]: mismatched types + --> $DIR/field-access.rs:32:9 + | +LL | match foo { + | --- this expression has type `Foo` +LL | +LL | 1u32 => (), + | ^^^^ expected union `Foo`, found `u32` + | +help: you might have meant to use field `bar` whose type is `u32` + | +LL | match unsafe { foo.bar } { + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/field-has-method.rs b/tests/ui/suggestions/field-has-method.rs new file mode 100644 index 000000000..980000151 --- /dev/null +++ b/tests/ui/suggestions/field-has-method.rs @@ -0,0 +1,23 @@ +struct Kind; + +struct Ty { + kind: Kind, +} + +impl Ty { + fn kind(&self) -> Kind { + todo!() + } +} + +struct InferOk { + value: T, + predicates: Vec<()>, +} + +fn foo(i: InferOk) { + let k = i.kind(); + //~^ no method named `kind` found for struct `InferOk` in the current scope +} + +fn main() {} diff --git a/tests/ui/suggestions/field-has-method.stderr b/tests/ui/suggestions/field-has-method.stderr new file mode 100644 index 000000000..def164017 --- /dev/null +++ b/tests/ui/suggestions/field-has-method.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `kind` found for struct `InferOk` in the current scope + --> $DIR/field-has-method.rs:19:15 + | +LL | struct InferOk { + | ----------------- method `kind` not found for this struct +... +LL | let k = i.kind(); + | ^^^^ method not found in `InferOk` + | +help: one of the expressions' fields has a method of the same name + | +LL | let k = i.value.kind(); + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs new file mode 100644 index 000000000..4303e5c54 --- /dev/null +++ b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs @@ -0,0 +1,20 @@ +// edition:2018 +trait T { + type O; +} + +struct S; + +impl T for S { + type O = (); +} + +fn foo() -> impl T { S } + +fn bar(f: impl T) {} + +fn main() { + bar(foo); //~ERROR E0277 + let closure = || S; + bar(closure); //~ERROR E0277 +} diff --git a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr new file mode 100644 index 000000000..955148315 --- /dev/null +++ b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -0,0 +1,39 @@ +error[E0277]: the trait bound `fn() -> impl T {foo}: T` is not satisfied + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9 + | +LL | bar(foo); + | --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T {foo}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 + | +LL | fn bar(f: impl T) {} + | ^^^^^^^ required by this bound in `bar` +help: use parentheses to call this function + | +LL | bar(foo()); + | ++ + +error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 + | +LL | bar(closure); + | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 + | +LL | fn bar(f: impl T) {} + | ^^^^^^^ required by this bound in `bar` +help: use parentheses to call this closure + | +LL | bar(closure()); + | ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/fn-missing-lifetime-in-item.rs b/tests/ui/suggestions/fn-missing-lifetime-in-item.rs new file mode 100644 index 000000000..dac6610b3 --- /dev/null +++ b/tests/ui/suggestions/fn-missing-lifetime-in-item.rs @@ -0,0 +1,8 @@ +struct S1 &'a i32>(F); //~ ERROR use of undeclared lifetime name `'a` +struct S2 &i32>(F); //~ ERROR missing lifetime specifier +struct S3 Fn(&i32, &i32) -> &'a i32>(F); +//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear +struct S4 Fn(&'x i32, &'x i32) -> &'x i32>(F); +const C: Option Fn(&usize, &usize) -> &'a usize>> = None; +//~^ ERROR binding for associated type `Output` references lifetime `'a`, which does not appear +fn main() {} diff --git a/tests/ui/suggestions/fn-missing-lifetime-in-item.stderr b/tests/ui/suggestions/fn-missing-lifetime-in-item.stderr new file mode 100644 index 000000000..6d7c3d730 --- /dev/null +++ b/tests/ui/suggestions/fn-missing-lifetime-in-item.stderr @@ -0,0 +1,48 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/fn-missing-lifetime-in-item.rs:1:33 + | +LL | struct S1 &'a i32>(F); + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | struct S1 Fn(&i32, &i32) -> &'a i32>(F); + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | struct S1<'a, F: Fn(&i32, &i32) -> &'a i32>(F); + | +++ + +error[E0106]: missing lifetime specifier + --> $DIR/fn-missing-lifetime-in-item.rs:2:32 + | +LL | struct S2 &i32>(F); + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | struct S2 Fn(&'a i32, &'a i32) -> &'a i32>(F); + | +++++++ ++ ++ ++ +help: consider introducing a named lifetime parameter + | +LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F); + | +++ ++ ++ ++ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/fn-missing-lifetime-in-item.rs:3:40 + | +LL | struct S3 Fn(&i32, &i32) -> &'a i32>(F); + | ^^^^^^^ + +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/fn-missing-lifetime-in-item.rs:6:55 + | +LL | const C: Option Fn(&usize, &usize) -> &'a usize>> = None; + | ^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0106, E0261, E0582. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/fn-needing-specified-return-type-param.rs b/tests/ui/suggestions/fn-needing-specified-return-type-param.rs new file mode 100644 index 000000000..bcc91b5cb --- /dev/null +++ b/tests/ui/suggestions/fn-needing-specified-return-type-param.rs @@ -0,0 +1,7 @@ +fn f() -> A { unimplemented!() } +fn foo() { + let _ = f; + //~^ ERROR type annotations needed + //~| HELP consider specifying the generic argument +} +fn main() {} diff --git a/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr b/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr new file mode 100644 index 000000000..9dea667fb --- /dev/null +++ b/tests/ui/suggestions/fn-needing-specified-return-type-param.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/fn-needing-specified-return-type-param.rs:3:13 + | +LL | let _ = f; + | ^ cannot infer type of the type parameter `A` declared on the function `f` + | +help: consider specifying the generic argument + | +LL | let _ = f::; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs new file mode 100644 index 000000000..ae1dbfeea --- /dev/null +++ b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.rs @@ -0,0 +1,19 @@ +fn foo(a: usize, b: usize) -> usize { a } + +struct S(usize, usize); + +trait T { + fn baz(x: usize, y: usize) -> usize { x } +} + +fn main() { + let _: usize = foo(_, _); + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + let _: S = S(_, _); + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment + let _: usize = T::baz(_, _); + //~^ ERROR `_` can only be used on the left-hand side of an assignment + //~| ERROR `_` can only be used on the left-hand side of an assignment +} diff --git a/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr new file mode 100644 index 000000000..aa5620306 --- /dev/null +++ b/tests/ui/suggestions/fn-or-tuple-struct-with-underscore-args.stderr @@ -0,0 +1,38 @@ +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:24 + | +LL | let _: usize = foo(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:10:27 + | +LL | let _: usize = foo(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:18 + | +LL | let _: S = S(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:13:21 + | +LL | let _: S = S(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:27 + | +LL | let _: usize = T::baz(_, _); + | ^ `_` not allowed here + +error: in expressions, `_` can only be used on the left-hand side of an assignment + --> $DIR/fn-or-tuple-struct-with-underscore-args.rs:16:30 + | +LL | let _: usize = T::baz(_, _); + | ^ `_` not allowed here + +error: aborting due to 6 previous errors + diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.rs b/tests/ui/suggestions/fn-or-tuple-struct-without-args.rs new file mode 100644 index 000000000..dd5af3e34 --- /dev/null +++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.rs @@ -0,0 +1,47 @@ +fn foo(a: usize, b: usize) -> usize { a } + +fn bar() -> usize { 42 } + +struct S(usize, usize); +enum E { + A(usize), + B { a: usize }, +} +struct V(); + +trait T { + fn baz(x: usize, y: usize) -> usize { x } + fn bat(x: usize) -> usize { 42 } + fn bax(x: usize) -> usize { 42 } + fn bach(x: usize) -> usize; + fn ban(&self) -> usize { 42 } + fn bal(&self) -> usize; +} + +struct X; + +impl T for X { + fn bach(x: usize) -> usize { 42 } + fn bal(&self) -> usize { 42 } +} + +fn main() { + let _: usize = foo; //~ ERROR mismatched types + let _: S = S; //~ ERROR mismatched types + let _: usize = bar; //~ ERROR mismatched types + let _: V = V; //~ ERROR mismatched types + let _: usize = T::baz; //~ ERROR mismatched types + let _: usize = T::bat; //~ ERROR mismatched types + let _: E = E::A; //~ ERROR mismatched types + let _: E = E::B; //~ ERROR expected value, found struct variant `E::B` + let _: usize = X::baz; //~ ERROR mismatched types + let _: usize = X::bat; //~ ERROR mismatched types + let _: usize = X::bax; //~ ERROR mismatched types + let _: usize = X::bach; //~ ERROR mismatched types + let _: usize = X::ban; //~ ERROR mismatched types + let _: usize = X::bal; //~ ERROR mismatched types + let _: usize = X.ban; //~ ERROR attempted to take value of method + let _: usize = X.bal; //~ ERROR attempted to take value of method + let closure = || 42; + let _: usize = closure; //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr new file mode 100644 index 000000000..4cbcd31fa --- /dev/null +++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -0,0 +1,283 @@ +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:29:20 + | +LL | fn foo(a: usize, b: usize) -> usize { a } + | ----------------------------------- function `foo` defined here +... +LL | let _: usize = foo; + | ----- ^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize, usize) -> usize {foo}` +help: use parentheses to call this function + | +LL | let _: usize = foo(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:30:16 + | +LL | struct S(usize, usize); + | -------- `S` defines a struct constructor here, which should be called +... +LL | let _: S = S; + | - ^ expected struct `S`, found struct constructor + | | + | expected due to this + | + = note: expected struct `S` + found struct constructor `fn(usize, usize) -> S {S}` +help: use parentheses to construct this tuple struct + | +LL | let _: S = S(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:31:20 + | +LL | fn bar() -> usize { 42 } + | ----------------- function `bar` defined here +... +LL | let _: usize = bar; + | ----- ^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn() -> usize {bar}` +help: use parentheses to call this function + | +LL | let _: usize = bar(); + | ++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:32:16 + | +LL | struct V(); + | -------- `V` defines a struct constructor here, which should be called +... +LL | let _: V = V; + | - ^ expected struct `V`, found struct constructor + | | + | expected due to this + | + = note: expected struct `V` + found struct constructor `fn() -> V {V}` +help: use parentheses to construct this tuple struct + | +LL | let _: V = V(); + | ++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:33:20 + | +LL | fn baz(x: usize, y: usize) -> usize { x } + | ----------------------------------- associated function `baz` defined here +... +LL | let _: usize = T::baz; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize, usize) -> usize {<_ as T>::baz}` +help: use parentheses to call this associated function + | +LL | let _: usize = T::baz(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:34:20 + | +LL | fn bat(x: usize) -> usize { 42 } + | ------------------------- associated function `bat` defined here +... +LL | let _: usize = T::bat; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {<_ as T>::bat}` +help: use parentheses to call this associated function + | +LL | let _: usize = T::bat(/* usize */); + | +++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:35:16 + | +LL | A(usize), + | - `A` defines an enum variant constructor here, which should be called +... +LL | let _: E = E::A; + | - ^^^^ expected enum `E`, found enum constructor + | | + | expected due to this + | + = note: expected enum `E` + found enum constructor `fn(usize) -> E {E::A}` +help: use parentheses to construct this tuple variant + | +LL | let _: E = E::A(/* usize */); + | +++++++++++++ + +error[E0533]: expected value, found struct variant `E::B` + --> $DIR/fn-or-tuple-struct-without-args.rs:36:16 + | +LL | let _: E = E::B; + | ^^^^ not a value + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:37:20 + | +LL | fn baz(x: usize, y: usize) -> usize { x } + | ----------------------------------- associated function `baz` defined here +... +LL | let _: usize = X::baz; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize, usize) -> usize {::baz}` +help: use parentheses to call this associated function + | +LL | let _: usize = X::baz(/* usize */, /* usize */); + | ++++++++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:38:20 + | +LL | fn bat(x: usize) -> usize { 42 } + | ------------------------- associated function `bat` defined here +... +LL | let _: usize = X::bat; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {::bat}` +help: use parentheses to call this associated function + | +LL | let _: usize = X::bat(/* usize */); + | +++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:39:20 + | +LL | fn bax(x: usize) -> usize { 42 } + | ------------------------- associated function `bax` defined here +... +LL | let _: usize = X::bax; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {::bax}` +help: use parentheses to call this associated function + | +LL | let _: usize = X::bax(/* usize */); + | +++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:40:20 + | +LL | fn bach(x: usize) -> usize; + | --------------------------- associated function `bach` defined here +... +LL | let _: usize = X::bach; + | ----- ^^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `fn(usize) -> usize {::bach}` +help: use parentheses to call this associated function + | +LL | let _: usize = X::bach(/* usize */); + | +++++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:41:20 + | +LL | fn ban(&self) -> usize { 42 } + | ---------------------- associated function `ban` defined here +... +LL | let _: usize = X::ban; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `for<'a> fn(&'a X) -> usize {::ban}` +help: use parentheses to call this associated function + | +LL | let _: usize = X::ban(/* &X */); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:42:20 + | +LL | fn bal(&self) -> usize; + | ----------------------- associated function `bal` defined here +... +LL | let _: usize = X::bal; + | ----- ^^^^^^ expected `usize`, found fn item + | | + | expected due to this + | + = note: expected type `usize` + found fn item `for<'a> fn(&'a X) -> usize {::bal}` +help: use parentheses to call this associated function + | +LL | let _: usize = X::bal(/* &X */); + | ++++++++++ + +error[E0615]: attempted to take value of method `ban` on type `X` + --> $DIR/fn-or-tuple-struct-without-args.rs:43:22 + | +LL | let _: usize = X.ban; + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _: usize = X.ban(); + | ++ + +error[E0615]: attempted to take value of method `bal` on type `X` + --> $DIR/fn-or-tuple-struct-without-args.rs:44:22 + | +LL | let _: usize = X.bal; + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _: usize = X.bal(); + | ++ + +error[E0308]: mismatched types + --> $DIR/fn-or-tuple-struct-without-args.rs:46:20 + | +LL | let closure = || 42; + | -- the found closure +LL | let _: usize = closure; + | ----- ^^^^^^^ expected `usize`, found closure + | | + | expected due to this + | + = note: expected type `usize` + found closure `[closure@$DIR/fn-or-tuple-struct-without-args.rs:45:19: 45:21]` +help: use parentheses to call this closure + | +LL | let _: usize = closure(); + | ++ + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0308, E0533, E0615. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/fn-to-method-deeply-nested.rs b/tests/ui/suggestions/fn-to-method-deeply-nested.rs new file mode 100644 index 000000000..58ee3d640 --- /dev/null +++ b/tests/ui/suggestions/fn-to-method-deeply-nested.rs @@ -0,0 +1,13 @@ +fn main() -> Result<(), ()> { + a(b(c(d(e( + //~^ ERROR cannot find function `a` in this scope + //~| ERROR cannot find function `b` in this scope + //~| ERROR cannot find function `c` in this scope + //~| ERROR cannot find function `d` in this scope + //~| ERROR cannot find function `e` in this scope + z???????????????????????????????????????????????????????????????????????????????????????? + ????????????????????????????????????????????????????????????????????????????????????????? + ?????????????????????????????????????????????????????????????????? + //~^^^ ERROR cannot find value `z` in this scope + ))))) +} diff --git a/tests/ui/suggestions/fn-to-method-deeply-nested.stderr b/tests/ui/suggestions/fn-to-method-deeply-nested.stderr new file mode 100644 index 000000000..ce813ea7a --- /dev/null +++ b/tests/ui/suggestions/fn-to-method-deeply-nested.stderr @@ -0,0 +1,39 @@ +error[E0425]: cannot find value `z` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:8:9 + | +LL | z???????????????????????????????????????????????????????????????????????????????????????? + | ^ not found in this scope + +error[E0425]: cannot find function `e` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:13 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `d` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:11 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `c` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:9 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `b` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:7 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error[E0425]: cannot find function `a` in this scope + --> $DIR/fn-to-method-deeply-nested.rs:2:5 + | +LL | a(b(c(d(e( + | ^ not found in this scope + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/fn-to-method.rs b/tests/ui/suggestions/fn-to-method.rs new file mode 100644 index 000000000..9a35c3efc --- /dev/null +++ b/tests/ui/suggestions/fn-to-method.rs @@ -0,0 +1,19 @@ +struct Foo; + +impl Foo { + fn bar(self) {} +} + +fn main() { + let x = cmp(&1, &2); + //~^ ERROR cannot find function `cmp` in this scope + //~| HELP use the `.` operator to call the method `Ord::cmp` on `&{integer}` + + let y = len([1, 2, 3]); + //~^ ERROR cannot find function `len` in this scope + //~| HELP use the `.` operator to call the method `len` on `&[{integer}]` + + let z = bar(Foo); + //~^ ERROR cannot find function `bar` in this scope + //~| HELP use the `.` operator to call the method `bar` on `Foo` +} diff --git a/tests/ui/suggestions/fn-to-method.stderr b/tests/ui/suggestions/fn-to-method.stderr new file mode 100644 index 000000000..36c17e60d --- /dev/null +++ b/tests/ui/suggestions/fn-to-method.stderr @@ -0,0 +1,38 @@ +error[E0425]: cannot find function `cmp` in this scope + --> $DIR/fn-to-method.rs:8:13 + | +LL | let x = cmp(&1, &2); + | ^^^ not found in this scope + | +help: use the `.` operator to call the method `Ord::cmp` on `&{integer}` + | +LL | let x = (&1).cmp(&2); + | ~ ~~~~~~~~~ + +error[E0425]: cannot find function `len` in this scope + --> $DIR/fn-to-method.rs:12:13 + | +LL | let y = len([1, 2, 3]); + | ^^^ not found in this scope + | +help: use the `.` operator to call the method `len` on `&[{integer}]` + | +LL - let y = len([1, 2, 3]); +LL + let y = [1, 2, 3].len(); + | + +error[E0425]: cannot find function `bar` in this scope + --> $DIR/fn-to-method.rs:16:13 + | +LL | let z = bar(Foo); + | ^^^ not found in this scope + | +help: use the `.` operator to call the method `bar` on `Foo` + | +LL - let z = bar(Foo); +LL + let z = Foo.bar(); + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/fn-trait-notation.fixed b/tests/ui/suggestions/fn-trait-notation.fixed new file mode 100644 index 000000000..cf940f4e9 --- /dev/null +++ b/tests/ui/suggestions/fn-trait-notation.fixed @@ -0,0 +1,19 @@ +// run-rustfix +fn e0658(f: F, g: G, h: H) -> i32 +where + F: Fn(i32) -> i32, //~ ERROR E0658 + G: Fn(i32, i32) -> (i32, i32), //~ ERROR E0658 + H: Fn(i32) -> i32, //~ ERROR E0658 +{ + f(3); + g(3, 4); + h(3) +} + +fn main() { + e0658( + |a| a, + |a, b| (b, a), + |a| a, + ); +} diff --git a/tests/ui/suggestions/fn-trait-notation.rs b/tests/ui/suggestions/fn-trait-notation.rs new file mode 100644 index 000000000..f0bb03315 --- /dev/null +++ b/tests/ui/suggestions/fn-trait-notation.rs @@ -0,0 +1,19 @@ +// run-rustfix +fn e0658(f: F, g: G, h: H) -> i32 +where + F: Fn, //~ ERROR E0658 + G: Fn<(i32, i32, ), Output = (i32, i32)>, //~ ERROR E0658 + H: Fn<(i32,), Output = i32>, //~ ERROR E0658 +{ + f(3); + g(3, 4); + h(3) +} + +fn main() { + e0658( + |a| a, + |a, b| (b, a), + |a| a, + ); +} diff --git a/tests/ui/suggestions/fn-trait-notation.stderr b/tests/ui/suggestions/fn-trait-notation.stderr new file mode 100644 index 000000000..3e3b54174 --- /dev/null +++ b/tests/ui/suggestions/fn-trait-notation.stderr @@ -0,0 +1,30 @@ +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:4:8 + | +LL | F: Fn, + | ^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:5:8 + | +LL | G: Fn<(i32, i32, ), Output = (i32, i32)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32, i32) -> (i32, i32)` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:6:8 + | +LL | H: Fn<(i32,), Output = i32>, + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/suggestions/for-i-in-vec.fixed b/tests/ui/suggestions/for-i-in-vec.fixed new file mode 100644 index 000000000..4f2007bef --- /dev/null +++ b/tests/ui/suggestions/for-i-in-vec.fixed @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(dead_code)] + +struct Foo { + v: Vec, + h: std::collections::HashMap, +} + +impl Foo { + fn bar(&self) { + for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference + } + for _ in &self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference + } + } +} + +const LOADERS: &Vec<&'static u8> = &Vec::new(); + +pub fn break_code() -> Option<&'static u8> { + for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference + return Some(loader); + } + None +} + +fn main() {} diff --git a/tests/ui/suggestions/for-i-in-vec.rs b/tests/ui/suggestions/for-i-in-vec.rs new file mode 100644 index 000000000..55fc7ad4e --- /dev/null +++ b/tests/ui/suggestions/for-i-in-vec.rs @@ -0,0 +1,27 @@ +// run-rustfix +#![allow(dead_code)] + +struct Foo { + v: Vec, + h: std::collections::HashMap, +} + +impl Foo { + fn bar(&self) { + for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference + } + for _ in self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference + } + } +} + +const LOADERS: &Vec<&'static u8> = &Vec::new(); + +pub fn break_code() -> Option<&'static u8> { + for loader in *LOADERS { //~ ERROR cannot move out of a shared reference + return Some(loader); + } + None +} + +fn main() {} diff --git a/tests/ui/suggestions/for-i-in-vec.stderr b/tests/ui/suggestions/for-i-in-vec.stderr new file mode 100644 index 000000000..c5b81e6b8 --- /dev/null +++ b/tests/ui/suggestions/for-i-in-vec.stderr @@ -0,0 +1,49 @@ +error[E0507]: cannot move out of `self.v` which is behind a shared reference + --> $DIR/for-i-in-vec.rs:11:18 + | +LL | for _ in self.v { + | ^^^^^^ + | | + | `self.v` moved due to this implicit call to `.into_iter()` + | move occurs because `self.v` has type `Vec`, which does not implement the `Copy` trait + | +note: `into_iter` takes ownership of the receiver `self`, which moves `self.v` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider iterating over a slice of the `Vec`'s content to avoid moving into the `for` loop + | +LL | for _ in &self.v { + | + + +error[E0507]: cannot move out of `self.h` which is behind a shared reference + --> $DIR/for-i-in-vec.rs:13:18 + | +LL | for _ in self.h { + | ^^^^^^ + | | + | `self.h` moved due to this implicit call to `.into_iter()` + | move occurs because `self.h` has type `HashMap`, which does not implement the `Copy` trait + | +help: consider iterating over a slice of the `HashMap`'s content to avoid moving into the `for` loop + | +LL | for _ in &self.h { + | + + +error[E0507]: cannot move out of a shared reference + --> $DIR/for-i-in-vec.rs:21:19 + | +LL | for loader in *LOADERS { + | ^^^^^^^^ + | | + | value moved due to this implicit call to `.into_iter()` + | move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait + | +note: `into_iter` takes ownership of the receiver `self`, which moves value + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop + | +LL | for loader in &*LOADERS { + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/format-borrow.rs b/tests/ui/suggestions/format-borrow.rs new file mode 100644 index 000000000..599a79fc0 --- /dev/null +++ b/tests/ui/suggestions/format-borrow.rs @@ -0,0 +1,10 @@ +fn main() { + let a: String = &String::from("a"); + //~^ ERROR mismatched types + let b: String = &format!("b"); + //~^ ERROR mismatched types + let c: String = &mut format!("c"); + //~^ ERROR mismatched types + let d: String = &mut (format!("d")); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/format-borrow.stderr b/tests/ui/suggestions/format-borrow.stderr new file mode 100644 index 000000000..8ed2b9c9a --- /dev/null +++ b/tests/ui/suggestions/format-borrow.stderr @@ -0,0 +1,75 @@ +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:2:21 + | +LL | let a: String = &String::from("a"); + | ------ ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let a: String = &String::from("a"); +LL + let a: String = String::from("a"); + | +help: alternatively, consider changing the type annotation + | +LL | let a: &String = &String::from("a"); + | + + +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:4:21 + | +LL | let b: String = &format!("b"); + | ------ ^^^^^^^^^^^^^ expected struct `String`, found `&String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let b: String = &format!("b"); +LL + let b: String = format!("b"); + | +help: alternatively, consider changing the type annotation + | +LL | let b: &String = &format!("b"); + | + + +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:6:21 + | +LL | let c: String = &mut format!("c"); + | ------ ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let c: String = &mut format!("c"); +LL + let c: String = format!("c"); + | +help: alternatively, consider changing the type annotation + | +LL | let c: &mut String = &mut format!("c"); + | ++++ + +error[E0308]: mismatched types + --> $DIR/format-borrow.rs:8:21 + | +LL | let d: String = &mut (format!("d")); + | ------ ^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let d: String = &mut (format!("d")); +LL + let d: String = format!("d")); + | +help: alternatively, consider changing the type annotation + | +LL | let d: &mut String = &mut (format!("d")); + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/if-let-typo.rs b/tests/ui/suggestions/if-let-typo.rs new file mode 100644 index 000000000..375bd3f03 --- /dev/null +++ b/tests/ui/suggestions/if-let-typo.rs @@ -0,0 +1,11 @@ +fn main() { + let foo = Some(0); + let bar = None; + if Some(x) = foo {} //~ ERROR cannot find value `x` in this scope + //~^ ERROR mismatched types + if Some(foo) = bar {} //~ ERROR mismatched types + if 3 = foo {} //~ ERROR mismatched types + if Some(3) = foo {} //~ ERROR mismatched types + //~^ ERROR invalid left-hand side of assignment + if x = 5 {} //~ ERROR cannot find value `x` in this scope +} diff --git a/tests/ui/suggestions/if-let-typo.stderr b/tests/ui/suggestions/if-let-typo.stderr new file mode 100644 index 000000000..02148b7f7 --- /dev/null +++ b/tests/ui/suggestions/if-let-typo.stderr @@ -0,0 +1,73 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/if-let-typo.rs:4:13 + | +LL | if Some(x) = foo {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let Some(x) = foo {} + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/if-let-typo.rs:10:8 + | +LL | if x = 5 {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | if let x = 5 {} + | +++ + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:4:8 + | +LL | if Some(x) = foo {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(x) = foo {} + | +++ + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:6:8 + | +LL | if Some(foo) = bar {} + | ^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(foo) = bar {} + | +++ + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:7:8 + | +LL | if 3 = foo {} + | ^^^^^^^ expected `bool`, found `()` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/if-let-typo.rs:8:16 + | +LL | if Some(3) = foo {} + | - ^ + | | + | cannot assign to this expression + +error[E0308]: mismatched types + --> $DIR/if-let-typo.rs:8:8 + | +LL | if Some(3) = foo {} + | ^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: consider adding `let` + | +LL | if let Some(3) = foo {} + | +++ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0070, E0308, E0425. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/suggestions/if-then-neeing-semi.rs b/tests/ui/suggestions/if-then-neeing-semi.rs new file mode 100644 index 000000000..b487f013d --- /dev/null +++ b/tests/ui/suggestions/if-then-neeing-semi.rs @@ -0,0 +1,70 @@ +// edition:2018 + +fn dummy() -> i32 { + 42 +} + +fn extra_semicolon() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found `i32` + }; +} + +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function + +async fn async_extra_semicolon_same() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_extra_semicolon_different() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_different_futures() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy() //~ NOTE expected because of this + //~| HELP consider `await`ing on both `Future`s + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected opaque type, found a different opaque type + //~| NOTE expected opaque type `impl Future` + //~| NOTE distinct uses of `impl Trait` result in different opaque types + }; +} + +fn main() {} diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr new file mode 100644 index 000000000..d7c5818ab --- /dev/null +++ b/tests/ui/suggestions/if-then-neeing-semi.stderr @@ -0,0 +1,130 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:37:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy() + | | ^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future` +help: consider `await`ing on the `Future` + | +LL | async_dummy().await + | ++++++ +help: consider removing this semicolon + | +LL - async_dummy(); +LL + async_dummy() + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:50:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future` +help: consider `await`ing on the `Future` + | +LL | async_dummy2().await + | ++++++ +help: consider removing this semicolon and boxing the expressions + | +LL ~ Box::new(async_dummy()) +LL | +LL | } else { +LL ~ Box::new(async_dummy2()) + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:63:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy() + | | ------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>) + found opaque type `impl Future` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ async_dummy().await +LL | +LL | } else { +LL ~ async_dummy2().await + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:13:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | dummy(); + | | -------- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | +LL | | } else { +LL | | dummy() + | | ^^^^^^^ expected `()`, found `i32` +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/ignore-nested-field-binding.fixed b/tests/ui/suggestions/ignore-nested-field-binding.fixed new file mode 100644 index 000000000..1dc44838e --- /dev/null +++ b/tests/ui/suggestions/ignore-nested-field-binding.fixed @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i: _ } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i: _ } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/tests/ui/suggestions/ignore-nested-field-binding.rs b/tests/ui/suggestions/ignore-nested-field-binding.rs new file mode 100644 index 000000000..6dc0263ec --- /dev/null +++ b/tests/ui/suggestions/ignore-nested-field-binding.rs @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/tests/ui/suggestions/ignore-nested-field-binding.stderr b/tests/ui/suggestions/ignore-nested-field-binding.stderr new file mode 100644 index 000000000..b2936a22a --- /dev/null +++ b/tests/ui/suggestions/ignore-nested-field-binding.stderr @@ -0,0 +1,20 @@ +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:11:27 + | +LL | fn foo(Outer { o: Inner { i } }: Outer) {} + | ^ help: try ignoring the field: `i: _` + | +note: the lint level is defined here + --> $DIR/ignore-nested-field-binding.rs:6:11 + | +LL | #![forbid(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:17:28 + | +LL | let Outer { o: Inner { i } } = s; + | ^ help: try ignoring the field: `i: _` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs new file mode 100644 index 000000000..319789c4e --- /dev/null +++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs @@ -0,0 +1,18 @@ +// Regression test for #70813 (this used to trigger a debug assertion) + +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo(_: X) +where + for<'b> &'b X: Trait, +{ +} + +fn main() { + let s = S; + foo::(s); //~ ERROR the trait bound `for<'b> &'b S: Trait` is not satisfied +} diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr new file mode 100644 index 000000000..864ab0535 --- /dev/null +++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:14 + | +LL | foo::(s); + | -------- ^ the trait `for<'b> Trait` is not implemented for `&'b S` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for `&'a mut S` + = note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S` +note: required by a bound in `foo` + --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20 + | +LL | fn foo(_: X) + | --- required by a bound in this +LL | where +LL | for<'b> &'b X: Trait, + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal.rs b/tests/ui/suggestions/imm-ref-trait-object-literal.rs new file mode 100644 index 000000000..22ca6dde4 --- /dev/null +++ b/tests/ui/suggestions/imm-ref-trait-object-literal.rs @@ -0,0 +1,14 @@ +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo(_: X) {} + + +fn main() { + let s = S; + foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied + foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied +} diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr new file mode 100644 index 000000000..e01102e38 --- /dev/null +++ b/tests/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -0,0 +1,40 @@ +error[E0277]: the trait bound `&S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:12:7 + | +LL | foo(&s); + | --- ^^ the trait `Trait` is not implemented for `&S` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for `&'a mut S` +note: required by a bound in `foo` + --> $DIR/imm-ref-trait-object-literal.rs:7:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider changing this borrow's mutability + | +LL | foo(&mut s); + | ~~~~ + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:13:7 + | +LL | foo(s); + | --- ^ the trait `Trait` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/imm-ref-trait-object-literal.rs:7:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut s); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/imm-ref-trait-object.rs b/tests/ui/suggestions/imm-ref-trait-object.rs new file mode 100644 index 000000000..c1c969b90 --- /dev/null +++ b/tests/ui/suggestions/imm-ref-trait-object.rs @@ -0,0 +1,8 @@ +fn test(t: &dyn Iterator) -> u64 { + t.min().unwrap() //~ ERROR the `min` method cannot be invoked on `&dyn Iterator` +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/tests/ui/suggestions/imm-ref-trait-object.stderr b/tests/ui/suggestions/imm-ref-trait-object.stderr new file mode 100644 index 000000000..f7f7902c1 --- /dev/null +++ b/tests/ui/suggestions/imm-ref-trait-object.stderr @@ -0,0 +1,13 @@ +error: the `min` method cannot be invoked on `&dyn Iterator` + --> $DIR/imm-ref-trait-object.rs:2:8 + | +LL | t.min().unwrap() + | ^^^ + | +help: you need `&mut dyn Iterator` instead of `&dyn Iterator` + | +LL | fn test(t: &mut dyn Iterator) -> u64 { + | +++ + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs new file mode 100644 index 000000000..711cbbd38 --- /dev/null +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -0,0 +1,113 @@ +// FIXME: the following cases need to suggest more things to make users reach a working end state. + +mod bav { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR cannot return reference to function parameter + } +} + +mod bap { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box>) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR E0515 + } +} + +// This case in particular requires the user to write all of the bounds we have in `mod bax`. +mod bay { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl MyTrait for Box> { + fn use_self(&self) -> &() { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box + 'a>) -> &'a () { + val.use_self() + } +} + +mod bax { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait<'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + trait Bar {} + + impl<'a> MyTrait<'a> for Box + 'a> { + fn use_self(&'a self) -> &'a () { panic!() } + } + impl Bar for i32 {} + + fn use_it<'a>(val: Box + 'a>) -> &'a () { + val.use_self() + } +} + +mod baw { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait { + type Assoc: Bar; + } + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Bar {} + + impl<'a> MyTrait for Box>> { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: Box>>) -> impl OtherTrait<'a> + 'a{ + val.use_self() //~ ERROR E0515 + } +} + +fn main() {} diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr new file mode 100644 index 000000000..2dc300ac7 --- /dev/null +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -0,0 +1,21 @@ +error[E0515]: cannot return reference to function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9 + | +LL | val.use_self() + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9 + | +LL | val.use_self() + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function + +error[E0515]: cannot return reference to function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 + | +LL | val.use_self() + | ^^^^^^^^^^^^^^ returns a reference to data owned by the current function + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs new file mode 100644 index 000000000..ae3cd315c --- /dev/null +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -0,0 +1,114 @@ +// FIXME(#96332): We should be able to suggest a fix and automatically fix. + +#![allow(dead_code)] + +mod foo { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self::() //~ ERROR borrowed data escapes + } +} + +mod bar { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + val.use_self() + } +} + +mod baz { + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &(); + } + trait Irrelevant {} + + impl MyTrait for Box { + fn use_self(&self) -> &() { panic!() } + } + impl Irrelevant for Box {} + + fn use_it<'a>(val: &'a Box) -> &'a () { + val.use_self() + } +} + +mod bat { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + + impl dyn ObjectTrait { + fn use_self(&self) -> &() { panic!() } + } + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() + //~^ ERROR borrowed data escapes + } +} + +mod ban { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + val.use_self() //~ ERROR borrowed data escapes + } +} + +mod bal { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + impl Irrelevant for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + MyTrait::use_self(val) //~ ERROR borrowed data escapes + } +} + +fn main() {} diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr new file mode 100644 index 000000000..679ebd61e --- /dev/null +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -0,0 +1,105 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:21:9 + | +LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self::() + | ^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:32 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:70:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:65:14 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:90:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:110:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | MyTrait::use_self(val) + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26 + | +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s 'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs new file mode 100644 index 000000000..a1a51c481 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -0,0 +1,68 @@ +// edition:2021 +// gate-test-anonymous_lifetime_in_impl_trait +// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`. + +mod elided { + fn f(_: impl Iterator) {} + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + + fn g(mut x: impl Iterator) -> Option<&()> { x.next() } + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~| ERROR missing lifetime specifier + + // Anonymous lifetimes in async fn are already allowed. + // This is understood as `fn foo<'_1>(_: impl Iterator) {}`. + async fn h(_: impl Iterator) {} + + // Anonymous lifetimes in async fn are already allowed. + // But that lifetime does not participate in resolution. + async fn i(mut x: impl Iterator) -> Option<&()> { x.next() } + //~^ ERROR missing lifetime specifier +} + +mod underscore { + fn f(_: impl Iterator) {} + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + + fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~| ERROR missing lifetime specifier + + // Anonymous lifetimes in async fn are already allowed. + // This is understood as `fn foo<'_1>(_: impl Iterator) {}`. + async fn h(_: impl Iterator) {} + + // Anonymous lifetimes in async fn are already allowed. + // But that lifetime does not participate in resolution. + async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + //~^ ERROR missing lifetime specifier +} + +mod alone_in_path { + trait Foo<'a> { fn next(&mut self) -> Option<&'a ()>; } + + fn f(_: impl Foo) {} + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + + fn g(mut x: impl Foo) -> Option<&()> { x.next() } + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~| ERROR missing lifetime specifier +} + +mod in_path { + trait Foo<'a, T> { fn next(&mut self) -> Option<&'a T>; } + + fn f(_: impl Foo<()>) {} + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + + fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } + //~^ ERROR anonymous lifetimes in `impl Trait` are unstable + //~| ERROR missing lifetime specifier +} + +// This must not err, as the `&` actually resolves to `'a`. +fn resolved_anonymous<'a, T>(f: impl Fn(&'a str) -> &T) { + f("f") +} + +fn main() {} diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr new file mode 100644 index 000000000..50806a672 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -0,0 +1,172 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:9:54 + | +LL | fn g(mut x: impl Iterator) -> Option<&()> { x.next() } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(mut x: impl Iterator) -> Option<&'static ()> { x.next() } + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:19:60 + | +LL | async fn i(mut x: impl Iterator) -> Option<&()> { x.next() } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | async fn i(mut x: impl Iterator) -> Option<&'static ()> { x.next() } + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:27:58 + | +LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(mut x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:37:64 + | +LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | async fn i(mut x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:47:37 + | +LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(mut x: impl Foo) -> Option<&'static ()> { x.next() } + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime-gated.rs:58:41 + | +LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(mut x: impl Foo<()>) -> Option<&'static ()> { x.next() } + | +++++++ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 + | +LL | fn f(_: impl Iterator) {} + | ^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(_: impl Iterator) {} + | ++++ ++ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:9:39 + | +LL | fn g(mut x: impl Iterator) -> Option<&()> { x.next() } + | ^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Iterator) -> Option<&()> { x.next() } + | ++++ ++ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:24:35 + | +LL | fn f(_: impl Iterator) {} + | ^^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(_: impl Iterator) {} + | ++++ ~~ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:27:39 + | +LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ++++ ~~ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:44:18 + | +LL | fn f(_: impl Foo) {} + | ^^^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(_: impl Foo<'a>) {} + | ++++ ++++ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:47:22 + | +LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() } + | ^^^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() } + | ++++ ++++ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:55:22 + | +LL | fn f(_: impl Foo<()>) {} + | ^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(_: impl Foo<'a, ()>) {} + | ++++ +++ + +error[E0658]: anonymous lifetimes in `impl Trait` are unstable + --> $DIR/impl-trait-missing-lifetime-gated.rs:58:26 + | +LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } + | ^ expected named lifetime parameter + | + = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() } + | ++++ +++ + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0106, E0658. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.rs b/tests/ui/suggestions/impl-trait-missing-lifetime.rs new file mode 100644 index 000000000..6f7c912d7 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.rs @@ -0,0 +1,20 @@ +// edition:2021 + +#![feature(anonymous_lifetime_in_impl_trait)] + +// This is understood as `fn foo<'_1>(_: impl Iterator) {}`. +fn f(_: impl Iterator) {} + +// But that lifetime does not participate in resolution. +fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier + +// This is understood as `fn foo<'_1>(_: impl Iterator) {}`. +async fn h(_: impl Iterator) {} + +// But that lifetime does not participate in resolution. +async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } +//~^ ERROR missing lifetime specifier +//~| ERROR lifetime may not live long enough + +fn main() {} diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr new file mode 100644 index 000000000..b476d6101 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -0,0 +1,35 @@ +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime.rs:9:54 + | +LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn g(mut x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error[E0106]: missing lifetime specifier + --> $DIR/impl-trait-missing-lifetime.rs:16:60 + | +LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | async fn i(mut x: impl Iterator) -> Option<&'static ()> { x.next() } + | ~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime.rs:16:69 + | +LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | -------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | return type `impl Future>` contains a lifetime `'1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs new file mode 100644 index 000000000..cd3741356 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.rs @@ -0,0 +1,21 @@ +trait Bar {} + +impl Bar for i32 {} + +struct Qux; + +impl Bar for Qux {} + +fn foo() -> impl Bar { + //~^ ERROR the trait bound `(): Bar` is not satisfied + 5; + //~^ HELP remove this semicolon +} + +fn bar() -> impl Bar { + //~^ ERROR the trait bound `(): Bar` is not satisfied + //~| HELP the following other types implement trait `Bar`: + ""; +} + +fn main() {} diff --git a/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr new file mode 100644 index 000000000..e74c2c421 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-return-trailing-semicolon.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/impl-trait-return-trailing-semicolon.rs:9:13 + | +LL | fn foo() -> impl Bar { + | ^^^^^^^^ the trait `Bar` is not implemented for `()` +LL | +LL | 5; + | -- help: remove this semicolon + | | + | this expression has type `{integer}`, which implements `Bar` + +error[E0277]: the trait bound `(): Bar` is not satisfied + --> $DIR/impl-trait-return-trailing-semicolon.rs:15:13 + | +LL | fn bar() -> impl Bar { + | ^^^^^^^^ the trait `Bar` is not implemented for `()` + | + = help: the following other types implement trait `Bar`: + Qux + i32 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/impl-trait-with-missing-bounds.rs b/tests/ui/suggestions/impl-trait-with-missing-bounds.rs new file mode 100644 index 000000000..949b23600 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-with-missing-bounds.rs @@ -0,0 +1,52 @@ +// The double space in `impl Iterator` is load bearing! We want to make sure we don't regress by +// accident if the internal string representation changes. +#[rustfmt::skip] +fn foo(constraints: impl Iterator) { + for constraint in constraints { + qux(constraint); +//~^ ERROR `::Item` doesn't implement `Debug` + } +} + +fn bar(t: T, constraints: impl Iterator) where T: std::fmt::Debug { + for constraint in constraints { + qux(t); + qux(constraint); +//~^ ERROR `::Item` doesn't implement `Debug` + } +} + +fn baz(t: impl std::fmt::Debug, constraints: impl Iterator) { + for constraint in constraints { + qux(t); + qux(constraint); +//~^ ERROR `::Item` doesn't implement `Debug` + } +} + +fn bat(t: T, constraints: impl Iterator, _: I) { + for constraint in constraints { + qux(t); + qux(constraint); +//~^ ERROR `::Item` doesn't implement `Debug` + } +} + +fn bak(constraints: impl Iterator + std::fmt::Debug) { + for constraint in constraints { + qux(constraint); +//~^ ERROR `::Item` doesn't implement + } +} + +#[rustfmt::skip] +fn baw<>(constraints: impl Iterator) { + for constraint in constraints { + qux(constraint); +//~^ ERROR `::Item` doesn't implement `Debug` + } +} + +fn qux(_: impl std::fmt::Debug) {} + +fn main() {} diff --git a/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr b/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr new file mode 100644 index 000000000..a763eb6f2 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-with-missing-bounds.stderr @@ -0,0 +1,117 @@ +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:6:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn foo(constraints: I) where ::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:14:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn bar(t: T, constraints: I) where T: std::fmt::Debug, ::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++ + +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:22:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn baz(t: impl std::fmt::Debug, constraints: I) where ::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:30:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn bat(t: T, constraints: U, _: I) where ::Item: Debug { + | +++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:37:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn bak(constraints: I) where ::Item: Debug { + | +++++++++++++++++++++++++++++++ ~ ++++++++++++++++++++++++++++++++++ + +error[E0277]: `::Item` doesn't implement `Debug` + --> $DIR/impl-trait-with-missing-bounds.rs:45:13 + | +LL | qux(constraint); + | --- ^^^^^^^^^^ `::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by a bound introduced by this call + | + = help: the trait `Debug` is not implemented for `::Item` +note: required by a bound in `qux` + --> $DIR/impl-trait-with-missing-bounds.rs:50:16 + | +LL | fn qux(_: impl std::fmt::Debug) {} + | ^^^^^^^^^^^^^^^ required by this bound in `qux` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | fn baw(constraints: I) where ::Item: Debug { + | ~~~~~~~~~~~~~ ~ ++++++++++++++++++++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed new file mode 100644 index 000000000..5109511f9 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo + Bar) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs new file mode 100644 index 000000000..cd05b7738 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr new file mode 100644 index 000000000..20f8e65f7 --- /dev/null +++ b/tests/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope + --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 + | +LL | fn test(foo: impl Foo) { + | -------- method `hello` not found for this type parameter +LL | foo.hello(); + | ^^^^^ method not found in `impl Foo` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it: + | +LL | fn test(foo: impl Foo + Bar) { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/import-trait-for-method-call.rs b/tests/ui/suggestions/import-trait-for-method-call.rs new file mode 100644 index 000000000..4dbadbdf9 --- /dev/null +++ b/tests/ui/suggestions/import-trait-for-method-call.rs @@ -0,0 +1,16 @@ +use std::hash::BuildHasher; + +fn next_u64() -> u64 { + let bh = std::collections::hash_map::RandomState::new(); + let h = bh.build_hasher(); + h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher` +} + +trait Bar {} +impl Bar for String {} + +fn main() { + let s = String::from("hey"); + let x: &dyn Bar = &s; + x.as_ref(); //~ ERROR the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds +} diff --git a/tests/ui/suggestions/import-trait-for-method-call.stderr b/tests/ui/suggestions/import-trait-for-method-call.stderr new file mode 100644 index 000000000..f159b51a2 --- /dev/null +++ b/tests/ui/suggestions/import-trait-for-method-call.stderr @@ -0,0 +1,34 @@ +error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope + --> $DIR/import-trait-for-method-call.rs:6:7 + | +LL | h.finish() + | ^^^^^^ method not found in `DefaultHasher` + --> $SRC_DIR/core/src/hash/mod.rs:LL:COL + | + = note: the method is available for `DefaultHasher` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::hash::Hasher; + | + +error[E0599]: the method `as_ref` exists for reference `&dyn Bar`, but its trait bounds were not satisfied + --> $DIR/import-trait-for-method-call.rs:15:7 + | +LL | trait Bar {} + | --------- doesn't satisfy `dyn Bar: AsRef<_>` +... +LL | x.as_ref(); + | ^^^^^^ method cannot be called on `&dyn Bar` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `dyn Bar: AsRef<_>` + which is required by `&dyn Bar: AsRef<_>` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `as_ref`, perhaps you need to implement it: + candidate #1: `AsRef` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed new file mode 100644 index 000000000..7af7391ca --- /dev/null +++ b/tests/ui/suggestions/inner_type.fixed @@ -0,0 +1,40 @@ +// compile-flags: --edition=2021 +// run-rustfix + +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +fn main() { + let other_item = std::cell::RefCell::new(Struct { p: 42_u32 }); + + other_item.borrow().method(); + //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists + + other_item.borrow_mut().some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] + //~| HELP .borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist + + let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); + + another_item.lock().unwrap().method(); + //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] + //~| HELP use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired + + let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); + + another_item.read().unwrap().method(); + //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired + + another_item.write().unwrap().some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired +} diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs new file mode 100644 index 000000000..4aca50716 --- /dev/null +++ b/tests/ui/suggestions/inner_type.rs @@ -0,0 +1,40 @@ +// compile-flags: --edition=2021 +// run-rustfix + +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +fn main() { + let other_item = std::cell::RefCell::new(Struct { p: 42_u32 }); + + other_item.method(); + //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599] + //~| HELP use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists + + other_item.some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599] + //~| HELP .borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist + + let another_item = std::sync::Mutex::new(Struct { p: 42_u32 }); + + another_item.method(); + //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599] + //~| HELP use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired + + let another_item = std::sync::RwLock::new(Struct { p: 42_u32 }); + + another_item.method(); + //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired + + another_item.some_mutable_method(); + //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599] + //~| HELP use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired +} diff --git a/tests/ui/suggestions/inner_type.stderr b/tests/ui/suggestions/inner_type.stderr new file mode 100644 index 000000000..5ac3d04f1 --- /dev/null +++ b/tests/ui/suggestions/inner_type.stderr @@ -0,0 +1,83 @@ +error[E0599]: no method named `method` found for struct `RefCell` in the current scope + --> $DIR/inner_type.rs:17:16 + | +LL | other_item.method(); + | ^^^^^^ method not found in `RefCell>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.borrow()` to borrow the `Struct`, panicking if a mutable borrow exists + | +LL | other_item.borrow().method(); + | +++++++++ + +error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope + --> $DIR/inner_type.rs:21:16 + | +LL | other_item.some_mutable_method(); + | ^^^^^^^^^^^^^^^^^^^ method not found in `RefCell>` + | +note: the method `some_mutable_method` exists on the type `Struct` + --> $DIR/inner_type.rs:11:5 + | +LL | pub fn some_mutable_method(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `.borrow_mut()` to mutably borrow the `Struct`, panicking if any borrows exist + | +LL | other_item.borrow_mut().some_mutable_method(); + | +++++++++++++ + +error[E0599]: no method named `method` found for struct `Mutex` in the current scope + --> $DIR/inner_type.rs:27:18 + | +LL | another_item.method(); + | ^^^^^^ method not found in `Mutex>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.lock().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.lock().unwrap().method(); + | ++++++++++++++++ + +error[E0599]: no method named `method` found for struct `RwLock` in the current scope + --> $DIR/inner_type.rs:33:18 + | +LL | another_item.method(); + | ^^^^^^ method not found in `RwLock>` + | +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type.rs:9:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ +help: use `.read().unwrap()` to borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.read().unwrap().method(); + | ++++++++++++++++ + +error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope + --> $DIR/inner_type.rs:37:18 + | +LL | another_item.some_mutable_method(); + | ^^^^^^^^^^^^^^^^^^^ method not found in `RwLock>` + | +note: the method `some_mutable_method` exists on the type `Struct` + --> $DIR/inner_type.rs:11:5 + | +LL | pub fn some_mutable_method(&mut self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `.write().unwrap()` to mutably borrow the `Struct`, blocking the current thread until it can be acquired + | +LL | another_item.write().unwrap().some_mutable_method(); + | +++++++++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/inner_type2.rs b/tests/ui/suggestions/inner_type2.rs new file mode 100644 index 000000000..fac68c053 --- /dev/null +++ b/tests/ui/suggestions/inner_type2.rs @@ -0,0 +1,26 @@ +pub struct Struct { + pub p: T, +} + +impl Struct { + pub fn method(&self) {} + + pub fn some_mutable_method(&mut self) {} +} + +thread_local! { + static STRUCT: Struct = Struct { + p: 42_u32 + }; +} + +fn main() { + STRUCT.method(); + //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599] + //~| HELP use `with` or `try_with` to access thread local storage + + let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 }); + item.method(); + //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599] + //~| HELP if this `MaybeUninit>` has been initialized, use one of the `assume_init` methods to access the inner value +} diff --git a/tests/ui/suggestions/inner_type2.stderr b/tests/ui/suggestions/inner_type2.stderr new file mode 100644 index 000000000..984366123 --- /dev/null +++ b/tests/ui/suggestions/inner_type2.stderr @@ -0,0 +1,29 @@ +error[E0599]: no method named `method` found for struct `LocalKey` in the current scope + --> $DIR/inner_type2.rs:18:12 + | +LL | STRUCT.method(); + | ^^^^^^ method not found in `LocalKey>` + | + = help: use `with` or `try_with` to access thread local storage +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type2.rs:6:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope + --> $DIR/inner_type2.rs:23:10 + | +LL | item.method(); + | ^^^^^^ method not found in `MaybeUninit>` + | + = help: if this `MaybeUninit>` has been initialized, use one of the `assume_init` methods to access the inner value +note: the method `method` exists on the type `Struct` + --> $DIR/inner_type2.rs:6:5 + | +LL | pub fn method(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/into-convert.rs b/tests/ui/suggestions/into-convert.rs new file mode 100644 index 000000000..1c9a9e0aa --- /dev/null +++ b/tests/ui/suggestions/into-convert.rs @@ -0,0 +1,26 @@ +use std::path::{Path, PathBuf}; +use std::sync::atomic::AtomicU32; +use std::sync::Arc; + +fn main() { + let x: A = B; + //~^ ERROR mismatched types + //~| HELP call `Into::into` on this expression to convert `B` into `A` + + let y: Arc = PathBuf::new(); + //~^ ERROR mismatched types + //~| HELP call `Into::into` on this expression to convert `PathBuf` into `Arc` + + let z: AtomicU32 = 1; + //~^ ERROR mismatched types + //~| HELP call `Into::into` on this expression to convert `{integer}` into `AtomicU32` +} + +struct A; +struct B; + +impl From for A { + fn from(_: B) -> Self { + A + } +} diff --git a/tests/ui/suggestions/into-convert.stderr b/tests/ui/suggestions/into-convert.stderr new file mode 100644 index 000000000..d43104a21 --- /dev/null +++ b/tests/ui/suggestions/into-convert.stderr @@ -0,0 +1,44 @@ +error[E0308]: mismatched types + --> $DIR/into-convert.rs:6:16 + | +LL | let x: A = B; + | - ^ expected struct `A`, found struct `B` + | | + | expected due to this + | +help: call `Into::into` on this expression to convert `B` into `A` + | +LL | let x: A = B.into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/into-convert.rs:10:24 + | +LL | let y: Arc = PathBuf::new(); + | --------- ^^^^^^^^^^^^^^ expected struct `Arc`, found struct `PathBuf` + | | + | expected due to this + | + = note: expected struct `Arc` + found struct `PathBuf` +help: call `Into::into` on this expression to convert `PathBuf` into `Arc` + | +LL | let y: Arc = PathBuf::new().into(); + | +++++++ + +error[E0308]: mismatched types + --> $DIR/into-convert.rs:14:24 + | +LL | let z: AtomicU32 = 1; + | --------- ^ expected struct `AtomicU32`, found integer + | | + | expected due to this + | +help: call `Into::into` on this expression to convert `{integer}` into `AtomicU32` + | +LL | let z: AtomicU32 = 1.into(); + | +++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/into-str.rs b/tests/ui/suggestions/into-str.rs new file mode 100644 index 000000000..606e44b2e --- /dev/null +++ b/tests/ui/suggestions/into-str.rs @@ -0,0 +1,6 @@ +fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + +fn main() { + foo(String::new()); + //~^ ERROR the trait bound `&str: From` is not satisfied +} diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr new file mode 100644 index 000000000..a56a2a188 --- /dev/null +++ b/tests/ui/suggestions/into-str.stderr @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `&str: From` is not satisfied + --> $DIR/into-str.rs:4:9 + | +LL | foo(String::new()); + | --- ^^^^^^^^^^^^^ the trait `From` is not implemented for `&str` + | | + | required by a bound introduced by this call + | + = note: to coerce a `String` into a `&str`, use `&*` as a prefix + = help: the following other types implement trait `From`: + > + > + > + >> + >> + > + = note: required for `String` to implement `Into<&str>` +note: required by a bound in `foo` + --> $DIR/into-str.rs:1:31 + | +LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {} + | ^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/invalid-bin-op.rs b/tests/ui/suggestions/invalid-bin-op.rs new file mode 100644 index 000000000..bea1b9155 --- /dev/null +++ b/tests/ui/suggestions/invalid-bin-op.rs @@ -0,0 +1,7 @@ +pub fn foo(s: S, t: S) { + let _ = s == t; //~ ERROR binary operation `==` cannot be applied to type `S` +} + +struct S(T); + +fn main() {} diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr new file mode 100644 index 000000000..08502dfeb --- /dev/null +++ b/tests/ui/suggestions/invalid-bin-op.stderr @@ -0,0 +1,25 @@ +error[E0369]: binary operation `==` cannot be applied to type `S` + --> $DIR/invalid-bin-op.rs:2:15 + | +LL | let _ = s == t; + | - ^^ - S + | | + | S + | +note: an implementation of `PartialEq<_>` might be missing for `S` + --> $DIR/invalid-bin-op.rs:5:1 + | +LL | struct S(T); + | ^^^^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `S` with `#[derive(PartialEq)]` + | +LL | #[derive(PartialEq)] + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub fn foo(s: S, t: S) where S: PartialEq { + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/suggestions/issue-101065.fixed b/tests/ui/suggestions/issue-101065.fixed new file mode 100644 index 000000000..88c716cc8 --- /dev/null +++ b/tests/ui/suggestions/issue-101065.fixed @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(FakeResult::Ok(())) //~ERROR E0308 + }; +} diff --git a/tests/ui/suggestions/issue-101065.rs b/tests/ui/suggestions/issue-101065.rs new file mode 100644 index 000000000..2715f1027 --- /dev/null +++ b/tests/ui/suggestions/issue-101065.rs @@ -0,0 +1,14 @@ +// check-fail +// run-rustfix + +enum FakeResult { + Ok(T) +} + +fn main() { + let _x = if true { + FakeResult::Ok(FakeResult::Ok(())) + } else { + FakeResult::Ok(()) //~ERROR E0308 + }; +} diff --git a/tests/ui/suggestions/issue-101065.stderr b/tests/ui/suggestions/issue-101065.stderr new file mode 100644 index 000000000..6f7ecd24c --- /dev/null +++ b/tests/ui/suggestions/issue-101065.stderr @@ -0,0 +1,23 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-101065.rs:12:9 + | +LL | let _x = if true { + | ______________- +LL | | FakeResult::Ok(FakeResult::Ok(())) + | | ---------------------------------- expected because of this +LL | | } else { +LL | | FakeResult::Ok(()) + | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()` +LL | | }; + | |_____- `if` and `else` have incompatible types + | + = note: expected enum `FakeResult>` + found enum `FakeResult<()>` +help: try wrapping the expression in `FakeResult::Ok` + | +LL | FakeResult::Ok(FakeResult::Ok(())) + | +++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-101421.rs b/tests/ui/suggestions/issue-101421.rs new file mode 100644 index 000000000..b615997d1 --- /dev/null +++ b/tests/ui/suggestions/issue-101421.rs @@ -0,0 +1,12 @@ +pub trait Ice { + fn f(&self, _: ()); +} + +impl Ice for () { + fn f(&self, _: ()) {} +} + +fn main() { + ().f::<()>(()); + //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied +} diff --git a/tests/ui/suggestions/issue-101421.stderr b/tests/ui/suggestions/issue-101421.stderr new file mode 100644 index 000000000..f8e1efb88 --- /dev/null +++ b/tests/ui/suggestions/issue-101421.stderr @@ -0,0 +1,17 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-101421.rs:10:8 + | +LL | ().f::<()>(()); + | ^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-101421.rs:2:8 + | +LL | fn f(&self, _: ()); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/issue-101465.rs b/tests/ui/suggestions/issue-101465.rs new file mode 100644 index 000000000..8e42e2c22 --- /dev/null +++ b/tests/ui/suggestions/issue-101465.rs @@ -0,0 +1,25 @@ +#![feature(trait_alias)] + +struct B; +struct C; + +trait Tr {} + +impl Tr for B {} +impl Tr for C {} + +trait Tr2 = Into; + +fn foo2>() {} + +fn foo() -> impl Tr { + let x = foo2::<_>(); + + match true { + true => B, + false => C, + //~^ `match` arms have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-101465.stderr b/tests/ui/suggestions/issue-101465.stderr new file mode 100644 index 000000000..e2ca77712 --- /dev/null +++ b/tests/ui/suggestions/issue-101465.stderr @@ -0,0 +1,25 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-101465.rs:20:18 + | +LL | / match true { +LL | | true => B, + | | - this is found to be of type `B` +LL | | false => C, + | | ^ expected struct `B`, found struct `C` +LL | | +LL | | } + | |_____- `match` arms have incompatible types + | +help: you could change the return type to be a boxed trait object + | +LL | fn foo() -> Box { + | ~~~~~~~ + +help: if you change the return type to expect trait objects, box the returned expressions + | +LL ~ true => Box::new(B), +LL ~ false => Box::new(C), + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-101623.rs b/tests/ui/suggestions/issue-101623.rs new file mode 100644 index 000000000..d18a4a21f --- /dev/null +++ b/tests/ui/suggestions/issue-101623.rs @@ -0,0 +1,25 @@ +pub struct Stuff { + inner: *mut (), +} + +pub struct Wrap(T); + +fn fun(t: T) -> Wrap { + todo!() +} + +pub trait Trait<'de> { + fn do_stuff(_: Wrap<&'de mut Self>); +} + +impl<'a> Trait<'a> for () { + fn do_stuff(_: Wrap<&'a mut Self>) {} +} + +fn fun2(t: &mut Stuff) -> () { + let Stuff { inner, .. } = t; + Trait::do_stuff({ fun(&mut *inner) }); + //~^ ERROR the trait bound `*mut (): Trait<'_>` is not satisfied +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr new file mode 100644 index 000000000..361483cc0 --- /dev/null +++ b/tests/ui/suggestions/issue-101623.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `*mut (): Trait<'_>` is not satisfied + --> $DIR/issue-101623.rs:21:21 + | +LL | Trait::do_stuff({ fun(&mut *inner) }); + | --------------- ^^----------------^^ + | | | + | | the trait `Trait<'_>` is not implemented for `*mut ()` + | required by a bound introduced by this call + | + = help: the trait `Trait<'a>` is implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-101984.rs b/tests/ui/suggestions/issue-101984.rs new file mode 100644 index 000000000..5f7ecb77e --- /dev/null +++ b/tests/ui/suggestions/issue-101984.rs @@ -0,0 +1,27 @@ +use std::marker::PhantomData; + +type Component = fn(&()); + +struct Wrapper { + router: Router<(Component, Box)>, +} + +struct Match(PhantomData); + +struct Router(PhantomData); + +impl Router { + pub fn at(&self) -> Result, ()> { + todo!() + } +} + +impl Wrapper { + fn at(&self, path: &str) -> Result<(Component, Box), ()> { + let (cmp, router) = self.router.at()?; + //~^ ERROR mismatched types + todo!() + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-101984.stderr b/tests/ui/suggestions/issue-101984.stderr new file mode 100644 index 000000000..81758a700 --- /dev/null +++ b/tests/ui/suggestions/issue-101984.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-101984.rs:21:13 + | +LL | let (cmp, router) = self.router.at()?; + | ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'a> fn(&'a ()), Box)>` + | | + | expected struct `Match`, found tuple + | + = note: expected struct `Match<&(for<'a> fn(&'a ()), Box)>` + found tuple `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-102354.rs b/tests/ui/suggestions/issue-102354.rs new file mode 100644 index 000000000..f881feb00 --- /dev/null +++ b/tests/ui/suggestions/issue-102354.rs @@ -0,0 +1,10 @@ +trait Trait { + fn func() {} +} + +impl Trait for i32 {} + +fn main() { + let x: i32 = 123; + x.func(); //~ERROR no method +} diff --git a/tests/ui/suggestions/issue-102354.stderr b/tests/ui/suggestions/issue-102354.stderr new file mode 100644 index 000000000..08d4b9955 --- /dev/null +++ b/tests/ui/suggestions/issue-102354.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `func` found for type `i32` in the current scope + --> $DIR/issue-102354.rs:9:7 + | +LL | x.func(); + | --^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `i32::func()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in the trait `Trait` + --> $DIR/issue-102354.rs:2:5 + | +LL | fn func() {} + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/issue-102892.rs b/tests/ui/suggestions/issue-102892.rs new file mode 100644 index 000000000..c1a791d8d --- /dev/null +++ b/tests/ui/suggestions/issue-102892.rs @@ -0,0 +1,25 @@ +#![allow(dead_code, unused_variables)] + +use std::sync::Arc; + +#[derive(Debug)] +struct A; +#[derive(Debug)] +struct B; + +fn process_without_annot(arc: &Arc<(A, B)>) { + let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +} + +fn process_with_annot(arc: &Arc<(A, B)>) { + let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too + //~^ ERROR mismatched types +} + +fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) { + let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + //~^ ERROR mismatched types + //~| ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr new file mode 100644 index 000000000..a3dbc7cb8 --- /dev/null +++ b/tests/ui/suggestions/issue-102892.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:15:26 + | +LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too + | ------ ^^^^^^ expected tuple, found `&(A, B)` + | | + | expected due to this + | + = note: expected tuple `(A, B)` + found reference `&(A, B)` +help: consider removing the borrow + | +LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too +LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too + | + + +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:20:32 + | +LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)` + | + = note: expected tuple `(A, B)` + found mutable reference `&mut (A, B)` +help: consider removing the borrow + | +LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too +LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ++++ + +error[E0308]: mismatched types + --> $DIR/issue-102892.rs:20:48 + | +LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | ^^^^^^^^^^ expected struct `A`, found `&A` + | +help: consider removing the borrow + | +LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too +LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too + | +help: alternatively, consider changing the type annotation + | +LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-103112.rs b/tests/ui/suggestions/issue-103112.rs new file mode 100644 index 000000000..111ae7c73 --- /dev/null +++ b/tests/ui/suggestions/issue-103112.rs @@ -0,0 +1,4 @@ +fn main() { + std::process::abort!(); + //~^ ERROR: failed to resolve +} diff --git a/tests/ui/suggestions/issue-103112.stderr b/tests/ui/suggestions/issue-103112.stderr new file mode 100644 index 000000000..4ca7fdf9b --- /dev/null +++ b/tests/ui/suggestions/issue-103112.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: could not find `abort` in `process` + --> $DIR/issue-103112.rs:2:19 + | +LL | std::process::abort!(); + | ^^^^^ could not find `abort` in `process` + | +help: std::process::abort is not a macro, but a function, try to remove `!` + | +LL - std::process::abort!(); +LL + std::process::abort(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/issue-104086-suggest-let.rs b/tests/ui/suggestions/issue-104086-suggest-let.rs new file mode 100644 index 000000000..d22ad27d0 --- /dev/null +++ b/tests/ui/suggestions/issue-104086-suggest-let.rs @@ -0,0 +1,30 @@ +fn main() { + x = x = x; + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + + x = y = y = y; + //~^ ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `x` in this scope + + x = y = y; + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `y` in this scope + //~| ERROR cannot find value `y` in this scope + + x = x = y; + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `y` in this scope + + x = x; // will suggest add `let` + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `x` in this scope + + x = y // will suggest add `let` + //~^ ERROR cannot find value `x` in this scope + //~| ERROR cannot find value `y` in this scope +} diff --git a/tests/ui/suggestions/issue-104086-suggest-let.stderr b/tests/ui/suggestions/issue-104086-suggest-let.stderr new file mode 100644 index 000000000..fb4ea3121 --- /dev/null +++ b/tests/ui/suggestions/issue-104086-suggest-let.stderr @@ -0,0 +1,135 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:2:5 + | +LL | x = x = x; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x = x; + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:2:9 + | +LL | x = x = x; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:2:13 + | +LL | x = x = x; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:5 + | +LL | x = y = y = y; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y = y = y; + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:9 + | +LL | x = y = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:13 + | +LL | x = y = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:7:17 + | +LL | x = y = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:13:5 + | +LL | x = y = y; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y = y; + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:13:9 + | +LL | x = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:13:13 + | +LL | x = y = y; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:18:5 + | +LL | x = x = y; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x = y; + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:18:9 + | +LL | x = x = y; + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:18:13 + | +LL | x = x = y; + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:23:5 + | +LL | x = x; // will suggest add `let` + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = x; // will suggest add `let` + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:23:9 + | +LL | x = x; // will suggest add `let` + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-104086-suggest-let.rs:27:5 + | +LL | x = y // will suggest add `let` + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = y // will suggest add `let` + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/issue-104086-suggest-let.rs:27:9 + | +LL | x = y // will suggest add `let` + | ^ not found in this scope + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/issue-104287.rs b/tests/ui/suggestions/issue-104287.rs new file mode 100644 index 000000000..e3fa22a8f --- /dev/null +++ b/tests/ui/suggestions/issue-104287.rs @@ -0,0 +1,13 @@ +// The purpose of this test is not to validate the output of the compiler. +// Instead, it ensures the suggestion is generated without performing an arithmetic overflow. + +struct S; +impl S { + fn foo(&self) {} +} +fn main() { + let x = S; + foo::<()>(x); + //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR cannot find function `foo` in this scope +} diff --git a/tests/ui/suggestions/issue-104287.stderr b/tests/ui/suggestions/issue-104287.stderr new file mode 100644 index 000000000..602a01828 --- /dev/null +++ b/tests/ui/suggestions/issue-104287.stderr @@ -0,0 +1,30 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-104287.rs:10:5 + | +LL | foo::<()>(x); + | ^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-104287.rs:6:8 + | +LL | fn foo(&self) {} + | ^^^ + +error[E0425]: cannot find function `foo` in this scope + --> $DIR/issue-104287.rs:10:5 + | +LL | foo::<()>(x); + | ^^^ not found in this scope + | +help: use the `.` operator to call the method `foo` on `&S` + | +LL - foo::<()>(x); +LL + x.foo(); + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0425. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/issue-104327.rs b/tests/ui/suggestions/issue-104327.rs new file mode 100644 index 000000000..dd621ae71 --- /dev/null +++ b/tests/ui/suggestions/issue-104327.rs @@ -0,0 +1,12 @@ +trait Bar {} + +trait Foo { + fn f() {} +} + +impl Foo for dyn Bar {} + +fn main() { + Foo::f(); + //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type +} diff --git a/tests/ui/suggestions/issue-104327.stderr b/tests/ui/suggestions/issue-104327.stderr new file mode 100644 index 000000000..acec3a55d --- /dev/null +++ b/tests/ui/suggestions/issue-104327.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/issue-104327.rs:10:5 + | +LL | fn f() {} + | --------- `Foo::f` defined here +... +LL | Foo::f(); + | ^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | <(dyn Bar + 'static) as Foo>::f(); + | +++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/suggestions/issue-104328.rs b/tests/ui/suggestions/issue-104328.rs new file mode 100644 index 000000000..c3707baf7 --- /dev/null +++ b/tests/ui/suggestions/issue-104328.rs @@ -0,0 +1,12 @@ +#![feature(object_safe_for_dispatch)] + +trait Foo { + fn f() {} +} + +impl Foo for dyn Sized {} + +fn main() { + Foo::f(); + //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type +} diff --git a/tests/ui/suggestions/issue-104328.stderr b/tests/ui/suggestions/issue-104328.stderr new file mode 100644 index 000000000..b31b84781 --- /dev/null +++ b/tests/ui/suggestions/issue-104328.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/issue-104328.rs:10:5 + | +LL | fn f() {} + | --------- `Foo::f` defined here +... +LL | Foo::f(); + | ^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | <(dyn Sized + 'static) as Foo>::f(); + | +++++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/suggestions/issue-105226.rs b/tests/ui/suggestions/issue-105226.rs new file mode 100644 index 000000000..f123dbf4c --- /dev/null +++ b/tests/ui/suggestions/issue-105226.rs @@ -0,0 +1,22 @@ +use std::fmt; + +struct S { +} + +impl S { + fn hello

(&self, val: &P) where P: fmt::Display; { + //~^ ERROR non-item in item list + //~| ERROR associated function in `impl` without body + println!("val: {}", val); + } +} + +impl S { + fn hello_empty

(&self, val: &P) where P: fmt::Display; + //~^ ERROR associated function in `impl` without body +} + +fn main() { + let s = S{}; + s.hello(&32); +} diff --git a/tests/ui/suggestions/issue-105226.stderr b/tests/ui/suggestions/issue-105226.stderr new file mode 100644 index 000000000..f16a80901 --- /dev/null +++ b/tests/ui/suggestions/issue-105226.stderr @@ -0,0 +1,31 @@ +error: non-item in item list + --> $DIR/issue-105226.rs:7:56 + | +LL | impl S { + | - item list starts here +LL | fn hello

(&self, val: &P) where P: fmt::Display; { + | - ^ non-item starts here + | | + | help: consider removing this semicolon +... +LL | } + | - item list ends here + +error: associated function in `impl` without body + --> $DIR/issue-105226.rs:7:5 + | +LL | fn hello

(&self, val: &P) where P: fmt::Display; { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: associated function in `impl` without body + --> $DIR/issue-105226.rs:15:5 + | +LL | fn hello_empty

(&self, val: &P) where P: fmt::Display; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/suggestions/issue-105494.rs b/tests/ui/suggestions/issue-105494.rs new file mode 100644 index 000000000..8b409232c --- /dev/null +++ b/tests/ui/suggestions/issue-105494.rs @@ -0,0 +1,22 @@ +fn test1() { + let _v: i32 = (1 as i32).to_string(); //~ ERROR mismatched types + + // won't suggestion + let _v: i32 = (1 as i128).to_string(); //~ ERROR mismatched types + + let _v: &str = "foo".to_string(); //~ ERROR mismatched types +} + +fn test2() { + let mut path: String = "/usr".to_string(); + let folder: String = "lib".to_string(); + + path = format!("{}/{}", path, folder).as_str(); //~ ERROR mismatched types + + println!("{}", &path); +} + +fn main() { + test1(); + test2(); +} diff --git a/tests/ui/suggestions/issue-105494.stderr b/tests/ui/suggestions/issue-105494.stderr new file mode 100644 index 000000000..5aa3f2af7 --- /dev/null +++ b/tests/ui/suggestions/issue-105494.stderr @@ -0,0 +1,54 @@ +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:2:19 + | +LL | let _v: i32 = (1 as i32).to_string(); + | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` + | | + | expected due to this + | +help: try removing the method call + | +LL - let _v: i32 = (1 as i32).to_string(); +LL + let _v: i32 = (1 as i32); + | + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:5:19 + | +LL | let _v: i32 = (1 as i128).to_string(); + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:7:20 + | +LL | let _v: &str = "foo".to_string(); + | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String` + | | + | expected due to this + | +help: try removing the method call + | +LL - let _v: &str = "foo".to_string(); +LL + let _v: &str = "foo"; + | + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:14:12 + | +LL | let mut path: String = "/usr".to_string(); + | ------ expected due to this type +... +LL | path = format!("{}/{}", path, folder).as_str(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str` + | +help: try removing the method call + | +LL - path = format!("{}/{}", path, folder).as_str(); +LL + path = format!("{}/{}", path, folder); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-105645.rs b/tests/ui/suggestions/issue-105645.rs new file mode 100644 index 000000000..681ce1c6e --- /dev/null +++ b/tests/ui/suggestions/issue-105645.rs @@ -0,0 +1,8 @@ +fn main() { + let mut buf = [0u8; 50]; + let mut bref = buf.as_slice(); + foo(&mut bref); + //~^ ERROR 4:9: 4:18: the trait bound `&[u8]: std::io::Write` is not satisfied [E0277] +} + +fn foo(_: &mut impl std::io::Write) {} diff --git a/tests/ui/suggestions/issue-105645.stderr b/tests/ui/suggestions/issue-105645.stderr new file mode 100644 index 000000000..895f5ffd1 --- /dev/null +++ b/tests/ui/suggestions/issue-105645.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `&[u8]: std::io::Write` is not satisfied + --> $DIR/issue-105645.rs:4:9 + | +LL | foo(&mut bref); + | --- ^^^^^^^^^ the trait `std::io::Write` is not implemented for `&[u8]` + | | + | required by a bound introduced by this call + | + = help: the trait `std::io::Write` is implemented for `&mut [u8]` +note: required by a bound in `foo` + --> $DIR/issue-105645.rs:8:21 + | +LL | fn foo(_: &mut impl std::io::Write) {} + | ^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed new file mode 100644 index 000000000..78e48364b --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed @@ -0,0 +1,28 @@ +//run-rustfix +#![allow(unused)] + +struct S; +impl S { + fn foo(&mut self) { + let x = |this: &Self, v: i32| { + this.bar(); + this.hel(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + x(self, 1); + x(self, 3); + } + fn bar(&self) {} + fn hel(&self) {} + fn qux(&mut self) {} + + fn hello(&mut self) { + let y = |this: &Self| { + this.bar(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + y(self); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs new file mode 100644 index 000000000..6d8a9ffc1 --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs @@ -0,0 +1,28 @@ +//run-rustfix +#![allow(unused)] + +struct S; +impl S { + fn foo(&mut self) { + let x = |v: i32| { + self.bar(); + self.hel(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + x(1); + x(3); + } + fn bar(&self) {} + fn hel(&self) {} + fn qux(&mut self) {} + + fn hello(&mut self) { + let y = || { + self.bar(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + y(); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr new file mode 100644 index 000000000..bc97d32eb --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr @@ -0,0 +1,49 @@ +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/issue-105761-suggest-self-for-closure.rs:11:9 + | +LL | let x = |v: i32| { + | -------- immutable borrow occurs here +LL | self.bar(); + | ---- first borrow occurs due to use of `self` in closure +... +LL | self.qux(); + | ^^^^^^^^^^ mutable borrow occurs here +LL | x(1); + | - immutable borrow later used here + | +help: try explicitly pass `&Self` into the Closure as an argument + | +LL ~ let x = |this: &Self, v: i32| { +LL ~ this.bar(); +LL ~ this.hel(); +LL | }; +LL | self.qux(); +LL ~ x(self, 1); +LL ~ x(self, 3); + | + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/issue-105761-suggest-self-for-closure.rs:23:9 + | +LL | let y = || { + | -- immutable borrow occurs here +LL | self.bar(); + | ---- first borrow occurs due to use of `self` in closure +LL | }; +LL | self.qux(); + | ^^^^^^^^^^ mutable borrow occurs here +LL | y(); + | - immutable borrow later used here + | +help: try explicitly pass `&Self` into the Closure as an argument + | +LL ~ let y = |this: &Self| { +LL ~ this.bar(); +LL | }; +LL | self.qux(); +LL ~ y(self); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs new file mode 100644 index 000000000..48efdb82c --- /dev/null +++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.rs @@ -0,0 +1,23 @@ +#[derive(Clone)] +struct S; + +// without Clone +struct T; + +fn foo(_: S) {} + +fn test1() { + let s = &S; + foo(s); //~ ERROR mismatched types +} + +fn bar(_: T) {} +fn test2() { + let t = &T; + bar(t); //~ ERROR mismatched types +} + +fn main() { + test1(); + test2(); +} diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr new file mode 100644 index 000000000..1e66fe3af --- /dev/null +++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-106443-sugg-clone-for-arg.rs:11:9 + | +LL | foo(s); + | --- ^ expected struct `S`, found `&S` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-106443-sugg-clone-for-arg.rs:7:4 + | +LL | fn foo(_: S) {} + | ^^^ ---- +help: consider using clone here + | +LL | foo(s.clone()); + | ++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-106443-sugg-clone-for-arg.rs:17:9 + | +LL | bar(t); + | --- ^ expected struct `T`, found `&T` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-106443-sugg-clone-for-arg.rs:14:4 + | +LL | fn bar(_: T) {} + | ^^^ ---- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs new file mode 100644 index 000000000..3b2e316b2 --- /dev/null +++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.rs @@ -0,0 +1,20 @@ +#[derive(Clone)] +struct S; + +trait X {} + +impl X for S {} + +fn foo(_: T) {} +fn bar(s: &T) { + foo(s); //~ ERROR the trait bound `&T: X` is not satisfied +} + +fn bar_with_clone(s: &T) { + foo(s); //~ ERROR the trait bound `&T: X` is not satisfied +} + +fn main() { + let s = &S; + bar(s); +} diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr new file mode 100644 index 000000000..8607917ed --- /dev/null +++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `&T: X` is not satisfied + --> $DIR/issue-106443-sugg-clone-for-bound.rs:10:9 + | +LL | foo(s); + | ^ the trait `X` is not implemented for `&T` + | +help: consider further restricting this bound + | +LL | fn bar(s: &T) { + | +++++++ +help: consider using clone here + | +LL | foo(s.clone()); + | ++++++++ + +error[E0277]: the trait bound `&T: X` is not satisfied + --> $DIR/issue-106443-sugg-clone-for-bound.rs:14:9 + | +LL | foo(s); + | ^ the trait `X` is not implemented for `&T` + | +help: consider using clone here + | +LL | foo(s.clone()); + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-21673.rs b/tests/ui/suggestions/issue-21673.rs new file mode 100644 index 000000000..9d66cae05 --- /dev/null +++ b/tests/ui/suggestions/issue-21673.rs @@ -0,0 +1,13 @@ +trait Foo { + fn method(&self) {} +} + +fn call_method(x: &T) { + x.method() //~ ERROR E0599 +} + +fn call_method_2(x: T) { + x.method() //~ ERROR E0599 +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-21673.stderr b/tests/ui/suggestions/issue-21673.stderr new file mode 100644 index 000000000..523d7a7cc --- /dev/null +++ b/tests/ui/suggestions/issue-21673.stderr @@ -0,0 +1,29 @@ +error[E0599]: no method named `method` found for reference `&T` in the current scope + --> $DIR/issue-21673.rs:6:7 + | +LL | x.method() + | ^^^^^^ method not found in `&T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn call_method(x: &T) { + | +++++ + +error[E0599]: no method named `method` found for type parameter `T` in the current scope + --> $DIR/issue-21673.rs:10:7 + | +LL | fn call_method_2(x: T) { + | - method `method` not found for this type parameter +LL | x.method() + | ^^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn call_method_2(x: T) { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs new file mode 100644 index 000000000..37f078285 --- /dev/null +++ b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs @@ -0,0 +1,8 @@ +fn vindictive() -> bool { true } + +fn perfidy() -> (i32, i32) { + vindictive() //~ ERROR expected function, found `bool` + (1, 2) +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr new file mode 100644 index 000000000..438075083 --- /dev/null +++ b/tests/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr @@ -0,0 +1,16 @@ +error[E0618]: expected function, found `bool` + --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5 + | +LL | fn vindictive() -> bool { true } + | ----------------------- `vindictive` defined here returns `bool` +... +LL | vindictive() + | -^^^^^^^^^^^- help: consider using a semicolon here: `;` + | _____| + | | +LL | | (1, 2) + | |__________- call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/issue-52820.fixed b/tests/ui/suggestions/issue-52820.fixed new file mode 100644 index 000000000..514690de4 --- /dev/null +++ b/tests/ui/suggestions/issue-52820.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(dead_code)] + +struct Bravery { + guts: String, + brains: String, +} + +fn main() { + let guts = "mettle"; + let _ = Bravery { + guts: guts.to_string(), //~ ERROR mismatched types + brains: guts.to_string(), //~ ERROR mismatched types + }; +} diff --git a/tests/ui/suggestions/issue-52820.rs b/tests/ui/suggestions/issue-52820.rs new file mode 100644 index 000000000..17cd9224c --- /dev/null +++ b/tests/ui/suggestions/issue-52820.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(dead_code)] + +struct Bravery { + guts: String, + brains: String, +} + +fn main() { + let guts = "mettle"; + let _ = Bravery { + guts, //~ ERROR mismatched types + brains: guts.clone(), //~ ERROR mismatched types + }; +} diff --git a/tests/ui/suggestions/issue-52820.stderr b/tests/ui/suggestions/issue-52820.stderr new file mode 100644 index 000000000..09269ed4e --- /dev/null +++ b/tests/ui/suggestions/issue-52820.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/issue-52820.rs:12:9 + | +LL | guts, + | ^^^^ expected struct `String`, found `&str` + | +help: try using a conversion method + | +LL | guts: guts.to_string(), + | +++++ ++++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-52820.rs:13:17 + | +LL | brains: guts.clone(), + | ^^^^^-----^^ + | | | + | | help: try using a conversion method: `to_string` + | expected struct `String`, found `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-53692.fixed b/tests/ui/suggestions/issue-53692.fixed new file mode 100644 index 000000000..35a677b47 --- /dev/null +++ b/tests/ui/suggestions/issue-53692.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let items = vec![1, 2, 3]; + let ref_items: &[i32] = &items; + let items_clone: Vec = ref_items.to_vec(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let items_clone_2: Vec = items.clone(); + + let s = "hi"; + let string: String = s.to_string(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let s2 = "hi"; + let string_2: String = s2.to_string(); +} diff --git a/tests/ui/suggestions/issue-53692.rs b/tests/ui/suggestions/issue-53692.rs new file mode 100644 index 000000000..6f6707be5 --- /dev/null +++ b/tests/ui/suggestions/issue-53692.rs @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let items = vec![1, 2, 3]; + let ref_items: &[i32] = &items; + let items_clone: Vec = ref_items.clone(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let items_clone_2: Vec = items.clone(); + + let s = "hi"; + let string: String = s.clone(); + //~^ ERROR mismatched types + + // in that case no suggestion will be triggered + let s2 = "hi"; + let string_2: String = s2.to_string(); +} diff --git a/tests/ui/suggestions/issue-53692.stderr b/tests/ui/suggestions/issue-53692.stderr new file mode 100644 index 000000000..3a1b624f4 --- /dev/null +++ b/tests/ui/suggestions/issue-53692.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/issue-53692.rs:7:33 + | +LL | let items_clone: Vec = ref_items.clone(); + | -------- ^^^^^^^^^^-----^^ + | | | | + | | | help: try using a conversion method: `to_vec` + | | expected struct `Vec`, found `&[i32]` + | expected due to this + | + = note: expected struct `Vec` + found reference `&[i32]` + +error[E0308]: mismatched types + --> $DIR/issue-53692.rs:14:26 + | +LL | let string: String = s.clone(); + | ------ ^^-----^^ + | | | | + | | | help: try using a conversion method: `to_string` + | | expected struct `String`, found `&str` + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-57672.rs b/tests/ui/suggestions/issue-57672.rs new file mode 100644 index 000000000..ee999d83e --- /dev/null +++ b/tests/ui/suggestions/issue-57672.rs @@ -0,0 +1,14 @@ +// aux-build:foo.rs +// compile-flags:--extern foo +// check-pass +// edition:2018 + +#![deny(unused_extern_crates)] + +extern crate foo as foo_renamed; + +pub mod m { + pub use foo_renamed::Foo; +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-59819.fixed b/tests/ui/suggestions/issue-59819.fixed new file mode 100644 index 000000000..644d2a4e4 --- /dev/null +++ b/tests/ui/suggestions/issue-59819.fixed @@ -0,0 +1,35 @@ +// run-rustfix + +#![allow(warnings)] + +// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as +// references. + +struct Foo(i32); + +struct Bar(String); + +impl std::ops::Deref for Foo { + type Target = i32; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::Deref for Bar { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let x = Foo(42); + let y: i32 = *x; //~ ERROR mismatched types + let a = &42; + let b: i32 = *a; //~ ERROR mismatched types + + // Do not make a suggestion when adding a `*` wouldn't actually fix the issue: + let f = Bar("bar".to_string()); + let g: String = f.to_string(); //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/issue-59819.rs b/tests/ui/suggestions/issue-59819.rs new file mode 100644 index 000000000..8e8ff8372 --- /dev/null +++ b/tests/ui/suggestions/issue-59819.rs @@ -0,0 +1,35 @@ +// run-rustfix + +#![allow(warnings)] + +// Test that suggestion to add `*` characters applies to implementations of `Deref` as well as +// references. + +struct Foo(i32); + +struct Bar(String); + +impl std::ops::Deref for Foo { + type Target = i32; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::Deref for Bar { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let x = Foo(42); + let y: i32 = x; //~ ERROR mismatched types + let a = &42; + let b: i32 = a; //~ ERROR mismatched types + + // Do not make a suggestion when adding a `*` wouldn't actually fix the issue: + let f = Bar("bar".to_string()); + let g: String = f; //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/issue-59819.stderr b/tests/ui/suggestions/issue-59819.stderr new file mode 100644 index 000000000..40e4c7b78 --- /dev/null +++ b/tests/ui/suggestions/issue-59819.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/issue-59819.rs:28:18 + | +LL | let y: i32 = x; + | --- ^ expected `i32`, found struct `Foo` + | | + | expected due to this + | +help: consider dereferencing the type + | +LL | let y: i32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/issue-59819.rs:30:18 + | +LL | let b: i32 = a; + | --- ^ expected `i32`, found `&{integer}` + | | + | expected due to this + | +help: consider dereferencing the borrow + | +LL | let b: i32 = *a; + | + + +error[E0308]: mismatched types + --> $DIR/issue-59819.rs:34:21 + | +LL | let g: String = f; + | ------ ^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found struct `Bar` + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-61226.fixed b/tests/ui/suggestions/issue-61226.fixed new file mode 100644 index 000000000..6e9d74344 --- /dev/null +++ b/tests/ui/suggestions/issue-61226.fixed @@ -0,0 +1,6 @@ +// run-rustfix +struct X {} +fn main() { + let _ = vec![X {}]; //… + //~^ ERROR expected value, found struct `X` +} diff --git a/tests/ui/suggestions/issue-61226.rs b/tests/ui/suggestions/issue-61226.rs new file mode 100644 index 000000000..695fe7341 --- /dev/null +++ b/tests/ui/suggestions/issue-61226.rs @@ -0,0 +1,6 @@ +// run-rustfix +struct X {} +fn main() { + let _ = vec![X]; //… + //~^ ERROR expected value, found struct `X` +} diff --git a/tests/ui/suggestions/issue-61226.stderr b/tests/ui/suggestions/issue-61226.stderr new file mode 100644 index 000000000..cda962a90 --- /dev/null +++ b/tests/ui/suggestions/issue-61226.stderr @@ -0,0 +1,12 @@ +error[E0423]: expected value, found struct `X` + --> $DIR/issue-61226.rs:4:18 + | +LL | struct X {} + | ----------- `X` defined here +LL | fn main() { +LL | let _ = vec![X]; //… + | ^ help: use struct literal syntax instead: `X {}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs new file mode 100644 index 000000000..a27c38452 --- /dev/null +++ b/tests/ui/suggestions/issue-61963.rs @@ -0,0 +1,37 @@ +// aux-build:issue-61963.rs +// aux-build:issue-61963-1.rs +#![deny(bare_trait_objects)] + +#[macro_use] +extern crate issue_61963; +#[macro_use] +extern crate issue_61963_1; + +// This test checks that the bare trait object lint does not trigger on macro attributes that +// generate code which would trigger the lint. + +pub struct Baz; +pub trait Bar {} +pub struct Qux(T); + +#[dom_struct] +pub struct Foo { + //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + qux: Qux>, + bar: Box, + //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition + //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr new file mode 100644 index 000000000..b99b1b0b9 --- /dev/null +++ b/tests/ui/suggestions/issue-61963.stderr @@ -0,0 +1,98 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:28:14 + | +LL | bar: Box, + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +note: the lint level is defined here + --> $DIR/issue-61963.rs:3:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: use `dyn` + | +LL | bar: Box, + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | dyn pub struct Foo { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:28:14 + | +LL | bar: Box, + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | bar: Box, + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:28:14 + | +LL | bar: Box, + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | bar: Box, + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | dyn pub struct Foo { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | dyn pub struct Foo { + | +++ + +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-61963.rs:18:1 + | +LL | pub struct Foo { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | dyn pub struct Foo { + | +++ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/suggestions/issue-62843.rs b/tests/ui/suggestions/issue-62843.rs new file mode 100644 index 000000000..d96b12fd1 --- /dev/null +++ b/tests/ui/suggestions/issue-62843.rs @@ -0,0 +1,5 @@ +fn main() { + let line = String::from("abc"); + let pattern = String::from("bc"); + println!("{:?}", line.find(pattern)); //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr new file mode 100644 index 000000000..b6e271de8 --- /dev/null +++ b/tests/ui/suggestions/issue-62843.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `FnMut<(char,)>` closure, found `String` + --> $DIR/issue-62843.rs:4:32 + | +LL | println!("{:?}", line.find(pattern)); + | ---- ^^^^^^^ the trait `Pattern<'_>` is not implemented for `String` + | | + | required by a bound introduced by this call + | + = note: the trait bound `String: Pattern<'_>` is not satisfied + = note: required for `String` to implement `Pattern<'_>` +note: required by a bound in `core::str::::find` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL +help: consider borrowing here + | +LL | println!("{:?}", line.find(&pattern)); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-64252-self-type.rs b/tests/ui/suggestions/issue-64252-self-type.rs new file mode 100644 index 000000000..128d5e85c --- /dev/null +++ b/tests/ui/suggestions/issue-64252-self-type.rs @@ -0,0 +1,14 @@ +// This test checks that a suggestion to add a `self: ` parameter name is provided +// to functions where this is applicable. + +pub fn foo(Box) { } +//~^ ERROR expected one of `:`, `@`, or `|`, found `<` + +struct Bar; + +impl Bar { + fn bar(Box) { } + //~^ ERROR expected one of `:`, `@`, or `|`, found `<` +} + +fn main() { } diff --git a/tests/ui/suggestions/issue-64252-self-type.stderr b/tests/ui/suggestions/issue-64252-self-type.stderr new file mode 100644 index 000000000..c3418dab0 --- /dev/null +++ b/tests/ui/suggestions/issue-64252-self-type.stderr @@ -0,0 +1,34 @@ +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/issue-64252-self-type.rs:4:15 + | +LL | pub fn foo(Box) { } + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | pub fn foo(self: Box) { } + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | pub fn foo(_: Box) { } + | ++ + +error: expected one of `:`, `@`, or `|`, found `<` + --> $DIR/issue-64252-self-type.rs:10:15 + | +LL | fn bar(Box) { } + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn bar(self: Box) { } + | +++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn bar(_: Box) { } + | ++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/suggestions/issue-66968-suggest-sorted-words.rs b/tests/ui/suggestions/issue-66968-suggest-sorted-words.rs new file mode 100644 index 000000000..440bb653a --- /dev/null +++ b/tests/ui/suggestions/issue-66968-suggest-sorted-words.rs @@ -0,0 +1,4 @@ +fn main() { + let a_longer_variable_name = 1; + println!("{}", a_variable_longer_name); //~ ERROR E0425 +} diff --git a/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr b/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr new file mode 100644 index 000000000..d7b33ea41 --- /dev/null +++ b/tests/ui/suggestions/issue-66968-suggest-sorted-words.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `a_variable_longer_name` in this scope + --> $DIR/issue-66968-suggest-sorted-words.rs:3:20 + | +LL | println!("{}", a_variable_longer_name); + | ^^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `a_longer_variable_name` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/issue-68049-1.rs b/tests/ui/suggestions/issue-68049-1.rs new file mode 100644 index 000000000..0acb7b1bf --- /dev/null +++ b/tests/ui/suggestions/issue-68049-1.rs @@ -0,0 +1,16 @@ +use std::alloc::{GlobalAlloc, Layout}; + +struct Test(u32); + +unsafe impl GlobalAlloc for Test { + unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { + self.0 += 1; //~ ERROR cannot assign + 0 as *mut u8 + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + unimplemented!(); + } +} + +fn main() { } diff --git a/tests/ui/suggestions/issue-68049-1.stderr b/tests/ui/suggestions/issue-68049-1.stderr new file mode 100644 index 000000000..7f931f0cd --- /dev/null +++ b/tests/ui/suggestions/issue-68049-1.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/issue-68049-1.rs:7:9 + | +LL | self.0 += 1; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/issue-68049-2.rs b/tests/ui/suggestions/issue-68049-2.rs new file mode 100644 index 000000000..1c3430c14 --- /dev/null +++ b/tests/ui/suggestions/issue-68049-2.rs @@ -0,0 +1,21 @@ +trait Hello { + fn example(&self, input: &i32); // should suggest here +} + +struct Test1(i32); + +impl Hello for Test1 { + fn example(&self, input: &i32) { // should not suggest here + *input = self.0; //~ ERROR cannot assign + } +} + +struct Test2(i32); + +impl Hello for Test2 { + fn example(&self, input: &i32) { // should not suggest here + self.0 += *input; //~ ERROR cannot assign + } +} + +fn main() { } diff --git a/tests/ui/suggestions/issue-68049-2.stderr b/tests/ui/suggestions/issue-68049-2.stderr new file mode 100644 index 000000000..de35aa5b1 --- /dev/null +++ b/tests/ui/suggestions/issue-68049-2.stderr @@ -0,0 +1,25 @@ +error[E0594]: cannot assign to `*input`, which is behind a `&` reference + --> $DIR/issue-68049-2.rs:9:7 + | +LL | *input = self.0; + | ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing that to be a mutable reference + | +LL | fn example(&self, input: &mut i32); // should suggest here + | ~~~~~~~~ + +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/issue-68049-2.rs:17:5 + | +LL | self.0 += *input; + | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing that to be a mutable reference + | +LL | fn example(&mut self, input: &i32); // should suggest here + | ~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.rs b/tests/ui/suggestions/issue-71394-no-from-impl.rs new file mode 100644 index 000000000..0c35deb51 --- /dev/null +++ b/tests/ui/suggestions/issue-71394-no-from-impl.rs @@ -0,0 +1,5 @@ +fn main() { + let data: &[u8] = &[0; 10]; + let _: &[i8] = data.into(); + //~^ ERROR the trait bound `&[i8]: From<&[u8]>` is not satisfied +} diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr new file mode 100644 index 000000000..a5e6f5b5f --- /dev/null +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied + --> $DIR/issue-71394-no-from-impl.rs:3:25 + | +LL | let _: &[i8] = data.into(); + | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` + | + = help: the following other types implement trait `From`: + <[T; LANES] as From>> + <[bool; LANES] as From>> + = note: required for `&[u8]` to implement `Into<&[i8]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-72766.rs b/tests/ui/suggestions/issue-72766.rs new file mode 100644 index 000000000..c54be7f5d --- /dev/null +++ b/tests/ui/suggestions/issue-72766.rs @@ -0,0 +1,20 @@ +// edition:2018 +// incremental + +pub struct SadGirl; + +impl SadGirl { + pub async fn call(&self) -> Result<(), ()> { + Ok(()) + } +} + +async fn async_main() -> Result<(), ()> { + // should be `.call().await?` + SadGirl {}.call()?; //~ ERROR: the `?` operator can only be applied to values + Ok(()) +} + +fn main() { + let _ = async_main(); +} diff --git a/tests/ui/suggestions/issue-72766.stderr b/tests/ui/suggestions/issue-72766.stderr new file mode 100644 index 000000000..f257bb9b0 --- /dev/null +++ b/tests/ui/suggestions/issue-72766.stderr @@ -0,0 +1,15 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-72766.rs:14:5 + | +LL | SadGirl {}.call()?; + | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future>` + | + = help: the trait `Try` is not implemented for `impl Future>` +help: consider `await`ing on the `Future` + | +LL | SadGirl {}.call().await?; + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs new file mode 100644 index 000000000..3cd6d336e --- /dev/null +++ b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs @@ -0,0 +1,32 @@ +// Regression test: if we suggest replacing an `impl Trait` argument to an async +// fn with a named type parameter in order to add bounds, the suggested function +// signature should be well-formed. +// +// edition:2018 + +trait Foo { + type Bar; + fn bar(&self) -> Self::Bar; +} + +async fn run(_: &(), foo: impl Foo) -> std::io::Result<()> { + let bar = foo.bar(); + assert_is_send(&bar); +//~^ ERROR: `::Bar` cannot be sent between threads safely + + Ok(()) +} + +// Test our handling of cases where there is a generic parameter list in the +// source, but only synthetic generic parameters +async fn run2< >(_: &(), foo: impl Foo) -> std::io::Result<()> { + let bar = foo.bar(); + assert_is_send(&bar); +//~^ ERROR: `::Bar` cannot be sent between threads safely + + Ok(()) +} + +fn assert_is_send(_: &T) {} + +fn main() {} diff --git a/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr new file mode 100644 index 000000000..a3ab0b8ef --- /dev/null +++ b/tests/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr @@ -0,0 +1,41 @@ +error[E0277]: `::Bar` cannot be sent between threads safely + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20 + | +LL | assert_is_send(&bar); + | -------------- ^^^^ `::Bar` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `::Bar` +note: required by a bound in `assert_is_send` + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:30:22 + | +LL | fn assert_is_send(_: &T) {} + | ^^^^ required by this bound in `assert_is_send` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | async fn run(_: &(), foo: F) -> std::io::Result<()> where ::Bar: Send { + | ++++++++ ~ +++++++++++++++++++++++++++ + +error[E0277]: `::Bar` cannot be sent between threads safely + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20 + | +LL | assert_is_send(&bar); + | -------------- ^^^^ `::Bar` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `::Bar` +note: required by a bound in `assert_is_send` + --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:30:22 + | +LL | fn assert_is_send(_: &T) {} + | ^^^^ required by this bound in `assert_is_send` +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL | async fn run2(_: &(), foo: F) -> std::io::Result<()> where ::Bar: Send { + | ~~~~~~~~ ~ +++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-81098.rs b/tests/ui/suggestions/issue-81098.rs new file mode 100644 index 000000000..a601b5866 --- /dev/null +++ b/tests/ui/suggestions/issue-81098.rs @@ -0,0 +1,13 @@ +// Don't suggest removing a semicolon if the last statement isn't an expression with semicolon +// (#81098) +fn wat() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display` + fn why() {} +} + +// Do it if the last statement is an expression with semicolon +// (#54771) +fn ok() -> impl core::fmt::Display { //~ ERROR: `()` doesn't implement `std::fmt::Display` + 1; +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-81098.stderr b/tests/ui/suggestions/issue-81098.stderr new file mode 100644 index 000000000..4dc47a202 --- /dev/null +++ b/tests/ui/suggestions/issue-81098.stderr @@ -0,0 +1,25 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/issue-81098.rs:3:13 + | +LL | fn wat() -> impl core::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/issue-81098.rs:9:12 + | +LL | fn ok() -> impl core::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter +LL | 1; + | -- help: remove this semicolon + | | + | this expression has type `{integer}`, which implements `std::fmt::Display` + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-81839.rs b/tests/ui/suggestions/issue-81839.rs new file mode 100644 index 000000000..0b9b7aefe --- /dev/null +++ b/tests/ui/suggestions/issue-81839.rs @@ -0,0 +1,17 @@ +// aux-build:issue-81839.rs +// edition:2018 + +extern crate issue_81839; + +async fn test(ans: &str, num: i32, cx: &issue_81839::Test) -> u32 { + match num { + 1 => { + cx.answer_str("hi"); + } + _ => cx.answer_str("hi"), //~ `match` arms have incompatible types + } + + 1 +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-81839.stderr b/tests/ui/suggestions/issue-81839.stderr new file mode 100644 index 000000000..fae474ced --- /dev/null +++ b/tests/ui/suggestions/issue-81839.stderr @@ -0,0 +1,27 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-81839.rs:11:14 + | +LL | / match num { +LL | | 1 => { +LL | | cx.answer_str("hi"); + | | -------------------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` +LL | | } +LL | | _ => cx.answer_str("hi"), + | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type +LL | | } + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/auxiliary/issue-81839.rs:6:49 + | +LL | pub async fn answer_str(&self, _s: &str) -> Test { + | ^^^^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-82361.fixed b/tests/ui/suggestions/issue-82361.fixed new file mode 100644 index 000000000..d72de982b --- /dev/null +++ b/tests/ui/suggestions/issue-82361.fixed @@ -0,0 +1,24 @@ +// run-rustfix + +fn main() { + let a: usize = 123; + let b: &usize = &a; + + if true { + a + } else { + *b //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; +} diff --git a/tests/ui/suggestions/issue-82361.rs b/tests/ui/suggestions/issue-82361.rs new file mode 100644 index 000000000..c068f6d22 --- /dev/null +++ b/tests/ui/suggestions/issue-82361.rs @@ -0,0 +1,24 @@ +// run-rustfix + +fn main() { + let a: usize = 123; + let b: &usize = &a; + + if true { + a + } else { + b //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + &1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; + + if true { + 1 + } else { + &mut 1 //~ ERROR `if` and `else` have incompatible types [E0308] + }; +} diff --git a/tests/ui/suggestions/issue-82361.stderr b/tests/ui/suggestions/issue-82361.stderr new file mode 100644 index 000000000..e4e8ad15d --- /dev/null +++ b/tests/ui/suggestions/issue-82361.stderr @@ -0,0 +1,56 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:10:9 + | +LL | / if true { +LL | | a + | | - expected because of this +LL | | } else { +LL | | b + | | ^ expected `usize`, found `&usize` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: consider dereferencing the borrow + | +LL | *b + | + + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:16:9 + | +LL | / if true { +LL | | 1 + | | - expected because of this +LL | | } else { +LL | | &1 + | | ^^ expected integer, found `&{integer}` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: consider removing the borrow + | +LL - &1 +LL + 1 + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-82361.rs:22:9 + | +LL | / if true { +LL | | 1 + | | - expected because of this +LL | | } else { +LL | | &mut 1 + | | ^^^^^^ expected integer, found `&mut {integer}` +LL | | }; + | |_____- `if` and `else` have incompatible types + | +help: consider removing the borrow + | +LL - &mut 1 +LL + 1 + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-82566-1.rs b/tests/ui/suggestions/issue-82566-1.rs new file mode 100644 index 000000000..95c31fbaa --- /dev/null +++ b/tests/ui/suggestions/issue-82566-1.rs @@ -0,0 +1,21 @@ +struct T1; +struct T2; +struct T3; + +impl T1<1> { + const C: () = (); +} + +impl T2<1, 2> { + const C: () = (); +} + +impl T3<1, 2, 3> { + const C: () = (); +} + +fn main() { + T1<1>::C; //~ ERROR: comparison operators cannot be chained + T2<1, 2>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + T3<1, 2, 3>::C; //~ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` +} diff --git a/tests/ui/suggestions/issue-82566-1.stderr b/tests/ui/suggestions/issue-82566-1.stderr new file mode 100644 index 000000000..72f0f45fb --- /dev/null +++ b/tests/ui/suggestions/issue-82566-1.stderr @@ -0,0 +1,35 @@ +error: comparison operators cannot be chained + --> $DIR/issue-82566-1.rs:18:7 + | +LL | T1<1>::C; + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | T1::<1>::C; + | ++ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-82566-1.rs:19:9 + | +LL | T2<1, 2>::C; + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | T2::<1, 2>::C; + | ++ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-82566-1.rs:20:9 + | +LL | T3<1, 2, 3>::C; + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | T3::<1, 2, 3>::C; + | ++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/suggestions/issue-82566-2.rs b/tests/ui/suggestions/issue-82566-2.rs new file mode 100644 index 000000000..80c8034bd --- /dev/null +++ b/tests/ui/suggestions/issue-82566-2.rs @@ -0,0 +1,31 @@ +struct Foo1; +struct Foo2; +struct Foo3; + +impl Foo1 { + const SUM: usize = N1; +} + +impl Foo2 { + const SUM: usize = N1 + N2; +} + +impl Foo3 { + const SUM: usize = N1 + N2 + N3; +} + +fn foo1() -> [(); Foo1<10>::SUM] { //~ ERROR: comparison operators cannot be chained + todo!() +} + +fn foo2() -> [(); Foo2<10, 20>::SUM] { + //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,` + todo!() +} + +fn foo3() -> [(); Foo3<10, 20, 30>::SUM] { + //~^ ERROR: expected one of `.`, `?`, `]`, or an operator, found `,` + todo!() +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-82566-2.stderr b/tests/ui/suggestions/issue-82566-2.stderr new file mode 100644 index 000000000..ef9a41430 --- /dev/null +++ b/tests/ui/suggestions/issue-82566-2.stderr @@ -0,0 +1,35 @@ +error: comparison operators cannot be chained + --> $DIR/issue-82566-2.rs:17:23 + | +LL | fn foo1() -> [(); Foo1<10>::SUM] { + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | fn foo1() -> [(); Foo1::<10>::SUM] { + | ++ + +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/issue-82566-2.rs:21:26 + | +LL | fn foo2() -> [(); Foo2<10, 20>::SUM] { + | ^ expected one of `.`, `?`, `]`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | fn foo2() -> [(); Foo2::<10, 20>::SUM] { + | ++ + +error: expected one of `.`, `?`, `]`, or an operator, found `,` + --> $DIR/issue-82566-2.rs:26:26 + | +LL | fn foo3() -> [(); Foo3<10, 20, 30>::SUM] { + | ^ expected one of `.`, `?`, `]`, or an operator + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | fn foo3() -> [(); Foo3::<10, 20, 30>::SUM] { + | ++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/suggestions/issue-83892.fixed b/tests/ui/suggestions/issue-83892.fixed new file mode 100644 index 000000000..dd093a7a0 --- /dev/null +++ b/tests/ui/suggestions/issue-83892.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +fn func() -> u8 { + 0 +} + +fn main() { + match () { + () => func() //~ ERROR mismatched types + }; +} diff --git a/tests/ui/suggestions/issue-83892.rs b/tests/ui/suggestions/issue-83892.rs new file mode 100644 index 000000000..1d56ecee8 --- /dev/null +++ b/tests/ui/suggestions/issue-83892.rs @@ -0,0 +1,11 @@ +// run-rustfix + +fn func() -> u8 { + 0 +} + +fn main() { + match () { + () => func() //~ ERROR mismatched types + } +} diff --git a/tests/ui/suggestions/issue-83892.stderr b/tests/ui/suggestions/issue-83892.stderr new file mode 100644 index 000000000..baf6b1447 --- /dev/null +++ b/tests/ui/suggestions/issue-83892.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-83892.rs:9:15 + | +LL | fn main() { + | - expected `()` because of default return type +LL | match () { +LL | () => func() + | ^^^^^^ expected `()`, found `u8` +LL | } + | - help: consider using a semicolon here: `;` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-83943.fixed b/tests/ui/suggestions/issue-83943.fixed new file mode 100644 index 000000000..e0d4ee29e --- /dev/null +++ b/tests/ui/suggestions/issue-83943.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + if true { + "A".to_string() + } else { + "B".to_string() //~ ERROR `if` and `else` have incompatible types + }; +} diff --git a/tests/ui/suggestions/issue-83943.rs b/tests/ui/suggestions/issue-83943.rs new file mode 100644 index 000000000..68d50c177 --- /dev/null +++ b/tests/ui/suggestions/issue-83943.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + if true { + "A".to_string() + } else { + "B" //~ ERROR `if` and `else` have incompatible types + }; +} diff --git a/tests/ui/suggestions/issue-83943.stderr b/tests/ui/suggestions/issue-83943.stderr new file mode 100644 index 000000000..885106e84 --- /dev/null +++ b/tests/ui/suggestions/issue-83943.stderr @@ -0,0 +1,17 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/issue-83943.rs:7:9 + | +LL | / if true { +LL | | "A".to_string() + | | --------------- expected because of this +LL | | } else { +LL | | "B" + | | ^^^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found `&str` +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-84592.rs b/tests/ui/suggestions/issue-84592.rs new file mode 100644 index 000000000..aa246aaa3 --- /dev/null +++ b/tests/ui/suggestions/issue-84592.rs @@ -0,0 +1,17 @@ +/* Checks whether issue #84592 has been resolved. The issue was + * that in this example, there are two expected/missing lifetime + * parameters with *different spans*, leading to incorrect + * suggestions from rustc. + */ + +struct TwoLifetimes<'x, 'y> { + x: &'x (), + y: &'y (), +} + +fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { +//~^ ERROR missing lifetime specifiers [E0106] + TwoLifetimes { x: &(), y: &() } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-84592.stderr b/tests/ui/suggestions/issue-84592.stderr new file mode 100644 index 000000000..70c96feb1 --- /dev/null +++ b/tests/ui/suggestions/issue-84592.stderr @@ -0,0 +1,17 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/issue-84592.rs:12:57 + | +LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { + | --- --- ^^ ^^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` +help: consider introducing a named lifetime parameter + | +LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> { + | ++++ ++ ++ ~~ ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/issue-84700.rs b/tests/ui/suggestions/issue-84700.rs new file mode 100644 index 000000000..a27169fdb --- /dev/null +++ b/tests/ui/suggestions/issue-84700.rs @@ -0,0 +1,26 @@ +// test for suggestion on fieldless enum variant + +#[derive(PartialEq, Debug)] +enum FarmAnimal { + Worm, + Cow, + Bull, + Chicken { num_eggs: usize }, + Dog (String), +} + +fn what_does_the_animal_say(animal: &FarmAnimal) { + + let noise = match animal { + FarmAnimal::Cow(_) => "moo".to_string(), + //~^ ERROR expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow` + FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), + //~^ ERROR expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken` + FarmAnimal::Dog{..} => "woof!".to_string(), + _ => todo!() + }; + + println!("{:?} says: {:?}", animal, noise); +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-84700.stderr b/tests/ui/suggestions/issue-84700.stderr new file mode 100644 index 000000000..ac9f5ab0b --- /dev/null +++ b/tests/ui/suggestions/issue-84700.stderr @@ -0,0 +1,19 @@ +error[E0532]: expected tuple struct or tuple variant, found unit variant `FarmAnimal::Cow` + --> $DIR/issue-84700.rs:15:9 + | +LL | Cow, + | --- `FarmAnimal::Cow` defined here +... +LL | FarmAnimal::Cow(_) => "moo".to_string(), + | ^^^^^^^^^^^^^^^^^^ help: use this syntax instead: `FarmAnimal::Cow` + +error[E0164]: expected tuple struct or tuple variant, found struct variant `FarmAnimal::Chicken` + --> $DIR/issue-84700.rs:17:9 + | +LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), + | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0164, E0532. +For more information about an error, try `rustc --explain E0164`. diff --git a/tests/ui/suggestions/issue-84973-2.rs b/tests/ui/suggestions/issue-84973-2.rs new file mode 100644 index 000000000..050cf8c64 --- /dev/null +++ b/tests/ui/suggestions/issue-84973-2.rs @@ -0,0 +1,13 @@ +// A slight variation of issue-84973.rs. Here, a mutable borrow is +// required (and the obligation kind is different). + +trait Tr {} +impl Tr for &mut i32 {} + +fn foo(i: T) {} + +fn main() { + let a: i32 = 32; + foo(a); + //~^ ERROR: the trait bound `i32: Tr` is not satisfied [E0277] +} diff --git a/tests/ui/suggestions/issue-84973-2.stderr b/tests/ui/suggestions/issue-84973-2.stderr new file mode 100644 index 000000000..513bf28fb --- /dev/null +++ b/tests/ui/suggestions/issue-84973-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `i32: Tr` is not satisfied + --> $DIR/issue-84973-2.rs:11:9 + | +LL | foo(a); + | --- ^ the trait `Tr` is not implemented for `i32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/issue-84973-2.rs:7:11 + | +LL | fn foo(i: T) {} + | ^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut a); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-84973-blacklist.rs b/tests/ui/suggestions/issue-84973-blacklist.rs new file mode 100644 index 000000000..6813b07a2 --- /dev/null +++ b/tests/ui/suggestions/issue-84973-blacklist.rs @@ -0,0 +1,28 @@ +// Checks that certain traits for which we don't want to suggest borrowing +// are blacklisted and don't cause the suggestion to be issued. + +#![feature(generators)] + +fn f_copy(t: T) {} +fn f_clone(t: T) {} +fn f_unpin(t: T) {} +fn f_sized(t: T) {} +fn f_send(t: T) {} + +struct S; + +fn main() { + f_copy("".to_string()); //~ ERROR: the trait bound `String: Copy` is not satisfied [E0277] + f_clone(S); //~ ERROR: the trait bound `S: Clone` is not satisfied [E0277] + f_unpin(static || { yield; }); + //~^ ERROR: cannot be unpinned [E0277] + + let cl = || (); + let ref_cl: &dyn Fn() -> () = &cl; + f_sized(*ref_cl); + //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277] + + use std::rc::Rc; + let rc = Rc::new(0); + f_send(rc); //~ ERROR: `Rc<{integer}>` cannot be sent between threads safely [E0277] +} diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr new file mode 100644 index 000000000..c20cc8164 --- /dev/null +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -0,0 +1,80 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/issue-84973-blacklist.rs:15:12 + | +LL | f_copy("".to_string()); + | ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f_copy` + --> $DIR/issue-84973-blacklist.rs:6:14 + | +LL | fn f_copy(t: T) {} + | ^^^^ required by this bound in `f_copy` + +error[E0277]: the trait bound `S: Clone` is not satisfied + --> $DIR/issue-84973-blacklist.rs:16:13 + | +LL | f_clone(S); + | ------- ^ the trait `Clone` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `f_clone` + --> $DIR/issue-84973-blacklist.rs:7:15 + | +LL | fn f_clone(t: T) {} + | ^^^^^ required by this bound in `f_clone` +help: consider annotating `S` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned + --> $DIR/issue-84973-blacklist.rs:17:13 + | +LL | f_unpin(static || { yield; }); + | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `f_unpin` + --> $DIR/issue-84973-blacklist.rs:8:15 + | +LL | fn f_unpin(t: T) {} + | ^^^^^ required by this bound in `f_unpin` + +error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time + --> $DIR/issue-84973-blacklist.rs:22:13 + | +LL | f_sized(*ref_cl); + | ------- ^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `dyn Fn()` +note: required by a bound in `f_sized` + --> $DIR/issue-84973-blacklist.rs:9:12 + | +LL | fn f_sized(t: T) {} + | ^ required by this bound in `f_sized` + +error[E0277]: `Rc<{integer}>` cannot be sent between threads safely + --> $DIR/issue-84973-blacklist.rs:27:12 + | +LL | f_send(rc); + | ------ ^^ `Rc<{integer}>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `Rc<{integer}>` +note: required by a bound in `f_send` + --> $DIR/issue-84973-blacklist.rs:10:14 + | +LL | fn f_send(t: T) {} + | ^^^^ required by this bound in `f_send` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-84973-negative.rs b/tests/ui/suggestions/issue-84973-negative.rs new file mode 100644 index 000000000..f339251e5 --- /dev/null +++ b/tests/ui/suggestions/issue-84973-negative.rs @@ -0,0 +1,12 @@ +// Checks that we only suggest borrowing if &T actually implements the trait. + +trait Tr {} +impl Tr for &f32 {} +fn bar(t: T) {} + +fn main() { + let a = 0i32; + let b = 0.0f32; + bar(a); //~ ERROR: the trait bound `i32: Tr` is not satisfied [E0277] + bar(b); //~ ERROR: the trait bound `f32: Tr` is not satisfied [E0277] +} diff --git a/tests/ui/suggestions/issue-84973-negative.stderr b/tests/ui/suggestions/issue-84973-negative.stderr new file mode 100644 index 000000000..ce838bce0 --- /dev/null +++ b/tests/ui/suggestions/issue-84973-negative.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `i32: Tr` is not satisfied + --> $DIR/issue-84973-negative.rs:10:9 + | +LL | bar(a); + | --- ^ the trait `Tr` is not implemented for `i32` + | | + | required by a bound introduced by this call + | + = help: the trait `Tr` is implemented for `&f32` +note: required by a bound in `bar` + --> $DIR/issue-84973-negative.rs:5:11 + | +LL | fn bar(t: T) {} + | ^^ required by this bound in `bar` + +error[E0277]: the trait bound `f32: Tr` is not satisfied + --> $DIR/issue-84973-negative.rs:11:9 + | +LL | bar(b); + | --- ^ the trait `Tr` is not implemented for `f32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/issue-84973-negative.rs:5:11 + | +LL | fn bar(t: T) {} + | ^^ required by this bound in `bar` +help: consider borrowing here + | +LL | bar(&b); + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-84973.rs b/tests/ui/suggestions/issue-84973.rs new file mode 100644 index 000000000..42468478e --- /dev/null +++ b/tests/ui/suggestions/issue-84973.rs @@ -0,0 +1,33 @@ +// Checks whether borrowing is suggested when a trait bound is not satisfied +// for found type `T`, but is for `&/&mut T`. + +fn main() { + let f = Fancy{}; + let o = Other::new(f); + //~^ ERROR: the trait bound `Fancy: SomeTrait` is not satisfied [E0277] +} + +struct Fancy {} + +impl <'a> SomeTrait for &'a Fancy { +} + +trait SomeTrait {} + +struct Other<'a, G> { + a: &'a str, + g: G, +} + +// Broadly copied from https://docs.rs/petgraph/0.5.1/src/petgraph/dot.rs.html#70 +impl<'a, G> Other<'a, G> +where + G: SomeTrait, +{ + pub fn new(g: G) -> Self { + Other { + a: "hi", + g: g, + } + } +} diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr new file mode 100644 index 000000000..ae2bf5aac --- /dev/null +++ b/tests/ui/suggestions/issue-84973.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied + --> $DIR/issue-84973.rs:6:24 + | +LL | let o = Other::new(f); + | ---------- ^ the trait `SomeTrait` is not implemented for `Fancy` + | | + | required by a bound introduced by this call + | +note: required by a bound in `Other::<'a, G>::new` + --> $DIR/issue-84973.rs:25:8 + | +LL | G: SomeTrait, + | ^^^^^^^^^ required by this bound in `Other::<'a, G>::new` +LL | { +LL | pub fn new(g: G) -> Self { + | --- required by a bound in this +help: consider borrowing here + | +LL | let o = Other::new(&f); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-85347.rs b/tests/ui/suggestions/issue-85347.rs new file mode 100644 index 000000000..02b5fb618 --- /dev/null +++ b/tests/ui/suggestions/issue-85347.rs @@ -0,0 +1,9 @@ +use std::ops::Deref; +trait Foo { + type Bar<'a>: Deref::Bar>; + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + //~| ERROR associated type bindings are not allowed here + //~| HELP add missing +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr new file mode 100644 index 000000000..17c1b7dc4 --- /dev/null +++ b/tests/ui/suggestions/issue-85347.stderr @@ -0,0 +1,26 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/issue-85347.rs:3:42 + | +LL | type Bar<'a>: Deref::Bar>; + | ^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-85347.rs:3:10 + | +LL | type Bar<'a>: Deref::Bar>; + | ^^^ -- +help: add missing lifetime argument + | +LL | type Bar<'a>: Deref::Bar<'a, Target = Self>>; + | +++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-85347.rs:3:46 + | +LL | type Bar<'a>: Deref::Bar>; + | ^^^^^^^^^^^^^ associated type not allowed here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0229. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs new file mode 100644 index 000000000..390d8bbdd --- /dev/null +++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs @@ -0,0 +1,9 @@ +// Regression test for #85943: should not emit suggestions for adding +// indirection to type parameters in where-clauses when suggesting +// adding `?Sized`. +struct A(T) where T: Send; +struct B(A<[u8]>); +//~^ ERROR the size for values of type + +pub fn main() { +} diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr new file mode 100644 index 000000000..752533cdc --- /dev/null +++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr @@ -0,0 +1,23 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:5:10 + | +LL | struct B(A<[u8]>); + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `A` + --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 + | +LL | struct A(T) where T: Send; + | ^ required by this bound in `A` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 + | +LL | struct A(T) where T: Send; + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `T: ?Sized`... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs new file mode 100644 index 000000000..1a36f6e8e --- /dev/null +++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs @@ -0,0 +1,8 @@ +// Regression test for #85945: Don't suggest `?Sized` bound if an explicit +// `Sized` bound is already in a `where` clause. +fn foo(_: &T) where T: Sized {} +fn bar() { foo(""); } +//~^ ERROR the size for values of type + +pub fn main() { +} diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr new file mode 100644 index 000000000..92be9f764 --- /dev/null +++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr @@ -0,0 +1,18 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16 + | +LL | fn bar() { foo(""); } + | --- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `foo` + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8 + | +LL | fn foo(_: &T) where T: Sized {} + | ^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-86100-tuple-paren-comma.rs b/tests/ui/suggestions/issue-86100-tuple-paren-comma.rs new file mode 100644 index 000000000..fa9d1a889 --- /dev/null +++ b/tests/ui/suggestions/issue-86100-tuple-paren-comma.rs @@ -0,0 +1,25 @@ +// Tests that a suggestion is issued for type mismatch errors when a +// 1-tuple is expected and a parenthesized expression of non-tuple +// type is supplied. + +fn foo(_t: (T,)) {} +struct S { _s: (String,) } + +fn main() { + let _x: (i32,) = (5); + //~^ ERROR: mismatched types [E0308] + //~| HELP: use a trailing comma to create a tuple with one element + + foo((Some(3))); + //~^ ERROR: mismatched types [E0308] + //~| HELP: use a trailing comma to create a tuple with one element + + let _s = S { _s: ("abc".to_string()) }; + //~^ ERROR: mismatched types [E0308] + //~| HELP: use a trailing comma to create a tuple with one element + + // Do not issue the suggestion if the found type is already a tuple. + let t = (1, 2); + let _x: (i32,) = (t); + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr new file mode 100644 index 000000000..8c9a41a20 --- /dev/null +++ b/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr @@ -0,0 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:9:22 + | +LL | let _x: (i32,) = (5); + | ------ ^^^ expected tuple, found integer + | | + | expected due to this + | + = note: expected tuple `(i32,)` + found type `{integer}` +help: use a trailing comma to create a tuple with one element + | +LL | let _x: (i32,) = (5,); + | + + +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:13:9 + | +LL | foo((Some(3))); + | --- ^^^^^^^^^ expected tuple, found enum `Option` + | | + | arguments to this function are incorrect + | + = note: expected tuple `(_,)` + found enum `Option<{integer}>` +note: function defined here + --> $DIR/issue-86100-tuple-paren-comma.rs:5:4 + | +LL | fn foo(_t: (T,)) {} + | ^^^ -------- +help: use a trailing comma to create a tuple with one element + | +LL | foo((Some(3),)); + | + + +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:17:22 + | +LL | let _s = S { _s: ("abc".to_string()) }; + | ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String` + | + = note: expected tuple `(String,)` + found struct `String` +help: use a trailing comma to create a tuple with one element + | +LL | let _s = S { _s: ("abc".to_string(),) }; + | + + +error[E0308]: mismatched types + --> $DIR/issue-86100-tuple-paren-comma.rs:23:22 + | +LL | let _x: (i32,) = (t); + | ------ ^^^ expected a tuple with 1 element, found one with 2 elements + | | + | expected due to this + | + = note: expected tuple `(i32,)` + found tuple `({integer}, {integer})` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs new file mode 100644 index 000000000..366787df1 --- /dev/null +++ b/tests/ui/suggestions/issue-86667.rs @@ -0,0 +1,17 @@ +// Regression test for #86667, where a garbled suggestion was issued for +// a missing named lifetime parameter. + +// compile-flags: --edition 2018 + +async fn a(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +//~^ ERROR: lifetime may not live long enough +} + +fn b(s1: &str, s2: &str) -> &str { +//~^ ERROR: missing lifetime specifier [E0106] + s1 +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-86667.stderr b/tests/ui/suggestions/issue-86667.stderr new file mode 100644 index 000000000..8d6116416 --- /dev/null +++ b/tests/ui/suggestions/issue-86667.stderr @@ -0,0 +1,36 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:6:35 + | +LL | async fn a(s1: &str, s2: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ++++ ++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-86667.rs:12:29 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `s1` or `s2` +help: consider introducing a named lifetime parameter + | +LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { + | ++++ ++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/issue-86667.rs:8:5 + | +LL | async fn a(s1: &str, s2: &str) -> &str { + | - let's call the lifetime of this reference `'1` +LL | +LL | s1 + | ^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/issue-88730.rs b/tests/ui/suggestions/issue-88730.rs new file mode 100644 index 000000000..d161ed284 --- /dev/null +++ b/tests/ui/suggestions/issue-88730.rs @@ -0,0 +1,15 @@ +#![allow(unused, nonstandard_style)] + +// If an enum has two different variants, +// then it cannot be matched upon in a function argument. +// It still gets an error, but no suggestions. +enum Foo { + C, + D, +} + +fn foo(C: Foo) {} //~ERROR + +fn main() { + let C = Foo::D; //~ERROR +} diff --git a/tests/ui/suggestions/issue-88730.stderr b/tests/ui/suggestions/issue-88730.stderr new file mode 100644 index 000000000..0bd1b7ba4 --- /dev/null +++ b/tests/ui/suggestions/issue-88730.stderr @@ -0,0 +1,17 @@ +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:11:8 + | +LL | fn foo(C: Foo) {} + | ^ + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `C` is named the same as one of the variants of the type `Foo` + --> $DIR/issue-88730.rs:14:9 + | +LL | let C = Foo::D; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0170`. diff --git a/tests/ui/suggestions/issue-89064.rs b/tests/ui/suggestions/issue-89064.rs new file mode 100644 index 000000000..fa5fc899d --- /dev/null +++ b/tests/ui/suggestions/issue-89064.rs @@ -0,0 +1,35 @@ +use std::convert::TryInto; + +trait A { + fn foo() {} +} + +trait B { + fn bar() {} +} + +struct S; + +impl A for S {} +impl B for S {} + +fn main() { + let _ = A::foo::(); + //~^ ERROR + //~| HELP remove these generics + //~| HELP consider moving this generic argument + + let _ = B::bar::(); + //~^ ERROR + //~| HELP remove these generics + //~| HELP consider moving these generic arguments + + let _ = A::::foo::(); + //~^ ERROR + //~| HELP remove these generics + + let _ = 42.into::>(); + //~^ ERROR + //~| HELP remove these generics + //~| HELP consider moving this generic argument +} diff --git a/tests/ui/suggestions/issue-89064.stderr b/tests/ui/suggestions/issue-89064.stderr new file mode 100644 index 000000000..93d8da226 --- /dev/null +++ b/tests/ui/suggestions/issue-89064.stderr @@ -0,0 +1,77 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-89064.rs:17:16 + | +LL | let _ = A::foo::(); + | ^^^ expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-89064.rs:4:8 + | +LL | fn foo() {} + | ^^^ +help: consider moving this generic argument to the `A` trait, which takes up to 1 argument + | +LL - let _ = A::foo::(); +LL + let _ = A::::foo(); + | +help: remove these generics + | +LL - let _ = A::foo::(); +LL + let _ = A::foo(); + | + +error[E0107]: this associated function takes 0 generic arguments but 2 generic arguments were supplied + --> $DIR/issue-89064.rs:22:16 + | +LL | let _ = B::bar::(); + | ^^^ expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-89064.rs:8:8 + | +LL | fn bar() {} + | ^^^ +help: consider moving these generic arguments to the `B` trait, which takes up to 2 arguments + | +LL - let _ = B::bar::(); +LL + let _ = B::::bar(); + | +help: remove these generics + | +LL - let _ = B::bar::(); +LL + let _ = B::bar(); + | + +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-89064.rs:27:21 + | +LL | let _ = A::::foo::(); + | ^^^----- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-89064.rs:4:8 + | +LL | fn foo() {} + | ^^^ + +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-89064.rs:31:16 + | +LL | let _ = 42.into::>(); + | ^^^^ expected 0 generic arguments + | +help: consider moving this generic argument to the `Into` trait, which takes up to 1 argument + | +LL | let _ = Into::>::into(42); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: remove these generics + | +LL - let _ = 42.into::>(); +LL + let _ = 42.into(); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/issue-89333.rs b/tests/ui/suggestions/issue-89333.rs new file mode 100644 index 000000000..03ed28ede --- /dev/null +++ b/tests/ui/suggestions/issue-89333.rs @@ -0,0 +1,11 @@ +// check-fail +// Ensure we don't error when emitting trait bound not satisfied when self type +// has late bound var + +fn main() { + test(&|| 0); //~ ERROR the trait bound +} + +trait Trait {} + +fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} diff --git a/tests/ui/suggestions/issue-89333.stderr b/tests/ui/suggestions/issue-89333.stderr new file mode 100644 index 000000000..f73f1147d --- /dev/null +++ b/tests/ui/suggestions/issue-89333.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied + --> $DIR/issue-89333.rs:6:5 + | +LL | test(&|| 0); + | ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` + | +note: required by a bound in `test` + --> $DIR/issue-89333.rs:11:55 + | +LL | fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Trait {} + | ^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs new file mode 100644 index 000000000..1e36b2fab --- /dev/null +++ b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs @@ -0,0 +1,13 @@ +// Checks that we do not ICE when comparing `Self` to `Pin` +// edition:2021 + +struct S; + +impl S { + fn foo(_: Box>) {} + fn bar() { + Self::foo(None) //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr new file mode 100644 index 000000000..611f7d5dd --- /dev/null +++ b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19 + | +LL | Self::foo(None) + | --------- ^^^^ expected struct `Box`, found enum `Option` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box>` + found enum `Option<_>` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +note: associated function defined here + --> $DIR/issue-90213-expected-boxfuture-self-ice.rs:7:8 + | +LL | fn foo(_: Box>) {} + | ^^^ ----------------- +help: store this in the heap by calling `Box::new` + | +LL | Self::foo(Box::new(None)) + | +++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-90974.rs b/tests/ui/suggestions/issue-90974.rs new file mode 100644 index 000000000..83590dbf7 --- /dev/null +++ b/tests/ui/suggestions/issue-90974.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", (3.).recip()); //~ERROR +} diff --git a/tests/ui/suggestions/issue-90974.stderr b/tests/ui/suggestions/issue-90974.stderr new file mode 100644 index 000000000..e1fb479a3 --- /dev/null +++ b/tests/ui/suggestions/issue-90974.stderr @@ -0,0 +1,14 @@ +error[E0689]: can't call method `recip` on ambiguous numeric type `{float}` + --> $DIR/issue-90974.rs:2:25 + | +LL | println!("{}", (3.).recip()); + | ^^^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | println!("{}", (3_f32).recip()); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0689`. diff --git a/tests/ui/suggestions/issue-96223.rs b/tests/ui/suggestions/issue-96223.rs new file mode 100644 index 000000000..85667bb84 --- /dev/null +++ b/tests/ui/suggestions/issue-96223.rs @@ -0,0 +1,52 @@ +// Previously ICEd because we didn't properly track binders in suggestions +// check-fail + +pub trait Foo<'de>: Sized {} + +pub trait Bar<'a>: 'static { + type Inner: 'a; +} + +pub trait Fubar { + type Bar: for<'a> Bar<'a>; +} + +pub struct Baz(pub T); + +impl<'de, T> Foo<'de> for Baz where T: Foo<'de> {} + +struct Empty; + +impl Dummy for Empty +where + M: Fubar, + for<'de> Baz<>::Inner>: Foo<'de>, +{ +} + +pub trait Dummy +where + M: Fubar, +{ +} + +pub struct EmptyBis<'a>(&'a [u8]); + +impl<'a> Bar<'a> for EmptyBis<'static> { + type Inner = EmptyBis<'a>; +} + +pub struct EmptyMarker; + +impl Fubar for EmptyMarker { + type Bar = EmptyBis<'static>; +} + +fn icey_bounds>(p: &D) {} + +fn trigger_ice() { + let p = Empty; + icey_bounds(&p); //~ERROR the trait bound +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-96223.stderr b/tests/ui/suggestions/issue-96223.stderr new file mode 100644 index 000000000..d4e9433df --- /dev/null +++ b/tests/ui/suggestions/issue-96223.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied + --> $DIR/issue-96223.rs:49:17 + | +LL | icey_bounds(&p); + | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>` + | | + | required by a bound introduced by this call + | + = help: the trait `Foo<'de>` is implemented for `Baz` +note: required for `Baz>` to implement `for<'de> Foo<'de>` + --> $DIR/issue-96223.rs:16:14 + | +LL | impl<'de, T> Foo<'de> for Baz where T: Foo<'de> {} + | ^^^^^^^^ ^^^^^^ -------- unsatisfied trait bound introduced here +note: required for `Empty` to implement `Dummy` + --> $DIR/issue-96223.rs:20:9 + | +LL | impl Dummy for Empty + | ^^^^^^^^ ^^^^^ +... +LL | for<'de> Baz<>::Inner>: Foo<'de>, + | -------- unsatisfied trait bound introduced here +note: required by a bound in `icey_bounds` + --> $DIR/issue-96223.rs:45:19 + | +LL | fn icey_bounds>(p: &D) {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `icey_bounds` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-96555.rs b/tests/ui/suggestions/issue-96555.rs new file mode 100644 index 000000000..9f0a047c6 --- /dev/null +++ b/tests/ui/suggestions/issue-96555.rs @@ -0,0 +1,19 @@ +// edition:2018 + +async fn f() { + m::f1().await; //~ ERROR `()` is not a future + m::f2().await; //~ ERROR `()` is not a future + m::f3().await; //~ ERROR `()` is not a future +} + +mod m { + pub fn f1() {} + + pub(crate) fn f2() {} + + pub + fn + f3() {} +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-96555.stderr b/tests/ui/suggestions/issue-96555.stderr new file mode 100644 index 000000000..9a8a183dc --- /dev/null +++ b/tests/ui/suggestions/issue-96555.stderr @@ -0,0 +1,66 @@ +error[E0277]: `()` is not a future + --> $DIR/issue-96555.rs:4:12 + | +LL | m::f1().await; + | -------^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - m::f1().await; +LL + m::f1(); + | +help: alternatively, consider making `fn f1` asynchronous + | +LL | pub async fn f1() {} + | +++++ + +error[E0277]: `()` is not a future + --> $DIR/issue-96555.rs:5:12 + | +LL | m::f2().await; + | -------^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - m::f2().await; +LL + m::f2(); + | +help: alternatively, consider making `fn f2` asynchronous + | +LL | pub(crate) async fn f2() {} + | +++++ + +error[E0277]: `()` is not a future + --> $DIR/issue-96555.rs:6:12 + | +LL | m::f3().await; + | -------^^^^^^ `()` is not a future + | | + | this call returns `()` + | + = help: the trait `Future` is not implemented for `()` + = note: () must be a future or must implement `IntoFuture` to be awaited + = note: required for `()` to implement `IntoFuture` +help: remove the `.await` + | +LL - m::f3().await; +LL + m::f3(); + | +help: alternatively, consider making `fn f3` asynchronous + | +LL | pub async + | +++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-97677.fixed b/tests/ui/suggestions/issue-97677.fixed new file mode 100644 index 000000000..1e7569fa4 --- /dev/null +++ b/tests/ui/suggestions/issue-97677.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn add_ten>(n: N) -> N { + n + 10 + //~^ ERROR cannot add `{integer}` to `N` +} + +fn main() { add_ten(0); } diff --git a/tests/ui/suggestions/issue-97677.rs b/tests/ui/suggestions/issue-97677.rs new file mode 100644 index 000000000..2abf2af33 --- /dev/null +++ b/tests/ui/suggestions/issue-97677.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn add_ten(n: N) -> N { + n + 10 + //~^ ERROR cannot add `{integer}` to `N` +} + +fn main() { add_ten(0); } diff --git a/tests/ui/suggestions/issue-97677.stderr b/tests/ui/suggestions/issue-97677.stderr new file mode 100644 index 000000000..575d79267 --- /dev/null +++ b/tests/ui/suggestions/issue-97677.stderr @@ -0,0 +1,16 @@ +error[E0369]: cannot add `{integer}` to `N` + --> $DIR/issue-97677.rs:4:7 + | +LL | n + 10 + | - ^ -- {integer} + | | + | N + | +help: consider restricting type parameter `N` + | +LL | fn add_ten>(n: N) -> N { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/suggestions/issue-97704.fixed b/tests/ui/suggestions/issue-97704.fixed new file mode 100644 index 000000000..c42bdfff5 --- /dev/null +++ b/tests/ui/suggestions/issue-97704.fixed @@ -0,0 +1,19 @@ +// edition:2021 +// run-rustfix + +#![allow(unused)] + +use std::future::Future; + +async fn foo() -> Result<(), i32> { + func(async { Ok::<_, i32>(()) }).await?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + + Ok(()) +} + +async fn func(fut: impl Future) -> T { + fut.await +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-97704.rs b/tests/ui/suggestions/issue-97704.rs new file mode 100644 index 000000000..5dfee6cac --- /dev/null +++ b/tests/ui/suggestions/issue-97704.rs @@ -0,0 +1,19 @@ +// edition:2021 +// run-rustfix + +#![allow(unused)] + +use std::future::Future; + +async fn foo() -> Result<(), i32> { + func(async { Ok::<_, i32>(()) })?; + //~^ ERROR the `?` operator can only be applied to values that implement `Try` + + Ok(()) +} + +async fn func(fut: impl Future) -> T { + fut.await +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-97704.stderr b/tests/ui/suggestions/issue-97704.stderr new file mode 100644 index 000000000..ca017be45 --- /dev/null +++ b/tests/ui/suggestions/issue-97704.stderr @@ -0,0 +1,15 @@ +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/issue-97704.rs:9:5 + | +LL | func(async { Ok::<_, i32>(()) })?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future>` + | + = help: the trait `Try` is not implemented for `impl Future>` +help: consider `await`ing on the `Future` + | +LL | func(async { Ok::<_, i32>(()) }).await?; + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-97760.rs b/tests/ui/suggestions/issue-97760.rs new file mode 100644 index 000000000..cf9c3c58d --- /dev/null +++ b/tests/ui/suggestions/issue-97760.rs @@ -0,0 +1,9 @@ +pub fn print_values(values: &impl IntoIterator) +where { + for x in values.into_iter() { + println!("{x}"); + //~^ ERROR ::Item` doesn't implement `std::fmt::Display + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-97760.stderr b/tests/ui/suggestions/issue-97760.stderr new file mode 100644 index 000000000..bbcc3693f --- /dev/null +++ b/tests/ui/suggestions/issue-97760.stderr @@ -0,0 +1,18 @@ +error[E0277]: `::Item` doesn't implement `std::fmt::Display` + --> $DIR/issue-97760.rs:4:20 + | +LL | println!("{x}"); + | ^ `::Item` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `::Item` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: introduce a type parameter with a trait bound instead of using `impl Trait` + | +LL ~ pub fn print_values(values: &I) +LL ~ where ::Item: std::fmt::Display { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-98500.rs b/tests/ui/suggestions/issue-98500.rs new file mode 100644 index 000000000..a2717fd92 --- /dev/null +++ b/tests/ui/suggestions/issue-98500.rs @@ -0,0 +1,14 @@ +// aux-build:not-object-safe.rs + +extern crate not_object_safe; + +pub trait B where + Self: not_object_safe::A, +{ + fn f2(&self); +} + +struct S(Box); +//~^ ERROR the trait `B` cannot be made into an object + +fn main() {} diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr new file mode 100644 index 000000000..e7251d735 --- /dev/null +++ b/tests/ui/suggestions/issue-98500.stderr @@ -0,0 +1,24 @@ +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/issue-98500.rs:11:14 + | +LL | struct S(Box); + | ^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/auxiliary/not-object-safe.rs:4:8 + | +LL | fn f(); + | ^ ...because associated function `f` has no `self` parameter +LL | fn f2(self: &Arc); + | ^^ ...because method `f2`'s `self` parameter cannot be dispatched on + | + ::: $DIR/issue-98500.rs:5:11 + | +LL | pub trait B where + | - this trait cannot be made into an object... + = help: consider moving `f` to another trait + = help: consider moving `f2` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/issue-99080.rs b/tests/ui/suggestions/issue-99080.rs new file mode 100644 index 000000000..91f574f35 --- /dev/null +++ b/tests/ui/suggestions/issue-99080.rs @@ -0,0 +1,16 @@ +// aux-build:meow.rs + +extern crate meow; + +use meow::Meow; + +fn needs_meow(t: T) {} + +fn main() { + needs_meow(1usize); + //~^ ERROR the trait bound `usize: Meow` is not satisfied +} + +struct LocalMeow; + +impl Meow for LocalMeow {} diff --git a/tests/ui/suggestions/issue-99080.stderr b/tests/ui/suggestions/issue-99080.stderr new file mode 100644 index 000000000..d1908dd9d --- /dev/null +++ b/tests/ui/suggestions/issue-99080.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `usize: Meow` is not satisfied + --> $DIR/issue-99080.rs:10:16 + | +LL | needs_meow(1usize); + | ---------- ^^^^^^ the trait `Meow` is not implemented for `usize` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Meow`: + GlobalMeow + LocalMeow +note: required by a bound in `needs_meow` + --> $DIR/issue-99080.rs:7:18 + | +LL | fn needs_meow(t: T) {} + | ^^^^ required by this bound in `needs_meow` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/issue-99240-2.rs b/tests/ui/suggestions/issue-99240-2.rs new file mode 100644 index 000000000..0a418b5ae --- /dev/null +++ b/tests/ui/suggestions/issue-99240-2.rs @@ -0,0 +1,10 @@ +enum Enum { + Unit, +} +type Alias = Enum; + +fn main() { + Alias:: + Unit(); + //~^^ ERROR expected function, found enum variant `Alias::Unit` +} diff --git a/tests/ui/suggestions/issue-99240-2.stderr b/tests/ui/suggestions/issue-99240-2.stderr new file mode 100644 index 000000000..a2b559784 --- /dev/null +++ b/tests/ui/suggestions/issue-99240-2.stderr @@ -0,0 +1,21 @@ +error[E0618]: expected function, found enum variant `Alias::Unit` + --> $DIR/issue-99240-2.rs:7:5 + | +LL | Unit, + | ---- enum variant `Alias::Unit` defined here +... +LL | // Alias:: +LL | || Unit(); + | ||________^_- call expression requires function + | |________| + | + | +help: `Alias::Unit` is a unit enum variant, and does not take parentheses to be constructed + | +LL - Unit(); +LL + Unit; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/issue-99240.rs b/tests/ui/suggestions/issue-99240.rs new file mode 100644 index 000000000..2115a4266 --- /dev/null +++ b/tests/ui/suggestions/issue-99240.rs @@ -0,0 +1,6 @@ +fn fmt(it: &(std::cell::Cell>,)) { + (it.0.take())() + //~^ ERROR expected function +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-99240.stderr b/tests/ui/suggestions/issue-99240.stderr new file mode 100644 index 000000000..f1bea688b --- /dev/null +++ b/tests/ui/suggestions/issue-99240.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `Option` + --> $DIR/issue-99240.rs:2:5 + | +LL | (it.0.take())() + | ^^^^^^^^^^^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs new file mode 100644 index 000000000..b24d25648 --- /dev/null +++ b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.rs @@ -0,0 +1,5 @@ +fn main() { + if 1 == = 1 { //~ ERROR expected expression + println!("yup!"); + } +} diff --git a/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr new file mode 100644 index 000000000..6adefe3de --- /dev/null +++ b/tests/ui/suggestions/js-style-comparison-op-separate-eq-token.stderr @@ -0,0 +1,8 @@ +error: expected expression, found `=` + --> $DIR/js-style-comparison-op-separate-eq-token.rs:2:13 + | +LL | if 1 == = 1 { + | ^ expected expression + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/js-style-comparison-op.fixed b/tests/ui/suggestions/js-style-comparison-op.fixed new file mode 100644 index 000000000..f7e977b91 --- /dev/null +++ b/tests/ui/suggestions/js-style-comparison-op.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + if 1 == 1 { //~ ERROR invalid comparison operator `===` + println!("yup!"); + } else if 1 != 1 { //~ ERROR invalid comparison operator `!==` + println!("nope!"); + } +} diff --git a/tests/ui/suggestions/js-style-comparison-op.rs b/tests/ui/suggestions/js-style-comparison-op.rs new file mode 100644 index 000000000..c89c1052e --- /dev/null +++ b/tests/ui/suggestions/js-style-comparison-op.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + if 1 === 1 { //~ ERROR invalid comparison operator `===` + println!("yup!"); + } else if 1 !== 1 { //~ ERROR invalid comparison operator `!==` + println!("nope!"); + } +} diff --git a/tests/ui/suggestions/js-style-comparison-op.stderr b/tests/ui/suggestions/js-style-comparison-op.stderr new file mode 100644 index 000000000..33f7a0844 --- /dev/null +++ b/tests/ui/suggestions/js-style-comparison-op.stderr @@ -0,0 +1,14 @@ +error: invalid comparison operator `===` + --> $DIR/js-style-comparison-op.rs:3:10 + | +LL | if 1 === 1 { + | ^^^ help: `===` is not a valid comparison operator, use `==` + +error: invalid comparison operator `!==` + --> $DIR/js-style-comparison-op.rs:5:17 + | +LL | } else if 1 !== 1 { + | ^^^ help: `!==` is not a valid comparison operator, use `!=` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs new file mode 100644 index 000000000..06ee421fc --- /dev/null +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs @@ -0,0 +1,11 @@ +pub fn foo(num: i32) -> i32 { + let foo: i32::from_be(num); + //~^ ERROR expected type, found local variable `num` + //~| ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR ambiguous associated type + foo +} + +fn main() { + let _ = foo(42); +} diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr new file mode 100644 index 000000000..b90ae051f --- /dev/null +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr @@ -0,0 +1,34 @@ +error[E0573]: expected type, found local variable `num` + --> $DIR/let-binding-init-expr-as-ty.rs:2:27 + | +LL | let foo: i32::from_be(num); + | -- ^^^ not a type + | | + | help: use `=` if you meant to assign + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/let-binding-init-expr-as-ty.rs:2:19 + | +LL | let foo: i32::from_be(num); + | ^^^^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | let foo: i32::from_be; + | ~ ~ + +error[E0223]: ambiguous associated type + --> $DIR/let-binding-init-expr-as-ty.rs:2:14 + | +LL | let foo: i32::from_be(num); + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path + | +LL | let foo: ::from_be; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0214, E0223, E0573. +For more information about an error, try `rustc --explain E0214`. diff --git a/tests/ui/suggestions/lifetimes/issue-105544.fixed b/tests/ui/suggestions/lifetimes/issue-105544.fixed new file mode 100644 index 000000000..47087eb47 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/issue-105544.fixed @@ -0,0 +1,45 @@ +// run-rustfix + +#![allow(warnings)] + +fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `impl Sized` may not live long enough + //~| NOTE ...so that the type `impl Sized` will meet its required lifetime bounds +} + +fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ { +//~^ HELP consider adding an explicit lifetime bound... + (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds + //~^ ERROR the parameter type `impl Sized` may not live long enough +} + +fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough + //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds +} + +fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `T` may not live long enough + //~| NOTE ...so that the type `T` will meet its required lifetime bounds +} + +fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { +//~^ HELP consider adding an explicit lifetime bound... + (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds + //~^ ERROR the parameter type `T` may not live long enough +} + +fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `T` may not live long enough + //~| NOTE ...so that the type `T` will meet its required lifetime bounds +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/issue-105544.rs b/tests/ui/suggestions/lifetimes/issue-105544.rs new file mode 100644 index 000000000..bd3bc1ef9 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/issue-105544.rs @@ -0,0 +1,45 @@ +// run-rustfix + +#![allow(warnings)] + +fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `impl Sized` may not live long enough + //~| NOTE ...so that the type `impl Sized` will meet its required lifetime bounds +} + +fn foo1<'b>(d: impl Sized, p: &'b mut ()) -> impl Sized + '_ { +//~^ HELP consider adding an explicit lifetime bound... + (d, p) //~ NOTE ...so that the type `impl Sized` will meet its required lifetime bounds + //~^ ERROR the parameter type `impl Sized` may not live long enough +} + +fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `impl Sized + 'a` may not live long enough + //~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds +} + +fn bar(d: T, p: & mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `T` may not live long enough + //~| NOTE ...so that the type `T` will meet its required lifetime bounds +} + +fn bar1<'b, T : Sized>(d: T, p: &'b mut ()) -> impl Sized + '_ { +//~^ HELP consider adding an explicit lifetime bound... + (d, p) //~ NOTE ...so that the type `T` will meet its required lifetime bounds + //~^ ERROR the parameter type `T` may not live long enough +} + +fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here... +//~^ HELP consider adding an explicit lifetime bound + (d, p) + //~^ ERROR the parameter type `T` may not live long enough + //~| NOTE ...so that the type `T` will meet its required lifetime bounds +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/issue-105544.stderr b/tests/ui/suggestions/lifetimes/issue-105544.stderr new file mode 100644 index 000000000..08fe21b11 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/issue-105544.stderr @@ -0,0 +1,110 @@ +error[E0311]: the parameter type `impl Sized` may not live long enough + --> $DIR/issue-105544.rs:7:5 + | +LL | (d, p) + | ^^^^^^ + | +note: the parameter type `impl Sized` must be valid for the anonymous lifetime defined here... + --> $DIR/issue-105544.rs:5:26 + | +LL | fn foo(d: impl Sized, p: &mut ()) -> impl Sized + '_ { + | ^^^^^^^ +note: ...so that the type `impl Sized` will meet its required lifetime bounds + --> $DIR/issue-105544.rs:7:5 + | +LL | (d, p) + | ^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { + | ++++ ++++ ++ + +error[E0309]: the parameter type `impl Sized` may not live long enough + --> $DIR/issue-105544.rs:14:5 + | +LL | (d, p) + | ^^^^^^ ...so that the type `impl Sized` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ { + | ++++ + +error[E0311]: the parameter type `impl Sized + 'a` may not live long enough + --> $DIR/issue-105544.rs:20:5 + | +LL | (d, p) + | ^^^^^^ + | +note: the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here... + --> $DIR/issue-105544.rs:18:36 + | +LL | fn foo2<'a>(d: impl Sized + 'a, p: &mut ()) -> impl Sized + '_ { + | ^^^^^^^ +note: ...so that the type `impl Sized + 'a` will meet its required lifetime bounds + --> $DIR/issue-105544.rs:20:5 + | +LL | (d, p) + | ^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { + | +++ ++++ ++ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/issue-105544.rs:27:5 + | +LL | (d, p) + | ^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/issue-105544.rs:25:28 + | +LL | fn bar(d: T, p: & mut ()) -> impl Sized + '_ { + | ^^^^^^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/issue-105544.rs:27:5 + | +LL | (d, p) + | ^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { + | +++ ++++ ++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-105544.rs:34:5 + | +LL | (d, p) + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { + | ++++ + +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/issue-105544.rs:40:5 + | +LL | (d, p) + | ^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/issue-105544.rs:38:38 + | +LL | fn bar2<'a, T : Sized + 'a>(d: T, p: &mut ()) -> impl Sized + '_ { + | ^^^^^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/issue-105544.rs:40:5 + | +LL | (d, p) + | ^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { + | +++ ++++ ++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0309, E0311. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed new file mode 100644 index 000000000..4013d98c3 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.fixed @@ -0,0 +1,29 @@ +// Regression test for #81650 +// run-rustfix + +#![allow(warnings)] + +struct Foo<'a> { + x: &'a mut &'a i32, +} + +impl<'a> Foo<'a> { + fn bar(&self, f: F) + where + F: FnOnce(&Foo<'a>) -> T, + F: 'a, + {} +} + +trait Test { + fn test(&self); +} + +fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) { + foo.bar(move |_| { + //~^ ERROR the parameter type `T` may not live long enough + t.test(); + }); +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs new file mode 100644 index 000000000..4096d95e5 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.rs @@ -0,0 +1,29 @@ +// Regression test for #81650 +// run-rustfix + +#![allow(warnings)] + +struct Foo<'a> { + x: &'a mut &'a i32, +} + +impl<'a> Foo<'a> { + fn bar(&self, f: F) + where + F: FnOnce(&Foo<'a>) -> T, + F: 'a, + {} +} + +trait Test { + fn test(&self); +} + +fn func(foo: &Foo, t: T) { + foo.bar(move |_| { + //~^ ERROR the parameter type `T` may not live long enough + t.test(); + }); +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr new file mode 100644 index 000000000..936d87f79 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -0,0 +1,30 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/missing-lifetimes-in-signature-2.rs:23:5 + | +LL | / foo.bar(move |_| { +LL | | +LL | | t.test(); +LL | | }); + | |______^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature-2.rs:22:24 + | +LL | fn func(foo: &Foo, t: T) { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature-2.rs:23:5 + | +LL | / foo.bar(move |_| { +LL | | +LL | | t.test(); +LL | | }); + | |______^ +help: consider adding an explicit lifetime bound... + | +LL | fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) { + | +++ ++++ ++ ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed new file mode 100644 index 000000000..3c06f4f88 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.fixed @@ -0,0 +1,10 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/95616 + +fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { //~ERROR [E0106] + return ""; +} + +fn main() { + buggy_const(&Some([69,69,69,69,0]), "test"); +} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs new file mode 100644 index 000000000..110468cbb --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.rs @@ -0,0 +1,10 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/95616 + +fn buggy_const(_a: &Option<[u8; N]>, _f: &str) -> &str { //~ERROR [E0106] + return ""; +} + +fn main() { + buggy_const(&Some([69,69,69,69,0]), "test"); +} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr new file mode 100644 index 000000000..7b126c90e --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature-before-const.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetimes-in-signature-before-const.rs:4:67 + | +LL | fn buggy_const(_a: &Option<[u8; N]>, _f: &str) -> &str { + | ---------------- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_a` or `_f` +help: consider introducing a named lifetime parameter + | +LL | fn buggy_const<'a, const N: usize>(_a: &'a Option<[u8; N]>, _f: &'a str) -> &'a str { + | +++ ++ ++ ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs new file mode 100644 index 000000000..b641f5941 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -0,0 +1,111 @@ +pub trait Get { + fn get(self) -> T; +} + +struct Foo { + x: usize, +} + +impl Get for Foo { + fn get(self) -> usize { + self.x + } +} + +fn foo(g: G, dest: &mut T) -> impl FnOnce() +where + G: Get, +{ + move || { + //~^ ERROR hidden type for `impl FnOnce()` captures lifetime + *dest = g.get(); + } +} + +// After applying suggestion for `foo`: +fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +where + G: Get, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } +} + +// After applying suggestion for `bar`: +fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ +//~^ ERROR undeclared lifetime name `'a` +where + G: Get, +{ + move || { + *dest = g.get(); + } +} + +// After applying suggestion for `baz`: +fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +where + G: Get, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } +} + +// Same as above, but show that we pay attention to lifetime names from parent item +impl<'a> Foo { + fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } + } +} + +// After applying suggestion for `qux`: +fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +where + G: Get, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + //~| ERROR explicit lifetime required + *dest = g.get(); + } +} + +// Potential incorrect attempt: +fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +where + G: Get, +{ + move || { + //~^ ERROR the parameter type `G` may not live long enough + *dest = g.get(); + } +} + +// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure: +fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +where + G: Get, +{ + move || { + *dest = g.get(); + } +} + +// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: +fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +where + G: Get, +{ + move || { + *dest = g.get(); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr new file mode 100644 index 000000000..c5c3f7b46 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -0,0 +1,168 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetimes-in-signature.rs:37:11 + | +LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds + --> $DIR/missing-lifetimes-in-signature.rs:19:5 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here +... +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ++++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:30:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:26:26 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:30:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ +help: consider adding an explicit lifetime bound... + | +LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ +LL | where +LL ~ G: Get + 'a, + | + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:52:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:48:34 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:52:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ +help: consider adding an explicit lifetime bound... + | +LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ + | +++ ++++ ++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:61:9 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_________^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:60:47 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:61:9 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_________^ +help: consider adding an explicit lifetime bound... + | +LL | fn qux<'c, 'b, G: Get + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + '_ { + | +++ ++++ ++ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | / move || { +LL | | +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ + | +note: the parameter type `G` must be valid for the anonymous lifetime defined here... + --> $DIR/missing-lifetimes-in-signature.rs:69:34 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^^ +note: ...so that the type `G` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | / move || { +LL | | +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ +help: consider adding an explicit lifetime bound... + | +LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ + 'a + | +++ ++++ ++ + +error[E0621]: explicit lifetime required in the type of `dest` + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` +... +LL | / move || { +LL | | +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ lifetime `'a` required + +error[E0309]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:85:5 + | +LL | / move || { +LL | | +LL | | *dest = g.get(); +LL | | } + | |_____^ ...so that the type `G` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | G: Get + 'a, + | ++++ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs new file mode 100644 index 000000000..ff27011f8 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs @@ -0,0 +1,72 @@ +trait Foo {} +impl<'a, T: Foo> Foo for &'a T {} +impl Foo for Box {} + +struct Iter<'a, T> { + current: Option>, + remaining: T, +} + +impl<'a, T> Iterator for Iter<'a, T> +where + T: Iterator, + T::Item: Foo + 'a, +{ + type Item = Box; + + fn next(&mut self) -> Option { + let result = self.current.take(); + self.current = Box::new(self.remaining.next()).map(|f| Box::new(f) as _); + result + } +} + +struct Bar(Vec>); + +impl Bar { + fn iter(&self) -> impl Iterator> { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +struct Baz(Vec>); + +impl Baz { + fn iter(&self) -> impl Iterator> + '_ { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +struct Bat(Vec>); + +impl Bat { + fn iter<'a>(&'a self) -> impl Iterator> + 'a { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +struct Ban(Vec>); + +impl Ban { + fn iter<'a>(&'a self) -> impl Iterator> { + Iter { + //~^ ERROR lifetime may not live long enough + current: None, + remaining: self.0.iter(), + } + } +} + +fn main() {} diff --git a/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr new file mode 100644 index 000000000..c77ef79e7 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr @@ -0,0 +1,78 @@ +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:28:9 + | +LL | fn iter(&self) -> impl Iterator> { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that `impl Iterator>` captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ++++ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> { + | ++++ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:40:9 + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | - let's call the lifetime of this reference `'1` +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound + | +LL | fn iter(&self) -> impl Iterator> + '_ { + | ++++ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:52:9 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ++++ + +error: lifetime may not live long enough + --> $DIR/trait-object-nested-in-impl-trait.rs:64:9 + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | -- lifetime `'a` defined here +LL | / Iter { +LL | | +LL | | current: None, +LL | | remaining: self.0.iter(), +LL | | } + | |_________^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that `impl Iterator>` captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> + 'a { + | ++++ +help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound + | +LL | fn iter<'a>(&'a self) -> impl Iterator> { + | ++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/suggestions/many-type-ascription.rs b/tests/ui/suggestions/many-type-ascription.rs new file mode 100644 index 000000000..31ac556b9 --- /dev/null +++ b/tests/ui/suggestions/many-type-ascription.rs @@ -0,0 +1,4 @@ +fn main() { + let _ = 0: i32; //~ ERROR: type ascription is experimental + let _ = 0: i32; // (error only emitted once) +} diff --git a/tests/ui/suggestions/many-type-ascription.stderr b/tests/ui/suggestions/many-type-ascription.stderr new file mode 100644 index 000000000..3706bbae9 --- /dev/null +++ b/tests/ui/suggestions/many-type-ascription.stderr @@ -0,0 +1,12 @@ +error[E0658]: type ascription is experimental + --> $DIR/many-type-ascription.rs:2:13 + | +LL | let _ = 0: i32; + | ^^^^^^ + | + = note: see issue #23416 for more information + = help: add `#![feature(type_ascription)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/suggestions/match-ergonomics.rs b/tests/ui/suggestions/match-ergonomics.rs new file mode 100644 index 000000000..c4fc01469 --- /dev/null +++ b/tests/ui/suggestions/match-ergonomics.rs @@ -0,0 +1,41 @@ +fn main() { + let x = vec![1i32]; + match &x[..] { + [&v] => {}, //~ ERROR mismatched types + _ => {}, + } + match x { + [&v] => {}, //~ ERROR expected an array or slice + _ => {}, + } + match &x[..] { + [v] => {}, + _ => {}, + } + match &x[..] { + &[v] => {}, + _ => {}, + } + match x { + [v] => {}, //~ ERROR expected an array or slice + _ => {}, + } + let y = 1i32; + match &y { + &v => {}, + _ => {}, + } + match y { + &v => {}, //~ ERROR mismatched types + _ => {}, + } + match &y { + v => {}, + _ => {}, + } + match y { + v => {}, + _ => {}, + } + if let [&v] = &x[..] {} //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/match-ergonomics.stderr b/tests/ui/suggestions/match-ergonomics.stderr new file mode 100644 index 000000000..aa2b407bf --- /dev/null +++ b/tests/ui/suggestions/match-ergonomics.stderr @@ -0,0 +1,68 @@ +error[E0308]: mismatched types + --> $DIR/match-ergonomics.rs:4:10 + | +LL | match &x[..] { + | ------ this expression has type `&[i32]` +LL | [&v] => {}, + | ^^ expected `i32`, found reference + | + = note: expected type `i32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - [&v] => {}, +LL + [v] => {}, + | + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/match-ergonomics.rs:8:9 + | +LL | match x { + | - help: consider slicing here: `x[..]` +LL | [&v] => {}, + | ^^^^ pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/match-ergonomics.rs:20:9 + | +LL | match x { + | - help: consider slicing here: `x[..]` +LL | [v] => {}, + | ^^^ pattern cannot match with input type `Vec` + +error[E0308]: mismatched types + --> $DIR/match-ergonomics.rs:29:9 + | +LL | match y { + | - this expression has type `i32` +LL | &v => {}, + | ^^ expected `i32`, found reference + | + = note: expected type `i32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - &v => {}, +LL + v => {}, + | + +error[E0308]: mismatched types + --> $DIR/match-ergonomics.rs:40:13 + | +LL | if let [&v] = &x[..] {} + | ^^ ------ this expression has type `&[i32]` + | | + | expected `i32`, found reference + | + = note: expected type `i32` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - if let [&v] = &x[..] {} +LL + if let [v] = &x[..] {} + | + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0529. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/match-needing-semi.rs b/tests/ui/suggestions/match-needing-semi.rs new file mode 100644 index 000000000..833555d0e --- /dev/null +++ b/tests/ui/suggestions/match-needing-semi.rs @@ -0,0 +1,21 @@ +// check-only + +fn main() { + match 3 { + 4 => 1, + 3 => { + foo() //~ ERROR mismatched types + } + _ => 2 + } + match 3 { //~ ERROR mismatched types + 4 => 1, + 3 => 2, + _ => 2 + } + let _ = (); +} + +fn foo() -> i32 { + 42 +} diff --git a/tests/ui/suggestions/match-needing-semi.stderr b/tests/ui/suggestions/match-needing-semi.stderr new file mode 100644 index 000000000..b5f01d703 --- /dev/null +++ b/tests/ui/suggestions/match-needing-semi.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> $DIR/match-needing-semi.rs:7:13 + | +LL | / match 3 { +LL | | 4 => 1, +LL | | 3 => { +LL | | foo() + | | ^^^^^ expected `()`, found `i32` +LL | | } +LL | | _ => 2 +LL | | } + | |_____- expected this to be `()` + | +help: consider using a semicolon here + | +LL | foo(); + | + +help: consider using a semicolon here + | +LL | }; + | + + +error[E0308]: mismatched types + --> $DIR/match-needing-semi.rs:11:5 + | +LL | / match 3 { +LL | | 4 => 1, +LL | | 3 => 2, +LL | | _ => 2 +LL | | } + | | ^- help: consider using a semicolon here + | |_____| + | expected `()`, found integer + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.rs b/tests/ui/suggestions/match-prev-arm-needing-semi.rs new file mode 100644 index 000000000..8c8abe047 --- /dev/null +++ b/tests/ui/suggestions/match-prev-arm-needing-semi.rs @@ -0,0 +1,66 @@ +// edition:2018 + +fn dummy() -> i32 { 42 } + +fn extra_semicolon() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => { + dummy(); //~ NOTE this is found to be + //~^ HELP consider removing this semicolon + } + false => dummy(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected `()`, found `i32` + }; +} + +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function + +async fn async_extra_semicolon_same() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => { + async_dummy(); //~ NOTE this is found to be + //~^ HELP consider removing this semicolon + } + false => async_dummy(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_extra_semicolon_different() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => { + async_dummy(); //~ NOTE this is found to be + //~^ HELP consider removing this semicolon + } + false => async_dummy2(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_different_futures() { + let _ = match true { //~ NOTE `match` arms have incompatible types + true => async_dummy(), //~ NOTE this is found to be + //~| HELP consider `await`ing on both `Future`s + false => async_dummy2(), //~ ERROR `match` arms have incompatible types + //~^ NOTE expected opaque type, found a different opaque type + //~| NOTE expected opaque type `impl Future` + //~| NOTE distinct uses of `impl Trait` result in different opaque types + }; +} + +fn main() {} diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr new file mode 100644 index 000000000..8d735b71f --- /dev/null +++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -0,0 +1,127 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:35:18 + | +LL | let _ = match true { + | _____________- +LL | | true => { +LL | | async_dummy(); + | | -------------- this is found to be of type `()` +LL | | +LL | | } +LL | | false => async_dummy(), + | | ^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:16:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future` +help: consider `await`ing on the `Future` + | +LL | false => async_dummy().await, + | ++++++ +help: consider removing this semicolon + | +LL - async_dummy(); +LL + async_dummy() + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:48:18 + | +LL | let _ = match true { + | _____________- +LL | | true => { +LL | | async_dummy(); + | | -------------- this is found to be of type `()` +LL | | +LL | | } +LL | | false => async_dummy2(), + | | ^^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:22:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future` +help: consider `await`ing on the `Future` + | +LL | false => async_dummy2().await, + | ++++++ +help: consider removing this semicolon and boxing the expressions + | +LL ~ Box::new(async_dummy()) +LL | +LL | } +LL ~ false => Box::new(async_dummy2()), + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:59:18 + | +LL | let _ = match true { + | _____________- +LL | | true => async_dummy(), + | | ------------- this is found to be of type `impl Future` +LL | | +LL | | false => async_dummy2(), + | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type +... | +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:16:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/match-prev-arm-needing-semi.rs:22:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) + found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ true => async_dummy().await, +LL | +LL ~ false => async_dummy2().await, + | + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-prev-arm-needing-semi.rs:11:18 + | +LL | let _ = match true { + | _____________- +LL | | true => { +LL | | dummy(); + | | -------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` +LL | | +LL | | } +LL | | false => dummy(), + | | ^^^^^^^ expected `()`, found `i32` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs new file mode 100644 index 000000000..0360ce6e6 --- /dev/null +++ b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.rs @@ -0,0 +1,30 @@ +pub trait Foo {} + +struct Bar; +struct Baz; + +impl Foo for Bar { } +impl Foo for Baz { } + +fn not_all_paths(a: &str) -> u32 { //~ ERROR mismatched types + match a { + "baz" => 0, + _ => 1, + }; +} + +fn right(b: &str) -> Box { + match b { + "baz" => Box::new(Baz), + _ => Box::new(Bar), + } +} + +fn wrong(c: &str) -> Box { //~ ERROR mismatched types + match c { + "baz" => Box::new(Baz), + _ => Box::new(Bar), //~ ERROR `match` arms have incompatible types + }; +} + +fn main() {} diff --git a/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr new file mode 100644 index 000000000..00aa7d18a --- /dev/null +++ b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:9:30 + | +LL | fn not_all_paths(a: &str) -> u32 { + | ------------- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression +... +LL | }; + | - help: remove this semicolon to return this value + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:26:14 + | +LL | / match c { +LL | | "baz" => Box::new(Baz), + | | ------------- this is found to be of type `Box` +LL | | _ => Box::new(Bar), + | | ^^^^^^^^^^^^^ expected struct `Baz`, found struct `Bar` +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected struct `Box` + found struct `Box` +note: you might have meant to return the `match` expression + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:27:6 + | +LL | fn wrong(c: &str) -> Box { + | ------------ the `match` arms can conform to this return type +LL | / match c { +LL | | "baz" => Box::new(Baz), +LL | | _ => Box::new(Bar), +LL | | }; + | | -^ the `match` is a statement because of this semicolon, consider removing it + | |_____| + | this could be implicitly returned but it is a statement, not a tail expression + +error[E0308]: mismatched types + --> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:23:22 + | +LL | fn wrong(c: &str) -> Box { + | ----- ^^^^^^^^^^^^ expected struct `Box`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Box<(dyn Foo + 'static)>` + found unit type `()` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.fixed b/tests/ui/suggestions/method-access-to-range-literal-typo.fixed new file mode 100644 index 000000000..13601eef6 --- /dev/null +++ b/tests/ui/suggestions/method-access-to-range-literal-typo.fixed @@ -0,0 +1,34 @@ +// run-rustfix + +#![allow(unused)] + +fn as_ref() -> Option> { + None +} +struct Type { + option: Option> +} +trait Trait { + fn foo(&self) -> &Vec; +} +impl Trait for Option> { + fn foo(&self) -> &Vec { + self.as_ref().unwrap() + } +} + +impl Type { + fn method(&self) -> Option<&Vec> { + self.option.as_ref().map(|x| x) + //~^ ERROR E0308 + } + fn method2(&self) -> Option<&u8> { + self.option.foo().get(0) + //~^ ERROR E0425 + //~| ERROR E0308 + } +} + +fn main() { + let _ = Type { option: None }.method(); +} diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.rs b/tests/ui/suggestions/method-access-to-range-literal-typo.rs new file mode 100644 index 000000000..fdcd6425d --- /dev/null +++ b/tests/ui/suggestions/method-access-to-range-literal-typo.rs @@ -0,0 +1,34 @@ +// run-rustfix + +#![allow(unused)] + +fn as_ref() -> Option> { + None +} +struct Type { + option: Option> +} +trait Trait { + fn foo(&self) -> &Vec; +} +impl Trait for Option> { + fn foo(&self) -> &Vec { + self.as_ref().unwrap() + } +} + +impl Type { + fn method(&self) -> Option<&Vec> { + self.option..as_ref().map(|x| x) + //~^ ERROR E0308 + } + fn method2(&self) -> Option<&u8> { + self.option..foo().get(0) + //~^ ERROR E0425 + //~| ERROR E0308 + } +} + +fn main() { + let _ = Type { option: None }.method(); +} diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr new file mode 100644 index 000000000..f42140894 --- /dev/null +++ b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr @@ -0,0 +1,48 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/method-access-to-range-literal-typo.rs:26:22 + | +LL | self.option..foo().get(0) + | ^^^ not found in this scope + | +help: you might have meant to write `.` instead of `..` + | +LL - self.option..foo().get(0) +LL + self.option.foo().get(0) + | + +error[E0308]: mismatched types + --> $DIR/method-access-to-range-literal-typo.rs:22:9 + | +LL | fn method(&self) -> Option<&Vec> { + | ---------------- expected `Option<&Vec>` because of return type +LL | self.option..as_ref().map(|x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range` + | + = note: expected enum `Option<&Vec>` + found struct `std::ops::Range>>` +help: you likely meant to write a method call instead of a range + | +LL - self.option..as_ref().map(|x| x) +LL + self.option.as_ref().map(|x| x) + | + +error[E0308]: mismatched types + --> $DIR/method-access-to-range-literal-typo.rs:26:9 + | +LL | fn method2(&self) -> Option<&u8> { + | ----------- expected `Option<&u8>` because of return type +LL | self.option..foo().get(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range` + | + = note: expected enum `Option<&u8>` + found struct `std::ops::Range>>` +help: you likely meant to write a method call instead of a range + | +LL - self.option..foo().get(0) +LL + self.option.foo().get(0) + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/method-missing-parentheses.rs b/tests/ui/suggestions/method-missing-parentheses.rs new file mode 100644 index 000000000..f10bfb56d --- /dev/null +++ b/tests/ui/suggestions/method-missing-parentheses.rs @@ -0,0 +1,5 @@ +fn main() { + let _ = vec![].into_iter().collect::; + //~^ ERROR attempted to take value of method `collect` on type `std::vec::IntoIter<_>` + //~| ERROR field expressions cannot have generic arguments +} diff --git a/tests/ui/suggestions/method-missing-parentheses.stderr b/tests/ui/suggestions/method-missing-parentheses.stderr new file mode 100644 index 000000000..1bfff56a6 --- /dev/null +++ b/tests/ui/suggestions/method-missing-parentheses.stderr @@ -0,0 +1,20 @@ +error: field expressions cannot have generic arguments + --> $DIR/method-missing-parentheses.rs:2:41 + | +LL | let _ = vec![].into_iter().collect::; + | ^^^^^^^ + +error[E0615]: attempted to take value of method `collect` on type `std::vec::IntoIter<_>` + --> $DIR/method-missing-parentheses.rs:2:32 + | +LL | let _ = vec![].into_iter().collect::; + | ^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let _ = vec![].into_iter().collect::(); + | ++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/suggestions/mismatched-types-numeric-from.rs b/tests/ui/suggestions/mismatched-types-numeric-from.rs new file mode 100644 index 000000000..56549da9c --- /dev/null +++ b/tests/ui/suggestions/mismatched-types-numeric-from.rs @@ -0,0 +1,3 @@ +fn main() { + let _: u32 = i32::from(0_u8); //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/mismatched-types-numeric-from.stderr b/tests/ui/suggestions/mismatched-types-numeric-from.stderr new file mode 100644 index 000000000..4d44d893a --- /dev/null +++ b/tests/ui/suggestions/mismatched-types-numeric-from.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/mismatched-types-numeric-from.rs:2:18 + | +LL | let _: u32 = i32::from(0_u8); + | --- ^^^^^^^^^^^^^^^ expected `u32`, found `i32` + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed new file mode 100644 index 000000000..a0cb39a3f --- /dev/null +++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.fixed @@ -0,0 +1,21 @@ +// run-rustfix +trait TraitB { + type Item; +} + +trait TraitA { + type Type; + fn bar(_: T) -> Self; + fn baz(_: T) -> Self where T: TraitB, ::Item: Copy; +} + +struct S; +struct Type; + +impl TraitA<()> for S { //~ ERROR not all trait items implemented +fn baz(_: T) -> Self where T: TraitB, ::Item: Copy { todo!() } +fn bar(_: T) -> Self { todo!() } +type Type = Type; +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs new file mode 100644 index 000000000..c80ede1b2 --- /dev/null +++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.rs @@ -0,0 +1,18 @@ +// run-rustfix +trait TraitB { + type Item; +} + +trait TraitA { + type Type; + fn bar(_: T) -> Self; + fn baz(_: T) -> Self where T: TraitB, ::Item: Copy; +} + +struct S; +struct Type; + +impl TraitA<()> for S { //~ ERROR not all trait items implemented +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr new file mode 100644 index 000000000..4c75fbe4c --- /dev/null +++ b/tests/ui/suggestions/missing-assoc-fn-applicable-suggestions.stderr @@ -0,0 +1,16 @@ +error[E0046]: not all trait items implemented, missing: `Type`, `bar`, `baz` + --> $DIR/missing-assoc-fn-applicable-suggestions.rs:15:1 + | +LL | type Type; + | --------- `Type` from trait +LL | fn bar(_: T) -> Self; + | ------------------------ `bar` from trait +LL | fn baz(_: T) -> Self where T: TraitB, ::Item: Copy; + | ------------------------------------------------------------------- `baz` from trait +... +LL | impl TraitA<()> for S { + | ^^^^^^^^^^^^^^^^^^^^^ missing `Type`, `bar`, `baz` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/missing-assoc-fn.rs b/tests/ui/suggestions/missing-assoc-fn.rs new file mode 100644 index 000000000..9af8e5a93 --- /dev/null +++ b/tests/ui/suggestions/missing-assoc-fn.rs @@ -0,0 +1,22 @@ +trait TraitB { + type Item; +} + +trait TraitA { + fn foo>(_: T) -> Self; + fn bar(_: T) -> Self; + fn baz(_: T) -> Self where T: TraitB, ::Item: Copy; + fn bat>(_: T) -> Self; //~ ERROR associated type bounds are unstable +} + +struct S; + +impl TraitA<()> for S { //~ ERROR not all trait items implemented +} + +use std::iter::FromIterator; +struct X; +impl FromIterator<()> for X { //~ ERROR not all trait items implemented +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-assoc-fn.stderr b/tests/ui/suggestions/missing-assoc-fn.stderr new file mode 100644 index 000000000..136ec2152 --- /dev/null +++ b/tests/ui/suggestions/missing-assoc-fn.stderr @@ -0,0 +1,36 @@ +error[E0658]: associated type bounds are unstable + --> $DIR/missing-assoc-fn.rs:9:22 + | +LL | fn bat>(_: T) -> Self; + | ^^^^^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `bat` + --> $DIR/missing-assoc-fn.rs:14:1 + | +LL | fn foo>(_: T) -> Self; + | ------------------------------------------ `foo` from trait +LL | fn bar(_: T) -> Self; + | ------------------------ `bar` from trait +LL | fn baz(_: T) -> Self where T: TraitB, ::Item: Copy; + | ------------------------------------------------------------------- `baz` from trait +LL | fn bat>(_: T) -> Self; + | -------------------------------------------- `bat` from trait +... +LL | impl TraitA<()> for S { + | ^^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `bat` in implementation + +error[E0046]: not all trait items implemented, missing: `from_iter` + --> $DIR/missing-assoc-fn.rs:19:1 + | +LL | impl FromIterator<()> for X { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation + | + = help: implement the missing item: `fn from_iter(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = A { todo!() }` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0046, E0658. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/missing-assoc-type-bound-restriction.rs b/tests/ui/suggestions/missing-assoc-type-bound-restriction.rs new file mode 100644 index 000000000..4954a8a69 --- /dev/null +++ b/tests/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Parent { + type Ty; + type Assoc: Child; +} + +trait Child {} + +struct ChildWrapper(T); + +impl Child for ChildWrapper where T: Child {} + +struct ParentWrapper(T); + +impl> Parent for ParentWrapper { + type Ty = A; + type Assoc = ChildWrapper; +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed new file mode 100644 index 000000000..ac0b14fba --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.fixed @@ -0,0 +1,16 @@ +// run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] +pub struct AABB{ + pub loc: Vector2, //~ ERROR the trait bound `K: Copy` is not satisfied + pub size: Vector2 +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs new file mode 100644 index 000000000..31f8cd6fc --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.rs @@ -0,0 +1,16 @@ +// run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] +pub struct AABB{ + pub loc: Vector2, //~ ERROR the trait bound `K: Copy` is not satisfied + pub size: Vector2 +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr new file mode 100644 index 000000000..03082be69 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `K: Copy` is not satisfied + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:12:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ the trait `Copy` is not implemented for `K` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31 + | +LL | pub struct Vector2{ + | ^^^^ required by this bound in `Vector2` +help: consider further restricting this bound + | +LL | pub struct AABB{ + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed new file mode 100644 index 000000000..304360d48 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -0,0 +1,16 @@ +//run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB{ + pub loc: Vector2, + pub size: Vector2 +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs new file mode 100644 index 000000000..14e1fbb33 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -0,0 +1,16 @@ +//run-rustfix +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB{ + pub loc: Vector2, + pub size: Vector2 +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr new file mode 100644 index 000000000..faf730a5c --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -0,0 +1,27 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ +LL | pub struct AABB{ +LL | pub loc: Vector2, + | ------------------- this field does not implement `Copy` +LL | pub size: Vector2 + | -------------------- this field does not implement `Copy` + | +note: the `Copy` impl for `Vector2` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ +LL | pub size: Vector2 + | ^^^^^^^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider further restricting this bound + | +LL | pub struct AABB{ + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs new file mode 100644 index 000000000..52163bddd --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -0,0 +1,15 @@ +use std::fmt::Debug; + +#[derive(Debug, Copy, Clone)] +pub struct Vector2{ + pub x: T, + pub y: T +} + +#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented for this type +pub struct AABB{ + pub loc: Vector2, + pub size: Vector2 +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr new file mode 100644 index 000000000..11bc54099 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -0,0 +1,27 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + | +LL | #[derive(Debug, Copy, Clone)] + | ^^^^ +LL | pub struct AABB{ +LL | pub loc: Vector2, + | ------------------- this field does not implement `Copy` +LL | pub size: Vector2 + | -------------------- this field does not implement `Copy` + | +note: the `Copy` impl for `Vector2` requires that `K: Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ +LL | pub size: Vector2 + | ^^^^^^^^^^ + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `K` + | +LL | pub struct AABB{ + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed new file mode 100644 index 000000000..691e7553a --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -0,0 +1,19 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper(T); + +struct OnlyCopyIfDisplay(std::marker::PhantomData); + +impl Clone for OnlyCopyIfDisplay { + fn clone(&self) -> Self { + OnlyCopyIfDisplay(std::marker::PhantomData) + } +} + +impl Copy for OnlyCopyIfDisplay {} + +impl Copy for Wrapper> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs new file mode 100644 index 000000000..e3185e7ef --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -0,0 +1,19 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper(T); + +struct OnlyCopyIfDisplay(std::marker::PhantomData); + +impl Clone for OnlyCopyIfDisplay { + fn clone(&self) -> Self { + OnlyCopyIfDisplay(std::marker::PhantomData) + } +} + +impl Copy for OnlyCopyIfDisplay {} + +impl Copy for Wrapper> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr new file mode 100644 index 000000000..9e6f0d9eb --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -0,0 +1,22 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18 + | +LL | struct Wrapper(T); + | - this field does not implement `Copy` +... +LL | impl Copy for Wrapper> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the `Copy` impl for `OnlyCopyIfDisplay` requires that `S: std::fmt::Display` + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 + | +LL | struct Wrapper(T); + | ^ +help: consider restricting type parameter `S` + | +LL | impl Copy for Wrapper> {} + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed new file mode 100644 index 000000000..32a7215c5 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper(T); + +impl Copy for Wrapper {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs new file mode 100644 index 000000000..c688f4d41 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#[derive(Clone)] +struct Wrapper(T); + +impl Copy for Wrapper {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr new file mode 100644 index 000000000..fe2d133c8 --- /dev/null +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -0,0 +1,17 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18 + | +LL | struct Wrapper(T); + | - this field does not implement `Copy` +LL | +LL | impl Copy for Wrapper {} + | ^^^^^^^^^^ + | +help: consider restricting type parameter `S` + | +LL | impl Copy for Wrapper {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs new file mode 100644 index 000000000..38332627f --- /dev/null +++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.rs @@ -0,0 +1,16 @@ +trait ZstAssert: Sized { + const A: &str = ""; //~ ERROR missing lifetime specifier + const B: S = S { s: &() }; //~ ERROR missing lifetime specifier + const C: &'_ str = ""; //~ ERROR missing lifetime specifier + const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier +} + +struct S<'a> { + s: &'a (), +} +struct T<'a, 'b> { + a: &'a (), + b: &'b (), +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr new file mode 100644 index 000000000..233f1bc5a --- /dev/null +++ b/tests/ui/suggestions/missing-lifetime-in-assoc-const-type.stderr @@ -0,0 +1,57 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-const-type.rs:2:14 + | +LL | const A: &str = ""; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL ~ const A: &'a str = ""; + | + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-const-type.rs:3:14 + | +LL | const B: S = S { s: &() }; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL | const A: &str = ""; +LL ~ const B: S<'a> = S { s: &() }; + | + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-in-assoc-const-type.rs:4:15 + | +LL | const C: &'_ str = ""; + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL | const A: &str = ""; +LL | const B: S = S { s: &() }; +LL ~ const C: &'a str = ""; + | + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-in-assoc-const-type.rs:5:14 + | +LL | const D: T = T { a: &(), b: &() }; + | ^ expected 2 lifetime parameters + | +help: consider introducing a named lifetime parameter + | +LL ~ trait ZstAssert<'a>: Sized { +LL | const A: &str = ""; +LL | const B: S = S { s: &() }; +LL | const C: &'_ str = ""; +LL ~ const D: T<'a, 'a> = T { a: &(), b: &() }; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs new file mode 100644 index 000000000..24f5f782f --- /dev/null +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -0,0 +1,57 @@ +#![allow(bare_trait_objects)] +use std::collections::HashMap; +use std::cell::RefCell; + +pub union Foo<'t, 'k> { + i: &'t i64, + f: &'k f64, +} +trait Bar<'t, 'k> {} + +pub union Qux<'t, 'k, I> { + i: &'t I, + f: &'k I, +} +trait Tar<'t, 'k, I> {} + +thread_local! { + static a: RefCell>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} +thread_local! { + static b: RefCell>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} +thread_local! { + static c: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} +thread_local! { + static d: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR missing lifetime specifiers + //~| ERROR missing lifetime specifiers +} + +thread_local! { + static e: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR this union takes 2 lifetime arguments but 1 lifetime argument + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied +} +thread_local! { + static f: RefCell>>>> = RefCell::new(HashMap::new()); + //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR missing lifetime + //~| ERROR missing lifetime +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr new file mode 100644 index 000000000..997bbb5e9 --- /dev/null +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -0,0 +1,319 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:18:44 + | +LL | static a: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^ expected 2 lifetime parameters + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); + | ++++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:18:44 + | +LL | / thread_local! { +LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); + | | ^^^ expected 2 lifetime parameters +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:23:44 + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ^^^^ expected 2 lifetime parameters + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++ ++++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:23:44 + | +LL | / thread_local! { +LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); + | | ^^^^ expected 2 lifetime parameters + | | | + | | expected named lifetime parameter +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:28:47 + | +LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ expected 2 lifetime parameters + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:28:47 + | +LL | / thread_local! { +LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); + | | ^ expected 2 lifetime parameters +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:33:44 + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ ^ expected 2 lifetime parameters + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++ +++++++++++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lifetime-specifier.rs:33:44 + | +LL | / thread_local! { +LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | | ^ ^ expected 2 lifetime parameters + | | | + | | expected named lifetime parameter +LL | | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/missing-lifetime-specifier.rs:47:44 + | +LL | / thread_local! { +LL | | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | | ^ expected named lifetime parameter +LL | | +LL | | +... | +LL | | +LL | | } + | |_- + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:39:44 + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: union defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:11:11 + | +LL | pub union Qux<'t, 'k, I> { + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/missing-lifetime-specifier.rs:47:45 + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | ^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'t`, `'k` + --> $DIR/missing-lifetime-specifier.rs:15:7 + | +LL | trait Tar<'t, 'k, I> {} + | ^^^ -- -- +help: add missing lifetime argument + | +LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); + | +++++++++ + +error: aborting due to 20 previous errors + +Some errors have detailed explanations: E0106, E0107. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.rs b/tests/ui/suggestions/missing-lt-for-hrtb.rs new file mode 100644 index 000000000..04ea3d831 --- /dev/null +++ b/tests/ui/suggestions/missing-lt-for-hrtb.rs @@ -0,0 +1,13 @@ +struct X<'a>(&'a ()); +struct S<'a>(&'a dyn Fn(&X) -> &X); +//~^ ERROR missing lifetime specifiers +struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); +//~^ ERROR missing lifetime specifiers + +fn main() { + let x = S(&|x| { + println!("hi"); + x + }); + x.0(&X(&())); +} diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.stderr b/tests/ui/suggestions/missing-lt-for-hrtb.stderr new file mode 100644 index 000000000..fa5156444 --- /dev/null +++ b/tests/ui/suggestions/missing-lt-for-hrtb.stderr @@ -0,0 +1,36 @@ +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lt-for-hrtb.rs:2:32 + | +LL | struct S<'a>(&'a dyn Fn(&X) -> &X); + | -- ^^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from +help: consider using the `'a` lifetime + | +LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X<'a>); + | ++ ++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/missing-lt-for-hrtb.rs:4:40 + | +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); + | -- ^^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from +note: these named lifetimes are available to use + --> $DIR/missing-lt-for-hrtb.rs:4:10 + | +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>); + | +++++++++ +++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-trait-item.fixed b/tests/ui/suggestions/missing-trait-item.fixed new file mode 100644 index 000000000..a1cf359ec --- /dev/null +++ b/tests/ui/suggestions/missing-trait-item.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait T { + unsafe fn foo(a: &usize, b: &usize) -> usize; + fn bar(&self, a: &usize, b: &usize) -> usize; +} + +mod foo { + use super::T; + impl T for () { fn bar(&self, _: &usize, _: &usize) -> usize { todo!() } + unsafe fn foo(_: &usize, _: &usize) -> usize { todo!() } + } //~ ERROR not all trait items + + impl T for usize { //~ ERROR not all trait items + fn bar(&self, _: &usize, _: &usize) -> usize { todo!() } + unsafe fn foo(_: &usize, _: &usize) -> usize { todo!() } + } +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-trait-item.rs b/tests/ui/suggestions/missing-trait-item.rs new file mode 100644 index 000000000..b4fca25ba --- /dev/null +++ b/tests/ui/suggestions/missing-trait-item.rs @@ -0,0 +1,16 @@ +// run-rustfix + +trait T { + unsafe fn foo(a: &usize, b: &usize) -> usize; + fn bar(&self, a: &usize, b: &usize) -> usize; +} + +mod foo { + use super::T; + impl T for () {} //~ ERROR not all trait items + + impl T for usize { //~ ERROR not all trait items + } +} + +fn main() {} diff --git a/tests/ui/suggestions/missing-trait-item.stderr b/tests/ui/suggestions/missing-trait-item.stderr new file mode 100644 index 000000000..4a9d7b472 --- /dev/null +++ b/tests/ui/suggestions/missing-trait-item.stderr @@ -0,0 +1,25 @@ +error[E0046]: not all trait items implemented, missing: `foo`, `bar` + --> $DIR/missing-trait-item.rs:10:5 + | +LL | unsafe fn foo(a: &usize, b: &usize) -> usize; + | --------------------------------------------- `foo` from trait +LL | fn bar(&self, a: &usize, b: &usize) -> usize; + | --------------------------------------------- `bar` from trait +... +LL | impl T for () {} + | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation + +error[E0046]: not all trait items implemented, missing: `foo`, `bar` + --> $DIR/missing-trait-item.rs:12:5 + | +LL | unsafe fn foo(a: &usize, b: &usize) -> usize; + | --------------------------------------------- `foo` from trait +LL | fn bar(&self, a: &usize, b: &usize) -> usize; + | --------------------------------------------- `bar` from trait +... +LL | impl T for usize { + | ^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.fixed b/tests/ui/suggestions/missing-type-param-used-in-param.fixed new file mode 100644 index 000000000..be4394031 --- /dev/null +++ b/tests/ui/suggestions/missing-type-param-used-in-param.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn two_type_params(_: B) {} + +fn main() { + two_type_params::(100); //~ ERROR function takes 2 generic arguments + two_type_params::(100); +} diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.rs b/tests/ui/suggestions/missing-type-param-used-in-param.rs new file mode 100644 index 000000000..d444998d3 --- /dev/null +++ b/tests/ui/suggestions/missing-type-param-used-in-param.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn two_type_params(_: B) {} + +fn main() { + two_type_params::(100); //~ ERROR function takes 2 generic arguments + two_type_params::(100); +} diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.stderr b/tests/ui/suggestions/missing-type-param-used-in-param.stderr new file mode 100644 index 000000000..4f7058a64 --- /dev/null +++ b/tests/ui/suggestions/missing-type-param-used-in-param.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/missing-type-param-used-in-param.rs:6:5 + | +LL | two_type_params::(100); + | ^^^^^^^^^^^^^^^ ------ supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `A`, `B` + --> $DIR/missing-type-param-used-in-param.rs:3:4 + | +LL | fn two_type_params(_: B) {} + | ^^^^^^^^^^^^^^^ - - +help: add missing generic argument + | +LL | two_type_params::(100); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs new file mode 100644 index 000000000..2f540060a --- /dev/null +++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs @@ -0,0 +1,18 @@ +// Generalizes the suggestion introduced in #100838 + +trait Foo { + fn bar(&self, _: T); +} + +impl Foo for i32 { + fn bar(&self, x: i32) { + println!("{}", self + x); + } +} + +fn main() { + 1.bar::(0); + //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied + //~| HELP consider moving this generic argument to the `Foo` trait, which takes up to 1 argument + //~| HELP remove these generics +} diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr new file mode 100644 index 000000000..9557220f6 --- /dev/null +++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr @@ -0,0 +1,24 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/move-generic-to-trait-in-method-with-params.rs:14:7 + | +LL | 1.bar::(0); + | ^^^ expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/move-generic-to-trait-in-method-with-params.rs:4:8 + | +LL | fn bar(&self, _: T); + | ^^^ +help: consider moving this generic argument to the `Foo` trait, which takes up to 1 argument + | +LL | Foo::::bar(1, 0); + | ~~~~~~~~~~~~~~~~~~~~~ +help: remove these generics + | +LL - 1.bar::(0); +LL + 1.bar(0); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/multibyte-escapes.rs b/tests/ui/suggestions/multibyte-escapes.rs new file mode 100644 index 000000000..c41051862 --- /dev/null +++ b/tests/ui/suggestions/multibyte-escapes.rs @@ -0,0 +1,18 @@ +// Regression test for #87397. + +fn main() { + b'µ'; + //~^ ERROR: non-ASCII character in byte literal + //~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape + //~| NOTE: must be ASCII + + b'字'; + //~^ ERROR: non-ASCII character in byte literal + //~| NOTE: this multibyte character does not fit into a single byte + //~| NOTE: must be ASCII + + b"字"; + //~^ ERROR: non-ASCII character in byte string literal + //~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes + //~| NOTE: must be ASCII +} diff --git a/tests/ui/suggestions/multibyte-escapes.stderr b/tests/ui/suggestions/multibyte-escapes.stderr new file mode 100644 index 000000000..1e7c43e65 --- /dev/null +++ b/tests/ui/suggestions/multibyte-escapes.stderr @@ -0,0 +1,33 @@ +error: non-ASCII character in byte literal + --> $DIR/multibyte-escapes.rs:4:7 + | +LL | b'µ'; + | ^ must be ASCII + | +help: if you meant to use the unicode code point for 'µ', use a \xHH escape + | +LL | b'\xB5'; + | ~~~~ + +error: non-ASCII character in byte literal + --> $DIR/multibyte-escapes.rs:9:7 + | +LL | b'字'; + | ^^ + | | + | must be ASCII + | this multibyte character does not fit into a single byte + +error: non-ASCII character in byte string literal + --> $DIR/multibyte-escapes.rs:14:7 + | +LL | b"字"; + | ^^ must be ASCII + | +help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes + | +LL | b"\xE5\xAD\x97"; + | ~~~~~~~~~~~~ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.rs b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs new file mode 100644 index 000000000..66e1e77c9 --- /dev/null +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -0,0 +1,22 @@ +use std::env::args; +use std::fs::File; +use std::io::{stdout, Write, BufWriter}; + +fn main() { + let mut args = args(); + let _ = args.next(); + let dest = args.next(); + + let h1; let h2; let h3; + + let fp: &dyn Write = match dest { + Some(path) => { h1 = File::create(path).unwrap(); &h1 }, + None => { h2 = stdout(); h3 = h2.lock(); &h3 } + }; + + let fp = BufWriter::new(fp); + //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + + writeln!(fp, "hello world").unwrap(); //~ ERROR the method +} diff --git a/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr new file mode 100644 index 000000000..6910b77d9 --- /dev/null +++ b/tests/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -0,0 +1,40 @@ +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:29 + | +LL | let fp = BufWriter::new(fp); + | -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | | + | required by a bound introduced by this call + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` +note: required by a bound in `BufWriter::::new` + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` +note: required by a bound in `BufWriter` + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + +error[E0599]: the method `write_fmt` exists for struct `BufWriter<&dyn Write>`, but its trait bounds were not satisfied + --> $DIR/mut-borrow-needed-by-trait.rs:21:5 + | +LL | writeln!(fp, "hello world").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `BufWriter<&dyn Write>` due to unsatisfied trait bounds + --> $SRC_DIR/std/src/io/buffered/bufwriter.rs:LL:COL + | + = note: doesn't satisfy `BufWriter<&dyn std::io::Write>: std::io::Write` + | + = note: the following trait bounds were not satisfied: + `&dyn std::io::Write: std::io::Write` + which is required by `BufWriter<&dyn std::io::Write>: std::io::Write` + = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/mut-ref-reassignment.rs b/tests/ui/suggestions/mut-ref-reassignment.rs new file mode 100644 index 000000000..142832493 --- /dev/null +++ b/tests/ui/suggestions/mut-ref-reassignment.rs @@ -0,0 +1,17 @@ +fn suggestion(opt: &mut Option) { + opt = None; //~ ERROR mismatched types +} + +fn no_suggestion(opt: &mut Result) { + opt = None //~ ERROR mismatched types +} + +fn suggestion2(opt: &mut Option) { + opt = Some(String::new())//~ ERROR mismatched types +} + +fn no_suggestion2(opt: &mut Option) { + opt = Some(42)//~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/mut-ref-reassignment.stderr b/tests/ui/suggestions/mut-ref-reassignment.stderr new file mode 100644 index 000000000..b3cb6dd06 --- /dev/null +++ b/tests/ui/suggestions/mut-ref-reassignment.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:2:11 + | +LL | fn suggestion(opt: &mut Option) { + | ------------------- expected due to this parameter type +LL | opt = None; + | ^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Option` + found enum `Option<_>` +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *opt = None; + | + + +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:6:11 + | +LL | fn no_suggestion(opt: &mut Result) { + | ----------------------- expected due to this parameter type +LL | opt = None + | ^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Result` + found enum `Option<_>` + +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:10:11 + | +LL | fn suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type +LL | opt = Some(String::new()) + | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Option` + found enum `Option` +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *opt = Some(String::new()) + | + + +error[E0308]: mismatched types + --> $DIR/mut-ref-reassignment.rs:14:11 + | +LL | fn no_suggestion2(opt: &mut Option) { + | ------------------- expected due to this parameter type +LL | opt = Some(42) + | ^^^^^^^^ expected mutable reference, found enum `Option` + | + = note: expected mutable reference `&mut Option` + found enum `Option<{integer}>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/negative-literal-index.fixed b/tests/ui/suggestions/negative-literal-index.fixed new file mode 100644 index 000000000..e52714cf9 --- /dev/null +++ b/tests/ui/suggestions/negative-literal-index.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +use std::ops::Index; +struct X; +impl Index for X { + type Output = (); + + fn index(&self, _: i32) -> &() { + &() + } +} + +fn main() { + let x = vec![1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let x = [1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let x = &[1, 2, 3]; + x[x.len() -1]; //~ ERROR negative integers cannot be used to index on a + let _ = x; + X[-1]; +} diff --git a/tests/ui/suggestions/negative-literal-index.rs b/tests/ui/suggestions/negative-literal-index.rs new file mode 100644 index 000000000..d88b66e67 --- /dev/null +++ b/tests/ui/suggestions/negative-literal-index.rs @@ -0,0 +1,22 @@ +// run-rustfix + +use std::ops::Index; +struct X; +impl Index for X { + type Output = (); + + fn index(&self, _: i32) -> &() { + &() + } +} + +fn main() { + let x = vec![1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let x = [1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let x = &[1, 2, 3]; + x[-1]; //~ ERROR negative integers cannot be used to index on a + let _ = x; + X[-1]; +} diff --git a/tests/ui/suggestions/negative-literal-index.stderr b/tests/ui/suggestions/negative-literal-index.stderr new file mode 100644 index 000000000..2b51bf7b7 --- /dev/null +++ b/tests/ui/suggestions/negative-literal-index.stderr @@ -0,0 +1,35 @@ +error: negative integers cannot be used to index on a `Vec<{integer}>` + --> $DIR/negative-literal-index.rs:15:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `Vec<{integer}>` + | +help: to access an element starting from the end of the `Vec<{integer}>`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: negative integers cannot be used to index on a `[{integer}; 3]` + --> $DIR/negative-literal-index.rs:17:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `[{integer}; 3]` + | +help: to access an element starting from the end of the `[{integer}; 3]`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: negative integers cannot be used to index on a `[{integer}; 3]` + --> $DIR/negative-literal-index.rs:19:7 + | +LL | x[-1]; + | ^^ cannot use a negative integer for indexing on `[{integer}; 3]` + | +help: to access an element starting from the end of the `[{integer}; 3]`, compute the index + | +LL | x[x.len() -1]; + | +++++++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/suggestions/nested-non-tuple-tuple-struct.rs b/tests/ui/suggestions/nested-non-tuple-tuple-struct.rs new file mode 100644 index 000000000..308adcf01 --- /dev/null +++ b/tests/ui/suggestions/nested-non-tuple-tuple-struct.rs @@ -0,0 +1,18 @@ +pub struct S(f32, f32); + +pub enum E { + V(f32, f32), +} + +fn main() { + let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + //~^ ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + //~| ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + //~^ ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` + //~| ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` +} diff --git a/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr new file mode 100644 index 000000000..948f09fc3 --- /dev/null +++ b/tests/ui/suggestions/nested-non-tuple-tuple-struct.stderr @@ -0,0 +1,116 @@ +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:19 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:27 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:41 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */)); + | ~~~~~~~~~~~~~~~ + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:49 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `S` is a tuple struct, use the appropriate syntax + | +LL | let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */)); + | ~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:22 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:30 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 }); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:47 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */)); + | ~~~~~~~~~~~~~~~~~~ + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:55 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ^ field does not exist + | +help: `E::V` is a tuple variant, use the appropriate syntax + | +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */)); + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0559, E0560. +For more information about an error, try `rustc --explain E0559`. diff --git a/tests/ui/suggestions/no-extern-crate-in-type.rs b/tests/ui/suggestions/no-extern-crate-in-type.rs new file mode 100644 index 000000000..bb93ef454 --- /dev/null +++ b/tests/ui/suggestions/no-extern-crate-in-type.rs @@ -0,0 +1,7 @@ +// aux-build:foo.rs + +extern crate foo; + +type Output = Option; //~ ERROR cannot find type `Foo` + +fn main() {} diff --git a/tests/ui/suggestions/no-extern-crate-in-type.stderr b/tests/ui/suggestions/no-extern-crate-in-type.stderr new file mode 100644 index 000000000..876eef2b6 --- /dev/null +++ b/tests/ui/suggestions/no-extern-crate-in-type.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Foo` in this scope + --> $DIR/no-extern-crate-in-type.rs:5:22 + | +LL | type Output = Option; + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL | use foo::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs new file mode 100644 index 000000000..a7a3f9818 --- /dev/null +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs @@ -0,0 +1,43 @@ +// In rustc_hir_analysis::check::expr::no_such_field_err we recursively +// look in subfields for the field. This recursive search is limited +// in depth for compile-time reasons and to avoid infinite recursion +// in case of cycles. This file tests that the limit in the recursion +// depth is enforced. + +struct Foo { + first: Bar, + second: u32, + third: u32, +} + +struct Bar { + bar: C, +} + +struct C { + c: D, +} + +struct D { + test: E, +} + +struct E { + e: F, +} + +struct F { + f: u32, +} + +fn main() { + let f = F { f: 6 }; + let e = E { e: f }; + let d = D { test: e }; + let c = C { c: d }; + let bar = Bar { bar: c }; + let fooer = Foo { first: bar, second: 4, third: 5 }; + + let test = fooer.f; + //~^ ERROR no field +} diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr new file mode 100644 index 000000000..b294f4da7 --- /dev/null +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `f` on type `Foo` + --> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22 + | +LL | let test = fooer.f; + | ^ unknown field + | + = note: available fields are: `first`, `second`, `third` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.fixed b/tests/ui/suggestions/non-existent-field-present-in-subfield.fixed new file mode 100644 index 000000000..e58b4e6ca --- /dev/null +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.fixed @@ -0,0 +1,42 @@ +// run-rustfix + +struct Foo { + first: Bar, + _second: u32, + _third: Vec, +} + +struct Bar { + bar: C, +} + +struct C { + c: D, +} + +struct D { + test: E, +} + +struct E { + _e: F, +} + +struct F { + _f: u32, +} + +fn main() { + let f = F { _f: 6 }; + let e = E { _e: f }; + let d = D { test: e }; + let c = C { c: d }; + let bar = Bar { bar: c }; + let fooer = Foo { first: bar, _second: 4, _third: Vec::new() }; + + let _test = &fooer.first.bar.c; + //~^ ERROR no field + + let _test2 = fooer.first.bar.c.test; + //~^ ERROR no field +} diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.rs b/tests/ui/suggestions/non-existent-field-present-in-subfield.rs new file mode 100644 index 000000000..7e273ac23 --- /dev/null +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.rs @@ -0,0 +1,42 @@ +// run-rustfix + +struct Foo { + first: Bar, + _second: u32, + _third: Vec, +} + +struct Bar { + bar: C, +} + +struct C { + c: D, +} + +struct D { + test: E, +} + +struct E { + _e: F, +} + +struct F { + _f: u32, +} + +fn main() { + let f = F { _f: 6 }; + let e = E { _e: f }; + let d = D { test: e }; + let c = C { c: d }; + let bar = Bar { bar: c }; + let fooer = Foo { first: bar, _second: 4, _third: Vec::new() }; + + let _test = &fooer.c; + //~^ ERROR no field + + let _test2 = fooer.test; + //~^ ERROR no field +} diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr new file mode 100644 index 000000000..cc991b915 --- /dev/null +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr @@ -0,0 +1,27 @@ +error[E0609]: no field `c` on type `Foo` + --> $DIR/non-existent-field-present-in-subfield.rs:37:24 + | +LL | let _test = &fooer.c; + | ^ unknown field + | + = note: available fields are: `first`, `_second`, `_third` +help: one of the expressions' fields has a field of the same name + | +LL | let _test = &fooer.first.bar.c; + | ++++++++++ + +error[E0609]: no field `test` on type `Foo` + --> $DIR/non-existent-field-present-in-subfield.rs:40:24 + | +LL | let _test2 = fooer.test; + | ^^^^ unknown field + | + = note: available fields are: `first`, `_second`, `_third` +help: one of the expressions' fields has a field of the same name + | +LL | let _test2 = fooer.first.bar.c.test; + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.rs b/tests/ui/suggestions/object-unsafe-trait-references-self.rs new file mode 100644 index 000000000..07bf053e9 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-references-self.rs @@ -0,0 +1,12 @@ +trait Trait { + fn baz(&self, _: Self) {} + fn bat(&self) -> Self {} +} + +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object + +trait Other: Sized {} + +fn foo(x: &dyn Other) {} //~ ERROR the trait `Other` cannot be made into an object + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.stderr b/tests/ui/suggestions/object-unsafe-trait-references-self.stderr new file mode 100644 index 000000000..54f19fe9d --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-references-self.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/object-unsafe-trait-references-self.rs:6:12 + | +LL | fn bar(x: &dyn Trait) {} + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-references-self.rs:2:22 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | fn baz(&self, _: Self) {} + | ^^^^ ...because method `baz` references the `Self` type in this parameter +LL | fn bat(&self) -> Self {} + | ^^^^ ...because method `bat` references the `Self` type in its return type + = help: consider moving `baz` to another trait + = help: consider moving `bat` to another trait + +error[E0038]: the trait `Other` cannot be made into an object + --> $DIR/object-unsafe-trait-references-self.rs:10:12 + | +LL | fn foo(x: &dyn Other) {} + | ^^^^^^^^^ `Other` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-references-self.rs:8:14 + | +LL | trait Other: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs new file mode 100644 index 000000000..75f99075e --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs @@ -0,0 +1,16 @@ +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: A) -> A; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: B) -> B; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: C) -> C; +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr new file mode 100644 index 000000000..55047b426 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr @@ -0,0 +1,65 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + | +LL | fn f(a: A) -> A; + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self.rs:2:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + | +LL | fn f(a: B) -> B; + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-self.rs:8:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: B) -> B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: B) -> B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: B) -> B where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed new file mode 100644 index 000000000..69487c565 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed @@ -0,0 +1,13 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] + +trait Trait { + fn foo(&self) where Self: Other, Self: Sized { } + fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type +} + +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object + +trait Other {} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs new file mode 100644 index 000000000..38d9aea16 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs @@ -0,0 +1,13 @@ +// run-rustfix +#![allow(unused_variables, dead_code)] + +trait Trait { + fn foo() where Self: Other, { } + fn bar(self: ()) {} //~ ERROR invalid `self` parameter type +} + +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object + +trait Other {} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr new file mode 100644 index 000000000..c0dc71df0 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr @@ -0,0 +1,41 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 + | +LL | fn bar(x: &dyn Trait) {} + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | fn foo() where Self: Other, { } + | ^^^ ...because associated function `foo` has no `self` parameter +LL | fn bar(self: ()) {} + | ^^ ...because method `bar`'s `self` parameter cannot be dispatched on +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) where Self: Other, { } + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Other, Self: Sized { } + | ~~~~~~~~~~~~~ +help: consider changing method `bar`'s `self` parameter to be `&self` + | +LL | fn bar(self: &Self) {} + | ~~~~~ + +error[E0307]: invalid `self` parameter type: () + --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 + | +LL | fn bar(self: ()) {} + | ^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0307. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/opaque-type-error.rs b/tests/ui/suggestions/opaque-type-error.rs new file mode 100644 index 000000000..5e1147403 --- /dev/null +++ b/tests/ui/suggestions/opaque-type-error.rs @@ -0,0 +1,24 @@ +// edition:2018 +use core::future::Future; + +async fn base_thing() -> Result<(), ()> { + Ok(()) +} + +fn thing_one() -> impl Future> { + base_thing() +} + +fn thing_two() -> impl Future> { + base_thing() +} + +async fn thing() -> Result<(), ()> { + if true { + thing_one() + } else { + thing_two() //~ ERROR `if` and `else` have incompatible types + }.await +} + +fn main() {} diff --git a/tests/ui/suggestions/opaque-type-error.stderr b/tests/ui/suggestions/opaque-type-error.stderr new file mode 100644 index 000000000..133ffb058 --- /dev/null +++ b/tests/ui/suggestions/opaque-type-error.stderr @@ -0,0 +1,31 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/opaque-type-error.rs:20:9 + | +LL | fn thing_one() -> impl Future> { + | ------------------------------------ the expected opaque type +... +LL | fn thing_two() -> impl Future> { + | ------------------------------------ the found opaque type +... +LL | / if true { +LL | | thing_one() + | | ----------- expected because of this +LL | | } else { +LL | | thing_two() + | | ^^^^^^^^^^^ expected opaque type, found a different opaque type +LL | | }.await + | |_____- `if` and `else` have incompatible types + | + = note: expected opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:8:19>) + found opaque type `impl Future>` (opaque type at <$DIR/opaque-type-error.rs:12:19>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ thing_one().await +LL | } else { +LL ~ thing_two().await + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/option-content-move-from-tuple-match.rs b/tests/ui/suggestions/option-content-move-from-tuple-match.rs new file mode 100644 index 000000000..7f22d8136 --- /dev/null +++ b/tests/ui/suggestions/option-content-move-from-tuple-match.rs @@ -0,0 +1,9 @@ +fn foo(a: &Option, b: &Option) { + match (a, b) { + //~^ ERROR cannot move out of a shared reference + (None, &c) => &c.unwrap(), + (&Some(ref c), _) => c, + }; +} + +fn main() {} diff --git a/tests/ui/suggestions/option-content-move-from-tuple-match.stderr b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr new file mode 100644 index 000000000..97d05d9dc --- /dev/null +++ b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr @@ -0,0 +1,20 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/option-content-move-from-tuple-match.rs:2:11 + | +LL | match (a, b) { + | ^^^^^^ +LL | +LL | (None, &c) => &c.unwrap(), + | - + | | + | data moved here + | move occurs because `c` has type `Option`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (None, &ref c) => &c.unwrap(), + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs new file mode 100644 index 000000000..46c895b95 --- /dev/null +++ b/tests/ui/suggestions/option-content-move.rs @@ -0,0 +1,37 @@ +pub struct LipogramCorpora { + selections: Vec<(char, Option)>, +} + +impl LipogramCorpora { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_some() { + if selection.1.unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +pub struct LipogramCorpora2 { + selections: Vec<(char, Result)>, +} + +impl LipogramCorpora2 { + pub fn validate_all(&mut self) -> Result<(), char> { + for selection in &self.selections { + if selection.1.is_ok() { + if selection.1.unwrap().contains(selection.0) { + //~^ ERROR cannot move out of `selection.1` + return Err(selection.0); + } + } + } + Ok(()) + } +} + +fn main() {} diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr new file mode 100644 index 000000000..474a72093 --- /dev/null +++ b/tests/ui/suggestions/option-content-move.stderr @@ -0,0 +1,35 @@ +error[E0507]: cannot move out of `selection.1` which is behind a shared reference + --> $DIR/option-content-move.rs:9:20 + | +LL | if selection.1.unwrap().contains(selection.0) { + | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call + | | + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents + | move occurs because `selection.1` has type `Option`, which does not implement the `Copy` trait + | +note: `Option::::unwrap` takes ownership of the receiver `self`, which moves `selection.1` + --> $SRC_DIR/core/src/option.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | if selection.1.clone().unwrap().contains(selection.0) { + | ++++++++ + +error[E0507]: cannot move out of `selection.1` which is behind a shared reference + --> $DIR/option-content-move.rs:27:20 + | +LL | if selection.1.unwrap().contains(selection.0) { + | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call + | | + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents + | move occurs because `selection.1` has type `Result`, which does not implement the `Copy` trait + | +note: `Result::::unwrap` takes ownership of the receiver `self`, which moves `selection.1` + --> $SRC_DIR/core/src/result.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | if selection.1.clone().unwrap().contains(selection.0) { + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/option-content-move2.rs b/tests/ui/suggestions/option-content-move2.rs new file mode 100644 index 000000000..88e8a5b7a --- /dev/null +++ b/tests/ui/suggestions/option-content-move2.rs @@ -0,0 +1,16 @@ +struct NotCopyable; + +fn func H, H: FnMut()>(_: F) {} + +fn parse() { + let mut var = None; + func(|| { + // Shouldn't suggest `move ||.as_ref()` here + move || { + //~^ ERROR: cannot move out of `var` + var = Some(NotCopyable); + } + }); +} + +fn main() {} diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr new file mode 100644 index 000000000..1d3dff3be --- /dev/null +++ b/tests/ui/suggestions/option-content-move2.stderr @@ -0,0 +1,20 @@ +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move2.rs:9:9 + | +LL | let mut var = None; + | ------- captured outer variable +LL | func(|| { + | -- captured by this `FnMut` closure +LL | // Shouldn't suggest `move ||.as_ref()` here +LL | move || { + | ^^^^^^^ move out of `var` occurs here +LL | +LL | var = Some(NotCopyable); + | --- + | | + | variable moved due to use in closure + | move occurs because `var` has type `Option`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/option-to-bool.rs b/tests/ui/suggestions/option-to-bool.rs new file mode 100644 index 000000000..2a1823b15 --- /dev/null +++ b/tests/ui/suggestions/option-to-bool.rs @@ -0,0 +1,9 @@ +#![cfg_attr(let_chains, feature(let_chains))] + +fn foo(x: Option) { + if true && x {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value +} + +fn main() {} diff --git a/tests/ui/suggestions/option-to-bool.stderr b/tests/ui/suggestions/option-to-bool.stderr new file mode 100644 index 000000000..4050c7be8 --- /dev/null +++ b/tests/ui/suggestions/option-to-bool.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/option-to-bool.rs:4:16 + | +LL | if true && x {} + | ---- ^ expected `bool`, found enum `Option` + | | + | expected because this is `bool` + | + = note: expected type `bool` + found enum `Option` +help: use `Option::is_some` to test if the `Option` has a value + | +LL | if true && x.is_some() {} + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.rs b/tests/ui/suggestions/parenthesized-deref-suggestion.rs new file mode 100644 index 000000000..0b4ccdd5a --- /dev/null +++ b/tests/ui/suggestions/parenthesized-deref-suggestion.rs @@ -0,0 +1,11 @@ +struct Session { + opts: u8, +} + +fn main() { + let sess: &Session = &Session { opts: 0 }; + (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session` + + let x = [0u32]; + (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]` +} diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr new file mode 100644 index 000000000..cafddbe26 --- /dev/null +++ b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr @@ -0,0 +1,22 @@ +error[E0609]: no field `opts` on type `*const Session` + --> $DIR/parenthesized-deref-suggestion.rs:7:30 + | +LL | (sess as *const Session).opts; + | ^^^^ + | +help: `(sess as *const Session)` is a raw pointer; try dereferencing it + | +LL | (*(sess as *const Session)).opts; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0609]: no field `0` on type `[u32; 1]` + --> $DIR/parenthesized-deref-suggestion.rs:10:21 + | +LL | (x as [u32; 1]).0; + | ----------------^ + | | + | help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/path-by-value.rs b/tests/ui/suggestions/path-by-value.rs new file mode 100644 index 000000000..c875ca674 --- /dev/null +++ b/tests/ui/suggestions/path-by-value.rs @@ -0,0 +1,6 @@ +use std::path::Path; + +fn f(p: Path) { } +//~^ ERROR E0277 + +fn main() {} diff --git a/tests/ui/suggestions/path-by-value.stderr b/tests/ui/suggestions/path-by-value.stderr new file mode 100644 index 000000000..bbeaa26a9 --- /dev/null +++ b/tests/ui/suggestions/path-by-value.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/path-by-value.rs:3:6 + | +LL | fn f(p: Path) { } + | ^ doesn't have a size known at compile-time + | + = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `Path` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn f(p: &Path) { } + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/path-display.rs b/tests/ui/suggestions/path-display.rs new file mode 100644 index 000000000..3a022e6b0 --- /dev/null +++ b/tests/ui/suggestions/path-display.rs @@ -0,0 +1,11 @@ +use std::path::{Path, PathBuf}; + +fn main() { + let path = Path::new("/tmp/foo/bar.txt"); + println!("{}", path); + //~^ ERROR E0277 + + let path = PathBuf::from("/tmp/foo/bar.txt"); + println!("{}", path); + //~^ ERROR E0277 +} diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr new file mode 100644 index 000000000..8359b3658 --- /dev/null +++ b/tests/ui/suggestions/path-display.stderr @@ -0,0 +1,23 @@ +error[E0277]: `Path` doesn't implement `std::fmt::Display` + --> $DIR/path-display.rs:5:20 + | +LL | println!("{}", path); + | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it + | + = help: the trait `std::fmt::Display` is not implemented for `Path` + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `PathBuf` doesn't implement `std::fmt::Display` + --> $DIR/path-display.rs:9:20 + | +LL | println!("{}", path); + | ^^^^ `PathBuf` cannot be formatted with the default formatter; call `.display()` on it + | + = help: the trait `std::fmt::Display` is not implemented for `PathBuf` + = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/pattern-slice-vec.fixed b/tests/ui/suggestions/pattern-slice-vec.fixed new file mode 100644 index 000000000..f8144641f --- /dev/null +++ b/tests/ui/suggestions/pattern-slice-vec.fixed @@ -0,0 +1,31 @@ +// Regression test for #87017. + +// run-rustfix + +fn main() { + fn foo() -> Vec { vec![1, 2, 3] } + + if let [_, _, _] = foo()[..] {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = &foo()[..] {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = foo()[..] {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + let v = vec![]; + match &v[..] { + //~^ HELP: consider slicing here + [5] => {} + //~^ ERROR: expected an array or slice + _ => {} + } + + let [..] = vec![1, 2, 3][..]; + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here +} diff --git a/tests/ui/suggestions/pattern-slice-vec.rs b/tests/ui/suggestions/pattern-slice-vec.rs new file mode 100644 index 000000000..444687c85 --- /dev/null +++ b/tests/ui/suggestions/pattern-slice-vec.rs @@ -0,0 +1,31 @@ +// Regression test for #87017. + +// run-rustfix + +fn main() { + fn foo() -> Vec { vec![1, 2, 3] } + + if let [_, _, _] = foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = &foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + if let [] = foo() {} + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here + + let v = vec![]; + match &v { + //~^ HELP: consider slicing here + [5] => {} + //~^ ERROR: expected an array or slice + _ => {} + } + + let [..] = vec![1, 2, 3]; + //~^ ERROR: expected an array or slice + //~| HELP: consider slicing here +} diff --git a/tests/ui/suggestions/pattern-slice-vec.stderr b/tests/ui/suggestions/pattern-slice-vec.stderr new file mode 100644 index 000000000..f69e7de97 --- /dev/null +++ b/tests/ui/suggestions/pattern-slice-vec.stderr @@ -0,0 +1,44 @@ +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/pattern-slice-vec.rs:8:12 + | +LL | if let [_, _, _] = foo() {} + | ^^^^^^^^^ ----- help: consider slicing here: `foo()[..]` + | | + | pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/pattern-slice-vec.rs:12:12 + | +LL | if let [] = &foo() {} + | ^^ ------ help: consider slicing here: `&foo()[..]` + | | + | pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/pattern-slice-vec.rs:16:12 + | +LL | if let [] = foo() {} + | ^^ ----- help: consider slicing here: `foo()[..]` + | | + | pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec<_>` + --> $DIR/pattern-slice-vec.rs:23:9 + | +LL | match &v { + | -- help: consider slicing here: `&v[..]` +LL | +LL | [5] => {} + | ^^^ pattern cannot match with input type `Vec<_>` + +error[E0529]: expected an array or slice, found `Vec<{integer}>` + --> $DIR/pattern-slice-vec.rs:28:9 + | +LL | let [..] = vec![1, 2, 3]; + | ^^^^ ------------- help: consider slicing here: `vec![1, 2, 3][..]` + | | + | pattern cannot match with input type `Vec<{integer}>` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs new file mode 100644 index 000000000..5b223a91f --- /dev/null +++ b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.rs @@ -0,0 +1,35 @@ +use std::ops::Deref; + +struct Foo { + v: Vec, +} + +struct Bar { + v: Vec, +} + +impl Deref for Bar { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.v + } +} + +fn f(foo: &Foo) { + match foo { + Foo { v: [1, 2] } => {} + //~^ ERROR expected an array or slice, found `Vec + _ => {} + } +} + +fn bar(bar: &Bar) { + match bar { + Bar { v: [1, 2] } => {} + //~^ ERROR expected an array or slice, found `Vec + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr new file mode 100644 index 000000000..5b48a8b18 --- /dev/null +++ b/tests/ui/suggestions/pattern-struct-with-slice-vec-field.stderr @@ -0,0 +1,15 @@ +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/pattern-struct-with-slice-vec-field.rs:21:18 + | +LL | Foo { v: [1, 2] } => {} + | ^^^^^^ pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/pattern-struct-with-slice-vec-field.rs:29:18 + | +LL | Bar { v: [1, 2] } => {} + | ^^^^^^ pattern cannot match with input type `Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/suggestions/private-field.rs b/tests/ui/suggestions/private-field.rs new file mode 100644 index 000000000..1cc4d2a4d --- /dev/null +++ b/tests/ui/suggestions/private-field.rs @@ -0,0 +1,19 @@ +// compile-flags: --crate-type lib +pub struct S { + pub val: string::MyString, +} + +pub fn test(s: S) { + dbg!(s.cap) //~ ERROR: no field `cap` on type `S` [E0609] +} + +pub(crate) mod string { + + pub struct MyString { + buf: MyVec, + } + + struct MyVec { + cap: usize, + } +} diff --git a/tests/ui/suggestions/private-field.stderr b/tests/ui/suggestions/private-field.stderr new file mode 100644 index 000000000..c38c795e0 --- /dev/null +++ b/tests/ui/suggestions/private-field.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `cap` on type `S` + --> $DIR/private-field.rs:7:12 + | +LL | dbg!(s.cap) + | ^^^ unknown field + | + = note: available fields are: `val` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/raw-byte-string-prefix.rs b/tests/ui/suggestions/raw-byte-string-prefix.rs new file mode 100644 index 000000000..576561c31 --- /dev/null +++ b/tests/ui/suggestions/raw-byte-string-prefix.rs @@ -0,0 +1,10 @@ +// `br` and `rb` are easy to confuse; check that we issue a suggestion to help. + +// edition:2021 + +fn main() { + rb"abc"; + //~^ ERROR: prefix `rb` is unknown + //~| HELP: use `br` for a raw byte string + //~| ERROR: expected one of +} diff --git a/tests/ui/suggestions/raw-byte-string-prefix.stderr b/tests/ui/suggestions/raw-byte-string-prefix.stderr new file mode 100644 index 000000000..4f5106849 --- /dev/null +++ b/tests/ui/suggestions/raw-byte-string-prefix.stderr @@ -0,0 +1,20 @@ +error: prefix `rb` is unknown + --> $DIR/raw-byte-string-prefix.rs:6:5 + | +LL | rb"abc"; + | ^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: use `br` for a raw byte string + | +LL | br"abc"; + | ~~ + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"abc"` + --> $DIR/raw-byte-string-prefix.rs:6:7 + | +LL | rb"abc"; + | ^^^^^ expected one of 8 possible tokens + +error: aborting due to 2 previous errors + diff --git a/tests/ui/suggestions/raw-name-use-suggestion.rs b/tests/ui/suggestions/raw-name-use-suggestion.rs new file mode 100644 index 000000000..0a8073c0b --- /dev/null +++ b/tests/ui/suggestions/raw-name-use-suggestion.rs @@ -0,0 +1,9 @@ +mod foo { + pub fn r#let() {} + pub fn break() {} //~ ERROR expected identifier, found keyword `break` +} + +fn main() { + foo::let(); //~ ERROR expected identifier, found keyword `let` + r#break(); //~ ERROR cannot find function `r#break` in this scope +} diff --git a/tests/ui/suggestions/raw-name-use-suggestion.stderr b/tests/ui/suggestions/raw-name-use-suggestion.stderr new file mode 100644 index 000000000..95c26b9ad --- /dev/null +++ b/tests/ui/suggestions/raw-name-use-suggestion.stderr @@ -0,0 +1,36 @@ +error: expected identifier, found keyword `break` + --> $DIR/raw-name-use-suggestion.rs:3:12 + | +LL | pub fn break() {} + | ^^^^^ expected identifier, found keyword + | +help: escape `break` to use it as an identifier + | +LL | pub fn r#break() {} + | ++ + +error: expected identifier, found keyword `let` + --> $DIR/raw-name-use-suggestion.rs:7:10 + | +LL | foo::let(); + | ^^^ expected identifier, found keyword + | +help: escape `let` to use it as an identifier + | +LL | foo::r#let(); + | ++ + +error[E0425]: cannot find function `r#break` in this scope + --> $DIR/raw-name-use-suggestion.rs:8:5 + | +LL | r#break(); + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use foo::r#break; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/recover-from-semicolon-trailing-item.rs b/tests/ui/suggestions/recover-from-semicolon-trailing-item.rs new file mode 100644 index 000000000..82935af0a --- /dev/null +++ b/tests/ui/suggestions/recover-from-semicolon-trailing-item.rs @@ -0,0 +1,16 @@ +// verify that after encountering a semicolon after an item the parser recovers +mod M {}; +//~^ ERROR expected item, found `;` +struct S {}; +//~^ ERROR expected item, found `;` +fn foo(a: usize) {}; +//~^ ERROR expected item, found `;` +fn main() { + struct X {}; // ok + let _: usize = S {}; + //~^ ERROR mismatched types + let _: usize = X {}; + //~^ ERROR mismatched types + foo(""); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr new file mode 100644 index 000000000..9588eedc9 --- /dev/null +++ b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr @@ -0,0 +1,53 @@ +error: expected item, found `;` + --> $DIR/recover-from-semicolon-trailing-item.rs:2:9 + | +LL | mod M {}; + | ^ help: remove this semicolon + +error: expected item, found `;` + --> $DIR/recover-from-semicolon-trailing-item.rs:4:12 + | +LL | struct S {}; + | ^ help: remove this semicolon + | + = help: braced struct declarations are not followed by a semicolon + +error: expected item, found `;` + --> $DIR/recover-from-semicolon-trailing-item.rs:6:20 + | +LL | fn foo(a: usize) {}; + | ^ help: remove this semicolon + +error[E0308]: mismatched types + --> $DIR/recover-from-semicolon-trailing-item.rs:10:20 + | +LL | let _: usize = S {}; + | ----- ^^^^ expected `usize`, found struct `S` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/recover-from-semicolon-trailing-item.rs:12:20 + | +LL | let _: usize = X {}; + | ----- ^^^^ expected `usize`, found struct `X` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/recover-from-semicolon-trailing-item.rs:14:9 + | +LL | foo(""); + | --- ^^ expected `usize`, found `&str` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/recover-from-semicolon-trailing-item.rs:6:4 + | +LL | fn foo(a: usize) {}; + | ^^^ -------- + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/recover-invalid-float.fixed b/tests/ui/suggestions/recover-invalid-float.fixed new file mode 100644 index 000000000..62389ba61 --- /dev/null +++ b/tests/ui/suggestions/recover-invalid-float.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _: f32 = 0.3; + //~^ ERROR float literals must have an integer part + let _: f32 = 0.42f32; + //~^ ERROR float literals must have an integer part + let _: f64 = 0.5f64; + //~^ ERROR float literals must have an integer part +} diff --git a/tests/ui/suggestions/recover-invalid-float.rs b/tests/ui/suggestions/recover-invalid-float.rs new file mode 100644 index 000000000..a5a7efe5e --- /dev/null +++ b/tests/ui/suggestions/recover-invalid-float.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _: f32 = .3; + //~^ ERROR float literals must have an integer part + let _: f32 = .42f32; + //~^ ERROR float literals must have an integer part + let _: f64 = .5f64; + //~^ ERROR float literals must have an integer part +} diff --git a/tests/ui/suggestions/recover-invalid-float.stderr b/tests/ui/suggestions/recover-invalid-float.stderr new file mode 100644 index 000000000..dd24746ea --- /dev/null +++ b/tests/ui/suggestions/recover-invalid-float.stderr @@ -0,0 +1,20 @@ +error: float literals must have an integer part + --> $DIR/recover-invalid-float.rs:4:18 + | +LL | let _: f32 = .3; + | ^^ help: must have an integer part: `0.3` + +error: float literals must have an integer part + --> $DIR/recover-invalid-float.rs:6:18 + | +LL | let _: f32 = .42f32; + | ^^^^^^ help: must have an integer part: `0.42f32` + +error: float literals must have an integer part + --> $DIR/recover-invalid-float.rs:8:18 + | +LL | let _: f64 = .5f64; + | ^^^^^ help: must have an integer part: `0.5f64` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs new file mode 100644 index 000000000..333dce390 --- /dev/null +++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs @@ -0,0 +1,10 @@ +fn main() { + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>(); + //~^ ERROR generic parameters without surrounding angle brackets + let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); + //~^ ERROR generic parameters without surrounding angle brackets +} diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr new file mode 100644 index 000000000..618ccba0d --- /dev/null +++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr @@ -0,0 +1,46 @@ +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:2:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | + + + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:4:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | + ~ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:6:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | + ~ + +error: generic parameters without surrounding angle brackets + --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:8:48 + | +LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); + | ^^^^^^ + | +help: surround the type parameters with angle brackets + | +LL | let _ = vec![1, 2, 3].into_iter().collect::>(); + | + ~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/suggestions/ref-pattern-binding.fixed b/tests/ui/suggestions/ref-pattern-binding.fixed new file mode 100644 index 000000000..c36040eec --- /dev/null +++ b/tests/ui/suggestions/ref-pattern-binding.fixed @@ -0,0 +1,19 @@ +// run-rustfix +#![allow(unused)] + +struct S { + f: String, +} + +fn main() { + let ref _moved @ ref _from = String::from("foo"); //~ ERROR + let ref _moved @ ref _from = String::from("foo"); //~ ERROR + let ref _moved @ ref _from = String::from("foo"); //~ ERROR + //~^ ERROR + let ref _moved @ ref _from = String::from("foo"); // ok + let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR + let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR + //~^ ERROR + let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok + let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR +} diff --git a/tests/ui/suggestions/ref-pattern-binding.rs b/tests/ui/suggestions/ref-pattern-binding.rs new file mode 100644 index 000000000..c0d4feb03 --- /dev/null +++ b/tests/ui/suggestions/ref-pattern-binding.rs @@ -0,0 +1,19 @@ +// run-rustfix +#![allow(unused)] + +struct S { + f: String, +} + +fn main() { + let _moved @ _from = String::from("foo"); //~ ERROR + let _moved @ ref _from = String::from("foo"); //~ ERROR + let ref _moved @ _from = String::from("foo"); //~ ERROR + //~^ ERROR + let ref _moved @ ref _from = String::from("foo"); // ok + let _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR + let ref _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR + //~^ ERROR + let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok + let _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR +} diff --git a/tests/ui/suggestions/ref-pattern-binding.stderr b/tests/ui/suggestions/ref-pattern-binding.stderr new file mode 100644 index 000000000..10447ba70 --- /dev/null +++ b/tests/ui/suggestions/ref-pattern-binding.stderr @@ -0,0 +1,107 @@ +error: borrow of moved value + --> $DIR/ref-pattern-binding.rs:10:9 + | +LL | let _moved @ ref _from = String::from("foo"); + | ------^^^--------- + | | | + | | value borrowed here after move + | value moved into `_moved` here + | move occurs because `_moved` has type `String` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ + +error: cannot move out of value because it is borrowed + --> $DIR/ref-pattern-binding.rs:11:9 + | +LL | let ref _moved @ _from = String::from("foo"); + | ----------^^^----- + | | | + | | value moved into `_from` here + | value borrowed, by `_moved`, here + +error: cannot move out of value because it is borrowed + --> $DIR/ref-pattern-binding.rs:15:9 + | +LL | let ref _moved @ S { f } = S { f: String::from("foo") }; + | ----------^^^^^^^-^^ + | | | + | | value moved into `f` here + | value borrowed, by `_moved`, here + +error: borrow of moved value + --> $DIR/ref-pattern-binding.rs:18:9 + | +LL | let _moved @ S { ref f } = S { f: String::from("foo") }; + | ------^^^^^^^-----^^ + | | | + | | value borrowed here after move + | value moved into `_moved` here + | move occurs because `_moved` has type `S` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ S { ref f } = S { f: String::from("foo") }; + | +++ + +error[E0382]: use of moved value + --> $DIR/ref-pattern-binding.rs:9:9 + | +LL | let _moved @ _from = String::from("foo"); + | ^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait + | | | + | | value moved here + | value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ +++ + +error[E0382]: borrow of moved value + --> $DIR/ref-pattern-binding.rs:11:9 + | +LL | let ref _moved @ _from = String::from("foo"); + | ^^^^^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait + | | | + | | value moved here + | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ + +error[E0382]: use of partially moved value + --> $DIR/ref-pattern-binding.rs:14:9 + | +LL | let _moved @ S { f } = S { f: String::from("foo") }; + | ^^^^^^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ S { ref f } = S { f: String::from("foo") }; + | +++ +++ + +error[E0382]: borrow of partially moved value + --> $DIR/ref-pattern-binding.rs:15:9 + | +LL | let ref _moved @ S { f } = S { f: String::from("foo") }; + | ^^^^^^^^^^ - value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ S { ref f } = S { f: String::from("foo") }; + | +++ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs new file mode 100644 index 000000000..56aed77c1 --- /dev/null +++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.rs @@ -0,0 +1,30 @@ +struct Wrapper(T); + +fn foo(foo: Wrapper) +//~^ ERROR the size for values of type `T` cannot be known at compilation time +where + T + : + ? + Sized +{ + // +} + +fn bar(foo: Wrapper) +//~^ ERROR the size for values of type `T` cannot be known at compilation time +where T: ?Sized +{ + // +} + +fn qux(foo: Wrapper) +//~^ ERROR the size for values of type `T` cannot be known at compilation time +where + T: ?Sized +{ + // +} + + +fn main() {} diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr new file mode 100644 index 000000000..6071b10d3 --- /dev/null +++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr @@ -0,0 +1,83 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:3:16 + | +LL | fn foo(foo: Wrapper) + | - ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Wrapper` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper(T); + | ^ required by this bound in `Wrapper` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper(T); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - where +LL - T +LL - : +LL - ? +LL - Sized + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:14:16 + | +LL | fn bar(foo: Wrapper) + | - ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Wrapper` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper(T); + | ^ required by this bound in `Wrapper` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper(T); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - where T: ?Sized + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:21:16 + | +LL | fn qux(foo: Wrapper) + | - ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Wrapper` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper(T); + | ^ required by this bound in `Wrapper` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 + | +LL | struct Wrapper(T); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - where +LL - T: ?Sized + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/remove-as_str.rs b/tests/ui/suggestions/remove-as_str.rs new file mode 100644 index 000000000..289a784ba --- /dev/null +++ b/tests/ui/suggestions/remove-as_str.rs @@ -0,0 +1,21 @@ +fn foo1(s: &str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn foo2<'a>(s: &'a str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn foo3(s: &mut str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn foo4(s: &&str) { + s.as_str(); + //~^ ERROR no method named `as_str` found +} + +fn main() {} diff --git a/tests/ui/suggestions/remove-as_str.stderr b/tests/ui/suggestions/remove-as_str.stderr new file mode 100644 index 000000000..534c49778 --- /dev/null +++ b/tests/ui/suggestions/remove-as_str.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `as_str` found for reference `&str` in the current scope + --> $DIR/remove-as_str.rs:2:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error[E0599]: no method named `as_str` found for reference `&'a str` in the current scope + --> $DIR/remove-as_str.rs:7:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error[E0599]: no method named `as_str` found for mutable reference `&mut str` in the current scope + --> $DIR/remove-as_str.rs:12:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error[E0599]: no method named `as_str` found for reference `&&str` in the current scope + --> $DIR/remove-as_str.rs:17:7 + | +LL | s.as_str(); + | -^^^^^^-- help: remove this method call + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/restrict-type-argument.rs b/tests/ui/suggestions/restrict-type-argument.rs new file mode 100644 index 000000000..c4ebfbe92 --- /dev/null +++ b/tests/ui/suggestions/restrict-type-argument.rs @@ -0,0 +1,31 @@ +fn is_send(val: T) {} + +fn use_impl_sync(val: impl Sync) { + is_send(val); //~ ERROR `impl Sync` cannot be sent between threads safely +} + +fn use_where(val: S) where S: Sync { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound_2< + S // Make sure we can synthezise a correct suggestion span for this case + : + Sync +>(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound_and_where(val: S) where S: std::fmt::Debug { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_unbound(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn main() {} diff --git a/tests/ui/suggestions/restrict-type-argument.stderr b/tests/ui/suggestions/restrict-type-argument.stderr new file mode 100644 index 000000000..01c2de798 --- /dev/null +++ b/tests/ui/suggestions/restrict-type-argument.stderr @@ -0,0 +1,111 @@ +error[E0277]: `impl Sync` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:4:13 + | +LL | is_send(val); + | ------- ^^^ `impl Sync` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_impl_sync(val: impl Sync + std::marker::Send) { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:8:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_where(val: S) where S: Sync + std::marker::Send { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:12:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_bound(val: S) { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:20:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | Sync + std::marker::Send + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:24:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider further restricting this bound + | +LL | fn use_bound_and_where(val: S) where S: std::fmt::Debug { + | +++++++++++++++++++ + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:28:13 + | +LL | is_send(val); + | ------- ^^^ `S` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | +note: required by a bound in `is_send` + --> $DIR/restrict-type-argument.rs:1:15 + | +LL | fn is_send(val: T) {} + | ^^^^ required by this bound in `is_send` +help: consider restricting type parameter `S` + | +LL | fn use_unbound(val: S) { + | +++++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/restrict-type-not-param.rs b/tests/ui/suggestions/restrict-type-not-param.rs new file mode 100644 index 000000000..60f5ba45c --- /dev/null +++ b/tests/ui/suggestions/restrict-type-not-param.rs @@ -0,0 +1,12 @@ +use std::ops::Add; + +struct Wrapper(T); + +trait Foo {} + +fn qux(a: Wrapper, b: T) -> T { + a + b + //~^ ERROR cannot add `T` to `Wrapper` +} + +fn main() {} diff --git a/tests/ui/suggestions/restrict-type-not-param.stderr b/tests/ui/suggestions/restrict-type-not-param.stderr new file mode 100644 index 000000000..5434472ce --- /dev/null +++ b/tests/ui/suggestions/restrict-type-not-param.stderr @@ -0,0 +1,23 @@ +error[E0369]: cannot add `T` to `Wrapper` + --> $DIR/restrict-type-not-param.rs:8:7 + | +LL | a + b + | - ^ - T + | | + | Wrapper + | +note: an implementation of `Add<_>` might be missing for `Wrapper` + --> $DIR/restrict-type-not-param.rs:3:1 + | +LL | struct Wrapper(T); + | ^^^^^^^^^^^^^^^^^ must implement `Add<_>` +note: the trait `Add` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn qux(a: Wrapper, b: T) -> T where Wrapper: Add { + | ++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/suggestions/return-bindings-multi.rs b/tests/ui/suggestions/return-bindings-multi.rs new file mode 100644 index 000000000..8c3bd641e --- /dev/null +++ b/tests/ui/suggestions/return-bindings-multi.rs @@ -0,0 +1,9 @@ +fn a(i: i32) -> i32 { + //~^ ERROR mismatched types + let j = 2i32; +} + +fn b(i: i32, j: i32) -> i32 {} +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/suggestions/return-bindings-multi.stderr b/tests/ui/suggestions/return-bindings-multi.stderr new file mode 100644 index 000000000..738e3f2f4 --- /dev/null +++ b/tests/ui/suggestions/return-bindings-multi.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/return-bindings-multi.rs:1:17 + | +LL | fn a(i: i32) -> i32 { + | - ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +note: consider returning one of these bindings + --> $DIR/return-bindings-multi.rs:1:6 + | +LL | fn a(i: i32) -> i32 { + | ^ +LL | +LL | let j = 2i32; + | ^ + +error[E0308]: mismatched types + --> $DIR/return-bindings-multi.rs:6:25 + | +LL | fn b(i: i32, j: i32) -> i32 {} + | - ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +note: consider returning one of these bindings + --> $DIR/return-bindings-multi.rs:6:6 + | +LL | fn b(i: i32, j: i32) -> i32 {} + | ^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/return-bindings.rs b/tests/ui/suggestions/return-bindings.rs new file mode 100644 index 000000000..fa1bad376 --- /dev/null +++ b/tests/ui/suggestions/return-bindings.rs @@ -0,0 +1,51 @@ +#![allow(unused)] + +fn a(i: i32) -> i32 {} +//~^ ERROR mismatched types + +fn b(opt_str: Option) { + let s: String = if let Some(s) = opt_str { + //~^ ERROR mismatched types + } else { + String::new() + }; +} + +fn c() -> Option { + //~^ ERROR mismatched types + let x = Some(1); +} + +fn d(opt_str: Option) { + let s: String = if let Some(s) = opt_str { + //~^ ERROR mismatched types + } else { + String::new() + }; +} + +fn d2(opt_str: Option) { + let s = if let Some(s) = opt_str { + } else { + String::new() + //~^ ERROR `if` and `else` have incompatible types + }; +} + +fn e(opt_str: Option) { + let s: String = match opt_str { + Some(s) => {} + //~^ ERROR mismatched types + None => String::new(), + }; +} + +fn e2(opt_str: Option) { + let s = match opt_str { + Some(s) => {} + None => String::new(), + //~^ ERROR `match` arms have incompatible types + }; +} + +fn main() {} diff --git a/tests/ui/suggestions/return-bindings.stderr b/tests/ui/suggestions/return-bindings.stderr new file mode 100644 index 000000000..c14fb3367 --- /dev/null +++ b/tests/ui/suggestions/return-bindings.stderr @@ -0,0 +1,110 @@ +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:3:17 + | +LL | fn a(i: i32) -> i32 {} + | - ^^^ expected `i32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +help: consider returning the local binding `i` + | +LL | fn a(i: i32) -> i32 { i } + | + + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:7:46 + | +LL | let s: String = if let Some(s) = opt_str { + | ______________________________________________^ +LL | | +LL | | } else { + | |_____^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL ~ let s: String = if let Some(s) = opt_str { +LL + s +LL ~ + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:14:11 + | +LL | fn c() -> Option { + | - ^^^^^^^^^^^ expected enum `Option`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Option` + found unit type `()` +help: consider returning the local binding `x` + | +LL ~ let x = Some(1); +LL + x + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:20:46 + | +LL | let s: String = if let Some(s) = opt_str { + | ______________________________________________^ +LL | | +LL | | } else { + | |_____^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL ~ let s: String = if let Some(s) = opt_str { +LL + s +LL ~ + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/return-bindings.rs:30:9 + | +LL | let s = if let Some(s) = opt_str { + | ______________________________________- +LL | | } else { + | |_____- expected because of this +LL | String::new() + | ^^^^^^^^^^^^^ expected `()`, found struct `String` + | +help: consider returning the local binding `s` + | +LL ~ let s = if let Some(s) = opt_str { +LL + s +LL ~ } else { + | + +error[E0308]: mismatched types + --> $DIR/return-bindings.rs:37:20 + | +LL | Some(s) => {} + | ^^ expected struct `String`, found `()` + | +help: consider returning the local binding `s` + | +LL | Some(s) => { s } + | + + +error[E0308]: `match` arms have incompatible types + --> $DIR/return-bindings.rs:46:17 + | +LL | let s = match opt_str { + | _____________- +LL | | Some(s) => {} + | | -- this is found to be of type `()` +LL | | None => String::new(), + | | ^^^^^^^^^^^^^ expected `()`, found struct `String` +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | +help: consider returning the local binding `s` + | +LL | Some(s) => { s } + | + + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/return-closures.rs b/tests/ui/suggestions/return-closures.rs new file mode 100644 index 000000000..86c7c1537 --- /dev/null +++ b/tests/ui/suggestions/return-closures.rs @@ -0,0 +1,13 @@ +fn foo() { + //~^ HELP try adding a return type + |x: &i32| 1i32 + //~^ ERROR mismatched types +} + +fn bar(i: impl Sized) { + //~^ HELP a return type might be missing here + || i + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr new file mode 100644 index 000000000..8b856d8de --- /dev/null +++ b/tests/ui/suggestions/return-closures.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/return-closures.rs:3:5 + | +LL | fn foo() { + | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` +LL | +LL | |x: &i32| 1i32 + | ^^^^^^^^^^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/return-closures.rs:3:5: 3:14]` + +error[E0308]: mismatched types + --> $DIR/return-closures.rs:9:5 + | +LL | fn bar(i: impl Sized) { + | - help: a return type might be missing here: `-> _` +LL | +LL | || i + | ^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/return-closures.rs:9:5: 9:7]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/return-cycle-2.rs b/tests/ui/suggestions/return-cycle-2.rs new file mode 100644 index 000000000..d6d24be1b --- /dev/null +++ b/tests/ui/suggestions/return-cycle-2.rs @@ -0,0 +1,14 @@ +use std::marker::PhantomData; + +struct Token(PhantomData); + +impl Token { + fn as_ref(_: i32, _: i32) -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + //~| NOTE not allowed in type signatures + //~| HELP replace with the correct return type + Token(PhantomData::<&T>) + } +} + +fn main() {} diff --git a/tests/ui/suggestions/return-cycle-2.stderr b/tests/ui/suggestions/return-cycle-2.stderr new file mode 100644 index 000000000..3a1a0f7f4 --- /dev/null +++ b/tests/ui/suggestions/return-cycle-2.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/return-cycle-2.rs:6:34 + | +LL | fn as_ref(_: i32, _: i32) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `Token<&'static T>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/return-cycle.rs b/tests/ui/suggestions/return-cycle.rs new file mode 100644 index 000000000..60b80e35a --- /dev/null +++ b/tests/ui/suggestions/return-cycle.rs @@ -0,0 +1,14 @@ +use std::marker::PhantomData; + +struct Token(PhantomData); + +impl Token { + fn new() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + //~| NOTE not allowed in type signatures + //~| HELP replace with the correct return type + Token(PhantomData::<()>) + } +} + +fn main() {} diff --git a/tests/ui/suggestions/return-cycle.stderr b/tests/ui/suggestions/return-cycle.stderr new file mode 100644 index 000000000..63fa9e040 --- /dev/null +++ b/tests/ui/suggestions/return-cycle.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/return-cycle.rs:6:17 + | +LL | fn new() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `Token<()>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/return-elided-lifetime.rs b/tests/ui/suggestions/return-elided-lifetime.rs new file mode 100644 index 000000000..012d5492a --- /dev/null +++ b/tests/ui/suggestions/return-elided-lifetime.rs @@ -0,0 +1,32 @@ +/* Checks all four scenarios possible in report_elision_failure() of + * rustc_resolve::late::lifetimes::LifetimeContext related to returning + * borrowed values, in various configurations. + */ + +fn f1() -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f1_() -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn f2(a: i32, b: i32) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +struct S<'a, 'b> { a: &'a i32, b: &'b i32 } +fn f3(s: &S) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } +//~^ ERROR missing lifetime specifier [E0106] +fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } +//~^ ERROR missing lifetime specifiers [E0106] + +fn main() {} diff --git a/tests/ui/suggestions/return-elided-lifetime.stderr b/tests/ui/suggestions/return-elided-lifetime.stderr new file mode 100644 index 000000000..273d95bc7 --- /dev/null +++ b/tests/ui/suggestions/return-elided-lifetime.stderr @@ -0,0 +1,143 @@ +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:6:12 + | +LL | fn f1() -> &i32 { loop {} } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f1() -> &'static i32 { loop {} } + | +++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:8:14 + | +LL | fn f1_() -> (&i32, &i32) { loop {} } + | ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f1_() -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:11:26 + | +LL | fn f2(a: i32, b: i32) -> &i32 { loop {} } + | ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f2(a: i32, b: i32) -> &'static i32 { loop {} } + | +++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:13:28 + | +LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} } + | ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn f2_(a: i32, b: i32) -> (&'static i32, &'static i32) { loop {} } + | +++++++ +++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:17:17 + | +LL | fn f3(s: &S) -> &i32 { loop {} } + | -- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `s`'s 3 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn f3<'a>(s: &'a S<'a, 'a>) -> &'a i32 { loop {} } + | ++++ ++ ++++++++ ++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:19:26 + | +LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } + | -- -- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `s`'s 3 lifetimes or one of `t`'s 3 lifetimes +help: consider introducing a named lifetime parameter + | +LL | fn f3_<'a>(s: &'a S<'a, 'a>, t: &'a S<'a, 'a>) -> (&'a i32, &'a i32) { loop {} } + | ++++ ++ ++++++++ ++ ++++++++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:22:42 + | +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } + | ------- ------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +note: these named lifetimes are available to use + --> $DIR/return-elided-lifetime.rs:22:7 + | +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} } + | +++++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:24:44 + | +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } + | ------- ------- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments +note: these named lifetimes are available to use + --> $DIR/return-elided-lifetime.rs:24:8 + | +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } + | ^^ ^^ +help: consider using one of the available lifetimes here + | +LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &'lifetime i32) { loop {} } + | +++++++++ +++++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-elided-lifetime.rs:27:35 + | +LL | fn f5<'a>(a: &'a i32, b: &i32) -> &i32 { loop {} } + | ------- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` +help: consider using the `'a` lifetime + | +LL | fn f5<'a>(a: &'a i32, b: &i32) -> &'a i32 { loop {} } + | ++ + +error[E0106]: missing lifetime specifiers + --> $DIR/return-elided-lifetime.rs:29:37 + | +LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&i32, &i32) { loop {} } + | ------- ---- ^ ^ expected named lifetime parameter + | | + | expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b` +help: consider using the `'a` lifetime + | +LL | fn f5_<'a>(a: &'a i32, b: &i32) -> (&'a i32, &'a i32) { loop {} } + | ++ ++ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/return-without-lifetime.rs b/tests/ui/suggestions/return-without-lifetime.rs new file mode 100644 index 000000000..9bfce11be --- /dev/null +++ b/tests/ui/suggestions/return-without-lifetime.rs @@ -0,0 +1,10 @@ +struct Thing<'a>(&'a ()); +struct Foo<'a>(&usize); +//~^ ERROR missing lifetime specifier + +fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } +//~^ ERROR missing lifetime specifier +fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } +//~^ ERROR missing lifetime specifier + +fn main() {} diff --git a/tests/ui/suggestions/return-without-lifetime.stderr b/tests/ui/suggestions/return-without-lifetime.stderr new file mode 100644 index 000000000..5028e8d62 --- /dev/null +++ b/tests/ui/suggestions/return-without-lifetime.stderr @@ -0,0 +1,38 @@ +error[E0106]: missing lifetime specifier + --> $DIR/return-without-lifetime.rs:2:16 + | +LL | struct Foo<'a>(&usize); + | ^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct Foo<'a>(&'a usize); + | ++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-without-lifetime.rs:5:34 + | +LL | fn func1<'a>(_arg: &'a Thing) -> &() { unimplemented!() } + | --------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from +help: consider using the `'a` lifetime + | +LL | fn func1<'a>(_arg: &'a Thing) -> &'a () { unimplemented!() } + | ++ + +error[E0106]: missing lifetime specifier + --> $DIR/return-without-lifetime.rs:7:35 + | +LL | fn func2<'a>(_arg: &Thing<'a>) -> &() { unimplemented!() } + | ---------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `_arg`'s 2 lifetimes it is borrowed from +help: consider using the `'a` lifetime + | +LL | fn func2<'a>(_arg: &Thing<'a>) -> &'a () { unimplemented!() } + | ++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/shadowed-lplace-method-2.rs b/tests/ui/suggestions/shadowed-lplace-method-2.rs new file mode 100644 index 000000000..dab99fbac --- /dev/null +++ b/tests/ui/suggestions/shadowed-lplace-method-2.rs @@ -0,0 +1,23 @@ +#![allow(unused)] + +struct X { + x: (), +} +pub trait A { + fn foo(&mut self, _: usize) -> &mut (); +} +impl A for X { + fn foo(&mut self, _: usize) -> &mut () { + &mut self.x + } +} +impl X { + fn foo(&mut self, _: usize) -> &mut Self { + self + } +} + +fn main() { + let mut x = X { x: () }; + *x.foo(0) = (); //~ ERROR E0308 +} diff --git a/tests/ui/suggestions/shadowed-lplace-method-2.stderr b/tests/ui/suggestions/shadowed-lplace-method-2.stderr new file mode 100644 index 000000000..94eef15f3 --- /dev/null +++ b/tests/ui/suggestions/shadowed-lplace-method-2.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/shadowed-lplace-method-2.rs:22:17 + | +LL | *x.foo(0) = (); + | --------- ^^ expected struct `X`, found `()` + | | + | expected due to the type of this binding + | +note: the `foo` call is resolved to the method in `X`, shadowing the method of the same name on trait `A` + --> $DIR/shadowed-lplace-method-2.rs:22:8 + | +LL | *x.foo(0) = (); + | ^^^ refers to `X::foo` +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL | *<_ as A>::foo(&mut x, 0) = (); + | ++++++++++++++++++ ~ +help: try wrapping the expression in `X` + | +LL | *x.foo(0) = X { x: () }; + | ++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/shadowed-lplace-method.fixed b/tests/ui/suggestions/shadowed-lplace-method.fixed new file mode 100644 index 000000000..740ac77ee --- /dev/null +++ b/tests/ui/suggestions/shadowed-lplace-method.fixed @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused_imports)] +use std::borrow::BorrowMut; +use std::cell::RefCell; +use std::rc::Rc; + +fn main() { + let rc = Rc::new(RefCell::new(true)); + *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308 +} diff --git a/tests/ui/suggestions/shadowed-lplace-method.rs b/tests/ui/suggestions/shadowed-lplace-method.rs new file mode 100644 index 000000000..6bf12879e --- /dev/null +++ b/tests/ui/suggestions/shadowed-lplace-method.rs @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused_imports)] +use std::borrow::BorrowMut; +use std::cell::RefCell; +use std::rc::Rc; + +fn main() { + let rc = Rc::new(RefCell::new(true)); + *rc.borrow_mut() = false; //~ ERROR E0308 +} diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr new file mode 100644 index 000000000..91d0d1200 --- /dev/null +++ b/tests/ui/suggestions/shadowed-lplace-method.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/shadowed-lplace-method.rs:9:24 + | +LL | *rc.borrow_mut() = false; + | ---------------- ^^^^^ expected struct `Rc`, found `bool` + | | + | expected due to the type of this binding + | + = note: expected struct `Rc>` + found type `bool` +note: the `borrow_mut` call is resolved to the method in `std::borrow::BorrowMut`, shadowing the method of the same name on the inherent impl for `std::cell::RefCell` + --> $DIR/shadowed-lplace-method.rs:9:9 + | +LL | use std::borrow::BorrowMut; + | ---------------------- `std::borrow::BorrowMut` imported here +... +LL | *rc.borrow_mut() = false; + | ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut` +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false; + | +++++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/slice-issue-87994.rs b/tests/ui/suggestions/slice-issue-87994.rs new file mode 100644 index 000000000..ecb7f54ea --- /dev/null +++ b/tests/ui/suggestions/slice-issue-87994.rs @@ -0,0 +1,16 @@ +fn main() { + let v = vec![1i32, 2, 3]; + for _ in v[1..] { + //~^ ERROR [i32]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + } + struct K { + n: i32, + } + let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }]; + for i2 in v2[1..] { + //~^ ERROR [K]` is not an iterator [E0277] + //~^^ ERROR known at compilation time + i2.n = 2; + } +} diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr new file mode 100644 index 000000000..84ecd749b --- /dev/null +++ b/tests/ui/suggestions/slice-issue-87994.stderr @@ -0,0 +1,63 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]` + | + = note: the trait bound `[i32]: IntoIterator` is not satisfied + = note: required for `[i32]` to implement `IntoIterator` +help: consider borrowing here + | +LL | for _ in &v[1..] { + | + +LL | for _ in &mut v[1..] { + | ++++ + +error[E0277]: `[i32]` is not an iterator + --> $DIR/slice-issue-87994.rs:3:12 + | +LL | for _ in v[1..] { + | ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]` + | + = note: the trait bound `[i32]: IntoIterator` is not satisfied + = note: required for `[i32]` to implement `IntoIterator` +help: consider borrowing here + | +LL | for _ in &v[1..] { + | + +LL | for _ in &mut v[1..] { + | ++++ + +error[E0277]: the size for values of type `[K]` cannot be known at compilation time + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]` + | + = note: the trait bound `[K]: IntoIterator` is not satisfied + = note: required for `[K]` to implement `IntoIterator` +help: consider borrowing here + | +LL | for i2 in &v2[1..] { + | + +LL | for i2 in &mut v2[1..] { + | ++++ + +error[E0277]: `[K]` is not an iterator + --> $DIR/slice-issue-87994.rs:11:13 + | +LL | for i2 in v2[1..] { + | ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]` + | + = note: the trait bound `[K]: IntoIterator` is not satisfied + = note: required for `[K]` to implement `IntoIterator` +help: consider borrowing here + | +LL | for i2 in &v2[1..] { + | + +LL | for i2 in &mut v2[1..] { + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.rs b/tests/ui/suggestions/struct-field-type-including-single-colon.rs new file mode 100644 index 000000000..b7ad6d996 --- /dev/null +++ b/tests/ui/suggestions/struct-field-type-including-single-colon.rs @@ -0,0 +1,20 @@ +mod foo { + struct A; + mod bar { + struct B; + } +} + +struct Foo { + a: foo:A, + //~^ ERROR found single colon in a struct field type path + //~| expected `,`, or `}`, found `:` +} + +struct Bar { + b: foo::bar:B, + //~^ ERROR found single colon in a struct field type path + //~| expected `,`, or `}`, found `:` +} + +fn main() {} diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr new file mode 100644 index 000000000..4dd514480 --- /dev/null +++ b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr @@ -0,0 +1,40 @@ +error: found single colon in a struct field type path + --> $DIR/struct-field-type-including-single-colon.rs:9:11 + | +LL | a: foo:A, + | ^ + | +help: write a path separator here + | +LL | a: foo::A, + | ~~ + +error: expected `,`, or `}`, found `:` + --> $DIR/struct-field-type-including-single-colon.rs:9:11 + | +LL | struct Foo { + | --- while parsing this struct +LL | a: foo:A, + | ^ + +error: found single colon in a struct field type path + --> $DIR/struct-field-type-including-single-colon.rs:15:16 + | +LL | b: foo::bar:B, + | ^ + | +help: write a path separator here + | +LL | b: foo::bar::B, + | ~~ + +error: expected `,`, or `}`, found `:` + --> $DIR/struct-field-type-including-single-colon.rs:15:16 + | +LL | struct Bar { + | --- while parsing this struct +LL | b: foo::bar:B, + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/suggestions/struct-initializer-comma.fixed b/tests/ui/suggestions/struct-initializer-comma.fixed new file mode 100644 index 000000000..6a4ee39b1 --- /dev/null +++ b/tests/ui/suggestions/struct-initializer-comma.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +pub struct Foo { + pub first: bool, + pub second: u8, +} + +fn main() { + let _ = Foo { + //~^ ERROR missing field + first: true, + second: 25 + //~^ ERROR expected one of + }; +} diff --git a/tests/ui/suggestions/struct-initializer-comma.rs b/tests/ui/suggestions/struct-initializer-comma.rs new file mode 100644 index 000000000..c137f0594 --- /dev/null +++ b/tests/ui/suggestions/struct-initializer-comma.rs @@ -0,0 +1,15 @@ +// run-rustfix + +pub struct Foo { + pub first: bool, + pub second: u8, +} + +fn main() { + let _ = Foo { + //~^ ERROR missing field + first: true + second: 25 + //~^ ERROR expected one of + }; +} diff --git a/tests/ui/suggestions/struct-initializer-comma.stderr b/tests/ui/suggestions/struct-initializer-comma.stderr new file mode 100644 index 000000000..5eff43f32 --- /dev/null +++ b/tests/ui/suggestions/struct-initializer-comma.stderr @@ -0,0 +1,23 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `second` + --> $DIR/struct-initializer-comma.rs:12:9 + | +LL | let _ = Foo { + | --- while parsing this struct +LL | +LL | first: true + | - + | | + | expected one of `,`, `.`, `?`, `}`, or an operator + | help: try adding a comma: `,` +LL | second: 25 + | ^^^^^^ unexpected token + +error[E0063]: missing field `second` in initializer of `Foo` + --> $DIR/struct-initializer-comma.rs:9:13 + | +LL | let _ = Foo { + | ^^^ missing `second` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/suggestions/sugg-else-for-closure.fixed b/tests/ui/suggestions/sugg-else-for-closure.fixed new file mode 100644 index 000000000..cf381d9da --- /dev/null +++ b/tests/ui/suggestions/sugg-else-for-closure.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let x = "com.example.app"; + let y: Option<&str> = None; + let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap()); + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/suggestions/sugg-else-for-closure.rs b/tests/ui/suggestions/sugg-else-for-closure.rs new file mode 100644 index 000000000..540ced91f --- /dev/null +++ b/tests/ui/suggestions/sugg-else-for-closure.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let x = "com.example.app"; + let y: Option<&str> = None; + let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr new file mode 100644 index 000000000..7f05832bc --- /dev/null +++ b/tests/ui/suggestions/sugg-else-for-closure.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/sugg-else-for-closure.rs:6:26 + | +LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found closure + | | + | arguments to this method are incorrect + | + = note: expected reference `&str` + found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` +help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed + --> $DIR/sugg-else-for-closure.rs:6:14 + | +LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); + | ^^^^^^^^^^^^-------------------------------^ + | | + | this argument influences the return type of `unwrap_or` +note: associated function defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: try calling `unwrap_or_else` instead + | +LL | let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap()); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs new file mode 100644 index 000000000..21ab6830b --- /dev/null +++ b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.rs @@ -0,0 +1,10 @@ +// When build the suggesttion take in consideration the `:?` +// https://github.com/rust-lang/rust/issues/100648 +#![deny(warnings)] + +fn main () { + println!("hello {:?}", world = "world"); + //~^ ERROR named argument `world` is not used by name + //~| HELP use the named argument by name to avoid ambiguity + //~| SUGGESTION world +} diff --git a/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr new file mode 100644 index 000000000..850f69f2d --- /dev/null +++ b/tests/ui/suggestions/sugg_with_positional_args_and_debug_fmt.stderr @@ -0,0 +1,21 @@ +error: named argument `world` is not used by name + --> $DIR/sugg_with_positional_args_and_debug_fmt.rs:6:28 + | +LL | println!("hello {:?}", world = "world"); + | ---- ^^^^^ this named argument is referred to by position in formatting string + | | + | this formatting argument uses named argument `world` by position + | +note: the lint level is defined here + --> $DIR/sugg_with_positional_args_and_debug_fmt.rs:3:9 + | +LL | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(named_arguments_used_positionally)]` implied by `#[deny(warnings)]` +help: use the named argument by name to avoid ambiguity + | +LL | println!("hello {world:?}", world = "world"); + | +++++ + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/suggest-add-self.rs b/tests/ui/suggestions/suggest-add-self.rs new file mode 100644 index 000000000..40692c8df --- /dev/null +++ b/tests/ui/suggestions/suggest-add-self.rs @@ -0,0 +1,15 @@ +struct X(i32); + +impl X { + pub(crate) fn f() { + self.0 + //~^ ERROR expected value, found module `self` + } + + pub fn g() { + self.0 + //~^ ERROR expected value, found module `self` + } +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-add-self.stderr b/tests/ui/suggestions/suggest-add-self.stderr new file mode 100644 index 000000000..a5e8f93de --- /dev/null +++ b/tests/ui/suggestions/suggest-add-self.stderr @@ -0,0 +1,29 @@ +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self.rs:5:9 + | +LL | pub(crate) fn f() { + | - this function doesn't have a `self` parameter +LL | self.0 + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | pub(crate) fn f(&self) { + | +++++ + +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self.rs:10:9 + | +LL | pub fn g() { + | - this function doesn't have a `self` parameter +LL | self.0 + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | pub fn g(&self) { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0424`. diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed new file mode 100644 index 000000000..e9b8a9caa --- /dev/null +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused_variables)] + +fn foo(foo: &mut usize) { + todo!() +} + +fn bar(bar: &usize) { + todo!() +} + +fn main() { + foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied + bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied +} diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs new file mode 100644 index 000000000..5fae21ccc --- /dev/null +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused_variables)] + +fn foo(foo: &mut usize) { + todo!() +} + +fn bar(bar: &usize) { + todo!() +} + +fn main() { + foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied + bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied +} diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr new file mode 100644 index 000000000..125a8b44f --- /dev/null +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `&mut usize: Default` is not satisfied + --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9 + | +LL | foo(Default::default()); + | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` + | +help: consider mutably borrowing here + | +LL | foo(&mut Default::default()); + | ++++ + +error[E0277]: the trait bound `&usize: Default` is not satisfied + --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9 + | +LL | bar(Default::default()); + | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` + | +help: consider borrowing here + | +LL | bar(&Default::default()); + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed new file mode 100644 index 000000000..8d96cf590 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +#![allow(unused)] + +struct Foo(T); + +impl Foo { + fn test() -> i32 { 1 } +} + +fn main() { + let x = Box::new(Foo(1i32)); + Foo::::test(); + //~^ ERROR no method named `test` found for struct `Box>` in the current scope +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.rs b/tests/ui/suggestions/suggest-assoc-fn-call-deref.rs new file mode 100644 index 000000000..186901f75 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.rs @@ -0,0 +1,15 @@ +// run-rustfix + +#![allow(unused)] + +struct Foo(T); + +impl Foo { + fn test() -> i32 { 1 } +} + +fn main() { + let x = Box::new(Foo(1i32)); + x.test(); + //~^ ERROR no method named `test` found for struct `Box>` in the current scope +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr new file mode 100644 index 000000000..00fb96f03 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-deref.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `test` found for struct `Box>` in the current scope + --> $DIR/suggest-assoc-fn-call-deref.rs:13:7 + | +LL | x.test(); + | --^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `Foo::::test()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `Foo` + --> $DIR/suggest-assoc-fn-call-deref.rs:8:5 + | +LL | fn test() -> i32 { 1 } + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs new file mode 100644 index 000000000..a39b8711d --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.rs @@ -0,0 +1,11 @@ +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} +} + +fn main() { + let x = GenericAssocMethod(33); + x.default_hello(); + //~^ ERROR no method named `default_hello` found +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr new file mode 100644 index 000000000..c247e73b3 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-placeholder.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:9:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `default_hello` not found for this struct +... +LL | x.default_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::default_hello()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish-placeholder.rs:4:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs new file mode 100644 index 000000000..f738a1f21 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs @@ -0,0 +1,13 @@ +use std::cell::RefCell; + +struct HasAssocMethod; + +impl HasAssocMethod { + fn hello() {} +} +fn main() { + let shared_state = RefCell::new(HasAssocMethod); + let state = shared_state.borrow_mut(); + state.hello(); + //~^ ERROR no method named `hello` found +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr new file mode 100644 index 000000000..7c9f0b6c2 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `hello` found for struct `RefMut<'_, HasAssocMethod>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11 + | +LL | state.hello(); + | ------^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `HasAssocMethod::hello()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `HasAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:6:5 + | +LL | fn hello() {} + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed new file mode 100644 index 000000000..02dd0715c --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.fixed @@ -0,0 +1,26 @@ +// run-rustfix + +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} + fn self_ty_hello(_: Self) {} + fn self_ty_ref_hello(_: &Self) {} +} + +fn main() { + // Test for inferred types + let x = GenericAssocMethod(33); + GenericAssocMethod::<_>::self_ty_ref_hello(&x); + //~^ ERROR no method named `self_ty_ref_hello` found + GenericAssocMethod::<_>::self_ty_hello(x); + //~^ ERROR no method named `self_ty_hello` found + // Test for known types + let y = GenericAssocMethod(33i32); + GenericAssocMethod::::default_hello(); + //~^ ERROR no method named `default_hello` found + GenericAssocMethod::::self_ty_ref_hello(&y); + //~^ ERROR no method named `self_ty_ref_hello` found + GenericAssocMethod::::self_ty_hello(y); + //~^ ERROR no method named `self_ty_hello` found +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs new file mode 100644 index 000000000..1d0ca8e78 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -0,0 +1,26 @@ +// run-rustfix + +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} + fn self_ty_hello(_: Self) {} + fn self_ty_ref_hello(_: &Self) {} +} + +fn main() { + // Test for inferred types + let x = GenericAssocMethod(33); + x.self_ty_ref_hello(); + //~^ ERROR no method named `self_ty_ref_hello` found + x.self_ty_hello(); + //~^ ERROR no method named `self_ty_hello` found + // Test for known types + let y = GenericAssocMethod(33i32); + y.default_hello(); + //~^ ERROR no method named `default_hello` found + y.self_ty_ref_hello(); + //~^ ERROR no method named `self_ty_ref_hello` found + y.self_ty_hello(); + //~^ ERROR no method named `self_ty_hello` found +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr new file mode 100644 index 000000000..92b03fc77 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -0,0 +1,98 @@ +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:14:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | x.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_ref_hello(&x)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5 + | +LL | fn self_ty_ref_hello(_: &Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod<{integer}>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:16:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_hello` not found for this struct +... +LL | x.self_ty_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::<_>::self_ty_hello(x)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5 + | +LL | fn self_ty_hello(_: Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `default_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:20:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `default_hello` not found for this struct +... +LL | y.default_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::default_hello()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:6:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_ref_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:22:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_ref_hello` not found for this struct +... +LL | y.self_ty_ref_hello(); + | --^^^^^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_ref_hello(&y)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:8:5 + | +LL | fn self_ty_ref_hello(_: &Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `self_ty_hello` found for struct `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:24:7 + | +LL | struct GenericAssocMethod(T); + | ---------------------------- method `self_ty_hello` not found for this struct +... +LL | y.self_ty_hello(); + | --^^^^^^^^^^^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::self_ty_hello(y)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:7:5 + | +LL | fn self_ty_hello(_: Self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs new file mode 100644 index 000000000..14fef1b52 --- /dev/null +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -0,0 +1,58 @@ +// Ensure that the compiler include the blanklet implementation suggestion +// when inside a `impl` statement are used two local traits. +// +// edition:2021 +use std::fmt; + +trait LocalTraitOne { } + +trait LocalTraitTwo { } + +trait GenericTrait {} + +impl LocalTraitTwo for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + +impl fmt::Display for LocalTraitOne { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl fmt::Display for LocalTraitTwo + Send { +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!(); + } +} + +impl LocalTraitOne for fmt::Display {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + + +impl LocalTraitOne for fmt::Display + Send {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + + +impl GenericTrait for LocalTraitOne {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` + +trait GenericTraitTwo {} + +impl GenericTraitTwo for GenericTrait {} +//~^ ERROR trait objects must include the `dyn` keyword +//~| HELP add `dyn` keyword before this trait +//~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` + +fn main() {} diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr new file mode 100644 index 000000000..398caa98b --- /dev/null +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -0,0 +1,100 @@ +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 + | +LL | impl LocalTraitTwo for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl LocalTraitTwo for dyn LocalTraitOne {} + | +++ +help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` + | +LL | impl LocalTraitTwo for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 + | +LL | impl fmt::Display for LocalTraitOne { + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl fmt::Display for dyn LocalTraitOne { + | +++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 + | +LL | impl fmt::Display for LocalTraitTwo + Send { + | ^^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl fmt::Display for dyn LocalTraitTwo + Send { + | +++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 + | +LL | impl LocalTraitOne for fmt::Display {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl LocalTraitOne for dyn fmt::Display {} + | +++ +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` + | +LL | impl LocalTraitOne for T {} + | +++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 + | +LL | impl LocalTraitOne for fmt::Display + Send {} + | ^^^^^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl LocalTraitOne for dyn fmt::Display + Send {} + | +++ +help: alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` + | +LL | impl LocalTraitOne for T {} + | ++++++++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 + | +LL | impl GenericTrait for LocalTraitOne {} + | ^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl GenericTrait for dyn LocalTraitOne {} + | +++ +help: alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` + | +LL | impl GenericTrait for T {} + | ++++++++++++++++++ ~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 + | +LL | impl GenericTraitTwo for GenericTrait {} + | ^^^^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl GenericTraitTwo for dyn GenericTrait {} + | +++ +help: alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` + | +LL | impl> GenericTraitTwo for U {} + | ++++++++++++++++++++ ~ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs b/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs new file mode 100644 index 000000000..120fc5383 --- /dev/null +++ b/tests/ui/suggestions/suggest-borrow-to-dyn-object.rs @@ -0,0 +1,16 @@ +use std::ffi::{OsStr, OsString}; +use std::path::Path; + +fn check(p: &dyn AsRef) { + let m = std::fs::metadata(&p); + println!("{:?}", &m); +} + +fn main() { + let s: OsString = ".".into(); + let s: &OsStr = &s; + check(s); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]` + //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` +} diff --git a/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr new file mode 100644 index 000000000..6ce9bfd9d --- /dev/null +++ b/tests/ui/suggestions/suggest-borrow-to-dyn-object.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow-to-dyn-object.rs:12:11 + | +LL | check(s); + | ^ doesn't have a size known at compile-time + | + = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `OsStr` + = note: required for the cast from `OsStr` to the object type `dyn AsRef` +help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` + | +LL | check(&s); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-box.fixed b/tests/ui/suggestions/suggest-box.fixed new file mode 100644 index 000000000..3de02cd0b --- /dev/null +++ b/tests/ui/suggestions/suggest-box.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types + Err(())?; + Ok(()) + }); +} diff --git a/tests/ui/suggestions/suggest-box.rs b/tests/ui/suggestions/suggest-box.rs new file mode 100644 index 000000000..e680a61db --- /dev/null +++ b/tests/ui/suggestions/suggest-box.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box Result<(), ()>> = || { //~ ERROR mismatched types + Err(())?; + Ok(()) + }; +} diff --git a/tests/ui/suggestions/suggest-box.stderr b/tests/ui/suggestions/suggest-box.stderr new file mode 100644 index 000000000..2bdaa4e97 --- /dev/null +++ b/tests/ui/suggestions/suggest-box.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/suggest-box.rs:4:47 + | +LL | let _x: Box Result<(), ()>> = || { + | _____________-------------------------------___^ + | | | + | | expected due to this +LL | | Err(())?; +LL | | Ok(()) +LL | | }; + | |_____^ expected struct `Box`, found closure + | + = note: expected struct `Box Result<(), ()>>` + found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL ~ let _x: Box Result<(), ()>> = Box::new(|| { +LL | Err(())?; +LL | Ok(()) +LL ~ }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-change-mut.rs b/tests/ui/suggestions/suggest-change-mut.rs new file mode 100644 index 000000000..47dc7c343 --- /dev/null +++ b/tests/ui/suggestions/suggest-change-mut.rs @@ -0,0 +1,21 @@ +#![allow(warnings)] + +use std::io::{BufRead, BufReader, Read, Write}; + +fn issue_81421(mut stream: T) { //~ HELP consider introducing a `where` clause + let initial_message = format!("Hello world"); + let mut buffer: Vec = Vec::new(); + let bytes_written = stream.write_all(initial_message.as_bytes()); + let flush = stream.flush(); + + loop { + let mut stream_reader = BufReader::new(&stream); + //~^ ERROR the trait bound `&T: std::io::Read` is not satisfied [E0277] + //~| HELP consider removing the leading `&`-reference + //~| HELP consider changing this borrow's mutability + stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed"); + //~^ ERROR the method `read_until` exists for struct `BufReader<&T>`, + } +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-change-mut.stderr b/tests/ui/suggestions/suggest-change-mut.stderr new file mode 100644 index 000000000..d194afeaf --- /dev/null +++ b/tests/ui/suggestions/suggest-change-mut.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `&T: std::io::Read` is not satisfied + --> $DIR/suggest-change-mut.rs:12:48 + | +LL | let mut stream_reader = BufReader::new(&stream); + | -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `BufReader::::new` + --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL +help: consider removing the leading `&`-reference + | +LL - let mut stream_reader = BufReader::new(&stream); +LL + let mut stream_reader = BufReader::new(stream); + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn issue_81421(mut stream: T) where &T: std::io::Read { + | +++++++++++++++++++++++ +help: consider changing this borrow's mutability + | +LL | let mut stream_reader = BufReader::new(&mut stream); + | ~~~~ + +error[E0599]: the method `read_until` exists for struct `BufReader<&T>`, but its trait bounds were not satisfied + --> $DIR/suggest-change-mut.rs:16:23 + | +LL | stream_reader.read_until(b'\n', &mut buffer).expect("Reading into buffer failed"); + | ^^^^^^^^^^ method cannot be called on `BufReader<&T>` due to unsatisfied trait bounds + --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL + | + = note: doesn't satisfy `BufReader<&T>: BufRead` + | + = note: the following trait bounds were not satisfied: + `&T: std::io::Read` + which is required by `BufReader<&T>: BufRead` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-closure-return-type-1.rs b/tests/ui/suggestions/suggest-closure-return-type-1.rs new file mode 100644 index 000000000..8bb421903 --- /dev/null +++ b/tests/ui/suggestions/suggest-closure-return-type-1.rs @@ -0,0 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + +fn main() { + unbound_drop(|| -> _ { [] }); + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type +} diff --git a/tests/ui/suggestions/suggest-closure-return-type-1.stderr b/tests/ui/suggestions/suggest-closure-return-type-1.stderr new file mode 100644 index 000000000..f4c2eb7ff --- /dev/null +++ b/tests/ui/suggestions/suggest-closure-return-type-1.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-1.rs:4:18 + | +LL | unbound_drop(|| -> _ { [] }); + | ^^^^^^^ -- type must be known at this point + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }); + | ~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/suggest-closure-return-type-2.rs b/tests/ui/suggestions/suggest-closure-return-type-2.rs new file mode 100644 index 000000000..25ed1882e --- /dev/null +++ b/tests/ui/suggestions/suggest-closure-return-type-2.rs @@ -0,0 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + +fn main() { + unbound_drop(|| { [] }) + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type +} diff --git a/tests/ui/suggestions/suggest-closure-return-type-2.stderr b/tests/ui/suggestions/suggest-closure-return-type-2.stderr new file mode 100644 index 000000000..88bf26304 --- /dev/null +++ b/tests/ui/suggestions/suggest-closure-return-type-2.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-2.rs:4:18 + | +LL | unbound_drop(|| { [] }) + | ^^ -- type must be known at this point + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }) + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/suggest-closure-return-type-3.rs b/tests/ui/suggestions/suggest-closure-return-type-3.rs new file mode 100644 index 000000000..3de6c55cf --- /dev/null +++ b/tests/ui/suggestions/suggest-closure-return-type-3.rs @@ -0,0 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + +fn main() { + unbound_drop(|| []); + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type +} diff --git a/tests/ui/suggestions/suggest-closure-return-type-3.stderr b/tests/ui/suggestions/suggest-closure-return-type-3.stderr new file mode 100644 index 000000000..bc4107528 --- /dev/null +++ b/tests/ui/suggestions/suggest-closure-return-type-3.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-3.rs:4:18 + | +LL | unbound_drop(|| []); + | ^^ -- type must be known at this point + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }); + | +++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/suggestions/suggest-dereferencing-index.fixed b/tests/ui/suggestions/suggest-dereferencing-index.fixed new file mode 100644 index 000000000..dd4ae4eb1 --- /dev/null +++ b/tests/ui/suggestions/suggest-dereferencing-index.fixed @@ -0,0 +1,7 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let i: &usize = &1; + let one_item_please: i32 = [1, 2, 3][*i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize` +} diff --git a/tests/ui/suggestions/suggest-dereferencing-index.rs b/tests/ui/suggestions/suggest-dereferencing-index.rs new file mode 100644 index 000000000..82ebacc49 --- /dev/null +++ b/tests/ui/suggestions/suggest-dereferencing-index.rs @@ -0,0 +1,7 @@ +// run-rustfix +#![allow(unused_variables)] + +fn main() { + let i: &usize = &1; + let one_item_please: i32 = [1, 2, 3][i]; //~ ERROR the type `[{integer}]` cannot be indexed by `&usize` +} diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr new file mode 100644 index 000000000..147dc9234 --- /dev/null +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -0,0 +1,17 @@ +error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` + --> $DIR/suggest-dereferencing-index.rs:6:42 + | +LL | let one_item_please: i32 = [1, 2, 3][i]; + | ^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` + = help: the trait `SliceIndex<[T]>` is implemented for `usize` + = note: required for `[{integer}]` to implement `Index<&usize>` +help: dereference this index + | +LL | let one_item_please: i32 = [1, 2, 3][*i]; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs new file mode 100644 index 000000000..1dfc07866 --- /dev/null +++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs @@ -0,0 +1,10 @@ +mod option { + pub enum O { + Some(T), + None, + } +} + +fn main() { + let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308] +} diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr new file mode 100644 index 000000000..9b6dba7e9 --- /dev/null +++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28 + | +LL | let _: option::O<()> = (); + | ------------- ^^ expected enum `O`, found `()` + | | + | expected due to this + | + = note: expected enum `O<()>` + found unit type `()` +help: try wrapping the expression in `option::O::Some` + | +LL | let _: option::O<()> = option::O::Some(()); + | ++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs new file mode 100644 index 000000000..a62669d5b --- /dev/null +++ b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.rs @@ -0,0 +1,23 @@ +trait Trait {} + +struct A; +struct B; +struct C; + +impl Trait for &A {} +impl Trait for &mut A {} + +impl Trait for &B {} + +impl Trait for &mut C {} + +fn foo(_: X) {} + +fn main() { + let a = A; + let b = B; + let c = C; + foo(a); //~ ERROR the trait bound `A: Trait` is not satisfied + foo(b); //~ ERROR the trait bound `B: Trait` is not satisfied + foo(c); //~ ERROR the trait bound `C: Trait` is not satisfied +} diff --git a/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr new file mode 100644 index 000000000..f2eb651ea --- /dev/null +++ b/tests/ui/suggestions/suggest-imm-mut-trait-implementations.stderr @@ -0,0 +1,59 @@ +error[E0277]: the trait bound `A: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:20:9 + | +LL | foo(a); + | --- ^ the trait `Trait` is not implemented for `A` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&a); + | + +LL | foo(&mut a); + | ++++ + +error[E0277]: the trait bound `B: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9 + | +LL | foo(b); + | --- ^ the trait `Trait` is not implemented for `B` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider borrowing here + | +LL | foo(&b); + | + + +error[E0277]: the trait bound `C: Trait` is not satisfied + --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9 + | +LL | foo(c); + | --- ^ the trait `Trait` is not implemented for `C` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/suggest-imm-mut-trait-implementations.rs:14:11 + | +LL | fn foo(_: X) {} + | ^^^^^ required by this bound in `foo` +help: consider mutably borrowing here + | +LL | foo(&mut c); + | ++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed b/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed new file mode 100644 index 000000000..589ee1a47 --- /dev/null +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug + 'static) { +//~^ HELP consider adding an explicit lifetime bound... + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.rs b/tests/ui/suggestions/suggest-impl-trait-lifetime.rs new file mode 100644 index 000000000..9a87129fb --- /dev/null +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.rs @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug) { +//~^ HELP consider adding an explicit lifetime bound... + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr new file mode 100644 index 000000000..cf912f4aa --- /dev/null +++ b/tests/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `impl Debug` may not live long enough + --> $DIR/suggest-impl-trait-lifetime.rs:7:5 + | +LL | bar(d); + | ^^^^^^ ...so that the type `impl Debug` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo(d: impl Debug + 'static) { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/suggestions/suggest-labels.rs b/tests/ui/suggestions/suggest-labels.rs new file mode 100644 index 000000000..159f45855 --- /dev/null +++ b/tests/ui/suggestions/suggest-labels.rs @@ -0,0 +1,16 @@ +#[allow(unreachable_code, unused_labels)] +fn main() { + 'foo: loop { + break 'fo; //~ ERROR use of undeclared label + } + + 'bar: loop { + continue 'bor; //~ ERROR use of undeclared label + } + + 'longlabel: loop { + 'longlabel1: loop { + break 'longlable; //~ ERROR use of undeclared label + } + } +} diff --git a/tests/ui/suggestions/suggest-labels.stderr b/tests/ui/suggestions/suggest-labels.stderr new file mode 100644 index 000000000..aac6515b5 --- /dev/null +++ b/tests/ui/suggestions/suggest-labels.stderr @@ -0,0 +1,36 @@ +error[E0426]: use of undeclared label `'fo` + --> $DIR/suggest-labels.rs:4:15 + | +LL | 'foo: loop { + | ---- a label with a similar name is reachable +LL | break 'fo; + | ^^^ + | | + | undeclared label `'fo` + | help: try using similarly named label: `'foo` + +error[E0426]: use of undeclared label `'bor` + --> $DIR/suggest-labels.rs:8:18 + | +LL | 'bar: loop { + | ---- a label with a similar name is reachable +LL | continue 'bor; + | ^^^^ + | | + | undeclared label `'bor` + | help: try using similarly named label: `'bar` + +error[E0426]: use of undeclared label `'longlable` + --> $DIR/suggest-labels.rs:13:19 + | +LL | 'longlabel1: loop { + | ----------- a label with a similar name is reachable +LL | break 'longlable; + | ^^^^^^^^^^ + | | + | undeclared label `'longlable` + | help: try using similarly named label: `'longlabel1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0426`. diff --git a/tests/ui/suggestions/suggest-let-for-assignment.fixed b/tests/ui/suggestions/suggest-let-for-assignment.fixed new file mode 100644 index 000000000..3a25e25ee --- /dev/null +++ b/tests/ui/suggestions/suggest-let-for-assignment.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +fn main() { + let demo = 1; //~ ERROR cannot find value `demo` in this scope + dbg!(demo); //~ ERROR cannot find value `demo` in this scope + + let x = "x"; //~ ERROR cannot find value `x` in this scope + println!("x: {}", x); //~ ERROR cannot find value `x` in this scope + + if x == "x" { + //~^ ERROR cannot find value `x` in this scope + println!("x is 1"); + } + + let y = 1 + 2; //~ ERROR cannot find value `y` in this scope + println!("y: {}", y); //~ ERROR cannot find value `y` in this scope +} diff --git a/tests/ui/suggestions/suggest-let-for-assignment.rs b/tests/ui/suggestions/suggest-let-for-assignment.rs new file mode 100644 index 000000000..67705fe06 --- /dev/null +++ b/tests/ui/suggestions/suggest-let-for-assignment.rs @@ -0,0 +1,17 @@ +// run-rustfix + +fn main() { + demo = 1; //~ ERROR cannot find value `demo` in this scope + dbg!(demo); //~ ERROR cannot find value `demo` in this scope + + x = "x"; //~ ERROR cannot find value `x` in this scope + println!("x: {}", x); //~ ERROR cannot find value `x` in this scope + + if x == "x" { + //~^ ERROR cannot find value `x` in this scope + println!("x is 1"); + } + + y = 1 + 2; //~ ERROR cannot find value `y` in this scope + println!("y: {}", y); //~ ERROR cannot find value `y` in this scope +} diff --git a/tests/ui/suggestions/suggest-let-for-assignment.stderr b/tests/ui/suggestions/suggest-let-for-assignment.stderr new file mode 100644 index 000000000..3f6a3da4b --- /dev/null +++ b/tests/ui/suggestions/suggest-let-for-assignment.stderr @@ -0,0 +1,60 @@ +error[E0425]: cannot find value `demo` in this scope + --> $DIR/suggest-let-for-assignment.rs:4:5 + | +LL | demo = 1; + | ^^^^ + | +help: you might have meant to introduce a new binding + | +LL | let demo = 1; + | +++ + +error[E0425]: cannot find value `demo` in this scope + --> $DIR/suggest-let-for-assignment.rs:5:10 + | +LL | dbg!(demo); + | ^^^^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/suggest-let-for-assignment.rs:7:5 + | +LL | x = "x"; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let x = "x"; + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/suggest-let-for-assignment.rs:8:23 + | +LL | println!("x: {}", x); + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/suggest-let-for-assignment.rs:10:8 + | +LL | if x == "x" { + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/suggest-let-for-assignment.rs:15:5 + | +LL | y = 1 + 2; + | ^ + | +help: you might have meant to introduce a new binding + | +LL | let y = 1 + 2; + | +++ + +error[E0425]: cannot find value `y` in this scope + --> $DIR/suggest-let-for-assignment.rs:16:23 + | +LL | println!("y: {}", y); + | ^ 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/tests/ui/suggestions/suggest-methods.rs b/tests/ui/suggestions/suggest-methods.rs new file mode 100644 index 000000000..f40b9ed99 --- /dev/null +++ b/tests/ui/suggestions/suggest-methods.rs @@ -0,0 +1,30 @@ +struct Foo; + +impl Foo { + fn bar(self) {} + fn baz(&self, x: f64) {} +} + +trait FooT { + fn bag(&self); +} + +impl FooT for Foo { + fn bag(&self) {} +} + +fn main() { + let f = Foo; + f.bat(1.0); //~ ERROR no method named + + let s = "foo".to_string(); + let _ = s.is_emtpy(); //~ ERROR no method named + + // Generates a warning for `count_zeros()`. `count_ones()` is also a close + // match, but the former is closer. + let _ = 63u32.count_eos(); //~ ERROR no method named + + // Does not generate a warning + let _ = 63u32.count_o(); //~ ERROR no method named + +} diff --git a/tests/ui/suggestions/suggest-methods.stderr b/tests/ui/suggestions/suggest-methods.stderr new file mode 100644 index 000000000..03cb9c779 --- /dev/null +++ b/tests/ui/suggestions/suggest-methods.stderr @@ -0,0 +1,30 @@ +error[E0599]: no method named `bat` found for struct `Foo` in the current scope + --> $DIR/suggest-methods.rs:18:7 + | +LL | struct Foo; + | ---------- method `bat` not found for this struct +... +LL | f.bat(1.0); + | ^^^ help: there is a method with a similar name: `bar` + +error[E0599]: no method named `is_emtpy` found for struct `String` in the current scope + --> $DIR/suggest-methods.rs:21:15 + | +LL | let _ = s.is_emtpy(); + | ^^^^^^^^ help: there is a method with a similar name: `is_empty` + +error[E0599]: no method named `count_eos` found for type `u32` in the current scope + --> $DIR/suggest-methods.rs:25:19 + | +LL | let _ = 63u32.count_eos(); + | ^^^^^^^^^ help: there is a method with a similar name: `count_zeros` + +error[E0599]: no method named `count_o` found for type `u32` in the current scope + --> $DIR/suggest-methods.rs:28:19 + | +LL | let _ = 63u32.count_o(); + | ^^^^^^^ help: there is a method with a similar name: `count_ones` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-move-lifetimes.rs b/tests/ui/suggestions/suggest-move-lifetimes.rs new file mode 100644 index 000000000..6b26f1214 --- /dev/null +++ b/tests/ui/suggestions/suggest-move-lifetimes.rs @@ -0,0 +1,21 @@ +struct A { //~ ERROR lifetime parameters must be declared + t: &'a T, +} + +struct B { //~ ERROR lifetime parameters must be declared + t: &'a T, + u: U, +} + +struct C { //~ ERROR lifetime parameters must be declared + t: &'a T, + u: U, +} + +struct D { //~ ERROR lifetime parameters must be declared + t: &'a T, + u: &'b U, + v: &'c V, +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-move-lifetimes.stderr b/tests/ui/suggestions/suggest-move-lifetimes.stderr new file mode 100644 index 000000000..b1a49447d --- /dev/null +++ b/tests/ui/suggestions/suggest-move-lifetimes.stderr @@ -0,0 +1,26 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/suggest-move-lifetimes.rs:1:13 + | +LL | struct A { + | ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/suggest-move-lifetimes.rs:5:13 + | +LL | struct B { + | ----^^---- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/suggest-move-lifetimes.rs:10:16 + | +LL | struct C { + | -------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/suggest-move-lifetimes.rs:15:16 + | +LL | struct D { + | -------^^--^^-----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, 'c, T, U, V>` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/suggestions/suggest-move-types.rs b/tests/ui/suggestions/suggest-move-types.rs new file mode 100644 index 000000000..27930626a --- /dev/null +++ b/tests/ui/suggestions/suggest-move-types.rs @@ -0,0 +1,91 @@ +#![allow(warnings)] + +// This test verifies that the suggestion to move types before associated type bindings +// is correct. + +trait One { + type A; +} + +trait OneWithLifetime<'a, T> { + type A; +} + +trait Three { + type A; + type B; + type C; +} + +trait ThreeWithLifetime<'a, 'b, 'c, T, U, V> { + type A; + type B; + type C; +} + +struct A> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, +} + + +struct Al<'a, T, M: OneWithLifetime> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR type provided when a lifetime was expected + m: M, + t: &'a T, +} + +struct B> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, + u: U, + v: V, +} + +struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR type provided when a lifetime was expected + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + +struct C> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, + u: U, + v: V, +} + +struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR lifetime provided when a type was expected + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + +struct D> { +//~^ ERROR generic arguments must come before the first constraint + m: M, + t: T, + u: U, + v: V, +} + +struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { +//~^ ERROR generic arguments must come before the first constraint +//~^^ ERROR lifetime provided when a type was expected + m: M, + t: &'a T, + u: &'b U, + v: &'c V, +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-move-types.stderr b/tests/ui/suggestions/suggest-move-types.stderr new file mode 100644 index 000000000..b222e8142 --- /dev/null +++ b/tests/ui/suggestions/suggest-move-types.stderr @@ -0,0 +1,137 @@ +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:26:26 + | +LL | struct A> { + | ---- ^ generic argument + | | + | constraint + | +help: move the constraint after the generic argument + | +LL | struct A> { + | ~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:33:43 + | +LL | struct Al<'a, T, M: OneWithLifetime> { + | ---- ^ ^^ generic arguments + | | + | constraint + | +help: move the constraint after the generic arguments + | +LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A = ()>> { + | ~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:40:46 + | +LL | struct B> { + | ---- ---- ---- ^ ^ ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct B> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:48:71 + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ---- ---- ---- ^ ^ ^ ^^ ^^ ^^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:57:28 + | +LL | struct C> { + | ^ ---- ---- ---- ^ ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct C> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:65:53 + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^ ^^ ---- ---- ---- ^ ^^ ^ ^^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:74:28 + | +LL | struct D> { + | ^ ---- ---- ^ ---- ^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct D> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: generic arguments must come before the first constraint + --> $DIR/suggest-move-types.rs:82:53 + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^ ^^ ---- ---- ^ ^^ ---- ^ ^^ generic arguments + | | + | constraints + | +help: move the constraints after the generic arguments + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/suggest-move-types.rs:33:43 + | +LL | struct Al<'a, T, M: OneWithLifetime> { + | ^ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/suggest-move-types.rs:48:71 + | +LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^ + +error[E0747]: lifetime provided when a type was expected + --> $DIR/suggest-move-types.rs:65:56 + | +LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, 'c, T, U, V>` + +error[E0747]: lifetime provided when a type was expected + --> $DIR/suggest-move-types.rs:82:56 + | +LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { + | ^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, 'c, T, U, V>` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed new file mode 100644 index 000000000..b69bad988 --- /dev/null +++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed @@ -0,0 +1,21 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/82081 + +use std::collections::HashMap; + +struct Test { + v: u32, +} + +fn main() { + let mut map = HashMap::new(); + map.insert("a", Test { v: 0 }); + + for (_k, mut v) in map.iter_mut() { + //~^ HELP use mutable method + //~| NOTE this iterator yields `&` references + v.v += 1; + //~^ ERROR cannot assign to `v.v` + //~| NOTE `v` is a `&` reference + } +} diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs new file mode 100644 index 000000000..9284410df --- /dev/null +++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs @@ -0,0 +1,21 @@ +// run-rustfix +// https://github.com/rust-lang/rust/issues/82081 + +use std::collections::HashMap; + +struct Test { + v: u32, +} + +fn main() { + let mut map = HashMap::new(); + map.insert("a", Test { v: 0 }); + + for (_k, mut v) in map.iter() { + //~^ HELP use mutable method + //~| NOTE this iterator yields `&` references + v.v += 1; + //~^ ERROR cannot assign to `v.v` + //~| NOTE `v` is a `&` reference + } +} diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr new file mode 100644 index 000000000..74433daa6 --- /dev/null +++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr @@ -0,0 +1,15 @@ +error[E0594]: cannot assign to `v.v`, which is behind a `&` reference + --> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9 + | +LL | for (_k, mut v) in map.iter() { + | ---------- + | | | + | | help: use mutable method: `iter_mut()` + | this iterator yields `&` references +... +LL | v.v += 1; + | ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop.rs b/tests/ui/suggestions/suggest-mut-method-for-loop.rs new file mode 100644 index 000000000..756768bce --- /dev/null +++ b/tests/ui/suggestions/suggest-mut-method-for-loop.rs @@ -0,0 +1,17 @@ +use std::collections::HashMap; +struct X(usize); +struct Y { + v: u32 +} + +fn main() { + let mut buzz = HashMap::new(); + buzz.insert("a", Y { v: 0 }); + + for mut t in buzz.values() { + //~^ HELP + //~| SUGGESTION values_mut() + t.v += 1; + //~^ ERROR cannot assign + } +} diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop.stderr new file mode 100644 index 000000000..3eb9e1031 --- /dev/null +++ b/tests/ui/suggestions/suggest-mut-method-for-loop.stderr @@ -0,0 +1,15 @@ +error[E0594]: cannot assign to `t.v`, which is behind a `&` reference + --> $DIR/suggest-mut-method-for-loop.rs:14:9 + | +LL | for mut t in buzz.values() { + | ------------- + | | | + | | help: use mutable method: `values_mut()` + | this iterator yields `&` references +... +LL | t.v += 1; + | ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.rs b/tests/ui/suggestions/suggest-on-bare-closure-call.rs new file mode 100644 index 000000000..496c305bc --- /dev/null +++ b/tests/ui/suggestions/suggest-on-bare-closure-call.rs @@ -0,0 +1,11 @@ +// edition:2021 + +#![feature(async_closure)] + +fn main() { + let _ = ||{}(); + //~^ ERROR expected function, found `()` + + let _ = async ||{}(); + //~^ ERROR expected function, found `()` +} diff --git a/tests/ui/suggestions/suggest-on-bare-closure-call.stderr b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr new file mode 100644 index 000000000..e65a6eb49 --- /dev/null +++ b/tests/ui/suggestions/suggest-on-bare-closure-call.stderr @@ -0,0 +1,29 @@ +error[E0618]: expected function, found `()` + --> $DIR/suggest-on-bare-closure-call.rs:6:15 + | +LL | let _ = ||{}(); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (||{})(); + | + + + +error[E0618]: expected function, found `()` + --> $DIR/suggest-on-bare-closure-call.rs:9:21 + | +LL | let _ = async ||{}(); + | ^^-- + | | + | call expression requires function + | +help: if you meant to create this closure and immediately call it, surround the closure with parentheses + | +LL | let _ = (async ||{})(); + | + + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/suggestions/suggest-ref-macro.rs b/tests/ui/suggestions/suggest-ref-macro.rs new file mode 100644 index 000000000..6f780f32a --- /dev/null +++ b/tests/ui/suggestions/suggest-ref-macro.rs @@ -0,0 +1,29 @@ +// run-check +// aux-build:proc-macro-type-error.rs + +extern crate proc_macro_type_error; + +use proc_macro_type_error::hello; + +#[hello] //~ERROR mismatched types +fn abc() {} + +fn x(_: &mut i32) {} + +macro_rules! bla { + () => { + x(123); + //~^ ERROR mismatched types + //~| SUGGESTION &mut 123 + }; + ($v:expr) => { + x($v) + } +} + +fn main() { + bla!(); + bla!(456); + //~^ ERROR mismatched types + //~| SUGGESTION &mut 456 +} diff --git a/tests/ui/suggestions/suggest-ref-macro.stderr b/tests/ui/suggestions/suggest-ref-macro.stderr new file mode 100644 index 000000000..17de49fbd --- /dev/null +++ b/tests/ui/suggestions/suggest-ref-macro.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | ^^^^^^^^ + | | + | expected `&mut i32`, found integer + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:8:1 + | +LL | #[hello] + | ^^^^^^^^ + = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:15:11 + | +LL | x(123); + | - ^^^ + | | | + | | expected `&mut i32`, found integer + | | help: consider mutably borrowing here: `&mut 123` + | arguments to this function are incorrect +... +LL | bla!(); + | ------ in this macro invocation + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:11:4 + | +LL | fn x(_: &mut i32) {} + | ^ ----------- + = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/suggest-ref-macro.rs:26:10 + | +LL | x($v) + | - arguments to this function are incorrect +... +LL | bla!(456); + | ^^^ + | | + | expected `&mut i32`, found integer + | help: consider mutably borrowing here: `&mut 456` + | +note: function defined here + --> $DIR/suggest-ref-macro.rs:11:4 + | +LL | fn x(_: &mut i32) {} + | ^ ----------- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/suggest-ref-mut.rs b/tests/ui/suggestions/suggest-ref-mut.rs new file mode 100644 index 000000000..d04113ffc --- /dev/null +++ b/tests/ui/suggestions/suggest-ref-mut.rs @@ -0,0 +1,30 @@ +struct X(usize); + +impl X { + fn zap(&self) { + //~^ HELP + //~| SUGGESTION &mut self + self.0 = 32; + //~^ ERROR + } +} + +fn main() { + let ref foo = 16; + //~^ HELP + //~| SUGGESTION ref mut foo + *foo = 32; + //~^ ERROR + if let Some(ref bar) = Some(16) { + //~^ HELP + //~| SUGGESTION ref mut bar + *bar = 32; + //~^ ERROR + } + match 16 { + ref quo => { *quo = 32; }, + //~^ ERROR + //~| HELP + //~| SUGGESTION ref mut quo + } +} diff --git a/tests/ui/suggestions/suggest-ref-mut.stderr b/tests/ui/suggestions/suggest-ref-mut.stderr new file mode 100644 index 000000000..7973759bf --- /dev/null +++ b/tests/ui/suggestions/suggest-ref-mut.stderr @@ -0,0 +1,47 @@ +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:7:9 + | +LL | self.0 = 32; + | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn zap(&mut self) { + | ~~~~~~~~~ + +error[E0594]: cannot assign to `*foo`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:16:5 + | +LL | *foo = 32; + | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let ref mut foo = 16; + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to `*bar`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:21:9 + | +LL | *bar = 32; + | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | if let Some(ref mut bar) = Some(16) { + | ~~~~~~~~~~~ + +error[E0594]: cannot assign to `*quo`, which is behind a `&` reference + --> $DIR/suggest-ref-mut.rs:25:22 + | +LL | ref quo => { *quo = 32; }, + | ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | ref mut quo => { *quo = 32; }, + | ~~~~~~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/suggestions/suggest-remove-refs-1.fixed b/tests/ui/suggestions/suggest-remove-refs-1.fixed new file mode 100644 index 000000000..a39e0fbd1 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-1.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in v.iter().enumerate() { + //~^ ERROR `&Enumerate>` is not an iterator + println!("{}", i); + } +} diff --git a/tests/ui/suggestions/suggest-remove-refs-1.rs b/tests/ui/suggestions/suggest-remove-refs-1.rs new file mode 100644 index 000000000..6f767f2c1 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-1.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in &v.iter().enumerate() { + //~^ ERROR `&Enumerate>` is not an iterator + println!("{}", i); + } +} diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr new file mode 100644 index 000000000..387770535 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr @@ -0,0 +1,17 @@ +error[E0277]: `&Enumerate>` is not an iterator + --> $DIR/suggest-remove-refs-1.rs:6:19 + | +LL | for (i, _) in &v.iter().enumerate() { + | ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&Enumerate>` + = note: required for `&Enumerate>` to implement `IntoIterator` +help: consider removing the leading `&`-reference + | +LL - for (i, _) in &v.iter().enumerate() { +LL + for (i, _) in v.iter().enumerate() { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-2.fixed b/tests/ui/suggestions/suggest-remove-refs-2.fixed new file mode 100644 index 000000000..0f9c3abfe --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-2.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in v.iter().enumerate() { + //~^ ERROR `&&&&&Enumerate>` is not an iterator + println!("{}", i); + } +} diff --git a/tests/ui/suggestions/suggest-remove-refs-2.rs b/tests/ui/suggestions/suggest-remove-refs-2.rs new file mode 100644 index 000000000..6c94b12d2 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-2.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in & & & & &v.iter().enumerate() { + //~^ ERROR `&&&&&Enumerate>` is not an iterator + println!("{}", i); + } +} diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr new file mode 100644 index 000000000..1632b2abb --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr @@ -0,0 +1,17 @@ +error[E0277]: `&&&&&Enumerate>` is not an iterator + --> $DIR/suggest-remove-refs-2.rs:6:19 + | +LL | for (i, _) in & & & & &v.iter().enumerate() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = note: required for `&&&&&Enumerate>` to implement `IntoIterator` +help: consider removing 5 leading `&`-references + | +LL - for (i, _) in & & & & &v.iter().enumerate() { +LL + for (i, _) in v.iter().enumerate() { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-3.fixed b/tests/ui/suggestions/suggest-remove-refs-3.fixed new file mode 100644 index 000000000..3148fcbe5 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-3.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in v + .iter() + .enumerate() { + //~^^^^ ERROR `&&&&&Enumerate>` is not an + println!("{}", i); + } +} diff --git a/tests/ui/suggestions/suggest-remove-refs-3.rs b/tests/ui/suggestions/suggest-remove-refs-3.rs new file mode 100644 index 000000000..0622adada --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-3.rs @@ -0,0 +1,13 @@ +// run-rustfix + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, _) in & & & + & &v + .iter() + .enumerate() { + //~^^^^ ERROR `&&&&&Enumerate>` is not an + println!("{}", i); + } +} diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr new file mode 100644 index 000000000..7bf421a77 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr @@ -0,0 +1,21 @@ +error[E0277]: `&&&&&Enumerate>` is not an iterator + --> $DIR/suggest-remove-refs-3.rs:6:19 + | +LL | for (i, _) in & & & + | ___________________^ +LL | | & &v +LL | | .iter() +LL | | .enumerate() { + | |____________________^ `&&&&&Enumerate>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = note: required for `&&&&&Enumerate>` to implement `IntoIterator` +help: consider removing 5 leading `&`-references + | +LL - for (i, _) in & & & +LL + for (i, _) in v + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-4.fixed b/tests/ui/suggestions/suggest-remove-refs-4.fixed new file mode 100644 index 000000000..dd63d2159 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-4.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let foo = [1,2,3].iter(); + for _i in foo {} //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/suggest-remove-refs-4.rs b/tests/ui/suggestions/suggest-remove-refs-4.rs new file mode 100644 index 000000000..3c3d9b1b3 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-4.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let foo = &[1,2,3].iter(); + for _i in &foo {} //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr new file mode 100644 index 000000000..e4ad17e06 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr @@ -0,0 +1,17 @@ +error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/suggest-remove-refs-4.rs:4:15 + | +LL | for _i in &foo {} + | ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>` + = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` +help: consider removing 2 leading `&`-references + | +LL ~ let foo = [1,2,3].iter(); +LL ~ for _i in foo {} + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-remove-refs-5.fixed b/tests/ui/suggestions/suggest-remove-refs-5.fixed new file mode 100644 index 000000000..9f59f9c19 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-5.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let v = &mut Vec::::new(); + for _ in v {} //~ ERROR E0277 + + let v = &mut [1u8]; + for _ in v {} //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/suggest-remove-refs-5.rs b/tests/ui/suggestions/suggest-remove-refs-5.rs new file mode 100644 index 000000000..d56aa0c9c --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-5.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let v = &mut &mut Vec::::new(); + for _ in &mut &mut v {} //~ ERROR E0277 + + let v = &mut &mut [1u8]; + for _ in &mut v {} //~ ERROR E0277 +} diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr new file mode 100644 index 000000000..7de84d612 --- /dev/null +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -0,0 +1,37 @@ +error[E0277]: `Vec` is not an iterator + --> $DIR/suggest-remove-refs-5.rs:4:14 + | +LL | for _ in &mut &mut v {} + | ^^^^^^^^^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` + | + = help: the trait `Iterator` is not implemented for `Vec` + = note: required for `&mut Vec` to implement `Iterator` + = note: 3 redundant requirements hidden + = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` + = note: required for `&mut &mut &mut &mut Vec` to implement `IntoIterator` +help: consider removing 3 leading `&`-references + | +LL ~ let v = &mut Vec::::new(); +LL ~ for _ in v {} + | + +error[E0277]: `[u8; 1]` is not an iterator + --> $DIR/suggest-remove-refs-5.rs:7:14 + | +LL | for _ in &mut v {} + | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()` + | + = help: the trait `Iterator` is not implemented for `[u8; 1]` + = note: required for `&mut [u8; 1]` to implement `Iterator` + = note: 2 redundant requirements hidden + = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` + = note: required for `&mut &mut &mut [u8; 1]` to implement `IntoIterator` +help: consider removing 2 leading `&`-references + | +LL ~ let v = &mut [1u8]; +LL ~ for _ in v {} + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed new file mode 100644 index 000000000..5c55566ff --- /dev/null +++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +#[allow(dead_code)] + +extern "C" { + fn foo(); //~ERROR expected `;` +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs new file mode 100644 index 000000000..91971cba3 --- /dev/null +++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.rs @@ -0,0 +1,9 @@ +// run-rustfix + +#[allow(dead_code)] + +extern "C" { + fn foo() //~ERROR expected `;` +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr new file mode 100644 index 000000000..c5df72c4a --- /dev/null +++ b/tests/ui/suggestions/suggest-semicolon-for-fn-in-extern-block.stderr @@ -0,0 +1,10 @@ +error: expected `;`, found `}` + --> $DIR/suggest-semicolon-for-fn-in-extern-block.rs:6:11 + | +LL | fn foo() + | ^ help: add `;` here +LL | } + | - unexpected token + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/suggest-split-at-mut.rs b/tests/ui/suggestions/suggest-split-at-mut.rs new file mode 100644 index 000000000..d294c20b8 --- /dev/null +++ b/tests/ui/suggestions/suggest-split-at-mut.rs @@ -0,0 +1,8 @@ +fn main() { + let mut foo = [1, 2, 3, 4]; + let a = &mut foo[2]; + let b = &mut foo[3]; //~ ERROR cannot borrow `foo[_]` as mutable more than once at a time + *a = 5; + *b = 6; + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/suggestions/suggest-split-at-mut.stderr b/tests/ui/suggestions/suggest-split-at-mut.stderr new file mode 100644 index 000000000..330f012b2 --- /dev/null +++ b/tests/ui/suggestions/suggest-split-at-mut.stderr @@ -0,0 +1,15 @@ +error[E0499]: cannot borrow `foo[_]` as mutable more than once at a time + --> $DIR/suggest-split-at-mut.rs:4:13 + | +LL | let a = &mut foo[2]; + | ----------- first mutable borrow occurs here +LL | let b = &mut foo[3]; + | ^^^^^^^^^^^ second mutable borrow occurs here +LL | *a = 5; + | ------ first borrow later used here + | + = help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/suggestions/suggest-std-when-using-type.fixed b/tests/ui/suggestions/suggest-std-when-using-type.fixed new file mode 100644 index 000000000..102c5c186 --- /dev/null +++ b/tests/ui/suggestions/suggest-std-when-using-type.fixed @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let pi = std::f32::consts::PI; //~ ERROR ambiguous associated type + let bytes = "hello world".as_bytes(); + let string = std::str::from_utf8(bytes).unwrap(); + //~^ ERROR no function or associated item named `from_utf8` found + println!("{pi} {bytes:?} {string}"); +} diff --git a/tests/ui/suggestions/suggest-std-when-using-type.rs b/tests/ui/suggestions/suggest-std-when-using-type.rs new file mode 100644 index 000000000..5abc016de --- /dev/null +++ b/tests/ui/suggestions/suggest-std-when-using-type.rs @@ -0,0 +1,8 @@ +// run-rustfix +fn main() { + let pi = f32::consts::PI; //~ ERROR ambiguous associated type + let bytes = "hello world".as_bytes(); + let string = str::from_utf8(bytes).unwrap(); + //~^ ERROR no function or associated item named `from_utf8` found + println!("{pi} {bytes:?} {string}"); +} diff --git a/tests/ui/suggestions/suggest-std-when-using-type.stderr b/tests/ui/suggestions/suggest-std-when-using-type.stderr new file mode 100644 index 000000000..6f890b87b --- /dev/null +++ b/tests/ui/suggestions/suggest-std-when-using-type.stderr @@ -0,0 +1,26 @@ +error[E0223]: ambiguous associated type + --> $DIR/suggest-std-when-using-type.rs:3:14 + | +LL | let pi = f32::consts::PI; + | ^^^^^^^^^^^ + | +help: you are looking for the module in `std`, not the primitive type + | +LL | let pi = std::f32::consts::PI; + | +++++ + +error[E0599]: no function or associated item named `from_utf8` found for type `str` in the current scope + --> $DIR/suggest-std-when-using-type.rs:5:23 + | +LL | let string = str::from_utf8(bytes).unwrap(); + | ^^^^^^^^^ function or associated item not found in `str` + | +help: you are looking for the module in `std`, not the primitive type + | +LL | let string = std::str::from_utf8(bytes).unwrap(); + | +++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0223, E0599. +For more information about an error, try `rustc --explain E0223`. diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs new file mode 100644 index 000000000..03c7ed347 --- /dev/null +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs @@ -0,0 +1,22 @@ +// edition:2021 + +pub trait Trait<'a, T> {} + +pub struct Struct; +pub enum Enum {} + +pub union Union { + f1: usize, +} + +impl<'a, T> Struct for Trait<'a, T> {} +//~^ ERROR expected trait, found struct `Struct` +//~| ERROR trait objects must include the `dyn` keyword + +impl<'a, T> Enum for Trait<'a, T> {} +//~^ ERROR expected trait, found enum `Enum` + +impl<'a, T> Union for Trait<'a, T> {} +//~^ ERROR expected trait, found union `Union` + +fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr new file mode 100644 index 000000000..87e716436 --- /dev/null +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr @@ -0,0 +1,48 @@ +error[E0404]: expected trait, found struct `Struct` + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:13 + | +LL | impl<'a, T> Struct for Trait<'a, T> {} + | ^^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Struct {} + | ~~~~~~~~~~~~ ~~~~~~~~~ + +error[E0404]: expected trait, found enum `Enum` + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:16:13 + | +LL | impl<'a, T> Enum for Trait<'a, T> {} + | ^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Enum {} + | ~~~~~~~~~~~~ ~~~~~~~ + +error[E0404]: expected trait, found union `Union` + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13 + | +LL | impl<'a, T> Union for Trait<'a, T> {} + | ^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Union {} + | ~~~~~~~~~~~~ ~~~~~~~~ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:27 + | +LL | impl<'a, T> Struct for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | impl<'a, T> Struct for dyn Trait<'a, T> {} + | +++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0404, E0782. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs new file mode 100644 index 000000000..947bc2c79 --- /dev/null +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs @@ -0,0 +1,21 @@ +pub trait Trait<'a, T> {} + +pub struct Struct; +pub enum Enum {} + +pub union Union { + f1: usize, +} + +impl<'a, T> Struct for Trait<'a, T> {} +//~^ ERROR expected trait, found struct `Struct` +//~| WARNING trait objects without an explicit `dyn` are deprecated +//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + +impl<'a, T> Enum for Trait<'a, T> {} +//~^ ERROR expected trait, found enum `Enum` + +impl<'a, T> Union for Trait<'a, T> {} +//~^ ERROR expected trait, found union `Union` + +fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr new file mode 100644 index 000000000..ffd505fff --- /dev/null +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr @@ -0,0 +1,50 @@ +error[E0404]: expected trait, found struct `Struct` + --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:13 + | +LL | impl<'a, T> Struct for Trait<'a, T> {} + | ^^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Struct {} + | ~~~~~~~~~~~~ ~~~~~~~~~ + +error[E0404]: expected trait, found enum `Enum` + --> $DIR/suggest-swapping-self-ty-and-trait.rs:15:13 + | +LL | impl<'a, T> Enum for Trait<'a, T> {} + | ^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Enum {} + | ~~~~~~~~~~~~ ~~~~~~~ + +error[E0404]: expected trait, found union `Union` + --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13 + | +LL | impl<'a, T> Union for Trait<'a, T> {} + | ^^^^^^^^ not a trait + | +help: `impl` items mention the trait being implemented first and the type it is being implemented for second + | +LL | impl<'a, T> Trait<'a, T> for Union {} + | ~~~~~~~~~~~~ ~~~~~~~~ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:27 + | +LL | impl<'a, T> Struct for Trait<'a, T> {} + | ^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | impl<'a, T> Struct for dyn Trait<'a, T> {} + | +++ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/suggestions/suggest-trait-items.rs b/tests/ui/suggestions/suggest-trait-items.rs new file mode 100644 index 000000000..9d42a7342 --- /dev/null +++ b/tests/ui/suggestions/suggest-trait-items.rs @@ -0,0 +1,48 @@ +trait Foo { + type Type; + + fn foo(); + fn bar(); + fn qux(); +} + +struct A; + +impl Foo for A { +//~^ ERROR not all trait items implemented + type Typ = (); + //~^ ERROR type `Typ` is not a member of trait + //~| HELP there is an associated type with a similar name + + fn fooo() {} + //~^ ERROR method `fooo` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn barr() {} + //~^ ERROR method `barr` is not a member of trait + //~| HELP there is an associated function with a similar name + + fn quux() {} + //~^ ERROR method `quux` is not a member of trait + //~| HELP there is an associated function with a similar name +} +//~^ HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item +//~| HELP implement the missing item + +trait Bar { + const Const: i32; +} + +struct B; + +impl Bar for B { +//~^ ERROR not all trait items implemented + const Cnst: i32 = 0; + //~^ ERROR const `Cnst` is not a member of trait + //~| HELP there is an associated constant with a similar name +} +//~^ HELP implement the missing item + +fn main() {} diff --git a/tests/ui/suggestions/suggest-trait-items.stderr b/tests/ui/suggestions/suggest-trait-items.stderr new file mode 100644 index 000000000..8bc3df7b8 --- /dev/null +++ b/tests/ui/suggestions/suggest-trait-items.stderr @@ -0,0 +1,74 @@ +error[E0437]: type `Typ` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:13:5 + | +LL | type Typ = (); + | ^^^^^---^^^^^^ + | | | + | | help: there is an associated type with a similar name: `Type` + | not a member of trait `Foo` + +error[E0407]: method `fooo` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:17:5 + | +LL | fn fooo() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `foo` + | not a member of trait `Foo` + +error[E0407]: method `barr` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:21:5 + | +LL | fn barr() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `bar` + | not a member of trait `Foo` + +error[E0407]: method `quux` is not a member of trait `Foo` + --> $DIR/suggest-trait-items.rs:25:5 + | +LL | fn quux() {} + | ^^^----^^^^^ + | | | + | | help: there is an associated function with a similar name: `qux` + | not a member of trait `Foo` + +error[E0438]: const `Cnst` is not a member of trait `Bar` + --> $DIR/suggest-trait-items.rs:42:5 + | +LL | const Cnst: i32 = 0; + | ^^^^^^----^^^^^^^^^^ + | | | + | | help: there is an associated constant with a similar name: `Const` + | not a member of trait `Bar` + +error[E0046]: not all trait items implemented, missing: `Type`, `foo`, `bar`, `qux` + --> $DIR/suggest-trait-items.rs:11:1 + | +LL | type Type; + | --------- `Type` from trait +LL | +LL | fn foo(); + | --------- `foo` from trait +LL | fn bar(); + | --------- `bar` from trait +LL | fn qux(); + | --------- `qux` from trait +... +LL | impl Foo for A { + | ^^^^^^^^^^^^^^ missing `Type`, `foo`, `bar`, `qux` in implementation + +error[E0046]: not all trait items implemented, missing: `Const` + --> $DIR/suggest-trait-items.rs:40:1 + | +LL | const Const: i32; + | ---------------- `Const` from trait +... +LL | impl Bar for B { + | ^^^^^^^^^^^^^^ missing `Const` in implementation + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0046, E0407, E0437, E0438. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.rs b/tests/ui/suggestions/suggest-tryinto-edition-change.rs new file mode 100644 index 000000000..70c4b210d --- /dev/null +++ b/tests/ui/suggestions/suggest-tryinto-edition-change.rs @@ -0,0 +1,32 @@ +// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions +// Edition 2021 change +// edition:2018 + +fn test() { + let _i: i16 = 0_i32.try_into().unwrap(); + //~^ ERROR no method named `try_into` found for type `i32` in the current scope + //~| NOTE method not found in `i32` + //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + + let _i: i16 = TryFrom::try_from(0_i32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE use of undeclared type + //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 + + let _i: i16 = TryInto::try_into(0_i32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE use of undeclared type + //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021 + + let _v: Vec<_> = FromIterator::from_iter(&[1]); + //~^ ERROR failed to resolve: use of undeclared type + //~| NOTE use of undeclared type + //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 + //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 +} + +fn main() { + test(); +} diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr new file mode 100644 index 000000000..018083f9e --- /dev/null +++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -0,0 +1,69 @@ +error[E0433]: failed to resolve: use of undeclared type `TryFrom` + --> $DIR/suggest-tryinto-edition-change.rs:11:19 + | +LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap(); + | ^^^^^^^ use of undeclared type `TryFrom` + | + = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 + = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 +help: consider importing one of these items + | +LL | use core::convert::TryFrom; + | +LL | use std::convert::TryFrom; + | + +error[E0433]: failed to resolve: use of undeclared type `TryInto` + --> $DIR/suggest-tryinto-edition-change.rs:17:19 + | +LL | let _i: i16 = TryInto::try_into(0_i32).unwrap(); + | ^^^^^^^ use of undeclared type `TryInto` + | + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 + = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021 +help: consider importing one of these items + | +LL | use core::convert::TryInto; + | +LL | use std::convert::TryInto; + | + +error[E0433]: failed to resolve: use of undeclared type `FromIterator` + --> $DIR/suggest-tryinto-edition-change.rs:23:22 + | +LL | let _v: Vec<_> = FromIterator::from_iter(&[1]); + | ^^^^^^^^^^^^ use of undeclared type `FromIterator` + | + = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 + = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 +help: a trait with a similar name exists + | +LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]); + | ~~~~~~~~~~~~ +help: consider importing one of these items + | +LL | use core::iter::FromIterator; + | +LL | use std::iter::FromIterator; + | + +error[E0599]: no method named `try_into` found for type `i32` in the current scope + --> $DIR/suggest-tryinto-edition-change.rs:6:25 + | +LL | let _i: i16 = 0_i32.try_into().unwrap(); + | ^^^^^^^^ method not found in `i32` + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | + = note: the method is available for `i32` here + | + = help: items from traits can only be used if the trait is in scope + = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::convert::TryInto; + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0433, E0599. +For more information about an error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/suggest-using-chars.rs b/tests/ui/suggestions/suggest-using-chars.rs new file mode 100644 index 000000000..95732881b --- /dev/null +++ b/tests/ui/suggestions/suggest-using-chars.rs @@ -0,0 +1,7 @@ +pub fn main() { + let _ = "foo".iter(); //~ ERROR no method named `iter` found for reference `&'static str` in the current scope + let _ = "foo".foo(); //~ ERROR no method named `foo` found for reference `&'static str` in the current scope + let _ = String::from("bar").iter(); //~ ERROR no method named `iter` found for struct `String` in the current scope + let _ = (&String::from("bar")).iter(); //~ ERROR no method named `iter` found for reference `&String` in the current scope + let _ = 0.iter(); //~ ERROR no method named `iter` found for type `{integer}` in the current scope +} diff --git a/tests/ui/suggestions/suggest-using-chars.stderr b/tests/ui/suggestions/suggest-using-chars.stderr new file mode 100644 index 000000000..99bcfb08a --- /dev/null +++ b/tests/ui/suggestions/suggest-using-chars.stderr @@ -0,0 +1,48 @@ +error[E0599]: no method named `iter` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:2:19 + | +LL | let _ = "foo".iter(); + | ^^^^ method not found in `&'static str` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = "foo".chars(); + | ~~~~~ + +error[E0599]: no method named `foo` found for reference `&'static str` in the current scope + --> $DIR/suggest-using-chars.rs:3:19 + | +LL | let _ = "foo".foo(); + | ^^^ method not found in `&'static str` + +error[E0599]: no method named `iter` found for struct `String` in the current scope + --> $DIR/suggest-using-chars.rs:4:33 + | +LL | let _ = String::from("bar").iter(); + | ^^^^ method not found in `String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = String::from("bar").chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for reference `&String` in the current scope + --> $DIR/suggest-using-chars.rs:5:36 + | +LL | let _ = (&String::from("bar")).iter(); + | ^^^^ method not found in `&String` + | +help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars` + | +LL | let _ = (&String::from("bar")).chars(); + | ~~~~~ + +error[E0599]: no method named `iter` found for type `{integer}` in the current scope + --> $DIR/suggest-using-chars.rs:6:15 + | +LL | let _ = 0.iter(); + | ^^^^ method not found in `{integer}` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest-variants.rs b/tests/ui/suggestions/suggest-variants.rs new file mode 100644 index 000000000..dd05d0f04 --- /dev/null +++ b/tests/ui/suggestions/suggest-variants.rs @@ -0,0 +1,18 @@ +#[derive(Debug)] +enum Shape { + Square { size: i32 }, + Circle { radius: i32 }, +} + +struct S { + x: usize, +} + +fn main() { + println!("My shape is {:?}", Shape::Squareee { size: 5}); //~ ERROR no variant named `Squareee` + println!("My shape is {:?}", Shape::Circl { size: 5}); //~ ERROR no variant named `Circl` + println!("My shape is {:?}", Shape::Rombus{ size: 5}); //~ ERROR no variant named `Rombus` + Shape::Squareee; //~ ERROR no variant + Shape::Circl; //~ ERROR no variant + Shape::Rombus; //~ ERROR no variant +} diff --git a/tests/ui/suggestions/suggest-variants.stderr b/tests/ui/suggestions/suggest-variants.stderr new file mode 100644 index 000000000..a422bc656 --- /dev/null +++ b/tests/ui/suggestions/suggest-variants.stderr @@ -0,0 +1,63 @@ +error[E0599]: no variant named `Squareee` found for enum `Shape` + --> $DIR/suggest-variants.rs:12:41 + | +LL | enum Shape { + | ---------- variant `Squareee` not found here +... +LL | println!("My shape is {:?}", Shape::Squareee { size: 5}); + | ^^^^^^^^ help: there is a variant with a similar name: `Square` + +error[E0599]: no variant named `Circl` found for enum `Shape` + --> $DIR/suggest-variants.rs:13:41 + | +LL | enum Shape { + | ---------- variant `Circl` not found here +... +LL | println!("My shape is {:?}", Shape::Circl { size: 5}); + | ^^^^^ help: there is a variant with a similar name: `Circle` + +error[E0599]: no variant named `Rombus` found for enum `Shape` + --> $DIR/suggest-variants.rs:14:41 + | +LL | enum Shape { + | ---------- variant `Rombus` not found here +... +LL | println!("My shape is {:?}", Shape::Rombus{ size: 5}); + | ^^^^^^ variant not found in `Shape` + +error[E0599]: no variant or associated item named `Squareee` found for enum `Shape` in the current scope + --> $DIR/suggest-variants.rs:15:12 + | +LL | enum Shape { + | ---------- variant or associated item `Squareee` not found for this enum +... +LL | Shape::Squareee; + | ^^^^^^^^ + | | + | variant or associated item not found in `Shape` + | help: there is a variant with a similar name: `Square` + +error[E0599]: no variant or associated item named `Circl` found for enum `Shape` in the current scope + --> $DIR/suggest-variants.rs:16:12 + | +LL | enum Shape { + | ---------- variant or associated item `Circl` not found for this enum +... +LL | Shape::Circl; + | ^^^^^ + | | + | variant or associated item not found in `Shape` + | help: there is a variant with a similar name: `Circle` + +error[E0599]: no variant or associated item named `Rombus` found for enum `Shape` in the current scope + --> $DIR/suggest-variants.rs:17:12 + | +LL | enum Shape { + | ---------- variant or associated item `Rombus` not found for this enum +... +LL | Shape::Rombus; + | ^^^^^^ variant or associated item not found in `Shape` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/suggest_print_over_printf.rs b/tests/ui/suggestions/suggest_print_over_printf.rs new file mode 100644 index 000000000..124ddec50 --- /dev/null +++ b/tests/ui/suggestions/suggest_print_over_printf.rs @@ -0,0 +1,8 @@ +// Suggest print macro when user erroneously uses printf + +fn main() { + let x = 4; + printf("%d", x); + //~^ ERROR cannot find function `printf` in this scope + //~| HELP you may have meant to use the `print` macro +} diff --git a/tests/ui/suggestions/suggest_print_over_printf.stderr b/tests/ui/suggestions/suggest_print_over_printf.stderr new file mode 100644 index 000000000..1214bec16 --- /dev/null +++ b/tests/ui/suggestions/suggest_print_over_printf.stderr @@ -0,0 +1,14 @@ +error[E0425]: cannot find function `printf` in this scope + --> $DIR/suggest_print_over_printf.rs:5:5 + | +LL | printf("%d", x); + | ^^^^^^ not found in this scope + | +help: you may have meant to use the `print` macro + | +LL | print!("%d", x); + | ~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/too-many-field-suggestions.rs b/tests/ui/suggestions/too-many-field-suggestions.rs new file mode 100644 index 000000000..905f9502c --- /dev/null +++ b/tests/ui/suggestions/too-many-field-suggestions.rs @@ -0,0 +1,29 @@ +struct Thing { + a0: Foo, + a1: Foo, + a2: Foo, + a3: Foo, + a4: Foo, + a5: Foo, + a6: Foo, + a7: Foo, + a8: Foo, + a9: Foo, +} + +struct Foo { + field: Field, +} + +struct Field; + +impl Foo { + fn bar(&self) {} +} + +fn bar(t: Thing) { + t.bar(); //~ ERROR no method named `bar` found for struct `Thing` + t.field; //~ ERROR no field `field` on type `Thing` +} + +fn main() {} diff --git a/tests/ui/suggestions/too-many-field-suggestions.stderr b/tests/ui/suggestions/too-many-field-suggestions.stderr new file mode 100644 index 000000000..63ad6fdb1 --- /dev/null +++ b/tests/ui/suggestions/too-many-field-suggestions.stderr @@ -0,0 +1,44 @@ +error[E0599]: no method named `bar` found for struct `Thing` in the current scope + --> $DIR/too-many-field-suggestions.rs:25:7 + | +LL | struct Thing { + | ------------ method `bar` not found for this struct +... +LL | t.bar(); + | ^^^ method not found in `Thing` + | +help: some of the expressions' fields have a method of the same name + | +LL | t.a0.bar(); + | +++ +LL | t.a1.bar(); + | +++ +LL | t.a2.bar(); + | +++ +LL | t.a3.bar(); + | +++ + and 6 other candidates + +error[E0609]: no field `field` on type `Thing` + --> $DIR/too-many-field-suggestions.rs:26:7 + | +LL | t.field; + | ^^^^^ unknown field + | + = note: available fields are: `a0`, `a1`, `a2`, `a3`, `a4` ... and 5 others +help: some of the expressions' fields have a field of the same name + | +LL | t.a0.field; + | +++ +LL | t.a1.field; + | +++ +LL | t.a2.field; + | +++ +LL | t.a3.field; + | +++ + and 6 other candidates + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0609. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed new file mode 100644 index 000000000..8ef7e34ab --- /dev/null +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.fixed @@ -0,0 +1,43 @@ +// run-rustfix +#![allow(unused)] // for the fixed file + +trait Trait { + type A; + + fn func(&self) -> Self::A; +} + +struct S(T); +impl S { + fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types + } + + fn ban(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types + } +} + +fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs new file mode 100644 index 000000000..7bd38d0d4 --- /dev/null +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.rs @@ -0,0 +1,43 @@ +// run-rustfix +#![allow(unused)] // for the fixed file + +trait Trait { + type A; + + fn func(&self) -> Self::A; +} + +struct S(T); +impl S { + fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types + } + + fn ban(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types + } +} + +fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait, _: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr new file mode 100644 index 000000000..ac839ff7e --- /dev/null +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction-fixable.stderr @@ -0,0 +1,143 @@ +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:13:13 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn foo<'a, T: Trait + 'a>(&self, _: impl Trait, x: impl Trait, _: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:17:13 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn ban(x: T) where T: Trait { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:22:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn foo<'a, T: Trait + 'a>(_: impl Trait, x: impl Trait, _: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:26:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn bar>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:30:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type ` as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type ` as Trait>::A` to `usize` + | +LL | fn foo2(x: impl Trait) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:34:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `>::A` to `usize` + | +LL | fn bar2>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:38:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction-fixable.rs:41:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn ban(x: T) where T: Trait { + | +++++++++++ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs new file mode 100644 index 000000000..0d90e4495 --- /dev/null +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.rs @@ -0,0 +1,44 @@ +// These are all the possible variations of this error I could think of for. +// `trait-with-missing-associated-type-restriction-fixable.rs` contains the subset of these that +// can be fixed with `rustfix`. + +trait Trait { + type A; + + fn func(&self) -> Self::A; + fn funk(&self, _: Self::A); + fn funq(&self) -> Self::A {} //~ ERROR mismatched types +} + +fn foo(_: impl Trait, x: impl Trait) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn foo2(x: impl Trait) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bar2>(x: T) { + x.funk(3); //~ ERROR mismatched types + qux(x.func()) //~ ERROR mismatched types +} + +fn baz>(x: T) { + qux(x.func()) //~ ERROR mismatched types +} + +fn bat(x: &mut dyn Trait<(), A = ()>) { + qux(x.func()) //~ ERROR mismatched types +} + +fn ban(x: T) where T: Trait { + qux(x.func()) //~ ERROR mismatched types +} + +fn qux(_: usize) {} + +fn main() {} diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr new file mode 100644 index 000000000..f520d88c6 --- /dev/null +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -0,0 +1,177 @@ +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:10:31 + | +LL | fn funq(&self) -> Self::A {} + | ^^ expected associated type, found `()` + | + = note: expected associated type `>::A` + found unit type `()` +help: a method is available that returns `>::A` + --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5 + | +LL | fn func(&self) -> Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:14:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn foo(_: impl Trait, x: impl Trait) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:18:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn bar>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:22:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type ` as Trait>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type ` as Trait>::A` to `usize` + | +LL | fn foo2(x: impl Trait) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:26:12 + | +LL | x.funk(3); + | ---- ^ expected associated type, found integer + | | + | arguments to this method are incorrect + | + = note: expected associated type `>::A` + found type `{integer}` +help: some methods are available that return `>::A` + --> $DIR/trait-with-missing-associated-type-restriction.rs:8:5 + | +LL | fn func(&self) -> Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::func` +LL | fn funk(&self, _: Self::A); +LL | fn funq(&self) -> Self::A {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq` +note: associated function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8 + | +LL | fn funk(&self, _: Self::A); + | ^^^^ +help: consider constraining the associated type `>::A` to `{integer}` + | +LL | fn bar2>(x: T) { + | +++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:27:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `>::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `>::A` to `usize` + | +LL | fn bar2>(x: T) { + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:31:9 + | +LL | fn baz>(x: T) { + | - this type parameter +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found type parameter `D` + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found type parameter `D` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:35:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found `()` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- + +error[E0308]: mismatched types + --> $DIR/trait-with-missing-associated-type-restriction.rs:39:9 + | +LL | qux(x.func()) + | --- ^^^^^^^^ expected `usize`, found associated type + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found associated type `::A` +note: function defined here + --> $DIR/trait-with-missing-associated-type-restriction.rs:42:4 + | +LL | fn qux(_: usize) {} + | ^^^ -------- +help: consider constraining the associated type `::A` to `usize` + | +LL | fn ban(x: T) where T: Trait { + | +++++++++++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs new file mode 100644 index 000000000..f882a159f --- /dev/null +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs @@ -0,0 +1,27 @@ +// Regression test for #87051, where a double semicolon was erroneously +// suggested after a `?` operator. + +fn main() -> Result<(), ()> { + a(|| { + b() + //~^ ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found `i32` + //~| HELP: consider using a semicolon here + })?; + + // Here, we do want to suggest a semicolon: + let x = Ok(42); + if true { + //~^ NOTE: expected this to be `()` + x? + //~^ ERROR: mismatched types [E0308] + //~| NOTE: expected `()`, found integer + //~| HELP: consider using a semicolon here + } + //~^ HELP: consider using a semicolon here + + Ok(()) +} + +fn a(f: F) -> Result<(), ()> where F: FnMut() { Ok(()) } +fn b() -> i32 { 42 } diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr new file mode 100644 index 000000000..939285498 --- /dev/null +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9 + | +LL | b() + | ^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `i32` + +error[E0308]: mismatched types + --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9 + | +LL | / if true { +LL | | +LL | | x? + | | ^^ expected `()`, found integer +LL | | +LL | | +LL | | +LL | | } + | |_____- expected this to be `()` + | +help: consider using a semicolon here + | +LL | x?; + | + +help: consider using a semicolon here + | +LL | }; + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/try-removing-the-field.rs b/tests/ui/suggestions/try-removing-the-field.rs new file mode 100644 index 000000000..1b7289b22 --- /dev/null +++ b/tests/ui/suggestions/try-removing-the-field.rs @@ -0,0 +1,32 @@ +// run-pass + +#![allow(dead_code)] + +struct Foo { + foo: i32, + bar: (), + baz: (), +} + +fn use_foo(x: Foo) -> i32 { + let Foo { foo, bar, .. } = x; //~ WARNING unused variable: `bar` + //~| help: try removing the field + return foo; +} + +// issue #105028, suggest removing the field only for shorthand +fn use_match(x: Foo) { + match x { + Foo { foo: unused, .. } => { //~ WARNING unused variable + //~| help: if this is intentional, prefix it with an underscore + } + } + + match x { + Foo { foo, .. } => { //~ WARNING unused variable + //~| help: try removing the field + } + } +} + +fn main() {} diff --git a/tests/ui/suggestions/try-removing-the-field.stderr b/tests/ui/suggestions/try-removing-the-field.stderr new file mode 100644 index 000000000..7a6013d4a --- /dev/null +++ b/tests/ui/suggestions/try-removing-the-field.stderr @@ -0,0 +1,26 @@ +warning: unused variable: `bar` + --> $DIR/try-removing-the-field.rs:12:20 + | +LL | let Foo { foo, bar, .. } = x; + | ^^^- + | | + | help: try removing the field + | + = note: `#[warn(unused_variables)]` on by default + +warning: unused variable: `unused` + --> $DIR/try-removing-the-field.rs:20:20 + | +LL | Foo { foo: unused, .. } => { + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + +warning: unused variable: `foo` + --> $DIR/try-removing-the-field.rs:26:15 + | +LL | Foo { foo, .. } => { + | ^^^- + | | + | help: try removing the field + +warning: 3 warnings emitted + diff --git a/tests/ui/suggestions/type-ascription-and-other-error.rs b/tests/ui/suggestions/type-ascription-and-other-error.rs new file mode 100644 index 000000000..99ab2f3c8 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-and-other-error.rs @@ -0,0 +1,6 @@ +fn main() { + not rust; //~ ERROR + let _ = 0: i32; // (error hidden by existing error) + #[cfg(FALSE)] + let _ = 0: i32; // (warning hidden by existing error) +} diff --git a/tests/ui/suggestions/type-ascription-and-other-error.stderr b/tests/ui/suggestions/type-ascription-and-other-error.stderr new file mode 100644 index 000000000..eadf634bb --- /dev/null +++ b/tests/ui/suggestions/type-ascription-and-other-error.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `rust` + --> $DIR/type-ascription-and-other-error.rs:2:9 + | +LL | not rust; + | ^^^^ expected one of 8 possible tokens + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/type-ascription-instead-of-let.rs b/tests/ui/suggestions/type-ascription-instead-of-let.rs new file mode 100644 index 000000000..0e1c30750 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-let.rs @@ -0,0 +1,10 @@ +fn fun(x: i32) -> i32 { x } + +fn main() { + let closure_annotated = |value: i32| -> i32 { + temp: i32 = fun(5i32); + //~^ ERROR cannot find value `temp` in this scope + temp + value + 1 + //~^ ERROR cannot find value `temp` in this scope + }; +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-let.stderr b/tests/ui/suggestions/type-ascription-instead-of-let.stderr new file mode 100644 index 000000000..92e4b5798 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-let.stderr @@ -0,0 +1,18 @@ +error[E0425]: cannot find value `temp` in this scope + --> $DIR/type-ascription-instead-of-let.rs:5:9 + | +LL | temp: i32 = fun(5i32); + | ^^^^ + | | + | not found in this scope + | help: maybe you meant to write an assignment here: `let temp` + +error[E0425]: cannot find value `temp` in this scope + --> $DIR/type-ascription-instead-of-let.rs:7:9 + | +LL | temp + value + 1 + | ^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.fixed b/tests/ui/suggestions/type-ascription-instead-of-method.fixed new file mode 100644 index 000000000..56b740b0d --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-method.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Box::new("foo".to_string()); + //~^ ERROR expected type, found +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.rs b/tests/ui/suggestions/type-ascription-instead-of-method.rs new file mode 100644 index 000000000..a603e09e7 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-method.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Box:new("foo".to_string()); + //~^ ERROR expected type, found +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.stderr b/tests/ui/suggestions/type-ascription-instead-of-method.stderr new file mode 100644 index 000000000..83bc33f41 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-method.stderr @@ -0,0 +1,12 @@ +error: expected type, found `"foo"` + --> $DIR/type-ascription-instead-of-method.rs:3:21 + | +LL | let _ = Box:new("foo".to_string()); + | - ^^^^^ expected type + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.fixed b/tests/ui/suggestions/type-ascription-instead-of-path-2.fixed new file mode 100644 index 000000000..787fcc120 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.fixed @@ -0,0 +1,6 @@ +// run-rustfix +fn main() -> Result<(), ()> { + let _ = vec![Ok(2)].into_iter().collect::,_>>()?; + //~^ ERROR expected `::`, found `(` + Ok(()) +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.rs b/tests/ui/suggestions/type-ascription-instead-of-path-2.rs new file mode 100644 index 000000000..934016b3b --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.rs @@ -0,0 +1,6 @@ +// run-rustfix +fn main() -> Result<(), ()> { + let _ = vec![Ok(2)].into_iter().collect:,_>>()?; + //~^ ERROR expected `::`, found `(` + Ok(()) +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr new file mode 100644 index 000000000..970b220b7 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr @@ -0,0 +1,12 @@ +error: expected `::`, found `(` + --> $DIR/type-ascription-instead-of-path-2.rs:3:63 + | +LL | let _ = vec![Ok(2)].into_iter().collect:,_>>()?; + | - ^ expected `::` + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs new file mode 100644 index 000000000..48d19f6dd --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs @@ -0,0 +1,14 @@ +enum A { + B, +} + +fn main() { + let _: Vec = A::B; + //~^ ERROR cannot find trait `B` in this scope + //~| HELP you might have meant to write a path instead of an associated type bound + //~| ERROR associated type bounds are unstable + //~| HELP add `#![feature(associated_type_bounds)]` to the crate attributes to enable + //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied + //~| HELP add missing generic argument + //~| ERROR associated type bindings are not allowed here +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr new file mode 100644 index 000000000..fcff02e09 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr @@ -0,0 +1,41 @@ +error[E0405]: cannot find trait `B` in this scope + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:18 + | +LL | let _: Vec = A::B; + | ^ not found in this scope + | +help: you might have meant to write a path instead of an associated type bound + | +LL | let _: Vec = A::B; + | ~~ + +error[E0658]: associated type bounds are unstable + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 + | +LL | let _: Vec = A::B; + | ^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error[E0107]: this struct takes at least 1 generic argument but 0 generic arguments were supplied + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:12 + | +LL | let _: Vec = A::B; + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | let _: Vec = A::B; + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 + | +LL | let _: Vec = A::B; + | ^^^ associated type not allowed here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0229, E0405, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.rs b/tests/ui/suggestions/type-ascription-instead-of-path.rs new file mode 100644 index 000000000..ce40b55f1 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path.rs @@ -0,0 +1,5 @@ +fn main() { + std:io::stdin(); + //~^ ERROR failed to resolve: use of undeclared crate or module `io` + //~| ERROR expected value, found crate +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.stderr b/tests/ui/suggestions/type-ascription-instead-of-path.stderr new file mode 100644 index 000000000..518660cfa --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-path.stderr @@ -0,0 +1,18 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `io` + --> $DIR/type-ascription-instead-of-path.rs:2:9 + | +LL | std:io::stdin(); + | ^^ use of undeclared crate or module `io` + +error[E0423]: expected value, found crate `std` + --> $DIR/type-ascription-instead-of-path.rs:2:5 + | +LL | std:io::stdin(); + | ^^^- help: maybe you meant to write a path separator here: `::` + | | + | not a value + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0433. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.fixed b/tests/ui/suggestions/type-ascription-instead-of-variant.fixed new file mode 100644 index 000000000..b3247e128 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-variant.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Option::Some(""); + //~^ ERROR expected type, found +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.rs b/tests/ui/suggestions/type-ascription-instead-of-variant.rs new file mode 100644 index 000000000..6fd2c1954 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-variant.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _ = Option:Some(""); + //~^ ERROR expected type, found +} diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr new file mode 100644 index 000000000..f59ba78d4 --- /dev/null +++ b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr @@ -0,0 +1,12 @@ +error: expected type, found `""` + --> $DIR/type-ascription-instead-of-variant.rs:3:25 + | +LL | let _ = Option:Some(""); + | - ^^ expected type + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + +error: aborting due to previous error + diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.rs b/tests/ui/suggestions/type-mismatch-byte-literal.rs new file mode 100644 index 000000000..34199f8c3 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-byte-literal.rs @@ -0,0 +1,18 @@ +// Tests that a suggestion is issued for type mismatch errors when a +// u8 is expected and a char literal which is ASCII is supplied. + +fn foo(_t: u8) {} + +fn main() { + let _x: u8 = 'X'; + //~^ ERROR: mismatched types [E0308] + //~| HELP: if you meant to write a byte literal, prefix with `b` + + foo('#'); + //~^ ERROR: mismatched types [E0308] + //~| HELP: if you meant to write a byte literal, prefix with `b` + + // Do not issue the suggestion if the char literal isn't ASCII + let _t: u8 = '€'; + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.stderr b/tests/ui/suggestions/type-mismatch-byte-literal.stderr new file mode 100644 index 000000000..c9c2e7498 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-byte-literal.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-byte-literal.rs:7:18 + | +LL | let _x: u8 = 'X'; + | -- ^^^ expected `u8`, found `char` + | | + | expected due to this + | +help: if you meant to write a byte literal, prefix with `b` + | +LL | let _x: u8 = b'X'; + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-byte-literal.rs:11:9 + | +LL | foo('#'); + | --- ^^^ expected `u8`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/type-mismatch-byte-literal.rs:4:4 + | +LL | fn foo(_t: u8) {} + | ^^^ ------ +help: if you meant to write a byte literal, prefix with `b` + | +LL | foo(b'#'); + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-byte-literal.rs:16:18 + | +LL | let _t: u8 = '€'; + | -- ^^^ expected `u8`, found `char` + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs new file mode 100644 index 000000000..2ce122207 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs @@ -0,0 +1,9 @@ +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, c): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, c }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR struct `RGB` has no field named `c` +} diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr new file mode 100644 index 000000000..12466868f --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19 + | +LL | let _ = RGB { r, g, c }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r: r.into(), g, c }; + | ++ +++++++ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22 + | +LL | let _ = RGB { r, g, c }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g: g.into(), c }; + | ++ +++++++ + +error[E0560]: struct `RGB` has no field named `c` + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 + | +LL | let _ = RGB { r, g, c }; + | ^ help: a field with a similar name exists: `b` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed new file mode 100644 index 000000000..91758c0b2 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r: r.into(), g: g.into(), b: b.into() }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs new file mode 100644 index 000000000..9d3a17a72 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, b }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr new file mode 100644 index 000000000..72c84d167 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand.stderr @@ -0,0 +1,36 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19 + | +LL | let _ = RGB { r, g, b }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r: r.into(), g, b }; + | ++ +++++++ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22 + | +LL | let _ = RGB { r, g, b }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g: g.into(), b }; + | ++ +++++++ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25 + | +LL | let _ = RGB { r, g, b }; + | ^ expected `f64`, found `f32` + | +help: you can convert an `f32` to an `f64` + | +LL | let _ = RGB { r, g, b: b.into() }; + | ++ +++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/type-not-found-in-adt-field.rs b/tests/ui/suggestions/type-not-found-in-adt-field.rs new file mode 100644 index 000000000..4cbfe58d3 --- /dev/null +++ b/tests/ui/suggestions/type-not-found-in-adt-field.rs @@ -0,0 +1,9 @@ +struct Struct { + m: Vec>, //~ ERROR cannot find type `Someunknownname` in this scope + //~^ NOTE not found in this scope +} +struct OtherStruct { //~ HELP you might be missing a type parameter + m: K, //~ ERROR cannot find type `K` in this scope + //~^ NOTE not found in this scope +} +fn main() {} diff --git a/tests/ui/suggestions/type-not-found-in-adt-field.stderr b/tests/ui/suggestions/type-not-found-in-adt-field.stderr new file mode 100644 index 000000000..934ba87bb --- /dev/null +++ b/tests/ui/suggestions/type-not-found-in-adt-field.stderr @@ -0,0 +1,20 @@ +error[E0412]: cannot find type `Someunknownname` in this scope + --> $DIR/type-not-found-in-adt-field.rs:2:12 + | +LL | m: Vec>, + | ^^^^^^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `K` in this scope + --> $DIR/type-not-found-in-adt-field.rs:6:8 + | +LL | m: K, + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct OtherStruct { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/suggestions/undeclared-module-alloc.rs b/tests/ui/suggestions/undeclared-module-alloc.rs new file mode 100644 index 000000000..1defa1cef --- /dev/null +++ b/tests/ui/suggestions/undeclared-module-alloc.rs @@ -0,0 +1,5 @@ +// edition:2018 + +use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc` + +fn main() {} diff --git a/tests/ui/suggestions/undeclared-module-alloc.stderr b/tests/ui/suggestions/undeclared-module-alloc.stderr new file mode 100644 index 000000000..39169dfa9 --- /dev/null +++ b/tests/ui/suggestions/undeclared-module-alloc.stderr @@ -0,0 +1,11 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `alloc` + --> $DIR/undeclared-module-alloc.rs:3:5 + | +LL | use alloc::rc::Rc; + | ^^^^^ use of undeclared crate or module `alloc` + | + = help: add `extern crate alloc` to use the `alloc` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs new file mode 100644 index 000000000..f2485041d --- /dev/null +++ b/tests/ui/suggestions/unnamable-types.rs @@ -0,0 +1,39 @@ +// Test that we do not suggest to add type annotations for unnamable types. + +#![crate_type="lib"] +#![feature(generators)] + +const A = 5; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant + +static B: _ = "abc"; +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static variables +//~| NOTE: not allowed in type signatures +//~| HELP: replace with the correct type + + +// FIXME: this should also suggest a function pointer, as the closure is non-capturing +const C: _ = || 42; +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants +//~| NOTE: not allowed in type signatures +//~| NOTE: however, the inferred type + +struct S { t: T } +const D = S { t: { let i = 0; move || -> i32 { i } } }; +//~^ ERROR: missing type for `const` item +//~| NOTE: however, the inferred type + + +fn foo() -> i32 { 42 } +const E = foo; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant +const F = S { t: foo }; +//~^ ERROR: missing type for `const` item +//~| HELP: provide a type for the constant + + +const G = || -> i32 { yield 0; return 1; }; +//~^ ERROR: missing type for `const` item +//~| NOTE: however, the inferred type diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr new file mode 100644 index 000000000..24bedb529 --- /dev/null +++ b/tests/ui/suggestions/unnamable-types.stderr @@ -0,0 +1,66 @@ +error: missing type for `const` item + --> $DIR/unnamable-types.rs:6:8 + | +LL | const A = 5; + | ^ help: provide a type for the constant: `: i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/unnamable-types.rs:10:11 + | +LL | static B: _ = "abc"; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `&str` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/unnamable-types.rs:17:10 + | +LL | const C: _ = || 42; + | ^ not allowed in type signatures + | +note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named + --> $DIR/unnamable-types.rs:17:14 + | +LL | const C: _ = || 42; + | ^^^^^ + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:23:8 + | +LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; + | ^ + | +note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named + --> $DIR/unnamable-types.rs:23:11 + | +LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:29:8 + | +LL | const E = foo; + | ^ help: provide a type for the constant: `: fn() -> i32` + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:32:8 + | +LL | const F = S { t: foo }; + | ^ help: provide a type for the constant: `: S i32>` + +error: missing type for `const` item + --> $DIR/unnamable-types.rs:37:8 + | +LL | const G = || -> i32 { yield 0; return 1; }; + | ^ + | +note: however, the inferred type `[generator@$DIR/unnamable-types.rs:37:11: 37:20]` cannot be named + --> $DIR/unnamable-types.rs:37:11 + | +LL | const G = || -> i32 { yield 0; return 1; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs new file mode 100644 index 000000000..c1a944562 --- /dev/null +++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.rs @@ -0,0 +1,6 @@ +fn main() { + let _: f64 = 0..10; //~ ERROR mismatched types + let _: f64 = 1..; //~ ERROR mismatched types + let _: f64 = ..10; //~ ERROR mismatched types + let _: f64 = std::ops::Range { start: 0, end: 1 }; //~ ERROR mismatched types +} diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr new file mode 100644 index 000000000..34eaa8322 --- /dev/null +++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18 + | +LL | let _: f64 = 0..10; + | --- ^^^^^ expected `f64`, found struct `Range` + | | + | expected due to this + | + = note: expected type `f64` + found struct `std::ops::Range<{integer}>` +help: remove the unnecessary `.` operator for a floating point literal + | +LL | let _: f64 = 0.10; + | ~ + +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:3:18 + | +LL | let _: f64 = 1..; + | --- ^^^ expected `f64`, found struct `RangeFrom` + | | + | expected due to this + | + = note: expected type `f64` + found struct `RangeFrom<{integer}>` +help: remove the unnecessary `.` operator for a floating point literal + | +LL | let _: f64 = 1.; + | ~ + +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:4:18 + | +LL | let _: f64 = ..10; + | --- ^^^^ expected `f64`, found struct `RangeTo` + | | + | expected due to this + | + = note: expected type `f64` + found struct `RangeTo<{integer}>` +help: remove the unnecessary `.` operator and add an integer part for a floating point literal + | +LL | let _: f64 = 0.10; + | ~~ + +error[E0308]: mismatched types + --> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18 + | +LL | let _: f64 = std::ops::Range { start: 0, end: 1 }; + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range` + | | + | expected due to this + | + = note: expected type `f64` + found struct `std::ops::Range<{integer}>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/unsized-function-parameter.fixed b/tests/ui/suggestions/unsized-function-parameter.fixed new file mode 100644 index 000000000..18e93cb96 --- /dev/null +++ b/tests/ui/suggestions/unsized-function-parameter.fixed @@ -0,0 +1,23 @@ +// run-rustfix + +#![allow(dead_code, unused_variables)] + +fn foo1(bar: &str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo2(_bar: &str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo3(_: &str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn main() {} diff --git a/tests/ui/suggestions/unsized-function-parameter.rs b/tests/ui/suggestions/unsized-function-parameter.rs new file mode 100644 index 000000000..344ee71c1 --- /dev/null +++ b/tests/ui/suggestions/unsized-function-parameter.rs @@ -0,0 +1,23 @@ +// run-rustfix + +#![allow(dead_code, unused_variables)] + +fn foo1(bar: str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo2(_bar: str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn foo3(_: str) {} +//~^ ERROR the size for values of type `str` cannot be known at compilation time +//~| HELP the trait `Sized` is not implemented for `str` +//~| HELP unsized fn params are gated as an unstable feature +//~| HELP function arguments must have a statically known size, borrowed types always have a known size + +fn main() {} diff --git a/tests/ui/suggestions/unsized-function-parameter.stderr b/tests/ui/suggestions/unsized-function-parameter.stderr new file mode 100644 index 000000000..55d8d1ab1 --- /dev/null +++ b/tests/ui/suggestions/unsized-function-parameter.stderr @@ -0,0 +1,42 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-function-parameter.rs:5:9 + | +LL | fn foo1(bar: str) {} + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo1(bar: &str) {} + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-function-parameter.rs:11:9 + | +LL | fn foo2(_bar: str) {} + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo2(_bar: &str) {} + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-function-parameter.rs:17:9 + | +LL | fn foo3(_: str) {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo3(_: &str) {} + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/unused-closure-argument.rs b/tests/ui/suggestions/unused-closure-argument.rs new file mode 100644 index 000000000..677003ebf --- /dev/null +++ b/tests/ui/suggestions/unused-closure-argument.rs @@ -0,0 +1,20 @@ +#![deny(unused_variables)] + +struct Point { + x: i32, + y: i32, +} + +fn main() { + let points = vec!(Point { x: 1, y: 2 }, Point { x: 3, y: 4 }); + + let _: i32 = points.iter() + .map(|Point { x, y }| y) + //~^ ERROR unused variable + .sum(); + + let _: i32 = points.iter() + .map(|x| 4) + //~^ ERROR unused variable + .sum(); +} diff --git a/tests/ui/suggestions/unused-closure-argument.stderr b/tests/ui/suggestions/unused-closure-argument.stderr new file mode 100644 index 000000000..55195ce50 --- /dev/null +++ b/tests/ui/suggestions/unused-closure-argument.stderr @@ -0,0 +1,20 @@ +error: unused variable: `x` + --> $DIR/unused-closure-argument.rs:12:23 + | +LL | .map(|Point { x, y }| y) + | ^ help: try ignoring the field: `x: _` + | +note: the lint level is defined here + --> $DIR/unused-closure-argument.rs:1:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `x` + --> $DIR/unused-closure-argument.rs:17:15 + | +LL | .map(|x| 4) + | ^ help: if this is intentional, prefix it with an underscore: `_x` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/suggestions/use-placement-resolve.fixed b/tests/ui/suggestions/use-placement-resolve.fixed new file mode 100644 index 000000000..afe74cff2 --- /dev/null +++ b/tests/ui/suggestions/use-placement-resolve.fixed @@ -0,0 +1,13 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +use std::fmt::Debug; + +fn main() {} + +fn foobar(x: T) {} //~ ERROR expected trait, found derive macro diff --git a/tests/ui/suggestions/use-placement-resolve.rs b/tests/ui/suggestions/use-placement-resolve.rs new file mode 100644 index 000000000..b30ddb3af --- /dev/null +++ b/tests/ui/suggestions/use-placement-resolve.rs @@ -0,0 +1,11 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +fn main() {} + +fn foobar(x: T) {} //~ ERROR expected trait, found derive macro diff --git a/tests/ui/suggestions/use-placement-resolve.stderr b/tests/ui/suggestions/use-placement-resolve.stderr new file mode 100644 index 000000000..9da9e8e27 --- /dev/null +++ b/tests/ui/suggestions/use-placement-resolve.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found derive macro `Debug` + --> $DIR/use-placement-resolve.rs:11:14 + | +LL | fn foobar(x: T) {} + | ^^^^^ not a trait + | +help: consider importing this trait instead + | +LL | use std::fmt::Debug; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/suggestions/use-placement-typeck.fixed b/tests/ui/suggestions/use-placement-typeck.fixed new file mode 100644 index 000000000..37335da06 --- /dev/null +++ b/tests/ui/suggestions/use-placement-typeck.fixed @@ -0,0 +1,21 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +use m::Foo; +fn main() { + let s = m::S; + s.abc(); //~ ERROR no method named `abc` +} + +mod m { + pub trait Foo { + fn abc(&self) {} + } + pub struct S; + impl Foo for S{} +} diff --git a/tests/ui/suggestions/use-placement-typeck.rs b/tests/ui/suggestions/use-placement-typeck.rs new file mode 100644 index 000000000..aab20d2e9 --- /dev/null +++ b/tests/ui/suggestions/use-placement-typeck.rs @@ -0,0 +1,20 @@ +// compile-flags: --test +// run-rustfix +// Checks that the `use` suggestion appears *below* this inner attribute. +// There was an issue where the test synthetic #[allow(dead)] attribute on +// main which has a dummy span caused the suggestion to be placed at the top +// of the file. +#![allow(unused)] + +fn main() { + let s = m::S; + s.abc(); //~ ERROR no method named `abc` +} + +mod m { + pub trait Foo { + fn abc(&self) {} + } + pub struct S; + impl Foo for S{} +} diff --git a/tests/ui/suggestions/use-placement-typeck.stderr b/tests/ui/suggestions/use-placement-typeck.stderr new file mode 100644 index 000000000..3b2749773 --- /dev/null +++ b/tests/ui/suggestions/use-placement-typeck.stderr @@ -0,0 +1,21 @@ +error[E0599]: no method named `abc` found for struct `S` in the current scope + --> $DIR/use-placement-typeck.rs:11:7 + | +LL | s.abc(); + | ^^^ method not found in `S` +... +LL | fn abc(&self) {} + | --- the method is available for `S` here +LL | } +LL | pub struct S; + | ------------ method `abc` not found for this struct + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use m::Foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs new file mode 100644 index 000000000..8b6e8cfd7 --- /dev/null +++ b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs @@ -0,0 +1,13 @@ +pub trait T { + type A; + type B; + type C; +} +pub struct Foo { + i: Box>, + //~^ ERROR must be specified + //~| ERROR this trait takes 2 generic arguments but 4 generic arguments were supplied +} + + +fn main() {} diff --git a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr new file mode 100644 index 000000000..75b919232 --- /dev/null +++ b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr @@ -0,0 +1,32 @@ +error[E0107]: this trait takes 2 generic arguments but 4 generic arguments were supplied + --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16 + | +LL | i: Box>, + | ^ expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `X`, `Y` + --> $DIR/use-type-argument-instead-of-assoc-type.rs:1:11 + | +LL | pub trait T { + | ^ - - +help: replace the generic bounds with the associated types + | +LL | i: Box>, + | +++ +++ + +error[E0191]: the value of the associated types `A` (from trait `T`), `C` (from trait `T`) must be specified + --> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16 + | +LL | type A; + | ------ `A` defined here +LL | type B; +LL | type C; + | ------ `C` defined here +... +LL | i: Box>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated types `A`, `C` must be specified + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0191. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/suggestions/while-let-typo.rs b/tests/ui/suggestions/while-let-typo.rs new file mode 100644 index 000000000..dbbcdee3c --- /dev/null +++ b/tests/ui/suggestions/while-let-typo.rs @@ -0,0 +1,9 @@ +fn main() { + let foo = Some(0); + let bar = None; + while Some(x) = foo {} //~ ERROR cannot find value `x` in this scope + while Some(foo) = bar {} + while 3 = foo {} //~ ERROR mismatched types + while Some(3) = foo {} //~ ERROR invalid left-hand side of assignment + while x = 5 {} //~ ERROR cannot find value `x` in this scope +} diff --git a/tests/ui/suggestions/while-let-typo.stderr b/tests/ui/suggestions/while-let-typo.stderr new file mode 100644 index 000000000..7cc2ed314 --- /dev/null +++ b/tests/ui/suggestions/while-let-typo.stderr @@ -0,0 +1,45 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/while-let-typo.rs:4:16 + | +LL | while Some(x) = foo {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | while let Some(x) = foo {} + | +++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/while-let-typo.rs:8:11 + | +LL | while x = 5 {} + | ^ not found in this scope + | +help: you might have meant to use pattern matching + | +LL | while let x = 5 {} + | +++ + +error[E0308]: mismatched types + --> $DIR/while-let-typo.rs:6:11 + | +LL | while 3 = foo {} + | ^^^^^^^ expected `bool`, found `()` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/while-let-typo.rs:7:19 + | +LL | while Some(3) = foo {} + | - ^ + | | + | cannot assign to this expression + | +help: you might have meant to use pattern destructuring + | +LL | while let Some(3) = foo {} + | +++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0308, E0425. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/super-at-top-level.rs b/tests/ui/super-at-top-level.rs new file mode 100644 index 000000000..e4d587bc9 --- /dev/null +++ b/tests/ui/super-at-top-level.rs @@ -0,0 +1,4 @@ +use super::f; //~ ERROR there are too many leading `super` keywords + +fn main() { +} diff --git a/tests/ui/super-at-top-level.stderr b/tests/ui/super-at-top-level.stderr new file mode 100644 index 000000000..23613df67 --- /dev/null +++ b/tests/ui/super-at-top-level.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: there are too many leading `super` keywords + --> $DIR/super-at-top-level.rs:1:5 + | +LL | use super::f; + | ^^^^^ there are too many leading `super` keywords + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/super-fast-paren-parsing.rs b/tests/ui/super-fast-paren-parsing.rs new file mode 100644 index 000000000..cb42ff2c6 --- /dev/null +++ b/tests/ui/super-fast-paren-parsing.rs @@ -0,0 +1,25 @@ +// run-pass + +#![allow(unused_parens)] +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +// exec-env:RUST_MIN_STACK=16000000 +// rustc-env:RUST_MIN_STACK=16000000 +// +// Big stack is needed for pretty printing, a little sad... + +static a: isize = +((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +))))))))))))))))))))))))))))))))))))))))))))))))))) +))))))))))))))))))))))))))))))))))))))))))))))))))) +))))))))))))))))))))))))))))))))))))))))))))))))))) +))))))))))))))))))))))))))))))))))))))))))))))))))) +))))))))))))))))))))))))))))))))))))))))))))))))))) +; + +pub fn main() {} diff --git a/tests/ui/super.rs b/tests/ui/super.rs new file mode 100644 index 000000000..86c720288 --- /dev/null +++ b/tests/ui/super.rs @@ -0,0 +1,16 @@ +// run-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub mod a { + pub fn f() {} + pub mod b { + fn g() { + super::f(); + } + } +} + +pub fn main() { +} diff --git a/tests/ui/suppressed-error.rs b/tests/ui/suppressed-error.rs new file mode 100644 index 000000000..256ec1713 --- /dev/null +++ b/tests/ui/suppressed-error.rs @@ -0,0 +1,8 @@ +fn main() { + let (x, y) = (); +//~^ ERROR mismatched types +//~| expected unit type `()` +//~| found tuple `(_, _)` +//~| expected `()`, found tuple + return x; +} diff --git a/tests/ui/suppressed-error.stderr b/tests/ui/suppressed-error.stderr new file mode 100644 index 000000000..c2874ae9a --- /dev/null +++ b/tests/ui/suppressed-error.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/suppressed-error.rs:2:9 + | +LL | let (x, y) = (); + | ^^^^^^ -- this expression has type `()` + | | + | expected `()`, found tuple + | + = note: expected unit type `()` + found tuple `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/svh-add-nothing.rs b/tests/ui/svh-add-nothing.rs new file mode 100644 index 000000000..d7d037f0b --- /dev/null +++ b/tests/ui/svh-add-nothing.rs @@ -0,0 +1,14 @@ +// run-pass +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-base.rs + +// pretty-expanded FIXME #23616 + +extern crate a; +extern crate b; + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/auxiliary/changing-crates-a1.rs b/tests/ui/svh/auxiliary/changing-crates-a1.rs new file mode 100644 index 000000000..bc0559b8b --- /dev/null +++ b/tests/ui/svh/auxiliary/changing-crates-a1.rs @@ -0,0 +1,3 @@ +#![crate_name = "a"] + +pub fn foo() {} diff --git a/tests/ui/svh/auxiliary/changing-crates-a2.rs b/tests/ui/svh/auxiliary/changing-crates-a2.rs new file mode 100644 index 000000000..fafc6d5b1 --- /dev/null +++ b/tests/ui/svh/auxiliary/changing-crates-a2.rs @@ -0,0 +1,3 @@ +#![crate_name = "a"] + +pub fn foo() { println!("hello!"); } diff --git a/tests/ui/svh/auxiliary/changing-crates-b.rs b/tests/ui/svh/auxiliary/changing-crates-b.rs new file mode 100644 index 000000000..f9ce29e4c --- /dev/null +++ b/tests/ui/svh/auxiliary/changing-crates-b.rs @@ -0,0 +1,5 @@ +#![crate_name = "b"] + +extern crate a; + +pub fn foo() { a::foo::(); } diff --git a/tests/ui/svh/auxiliary/svh-a-base.rs b/tests/ui/svh/auxiliary/svh-a-base.rs new file mode 100644 index 000000000..36b41fc81 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-base.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +pub fn foo(_: isize) -> isize { + 3 +} + +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-a-change-lit.rs b/tests/ui/svh/auxiliary/svh-a-change-lit.rs new file mode 100644 index 000000000..c76f2c992 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-change-lit.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +pub fn foo(_: isize) -> isize { + 0 +} + +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-a-change-significant-cfg.rs b/tests/ui/svh/auxiliary/svh-a-change-significant-cfg.rs new file mode 100644 index 000000000..37f59c97e --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-change-significant-cfg.rs @@ -0,0 +1,27 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +#[cfg(some_flag)] +pub fn foo(_: isize) -> isize { + 3 +} + +#[cfg(not(some_flag))] +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-a-change-trait-bound.rs b/tests/ui/svh/auxiliary/svh-a-change-trait-bound.rs new file mode 100644 index 000000000..be24b1e22 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-change-trait-bound.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +pub fn foo(_: isize) -> isize { + 3 +} + +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-a-change-type-arg.rs b/tests/ui/svh/auxiliary/svh-a-change-type-arg.rs new file mode 100644 index 000000000..3fe102245 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-change-type-arg.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +pub fn foo(_: i32) -> isize { + 3 +} + +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-a-change-type-ret.rs b/tests/ui/svh/auxiliary/svh-a-change-type-ret.rs new file mode 100644 index 000000000..06e4fad06 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-change-type-ret.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : isize = 2; + +pub fn foo(_: isize) -> i64 { + 3 +} + +pub fn an_unused_name() -> i32 { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-a-change-type-static.rs b/tests/ui/svh/auxiliary/svh-a-change-type-static.rs new file mode 100644 index 000000000..440cb3213 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-a-change-type-static.rs @@ -0,0 +1,25 @@ +//! The `svh-a-*.rs` files are all deviations from the base file +//! svh-a-base.rs with some difference (usually in `fn foo`) that +//! should not affect the strict version hash (SVH) computation +//! (#14132). + +#![crate_name = "a"] + +macro_rules! three { + () => { 3 } +} + +pub trait U {} +pub trait V {} +impl U for () {} +impl V for () {} + +static A_CONSTANT : i32 = 2; + +pub fn foo(_: isize) -> isize { + 3 +} + +pub fn an_unused_name() -> isize { + 4 +} diff --git a/tests/ui/svh/auxiliary/svh-b.rs b/tests/ui/svh/auxiliary/svh-b.rs new file mode 100644 index 000000000..57029f708 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-b.rs @@ -0,0 +1,13 @@ +//! This is a client of the `a` crate defined in `svn-a-base.rs`. The +//! rpass and cfail tests (such as `run-pass/svh-add-comment.rs`) use +//! it by swapping in a different object code library crate built from +//! some variant of `svn-a-base.rs`, and then we are checking if the +//! compiler properly ignores or accepts the change, based on whether +//! the change could affect the downstream crate content or not +//! (#14132). + +#![crate_name = "b"] + +extern crate a; + +pub fn foo() { assert_eq!(a::foo::<()>(0), 3); } diff --git a/tests/ui/svh/auxiliary/svh-uta-base.rs b/tests/ui/svh/auxiliary/svh-uta-base.rs new file mode 100644 index 000000000..221a096e0 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-uta-base.rs @@ -0,0 +1,22 @@ +//! "svh-uta-trait.rs" is checking that we detect a +//! change from `use foo::TraitB` to use `foo::TraitB` in the hash +//! (SVH) computation (#14132), since that will affect method +//! resolution. +//! +//! This is the upstream crate. + +#![crate_name = "uta"] + +mod traits { + pub trait TraitA { fn val(&self) -> isize { 2 } } + pub trait TraitB { fn val(&self) -> isize { 3 } } +} + +impl traits::TraitA for () {} +impl traits::TraitB for () {} + +pub fn foo(_: isize) -> isize { + use traits::TraitA; + let v = (); + v.val() +} diff --git a/tests/ui/svh/auxiliary/svh-uta-change-use-trait.rs b/tests/ui/svh/auxiliary/svh-uta-change-use-trait.rs new file mode 100644 index 000000000..823d29571 --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-uta-change-use-trait.rs @@ -0,0 +1,22 @@ +//! "svh-uta-trait.rs" is checking that we detect a +//! change from `use foo::TraitB` to use `foo::TraitB` in the hash +//! (SVH) computation (#14132), since that will affect method +//! resolution. +//! +//! This is the upstream crate. + +#![crate_name = "uta"] + +mod traits { + pub trait TraitA { fn val(&self) -> isize { 2 } } + pub trait TraitB { fn val(&self) -> isize { 3 } } +} + +impl traits::TraitA for () {} +impl traits::TraitB for () {} + +pub fn foo(_: isize) -> isize { + use traits::TraitB; + let v = (); + v.val() +} diff --git a/tests/ui/svh/auxiliary/svh-utb.rs b/tests/ui/svh/auxiliary/svh-utb.rs new file mode 100644 index 000000000..a03e29dce --- /dev/null +++ b/tests/ui/svh/auxiliary/svh-utb.rs @@ -0,0 +1,12 @@ +//! "svh-uta-trait.rs" is checking that we detect a +//! change from `use foo::TraitB` to use `foo::TraitB` in the hash +//! (SVH) computation (#14132), since that will affect method +//! resolution. +//! +//! This is the downstream crate. + +#![crate_name = "utb"] + +extern crate uta; + +pub fn foo() { assert_eq!(uta::foo::<()>(0), 3); } diff --git a/tests/ui/svh/changing-crates.rs b/tests/ui/svh/changing-crates.rs new file mode 100644 index 000000000..66298e06e --- /dev/null +++ b/tests/ui/svh/changing-crates.rs @@ -0,0 +1,10 @@ +// note that these aux-build directives must be in this order +// aux-build:changing-crates-a1.rs +// aux-build:changing-crates-b.rs +// aux-build:changing-crates-a2.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() {} diff --git a/tests/ui/svh/changing-crates.stderr b/tests/ui/svh/changing-crates.stderr new file mode 100644 index 000000000..caefdfc96 --- /dev/null +++ b/tests/ui/svh/changing-crates.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/changing-crates.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-lit.rs b/tests/ui/svh/svh-change-lit.rs new file mode 100644 index 000000000..ea500711b --- /dev/null +++ b/tests/ui/svh/svh-change-lit.rs @@ -0,0 +1,12 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-change-lit.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/svh-change-lit.stderr b/tests/ui/svh/svh-change-lit.stderr new file mode 100644 index 000000000..5e890c6aa --- /dev/null +++ b/tests/ui/svh/svh-change-lit.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/svh-change-lit.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-significant-cfg.rs b/tests/ui/svh/svh-change-significant-cfg.rs new file mode 100644 index 000000000..ff919ea83 --- /dev/null +++ b/tests/ui/svh/svh-change-significant-cfg.rs @@ -0,0 +1,12 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-change-significant-cfg.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/svh-change-significant-cfg.stderr b/tests/ui/svh/svh-change-significant-cfg.stderr new file mode 100644 index 000000000..dcc250d52 --- /dev/null +++ b/tests/ui/svh/svh-change-significant-cfg.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/svh-change-significant-cfg.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-trait-bound.rs b/tests/ui/svh/svh-change-trait-bound.rs new file mode 100644 index 000000000..a4ba06eaf --- /dev/null +++ b/tests/ui/svh/svh-change-trait-bound.rs @@ -0,0 +1,12 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-change-trait-bound.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/svh-change-trait-bound.stderr b/tests/ui/svh/svh-change-trait-bound.stderr new file mode 100644 index 000000000..2035993d2 --- /dev/null +++ b/tests/ui/svh/svh-change-trait-bound.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/svh-change-trait-bound.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-type-arg.rs b/tests/ui/svh/svh-change-type-arg.rs new file mode 100644 index 000000000..d1651814b --- /dev/null +++ b/tests/ui/svh/svh-change-type-arg.rs @@ -0,0 +1,12 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-change-type-arg.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/svh-change-type-arg.stderr b/tests/ui/svh/svh-change-type-arg.stderr new file mode 100644 index 000000000..eef85aa95 --- /dev/null +++ b/tests/ui/svh/svh-change-type-arg.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/svh-change-type-arg.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-type-ret.rs b/tests/ui/svh/svh-change-type-ret.rs new file mode 100644 index 000000000..a4be50a64 --- /dev/null +++ b/tests/ui/svh/svh-change-type-ret.rs @@ -0,0 +1,12 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-change-type-ret.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/svh-change-type-ret.stderr b/tests/ui/svh/svh-change-type-ret.stderr new file mode 100644 index 000000000..247f74e50 --- /dev/null +++ b/tests/ui/svh/svh-change-type-ret.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/svh-change-type-ret.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-change-type-static.rs b/tests/ui/svh/svh-change-type-static.rs new file mode 100644 index 000000000..c470761be --- /dev/null +++ b/tests/ui/svh/svh-change-type-static.rs @@ -0,0 +1,12 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-a-base.rs +// aux-build:svh-b.rs +// aux-build:svh-a-change-type-static.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +extern crate a; +extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on + +fn main() { + b::foo() +} diff --git a/tests/ui/svh/svh-change-type-static.stderr b/tests/ui/svh/svh-change-type-static.stderr new file mode 100644 index 000000000..78b54f227 --- /dev/null +++ b/tests/ui/svh/svh-change-type-static.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `a` which `b` depends on + --> $DIR/svh-change-type-static.rs:8:1 + | +LL | extern crate b; + | ^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `a`: $PATH_a + crate `b`: $PATH_b + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/svh/svh-use-trait.rs b/tests/ui/svh/svh-use-trait.rs new file mode 100644 index 000000000..e144fdffb --- /dev/null +++ b/tests/ui/svh/svh-use-trait.rs @@ -0,0 +1,17 @@ +// note that these aux-build directives must be in this order +// aux-build:svh-uta-base.rs +// aux-build:svh-utb.rs +// aux-build:svh-uta-change-use-trait.rs +// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2" + +//! "svh-uta-trait.rs" is checking that we detect a +//! change from `use foo::TraitB` to use `foo::TraitB` in the hash +//! (SVH) computation (#14132), since that will affect method +//! resolution. + +extern crate uta; +extern crate utb; //~ ERROR: found possibly newer version of crate `uta` which `utb` depends + +fn main() { + utb::foo() +} diff --git a/tests/ui/svh/svh-use-trait.stderr b/tests/ui/svh/svh-use-trait.stderr new file mode 100644 index 000000000..d8a81864d --- /dev/null +++ b/tests/ui/svh/svh-use-trait.stderr @@ -0,0 +1,14 @@ +error[E0460]: found possibly newer version of crate `uta` which `utb` depends on + --> $DIR/svh-use-trait.rs:13:1 + | +LL | extern crate utb; + | ^^^^^^^^^^^^^^^^^ + | + = note: perhaps that crate needs to be recompiled? + = note: the following crate versions were found: + crate `uta`: $PATH_uta + crate `utb`: $PATH_utb + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0460`. diff --git a/tests/ui/swap-1.rs b/tests/ui/swap-1.rs new file mode 100644 index 000000000..d87114748 --- /dev/null +++ b/tests/ui/swap-1.rs @@ -0,0 +1,10 @@ +// run-pass + +use std::mem::swap; + +pub fn main() { + let mut x = 3; let mut y = 7; + swap(&mut x, &mut y); + assert_eq!(x, 7); + assert_eq!(y, 3); +} diff --git a/tests/ui/swap-overlapping.rs b/tests/ui/swap-overlapping.rs new file mode 100644 index 000000000..85b357e0c --- /dev/null +++ b/tests/ui/swap-overlapping.rs @@ -0,0 +1,44 @@ +// run-pass + +#![allow(dead_code)] +// Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same + +// pretty-expanded FIXME #23616 + +use std::ptr; + +pub fn main() { + let mut test = TestDescAndFn { + desc: TestDesc { + name: TestName::DynTestName("test".to_string()), + should_fail: false + }, + testfn: TestFn::DynTestFn(22), + }; + do_swap(&mut test); +} + +fn do_swap(test: &mut TestDescAndFn) { + unsafe { + ptr::swap(test, test); + } +} + +pub enum TestName { + DynTestName(String) +} + +pub enum TestFn { + DynTestFn(isize), + DynBenchFn(isize), +} + +pub struct TestDesc { + name: TestName, + should_fail: bool +} + +pub struct TestDescAndFn { + desc: TestDesc, + testfn: TestFn, +} diff --git a/tests/ui/switched-expectations.rs b/tests/ui/switched-expectations.rs new file mode 100644 index 000000000..c5bc84de5 --- /dev/null +++ b/tests/ui/switched-expectations.rs @@ -0,0 +1,4 @@ +fn main() { + let var = 10i32; + let ref string: String = var; //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/switched-expectations.stderr b/tests/ui/switched-expectations.stderr new file mode 100644 index 000000000..82fea0f14 --- /dev/null +++ b/tests/ui/switched-expectations.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/switched-expectations.rs:3:30 + | +LL | let ref string: String = var; + | ^^^ expected struct `String`, found `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr new file mode 100644 index 000000000..3ad4ed24c --- /dev/null +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -0,0 +1,26 @@ +error: symbol-name(_ZN5basic4main17hcbad207c0eeb0b3bE) + --> $DIR/basic.rs:8:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(basic::main::hcbad207c0eeb0b3b) + --> $DIR/basic.rs:8:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(basic::main) + --> $DIR/basic.rs:8:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(main) + --> $DIR/basic.rs:15:1 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/symbol-names/basic.rs b/tests/ui/symbol-names/basic.rs new file mode 100644 index 000000000..65a632628 --- /dev/null +++ b/tests/ui/symbol-names/basic.rs @@ -0,0 +1,19 @@ +// build-fail +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy + //[v0]compile-flags: -C symbol-mangling-version=v0 + +#![feature(rustc_attrs)] + +#[rustc_symbol_name] +//[legacy]~^ ERROR symbol-name(_ZN5basic4main +//[legacy]~| ERROR demangling(basic::main +//[legacy]~| ERROR demangling-alt(basic::main) + //[v0]~^^^^ ERROR symbol-name(_RNv + //[v0]~| ERROR demangling(basic[ + //[v0]~| ERROR demangling-alt(basic::main) +#[rustc_def_path] +//[legacy]~^ ERROR def-path(main) + //[v0]~^^ ERROR def-path(main) +fn main() { +} diff --git a/tests/ui/symbol-names/basic.v0.stderr b/tests/ui/symbol-names/basic.v0.stderr new file mode 100644 index 000000000..1f0278136 --- /dev/null +++ b/tests/ui/symbol-names/basic.v0.stderr @@ -0,0 +1,26 @@ +error: symbol-name(_RNvCsCRATE_HASH_5basic4main) + --> $DIR/basic.rs:8:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(basic[b751b4a00e2291d9]::main) + --> $DIR/basic.rs:8:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(basic::main) + --> $DIR/basic.rs:8:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(main) + --> $DIR/basic.rs:15:1 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/symbol-names/const-generics-demangling.legacy.stderr b/tests/ui/symbol-names/const-generics-demangling.legacy.stderr new file mode 100644 index 000000000..bebbb7aac --- /dev/null +++ b/tests/ui/symbol-names/const-generics-demangling.legacy.stderr @@ -0,0 +1,74 @@ +error: symbol-name(_ZN1c21Unsigned$LT$11_u8$GT$1f17h[HASH]E) + --> $DIR/const-generics-demangling.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(c::Unsigned<11_u8>::f::h[HASH]) + --> $DIR/const-generics-demangling.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(c::Unsigned<11_u8>::f) + --> $DIR/const-generics-demangling.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1c22Signed$LT$.152_i16$GT$1f17h[HASH]E) + --> $DIR/const-generics-demangling.rs:26:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(c::Signed<.152_i16>::f::h[HASH]) + --> $DIR/const-generics-demangling.rs:26:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(c::Signed<.152_i16>::f) + --> $DIR/const-generics-demangling.rs:26:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1c13Bool$LT$_$GT$1f17h[HASH]E) + --> $DIR/const-generics-demangling.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(c::Bool<_>::f::h[HASH]) + --> $DIR/const-generics-demangling.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(c::Bool<_>::f) + --> $DIR/const-generics-demangling.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1c13Char$LT$_$GT$1f17h[HASH]E) + --> $DIR/const-generics-demangling.rs:52:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(c::Char<_>::f::h[HASH]) + --> $DIR/const-generics-demangling.rs:52:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(c::Char<_>::f) + --> $DIR/const-generics-demangling.rs:52:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/symbol-names/const-generics-demangling.rs b/tests/ui/symbol-names/const-generics-demangling.rs new file mode 100644 index 000000000..4a04eca67 --- /dev/null +++ b/tests/ui/symbol-names/const-generics-demangling.rs @@ -0,0 +1,62 @@ +// build-fail +// revisions: legacy v0 +// compile-flags: --crate-name=c +//[legacy]compile-flags: -C symbol-mangling-version=legacy -Z unstable-options +// [v0]compile-flags: -C symbol-mangling-version=v0 +//[legacy]normalize-stderr-test: "h[[:xdigit:]]{16}" -> "h[HASH]" +// [v0]normalize-stderr-test: "c\[.*?\]" -> "c[HASH]" +#![feature(rustc_attrs)] + +pub struct Unsigned; + +impl Unsigned<11> { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name(_RNvMCs + //[v0]~| ERROR demangling(>::f) + //[legacy]~^^^^ ERROR symbol-name(_ZN1c21Unsigned$LT$11_u8$GT$ + //[legacy]~| ERROR demangling(c::Unsigned<11_u8>::f:: + //[legacy]~| ERROR demangling-alt(c::Unsigned<11_u8>::f) + fn f() {} +} + +pub struct Signed; + +impl Signed<-152> { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name(_RNvMs_Cs + //[v0]~| ERROR demangling(>::f) + //[legacy]~^^^^ ERROR symbol-name(_ZN1c22Signed$LT$.152_i16$GT$ + //[legacy]~| ERROR demangling(c::Signed<.152_i16>::f:: + //[legacy]~| ERROR demangling-alt(c::Signed<.152_i16>::f) + fn f() {} +} + +pub struct Bool; + +impl Bool { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name(_RNvMs0_Cs + //[v0]~| ERROR demangling(>::f) + //[legacy]~^^^^ ERROR symbol-name(_ZN1c13Bool$LT$_$GT$ + //[legacy]~| ERROR demangling(c::Bool<_>::f:: + //[legacy]~| ERROR demangling-alt(c::Bool<_>::f) + fn f() {} +} + +pub struct Char; + +impl Char<'∂'> { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name(_RNvMs1_Cs + //[v0]~| ERROR demangling(>::f) + //[legacy]~^^^^ ERROR symbol-name(_ZN1c13Char$LT$_$GT$ + //[legacy]~| ERROR demangling(c::Char<_>::f:: + //[legacy]~| ERROR demangling-alt(c::Char<_>::f) + fn f() {} +} + +fn main() {} diff --git a/tests/ui/symbol-names/const-generics-demangling.v0.stderr b/tests/ui/symbol-names/const-generics-demangling.v0.stderr new file mode 100644 index 000000000..7238a8493 --- /dev/null +++ b/tests/ui/symbol-names/const-generics-demangling.v0.stderr @@ -0,0 +1,74 @@ +error: symbol-name(_RNvMCsCRATE_HASH_1cINtB_8UnsignedKhb_E1f) + --> $DIR/const-generics-demangling.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>::f) + --> $DIR/const-generics-demangling.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>::f) + --> $DIR/const-generics-demangling.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvMs_CsCRATE_HASH_1cINtB_6SignedKsn98_E1f) + --> $DIR/const-generics-demangling.rs:26:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>::f) + --> $DIR/const-generics-demangling.rs:26:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>::f) + --> $DIR/const-generics-demangling.rs:26:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvMs0_CsCRATE_HASH_1cINtB_4BoolKb1_E1f) + --> $DIR/const-generics-demangling.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>::f) + --> $DIR/const-generics-demangling.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>::f) + --> $DIR/const-generics-demangling.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvMs1_CsCRATE_HASH_1cINtB_4CharKc2202_E1f) + --> $DIR/const-generics-demangling.rs:52:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>::f) + --> $DIR/const-generics-demangling.rs:52:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>::f) + --> $DIR/const-generics-demangling.rs:52:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/symbol-names/const-generics-str-demangling.rs b/tests/ui/symbol-names/const-generics-str-demangling.rs new file mode 100644 index 000000000..619b34f25 --- /dev/null +++ b/tests/ui/symbol-names/const-generics-str-demangling.rs @@ -0,0 +1,45 @@ +// build-fail +// compile-flags: -C symbol-mangling-version=v0 --crate-name=c +// normalize-stderr-test: "c\[.*?\]" -> "c[HASH]" +#![feature(adt_const_params, rustc_attrs)] +#![allow(incomplete_features)] + +pub struct Str; + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Str<"abc"> {} + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Str<"'"> {} + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Str<"\t\n"> {} + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Str<"∂ü"> {} + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Str<"სáƒáƒ­áƒ›áƒ”ლáƒáƒ“_გემრიელი_სáƒáƒ“ილი"> {} + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Str<"ðŸŠðŸ¦ˆðŸ¦†ðŸ® § ðŸ¶ðŸ‘’☕🔥 § 🧡💛💚💙💜"> {} + +fn main() {} diff --git a/tests/ui/symbol-names/const-generics-str-demangling.stderr b/tests/ui/symbol-names/const-generics-str-demangling.stderr new file mode 100644 index 000000000..06d3cdda2 --- /dev/null +++ b/tests/ui/symbol-names/const-generics-str-demangling.stderr @@ -0,0 +1,110 @@ +error: symbol-name(_RMCsCRATE_HASH_1cINtB_3StrKRe616263_E) + --> $DIR/const-generics-str-demangling.rs:9:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-str-demangling.rs:9:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-str-demangling.rs:9:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs_CsCRATE_HASH_1cINtB_3StrKRe27_E) + --> $DIR/const-generics-str-demangling.rs:15:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-str-demangling.rs:15:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-str-demangling.rs:15:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs0_CsCRATE_HASH_1cINtB_3StrKRe090a_E) + --> $DIR/const-generics-str-demangling.rs:21:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-str-demangling.rs:21:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-str-demangling.rs:21:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs1_CsCRATE_HASH_1cINtB_3StrKRee28882c3bc_E) + --> $DIR/const-generics-str-demangling.rs:27:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-str-demangling.rs:27:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-str-demangling.rs:27:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs2_CsCRATE_HASH_1cINtB_3StrKRee183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839be183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_E) + --> $DIR/const-generics-str-demangling.rs:33:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-str-demangling.rs:33:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-str-demangling.rs:33:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs3_CsCRATE_HASH_1cINtB_3StrKRef09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e29895f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_E) + --> $DIR/const-generics-str-demangling.rs:39:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-str-demangling.rs:39:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-str-demangling.rs:39:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors + diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.rs b/tests/ui/symbol-names/const-generics-structural-demangling.rs new file mode 100644 index 000000000..df09ba494 --- /dev/null +++ b/tests/ui/symbol-names/const-generics-structural-demangling.rs @@ -0,0 +1,96 @@ +// build-fail +// compile-flags: -C symbol-mangling-version=v0 --crate-name=c + +// NOTE(eddyb) we need `core` for `core::option::Option`, normalize away its +// disambiguator hash, which can/should change (including between stage{1,2}). +// normalize-stderr-test: "core\[[0-9a-f]+\]" -> "core[HASH]" +// normalize-stderr-test: "c\[[0-9a-f]+\]" -> "c[HASH]" + +#![feature(adt_const_params, decl_macro, rustc_attrs)] +#![allow(incomplete_features)] + +pub struct RefByte; + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl RefByte<{&123}> {} + +// FIXME(eddyb) this was supposed to be `RefMutZst` with `&mut []`, +// but that is currently not allowed in const generics. +pub struct RefZst; + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl RefZst<{&[]}> {} + +pub struct Array3Bytes; + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Array3Bytes<{[1, 2, 3]}> {} + +pub struct TupleByteBool; + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl TupleByteBool<{(1, false)}> {} + +pub struct OptionUsize>; + +// HACK(eddyb) the full mangling is only in `.stderr` because we can normalize +// the `core` disambiguator hash away there, but not here. +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(::None}>>) +impl OptionUsize<{None}> {} + +// HACK(eddyb) the full mangling is only in `.stderr` because we can normalize +// the `core` disambiguator hash away there, but not here. +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(::Some(0)}>>) +impl OptionUsize<{Some(0)}> {} + +#[derive(PartialEq, Eq)] +pub struct Foo { + s: &'static str, + ch: char, + slice: &'static [u8], +} +pub struct Foo_; + +#[rustc_symbol_name] +//~^ ERROR symbol-name +//~| ERROR demangling +//~| ERROR demangling-alt(>) +impl Foo_<{Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] }}> {} + +// NOTE(eddyb) this tests specifically the use of disambiguators in field names, +// using macros 2.0 hygiene to create a `struct` with conflicting field names. +macro duplicate_field_name_test($x:ident) { + #[derive(PartialEq, Eq)] + pub struct Bar { + $x: u8, + x: u16, + } + pub struct Bar_; + + #[rustc_symbol_name] + //~^ ERROR symbol-name + //~| ERROR demangling + //~| ERROR demangling-alt(>) + impl Bar_<{Bar { $x: 123, x: 4096 }}> {} +} +duplicate_field_name_test!(x); + +fn main() {} diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.stderr b/tests/ui/symbol-names/const-generics-structural-demangling.stderr new file mode 100644 index 000000000..a4c997477 --- /dev/null +++ b/tests/ui/symbol-names/const-generics-structural-demangling.stderr @@ -0,0 +1,161 @@ +error: symbol-name(_RMCsCRATE_HASH_1cINtB_7RefByteKRh7b_E) + --> $DIR/const-generics-structural-demangling.rs:14:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-structural-demangling.rs:14:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-structural-demangling.rs:14:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs_CsCRATE_HASH_1cINtB_6RefZstKRAEE) + --> $DIR/const-generics-structural-demangling.rs:24:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-structural-demangling.rs:24:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-structural-demangling.rs:24:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs0_CsCRATE_HASH_1cINtB_11Array3BytesKAh1_h2_h3_EE) + --> $DIR/const-generics-structural-demangling.rs:32:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-structural-demangling.rs:32:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-structural-demangling.rs:32:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs1_CsCRATE_HASH_1cINtB_13TupleByteBoolKTh1_b0_EE) + --> $DIR/const-generics-structural-demangling.rs:40:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-structural-demangling.rs:40:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-structural-demangling.rs:40:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs2_CsCRATE_HASH_1cINtB_11OptionUsizeKVNtINtNtCsCRATE_HASH_4core6option6OptionjE4NoneUE) + --> $DIR/const-generics-structural-demangling.rs:50:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(::None}>>) + --> $DIR/const-generics-structural-demangling.rs:50:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(::None}>>) + --> $DIR/const-generics-structural-demangling.rs:50:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs3_CsCRATE_HASH_1cINtB_11OptionUsizeKVNtINtNtCsCRATE_HASH_4core6option6OptionjE4SomeTj0_EE) + --> $DIR/const-generics-structural-demangling.rs:58:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(::Some(0usize)}>>) + --> $DIR/const-generics-structural-demangling.rs:58:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(::Some(0)}>>) + --> $DIR/const-generics-structural-demangling.rs:58:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs4_CsCRATE_HASH_1cINtB_4Foo_KVNtB_3FooS1sRe616263_2chc78_5sliceRAh1_h2_h3_EEE) + --> $DIR/const-generics-structural-demangling.rs:72:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/const-generics-structural-demangling.rs:72:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/const-generics-structural-demangling.rs:72:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RMs9_CsCRATE_HASH_1cINtB_4Bar_KVNtB_3BarS1xh7b_s_1xt1000_EE) + --> $DIR/const-generics-structural-demangling.rs:88:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | duplicate_field_name_test!(x); + | ----------------------------- in this macro invocation + | + = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: demangling(>) + --> $DIR/const-generics-structural-demangling.rs:88:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | duplicate_field_name_test!(x); + | ----------------------------- in this macro invocation + | + = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: demangling-alt(>) + --> $DIR/const-generics-structural-demangling.rs:88:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ +... +LL | duplicate_field_name_test!(x); + | ----------------------------- in this macro invocation + | + = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 24 previous errors + diff --git a/tests/ui/symbol-names/const-generics.rs b/tests/ui/symbol-names/const-generics.rs new file mode 100644 index 000000000..1242126e0 --- /dev/null +++ b/tests/ui/symbol-names/const-generics.rs @@ -0,0 +1,85 @@ +// check-pass +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy --crate-type=lib +//[v0]compile-flags: -C symbol-mangling-version=v0 --crate-type=lib + +// `char` +pub struct Char; + +impl Char<'A'> { + pub fn foo() {} +} + +impl Char { + pub fn bar() {} +} + +// `i8` +pub struct I8; + +impl I8<{i8::MIN}> { + pub fn foo() {} +} + +impl I8<{i8::MAX}> { + pub fn foo() {} +} + +impl I8 { + pub fn bar() {} +} + +// `i16` +pub struct I16; + +impl I16<{i16::MIN}> { + pub fn foo() {} +} + +impl I16 { + pub fn bar() {} +} + +// `i32` +pub struct I32; + +impl I32<{i32::MIN}> { + pub fn foo() {} +} + +impl I32 { + pub fn bar() {} +} + +// `i64` +pub struct I64; + +impl I64<{i64::MIN}> { + pub fn foo() {} +} + +impl I64 { + pub fn bar() {} +} + +// `i128` +pub struct I128; + +impl I128<{i128::MIN}> { + pub fn foo() {} +} + +impl I128 { + pub fn bar() {} +} + +// `isize` +pub struct ISize; + +impl ISize<3> { + pub fn foo() {} +} + +impl ISize { + pub fn bar() {} +} diff --git a/tests/ui/symbol-names/foreign-types.rs b/tests/ui/symbol-names/foreign-types.rs new file mode 100644 index 000000000..8f5b07769 --- /dev/null +++ b/tests/ui/symbol-names/foreign-types.rs @@ -0,0 +1,19 @@ +// build-fail +// compile-flags: -C symbol-mangling-version=v0 + +#![feature(extern_types)] +#![feature(rustc_attrs)] + +extern "C" { + type ForeignType; +} + +struct Check(T); + +#[rustc_symbol_name] +//~^ ERROR symbol-name(_RMCs +//~| ERROR demangling(>) +impl Check {} + +fn main() {} diff --git a/tests/ui/symbol-names/foreign-types.stderr b/tests/ui/symbol-names/foreign-types.stderr new file mode 100644 index 000000000..d6ee388dd --- /dev/null +++ b/tests/ui/symbol-names/foreign-types.stderr @@ -0,0 +1,20 @@ +error: symbol-name(_RMCsCRATE_HASH_13foreign_typesINtB_5CheckNvB_11ForeignTypeE) + --> $DIR/foreign-types.rs:13:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>) + --> $DIR/foreign-types.rs:13:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>) + --> $DIR/foreign-types.rs:13:1 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/symbol-names/impl1.legacy.stderr b/tests/ui/symbol-names/impl1.legacy.stderr new file mode 100644 index 000000000..3d438df92 --- /dev/null +++ b/tests/ui/symbol-names/impl1.legacy.stderr @@ -0,0 +1,74 @@ +error: symbol-name(_ZN5impl13foo3Foo3bar17) + --> $DIR/impl1.rs:14:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(impl1::foo::Foo::bar::) + --> $DIR/impl1.rs:14:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(impl1::foo::Foo::bar) + --> $DIR/impl1.rs:14:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(foo::Foo::bar) + --> $DIR/impl1.rs:21:9 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17) + --> $DIR/impl1.rs:32:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(impl1::bar::::baz::) + --> $DIR/impl1.rs:32:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(impl1::bar::::baz) + --> $DIR/impl1.rs:32:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(bar::::baz) + --> $DIR/impl1.rs:39:9 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17) + --> $DIR/impl1.rs:62:13 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::) + --> $DIR/impl1.rs:62:13 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) + --> $DIR/impl1.rs:62:13 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) + --> $DIR/impl1.rs:69:13 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/symbol-names/impl1.rs b/tests/ui/symbol-names/impl1.rs new file mode 100644 index 000000000..629c2f33d --- /dev/null +++ b/tests/ui/symbol-names/impl1.rs @@ -0,0 +1,75 @@ +// build-fail +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy + //[v0]compile-flags: -C symbol-mangling-version=v0 +//[legacy]normalize-stderr-test: "h[\w]{16}E?\)" -> ")" + +#![feature(auto_traits, rustc_attrs)] +#![allow(dead_code)] + +mod foo { + pub struct Foo { x: u32 } + + impl Foo { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar + //[legacy]~| ERROR demangling(impl1::foo::Foo::bar + //[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar) + //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs + //[v0]~| ERROR demangling(::bar) + #[rustc_def_path] + //[legacy]~^ ERROR def-path(foo::Foo::bar) + //[v0]~^^ ERROR def-path(foo::Foo::bar) + fn bar() { } + } +} + +mod bar { + use foo::Foo; + + impl Foo { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz + //[legacy]~| ERROR demangling(impl1::bar::::baz + //[legacy]~| ERROR demangling-alt(impl1::bar::::baz) + //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs + //[v0]~| ERROR demangling(::baz) + #[rustc_def_path] + //[legacy]~^ ERROR def-path(bar::::baz) + //[v0]~^^ ERROR def-path(bar::::baz) + fn baz() { } + } +} + +trait Foo { + type Assoc; +} + +auto trait AutoTrait {} + +fn main() { + // Test closure mangling, and disambiguators. + || {}; + || { + trait Bar { + fn method(&self) {} + } + + // Test type mangling, by putting them in an `impl` header. + impl Bar for [&'_ (dyn Foo + AutoTrait); 3] { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method + //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method + //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) + //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs + //[v0]~| ERROR demangling(<[&dyn + //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + #[rustc_def_path] + //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) + //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) + fn method(&self) {} + } + }; +} diff --git a/tests/ui/symbol-names/impl1.v0.stderr b/tests/ui/symbol-names/impl1.v0.stderr new file mode 100644 index 000000000..33caad71f --- /dev/null +++ b/tests/ui/symbol-names/impl1.v0.stderr @@ -0,0 +1,74 @@ +error: symbol-name(_RNvMNtCsCRATE_HASH_5impl13fooNtB_3Foo3bar) + --> $DIR/impl1.rs:14:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(::bar) + --> $DIR/impl1.rs:14:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(::bar) + --> $DIR/impl1.rs:14:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(foo::Foo::bar) + --> $DIR/impl1.rs:21:9 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvMNtCsCRATE_HASH_5impl13barNtNtB_3foo3Foo3baz) + --> $DIR/impl1.rs:32:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(::baz) + --> $DIR/impl1.rs:32:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(::baz) + --> $DIR/impl1.rs:32:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(bar::::baz) + --> $DIR/impl1.rs:39:9 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvXNCNvCsCRATE_HASH_5impl14mains_0ARDNtB_3Foop5AssocFG_KCRL0_hvEuNtB_9AutoTraitEL_j3_NtB_3Bar6method) + --> $DIR/impl1.rs:62:13 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<[&dyn impl1[2c09c4f1c7c8e90c]::Foo extern "C" fn(&'a u8, ...)> + impl1[2c09c4f1c7c8e90c]::AutoTrait; 3usize] as impl1[2c09c4f1c7c8e90c]::main::{closure#1}::Bar>::method) + --> $DIR/impl1.rs:62:13 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + --> $DIR/impl1.rs:62:13 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) + --> $DIR/impl1.rs:69:13 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/tests/ui/symbol-names/impl2.rs b/tests/ui/symbol-names/impl2.rs new file mode 100644 index 000000000..81aba403d --- /dev/null +++ b/tests/ui/symbol-names/impl2.rs @@ -0,0 +1,15 @@ +// build-fail + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait Foo { + fn baz(); +} + +impl Foo for [u8; 1 + 2] { + #[rustc_def_path] //~ ERROR def-path(<[u8; 1 + 2] as Foo>::baz) + fn baz() {} +} + +fn main() {} diff --git a/tests/ui/symbol-names/impl2.stderr b/tests/ui/symbol-names/impl2.stderr new file mode 100644 index 000000000..0c3205e01 --- /dev/null +++ b/tests/ui/symbol-names/impl2.stderr @@ -0,0 +1,8 @@ +error: def-path(<[u8; 1 + 2] as Foo>::baz) + --> $DIR/impl2.rs:11:5 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/symbol-names/issue-53912.rs b/tests/ui/symbol-names/issue-53912.rs new file mode 100644 index 000000000..65b6825a8 --- /dev/null +++ b/tests/ui/symbol-names/issue-53912.rs @@ -0,0 +1,37 @@ +// build-pass + +// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the +// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the +// symbol mangling fix produces the correct result. + +fn dummy() {} + +mod llvm { + pub(crate) struct Foo; +} +mod foo { + pub(crate) struct Foo(T); + + impl Foo<::llvm::Foo> { + pub(crate) fn foo() { + for _ in 0..0 { + for _ in &[::dummy()] { + ::dummy(); + ::dummy(); + ::dummy(); + } + } + } + } + + pub(crate) fn foo() { + Foo::foo(); + Foo::foo(); + } +} + +pub fn foo() { + foo::foo(); +} + +fn main() {} diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr new file mode 100644 index 000000000..21bf21ee7 --- /dev/null +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -0,0 +1,20 @@ +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h2f2efcf580c9b1eeE) + --> $DIR/issue-60925.rs:21:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(issue_60925::foo::Foo::foo::h2f2efcf580c9b1ee) + --> $DIR/issue-60925.rs:21:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(issue_60925::foo::Foo::foo) + --> $DIR/issue-60925.rs:21:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/symbol-names/issue-60925.rs b/tests/ui/symbol-names/issue-60925.rs new file mode 100644 index 000000000..ab0a3a7df --- /dev/null +++ b/tests/ui/symbol-names/issue-60925.rs @@ -0,0 +1,49 @@ +// build-fail +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy + //[v0]compile-flags: -C symbol-mangling-version=v0 + +#![feature(rustc_attrs)] + +// This test is the same code as in ui/issue-53912.rs but this test checks that the symbol mangling +// fix produces the correct result, whereas that test just checks that the reproduction compiles +// successfully and doesn't crash LLVM + +fn dummy() {} + +mod llvm { + pub(crate) struct Foo; +} +mod foo { + pub(crate) struct Foo(T); + + impl Foo<::llvm::Foo> { + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo + //[legacy]~| ERROR demangling(issue_60925::foo::Foo::foo + //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo::foo) + //[v0]~^^^^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt(>::foo) + pub(crate) fn foo() { + for _ in 0..0 { + for _ in &[::dummy()] { + ::dummy(); + ::dummy(); + ::dummy(); + } + } + } + } + + pub(crate) fn foo() { + Foo::foo(); + Foo::foo(); + } +} + +pub fn foo() { + foo::foo(); +} + +fn main() {} diff --git a/tests/ui/symbol-names/issue-60925.v0.stderr b/tests/ui/symbol-names/issue-60925.v0.stderr new file mode 100644 index 000000000..408c957c6 --- /dev/null +++ b/tests/ui/symbol-names/issue-60925.v0.stderr @@ -0,0 +1,20 @@ +error: symbol-name(_RNvMNtCsCRATE_HASH_11issue_609253fooINtB_3FooNtNtB_4llvm3FooE3foo) + --> $DIR/issue-60925.rs:21:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(>::foo) + --> $DIR/issue-60925.rs:21:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(>::foo) + --> $DIR/issue-60925.rs:21:9 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/symbol-names/issue-75326.legacy.stderr b/tests/ui/symbol-names/issue-75326.legacy.stderr new file mode 100644 index 000000000..aadc0cf43 --- /dev/null +++ b/tests/ui/symbol-names/issue-75326.legacy.stderr @@ -0,0 +1,20 @@ +error: symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next17SYMBOL_HASH) + --> $DIR/issue-75326.rs:41:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling( as issue_75326::Iterator2>::next::SYMBOL_HASH) + --> $DIR/issue-75326.rs:41:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt( as issue_75326::Iterator2>::next) + --> $DIR/issue-75326.rs:41:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/symbol-names/issue-75326.rs b/tests/ui/symbol-names/issue-75326.rs new file mode 100644 index 000000000..4a1f5a212 --- /dev/null +++ b/tests/ui/symbol-names/issue-75326.rs @@ -0,0 +1,56 @@ +// build-fail +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy +//[v0]compile-flags: -C symbol-mangling-version=v0 +//[legacy]normalize-stderr-test: "h[\w{16}]+" -> "SYMBOL_HASH" + +#![feature(rustc_attrs)] + +pub(crate) struct Foo(I, E); + +pub trait Iterator2 { + type Item; + + fn next(&mut self) -> Option; + + fn find

(&mut self, predicate: P) -> Option + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + unimplemented!() + } +} + +struct Bar; + +impl Iterator2 for Bar { + type Item = (u32, u16); + + fn next(&mut self) -> Option { + unimplemented!() + } +} + +impl Iterator2 for Foo +where + I: Iterator2, +{ + type Item = T; + + #[rustc_symbol_name] + //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next + //[legacy]~| ERROR demangling( as issue_75326::Iterator2>::next + //[legacy]~| ERROR demangling-alt( as issue_75326::Iterator2>::next) + //[v0]~^^^^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt( as issue_75326::Iterator2>::next) + fn next(&mut self) -> Option { + self.find(|_| true) + } +} + +fn main() { + let mut a = Foo(Bar, 1u16); + let _ = a.next(); +} diff --git a/tests/ui/symbol-names/issue-75326.v0.stderr b/tests/ui/symbol-names/issue-75326.v0.stderr new file mode 100644 index 000000000..3d7803a0c --- /dev/null +++ b/tests/ui/symbol-names/issue-75326.v0.stderr @@ -0,0 +1,20 @@ +error: symbol-name(_RNvXINICsCRATE_HASH_11issue_75326s_0pppEINtB_3FooppENtB_9Iterator24nextB_) + --> $DIR/issue-75326.rs:41:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling( as issue_75326[e8e253d78520f2a2]::Iterator2>::next) + --> $DIR/issue-75326.rs:41:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt( as issue_75326::Iterator2>::next) + --> $DIR/issue-75326.rs:41:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/symbol-names/issue-76365.rs b/tests/ui/symbol-names/issue-76365.rs new file mode 100644 index 000000000..932057b65 --- /dev/null +++ b/tests/ui/symbol-names/issue-76365.rs @@ -0,0 +1,17 @@ +// check-pass +// revisions: legacy v0 +//[legacy]compile-flags: -Z unstable-options -C symbol-mangling-version=legacy --crate-type=lib +//[v0]compile-flags: -C symbol-mangling-version=v0 --crate-type=lib + + +pub struct Bar; + +impl Bar { + pub fn foo() {} +} + +impl Bar { + pub fn bar() {} +} + +fn main() {} diff --git a/tests/ui/symbol-names/trait-objects.rs b/tests/ui/symbol-names/trait-objects.rs new file mode 100644 index 000000000..5bcbc0841 --- /dev/null +++ b/tests/ui/symbol-names/trait-objects.rs @@ -0,0 +1,47 @@ +// Ensure that trait objects don't include more than one binder. See #83611 + +// build-fail +// revisions: v0 +//[v0]compile-flags: -C symbol-mangling-version=v0 +//[v0]normalize-stderr-test: "core\[.*?\]" -> "core[HASH]" + +#![feature(rustc_attrs)] + +trait Bar { + fn method(&self) {} +} + +impl Bar for &dyn FnMut(&u8) { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt + fn method(&self) {} +} + +trait Foo { + fn method(&self) {} +} + +impl Foo for &(dyn FnMut(&u8) + for<'b> Send) { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt + fn method(&self) {} +} + +trait Baz { + fn method(&self) {} +} + +impl Baz for &(dyn for<'b> Send + FnMut(&u8)) { + #[rustc_symbol_name] + //[v0]~^ ERROR symbol-name + //[v0]~| ERROR demangling + //[v0]~| ERROR demangling-alt + fn method(&self) {} +} + +fn main() { +} diff --git a/tests/ui/symbol-names/trait-objects.v0.stderr b/tests/ui/symbol-names/trait-objects.v0.stderr new file mode 100644 index 000000000..47192ce5b --- /dev/null +++ b/tests/ui/symbol-names/trait-objects.v0.stderr @@ -0,0 +1,56 @@ +error: symbol-name(_RNvXCsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB_3Bar6method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[7260a56bea9f357b]::Bar>::method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method) + --> $DIR/trait-objects.rs:15:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvXs_CsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtB_6marker4SendEL_NtB_3Foo6method) + --> $DIR/trait-objects.rs:27:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[7260a56bea9f357b]::Foo>::method) + --> $DIR/trait-objects.rs:27:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method) + --> $DIR/trait-objects.rs:27:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_RNvXs0_CsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtB_6marker4SendEL_NtB_3Baz6method) + --> $DIR/trait-objects.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[7260a56bea9f357b]::Baz>::method) + --> $DIR/trait-objects.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method) + --> $DIR/trait-objects.rs:39:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/symbol-names/types.legacy.stderr b/tests/ui/symbol-names/types.legacy.stderr new file mode 100644 index 000000000..a4984d562 --- /dev/null +++ b/tests/ui/symbol-names/types.legacy.stderr @@ -0,0 +1,470 @@ +error: symbol-name(_ZN1a1b16Type$LT$bool$GT$17h[HASH]E) + --> $DIR/types.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b16Type$LT$char$GT$17h[HASH]E) + --> $DIR/types.rs:19:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:19:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:19:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b14Type$LT$i8$GT$17h[HASH]E) + --> $DIR/types.rs:25:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:25:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:25:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$i16$GT$17h[HASH]E) + --> $DIR/types.rs:31:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:31:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:31:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$i32$GT$17h[HASH]E) + --> $DIR/types.rs:37:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:37:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:37:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$i64$GT$17h[HASH]E) + --> $DIR/types.rs:43:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:43:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:43:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b14Type$LT$u8$GT$17h[HASH]E) + --> $DIR/types.rs:49:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:49:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:49:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$u16$GT$17h[HASH]E) + --> $DIR/types.rs:55:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:55:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:55:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$u32$GT$17h[HASH]E) + --> $DIR/types.rs:61:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:61:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:61:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$u64$GT$17h[HASH]E) + --> $DIR/types.rs:67:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:67:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:67:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$f32$GT$17h[HASH]E) + --> $DIR/types.rs:73:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:73:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:73:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$f64$GT$17h[HASH]E) + --> $DIR/types.rs:79:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:79:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:79:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$str$GT$17h[HASH]E) + --> $DIR/types.rs:85:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:85:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:85:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b17Type$LT$$u21$$GT$17h[HASH]E) + --> $DIR/types.rs:91:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:91:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:91:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:97:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<()>::h[HASH]) + --> $DIR/types.rs:97:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<()>) + --> $DIR/types.rs:97:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:103:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<(u8,)>::h[HASH]) + --> $DIR/types.rs:103:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<(u8,)>) + --> $DIR/types.rs:103:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:109:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<(u8,u16)>::h[HASH]) + --> $DIR/types.rs:109:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<(u8,u16)>) + --> $DIR/types.rs:109:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:115:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<(u8,u16,u32)>::h[HASH]) + --> $DIR/types.rs:115:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<(u8,u16,u32)>) + --> $DIR/types.rs:115:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$17h[HASH]E) + --> $DIR/types.rs:121:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<*const u8>::h[HASH]) + --> $DIR/types.rs:121:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<*const u8>) + --> $DIR/types.rs:121:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$17h[HASH]E) + --> $DIR/types.rs:127:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<*mut u8>::h[HASH]) + --> $DIR/types.rs:127:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<*mut u8>) + --> $DIR/types.rs:127:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$17h[HASH]E) + --> $DIR/types.rs:133:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<&str>::h[HASH]) + --> $DIR/types.rs:133:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<&str>) + --> $DIR/types.rs:133:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$17h[HASH]E) + --> $DIR/types.rs:139:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<&mut str>::h[HASH]) + --> $DIR/types.rs:139:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<&mut str>) + --> $DIR/types.rs:139:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) + --> $DIR/types.rs:145:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<[u8; 0]>::h[HASH]) + --> $DIR/types.rs:145:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<[u8; 0]>) + --> $DIR/types.rs:145:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:151:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:151:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:151:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:157:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:157:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:157:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$17h[HASH]E) + --> $DIR/types.rs:163:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<[T; N]>::h[HASH]) + --> $DIR/types.rs:163:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<[T; N]>) + --> $DIR/types.rs:163:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 78 previous errors + diff --git a/tests/ui/symbol-names/types.rs b/tests/ui/symbol-names/types.rs new file mode 100644 index 000000000..0ae699c93 --- /dev/null +++ b/tests/ui/symbol-names/types.rs @@ -0,0 +1,170 @@ +// build-fail +// revisions: legacy verbose-legacy +// compile-flags: --crate-name=a -C symbol-mangling-version=legacy -Z unstable-options +//[verbose-legacy]compile-flags: -Zverbose +// normalize-stderr-test: "h[[:xdigit:]]{16}" -> "h[HASH]" + +#![feature(never_type)] +#![feature(rustc_attrs)] + +pub fn b() { + struct Type(T); + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b16Type$LT$bool$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b16Type$LT$char$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b14Type$LT$i8$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$i16$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$i32$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$i64$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b14Type$LT$u8$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$u16$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$u32$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$u64$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$f32$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$f64$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b15Type$LT$str$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b17Type$LT$$u21$$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT + //~| ERROR demangling(a::b::Type<()>:: + //~| ERROR demangling-alt(a::b::Type<()>) + impl Type<()> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$ + //~| ERROR demangling(a::b::Type<(u8,)>:: + //~| ERROR demangling-alt(a::b::Type<(u8,)>) + impl Type<(u8,)> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$ + //~| ERROR demangling(a::b::Type<(u8,u16)>:: + //~| ERROR demangling-alt(a::b::Type<(u8,u16)>) + impl Type<(u8,u16)> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$ + //~| ERROR demangling(a::b::Type<(u8,u16,u32)>:: + //~| ERROR demangling-alt(a::b::Type<(u8,u16,u32)>) + impl Type<(u8,u16,u32)> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$ + //~| ERROR demangling(a::b::Type<*const u8>:: + //~| ERROR demangling-alt(a::b::Type<*const u8>) + impl Type<*const u8> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$ + //~| ERROR demangling(a::b::Type<*mut u8>:: + //~| ERROR demangling-alt(a::b::Type<*mut u8>) + impl Type<*mut u8> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$ + //~| ERROR demangling(a::b::Type<&str>:: + //~| ERROR demangling-alt(a::b::Type<&str>) + impl Type<&str> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$ + //~| ERROR demangling(a::b::Type<&mut str>:: + //~| ERROR demangling-alt(a::b::Type<&mut str>) + impl Type<&mut str> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$ + //~| ERROR demangling(a::b::Type<[u8; 0]>:: + //~| ERROR demangling-alt(a::b::Type<[u8; 0]>) + impl Type<[u8; 0]> {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$ + //~| ERROR demangling(a::b::Type:: + //~| ERROR demangling-alt(a::b::Type) + impl Type {} + + #[rustc_symbol_name] + //~^ ERROR symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$ + //~| ERROR demangling(a::b::Type<[T; N]>:: + //~| ERROR demangling-alt(a::b::Type<[T; N]>) + impl Type<[T; N]> {} +} + +fn main() {} diff --git a/tests/ui/symbol-names/types.verbose-legacy.stderr b/tests/ui/symbol-names/types.verbose-legacy.stderr new file mode 100644 index 000000000..a4984d562 --- /dev/null +++ b/tests/ui/symbol-names/types.verbose-legacy.stderr @@ -0,0 +1,470 @@ +error: symbol-name(_ZN1a1b16Type$LT$bool$GT$17h[HASH]E) + --> $DIR/types.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:13:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b16Type$LT$char$GT$17h[HASH]E) + --> $DIR/types.rs:19:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:19:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:19:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b14Type$LT$i8$GT$17h[HASH]E) + --> $DIR/types.rs:25:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:25:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:25:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$i16$GT$17h[HASH]E) + --> $DIR/types.rs:31:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:31:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:31:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$i32$GT$17h[HASH]E) + --> $DIR/types.rs:37:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:37:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:37:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$i64$GT$17h[HASH]E) + --> $DIR/types.rs:43:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:43:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:43:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b14Type$LT$u8$GT$17h[HASH]E) + --> $DIR/types.rs:49:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:49:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:49:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$u16$GT$17h[HASH]E) + --> $DIR/types.rs:55:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:55:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:55:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$u32$GT$17h[HASH]E) + --> $DIR/types.rs:61:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:61:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:61:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$u64$GT$17h[HASH]E) + --> $DIR/types.rs:67:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:67:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:67:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$f32$GT$17h[HASH]E) + --> $DIR/types.rs:73:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:73:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:73:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$f64$GT$17h[HASH]E) + --> $DIR/types.rs:79:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:79:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:79:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b15Type$LT$str$GT$17h[HASH]E) + --> $DIR/types.rs:85:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:85:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:85:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b17Type$LT$$u21$$GT$17h[HASH]E) + --> $DIR/types.rs:91:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:91:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:91:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:97:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<()>::h[HASH]) + --> $DIR/types.rs:97:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<()>) + --> $DIR/types.rs:97:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:103:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<(u8,)>::h[HASH]) + --> $DIR/types.rs:103:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<(u8,)>) + --> $DIR/types.rs:103:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:109:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<(u8,u16)>::h[HASH]) + --> $DIR/types.rs:109:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<(u8,u16)>) + --> $DIR/types.rs:109:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:115:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<(u8,u16,u32)>::h[HASH]) + --> $DIR/types.rs:115:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<(u8,u16,u32)>) + --> $DIR/types.rs:115:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$17h[HASH]E) + --> $DIR/types.rs:121:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<*const u8>::h[HASH]) + --> $DIR/types.rs:121:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<*const u8>) + --> $DIR/types.rs:121:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$17h[HASH]E) + --> $DIR/types.rs:127:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<*mut u8>::h[HASH]) + --> $DIR/types.rs:127:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<*mut u8>) + --> $DIR/types.rs:127:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$17h[HASH]E) + --> $DIR/types.rs:133:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<&str>::h[HASH]) + --> $DIR/types.rs:133:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<&str>) + --> $DIR/types.rs:133:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$17h[HASH]E) + --> $DIR/types.rs:139:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<&mut str>::h[HASH]) + --> $DIR/types.rs:139:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<&mut str>) + --> $DIR/types.rs:139:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) + --> $DIR/types.rs:145:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<[u8; 0]>::h[HASH]) + --> $DIR/types.rs:145:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<[u8; 0]>) + --> $DIR/types.rs:145:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:151:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:151:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:151:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$17h[HASH]E) + --> $DIR/types.rs:157:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type::h[HASH]) + --> $DIR/types.rs:157:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type) + --> $DIR/types.rs:157:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$17h[HASH]E) + --> $DIR/types.rs:163:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling(a::b::Type<[T; N]>::h[HASH]) + --> $DIR/types.rs:163:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: demangling-alt(a::b::Type<[T; N]>) + --> $DIR/types.rs:163:5 + | +LL | #[rustc_symbol_name] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 78 previous errors + diff --git a/tests/ui/symbol-names/verbose.rs b/tests/ui/symbol-names/verbose.rs new file mode 100644 index 000000000..e00c592b6 --- /dev/null +++ b/tests/ui/symbol-names/verbose.rs @@ -0,0 +1,15 @@ +// Regression test for issue #57596, where -Zverbose flag unintentionally +// affected produced symbols making it impossible to link between crates +// with a different value of the flag (for symbols involving generic +// arguments equal to defaults of their respective parameters). +// +// build-pass +// compile-flags: -Zverbose + +pub fn error(msg: String) -> Box { + msg.into() +} + +fn main() { + error(String::new()); +} diff --git a/tests/ui/symbol-names/x86-stdcall.rs b/tests/ui/symbol-names/x86-stdcall.rs new file mode 100644 index 000000000..9948488c0 --- /dev/null +++ b/tests/ui/symbol-names/x86-stdcall.rs @@ -0,0 +1,13 @@ +// build-pass +// only-x86-windows +#![crate_type = "cdylib"] +#![feature(abi_vectorcall)] + +#[no_mangle] +extern "stdcall" fn foo(_: bool) {} + +#[no_mangle] +extern "fastcall" fn bar(_: u8) {} + +#[no_mangle] +extern "vectorcall" fn baz(_: u16) {} diff --git a/tests/ui/syntax-extension-minor.rs b/tests/ui/syntax-extension-minor.rs new file mode 100644 index 000000000..2d6710af3 --- /dev/null +++ b/tests/ui/syntax-extension-minor.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(concat_idents)] + +pub fn main() { + struct Foo; + let _: concat_idents!(F, oo) = Foo; // Test that `concat_idents!` can be used in type positions + + let asdf_fdsa = "<.<".to_string(); + // concat_idents should have call-site hygiene. + assert!(concat_idents!(asd, f_f, dsa) == "<.<".to_string()); + + assert_eq!(stringify!(use_mention_distinction), "use_mention_distinction"); +} diff --git a/tests/ui/tag-that-dare-not-speak-its-name.rs b/tests/ui/tag-that-dare-not-speak-its-name.rs new file mode 100644 index 000000000..36e22f0b5 --- /dev/null +++ b/tests/ui/tag-that-dare-not-speak-its-name.rs @@ -0,0 +1,16 @@ +// Issue #876 + +use std::vec::Vec; + +fn last(v: Vec<&T> ) -> std::option::Option { + ::std::panic!(); +} + +fn main() { + let y; + let x : char = last(y); + //~^ ERROR mismatched types + //~| expected type `char` + //~| found enum `Option<_>` + //~| expected `char`, found enum `Option` +} diff --git a/tests/ui/tag-that-dare-not-speak-its-name.stderr b/tests/ui/tag-that-dare-not-speak-its-name.stderr new file mode 100644 index 000000000..96bab1526 --- /dev/null +++ b/tests/ui/tag-that-dare-not-speak-its-name.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/tag-that-dare-not-speak-its-name.rs:11:20 + | +LL | let x : char = last(y); + | ---- ^^^^^^^ expected `char`, found enum `Option` + | | + | expected due to this + | + = note: expected type `char` + found enum `Option<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/tag-type-args.rs b/tests/ui/tag-type-args.rs new file mode 100644 index 000000000..660d860ba --- /dev/null +++ b/tests/ui/tag-type-args.rs @@ -0,0 +1,5 @@ +enum Quux { Bar } + +fn foo(c: Quux) { assert!((false)); } //~ ERROR missing generics for enum `Quux` + +fn main() { panic!(); } diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr new file mode 100644 index 000000000..5b54880a6 --- /dev/null +++ b/tests/ui/tag-type-args.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for enum `Quux` + --> $DIR/tag-type-args.rs:3:11 + | +LL | fn foo(c: Quux) { assert!((false)); } + | ^^^^ expected 1 generic argument + | +note: enum defined here, with 1 generic parameter: `T` + --> $DIR/tag-type-args.rs:1:6 + | +LL | enum Quux { Bar } + | ^^^^ - +help: add missing generic argument + | +LL | fn foo(c: Quux) { assert!((false)); } + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/tag-variant-cast-non-nullary.fixed b/tests/ui/tag-variant-cast-non-nullary.fixed new file mode 100644 index 000000000..53e68c2ac --- /dev/null +++ b/tests/ui/tag-variant-cast-non-nullary.fixed @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] +enum NonNullary { + Nullary, + Other(isize), +} + +impl From for isize { + fn from(val: NonNullary) -> isize { + match val { + NonNullary::Nullary => 0, + NonNullary::Other(i) => i, + } + } +} + +fn main() { + let v = NonNullary::Nullary; + let val = isize::from(v); //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605] +} diff --git a/tests/ui/tag-variant-cast-non-nullary.rs b/tests/ui/tag-variant-cast-non-nullary.rs new file mode 100644 index 000000000..0d0c6188a --- /dev/null +++ b/tests/ui/tag-variant-cast-non-nullary.rs @@ -0,0 +1,20 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] +enum NonNullary { + Nullary, + Other(isize), +} + +impl From for isize { + fn from(val: NonNullary) -> isize { + match val { + NonNullary::Nullary => 0, + NonNullary::Other(i) => i, + } + } +} + +fn main() { + let v = NonNullary::Nullary; + let val = v as isize; //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605] +} diff --git a/tests/ui/tag-variant-cast-non-nullary.stderr b/tests/ui/tag-variant-cast-non-nullary.stderr new file mode 100644 index 000000000..ae2f5a7ae --- /dev/null +++ b/tests/ui/tag-variant-cast-non-nullary.stderr @@ -0,0 +1,11 @@ +error[E0605]: non-primitive cast: `NonNullary` as `isize` + --> $DIR/tag-variant-cast-non-nullary.rs:19:15 + | +LL | let val = v as isize; + | ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)` + | + = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/tail-call-arg-leak.rs b/tests/ui/tail-call-arg-leak.rs new file mode 100644 index 000000000..a60944b63 --- /dev/null +++ b/tests/ui/tail-call-arg-leak.rs @@ -0,0 +1,9 @@ +// run-pass +// use of tail calls causes arg slot leaks, issue #160. +// pretty-expanded FIXME #23616 + +fn inner(dummy: String, b: bool) { if b { return inner(dummy, false); } } + +pub fn main() { + inner("hi".to_string(), true); +} diff --git a/tests/ui/tail-cps.rs b/tests/ui/tail-cps.rs new file mode 100644 index 000000000..f186683ea --- /dev/null +++ b/tests/ui/tail-cps.rs @@ -0,0 +1,17 @@ +// run-pass + +fn checktrue(rs: bool) -> bool { assert!((rs)); return true; } + +pub fn main() { let k = checktrue; evenk(42, k); oddk(45, k); } + +fn evenk(n: isize, k: fn(bool) -> bool) -> bool { + println!("evenk"); + println!("{}", n); + if n == 0 { return k(true); } else { return oddk(n - 1, k); } +} + +fn oddk(n: isize, k: fn(bool) -> bool) -> bool { + println!("oddk"); + println!("{}", n); + if n == 0 { return k(false); } else { return evenk(n - 1, k); } +} diff --git a/tests/ui/tail-typeck.rs b/tests/ui/tail-typeck.rs new file mode 100644 index 000000000..37a7694c8 --- /dev/null +++ b/tests/ui/tail-typeck.rs @@ -0,0 +1,7 @@ +// error-pattern: mismatched types + +fn f() -> isize { return g(); } + +fn g() -> usize { return 0; } + +fn main() { let y = f(); } diff --git a/tests/ui/tail-typeck.stderr b/tests/ui/tail-typeck.stderr new file mode 100644 index 000000000..10dfd2de7 --- /dev/null +++ b/tests/ui/tail-typeck.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/tail-typeck.rs:3:26 + | +LL | fn f() -> isize { return g(); } + | ----- ^^^ expected `isize`, found `usize` + | | + | expected `isize` because of return type + | +help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit + | +LL | fn f() -> isize { return g().try_into().unwrap(); } + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/target-feature/aarch64-neon-works.rs b/tests/ui/target-feature/aarch64-neon-works.rs new file mode 100644 index 000000000..3878806fd --- /dev/null +++ b/tests/ui/target-feature/aarch64-neon-works.rs @@ -0,0 +1,23 @@ +// only-aarch64 +// run-pass +#![allow(dead_code)] +use std::arch::*; +use std::arch::aarch64::*; + +// Smoke test to verify aarch64 code that enables NEON compiles. +fn main() { + let _zero = if is_aarch64_feature_detected!("neon") { + unsafe { + let zeros = zero_vector(); + vgetq_lane_u8::<1>(zeros) + } + } else { + 0 + }; +} + + +#[target_feature(enable = "neon")] +unsafe fn zero_vector() -> uint8x16_t { + vmovq_n_u8(0) +} diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs new file mode 100644 index 000000000..5fbd5e8a2 --- /dev/null +++ b/tests/ui/target-feature/feature-hierarchy.rs @@ -0,0 +1,58 @@ +// revisions: aarch64-neon aarch64-sve2 +// [aarch64-neon] compile-flags: -Ctarget-feature=+neon --target=aarch64-unknown-linux-gnu +// [aarch64-neon] needs-llvm-components: aarch64 +// [aarch64-sve2] compile-flags: -Ctarget-feature=-neon,+sve2 --target=aarch64-unknown-linux-gnu +// [aarch64-sve2] needs-llvm-components: aarch64 +// build-pass +#![no_core] +#![crate_type = "rlib"] +#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)] +#![stable(feature = "test", since = "1.0.0")] + +// Tests vetting "feature hierarchies" in the cases where we impose them. + +// Supporting minimal rust core code +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for bool {} + +extern "rust-intrinsic" { + #[rustc_const_stable(feature = "test", since = "1.0.0")] + fn unreachable() -> !; +} + +#[rustc_builtin_macro] +macro_rules! cfg { + ($($cfg:tt)*) => {}; +} + +// Test code +const fn do_or_die(cond: bool) { + if cond { + } else { + unsafe { unreachable() } + } +} + +macro_rules! assert { + ($x:expr $(,)?) => { + const _: () = do_or_die($x); + }; +} + + +#[cfg(aarch64_neon)] +fn check_neon_not_sve2() { + // This checks that a normal aarch64 target doesn't suddenly jump up the feature hierarchy. + assert!(cfg!(target_feature = "neon")); + assert!(cfg!(not(target_feature = "sve2"))); +} + +#[cfg(aarch64_sve2)] +fn check_sve2_includes_neon() { + // This checks that aarch64's sve2 includes neon + assert!(cfg!(target_feature = "neon")); + assert!(cfg!(target_feature = "sve2")); +} diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs new file mode 100644 index 000000000..2382c98f8 --- /dev/null +++ b/tests/ui/target-feature/gate.rs @@ -0,0 +1,36 @@ +// ignore-arm +// ignore-aarch64 +// ignore-wasm +// ignore-emscripten +// ignore-mips +// ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-riscv64 +// ignore-sparc +// ignore-sparc64 +// ignore-s390x +// gate-test-sse4a_target_feature +// gate-test-powerpc_target_feature +// gate-test-avx512_target_feature +// gate-test-tbm_target_feature +// gate-test-arm_target_feature +// gate-test-hexagon_target_feature +// gate-test-mips_target_feature +// gate-test-wasm_target_feature +// gate-test-adx_target_feature +// gate-test-cmpxchg16b_target_feature +// gate-test-movbe_target_feature +// gate-test-rtm_target_feature +// gate-test-f16c_target_feature +// gate-test-riscv_target_feature +// gate-test-ermsb_target_feature +// gate-test-bpf_target_feature +// gate-test-aarch64_ver_target_feature + +#[target_feature(enable = "avx512bw")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr new file mode 100644 index 000000000..ee542b60a --- /dev/null +++ b/tests/ui/target-feature/gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: the target feature `avx512bw` is currently unstable + --> $DIR/gate.rs:32:18 + | +LL | #[target_feature(enable = "avx512bw")] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44839 for more information + = help: add `#![feature(avx512_target_feature)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs new file mode 100644 index 000000000..ad1b6e96b --- /dev/null +++ b/tests/ui/target-feature/invalid-attribute.rs @@ -0,0 +1,97 @@ +// ignore-arm +// ignore-aarch64 +// ignore-wasm +// ignore-emscripten +// ignore-mips +// ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-riscv64 +// ignore-s390x +// ignore-sparc +// ignore-sparc64 + +#![warn(unused_attributes)] + +#[target_feature = "+sse2"] +//~^ ERROR malformed `target_feature` attribute +#[target_feature(enable = "foo")] +//~^ ERROR not valid for this target +//~| NOTE `foo` is not valid for this target +#[target_feature(bar)] +//~^ ERROR malformed `target_feature` attribute +#[target_feature(disable = "baz")] +//~^ ERROR malformed `target_feature` attribute +unsafe fn foo() {} + +#[target_feature(enable = "sse2")] +//~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions +//~| NOTE see issue #69098 +fn bar() {} +//~^ NOTE not an `unsafe` function + +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +mod another {} +//~^ NOTE not a function + +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +const FOO: usize = 7; +//~^ NOTE not a function + +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +struct Foo; +//~^ NOTE not a function + +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +enum Bar {} +//~^ NOTE not a function + +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +union Qux { +//~^ NOTE not a function + f1: u16, + f2: u16, +} + +#[target_feature(enable = "sse2")] +//~^ ERROR attribute should be applied to a function +trait Baz {} +//~^ NOTE not a function + +#[inline(always)] +//~^ ERROR: cannot use `#[inline(always)]` +#[target_feature(enable = "sse2")] +unsafe fn test() {} + +trait Quux { + fn foo(); +} + +impl Quux for Foo { + #[target_feature(enable = "sse2")] + //~^ ERROR `#[target_feature(..)]` can only be applied to `unsafe` functions + //~| NOTE see issue #69098 + fn foo() {} + //~^ NOTE not an `unsafe` function +} + +fn main() { + #[target_feature(enable = "sse2")] + //~^ ERROR attribute should be applied to a function + unsafe { + foo(); + bar(); + } + //~^^^^ NOTE not a function + + #[target_feature(enable = "sse2")] + //~^ ERROR attribute should be applied to a function + || {}; + //~^ NOTE not a function +} diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr new file mode 100644 index 000000000..a2adfc67f --- /dev/null +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -0,0 +1,136 @@ +error: malformed `target_feature` attribute input + --> $DIR/invalid-attribute.rs:17:1 + | +LL | #[target_feature = "+sse2"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[target_feature(enable = "name")]` + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:34:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | mod another {} + | -------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:39:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | const FOO: usize = 7; + | --------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:44:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Foo; + | ----------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:49:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | enum Bar {} + | ----------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:54:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / union Qux { +LL | | +LL | | f1: u16, +LL | | f2: u16, +LL | | } + | |_- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:62:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | trait Baz {} + | ------------ not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:85:5 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / unsafe { +LL | | foo(); +LL | | bar(); +LL | | } + | |_____- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/invalid-attribute.rs:93:5 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | || {}; + | ----- not a function definition + +error: the feature named `foo` is not valid for this target + --> $DIR/invalid-attribute.rs:19:18 + | +LL | #[target_feature(enable = "foo")] + | ^^^^^^^^^^^^^^ `foo` is not valid for this target + +error: malformed `target_feature` attribute input + --> $DIR/invalid-attribute.rs:22:18 + | +LL | #[target_feature(bar)] + | ^^^ help: must be of the form: `enable = ".."` + +error: malformed `target_feature` attribute input + --> $DIR/invalid-attribute.rs:24:18 + | +LL | #[target_feature(disable = "baz")] + | ^^^^^^^^^^^^^^^ help: must be of the form: `enable = ".."` + +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/invalid-attribute.rs:28:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn bar() {} + | -------- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable + +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/invalid-attribute.rs:67:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + +error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/invalid-attribute.rs:77:5 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn foo() {} + | -------- not an `unsafe` function + | + = note: see issue #69098 for more information + = help: add `#![feature(target_feature_11)]` to the crate attributes to enable + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/target-feature/missing-plusminus-2.rs b/tests/ui/target-feature/missing-plusminus-2.rs new file mode 100644 index 000000000..131687289 --- /dev/null +++ b/tests/ui/target-feature/missing-plusminus-2.rs @@ -0,0 +1,6 @@ +// compile-flags: -Ctarget-feature=rdrand --crate-type=rlib --target=x86_64-unknown-linux-gnu +// build-pass +// needs-llvm-components: x86 + +#![feature(no_core)] +#![no_core] diff --git a/tests/ui/target-feature/missing-plusminus-2.stderr b/tests/ui/target-feature/missing-plusminus-2.stderr new file mode 100644 index 000000000..5ed2652a0 --- /dev/null +++ b/tests/ui/target-feature/missing-plusminus-2.stderr @@ -0,0 +1,6 @@ +warning: unknown feature specified for `-Ctarget-feature`: `rdrand` + | + = note: features must begin with a `+` to enable or `-` to disable it + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/missing-plusminus.rs b/tests/ui/target-feature/missing-plusminus.rs new file mode 100644 index 000000000..efee65929 --- /dev/null +++ b/tests/ui/target-feature/missing-plusminus.rs @@ -0,0 +1,2 @@ +// compile-flags: -Ctarget-feature=banana --crate-type=rlib +// build-pass diff --git a/tests/ui/target-feature/missing-plusminus.stderr b/tests/ui/target-feature/missing-plusminus.stderr new file mode 100644 index 000000000..93abf3508 --- /dev/null +++ b/tests/ui/target-feature/missing-plusminus.stderr @@ -0,0 +1,6 @@ +warning: unknown feature specified for `-Ctarget-feature`: `banana` + | + = note: features must begin with a `+` to enable or `-` to disable it + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs new file mode 100644 index 000000000..5a71b2166 --- /dev/null +++ b/tests/ui/target-feature/no-llvm-leaks.rs @@ -0,0 +1,64 @@ +// revisions: aarch64 x86-64 +// [aarch64] compile-flags: -Ctarget-feature=+neon,+fp16,+fhm --target=aarch64-unknown-linux-gnu +// [aarch64] needs-llvm-components: aarch64 +// [x86-64] compile-flags: -Ctarget-feature=+sse4.2,+rdrand --target=x86_64-unknown-linux-gnu +// [x86-64] needs-llvm-components: x86 +// build-pass +#![no_core] +#![crate_type = "rlib"] +#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)] +#![stable(feature = "test", since = "1.0.0")] + +// Supporting minimal rust core code +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +impl Copy for bool {} + +extern "rust-intrinsic" { + #[rustc_const_stable(feature = "test", since = "1.0.0")] + fn unreachable() -> !; +} + +#[rustc_builtin_macro] +macro_rules! cfg { + ($($cfg:tt)*) => {}; +} + +// Test code +const fn do_or_die(cond: bool) { + if cond { + } else { + unsafe { unreachable() } + } +} + +macro_rules! assert { + ($x:expr $(,)?) => { + const _: () = do_or_die($x); + }; +} + + +#[cfg(target_arch = "aarch64")] +fn check_aarch64() { + // This checks that the rustc feature name is used, not the LLVM feature. + assert!(cfg!(target_feature = "neon")); + assert!(cfg!(not(target_feature = "fp-armv8"))); + assert!(cfg!(target_feature = "fhm")); + assert!(cfg!(not(target_feature = "fp16fml"))); + assert!(cfg!(target_feature = "fp16")); + assert!(cfg!(not(target_feature = "fullfp16"))); +} + +#[cfg(target_arch = "x86_64")] +fn check_x86_64() { + // This checks that the rustc feature name is used, not the LLVM feature. + assert!(cfg!(target_feature = "rdrand")); + assert!(cfg!(not(target_feature = "rdrnd"))); + + // Likewise: We enable LLVM's crc32 feature with SSE4.2, but Rust says it's just SSE4.2 + assert!(cfg!(target_feature = "sse4.2")); + assert!(cfg!(not(target_feature = "crc32"))); +} diff --git a/tests/ui/target-feature/rust-specific-name-no-warnings.rs b/tests/ui/target-feature/rust-specific-name-no-warnings.rs new file mode 100644 index 000000000..1708a71a9 --- /dev/null +++ b/tests/ui/target-feature/rust-specific-name-no-warnings.rs @@ -0,0 +1,5 @@ +// build-pass +// only-x86 +// compile-flags: -C target-feature=+pclmulqdq + +fn main() {} diff --git a/tests/ui/target-feature/similar-feature-suggestion.rs b/tests/ui/target-feature/similar-feature-suggestion.rs new file mode 100644 index 000000000..4e4e2160c --- /dev/null +++ b/tests/ui/target-feature/similar-feature-suggestion.rs @@ -0,0 +1,6 @@ +// compile-flags: -Ctarget-feature=+rdrnd --crate-type=rlib --target=x86_64-unknown-linux-gnu +// build-pass +// needs-llvm-components: x86 + +#![feature(no_core)] +#![no_core] diff --git a/tests/ui/target-feature/similar-feature-suggestion.stderr b/tests/ui/target-feature/similar-feature-suggestion.stderr new file mode 100644 index 000000000..2f376065f --- /dev/null +++ b/tests/ui/target-feature/similar-feature-suggestion.stderr @@ -0,0 +1,7 @@ +warning: unknown feature specified for `-Ctarget-feature`: `rdrnd` + | + = note: it is still passed through to the codegen backend + = help: you might have meant: `rdrand` + +warning: 1 warning emitted + diff --git a/tests/ui/target-feature/tied-features-cli.one.stderr b/tests/ui/target-feature/tied-features-cli.one.stderr new file mode 100644 index 000000000..b4b50d981 --- /dev/null +++ b/tests/ui/target-feature/tied-features-cli.one.stderr @@ -0,0 +1,4 @@ +error: the target features paca, pacg must all be either enabled or disabled together + +error: aborting due to previous error + diff --git a/tests/ui/target-feature/tied-features-cli.rs b/tests/ui/target-feature/tied-features-cli.rs new file mode 100644 index 000000000..72b7e3da5 --- /dev/null +++ b/tests/ui/target-feature/tied-features-cli.rs @@ -0,0 +1,20 @@ +// revisions: one two three +// compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu +// needs-llvm-components: aarch64 +// +// +// [one] check-fail +// [one] compile-flags: -C target-feature=+paca +// [two] check-fail +// [two] compile-flags: -C target-feature=-pacg,+pacg +// [three] check-fail +// [three] compile-flags: -C target-feature=+paca,+pacg,-paca +// [four] build-pass +// [four] compile-flags: -C target-feature=-paca,+pacg -C target-feature=+paca +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +fn main() {} diff --git a/tests/ui/target-feature/tied-features-cli.three.stderr b/tests/ui/target-feature/tied-features-cli.three.stderr new file mode 100644 index 000000000..b4b50d981 --- /dev/null +++ b/tests/ui/target-feature/tied-features-cli.three.stderr @@ -0,0 +1,4 @@ +error: the target features paca, pacg must all be either enabled or disabled together + +error: aborting due to previous error + diff --git a/tests/ui/target-feature/tied-features-cli.two.stderr b/tests/ui/target-feature/tied-features-cli.two.stderr new file mode 100644 index 000000000..b4b50d981 --- /dev/null +++ b/tests/ui/target-feature/tied-features-cli.two.stderr @@ -0,0 +1,4 @@ +error: the target features paca, pacg must all be either enabled or disabled together + +error: aborting due to previous error + diff --git a/tests/ui/target-feature/tied-features.rs b/tests/ui/target-feature/tied-features.rs new file mode 100644 index 000000000..15f01505e --- /dev/null +++ b/tests/ui/target-feature/tied-features.rs @@ -0,0 +1,34 @@ +// build-fail +// compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu +// needs-llvm-components: aarch64 +#![feature(no_core, lang_items)] +#![no_core] + +#[lang="sized"] +trait Sized {} + +// FIXME: this should not need to be public. +pub 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/tests/ui/target-feature/tied-features.stderr b/tests/ui/target-feature/tied-features.stderr new file mode 100644 index 000000000..525c90843 --- /dev/null +++ b/tests/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:12: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:24: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/tests/ui/target-feature/wasm-safe.rs b/tests/ui/target-feature/wasm-safe.rs new file mode 100644 index 000000000..4b868684a --- /dev/null +++ b/tests/ui/target-feature/wasm-safe.rs @@ -0,0 +1,44 @@ +// only-wasm32 +// check-pass + +#![feature(wasm_target_feature)] +#![allow(dead_code)] + +#[target_feature(enable = "nontrapping-fptoint")] +fn foo() {} + +#[target_feature(enable = "nontrapping-fptoint")] +extern "C" fn bar() {} + +trait A { + fn foo(); + fn bar(&self); +} + +struct B; + +impl B { + #[target_feature(enable = "nontrapping-fptoint")] + fn foo() {} + #[target_feature(enable = "nontrapping-fptoint")] + fn bar(&self) {} +} + +impl A for B { + #[target_feature(enable = "nontrapping-fptoint")] + fn foo() {} + #[target_feature(enable = "nontrapping-fptoint")] + fn bar(&self) {} +} + +fn no_features_enabled_on_this_function() { + bar(); + foo(); + B.bar(); + B::foo(); + ::foo(); + ::bar(&B); +} + +#[target_feature(enable = "nontrapping-fptoint")] +fn main() {} diff --git a/tests/ui/terr-in-field.rs b/tests/ui/terr-in-field.rs new file mode 100644 index 000000000..aa801fd0a --- /dev/null +++ b/tests/ui/terr-in-field.rs @@ -0,0 +1,17 @@ +struct Foo { + a: isize, + b: isize, +} + +struct Bar { + a: isize, + b: usize, +} + +fn want_foo(f: Foo) {} +fn have_bar(b: Bar) { + want_foo(b); //~ ERROR mismatched types + //~| expected struct `Foo`, found struct `Bar` +} + +fn main() {} diff --git a/tests/ui/terr-in-field.stderr b/tests/ui/terr-in-field.stderr new file mode 100644 index 000000000..d2fda09c0 --- /dev/null +++ b/tests/ui/terr-in-field.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/terr-in-field.rs:13:14 + | +LL | want_foo(b); + | -------- ^ expected struct `Foo`, found struct `Bar` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/terr-in-field.rs:11:4 + | +LL | fn want_foo(f: Foo) {} + | ^^^^^^^^ ------ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/terr-sorts.rs b/tests/ui/terr-sorts.rs new file mode 100644 index 000000000..c1e2f7dae --- /dev/null +++ b/tests/ui/terr-sorts.rs @@ -0,0 +1,15 @@ +struct Foo { + a: isize, + b: isize, +} + +type Bar = Box; + +fn want_foo(f: Foo) {} +fn have_bar(b: Bar) { + want_foo(b); //~ ERROR mismatched types + //~| expected struct `Foo` + //~| found struct `Box` +} + +fn main() {} diff --git a/tests/ui/terr-sorts.stderr b/tests/ui/terr-sorts.stderr new file mode 100644 index 000000000..5a61a2fab --- /dev/null +++ b/tests/ui/terr-sorts.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/terr-sorts.rs:10:14 + | +LL | want_foo(b); + | -------- ^ expected struct `Foo`, found struct `Box` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Box` +note: function defined here + --> $DIR/terr-sorts.rs:8:4 + | +LL | fn want_foo(f: Foo) {} + | ^^^^^^^^ ------ +help: consider unboxing the value + | +LL | want_foo(*b); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/test-attrs/auxiliary/test_macro.rs b/tests/ui/test-attrs/auxiliary/test_macro.rs new file mode 100644 index 000000000..60a98ab6a --- /dev/null +++ b/tests/ui/test-attrs/auxiliary/test_macro.rs @@ -0,0 +1,4 @@ +#[macro_export] +macro_rules! test { + () => {}; +} diff --git a/tests/ui/test-attrs/decl-macro-test.rs b/tests/ui/test-attrs/decl-macro-test.rs new file mode 100644 index 000000000..fcbe9f49e --- /dev/null +++ b/tests/ui/test-attrs/decl-macro-test.rs @@ -0,0 +1,22 @@ +// Check that declarative macros can declare tests + +// check-pass +// compile-flags: --test + +#![feature(decl_macro)] + +macro create_test() { + #[test] + fn test() {} +} + +macro create_module_test() { + mod x { + #[test] + fn test() {} + } +} + +create_test!(); +create_test!(); +create_module_test!(); diff --git a/tests/ui/test-attrs/inaccessible-test-modules.rs b/tests/ui/test-attrs/inaccessible-test-modules.rs new file mode 100644 index 000000000..f5b347937 --- /dev/null +++ b/tests/ui/test-attrs/inaccessible-test-modules.rs @@ -0,0 +1,9 @@ +// compile-flags:--test + +// the `--test` harness creates modules with these textual names, but +// they should be inaccessible from normal code. +use main as x; //~ ERROR unresolved import `main` +use test as y; //~ ERROR unresolved import `test` + +#[test] +fn baz() {} diff --git a/tests/ui/test-attrs/inaccessible-test-modules.stderr b/tests/ui/test-attrs/inaccessible-test-modules.stderr new file mode 100644 index 000000000..7635f579d --- /dev/null +++ b/tests/ui/test-attrs/inaccessible-test-modules.stderr @@ -0,0 +1,20 @@ +error[E0432]: unresolved import `main` + --> $DIR/inaccessible-test-modules.rs:5:5 + | +LL | use main as x; + | ^^^^^^^^^ no `main` in the root + +error[E0432]: unresolved import `test` + --> $DIR/inaccessible-test-modules.rs:6:5 + | +LL | use test as y; + | ^^^^^^^^^ no `test` in the root + | +help: consider importing this module instead + | +LL | use test::test as y; + | ~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/test-attrs/issue-16597-empty.rs b/tests/ui/test-attrs/issue-16597-empty.rs new file mode 100644 index 000000000..2bdd08575 --- /dev/null +++ b/tests/ui/test-attrs/issue-16597-empty.rs @@ -0,0 +1,5 @@ +// run-pass +// compile-flags:--test + +// This verifies that the test generation doesn't crash when we have +// no tests - for more information, see PR #16892. diff --git a/tests/ui/test-attrs/issue-16597.rs b/tests/ui/test-attrs/issue-16597.rs new file mode 100644 index 000000000..35769bfc1 --- /dev/null +++ b/tests/ui/test-attrs/issue-16597.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_imports)] +// compile-flags:--test + +mod tests { + use super::*; + + #[test] + pub fn test(){} +} diff --git a/tests/ui/test-attrs/issue-20823.rs b/tests/ui/test-attrs/issue-20823.rs new file mode 100644 index 000000000..9e209d5d3 --- /dev/null +++ b/tests/ui/test-attrs/issue-20823.rs @@ -0,0 +1,5 @@ +// run-pass +// compile-flags: --test + +#[test] +pub fn foo() {} diff --git a/tests/ui/test-attrs/issue-36768.rs b/tests/ui/test-attrs/issue-36768.rs new file mode 100644 index 000000000..f671cbc82 --- /dev/null +++ b/tests/ui/test-attrs/issue-36768.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags:--test +#![deny(private_in_public)] + +#[test] fn foo() {} +mod foo {} + +#[test] fn core() {} +extern crate core; diff --git a/tests/ui/test-attrs/issue-52557.rs b/tests/ui/test-attrs/issue-52557.rs new file mode 100644 index 000000000..09f7a8c51 --- /dev/null +++ b/tests/ui/test-attrs/issue-52557.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_imports)] +// This test checks for namespace pollution by private tests. +// Tests used to marked as public causing name conflicts with normal +// functions only in test builds. + +// compile-flags: --test + +mod a { + pub fn foo() -> bool { + true + } +} + +mod b { + #[test] + fn foo() { + local_name(); // ensure the local name still works + } + + #[test] + fn local_name() {} +} + +use a::*; +use b::*; + +pub fn conflict() { + let _: bool = foo(); +} diff --git a/tests/ui/test-attrs/issue-53675-a-test-called-panic.rs b/tests/ui/test-attrs/issue-53675-a-test-called-panic.rs new file mode 100644 index 000000000..e57303898 --- /dev/null +++ b/tests/ui/test-attrs/issue-53675-a-test-called-panic.rs @@ -0,0 +1,36 @@ +// rust-lang/rust#53675: At one point the compiler errored when a test +// named `panic` used the `assert!` macro in expression position. + +// check-pass +// compile-flags: --test + +mod in_expression_position { + #[test] + fn panic() { + assert!(true) + } +} + +mod in_statement_position { + #[test] + fn panic() { + assert!(true); + } +} + +mod what_if_we_use_panic_directly_in_expr { + #[test] + #[should_panic] + fn panic() { + panic!("in expr") + } +} + + +mod what_if_we_use_panic_directly_in_stmt { + #[test] + #[should_panic] + fn panic() { + panic!("in stmt"); + } +} diff --git a/tests/ui/test-attrs/run-unexported-tests.rs b/tests/ui/test-attrs/run-unexported-tests.rs new file mode 100644 index 000000000..f533a3ef8 --- /dev/null +++ b/tests/ui/test-attrs/run-unexported-tests.rs @@ -0,0 +1,12 @@ +// run-fail +// compile-flags:--test +// check-stdout + +mod m { + pub fn exported() {} + + #[test] + fn unexported() { + panic!("ran an unexported test"); + } +} diff --git a/tests/ui/test-attrs/test-attr-non-associated-functions.rs b/tests/ui/test-attrs/test-attr-non-associated-functions.rs new file mode 100644 index 000000000..31e567c39 --- /dev/null +++ b/tests/ui/test-attrs/test-attr-non-associated-functions.rs @@ -0,0 +1,25 @@ +// #[test] attribute is not allowed on associated functions or methods +// reworded error message +// compile-flags:--test + +struct A {} + +impl A { + #[test] + fn new() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions + A {} + } + #[test] + fn recovery_witness() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions + A {} + } +} + +#[test] +fn test() { + let _ = A::new(); +} + +fn main() {} diff --git a/tests/ui/test-attrs/test-attr-non-associated-functions.stderr b/tests/ui/test-attrs/test-attr-non-associated-functions.stderr new file mode 100644 index 000000000..a81b8f398 --- /dev/null +++ b/tests/ui/test-attrs/test-attr-non-associated-functions.stderr @@ -0,0 +1,20 @@ +error: `#[test]` attribute is only allowed on non associated functions + --> $DIR/test-attr-non-associated-functions.rs:9:5 + | +LL | / fn new() -> A { +LL | | +LL | | A {} +LL | | } + | |_____^ + +error: `#[test]` attribute is only allowed on non associated functions + --> $DIR/test-attr-non-associated-functions.rs:14:5 + | +LL | / fn recovery_witness() -> A { +LL | | +LL | | A {} +LL | | } + | |_____^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/test-attrs/test-cant-be-shadowed.rs b/tests/ui/test-attrs/test-cant-be-shadowed.rs new file mode 100644 index 000000000..831372d45 --- /dev/null +++ b/tests/ui/test-attrs/test-cant-be-shadowed.rs @@ -0,0 +1,13 @@ +// build-pass (FIXME(62277): could be check-pass?) +// aux-build:test_macro.rs +// compile-flags:--test + +#[macro_use] extern crate test_macro; + +#[test] +fn foo(){} + +macro_rules! test { () => () } + +#[test] +fn bar() {} diff --git a/tests/ui/test-attrs/test-filter-multiple.rs b/tests/ui/test-attrs/test-filter-multiple.rs new file mode 100644 index 000000000..04dd83b7f --- /dev/null +++ b/tests/ui/test-attrs/test-filter-multiple.rs @@ -0,0 +1,17 @@ +// run-pass +// compile-flags: --test +// run-flags: --test-threads=1 test1 test2 +// check-run-results +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-emscripten no threads support + +#[test] +fn test1() {} + +#[test] +fn test2() {} + +#[test] +fn test3() { + panic!("this should not run"); +} diff --git a/tests/ui/test-attrs/test-filter-multiple.run.stdout b/tests/ui/test-attrs/test-filter-multiple.run.stdout new file mode 100644 index 000000000..1aa684ed5 --- /dev/null +++ b/tests/ui/test-attrs/test-filter-multiple.run.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test test1 ... ok +test test2 ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs b/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs new file mode 100644 index 000000000..585874e27 --- /dev/null +++ b/tests/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs @@ -0,0 +1,13 @@ +// run-pass +// needs-unwind (#73509) + +#![feature(test)] + +// compile-flags: --test +extern crate test; + +#[bench] +pub fn bench_explicit_return_type(_: &mut ::test::Bencher) -> () {} + +#[test] +pub fn test_explicit_return_type() -> () {} diff --git a/tests/ui/test-attrs/test-main-not-dead-attr.rs b/tests/ui/test-attrs/test-main-not-dead-attr.rs new file mode 100644 index 000000000..0b2a9a354 --- /dev/null +++ b/tests/ui/test-attrs/test-main-not-dead-attr.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: --test + +#![feature(rustc_attrs)] + +#![deny(dead_code)] + +#[rustc_main] +fn foo() { panic!(); } diff --git a/tests/ui/test-attrs/test-main-not-dead.rs b/tests/ui/test-attrs/test-main-not-dead.rs new file mode 100644 index 000000000..30a9c85e3 --- /dev/null +++ b/tests/ui/test-attrs/test-main-not-dead.rs @@ -0,0 +1,6 @@ +// run-pass +// compile-flags: --test + +#![deny(dead_code)] + +fn main() { panic!(); } diff --git a/tests/ui/test-attrs/test-on-not-fn.rs b/tests/ui/test-attrs/test-on-not-fn.rs new file mode 100644 index 000000000..a460480af --- /dev/null +++ b/tests/ui/test-attrs/test-on-not-fn.rs @@ -0,0 +1,80 @@ +// compile-flags: --test + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +mod test {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +mod loooooooooooooong_teeeeeeeeeest { + /* + this is a comment + this comment goes on for a very long time + this is to pad out the span for this module for a long time + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco + laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in + voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat + non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + */ +} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +extern "C" {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +trait Foo {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +impl Foo for i32 {} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +const FOO: i32 = -1_i32; + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +static BAR: u64 = 10_000_u64; + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +enum MyUnit { + Unit, +} + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +struct NewI32(i32); + +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +union Spooky { + x: i32, + y: u32, +} + +#[repr(C, align(64))] +#[test] //~ ERROR: the `#[test]` attribute may only be used on a non-associated function +#[derive(Copy, Clone, Debug)] +struct MoreAttrs { + a: i32, + b: u64, +} + +macro_rules! foo { + () => {}; +} + +#[test] //~ WARN: the `#[test]` attribute may only be used on a non-associated function +foo!(); + +// make sure it doesn't erroneously trigger on a real test +#[test] +fn real_test() { + assert_eq!(42_i32, 42_i32); +} + +// make sure it works with cfg test +#[cfg(test)] +mod real_tests { + #[cfg(test)] + fn foo() {} + + #[test] + fn bar() { + foo(); + } +} diff --git a/tests/ui/test-attrs/test-on-not-fn.stderr b/tests/ui/test-attrs/test-on-not-fn.stderr new file mode 100644 index 000000000..fc2c5f62b --- /dev/null +++ b/tests/ui/test-attrs/test-on-not-fn.stderr @@ -0,0 +1,173 @@ +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:3:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | mod test {} + | ----------- expected a non-associated function, found a module + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:6:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | / mod loooooooooooooong_teeeeeeeeeest { +LL | | /* +LL | | this is a comment +LL | | this comment goes on for a very long time +... | +LL | | */ +LL | | } + | |_- expected a non-associated function, found a module + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:20:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | extern "C" {} + | ------------- expected a non-associated function, found an extern block + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:23:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | trait Foo {} + | ------------ expected a non-associated function, found a trait + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:26:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | impl Foo for i32 {} + | ------------------- expected a non-associated function, found an implementation + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:29:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | const FOO: i32 = -1_i32; + | ------------------------ expected a non-associated function, found a constant item + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:32:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | static BAR: u64 = 10_000_u64; + | ----------------------------- expected a non-associated function, found a static item + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:35:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | / enum MyUnit { +LL | | Unit, +LL | | } + | |_- expected a non-associated function, found an enum + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:40:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | struct NewI32(i32); + | ------------------- expected a non-associated function, found a struct + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:43:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | / union Spooky { +LL | | x: i32, +LL | | y: u32, +LL | | } + | |_- expected a non-associated function, found a union + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:50:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | #[derive(Copy, Clone, Debug)] +LL | / struct MoreAttrs { +LL | | a: i32, +LL | | b: u64, +LL | | } + | |_- expected a non-associated function, found a struct + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +warning: the `#[test]` attribute may only be used on a non-associated function + --> $DIR/test-on-not-fn.rs:61:1 + | +LL | #[test] + | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions +LL | foo!(); + | ------- expected a non-associated function, found an item macro invocation + | +help: replace with conditional compilation to make the item only exist when tests are being run + | +LL | #[cfg(test)] + | ~~~~~~~~~~~~ + +error: aborting due to 11 previous errors; 1 warning emitted + diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs new file mode 100644 index 000000000..874dbdb42 --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort-disabled.rs @@ -0,0 +1,20 @@ +// error-pattern:building tests with panic=abort is not supported +// no-prefer-dynamic +// compile-flags: --test -Cpanic=abort -Zpanic-abort-tests=no +// run-flags: --test-threads=1 + +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +#![cfg(test)] + +#[test] +fn it_works() { + assert_eq!(1 + 1, 2); +} + +#[test] +#[should_panic] +fn it_panics() { + assert_eq!(1 + 1, 4); +} diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.stderr b/tests/ui/test-attrs/test-panic-abort-disabled.stderr new file mode 100644 index 000000000..9c65c7360 --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort-disabled.stderr @@ -0,0 +1,4 @@ +error: building tests with panic=abort is not supported without `-Zpanic_abort_tests` + +error: aborting due to previous error + diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs new file mode 100644 index 000000000..af530cc1a --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs @@ -0,0 +1,41 @@ +// no-prefer-dynamic +// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests +// run-flags: --test-threads=1 --nocapture +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=0 +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support +// ignore-sgx no subprocess support + +#![cfg(test)] + +use std::io::Write; + +#[test] +fn it_works() { + println!("about to succeed"); + assert_eq!(1 + 1, 2); +} + +#[test] +#[should_panic] +fn it_panics() { + println!("about to panic"); + assert_eq!(1 + 1, 4); +} + +#[test] +fn it_fails() { + println!("about to fail"); + assert_eq!(1 + 1, 4); +} + +#[test] +fn it_writes_to_stdio() { + println!("hello, world"); + writeln!(std::io::stdout(), "testing123").unwrap(); + writeln!(std::io::stderr(), "testing321").unwrap(); +} diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr new file mode 100644 index 000000000..727e9691c --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr @@ -0,0 +1,9 @@ +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `2`, + right: `4`', $DIR/test-panic-abort-nocapture.rs:33:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `2`, + right: `4`', $DIR/test-panic-abort-nocapture.rs:27:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +testing321 diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stdout b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stdout new file mode 100644 index 000000000..8a91732a7 --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stdout @@ -0,0 +1,23 @@ + +running 4 tests +test it_fails ... about to fail +FAILED +test it_panics - should panic ... about to panic +ok +test it_works ... about to succeed +ok +test it_writes_to_stdio ... hello, world +testing123 +ok + +failures: + +---- it_fails stdout ---- +---- it_fails stderr ---- + + +failures: + it_fails + +test result: FAILED. 3 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs new file mode 100644 index 000000000..931b7993c --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort.rs @@ -0,0 +1,50 @@ +// no-prefer-dynamic +// compile-flags: --test -Cpanic=abort -Zpanic_abort_tests +// run-flags: --test-threads=1 +// run-fail +// check-run-results +// exec-env:RUST_BACKTRACE=0 +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" + +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support +// ignore-sgx no subprocess support + +#![cfg(test)] + +use std::io::Write; +use std::env; + +#[test] +fn it_works() { + assert_eq!(1 + 1, 2); +} + +#[test] +#[should_panic] +fn it_panics() { + assert_eq!(1 + 1, 4); +} + +#[test] +fn it_fails() { + println!("hello, world"); + writeln!(std::io::stdout(), "testing123").unwrap(); + writeln!(std::io::stderr(), "testing321").unwrap(); + assert_eq!(1 + 1, 5); +} + +#[test] +fn it_exits() { + std::process::exit(123); +} + +#[test] +fn no_residual_environment() { + for (key, _) in env::vars() { + // Look for keys like __RUST_TEST_INVOKE. + if key.contains("TEST_INVOKE") { + panic!("shouldn't have '{}' in environment", key); + } + } +} diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout new file mode 100644 index 000000000..f608a8cdc --- /dev/null +++ b/tests/ui/test-attrs/test-panic-abort.run.stdout @@ -0,0 +1,30 @@ + +running 5 tests +test it_exits ... FAILED +test it_fails ... FAILED +test it_panics - should panic ... ok +test it_works ... ok +test no_residual_environment ... ok + +failures: + +---- it_exits stdout ---- +---- it_exits stderr ---- +note: got unexpected return code 123 +---- it_fails stdout ---- +hello, world +testing123 +---- it_fails stderr ---- +testing321 +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `2`, + right: `5`', $DIR/test-panic-abort.rs:34:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + it_exits + it_fails + +test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-panic-while-printing.rs b/tests/ui/test-attrs/test-panic-while-printing.rs new file mode 100644 index 000000000..033c8beb4 --- /dev/null +++ b/tests/ui/test-attrs/test-panic-while-printing.rs @@ -0,0 +1,24 @@ +// compile-flags:--test +// run-pass +// needs-unwind + +use std::fmt; +use std::fmt::{Display, Formatter}; + +pub struct A(Vec); + +impl Display for A { + fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { + self.0[0]; + Ok(()) + } +} + +#[test] +fn main() { + let result = std::panic::catch_unwind(|| { + let a = A(vec![]); + eprintln!("{}", a); + }); + assert!(result.is_err()); +} diff --git a/tests/ui/test-attrs/test-passed-wasm.rs b/tests/ui/test-attrs/test-passed-wasm.rs new file mode 100644 index 000000000..578aa4b17 --- /dev/null +++ b/tests/ui/test-attrs/test-passed-wasm.rs @@ -0,0 +1,20 @@ +// no-prefer-dynamic +// compile-flags: --test +// run-flags: --test-threads=1 +// run-pass +// check-run-results +// only-wasm32 + +// Tests the output of the test harness with only passed tests. + +#![cfg(test)] + +#[test] +fn it_works() { + assert_eq!(1 + 1, 2); +} + +#[test] +fn it_works_too() { + assert_eq!(1 * 0, 0); +} diff --git a/tests/ui/test-attrs/test-passed-wasm.run.stdout b/tests/ui/test-attrs/test-passed-wasm.run.stdout new file mode 100644 index 000000000..c3005a779 --- /dev/null +++ b/tests/ui/test-attrs/test-passed-wasm.run.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test it_works ... ok +test it_works_too ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + diff --git a/tests/ui/test-attrs/test-passed.rs b/tests/ui/test-attrs/test-passed.rs new file mode 100644 index 000000000..f65f00030 --- /dev/null +++ b/tests/ui/test-attrs/test-passed.rs @@ -0,0 +1,21 @@ +// no-prefer-dynamic +// compile-flags: --test +// run-flags: --test-threads=1 +// run-pass +// check-run-results +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-wasm32 no support for `Instant` + +// Tests the output of the test harness with only passed tests. + +#![cfg(test)] + +#[test] +fn it_works() { + assert_eq!(1 + 1, 2); +} + +#[test] +fn it_works_too() { + assert_eq!(1 * 0, 0); +} diff --git a/tests/ui/test-attrs/test-passed.run.stdout b/tests/ui/test-attrs/test-passed.run.stdout new file mode 100644 index 000000000..17f70d607 --- /dev/null +++ b/tests/ui/test-attrs/test-passed.run.stdout @@ -0,0 +1,7 @@ + +running 2 tests +test it_works ... ok +test it_works_too ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-runner-hides-buried-main.rs b/tests/ui/test-attrs/test-runner-hides-buried-main.rs new file mode 100644 index 000000000..346aa868e --- /dev/null +++ b/tests/ui/test-attrs/test-runner-hides-buried-main.rs @@ -0,0 +1,15 @@ +// run-pass +// compile-flags: --test + +#![feature(rustc_attrs)] + +#![allow(dead_code)] + +mod a { + fn b() { + (|| { + #[rustc_main] + fn c() { panic!(); } + })(); + } +} diff --git a/tests/ui/test-attrs/test-runner-hides-main.rs b/tests/ui/test-attrs/test-runner-hides-main.rs new file mode 100644 index 000000000..0de1d64f0 --- /dev/null +++ b/tests/ui/test-attrs/test-runner-hides-main.rs @@ -0,0 +1,5 @@ +// run-pass +// compile-flags:--test +// Building as a test runner means that a synthetic main will be run, +// not ours +pub fn main() { panic!(); } diff --git a/tests/ui/test-attrs/test-runner-hides-start.rs b/tests/ui/test-attrs/test-runner-hides-start.rs new file mode 100644 index 000000000..56212bb6f --- /dev/null +++ b/tests/ui/test-attrs/test-runner-hides-start.rs @@ -0,0 +1,7 @@ +// run-pass +// compile-flags: --test + +#![feature(start)] + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { panic!(); } diff --git a/tests/ui/test-attrs/test-should-fail-good-message.rs b/tests/ui/test-attrs/test-should-fail-good-message.rs new file mode 100644 index 000000000..83519c452 --- /dev/null +++ b/tests/ui/test-attrs/test-should-fail-good-message.rs @@ -0,0 +1,14 @@ +// run-pass +// needs-unwind +// compile-flags: --test +#[test] +#[should_panic(expected = "foo")] +pub fn test_foo() { + panic!("foo bar") +} + +#[test] +#[should_panic(expected = "foo")] +pub fn test_foo_dynamic() { + panic!("{} bar", "foo") +} diff --git a/tests/ui/test-attrs/test-should-panic-attr.rs b/tests/ui/test-attrs/test-should-panic-attr.rs new file mode 100644 index 000000000..b71878406 --- /dev/null +++ b/tests/ui/test-attrs/test-should-panic-attr.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: --test + +#[test] +#[should_panic = "foo"] +fn test1() { + panic!(); +} + +#[test] +#[should_panic(expected)] +//~^ WARN: argument must be of the form: +fn test2() { + panic!(); +} + +#[test] +#[should_panic(expect)] +//~^ WARN: argument must be of the form: +fn test3() { + panic!(); +} + +#[test] +#[should_panic(expected(foo, bar))] +//~^ WARN: argument must be of the form: +fn test4() { + panic!(); +} + +#[test] +#[should_panic(expected = "foo", bar)] +//~^ WARN: argument must be of the form: +fn test5() { + panic!(); +} diff --git a/tests/ui/test-attrs/test-should-panic-attr.stderr b/tests/ui/test-attrs/test-should-panic-attr.stderr new file mode 100644 index 000000000..492d1d5e0 --- /dev/null +++ b/tests/ui/test-attrs/test-should-panic-attr.stderr @@ -0,0 +1,34 @@ +warning: argument must be of the form: `expected = "error message"` + --> $DIR/test-should-panic-attr.rs:11:1 + | +LL | #[should_panic(expected)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release + +warning: argument must be of the form: `expected = "error message"` + --> $DIR/test-should-panic-attr.rs:18:1 + | +LL | #[should_panic(expect)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release + +warning: argument must be of the form: `expected = "error message"` + --> $DIR/test-should-panic-attr.rs:25:1 + | +LL | #[should_panic(expected(foo, bar))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release + +warning: argument must be of the form: `expected = "error message"` + --> $DIR/test-should-panic-attr.rs:32:1 + | +LL | #[should_panic(expected = "foo", bar)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: errors in this attribute were erroneously allowed and will become a hard error in a future release + +warning: 4 warnings emitted + diff --git a/tests/ui/test-attrs/test-thread-capture.rs b/tests/ui/test-attrs/test-thread-capture.rs new file mode 100644 index 000000000..53acca341 --- /dev/null +++ b/tests/ui/test-attrs/test-thread-capture.rs @@ -0,0 +1,33 @@ +// compile-flags: --test +// run-fail +// run-flags: --test-threads=1 +// check-run-results +// exec-env:RUST_BACKTRACE=0 +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-emscripten no threads support +// needs-unwind + +#[test] +fn thready_pass() { + println!("fee"); + std::thread::spawn(|| { + println!("fie"); + println!("foe"); + }) + .join() + .unwrap(); + println!("fum"); +} + +#[test] +fn thready_fail() { + println!("fee"); + std::thread::spawn(|| { + println!("fie"); + println!("foe"); + }) + .join() + .unwrap(); + println!("fum"); + panic!(); +} diff --git a/tests/ui/test-attrs/test-thread-capture.run.stdout b/tests/ui/test-attrs/test-thread-capture.run.stdout new file mode 100644 index 000000000..513c8cf2a --- /dev/null +++ b/tests/ui/test-attrs/test-thread-capture.run.stdout @@ -0,0 +1,21 @@ + +running 2 tests +test thready_fail ... FAILED +test thready_pass ... ok + +failures: + +---- thready_fail stdout ---- +fee +fie +foe +fum +thread 'thready_fail' panicked at 'explicit panic', $DIR/test-thread-capture.rs:32:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + thready_fail + +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-thread-nocapture.rs b/tests/ui/test-attrs/test-thread-nocapture.rs new file mode 100644 index 000000000..2b57eb8aa --- /dev/null +++ b/tests/ui/test-attrs/test-thread-nocapture.rs @@ -0,0 +1,33 @@ +// compile-flags: --test +// run-fail +// run-flags: --test-threads=1 --nocapture +// check-run-results +// exec-env:RUST_BACKTRACE=0 +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-emscripten no threads support +// needs-unwind + +#[test] +fn thready_pass() { + println!("fee"); + std::thread::spawn(|| { + println!("fie"); + println!("foe"); + }) + .join() + .unwrap(); + println!("fum"); +} + +#[test] +fn thready_fail() { + println!("fee"); + std::thread::spawn(|| { + println!("fie"); + println!("foe"); + }) + .join() + .unwrap(); + println!("fum"); + panic!(); +} diff --git a/tests/ui/test-attrs/test-thread-nocapture.run.stderr b/tests/ui/test-attrs/test-thread-nocapture.run.stderr new file mode 100644 index 000000000..8c905d1af --- /dev/null +++ b/tests/ui/test-attrs/test-thread-nocapture.run.stderr @@ -0,0 +1,2 @@ +thread 'thready_fail' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:32:5 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/test-attrs/test-thread-nocapture.run.stdout b/tests/ui/test-attrs/test-thread-nocapture.run.stdout new file mode 100644 index 000000000..9d2da5082 --- /dev/null +++ b/tests/ui/test-attrs/test-thread-nocapture.run.stdout @@ -0,0 +1,20 @@ + +running 2 tests +test thready_fail ... fee +fie +foe +fum +FAILED +test thready_pass ... fee +fie +foe +fum +ok + +failures: + +failures: + thready_fail + +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs new file mode 100644 index 000000000..f99e476ea --- /dev/null +++ b/tests/ui/test-attrs/test-type.rs @@ -0,0 +1,27 @@ +// compile-flags: --test +// run-flags: --test-threads=1 +// check-run-results +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-emscripten no threads support +// run-pass + +#[test] +fn test_ok() { + let _a = true; +} + +#[test] +#[should_panic] +fn test_panic() { + panic!(); +} + +#[test] +#[ignore = "msg"] +fn test_no_run() { + loop { + println!("Hello, world"); + } +} + +fn main() {} diff --git a/tests/ui/test-attrs/test-type.run.stdout b/tests/ui/test-attrs/test-type.run.stdout new file mode 100644 index 000000000..143c13a36 --- /dev/null +++ b/tests/ui/test-attrs/test-type.run.stdout @@ -0,0 +1,8 @@ + +running 3 tests +test test_no_run ... ignored, msg +test test_ok ... ok +test test_panic - should panic ... ok + +test result: ok. 2 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-vs-cfg-test.rs b/tests/ui/test-attrs/test-vs-cfg-test.rs new file mode 100644 index 000000000..cd1cd33c2 --- /dev/null +++ b/tests/ui/test-attrs/test-vs-cfg-test.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: --cfg test + +// Make sure `--cfg test` does not inject test harness + +#[test] +fn test() { panic!(); } + +fn main() {} diff --git a/tests/ui/test-attrs/test-warns-dead-code.rs b/tests/ui/test-attrs/test-warns-dead-code.rs new file mode 100644 index 000000000..4190885b6 --- /dev/null +++ b/tests/ui/test-attrs/test-warns-dead-code.rs @@ -0,0 +1,7 @@ +// compile-flags: --test + +#![deny(dead_code)] + +fn dead() {} //~ error: function `dead` is never used + +fn main() {} diff --git a/tests/ui/test-attrs/test-warns-dead-code.stderr b/tests/ui/test-attrs/test-warns-dead-code.stderr new file mode 100644 index 000000000..6c0f28841 --- /dev/null +++ b/tests/ui/test-attrs/test-warns-dead-code.stderr @@ -0,0 +1,14 @@ +error: function `dead` is never used + --> $DIR/test-warns-dead-code.rs:5:4 + | +LL | fn dead() {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/test-warns-dead-code.rs:3:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/thir-tree.rs b/tests/ui/thir-tree.rs new file mode 100644 index 000000000..32df7905a --- /dev/null +++ b/tests/ui/thir-tree.rs @@ -0,0 +1,4 @@ +// compile-flags: -Z unpretty=thir-tree +// check-pass + +pub fn main() {} diff --git a/tests/ui/thir-tree.stdout b/tests/ui/thir-tree.stdout new file mode 100644 index 000000000..4b6915f77 --- /dev/null +++ b/tests/ui/thir-tree.stdout @@ -0,0 +1,56 @@ +DefId(0:3 ~ thir_tree[8f1d]::main): +Thir { + arms: [], + blocks: [ + Block { + targeted_by_break: false, + region_scope: Node(1), + opt_destruction_scope: None, + span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + stmts: [], + expr: None, + safety_mode: Safe, + }, + ], + exprs: [ + Expr { + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + kind: Block { + block: b0, + }, + }, + Expr { + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + kind: Scope { + region_scope: Node(2), + lint_level: Explicit( + HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2), + ), + value: e0, + }, + }, + Expr { + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + kind: Scope { + region_scope: Destruction(2), + lint_level: Inherited, + value: e1, + }, + }, + ], + stmts: [], + params: [], +} + diff --git a/tests/ui/thread-local-mutation.rs b/tests/ui/thread-local-mutation.rs new file mode 100644 index 000000000..e738225ce --- /dev/null +++ b/tests/ui/thread-local-mutation.rs @@ -0,0 +1,18 @@ +// Regression test for #54901: immutable thread locals could be mutated. See: +// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697 +// https://github.com/rust-lang/rust/issues/54901 + +#![feature(thread_local)] + +#[thread_local] +static S: &str = "before"; + +fn set_s() { + S = "after"; //~ ERROR cannot assign to immutable +} + +fn main() { + println!("{}", S); + set_s(); + println!("{}", S); +} diff --git a/tests/ui/thread-local-mutation.stderr b/tests/ui/thread-local-mutation.stderr new file mode 100644 index 000000000..e5dc0e72e --- /dev/null +++ b/tests/ui/thread-local-mutation.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `S` + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; + | ^^^^^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/thread-local-static.rs b/tests/ui/thread-local-static.rs new file mode 100644 index 000000000..c7fee9e6b --- /dev/null +++ b/tests/ui/thread-local-static.rs @@ -0,0 +1,16 @@ +// edition:2018 + +#![feature(thread_local)] +#![feature(const_swap)] +#[thread_local] +static mut STATIC_VAR_2: [u32; 8] = [4; 8]; +const fn g(x: &mut [u32; 8]) { + //~^ ERROR mutable references are not allowed + std::mem::swap(x, &mut STATIC_VAR_2) + //~^ ERROR thread-local statics cannot be accessed + //~| ERROR mutable references are not allowed + //~| ERROR use of mutable static is unsafe + //~| constant functions cannot refer to statics +} + +fn main() {} diff --git a/tests/ui/thread-local-static.stderr b/tests/ui/thread-local-static.stderr new file mode 100644 index 000000000..712050a25 --- /dev/null +++ b/tests/ui/thread-local-static.stderr @@ -0,0 +1,44 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:7:12 + | +LL | const fn g(x: &mut [u32; 8]) { + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-static.rs:9:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + +error[E0013]: constant functions cannot refer to statics + --> $DIR/thread-local-static.rs:9:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:9:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/thread-local-static.rs:9:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0013, E0133, E0625, E0658. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/thread-local/name-collision.rs b/tests/ui/thread-local/name-collision.rs new file mode 100644 index 000000000..dcff9183a --- /dev/null +++ b/tests/ui/thread-local/name-collision.rs @@ -0,0 +1,15 @@ +// check-pass + +#[allow(non_camel_case_types)] +struct u8; + +std::thread_local! { + pub static A: i32 = f(); + pub static B: i32 = const { 0 }; +} + +fn f() -> i32 { + 0 +} + +fn main() {} diff --git a/tests/ui/thread-local/non-static.rs b/tests/ui/thread-local/non-static.rs new file mode 100644 index 000000000..f1c427387 --- /dev/null +++ b/tests/ui/thread-local/non-static.rs @@ -0,0 +1,30 @@ +// Check that #[thread_local] attribute is rejected on non-static items. +#![feature(thread_local)] + +#[thread_local] +//~^ ERROR attribute should be applied to a static +const A: u32 = 0; + +#[thread_local] +//~^ ERROR attribute should be applied to a static +fn main() { + #[thread_local] || {}; + //~^ ERROR attribute should be applied to a static +} + +struct S { + #[thread_local] + //~^ ERROR attribute should be applied to a static + a: String, + b: String, +} + +#[thread_local] +// Static. OK. +static B: u32 = 0; + +extern "C" { + #[thread_local] + // Foreign static. OK. + static C: u32; +} diff --git a/tests/ui/thread-local/non-static.stderr b/tests/ui/thread-local/non-static.stderr new file mode 100644 index 000000000..09a1618d6 --- /dev/null +++ b/tests/ui/thread-local/non-static.stderr @@ -0,0 +1,38 @@ +error: attribute should be applied to a static + --> $DIR/non-static.rs:4:1 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ +LL | +LL | const A: u32 = 0; + | ----------------- not a static + +error: attribute should be applied to a static + --> $DIR/non-static.rs:8:1 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ +LL | +LL | / fn main() { +LL | | #[thread_local] || {}; +LL | | +LL | | } + | |_- not a static + +error: attribute should be applied to a static + --> $DIR/non-static.rs:11:5 + | +LL | #[thread_local] || {}; + | ^^^^^^^^^^^^^^^ ----- not a static + +error: attribute should be applied to a static + --> $DIR/non-static.rs:16:5 + | +LL | #[thread_local] + | ^^^^^^^^^^^^^^^ +LL | +LL | a: String, + | --------- not a static + +error: aborting due to 4 previous errors + diff --git a/tests/ui/thread-local/thread-local-issue-37508.rs b/tests/ui/thread-local/thread-local-issue-37508.rs new file mode 100644 index 000000000..219108c77 --- /dev/null +++ b/tests/ui/thread-local/thread-local-issue-37508.rs @@ -0,0 +1,36 @@ +// only-x86_64 +// compile-flags: -Ccode-model=large --crate-type lib +// build-pass +// +// Regression test for issue #37508 + +#![no_main] +#![no_std] +#![feature(thread_local, lang_items)] + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_panic: &PanicInfo<'_>) -> ! { + loop {} +} + +pub struct BB; + +#[thread_local] +static mut KEY: Key = Key { inner: BB, dtor_running: false }; + +pub unsafe fn set() -> Option<&'static BB> { + if KEY.dtor_running { + return None; + } + Some(&KEY.inner) +} + +pub struct Key { + inner: BB, + dtor_running: bool, +} diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs new file mode 100644 index 000000000..fbd341388 --- /dev/null +++ b/tests/ui/thread-local/tls.rs @@ -0,0 +1,14 @@ +// run-pass +// ignore-emscripten no threads support +// compile-flags: -O + +#![feature(thread_local)] + +#[thread_local] +static S: u32 = 222; + +fn main() { + let local = &S as *const u32 as usize; + let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap(); + assert_ne!(local, foreign); +} diff --git a/tests/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs b/tests/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs new file mode 100644 index 000000000..4d3c4e8ac --- /dev/null +++ b/tests/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs @@ -0,0 +1,10 @@ +#![feature(cfg_target_thread_local, thread_local)] +#![crate_type = "lib"] + +#[cfg(target_thread_local)] +use std::cell::Cell; + +#[no_mangle] +#[cfg(target_thread_local)] +#[thread_local] +pub static FOO: Cell = Cell::new(3); diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs new file mode 100644 index 000000000..e3a39a44b --- /dev/null +++ b/tests/ui/threads-sendsync/child-outlives-parent.rs @@ -0,0 +1,13 @@ +// run-pass +// Reported as issue #126, child leaks the string. + +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +use std::thread; + +fn child2(_s: String) { } + +pub fn main() { + let _x = thread::spawn(move|| child2("hi".to_string())); +} diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs new file mode 100644 index 000000000..9fc661b14 --- /dev/null +++ b/tests/ui/threads-sendsync/clone-with-exterior.rs @@ -0,0 +1,20 @@ +// run-pass + +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +struct Pair { + a: isize, + b: isize +} + +pub fn main() { + let z: Box<_> = Box::new(Pair { a : 10, b : 12}); + + thread::spawn(move|| { + assert_eq!(z.a, 10); + assert_eq!(z.b, 12); + }).join(); +} diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs new file mode 100644 index 000000000..aa86e174d --- /dev/null +++ b/tests/ui/threads-sendsync/comm.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { + let (tx, rx) = channel(); + let t = thread::spawn(move|| { child(&tx) }); + let y = rx.recv().unwrap(); + println!("received"); + println!("{}", y); + assert_eq!(y, 10); + t.join(); +} + +fn child(c: &Sender) { + println!("sending"); + c.send(10).unwrap(); + println!("value sent"); +} diff --git a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs new file mode 100644 index 000000000..f52430773 --- /dev/null +++ b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs @@ -0,0 +1,49 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +use std::cell::RefCell; +use std::env; +use std::process::Command; + +fn main() { + let name = "YOU_ARE_THE_TEST"; + if env::var(name).is_ok() { + std::thread::spawn(|| { + TLS.with(|f| f.borrow().ensure()); + }) + .join() + .unwrap(); + } else { + let me = env::current_exe().unwrap(); + let output = Command::new(&me).env(name, "1").output().unwrap(); + println!("{:?}", output); + assert!(output.status.success()); + let stderr = String::from_utf8(output.stderr).unwrap(); + assert!(stderr.contains("hello new\n")); + assert!(stderr.contains("hello drop\n")); + } +} + +struct Stuff { + _x: usize, +} + +impl Stuff { + fn new() -> Self { + eprintln!("hello new"); + Self { _x: 0 } + } + + fn ensure(&self) {} +} + +impl Drop for Stuff { + fn drop(&mut self) { + eprintln!("hello drop"); + } +} + +thread_local! { + static TLS: RefCell = RefCell::new(Stuff::new()); +} diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs new file mode 100644 index 000000000..c28b4ca96 --- /dev/null +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -0,0 +1,32 @@ +// run-pass +// ignore-emscripten no threads +// ignore-sgx no processes + +use std::thread; +use std::env; +use std::process::Command; + +struct Handle(i32); + +impl Drop for Handle { + fn drop(&mut self) { panic!(); } +} + +thread_local!(static HANDLE: Handle = Handle(0)); + +fn main() { + let args = env::args().collect::>(); + if args.len() == 1 { + let out = Command::new(&args[0]).arg("test").output().unwrap(); + let stderr = std::str::from_utf8(&out.stderr).unwrap(); + assert!(stderr.contains("panicked at 'explicit panic'"), + "bad failure message:\n{}\n", stderr); + } else { + // TLS dtors are not always run on process exit + thread::spawn(|| { + HANDLE.with(|h| { + println!("{}", h.0); + }); + }).join().unwrap(); + } +} diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs new file mode 100644 index 000000000..3c9a6a80d --- /dev/null +++ b/tests/ui/threads-sendsync/issue-29488.rs @@ -0,0 +1,23 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + println!("test2"); + } +} + +thread_local!(static FOO: Foo = Foo); + +fn main() { + // Off the main thread due to #28129, be sure to initialize FOO first before + // calling `println!` + thread::spawn(|| { + FOO.with(|_| {}); + println!("test1"); + }).join().unwrap(); +} diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs new file mode 100644 index 000000000..32baeec43 --- /dev/null +++ b/tests/ui/threads-sendsync/issue-43733-2.rs @@ -0,0 +1,30 @@ +// ignore-wasm32 +// dont-check-compiler-stderr +#![feature(cfg_target_thread_local, thread_local_internals)] + +// On platforms *without* `#[thread_local]`, use +// a custom non-`Sync` type to fake the same error. +#[cfg(not(target_thread_local))] +struct Key { + _data: std::cell::UnsafeCell>, + _flag: std::cell::Cell<()>, +} + +#[cfg(not(target_thread_local))] +impl Key { + const fn new() -> Self { + Key { + _data: std::cell::UnsafeCell::new(None), + _flag: std::cell::Cell::new(()), + } + } +} + +#[cfg(target_thread_local)] +use std::thread::__FastLocalKeyInner as Key; + +static __KEY: Key<()> = Key::new(); +//~^ ERROR `UnsafeCell>` cannot be shared between threads +//~| ERROR cannot be shared between threads safely [E0277] + +fn main() {} diff --git a/tests/ui/threads-sendsync/issue-43733.mir.stderr b/tests/ui/threads-sendsync/issue-43733.mir.stderr new file mode 100644 index 000000000..1e21a6b37 --- /dev/null +++ b/tests/ui/threads-sendsync/issue-43733.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:21:5 + | +LL | __KEY.get(Default::default) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:26:42 + | +LL | static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs new file mode 100644 index 000000000..935e02944 --- /dev/null +++ b/tests/ui/threads-sendsync/issue-43733.rs @@ -0,0 +1,38 @@ +// ignore-wasm32 +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +// normalize-stderr-test: "__FastLocalKeyInner::::get" -> "$$LOCALKEYINNER::::get" +// normalize-stderr-test: "__OsLocalKeyInner::::get" -> "$$LOCALKEYINNER::::get" +#![feature(thread_local)] +#![feature(cfg_target_thread_local, thread_local_internals)] + +use std::cell::RefCell; + +type Foo = std::cell::RefCell; + +#[cfg(target_thread_local)] +#[thread_local] +static __KEY: std::thread::__FastLocalKeyInner = std::thread::__FastLocalKeyInner::new(); + +#[cfg(not(target_thread_local))] +static __KEY: std::thread::__OsLocalKeyInner = std::thread::__OsLocalKeyInner::new(); + +fn __getit(_: Option<&mut Option>>) -> std::option::Option<&'static Foo> { + __KEY.get(Default::default) + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `__ +} + +static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `LocalKey::::new` + +fn main() { + FOO.with(|foo| println!("{}", foo.borrow())); + std::thread::spawn(|| { + FOO.with(|foo| *foo.borrow_mut() += "foo"); + }) + .join() + .unwrap(); + FOO.with(|foo| println!("{}", foo.borrow())); +} diff --git a/tests/ui/threads-sendsync/issue-43733.thir.stderr b/tests/ui/threads-sendsync/issue-43733.thir.stderr new file mode 100644 index 000000000..ea7ff4080 --- /dev/null +++ b/tests/ui/threads-sendsync/issue-43733.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function `$LOCALKEYINNER::::get` is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:21:5 + | +LL | __KEY.get(Default::default) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `LocalKey::::new` is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:26:42 + | +LL | static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs new file mode 100644 index 000000000..948f2a7bd --- /dev/null +++ b/tests/ui/threads-sendsync/issue-4446.rs @@ -0,0 +1,15 @@ +// run-pass +// ignore-emscripten no threads support + +use std::sync::mpsc::channel; +use std::thread; + +pub fn main() { + let (tx, rx) = channel(); + + tx.send("hello, world").unwrap(); + + thread::spawn(move|| { + println!("{}", rx.recv().unwrap()); + }).join().ok().unwrap(); +} diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs new file mode 100644 index 000000000..27d032689 --- /dev/null +++ b/tests/ui/threads-sendsync/issue-4448.rs @@ -0,0 +1,16 @@ +// run-pass +// ignore-emscripten no threads support + +use std::sync::mpsc::channel; +use std::thread; + +pub fn main() { + let (tx, rx) = channel::<&'static str>(); + + let t = thread::spawn(move|| { + assert_eq!(rx.recv().unwrap(), "hello, world"); + }); + + tx.send("hello, world").unwrap(); + t.join().ok().unwrap(); +} diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs new file mode 100644 index 000000000..95be7616a --- /dev/null +++ b/tests/ui/threads-sendsync/issue-8827.rs @@ -0,0 +1,53 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Receiver}; + +fn periodical(n: isize) -> Receiver { + let (chan, port) = channel(); + thread::spawn(move|| { + loop { + for _ in 1..n { + match chan.send(false) { + Ok(()) => {} + Err(..) => break, + } + } + match chan.send(true) { + Ok(()) => {} + Err(..) => break + } + } + }); + return port; +} + +fn integers() -> Receiver { + let (chan, port) = channel(); + thread::spawn(move|| { + let mut i = 1; + loop { + match chan.send(i) { + Ok(()) => {} + Err(..) => break, + } + i = i + 1; + } + }); + return port; +} + +fn main() { + let ints = integers(); + let threes = periodical(3); + let fives = periodical(5); + for _ in 1..100 { + match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) { + (_, true, true) => println!("FizzBuzz"), + (_, true, false) => println!("Fizz"), + (_, false, true) => println!("Buzz"), + (i, false, false) => println!("{}", i) + } + } +} diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs new file mode 100644 index 000000000..3e7e9a51c --- /dev/null +++ b/tests/ui/threads-sendsync/issue-9396.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(deprecated)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{TryRecvError, channel}; +use std::thread; + +pub fn main() { + let (tx, rx) = channel(); + let t = thread::spawn(move||{ + thread::sleep_ms(10); + tx.send(()).unwrap(); + }); + loop { + match rx.try_recv() { + Ok(()) => break, + Err(TryRecvError::Empty) => {} + Err(TryRecvError::Disconnected) => unreachable!() + } + } + t.join(); +} diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs new file mode 100644 index 000000000..c2e1912de --- /dev/null +++ b/tests/ui/threads-sendsync/mpsc_stress.rs @@ -0,0 +1,200 @@ +// run-pass +// compile-flags:--test +// ignore-emscripten + +use std::sync::mpsc::channel; +use std::sync::mpsc::TryRecvError; +use std::sync::mpsc::RecvError; +use std::sync::mpsc::RecvTimeoutError; +use std::sync::Arc; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; + +use std::thread; +use std::time::Duration; + + +/// Simple thread synchronization utility +struct Barrier { + // Not using mutex/condvar for precision + shared: Arc, + count: usize, +} + +impl Barrier { + fn new(count: usize) -> Vec { + let shared = Arc::new(AtomicUsize::new(0)); + (0..count).map(|_| Barrier { shared: shared.clone(), count: count }).collect() + } + + fn new2() -> (Barrier, Barrier) { + let mut v = Barrier::new(2); + (v.pop().unwrap(), v.pop().unwrap()) + } + + /// Returns when `count` threads enter `wait` + fn wait(self) { + self.shared.fetch_add(1, Ordering::SeqCst); + while self.shared.load(Ordering::SeqCst) != self.count { + #[cfg(target_env = "sgx")] + thread::yield_now(); + } + } +} + + +fn shared_close_sender_does_not_lose_messages_iter() { + let (tb, rb) = Barrier::new2(); + + let (tx, rx) = channel(); + let _ = tx.clone(); // convert to shared + + thread::spawn(move || { + tb.wait(); + thread::sleep(Duration::from_micros(1)); + tx.send(17).expect("send"); + drop(tx); + }); + + let i = rx.into_iter(); + rb.wait(); + // Make sure it doesn't return disconnected before returning an element + assert_eq!(vec![17], i.collect::>()); +} + +#[test] +fn shared_close_sender_does_not_lose_messages() { + with_minimum_timer_resolution(|| { + for _ in 0..10000 { + shared_close_sender_does_not_lose_messages_iter(); + } + }); +} + + +// https://github.com/rust-lang/rust/issues/39364 +fn concurrent_recv_timeout_and_upgrade_iter() { + // 1 us + let sleep = Duration::new(0, 1_000); + + let (a, b) = Barrier::new2(); + let (tx, rx) = channel(); + let th = thread::spawn(move || { + a.wait(); + loop { + match rx.recv_timeout(sleep) { + Ok(_) => { + break; + }, + Err(_) => {}, + } + } + }); + b.wait(); + thread::sleep(sleep); + tx.clone().send(()).expect("send"); + th.join().unwrap(); +} + +#[test] +fn concurrent_recv_timeout_and_upgrade() { + with_minimum_timer_resolution(|| { + for _ in 0..10000 { + concurrent_recv_timeout_and_upgrade_iter(); + } + }); +} + + +fn concurrent_writes_iter() { + const THREADS: usize = 4; + const PER_THR: usize = 100; + + let mut bs = Barrier::new(THREADS + 1); + let (tx, rx) = channel(); + + let mut threads = Vec::new(); + for j in 0..THREADS { + let tx = tx.clone(); + let b = bs.pop().unwrap(); + threads.push(thread::spawn(move || { + b.wait(); + for i in 0..PER_THR { + tx.send(j * 1000 + i).expect("send"); + } + })); + } + + let b = bs.pop().unwrap(); + b.wait(); + + let mut v: Vec<_> = rx.iter().take(THREADS * PER_THR).collect(); + v.sort(); + + for j in 0..THREADS { + for i in 0..PER_THR { + assert_eq!(j * 1000 + i, v[j * PER_THR + i]); + } + } + + for t in threads { + t.join().unwrap(); + } + + let one_us = Duration::new(0, 1000); + + assert_eq!(TryRecvError::Empty, rx.try_recv().unwrap_err()); + assert_eq!(RecvTimeoutError::Timeout, rx.recv_timeout(one_us).unwrap_err()); + + drop(tx); + + assert_eq!(RecvError, rx.recv().unwrap_err()); + assert_eq!(RecvTimeoutError::Disconnected, rx.recv_timeout(one_us).unwrap_err()); + assert_eq!(TryRecvError::Disconnected, rx.try_recv().unwrap_err()); +} + +#[test] +fn concurrent_writes() { + with_minimum_timer_resolution(|| { + for _ in 0..100 { + concurrent_writes_iter(); + } + }); +} + +#[cfg(windows)] +pub mod timeapi { + #![allow(non_snake_case)] + use std::ffi::c_uint; + + pub const TIMERR_NOERROR: c_uint = 0; + + #[link(name = "winmm")] + extern "system" { + pub fn timeBeginPeriod(uPeriod: c_uint) -> c_uint; + pub fn timeEndPeriod(uPeriod: c_uint) -> c_uint; + } +} + +/// Window's minimum sleep time can be as much as 16ms. +// This function evaluates the closure with this resolution +// set as low as possible. +/// +/// This takes the above test's duration from 10000*16/1000/60=2.67 minutes to ~16 seconds. +fn with_minimum_timer_resolution(f: impl Fn()) { + #[cfg(windows)] + unsafe { + let ret = timeapi::timeBeginPeriod(1); + assert_eq!(ret, timeapi::TIMERR_NOERROR); + + f(); + + let ret = timeapi::timeEndPeriod(1); + assert_eq!(ret, timeapi::TIMERR_NOERROR); + } + + #[cfg(not(windows))] + { + f(); + } +} diff --git a/tests/ui/threads-sendsync/send-is-not-static-par-for.rs b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs new file mode 100644 index 000000000..dbe465551 --- /dev/null +++ b/tests/ui/threads-sendsync/send-is-not-static-par-for.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(unused_imports)] +use std::thread; +use std::sync::Mutex; + +fn par_for(iter: I, f: F) + where I: Iterator, + I::Item: Send, + F: Fn(I::Item) + Sync +{ + for item in iter { + f(item) + } +} + +fn sum(x: &[i32]) { + let sum_lengths = Mutex::new(0); + par_for(x.windows(4), |x| { + *sum_lengths.lock().unwrap() += x.len() + }); + + assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4); +} + +fn main() { + let mut elements = [0; 20]; + + // iterators over references into this stack frame + par_for(elements.iter_mut().enumerate(), |(i, x)| { + *x = i as i32 + }); + + sum(&elements) +} diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs new file mode 100644 index 000000000..023a84d6b --- /dev/null +++ b/tests/ui/threads-sendsync/send-resource.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::channel; + +struct test { + f: isize, +} + +impl Drop for test { + fn drop(&mut self) {} +} + +fn test(f: isize) -> test { + test { + f: f + } +} + +pub fn main() { + let (tx, rx) = channel(); + + let t = thread::spawn(move|| { + let (tx2, rx2) = channel(); + tx.send(tx2).unwrap(); + + let _r = rx2.recv().unwrap(); + }); + + rx.recv().unwrap().send(test(42)).unwrap(); + + t.join(); +} diff --git a/tests/ui/threads-sendsync/send-type-inference.rs b/tests/ui/threads-sendsync/send-type-inference.rs new file mode 100644 index 000000000..0d9af7512 --- /dev/null +++ b/tests/ui/threads-sendsync/send-type-inference.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_mut)] +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::{channel, Sender}; + +// tests that ctrl's type gets inferred properly +struct Command { + key: K, + val: V +} + +fn cache_server(mut tx: Sender>>) { + let (tx1, _rx) = channel(); + tx.send(tx1); +} +pub fn main() { } diff --git a/tests/ui/threads-sendsync/send_str_hashmap.rs b/tests/ui/threads-sendsync/send_str_hashmap.rs new file mode 100644 index 000000000..7d4cca8ad --- /dev/null +++ b/tests/ui/threads-sendsync/send_str_hashmap.rs @@ -0,0 +1,53 @@ +// run-pass +use std::collections::HashMap; +use std::borrow::Cow; + +use std::borrow::Cow::Borrowed as B; +use std::borrow::Cow::Owned as O; + +type SendStr = Cow<'static, str>; + +fn main() { + let mut map: HashMap = HashMap::new(); + assert!(map.insert(B("foo"), 42).is_none()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + assert!(map.insert(B("foo"), 42).is_some()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + + assert!(map.insert(B("foo"), 43).is_some()); + assert!(map.insert(O("foo".to_string()), 44).is_some()); + assert!(map.insert(B("foo"), 45).is_some()); + assert!(map.insert(O("foo".to_string()), 46).is_some()); + + let v = 46; + + assert_eq!(map.get(&O("foo".to_string())), Some(&v)); + assert_eq!(map.get(&B("foo")), Some(&v)); + + let (a, b, c, d) = (50, 51, 52, 53); + + assert!(map.insert(B("abc"), a).is_none()); + assert!(map.insert(O("bcd".to_string()), b).is_none()); + assert!(map.insert(B("cde"), c).is_none()); + assert!(map.insert(O("def".to_string()), d).is_none()); + + assert!(map.insert(B("abc"), a).is_some()); + assert!(map.insert(O("bcd".to_string()), b).is_some()); + assert!(map.insert(B("cde"), c).is_some()); + assert!(map.insert(O("def".to_string()), d).is_some()); + + assert!(map.insert(O("abc".to_string()), a).is_some()); + assert!(map.insert(B("bcd"), b).is_some()); + assert!(map.insert(O("cde".to_string()), c).is_some()); + assert!(map.insert(B("def"), d).is_some()); + + assert_eq!(map.get("abc"), Some(&a)); + assert_eq!(map.get("bcd"), Some(&b)); + assert_eq!(map.get("cde"), Some(&c)); + assert_eq!(map.get("def"), Some(&d)); + + assert_eq!(map.get(&B("abc")), Some(&a)); + assert_eq!(map.get(&B("bcd")), Some(&b)); + assert_eq!(map.get(&B("cde")), Some(&c)); + assert_eq!(map.get(&B("def")), Some(&d)); +} diff --git a/tests/ui/threads-sendsync/send_str_treemap.rs b/tests/ui/threads-sendsync/send_str_treemap.rs new file mode 100644 index 000000000..4d4631745 --- /dev/null +++ b/tests/ui/threads-sendsync/send_str_treemap.rs @@ -0,0 +1,58 @@ +// run-pass +use std::collections::BTreeMap; +use std::borrow::Cow; + +use std::borrow::Cow::{Owned as O, Borrowed as B}; + +type SendStr = Cow<'static, str>; + +fn main() { + let mut map: BTreeMap = BTreeMap::new(); + assert!(map.insert(B("foo"), 42).is_none()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + assert!(map.insert(B("foo"), 42).is_some()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + + assert!(map.insert(B("foo"), 43).is_some()); + assert!(map.insert(O("foo".to_string()), 44).is_some()); + assert!(map.insert(B("foo"), 45).is_some()); + assert!(map.insert(O("foo".to_string()), 46).is_some()); + + let v = 46; + + assert_eq!(map.get(&O("foo".to_string())), Some(&v)); + assert_eq!(map.get(&B("foo")), Some(&v)); + + let (a, b, c, d) = (50, 51, 52, 53); + + assert!(map.insert(B("abc"), a).is_none()); + assert!(map.insert(O("bcd".to_string()), b).is_none()); + assert!(map.insert(B("cde"), c).is_none()); + assert!(map.insert(O("def".to_string()), d).is_none()); + + assert!(map.insert(B("abc"), a).is_some()); + assert!(map.insert(O("bcd".to_string()), b).is_some()); + assert!(map.insert(B("cde"), c).is_some()); + assert!(map.insert(O("def".to_string()), d).is_some()); + + assert!(map.insert(O("abc".to_string()), a).is_some()); + assert!(map.insert(B("bcd"), b).is_some()); + assert!(map.insert(O("cde".to_string()), c).is_some()); + assert!(map.insert(B("def"), d).is_some()); + + assert_eq!(map.get(&B("abc")), Some(&a)); + assert_eq!(map.get(&B("bcd")), Some(&b)); + assert_eq!(map.get(&B("cde")), Some(&c)); + assert_eq!(map.get(&B("def")), Some(&d)); + + assert_eq!(map.get(&O("abc".to_string())), Some(&a)); + assert_eq!(map.get(&O("bcd".to_string())), Some(&b)); + assert_eq!(map.get(&O("cde".to_string())), Some(&c)); + assert_eq!(map.get(&O("def".to_string())), Some(&d)); + + assert!(map.remove(&B("foo")).is_some()); + assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v)) + .collect::>() + .concat(), + "abc50bcd51cde52def53".to_string()); +} diff --git a/tests/ui/threads-sendsync/sendable-class.rs b/tests/ui/threads-sendsync/sendable-class.rs new file mode 100644 index 000000000..7facf245b --- /dev/null +++ b/tests/ui/threads-sendsync/sendable-class.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_camel_case_types)] + +// Test that a class with only sendable fields can be sent + +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::channel; + +struct foo { + i: isize, + j: char, +} + +fn foo(i:isize, j: char) -> foo { + foo { + i: i, + j: j + } +} + +pub fn main() { + let (tx, rx) = channel(); + tx.send(foo(42, 'c')); +} diff --git a/tests/ui/threads-sendsync/sendfn-is-a-block.rs b/tests/ui/threads-sendsync/sendfn-is-a-block.rs new file mode 100644 index 000000000..62807d894 --- /dev/null +++ b/tests/ui/threads-sendsync/sendfn-is-a-block.rs @@ -0,0 +1,11 @@ +// run-pass + + +fn test(f: F) -> usize where F: FnOnce(usize) -> usize { + return f(22); +} + +pub fn main() { + let y = test(|x| 4 * x); + assert_eq!(y, 88); +} diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs new file mode 100644 index 000000000..1e598b9e7 --- /dev/null +++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -0,0 +1,21 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { test05(); } + +fn test05_start(f: F) { + f(22); +} + +fn test05() { + let three: Box<_> = Box::new(3); + let fn_to_send = move|n:isize| { + println!("{}", *three + n); // will copy x into the closure + assert_eq!(*three, 3); + }; + thread::spawn(move|| { + test05_start(fn_to_send); + }).join().ok().unwrap(); +} diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs new file mode 100644 index 000000000..1243bb257 --- /dev/null +++ b/tests/ui/threads-sendsync/spawn-fn.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +fn x(s: String, n: isize) { + println!("{}", s); + println!("{}", n); +} + +pub fn main() { + let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65) ); + let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66) ); + let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67) ); + let mut i = 30; + while i > 0 { + i = i - 1; + println!("parent sleeping"); + thread::yield_now(); + } + t1.join(); + t2.join(); + t3.join(); +} diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs new file mode 100644 index 000000000..1bead6e1b --- /dev/null +++ b/tests/ui/threads-sendsync/spawn-types.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-emscripten no threads support + +/* + Make sure we can spawn tasks that take different types of + parameters. This is based on a test case for #520 provided by Rob + Arnold. + */ + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +type ctx = Sender; + +fn iotask(_tx: &ctx, ip: String) { + assert_eq!(ip, "localhost".to_string()); +} + +pub fn main() { + let (tx, _rx) = channel::(); + let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); + t.join().ok().unwrap(); +} diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs new file mode 100644 index 000000000..b1dcc9417 --- /dev/null +++ b/tests/ui/threads-sendsync/spawn.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + thread::spawn(move|| child(10)).join().ok().unwrap(); +} + +fn child(i: isize) { println!("{}", i); assert_eq!(i, 10); } diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs new file mode 100644 index 000000000..83e066aef --- /dev/null +++ b/tests/ui/threads-sendsync/spawn2.rs @@ -0,0 +1,31 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); + t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug +} + +fn child(args: (isize, isize, isize, isize, isize, isize, isize, isize, isize)) { + let (i1, i2, i3, i4, i5, i6, i7, i8, i9) = args; + println!("{}", i1); + println!("{}", i2); + println!("{}", i3); + println!("{}", i4); + println!("{}", i5); + println!("{}", i6); + println!("{}", i7); + println!("{}", i8); + println!("{}", i9); + assert_eq!(i1, 10); + assert_eq!(i2, 20); + assert_eq!(i3, 30); + assert_eq!(i4, 40); + assert_eq!(i5, 50); + assert_eq!(i6, 60); + assert_eq!(i7, 70); + assert_eq!(i8, 80); + assert_eq!(i9, 90); +} diff --git a/tests/ui/threads-sendsync/spawning-with-debug.rs b/tests/ui/threads-sendsync/spawning-with-debug.rs new file mode 100644 index 000000000..9d3487ffb --- /dev/null +++ b/tests/ui/threads-sendsync/spawning-with-debug.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-windows +// exec-env:RUST_LOG=debug +// ignore-emscripten no threads support + +// regression test for issue #10405, make sure we don't call println! too soon. + +use std::thread::Builder; + +pub fn main() { + let mut t = Builder::new(); + t.spawn(move || ()); +} diff --git a/tests/ui/threads-sendsync/std-sync-right-kind-impls.rs b/tests/ui/threads-sendsync/std-sync-right-kind-impls.rs new file mode 100644 index 000000000..bc64c8162 --- /dev/null +++ b/tests/ui/threads-sendsync/std-sync-right-kind-impls.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::sync; + +fn assert_both() {} + +fn main() { + assert_both::>(); + assert_both::(); + assert_both::>(); + assert_both::(); + assert_both::>(); + assert_both::>(); + assert_both::(); +} diff --git a/tests/ui/threads-sendsync/sync-send-atomics.rs b/tests/ui/threads-sendsync/sync-send-atomics.rs new file mode 100644 index 000000000..0466f4f0e --- /dev/null +++ b/tests/ui/threads-sendsync/sync-send-atomics.rs @@ -0,0 +1,14 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +use std::sync::atomic::*; + +trait SendSync: Send + Sync {} + +impl SendSync for AtomicBool {} +impl SendSync for AtomicIsize {} +impl SendSync for AtomicUsize {} +impl SendSync for AtomicPtr {} + +fn main() {} diff --git a/tests/ui/threads-sendsync/sync-send-in-std.rs b/tests/ui/threads-sendsync/sync-send-in-std.rs new file mode 100644 index 000000000..6d1fba64e --- /dev/null +++ b/tests/ui/threads-sendsync/sync-send-in-std.rs @@ -0,0 +1,25 @@ +// run-pass + +// ignore-wasm32-bare networking not available +// ignore-sgx ToSocketAddrs cannot be used for DNS Resolution +// ignore-fuchsia Req. test-harness networking privileges + +use std::net::ToSocketAddrs; + +fn is_sync(_: T) where T: Sync {} +fn is_send(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + )+ + }) +} + +fn main() { + all_sync_send!("localhost:80".to_socket_addrs().unwrap(), next); +} diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs new file mode 100644 index 000000000..fd53bb607 --- /dev/null +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs @@ -0,0 +1,71 @@ +// run-pass + +#![allow(warnings)] +#![feature(drain, collections_bound, btree_range)] + +use std::collections::BinaryHeap; +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::LinkedList; +use std::collections::VecDeque; +use std::collections::HashMap; +use std::collections::HashSet; + +use std::mem; +use std::ops::Bound::Included; + +fn is_sync(_: T) where T: Sync {} +fn is_send(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + )+ + }) +} + +macro_rules! is_sync_send { + ($ctor:expr, $iter:ident($($param:expr),+)) => ({ + let mut x = $ctor; + is_sync(x.$iter($( $param ),+)); + let mut y = $ctor; + is_send(y.$iter($( $param ),+)); + }) +} + +fn main() { + // The iterator "generator" list should exhaust what corresponding + // implementations have where `Sync` and `Send` semantics apply. + all_sync_send!(BinaryHeap::::new(), iter, drain, into_iter); + + all_sync_send!(BTreeMap::::new(), iter, iter_mut, into_iter, keys, values); + is_sync_send!(BTreeMap::::new(), range((Included(&0), Included(&9)))); + is_sync_send!(BTreeMap::::new(), range_mut((Included(&0), Included(&9)))); + + all_sync_send!(BTreeSet::::new(), iter, into_iter); + is_sync_send!(BTreeSet::::new(), range((Included(&0), Included(&9)))); + is_sync_send!(BTreeSet::::new(), difference(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), symmetric_difference(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), intersection(&BTreeSet::::new())); + is_sync_send!(BTreeSet::::new(), union(&BTreeSet::::new())); + + all_sync_send!(HashMap::::new(), iter, iter_mut, drain, into_iter, keys, values); + is_sync_send!(HashMap::::new(), entry(0)); + all_sync_send!(HashSet::::new(), iter, drain, into_iter); + is_sync_send!(HashSet::::new(), difference(&HashSet::::new())); + is_sync_send!(HashSet::::new(), symmetric_difference(&HashSet::::new())); + is_sync_send!(HashSet::::new(), intersection(&HashSet::::new())); + is_sync_send!(HashSet::::new(), union(&HashSet::::new())); + + all_sync_send!(LinkedList::::new(), iter, iter_mut, into_iter); + + all_sync_send!(VecDeque::::new(), iter, iter_mut, into_iter); + is_sync_send!(VecDeque::::new(), drain(..)); + + all_sync_send!(Vec::::new(), into_iter); + is_sync_send!(Vec::::new(), drain(..)); + is_sync_send!(String::new(), drain(..)); +} diff --git a/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs new file mode 100644 index 000000000..2f6d35f01 --- /dev/null +++ b/tests/ui/threads-sendsync/sync-send-iterators-in-libcore.rs @@ -0,0 +1,105 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(warnings)] + +use std::iter::{empty, once, repeat}; + +fn is_sync(_: T) where T: Sync {} +fn is_send(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $iter:ident) => ({ + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + }); + ($ctor:expr, $iter:ident($($param:expr),+)) => ({ + let mut x = $ctor; + is_sync(x.$iter($( $param ),+)); + let mut y = $ctor; + is_send(y.$iter($( $param ),+)); + }); + ($ctor:expr, $iter:ident, $($rest:tt)*) => ({ + all_sync_send!($ctor, $iter); + all_sync_send!($ctor, $($rest)*); + }); + ($ctor:expr, $iter:ident($($param:expr),+), $($rest:tt)*) => ({ + all_sync_send!($ctor, $iter($( $param ),+)); + all_sync_send!($ctor, $($rest)*); + }); +} + +macro_rules! all_sync_send_mutable_ref { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync((&mut x).$iter()); + let mut y = $ctor; + is_send((&mut y).$iter()); + )+ + }) +} + +macro_rules! is_sync_send { + ($ctor:expr) => ({ + let x = $ctor; + is_sync(x); + let y = $ctor; + is_send(y); + }) +} + +fn main() { + // for char.rs + all_sync_send!("Я", escape_debug, escape_default, escape_unicode); + + // for iter.rs + all_sync_send_mutable_ref!([1], iter); + + // Bytes implements DoubleEndedIterator + all_sync_send!("a".bytes(), rev); + + let a = [1]; + let b = [2]; + all_sync_send!(a.iter(), + cloned, + cycle, + chain([2].iter()), + zip([2].iter()), + map(|_| 1), + filter(|_| true), + filter_map(|_| Some(1)), + enumerate, + peekable, + skip_while(|_| true), + take_while(|_| true), + skip(1), + take(1), + scan(1, |_, _| Some(1)), + flat_map(|_| b.iter()), + fuse, + inspect(|_| ())); + + is_sync_send!((1..).step_by(2)); + is_sync_send!((1..2).step_by(2)); + is_sync_send!((1..2)); + is_sync_send!((1..)); + is_sync_send!(repeat(1)); + is_sync_send!(empty::()); + is_sync_send!(empty::<*mut i32>()); + is_sync_send!(once(1)); + + // for option.rs + // FIXME + + // for result.rs + // FIXME + + // for slice.rs + // FIXME + + // for str/mod.rs + // FIXME +} diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs new file mode 100644 index 000000000..2b9a50e4d --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-0.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { test05(); } + +fn test05_start(tx : &Sender) { + tx.send(10).unwrap(); + println!("sent 10"); + tx.send(20).unwrap(); + println!("sent 20"); + tx.send(30).unwrap(); + println!("sent 30"); +} + +fn test05() { + let (tx, rx) = channel(); + let t = thread::spawn(move|| { test05_start(&tx) }); + let mut value: isize = rx.recv().unwrap(); + println!("{}", value); + value = rx.recv().unwrap(); + println!("{}", value); + value = rx.recv().unwrap(); + println!("{}", value); + assert_eq!(value, 30); + t.join(); +} diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs new file mode 100644 index 000000000..68ca62909 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-1.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { test00(); } + +fn start() { println!("Started / Finished task."); } + +fn test00() { + thread::spawn(move|| start() ).join(); + println!("Completing."); +} diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs new file mode 100644 index 000000000..4cac0dc90 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-10.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +fn start(tx: &Sender>) { + let (tx2, rx) = channel(); + tx.send(tx2).unwrap(); + + let mut a; + let mut b; + a = rx.recv().unwrap(); + assert_eq!(a, "A".to_string()); + println!("{}", a); + b = rx.recv().unwrap(); + assert_eq!(b, "B".to_string()); + println!("{}", b); +} + +pub fn main() { + let (tx, rx) = channel(); + let child = thread::spawn(move|| { start(&tx) }); + + let mut c = rx.recv().unwrap(); + c.send("A".to_string()).unwrap(); + c.send("B".to_string()).unwrap(); + thread::yield_now(); + + child.join(); +} diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs new file mode 100644 index 000000000..8541e143f --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-11.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_must_use)] +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn start(tx: &Sender>) { + let (tx2, _rx) = channel(); + tx.send(tx2).unwrap(); +} + +pub fn main() { + let (tx, rx) = channel(); + let child = thread::spawn(move|| { + start(&tx) + }); + let _tx = rx.recv().unwrap(); + child.join(); +} diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs new file mode 100644 index 000000000..613a5cee5 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-12.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { test00(); } + +fn start(_task_number: isize) { println!("Started / Finished task."); } + +fn test00() { + let i: isize = 0; + let mut result = thread::spawn(move|| { + start(i) + }); + + // Sleep long enough for the thread to finish. + let mut i = 0_usize; + while i < 10000 { + thread::yield_now(); + i += 1; + } + + // Try joining threads that have already finished. + result.join(); + + println!("Joined task."); +} diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs new file mode 100644 index 000000000..327eaaf8f --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-13.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_variables)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn start(tx: &Sender, start: isize, number_of_messages: isize) { + let mut i: isize = 0; + while i< number_of_messages { tx.send(start + i).unwrap(); i += 1; } +} + +pub fn main() { + println!("Check that we don't deadlock."); + let (tx, rx) = channel(); + let _ = thread::spawn(move|| { start(&tx, 0, 10) }).join(); + println!("Joined task"); +} diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs new file mode 100644 index 000000000..88d6b0902 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-14.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(unused_parens)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +pub fn main() { + let (tx, rx) = channel(); + + // Spawn 10 threads each sending us back one isize. + let mut i = 10; + while (i > 0) { + println!("{}", i); + let tx = tx.clone(); + thread::spawn({let i = i; move|| { child(i, &tx) }}); + i = i - 1; + } + + // Spawned threads are likely killed before they get a chance to send + // anything back, so we deadlock here. + + i = 10; + while (i > 0) { + println!("{}", i); + rx.recv().unwrap(); + i = i - 1; + } + + println!("main thread exiting"); +} + +fn child(x: isize, tx: &Sender) { + println!("{}", x); + tx.send(x).unwrap(); +} diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs new file mode 100644 index 000000000..adb14abdc --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-15.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn start(tx: &Sender, i0: isize) { + let mut i = i0; + while i > 0 { + tx.send(0).unwrap(); + i = i - 1; + } +} + +pub fn main() { + // Spawn a thread that sends us back messages. The parent thread + // is likely to terminate before the child completes, so from + // the child's point of view the receiver may die. We should + // drop messages on the floor in this case, and not crash! + let (tx, rx) = channel(); + let t = thread::spawn(move|| { + start(&tx, 10) + }); + rx.recv(); + t.join(); +} diff --git a/tests/ui/threads-sendsync/task-comm-16.rs b/tests/ui/threads-sendsync/task-comm-16.rs new file mode 100644 index 000000000..d808fd9ac --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-16.rs @@ -0,0 +1,111 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_parens)] +#![allow(non_camel_case_types)] + +use std::sync::mpsc::channel; +use std::cmp; + +// Tests of ports and channels on various types +fn test_rec() { + struct R {val0: isize, val1: u8, val2: char} + + let (tx, rx) = channel(); + let r0: R = R {val0: 0, val1: 1, val2: '2'}; + tx.send(r0).unwrap(); + let mut r1: R; + r1 = rx.recv().unwrap(); + assert_eq!(r1.val0, 0); + assert_eq!(r1.val1, 1); + assert_eq!(r1.val2, '2'); +} + +fn test_vec() { + let (tx, rx) = channel(); + let v0: Vec = vec![0, 1, 2]; + tx.send(v0).unwrap(); + let v1 = rx.recv().unwrap(); + assert_eq!(v1[0], 0); + assert_eq!(v1[1], 1); + assert_eq!(v1[2], 2); +} + +fn test_str() { + let (tx, rx) = channel(); + let s0 = "test".to_string(); + tx.send(s0).unwrap(); + let s1 = rx.recv().unwrap(); + assert_eq!(s1.as_bytes()[0], 't' as u8); + assert_eq!(s1.as_bytes()[1], 'e' as u8); + assert_eq!(s1.as_bytes()[2], 's' as u8); + assert_eq!(s1.as_bytes()[3], 't' as u8); +} + +#[derive(Debug)] +enum t { + tag1, + tag2(isize), + tag3(isize, u8, char) +} + +impl cmp::PartialEq for t { + fn eq(&self, other: &t) -> bool { + match *self { + t::tag1 => { + match (*other) { + t::tag1 => true, + _ => false + } + } + t::tag2(e0a) => { + match (*other) { + t::tag2(e0b) => e0a == e0b, + _ => false + } + } + t::tag3(e0a, e1a, e2a) => { + match (*other) { + t::tag3(e0b, e1b, e2b) => + e0a == e0b && e1a == e1b && e2a == e2b, + _ => false + } + } + } + } + fn ne(&self, other: &t) -> bool { !(*self).eq(other) } +} + +fn test_tag() { + let (tx, rx) = channel(); + tx.send(t::tag1).unwrap(); + tx.send(t::tag2(10)).unwrap(); + tx.send(t::tag3(10, 11, 'A')).unwrap(); + let mut t1: t; + t1 = rx.recv().unwrap(); + assert_eq!(t1, t::tag1); + t1 = rx.recv().unwrap(); + assert_eq!(t1, t::tag2(10)); + t1 = rx.recv().unwrap(); + assert_eq!(t1, t::tag3(10, 11, 'A')); +} + +fn test_chan() { + let (tx1, rx1) = channel(); + let (tx2, rx2) = channel(); + tx1.send(tx2).unwrap(); + let tx2 = rx1.recv().unwrap(); + // Does the transmitted channel still work? + + tx2.send(10).unwrap(); + let mut i: isize; + i = rx2.recv().unwrap(); + assert_eq!(i, 10); +} + +pub fn main() { + test_rec(); + test_vec(); + test_str(); + test_tag(); + test_chan(); +} diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs new file mode 100644 index 000000000..722497870 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-17.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +// Issue #922 + +// This test is specifically about spawning temporary closures. + +use std::thread; + +fn f() { +} + +pub fn main() { + thread::spawn(move|| f() ).join(); +} diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs new file mode 100644 index 000000000..570ae0a82 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-3.rs @@ -0,0 +1,63 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } + +fn test00_start(ch: &Sender, message: isize, count: isize) { + println!("Starting test00_start"); + let mut i: isize = 0; + while i < count { + println!("Sending Message"); + ch.send(message + 0).unwrap(); + i = i + 1; + } + println!("Ending test00_start"); +} + +fn test00() { + let number_of_tasks: isize = 16; + let number_of_messages: isize = 4; + + println!("Creating tasks"); + + let (tx, rx) = channel(); + + let mut i: isize = 0; + + // Create and spawn threads... + let mut results = Vec::new(); + while i < number_of_tasks { + let tx = tx.clone(); + results.push(thread::spawn({ + let i = i; + move|| { + test00_start(&tx, i, number_of_messages) + } + })); + i = i + 1; + } + + // Read from spawned threads... + let mut sum = 0; + for _r in &results { + i = 0; + while i < number_of_messages { + let value = rx.recv().unwrap(); + sum += value; + i = i + 1; + } + } + + // Join spawned threads... + for r in results { r.join(); } + + println!("Completed: Final number is: "); + println!("{}", sum); + // assert (sum == (((number_of_threads * (number_of_threads - 1)) / 2) * + // number_of_messages)); + assert_eq!(sum, 480); +} diff --git a/tests/ui/threads-sendsync/task-comm-4.rs b/tests/ui/threads-sendsync/task-comm-4.rs new file mode 100644 index 000000000..b259d69d1 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-4.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(unused_assignments)] + +use std::sync::mpsc::channel; + +pub fn main() { test00(); } + +fn test00() { + let mut r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); + tx.send(3).unwrap(); + tx.send(4).unwrap(); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + tx.send(5).unwrap(); + tx.send(6).unwrap(); + tx.send(7).unwrap(); + tx.send(8).unwrap(); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); +} diff --git a/tests/ui/threads-sendsync/task-comm-5.rs b/tests/ui/threads-sendsync/task-comm-5.rs new file mode 100644 index 000000000..cdedf034a --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-5.rs @@ -0,0 +1,17 @@ +// run-pass + +use std::sync::mpsc::channel; + +pub fn main() { test00(); } + +fn test00() { + let _r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let number_of_messages: isize = 1000; + let mut i: isize = 0; + while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } + i = 0; + while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } + assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); +} diff --git a/tests/ui/threads-sendsync/task-comm-6.rs b/tests/ui/threads-sendsync/task-comm-6.rs new file mode 100644 index 000000000..990205ad3 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-6.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_assignments)] + +use std::sync::mpsc::channel; + +pub fn main() { test00(); } + +fn test00() { + let mut r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let mut tx0 = tx.clone(); + let mut tx1 = tx.clone(); + let mut tx2 = tx.clone(); + let mut tx3 = tx.clone(); + let number_of_messages: isize = 1000; + let mut i: isize = 0; + while i < number_of_messages { + tx0.send(i + 0).unwrap(); + tx1.send(i + 0).unwrap(); + tx2.send(i + 0).unwrap(); + tx3.send(i + 0).unwrap(); + i += 1; + } + i = 0; + while i < number_of_messages { + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + i += 1; + } + assert_eq!(sum, 1998000); + // assert (sum == 4 * ((number_of_messages * + // (number_of_messages - 1)) / 2)); + +} diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs new file mode 100644 index 000000000..0b9673e00 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-7.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_assignments)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +pub fn main() { test00(); } + +fn test00_start(c: &Sender, start: isize, + number_of_messages: isize) { + let mut i: isize = 0; + while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } +} + +fn test00() { + let mut r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let number_of_messages: isize = 10; + + let tx2 = tx.clone(); + let t1 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 0, number_of_messages); + }); + let tx2 = tx.clone(); + let t2 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 1, number_of_messages); + }); + let tx2 = tx.clone(); + let t3 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 2, number_of_messages); + }); + let tx2 = tx.clone(); + let t4 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 3, number_of_messages); + }); + + let mut i: isize = 0; + while i < number_of_messages { + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + i += 1; + } + + assert_eq!(sum, number_of_messages * 4 * (number_of_messages * 4 - 1) / 2); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs new file mode 100644 index 000000000..5ed330121 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-9.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { test00(); } + +fn test00_start(c: &Sender, number_of_messages: isize) { + let mut i: isize = 0; + while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } +} + +fn test00() { + let r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let number_of_messages: isize = 10; + + let result = thread::spawn(move|| { + test00_start(&tx, number_of_messages); + }); + + let mut i: isize = 0; + while i < number_of_messages { + sum += rx.recv().unwrap(); + println!("{}", r); + i += 1; + } + + result.join(); + + assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); +} diff --git a/tests/ui/threads-sendsync/task-comm-chan-nil.rs b/tests/ui/threads-sendsync/task-comm-chan-nil.rs new file mode 100644 index 000000000..a93ddff43 --- /dev/null +++ b/tests/ui/threads-sendsync/task-comm-chan-nil.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::sync::mpsc::channel; + +// rustboot can't transmit nils across channels because they don't have +// any size, but rustc currently can because they do have size. Whether +// or not this is desirable I don't know, but here's a regression test. +pub fn main() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + let n: () = rx.recv().unwrap(); + assert_eq!(n, ()); +} diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs new file mode 100644 index 000000000..785cff9a0 --- /dev/null +++ b/tests/ui/threads-sendsync/task-life-0.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +use std::thread; + +pub fn main() { + thread::spawn(move|| child("Hello".to_string()) ).join(); +} + +fn child(_s: String) { + +} diff --git a/tests/ui/threads-sendsync/task-spawn-barefn.rs b/tests/ui/threads-sendsync/task-spawn-barefn.rs new file mode 100644 index 000000000..e5b899e0a --- /dev/null +++ b/tests/ui/threads-sendsync/task-spawn-barefn.rs @@ -0,0 +1,18 @@ +// run-fail +// error-pattern:Ensure that the child thread runs by panicking +// ignore-emscripten Needs threads. + +use std::thread; + +fn main() { + // the purpose of this test is to make sure that thread::spawn() + // works when provided with a bare function: + let r = thread::spawn(startfn).join(); + if r.is_err() { + panic!() + } +} + +fn startfn() { + assert!("Ensure that the child thread runs by panicking".is_empty()); +} diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs new file mode 100644 index 000000000..a63903778 --- /dev/null +++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::channel; + +pub fn main() { + let (tx, rx) = channel::(); + + let x: Box = Box::new(1); + let x_in_parent = &(*x) as *const isize as usize; + + let t = thread::spawn(move || { + let x_in_child = &(*x) as *const isize as usize; + tx.send(x_in_child).unwrap(); + }); + + let x_in_child = rx.recv().unwrap(); + assert_eq!(x_in_parent, x_in_child); + + t.join(); +} diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs new file mode 100644 index 000000000..68d226ffb --- /dev/null +++ b/tests/ui/threads-sendsync/task-stderr.rs @@ -0,0 +1,26 @@ +// run-pass +// ignore-emscripten no threads support +// needs-unwind + +#![feature(internal_output_capture)] + +use std::io; +use std::str; +use std::sync::{Arc, Mutex}; +use std::thread; + +fn main() { + let data = Arc::new(Mutex::new(Vec::new())); + let res = thread::Builder::new().spawn({ + let data = data.clone(); + move || { + io::set_output_capture(Some(data)); + panic!("Hello, world!") + } + }).unwrap().join(); + assert!(res.is_err()); + + let output = data.lock().unwrap(); + let output = str::from_utf8(&output).unwrap(); + assert!(output.contains("Hello, world!")); +} diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs new file mode 100644 index 000000000..175663643 --- /dev/null +++ b/tests/ui/threads-sendsync/tcp-stress.rs @@ -0,0 +1,64 @@ +// run-pass +// ignore-android needs extra network permissions +// ignore-emscripten no threads or sockets support +// ignore-netbsd system ulimit (Too many open files) +// ignore-openbsd system ulimit (Too many open files) + +use std::io::prelude::*; +use std::net::{TcpListener, TcpStream}; +use std::process; +use std::sync::mpsc::channel; +use std::time::Duration; +use std::thread::{self, Builder}; + +const TARGET_CNT: usize = 200; + +fn main() { + // This test has a chance to time out, try to not let it time out + thread::spawn(move|| -> () { + thread::sleep(Duration::from_secs(30)); + process::exit(1); + }); + + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + thread::spawn(move || -> () { + loop { + let mut stream = match listener.accept() { + Ok(stream) => stream.0, + Err(_) => continue, + }; + let _ = stream.read(&mut [0]); + let _ = stream.write(&[2]); + } + }); + + let (tx, rx) = channel(); + + let mut spawned_cnt = 0; + for _ in 0..TARGET_CNT { + let tx = tx.clone(); + let res = Builder::new().stack_size(64 * 1024).spawn(move|| { + match TcpStream::connect(addr) { + Ok(mut stream) => { + let _ = stream.write(&[1]); + let _ = stream.read(&mut [0]); + }, + Err(..) => {} + } + tx.send(()).unwrap(); + }); + if let Ok(_) = res { + spawned_cnt += 1; + }; + } + + // Wait for all clients to exit, but don't wait for the server to exit. The + // server just runs infinitely. + drop(tx); + for _ in 0..spawned_cnt { + rx.recv().unwrap(); + } + assert_eq!(spawned_cnt, TARGET_CNT); + process::exit(0); +} diff --git a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs new file mode 100644 index 000000000..641142142 --- /dev/null +++ b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs @@ -0,0 +1,11 @@ +// This checks that RUST_TEST_THREADS not being 1, 2, ... is detected +// properly. + +// run-fail +// error-pattern:should be a positive integer +// compile-flags: --test +// exec-env:RUST_TEST_THREADS=foo +// ignore-emscripten + +#[test] +fn do_nothing() {} diff --git a/tests/ui/threads-sendsync/thread-local-extern-static.rs b/tests/ui/threads-sendsync/thread-local-extern-static.rs new file mode 100644 index 000000000..a2dda31aa --- /dev/null +++ b/tests/ui/threads-sendsync/thread-local-extern-static.rs @@ -0,0 +1,27 @@ +// run-pass +// ignore-windows +// aux-build:thread-local-extern-static.rs + +#![feature(cfg_target_thread_local, thread_local)] + +#[cfg(target_thread_local)] +extern crate thread_local_extern_static; + +#[cfg(target_thread_local)] +use std::cell::Cell; + +#[cfg(target_thread_local)] +extern "C" { + #[thread_local] + static FOO: Cell; +} + +#[cfg(target_thread_local)] +fn main() { + unsafe { + assert_eq!(FOO.get(), 3); + } +} + +#[cfg(not(target_thread_local))] +fn main() {} diff --git a/tests/ui/threads-sendsync/thread-local-syntax.rs b/tests/ui/threads-sendsync/thread-local-syntax.rs new file mode 100644 index 000000000..2f4805e47 --- /dev/null +++ b/tests/ui/threads-sendsync/thread-local-syntax.rs @@ -0,0 +1,22 @@ +// run-pass +#![deny(missing_docs)] +//! this tests the syntax of `thread_local!` + +mod foo { + mod bar { + thread_local! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; + } + thread_local!(static SPLOK: u32 = 0); + } +} + +fn main() {} diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs new file mode 100644 index 000000000..e3da83aa1 --- /dev/null +++ b/tests/ui/threads-sendsync/threads.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let mut i = 10; + while i > 0 { + thread::spawn({let i = i; move|| child(i)}).join(); + i = i - 1; + } + println!("main thread exiting"); +} + +fn child(x: isize) { println!("{}", x); } diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs new file mode 100644 index 000000000..8baef4334 --- /dev/null +++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -0,0 +1,22 @@ +// run-pass +// no-prefer-dynamic +// ignore-emscripten no threads support + +static mut HIT: bool = false; + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { HIT = true; } + } +} + +thread_local!(static FOO: Foo = Foo); + +fn main() { + std::thread::spawn(|| { + FOO.with(|_| {}); + }).join().unwrap(); + assert!(unsafe { HIT }); +} diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs new file mode 100644 index 000000000..193c18151 --- /dev/null +++ b/tests/ui/threads-sendsync/tls-init-on-init.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(stable_features)] + +// ignore-emscripten no threads support + +#![feature(thread_local_try_with)] + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +struct Foo { cnt: usize } + +thread_local!(static FOO: Foo = Foo::init()); + +static CNT: AtomicUsize = AtomicUsize::new(0); + +impl Foo { + fn init() -> Foo { + let cnt = CNT.fetch_add(1, Ordering::SeqCst); + if cnt == 0 { + FOO.with(|_| {}); + } + Foo { cnt: cnt } + } +} + +impl Drop for Foo { + fn drop(&mut self) { + if self.cnt == 1 { + FOO.with(|foo| assert_eq!(foo.cnt, 0)); + } else { + assert_eq!(self.cnt, 0); + if FOO.try_with(|_| ()).is_ok() { + panic!("should not be in valid state"); + } + } + } +} + +fn main() { + thread::spawn(|| { + FOO.with(|_| {}); + }).join().unwrap(); +} diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs new file mode 100644 index 000000000..f36ab4e4f --- /dev/null +++ b/tests/ui/threads-sendsync/tls-try-with.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(stable_features)] + +// ignore-emscripten no threads support + +#![feature(thread_local_try_with)] + +use std::thread; + +static mut DROP_RUN: bool = false; + +struct Foo; + +thread_local!(static FOO: Foo = Foo {}); + +impl Drop for Foo { + fn drop(&mut self) { + assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); + unsafe { DROP_RUN = true; } + } +} + +fn main() { + thread::spawn(|| { + assert_eq!(FOO.try_with(|_| { + 132 + }).expect("`try_with` failed"), 132); + }).join().unwrap(); + assert!(unsafe { DROP_RUN }); +} diff --git a/tests/ui/threads-sendsync/trivial-message.rs b/tests/ui/threads-sendsync/trivial-message.rs new file mode 100644 index 000000000..5831e867b --- /dev/null +++ b/tests/ui/threads-sendsync/trivial-message.rs @@ -0,0 +1,16 @@ +// run-pass + +#![allow(unused_must_use)] +/* + This is about the simplest program that can successfully send a + message. + */ + +use std::sync::mpsc::channel; + +pub fn main() { + let (tx, rx) = channel(); + tx.send(42); + let r = rx.recv(); + println!("{:?}", r); +} diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs new file mode 100644 index 000000000..6950a9c40 --- /dev/null +++ b/tests/ui/threads-sendsync/unwind-resource.rs @@ -0,0 +1,40 @@ +// run-pass +// needs-unwind + +#![allow(non_camel_case_types)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +struct complainer { + tx: Sender, +} + +impl Drop for complainer { + fn drop(&mut self) { + println!("About to send!"); + self.tx.send(true).unwrap(); + println!("Sent!"); + } +} + +fn complainer(tx: Sender) -> complainer { + println!("Hello!"); + complainer { + tx: tx + } +} + +fn f(tx: Sender) { + let _tx = complainer(tx); + panic!(); +} + +pub fn main() { + let (tx, rx) = channel(); + let t = thread::spawn(move|| f(tx.clone())); + println!("hiiiiiiiii"); + assert!(rx.recv().unwrap()); + drop(t.join()); +} diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs new file mode 100644 index 000000000..e83ba5560 --- /dev/null +++ b/tests/ui/threads-sendsync/yield.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let mut result = thread::spawn(child); + println!("1"); + thread::yield_now(); + println!("2"); + thread::yield_now(); + println!("3"); + result.join(); +} + +fn child() { + println!("4"); thread::yield_now(); println!("5"); thread::yield_now(); println!("6"); +} diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs new file mode 100644 index 000000000..002e59055 --- /dev/null +++ b/tests/ui/threads-sendsync/yield1.rs @@ -0,0 +1,16 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let mut result = thread::spawn(child); + println!("1"); + thread::yield_now(); + result.join(); +} + +fn child() { println!("2"); } diff --git a/tests/ui/threads-sendsync/yield2.rs b/tests/ui/threads-sendsync/yield2.rs new file mode 100644 index 000000000..376faab0c --- /dev/null +++ b/tests/ui/threads-sendsync/yield2.rs @@ -0,0 +1,8 @@ +// run-pass + +use std::thread; + +pub fn main() { + let mut i: isize = 0; + while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); } +} diff --git a/tests/ui/tool-attributes/diagnostic_item.rs b/tests/ui/tool-attributes/diagnostic_item.rs new file mode 100644 index 000000000..26a52ce60 --- /dev/null +++ b/tests/ui/tool-attributes/diagnostic_item.rs @@ -0,0 +1,3 @@ +#[rustc_diagnostic_item = "foomp"] //~ ERROR compiler internal support for linting +struct Foomp; +fn main() {} diff --git a/tests/ui/tool-attributes/diagnostic_item.stderr b/tests/ui/tool-attributes/diagnostic_item.stderr new file mode 100644 index 000000000..743e4b658 --- /dev/null +++ b/tests/ui/tool-attributes/diagnostic_item.stderr @@ -0,0 +1,11 @@ +error[E0658]: diagnostic items compiler internal support for linting + --> $DIR/diagnostic_item.rs:1:1 + | +LL | #[rustc_diagnostic_item = "foomp"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/tool-attributes/diagnostic_item2.rs b/tests/ui/tool-attributes/diagnostic_item2.rs new file mode 100644 index 000000000..b32a66b16 --- /dev/null +++ b/tests/ui/tool-attributes/diagnostic_item2.rs @@ -0,0 +1,6 @@ +// check-pass + +#[clippy::diagnostic_item = "mep"] +struct Mep; + +fn main() {} diff --git a/tests/ui/tool-attributes/diagnostic_item3.rs b/tests/ui/tool-attributes/diagnostic_item3.rs new file mode 100644 index 000000000..c1a236ed1 --- /dev/null +++ b/tests/ui/tool-attributes/diagnostic_item3.rs @@ -0,0 +1,7 @@ +// check-pass +#![feature(rustc_attrs)] + +#[rustc_diagnostic_item = "foomp"] +struct Foomp; + +fn main() {} diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-1.rs b/tests/ui/tool-attributes/tool-attributes-misplaced-1.rs new file mode 100644 index 000000000..bf45ba2ed --- /dev/null +++ b/tests/ui/tool-attributes/tool-attributes-misplaced-1.rs @@ -0,0 +1,18 @@ +type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt` +type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip` + +#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope + //~| ERROR cannot find derive macro `rustfmt` in this scope +struct S; + +// Interpreted as an unstable custom attribute +#[rustfmt] //~ ERROR cannot find attribute `rustfmt` in this scope +fn check() {} + +#[rustfmt::skip] // OK +fn main() { + rustfmt; //~ ERROR expected value, found tool module `rustfmt` + rustfmt!(); //~ ERROR cannot find macro `rustfmt` in this scope + + rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip` +} diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr new file mode 100644 index 000000000..71fd5f1d4 --- /dev/null +++ b/tests/ui/tool-attributes/tool-attributes-misplaced-1.stderr @@ -0,0 +1,52 @@ +error: cannot find derive macro `rustfmt` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:4:10 + | +LL | #[derive(rustfmt)] + | ^^^^^^^ + +error: cannot find derive macro `rustfmt` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:4:10 + | +LL | #[derive(rustfmt)] + | ^^^^^^^ + +error: cannot find attribute `rustfmt` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:9:3 + | +LL | #[rustfmt] + | ^^^^^^^ + +error: cannot find macro `rustfmt` in this scope + --> $DIR/tool-attributes-misplaced-1.rs:15:5 + | +LL | rustfmt!(); + | ^^^^^^^ + +error[E0573]: expected type, found tool module `rustfmt` + --> $DIR/tool-attributes-misplaced-1.rs:1:10 + | +LL | type A = rustfmt; + | ^^^^^^^ not a type + +error[E0573]: expected type, found tool attribute `rustfmt::skip` + --> $DIR/tool-attributes-misplaced-1.rs:2:10 + | +LL | type B = rustfmt::skip; + | ^^^^^^^^^^^^^ not a type + +error[E0423]: expected value, found tool module `rustfmt` + --> $DIR/tool-attributes-misplaced-1.rs:14:5 + | +LL | rustfmt; + | ^^^^^^^ not a value + +error[E0423]: expected value, found tool attribute `rustfmt::skip` + --> $DIR/tool-attributes-misplaced-1.rs:17:5 + | +LL | rustfmt::skip; + | ^^^^^^^^^^^^^ not a value + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0423, E0573. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-2.rs b/tests/ui/tool-attributes/tool-attributes-misplaced-2.rs new file mode 100644 index 000000000..b5666e4ea --- /dev/null +++ b/tests/ui/tool-attributes/tool-attributes-misplaced-2.rs @@ -0,0 +1,6 @@ +#[derive(rustfmt::skip)] //~ ERROR expected derive macro, found tool attribute `rustfmt::skip` +struct S; + +fn main() { + rustfmt::skip!(); //~ ERROR expected macro, found tool attribute `rustfmt::skip` +} diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr b/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr new file mode 100644 index 000000000..6d0f826e6 --- /dev/null +++ b/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr @@ -0,0 +1,14 @@ +error: expected derive macro, found tool attribute `rustfmt::skip` + --> $DIR/tool-attributes-misplaced-2.rs:1:10 + | +LL | #[derive(rustfmt::skip)] + | ^^^^^^^^^^^^^ not a derive macro + +error: expected macro, found tool attribute `rustfmt::skip` + --> $DIR/tool-attributes-misplaced-2.rs:5:5 + | +LL | rustfmt::skip!(); + | ^^^^^^^^^^^^^ not a macro + +error: aborting due to 2 previous errors + diff --git a/tests/ui/tool-attributes/tool-attributes-shadowing.rs b/tests/ui/tool-attributes/tool-attributes-shadowing.rs new file mode 100644 index 000000000..21bbaa3a7 --- /dev/null +++ b/tests/ui/tool-attributes/tool-attributes-shadowing.rs @@ -0,0 +1,4 @@ +mod rustfmt {} + +#[rustfmt::skip] //~ ERROR failed to resolve: could not find `skip` in `rustfmt` +fn main() {} diff --git a/tests/ui/tool-attributes/tool-attributes-shadowing.stderr b/tests/ui/tool-attributes/tool-attributes-shadowing.stderr new file mode 100644 index 000000000..98ad109a0 --- /dev/null +++ b/tests/ui/tool-attributes/tool-attributes-shadowing.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: could not find `skip` in `rustfmt` + --> $DIR/tool-attributes-shadowing.rs:3:12 + | +LL | #[rustfmt::skip] + | ^^^^ could not find `skip` in `rustfmt` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/tool_lints-fail.rs b/tests/ui/tool_lints-fail.rs new file mode 100644 index 000000000..5cbd63be5 --- /dev/null +++ b/tests/ui/tool_lints-fail.rs @@ -0,0 +1,8 @@ +// Don't allow tool_lints, which aren't scoped + + +#![deny(unknown_lints)] + +#![deny(clippy)] //~ ERROR: unknown lint: `clippy` + +fn main() {} diff --git a/tests/ui/tool_lints-fail.stderr b/tests/ui/tool_lints-fail.stderr new file mode 100644 index 000000000..16f678144 --- /dev/null +++ b/tests/ui/tool_lints-fail.stderr @@ -0,0 +1,14 @@ +error: unknown lint: `clippy` + --> $DIR/tool_lints-fail.rs:6:9 + | +LL | #![deny(clippy)] + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/tool_lints-fail.rs:4:9 + | +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/tool_lints-rpass.rs b/tests/ui/tool_lints-rpass.rs new file mode 100644 index 000000000..e467d3437 --- /dev/null +++ b/tests/ui/tool_lints-rpass.rs @@ -0,0 +1,6 @@ +// run-pass + +#![deny(unknown_lints)] + +#[allow(clippy::almost_swapped)] +fn main() {} diff --git a/tests/ui/tool_lints.rs b/tests/ui/tool_lints.rs new file mode 100644 index 000000000..ef27532f6 --- /dev/null +++ b/tests/ui/tool_lints.rs @@ -0,0 +1,4 @@ +#[warn(foo::bar)] +//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` +//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` +fn main() {} diff --git a/tests/ui/tool_lints.stderr b/tests/ui/tool_lints.stderr new file mode 100644 index 000000000..d36cd193b --- /dev/null +++ b/tests/ui/tool_lints.stderr @@ -0,0 +1,19 @@ +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/tool_lints.rs:1:8 + | +LL | #[warn(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/tool_lints.rs:1:8 + | +LL | #[warn(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/tool_lints_2018_preview.rs b/tests/ui/tool_lints_2018_preview.rs new file mode 100644 index 000000000..190f0b99d --- /dev/null +++ b/tests/ui/tool_lints_2018_preview.rs @@ -0,0 +1,7 @@ +// run-pass + +#![feature(rust_2018_preview)] +#![deny(unknown_lints)] + +#[allow(clippy::almost_swapped)] +fn main() {} diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs new file mode 100644 index 000000000..61b9137ea --- /dev/null +++ b/tests/ui/track-diagnostics/track.rs @@ -0,0 +1,11 @@ +// compile-flags: -Z track-diagnostics +// error-pattern: created at + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" +// normalize-stderr-test "note: rustc .+ running on .+" -> "note: rustc $$VERSION running on $$TARGET" + +fn main() { + break rust +} diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr new file mode 100644 index 000000000..8256c1f5f --- /dev/null +++ b/tests/ui/track-diagnostics/track.stderr @@ -0,0 +1,26 @@ +error[E0425]: cannot find value `rust` in this scope + --> $DIR/track.rs:LL:CC + | +LL | break rust + | ^^^^ not found in this scope +-Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/track.rs:LL:CC + | +LL | break rust + | ^^^^^^^^^^ cannot `break` outside of a loop or labeled block +-Ztrack-diagnostics: created at compiler/rustc_passes/src/loops.rs:LL:CC + +error: internal compiler error: It looks like you're trying to break rust; would you like some ICE? + +note: the compiler expectedly panicked. this is a feature. + +note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 + +note: rustc $VERSION running on $TARGET + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0268, E0425. +For more information about an error, try `rustc --explain E0268`. diff --git a/tests/ui/track-diagnostics/track2.rs b/tests/ui/track-diagnostics/track2.rs new file mode 100644 index 000000000..dc105c61d --- /dev/null +++ b/tests/ui/track-diagnostics/track2.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z track-diagnostics +// error-pattern: created at + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" + +fn main() { + let _moved @ _from = String::from("foo"); +} diff --git a/tests/ui/track-diagnostics/track2.stderr b/tests/ui/track-diagnostics/track2.stderr new file mode 100644 index 000000000..fe13e5ef3 --- /dev/null +++ b/tests/ui/track-diagnostics/track2.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of moved value + --> $DIR/track2.rs:LL:CC + | +LL | let _moved @ _from = String::from("foo"); + | ^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait + | | | + | | value moved here + | value used here after move +-Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/track-diagnostics/track3.rs b/tests/ui/track-diagnostics/track3.rs new file mode 100644 index 000000000..069923950 --- /dev/null +++ b/tests/ui/track-diagnostics/track3.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z track-diagnostics +// error-pattern: created at + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" + +fn main() { + let _unimported = Blah { field: u8 }; +} diff --git a/tests/ui/track-diagnostics/track3.stderr b/tests/ui/track-diagnostics/track3.stderr new file mode 100644 index 000000000..dc468d7e8 --- /dev/null +++ b/tests/ui/track-diagnostics/track3.stderr @@ -0,0 +1,18 @@ +error[E0422]: cannot find struct, variant or union type `Blah` in this scope + --> $DIR/track3.rs:LL:CC + | +LL | let _unimported = Blah { field: u8 }; + | ^^^^ not found in this scope +-Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC + +error[E0423]: expected value, found builtin type `u8` + --> $DIR/track3.rs:LL:CC + | +LL | let _unimported = Blah { field: u8 }; + | ^^ not a value +-Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0422, E0423. +For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/track-diagnostics/track4.rs b/tests/ui/track-diagnostics/track4.rs new file mode 100644 index 000000000..35eec799b --- /dev/null +++ b/tests/ui/track-diagnostics/track4.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z track-diagnostics +// error-pattern: created at + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" + +pub onion { + Owo(u8), + Uwu(i8), +} + +fn main() {} diff --git a/tests/ui/track-diagnostics/track4.stderr b/tests/ui/track-diagnostics/track4.stderr new file mode 100644 index 000000000..c4668444c --- /dev/null +++ b/tests/ui/track-diagnostics/track4.stderr @@ -0,0 +1,14 @@ +error: missing `struct` for struct definition + --> $DIR/track4.rs:LL:CC + | +LL | pub onion { + | ^ +-Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/diagnostics.rs:LL:CC + | +help: add `struct` here to parse `onion` as a public struct + | +LL | pub struct onion { + | ++++++ + +error: aborting due to previous error + diff --git a/tests/ui/track-diagnostics/track5.rs b/tests/ui/track-diagnostics/track5.rs new file mode 100644 index 000000000..c41d9424e --- /dev/null +++ b/tests/ui/track-diagnostics/track5.rs @@ -0,0 +1,8 @@ +// compile-flags: -Z track-diagnostics +// error-pattern: created at + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +// normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" + +} diff --git a/tests/ui/track-diagnostics/track5.stderr b/tests/ui/track-diagnostics/track5.stderr new file mode 100644 index 000000000..aa54f92b6 --- /dev/null +++ b/tests/ui/track-diagnostics/track5.stderr @@ -0,0 +1,9 @@ +error: unexpected closing delimiter: `}` + --> $DIR/track5.rs:LL:CC + | +LL | } + | ^ unexpected closing delimiter +-Ztrack-diagnostics: created at compiler/rustc_parse/src/lexer/tokentrees.rs:LL:CC + +error: aborting due to previous error + diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs new file mode 100644 index 000000000..307e31018 --- /dev/null +++ b/tests/ui/track-diagnostics/track6.rs @@ -0,0 +1,14 @@ +// compile-flags: -Z track-diagnostics +// error-pattern: created at + + + +pub trait Foo { + fn bar(); +} + +impl Foo for T { + default fn bar() {} +} + +fn main() {} diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr new file mode 100644 index 000000000..1c7537633 --- /dev/null +++ b/tests/ui/track-diagnostics/track6.stderr @@ -0,0 +1,13 @@ +error[E0658]: specialization is unstable + --> $DIR/track6.rs:11:5 + | +LL | default fn bar() {} + | ^^^^^^^^^^^^^^^^^^^ +-Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:93:5 + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/trailing-comma.rs b/tests/ui/trailing-comma.rs new file mode 100644 index 000000000..90adba99e --- /dev/null +++ b/tests/ui/trailing-comma.rs @@ -0,0 +1,35 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f(_: T,) {} + +struct Foo(#[allow(unused_tuple_struct_fields)] T); + +struct Bar; + +impl Bar { + fn f(_: isize,) {} + fn g(self, _: isize,) {} + fn h(self,) {} +} + +enum Baz { + Qux(#[allow(unused_tuple_struct_fields)] isize,), +} + +#[allow(unused,)] +pub fn main() { + f::(0,); + let (_, _,) = (1, 1,); + let [_, _,] = [1, 1,]; + let [_, _, .., _,] = [1, 1, 1, 1,]; + let [_, _, _, ..,] = [1, 1, 1, 1,]; + + let x: Foo = Foo::(1); + + Bar::f(0,); + Bar.g(0,); + Bar.h(); + + let x = Baz::Qux(1,); +} diff --git a/tests/ui/trait-bounds/impl-bound-with-references-error.rs b/tests/ui/trait-bounds/impl-bound-with-references-error.rs new file mode 100644 index 000000000..e5d0a1aae --- /dev/null +++ b/tests/ui/trait-bounds/impl-bound-with-references-error.rs @@ -0,0 +1,20 @@ +// Regression test for #105138. +// This test ensures that the compiler does not add note +// for implementation of trait whose inner type is erroneous. + +pub enum LabelText { + Plain, +} + +impl From for LabelText +//~^ ERROR conflicting implementations of trait `From` for type `LabelText` [E0119] +where + T: Into>, + //~^ ERROR cannot find type `Cow` in this scope [E0412] +{ + fn from(text: T) -> Self { + LabelText::Plain(text.into()) + } +} + +fn main() {} diff --git a/tests/ui/trait-bounds/impl-bound-with-references-error.stderr b/tests/ui/trait-bounds/impl-bound-with-references-error.stderr new file mode 100644 index 000000000..95fd6bd50 --- /dev/null +++ b/tests/ui/trait-bounds/impl-bound-with-references-error.stderr @@ -0,0 +1,24 @@ +error[E0412]: cannot find type `Cow` in this scope + --> $DIR/impl-bound-with-references-error.rs:12:13 + | +LL | T: Into>, + | ^^^ not found in this scope + | +help: consider importing this enum + | +LL | use std::borrow::Cow; + | + +error[E0119]: conflicting implementations of trait `From` for type `LabelText` + --> $DIR/impl-bound-with-references-error.rs:9:1 + | +LL | impl From for LabelText + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl From for T; + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0412. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs new file mode 100644 index 000000000..557d89088 --- /dev/null +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.rs @@ -0,0 +1,33 @@ +struct Victim<'a, T: Perpetrator + ?Sized> { + value: u8, + perp: &'a T, +} + +trait VictimTrait { + type Ret; + fn get(self) -> Self::Ret; +} + +// Actual fix is here +impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { + type Ret = u8; + fn get(self) -> Self::Ret { + self.value + } +} + +trait Perpetrator { + fn getter<'a>(&'a self) -> Victim<'a, Self> { + Victim { + value: 0, + perp: self, + } + } + + fn trigger(&self) { + self.getter().get(); + //~^ ERROR the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied + } +} + +fn main() {} diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr new file mode 100644 index 000000000..543ceac8e --- /dev/null +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound-2.stderr @@ -0,0 +1,31 @@ +error[E0599]: the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied + --> $DIR/impl-derived-implicit-sized-bound-2.rs:28:19 + | +LL | struct Victim<'a, T: Perpetrator + ?Sized> { + | ------------------------------------------ + | | + | method `get` not found for this struct + | doesn't satisfy `Victim<'_, Self>: VictimTrait` +... +LL | self.getter().get(); + | ^^^ method cannot be called on `Victim<'_, Self>` due to unsatisfied trait bounds + | +note: trait bound `Self: Sized` was not satisfied + --> $DIR/impl-derived-implicit-sized-bound-2.rs:12:10 + | +LL | impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { + | ^ ----------- ------------- + | | + | unsatisfied trait bound introduced here +help: consider relaxing the type parameter's implicit `Sized` bound + | +LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { + | ++++++++ +help: consider restricting the type parameter to satisfy the trait bound + | +LL | struct Victim<'a, T: Perpetrator + ?Sized> where Self: Sized { + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs new file mode 100644 index 000000000..28da41a0c --- /dev/null +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.rs @@ -0,0 +1,36 @@ +struct Victim<'a, T: Perpetrator + ?Sized> +where + Self: Sized +{ + value: u8, + perp: &'a T, +} + +trait VictimTrait { + type Ret; + fn get(self) -> Self::Ret; +} + +// Actual fix is here +impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { + type Ret = u8; + fn get(self) -> Self::Ret { + self.value + } +} + +trait Perpetrator { + fn getter<'a>(&'a self) -> Victim<'a, Self> { + Victim { + value: 0, + perp: self, + } + } + + fn trigger(&self) { + self.getter().get(); + //~^ ERROR the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied + } +} + +fn main() {} diff --git a/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr new file mode 100644 index 000000000..f08d68583 --- /dev/null +++ b/tests/ui/trait-bounds/impl-derived-implicit-sized-bound.stderr @@ -0,0 +1,31 @@ +error[E0599]: the method `get` exists for struct `Victim<'_, Self>`, but its trait bounds were not satisfied + --> $DIR/impl-derived-implicit-sized-bound.rs:31:19 + | +LL | struct Victim<'a, T: Perpetrator + ?Sized> + | ------------------------------------------ + | | + | method `get` not found for this struct + | doesn't satisfy `Victim<'_, Self>: VictimTrait` +... +LL | self.getter().get(); + | ^^^ method cannot be called on `Victim<'_, Self>` due to unsatisfied trait bounds + | +note: trait bound `Self: Sized` was not satisfied + --> $DIR/impl-derived-implicit-sized-bound.rs:15:10 + | +LL | impl<'a, T: Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { + | ^ ----------- ------------- + | | + | unsatisfied trait bound introduced here +help: consider relaxing the type parameter's implicit `Sized` bound + | +LL | impl<'a, T: ?Sized + Perpetrator /*+ ?Sized*/> VictimTrait for Victim<'a, T> { + | ++++++++ +help: consider restricting the type parameter to satisfy the trait bound + | +LL | Self: Sized, Self: Sized + | +++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs new file mode 100644 index 000000000..dcdbd0228 --- /dev/null +++ b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs @@ -0,0 +1,38 @@ +trait Trait { + fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a; +} + +impl Trait<()> for () { + fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195 + todo!(); + } +} + +struct State; + +trait Foo { + fn foo<'a>(&self, state: &'a State) -> &'a T + where + T: 'a; +} + +impl Foo for F +where + F: Fn(&State) -> &T, +{ + fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195 + self(state) + } +} + +trait Bar { + fn foo<'a>(&'a self) {} +} + +impl Bar for () { + fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195 +} + +fn main() { + ().foo((), ()); +} diff --git a/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr new file mode 100644 index 000000000..e26cb2216 --- /dev/null +++ b/tests/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr @@ -0,0 +1,36 @@ +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11 + | +LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a; + | ------- -- -- this bound might be missing in the impl + | | | + | | this bound might be missing in the impl + | lifetimes in impl do not match this method in trait +... +LL | fn foo<'a, K>(self, _: (), _: K) where { + | ^^^^^^^ lifetimes do not match method in trait + +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11 + | +LL | fn foo<'a>(&self, state: &'a State) -> &'a T + | ---- lifetimes in impl do not match this method in trait +LL | where +LL | T: 'a; + | -- this bound might be missing in the impl +... +LL | fn foo<'a>(&self, state: &'a State) -> &'a T { + | ^^^^ lifetimes do not match method in trait + +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11 + | +LL | fn foo<'a>(&'a self) {} + | ---- lifetimes in impl do not match this method in trait +... +LL | fn foo<'a: 'a>(&'a self) {} + | ^^^^^^^^ lifetimes do not match method in trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/trait-bounds/issue-75961.rs b/tests/ui/trait-bounds/issue-75961.rs new file mode 100644 index 000000000..367eac718 --- /dev/null +++ b/tests/ui/trait-bounds/issue-75961.rs @@ -0,0 +1,7 @@ +// check-pass + +pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { + <&mut () as Clone>::clone(&s); +} + +fn main() {} diff --git a/tests/ui/trait-bounds/issue-93008.rs b/tests/ui/trait-bounds/issue-93008.rs new file mode 100644 index 000000000..f4d21a160 --- /dev/null +++ b/tests/ui/trait-bounds/issue-93008.rs @@ -0,0 +1,15 @@ +// build-pass +// compile-flags: -Zmir-opt-level=3 --crate-type=lib + +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +trait Foo { + fn test(self); +} +fn baz() +where + &'static str: Foo, +{ + "Foo".test() +} diff --git a/tests/ui/trait-bounds/issue-94680.rs b/tests/ui/trait-bounds/issue-94680.rs new file mode 100644 index 000000000..58e892079 --- /dev/null +++ b/tests/ui/trait-bounds/issue-94680.rs @@ -0,0 +1,14 @@ +// check-pass + +fn main() { + println!("{:?}", { + type T = (); + + pub fn cloneit(it: &'_ mut T) -> (&'_ mut T, &'_ mut T) + where + for<'any> &'any mut T: Clone, + { + (it.clone(), it) + } + }); +} diff --git a/tests/ui/trait-bounds/issue-94999.rs b/tests/ui/trait-bounds/issue-94999.rs new file mode 100644 index 000000000..e13190234 --- /dev/null +++ b/tests/ui/trait-bounds/issue-94999.rs @@ -0,0 +1,34 @@ +// check-pass + +trait Identity { + type T; +} + +impl Identity for T { + type T = T; +} + +trait Holds { + type Q; +} + +struct S; +struct X(S); + +struct XHelper; + +impl Holds for X { + type Q = XHelper; +} + +impl Clone for X +where + >::T: Clone, + X: Holds, +{ + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +fn main() {} diff --git a/tests/ui/trait-bounds/issue-95640.rs b/tests/ui/trait-bounds/issue-95640.rs new file mode 100644 index 000000000..e4e998b5d --- /dev/null +++ b/tests/ui/trait-bounds/issue-95640.rs @@ -0,0 +1,31 @@ +// build-pass +// compile-flags:-Zmir-opt-level=3 + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { + None + } +} + +fn run(f: F) +where + for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.rs b/tests/ui/trait-bounds/mismatch-fn-trait.rs new file mode 100644 index 000000000..0ed64043a --- /dev/null +++ b/tests/ui/trait-bounds/mismatch-fn-trait.rs @@ -0,0 +1,28 @@ +fn take(_f: impl FnMut(i32)) {} + +fn test1(f: impl FnMut(u32)) { + take(f) + //~^ ERROR [E0277] +} + +fn test2(f: impl FnMut(i32, i32)) { + take(f) + //~^ ERROR [E0277] +} + +fn test3(f: impl FnMut()) { + take(f) + //~^ ERROR [E0277] +} + +fn test4(f: impl FnOnce(i32)) { + take(f) + //~^ ERROR [E0277] +} + +fn test5(f: impl FnOnce(u32)) { + take(f) + //~^ ERROR [E0277] +} + +fn main() {} diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr new file mode 100644 index 000000000..961e6d88f --- /dev/null +++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr @@ -0,0 +1,81 @@ +error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut(u32)` + --> $DIR/mismatch-fn-trait.rs:4:10 + | +LL | take(f) + | ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut(u32)` + | | + | required by a bound introduced by this call + | + = note: expected a closure with arguments `(u32,)` + found a closure with arguments `(i32,)` +note: required by a bound in `take` + --> $DIR/mismatch-fn-trait.rs:1:18 + | +LL | fn take(_f: impl FnMut(i32)) {} + | ^^^^^^^^^^ required by this bound in `take` + +error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut(i32, i32)` + --> $DIR/mismatch-fn-trait.rs:9:10 + | +LL | take(f) + | ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut(i32, i32)` + | | + | required by a bound introduced by this call + | + = note: expected a closure taking 2 arguments, but one taking 1 argument was given +note: required by a bound in `take` + --> $DIR/mismatch-fn-trait.rs:1:18 + | +LL | fn take(_f: impl FnMut(i32)) {} + | ^^^^^^^^^^ required by this bound in `take` + +error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut()` + --> $DIR/mismatch-fn-trait.rs:14:10 + | +LL | take(f) + | ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut()` + | | + | required by a bound introduced by this call + | + = note: expected a closure taking 0 arguments, but one taking 1 argument was given +note: required by a bound in `take` + --> $DIR/mismatch-fn-trait.rs:1:18 + | +LL | fn take(_f: impl FnMut(i32)) {} + | ^^^^^^^^^^ required by this bound in `take` + +error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnOnce(i32)` + --> $DIR/mismatch-fn-trait.rs:19:10 + | +LL | take(f) + | ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnOnce(i32)` + | | + | required by a bound introduced by this call + | + = note: `impl FnOnce(i32)` implements `FnOnce`, but it must implement `FnMut`, which is more general +note: required by a bound in `take` + --> $DIR/mismatch-fn-trait.rs:1:18 + | +LL | fn take(_f: impl FnMut(i32)) {} + | ^^^^^^^^^^ required by this bound in `take` + +error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnOnce(u32)` + --> $DIR/mismatch-fn-trait.rs:24:10 + | +LL | take(f) + | ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnOnce(u32)` + | | + | required by a bound introduced by this call + | + = note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general + = note: expected a closure with arguments `(u32,)` + found a closure with arguments `(i32,)` +note: required by a bound in `take` + --> $DIR/mismatch-fn-trait.rs:1:18 + | +LL | fn take(_f: impl FnMut(i32)) {} + | ^^^^^^^^^^ required by this bound in `take` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed new file mode 100644 index 000000000..39e90d7a3 --- /dev/null +++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![allow(non_snake_case)] +mod A { + pub trait Trait {} + impl Trait for i32 {} +} + +mod B { + use A::Trait; + +pub struct A(pub H); //~ ERROR cannot find trait +} + +fn main() { + let _ = B::A(42); +} diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs new file mode 100644 index 000000000..ee6ed0cae --- /dev/null +++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(non_snake_case)] +mod A { + pub trait Trait {} + impl Trait for i32 {} +} + +mod B { + pub struct A(pub H); //~ ERROR cannot find trait +} + +fn main() { + let _ = B::A(42); +} diff --git a/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr new file mode 100644 index 000000000..b29766295 --- /dev/null +++ b/tests/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr @@ -0,0 +1,19 @@ +error[E0405]: cannot find trait `Trait` in `A` + --> $DIR/shadowed-path-in-trait-bound-suggestion.rs:9:24 + | +LL | pub struct A(pub H); + | ^^^^^ not found in `A` + | +help: consider importing this trait + | +LL | use A::Trait; + | +help: if you import `Trait`, refer to it directly + | +LL - pub struct A(pub H); +LL + pub struct A(pub H); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/trait-bounds/unsized-bound.rs b/tests/ui/trait-bounds/unsized-bound.rs new file mode 100644 index 000000000..035b8ef1b --- /dev/null +++ b/tests/ui/trait-bounds/unsized-bound.rs @@ -0,0 +1,32 @@ +trait Trait {} +impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} +//~^ ERROR E0277 +//~| ERROR E0277 +impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +//~^ ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 +trait Trait2 {} +impl Trait2<(A, B)> for (A, B) {} +//~^ ERROR E0277 +//~| ERROR E0277 +trait Trait3 {} +impl Trait3 for A where A: ?Sized {} +//~^ ERROR E0277 +trait Trait4 {} +impl Trait4 for A {} +//~^ ERROR E0277 +trait Trait5 {} +impl Trait5 for X where X: ?Sized {} +//~^ ERROR E0277 +trait Trait6 {} +impl Trait6 for X {} +//~^ ERROR E0277 +trait Trait7 {} +impl Trait7 for X where Y: ?Sized {} +//~^ ERROR E0277 +trait Trait8 {} +impl Trait8 for X {} +//~^ ERROR E0277 + +fn main() {} diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr new file mode 100644 index 000000000..da27ba1c5 --- /dev/null +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -0,0 +1,273 @@ +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:2:30 + | +LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: required because it appears within the type `(A, B)` +note: required by a bound in `Trait` + --> $DIR/unsized-bound.rs:1:13 + | +LL | trait Trait {} + | ^ required by this bound in `Trait` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} +LL + impl Trait<(A, B)> for (A, B) where A: ?Sized, {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:2:30 + | +LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} +LL + impl Trait<(A, B)> for (A, B) where B: ?Sized, {} + | + +error[E0277]: the size for values of type `C` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:52 + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: required because it appears within the type `(A, B, C)` +note: required by a bound in `Trait` + --> $DIR/unsized-bound.rs:1:13 + | +LL | trait Trait {} + | ^ required by this bound in `Trait` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +LL + impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:52 + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +LL + impl Trait<(A, B, C)> for (A, B, C) {} + | + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:5:52 + | +LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | - ^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} +LL + impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} + | + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/unsized-bound.rs:10:47 + | +LL | impl Trait2<(A, B)> for (A, B) {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: required because it appears within the type `(A, B)` +note: required by a bound in `Trait2` + --> $DIR/unsized-bound.rs:9:14 + | +LL | trait Trait2 {} + | ^ required by this bound in `Trait2` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait2<(A, B)> for (A, B) {} +LL + impl Trait2<(A, B)> for (A, B) {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait2 {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:10:47 + | +LL | impl Trait2<(A, B)> for (A, B) {} + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait2<(A, B)> for (A, B) {} +LL + impl Trait2<(A, B)> for (A, B) {} + | + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:14:23 + | +LL | impl Trait3 for A where A: ?Sized {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Trait3` + --> $DIR/unsized-bound.rs:13:14 + | +LL | trait Trait3 {} + | ^ required by this bound in `Trait3` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait3 for A where A: ?Sized {} +LL + impl Trait3 for A {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait3 {} + | ++++++++ + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/unsized-bound.rs:17:31 + | +LL | impl Trait4 for A {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Trait4` + --> $DIR/unsized-bound.rs:16:14 + | +LL | trait Trait4 {} + | ^ required by this bound in `Trait4` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait4 for A {} +LL + impl Trait4 for A {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait4 {} + | ++++++++ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-bound.rs:20:29 + | +LL | impl Trait5 for X where X: ?Sized {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Trait5` + --> $DIR/unsized-bound.rs:19:14 + | +LL | trait Trait5 {} + | ^ required by this bound in `Trait5` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait5 for X where X: ?Sized {} +LL + impl Trait5 for X {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait5 {} + | ++++++++ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-bound.rs:23:37 + | +LL | impl Trait6 for X {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Trait6` + --> $DIR/unsized-bound.rs:22:14 + | +LL | trait Trait6 {} + | ^ required by this bound in `Trait6` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait6 for X {} +LL + impl Trait6 for X {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait6 {} + | ++++++++ + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized-bound.rs:26:12 + | +LL | impl Trait7 for X where Y: ?Sized {} + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Trait7` + --> $DIR/unsized-bound.rs:25:17 + | +LL | trait Trait7 {} + | ^ required by this bound in `Trait7` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait7 for X where Y: ?Sized {} +LL + impl Trait7 for X {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait7 {} + | ++++++++ + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized-bound.rs:29:20 + | +LL | impl Trait8 for X {} + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Trait8` + --> $DIR/unsized-bound.rs:28:17 + | +LL | trait Trait8 {} + | ^ required by this bound in `Trait8` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl Trait8 for X {} +LL + impl Trait8 for X {} + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait Trait8 {} + | ++++++++ + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-impl-bound-suggestions.fixed b/tests/ui/trait-impl-bound-suggestions.fixed new file mode 100644 index 000000000..744e7bef0 --- /dev/null +++ b/tests/ui/trait-impl-bound-suggestions.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +#[allow(unused)] +use std::fmt::Debug; +// Rustfix should add this, or use `std::fmt::Debug` instead. + +#[allow(dead_code)] +struct ConstrainedStruct { + x: X +} + +#[allow(dead_code)] +trait InsufficientlyConstrainedGeneric where X: std::marker::Copy { + fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct { + //~^ ERROR the trait bound `X: Copy` is not satisfied + ConstrainedStruct { x } + } +} + +pub fn main() { } diff --git a/tests/ui/trait-impl-bound-suggestions.rs b/tests/ui/trait-impl-bound-suggestions.rs new file mode 100644 index 000000000..bf7517517 --- /dev/null +++ b/tests/ui/trait-impl-bound-suggestions.rs @@ -0,0 +1,20 @@ +// run-rustfix + +#[allow(unused)] +use std::fmt::Debug; +// Rustfix should add this, or use `std::fmt::Debug` instead. + +#[allow(dead_code)] +struct ConstrainedStruct { + x: X +} + +#[allow(dead_code)] +trait InsufficientlyConstrainedGeneric { + fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct { + //~^ ERROR the trait bound `X: Copy` is not satisfied + ConstrainedStruct { x } + } +} + +pub fn main() { } diff --git a/tests/ui/trait-impl-bound-suggestions.stderr b/tests/ui/trait-impl-bound-suggestions.stderr new file mode 100644 index 000000000..38679679c --- /dev/null +++ b/tests/ui/trait-impl-bound-suggestions.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `X: Copy` is not satisfied + --> $DIR/trait-impl-bound-suggestions.rs:14:52 + | +LL | fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct { + | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X` + | +note: required by a bound in `ConstrainedStruct` + --> $DIR/trait-impl-bound-suggestions.rs:8:29 + | +LL | struct ConstrainedStruct { + | ^^^^ required by this bound in `ConstrainedStruct` +help: consider further restricting type parameter `X` + | +LL | trait InsufficientlyConstrainedGeneric where X: std::marker::Copy { + | ++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trait-method-number-parameters.rs b/tests/ui/trait-method-number-parameters.rs new file mode 100644 index 000000000..719005d66 --- /dev/null +++ b/tests/ui/trait-method-number-parameters.rs @@ -0,0 +1,13 @@ +trait Foo { + fn foo(&mut self, x: i32, y: i32) -> i32; +} + +impl Foo for i32 { + fn foo( + &mut self, //~ ERROR + x: i32, + ) { + } +} + +fn main() {} diff --git a/tests/ui/trait-method-number-parameters.stderr b/tests/ui/trait-method-number-parameters.stderr new file mode 100644 index 000000000..e47fe1a80 --- /dev/null +++ b/tests/ui/trait-method-number-parameters.stderr @@ -0,0 +1,13 @@ +error[E0050]: method `foo` has 2 parameters but the declaration in trait `Foo::foo` has 3 + --> $DIR/trait-method-number-parameters.rs:7:9 + | +LL | fn foo(&mut self, x: i32, y: i32) -> i32; + | ------------------------- trait requires 3 parameters +... +LL | / &mut self, +LL | | x: i32, + | |______________^ expected 3 parameters, found 2 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/traits/alias/ambiguous.rs b/tests/ui/traits/alias/ambiguous.rs new file mode 100644 index 000000000..28409e0c6 --- /dev/null +++ b/tests/ui/traits/alias/ambiguous.rs @@ -0,0 +1,24 @@ +#![feature(trait_alias)] + +mod inner { + pub trait A { fn foo(&self); } + pub trait B { fn foo(&self); } + + impl A for u8 { + fn foo(&self) {} + } + impl B for u8 { + fn foo(&self) {} + } + + pub trait C = A + B; +} + +use inner::C; + +fn main() { + let t = 1u8; + t.foo(); //~ ERROR E0034 + + inner::A::foo(&t); // ok +} diff --git a/tests/ui/traits/alias/ambiguous.stderr b/tests/ui/traits/alias/ambiguous.stderr new file mode 100644 index 000000000..0fe1a7967 --- /dev/null +++ b/tests/ui/traits/alias/ambiguous.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/ambiguous.rs:21:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `A` for the type `u8` + --> $DIR/ambiguous.rs:8:9 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `B` for the type `u8` + --> $DIR/ambiguous.rs:11:9 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +help: disambiguate the associated function for candidate #1 + | +LL | A::foo(&t); + | ~~~~~~~~~~ +help: disambiguate the associated function for candidate #2 + | +LL | B::foo(&t); + | ~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/traits/alias/auxiliary/greeter.rs b/tests/ui/traits/alias/auxiliary/greeter.rs new file mode 100644 index 000000000..9e4122155 --- /dev/null +++ b/tests/ui/traits/alias/auxiliary/greeter.rs @@ -0,0 +1,13 @@ +#![feature(trait_alias)] + +pub trait Hello { + fn hello(&self); +} + +pub struct Hi; + +impl Hello for Hi { + fn hello(&self) {} +} + +pub trait Greet = Hello; diff --git a/tests/ui/traits/alias/auxiliary/send_sync.rs b/tests/ui/traits/alias/auxiliary/send_sync.rs new file mode 100644 index 000000000..9e56b87e0 --- /dev/null +++ b/tests/ui/traits/alias/auxiliary/send_sync.rs @@ -0,0 +1,3 @@ +#![feature(trait_alias)] + +pub trait SendSync = Send + Sync; diff --git a/tests/ui/traits/alias/basic.rs b/tests/ui/traits/alias/basic.rs new file mode 100644 index 000000000..d8168f299 --- /dev/null +++ b/tests/ui/traits/alias/basic.rs @@ -0,0 +1,8 @@ +// run-pass + +#![feature(trait_alias)] + +pub trait Foo {} +pub trait FooAlias = Foo; + +fn main() {} diff --git a/tests/ui/traits/alias/bounds.rs b/tests/ui/traits/alias/bounds.rs new file mode 100644 index 000000000..b97eb38c5 --- /dev/null +++ b/tests/ui/traits/alias/bounds.rs @@ -0,0 +1,57 @@ +// run-pass + +#![feature(trait_alias)] + +use std::marker::PhantomData; + +trait Empty {} +trait EmptyAlias = Empty; +trait CloneDefault = Clone + Default; +trait SendSyncAlias = Send + Sync; +trait WhereSendAlias = where Self: Send; +trait SendEqAlias = Send where T: PartialEq; +trait I32Iterator = Iterator; + +#[allow(dead_code)] +struct Foo(PhantomData); +#[allow(dead_code)] +struct Bar(PhantomData) where T: SendSyncAlias; + +impl dyn EmptyAlias {} + +impl Empty for T {} + +fn a() -> (T, T) { + let one = T::default(); + let two = one.clone(); + (one, two) +} + +fn b(x: &impl SendEqAlias) -> bool { + 22_i32 == *x +} + +fn c(x: &mut T) -> Option { + x.next() +} + +fn d() { + is_send_and_sync::(); +} + +fn is_send_and_sync() {} + +fn main() { + let both = a::(); + assert_eq!(both.0, 0); + assert_eq!(both.1, 0); + let both: (i32, i32) = a(); + assert_eq!(both.0, 0); + assert_eq!(both.1, 0); + + assert!(b(&22)); + + assert_eq!(c(&mut vec![22].into_iter()), Some(22)); + + d::(); +} diff --git a/tests/ui/traits/alias/cross-crate.rs b/tests/ui/traits/alias/cross-crate.rs new file mode 100644 index 000000000..8919c6434 --- /dev/null +++ b/tests/ui/traits/alias/cross-crate.rs @@ -0,0 +1,17 @@ +// aux-build:send_sync.rs + +#![feature(trait_alias)] + +extern crate send_sync; + +use std::rc::Rc; +use send_sync::SendSync; + +fn use_alias() {} + +fn main() { + use_alias::(); + use_alias::>(); + //~^ ERROR `Rc` cannot be sent between threads safely [E0277] + //~^^ ERROR `Rc` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr new file mode 100644 index 000000000..ae9d7d0a9 --- /dev/null +++ b/tests/ui/traits/alias/cross-crate.stderr @@ -0,0 +1,31 @@ +error[E0277]: `Rc` cannot be sent between threads safely + --> $DIR/cross-crate.rs:14:17 + | +LL | use_alias::>(); + | ^^^^^^^ `Rc` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `Rc` + = note: required for `Rc` to implement `SendSync` +note: required by a bound in `use_alias` + --> $DIR/cross-crate.rs:10:17 + | +LL | fn use_alias() {} + | ^^^^^^^^ required by this bound in `use_alias` + +error[E0277]: `Rc` cannot be shared between threads safely + --> $DIR/cross-crate.rs:14:17 + | +LL | use_alias::>(); + | ^^^^^^^ `Rc` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Rc` + = note: required for `Rc` to implement `SendSync` +note: required by a bound in `use_alias` + --> $DIR/cross-crate.rs:10:17 + | +LL | fn use_alias() {} + | ^^^^^^^^ required by this bound in `use_alias` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/generic-default-in-dyn.rs b/tests/ui/traits/alias/generic-default-in-dyn.rs new file mode 100644 index 000000000..d44e1c2a9 --- /dev/null +++ b/tests/ui/traits/alias/generic-default-in-dyn.rs @@ -0,0 +1,10 @@ +trait SendEqAlias = PartialEq; +//~^ ERROR trait aliases are experimental + +struct Foo(dyn SendEqAlias); +//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] + +struct Bar(dyn SendEqAlias, T); +//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] + +fn main() {} diff --git a/tests/ui/traits/alias/generic-default-in-dyn.stderr b/tests/ui/traits/alias/generic-default-in-dyn.stderr new file mode 100644 index 000000000..0d3f794aa --- /dev/null +++ b/tests/ui/traits/alias/generic-default-in-dyn.stderr @@ -0,0 +1,35 @@ +error[E0658]: trait aliases are experimental + --> $DIR/generic-default-in-dyn.rs:1:1 + | +LL | trait SendEqAlias = PartialEq; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #41517 for more information + = help: add `#![feature(trait_alias)]` to the crate attributes to enable + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/generic-default-in-dyn.rs:4:19 + | +LL | struct Foo(dyn SendEqAlias); + | ^^^^^^^^^^^^^^ missing reference to `Rhs` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: type parameter `Rhs` must be specified for this + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/generic-default-in-dyn.rs:7:19 + | +LL | struct Bar(dyn SendEqAlias, T); + | ^^^^^^^^^^^^^^ missing reference to `Rhs` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: type parameter `Rhs` must be specified for this + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0393, E0658. +For more information about an error, try `rustc --explain E0393`. diff --git a/tests/ui/traits/alias/impl.rs b/tests/ui/traits/alias/impl.rs new file mode 100644 index 000000000..6e35793a0 --- /dev/null +++ b/tests/ui/traits/alias/impl.rs @@ -0,0 +1,7 @@ +#![feature(trait_alias)] + +trait DefaultAlias = Default; + +impl DefaultAlias for () {} //~ ERROR expected trait, found trait alias + +fn main() {} diff --git a/tests/ui/traits/alias/impl.stderr b/tests/ui/traits/alias/impl.stderr new file mode 100644 index 000000000..cedcd1021 --- /dev/null +++ b/tests/ui/traits/alias/impl.stderr @@ -0,0 +1,9 @@ +error[E0404]: expected trait, found trait alias `DefaultAlias` + --> $DIR/impl.rs:5:6 + | +LL | impl DefaultAlias for () {} + | ^^^^^^^^^^^^ not a trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/alias/import-cross-crate.rs b/tests/ui/traits/alias/import-cross-crate.rs new file mode 100644 index 000000000..868585cd0 --- /dev/null +++ b/tests/ui/traits/alias/import-cross-crate.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:greeter.rs + +#![feature(trait_alias)] + +extern crate greeter; + +// Import only the alias, not the real trait. +use greeter::{Greet, Hi}; + +fn main() { + let hi = Hi; + hi.hello(); // From `Hello`, via `Greet` alias. +} diff --git a/tests/ui/traits/alias/import.rs b/tests/ui/traits/alias/import.rs new file mode 100644 index 000000000..802a8f156 --- /dev/null +++ b/tests/ui/traits/alias/import.rs @@ -0,0 +1,40 @@ +// run-pass + +#![feature(trait_alias)] + +mod inner { + pub trait Foo { + fn foo(&self); + } + + pub struct Qux; + + impl Foo for Qux { + fn foo(&self) {} + } + + pub trait Bar = Foo; +} + +mod two { + pub trait A { + fn foo(); + } + + impl A for u8 { + fn foo() {} + } +} + +// Import only the alias, not the `Foo` trait. +use inner::{Bar, Qux}; + +// Declaring an alias also brings in aliased methods. +trait Two = two::A; + +fn main() { + let q = Qux; + q.foo(); // From Bar. + + u8::foo(); // From A. +} diff --git a/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs b/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs new file mode 100644 index 000000000..5e27ed3c6 --- /dev/null +++ b/tests/ui/traits/alias/issue-60021-assoc-method-resolve.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(trait_alias)] + +trait SomeTrait { + fn map(&self) {} +} + +impl SomeTrait for Option {} + +trait SomeAlias = SomeTrait; + +fn main() { + let x = Some(123); + // This should resolve to the trait impl for Option + Option::map(x, |z| z); + // This should resolve to the trait impl for SomeTrait + SomeTrait::map(&x); +} diff --git a/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs b/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs new file mode 100644 index 000000000..e49125d10 --- /dev/null +++ b/tests/ui/traits/alias/issue-72415-assoc-const-resolve.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(trait_alias)] + +trait Bounded { const MAX: Self; } + +impl Bounded for u32 { + // This should correctly resolve to the associated const in the inherent impl of u32. + const MAX: Self = u32::MAX; +} + +trait Num = Bounded + Copy; + +fn main() {} diff --git a/tests/ui/traits/alias/issue-75983.rs b/tests/ui/traits/alias/issue-75983.rs new file mode 100644 index 000000000..f9a7f36de --- /dev/null +++ b/tests/ui/traits/alias/issue-75983.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(trait_alias)] + +struct Bar; +trait Foo {} +impl Foo for Bar {} + +trait Baz = Foo where Bar: Foo; + +fn new() -> impl Baz { + Bar +} + +fn main() { + let _ = new(); +} diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs new file mode 100644 index 000000000..2462e703a --- /dev/null +++ b/tests/ui/traits/alias/issue-83613.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] +trait OpaqueTrait {} +impl OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + || 0 +} +trait AnotherTrait {} +impl AnotherTrait for T {} +impl AnotherTrait for OpaqueType {} +//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +fn main() {} diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr new file mode 100644 index 000000000..a78294da6 --- /dev/null +++ b/tests/ui/traits/alias/issue-83613.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + --> $DIR/issue-83613.rs:10:1 + | +LL | impl AnotherTrait for T {} + | -------------------------------- first implementation here +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/alias/maybe-bound.rs b/tests/ui/traits/alias/maybe-bound.rs new file mode 100644 index 000000000..284baa481 --- /dev/null +++ b/tests/ui/traits/alias/maybe-bound.rs @@ -0,0 +1,29 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. + +#![feature(trait_alias)] + +trait Foo {} + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1 + Foo; + +// In second position: +type _T1 = dyn Foo + _1; + +// ... and with an auto trait: +type _T2 = dyn Foo + Send + _1; + +// Twice: +trait _2 = _1 + _1; + +type _T3 = dyn _2 + Foo; + +fn main() {} diff --git a/tests/ui/traits/alias/no-duplicates.rs b/tests/ui/traits/alias/no-duplicates.rs new file mode 100644 index 000000000..88feb8917 --- /dev/null +++ b/tests/ui/traits/alias/no-duplicates.rs @@ -0,0 +1,126 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto traits is rejected with trait aliases even though one could +// reasonably accept this. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitrary object-safe trait: +trait Obj {} + +// Nest a few levels deep: +trait _0 = Obj; +trait _1 = _0; + +type _T00 = dyn _0 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn _1 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn _1 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn Obj + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T04 = dyn _1 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = _0 + _1; +trait _3 = Obj; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn Obj + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _2 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T14 = dyn _1 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T15 = dyn _3 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T16 = dyn _1 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T17 = dyn _4 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Obj + Send; + +type _T20 = dyn _5 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn Obj + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn _5 + Send + Sync + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _7 = _5 + Sync; +trait _8 = Unpin + _7; + +type _T40 = dyn _8 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn Obj + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _8 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn _4 + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn _4 + Send + Sync + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +trait _9 = for<'a> ObjL<'a>; +trait _10 = for<'b> ObjL<'b>; +type _T50 = dyn _9 + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT {} +trait _11 = ObjT fn(&'a u8)>; +trait _12 = ObjT fn(&'b u8)>; +type _T60 = dyn _11 + _12; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/tests/ui/traits/alias/no-duplicates.stderr b/tests/ui/traits/alias/no-duplicates.stderr new file mode 100644 index 000000000..bf244b97e --- /dev/null +++ b/tests/ui/traits/alias/no-duplicates.stderr @@ -0,0 +1,527 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:16:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T00 = dyn _0 + _0; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:19:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | type _T01 = dyn _1 + _0; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:22:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T02 = dyn _1 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:25:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | type _T03 = dyn Obj + _1; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:28:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | type _T04 = dyn _1 + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:37:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _2 = _0 + _1; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T10 = dyn _2 + _3; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:40:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here (additional use) +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T11 = dyn _3 + _2; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:43:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here (additional use) +... +LL | type _T12 = dyn Obj + _2; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:46:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _2 = _0 + _1; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T13 = dyn _2 + Obj; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:49:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _3 = Obj; + | --- additional non-auto trait +... +LL | type _T14 = dyn _1 + _3; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:52:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T15 = dyn _3 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:55:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here (additional use) +... +LL | type _T16 = dyn _1 + _4; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:58:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _3 = Obj; + | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | type _T17 = dyn _4 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:65:22 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | +LL | type _T20 = dyn _5 + _5; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:68:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | type _T21 = dyn Obj + _5; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:71:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T22 = dyn _5 + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:74:36 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T23 = dyn _5 + Send + Sync + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:81:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | +LL | type _T30 = dyn _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:84:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T31 = dyn _6 + Send; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:87:24 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T32 = dyn Send + _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:95:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +LL | +LL | type _T40 = dyn _8 + Obj; + | -- ^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:98:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- referenced here (additional use) +... +LL | type _T41 = dyn Obj + _8; + | --- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:101:22 + | +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here (additional use) +... +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +... +LL | type _T42 = dyn _8 + _4; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:104:22 + | +LL | trait _3 = Obj; + | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- referenced here (additional use) +... +LL | type _T43 = dyn _4 + _8; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:107:36 + | +LL | trait _3 = Obj; + | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _8 = Unpin + _7; + | -- referenced here (additional use) +... +LL | type _T44 = dyn _4 + Send + Sync + _8; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:117:22 + | +LL | trait _9 = for<'a> ObjL<'a>; + | ---------------- first non-auto trait +LL | trait _10 = for<'b> ObjL<'b>; + | ---------------- additional non-auto trait +LL | type _T50 = dyn _9 + _10; + | -- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:123:23 + | +LL | trait _11 = ObjT fn(&'a u8)>; + | ------------------------ first non-auto trait +LL | trait _12 = ObjT fn(&'b u8)>; + | ------------------------ additional non-auto trait +LL | type _T60 = dyn _11 + _12; + | --- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/alias/no-extra-traits.rs b/tests/ui/traits/alias/no-extra-traits.rs new file mode 100644 index 000000000..4dad8c0f8 --- /dev/null +++ b/tests/ui/traits/alias/no-extra-traits.rs @@ -0,0 +1,121 @@ +// The purpose of this test is to demonstrate that trait alias expansion +// preserves the rule that `dyn Trait` may only reference one non-auto trait. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitrary object-safe traits: +trait ObjA {} +trait ObjB {} + +// Nest a few levels deep: +trait _0 = ObjA; +trait _1 = _0; + +type _T00 = dyn _0 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn ObjB + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn ObjB + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn _1 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = ObjB; +trait _3 = _2; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn _2 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _4 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Sync + ObjB + Send; + +type _T20 = dyn _5 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn _1 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T24 = dyn Send + _5 + _1 + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T25 = dyn _1 + Sync + _5 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T26 = dyn Sync + Send + _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T27 = dyn Send + Sync + ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _1 + _5; +trait _7 = _6; +trait _8 = _7; + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T33 = dyn _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T34 = dyn _8 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T35 = dyn Send + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _9 = _5 + Sync; +trait _10 = Unpin + _9; + +type _T40 = dyn _10 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn ObjA + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn Send + _10 + Sync + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn ObjA + _10 + Send + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T45 = dyn Sync + Send + _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/tests/ui/traits/alias/no-extra-traits.stderr b/tests/ui/traits/alias/no-extra-traits.stderr new file mode 100644 index 000000000..4b1ddf684 --- /dev/null +++ b/tests/ui/traits/alias/no-extra-traits.stderr @@ -0,0 +1,579 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:16:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | type _T00 = dyn _0 + ObjB; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:19:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +... +LL | type _T01 = dyn ObjB + _0; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:22:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | type _T02 = dyn ObjB + _1; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:25:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | type _T03 = dyn _1 + ObjB; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:34:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (additional use) +... +LL | type _T10 = dyn _2 + _3; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:37:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) +... +LL | type _T11 = dyn _3 + _2; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:40:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (additional use) +LL | trait _4 = _3; + | -- referenced here (additional use) +... +LL | type _T12 = dyn _2 + _4; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:43:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) +LL | trait _4 = _3; + | -- referenced here (first use) +... +LL | type _T13 = dyn _4 + _2; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:50:22 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +LL | +LL | type _T20 = dyn _5 + _1; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:53:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T21 = dyn _1 + _5; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:56:22 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T22 = dyn _5 + ObjA; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:59:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T23 = dyn ObjA + _5; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:62:29 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T24 = dyn Send + _5 + _1 + Sync; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:65:29 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T25 = dyn _1 + Sync + _5 + Send; + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:68:36 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T26 = dyn Sync + Send + _5 + ObjA; + | -- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:71:38 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T27 = dyn Send + Sync + ObjA + _5; + | ---- ^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:80:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T30 = dyn _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:83:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T31 = dyn _6 + Send; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:86:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +... +LL | type _T32 = dyn Send + _6; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:89:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T33 = dyn _8; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:92:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T34 = dyn _8 + Send; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:95:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- -- referenced here (additional use) + | | + | referenced here (first use) +LL | trait _7 = _6; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +LL | trait _8 = _7; + | -- + | | + | referenced here (additional use) + | referenced here (first use) +... +LL | type _T35 = dyn Send + _8; + | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:103:23 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +LL | +LL | type _T40 = dyn _10 + ObjA; + | --- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:106:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _10 = Unpin + _9; + | -- referenced here (additional use) +... +LL | type _T41 = dyn ObjA + _10; + | ---- ^^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:109:23 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... +LL | type _T42 = dyn _10 + _1; + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:112:37 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... +LL | type _T43 = dyn Send + _10 + Sync + ObjA; + | --- ^^^^ additional non-auto trait + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:115:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (additional use) +LL | trait _10 = Unpin + _9; + | -- referenced here (additional use) +... +LL | type _T44 = dyn ObjA + _10 + Send + Sync; + | ---- ^^^ trait alias used in trait object type (additional use) + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-extra-traits.rs:118:37 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here (additional use) +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... +LL | type _T45 = dyn Sync + Send + _10 + _1; + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error: aborting due to 28 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/alias/object-fail.rs b/tests/ui/traits/alias/object-fail.rs new file mode 100644 index 000000000..5c753ff20 --- /dev/null +++ b/tests/ui/traits/alias/object-fail.rs @@ -0,0 +1,11 @@ +#![feature(trait_alias)] + +trait EqAlias = Eq; +trait IteratorAlias = Iterator; + +fn main() { + let _: &dyn EqAlias = &123; + //~^ ERROR the trait `Eq` cannot be made into an object [E0038] + let _: &dyn IteratorAlias = &vec![123].into_iter(); + //~^ ERROR must be specified +} diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr new file mode 100644 index 000000000..048a150df --- /dev/null +++ b/tests/ui/traits/alias/object-fail.stderr @@ -0,0 +1,21 @@ +error[E0038]: the trait `Eq` cannot be made into an object + --> $DIR/object-fail.rs:7:13 + | +LL | let _: &dyn EqAlias = &123; + | ^^^^^^^^^^^ `Eq` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + +error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified + --> $DIR/object-fail.rs:9:17 + | +LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); + | ^^^^^^^^^^^^^ help: specify the associated type: `IteratorAlias` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0191. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/object-wf.rs b/tests/ui/traits/alias/object-wf.rs new file mode 100644 index 000000000..1440f02df --- /dev/null +++ b/tests/ui/traits/alias/object-wf.rs @@ -0,0 +1,85 @@ +// check-pass + +// This test checks that trait objects involving trait aliases are well-formed. + +#![feature(trait_alias)] + +trait Obj {} + +trait _0 = Send + Sync; + +// Just auto traits: + +trait _1 = _0 + Send + Sync; + +use std::marker::Unpin; + +fn _f0() { + let _: Box; + let _: Box; + let _: Box; +} + +// Include object safe traits: + +fn _f1() { + let _: Box; + let _: Box; + let _: Box; +} + +// And when the object safe trait is in a trait alias: + +trait _2 = Obj; + +fn _f2() { + let _: Box; + let _: Box; + let _: Box; +} + +// And it should also work when that trait is has auto traits to the right of it. + +trait _3 = Obj + Unpin; + +fn _f3() { + let _: Box; + let _: Box; + let _: Box; +} + +// Nest the trait deeply: + +trait _4 = _3; +trait _5 = _4 + Sync + _0 + Send; +trait _6 = _5 + Send + _1 + Sync; + +fn _f4() { + let _: Box; + let _: Box; + let _: Box; +} + +// Just nest the trait alone: + +trait _7 = _2; +trait _8 = _7; +trait _9 = _8; + +fn _f5() { + let _: Box; +} + +// First bound is auto trait: + +trait _10 = Send + Obj; +trait _11 = Obj + Send; +trait _12 = Sync + _11; +trait _13 = Send + _12; + +fn f6() { + let _: Box; + let _: Box; +} + +fn main() {} diff --git a/tests/ui/traits/alias/object.rs b/tests/ui/traits/alias/object.rs new file mode 100644 index 000000000..12177cd82 --- /dev/null +++ b/tests/ui/traits/alias/object.rs @@ -0,0 +1,18 @@ +// run-pass + +#![feature(trait_alias)] + +trait Foo = PartialEq + Send; +trait Bar = Foo + Sync; + +trait I32Iterator = Iterator; + +pub fn main() { + let a: &dyn Bar = &123; + assert!(*a == 123); + let b = Box::new(456) as Box; + assert!(*b == 456); + + let c: &mut dyn I32Iterator = &mut vec![123].into_iter(); + assert_eq!(c.next(), Some(123)); +} diff --git a/tests/ui/traits/alias/only-maybe-bound.rs b/tests/ui/traits/alias/only-maybe-bound.rs new file mode 100644 index 000000000..e4abf314e --- /dev/null +++ b/tests/ui/traits/alias/only-maybe-bound.rs @@ -0,0 +1,22 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just +// `?Sized` results from trait alias expansion. + +#![feature(trait_alias)] + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1; +//~^ ERROR at least one trait is required for an object type [E0224] + +// Twice: +trait _2 = _1 + _1; + +type _T1 = dyn _2; +//~^ ERROR at least one trait is required for an object type [E0224] + +fn main() {} diff --git a/tests/ui/traits/alias/only-maybe-bound.stderr b/tests/ui/traits/alias/only-maybe-bound.stderr new file mode 100644 index 000000000..175ec8120 --- /dev/null +++ b/tests/ui/traits/alias/only-maybe-bound.stderr @@ -0,0 +1,21 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/only-maybe-bound.rs:13:12 + | +LL | trait _1 = _0; + | -------- this alias does not contain a trait +... +LL | type _T0 = dyn _1; + | ^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/only-maybe-bound.rs:19:12 + | +LL | trait _2 = _1 + _1; + | -------- this alias does not contain a trait +LL | +LL | type _T1 = dyn _2; + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/alias/self-in-const-generics.rs b/tests/ui/traits/alias/self-in-const-generics.rs new file mode 100644 index 000000000..b0de8ccd6 --- /dev/null +++ b/tests/ui/traits/alias/self-in-const-generics.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(trait_alias)] + +trait Bar {} + +trait BB = Bar<{ 2 + 1 }>; + +fn foo(x: &dyn BB) {} +//~^ ERROR the trait alias `BB` cannot be made into an object [E0038] + +fn main() {} diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr new file mode 100644 index 000000000..61cc217cf --- /dev/null +++ b/tests/ui/traits/alias/self-in-const-generics.stderr @@ -0,0 +1,11 @@ +error[E0038]: the trait alias `BB` cannot be made into an object + --> $DIR/self-in-const-generics.rs:9:16 + | +LL | fn foo(x: &dyn BB) {} + | ^^ + | + = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/self-in-generics.rs b/tests/ui/traits/alias/self-in-generics.rs new file mode 100644 index 000000000..0bb6335f9 --- /dev/null +++ b/tests/ui/traits/alias/self-in-generics.rs @@ -0,0 +1,15 @@ +// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects. +// This `FreshTy(0)` can leak into substs, causing ICEs in several places. +// Using `save-analysis` triggers type-checking `f` that would be normally skipped +// as `type_of` emitted an error. +// +// compile-flags: -Zsave-analysis + +#![feature(trait_alias)] + +pub trait SelfInput = Fn(&mut Self); + +pub fn f(_f: &dyn SelfInput) {} +//~^ ERROR the trait alias `SelfInput` cannot be made into an object [E0038] + +fn main() {} diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr new file mode 100644 index 000000000..110d60e6e --- /dev/null +++ b/tests/ui/traits/alias/self-in-generics.stderr @@ -0,0 +1,11 @@ +error[E0038]: the trait alias `SelfInput` cannot be made into an object + --> $DIR/self-in-generics.rs:12:19 + | +LL | pub fn f(_f: &dyn SelfInput) {} + | ^^^^^^^^^ + | + = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/style_lint.rs b/tests/ui/traits/alias/style_lint.rs new file mode 100644 index 000000000..33be20054 --- /dev/null +++ b/tests/ui/traits/alias/style_lint.rs @@ -0,0 +1,8 @@ +// check-pass + +#![feature(trait_alias)] + +trait Foo = std::fmt::Display + std::fmt::Debug; +trait bar = std::fmt::Display + std::fmt::Debug; //~WARN trait alias `bar` should have an upper camel case name + +fn main() {} diff --git a/tests/ui/traits/alias/style_lint.stderr b/tests/ui/traits/alias/style_lint.stderr new file mode 100644 index 000000000..91e2ea90e --- /dev/null +++ b/tests/ui/traits/alias/style_lint.stderr @@ -0,0 +1,10 @@ +warning: trait alias `bar` should have an upper camel case name + --> $DIR/style_lint.rs:6:7 + | +LL | trait bar = std::fmt::Display + std::fmt::Debug; + | ^^^ help: convert the identifier to upper camel case: `Bar` + | + = note: `#[warn(non_camel_case_types)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed new file mode 100644 index 000000000..8a94abaeb --- /dev/null +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +trait Strings = Iterator; + +struct Struct(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs new file mode 100644 index 000000000..40c678c28 --- /dev/null +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.rs @@ -0,0 +1,13 @@ +// Regression test of #43913. + +// run-rustfix + +#![feature(trait_alias)] +#![allow(bare_trait_objects, dead_code)] + +type Strings = Iterator; + +struct Struct(S); +//~^ ERROR: expected trait, found type alias `Strings` + +fn main() {} diff --git a/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr new file mode 100644 index 000000000..6e03eeada --- /dev/null +++ b/tests/ui/traits/alias/suggest-trait-alias-instead-of-type.stderr @@ -0,0 +1,14 @@ +error[E0404]: expected trait, found type alias `Strings` + --> $DIR/suggest-trait-alias-instead-of-type.rs:10:18 + | +LL | struct Struct(S); + | ^^^^^^^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait Strings = Iterator; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/alias/syntax-fail.rs b/tests/ui/traits/alias/syntax-fail.rs new file mode 100644 index 000000000..039bbce8c --- /dev/null +++ b/tests/ui/traits/alias/syntax-fail.rs @@ -0,0 +1,10 @@ +#![feature(trait_alias)] + +trait Foo {} +auto trait A = Foo; //~ ERROR trait aliases cannot be `auto` +unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe` + +trait C: Ord = Eq; //~ ERROR bounds are not allowed on trait aliases +trait D: = Eq; //~ ERROR bounds are not allowed on trait aliases + +fn main() {} diff --git a/tests/ui/traits/alias/syntax-fail.stderr b/tests/ui/traits/alias/syntax-fail.stderr new file mode 100644 index 000000000..748b92056 --- /dev/null +++ b/tests/ui/traits/alias/syntax-fail.stderr @@ -0,0 +1,26 @@ +error: trait aliases cannot be `auto` + --> $DIR/syntax-fail.rs:4:1 + | +LL | auto trait A = Foo; + | ^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto` + +error: trait aliases cannot be `unsafe` + --> $DIR/syntax-fail.rs:5:1 + | +LL | unsafe trait B = Foo; + | ^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe` + +error: bounds are not allowed on trait aliases + --> $DIR/syntax-fail.rs:7:8 + | +LL | trait C: Ord = Eq; + | ^^^^^ + +error: bounds are not allowed on trait aliases + --> $DIR/syntax-fail.rs:8:8 + | +LL | trait D: = Eq; + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/alias/syntax.rs b/tests/ui/traits/alias/syntax.rs new file mode 100644 index 000000000..17557a51a --- /dev/null +++ b/tests/ui/traits/alias/syntax.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(trait_alias)] + +trait SimpleAlias = Default; +trait GenericAlias = Iterator; +trait Partial = IntoIterator; +trait SpecificAlias = GenericAlias; +trait PartialEqRef<'a, T: 'a> = PartialEq<&'a T>; +trait StaticAlias = 'static; + +trait Things {} +trait Romeo {} +#[allow(dead_code)] +struct The(T); +#[allow(dead_code)] +struct Fore(T); +impl Things for The {} +impl Romeo for Fore {} + +trait WithWhere = Romeo + Romeo where Fore<(Art, Thou)>: Romeo; +trait BareWhere = where The: Things; + +fn main() {} diff --git a/tests/ui/traits/alias/wf.rs b/tests/ui/traits/alias/wf.rs new file mode 100644 index 000000000..d10e2abb0 --- /dev/null +++ b/tests/ui/traits/alias/wf.rs @@ -0,0 +1,7 @@ +#![feature(trait_alias)] + +trait Foo {} +trait A {} +trait B = A; //~ ERROR `T: Foo` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr new file mode 100644 index 000000000..7172008d3 --- /dev/null +++ b/tests/ui/traits/alias/wf.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Foo` is not satisfied + --> $DIR/wf.rs:5:14 + | +LL | trait B = A; + | ^^^^ the trait `Foo` is not implemented for `T` + | +note: required by a bound in `A` + --> $DIR/wf.rs:4:12 + | +LL | trait A {} + | ^^^ required by this bound in `A` +help: consider restricting type parameter `T` + | +LL | trait B = A; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alignment-gep-tup-like-1.rs b/tests/ui/traits/alignment-gep-tup-like-1.rs new file mode 100644 index 000000000..eb503dcf3 --- /dev/null +++ b/tests/ui/traits/alignment-gep-tup-like-1.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + +struct pair { + a: A, b: B +} + +trait Invokable { + fn f(&self) -> (A, u16); +} + +struct Invoker { + a: A, + b: u16, +} + +impl Invokable for Invoker { + fn f(&self) -> (A, u16) { + (self.a.clone(), self.b) + } +} + +fn f(a: A, b: u16) -> Box+'static> { + Box::new(Invoker { + a: a, + b: b, + }) as Box+'static> +} + +pub fn main() { + let (a, b) = f(22_u64, 44u16).f(); + println!("a={} b={}", a, b); + assert_eq!(a, 22u64); + assert_eq!(b, 44u16); +} diff --git a/tests/ui/traits/anon-static-method.rs b/tests/ui/traits/anon-static-method.rs new file mode 100644 index 000000000..ede01afae --- /dev/null +++ b/tests/ui/traits/anon-static-method.rs @@ -0,0 +1,15 @@ +// run-pass +struct Foo { + x: isize +} + +impl Foo { + pub fn new() -> Foo { + Foo { x: 3 } + } +} + +pub fn main() { + let x = Foo::new(); + println!("{}", x.x); +} diff --git a/tests/ui/traits/anon_trait_static_method_exe.rs b/tests/ui/traits/anon_trait_static_method_exe.rs new file mode 100644 index 000000000..b49302954 --- /dev/null +++ b/tests/ui/traits/anon_trait_static_method_exe.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(non_camel_case_types)] + +// aux-build:anon_trait_static_method_lib.rs + +extern crate anon_trait_static_method_lib; +use anon_trait_static_method_lib::Foo; + +pub fn main() { + let x = Foo::new(); + println!("{}", x.x); +} diff --git a/tests/ui/traits/as-struct-constructor.rs b/tests/ui/traits/as-struct-constructor.rs new file mode 100644 index 000000000..13ebf9d8d --- /dev/null +++ b/tests/ui/traits/as-struct-constructor.rs @@ -0,0 +1,6 @@ +trait TraitNotAStruct {} + +fn main() { + TraitNotAStruct{ value: 0 }; + //~^ ERROR expected struct, variant or union type, found trait `TraitNotAStruct` +} diff --git a/tests/ui/traits/as-struct-constructor.stderr b/tests/ui/traits/as-struct-constructor.stderr new file mode 100644 index 000000000..d06e85f3a --- /dev/null +++ b/tests/ui/traits/as-struct-constructor.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found trait `TraitNotAStruct` + --> $DIR/as-struct-constructor.rs:4:5 + | +LL | TraitNotAStruct{ value: 0 }; + | ^^^^^^^^^^^^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/traits/assignability-trait.rs b/tests/ui/traits/assignability-trait.rs new file mode 100644 index 000000000..a8547c1d2 --- /dev/null +++ b/tests/ui/traits/assignability-trait.rs @@ -0,0 +1,47 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Tests that type assignability is used to search for instances when +// making method calls, but only if there aren't any matches without +// it. + +trait iterable { + fn iterate(&self, blk: F) -> bool where F: FnMut(&A) -> bool; +} + +impl<'a,A> iterable for &'a [A] { + fn iterate(&self, f: F) -> bool where F: FnMut(&A) -> bool { + self.iter().all(f) + } +} + +impl iterable for Vec { + fn iterate(&self, f: F) -> bool where F: FnMut(&A) -> bool { + self.iter().all(f) + } +} + +fn length>(x: T) -> usize { + let mut len = 0; + x.iterate(|_y| { + len += 1; + true + }); + return len; +} + +pub fn main() { + let x: Vec = vec![0,1,2,3]; + // Call a method + x.iterate(|y| { assert_eq!(x[*y as usize], *y); true }); + // Call a parameterized function + assert_eq!(length(x.clone()), x.len()); + // Call a parameterized function, with type arguments that require + // a borrow + assert_eq!(length::(&*x), x.len()); + + // Now try it with a type that *needs* to be borrowed + let z = [0,1,2,3]; + // Call a parameterized function + assert_eq!(length::(&z), z.len()); +} diff --git a/tests/ui/traits/assoc-type-in-superbad.rs b/tests/ui/traits/assoc-type-in-superbad.rs new file mode 100644 index 000000000..65340b2a2 --- /dev/null +++ b/tests/ui/traits/assoc-type-in-superbad.rs @@ -0,0 +1,16 @@ +// Test case where an associated type is referenced from within the +// supertrait definition, and the impl makes the wrong +// associations. Issue #20220. + +use std::vec::IntoIter; + +pub trait Foo: Iterator::Key> { + type Key; +} + +impl Foo for IntoIter { + type Key = u32; + //~^ ERROR expected `IntoIter` to be an iterator that yields `u32`, but it yields `i32` +} + +fn main() {} diff --git a/tests/ui/traits/assoc-type-in-superbad.stderr b/tests/ui/traits/assoc-type-in-superbad.stderr new file mode 100644 index 000000000..7fa1d2c2e --- /dev/null +++ b/tests/ui/traits/assoc-type-in-superbad.stderr @@ -0,0 +1,15 @@ +error[E0271]: expected `IntoIter` to be an iterator that yields `u32`, but it yields `i32` + --> $DIR/assoc-type-in-superbad.rs:12:16 + | +LL | type Key = u32; + | ^^^ expected `u32`, found `i32` + | +note: required by a bound in `Foo` + --> $DIR/assoc-type-in-superbad.rs:7:25 + | +LL | pub trait Foo: Iterator::Key> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/assoc-type-in-supertrait.rs b/tests/ui/traits/assoc-type-in-supertrait.rs new file mode 100644 index 000000000..7d6a754cc --- /dev/null +++ b/tests/ui/traits/assoc-type-in-supertrait.rs @@ -0,0 +1,23 @@ +// run-pass +// Test case where an associated type is referenced from within the +// supertrait definition. Issue #20220. + + +use std::vec::IntoIter; + +pub trait Foo: Iterator::Key> { + type Key; +} + +impl Foo for IntoIter { + type Key = i32; +} + +fn sum_foo>(f: F) -> i32 { + f.fold(0, |a,b| a + b) +} + +fn main() { + let x = sum_foo(vec![11, 10, 1].into_iter()); + assert_eq!(x, 22); +} diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs new file mode 100644 index 000000000..471a6b836 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs @@ -0,0 +1,23 @@ +trait Bar { + type Baz; +} + +struct Foo where T: Bar, ::Baz: String { //~ ERROR expected trait, found struct + t: T, +} + +struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found struct + t: &'a T, +} + +fn foo(_: T) where ::Baz: String { //~ ERROR expected trait, found struct +} + +fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found +} + +fn issue_95327() where ::Assoc: String {} +//~^ ERROR expected trait, found struct +//~| ERROR use of undeclared type `Unresolved` + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr new file mode 100644 index 000000000..5be334986 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr @@ -0,0 +1,91 @@ +error[E0433]: failed to resolve: use of undeclared type `Unresolved` + --> $DIR/assoc_type_bound_with_struct.rs:19:31 + | +LL | fn issue_95327() where ::Assoc: String {} + | ^^^^^^^^^^ use of undeclared type `Unresolved` + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:5:46 + | +LL | struct Foo where T: Bar, ::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | struct Foo where T: Bar, T: Bar { + | ~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | struct Foo where T: Bar, ::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:9:54 + | +LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | struct Qux<'a, T> where T: Bar, &'a T: Bar { + | ~~~~~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:13:45 + | +LL | fn foo(_: T) where ::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | fn foo(_: T) where T: Bar { + | ~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | fn foo(_: T) where ::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:16:57 + | +LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { + | ^^^^^^ not a trait + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + | +help: constrain the associated type to `String` + | +LL | fn qux<'a, T: Bar>(_: &'a T) where &'a T: Bar { + | ~~~~~~~~~~~~~~~~~~~~~~~~ +help: a trait with a similar name exists + | +LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString { + | ~~~~~~~~ + +error[E0404]: expected trait, found struct `String` + --> $DIR/assoc_type_bound_with_struct.rs:19:51 + | +LL | fn issue_95327() where ::Assoc: String {} + | ^^^^^^ help: a trait with a similar name exists: `ToString` + --> $SRC_DIR/alloc/src/string.rs:LL:COL + | + = note: similarly named trait `ToString` defined here + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0404, E0433. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs new file mode 100644 index 000000000..b1f124c7e --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.rs @@ -0,0 +1,14 @@ +// Check that we validate associated type bounds for trait objects + +trait X { + type Y: Clone; +} + +fn f() { + None::.clone(); +} + +fn main() { + f::>(); + //~^ ERROR the trait bound `str: Clone` is not satisfied +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr new file mode 100644 index 000000000..fa7a8a2a0 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/check-trait-object-bounds-1.rs:12:9 + | +LL | f::>(); + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `f` + --> $DIR/check-trait-object-bounds-1.rs:7:9 + | +LL | fn f() { + | ^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs new file mode 100644 index 000000000..1422dda27 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2-ok.rs @@ -0,0 +1,15 @@ +// Make sure that we're handling bound lifetimes correctly when validating trait +// bounds. +// run-pass + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f X<'r> + ?Sized>() { + None::.map(|f| f(&0)); +} + +fn main() { + f:: X<'x, F = fn(&i32) -> &'x i32>>(); +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs new file mode 100644 index 000000000..eb2fb6e84 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs @@ -0,0 +1,15 @@ +// Check that we validate associated type bounds for trait objects when they +// have bound lifetimes + +trait X<'a> { + type F: FnOnce(&i32) -> &'a i32; +} + +fn f X<'r> + ?Sized>() { + None::.map(|f| f(&0)); +} + +fn main() { + f:: X<'x, F = i32>>(); + //~^ expected a `FnOnce<(&i32,)>` closure, found `i32` +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr new file mode 100644 index 000000000..10e82c54e --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr @@ -0,0 +1,16 @@ +error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32` + --> $DIR/check-trait-object-bounds-2.rs:13:9 + | +LL | f:: X<'x, F = i32>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32` + | + = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32` +note: required by a bound in `f` + --> $DIR/check-trait-object-bounds-2.rs:8:9 + | +LL | fn f X<'r> + ?Sized>() { + | ^^^^^^^^^^^^^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs new file mode 100644 index 000000000..ba04fd93a --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.rs @@ -0,0 +1,20 @@ +// Check that we validate associated type bounds for trait objects + +trait X<'a> { + type Y: Into<&'static str> + From<&'a str>; +} + +fn f<'a, T: X<'a> + ?Sized>(s: &'a str) -> &'static str { + T::Y::from(s).into() +} + +pub fn main() { + let z; + { + let s = String::from("abcdef"); + z = f::>(&s); + //~^ ERROR `s` does not live long enough + } + + println!("{}", z) +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr new file mode 100644 index 000000000..ade552c4b --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr @@ -0,0 +1,15 @@ +error[E0597]: `s` does not live long enough + --> $DIR/check-trait-object-bounds-3.rs:15:34 + | +LL | z = f::>(&s); + | ---------------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `s` is borrowed for `'static` +LL | +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs new file mode 100644 index 000000000..e9ca1563f --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.rs @@ -0,0 +1,17 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Super { + type Y: Clone; +} + +trait X: Super {} + +fn f() { + None::.clone(); +} + +fn main() { + f::>(); + //~^ ERROR the trait bound `str: Clone` is not satisfied +} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr new file mode 100644 index 000000000..4891ee9c2 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `str: Clone` is not satisfied + --> $DIR/check-trait-object-bounds-4.rs:15:9 + | +LL | f::>(); + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str` + | + = help: the trait `Clone` is implemented for `String` +note: required by a bound in `f` + --> $DIR/check-trait-object-bounds-4.rs:10:9 + | +LL | fn f() { + | ^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs new file mode 100644 index 000000000..7d733ad26 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs @@ -0,0 +1,27 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) + //~^ type mismatch resolving `::T == i64` +} + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr new file mode 100644 index 000000000..00fdb3753 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `::T == i64` + --> $DIR/check-trait-object-bounds-5.rs:23:12 + | +LL | is_obj(x) + | ------ ^ type mismatch resolving `::T == i64` + | | + | required by a bound introduced by this call + | +note: expected this to be `i64` + --> $DIR/check-trait-object-bounds-5.rs:9:14 + | +LL | type T = U; + | ^ +note: required by a bound in `is_obj` + --> $DIR/check-trait-object-bounds-5.rs:20:23 + | +LL | fn is_obj(_: &T) {} + | ^^^ required by this bound in `is_obj` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs new file mode 100644 index 000000000..cb196d67f --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.rs @@ -0,0 +1,24 @@ +// Check that we validate associated type bounds on super traits for trait +// objects + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) + //~^ ERROR type mismatch resolving `::T == i64` +} + +fn main() {} diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr new file mode 100644 index 000000000..9b0975e5e --- /dev/null +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-6.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `::T == i64` + --> $DIR/check-trait-object-bounds-6.rs:20:12 + | +LL | is_obj(x) + | ------ ^ type mismatch resolving `::T == i64` + | | + | required by a bound introduced by this call + | +note: expected this to be `i64` + --> $DIR/check-trait-object-bounds-6.rs:9:14 + | +LL | type T = U; + | ^ +note: required by a bound in `is_obj` + --> $DIR/check-trait-object-bounds-6.rs:17:23 + | +LL | fn is_obj(_: &T) {} + | ^^^ required by this bound in `is_obj` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/associated_type_bound/issue-51446.rs b/tests/ui/traits/associated_type_bound/issue-51446.rs new file mode 100644 index 000000000..7dd95de73 --- /dev/null +++ b/tests/ui/traits/associated_type_bound/issue-51446.rs @@ -0,0 +1,34 @@ +// Regression test for #51446. +// check-pass + +trait Foo { + type Item; + fn get(&self) -> Self::Item; +} + +fn blah(x: T, f: F) -> B +where + T: Foo, + F: Fn(T::Item), +{ + B { x: x.get(), f } +} + +pub struct B +where + F: Fn(T), +{ + pub x: T, + pub f: F, +} + +impl Foo for i32 { + type Item = i32; + fn get(&self) -> i32 { + *self + } +} + +fn main() { + let _ = blah(0, |_| ()); +} diff --git a/tests/ui/traits/astconv-cycle-between-and-type.rs b/tests/ui/traits/astconv-cycle-between-and-type.rs new file mode 100644 index 000000000..cc8f9dc51 --- /dev/null +++ b/tests/ui/traits/astconv-cycle-between-and-type.rs @@ -0,0 +1,29 @@ +// run-pass +// Test that we are able to successfully compile a setup where a trait +// (`Trait1`) references a struct (`SomeType`) which in turn +// carries a predicate that references the trait (`u32 : Trait1`, +// substituted). + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Trait1 : Trait2> { + fn dumb(&self) { } +} + +trait Trait2 { + fn dumber(&self, _: A) { } +} + +struct SomeType + where A : Trait1 +{ + a: A +} + +impl Trait1 for u32 { } + +impl Trait2> for u32 { } + +fn main() { } diff --git a/tests/ui/traits/augmented-assignments-trait.rs b/tests/ui/traits/augmented-assignments-trait.rs new file mode 100644 index 000000000..747a5393f --- /dev/null +++ b/tests/ui/traits/augmented-assignments-trait.rs @@ -0,0 +1,12 @@ +// run-pass +use std::ops::AddAssign; + +struct Int(#[allow(unused_tuple_struct_fields)] i32); + +impl AddAssign for Int { + fn add_assign(&mut self, _: Int) { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs b/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs new file mode 100644 index 000000000..dceec7e3e --- /dev/null +++ b/tests/ui/traits/auxiliary/anon_trait_static_method_lib.rs @@ -0,0 +1,9 @@ +pub struct Foo { + pub x: isize +} + +impl Foo { + pub fn new() -> Foo { + Foo { x: 3 } + } +} diff --git a/tests/ui/traits/auxiliary/go_trait.rs b/tests/ui/traits/auxiliary/go_trait.rs new file mode 100644 index 000000000..aa0ec2289 --- /dev/null +++ b/tests/ui/traits/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once(this: G, arg: isize) { + this.go_once(arg) +} + +impl GoMut for G + where G : Go +{ + default fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +impl GoOnce for G + where G : GoMut +{ + default fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs b/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs new file mode 100644 index 000000000..769e89731 --- /dev/null +++ b/tests/ui/traits/auxiliary/issue_89119_intercrate_caching.rs @@ -0,0 +1,60 @@ +// This is the auxiliary crate for the regression test for issue #89119, minimized +// from `zvariant-2.8.0`. + +use std::convert::TryFrom; +use std::borrow::Cow; + +pub struct Str<'a>(Cow<'a, str>); +impl<'a> Str<'a> { + pub fn to_owned(&self) -> Str<'static> { + todo!() + } +} + +pub enum Value<'a> { + Str(Str<'a>), + Value(Box>), +} +impl<'a> Value<'a> { + pub fn to_owned(&self) -> Value<'static> { + match self { + Value::Str(v) => Value::Str(v.to_owned()), + Value::Value(v) => { + let o = OwnedValue::from(&**v); + Value::Value(Box::new(o.into_inner())) + } + } + } +} + +struct OwnedValue(Value<'static>); +impl OwnedValue { + pub(crate) fn into_inner(self) -> Value<'static> { + todo!() + } +} +impl<'a, T> TryFrom for Vec +where + T: TryFrom, Error = ()>, +{ + type Error = (); + fn try_from(_: OwnedValue) -> Result { + todo!() + } +} +impl TryFrom for Vec { + type Error = (); + fn try_from(_: OwnedValue) -> Result { + todo!() + } +} +impl<'a> From> for OwnedValue { + fn from(_: Value<'a>) -> Self { + todo!() + } +} +impl<'a> From<&Value<'a>> for OwnedValue { + fn from(_: &Value<'a>) -> Self { + todo!() + } +} diff --git a/tests/ui/traits/auxiliary/trait_safety_lib.rs b/tests/ui/traits/auxiliary/trait_safety_lib.rs new file mode 100644 index 000000000..6fc432ed4 --- /dev/null +++ b/tests/ui/traits/auxiliary/trait_safety_lib.rs @@ -0,0 +1,9 @@ +// Simple smoke test that unsafe traits can be compiled etc. + +pub unsafe trait Foo { + fn foo(&self) -> isize; +} + +unsafe impl Foo for isize { + fn foo(&self) -> isize { *self } +} diff --git a/tests/ui/traits/auxiliary/traitimpl.rs b/tests/ui/traits/auxiliary/traitimpl.rs new file mode 100644 index 000000000..fda5314cd --- /dev/null +++ b/tests/ui/traits/auxiliary/traitimpl.rs @@ -0,0 +1,7 @@ +// Test inherent trait impls work cross-crait. + +pub trait Bar<'a> : 'a {} + +impl<'a> Bar<'a> { + pub fn bar(&self) {} +} diff --git a/tests/ui/traits/bad-method-typaram-kind.rs b/tests/ui/traits/bad-method-typaram-kind.rs new file mode 100644 index 000000000..b088eae1c --- /dev/null +++ b/tests/ui/traits/bad-method-typaram-kind.rs @@ -0,0 +1,14 @@ +fn foo() { + 1.bar::(); //~ ERROR `T` cannot be sent between threads safely +} + +trait Bar { + fn bar(&self); +} + +impl Bar for usize { + fn bar(&self) { + } +} + +fn main() {} diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr new file mode 100644 index 000000000..56acfbe80 --- /dev/null +++ b/tests/ui/traits/bad-method-typaram-kind.stderr @@ -0,0 +1,19 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/bad-method-typaram-kind.rs:2:13 + | +LL | 1.bar::(); + | ^ `T` cannot be sent between threads safely + | +note: required by a bound in `Bar::bar` + --> $DIR/bad-method-typaram-kind.rs:6:14 + | +LL | fn bar(&self); + | ^^^^ required by this bound in `Bar::bar` +help: consider further restricting this bound + | +LL | fn foo() { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bad-sized.rs b/tests/ui/traits/bad-sized.rs new file mode 100644 index 000000000..a15219679 --- /dev/null +++ b/tests/ui/traits/bad-sized.rs @@ -0,0 +1,9 @@ +trait Trait {} + +pub fn main() { + let x: Vec = Vec::new(); + //~^ ERROR only auto traits can be used as additional traits in a trait object + //~| ERROR the size for values of type + //~| ERROR the size for values of type + //~| ERROR the size for values of type +} diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr new file mode 100644 index 000000000..fb9900bc5 --- /dev/null +++ b/tests/ui/traits/bad-sized.stderr @@ -0,0 +1,45 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/bad-sized.rs:4:28 + | +LL | let x: Vec = Vec::new(); + | ----- ^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Trait + Sized {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:12 + | +LL | let x: Vec = Vec::new(); + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:37 + | +LL | let x: Vec = Vec::new(); + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec::::new` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time + --> $DIR/bad-sized.rs:4:37 + | +LL | let x: Vec = Vec::new(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Trait` +note: required by a bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0225, E0277. +For more information about an error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs new file mode 100644 index 000000000..f9a934764 --- /dev/null +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs @@ -0,0 +1,11 @@ +fn strip_lf(s: &str) -> &str { + s.strip_suffix(b'\n').unwrap_or(s) + //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8` + //~| NOTE expected an `FnMut<(char,)>` closure, found `u8` + //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8` + //~| HELP the following other types implement trait `Pattern<'a>`: + //~| NOTE required for `u8` to implement `Pattern<'_>` + +} + +fn main() {} diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr new file mode 100644 index 000000000..ce9ab2d81 --- /dev/null +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -0,0 +1,20 @@ +error[E0277]: expected a `FnMut<(char,)>` closure, found `u8` + --> $DIR/assoc-fn-bound-root-obligation.rs:2:7 + | +LL | s.strip_suffix(b'\n').unwrap_or(s) + | ^^^^^^^^^^^^ expected an `FnMut<(char,)>` closure, found `u8` + | + = help: the trait `FnMut<(char,)>` is not implemented for `u8` + = help: the following other types implement trait `Pattern<'a>`: + &'b String + &'b [char; N] + &'b [char] + &'b str + &'c &'b str + [char; N] + char + = note: required for `u8` to implement `Pattern<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/auxiliary/crate_a1.rs b/tests/ui/traits/bound/auxiliary/crate_a1.rs new file mode 100644 index 000000000..6aa010258 --- /dev/null +++ b/tests/ui/traits/bound/auxiliary/crate_a1.rs @@ -0,0 +1,9 @@ +pub trait Bar {} + +pub fn try_foo(x: impl Bar) {} + +pub struct ImplementsTraitForUsize { + _marker: std::marker::PhantomData, +} + +impl Bar for ImplementsTraitForUsize {} diff --git a/tests/ui/traits/bound/auxiliary/crate_a2.rs b/tests/ui/traits/bound/auxiliary/crate_a2.rs new file mode 100644 index 000000000..d6057db5e --- /dev/null +++ b/tests/ui/traits/bound/auxiliary/crate_a2.rs @@ -0,0 +1,13 @@ +pub struct Foo; + +pub trait Bar {} + +impl Bar for Foo {} + +pub struct DoesNotImplementTrait; + +pub struct ImplementsWrongTraitConditionally { + _marker: std::marker::PhantomData, +} + +impl Bar for ImplementsWrongTraitConditionally {} diff --git a/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs b/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs new file mode 100644 index 000000000..7e9592eee --- /dev/null +++ b/tests/ui/traits/bound/auxiliary/on_structs_and_enums_xc.rs @@ -0,0 +1,13 @@ +pub trait Trait { + fn dummy(&self) { } +} + +pub struct Foo { + pub x: T, +} + +pub enum Bar { + ABar(isize), + BBar(T), + CBar(usize), +} diff --git a/tests/ui/traits/bound/basic.rs b/tests/ui/traits/bound/basic.rs new file mode 100644 index 000000000..8c8a7eb7d --- /dev/null +++ b/tests/ui/traits/bound/basic.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(unconditional_recursion)] + +// pretty-expanded FIXME #23616 + +trait Foo { +} + +fn b(_x: Box) { +} + +fn c(x: Box) { + e(x); +} + +fn d(x: Box) { + e(x); +} + +fn e(x: Box) { + e(x); +} + +pub fn main() { } diff --git a/tests/ui/traits/bound/generic_trait.rs b/tests/ui/traits/bound/generic_trait.rs new file mode 100644 index 000000000..18382bb59 --- /dev/null +++ b/tests/ui/traits/bound/generic_trait.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +trait connection { + fn read(&self) -> isize; +} + +trait connection_factory { + fn create(&self) -> C; +} + +type my_connection = (); +type my_connection_factory = (); + +impl connection for () { + fn read(&self) -> isize { 43 } +} + +impl connection_factory for my_connection_factory { + fn create(&self) -> my_connection { () } +} + +pub fn main() { + let factory = (); + let connection = factory.create(); + let result = connection.read(); + assert_eq!(result, 43); +} diff --git a/tests/ui/traits/bound/impl-comparison-duplicates.rs b/tests/ui/traits/bound/impl-comparison-duplicates.rs new file mode 100644 index 000000000..de6c2afa2 --- /dev/null +++ b/tests/ui/traits/bound/impl-comparison-duplicates.rs @@ -0,0 +1,16 @@ +// run-pass +// Tests that type parameter bounds on an implementation need not match the +// trait exactly, as long as the implementation doesn't demand *more* bounds +// than the trait. + +// pretty-expanded FIXME #23616 + +trait A { + fn foo(&self); +} + +impl A for isize { + fn foo(&self) {} // Ord implies Eq, so this is ok. +} + +fn main() {} diff --git a/tests/ui/traits/bound/in-arc.rs b/tests/ui/traits/bound/in-arc.rs new file mode 100644 index 000000000..a1492c0b9 --- /dev/null +++ b/tests/ui/traits/bound/in-arc.rs @@ -0,0 +1,108 @@ +// run-pass +#![allow(unused_must_use)] +// Tests that a heterogeneous list of existential `dyn` types can be put inside an Arc +// and shared between threads as long as all types fulfill Send. + +// ignore-emscripten no threads support + +use std::sync::Arc; +use std::sync::mpsc::channel; +use std::thread; + +trait Pet { + fn name(&self, blk: Box); + fn num_legs(&self) -> usize; + fn of_good_pedigree(&self) -> bool; +} + +struct Catte { + num_whiskers: usize, + name: String, +} + +struct Dogge { + bark_decibels: usize, + tricks_known: usize, + name: String, +} + +struct Goldfyshe { + swim_speed: usize, + name: String, +} + +impl Pet for Catte { + fn name(&self, mut blk: Box) { blk(&self.name) } + fn num_legs(&self) -> usize { 4 } + fn of_good_pedigree(&self) -> bool { self.num_whiskers >= 4 } +} +impl Pet for Dogge { + fn name(&self, mut blk: Box) { blk(&self.name) } + fn num_legs(&self) -> usize { 4 } + fn of_good_pedigree(&self) -> bool { + self.bark_decibels < 70 || self.tricks_known > 20 + } +} +impl Pet for Goldfyshe { + fn name(&self, mut blk: Box) { blk(&self.name) } + fn num_legs(&self) -> usize { 0 } + fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 } +} + +pub fn main() { + let catte = Catte { num_whiskers: 7, name: "alonzo_church".to_string() }; + let dogge1 = Dogge { + bark_decibels: 100, + tricks_known: 42, + name: "alan_turing".to_string(), + }; + let dogge2 = Dogge { + bark_decibels: 55, + tricks_known: 11, + name: "albert_einstein".to_string(), + }; + let fishe = Goldfyshe { + swim_speed: 998, + name: "alec_guinness".to_string(), + }; + let arc = Arc::new(vec![ + Box::new(catte) as Box, + Box::new(dogge1) as Box, + Box::new(fishe) as Box, + Box::new(dogge2) as Box]); + let (tx1, rx1) = channel(); + let arc1 = arc.clone(); + let t1 = thread::spawn(move|| { check_legs(arc1); tx1.send(()); }); + let (tx2, rx2) = channel(); + let arc2 = arc.clone(); + let t2 = thread::spawn(move|| { check_names(arc2); tx2.send(()); }); + let (tx3, rx3) = channel(); + let arc3 = arc.clone(); + let t3 = thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); }); + rx1.recv(); + rx2.recv(); + rx3.recv(); + t1.join(); + t2.join(); + t3.join(); +} + +fn check_legs(arc: Arc>>) { + let mut legs = 0; + for pet in arc.iter() { + legs += pet.num_legs(); + } + assert!(legs == 12); +} +fn check_names(arc: Arc>>) { + for pet in arc.iter() { + pet.name(Box::new(|name| { + assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8); + })) + } +} +fn check_pedigree(arc: Arc>>) { + for pet in arc.iter() { + assert!(pet.of_good_pedigree()); + } +} diff --git a/tests/ui/traits/bound/multiple.rs b/tests/ui/traits/bound/multiple.rs new file mode 100644 index 000000000..868b33407 --- /dev/null +++ b/tests/ui/traits/bound/multiple.rs @@ -0,0 +1,9 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn f(_: T) { +} + +pub fn main() { + f(3); +} diff --git a/tests/ui/traits/bound/not-on-bare-trait.rs b/tests/ui/traits/bound/not-on-bare-trait.rs new file mode 100644 index 000000000..daf18c670 --- /dev/null +++ b/tests/ui/traits/bound/not-on-bare-trait.rs @@ -0,0 +1,13 @@ +trait Foo { + fn dummy(&self) {} +} + +// This should emit the less confusing error, not the more confusing one. + +fn foo(_x: Foo + Send) { + //~^ ERROR the size for values of type + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} + +fn main() {} diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr new file mode 100644 index 000000000..36b08a7d3 --- /dev/null +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -0,0 +1,34 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/not-on-bare-trait.rs:7:12 + | +LL | fn foo(_x: Foo + Send) { + | ^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | fn foo(_x: dyn Foo + Send) { + | +++ + +error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time + --> $DIR/not-on-bare-trait.rs:7:8 + | +LL | fn foo(_x: Foo + Send) { + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL | fn foo(_x: impl Foo + Send) { + | ++++ +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(_x: &Foo + Send) { + | + + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/not-on-struct.rs b/tests/ui/traits/bound/not-on-struct.rs new file mode 100644 index 000000000..8633e9d7a --- /dev/null +++ b/tests/ui/traits/bound/not-on-struct.rs @@ -0,0 +1,38 @@ +// We don't need those errors. Ideally we would silence them, but to do so we need to move the +// lint from being an early-lint during parsing to a late-lint, because it needs to be aware of +// the types involved. +#![allow(bare_trait_objects)] + +struct Foo; + +fn foo(_x: Box) { } //~ ERROR expected trait, found struct `Foo` + +type TypeAlias = Box>; //~ ERROR expected trait, found struct `Vec` + +struct A; +fn a() -> A + 'static { //~ ERROR expected trait, found + A +} +fn b<'a,T,E>(iter: Iterator + 'a>) { //~ ERROR expected trait, found + panic!() +} +fn c() -> 'static + A { //~ ERROR expected trait, found + A +} +fn d<'a,T,E>(iter: Iterator>) { //~ ERROR expected trait, found + panic!() +} +fn e() -> 'static + A + 'static { //~ ERROR expected trait, found +//~^ ERROR only a single explicit lifetime bound is permitted + A +} +fn f<'a,T,E>(iter: Iterator + 'a>) { //~ ERROR expected trait, found +//~^ ERROR only a single explicit lifetime bound is permitted + panic!() +} +struct Traitor; +trait Trait {} +fn g() -> Traitor + 'static { //~ ERROR expected trait, found struct `Traitor` + A +} +fn main() {} diff --git a/tests/ui/traits/bound/not-on-struct.stderr b/tests/ui/traits/bound/not-on-struct.stderr new file mode 100644 index 000000000..2de35dc7f --- /dev/null +++ b/tests/ui/traits/bound/not-on-struct.stderr @@ -0,0 +1,175 @@ +error[E0226]: only a single explicit lifetime bound is permitted + --> $DIR/not-on-struct.rs:25:25 + | +LL | fn e() -> 'static + A + 'static { + | ^^^^^^^ + +error[E0226]: only a single explicit lifetime bound is permitted + --> $DIR/not-on-struct.rs:29:53 + | +LL | fn f<'a,T,E>(iter: Iterator + 'a>) { + | ^^ + +error[E0404]: expected trait, found struct `Foo` + --> $DIR/not-on-struct.rs:8:16 + | +LL | fn foo(_x: Box) { } + | ^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:8:22 + | +LL | fn foo(_x: Box) { } + | --- ^^^^ ...because of this bound + | | + | expected this type to be a trait... + +error[E0404]: expected trait, found struct `Vec` + --> $DIR/not-on-struct.rs:10:29 + | +LL | type TypeAlias = Box>; + | ^^^^^^ not a trait + +error[E0404]: expected trait, found struct `A` + --> $DIR/not-on-struct.rs:13:11 + | +LL | fn a() -> A + 'static { + | ^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:13:15 + | +LL | fn a() -> A + 'static { + | - ^^^^^^^ ...because of this bound + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn a() -> A + 'static { +LL + fn a() -> A { + | + +error[E0404]: expected trait, found enum `Result` + --> $DIR/not-on-struct.rs:16:34 + | +LL | fn b<'a,T,E>(iter: Iterator + 'a>) { + | ^^^^^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:16:48 + | +LL | fn b<'a,T,E>(iter: Iterator + 'a>) { + | ----------- ^^ ...because of this bound + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn b<'a,T,E>(iter: Iterator + 'a>) { +LL + fn b<'a,T,E>(iter: Iterator>) { + | + +error[E0404]: expected trait, found struct `A` + --> $DIR/not-on-struct.rs:19:21 + | +LL | fn c() -> 'static + A { + | ^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:19:11 + | +LL | fn c() -> 'static + A { + | ^^^^^^^ - expected this type to be a trait... + | | + | ...because of this bound +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn c() -> 'static + A { +LL + fn c() -> A { + | + +error[E0404]: expected trait, found enum `Result` + --> $DIR/not-on-struct.rs:22:39 + | +LL | fn d<'a,T,E>(iter: Iterator>) { + | ^^^^^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:22:34 + | +LL | fn d<'a,T,E>(iter: Iterator>) { + | ^^ ----------- expected this type to be a trait... + | | + | ...because of this bound +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn d<'a,T,E>(iter: Iterator>) { +LL + fn d<'a,T,E>(iter: Iterator>) { + | + +error[E0404]: expected trait, found struct `A` + --> $DIR/not-on-struct.rs:25:21 + | +LL | fn e() -> 'static + A + 'static { + | ^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:25:11 + | +LL | fn e() -> 'static + A + 'static { + | ^^^^^^^ - ^^^^^^^ ...because of these bounds + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn e() -> 'static + A + 'static { +LL + fn e() -> A { + | + +error[E0404]: expected trait, found enum `Result` + --> $DIR/not-on-struct.rs:29:39 + | +LL | fn f<'a,T,E>(iter: Iterator + 'a>) { + | ^^^^^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:29:34 + | +LL | fn f<'a,T,E>(iter: Iterator + 'a>) { + | ^^ ----------- ^^ ...because of these bounds + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn f<'a,T,E>(iter: Iterator + 'a>) { +LL + fn f<'a,T,E>(iter: Iterator>) { + | + +error[E0404]: expected trait, found struct `Traitor` + --> $DIR/not-on-struct.rs:35:11 + | +LL | trait Trait {} + | ----------- similarly named trait `Trait` defined here +LL | fn g() -> Traitor + 'static { + | ^^^^^^^ not a trait + | +help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way + --> $DIR/not-on-struct.rs:35:21 + | +LL | fn g() -> Traitor + 'static { + | ------- ^^^^^^^ ...because of this bound + | | + | expected this type to be a trait... +help: if you meant to use a type and not a trait here, remove the bounds + | +LL - fn g() -> Traitor + 'static { +LL + fn g() -> Traitor { + | +help: a trait with a similar name exists + | +LL | fn g() -> Trait + 'static { + | ~~~~~ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0226, E0404. +For more information about an error, try `rustc --explain E0226`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs b/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs new file mode 100644 index 000000000..6a6fcf530 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.rs @@ -0,0 +1,20 @@ +trait Trait {} + +struct Foo { + x: T, +} + +enum Bar { + ABar(isize), + BBar(T), + CBar(usize), +} + +fn explode(x: Foo) {} +//~^ ERROR E0277 + +fn kaboom(y: Bar) {} +//~^ ERROR E0277 + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr new file mode 100644 index 000000000..61237a63e --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-fns.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `u32: Trait` is not satisfied + --> $DIR/on-structs-and-enums-in-fns.rs:13:15 + | +LL | fn explode(x: Foo) {} + | ^^^^^^^^ the trait `Trait` is not implemented for `u32` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-in-fns.rs:3:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `f32: Trait` is not satisfied + --> $DIR/on-structs-and-enums-in-fns.rs:16:14 + | +LL | fn kaboom(y: Bar) {} + | ^^^^^^^^ the trait `Trait` is not implemented for `f32` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums-in-fns.rs:7:12 + | +LL | enum Bar { + | ^^^^^ required by this bound in `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs b/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs new file mode 100644 index 000000000..d37949952 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.rs @@ -0,0 +1,25 @@ +trait Trait {} + +struct Foo { + x: T, +} + +enum Bar { + ABar(isize), + BBar(T), + CBar(usize), +} + +trait PolyTrait +{ + fn whatever(&self, t: T) {} +} + +struct Struct; + +impl PolyTrait> for Struct { +//~^ ERROR E0277 +} + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr new file mode 100644 index 000000000..8a4374226 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u16: Trait` is not satisfied + --> $DIR/on-structs-and-enums-in-impls.rs:20:6 + | +LL | impl PolyTrait> for Struct { + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-in-impls.rs:3:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.rs b/tests/ui/traits/bound/on-structs-and-enums-locals.rs new file mode 100644 index 000000000..60ba343bb --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-locals.rs @@ -0,0 +1,17 @@ +trait Trait { + fn dummy(&self) { } +} + +struct Foo { + x: T, +} + +fn main() { + let foo = Foo { + x: 3 + //~^ ERROR E0277 + }; + + let baz: Foo = loop { }; + //~^ ERROR E0277 +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-locals.stderr b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr new file mode 100644 index 000000000..20bbe69c0 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-locals.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-locals.rs:15:14 + | +LL | let baz: Foo = loop { }; + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `{integer}: Trait` is not satisfied + --> $DIR/on-structs-and-enums-locals.rs:11:12 + | +LL | x: 3 + | ^ the trait `Trait` is not implemented for `{integer}` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-locals.rs:5:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-rpass.rs b/tests/ui/traits/bound/on-structs-and-enums-rpass.rs new file mode 100644 index 000000000..4dc4fecc9 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-rpass.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +trait U {} +trait T { fn get(self) -> X; } + +trait S2 { + fn m(x: Box+'static>) {} +} + +struct St { + f: Box+'static>, +} + +impl St { + fn blah() {} +} + +fn main() {} diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.rs b/tests/ui/traits/bound/on-structs-and-enums-static.rs new file mode 100644 index 000000000..df3f8b8a5 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-static.rs @@ -0,0 +1,15 @@ +trait Trait { + fn dummy(&self) { } +} + +struct Foo { + x: T, +} + +static X: Foo = Foo { +//~^ ERROR E0277 + x: 1, +}; + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr new file mode 100644 index 000000000..fda734e85 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-static.rs:9:11 + | +LL | static X: Foo = Foo { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums-static.rs:5:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc.rs b/tests/ui/traits/bound/on-structs-and-enums-xc.rs new file mode 100644 index 000000000..94316d240 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc.rs @@ -0,0 +1,14 @@ +// aux-build:on_structs_and_enums_xc.rs + +extern crate on_structs_and_enums_xc; + +use on_structs_and_enums_xc::{Bar, Foo, Trait}; + +fn explode(x: Foo) {} +//~^ ERROR E0277 + +fn kaboom(y: Bar) {} +//~^ ERROR E0277 + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc.stderr new file mode 100644 index 000000000..5064b60bf --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc.rs:7:15 + | +LL | fn explode(x: Foo) {} + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Foo` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18 + | +LL | pub struct Foo { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `f32: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc.rs:10:14 + | +LL | fn kaboom(y: Bar) {} + | ^^^^^^^^ the trait `Trait` is not implemented for `f32` + | +note: required by a bound in `Bar` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16 + | +LL | pub enum Bar { + | ^^^^^ required by this bound in `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc1.rs b/tests/ui/traits/bound/on-structs-and-enums-xc1.rs new file mode 100644 index 000000000..5ef35b513 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.rs @@ -0,0 +1,15 @@ +// aux-build:on_structs_and_enums_xc.rs + +extern crate on_structs_and_enums_xc; + +use on_structs_and_enums_xc::{Bar, Foo, Trait}; + +fn main() { + let foo = Foo { + x: 3 + //~^ ERROR E0277 + }; + let bar: Bar = return; + //~^ ERROR E0277 + let _ = bar; +} diff --git a/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr new file mode 100644 index 000000000..3fb5decb7 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums-xc1.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `f64: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc1.rs:12:14 + | +LL | let bar: Bar = return; + | ^^^^^^^^ the trait `Trait` is not implemented for `f64` + | +note: required by a bound in `Bar` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:9:16 + | +LL | pub enum Bar { + | ^^^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `{integer}: Trait` is not satisfied + --> $DIR/on-structs-and-enums-xc1.rs:9:12 + | +LL | x: 3 + | ^ the trait `Trait` is not implemented for `{integer}` + | +note: required by a bound in `Foo` + --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18 + | +LL | pub struct Foo { + | ^^^^^ required by this bound in `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/on-structs-and-enums.rs b/tests/ui/traits/bound/on-structs-and-enums.rs new file mode 100644 index 000000000..024084fa7 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums.rs @@ -0,0 +1,43 @@ +trait Trait {} + +struct Foo { + x: T, +} + +enum Bar { + ABar(isize), + BBar(T), + CBar(usize), +} + +impl Foo { +//~^ ERROR `T: Trait` is not satisfied + fn uhoh() {} +} + +struct Baz { + a: Foo, //~ ERROR E0277 +} + +enum Boo { + Quux(Bar), //~ ERROR E0277 +} + +struct Badness { + b: Foo, //~ ERROR E0277 +} + +enum MoreBadness { + EvenMoreBadness(Bar), //~ ERROR E0277 +} + +struct TupleLike( + Foo, //~ ERROR E0277 +); + +enum Enum { + DictionaryLike { field: Bar }, //~ ERROR E0277 +} + +fn main() { +} diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr new file mode 100644 index 000000000..fe05b8634 --- /dev/null +++ b/tests/ui/traits/bound/on-structs-and-enums.stderr @@ -0,0 +1,99 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:13:9 + | +LL | impl Foo { + | ^^^^^^ the trait `Trait` is not implemented for `T` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` +help: consider restricting type parameter `T` + | +LL | impl Foo { + | +++++++ + +error[E0277]: the trait bound `isize: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:19:8 + | +LL | a: Foo, + | ^^^^^^^^^^ the trait `Trait` is not implemented for `isize` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `usize: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:23:10 + | +LL | Quux(Bar), + | ^^^^^^^^^^ the trait `Trait` is not implemented for `usize` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums.rs:7:12 + | +LL | enum Bar { + | ^^^^^ required by this bound in `Bar` + +error[E0277]: the trait bound `U: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:27:8 + | +LL | b: Foo, + | ^^^^^^ the trait `Trait` is not implemented for `U` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` +help: consider restricting type parameter `U` + | +LL | struct Badness { + | +++++++ + +error[E0277]: the trait bound `V: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:31:21 + | +LL | EvenMoreBadness(Bar), + | ^^^^^^ the trait `Trait` is not implemented for `V` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums.rs:7:12 + | +LL | enum Bar { + | ^^^^^ required by this bound in `Bar` +help: consider restricting type parameter `V` + | +LL | enum MoreBadness { + | +++++++ + +error[E0277]: the trait bound `i32: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:35:5 + | +LL | Foo, + | ^^^^^^^^ the trait `Trait` is not implemented for `i32` + | +note: required by a bound in `Foo` + --> $DIR/on-structs-and-enums.rs:3:14 + | +LL | struct Foo { + | ^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/on-structs-and-enums.rs:39:29 + | +LL | DictionaryLike { field: Bar }, + | ^^^^^^^ the trait `Trait` is not implemented for `u8` + | +note: required by a bound in `Bar` + --> $DIR/on-structs-and-enums.rs:7:12 + | +LL | enum Bar { + | ^^^^^ required by this bound in `Bar` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/recursion.rs b/tests/ui/traits/bound/recursion.rs new file mode 100644 index 000000000..0023ff654 --- /dev/null +++ b/tests/ui/traits/bound/recursion.rs @@ -0,0 +1,20 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait I { fn i(&self) -> Self; } + +trait A { + fn id(x:T) -> T { x.i() } +} + +trait J { fn j(&self) -> T; } + +trait B> { + fn id(x:T) -> T { x.j() } +} + +trait C { + fn id>(x:T) -> T { x.j() } +} + +pub fn main() { } diff --git a/tests/ui/traits/bound/same-crate-name.rs b/tests/ui/traits/bound/same-crate-name.rs new file mode 100644 index 000000000..8d646a414 --- /dev/null +++ b/tests/ui/traits/bound/same-crate-name.rs @@ -0,0 +1,55 @@ +// aux-build:crate_a1.rs +// aux-build:crate_a2.rs + +// Issue 22750 +// This tests the extra help message reported when a trait bound +// is not met but the struct implements a trait with the same path. + +fn main() { + let foo = { + extern crate crate_a2 as a; + a::Foo + }; + + let implements_no_traits = { + extern crate crate_a2 as a; + a::DoesNotImplementTrait + }; + + let other_variant_implements_mismatched_trait = { + extern crate crate_a2 as a; + a::ImplementsWrongTraitConditionally { _marker: std::marker::PhantomData:: } + }; + + let other_variant_implements_correct_trait = { + extern crate crate_a1 as a; + a::ImplementsTraitForUsize { _marker: std::marker::PhantomData:: } + }; + + { + extern crate crate_a1 as a; + a::try_foo(foo); + //~^ ERROR E0277 + //~| trait impl with same name found + //~| perhaps two different versions of crate `crate_a2` + + // We don't want to see the "version mismatch" help message here + // because `implements_no_traits` has no impl for `Foo` + a::try_foo(implements_no_traits); + //~^ ERROR E0277 + + // We don't want to see the "version mismatch" help message here + // because `other_variant_implements_mismatched_trait` + // does not have an impl for its `` variant, + // only for its `` variant. + a::try_foo(other_variant_implements_mismatched_trait); + //~^ ERROR E0277 + + // We don't want to see the "version mismatch" help message here + // because `ImplementsTraitForUsize` only has + // impls for the correct trait where the path is not misleading. + a::try_foo(other_variant_implements_correct_trait); + //~^ ERROR E0277 + //~| the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` + } +} diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr new file mode 100644 index 000000000..f66cad77f --- /dev/null +++ b/tests/ui/traits/bound/same-crate-name.stderr @@ -0,0 +1,75 @@ +error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:31:20 + | +LL | a::try_foo(foo); + | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +help: trait impl with same name found + --> $DIR/auxiliary/crate_a2.rs:5:1 + | +LL | impl Bar for Foo {} + | ^^^^^^^^^^^^^^^^ + = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:38:20 + | +LL | a::try_foo(implements_no_traits); + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` + | | + | required by a bound introduced by this call + | + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error[E0277]: the trait bound `ImplementsWrongTraitConditionally: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:45:20 + | +LL | a::try_foo(other_variant_implements_mismatched_trait); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally` + | | + | required by a bound introduced by this call + | +help: trait impl with same name found + --> $DIR/auxiliary/crate_a2.rs:13:1 + | +LL | impl Bar for ImplementsWrongTraitConditionally {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: perhaps two different versions of crate `crate_a2` are being used? + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error[E0277]: the trait bound `ImplementsTraitForUsize: main::a::Bar` is not satisfied + --> $DIR/same-crate-name.rs:51:20 + | +LL | a::try_foo(other_variant_implements_correct_trait); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize` + | | + | required by a bound introduced by this call + | + = help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +note: required by a bound in `try_foo` + --> $DIR/auxiliary/crate_a1.rs:3:24 + | +LL | pub fn try_foo(x: impl Bar) {} + | ^^^ required by this bound in `try_foo` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/bound/sugar.rs b/tests/ui/traits/bound/sugar.rs new file mode 100644 index 000000000..65b6f6faa --- /dev/null +++ b/tests/ui/traits/bound/sugar.rs @@ -0,0 +1,19 @@ +// Tests for "default" bounds inferred for traits with no bounds list. + +trait Foo {} + +fn a(_x: Box) { +} + +fn b(_x: &'static (dyn Foo + 'static)) { +} + +fn c(x: Box) { + a(x); //~ ERROR mismatched types +} + +fn d(x: &'static (dyn Foo + Sync)) { + b(x); +} + +fn main() {} diff --git a/tests/ui/traits/bound/sugar.stderr b/tests/ui/traits/bound/sugar.stderr new file mode 100644 index 000000000..b67648c7b --- /dev/null +++ b/tests/ui/traits/bound/sugar.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/sugar.rs:12:7 + | +LL | a(x); + | - ^ expected trait `Foo + Send`, found trait `Foo + Sync` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box<(dyn Foo + Send + 'static)>` + found struct `Box<(dyn Foo + Sync + 'static)>` +note: function defined here + --> $DIR/sugar.rs:5:4 + | +LL | fn a(_x: Box) { + | ^ ----------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/bug-7183-generics.rs b/tests/ui/traits/bug-7183-generics.rs new file mode 100644 index 000000000..f53a17361 --- /dev/null +++ b/tests/ui/traits/bug-7183-generics.rs @@ -0,0 +1,36 @@ +// run-pass + +trait Speak : Sized { + fn say(&self, s:&str) -> String; + fn hi(&self) -> String { hello(self) } +} + +fn hello(s:&S) -> String{ + s.say("hello") +} + +impl Speak for isize { + fn say(&self, s:&str) -> String { + format!("{}: {}", s, *self) + } +} + +impl Speak for Option { + fn say(&self, s:&str) -> String { + match *self { + None => format!("{} - none", s), + Some(ref x) => { format!("something!{}", x.say(s)) } + } + } +} + + +pub fn main() { + assert_eq!(3.hi(), "hello: 3".to_string()); + assert_eq!(Some(Some(3)).hi(), + "something!something!hello: 3".to_string()); + assert_eq!(None::.hi(), "hello - none".to_string()); + + assert_eq!(Some(None::).hi(), "something!hello - none".to_string()); + assert_eq!(Some(3).hi(), "something!hello: 3".to_string()); +} diff --git a/tests/ui/traits/bug-7295.rs b/tests/ui/traits/bug-7295.rs new file mode 100644 index 000000000..156ff2ee8 --- /dev/null +++ b/tests/ui/traits/bug-7295.rs @@ -0,0 +1,14 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait Foo { + fn func1(&self, t: U, w: T); + + fn func2(&self, t: U, w: T) { + self.func1(t, w); + } +} + +pub fn main() { + +} diff --git a/tests/ui/traits/cache-issue-18209.rs b/tests/ui/traits/cache-issue-18209.rs new file mode 100644 index 000000000..15676e455 --- /dev/null +++ b/tests/ui/traits/cache-issue-18209.rs @@ -0,0 +1,20 @@ +// run-pass +// Test that the cache results from the default method do not pollute +// the cache for the later call in `load()`. +// +// See issue #18209. + +// pretty-expanded FIXME #23616 + +pub trait Foo { + fn load_from() -> Box; + fn load() -> Box { + Foo::load_from() + } +} + +pub fn load() -> Box { + Foo::load() +} + +fn main() { } diff --git a/tests/ui/traits/cache-reached-depth-ice.rs b/tests/ui/traits/cache-reached-depth-ice.rs new file mode 100644 index 000000000..c36ac0857 --- /dev/null +++ b/tests/ui/traits/cache-reached-depth-ice.rs @@ -0,0 +1,45 @@ +#![feature(rustc_attrs)] + +// Test for a particular corner case where the evaluation +// cache can get out of date. The problem here is that +// when we cache C, we have observed that it reaches +// to depth 2 (the node for B), but we later realize +// that B itself depends on A (reached depth 0). We +// failed to update the depth for C transitively, which +// resulted in an assertion failure when it was referenced +// from D. +// +// A (reached depth 0) +// E +// B // depth 2 -- reached depth = 0 +// C // depth 3 -- reached depth = 2 (should be 0) +// B +// A // depth 0 +// D (depth 1) +// C (cache -- reached depth = 2) + +struct A { + e: E, + d: C, +} + +struct E { + b: B, +} + +struct B { + a: Option>, + c: C, +} + +struct C { + b: Option>, +} + +#[rustc_evaluate_where_clauses] +fn test() {} + +fn main() { + test::(); + //~^ ERROR evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOk) +} diff --git a/tests/ui/traits/cache-reached-depth-ice.stderr b/tests/ui/traits/cache-reached-depth-ice.stderr new file mode 100644 index 000000000..082aa0f5c --- /dev/null +++ b/tests/ui/traits/cache-reached-depth-ice.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/cache-reached-depth-ice.rs:43:5 + | +LL | fn test() {} + | ---- predicate +... +LL | test::(); + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/coercion-generic-bad.rs b/tests/ui/traits/coercion-generic-bad.rs new file mode 100644 index 000000000..2e115c732 --- /dev/null +++ b/tests/ui/traits/coercion-generic-bad.rs @@ -0,0 +1,19 @@ +struct Struct { + person: &'static str +} + +trait Trait { + fn f(&self, x: T); +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println!("Hello, {}!", x); + } +} + +fn main() { + let s: Box> = Box::new(Struct { person: "Fred" }); + //~^ ERROR `Struct: Trait` is not satisfied + s.f(1); +} diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr new file mode 100644 index 000000000..93d6770eb --- /dev/null +++ b/tests/ui/traits/coercion-generic-bad.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Struct: Trait` is not satisfied + --> $DIR/coercion-generic-bad.rs:16:36 + | +LL | let s: Box> = Box::new(Struct { person: "Fred" }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Struct` + | + = help: the trait `Trait<&'static str>` is implemented for `Struct` + = note: required for the cast from `Struct` to the object type `dyn Trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/coercion-generic-regions.rs b/tests/ui/traits/coercion-generic-regions.rs new file mode 100644 index 000000000..af478df6d --- /dev/null +++ b/tests/ui/traits/coercion-generic-regions.rs @@ -0,0 +1,19 @@ +struct Struct { + person: &'static str +} + +trait Trait { + fn f(&self, x: T); +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println!("Hello, {}!", x); + } +} + +fn main() { + let person = "Fred".to_string(); + let person: &str = &person; //~ ERROR `person` does not live long enough + let s: Box> = Box::new(Struct { person: person }); +} diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr new file mode 100644 index 000000000..5cfb64901 --- /dev/null +++ b/tests/ui/traits/coercion-generic-regions.stderr @@ -0,0 +1,15 @@ +error[E0597]: `person` does not live long enough + --> $DIR/coercion-generic-regions.rs:17:24 + | +LL | let person: &str = &person; + | ^^^^^^^ + | | + | borrowed value does not live long enough + | assignment requires that `person` is borrowed for `'static` +LL | let s: Box> = Box::new(Struct { person: person }); +LL | } + | - `person` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/traits/coercion-generic.rs b/tests/ui/traits/coercion-generic.rs new file mode 100644 index 000000000..bf4dda495 --- /dev/null +++ b/tests/ui/traits/coercion-generic.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +trait Trait { + fn f(&self, x: T); +} + +#[derive(Copy, Clone)] +struct Struct { + x: isize, + y: isize, +} + +impl Trait<&'static str> for Struct { + fn f(&self, x: &'static str) { + println!("Hi, {}!", x); + } +} + +pub fn main() { + let a = Struct { x: 1, y: 2 }; + let b: Box> = Box::new(a); + b.f("Mary"); + let c: &dyn Trait<&'static str> = &a; + c.f("Joe"); +} diff --git a/tests/ui/traits/coercion.rs b/tests/ui/traits/coercion.rs new file mode 100644 index 000000000..e62742bac --- /dev/null +++ b/tests/ui/traits/coercion.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(unused_variables)] + +use std::io::{self, Write}; + +trait Trait { + fn f(&self); +} + +#[derive(Copy, Clone)] +struct Struct { + x: isize, + y: isize, +} + +impl Trait for Struct { + fn f(&self) { + println!("Hi!"); + } +} + +fn foo(mut a: Box) {} + +pub fn main() { + let a = Struct { x: 1, y: 2 }; + let b: Box = Box::new(a); + b.f(); + let c: &dyn Trait = &a; + c.f(); + + let out = io::stdout(); + foo(Box::new(out)); +} diff --git a/tests/ui/traits/composition-trivial.rs b/tests/ui/traits/composition-trivial.rs new file mode 100644 index 000000000..90e5dcd68 --- /dev/null +++ b/tests/ui/traits/composition-trivial.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Foo { + fn foo(&self); +} + +trait Bar : Foo { + fn bar(&self); +} + +pub fn main() {} diff --git a/tests/ui/traits/conditional-dispatch.rs b/tests/ui/traits/conditional-dispatch.rs new file mode 100644 index 000000000..dd882dce6 --- /dev/null +++ b/tests/ui/traits/conditional-dispatch.rs @@ -0,0 +1,34 @@ +// run-pass +// Test that we are able to resolve conditional dispatch. Here, the +// blanket impl for T:Copy coexists with an impl for Box, because +// Box does not impl Copy. + + +trait Get { + fn get(&self) -> Self; +} + +trait MyCopy { fn copy(&self) -> Self; } +impl MyCopy for u16 { fn copy(&self) -> Self { *self } } +impl MyCopy for u32 { fn copy(&self) -> Self { *self } } +impl MyCopy for i32 { fn copy(&self) -> Self { *self } } +impl MyCopy for Option { fn copy(&self) -> Self { *self } } + +impl Get for T { + fn get(&self) -> T { self.copy() } +} + +impl Get for Box { + fn get(&self) -> Box { Box::new(get_it(&**self)) } +} + +fn get_it(t: &T) -> T { + (*t).get() +} + +fn main() { + assert_eq!(get_it(&1_u32), 1_u32); + assert_eq!(get_it(&1_u16), 1_u16); + assert_eq!(get_it(&Some(1_u16)), Some(1_u16)); + assert_eq!(get_it(&Box::new(1)), Box::new(1)); +} diff --git a/tests/ui/traits/conditional-model-fn.rs b/tests/ui/traits/conditional-model-fn.rs new file mode 100644 index 000000000..ba8867003 --- /dev/null +++ b/tests/ui/traits/conditional-model-fn.rs @@ -0,0 +1,53 @@ +// run-pass +#![allow(unused_imports)] +// A model for how the `Fn` traits could work. You can implement at +// most one of `Go`, `GoMut`, or `GoOnce`, and then the others follow +// automatically. + +// aux-build:go_trait.rs + +extern crate go_trait; + +use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; + +use std::rc::Rc; +use std::cell::Cell; + +struct SomeGoableThing { + counter: Rc> +} + +impl Go for SomeGoableThing { + fn go(&self, arg: isize) { + self.counter.set(self.counter.get() + arg); + } +} + +struct SomeGoOnceableThing { + counter: Rc> +} + +impl GoOnce for SomeGoOnceableThing { + fn go_once(self, arg: isize) { + self.counter.set(self.counter.get() + arg); + } +} + +fn main() { + let counter = Rc::new(Cell::new(0)); + let mut x = SomeGoableThing { counter: counter.clone() }; + + go(&x, 10); + assert_eq!(counter.get(), 10); + + go_mut(&mut x, 100); + assert_eq!(counter.get(), 110); + + go_once(x, 1_000); + assert_eq!(counter.get(), 1_110); + + let x = SomeGoOnceableThing { counter: counter.clone() }; + + go_once(x, 10_000); + assert_eq!(counter.get(), 11_110); +} diff --git a/tests/ui/traits/conservative_impl_trait.rs b/tests/ui/traits/conservative_impl_trait.rs new file mode 100644 index 000000000..4f25e57be --- /dev/null +++ b/tests/ui/traits/conservative_impl_trait.rs @@ -0,0 +1,8 @@ +// build-pass (FIXME(62277): could be check-pass?) +// #39665 + +fn batches(n: &u32) -> impl Iterator { + std::iter::once(n) +} + +fn main() {} diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs new file mode 100644 index 000000000..f031dd9ca --- /dev/null +++ b/tests/ui/traits/copy-guessing.rs @@ -0,0 +1,38 @@ +// run-pass +#![allow(dead_code)] +// "guessing" in trait selection can affect `copy_or_move`. Check that this +// is correctly handled. I am not sure what is the "correct" behaviour, +// but we should at least not ICE. + +use std::mem; + +struct U([u8; 1337]); + +struct S<'a,T:'a>(&'a T); +impl<'a, T> Clone for S<'a, T> { fn clone(&self) -> Self { S(self.0) } } +/// This impl triggers inference "guessing" - S<_>: Copy => _ = U +impl<'a> Copy for S<'a, Option> {} + +fn assert_impls_fnR>(_: &T){} + +fn main() { + let n = None; + let e = S(&n); + let f = || { + // S being copy is critical for this to work + drop(e); + mem::size_of_val(e.0) + }; + assert_impls_fn(&f); + assert_eq!(f(), 1337+1); + + assert_eq!((|| { + // S being Copy is not critical here, but + // we check it anyway. + let n = None; + let e = S(&n); + let ret = mem::size_of_val(e.0); + drop(e); + ret + })(), 1337+1); +} diff --git a/tests/ui/traits/copy-impl-cannot-normalize.rs b/tests/ui/traits/copy-impl-cannot-normalize.rs new file mode 100644 index 000000000..a78ff046e --- /dev/null +++ b/tests/ui/traits/copy-impl-cannot-normalize.rs @@ -0,0 +1,25 @@ +trait TraitFoo { + type Bar; +} + +struct Foo +where + T: TraitFoo, +{ + inner: T::Bar, +} + +impl Clone for Foo +where + T: TraitFoo, + T::Bar: Clone, +{ + fn clone(&self) -> Self { + Self { inner: self.inner.clone() } + } +} + +impl Copy for Foo {} +//~^ ERROR the trait bound `T: TraitFoo` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr new file mode 100644 index 000000000..86c511c08 --- /dev/null +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: TraitFoo` is not satisfied + --> $DIR/copy-impl-cannot-normalize.rs:22:18 + | +LL | impl Copy for Foo {} + | ^^^^^^ the trait `TraitFoo` is not implemented for `T` + | +note: required for `Foo` to implement `Clone` + --> $DIR/copy-impl-cannot-normalize.rs:12:9 + | +LL | impl Clone for Foo + | ^^^^^ ^^^^^^ +LL | where +LL | T: TraitFoo, + | -------- unsatisfied trait bound introduced here +note: required by a bound in `Copy` + --> $SRC_DIR/core/src/marker.rs:LL:COL +help: consider restricting type parameter `T` + | +LL | impl Copy for Foo {} + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr new file mode 100644 index 000000000..edd94d201 --- /dev/null +++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr @@ -0,0 +1,22 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/copy-is-not-modulo-regions.rs:13:21 + | +LL | struct Bar<'lt>(Foo<'lt>); + | -------- this field does not implement `Copy` +... +LL | impl<'any> Copy for Bar<'any> {} + | ^^^^^^^^^ + | +note: the `Copy` impl for `Foo<'any>` requires that `'any: 'static` + --> $DIR/copy-is-not-modulo-regions.rs:10:17 + | +LL | struct Bar<'lt>(Foo<'lt>); + | ^^^^^^^^ +help: consider restricting type parameter `'any` + | +LL | impl<'any: 'static> Copy for Bar<'any> {} + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/copy-is-not-modulo-regions.rs b/tests/ui/traits/copy-is-not-modulo-regions.rs new file mode 100644 index 000000000..adb870237 --- /dev/null +++ b/tests/ui/traits/copy-is-not-modulo-regions.rs @@ -0,0 +1,19 @@ +// revisions: not_static yes_static +//[yes_static] check-pass + +#[derive(Clone)] +struct Foo<'lt>(&'lt ()); + +impl Copy for Foo<'static> {} + +#[derive(Clone)] +struct Bar<'lt>(Foo<'lt>); + +#[cfg(not_static)] +impl<'any> Copy for Bar<'any> {} +//[not_static]~^ the trait `Copy` may not be implemented for this type + +#[cfg(yes_static)] +impl<'any> Copy for Bar<'static> {} + +fn main() {} diff --git a/tests/ui/traits/copy-requires-self-wf.rs b/tests/ui/traits/copy-requires-self-wf.rs new file mode 100644 index 000000000..9abfdfab9 --- /dev/null +++ b/tests/ui/traits/copy-requires-self-wf.rs @@ -0,0 +1,14 @@ +// check-pass + +#[derive(Clone)] +struct A<'a, T>(&'a T); + +impl<'a, T: Copy + 'a> Copy for A<'a, T> {} + +#[derive(Clone)] +struct B<'a, T>(A<'a, T>); + +// `T: '_` should be implied by `WF(B<'_, T>)`. +impl Copy for B<'_, T> {} + +fn main() {} diff --git a/tests/ui/traits/cycle-cache-err-60010.rs b/tests/ui/traits/cycle-cache-err-60010.rs new file mode 100644 index 000000000..94e718317 --- /dev/null +++ b/tests/ui/traits/cycle-cache-err-60010.rs @@ -0,0 +1,74 @@ +// Test that we properly detect the cycle amongst the traits +// here and report an error. + +use std::panic::RefUnwindSafe; + +trait Database { + type Storage; +} +trait HasQueryGroup {} +trait Query { + type Data; +} +trait SourceDatabase { + fn parse(&self) { + loop {} + } +} + +struct ParseQuery; +struct RootDatabase { + _runtime: Runtime, +} +struct Runtime { + _storage: Box, +} +struct SalsaStorage { + _parse: >::Data, + //~^ ERROR overflow +} + +impl Database for RootDatabase { + // This would also be an error if we didn't abort compilation on the error + // above. + type Storage = SalsaStorage; +} +impl HasQueryGroup for RootDatabase {} +impl Query for ParseQuery +where + DB: SourceDatabase, + DB: Database, +{ + type Data = RootDatabase; +} +impl SourceDatabase for T +where + T: RefUnwindSafe, + T: HasQueryGroup, +{ +} + +pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 { + // This is not satisfied: + // + // - `RootDatabase: SourceDatabase` + // - requires `RootDatabase: RefUnwindSafe` + `RootDatabase: HasQueryGroup` + // - `RootDatabase: RefUnwindSafe` + // - requires `Runtime: RefUnwindSafe` + // - `Runtime: RefUnwindSafe` + // - requires `DB::Storage: RefUnwindSafe` (`SalsaStorage: RefUnwindSafe`) + // - `SalsaStorage: RefUnwindSafe` + // - requires `>::Data: RefUnwindSafe`, + // which means `ParseQuery: Query` + // - `ParseQuery: Query` + // - requires `RootDatabase: SourceDatabase`, + // - `RootDatabase: SourceDatabase` is already on the stack, so we have a + // cycle with non-coinductive participants + // + // we used to fail to report an error here because we got the + // caching wrong. + SourceDatabase::parse(db); + 22 +} + +fn main() {} diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr new file mode 100644 index 000000000..eeee99760 --- /dev/null +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -0,0 +1,39 @@ +error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe` + --> $DIR/cycle-cache-err-60010.rs:27:13 + | +LL | _parse: >::Data, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: required because it appears within the type `PhantomData` + = note: required because it appears within the type `Unique` + = note: required because it appears within the type `Box` +note: required because it appears within the type `Runtime` + --> $DIR/cycle-cache-err-60010.rs:23:8 + | +LL | struct Runtime { + | ^^^^^^^ +note: required because it appears within the type `RootDatabase` + --> $DIR/cycle-cache-err-60010.rs:20:8 + | +LL | struct RootDatabase { + | ^^^^^^^^^^^^ +note: required for `RootDatabase` to implement `SourceDatabase` + --> $DIR/cycle-cache-err-60010.rs:44:9 + | +LL | impl SourceDatabase for T + | ^^^^^^^^^^^^^^ ^ +LL | where +LL | T: RefUnwindSafe, + | ------------- unsatisfied trait bound introduced here +note: required for `ParseQuery` to implement `Query` + --> $DIR/cycle-cache-err-60010.rs:37:10 + | +LL | impl Query for ParseQuery + | ^^^^^^^^^ ^^^^^^^^^^ +LL | where +LL | DB: SourceDatabase, + | -------------- unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/cycle-generic-bound.rs b/tests/ui/traits/cycle-generic-bound.rs new file mode 100644 index 000000000..9241f3789 --- /dev/null +++ b/tests/ui/traits/cycle-generic-bound.rs @@ -0,0 +1,11 @@ +// run-pass +// Regression test for #15477. This test just needs to compile. + +// pretty-expanded FIXME #23616 + +trait Chromosome> { +} + +impl Chromosome for i32 { } + +fn main() { } diff --git a/tests/ui/traits/cycle-type-trait.rs b/tests/ui/traits/cycle-type-trait.rs new file mode 100644 index 000000000..c62d01403 --- /dev/null +++ b/tests/ui/traits/cycle-type-trait.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// Test a case where a supertrait references a type that references +// the original trait. This poses no problem at the moment. + +// pretty-expanded FIXME #23616 + +trait Chromosome: Get> { +} + +trait Get { + fn get(&self) -> A; +} + +struct Struct { c: C } + +impl Chromosome for i32 { } + +impl Get> for i32 { + fn get(&self) -> Struct { + Struct { c: *self } + } +} + +fn main() { } diff --git a/tests/ui/traits/default-method/auxiliary/xc.rs b/tests/ui/traits/default-method/auxiliary/xc.rs new file mode 100644 index 000000000..0fb26af80 --- /dev/null +++ b/tests/ui/traits/default-method/auxiliary/xc.rs @@ -0,0 +1,40 @@ +pub struct Something { pub x: isize } + +pub trait A { + fn f(&self) -> isize; + fn g(&self) -> isize { 10 } + fn h(&self) -> isize { 11 } + fn lurr(x: &Self, y: &Self) -> isize { x.g() + y.h() } +} + + +impl A for isize { + fn f(&self) -> isize { 10 } +} + +impl A for Something { + fn f(&self) -> isize { 10 } +} + +pub trait B { + fn thing(&self, x: T, y: U) -> (T, U) { (x, y) } + fn staticthing(_z: &Self, x: T, y: U) -> (T, U) { (x, y) } +} + +impl B for isize { } +impl B for bool { } + + + +pub trait TestEquality { + fn test_eq(&self, rhs: &Self) -> bool; + fn test_neq(&self, rhs: &Self) -> bool { + !self.test_eq(rhs) + } +} + +impl TestEquality for isize { + fn test_eq(&self, rhs: &isize) -> bool { + *self == *rhs + } +} diff --git a/tests/ui/traits/default-method/auxiliary/xc_2.rs b/tests/ui/traits/default-method/auxiliary/xc_2.rs new file mode 100644 index 000000000..979233820 --- /dev/null +++ b/tests/ui/traits/default-method/auxiliary/xc_2.rs @@ -0,0 +1,17 @@ +// aux-build:xc.rs + +extern crate xc as aux; +use aux::A; + +pub struct a_struct { pub x: isize } + +impl A for a_struct { + fn f(&self) -> isize { 10 } +} + +// This function will need to get inlined, and badness may result. +pub fn welp(x: A) -> A { + let a = a_struct { x: 0 }; + a.g(); + x +} diff --git a/tests/ui/traits/default-method/bound-subst.rs b/tests/ui/traits/default-method/bound-subst.rs new file mode 100644 index 000000000..6a5d5c8ba --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst.rs @@ -0,0 +1,18 @@ +// run-pass + + +trait A { + fn g(&self, x: T, y: U) -> (T, U) { (x, y) } +} + +impl A for i32 { } +impl A for u32 { } + +fn f>(i: V, j: T, k: U) -> (T, U) { + i.g(j, k) +} + +pub fn main () { + assert_eq!(f(0, 1, 2), (1, 2)); + assert_eq!(f(0, 1, 2), (1, 2)); +} diff --git a/tests/ui/traits/default-method/bound-subst2.rs b/tests/ui/traits/default-method/bound-subst2.rs new file mode 100644 index 000000000..78eabba2d --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst2.rs @@ -0,0 +1,16 @@ +// run-pass + + +trait A { + fn g(&self, x: T) -> T { x } +} + +impl A for isize { } + +fn f>(i: V, j: T) -> T { + i.g(j) +} + +pub fn main () { + assert_eq!(f(0, 2), 2); +} diff --git a/tests/ui/traits/default-method/bound-subst3.rs b/tests/ui/traits/default-method/bound-subst3.rs new file mode 100644 index 000000000..dd39dec4b --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst3.rs @@ -0,0 +1,17 @@ +// run-pass + + +trait A { + fn g(&self, x: T, y: T) -> (T, T) { (x, y) } +} + +impl A for isize { } + +fn f(i: V, j: T, k: T) -> (T, T) { + i.g(j, k) +} + +pub fn main () { + assert_eq!(f(0, 1, 2), (1, 2)); + assert_eq!(f(0, 1u8, 2u8), (1u8, 2u8)); +} diff --git a/tests/ui/traits/default-method/bound-subst4.rs b/tests/ui/traits/default-method/bound-subst4.rs new file mode 100644 index 000000000..ef1330645 --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst4.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_variables)] + + +trait A { + fn g(&self, x: usize) -> usize { x } + fn h(&self, x: T) { } +} + +impl A for isize { } + +fn f>(i: V, j: usize) -> usize { + i.g(j) +} + +pub fn main () { + assert_eq!(f::(0, 2), 2); + assert_eq!(f::(0, 2), 2); +} diff --git a/tests/ui/traits/default-method/bound.rs b/tests/ui/traits/default-method/bound.rs new file mode 100644 index 000000000..0855a9db8 --- /dev/null +++ b/tests/ui/traits/default-method/bound.rs @@ -0,0 +1,16 @@ +// run-pass + + +trait A { + fn g(&self) -> isize { 10 } +} + +impl A for isize { } + +fn f(i: T) { + assert_eq!(i.g(), 10); +} + +pub fn main () { + f(0); +} diff --git a/tests/ui/traits/default-method/macro.rs b/tests/ui/traits/default-method/macro.rs new file mode 100644 index 000000000..2b50ee9b4 --- /dev/null +++ b/tests/ui/traits/default-method/macro.rs @@ -0,0 +1,20 @@ +// run-pass + + +trait Foo { + fn bar(&self) -> String { + format!("test") + } +} + +enum Baz { + Quux +} + +impl Foo for Baz { +} + +pub fn main() { + let q = Baz::Quux; + assert_eq!(q.bar(), "test".to_string()); +} diff --git a/tests/ui/traits/default-method/mut.rs b/tests/ui/traits/default-method/mut.rs new file mode 100644 index 000000000..5f8e983b0 --- /dev/null +++ b/tests/ui/traits/default-method/mut.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] + +trait Foo { + fn foo(&self, mut v: isize) { v = 1; } +} + +pub fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs new file mode 100644 index 000000000..5ba2f5ce3 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(eq, neq)] +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +struct T0; +struct T1; +struct T2; +struct T3; + +impl Equal for T0 { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Equal for T1 { + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T2 { + fn eq(&self, _other: &Self) -> bool { + true + } + + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T3 {} +//~^ not all trait items implemented, missing one of: `eq`, `neq` + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr new file mode 100644 index 000000000..5a4dd1388 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.stderr @@ -0,0 +1,15 @@ +error[E0046]: not all trait items implemented, missing one of: `eq`, `neq` + --> $DIR/rustc_must_implement_one_of.rs:41:1 + | +LL | impl Equal for T3 {} + | ^^^^^^^^^^^^^^^^^ missing one of `eq`, `neq` in implementation + | +note: required because of this annotation + --> $DIR/rustc_must_implement_one_of.rs:3:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs new file mode 100644 index 000000000..8db5fa615 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs @@ -0,0 +1,19 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, a)] +//~^ functions names are duplicated +trait Trait { + fn a() {} +} + +#[rustc_must_implement_one_of(b, a, a, c, b, c)] +//~^ functions names are duplicated +//~| functions names are duplicated +//~| functions names are duplicated +trait Trait1 { + fn a() {} + fn b() {} + fn c() {} +} + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr new file mode 100644 index 000000000..cd1476a6e --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr @@ -0,0 +1,34 @@ +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, a)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: all `#[rustc_must_implement_one_of]` arguments must be unique + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs new file mode 100644 index 000000000..ec2995872 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs @@ -0,0 +1,13 @@ +#[rustc_must_implement_one_of(eq, neq)] +//~^ the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr new file mode 100644 index 000000000..228bc3e35 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std + --> $DIR/rustc_must_implement_one_of_gated.rs:1:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs new file mode 100644 index 000000000..b1b91966c --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -0,0 +1,46 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, b)] +//~^ function not found in this trait +//~| function not found in this trait +trait Tr0 {} + +#[rustc_must_implement_one_of(a, b)] +//~^ function not found in this trait +trait Tr1 { + fn a() {} +} + +#[rustc_must_implement_one_of(a)] +//~^ the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +trait Tr2 { + fn a() {} +} + +#[rustc_must_implement_one_of] +//~^ malformed `rustc_must_implement_one_of` attribute input +trait Tr3 {} + +#[rustc_must_implement_one_of(A, B)] +trait Tr4 { + const A: u8 = 1; //~ not a function + + type B; //~ not a function +} + +#[rustc_must_implement_one_of(a, b)] +trait Tr5 { + fn a(); //~ function doesn't have a default implementation + + fn b(); //~ function doesn't have a default implementation +} + +#[rustc_must_implement_one_of(abc, xyz)] +//~^ attribute should be applied to a trait +fn function() {} + +#[rustc_must_implement_one_of(abc, xyz)] +//~^ attribute should be applied to a trait +struct Struct {} + +fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr new file mode 100644 index 000000000..38e692521 --- /dev/null +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -0,0 +1,100 @@ +error: malformed `rustc_must_implement_one_of` attribute input + --> $DIR/rustc_must_implement_one_of_misuse.rs:20:1 + | +LL | #[rustc_must_implement_one_of] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]` + +error: attribute should be applied to a trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:38:1 + | +LL | #[rustc_must_implement_one_of(abc, xyz)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | fn function() {} + | ---------------- not a trait + +error: attribute should be applied to a trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:42:1 + | +LL | #[rustc_must_implement_one_of(abc, xyz)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | struct Struct {} + | ---------------- not a trait + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 + | +LL | #[rustc_must_implement_one_of(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: not a function + --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 + | +LL | const A: u8 = 1; + | ^^^^^^^^^^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names + +error: not a function + --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5 + | +LL | type B; + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names + +error: function doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5 + | +LL | fn a(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5 + | +LL | fn b(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/traits/default-method/self.rs b/tests/ui/traits/default-method/self.rs new file mode 100644 index 000000000..cdf4d1e14 --- /dev/null +++ b/tests/ui/traits/default-method/self.rs @@ -0,0 +1,18 @@ +// run-pass + + +trait Cat { + fn meow(&self) -> bool; + fn scratch(&self) -> bool { self.purr() } + fn purr(&self) -> bool { true } +} + +impl Cat for isize { + fn meow(&self) -> bool { + self.scratch() + } +} + +pub fn main() { + assert!(5.meow()); +} diff --git a/tests/ui/traits/default-method/supervtable.rs b/tests/ui/traits/default-method/supervtable.rs new file mode 100644 index 000000000..939ad5135 --- /dev/null +++ b/tests/ui/traits/default-method/supervtable.rs @@ -0,0 +1,28 @@ +// run-pass + + +// Tests that we can call a function bounded over a supertrait from +// a default method + +fn require_y(x: T) -> isize { x.y() } + +trait Y { + fn y(self) -> isize; +} + + +trait Z: Y + Sized { + fn x(self) -> isize { + require_y(self) + } +} + +impl Y for isize { + fn y(self) -> isize { self } +} + +impl Z for isize {} + +pub fn main() { + assert_eq!(12.x(), 12); +} diff --git a/tests/ui/traits/default-method/trivial.rs b/tests/ui/traits/default-method/trivial.rs new file mode 100644 index 000000000..dc41938ec --- /dev/null +++ b/tests/ui/traits/default-method/trivial.rs @@ -0,0 +1,21 @@ +// run-pass + + +trait Cat { + fn meow(&self) -> bool; + fn scratch(&self) -> bool; + fn purr(&self) -> bool { true } +} + +impl Cat for isize { + fn meow(&self) -> bool { + self.scratch() + } + fn scratch(&self) -> bool { + self.purr() + } +} + +pub fn main() { + assert!(5.meow()); +} diff --git a/tests/ui/traits/default-method/xc-2.rs b/tests/ui/traits/default-method/xc-2.rs new file mode 100644 index 000000000..1de61dcf8 --- /dev/null +++ b/tests/ui/traits/default-method/xc-2.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:xc.rs +// aux-build:xc_2.rs + + + +extern crate xc as aux; +extern crate xc_2 as aux2; +use aux::A; +use aux2::{a_struct, welp}; + + +pub fn main () { + + let a = a_struct { x: 0 }; + let b = a_struct { x: 1 }; + + assert_eq!(0.g(), 10); + assert_eq!(a.g(), 10); + assert_eq!(a.h(), 11); + assert_eq!(b.g(), 10); + assert_eq!(b.h(), 11); + assert_eq!(A::lurr(&a, &b), 21); + + welp(&0); +} diff --git a/tests/ui/traits/default-method/xc.rs b/tests/ui/traits/default-method/xc.rs new file mode 100644 index 000000000..76a1573d6 --- /dev/null +++ b/tests/ui/traits/default-method/xc.rs @@ -0,0 +1,81 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// aux-build:xc.rs + + +extern crate xc as aux; +use aux::{A, TestEquality, Something}; +use aux::B; + +fn f(i: T) { + assert_eq!(i.g(), 10); +} + +fn welp(i: isize, _x: &T) -> isize { + i.g() +} + +mod stuff { + pub struct thing { pub x: isize } +} + +impl A for stuff::thing { + fn f(&self) -> isize { 10 } +} + +fn g>(i: V, j: T, k: U) -> (T, U) { + i.thing(j, k) +} + +fn eq(lhs: &T, rhs: &T) -> bool { + lhs.test_eq(rhs) +} +fn neq(lhs: &T, rhs: &T) -> bool { + lhs.test_neq(rhs) +} + + +impl TestEquality for stuff::thing { + fn test_eq(&self, rhs: &stuff::thing) -> bool { + //self.x.test_eq(&rhs.x) + eq(&self.x, &rhs.x) + } +} + + +pub fn main() { + // Some tests of random things + f(0); + + assert_eq!(A::lurr(&0, &1), 21); + + let a = stuff::thing { x: 0 }; + let b = stuff::thing { x: 1 }; + let c = Something { x: 1 }; + + assert_eq!(0.g(), 10); + assert_eq!(a.g(), 10); + assert_eq!(a.h(), 11); + assert_eq!(c.h(), 11); + + assert_eq!(0.thing(3.14f64, 1), (3.14f64, 1)); + assert_eq!(B::staticthing(&0, 3.14f64, 1), (3.14f64, 1)); + assert_eq!(B::::staticthing::(&0, 3.14, 1), (3.14, 1)); + + assert_eq!(g(0, 3.14f64, 1), (3.14f64, 1)); + assert_eq!(g(false, 3.14f64, 1), (3.14, 1)); + + + // Trying out a real one + assert!(12.test_neq(&10)); + assert!(!10.test_neq(&10)); + assert!(a.test_neq(&b)); + assert!(!a.test_neq(&a)); + + assert!(neq(&12, &10)); + assert!(!neq(&10, &10)); + assert!(neq(&a, &b)); + assert!(!neq(&a, &a)); +} diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs new file mode 100644 index 000000000..9a444be50 --- /dev/null +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs @@ -0,0 +1,20 @@ +struct Thing(X); + +trait Method { + fn method(self, _: i32) -> T; +} + +impl Method for Thing { + fn method(self, _: i32) -> i32 { 0 } +} + +impl Method for Thing { + fn method(self, _: i32) -> u32 { 0 } +} + +fn main() { + let thing = Thing(true); + thing.method(42); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} diff --git a/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr new file mode 100644 index 000000000..57b2587ae --- /dev/null +++ b/tests/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -0,0 +1,34 @@ +error[E0282]: type annotations needed + --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 + | +LL | thing.method(42); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | as Method>::method(thing, 42); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 + | +LL | thing.method(42); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | as Method>::method(thing, 42); + | +++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/duplicate-methods.rs b/tests/ui/traits/duplicate-methods.rs new file mode 100644 index 000000000..1f9bdf56f --- /dev/null +++ b/tests/ui/traits/duplicate-methods.rs @@ -0,0 +1,6 @@ +trait Foo { + fn orange(&self); + fn orange(&self); //~ ERROR the name `orange` is defined multiple times +} + +fn main() {} diff --git a/tests/ui/traits/duplicate-methods.stderr b/tests/ui/traits/duplicate-methods.stderr new file mode 100644 index 000000000..6aa88d0df --- /dev/null +++ b/tests/ui/traits/duplicate-methods.stderr @@ -0,0 +1,13 @@ +error[E0428]: the name `orange` is defined multiple times + --> $DIR/duplicate-methods.rs:3:5 + | +LL | fn orange(&self); + | ----------------- previous definition of the value `orange` here +LL | fn orange(&self); + | ^^^^^^^^^^^^^^^^^ `orange` redefined here + | + = note: `orange` must be defined only once in the value namespace of this trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/dyn-trait.rs b/tests/ui/traits/dyn-trait.rs new file mode 100644 index 000000000..e1c1a8de5 --- /dev/null +++ b/tests/ui/traits/dyn-trait.rs @@ -0,0 +1,17 @@ +// run-pass +// ignore-pretty `dyn ::foo` parses differently in the current edition + +use std::fmt::Display; + +static BYTE: u8 = 33; + +fn main() { + let x: &(dyn 'static + Display) = &BYTE; + let y: Box = Box::new(BYTE); + let _: &dyn (Display) = &BYTE; + let _: &dyn (::std::fmt::Display) = &BYTE; + let xstr = format!("{}", x); + let ystr = format!("{}", y); + assert_eq!(xstr, "33"); + assert_eq!(ystr, "33"); +} diff --git a/tests/ui/traits/early-vtbl-resolution.rs b/tests/ui/traits/early-vtbl-resolution.rs new file mode 100644 index 000000000..f4b69c140 --- /dev/null +++ b/tests/ui/traits/early-vtbl-resolution.rs @@ -0,0 +1,19 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait thing { + fn foo(&self) -> Option; +} +impl thing for isize { + fn foo(&self) -> Option { None } +} +fn foo_func>(x: B) -> Option { x.foo() } + +struct A { a: isize } + +pub fn main() { + let _x: Option = foo_func(0); +} diff --git a/tests/ui/traits/elaborate-type-region.rs b/tests/ui/traits/elaborate-type-region.rs new file mode 100644 index 000000000..03aef0184 --- /dev/null +++ b/tests/ui/traits/elaborate-type-region.rs @@ -0,0 +1,49 @@ +// run-pass +#![allow(dead_code)] + +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized> { + fn foo() where T: 'a; +} + +// [U]: 'a => U: 'a +impl<'a, U> Master<'a, [U]> for () { + fn foo() where U: 'a { } +} + +// &'b U: 'a => 'b: 'a, U: 'a +impl<'a, 'b, U> Master<'a, &'b U> for () { + fn foo() where 'b: 'a, U: 'a { } +} + +// &'b [U]: 'a => 'b: 'a, U: 'a +impl<'a, 'b, U> Master<'a, &'b [U]> for () { + fn foo() where 'b: 'a, U: 'a { } +} + +// Foo<'b>: 'a => 'b: 'a +struct Foo<'a> { x: &'a () } +impl<'a, 'b> Master<'a, Foo<'b>> for () { + fn foo() where 'b: 'a { } +} + +// Bar<'b, T>: 'a => 'b: 'a, T: 'a +struct Bar<'a, T: 'a> { x: &'a T } +impl<'a, 'b, T> Master<'a, Bar<'b, T>> for () { + fn foo() where 'b: 'a, T: 'a { } +} + +// fn(T): 'a => T: 'a +impl<'a, T> Master<'a, fn(T)> for () { + fn foo() where T: 'a { } +} + +// fn() -> T: 'a => T: 'a +impl<'a, T> Master<'a, fn() -> T> for () { + fn foo() where T: 'a { } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs b/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs new file mode 100644 index 000000000..3413db6a6 --- /dev/null +++ b/tests/ui/traits/false-ambiguity-where-clause-builtin-bound.rs @@ -0,0 +1,16 @@ +// run-pass +// Test that we do not error out because of a (False) ambiguity +// between the builtin rules for Sized and the where clause. Issue +// #20959. + +// pretty-expanded FIXME #23616 + +fn foo(x: Option) + where Option : Sized +{ + let _y = x; +} + +fn main() { + foo(Some(22)); +} diff --git a/tests/ui/traits/fmt-pointer-trait.rs b/tests/ui/traits/fmt-pointer-trait.rs new file mode 100644 index 000000000..b7876b9bd --- /dev/null +++ b/tests/ui/traits/fmt-pointer-trait.rs @@ -0,0 +1,24 @@ +// run-pass +use std::ptr; +use std::rc::Rc; +use std::sync::Arc; + +fn main() { + let p: *const u8 = ptr::null(); + let rc = Rc::new(1usize); + let arc = Arc::new(1usize); + let b = Box::new("hi"); + + let _ = format!("{:p}{:p}{:p}", + rc, arc, b); + + if cfg!(target_pointer_width = "32") { + assert_eq!(format!("{:#p}", p), + "0x00000000"); + } else { + assert_eq!(format!("{:#p}", p), + "0x0000000000000000"); + } + assert_eq!(format!("{:p}", p), + "0x0"); +} diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.rs b/tests/ui/traits/fn-trait-cast-diagnostic.rs new file mode 100644 index 000000000..e20aa210e --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.rs @@ -0,0 +1,26 @@ +// There are two different instances to check that even if +// the trait is implemented for the output of a function, +// it will still be displayed if the function itself implements a trait. +trait Foo {} + +impl Foo for fn() -> bool {} +impl Foo for bool {} + +fn example() -> bool { + true +} + +trait NoOtherFoo {} + +impl NoOtherFoo for fn() -> bool {} + +fn do_on_foo(v: impl Foo) {} +fn do_on_single_foo(v: impl NoOtherFoo) {} + +fn main() { + do_on_foo(example); + //~^ ERROR the trait bound + + do_on_single_foo(example); + //~^ ERROR the trait bound +} diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.stderr b/tests/ui/traits/fn-trait-cast-diagnostic.stderr new file mode 100644 index 000000000..6851dcdd5 --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:21:15 + | +LL | do_on_foo(example); + | --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:17:22 + | +LL | fn do_on_foo(v: impl Foo) {} + | ^^^ required by this bound in `do_on_foo` +help: use parentheses to call this function + | +LL | do_on_foo(example()); + | ++ +help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_foo(example as fn() -> bool); + | +++++++++++++++ + +error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:24:22 + | +LL | do_on_single_foo(example); + | ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_single_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:18:29 + | +LL | fn do_on_single_foo(v: impl NoOtherFoo) {} + | ^^^^^^^^^^ required by this bound in `do_on_single_foo` +help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_single_foo(example as fn() -> bool); + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/generic.rs b/tests/ui/traits/generic.rs new file mode 100644 index 000000000..80efe1c93 --- /dev/null +++ b/tests/ui/traits/generic.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(non_camel_case_types)] + + + +trait to_str { + fn to_string_(&self) -> String; +} +impl to_str for isize { + fn to_string_(&self) -> String { self.to_string() } +} +impl to_str for String { + fn to_string_(&self) -> String { self.clone() } +} +impl to_str for () { + fn to_string_(&self) -> String { "()".to_string() } +} + +trait map { + fn map(&self, f: F) -> Vec where F: FnMut(&T) -> U; +} +impl map for Vec { + fn map(&self, mut f: F) -> Vec where F: FnMut(&T) -> U { + let mut r = Vec::new(); + for i in self { + r.push(f(i)); + } + r + } +} + +fn foo>(x: T) -> Vec { + x.map(|_e| "hi".to_string() ) +} +fn bar>(x: T) -> Vec { + x.map(|_e| _e.to_string_() ) +} + +pub fn main() { + assert_eq!(foo(vec![1]), ["hi".to_string()]); + assert_eq!(bar:: >(vec![4, 5]), ["4".to_string(), "5".to_string()]); + assert_eq!(bar:: >(vec!["x".to_string(), "y".to_string()]), + ["x".to_string(), "y".to_string()]); + assert_eq!(bar::<(), Vec<()>>(vec![()]), ["()".to_string()]); +} diff --git a/tests/ui/traits/ignore-err-impls.rs b/tests/ui/traits/ignore-err-impls.rs new file mode 100644 index 000000000..67e880b00 --- /dev/null +++ b/tests/ui/traits/ignore-err-impls.rs @@ -0,0 +1,9 @@ +pub struct S; + +trait Generic {} + +impl<'a, T> Generic<&'a T> for S {} +impl Generic for S {} +//~^ ERROR cannot find type `Type` in this scope + +fn main() {} diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr new file mode 100644 index 000000000..45bd533b5 --- /dev/null +++ b/tests/ui/traits/ignore-err-impls.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Type` in this scope + --> $DIR/ignore-err-impls.rs:6:14 + | +LL | impl Generic for S {} + | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl Generic for S {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/impl-1.rs b/tests/ui/traits/impl-1.rs new file mode 100644 index 000000000..d22ac72d1 --- /dev/null +++ b/tests/ui/traits/impl-1.rs @@ -0,0 +1,16 @@ +// Test calling methods on an impl for a bare trait. This test checks that the +// trait impl is only applied to a trait object, not concrete types which implement +// the trait. + +trait T {} + +impl<'a> dyn T + 'a { + fn foo(&self) {} +} + +impl T for i32 {} + +fn main() { + let x = &42i32; + x.foo(); //~ERROR: no method named `foo` found +} diff --git a/tests/ui/traits/impl-1.stderr b/tests/ui/traits/impl-1.stderr new file mode 100644 index 000000000..7694e3f5c --- /dev/null +++ b/tests/ui/traits/impl-1.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `foo` found for reference `&i32` in the current scope + --> $DIR/impl-1.rs:15:7 + | +LL | x.foo(); + | ^^^ method not found in `&i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/impl-2.rs b/tests/ui/traits/impl-2.rs new file mode 100644 index 000000000..804ffec12 --- /dev/null +++ b/tests/ui/traits/impl-2.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// pretty-expanded FIXME #23616 + +pub mod Foo { + pub trait Trait { + fn foo(&self); + } +} + +mod Bar { + impl<'a> dyn (::Foo::Trait) + 'a { + fn bar(&self) { self.foo() } + } +} + +fn main() {} diff --git a/tests/ui/traits/impl-bounds-checking.rs b/tests/ui/traits/impl-bounds-checking.rs new file mode 100644 index 000000000..5e65a27bf --- /dev/null +++ b/tests/ui/traits/impl-bounds-checking.rs @@ -0,0 +1,14 @@ +pub trait Clone2 { + fn clone(&self) -> Self; +} + + +trait Getter { + fn get(&self) -> T; +} + +impl Getter for isize { //~ ERROR `isize: Clone2` is not satisfied + fn get(&self) -> isize { *self } +} + +fn main() { } diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr new file mode 100644 index 000000000..1f969efe1 --- /dev/null +++ b/tests/ui/traits/impl-bounds-checking.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `isize: Clone2` is not satisfied + --> $DIR/impl-bounds-checking.rs:10:24 + | +LL | impl Getter for isize { + | ^^^^^ the trait `Clone2` is not implemented for `isize` + | +note: required by a bound in `Getter` + --> $DIR/impl-bounds-checking.rs:6:17 + | +LL | trait Getter { + | ^^^^^^ required by this bound in `Getter` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/impl-can-not-have-untraitful-items.rs b/tests/ui/traits/impl-can-not-have-untraitful-items.rs new file mode 100644 index 000000000..0c885447b --- /dev/null +++ b/tests/ui/traits/impl-can-not-have-untraitful-items.rs @@ -0,0 +1,9 @@ +trait A { } + +impl A for isize { + const BAR: () = (); //~ ERROR const `BAR` is not a member of trait `A` + type Baz = (); //~ ERROR type `Baz` is not a member of trait `A` + fn foo(&self) { } //~ ERROR method `foo` is not a member of trait `A` +} + +fn main() { } diff --git a/tests/ui/traits/impl-can-not-have-untraitful-items.stderr b/tests/ui/traits/impl-can-not-have-untraitful-items.stderr new file mode 100644 index 000000000..7f56f34ea --- /dev/null +++ b/tests/ui/traits/impl-can-not-have-untraitful-items.stderr @@ -0,0 +1,22 @@ +error[E0438]: const `BAR` is not a member of trait `A` + --> $DIR/impl-can-not-have-untraitful-items.rs:4:5 + | +LL | const BAR: () = (); + | ^^^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error[E0437]: type `Baz` is not a member of trait `A` + --> $DIR/impl-can-not-have-untraitful-items.rs:5:5 + | +LL | type Baz = (); + | ^^^^^^^^^^^^^^ not a member of trait `A` + +error[E0407]: method `foo` is not a member of trait `A` + --> $DIR/impl-can-not-have-untraitful-items.rs:6:5 + | +LL | fn foo(&self) { } + | ^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0407, E0437, E0438. +For more information about an error, try `rustc --explain E0407`. diff --git a/tests/ui/traits/impl-different-num-params.rs b/tests/ui/traits/impl-different-num-params.rs new file mode 100644 index 000000000..53400622d --- /dev/null +++ b/tests/ui/traits/impl-different-num-params.rs @@ -0,0 +1,12 @@ +trait Foo { + fn bar(&self, x: usize) -> Self; +} +impl Foo for isize { + fn bar(&self) -> isize { + //~^ ERROR method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2 + *self + } +} + +fn main() { +} diff --git a/tests/ui/traits/impl-different-num-params.stderr b/tests/ui/traits/impl-different-num-params.stderr new file mode 100644 index 000000000..910ba3510 --- /dev/null +++ b/tests/ui/traits/impl-different-num-params.stderr @@ -0,0 +1,12 @@ +error[E0050]: method `bar` has 1 parameter but the declaration in trait `Foo::bar` has 2 + --> $DIR/impl-different-num-params.rs:5:12 + | +LL | fn bar(&self, x: usize) -> Self; + | --------------- trait requires 2 parameters +... +LL | fn bar(&self) -> isize { + | ^^^^^ expected 2 parameters, found 1 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0050`. diff --git a/tests/ui/traits/impl-evaluation-order.rs b/tests/ui/traits/impl-evaluation-order.rs new file mode 100644 index 000000000..57809d89a --- /dev/null +++ b/tests/ui/traits/impl-evaluation-order.rs @@ -0,0 +1,39 @@ +// Regression test for #79902 + +// Check that evaluation (which is used to determine whether to copy a type in +// MIR building) evaluates bounds from normalizing an impl after evaluating +// any bounds on the impl. + +// check-pass + +trait A { + type B; +} +trait M {} + +struct G(*const T, *const U); + +impl Clone for G { + fn clone(&self) -> Self { + G { ..*self } + } +} + +impl Copy for G +where + T: A, + U: A, +{ +} + +impl A for () { + type B = (); +} + +fn is_m(_: T) {} + +fn main() { + let x = G(&(), &()); + drop(x); + drop(x); +} diff --git a/tests/ui/traits/impl-for-module.rs b/tests/ui/traits/impl-for-module.rs new file mode 100644 index 000000000..9004627c5 --- /dev/null +++ b/tests/ui/traits/impl-for-module.rs @@ -0,0 +1,11 @@ +mod a { +} + +trait A { +} + +impl A for a { //~ ERROR expected type, found module +} + +fn main() { +} diff --git a/tests/ui/traits/impl-for-module.stderr b/tests/ui/traits/impl-for-module.stderr new file mode 100644 index 000000000..6ec4083b5 --- /dev/null +++ b/tests/ui/traits/impl-for-module.stderr @@ -0,0 +1,12 @@ +error[E0573]: expected type, found module `a` + --> $DIR/impl-for-module.rs:7:12 + | +LL | trait A { + | ------- similarly named trait `A` defined here +... +LL | impl A for a { + | ^ help: a trait with a similar name exists: `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/traits/impl-implicit-trait.rs b/tests/ui/traits/impl-implicit-trait.rs new file mode 100644 index 000000000..fac2bcce2 --- /dev/null +++ b/tests/ui/traits/impl-implicit-trait.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum option_ { + none_, + some_(T), +} + +impl option_ { + pub fn foo(&self) -> bool { true } +} + +enum option__ { + none__, + some__(isize) +} + +impl option__ { + pub fn foo(&self) -> bool { true } +} + +pub fn main() { +} diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.rs b/tests/ui/traits/impl-inherent-prefer-over-trait.rs new file mode 100644 index 000000000..827607888 --- /dev/null +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.rs @@ -0,0 +1,30 @@ +// run-pass + +struct Foo; + +trait Trait { + fn bar(&self); +} + +// Inherent impls should be preferred over trait ones. +impl Foo { + fn bar(&self) {} +} + +impl dyn Trait { + fn baz(_: &Foo) {} +} + +impl Trait for Foo { + fn bar(&self) { panic!("wrong method called!") } +} + +fn main() { + Foo.bar(); + Foo::bar(&Foo); + ::bar(&Foo); + + // Should work even if Trait::baz doesn't exist. + // N.B: `::bar` would be ambiguous. + ::baz(&Foo); +} diff --git a/tests/ui/traits/impl-method-mismatch.rs b/tests/ui/traits/impl-method-mismatch.rs new file mode 100644 index 000000000..62580755c --- /dev/null +++ b/tests/ui/traits/impl-method-mismatch.rs @@ -0,0 +1,13 @@ +trait Mumbo { + fn jumbo(&self, x: &usize) -> usize; +} + +impl Mumbo for usize { + // Cannot have a larger effect than the trait: + unsafe fn jumbo(&self, x: &usize) { *self + *x; } + //~^ ERROR method `jumbo` has an incompatible type for trait + //~| expected signature `fn + //~| found signature `unsafe fn +} + +fn main() {} diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr new file mode 100644 index 000000000..252b5aff9 --- /dev/null +++ b/tests/ui/traits/impl-method-mismatch.stderr @@ -0,0 +1,17 @@ +error[E0053]: method `jumbo` has an incompatible type for trait + --> $DIR/impl-method-mismatch.rs:7:5 + | +LL | unsafe fn jumbo(&self, x: &usize) { *self + *x; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn + | +note: type in trait + --> $DIR/impl-method-mismatch.rs:2:5 + | +LL | fn jumbo(&self, x: &usize) -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn(&usize, &usize) -> usize` + found signature `unsafe fn(&usize, &usize)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.rs b/tests/ui/traits/impl-object-overlap-issue-23853.rs new file mode 100644 index 000000000..e490967b6 --- /dev/null +++ b/tests/ui/traits/impl-object-overlap-issue-23853.rs @@ -0,0 +1,18 @@ +// run-pass +// Test that we are able to compile the case where both a blanket impl +// and the object type itself supply the required trait obligation. +// In this case, the blanket impl for `Foo` applies to any type, +// including `Bar`, but the object type `Bar` also implicitly supplies +// this context. + +trait Foo { fn dummy(&self) { } } + +trait Bar: Foo { } + +impl Foo for T { } + +fn want_foo() { } + +fn main() { + want_foo::(); +} diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs new file mode 100644 index 000000000..05b9db972 --- /dev/null +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.rs @@ -0,0 +1,31 @@ +// Check that when we test the supertrait we ensure consistent use of +// lifetime parameters. In this case, implementing T2<'a,'b> requires +// an impl of T1<'a>, but we have an impl of T1<'b>. + +trait T1<'x> { + fn x(&self) -> &'x isize; +} + +trait T2<'x, 'y> : T1<'x> { + fn y(&self) -> &'y isize; +} + +struct S<'a, 'b> { + a: &'a isize, + b: &'b isize +} + +impl<'a,'b> T1<'b> for S<'a, 'b> { + fn x(&self) -> &'b isize { + self.b + } +} + +impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { //~ ERROR cannot infer an appropriate lifetime + fn y(&self) -> &'b isize { + self.b + } +} + +pub fn main() { +} diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr new file mode 100644 index 000000000..1bace8ab2 --- /dev/null +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^ +note: ...but the lifetime must also be valid for the lifetime `'b` as defined here... + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^ +note: ...so that the types are compatible + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 + | +LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { + | ^^^^^^^^^ + = note: expected `T1<'a>` + found `T1<'_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs new file mode 100644 index 000000000..f512d91eb --- /dev/null +++ b/tests/ui/traits/impl.rs @@ -0,0 +1,41 @@ +// run-pass +// Test calling methods on an impl for a bare trait. + +// aux-build:traitimpl.rs + +extern crate traitimpl; +use traitimpl::Bar; + +static mut COUNT: usize = 1; + +trait T { + fn t(&self) {} +} + +impl<'a> dyn T+'a { + fn foo(&self) { + unsafe { COUNT *= 2; } + } + fn bar() { + unsafe { COUNT *= 3; } + } +} + +impl T for isize {} + +struct Foo; +impl<'a> Bar<'a> for Foo {} + +fn main() { + let x: &dyn T = &42; + + x.foo(); + ::foo(x); + ::bar(); + + unsafe { assert_eq!(COUNT, 12); } + + // Cross-crait case + let x: &dyn Bar = &Foo; + x.bar(); +} diff --git a/tests/ui/traits/impl_trait_as_trait_return_position.rs b/tests/ui/traits/impl_trait_as_trait_return_position.rs new file mode 100644 index 000000000..c3325fd80 --- /dev/null +++ b/tests/ui/traits/impl_trait_as_trait_return_position.rs @@ -0,0 +1,17 @@ +// check-pass + +trait A { + type Foo; +} + +impl A for T { + type Foo = (); +} + +fn foo() -> impl std::borrow::Borrow<::Foo> { + () +} + +fn main() { + foo(); +} diff --git a/tests/ui/traits/inductive-overflow/lifetime.rs b/tests/ui/traits/inductive-overflow/lifetime.rs new file mode 100644 index 000000000..bf536d21c --- /dev/null +++ b/tests/ui/traits/inductive-overflow/lifetime.rs @@ -0,0 +1,33 @@ +// Test that we don't hit the recursion limit for short cycles involving lifetimes. + +// Shouldn't hit this, we should realize that we're in a cycle sooner. +#![recursion_limit="20"] + +trait NotAuto {} +trait Y { + type P; +} + +impl<'a> Y for C<'a> { + type P = Box>>; +} + +struct C<'a>(&'a ()); +struct X(T::P); + +impl NotAuto for Box {} //~ NOTE: required +//~^ NOTE unsatisfied trait bound introduced here +impl NotAuto for X where T::P: NotAuto {} +impl<'a> NotAuto for C<'a> {} + +fn is_send() {} +//~^ NOTE: required +//~| NOTE: required + +fn main() { + // Should only be a few notes. + is_send::>>(); + //~^ ERROR overflow evaluating + //~| 3 redundant requirements hidden + //~| required for +} diff --git a/tests/ui/traits/inductive-overflow/lifetime.stderr b/tests/ui/traits/inductive-overflow/lifetime.stderr new file mode 100644 index 000000000..357e59991 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/lifetime.stderr @@ -0,0 +1,24 @@ +error[E0275]: overflow evaluating the requirement `X>: NotAuto` + --> $DIR/lifetime.rs:29:5 + | +LL | is_send::>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `Box>>` to implement `NotAuto` + --> $DIR/lifetime.rs:18:18 + | +LL | impl NotAuto for Box {} + | ------- ^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 3 redundant requirements hidden + = note: required for `X>` to implement `NotAuto` +note: required by a bound in `is_send` + --> $DIR/lifetime.rs:23:15 + | +LL | fn is_send() {} + | ^^^^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/simultaneous.rs b/tests/ui/traits/inductive-overflow/simultaneous.rs new file mode 100644 index 000000000..40ac92146 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/simultaneous.rs @@ -0,0 +1,20 @@ +// Regression test for #33344, initial version. This example allowed +// arbitrary trait bounds to be synthesized. + +trait Tweedledum: IntoIterator {} +trait Tweedledee: IntoIterator {} + +impl Tweedledee for T {} +impl Tweedledum for T {} + +trait Combo: IntoIterator {} +impl Combo for T {} + +fn is_ee(t: T) { + t.into_iter(); +} + +fn main() { + is_ee(4); + //~^ ERROR overflow evaluating the requirement `{integer}: Tweedle +} diff --git a/tests/ui/traits/inductive-overflow/simultaneous.stderr b/tests/ui/traits/inductive-overflow/simultaneous.stderr new file mode 100644 index 000000000..e3b4ec07d --- /dev/null +++ b/tests/ui/traits/inductive-overflow/simultaneous.stderr @@ -0,0 +1,22 @@ +error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum` + --> $DIR/simultaneous.rs:18:5 + | +LL | is_ee(4); + | ^^^^^ + | +note: required for `{integer}` to implement `Combo` + --> $DIR/simultaneous.rs:11:34 + | +LL | impl Combo for T {} + | ---------- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `is_ee` + --> $DIR/simultaneous.rs:13:13 + | +LL | fn is_ee(t: T) { + | ^^^^^ required by this bound in `is_ee` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs new file mode 100644 index 000000000..5fea47a1b --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.rs @@ -0,0 +1,18 @@ +// Auto-trait-based version of #29859, supertrait version. Test that using +// a simple auto trait `..` impl alone still doesn't allow arbitrary bounds +// to be synthesized. + +#![feature(auto_traits)] +#![feature(negative_impls)] + +auto trait Magic: Copy {} //~ ERROR E0568 + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); //~ ERROR + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr new file mode 100644 index 000000000..3ec288d13 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -0,0 +1,35 @@ +error[E0568]: auto traits cannot have super traits or lifetime bounds + --> $DIR/supertrait-auto-trait.rs:8:17 + | +LL | auto trait Magic: Copy {} + | -----^^^^^^ help: remove the super traits or lifetime bounds + | | + | auto trait cannot have super traits or lifetime bounds + +error[E0277]: the trait bound `NoClone: Copy` is not satisfied + --> $DIR/supertrait-auto-trait.rs:16:23 + | +LL | let (a, b) = copy(NoClone); + | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone` + | | + | required by a bound introduced by this call + | +note: required for `NoClone` to implement `Magic` + --> $DIR/supertrait-auto-trait.rs:8:12 + | +LL | auto trait Magic: Copy {} + | ^^^^^ +note: required by a bound in `copy` + --> $DIR/supertrait-auto-trait.rs:10:12 + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ^^^^^ required by this bound in `copy` +help: consider annotating `NoClone` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0568. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inductive-overflow/supertrait.rs b/tests/ui/traits/inductive-overflow/supertrait.rs new file mode 100644 index 000000000..c7aa4d90f --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait.rs @@ -0,0 +1,15 @@ +// Regression test for #29859, supertrait version. This example +// allowed arbitrary trait bounds to be synthesized. + +trait Magic: Copy {} +impl Magic for T {} + +fn copy(x: T) -> (T, T) { (x, x) } + +#[derive(Debug)] +struct NoClone; + +fn main() { + let (a, b) = copy(NoClone); //~ ERROR E0275 + println!("{:?} {:?}", a, b); +} diff --git a/tests/ui/traits/inductive-overflow/supertrait.stderr b/tests/ui/traits/inductive-overflow/supertrait.stderr new file mode 100644 index 000000000..b537ecf17 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/supertrait.stderr @@ -0,0 +1,22 @@ +error[E0275]: overflow evaluating the requirement `NoClone: Magic` + --> $DIR/supertrait.rs:13:18 + | +LL | let (a, b) = copy(NoClone); + | ^^^^ + | +note: required for `NoClone` to implement `Magic` + --> $DIR/supertrait.rs:5:16 + | +LL | impl Magic for T {} + | ----- ^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `copy` + --> $DIR/supertrait.rs:7:12 + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ^^^^^ required by this bound in `copy` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/inductive-overflow/two-traits.rs b/tests/ui/traits/inductive-overflow/two-traits.rs new file mode 100644 index 000000000..463b55d85 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/two-traits.rs @@ -0,0 +1,22 @@ +// Regression test for #29859, initial version. This example allowed +// arbitrary trait bounds to be synthesized. + +// Trait that you want all types to implement. +use std::marker::{Sync as Trait}; + +pub trait Magic { + type X: Trait; +} +impl Magic for T { + type X = Self; + //~^ ERROR E0277 +} + +fn check() {} + +fn wizard() { check::<::X>(); } + +fn main() { + wizard::<*mut ()>(); //~ ERROR E0275 + // check::<*mut ()>(); +} diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr new file mode 100644 index 000000000..0d0bf8861 --- /dev/null +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -0,0 +1,32 @@ +error[E0277]: `T` cannot be shared between threads safely + --> $DIR/two-traits.rs:11:14 + | +LL | type X = Self; + | ^^^^ `T` cannot be shared between threads safely + | +note: required by a bound in `Magic::X` + --> $DIR/two-traits.rs:8:13 + | +LL | type X: Trait; + | ^^^^^ required by this bound in `Magic::X` +help: consider further restricting this bound + | +LL | impl Magic for T { + | +++++++++++++++++++ + +error[E0275]: overflow evaluating the requirement `*mut (): Magic` + --> $DIR/two-traits.rs:20:5 + | +LL | wizard::<*mut ()>(); + | ^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `wizard` + --> $DIR/two-traits.rs:17:14 + | +LL | fn wizard() { check::<::X>(); } + | ^^^^^ required by this bound in `wizard` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0275, E0277. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/infer-from-object-issue-26952.rs b/tests/ui/traits/infer-from-object-issue-26952.rs new file mode 100644 index 000000000..ed258dbb2 --- /dev/null +++ b/tests/ui/traits/infer-from-object-issue-26952.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that when we match a trait reference like `Foo: Foo<_#0t>`, +// we unify with `_#0t` with `A`. In this code, if we failed to do +// that, then you get an unconstrained type-variable in `call`. +// +// Also serves as a regression test for issue #26952, though the test +// was derived from another reported regression with the same cause. + +use std::marker::PhantomData; + +trait Trait { fn foo(&self); } + +struct Type { a: PhantomData } + +fn as_trait(t: &Type) -> &dyn Trait { loop { } } + +fn want+?Sized>(t: &T) { } + +fn call(p: Type) { + let q = as_trait(&p); + want(q); // parameter A to `want` *would* be unconstrained +} + +fn main() { } diff --git a/tests/ui/traits/inherent-method-order.rs b/tests/ui/traits/inherent-method-order.rs new file mode 100644 index 000000000..f632ae8a9 --- /dev/null +++ b/tests/ui/traits/inherent-method-order.rs @@ -0,0 +1,25 @@ +// run-pass + +struct Foo; + +impl Foo { + #[allow(dead_code)] + fn foo(self) { + panic!("wrong method!") + } +} + +trait Trait { + fn foo(self); +} + +impl<'a,'b,'c> Trait for &'a &'b &'c Foo { + fn foo(self) { + // ok + } +} + +fn main() { + let x = &(&(&Foo)); + x.foo(); +} diff --git a/tests/ui/traits/inheritance/auto-xc-2.rs b/tests/ui/traits/inheritance/auto-xc-2.rs new file mode 100644 index 000000000..f2130228d --- /dev/null +++ b/tests/ui/traits/inheritance/auto-xc-2.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:auto_xc_2.rs + + +extern crate auto_xc_2 as aux; + +// aux defines impls of Foo, Bar and Baz for A +use aux::{Foo, Bar, Baz, A}; + +// We want to extend all Foo, Bar, Bazes to Quuxes +pub trait Quux: Foo + Bar + Baz { } +impl Quux for T { } + +fn f(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auto-xc.rs b/tests/ui/traits/inheritance/auto-xc.rs new file mode 100644 index 000000000..3d5ae182a --- /dev/null +++ b/tests/ui/traits/inheritance/auto-xc.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// aux-build:auto_xc.rs + + +extern crate auto_xc as aux; + +use aux::{Foo, Bar, Baz, Quux}; + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +fn f(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auto.rs b/tests/ui/traits/inheritance/auto.rs new file mode 100644 index 000000000..0be67a55e --- /dev/null +++ b/tests/ui/traits/inheritance/auto.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +// Testing that this impl turns A into a Quux, because +// A is already a Foo Bar Baz + +impl Quux for T { } + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } + +trait Quux: Foo + Bar + Baz { } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +fn f(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs new file mode 100644 index 000000000..9af26cb2e --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs @@ -0,0 +1,7 @@ +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } + +pub trait Quux: Foo + Bar + Baz { } + +impl Quux for T { } diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs new file mode 100644 index 000000000..e9327676d --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs @@ -0,0 +1,9 @@ +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } + +pub struct A { pub x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } diff --git a/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs new file mode 100644 index 000000000..a25704412 --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs @@ -0,0 +1,38 @@ +use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; + +pub trait MyNum : Add + Sub + Mul + PartialEq + Clone { +} + +#[derive(Clone, Debug)] +pub struct MyInt { + pub val: isize +} + +impl Add for MyInt { + type Output = MyInt; + + fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl Sub for MyInt { + type Output = MyInt; + + fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) } +} + +impl Mul for MyInt { + type Output = MyInt; + + fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) } +} + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } diff --git a/tests/ui/traits/inheritance/auxiliary/xc_call.rs b/tests/ui/traits/inheritance/auxiliary/xc_call.rs new file mode 100644 index 000000000..b76c52e62 --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/xc_call.rs @@ -0,0 +1,11 @@ +pub trait Foo { + fn f(&self) -> isize; +} + +pub struct A { + pub x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} diff --git a/tests/ui/traits/inheritance/basic.rs b/tests/ui/traits/inheritance/basic.rs new file mode 100644 index 000000000..5bfa60b1a --- /dev/null +++ b/tests/ui/traits/inheritance/basic.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } + +trait Quux: Foo + Bar + Baz { } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } +impl Quux for A {} + +fn f(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/call-bound-inherited.rs b/tests/ui/traits/inheritance/call-bound-inherited.rs new file mode 100644 index 000000000..37c2ff63c --- /dev/null +++ b/tests/ui/traits/inheritance/call-bound-inherited.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +// Call a function on Foo, given a T: Bar +fn gg(a: &T) -> isize { + a.f() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(gg(a), 10); +} diff --git a/tests/ui/traits/inheritance/call-bound-inherited2.rs b/tests/ui/traits/inheritance/call-bound-inherited2.rs new file mode 100644 index 000000000..8576d29f2 --- /dev/null +++ b/tests/ui/traits/inheritance/call-bound-inherited2.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } +trait Baz : Bar { fn h(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +// Call a function on Foo, given a T: Baz, +// which is inherited via Bar +fn gg(a: &T) -> isize { + a.f() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(gg(a), 10); +} diff --git a/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs new file mode 100644 index 000000000..25159c1ad --- /dev/null +++ b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// Testing that we can cast to a subtrait and call subtrait +// methods. Not testing supertrait methods + + +trait Foo { + fn f(&self) -> isize; +} + +trait Bar : Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} + +impl Bar for A { + fn g(&self) -> isize { 20 } +} + +pub fn main() { + let a = &A { x: 3 }; + let afoo = a as &dyn Foo; + let abar = a as &dyn Bar; + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); +} diff --git a/tests/ui/traits/inheritance/cast.rs b/tests/ui/traits/inheritance/cast.rs new file mode 100644 index 000000000..9070b9d1f --- /dev/null +++ b/tests/ui/traits/inheritance/cast.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// Testing that supertrait methods can be called on subtrait object types + + +trait Foo { + fn f(&self) -> isize; +} + +trait Bar : Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} + +impl Bar for A { + fn g(&self) -> isize { 20 } +} + +pub fn main() { + let a = &A { x: 3 }; + let afoo = a as &dyn Foo; + let abar = a as &dyn Bar; + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); + assert_eq!(abar.f(), 10); +} diff --git a/tests/ui/traits/inheritance/cross-trait-call-xc.rs b/tests/ui/traits/inheritance/cross-trait-call-xc.rs new file mode 100644 index 000000000..99fbb5c61 --- /dev/null +++ b/tests/ui/traits/inheritance/cross-trait-call-xc.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:xc_call.rs + + +extern crate xc_call as aux; + +use aux::Foo; + +trait Bar : Foo { + fn g(&self) -> isize; +} + +impl Bar for aux::A { + fn g(&self) -> isize { self.f() } +} + +pub fn main() { + let a = &aux::A { x: 3 }; + assert_eq!(a.g(), 10); +} diff --git a/tests/ui/traits/inheritance/cross-trait-call.rs b/tests/ui/traits/inheritance/cross-trait-call.rs new file mode 100644 index 000000000..512c928ca --- /dev/null +++ b/tests/ui/traits/inheritance/cross-trait-call.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } + +impl Bar for A { + // Testing that this impl can call the impl of Foo + fn g(&self) -> isize { self.f() } +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(a.g(), 10); +} diff --git a/tests/ui/traits/inheritance/diamond.rs b/tests/ui/traits/inheritance/diamond.rs new file mode 100644 index 000000000..32ad0fb4d --- /dev/null +++ b/tests/ui/traits/inheritance/diamond.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +// B and C both require A, so D does as well, twice, but that's just fine + + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } +trait D: B + C { fn d(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } +impl D for S { fn d(&self) -> isize { 40 } } + +fn f(x: &T) { + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); + assert_eq!(x.d(), 40); +} + +pub fn main() { + let value = &S { bogus: () }; + f(value); +} diff --git a/tests/ui/traits/inheritance/multiple-inheritors.rs b/tests/ui/traits/inheritance/multiple-inheritors.rs new file mode 100644 index 000000000..77ecbd8eb --- /dev/null +++ b/tests/ui/traits/inheritance/multiple-inheritors.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } + +// Both B and C inherit from A +fn f(x: &T) { + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); +} + +pub fn main() { + f(&S { bogus: () }) +} diff --git a/tests/ui/traits/inheritance/multiple-params.rs b/tests/ui/traits/inheritance/multiple-params.rs new file mode 100644 index 000000000..8ff5ba541 --- /dev/null +++ b/tests/ui/traits/inheritance/multiple-params.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } + +// Multiple type params, multiple levels of inheritance +fn f(x: &X, y: &Y, z: &Z) { + assert_eq!(x.a(), 10); + assert_eq!(y.a(), 10); + assert_eq!(y.b(), 20); + assert_eq!(z.a(), 10); + assert_eq!(z.c(), 30); +} + +pub fn main() { + let s = &S { bogus: () }; + f(s, s, s); +} diff --git a/tests/ui/traits/inheritance/num.rs b/tests/ui/traits/inheritance/num.rs new file mode 100644 index 000000000..3d63d78ca --- /dev/null +++ b/tests/ui/traits/inheritance/num.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +pub trait NumExt: PartialEq + PartialOrd {} + +pub trait FloatExt: NumExt {} + +fn greater_than_one(n: &T) -> bool { loop {} } +fn greater_than_one_float(n: &T) -> bool { loop {} } + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num0.rs b/tests/ui/traits/inheritance/num0.rs new file mode 100644 index 000000000..cee52542d --- /dev/null +++ b/tests/ui/traits/inheritance/num0.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +// Extending Num and using inherited static methods + +// pretty-expanded FIXME #23616 + +use std::cmp::PartialOrd; + +pub trait NumCast: Sized { + fn from(i: i32) -> Option; +} + +pub trait Num { + fn from_int(i: isize) -> Self; + fn gt(&self, other: &Self) -> bool; +} + +pub trait NumExt: NumCast + PartialOrd { } + +fn greater_than_one(n: &T) -> bool { + n.gt(&NumCast::from(1).unwrap()) +} + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num1.rs b/tests/ui/traits/inheritance/num1.rs new file mode 100644 index 000000000..663dd3a5e --- /dev/null +++ b/tests/ui/traits/inheritance/num1.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub trait NumCast: Sized { + fn from(i: i32) -> Option; +} + +pub trait NumExt: NumCast + PartialOrd { } + +fn greater_than_one(n: &T) -> bool { + *n > NumCast::from(1).unwrap() +} + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num2.rs b/tests/ui/traits/inheritance/num2.rs new file mode 100644 index 000000000..b713c66a3 --- /dev/null +++ b/tests/ui/traits/inheritance/num2.rs @@ -0,0 +1,86 @@ +// run-pass +// A more complex example of numeric extensions + +pub trait TypeExt {} + +impl TypeExt for u8 {} +impl TypeExt for u16 {} +impl TypeExt for u32 {} +impl TypeExt for u64 {} +impl TypeExt for usize {} + +impl TypeExt for i8 {} +impl TypeExt for i16 {} +impl TypeExt for i32 {} +impl TypeExt for i64 {} +impl TypeExt for isize {} + +impl TypeExt for f32 {} +impl TypeExt for f64 {} + + +pub trait NumExt: TypeExt + PartialEq + PartialOrd {} + +impl NumExt for u8 {} +impl NumExt for u16 {} +impl NumExt for u32 {} +impl NumExt for u64 {} +impl NumExt for usize {} + +impl NumExt for i8 {} +impl NumExt for i16 {} +impl NumExt for i32 {} +impl NumExt for i64 {} +impl NumExt for isize {} + +impl NumExt for f32 {} +impl NumExt for f64 {} + + +pub trait UnSignedExt: NumExt {} + +impl UnSignedExt for u8 {} +impl UnSignedExt for u16 {} +impl UnSignedExt for u32 {} +impl UnSignedExt for u64 {} +impl UnSignedExt for usize {} + + +pub trait SignedExt: NumExt {} + +impl SignedExt for i8 {} +impl SignedExt for i16 {} +impl SignedExt for i32 {} +impl SignedExt for i64 {} +impl SignedExt for isize {} + +impl SignedExt for f32 {} +impl SignedExt for f64 {} + + +pub trait IntegerExt: NumExt {} + +impl IntegerExt for u8 {} +impl IntegerExt for u16 {} +impl IntegerExt for u32 {} +impl IntegerExt for u64 {} +impl IntegerExt for usize {} + +impl IntegerExt for i8 {} +impl IntegerExt for i16 {} +impl IntegerExt for i32 {} +impl IntegerExt for i64 {} +impl IntegerExt for isize {} + + +pub trait FloatExt: NumExt {} + +impl FloatExt for f32 {} +impl FloatExt for f64 {} + + +fn test_float_ext(n: T) { println!("{}", n < n) } + +pub fn main() { + test_float_ext(1f32); +} diff --git a/tests/ui/traits/inheritance/num3.rs b/tests/ui/traits/inheritance/num3.rs new file mode 100644 index 000000000..c40be6f83 --- /dev/null +++ b/tests/ui/traits/inheritance/num3.rs @@ -0,0 +1,19 @@ +// run-pass +pub trait NumCast: Sized { + fn from(i: i32) -> Option; +} + +pub trait NumExt: PartialEq + PartialOrd + NumCast {} + +impl NumExt for f32 {} +impl NumCast for f32 { + fn from(i: i32) -> Option { Some(i as f32) } +} + +fn num_eq_one(n: T) { + println!("{}", n == NumCast::from(1).unwrap()) +} + +pub fn main() { + num_eq_one(1f32); // you need to actually use the function to trigger the ICE +} diff --git a/tests/ui/traits/inheritance/num5.rs b/tests/ui/traits/inheritance/num5.rs new file mode 100644 index 000000000..f478618f7 --- /dev/null +++ b/tests/ui/traits/inheritance/num5.rs @@ -0,0 +1,26 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait NumCast: Sized { + fn from(i: i32) -> Option; +} + +pub trait NumExt: PartialEq + NumCast {} + +impl NumExt for f32 {} +impl NumExt for isize {} + +impl NumCast for f32 { + fn from(i: i32) -> Option { Some(i as f32) } +} +impl NumCast for isize { + fn from(i: i32) -> Option { Some(i as isize) } +} + +fn num_eq_one() -> T { + NumCast::from(1).unwrap() +} + +pub fn main() { + num_eq_one::(); // you need to actually use the function to trigger the ICE +} diff --git a/tests/ui/traits/inheritance/overloading-simple.rs b/tests/ui/traits/inheritance/overloading-simple.rs new file mode 100644 index 000000000..c306aa2cd --- /dev/null +++ b/tests/ui/traits/inheritance/overloading-simple.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +use std::cmp::PartialEq; + +trait MyNum : PartialEq { } + +#[derive(Debug)] +struct MyInt { val: isize } + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn f(x: T, y: T) -> bool { + return x == y; +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y, z) = (mi(3), mi(5), mi(3)); + assert!(x != y); + assert_eq!(x, z); +} diff --git a/tests/ui/traits/inheritance/overloading-xc-exe.rs b/tests/ui/traits/inheritance/overloading-xc-exe.rs new file mode 100644 index 000000000..08778061b --- /dev/null +++ b/tests/ui/traits/inheritance/overloading-xc-exe.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:overloading_xc.rs + + +extern crate overloading_xc; +use overloading_xc::{MyNum, MyInt}; + +fn f(x: T, y: T) -> (T, T, T) { + return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let (a, b, c) = f(x, y); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); +} diff --git a/tests/ui/traits/inheritance/overloading.rs b/tests/ui/traits/inheritance/overloading.rs new file mode 100644 index 000000000..083643e82 --- /dev/null +++ b/tests/ui/traits/inheritance/overloading.rs @@ -0,0 +1,47 @@ +// run-pass +use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; + +trait MyNum : Add + Sub + Mul + PartialEq + Clone { } + +#[derive(Clone, Debug)] +struct MyInt { val: isize } + +impl Add for MyInt { + type Output = MyInt; + + fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl Sub for MyInt { + type Output = MyInt; + + fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) } +} + +impl Mul for MyInt { + type Output = MyInt; + + fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) } +} + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn f(x: T, y: T) -> (T, T, T) { + return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let (a, b, c) = f(x, y); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); +} diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs new file mode 100644 index 000000000..727897d20 --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs @@ -0,0 +1,43 @@ +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test then that when we don't give +// enough information to pick between these, no selection is made. In +// this particular case, the two choices are i64/u64 -- so when we use +// an integer literal, we wind up falling this literal back to i32. +// See also `run-pass/trait-repeated-supertrait.rs`. + +trait CompareTo { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo + CompareTo { +} + +impl CompareTo for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &dyn CompareToInts) -> bool { + c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo` is not satisfied +} + +fn with_trait(c: &C) -> bool { + c.same_as(22) //~ ERROR `C: CompareTo` is not satisfied +} + +fn with_ufcs1(c: &C) -> bool { + ::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo` is not satisfi +} + +fn with_ufcs2(c: &C) -> bool { + CompareTo::same_as(c, 22) //~ ERROR `C: CompareTo` is not satisfied +} + +fn main() { + assert_eq!(22_i64.same_as(22), true); //~ ERROR `i64: CompareTo` is not satisfied +} diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr new file mode 100644 index 000000000..656e0d0bf --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:26:15 + | +LL | c.same_as(22) + | ------- ^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo`: + > + > + +error[E0277]: the trait bound `C: CompareTo` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:30:15 + | +LL | c.same_as(22) + | ------- ^^ the trait `CompareTo` is not implemented for `C` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | fn with_trait>(c: &C) -> bool { + | ++++++++++++++++ + +error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:34:37 + | +LL | ::same_as(c, 22) + | ---------------------------- ^^ the trait `CompareTo` is not implemented for `dyn CompareToInts` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo`: + > + > + +error[E0277]: the trait bound `C: CompareTo` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:38:27 + | +LL | CompareTo::same_as(c, 22) + | ------------------ ^^ the trait `CompareTo` is not implemented for `C` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | fn with_ufcs2>(c: &C) -> bool { + | ++++++++++++++++ + +error[E0277]: the trait bound `i64: CompareTo` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:42:31 + | +LL | assert_eq!(22_i64.same_as(22), true); + | ------- ^^ the trait `CompareTo` is not implemented for `i64` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo`: + > + > + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inheritance/repeated-supertrait.rs b/tests/ui/traits/inheritance/repeated-supertrait.rs new file mode 100644 index 000000000..cb2581ffa --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait.rs @@ -0,0 +1,48 @@ +// run-pass +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test that we can invoke the +// various methods in various ways successfully. +// See also `ui/traits/trait-repeated-supertrait-ambig.rs`. + + +trait CompareTo { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo + CompareTo { +} + +impl CompareTo for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &dyn CompareToInts) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_trait(c: &C) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_ufcs1(c: &C) -> bool { + ::same_as(c, 22_i64) && ::same_as(c, 22_u64) +} + +fn with_ufcs2(c: &C) -> bool { + CompareTo::same_as(c, 22_i64) && CompareTo::same_as(c, 22_u64) +} + +fn main() { + assert_eq!(22_i64.same_as(22_i64), true); + assert_eq!(22_i64.same_as(22_u64), true); + assert_eq!(with_trait(&22), true); + assert_eq!(with_obj(&22), true); + assert_eq!(with_ufcs1(&22), true); + assert_eq!(with_ufcs2(&22), true); +} diff --git a/tests/ui/traits/inheritance/self-in-supertype.rs b/tests/ui/traits/inheritance/self-in-supertype.rs new file mode 100644 index 000000000..e8a2bd791 --- /dev/null +++ b/tests/ui/traits/inheritance/self-in-supertype.rs @@ -0,0 +1,62 @@ +// run-pass +// Test for issue #4183: use of Self in supertraits. + +pub static FUZZY_EPSILON: f64 = 0.1; + +pub trait FuzzyEq { + fn fuzzy_eq(&self, other: &Self) -> bool; + fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool; +} + +trait Float: Sized+FuzzyEq { + fn two_pi() -> Self; +} + +impl FuzzyEq for f32 { + fn fuzzy_eq(&self, other: &f32) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32)) + } + + fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool { + (*self - *other).abs() < *epsilon + } +} + +impl Float for f32 { + fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 } +} + +impl FuzzyEq for f64 { + fn fuzzy_eq(&self, other: &f64) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64)) + } + + fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool { + (*self - *other).abs() < *epsilon + } +} + +impl Float for f64 { + fn two_pi() -> f64 { 6.28318530717958647692528676655900576_f64 } +} + +fn compare(f1: F) -> bool { + let f2 = Float::two_pi(); + f1.fuzzy_eq(&f2) +} + +pub fn main() { + assert!(compare::(6.28318530717958647692528676655900576)); + assert!(compare::(6.29)); + assert!(compare::(6.3)); + assert!(compare::(6.19)); + assert!(!compare::(7.28318530717958647692528676655900576)); + assert!(!compare::(6.18)); + + assert!(compare::(6.28318530717958647692528676655900576)); + assert!(compare::(6.29)); + assert!(compare::(6.3)); + assert!(compare::(6.19)); + assert!(!compare::(7.28318530717958647692528676655900576)); + assert!(!compare::(6.18)); +} diff --git a/tests/ui/traits/inheritance/self.rs b/tests/ui/traits/inheritance/self.rs new file mode 100644 index 000000000..5f2559f48 --- /dev/null +++ b/tests/ui/traits/inheritance/self.rs @@ -0,0 +1,29 @@ +// run-pass +trait Foo { + fn f(&self, x: &T); +} + +trait Bar : Sized + Foo { + fn g(&self); +} + +struct S { + x: isize +} + +impl Foo for S { + fn f(&self, x: &S) { + println!("{}", x.x); + } +} + +impl Bar for S { + fn g(&self) { + self.f(self); + } +} + +pub fn main() { + let s = S { x: 1 }; + s.g(); +} diff --git a/tests/ui/traits/inheritance/simple.rs b/tests/ui/traits/inheritance/simple.rs new file mode 100644 index 000000000..ca3a284e5 --- /dev/null +++ b/tests/ui/traits/inheritance/simple.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +fn ff(a: &T) -> isize { + a.f() +} + +fn gg(a: &T) -> isize { + a.g() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(ff(a), 10); + assert_eq!(gg(a), 20); +} diff --git a/tests/ui/traits/inheritance/static.rs b/tests/ui/traits/inheritance/static.rs new file mode 100644 index 000000000..16218fbd2 --- /dev/null +++ b/tests/ui/traits/inheritance/static.rs @@ -0,0 +1,26 @@ +// run-pass + +pub trait MyNum { + fn from_int(_: isize) -> Self; +} + +pub trait NumExt: MyNum { } + +struct S { v: isize } + +impl MyNum for S { + fn from_int(i: isize) -> S { + S { + v: i + } + } +} + +impl NumExt for S { } + +fn greater_than_one() -> T { MyNum::from_int(1) } + +pub fn main() { + let v: S = greater_than_one(); + assert_eq!(v.v, 1); +} diff --git a/tests/ui/traits/inheritance/static2.rs b/tests/ui/traits/inheritance/static2.rs new file mode 100644 index 000000000..bc78e1e23 --- /dev/null +++ b/tests/ui/traits/inheritance/static2.rs @@ -0,0 +1,29 @@ +// run-pass +pub trait MyEq {} + +pub trait MyNum { + fn from_int(_: isize) -> Self; +} + +pub trait NumExt: MyEq + MyNum { } + +struct S { v: isize } + +impl MyEq for S { } + +impl MyNum for S { + fn from_int(i: isize) -> S { + S { + v: i + } + } +} + +impl NumExt for S { } + +fn greater_than_one() -> T { MyNum::from_int(1) } + +pub fn main() { + let v: S = greater_than_one(); + assert_eq!(v.v, 1); +} diff --git a/tests/ui/traits/inheritance/subst.rs b/tests/ui/traits/inheritance/subst.rs new file mode 100644 index 000000000..b2b650366 --- /dev/null +++ b/tests/ui/traits/inheritance/subst.rs @@ -0,0 +1,27 @@ +// run-pass + +pub trait Add { + fn add(&self, rhs: &RHS) -> Result; +} + +trait MyNum : Sized + Add { } + +struct MyInt { val: isize } + +impl Add for MyInt { + fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl MyNum for MyInt {} + +fn f(x: T, y: T) -> T { + return x.add(&y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let z = f(x, y); + assert_eq!(z.val, 8) +} diff --git a/tests/ui/traits/inheritance/subst2.rs b/tests/ui/traits/inheritance/subst2.rs new file mode 100644 index 000000000..ccc9628c7 --- /dev/null +++ b/tests/ui/traits/inheritance/subst2.rs @@ -0,0 +1,37 @@ +// run-pass + +trait Panda { + fn chomp(&self, bamboo: &T) -> T; +} + +trait Add: Panda { + fn add(&self, rhs: &RHS) -> Result; +} + +trait MyNum : Sized + Add { } + +struct MyInt { val: isize } + +impl Panda for MyInt { + fn chomp(&self, bamboo: &MyInt) -> MyInt { + mi(self.val + bamboo.val) + } +} + +impl Add for MyInt { + fn add(&self, other: &MyInt) -> MyInt { self.chomp(other) } +} + +impl MyNum for MyInt {} + +fn f(x: T, y: T) -> T { + return x.add(&y).chomp(&y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let z = f(x, y); + assert_eq!(z.val, 13); +} diff --git a/tests/ui/traits/inheritance/visibility.rs b/tests/ui/traits/inheritance/visibility.rs new file mode 100644 index 000000000..6ad864926 --- /dev/null +++ b/tests/ui/traits/inheritance/visibility.rs @@ -0,0 +1,20 @@ +// run-pass + +mod traits { + pub trait Foo { fn f(&self) -> isize; } + + impl Foo for isize { fn f(&self) -> isize { 10 } } +} + +trait Quux: traits::Foo { } +impl Quux for T { } + +// Foo is not in scope but because Quux is we can still access +// Foo's methods on a Quux bound typaram +fn f(x: &T) { + assert_eq!(x.f(), 10); +} + +pub fn main() { + f(&0) +} diff --git a/tests/ui/traits/invalid_operator_trait.rs b/tests/ui/traits/invalid_operator_trait.rs new file mode 100644 index 000000000..7ea3b0d5b --- /dev/null +++ b/tests/ui/traits/invalid_operator_trait.rs @@ -0,0 +1,23 @@ +#![crate_type = "lib"] +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang="sized"] +pub trait Sized { + // Empty. +} + +#[lang = "add"] +trait Add { + type Output; + + fn add(self, _: RHS) -> Self::Output; + //~^ ERROR `add` must not have any generic parameters +} + +#[allow(unreachable_code)] +fn ice(a: usize) { + let r = loop {}; + r = r + a; +} diff --git a/tests/ui/traits/invalid_operator_trait.stderr b/tests/ui/traits/invalid_operator_trait.stderr new file mode 100644 index 000000000..8c6e36959 --- /dev/null +++ b/tests/ui/traits/invalid_operator_trait.stderr @@ -0,0 +1,8 @@ +error: `add` must not have any generic parameters + --> $DIR/invalid_operator_trait.rs:15:5 + | +LL | fn add(self, _: RHS) -> Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/issue-102989.rs b/tests/ui/traits/issue-102989.rs new file mode 100644 index 000000000..216cd78e5 --- /dev/null +++ b/tests/ui/traits/issue-102989.rs @@ -0,0 +1,14 @@ +// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" + +#![feature(lang_items)] +#[lang="sized"] +trait Sized { } //~ ERROR found duplicate lang item `sized` + +fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR cannot find type `Struct` in this scope + let x = x << 1; + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/tests/ui/traits/issue-102989.stderr b/tests/ui/traits/issue-102989.stderr new file mode 100644 index 000000000..7d0098fe8 --- /dev/null +++ b/tests/ui/traits/issue-102989.stderr @@ -0,0 +1,34 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/issue-102989.rs:7:15 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0412]: cannot find type `Struct` in this scope + --> $DIR/issue-102989.rs:7:22 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-102989.rs:10:13 + | +LL | let x = x << 1; + | ^ help: a local variable with a similar name exists: `f` + +error[E0152]: found duplicate lang item `sized` + --> $DIR/issue-102989.rs:5:1 + | +LL | trait Sized { } + | ^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `core` (which `std` depends on) + = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib + = note: second definition in the local crate (`issue_102989`) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0152, E0412, E0425. +For more information about an error, try `rustc --explain E0152`. diff --git a/tests/ui/traits/issue-104322.rs b/tests/ui/traits/issue-104322.rs new file mode 100644 index 000000000..dcc27f1f0 --- /dev/null +++ b/tests/ui/traits/issue-104322.rs @@ -0,0 +1,80 @@ +// build-pass +// +// Tests that overflows do not occur in certain situations +// related to generic diesel code + +use mini_diesel::*; + +pub trait HandleDelete {} + +pub fn handle_delete() +where + R: HasTable, + R::Table: HandleDelete + 'static, +{ +} + +impl HandleDelete for T +where + T: Table + HasTable + 'static, + K: 'static, + &'static K: Identifiable
, + T::PrimaryKey: EqAll<<&'static K as Identifiable>::Id>, + T::Query: FilterDsl<::Id>>::Output>, + Filter::Id>>::Output>: + IntoUpdateTarget
, +{ +} + +mod mini_diesel { + pub trait HasTable { + type Table: Table; + } + + pub trait Identifiable: HasTable { + type Id; + } + + pub trait EqAll { + type Output; + } + + pub trait IntoUpdateTarget: HasTable { + type WhereClause; + } + + pub trait Query { + type SqlType; + } + + pub trait AsQuery { + type Query: Query; + } + impl AsQuery for T { + type Query = Self; + } + + pub trait FilterDsl { + type Output; + } + + impl FilterDsl for T + where + T: Table, + T::Query: FilterDsl, + { + type Output = Filter; + } + + pub trait QuerySource { + type FromClause; + } + + pub trait Table: QuerySource + AsQuery + Sized { + type PrimaryKey; + } + + pub type Filter = >::Output; +} + +fn main() {} diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs new file mode 100644 index 000000000..7064a39d2 --- /dev/null +++ b/tests/ui/traits/issue-106072.rs @@ -0,0 +1,5 @@ +#[derive(Clone)] //~ trait objects must include the `dyn` keyword + //~| trait objects must include the `dyn` keyword +struct Foo; +trait Foo {} //~ the name `Foo` is defined multiple times +fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr new file mode 100644 index 000000000..f9b7b8146 --- /dev/null +++ b/tests/ui/traits/issue-106072.stderr @@ -0,0 +1,30 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-106072.rs:4:1 + | +LL | struct Foo; + | ----------- previous definition of the type `Foo` here +LL | trait Foo {} + | ^^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-106072.rs:1:10 + | +LL | #[derive(Clone)] + | ^^^^^ + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-106072.rs:1:10 + | +LL | #[derive(Clone)] + | ^^^^^ + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/issue-18400.rs b/tests/ui/traits/issue-18400.rs new file mode 100644 index 000000000..fdd11512d --- /dev/null +++ b/tests/ui/traits/issue-18400.rs @@ -0,0 +1,26 @@ +trait Set { + fn contains(&self, _: T) -> bool; + fn set(&mut self, _: T); +} + +impl<'a, T, S> Set<&'a [T]> for S where + T: Copy, + S: Set, +{ + fn contains(&self, bits: &[T]) -> bool { + bits.iter().all(|&bit| self.contains(bit)) + } + + fn set(&mut self, bits: &[T]) { + for &bit in bits { + self.set(bit) + } + } +} + +fn main() { + let bits: &[_] = &[0, 1]; + + 0.contains(bits); + //~^ ERROR overflow +} diff --git a/tests/ui/traits/issue-18400.stderr b/tests/ui/traits/issue-18400.stderr new file mode 100644 index 000000000..edaf08f49 --- /dev/null +++ b/tests/ui/traits/issue-18400.stderr @@ -0,0 +1,20 @@ +error[E0275]: overflow evaluating the requirement `_: Sized` + --> $DIR/issue-18400.rs:24:7 + | +LL | 0.contains(bits); + | ^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_18400`) +note: required for `{integer}` to implement `Set<&[_]>` + --> $DIR/issue-18400.rs:6:16 + | +LL | impl<'a, T, S> Set<&'a [T]> for S where + | - ^^^^^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 128 redundant requirements hidden + = note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/issue-18412.rs b/tests/ui/traits/issue-18412.rs new file mode 100644 index 000000000..fe1cfb3df --- /dev/null +++ b/tests/ui/traits/issue-18412.rs @@ -0,0 +1,26 @@ +// run-pass +// Test that non-static methods can be assigned to local variables as +// function pointers. + + +trait Foo { + fn foo(&self) -> usize; +} + +struct A(usize); + +impl A { + fn bar(&self) -> usize { self.0 } +} + +impl Foo for A { + fn foo(&self) -> usize { self.bar() } +} + +fn main() { + let f = A::bar; + let g = Foo::foo; + let a = A(42); + + assert_eq!(f(&a), g(&a)); +} diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs new file mode 100644 index 000000000..1cb2d8c73 --- /dev/null +++ b/tests/ui/traits/issue-20692.rs @@ -0,0 +1,11 @@ +trait Array: Sized + Copy {} + +fn f(x: &T) { + let _ = x + //~^ ERROR `Array` cannot be made into an object + as + &dyn Array; + //~^ ERROR `Array` cannot be made into an object +} + +fn main() {} diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr new file mode 100644 index 000000000..2028994cd --- /dev/null +++ b/tests/ui/traits/issue-20692.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Array` cannot be made into an object + --> $DIR/issue-20692.rs:7:5 + | +LL | &dyn Array; + | ^^^^^^^^^^ `Array` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-20692.rs:1:14 + | +LL | trait Array: Sized + Copy {} + | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` + | | | + | | ...because it requires `Self: Sized` + | this trait cannot be made into an object... + +error[E0038]: the trait `Array` cannot be made into an object + --> $DIR/issue-20692.rs:4:13 + | +LL | let _ = x + | ^ `Array` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-20692.rs:1:14 + | +LL | trait Array: Sized + Copy {} + | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` + | | | + | | ...because it requires `Self: Sized` + | this trait cannot be made into an object... + = note: required for `&T` to implement `CoerceUnsized<&dyn Array>` + = note: required by cast to type `&dyn Array` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-22019.rs b/tests/ui/traits/issue-22019.rs new file mode 100644 index 000000000..1a887f0f3 --- /dev/null +++ b/tests/ui/traits/issue-22019.rs @@ -0,0 +1,34 @@ +// run-pass +// Test an issue where global caching was causing free regions from +// distinct scopes to be compared (`'g` and `'h`). The only important +// thing is that compilation succeeds here. + +// pretty-expanded FIXME #23616 + +#![allow(missing_copy_implementations)] +#![allow(unused_variables)] + +use std::borrow::ToOwned; + +pub struct CFGNode; + +pub type Node<'a> = &'a CFGNode; + +pub trait GraphWalk<'c, N> { + /// Returns all the nodes in this graph. + fn nodes(&'c self) where [N]:ToOwned>; +} + +impl<'g> GraphWalk<'g, Node<'g>> for u32 +{ + fn nodes(&'g self) where [Node<'g>]:ToOwned>> + { loop { } } +} + +impl<'h> GraphWalk<'h, Node<'h>> for u64 +{ + fn nodes(&'h self) where [Node<'h>]:ToOwned>> + { loop { } } +} + +fn main() { } diff --git a/tests/ui/traits/issue-22110.rs b/tests/ui/traits/issue-22110.rs new file mode 100644 index 000000000..bdbfee799 --- /dev/null +++ b/tests/ui/traits/issue-22110.rs @@ -0,0 +1,27 @@ +// run-pass +// Test an issue where we reported ambiguity between the where-clause +// and the blanket impl. The only important thing is that compilation +// succeeds here. Issue #22110. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Foo { + fn foo(&self, a: A); +} + +impl Foo for F { + fn foo(&self, _: A) { } +} + +fn baz Foo<(&'a A,)>>(_: F) { } + +fn components(t: fn(&A)) + where fn(&A) : for<'a> Foo<(&'a A,)>, +{ + baz(t) +} + +fn main() { +} diff --git a/tests/ui/traits/issue-22655.rs b/tests/ui/traits/issue-22655.rs new file mode 100644 index 000000000..bc08ca0a2 --- /dev/null +++ b/tests/ui/traits/issue-22655.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] +// Regression test for issue #22655: This test should not lead to +// infinite recursion. + +// pretty-expanded FIXME #23616 + +unsafe impl Send for Unique { } + +pub struct Unique { + pointer: *const T, +} + +pub struct Node { + vals: V, + edges: Unique>, +} + +fn is_send() {} + +fn main() { + is_send::>(); +} diff --git a/tests/ui/traits/issue-23003-overflow.rs b/tests/ui/traits/issue-23003-overflow.rs new file mode 100644 index 000000000..c5f471f23 --- /dev/null +++ b/tests/ui/traits/issue-23003-overflow.rs @@ -0,0 +1,29 @@ +// A variant of traits-issue-23003 in which an infinite series of +// types are required. This test now just compiles fine, since the +// relevant rules that triggered the overflow were removed. + +// check-pass +#![allow(dead_code)] + +use std::marker::PhantomData; + +trait Async { + type Cancel; +} + +struct Receipt { + marker: PhantomData, +} + +struct Complete { + core: Option, +} + +impl Async for Complete { + type Cancel = Receipt>>; +} + +fn foo(_: Receipt>) { } + + +fn main() { } diff --git a/tests/ui/traits/issue-23003.rs b/tests/ui/traits/issue-23003.rs new file mode 100644 index 000000000..24c2b2ad6 --- /dev/null +++ b/tests/ui/traits/issue-23003.rs @@ -0,0 +1,32 @@ +// run-pass +// Test stack overflow triggered by evaluating the implications. To be +// WF, the type `Receipt` would require that `::Cancel` be WF. This normalizes to `Receipt` +// again, leading to an infinite cycle. Issue #23003. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] +#![allow(unused_variables)] + +use std::marker::PhantomData; + +trait Async { + type Cancel; +} + +struct Receipt { + marker: PhantomData, +} + +struct Complete { + core: Option<()>, +} + +impl Async for Complete { + type Cancel = Receipt; +} + +fn foo(r: Receipt) { } + +fn main() { } diff --git a/tests/ui/traits/issue-23825.rs b/tests/ui/traits/issue-23825.rs new file mode 100644 index 000000000..a9f0095d2 --- /dev/null +++ b/tests/ui/traits/issue-23825.rs @@ -0,0 +1,21 @@ +// run-pass +trait Stringify { + fn to_string(&self) -> String; +} + +impl Stringify for u32 { + fn to_string(&self) -> String { format!("u32: {}", *self) } +} + +impl Stringify for f32 { + fn to_string(&self) -> String { format!("f32: {}", *self) } +} + +fn print(x: T) -> String { + x.to_string() +} + +fn main() { + assert_eq!(&print(5), "u32: 5"); + assert_eq!(&print(5.0), "f32: 5"); +} diff --git a/tests/ui/traits/issue-24010.rs b/tests/ui/traits/issue-24010.rs new file mode 100644 index 000000000..f18185334 --- /dev/null +++ b/tests/ui/traits/issue-24010.rs @@ -0,0 +1,14 @@ +// run-pass + +trait Foo: Fn(i32) -> i32 + Send {} + +impl i32 + Send> Foo for T {} + +fn wants_foo(f: Box) -> i32 { + f(42) +} + +fn main() { + let f = Box::new(|x| x); + assert_eq!(wants_foo(f), 42); +} diff --git a/tests/ui/traits/issue-26339.rs b/tests/ui/traits/issue-26339.rs new file mode 100644 index 000000000..bedd87cc4 --- /dev/null +++ b/tests/ui/traits/issue-26339.rs @@ -0,0 +1,31 @@ +// run-pass +// Test that the right implementation is called through a trait +// object when supertraits include multiple references to the +// same trait, with different type parameters. + +trait A: PartialEq + PartialEq { } + +struct Foo; +struct Bar; + +struct Aimpl; + +impl PartialEq for Aimpl { + fn eq(&self, _rhs: &Foo) -> bool { + true + } +} + +impl PartialEq for Aimpl { + fn eq(&self, _rhs: &Bar) -> bool { + false + } +} + +impl A for Aimpl { } + +fn main() { + let a = &Aimpl as &dyn A; + + assert!(*a == Foo); +} diff --git a/tests/ui/traits/issue-28576.rs b/tests/ui/traits/issue-28576.rs new file mode 100644 index 000000000..972c839b6 --- /dev/null +++ b/tests/ui/traits/issue-28576.rs @@ -0,0 +1,12 @@ +pub trait Foo { + type Assoc; +} + +pub trait Bar: Foo { + fn new(&self, b: & + dyn Bar //~ ERROR the trait `Bar` cannot be made into an object + + ); +} + +fn main() {} diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr new file mode 100644 index 000000000..203cd0630 --- /dev/null +++ b/tests/ui/traits/issue-28576.stderr @@ -0,0 +1,20 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-28576.rs:7:12 + | +LL | / dyn Bar +LL | | + | |________________________^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-28576.rs:5:16 + | +LL | pub trait Bar: Foo { + | --- ^^^^^^^^^^^^^ + | | | | + | | | ...because it uses `Self` as a type parameter + | | ...because it uses `Self` as a type parameter + | this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-32963.rs b/tests/ui/traits/issue-32963.rs new file mode 100644 index 000000000..56a68f3a2 --- /dev/null +++ b/tests/ui/traits/issue-32963.rs @@ -0,0 +1,11 @@ +use std::mem; + +trait Misc {} + +fn size_of_copy() -> usize { mem::size_of::() } + +fn main() { + size_of_copy::(); + //~^ ERROR only auto traits can be used as additional traits in a trait object + //~| ERROR the trait bound `dyn Misc: Copy` is not satisfied +} diff --git a/tests/ui/traits/issue-32963.stderr b/tests/ui/traits/issue-32963.stderr new file mode 100644 index 000000000..bad45e54d --- /dev/null +++ b/tests/ui/traits/issue-32963.stderr @@ -0,0 +1,27 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/issue-32963.rs:8:31 + | +LL | size_of_copy::(); + | ---- ^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Misc + Copy {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0277]: the trait bound `dyn Misc: Copy` is not satisfied + --> $DIR/issue-32963.rs:8:20 + | +LL | size_of_copy::(); + | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `dyn Misc` + | +note: required by a bound in `size_of_copy` + --> $DIR/issue-32963.rs:5:20 + | +LL | fn size_of_copy() -> usize { mem::size_of::() } + | ^^^^ required by this bound in `size_of_copy` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0225, E0277. +For more information about an error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/issue-33140-hack-boundaries.rs b/tests/ui/traits/issue-33140-hack-boundaries.rs new file mode 100644 index 000000000..d091162fc --- /dev/null +++ b/tests/ui/traits/issue-33140-hack-boundaries.rs @@ -0,0 +1,70 @@ +#![feature(negative_impls)] +#![allow(order_dependent_trait_objects)] + +// Check that the issue #33140 hack does not allow unintended things. + +// OK +trait Trait0 {} + +impl Trait0 for dyn Send {} +impl Trait0 for dyn Send {} + +// Problem 1: associated types +trait Trait1 { + fn my_fn(&self) {} +} + +impl Trait1 for dyn Send {} +impl Trait1 for dyn Send {} +//~^ ERROR E0119 + +// Problem 2: negative impl +trait Trait2 {} + +impl Trait2 for dyn Send {} +impl !Trait2 for dyn Send {} +//~^ ERROR E0751 + +// Problem 3: type parameter +trait Trait3 {} + +impl Trait3 for dyn Send {} +impl Trait3 for dyn Send {} +//~^ ERROR E0119 + +// Problem 4a: not a trait object - generic +trait Trait4a {} + +impl Trait4a for T {} +impl Trait4a for dyn Send {} +//~^ ERROR E0119 + +// Problem 4b: not a trait object - misc +trait Trait4b {} + +impl Trait4b for () {} +impl Trait4b for () {} +//~^ ERROR E0119 + +// Problem 4c: not a principal-less trait object +trait Trait4c {} + +impl Trait4c for dyn Trait1 + Send {} +impl Trait4c for dyn Trait1 + Send {} +//~^ ERROR E0119 + +// Problem 4d: lifetimes +trait Trait4d {} + +impl<'a> Trait4d for dyn Send + 'a {} +impl<'a> Trait4d for dyn Send + 'a {} +//~^ ERROR E0119 + +// Problem 5: where-clauses +trait Trait5 {} + +impl Trait5 for dyn Send {} +impl Trait5 for dyn Send where u32: Copy {} +//~^ ERROR E0119 + +fn main() {} diff --git a/tests/ui/traits/issue-33140-hack-boundaries.stderr b/tests/ui/traits/issue-33140-hack-boundaries.stderr new file mode 100644 index 000000000..80a502c63 --- /dev/null +++ b/tests/ui/traits/issue-33140-hack-boundaries.stderr @@ -0,0 +1,85 @@ +error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:18:1 + | +LL | impl Trait1 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait1 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error[E0751]: found both positive and negative implementation of trait `Trait2` for type `(dyn Send + 'static)`: + --> $DIR/issue-33140-hack-boundaries.rs:25:1 + | +LL | impl Trait2 for dyn Send {} + | ------------------------ positive implementation here +LL | impl !Trait2 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error[E0119]: conflicting implementations of trait `Trait3<(dyn Sync + 'static)>` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:32:1 + | +LL | impl Trait3 for dyn Send {} + | ---------------------------------- first implementation here +LL | impl Trait3 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:39:1 + | +LL | impl Trait4a for T {} + | ----------------------------- first implementation here +LL | impl Trait4a for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4b` for type `()` + --> $DIR/issue-33140-hack-boundaries.rs:46:1 + | +LL | impl Trait4b for () {} + | ------------------- first implementation here +LL | impl Trait4b for () {} + | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:53:1 + | +LL | impl Trait4c for dyn Trait1 + Send {} + | ---------------------------------- first implementation here +LL | impl Trait4c for dyn Trait1 + Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + Send + 'static)` + +error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn Send` + --> $DIR/issue-33140-hack-boundaries.rs:60:1 + | +LL | impl<'a> Trait4d for dyn Send + 'a {} + | ---------------------------------- first implementation here +LL | impl<'a> Trait4d for dyn Send + 'a {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn Send` + +error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn Send + 'static)` + --> $DIR/issue-33140-hack-boundaries.rs:67:1 + | +LL | impl Trait5 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait5 for dyn Send where u32: Copy {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0119, E0751. +For more information about an error, try `rustc --explain E0119`. +Future incompatibility report: Future breakage diagnostic: +warning: conflicting implementations of trait `Trait0` for type `(dyn Send + 'static)`: (E0119) + --> $DIR/issue-33140-hack-boundaries.rs:10:1 + | +LL | impl Trait0 for dyn Send {} + | ------------------------ first implementation here +LL | impl Trait0 for dyn Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 +note: the lint level is defined here + --> $DIR/issue-33140-hack-boundaries.rs:2:10 + | +LL | #![allow(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/traits/issue-33140.rs b/tests/ui/traits/issue-33140.rs new file mode 100644 index 000000000..9bdac4b83 --- /dev/null +++ b/tests/ui/traits/issue-33140.rs @@ -0,0 +1,47 @@ +trait Trait { + fn xyz() -> bool; +} + +impl Trait for dyn Send + Sync { + fn xyz() -> bool { false } +} + +impl Trait for dyn Sync + Send { +//~^ ERROR conflicting implementations + fn xyz() -> bool { true } +} + +trait Trait2 { + fn uvw() -> bool; +} + +impl Trait2 for dyn Send + Sync { + fn uvw() -> bool { false } +} + +impl Trait2 for dyn Sync + Send + Sync { +//~^ ERROR conflicting implementations + fn uvw() -> bool { true } +} + +struct Foo(T); +impl Foo { + fn abc() -> bool { //~ ERROR duplicate definitions with name `abc` + false + } +} + +impl Foo { + fn abc() -> bool { + true + } +} + +fn main() { + assert_eq!(::xyz(), false); + assert_eq!(::xyz(), true); + assert_eq!(::uvw(), false); + assert_eq!(::uvw(), true); + assert_eq!(>::abc(), false); + assert_eq!(>::abc(), true); +} diff --git a/tests/ui/traits/issue-33140.stderr b/tests/ui/traits/issue-33140.stderr new file mode 100644 index 000000000..d31281f72 --- /dev/null +++ b/tests/ui/traits/issue-33140.stderr @@ -0,0 +1,31 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)` + --> $DIR/issue-33140.rs:9:1 + | +LL | impl Trait for dyn Send + Sync { + | ------------------------------ first implementation here +... +LL | impl Trait for dyn Sync + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + +error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn Send + Sync + 'static)` + --> $DIR/issue-33140.rs:22:1 + | +LL | impl Trait2 for dyn Send + Sync { + | ------------------------------- first implementation here +... +LL | impl Trait2 for dyn Sync + Send + Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + +error[E0592]: duplicate definitions with name `abc` + --> $DIR/issue-33140.rs:29:5 + | +LL | fn abc() -> bool { + | ^^^^^^^^^^^^^^^^ duplicate definitions for `abc` +... +LL | fn abc() -> bool { + | ---------------- other definition for `abc` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0592. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/issue-35869.rs b/tests/ui/traits/issue-35869.rs new file mode 100644 index 000000000..b9b4c972e --- /dev/null +++ b/tests/ui/traits/issue-35869.rs @@ -0,0 +1,21 @@ +trait Foo { + fn foo(_: fn(u8) -> ()); + fn bar(_: Option); + fn baz(_: (u8, u16)); + fn qux() -> u8; +} + +struct Bar; + +impl Foo for Bar { + fn foo(_: fn(u16) -> ()) {} + //~^ ERROR method `foo` has an incompatible type for trait + fn bar(_: Option) {} + //~^ ERROR method `bar` has an incompatible type for trait + fn baz(_: (u16, u16)) {} + //~^ ERROR method `baz` has an incompatible type for trait + fn qux() -> u16 { 5u16 } + //~^ ERROR method `qux` has an incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/traits/issue-35869.stderr b/tests/ui/traits/issue-35869.stderr new file mode 100644 index 000000000..6d985bdea --- /dev/null +++ b/tests/ui/traits/issue-35869.stderr @@ -0,0 +1,71 @@ +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/issue-35869.rs:11:15 + | +LL | fn foo(_: fn(u16) -> ()) {} + | ^^^^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `fn(u8)` + | +note: type in trait + --> $DIR/issue-35869.rs:2:15 + | +LL | fn foo(_: fn(u8) -> ()); + | ^^^^^^^^^^^^ + = note: expected signature `fn(fn(u8))` + found signature `fn(fn(u16))` + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/issue-35869.rs:13:15 + | +LL | fn bar(_: Option) {} + | ^^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `Option` + | +note: type in trait + --> $DIR/issue-35869.rs:3:15 + | +LL | fn bar(_: Option); + | ^^^^^^^^^^ + = note: expected signature `fn(Option)` + found signature `fn(Option)` + +error[E0053]: method `baz` has an incompatible type for trait + --> $DIR/issue-35869.rs:15:15 + | +LL | fn baz(_: (u16, u16)) {} + | ^^^^^^^^^^ + | | + | expected `u8`, found `u16` + | help: change the parameter type to match the trait: `(u8, u16)` + | +note: type in trait + --> $DIR/issue-35869.rs:4:15 + | +LL | fn baz(_: (u8, u16)); + | ^^^^^^^^^ + = note: expected signature `fn((u8, _))` + found signature `fn((u16, _))` + +error[E0053]: method `qux` has an incompatible type for trait + --> $DIR/issue-35869.rs:17:17 + | +LL | fn qux() -> u16 { 5u16 } + | ^^^ + | | + | expected `u8`, found `u16` + | help: change the output type to match the trait: `u8` + | +note: type in trait + --> $DIR/issue-35869.rs:5:17 + | +LL | fn qux() -> u8; + | ^^ + = note: expected signature `fn() -> u8` + found signature `fn() -> u16` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/traits/issue-3683.rs b/tests/ui/traits/issue-3683.rs new file mode 100644 index 000000000..b12c450c9 --- /dev/null +++ b/tests/ui/traits/issue-3683.rs @@ -0,0 +1,18 @@ +// run-pass + +trait Foo { + fn a(&self) -> isize; + fn b(&self) -> isize { + self.a() + 2 + } +} + +impl Foo for isize { + fn a(&self) -> isize { + 3 + } +} + +pub fn main() { + assert_eq!(3.b(), 5); +} diff --git a/tests/ui/traits/issue-38033.rs b/tests/ui/traits/issue-38033.rs new file mode 100644 index 000000000..16b867ec8 --- /dev/null +++ b/tests/ui/traits/issue-38033.rs @@ -0,0 +1,79 @@ +// run-pass +use std::marker; +use std::mem; + +fn main() { + let workers = (0..0).map(|_| result::()); + drop(join_all(workers).poll()); +} + +trait Future { + type Item; + type Error; + + fn poll(&mut self) -> Result; +} + +trait IntoFuture { + type Future: Future; + type Item; + type Error; + + fn into_future(self) -> Self::Future; +} + +impl IntoFuture for F { + type Future = F; + type Item = F::Item; + type Error = F::Error; + + fn into_future(self) -> F { + self + } +} + +struct FutureResult { + _inner: marker::PhantomData<(T, E)>, +} + +fn result() -> FutureResult { + loop {} +} + +impl Future for FutureResult { + type Item = T; + type Error = E; + + fn poll(&mut self) -> Result { + loop {} + } +} + +struct JoinAll + where I: IntoIterator, + I::Item: IntoFuture, +{ + elems: Vec<::Item>, +} + +fn join_all(_: I) -> JoinAll + where I: IntoIterator, + I::Item: IntoFuture, +{ + JoinAll { elems: vec![] } +} + +impl Future for JoinAll + where I: IntoIterator, + I::Item: IntoFuture, +{ + type Item = Vec<::Item>; + type Error = ::Error; + + fn poll(&mut self) -> Result { + let elems = mem::replace(&mut self.elems, Vec::new()); + Ok(elems.into_iter().map(|e| { + e + }).collect::>()) + } +} diff --git a/tests/ui/traits/issue-38404.rs b/tests/ui/traits/issue-38404.rs new file mode 100644 index 000000000..1a92acc34 --- /dev/null +++ b/tests/ui/traits/issue-38404.rs @@ -0,0 +1,6 @@ +trait A: std::ops::Add + Sized {} +trait B: A {} +trait C: A> {} +//~^ ERROR the trait `B` cannot be made into an object + +fn main() {} diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr new file mode 100644 index 000000000..d7721d7e6 --- /dev/null +++ b/tests/ui/traits/issue-38404.stderr @@ -0,0 +1,17 @@ +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/issue-38404.rs:3:15 + | +LL | trait C: A> {} + | ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-38404.rs:1:13 + | +LL | trait A: std::ops::Add + Sized {} + | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter +LL | trait B: A {} + | - this trait cannot be made into an object... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs new file mode 100644 index 000000000..002a3c43f --- /dev/null +++ b/tests/ui/traits/issue-38604.rs @@ -0,0 +1,16 @@ +trait Q {} +trait Foo where u32: Q { + fn foo(&self); +} + +impl Q<()> for u32 {} +impl Foo for () { + fn foo(&self) { + println!("foo!"); + } +} + +fn main() { + let _f: Box = //~ ERROR `Foo` cannot be made into an object + Box::new(()); //~ ERROR `Foo` cannot be made into an object +} diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr new file mode 100644 index 000000000..50d6fb054 --- /dev/null +++ b/tests/ui/traits/issue-38604.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-38604.rs:14:13 + | +LL | let _f: Box = + | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-38604.rs:2:22 + | +LL | trait Foo where u32: Q { + | --- ^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-38604.rs:15:9 + | +LL | Box::new(()); + | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-38604.rs:2:22 + | +LL | trait Foo where u32: Q { + | --- ^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait cannot be made into an object... + = note: required for `Box<()>` to implement `CoerceUnsized>` + = note: required by cast to type `Box` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-3973.rs b/tests/ui/traits/issue-3973.rs new file mode 100644 index 000000000..a5ed5b870 --- /dev/null +++ b/tests/ui/traits/issue-3973.rs @@ -0,0 +1,25 @@ +struct Point { + x: f64, + y: f64, +} + +trait ToString_ { + fn to_string(&self) -> String; +} + +impl ToString_ for Point { + fn new(x: f64, y: f64) -> Point { + //~^ ERROR method `new` is not a member of trait `ToString_` + Point { x: x, y: y } + } + + fn to_string(&self) -> String { + format!("({}, {})", self.x, self.y) + } +} + +fn main() { + let p = Point::new(0.0, 0.0); + //~^ ERROR no function or associated item named `new` found for struct `Point` + println!("{}", p.to_string()); +} diff --git a/tests/ui/traits/issue-3973.stderr b/tests/ui/traits/issue-3973.stderr new file mode 100644 index 000000000..87ee08049 --- /dev/null +++ b/tests/ui/traits/issue-3973.stderr @@ -0,0 +1,22 @@ +error[E0407]: method `new` is not a member of trait `ToString_` + --> $DIR/issue-3973.rs:11:5 + | +LL | / fn new(x: f64, y: f64) -> Point { +LL | | +LL | | Point { x: x, y: y } +LL | | } + | |_____^ not a member of trait `ToString_` + +error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope + --> $DIR/issue-3973.rs:22:20 + | +LL | struct Point { + | ------------ function or associated item `new` not found for this struct +... +LL | let p = Point::new(0.0, 0.0); + | ^^^ function or associated item not found in `Point` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0407, E0599. +For more information about an error, try `rustc --explain E0407`. diff --git a/tests/ui/traits/issue-4107.rs b/tests/ui/traits/issue-4107.rs new file mode 100644 index 000000000..98433e806 --- /dev/null +++ b/tests/ui/traits/issue-4107.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + let _id: &Mat2 = &Matrix::identity(1.0); +} + +pub trait Index { fn get(&self, _: Index) -> Result { panic!() } } +pub trait Dimensional: Index { } + +pub struct Mat2 { x: T } +pub struct Vec2 { x: T } + +impl Dimensional> for Mat2 { } +impl Index> for Mat2 { } + +impl Dimensional for Vec2 { } +impl Index for Vec2 { } + +pub trait Matrix: Dimensional { + fn identity(t:T) -> Self; +} + +impl Matrix> for Mat2 { + fn identity(t:T) -> Mat2 { Mat2{ x: t } } +} diff --git a/tests/ui/traits/issue-43132.rs b/tests/ui/traits/issue-43132.rs new file mode 100644 index 000000000..c886f4b0a --- /dev/null +++ b/tests/ui/traits/issue-43132.rs @@ -0,0 +1,65 @@ +// run-pass +#![allow(unused)] + +fn main() { +} + +fn foo() { + let b = mk::< + Forward<(Box>,)>, + >(); + b.map_err(|_| ()).join(); +} + +fn mk() -> T { + loop {} +} + +impl, E> Future for (I,) { + type Error = E; +} + +struct Forward { + _a: T, +} + +impl Future for Forward +where + T::Error: From, +{ + type Error = T::Error; +} + +trait Future { + type Error; + + fn map_err(self, _: F) -> (Self, F) + where + F: FnOnce(Self::Error) -> E, + Self: Sized, + { + loop {} + } + + fn join(self) -> (MaybeDone, ()) + where + Self: Sized, + { + loop {} + } +} + +impl Future for Box { + type Error = S::Error; +} + +enum MaybeDone { + _Done(A::Error), +} + +impl Future for (A, F) +where + F: FnOnce(A::Error) -> U, +{ + type Error = U; +} diff --git a/tests/ui/traits/issue-43784-supertrait.rs b/tests/ui/traits/issue-43784-supertrait.rs new file mode 100644 index 000000000..55c26ccd2 --- /dev/null +++ b/tests/ui/traits/issue-43784-supertrait.rs @@ -0,0 +1,10 @@ +pub trait Partial: Copy { +} + +pub trait Complete: Partial { +} + +impl Partial for T where T: Complete {} +impl Complete for T {} //~ ERROR the trait bound `T: Copy` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr new file mode 100644 index 000000000..6b5b72138 --- /dev/null +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-43784-supertrait.rs:8:22 + | +LL | impl Complete for T {} + | ^ the trait `Copy` is not implemented for `T` + | +note: required for `T` to implement `Partial` + --> $DIR/issue-43784-supertrait.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ +note: required by a bound in `Complete` + --> $DIR/issue-43784-supertrait.rs:4:21 + | +LL | pub trait Complete: Partial { + | ^^^^^^^ required by this bound in `Complete` +help: consider restricting type parameter `T` + | +LL | impl Complete for T {} + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs new file mode 100644 index 000000000..005939e0c --- /dev/null +++ b/tests/ui/traits/issue-50480.rs @@ -0,0 +1,15 @@ +#[derive(Clone, Copy)] +//~^ ERROR the trait `Copy` may not be implemented for this type +struct Foo(N, NotDefined, ::Item, Vec, String); +//~^ ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `N` in this scope +//~| ERROR cannot find type `N` in this scope + +#[derive(Clone, Copy)] +//~^ ERROR the trait `Copy` may not be implemented for this type +struct Bar(T, N, NotDefined, ::Item, Vec, String); +//~^ ERROR cannot find type `NotDefined` in this scope +//~| ERROR cannot find type `N` in this scope + +fn main() {} diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr new file mode 100644 index 000000000..5063fdca0 --- /dev/null +++ b/tests/ui/traits/issue-50480.stderr @@ -0,0 +1,92 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:3:12 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:3:15 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:3:12 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:3:15 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ++++++++++++ + +error[E0412]: cannot find type `N` in this scope + --> $DIR/issue-50480.rs:11:18 + | +LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | struct Bar(T, T, NotDefined, ::Item, Vec, String); + | ~ +help: you might be missing a type parameter + | +LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); + | +++ + +error[E0412]: cannot find type `NotDefined` in this scope + --> $DIR/issue-50480.rs:11:21 + | +LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^ not found in this scope + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/issue-50480.rs:1:17 + | +LL | #[derive(Clone, Copy)] + | ^^^^ +LL | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | -------- ------ this field does not implement `Copy` + | | + | this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/issue-50480.rs:9:17 + | +LL | #[derive(Clone, Copy)] + | ^^^^ +LL | +LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); + | -------- ------ this field does not implement `Copy` + | | + | this field does not implement `Copy` + | + = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0204, E0412. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/issue-52893.rs b/tests/ui/traits/issue-52893.rs new file mode 100644 index 000000000..d72598d5d --- /dev/null +++ b/tests/ui/traits/issue-52893.rs @@ -0,0 +1,57 @@ +// check-fail +// +// regression test for issue 52893 +trait At { + type AtRes; + fn at(self) -> Self::AtRes; +} + +trait Push { + type PushRes; + fn push(self, other: T) -> Self::PushRes; +} + +trait AddClass { + type AddRes; + fn init(self, func: F); +} + +trait ToRef { + type RefRes; + fn to_ref(&self) -> Self::RefRes; +} + +struct Class

(P); + +impl

Class

{ + fn with(self) -> >::AddRes + where + Self: AddClass, + { + todo!() + } + + fn from(self) -> >::AddRes + where + Self: AddClass, + { + todo!() + } +} + +impl AddClass for Class

+where + Self: At, + >::AtRes: Push, + <>::AtRes as Push>::PushRes: ToRef + Push, +{ + type AddRes = (); + + fn init(self, func: F) { + let builder = self.at().push(func); + let output = builder.to_ref(); + builder.push(output); //~ ERROR mismatched types [E0308] + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr new file mode 100644 index 000000000..a11867c03 --- /dev/null +++ b/tests/ui/traits/issue-52893.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> $DIR/issue-52893.rs:53:22 + | +LL | impl AddClass for Class

+ | - this type parameter +... +LL | builder.push(output); + | ---- ^^^^^^ expected type parameter `F`, found struct `Class` + | | + | arguments to this method are incorrect + | + = note: expected type parameter `F` + found struct `Class

` +help: the return type of this call is `Class

` due to the type of the argument passed + --> $DIR/issue-52893.rs:53:9 + | +LL | builder.push(output); + | ^^^^^^^^^^^^^------^ + | | + | this argument influences the return type of `push` +note: associated function defined here + --> $DIR/issue-52893.rs:11:8 + | +LL | fn push(self, other: T) -> Self::PushRes; + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-56202.rs b/tests/ui/traits/issue-56202.rs new file mode 100644 index 000000000..0952843e6 --- /dev/null +++ b/tests/ui/traits/issue-56202.rs @@ -0,0 +1,17 @@ +// build-pass + +trait FooTrait {} + +trait BarTrait { + fn foo(_: T) -> Self; +} + +struct FooStruct(u32); + +impl BarTrait for FooStruct { + fn foo(_: T) -> Self { + Self(u32::default()) + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-56488.rs b/tests/ui/traits/issue-56488.rs new file mode 100644 index 000000000..e2f399692 --- /dev/null +++ b/tests/ui/traits/issue-56488.rs @@ -0,0 +1,13 @@ +// run-pass + +#![feature(trait_alias)] + +mod alpha { + pub trait A {} + pub trait C = A; +} + +#[allow(unused_imports)] +use alpha::C; + +fn main() {} diff --git a/tests/ui/traits/issue-59029-1.rs b/tests/ui/traits/issue-59029-1.rs new file mode 100644 index 000000000..8ab47a4af --- /dev/null +++ b/tests/ui/traits/issue-59029-1.rs @@ -0,0 +1,9 @@ +#![feature(trait_alias)] + +trait Svc { type Res; } + +trait MkSvc = Svc where Self::Res: Svc; +//~^ ERROR associated type `Res` not found for `Self` +//~| ERROR associated type `Res` not found for `Self` + +fn main() {} diff --git a/tests/ui/traits/issue-59029-1.stderr b/tests/ui/traits/issue-59029-1.stderr new file mode 100644 index 000000000..203a89285 --- /dev/null +++ b/tests/ui/traits/issue-59029-1.stderr @@ -0,0 +1,15 @@ +error[E0220]: associated type `Res` not found for `Self` + --> $DIR/issue-59029-1.rs:5:52 + | +LL | trait MkSvc = Svc where Self::Res: Svc; + | ^^^ there is a similarly named associated type `Res` in the trait `Svc` + +error[E0220]: associated type `Res` not found for `Self` + --> $DIR/issue-59029-1.rs:5:52 + | +LL | trait MkSvc = Svc where Self::Res: Svc; + | ^^^ there is a similarly named associated type `Res` in the trait `Svc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/traits/issue-59029-2.rs b/tests/ui/traits/issue-59029-2.rs new file mode 100644 index 000000000..2bdb128d8 --- /dev/null +++ b/tests/ui/traits/issue-59029-2.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(trait_alias)] + +trait Svc { type Res; } + +trait MkSvc = Svc where >::Res: Svc; + +fn main() {} diff --git a/tests/ui/traits/issue-6128.rs b/tests/ui/traits/issue-6128.rs new file mode 100644 index 000000000..07d92f8f8 --- /dev/null +++ b/tests/ui/traits/issue-6128.rs @@ -0,0 +1,22 @@ +// run-pass + +use std::collections::HashMap; + +trait Graph { + fn f(&self, _: Edge); + fn g(&self, _: Node); +} + +impl Graph for HashMap { + fn f(&self, _e: E) { + panic!(); + } + fn g(&self, _e: isize) { + panic!(); + } +} + +pub fn main() { + let g : Box> = Box::new(HashMap::new()); + let _g2 : Box> = g as Box>; +} diff --git a/tests/ui/traits/issue-6334.rs b/tests/ui/traits/issue-6334.rs new file mode 100644 index 000000000..acf48da15 --- /dev/null +++ b/tests/ui/traits/issue-6334.rs @@ -0,0 +1,46 @@ +// run-pass +// Tests that everything still compiles and runs fine even when +// we reorder the bounds. + + +trait A { + fn a(&self) -> usize; +} + +trait B { + fn b(&self) -> usize; +} + +trait C { + fn combine(&self, t: &T) -> usize; +} + +struct Foo; + +impl A for Foo { + fn a(&self) -> usize { 1 } +} + +impl B for Foo { + fn b(&self) -> usize { 2 } +} + +struct Bar; + +impl C for Bar { + // Note below: bounds in impl decl are in reverse order. + fn combine(&self, t: &T) -> usize { + (t.a() * 100) + t.b() + } +} + +fn use_c(s: &S, t: &T) -> usize { + s.combine(t) +} + +pub fn main() { + let foo = Foo; + let bar = Bar; + let r = use_c(&bar, &foo); + assert_eq!(r, 102); +} diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs new file mode 100644 index 000000000..018ce0459 --- /dev/null +++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.rs @@ -0,0 +1,11 @@ +trait Foo { + fn foo(&self); +} + +trait Bar {} + +fn do_stuff(t : T) { + t.foo() //~ ERROR no method named `foo` found +} + +fn main() {} diff --git a/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr new file mode 100644 index 000000000..ae33e61d8 --- /dev/null +++ b/tests/ui/traits/issue-65284-suggest-generic-trait-bound.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `foo` found for type parameter `T` in the current scope + --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7 + | +LL | fn do_stuff(t : T) { + | - method `foo` not found for this type parameter +LL | t.foo() + | ^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn do_stuff(t : T) { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/issue-65673.rs b/tests/ui/traits/issue-65673.rs new file mode 100644 index 000000000..e5c2fccb2 --- /dev/null +++ b/tests/ui/traits/issue-65673.rs @@ -0,0 +1,12 @@ +#![feature(trait_alias)] // Enabled to reduce stderr output, but can be triggered even if disabled. +trait Trait {} +trait WithType { + type Ctx; +} +trait Alias = where T: Trait; + +impl WithType for T { + type Ctx = dyn Alias; + //~^ ERROR at least one trait is required for an object type [E0224] +} +fn main() {} diff --git a/tests/ui/traits/issue-65673.stderr b/tests/ui/traits/issue-65673.stderr new file mode 100644 index 000000000..8f01d7c53 --- /dev/null +++ b/tests/ui/traits/issue-65673.stderr @@ -0,0 +1,12 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-65673.rs:9:16 + | +LL | trait Alias = where T: Trait; + | -------------- this alias does not contain a trait +... +LL | type Ctx = dyn Alias; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/issue-68295.rs b/tests/ui/traits/issue-68295.rs new file mode 100644 index 000000000..7ff54539a --- /dev/null +++ b/tests/ui/traits/issue-68295.rs @@ -0,0 +1,47 @@ +// check-fail +// +// regression test for #68295 + +struct Matrix(R, C, S); + +impl Matrix { + fn into_owned(self) -> Matrix> + where + (): Allocator, + { + unimplemented!() + } +} + +impl Matrix { + fn hermitian_part(&self) -> Matrix> + where + (): Allocator, + { + unimplemented!() + } +} + +trait Allocator { + type Buffer; +} + +trait Trait { + type Power; +} + +impl> Trait for () { + type Power = A::Buffer; +} + +type Owned = >::Power; + +fn crash(input: Matrix) -> Matrix +where + (): Allocator, +{ + input.into_owned() + //~^ ERROR mismatched types [E0308] +} + +fn main() {} diff --git a/tests/ui/traits/issue-68295.stderr b/tests/ui/traits/issue-68295.stderr new file mode 100644 index 000000000..cb6e6e076 --- /dev/null +++ b/tests/ui/traits/issue-68295.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-68295.rs:43:5 + | +LL | fn crash(input: Matrix) -> Matrix + | ----------------- expected `Matrix` because of return type +... +LL | input.into_owned() + | ^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type + | + = note: expected struct `Matrix<_, _, u32>` + found struct `Matrix<_, _, <() as Allocator>::Buffer>` + = help: consider constraining the associated type `<() as Allocator>::Buffer` to `u32` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/issue-7013.rs b/tests/ui/traits/issue-7013.rs new file mode 100644 index 000000000..1fb01303c --- /dev/null +++ b/tests/ui/traits/issue-7013.rs @@ -0,0 +1,26 @@ +use std::cell::RefCell; +use std::rc::Rc; + +trait Foo { + fn set(&mut self, v: Rc>); +} + +struct B { + v: Option>> +} + +impl Foo for B { + fn set(&mut self, v: Rc>) + { + self.v = Some(v); + } +} + +struct A { + v: Box, +} + +fn main() { + let a = A {v: Box::new(B{v: None}) as Box}; + //~^ ERROR `Rc>` cannot be sent between threads safely +} diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr new file mode 100644 index 000000000..4575f4dba --- /dev/null +++ b/tests/ui/traits/issue-7013.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Rc>` cannot be sent between threads safely + --> $DIR/issue-7013.rs:24:19 + | +LL | let a = A {v: Box::new(B{v: None}) as Box}; + | ^^^^^^^^^^^^^^^^^^^^ `Rc>` cannot be sent between threads safely + | + = help: within `B`, the trait `Send` is not implemented for `Rc>` + = note: required because it appears within the type `Option>>` +note: required because it appears within the type `B` + --> $DIR/issue-7013.rs:8:8 + | +LL | struct B { + | ^ + = note: required for the cast from `B` to the object type `dyn Foo + Send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-70944.rs b/tests/ui/traits/issue-70944.rs new file mode 100644 index 000000000..3286de9d5 --- /dev/null +++ b/tests/ui/traits/issue-70944.rs @@ -0,0 +1,23 @@ +// check-pass +// Regression test of #70944, should compile fine. + +use std::ops::Index; + +pub struct KeyA; +pub struct KeyB; +pub struct KeyC; + +pub trait Foo: Index + Index + Index {} +pub trait FooBuilder { + type Inner: Foo; + fn inner(&self) -> &Self::Inner; +} + +pub fn do_stuff(foo: &impl FooBuilder) { + let inner = foo.inner(); + &inner[KeyA]; + &inner[KeyB]; + &inner[KeyC]; +} + +fn main() {} diff --git a/tests/ui/traits/issue-71036.rs b/tests/ui/traits/issue-71036.rs new file mode 100644 index 000000000..69eed0c04 --- /dev/null +++ b/tests/ui/traits/issue-71036.rs @@ -0,0 +1,17 @@ +#![feature(unsize, dispatch_from_dyn)] + +use std::marker::Unsize; +use std::ops::DispatchFromDyn; + +#[allow(unused)] +struct Foo<'a, T: ?Sized> { + _inner: &'a &'a T, +} + +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} +//~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied +//~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T` +//~| NOTE all implementations of `Unsize` are provided automatically by the compiler +//~| NOTE required for + +fn main() {} diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr new file mode 100644 index 000000000..79eb7a2ae --- /dev/null +++ b/tests/ui/traits/issue-71036.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied + --> $DIR/issue-71036.rs:11:1 + | +LL | impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` + | + = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information + = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-71136.rs b/tests/ui/traits/issue-71136.rs new file mode 100644 index 000000000..b21756e2b --- /dev/null +++ b/tests/ui/traits/issue-71136.rs @@ -0,0 +1,8 @@ +struct Foo(u8); + +#[derive(Clone)] +struct FooHolster { + the_foos: Vec, //~ERROR Clone +} + +fn main() {} diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr new file mode 100644 index 000000000..f54173392 --- /dev/null +++ b/tests/ui/traits/issue-71136.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Foo: Clone` is not satisfied + --> $DIR/issue-71136.rs:5:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct FooHolster { +LL | the_foos: Vec, + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo` + | + = note: required for `Vec` to implement `Clone` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Foo` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-72410.rs b/tests/ui/traits/issue-72410.rs new file mode 100644 index 000000000..c95f1dfdc --- /dev/null +++ b/tests/ui/traits/issue-72410.rs @@ -0,0 +1,18 @@ +// Regression test for #72410, this should be used with debug assertion enabled. + +// should be fine +pub trait Foo { + fn map() + where + Self: Sized, + for<'a> &'a mut [u8]: ; +} + +// should fail +pub trait Bar { + fn map() + where for<'a> &'a mut [dyn Bar]: ; + //~^ ERROR: the trait `Bar` cannot be made into an object +} + +fn main() {} diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr new file mode 100644 index 000000000..c7beb834b --- /dev/null +++ b/tests/ui/traits/issue-72410.stderr @@ -0,0 +1,25 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-72410.rs:14:19 + | +LL | where for<'a> &'a mut [dyn Bar]: ; + | ^^^^^^^^^^^^^^^^^ `Bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-72410.rs:13:8 + | +LL | pub trait Bar { + | --- this trait cannot be made into an object... +LL | fn map() + | ^^^ ...because associated function `map` has no `self` parameter +help: consider turning `map` into a method by giving it a `&self` argument + | +LL | fn map(&self) + | +++++ +help: alternatively, consider constraining `map` so it does not apply to trait objects + | +LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ; + | +++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-72455.rs b/tests/ui/traits/issue-72455.rs new file mode 100644 index 000000000..b6c3bb222 --- /dev/null +++ b/tests/ui/traits/issue-72455.rs @@ -0,0 +1,27 @@ +// check-pass + +pub trait ResultExt { + type Ok; + fn err_eprint_and_ignore(self) -> Option; +} + +impl ResultExt for std::result::Result +where + E: std::error::Error, +{ + type Ok = O; + fn err_eprint_and_ignore(self) -> Option + where + Self: , + { + match self { + Err(e) => { + eprintln!("{}", e); + None + } + Ok(o) => Some(o), + } + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-75627.rs b/tests/ui/traits/issue-75627.rs new file mode 100644 index 000000000..93a2ec1cc --- /dev/null +++ b/tests/ui/traits/issue-75627.rs @@ -0,0 +1,6 @@ +struct Foo(T, *const ()); + +unsafe impl Send for Foo {} +//~^ ERROR cannot find type + +fn main() {} diff --git a/tests/ui/traits/issue-75627.stderr b/tests/ui/traits/issue-75627.stderr new file mode 100644 index 000000000..1675edc9f --- /dev/null +++ b/tests/ui/traits/issue-75627.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/issue-75627.rs:3:26 + | +LL | unsafe impl Send for Foo {} + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | unsafe impl Send for Foo {} + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs new file mode 100644 index 000000000..f5be6cf21 --- /dev/null +++ b/tests/ui/traits/issue-77982.rs @@ -0,0 +1,41 @@ +use std::collections::HashMap; + +fn what() { + let descr = String::new(); + let mut opts = HashMap::::new(); + let opt = String::new(); + + opts.get(opt.as_ref()); //~ ERROR type annotations needed + //~^ ERROR type annotations needed +} + +fn main() { + let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); + //~^ ERROR type annotations needed +} + +trait Foo<'a, T: ?Sized> { + fn foo(&self) -> Box { + todo!() + } +} + +trait Bar<'a, T: ?Sized> { + fn bar(&self) -> Box { + todo!() + } +} + +impl Foo<'static, u32> for () {} +impl<'a> Foo<'a, i16> for () {} + +impl<'a> Bar<'static, u32> for &'a () {} +impl<'a> Bar<'a, i16> for &'a () {} + +fn foo() { + let _ = ().foo(); //~ ERROR type annotations needed +} + +fn bar() { + let _ = (&()).bar(); //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr new file mode 100644 index 000000000..0b57a8212 --- /dev/null +++ b/tests/ui/traits/issue-77982.stderr @@ -0,0 +1,98 @@ +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:8:10 + | +LL | opts.get(opt.as_ref()); + | ^^^ ------------ type must be known at this point + | | + | cannot infer type of the type parameter `Q` declared on the associated function `get` + | + = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: + - impl Borrow for String; + - impl Borrow for T + where T: ?Sized; +note: required by a bound in `HashMap::::get` + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL +help: consider specifying the generic argument + | +LL | opts.get::(opt.as_ref()); + | +++++ + +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:8:10 + | +LL | opts.get(opt.as_ref()); + | ^^^ ------ type must be known at this point + | | + | cannot infer type of the type parameter `Q` declared on the associated function `get` + | + = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`: + - impl AsRef for String; + - impl AsRef for String; + - impl AsRef<[u8]> for String; + - impl AsRef for String; +help: consider specifying the generic argument + | +LL | opts.get::(opt.as_ref()); + | +++++ + +error[E0283]: type annotations needed + --> $DIR/issue-77982.rs:13:59 + | +LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); + | --------- ^^^^ + | | + | required by a bound introduced by this call + | + = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for u32; + - impl From for T; + - impl From for T; +help: try using a fully qualified path to specify the expected types + | +LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into(0u32))).collect(); + | +++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed for `Box` + --> $DIR/issue-77982.rs:36:9 + | +LL | let _ = ().foo(); + | ^ --- type must be known at this point + | +note: multiple `impl`s satisfying `(): Foo<'_, _>` found + --> $DIR/issue-77982.rs:29:1 + | +LL | impl Foo<'static, u32> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> Foo<'a, i16> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: Box = ().foo(); + | ++++++++ + +error[E0283]: type annotations needed for `Box` + --> $DIR/issue-77982.rs:40:9 + | +LL | let _ = (&()).bar(); + | ^ --- type must be known at this point + | +note: multiple `impl`s satisfying `&(): Bar<'_, _>` found + --> $DIR/issue-77982.rs:32:1 + | +LL | impl<'a> Bar<'static, u32> for &'a () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl<'a> Bar<'a, i16> for &'a () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: Box = (&()).bar(); + | ++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs new file mode 100644 index 000000000..92f9f4b46 --- /dev/null +++ b/tests/ui/traits/issue-78372.rs @@ -0,0 +1,13 @@ +use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature 'dispatch_from_dyn' +struct Smaht(PhantomData); //~ ERROR cannot find type `PhantomData` in this scope +impl DispatchFromDyn> for T {} //~ ERROR cannot find type `U` in this scope +//~^ ERROR cannot find type `MISC` in this scope +//~| ERROR use of unstable library feature 'dispatch_from_dyn' +//~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures +trait Foo: X {} +trait X { + fn foo(self: Smaht); +} +trait Marker {} +impl Marker for dyn Foo {} +fn main() {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr new file mode 100644 index 000000000..8e7fd5f25 --- /dev/null +++ b/tests/ui/traits/issue-78372.stderr @@ -0,0 +1,65 @@ +error[E0412]: cannot find type `PhantomData` in this scope + --> $DIR/issue-78372.rs:2:23 + | +LL | struct Smaht(PhantomData); + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL | use std::marker::PhantomData; + | + +error[E0412]: cannot find type `U` in this scope + --> $DIR/issue-78372.rs:3:31 + | +LL | impl DispatchFromDyn> for T {} + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | impl DispatchFromDyn> for T {} + | ~ +help: you might be missing a type parameter + | +LL | impl DispatchFromDyn> for T {} + | +++ + +error[E0412]: cannot find type `MISC` in this scope + --> $DIR/issue-78372.rs:3:34 + | +LL | impl DispatchFromDyn> for T {} + | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl DispatchFromDyn> for T {} + | ++++++ + +error[E0658]: use of unstable library feature 'dispatch_from_dyn' + --> $DIR/issue-78372.rs:1:5 + | +LL | use std::ops::DispatchFromDyn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'dispatch_from_dyn' + --> $DIR/issue-78372.rs:3:9 + | +LL | impl DispatchFromDyn> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable + +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures + --> $DIR/issue-78372.rs:3:1 + | +LL | impl DispatchFromDyn> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0378`. diff --git a/tests/ui/traits/issue-78632.rs b/tests/ui/traits/issue-78632.rs new file mode 100644 index 000000000..c72a2aef4 --- /dev/null +++ b/tests/ui/traits/issue-78632.rs @@ -0,0 +1,59 @@ +// check-pass +// +// Regression test for issue #78632 + +#![crate_type = "lib"] + +pub trait Corge { + type Fred; +} + +impl Corge for () { + type Fred = u32; +} + +pub trait Waldo { + type Quax; +} + +impl Waldo for u32 { + type Quax = u8; +} + +pub trait Grault +where + (): Corge, +{ + type Thud; + fn bar(_: <() as Corge>::Fred) {} +} + +impl Grault for T +where + T: Waldo, + (): Corge, + <() as Corge>::Fred: Waldo, +{ + type Thud = u8; +} + +pub trait Plugh { + fn baz(); +} + +#[derive(Copy, Clone, Debug)] +pub struct Qiz { + foo: T, +} + +impl Plugh<<() as Corge>::Fred> for Qiz +where + T: Grault, + (): Corge, +{ + fn baz() {} +} + +pub fn test() { + as Plugh>::baz(); +} diff --git a/tests/ui/traits/issue-79458.rs b/tests/ui/traits/issue-79458.rs new file mode 100644 index 000000000..a41add6a1 --- /dev/null +++ b/tests/ui/traits/issue-79458.rs @@ -0,0 +1,10 @@ +// Negative implementations should not be shown in trait suggestions. +// This is a regression test of #79458. + +#[derive(Clone)] +struct Foo<'a, T> { + bar: &'a mut T + //~^ ERROR the trait bound `&mut T: Clone` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/issue-79458.stderr b/tests/ui/traits/issue-79458.stderr new file mode 100644 index 000000000..08f7bbbf0 --- /dev/null +++ b/tests/ui/traits/issue-79458.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `&mut T: Clone` is not satisfied + --> $DIR/issue-79458.rs:6:5 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Foo<'a, T> { +LL | bar: &'a mut T + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T` + | + = help: the trait `Clone` is implemented for `&T` + = note: `Clone` is implemented for `&T`, but not for `&mut T` + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-8153.rs b/tests/ui/traits/issue-8153.rs new file mode 100644 index 000000000..81a8f5338 --- /dev/null +++ b/tests/ui/traits/issue-8153.rs @@ -0,0 +1,16 @@ +// Test that duplicate methods in impls are not allowed + +struct Foo; + +trait Bar { + fn bar(&self) -> isize; +} + +impl Bar for Foo { + fn bar(&self) -> isize {1} + fn bar(&self) -> isize {2} //~ ERROR duplicate definitions +} + +fn main() { + println!("{}", Foo.bar()); +} diff --git a/tests/ui/traits/issue-8153.stderr b/tests/ui/traits/issue-8153.stderr new file mode 100644 index 000000000..ae214bb9e --- /dev/null +++ b/tests/ui/traits/issue-8153.stderr @@ -0,0 +1,14 @@ +error[E0201]: duplicate definitions with name `bar`: + --> $DIR/issue-8153.rs:11:5 + | +LL | fn bar(&self) -> isize; + | ----------------------- item in trait +... +LL | fn bar(&self) -> isize {1} + | -------------------------- previous definition here +LL | fn bar(&self) -> isize {2} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0201`. diff --git a/tests/ui/traits/issue-82830.rs b/tests/ui/traits/issue-82830.rs new file mode 100644 index 000000000..37bae2e90 --- /dev/null +++ b/tests/ui/traits/issue-82830.rs @@ -0,0 +1,18 @@ +// check-pass + +trait A { + type B; +} + +type MaybeBox = >>::B; +struct P { + t: MaybeBox

, +} + +impl A for P { + type B = N; +} + +fn main() { + let t: MaybeBox

) { + obj.is_derived(); + Base::::is_base(obj); + Base::<()>::is_base(obj); +} + +fn main() { + let x: fn(_) = f::<()>; + let x: fn(_) = f::; +} diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs new file mode 100644 index 000000000..538e74ee1 --- /dev/null +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.rs @@ -0,0 +1,24 @@ +struct A(T); +struct B; + +trait I {} +impl I for B {} +impl I for B {} + +trait V { + fn method(self) -> U; +} + +impl V for A +where + T: I, +{ + fn method(self) -> U { unimplemented!() } +} + +fn main() { + let a = A(B); + a.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} diff --git a/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr new file mode 100644 index 000000000..92d9d32cf --- /dev/null +++ b/tests/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -0,0 +1,41 @@ +error[E0282]: type annotations needed + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 + | +LL | a.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | as V>::method(a); + | +++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 + | +LL | a.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `B: I<_>` found + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:5:1 + | +LL | impl I for B {} + | ^^^^^^^^^^^^^^^^^ +LL | impl I for B {} + | ^^^^^^^^^^^^^^^^^ +note: required for `A` to implement `V<_>` + --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:12:12 + | +LL | impl V for A + | ^^^^ ^^^^ +LL | where +LL | T: I, + | ---- unsatisfied trait bound introduced here +help: try using a fully qualified path to specify the expected types + | +LL | as V>::method(a); + | +++++++++++++++++++++++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/object-does-not-impl-trait.rs b/tests/ui/traits/object-does-not-impl-trait.rs new file mode 100644 index 000000000..b3b679813 --- /dev/null +++ b/tests/ui/traits/object-does-not-impl-trait.rs @@ -0,0 +1,8 @@ +// Test that an object type `Box` is not considered to implement the +// trait `Foo`. Issue #5087. + +trait Foo {} +fn take_foo(f: F) {} +fn take_object(f: Box) { take_foo(f); } +//~^ ERROR `Box: Foo` is not satisfied +fn main() {} diff --git a/tests/ui/traits/object-does-not-impl-trait.stderr b/tests/ui/traits/object-does-not-impl-trait.stderr new file mode 100644 index 000000000..f1dd508a4 --- /dev/null +++ b/tests/ui/traits/object-does-not-impl-trait.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Box: Foo` is not satisfied + --> $DIR/object-does-not-impl-trait.rs:6:44 + | +LL | fn take_object(f: Box) { take_foo(f); } + | -------- ^ the trait `Foo` is not implemented for `Box` + | | + | required by a bound introduced by this call + | +note: required by a bound in `take_foo` + --> $DIR/object-does-not-impl-trait.rs:5:15 + | +LL | fn take_foo(f: F) {} + | ^^^ required by this bound in `take_foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/object-one-type-two-traits.rs b/tests/ui/traits/object-one-type-two-traits.rs new file mode 100644 index 000000000..86a2094ee --- /dev/null +++ b/tests/ui/traits/object-one-type-two-traits.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Testing creating two vtables with the same self type, but different +// traits. + +use std::any::Any; + +trait Wrap { + fn get(&self) -> isize; + fn wrap(self: Box) -> Box; +} + +impl Wrap for isize { + fn get(&self) -> isize { + *self + } + fn wrap(self: Box) -> Box { + self as Box + } +} + +fn is(x: &dyn Any) -> bool { + x.is::() +} + +fn main() { + let x = Box::new(22isize) as Box; + println!("x={}", x.get()); + let y = x.wrap(); +} diff --git a/tests/ui/traits/object/auto-dedup-in-impl.rs b/tests/ui/traits/object/auto-dedup-in-impl.rs new file mode 100644 index 000000000..85698f194 --- /dev/null +++ b/tests/ui/traits/object/auto-dedup-in-impl.rs @@ -0,0 +1,19 @@ +// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type. +// Issue: #47010 + +struct Struct; +impl Trait for Struct {} +trait Trait {} + +type Send1 = dyn Trait + Send; +type Send2 = dyn Trait + Send + Send; + +fn main () {} + +impl dyn Trait + Send { + fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test` +} + +impl dyn Trait + Send + Send { + fn test(&self) { println!("two"); } +} diff --git a/tests/ui/traits/object/auto-dedup-in-impl.stderr b/tests/ui/traits/object/auto-dedup-in-impl.stderr new file mode 100644 index 000000000..5f13c7813 --- /dev/null +++ b/tests/ui/traits/object/auto-dedup-in-impl.stderr @@ -0,0 +1,12 @@ +error[E0592]: duplicate definitions with name `test` + --> $DIR/auto-dedup-in-impl.rs:14:5 + | +LL | fn test(&self) { println!("one"); } + | ^^^^^^^^^^^^^^ duplicate definitions for `test` +... +LL | fn test(&self) { println!("two"); } + | -------------- other definition for `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/traits/object/auto-dedup.rs b/tests/ui/traits/object/auto-dedup.rs new file mode 100644 index 000000000..39d25eb7f --- /dev/null +++ b/tests/ui/traits/object/auto-dedup.rs @@ -0,0 +1,46 @@ +// run-pass + +#![allow(unused_assignments)] + +// Test that duplicate auto trait bounds in trait objects don't create new types. +#[allow(unused_assignments)] +use std::marker::Send as SendAlias; + +// A dummy trait for the non-auto trait. +trait Trait {} + +// A dummy struct to implement `Trait` and `Send`. +struct Struct; + +impl Trait for Struct {} + +// These three functions should be equivalent. +fn takes_dyn_trait_send(_: Box) {} +fn takes_dyn_trait_send_send(_: Box) {} +fn takes_dyn_trait_send_sendalias(_: Box) {} + +impl dyn Trait + Send + Send { + fn do_nothing(&self) {} +} + +fn main() { + // 1. Moving into a variable with more `Send`s and back. + let mut dyn_trait_send = Box::new(Struct) as Box; + let dyn_trait_send_send: Box = dyn_trait_send; + dyn_trait_send = dyn_trait_send_send; + + // 2. Calling methods with different number of `Send`s. + let dyn_trait_send = Box::new(Struct) as Box; + takes_dyn_trait_send_send(dyn_trait_send); + + let dyn_trait_send_send = Box::new(Struct) as Box; + takes_dyn_trait_send(dyn_trait_send_send); + + // 3. Aliases to the trait are transparent. + let dyn_trait_send = Box::new(Struct) as Box; + takes_dyn_trait_send_sendalias(dyn_trait_send); + + // 4. Calling an impl that duplicates an auto trait. + let dyn_trait_send = Box::new(Struct) as Box; + dyn_trait_send.do_nothing(); +} diff --git a/tests/ui/traits/object/bounds-cycle-1.rs b/tests/ui/traits/object/bounds-cycle-1.rs new file mode 100644 index 000000000..314676492 --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-1.rs @@ -0,0 +1,24 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/bounds-cycle-2.rs b/tests/ui/traits/object/bounds-cycle-2.rs new file mode 100644 index 000000000..4c1df3805 --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-2.rs @@ -0,0 +1,28 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Super { + type V; +} + +trait Obj: Super { + type U: Is; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/bounds-cycle-3.rs b/tests/ui/traits/object/bounds-cycle-3.rs new file mode 100644 index 000000000..55726a5ae --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-3.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::V` in the +// bound below. + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj { + type U: Is; + type V; +} + +fn is_obj(_: &T) {} + +fn f(x: &dyn Obj) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/bounds-cycle-4.rs b/tests/ui/traits/object/bounds-cycle-4.rs new file mode 100644 index 000000000..f83cb75c7 --- /dev/null +++ b/tests/ui/traits/object/bounds-cycle-4.rs @@ -0,0 +1,25 @@ +// Check that we don't have a cycle when we try to normalize `Self::U` in the +// bound below. Make sure that having a lifetime on the trait object doesn't break things + +// check-pass + +trait Is { + type T; +} + +impl Is for U { + type T = U; +} + +trait Obj<'a> { + type U: Is; + type V; +} + +fn is_obj<'a, T: ?Sized + Obj<'a>>(_: &T) {} + +fn f<'a>(x: &dyn Obj<'a, U = i32, V = i32>) { + is_obj(x) +} + +fn main() {} diff --git a/tests/ui/traits/object/enforce-supertrait-projection.rs b/tests/ui/traits/object/enforce-supertrait-projection.rs new file mode 100644 index 000000000..2c9b41eea --- /dev/null +++ b/tests/ui/traits/object/enforce-supertrait-projection.rs @@ -0,0 +1,24 @@ +trait SuperTrait { + type A; + type B; +} + +trait Trait: SuperTrait::B> {} + +fn transmute(x: A) -> B { + foo::>(x) + //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` +} + +fn foo(x: T::A) -> B +where + T: Trait, +{ + x +} + +static X: u8 = 0; +fn main() { + let x = transmute::<&u8, &[u8; 1_000_000]>(&X); + println!("{:?}", x[100_000]); +} diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr new file mode 100644 index 000000000..cbf093866 --- /dev/null +++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr @@ -0,0 +1,26 @@ +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` + --> $DIR/enforce-supertrait-projection.rs:9:17 + | +LL | fn transmute(x: A) -> B { + | - - expected type parameter + | | + | found type parameter +LL | foo::>(x) + | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` + | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: required by a bound in `foo` + --> $DIR/enforce-supertrait-projection.rs:15:8 + | +LL | fn foo(x: T::A) -> B + | --- required by a bound in this +LL | where +LL | T: Trait, + | ^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/object/exclusion.rs b/tests/ui/traits/object/exclusion.rs new file mode 100644 index 000000000..766dceeaf --- /dev/null +++ b/tests/ui/traits/object/exclusion.rs @@ -0,0 +1,19 @@ +// run-pass +trait Future: 'static { + // The requirement for Self: Sized must prevent instantiation of + // Future::forget in vtables, otherwise there's an infinite type + // recursion through as Future>::forget. + fn forget(self) where Self: Sized { + Box::new(Map(self)) as Box; + } +} + +struct Map(#[allow(unused_tuple_struct_fields)] A); +impl Future for Map {} + +pub struct Promise; +impl Future for Promise {} + +fn main() { + Promise.forget(); +} diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs new file mode 100644 index 000000000..5a4a6aecc --- /dev/null +++ b/tests/ui/traits/object/generics.rs @@ -0,0 +1,41 @@ +// run-pass +// test for #8664 + +use std::marker; + +pub trait Trait2 { + fn doit(&self) -> A; +} + +pub struct Impl { + m1: marker::PhantomData<(A1,A2,A3)>, + /* + * With A2 we get the ICE: + * task failed at 'index out of bounds: the len is 1 but the index is 1', + * src/librustc/middle/subst.rs:58 + */ + t: Box+'static> +} + +impl Impl { + pub fn step(&self) { + self.t.doit(); + } +} + +// test for #8601 + +enum Type { Constant(#[allow(unused_tuple_struct_fields)] T) } + +trait Trait { + fn method(&self, _: Type<(K,V)>) -> isize; +} + +impl Trait for () { + fn method(&self, _x: Type<(u8,V)>) -> isize { 0 } +} + +pub fn main() { + let a = Box::new(()) as Box>; + assert_eq!(a.method(Type::Constant((1, 2))), 0); +} diff --git a/tests/ui/traits/object/issue-33140-traitobject-crate.rs b/tests/ui/traits/object/issue-33140-traitobject-crate.rs new file mode 100644 index 000000000..8abd92da3 --- /dev/null +++ b/tests/ui/traits/object/issue-33140-traitobject-crate.rs @@ -0,0 +1,108 @@ +// check-pass + +#![warn(order_dependent_trait_objects)] +#![allow(dyn_drop)] + +// Check that traitobject 0.1.0 compiles + +//! # traitobject +//! +//! Unsafe helpers for working with raw TraitObjects. + +/// A trait implemented for all trait objects. +/// +/// Implementations for all traits in std are provided. +pub unsafe trait Trait {} + +unsafe impl Trait for dyn (::std::any::Any) + Send { } +unsafe impl Trait for dyn (::std::any::Any) + Sync { } +unsafe impl Trait for dyn (::std::any::Any) + Send + Sync { } +unsafe impl Trait for dyn (::std::borrow::Borrow) + Send { } +unsafe impl Trait for dyn (::std::borrow::Borrow) + Sync { } +unsafe impl Trait for dyn (::std::borrow::Borrow) + Send + Sync { } +unsafe impl Trait for dyn (::std::borrow::BorrowMut) + Send { } +unsafe impl Trait for dyn (::std::borrow::BorrowMut) + Sync { } +unsafe impl Trait for dyn (::std::borrow::BorrowMut) + Send + Sync { } +unsafe impl Trait for dyn (::std::convert::AsMut) + Send { } +unsafe impl Trait for dyn (::std::convert::AsMut) + Sync { } +unsafe impl Trait for dyn (::std::convert::AsMut) + Send + Sync { } +unsafe impl Trait for dyn (::std::convert::AsRef) + Send { } +unsafe impl Trait for dyn (::std::convert::AsRef) + Sync { } +unsafe impl Trait for dyn (::std::convert::AsRef) + Send + Sync { } +unsafe impl Trait for dyn (::std::error::Error) + Send { } +unsafe impl Trait for dyn (::std::error::Error) + Sync { } +unsafe impl Trait for dyn (::std::error::Error) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Send { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Binary) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Send { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Debug) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Display) + Send { } +unsafe impl Trait for dyn (::std::fmt::Display) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Display) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerExp) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Sync { } +unsafe impl Trait for dyn (::std::fmt::LowerHex) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Send { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Octal) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Send { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Pointer) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperExp) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Sync { } +unsafe impl Trait for dyn (::std::fmt::UpperHex) + Send + Sync { } +unsafe impl Trait for dyn (::std::fmt::Write) + Send { } +unsafe impl Trait for dyn (::std::fmt::Write) + Sync { } +unsafe impl Trait for dyn (::std::fmt::Write) + Send + Sync { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Send { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Sync { } +unsafe impl Trait for dyn (::std::hash::Hasher) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::BufRead) + Send { } +unsafe impl Trait for dyn (::std::io::BufRead) + Sync { } +unsafe impl Trait for dyn (::std::io::BufRead) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Read) + Send { } +unsafe impl Trait for dyn (::std::io::Read) + Sync { } +unsafe impl Trait for dyn (::std::io::Read) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Seek) + Send { } +unsafe impl Trait for dyn (::std::io::Seek) + Sync { } +unsafe impl Trait for dyn (::std::io::Seek) + Send + Sync { } +unsafe impl Trait for dyn (::std::io::Write) + Send { } +unsafe impl Trait for dyn (::std::io::Write) + Sync { } +unsafe impl Trait for dyn (::std::io::Write) + Send + Sync { } +unsafe impl Trait for dyn (::std::iter::IntoIterator) { } +unsafe impl Trait for dyn (::std::iter::Iterator) + Send { } +unsafe impl Trait for dyn (::std::iter::Iterator) + Sync { } +unsafe impl Trait for dyn (::std::iter::Iterator) + Send + Sync { } +unsafe impl Trait for dyn (::std::marker::Send) + Send { } +unsafe impl Trait for dyn (::std::marker::Send) + Sync { } +unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::marker::Sync) + Send { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::marker::Sync) + Sync { } +unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } +//~^ WARNING conflicting implementations of trait `Trait` for type +//~| WARNING this was previously accepted by the compiler but is being phased out +unsafe impl Trait for dyn (::std::ops::Drop) + Send { } +unsafe impl Trait for dyn (::std::ops::Drop) + Sync { } +unsafe impl Trait for dyn (::std::ops::Drop) + Send + Sync { } +unsafe impl Trait for dyn (::std::string::ToString) + Send { } +unsafe impl Trait for dyn (::std::string::ToString) + Sync { } +unsafe impl Trait for dyn (::std::string::ToString) + Send + Sync { } +fn assert_trait() {} + +fn main() { + assert_trait::(); + assert_trait::(); + assert_trait::(); +} diff --git a/tests/ui/traits/object/issue-33140-traitobject-crate.stderr b/tests/ui/traits/object/issue-33140-traitobject-crate.stderr new file mode 100644 index 000000000..525401f9d --- /dev/null +++ b/tests/ui/traits/object/issue-33140-traitobject-crate.stderr @@ -0,0 +1,95 @@ +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:86:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { } + | ------------------------------------------------------ first implementation here +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:89:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ------------------------------------------------------------- first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:93:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ------------------------------------------------------ first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 + +warning: 3 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:86:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { } + | ------------------------------------------------------ first implementation here +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:89:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { } + | ------------------------------------------------------------- first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: conflicting implementations of trait `Trait` for type `(dyn Send + Sync + 'static)`: (E0119) + --> $DIR/issue-33140-traitobject-crate.rs:93:1 + | +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { } + | ------------------------------------------------------ first implementation here +... +LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Send + Sync + 'static)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56484 +note: the lint level is defined here + --> $DIR/issue-33140-traitobject-crate.rs:3:9 + | +LL | #![warn(order_dependent_trait_objects)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/traits/object/issue-44454-1.rs b/tests/ui/traits/object/issue-44454-1.rs new file mode 100644 index 000000000..bbaf3188a --- /dev/null +++ b/tests/ui/traits/object/issue-44454-1.rs @@ -0,0 +1,22 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333 + +trait Animal: 'static {} + +fn foo() +where + Y: Animal + ?Sized, +{ + // `Y` implements `Animal` so `Y` is 'static. + baz::() +} + +fn bar<'a>(_arg: &'a i32) { + foo::, &'a i32>() //~ ERROR: lifetime may not live long enough +} + +fn baz() {} + +fn main() { + let a = 5; + bar(&a); +} diff --git a/tests/ui/traits/object/issue-44454-1.stderr b/tests/ui/traits/object/issue-44454-1.stderr new file mode 100644 index 000000000..859487f50 --- /dev/null +++ b/tests/ui/traits/object/issue-44454-1.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-44454-1.rs:14:5 + | +LL | fn bar<'a>(_arg: &'a i32) { + | -- lifetime `'a` defined here +LL | foo::, &'a i32>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/object/issue-44454-2.rs b/tests/ui/traits/object/issue-44454-2.rs new file mode 100644 index 000000000..f5178bcdb --- /dev/null +++ b/tests/ui/traits/object/issue-44454-2.rs @@ -0,0 +1,22 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928 + +trait Trait: 'static { + type Assoc: AsRef; +} + +fn hr(x: T::Assoc) -> Box + 'static> +where + T: Trait +{ + Box::new(x) +} + +fn extend_lt<'a>(x: &'a str) -> Box + 'static> { + type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; + hr::(x) //~ ERROR: borrowed data escapes outside of function +} + +fn main() { + let extended = extend_lt(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); +} diff --git a/tests/ui/traits/object/issue-44454-2.stderr b/tests/ui/traits/object/issue-44454-2.stderr new file mode 100644 index 000000000..7f574769b --- /dev/null +++ b/tests/ui/traits/object/issue-44454-2.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-44454-2.rs:16:5 + | +LL | fn extend_lt<'a>(x: &'a str) -> Box + 'static> { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; +LL | hr::(x) + | ^^^^^^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/traits/object/issue-44454-3.rs b/tests/ui/traits/object/issue-44454-3.rs new file mode 100644 index 000000000..bff727035 --- /dev/null +++ b/tests/ui/traits/object/issue-44454-3.rs @@ -0,0 +1,33 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290 + +use std::any::Any; + +trait Animal: 'static {} + +trait Projector { + type Foo; +} + +impl Projector for dyn Animal { + type Foo = X; +} + +fn make_static<'a, T>(t: &'a T) -> &'static T { + let x: as Projector>::Foo = t; + let any = generic::, &'a T>(x); + //~^ ERROR: lifetime may not live long enough + any.downcast_ref::<&'static T>().unwrap() +} + +fn generic + ?Sized, U>(x: ::Foo) -> Box { + make_static_any(x) +} + +fn make_static_any(u: U) -> Box { + Box::new(u) +} + +fn main() { + let a = make_static(&"salut".to_string()); + println!("{}", *a); +} diff --git a/tests/ui/traits/object/issue-44454-3.stderr b/tests/ui/traits/object/issue-44454-3.stderr new file mode 100644 index 000000000..294684d26 --- /dev/null +++ b/tests/ui/traits/object/issue-44454-3.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-44454-3.rs:17:15 + | +LL | fn make_static<'a, T>(t: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let x: as Projector>::Foo = t; +LL | let any = generic::, &'a T>(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/object/lifetime-first.rs b/tests/ui/traits/object/lifetime-first.rs new file mode 100644 index 000000000..33757cb7c --- /dev/null +++ b/tests/ui/traits/object/lifetime-first.rs @@ -0,0 +1,13 @@ +// run-pass +use std::fmt::Display; + +static BYTE: u8 = 33; + +fn main() { + let x: &(dyn 'static + Display) = &BYTE; + let y: Box = Box::new(BYTE); + let xstr = format!("{}", x); + let ystr = format!("{}", y); + assert_eq!(xstr, "33"); + assert_eq!(ystr, "33"); +} diff --git a/tests/ui/traits/object/macro-matcher.rs b/tests/ui/traits/object/macro-matcher.rs new file mode 100644 index 000000000..910978749 --- /dev/null +++ b/tests/ui/traits/object/macro-matcher.rs @@ -0,0 +1,12 @@ +// `ty` matcher accepts trait object types + +macro_rules! m { + ($t: ty) => ( let _: $t; ) +} + +fn main() { + m!(dyn Copy + Send + 'static); + //~^ ERROR the trait `Copy` cannot be made into an object + m!(dyn 'static + Send); + m!(dyn 'static +); //~ ERROR at least one trait is required for an object type +} diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr new file mode 100644 index 000000000..6d1e236c0 --- /dev/null +++ b/tests/ui/traits/object/macro-matcher.stderr @@ -0,0 +1,19 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/macro-matcher.rs:11:8 + | +LL | m!(dyn 'static +); + | ^^^^^^^^^^^^^ + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/macro-matcher.rs:8:8 + | +LL | m!(dyn Copy + Send + 'static); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0224. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs new file mode 100644 index 000000000..f43d332d6 --- /dev/null +++ b/tests/ui/traits/object/safety.rs @@ -0,0 +1,17 @@ +// Check that static methods are not object-safe. + +trait Tr { + fn foo(); + fn bar(&self) { } +} + +struct St; + +impl Tr for St { + fn foo() {} +} + +fn main() { + let _: &dyn Tr = &St; //~ ERROR E0038 + //~^ ERROR E0038 +} diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr new file mode 100644 index 000000000..dc18adeaf --- /dev/null +++ b/tests/ui/traits/object/safety.stderr @@ -0,0 +1,49 @@ +error[E0038]: the trait `Tr` cannot be made into an object + --> $DIR/safety.rs:15:22 + | +LL | let _: &dyn Tr = &St; + | ^^^ `Tr` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/safety.rs:4:8 + | +LL | trait Tr { + | -- this trait cannot be made into an object... +LL | fn foo(); + | ^^^ ...because associated function `foo` has no `self` parameter + = note: required for `&St` to implement `CoerceUnsized<&dyn Tr>` + = note: required by cast to type `&dyn Tr` +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self); + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | +++++++++++++++++ + +error[E0038]: the trait `Tr` cannot be made into an object + --> $DIR/safety.rs:15:12 + | +LL | let _: &dyn Tr = &St; + | ^^^^^^^ `Tr` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/safety.rs:4:8 + | +LL | trait Tr { + | -- this trait cannot be made into an object... +LL | fn foo(); + | ^^^ ...because associated function `foo` has no `self` parameter +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self); + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.rs b/tests/ui/traits/object/supertrait-lifetime-bound.rs new file mode 100644 index 000000000..f929a9bb6 --- /dev/null +++ b/tests/ui/traits/object/supertrait-lifetime-bound.rs @@ -0,0 +1,14 @@ +trait Foo: 'static { } + +trait Bar: Foo { } + +fn test1, S>() { } + +fn test2<'a>() { + // Here: the type `dyn Bar<&'a u32>` references `'a`, + // and so it does not outlive `'static`. + test1::, _>(); + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/traits/object/supertrait-lifetime-bound.stderr b/tests/ui/traits/object/supertrait-lifetime-bound.stderr new file mode 100644 index 000000000..ed2f86243 --- /dev/null +++ b/tests/ui/traits/object/supertrait-lifetime-bound.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/supertrait-lifetime-bound.rs:10:5 + | +LL | fn test2<'a>() { + | -- lifetime `'a` defined here +... +LL | test1::, _>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/traits/object/vs-lifetime-2.rs b/tests/ui/traits/object/vs-lifetime-2.rs new file mode 100644 index 000000000..0b33dc7f6 --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime-2.rs @@ -0,0 +1,11 @@ +// A few contrived examples where lifetime should (or should not) be parsed as an object type. +// Lifetimes parsed as types are still rejected later by semantic checks. + +// `'static` is a lifetime, `'static +` is a type, `'a` is a type +fn g() where + 'static: 'static, + dyn 'static +: 'static + Copy, + //~^ ERROR at least one trait is required for an object type +{} + +fn main() {} diff --git a/tests/ui/traits/object/vs-lifetime-2.stderr b/tests/ui/traits/object/vs-lifetime-2.stderr new file mode 100644 index 000000000..9b8e793df --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime-2.stderr @@ -0,0 +1,9 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime-2.rs:7:5 + | +LL | dyn 'static +: 'static + Copy, + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/object/vs-lifetime.rs b/tests/ui/traits/object/vs-lifetime.rs new file mode 100644 index 000000000..14ae67cff --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime.rs @@ -0,0 +1,17 @@ +// A few contrived examples where lifetime should (or should not) be parsed as an object type. +// Lifetimes parsed as types are still rejected later by semantic checks. + +struct S<'a, T>(&'a u8, T); + +fn main() { + // `'static` is a lifetime argument, `'static +` is a type argument + let _: S<'static, u8>; + let _: S<'static, dyn 'static +>; + //~^ at least one trait is required for an object type + let _: S<'static, 'static>; + //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| ERROR this struct takes 1 generic argument but 0 generic arguments were supplied + let _: S; + //~^ ERROR type provided when a lifetime was expected + //~| ERROR at least one trait is required for an object type +} diff --git a/tests/ui/traits/object/vs-lifetime.stderr b/tests/ui/traits/object/vs-lifetime.stderr new file mode 100644 index 000000000..224465228 --- /dev/null +++ b/tests/ui/traits/object/vs-lifetime.stderr @@ -0,0 +1,52 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime.rs:9:23 + | +LL | let _: S<'static, dyn 'static +>; + | ^^^^^^^^^^^^^ + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/vs-lifetime.rs:11:12 + | +LL | let _: S<'static, 'static>; + | ^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/vs-lifetime.rs:4:8 + | +LL | struct S<'a, T>(&'a u8, T); + | ^ -- + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/vs-lifetime.rs:11:12 + | +LL | let _: S<'static, 'static>; + | ^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/vs-lifetime.rs:4:8 + | +LL | struct S<'a, T>(&'a u8, T); + | ^ - +help: add missing generic argument + | +LL | let _: S<'static, 'static, T>; + | +++ + +error[E0224]: at least one trait is required for an object type + --> $DIR/vs-lifetime.rs:14:14 + | +LL | let _: S; + | ^^^^^^^^^^^^^ + +error[E0747]: type provided when a lifetime was expected + --> $DIR/vs-lifetime.rs:14:14 + | +LL | let _: S; + | ^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0107, E0224, E0747. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/object/with-lifetime-bound.rs b/tests/ui/traits/object/with-lifetime-bound.rs new file mode 100644 index 000000000..05aab5e3b --- /dev/null +++ b/tests/ui/traits/object/with-lifetime-bound.rs @@ -0,0 +1,34 @@ +// run-pass +// Uncovered during work on new scoping rules for safe destructors +// as an important use case to support properly. + + +pub struct E<'a> { + pub f: &'a u8, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b u8 { self.f } +} + +pub struct P<'c> { + pub g: &'c u8, +} +pub trait M { + fn n(&self) -> u8; +} +impl<'d> M for P<'d> { + fn n(&self) -> u8 { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return Box::new(p) as Box; + } +} + +fn main() { + let w = E { f: &10 }; + let o = extension(&w); + assert_eq!(o.n(), 10); +} diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.rs b/tests/ui/traits/object/with-self-in-projection-output-bad.rs new file mode 100644 index 000000000..f34fa80a0 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-bad.rs @@ -0,0 +1,50 @@ +// Regression test for #56288. Checks that if a supertrait defines an associated type +// projection that references `Self`, then that associated type must still be explicitly +// specified in the `dyn Trait` variant, since we don't know what `Self` is anymore. + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +// Test that you still need to manually give a projection type if the Output type +// is normalizable. +trait NormalizableHelper: + Base::Out> +{ + type Target; +} + +impl NormalizableHelper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified + + let _y: Box> = Box::new(2u32); + //~^ ERROR the value of the associated type `Output` (from trait `Base`) must be specified +} diff --git a/tests/ui/traits/object/with-self-in-projection-output-bad.stderr b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr new file mode 100644 index 000000000..641bfe236 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-bad.stderr @@ -0,0 +1,21 @@ +error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified + --> $DIR/with-self-in-projection-output-bad.rs:45:21 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let _x: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^ help: specify the associated type: `Helper` + +error[E0191]: the value of the associated type `Output` (from trait `Base`) must be specified + --> $DIR/with-self-in-projection-output-bad.rs:48:21 + | +LL | type Output; + | ----------- `Output` defined here +... +LL | let _y: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated type: `NormalizableHelper` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/traits/object/with-self-in-projection-output-good.rs b/tests/ui/traits/object/with-self-in-projection-output-good.rs new file mode 100644 index 000000000..d1b7bf6c2 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-good.rs @@ -0,0 +1,28 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` can be ok if it is referencing a projection (of +// `Self::Target`, in this case). Note that we still require the user to manually +// specify both `Target` and `Output` for now. + +trait Base { + type Output; +} + +trait Helper: Base::Target> { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl Helper for u32 +{ + type Target = i32; +} + +fn main() { + let _x: Box> = Box::new(2u32); +} diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs new file mode 100644 index 000000000..39e817168 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs @@ -0,0 +1,51 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// FIXME(eddyb) shorten the name so windows doesn't choke on it. +#![crate_name = "trait_test"] + +// Regression test related to #56288. Check that a supertrait projection (of +// `Output`) that references `Self` is ok if there is another occurrence of +// the same supertrait that specifies the projection explicitly, even if +// the projection's associated type is not explicitly specified in the object type. +// +// Note that in order for this to compile, we need the `Self`-referencing projection +// to normalize fairly directly to a concrete type, otherwise the trait resolver +// will hate us. +// +// There is a test in `trait-object-with-self-in-projection-output-bad.rs` that +// having a normalizing, but `Self`-containing projection does not *by itself* +// allow you to avoid writing the projected type (`Output`, in this example) +// explicitly. + +trait ConstI32 { + type Out; +} + +impl ConstI32 for T { + type Out = i32; +} + +trait Base { + type Output; +} + +trait NormalizingHelper: Base::Out> + Base { + type Target; +} + +impl Base for u32 +{ + type Output = i32; +} + +impl NormalizingHelper for u32 +{ + type Target = i32; +} + +fn main() { + // Make sure this works both with and without the associated type + // being specified. + let _x: Box> = Box::new(2u32); + let _y: Box> = Box::new(2u32); +} diff --git a/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs b/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs new file mode 100644 index 000000000..fce1341fc --- /dev/null +++ b/tests/ui/traits/objects-owned-object-borrowed-method-headerless.rs @@ -0,0 +1,30 @@ +// run-pass +// Test invoked `&self` methods on owned objects where the values +// closed over do not contain managed values, and thus the boxes do +// not have headers. + +trait FooTrait { + fn foo(&self) -> usize; +} + +struct BarStruct { + x: usize +} + +impl FooTrait for BarStruct { + fn foo(&self) -> usize { + self.x + } +} + +pub fn main() { + let foos: Vec> = vec![ + Box::new(BarStruct{ x: 0 }) as Box, + Box::new(BarStruct{ x: 1 }) as Box, + Box::new(BarStruct{ x: 2 }) as Box, + ]; + + for i in 0..foos.len() { + assert_eq!(i, foos[i].foo()); + } +} diff --git a/tests/ui/traits/operator-overloading-issue-52025.rs b/tests/ui/traits/operator-overloading-issue-52025.rs new file mode 100644 index 000000000..7ce638832 --- /dev/null +++ b/tests/ui/traits/operator-overloading-issue-52025.rs @@ -0,0 +1,57 @@ +// only-x86_64 +// build-pass + +use std::arch::x86_64::*; +use std::fmt::Debug; +use std::ops::*; + +pub trait Simd { + type Vf32: Copy + Debug + Add + Add; + + unsafe fn set1_ps(a: f32) -> Self::Vf32; + unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32; +} + +#[derive(Copy, Debug, Clone)] +pub struct F32x4(pub __m128); + +impl Add for F32x4 { + type Output = F32x4; + + fn add(self, rhs: F32x4) -> F32x4 { + F32x4(unsafe { _mm_add_ps(self.0, rhs.0) }) + } +} + +impl Add for F32x4 { + type Output = F32x4; + fn add(self, rhs: f32) -> F32x4 { + F32x4(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }) + } +} + +pub struct Sse2; +impl Simd for Sse2 { + type Vf32 = F32x4; + + #[inline(always)] + unsafe fn set1_ps(a: f32) -> Self::Vf32 { + F32x4(_mm_set1_ps(a)) + } + + #[inline(always)] + unsafe fn add_ps(a: Self::Vf32, b: Self::Vf32) -> Self::Vf32 { + F32x4(_mm_add_ps(a.0, b.0)) + } +} + +unsafe fn test() -> S::Vf32 { + let a = S::set1_ps(3.0); + let b = S::set1_ps(2.0); + let result = a + b; + result +} + +fn main() { + println!("{:?}", unsafe { test::() }); +} diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs new file mode 100644 index 000000000..4106f56d6 --- /dev/null +++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.rs @@ -0,0 +1,10 @@ +#![allow(dead_code)] +#![feature(negative_impls)] + +// Overlapping negative impls for `MyStruct` are not permitted: +struct MyStruct; +impl !Send for MyStruct {} +impl !Send for MyStruct {} +//~^ ERROR conflicting implementations of trait + +fn main() {} diff --git a/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr new file mode 100644 index 000000000..e24ed695d --- /dev/null +++ b/tests/ui/traits/overlap-not-permitted-for-builtin-trait.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Send` for type `MyStruct` + --> $DIR/overlap-not-permitted-for-builtin-trait.rs:7:1 + | +LL | impl !Send for MyStruct {} + | ----------------------- first implementation here +LL | impl !Send for MyStruct {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/overlap-permitted-for-marker-traits.rs b/tests/ui/traits/overlap-permitted-for-marker-traits.rs new file mode 100644 index 000000000..00823d13b --- /dev/null +++ b/tests/ui/traits/overlap-permitted-for-marker-traits.rs @@ -0,0 +1,28 @@ +// run-pass +// Tests for RFC 1268: we allow overlapping impls of marker traits, +// that is, traits without items. In this case, a type `T` is +// `MyMarker` if it is either `Debug` or `Display`. + +#![feature(marker_trait_attr)] +#![feature(negative_impls)] + +use std::fmt::{Debug, Display}; + +#[marker] +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for T {} + +fn foo(t: T) -> T { + t +} + +fn main() { + // Debug && Display: + assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); + + // Debug && !Display: + assert_eq!(vec![1], foo(vec![1])); +} diff --git a/tests/ui/traits/param-without-lifetime-constraint.rs b/tests/ui/traits/param-without-lifetime-constraint.rs new file mode 100644 index 000000000..a79b74dcd --- /dev/null +++ b/tests/ui/traits/param-without-lifetime-constraint.rs @@ -0,0 +1,20 @@ +struct Article { + proof_reader: ProofReader, +} + +struct ProofReader { + name: String, +} + +pub trait HaveRelationship { + fn get_relation(&self) -> To; +} + +impl HaveRelationship<&ProofReader> for Article { + fn get_relation(&self) -> &ProofReader { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + &self.proof_reader + } +} + +fn main() {} diff --git a/tests/ui/traits/param-without-lifetime-constraint.stderr b/tests/ui/traits/param-without-lifetime-constraint.stderr new file mode 100644 index 000000000..b128b6518 --- /dev/null +++ b/tests/ui/traits/param-without-lifetime-constraint.stderr @@ -0,0 +1,19 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/param-without-lifetime-constraint.rs:14:5 + | +LL | fn get_relation(&self) -> To; + | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader` +... +LL | fn get_relation(&self) -> &ProofReader { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader` + | + = note: expected signature `fn(&'1 Article) -> &'2 ProofReader` + found signature `fn(&'1 Article) -> &'1 ProofReader` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/param-without-lifetime-constraint.rs:10:31 + | +LL | fn get_relation(&self) -> To; + | ^^ consider borrowing this type parameter in the trait + +error: aborting due to previous error + diff --git a/tests/ui/traits/parameterized-with-bounds.rs b/tests/ui/traits/parameterized-with-bounds.rs new file mode 100644 index 000000000..832d4f6c8 --- /dev/null +++ b/tests/ui/traits/parameterized-with-bounds.rs @@ -0,0 +1,21 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + + +trait A { fn get(self) -> T; } +trait B { fn get(self) -> (T,U); } +trait C<'a, U> { fn get(self) -> &'a U; } + +mod foo { + pub trait D<'a, T> { fn get(self) -> &'a T; } +} + +fn foo1(_: &(dyn A + Send)) {} +fn foo2(_: Box + Send + Sync>) {} +fn foo3(_: Box + 'static>) {} +fn foo4<'a, T>(_: Box + 'static + Send>) {} +fn foo5<'a, T>(_: Box + 'static + Send>) {} + +pub fn main() {} diff --git a/tests/ui/traits/pointee-deduction.rs b/tests/ui/traits/pointee-deduction.rs new file mode 100644 index 000000000..c333b0129 --- /dev/null +++ b/tests/ui/traits/pointee-deduction.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(ptr_metadata)] + +use std::alloc::Layout; +use std::ptr::Pointee; + +trait Foo { + type Bar; +} + +impl Foo for () { + type Bar = (); +} + +struct Wrapper1(#[allow(unused_tuple_struct_fields)] ::Bar); +struct Wrapper2(#[allow(unused_tuple_struct_fields)] as Pointee>::Metadata); + +fn main() { + let _: Wrapper2<()> = Wrapper2(()); + let _ = Layout::new::>(); +} diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.rs b/tests/ui/traits/pointee-tail-is-generic-errors.rs new file mode 100644 index 000000000..28bc1da96 --- /dev/null +++ b/tests/ui/traits/pointee-tail-is-generic-errors.rs @@ -0,0 +1,22 @@ +// edition:2018 + +#![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] + +type Opaque = impl std::fmt::Debug + ?Sized; + +fn opaque() -> &'static Opaque { + &[1] as &[i32] +} + +fn a() { + is_thin::(); + //~^ ERROR type mismatch resolving `::Metadata == ()` + + is_thin::(); + //~^ ERROR type mismatch resolving `::Metadata == ()` +} + +fn is_thin + ?Sized>() {} + +fn main() {} diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.stderr b/tests/ui/traits/pointee-tail-is-generic-errors.stderr new file mode 100644 index 000000000..0c3d7060d --- /dev/null +++ b/tests/ui/traits/pointee-tail-is-generic-errors.stderr @@ -0,0 +1,40 @@ +error[E0271]: type mismatch resolving `::Metadata == ()` + --> $DIR/pointee-tail-is-generic-errors.rs:13:15 + | +LL | is_thin::(); + | ^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Metadata` + = help: consider constraining the associated type `::Metadata` to `()` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `is_thin` + --> $DIR/pointee-tail-is-generic-errors.rs:20:33 + | +LL | fn is_thin + ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `is_thin` + +error[E0271]: type mismatch resolving `::Metadata == ()` + --> $DIR/pointee-tail-is-generic-errors.rs:16:15 + | +LL | type Opaque = impl std::fmt::Debug + ?Sized; + | ----------------------------- the found opaque type +... +LL | is_thin::(); + | ^^^^^^ expected `()`, found associated type + | + = note: expected unit type `()` + found associated type `::Metadata` +note: required by a bound in `is_thin` + --> $DIR/pointee-tail-is-generic-errors.rs:20:33 + | +LL | fn is_thin + ?Sized>() {} + | ^^^^^^^^^^^^^ required by this bound in `is_thin` +help: consider constraining the associated type `::Metadata` to `()` + | +LL | type Opaque = impl std::fmt::Debug + ?Sized; + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/pointee-tail-is-generic.rs b/tests/ui/traits/pointee-tail-is-generic.rs new file mode 100644 index 000000000..e0da0fc38 --- /dev/null +++ b/tests/ui/traits/pointee-tail-is-generic.rs @@ -0,0 +1,29 @@ +// check-pass +// edition:2018 + +#![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] + +type Opaque = impl std::future::Future; + +fn opaque() -> Opaque { + async {} +} + +fn a() { + // type parameter T is known to be sized + is_thin::(); + // tail of ADT (which is a type param) is known to be sized + is_thin::>(); + // opaque type is known to be sized + is_thin::(); +} + +fn a2() { + // associated type is known to be sized + is_thin::(); +} + +fn is_thin>() {} + +fn main() {} diff --git a/tests/ui/traits/principal-less-objects.rs b/tests/ui/traits/principal-less-objects.rs new file mode 100644 index 000000000..62bad0d7d --- /dev/null +++ b/tests/ui/traits/principal-less-objects.rs @@ -0,0 +1,42 @@ +// run-pass +// Check that trait objects without a principal codegen properly. + +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::mem; + +// Array is to make sure the size is not exactly pointer-size, so +// we can be sure we are measuring the right size in the +// `size_of_val` test. +struct SetOnDrop<'a>(&'a AtomicUsize, #[allow(unused_tuple_struct_fields)] [u8; 64]); +impl<'a> Drop for SetOnDrop<'a> { + fn drop(&mut self) { + self.0.store(self.0.load(Ordering::Relaxed) + 1, Ordering::Relaxed); + } +} + +trait TypeEq {} +impl TypeEq for T {} +fn assert_types_eq() where U: TypeEq {} + +fn main() { + // Check that different ways of writing the same type are equal. + assert_types_eq::(); + assert_types_eq::(); + assert_types_eq::(); + + // Check that codegen works. + // + // Using `AtomicUsize` here because `Cell` is not `Sync`, and + // so can't be made into a `Box`. + let c = AtomicUsize::new(0); + { + let d: Box = Box::new(SetOnDrop(&c, [0; 64])); + + assert_eq!(mem::size_of_val(&*d), + mem::size_of::()); + assert_eq!(mem::align_of_val(&*d), + mem::align_of::()); + assert_eq!(c.load(Ordering::Relaxed), 0); + } + assert_eq!(c.load(Ordering::Relaxed), 1); +} diff --git a/tests/ui/traits/privacy.rs b/tests/ui/traits/privacy.rs new file mode 100644 index 000000000..17a2e05e9 --- /dev/null +++ b/tests/ui/traits/privacy.rs @@ -0,0 +1,24 @@ +// build-pass (FIXME(62277): could be check-pass?) +#![allow(dead_code)] +mod foo { + pub use self::bar::T; + mod bar { + pub trait T { + fn f(&self) {} + } + impl T for () {} + } +} + +fn g() { + use foo::T; + ().f(); // Check that this does not trigger a privacy error +} + +fn f() { + let error = ::std::thread::spawn(|| {}).join().unwrap_err(); + error.type_id(); // Regression test for #21670 +} + + +fn main() {} diff --git a/tests/ui/traits/project-modulo-regions.rs b/tests/ui/traits/project-modulo-regions.rs new file mode 100644 index 000000000..f0c0dd3ed --- /dev/null +++ b/tests/ui/traits/project-modulo-regions.rs @@ -0,0 +1,55 @@ +// revisions: with_clause without_clause +// Tests that `EvaluatedToOkModuloRegions` from a projection sub-obligation +// is correctly propagated + +#![feature(rustc_attrs)] + +trait MyTrait { + type Assoc; +} + +struct MyStruct; + +impl MyTrait for MyStruct { + // Evaluating this projection will result in `EvaluatedToOkModuloRegions` + // (when `with_clause` is enabled) + type Assoc = ::Assoc; +} + +struct Bar; + +// The `where` clause on this impl will cause us to produce `EvaluatedToOkModuloRegions` +// when evaluating a projection involving this impl +#[cfg(with_clause)] +impl MyTrait for Bar where for<'b> &'b (): 'b { + type Assoc = bool; +} + +// This impl tests that the `EvaluatedToOkModuoRegions` result that we get +// is really due to the `where` clause on the `with_clause` impl +#[cfg(without_clause)] +impl MyTrait for Bar { + type Assoc = bool; +} + +// The implementation of `#[rustc_evaluate_where_clauses]` doesn't perform +// normalization, so we need to place the projection predicate behind a normal +// trait predicate +struct Helper {} +trait HelperTrait {} +impl HelperTrait for Helper where ::Assoc: Sized {} + +// Evaluating this 'where' clause will (recursively) end up evaluating +// `for<'b> &'b (): 'b`, which will produce `EvaluatedToOkModuloRegions` +#[rustc_evaluate_where_clauses] +fn test(val: MyStruct) where Helper: HelperTrait { + panic!() +} + +fn foo(val: MyStruct) { + test(val); + //[with_clause]~^ ERROR evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + //[without_clause]~^^ ERROR evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOk) +} + +fn main() {} diff --git a/tests/ui/traits/project-modulo-regions.with_clause.stderr b/tests/ui/traits/project-modulo-regions.with_clause.stderr new file mode 100644 index 000000000..2434c32c8 --- /dev/null +++ b/tests/ui/traits/project-modulo-regions.with_clause.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/project-modulo-regions.rs:50:5 + | +LL | fn test(val: MyStruct) where Helper: HelperTrait { + | ----------- predicate +... +LL | test(val); + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/project-modulo-regions.without_clause.stderr b/tests/ui/traits/project-modulo-regions.without_clause.stderr new file mode 100644 index 000000000..9d35690d5 --- /dev/null +++ b/tests/ui/traits/project-modulo-regions.without_clause.stderr @@ -0,0 +1,11 @@ +error: evaluate(Binder(TraitPredicate(, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/project-modulo-regions.rs:50:5 + | +LL | fn test(val: MyStruct) where Helper: HelperTrait { + | ----------- predicate +... +LL | test(val); + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/region-pointer-simple.rs b/tests/ui/traits/region-pointer-simple.rs new file mode 100644 index 000000000..0456ca931 --- /dev/null +++ b/tests/ui/traits/region-pointer-simple.rs @@ -0,0 +1,21 @@ +// run-pass +trait Foo { + fn f(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { + println!("Today's number is {}", self.x); + return self.x; + } +} + +pub fn main() { + let a = A { x: 3 }; + let b = (&a) as &dyn Foo; + assert_eq!(b.f(), 3); +} diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.rs b/tests/ui/traits/reservation-impl/coherence-conflict.rs new file mode 100644 index 000000000..fa4a30931 --- /dev/null +++ b/tests/ui/traits/reservation-impl/coherence-conflict.rs @@ -0,0 +1,14 @@ +// check that reservation impls are accounted for in negative reasoning. + +#![feature(rustc_attrs)] + +trait MyTrait {} +#[rustc_reservation_impl="this impl is reserved"] +impl MyTrait for () {} + +trait OtherTrait {} +impl OtherTrait for () {} +impl OtherTrait for T {} +//~^ ERROR conflicting implementations + +fn main() {} diff --git a/tests/ui/traits/reservation-impl/coherence-conflict.stderr b/tests/ui/traits/reservation-impl/coherence-conflict.stderr new file mode 100644 index 000000000..a811d7e32 --- /dev/null +++ b/tests/ui/traits/reservation-impl/coherence-conflict.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `OtherTrait` for type `()` + --> $DIR/coherence-conflict.rs:11:1 + | +LL | impl OtherTrait for () {} + | ---------------------- first implementation here +LL | impl OtherTrait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: this impl is reserved + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/reservation-impl/no-use.rs b/tests/ui/traits/reservation-impl/no-use.rs new file mode 100644 index 000000000..65a55d9e2 --- /dev/null +++ b/tests/ui/traits/reservation-impl/no-use.rs @@ -0,0 +1,12 @@ +// check that reservation impls can't be used as normal impls in positive reasoning. + +#![feature(rustc_attrs)] + +trait MyTrait { fn foo(&self); } +#[rustc_reservation_impl = "foo"] +impl MyTrait for () { fn foo(&self) {} } + +fn main() { + <() as MyTrait>::foo(&()); + //~^ ERROR the trait bound `(): MyTrait` is not satisfied +} diff --git a/tests/ui/traits/reservation-impl/no-use.stderr b/tests/ui/traits/reservation-impl/no-use.stderr new file mode 100644 index 000000000..cefb2a879 --- /dev/null +++ b/tests/ui/traits/reservation-impl/no-use.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `(): MyTrait` is not satisfied + --> $DIR/no-use.rs:10:26 + | +LL | <() as MyTrait>::foo(&()); + | -------------------- ^^^ the trait `MyTrait` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `MyTrait` is implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/reservation-impl/non-lattice-ok.rs b/tests/ui/traits/reservation-impl/non-lattice-ok.rs new file mode 100644 index 000000000..a71051243 --- /dev/null +++ b/tests/ui/traits/reservation-impl/non-lattice-ok.rs @@ -0,0 +1,59 @@ +// build-pass + +// Check that a reservation impl does not force other impls to follow +// a lattice discipline. + +// Why did we ever want to do this? +// +// We want to eventually add an `impl From for T` impl. That impl conflicts +// with existing impls - at least the `impl From for T` impl. There are +// 2 ways we thought of for dealing with that conflict: +// +// 1. Using specialization and doing some handling for the +// overlap. The current thought is to require ["intersection +// impls"][ii], specialization", which means providing an +// (higher-priority) impl for the intersection of every 2 conflicting +// impls that determines what happens in the intersection case. That's +// the first thing we thought about - see e.g. +// https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775 +// +// 2. The other way is to notice that `impl From for T` is basically a +// marker trait since its only method is uninhabited, and allow for "marker +// trait overlap", where the conflict "doesn't matter" because it can't +// actually cause any ambiguity. +// +// Now it turned out lattice specialization doesn't work it, because an +// `impl From for Smaht` would require an `impl From for Smaht`, +// breaking backwards-compatibility in a fairly painful way. So if we want to +// go with a known approach, we should go with a "marker trait overlap"-style +// approach. +// +// [ii]: https://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/ + +#![feature(rustc_attrs, never_type)] + +trait MyTrait {} + +impl MyTrait for ! {} + +trait MyFrom { + fn my_from(x: T) -> Self; +} + +// Given the "normal" impls for From +#[rustc_reservation_impl="this impl is reserved"] +impl MyFrom for T { + fn my_from(x: !) -> Self { match x {} } +} + +impl MyFrom for T { + fn my_from(x: T) -> Self { x } +} + +// ... we *do* want to allow this common pattern, of `From for MySmaht` +struct MySmaht(T); +impl MyFrom for MySmaht { + fn my_from(x: T) -> Self { MySmaht(x) } +} + +fn main() {} diff --git a/tests/ui/traits/reservation-impl/ok.rs b/tests/ui/traits/reservation-impl/ok.rs new file mode 100644 index 000000000..611c8d884 --- /dev/null +++ b/tests/ui/traits/reservation-impl/ok.rs @@ -0,0 +1,28 @@ +// run-pass + +// rpass test for reservation impls. Not 100% required because `From` uses them, +// but still. + +#![feature(rustc_attrs)] + +use std::mem; + +trait MyTrait { + fn foo(&self, s: S) -> usize; +} + +#[rustc_reservation_impl = "foo"] +impl MyTrait for T { + fn foo(&self, _x: u64) -> usize { 0 } +} + +// reservation impls don't create coherence conflicts, even with +// non-chain overlap. +impl MyTrait for u32 { + fn foo(&self, _x: S) -> usize { mem::size_of::() } +} + +fn main() { + // ...and the non-reservation impl gets picked.XS + assert_eq!(0u32.foo(0u64), mem::size_of::()); +} diff --git a/tests/ui/traits/resolution-in-overloaded-op.rs b/tests/ui/traits/resolution-in-overloaded-op.rs new file mode 100644 index 000000000..a9bacc357 --- /dev/null +++ b/tests/ui/traits/resolution-in-overloaded-op.rs @@ -0,0 +1,11 @@ +// #12402 Operator overloading only considers the method name, not which trait is implemented + +trait MyMul { + fn mul(&self, rhs: &Rhs) -> Res; +} + +fn foo>(a: &T, b: f64) -> f64 { + a * b //~ ERROR cannot multiply `&T` by `f64` +} + +fn main() {} diff --git a/tests/ui/traits/resolution-in-overloaded-op.stderr b/tests/ui/traits/resolution-in-overloaded-op.stderr new file mode 100644 index 000000000..fe5e1d6d2 --- /dev/null +++ b/tests/ui/traits/resolution-in-overloaded-op.stderr @@ -0,0 +1,16 @@ +error[E0369]: cannot multiply `&T` by `f64` + --> $DIR/resolution-in-overloaded-op.rs:8:7 + | +LL | a * b + | - ^ - f64 + | | + | &T + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn foo>(a: &T, b: f64) -> f64 where &T: Mul { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/traits/safety-fn-body.mir.stderr b/tests/ui/traits/safety-fn-body.mir.stderr new file mode 100644 index 000000000..ea7b2048e --- /dev/null +++ b/tests/ui/traits/safety-fn-body.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/safety-fn-body.rs:14:9 + | +LL | *self += 1; + | ^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/safety-fn-body.rs b/tests/ui/traits/safety-fn-body.rs new file mode 100644 index 000000000..2cc4fe1b3 --- /dev/null +++ b/tests/ui/traits/safety-fn-body.rs @@ -0,0 +1,19 @@ +// Check that an unsafe impl does not imply that unsafe actions are +// legal in the methods. + +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +unsafe trait UnsafeTrait : Sized { + fn foo(self) { } +} + +unsafe impl UnsafeTrait for *mut isize { + fn foo(self) { + // Unsafe actions are not made legal by taking place in an unsafe trait: + *self += 1; + //~^ ERROR E0133 + } +} + +fn main() { } diff --git a/tests/ui/traits/safety-fn-body.thir.stderr b/tests/ui/traits/safety-fn-body.thir.stderr new file mode 100644 index 000000000..23696c32b --- /dev/null +++ b/tests/ui/traits/safety-fn-body.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/safety-fn-body.rs:14:9 + | +LL | *self += 1; + | ^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/traits/safety-inherent-impl.rs b/tests/ui/traits/safety-inherent-impl.rs new file mode 100644 index 000000000..50e15f0d2 --- /dev/null +++ b/tests/ui/traits/safety-inherent-impl.rs @@ -0,0 +1,9 @@ +// Check that inherent impls cannot be unsafe. + +struct SomeStruct; + +unsafe impl SomeStruct { //~ ERROR inherent impls cannot be unsafe + fn foo(self) { } +} + +fn main() { } diff --git a/tests/ui/traits/safety-inherent-impl.stderr b/tests/ui/traits/safety-inherent-impl.stderr new file mode 100644 index 000000000..1c8f43fec --- /dev/null +++ b/tests/ui/traits/safety-inherent-impl.stderr @@ -0,0 +1,11 @@ +error[E0197]: inherent impls cannot be unsafe + --> $DIR/safety-inherent-impl.rs:5:13 + | +LL | unsafe impl SomeStruct { + | ------ ^^^^^^^^^^ inherent impl for this type + | | + | unsafe because of this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0197`. diff --git a/tests/ui/traits/safety-ok-cc.rs b/tests/ui/traits/safety-ok-cc.rs new file mode 100644 index 000000000..099ba80e5 --- /dev/null +++ b/tests/ui/traits/safety-ok-cc.rs @@ -0,0 +1,24 @@ +// run-pass +// aux-build:trait_safety_lib.rs + +// Simple smoke test that unsafe traits can be compiled across crates. + + +extern crate trait_safety_lib as lib; + +use lib::Foo; + +struct Bar { x: isize } +unsafe impl Foo for Bar { + fn foo(&self) -> isize { self.x } +} + +fn take_foo(f: &F) -> isize { f.foo() } + +fn main() { + let x: isize = 22; + assert_eq!(22, take_foo(&x)); + + let x: Bar = Bar { x: 23 }; + assert_eq!(23, take_foo(&x)); +} diff --git a/tests/ui/traits/safety-ok.rs b/tests/ui/traits/safety-ok.rs new file mode 100644 index 000000000..d456a78b6 --- /dev/null +++ b/tests/ui/traits/safety-ok.rs @@ -0,0 +1,18 @@ +// run-pass +// Simple smoke test that unsafe traits can be compiled etc. + + +unsafe trait Foo { + fn foo(&self) -> isize; +} + +unsafe impl Foo for isize { + fn foo(&self) -> isize { *self } +} + +fn take_foo(f: &F) -> isize { f.foo() } + +fn main() { + let x: isize = 22; + assert_eq!(22, take_foo(&x)); +} diff --git a/tests/ui/traits/safety-trait-impl-cc.rs b/tests/ui/traits/safety-trait-impl-cc.rs new file mode 100644 index 000000000..6f125e5f9 --- /dev/null +++ b/tests/ui/traits/safety-trait-impl-cc.rs @@ -0,0 +1,15 @@ +// aux-build:trait_safety_lib.rs + +// Check that unsafe traits require unsafe impls and that inherent +// impls cannot be unsafe. + +extern crate trait_safety_lib as lib; + +struct Bar; +impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration + fn foo(&self) -> isize { + panic!(); + } +} + +fn main() { } diff --git a/tests/ui/traits/safety-trait-impl-cc.stderr b/tests/ui/traits/safety-trait-impl-cc.stderr new file mode 100644 index 000000000..0ca565787 --- /dev/null +++ b/tests/ui/traits/safety-trait-impl-cc.stderr @@ -0,0 +1,15 @@ +error[E0200]: the trait `Foo` requires an `unsafe impl` declaration + --> $DIR/safety-trait-impl-cc.rs:9:1 + | +LL | impl lib::Foo for Bar { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl lib::Foo for Bar { + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0200`. diff --git a/tests/ui/traits/safety-trait-impl.rs b/tests/ui/traits/safety-trait-impl.rs new file mode 100644 index 000000000..45258b78d --- /dev/null +++ b/tests/ui/traits/safety-trait-impl.rs @@ -0,0 +1,18 @@ +// Check that unsafe traits require unsafe impls and that inherent +// impls cannot be unsafe. + +trait SafeTrait { + fn foo(&self) { } +} + +unsafe trait UnsafeTrait { + fn foo(&self) { } +} + +unsafe impl UnsafeTrait for u8 { } // OK + +impl UnsafeTrait for u16 { } //~ ERROR requires an `unsafe impl` declaration + +unsafe impl SafeTrait for u32 { } //~ ERROR the trait `SafeTrait` is not unsafe + +fn main() { } diff --git a/tests/ui/traits/safety-trait-impl.stderr b/tests/ui/traits/safety-trait-impl.stderr new file mode 100644 index 000000000..e78e0e3a6 --- /dev/null +++ b/tests/ui/traits/safety-trait-impl.stderr @@ -0,0 +1,28 @@ +error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration + --> $DIR/safety-trait-impl.rs:14:1 + | +LL | impl UnsafeTrait for u16 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword +help: add `unsafe` to this trait implementation + | +LL | unsafe impl UnsafeTrait for u16 { } + | ++++++ + +error[E0199]: implementing the trait `SafeTrait` is not unsafe + --> $DIR/safety-trait-impl.rs:16:1 + | +LL | unsafe impl SafeTrait for u32 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `unsafe` from this trait implementation + | +LL - unsafe impl SafeTrait for u32 { } +LL + impl SafeTrait for u32 { } + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0199, E0200. +For more information about an error, try `rustc --explain E0199`. diff --git a/tests/ui/traits/self-without-lifetime-constraint.rs b/tests/ui/traits/self-without-lifetime-constraint.rs new file mode 100644 index 000000000..99013d32a --- /dev/null +++ b/tests/ui/traits/self-without-lifetime-constraint.rs @@ -0,0 +1,53 @@ +use std::error::Error; +use std::fmt; + +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ValueRef<'a> { + Null, + Integer(i64), + Real(f64), + Text(&'a [u8]), + Blob(&'a [u8]), +} + +impl<'a> ValueRef<'a> { + pub fn as_str(&self) -> FromSqlResult<&'a str, &'a &'a str> { + match *self { + ValueRef::Text(t) => { + std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + } + _ => Err(FromSqlError::InvalidType), + } + } +} + +#[derive(Debug)] +#[non_exhaustive] +pub enum FromSqlError { + InvalidType +} + +impl fmt::Display for FromSqlError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "InvalidType") + } +} + +impl Error for FromSqlError {} + +pub type FromSqlResult = Result<(T, K), FromSqlError>; + +pub trait FromSql: Sized { + fn column_result(value: ValueRef<'_>) -> FromSqlResult; +} + +impl FromSql for &str { + fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { + //~^ ERROR `impl` item signature doesn't match `trait` item signature + value.as_str() + } +} + +pub fn main() { + println!("{}", "Hello World"); +} diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr new file mode 100644 index 000000000..05a49820a --- /dev/null +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -0,0 +1,19 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/self-without-lifetime-constraint.rs:45:5 + | +LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; + | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` +... +LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` + | + = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` + found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/self-without-lifetime-constraint.rs:41:60 + | +LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; + | ^^^^ consider borrowing this type parameter in the trait + +error: aborting due to previous error + diff --git a/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs new file mode 100644 index 000000000..5449f5f00 --- /dev/null +++ b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs @@ -0,0 +1,69 @@ +// check-pass + +// This test checks that we're correctly dealing with inductive cycles +// with canonical inference variables. + +trait Trait {} + +trait IsNotU32 {} +impl IsNotU32 for i32 {} +impl Trait for () // impl 1 +where + (): Trait +{} + +impl Trait for () {} // impl 2 + +// If we now check whether `(): Trait` holds this has to +// result in ambiguity as both `for (): Trait` and `(): Trait` +// applies. The remainder of this test asserts that. + +// If we were to error on inductive cycles with canonical inference variables +// this would be wrong: + +// (): Trait +// - impl 1 +// - ?0: IsNotU32 // ambig +// - (): Trait // canonical cycle -> err +// - ERR +// - impl 2 +// - OK ?0 == u32 +// +// Result: OK ?0 == u32. + +// (): Trait +// - impl 1 +// - i32: IsNotU32 // ok +// - (): Trait +// - impl 1 +// - u32: IsNotU32 // err +// - ERR +// - impl 2 +// - OK +// - OK +// - impl 2 (trivial ERR) +// +// Result OK + +// This would mean that `(): Trait` is not complete, +// which is unsound if we're in coherence. + +fn implements_trait() -> (T, U) +where + (): Trait, +{ + todo!() +} + +// A hack to only constrain the infer vars after first checking +// the `(): Trait<_, _>`. +trait Constrain {} +impl Constrain for T {} +fn constrain, U>(_: U) {} + +fn main() { + let (x, y) = implements_trait::<_, _>(); + + constrain::(x); + constrain::(y); +} diff --git a/tests/ui/traits/static-method-generic-inference.rs b/tests/ui/traits/static-method-generic-inference.rs new file mode 100644 index 000000000..f4e94c4f7 --- /dev/null +++ b/tests/ui/traits/static-method-generic-inference.rs @@ -0,0 +1,28 @@ +// Issue #3902. We are (at least currently) unable to infer `Self` +// based on `T`, even though there is only a single impl, because of +// the possibility of associated types and other things (basically: no +// constraints on `Self` here at all). + +mod base { + pub trait HasNew { + fn new() -> T; + fn dummy(&self) { } + } + + pub struct Foo { + dummy: (), + } + + impl HasNew for Foo { + fn new() -> Foo { + Foo { dummy: () } + } + } +} + +pub fn foo() { + let _f: base::Foo = base::HasNew::new(); + //~^ ERROR E0790 +} + +fn main() { } diff --git a/tests/ui/traits/static-method-generic-inference.stderr b/tests/ui/traits/static-method-generic-inference.stderr new file mode 100644 index 000000000..575ace237 --- /dev/null +++ b/tests/ui/traits/static-method-generic-inference.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/static-method-generic-inference.rs:24:25 + | +LL | fn new() -> T; + | -------------- `HasNew::new` defined here +... +LL | let _f: base::Foo = base::HasNew::new(); + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let _f: base::Foo = ::new(); + | +++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/traits/static-method-overwriting.rs b/tests/ui/traits/static-method-overwriting.rs new file mode 100644 index 000000000..f669ffae6 --- /dev/null +++ b/tests/ui/traits/static-method-overwriting.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(dead_code)] +mod base { + pub trait HasNew { + fn new() -> Self; + } + + pub struct Foo { + dummy: (), + } + + impl ::base::HasNew for Foo { + fn new() -> Foo { + println!("Foo"); + Foo { dummy: () } + } + } + + pub struct Bar { + dummy: (), + } + + impl ::base::HasNew for Bar { + fn new() -> Bar { + println!("Bar"); + Bar { dummy: () } + } + } +} + +pub fn main() { + let _f: base::Foo = base::HasNew::new(); + let _b: base::Bar = base::HasNew::new(); +} diff --git a/tests/ui/traits/static-outlives-a-where-clause.rs b/tests/ui/traits/static-outlives-a-where-clause.rs new file mode 100644 index 000000000..f0c2c1082 --- /dev/null +++ b/tests/ui/traits/static-outlives-a-where-clause.rs @@ -0,0 +1,23 @@ +// run-pass + +trait Foo<'a> { + fn xyz(self); +} +impl<'a, T> Foo<'a> for T where 'static: 'a { + fn xyz(self) {} +} + +trait Bar { + fn uvw(self); +} +impl Bar for T where for<'a> T: Foo<'a> { + fn uvw(self) { self.xyz(); } +} + +fn foo(t: T) where T: Bar { + t.uvw(); +} + +fn main() { + foo(0); +} diff --git a/tests/ui/traits/staticness-mismatch.rs b/tests/ui/traits/staticness-mismatch.rs new file mode 100644 index 000000000..8710d0112 --- /dev/null +++ b/tests/ui/traits/staticness-mismatch.rs @@ -0,0 +1,11 @@ +trait Foo { + fn dummy(&self) { } + fn bar(); +} + +impl Foo for isize { + fn bar(&self) {} + //~^ ERROR method `bar` has a `&self` declaration in the impl, but not in the trait +} + +fn main() {} diff --git a/tests/ui/traits/staticness-mismatch.stderr b/tests/ui/traits/staticness-mismatch.stderr new file mode 100644 index 000000000..b67ac5adb --- /dev/null +++ b/tests/ui/traits/staticness-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0185]: method `bar` has a `&self` declaration in the impl, but not in the trait + --> $DIR/staticness-mismatch.rs:7:5 + | +LL | fn bar(); + | --------- trait method declared without `&self` +... +LL | fn bar(&self) {} + | ^^^^^^^^^^^^^ `&self` used in impl + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0185`. diff --git a/tests/ui/traits/suggest-deferences/issue-39029.fixed b/tests/ui/traits/suggest-deferences/issue-39029.fixed new file mode 100644 index 000000000..a1abf668b --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-39029.fixed @@ -0,0 +1,18 @@ +// run-rustfix +use std::net::TcpListener; + +struct NoToSocketAddrs(String); + +impl std::ops::Deref for NoToSocketAddrs { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let _works = TcpListener::bind("some string"); + let bad = NoToSocketAddrs("bad".to_owned()); + let _errors = TcpListener::bind(&*bad); + //~^ ERROR the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-39029.rs b/tests/ui/traits/suggest-deferences/issue-39029.rs new file mode 100644 index 000000000..90d097105 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-39029.rs @@ -0,0 +1,18 @@ +// run-rustfix +use std::net::TcpListener; + +struct NoToSocketAddrs(String); + +impl std::ops::Deref for NoToSocketAddrs { + type Target = String; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn main() { + let _works = TcpListener::bind("some string"); + let bad = NoToSocketAddrs("bad".to_owned()); + let _errors = TcpListener::bind(&bad); + //~^ ERROR the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-39029.stderr b/tests/ui/traits/suggest-deferences/issue-39029.stderr new file mode 100644 index 000000000..49e20c6a7 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-39029.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied + --> $DIR/issue-39029.rs:16:37 + | +LL | let _errors = TcpListener::bind(&bad); + | ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | | + | required by a bound introduced by this call + | + = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs` +note: required by a bound in `TcpListener::bind` + --> $SRC_DIR/std/src/net/tcp.rs:LL:COL +help: consider dereferencing here + | +LL | let _errors = TcpListener::bind(&*bad); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/issue-62530.fixed b/tests/ui/traits/suggest-deferences/issue-62530.fixed new file mode 100644 index 000000000..406caaa00 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-62530.fixed @@ -0,0 +1,15 @@ +// run-rustfix +fn takes_str(_x: &str) {} + +fn takes_type_parameter(_x: T) where T: SomeTrait {} + +trait SomeTrait {} +impl SomeTrait for &'_ str {} +impl SomeTrait for char {} + +fn main() { + let string = String::new(); + takes_str(&string); // Ok + takes_type_parameter(&*string); // Error + //~^ ERROR the trait bound `&String: SomeTrait` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-62530.rs b/tests/ui/traits/suggest-deferences/issue-62530.rs new file mode 100644 index 000000000..53846be73 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-62530.rs @@ -0,0 +1,15 @@ +// run-rustfix +fn takes_str(_x: &str) {} + +fn takes_type_parameter(_x: T) where T: SomeTrait {} + +trait SomeTrait {} +impl SomeTrait for &'_ str {} +impl SomeTrait for char {} + +fn main() { + let string = String::new(); + takes_str(&string); // Ok + takes_type_parameter(&string); // Error + //~^ ERROR the trait bound `&String: SomeTrait` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/issue-62530.stderr b/tests/ui/traits/suggest-deferences/issue-62530.stderr new file mode 100644 index 000000000..e47ae0b65 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/issue-62530.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&String: SomeTrait` is not satisfied + --> $DIR/issue-62530.rs:13:26 + | +LL | takes_type_parameter(&string); // Error + | -------------------- ^^^^^^^ the trait `SomeTrait` is not implemented for `&String` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes_type_parameter` + --> $DIR/issue-62530.rs:4:44 + | +LL | fn takes_type_parameter(_x: T) where T: SomeTrait {} + | ^^^^^^^^^ required by this bound in `takes_type_parameter` +help: consider dereferencing here + | +LL | takes_type_parameter(&*string); // Error + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/multiple-0.fixed b/tests/ui/traits/suggest-deferences/multiple-0.fixed new file mode 100644 index 000000000..b7160b75c --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-0.fixed @@ -0,0 +1,36 @@ +// run-rustfix +use std::ops::Deref; + +trait Happy {} +struct LDM; +impl Happy for &LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo(_: T) where T: Happy {} + +fn main() { + let baz = Baz(Bar(Foo(LDM))); + foo(&***baz); + //~^ ERROR the trait bound `&Baz: Happy` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/multiple-0.rs b/tests/ui/traits/suggest-deferences/multiple-0.rs new file mode 100644 index 000000000..9ac55177f --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-0.rs @@ -0,0 +1,36 @@ +// run-rustfix +use std::ops::Deref; + +trait Happy {} +struct LDM; +impl Happy for &LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn foo(_: T) where T: Happy {} + +fn main() { + let baz = Baz(Bar(Foo(LDM))); + foo(&baz); + //~^ ERROR the trait bound `&Baz: Happy` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/multiple-0.stderr b/tests/ui/traits/suggest-deferences/multiple-0.stderr new file mode 100644 index 000000000..6a4d4b8d5 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-0.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&Baz: Happy` is not satisfied + --> $DIR/multiple-0.rs:34:9 + | +LL | foo(&baz); + | --- ^^^^ the trait `Happy` is not implemented for `&Baz` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/multiple-0.rs:30:26 + | +LL | fn foo(_: T) where T: Happy {} + | ^^^^^ required by this bound in `foo` +help: consider dereferencing here + | +LL | foo(&***baz); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/multiple-1.rs b/tests/ui/traits/suggest-deferences/multiple-1.rs new file mode 100644 index 000000000..91c6c7924 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-1.rs @@ -0,0 +1,54 @@ +use std::ops::{Deref, DerefMut}; + +trait Happy {} +struct LDM; +impl Happy for &mut LDM {} + +struct Foo(LDM); +struct Bar(Foo); +struct Baz(Bar); +impl Deref for Foo { + type Target = LDM; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Bar { + type Target = Foo; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl Deref for Baz { + type Target = Bar; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Foo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Bar { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl DerefMut for Baz { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + + +fn foo(_: T) where T: Happy {} + +fn main() { + // Currently the compiler doesn't try to suggest dereferences for situations + // where DerefMut involves. So this test is meant to ensure compiler doesn't + // generate incorrect help message. + let mut baz = Baz(Bar(Foo(LDM))); + foo(&mut baz); + //~^ ERROR the trait bound `&mut Baz: Happy` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/multiple-1.stderr b/tests/ui/traits/suggest-deferences/multiple-1.stderr new file mode 100644 index 000000000..6e12321c2 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/multiple-1.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied + --> $DIR/multiple-1.rs:52:9 + | +LL | foo(&mut baz); + | --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz` + | | + | required by a bound introduced by this call + | + = help: the trait `Happy` is implemented for `&mut LDM` +note: required by a bound in `foo` + --> $DIR/multiple-1.rs:45:26 + | +LL | fn foo(_: T) where T: Happy {} + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/root-obligation.fixed b/tests/ui/traits/suggest-deferences/root-obligation.fixed new file mode 100644 index 000000000..7a8433f90 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/root-obligation.fixed @@ -0,0 +1,13 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(*c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +} diff --git a/tests/ui/traits/suggest-deferences/root-obligation.rs b/tests/ui/traits/suggest-deferences/root-obligation.rs new file mode 100644 index 000000000..51bac2107 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/root-obligation.rs @@ -0,0 +1,13 @@ +// run-rustfix + +fn get_vowel_count(string: &str) -> usize { + string + .chars() + .filter(|c| "aeiou".contains(c)) + //~^ ERROR expected a `Fn<(char,)>` closure, found `char` + .count() +} + +fn main() { + let _ = get_vowel_count("asdf"); +} diff --git a/tests/ui/traits/suggest-deferences/root-obligation.stderr b/tests/ui/traits/suggest-deferences/root-obligation.stderr new file mode 100644 index 000000000..1363fb8c4 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/root-obligation.stderr @@ -0,0 +1,21 @@ +error[E0277]: expected a `Fn<(char,)>` closure, found `char` + --> $DIR/root-obligation.rs:6:38 + | +LL | .filter(|c| "aeiou".contains(c)) + | -------- ^ expected an `Fn<(char,)>` closure, found `char` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(char,)>` is not implemented for `char` + = note: required for `&char` to implement `FnOnce<(char,)>` + = note: required for `&char` to implement `Pattern<'_>` +note: required by a bound in `core::str::::contains` + --> $SRC_DIR/core/src/str/mod.rs:LL:COL +help: consider dereferencing here + | +LL | .filter(|c| "aeiou".contains(*c)) + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed new file mode 100644 index 000000000..ea3d1bf85 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.fixed @@ -0,0 +1,14 @@ +// run-rustfix + +struct TargetStruct; + +impl From for TargetStruct { + fn from(_unchecked: usize) -> Self { + TargetStruct + } +} + +fn main() { + let a = &3; + let _b: TargetStruct = (*a).into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs new file mode 100644 index 000000000..9eda68027 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.rs @@ -0,0 +1,14 @@ +// run-rustfix + +struct TargetStruct; + +impl From for TargetStruct { + fn from(_unchecked: usize) -> Self { + TargetStruct + } +} + +fn main() { + let a = &3; + let _b: TargetStruct = a.into(); //~ ERROR the trait bound `TargetStruct: From<&{integer}>` is not satisfied +} diff --git a/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr new file mode 100644 index 000000000..ede31a2c7 --- /dev/null +++ b/tests/ui/traits/suggest-deferences/suggest-dereferencing-receiver-argument.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied + --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30 + | +LL | let _b: TargetStruct = a.into(); + | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct` + | + = note: required for `&{integer}` to implement `Into` +help: consider dereferencing here + | +LL | let _b: TargetStruct = (*a).into(); + | ++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-fully-qualified-closure.rs b/tests/ui/traits/suggest-fully-qualified-closure.rs new file mode 100644 index 000000000..c077921c0 --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-closure.rs @@ -0,0 +1,24 @@ +// check-fail +// known-bug: #103705 +// normalize-stderr-test "\[closure@.*\]" -> "[closure@]" +// normalize-stderr-test "\+* ~" -> "+++ ~" + +// The output of this currently suggests writing a closure in the qualified path. + +trait MyTrait { + fn lol(&self, f:F) -> u16; +} + +struct Qqq; + +impl MyTrait for Qqq{ + fn lol(&self, _f:F) -> u16 { 5 } +} +impl MyTrait for Qqq{ + fn lol(&self, _f:F) -> u16 { 6 } +} + +fn main() { + let q = Qqq; + q.lol(||()); +} diff --git a/tests/ui/traits/suggest-fully-qualified-closure.stderr b/tests/ui/traits/suggest-fully-qualified-closure.stderr new file mode 100644 index 000000000..3df623c14 --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-closure.stderr @@ -0,0 +1,34 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-closure.rs:23:7 + | +LL | q.lol(||()); + | ^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >::lol::<[closure@]>(&q, ||()); + | +++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-closure.rs:23:7 + | +LL | q.lol(||()); + | ^^^ + | +note: multiple `impl`s satisfying `Qqq: MyTrait<_>` found + --> $DIR/suggest-fully-qualified-closure.rs:14:1 + | +LL | impl MyTrait for Qqq{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MyTrait for Qqq{ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::lol::<[closure@]>(&q, ||()); + | +++ ~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs new file mode 100644 index 000000000..9a2cf469d --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.rs @@ -0,0 +1,60 @@ +use std::ops::{Deref, DerefMut}; + +struct Thing; + +trait Method { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method for Thing { + fn method(&self) -> u32 { 0 } + fn mut_method(&mut self) -> u32 { 0 } +} +trait MethodRef { + fn by_self(self); +} +impl MethodRef for &Thing { + fn by_self(self) {} +} +impl MethodRef for &Thing { + fn by_self(self) {} +} + + +struct DerefsTo(T); +impl Deref for DerefsTo { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for DerefsTo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + let mut thing = Thing; + thing.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + thing.mut_method(); //~ ERROR type annotations needed + thing.by_self(); //~ ERROR type annotations needed + + let mut deref_to = DerefsTo(Thing); + deref_to.method(); //~ ERROR type annotations needed + deref_to.mut_method(); //~ ERROR type annotations needed + deref_to.by_self(); //~ ERROR type annotations needed + + let mut deref_deref_to = DerefsTo(DerefsTo(Thing)); + deref_deref_to.method(); //~ ERROR type annotations needed + deref_deref_to.mut_method(); //~ ERROR type annotations needed + deref_deref_to.by_self(); //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr new file mode 100644 index 000000000..68b31a1ca --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr @@ -0,0 +1,186 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 + | +LL | thing.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&thing); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 + | +LL | thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&thing); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:48:11 + | +LL | thing.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(&mut thing); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:49:11 + | +LL | thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(&thing); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14 + | +LL | deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&deref_to); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:53:14 + | +LL | deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(&mut deref_to); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:54:14 + | +LL | deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(&deref_to); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20 + | +LL | deref_deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&deref_deref_to); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:58:20 + | +LL | deref_deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(&mut deref_deref_to); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:59:20 + | +LL | deref_deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(&deref_deref_to); + | +++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs new file mode 100644 index 000000000..da640c8c8 --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.rs @@ -0,0 +1,64 @@ +use std::ops::{Deref, DerefMut}; + +struct Thing; + +trait Method { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method for Thing { + fn method(&self) -> u32 { 0 } + fn mut_method(&mut self) -> u32 { 0 } +} + +trait MethodRef { + fn by_self(self); +} +impl MethodRef for &Thing { + fn by_self(self) {} +} +impl MethodRef for &Thing { + fn by_self(self) {} +} + +struct DerefsTo(T); +impl Deref for DerefsTo { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for DerefsTo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + let mut ref_thing = &Thing; + ref_thing.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + ref_thing.by_self(); //~ ERROR type annotations needed + + let mut mut_thing = &mut Thing; + mut_thing.method(); //~ ERROR type annotations needed + mut_thing.mut_method(); //~ ERROR type annotations needed + mut_thing.by_self(); //~ ERROR type annotations needed + + let mut deref_to = &DerefsTo(Thing); + deref_to.method(); //~ ERROR type annotations needed + deref_to.mut_method(); //~ ERROR type annotations needed + deref_to.by_self(); //~ ERROR type annotations needed + + let mut deref_deref_to = &DerefsTo(DerefsTo(Thing)); + deref_deref_to.method(); //~ ERROR type annotations needed + deref_deref_to.mut_method(); //~ ERROR type annotations needed + deref_deref_to.by_self(); //~ ERROR type annotations needed +} diff --git a/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr new file mode 100644 index 000000000..27518a54e --- /dev/null +++ b/tests/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr @@ -0,0 +1,224 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 + | +LL | ref_thing.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >::method(ref_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 + | +LL | ref_thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(ref_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:48:15 + | +LL | ref_thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(ref_thing); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15 + | +LL | mut_thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(mut_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:52:15 + | +LL | mut_thing.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(mut_thing); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:53:15 + | +LL | mut_thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(mut_thing); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14 + | +LL | deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(deref_to); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:57:14 + | +LL | deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(deref_to); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:58:14 + | +LL | deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(deref_to); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20 + | +LL | deref_deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(deref_deref_to); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:62:20 + | +LL | deref_deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(deref_deref_to); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:63:20 + | +LL | deref_deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(deref_deref_to); + | ++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/suggest-where-clause.rs b/tests/ui/traits/suggest-where-clause.rs new file mode 100644 index 000000000..46d047a2d --- /dev/null +++ b/tests/ui/traits/suggest-where-clause.rs @@ -0,0 +1,36 @@ +use std::mem; + +struct Misc(T); + +fn check() { + // suggest a where-clause, if needed + mem::size_of::(); + //~^ ERROR the size for values of type + + mem::size_of::>(); + //~^ ERROR the size for values of type + + // ... even if T occurs as a type parameter + + >::from; + //~^ ERROR `u64: From` is not satisfied + + ::Item>>::from; + //~^ ERROR `u64: From<::Item>` is not satisfied + + // ... but not if there are inference variables + + as From>::from; + //~^ ERROR `Misc<_>: From` is not satisfied + + // ... and also not if the error is not related to the type + + mem::size_of::<[T]>(); + //~^ ERROR the size for values of type + + mem::size_of::<[&U]>(); + //~^ ERROR the size for values of type +} + +fn main() { +} diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr new file mode 100644 index 000000000..44e63b78c --- /dev/null +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -0,0 +1,90 @@ +error[E0277]: the size for values of type `U` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:7:20 + | +LL | fn check() { + | - this type parameter needs to be `std::marker::Sized` +LL | // suggest a where-clause, if needed +LL | mem::size_of::(); + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn check() { +LL + fn check() { + | + +error[E0277]: the size for values of type `U` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:10:20 + | +LL | fn check() { + | - this type parameter needs to be `std::marker::Sized` +... +LL | mem::size_of::>(); + | ^^^^^^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `Misc` + --> $DIR/suggest-where-clause.rs:3:8 + | +LL | struct Misc(T); + | ^^^^ +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn check() { +LL + fn check() { + | + +error[E0277]: the trait bound `u64: From` is not satisfied + --> $DIR/suggest-where-clause.rs:15:5 + | +LL | >::from; + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `u64` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn check() where u64: From { + | ++++++++++++++++++ + +error[E0277]: the trait bound `u64: From<::Item>` is not satisfied + --> $DIR/suggest-where-clause.rs:18:5 + | +LL | ::Item>>::from; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<::Item>` is not implemented for `u64` + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn check() where u64: From<::Item> { + | ++++++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `Misc<_>: From` is not satisfied + --> $DIR/suggest-where-clause.rs:23:5 + | +LL | as From>::from; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From` is not implemented for `Misc<_>` + +error[E0277]: the size for values of type `[T]` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:28:20 + | +LL | mem::size_of::<[T]>(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[T]` +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error[E0277]: the size for values of type `[&U]` cannot be known at compilation time + --> $DIR/suggest-where-clause.rs:31:20 + | +LL | mem::size_of::<[&U]>(); + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[&U]` +note: required by a bound in `std::mem::size_of` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/superdefault-generics.rs b/tests/ui/traits/superdefault-generics.rs new file mode 100644 index 000000000..e862c0e97 --- /dev/null +++ b/tests/ui/traits/superdefault-generics.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_snake_case)] + +// There is some other borrowck bug, so we make the stuff not mut. + + +use std::ops::Add; + +trait Positioned { + fn SetX(&mut self, _: S); + fn X(&self) -> S; +} + +trait Movable>: Positioned { + fn translate(&mut self, dx: S) { + let x = self.X() + dx; + self.SetX(x); + } +} + +struct Point { x: S, y: S } + +impl Positioned for Point { + fn SetX(&mut self, x: S) { + self.x = x; + } + fn X(&self) -> S { + self.x.clone() + } +} + +impl> Movable for Point {} + +pub fn main() { + let mut p = Point{ x: 1, y: 2}; + p.translate(3); + assert_eq!(p.X(), 4); +} diff --git a/tests/ui/traits/syntax-polarity.rs b/tests/ui/traits/syntax-polarity.rs new file mode 100644 index 000000000..c809f9e89 --- /dev/null +++ b/tests/ui/traits/syntax-polarity.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +#![feature(negative_impls)] + +struct TestType; + +impl TestType {} + +trait TestTrait {} + +impl !Send for TestType {} + +struct TestType2(T); + +impl TestType2 {} + +impl !Send for TestType2 {} + +fn main() {} diff --git a/tests/ui/traits/syntax-trait-polarity.rs b/tests/ui/traits/syntax-trait-polarity.rs new file mode 100644 index 000000000..ed2947493 --- /dev/null +++ b/tests/ui/traits/syntax-trait-polarity.rs @@ -0,0 +1,25 @@ +#![feature(negative_impls)] + +use std::marker::Send; + +struct TestType; + +impl !TestType {} +//~^ ERROR inherent impls cannot be negative + +trait TestTrait {} + +unsafe impl !Send for TestType {} +//~^ ERROR negative impls cannot be unsafe +impl !TestTrait for TestType {} + +struct TestType2(T); + +impl !TestType2 {} +//~^ ERROR inherent impls cannot be negative + +unsafe impl !Send for TestType2 {} +//~^ ERROR negative impls cannot be unsafe +impl !TestTrait for TestType2 {} + +fn main() {} diff --git a/tests/ui/traits/syntax-trait-polarity.stderr b/tests/ui/traits/syntax-trait-polarity.stderr new file mode 100644 index 000000000..1fd40fb66 --- /dev/null +++ b/tests/ui/traits/syntax-trait-polarity.stderr @@ -0,0 +1,37 @@ +error: inherent impls cannot be negative + --> $DIR/syntax-trait-polarity.rs:7:7 + | +LL | impl !TestType {} + | -^^^^^^^^ inherent impl for this type + | | + | negative because of this + +error[E0198]: negative impls cannot be unsafe + --> $DIR/syntax-trait-polarity.rs:12:13 + | +LL | unsafe impl !Send for TestType {} + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this + +error: inherent impls cannot be negative + --> $DIR/syntax-trait-polarity.rs:18:10 + | +LL | impl !TestType2 {} + | -^^^^^^^^^^^^ inherent impl for this type + | | + | negative because of this + +error[E0198]: negative impls cannot be unsafe + --> $DIR/syntax-trait-polarity.rs:21:16 + | +LL | unsafe impl !Send for TestType2 {} + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0198`. diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs new file mode 100644 index 000000000..342928e88 --- /dev/null +++ b/tests/ui/traits/test-2.rs @@ -0,0 +1,17 @@ +#[allow(non_camel_case_types)] + + +trait bar { fn dup(&self) -> Self; fn blah(&self); } +impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah(&self) {} } +impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah(&self) {} } + +fn main() { + 10.dup::(); + //~^ ERROR this associated function takes 0 generic arguments but 1 + 10.blah::(); + //~^ ERROR this associated function takes 1 generic argument but 2 + (Box::new(10) as Box).dup(); + //~^ ERROR E0038 + //~| ERROR E0038 + //~| ERROR E0038 +} diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr new file mode 100644 index 000000000..eaa20b0b4 --- /dev/null +++ b/tests/ui/traits/test-2.stderr @@ -0,0 +1,85 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/test-2.rs:9:8 + | +LL | 10.dup::(); + | ^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/test-2.rs:4:16 + | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | ^^^ + +error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/test-2.rs:11:8 + | +LL | 10.blah::(); + | ^^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + | +note: associated function defined here, with 1 generic parameter: `X` + --> $DIR/test-2.rs:4:39 + | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | ^^^^ - + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:22 + | +LL | (Box::new(10) as Box).dup(); + | ^^^^^^^^^^^^ `bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:5 + | +LL | (Box::new(10) as Box).dup(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + +error[E0038]: the trait `bar` cannot be made into an object + --> $DIR/test-2.rs:13:6 + | +LL | (Box::new(10) as Box).dup(); + | ^^^^^^^^^^^^ `bar` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/test-2.rs:4:30 + | +LL | trait bar { fn dup(&self) -> Self; fn blah(&self); } + | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters + | | | + | | ...because method `dup` references the `Self` type in its return type + | this trait cannot be made into an object... + = help: consider moving `dup` to another trait + = help: consider moving `blah` to another trait + = note: required for `Box<{integer}>` to implement `CoerceUnsized>` + = note: required by cast to type `Box` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/test.rs b/tests/ui/traits/test.rs new file mode 100644 index 000000000..72fc66f74 --- /dev/null +++ b/tests/ui/traits/test.rs @@ -0,0 +1,6 @@ +#[allow(non_camel_case_types)] +trait foo { fn foo(&self); } + +impl isize for usize { fn foo(&self) {} } //~ ERROR trait + +fn main() {} diff --git a/tests/ui/traits/test.stderr b/tests/ui/traits/test.stderr new file mode 100644 index 000000000..668228abe --- /dev/null +++ b/tests/ui/traits/test.stderr @@ -0,0 +1,9 @@ +error[E0404]: expected trait, found builtin type `isize` + --> $DIR/test.rs:4:6 + | +LL | impl isize for usize { fn foo(&self) {} } + | ^^^^^ not a trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/traits/to-str.rs b/tests/ui/traits/to-str.rs new file mode 100644 index 000000000..9670edbfa --- /dev/null +++ b/tests/ui/traits/to-str.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(non_camel_case_types)] + + +trait to_str { + fn to_string_(&self) -> String; +} + +impl to_str for isize { + fn to_string_(&self) -> String { self.to_string() } +} + +impl to_str for Vec { + fn to_string_(&self) -> String { + format!("[{}]", + self.iter() + .map(|e| e.to_string_()) + .collect::>() + .join(", ")) + } +} + +pub fn main() { + assert_eq!(1.to_string_(), "1".to_string()); + assert_eq!((vec![2, 3, 4]).to_string_(), "[2, 3, 4]".to_string()); + + fn indirect(x: T) -> String { + format!("{}!", x.to_string_()) + } + assert_eq!(indirect(vec![10, 20]), "[10, 20]!".to_string()); + + fn indirect2(x: T) -> String { + indirect(x) + } + assert_eq!(indirect2(vec![1]), "[1]!".to_string()); +} diff --git a/tests/ui/traits/track-obligations.rs b/tests/ui/traits/track-obligations.rs new file mode 100644 index 000000000..77e753c13 --- /dev/null +++ b/tests/ui/traits/track-obligations.rs @@ -0,0 +1,88 @@ +// These are simplifications of the tower traits by the same name: + +pub trait Service { + type Response; +} + +pub trait Layer { + type Service; +} + +// Any type will do here: + +pub struct Req; +pub struct Res; + +// This is encoding a trait alias. + +pub trait ParticularService: + Service { +} + +impl ParticularService for T +where + T: Service, +{ +} + +// This is also a trait alias. +// The weird = bound is there so that users of the trait do not +// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671 +// for context, and in particular the workaround in: +// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828 + +pub trait ParticularServiceLayer: + Layer>::Service> +{ + type Service: ParticularService; +} + +impl ParticularServiceLayer for T +where + T: Layer, + T::Service: ParticularService, +{ + type Service = T::Service; +} + +// These are types that implement the traits that the trait aliases refer to. +// They should also implement the alias traits due to the blanket impls. + +struct ALayer(C); +impl Layer for ALayer { + type Service = AService; +} + +struct AService; +impl Service for AService { + // However, AService does _not_ meet the blanket implementation, + // since its Response type is bool, not Res as it should be. + type Response = bool; +} + +// This is a wrapper type around ALayer that uses the trait alias +// as a way to communicate the requirements of the provided types. +struct Client(C); + +// The method and the free-standing function below both have the same bounds. + +impl Client +where + ALayer: ParticularServiceLayer, +{ + fn check(&self) {} +} + +fn check(_: C) where ALayer: ParticularServiceLayer {} + +// But, they give very different error messages. + +fn main() { + // This gives a very poor error message that does nothing to point the user + // at the underlying cause of why the types involved do not meet the bounds. + Client(()).check(); //~ ERROR E0599 + + // This gives a good(ish) error message that points the user at _why_ the + // bound isn't met, and thus how they might fix it. + check(()); //~ ERROR E0271 +} diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr new file mode 100644 index 000000000..894774759 --- /dev/null +++ b/tests/ui/traits/track-obligations.stderr @@ -0,0 +1,76 @@ +error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied + --> $DIR/track-obligations.rs:83:16 + | +LL | struct ALayer(C); + | ---------------- + | | + | doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` + | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` +... +LL | struct Client(C); + | ---------------- method `check` not found for this struct +... +LL | Client(()).check(); + | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds + | +note: trait bound ` as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` was not satisfied + --> $DIR/track-obligations.rs:35:14 + | +LL | pub trait ParticularServiceLayer: + | ---------------------- +LL | Layer>::Service> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied + --> $DIR/track-obligations.rs:71:16 + | +LL | impl Client + | --------- +LL | where +LL | ALayer: ParticularServiceLayer, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: the trait `ParticularServiceLayer` must be implemented + --> $DIR/track-obligations.rs:34:1 + | +LL | / pub trait ParticularServiceLayer: +LL | | Layer>::Service> + | |____________________________________________________________________^ + +error[E0271]: type mismatch resolving `>::Response == Res` + --> $DIR/track-obligations.rs:87:11 + | +LL | check(()); + | ----- ^^ type mismatch resolving `>::Response == Res` + | | + | required by a bound introduced by this call + | +note: expected this to be `Res` + --> $DIR/track-obligations.rs:60:21 + | +LL | type Response = bool; + | ^^^^ +note: required for `AService` to implement `ParticularService` + --> $DIR/track-obligations.rs:22:9 + | +LL | impl ParticularService for T + | ^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | T: Service, + | -------------- unsatisfied trait bound introduced here +note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>` + --> $DIR/track-obligations.rs:40:12 + | +LL | impl ParticularServiceLayer for T + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +... +LL | T::Service: ParticularService, + | ----------------- unsatisfied trait bound introduced here +note: required by a bound in `check` + --> $DIR/track-obligations.rs:76:36 + | +LL | fn check(_: C) where ALayer: ParticularServiceLayer {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0599. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/trait-or-new-type-instead.rs b/tests/ui/traits/trait-or-new-type-instead.rs new file mode 100644 index 000000000..572b03efc --- /dev/null +++ b/tests/ui/traits/trait-or-new-type-instead.rs @@ -0,0 +1,6 @@ +impl Option { +//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined + pub fn foo(&self) { } +} + +fn main() { } diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr new file mode 100644 index 000000000..4726b0668 --- /dev/null +++ b/tests/ui/traits/trait-or-new-type-instead.stderr @@ -0,0 +1,14 @@ +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/trait-or-new-type-instead.rs:1:1 + | +LL | / impl Option { +LL | | +LL | | pub fn foo(&self) { } +LL | | } + | |_^ impl for type defined outside of crate. + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0116`. diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs new file mode 100644 index 000000000..570ec5160 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/basic.rs @@ -0,0 +1,86 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let bar: &dyn Bar = baz; + let _: &dyn std::fmt::Debug = bar; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let foo: &dyn Foo = baz; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let foo: &dyn Foo = bar; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs new file mode 100644 index 000000000..eae5cf8d5 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs @@ -0,0 +1,38 @@ +// run-pass +#![feature(trait_upcasting)] + +trait Foo: Bar + Bar {} +trait Bar { + fn bar(&self) -> String { + T::default().to_string() + } +} + +struct S1; + +impl Bar for S1 {} +impl Foo for S1 {} + +struct S2; +impl Bar for S2 {} +impl Bar for S2 {} +impl Foo for S2 {} + +fn test1(x: &dyn Foo) { + let s = x as &dyn Bar; + assert_eq!("0", &s.bar().to_string()); +} + +fn test2(x: &dyn Foo) { + let p = x as &dyn Bar; + assert_eq!("0", &p.bar().to_string()); + let q = x as &dyn Bar; + assert_eq!("false", &q.bar().to_string()); +} + +fn main() { + let s1 = S1; + test1(&s1); + let s2 = S2; + test2(&s2); +} diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs new file mode 100644 index 000000000..511e41562 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs @@ -0,0 +1,13 @@ +trait A: B + A {} +//~^ ERROR cycle detected when computing the super predicates of `A` [E0391] + +trait B {} + +impl A for () {} + +impl B for () {} + +fn main() { + let a: Box = Box::new(()); + let _b: Box = a; +} diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr new file mode 100644 index 000000000..15faab16a --- /dev/null +++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when computing the super predicates of `A` + --> $DIR/cyclic-trait-resolution.rs:1:1 + | +LL | trait A: B + A {} + | ^^^^^^^^^^^^^^ + | +note: ...which requires computing the super traits of `A`... + --> $DIR/cyclic-trait-resolution.rs:1:14 + | +LL | trait A: B + A {} + | ^ + = note: ...which again requires computing the super predicates of `A`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cyclic-trait-resolution.rs:1:1 + | +LL | trait A: B + A {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs new file mode 100644 index 000000000..a4f81c464 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/diamond.rs @@ -0,0 +1,114 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar1: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Bar2: Foo { + fn c(&self) -> i32 { + 30 + } + + fn v(&self) -> i32 { + 31 + } +} + +trait Baz: Bar1 + Bar2 { + fn d(&self) -> i32 { + 40 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar1 for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Bar2 for i32 { + fn c(&self) -> i32 { + 300 + } +} + +impl Baz for i32 { + fn d(&self) -> i32 { + 400 + } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.d(), 400); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + assert_eq!(baz.v(), 31); + + let bar1: &dyn Bar1 = baz; + let _: &dyn std::fmt::Debug = bar1; + assert_eq!(*bar1, 1); + assert_eq!(bar1.a(), 100); + assert_eq!(bar1.b(), 200); + assert_eq!(bar1.z(), 11); + assert_eq!(bar1.y(), 12); + assert_eq!(bar1.w(), 21); + + let bar2: &dyn Bar2 = baz; + let _: &dyn std::fmt::Debug = bar2; + assert_eq!(*bar2, 1); + assert_eq!(bar2.a(), 100); + assert_eq!(bar2.c(), 300); + assert_eq!(bar2.z(), 11); + assert_eq!(bar2.y(), 12); + assert_eq!(bar2.v(), 31); + + let foo: &dyn Foo = baz; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + + let foo: &dyn Foo = bar1; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + + let foo: &dyn Foo = bar2; + let _: &dyn std::fmt::Debug = foo; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); +} diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs new file mode 100644 index 000000000..e634bbd5a --- /dev/null +++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs @@ -0,0 +1,86 @@ +#![feature(trait_upcasting)] + +trait Foo { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn main() { + let baz: &dyn Baz = &1; + let _: &dyn std::fmt::Debug = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = baz; + //~^ ERROR mismatched types [E0308] + + let bar: &dyn Bar = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn std::fmt::Debug = bar; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = bar; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = bar; + //~^ ERROR mismatched types [E0308] + + let foo: &dyn Foo = baz; + //~^ ERROR mismatched types [E0308] + let _: &dyn std::fmt::Debug = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = foo; + //~^ ERROR mismatched types [E0308] + + let foo: &dyn Foo = bar; + //~^ ERROR mismatched types [E0308] + let _: &dyn std::fmt::Debug = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Send = foo; + //~^ ERROR mismatched types [E0308] + let _: &dyn Sync = foo; + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr new file mode 100644 index 000000000..3aa21ee3d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr @@ -0,0 +1,168 @@ +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:53:35 + | +LL | let _: &dyn std::fmt::Debug = baz; + | -------------------- ^^^ expected trait `Debug`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:55:24 + | +LL | let _: &dyn Send = baz; + | --------- ^^^ expected trait `Send`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:57:24 + | +LL | let _: &dyn Sync = baz; + | --------- ^^^ expected trait `Sync`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:60:25 + | +LL | let bar: &dyn Bar = baz; + | -------- ^^^ expected trait `Bar`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Bar` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:62:35 + | +LL | let _: &dyn std::fmt::Debug = bar; + | -------------------- ^^^ expected trait `Debug`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:64:24 + | +LL | let _: &dyn Send = bar; + | --------- ^^^ expected trait `Send`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:66:24 + | +LL | let _: &dyn Sync = bar; + | --------- ^^^ expected trait `Sync`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:69:25 + | +LL | let foo: &dyn Foo = baz; + | -------- ^^^ expected trait `Foo`, found trait `Baz` + | | + | expected due to this + | + = note: expected reference `&dyn Foo` + found reference `&dyn Baz` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:71:35 + | +LL | let _: &dyn std::fmt::Debug = foo; + | -------------------- ^^^ expected trait `Debug`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:73:24 + | +LL | let _: &dyn Send = foo; + | --------- ^^^ expected trait `Send`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:75:24 + | +LL | let _: &dyn Sync = foo; + | --------- ^^^ expected trait `Sync`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:78:25 + | +LL | let foo: &dyn Foo = bar; + | -------- ^^^ expected trait `Foo`, found trait `Bar` + | | + | expected due to this + | + = note: expected reference `&dyn Foo` + found reference `&dyn Bar` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:80:35 + | +LL | let _: &dyn std::fmt::Debug = foo; + | -------------------- ^^^ expected trait `Debug`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Debug` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:82:24 + | +LL | let _: &dyn Send = foo; + | --------- ^^^ expected trait `Send`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Send` + found reference `&dyn Foo` + +error[E0308]: mismatched types + --> $DIR/invalid-upcast.rs:84:24 + | +LL | let _: &dyn Sync = foo; + | --------- ^^^ expected trait `Sync`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Sync` + found reference `&dyn Foo` + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs new file mode 100644 index 000000000..b672963ae --- /dev/null +++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs @@ -0,0 +1,12 @@ +// run-pass +#![feature(trait_upcasting)] + +struct Test { + func: Box, +} + +fn main() { + let closure: Box = Box::new(|| ()); + let mut test = Box::new(Test { func: closure }); + (test.func)(); +} diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs new file mode 100644 index 000000000..9825158c2 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/lifetime.rs @@ -0,0 +1,94 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +// Note: upcast lifetime means a shorter lifetime. +fn upcast_baz<'a: 'b, 'b, T>(v: Box, _l: &'b T) -> Box { + v +} +fn upcast_bar<'a: 'b, 'b, T>(v: Box, _l: &'b T) -> Box { + v +} +fn upcast_foo<'a: 'b, 'b, T>(v: Box, _l: &'b T) -> Box { + v +} + +fn main() { + let v = Box::new(1); + let l = &(); // dummy lifetime (shorter than `baz`) + + let baz: Box = v.clone(); + let u = upcast_baz(baz, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + assert_eq!(u.c(), 300); + + let baz: Box = v.clone(); + let bar: Box = baz; + let u = upcast_bar(bar, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + assert_eq!(u.b(), 200); + + let baz: Box = v.clone(); + let foo: Box = baz; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); + + let baz: Box = v.clone(); + let bar: Box = baz; + let foo: Box = bar; + let u = upcast_foo(foo, &l); + assert_eq!(*u, 1); + assert_eq!(u.a(), 100); +} diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs new file mode 100644 index 000000000..d62418756 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -0,0 +1,27 @@ +#![deny(deref_into_dyn_supertrait)] + +extern crate core; + +use core::ops::Deref; + +// issue 89190 +trait A {} +trait B: A {} + +impl<'a> Deref for dyn 'a + B { + //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + //~| WARN this was previously accepted by the compiler but is being phased out; + + type Target = dyn A; + fn deref(&self) -> &Self::Target { + todo!() + } +} + +fn take_a(_: &dyn A) {} + +fn whoops(b: &dyn B) { + take_a(b) +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr new file mode 100644 index 000000000..4533b1163 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -0,0 +1,19 @@ +error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + --> $DIR/migrate-lint-deny.rs:11:1 + | +LL | impl<'a> Deref for dyn 'a + B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | type Target = dyn A; + | -------------------- target type is set here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #89460 +note: the lint level is defined here + --> $DIR/migrate-lint-deny.rs:1:9 + | +LL | #![deny(deref_into_dyn_supertrait)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs new file mode 100644 index 000000000..2e53a00a9 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs @@ -0,0 +1,21 @@ +// check-fail +#![feature(trait_upcasting)] + +trait Bar { + fn bar(&self, _: T) {} +} + +trait Foo: Bar + Bar { + fn foo(&self, _: ()) {} +} + +struct S; + +impl Bar for S {} +impl Bar for S {} +impl Foo for S {} + +fn main() { + let s: &dyn Foo = &S; + let t: &dyn Bar<_> = s; //~ ERROR mismatched types +} diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr new file mode 100644 index 000000000..0ad18be03 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/multiple-occurrence-ambiguousity.rs:20:26 + | +LL | let t: &dyn Bar<_> = s; + | ----------- ^ expected trait `Bar`, found trait `Foo` + | | + | expected due to this + | + = note: expected reference `&dyn Bar<_>` + found reference `&dyn Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs new file mode 100644 index 000000000..9ccfc9306 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs @@ -0,0 +1,48 @@ +// run-pass + +#![feature(trait_upcasting)] + +trait A { + fn foo_a(&self); +} + +trait B { + fn foo_b(&self); +} + +trait C: A + B { + fn foo_c(&self); +} + +struct S(i32); + +impl A for S { + fn foo_a(&self) { + unreachable!(); + } +} + +impl B for S { + fn foo_b(&self) { + assert_eq!(42, self.0); + } +} + +impl C for S { + fn foo_c(&self) { + unreachable!(); + } +} + +fn invoke_inner(b: &dyn B) { + b.foo_b(); +} + +fn invoke_outer(c: &dyn C) { + invoke_inner(c); +} + +fn main() { + let s = S(42); + invoke_outer(&s); +} diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs new file mode 100644 index 000000000..a3e416969 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/struct.rs @@ -0,0 +1,173 @@ +// run-pass + +#![feature(trait_upcasting)] + +use std::rc::Rc; +use std::sync::Arc; + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn test_box() { + let v = Box::new(1); + + let baz: Box = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Box = v.clone(); + let bar: Box = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Box = v.clone(); + let foo: Box = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Box = v.clone(); + let bar: Box = baz; + let foo: Box = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn test_rc() { + let v = Rc::new(1); + + let baz: Rc = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Rc = v.clone(); + let bar: Rc = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Rc = v.clone(); + let foo: Rc = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Rc = v.clone(); + let bar: Rc = baz; + let foo: Rc = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn test_arc() { + let v = Arc::new(1); + + let baz: Arc = v.clone(); + assert_eq!(*baz, 1); + assert_eq!(baz.a(), 100); + assert_eq!(baz.b(), 200); + assert_eq!(baz.c(), 300); + assert_eq!(baz.z(), 11); + assert_eq!(baz.y(), 12); + assert_eq!(baz.w(), 21); + + let baz: Arc = v.clone(); + let bar: Arc = baz; + assert_eq!(*bar, 1); + assert_eq!(bar.a(), 100); + assert_eq!(bar.b(), 200); + assert_eq!(bar.z(), 11); + assert_eq!(bar.y(), 12); + assert_eq!(bar.w(), 21); + + let baz: Arc = v.clone(); + let foo: Arc = baz; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); + + let baz: Arc = v.clone(); + let bar: Arc = baz; + let foo: Arc = bar; + assert_eq!(*foo, 1); + assert_eq!(foo.a(), 100); + assert_eq!(foo.z(), 11); + assert_eq!(foo.y(), 12); +} + +fn main() { + test_box(); + test_rc(); + test_arc(); +} diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs new file mode 100644 index 000000000..136d15af0 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs @@ -0,0 +1,69 @@ +#![feature(trait_upcasting)] + +trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + fn a(&self) -> i32 { + 10 + } + + fn z(&self) -> i32 { + 11 + } + + fn y(&self) -> i32 { + 12 + } +} + +trait Bar: Foo { + fn b(&self) -> i32 { + 20 + } + + fn w(&self) -> i32 { + 21 + } +} + +trait Baz: Bar { + fn c(&self) -> i32 { + 30 + } +} + +impl Foo for i32 { + fn a(&self) -> i32 { + 100 + } +} + +impl Bar for i32 { + fn b(&self) -> i32 { + 200 + } +} + +impl Baz for i32 { + fn c(&self) -> i32 { + 300 + } +} + +fn main() { + let baz: &dyn Baz = &1; + + let bar: &dyn Bar = baz; + bar.c(); + //~^ ERROR no method named `c` found for reference `&dyn Bar` in the current scope [E0599] + + let foo: &dyn Foo = baz; + foo.b(); + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + foo.c(); + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] + + let foo: &dyn Foo = bar; + foo.b(); + //~^ ERROR no method named `b` found for reference `&dyn Foo` in the current scope [E0599] + foo.c(); + //~^ ERROR no method named `c` found for reference `&dyn Foo` in the current scope [E0599] +} diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr new file mode 100644 index 000000000..918159e84 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr @@ -0,0 +1,68 @@ +error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope + --> $DIR/subtrait-method.rs:55:9 + | +LL | bar.c(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:27:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:59:9 + | +LL | foo.b(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `b`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Bar: Foo { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:61:9 + | +LL | foo.c(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:27:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:65:9 + | +LL | foo.b(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `b`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:17:1 + | +LL | trait Bar: Foo { + | ^^^^^^^^^^^^^^ + +error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope + --> $DIR/subtrait-method.rs:67:9 + | +LL | foo.c(); + | ^ help: there is a method with a similar name: `a` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Baz` defines an item `c`, perhaps you need to implement it + --> $DIR/subtrait-method.rs:27:1 + | +LL | trait Baz: Bar { + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs new file mode 100644 index 000000000..6bc9f4a75 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -0,0 +1,26 @@ +#![feature(trait_upcasting)] + +trait Foo: Bar + Bar {} +trait Bar { + fn bar(&self) -> Option { + None + } +} + +fn test_specific(x: &dyn Foo) { + let _ = x as &dyn Bar; // OK + let _ = x as &dyn Bar; // OK +} + +fn test_unknown_version(x: &dyn Foo) { + let _ = x as &dyn Bar<_>; // Ambiguous + //~^ ERROR non-primitive cast + //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied +} + +fn test_infer_version(x: &dyn Foo) { + let a = x as &dyn Bar<_>; // OK + let _: Option = a.bar(); +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr new file mode 100644 index 000000000..fe269d8e9 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr @@ -0,0 +1,23 @@ +error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` + --> $DIR/type-checking-test-1.rs:16:13 + | +LL | let _ = x as &dyn Bar<_>; // Ambiguous + | ^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let _ = &x as &dyn Bar<_>; // Ambiguous + | + + +error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied + --> $DIR/type-checking-test-1.rs:16:13 + | +LL | let _ = x as &dyn Bar<_>; // Ambiguous + | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` + | + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0605. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs new file mode 100644 index 000000000..36b11dffd --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs @@ -0,0 +1,31 @@ +#![feature(trait_upcasting)] + +trait Foo: Bar + Bar {} +trait Bar { + fn bar(&self) -> Option { + None + } +} + +fn test_specific(x: &dyn Foo) { + let _ = x as &dyn Bar; // OK +} + +fn test_specific2(x: &dyn Foo) { + let _ = x as &dyn Bar; // OK +} + +fn test_specific3(x: &dyn Foo) { + let _ = x as &dyn Bar; // Error + //~^ ERROR non-primitive cast + //~^^ ERROR the trait bound `&dyn Foo: Bar` is not satisfied +} + +fn test_infer_arg(x: &dyn Foo) { + let a = x as &dyn Bar<_>; // Ambiguous + //~^ ERROR non-primitive cast + //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied + let _ = a.bar(); +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr new file mode 100644 index 000000000..ef007d5cb --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -0,0 +1,42 @@ +error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar` + --> $DIR/type-checking-test-2.rs:19:13 + | +LL | let _ = x as &dyn Bar; // Error + | ^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let _ = &x as &dyn Bar; // Error + | + + +error[E0277]: the trait bound `&dyn Foo: Bar` is not satisfied + --> $DIR/type-checking-test-2.rs:19:13 + | +LL | let _ = x as &dyn Bar; // Error + | ^ the trait `Bar` is not implemented for `&dyn Foo` + | + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar` + +error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` + --> $DIR/type-checking-test-2.rs:25:13 + | +LL | let a = x as &dyn Bar<_>; // Ambiguous + | ^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL | let a = &x as &dyn Bar<_>; // Ambiguous + | + + +error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied + --> $DIR/type-checking-test-2.rs:25:13 + | +LL | let a = x as &dyn Bar<_>; // Ambiguous + | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` + | + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0605. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr new file mode 100644 index 000000000..e6cb6a753 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:11:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a>; // Error + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:16:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs new file mode 100644 index 000000000..b2db3a127 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs @@ -0,0 +1,20 @@ +#![feature(trait_upcasting)] + +trait Foo<'a>: Bar<'a> {} +trait Bar<'a> {} + +fn test_correct(x: &dyn Foo<'static>) { + let _ = x as &dyn Bar<'static>; +} + +fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + let _ = x as &dyn Bar<'a>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong2<'a>(x: &dyn Foo<'a>) { + let _ = x as &dyn Bar<'static>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr new file mode 100644 index 000000000..e6cb6a753 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:11:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a>; // Error + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-3.rs:16:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr new file mode 100644 index 000000000..8d506e580 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr @@ -0,0 +1,52 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:15:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static, 'a>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:20:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a, 'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:26:5 + | +LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | let y = x as &dyn Bar<'_, '_>; +LL | y.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:31:5 + | +LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:36:5 + | +LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:44:5 + | +LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +... +LL | z.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs new file mode 100644 index 000000000..f40c48f0d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs @@ -0,0 +1,48 @@ +#![feature(trait_upcasting)] + +trait Foo<'a>: Bar<'a, 'a> {} +trait Bar<'a, 'b> { + fn get_b(&self) -> Option<&'a u32> { + None + } +} + +fn test_correct(x: &dyn Foo<'static>) { + let _ = x as &dyn Bar<'static, 'static>; +} + +fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + let _ = x as &dyn Bar<'static, 'a>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { + let _ = x as &dyn Bar<'a, 'static>; // Error + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + let y = x as &dyn Bar<'_, '_>; + y.get_b() // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + <_ as Bar>::get_b(x) // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + <_ as Bar<'_, '_>>::get_b(x) // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + let y = x as &dyn Bar<'_, '_>; + y.get_b(); // ERROR + let z = y; + z.get_b() // ERROR + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr new file mode 100644 index 000000000..8d506e580 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -0,0 +1,52 @@ +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:15:13 + | +LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'static, 'a>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:20:13 + | +LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { + | -- lifetime `'a` defined here +LL | let _ = x as &dyn Bar<'a, 'static>; // Error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:26:5 + | +LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | let y = x as &dyn Bar<'_, '_>; +LL | y.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:31:5 + | +LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:36:5 + | +LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/type-checking-test-4.rs:44:5 + | +LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { + | -- lifetime `'a` defined here +... +LL | z.get_b() // ERROR + | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/traits/typeclasses-eq-example-static.rs b/tests/ui/traits/typeclasses-eq-example-static.rs new file mode 100644 index 000000000..f982ad6a0 --- /dev/null +++ b/tests/ui/traits/typeclasses-eq-example-static.rs @@ -0,0 +1,68 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +// Example from lkuper's intern talk, August 2012 -- now with static +// methods! +use Color::{cyan, magenta, yellow, black}; +use ColorTree::{leaf, branch}; + +trait Equal { + fn isEq(a: &Self, b: &Self) -> bool; +} + +#[derive(Clone, Copy)] +enum Color { cyan, magenta, yellow, black } + +impl Equal for Color { + fn isEq(a: &Color, b: &Color) -> bool { + match (*a, *b) { + (cyan, cyan) => { true } + (magenta, magenta) => { true } + (yellow, yellow) => { true } + (black, black) => { true } + _ => { false } + } + } +} + +#[derive(Clone)] +enum ColorTree { + leaf(Color), + branch(Box, Box) +} + +impl Equal for ColorTree { + fn isEq(a: &ColorTree, b: &ColorTree) -> bool { + match (a, b) { + (&leaf(ref x), &leaf(ref y)) => { + Equal::isEq(&(*x).clone(), &(*y).clone()) + } + (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { + Equal::isEq(&(**l1).clone(), &(**l2).clone()) && + Equal::isEq(&(**r1).clone(), &(**r2).clone()) + } + _ => { false } + } + } +} + +pub fn main() { + assert!(Equal::isEq(&cyan, &cyan)); + assert!(Equal::isEq(&magenta, &magenta)); + assert!(!Equal::isEq(&cyan, &yellow)); + assert!(!Equal::isEq(&magenta, &cyan)); + + assert!(Equal::isEq(&leaf(cyan), &leaf(cyan))); + assert!(!Equal::isEq(&leaf(cyan), &leaf(yellow))); + + assert!(Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))), + &branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); + + assert!(!Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))), + &branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); + + println!("Assertions all succeeded!"); +} diff --git a/tests/ui/traits/typeclasses-eq-example.rs b/tests/ui/traits/typeclasses-eq-example.rs new file mode 100644 index 000000000..4400301e6 --- /dev/null +++ b/tests/ui/traits/typeclasses-eq-example.rs @@ -0,0 +1,64 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] + +// Example from lkuper's intern talk, August 2012. +use Color::{cyan, magenta, yellow, black}; +use ColorTree::{leaf, branch}; + +trait Equal { + fn isEq(&self, a: &Self) -> bool; +} + +#[derive(Clone, Copy)] +enum Color { cyan, magenta, yellow, black } + +impl Equal for Color { + fn isEq(&self, a: &Color) -> bool { + match (*self, *a) { + (cyan, cyan) => { true } + (magenta, magenta) => { true } + (yellow, yellow) => { true } + (black, black) => { true } + _ => { false } + } + } +} + +#[derive(Clone)] +enum ColorTree { + leaf(Color), + branch(Box, Box) +} + +impl Equal for ColorTree { + fn isEq(&self, a: &ColorTree) -> bool { + match (self, a) { + (&leaf(ref x), &leaf(ref y)) => { x.isEq(&(*y).clone()) } + (&branch(ref l1, ref r1), &branch(ref l2, ref r2)) => { + (*l1).isEq(&(**l2).clone()) && (*r1).isEq(&(**r2).clone()) + } + _ => { false } + } + } +} + +pub fn main() { + assert!(cyan.isEq(&cyan)); + assert!(magenta.isEq(&magenta)); + assert!(!cyan.isEq(&yellow)); + assert!(!magenta.isEq(&cyan)); + + assert!(leaf(cyan).isEq(&leaf(cyan))); + assert!(!leaf(cyan).isEq(&leaf(yellow))); + + assert!(branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) + .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))))); + + assert!(!branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))) + .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(magenta))))); + + println!("Assertions all succeeded!"); +} diff --git a/tests/ui/traits/ufcs-object.rs b/tests/ui/traits/ufcs-object.rs new file mode 100644 index 000000000..700488c22 --- /dev/null +++ b/tests/ui/traits/ufcs-object.rs @@ -0,0 +1,17 @@ +// run-pass +// Test that when you use ufcs form to invoke a trait method (on a +// trait object) everything works fine. + + +trait Foo { + fn test(&self) -> i32; +} + +impl Foo for i32 { + fn test(&self) -> i32 { *self } +} + +fn main() { + let a: &dyn Foo = &22; + assert_eq!(Foo::test(a), 22); +} diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.rs b/tests/ui/traits/unspecified-self-in-trait-ref.rs new file mode 100644 index 000000000..158b5a985 --- /dev/null +++ b/tests/ui/traits/unspecified-self-in-trait-ref.rs @@ -0,0 +1,30 @@ +pub trait Foo { + fn foo(&self); +} + +pub trait Bar { + fn foo(&self); +} + +fn main() { + let a = Foo::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let b = Foo::<_>::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let c = Bar::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let d = Bar::::lol(); + //~^ ERROR no function or associated item named + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition + let e = Bar::::lol(); + //~^ ERROR must be explicitly specified + //~| WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition +} diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr new file mode 100644 index 000000000..b5e8e8867 --- /dev/null +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -0,0 +1,105 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:10:13 + | +LL | let a = Foo::lol(); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: use `dyn` + | +LL | let a = ::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:10:18 + | +LL | let a = Foo::lol(); + | ^^^ function or associated item not found in `dyn Foo<_>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:14:13 + | +LL | let b = Foo::<_>::lol(); + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let b = >::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Foo<_>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:14:23 + | +LL | let b = Foo::<_>::lol(); + | ^^^ function or associated item not found in `dyn Foo<_>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:18:13 + | +LL | let c = Bar::lol(); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let c = ::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar<_, _>` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:18:18 + | +LL | let c = Bar::lol(); + | ^^^ function or associated item not found in `dyn Bar<_, _>` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:22:13 + | +LL | let d = Bar::::lol(); + | ^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let d = >::lol(); + | ++++ + + +error[E0599]: no function or associated item named `lol` found for trait object `dyn Bar` in the current scope + --> $DIR/unspecified-self-in-trait-ref.rs:22:30 + | +LL | let d = Bar::::lol(); + | ^^^ function or associated item not found in `dyn Bar` + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/unspecified-self-in-trait-ref.rs:26:13 + | +LL | let e = Bar::::lol(); + | ^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: use `dyn` + | +LL | let e = >::lol(); + | ++++ + + +error[E0393]: the type parameter `A` must be explicitly specified + --> $DIR/unspecified-self-in-trait-ref.rs:26:13 + | +LL | pub trait Bar { + | ------------------------------ type parameter `A` must be specified for this +... +LL | let e = Bar::::lol(); + | ^^^^^^^^^^^^ missing reference to `A` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to 5 previous errors; 5 warnings emitted + +Some errors have detailed explanations: E0393, E0599. +For more information about an error, try `rustc --explain E0393`. diff --git a/tests/ui/traits/use-before-def.rs b/tests/ui/traits/use-before-def.rs new file mode 100644 index 000000000..1ee2b9419 --- /dev/null +++ b/tests/ui/traits/use-before-def.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Issue #1761 + +// pretty-expanded FIXME #23616 + +impl foo for isize { fn foo(&self) -> isize { 10 } } +trait foo { fn foo(&self) -> isize; } +pub fn main() {} diff --git a/tests/ui/traits/vtable-res-trait-param.rs b/tests/ui/traits/vtable-res-trait-param.rs new file mode 100644 index 000000000..3d7c2eb08 --- /dev/null +++ b/tests/ui/traits/vtable-res-trait-param.rs @@ -0,0 +1,23 @@ +trait TraitA { + fn method_a(&self) -> isize; +} + +trait TraitB { + fn gimme_an_a(&self, a: A) -> isize; +} + +impl TraitB for isize { + fn gimme_an_a(&self, a: A) -> isize { + a.method_a() + *self + } +} + +fn call_it(b: B) -> isize { + let y = 4; + b.gimme_an_a(y) //~ ERROR `{integer}: TraitA` is not satisfied +} + +fn main() { + let x = 3; + assert_eq!(call_it(x), 22); +} diff --git a/tests/ui/traits/vtable-res-trait-param.stderr b/tests/ui/traits/vtable-res-trait-param.stderr new file mode 100644 index 000000000..2b3e3de9b --- /dev/null +++ b/tests/ui/traits/vtable-res-trait-param.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `{integer}: TraitA` is not satisfied + --> $DIR/vtable-res-trait-param.rs:17:18 + | +LL | b.gimme_an_a(y) + | ---------- ^ the trait `TraitA` is not implemented for `{integer}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `TraitB::gimme_an_a` + --> $DIR/vtable-res-trait-param.rs:6:21 + | +LL | fn gimme_an_a(&self, a: A) -> isize; + | ^^^^^^ required by this bound in `TraitB::gimme_an_a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/vtable/issue-91807.rs b/tests/ui/traits/vtable/issue-91807.rs new file mode 100644 index 000000000..f435ff09d --- /dev/null +++ b/tests/ui/traits/vtable/issue-91807.rs @@ -0,0 +1,17 @@ +// check-pass +// incremental + +struct Struct(T); + +impl std::ops::Deref for Struct { + type Target = dyn Fn(T); + fn deref(&self) -> &Self::Target { + unimplemented!() + } +} + +fn main() { + let f = Struct(Default::default()); + f(0); + f(0); +} diff --git a/tests/ui/traits/vtable/issue-97381.rs b/tests/ui/traits/vtable/issue-97381.rs new file mode 100644 index 000000000..393cf91ef --- /dev/null +++ b/tests/ui/traits/vtable/issue-97381.rs @@ -0,0 +1,30 @@ +use std::ops::Deref; +trait MyTrait: Deref {} +struct MyStruct(u32); +impl MyTrait for MyStruct {} +impl Deref for MyStruct { + type Target = u32; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +fn get_concrete_value(i: u32) -> MyStruct { + MyStruct(i) +} +fn get_boxed_value(i: u32) -> Box { + Box::new(get_concrete_value(i)) +} +fn main() { + let v = [1, 2, 3] + .iter() + .map(|i| get_boxed_value(*i)) + .collect::>(); + + let el = &v[0]; + + for _ in v { + //~^ ERROR cannot move out of `v` because it is borrowed + println!("{}", ***el > 0); + } +} diff --git a/tests/ui/traits/vtable/issue-97381.stderr b/tests/ui/traits/vtable/issue-97381.stderr new file mode 100644 index 000000000..c4f8294e2 --- /dev/null +++ b/tests/ui/traits/vtable/issue-97381.stderr @@ -0,0 +1,15 @@ +error[E0505]: cannot move out of `v` because it is borrowed + --> $DIR/issue-97381.rs:26:14 + | +LL | let el = &v[0]; + | - borrow of `v` occurs here +LL | +LL | for _ in v { + | ^ move out of `v` occurs here +LL | +LL | println!("{}", ***el > 0); + | ---- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/traits/vtable/vtable-diamond.rs b/tests/ui/traits/vtable/vtable-diamond.rs new file mode 100644 index 000000000..dc3c17ac3 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-diamond.rs @@ -0,0 +1,44 @@ +// build-fail +#![feature(rustc_attrs)] + +#[rustc_dump_vtable] +trait A { + fn foo_a(&self) {} +} + +#[rustc_dump_vtable] +trait B: A { + fn foo_b(&self) {} +} + +#[rustc_dump_vtable] +trait C: A { + //~^ error vtable + fn foo_c(&self) {} +} + +#[rustc_dump_vtable] +trait D: B + C { + //~^ error vtable + fn foo_d(&self) {} +} + +struct S; + +impl A for S {} +impl B for S {} +impl C for S {} +impl D for S {} + +fn foo(d: &dyn D) { + d.foo_d(); +} + +fn bar(d: &dyn C) { + d.foo_c(); +} + +fn main() { + foo(&S); + bar(&S); +} diff --git a/tests/ui/traits/vtable/vtable-diamond.stderr b/tests/ui/traits/vtable/vtable-diamond.stderr new file mode 100644 index 000000000..f3718c5d8 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-diamond.stderr @@ -0,0 +1,29 @@ +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a), + Method(::foo_b), + Method(::foo_c), + TraitVPtr(), + Method(::foo_d), + ] + --> $DIR/vtable-diamond.rs:21:1 + | +LL | trait D: B + C { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a), + Method(::foo_c), + ] + --> $DIR/vtable-diamond.rs:15:1 + | +LL | trait C: A { + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/vtable/vtable-multi-level.rs b/tests/ui/traits/vtable/vtable-multi-level.rs new file mode 100644 index 000000000..ebd55bcf3 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multi-level.rs @@ -0,0 +1,143 @@ +// build-fail +#![feature(rustc_attrs)] + +// O --> G --> C --> A +// \ \ \-> B +// | |-> F --> D +// | \-> E +// |-> N --> J --> H +// \ \-> I +// |-> M --> K +// \-> L + +#[rustc_dump_vtable] +trait A { + //~^ error vtable + fn foo_a(&self) {} +} + +#[rustc_dump_vtable] +trait B { + //~^ error vtable + fn foo_b(&self) {} +} + +#[rustc_dump_vtable] +trait C: A + B { + //~^ error vtable + fn foo_c(&self) {} +} + +#[rustc_dump_vtable] +trait D { + //~^ error vtable + fn foo_d(&self) {} +} + +#[rustc_dump_vtable] +trait E { + //~^ error vtable + fn foo_e(&self) {} +} + +#[rustc_dump_vtable] +trait F: D + E { + //~^ error vtable + fn foo_f(&self) {} +} + +#[rustc_dump_vtable] +trait G: C + F { + fn foo_g(&self) {} +} + +#[rustc_dump_vtable] +trait H { + //~^ error vtable + fn foo_h(&self) {} +} + +#[rustc_dump_vtable] +trait I { + //~^ error vtable + fn foo_i(&self) {} +} + +#[rustc_dump_vtable] +trait J: H + I { + //~^ error vtable + fn foo_j(&self) {} +} + +#[rustc_dump_vtable] +trait K { + //~^ error vtable + fn foo_k(&self) {} +} + +#[rustc_dump_vtable] +trait L { + //~^ error vtable + fn foo_l(&self) {} +} + +#[rustc_dump_vtable] +trait M: K + L { + //~^ error vtable + fn foo_m(&self) {} +} + +#[rustc_dump_vtable] +trait N: J + M { + //~^ error vtable + fn foo_n(&self) {} +} + +#[rustc_dump_vtable] +trait O: G + N { + //~^ error vtable + fn foo_o(&self) {} +} + +struct S; + +impl A for S {} +impl B for S {} +impl C for S {} +impl D for S {} +impl E for S {} +impl F for S {} +impl G for S {} +impl H for S {} +impl I for S {} +impl J for S {} +impl K for S {} +impl L for S {} +impl M for S {} +impl N for S {} +impl O for S {} + +macro_rules! monomorphize_vtable { + ($trait:ident) => {{ + fn foo(_ : &dyn $trait) {} + foo(&S); + }} +} + +fn main() { + monomorphize_vtable!(O); + + monomorphize_vtable!(A); + monomorphize_vtable!(B); + monomorphize_vtable!(C); + monomorphize_vtable!(D); + monomorphize_vtable!(E); + monomorphize_vtable!(F); + monomorphize_vtable!(H); + monomorphize_vtable!(I); + monomorphize_vtable!(J); + monomorphize_vtable!(K); + monomorphize_vtable!(L); + monomorphize_vtable!(M); + monomorphize_vtable!(N); +} diff --git a/tests/ui/traits/vtable/vtable-multi-level.stderr b/tests/ui/traits/vtable/vtable-multi-level.stderr new file mode 100644 index 000000000..c4389e23f --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multi-level.stderr @@ -0,0 +1,203 @@ +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a), + Method(::foo_b), + TraitVPtr(), + Method(::foo_c), + Method(::foo_d), + TraitVPtr(), + Method(::foo_e), + TraitVPtr(), + Method(::foo_f), + TraitVPtr(), + Method(::foo_g), + Method(::foo_h), + TraitVPtr(), + Method(::foo_i), + TraitVPtr(), + Method(::foo_j), + TraitVPtr(), + Method(::foo_k), + TraitVPtr(), + Method(::foo_l), + TraitVPtr(), + Method(::foo_m), + TraitVPtr(), + Method(::foo_n), + TraitVPtr(), + Method(::foo_o), + ] + --> $DIR/vtable-multi-level.rs:97:1 + | +LL | trait O: G + N { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a), + ] + --> $DIR/vtable-multi-level.rs:14:1 + | +LL | trait A { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_b), + ] + --> $DIR/vtable-multi-level.rs:20:1 + | +LL | trait B { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a), + Method(::foo_b), + TraitVPtr(), + Method(::foo_c), + ] + --> $DIR/vtable-multi-level.rs:26:1 + | +LL | trait C: A + B { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_d), + ] + --> $DIR/vtable-multi-level.rs:32:1 + | +LL | trait D { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_e), + ] + --> $DIR/vtable-multi-level.rs:38:1 + | +LL | trait E { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_d), + Method(::foo_e), + TraitVPtr(), + Method(::foo_f), + ] + --> $DIR/vtable-multi-level.rs:44:1 + | +LL | trait F: D + E { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_h), + ] + --> $DIR/vtable-multi-level.rs:55:1 + | +LL | trait H { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_i), + ] + --> $DIR/vtable-multi-level.rs:61:1 + | +LL | trait I { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_h), + Method(::foo_i), + TraitVPtr(), + Method(::foo_j), + ] + --> $DIR/vtable-multi-level.rs:67:1 + | +LL | trait J: H + I { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_k), + ] + --> $DIR/vtable-multi-level.rs:73:1 + | +LL | trait K { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_l), + ] + --> $DIR/vtable-multi-level.rs:79:1 + | +LL | trait L { + | ^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_k), + Method(::foo_l), + TraitVPtr(), + Method(::foo_m), + ] + --> $DIR/vtable-multi-level.rs:85:1 + | +LL | trait M: K + L { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_h), + Method(::foo_i), + TraitVPtr(), + Method(::foo_j), + Method(::foo_k), + TraitVPtr(), + Method(::foo_l), + TraitVPtr(), + Method(::foo_m), + TraitVPtr(), + Method(::foo_n), + ] + --> $DIR/vtable-multi-level.rs:91:1 + | +LL | trait N: J + M { + | ^^^^^^^^^^^^^^ + +error: aborting due to 14 previous errors + diff --git a/tests/ui/traits/vtable/vtable-multiple.rs b/tests/ui/traits/vtable/vtable-multiple.rs new file mode 100644 index 000000000..7a0111c5e --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multiple.rs @@ -0,0 +1,33 @@ +// build-fail +#![feature(rustc_attrs)] + +#[rustc_dump_vtable] +trait A { + fn foo_a(&self) {} +} + +#[rustc_dump_vtable] +trait B { + //~^ error vtable + fn foo_b(&self) {} +} + +#[rustc_dump_vtable] +trait C: A + B { + //~^ error vtable + fn foo_c(&self) {} +} + +struct S; + +impl A for S {} +impl B for S {} +impl C for S {} + +fn foo(c: &dyn C) {} +fn bar(c: &dyn B) {} + +fn main() { + foo(&S); + bar(&S); +} diff --git a/tests/ui/traits/vtable/vtable-multiple.stderr b/tests/ui/traits/vtable/vtable-multiple.stderr new file mode 100644 index 000000000..0dcd84433 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-multiple.stderr @@ -0,0 +1,27 @@ +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a), + Method(::foo_b), + TraitVPtr(), + Method(::foo_c), + ] + --> $DIR/vtable-multiple.rs:16:1 + | +LL | trait C: A + B { + | ^^^^^^^^^^^^^^ + +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_b), + ] + --> $DIR/vtable-multiple.rs:10:1 + | +LL | trait B { + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.rs b/tests/ui/traits/vtable/vtable-non-object-safe.rs new file mode 100644 index 000000000..7661bb574 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-non-object-safe.rs @@ -0,0 +1,18 @@ +// build-fail +#![feature(rustc_attrs)] + +// Ensure that non-object-safe methods in Iterator does not generate +// vtable entries. + +#[rustc_dump_vtable] +trait A: Iterator {} +//~^ error vtable + +impl A for T where T: Iterator {} + +fn foo(_a: &mut dyn A) { +} + +fn main() { + foo(&mut vec![0, 1, 2, 3].into_iter()); +} diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.stderr b/tests/ui/traits/vtable/vtable-non-object-safe.stderr new file mode 100644 index 000000000..9345c2711 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-non-object-safe.stderr @@ -0,0 +1,16 @@ +error: vtable entries for ` as A>`: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method( as Iterator>::next), + Method( as Iterator>::size_hint), + Method( as Iterator>::advance_by), + Method( as Iterator>::nth), + ] + --> $DIR/vtable-non-object-safe.rs:8:1 + | +LL | trait A: Iterator {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/vtable/vtable-vacant.rs b/tests/ui/traits/vtable/vtable-vacant.rs new file mode 100644 index 000000000..a64796358 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-vacant.rs @@ -0,0 +1,31 @@ +// build-fail +#![feature(rustc_attrs)] +#![feature(negative_impls)] +#![allow(where_clauses_object_safety)] + +// B --> A + +#[rustc_dump_vtable] +trait A { + fn foo_a1(&self) {} + fn foo_a2(&self) where Self: Send {} +} + +#[rustc_dump_vtable] +trait B: A { + //~^ error vtable + fn foo_b1(&self) {} + fn foo_b2(&self) where Self: Send {} +} + +struct S; +impl !Send for S {} + +impl A for S {} +impl B for S {} + +fn foo(_: &dyn B) {} + +fn main() { + foo(&S); +} diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr new file mode 100644 index 000000000..5346a7027 --- /dev/null +++ b/tests/ui/traits/vtable/vtable-vacant.stderr @@ -0,0 +1,16 @@ +error: vtable entries for ``: [ + MetadataDropInPlace, + MetadataSize, + MetadataAlign, + Method(::foo_a1), + Vacant, + Method(::foo_b1), + Vacant, + ] + --> $DIR/vtable-vacant.rs:15:1 + | +LL | trait B: A { + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/traits/wf-object/maybe-bound.rs b/tests/ui/traits/wf-object/maybe-bound.rs new file mode 100644 index 000000000..17771e976 --- /dev/null +++ b/tests/ui/traits/wf-object/maybe-bound.rs @@ -0,0 +1,18 @@ +// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). + +trait Foo {} + +type _0 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types + +type _1 = dyn Foo + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types + +type _2 = dyn Foo + ?Sized + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types +//~| ERROR `?Trait` is not permitted in trait object types + +type _3 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types + +fn main() {} diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr new file mode 100644 index 000000000..2fe3f0fc3 --- /dev/null +++ b/tests/ui/traits/wf-object/maybe-bound.stderr @@ -0,0 +1,32 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:5:15 + | +LL | type _0 = dyn ?Sized + Foo; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:8:21 + | +LL | type _1 = dyn Foo + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:11:21 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:11:30 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bound.rs:15:15 + | +LL | type _3 = dyn ?Sized + Foo; + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/traits/wf-object/no-duplicates.rs b/tests/ui/traits/wf-object/no-duplicates.rs new file mode 100644 index 000000000..678ede582 --- /dev/null +++ b/tests/ui/traits/wf-object/no-duplicates.rs @@ -0,0 +1,33 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto-traits is rejected even though one could reasonably accept this. + +// Some arbitrary object-safe trait: +trait Obj {} + +// Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: +type _0 = dyn Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Some variations: + +type _1 = dyn Send + Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _2 = dyn Obj + Send + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _3 = dyn Obj + Send + Send; // But it is OK to duplicate auto traits. + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT {} +type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/tests/ui/traits/wf-object/no-duplicates.stderr b/tests/ui/traits/wf-object/no-duplicates.stderr new file mode 100644 index 000000000..50dfcf956 --- /dev/null +++ b/tests/ui/traits/wf-object/no-duplicates.stderr @@ -0,0 +1,58 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:8:21 + | +LL | type _0 = dyn Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:13:28 + | +LL | type _1 = dyn Send + Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:16:28 + | +LL | type _2 = dyn Obj + Send + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:26:34 + | +LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; + | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/no-duplicates.rs:30:42 + | +LL | type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + | + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT fn(&'a u8)> + ObjT fn(&'b u8)> {}` + = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs new file mode 100644 index 000000000..3e6db3e99 --- /dev/null +++ b/tests/ui/traits/wf-object/only-maybe-bound.rs @@ -0,0 +1,7 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed. + +type _0 = dyn ?Sized; +//~^ ERROR at least one trait is required for an object type [E0224] +//~| ERROR ?Trait` is not permitted in trait object types + +fn main() {} diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr new file mode 100644 index 000000000..cbc41feec --- /dev/null +++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr @@ -0,0 +1,15 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/only-maybe-bound.rs:3:15 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/only-maybe-bound.rs:3:11 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs new file mode 100644 index 000000000..4f676cbe3 --- /dev/null +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -0,0 +1,15 @@ +// run-pass + +// Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. + +use std::marker::Unpin; + +// Some arbitrary object-safe trait: +trait Obj {} + +type _0 = dyn Unpin; +type _1 = dyn Send + Obj; +type _2 = dyn Send + Unpin + Obj; +type _3 = dyn Send + Unpin + Sync + Obj; + +fn main() {} diff --git a/tests/ui/traits/where-clause-vs-impl.rs b/tests/ui/traits/where-clause-vs-impl.rs new file mode 100644 index 000000000..7cfee27ef --- /dev/null +++ b/tests/ui/traits/where-clause-vs-impl.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that when there is a conditional (but blanket) impl and a +// where clause, we don't get confused in trait resolution. +// +// Issue #18453. + +// pretty-expanded FIXME #23616 + +use std::rc::Rc; + +pub trait Foo { + fn foo(&mut self, msg: M); +} + +pub trait Bar { + fn dummy(&self) -> M; +} + +impl> Foo for F { + fn foo(&mut self, msg: M) { + } +} + +pub struct Both { + inner: Rc<(M, F)>, +} + +impl> Clone for Both { + fn clone(&self) -> Both { + Both { inner: self.inner.clone() } + } +} + +fn repro1>(_both: Both) { +} + +fn repro2>(msg: M, foo: F) { + let both = Both { inner: Rc::new((msg, foo)) }; + repro1(both.clone()); // <--- This clone causes problem +} + +pub fn main() { +} diff --git a/tests/ui/traits/with-bounds-default.rs b/tests/ui/traits/with-bounds-default.rs new file mode 100644 index 000000000..31f73d79c --- /dev/null +++ b/tests/ui/traits/with-bounds-default.rs @@ -0,0 +1,32 @@ +// run-pass + +pub trait Clone2 { + /// Returns a copy of the value. The contents of boxes + /// are copied to maintain uniqueness, while the contents of + /// managed pointers are not copied. + fn clone(&self) -> Self; +} + +trait Getter { + fn do_get(&self) -> T; + + fn do_get2(&self) -> (T, T) { + let x = self.do_get(); + (x.clone(), x.clone()) + } + +} + +impl Getter for isize { + fn do_get(&self) -> isize { *self } +} + +impl Getter for Option { + fn do_get(&self) -> T { self.as_ref().unwrap().clone() } +} + + +pub fn main() { + assert_eq!(3.do_get2(), (3, 3)); + assert_eq!(Some("hi".to_string()).do_get2(), ("hi".to_string(), "hi".to_string())); +} diff --git a/tests/ui/traits/with-dst.rs b/tests/ui/traits/with-dst.rs new file mode 100644 index 000000000..a3e3b31df --- /dev/null +++ b/tests/ui/traits/with-dst.rs @@ -0,0 +1,22 @@ +// build-pass (FIXME(62277): could be check-pass?) +// #55266 + +struct VTable { + _to_dst_ptr: fn(*mut ()) -> *mut DST, +} + +trait HasVTableFor { + const VTABLE: &'static VTable; +} + +impl HasVTableFor for T { + const VTABLE: &'static VTable = &VTable { + _to_dst_ptr: |_: *mut ()| unsafe { std::mem::zeroed() }, + }; +} + +pub fn push() { + >::VTABLE; +} + +fn main() {} diff --git a/tests/ui/transmutability/abstraction/abstracted_assume.rs b/tests/ui/transmutability/abstraction/abstracted_assume.rs new file mode 100644 index 000000000..0225c4230 --- /dev/null +++ b/tests/ui/transmutability/abstraction/abstracted_assume.rs @@ -0,0 +1,72 @@ +// check-pass +//! The implementation should behave correctly when the `ASSUME` parameters are +//! provided indirectly through an abstraction. + +#![crate_type = "lib"] +#![feature(adt_const_params)] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME: std::mem::Assume, + >() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + ASSUME, + >, + {} +} + +fn direct() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + assert::is_transmutable::(); +} + +fn via_const() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + const FALSE: bool = false; + + assert::is_transmutable::(); +} + +fn via_associated_const() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + trait Trait { + const FALSE: bool = true; + } + + struct Ty; + + impl Trait for Ty {} + + assert::is_transmutable::< + Src, + Dst, + Context, + { + std::mem::Assume { + alignment: {Ty::FALSE}, + lifetimes: {Ty::FALSE}, + safety: {Ty::FALSE}, + validity: {Ty::FALSE}, + } + } + >(); +} diff --git a/tests/ui/transmutability/abstraction/const_generic_fn.rs b/tests/ui/transmutability/abstraction/const_generic_fn.rs new file mode 100644 index 000000000..e693a0957 --- /dev/null +++ b/tests/ui/transmutability/abstraction/const_generic_fn.rs @@ -0,0 +1,41 @@ +// check-pass +//! An array must have the correct length. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn array_like() + where + T: BikeshedIntrinsicFrom<[E; N], Context, { Assume::SAFETY }>, + [E; N]: BikeshedIntrinsicFrom + {} +} + +fn len_0() { + type Array = [u8; 0]; + #[repr(C)] struct Struct(); + assert::array_like::(); +} + +fn len_1() { + type Array = [u8; 1]; + #[repr(C)] struct Struct(u8); + assert::array_like::(); +} + +fn len_2() { + type Array = [u8; 2]; + #[repr(C)] struct Struct(u8, u8); + assert::array_like::(); +} + +fn len_3() { + type Array = [u8; 3]; + #[repr(C)] struct Struct(u8, u8, u8); + assert::array_like::(); +} diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.rs b/tests/ui/transmutability/arrays/issue-103783-array-length.rs new file mode 100644 index 000000000..cb36e539e --- /dev/null +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.rs @@ -0,0 +1,24 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, + >, + { + } +} + +fn test() { + type NaughtyLenArray = [u32; 3.14159]; //~ ERROR mismatched types + type JustUnit = (); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.stderr b/tests/ui/transmutability/arrays/issue-103783-array-length.stderr new file mode 100644 index 000000000..37774c59e --- /dev/null +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-103783-array-length.rs:21:34 + | +LL | type NaughtyLenArray = [u32; 3.14159]; + | ^^^^^^^ expected `usize`, found floating-point number + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/arrays/should_have_correct_length.rs b/tests/ui/transmutability/arrays/should_have_correct_length.rs new file mode 100644 index 000000000..353797d0c --- /dev/null +++ b/tests/ui/transmutability/arrays/should_have_correct_length.rs @@ -0,0 +1,44 @@ +// check-pass +//! An array must have the correct length. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_have_len_0() { + type Array = [u8; 0]; + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} + +fn should_have_len_1() { + type Array = [u8; 1]; + #[repr(C)] struct Struct(u8); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} + +fn should_have_len_2() { + type Array = [u8; 2]; + #[repr(C)] struct Struct(u8, u8); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} + +fn should_have_len_3() { + type Array = [u8; 3]; + #[repr(C)] struct Struct(u8, u8, u8); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/arrays/should_inherit_alignment.rs b/tests/ui/transmutability/arrays/should_inherit_alignment.rs new file mode 100644 index 000000000..b00e5c7e4 --- /dev/null +++ b/tests/ui/transmutability/arrays/should_inherit_alignment.rs @@ -0,0 +1,60 @@ +// check-pass +//! An array must inherit the alignment of its inner type. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox01 { V = 0x01 } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +#[repr(C)] +union Uninit { + a: (), + b: OxFF, +} + +#[repr(C, align(2))] struct align_2(Ox00); + +fn len_0() { + #[repr(C)] struct ImplicitlyPadded([align_2; 0], Ox01); + #[repr(C)] struct ExplicitlyPadded(Ox01, Uninit); + + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} + +fn len_1() { + #[repr(C)] struct ImplicitlyPadded([align_2; 1], Ox01); + #[repr(C)] struct ExplicitlyPadded(Ox00, Uninit, Ox01, Uninit); + + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} + +fn len_2() { + #[repr(C)] struct ImplicitlyPadded([align_2; 2], Ox01); + #[repr(C)] struct ExplicitlyPadded(Ox00, Uninit, Ox00, Uninit, Ox01, Uninit); + + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs new file mode 100644 index 000000000..853bd9cbc --- /dev/null +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs @@ -0,0 +1,66 @@ +//! An array must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_reject_repr_rust() +{ + fn unit() { + type repr_rust = [String; 0]; + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn singleton() { + type repr_rust = [String; 1]; + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn duplex() { + type repr_rust = [String; 2]; + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn should_accept_repr_C() +{ + fn unit() { + #[repr(C)] struct repr_c(u8, u16, u8); + type array = [repr_c; 0]; + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn singleton() { + #[repr(C)] struct repr_c(u8, u16, u8); + type array = [repr_c; 1]; + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn duplex() { + #[repr(C)] struct repr_c(u8, u16, u8); + #[repr(C)] struct duplex(repr_c, repr_c); + type array = [repr_c; 2]; + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } +} diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..96a2fdc54 --- /dev/null +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr @@ -0,0 +1,135 @@ +error[E0277]: `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:26:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<[String; 0], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:27:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `[String; 0]` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:32:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<[String; 1], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:33:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `[String; 1]` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:38:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<[String; 2], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:39:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `[String; 2]` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs new file mode 100644 index 000000000..940f070e7 --- /dev/null +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs @@ -0,0 +1,156 @@ +//! An enum with a primitive repr should have exactly the size of that primitive. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[repr(C)] +struct Zst; + +#[derive(Clone, Copy)] +#[repr(i8)] enum V0i8 { V } +#[repr(u8)] enum V0u8 { V } +#[repr(i16)] enum V0i16 { V } +#[repr(u16)] enum V0u16 { V } +#[repr(i32)] enum V0i32 { V } +#[repr(u32)] enum V0u32 { V } +#[repr(i64)] enum V0i64 { V } +#[repr(u64)] enum V0u64 { V } +#[repr(isize)] enum V0isize { V } +#[repr(usize)] enum V0usize { V } + +fn n8() { + struct Context; + + type Smaller = Zst; + type Analog = u8; + type Larger = u16; + + fn i_should_have_correct_length() { + type Current = V0i8; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u8; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn n16() { + struct Context; + + type Smaller = u8; + type Analog = u16; + type Larger = u32; + + fn i_should_have_correct_length() { + type Current = V0i16; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u16; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn n32() { + struct Context; + + type Smaller = u16; + type Analog = u32; + type Larger = u64; + + fn i_should_have_correct_length() { + type Current = V0i32; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u32; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn n64() { + struct Context; + + type Smaller = u32; + type Analog = u64; + type Larger = u128; + + fn i_should_have_correct_length() { + type Current = V0i64; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u64; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn nsize() { + struct Context; + + type Smaller = u8; + type Analog = usize; + type Larger = [usize; 2]; + + fn i_should_have_correct_length() { + type Current = V0isize; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0usize; + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + } +} diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr new file mode 100644 index 000000000..4da5fcea3 --- /dev/null +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr @@ -0,0 +1,463 @@ +error[E0277]: `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:48:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0i8` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:50:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:56:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0u8` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:58:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:72:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0i16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:74:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:80:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0u16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:82:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:96:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0i32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:98:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:104:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0u32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:106:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:120:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0i64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:122:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:128:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0u64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:130:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:144:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0isize` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:146:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `[usize; 2]` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:152:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `V0usize` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:154:44 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `[usize; 2]` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..102111ae2 --- /dev/null +++ b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs @@ -0,0 +1,124 @@ +//! An enum must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(repr128)] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_reject_repr_rust() { + fn void() { + enum repr_rust {} + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn singleton() { + enum repr_rust { V } + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn duplex() { + enum repr_rust { A, B } + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn should_accept_primitive_reprs() +{ + fn should_accept_repr_i8() { + #[repr(i8)] enum repr_i8 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_u8() { + #[repr(u8)] enum repr_u8 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_i16() { + #[repr(i16)] enum repr_i16 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_u16() { + #[repr(u16)] enum repr_u16 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_i32() { + #[repr(i32)] enum repr_i32 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_u32() { + #[repr(u32)] enum repr_u32 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_i64() { + #[repr(i64)] enum repr_i64 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_u64() { + #[repr(u64)] enum repr_u64 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_i128() { + #[repr(i128)] enum repr_i128 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_u128() { + #[repr(u128)] enum repr_u128 { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_isize() { + #[repr(isize)] enum repr_isize { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn should_accept_repr_usize() { + #[repr(usize)] enum repr_usize { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } +} + +fn should_accept_repr_C() { + #[repr(C)] enum repr_c { V } + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..510b8c56e --- /dev/null +++ b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,141 @@ +error[E0277]: `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:28:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:29:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `void::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:34:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:35:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `singleton::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:40:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:41:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `duplex::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/should_order_correctly.rs b/tests/ui/transmutability/enums/should_order_correctly.rs new file mode 100644 index 000000000..1335cc9d2 --- /dev/null +++ b/tests/ui/transmutability/enums/should_order_correctly.rs @@ -0,0 +1,36 @@ +// check-pass +//! The payloads of an enum variant should be ordered after its tag. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[repr(u8)] enum V0 { V = 0 } +#[repr(u8)] enum V1 { V = 1 } +#[repr(u8)] enum V2 { V = 2 } + +#[repr(u8)] enum E01 { V0(V1) = 0u8 } +#[repr(u8)] enum E012 { V0(V1, V2) = 0u8 } + +fn should_order_tag_and_fields_correctly() { + // An implementation that (incorrectly) arranges E01 as [0x01, 0x00] will, + // in principle, reject this transmutation. + assert::is_transmutable::(); + // Again, but with one more field. + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/enums/should_pad_variants.rs b/tests/ui/transmutability/enums/should_pad_variants.rs new file mode 100644 index 000000000..c077c52a3 --- /dev/null +++ b/tests/ui/transmutability/enums/should_pad_variants.rs @@ -0,0 +1,45 @@ +//! The variants of an enum must be padded with uninit bytes such that they have +//! the same length (in bytes). + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[derive(Clone, Copy)] +#[repr(C)] struct Zst; + +#[derive(Clone, Copy)] +#[repr(u8)] enum V0 { V = 0 } + +#[derive(Clone, Copy)] +#[repr(u8)] enum V2 { V = 2 } + +#[repr(C, u8)] +enum Lopsided { + Smol(Zst), + Lorg(V0), +} + +#[repr(C)] struct Src(V0, Zst, V2); +#[repr(C)] struct Dst(Lopsided, V2); + +fn should_pad_variants() { + struct Context; + // If the implementation (incorrectly) fails to pad `Lopsided::Smol` with + // an uninitialized byte, this transmutation might be (wrongly) accepted: + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/enums/should_pad_variants.stderr b/tests/ui/transmutability/enums/should_pad_variants.stderr new file mode 100644 index 000000000..a823503d5 --- /dev/null +++ b/tests/ui/transmutability/enums/should_pad_variants.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + --> $DIR/should_pad_variants.rs:44:36 + | +LL | assert::is_transmutable::(); + | ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_pad_variants.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/should_respect_endianness.rs b/tests/ui/transmutability/enums/should_respect_endianness.rs new file mode 100644 index 000000000..f3567b405 --- /dev/null +++ b/tests/ui/transmutability/enums/should_respect_endianness.rs @@ -0,0 +1,37 @@ +//! The target endianness should be a consideration in computing the layout of +//! an enum with a multi-byte tag. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[repr(u16)] enum Src { V = 0xCAFE } + +#[repr(u8)] enum OxCA { V = 0xCA } +#[repr(u8)] enum OxFE { V = 0xFE } + +#[cfg(target_endian = "big")] #[repr(C)] struct Expected(OxCA, OxFE); +#[cfg(target_endian = "big")] #[repr(C)] struct Unexpected(OxFE, OxCA); + +#[cfg(target_endian = "little")] #[repr(C)] struct Expected(OxFE, OxCA); +#[cfg(target_endian = "little")] #[repr(C)] struct Unexpected(OxCA, OxFE); + +fn should_respect_endianness() { + assert::is_transmutable::(); + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/enums/should_respect_endianness.stderr b/tests/ui/transmutability/enums/should_respect_endianness.stderr new file mode 100644 index 000000000..0845a5edf --- /dev/null +++ b/tests/ui/transmutability/enums/should_respect_endianness.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. + --> $DIR/should_respect_endianness.rs:36:36 + | +LL | assert::is_transmutable::(); + | ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Unexpected` +note: required by a bound in `is_transmutable` + --> $DIR/should_respect_endianness.rs:14:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs new file mode 100644 index 000000000..bcb8b158e --- /dev/null +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -0,0 +1,21 @@ +#![feature(transmutability)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom, //~ ERROR cannot find type `Dst` in this scope + //~^ ERROR mismatched types + { + } +} + +fn via_const() { + struct Context; + struct Src; + + assert::is_transmutable::(); +} + +fn main() {} diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr new file mode 100644 index 000000000..5fa741f26 --- /dev/null +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -0,0 +1,16 @@ +error[E0412]: cannot find type `Dst` in this scope + --> $DIR/issue-101739-1.rs:8:9 + | +LL | Dst: BikeshedIntrinsicFrom, + | ^^^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/issue-101739-1.rs:8:50 + | +LL | Dst: BikeshedIntrinsicFrom, + | ^^^^^^^^^^^^^^^^ expected struct `Assume`, found `bool` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0412. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs new file mode 100644 index 000000000..964a7e49e --- /dev/null +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -0,0 +1,37 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME_ALIGNMENT: bool, + const ASSUME_LIFETIMES: bool, + const ASSUME_VALIDITY: bool, + const ASSUME_VISIBILITY: bool, + >() + where + Dst: BikeshedIntrinsicFrom< //~ ERROR this trait takes at most 3 generic arguments but 6 generic arguments were supplied + Src, + Context, + ASSUME_ALIGNMENT, + ASSUME_LIFETIMES, + ASSUME_VALIDITY, + ASSUME_VISIBILITY, + >, + {} +} + +fn via_const() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + const FALSE: bool = false; + + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr new file mode 100644 index 000000000..1b3d20259 --- /dev/null +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -0,0 +1,14 @@ +error[E0107]: this trait takes at most 3 generic arguments but 6 generic arguments were supplied + --> $DIR/issue-101739-2.rs:18:14 + | +LL | Dst: BikeshedIntrinsicFrom< + | ^^^^^^^^^^^^^^^^^^^^^ expected at most 3 generic arguments +... +LL | / ASSUME_LIFETIMES, +LL | | ASSUME_VALIDITY, +LL | | ASSUME_VISIBILITY, + | |_____________________________- help: remove these generic arguments + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs new file mode 100644 index 000000000..30c381745 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs @@ -0,0 +1,9 @@ +// The trait must not be available if its feature flag is absent. + +#![crate_type = "lib"] + +use std::mem::BikeshedIntrinsicFrom; +//~^ ERROR use of unstable library feature 'transmutability' [E0658] + +use std::mem::Assume; +//~^ ERROR use of unstable library feature 'transmutability' [E0658] diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr new file mode 100644 index 000000000..ba8093f86 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/feature-missing.rs:5:5 + | +LL | use std::mem::BikeshedIntrinsicFrom; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #99571 for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/feature-missing.rs:8:5 + | +LL | use std::mem::Assume; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #99571 for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs new file mode 100644 index 000000000..b3a1e13b8 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs @@ -0,0 +1,21 @@ +// An unknown destination type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_gracefully_handle_unknown_dst() { + struct Context; + struct Src; + assert::is_transmutable::(); //~ cannot find type +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr new file mode 100644 index 000000000..b4591778f --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Dst` in this scope + --> $DIR/unknown_dst.rs:20:36 + | +LL | assert::is_transmutable::(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn should_gracefully_handle_unknown_dst() { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs new file mode 100644 index 000000000..092b205b7 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs @@ -0,0 +1,21 @@ +// An unknown source type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_gracefully_handle_unknown_src() { + struct Context; + #[repr(C)] struct Dst; + assert::is_transmutable::(); //~ cannot find type +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr new file mode 100644 index 000000000..a55d71d80 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Src` in this scope + --> $DIR/unknown_src.rs:20:31 + | +LL | assert::is_transmutable::(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn should_gracefully_handle_unknown_src() { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs new file mode 100644 index 000000000..ebe34e134 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs @@ -0,0 +1,22 @@ +// An unknown destination type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_gracefully_handle_unknown_dst_field() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst(Missing); //~ cannot find type + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr new file mode 100644 index 000000000..475e6f429 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_src_field.rs:20:27 + | +LL | #[repr(C)] struct Dst(Missing); + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs new file mode 100644 index 000000000..52aa4bb31 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs @@ -0,0 +1,53 @@ +//! The implementation must behave well if const values of wrong types are +//! provided. + +#![crate_type = "lib"] +#![feature(adt_const_params)] +#![feature(generic_const_exprs)] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME_ALIGNMENT: bool, + const ASSUME_LIFETIMES: bool, + const ASSUME_SAFETY: bool, + const ASSUME_VALIDITY: bool, + >() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } + >, + {} + + const fn from_options( + alignment: bool, + lifetimes: bool, + safety: bool, + validity: bool, + ) -> Assume { + Assume { + alignment, + lifetimes, + safety, + validity, + } + } +} + +fn test() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + assert::is_transmutable::(); //~ ERROR mismatched types + assert::is_transmutable::(); //~ ERROR mismatched types + assert::is_transmutable::(); //~ ERROR mismatched types + assert::is_transmutable::(); //~ ERROR mismatched types +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr new file mode 100644 index 000000000..c6d93876c --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:49:51 + | +LL | assert::is_transmutable::(); + | ^^^ expected `bool`, found `u8` + +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:50:58 + | +LL | assert::is_transmutable::(); + | ^^^ expected `bool`, found `u8` + +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:51:65 + | +LL | assert::is_transmutable::(); + | ^^^ expected `bool`, found `u8` + +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:52:72 + | +LL | assert::is_transmutable::(); + | ^^^ expected `bool`, found `u8` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs new file mode 100644 index 000000000..eebb74fff --- /dev/null +++ b/tests/ui/transmutability/primitives/bool.rs @@ -0,0 +1,25 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn contrast_with_u8() { + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/primitives/bool.stderr b/tests/ui/transmutability/primitives/bool.stderr new file mode 100644 index 000000000..214b5e150 --- /dev/null +++ b/tests/ui/transmutability/primitives/bool.stderr @@ -0,0 +1,19 @@ +error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`. + --> $DIR/bool.rs:22:35 + | +LL | assert::is_transmutable::(); + | ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `bool` +note: required by a bound in `is_transmutable` + --> $DIR/bool.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs new file mode 100644 index 000000000..0df43d204 --- /dev/null +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -0,0 +1,128 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_accept_identity() { + assert::is_transmutable::< i8, i8>(); + assert::is_transmutable::< u8, u8>(); + assert::is_transmutable::< i16, i16>(); + assert::is_transmutable::< u16, u16>(); + assert::is_transmutable::< i32, i32>(); + assert::is_transmutable::< f32, f32>(); + assert::is_transmutable::< u32, u32>(); + assert::is_transmutable::< i64, i64>(); + assert::is_transmutable::< f64, f64>(); + assert::is_transmutable::< u64, u64>(); + assert::is_transmutable::< i128, i128>(); + assert::is_transmutable::< u128, u128>(); + assert::is_transmutable::(); + assert::is_transmutable::(); +} + +fn should_be_bitransmutable() { + assert::is_transmutable::< i8, u8>(); + assert::is_transmutable::< u8, i8>(); + + assert::is_transmutable::< i16, u16>(); + assert::is_transmutable::< u16, i16>(); + + assert::is_transmutable::< i32, f32>(); + assert::is_transmutable::< i32, u32>(); + assert::is_transmutable::< f32, i32>(); + assert::is_transmutable::< f32, u32>(); + assert::is_transmutable::< u32, i32>(); + assert::is_transmutable::< u32, f32>(); + + assert::is_transmutable::< u64, i64>(); + assert::is_transmutable::< u64, f64>(); + assert::is_transmutable::< i64, u64>(); + assert::is_transmutable::< i64, f64>(); + assert::is_transmutable::< f64, u64>(); + assert::is_transmutable::< f64, i64>(); + + assert::is_transmutable::< u128, i128>(); + assert::is_transmutable::< i128, u128>(); + + assert::is_transmutable::(); + assert::is_transmutable::(); +} + +fn should_reject_extension() { + assert::is_transmutable::< i8, i16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u8, i16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< i16, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u16, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< i32, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< f32, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u32, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u64, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u64, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< i64, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i64, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< f64, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f64, i128>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/primitives/numbers.stderr b/tests/ui/transmutability/primitives/numbers.stderr new file mode 100644 index 000000000..7cb7ca8e6 --- /dev/null +++ b/tests/ui/transmutability/primitives/numbers.stderr @@ -0,0 +1,915 @@ +error[E0277]: `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:62:40 + | +LL | assert::is_transmutable::< i8, i16>(); + | ^^^ `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:63:40 + | +LL | assert::is_transmutable::< i8, u16>(); + | ^^^ `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:64:40 + | +LL | assert::is_transmutable::< i8, i32>(); + | ^^^ `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:65:40 + | +LL | assert::is_transmutable::< i8, f32>(); + | ^^^ `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:66:40 + | +LL | assert::is_transmutable::< i8, u32>(); + | ^^^ `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:67:40 + | +LL | assert::is_transmutable::< i8, u64>(); + | ^^^ `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:68:40 + | +LL | assert::is_transmutable::< i8, i64>(); + | ^^^ `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:69:40 + | +LL | assert::is_transmutable::< i8, f64>(); + | ^^^ `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:70:39 + | +LL | assert::is_transmutable::< i8, u128>(); + | ^^^^ `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:71:39 + | +LL | assert::is_transmutable::< i8, i128>(); + | ^^^^ `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:73:40 + | +LL | assert::is_transmutable::< u8, i16>(); + | ^^^ `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:74:40 + | +LL | assert::is_transmutable::< u8, u16>(); + | ^^^ `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:75:40 + | +LL | assert::is_transmutable::< u8, i32>(); + | ^^^ `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:76:40 + | +LL | assert::is_transmutable::< u8, f32>(); + | ^^^ `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:77:40 + | +LL | assert::is_transmutable::< u8, u32>(); + | ^^^ `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:78:40 + | +LL | assert::is_transmutable::< u8, u64>(); + | ^^^ `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:79:40 + | +LL | assert::is_transmutable::< u8, i64>(); + | ^^^ `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:80:40 + | +LL | assert::is_transmutable::< u8, f64>(); + | ^^^ `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:81:39 + | +LL | assert::is_transmutable::< u8, u128>(); + | ^^^^ `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:82:39 + | +LL | assert::is_transmutable::< u8, i128>(); + | ^^^^ `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:84:40 + | +LL | assert::is_transmutable::< i16, i32>(); + | ^^^ `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:85:40 + | +LL | assert::is_transmutable::< i16, f32>(); + | ^^^ `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:86:40 + | +LL | assert::is_transmutable::< i16, u32>(); + | ^^^ `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:87:40 + | +LL | assert::is_transmutable::< i16, u64>(); + | ^^^ `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:88:40 + | +LL | assert::is_transmutable::< i16, i64>(); + | ^^^ `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:89:40 + | +LL | assert::is_transmutable::< i16, f64>(); + | ^^^ `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:90:39 + | +LL | assert::is_transmutable::< i16, u128>(); + | ^^^^ `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:91:39 + | +LL | assert::is_transmutable::< i16, i128>(); + | ^^^^ `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:93:40 + | +LL | assert::is_transmutable::< u16, i32>(); + | ^^^ `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:94:40 + | +LL | assert::is_transmutable::< u16, f32>(); + | ^^^ `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:95:40 + | +LL | assert::is_transmutable::< u16, u32>(); + | ^^^ `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:96:40 + | +LL | assert::is_transmutable::< u16, u64>(); + | ^^^ `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:97:40 + | +LL | assert::is_transmutable::< u16, i64>(); + | ^^^ `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:98:40 + | +LL | assert::is_transmutable::< u16, f64>(); + | ^^^ `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:99:39 + | +LL | assert::is_transmutable::< u16, u128>(); + | ^^^^ `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:100:39 + | +LL | assert::is_transmutable::< u16, i128>(); + | ^^^^ `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:102:40 + | +LL | assert::is_transmutable::< i32, u64>(); + | ^^^ `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:103:40 + | +LL | assert::is_transmutable::< i32, i64>(); + | ^^^ `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:104:40 + | +LL | assert::is_transmutable::< i32, f64>(); + | ^^^ `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:105:39 + | +LL | assert::is_transmutable::< i32, u128>(); + | ^^^^ `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:106:39 + | +LL | assert::is_transmutable::< i32, i128>(); + | ^^^^ `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:108:40 + | +LL | assert::is_transmutable::< f32, u64>(); + | ^^^ `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:109:40 + | +LL | assert::is_transmutable::< f32, i64>(); + | ^^^ `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:110:40 + | +LL | assert::is_transmutable::< f32, f64>(); + | ^^^ `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:111:39 + | +LL | assert::is_transmutable::< f32, u128>(); + | ^^^^ `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:112:39 + | +LL | assert::is_transmutable::< f32, i128>(); + | ^^^^ `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:114:40 + | +LL | assert::is_transmutable::< u32, u64>(); + | ^^^ `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:115:40 + | +LL | assert::is_transmutable::< u32, i64>(); + | ^^^ `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:116:40 + | +LL | assert::is_transmutable::< u32, f64>(); + | ^^^ `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:117:39 + | +LL | assert::is_transmutable::< u32, u128>(); + | ^^^^ `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:118:39 + | +LL | assert::is_transmutable::< u32, i128>(); + | ^^^^ `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:120:39 + | +LL | assert::is_transmutable::< u64, u128>(); + | ^^^^ `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:121:39 + | +LL | assert::is_transmutable::< u64, i128>(); + | ^^^^ `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:123:39 + | +LL | assert::is_transmutable::< i64, u128>(); + | ^^^^ `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:124:39 + | +LL | assert::is_transmutable::< i64, i128>(); + | ^^^^ `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:126:39 + | +LL | assert::is_transmutable::< f64, u128>(); + | ^^^^ `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:127:39 + | +LL | assert::is_transmutable::< f64, i128>(); + | ^^^^ `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 57 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/unit.rs b/tests/ui/transmutability/primitives/unit.rs new file mode 100644 index 000000000..1975a61de --- /dev/null +++ b/tests/ui/transmutability/primitives/unit.rs @@ -0,0 +1,29 @@ +//! The unit type, `()`, should be one byte. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[repr(C)] +struct Zst; + +fn should_have_correct_size() { + struct Context; + assert::is_transmutable::<(), Zst, Context>(); + assert::is_transmutable::(); + assert::is_transmutable::<(), u8, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/primitives/unit.stderr b/tests/ui/transmutability/primitives/unit.stderr new file mode 100644 index 000000000..8cabe44a0 --- /dev/null +++ b/tests/ui/transmutability/primitives/unit.stderr @@ -0,0 +1,25 @@ +error[E0277]: `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`. + --> $DIR/unit.rs:28:35 + | +LL | assert::is_transmutable::<(), u8, Context>(); + | ^^ `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u8` +note: required by a bound in `is_transmutable` + --> $DIR/unit.rs:12:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references.rs b/tests/ui/transmutability/references.rs new file mode 100644 index 000000000..af3ff0ec1 --- /dev/null +++ b/tests/ui/transmutability/references.rs @@ -0,0 +1,27 @@ +//! Transmutations involving references are not yet supported. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn not_yet_implemented() { + #[repr(C)] struct Unit; + assert::is_maybe_transmutable::<&'static Unit, &'static Unit>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/references.stderr b/tests/ui/transmutability/references.stderr new file mode 100644 index 000000000..e9c7b144a --- /dev/null +++ b/tests/ui/transmutability/references.stderr @@ -0,0 +1,26 @@ +error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`. + --> $DIR/references.rs:26:52 + | +LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>(); + | ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `&'static Unit` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/references.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/structs/repr/should_handle_align.rs b/tests/ui/transmutability/structs/repr/should_handle_align.rs new file mode 100644 index 000000000..ea9bf2a23 --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_handle_align.rs @@ -0,0 +1,43 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_pad_explicitly_aligned_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V0u8, + } + + #[repr(C, align(2))] struct align_2(V0u8); + + #[repr(C)] struct ImplicitlyPadded(align_2, V0u8); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V0u8); + + // An implementation that (incorrectly) does not place a padding byte after + // `align_2` will, incorrectly, reject the following transmutations. + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/structs/repr/should_handle_packed.rs b/tests/ui/transmutability/structs/repr/should_handle_packed.rs new file mode 100644 index 000000000..17dc995fc --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_handle_packed.rs @@ -0,0 +1,42 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_pad_explicitly_packed_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + #[derive(Clone, Copy)] #[repr(u32)] enum V0u32 { V = 0 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V0u8, + } + + #[repr(C, packed(2))] struct ImplicitlyPadded(V0u8, V0u32); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V0u8, V0u8, V0u8, V0u8); + + // An implementation that (incorrectly) does not place a padding byte after + // `align_2` will, incorrectly, reject the following transmutations. + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..9a65b4d70 --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs @@ -0,0 +1,83 @@ +//! A struct must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_reject_repr_rust() +{ + fn unit() { + struct repr_rust; + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn tuple() { + struct repr_rust(); + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn braces() { + struct repr_rust{} + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn aligned() { + #[repr(align(1))] struct repr_rust{} + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn packed() { + #[repr(packed)] struct repr_rust{} + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } + + fn nested() { + struct repr_rust; + #[repr(C)] struct repr_c(repr_rust); + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + } +} + +fn should_accept_repr_C() +{ + fn unit() { + #[repr(C)] struct repr_c; + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn tuple() { + #[repr(C)] struct repr_c(); + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } + + fn braces() { + #[repr(C)] struct repr_c{} + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); + } +} diff --git a/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..621dbee84 --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,279 @@ +error[E0277]: `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:28:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:29:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `should_reject_repr_rust::unit::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:34:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:35:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `should_reject_repr_rust::tuple::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:40:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:41:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `should_reject_repr_rust::braces::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:46:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:47:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `aligned::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:52:52 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:53:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `packed::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:59:49 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:60:47 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^ `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `nested::repr_c` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/structs/should_order_fields_correctly.rs b/tests/ui/transmutability/structs/should_order_fields_correctly.rs new file mode 100644 index 000000000..28724562b --- /dev/null +++ b/tests/ui/transmutability/structs/should_order_fields_correctly.rs @@ -0,0 +1,36 @@ +// check-pass +//! The fields of a struct should be laid out in lexical order. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[repr(u8)] enum V0 { V = 0 } +#[repr(u8)] enum V1 { V = 1 } +#[repr(u8)] enum V2 { V = 2 } + +#[repr(C)] struct S01(V0, V1); +#[repr(C)] struct S012(V0, V1, V2); + +fn should_order_tag_and_fields_correctly() { + // An implementation that (incorrectly) arranges S01 as [0x01, 0x00] will, + // in principle, reject this transmutation. + assert::is_transmutable::(); + // Again, but with one more field. + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/unions/boolish.rs b/tests/ui/transmutability/unions/boolish.rs new file mode 100644 index 000000000..e469c4973 --- /dev/null +++ b/tests/ui/transmutability/unions/boolish.rs @@ -0,0 +1,31 @@ +// check-pass + +#![crate_type = "lib"] +#![feature(transmutability)] +#![feature(marker_trait_attr)] +#![allow(dead_code)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_match_bool() { + #[derive(Copy, Clone)] #[repr(u8)] pub enum False { V = 0 } + #[derive(Copy, Clone)] #[repr(u8)] pub enum True { V = 1 } + + #[repr(C)] + pub union Bool { + pub f: False, + pub t: True, + } + + assert::is_transmutable::(); + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/unions/repr/should_handle_align.rs b/tests/ui/transmutability/unions/repr/should_handle_align.rs new file mode 100644 index 000000000..09c13cc4d --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_handle_align.rs @@ -0,0 +1,47 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_pad_explicitly_aligned_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + #[derive(Clone, Copy)] #[repr(u8)] enum V1u8 { V = 1 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V1u8, + } + + #[repr(C, align(2))] + pub union align_2 { + a: V0u8, + } + + #[repr(C)] struct ImplicitlyPadded(align_2, V0u8); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V0u8); + + // An implementation that (incorrectly) does not place a padding byte after + // `align_2` will, incorrectly, reject the following transmutations. + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/unions/repr/should_handle_packed.rs b/tests/ui/transmutability/unions/repr/should_handle_packed.rs new file mode 100644 index 000000000..24c2abd69 --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_handle_packed.rs @@ -0,0 +1,48 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_pad_explicitly_packed_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + #[derive(Clone, Copy)] #[repr(u8)] enum V1u8 { V = 1 } + #[derive(Clone, Copy)] #[repr(u8)] enum V2u8 { V = 2 } + #[derive(Clone, Copy)] #[repr(u32)] enum V3u32 { V = 3 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V1u8, + } + + #[repr(C, packed(2))] + pub union Packed { + a: [V3u32; 0], + b: V0u8, + } + + #[repr(C)] struct ImplicitlyPadded(Packed, V2u8); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V2u8); + + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..b1d5f71dc --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs @@ -0,0 +1,44 @@ +//! A struct must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +fn should_reject_repr_rust() +{ + union repr_rust { + a: u8 + } + + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted +} + +fn should_accept_repr_C() +{ + #[repr(C)] + union repr_c { + a: u8 + } + + struct repr_rust; + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..523bde85a --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,49 @@ +error[E0277]: `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:30:48 + | +LL | assert::is_maybe_transmutable::(); + | ^^ `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:31:43 + | +LL | assert::is_maybe_transmutable::(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `should_reject_repr_rust::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_pad_variants.rs b/tests/ui/transmutability/unions/should_pad_variants.rs new file mode 100644 index 000000000..cabe54467 --- /dev/null +++ b/tests/ui/transmutability/unions/should_pad_variants.rs @@ -0,0 +1,45 @@ +//! The variants of a union must be padded with uninit bytes such that they have +//! the same length (in bytes). + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[derive(Clone, Copy)] +#[repr(C)] struct Zst; + +#[derive(Clone, Copy)] +#[repr(u8)] enum V0 { V = 0 } + +#[derive(Clone, Copy)] +#[repr(u8)] enum V2 { V = 2 } + +#[repr(C)] +union Lopsided { + smol: Zst, + lorg: V0, +} + +#[repr(C)] struct Src(V0, Zst, V2); +#[repr(C)] struct Dst(V0, Lopsided, V2); + +fn should_pad_variants() { + struct Context; + // If the implementation (incorrectly) fails to pad `Lopsided::smol` with + // an uninitialized byte, this transmutation might be (wrongly) accepted: + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr new file mode 100644 index 000000000..a823503d5 --- /dev/null +++ b/tests/ui/transmutability/unions/should_pad_variants.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + --> $DIR/should_pad_variants.rs:44:36 + | +LL | assert::is_transmutable::(); + | ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_pad_variants.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs b/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs new file mode 100644 index 000000000..1007fdd79 --- /dev/null +++ b/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs @@ -0,0 +1,38 @@ +// check-pass +//! If validity is assumed, there need only be one matching bit-pattern between +//! the source and destination types. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox7F { V = 0x7F } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union A { + a: Ox00, + b: Ox7F, + } + + #[repr(C)] + union B { + a: Ox7F, + b: OxFF, + } + + assert::is_maybe_transmutable::(); + assert::is_maybe_transmutable::(); +} diff --git a/tests/ui/transmutability/unions/should_reject_contraction.rs b/tests/ui/transmutability/unions/should_reject_contraction.rs new file mode 100644 index 000000000..a24dfccd3 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_contraction.rs @@ -0,0 +1,36 @@ +//! Validity may not be contracted, unless validity is assumed. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox01 { V = 0x01 } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union Subset { + a: Ox00, + b: OxFF, + } + + #[repr(C)] + union Superset { + a: Ox00, + b: OxFF, + c: Ox01, + } + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr new file mode 100644 index 000000000..41f0cedc3 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Superset` cannot be safely transmuted into `Subset` in the defining scope of `assert::Context`. + --> $DIR/should_reject_contraction.rs:35:41 + | +LL | assert::is_transmutable::(); + | ^^^^^^ `Superset` cannot be safely transmuted into `Subset` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Subset` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_contraction.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.rs b/tests/ui/transmutability/unions/should_reject_disjoint.rs new file mode 100644 index 000000000..43aaa6905 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_disjoint.rs @@ -0,0 +1,35 @@ +//! Validity must be satisfiable, even if validity is assumed. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox01 { V = 0x01 } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union A { + a: Ox00, + b: OxFF, + } + + #[repr(C)] + union B { + c: Ox01, + } + + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr new file mode 100644 index 000000000..4323f9740 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr @@ -0,0 +1,35 @@ +error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + --> $DIR/should_reject_disjoint.rs:33:40 + | +LL | assert::is_maybe_transmutable::(); + | ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `B` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_reject_disjoint.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/should_reject_disjoint.rs:34:40 + | +LL | assert::is_maybe_transmutable::(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `A` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_reject_disjoint.rs:13:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.rs b/tests/ui/transmutability/unions/should_reject_intersecting.rs new file mode 100644 index 000000000..9cd4233ee --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_intersecting.rs @@ -0,0 +1,38 @@ +//! ALL valid bit patterns of the source must be valid bit patterns of the +//! destination type, unless validity is assumed. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + // validity is NOT assumed --------------^^^^^^^^^^^^^^^^^^ + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox7F { V = 0x7F } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union A { + a: Ox00, + b: Ox7F, + } + + #[repr(C)] + union B { + a: Ox7F, + b: OxFF, + } + + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr new file mode 100644 index 000000000..e009888ae --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr @@ -0,0 +1,35 @@ +error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + --> $DIR/should_reject_intersecting.rs:36:34 + | +LL | assert::is_transmutable::(); + | ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `B` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_intersecting.rs:14:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/should_reject_intersecting.rs:37:34 + | +LL | assert::is_transmutable::(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `A` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_intersecting.rs:14:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs new file mode 100644 index 000000000..8a41669c6 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs @@ -0,0 +1,38 @@ +// check-pass +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains a private field. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(self) field: Zst, // <- private field + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs new file mode 100644 index 000000000..dd57b877d --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs @@ -0,0 +1,39 @@ +// check-pass +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains a private variant. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[derive(Copy, Clone)] + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) union Dst { + pub(self) field: Zst, // <- private variant + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs new file mode 100644 index 000000000..ebce8ce87 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs @@ -0,0 +1,46 @@ +// check-pass +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) +//! +//! This test exercises a tricky-to-implement instance of this principle: the +//! "pub-in-priv trick". In the below example, the type `dst::private::Zst` is +//! unreachable from `Context`. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + mod private { + #[repr(C)] pub struct Zst; // <- unreachable type + } + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: private::Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs new file mode 100644 index 000000000..546fcbaa3 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs @@ -0,0 +1,39 @@ +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(self) struct Zst; // <- unreachable type + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, //~ ERROR private type + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr new file mode 100644 index 000000000..be83b7ce3 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `dst::Zst` in public interface + --> $DIR/should_accept_if_dst_has_unreachable_field.rs:32:9 + | +LL | #[repr(C)] pub(self) struct Zst; // <- unreachable type + | -------------------- `dst::Zst` declared as private +... +LL | pub(in super) field: Zst, + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs new file mode 100644 index 000000000..b9b74d183 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs @@ -0,0 +1,40 @@ +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + // unreachable type + #[repr(C)] pub(self) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); //~ ERROR `Dst` is private +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr new file mode 100644 index 000000000..827df05de --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr @@ -0,0 +1,15 @@ +error[E0603]: struct `Dst` is private + --> $DIR/should_accept_if_dst_has_unreachable_ty.rs:39:46 + | +LL | assert::is_transmutable::(); + | ^^^ private struct + | +note: the struct `Dst` is defined here + --> $DIR/should_accept_if_dst_has_unreachable_ty.rs:32:16 + | +LL | #[repr(C)] pub(self) struct Dst { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs new file mode 100644 index 000000000..5a0df09d4 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs @@ -0,0 +1,37 @@ +// check-pass +//! The presence of a private field in the source type does not affect +//! transmutability. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, // <- private field + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs new file mode 100644 index 000000000..0f69630cc --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs @@ -0,0 +1,38 @@ +// check-pass +//! The presence of a private variant in the source type does not affect +//! transmutability. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[derive(Copy, Clone)] + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) union Src { + pub(self) field: Zst, // <- private variant + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs new file mode 100644 index 000000000..9c8345a8e --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs @@ -0,0 +1,37 @@ +//! The presence of an unreachable field in the source type (e.g., a public +//! field with a private type does not affect transmutability. (This rule is +//! distinct from type privacy, which still may forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; // <- unreachable type + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, //~ ERROR private type + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr new file mode 100644 index 000000000..39b73302e --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `src::Zst` in public interface + --> $DIR/should_accept_if_src_has_unreachable_field.rs:22:9 + | +LL | #[repr(C)] pub(self) struct Zst; // <- unreachable type + | -------------------- `src::Zst` declared as private +... +LL | pub(in super) field: Zst, + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs new file mode 100644 index 000000000..acf9f2302 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs @@ -0,0 +1,38 @@ +//! The presence of an unreachable source type (i.e., the source type is +//! private) does not affect transmutability. (This rule is distinct from type +//! privacy, which still may forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + // unreachable type + #[repr(C)] pub(self) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); //~ ERROR `Src` is private +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr new file mode 100644 index 000000000..76dc7f340 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr @@ -0,0 +1,15 @@ +error[E0603]: struct `Src` is private + --> $DIR/should_accept_if_src_has_unreachable_ty.rs:37:36 + | +LL | assert::is_transmutable::(); + | ^^^ private struct + | +note: the struct `Src` is defined here + --> $DIR/should_accept_if_src_has_unreachable_ty.rs:22:16 + | +LL | #[repr(C)] pub(self) struct Src { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs new file mode 100644 index 000000000..e8c3fbc9a --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs @@ -0,0 +1,36 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains a private field. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(self) field: Zst, // <- private field + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr new file mode 100644 index 000000000..d5d6d431b --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_private_field.rs:35:41 + | +LL | assert::is_transmutable::(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_private_field.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs new file mode 100644 index 000000000..47bca27ab --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs @@ -0,0 +1,37 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains a private variant. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[derive(Copy, Clone)] + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) union Dst { + pub(self) field: Zst, // <- private variant + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr new file mode 100644 index 000000000..a1ca2ced5 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_private_variant.rs:36:41 + | +LL | assert::is_transmutable::(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_private_variant.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs new file mode 100644 index 000000000..662c32af1 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs @@ -0,0 +1,51 @@ +// check-pass +//! NOTE: This test documents a known-bug in the implementation of the +//! transmutability trait. Once fixed, the above "check-pass" header should be +//! removed, and an "ERROR cannot be safely transmuted" annotation should be added at the end +//! of the line starting with `assert::is_transmutable`. +//! +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) +//! +//! This test exercises a tricky-to-implement instance of this principle: the +//! "pub-in-priv trick". In the below example, the type `dst::private::Zst` is +//! unreachable from `Context`. Consequently, the transmute from `Src` to `Dst` +//! SHOULD be rejected. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + mod private { + #[repr(C)] pub struct Zst; // <- unreachable type + } + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: private::Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs new file mode 100644 index 000000000..d7e21676f --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs @@ -0,0 +1,38 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(self) struct Zst; // <- unreachable type + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr new file mode 100644 index 000000000..4e648664d --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_unreachable_field.rs:37:41 + | +LL | assert::is_transmutable::(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_unreachable_field.rs:15:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs new file mode 100644 index 000000000..c7b59f15b --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs @@ -0,0 +1,41 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + // unreachable type + #[repr(C)] pub(self) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::(); + //~^ ERROR `Dst` is private + //~| ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr new file mode 100644 index 000000000..bd72d64cc --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr @@ -0,0 +1,32 @@ +error[E0603]: struct `Dst` is private + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:46 + | +LL | assert::is_transmutable::(); + | ^^^ private struct + | +note: the struct `Dst` is defined here + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:31:16 + | +LL | #[repr(C)] pub(self) struct Dst { + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:41 + | +LL | assert::is_transmutable::(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:15:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0603. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/transmute-equal-assoc-types.rs b/tests/ui/transmute-equal-assoc-types.rs new file mode 100644 index 000000000..d1b593b7f --- /dev/null +++ b/tests/ui/transmute-equal-assoc-types.rs @@ -0,0 +1,11 @@ +// check-pass + +trait Foo { + type Bar; +} + +unsafe fn noop(foo: F::Bar) -> F::Bar { + ::std::mem::transmute(foo) +} + +fn main() {} diff --git a/tests/ui/transmute-non-immediate-to-immediate.rs b/tests/ui/transmute-non-immediate-to-immediate.rs new file mode 100644 index 000000000..cf77c113f --- /dev/null +++ b/tests/ui/transmute-non-immediate-to-immediate.rs @@ -0,0 +1,11 @@ +// run-pass +// Issue #7988 +// Transmuting non-immediate type to immediate type + +// pretty-expanded FIXME #23616 + +pub fn main() { + unsafe { + ::std::mem::transmute::<[isize; 1],isize>([1]) + }; +} diff --git a/tests/ui/transmute/lifetimes.rs b/tests/ui/transmute/lifetimes.rs new file mode 100644 index 000000000..943191551 --- /dev/null +++ b/tests/ui/transmute/lifetimes.rs @@ -0,0 +1,23 @@ +// check-pass + +use std::ptr::NonNull; + +struct Foo<'a, T: ?Sized>(&'a (), NonNull); + +fn foo<'a, 'b, T: ?Sized>(x: Foo<'a, T>) -> Foo<'b, T> { + unsafe { std::mem::transmute(x) } +} + +struct Bar<'a, T: ?Sized>(&'a T); + +fn bar<'a, 'b, T: ?Sized>(x: Bar<'a, T>) -> Bar<'b, T> { + unsafe { std::mem::transmute(x) } +} + +struct Boo<'a, T: ?Sized>(&'a T, u32); + +fn boo<'a, 'b, T: ?Sized>(x: Boo<'a, T>) -> Boo<'b, T> { + unsafe { std::mem::transmute(x) } +} + +fn main() {} diff --git a/tests/ui/transmute/main.rs b/tests/ui/transmute/main.rs new file mode 100644 index 000000000..da4a0a660 --- /dev/null +++ b/tests/ui/transmute/main.rs @@ -0,0 +1,29 @@ +// normalize-stderr-32bit: "`&str` \(64 bits\)" -> "`&str` ($$STR bits)" +// normalize-stderr-64bit: "`&str` \(128 bits\)" -> "`&str` ($$STR bits)" + +use std::mem::transmute; + +pub trait TypeConstructor<'a> { + type T; +} + +unsafe fn transmute_lifetime<'a, 'b, C>(x: >::T) + -> >::T +where for<'z> C: TypeConstructor<'z> { + transmute(x) +} + +unsafe fn sizes() { + let x: u8 = transmute(10u16); //~ ERROR cannot transmute between types of different sizes +} + +unsafe fn ptrs() { + let x: u8 = transmute("test"); //~ ERROR cannot transmute between types of different sizes +} + +union Foo { x: () } +unsafe fn vary() { + let x: Foo = transmute(10); //~ ERROR cannot transmute between types of different sizes +} + +fn main() {} diff --git a/tests/ui/transmute/main.stderr b/tests/ui/transmute/main.stderr new file mode 100644 index 000000000..6cb0d7f67 --- /dev/null +++ b/tests/ui/transmute/main.stderr @@ -0,0 +1,30 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/main.rs:17:17 + | +LL | let x: u8 = transmute(10u16); + | ^^^^^^^^^ + | + = note: source type: `u16` (16 bits) + = note: target type: `u8` (8 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/main.rs:21:17 + | +LL | let x: u8 = transmute("test"); + | ^^^^^^^^^ + | + = note: source type: `&str` ($STR bits) + = note: target type: `u8` (8 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/main.rs:26:18 + | +LL | let x: Foo = transmute(10); + | ^^^^^^^^^ + | + = note: source type: `i32` (32 bits) + = note: target type: `Foo` (0 bits) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute/transmute-different-sizes.rs b/tests/ui/transmute/transmute-different-sizes.rs new file mode 100644 index 000000000..690decf63 --- /dev/null +++ b/tests/ui/transmute/transmute-different-sizes.rs @@ -0,0 +1,31 @@ +// normalize-stderr-test "\d+ bits" -> "N bits" + +// Tests that `transmute` cannot be called on types of different size. + +#![allow(warnings)] +#![feature(specialization)] + +use std::mem::transmute; + +unsafe fn f() { + let _: i8 = transmute(16i16); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +unsafe fn g(x: &T) { + let _: i8 = transmute(x); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +trait Specializable { type Output; } + +impl Specializable for T { + default type Output = u16; +} + +unsafe fn specializable(x: u16) -> ::Output { + transmute(x) + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +fn main() {} diff --git a/tests/ui/transmute/transmute-different-sizes.stderr b/tests/ui/transmute/transmute-different-sizes.stderr new file mode 100644 index 000000000..07a38df69 --- /dev/null +++ b/tests/ui/transmute/transmute-different-sizes.stderr @@ -0,0 +1,30 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-different-sizes.rs:11:17 + | +LL | let _: i8 = transmute(16i16); + | ^^^^^^^^^ + | + = note: source type: `i16` (N bits) + = note: target type: `i8` (N bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-different-sizes.rs:16:17 + | +LL | let _: i8 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `&T` (N bits) + = note: target type: `i8` (N bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-different-sizes.rs:27:5 + | +LL | transmute(x) + | ^^^^^^^^^ + | + = note: source type: `u16` (N bits) + = note: target type: `::Output` (this type does not have a fixed size) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute/transmute-fat-pointers.rs b/tests/ui/transmute/transmute-fat-pointers.rs new file mode 100644 index 000000000..7c1beffd1 --- /dev/null +++ b/tests/ui/transmute/transmute-fat-pointers.rs @@ -0,0 +1,33 @@ +// normalize-stderr-test "\d+ bits" -> "N bits" + +// Tests that are conservative around thin/fat pointer mismatches. + +#![allow(dead_code)] + +use std::mem::transmute; + +fn a(x: &[T]) -> &U { + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes +} + +fn b(x: &T) -> &U { + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes +} + +fn c(x: &T) -> &U { + unsafe { transmute(x) } +} + +fn d(x: &[T]) -> &[U] { + unsafe { transmute(x) } +} + +fn e(x: &T) -> &U { + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes +} + +fn f(x: &T) -> &U { + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes +} + +fn main() { } diff --git a/tests/ui/transmute/transmute-fat-pointers.stderr b/tests/ui/transmute/transmute-fat-pointers.stderr new file mode 100644 index 000000000..e8335fcbe --- /dev/null +++ b/tests/ui/transmute/transmute-fat-pointers.stderr @@ -0,0 +1,39 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fat-pointers.rs:10:14 + | +LL | unsafe { transmute(x) } + | ^^^^^^^^^ + | + = note: source type: `&[T]` (N bits) + = note: target type: `&U` (pointer to `U`) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fat-pointers.rs:14:14 + | +LL | unsafe { transmute(x) } + | ^^^^^^^^^ + | + = note: source type: `&T` (pointer to `T`) + = note: target type: `&U` (pointer to `U`) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fat-pointers.rs:26:14 + | +LL | unsafe { transmute(x) } + | ^^^^^^^^^ + | + = note: source type: `&T` (pointer to `T`) + = note: target type: `&U` (N bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fat-pointers.rs:30:14 + | +LL | unsafe { transmute(x) } + | ^^^^^^^^^ + | + = note: source type: `&T` (N bits) + = note: target type: `&U` (pointer to `U`) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute/transmute-from-fn-item-types-error.rs b/tests/ui/transmute/transmute-from-fn-item-types-error.rs new file mode 100644 index 000000000..f858a199e --- /dev/null +++ b/tests/ui/transmute/transmute-from-fn-item-types-error.rs @@ -0,0 +1,60 @@ +use std::mem; + +unsafe fn foo() -> (i8, *const (), Option) { + let i = mem::transmute(bar); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types + + + let p = mem::transmute(foo); + //~^ ERROR can't transmute zero-sized type + + + let of = mem::transmute(main); + //~^ ERROR can't transmute zero-sized type + + + (i, p, of) +} + +unsafe fn bar() { + // Error as usual if the resulting type is not pointer-sized. + mem::transmute::<_, u8>(main); + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types + + + mem::transmute::<_, *mut ()>(foo); + //~^ ERROR can't transmute zero-sized type + + + mem::transmute::<_, fn()>(bar); + //~^ ERROR can't transmute zero-sized type + + + // No error if a coercion would otherwise occur. + mem::transmute::(main); +} + +unsafe fn baz() { + mem::transmute::<_, *mut ()>(Some(foo)); + //~^ ERROR can't transmute zero-sized type + + + mem::transmute::<_, fn()>(Some(bar)); + //~^ ERROR can't transmute zero-sized type + + + mem::transmute::<_, Option>(Some(baz)); + //~^ ERROR can't transmute zero-sized type + + + // No error if a coercion would otherwise occur. + mem::transmute::, usize>(Some(main)); +} + +fn main() { + unsafe { + foo(); + bar(); + baz(); + } +} diff --git a/tests/ui/transmute/transmute-from-fn-item-types-error.stderr b/tests/ui/transmute/transmute-from-fn-item-types-error.stderr new file mode 100644 index 000000000..aefe3fb8e --- /dev/null +++ b/tests/ui/transmute/transmute-from-fn-item-types-error.stderr @@ -0,0 +1,92 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-from-fn-item-types-error.rs:4:13 + | +LL | let i = mem::transmute(bar); + | ^^^^^^^^^^^^^^ + | + = note: source type: `unsafe fn() {bar}` (0 bits) + = note: target type: `i8` (8 bits) + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:8:13 + | +LL | let p = mem::transmute(foo); + | ^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() -> (i8, *const (), Option) {foo} + = note: target type: *const () + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:12:14 + | +LL | let of = mem::transmute(main); + | ^^^^^^^^^^^^^^ + | + = note: source type: fn() {main} + = note: target type: Option + = help: cast with `as` to a pointer instead + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-from-fn-item-types-error.rs:21:5 + | +LL | mem::transmute::<_, u8>(main); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `fn() {main}` (0 bits) + = note: target type: `u8` (8 bits) + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:25:5 + | +LL | mem::transmute::<_, *mut ()>(foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() -> (i8, *const (), Option) {foo} + = note: target type: *mut () + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:29:5 + | +LL | mem::transmute::<_, fn()>(bar); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {bar} + = note: target type: fn() + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:38:5 + | +LL | mem::transmute::<_, *mut ()>(Some(foo)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() -> (i8, *const (), Option) {foo} + = note: target type: *mut () + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:42:5 + | +LL | mem::transmute::<_, fn()>(Some(bar)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {bar} + = note: target type: fn() + = help: cast with `as` to a pointer instead + +error[E0591]: can't transmute zero-sized type + --> $DIR/transmute-from-fn-item-types-error.rs:46:5 + | +LL | mem::transmute::<_, Option>(Some(baz)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: unsafe fn() {baz} + = note: target type: Option + = help: cast with `as` to a pointer instead + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0512, E0591. +For more information about an error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute/transmute-impl.rs b/tests/ui/transmute/transmute-impl.rs new file mode 100644 index 000000000..df422bda1 --- /dev/null +++ b/tests/ui/transmute/transmute-impl.rs @@ -0,0 +1,25 @@ +// normalize-stderr-test "\d+ bits" -> "N bits" + +// Tests that are conservative around thin/fat pointer mismatches. + +#![allow(dead_code)] + +use std::mem::transmute; + +struct Foo { + t: Box +} + +impl Foo { + fn m(x: &T) -> &isize where T : Sized { + // OK here, because T : Sized is in scope. + unsafe { transmute(x) } + } + + fn n(x: &T) -> &isize { + // Not OK here, because T : Sized is not in scope. + unsafe { transmute(x) } //~ ERROR cannot transmute between types of different sizes + } +} + +fn main() { } diff --git a/tests/ui/transmute/transmute-impl.stderr b/tests/ui/transmute/transmute-impl.stderr new file mode 100644 index 000000000..dd19bcd54 --- /dev/null +++ b/tests/ui/transmute/transmute-impl.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-impl.rs:21:18 + | +LL | unsafe { transmute(x) } + | ^^^^^^^^^ + | + = note: source type: `&T` (pointer to `T`) + = note: target type: `&isize` (N bits) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/transmute/transmute-imut-to-mut.rs b/tests/ui/transmute/transmute-imut-to-mut.rs new file mode 100644 index 000000000..9f3f76c1e --- /dev/null +++ b/tests/ui/transmute/transmute-imut-to-mut.rs @@ -0,0 +1,8 @@ +// Tests that transmuting from &T to &mut T is Undefined Behavior. + +use std::mem::transmute; + +fn main() { + let _a: &mut u8 = unsafe { transmute(&1u8) }; + //~^ ERROR transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell +} diff --git a/tests/ui/transmute/transmute-imut-to-mut.stderr b/tests/ui/transmute/transmute-imut-to-mut.stderr new file mode 100644 index 000000000..1e9dff3ce --- /dev/null +++ b/tests/ui/transmute/transmute-imut-to-mut.stderr @@ -0,0 +1,10 @@ +error: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell + --> $DIR/transmute-imut-to-mut.rs:6:32 + | +LL | let _a: &mut u8 = unsafe { transmute(&1u8) }; + | ^^^^^^^^^ + | + = note: `#[deny(mutable_transmutes)]` on by default + +error: aborting due to previous error + diff --git a/tests/ui/transmute/transmute-padding-ice.rs b/tests/ui/transmute/transmute-padding-ice.rs new file mode 100644 index 000000000..a1be7075a --- /dev/null +++ b/tests/ui/transmute/transmute-padding-ice.rs @@ -0,0 +1,29 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, + >, + { + } +} + +fn test() { + #[repr(C, align(2))] + struct A(u8, u8); + + #[repr(C)] + struct B(u8, u8); + + assert::is_maybe_transmutable::(); + //~^ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmute/transmute-padding-ice.stderr b/tests/ui/transmute/transmute-padding-ice.stderr new file mode 100644 index 000000000..c9233890f --- /dev/null +++ b/tests/ui/transmute/transmute-padding-ice.stderr @@ -0,0 +1,24 @@ +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/transmute-padding-ice.rs:27:40 + | +LL | assert::is_maybe_transmutable::(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom` is not implemented for `A` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/transmute-padding-ice.rs:11:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom< + | ______________^ +LL | | Src, +LL | | Context, +LL | | { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, +LL | | >, + | |_________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmute/transmute-type-parameters.rs b/tests/ui/transmute/transmute-type-parameters.rs new file mode 100644 index 000000000..5f44b2d0f --- /dev/null +++ b/tests/ui/transmute/transmute-type-parameters.rs @@ -0,0 +1,44 @@ +// Tests that `transmute` cannot be called on type parameters. + +use std::mem::transmute; + +unsafe fn f(x: T) { + let _: i32 = transmute(x); +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +unsafe fn g(x: (T, i32)) { + let _: i32 = transmute(x); +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +unsafe fn h(x: [T; 10]) { + let _: i32 = transmute(x); +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +struct Bad { + f: T, +} + +unsafe fn i(x: Bad) { + let _: i32 = transmute(x); +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +enum Worse { + A(T), + B, +} + +unsafe fn j(x: Worse) { + let _: i32 = transmute(x); +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +unsafe fn k(x: Option) { + let _: i32 = transmute(x); +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types +} + +fn main() {} diff --git a/tests/ui/transmute/transmute-type-parameters.stderr b/tests/ui/transmute/transmute-type-parameters.stderr new file mode 100644 index 000000000..220b929d4 --- /dev/null +++ b/tests/ui/transmute/transmute-type-parameters.stderr @@ -0,0 +1,57 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-type-parameters.rs:6:18 + | +LL | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `i32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-type-parameters.rs:11:18 + | +LL | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `(T, i32)` (size can vary because of T) + = note: target type: `i32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-type-parameters.rs:16:18 + | +LL | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `[T; 10]` (size can vary because of T) + = note: target type: `i32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-type-parameters.rs:25:18 + | +LL | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `Bad` (size can vary because of T) + = note: target type: `i32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-type-parameters.rs:35:18 + | +LL | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `Worse` (size can vary because of T) + = note: target type: `i32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-type-parameters.rs:40:18 + | +LL | let _: i32 = transmute(x); + | ^^^^^^^^^ + | + = note: source type: `Option` (size can vary because of T) + = note: target type: `i32` (32 bits) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/treat-err-as-bug/delay_span_bug.rs b/tests/ui/treat-err-as-bug/delay_span_bug.rs new file mode 100644 index 000000000..832afddf8 --- /dev/null +++ b/tests/ui/treat-err-as-bug/delay_span_bug.rs @@ -0,0 +1,12 @@ +// compile-flags: -Ztreat-err-as-bug +// failure-status: 101 +// error-pattern: aborting due to `-Z treat-err-as-bug=1` +// error-pattern: [trigger_delay_span_bug] triggering a delay span bug +// normalize-stderr-test "note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// rustc-env:RUST_BACKTRACE=0 + +#![feature(rustc_attrs)] + +#[rustc_error(delay_span_bug_from_inside_query)] +fn main() {} diff --git a/tests/ui/treat-err-as-bug/delay_span_bug.stderr b/tests/ui/treat-err-as-bug/delay_span_bug.stderr new file mode 100644 index 000000000..e9457c8fa --- /dev/null +++ b/tests/ui/treat-err-as-bug/delay_span_bug.stderr @@ -0,0 +1,11 @@ +error: internal compiler error: delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)] + --> $DIR/delay_span_bug.rs:12:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: internal compiler error: unexpected panic + +query stack during panic: +#0 [trigger_delay_span_bug] triggering a delay span bug +end of query stack diff --git a/tests/ui/treat-err-as-bug/err.rs b/tests/ui/treat-err-as-bug/err.rs new file mode 100644 index 000000000..de3e9ed6c --- /dev/null +++ b/tests/ui/treat-err-as-bug/err.rs @@ -0,0 +1,12 @@ +// compile-flags: -Ztreat-err-as-bug +// failure-status: 101 +// error-pattern: aborting due to `-Z treat-err-as-bug=1` +// error-pattern: [eval_to_allocation_raw] const-evaluating + checking `C` +// normalize-stderr-test "note: .*\n\n" -> "" +// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" +// rustc-env:RUST_BACKTRACE=0 + +#![crate_type = "rlib"] + +pub static C: u32 = 0 - 1; +//~^ ERROR could not evaluate static initializer diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr new file mode 100644 index 000000000..8f67571c2 --- /dev/null +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -0,0 +1,12 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/err.rs:11:21 + | +LL | pub static C: u32 = 0 - 1; + | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow + +error: internal compiler error: unexpected panic + +query stack during panic: +#0 [eval_to_allocation_raw] const-evaluating + checking `C` +#1 [eval_to_allocation_raw] const-evaluating + checking `C` +end of query stack diff --git a/tests/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr b/tests/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr new file mode 100644 index 000000000..40829f537 --- /dev/null +++ b/tests/ui/trivial-bounds/issue-73021-impossible-inline.inline.stderr @@ -0,0 +1,46 @@ +warning: trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:20:29 + | +LL | for<'any> &'any mut (): Clone, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:28:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:31:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:40:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:48:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:57:13 + | +LL | String: ::std::ops::Neg, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:65:10 + | +LL | i32: Iterator, + | ^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/tests/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr b/tests/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr new file mode 100644 index 000000000..40829f537 --- /dev/null +++ b/tests/ui/trivial-bounds/issue-73021-impossible-inline.no-opt.stderr @@ -0,0 +1,46 @@ +warning: trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:20:29 + | +LL | for<'any> &'any mut (): Clone, + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:28:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:31:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:40:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:48:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:57:13 + | +LL | String: ::std::ops::Neg, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/issue-73021-impossible-inline.rs:65:10 + | +LL | i32: Iterator, + | ^^^^^^^^ + +warning: 7 warnings emitted + diff --git a/tests/ui/trivial-bounds/issue-73021-impossible-inline.rs b/tests/ui/trivial-bounds/issue-73021-impossible-inline.rs new file mode 100644 index 000000000..ab6677e91 --- /dev/null +++ b/tests/ui/trivial-bounds/issue-73021-impossible-inline.rs @@ -0,0 +1,71 @@ +// build-pass +// revisions: no-opt inline +// [inline]compile-flags: -Zmir-opt-level=3 --emit=mir +#![feature(trivial_bounds)] +#![allow(unused)] + +trait Foo { + fn test(&self); +} + +fn foo<'a>(s: &'a mut ()) +where + &'a mut (): Foo, +{ + s.test(); +} + +fn clone(it: &mut ()) -> &mut () +where + for<'any> &'any mut (): Clone, + //~^ WARN trait bound for<'any> &'any mut (): Clone does not depend on any type or lifetime parameters +{ + it.clone() +} + +fn generic_function(x: X) {} + +struct S where i32: Foo; +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + +impl Foo for () where i32: Foo { +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + fn test(&self) { + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); + } +} + +fn f() where i32: Foo { +//~^ WARN trait bound i32: Foo does not depend on any type or lifetime parameters + let s = S; + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn g() where &'static str: Foo { +//~^ WARN trait bound &'static str: Foo does not depend on any type or lifetime parameters + "Foo".test(); + Foo::test(&"Foo"); + generic_function("Foo"); +} + +fn use_op(s: String) -> String +where + String: ::std::ops::Neg, +//~^ WARN trait bound String: Neg does not depend on any type or lifetime parameters +{ + -s +} + +fn use_for() +where + i32: Iterator, +//~^ WARN trait bound i32: Iterator does not depend on any type or lifetime parameters +{ + for _ in 2i32 {} +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs new file mode 100644 index 000000000..69eee66e6 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-associated-functions.rs @@ -0,0 +1,23 @@ +// check-pass +// compile-flags: --emit=mir,link +// Force mir to be emitted, to ensure that const +// propagation doesn't ICE on a function +// with an 'impossible' body. See issue #67696 +// Inconsistent bounds with trait implementations + +#![feature(trivial_bounds)] +#![allow(unused)] + +trait A { + fn foo(&self) -> Self where Self: Copy; +} + +impl A for str { + fn foo(&self) -> Self where Self: Copy { *"" } +} + +impl A for i32 { + fn foo(&self) -> Self { 3 } +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs new file mode 100644 index 000000000..b1ff23fd0 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.rs @@ -0,0 +1,13 @@ +// Check that reborrows are still illegal with Copy mutable references +#![feature(trivial_bounds)] +#![allow(unused)] + +fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + *t //~ ERROR +} + +fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + {*t} //~ ERROR +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr new file mode 100644 index 000000000..39b60c311 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr @@ -0,0 +1,25 @@ +error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference + --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:6:5 + | +LL | *t + | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn reborrow_mut<'a>(t: &'a mut &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | ~~~~~~~~~~~~~~~~~~~ + +error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference + --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:10:6 + | +LL | {*t} + | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn copy_reborrow_mut<'a>(t: &'a mut &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | ~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs new file mode 100644 index 000000000..3416503b8 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs @@ -0,0 +1,33 @@ +// check-pass +// Check tautalogically false `Copy` bounds +#![feature(trivial_bounds)] + +fn copy_string(t: String) -> String where String: Copy { //~ WARNING trivial_bounds + is_copy(&t); + let x = t; + drop(t); + t +} + +fn copy_out_string(t: &String) -> String where String: Copy { //~ WARNING trivial_bounds + *t +} + +fn copy_string_with_param(x: String) where String: Copy { //~ WARNING trivial_bounds + let y = x; + let z = x; +} + +// Check that no reborrowing occurs +fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy { + //~^ WARNING trivial_bounds + is_copy(t); + let x = *t; + drop(x); + x +} + +fn is_copy(t: &T) {} + + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr new file mode 100644 index 000000000..1e2662389 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.stderr @@ -0,0 +1,28 @@ +warning: trait bound String: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:5:51 + | +LL | fn copy_string(t: String) -> String where String: Copy { + | ^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound String: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:12:56 + | +LL | fn copy_out_string(t: &String) -> String where String: Copy { + | ^^^^ + +warning: trait bound String: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:16:55 + | +LL | fn copy_string_with_param(x: String) where String: Copy { + | ^^^^ + +warning: trait bound for<'b> &'b mut i32: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-copy.rs:22:76 + | +LL | fn copy_mut<'a>(t: &&'a mut i32) -> &'a mut i32 where for<'b> &'b mut i32: Copy { + | ^^^^ + +warning: 4 warnings emitted + diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs new file mode 100644 index 000000000..e0f299630 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.rs @@ -0,0 +1,23 @@ +#![feature(trivial_bounds)] +#![allow(unused)] + +struct B; + +trait A { + type X; + fn get_x() -> Self::X; +} + +impl A for B { + type X = u8; + fn get_x() -> u8 { 0 } +} + +fn global_bound_is_hidden() -> u8 +where + B: A +{ + B::get_x() //~ ERROR +} + +fn main () {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr new file mode 100644 index 000000000..26679e713 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/trivial-bounds-inconsistent-projection-error.rs:20:5 + | +LL | fn global_bound_is_hidden() -> u8 + | -- expected `u8` because of return type +... +LL | B::get_x() + | ^^^^^^^^^^ expected `u8`, found `i32` + | +help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit + | +LL | B::get_x().try_into().unwrap() + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs new file mode 100644 index 000000000..b13956673 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.rs @@ -0,0 +1,58 @@ +// run-pass +// Check that global bounds result in the expected choice of associated type + +#![feature(trivial_bounds)] +#![allow(unused)] + +struct B; + +trait A { + type X; + fn get_x() -> Self::X; +} + +impl A for B { + type X = u8; + fn get_x() -> u8 { 0 } +} + +fn underspecified_bound() -> u8 +where + B: A //~ WARNING trivial_bounds +{ + B::get_x() +} + +fn inconsistent_bound() -> i32 +where + B: A //~ WARNING trivial_bounds +{ + B::get_x() +} + +fn redundant_bound() -> u8 +where + B: A //~ WARNING trivial_bounds +{ + B::get_x() +} + +fn inconsistent_dup_bound() -> i32 +where + B: A + A + //~^ WARNING trivial_bounds + //~| WARNING trivial_bounds +{ + B::get_x() +} + +fn redundant_dup_bound() -> u8 +where + B: A + A + //~^ WARNING trivial_bounds + //~| WARNING trivial_bounds +{ + B::get_x() +} + +fn main () {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr new file mode 100644 index 000000000..ddc13c512 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-projection.stderr @@ -0,0 +1,46 @@ +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:21:8 + | +LL | B: A + | ^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:28:8 + | +LL | B: A + | ^^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:35:8 + | +LL | B: A + | ^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:42:8 + | +LL | B: A + A + | ^^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:42:21 + | +LL | B: A + A + | ^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:51:8 + | +LL | B: A + A + | ^^^^^^^^^ + +warning: trait bound B: A does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-projection.rs:51:20 + | +LL | B: A + A + | ^ + +warning: 7 warnings emitted + diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs new file mode 100644 index 000000000..bfa083655 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.rs @@ -0,0 +1,27 @@ +// run-pass +// Check tautalogically false `Sized` bounds +#![feature(trivial_bounds)] +#![allow(unused)] + +trait A {} + +impl A for i32 {} + +struct T { + x: X, +} + +struct S(str, str) where str: Sized; +//~^ WARNING Sized does not depend on any type or lifetime + +fn unsized_local() where for<'a> T: Sized { + //~^ WARNING Sized does not depend on any type or lifetime + let x: T = *(Box::new(T { x: 1 }) as Box>); +} + +fn return_str() -> str where str: Sized { + //~^ WARNING Sized does not depend on any type or lifetime + *"Sized".to_string().into_boxed_str() +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr new file mode 100644 index 000000000..cf24d811c --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-sized.stderr @@ -0,0 +1,22 @@ +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-sized.rs:14:31 + | +LL | struct S(str, str) where str: Sized; + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound for<'a> T<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-sized.rs:17:49 + | +LL | fn unsized_local() where for<'a> T: Sized { + | ^^^^^ + +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-sized.rs:22:35 + | +LL | fn return_str() -> str where str: Sized { + | ^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs new file mode 100644 index 000000000..9efa22b10 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.rs @@ -0,0 +1,14 @@ +// run-pass +// Test that inconsistent bounds are used in well-formedness checks +#![feature(trivial_bounds)] + +use std::fmt::Debug; + +pub fn foo() where Vec: Debug, str: Copy { + //~^ WARNING Debug does not depend on any type or lifetime + //~| WARNING Copy does not depend on any type or lifetime + let x = vec![*"1"]; + println!("{:?}", x); +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr new file mode 100644 index 000000000..8f58a99a8 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-well-formed.stderr @@ -0,0 +1,16 @@ +warning: trait bound Vec: Debug does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:30 + | +LL | pub fn foo() where Vec: Debug, str: Copy { + | ^^^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound str: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent-well-formed.rs:7:42 + | +LL | pub fn foo() where Vec: Debug, str: Copy { + | ^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent.rs new file mode 100644 index 000000000..7148f5d6d --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent.rs @@ -0,0 +1,74 @@ +// run-pass + +// Check that tautalogically false bounds are accepted, and are used +// in type inference. +#![feature(trivial_bounds)] +#![allow(unused)] + +pub trait Foo { + fn test(&self); +} + +fn generic_function(x: X) {} + +enum E where i32: Foo { V } //~ WARNING trivial_bounds + +struct S where i32: Foo; //~ WARNING trivial_bounds + +trait T where i32: Foo {} //~ WARNING trivial_bounds + +union U where i32: Foo { f: i32 } //~ WARNING trivial_bounds + +type Y where i32: Foo = (); +//~^ WARNING type_alias_bounds +//~| WARNING trivial_bounds + +impl Foo for () where i32: Foo { //~ WARNING trivial_bounds + fn test(&self) { + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); + } +} + +fn f() where i32: Foo { //~ WARNING trivial_bounds + let s = S; + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn g() where &'static str: Foo { //~ WARNING trivial_bounds + "Foo".test(); + Foo::test(&"Foo"); + generic_function("Foo"); +} + +trait A {} + +impl A for i32 {} + +struct Dst { + x: X, +} + +struct TwoStrs(str, str) where str: Sized; //~ WARNING trivial_bounds + +fn unsized_local() where for<'a> Dst: Sized { //~ WARNING trivial_bounds + let x: Dst = *(Box::new(Dst { x: 1 }) as Box>); +} + +fn return_str() -> str where str: Sized { //~ WARNING trivial_bounds + *"Sized".to_string().into_boxed_str() +} + +fn use_op(s: String) -> String where String: ::std::ops::Neg { + //~^ WARNING trivial_bounds + -s +} + +fn use_for() where i32: Iterator { //~ WARNING trivial_bounds + for _ in 2i32 {} +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr new file mode 100644 index 000000000..d66e46887 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent.stderr @@ -0,0 +1,95 @@ +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:14:19 + | +LL | enum E where i32: Foo { V } + | ^^^ + | + = note: `#[warn(trivial_bounds)]` on by default + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:16:21 + | +LL | struct S where i32: Foo; + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:18:20 + | +LL | trait T where i32: Foo {} + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:20:20 + | +LL | union U where i32: Foo { f: i32 } + | ^^^ + +warning: where clauses are not enforced in type aliases + --> $DIR/trivial-bounds-inconsistent.rs:22:14 + | +LL | type Y where i32: Foo = (); + | ^^^^^^^^ + | + = note: `#[warn(type_alias_bounds)]` on by default +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type Y where i32: Foo = (); +LL + type Y = (); + | + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:22:19 + | +LL | type Y where i32: Foo = (); + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:26:28 + | +LL | impl Foo for () where i32: Foo { + | ^^^ + +warning: trait bound i32: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:34:19 + | +LL | fn f() where i32: Foo { + | ^^^ + +warning: trait bound &'static str: Foo does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:41:28 + | +LL | fn g() where &'static str: Foo { + | ^^^ + +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:55:37 + | +LL | struct TwoStrs(str, str) where str: Sized; + | ^^^^^ + +warning: trait bound for<'a> Dst<(dyn A + 'a)>: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:57:51 + | +LL | fn unsized_local() where for<'a> Dst: Sized { + | ^^^^^ + +warning: trait bound str: Sized does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:61:35 + | +LL | fn return_str() -> str where str: Sized { + | ^^^^^ + +warning: trait bound String: Neg does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:65:46 + | +LL | fn use_op(s: String) -> String where String: ::std::ops::Neg { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: trait bound i32: Iterator does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-inconsistent.rs:70:25 + | +LL | fn use_for() where i32: Iterator { + | ^^^^^^^^ + +warning: 14 warnings emitted + diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak-copy.rs b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.rs new file mode 100644 index 000000000..cecc0b2da --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.rs @@ -0,0 +1,12 @@ +// Check that false Copy bounds don't leak +#![feature(trivial_bounds)] + +fn copy_out_string(t: &String) -> String where String: Copy { + *t +} + +fn move_out_string(t: &String) -> String { + *t //~ ERROR +} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr new file mode 100644 index 000000000..b3ec3cd8d --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*t` which is behind a shared reference + --> $DIR/trivial-bounds-leak-copy.rs:9:5 + | +LL | *t + | ^^ move occurs because `*t` has type `String`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak.rs b/tests/ui/trivial-bounds/trivial-bounds-leak.rs new file mode 100644 index 000000000..249051d80 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-leak.rs @@ -0,0 +1,31 @@ +// Check that false bounds don't leak +#![feature(trivial_bounds)] + +pub trait Foo { + fn test(&self); +} + +fn return_str() -> str where str: Sized { + *"Sized".to_string().into_boxed_str() +} + +fn cant_return_str() -> str { //~ ERROR + *"Sized".to_string().into_boxed_str() +} + +fn my_function() where i32: Foo +{ + 3i32.test(); + Foo::test(&4i32); + generic_function(5i32); +} + +fn foo() { + 3i32.test(); //~ ERROR + Foo::test(&4i32); //~ ERROR + generic_function(5i32); //~ ERROR +} + +fn generic_function(t: T) {} + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak.stderr b/tests/ui/trivial-bounds/trivial-bounds-leak.stderr new file mode 100644 index 000000000..02c5d5d24 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -0,0 +1,48 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/trivial-bounds-leak.rs:12:25 + | +LL | fn cant_return_str() -> str { + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + +error[E0599]: no method named `test` found for type `i32` in the current scope + --> $DIR/trivial-bounds-leak.rs:24:10 + | +LL | 3i32.test(); + | ^^^^ method not found in `i32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `test`, perhaps you need to implement it + --> $DIR/trivial-bounds-leak.rs:4:1 + | +LL | pub trait Foo { + | ^^^^^^^^^^^^^ + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/trivial-bounds-leak.rs:25:15 + | +LL | Foo::test(&4i32); + | --------- ^^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call + +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/trivial-bounds-leak.rs:26:22 + | +LL | generic_function(5i32); + | ---------------- ^^^^ the trait `Foo` is not implemented for `i32` + | | + | required by a bound introduced by this call + | +note: required by a bound in `generic_function` + --> $DIR/trivial-bounds-leak.rs:29:24 + | +LL | fn generic_function(t: T) {} + | ^^^ required by this bound in `generic_function` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/trivial-bounds/trivial-bounds-lint.rs b/tests/ui/trivial-bounds/trivial-bounds-lint.rs new file mode 100644 index 000000000..078578372 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-lint.rs @@ -0,0 +1,40 @@ +#![feature(trivial_bounds)] +#![allow(unused)] +#![deny(trivial_bounds)] + +struct A where i32: Copy; //~ ERROR + +trait X {} + +trait Y: Copy {} + +trait Z { + type S: Copy; +} + +// Check only the bound the user writes trigger the lint +fn trivial_elaboration() where T: X + Z, i32: Y {} // OK + +fn global_param() where i32: X<()> {} //~ ERROR + +// Should only error on the trait bound, not the implicit +// projection bound ::S == i32. +fn global_projection() where i32: Z {} //~ ERROR + +impl A { + fn new() -> A { A } +} + +// Lifetime bounds should be linted as well +fn global_lifetimes() where i32: 'static, &'static str: 'static {} +//~^ ERROR +//~| ERROR + +fn local_lifetimes<'a>() where i32: 'a, &'a str: 'a {} // OK + +fn global_outlives() where 'static: 'static {} //~ ERROR + +// Check that each bound is checked individually +fn mixed_bounds() where i32: X + Copy {} //~ ERROR + +fn main() {} diff --git a/tests/ui/trivial-bounds/trivial-bounds-lint.stderr b/tests/ui/trivial-bounds/trivial-bounds-lint.stderr new file mode 100644 index 000000000..20e0ddfc2 --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-lint.stderr @@ -0,0 +1,50 @@ +error: trait bound i32: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:5:21 + | +LL | struct A where i32: Copy; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/trivial-bounds-lint.rs:3:9 + | +LL | #![deny(trivial_bounds)] + | ^^^^^^^^^^^^^^ + +error: trait bound i32: X<()> does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:18:30 + | +LL | fn global_param() where i32: X<()> {} + | ^^^^^ + +error: trait bound i32: Z does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:22:35 + | +LL | fn global_projection() where i32: Z {} + | ^^^^^^^^^^ + +error: lifetime bound i32: 'static does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:29:34 + | +LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} + | ^^^^^^^ + +error: lifetime bound &'static str: 'static does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:29:57 + | +LL | fn global_lifetimes() where i32: 'static, &'static str: 'static {} + | ^^^^^^^ + +error: lifetime bound 'static: 'static does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:35:37 + | +LL | fn global_outlives() where 'static: 'static {} + | ^^^^^^^ + +error: trait bound i32: Copy does not depend on any type or lifetime parameters + --> $DIR/trivial-bounds-lint.rs:38:46 + | +LL | fn mixed_bounds() where i32: X + Copy {} + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/trivial-bounds/trivial-bounds-object.rs b/tests/ui/trivial-bounds/trivial-bounds-object.rs new file mode 100644 index 000000000..f5feeea7c --- /dev/null +++ b/tests/ui/trivial-bounds/trivial-bounds-object.rs @@ -0,0 +1,18 @@ +// run-pass +// Check that the object bound dyn A + 'a: A is preferred over the +// where clause bound dyn A + 'static: A. + +#![allow(unused)] + +trait A { + fn test(&self); +} + +fn foo(x: &dyn A) +where + dyn A + 'static: A, // Using this bound would lead to a lifetime error. +{ + x.test(); +} + +fn main () {} diff --git a/tests/ui/trivial_casts-rpass.rs b/tests/ui/trivial_casts-rpass.rs new file mode 100644 index 000000000..8e49468bf --- /dev/null +++ b/tests/ui/trivial_casts-rpass.rs @@ -0,0 +1,62 @@ +// run-pass +// Test that all coercions can actually be done using casts (modulo the lints). + +#![allow(trivial_casts, trivial_numeric_casts)] + +trait Foo { + fn foo(&self) {} +} + +pub struct Bar; + +impl Foo for Bar {} + +pub fn main() { + // Numeric + let _ = 42_i32 as i32; + let _ = 42_u8 as u8; + + // & to * pointers + let x: &u32 = &42; + let _ = x as *const u32; + + let x: &mut u32 = &mut 42; + let _ = x as *mut u32; + + // unsize array + let x: &[u32; 3] = &[42, 43, 44]; + let _ = x as &[u32]; + let _ = x as *const [u32]; + + let x: &mut [u32; 3] = &mut [42, 43, 44]; + let _ = x as &mut [u32]; + let _ = x as *mut [u32]; + + let x: Box<[u32; 3]> = Box::new([42, 43, 44]); + let _ = x as Box<[u32]>; + + // unsize trait + let x: &Bar = &Bar; + let _ = x as &dyn Foo; + let _ = x as *const dyn Foo; + + let x: &mut Bar = &mut Bar; + let _ = x as &mut dyn Foo; + let _ = x as *mut dyn Foo; + + let x: Box = Box::new(Bar); + let _ = x as Box; + + // functions + fn baz(_x: i32) {} + let _ = &baz as &dyn Fn(i32); + let x = |_x: i32| {}; + let _ = &x as &dyn Fn(i32); +} + +// subtyping +pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) { + let _ = a as &'a Bar; + let _ = b as &'a Bar; + let _ = b as &'b Bar; +} diff --git a/tests/ui/try-block/issue-45124.rs b/tests/ui/try-block/issue-45124.rs new file mode 100644 index 000000000..942014c91 --- /dev/null +++ b/tests/ui/try-block/issue-45124.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unreachable_code)] +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + let mut a = 0; + let () = { + let _: Result<(), ()> = try { + let _ = Err(())?; + return + }; + a += 1; + }; + a += 2; + assert_eq!(a, 3); +} diff --git a/tests/ui/try-block/try-block-bad-lifetime.rs b/tests/ui/try-block/try-block-bad-lifetime.rs new file mode 100644 index 000000000..d9524e99f --- /dev/null +++ b/tests/ui/try-block/try-block-bad-lifetime.rs @@ -0,0 +1,37 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +#[inline(never)] +fn do_something_with(_x: T) {} + +// This test checks that borrows made and returned inside try blocks are properly constrained +pub fn main() { + { + // Test that borrows returned from a try block must be valid for the lifetime of the + // result variable + let result: Result<(), &str> = try { + let my_string = String::from(""); + let my_str: & str = & my_string; + //~^ ERROR `my_string` does not live long enough + Err(my_str) ?; + Err("") ?; + }; + do_something_with(result); + } + + { + // Test that borrows returned from try blocks freeze their referent + let mut i = 5; + let k = &mut i; + let mut j: Result<(), &mut i32> = try { + Err(k) ?; + i = 10; //~ ERROR cannot assign to `i` because it is borrowed + }; + ::std::mem::drop(k); //~ ERROR use of moved value: `k` + i = 40; //~ ERROR cannot assign to `i` because it is borrowed + + let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; + *i_ptr = 50; + } +} diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr new file mode 100644 index 000000000..ea079e30d --- /dev/null +++ b/tests/ui/try-block/try-block-bad-lifetime.stderr @@ -0,0 +1,52 @@ +error[E0597]: `my_string` does not live long enough + --> $DIR/try-block-bad-lifetime.rs:15:33 + | +LL | let result: Result<(), &str> = try { + | ------ borrow later stored here +LL | let my_string = String::from(""); +LL | let my_str: & str = & my_string; + | ^^^^^^^^^^^ borrowed value does not live long enough +... +LL | }; + | - `my_string` dropped here while still borrowed + +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-bad-lifetime.rs:29:13 + | +LL | let k = &mut i; + | ------ borrow of `i` occurs here +... +LL | i = 10; + | ^^^^^^ assignment to borrowed `i` occurs here +LL | }; +LL | ::std::mem::drop(k); + | - borrow later used here + +error[E0382]: use of moved value: `k` + --> $DIR/try-block-bad-lifetime.rs:31:26 + | +LL | let k = &mut i; + | - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait +LL | let mut j: Result<(), &mut i32> = try { +LL | Err(k) ?; + | - value moved here +... +LL | ::std::mem::drop(k); + | ^ value used here after move + +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-bad-lifetime.rs:32:9 + | +LL | let k = &mut i; + | ------ borrow of `i` occurs here +... +LL | i = 40; + | ^^^^^^ assignment to borrowed `i` occurs here +LL | +LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; + | - borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0382, E0506, E0597. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/try-block/try-block-bad-type.rs b/tests/ui/try-block/try-block-bad-type.rs new file mode 100644 index 000000000..30ae96763 --- /dev/null +++ b/tests/ui/try-block/try-block-bad-type.rs @@ -0,0 +1,21 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +pub fn main() { + let res: Result = try { + Err("")?; //~ ERROR `?` couldn't convert the error + 5 + }; + + let res: Result = try { + "" //~ ERROR type mismatch + }; + + let res: Result = try { }; //~ ERROR type mismatch + + let res: () = try { }; + //~^ ERROR a `try` block must return `Result` or `Option` + + let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option` +} diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr new file mode 100644 index 000000000..e11c3f810 --- /dev/null +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -0,0 +1,42 @@ +error[E0277]: `?` couldn't convert the error to `TryFromSliceError` + --> $DIR/try-block-bad-type.rs:7:16 + | +LL | Err("")?; + | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the trait `From` is implemented for `TryFromSliceError` + = note: required for `Result` to implement `FromResidual>` + +error[E0271]: type mismatch resolving ` as Try>::Output == &str` + --> $DIR/try-block-bad-type.rs:12:9 + | +LL | "" + | ^^ expected `i32`, found `&str` + +error[E0271]: type mismatch resolving ` as Try>::Output == ()` + --> $DIR/try-block-bad-type.rs:15:39 + | +LL | let res: Result = try { }; + | ^ expected `i32`, found `()` + +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-bad-type.rs:17:25 + | +LL | let res: () = try { }; + | ^ could not wrap the final value of the block as `()` doesn't implement `Try` + | + = help: the trait `Try` is not implemented for `()` + +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-bad-type.rs:20:26 + | +LL | let res: i32 = try { 5 }; + | ^ could not wrap the final value of the block as `i32` doesn't implement `Try` + | + = help: the trait `Try` is not implemented for `i32` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/try-block/try-block-catch.rs b/tests/ui/try-block/try-block-catch.rs new file mode 100644 index 000000000..d16501561 --- /dev/null +++ b/tests/ui/try-block/try-block-catch.rs @@ -0,0 +1,10 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + let res: Option = try { + true + } catch { }; + //~^ ERROR keyword `catch` cannot follow a `try` block +} diff --git a/tests/ui/try-block/try-block-catch.stderr b/tests/ui/try-block/try-block-catch.stderr new file mode 100644 index 000000000..39cf943f4 --- /dev/null +++ b/tests/ui/try-block/try-block-catch.stderr @@ -0,0 +1,10 @@ +error: keyword `catch` cannot follow a `try` block + --> $DIR/try-block-catch.rs:8:7 + | +LL | } catch { }; + | ^^^^^ + | + = help: try using `match` on the result of the `try` block instead + +error: aborting due to previous error + diff --git a/tests/ui/try-block/try-block-in-edition2015.rs b/tests/ui/try-block/try-block-in-edition2015.rs new file mode 100644 index 000000000..009642973 --- /dev/null +++ b/tests/ui/try-block/try-block-in-edition2015.rs @@ -0,0 +1,10 @@ +// compile-flags: --edition 2015 + +pub fn main() { + let try_result: Option<_> = try { + //~^ ERROR expected struct, variant or union type, found macro `try` + let x = 5; //~ ERROR expected identifier, found keyword + x + }; + assert_eq!(try_result, Some(5)); +} diff --git a/tests/ui/try-block/try-block-in-edition2015.stderr b/tests/ui/try-block/try-block-in-edition2015.stderr new file mode 100644 index 000000000..a00064c44 --- /dev/null +++ b/tests/ui/try-block/try-block-in-edition2015.stderr @@ -0,0 +1,24 @@ +error: expected identifier, found keyword `let` + --> $DIR/try-block-in-edition2015.rs:6:9 + | +LL | let try_result: Option<_> = try { + | --- while parsing this struct +LL | +LL | let x = 5; + | ^^^ expected identifier, found keyword + +error[E0574]: expected struct, variant or union type, found macro `try` + --> $DIR/try-block-in-edition2015.rs:4:33 + | +LL | let try_result: Option<_> = try { + | ^^^ not a struct, variant or union type + | + = note: if you want the `try` keyword, you need Rust 2018 or later +help: use `!` to invoke the macro + | +LL | let try_result: Option<_> = try! { + | + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/try-block/try-block-in-match.rs b/tests/ui/try-block/try-block-in-match.rs new file mode 100644 index 000000000..cd0b967e7 --- /dev/null +++ b/tests/ui/try-block/try-block-in-match.rs @@ -0,0 +1,11 @@ +// run-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + match try { } { + Err(()) => (), + Ok(()) => (), + } +} diff --git a/tests/ui/try-block/try-block-in-return.rs b/tests/ui/try-block/try-block-in-return.rs new file mode 100644 index 000000000..a15bfeef1 --- /dev/null +++ b/tests/ui/try-block/try-block-in-return.rs @@ -0,0 +1,12 @@ +// run-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn issue_76271() -> Option { + return try { 4 } +} + +fn main() { + assert_eq!(issue_76271(), Some(4)); +} diff --git a/tests/ui/try-block/try-block-in-while.rs b/tests/ui/try-block/try-block-in-while.rs new file mode 100644 index 000000000..69793df52 --- /dev/null +++ b/tests/ui/try-block/try-block-in-while.rs @@ -0,0 +1,8 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + while try { false } {} + //~^ ERROR a `try` block must +} diff --git a/tests/ui/try-block/try-block-in-while.stderr b/tests/ui/try-block/try-block-in-while.stderr new file mode 100644 index 000000000..62cc26dd4 --- /dev/null +++ b/tests/ui/try-block/try-block-in-while.stderr @@ -0,0 +1,11 @@ +error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`) + --> $DIR/try-block-in-while.rs:6:17 + | +LL | while try { false } {} + | ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try` + | + = help: the trait `Try` is not implemented for `bool` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs new file mode 100644 index 000000000..cd2ddf63a --- /dev/null +++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs @@ -0,0 +1,44 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +#[inline(never)] +fn do_something_with(_x: T) {} + +// This test checks that borrows made and returned inside try blocks are properly constrained +pub fn main() { + { + // Test that a borrow which *might* be returned still freezes its referent + let mut i = 222; + let x: Result<&i32, ()> = try { + Err(())?; + &i + }; + i = 0; //~ ERROR cannot assign to `i` because it is borrowed + let _ = i; + do_something_with(x); + } + + { + let x = String::new(); + let _y: Result<(), ()> = try { + Err(())?; + ::std::mem::drop(x); + }; + println!("{}", x); //~ ERROR borrow of moved value: `x` + } + + { + // Test that a borrow which *might* be assigned to an outer variable still freezes + // its referent + let mut i = 222; + let mut j = &-1; + let _x: Result<(), ()> = try { + Err(())?; + j = &i; + }; + i = 0; //~ ERROR cannot assign to `i` because it is borrowed + let _ = i; + do_something_with(j); + } +} diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr b/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr new file mode 100644 index 000000000..f738b03ee --- /dev/null +++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr @@ -0,0 +1,46 @@ +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-maybe-bad-lifetime.rs:17:9 + | +LL | &i + | -- borrow of `i` occurs here +LL | }; +LL | i = 0; + | ^^^^^ assignment to borrowed `i` occurs here +LL | let _ = i; +LL | do_something_with(x); + | - borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/try-block-maybe-bad-lifetime.rs:28:24 + | +LL | let x = String::new(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +... +LL | ::std::mem::drop(x); + | - value moved here +LL | }; +LL | println!("{}", x); + | ^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | ::std::mem::drop(x.clone()); + | ++++++++ + +error[E0506]: cannot assign to `i` because it is borrowed + --> $DIR/try-block-maybe-bad-lifetime.rs:40:9 + | +LL | j = &i; + | -- borrow of `i` occurs here +LL | }; +LL | i = 0; + | ^^^^^ assignment to borrowed `i` occurs here +LL | let _ = i; +LL | do_something_with(j); + | - borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0506. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/try-block/try-block-opt-init.rs b/tests/ui/try-block/try-block-opt-init.rs new file mode 100644 index 000000000..f4f45abcc --- /dev/null +++ b/tests/ui/try-block/try-block-opt-init.rs @@ -0,0 +1,16 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn use_val(_x: T) {} + +pub fn main() { + let cfg_res; + let _: Result<(), ()> = try { + Err(())?; + cfg_res = 5; + Ok::<(), ()>(())?; + use_val(cfg_res); + }; + assert_eq!(cfg_res, 5); //~ ERROR E0381 +} diff --git a/tests/ui/try-block/try-block-opt-init.stderr b/tests/ui/try-block/try-block-opt-init.stderr new file mode 100644 index 000000000..c39738501 --- /dev/null +++ b/tests/ui/try-block/try-block-opt-init.stderr @@ -0,0 +1,17 @@ +error[E0381]: used binding `cfg_res` is possibly-uninitialized + --> $DIR/try-block-opt-init.rs:15:5 + | +LL | let cfg_res; + | ------- binding declared here but left uninitialized +... +LL | cfg_res = 5; + | ----------- binding initialized here in some conditions +... +LL | assert_eq!(cfg_res, 5); + | ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` used here but it is possibly-uninitialized + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/try-block/try-block-type-error.rs b/tests/ui/try-block/try-block-type-error.rs new file mode 100644 index 000000000..fe1993a37 --- /dev/null +++ b/tests/ui/try-block/try-block-type-error.rs @@ -0,0 +1,18 @@ +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn foo() -> Option<()> { Some(()) } + +fn main() { + let _: Option = try { + foo()?; + 42 + //~^ ERROR type mismatch + }; + + let _: Option = try { + foo()?; + }; + //~^ ERROR type mismatch +} diff --git a/tests/ui/try-block/try-block-type-error.stderr b/tests/ui/try-block/try-block-type-error.stderr new file mode 100644 index 000000000..3e9a584a5 --- /dev/null +++ b/tests/ui/try-block/try-block-type-error.stderr @@ -0,0 +1,18 @@ +error[E0271]: type mismatch resolving ` as Try>::Output == {integer}` + --> $DIR/try-block-type-error.rs:10:9 + | +LL | 42 + | ^^ + | | + | expected `f32`, found integer + | help: use a float literal: `42.0` + +error[E0271]: type mismatch resolving ` as Try>::Output == ()` + --> $DIR/try-block-type-error.rs:16:5 + | +LL | }; + | ^ expected `i32`, found `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/try-block/try-block-unreachable-code-lint.rs b/tests/ui/try-block/try-block-unreachable-code-lint.rs new file mode 100644 index 000000000..e1d82ea36 --- /dev/null +++ b/tests/ui/try-block/try-block-unreachable-code-lint.rs @@ -0,0 +1,76 @@ +// Test unreachable_code lint for `try {}` block ok-wrapping. See issues #54165, #63324. + +// compile-flags: --edition 2018 +// check-pass +#![feature(try_blocks)] +#![warn(unreachable_code)] + +fn err() -> Result { + Err(()) +} + +// In the following cases unreachable code is autogenerated and should not be reported. + +fn test_ok_wrapped_divergent_expr_1() { + let res: Result = try { + loop { + err()?; + } + }; + println!("res: {:?}", res); +} + +fn test_ok_wrapped_divergent_expr_2() { + let _: Result = try { + return + }; +} + +fn test_autogenerated_unit_after_divergent_expr() { + let _: Result<(), ()> = try { + return; + }; +} + +// In the following cases unreachable code should be reported. + +fn test_try_block_after_divergent_stmt() { + let _: Result = { + return; + + try { + loop { + err()?; + } + } + //~^^^^^ WARNING unreachable expression + }; +} + +fn test_wrapped_divergent_expr() { + let _: Result = { + Err(return) + //~^ WARNING unreachable call + }; +} + +fn test_expr_after_divergent_stmt_in_try_block() { + let res: Result = try { + loop { + err()?; + } + + 42 + //~^ WARNING unreachable expression + }; + println!("res: {:?}", res); +} + +fn main() { + test_ok_wrapped_divergent_expr_1(); + test_ok_wrapped_divergent_expr_2(); + test_autogenerated_unit_after_divergent_expr(); + test_try_block_after_divergent_stmt(); + test_wrapped_divergent_expr(); + test_expr_after_divergent_stmt_in_try_block(); +} diff --git a/tests/ui/try-block/try-block-unreachable-code-lint.stderr b/tests/ui/try-block/try-block-unreachable-code-lint.stderr new file mode 100644 index 000000000..9fc0b661f --- /dev/null +++ b/tests/ui/try-block/try-block-unreachable-code-lint.stderr @@ -0,0 +1,40 @@ +warning: unreachable expression + --> $DIR/try-block-unreachable-code-lint.rs:41:9 + | +LL | return; + | ------ any code following this expression is unreachable +LL | +LL | / try { +LL | | loop { +LL | | err()?; +LL | | } +LL | | } + | |_________^ unreachable expression + | +note: the lint level is defined here + --> $DIR/try-block-unreachable-code-lint.rs:6:9 + | +LL | #![warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +warning: unreachable call + --> $DIR/try-block-unreachable-code-lint.rs:52:9 + | +LL | Err(return) + | ^^^ ------ any code following this expression is unreachable + | | + | unreachable call + +warning: unreachable expression + --> $DIR/try-block-unreachable-code-lint.rs:63:9 + | +LL | / loop { +LL | | err()?; +LL | | } + | |_________- any code following this expression is unreachable +LL | +LL | 42 + | ^^ unreachable expression + +warning: 3 warnings emitted + diff --git a/tests/ui/try-block/try-block-unused-delims.fixed b/tests/ui/try-block/try-block-unused-delims.fixed new file mode 100644 index 000000000..756081738 --- /dev/null +++ b/tests/ui/try-block/try-block-unused-delims.fixed @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: --edition 2018 +// run-rustfix + +#![feature(try_blocks)] +#![warn(unused_parens, unused_braces)] + +fn consume(_: Result) -> T { todo!() } + +fn main() { + consume(try {}); + //~^ WARN unnecessary parentheses + + consume(try {}); + //~^ WARN unnecessary braces + + match try {} { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } + + if let Err(()) = try {} {} + //~^ WARN unnecessary parentheses + + match try {} { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } +} diff --git a/tests/ui/try-block/try-block-unused-delims.rs b/tests/ui/try-block/try-block-unused-delims.rs new file mode 100644 index 000000000..ce087fb35 --- /dev/null +++ b/tests/ui/try-block/try-block-unused-delims.rs @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: --edition 2018 +// run-rustfix + +#![feature(try_blocks)] +#![warn(unused_parens, unused_braces)] + +fn consume(_: Result) -> T { todo!() } + +fn main() { + consume((try {})); + //~^ WARN unnecessary parentheses + + consume({ try {} }); + //~^ WARN unnecessary braces + + match (try {}) { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } + + if let Err(()) = (try {}) {} + //~^ WARN unnecessary parentheses + + match (try {}) { + //~^ WARN unnecessary parentheses + Ok(()) | Err(()) => (), + } +} diff --git a/tests/ui/try-block/try-block-unused-delims.stderr b/tests/ui/try-block/try-block-unused-delims.stderr new file mode 100644 index 000000000..765cd9c0f --- /dev/null +++ b/tests/ui/try-block/try-block-unused-delims.stderr @@ -0,0 +1,72 @@ +warning: unnecessary parentheses around function argument + --> $DIR/try-block-unused-delims.rs:11:13 + | +LL | consume((try {})); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/try-block-unused-delims.rs:6:9 + | +LL | #![warn(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - consume((try {})); +LL + consume(try {}); + | + +warning: unnecessary braces around function argument + --> $DIR/try-block-unused-delims.rs:14:13 + | +LL | consume({ try {} }); + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/try-block-unused-delims.rs:6:24 + | +LL | #![warn(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - consume({ try {} }); +LL + consume(try {}); + | + +warning: unnecessary parentheses around `match` scrutinee expression + --> $DIR/try-block-unused-delims.rs:17:11 + | +LL | match (try {}) { + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | + +warning: unnecessary parentheses around `let` scrutinee expression + --> $DIR/try-block-unused-delims.rs:22:22 + | +LL | if let Err(()) = (try {}) {} + | ^ ^ + | +help: remove these parentheses + | +LL - if let Err(()) = (try {}) {} +LL + if let Err(()) = try {} {} + | + +warning: unnecessary parentheses around `match` scrutinee expression + --> $DIR/try-block-unused-delims.rs:25:11 + | +LL | match (try {}) { + | ^ ^ + | +help: remove these parentheses + | +LL - match (try {}) { +LL + match try {} { + | + +warning: 5 warnings emitted + diff --git a/tests/ui/try-block/try-block.rs b/tests/ui/try-block/try-block.rs new file mode 100644 index 000000000..c29ccc704 --- /dev/null +++ b/tests/ui/try-block/try-block.rs @@ -0,0 +1,75 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +struct catch {} + +pub fn main() { + let catch_result: Option<_> = try { + let x = 5; + x + }; + assert_eq!(catch_result, Some(5)); + + let mut catch = true; + while catch { catch = false; } + assert_eq!(catch, false); + + catch = if catch { false } else { true }; + assert_eq!(catch, true); + + match catch { + _ => {} + }; + + let catch_err: Result<_, i32> = try { + Err(22)?; + 1 + }; + assert_eq!(catch_err, Err(22)); + + let catch_okay: Result = try { + if false { Err(25)?; } + Ok::<(), i32>(())?; + 28 + }; + assert_eq!(catch_okay, Ok(28)); + + let catch_from_loop: Result = try { + for i in 0..10 { + if i < 5 { Ok::(i)?; } else { Err(i)?; } + } + 22 + }; + assert_eq!(catch_from_loop, Err(5)); + + let cfg_init; + let _res: Result<(), ()> = try { + cfg_init = 5; + }; + assert_eq!(cfg_init, 5); + + let cfg_init_2; + let _res: Result<(), ()> = try { + cfg_init_2 = 6; + Err(())?; + }; + assert_eq!(cfg_init_2, 6); + + let my_string = "test".to_string(); + let res: Result<&str, ()> = try { + // Unfortunately, deref doesn't fire here (#49356) + &my_string[..] + }; + assert_eq!(res, Ok("test")); + + let my_opt: Option<_> = try { () }; + assert_eq!(my_opt, Some(())); + + let my_opt: Option<_> = try { }; + assert_eq!(my_opt, Some(())); +} diff --git a/tests/ui/try-block/try-is-identifier-edition2015.rs b/tests/ui/try-block/try-is-identifier-edition2015.rs new file mode 100644 index 000000000..90f56d5fa --- /dev/null +++ b/tests/ui/try-block/try-is-identifier-edition2015.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(non_camel_case_types)] +// compile-flags: --edition 2015 + +fn main() { + let try = 2; + struct try { try: u32 } + let try: try = try { try }; + assert_eq!(try.try, 2); +} diff --git a/tests/ui/try-from-int-error-partial-eq.rs b/tests/ui/try-from-int-error-partial-eq.rs new file mode 100644 index 000000000..6ee4a4cf3 --- /dev/null +++ b/tests/ui/try-from-int-error-partial-eq.rs @@ -0,0 +1,12 @@ +// run-pass + +#![allow(unused_must_use)] + +use std::convert::TryFrom; +use std::num::TryFromIntError; + +fn main() { + let x: u32 = 125; + let y: Result = u8::try_from(x); + y == Ok(125); +} diff --git a/tests/ui/try-operator-hygiene.rs b/tests/ui/try-operator-hygiene.rs new file mode 100644 index 000000000..0b24b4305 --- /dev/null +++ b/tests/ui/try-operator-hygiene.rs @@ -0,0 +1,26 @@ +// run-pass + +#![allow(non_upper_case_globals)] +#![allow(dead_code)] +// `expr?` expands to: +// +// match expr { +// Ok(val) => val, +// Err(err) => return Err(From::from(err)), +// } +// +// This test verifies that the expansion is hygienic, i.e., it's not affected by other `val` and +// `err` bindings that may be in scope. + +use std::num::ParseIntError; + +fn main() { + assert_eq!(parse(), Ok(1)); +} + +fn parse() -> Result { + const val: char = 'a'; + const err: char = 'b'; + + Ok("1".parse::()?) +} diff --git a/tests/ui/try-operator.rs b/tests/ui/try-operator.rs new file mode 100644 index 000000000..516ae4c40 --- /dev/null +++ b/tests/ui/try-operator.rs @@ -0,0 +1,192 @@ +// run-pass + +#![allow(dead_code)] + +use std::fs::File; +use std::io::{Read, self}; +use std::num::ParseIntError; +use std::str::FromStr; + +fn on_method() -> Result { + Ok("1".parse::()? + "2".parse::()?) +} + +fn in_chain() -> Result { + Ok("3".parse::()?.to_string()) +} + +fn on_call() -> Result { + fn parse(s: &str) -> Result { + s.parse() + } + + Ok(parse("4")?) +} + +fn nested() -> Result { + Ok("5".parse::()?.to_string().parse()?) +} + +fn on_path() -> Result { + let x = "6".parse::(); + + Ok(x?) +} + +fn on_macro() -> Result { + macro_rules! id { + ($e:expr) => { $e } + } + + Ok(id!("7".parse::())?) +} + +fn on_parens() -> Result { + let x = "8".parse::(); + + Ok((x)?) +} + +fn on_block() -> Result { + let x = "9".parse::(); + + Ok({x}?) +} + +fn on_field() -> Result { + struct Pair { a: A, b: B } + + let x = Pair { a: "10".parse::(), b: 0 }; + + Ok(x.a?) +} + +fn on_tuple_field() -> Result { + let x = ("11".parse::(), 0); + + Ok(x.0?) +} + +fn on_try() -> Result { + let x = "12".parse::().map(|i| i.to_string().parse::()); + + Ok(x??) +} + +fn on_binary_op() -> Result { + let x = 13 - "14".parse::()?; + let y = "15".parse::()? - 16; + let z = "17".parse::()? - "18".parse::()?; + + Ok(x + y + z) +} + +fn on_index() -> Result { + let x = [19]; + let y = "0".parse::(); + + Ok(x[y?]) +} + +fn on_args() -> Result { + fn sub(x: i32, y: i32) -> i32 { x - y } + + let x = "20".parse(); + let y = "21".parse(); + + Ok(sub(x?, y?)) +} + +fn on_if() -> Result { + Ok(if true { + "22".parse::() + } else { + "23".parse::() + }?) +} + +fn on_if_let() -> Result { + Ok(if let Ok(..) = "24".parse::() { + "25".parse::() + } else { + "26".parse::() + }?) +} + +fn on_match() -> Result { + Ok(match "27".parse::() { + Err(..) => "28".parse::(), + Ok(..) => "29".parse::(), + }?) +} + +fn tight_binding() -> Result { + fn ok(x: T) -> Result { Ok(x) } + + let x = ok(true); + Ok(!x?) +} + +// just type check +fn merge_error() -> Result { + let mut s = String::new(); + + File::open("foo.txt")?.read_to_string(&mut s)?; + + Ok(s.parse::()? + 1) +} + +fn main() { + assert_eq!(Ok(3), on_method()); + + assert_eq!(Ok("3".to_string()), in_chain()); + + assert_eq!(Ok(4), on_call()); + + assert_eq!(Ok(5), nested()); + + assert_eq!(Ok(6), on_path()); + + assert_eq!(Ok(7), on_macro()); + + assert_eq!(Ok(8), on_parens()); + + assert_eq!(Ok(9), on_block()); + + assert_eq!(Ok(10), on_field()); + + assert_eq!(Ok(11), on_tuple_field()); + + assert_eq!(Ok(12), on_try()); + + assert_eq!(Ok(-3), on_binary_op()); + + assert_eq!(Ok(19), on_index()); + + assert_eq!(Ok(-1), on_args()); + + assert_eq!(Ok(22), on_if()); + + assert_eq!(Ok(25), on_if_let()); + + assert_eq!(Ok(29), on_match()); + + assert_eq!(Ok(false), tight_binding()); +} + +enum Error { + Io(io::Error), + Parse(ParseIntError), +} + +impl From for Error { + fn from(e: io::Error) -> Error { + Error::Io(e) + } +} + +impl From for Error { + fn from(e: ParseIntError) -> Error { + Error::Parse(e) + } +} diff --git a/tests/ui/try-trait/bad-interconversion.rs b/tests/ui/try-trait/bad-interconversion.rs new file mode 100644 index 000000000..385f5510f --- /dev/null +++ b/tests/ui/try-trait/bad-interconversion.rs @@ -0,0 +1,48 @@ +#![feature(control_flow_enum)] + +use std::ops::ControlFlow; + +fn result_to_result() -> Result { + Ok(Err(123_i32)?) + //~^ ERROR `?` couldn't convert the error to `u8` +} + +fn option_to_result() -> Result { + Some(3)?; + //~^ ERROR the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + Ok(10) +} + +fn control_flow_to_result() -> Result { + Ok(ControlFlow::Break(123)?) + //~^ ERROR the `?` operator can only be used on `Result`s in a function that returns `Result` +} + +fn result_to_option() -> Option { + Some(Err("hello")?) + //~^ ERROR the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` +} + +fn control_flow_to_option() -> Option { + Some(ControlFlow::Break(123)?) + //~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option` +} + +fn result_to_control_flow() -> ControlFlow { + ControlFlow::Continue(Err("hello")?) + //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` +} + +fn option_to_control_flow() -> ControlFlow { + Some(3)?; + //~^ ERROR the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + ControlFlow::Break(10) +} + +fn control_flow_to_control_flow() -> ControlFlow { + ControlFlow::Break(4_u8)?; + //~^ ERROR the `?` operator in a function that returns `ControlFlow` can only be used on other `ControlFlow`s + ControlFlow::Continue(()) +} + +fn main() {} diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr new file mode 100644 index 000000000..a49630adb --- /dev/null +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -0,0 +1,103 @@ +error[E0277]: `?` couldn't convert the error to `u8` + --> $DIR/bad-interconversion.rs:6:20 + | +LL | fn result_to_result() -> Result { + | --------------- expected `u8` because of this +LL | Ok(Err(123_i32)?) + | ^ the trait `From` is not implemented for `u8` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = help: the following other types implement trait `From`: + > + > + = note: required for `Result` to implement `FromResidual>` + +error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + --> $DIR/bad-interconversion.rs:11:12 + | +LL | fn option_to_result() -> Result { + | -------------------------------------------- this function returns a `Result` +LL | Some(3)?; + | ^ use `.ok_or(...)?` to provide an error compatible with `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual>> + +error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` + --> $DIR/bad-interconversion.rs:17:31 + | +LL | fn control_flow_to_result() -> Result { + | -------------------------------------------------- this function returns a `Result` +LL | Ok(ControlFlow::Break(123)?) + | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual>> + +error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` + --> $DIR/bad-interconversion.rs:22:22 + | +LL | fn result_to_option() -> Option { + | ------------------------------------ this function returns an `Option` +LL | Some(Err("hello")?) + | ^ use `.ok()?` if you want to discard the `Result` error information + | + = help: the trait `FromResidual>` is not implemented for `Option` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual> + +error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` + --> $DIR/bad-interconversion.rs:27:33 + | +LL | fn control_flow_to_option() -> Option { + | ------------------------------------------ this function returns an `Option` +LL | Some(ControlFlow::Break(123)?) + | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option` + | + = help: the trait `FromResidual>` is not implemented for `Option` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual> + +error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + --> $DIR/bad-interconversion.rs:32:39 + | +LL | fn result_to_control_flow() -> ControlFlow { + | -------------------------------------------------- this function returns a `ControlFlow` +LL | ControlFlow::Continue(Err("hello")?) + | ^ this `?` produces `Result`, which is incompatible with `ControlFlow` + | + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow` + +error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` + --> $DIR/bad-interconversion.rs:37:12 + | +LL | fn option_to_control_flow() -> ControlFlow { + | ----------------------------------------------- this function returns a `ControlFlow` +LL | Some(3)?; + | ^ this `?` produces `Option`, which is incompatible with `ControlFlow` + | + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow` + +error[E0277]: the `?` operator in a function that returns `ControlFlow` can only be used on other `ControlFlow`s (with the same Break type) + --> $DIR/bad-interconversion.rs:43:29 + | +LL | fn control_flow_to_control_flow() -> ControlFlow { + | ----------------------------------------------------- this function returns a `ControlFlow` +LL | ControlFlow::Break(4_u8)?; + | ^ this `?` produces `ControlFlow`, which is incompatible with `ControlFlow` + | + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` + = help: the trait `FromResidual` is implemented for `ControlFlow` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-trait/option-to-result.rs b/tests/ui/try-trait/option-to-result.rs new file mode 100644 index 000000000..45aaf361a --- /dev/null +++ b/tests/ui/try-trait/option-to-result.rs @@ -0,0 +1,13 @@ +fn main(){ } + +fn test_result() -> Result<(),()> { + let a:Option<()> = Some(()); + a?;//~ ERROR the `?` operator can only be used + Ok(()) +} + +fn test_option() -> Option{ + let a:Result = Ok(5); + a?;//~ ERROR the `?` operator can only be used + Some(5) +} diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr new file mode 100644 index 000000000..fabc1ff2c --- /dev/null +++ b/tests/ui/try-trait/option-to-result.stderr @@ -0,0 +1,31 @@ +error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + --> $DIR/option-to-result.rs:5:6 + | +LL | fn test_result() -> Result<(),()> { + | --------------------------------- this function returns a `Result` +LL | let a:Option<()> = Some(()); +LL | a?; + | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>` + | + = help: the trait `FromResidual>` is not implemented for `Result<(), ()>` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual>> + +error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` + --> $DIR/option-to-result.rs:11:6 + | +LL | fn test_option() -> Option{ + | ------------------------------- this function returns an `Option` +LL | let a:Result = Ok(5); +LL | a?; + | ^ use `.ok()?` if you want to discard the `Result` error information + | + = help: the trait `FromResidual>` is not implemented for `Option` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-trait/try-as-monad.rs b/tests/ui/try-trait/try-as-monad.rs new file mode 100644 index 000000000..cf09838b3 --- /dev/null +++ b/tests/ui/try-trait/try-as-monad.rs @@ -0,0 +1,24 @@ +// run-pass + +#![feature(try_trait_v2)] + +use std::ops::Try; + +fn monad_unit(x: ::Output) -> T { + T::from_output(x) +} + +fn monad_bind, T2: Try, R>( + mx: T1, + f: impl FnOnce(::Output) -> T2) +-> T2 { + let x = mx?; + f(x) +} + +fn main() { + let mx: Option = monad_unit(1); + let my = monad_bind(mx, |x| Some(x + 1)); + let mz = monad_bind(my, |x| Some(-x)); + assert_eq!(mz, Some(-2)); +} diff --git a/tests/ui/try-trait/try-on-option-diagnostics.rs b/tests/ui/try-trait/try-on-option-diagnostics.rs new file mode 100644 index 000000000..7ffa0de6c --- /dev/null +++ b/tests/ui/try-trait/try-on-option-diagnostics.rs @@ -0,0 +1,47 @@ +// edition:2018 + +fn main() {} + +fn a_function() -> u32 { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 +} + +fn a_closure() -> u32 { + let a_closure = || { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 + }; + a_closure() +} + +fn a_method() -> u32 { + struct S; + + impl S { + fn a_method() { + let x: Option = None; + x?; //~ ERROR the `?` operator + } + } + + S::a_method(); + 22 +} + +fn a_trait_method() -> u32 { + struct S; + trait T { + fn a_trait_method() { + let x: Option = None; + x?; //~ ERROR the `?` operator + } + } + + impl T for S { } + + S::a_trait_method(); + 22 +} diff --git a/tests/ui/try-trait/try-on-option-diagnostics.stderr b/tests/ui/try-trait/try-on-option-diagnostics.stderr new file mode 100644 index 000000000..9ee540c79 --- /dev/null +++ b/tests/ui/try-trait/try-on-option-diagnostics.stderr @@ -0,0 +1,47 @@ +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:7:6 + | +LL | fn a_function() -> u32 { + | ---------------------- this function should return `Result` or `Option` to accept `?` +LL | let x: Option = None; +LL | x?; + | ^ cannot use the `?` operator in a function that returns `u32` + | + = help: the trait `FromResidual>` is not implemented for `u32` + +error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:14:10 + | +LL | let a_closure = || { + | -- this function should return `Result` or `Option` to accept `?` +LL | let x: Option = None; +LL | x?; + | ^ cannot use the `?` operator in a closure that returns `{integer}` + | + = help: the trait `FromResidual>` is not implemented for `{integer}` + +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:26:14 + | +LL | fn a_method() { + | ------------- this function should return `Result` or `Option` to accept `?` +LL | let x: Option = None; +LL | x?; + | ^ cannot use the `?` operator in a method that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` + +error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option-diagnostics.rs:39:14 + | +LL | fn a_trait_method() { + | ------------------- this function should return `Result` or `Option` to accept `?` +LL | let x: Option = None; +LL | x?; + | ^ cannot use the `?` operator in a trait method that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-trait/try-on-option.rs b/tests/ui/try-trait/try-on-option.rs new file mode 100644 index 000000000..8519932a6 --- /dev/null +++ b/tests/ui/try-trait/try-on-option.rs @@ -0,0 +1,13 @@ +fn main() {} + +fn foo() -> Result { + let x: Option = None; + x?; //~ ERROR the `?` operator + Ok(22) +} + +fn bar() -> u32 { + let x: Option = None; + x?; //~ ERROR the `?` operator + 22 +} diff --git a/tests/ui/try-trait/try-on-option.stderr b/tests/ui/try-trait/try-on-option.stderr new file mode 100644 index 000000000..fad6a1fe8 --- /dev/null +++ b/tests/ui/try-trait/try-on-option.stderr @@ -0,0 +1,28 @@ +error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` + --> $DIR/try-on-option.rs:5:6 + | +LL | fn foo() -> Result { + | --------------------------- this function returns a `Result` +LL | let x: Option = None; +LL | x?; + | ^ use `.ok_or(...)?` to provide an error compatible with `Result` + | + = help: the trait `FromResidual>` is not implemented for `Result` + = help: the following other types implement trait `FromResidual`: + as FromResidual>> + as FromResidual>> + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-on-option.rs:11:6 + | +LL | fn bar() -> u32 { + | --------------- this function should return `Result` or `Option` to accept `?` +LL | let x: Option = None; +LL | x?; + | ^ cannot use the `?` operator in a function that returns `u32` + | + = help: the trait `FromResidual>` is not implemented for `u32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-trait/try-operator-custom.rs b/tests/ui/try-trait/try-operator-custom.rs new file mode 100644 index 000000000..45636a7fc --- /dev/null +++ b/tests/ui/try-trait/try-operator-custom.rs @@ -0,0 +1,91 @@ +// run-pass + +#![feature(control_flow_enum)] +#![feature(try_trait_v2)] + +use std::ops::{ControlFlow, FromResidual, Try}; + +enum MyResult { + Awesome(T), + Terrible(U) +} + +enum Never {} + +impl Try for MyResult { + type Output = U; + type Residual = MyResult; + + fn from_output(u: U) -> MyResult { + MyResult::Awesome(u) + } + + fn branch(self) -> ControlFlow { + match self { + MyResult::Awesome(u) => ControlFlow::Continue(u), + MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)), + } + } +} + +impl FromResidual> for MyResult where V: Into { + fn from_residual(x: MyResult) -> Self { + match x { + MyResult::Awesome(u) => match u {}, + MyResult::Terrible(e) => MyResult::Terrible(e.into()), + } + } +} + +type ResultResidual = Result; + +impl FromResidual> for MyResult where V: Into { + fn from_residual(x: ResultResidual) -> Self { + match x { + Ok(v) => match v {} + Err(e) => MyResult::Terrible(e.into()), + } + } +} + +impl FromResidual> for Result where V: Into { + fn from_residual(x: MyResult) -> Self { + match x { + MyResult::Awesome(u) => match u {}, + MyResult::Terrible(e) => Err(e.into()), + } + } +} + +fn f(x: i32) -> Result { + if x == 0 { + Ok(42) + } else { + let y = g(x)?; + Ok(y) + } +} + +fn g(x: i32) -> MyResult { + let _y = f(x - 1)?; + MyResult::Terrible("Hello".to_owned()) +} + +fn h() -> MyResult { + let a: Result = Err("Hello"); + let b = a?; + MyResult::Awesome(b) +} + +fn i() -> MyResult { + let a: MyResult = MyResult::Terrible("Hello"); + let b = a?; + MyResult::Awesome(b) +} + +fn main() { + assert!(f(0) == Ok(42)); + assert!(f(10) == Err("Hello".to_owned())); + let _ = h(); + let _ = i(); +} diff --git a/tests/ui/try-trait/try-operator-on-main.rs b/tests/ui/try-trait/try-operator-on-main.rs new file mode 100644 index 000000000..3b364f7e7 --- /dev/null +++ b/tests/ui/try-trait/try-operator-on-main.rs @@ -0,0 +1,22 @@ +#![feature(try_trait_v2)] + +use std::ops::Try; + +fn main() { + // error for a `Try` type on a non-`Try` fn + std::fs::File::open("foo")?; //~ ERROR the `?` operator can only + + // a non-`Try` type on a non-`Try` fn + ()?; //~ ERROR the `?` operator can only be applied to + //~^ ERROR the `?` operator can only be used in a function that + + // an unrelated use of `Try` + try_trait_generic::<()>(); //~ ERROR the trait bound +} + +fn try_trait_generic() -> T { + // and a non-`Try` object on a `Try` fn. + ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` + + loop {} +} diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr new file mode 100644 index 000000000..7cd38e0cf --- /dev/null +++ b/tests/ui/try-trait/try-operator-on-main.stderr @@ -0,0 +1,53 @@ +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-operator-on-main.rs:7:31 + | +LL | fn main() { + | --------- this function should return `Result` or `Option` to accept `?` +LL | // error for a `Try` type on a non-`Try` fn +LL | std::fs::File::open("foo")?; + | ^ cannot use the `?` operator in a function that returns `()` + | + = help: the trait `FromResidual>` is not implemented for `()` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/try-operator-on-main.rs:10:5 + | +LL | ()?; + | ^^^ the `?` operator cannot be applied to type `()` + | + = help: the trait `Try` is not implemented for `()` + +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) + --> $DIR/try-operator-on-main.rs:10:7 + | +LL | fn main() { + | --------- this function should return `Result` or `Option` to accept `?` +... +LL | ()?; + | ^ cannot use the `?` operator in a function that returns `()` + | + = help: the trait `FromResidual<_>` is not implemented for `()` + +error[E0277]: the trait bound `(): Try` is not satisfied + --> $DIR/try-operator-on-main.rs:14:25 + | +LL | try_trait_generic::<()>(); + | ^^ the trait `Try` is not implemented for `()` + | +note: required by a bound in `try_trait_generic` + --> $DIR/try-operator-on-main.rs:17:25 + | +LL | fn try_trait_generic() -> T { + | ^^^ required by this bound in `try_trait_generic` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/try-operator-on-main.rs:19:5 + | +LL | ()?; + | ^^^ the `?` operator cannot be applied to type `()` + | + = help: the trait `Try` is not implemented for `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/try-trait/try-poll.rs b/tests/ui/try-trait/try-poll.rs new file mode 100644 index 000000000..d42e51c74 --- /dev/null +++ b/tests/ui/try-trait/try-poll.rs @@ -0,0 +1,50 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(dead_code, unused)] + +use std::task::Poll; + +struct K; +struct E; + +fn as_result() -> Result<(), E> { + // From Result + let K = Ok::(K)?; + + // From Poll + let _: Poll = Poll::Ready::>(Ok(K))?; + + // From Poll> + let _: Poll> = Poll::Ready::>>(None)?; + + Ok(()) +} + +fn as_poll_result() -> Poll> { + // From Result + let K = Ok::(K)?; + + // From Poll + let _: Poll = Poll::Ready::>(Ok(K))?; + + // From Poll> + let _: Poll> = Poll::Ready::>>(None)?; + + Poll::Ready(Ok(())) +} + +fn as_poll_option_result() -> Poll>> { + // From Result + let K = Ok::(K)?; + + // From Poll + let _: Poll = Poll::Ready::>(Ok(K))?; + + // From Poll> + let _: Poll> = Poll::Ready::>>(None)?; + + Poll::Ready(Some(Ok(()))) +} + +fn main() { +} diff --git a/tests/ui/try-trait/yeet-for-option.rs b/tests/ui/try-trait/yeet-for-option.rs new file mode 100644 index 000000000..753fbc1de --- /dev/null +++ b/tests/ui/try-trait/yeet-for-option.rs @@ -0,0 +1,11 @@ +// run-pass + +#![feature(yeet_expr)] + +fn always_yeet() -> Option { + do yeet; +} + +fn main() { + assert_eq!(always_yeet(), None); +} diff --git a/tests/ui/try-trait/yeet-for-result.rs b/tests/ui/try-trait/yeet-for-result.rs new file mode 100644 index 000000000..b7b113797 --- /dev/null +++ b/tests/ui/try-trait/yeet-for-result.rs @@ -0,0 +1,11 @@ +// run-pass + +#![feature(yeet_expr)] + +fn always_yeet() -> Result { + do yeet "hello"; +} + +fn main() { + assert_eq!(always_yeet(), Err("hello".to_string())); +} diff --git a/tests/ui/tuple-index.rs b/tests/ui/tuple-index.rs new file mode 100644 index 000000000..3e1d92b42 --- /dev/null +++ b/tests/ui/tuple-index.rs @@ -0,0 +1,32 @@ +// run-pass + +struct Point(isize, isize); + +fn main() { + let mut x = Point(3, 2); + assert_eq!(x.0, 3); + assert_eq!(x.1, 2); + x.0 += 5; + assert_eq!(x.0, 8); + { + let ry = &mut x.1; + *ry -= 2; + x.0 += 3; + assert_eq!(x.0, 11); + } + assert_eq!(x.1, 0); + + let mut x = (3, 2); + assert_eq!(x.0, 3); + assert_eq!(x.1, 2); + x.0 += 5; + assert_eq!(x.0, 8); + { + let ry = &mut x.1; + *ry -= 2; + x.0 += 3; + assert_eq!(x.0, 11); + } + assert_eq!(x.1, 0); + +} diff --git a/tests/ui/tuple/add-tuple-within-arguments.rs b/tests/ui/tuple/add-tuple-within-arguments.rs new file mode 100644 index 000000000..01b13b29f --- /dev/null +++ b/tests/ui/tuple/add-tuple-within-arguments.rs @@ -0,0 +1,10 @@ +fn foo(s: &str, a: (i32, i32), s2: &str) {} + +fn bar(s: &str, a: (&str,), s2: &str) {} + +fn main() { + foo("hi", 1, 2, "hi"); + //~^ ERROR function takes 3 arguments but 4 arguments were supplied + bar("hi", "hi", "hi"); + //~^ ERROR mismatched types +} diff --git a/tests/ui/tuple/add-tuple-within-arguments.stderr b/tests/ui/tuple/add-tuple-within-arguments.stderr new file mode 100644 index 000000000..2e20a4cca --- /dev/null +++ b/tests/ui/tuple/add-tuple-within-arguments.stderr @@ -0,0 +1,40 @@ +error[E0061]: function takes 3 arguments but 4 arguments were supplied + --> $DIR/add-tuple-within-arguments.rs:6:5 + | +LL | foo("hi", 1, 2, "hi"); + | ^^^ + | +note: function defined here + --> $DIR/add-tuple-within-arguments.rs:1:4 + | +LL | fn foo(s: &str, a: (i32, i32), s2: &str) {} + | ^^^ ------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | foo("hi", (1, 2), "hi"); + | + + + +error[E0308]: mismatched types + --> $DIR/add-tuple-within-arguments.rs:8:15 + | +LL | bar("hi", "hi", "hi"); + | --- ^^^^ expected tuple, found `&str` + | | + | arguments to this function are incorrect + | + = note: expected tuple `(&str,)` + found reference `&'static str` +note: function defined here + --> $DIR/add-tuple-within-arguments.rs:3:4 + | +LL | fn bar(s: &str, a: (&str,), s2: &str) {} + | ^^^ ---------- +help: use a trailing comma to create a tuple with one element + | +LL | bar("hi", ("hi",), "hi"); + | + ++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/tuple/array-diagnostics.rs b/tests/ui/tuple/array-diagnostics.rs new file mode 100644 index 000000000..1929dab07 --- /dev/null +++ b/tests/ui/tuple/array-diagnostics.rs @@ -0,0 +1,7 @@ +fn main() { + let _tmp = [ + ("C200B40A82", 3), + ("C200B40A83", 4) //~ ERROR: expected function, found `(&'static str, {integer})` [E0618] + ("C200B40A8537", 5), + ]; +} diff --git a/tests/ui/tuple/array-diagnostics.stderr b/tests/ui/tuple/array-diagnostics.stderr new file mode 100644 index 000000000..a10d7af47 --- /dev/null +++ b/tests/ui/tuple/array-diagnostics.stderr @@ -0,0 +1,9 @@ +error[E0618]: expected function, found `(&'static str, {integer})` + --> $DIR/array-diagnostics.rs:4:9 + | +LL | ("C200B40A83", 4) + | ^^^^^^^^^^^^^^^^^- help: consider separating array elements with a comma: `,` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/tuple/builtin-fail.rs b/tests/ui/tuple/builtin-fail.rs new file mode 100644 index 000000000..312080961 --- /dev/null +++ b/tests/ui/tuple/builtin-fail.rs @@ -0,0 +1,19 @@ +#![feature(tuple_trait)] + +fn assert_is_tuple() {} + +struct TupleStruct(i32, i32); + +fn from_param_env() { + assert_is_tuple::(); + //~^ ERROR `T` is not a tuple +} + +fn main() { + assert_is_tuple::(); + //~^ ERROR `i32` is not a tuple + assert_is_tuple::<(i32)>(); + //~^ ERROR `i32` is not a tuple + assert_is_tuple::(); + //~^ ERROR `TupleStruct` is not a tuple +} diff --git a/tests/ui/tuple/builtin-fail.stderr b/tests/ui/tuple/builtin-fail.stderr new file mode 100644 index 000000000..e3e29a73f --- /dev/null +++ b/tests/ui/tuple/builtin-fail.stderr @@ -0,0 +1,55 @@ +error[E0277]: `T` is not a tuple + --> $DIR/builtin-fail.rs:8:23 + | +LL | assert_is_tuple::(); + | ^ the trait `Tuple` is not implemented for `T` + | +note: required by a bound in `assert_is_tuple` + --> $DIR/builtin-fail.rs:3:23 + | +LL | fn assert_is_tuple() {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple` +help: consider restricting type parameter `T` + | +LL | fn from_param_env() { + | ++++++++++++++++++++ + +error[E0277]: `i32` is not a tuple + --> $DIR/builtin-fail.rs:13:23 + | +LL | assert_is_tuple::(); + | ^^^ the trait `Tuple` is not implemented for `i32` + | +note: required by a bound in `assert_is_tuple` + --> $DIR/builtin-fail.rs:3:23 + | +LL | fn assert_is_tuple() {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple` + +error[E0277]: `i32` is not a tuple + --> $DIR/builtin-fail.rs:15:24 + | +LL | assert_is_tuple::<(i32)>(); + | ^^^ the trait `Tuple` is not implemented for `i32` + | +note: required by a bound in `assert_is_tuple` + --> $DIR/builtin-fail.rs:3:23 + | +LL | fn assert_is_tuple() {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple` + +error[E0277]: `TupleStruct` is not a tuple + --> $DIR/builtin-fail.rs:17:23 + | +LL | assert_is_tuple::(); + | ^^^^^^^^^^^ the trait `Tuple` is not implemented for `TupleStruct` + | +note: required by a bound in `assert_is_tuple` + --> $DIR/builtin-fail.rs:3:23 + | +LL | fn assert_is_tuple() {} + | ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/tuple/builtin.rs b/tests/ui/tuple/builtin.rs new file mode 100644 index 000000000..d87ce5263 --- /dev/null +++ b/tests/ui/tuple/builtin.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(tuple_trait)] + +fn assert_is_tuple() {} + +struct Unsized([u8]); + +fn from_param_env() { + assert_is_tuple::(); +} + +fn main() { + assert_is_tuple::<()>(); + assert_is_tuple::<(i32,)>(); + assert_is_tuple::<(Unsized,)>(); + from_param_env::<()>(); + from_param_env::<(i32,)>(); + from_param_env::<(Unsized,)>(); +} diff --git a/tests/ui/tuple/index-float.rs b/tests/ui/tuple/index-float.rs new file mode 100644 index 000000000..eda2bf485 --- /dev/null +++ b/tests/ui/tuple/index-float.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() { + let tuple = (((),),); + + let _ = tuple. 0.0; // OK, whitespace + let _ = tuple.0. 0; // OK, whitespace + + let _ = tuple./*special cases*/0.0; // OK, comment +} diff --git a/tests/ui/tuple/index-invalid.rs b/tests/ui/tuple/index-invalid.rs new file mode 100644 index 000000000..d36f6cfe3 --- /dev/null +++ b/tests/ui/tuple/index-invalid.rs @@ -0,0 +1,7 @@ +fn main() { + let _ = (((),),).1.0; //~ ERROR no field `1` on type `(((),),)` + + let _ = (((),),).0.1; //~ ERROR no field `1` on type `((),)` + + let _ = (((),),).000.000; //~ ERROR no field `000` on type `(((),),)` +} diff --git a/tests/ui/tuple/index-invalid.stderr b/tests/ui/tuple/index-invalid.stderr new file mode 100644 index 000000000..8d22f458a --- /dev/null +++ b/tests/ui/tuple/index-invalid.stderr @@ -0,0 +1,21 @@ +error[E0609]: no field `1` on type `(((),),)` + --> $DIR/index-invalid.rs:2:22 + | +LL | let _ = (((),),).1.0; + | ^ + +error[E0609]: no field `1` on type `((),)` + --> $DIR/index-invalid.rs:4:24 + | +LL | let _ = (((),),).0.1; + | ^ + +error[E0609]: no field `000` on type `(((),),)` + --> $DIR/index-invalid.rs:6:22 + | +LL | let _ = (((),),).000.000; + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/tuple/indexing-in-macro.rs b/tests/ui/tuple/indexing-in-macro.rs new file mode 100644 index 000000000..bef4a69ab --- /dev/null +++ b/tests/ui/tuple/indexing-in-macro.rs @@ -0,0 +1,9 @@ +// check-pass + +macro_rules! m { + (.$l:literal) => {}; +} + +m!(.0.0); // OK, `0.0` after a dot is still a float token. + +fn main() {} diff --git a/tests/ui/tuple/nested-index.rs b/tests/ui/tuple/nested-index.rs new file mode 100644 index 000000000..a3232d6fc --- /dev/null +++ b/tests/ui/tuple/nested-index.rs @@ -0,0 +1,12 @@ +// run-pass + +fn main () { + let n = (1, (2, 3)).1.1; + assert_eq!(n, 3); + + let n = (1, (2, (3, 4))).1.1.1; + assert_eq!(n, 4); + + // This is a range expression, not nested indexing. + let _ = 0.0..1.1; +} diff --git a/tests/ui/tuple/one-tuple.rs b/tests/ui/tuple/one-tuple.rs new file mode 100644 index 000000000..00fbadce1 --- /dev/null +++ b/tests/ui/tuple/one-tuple.rs @@ -0,0 +1,15 @@ +// run-pass +// Why one-tuples? Because macros. + + +pub fn main() { + match ('c',) { + (x,) => { + assert_eq!(x, 'c'); + } + } + // test the 1-tuple type too + let x: (char,) = ('d',); + let (y,) = x; + assert_eq!(y, 'd'); +} diff --git a/tests/ui/tuple/tup.rs b/tests/ui/tuple/tup.rs new file mode 100644 index 000000000..160477b0b --- /dev/null +++ b/tests/ui/tuple/tup.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(non_camel_case_types)] + +type point = (isize, isize); + +fn f(p: point, x: isize, y: isize) { + let (a, b) = p; + assert_eq!(a, x); + assert_eq!(b, y); +} + +pub fn main() { + let p: point = (10, 20); + let (a, b) = p; + assert_eq!(a, 10); + assert_eq!(b, 20); + let p2: point = p; + f(p, 10, 20); + f(p2, 10, 20); +} diff --git a/tests/ui/tuple/tuple-arity-mismatch.rs b/tests/ui/tuple/tuple-arity-mismatch.rs new file mode 100644 index 000000000..f1e525c93 --- /dev/null +++ b/tests/ui/tuple/tuple-arity-mismatch.rs @@ -0,0 +1,17 @@ +// Issue #6155 + +fn first((value, _): (isize, f64)) -> isize { value } + +fn main() { + let y = first ((1,2.0,3)); + //~^ ERROR mismatched types + //~| expected tuple `(isize, f64)` + //~| found tuple `(isize, f64, {integer})` + //~| expected a tuple with 2 elements, found one with 3 elements + + let y = first ((1,)); + //~^ ERROR mismatched types + //~| expected tuple `(isize, f64)` + //~| found tuple `(isize,)` + //~| expected a tuple with 2 elements, found one with 1 element +} diff --git a/tests/ui/tuple/tuple-arity-mismatch.stderr b/tests/ui/tuple/tuple-arity-mismatch.stderr new file mode 100644 index 000000000..fff7be987 --- /dev/null +++ b/tests/ui/tuple/tuple-arity-mismatch.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/tuple-arity-mismatch.rs:6:20 + | +LL | let y = first ((1,2.0,3)); + | ----- ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | | + | arguments to this function are incorrect + | + = note: expected tuple `(isize, f64)` + found tuple `(isize, f64, {integer})` +note: function defined here + --> $DIR/tuple-arity-mismatch.rs:3:4 + | +LL | fn first((value, _): (isize, f64)) -> isize { value } + | ^^^^^ ------------------------ + +error[E0308]: mismatched types + --> $DIR/tuple-arity-mismatch.rs:12:20 + | +LL | let y = first ((1,)); + | ----- ^^^^ expected a tuple with 2 elements, found one with 1 element + | | + | arguments to this function are incorrect + | + = note: expected tuple `(isize, f64)` + found tuple `(isize,)` +note: function defined here + --> $DIR/tuple-arity-mismatch.rs:3:4 + | +LL | fn first((value, _): (isize, f64)) -> isize { value } + | ^^^^^ ------------------------ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/tuple/tuple-index-fat-types.rs b/tests/ui/tuple/tuple-index-fat-types.rs new file mode 100644 index 000000000..5dda1ed97 --- /dev/null +++ b/tests/ui/tuple/tuple-index-fat-types.rs @@ -0,0 +1,13 @@ +// run-pass + +struct Foo<'a>(&'a [isize]); + +fn main() { + let x: &[isize] = &[1, 2, 3]; + let y = (x,); + assert_eq!(y.0, x); + + let x: &[isize] = &[1, 2, 3]; + let y = Foo(x); + assert_eq!(y.0, x); +} diff --git a/tests/ui/tuple/tuple-index-not-tuple.rs b/tests/ui/tuple/tuple-index-not-tuple.rs new file mode 100644 index 000000000..c478e1c67 --- /dev/null +++ b/tests/ui/tuple/tuple-index-not-tuple.rs @@ -0,0 +1,10 @@ +struct Point { x: isize, y: isize } +struct Empty; + +fn main() { + let origin = Point { x: 0, y: 0 }; + origin.0; + //~^ ERROR no field `0` on type `Point` + Empty.0; + //~^ ERROR no field `0` on type `Empty` +} diff --git a/tests/ui/tuple/tuple-index-not-tuple.stderr b/tests/ui/tuple/tuple-index-not-tuple.stderr new file mode 100644 index 000000000..a1bcdfaed --- /dev/null +++ b/tests/ui/tuple/tuple-index-not-tuple.stderr @@ -0,0 +1,15 @@ +error[E0609]: no field `0` on type `Point` + --> $DIR/tuple-index-not-tuple.rs:6:12 + | +LL | origin.0; + | ^ help: a field with a similar name exists: `x` + +error[E0609]: no field `0` on type `Empty` + --> $DIR/tuple-index-not-tuple.rs:8:11 + | +LL | Empty.0; + | ^ unknown field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.rs b/tests/ui/tuple/tuple-index-out-of-bounds.rs new file mode 100644 index 000000000..c772c0daa --- /dev/null +++ b/tests/ui/tuple/tuple-index-out-of-bounds.rs @@ -0,0 +1,14 @@ +struct Point(i32, i32); + +fn main() { + let origin = Point(0, 0); + origin.0; + origin.1; + origin.2; + //~^ ERROR no field `2` on type `Point` + let tuple = (0, 0); + tuple.0; + tuple.1; + tuple.2; + //~^ ERROR no field `2` on type `({integer}, {integer})` +} diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr new file mode 100644 index 000000000..7d7c5cd78 --- /dev/null +++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr @@ -0,0 +1,15 @@ +error[E0609]: no field `2` on type `Point` + --> $DIR/tuple-index-out-of-bounds.rs:7:12 + | +LL | origin.2; + | ^ help: a field with a similar name exists: `0` + +error[E0609]: no field `2` on type `({integer}, {integer})` + --> $DIR/tuple-index-out-of-bounds.rs:12:11 + | +LL | tuple.2; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/tuple/tuple-struct-fields/test.rs b/tests/ui/tuple/tuple-struct-fields/test.rs new file mode 100644 index 000000000..00677090d --- /dev/null +++ b/tests/ui/tuple/tuple-struct-fields/test.rs @@ -0,0 +1,9 @@ +mod foo { + type T = (); + struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T))); + struct S2(pub((foo)) ()); + //~^ ERROR expected one of `)` or `,`, found `(` + //~| ERROR cannot find type `foo` in this scope +} + +fn main() {} diff --git a/tests/ui/tuple/tuple-struct-fields/test.stderr b/tests/ui/tuple/tuple-struct-fields/test.stderr new file mode 100644 index 000000000..bfa0b32fd --- /dev/null +++ b/tests/ui/tuple/tuple-struct-fields/test.stderr @@ -0,0 +1,17 @@ +error: expected one of `)` or `,`, found `(` + --> $DIR/test.rs:4:26 + | +LL | struct S2(pub((foo)) ()); + | -^ expected one of `)` or `,` + | | + | help: missing `,` + +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test.rs:4:20 + | +LL | struct S2(pub((foo)) ()); + | ^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/tuple/tuple-struct-fields/test2.rs b/tests/ui/tuple/tuple-struct-fields/test2.rs new file mode 100644 index 000000000..2b2a2c127 --- /dev/null +++ b/tests/ui/tuple/tuple-struct-fields/test2.rs @@ -0,0 +1,15 @@ +macro_rules! define_struct { + ($t:ty) => { + struct S1(pub $t); + struct S2(pub (in foo) ()); + struct S3(pub $t ()); + //~^ ERROR expected one of `)` or `,`, found `(` + } +} + +mod foo { + define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope + //~| ERROR cannot find type `foo` in this scope +} + +fn main() {} diff --git a/tests/ui/tuple/tuple-struct-fields/test2.stderr b/tests/ui/tuple/tuple-struct-fields/test2.stderr new file mode 100644 index 000000000..64a9ac135 --- /dev/null +++ b/tests/ui/tuple/tuple-struct-fields/test2.stderr @@ -0,0 +1,28 @@ +error: expected one of `)` or `,`, found `(` + --> $DIR/test2.rs:5:26 + | +LL | struct S3(pub $t ()); + | -^ expected one of `)` or `,` + | | + | help: missing `,` +... +LL | define_struct! { (foo) } + | ------------------------ in this macro invocation + | + = note: this error originates in the macro `define_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test2.rs:11:23 + | +LL | define_struct! { (foo) } + | ^^^ not found in this scope + +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test2.rs:11:23 + | +LL | define_struct! { (foo) } + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/tuple/tuple-struct-fields/test3.rs b/tests/ui/tuple/tuple-struct-fields/test3.rs new file mode 100644 index 000000000..98d19426e --- /dev/null +++ b/tests/ui/tuple/tuple-struct-fields/test3.rs @@ -0,0 +1,15 @@ +macro_rules! define_struct { + ($t:ty) => { + struct S1(pub($t)); + struct S2(pub (in foo) ()); + struct S3(pub($t) ()); + //~^ ERROR expected one of `)` or `,`, found `(` + } +} + +mod foo { + define_struct! { foo } //~ ERROR cannot find type `foo` in this scope + //~| ERROR cannot find type `foo` in this scope +} + +fn main() {} diff --git a/tests/ui/tuple/tuple-struct-fields/test3.stderr b/tests/ui/tuple/tuple-struct-fields/test3.stderr new file mode 100644 index 000000000..75262ed57 --- /dev/null +++ b/tests/ui/tuple/tuple-struct-fields/test3.stderr @@ -0,0 +1,28 @@ +error: expected one of `)` or `,`, found `(` + --> $DIR/test3.rs:5:27 + | +LL | struct S3(pub($t) ()); + | -^ expected one of `)` or `,` + | | + | help: missing `,` +... +LL | define_struct! { foo } + | ---------------------- in this macro invocation + | + = note: this error originates in the macro `define_struct` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test3.rs:11:22 + | +LL | define_struct! { foo } + | ^^^ not found in this scope + +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test3.rs:11:22 + | +LL | define_struct! { foo } + | ^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/tuple/wrong_argument_ice-2.rs b/tests/ui/tuple/wrong_argument_ice-2.rs new file mode 100644 index 000000000..e1c1d748f --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice-2.rs @@ -0,0 +1,17 @@ +fn test(t: (i32, i32)) {} + +struct Foo; + +impl Foo { + fn qux(&self) -> i32 { + 0 + } +} + +fn bar() { + let x = Foo; + test(x.qux(), x.qux()); + //~^ ERROR function takes 1 argument but 2 arguments were supplied +} + +fn main() {} diff --git a/tests/ui/tuple/wrong_argument_ice-2.stderr b/tests/ui/tuple/wrong_argument_ice-2.stderr new file mode 100644 index 000000000..412442092 --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice-2.stderr @@ -0,0 +1,19 @@ +error[E0061]: function takes 1 argument but 2 arguments were supplied + --> $DIR/wrong_argument_ice-2.rs:13:5 + | +LL | test(x.qux(), x.qux()); + | ^^^^ + | +note: function defined here + --> $DIR/wrong_argument_ice-2.rs:1:4 + | +LL | fn test(t: (i32, i32)) {} + | ^^^^ ------------- +help: wrap these arguments in parentheses to construct a tuple + | +LL | test((x.qux(), x.qux())); + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/tuple/wrong_argument_ice-3.rs b/tests/ui/tuple/wrong_argument_ice-3.rs new file mode 100644 index 000000000..96633180b --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice-3.rs @@ -0,0 +1,17 @@ +struct Process; + +pub type Group = (Vec, Vec); + +fn test(process: &Process, groups: Vec) -> Vec { + let new_group = vec![String::new()]; + + if groups.capacity() == 0 { + groups.push(new_group, vec![process]); + //~^ ERROR this method takes 1 argument but 2 arguments were supplied + return groups; + } + + todo!() +} + +fn main() {} diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr new file mode 100644 index 000000000..0a503e1fe --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice-3.stderr @@ -0,0 +1,23 @@ +error[E0061]: this method takes 1 argument but 2 arguments were supplied + --> $DIR/wrong_argument_ice-3.rs:9:16 + | +LL | groups.push(new_group, vec![process]); + | ^^^^ ------------- argument of type `Vec<&Process>` unexpected + | +note: expected tuple, found struct `Vec` + --> $DIR/wrong_argument_ice-3.rs:9:21 + | +LL | groups.push(new_group, vec![process]); + | ^^^^^^^^^ + = note: expected tuple `(Vec, Vec)` + found struct `Vec` +note: associated function defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +help: remove the extra argument + | +LL | groups.push(/* (Vec, Vec) */); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/tuple/wrong_argument_ice-4.rs b/tests/ui/tuple/wrong_argument_ice-4.rs new file mode 100644 index 000000000..883d92dcc --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice-4.rs @@ -0,0 +1,6 @@ +fn main() { + (|| {})(|| { + //~^ ERROR function takes 0 arguments but 1 argument was supplied + let b = 1; + }); +} diff --git a/tests/ui/tuple/wrong_argument_ice-4.stderr b/tests/ui/tuple/wrong_argument_ice-4.stderr new file mode 100644 index 000000000..a2686ab94 --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice-4.stderr @@ -0,0 +1,23 @@ +error[E0057]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/wrong_argument_ice-4.rs:2:5 + | +LL | (|| {})(|| { + | _____^^^^^^^_- +LL | | +LL | | let b = 1; +LL | | }); + | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]` unexpected + | +note: closure defined here + --> $DIR/wrong_argument_ice-4.rs:2:6 + | +LL | (|| {})(|| { + | ^^ +help: remove the extra argument + | +LL | (|| {})(); + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0057`. diff --git a/tests/ui/tuple/wrong_argument_ice.rs b/tests/ui/tuple/wrong_argument_ice.rs new file mode 100644 index 000000000..b7e0225fe --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice.rs @@ -0,0 +1,17 @@ +use std::collections::VecDeque; + +pub struct BuildPlanBuilder { + acc: VecDeque<(String, String)>, + current_provides: String, + current_requires: String, +} + +impl BuildPlanBuilder { + pub fn or(&mut self) -> &mut Self { + self.acc.push_back(self.current_provides, self.current_requires); + //~^ ERROR method takes 1 argument but 2 arguments were supplied + self + } +} + +fn main() {} diff --git a/tests/ui/tuple/wrong_argument_ice.stderr b/tests/ui/tuple/wrong_argument_ice.stderr new file mode 100644 index 000000000..f1b00ae0b --- /dev/null +++ b/tests/ui/tuple/wrong_argument_ice.stderr @@ -0,0 +1,16 @@ +error[E0061]: method takes 1 argument but 2 arguments were supplied + --> $DIR/wrong_argument_ice.rs:11:18 + | +LL | self.acc.push_back(self.current_provides, self.current_requires); + | ^^^^^^^^^ + | +note: associated function defined here + --> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL +help: wrap these arguments in parentheses to construct a tuple + | +LL | self.acc.push_back((self.current_provides, self.current_requires)); + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/tydesc-name.rs b/tests/ui/tydesc-name.rs new file mode 100644 index 000000000..c432e5b54 --- /dev/null +++ b/tests/ui/tydesc-name.rs @@ -0,0 +1,14 @@ +// run-pass + +#![allow(dead_code)] + +use std::any::type_name; + +struct Foo { + x: T +} + +pub fn main() { + assert_eq!(type_name::(), "isize"); + assert_eq!(type_name::>(), "tydesc_name::Foo"); +} diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs b/tests/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs new file mode 100644 index 000000000..0aa644db0 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs @@ -0,0 +1,59 @@ +// run-pass + +// Check that resolving, in the value namespace, to an `enum` variant +// through a type alias is well behaved in the presence of generics. +// We check for situations with: +// 1. a generic type `Alias`, we can type-apply `Alias` when referring to a variant. +// 2. a monotype `AliasFixed` of generic `Enum`, we can refer to variants +// and the type-application of `T` in `AliasFixed` is kept. + +#![allow(irrefutable_let_patterns)] + +enum Enum { TSVariant(#[allow(unused_tuple_struct_fields)] T), SVariant { _v: T }, UVariant } +type Alias = Enum; +type AliasFixed = Enum<()>; + +macro_rules! is_variant { + (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr)); + (SVariant, $expr:expr) => (is_variant!(@check SVariant, { _v: _ }, $expr)); + (UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr)); + (@check $variant:ident, $matcher:tt, $expr:expr) => ( + assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false }, + "expr does not have correct type"); + ); +} + +fn main() { + // Tuple struct variant + + is_variant!(TSVariant, Enum::TSVariant(())); + is_variant!(TSVariant, Enum::TSVariant::<()>(())); + is_variant!(TSVariant, Enum::<()>::TSVariant(())); + + is_variant!(TSVariant, Alias::TSVariant(())); + is_variant!(TSVariant, Alias::<()>::TSVariant(())); + + is_variant!(TSVariant, AliasFixed::TSVariant(())); + + // Struct variant + + is_variant!(SVariant, Enum::SVariant { _v: () }); + is_variant!(SVariant, Enum::SVariant::<()> { _v: () }); + is_variant!(SVariant, Enum::<()>::SVariant { _v: () }); + + is_variant!(SVariant, Alias::SVariant { _v: () }); + is_variant!(SVariant, Alias::<()>::SVariant { _v: () }); + + is_variant!(SVariant, AliasFixed::SVariant { _v: () }); + + // Unit variant + + is_variant!(UVariant, Enum::UVariant); + is_variant!(UVariant, Enum::UVariant::<()>); + is_variant!(UVariant, Enum::<()>::UVariant); + + is_variant!(UVariant, Alias::UVariant); + is_variant!(UVariant, Alias::<()>::UVariant); + + is_variant!(UVariant, AliasFixed::UVariant); +} diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs new file mode 100644 index 000000000..0031a4665 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs @@ -0,0 +1,105 @@ +// Checks that applied type arguments of enums, and aliases to them, are respected. +// For example, `Self` is never a type constructor. Therefore, no types can be applied to it. +// +// We also check that the variant to an type-aliased enum cannot be type applied whether +// that alias is generic or monomorphic. + +enum Enum { TSVariant(T), SVariant { v: T }, UVariant } +type Alias = Enum; +type AliasFixed = Enum<()>; + +impl Enum { + fn ts_variant() { + Self::TSVariant(()); + //~^ ERROR mismatched types [E0308] + Self::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this type [E0109] + Self::<()>::TSVariant(()); + //~^ ERROR type arguments are not allowed on self type [E0109] + //~| ERROR mismatched types [E0308] + Self::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on self type [E0109] + //~| ERROR type arguments are not allowed on this type [E0109] + } + + fn s_variant() { + Self::SVariant { v: () }; + //~^ ERROR mismatched types [E0308] + Self::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this type [E0109] + //~| ERROR mismatched types [E0308] + Self::<()>::SVariant { v: () }; + //~^ ERROR type arguments are not allowed on self type [E0109] + //~| ERROR mismatched types [E0308] + Self::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on self type [E0109] + //~| ERROR type arguments are not allowed on this type [E0109] + //~| ERROR mismatched types [E0308] + } + + fn u_variant() { + Self::UVariant::<()>; + //~^ ERROR type arguments are not allowed on this type [E0109] + Self::<()>::UVariant; + //~^ ERROR type arguments are not allowed on self type [E0109] + Self::<()>::UVariant::<()>; + //~^ ERROR type arguments are not allowed on self type [E0109] + //~| ERROR type arguments are not allowed on this type [E0109] + } +} + +fn main() { + // Tuple struct variant + + Enum::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on tuple variant `TSVariant` [E0109] + + Alias::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this type [E0109] + Alias::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this type [E0109] + + AliasFixed::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this type [E0109] + AliasFixed::<()>::TSVariant(()); + //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107] + AliasFixed::<()>::TSVariant::<()>(()); + //~^ ERROR type arguments are not allowed on this type [E0109] + //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107] + + // Struct variant + + Enum::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on variant `SVariant` [E0109] + + Alias::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this type [E0109] + Alias::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this type [E0109] + + AliasFixed::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this type [E0109] + AliasFixed::<()>::SVariant { v: () }; + //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107] + AliasFixed::<()>::SVariant::<()> { v: () }; + //~^ ERROR type arguments are not allowed on this type [E0109] + //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107] + + // Unit variant + + Enum::<()>::UVariant::<()>; + //~^ ERROR type arguments are not allowed on unit variant `UVariant` [E0109] + + Alias::UVariant::<()>; + //~^ ERROR type arguments are not allowed on this type [E0109] + Alias::<()>::UVariant::<()>; + //~^ ERROR type arguments are not allowed on this type [E0109] + + AliasFixed::UVariant::<()>; + //~^ ERROR type arguments are not allowed on this type [E0109] + AliasFixed::<()>::UVariant; + //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107] + AliasFixed::<()>::UVariant::<()>; + //~^ ERROR type arguments are not allowed on this type [E0109] + //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107] +} diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr new file mode 100644 index 000000000..a922d7a5e --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -0,0 +1,512 @@ +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:13:25 + | +LL | impl Enum { + | - this type parameter +LL | fn ts_variant() { +LL | Self::TSVariant(()); + | --------------- ^^ expected type parameter `T`, found `()` + | | + | arguments to this enum variant are incorrect + | + = note: expected type parameter `T` + found unit type `()` +note: tuple variant defined here + --> $DIR/enum-variant-generic-args.rs:7:16 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^^^^^^ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:15:27 + | +LL | Self::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on self type + --> $DIR/enum-variant-generic-args.rs:17:16 + | +LL | Self::<()>::TSVariant(()); + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `Enum` + --> $DIR/enum-variant-generic-args.rs:7:6 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^ `Self` corresponds to this type +... +LL | impl Enum { + | --------------- `Self` is on type `Enum` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters + | +LL | Enum::<()>::TSVariant(()); + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:17:31 + | +LL | impl Enum { + | - this type parameter +... +LL | Self::<()>::TSVariant(()); + | --------------------- ^^ expected type parameter `T`, found `()` + | | + | arguments to this enum variant are incorrect + | + = note: expected type parameter `T` + found unit type `()` +note: tuple variant defined here + --> $DIR/enum-variant-generic-args.rs:7:16 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^^^^^^ + +error[E0109]: type arguments are not allowed on self type + --> $DIR/enum-variant-generic-args.rs:20:16 + | +LL | Self::<()>::TSVariant::<()>(()); + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `Enum` + --> $DIR/enum-variant-generic-args.rs:7:6 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^ `Self` corresponds to this type +... +LL | impl Enum { + | --------------- `Self` is on type `Enum` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters + | +LL | Enum::<()>::TSVariant::<()>(()); + | ~~~~ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:20:33 + | +LL | Self::<()>::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:26:29 + | +LL | impl Enum { + | - this type parameter +... +LL | Self::SVariant { v: () }; + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:28:26 + | +LL | Self::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specity type parameters on enum `Enum` + | +LL - Self::SVariant::<()> { v: () }; +LL + Enum::<()>::SVariant { v: () }; + | + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:28:35 + | +LL | impl Enum { + | - this type parameter +... +LL | Self::SVariant::<()> { v: () }; + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error[E0109]: type arguments are not allowed on self type + --> $DIR/enum-variant-generic-args.rs:31:16 + | +LL | Self::<()>::SVariant { v: () }; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `Enum` + --> $DIR/enum-variant-generic-args.rs:7:6 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^ `Self` corresponds to this type +... +LL | impl Enum { + | --------------- `Self` is on type `Enum` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters + | +LL | Enum::<()>::SVariant { v: () }; + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:31:35 + | +LL | impl Enum { + | - this type parameter +... +LL | Self::<()>::SVariant { v: () }; + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error[E0109]: type arguments are not allowed on self type + --> $DIR/enum-variant-generic-args.rs:34:16 + | +LL | Self::<()>::SVariant::<()> { v: () }; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `Enum` + --> $DIR/enum-variant-generic-args.rs:7:6 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^ `Self` corresponds to this type +... +LL | impl Enum { + | --------------- `Self` is on type `Enum` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters + | +LL | Enum::<()>::SVariant::<()> { v: () }; + | ~~~~ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:34:32 + | +LL | Self::<()>::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specity type parameters on enum `Enum` + | +LL - Self::<()>::SVariant::<()> { v: () }; +LL + Enum::<()>::SVariant { v: () }; + | + +error[E0308]: mismatched types + --> $DIR/enum-variant-generic-args.rs:34:41 + | +LL | impl Enum { + | - this type parameter +... +LL | Self::<()>::SVariant::<()> { v: () }; + | ^^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:41:26 + | +LL | Self::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on self type + --> $DIR/enum-variant-generic-args.rs:43:16 + | +LL | Self::<()>::UVariant; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `Enum` + --> $DIR/enum-variant-generic-args.rs:7:6 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^ `Self` corresponds to this type +... +LL | impl Enum { + | --------------- `Self` is on type `Enum` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters + | +LL | Enum::<()>::UVariant; + | ~~~~ + +error[E0109]: type arguments are not allowed on self type + --> $DIR/enum-variant-generic-args.rs:45:16 + | +LL | Self::<()>::UVariant::<()>; + | ---- ^^ type argument not allowed + | | + | not allowed on self type + | +note: `Self` is of type `Enum` + --> $DIR/enum-variant-generic-args.rs:7:6 + | +LL | enum Enum { TSVariant(T), SVariant { v: T }, UVariant } + | ^^^^ `Self` corresponds to this type +... +LL | impl Enum { + | --------------- `Self` is on type `Enum` in this `impl` +help: the `Self` type doesn't accept type parameters, use the concrete type's name `Enum` instead if you want to specify its type parameters + | +LL | Enum::<()>::UVariant::<()>; + | ~~~~ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:45:32 + | +LL | Self::<()>::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on tuple variant `TSVariant` + --> $DIR/enum-variant-generic-args.rs:54:29 + | +LL | Enum::<()>::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on tuple variant `TSVariant` + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:57:24 + | +LL | Alias::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:59:30 + | +LL | Alias::<()>::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:62:29 + | +LL | AliasFixed::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/enum-variant-generic-args.rs:64:5 + | +LL | AliasFixed::<()>::TSVariant(()); + | ^^^^^^^^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/enum-variant-generic-args.rs:9:6 + | +LL | type AliasFixed = Enum<()>; + | ^^^^^^^^^^ + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/enum-variant-generic-args.rs:66:5 + | +LL | AliasFixed::<()>::TSVariant::<()>(()); + | ^^^^^^^^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/enum-variant-generic-args.rs:9:6 + | +LL | type AliasFixed = Enum<()>; + | ^^^^^^^^^^ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:66:35 + | +LL | AliasFixed::<()>::TSVariant::<()>(()); + | --------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on variant `SVariant` + --> $DIR/enum-variant-generic-args.rs:72:28 + | +LL | Enum::<()>::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on variant `SVariant` + | + = note: enum variants can't have type parameters + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:75:23 + | +LL | Alias::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specity type parameters on enum `Enum` + | +LL - Alias::SVariant::<()> { v: () }; +LL + Alias::<()>::SVariant { v: () }; + | + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:77:29 + | +LL | Alias::<()>::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specity type parameters on enum `Enum` + | +LL - Alias::<()>::SVariant::<()> { v: () }; +LL + Alias::<()>::SVariant { v: () }; + | + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:80:28 + | +LL | AliasFixed::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specity type parameters on enum `Enum` + | +LL - AliasFixed::SVariant::<()> { v: () }; +LL + AliasFixed::<()>::SVariant { v: () }; + | + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/enum-variant-generic-args.rs:82:5 + | +LL | AliasFixed::<()>::SVariant { v: () }; + | ^^^^^^^^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/enum-variant-generic-args.rs:9:6 + | +LL | type AliasFixed = Enum<()>; + | ^^^^^^^^^^ + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/enum-variant-generic-args.rs:84:5 + | +LL | AliasFixed::<()>::SVariant::<()> { v: () }; + | ^^^^^^^^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/enum-variant-generic-args.rs:9:6 + | +LL | type AliasFixed = Enum<()>; + | ^^^^^^^^^^ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:84:34 + | +LL | AliasFixed::<()>::SVariant::<()> { v: () }; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + | + = note: enum variants can't have type parameters +help: you might have meant to specity type parameters on enum `Enum` + | +LL - AliasFixed::<()>::SVariant::<()> { v: () }; +LL + AliasFixed::<()>::SVariant { v: () }; + | + +error[E0109]: type arguments are not allowed on unit variant `UVariant` + --> $DIR/enum-variant-generic-args.rs:90:28 + | +LL | Enum::<()>::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on unit variant `UVariant` + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:93:23 + | +LL | Alias::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:95:29 + | +LL | Alias::<()>::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:98:28 + | +LL | AliasFixed::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/enum-variant-generic-args.rs:100:5 + | +LL | AliasFixed::<()>::UVariant; + | ^^^^^^^^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/enum-variant-generic-args.rs:9:6 + | +LL | type AliasFixed = Enum<()>; + | ^^^^^^^^^^ + +error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/enum-variant-generic-args.rs:102:5 + | +LL | AliasFixed::<()>::UVariant::<()>; + | ^^^^^^^^^^------ help: remove these generics + | | + | expected 0 generic arguments + | +note: type alias defined here, with 0 generic parameters + --> $DIR/enum-variant-generic-args.rs:9:6 + | +LL | type AliasFixed = Enum<()>; + | ^^^^^^^^^^ + +error[E0109]: type arguments are not allowed on this type + --> $DIR/enum-variant-generic-args.rs:102:34 + | +LL | AliasFixed::<()>::UVariant::<()>; + | -------- ^^ type argument not allowed + | | + | not allowed on this type + +error: aborting due to 39 previous errors + +Some errors have detailed explanations: E0107, E0109, E0308. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs new file mode 100644 index 000000000..3a8712f2a --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs @@ -0,0 +1,23 @@ +// Check that an `enum` variant is resolved, in the value namespace, +// with higher priority than other inherent items when there is a conflict. + +enum E { + V(u8) +} + +impl E { + fn V() {} +} + +enum E2 { + V, +} + +impl E2 { + const V: u8 = 0; +} + +fn main() { + ::V(); //~ ERROR this enum variant takes 1 argument but 0 arguments were supplied + let _: u8 = ::V; //~ ERROR mismatched types +} diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr new file mode 100644 index 000000000..eb58ee73c --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr @@ -0,0 +1,28 @@ +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5 + | +LL | ::V(); + | ^^^^^^-- an argument of type `u8` is missing + | +note: tuple variant defined here + --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5 + | +LL | V(u8) + | ^ +help: provide the argument + | +LL | ::V(/* u8 */); + | ~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17 + | +LL | let _: u8 = ::V; + | -- ^^^^^^^ expected `u8`, found enum `E2` + | | + | expected due to this + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0308. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs new file mode 100644 index 000000000..acbf15dcb --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs @@ -0,0 +1,41 @@ +// Check that a projection `Self::V` in a trait implementation, +// with an associated type named `V`, for an `enum` with a variant named `V`, +// results in triggering the deny-by-default lint `ambiguous_associated_items`. +// The lint suggests that qualified syntax should be used instead. +// That is, the user would write `::V`. +// +// The rationale for this is that while `enum` variants do currently +// not exist in the type namespace but solely in the value namespace, +// RFC #2593 "Enum variant types", would add enum variants to the type namespace. +// However, currently `enum` variants are resolved with high priority as +// they are resolved as inherent associated items. +// Should #2953 therefore be implemented, `Self::V` would suddenly switch +// from referring to the associated type `V` instead of the variant `V`. +// The lint exists to keep us forward compatible with #2593. +// +// As a closing note, provided that #2933 was implemented and +// if `enum` variants were given lower priority than associated types, +// it would be impossible to refer to the `enum` variant `V` whereas +// the associated type could be referred to with qualified syntax as seen above. + +enum E { + V +} + +trait Tr { + type V; + fn f() -> Self::V; +} + +impl Tr for E { + type V = u8; + fn f() -> Self::V { 0 } + //~^ ERROR ambiguous associated item + //~| ERROR ambiguous associated item + //~| WARN this was previously accepted + //~| WARN this was previously accepted + //~| HELP use fully-qualified syntax + //~| HELP use fully-qualified syntax +} + +fn main() {} diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr new file mode 100644 index 000000000..0202a2fea --- /dev/null +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -0,0 +1,41 @@ +error: ambiguous associated item + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 + | +LL | fn f() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `::V` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57644 +note: `V` could refer to the variant defined here + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 + | +LL | V + | ^ +note: `V` could also refer to the associated type defined here + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 + | +LL | type V; + | ^^^^^^ + = note: `#[deny(ambiguous_associated_items)]` on by default + +error: ambiguous associated item + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 + | +LL | fn f() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `::V` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57644 +note: `V` could refer to the variant defined here + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 + | +LL | V + | ^ +note: `V` could also refer to the associated type defined here + --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 + | +LL | type V; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs new file mode 100644 index 000000000..ab40bf580 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs @@ -0,0 +1,14 @@ +pub enum Enum { + A(usize), +} + +impl Enum { + fn foo(&self) -> () { + match self { + Self::A => (), + //~^ ERROR expected unit struct, unit variant or constant, found tuple variant + } + } +} + +fn main() {} diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr new file mode 100644 index 000000000..6870b9d7d --- /dev/null +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr @@ -0,0 +1,9 @@ +error[E0533]: expected unit struct, unit variant or constant, found tuple variant `Self::A` + --> $DIR/incorrect-variant-form-through-Self-issue-58006.rs:8:13 + | +LL | Self::A => (), + | ^^^^^^^ not a unit struct, unit variant or constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs new file mode 100644 index 000000000..5ed7988e4 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs @@ -0,0 +1,19 @@ +// Check that creating/matching on an enum variant through an alias with +// the wrong braced/unit form is caught as an error. + +enum Enum { Braced {}, Unit, Tuple() } +type Alias = Enum; + +fn main() { + Alias::Braced; + //~^ ERROR expected value, found struct variant `Alias::Braced` [E0533] + let Alias::Braced = panic!(); + //~^ ERROR expected unit struct, unit variant or constant, found struct variant `Alias::Braced` [E0533] + let Alias::Braced(..) = panic!(); + //~^ ERROR expected tuple struct or tuple variant, found struct variant `Alias::Braced` [E0164] + + Alias::Unit(); + //~^ ERROR expected function, found enum variant `Alias::Unit` + let Alias::Unit() = panic!(); + //~^ ERROR expected tuple struct or tuple variant, found unit variant `Alias::Unit` [E0164] +} diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr new file mode 100644 index 000000000..c9ac99ede --- /dev/null +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -0,0 +1,45 @@ +error[E0533]: expected value, found struct variant `Alias::Braced` + --> $DIR/incorrect-variant-form-through-alias-caught.rs:8:5 + | +LL | Alias::Braced; + | ^^^^^^^^^^^^^ not a value + +error[E0533]: expected unit struct, unit variant or constant, found struct variant `Alias::Braced` + --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:9 + | +LL | let Alias::Braced = panic!(); + | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant + +error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced` + --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 + | +LL | let Alias::Braced(..) = panic!(); + | ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error[E0618]: expected function, found enum variant `Alias::Unit` + --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5 + | +LL | enum Enum { Braced {}, Unit, Tuple() } + | ---- enum variant `Alias::Unit` defined here +... +LL | Alias::Unit(); + | ^^^^^^^^^^^-- + | | + | call expression requires function + | +help: `Alias::Unit` is a unit enum variant, and does not take parentheses to be constructed + | +LL - Alias::Unit(); +LL + Alias::Unit; + | + +error[E0164]: expected tuple struct or tuple variant, found unit variant `Alias::Unit` + --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:9 + | +LL | let Alias::Unit() = panic!(); + | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0164, E0533, E0618. +For more information about an error, try `rustc --explain E0164`. diff --git a/tests/ui/type-alias-enum-variants/issue-57866.rs b/tests/ui/type-alias-enum-variants/issue-57866.rs new file mode 100644 index 000000000..5e105b20a --- /dev/null +++ b/tests/ui/type-alias-enum-variants/issue-57866.rs @@ -0,0 +1,24 @@ +// check-pass + +enum Outer { + A(T) +} + +enum Inner { + A(i32) +} + +type OuterAlias = Outer; + +fn ice(x: OuterAlias) { + // Fine + match x { + OuterAlias::A(Inner::A(_)) => (), + } + // Not fine + match x { + OuterAlias::A(Inner::A(y)) => (), + } +} + +fn main() {} diff --git a/tests/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs b/tests/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs new file mode 100644 index 000000000..9c9eaab8d --- /dev/null +++ b/tests/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs @@ -0,0 +1,28 @@ +// In this regression test we check that a path pattern referring to a unit variant +// through a type alias is successful in inferring the generic argument. + +// check-pass + +enum Opt { + N, + S(T), +} + +type OptAlias = Opt; + +fn f1(x: OptAlias) { + match x { + OptAlias::N // We previously failed to infer `T` to `u8`. + => (), + _ => (), + } + + match x { + < + OptAlias<_> // And we failed to infer this type also. + >::N => (), + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs b/tests/ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs new file mode 100644 index 000000000..66fb8dd0d --- /dev/null +++ b/tests/ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs @@ -0,0 +1,26 @@ +// check-pass + +// Regression test for the issue #63151: +// Spurious unused field warning when matching variants under a `Self` scope +// +// This test checks that the `dead_code` lint properly inspects fields +// in struct patterns that use a type relative path. + +#![deny(dead_code)] + +enum Enum { + Variant { field: usize } +} + +impl Enum { + fn read_field(self) -> usize { + match self { + Self::Variant { field } => field + } + } +} + +fn main() { + let e = Enum::Variant { field: 42 }; + println!("{}", e.read_field()); +} diff --git a/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs b/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs new file mode 100644 index 000000000..872ece0c0 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs @@ -0,0 +1,14 @@ +// Check that a generic type for an `enum` admits type application +// on both the type constructor and the generic type's variant. +// +// Also check that a type alias to said generic type admits type application +// on the type constructor but *NOT* the variant. + +type Alias = Option; + +fn main() { + let _ = Option::::None; // OK + let _ = Option::None::; // OK (Lint in future!) + let _ = Alias::::None; // OK + let _ = Alias::None::; //~ ERROR type arguments are not allowed on this type +} diff --git a/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr b/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr new file mode 100644 index 000000000..51b1c8a10 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr @@ -0,0 +1,11 @@ +error[E0109]: type arguments are not allowed on this type + --> $DIR/no-type-application-on-aliased-enum-variant.rs:13:27 + | +LL | let _ = Alias::None::; + | ---- ^^ type argument not allowed + | | + | not allowed on this type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs b/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs new file mode 100644 index 000000000..11f4b05d0 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs @@ -0,0 +1,11 @@ +// Check that the compiler will resolve `::V` to the variant `V` in the type namespace +// but will reject this because `enum` variants do not exist in the type namespace. + +enum E { + V +} + +fn check() -> ::V {} +//~^ ERROR expected type, found variant `V` + +fn main() {} diff --git a/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr b/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr new file mode 100644 index 000000000..f190bfb69 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr @@ -0,0 +1,8 @@ +error: expected type, found variant `V` + --> $DIR/resolve-to-enum-variant-in-type-namespace-and-error.rs:8:15 + | +LL | fn check() -> ::V {} + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.rs b/tests/ui/type-alias-enum-variants/self-in-enum-definition.rs new file mode 100644 index 000000000..8dadd77fc --- /dev/null +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.rs @@ -0,0 +1,8 @@ +#[repr(u8)] +enum Alpha { + V1 = 41, + V2 = Self::V1 as u8 + 1, // OK; See #50072. + V3 = Self::V1 {} as u8 + 2, //~ ERROR cycle detected when simplifying constant +} + +fn main() {} diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr new file mode 100644 index 000000000..576fc6a4f --- /dev/null +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -0,0 +1,73 @@ +error[E0391]: cycle detected when simplifying constant for the type system `Alpha::V3::{constant#0}` + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `Alpha::V3::{constant#0}` for CTFE... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing MIR for `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires preparing `Alpha::V3::{constant#0}` for borrow checking... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `Alpha::V3::{constant#0}`... + --> $DIR/self-in-enum-definition.rs:5:10 + | +LL | V3 = Self::V1 {} as u8 + 2, + | ^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `Alpha`... + = note: ...which again requires simplifying constant for the type system `Alpha::V3::{constant#0}`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/self-in-enum-definition.rs:1:1 + | +LL | / #[repr(u8)] +LL | | enum Alpha { +LL | | V1 = 41, +LL | | V2 = Self::V1 as u8 + 1, // OK; See #50072. +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs b/tests/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs new file mode 100644 index 000000000..39677733d --- /dev/null +++ b/tests/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs @@ -0,0 +1,69 @@ +// run-pass + +// Check that it is possible to resolve, in the value namespace, +// to an `enum` variant through a type alias. This includes `Self`. +// Type qualified syntax `::Variant` also works when syntactically valid. + +#[derive(Debug, PartialEq, Eq)] +enum Foo { + Bar(i32), + Baz { i: i32 }, + Qux, +} + +type FooAlias = Foo; +type OptionAlias = Option; + +macro_rules! check_pat { + ($x:expr, $p:pat) => { + assert!(if let $p = $x { true } else { false }); + }; +} + +impl Foo { + fn bar() -> Self { + let x = Self::Bar(3); + assert_eq!(x, ::Bar(3)); + check_pat!(x, Self::Bar(3)); + x + } + + fn baz() -> Self { + let x = Self::Baz { i: 42 }; + check_pat!(x, Self::Baz { i: 42 }); + x + } + + fn qux() -> Self { + let x = Self::Qux; + assert_eq!(x, ::Qux); + check_pat!(x, Self::Qux); + check_pat!(x, ::Qux); + x + } +} + +fn main() { + let bar = Foo::Bar(1); + assert_eq!(bar, FooAlias::Bar(1)); + assert_eq!(bar, ::Bar(1)); + check_pat!(bar, FooAlias::Bar(1)); + + let baz = FooAlias::Baz { i: 2 }; + assert_eq!(baz, Foo::Baz { i: 2 }); + check_pat!(baz, FooAlias::Baz { i: 2 }); + + let qux = Foo::Qux; + assert_eq!(qux, FooAlias::Qux); + assert_eq!(qux, ::Qux); + check_pat!(qux, FooAlias::Qux); + check_pat!(qux, ::Qux); + + assert_eq!(Foo::bar(), Foo::Bar(3)); + assert_eq!(Foo::baz(), Foo::Baz { i: 42 }); + assert_eq!(Foo::qux(), Foo::Qux); + + let some = Option::Some(4); + assert_eq!(some, OptionAlias::Some(4)); + check_pat!(some, OptionAlias::Some(4)); +} diff --git a/tests/ui/type-alias-impl-trait/argument-types.rs b/tests/ui/type-alias-impl-trait/argument-types.rs new file mode 100644 index 000000000..185207b98 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/argument-types.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] +// check-pass +use std::fmt::Debug; + +type Foo = impl Debug; + +fn foo1(mut x: Foo) { + x = 22_u32; +} + +fn foo2(mut x: Foo) { + // no constraint on x +} + +fn foo3(x: Foo) { + println!("{:?}", x); +} + +fn foo_value() -> Foo { + 11_u32 +} + +fn main() { + foo3(foo_value()); +} diff --git a/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs b/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs new file mode 100644 index 000000000..703e3e869 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// build-pass + +trait T { type Item; } + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} diff --git a/tests/ui/type-alias-impl-trait/assoc-type-const.rs b/tests/ui/type-alias-impl-trait/assoc-type-const.rs new file mode 100644 index 000000000..0ade36daf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-const.rs @@ -0,0 +1,32 @@ +// Tests that we properly detect defining usages when using +// const generics in an associated opaque type +// check-pass + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt<'a, const C: usize> { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct {} + +trait MyTrait<'a, const C: usize> { + type MyItem; + const MY_CONST: usize; +} + +impl<'a, const C: usize> MyTrait<'a, C> for MyStruct { + type MyItem = u8; + const MY_CONST: usize = C; +} + +impl<'a, I, const C: usize> UnwrapItemsExt<'a, C> for I { + type Iter = impl MyTrait<'a, C>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct:: {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs new file mode 100644 index 000000000..3f34b00ec --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs @@ -0,0 +1,26 @@ +// Tests that we don't allow unconstrained lifetime parameters in impls when +// the lifetime is used in an associated opaque type. + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct {} + +trait MyTrait<'a> {} + +impl<'a> MyTrait<'a> for MyStruct {} + +impl<'a, I> UnwrapItemsExt for I { + //~^ ERROR the lifetime parameter `'a` is not constrained + type Iter = impl MyTrait<'a>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr new file mode 100644 index 000000000..e594dc577 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/assoc-type-lifetime-unconstrained.rs:17:6 + | +LL | impl<'a, I> UnwrapItemsExt for I { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs new file mode 100644 index 000000000..39f785d8c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime.rs @@ -0,0 +1,26 @@ +// Tests that we still detect defining usages when +// lifetimes are used in an associated opaque type +// check-pass + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt<'a> { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct {} + +trait MyTrait<'a> {} + +impl<'a> MyTrait<'a> for MyStruct {} + +impl<'a, I> UnwrapItemsExt<'a> for I { + type Iter = impl MyTrait<'a>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs b/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs new file mode 100644 index 000000000..42f07d49f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +// build-pass (FIXME(62277): could be check-pass?) + +trait Bar {} +struct Dummy; +impl Bar for Dummy {} + +trait Foo { + type Assoc: Bar; + fn foo() -> Self::Assoc; + fn bar() -> Self::Assoc; +} + +type Helper = impl Bar; + +impl Foo for i32 { + type Assoc = Helper; + fn foo() -> Helper { + Dummy + } + fn bar() -> Helper { + Dummy + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs new file mode 100644 index 000000000..962606508 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/associated-type-impl-trait-lifetime.rs @@ -0,0 +1,20 @@ +//check-pass + +#![feature(type_alias_impl_trait)] + +trait Trait { + type Opaque1; + type Opaque2; + fn constrain(self); +} + +impl<'a> Trait for &'a () { + type Opaque1 = impl Sized; + type Opaque2 = impl Sized + 'a; + fn constrain(self) { + let _: Self::Opaque1 = (); + let _: Self::Opaque2 = self; + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs new file mode 100644 index 000000000..a1584581e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +mod m { + type Foo = impl std::fmt::Debug; + + pub fn foo() -> Foo { + 22_u32 + } +} + +fn is_send(_: T) {} + +fn main() { + is_send(m::foo()); +} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs new file mode 100644 index 000000000..fc89b0e87 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +mod m { + use std::rc::Rc; + + type Foo = impl std::fmt::Debug; //~ NOTE appears within the type + //~^ within this `Foo` + //~| expansion of desugaring + + pub fn foo() -> Foo { + Rc::new(22_u32) + } +} + +fn is_send(_: T) {} +//~^ required by this bound +//~| required by a bound + +fn main() { + is_send(m::foo()); + //~^ ERROR: `Rc` cannot be sent between threads safely [E0277] + //~| NOTE cannot be sent + //~| NOTE required by a bound +} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr new file mode 100644 index 000000000..d7247302d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -0,0 +1,26 @@ +error[E0277]: `Rc` cannot be sent between threads safely + --> $DIR/auto-trait-leakage2.rs:21:13 + | +LL | type Foo = impl std::fmt::Debug; + | -------------------- within this `Foo` +... +LL | is_send(m::foo()); + | ------- ^^^^^^^^ `Rc` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Foo`, the trait `Send` is not implemented for `Rc` +note: required because it appears within the type `Foo` + --> $DIR/auto-trait-leakage2.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `is_send` + --> $DIR/auto-trait-leakage2.rs:16:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs new file mode 100644 index 000000000..5fb7a9473 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME This should compile, but it currently doesn't + +mod m { + type Foo = impl std::fmt::Debug; + //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391] + + pub fn foo() -> Foo { + 22_u32 + } + + pub fn bar() { + is_send(foo()); + } + + fn is_send(_: T) {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr new file mode 100644 index 000000000..1e9a45aac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr @@ -0,0 +1,22 @@ +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/auto-trait-leakage3.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/auto-trait-leakage3.rs:15:9 + | +LL | is_send(foo()); + | ^^^^^^^ + = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`... + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/auto-trait-leakage3.rs:6:1 + | +LL | mod m { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs b/tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs new file mode 100644 index 000000000..712ed5543 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/coherence_cross_crate_trait_decl.rs @@ -0,0 +1,9 @@ +pub trait SomeTrait {} + +impl SomeTrait for () {} + +// Adding this `impl` would cause errors in this crate's dependent, +// so it would be a breaking change. We explicitly don't add this impl, +// as the dependent crate already assumes this impl exists and thus already +// does not compile. +//impl SomeTrait for i32 {} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs b/tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs new file mode 100644 index 000000000..75d20a6fe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/collect_hidden_types.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +// edition:2018 + +use std::future::Future; + +pub trait Service { + type Future: Future; + fn call(&mut self, req: Request) -> Self::Future; +} + +// NOTE: the pub(crate) here is critical +pub(crate) fn new() -> () {} + +pub struct A; +impl Service<()> for A { + type Future = impl Future; + fn call(&mut self, _: ()) -> Self::Future { + async { new() } + } +} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs new file mode 100644 index 000000000..e7bca2231 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs @@ -0,0 +1,10 @@ +// Crate that exports an opaque `impl Trait` type. Used for testing cross-crate. + +#![crate_type = "rlib"] +#![feature(type_alias_impl_trait)] + +pub type Foo = impl std::fmt::Debug; + +pub fn foo() -> Foo { + 5 +} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs new file mode 100644 index 000000000..119f7df1f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs @@ -0,0 +1,20 @@ +// Crate that exports an opaque `impl Trait` type. Used for testing cross-crate. + +#![crate_type = "rlib"] +#![feature(type_alias_impl_trait)] + +pub trait View { + type Tmp: Iterator; + + fn test(&self) -> Self::Tmp; +} + +pub struct X; + +impl View for X { + type Tmp = impl Iterator; + + fn test(&self) -> Self::Tmp { + vec![1, 2, 3].into_iter() + } +} diff --git a/tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs b/tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs new file mode 100644 index 000000000..52802dd8f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs @@ -0,0 +1,2 @@ +pub trait ForeignTrait {} +pub struct ForeignType(pub T); diff --git a/tests/ui/type-alias-impl-trait/bound_reduction.rs b/tests/ui/type-alias-impl-trait/bound_reduction.rs new file mode 100644 index 000000000..b9b50f0b7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound_reduction.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(warnings)] +#![feature(type_alias_impl_trait)] + +fn main() { +} + +type Foo = impl std::fmt::Debug; + +trait Trait {} + +fn foo_desugared>(_: T) -> Foo { + (42, std::marker::PhantomData::) +} diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs new file mode 100644 index 000000000..0bcc9e002 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait TraitWithAssoc { + type Assoc; +} + +type Foo = impl Trait; + +trait Trait {} + +impl Trait for () {} + +fn foo_desugared(_: T) -> Foo { + () + //~^ ERROR expected generic type parameter, found `::Assoc` +} diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr new file mode 100644 index 000000000..3c259bd9e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `::Assoc` + --> $DIR/bound_reduction2.rs:16:5 + | +LL | type Foo = impl Trait; + | - this generic parameter must be used with a generic type parameter +... +LL | () + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs new file mode 100644 index 000000000..55b4dc8dc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs @@ -0,0 +1,19 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X = impl Clone; + +fn f(t: T) -> X { + t + //~^ ERROR the trait bound `T: Clone` is not satisfied +} + +fn g(o: Option>) -> Option> { + o.clone() +} + +fn main() { + g(None::>); +} diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr new file mode 100644 index 000000000..8678e9b33 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/bounds-are-checked-2.rs:9:5 + | +LL | t + | ^ the trait `Clone` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type X = impl Clone; + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs new file mode 100644 index 000000000..83d22161e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs @@ -0,0 +1,24 @@ +// Make sure that we check that impl trait types implement the traits that they +// claim to. + +#![feature(type_alias_impl_trait)] + +type X<'a> = impl Into<&'static str> + From<&'a str>; + +fn f<'a: 'static>(t: &'a str) -> X<'a> { + //~^ WARNING unnecessary lifetime parameter + t + //~^ ERROR non-defining opaque type use +} + +fn extend_lt<'a>(o: &'a str) -> &'static str { + X::<'_>::from(o).into() +} + +fn main() { + let r = { + let s = "abcdef".to_string(); + extend_lt(&s) + }; + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr new file mode 100644 index 000000000..920eef11d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr @@ -0,0 +1,19 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/bounds-are-checked.rs:8:6 + | +LL | fn f<'a: 'static>(t: &'a str) -> X<'a> { + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error: non-defining opaque type use in defining scope + --> $DIR/bounds-are-checked.rs:10:5 + | +LL | type X<'a> = impl Into<&'static str> + From<&'a str>; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | t + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/type-alias-impl-trait/closure_args.rs b/tests/ui/type-alias-impl-trait/closure_args.rs new file mode 100644 index 000000000..c5e7af81d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_args.rs @@ -0,0 +1,16 @@ +// check-pass + +// regression test for https://github.com/rust-lang/rust/issues/100800 + +#![feature(type_alias_impl_trait)] + +trait Anything {} +impl Anything for T {} +type Input = impl Anything; +fn run ()>(f: F, i: Input) { + f(i); +} + +fn main() { + run(|x: u32| {println!("{x}");}, 0); +} diff --git a/tests/ui/type-alias-impl-trait/closure_args2.rs b/tests/ui/type-alias-impl-trait/closure_args2.rs new file mode 100644 index 000000000..82386c280 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_args2.rs @@ -0,0 +1,23 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +trait Foo { + // This was reachable in https://github.com/rust-lang/rust/issues/100800 + fn foo(&self) { unreachable!() } +} +impl Foo for T {} + +struct B; +impl B { + fn foo(&self) {} +} + +type Input = impl Foo; +fn run1(f: F, i: Input) {f(i)} +fn run2(f: F, i: B) {f(i)} + +fn main() { + run1(|x: B| {x.foo()}, B); + run2(|x: B| {x.foo()}, B); +} diff --git a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs new file mode 100644 index 000000000..475f4724f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs @@ -0,0 +1,65 @@ +// When WF checking the hidden type in the ParamEnv of the opaque type, +// one complication arises when the hidden type is a closure/generator: +// the "parent_substs" of the type may reference lifetime parameters +// not present in the opaque type. +// These region parameters are not really useful in this check. +// So here we ignore them and replace them with fresh region variables. + +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// Basic test +mod test1 { + // Hidden type = Closure['_#0r] + type Opaque = impl Sized; + + fn define<'a: 'a>() -> Opaque { + || {} + } +} + +// the region vars cannot both be equal to `'static` or `'empty` +mod test2 { + trait Trait {} + + // Hidden type = Closure['a, '_#0r, '_#1r] + // Constraints = [('_#0r: 'a), ('a: '_#1r)] + type Opaque<'a> + where + &'a (): Trait, + = impl Sized + 'a; + + fn define<'a, 'x, 'y>() -> Opaque<'a> + where + &'a (): Trait, + 'x: 'a, + 'a: 'y, + { + || {} + } +} + +// the region var cannot be equal to `'a` or `'b` +mod test3 { + trait Trait {} + + // Hidden type = Closure['a, 'b, '_#0r] + // Constraints = [('_#0r: 'a), ('_#0r: 'b)] + type Opaque<'a, 'b> + where + (&'a (), &'b ()): Trait, + = impl Sized + 'a + 'b; + + fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> + where + (&'a (), &'b ()): Trait, + 'x: 'a, + 'x: 'b, + { + || {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs new file mode 100644 index 000000000..53974dbb3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs @@ -0,0 +1,65 @@ +// If the hidden type is a closure, we require the "outlives" bounds that appear on the +// defining site to also appear on the opaque type. +// +// It's not clear if this is the desired behavior but at least +// it's consistent and has no back-compat risk. + +// check-fail + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// requires `'a: 'b` bound +mod test1 { + type Opaque<'a, 'b> = impl Sized + 'a + 'b; + //~^ ERROR lifetime bound not satisfied + + fn define<'a, 'b>() -> Opaque<'a, 'b> + where + 'a: 'b, + { + || {} + } +} + +// Same as the above but through indirection `'x` +mod test2 { + type Opaque<'a, 'b> = impl Sized + 'a + 'b; + //~^ ERROR cannot infer an appropriate lifetime + + fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> + where + 'a: 'x, + 'x: 'b, + { + || {} + } +} + +// fixed version of the above +mod test2_fixed { + type Opaque<'a: 'b, 'b> = impl Sized + 'a + 'b; + + fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> + where + 'a: 'x, + 'x: 'b, + { + || {} + } +} + +// requires `T: 'static` +mod test3 { + type Opaque = impl Sized; + //~^ ERROR the parameter type `T` may not live long enough + + fn define() -> Opaque + where + T: 'static, + { + || {} + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr new file mode 100644 index 000000000..ae6462bb6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -0,0 +1,64 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/closure_wf_outlives.rs:14:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'a` as defined here + --> $DIR/closure_wf_outlives.rs:14:17 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ +note: but lifetime parameter must outlive the lifetime `'b` as defined here + --> $DIR/closure_wf_outlives.rs:14:21 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ + +error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements + --> $DIR/closure_wf_outlives.rs:27:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/closure_wf_outlives.rs:27:17 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/closure_wf_outlives.rs:27:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ +note: but, the lifetime must be valid for the lifetime `'b` as defined here... + --> $DIR/closure_wf_outlives.rs:27:21 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^ +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/closure_wf_outlives.rs:27:27 + | +LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/closure_wf_outlives.rs:54:22 + | +LL | type Opaque = impl Sized; + | ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/closure_wf_outlives.rs:59:12 + | +LL | T: 'static, + | ^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | type Opaque = impl Sized; + | +++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0310, E0478, E0495. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/closures_in_branches.rs b/tests/ui/type-alias-impl-trait/closures_in_branches.rs new file mode 100644 index 000000000..7bb490bbe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closures_in_branches.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::ops::FnOnce(String) -> usize; + +fn foo(b: bool) -> Foo { + if b { + |x| x.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + + +type Foo1 = impl std::ops::FnOnce(String) -> usize; +fn foo1(b: bool) -> Foo1 { + |x| x.len() +} + +fn bar(b: bool) -> impl std::ops::FnOnce(String) -> usize { + if b { + |x| x.len() //~ ERROR type annotations needed + } else { + panic!() + } +} + +fn bar1(b: bool) -> impl std::ops::FnOnce(String) -> usize { + |x| x.len() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/closures_in_branches.stderr b/tests/ui/type-alias-impl-trait/closures_in_branches.stderr new file mode 100644 index 000000000..9cc15f14a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/closures_in_branches.stderr @@ -0,0 +1,25 @@ +error[E0282]: type annotations needed + --> $DIR/closures_in_branches.rs:7:10 + | +LL | |x| x.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |x: /* Type */| x.len() + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/closures_in_branches.rs:21:10 + | +LL | |x| x.len() + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | |x: /* Type */| x.len() + | ++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs new file mode 100644 index 000000000..077a31494 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence.rs @@ -0,0 +1,17 @@ +// aux-build:foreign-crate.rs +#![feature(type_alias_impl_trait)] + +extern crate foreign_crate; + +trait LocalTrait {} +impl LocalTrait for foreign_crate::ForeignType {} + +type AliasOfForeignType = impl LocalTrait; +fn use_alias(val: T) -> AliasOfForeignType { + foreign_crate::ForeignType(val) +} + +impl foreign_crate::ForeignTrait for AliasOfForeignType {} +//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr new file mode 100644 index 000000000..00b0dbbb5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence.rs:14:1 + | +LL | impl foreign_crate::ForeignTrait for AliasOfForeignType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- + | | | + | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs b/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs new file mode 100644 index 000000000..a63e0a1ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs @@ -0,0 +1,24 @@ +// aux-build: coherence_cross_crate_trait_decl.rs +// This test ensures that adding an `impl SomeTrait for i32` within +// `coherence_cross_crate_trait_decl` is not a breaking change, by +// making sure that even without such an impl this test fails to compile. + +#![feature(type_alias_impl_trait)] + +extern crate coherence_cross_crate_trait_decl; + +use coherence_cross_crate_trait_decl::SomeTrait; + +trait OtherTrait {} + +type Alias = impl SomeTrait; + +fn constrain() -> Alias { + () +} + +impl OtherTrait for Alias {} +impl OtherTrait for i32 {} +//~^ ERROR: conflicting implementations of trait `OtherTrait` for type `Alias` + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr new file mode 100644 index 000000000..63a3ce29c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `OtherTrait` for type `Alias` + --> $DIR/coherence_cross_crate.rs:21:1 + | +LL | impl OtherTrait for Alias {} + | ------------------------- first implementation here +LL | impl OtherTrait for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias` + | + = note: upstream crates may add a new impl of trait `coherence_cross_crate_trait_decl::SomeTrait` for type `i32` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/coherence_generalization.rs b/tests/ui/type-alias-impl-trait/coherence_generalization.rs new file mode 100644 index 000000000..5c9ad9498 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence_generalization.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Opaque = impl Sized; +fn foo() -> Opaque { + () +} + +impl Trait for (T, V, V, u32) {} +impl Trait for (Opaque, V, i32, V) {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/collect_hidden_types.rs b/tests/ui/type-alias-impl-trait/collect_hidden_types.rs new file mode 100644 index 000000000..e78f178e4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/collect_hidden_types.rs @@ -0,0 +1,22 @@ +// aux-build:collect_hidden_types.rs +use collect_hidden_types::Service; +use std::future::Future; +use std::pin::Pin; +use std::task::Context; + +// build-pass + +// edition:2018 + +extern crate collect_hidden_types; + +fn broken(mut a: collect_hidden_types::A, cx: &mut Context<'_>) { + let mut fut = a.call(()); + let _ = unsafe { Pin::new_unchecked(&mut fut) }.poll(cx); +} + +pub async fn meeb(cx: &mut Context<'_>) { + broken(collect_hidden_types::A, cx); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.rs b/tests/ui/type-alias-impl-trait/constrain_inputs.rs new file mode 100644 index 000000000..03fb64b7b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +mod lifetime_params { + type Ty<'a> = impl Sized; + fn defining(s: &str) -> Ty<'_> { s } + fn execute(ty: Ty<'_>) -> &str { todo!() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + + type BadFnSig = fn(Ty<'_>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime +} + +mod lifetime_params_2 { + type Ty<'a> = impl FnOnce() -> &'a str; + fn defining(s: &str) -> Ty<'_> { move || s } + fn execute(ty: Ty<'_>) -> &str { ty() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types +} + +// regression test for https://github.com/rust-lang/rust/issues/97104 +mod type_params { + type Ty = impl Sized; + fn define(s: T) -> Ty { s } + + type BadFnSig = fn(Ty<&str>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr new file mode 100644 index 000000000..93953fd06 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -0,0 +1,58 @@ +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:6:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { todo!() } + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:9:35 + | +LL | type BadFnSig = fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:11:42 + | +LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:18:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { ty() } + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:27:37 + | +LL | type BadFnSig = fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:29:44 + | +LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0581, E0582. +For more information about an error, try `rustc --explain E0581`. diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs new file mode 100644 index 000000000..3bae0f173 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Static: 'static {} +impl Static for () {} + +type Gal = impl Static; +fn _defining() -> Gal {} + +trait Callable { type Output; } + +/// We can infer `>::Output: 'static`, +/// because we know `C: 'static` and `Arg: 'static`, +fn box_str(s: C::Output) -> Box + 'static> +where + Arg: Static, + C: ?Sized + Callable + 'static, + C::Output: AsRef, +{ + Box::new(s) +} + +fn extend_lifetime(s: &str) -> Box + 'static> { + type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + //~^ ERROR binding for associated type `Output` references lifetime `'a` + box_str::(s) +} + +fn main() { + let extended = extend_lifetime(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); +} diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr new file mode 100644 index 000000000..d5fc46cb1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/constrain_inputs_unsound.rs:23:58 + | +LL | type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. diff --git a/tests/ui/type-alias-impl-trait/cross_crate_ice.rs b/tests/ui/type-alias-impl-trait/cross_crate_ice.rs new file mode 100644 index 000000000..c30608176 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_crate_ice.rs @@ -0,0 +1,16 @@ +// aux-build:cross_crate_ice.rs +// build-pass (FIXME(62277): could be check-pass?) + +extern crate cross_crate_ice; + +struct Bar(cross_crate_ice::Foo); + +impl Bar { + fn zero(&self) -> &cross_crate_ice::Foo { + &self.0 + } +} + +fn main() { + let _ = cross_crate_ice::foo(); +} diff --git a/tests/ui/type-alias-impl-trait/cross_crate_ice2.rs b/tests/ui/type-alias-impl-trait/cross_crate_ice2.rs new file mode 100644 index 000000000..3a7e49026 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_crate_ice2.rs @@ -0,0 +1,11 @@ +// aux-build:cross_crate_ice2.rs +// build-pass (FIXME(62277): could be check-pass?) + +extern crate cross_crate_ice2; + +use cross_crate_ice2::View; + +fn main() { + let v = cross_crate_ice2::X; + v.test(); +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference.rs b/tests/ui/type-alias-impl-trait/cross_inference.rs new file mode 100644 index 000000000..dafaf40a6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = (1u32, 2u32); + let x: (_, _) = foo; + println!("{:?}", x); +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs new file mode 100644 index 000000000..9a50c0f98 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -0,0 +1,9 @@ +// compile-flags: --edition=2021 +// check-pass +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = (1u32, 2u32); + let (a, b): (u32, u32) = foo; +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs new file mode 100644 index 000000000..b929122a6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -0,0 +1,13 @@ +// compile-flags: --edition=2021 --crate-type=lib +// rustc-env:RUST_BACKTRACE=0 +// check-pass + +// tracked in https://github.com/rust-lang/rust/issues/96572 + +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = (1u32, 2u32); + let (a, b) = foo; // this line used to make the code fail +} diff --git a/tests/ui/type-alias-impl-trait/cross_inference_rpit.rs b/tests/ui/type-alias-impl-trait/cross_inference_rpit.rs new file mode 100644 index 000000000..f6affbf17 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/cross_inference_rpit.rs @@ -0,0 +1,14 @@ +// check-pass + +fn foo(b: bool) -> impl Copy { + if b { + return (5,6) + } + let x: (_, _) = foo(true); + println!("{:?}", x); + (1u32, 2u32) +} + +fn main() { + foo(false); +} diff --git a/tests/ui/type-alias-impl-trait/declared_but_never_defined.rs b/tests/ui/type-alias-impl-trait/declared_but_never_defined.rs new file mode 100644 index 000000000..6febd0715 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_never_defined.rs @@ -0,0 +1,6 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +// declared but never defined +type Bar = impl std::fmt::Debug; //~ ERROR unconstrained opaque type diff --git a/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr new file mode 100644 index 000000000..60bc24320 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/declared_but_never_defined.rs:6:12 + | +LL | type Bar = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs new file mode 100644 index 000000000..5bda5f0fc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +mod boo { + // declared in module but not defined inside of it + pub type Boo = impl ::std::fmt::Debug; //~ ERROR unconstrained opaque type +} + +fn bomp() -> boo::Boo { + "" + //~^ mismatched types +} diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr new file mode 100644 index 000000000..fbfa0ccf1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr @@ -0,0 +1,25 @@ +error: unconstrained opaque type + --> $DIR/declared_but_not_defined_in_scope.rs:7:20 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Boo` must be used in combination with a concrete type within the same module + +error[E0308]: mismatched types + --> $DIR/declared_but_not_defined_in_scope.rs:11:5 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ---------------------- the expected opaque type +... +LL | fn bomp() -> boo::Boo { + | -------- expected `Boo` because of return type +LL | "" + | ^^ expected opaque type, found `&str` + | + = note: expected opaque type `Boo` + found reference `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs new file mode 100644 index 000000000..8b51f5571 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// test that the type alias impl trait defining use is in a submodule + +fn main() {} + +type Foo = impl std::fmt::Display; +type Bar = impl std::fmt::Display; + +mod foo { + pub fn foo() -> super::Foo { + "foo" + } + + pub mod bar { + pub fn bar() -> crate::Bar { + 1 + } + } +} diff --git a/tests/ui/type-alias-impl-trait/destructuring.rs b/tests/ui/type-alias-impl-trait/destructuring.rs new file mode 100644 index 000000000..b752e5838 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/destructuring.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +// issue: https://github.com/rust-lang/rust/issues/104551 + +fn main() { + type T = impl Sized; + let (_a, _b): T = (1u32, 2u32); +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_defining_uses.rs new file mode 100644 index 000000000..4505c4d95 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar() -> Foo { + 42i32 + //~^ ERROR concrete type differs from previous +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr new file mode 100644 index 000000000..a8b4cd7af --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_defining_uses.rs:13:5 + | +LL | 42i32 + | ^^^^^ expected `&'static str`, got `i32` + | +note: previous use here + --> $DIR/different_defining_uses.rs:9:5 + | +LL | "" + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs new file mode 100644 index 000000000..0b8157fe3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar() -> Foo { //~ ERROR: concrete type differs from previous defining opaque type use + panic!() +} + +fn boo() -> Foo { + loop {} +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr new file mode 100644 index 000000000..09dadb0af --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_defining_uses_never_type.rs:12:13 + | +LL | fn bar() -> Foo { + | ^^^ expected `&'static str`, got `()` + | +note: previous use here + --> $DIR/different_defining_uses_never_type.rs:9:5 + | +LL | "" + | ^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs new file mode 100644 index 000000000..8549687ea --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs @@ -0,0 +1,44 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![feature(type_alias_impl_trait)] + +fn main() {} + +// two definitions with different types +type Foo = impl std::fmt::Debug; + +fn foo() -> Foo { + "" +} + +fn bar(arg: bool) -> Foo { + if arg { + panic!() + } else { + "bar" + } +} + +fn boo(arg: bool) -> Foo { + if arg { + loop {} + } else { + "boo" + } +} + +fn bar2(arg: bool) -> Foo { + if arg { + "bar2" + } else { + panic!() + } +} + +fn boo2(arg: bool) -> Foo { + if arg { + "boo2" + } else { + loop {} + } +} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs new file mode 100644 index 000000000..bc827a8f2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +type Tait = impl Sized; + +struct One; +fn one() -> Tait { One } + +struct Two(T); +fn two() -> Tait { Two::<()>(todo!()) } +//~^ ERROR concrete type differs from previous defining opaque type use + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr new file mode 100644 index 000000000..146a57cbb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_defining_uses_never_type3.rs:9:13 + | +LL | fn two() -> Tait { Two::<()>(todo!()) } + | ^^^^ expected `One`, got `Two<()>` + | +note: previous use here + --> $DIR/different_defining_uses_never_type3.rs:6:20 + | +LL | fn one() -> Tait { One } + | ^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs new file mode 100644 index 000000000..5f75fdc71 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type OneLifetime<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { + a +} + +fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> { + b + //~^ ERROR: concrete type differs from previous defining opaque type use +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr new file mode 100644 index 000000000..546598e8a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/different_lifetimes_defining_uses.rs:15:5 + | +LL | b + | ^ expected `&'a u32`, got `&'b u32` + | +note: previous use here + --> $DIR/different_lifetimes_defining_uses.rs:11:5 + | +LL | a + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/fallback.rs b/tests/ui/type-alias-impl-trait/fallback.rs new file mode 100644 index 000000000..d8cf7d71f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/fallback.rs @@ -0,0 +1,28 @@ +// Tests that we correctly handle opaque types being used opaquely, +// even within their defining scope. +// +#![feature(type_alias_impl_trait)] + +type Foo = impl Copy; + +enum Wrapper { + First(T), + Second +} + +// This method constrains `Foo` to be `bool` +fn constrained_foo() -> Foo { + true +} + + +// This method does not constrain `Foo`. +// Per RFC 2071, function bodies may either +// fully constrain an opaque type, or place no +// constraints on it. +fn unconstrained_foo() -> Wrapper { + Wrapper::Second + //~^ ERROR: type annotations needed +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/fallback.stderr b/tests/ui/type-alias-impl-trait/fallback.stderr new file mode 100644 index 000000000..e767bfdb0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/fallback.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed + --> $DIR/fallback.rs:24:5 + | +LL | fn unconstrained_foo() -> Wrapper { + | ------------ type must be known at this point +LL | Wrapper::Second + | ^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Wrapper` + | + = note: cannot satisfy `_: Copy` +help: consider specifying the generic argument + | +LL | Wrapper::::Second + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/field-types.rs b/tests/ui/type-alias-impl-trait/field-types.rs new file mode 100644 index 000000000..d99ed5812 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/field-types.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// check-pass + +use std::fmt::Debug; + +type Foo = impl Debug; + +struct Bar { + foo: Foo, +} + +fn bar() -> Bar { + Bar { foo: "foo" } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/future.rs b/tests/ui/type-alias-impl-trait/future.rs new file mode 100644 index 000000000..56323216e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/future.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] + +// edition:2021 +// compile-flags: --crate-type=lib + +use std::future::Future; + +trait Bar { + fn bar(&self); +} + +type FooFuture = impl Future; + +fn foo(bar: B) -> FooFuture { + async move { bar.bar() } + //~^ ERROR: the trait bound `B: Bar` is not satisfied +} + +pub fn mainish(ctx: &mut std::task::Context) { + let boom: FooFuture = unsafe { core::mem::zeroed() }; + Box::pin(boom).as_mut().poll(ctx); +} diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr new file mode 100644 index 000000000..7e76c120a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/future.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/future.rs:15:5 + | +LL | async move { bar.bar() } + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `foo` + --> $DIR/future.rs:14:11 + | +LL | fn foo(bar: B) -> FooFuture { + | ^^^ required by this bound in `foo` +help: consider restricting type parameter `B` + | +LL | type FooFuture = impl Future; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs new file mode 100644 index 000000000..8b683ad28 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type MyIter = impl Iterator; + +fn my_iter(t: T) -> MyIter { + std::iter::once(t) +} + +fn my_iter2(t: T) -> MyIter { + Some(t).into_iter() + //~^ ERROR concrete type differs from previous +} diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr new file mode 100644 index 000000000..47ac33462 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_different_defining_uses.rs:12:5 + | +LL | Some(t).into_iter() + | ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once`, got `std::option::IntoIter` + | +note: previous use here + --> $DIR/generic_different_defining_uses.rs:8:5 + | +LL | std::iter::once(t) + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs new file mode 100644 index 000000000..9d938a616 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn one<'a>(t: &'a ()) -> Two<'a, 'a> { + t + //~^ ERROR non-defining opaque type use +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr new file mode 100644 index 000000000..72e1ef4b4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr @@ -0,0 +1,14 @@ +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_lifetime_param.rs:12:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_lifetime_param.rs:9:10 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + | ^^ ^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs new file mode 100644 index 000000000..80462f8ac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type TwoTys = impl Debug; + + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; + +type TwoConsts = impl Debug; + + +fn one_ty(t: T) -> TwoTys { + t + //~^ ERROR non-defining opaque type use in defining scope +} + +fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> { + t + //~^ ERROR non-defining opaque type use in defining scope +} + +fn one_const(t: *mut [u8; N]) -> TwoConsts { + t + //~^ ERROR non-defining opaque type use in defining scope +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr new file mode 100644 index 000000000..98e4bfea1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr @@ -0,0 +1,38 @@ +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:21:5 + | +LL | t + | ^ + | +note: type used multiple times + --> $DIR/generic_duplicate_param_use.rs:8:13 + | +LL | type TwoTys = impl Debug; + | ^ ^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:26:5 + | +LL | t + | ^ + | +note: lifetime used multiple times + --> $DIR/generic_duplicate_param_use.rs:15:19 + | +LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>; + | ^^ ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_duplicate_param_use.rs:31:5 + | +LL | t + | ^ + | +note: constant used multiple times + --> $DIR/generic_duplicate_param_use.rs:17:16 + | +LL | type TwoConsts = impl Debug; + | ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs new file mode 100644 index 000000000..c17d595db --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two = impl Debug; + +fn two(t: T, _: U) -> Two { + (t, 4u32) +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs new file mode 100644 index 000000000..201535efe --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two = impl Debug; + +fn two(t: T, _: U) -> Two { + t + //~^ ERROR `T` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr new file mode 100644 index 000000000..3dbfff745 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -0,0 +1,14 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use2.rs:11:5 + | +LL | t + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs new file mode 100644 index 000000000..e7a25fc72 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two = impl Debug; + +fn two(t: T, _: U) -> Two { + t + //~^ ERROR `T` doesn't implement `Debug` +} + +fn three(_: T, u: U) -> Two { + u + //~^ ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr new file mode 100644 index 000000000..7bec38220 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -0,0 +1,25 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use3.rs:11:5 + | +LL | t + | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use3.rs:16:5 + | +LL | u + | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs new file mode 100644 index 000000000..d1e5a0f01 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two = impl Debug; + +fn three(_: T, u: U) -> Two { + u + //~^ ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr new file mode 100644 index 000000000..21a5369d9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -0,0 +1,14 @@ +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use4.rs:11:5 + | +LL | u + | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs new file mode 100644 index 000000000..3bd1dda63 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two = impl Debug; + +fn two(t: T, u: U) -> Two { + (t, u) + //~^ ERROR `T` doesn't implement `Debug` + //~| ERROR `U` doesn't implement `Debug` +} + +fn three(t: T, u: U) -> Two { + (u, t) + //~^ ERROR `T` doesn't implement `Debug` + //~| ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr new file mode 100644 index 000000000..586ea8234 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -0,0 +1,51 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:11:5 + | +LL | (t, u) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, U)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:11:5 + | +LL | (t, u) + | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, U)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:17:5 + | +LL | (u, t) + | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use5.rs:17:5 + | +LL | (u, t) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs new file mode 100644 index 000000000..5120925e5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +// test that unused generic parameters are ok +type Two = impl Debug; + +fn two(t: T, u: U) -> Two { + (t, t) + //~^ ERROR `T` doesn't implement `Debug` +} + +fn three(t: T, u: U) -> Two { + (u, t) + //~^ ERROR `T` doesn't implement `Debug` + //~| ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr new file mode 100644 index 000000000..cb162d382 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -0,0 +1,39 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:11:5 + | +LL | (t, t) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, T)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:16:5 + | +LL | (u, t) + | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use6.rs:16:5 + | +LL | (u, t) + | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, T)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs new file mode 100644 index 000000000..feebf81ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two = impl Debug; + +fn two(t: T, u: U) -> Two { + (t, t) +} + +fn three(t: T, t2: T, u: U) -> Two { + (t, t2) +} + +fn four(t: T, t2: T, u: U, v: V) -> Two { + (t, t2) +} + +fn five(x: X, y: Y, y2: Y) -> Two { + (y, y2) +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs new file mode 100644 index 000000000..3a4b5047b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two = impl Debug; + +fn two(t: T, _: U) -> Two { + (t, 4u32) + //~^ ERROR `T` doesn't implement `Debug` +} + +fn three(_: T, u: U) -> Two { + (u, 4u32) + //~^ ERROR `U` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr new file mode 100644 index 000000000..14cbfb380 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -0,0 +1,27 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use8.rs:10:5 + | +LL | (t, 4u32) + | ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, u32)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use8.rs:15:5 + | +LL | (u, 4u32) + | ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(U, u32)` to implement `Debug` +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs new file mode 100644 index 000000000..6afcdfe4d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two = impl Debug; + +trait Foo { + type Bar: Debug; + const BAR: Self::Bar; +} + +fn two(t: T, u: U) -> Two { + (t, u, T::BAR) + //~^ ERROR the trait bound `A: Foo` is not satisfied + //~| ERROR `A` doesn't implement `Debug` + //~| ERROR `B` doesn't implement `Debug` +} + +fn three(t: T, u: U) -> Two { + (t, u, 42) + //~^ ERROR `A` doesn't implement `Debug` + //~| ERROR `B` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr new file mode 100644 index 000000000..722693e42 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -0,0 +1,62 @@ +error[E0277]: the trait bound `A: Foo` is not satisfied + --> $DIR/generic_duplicate_param_use9.rs:15:5 + | +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` + | +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | +++++ + +error[E0277]: `A` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:15:5 + | +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, _)` to implement `Debug` +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `B` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:15:5 + | +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, _)` to implement `Debug` +help: consider restricting type parameter `B` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `A` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:22:5 + | +LL | (t, u, 42) + | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, i32)` to implement `Debug` +help: consider restricting type parameter `A` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: `B` doesn't implement `Debug` + --> $DIR/generic_duplicate_param_use9.rs:22:5 + | +LL | (t, u, 42) + | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(A, B, i32)` to implement `Debug` +help: consider restricting type parameter `B` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs new file mode 100644 index 000000000..106efefba --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Region<'a> = impl std::fmt::Debug + 'a; + + +fn region<'b>(a: &'b ()) -> Region<'b> { + a +} diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs new file mode 100644 index 000000000..f5045d382 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type OneTy = impl Debug; + +type OneLifetime<'a> = impl Debug; + +type OneConst = impl Debug; + +// Not defining uses, because they doesn't define *all* possible generics. + +fn concrete_ty() -> OneTy { + 5u32 + //~^ ERROR expected generic type parameter, found `u32` +} + +fn concrete_lifetime() -> OneLifetime<'static> { + 6u32 + //~^ ERROR non-defining opaque type use in defining scope +} + +fn concrete_const() -> OneConst<{ 123 }> { + 7u32 + //~^ ERROR expected generic constant parameter, found `123` +} diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr new file mode 100644 index 000000000..564648630 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr @@ -0,0 +1,30 @@ +error[E0792]: expected generic type parameter, found `u32` + --> $DIR/generic_nondefining_use.rs:16:5 + | +LL | type OneTy = impl Debug; + | - this generic parameter must be used with a generic type parameter +... +LL | 5u32 + | ^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/generic_nondefining_use.rs:21:5 + | +LL | type OneLifetime<'a> = impl Debug; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +... +LL | 6u32 + | ^^^^ + +error[E0792]: expected generic constant parameter, found `123` + --> $DIR/generic_nondefining_use.rs:26:5 + | +LL | type OneConst = impl Debug; + | -------------- this generic parameter must be used with a generic constant parameter +... +LL | 7u32 + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.rs b/tests/ui/type-alias-impl-trait/generic_not_used.rs new file mode 100644 index 000000000..c70f473cf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_not_used.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type WrongGeneric = impl 'static; +//~^ ERROR: at least one trait must be specified + +fn wrong_generic(_: U, v: V) -> WrongGeneric { + v + //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list +} diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.stderr b/tests/ui/type-alias-impl-trait/generic_not_used.stderr new file mode 100644 index 000000000..fd720239a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_not_used.stderr @@ -0,0 +1,14 @@ +error: at least one trait must be specified + --> $DIR/generic_not_used.rs:5:33 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ + +error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/generic_not_used.rs:9:5 + | +LL | v + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs new file mode 100644 index 000000000..d3e169a70 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +fn main() { + let y = 42; + let x = wrong_generic(&y); + let z: i32 = x; + //~^ ERROR expected generic type parameter, found `&'static i32 +} + +type WrongGeneric = impl 'static; +//~^ ERROR: at least one trait must be specified + +fn wrong_generic(t: T) -> WrongGeneric { + t + //~^ ERROR the parameter type `T` may not live long enough +} diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr new file mode 100644 index 000000000..19115fd28 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -0,0 +1,30 @@ +error: at least one trait must be specified + --> $DIR/generic_type_does_not_live_long_enough.rs:10:24 + | +LL | type WrongGeneric = impl 'static; + | ^^^^^^^^^^^^ + +error[E0792]: expected generic type parameter, found `&'static i32` + --> $DIR/generic_type_does_not_live_long_enough.rs:6:18 + | +LL | let z: i32 = x; + | ^ +... +LL | type WrongGeneric = impl 'static; + | - this generic parameter must be used with a generic type parameter + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/generic_type_does_not_live_long_enough.rs:14:5 + | +LL | t + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn wrong_generic(t: T) -> WrongGeneric { + | +++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0310, E0792. +For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.rs b/tests/ui/type-alias-impl-trait/generic_underconstrained.rs new file mode 100644 index 000000000..d87a25aad --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait Trait {} +type Underconstrained = impl Send; + +// no `Trait` bound +fn underconstrain(_: T) -> Underconstrained { + //~^ ERROR the trait bound `T: Trait` + unimplemented!() +} diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr new file mode 100644 index 000000000..c73288329 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/generic_underconstrained.rs:9:31 + | +LL | fn underconstrain(_: T) -> Underconstrained { + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +note: required by a bound in `Underconstrained` + --> $DIR/generic_underconstrained.rs:6:26 + | +LL | type Underconstrained = impl Send; + | ^^^^^ required by this bound in `Underconstrained` +help: consider restricting type parameter `T` + | +LL | fn underconstrain(_: T) -> Underconstrained { + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs b/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs new file mode 100644 index 000000000..8adc0bf32 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +type Underconstrained = impl Send; + +// not a defining use, because it doesn't define *all* possible generics +fn underconstrained(_: U) -> Underconstrained { + //~^ ERROR `U` doesn't implement `Debug` + 5u32 +} + +type Underconstrained2 = impl Send; + +// not a defining use, because it doesn't define *all* possible generics +fn underconstrained2(_: U, _: V) -> Underconstrained2 { + //~^ ERROR `V` doesn't implement `Debug` + 5u32 +} diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr new file mode 100644 index 000000000..d77d978aa --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -0,0 +1,35 @@ +error[E0277]: `U` doesn't implement `Debug` + --> $DIR/generic_underconstrained2.rs:8:33 + | +LL | fn underconstrained(_: U) -> Underconstrained { + | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Underconstrained` + --> $DIR/generic_underconstrained2.rs:5:26 + | +LL | type Underconstrained = impl Send; + | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained` +help: consider restricting type parameter `U` + | +LL | fn underconstrained(_: U) -> Underconstrained { + | +++++++++++++++++ + +error[E0277]: `V` doesn't implement `Debug` + --> $DIR/generic_underconstrained2.rs:16:43 + | +LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { + | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Underconstrained2` + --> $DIR/generic_underconstrained2.rs:13:27 + | +LL | type Underconstrained2 = impl Send; + | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained2` +help: consider restricting type parameter `V` + | +LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs new file mode 100644 index 000000000..851c2f66c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs @@ -0,0 +1,17 @@ +// Ensure that we don't ICE if associated type impl trait is used in an impl +// with an unconstrained type parameter. + +#![feature(type_alias_impl_trait)] + +trait X { + type I; + fn f() -> Self::I; +} + +impl X for () { + //~^ ERROR the type parameter `T` is not constrained + type I = impl Sized; + fn f() -> Self::I {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr new file mode 100644 index 000000000..8cf8fb1d1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/impl-with-unconstrained-param.rs:11:6 + | +LL | impl X for () { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs new file mode 100644 index 000000000..0efbd1c2b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +trait Foo { + type Assoc; +} + +impl Foo for i32 { + type Assoc = u32; +} +type ImplTrait = impl Sized; +fn constrain() -> ImplTrait { + 1u64 +} +impl Foo for i64 { + type Assoc = ImplTrait; +} + +trait Bar {} + +impl Bar<::Assoc> for T {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs new file mode 100644 index 000000000..3f1a9d12b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs @@ -0,0 +1,33 @@ +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +impl Foo for i32 {} + +type Bar = impl std::fmt::Debug; +fn defining_use() -> Bar { + 42 +} + +trait Bop {} + +impl Bop for Bar<()> {} + +// If the hidden type is the same, this is effectively a second impl for the same type. +impl Bop for Bar {} +//~^ ERROR conflicting implementations + +type Barr = impl std::fmt::Debug; +fn defining_use2() -> Barr { + 42 +} + +// Even completely different opaque types must conflict. +impl Bop for Barr {} +//~^ ERROR conflicting implementations + +// And obviously the hidden type must conflict, too. +impl Bop for i32 {} +//~^ ERROR conflicting implementations + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr new file mode 100644 index 000000000..aaf75cc3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -0,0 +1,30 @@ +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` + --> $DIR/impl_trait_for_same_tait.rs:17:1 + | +LL | impl Bop for Bar<()> {} + | -------------------- first implementation here +... +LL | impl Bop for Bar {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` + --> $DIR/impl_trait_for_same_tait.rs:26:1 + | +LL | impl Bop for Bar<()> {} + | -------------------- first implementation here +... +LL | impl Bop for Barr {} + | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` + --> $DIR/impl_trait_for_same_tait.rs:30:1 + | +LL | impl Bop for Bar<()> {} + | -------------------- first implementation here +... +LL | impl Bop for i32 {} + | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs new file mode 100644 index 000000000..9f32c5d88 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs @@ -0,0 +1,21 @@ +// compile-flags: --crate-type=lib +// check-pass + +#![feature(type_alias_impl_trait)] +type Alias = impl Sized; + +fn constrain() -> Alias { + 1i32 +} + +trait HideIt { + type Assoc; +} + +impl HideIt for () { + type Assoc = Alias; +} + +pub trait Yay {} + +impl Yay for <() as HideIt>::Assoc {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs new file mode 100644 index 000000000..8ec20acef --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; +pub trait Yay { } +impl Yay for Foo { } + +fn foo() { + is_yay::(); //~ ERROR: the trait bound `u32: Yay` is not satisfied + is_debug::(); // OK + is_yay::(); // OK + is_debug::(); // OK +} + +fn is_yay() { } +fn is_debug() { } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr new file mode 100644 index 000000000..1c83105a1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `u32: Yay` is not satisfied + --> $DIR/impl_trait_for_tait_bound.rs:10:14 + | +LL | is_yay::(); + | ^^^ the trait `Yay` is not implemented for `u32` + | + = help: the trait `Yay` is implemented for `Foo` +note: required by a bound in `is_yay` + --> $DIR/impl_trait_for_tait_bound.rs:16:14 + | +LL | fn is_yay() { } + | ^^^ required by this bound in `is_yay` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs new file mode 100644 index 000000000..a4b8c2d19 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; + +pub trait Yay { } +impl Yay for u32 { } + +fn foo() { + is_yay::(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied +} + +fn is_yay() { } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr new file mode 100644 index 000000000..a6440f02c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `Foo: Yay` is not satisfied + --> $DIR/impl_trait_for_tait_bound2.rs:11:14 + | +LL | is_yay::(); + | ^^^ the trait `Yay` is not implemented for `Foo` + | + = help: the trait `Yay` is implemented for `u32` +note: required by a bound in `is_yay` + --> $DIR/impl_trait_for_tait_bound2.rs:14:14 + | +LL | fn is_yay() { } + | ^^^ required by this bound in `is_yay` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.rs b/tests/ui/type-alias-impl-trait/implied_bounds.rs new file mode 100644 index 000000000..53cbf8d22 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime<'a> = impl Equals; +fn _defining_use<'a>() -> WithLifetime<'a> {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<'a>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<'a>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<'a>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.stderr b/tests/ui/type-alias-impl-trait/implied_bounds.stderr new file mode 100644 index 000000000..6f11b6663 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/implied_bounds2.rs b/tests/ui/type-alias-impl-trait/implied_bounds2.rs new file mode 100644 index 000000000..b4c4c013c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds2.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type Ty<'a, A> = impl Sized + 'a; +fn defining<'a, A>() -> Ty<'a, A> {} +fn assert_static() {} +fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::>() } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds3.rs b/tests/ui/type-alias-impl-trait/implied_bounds3.rs new file mode 100644 index 000000000..e39c61328 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds3.rs @@ -0,0 +1,18 @@ +// check-pass + +fn foo(_: F) +where + F: 'static, +{ +} + +fn from(f: F) -> impl Send { + f +} + +fn bar() { + foo(from(|| ())) +} + +fn main() { +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_closure.rs b/tests/ui/type-alias-impl-trait/implied_bounds_closure.rs new file mode 100644 index 000000000..4cf35f951 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_closure.rs @@ -0,0 +1,31 @@ +trait StaticDefaultRef: 'static { + fn default_ref() -> &'static Self; +} + +impl StaticDefaultRef for str { + fn default_ref() -> &'static str { + "" + } +} + +fn into_impl(x: &str) -> &(impl ?Sized + AsRef + StaticDefaultRef + '_) { + x +} + +fn extend_lifetime<'a>(x: &'a str) -> &'static str { + let t = into_impl(x); + helper(|_| t) //~ ERROR lifetime may not live long enough +} + +fn helper + StaticDefaultRef>(f: impl FnOnce(&T) -> &T) -> &'static str { + f(T::default_ref()).as_ref() +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr new file mode 100644 index 000000000..151564c3b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_closure.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_closure.rs:17:16 + | +LL | fn extend_lifetime<'a>(x: &'a str) -> &'static str { + | -- lifetime `'a` defined here +LL | let t = into_impl(x); +LL | helper(|_| t) + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs new file mode 100644 index 000000000..8023cd24f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs @@ -0,0 +1,51 @@ +#![feature(type_alias_impl_trait)] + +type WithLifetime = impl Equals; +fn _defining_use() -> WithLifetime {} + +trait Convert<'a> { + type Witness; + fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T; +} + +impl<'a> Convert<'a> for () { + type Witness = WithLifetime<&'a ()>; + + fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + // compiler used to think it gets to assume 'a: 'b here because + // of the `&'b WithLifetime<&'a ()>` argument + x + //~^ ERROR lifetime may not live long enough + } +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + WithLifetime::<&'a ()>::convert_helper::<(), T>(&(), x) +} + +trait Equals { + type SelfType; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self::SelfType, + x: &'a T, + ) -> &'b T; +} + +impl Equals for S { + type SelfType = Self; + fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>( + proof: &'b Self, + x: &'a T, + ) -> &'b T { + W::convert(proof, x) + } +} + +fn main() { + let r; + { + let x = String::from("Hello World?"); + r = extend_lifetime(&x); + } + println!("{}", r); +} diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr new file mode 100644 index 000000000..cbc5e6073 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/implied_bounds_from_types.rs:17:9 + | +LL | impl<'a> Convert<'a> for () { + | -- lifetime `'a` defined here +... +LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T { + | -- lifetime `'b` defined here +... +LL | x + | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs new file mode 100644 index 000000000..b6a7264a5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs @@ -0,0 +1,27 @@ +#![feature(type_alias_impl_trait)] + +// known-bug: #99840 +// this should not compile +// check-pass + +type Alias = impl Sized; + +fn constrain() -> Alias { + 1i32 +} + +trait HideIt { + type Assoc; +} + +impl HideIt for () { + type Assoc = Alias; +} + +pub trait Yay {} + +impl Yay for <() as HideIt>::Assoc {} +// impl Yay for i32 {} // this already errors +// impl Yay for u32 {} // this also already errors + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs new file mode 100644 index 000000000..07f825aea --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs @@ -0,0 +1,43 @@ +#![feature(type_alias_impl_trait)] + +mod test_lifetime_param { + type Ty<'a> = impl Sized + 'a; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_higher_kinded_lifetime_param { + type Ty<'a> = impl Sized + 'a; + fn defining(a: &str) -> Ty<'_> { a } + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_higher_kinded_lifetime_param2 { + fn assert_static<'a: 'static>() {} + //~^ WARN: unnecessary lifetime parameter `'a` + fn test<'a>() { assert_static::<'a>() } + //~^ ERROR: lifetime may not live long enough +} + +mod test_type_param { + type Ty = impl Sized; + fn defining(s: A) -> Ty { s } + fn assert_static() {} + fn test() where Ty: 'static { assert_static::() } + //~^ ERROR: parameter type `A` may not live long enough +} + +mod test_implied_from_fn_sig { + type Opaque = impl Sized; + fn defining() -> Opaque {} + fn assert_static() {} + fn test(_: Opaque) { assert_static::(); } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr new file mode 100644 index 000000000..887620a4d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr @@ -0,0 +1,58 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:6:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:15:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +warning: unnecessary lifetime parameter `'a` + --> $DIR/implied_lifetime_wf_check3.rs:22:22 + | +LL | fn assert_static<'a: 'static>() {} + | ^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:8:43 + | +LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:17:46 + | +LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() } + | -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:24:21 + | +LL | fn test<'a>() { assert_static::<'a>() } + | -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | | + | lifetime `'a` defined here + +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check3.rs:32:41 + | +LL | fn test() where Ty: 'static { assert_static::() } + | ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test() where Ty: 'static { assert_static::() } + | +++++++++ + +error: aborting due to 4 previous errors; 3 warnings emitted + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs new file mode 100644 index 000000000..ac32dbde0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] + +mod test_type_param_static { + type Ty = impl Sized + 'static; + //~^ ERROR: the parameter type `A` may not live long enough + fn defining(s: A) -> Ty { s } + fn assert_static() {} + fn test() where Ty: 'static { assert_static::() } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr new file mode 100644 index 000000000..47bc31e78 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:4:18 + | +LL | type Ty = impl Sized + 'static; + | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | type Ty = impl Sized + 'static; + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs new file mode 100644 index 000000000..ee9bce15d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Callable { + type Output; + fn call() -> Self::Output; +} + +impl<'a> Callable for &'a () { + type Output = impl Sized; + fn call() -> Self::Output {} +} + +fn test<'a>() -> impl Sized { + <&'a () as Callable>::call() +} + +fn want_static(_: T) {} + +fn test2<'a>() { + want_static(<&'a () as Callable>::call()); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs new file mode 100644 index 000000000..ae21a9134 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs @@ -0,0 +1,38 @@ +#![feature(type_alias_impl_trait)] + +trait Callable { + type Output; + fn call(x: Self) -> Self::Output; +} + +trait PlusOne { + fn plus_one(&mut self); +} + +impl<'a> PlusOne for &'a mut i32 { + fn plus_one(&mut self) { + **self += 1; + } +} + +impl Callable for T { + type Output = impl PlusOne; + fn call(t: T) -> Self::Output { t } +} + +fn test<'a>(y: &'a mut i32) -> impl PlusOne { + <&'a mut i32 as Callable>::call(y) + //~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds +} + +fn main() { + let mut z = 42; + let mut thing = test(&mut z); + let mut thing2 = test(&mut z); + thing.plus_one(); + assert_eq!(z, 43); + thing2.plus_one(); + assert_eq!(z, 44); + thing.plus_one(); + assert_eq!(z, 45); +} diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr new file mode 100644 index 000000000..0ed8a703b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds + --> $DIR/imply_bounds_from_bounds_param.rs:24:5 + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { + | -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here +LL | <&'a mut i32 as Callable>::call(y) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs new file mode 100644 index 000000000..685d76ee3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.rs @@ -0,0 +1,15 @@ +// Regression test for issue 67856 + +#![feature(unboxed_closures)] +#![feature(type_alias_impl_trait)] +#![feature(fn_traits)] + +trait MyTrait {} +impl MyTrait for () {} + +impl FnOnce<()> for &F { + //~^ ERROR type parameter `F` must be used + type Output = impl MyTrait; + extern "rust-call" fn call_once(self, _: ()) -> Self::Output {} +} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr new file mode 100644 index 000000000..b93ea955c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incoherent-assoc-imp-trait.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `F` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/incoherent-assoc-imp-trait.rs:10:6 + | +LL | impl FnOnce<()> for &F { + | ^ type parameter `F` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.rs b/tests/ui/type-alias-impl-trait/incomplete-inference.rs new file mode 100644 index 000000000..4c8bf2cfc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incomplete-inference.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Sized; + +fn bar() -> Foo { + None + //~^ ERROR: type annotations needed [E0282] +} + +fn baz() -> Foo { + Some(()) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.stderr b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr new file mode 100644 index 000000000..9a0e71b4e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/incomplete-inference.rs:6:5 + | +LL | None + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | None:: + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs new file mode 100644 index 000000000..79caddf79 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +mod m { + type Foo = impl std::fmt::Debug; + //~^ ERROR cycle detected + + // Cycle: error today, but it'd be nice if it eventually worked + + pub fn foo() -> Foo { + is_send(bar()) + } + + pub fn bar() { + is_send(foo()); // Today: error + } + + fn baz() { + let f: Foo = 22_u32; + } + + fn is_send(_: T) {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr new file mode 100644 index 000000000..b9d646b92 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr @@ -0,0 +1,22 @@ +error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}` + --> $DIR/inference-cycle.rs:5:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `m::bar`... + --> $DIR/inference-cycle.rs:15:9 + | +LL | is_send(foo()); // Today: error + | ^^^^^^^ + = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`... + = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in module `m` + --> $DIR/inference-cycle.rs:4:1 + | +LL | mod m { + | ^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/issue-101750.rs b/tests/ui/type-alias-impl-trait/issue-101750.rs new file mode 100644 index 000000000..f564f4fa7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-101750.rs @@ -0,0 +1,37 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait Trait {} + +type TAIT = impl Trait; + +struct Concrete; +impl Trait for Concrete {} + +fn tait() -> TAIT { + Concrete +} + +trait OuterTrait { + type Item; +} +struct Dummy { + t: T, +} +impl OuterTrait for Dummy { + type Item = T; +} + +fn tait_and_impl_trait() -> impl OuterTrait { + Dummy { + t: (tait(), Concrete), + } +} + +fn tait_and_dyn_trait() -> impl OuterTrait)> { + let b: Box = Box::new(Concrete); + Dummy { t: (tait(), b) } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs new file mode 100644 index 000000000..0d3bace4d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-104817.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] +#![cfg_attr(specialized, feature(specialization))] +#![allow(incomplete_features)] + +// revisions: stock specialized +// [specialized]check-pass + +trait OpaqueTrait {} +impl OpaqueTrait for T {} +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { + || 0 +} +trait AnotherTrait {} +impl AnotherTrait for T {} +impl AnotherTrait for OpaqueType {} +//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr new file mode 100644 index 000000000..47bae8bd1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` + --> $DIR/issue-104817.rs:16:1 + | +LL | impl AnotherTrait for T {} + | -------------------------------- first implementation here +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs new file mode 100644 index 000000000..50eeff0b1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs @@ -0,0 +1,13 @@ +// Checks to ensure that we properly detect when a closure constrains an opaque type + +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() { + type Opaque = impl Debug; + fn _unused() -> Opaque { String::new() } + let null = || -> Opaque { 0 }; + //~^ ERROR: concrete type differs from previous defining opaque type use + println!("{:?}", null()); +} diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr new file mode 100644 index 000000000..4c5fd2255 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-52843-closure-constrain.rs:10:31 + | +LL | let null = || -> Opaque { 0 }; + | ^ expected `String`, got `i32` + | +note: previous use here + --> $DIR/issue-52843-closure-constrain.rs:9:30 + | +LL | fn _unused() -> Opaque { String::new() } + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-52843.rs b/tests/ui/type-alias-impl-trait/issue-52843.rs new file mode 100644 index 000000000..159d3ccd2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Default; + +#[allow(unused)] +fn foo(t: T) -> Foo { + t + //~^ ERROR: the trait bound `T: Default` is not satisfied +} + +struct NotDefault; + +fn main() { + let _ = Foo::::default(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr new file mode 100644 index 000000000..acd40f980 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Default` is not satisfied + --> $DIR/issue-52843.rs:7:5 + | +LL | t + | ^ the trait `Default` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type Foo = impl Default; + | +++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs new file mode 100644 index 000000000..057930f0c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Bug = impl Fn(T) -> U + Copy; //~ ERROR cycle detected + +const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + +fn make_bug>() -> Bug { + |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied +} + +fn main() { + CONST_BUG(0); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr new file mode 100644 index 000000000..2565a28b4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -0,0 +1,46 @@ +error[E0391]: cycle detected when computing type of `Bug::{opaque#0}` + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires type-checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:6:1 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `Bug`... + = note: ...which requires normalizing `Bug`... + = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/issue-53092-2.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | #![allow(dead_code)] +LL | | +LL | | type Bug = impl Fn(T) -> U + Copy; +... | +LL | | CONST_BUG(0); +LL | | } + | |_^ + +error[E0277]: the trait bound `U: From` is not satisfied + --> $DIR/issue-53092-2.rs:9:5 + | +LL | |x| x.into() + | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` + | +note: required by a bound in `make_bug` + --> $DIR/issue-53092-2.rs:8:19 + | +LL | fn make_bug>() -> Bug { + | ^^^^^^^ required by this bound in `make_bug` +help: consider restricting type parameter `U` + | +LL | type Bug> = impl Fn(T) -> U + Copy; + | +++++++++++++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0391. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53092.rs b/tests/ui/type-alias-impl-trait/issue-53092.rs new file mode 100644 index 000000000..1be5b46d6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Bug = impl Fn(T) -> U + Copy; + +union Moo { + x: Bug, + y: (), +} + +const CONST_BUG: Bug = unsafe { Moo { y: () }.x }; + +fn make_bug>() -> Bug { + |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied +} + +fn main() { + CONST_BUG(0); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr new file mode 100644 index 000000000..2109cf8a7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: From` is not satisfied + --> $DIR/issue-53092.rs:14:5 + | +LL | |x| x.into() + | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` + | +note: required by a bound in `make_bug` + --> $DIR/issue-53092.rs:13:19 + | +LL | fn make_bug>() -> Bug { + | ^^^^^^^ required by this bound in `make_bug` +help: consider restricting type parameter `U` + | +LL | type Bug> = impl Fn(T) -> U + Copy; + | +++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs new file mode 100644 index 000000000..007dcf3bc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53096.rs @@ -0,0 +1,11 @@ +#![feature(rustc_attrs)] +#![feature(type_alias_impl_trait)] + +type Foo = impl Fn() -> usize; +const fn bar() -> Foo { + || 0usize +} +const BAZR: Foo = bar(); + +#[rustc_error] +fn main() {} //~ ERROR diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr new file mode 100644 index 000000000..0af3a75f8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53096.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-53096.rs:11:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs new file mode 100644 index 000000000..4a11bb502 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Fn() -> Foo; + +fn foo() -> Foo { +//~^ ERROR: overflow evaluating the requirement + foo +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr new file mode 100644 index 000000000..0a34e8486 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr @@ -0,0 +1,12 @@ +error[E0275]: overflow evaluating the requirement `Foo: Sized` + --> $DIR/issue-53398-cyclic-types.rs:5:13 + | +LL | fn foo() -> Foo { + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`) + = note: required because it appears within the type `fn() -> Foo {foo}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/issue-53598.rs b/tests/ui/type-alias-impl-trait/issue-53598.rs new file mode 100644 index 000000000..9c1cbf926 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53598.rs @@ -0,0 +1,27 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +pub trait Foo { + type Item: Debug; + + fn foo(_: T) -> Self::Item; +} + +#[derive(Debug)] +pub struct S(std::marker::PhantomData); + +pub struct S2; + +impl Foo for S2 { + type Item = impl Debug; + + fn foo(_: T) -> Self::Item { + S::(Default::default()) + //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + } +} + +fn main() { + S2::foo(123); +} diff --git a/tests/ui/type-alias-impl-trait/issue-53598.stderr b/tests/ui/type-alias-impl-trait/issue-53598.stderr new file mode 100644 index 000000000..f8b8201e2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53598.stderr @@ -0,0 +1,8 @@ +error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-53598.rs:20:9 + | +LL | S::(Default::default()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs new file mode 100644 index 000000000..a3f126d56 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs @@ -0,0 +1,19 @@ +#![feature(generators, generator_trait, rustc_attrs)] +#![feature(type_alias_impl_trait)] + +use std::ops::Generator; + +type GenOnce = impl Generator; + +const fn const_generator(yielding: Y, returning: R) -> GenOnce { + move || { + yield yielding; + + return returning; + } +} + +const FOO: GenOnce = const_generator(10, 100); + +#[rustc_error] +fn main() {} //~ ERROR diff --git a/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr new file mode 100644 index 000000000..eb1c9603a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-53678-generator-and-const-fn.rs:19:1 + | +LL | fn main() {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs b/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs new file mode 100644 index 000000000..af0780ab0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs @@ -0,0 +1,26 @@ +// check-pass +// Regression test for issue #55099 +// Tests that we don't incorrectly consider a lifetime to part +// of the concrete type + +#![feature(type_alias_impl_trait)] + +trait Future {} + +struct AndThen(F); + +impl Future for AndThen {} + +struct Foo<'a> { + x: &'a mut (), +} + +type F = impl Future; + +impl<'a> Foo<'a> { + fn reply(&mut self) -> F { + AndThen(|| ()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs b/tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs new file mode 100644 index 000000000..3a7a5da07 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs @@ -0,0 +1,24 @@ +// Regression test for #57188 + +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Baz<'a> { + source: &'a str, +} + +trait Foo<'a> { + type T: Iterator> + 'a; + fn foo(source: &'a str) -> Self::T; +} + +struct Bar; +impl<'a> Foo<'a> for Bar { + type T = impl Iterator> + 'a; + fn foo(source: &'a str) -> Self::T { + std::iter::once(Baz { source }) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs new file mode 100644 index 000000000..cad3e0f66 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -0,0 +1,26 @@ +// check-pass +// Regression test for issue #57611 +// Ensures that we don't ICE + +#![feature(trait_alias)] +#![feature(type_alias_impl_trait)] + +trait Foo { + type Bar: Baz; + + fn bar(&self) -> Self::Bar; +} + +struct X; + +impl Foo for X { + type Bar = impl Baz; + + fn bar(&self) -> Self::Bar { + |x| x + } +} + +trait Baz = Fn(&A) -> &B; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57700.rs b/tests/ui/type-alias-impl-trait/issue-57700.rs new file mode 100644 index 000000000..484589387 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57700.rs @@ -0,0 +1,21 @@ +#![feature(arbitrary_self_types)] +#![feature(type_alias_impl_trait)] + +use std::ops::Deref; + +trait Foo { + type Bar: Foo; + + fn foo(self: impl Deref) -> Self::Bar; +} + +impl Foo for C { + type Bar = impl Foo; + + fn foo(self: impl Deref) -> Self::Bar { + self + //~^ Error type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57700.stderr b/tests/ui/type-alias-impl-trait/issue-57700.stderr new file mode 100644 index 000000000..31b6df5d4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57700.stderr @@ -0,0 +1,8 @@ +error: type parameter `impl Deref` is part of concrete type but not used in parameter list for the `impl Trait` type alias + --> $DIR/issue-57700.rs:16:9 + | +LL | self + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs b/tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs new file mode 100644 index 000000000..fcab2c7db --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57807-associated-type.rs @@ -0,0 +1,31 @@ +// Regression test for issue #57807 - ensure +// that we properly unify associated types within +// a type alias impl trait +// check-pass +#![feature(type_alias_impl_trait)] + +trait Bar { + type A; +} + +impl Bar for () { + type A = (); +} + +trait Foo { + type A; + type B: Bar; + + fn foo() -> Self::B; +} + +impl Foo for () { + type A = (); + type B = impl Bar; + + fn foo() -> Self::B { + () + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57961.rs b/tests/ui/type-alias-impl-trait/issue-57961.rs new file mode 100644 index 000000000..4aa5966ff --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57961.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +type X = impl Sized; + +trait Foo { + type Bar: Iterator; +} + +impl Foo for () { + type Bar = std::vec::IntoIter; + //~^ ERROR expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` +} + +fn incoherent() { + let f: X = 22_i32; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-57961.stderr b/tests/ui/type-alias-impl-trait/issue-57961.stderr new file mode 100644 index 000000000..8d11b4888 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-57961.stderr @@ -0,0 +1,20 @@ +error[E0271]: expected `IntoIter` to be an iterator that yields `X`, but it yields `u32` + --> $DIR/issue-57961.rs:10:16 + | +LL | type X = impl Sized; + | ---------- the expected opaque type +... +LL | type Bar = std::vec::IntoIter; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `u32` + | + = note: expected opaque type `X` + found type `u32` +note: required by a bound in `Foo::Bar` + --> $DIR/issue-57961.rs:6:24 + | +LL | type Bar: Iterator; + | ^^^^^^^^ required by this bound in `Foo::Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs new file mode 100644 index 000000000..477b61390 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs @@ -0,0 +1,39 @@ +// check-pass + +#![feature(generators, generator_trait)] +#![feature(type_alias_impl_trait)] + +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +type RandGenerator<'a> = impl Generator + 'a; +fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> { + move || { + let _rng = rng; + loop { + yield 0; + } + } +} + +pub type RandGeneratorWithIndirection<'c> = impl Generator + 'c; +pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> { + fn helper<'b>(rng: &'b ()) -> impl 'b + Generator { + move || { + let _rng = rng; + loop { + yield 0; + } + } + } + + helper(rng) +} + +fn main() { + let mut gen = rand_generator(&()); + match unsafe { Pin::new_unchecked(&mut gen) }.resume(()) { + GeneratorState::Yielded(_) => {} + GeneratorState::Complete(_) => {} + }; +} diff --git a/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs new file mode 100644 index 000000000..27ca7d0fd --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generators, generator_trait)] +#![feature(type_alias_impl_trait)] + +trait Trait {} + +impl Trait for T {} + +type Foo<'c> = impl Trait + 'c; +fn foo<'a>(rng: &'a ()) -> Foo<'a> { + fn helper<'b>(rng: &'b ()) -> impl 'b + Trait { + rng + } + + helper(rng) +} + +fn main() { +} diff --git a/tests/ui/type-alias-impl-trait/issue-58887.rs b/tests/ui/type-alias-impl-trait/issue-58887.rs new file mode 100644 index 000000000..96ac78602 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58887.rs @@ -0,0 +1,22 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +impl UnwrapItemsExt for I +where + I: Iterator>, + E: std::fmt::Debug, +{ + type Iter = impl Iterator; + + fn unwrap_items(self) -> Self::Iter { + self.map(|x| x.unwrap()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-58951-2.rs b/tests/ui/type-alias-impl-trait/issue-58951-2.rs new file mode 100644 index 000000000..e4ba7f8e2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58951-2.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +mod defining_use_scope { + pub type A = impl Iterator; + + pub fn def_a() -> A { + 0..1 + } +} +use defining_use_scope::*; + +pub fn use_a() { + def_a().map(|x| x); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-58951.rs b/tests/ui/type-alias-impl-trait/issue-58951.rs new file mode 100644 index 000000000..7303cbab4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-58951.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type A = impl Iterator; + +fn def_a() -> A { + 0..1 +} + +pub fn use_a() { + def_a().map(|x| x); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60371.rs b/tests/ui/type-alias-impl-trait/issue-60371.rs new file mode 100644 index 000000000..9a40f3d9b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60371.rs @@ -0,0 +1,14 @@ +trait Bug { + type Item: Bug; + + const FUN: fn() -> Self::Item; +} + +impl Bug for &() { + type Item = impl Bug; //~ ERROR `impl Trait` in type aliases is unstable + + const FUN: fn() -> Self::Item = || (); + //~^ ERROR the trait bound `(): Bug` is not satisfied +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60371.stderr b/tests/ui/type-alias-impl-trait/issue-60371.stderr new file mode 100644 index 000000000..d0c04371b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60371.stderr @@ -0,0 +1,21 @@ +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/issue-60371.rs:8:17 + | +LL | type Item = impl Bug; + | ^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable + +error[E0277]: the trait bound `(): Bug` is not satisfied + --> $DIR/issue-60371.rs:10:40 + | +LL | const FUN: fn() -> Self::Item = || (); + | ^^ the trait `Bug` is not implemented for `()` + | + = help: the trait `Bug` is implemented for `&()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs new file mode 100644 index 000000000..b833429c7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60407.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait, rustc_attrs)] + +type Debuggable = impl core::fmt::Debug; + +static mut TEST: Option = None; + +#[rustc_error] +fn main() { + //~^ ERROR + unsafe { TEST = Some(foo()) } +} + +fn foo() -> Debuggable { + 0u32 +} diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr new file mode 100644 index 000000000..fecee2779 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60407.stderr @@ -0,0 +1,8 @@ +error: fatal error triggered by #[rustc_error] + --> $DIR/issue-60407.rs:8:1 + | +LL | fn main() { + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/issue-60564-working.rs b/tests/ui/type-alias-impl-trait/issue-60564-working.rs new file mode 100644 index 000000000..38accc824 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60564-working.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +trait IterBits { + type BitsIter: Iterator; + fn iter_bits(self, n: u8) -> Self::BitsIter; +} + +impl IterBits for T +where + T: std::ops::Shr + + std::ops::BitAnd + + std::convert::From + + std::convert::TryInto, + E: std::fmt::Debug, +{ + type BitsIter = impl std::iter::Iterator; + fn iter_bits(self, n: u8) -> Self::BitsIter { + (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs new file mode 100644 index 000000000..c2f4c3708 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60564.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +trait IterBits { + type BitsIter: Iterator; + fn iter_bits(self, n: u8) -> Self::BitsIter; +} + +type IterBitsIter = impl std::iter::Iterator; + +impl IterBits for T +where + T: std::ops::Shr + + std::ops::BitAnd + + std::convert::From + + std::convert::TryInto, + E: std::fmt::Debug, +{ + type BitsIter = IterBitsIter; + fn iter_bits(self, n: u8) -> Self::BitsIter { + (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + //~^ ERROR expected generic type parameter, found `u8` + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr new file mode 100644 index 000000000..f8fdb004d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `u8` + --> $DIR/issue-60564.rs:20:9 + | +LL | type IterBitsIter = impl std::iter::Iterator; + | - this generic parameter must be used with a generic type parameter +... +LL | (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-60662.rs b/tests/ui/type-alias-impl-trait/issue-60662.rs new file mode 100644 index 000000000..b9faa668b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60662.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Z unpretty=hir + +#![feature(type_alias_impl_trait)] + +trait Animal {} + +fn main() { + pub type ServeFut = impl Animal; +} diff --git a/tests/ui/type-alias-impl-trait/issue-60662.stdout b/tests/ui/type-alias-impl-trait/issue-60662.stdout new file mode 100644 index 000000000..5b3d7375d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-60662.stdout @@ -0,0 +1,14 @@ +// check-pass +// compile-flags: -Z unpretty=hir + +#![feature(type_alias_impl_trait)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +trait Animal { } + +fn main() { + type ServeFut = /*impl Trait*/; + } diff --git a/tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs b/tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs new file mode 100644 index 000000000..36779a0ce --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs @@ -0,0 +1,38 @@ +// Regression test for #62988 + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait MyTrait { + type AssocType: Send; + fn ret(&self) -> Self::AssocType; +} + +impl MyTrait for () { + type AssocType = impl Send; + fn ret(&self) -> Self::AssocType { + () + } +} + +impl<'a> MyTrait for &'a () { + type AssocType = impl Send; + fn ret(&self) -> Self::AssocType { + () + } +} + +trait MyLifetimeTrait<'a> { + type AssocType: Send + 'a; + fn ret(&self) -> Self::AssocType; +} + +impl<'a> MyLifetimeTrait<'a> for &'a () { + type AssocType = impl Send + 'a; + fn ret(&self) -> Self::AssocType { + *self + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs new file mode 100644 index 000000000..7414611a7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs @@ -0,0 +1,13 @@ +// Regression test for issue #63263. +// Tests that we properly handle closures with an explicit return type +// that return an opaque type. + +// check-pass + +#![feature(type_alias_impl_trait)] + +pub type Closure = impl FnOnce(); + +fn main() { + || -> Closure { || () }; +} diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs new file mode 100644 index 000000000..97332e16d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63279.rs @@ -0,0 +1,15 @@ +// compile-flags: -Zsave-analysis + +#![feature(type_alias_impl_trait)] + +type Closure = impl FnOnce(); + +fn c() -> Closure { + //~^ ERROR: expected a `FnOnce<()>` closure, found `()` + || -> Closure { || () } + //~^ ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: expected a `FnOnce<()>` closure, found `()` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr new file mode 100644 index 000000000..110b8d1ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr @@ -0,0 +1,48 @@ +error[E0277]: expected a `FnOnce<()>` closure, found `()` + --> $DIR/issue-63279.rs:7:11 + | +LL | fn c() -> Closure { + | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` + | + = help: the trait `FnOnce<()>` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + +error[E0277]: expected a `FnOnce<()>` closure, found `()` + --> $DIR/issue-63279.rs:9:11 + | +LL | || -> Closure { || () } + | ^^^^^^^ expected an `FnOnce<()>` closure, found `()` + | + = help: the trait `FnOnce<()>` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + +error[E0308]: mismatched types + --> $DIR/issue-63279.rs:9:21 + | +LL | || -> Closure { || () } + | ^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/issue-63279.rs:9:21: 9:23]` +help: use parentheses to call this closure + | +LL | || -> Closure { (|| ())() } + | + +++ + +error[E0308]: mismatched types + --> $DIR/issue-63279.rs:9:5 + | +LL | || -> Closure { || () } + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure + | + = note: expected unit type `()` + found closure `[closure@$DIR/issue-63279.rs:9:5: 9:18]` +help: use parentheses to call this closure + | +LL | (|| -> Closure { || () })() + | + +++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-63355.rs b/tests/ui/type-alias-impl-trait/issue-63355.rs new file mode 100644 index 000000000..7066a0535 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63355.rs @@ -0,0 +1,46 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +pub trait Foo {} + +pub trait Bar { + type Foo: Foo; + + fn foo() -> Self::Foo; +} + +pub trait Baz { + type Foo: Foo; + type Bar: Bar; + + fn foo() -> Self::Foo; + fn bar() -> Self::Bar; +} + +impl Foo for () {} + +impl Bar for () { + type Foo = FooImpl; + + fn foo() -> Self::Foo { + () + } +} + +pub type FooImpl = impl Foo; +pub type BarImpl = impl Bar; + +impl Baz for () { + type Foo = FooImpl; + type Bar = BarImpl; + + fn foo() -> Self::Foo { + () + } + + fn bar() -> Self::Bar { + () + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs b/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs new file mode 100644 index 000000000..28f4a85c9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs @@ -0,0 +1,21 @@ +// check-pass +// Regression test for issue #63677 - ensure that +// coherence checking can properly handle 'impl trait' +// in type aliases +#![feature(type_alias_impl_trait)] + +pub trait Trait {} +pub struct S1(T); +pub struct S2(T); + +pub type T1 = impl Trait; +pub type T2 = S1; +pub type T3 = S2; + +impl Trait for S1 {} +impl S2 {} +impl T3 {} + +pub fn use_t1() -> T1 { S1(()) } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-65384.rs b/tests/ui/type-alias-impl-trait/issue-65384.rs new file mode 100644 index 000000000..9a9b2269f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65384.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +trait MyTrait {} + +impl MyTrait for () {} + +type Bar = impl MyTrait; + +impl MyTrait for Bar {} +//~^ ERROR: conflicting implementations of trait `MyTrait` for type `()` + +fn bazr() -> Bar { } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-65384.stderr b/tests/ui/type-alias-impl-trait/issue-65384.stderr new file mode 100644 index 000000000..f6692ae32 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65384.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `()` + --> $DIR/issue-65384.rs:10:1 + | +LL | impl MyTrait for () {} + | ------------------- first implementation here +... +LL | impl MyTrait for Bar {} + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs new file mode 100644 index 000000000..72c22827f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -0,0 +1,18 @@ +// compile-flags: -Zsave-analysis +// check-pass + +#![feature(type_alias_impl_trait, rustc_attrs)] + +type T = impl Sized; +// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed +// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive; +// so difference assertion should not be declared on impl-trait-type-alias's instances. +// for details, check RFC-2515: +// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md + +fn take(_: fn() -> T) {} + +fn main() { + take(|| {}); + take(|| {}); +} diff --git a/tests/ui/type-alias-impl-trait/issue-65918.rs b/tests/ui/type-alias-impl-trait/issue-65918.rs new file mode 100644 index 000000000..af6d50109 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-65918.rs @@ -0,0 +1,51 @@ +// ignore-test: This now ICEs again. + +// build-pass + +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +/* copied Index and TryFrom for convenience (and simplicity) */ +trait MyIndex { + type O; + fn my_index(self) -> Self::O; +} +trait MyFrom: Sized { + type Error; + fn my_from(value: T) -> Result; +} + +/* MCVE starts here */ +trait F {} +impl F for () {} +type DummyT = impl F; +fn _dummy_t() -> DummyT {} + +struct Phantom1(PhantomData); +struct Phantom2(PhantomData); +struct Scope(Phantom2>); + +impl Scope { + fn new() -> Self { + unimplemented!() + } +} + +impl MyFrom> for Phantom1 { + type Error = (); + fn my_from(_: Phantom2) -> Result { + unimplemented!() + } +} + +impl>>, U> MyIndex> for Scope { + type O = T; + fn my_index(self) -> Self::O { + MyFrom::my_from(self.0).ok().unwrap() + } +} + +fn main() { + let _pos: Phantom1> = Scope::new().my_index(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs b/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs new file mode 100644 index 000000000..d97270c31 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs @@ -0,0 +1,21 @@ +// Regression test for issue #66580 +// Ensures that we don't try to determine whether a closure +// is foreign when it's the underlying type of an opaque type +// check-pass +#![feature(type_alias_impl_trait)] + +type Closure = impl FnOnce(); + +fn closure() -> Closure { + || {} +} + +struct Wrap { + f: T, +} + +impl Wrap {} + +impl Wrap {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs b/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs new file mode 100644 index 000000000..cd219328a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs @@ -0,0 +1,33 @@ +// check-pass +// Regression test for issue #67844 +// Ensures that we properly handle nested TAIT occurrences +// with generic parameters + +#![feature(type_alias_impl_trait)] + +trait WithAssoc { + type AssocType; +} + +trait WithParam {} + +type Return = impl WithAssoc>; + +struct MyParam; +impl WithParam for MyParam {} + +struct MyStruct; + +impl WithAssoc for MyStruct { + type AssocType = MyParam; +} + +fn my_fun() -> Return { + MyStruct +} + +fn my_other_fn() -> impl WithAssoc> { + MyStruct +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs new file mode 100644 index 000000000..5e0a82a72 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs @@ -0,0 +1,14 @@ +// Regression test for issue #68368 +// Ensures that we don't ICE when emitting an error +// for a non-defining use when lifetimes are involved + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Alias<'a, U> = impl Trait; + +fn f<'a>() -> Alias<'a, ()> {} +//~^ ERROR expected generic type parameter, found `()` + +fn main() {} + +impl Trait for () {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr new file mode 100644 index 000000000..271743a40 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `()` + --> $DIR/issue-68368-non-defining-use-2.rs:9:29 + | +LL | type Alias<'a, U> = impl Trait; + | - this generic parameter must be used with a generic type parameter +LL | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs new file mode 100644 index 000000000..3b32260c9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs @@ -0,0 +1,14 @@ +// Regression test for issue #68368 +// Ensures that we don't ICE when emitting an error +// for a non-defining use when lifetimes are involved + +#![feature(type_alias_impl_trait)] +trait Trait {} +type Alias<'a, U> = impl Trait; + +fn f<'a>() -> Alias<'a, ()> {} +//~^ ERROR expected generic type parameter, found `()` + +fn main() {} + +impl Trait<()> for () {} diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr new file mode 100644 index 000000000..4d9a8d6ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic type parameter, found `()` + --> $DIR/issue-68368-non-defining-use.rs:9:29 + | +LL | type Alias<'a, U> = impl Trait; + | - this generic parameter must be used with a generic type parameter +LL | +LL | fn f<'a>() -> Alias<'a, ()> {} + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs new file mode 100644 index 000000000..7657fe2fb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs @@ -0,0 +1,23 @@ +// Regression test for #69136 + +#![feature(type_alias_impl_trait)] + +trait SomeTrait {} + +impl SomeTrait for () {} + +trait WithAssoc { + type AssocType; +} + +impl WithAssoc for () { + type AssocType = (); +} + +type Return = impl WithAssoc; +//~^ ERROR use of undeclared lifetime name `'a` + +fn my_fun() -> Return<()> {} +//~^ ERROR expected generic type parameter, found `()` + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr new file mode 100644 index 000000000..d1250786d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr @@ -0,0 +1,29 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65 + | +LL | type Return = impl WithAssoc; + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type Return = impl for<'a> WithAssoc; + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | type Return<'a, A> = impl WithAssoc; + | +++ + +error[E0792]: expected generic type parameter, found `()` + --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:20:27 + | +LL | type Return = impl WithAssoc; + | - this generic parameter must be used with a generic type parameter +... +LL | fn my_fun() -> Return<()> {} + | ^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0792. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs new file mode 100644 index 000000000..a6916eda8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs @@ -0,0 +1,23 @@ +// Test-pass variant of #69136 + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait SomeTrait {} + +impl SomeTrait for () {} + +trait WithAssoc { + type AssocType; +} + +impl WithAssoc for () { + type AssocType = (); +} + +type Return<'a> = impl WithAssoc; + +fn my_fun<'a>() -> Return<'a> {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-69323.rs b/tests/ui/type-alias-impl-trait/issue-69323.rs new file mode 100644 index 000000000..a9bd6daf2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-69323.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +use std::iter::{once, Chain}; + +fn test1>(x: A) -> Chain> { + x.chain(once(",")) +} + +type I = Chain>; +fn test2>(x: A) -> I { + x.chain(once(",")) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs new file mode 100644 index 000000000..dff0d89d4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-70121.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub type Successors<'a> = impl Iterator; + +pub fn f<'a>() -> Successors<'a> { + None.into_iter() +} + +pub trait Tr { + type Item; +} + +impl<'a> Tr for &'a () { + type Item = Successors<'a>; +} + +pub fn kazusa<'a>() -> <&'a () as Tr>::Item { + None.into_iter() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-72793.rs b/tests/ui/type-alias-impl-trait/issue-72793.rs new file mode 100644 index 000000000..828c87114 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-72793.rs @@ -0,0 +1,25 @@ +// check-pass +// compile-flags: -Zmir-opt-level=3 + +#![feature(type_alias_impl_trait)] + +trait T { type Item; } + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S { + type Item = &'a (); +} + +fn filter_positive<'a>() -> Alias<'a> { + &S +} + +fn with_positive(fun: impl Fn(Alias<'_>)) { + fun(filter_positive()); +} + +fn main() { + with_positive(|_| ()); +} diff --git a/tests/ui/type-alias-impl-trait/issue-74244.rs b/tests/ui/type-alias-impl-trait/issue-74244.rs new file mode 100644 index 000000000..bb4104b3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74244.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +trait Allocator { + type Buffer; +} + +struct DefaultAllocator; + +impl Allocator for DefaultAllocator { + //~^ ERROR: the type parameter `T` is not constrained + type Buffer = (); +} + +type A = impl Fn(::Buffer); + +fn foo() -> A { + |_| () +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr new file mode 100644 index 000000000..ff6bacd27 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74244.rs:9:6 + | +LL | impl Allocator for DefaultAllocator { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74280.rs b/tests/ui/type-alias-impl-trait/issue-74280.rs new file mode 100644 index 000000000..ad641eaa0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74280.rs @@ -0,0 +1,12 @@ +// Regression test for #74280. + +#![feature(type_alias_impl_trait)] + +type Test = impl Copy; + +fn test() -> Test { + let y = || -> Test { () }; + 7 //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74280.stderr b/tests/ui/type-alias-impl-trait/issue-74280.stderr new file mode 100644 index 000000000..66886db6e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74280.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-74280.rs:9:5 + | +LL | fn test() -> Test { + | ---- expected `()` because of return type +LL | let y = || -> Test { () }; +LL | 7 + | ^ expected `()`, found integer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.rs b/tests/ui/type-alias-impl-trait/issue-74761-2.rs new file mode 100644 index 000000000..d26ca5c3e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +pub trait A { + type B; + fn f(&self) -> Self::B; +} +impl<'a, 'b> A for () { + //~^ ERROR the lifetime parameter `'a` is not constrained + //~| ERROR the lifetime parameter `'b` is not constrained + type B = impl core::fmt::Debug; + + fn f(&self) -> Self::B {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr new file mode 100644 index 000000000..f15d0a069 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr @@ -0,0 +1,15 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761-2.rs:7:6 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761-2.rs:7:10 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-74761.rs b/tests/ui/type-alias-impl-trait/issue-74761.rs new file mode 100644 index 000000000..d26ca5c3e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +pub trait A { + type B; + fn f(&self) -> Self::B; +} +impl<'a, 'b> A for () { + //~^ ERROR the lifetime parameter `'a` is not constrained + //~| ERROR the lifetime parameter `'b` is not constrained + type B = impl core::fmt::Debug; + + fn f(&self) -> Self::B {} +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-74761.stderr b/tests/ui/type-alias-impl-trait/issue-74761.stderr new file mode 100644 index 000000000..1d016fe07 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-74761.stderr @@ -0,0 +1,15 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761.rs:7:6 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-74761.rs:7:10 + | +LL | impl<'a, 'b> A for () { + | ^^ unconstrained lifetime parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs new file mode 100644 index 000000000..b97e444c6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs @@ -0,0 +1,31 @@ +// Regression test for issue #76202 +// Tests that we don't ICE when we have a trait impl on a TAIT. + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Dummy {} +impl Dummy for () {} + +type F = impl Dummy; +fn f() -> F {} + +trait Test { + fn test(self); +} + +impl Test for F { + fn test(self) {} +} + +// Ok because `i32` does not implement `Dummy`, +// so it can't possibly be the hidden type of `F`. +impl Test for i32 { + fn test(self) {} +} + +fn main() { + let x: F = f(); + x.test(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs new file mode 100644 index 000000000..8d818d4a3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -0,0 +1,14 @@ +// Regression test for #77179. + +#![feature(type_alias_impl_trait)] + +type Pointer = impl std::ops::Deref; + +fn test() -> Pointer<_> { + //~^ ERROR: the placeholder `_` is not allowed within types + Box::new(1) +} + +fn main() { + test(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr new file mode 100644 index 000000000..053546e4b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-77179.rs:7:22 + | +LL | fn test() -> Pointer<_> { + | --------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Pointer` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/issue-78450.rs b/tests/ui/type-alias-impl-trait/issue-78450.rs new file mode 100644 index 000000000..fccbfb74f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-78450.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +pub trait AssociatedImpl { + type ImplTrait; + + fn f() -> Self::ImplTrait; +} + +struct S(T); + +trait Associated { + type A; +} + +impl<'a, T: Associated> AssociatedImpl for S { + type ImplTrait = impl core::fmt::Debug; + + fn f() -> Self::ImplTrait { + () + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs new file mode 100644 index 000000000..2ba4befea --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs @@ -0,0 +1,25 @@ +// Regression test for issues #84660 and #86411: both are variations on #76202. +// Tests that we don't ICE when we have an opaque type appearing anywhere in an impl header. + +// check-pass + +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +type Bar = impl Foo; +fn _defining_use() -> Bar {} + +trait TraitArg { + fn f(); +} + +impl TraitArg for () { + fn f() { + println!("ho"); + } +} + +fn main() { + <() as TraitArg>::f(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs new file mode 100644 index 000000000..48d4b0c96 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs @@ -0,0 +1,41 @@ +// Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an +// impl header being accepted was used to create unsoundness. + +#![feature(type_alias_impl_trait)] + +trait Foo {} +impl Foo for () {} +type Bar = impl Foo; +fn _defining_use() -> Bar {} + +trait Trait { + type Out; + fn convert(i: In) -> Self::Out; +} + +impl Trait for Out { + type Out = Out; + fn convert(_i: In) -> Self::Out { + unreachable!(); + } +} + +impl Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait` + type Out = In; + fn convert(i: In) -> Self::Out { + i + } +} + +fn transmute(i: In) -> Out { + >::convert(i) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = transmute::<&String, &String>(&x); + } + println!("{}", d); +} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr new file mode 100644 index 000000000..6a75e1bd2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/issue-84660-unsoundness.rs:23:1 + | +LL | impl Trait for Out { + | ------------------------------------ first implementation here +... +LL | impl Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs new file mode 100644 index 000000000..80a74eb63 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs @@ -0,0 +1,73 @@ +// check-pass + +use std::error::Error as StdError; +use std::pin::Pin; +use std::task::{Context, Poll}; + +pub trait Stream { + type Item; + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + fn size_hint(&self) -> (usize, Option) { + (0, None) + } +} + +pub trait TryStream: Stream { + type Ok; + type Error; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>>; +} + +impl TryStream for S +where + S: ?Sized + Stream>, +{ + type Ok = T; + type Error = E; + + fn try_poll_next( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + self.poll_next(cx) + } +} + +pub trait ServerSentEvent: Sized + Send + Sync + 'static {} + +impl ServerSentEvent for T {} + +struct SseKeepAlive { + event_stream: S, +} + +struct SseComment(T); + +impl Stream for SseKeepAlive +where + S: TryStream + Send + 'static, + S::Ok: ServerSentEvent, + S::Error: StdError + Send + Sync + 'static, +{ + type Item = Result, ()>; + fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll> { + unimplemented!() + } +} + +pub fn keep( + event_stream: S, +) -> impl TryStream + Send + 'static +where + S: TryStream + Send + 'static, + S::Ok: ServerSentEvent + Send, + S::Error: StdError + Send + Sync + 'static, +{ + SseKeepAlive { event_stream } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-89686.rs b/tests/ui/type-alias-impl-trait/issue-89686.rs new file mode 100644 index 000000000..058417bdb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-89686.rs @@ -0,0 +1,23 @@ +// edition:2018 + +#![feature(type_alias_impl_trait)] + +use std::future::Future; + +type G<'a, T> = impl Future + 'a; + +trait Trait { + type F: Future; + + fn f(&self) -> Self::F; + + fn g<'a>(&'a self) -> G<'a, Self> + where + Self: Sized, + { + async move { self.f().await } + //~^ ERROR: the trait bound `T: Trait` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr new file mode 100644 index 000000000..3b95a575a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/issue-89686.rs:18:9 + | +LL | async move { self.f().await } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | type G<'a, T: Trait> = impl Future + 'a; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-89952.rs b/tests/ui/type-alias-impl-trait/issue-89952.rs new file mode 100644 index 000000000..dc0f19c04 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-89952.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +trait SomeTrait {} +impl SomeTrait for () {} + +trait MyFuture { + type Output; +} +impl MyFuture for T { + type Output = T; +} + +trait ReturnsFuture { + type Output: SomeTrait; + type Future: MyFuture>; + fn func() -> Self::Future; +} + +struct Foo; + +impl ReturnsFuture for Foo { + type Output = impl SomeTrait; + type Future = impl MyFuture>; + fn func() -> Self::Future { + Result::<(), ()>::Err(()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.rs b/tests/ui/type-alias-impl-trait/issue-90400-1.rs new file mode 100644 index 000000000..15aead2f6 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.rs @@ -0,0 +1,29 @@ +// Regression test for #90400, +// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836 + +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +trait Foo { + type FooFn: FnOnce(); + + fn foo(&self, bar: B) -> Self::FooFn; +} + +struct MyFoo; + +impl Foo for MyFoo { + type FooFn = impl FnOnce(); + + fn foo(&self, bar: B) -> Self::FooFn { + move || bar.bar() //~ ERROR: the trait bound `B: Bar` is not satisfied + } +} + +fn main() { + let boom: ::FooFn = unsafe { core::mem::zeroed() }; + boom(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr new file mode 100644 index 000000000..ead28769f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/issue-90400-1.rs:22:9 + | +LL | move || bar.bar() + | ^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `::foo` + --> $DIR/issue-90400-1.rs:21:15 + | +LL | fn foo(&self, bar: B) -> Self::FooFn { + | ^^^ required by this bound in `::foo` +help: consider restricting type parameter `B` + | +LL | type FooFn = impl FnOnce(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.rs b/tests/ui/type-alias-impl-trait/issue-90400-2.rs new file mode 100644 index 000000000..4c6e893c1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.rs @@ -0,0 +1,37 @@ +// Regression test for #90400, +// taken from https://github.com/rust-lang/rust/issues/90400#issuecomment-954927836 + +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +trait Baz { + fn baz(&self); +} + +trait Foo { + type FooFn: Baz; + + fn foo(&self, bar: B) -> Self::FooFn; +} + +struct MyFoo; +impl Foo for MyFoo { + type FooFn = impl Baz; + + fn foo(&self, bar: B) -> Self::FooFn { + MyBaz(bar) //~ ERROR: the trait bound `B: Bar` is not satisfied + } +} + +struct MyBaz(B); +impl Baz for MyBaz { + fn baz(&self) {} +} + +fn main() { + let boom: ::FooFn = unsafe { core::mem::zeroed() }; + boom.baz(); +} diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr new file mode 100644 index 000000000..0c45046f5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/issue-90400-2.rs:25:9 + | +LL | MyBaz(bar) + | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required for `MyBaz` to implement `Baz` + --> $DIR/issue-90400-2.rs:30:14 + | +LL | impl Baz for MyBaz { + | --- ^^^ ^^^^^^^^ + | | + | unsatisfied trait bound introduced here +help: consider restricting type parameter `B` + | +LL | type FooFn = impl Baz; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/issue-93411.rs b/tests/ui/type-alias-impl-trait/issue-93411.rs new file mode 100644 index 000000000..1f8c78926 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-93411.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +// this test used to stack overflow due to infinite recursion. +// check-pass +// compile-flags: --edition=2018 + +use std::future::Future; + +fn main() { + let _ = move || async move { + let value = 0u8; + blah(&value).await; + }; +} + +type BlahFut<'a> = impl Future + Send + 'a; +fn blah<'a>(_value: &'a u8) -> BlahFut<'a> { + async {} +} diff --git a/tests/ui/type-alias-impl-trait/issue-94429.rs b/tests/ui/type-alias-impl-trait/issue-94429.rs new file mode 100644 index 000000000..2c965b875 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-94429.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait, generator_trait, generators)] +use std::ops::Generator; + +trait Runnable { + type Gen: Generator; + + fn run(&mut self) -> Self::Gen; +} + +struct Implementor {} + +impl Runnable for Implementor { + type Gen = impl Generator; + + fn run(&mut self) -> Self::Gen { + //~^ ERROR: type mismatch resolving + move || { + yield 1; + } + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr new file mode 100644 index 000000000..8d7f7a07b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `<[generator@$DIR/issue-94429.rs:17:9: 17:16] as Generator>::Yield == ()` + --> $DIR/issue-94429.rs:15:26 + | +LL | fn run(&mut self) -> Self::Gen { + | ^^^^^^^^^ expected integer, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs new file mode 100644 index 000000000..825710851 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +fn main() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + match foo { + None => (), + Some((a, b, c)) => (), //~ ERROR mismatched types + } +} diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr new file mode 100644 index 000000000..728244a18 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-96572-unconstrained-mismatch.rs:8:14 + | +LL | match foo { + | --- this expression has type `T` +LL | None => (), +LL | Some((a, b, c)) => (), + | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | + = note: expected tuple `(u32, u32)` + found tuple `(_, _, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs new file mode 100644 index 000000000..2c740ccc1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -0,0 +1,92 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +fn main() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + match foo { + None => (), + Some((a, b)) => (), + } +} + +fn upvar() { + #[derive(Copy, Clone)] + struct Foo((u32, u32)); + + type T = impl Copy; + let foo: T = Foo((1u32, 2u32)); + let x = move || { + let Foo((a, b)) = foo; + }; +} + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some((a, b)) => (), + } + }; +} + +fn r#struct() { + #[derive(Copy, Clone)] + struct Foo((u32, u32)); + + type U = impl Copy; + let foo: U = Foo((1u32, 2u32)); + let Foo((a, b)) = foo; +} + +mod only_pattern { + type T = impl Copy; + + fn foo(foo: T) { + let (mut x, mut y) = foo; + x = 42; + y = "foo"; + } + + type U = impl Copy; + + fn bar(bar: Option) { + match bar { + Some((mut x, mut y)) => { + x = 42; + y = "foo"; + } + None => {} + } + } +} + +mod only_pattern_rpit { + #[allow(unconditional_recursion)] + fn foo(b: bool) -> impl Copy { + let (mut x, mut y) = foo(false); + x = 42; + y = "foo"; + if b { + panic!() + } else { + foo(true) + } + } + + fn bar(b: bool) -> Option { + if b { + return None; + } + match bar(!b) { + Some((mut x, mut y)) => { + x = 42; + y = "foo"; + } + None => {} + } + None + } +} diff --git a/tests/ui/type-alias-impl-trait/issue-98604.rs b/tests/ui/type-alias-impl-trait/issue-98604.rs new file mode 100644 index 000000000..32c2f9ed5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98604.rs @@ -0,0 +1,11 @@ +// edition:2018 + +type AsyncFnPtr = Box std::pin::Pin>>>; + +async fn test() {} + +#[allow(unused_must_use)] +fn main() { + Box::new(test) as AsyncFnPtr; + //~^ ERROR expected `fn() -> impl Future {test}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` +} diff --git a/tests/ui/type-alias-impl-trait/issue-98604.stderr b/tests/ui/type-alias-impl-trait/issue-98604.stderr new file mode 100644 index 000000000..92d01eb0d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98604.stderr @@ -0,0 +1,18 @@ +error[E0271]: expected `fn() -> impl Future {test}` to be a fn item that returns `Pin + 'static)>>`, but it returns `impl Future` + --> $DIR/issue-98604.rs:9:5 + | +LL | Box::new(test) as AsyncFnPtr; + | ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-98604.rs:5:17 + | +LL | async fn test() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected struct `Pin + 'static)>>` + found opaque type `impl Future` + = note: required for the cast from `fn() -> impl Future {test}` to the object type `dyn Fn() -> Pin + 'static)>>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/issue-98608.rs b/tests/ui/type-alias-impl-trait/issue-98608.rs new file mode 100644 index 000000000..1f89af045 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98608.rs @@ -0,0 +1,11 @@ +fn hi() -> impl Sized { + std::ptr::null::() +} + +fn main() { + let b: Box Box> = Box::new(hi); + //~^ ERROR expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box`, but it returns `impl Sized` + let boxed = b(); + let null = *boxed; + println!("{null:?}"); +} diff --git a/tests/ui/type-alias-impl-trait/issue-98608.stderr b/tests/ui/type-alias-impl-trait/issue-98608.stderr new file mode 100644 index 000000000..916a58451 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-98608.stderr @@ -0,0 +1,16 @@ +error[E0271]: expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box`, but it returns `impl Sized` + --> $DIR/issue-98608.rs:6:39 + | +LL | fn hi() -> impl Sized { + | ---------- the found opaque type +... +LL | let b: Box Box> = Box::new(hi); + | ^^^^^^^^^^^^ expected struct `Box`, found opaque type + | + = note: expected struct `Box` + found opaque type `impl Sized` + = note: required for the cast from `fn() -> impl Sized {hi}` to the object type `dyn Fn() -> Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs new file mode 100644 index 000000000..01d1f5db1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs @@ -0,0 +1,7 @@ +#![feature(type_alias_impl_trait)] + +type Opaque<'a, T> = impl Sized; +fn defining<'a, T>(x: &'a i32) -> Opaque { x } +//~^ ERROR: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr new file mode 100644 index 000000000..65a0af0d2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds + --> $DIR/missing_lifetime_bound.rs:4:47 + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } + | -- ^ + | | + | hidden type `&'a i32` captures the lifetime `'a` as defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs new file mode 100644 index 000000000..b887fcf30 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type Y = impl std::fmt::Debug; + +fn g() -> (Y, Y) { + (42_i64, 60) //~ ERROR concrete type differs from previous defining opaque type use +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr new file mode 100644 index 000000000..278117009 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5 + | +LL | (42_i64, 60) + | ^^^^^^^^^^^^ + | | + | expected `i64`, got `i32` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs new file mode 100644 index 000000000..65eb2952e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + (i, i) //~ ERROR concrete type differs from previous +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr new file mode 100644 index 000000000..d7676b8e9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5 + | +LL | (i, i) + | ^^^^^^ + | | + | expected `&'a i32`, got `&'b i32` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs new file mode 100644 index 000000000..21fca047a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(type_alias_impl_trait)] + +type X = impl ToString; + +fn f(a: A, b: B) -> (X, X) { + (a.clone(), a) +} + +pub trait Captures<'a> {} + +impl<'a, T: ?Sized> Captures<'a> for T {} + +type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>; + +fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { + (i, j) +} + +fn main() { + println!("{}", as ToString>::to_string(&f(42_i32, String::new()).1)); + let meh = 42; + let muh = 69; + println!("{:?}", foo(&meh, &muh)); +} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs new file mode 100644 index 000000000..da845e861 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type X = impl Into<&'static A>; + +fn f(a: &'static A, b: B) -> (X, X) { + //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied + (a, a) +} + +fn main() { + println!("{}", as Into<&String>>::into(f(&[1isize, 2, 3], String::new()).1)); +} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr new file mode 100644 index 000000000..66a6b0bbf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied + --> $DIR/multiple-def-uses-in-one-fn.rs:9:45 + | +LL | fn f(a: &'static A, b: B) -> (X, X) { + | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` + | + = note: required for `&A` to implement `Into<&'static B>` +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | fn f(a: &'static A, b: B) -> (X, X) where &'static B: From<&A> { + | ++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs new file mode 100644 index 000000000..14510a529 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type X = impl ToString; + +fn f(a: A, b: B) -> (X, X) { + (a.clone(), a) + //~^ ERROR concrete type differs from previous defining opaque type +} + +fn main() { + println!("{}", as ToString>::to_string(&f(42_i32, String::new()).1)); +} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr new file mode 100644 index 000000000..0f752212a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr @@ -0,0 +1,11 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5 + | +LL | (a.clone(), a) + | ^^^^^^^^^^^^^^ + | | + | expected `A`, got `B` + | this expression supplies two conflicting concrete types for the same opaque type + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs new file mode 100644 index 000000000..11a922443 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs @@ -0,0 +1,18 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(type_alias_impl_trait)] + +type X = impl ToString; + +fn f(a: A, b: B) -> (X, X) { + (a, b) +} + +fn g(a: A, b: B) -> (X, X) { + (a, b) + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr new file mode 100644 index 000000000..bbe709dcc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9 + | +LL | fn g(a: A, b: B) -> (X, X) { + | - - found type parameter + | | + | expected type parameter +LL | (a, b) + | ^ expected type parameter `A`, found type parameter `B` + | + = note: expected type parameter `A` + found type parameter `B` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/multiple_definitions.rs b/tests/ui/type-alias-impl-trait/multiple_definitions.rs new file mode 100644 index 000000000..9e6268e63 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple_definitions.rs @@ -0,0 +1,30 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct ConcreteError {} +pub trait IoBase {} +struct X {} +impl IoBase for X {} + +pub struct ClusterIterator { + pub fat: B, + phantom_s: PhantomData, + phantom_e: PhantomData, +} + +pub struct FileSystem { + pub disk: IO, +} + +impl FileSystem { + pub fn cluster_iter(&self) -> ClusterIterator { + ClusterIterator { + fat: X {}, + phantom_s: PhantomData::default(), + phantom_e: PhantomData::default(), + } + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs new file mode 100644 index 000000000..822489716 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; + +trait Foo { } + +impl Foo<()> for () { } + +fn foo() -> impl Foo { + //~^ ERROR: the trait bound `(): Foo` is not satisfied + // FIXME(type-alias-impl-trait): We could probably make this work. + () +} + +fn main() { } diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr new file mode 100644 index 000000000..62db019ed --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference.rs:12:13 + | +LL | fn foo() -> impl Foo { + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +... +LL | () + | -- return type was inferred to be `()` here + | + = help: the trait `Foo<()>` is implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs new file mode 100644 index 000000000..0d7f5bad2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; + +trait Foo {} + +impl Foo<()> for () {} +impl Foo for () {} + +fn foo() -> impl Foo { + //~^ ERROR: the trait bound `(): Foo` is not satisfied + () +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr new file mode 100644 index 000000000..f4d96038d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/nested-tait-inference2.rs:13:13 + | +LL | fn foo() -> impl Foo { + | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +LL | +LL | () + | -- return type was inferred to be `()` here + | + = help: the following other types implement trait `Foo`: + <() as Foo<()>> + <() as Foo> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs new file mode 100644 index 000000000..b0ebdd1bf --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type FooX = impl Debug; +//~^ ERROR unconstrained opaque type + +trait Foo { } + +impl Foo for () { } + +fn foo() -> impl Foo { + () +} + +fn main() { } diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr new file mode 100644 index 000000000..b1d947a9c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/nested-tait-inference3.rs:6:13 + | +LL | type FooX = impl Debug; + | ^^^^^^^^^^ + | + = note: `FooX` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/nested.rs b/tests/ui/type-alias-impl-trait/nested.rs new file mode 100644 index 000000000..6b866be7d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl Trait; + +trait Trait {} + +impl Trait for U {} + +fn bar() -> Bar { + 42 +} + +fn main() { + println!("{:?}", bar()); + //~^ ERROR `Bar` doesn't implement `Debug` +} diff --git a/tests/ui/type-alias-impl-trait/nested.stderr b/tests/ui/type-alias-impl-trait/nested.stderr new file mode 100644 index 000000000..732af5c0b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested.stderr @@ -0,0 +1,12 @@ +error[E0277]: `Bar` doesn't implement `Debug` + --> $DIR/nested.rs:15:22 + | +LL | println!("{:?}", bar()); + | ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `Bar` + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs new file mode 100644 index 000000000..60b6e1aac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +mod my_mod { + use std::fmt::Debug; + + pub type Foo = impl Debug; + pub type Foot = impl Debug; + + pub fn get_foo() -> Foo { + 5i32 + } + + pub fn get_foot() -> Foot { + get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type + } +} + +fn main() { + let _: my_mod::Foot = my_mod::get_foot(); +} diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr new file mode 100644 index 000000000..fa6ecf68d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr @@ -0,0 +1,19 @@ +error: opaque type's hidden type cannot be another opaque type from the same scope + --> $DIR/nested_type_alias_impl_trait.rs:14:9 + | +LL | get_foo() + | ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope + | +note: opaque type whose hidden type is being assigned + --> $DIR/nested_type_alias_impl_trait.rs:7:21 + | +LL | pub type Foot = impl Debug; + | ^^^^^^^^^^ +note: opaque type being used as hidden type + --> $DIR/nested_type_alias_impl_trait.rs:6:20 + | +LL | pub type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs new file mode 100644 index 000000000..fed5ac07c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] +// check-pass +fn main() {} + +type NoReveal = impl std::fmt::Debug; + +fn define_no_reveal() -> NoReveal { + "" +} + +fn no_reveal(x: NoReveal) { + let _: &'static str = x; + let _ = x as &'static str; +} diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs new file mode 100644 index 000000000..0f0a02e97 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -0,0 +1,18 @@ +// Issue 52985: user code provides no use case that allows a type alias `impl Trait` +// We now emit a 'unconstrained opaque type' error + +#![feature(type_alias_impl_trait)] + +mod foo { + pub type Foo = impl Copy; + //~^ ERROR unconstrained opaque type + + // make compiler happy about using 'Foo' + pub fn bar(x: Foo) -> Foo { + x + } +} + +fn main() { + let _: foo::Foo = std::mem::transmute(0u8); +} diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr new file mode 100644 index 000000000..f3e8ae9c7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/no_inferrable_concrete_type.rs:7:20 + | +LL | pub type Foo = impl Copy; + | ^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs new file mode 100644 index 000000000..61153b1e1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +mod boo { + pub type Boo = impl ::std::fmt::Debug; + fn bomp() -> Boo { + "" + } +} + +// We don't actually know the type here. + +fn bomp2() { + let _: &str = bomp(); //~ ERROR mismatched types +} + +fn bomp() -> boo::Boo { + "" //~ ERROR mismatched types +} + +fn bomp_loop() -> boo::Boo { + loop {} +} diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr new file mode 100644 index 000000000..ae03a5b3e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/no_revealing_outside_defining_module.rs:15:19 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ---------------------- the found opaque type +... +LL | let _: &str = bomp(); + | ---- ^^^^^^ expected `&str`, found opaque type + | | + | expected due to this + | + = note: expected reference `&str` + found opaque type `Boo` + +error[E0308]: mismatched types + --> $DIR/no_revealing_outside_defining_module.rs:19:5 + | +LL | pub type Boo = impl ::std::fmt::Debug; + | ---------------------- the expected opaque type +... +LL | fn bomp() -> boo::Boo { + | -------- expected `Boo` because of return type +LL | "" + | ^^ expected opaque type, found `&str` + | + = note: expected opaque type `Boo` + found reference `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs new file mode 100644 index 000000000..fa47d13f5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -0,0 +1,36 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +fn main() {} + +type Two = impl Debug; + +fn three(t: T) -> Two { + (t, 5i8) + //~^ ERROR `T` doesn't implement `Debug` +} + +trait Bar { + type Blub: Debug; + const FOO: Self::Blub; +} + +impl Bar for u32 { + type Blub = i32; + const FOO: i32 = 42; +} + +fn four(t: T) -> Two { + (t, ::FOO) + //~^ ERROR `U: Bar` is not satisfied + //~| ERROR `T` doesn't implement `Debug` +} + +fn is_sync() {} + +fn asdfl() { + //FIXME(oli-obk): these currently cause cycle errors + //is_sync::>(); + //is_sync::>(); +} diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr new file mode 100644 index 000000000..b11198c58 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -0,0 +1,38 @@ +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/not_a_defining_use.rs:10:5 + | +LL | (t, 5i8) + | ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, i8)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error[E0277]: the trait bound `U: Bar` is not satisfied + --> $DIR/not_a_defining_use.rs:25:5 + | +LL | (t, ::FOO) + | ^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `U` + | +help: consider restricting type parameter `U` + | +LL | type Two = impl Debug; + | +++++ + +error[E0277]: `T` doesn't implement `Debug` + --> $DIR/not_a_defining_use.rs:25:5 + | +LL | (t, ::FOO) + | ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = note: required for `(T, _)` to implement `Debug` +help: consider restricting type parameter `T` + | +LL | type Two = impl Debug; + | +++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.rs b/tests/ui/type-alias-impl-trait/not_well_formed.rs new file mode 100644 index 000000000..fbb7a4d58 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_well_formed.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait TraitWithAssoc { + type Assoc; +} + +type Foo = impl Trait; //~ associated type `Assoc` not found for `V` + +trait Trait {} + +impl Trait for () {} + +fn foo_desugared(_: T) -> Foo { + () +} diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.stderr b/tests/ui/type-alias-impl-trait/not_well_formed.stderr new file mode 100644 index 000000000..c36b95f47 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/not_well_formed.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Assoc` not found for `V` + --> $DIR/not_well_formed.rs:9:29 + | +LL | type Foo = impl Trait; + | ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs new file mode 100644 index 000000000..b8fac45b7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs @@ -0,0 +1,18 @@ +// Here we process outlive obligations involving +// opaque types with bound vars in substs. +// This was an ICE. +// +// check-pass +#![feature(type_alias_impl_trait)] + +type Ty<'a> = impl Sized + 'a; +fn define<'a>() -> Ty<'a> {} + +// Ty<'^0>: 'static +fn test1(_: &'static fn(Ty<'_>)) {} + +fn test2() { + None::<&fn(Ty<'_>)>; +} + +fn main() { } diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs new file mode 100644 index 000000000..7ecb55353 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Debug; + +type Foo = impl Debug; +//~^ ERROR cycle detected + +fn is_send() { } + +fn not_good() { + // Error: this function does not constrain `Foo` to any particular + // hidden type, so it cannot rely on `Send` being true. + is_send::(); +} + +fn not_gooder() { + // Constrain `Foo = u32` + let x: Foo = 22_u32; + + // while we could know this from the hidden type, it would + // need extra roundabout logic to support it. + is_send::(); +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr new file mode 100644 index 000000000..27fded333 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr @@ -0,0 +1,28 @@ +error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` + --> $DIR/reveal_local.rs:5:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + | +note: ...which requires type-checking `not_good`... + --> $DIR/reveal_local.rs:13:5 + | +LL | is_send::(); + | ^^^^^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`... + = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/reveal_local.rs:1:1 + | +LL | / #![feature(type_alias_impl_trait)] +LL | | +LL | | use std::fmt::Debug; +LL | | +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs new file mode 100644 index 000000000..8781196c3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl std::fmt::Debug; +type Bar = impl PartialEq; + +fn bar() -> Bar { + 42_i32 //~^ ERROR can't compare `i32` with `Foo` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.stderr new file mode 100644 index 000000000..c2cf70687 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: can't compare `i32` with `Foo` + --> $DIR/self-referential-2.rs:6:13 + | +LL | fn bar() -> Bar { + | ^^^ no implementation for `i32 == Foo` +LL | 42_i32 + | ------ return type was inferred to be `i32` here + | + = help: the trait `PartialEq` is not implemented for `i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs new file mode 100644 index 000000000..d40715717 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i +} + +fn main() { + let meh = 42; + let muh = 42; + assert_eq!(bar(&meh), bar(&muh)); +} diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.rs b/tests/ui/type-alias-impl-trait/self-referential-4.rs new file mode 100644 index 000000000..36742c8ad --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-4.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + i //~^ ERROR can't compare `&i32` with `Bar<'b, 'static>` +} + +type Foo<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + i //~^ ERROR can't compare `&i32` with `Foo<'static, 'b>` +} + +type Moo<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + i //~^ ERROR can't compare `&i32` with `Moo<'static, 'a>` +} + +fn main() { + let meh = 42; + let muh = 69; + assert_eq!(bar(&meh), bar(&meh)); +} diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.stderr b/tests/ui/type-alias-impl-trait/self-referential-4.stderr new file mode 100644 index 000000000..98c762e3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-4.stderr @@ -0,0 +1,36 @@ +error[E0277]: can't compare `&i32` with `Bar<'b, 'static>` + --> $DIR/self-referential-4.rs:5:31 + | +LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'static>` +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` + --> $DIR/self-referential-4.rs:11:31 + | +LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Foo<'static, 'b>` +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` + --> $DIR/self-referential-4.rs:17:31 + | +LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Moo<'static, 'a>` +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs new file mode 100644 index 000000000..3ff5406a3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; + +fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + //~^ ERROR can't compare `&i32` with `Bar<'b, 'a>` + i +} + +type Foo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); + +fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + //~^ ERROR can't compare `&i32` with `(i32, &i32)` + (42, i) +} + +type Moo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); + +fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` + (42, i) +} + +fn main() { + let meh = 42; + let muh = 69; + assert_eq!(bar(&meh), bar(&meh)); +} diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr new file mode 100644 index 000000000..aff489d70 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential.stderr @@ -0,0 +1,39 @@ +error[E0277]: can't compare `&i32` with `Bar<'b, 'a>` + --> $DIR/self-referential.rs:5:31 + | +LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'a>` +LL | +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `(i32, &i32)` + --> $DIR/self-referential.rs:12:31 + | +LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, &i32)` +LL | +LL | (42, i) + | ------- return type was inferred to be `(i32, &i32)` here + | + = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` + --> $DIR/self-referential.rs:19:31 + | +LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})` +LL | +LL | (42, i) + | ------- return type was inferred to be `(i32, &i32)` here + | + = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self_implication.rs b/tests/ui/type-alias-impl-trait/self_implication.rs new file mode 100644 index 000000000..4e805ee30 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self_implication.rs @@ -0,0 +1,38 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +fn foo() { + struct Foo<'a> { + x: &'a mut u8, + } + impl<'a> Foo<'a> { + fn foo(&self) -> impl Sized {} + } + // use site + let mut x = 5; + let y = Foo { x: &mut x }; + let z = y.foo(); + let _a = &x; // invalidate the `&'a mut`in `y` + let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live +} + +fn bar() { + struct Foo<'a> { + x: &'a mut u8, + } + + // desugared + type FooX<'a> = impl Sized; + impl<'a> Foo<'a> { + fn foo(&self) -> FooX<'a> {} + } + + // use site + let mut x = 5; + let y = Foo { x: &mut x }; + let z = y.foo(); + let _a = &x; // invalidate the `&'a mut`in `y` + let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/static-const-types.rs b/tests/ui/type-alias-impl-trait/static-const-types.rs new file mode 100644 index 000000000..748a279e4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/static-const-types.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// check-pass + +use std::fmt::Debug; + +type Foo = impl Debug; + +static FOO1: Foo = 22_u32; +const FOO2: Foo = 22_u32; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs new file mode 100644 index 000000000..c2ab6a9d1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +type Bar = impl Send; + +// While i32 is structural-match, we do not want to leak this information. +// (See https://github.com/rust-lang/rust/issues/72156) +const fn leak_free() -> Bar { + 7i32 +} +const LEAK_FREE: Bar = leak_free(); + +fn leak_free_test() { + match LEAK_FREE { + LEAK_FREE => (), + //~^ `Bar` cannot be used in patterns + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr new file mode 100644 index 000000000..dbc183f54 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr @@ -0,0 +1,8 @@ +error: `Bar` cannot be used in patterns + --> $DIR/structural-match-no-leak.rs:14:9 + | +LL | LEAK_FREE => (), + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/structural-match.rs b/tests/ui/type-alias-impl-trait/structural-match.rs new file mode 100644 index 000000000..7cc9ccaab --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match.rs @@ -0,0 +1,21 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Send; + +// This is not structural-match +struct A; + +const fn value() -> Foo { + A +} +const VALUE: Foo = value(); + +fn test() { + match VALUE { + VALUE => (), + //~^ `Foo` cannot be used in patterns + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr new file mode 100644 index 000000000..61287f268 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/structural-match.stderr @@ -0,0 +1,8 @@ +error: `Foo` cannot be used in patterns + --> $DIR/structural-match.rs:15:9 + | +LL | VALUE => (), + | ^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs new file mode 100644 index 000000000..f6a830296 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Foo = Box>; + +fn make_foo() -> Foo { + Box::new(vec![1, 2, 3].into_iter()) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs new file mode 100644 index 000000000..fddecfcac --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Foo = impl Iterator; + +fn make_foo() -> Foo { + vec![1, 2].into_iter() +} + +type Bar = impl Send; +type Baz = impl Iterator; + +fn make_baz() -> Baz { + vec!["1", "2"].into_iter() +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs new file mode 100644 index 000000000..5630e036b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -0,0 +1,11 @@ +#![feature(type_alias_impl_trait)] +// check-pass +// Ensures that `const` items can constrain an opaque `impl Trait`. + +use std::fmt::Debug; + +pub type Foo = impl Debug; + +const _FOO: Foo = 5; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs new file mode 100644 index 000000000..857066c78 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME: this is ruled out for now but should work + +type Foo = fn() -> impl Send; +//~^ ERROR: `impl Trait` only allowed in function and inherent method return types + +fn make_foo() -> Foo { + || 15 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr new file mode 100644 index 000000000..a31cf1a51 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr @@ -0,0 +1,9 @@ +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return + --> $DIR/type-alias-impl-trait-fn-type.rs:6:20 + | +LL | type Foo = fn() -> impl Send; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs new file mode 100644 index 000000000..07c891f06 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs @@ -0,0 +1,26 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +// Regression test for issue #61863 + +pub trait MyTrait {} + +#[derive(Debug)] +pub struct MyStruct { + v: u64, +} + +impl MyTrait for MyStruct {} + +pub fn bla() -> TE { + return MyStruct { v: 1 }; +} + +pub fn bla2() -> TE { + bla() +} + +type TE = impl MyTrait; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs new file mode 100644 index 000000000..c5e8068e5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type A = impl Sized; +fn f1() -> A { + 0 +} + +type B = impl ?Sized; +fn f2() -> &'static B { + &[0] +} + +type C = impl ?Sized + 'static; +fn f3() -> &'static C { + &[0] +} + +type D = impl ?Sized; +fn f4() -> &'static D { + &1 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs new file mode 100644 index 000000000..1a4064055 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +type Foo = Vec; + +fn make_foo() -> Foo { + vec![true, false] +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs new file mode 100644 index 000000000..1f2d0e47e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +pub trait MyTrait {} + +impl MyTrait for bool {} + +type Foo = impl MyTrait; + +struct Blah { + my_foo: Foo, + my_u8: u8, +} + +impl Blah { + fn new() -> Blah { + Blah { my_foo: make_foo(), my_u8: 12 } + } + fn into_inner(self) -> (Foo, u8, Foo) { + (self.my_foo, self.my_u8, make_foo()) + } +} + +fn make_foo() -> Foo { + true +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs new file mode 100644 index 000000000..efbf4f1e3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs @@ -0,0 +1,18 @@ +// regression test for #74018 + +#![feature(type_alias_impl_trait)] + +trait Trait { + type Associated; + fn into(self) -> Self::Associated; +} + +impl<'a, I: Iterator> Trait for (i32, I) { + //~^ ERROR the lifetime parameter `'a` is not constrained + type Associated = (i32, impl Iterator); + fn into(self) -> Self::Associated { + (0_i32, [0_i32].iter().copied()) + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr new file mode 100644 index 000000000..8cdce2f8e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/type-alias-impl-trait-unconstrained-lifetime.rs:10:6 + | +LL | impl<'a, I: Iterator> Trait for (i32, I) { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs new file mode 100644 index 000000000..e5e7fb677 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.rs @@ -0,0 +1,12 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl Fn() -> Foo; +//~^ ERROR: unconstrained opaque type + +fn crash(x: Foo) -> Foo { + x +} + +fn main() { + +} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr new file mode 100644 index 000000000..a770eeac3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12 + | +LL | type Foo = impl Fn() -> Foo; + | ^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs new file mode 100644 index 000000000..7c7a1b405 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +pub trait Bar { + type Item; +} + +type Foo = impl Bar; +//~^ ERROR: unconstrained opaque type + +fn crash(x: Foo) -> Foo { + x +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr new file mode 100644 index 000000000..3f3699ce5 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr @@ -0,0 +1,10 @@ +error: unconstrained opaque type + --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12 + | +LL | type Foo = impl Bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + +error: aborting due to previous error + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs new file mode 100644 index 000000000..8ca279eec --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] + +type Foo = impl 'static; +//~^ ERROR: at least one trait must be specified + +fn foo() -> Foo { + "foo" +} + +fn bar() -> impl 'static { //~ ERROR: at least one trait must be specified + "foo" +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr new file mode 100644 index 000000000..3f7acd338 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr @@ -0,0 +1,14 @@ +error: at least one trait must be specified + --> $DIR/type-alias-impl-trait-with-no-traits.rs:3:12 + | +LL | type Foo = impl 'static; + | ^^^^^^^^^^^^ + +error: at least one trait must be specified + --> $DIR/type-alias-impl-trait-with-no-traits.rs:10:13 + | +LL | fn bar() -> impl 'static { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs new file mode 100644 index 000000000..70c2ee427 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs @@ -0,0 +1,79 @@ +// check-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![feature(type_alias_impl_trait)] + +fn main() { + assert_eq!(foo().to_string(), "foo"); + assert_eq!(bar1().to_string(), "bar1"); + assert_eq!(bar2().to_string(), "bar2"); + let mut x = bar1(); + x = bar2(); + assert_eq!(my_iter(42u8).collect::>(), vec![42u8]); +} + +// single definition +type Foo = impl std::fmt::Display; + +fn foo() -> Foo { + "foo" +} + +// two definitions +type Bar = impl std::fmt::Display; + +fn bar1() -> Bar { + "bar1" +} + +fn bar2() -> Bar { + "bar2" +} + +type MyIter = impl Iterator; + +fn my_iter(t: T) -> MyIter { + std::iter::once(t) +} + +fn my_iter2(t: T) -> MyIter { + std::iter::once(t) +} + +// param names should not have an effect! +fn my_iter3(u: U) -> MyIter { + std::iter::once(u) +} + +// param position should not have an effect! +fn my_iter4(_: U, v: V) -> MyIter { + std::iter::once(v) +} + +// param names should not have an effect! +type MyOtherIter = impl Iterator; + +fn my_other_iter(u: U) -> MyOtherIter { + std::iter::once(u) +} + +trait Trait {} +type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; + +fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { + t +} + +mod pass_through { + pub type Passthrough = impl Sized + 'static; + + fn define_passthrough(t: T) -> Passthrough { + t + } +} + +fn use_passthrough(x: pass_through::Passthrough) -> pass_through::Passthrough { + x +} diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs new file mode 100644 index 000000000..67f56bcde --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs @@ -0,0 +1,84 @@ +// check-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![feature(type_alias_impl_trait)] + +fn main() { + assert_eq!(foo().to_string(), "foo"); + assert_eq!(bar1().to_string(), "bar1"); + assert_eq!(bar2().to_string(), "bar2"); + let mut x = bar1(); + x = bar2(); + assert_eq!(my_iter(42u8).collect::>(), vec![42u8]); +} + +use defining_use_scope::*; + +mod defining_use_scope { + // single definition + pub type Foo = impl std::fmt::Display; + + pub fn foo() -> Foo { + "foo" + } + + // two definitions + pub type Bar = impl std::fmt::Display; + + pub fn bar1() -> Bar { + "bar1" + } + + pub fn bar2() -> Bar { + "bar2" + } + + pub type MyIter = impl Iterator; + + pub fn my_iter(t: T) -> MyIter { + std::iter::once(t) + } + + fn my_iter2(t: T) -> MyIter { + std::iter::once(t) + } + + // param names should not have an effect! + fn my_iter3(u: U) -> MyIter { + std::iter::once(u) + } + + // param position should not have an effect! + fn my_iter4(_: U, v: V) -> MyIter { + std::iter::once(v) + } + + // param names should not have an effect! + type MyOtherIter = impl Iterator; + + fn my_other_iter(u: U) -> MyOtherIter { + std::iter::once(u) + } + + trait Trait {} + type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a; + + fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> { + t + } + + mod pass_through { + pub type Passthrough = impl Sized + 'static; + + fn define_passthrough(t: T) -> Passthrough { + t + } + } + + fn use_passthrough(x: pass_through::Passthrough) -> pass_through::Passthrough { + x + } + +} diff --git a/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs new file mode 100644 index 000000000..fd954801d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(type_alias_impl_trait)] + +use std::iter::{once, Chain}; + +type I = Chain>; +fn test2>(x: A) -> I { + x.chain(once("5")) +} + +fn main() { + assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::>()); +} diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs new file mode 100644 index 000000000..4e9d1788b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::fmt::Debug; + +type Foo = impl Debug; + +fn foo1() -> u32 { + let x: Foo = 22_u32; + x +} + +fn foo2() -> u32 { + let x: Foo = 22_u32; + let y: Foo = x; + same_type((x, y)); //~ ERROR use of moved value + y //~ ERROR use of moved value +} + +fn same_type(x: (T, T)) {} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr new file mode 100644 index 000000000..1dabe4586 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/type_of_a_let.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `x` + --> $DIR/type_of_a_let.rs:16:16 + | +LL | let x: Foo = 22_u32; + | - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait +LL | let y: Foo = x; + | - value moved here +LL | same_type((x, y)); + | ^ value used here after move + +error[E0382]: use of moved value: `y` + --> $DIR/type_of_a_let.rs:17:5 + | +LL | let y: Foo = x; + | - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait +LL | same_type((x, y)); + | - value moved here +LL | y + | ^ value used here after move + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs new file mode 100644 index 000000000..f43ad7dce --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +type Opaque = impl Sized; +fn defining() -> Opaque {} +struct Ss<'a, T>(&'a Opaque); + + +fn test<'a, T>(_: Ss<'a, T>) { + // test that we have an implied bound `Opaque: 'a` from fn signature + None::<&'a Opaque>; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.rs b/tests/ui/type-alias-impl-trait/underconstrained_generic.rs new file mode 100644 index 000000000..aa537dfc9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.rs @@ -0,0 +1,28 @@ +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +trait Trait { + fn foo(t: T) -> U; +} + +trait ProofForConversion { + fn convert(_: PhantomData, r: T) -> U; +} + +impl ProofForConversion for () { + fn convert(_: PhantomData, r: T) -> U { + X::foo(r) + } +} + +type Converter = impl ProofForConversion; + +fn _defining_use() -> Converter { + () + //~^ ERROR the trait bound `T: Trait` is not satisfied +} + + +fn main() { +} diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr new file mode 100644 index 000000000..103636b6c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/underconstrained_generic.rs:22:5 + | +LL | () + | ^^ the trait `Trait` is not implemented for `T` + | +note: required for `()` to implement `ProofForConversion` + --> $DIR/underconstrained_generic.rs:13:16 + | +LL | impl ProofForConversion for () { + | ----- ^^^^^^^^^^^^^^^^^^^^^ ^^ + | | + | unsatisfied trait bound introduced here +help: consider restricting type parameter `T` + | +LL | type Converter = impl ProofForConversion; + | +++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs new file mode 100644 index 000000000..c5b2e8a1c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs @@ -0,0 +1,34 @@ +#![feature(type_alias_impl_trait)] + +use std::marker::PhantomData; + +trait ProofForConversion<'a, 'b> { + fn convert(_: PhantomData, r: &'a T) -> &'b T; +} + +impl<'a, 'b> ProofForConversion<'a, 'b> for &'b &'a () { + fn convert(_: PhantomData, r: &'a T) -> &'b T { + r + } +} + +type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; +//~^ ERROR reference has a longer lifetime than the data it references + +// Even _defining_use with an explicit `'a: 'b` compiles fine, too. +fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> { + x +} + +fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { + Converter::<'a, 'b>::convert(PhantomData, x) +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = extend_lifetime(&x); + } + println!("{}", d); +} diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr new file mode 100644 index 000000000..12d85a49d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/underconstrained_lifetime.rs:15:26 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined here + --> $DIR/underconstrained_lifetime.rs:15:20 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/underconstrained_lifetime.rs:15:16 + | +LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.rs b/tests/ui/type-alias-impl-trait/unnameable_type.rs new file mode 100644 index 000000000..1739ab006 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unnameable_type.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +// This test ensures that unnameable types stay unnameable +// https://github.com/rust-lang/rust/issues/63063#issuecomment-1360053614 + +// library +mod private { + pub struct Private; + pub trait Trait { + fn dont_define_this(_private: Private) {} + } +} + +use private::Trait; + +// downstream +type MyPrivate = impl Sized; +//~^ ERROR: unconstrained opaque type +impl Trait for u32 { + fn dont_define_this(_private: MyPrivate) {} + //~^ ERROR: incompatible type for trait +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr new file mode 100644 index 000000000..7dc6efc4b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -0,0 +1,31 @@ +error: unconstrained opaque type + --> $DIR/unnameable_type.rs:17:18 + | +LL | type MyPrivate = impl Sized; + | ^^^^^^^^^^ + | + = note: `MyPrivate` must be used in combination with a concrete type within the same module + +error[E0053]: method `dont_define_this` has an incompatible type for trait + --> $DIR/unnameable_type.rs:20:35 + | +LL | type MyPrivate = impl Sized; + | ---------- the found opaque type +... +LL | fn dont_define_this(_private: MyPrivate) {} + | ^^^^^^^^^ + | | + | expected struct `Private`, found opaque type + | help: change the parameter type to match the trait: `Private` + | +note: type in trait + --> $DIR/unnameable_type.rs:10:39 + | +LL | fn dont_define_this(_private: Private) {} + | ^^^^^^^ + = note: expected signature `fn(Private)` + found signature `fn(MyPrivate)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/type-alias-impl-trait/unused_generic_param.rs b/tests/ui/type-alias-impl-trait/unused_generic_param.rs new file mode 100644 index 000000000..ad5e4918c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unused_generic_param.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +fn main() {} + +type PartiallyDefined = impl Sized; + +fn partially_defined(_: T) -> PartiallyDefined { + 4u32 +} + +type PartiallyDefined2 = impl Sized; + +fn partially_defined2(_: T) -> PartiallyDefined2 { + 4u32 +} + +fn partially_defined22(_: T) -> PartiallyDefined2 { + 4u32 +} diff --git a/tests/ui/type-alias-impl-trait/weird-return-types.rs b/tests/ui/type-alias-impl-trait/weird-return-types.rs new file mode 100644 index 000000000..faad5ee95 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/weird-return-types.rs @@ -0,0 +1,16 @@ +// edition:2018 +// check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::future::Future; +use std::fmt::Debug; + +type Foo = impl Debug; + +fn f() -> impl Future { + async move { 22_u32 } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs b/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs new file mode 100644 index 000000000..449e9fbd0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +type FooFn = impl FnOnce(B); + +fn foo() -> FooFn { + fn mop(bar: B) { bar.bar() } + mop // NOTE: no function pointer, but function zst item + //~^ ERROR the trait bound `B: Bar` is not satisfied +} + +fn main() { + let boom: FooFn = unsafe { core::mem::zeroed() }; + boom(42); +} diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr new file mode 100644 index 000000000..e0005489d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/wf-check-fn-def.rs:11:5 + | +LL | mop // NOTE: no function pointer, but function zst item + | ^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `mop` + --> $DIR/wf-check-fn-def.rs:10:15 + | +LL | fn mop(bar: B) { bar.bar() } + | ^^^ required by this bound in `mop` +help: consider restricting type parameter `B` + | +LL | type FooFn = impl FnOnce(B); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs b/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs new file mode 100644 index 000000000..3b8470e4a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs @@ -0,0 +1,23 @@ +#![feature(type_alias_impl_trait)] + +// build-pass + +trait Bar { + fn bar(&self); +} + +type FooFn = impl FnOnce(B); + +fn foo() -> FooFn { + fn mop(bar: B) { bar.bar() } + mop as fn(B) + // function pointers don't have any obligations on them, + // thus the above compiles. It's obviously unsound to just + // procure a `FooFn` from the ether without making sure that + // the pointer is actually legal for all `B` +} + +fn main() { + let boom: FooFn = unsafe { core::mem::zeroed() }; + boom(42); +} diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.rs b/tests/ui/type-alias-impl-trait/wf_check_closures.rs new file mode 100644 index 000000000..2c70696ff --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +trait Bar { + fn bar(&self); +} + +type FooFn = impl FnOnce(); + +fn foo(bar: B) -> FooFn { + move || { bar.bar() } + //~^ ERROR the trait bound `B: Bar` is not satisfied +} + +fn main() { + let boom: FooFn = unsafe { core::mem::zeroed() }; + boom(); +} diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr new file mode 100644 index 000000000..58ae8617b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `B: Bar` is not satisfied + --> $DIR/wf_check_closures.rs:10:5 + | +LL | move || { bar.bar() } + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | +note: required by a bound in `foo` + --> $DIR/wf_check_closures.rs:9:11 + | +LL | fn foo(bar: B) -> FooFn { + | ^^^ required by this bound in `foo` +help: consider restricting type parameter `B` + | +LL | type FooFn = impl FnOnce(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias/issue-14933.rs b/tests/ui/type-alias/issue-14933.rs new file mode 100644 index 000000000..bd95332ca --- /dev/null +++ b/tests/ui/type-alias/issue-14933.rs @@ -0,0 +1,6 @@ +// check-pass +// pretty-expanded FIXME #23616 + +pub type BigRat = T; + +fn main() {} diff --git a/tests/ui/type-alias/issue-37515.rs b/tests/ui/type-alias/issue-37515.rs new file mode 100644 index 000000000..b3a870d50 --- /dev/null +++ b/tests/ui/type-alias/issue-37515.rs @@ -0,0 +1,8 @@ +// check-pass + +#![warn(unused)] + +type Z = dyn for<'x> Send; +//~^ WARN type alias `Z` is never used + +fn main() {} diff --git a/tests/ui/type-alias/issue-37515.stderr b/tests/ui/type-alias/issue-37515.stderr new file mode 100644 index 000000000..f1e83ca74 --- /dev/null +++ b/tests/ui/type-alias/issue-37515.stderr @@ -0,0 +1,15 @@ +warning: type alias `Z` is never used + --> $DIR/issue-37515.rs:5:6 + | +LL | type Z = dyn for<'x> Send; + | ^ + | +note: the lint level is defined here + --> $DIR/issue-37515.rs:3:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(dead_code)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + diff --git a/tests/ui/type-alias/issue-62263-self-in-atb.rs b/tests/ui/type-alias/issue-62263-self-in-atb.rs new file mode 100644 index 000000000..91522d891 --- /dev/null +++ b/tests/ui/type-alias/issue-62263-self-in-atb.rs @@ -0,0 +1,8 @@ +pub trait Trait { + type A; +} + +pub type Alias = dyn Trait; +//~^ ERROR failed to resolve: `Self` + +fn main() {} diff --git a/tests/ui/type-alias/issue-62263-self-in-atb.stderr b/tests/ui/type-alias/issue-62263-self-in-atb.stderr new file mode 100644 index 000000000..c20074dc2 --- /dev/null +++ b/tests/ui/type-alias/issue-62263-self-in-atb.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions + --> $DIR/issue-62263-self-in-atb.rs:5:32 + | +LL | pub type Alias = dyn Trait; + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/type-alias/issue-62305-self-assoc-ty.rs b/tests/ui/type-alias/issue-62305-self-assoc-ty.rs new file mode 100644 index 000000000..a4d9a2854 --- /dev/null +++ b/tests/ui/type-alias/issue-62305-self-assoc-ty.rs @@ -0,0 +1,4 @@ +type Alias = Self::Target; +//~^ ERROR failed to resolve: `Self` + +fn main() {} diff --git a/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr b/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr new file mode 100644 index 000000000..f3da50df9 --- /dev/null +++ b/tests/ui/type-alias/issue-62305-self-assoc-ty.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions + --> $DIR/issue-62305-self-assoc-ty.rs:1:14 + | +LL | type Alias = Self::Target; + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/type-alias/issue-62364-self-ty-arg.rs b/tests/ui/type-alias/issue-62364-self-ty-arg.rs new file mode 100644 index 000000000..bebb4a902 --- /dev/null +++ b/tests/ui/type-alias/issue-62364-self-ty-arg.rs @@ -0,0 +1,8 @@ +struct Struct { + field: P1, +} + +type Alias<'a> = Struct<&'a Self>; +//~^ ERROR cannot find type `Self` in this scope [E0411] + +fn main() {} diff --git a/tests/ui/type-alias/issue-62364-self-ty-arg.stderr b/tests/ui/type-alias/issue-62364-self-ty-arg.stderr new file mode 100644 index 000000000..7e15e42e3 --- /dev/null +++ b/tests/ui/type-alias/issue-62364-self-ty-arg.stderr @@ -0,0 +1,11 @@ +error[E0411]: cannot find type `Self` in this scope + --> $DIR/issue-62364-self-ty-arg.rs:5:29 + | +LL | type Alias<'a> = Struct<&'a Self>; + | ----- ^^^^ `Self` is only available in impls, traits, and type definitions + | | + | `Self` not allowed in a type alias + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0411`. diff --git a/tests/ui/type-id-higher-rank-2.rs b/tests/ui/type-id-higher-rank-2.rs new file mode 100644 index 000000000..5391c849d --- /dev/null +++ b/tests/ui/type-id-higher-rank-2.rs @@ -0,0 +1,31 @@ +// run-pass +// Test that we can't ignore lifetimes by going through Any. + +use std::any::Any; + +struct Foo<'a>(&'a str); + +fn good(s: &String) -> Foo { Foo(s) } + +fn bad1(s: String) -> Option<&'static str> { + let a: Box = Box::new(good as fn(&String) -> Foo); + a.downcast_ref:: Foo<'static>>().map(|f| f(&s).0) +} + +trait AsStr<'a, 'b> { + fn get(&'a self) -> &'b str; +} + +impl<'a> AsStr<'a, 'a> for String { + fn get(&'a self) -> &'a str { self } +} + +fn bad2(s: String) -> Option<&'static str> { + let a: Box = Box::new(Box::new(s) as Box AsStr<'a, 'a>>); + a.downcast_ref:: AsStr<'a, 'static>>>().map(|x| x.get()) +} + +fn main() { + assert_eq!(bad1(String::from("foo")), None); + assert_eq!(bad2(String::from("bar")), None); +} diff --git a/tests/ui/type-inference/issue-30225.rs b/tests/ui/type-inference/issue-30225.rs new file mode 100644 index 000000000..42315332c --- /dev/null +++ b/tests/ui/type-inference/issue-30225.rs @@ -0,0 +1,38 @@ +// Regression test for #30225, which was an ICE that would trigger as +// a result of a poor interaction between trait result caching and +// type inference. Specifically, at that time, unification could cause +// unrelated type variables to become instantiated, if subtyping +// relationships existed. These relationships are now propagated +// through obligations and hence everything works out fine. + +trait Foo : Sized { + fn foo(self, u: Option, v: Option) {} +} + +struct A; +struct B; + +impl Foo for () {} // impl A +impl Foo for u32 {} // impl B, creating ambiguity + +fn toxic() { + // cache the resolution <() as Foo<$0,$1>> = impl A + let u = None; + let v = None; + Foo::foo((), u, v); +} + +fn bomb() { + let mut u = None; // type is Option<$0> + let mut v = None; // type is Option<$1> + let mut x = None; // type is Option<$2> + + Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>> + u = v; // mark $0 and $1 in a subtype relationship + //~^ ERROR mismatched types + x = Some(()); // set $2 = (), allowing impl selection + // to proceed for <() as Foo<$0, $1>> = impl A. + // kaboom, this *used* to trigge an ICE +} + +fn main() {} diff --git a/tests/ui/type-inference/issue-30225.stderr b/tests/ui/type-inference/issue-30225.stderr new file mode 100644 index 000000000..ccd05fa6b --- /dev/null +++ b/tests/ui/type-inference/issue-30225.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-30225.rs:31:9 + | +LL | u = v; // mark $0 and $1 in a subtype relationship + | ^ expected struct `A`, found struct `B` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-inference/or_else-multiple-type-params.rs b/tests/ui/type-inference/or_else-multiple-type-params.rs new file mode 100644 index 000000000..b15de2a45 --- /dev/null +++ b/tests/ui/type-inference/or_else-multiple-type-params.rs @@ -0,0 +1,10 @@ +use std::process::{Command, Stdio}; + +fn main() { + let process = Command::new("wc") + .stdout(Stdio::piped()) + .spawn() + .or_else(|err| { //~ ERROR type annotations needed + panic!("oh no: {:?}", err); + }).unwrap(); +} diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr new file mode 100644 index 000000000..6ac63a91e --- /dev/null +++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Result` + --> $DIR/or_else-multiple-type-params.rs:7:18 + | +LL | .or_else(|err| { + | ^^^^^ + | +help: try giving this closure an explicit return type + | +LL | .or_else(|err| -> Result { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/sort_by_key.rs b/tests/ui/type-inference/sort_by_key.rs new file mode 100644 index 000000000..afc4d90b8 --- /dev/null +++ b/tests/ui/type-inference/sort_by_key.rs @@ -0,0 +1,5 @@ +fn main() { + let mut lst: [([i32; 10], bool); 10] = [([0; 10], false); 10]; + lst.sort_by_key(|&(v, _)| v.iter().sum()); //~ ERROR type annotations needed + println!("{:?}", lst); +} diff --git a/tests/ui/type-inference/sort_by_key.stderr b/tests/ui/type-inference/sort_by_key.stderr new file mode 100644 index 000000000..0a48d5756 --- /dev/null +++ b/tests/ui/type-inference/sort_by_key.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/sort_by_key.rs:3:40 + | +LL | lst.sort_by_key(|&(v, _)| v.iter().sum()); + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | +help: consider specifying the generic argument + | +LL | lst.sort_by_key(|&(v, _)| v.iter().sum::()); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/unbounded-associated-type.rs b/tests/ui/type-inference/unbounded-associated-type.rs new file mode 100644 index 000000000..0167e9436 --- /dev/null +++ b/tests/ui/type-inference/unbounded-associated-type.rs @@ -0,0 +1,16 @@ +trait T { + type A; + fn foo(&self) -> Self::A { + panic!() + } +} + +struct S(std::marker::PhantomData); + +impl T for S { + type A = X; +} + +fn main() { + S(std::marker::PhantomData).foo(); //~ ERROR type annotations needed +} diff --git a/tests/ui/type-inference/unbounded-associated-type.stderr b/tests/ui/type-inference/unbounded-associated-type.stderr new file mode 100644 index 000000000..e0fecc72f --- /dev/null +++ b/tests/ui/type-inference/unbounded-associated-type.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/unbounded-associated-type.rs:15:7 + | +LL | S(std::marker::PhantomData).foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` + | +help: consider specifying the generic argument + | +LL | S(std::marker::PhantomData::).foo(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs new file mode 100644 index 000000000..81d054b3a --- /dev/null +++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs @@ -0,0 +1,9 @@ +#[allow(invalid_type_param_default)] + +fn foo() -> (T, U) { + panic!() +} + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr new file mode 100644 index 000000000..209abfe5c --- /dev/null +++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:8:5 + | +LL | foo(); + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | +help: consider specifying the generic arguments + | +LL | foo::(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn.rs b/tests/ui/type-inference/unbounded-type-param-in-fn.rs new file mode 100644 index 000000000..1f336ed59 --- /dev/null +++ b/tests/ui/type-inference/unbounded-type-param-in-fn.rs @@ -0,0 +1,7 @@ +fn foo() -> T { + panic!() +} + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn.stderr new file mode 100644 index 000000000..d92892eeb --- /dev/null +++ b/tests/ui/type-inference/unbounded-type-param-in-fn.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/unbounded-type-param-in-fn.rs:6:5 + | +LL | foo(); + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | +help: consider specifying the generic argument + | +LL | foo::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-namespace.rs b/tests/ui/type-namespace.rs new file mode 100644 index 000000000..3cc0bc447 --- /dev/null +++ b/tests/ui/type-namespace.rs @@ -0,0 +1,7 @@ +// run-pass + +struct A { a: isize } + +fn a(a: A) -> isize { return a.a; } + +pub fn main() { let x: A = A {a: 1}; assert_eq!(a(x), 1); } diff --git a/tests/ui/type-param-constraints.rs b/tests/ui/type-param-constraints.rs new file mode 100644 index 000000000..3d87a089f --- /dev/null +++ b/tests/ui/type-param-constraints.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn p_foo(_pinned: T) { } +fn s_foo(_shared: T) { } +fn u_foo(_unique: T) { } + +struct r { + i: isize, +} + +impl Drop for r { + fn drop(&mut self) {} +} + +fn r(i:isize) -> r { + r { + i: i + } +} + +pub fn main() { + p_foo(r(10)); + + p_foo::>(Box::new(r(10))); + p_foo::>(Box::new(10)); + p_foo(10); + + s_foo::>(Box::new(10)); + s_foo(10); + + u_foo::>(Box::new(10)); + u_foo(10); +} diff --git a/tests/ui/type-param.rs b/tests/ui/type-param.rs new file mode 100644 index 000000000..ca2f24d37 --- /dev/null +++ b/tests/ui/type-param.rs @@ -0,0 +1,11 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] + + +// pretty-expanded FIXME #23616 + +type lteq = extern "C" fn(T) -> bool; + +pub fn main() { } diff --git a/tests/ui/type-ptr.rs b/tests/ui/type-ptr.rs new file mode 100644 index 000000000..7c2438d38 --- /dev/null +++ b/tests/ui/type-ptr.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn f(a: *const isize) -> *const isize { return a; } + +fn g(a: *const isize) -> *const isize { let b = f(a); return b; } + +pub fn main() { return; } diff --git a/tests/ui/type-use-i1-versus-i8.rs b/tests/ui/type-use-i1-versus-i8.rs new file mode 100644 index 000000000..7315cd2fe --- /dev/null +++ b/tests/ui/type-use-i1-versus-i8.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::ptr; + +pub fn main() { + unsafe { + let mut x: bool = false; + // this line breaks it + ptr::write(&mut x, false); + } +} diff --git a/tests/ui/type/ascription/issue-34255-1.rs b/tests/ui/type/ascription/issue-34255-1.rs new file mode 100644 index 000000000..44b47cc4e --- /dev/null +++ b/tests/ui/type/ascription/issue-34255-1.rs @@ -0,0 +1,15 @@ +struct Reactor { + input_cells: Vec, +} + +impl Reactor { + pub fn new() -> Self { + input_cells: Vec::new() + //~^ ERROR cannot find value `input_cells` in this scope + //~| ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR missing generics for struct `Vec` + } +} + +// This case isn't currently being handled gracefully, including for completeness. +fn main() {} diff --git a/tests/ui/type/ascription/issue-34255-1.stderr b/tests/ui/type/ascription/issue-34255-1.stderr new file mode 100644 index 000000000..fafff19f8 --- /dev/null +++ b/tests/ui/type/ascription/issue-34255-1.stderr @@ -0,0 +1,36 @@ +error[E0425]: cannot find value `input_cells` in this scope + --> $DIR/issue-34255-1.rs:7:9 + | +LL | input_cells: Vec::new() + | ^^^^^^^^^^^ a field by this name exists in `Self` + | +help: you might have meant to write a `struct` literal + | +LL ~ pub fn new() -> Self { SomeStruct { +LL | input_cells: Vec::new() + ... +LL | +LL ~ }} + | + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-34255-1.rs:7:27 + | +LL | input_cells: Vec::new() + | ^^^^^ only `Fn` traits may use parentheses + +error[E0107]: missing generics for struct `Vec` + --> $DIR/issue-34255-1.rs:7:22 + | +LL | input_cells: Vec::new() + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | input_cells: Vec::new() + | +++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0214, E0425. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/type/ascription/issue-47666.fixed b/tests/ui/type/ascription/issue-47666.fixed new file mode 100644 index 000000000..c4db74755 --- /dev/null +++ b/tests/ui/type/ascription/issue-47666.fixed @@ -0,0 +1,4 @@ +// run-rustfix +fn main() { + let _ = Option::Some(vec![0, 1]); //~ ERROR expected type, found +} diff --git a/tests/ui/type/ascription/issue-47666.rs b/tests/ui/type/ascription/issue-47666.rs new file mode 100644 index 000000000..c67202e21 --- /dev/null +++ b/tests/ui/type/ascription/issue-47666.rs @@ -0,0 +1,4 @@ +// run-rustfix +fn main() { + let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found +} diff --git a/tests/ui/type/ascription/issue-47666.stderr b/tests/ui/type/ascription/issue-47666.stderr new file mode 100644 index 000000000..0f90fce3a --- /dev/null +++ b/tests/ui/type/ascription/issue-47666.stderr @@ -0,0 +1,16 @@ +error: expected type, found `<[_]>::into_vec(#[rustc_box] ::alloc::boxed::Box::new([0, 1]))` + --> $DIR/issue-47666.rs:3:25 + | +LL | let _ = Option:Some(vec![0, 1]); + | - ^^^^^^^^^^ + | | | + | | expected type + | | in this macro invocation + | | this macro call doesn't expand to a type + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: this error originates in the macro `$crate::__rust_force_expr` which comes from the expansion of the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/type/ascription/issue-54516.fixed b/tests/ui/type/ascription/issue-54516.fixed new file mode 100644 index 000000000..f78268894 --- /dev/null +++ b/tests/ui/type/ascription/issue-54516.fixed @@ -0,0 +1,7 @@ +// run-rustfix +use std::collections::BTreeMap; + +fn main() { + println!("{}", std::mem::size_of::>()); + //~^ ERROR type ascription cannot be followed by a function call +} diff --git a/tests/ui/type/ascription/issue-54516.rs b/tests/ui/type/ascription/issue-54516.rs new file mode 100644 index 000000000..1f34e6943 --- /dev/null +++ b/tests/ui/type/ascription/issue-54516.rs @@ -0,0 +1,7 @@ +// run-rustfix +use std::collections::BTreeMap; + +fn main() { + println!("{}", std::mem:size_of::>()); + //~^ ERROR type ascription cannot be followed by a function call +} diff --git a/tests/ui/type/ascription/issue-54516.stderr b/tests/ui/type/ascription/issue-54516.stderr new file mode 100644 index 000000000..1ab9093e5 --- /dev/null +++ b/tests/ui/type/ascription/issue-54516.stderr @@ -0,0 +1,12 @@ +error: type ascription cannot be followed by a function call + --> $DIR/issue-54516.rs:5:20 + | +LL | println!("{}", std::mem:size_of::>()); + | ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + +error: aborting due to previous error + diff --git a/tests/ui/type/ascription/issue-60933.fixed b/tests/ui/type/ascription/issue-60933.fixed new file mode 100644 index 000000000..3e8be3875 --- /dev/null +++ b/tests/ui/type/ascription/issue-60933.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _: usize = std::mem::size_of::(); + //~^ ERROR type ascription cannot be followed by a function call +} diff --git a/tests/ui/type/ascription/issue-60933.rs b/tests/ui/type/ascription/issue-60933.rs new file mode 100644 index 000000000..2a4ad7bdc --- /dev/null +++ b/tests/ui/type/ascription/issue-60933.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let _: usize = std::mem:size_of::(); + //~^ ERROR type ascription cannot be followed by a function call +} diff --git a/tests/ui/type/ascription/issue-60933.stderr b/tests/ui/type/ascription/issue-60933.stderr new file mode 100644 index 000000000..0b7f8edf6 --- /dev/null +++ b/tests/ui/type/ascription/issue-60933.stderr @@ -0,0 +1,12 @@ +error: type ascription cannot be followed by a function call + --> $DIR/issue-60933.rs:3:20 + | +LL | let _: usize = std::mem:size_of::(); + | ^^^^^^^^-^^^^^^^^^^^^^^ + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + +error: aborting due to previous error + diff --git a/tests/ui/type/auxiliary/crate_a1.rs b/tests/ui/type/auxiliary/crate_a1.rs new file mode 100644 index 000000000..e2e185005 --- /dev/null +++ b/tests/ui/type/auxiliary/crate_a1.rs @@ -0,0 +1,11 @@ +pub struct Foo; + +pub trait Bar{} + +pub fn bar() -> Box { + unimplemented!() +} + + +pub fn try_foo(x: Foo){} +pub fn try_bar(x: Box){} diff --git a/tests/ui/type/auxiliary/crate_a2.rs b/tests/ui/type/auxiliary/crate_a2.rs new file mode 100644 index 000000000..d16a4ac10 --- /dev/null +++ b/tests/ui/type/auxiliary/crate_a2.rs @@ -0,0 +1,7 @@ +pub struct Foo; + +pub trait Bar{} + +pub fn bar() -> Box { + unimplemented!() +} diff --git a/tests/ui/type/binding-assigned-block-without-tail-expression.rs b/tests/ui/type/binding-assigned-block-without-tail-expression.rs new file mode 100644 index 000000000..09afd27a0 --- /dev/null +++ b/tests/ui/type/binding-assigned-block-without-tail-expression.rs @@ -0,0 +1,22 @@ +struct S; +fn main() { + let x = { + println!("foo"); + 42; + }; + let y = {}; + let z = { + "hi"; + }; + let s = { + S; + }; + println!("{}", x); //~ ERROR E0277 + println!("{}", y); //~ ERROR E0277 + println!("{}", z); //~ ERROR E0277 + println!("{}", s); //~ ERROR E0277 + let _: i32 = x; //~ ERROR E0308 + let _: i32 = y; //~ ERROR E0308 + let _: i32 = z; //~ ERROR E0308 + let _: i32 = s; //~ ERROR E0308 +} diff --git a/tests/ui/type/binding-assigned-block-without-tail-expression.stderr b/tests/ui/type/binding-assigned-block-without-tail-expression.stderr new file mode 100644 index 000000000..3e96d7f31 --- /dev/null +++ b/tests/ui/type/binding-assigned-block-without-tail-expression.stderr @@ -0,0 +1,109 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:14:20 + | +LL | 42; + | - help: remove this semicolon +... +LL | println!("{}", x); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:15:20 + | +LL | let y = {}; + | -- this empty block is missing a tail expression +... +LL | println!("{}", y); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:16:20 + | +LL | "hi"; + | - help: remove this semicolon +... +LL | println!("{}", z); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:17:20 + | +LL | let s = { + | _____________- +LL | | S; +LL | | }; + | |_____- this block is missing a tail expression +... +LL | println!("{}", s); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:18:18 + | +LL | 42; + | - help: remove this semicolon +... +LL | let _: i32 = x; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:19:18 + | +LL | let y = {}; + | -- this empty block is missing a tail expression +... +LL | let _: i32 = y; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:20:18 + | +LL | let z = { + | _____________- +LL | | "hi"; +LL | | }; + | |_____- this block is missing a tail expression +... +LL | let _: i32 = z; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:21:18 + | +LL | let s = { + | _____________- +LL | | S; +LL | | }; + | |_____- this block is missing a tail expression +... +LL | let _: i32 = s; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type/closure-with-wrong-borrows.rs b/tests/ui/type/closure-with-wrong-borrows.rs new file mode 100644 index 000000000..5f6a78351 --- /dev/null +++ b/tests/ui/type/closure-with-wrong-borrows.rs @@ -0,0 +1,10 @@ +struct S<'a>(&'a str); + +fn f(inner: fn(&str, &S)) { +} + +#[allow(unreachable_code)] +fn main() { + let inner: fn(_, _) = unimplemented!(); + f(inner); //~ ERROR mismatched types +} diff --git a/tests/ui/type/closure-with-wrong-borrows.stderr b/tests/ui/type/closure-with-wrong-borrows.stderr new file mode 100644 index 000000000..7370bc764 --- /dev/null +++ b/tests/ui/type/closure-with-wrong-borrows.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/closure-with-wrong-borrows.rs:9:7 + | +LL | f(inner); + | - ^^^^^ one type is more general than the other + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `for<'a, 'b, 'c> fn(&'a str, &'b S<'c>)` + found fn pointer `fn(_, _)` +note: function defined here + --> $DIR/closure-with-wrong-borrows.rs:3:4 + | +LL | fn f(inner: fn(&str, &S)) { + | ^ ------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/issue-100584.rs b/tests/ui/type/issue-100584.rs new file mode 100644 index 000000000..102846563 --- /dev/null +++ b/tests/ui/type/issue-100584.rs @@ -0,0 +1,15 @@ +#![deny(unused)] +fn foo(xyza: &str) { +//~^ ERROR unused variable: `xyza` + let _ = "{xyza}"; +} + +fn foo3(xyza: &str) { +//~^ ERROR unused variable: `xyza` + let _ = "aaa{xyza}bbb"; +} + +fn main() { + foo("x"); + foo3("xx"); +} diff --git a/tests/ui/type/issue-100584.stderr b/tests/ui/type/issue-100584.stderr new file mode 100644 index 000000000..e1db14d1f --- /dev/null +++ b/tests/ui/type/issue-100584.stderr @@ -0,0 +1,44 @@ +error: unused variable: `xyza` + --> $DIR/issue-100584.rs:2:8 + | +LL | fn foo(xyza: &str) { + | ^^^^ unused variable +LL | +LL | let _ = "{xyza}"; + | -------- you might have meant to use string interpolation in this string literal + | +note: the lint level is defined here + --> $DIR/issue-100584.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` +help: string interpolation only works in `format!` invocations + | +LL | let _ = format!("{xyza}"); + | ++++++++ + +help: if this is intentional, prefix it with an underscore + | +LL | fn foo(_xyza: &str) { + | ~~~~~ + +error: unused variable: `xyza` + --> $DIR/issue-100584.rs:7:9 + | +LL | fn foo3(xyza: &str) { + | ^^^^ unused variable +LL | +LL | let _ = "aaa{xyza}bbb"; + | -------------- you might have meant to use string interpolation in this string literal + | +help: string interpolation only works in `format!` invocations + | +LL | let _ = format!("aaa{xyza}bbb"); + | ++++++++ + +help: if this is intentional, prefix it with an underscore + | +LL | fn foo3(_xyza: &str) { + | ~~~~~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type/issue-101866.rs b/tests/ui/type/issue-101866.rs new file mode 100644 index 000000000..d332c4adb --- /dev/null +++ b/tests/ui/type/issue-101866.rs @@ -0,0 +1,15 @@ +trait TraitA { + fn func(); +} + +struct StructA {} + +impl TraitA for StructA { + fn func() {} +} + +fn main() { + TraitA::::func(); + //~^ ERROR: cannot call associated function on trait without specifying the corresponding `impl` type [E0790] + //~| help: use the fully-qualified path to the only available implementation +} diff --git a/tests/ui/type/issue-101866.stderr b/tests/ui/type/issue-101866.stderr new file mode 100644 index 000000000..fe9982119 --- /dev/null +++ b/tests/ui/type/issue-101866.stderr @@ -0,0 +1,18 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/issue-101866.rs:12:5 + | +LL | fn func(); + | ---------- `TraitA::func` defined here +... +LL | TraitA::::func(); + | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL - TraitA::::func(); +LL + >::func(); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/type/issue-102598.rs b/tests/ui/type/issue-102598.rs new file mode 100644 index 000000000..93808f18b --- /dev/null +++ b/tests/ui/type/issue-102598.rs @@ -0,0 +1,8 @@ +fn foo<'a>(_: impl 'a Sized) {} +//~^ ERROR: expected `+` between lifetime and Sized +//~| ERROR: expected one of `:`, `@`, or `|`, found `)` +//~| ERROR: expected one of `)`, `+`, or `,`, found `Sized` +//~| ERROR: at least one trait must be specified + +fn main(){ +} diff --git a/tests/ui/type/issue-102598.stderr b/tests/ui/type/issue-102598.stderr new file mode 100644 index 000000000..a232395ce --- /dev/null +++ b/tests/ui/type/issue-102598.stderr @@ -0,0 +1,43 @@ +error: expected `+` between lifetime and Sized + --> $DIR/issue-102598.rs:1:20 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^^ + | +help: add `+` + | +LL | fn foo<'a>(_: impl 'a + Sized) {} + | + + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/issue-102598.rs:1:28 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn foo<'a>(_: impl 'a Sized: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo<'a>(_: impl 'a _: Sized) {} + | ++ + +error: expected one of `)`, `+`, or `,`, found `Sized` + --> $DIR/issue-102598.rs:1:23 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | -^^^^^ expected one of `)`, `+`, or `,` + | | + | help: missing `,` + +error: at least one trait must be specified + --> $DIR/issue-102598.rs:1:15 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/type/issue-103271.rs b/tests/ui/type/issue-103271.rs new file mode 100644 index 000000000..7cd76286a --- /dev/null +++ b/tests/ui/type/issue-103271.rs @@ -0,0 +1,18 @@ +fn main() { + let iter_fun = <&[u32]>::iter; + //~^ ERROR no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599] + //~| function or associated item not found in `&[u32]` + //~| HELP the function `iter` is implemented on `[u32]` + for item in iter_fun(&[1,1]) { + let x: &u32 = item; + assert_eq!(x, &1); + } + let iter_fun2 = <(&[u32])>::iter; + //~^ no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599] + //~| function or associated item not found in `&[u32]` + //~| HELP the function `iter` is implemented on `[u32]` + for item2 in iter_fun2(&[1,1]) { + let x: &u32 = item2; + assert_eq!(x, &1); + } +} diff --git a/tests/ui/type/issue-103271.stderr b/tests/ui/type/issue-103271.stderr new file mode 100644 index 000000000..f4dac51b2 --- /dev/null +++ b/tests/ui/type/issue-103271.stderr @@ -0,0 +1,25 @@ +error[E0599]: no function or associated item named `iter` found for reference `&[u32]` in the current scope + --> $DIR/issue-103271.rs:2:30 + | +LL | let iter_fun = <&[u32]>::iter; + | ^^^^ function or associated item not found in `&[u32]` + | +help: the function `iter` is implemented on `[u32]` + | +LL | let iter_fun = <[u32]>::iter; + | ~~~~~ + +error[E0599]: no function or associated item named `iter` found for reference `&[u32]` in the current scope + --> $DIR/issue-103271.rs:10:33 + | +LL | let iter_fun2 = <(&[u32])>::iter; + | ^^^^ function or associated item not found in `&[u32]` + | +help: the function `iter` is implemented on `[u32]` + | +LL | let iter_fun2 = <([u32])>::iter; + | ~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/type/issue-58355.rs b/tests/ui/type/issue-58355.rs new file mode 100644 index 000000000..3b62fdece --- /dev/null +++ b/tests/ui/type/issue-58355.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] + +pub fn foo(callback: fn() -> dyn ToString) { + let mut x: Option dyn ToString>> = None; + x = Some(Box::new(callback)); + //~^ ERROR: the size for values of type `dyn ToString` cannot be known at compilation time +} diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr new file mode 100644 index 000000000..6f89a7b00 --- /dev/null +++ b/tests/ui/type/issue-58355.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time + --> $DIR/issue-58355.rs:5:14 + | +LL | x = Some(Box::new(callback)); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString` + = note: required because it appears within the type `fn() -> dyn ToString` + = note: required for the cast from `fn() -> dyn ToString` to the object type `dyn Fn() -> (dyn ToString + 'static)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs new file mode 100644 index 000000000..68aadcf60 --- /dev/null +++ b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs @@ -0,0 +1,8 @@ +// Regression test for issue #67690 +// Rustc endless loop out-of-memory and consequent SIGKILL in generic new type + +// check-pass +pub type T = P; +//~^ WARN bounds on generic parameters are not enforced in type aliases + +fn main() {} diff --git a/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr new file mode 100644 index 000000000..125ffbbb4 --- /dev/null +++ b/tests/ui/type/issue-67690-type-alias-bound-diagnostic-crash.stderr @@ -0,0 +1,15 @@ +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15 + | +LL | pub type T = P; + | ^^^^ ^^^^ ^^^^ + | + = note: `#[warn(type_alias_bounds)]` on by default +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - pub type T = P; +LL + pub type T

= P; + | + +warning: 1 warning emitted + diff --git a/tests/ui/type/issue-91268.rs b/tests/ui/type/issue-91268.rs new file mode 100644 index 000000000..f1e16bc7b --- /dev/null +++ b/tests/ui/type/issue-91268.rs @@ -0,0 +1,9 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: cannot find type `ţ` in this scope +// error-pattern: parenthesized type parameters may only be used with a `Fn` trait +// error-pattern: type arguments are not allowed on builtin type `u8` +// error-pattern: mismatched types +// ignore-tidy-trailing-newlines +// `ţ` must be the last character in this file, it cannot be followed by a newline +fn main() { + 0: u8(ţ \ No newline at end of file diff --git a/tests/ui/type/issue-91268.stderr b/tests/ui/type/issue-91268.stderr new file mode 100644 index 000000000..6c9ee9945 --- /dev/null +++ b/tests/ui/type/issue-91268.stderr @@ -0,0 +1,63 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-91268.rs:9:12 + | +LL | fn main() { + | - unclosed delimiter +LL | 0: u8(ţ + | - ^ + | | + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-91268.rs:9:12 + | +LL | fn main() { + | - unclosed delimiter +LL | 0: u8(ţ + | - ^ + | | + | unclosed delimiter + +error[E0412]: cannot find type `ţ` in this scope + --> $DIR/issue-91268.rs:9:11 + | +LL | 0: u8(ţ + | ^ expecting a type here because of type ascription + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-91268.rs:9:8 + | +LL | 0: u8(ţ + | ^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | 0: u8<ţ> + | ~ + + +error[E0109]: type arguments are not allowed on builtin type `u8` + --> $DIR/issue-91268.rs:9:11 + | +LL | 0: u8(ţ + | -- ^ type argument not allowed + | | + | not allowed on builtin type `u8` + | +help: primitive type `u8` doesn't have generic parameters + | +LL - 0: u8(ţ +LL + 0: u8 + | + +error[E0308]: mismatched types + --> $DIR/issue-91268.rs:9:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | 0: u8(ţ + | ^^^^^^^ expected `()`, found `u8` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0109, E0214, E0308, E0412. +For more information about an error, try `rustc --explain E0109`. diff --git a/tests/ui/type/issue-94187-verbose-type-name.rs b/tests/ui/type/issue-94187-verbose-type-name.rs new file mode 100644 index 000000000..3713a32eb --- /dev/null +++ b/tests/ui/type/issue-94187-verbose-type-name.rs @@ -0,0 +1,16 @@ +// Check to insure that the output of `std::any::type_name` does not change based on `-Zverbose` +// run-pass +// edition: 2018 +// revisions: normal verbose +// [verbose]compile-flags:-Zverbose + +use std::any::type_name; + +fn main() { + assert_eq!(type_name::<[u32; 0]>(), "[u32; 0]"); + + struct Wrapper; + assert_eq!(type_name::>(), "issue_94187_verbose_type_name::main::Wrapper<0>"); + + assert_eq!(type_name:: u32>(), "dyn core::ops::function::Fn(u32) -> u32"); +} diff --git a/tests/ui/type/missing-let-in-binding.fixed b/tests/ui/type/missing-let-in-binding.fixed new file mode 100644 index 000000000..d17876889 --- /dev/null +++ b/tests/ui/type/missing-let-in-binding.fixed @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let mut _foo: i32 = 1; + let _foo: i32 = 4; //~ ERROR type ascription is experimental +} diff --git a/tests/ui/type/missing-let-in-binding.rs b/tests/ui/type/missing-let-in-binding.rs new file mode 100644 index 000000000..ca42f2e6e --- /dev/null +++ b/tests/ui/type/missing-let-in-binding.rs @@ -0,0 +1,5 @@ +// run-rustfix +fn main() { + let mut _foo: i32 = 1; + _foo: i32 = 4; //~ ERROR type ascription is experimental +} diff --git a/tests/ui/type/missing-let-in-binding.stderr b/tests/ui/type/missing-let-in-binding.stderr new file mode 100644 index 000000000..12759c509 --- /dev/null +++ b/tests/ui/type/missing-let-in-binding.stderr @@ -0,0 +1,16 @@ +error[E0658]: type ascription is experimental + --> $DIR/missing-let-in-binding.rs:4:5 + | +LL | _foo: i32 = 4; + | ^^^^^^^^^ + | + = note: see issue #23416 for more information + = help: add `#![feature(type_ascription)]` to the crate attributes to enable +help: you might have meant to introduce a new binding + | +LL | let _foo: i32 = 4; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/type/type-alias-bounds.rs b/tests/ui/type/type-alias-bounds.rs new file mode 100644 index 000000000..e49731725 --- /dev/null +++ b/tests/ui/type/type-alias-bounds.rs @@ -0,0 +1,59 @@ +// Test `ignored_generic_bounds` lint warning about bounds in type aliases. + +// check-pass +#![allow(dead_code)] + +use std::rc::Rc; + +type SVec = Vec; +//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] +type S2Vec where T: Send = Vec; +//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds] +type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); +//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] +type WVec<'b, T: 'b + 'b> = (&'b u32, Vec); +//~^ WARN bounds on generic parameters are not enforced in type aliases [type_alias_bounds] +type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); +//~^ WARN where clauses are not enforced in type aliases [type_alias_bounds] + +static STATIC: u32 = 0; + +fn foo<'a>(y: &'a i32) { + // If any of the bounds above would matter, the code below would be rejected. + // This can be seen when replacing the type aliases above by newtype structs. + // (The type aliases have no unused parameters to make that a valid transformation.) + let mut x: SVec<_> = Vec::new(); + x.push(Rc::new(42)); // is not send + + let mut x: S2Vec<_> = Vec::new(); + x.push(Rc::new(42)); // is not `Send` + + let mut x: VVec<'static, 'a> = (&STATIC, Vec::new()); + x.1.push(y); // `'a: 'static` does not hold + + let mut x: WVec<'static, &'a i32> = (&STATIC, Vec::new()); + x.1.push(y); // `&'a i32: 'static` does not hold + + let mut x: W2Vec<'static, &'a i32> = (&STATIC, Vec::new()); + x.1.push(y); // `&'a i32: 'static` does not hold +} + +// Bounds are not checked either; i.e., the definition is not necessarily well-formed. +struct Sendable(T); +type MySendable = Sendable; // no error here! + +// However, bounds *are* taken into account when accessing associated types +trait Bound { type Assoc; } +type T1 = U::Assoc; //~ WARN not enforced in type aliases +type T2 where U: Bound = U::Assoc; //~ WARN not enforced in type aliases + +// This errors: +// `type T3 = U::Assoc;` +// Do this instead: +type T4 = ::Assoc; + +// Make sure the help about associated types is not shown incorrectly +type T5 = ::Assoc; //~ WARN not enforced in type aliases +type T6 = ::std::vec::Vec; //~ WARN not enforced in type aliases + +fn main() {} diff --git a/tests/ui/type/type-alias-bounds.stderr b/tests/ui/type/type-alias-bounds.stderr new file mode 100644 index 000000000..92e573393 --- /dev/null +++ b/tests/ui/type/type-alias-bounds.stderr @@ -0,0 +1,121 @@ +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:8:14 + | +LL | type SVec = Vec; + | ^^^^ ^^^^ + | + = note: `#[warn(type_alias_bounds)]` on by default +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type SVec = Vec; +LL + type SVec = Vec; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:10:21 + | +LL | type S2Vec where T: Send = Vec; + | ^^^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type S2Vec where T: Send = Vec; +LL + type S2Vec = Vec; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:12:19 + | +LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); + | ^^ ^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); +LL + type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>); + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:14:18 + | +LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec); + | ^^ ^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type WVec<'b, T: 'b + 'b> = (&'b u32, Vec); +LL + type WVec<'b, T> = (&'b u32, Vec); + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:16:25 + | +LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); + | ^^^^^ ^^^^^ + | +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); +LL + type W2Vec<'b, T> = (&'b u32, Vec); + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:47:12 + | +LL | type T1 = U::Assoc; + | ^^^^^ + | +help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases + --> $DIR/type-alias-bounds.rs:47:21 + | +LL | type T1 = U::Assoc; + | ^^^^^^^^ +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type T1 = U::Assoc; +LL + type T1 = U::Assoc; + | + +warning: where clauses are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:48:18 + | +LL | type T2 where U: Bound = U::Assoc; + | ^^^^^^^^ + | +help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases + --> $DIR/type-alias-bounds.rs:48:29 + | +LL | type T2 where U: Bound = U::Assoc; + | ^^^^^^^^ +help: the clause will not be checked when the type alias is used, and should be removed + | +LL - type T2 where U: Bound = U::Assoc; +LL + type T2 = U::Assoc; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:56:12 + | +LL | type T5 = ::Assoc; + | ^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type T5 = ::Assoc; +LL + type T5 = ::Assoc; + | + +warning: bounds on generic parameters are not enforced in type aliases + --> $DIR/type-alias-bounds.rs:57:12 + | +LL | type T6 = ::std::vec::Vec; + | ^^^^^ + | +help: the bound will not be checked when the type alias is used, and should be removed + | +LL - type T6 = ::std::vec::Vec; +LL + type T6 = ::std::vec::Vec; + | + +warning: 9 warnings emitted + diff --git a/tests/ui/type/type-annotation-needed.rs b/tests/ui/type/type-annotation-needed.rs new file mode 100644 index 000000000..347887f4b --- /dev/null +++ b/tests/ui/type/type-annotation-needed.rs @@ -0,0 +1,10 @@ +fn foo>(x: i32) {} +//~^ NOTE required by +//~| NOTE required by + +fn main() { + foo(42); + //~^ ERROR type annotations needed + //~| NOTE cannot infer type + //~| NOTE cannot satisfy +} diff --git a/tests/ui/type/type-annotation-needed.stderr b/tests/ui/type/type-annotation-needed.stderr new file mode 100644 index 000000000..87bba3166 --- /dev/null +++ b/tests/ui/type/type-annotation-needed.stderr @@ -0,0 +1,20 @@ +error[E0283]: type annotations needed + --> $DIR/type-annotation-needed.rs:6:5 + | +LL | foo(42); + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` + | + = note: cannot satisfy `_: Into` +note: required by a bound in `foo` + --> $DIR/type-annotation-needed.rs:1:11 + | +LL | fn foo>(x: i32) {} + | ^^^^^^^^^^^^ required by this bound in `foo` +help: consider specifying the generic argument + | +LL | foo::(42); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type/type-arg-out-of-scope.rs b/tests/ui/type/type-arg-out-of-scope.rs new file mode 100644 index 000000000..02aad0077 --- /dev/null +++ b/tests/ui/type/type-arg-out-of-scope.rs @@ -0,0 +1,5 @@ +// error-pattern:can't use generic parameters from outer function +fn foo(x: T) { + fn bar(f: Box T>) { } +} +fn main() { foo(1); } diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr new file mode 100644 index 000000000..7f18b4510 --- /dev/null +++ b/tests/ui/type/type-arg-out-of-scope.stderr @@ -0,0 +1,23 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/type-arg-out-of-scope.rs:3:29 + | +LL | fn foo(x: T) { + | - type parameter from outer function +LL | fn bar(f: Box T>) { } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error[E0401]: can't use generic parameters from outer function + --> $DIR/type-arg-out-of-scope.rs:3:35 + | +LL | fn foo(x: T) { + | - type parameter from outer function +LL | fn bar(f: Box T>) { } + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/type/type-ascription-instead-of-initializer.rs b/tests/ui/type/type-ascription-instead-of-initializer.rs new file mode 100644 index 000000000..8978c85ed --- /dev/null +++ b/tests/ui/type/type-ascription-instead-of-initializer.rs @@ -0,0 +1,4 @@ +fn main() { + let x: Vec::with_capacity(10, 20); //~ ERROR expected type, found `10` + //~^ ERROR function takes 1 argument +} diff --git a/tests/ui/type/type-ascription-instead-of-initializer.stderr b/tests/ui/type/type-ascription-instead-of-initializer.stderr new file mode 100644 index 000000000..ba8d15d0b --- /dev/null +++ b/tests/ui/type/type-ascription-instead-of-initializer.stderr @@ -0,0 +1,25 @@ +error: expected type, found `10` + --> $DIR/type-ascription-instead-of-initializer.rs:2:31 + | +LL | let x: Vec::with_capacity(10, 20); + | -- ^^ expected type + | || + | |help: use `=` if you meant to assign + | while parsing the type for `x` + +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/type-ascription-instead-of-initializer.rs:2:12 + | +LL | let x: Vec::with_capacity(10, 20); + | ^^^^^^^^^^^^^^^^^^ -- argument of type `{integer}` unexpected + | +note: associated function defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +help: remove the extra argument + | +LL | let x: Vec::with_capacity(10); + | ~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/type/type-ascription-instead-of-statement-end.rs b/tests/ui/type/type-ascription-instead-of-statement-end.rs new file mode 100644 index 000000000..1d5565ab5 --- /dev/null +++ b/tests/ui/type/type-ascription-instead-of-statement-end.rs @@ -0,0 +1,10 @@ +#![feature(type_ascription)] + +fn main() { + println!("test"): + 0; //~ ERROR expected type, found `0` +} + +fn foo() { + println!("test"): 0; //~ ERROR expected type, found `0` +} diff --git a/tests/ui/type/type-ascription-instead-of-statement-end.stderr b/tests/ui/type/type-ascription-instead-of-statement-end.stderr new file mode 100644 index 000000000..521ebcdf1 --- /dev/null +++ b/tests/ui/type/type-ascription-instead-of-statement-end.stderr @@ -0,0 +1,24 @@ +error: expected type, found `0` + --> $DIR/type-ascription-instead-of-statement-end.rs:5:5 + | +LL | println!("test"): + | - help: try using a semicolon: `;` +LL | 0; + | ^ expected type + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: see issue #23416 for more information + +error: expected type, found `0` + --> $DIR/type-ascription-instead-of-statement-end.rs:9:23 + | +LL | println!("test"): 0; + | - ^ expected type + | | + | tried to parse a type due to this type ascription + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: see issue #23416 for more information + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type/type-ascription-precedence.rs b/tests/ui/type/type-ascription-precedence.rs new file mode 100644 index 000000000..d3aef929b --- /dev/null +++ b/tests/ui/type/type-ascription-precedence.rs @@ -0,0 +1,54 @@ +// Operator precedence of type ascription +// Type ascription has very high precedence, the same as operator `as` + +#![feature(type_ascription)] + +use std::ops::*; + +struct S; +struct Z; + +impl Add for S { + type Output = S; + fn add(self, _rhs: Z) -> S { panic!() } +} +impl Mul for S { + type Output = S; + fn mul(self, _rhs: Z) -> S { panic!() } +} +impl Neg for S { + type Output = Z; + fn neg(self) -> Z { panic!() } +} +impl Deref for S { + type Target = Z; + fn deref(&self) -> &Z { panic!() } +} + +fn main() { + &S: &S; // OK + (&S): &S; // OK + &(S: &S); //~ ERROR mismatched types + + *S: Z; // OK + (*S): Z; // OK + *(S: Z); //~ ERROR mismatched types + //~^ ERROR type `Z` cannot be dereferenced + + -S: Z; // OK + (-S): Z; // OK + -(S: Z); //~ ERROR mismatched types + //~^ ERROR cannot apply unary operator `-` to type `Z` + + S + Z: Z; // OK + S + (Z: Z); // OK + (S + Z): Z; //~ ERROR mismatched types + + S * Z: Z; // OK + S * (Z: Z); // OK + (S * Z): Z; //~ ERROR mismatched types + + S .. S: S; // OK + S .. (S: S); // OK + (S .. S): S; //~ ERROR mismatched types +} diff --git a/tests/ui/type/type-ascription-precedence.stderr b/tests/ui/type/type-ascription-precedence.stderr new file mode 100644 index 000000000..edc5aeffd --- /dev/null +++ b/tests/ui/type/type-ascription-precedence.stderr @@ -0,0 +1,63 @@ +error[E0308]: mismatched types + --> $DIR/type-ascription-precedence.rs:31:7 + | +LL | &(S: &S); + | ^ expected `&S`, found struct `S` + +error[E0308]: mismatched types + --> $DIR/type-ascription-precedence.rs:35:7 + | +LL | *(S: Z); + | ^ expected struct `Z`, found struct `S` + +error[E0614]: type `Z` cannot be dereferenced + --> $DIR/type-ascription-precedence.rs:35:5 + | +LL | *(S: Z); + | ^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-ascription-precedence.rs:40:7 + | +LL | -(S: Z); + | ^ expected struct `Z`, found struct `S` + +error[E0600]: cannot apply unary operator `-` to type `Z` + --> $DIR/type-ascription-precedence.rs:40:5 + | +LL | -(S: Z); + | ^^^^^^^ cannot apply unary operator `-` + | +note: an implementation of `std::ops::Neg` might be missing for `Z` + --> $DIR/type-ascription-precedence.rs:9:1 + | +LL | struct Z; + | ^^^^^^^^ must implement `std::ops::Neg` +note: the trait `std::ops::Neg` must be implemented + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL + +error[E0308]: mismatched types + --> $DIR/type-ascription-precedence.rs:45:5 + | +LL | (S + Z): Z; + | ^^^^^^^ expected struct `Z`, found struct `S` + +error[E0308]: mismatched types + --> $DIR/type-ascription-precedence.rs:49:5 + | +LL | (S * Z): Z; + | ^^^^^^^ expected struct `Z`, found struct `S` + +error[E0308]: mismatched types + --> $DIR/type-ascription-precedence.rs:53:5 + | +LL | (S .. S): S; + | ^^^^^^^^ expected struct `S`, found struct `Range` + | + = note: expected struct `S` + found struct `std::ops::Range` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0600, E0614. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-ascription-soundness.rs b/tests/ui/type/type-ascription-soundness.rs new file mode 100644 index 000000000..08316cdcd --- /dev/null +++ b/tests/ui/type/type-ascription-soundness.rs @@ -0,0 +1,13 @@ +// Type ascription doesn't lead to unsoundness + +#![feature(type_ascription)] + +fn main() { + let arr = &[1u8, 2, 3]; + let ref x = type_ascribe!(arr, &[u8]); //~ ERROR mismatched types + let ref mut x = type_ascribe!(arr, &[u8]); //~ ERROR mismatched types + match type_ascribe!(arr, &[u8]) { //~ ERROR mismatched types + ref x => {} + } + let _len = type_ascribe!(arr, &[u8]).len(); //~ ERROR mismatched types +} diff --git a/tests/ui/type/type-ascription-soundness.stderr b/tests/ui/type/type-ascription-soundness.stderr new file mode 100644 index 000000000..522d5b2e3 --- /dev/null +++ b/tests/ui/type/type-ascription-soundness.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> $DIR/type-ascription-soundness.rs:7:31 + | +LL | let ref x = type_ascribe!(arr, &[u8]); + | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | + = note: expected reference `&[u8]` + found reference `&[u8; 3]` + +error[E0308]: mismatched types + --> $DIR/type-ascription-soundness.rs:8:35 + | +LL | let ref mut x = type_ascribe!(arr, &[u8]); + | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | + = note: expected reference `&[u8]` + found reference `&[u8; 3]` + +error[E0308]: mismatched types + --> $DIR/type-ascription-soundness.rs:9:25 + | +LL | match type_ascribe!(arr, &[u8]) { + | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | + = note: expected reference `&[u8]` + found reference `&[u8; 3]` + +error[E0308]: mismatched types + --> $DIR/type-ascription-soundness.rs:12:30 + | +LL | let _len = type_ascribe!(arr, &[u8]).len(); + | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | + = note: expected reference `&[u8]` + found reference `&[u8; 3]` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-ascription-with-fn-call.fixed b/tests/ui/type/type-ascription-with-fn-call.fixed new file mode 100644 index 000000000..6d96c4303 --- /dev/null +++ b/tests/ui/type/type-ascription-with-fn-call.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![feature(type_ascription)] + +fn main() { + f() ; + f(); //~ ERROR expected type, found function +} + +fn f() {} diff --git a/tests/ui/type/type-ascription-with-fn-call.rs b/tests/ui/type/type-ascription-with-fn-call.rs new file mode 100644 index 000000000..ed4f7c904 --- /dev/null +++ b/tests/ui/type/type-ascription-with-fn-call.rs @@ -0,0 +1,9 @@ +// run-rustfix +#![feature(type_ascription)] + +fn main() { + f() : + f(); //~ ERROR expected type, found function +} + +fn f() {} diff --git a/tests/ui/type/type-ascription-with-fn-call.stderr b/tests/ui/type/type-ascription-with-fn-call.stderr new file mode 100644 index 000000000..d78fd08fd --- /dev/null +++ b/tests/ui/type/type-ascription-with-fn-call.stderr @@ -0,0 +1,11 @@ +error[E0573]: expected type, found function `f` + --> $DIR/type-ascription-with-fn-call.rs:6:5 + | +LL | f() : + | - help: maybe you meant to write `;` here +LL | f(); + | ^^^ expecting a type here because of type ascription + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/type/type-ascription.rs b/tests/ui/type/type-ascription.rs new file mode 100644 index 000000000..e4a4c89d0 --- /dev/null +++ b/tests/ui/type/type-ascription.rs @@ -0,0 +1,39 @@ +// run-pass + +#![allow(dead_code)] +#![allow(unused_variables)] +// Type ascription doesn't lead to unsoundness + +#![feature(type_ascription)] + +use std::mem; + +const C1: u8 = type_ascribe!(10, u8); +const C2: [u8; type_ascribe!(1, usize)] = [1]; + +struct S { + a: u8 +} + +fn main() { + assert_eq!(type_ascribe!(C1.into(), i32), 10); + assert_eq!(C2[0], 1); + + let s = S { a: type_ascribe!(10, u8) }; + let arr = &[1u8, 2, 3]; + + let mut v = type_ascribe!(arr.iter().cloned().collect(), Vec<_>); + v.push(4); + assert_eq!(v, [1, 2, 3, 4]); + + let a = type_ascribe!(1, u8); + let b = type_ascribe!(a.into(), u16); + assert_eq!(v[type_ascribe!(a.into(), usize)], 2); + assert_eq!(mem::size_of_val(&a), 1); + assert_eq!(mem::size_of_val(&b), 2); + assert_eq!(b, type_ascribe!(1, u16)); + + let mut v = Vec::new(); + type_ascribe!(v, Vec) = vec![1, 2, 3]; // Place expression type ascription + assert_eq!(v, [1u8, 2, 3]); +} diff --git a/tests/ui/type/type-check-defaults.rs b/tests/ui/type/type-check-defaults.rs new file mode 100644 index 000000000..6a0a7ed33 --- /dev/null +++ b/tests/ui/type/type-check-defaults.rs @@ -0,0 +1,27 @@ +use std::iter::FromIterator; +use std::vec::IntoIter; +use std::ops::Add; + +struct Foo>(T, U); +struct WellFormed>(Z); +//~^ ERROR a value of type `i32` cannot be built from an iterator over elements of type `i32` +struct WellFormedNoBounds>(Z); +//~^ ERROR a value of type `i32` cannot be built from an iterator over elements of type `i32` + +struct Bounds(T); +//~^ ERROR the trait bound `String: Copy` is not satisfied [E0277] + +struct WhereClause(T) where T: Copy; +//~^ ERROR the trait bound `String: Copy` is not satisfied [E0277] + +trait TraitBound {} +//~^ ERROR the trait bound `String: Copy` is not satisfied [E0277] + +trait Super { } +trait Base: Super { } +//~^ ERROR the trait bound `T: Copy` is not satisfied [E0277] + +trait ProjectionPred> where T::Item : Add {} +//~^ ERROR cannot add `u8` to `i32` [E0277] + +fn main() { } diff --git a/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr new file mode 100644 index 000000000..9ba63ffe9 --- /dev/null +++ b/tests/ui/type/type-check-defaults.stderr @@ -0,0 +1,76 @@ +error[E0277]: a value of type `i32` cannot be built from an iterator over elements of type `i32` + --> $DIR/type-check-defaults.rs:6:23 + | +LL | struct WellFormed>(Z); + | ^^^^^^^^^^^^^ value of type `i32` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator` is not implemented for `i32` +note: required by a bound in `Foo` + --> $DIR/type-check-defaults.rs:5:18 + | +LL | struct Foo>(T, U); + | ^^^^^^^^^^^^^^^ required by this bound in `Foo` + +error[E0277]: a value of type `i32` cannot be built from an iterator over elements of type `i32` + --> $DIR/type-check-defaults.rs:8:38 + | +LL | struct WellFormedNoBounds>(Z); + | ^^^^^^^^^^^^^ value of type `i32` cannot be built from `std::iter::Iterator` + | + = help: the trait `FromIterator` is not implemented for `i32` +note: required by a bound in `Foo` + --> $DIR/type-check-defaults.rs:5:18 + | +LL | struct Foo>(T, U); + | ^^^^^^^^^^^^^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/type-check-defaults.rs:11:17 + | +LL | struct Bounds(T); + | ^^^^ the trait `Copy` is not implemented for `String` + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/type-check-defaults.rs:14:42 + | +LL | struct WhereClause(T) where T: Copy; + | ^^^^ the trait `Copy` is not implemented for `String` + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/type-check-defaults.rs:17:20 + | +LL | trait TraitBound {} + | ^^^^ the trait `Copy` is not implemented for `String` + +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/type-check-defaults.rs:21:25 + | +LL | trait Base: Super { } + | ^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `Super` + --> $DIR/type-check-defaults.rs:20:16 + | +LL | trait Super { } + | ^^^^ required by this bound in `Super` +help: consider further restricting type parameter `T` + | +LL | trait Base: Super where T: std::marker::Copy { } + | ++++++++++++++++++++++++++ + +error[E0277]: cannot add `u8` to `i32` + --> $DIR/type-check-defaults.rs:24:66 + | +LL | trait ProjectionPred> where T::Item : Add {} + | ^^^^^^^ no implementation for `i32 + u8` + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + <&'a i32 as Add> + <&i32 as Add<&i32>> + > + + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type/type-check/assignment-expected-bool.rs b/tests/ui/type/type-check/assignment-expected-bool.rs new file mode 100644 index 000000000..191939bdb --- /dev/null +++ b/tests/ui/type/type-check/assignment-expected-bool.rs @@ -0,0 +1,34 @@ +// The purpose of this text is to ensure that we get good +// diagnostics when a `bool` is expected but that due to +// an assignment expression `x = y` the type is `()`. + +fn main() { + let _: bool = 0 = 0; //~ ERROR mismatched types [E0308] + + let _: bool = match 0 { + 0 => 0 = 0, //~ ERROR mismatched types [E0308] + _ => 0 = 0, //~ ERROR mismatched types [E0308] + }; + + let _: bool = match true { + true => 0 = 0, //~ ERROR mismatched types [E0308] + _ => (), + }; + + if 0 = 0 {} //~ ERROR mismatched types [E0308] + + let _: bool = if { 0 = 0 } { //~ ERROR mismatched types [E0308] + 0 = 0 //~ ERROR mismatched types [E0308] + } else { + 0 = 0 //~ ERROR mismatched types [E0308] + }; + + let _ = (0 = 0) //~ ERROR mismatched types [E0308] + && { 0 = 0 } //~ ERROR mismatched types [E0308] + || (0 = 0); //~ ERROR mismatched types [E0308] + + // A test to check that not expecting `bool` behaves well: + let _: usize = 0 = 0; + //~^ ERROR mismatched types [E0308] + //~| ERROR invalid left-hand side of assignment [E0070] +} diff --git a/tests/ui/type/type-check/assignment-expected-bool.stderr b/tests/ui/type/type-check/assignment-expected-bool.stderr new file mode 100644 index 000000000..56494baff --- /dev/null +++ b/tests/ui/type/type-check/assignment-expected-bool.stderr @@ -0,0 +1,141 @@ +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:6:19 + | +LL | let _: bool = 0 = 0; + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | let _: bool = 0 == 0; + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:9:14 + | +LL | 0 => 0 = 0, + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | 0 => 0 == 0, + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:10:14 + | +LL | _ => 0 = 0, + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | _ => 0 == 0, + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:14:17 + | +LL | true => 0 = 0, + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | true => 0 == 0, + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:18:8 + | +LL | if 0 = 0 {} + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if 0 == 0 {} + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:20:24 + | +LL | let _: bool = if { 0 = 0 } { + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | let _: bool = if { 0 == 0 } { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:21:9 + | +LL | 0 = 0 + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | 0 == 0 + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:23:9 + | +LL | 0 = 0 + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | 0 == 0 + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:26:13 + | +LL | let _ = (0 = 0) + | ^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | let _ = (0 == 0) + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:27:14 + | +LL | && { 0 = 0 } + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | && { 0 == 0 } + | + + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:28:12 + | +LL | || (0 = 0); + | ^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | || (0 == 0); + | + + +error[E0070]: invalid left-hand side of assignment + --> $DIR/assignment-expected-bool.rs:31:22 + | +LL | let _: usize = 0 = 0; + | - ^ + | | + | cannot assign to this expression + +error[E0308]: mismatched types + --> $DIR/assignment-expected-bool.rs:31:20 + | +LL | let _: usize = 0 = 0; + | ----- ^^^^^ expected `usize`, found `()` + | | + | expected due to this + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0070, E0308. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/type/type-check/assignment-in-if.rs b/tests/ui/type/type-check/assignment-in-if.rs new file mode 100644 index 000000000..ada250df2 --- /dev/null +++ b/tests/ui/type/type-check/assignment-in-if.rs @@ -0,0 +1,62 @@ +// Test that the parser does not attempt to parse struct literals +// within assignments in if expressions. + +#![allow(unused_parens)] + +struct Foo { + foo: usize +} + +fn main() { + let x = 1; + let y: Foo; + + // `x { ... }` should not be interpreted as a struct literal here + if x = x { + //~^ ERROR mismatched types + println!("{}", x); + } + // Explicit parentheses on the left should match behavior of above + if (x = x) { + //~^ ERROR mismatched types + println!("{}", x); + } + // The struct literal interpretation is fine with explicit parentheses on the right + if y = (Foo { foo: x }) { + //~^ ERROR mismatched types + println!("{}", x); + } + // "invalid left-hand side of assignment" error is suppresed + if 3 = x { + //~^ ERROR mismatched types + println!("{}", x); + } + if ( + if true { + x = 4 //~ ERROR mismatched types + } else { + x = 5 //~ ERROR mismatched types + } + ) { + println!("{}", x); + } + + if x == x && x = x && x == x { + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + println!("{}", x); + } + + if x == x && x == x && x = x { + //~^ ERROR mismatched types + //~| ERROR mismatched types + println!("{}", x); + } + + if x = 1 && x == 1 { + //~^ ERROR mismatched types + //~| ERROR mismatched types + println!("{}", x); + } +} diff --git a/tests/ui/type/type-check/assignment-in-if.stderr b/tests/ui/type/type-check/assignment-in-if.stderr new file mode 100644 index 000000000..9f4558ada --- /dev/null +++ b/tests/ui/type/type-check/assignment-in-if.stderr @@ -0,0 +1,130 @@ +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:15:8 + | +LL | if x = x { + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if x == x { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:20:8 + | +LL | if (x = x) { + | ^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if (x == x) { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:25:8 + | +LL | if y = (Foo { foo: x }) { + | ^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if y == (Foo { foo: x }) { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:30:8 + | +LL | if 3 = x { + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if 3 == x { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:36:13 + | +LL | x = 4 + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | x == 4 + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:38:13 + | +LL | x = 5 + | ^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | x == 5 + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:44:18 + | +LL | if x == x && x = x && x == x { + | ------ ^ expected `bool`, found `usize` + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:44:22 + | +LL | if x == x && x = x && x == x { + | ^ expected `bool`, found `usize` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:44:8 + | +LL | if x == x && x = x && x == x { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if x == x && x == x && x == x { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:51:28 + | +LL | if x == x && x == x && x = x { + | ---------------- ^ expected `bool`, found `usize` + | | + | expected because this is `bool` + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:51:8 + | +LL | if x == x && x == x && x = x { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if x == x && x == x && x == x { + | + + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:57:12 + | +LL | if x = 1 && x == 1 { + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/assignment-in-if.rs:57:8 + | +LL | if x = 1 && x == 1 { + | ^^^^^^^^^^^^^^^ expected `bool`, found `()` + | +help: you might have meant to compare for equality + | +LL | if x == 1 && x == 1 { + | + + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/cannot_infer_local_or_array.rs b/tests/ui/type/type-check/cannot_infer_local_or_array.rs new file mode 100644 index 000000000..af7552523 --- /dev/null +++ b/tests/ui/type/type-check/cannot_infer_local_or_array.rs @@ -0,0 +1,3 @@ +fn main() { + let x = []; //~ ERROR type annotations needed +} diff --git a/tests/ui/type/type-check/cannot_infer_local_or_array.stderr b/tests/ui/type/type-check/cannot_infer_local_or_array.stderr new file mode 100644 index 000000000..e823bad26 --- /dev/null +++ b/tests/ui/type/type-check/cannot_infer_local_or_array.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/cannot_infer_local_or_array.rs:2:9 + | +LL | let x = []; + | ^ -- type must be known at this point + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: [_; 0] = []; + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec.rs b/tests/ui/type/type-check/cannot_infer_local_or_vec.rs new file mode 100644 index 000000000..e72ddabf3 --- /dev/null +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec.rs @@ -0,0 +1,4 @@ +fn main() { + let x = vec![]; + //~^ ERROR type annotations needed +} diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr new file mode 100644 index 000000000..b63d2a3b6 --- /dev/null +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Vec` + --> $DIR/cannot_infer_local_or_vec.rs:2:9 + | +LL | let x = vec![]; + | ^ + | +help: consider giving `x` an explicit type, where the type for type parameter `T` is specified + | +LL | let x: Vec = vec![]; + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs new file mode 100644 index 000000000..d21456439 --- /dev/null +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.rs @@ -0,0 +1,4 @@ +fn main() { + let (x, ) = (vec![], ); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr new file mode 100644 index 000000000..e544b3695 --- /dev/null +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `(Vec,)` + --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9 + | +LL | let (x, ) = (vec![], ); + | ^^^^^ ---------- type must be known at this point + | +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let (x, ): (Vec,) = (vec![], ); + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/issue-22897.rs b/tests/ui/type/type-check/issue-22897.rs new file mode 100644 index 000000000..8171a0ef1 --- /dev/null +++ b/tests/ui/type/type-check/issue-22897.rs @@ -0,0 +1,5 @@ +fn main() { } + +fn unconstrained_type() { + []; //~ ERROR type annotations needed +} diff --git a/tests/ui/type/type-check/issue-22897.stderr b/tests/ui/type/type-check/issue-22897.stderr new file mode 100644 index 000000000..fae7b7926 --- /dev/null +++ b/tests/ui/type/type-check/issue-22897.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/issue-22897.rs:4:5 + | +LL | []; + | ^^ cannot infer type for array `[_; 0]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-check/issue-40294.rs b/tests/ui/type/type-check/issue-40294.rs new file mode 100644 index 000000000..5493a4e5f --- /dev/null +++ b/tests/ui/type/type-check/issue-40294.rs @@ -0,0 +1,13 @@ +trait Foo: Sized { + fn foo(self); +} + +fn foo<'a,'b,T>(x: &'a T, y: &'b T) + where &'a T : Foo, //~ ERROR type annotations needed + &'b T : Foo +{ + x.foo(); + y.foo(); +} + +fn main() { } diff --git a/tests/ui/type/type-check/issue-40294.stderr b/tests/ui/type/type-check/issue-40294.stderr new file mode 100644 index 000000000..d15fd2341 --- /dev/null +++ b/tests/ui/type/type-check/issue-40294.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `&'a T: Foo` + --> $DIR/issue-40294.rs:6:19 + | +LL | where &'a T : Foo, + | ^^^ + | +note: multiple `impl`s or `where` clauses satisfying `&'a T: Foo` found + --> $DIR/issue-40294.rs:6:19 + | +LL | where &'a T : Foo, + | ^^^ +LL | &'b T : Foo + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type/type-check/issue-41314.rs b/tests/ui/type/type-check/issue-41314.rs new file mode 100644 index 000000000..cbd39f5f9 --- /dev/null +++ b/tests/ui/type/type-check/issue-41314.rs @@ -0,0 +1,10 @@ +enum X { + Y(u32) +} + +fn main() { + match X::Y(0) { + X::Y { number } => {} + //~^ ERROR tuple variant `X::Y` written as struct variant + } +} diff --git a/tests/ui/type/type-check/issue-41314.stderr b/tests/ui/type/type-check/issue-41314.stderr new file mode 100644 index 000000000..4a9bf6106 --- /dev/null +++ b/tests/ui/type/type-check/issue-41314.stderr @@ -0,0 +1,14 @@ +error[E0769]: tuple variant `X::Y` written as struct variant + --> $DIR/issue-41314.rs:7:9 + | +LL | X::Y { number } => {} + | ^^^^^^^^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | X::Y(number) => {} + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0769`. diff --git a/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs new file mode 100644 index 000000000..c39ab9544 --- /dev/null +++ b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs @@ -0,0 +1,27 @@ +fn main() { + let mut i: i64; + // Expected type is an inference variable `?T` + // because the `match` is used as a statement. + // This is the "initial" type of the `coercion`. + match i { + // Add `bool` to the overall `coercion`. + 0 => true, + + // Necessary to cause the ICE: + 1 => true, + + // Suppose that we had `let _: bool = match i { ... }`. + // In that case, as the expected type would be `bool`, + // we would suggest `i == 1` as a fix. + // + // However, no type error happens when checking `i = 1` because `expected == ?T`, + // which will unify with `typeof(i = 1) == ()`. + // + // However, in #67273, we would delay the unification of this arm with the above + // because we used the hitherto accumulated coercion as opposed to the "initial" type. + 2 => i = 1, + //~^ ERROR `match` arms have incompatible types + + _ => (), + } +} diff --git a/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr new file mode 100644 index 000000000..a431fe89c --- /dev/null +++ b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr @@ -0,0 +1,22 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs:22:14 + | +LL | / match i { +LL | | // Add `bool` to the overall `coercion`. +LL | | 0 => true, + | | ---- this is found to be of type `bool` +LL | | +LL | | // Necessary to cause the ICE: +LL | | 1 => true, + | | ---- this is found to be of type `bool` +... | +LL | | 2 => i = 1, + | | ^^^^^ expected `bool`, found `()` +... | +LL | | _ => (), +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs new file mode 100644 index 000000000..e50cc5865 --- /dev/null +++ b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs @@ -0,0 +1,12 @@ +macro_rules! many_args { + ([$($t:tt)*]#$($h:tt)*) => { + many_args!{[$($t)*$($t)*]$($h)*} + }; + ([$($t:tt)*]) => { + fn _f($($t: ()),*) {} //~ ERROR function can not have more than 65535 arguments + } +} + +many_args!{[_]########## ######} + +fn main() {} diff --git a/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr new file mode 100644 index 000000000..847bc517e --- /dev/null +++ b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr @@ -0,0 +1,13 @@ +error: function can not have more than 65535 arguments + --> $DIR/issue-88577-check-fn-with-more-than-65535-arguments.rs:6:22 + | +LL | fn _f($($t: ()),*) {} + | ^ +... +LL | many_args!{[_]########## ######} + | -------------------------------- in this macro invocation + | + = note: this error originates in the macro `many_args` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/type/type-check/missing_trait_impl.rs b/tests/ui/type/type-check/missing_trait_impl.rs new file mode 100644 index 000000000..0e3e703a2 --- /dev/null +++ b/tests/ui/type/type-check/missing_trait_impl.rs @@ -0,0 +1,16 @@ +fn main() { +} + +fn foo(x: T, y: T) { + let z = x + y; //~ ERROR cannot add `T` to `T` +} + +fn bar(x: T) { + x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T` +} + +fn baz(x: T) { + let y = -x; //~ ERROR cannot apply unary operator `-` to type `T` + let y = !x; //~ ERROR cannot apply unary operator `!` to type `T` + let y = *x; //~ ERROR type `T` cannot be dereferenced +} diff --git a/tests/ui/type/type-check/missing_trait_impl.stderr b/tests/ui/type/type-check/missing_trait_impl.stderr new file mode 100644 index 000000000..2b58cd418 --- /dev/null +++ b/tests/ui/type/type-check/missing_trait_impl.stderr @@ -0,0 +1,58 @@ +error[E0369]: cannot add `T` to `T` + --> $DIR/missing_trait_impl.rs:5:15 + | +LL | let z = x + y; + | - ^ - T + | | + | T + | +help: consider restricting type parameter `T` + | +LL | fn foo(x: T, y: T) { + | +++++++++++++++ + +error[E0368]: binary assignment operation `+=` cannot be applied to type `T` + --> $DIR/missing_trait_impl.rs:9:5 + | +LL | x += x; + | -^^^^^ + | | + | cannot use `+=` on type `T` + | +help: consider restricting type parameter `T` + | +LL | fn bar(x: T) { + | +++++++++++++++++++++ + +error[E0600]: cannot apply unary operator `-` to type `T` + --> $DIR/missing_trait_impl.rs:13:13 + | +LL | let y = -x; + | ^^ cannot apply unary operator `-` + | +help: consider restricting type parameter `T` + | +LL | fn baz(x: T) { + | +++++++++++++++ + +error[E0600]: cannot apply unary operator `!` to type `T` + --> $DIR/missing_trait_impl.rs:14:13 + | +LL | let y = !x; + | ^^ cannot apply unary operator `!` + | +help: consider restricting type parameter `T` + | +LL | fn baz(x: T) { + | +++++++++++++++ + +error[E0614]: type `T` cannot be dereferenced + --> $DIR/missing_trait_impl.rs:15:13 + | +LL | let y = *x; + | ^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0368, E0369, E0600, E0614. +For more information about an error, try `rustc --explain E0368`. diff --git a/tests/ui/type/type-check/point-at-inference-2.rs b/tests/ui/type/type-check/point-at-inference-2.rs new file mode 100644 index 000000000..6557d7fa1 --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-2.rs @@ -0,0 +1,13 @@ +fn bar(_: Vec) {} +fn baz(_: &Vec<&i32>) {} +fn main() { + let v = vec![&1]; + bar(v); //~ ERROR E0308 + let v = vec![]; + baz(&v); + baz(&v); + bar(v); //~ ERROR E0308 + let v = vec![]; + baz(&v); + bar(v); //~ ERROR E0308 +} diff --git a/tests/ui/type/type-check/point-at-inference-2.stderr b/tests/ui/type/type-check/point-at-inference-2.stderr new file mode 100644 index 000000000..1368aba0d --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-2.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference-2.rs:5:9 + | +LL | bar(v); + | --- ^ expected `i32`, found `&{integer}` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&{integer}>` +note: function defined here + --> $DIR/point-at-inference-2.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error[E0308]: mismatched types + --> $DIR/point-at-inference-2.rs:9:9 + | +LL | bar(v); + | --- ^ expected `i32`, found `&i32` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&i32>` +note: function defined here + --> $DIR/point-at-inference-2.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error[E0308]: mismatched types + --> $DIR/point-at-inference-2.rs:12:9 + | +LL | bar(v); + | --- ^ expected `i32`, found `&i32` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&i32>` +note: function defined here + --> $DIR/point-at-inference-2.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/point-at-inference-3.fixed b/tests/ui/type/type-check/point-at-inference-3.fixed new file mode 100644 index 000000000..44c057c0d --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-3.fixed @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + let mut v = Vec::new(); + v.push(0i32); + v.push(0); + v.push(1i32); //~ ERROR mismatched types + //~^ NOTE expected `i32`, found `u32` + //~| NOTE arguments to this method are incorrect + //~| NOTE associated function defined here + //~| HELP change the type of the numeric literal from `u32` to `i32` +} diff --git a/tests/ui/type/type-check/point-at-inference-3.rs b/tests/ui/type/type-check/point-at-inference-3.rs new file mode 100644 index 000000000..e7ae54384 --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-3.rs @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + let mut v = Vec::new(); + v.push(0i32); + v.push(0); + v.push(1u32); //~ ERROR mismatched types + //~^ NOTE expected `i32`, found `u32` + //~| NOTE arguments to this method are incorrect + //~| NOTE associated function defined here + //~| HELP change the type of the numeric literal from `u32` to `i32` +} diff --git a/tests/ui/type/type-check/point-at-inference-3.stderr b/tests/ui/type/type-check/point-at-inference-3.stderr new file mode 100644 index 000000000..d7936e39c --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference-3.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference-3.rs:6:12 + | +LL | v.push(1u32); + | ---- ^^^^ expected `i32`, found `u32` + | | + | arguments to this method are incorrect + | +note: associated function defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +help: change the type of the numeric literal from `u32` to `i32` + | +LL | v.push(1i32); + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/point-at-inference.rs b/tests/ui/type/type-check/point-at-inference.rs new file mode 100644 index 000000000..5c46dd4ed --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference.rs @@ -0,0 +1,12 @@ +fn bar(_: Vec) {} +fn baz(_: &impl std::any::Any) {} +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let mut foo = vec![]; + baz(&foo); + for i in &v { + foo.push(i); + } + baz(&foo); + bar(foo); //~ ERROR E0308 +} diff --git a/tests/ui/type/type-check/point-at-inference.stderr b/tests/ui/type/type-check/point-at-inference.stderr new file mode 100644 index 000000000..2e17e5c5f --- /dev/null +++ b/tests/ui/type/type-check/point-at-inference.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference.rs:11:9 + | +LL | bar(foo); + | --- ^^^ expected `i32`, found `&{integer}` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&{integer}>` +note: function defined here + --> $DIR/point-at-inference.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-check/unknown_type_for_closure.rs b/tests/ui/type/type-check/unknown_type_for_closure.rs new file mode 100644 index 000000000..167687c18 --- /dev/null +++ b/tests/ui/type/type-check/unknown_type_for_closure.rs @@ -0,0 +1,17 @@ +fn infer_in_arg() { + let x = |b: Vec<_>| {}; //~ ERROR E0282 +} + +fn empty_pattern() { + let x = |_| {}; //~ ERROR type annotations needed +} + +fn infer_ty() { + let x = |k: _| {}; //~ ERROR type annotations needed +} + +fn ambig_return() { + let x = || -> Vec<_> { Vec::new() }; //~ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/type/type-check/unknown_type_for_closure.stderr b/tests/ui/type/type-check/unknown_type_for_closure.stderr new file mode 100644 index 000000000..e5e29aabf --- /dev/null +++ b/tests/ui/type/type-check/unknown_type_for_closure.stderr @@ -0,0 +1,37 @@ +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:2:13 + | +LL | let x = |b: Vec<_>| {}; + | ^^^^^^^^^^^^^^ cannot infer type for struct `Vec<_>` + +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:6:14 + | +LL | let x = |_| {}; + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | let x = |_: /* Type */| {}; + | ++++++++++++ + +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:10:14 + | +LL | let x = |k: _| {}; + | ^ cannot infer type + +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:14:28 + | +LL | let x = || -> Vec<_> { Vec::new() }; + | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` + | +help: consider specifying the generic argument + | +LL | let x = || -> Vec<_> { Vec::::new() }; + | +++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-dependent-def-issue-49241.rs b/tests/ui/type/type-dependent-def-issue-49241.rs new file mode 100644 index 000000000..caf5bade5 --- /dev/null +++ b/tests/ui/type/type-dependent-def-issue-49241.rs @@ -0,0 +1,6 @@ +fn main() { + let v = vec![0]; + const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant + let s: [u32; l] = v.into_iter().collect(); + //~^ constant +} diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr new file mode 100644 index 000000000..af16a6e8f --- /dev/null +++ b/tests/ui/type/type-dependent-def-issue-49241.stderr @@ -0,0 +1,17 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/type-dependent-def-issue-49241.rs:3:22 + | +LL | const l: usize = v.count(); + | ------- ^ non-constant value + | | + | help: consider using `let` instead of `const`: `let l` + +note: erroneous constant used + --> $DIR/type-dependent-def-issue-49241.rs:4:18 + | +LL | let s: [u32; l] = v.into_iter().collect(); + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/type/type-error-break-tail.rs b/tests/ui/type/type-error-break-tail.rs new file mode 100644 index 000000000..d4e3e93d0 --- /dev/null +++ b/tests/ui/type/type-error-break-tail.rs @@ -0,0 +1,8 @@ +fn loop_ending() -> i32 { + loop { + if false { break; } //~ ERROR mismatched types + return 42; + } +} + +fn main() {} diff --git a/tests/ui/type/type-error-break-tail.stderr b/tests/ui/type/type-error-break-tail.stderr new file mode 100644 index 000000000..16dc6475c --- /dev/null +++ b/tests/ui/type/type-error-break-tail.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/type-error-break-tail.rs:3:20 + | +LL | fn loop_ending() -> i32 { + | --- expected `i32` because of return type +LL | loop { +LL | if false { break; } + | ^^^^^ + | | + | expected `i32`, found `()` + | help: give it a value of the expected type: `break 42` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-mismatch-multiple.rs b/tests/ui/type/type-mismatch-multiple.rs new file mode 100644 index 000000000..55d6ceef1 --- /dev/null +++ b/tests/ui/type/type-mismatch-multiple.rs @@ -0,0 +1,7 @@ +// Checking that the compiler reports multiple type errors at once + +fn main() { let a: bool = 1; let b: i32 = true; } +//~^ ERROR mismatched types +//~| expected `bool`, found integer +//~| ERROR mismatched types +//~| expected `i32`, found `bool` diff --git a/tests/ui/type/type-mismatch-multiple.stderr b/tests/ui/type/type-mismatch-multiple.stderr new file mode 100644 index 000000000..2e8654d31 --- /dev/null +++ b/tests/ui/type/type-mismatch-multiple.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-multiple.rs:3:27 + | +LL | fn main() { let a: bool = 1; let b: i32 = true; } + | ---- ^ expected `bool`, found integer + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/type-mismatch-multiple.rs:3:43 + | +LL | fn main() { let a: bool = 1; let b: i32 = true; } + | --- ^^^^ expected `i32`, found `bool` + | | + | expected due to this + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs new file mode 100644 index 000000000..c9cdc874c --- /dev/null +++ b/tests/ui/type/type-mismatch-same-crate-name.rs @@ -0,0 +1,27 @@ +// aux-build:crate_a1.rs +// aux-build:crate_a2.rs + +// This tests the extra note reported when a type error deals with +// seemingly identical types. +// The main use case of this error is when there are two crates +// (generally different versions of the same crate) with the same name +// causing a type mismatch. Here, we simulate that error using block-scoped +// aliased `extern crate` declarations. + +fn main() { + let foo2 = {extern crate crate_a2 as a; a::Foo}; + let bar2 = {extern crate crate_a2 as a; a::bar()}; + { + extern crate crate_a1 as a; + a::try_foo(foo2); + //~^ ERROR mismatched types + //~| perhaps two different versions of crate `crate_a1` + //~| expected struct `main::a::Foo` + a::try_bar(bar2); + //~^ ERROR mismatched types + //~| perhaps two different versions of crate `crate_a1` + //~| expected trait `main::a::Bar` + //~| expected struct `Box<(dyn main::a::Bar + 'static)>` + //~| found struct `Box` + } +} diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr new file mode 100644 index 000000000..fcafd315e --- /dev/null +++ b/tests/ui/type/type-mismatch-same-crate-name.stderr @@ -0,0 +1,46 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-same-crate-name.rs:16:20 + | +LL | a::try_foo(foo2); + | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo` + | | + | arguments to this function are incorrect + | + = note: struct `main::a::Foo` and struct `main::a::Foo` have similar names, but are actually distinct types +note: struct `main::a::Foo` is defined in crate `crate_a2` + --> $DIR/auxiliary/crate_a2.rs:1:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ +note: struct `main::a::Foo` is defined in crate `crate_a1` + --> $DIR/auxiliary/crate_a1.rs:1:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^ + = note: perhaps two different versions of crate `crate_a1` are being used? +note: function defined here + --> $DIR/auxiliary/crate_a1.rs:10:8 + | +LL | pub fn try_foo(x: Foo){} + | ^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-same-crate-name.rs:20:20 + | +LL | a::try_bar(bar2); + | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box<(dyn main::a::Bar + 'static)>` + found struct `Box` + = note: perhaps two different versions of crate `crate_a1` are being used? +note: function defined here + --> $DIR/auxiliary/crate_a1.rs:11:8 + | +LL | pub fn try_bar(x: Box){} + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-mismatch.rs b/tests/ui/type/type-mismatch.rs new file mode 100644 index 000000000..11bfa3a72 --- /dev/null +++ b/tests/ui/type/type-mismatch.rs @@ -0,0 +1,78 @@ +#![allow(non_camel_case_types)] + +trait Qux {} +struct A; +struct B; +impl Qux for A {} +impl Qux for B {} + +struct Foo(T, U, V); + +struct foo; +struct bar; + +fn want(t: T) {} + +fn have_usize(f: usize) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types +} + +fn have_foo(f: foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types +} + +fn have_foo_foo(f: Foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types +} + +fn have_foo_foo_b(f: Foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types +} + +fn have_foo_foo_b_a(f: Foo) { + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types + want::<&Foo>(f); //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/type/type-mismatch.stderr b/tests/ui/type/type-mismatch.stderr new file mode 100644 index 000000000..6c187bad0 --- /dev/null +++ b/tests/ui/type/type-mismatch.stderr @@ -0,0 +1,751 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:17:17 + | +LL | want::(f); + | ----------- ^ expected struct `foo`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:18:17 + | +LL | want::(f); + | ----------- ^ expected struct `bar`, found `usize` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:19:24 + | +LL | want::>(f); + | ------------------ ^ expected struct `Foo`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found type `usize` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:20:27 + | +LL | want::>(f); + | --------------------- ^ expected struct `Foo`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found type `usize` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:21:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `Foo`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found type `usize` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:22:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `Foo`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found type `usize` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:23:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `Foo`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found type `usize` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:24:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `Foo`, found `usize` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found type `usize` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:28:19 + | +LL | want::(f); + | ------------- ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:29:17 + | +LL | want::(f); + | ----------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:30:24 + | +LL | want::>(f); + | ------------------ ^ expected struct `Foo`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:31:27 + | +LL | want::>(f); + | --------------------- ^ expected struct `Foo`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:32:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `Foo`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:33:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `Foo`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:34:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `Foo`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:35:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `Foo`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:39:19 + | +LL | want::(f); + | ------------- ^ expected `usize`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:40:17 + | +LL | want::(f); + | ----------- ^ expected struct `foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:41:17 + | +LL | want::(f); + | ----------- ^ expected struct `bar`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `bar` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:42:24 + | +LL | want::>(f); + | ------------------ ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:43:27 + | +LL | want::>(f); + | --------------------- ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:44:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `B`, found struct `A` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo<_, B>` + found struct `Foo<_, A>` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:45:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:46:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:47:23 + | +LL | want::<&Foo>(f); + | ----------------- ^ + | | | + | | expected `&Foo`, found struct `Foo` + | | help: consider borrowing here: `&f` + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:48:26 + | +LL | want::<&Foo>(f); + | -------------------- ^ expected `&Foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:52:19 + | +LL | want::(f); + | ------------- ^ expected `usize`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:53:17 + | +LL | want::(f); + | ----------- ^ expected struct `foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:54:17 + | +LL | want::(f); + | ----------- ^ expected struct `bar`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `bar` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:55:24 + | +LL | want::>(f); + | ------------------ ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:56:27 + | +LL | want::>(f); + | --------------------- ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:57:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `A`, found struct `B` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo<_, A>` + found struct `Foo<_, B>` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:58:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:59:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:60:23 + | +LL | want::<&Foo>(f); + | ----------------- ^ expected `&Foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:61:26 + | +LL | want::<&Foo>(f); + | -------------------- ^ + | | | + | | expected `&Foo`, found struct `Foo` + | | help: consider borrowing here: `&f` + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:65:19 + | +LL | want::(f); + | ------------- ^ expected `usize`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected type `usize` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:66:17 + | +LL | want::(f); + | ----------- ^ expected struct `foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:67:17 + | +LL | want::(f); + | ----------- ^ expected struct `bar`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `bar` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:68:24 + | +LL | want::>(f); + | ------------------ ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:69:27 + | +LL | want::>(f); + | --------------------- ^ expected `usize`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:70:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `A`, found struct `B` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo<_, A, B>` + found struct `Foo<_, B, A>` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:71:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `B`, found struct `A` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo<_, _, B>` + found struct `Foo<_, _, A>` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:72:22 + | +LL | want::>(f); + | ---------------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:73:25 + | +LL | want::>(f); + | ------------------- ^ expected struct `bar`, found struct `foo` + | | + | arguments to this function are incorrect + | + = note: expected struct `Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:74:23 + | +LL | want::<&Foo>(f); + | ----------------- ^ expected `&Foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error[E0308]: mismatched types + --> $DIR/type-mismatch.rs:75:26 + | +LL | want::<&Foo>(f); + | -------------------- ^ expected `&Foo`, found struct `Foo` + | | + | arguments to this function are incorrect + | + = note: expected reference `&Foo` + found struct `Foo` +note: function defined here + --> $DIR/type-mismatch.rs:14:4 + | +LL | fn want(t: T) {} + | ^^^^ ---- + +error: aborting due to 47 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs new file mode 100644 index 000000000..444453dc6 --- /dev/null +++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.rs @@ -0,0 +1,17 @@ +// Test a default that references `Self` which is then used in an +// object type. Issue #18956. In this case, the value is supplied by +// the user, but pretty-printing the type during the error message +// caused an ICE. + +trait MyAdd { fn add(&self, other: &Rhs) -> Self; } + +impl MyAdd for i32 { + fn add(&self, other: &i32) -> i32 { *self + *other } +} + +fn main() { + let x: i32 = 5; + let y = x as dyn MyAdd; + //~^ ERROR E0038 + //~| ERROR cast to unsized type: `i32` as `dyn MyAdd` +} diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr new file mode 100644 index 000000000..8a296dc7e --- /dev/null +++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -0,0 +1,31 @@ +error[E0620]: cast to unsized type: `i32` as `dyn MyAdd` + --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13 + | +LL | let y = x as dyn MyAdd; + | ^^^^^^^^^^^^^^^^^^^ + | +help: consider using a box or reference as appropriate + --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:13 + | +LL | let y = x as dyn MyAdd; + | ^ + +error[E0038]: the trait `MyAdd` cannot be made into an object + --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 + | +LL | let y = x as dyn MyAdd; + | ^^^^^^^^^^^^^^ `MyAdd` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:6:55 + | +LL | trait MyAdd { fn add(&self, other: &Rhs) -> Self; } + | ----- ^^^^ ...because method `add` references the `Self` type in its return type + | | + | this trait cannot be made into an object... + = help: consider moving `add` to another trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0620. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self.rs b/tests/ui/type/type-parameter-defaults-referencing-Self.rs new file mode 100644 index 000000000..e5c81556e --- /dev/null +++ b/tests/ui/type/type-parameter-defaults-referencing-Self.rs @@ -0,0 +1,11 @@ +// Test a default that references `Self` which is then used in an object type. +// Issue #18956. + +trait Foo { + fn method(&self); +} + +fn foo(x: &dyn Foo) { } +//~^ ERROR the type parameter `T` must be explicitly specified + +fn main() { } diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr new file mode 100644 index 000000000..67a4745b3 --- /dev/null +++ b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr @@ -0,0 +1,14 @@ +error[E0393]: the type parameter `T` must be explicitly specified + --> $DIR/type-parameter-defaults-referencing-Self.rs:8:16 + | +LL | trait Foo { + | ----------------- type parameter `T` must be specified for this +... +LL | fn foo(x: &dyn Foo) { } + | ^^^ help: set the type parameter to the desired type: `Foo` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/type/type-parameter-names.rs b/tests/ui/type/type-parameter-names.rs new file mode 100644 index 000000000..b54a3fae0 --- /dev/null +++ b/tests/ui/type/type-parameter-names.rs @@ -0,0 +1,12 @@ +// Test that we print out the names of type parameters correctly in +// our error messages. + +fn foo(x: Foo) -> Bar { + x +//~^ ERROR mismatched types +//~| expected type parameter `Bar`, found type parameter `Foo` +//~| expected type parameter `Bar` +//~| found type parameter `Foo` +} + +fn main() {} diff --git a/tests/ui/type/type-parameter-names.stderr b/tests/ui/type/type-parameter-names.stderr new file mode 100644 index 000000000..f0ca8afca --- /dev/null +++ b/tests/ui/type/type-parameter-names.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/type-parameter-names.rs:5:5 + | +LL | fn foo(x: Foo) -> Bar { + | --- --- --- expected `Bar` because of return type + | | | + | | expected type parameter + | found type parameter +LL | x + | ^ expected type parameter `Bar`, found type parameter `Foo` + | + = note: expected type parameter `Bar` + found type parameter `Foo` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-params-in-different-spaces-1.rs b/tests/ui/type/type-params-in-different-spaces-1.rs new file mode 100644 index 000000000..6efd14d37 --- /dev/null +++ b/tests/ui/type/type-params-in-different-spaces-1.rs @@ -0,0 +1,18 @@ +use std::ops::Add; + +trait BrokenAdd: Copy + Add { + fn broken_add(&self, rhs: T) -> Self { + *self + rhs //~ ERROR mismatched types + //~| expected type parameter `Self`, found type parameter `T` + //~| expected type parameter `Self` + //~| found type parameter `T` + } +} + +impl> BrokenAdd for T {} + +pub fn main() { + let foo: u8 = 0; + let x: u8 = foo.broken_add("hello darkness my old friend".to_string()); + println!("{}", x); +} diff --git a/tests/ui/type/type-params-in-different-spaces-1.stderr b/tests/ui/type/type-params-in-different-spaces-1.stderr new file mode 100644 index 000000000..7529f25bd --- /dev/null +++ b/tests/ui/type/type-params-in-different-spaces-1.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/type-params-in-different-spaces-1.rs:5:17 + | +LL | trait BrokenAdd: Copy + Add { + | ---------------------------------------- expected type parameter +LL | fn broken_add(&self, rhs: T) -> Self { + | - found type parameter +LL | *self + rhs + | ----- ^^^ expected type parameter `Self`, found type parameter `T` + | | + | expected because this is `Self` + | + = note: expected type parameter `Self` + found type parameter `T` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-params-in-different-spaces-2.rs b/tests/ui/type/type-params-in-different-spaces-2.rs new file mode 100644 index 000000000..1211e465b --- /dev/null +++ b/tests/ui/type/type-params-in-different-spaces-2.rs @@ -0,0 +1,21 @@ +// Test static calls to make sure that we align the Self and input +// type parameters on a trait correctly. + +trait Tr : Sized { + fn op(_: T) -> Self; +} + +trait A: Tr { + fn test(u: U) -> Self { + Tr::op(u) //~ ERROR E0277 + } +} + +trait B: Tr { + fn test(u: U) -> Self { + Tr::op(u) //~ ERROR E0277 + } +} + +fn main() { +} diff --git a/tests/ui/type/type-params-in-different-spaces-2.stderr b/tests/ui/type/type-params-in-different-spaces-2.stderr new file mode 100644 index 000000000..220b3929c --- /dev/null +++ b/tests/ui/type/type-params-in-different-spaces-2.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `Self: Tr` is not satisfied + --> $DIR/type-params-in-different-spaces-2.rs:10:16 + | +LL | Tr::op(u) + | ------ ^ the trait `Tr` is not implemented for `Self` + | | + | required by a bound introduced by this call + | +help: consider further restricting `Self` + | +LL | fn test(u: U) -> Self where Self: Tr { + | +++++++++++++++++ + +error[E0277]: the trait bound `Self: Tr` is not satisfied + --> $DIR/type-params-in-different-spaces-2.rs:16:16 + | +LL | Tr::op(u) + | ------ ^ the trait `Tr` is not implemented for `Self` + | | + | required by a bound introduced by this call + | +help: consider further restricting `Self` + | +LL | fn test(u: U) -> Self where Self: Tr { + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type/type-params-in-different-spaces-3.rs b/tests/ui/type/type-params-in-different-spaces-3.rs new file mode 100644 index 000000000..ac7b0c11f --- /dev/null +++ b/tests/ui/type/type-params-in-different-spaces-3.rs @@ -0,0 +1,7 @@ +trait Tr : Sized { + fn test(u: X) -> Self { + u //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/type/type-params-in-different-spaces-3.stderr b/tests/ui/type/type-params-in-different-spaces-3.stderr new file mode 100644 index 000000000..c538d6731 --- /dev/null +++ b/tests/ui/type/type-params-in-different-spaces-3.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/type-params-in-different-spaces-3.rs:3:9 + | +LL | trait Tr : Sized { + | ---------------- expected type parameter +LL | fn test(u: X) -> Self { + | - ---- expected `Self` because of return type + | | + | found type parameter +LL | u + | ^ expected type parameter `Self`, found type parameter `X` + | + = note: expected type parameter `Self` + found type parameter `X` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-path-err-node-types.rs b/tests/ui/type/type-path-err-node-types.rs new file mode 100644 index 000000000..b3795772e --- /dev/null +++ b/tests/ui/type/type-path-err-node-types.rs @@ -0,0 +1,26 @@ +// Type arguments in unresolved entities (reporting errors before type checking) +// should have their types recorded. + +trait Tr {} + +fn local_type() { + let _: Nonexistent; //~ ERROR cannot find type `Nonexistent` in this scope +} + +fn ufcs_trait() { + >::nonexistent(); //~ ERROR cannot find method or associated constant `nonexistent` +} + +fn ufcs_item() { + NonExistent::Assoc::; //~ ERROR undeclared type `NonExistent` +} + +fn method() { + nonexistent.nonexistent::(); //~ ERROR cannot find value `nonexistent` +} + +fn closure() { + let _ = |a, b: _| -> _ { 0 }; //~ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/type/type-path-err-node-types.stderr b/tests/ui/type/type-path-err-node-types.stderr new file mode 100644 index 000000000..1aed1dbe4 --- /dev/null +++ b/tests/ui/type/type-path-err-node-types.stderr @@ -0,0 +1,39 @@ +error[E0433]: failed to resolve: use of undeclared type `NonExistent` + --> $DIR/type-path-err-node-types.rs:15:5 + | +LL | NonExistent::Assoc::; + | ^^^^^^^^^^^ use of undeclared type `NonExistent` + +error[E0412]: cannot find type `Nonexistent` in this scope + --> $DIR/type-path-err-node-types.rs:7:12 + | +LL | let _: Nonexistent; + | ^^^^^^^^^^^ not found in this scope + +error[E0576]: cannot find method or associated constant `nonexistent` in trait `Tr` + --> $DIR/type-path-err-node-types.rs:11:21 + | +LL | >::nonexistent(); + | ^^^^^^^^^^^ not found in `Tr` + +error[E0425]: cannot find value `nonexistent` in this scope + --> $DIR/type-path-err-node-types.rs:19:5 + | +LL | nonexistent.nonexistent::(); + | ^^^^^^^^^^^ not found in this scope + +error[E0282]: type annotations needed + --> $DIR/type-path-err-node-types.rs:23:14 + | +LL | let _ = |a, b: _| -> _ { 0 }; + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | let _ = |a: /* Type */, b: _| -> _ { 0 }; + | ++++++++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0282, E0412, E0425, E0433, E0576. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/type/type-recursive-box-shadowed.rs b/tests/ui/type/type-recursive-box-shadowed.rs new file mode 100644 index 000000000..e141c2149 --- /dev/null +++ b/tests/ui/type/type-recursive-box-shadowed.rs @@ -0,0 +1,12 @@ +//FIXME(compiler-errors): This fixup should suggest the full box path, not just `Box` + +struct Box { + t: T, +} + +struct Foo { + //~^ ERROR recursive type `Foo` has infinite size + inner: Foo, +} + +fn main() {} diff --git a/tests/ui/type/type-recursive-box-shadowed.stderr b/tests/ui/type/type-recursive-box-shadowed.stderr new file mode 100644 index 000000000..cb0e98287 --- /dev/null +++ b/tests/ui/type/type-recursive-box-shadowed.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/type-recursive-box-shadowed.rs:7:1 + | +LL | struct Foo { + | ^^^^^^^^^^ +LL | +LL | inner: Foo, + | --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | inner: Box, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/type/type-recursive.rs b/tests/ui/type/type-recursive.rs new file mode 100644 index 000000000..e8084f0d0 --- /dev/null +++ b/tests/ui/type/type-recursive.rs @@ -0,0 +1,30 @@ +struct T1 { //~ ERROR E0072 + foo: isize, + foolish: T1, +} + +struct T2 { //~ ERROR E0072 + inner: Option, +} + +type OptionT3 = Option; + +struct T3 { //~ ERROR E0072 + inner: OptionT3, +} + +struct T4(Option); //~ ERROR E0072 + +enum T5 { //~ ERROR E0072 + Variant(Option), +} + +enum T6 { //~ ERROR E0072 + Variant{ field: Option }, +} + +struct T7 { //~ ERROR E0072 + foo: std::cell::Cell>, +} + +fn main() { } diff --git a/tests/ui/type/type-recursive.stderr b/tests/ui/type/type-recursive.stderr new file mode 100644 index 000000000..9a4d798f6 --- /dev/null +++ b/tests/ui/type/type-recursive.stderr @@ -0,0 +1,93 @@ +error[E0072]: recursive type `T1` has infinite size + --> $DIR/type-recursive.rs:1:1 + | +LL | struct T1 { + | ^^^^^^^^^ +LL | foo: isize, +LL | foolish: T1, + | -- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | foolish: Box, + | ++++ + + +error[E0072]: recursive type `T2` has infinite size + --> $DIR/type-recursive.rs:6:1 + | +LL | struct T2 { + | ^^^^^^^^^ +LL | inner: Option, + | -- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | inner: Option>, + | ++++ + + +error[E0072]: recursive type `T3` has infinite size + --> $DIR/type-recursive.rs:12:1 + | +LL | struct T3 { + | ^^^^^^^^^ +LL | inner: OptionT3, + | -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | inner: Box, + | ++++ + + +error[E0072]: recursive type `T4` has infinite size + --> $DIR/type-recursive.rs:16:1 + | +LL | struct T4(Option); + | ^^^^^^^^^ -- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct T4(Option>); + | ++++ + + +error[E0072]: recursive type `T5` has infinite size + --> $DIR/type-recursive.rs:18:1 + | +LL | enum T5 { + | ^^^^^^^ +LL | Variant(Option), + | -- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | Variant(Option>), + | ++++ + + +error[E0072]: recursive type `T6` has infinite size + --> $DIR/type-recursive.rs:22:1 + | +LL | enum T6 { + | ^^^^^^^ +LL | Variant{ field: Option }, + | -- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | Variant{ field: Option> }, + | ++++ + + +error[E0072]: recursive type `T7` has infinite size + --> $DIR/type-recursive.rs:26:1 + | +LL | struct T7 { + | ^^^^^^^^^ +LL | foo: std::cell::Cell>, + | -- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | foo: std::cell::Cell>>, + | ++++ + + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/type/type-shadow.rs b/tests/ui/type/type-shadow.rs new file mode 100644 index 000000000..48a68a390 --- /dev/null +++ b/tests/ui/type/type-shadow.rs @@ -0,0 +1,8 @@ +fn main() { + type X = isize; + type Y = X; + if true { + type X = &'static str; + let y: Y = "hello"; //~ ERROR mismatched types + } +} diff --git a/tests/ui/type/type-shadow.stderr b/tests/ui/type/type-shadow.stderr new file mode 100644 index 000000000..25b4bff4d --- /dev/null +++ b/tests/ui/type/type-shadow.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/type-shadow.rs:6:20 + | +LL | let y: Y = "hello"; + | - ^^^^^^^ expected `isize`, found `&str` + | | + | expected due to this + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/type-unsatisfiable.rs b/tests/ui/type/type-unsatisfiable.rs new file mode 100644 index 000000000..7fbbb50dc --- /dev/null +++ b/tests/ui/type/type-unsatisfiable.rs @@ -0,0 +1,59 @@ +// revisions: lib usage +//[lib] compile-flags: --crate-type=lib +//[lib] build-pass + +use std::ops::Sub; +trait Vector2 { + type ScalarType; + + fn from_values(x: Self::ScalarType, y: Self::ScalarType) -> Self + where + Self: Sized; + + fn x(&self) -> Self::ScalarType; + fn y(&self) -> Self::ScalarType; +} + +impl Sub for dyn Vector2 +where + T: Sub, + (dyn Vector2): Sized, +{ + type Output = dyn Vector2; + + fn sub(self, rhs: Self) -> Self::Output { + Self::from_values(self.x() - rhs.x(), self.y() - rhs.y()) + } +} + +struct Vec2 { + x: i32, + y: i32, +} + +impl Vector2 for Vec2 { + type ScalarType = i32; + + fn from_values(x: Self::ScalarType, y: Self::ScalarType) -> Self + where + Self: Sized, + { + Self { x, y } + } + + fn x(&self) -> Self::ScalarType { + self.x + } + fn y(&self) -> Self::ScalarType { + self.y + } +} + +#[cfg(usage)] +fn main() { + let hey: Box> = Box::new(Vec2 { x: 1, y: 2 }); + let word: Box> = Box::new(Vec2 { x: 1, y: 2 }); + + let bar = *hey - *word; + //[usage]~^ ERROR cannot subtract +} diff --git a/tests/ui/type/type-unsatisfiable.usage.stderr b/tests/ui/type/type-unsatisfiable.usage.stderr new file mode 100644 index 000000000..56e2e30af --- /dev/null +++ b/tests/ui/type/type-unsatisfiable.usage.stderr @@ -0,0 +1,11 @@ +error[E0369]: cannot subtract `(dyn Vector2 + 'static)` from `dyn Vector2` + --> $DIR/type-unsatisfiable.rs:57:20 + | +LL | let bar = *hey - *word; + | ---- ^ ----- (dyn Vector2 + 'static) + | | + | dyn Vector2 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs new file mode 100644 index 000000000..ba5b9f542 --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs @@ -0,0 +1,28 @@ +fn function(x: T, y: bool) -> T { + x +} + +struct S {} +impl S { + fn method(&self, x: T) -> T { + x + } +} + +fn wrong_arg_type(x: u32) -> u32 { + x +} + +fn main() { + // Should not trigger. + let x = wrong_arg_type(0u16); //~ ERROR mismatched types + let x: u16 = function(0, 0u8); //~ ERROR mismatched types + + // Should trigger exactly once for the first argument. + let x: u16 = function(0u32, 0u8); //~ ERROR arguments to this function are incorrect + + // Should trigger. + let x: u16 = function(0u32, true); //~ ERROR mismatched types + let x: u16 = (S {}).method(0u32); //~ ERROR mismatched types + function(0u32, 8u8) //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr new file mode 100644 index 000000000..4d012cb15 --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr @@ -0,0 +1,131 @@ +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:18:28 + | +LL | let x = wrong_arg_type(0u16); + | -------------- ^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:12:4 + | +LL | fn wrong_arg_type(x: u32) -> u32 { + | ^^^^^^^^^^^^^^ ------ +help: change the type of the numeric literal from `u16` to `u32` + | +LL | let x = wrong_arg_type(0u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:19:30 + | +LL | let x: u16 = function(0, 0u8); + | -------- ^^^ expected `bool`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18 + | +LL | let x: u16 = function(0u32, 0u8); + | ^^^^^^^^ ---- --- expected `bool`, found `u8` + | | + | expected `u16`, found `u32` + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18 + | +LL | let x: u16 = function(0u32, 0u8); + | ^^^^^^^^^----^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ---- ------- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = function(0u16, 0u8); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:27 + | +LL | let x: u16 = function(0u32, true); + | -------- ^^^^ expected `u16`, found `u32` + | | + | arguments to this function are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:18 + | +LL | let x: u16 = function(0u32, true); + | ^^^^^^^^^----^^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ---- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = function(0u16, true); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:32 + | +LL | let x: u16 = (S {}).method(0u32); + | ------ ^^^^ expected `u16`, found `u32` + | | + | arguments to this method are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:18 + | +LL | let x: u16 = (S {}).method(0u32); + | ^^^^^^^^^^^^^^----^ + | | + | this argument influences the return type of `method` +note: associated function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8 + | +LL | fn method(&self, x: T) -> T { + | ^^^^^^ ---- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = (S {}).method(0u16); + | ~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5 + | +LL | function(0u32, 8u8) + | ^^^^^^^^ ---- --- expected `bool`, found `u8` + | | + | expected `()`, found `u32` + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5 + | +LL | function(0u32, 8u8) + | ^^^^^^^^^----^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ---- ------- + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type_length_limit.polonius.stderr b/tests/ui/type_length_limit.polonius.stderr new file mode 100644 index 000000000..82d066b2a --- /dev/null +++ b/tests/ui/type_length_limit.polonius.stderr @@ -0,0 +1,11 @@ +error: reached the type-length limit while instantiating `std::mem::drop::>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub fn drop(_x: T) {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit.polonius/type_length_limit.long-type.txt' + = help: consider adding a `#![type_length_limit="8"]` attribute to your crate + +error: aborting due to previous error + diff --git a/tests/ui/type_length_limit.rs b/tests/ui/type_length_limit.rs new file mode 100644 index 000000000..b3c127474 --- /dev/null +++ b/tests/ui/type_length_limit.rs @@ -0,0 +1,34 @@ +// build-fail +// error-pattern: reached the type-length limit while instantiating +// compile-flags: -Copt-level=0 +// normalize-stderr-test: ".nll/" -> "/" + +// Test that the type length limit can be changed. +// The exact type depends on optimizations, so disable them. + +#![allow(dead_code)] +#![type_length_limit="8"] + +macro_rules! link { + ($id:ident, $t:ty) => { + pub type $id = ($t, $t, $t); + } +} + +link! { A1, B1 } +link! { B1, C1 } +link! { C1, D1 } +link! { D1, E1 } +link! { E1, A } +link! { A, B } +link! { B, C } +link! { C, D } +link! { D, E } +link! { E, F } +link! { F, G, Option> } + +pub struct G(std::marker::PhantomData::<(T, K)>); + +fn main() { + drop::>(None); +} diff --git a/tests/ui/type_length_limit.stderr b/tests/ui/type_length_limit.stderr new file mode 100644 index 000000000..5b00d387a --- /dev/null +++ b/tests/ui/type_length_limit.stderr @@ -0,0 +1,8 @@ +error: reached the type-length limit while instantiating `std::mem::drop::>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = help: consider adding a `#![type_length_limit="10"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' + +error: aborting due to previous error + diff --git a/tests/ui/typeck/assign-non-lval-derefmut.fixed b/tests/ui/typeck/assign-non-lval-derefmut.fixed new file mode 100644 index 000000000..0c23199af --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-derefmut.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +fn main() { + let x = std::sync::Mutex::new(1usize); + *x.lock().unwrap() = 2; + //~^ ERROR invalid left-hand side of assignment + *x.lock().unwrap() += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>` + + let mut y = x.lock().unwrap(); + *y = 2; + //~^ ERROR mismatched types + *y += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>` +} diff --git a/tests/ui/typeck/assign-non-lval-derefmut.rs b/tests/ui/typeck/assign-non-lval-derefmut.rs new file mode 100644 index 000000000..ec1882f52 --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-derefmut.rs @@ -0,0 +1,15 @@ +// run-rustfix + +fn main() { + let x = std::sync::Mutex::new(1usize); + x.lock().unwrap() = 2; + //~^ ERROR invalid left-hand side of assignment + x.lock().unwrap() += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>` + + let mut y = x.lock().unwrap(); + y = 2; + //~^ ERROR mismatched types + y += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>` +} diff --git a/tests/ui/typeck/assign-non-lval-derefmut.stderr b/tests/ui/typeck/assign-non-lval-derefmut.stderr new file mode 100644 index 000000000..e394cf820 --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-derefmut.stderr @@ -0,0 +1,58 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/assign-non-lval-derefmut.rs:5:23 + | +LL | x.lock().unwrap() = 2; + | ----------------- ^ + | | + | cannot assign to this expression + | +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *x.lock().unwrap() = 2; + | + + +error[E0368]: binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>` + --> $DIR/assign-non-lval-derefmut.rs:7:5 + | +LL | x.lock().unwrap() += 1; + | -----------------^^^^^ + | | + | cannot use `+=` on type `MutexGuard<'_, usize>` + | +help: `+=` can be used on `usize` if you dereference the left-hand side + | +LL | *x.lock().unwrap() += 1; + | + + +error[E0308]: mismatched types + --> $DIR/assign-non-lval-derefmut.rs:11:9 + | +LL | let mut y = x.lock().unwrap(); + | ----------------- expected due to this value +LL | y = 2; + | ^ expected struct `MutexGuard`, found integer + | + = note: expected struct `MutexGuard<'_, usize>` + found type `{integer}` +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *y = 2; + | + + +error[E0368]: binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>` + --> $DIR/assign-non-lval-derefmut.rs:13:5 + | +LL | y += 1; + | -^^^^^ + | | + | cannot use `+=` on type `MutexGuard<'_, usize>` + | +help: `+=` can be used on `usize` if you dereference the left-hand side + | +LL | *y += 1; + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0308, E0368. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/typeck/assign-non-lval-mut-ref.fixed b/tests/ui/typeck/assign-non-lval-mut-ref.fixed new file mode 100644 index 000000000..10c7b9dbf --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-mut-ref.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +fn main() { + let mut x = vec![1usize]; + *x.last_mut().unwrap() = 2; + //~^ ERROR invalid left-hand side of assignment + *x.last_mut().unwrap() += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize` + + let y = x.last_mut().unwrap(); + *y = 2; + //~^ ERROR mismatched types + *y += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize` +} diff --git a/tests/ui/typeck/assign-non-lval-mut-ref.rs b/tests/ui/typeck/assign-non-lval-mut-ref.rs new file mode 100644 index 000000000..bceff0ef0 --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-mut-ref.rs @@ -0,0 +1,15 @@ +// run-rustfix + +fn main() { + let mut x = vec![1usize]; + x.last_mut().unwrap() = 2; + //~^ ERROR invalid left-hand side of assignment + x.last_mut().unwrap() += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize` + + let y = x.last_mut().unwrap(); + y = 2; + //~^ ERROR mismatched types + y += 1; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize` +} diff --git a/tests/ui/typeck/assign-non-lval-mut-ref.stderr b/tests/ui/typeck/assign-non-lval-mut-ref.stderr new file mode 100644 index 000000000..cbdc960ba --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-mut-ref.stderr @@ -0,0 +1,56 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/assign-non-lval-mut-ref.rs:5:27 + | +LL | x.last_mut().unwrap() = 2; + | --------------------- ^ + | | + | cannot assign to this expression + | +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *x.last_mut().unwrap() = 2; + | + + +error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize` + --> $DIR/assign-non-lval-mut-ref.rs:7:5 + | +LL | x.last_mut().unwrap() += 1; + | ---------------------^^^^^ + | | + | cannot use `+=` on type `&mut usize` + | +help: `+=` can be used on `usize` if you dereference the left-hand side + | +LL | *x.last_mut().unwrap() += 1; + | + + +error[E0308]: mismatched types + --> $DIR/assign-non-lval-mut-ref.rs:11:9 + | +LL | let y = x.last_mut().unwrap(); + | --------------------- expected due to this value +LL | y = 2; + | ^ expected `&mut usize`, found integer + | +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *y = 2; + | + + +error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize` + --> $DIR/assign-non-lval-mut-ref.rs:13:5 + | +LL | y += 1; + | -^^^^^ + | | + | cannot use `+=` on type `&mut usize` + | +help: `+=` can be used on `usize` if you dereference the left-hand side + | +LL | *y += 1; + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0308, E0368. +For more information about an error, try `rustc --explain E0070`. diff --git a/tests/ui/typeck/assign-non-lval-needs-deref.rs b/tests/ui/typeck/assign-non-lval-needs-deref.rs new file mode 100644 index 000000000..c979d76b4 --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-needs-deref.rs @@ -0,0 +1,19 @@ +// issue #101376 + +use std::ops::AddAssign; +struct Foo; + +impl AddAssign<()> for Foo { + fn add_assign(&mut self, _: ()) {} +} + +impl AddAssign<()> for &mut Foo { + fn add_assign(&mut self, _: ()) {} +} + +fn main() { + (&mut Foo) += (); + //~^ ERROR invalid left-hand side of assignment + //~| NOTE cannot assign to this expression + //~| HELP consider dereferencing the left-hand side of this operation +} diff --git a/tests/ui/typeck/assign-non-lval-needs-deref.stderr b/tests/ui/typeck/assign-non-lval-needs-deref.stderr new file mode 100644 index 000000000..ee83b1453 --- /dev/null +++ b/tests/ui/typeck/assign-non-lval-needs-deref.stderr @@ -0,0 +1,16 @@ +error[E0067]: invalid left-hand side of assignment + --> $DIR/assign-non-lval-needs-deref.rs:15:16 + | +LL | (&mut Foo) += (); + | ---------- ^^ + | | + | cannot assign to this expression + | +help: consider dereferencing the left-hand side of this operation + | +LL | *(&mut Foo) += (); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0067`. diff --git a/tests/ui/typeck/autoderef-with-param-env-error.rs b/tests/ui/typeck/autoderef-with-param-env-error.rs new file mode 100644 index 000000000..ec96c61c6 --- /dev/null +++ b/tests/ui/typeck/autoderef-with-param-env-error.rs @@ -0,0 +1,9 @@ +fn foo() +where + T: Send, + //~^ cannot find type `T` in this scope +{ + let s = "abc".to_string(); +} + +fn main() {} diff --git a/tests/ui/typeck/autoderef-with-param-env-error.stderr b/tests/ui/typeck/autoderef-with-param-env-error.stderr new file mode 100644 index 000000000..182612d5e --- /dev/null +++ b/tests/ui/typeck/autoderef-with-param-env-error.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/autoderef-with-param-env-error.rs:3:5 + | +LL | T: Send, + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn foo() + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/auxiliary/issue-36708.rs b/tests/ui/typeck/auxiliary/issue-36708.rs new file mode 100644 index 000000000..bd8580f97 --- /dev/null +++ b/tests/ui/typeck/auxiliary/issue-36708.rs @@ -0,0 +1,5 @@ +#![crate_type = "lib"] + +pub trait Foo { + fn foo(); +} diff --git a/tests/ui/typeck/auxiliary/issue-81943-lib.rs b/tests/ui/typeck/auxiliary/issue-81943-lib.rs new file mode 100644 index 000000000..521c54f89 --- /dev/null +++ b/tests/ui/typeck/auxiliary/issue-81943-lib.rs @@ -0,0 +1,7 @@ +pub fn g(t: i32) -> i32 { t } +// This function imitates `dbg!` so that future changes +// to its macro definition won't make this test a dud. +#[macro_export] +macro_rules! d { + ($e:expr) => { match $e { x => { $crate::g(x) } } } +} diff --git a/tests/ui/typeck/auxiliary/tdticc_coherence_lib.rs b/tests/ui/typeck/auxiliary/tdticc_coherence_lib.rs new file mode 100644 index 000000000..ef2cd415f --- /dev/null +++ b/tests/ui/typeck/auxiliary/tdticc_coherence_lib.rs @@ -0,0 +1,6 @@ +#![feature(auto_traits, core)] +#![crate_type = "rlib"] + +pub auto trait DefaultedTrait { } + +pub struct Something { t: T } diff --git a/tests/ui/typeck/auxiliary/xcrate-issue-43189-a.rs b/tests/ui/typeck/auxiliary/xcrate-issue-43189-a.rs new file mode 100644 index 000000000..9ab570fd1 --- /dev/null +++ b/tests/ui/typeck/auxiliary/xcrate-issue-43189-a.rs @@ -0,0 +1,7 @@ +#![crate_type="lib"] + + +pub trait A { + fn a(&self) {} +} +impl A for () {} diff --git a/tests/ui/typeck/auxiliary/xcrate-issue-43189-b.rs b/tests/ui/typeck/auxiliary/xcrate-issue-43189-b.rs new file mode 100644 index 000000000..31dfb050b --- /dev/null +++ b/tests/ui/typeck/auxiliary/xcrate-issue-43189-b.rs @@ -0,0 +1,3 @@ +#![crate_type="lib"] + +pub extern crate xcrate_issue_43189_a; diff --git a/tests/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs b/tests/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs new file mode 100644 index 000000000..2b517b578 --- /dev/null +++ b/tests/ui/typeck/auxiliary/xcrate-issue-46112-rexport-core.rs @@ -0,0 +1,3 @@ +#![crate_type="lib"] + +pub extern crate core; diff --git a/tests/ui/typeck/auxiliary/xcrate-issue-61711-b.rs b/tests/ui/typeck/auxiliary/xcrate-issue-61711-b.rs new file mode 100644 index 000000000..88a040529 --- /dev/null +++ b/tests/ui/typeck/auxiliary/xcrate-issue-61711-b.rs @@ -0,0 +1,5 @@ +// edition:2018 +#![crate_type="lib"] +#![crate_name="xcrate_issue_61711_b"] +pub struct Struct; +pub use crate as alias; diff --git a/tests/ui/typeck/call-block.rs b/tests/ui/typeck/call-block.rs new file mode 100644 index 000000000..0390d7db0 --- /dev/null +++ b/tests/ui/typeck/call-block.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = {42}(); //~ ERROR expected function, found `{integer}` +} diff --git a/tests/ui/typeck/call-block.stderr b/tests/ui/typeck/call-block.stderr new file mode 100644 index 000000000..68984bc1c --- /dev/null +++ b/tests/ui/typeck/call-block.stderr @@ -0,0 +1,11 @@ +error[E0618]: expected function, found `{integer}` + --> $DIR/call-block.rs:2:13 + | +LL | let _ = {42}(); + | ^^^^-- + | | + | call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/typeck/check-args-on-fn-err-2.rs b/tests/ui/typeck/check-args-on-fn-err-2.rs new file mode 100644 index 000000000..af57dbe33 --- /dev/null +++ b/tests/ui/typeck/check-args-on-fn-err-2.rs @@ -0,0 +1,5 @@ +fn main() { + a((), 1i32 == 2u32); + //~^ ERROR cannot find function `a` in this scope + //~| ERROR mismatched types +} diff --git a/tests/ui/typeck/check-args-on-fn-err-2.stderr b/tests/ui/typeck/check-args-on-fn-err-2.stderr new file mode 100644 index 000000000..301bb88db --- /dev/null +++ b/tests/ui/typeck/check-args-on-fn-err-2.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/check-args-on-fn-err-2.rs:2:19 + | +LL | a((), 1i32 == 2u32); + | ---- ^^^^ expected `i32`, found `u32` + | | + | expected because this is `i32` + | +help: change the type of the numeric literal from `u32` to `i32` + | +LL | a((), 1i32 == 2i32); + | ~~~ + +error[E0425]: cannot find function `a` in this scope + --> $DIR/check-args-on-fn-err-2.rs:2:5 + | +LL | a((), 1i32 == 2u32); + | ^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/check-args-on-fn-err.rs b/tests/ui/typeck/check-args-on-fn-err.rs new file mode 100644 index 000000000..04b98ddd9 --- /dev/null +++ b/tests/ui/typeck/check-args-on-fn-err.rs @@ -0,0 +1,6 @@ +fn main() { + unknown(1, |glyf| { + //~^ ERROR: cannot find function `unknown` in this scope + let actual = glyf; + }); +} diff --git a/tests/ui/typeck/check-args-on-fn-err.stderr b/tests/ui/typeck/check-args-on-fn-err.stderr new file mode 100644 index 000000000..864d33e0e --- /dev/null +++ b/tests/ui/typeck/check-args-on-fn-err.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `unknown` in this scope + --> $DIR/check-args-on-fn-err.rs:2:5 + | +LL | unknown(1, |glyf| { + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/conversion-methods.rs b/tests/ui/typeck/conversion-methods.rs new file mode 100644 index 000000000..46c2e511f --- /dev/null +++ b/tests/ui/typeck/conversion-methods.rs @@ -0,0 +1,13 @@ +use std::path::{Path, PathBuf}; + + +fn main() { + let _tis_an_instants_play: String = "'Tis a fond Ambush—"; //~ ERROR mismatched types + let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise"); + //~^ ERROR mismatched types + + let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here + //~^ ERROR mismatched types + + let _prove_piercing_earnest: Vec = &[1, 2, 3]; //~ ERROR mismatched types +} diff --git a/tests/ui/typeck/conversion-methods.stderr b/tests/ui/typeck/conversion-methods.stderr new file mode 100644 index 000000000..091502bdd --- /dev/null +++ b/tests/ui/typeck/conversion-methods.stderr @@ -0,0 +1,45 @@ +error[E0308]: mismatched types + --> $DIR/conversion-methods.rs:5:41 + | +LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—"; + | ------ ^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found `&str` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/conversion-methods.rs:6:40 + | +LL | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise"); + | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_path_buf()` + | | | + | | expected struct `PathBuf`, found `&Path` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/conversion-methods.rs:9:40 + | +LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here + | ------ ^- help: try using a conversion method: `.to_string()` + | | | + | | expected struct `String`, found integer + | expected due to this + +error[E0308]: mismatched types + --> $DIR/conversion-methods.rs:12:47 + | +LL | let _prove_piercing_earnest: Vec = &[1, 2, 3]; + | ---------- ^^^^^^^^^^ expected struct `Vec`, found `&[{integer}; 3]` + | | + | expected due to this + | + = note: expected struct `Vec` + found reference `&[{integer}; 3]` +help: try using a conversion method + | +LL | let _prove_piercing_earnest: Vec = (&[1, 2, 3]).to_vec(); + | + ++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/deref-multi.rs b/tests/ui/typeck/deref-multi.rs new file mode 100644 index 000000000..3dc4771fe --- /dev/null +++ b/tests/ui/typeck/deref-multi.rs @@ -0,0 +1,26 @@ +fn a(x: &&i32) -> i32 { + x + //~^ ERROR mismatched types +} + +fn a2(x: &&&&&i32) -> i32 { + x + //~^ ERROR mismatched types +} + +fn b(x: &i32) -> i32 { + &x + //~^ ERROR mismatched types +} + +fn c(x: Box) -> i32 { + &x + //~^ ERROR mismatched types +} + +fn d(x: std::sync::Mutex<&i32>) -> i32 { + x.lock().unwrap() + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/typeck/deref-multi.stderr b/tests/ui/typeck/deref-multi.stderr new file mode 100644 index 000000000..bd6575c73 --- /dev/null +++ b/tests/ui/typeck/deref-multi.stderr @@ -0,0 +1,72 @@ +error[E0308]: mismatched types + --> $DIR/deref-multi.rs:2:5 + | +LL | fn a(x: &&i32) -> i32 { + | --- expected `i32` because of return type +LL | x + | ^ expected `i32`, found `&&i32` + | +help: consider dereferencing the borrow + | +LL | **x + | ++ + +error[E0308]: mismatched types + --> $DIR/deref-multi.rs:7:5 + | +LL | fn a2(x: &&&&&i32) -> i32 { + | --- expected `i32` because of return type +LL | x + | ^ expected `i32`, found `&&&&&i32` + | +help: consider dereferencing the borrow + | +LL | *****x + | +++++ + +error[E0308]: mismatched types + --> $DIR/deref-multi.rs:12:5 + | +LL | fn b(x: &i32) -> i32 { + | --- expected `i32` because of return type +LL | &x + | ^^ expected `i32`, found `&&i32` + | +help: consider removing the `&` and dereferencing the borrow instead + | +LL | *x + | ~ + +error[E0308]: mismatched types + --> $DIR/deref-multi.rs:17:5 + | +LL | fn c(x: Box) -> i32 { + | --- expected `i32` because of return type +LL | &x + | ^^ expected `i32`, found `&Box` + | + = note: expected type `i32` + found reference `&Box` +help: consider removing the `&` and dereferencing the borrow instead + | +LL | *x + | ~ + +error[E0308]: mismatched types + --> $DIR/deref-multi.rs:22:5 + | +LL | fn d(x: std::sync::Mutex<&i32>) -> i32 { + | --- expected `i32` because of return type +LL | x.lock().unwrap() + | ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `MutexGuard` + | + = note: expected type `i32` + found struct `MutexGuard<'_, &i32>` +help: consider dereferencing the type + | +LL | **x.lock().unwrap() + | ++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs b/tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs new file mode 100644 index 000000000..501f4b6ef --- /dev/null +++ b/tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.rs @@ -0,0 +1,21 @@ +macro_rules! num { () => { 1 } } + +fn main() { + let x = 1i32; + x.e10; //~ERROR `i32` is a primitive type and therefore doesn't have fields + + let y = 1; + y.e10; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 2u32.e10; //~ERROR `u32` is a primitive type and therefore doesn't have fields + + num!().e10; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 2.e10foo; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 42._; + //~^ERROR expected identifier, found reserved identifier `_` + //~|ERROR `{integer}` is a primitive type and therefore doesn't have fields + + 42.a; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr b/tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr new file mode 100644 index 000000000..1ef1d4c28 --- /dev/null +++ b/tests/ui/typeck/do-not-suggest-adding-missing-zero-to-floating-point-number.stderr @@ -0,0 +1,51 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:16:8 + | +LL | 42._; + | ^ expected identifier, found reserved identifier + +error[E0610]: `i32` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:5:7 + | +LL | x.e10; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:8:7 + | +LL | y.e10; + | ^^^ + +error[E0610]: `u32` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:10:10 + | +LL | 2u32.e10; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:12:12 + | +LL | num!().e10; + | ^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:14:7 + | +LL | 2.e10foo; + | ^^^^^^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:16:8 + | +LL | 42._; + | ^ + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/do-not-suggest-adding-missing-zero-to-floating-point-number.rs:20:8 + | +LL | 42.a; + | ^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs b/tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs new file mode 100644 index 000000000..97e0b213f --- /dev/null +++ b/tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs @@ -0,0 +1,8 @@ +trait Foo { + const A; //~ ERROR missing type for `const` item + static B; + //~^ ERROR associated `static` items are not allowed + //~| ERROR missing type for `static` item +} + +fn main() {} diff --git a/tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr b/tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr new file mode 100644 index 000000000..8982d6285 --- /dev/null +++ b/tests/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr @@ -0,0 +1,20 @@ +error: associated `static` items are not allowed + --> $DIR/do-not-suggest-placeholder-to-const-static-without-type.rs:3:5 + | +LL | static B; + | ^^^^^^^^^ + +error: missing type for `const` item + --> $DIR/do-not-suggest-placeholder-to-const-static-without-type.rs:2:12 + | +LL | const A; + | ^ help: provide a type for the item: `: ` + +error: missing type for `static` item + --> $DIR/do-not-suggest-placeholder-to-const-static-without-type.rs:3:13 + | +LL | static B; + | ^ help: provide a type for the item: `: ` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/typeck/explain_clone_autoref.rs b/tests/ui/typeck/explain_clone_autoref.rs new file mode 100644 index 000000000..9279e4c39 --- /dev/null +++ b/tests/ui/typeck/explain_clone_autoref.rs @@ -0,0 +1,13 @@ +struct NotClone; + +fn main() { + clone_thing(&NotClone); +} + +fn clone_thing(nc: &NotClone) -> NotClone { + //~^ NOTE expected `NotClone` because of return type + nc.clone() + //~^ ERROR mismatched type + //~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead + //~| NOTE expected struct `NotClone`, found `&NotClone` +} diff --git a/tests/ui/typeck/explain_clone_autoref.stderr b/tests/ui/typeck/explain_clone_autoref.stderr new file mode 100644 index 000000000..ff36e18d2 --- /dev/null +++ b/tests/ui/typeck/explain_clone_autoref.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/explain_clone_autoref.rs:9:5 + | +LL | fn clone_thing(nc: &NotClone) -> NotClone { + | -------- expected `NotClone` because of return type +LL | +LL | nc.clone() + | ^^^^^^^^^^ expected struct `NotClone`, found `&NotClone` + | +note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead + --> $DIR/explain_clone_autoref.rs:9:5 + | +LL | nc.clone() + | ^^ +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-100164.fixed b/tests/ui/typeck/issue-100164.fixed new file mode 100644 index 000000000..a5f68beb1 --- /dev/null +++ b/tests/ui/typeck/issue-100164.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +const _A: i32 = 123; +//~^ ERROR: missing type for `const` item + +fn main() { + const _B: i32 = 123; + //~^ ERROR: missing type for `const` item +} diff --git a/tests/ui/typeck/issue-100164.rs b/tests/ui/typeck/issue-100164.rs new file mode 100644 index 000000000..7efb9ac62 --- /dev/null +++ b/tests/ui/typeck/issue-100164.rs @@ -0,0 +1,9 @@ +// run-rustfix + +const _A: = 123; +//~^ ERROR: missing type for `const` item + +fn main() { + const _B: = 123; + //~^ ERROR: missing type for `const` item +} diff --git a/tests/ui/typeck/issue-100164.stderr b/tests/ui/typeck/issue-100164.stderr new file mode 100644 index 000000000..06a132d65 --- /dev/null +++ b/tests/ui/typeck/issue-100164.stderr @@ -0,0 +1,14 @@ +error: missing type for `const` item + --> $DIR/issue-100164.rs:3:10 + | +LL | const _A: = 123; + | ^ help: provide a type for the constant: `i32` + +error: missing type for `const` item + --> $DIR/issue-100164.rs:7:14 + | +LL | const _B: = 123; + | ^ help: provide a type for the constant: `i32` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/typeck/issue-100246.rs b/tests/ui/typeck/issue-100246.rs new file mode 100644 index 000000000..8f0b34bab --- /dev/null +++ b/tests/ui/typeck/issue-100246.rs @@ -0,0 +1,30 @@ +#![recursion_limit = "5"] // To reduce noise + +//expect incompatible type error when ambiguous traits are in scope +//and not an overflow error on the span in the main function. + +struct Ratio(T); + +pub trait Pow { + fn pow(self) -> Self; +} + +impl<'a, T> Pow for &'a Ratio +where + &'a T: Pow, +{ + fn pow(self) -> Self { + self + } +} + +fn downcast<'a, W: ?Sized>() -> std::io::Result<&'a W> { + todo!() +} + +struct Other; + +fn main() -> std::io::Result<()> { + let other: Other = downcast()?;//~ERROR 28:24: 28:35: `?` operator has incompatible types + Ok(()) +} diff --git a/tests/ui/typeck/issue-100246.stderr b/tests/ui/typeck/issue-100246.stderr new file mode 100644 index 000000000..8b77de94e --- /dev/null +++ b/tests/ui/typeck/issue-100246.stderr @@ -0,0 +1,13 @@ +error[E0308]: `?` operator has incompatible types + --> $DIR/issue-100246.rs:28:24 + | +LL | let other: Other = downcast()?; + | ^^^^^^^^^^^ expected struct `Other`, found reference + | + = note: `?` operator cannot convert from `&_` to `Other` + = note: expected struct `Other` + found reference `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-100285.rs b/tests/ui/typeck/issue-100285.rs new file mode 100644 index 000000000..e206469b8 --- /dev/null +++ b/tests/ui/typeck/issue-100285.rs @@ -0,0 +1,22 @@ +fn foo(n: i32) -> i32 { + for i in 0..0 { + //~^ ERROR: mismatched types [E0308] + if n < 0 { + return i; + } else if n < 10 { + return 1; + } else if n < 20 { + return 2; + } else if n < 30 { + return 3; + } else if n < 40 { + return 4; + } else { + return 5; + } + + } + //~| help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility +} + +fn main() {} diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr new file mode 100644 index 000000000..42c64b039 --- /dev/null +++ b/tests/ui/typeck/issue-100285.stderr @@ -0,0 +1,34 @@ +error[E0308]: mismatched types + --> $DIR/issue-100285.rs:2:5 + | +LL | fn foo(n: i32) -> i32 { + | --- expected `i32` because of return type +LL | / for i in 0..0 { +LL | | +LL | | if n < 0 { +LL | | return i; +... | +LL | | +LL | | } + | |_____^ expected `i32`, found `()` + | +note: the function expects a value to always be returned, but loops might run zero times + --> $DIR/issue-100285.rs:2:5 + | +LL | for i in 0..0 { + | ^^^^^^^^^^^^^ this might have zero elements to iterate on +... +LL | return i; + | -------- if the loop doesn't execute, this value would never get returned +LL | } else if n < 10 { +LL | return 1; + | -------- if the loop doesn't execute, this value would never get returned +LL | } else if n < 20 { +LL | return 2; + | -------- if the loop doesn't execute, this value would never get returned + = note: if the loop doesn't execute, 3 other values would never get returned + = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs new file mode 100644 index 000000000..ac9e4c716 --- /dev/null +++ b/tests/ui/typeck/issue-103899.rs @@ -0,0 +1,30 @@ +// check-fail +// failure-status: 101 +// dont-check-compiler-stderr +// known-bug: #103899 + +trait BaseWithAssoc { + type Assoc; +} + +trait WrapperWithAssoc { + type BaseAssoc: BaseWithAssoc; +} + +struct Wrapper { + inner: B, +} + +struct ProjectToBase { + data_type_h: T::Assoc, +} + +struct DoubleProject { + buffer: Wrapper>, +} + +fn trigger>() -> DoubleProject { + loop {} +} + +fn main() {} diff --git a/tests/ui/typeck/issue-10401.rs b/tests/ui/typeck/issue-10401.rs new file mode 100644 index 000000000..d77ff381e --- /dev/null +++ b/tests/ui/typeck/issue-10401.rs @@ -0,0 +1,5 @@ +fn main() { + let mut a = "a"; + a += { "b" }; + //~^ ERROR: binary assignment operation `+=` cannot be applied +} diff --git a/tests/ui/typeck/issue-10401.stderr b/tests/ui/typeck/issue-10401.stderr new file mode 100644 index 000000000..1f68abcfb --- /dev/null +++ b/tests/ui/typeck/issue-10401.stderr @@ -0,0 +1,11 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `&str` + --> $DIR/issue-10401.rs:3:5 + | +LL | a += { "b" }; + | -^^^^^^^^^^^ + | | + | cannot use `+=` on type `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0368`. diff --git a/tests/ui/typeck/issue-104510-ice.rs b/tests/ui/typeck/issue-104510-ice.rs new file mode 100644 index 000000000..157bdf07e --- /dev/null +++ b/tests/ui/typeck/issue-104510-ice.rs @@ -0,0 +1,16 @@ +// needs-asm-support +// only-x86_64 + +struct W(Oops); +//~^ ERROR cannot find type `Oops` in this scope + +unsafe fn test() { + let j = W(()); + let pointer = &j as *const _; + core::arch::asm!( + "nop", + in("eax") pointer, + ); +} + +fn main() {} diff --git a/tests/ui/typeck/issue-104510-ice.stderr b/tests/ui/typeck/issue-104510-ice.stderr new file mode 100644 index 000000000..ddb510ef0 --- /dev/null +++ b/tests/ui/typeck/issue-104510-ice.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Oops` in this scope + --> $DIR/issue-104510-ice.rs:4:21 + | +LL | struct W(Oops); + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/issue-104513-ice.rs b/tests/ui/typeck/issue-104513-ice.rs new file mode 100644 index 000000000..bcac0fa1e --- /dev/null +++ b/tests/ui/typeck/issue-104513-ice.rs @@ -0,0 +1,6 @@ +struct S; +fn f() { + let _: S = S; //~ ERROR cannot find trait `Oops` in this scope + //~^ ERROR `impl Trait` only allowed in function and inherent method return types +} +fn main() {} diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr new file mode 100644 index 000000000..42cfe38ae --- /dev/null +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -0,0 +1,16 @@ +error[E0405]: cannot find trait `Oops` in this scope + --> $DIR/issue-104513-ice.rs:3:19 + | +LL | let _: S = S; + | ^^^^ not found in this scope + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding + --> $DIR/issue-104513-ice.rs:3:14 + | +LL | let _: S = S; + | ^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0405, E0562. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/typeck/issue-104582.rs b/tests/ui/typeck/issue-104582.rs new file mode 100644 index 000000000..104669dad --- /dev/null +++ b/tests/ui/typeck/issue-104582.rs @@ -0,0 +1,5 @@ +fn main(){ + let my_var: String(String?); + //~^ ERROR: invalid `?` in type + //~| ERROR: parenthesized type parameters may only be used with a `Fn` trait +} diff --git a/tests/ui/typeck/issue-104582.stderr b/tests/ui/typeck/issue-104582.stderr new file mode 100644 index 000000000..61b6b2364 --- /dev/null +++ b/tests/ui/typeck/issue-104582.stderr @@ -0,0 +1,25 @@ +error: invalid `?` in type + --> $DIR/issue-104582.rs:2:30 + | +LL | let my_var: String(String?); + | ^ `?` is only allowed on expressions, not types + | +help: if you meant to express that the type might not contain a value, use the `Option` wrapper type + | +LL | let my_var: String(Option); + | +++++++ ~ + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-104582.rs:2:17 + | +LL | let my_var: String(String?); + | ^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | let my_var: String; + | ~ ~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/typeck/issue-105946.rs b/tests/ui/typeck/issue-105946.rs new file mode 100644 index 000000000..bf01751d5 --- /dev/null +++ b/tests/ui/typeck/issue-105946.rs @@ -0,0 +1,12 @@ +fn digit() -> str { + return {}; + //~^ ERROR: mismatched types [E0308] +} +fn main() { + let [_y..] = [box 1, box 2]; + //~^ ERROR: cannot find value `_y` in this scope [E0425] + //~| ERROR: `X..` patterns in slices are experimental [E0658] + //~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658] + //~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658] + //~| ERROR: pattern requires 1 element but array has 2 [E0527] +} diff --git a/tests/ui/typeck/issue-105946.stderr b/tests/ui/typeck/issue-105946.stderr new file mode 100644 index 000000000..d803de4df --- /dev/null +++ b/tests/ui/typeck/issue-105946.stderr @@ -0,0 +1,49 @@ +error[E0425]: cannot find value `_y` in this scope + --> $DIR/issue-105946.rs:6:10 + | +LL | let [_y..] = [box 1, box 2]; + | ^^ not found in this scope + +error[E0658]: `X..` patterns in slices are experimental + --> $DIR/issue-105946.rs:6:10 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable + +error[E0658]: box expression syntax is experimental; you can call `Box::new` instead + --> $DIR/issue-105946.rs:6:19 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^^ + | + = note: see issue #49733 for more information + = help: add `#![feature(box_syntax)]` to the crate attributes to enable + +error[E0658]: box expression syntax is experimental; you can call `Box::new` instead + --> $DIR/issue-105946.rs:6:26 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^^ + | + = note: see issue #49733 for more information + = help: add `#![feature(box_syntax)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-105946.rs:2:10 + | +LL | return {}; + | ^^ expected `str`, found `()` + +error[E0527]: pattern requires 1 element but array has 2 + --> $DIR/issue-105946.rs:6:9 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^^^ expected 2 elements + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0425, E0527, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-10969.rs b/tests/ui/typeck/issue-10969.rs new file mode 100644 index 000000000..0b78fc1bb --- /dev/null +++ b/tests/ui/typeck/issue-10969.rs @@ -0,0 +1,7 @@ +fn func(i: i32) { + i(); //~ERROR expected function, found `i32` +} +fn main() { + let i = 0i32; + i(); //~ERROR expected function, found `i32` +} diff --git a/tests/ui/typeck/issue-10969.stderr b/tests/ui/typeck/issue-10969.stderr new file mode 100644 index 000000000..f64b61aae --- /dev/null +++ b/tests/ui/typeck/issue-10969.stderr @@ -0,0 +1,23 @@ +error[E0618]: expected function, found `i32` + --> $DIR/issue-10969.rs:2:5 + | +LL | fn func(i: i32) { + | - `i` has type `i32` +LL | i(); + | ^-- + | | + | call expression requires function + +error[E0618]: expected function, found `i32` + --> $DIR/issue-10969.rs:6:5 + | +LL | let i = 0i32; + | - `i` has type `i32` +LL | i(); + | ^-- + | | + | call expression requires function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0618`. diff --git a/tests/ui/typeck/issue-13853-2.rs b/tests/ui/typeck/issue-13853-2.rs new file mode 100644 index 000000000..27319c98d --- /dev/null +++ b/tests/ui/typeck/issue-13853-2.rs @@ -0,0 +1,6 @@ +trait FromStructReader<'a> { } +trait ResponseHook { + fn get(&self); +} +fn foo(res : Box) { res.get } //~ ERROR attempted to take value of method +fn main() {} diff --git a/tests/ui/typeck/issue-13853-2.stderr b/tests/ui/typeck/issue-13853-2.stderr new file mode 100644 index 000000000..92068df6c --- /dev/null +++ b/tests/ui/typeck/issue-13853-2.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `get` on type `Box<(dyn ResponseHook + 'static)>` + --> $DIR/issue-13853-2.rs:5:43 + | +LL | fn foo(res : Box) { res.get } + | ^^^ method, not a field + | +help: use parentheses to call the method + | +LL | fn foo(res : Box) { res.get() } + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-13853-5.rs b/tests/ui/typeck/issue-13853-5.rs new file mode 100644 index 000000000..2afdf95aa --- /dev/null +++ b/tests/ui/typeck/issue-13853-5.rs @@ -0,0 +1,13 @@ +trait Deserializer<'a> { } + +trait Deserializable { + fn deserialize_token<'a, D: Deserializer<'a>>(_: D, _: &'a str) -> Self; +} + +impl<'a, T: Deserializable> Deserializable for &'a str { + //~^ ERROR type parameter `T` is not constrained + fn deserialize_token>(_x: D, _y: &'a str) -> &'a str { + } +} + +fn main() {} diff --git a/tests/ui/typeck/issue-13853-5.stderr b/tests/ui/typeck/issue-13853-5.stderr new file mode 100644 index 000000000..3d8f824ec --- /dev/null +++ b/tests/ui/typeck/issue-13853-5.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-13853-5.rs:7:10 + | +LL | impl<'a, T: Deserializable> Deserializable for &'a str { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/typeck/issue-13853.rs b/tests/ui/typeck/issue-13853.rs new file mode 100644 index 000000000..ac9886d2e --- /dev/null +++ b/tests/ui/typeck/issue-13853.rs @@ -0,0 +1,38 @@ +trait Node { + fn zomg(); +} + +trait Graph { + fn nodes<'a, I: Iterator>(&'a self) -> I + where N: 'a; +} + +impl Graph for Vec { + fn nodes<'a, I: Iterator>(&self) -> I + where N: 'a + { + self.iter() //~ ERROR mismatched types + } +} + +struct Stuff; + +impl Node for Stuff { + fn zomg() { + println!("zomg"); + } +} + +fn iterate>(graph: &G) { + for node in graph.iter() { //~ ERROR no method named `iter` found + node.zomg(); + } +} + +pub fn main() { + let graph = Vec::new(); + + graph.push(Stuff); + + iterate(graph); //~ ERROR mismatched types +} diff --git a/tests/ui/typeck/issue-13853.stderr b/tests/ui/typeck/issue-13853.stderr new file mode 100644 index 000000000..876ac2c67 --- /dev/null +++ b/tests/ui/typeck/issue-13853.stderr @@ -0,0 +1,40 @@ +error[E0308]: mismatched types + --> $DIR/issue-13853.rs:14:9 + | +LL | fn nodes<'a, I: Iterator>(&self) -> I + | - this type parameter - expected `I` because of return type +... +LL | self.iter() + | ^^^^^^^^^^^ expected type parameter `I`, found struct `Iter` + | + = note: expected type parameter `I` + found struct `std::slice::Iter<'_, N>` + +error[E0599]: no method named `iter` found for reference `&G` in the current scope + --> $DIR/issue-13853.rs:27:23 + | +LL | for node in graph.iter() { + | ^^^^ method not found in `&G` + +error[E0308]: mismatched types + --> $DIR/issue-13853.rs:37:13 + | +LL | iterate(graph); + | ------- ^^^^^ + | | | + | | expected reference, found struct `Vec` + | | help: consider borrowing here: `&graph` + | arguments to this function are incorrect + | + = note: expected reference `&_` + found struct `Vec` +note: function defined here + --> $DIR/issue-13853.rs:26:4 + | +LL | fn iterate>(graph: &G) { + | ^^^^^^^ --------- + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0599. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-18937-1.rs b/tests/ui/typeck/issue-18937-1.rs new file mode 100644 index 000000000..57e56d832 --- /dev/null +++ b/tests/ui/typeck/issue-18937-1.rs @@ -0,0 +1,21 @@ +// run-pass +// Test that we are able to type-check this example. In particular, +// knowing that `T: 'a` allows us to deduce that `[U]: 'a` (because +// when `T=[U]` it implies that `U: 'a`). +// +// Regr. test for live code we found in the wild when fixing #18937. + +pub trait Leak { + fn leak<'a>(self) -> &'a T where T: 'a; +} + +impl Leak<[U]> for Vec { + fn leak<'a>(mut self) -> &'a [U] where [U]: 'a { + let r: *mut [U] = &mut self[..]; + std::mem::forget(self); + unsafe { &mut *r } + } +} +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/typeck/issue-18937.rs b/tests/ui/typeck/issue-18937.rs new file mode 100644 index 000000000..af85e5b2b --- /dev/null +++ b/tests/ui/typeck/issue-18937.rs @@ -0,0 +1,40 @@ +// Regression test for #18937. + +use std::fmt; + +#[derive(Debug)] +struct MyString<'a>(&'a String); + +struct B { + list: Vec>, +} + +trait A<'a> { + fn foo(&mut self, f: F) + where F: fmt::Debug + 'a, + Self: Sized; +} + +impl<'a> A<'a> for B { + fn foo(&mut self, f: F) + where F: fmt::Debug + 'static, //~ ERROR impl has stricter + { + self.list.push(Box::new(f)); + } +} + +fn main() { + let mut b = B { list: Vec::new() }; + + // Create a borrowed pointer, put it in `b`, then drop what's borrowing it + let a = "hello".to_string(); + b.foo(MyString(&a)); + + // Drop the data which `b` has a reference to + drop(a); + + // Use the data, probably segfaulting + for b in b.list.iter() { + println!("{:?}", b); + } +} diff --git a/tests/ui/typeck/issue-18937.stderr b/tests/ui/typeck/issue-18937.stderr new file mode 100644 index 000000000..5e2ba0ef4 --- /dev/null +++ b/tests/ui/typeck/issue-18937.stderr @@ -0,0 +1,14 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/issue-18937.rs:20:31 + | +LL | / fn foo(&mut self, f: F) +LL | | where F: fmt::Debug + 'a, +LL | | Self: Sized; + | |__________________________- definition of `foo` from trait +... +LL | where F: fmt::Debug + 'static, + | ^^^^^^^ impl has extra requirement `F: 'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/typeck/issue-22375.rs b/tests/ui/typeck/issue-22375.rs new file mode 100644 index 000000000..21a1a4c83 --- /dev/null +++ b/tests/ui/typeck/issue-22375.rs @@ -0,0 +1,4 @@ +// check-pass +trait A> {} + +fn main() {} diff --git a/tests/ui/typeck/issue-29124.rs b/tests/ui/typeck/issue-29124.rs new file mode 100644 index 000000000..dd2784841 --- /dev/null +++ b/tests/ui/typeck/issue-29124.rs @@ -0,0 +1,19 @@ +struct Ret; +struct Obj; + +impl Obj { + fn func() -> Ret { + Ret + } +} + +fn func() -> Ret { + Ret +} + +fn main() { + Obj::func.x(); + //~^ ERROR no method named `x` found + func.x(); + //~^ ERROR no method named `x` found +} diff --git a/tests/ui/typeck/issue-29124.stderr b/tests/ui/typeck/issue-29124.stderr new file mode 100644 index 000000000..a837a7d2d --- /dev/null +++ b/tests/ui/typeck/issue-29124.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `x` found for fn item `fn() -> Ret {Obj::func}` in the current scope + --> $DIR/issue-29124.rs:15:15 + | +LL | Obj::func.x(); + | ^ method not found in `fn() -> Ret {Obj::func}` + +error[E0599]: no method named `x` found for fn item `fn() -> Ret {func}` in the current scope + --> $DIR/issue-29124.rs:17:10 + | +LL | func.x(); + | ^ method not found in `fn() -> Ret {func}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-31173.rs b/tests/ui/typeck/issue-31173.rs new file mode 100644 index 000000000..f678df5b4 --- /dev/null +++ b/tests/ui/typeck/issue-31173.rs @@ -0,0 +1,15 @@ +use std::vec::IntoIter; + +pub fn get_tok(it: &mut IntoIter) { + let mut found_e = false; + + let temp: Vec = it + .take_while(|&x| { + found_e = true; + false + }) + .cloned() //~ ERROR to be an iterator that yields `&_`, but it yields `u8` + .collect(); //~ ERROR the method +} + +fn main() {} diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr new file mode 100644 index 000000000..f3be99f9b --- /dev/null +++ b/tests/ui/typeck/issue-31173.stderr @@ -0,0 +1,45 @@ +error[E0271]: expected `TakeWhile<&mut IntoIter, [closure@issue-31173.rs:7:21]>` to be an iterator that yields `&_`, but it yields `u8` + --> $DIR/issue-31173.rs:11:10 + | +LL | .cloned() + | ^^^^^^ expected reference, found `u8` + | + = note: expected reference `&_` + found type `u8` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-31173.rs:3:20 + | +LL | pub fn get_tok(it: &mut IntoIter) { + | ^^^^^^^^^^^^^^^^^ `Iterator::Item` is `u8` here +... +LL | .take_while(|&x| { + | __________- +LL | | found_e = true; +LL | | false +LL | | }) + | |__________- `Iterator::Item` remains `u8` here +note: required by a bound in `cloned` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0599]: the method `collect` exists for struct `Cloned, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied + --> $DIR/issue-31173.rs:12:10 + | +LL | .collect(); + | ^^^^^^^ method cannot be called due to unsatisfied trait bounds + --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL + | + = note: doesn't satisfy `<_ as Iterator>::Item = &_` + --> $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL + | + = note: doesn't satisfy `_: Iterator` + | + = note: the following trait bounds were not satisfied: + `, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_` + which is required by `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` + `Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` + which is required by `&mut Cloned, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0599. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/typeck/issue-33575.rs b/tests/ui/typeck/issue-33575.rs new file mode 100644 index 000000000..de544afae --- /dev/null +++ b/tests/ui/typeck/issue-33575.rs @@ -0,0 +1,4 @@ +fn main() { + let baz = ().foo(); //~ ERROR no method named `foo` found + ::from_str(&baz); // No complaints about `str` being unsized +} diff --git a/tests/ui/typeck/issue-33575.stderr b/tests/ui/typeck/issue-33575.stderr new file mode 100644 index 000000000..bbd8042d1 --- /dev/null +++ b/tests/ui/typeck/issue-33575.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `foo` found for unit type `()` in the current scope + --> $DIR/issue-33575.rs:2:18 + | +LL | let baz = ().foo(); + | ^^^ method not found in `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-36708.rs b/tests/ui/typeck/issue-36708.rs new file mode 100644 index 000000000..c9d9f2a6d --- /dev/null +++ b/tests/ui/typeck/issue-36708.rs @@ -0,0 +1,12 @@ +// aux-build:issue-36708.rs + +extern crate issue_36708 as lib; + +struct Bar; + +impl lib::Foo for Bar { + fn foo() {} + //~^ ERROR E0049 +} + +fn main() {} diff --git a/tests/ui/typeck/issue-36708.stderr b/tests/ui/typeck/issue-36708.stderr new file mode 100644 index 000000000..140f19f1f --- /dev/null +++ b/tests/ui/typeck/issue-36708.stderr @@ -0,0 +1,9 @@ +error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters + --> $DIR/issue-36708.rs:8:12 + | +LL | fn foo() {} + | ^ found 1 type parameter, expected 0 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0049`. diff --git a/tests/ui/typeck/issue-43189.rs b/tests/ui/typeck/issue-43189.rs new file mode 100644 index 000000000..ce667a500 --- /dev/null +++ b/tests/ui/typeck/issue-43189.rs @@ -0,0 +1,12 @@ +// Issue 46112: An extern crate pub re-exporting libcore was causing +// paths rooted from `std` to be misrendered in the diagnostic output. + +// ignore-windows +// aux-build:xcrate-issue-43189-a.rs +// aux-build:xcrate-issue-43189-b.rs + +extern crate xcrate_issue_43189_b; +fn main() { + ().a(); + //~^ ERROR no method named `a` found +} diff --git a/tests/ui/typeck/issue-43189.stderr b/tests/ui/typeck/issue-43189.stderr new file mode 100644 index 000000000..caf7530b8 --- /dev/null +++ b/tests/ui/typeck/issue-43189.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `a` found for unit type `()` in the current scope + --> $DIR/issue-43189.rs:10:8 + | +LL | ().a(); + | ^ method not found in `()` + | + ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8 + | +LL | fn a(&self) {} + | - the method is available for `()` here + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-46112.rs b/tests/ui/typeck/issue-46112.rs new file mode 100644 index 000000000..0cdd2c27f --- /dev/null +++ b/tests/ui/typeck/issue-46112.rs @@ -0,0 +1,10 @@ +// Issue 46112: An extern crate pub re-exporting libcore was causing +// paths rooted from `std` to be misrendered in the diagnostic output. + +// ignore-windows +// aux-build:xcrate-issue-46112-rexport-core.rs + +extern crate xcrate_issue_46112_rexport_core; +fn test(r: Result, &'static str>) { } +fn main() { test(Ok(())); } +//~^ mismatched types diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr new file mode 100644 index 000000000..8f5ff51fb --- /dev/null +++ b/tests/ui/typeck/issue-46112.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/issue-46112.rs:9:21 + | +LL | fn main() { test(Ok(())); } + | -- ^^ expected enum `Option`, found `()` + | | + | arguments to this enum variant are incorrect + | + = note: expected enum `Option<()>` + found unit type `()` +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-46112.rs:9:18 + | +LL | fn main() { test(Ok(())); } + | ^^^--^ + | | + | this argument influences the type of `Ok` +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL +help: try wrapping the expression in `Some` + | +LL | fn main() { test(Ok(Some(()))); } + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-50687-ice-on-borrow.rs b/tests/ui/typeck/issue-50687-ice-on-borrow.rs new file mode 100644 index 000000000..7a8a12c2a --- /dev/null +++ b/tests/ui/typeck/issue-50687-ice-on-borrow.rs @@ -0,0 +1,41 @@ +// This previously caused an ICE at: +// librustc/traits/structural_impls.rs:180: impossible case reached + +#![no_main] + +use std::borrow::Borrow; +use std::io; +use std::io::Write; + +trait Constraint {} + +struct Container { + t: T, +} + +struct Borrowed; +struct Owned; + +impl<'a, T> Write for &'a Container +where + T: Constraint, + &'a T: Write, +{ + fn write(&mut self, buf: &[u8]) -> io::Result { + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Borrow for Owned { + fn borrow(&self) -> &Borrowed { + &Borrowed + } +} + +fn func(owned: Owned) { + let _: () = Borrow::borrow(&owned); //~ ERROR mismatched types +} diff --git a/tests/ui/typeck/issue-50687-ice-on-borrow.stderr b/tests/ui/typeck/issue-50687-ice-on-borrow.stderr new file mode 100644 index 000000000..e6a0edac4 --- /dev/null +++ b/tests/ui/typeck/issue-50687-ice-on-borrow.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-50687-ice-on-borrow.rs:40:17 + | +LL | let _: () = Borrow::borrow(&owned); + | -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found reference + | | + | expected due to this + | + = note: expected unit type `()` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: () = *Borrow::borrow(&owned); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.rs b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.rs new file mode 100644 index 000000000..7bf151514 --- /dev/null +++ b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.rs @@ -0,0 +1,54 @@ +// Fix issue 52082: Confusing error if accidentally defining a type parameter with the same name as +// an existing type +// +// To this end, make sure that when trying to retrieve a field of a (reference to) type parameter, +// rustc points to the point where the parameter was defined. +#[derive(Debug)] +struct Point +{ + x: i32, + y: i32 +} + +impl Point +{ + fn add(a: &Point, b: &Point) -> Point + { + Point {x: a.x + b.x, y: a.y + b.y} + } +} + +trait Eq +{ + fn equals_ref(a: &T, b: &T) -> bool; + fn equals_val(a: T, b: T) -> bool; +} + +impl Eq for Point +{ + fn equals_ref(a: &Point, b: &Point) -> bool + { + a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `&Point` [E0609] + //~|ERROR no field `x` on type `&Point` [E0609] + //~|ERROR no field `y` on type `&Point` [E0609] + //~|ERROR no field `y` on type `&Point` [E0609] + } + + fn equals_val(a: Point, b: Point) -> bool + { + a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `Point` [E0609] + //~|ERROR no field `x` on type `Point` [E0609] + //~|ERROR no field `y` on type `Point` [E0609] + //~|ERROR no field `y` on type `Point` [E0609] + } +} + +fn main() +{ + let p1 = Point {x: 0, y: 10}; + let p2 = Point {x: 20, y: 42}; + println!("{:?}", Point::add(&p1, &p2)); + println!("p1: {:?}, p2: {:?}", p1, p2); + println!("&p1 == &p2: {:?}", Point::equals_ref(&p1, &p2)); + println!("p1 == p2: {:?}", Point::equals_val(p1, p2)); +} diff --git a/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr new file mode 100644 index 000000000..4be4c91df --- /dev/null +++ b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr @@ -0,0 +1,75 @@ +error[E0609]: no field `x` on type `&Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:11 + | +LL | fn equals_ref(a: &Point, b: &Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `x` on type `&Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:18 + | +LL | fn equals_ref(a: &Point, b: &Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `y` on type `&Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:25 + | +LL | fn equals_ref(a: &Point, b: &Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `y` on type `&Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:32 + | +LL | fn equals_ref(a: &Point, b: &Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `x` on type `Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:11 + | +LL | fn equals_val(a: Point, b: Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `x` on type `Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:18 + | +LL | fn equals_val(a: Point, b: Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `y` on type `Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:25 + | +LL | fn equals_val(a: Point, b: Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error[E0609]: no field `y` on type `Point` + --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:32 + | +LL | fn equals_val(a: Point, b: Point) -> bool + | ----- type parameter 'Point' declared here +LL | { +LL | a.x == b.x && a.y == b.y + | ^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/tests/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs new file mode 100644 index 000000000..23ea0ad61 --- /dev/null +++ b/tests/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs @@ -0,0 +1,23 @@ +// check-pass + +// rust-lang/rust#55810: types for a binding in a match arm can be +// inferred from arms that come later in the match. + +struct S; + +impl S { + fn method(&self) -> bool { + unimplemented!() + } +} + +fn get() -> T { + unimplemented!() +} + +fn main() { + match get() { + x if x.method() => {} + &S => {} + } +} diff --git a/tests/ui/typeck/issue-57404.rs b/tests/ui/typeck/issue-57404.rs new file mode 100644 index 000000000..ecabca66a --- /dev/null +++ b/tests/ui/typeck/issue-57404.rs @@ -0,0 +1,7 @@ +#![feature(unboxed_closures)] +#![feature(fn_traits)] + +fn main() { + let handlers: Option FnMut<&'a mut (), Output=()>>> = None; + handlers.unwrap().as_mut().call_mut(&mut ()); //~ ERROR: `&mut ()` is not a tuple +} diff --git a/tests/ui/typeck/issue-57404.stderr b/tests/ui/typeck/issue-57404.stderr new file mode 100644 index 000000000..a631dbb39 --- /dev/null +++ b/tests/ui/typeck/issue-57404.stderr @@ -0,0 +1,19 @@ +error[E0277]: `&mut ()` is not a tuple + --> $DIR/issue-57404.rs:6:41 + | +LL | handlers.unwrap().as_mut().call_mut(&mut ()); + | -------- ^^^^^^^ the trait `Tuple` is not implemented for `&mut ()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `call_mut` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL +help: consider removing the leading `&`-reference + | +LL - handlers.unwrap().as_mut().call_mut(&mut ()); +LL + handlers.unwrap().as_mut().call_mut(()); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs new file mode 100644 index 000000000..0a4e7da2b --- /dev/null +++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs @@ -0,0 +1,7 @@ +//extern crate has_assoc_type; + +//fn ice(x: Box>) { +fn ice(x: Box>) { + *x //~ ERROR mismatched types [E0308] +} +fn main() {} diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr new file mode 100644 index 000000000..b92a6f2ec --- /dev/null +++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-57673-ice-on-deref-of-boxed-trait.rs:5:5 + | +LL | fn ice(x: Box>) { + | - help: try adding a return type: `-> (dyn Iterator + 'static)` +LL | *x + | ^^ expected `()`, found trait object `dyn Iterator` + | + = note: expected unit type `()` + found trait object `(dyn Iterator + 'static)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs b/tests/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs new file mode 100644 index 000000000..de7d6a0d8 --- /dev/null +++ b/tests/ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs @@ -0,0 +1,11 @@ +// Issue 61711: A crate pub re-exporting `crate` was causing an +// infinite loop. + +// edition:2018 +// aux-build:xcrate-issue-61711-b.rs +// compile-flags:--extern xcrate_issue_61711_b + +// build-pass + +fn f(_: F) { } +fn main() { } diff --git a/tests/ui/typeck/issue-65611.rs b/tests/ui/typeck/issue-65611.rs new file mode 100644 index 000000000..764531149 --- /dev/null +++ b/tests/ui/typeck/issue-65611.rs @@ -0,0 +1,63 @@ +use std::mem::MaybeUninit; +use std::ops::Deref; + +pub unsafe trait Array { + /// The array’s element type + type Item; + #[doc(hidden)] + /// The smallest index type that indexes the array. + type Index: Index; + #[doc(hidden)] + fn as_ptr(&self) -> *const Self::Item; + #[doc(hidden)] + fn as_mut_ptr(&mut self) -> *mut Self::Item; + #[doc(hidden)] + fn capacity() -> usize; +} + +pub trait Index : PartialEq + Copy { + fn to_usize(self) -> usize; + fn from(i: usize) -> Self; +} + +impl Index for usize { + fn to_usize(self) -> usize { self } + fn from(val: usize) -> Self { + val + } +} + +unsafe impl Array for [T; 1] { + type Item = T; + type Index = usize; + fn as_ptr(&self) -> *const T { self as *const _ as *const _ } + fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _} + fn capacity() -> usize { 1 } +} + +impl Deref for ArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + panic!() + } +} + +pub struct ArrayVec { + xs: MaybeUninit, + len: usize, +} + +impl ArrayVec { + pub fn new() -> ArrayVec { + panic!() + } +} + +fn main() { + let mut buffer = ArrayVec::new(); + let x = buffer.last().unwrap().0.clone(); + //~^ ERROR type annotations needed + //~| ERROR no field `0` on type `&_` + buffer.reverse(); +} diff --git a/tests/ui/typeck/issue-65611.stderr b/tests/ui/typeck/issue-65611.stderr new file mode 100644 index 000000000..003c63079 --- /dev/null +++ b/tests/ui/typeck/issue-65611.stderr @@ -0,0 +1,16 @@ +error[E0282]: type annotations needed + --> $DIR/issue-65611.rs:59:13 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + +error[E0609]: no field `0` on type `&_` + --> $DIR/issue-65611.rs:59:36 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/typeck/issue-67971.rs b/tests/ui/typeck/issue-67971.rs new file mode 100644 index 000000000..8bf725cb5 --- /dev/null +++ b/tests/ui/typeck/issue-67971.rs @@ -0,0 +1,9 @@ +struct S {} + +fn foo(ctx: &mut S) -> String { //~ ERROR mismatched types + // Don't suggest to remove semicolon as it won't fix anything + ctx.sleep = 0; + //~^ ERROR no field `sleep` on type `&mut S` +} + +fn main() {} diff --git a/tests/ui/typeck/issue-67971.stderr b/tests/ui/typeck/issue-67971.stderr new file mode 100644 index 000000000..5d07f9cc7 --- /dev/null +++ b/tests/ui/typeck/issue-67971.stderr @@ -0,0 +1,18 @@ +error[E0609]: no field `sleep` on type `&mut S` + --> $DIR/issue-67971.rs:5:9 + | +LL | ctx.sleep = 0; + | ^^^^^ unknown field + +error[E0308]: mismatched types + --> $DIR/issue-67971.rs:3:24 + | +LL | fn foo(ctx: &mut S) -> String { + | --- ^^^^^^ expected struct `String`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0609. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-68590-reborrow-through-derefmut.rs b/tests/ui/typeck/issue-68590-reborrow-through-derefmut.rs new file mode 100644 index 000000000..e4436260e --- /dev/null +++ b/tests/ui/typeck/issue-68590-reborrow-through-derefmut.rs @@ -0,0 +1,25 @@ +// check-pass + +// rust-lang/rust#68590: confusing diagnostics when reborrowing through DerefMut. + +use std::cell::RefCell; + +struct A; + +struct S<'a> { + a: &'a mut A, +} + +fn take_a(_: &mut A) {} + +fn test<'a>(s: &RefCell>) { + let mut guard = s.borrow_mut(); + take_a(guard.a); + let _s2 = S { a: guard.a }; +} + +fn main() { + let a = &mut A; + let s = RefCell::new(S { a }); + test(&s); +} diff --git a/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.rs b/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.rs new file mode 100644 index 000000000..571692a53 --- /dev/null +++ b/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.rs @@ -0,0 +1,9 @@ +// Regression test for #69378: no type for node after struct parse recovery + +struct Foo { 0: u8 } //~ ERROR expected identifier + +fn test(f: Foo) { + Foo{foo: 4, ..f}; +} + +fn main() {} diff --git a/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr b/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr new file mode 100644 index 000000000..fc7c23a22 --- /dev/null +++ b/tests/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr @@ -0,0 +1,10 @@ +error: expected identifier, found `0` + --> $DIR/issue-69378-ice-on-invalid-type-node-after-recovery.rs:3:14 + | +LL | struct Foo { 0: u8 } + | --- ^ expected identifier + | | + | while parsing this struct + +error: aborting due to previous error + diff --git a/tests/ui/typeck/issue-72225-call-fnmut-through-derefmut.rs b/tests/ui/typeck/issue-72225-call-fnmut-through-derefmut.rs new file mode 100644 index 000000000..3ea05389f --- /dev/null +++ b/tests/ui/typeck/issue-72225-call-fnmut-through-derefmut.rs @@ -0,0 +1,21 @@ +// check-pass + +// rust-lang/rust#72225: confusing diagnostics when calling FnMut through DerefMut. + +use std::cell::RefCell; + +struct S { + f: Box +} + +fn test(s: &RefCell) { + let mut guard = s.borrow_mut(); + (guard.f)(); +} + +fn main() { + let s = RefCell::new(S { + f: Box::new(|| ()) + }); + test(&s); +} diff --git a/tests/ui/typeck/issue-73592-borrow_mut-through-deref.fixed b/tests/ui/typeck/issue-73592-borrow_mut-through-deref.fixed new file mode 100644 index 000000000..7fdd618c2 --- /dev/null +++ b/tests/ui/typeck/issue-73592-borrow_mut-through-deref.fixed @@ -0,0 +1,59 @@ +// check-pass +// run-rustfix +// +// rust-lang/rust#73592: borrow_mut through Deref should work. +// +// Before #72280, when we see something like `&mut *rcvr.method()`, we +// incorrectly requires `rcvr` to be type-checked as a mut place. While this +// requirement is usually correct for smart pointers, it is overly restrictive +// for types like `Mutex` or `RefCell` which can produce a guard that +// implements `DerefMut` from `&self`. +// +// Making it more confusing, because we use Deref as the fallback when DerefMut +// is implemented, we won't see an issue when the smart pointer does not +// implement `DerefMut`. It only causes an issue when `rcvr` is obtained via a +// type that implements both `Deref` or `DerefMut`. +// +// This bug is only discovered in #73592 after it is already fixed as a side-effect +// of a refactoring made in #72280. + +#![warn(unused_mut)] + +use std::pin::Pin; +use std::cell::RefCell; + +struct S(RefCell<()>); + +fn test_pin(s: Pin<&S>) { + // This works before #72280. + let _ = &mut *s.0.borrow_mut(); +} + +fn test_pin_mut(s: Pin<&mut S>) { + // This should compile but didn't before #72280. + let _ = &mut *s.0.borrow_mut(); +} + +fn test_vec(s: &Vec>) { + // This should compile but didn't before #72280. + let _ = &mut *s[0].borrow_mut(); +} + +fn test_mut_pin(s: Pin<&S>) { + //~^ WARN variable does not need to be mutable + let _ = &mut *s.0.borrow_mut(); +} + +fn test_mut_pin_mut(s: Pin<&mut S>) { + //~^ WARN variable does not need to be mutable + let _ = &mut *s.0.borrow_mut(); +} + +fn main() { + let mut s = S(RefCell::new(())); + test_pin(Pin::new(&s)); + test_pin_mut(Pin::new(&mut s)); + test_mut_pin(Pin::new(&s)); + test_mut_pin_mut(Pin::new(&mut s)); + test_vec(&vec![s.0]); +} diff --git a/tests/ui/typeck/issue-73592-borrow_mut-through-deref.rs b/tests/ui/typeck/issue-73592-borrow_mut-through-deref.rs new file mode 100644 index 000000000..3b399e629 --- /dev/null +++ b/tests/ui/typeck/issue-73592-borrow_mut-through-deref.rs @@ -0,0 +1,59 @@ +// check-pass +// run-rustfix +// +// rust-lang/rust#73592: borrow_mut through Deref should work. +// +// Before #72280, when we see something like `&mut *rcvr.method()`, we +// incorrectly requires `rcvr` to be type-checked as a mut place. While this +// requirement is usually correct for smart pointers, it is overly restrictive +// for types like `Mutex` or `RefCell` which can produce a guard that +// implements `DerefMut` from `&self`. +// +// Making it more confusing, because we use Deref as the fallback when DerefMut +// is implemented, we won't see an issue when the smart pointer does not +// implement `DerefMut`. It only causes an issue when `rcvr` is obtained via a +// type that implements both `Deref` or `DerefMut`. +// +// This bug is only discovered in #73592 after it is already fixed as a side-effect +// of a refactoring made in #72280. + +#![warn(unused_mut)] + +use std::pin::Pin; +use std::cell::RefCell; + +struct S(RefCell<()>); + +fn test_pin(s: Pin<&S>) { + // This works before #72280. + let _ = &mut *s.0.borrow_mut(); +} + +fn test_pin_mut(s: Pin<&mut S>) { + // This should compile but didn't before #72280. + let _ = &mut *s.0.borrow_mut(); +} + +fn test_vec(s: &Vec>) { + // This should compile but didn't before #72280. + let _ = &mut *s[0].borrow_mut(); +} + +fn test_mut_pin(mut s: Pin<&S>) { + //~^ WARN variable does not need to be mutable + let _ = &mut *s.0.borrow_mut(); +} + +fn test_mut_pin_mut(mut s: Pin<&mut S>) { + //~^ WARN variable does not need to be mutable + let _ = &mut *s.0.borrow_mut(); +} + +fn main() { + let mut s = S(RefCell::new(())); + test_pin(Pin::new(&s)); + test_pin_mut(Pin::new(&mut s)); + test_mut_pin(Pin::new(&s)); + test_mut_pin_mut(Pin::new(&mut s)); + test_vec(&vec![s.0]); +} diff --git a/tests/ui/typeck/issue-73592-borrow_mut-through-deref.stderr b/tests/ui/typeck/issue-73592-borrow_mut-through-deref.stderr new file mode 100644 index 000000000..5f5f672c3 --- /dev/null +++ b/tests/ui/typeck/issue-73592-borrow_mut-through-deref.stderr @@ -0,0 +1,24 @@ +warning: variable does not need to be mutable + --> $DIR/issue-73592-borrow_mut-through-deref.rs:42:17 + | +LL | fn test_mut_pin(mut s: Pin<&S>) { + | ----^ + | | + | help: remove this `mut` + | +note: the lint level is defined here + --> $DIR/issue-73592-borrow_mut-through-deref.rs:20:9 + | +LL | #![warn(unused_mut)] + | ^^^^^^^^^^ + +warning: variable does not need to be mutable + --> $DIR/issue-73592-borrow_mut-through-deref.rs:47:21 + | +LL | fn test_mut_pin_mut(mut s: Pin<&mut S>) { + | ----^ + | | + | help: remove this `mut` + +warning: 2 warnings emitted + diff --git a/tests/ui/typeck/issue-74086.rs b/tests/ui/typeck/issue-74086.rs new file mode 100644 index 000000000..9b7c0d7cc --- /dev/null +++ b/tests/ui/typeck/issue-74086.rs @@ -0,0 +1,5 @@ +fn main() { + static BUG: fn(_) -> u8 = |_| 8; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR the placeholder `_` is not allowed within types on item signatures for static items +} diff --git a/tests/ui/typeck/issue-74086.stderr b/tests/ui/typeck/issue-74086.stderr new file mode 100644 index 000000000..95ebf9a90 --- /dev/null +++ b/tests/ui/typeck/issue-74086.stderr @@ -0,0 +1,15 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-74086.rs:2:20 + | +LL | static BUG: fn(_) -> u8 = |_| 8; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items + --> $DIR/issue-74086.rs:2:20 + | +LL | static BUG: fn(_) -> u8 = |_| 8; + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-74933.rs b/tests/ui/typeck/issue-74933.rs new file mode 100644 index 000000000..4b6c173b8 --- /dev/null +++ b/tests/ui/typeck/issue-74933.rs @@ -0,0 +1,38 @@ +// check-pass +// +// rust-lang/rust#74933: Lifetime error when indexing with borrowed index + +use std::ops::{Index, IndexMut}; + +struct S(V); +struct K<'a>(&'a ()); +struct V; + +impl<'a> Index<&'a K<'a>> for S { + type Output = V; + + fn index(&self, _: &'a K<'a>) -> &V { + &self.0 + } +} + +impl<'a> IndexMut<&'a K<'a>> for S { + fn index_mut(&mut self, _: &'a K<'a>) -> &mut V { + &mut self.0 + } +} + +impl V { + fn foo(&mut self) {} +} + +fn test(s: &mut S, k: &K<'_>) { + s[k] = V; + s[k].foo(); +} + +fn main() { + let mut s = S(V); + let k = K(&()); + test(&mut s, &k); +} diff --git a/tests/ui/typeck/issue-75883.rs b/tests/ui/typeck/issue-75883.rs new file mode 100644 index 000000000..885acc482 --- /dev/null +++ b/tests/ui/typeck/issue-75883.rs @@ -0,0 +1,22 @@ +// Regression test for #75883. + +pub struct UI {} + +impl UI { + pub fn run() -> Result<_> { + //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types + let mut ui = UI {}; + ui.interact(); + + unimplemented!(); + } + + pub fn interact(&mut self) -> Result<_> { + //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types + unimplemented!(); + } +} + +fn main() {} diff --git a/tests/ui/typeck/issue-75883.stderr b/tests/ui/typeck/issue-75883.stderr new file mode 100644 index 000000000..f5adcabe3 --- /dev/null +++ b/tests/ui/typeck/issue-75883.stderr @@ -0,0 +1,42 @@ +error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/issue-75883.rs:6:21 + | +LL | pub fn run() -> Result<_> { + | ^^^^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +help: add missing generic argument + | +LL | pub fn run() -> Result<_, E> { + | +++ + +error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/issue-75883.rs:15:35 + | +LL | pub fn interact(&mut self) -> Result<_> { + | ^^^^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +help: add missing generic argument + | +LL | pub fn interact(&mut self) -> Result<_, E> { + | +++ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-75883.rs:15:42 + | +LL | pub fn interact(&mut self) -> Result<_> { + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-75883.rs:6:28 + | +LL | pub fn run() -> Result<_> { + | ^ not allowed in type signatures + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0121. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/issue-75889.rs b/tests/ui/typeck/issue-75889.rs new file mode 100644 index 000000000..84c067ed0 --- /dev/null +++ b/tests/ui/typeck/issue-75889.rs @@ -0,0 +1,6 @@ +// Regression test for #75889. + +const FOO: dyn Fn() -> _ = ""; //~ ERROR E0121 +static BOO: dyn Fn() -> _ = ""; //~ ERROR E0121 + +fn main() {} diff --git a/tests/ui/typeck/issue-75889.stderr b/tests/ui/typeck/issue-75889.stderr new file mode 100644 index 000000000..1438f481e --- /dev/null +++ b/tests/ui/typeck/issue-75889.stderr @@ -0,0 +1,15 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items + --> $DIR/issue-75889.rs:3:24 + | +LL | const FOO: dyn Fn() -> _ = ""; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items + --> $DIR/issue-75889.rs:4:25 + | +LL | static BOO: dyn Fn() -> _ = ""; + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-79040.rs b/tests/ui/typeck/issue-79040.rs new file mode 100644 index 000000000..941612542 --- /dev/null +++ b/tests/ui/typeck/issue-79040.rs @@ -0,0 +1,5 @@ +fn main() { + const FOO = "hello" + 1; //~ ERROR cannot add `{integer}` to `&str` + //~^ missing type for `const` item + println!("{}", FOO); +} diff --git a/tests/ui/typeck/issue-79040.stderr b/tests/ui/typeck/issue-79040.stderr new file mode 100644 index 000000000..c820d1e08 --- /dev/null +++ b/tests/ui/typeck/issue-79040.stderr @@ -0,0 +1,17 @@ +error[E0369]: cannot add `{integer}` to `&str` + --> $DIR/issue-79040.rs:2:25 + | +LL | const FOO = "hello" + 1; + | ------- ^ - {integer} + | | + | &str + +error: missing type for `const` item + --> $DIR/issue-79040.rs:2:14 + | +LL | const FOO = "hello" + 1; + | ^ help: provide a type for the item: `: ` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/typeck/issue-80207-unsized-return.rs b/tests/ui/typeck/issue-80207-unsized-return.rs new file mode 100644 index 000000000..75430da14 --- /dev/null +++ b/tests/ui/typeck/issue-80207-unsized-return.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Foo { + fn do_stuff() -> Self; +} + +trait Bar { + type Output; +} + +impl Foo for dyn Bar +where + Self: Sized, +{ + fn do_stuff() -> Self { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/typeck/issue-80779.rs b/tests/ui/typeck/issue-80779.rs new file mode 100644 index 000000000..1624f6b77 --- /dev/null +++ b/tests/ui/typeck/issue-80779.rs @@ -0,0 +1,13 @@ +// Regression test for #80779. + +pub struct T<'a>(&'a str); + +pub fn f<'a>(val: T<'a>) -> _ { + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types + g(val) +} + +pub fn g(_: T<'static>) -> _ {} +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types + +fn main() {} diff --git a/tests/ui/typeck/issue-80779.stderr b/tests/ui/typeck/issue-80779.stderr new file mode 100644 index 000000000..2261ba616 --- /dev/null +++ b/tests/ui/typeck/issue-80779.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-80779.rs:10:28 + | +LL | pub fn g(_: T<'static>) -> _ {} + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `()` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-80779.rs:5:29 + | +LL | pub fn f<'a>(val: T<'a>) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-81293.rs b/tests/ui/typeck/issue-81293.rs new file mode 100644 index 000000000..076b8c944 --- /dev/null +++ b/tests/ui/typeck/issue-81293.rs @@ -0,0 +1,9 @@ +fn main() { + let a: u16; + let b: u16 = 42; + let c: usize = 5; + + a = c + b * 5; //~ ERROR: mismatched types [E0308] + //~| ERROR: mismatched types [E0308] + //~| ERROR: cannot add `u16` to `usize` [E0277] +} diff --git a/tests/ui/typeck/issue-81293.stderr b/tests/ui/typeck/issue-81293.stderr new file mode 100644 index 000000000..6976be711 --- /dev/null +++ b/tests/ui/typeck/issue-81293.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/issue-81293.rs:6:13 + | +LL | a = c + b * 5; + | ^^^^^ expected `usize`, found `u16` + +error[E0308]: mismatched types + --> $DIR/issue-81293.rs:6:9 + | +LL | let a: u16; + | --- expected due to this type +... +LL | a = c + b * 5; + | ^^^^^^^^^ expected `u16`, found `usize` + +error[E0277]: cannot add `u16` to `usize` + --> $DIR/issue-81293.rs:6:11 + | +LL | a = c + b * 5; + | ^ no implementation for `usize + u16` + | + = help: the trait `Add` is not implemented for `usize` + = help: the following other types implement trait `Add`: + <&'a usize as Add> + <&usize as Add<&usize>> + > + + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-81885.rs b/tests/ui/typeck/issue-81885.rs new file mode 100644 index 000000000..fb3949478 --- /dev/null +++ b/tests/ui/typeck/issue-81885.rs @@ -0,0 +1,9 @@ +const TEST4: fn() -> _ = 42; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + //~| ERROR the placeholder `_` is not allowed within types on item signatures for constant items + +fn main() { + const TEST5: fn() -> _ = 42; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + //~| ERROR the placeholder `_` is not allowed within types on item signatures for constant items +} diff --git a/tests/ui/typeck/issue-81885.stderr b/tests/ui/typeck/issue-81885.stderr new file mode 100644 index 000000000..91c08bd82 --- /dev/null +++ b/tests/ui/typeck/issue-81885.stderr @@ -0,0 +1,27 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-81885.rs:1:22 + | +LL | const TEST4: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items + --> $DIR/issue-81885.rs:1:22 + | +LL | const TEST4: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-81885.rs:6:26 + | +LL | const TEST5: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items + --> $DIR/issue-81885.rs:6:26 + | +LL | const TEST5: fn() -> _ = 42; + | ^ not allowed in type signatures + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-81943.rs b/tests/ui/typeck/issue-81943.rs new file mode 100644 index 000000000..18f5970a3 --- /dev/null +++ b/tests/ui/typeck/issue-81943.rs @@ -0,0 +1,13 @@ +// aux-build:issue-81943-lib.rs +extern crate issue_81943_lib as lib; + +fn f(f: F) { f(0); } +fn g(t: i32) -> i32 { t } +fn main() { + f(|x| lib::d!(x)); //~ERROR + f(|x| match x { tmp => { g(tmp) } }); //~ERROR + macro_rules! d { + ($e:expr) => { match $e { x => { g(x) } } } //~ERROR + } + f(|x| d!(x)); +} diff --git a/tests/ui/typeck/issue-81943.stderr b/tests/ui/typeck/issue-81943.stderr new file mode 100644 index 000000000..041ff1075 --- /dev/null +++ b/tests/ui/typeck/issue-81943.stderr @@ -0,0 +1,51 @@ +error[E0308]: mismatched types + --> $DIR/issue-81943.rs:7:9 + | +LL | f(|x| lib::d!(x)); + | ^^^^^^^^^^ expected `()`, found `i32` + | + = note: this error originates in the macro `lib::d` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/issue-81943.rs:8:28 + | +LL | f(|x| match x { tmp => { g(tmp) } }); + | -------------------^^^^^^---- + | | | + | | expected `()`, found `i32` + | expected this to be `()` + | +help: consider using a semicolon here + | +LL | f(|x| match x { tmp => { g(tmp); } }); + | + +help: consider using a semicolon here + | +LL | f(|x| match x { tmp => { g(tmp) } };); + | + + +error[E0308]: mismatched types + --> $DIR/issue-81943.rs:10:38 + | +LL | ($e:expr) => { match $e { x => { g(x) } } } + | ------------------^^^^---- + | | | + | | expected `()`, found `i32` + | expected this to be `()` +LL | } +LL | f(|x| d!(x)); + | ----- in this macro invocation + | + = note: this error originates in the macro `d` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider using a semicolon here + | +LL | ($e:expr) => { match $e { x => { g(x); } } } + | + +help: consider using a semicolon here + | +LL | ($e:expr) => { match $e { x => { g(x) } }; } + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-82772.rs b/tests/ui/typeck/issue-82772.rs new file mode 100644 index 000000000..326273bfe --- /dev/null +++ b/tests/ui/typeck/issue-82772.rs @@ -0,0 +1,13 @@ +// edition:2018 + +fn main() { + use a::ModPrivateStruct; + let Box { 0: _, .. }: Box<()>; //~ ERROR field `0` of + let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of + let ModPrivateStruct { 1: _, .. } = ModPrivateStruct::default(); //~ ERROR field `1` of +} + +mod a { + #[derive(Default)] + pub struct ModPrivateStruct(u8, u8); +} diff --git a/tests/ui/typeck/issue-82772.stderr b/tests/ui/typeck/issue-82772.stderr new file mode 100644 index 000000000..321143cb9 --- /dev/null +++ b/tests/ui/typeck/issue-82772.stderr @@ -0,0 +1,21 @@ +error[E0451]: field `0` of struct `Box` is private + --> $DIR/issue-82772.rs:5:15 + | +LL | let Box { 0: _, .. }: Box<()>; + | ^^^^ private field + +error[E0451]: field `1` of struct `Box` is private + --> $DIR/issue-82772.rs:6:15 + | +LL | let Box { 1: _, .. }: Box<()>; + | ^^^^ private field + +error[E0451]: field `1` of struct `ModPrivateStruct` is private + --> $DIR/issue-82772.rs:7:28 + | +LL | let ModPrivateStruct { 1: _, .. } = ModPrivateStruct::default(); + | ^^^^ private field + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/typeck/issue-83621-placeholder-static-in-extern.rs b/tests/ui/typeck/issue-83621-placeholder-static-in-extern.rs new file mode 100644 index 000000000..16ec2a546 --- /dev/null +++ b/tests/ui/typeck/issue-83621-placeholder-static-in-extern.rs @@ -0,0 +1,7 @@ +// Regression test for #83621. + +extern "C" { + static x: _; //~ ERROR: [E0121] +} + +fn main() {} diff --git a/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr b/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr new file mode 100644 index 000000000..9376e8bcf --- /dev/null +++ b/tests/ui/typeck/issue-83621-placeholder-static-in-extern.stderr @@ -0,0 +1,9 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/issue-83621-placeholder-static-in-extern.rs:4:15 + | +LL | static x: _; + | ^ not allowed in type signatures + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-83693.rs b/tests/ui/typeck/issue-83693.rs new file mode 100644 index 000000000..a42558220 --- /dev/null +++ b/tests/ui/typeck/issue-83693.rs @@ -0,0 +1,19 @@ +// Regression test for the ICE described in #83693. + +#![feature(fn_traits)] +#![crate_type="lib"] + +impl F { +//~^ ERROR: cannot find type `F` in this scope [E0412] + fn call() { + ::call + //~^ ERROR: cannot find type `TestResult` in this scope [E0412] + //~| associated type bindings are not allowed here [E0229] + } +} + +fn call() { + ::call + //~^ ERROR: cannot find type `x` in this scope [E0412] + //~| ERROR: associated type bindings are not allowed here [E0229] +} diff --git a/tests/ui/typeck/issue-83693.stderr b/tests/ui/typeck/issue-83693.stderr new file mode 100644 index 000000000..ce4f73b82 --- /dev/null +++ b/tests/ui/typeck/issue-83693.stderr @@ -0,0 +1,37 @@ +error[E0412]: cannot find type `F` in this scope + --> $DIR/issue-83693.rs:6:6 + | +LL | impl F { + | ^ help: a trait with a similar name exists: `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | + = note: similarly named trait `Fn` defined here + +error[E0412]: cannot find type `TestResult` in this scope + --> $DIR/issue-83693.rs:9:22 + | +LL | ::call + | ^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `x` in this scope + --> $DIR/issue-83693.rs:16:6 + | +LL | ::call + | ^ not found in this scope + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-83693.rs:9:18 + | +LL | ::call + | ^^^^^^^^^^^^^^^ associated type not allowed here + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-83693.rs:16:11 + | +LL | ::call + | ^^^^^^^^^^ associated type not allowed here + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0229, E0412. +For more information about an error, try `rustc --explain E0229`. diff --git a/tests/ui/typeck/issue-84160.rs b/tests/ui/typeck/issue-84160.rs new file mode 100644 index 000000000..7b444df85 --- /dev/null +++ b/tests/ui/typeck/issue-84160.rs @@ -0,0 +1,9 @@ +fn mismatched_types_with_reference(x: &u32) -> &u32 { + if false { + return x; + } + return "test"; + //~^ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/typeck/issue-84160.stderr b/tests/ui/typeck/issue-84160.stderr new file mode 100644 index 000000000..24c188b3f --- /dev/null +++ b/tests/ui/typeck/issue-84160.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-84160.rs:5:12 + | +LL | fn mismatched_types_with_reference(x: &u32) -> &u32 { + | ---- expected `&u32` because of return type +... +LL | return "test"; + | ^^^^^^ expected `u32`, found `str` + | + = note: expected reference `&u32` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-84768.rs b/tests/ui/typeck/issue-84768.rs new file mode 100644 index 000000000..ffa92823b --- /dev/null +++ b/tests/ui/typeck/issue-84768.rs @@ -0,0 +1,10 @@ +// Regression test for the ICE described in #84768. + +#![feature(fn_traits)] +#![crate_type="lib"] + +fn transform_mut(f: F) where F: for<'b> FnOnce(&'b mut u8) { + ::call_once(f, 1) + //~^ ERROR: associated type bindings are not allowed here [E0229] + //~| ERROR: mismatched types [E0308] +} diff --git a/tests/ui/typeck/issue-84768.stderr b/tests/ui/typeck/issue-84768.stderr new file mode 100644 index 000000000..09f3aee2d --- /dev/null +++ b/tests/ui/typeck/issue-84768.stderr @@ -0,0 +1,30 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-84768.rs:7:11 + | +LL | ::call_once(f, 1) + | ^^^^^^^^^^^^^^^ associated type not allowed here + +error[E0308]: mismatched types + --> $DIR/issue-84768.rs:7:42 + | +LL | ::call_once(f, 1) + | --------------------------------- ^ expected tuple, found integer + | | + | arguments to this function are incorrect + | + = note: expected tuple `(&mut u8,)` + found type `{integer}` +help: the return type of this call is `{integer}` due to the type of the argument passed + --> $DIR/issue-84768.rs:7:5 + | +LL | ::call_once(f, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | this argument influences the return type of `FnOnce` +note: associated function defined here + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0229, E0308. +For more information about an error, try `rustc --explain E0229`. diff --git a/tests/ui/typeck/issue-84831.rs b/tests/ui/typeck/issue-84831.rs new file mode 100644 index 000000000..c646f7107 --- /dev/null +++ b/tests/ui/typeck/issue-84831.rs @@ -0,0 +1,9 @@ +fn f() { + std::<0>; //~ ERROR expected value +} +fn j() { + std::<_ as _>; //~ ERROR expected value + //~^ ERROR expected one of `,` or `>`, found keyword `as` +} + +fn main () {} diff --git a/tests/ui/typeck/issue-84831.stderr b/tests/ui/typeck/issue-84831.stderr new file mode 100644 index 000000000..461ccb142 --- /dev/null +++ b/tests/ui/typeck/issue-84831.stderr @@ -0,0 +1,26 @@ +error: expected one of `,` or `>`, found keyword `as` + --> $DIR/issue-84831.rs:5:13 + | +LL | std::<_ as _>; + | ^^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | std::<{ _ as _ }>; + | + + + +error[E0423]: expected value, found crate `std` + --> $DIR/issue-84831.rs:2:5 + | +LL | std::<0>; + | ^^^^^^^^ not a value + +error[E0423]: expected value, found crate `std` + --> $DIR/issue-84831.rs:5:5 + | +LL | std::<_ as _>; + | ^^^^^^^^^^^^^ not a value + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr b/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr new file mode 100644 index 000000000..b1111fcf1 --- /dev/null +++ b/tests/ui/typeck/issue-86721-return-expr-ice.rev1.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:9:22 + | +LL | const U: usize = return; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr b/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr new file mode 100644 index 000000000..f489ae200 --- /dev/null +++ b/tests/ui/typeck/issue-86721-return-expr-ice.rev2.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:15:20 + | +LL | fn foo(a: [(); return]); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/tests/ui/typeck/issue-86721-return-expr-ice.rs b/tests/ui/typeck/issue-86721-return-expr-ice.rs new file mode 100644 index 000000000..cd7135f18 --- /dev/null +++ b/tests/ui/typeck/issue-86721-return-expr-ice.rs @@ -0,0 +1,17 @@ +// Regression test for the ICE described in #86721. + +// revisions: rev1 rev2 +#![cfg_attr(any(), rev1, rev2)] +#![crate_type="lib"] + +#[cfg(any(rev1))] +trait T { + const U: usize = return; + //[rev1]~^ ERROR: return statement outside of function body [E0572] +} + +#[cfg(any(rev2))] +trait T2 { + fn foo(a: [(); return]); + //[rev2]~^ ERROR: return statement outside of function body [E0572] +} diff --git a/tests/ui/typeck/issue-87181/empty-tuple-method.rs b/tests/ui/typeck/issue-87181/empty-tuple-method.rs new file mode 100644 index 000000000..96b3f8dab --- /dev/null +++ b/tests/ui/typeck/issue-87181/empty-tuple-method.rs @@ -0,0 +1,14 @@ +struct Bar { + bar: T +} + +struct Foo(); +impl Foo { + fn foo(&self) { } +} + +fn main() { + let thing = Bar { bar: Foo }; + thing.bar.foo(); + //~^ ERROR no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope [E0599] +} diff --git a/tests/ui/typeck/issue-87181/empty-tuple-method.stderr b/tests/ui/typeck/issue-87181/empty-tuple-method.stderr new file mode 100644 index 000000000..f0ca49e6d --- /dev/null +++ b/tests/ui/typeck/issue-87181/empty-tuple-method.stderr @@ -0,0 +1,14 @@ +error[E0599]: no method named `foo` found for struct constructor `fn() -> Foo {Foo}` in the current scope + --> $DIR/empty-tuple-method.rs:12:15 + | +LL | thing.bar.foo(); + | ^^^ method not found in `fn() -> Foo {Foo}` + | +help: use parentheses to construct this tuple struct + | +LL | (thing.bar)().foo(); + | + +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-87181/enum-variant.rs b/tests/ui/typeck/issue-87181/enum-variant.rs new file mode 100644 index 000000000..ed01656ce --- /dev/null +++ b/tests/ui/typeck/issue-87181/enum-variant.rs @@ -0,0 +1,16 @@ +struct Bar { + bar: T +} + +enum Foo{ + Tup() +} +impl Foo { + fn foo(&self) { } +} + +fn main() { + let thing = Bar { bar: Foo::Tup }; + thing.bar.foo(); + //~^ ERROR no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope [E0599] +} diff --git a/tests/ui/typeck/issue-87181/enum-variant.stderr b/tests/ui/typeck/issue-87181/enum-variant.stderr new file mode 100644 index 000000000..d313a887a --- /dev/null +++ b/tests/ui/typeck/issue-87181/enum-variant.stderr @@ -0,0 +1,14 @@ +error[E0599]: no method named `foo` found for enum constructor `fn() -> Foo {Foo::Tup}` in the current scope + --> $DIR/enum-variant.rs:14:15 + | +LL | thing.bar.foo(); + | ^^^ method not found in `fn() -> Foo {Foo::Tup}` + | +help: use parentheses to construct this tuple variant + | +LL | (thing.bar)().foo(); + | + +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-87181/tuple-field.rs b/tests/ui/typeck/issue-87181/tuple-field.rs new file mode 100644 index 000000000..00e3b460e --- /dev/null +++ b/tests/ui/typeck/issue-87181/tuple-field.rs @@ -0,0 +1,14 @@ +struct Bar { + bar: T +} + +struct Foo(char, u16); +impl Foo { + fn foo() { } +} + +fn main() { + let thing = Bar { bar: Foo }; + thing.bar.0; + //~^ ERROR no field `0` on type `fn(char, u16) -> Foo {Foo}` [E0609] +} diff --git a/tests/ui/typeck/issue-87181/tuple-field.stderr b/tests/ui/typeck/issue-87181/tuple-field.stderr new file mode 100644 index 000000000..0a7d30b61 --- /dev/null +++ b/tests/ui/typeck/issue-87181/tuple-field.stderr @@ -0,0 +1,14 @@ +error[E0609]: no field `0` on type `fn(char, u16) -> Foo {Foo}` + --> $DIR/tuple-field.rs:12:15 + | +LL | thing.bar.0; + | ^ + | +help: use parentheses to construct this tuple struct + | +LL | (thing.bar)(/* char */, /* u16 */).0; + | + ++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/typeck/issue-87181/tuple-method.rs b/tests/ui/typeck/issue-87181/tuple-method.rs new file mode 100644 index 000000000..631098443 --- /dev/null +++ b/tests/ui/typeck/issue-87181/tuple-method.rs @@ -0,0 +1,14 @@ +struct Bar { + bar: T +} + +struct Foo(u8, i32); +impl Foo { + fn foo() { } +} + +fn main() { + let thing = Bar { bar: Foo }; + thing.bar.foo(); + //~^ ERROR no method named `foo` found for struct constructor `fn(u8, i32) -> Foo {Foo}` in the current scope [E0599] +} diff --git a/tests/ui/typeck/issue-87181/tuple-method.stderr b/tests/ui/typeck/issue-87181/tuple-method.stderr new file mode 100644 index 000000000..de3dc15a5 --- /dev/null +++ b/tests/ui/typeck/issue-87181/tuple-method.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `foo` found for struct constructor `fn(u8, i32) -> Foo {Foo}` in the current scope + --> $DIR/tuple-method.rs:12:15 + | +LL | thing.bar.foo(); + | ^^^ method not found in `fn(u8, i32) -> Foo {Foo}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs b/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs new file mode 100644 index 000000000..751dc8719 --- /dev/null +++ b/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.rs @@ -0,0 +1,4 @@ +fn main() { + let mut a; + a = a = true; //~ ERROR mismatched types +} diff --git a/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr b/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr new file mode 100644 index 000000000..56817ee2c --- /dev/null +++ b/tests/ui/typeck/issue-87771-ice-assign-assign-to-bool.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-87771-ice-assign-assign-to-bool.rs:3:9 + | +LL | let mut a; + | ----- expected due to the type of this binding +LL | a = a = true; + | ^^^^^^^^ expected `bool`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs b/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs new file mode 100644 index 000000000..326e958aa --- /dev/null +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs @@ -0,0 +1,11 @@ +pub mod foo { + pub struct Foo { + pub you_can_use_this_field: bool, + you_cant_use_this_field: bool, + } +} + +fn main() { + foo::Foo {}; + //~^ ERROR cannot construct `Foo` with struct literal syntax due to private fields +} diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr b/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr new file mode 100644 index 000000000..f0bd3e0dd --- /dev/null +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr @@ -0,0 +1,10 @@ +error: cannot construct `Foo` with struct literal syntax due to private fields + --> $DIR/issue-87872-missing-inaccessible-field-literal.rs:9:5 + | +LL | foo::Foo {}; + | ^^^^^^^^ + | + = note: ... and other private field `you_cant_use_this_field` that was not provided + +error: aborting due to previous error + diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs new file mode 100644 index 000000000..d28e17559 --- /dev/null +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs @@ -0,0 +1,11 @@ +#![allow(dead_code, unused_variables)] + +pub mod foo { + #[derive(Default)] + pub struct Foo { pub visible: bool, invisible: bool, } +} + +fn main() { + let foo::Foo {} = foo::Foo::default(); + //~^ ERROR pattern does not mention field `visible` and inaccessible fields +} diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr new file mode 100644 index 000000000..dc3097510 --- /dev/null +++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr @@ -0,0 +1,18 @@ +error[E0027]: pattern does not mention field `visible` and inaccessible fields + --> $DIR/issue-87872-missing-inaccessible-field-pattern.rs:9:9 + | +LL | let foo::Foo {} = foo::Foo::default(); + | ^^^^^^^^^^^ missing field `visible` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let foo::Foo { visible, .. } = foo::Foo::default(); + | ~~~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let foo::Foo { .. } = foo::Foo::default(); + | ~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/typeck/issue-87935-unsized-box-expr.rs b/tests/ui/typeck/issue-87935-unsized-box-expr.rs new file mode 100644 index 000000000..cd2a82074 --- /dev/null +++ b/tests/ui/typeck/issue-87935-unsized-box-expr.rs @@ -0,0 +1,10 @@ +#![feature(box_syntax)] +// Box expression needs to be movable, and hence has to be of a Sized type. +fn main() { + let _x: Box<[u32]> = box { loop {} }; + //~^ ERROR: the size for values of type `[u32]` cannot be known at compilation time + + // Check that a deduced size does not cause issues. + let _y: Box<[u32]> = box []; + let _z: Box<[u32; 0]> = box { loop {} }; +} diff --git a/tests/ui/typeck/issue-87935-unsized-box-expr.stderr b/tests/ui/typeck/issue-87935-unsized-box-expr.stderr new file mode 100644 index 000000000..9ff822352 --- /dev/null +++ b/tests/ui/typeck/issue-87935-unsized-box-expr.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/issue-87935-unsized-box-expr.rs:4:30 + | +LL | let _x: Box<[u32]> = box { loop {} }; + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` + = note: the type of a box expression must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-88609.rs b/tests/ui/typeck/issue-88609.rs new file mode 100644 index 000000000..dc459c885 --- /dev/null +++ b/tests/ui/typeck/issue-88609.rs @@ -0,0 +1,19 @@ +// Regression test for #88609: +// The return type for `main` is not normalized while checking if it implements +// the trait `std::process::Termination`. + +// build-pass + +trait Same { + type Output; +} + +impl Same for T { + type Output = T; +} + +type Unit = <() as Same>::Output; + +fn main() -> Result { + unimplemented!() +} diff --git a/tests/ui/typeck/issue-88643.rs b/tests/ui/typeck/issue-88643.rs new file mode 100644 index 000000000..4435cba02 --- /dev/null +++ b/tests/ui/typeck/issue-88643.rs @@ -0,0 +1,19 @@ +// Regression test for the ICE described in #88643. Specifically: +// https://github.com/rust-lang/rust/issues/88643#issuecomment-913128893 +// and https://github.com/rust-lang/rust/issues/88643#issuecomment-913171935 +// and https://github.com/rust-lang/rust/issues/88643#issuecomment-913765984 + +use std::collections::HashMap; + +pub trait T {} + +static CALLBACKS: HashMap<*const dyn T, dyn FnMut(&mut _) + 'static> = HashMap::new(); +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static items [E0121] + +static CALLBACKS2: Vec = Vec::new(); +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static items [E0121] + +static CALLBACKS3: Option = None; +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for static items [E0121] + +fn main() {} diff --git a/tests/ui/typeck/issue-88643.stderr b/tests/ui/typeck/issue-88643.stderr new file mode 100644 index 000000000..d5d596b6f --- /dev/null +++ b/tests/ui/typeck/issue-88643.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items + --> $DIR/issue-88643.rs:10:56 + | +LL | static CALLBACKS: HashMap<*const dyn T, dyn FnMut(&mut _) + 'static> = HashMap::new(); + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items + --> $DIR/issue-88643.rs:13:33 + | +LL | static CALLBACKS2: Vec = Vec::new(); + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static items + --> $DIR/issue-88643.rs:16:36 + | +LL | static CALLBACKS3: Option = None; + | ^ not allowed in type signatures + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-88803-call-expr-method.fixed b/tests/ui/typeck/issue-88803-call-expr-method.fixed new file mode 100644 index 000000000..19b96ecf3 --- /dev/null +++ b/tests/ui/typeck/issue-88803-call-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + a.unwrap() //~ERROR [E0615] + ); +} diff --git a/tests/ui/typeck/issue-88803-call-expr-method.rs b/tests/ui/typeck/issue-88803-call-expr-method.rs new file mode 100644 index 000000000..a06199466 --- /dev/null +++ b/tests/ui/typeck/issue-88803-call-expr-method.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap)() //~ERROR [E0615] + ); +} diff --git a/tests/ui/typeck/issue-88803-call-expr-method.stderr b/tests/ui/typeck/issue-88803-call-expr-method.stderr new file mode 100644 index 000000000..645c04b87 --- /dev/null +++ b/tests/ui/typeck/issue-88803-call-expr-method.stderr @@ -0,0 +1,15 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-88803-call-expr-method.rs:7:12 + | +LL | (a.unwrap)() + | ^^^^^^ method, not a field + | +help: remove wrapping parentheses to call the method + | +LL - (a.unwrap)() +LL + a.unwrap() + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-88844.rs b/tests/ui/typeck/issue-88844.rs new file mode 100644 index 000000000..116c75aab --- /dev/null +++ b/tests/ui/typeck/issue-88844.rs @@ -0,0 +1,14 @@ +// Regression test for #88844. + +struct Struct { value: i32 } +//~^ NOTE: similarly named struct `Struct` defined here + +impl Stuct { +//~^ ERROR: cannot find type `Stuct` in this scope [E0412] +//~| HELP: a struct with a similar name exists + fn new() -> Self { + Self { value: 42 } + } +} + +fn main() {} diff --git a/tests/ui/typeck/issue-88844.stderr b/tests/ui/typeck/issue-88844.stderr new file mode 100644 index 000000000..90bba90be --- /dev/null +++ b/tests/ui/typeck/issue-88844.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `Stuct` in this scope + --> $DIR/issue-88844.rs:6:6 + | +LL | struct Struct { value: i32 } + | ------------- similarly named struct `Struct` defined here +... +LL | impl Stuct { + | ^^^^^ help: a struct with a similar name exists: `Struct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/issue-89044-wrapped-expr-method.fixed b/tests/ui/typeck/issue-89044-wrapped-expr-method.fixed new file mode 100644 index 000000000..0a3086a34 --- /dev/null +++ b/tests/ui/typeck/issue-89044-wrapped-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap()) //~ERROR [E0615] + ); +} diff --git a/tests/ui/typeck/issue-89044-wrapped-expr-method.rs b/tests/ui/typeck/issue-89044-wrapped-expr-method.rs new file mode 100644 index 000000000..83617e035 --- /dev/null +++ b/tests/ui/typeck/issue-89044-wrapped-expr-method.rs @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap) //~ERROR [E0615] + ); +} diff --git a/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr b/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr new file mode 100644 index 000000000..6fa0915dc --- /dev/null +++ b/tests/ui/typeck/issue-89044-wrapped-expr-method.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-89044-wrapped-expr-method.rs:7:12 + | +LL | (a.unwrap) + | ^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | (a.unwrap()) + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-89275.rs b/tests/ui/typeck/issue-89275.rs new file mode 100644 index 000000000..b91c00175 --- /dev/null +++ b/tests/ui/typeck/issue-89275.rs @@ -0,0 +1,29 @@ +#![recursion_limit = "5"] // To reduce noise + +//expect mutability error when ambiguous traits are in scope +//and not an overflow error on the span in the main function. + +struct Ratio(T); + +pub trait Pow { + fn pow(self) -> Self; +} + +impl<'a, T> Pow for &'a Ratio +where + &'a T: Pow, +{ + fn pow(self) -> Self { + self + } +} + +fn downcast<'a, W: ?Sized>() -> &'a W { + todo!() +} + +struct Other; + +fn main() { + let other: &mut Other = downcast();//~ERROR 28:29: 28:39: mismatched types [E0308] +} diff --git a/tests/ui/typeck/issue-89275.stderr b/tests/ui/typeck/issue-89275.stderr new file mode 100644 index 000000000..d73e647d2 --- /dev/null +++ b/tests/ui/typeck/issue-89275.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-89275.rs:28:29 + | +LL | let other: &mut Other = downcast(); + | ---------- ^^^^^^^^^^ types differ in mutability + | | + | expected due to this + | + = note: expected mutable reference `&mut Other` + found reference `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-89806.rs b/tests/ui/typeck/issue-89806.rs new file mode 100644 index 000000000..69cec0865 --- /dev/null +++ b/tests/ui/typeck/issue-89806.rs @@ -0,0 +1,3 @@ +fn main() { + 0u8.as_ref(); //~ ERROR no method named `as_ref` found for type `u8` in the current scope +} diff --git a/tests/ui/typeck/issue-89806.stderr b/tests/ui/typeck/issue-89806.stderr new file mode 100644 index 000000000..c36b4967e --- /dev/null +++ b/tests/ui/typeck/issue-89806.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `as_ref` found for type `u8` in the current scope + --> $DIR/issue-89806.rs:2:9 + | +LL | 0u8.as_ref(); + | ^^^^^^ method not found in `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-89856.rs b/tests/ui/typeck/issue-89856.rs new file mode 100644 index 000000000..b021e349e --- /dev/null +++ b/tests/ui/typeck/issue-89856.rs @@ -0,0 +1,8 @@ +fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } + +fn main() { + let string = String::from("Hello, world"); + let option = Some(&string); + take_str_maybe(option); + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/typeck/issue-89856.stderr b/tests/ui/typeck/issue-89856.stderr new file mode 100644 index 000000000..5fa1ae1a5 --- /dev/null +++ b/tests/ui/typeck/issue-89856.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/issue-89856.rs:6:20 + | +LL | take_str_maybe(option); + | -------------- ^^^^^^ expected `str`, found struct `String` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&str>` + found enum `Option<&String>` +note: function defined here + --> $DIR/issue-89856.rs:1:4 + | +LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } + | ^^^^^^^^^^^^^^ --------------- +help: try converting the passed type into a `&str` + | +LL | take_str_maybe(option.map(|x| &**x)); + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-89935.rs b/tests/ui/typeck/issue-89935.rs new file mode 100644 index 000000000..03f8f09a7 --- /dev/null +++ b/tests/ui/typeck/issue-89935.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Foo: Baz {} +trait Bar {} +trait Baz: Bar { + fn bar(&self); +} + +impl Bar for T {} +impl Baz for T { + fn bar(&self) {} +} + +fn accept_foo(x: Box) { + x.bar(); +} + +fn main() {} diff --git a/tests/ui/typeck/issue-90101.rs b/tests/ui/typeck/issue-90101.rs new file mode 100644 index 000000000..1954ee6f1 --- /dev/null +++ b/tests/ui/typeck/issue-90101.rs @@ -0,0 +1,8 @@ +use std::path::{Path, PathBuf}; + +fn func(path: impl Into, code: impl Into) {} + +fn main() { + func(Path::new("hello").to_path_buf().to_string_lossy(), "world") + //~^ ERROR [E0277] +} diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr new file mode 100644 index 000000000..d2729d853 --- /dev/null +++ b/tests/ui/typeck/issue-90101.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `PathBuf: From>` is not satisfied + --> $DIR/issue-90101.rs:6:10 + | +LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `PathBuf` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `From`: + > + >> + >> + > + > + = note: required for `Cow<'_, str>` to implement `Into` +note: required by a bound in `func` + --> $DIR/issue-90101.rs:3:20 + | +LL | fn func(path: impl Into, code: impl Into) {} + | ^^^^^^^^^^^^^ required by this bound in `func` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-90164.rs b/tests/ui/typeck/issue-90164.rs new file mode 100644 index 000000000..63350433e --- /dev/null +++ b/tests/ui/typeck/issue-90164.rs @@ -0,0 +1,9 @@ +fn copy(_: R, _: W) {} + +fn f(r: T) { + let w = (); + copy(r, w); + //~^ ERROR [E0277] +} + +fn main() {} diff --git a/tests/ui/typeck/issue-90164.stderr b/tests/ui/typeck/issue-90164.stderr new file mode 100644 index 000000000..1e2f1bae3 --- /dev/null +++ b/tests/ui/typeck/issue-90164.stderr @@ -0,0 +1,22 @@ +error[E0277]: `T` cannot be unpinned + --> $DIR/issue-90164.rs:5:10 + | +LL | copy(r, w); + | ---- ^ the trait `Unpin` is not implemented for `T` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `copy` + --> $DIR/issue-90164.rs:1:12 + | +LL | fn copy(_: R, _: W) {} + | ^^^^^ required by this bound in `copy` +help: consider restricting type parameter `T` + | +LL | fn f(r: T) { + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-90319.rs b/tests/ui/typeck/issue-90319.rs new file mode 100644 index 000000000..57e6ac7cf --- /dev/null +++ b/tests/ui/typeck/issue-90319.rs @@ -0,0 +1,17 @@ +struct Wrapper(T); + +trait Trait { + fn method(&self) {} +} + +impl<'a, T> Trait for Wrapper<&'a T> where Wrapper: Trait {} + +fn get() -> T { + unimplemented!() +} + +fn main() { + let thing = get::();//~ERROR cannot find type `Thing` in this scope [E0412] + let wrapper = Wrapper(thing); + Trait::method(&wrapper); +} diff --git a/tests/ui/typeck/issue-90319.stderr b/tests/ui/typeck/issue-90319.stderr new file mode 100644 index 000000000..61549dd70 --- /dev/null +++ b/tests/ui/typeck/issue-90319.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Thing` in this scope + --> $DIR/issue-90319.rs:14:23 + | +LL | let thing = get::(); + | ^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.rs b/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.rs new file mode 100644 index 000000000..74e50d46e --- /dev/null +++ b/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.rs @@ -0,0 +1,14 @@ +// edition:2021 + +mod m { + pub struct S { foo: i32 } + impl S { + pub fn foo(&self) -> i32 { 42 } + } +} + +fn bar(s: &m::S) { + || s.foo() + s.foo; //~ ERROR E0616 +} + +fn main() {} diff --git a/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr b/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr new file mode 100644 index 000000000..02cdc102c --- /dev/null +++ b/tests/ui/typeck/issue-90483-inaccessible-field-adjustment.stderr @@ -0,0 +1,14 @@ +error[E0616]: field `foo` of struct `S` is private + --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18 + | +LL | || s.foo() + s.foo; + | ^^^ private field + | +help: a method `foo` also exists, call it with parentheses + | +LL | || s.foo() + s.foo(); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. diff --git a/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.rs b/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.rs new file mode 100644 index 000000000..f891a42fc --- /dev/null +++ b/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.rs @@ -0,0 +1,11 @@ +// Do not suggest referencing the parameter to `check` + +trait Marker {} + +impl Marker for T {} + +pub fn check>(_: T) {} + +pub fn main() { + check::<()>(()); //~ ERROR [E0277] +} diff --git a/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr b/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr new file mode 100644 index 000000000..08eab0253 --- /dev/null +++ b/tests/ui/typeck/issue-90804-incorrect-reference-suggestion.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `(): Marker` is not satisfied + --> $DIR/issue-90804-incorrect-reference-suggestion.rs:10:17 + | +LL | check::<()>(()); + | ----------- ^^ the trait `Marker` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/issue-90804-incorrect-reference-suggestion.rs:7:17 + | +LL | pub fn check>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-91210-ptr-method.fixed b/tests/ui/typeck/issue-91210-ptr-method.fixed new file mode 100644 index 000000000..94200cce7 --- /dev/null +++ b/tests/ui/typeck/issue-91210-ptr-method.fixed @@ -0,0 +1,15 @@ +// Regression test for issue #91210. + +// run-rustfix + +#![allow(unused)] + +struct Foo { read: i32 } + +unsafe fn blah(x: *mut Foo) { + (*x).read = 4; + //~^ ERROR: attempted to take value of method + //~| HELP: to access the field, dereference first +} + +fn main() {} diff --git a/tests/ui/typeck/issue-91210-ptr-method.rs b/tests/ui/typeck/issue-91210-ptr-method.rs new file mode 100644 index 000000000..ed0ce6eff --- /dev/null +++ b/tests/ui/typeck/issue-91210-ptr-method.rs @@ -0,0 +1,15 @@ +// Regression test for issue #91210. + +// run-rustfix + +#![allow(unused)] + +struct Foo { read: i32 } + +unsafe fn blah(x: *mut Foo) { + x.read = 4; + //~^ ERROR: attempted to take value of method + //~| HELP: to access the field, dereference first +} + +fn main() {} diff --git a/tests/ui/typeck/issue-91210-ptr-method.stderr b/tests/ui/typeck/issue-91210-ptr-method.stderr new file mode 100644 index 000000000..7a0cfb2cf --- /dev/null +++ b/tests/ui/typeck/issue-91210-ptr-method.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `read` on type `*mut Foo` + --> $DIR/issue-91210-ptr-method.rs:10:7 + | +LL | x.read = 4; + | ^^^^ method, not a field + | +help: to access the field, dereference first + | +LL | (*x).read = 4; + | ++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. diff --git a/tests/ui/typeck/issue-91267.rs b/tests/ui/typeck/issue-91267.rs new file mode 100644 index 000000000..4e39cfab5 --- /dev/null +++ b/tests/ui/typeck/issue-91267.rs @@ -0,0 +1,8 @@ +#![feature(type_ascription)] + +fn main() { + type_ascribe!(0, u8=e>) + //~^ ERROR: cannot find type `e` in this scope [E0412] + //~| ERROR: associated type bindings are not allowed here [E0229] + //~| ERROR: mismatched types [E0308] +} diff --git a/tests/ui/typeck/issue-91267.stderr b/tests/ui/typeck/issue-91267.stderr new file mode 100644 index 000000000..72acd9c67 --- /dev/null +++ b/tests/ui/typeck/issue-91267.stderr @@ -0,0 +1,24 @@ +error[E0412]: cannot find type `e` in this scope + --> $DIR/issue-91267.rs:4:30 + | +LL | type_ascribe!(0, u8=e>) + | ^ not found in this scope + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-91267.rs:4:25 + | +LL | type_ascribe!(0, u8=e>) + | ^^^^^^ associated type not allowed here + +error[E0308]: mismatched types + --> $DIR/issue-91267.rs:4:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | type_ascribe!(0, u8=e>) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `u8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0229, E0308, E0412. +For more information about an error, try `rustc --explain E0229`. diff --git a/tests/ui/typeck/issue-91328.fixed b/tests/ui/typeck/issue-91328.fixed new file mode 100644 index 000000000..c0384399a --- /dev/null +++ b/tests/ui/typeck/issue-91328.fixed @@ -0,0 +1,47 @@ +// Regression test for issue #91328. + +// run-rustfix + +#![allow(dead_code)] + +fn foo(r: Result, i32>) -> i32 { + match r.as_deref() { + //~^ HELP: consider using `as_deref` here + Ok([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn bar(o: Option>) -> i32 { + match o.as_deref() { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn baz(v: Vec) -> i32 { + match v[..] { + //~^ HELP: consider slicing here + [a, b] => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn qux(a: &Option>) -> i32 { + match a.as_deref() { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn main() {} diff --git a/tests/ui/typeck/issue-91328.rs b/tests/ui/typeck/issue-91328.rs new file mode 100644 index 000000000..63602d26f --- /dev/null +++ b/tests/ui/typeck/issue-91328.rs @@ -0,0 +1,47 @@ +// Regression test for issue #91328. + +// run-rustfix + +#![allow(dead_code)] + +fn foo(r: Result, i32>) -> i32 { + match r { + //~^ HELP: consider using `as_deref` here + Ok([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn bar(o: Option>) -> i32 { + match o { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn baz(v: Vec) -> i32 { + match v { + //~^ HELP: consider slicing here + [a, b] => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn qux(a: &Option>) -> i32 { + match a { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + +fn main() {} diff --git a/tests/ui/typeck/issue-91328.stderr b/tests/ui/typeck/issue-91328.stderr new file mode 100644 index 000000000..f2f407bca --- /dev/null +++ b/tests/ui/typeck/issue-91328.stderr @@ -0,0 +1,39 @@ +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/issue-91328.rs:10:12 + | +LL | match r { + | - help: consider using `as_deref` here: `r.as_deref()` +LL | +LL | Ok([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/issue-91328.rs:20:14 + | +LL | match o { + | - help: consider using `as_deref` here: `o.as_deref()` +LL | +LL | Some([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Vec` + --> $DIR/issue-91328.rs:30:9 + | +LL | match v { + | - help: consider slicing here: `v[..]` +LL | +LL | [a, b] => a + b, + | ^^^^^^ pattern cannot match with input type `Vec` + +error[E0529]: expected an array or slice, found `Box<[i32; 2]>` + --> $DIR/issue-91328.rs:40:14 + | +LL | match a { + | - help: consider using `as_deref` here: `a.as_deref()` +LL | +LL | Some([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Box<[i32; 2]>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0529`. diff --git a/tests/ui/typeck/issue-91334.rs b/tests/ui/typeck/issue-91334.rs new file mode 100644 index 000000000..bf9a5a626 --- /dev/null +++ b/tests/ui/typeck/issue-91334.rs @@ -0,0 +1,10 @@ +// Regression test for the ICE described in issue #91334. + +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected one of +// error-pattern: mismatched closing delimiter +// error-pattern: mismatched types + +#![feature(generators)] + +fn f(){||yield(((){), diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr new file mode 100644 index 000000000..8508f7a38 --- /dev/null +++ b/tests/ui/typeck/issue-91334.stderr @@ -0,0 +1,50 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-91334.rs:10:23 + | +LL | fn f(){||yield(((){), + | - - ^ + | | | + | | unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-91334.rs:10:23 + | +LL | fn f(){||yield(((){), + | - - ^ + | | | + | | unclosed delimiter + | unclosed delimiter + +error: expected one of `)`, `,`, `.`, `?`, or an operator, found `{` + --> $DIR/issue-91334.rs:10:19 + | +LL | fn f(){||yield(((){), + | ^ + | | + | expected one of `)`, `,`, `.`, `?`, or an operator + | help: missing `,` + +error: mismatched closing delimiter: `)` + --> $DIR/issue-91334.rs:10:19 + | +LL | fn f(){||yield(((){), + | - ^^ mismatched closing delimiter + | | | + | | unclosed delimiter + | closing delimiter possibly meant for this + +error[E0308]: mismatched types + --> $DIR/issue-91334.rs:10:8 + | +LL | fn f(){||yield(((){), + | -^^^^^^^^^^^^^^^ expected `()`, found generator + | | + | help: a return type might be missing here: `-> _` + | + = note: expected unit type `()` + found generator `[generator@$DIR/issue-91334.rs:10:8: 10:10]` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-91450-inner-ty-error.rs b/tests/ui/typeck/issue-91450-inner-ty-error.rs new file mode 100644 index 000000000..3c7c990d4 --- /dev/null +++ b/tests/ui/typeck/issue-91450-inner-ty-error.rs @@ -0,0 +1,7 @@ +// Regression test for #91450. +// This test ensures that the compiler does not suggest `Foo<[type error]>` in diagnostic messages. + +fn foo() -> Option<_> {} //~ ERROR: [E0308] +//~^ ERROR: the placeholder `_` is not allowed + +fn main() {} diff --git a/tests/ui/typeck/issue-91450-inner-ty-error.stderr b/tests/ui/typeck/issue-91450-inner-ty-error.stderr new file mode 100644 index 000000000..32f4c8f6f --- /dev/null +++ b/tests/ui/typeck/issue-91450-inner-ty-error.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-91450-inner-ty-error.rs:4:13 + | +LL | fn foo() -> Option<_> {} + | --- ^^^^^^^^^ expected enum `Option`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Option<_>` + found unit type `()` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-91450-inner-ty-error.rs:4:20 + | +LL | fn foo() -> Option<_> {} + | ^ not allowed in type signatures + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0121, E0308. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-91633.rs b/tests/ui/typeck/issue-91633.rs new file mode 100644 index 000000000..331a798dd --- /dev/null +++ b/tests/ui/typeck/issue-91633.rs @@ -0,0 +1,8 @@ +// check-pass +fn f (it: &[T]) +where + [T] : std::ops::Index, +{ + let _ = &it[0]; +} +fn main(){} diff --git a/tests/ui/typeck/issue-92481.rs b/tests/ui/typeck/issue-92481.rs new file mode 100644 index 000000000..0a6b1843d --- /dev/null +++ b/tests/ui/typeck/issue-92481.rs @@ -0,0 +1,14 @@ +//check-fail + +#![crate_type="lib"] + +fn r({) { + Ok { //~ ERROR mismatched types [E0308] + d..||_=m + } +} +//~^^^^^ ERROR expected parameter name, found `{` +//~| ERROR expected one of `,`, `:`, or `}`, found `..` +//~^^^^^ ERROR cannot find value `d` in this scope [E0425] +//~| ERROR cannot find value `m` in this scope [E0425] +//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559] diff --git a/tests/ui/typeck/issue-92481.stderr b/tests/ui/typeck/issue-92481.stderr new file mode 100644 index 000000000..cd778a649 --- /dev/null +++ b/tests/ui/typeck/issue-92481.stderr @@ -0,0 +1,60 @@ +error: expected parameter name, found `{` + --> $DIR/issue-92481.rs:5:6 + | +LL | fn r({) { + | ^ expected parameter name + +error: expected one of `,`, `:`, or `}`, found `..` + --> $DIR/issue-92481.rs:5:6 + | +LL | fn r({) { + | ^ unclosed delimiter +LL | Ok { +LL | d..||_=m + | -^ + | | + | help: `}` may belong here + +error[E0425]: cannot find value `d` in this scope + --> $DIR/issue-92481.rs:7:9 + | +LL | d..||_=m + | ^ not found in this scope + +error[E0425]: cannot find value `m` in this scope + --> $DIR/issue-92481.rs:7:16 + | +LL | d..||_=m + | ^ not found in this scope + +error[E0559]: variant `Result<_, _>::Ok` has no field named `d` + --> $DIR/issue-92481.rs:7:9 + | +LL | d..||_=m + | ^ field does not exist + --> $SRC_DIR/core/src/result.rs:LL:COL + | + = note: `Result<_, _>::Ok` defined here + | +help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax + | +LL | Result<_, _>::Ok(/* fields */) + | + +error[E0308]: mismatched types + --> $DIR/issue-92481.rs:6:5 + | +LL | fn r({) { + | - help: a return type might be missing here: `-> _` +LL | / Ok { +LL | | d..||_=m +LL | | } + | |_____^ expected `()`, found enum `Result` + | + = note: expected unit type `()` + found enum `Result<_, _>` + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0425, E0559. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-93486.rs b/tests/ui/typeck/issue-93486.rs new file mode 100644 index 000000000..f8f98d5c1 --- /dev/null +++ b/tests/ui/typeck/issue-93486.rs @@ -0,0 +1,6 @@ +fn main() { + while let 1 = 1 { + vec![].last_mut().unwrap() = 3_u8; + //~^ ERROR invalid left-hand side of assignment + } +} diff --git a/tests/ui/typeck/issue-93486.stderr b/tests/ui/typeck/issue-93486.stderr new file mode 100644 index 000000000..167edc894 --- /dev/null +++ b/tests/ui/typeck/issue-93486.stderr @@ -0,0 +1,16 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/issue-93486.rs:3:36 + | +LL | vec![].last_mut().unwrap() = 3_u8; + | -------------------------- ^ + | | + | cannot assign to this expression + | +help: consider dereferencing here to assign to the mutably borrowed value + | +LL | *vec![].last_mut().unwrap() = 3_u8; + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/typeck/issue-96530.rs b/tests/ui/typeck/issue-96530.rs new file mode 100644 index 000000000..4ab93ab49 --- /dev/null +++ b/tests/ui/typeck/issue-96530.rs @@ -0,0 +1,20 @@ +struct Person { + first_name: String, + age: u32, +} + +fn first_woman(man: &Person) -> Person { + Person { + first_name: "Eve".to_string(), + ..man.clone() //~ ERROR: mismatched types + } +} + +fn main() { + let adam = Person { + first_name: "Adam".to_string(), + age: 0, + }; + + let eve = first_woman(&adam); +} diff --git a/tests/ui/typeck/issue-96530.stderr b/tests/ui/typeck/issue-96530.stderr new file mode 100644 index 000000000..4b4568b1d --- /dev/null +++ b/tests/ui/typeck/issue-96530.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-96530.rs:9:11 + | +LL | ..man.clone() + | ^^^^^^^^^^^ expected struct `Person`, found `&Person` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-96738.rs b/tests/ui/typeck/issue-96738.rs new file mode 100644 index 000000000..ce2556f86 --- /dev/null +++ b/tests/ui/typeck/issue-96738.rs @@ -0,0 +1,4 @@ +fn main() { + Some.nonexistent_method(); //~ ERROR: no method named `nonexistent_method` found + Some.nonexistent_field; //~ ERROR: no field `nonexistent_field` +} diff --git a/tests/ui/typeck/issue-96738.stderr b/tests/ui/typeck/issue-96738.stderr new file mode 100644 index 000000000..547cffffa --- /dev/null +++ b/tests/ui/typeck/issue-96738.stderr @@ -0,0 +1,16 @@ +error[E0599]: no method named `nonexistent_method` found for enum constructor `fn(_) -> Option<_> {Option::<_>::Some}` in the current scope + --> $DIR/issue-96738.rs:2:10 + | +LL | Some.nonexistent_method(); + | ^^^^^^^^^^^^^^^^^^ method not found in `fn(_) -> Option<_> {Option::<_>::Some}` + +error[E0609]: no field `nonexistent_field` on type `fn(_) -> Option<_> {Option::<_>::Some}` + --> $DIR/issue-96738.rs:3:10 + | +LL | Some.nonexistent_field; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0609. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/issue-98260.rs b/tests/ui/typeck/issue-98260.rs new file mode 100644 index 000000000..cf48294e1 --- /dev/null +++ b/tests/ui/typeck/issue-98260.rs @@ -0,0 +1,9 @@ +fn main() {} +trait A { + fn a(aa: B) -> Result<_, B> { + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for return types [E0121] + Ok(()) + } +} + +enum B {} diff --git a/tests/ui/typeck/issue-98260.stderr b/tests/ui/typeck/issue-98260.stderr new file mode 100644 index 000000000..08a1d17e2 --- /dev/null +++ b/tests/ui/typeck/issue-98260.stderr @@ -0,0 +1,12 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/issue-98260.rs:3:27 + | +LL | fn a(aa: B) -> Result<_, B> { + | -------^---- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Result<(), B>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/issue-98982.rs b/tests/ui/typeck/issue-98982.rs new file mode 100644 index 000000000..2553824bb --- /dev/null +++ b/tests/ui/typeck/issue-98982.rs @@ -0,0 +1,9 @@ +fn foo() -> i32 { + for i in 0..0 { + //~^ ERROR: mismatched types [E0308] + return i; + } + //~| help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility +} + +fn main() {} diff --git a/tests/ui/typeck/issue-98982.stderr b/tests/ui/typeck/issue-98982.stderr new file mode 100644 index 000000000..3c9806ac9 --- /dev/null +++ b/tests/ui/typeck/issue-98982.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-98982.rs:2:5 + | +LL | fn foo() -> i32 { + | --- expected `i32` because of return type +LL | / for i in 0..0 { +LL | | +LL | | return i; +LL | | } + | |_____^ expected `i32`, found `()` + | +note: the function expects a value to always be returned, but loops might run zero times + --> $DIR/issue-98982.rs:2:5 + | +LL | for i in 0..0 { + | ^^^^^^^^^^^^^ this might have zero elements to iterate on +LL | +LL | return i; + | -------- if the loop doesn't execute, this value would never get returned + = help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/missing-private-fields-in-struct-literal.rs b/tests/ui/typeck/missing-private-fields-in-struct-literal.rs new file mode 100644 index 000000000..9f1560bfb --- /dev/null +++ b/tests/ui/typeck/missing-private-fields-in-struct-literal.rs @@ -0,0 +1,18 @@ +pub mod m { + pub struct S { + pub visible: bool, + a: (), + b: (), + c: (), + d: (), + e: (), + } +} + +fn main() { + let _ = m::S { //~ ERROR cannot construct `S` with struct literal syntax due to private fields + visible: true, + a: (), + b: (), + }; +} diff --git a/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr b/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr new file mode 100644 index 000000000..234110f31 --- /dev/null +++ b/tests/ui/typeck/missing-private-fields-in-struct-literal.stderr @@ -0,0 +1,15 @@ +error: cannot construct `S` with struct literal syntax due to private fields + --> $DIR/missing-private-fields-in-struct-literal.rs:13:13 + | +LL | let _ = m::S { + | ^^^^ +LL | visible: true, +LL | a: (), + | ----- private field +LL | b: (), + | ----- private field + | + = note: ... and other private fields `c`, `d` and `e` that were not provided + +error: aborting due to previous error + diff --git a/tests/ui/typeck/no-type-for-node-ice.rs b/tests/ui/typeck/no-type-for-node-ice.rs new file mode 100644 index 000000000..d0cfdbf50 --- /dev/null +++ b/tests/ui/typeck/no-type-for-node-ice.rs @@ -0,0 +1,5 @@ +// Related issues: #20401, #20506, #20614, #20752, #20829, #20846, #20885, #20886 + +fn main() { + "".homura[""]; //~ no field `homura` on type `&'static str` +} diff --git a/tests/ui/typeck/no-type-for-node-ice.stderr b/tests/ui/typeck/no-type-for-node-ice.stderr new file mode 100644 index 000000000..b50241fb1 --- /dev/null +++ b/tests/ui/typeck/no-type-for-node-ice.stderr @@ -0,0 +1,9 @@ +error[E0609]: no field `homura` on type `&'static str` + --> $DIR/no-type-for-node-ice.rs:4:8 + | +LL | "".homura[""]; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/typeck/nonexistent-field-not-ambiguous.rs b/tests/ui/typeck/nonexistent-field-not-ambiguous.rs new file mode 100644 index 000000000..1cd192b78 --- /dev/null +++ b/tests/ui/typeck/nonexistent-field-not-ambiguous.rs @@ -0,0 +1,8 @@ +struct Foo { + val: MissingType, + //~^ ERROR cannot find type `MissingType` in this scope +} + +fn main() { + Foo { val: Default::default() }; +} diff --git a/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr b/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr new file mode 100644 index 000000000..76a2a5f99 --- /dev/null +++ b/tests/ui/typeck/nonexistent-field-not-ambiguous.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/nonexistent-field-not-ambiguous.rs:2:10 + | +LL | val: MissingType, + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs new file mode 100644 index 000000000..fb56b3944 --- /dev/null +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs @@ -0,0 +1,4 @@ +fn main() { + let page_size = page_size::get(); + //~^ ERROR failed to resolve: use of undeclared crate or module `page_size` +} diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr new file mode 100644 index 000000000..b01e30be5 --- /dev/null +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `page_size` + --> $DIR/path-to-method-sugg-unresolved-expr.rs:2:21 + | +LL | let page_size = page_size::get(); + | ^^^^^^^^^ use of undeclared crate or module `page_size` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/typeck/point-at-type-param-in-path-expr.rs b/tests/ui/typeck/point-at-type-param-in-path-expr.rs new file mode 100644 index 000000000..9a21536f9 --- /dev/null +++ b/tests/ui/typeck/point-at-type-param-in-path-expr.rs @@ -0,0 +1,6 @@ +fn foo() {} + +fn main() { + let x = foo::<()>; + //~^ ERROR `()` doesn't implement `std::fmt::Display` +} diff --git a/tests/ui/typeck/point-at-type-param-in-path-expr.stderr b/tests/ui/typeck/point-at-type-param-in-path-expr.stderr new file mode 100644 index 000000000..1feaa0508 --- /dev/null +++ b/tests/ui/typeck/point-at-type-param-in-path-expr.stderr @@ -0,0 +1,17 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/point-at-type-param-in-path-expr.rs:4:19 + | +LL | let x = foo::<()>; + | ^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `foo` + --> $DIR/point-at-type-param-in-path-expr.rs:1:11 + | +LL | fn foo() {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/point-at-type-parameter-definition.rs b/tests/ui/typeck/point-at-type-parameter-definition.rs new file mode 100644 index 000000000..856c0db08 --- /dev/null +++ b/tests/ui/typeck/point-at-type-parameter-definition.rs @@ -0,0 +1,17 @@ +trait Trait { + fn do_stuff(&self); +} + +struct Hello; + +impl Hello { + fn method(&self) {} +} + +impl Trait for Vec { + fn do_stuff(&self) { + self[0].method(); //~ ERROR no method named `method` found for type parameter `Hello` in the current scope + } +} + +fn main() {} diff --git a/tests/ui/typeck/point-at-type-parameter-definition.stderr b/tests/ui/typeck/point-at-type-parameter-definition.stderr new file mode 100644 index 000000000..8a6ab6110 --- /dev/null +++ b/tests/ui/typeck/point-at-type-parameter-definition.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `method` found for type parameter `Hello` in the current scope + --> $DIR/point-at-type-parameter-definition.rs:13:17 + | +LL | impl Trait for Vec { + | ----- method `method` not found for this type parameter +LL | fn do_stuff(&self) { +LL | self[0].method(); + | ^^^^^^ method not found in `Hello` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/typeck/prim-with-args.fixed b/tests/ui/typeck/prim-with-args.fixed new file mode 100644 index 000000000..e3f99479a --- /dev/null +++ b/tests/ui/typeck/prim-with-args.fixed @@ -0,0 +1,28 @@ +// run-rustfix +fn main() { + +let _x: isize; //~ ERROR type arguments are not allowed on builtin type +let _x: i8; //~ ERROR type arguments are not allowed on builtin type +let _x: i16; //~ ERROR type arguments are not allowed on builtin type +let _x: i32; //~ ERROR type arguments are not allowed on builtin type +let _x: i64; //~ ERROR type arguments are not allowed on builtin type +let _x: usize; //~ ERROR type arguments are not allowed on builtin type +let _x: u8; //~ ERROR type arguments are not allowed on builtin type +let _x: u16; //~ ERROR type arguments are not allowed on builtin type +let _x: u32; //~ ERROR type arguments are not allowed on builtin type +let _x: u64; //~ ERROR type arguments are not allowed on builtin type +let _x: char; //~ ERROR type arguments are not allowed on builtin type + +let _x: isize; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i8; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i16; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i32; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i64; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: usize; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u8; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u16; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u32; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u64; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: char; //~ ERROR lifetime arguments are not allowed on builtin type + +} diff --git a/tests/ui/typeck/prim-with-args.rs b/tests/ui/typeck/prim-with-args.rs new file mode 100644 index 000000000..b10471ecc --- /dev/null +++ b/tests/ui/typeck/prim-with-args.rs @@ -0,0 +1,28 @@ +// run-rustfix +fn main() { + +let _x: isize; //~ ERROR type arguments are not allowed on builtin type +let _x: i8; //~ ERROR type arguments are not allowed on builtin type +let _x: i16; //~ ERROR type arguments are not allowed on builtin type +let _x: i32; //~ ERROR type arguments are not allowed on builtin type +let _x: i64; //~ ERROR type arguments are not allowed on builtin type +let _x: usize; //~ ERROR type arguments are not allowed on builtin type +let _x: u8; //~ ERROR type arguments are not allowed on builtin type +let _x: u16; //~ ERROR type arguments are not allowed on builtin type +let _x: u32; //~ ERROR type arguments are not allowed on builtin type +let _x: u64; //~ ERROR type arguments are not allowed on builtin type +let _x: char; //~ ERROR type arguments are not allowed on builtin type + +let _x: isize<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i8<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i16<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i32<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i64<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: usize<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u8<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u16<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u32<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u64<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: char<'static>; //~ ERROR lifetime arguments are not allowed on builtin type + +} diff --git a/tests/ui/typeck/prim-with-args.stderr b/tests/ui/typeck/prim-with-args.stderr new file mode 100644 index 000000000..2ddad5ad7 --- /dev/null +++ b/tests/ui/typeck/prim-with-args.stderr @@ -0,0 +1,311 @@ +error[E0109]: type arguments are not allowed on builtin type `isize` + --> $DIR/prim-with-args.rs:4:15 + | +LL | let _x: isize; + | ----- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `isize` + | +help: primitive type `isize` doesn't have generic parameters + | +LL - let _x: isize; +LL + let _x: isize; + | + +error[E0109]: type arguments are not allowed on builtin type `i8` + --> $DIR/prim-with-args.rs:5:12 + | +LL | let _x: i8; + | -- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `i8` + | +help: primitive type `i8` doesn't have generic parameters + | +LL - let _x: i8; +LL + let _x: i8; + | + +error[E0109]: type arguments are not allowed on builtin type `i16` + --> $DIR/prim-with-args.rs:6:13 + | +LL | let _x: i16; + | --- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `i16` + | +help: primitive type `i16` doesn't have generic parameters + | +LL - let _x: i16; +LL + let _x: i16; + | + +error[E0109]: type arguments are not allowed on builtin type `i32` + --> $DIR/prim-with-args.rs:7:13 + | +LL | let _x: i32; + | --- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `i32` + | +help: primitive type `i32` doesn't have generic parameters + | +LL - let _x: i32; +LL + let _x: i32; + | + +error[E0109]: type arguments are not allowed on builtin type `i64` + --> $DIR/prim-with-args.rs:8:13 + | +LL | let _x: i64; + | --- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `i64` + | +help: primitive type `i64` doesn't have generic parameters + | +LL - let _x: i64; +LL + let _x: i64; + | + +error[E0109]: type arguments are not allowed on builtin type `usize` + --> $DIR/prim-with-args.rs:9:15 + | +LL | let _x: usize; + | ----- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `usize` + | +help: primitive type `usize` doesn't have generic parameters + | +LL - let _x: usize; +LL + let _x: usize; + | + +error[E0109]: type arguments are not allowed on builtin type `u8` + --> $DIR/prim-with-args.rs:10:12 + | +LL | let _x: u8; + | -- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `u8` + | +help: primitive type `u8` doesn't have generic parameters + | +LL - let _x: u8; +LL + let _x: u8; + | + +error[E0109]: type arguments are not allowed on builtin type `u16` + --> $DIR/prim-with-args.rs:11:13 + | +LL | let _x: u16; + | --- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `u16` + | +help: primitive type `u16` doesn't have generic parameters + | +LL - let _x: u16; +LL + let _x: u16; + | + +error[E0109]: type arguments are not allowed on builtin type `u32` + --> $DIR/prim-with-args.rs:12:13 + | +LL | let _x: u32; + | --- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `u32` + | +help: primitive type `u32` doesn't have generic parameters + | +LL - let _x: u32; +LL + let _x: u32; + | + +error[E0109]: type arguments are not allowed on builtin type `u64` + --> $DIR/prim-with-args.rs:13:13 + | +LL | let _x: u64; + | --- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `u64` + | +help: primitive type `u64` doesn't have generic parameters + | +LL - let _x: u64; +LL + let _x: u64; + | + +error[E0109]: type arguments are not allowed on builtin type `char` + --> $DIR/prim-with-args.rs:14:14 + | +LL | let _x: char; + | ---- ^^^^^ type argument not allowed + | | + | not allowed on builtin type `char` + | +help: primitive type `char` doesn't have generic parameters + | +LL - let _x: char; +LL + let _x: char; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `isize` + --> $DIR/prim-with-args.rs:16:15 + | +LL | let _x: isize<'static>; + | ----- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `isize` + | +help: primitive type `isize` doesn't have generic parameters + | +LL - let _x: isize<'static>; +LL + let _x: isize; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `i8` + --> $DIR/prim-with-args.rs:17:12 + | +LL | let _x: i8<'static>; + | -- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `i8` + | +help: primitive type `i8` doesn't have generic parameters + | +LL - let _x: i8<'static>; +LL + let _x: i8; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `i16` + --> $DIR/prim-with-args.rs:18:13 + | +LL | let _x: i16<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `i16` + | +help: primitive type `i16` doesn't have generic parameters + | +LL - let _x: i16<'static>; +LL + let _x: i16; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `i32` + --> $DIR/prim-with-args.rs:19:13 + | +LL | let _x: i32<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `i32` + | +help: primitive type `i32` doesn't have generic parameters + | +LL - let _x: i32<'static>; +LL + let _x: i32; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `i64` + --> $DIR/prim-with-args.rs:20:13 + | +LL | let _x: i64<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `i64` + | +help: primitive type `i64` doesn't have generic parameters + | +LL - let _x: i64<'static>; +LL + let _x: i64; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `usize` + --> $DIR/prim-with-args.rs:21:15 + | +LL | let _x: usize<'static>; + | ----- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `usize` + | +help: primitive type `usize` doesn't have generic parameters + | +LL - let _x: usize<'static>; +LL + let _x: usize; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `u8` + --> $DIR/prim-with-args.rs:22:12 + | +LL | let _x: u8<'static>; + | -- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `u8` + | +help: primitive type `u8` doesn't have generic parameters + | +LL - let _x: u8<'static>; +LL + let _x: u8; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `u16` + --> $DIR/prim-with-args.rs:23:13 + | +LL | let _x: u16<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `u16` + | +help: primitive type `u16` doesn't have generic parameters + | +LL - let _x: u16<'static>; +LL + let _x: u16; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `u32` + --> $DIR/prim-with-args.rs:24:13 + | +LL | let _x: u32<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `u32` + | +help: primitive type `u32` doesn't have generic parameters + | +LL - let _x: u32<'static>; +LL + let _x: u32; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `u64` + --> $DIR/prim-with-args.rs:25:13 + | +LL | let _x: u64<'static>; + | --- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `u64` + | +help: primitive type `u64` doesn't have generic parameters + | +LL - let _x: u64<'static>; +LL + let _x: u64; + | + +error[E0109]: lifetime arguments are not allowed on builtin type `char` + --> $DIR/prim-with-args.rs:26:14 + | +LL | let _x: char<'static>; + | ---- ^^^^^^^ lifetime argument not allowed + | | + | not allowed on builtin type `char` + | +help: primitive type `char` doesn't have generic parameters + | +LL - let _x: char<'static>; +LL + let _x: char; + | + +error: aborting due to 22 previous errors + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/typeck/project-cache-issue-37154.rs b/tests/ui/typeck/project-cache-issue-37154.rs new file mode 100644 index 000000000..b10239c22 --- /dev/null +++ b/tests/ui/typeck/project-cache-issue-37154.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(dead_code)] +// Regression test for #37154: the problem here was that the cache +// results in a false error because it was caching placeholder results +// even after those placeholder regions had been popped. + +trait Foo { + fn method(&self) {} +} + +struct Wrapper(T); + +impl Foo for Wrapper where for<'a> &'a T: IntoIterator {} + +fn f(x: Wrapper>) { + x.method(); // This works. + x.method(); // error: no method named `method` +} + +fn main() { } diff --git a/tests/ui/typeck/quiet-type-err-let-binding.rs b/tests/ui/typeck/quiet-type-err-let-binding.rs new file mode 100644 index 000000000..a6eab536a --- /dev/null +++ b/tests/ui/typeck/quiet-type-err-let-binding.rs @@ -0,0 +1,17 @@ +// fn foo() -> String { +// String::new() +// } + +fn test(s: &str) { + println!("{}", s); +} + +fn test2(s: String) { + println!("{}", s); +} + +fn main() { + let x = foo(); //~ERROR cannot find function `foo` in this scope + test(&x); + test2(x); // Does not complain about `x` being a `&str`. +} diff --git a/tests/ui/typeck/quiet-type-err-let-binding.stderr b/tests/ui/typeck/quiet-type-err-let-binding.stderr new file mode 100644 index 000000000..ad7f85e01 --- /dev/null +++ b/tests/ui/typeck/quiet-type-err-let-binding.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/quiet-type-err-let-binding.rs:14:13 + | +LL | let x = foo(); + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/typeck/remove-extra-argument.fixed b/tests/ui/typeck/remove-extra-argument.fixed new file mode 100644 index 000000000..d09306bf7 --- /dev/null +++ b/tests/ui/typeck/remove-extra-argument.fixed @@ -0,0 +1,9 @@ +// run-rustfix +// Check that the HELP suggestion is `l(vec![])` instead of `l($crate::vec::Vec::new())` +fn l(_a: Vec) {} + +fn main() { + l(vec![]) + //~^ ERROR function takes 1 argument but 2 arguments were supplied + //~| HELP remove the extra argument +} diff --git a/tests/ui/typeck/remove-extra-argument.rs b/tests/ui/typeck/remove-extra-argument.rs new file mode 100644 index 000000000..2181c37ce --- /dev/null +++ b/tests/ui/typeck/remove-extra-argument.rs @@ -0,0 +1,9 @@ +// run-rustfix +// Check that the HELP suggestion is `l(vec![])` instead of `l($crate::vec::Vec::new())` +fn l(_a: Vec) {} + +fn main() { + l(vec![], vec![]) + //~^ ERROR function takes 1 argument but 2 arguments were supplied + //~| HELP remove the extra argument +} diff --git a/tests/ui/typeck/remove-extra-argument.stderr b/tests/ui/typeck/remove-extra-argument.stderr new file mode 100644 index 000000000..b734bcd4e --- /dev/null +++ b/tests/ui/typeck/remove-extra-argument.stderr @@ -0,0 +1,19 @@ +error[E0061]: this function takes 1 argument but 2 arguments were supplied + --> $DIR/remove-extra-argument.rs:6:5 + | +LL | l(vec![], vec![]) + | ^ ------ argument of type `Vec<_>` unexpected + | +note: function defined here + --> $DIR/remove-extra-argument.rs:3:4 + | +LL | fn l(_a: Vec) {} + | ^ ----------- +help: remove the extra argument + | +LL | l(vec![]) + | ~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/typeck/return_type_containing_closure.rs b/tests/ui/typeck/return_type_containing_closure.rs new file mode 100644 index 000000000..29624e08a --- /dev/null +++ b/tests/ui/typeck/return_type_containing_closure.rs @@ -0,0 +1,10 @@ +#[allow(unused)] +fn foo() { //~ HELP a return type might be missing here + vec!['a'].iter().map(|c| c) + //~^ ERROR mismatched types [E0308] + //~| NOTE expected `()`, found struct `Map` + //~| NOTE expected unit type `()` + //~| HELP consider using a semicolon here +} + +fn main() {} diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr new file mode 100644 index 000000000..101aee395 --- /dev/null +++ b/tests/ui/typeck/return_type_containing_closure.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/return_type_containing_closure.rs:3:5 + | +LL | vec!['a'].iter().map(|c| c) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map` + | + = note: expected unit type `()` + found struct `Map, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>` +help: consider using a semicolon here + | +LL | vec!['a'].iter().map(|c| c); + | + +help: a return type might be missing here + | +LL | fn foo() -> _ { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/slow-lhs-suggestion.rs b/tests/ui/typeck/slow-lhs-suggestion.rs new file mode 100644 index 000000000..80dfd6835 --- /dev/null +++ b/tests/ui/typeck/slow-lhs-suggestion.rs @@ -0,0 +1,26 @@ +fn main() { + 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + //~^ ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment + //~| ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/typeck/slow-lhs-suggestion.stderr b/tests/ui/typeck/slow-lhs-suggestion.stderr new file mode 100644 index 000000000..c5bf795ee --- /dev/null +++ b/tests/ui/typeck/slow-lhs-suggestion.stderr @@ -0,0 +1,187 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:95 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:91 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:87 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:83 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:79 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:75 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:71 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:67 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:63 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:59 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:55 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:51 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:47 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:43 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:39 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:35 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:31 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:27 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:23 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:19 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:15 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:11 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error[E0070]: invalid left-hand side of assignment + --> $DIR/slow-lhs-suggestion.rs:2:7 + | +LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1; + | - ^ + | | + | cannot assign to this expression + +error: aborting due to 23 previous errors + +For more information about this error, try `rustc --explain E0070`. diff --git a/tests/ui/typeck/struct-enum-wrong-args.rs b/tests/ui/typeck/struct-enum-wrong-args.rs new file mode 100644 index 000000000..19de4d677 --- /dev/null +++ b/tests/ui/typeck/struct-enum-wrong-args.rs @@ -0,0 +1,14 @@ +// Regression test of #86481. +struct Wrapper(i32); +struct DoubleWrapper(i32, i32); + +fn main() { + let _ = Some(3, 2); //~ ERROR this enum variant takes + let _ = Ok(3, 6, 2); //~ ERROR this enum variant takes + let _ = Ok(); //~ ERROR this enum variant takes + let _ = Wrapper(); //~ ERROR this struct takes + let _ = Wrapper(5, 2); //~ ERROR this struct takes + let _ = DoubleWrapper(); //~ ERROR this struct takes + let _ = DoubleWrapper(5); //~ ERROR this struct takes + let _ = DoubleWrapper(5, 2, 7); //~ ERROR this struct takes +} diff --git a/tests/ui/typeck/struct-enum-wrong-args.stderr b/tests/ui/typeck/struct-enum-wrong-args.stderr new file mode 100644 index 000000000..fbced928a --- /dev/null +++ b/tests/ui/typeck/struct-enum-wrong-args.stderr @@ -0,0 +1,124 @@ +error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:6:13 + | +LL | let _ = Some(3, 2); + | ^^^^ - argument of type `{integer}` unexpected + | +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL +help: remove the extra argument + | +LL | let _ = Some(3); + | ~~~ + +error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:7:13 + | +LL | let _ = Ok(3, 6, 2); + | ^^ - - argument of type `{integer}` unexpected + | | + | argument of type `{integer}` unexpected + | +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL +help: remove the extra arguments + | +LL | let _ = Ok(3); + | ~~~ + +error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:8:13 + | +LL | let _ = Ok(); + | ^^-- an argument is missing + | +note: tuple variant defined here + --> $SRC_DIR/core/src/result.rs:LL:COL +help: provide the argument + | +LL | let _ = Ok(/* value */); + | ~~~~~~~~~~~~~ + +error[E0061]: this struct takes 1 argument but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:9:13 + | +LL | let _ = Wrapper(); + | ^^^^^^^-- an argument of type `i32` is missing + | +note: tuple struct defined here + --> $DIR/struct-enum-wrong-args.rs:2:8 + | +LL | struct Wrapper(i32); + | ^^^^^^^ +help: provide the argument + | +LL | let _ = Wrapper(/* i32 */); + | ~~~~~~~~~~~ + +error[E0061]: this struct takes 1 argument but 2 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:10:13 + | +LL | let _ = Wrapper(5, 2); + | ^^^^^^^ - argument of type `{integer}` unexpected + | +note: tuple struct defined here + --> $DIR/struct-enum-wrong-args.rs:2:8 + | +LL | struct Wrapper(i32); + | ^^^^^^^ +help: remove the extra argument + | +LL | let _ = Wrapper(5); + | ~~~ + +error[E0061]: this struct takes 2 arguments but 0 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:11:13 + | +LL | let _ = DoubleWrapper(); + | ^^^^^^^^^^^^^-- two arguments of type `i32` and `i32` are missing + | +note: tuple struct defined here + --> $DIR/struct-enum-wrong-args.rs:3:8 + | +LL | struct DoubleWrapper(i32, i32); + | ^^^^^^^^^^^^^ +help: provide the arguments + | +LL | let _ = DoubleWrapper(/* i32 */, /* i32 */); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0061]: this struct takes 2 arguments but 1 argument was supplied + --> $DIR/struct-enum-wrong-args.rs:12:13 + | +LL | let _ = DoubleWrapper(5); + | ^^^^^^^^^^^^^--- an argument of type `i32` is missing + | +note: tuple struct defined here + --> $DIR/struct-enum-wrong-args.rs:3:8 + | +LL | struct DoubleWrapper(i32, i32); + | ^^^^^^^^^^^^^ +help: provide the argument + | +LL | let _ = DoubleWrapper(5, /* i32 */); + | ~~~~~~~~~~~~~~ + +error[E0061]: this struct takes 2 arguments but 3 arguments were supplied + --> $DIR/struct-enum-wrong-args.rs:13:13 + | +LL | let _ = DoubleWrapper(5, 2, 7); + | ^^^^^^^^^^^^^ - argument of type `{integer}` unexpected + | +note: tuple struct defined here + --> $DIR/struct-enum-wrong-args.rs:3:8 + | +LL | struct DoubleWrapper(i32, i32); + | ^^^^^^^^^^^^^ +help: remove the extra argument + | +LL | let _ = DoubleWrapper(5, 2); + | ~~~~~~ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed b/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed new file mode 100644 index 000000000..ba83e7900 --- /dev/null +++ b/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +fn main() { + 2.0e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0E1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0e+12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0e-12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.0e1f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs b/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs new file mode 100644 index 000000000..c102447f6 --- /dev/null +++ b/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.rs @@ -0,0 +1,11 @@ +// run-rustfix + +fn main() { + 2.e1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.E1; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.f64; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.e+12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.e-12; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields + 2.e1f32; //~ERROR `{integer}` is a primitive type and therefore doesn't have fields +} diff --git a/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr b/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr new file mode 100644 index 000000000..503015f3b --- /dev/null +++ b/tests/ui/typeck/suggest-adding-missing-zero-to-floating-point-number.stderr @@ -0,0 +1,80 @@ +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:4:7 + | +LL | 2.e1; + | ^^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0e1; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:5:7 + | +LL | 2.E1; + | ^^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0E1; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:6:7 + | +LL | 2.f32; + | ^^^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0f32; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:7:7 + | +LL | 2.f64; + | ^^^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0f64; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:8:7 + | +LL | 2.e+12; + | ^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0e+12; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:9:7 + | +LL | 2.e-12; + | ^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0e-12; + | + + +error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields + --> $DIR/suggest-adding-missing-zero-to-floating-point-number.rs:10:7 + | +LL | 2.e1f32; + | ^^^^^ + | +help: if intended to be a floating point literal, consider adding a `0` after the period + | +LL | 2.0e1f32; + | + + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0610`. diff --git a/tests/ui/typeck/type-placeholder-fn-in-const.rs b/tests/ui/typeck/type-placeholder-fn-in-const.rs new file mode 100644 index 000000000..ab2e2d8c5 --- /dev/null +++ b/tests/ui/typeck/type-placeholder-fn-in-const.rs @@ -0,0 +1,14 @@ +struct MyStruct; + +trait Test { + const TEST: fn() -> _; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] + //~| ERROR: the placeholder `_` is not allowed within types on item signatures for constants [E0121] +} + +impl Test for MyStruct { + const TEST: fn() -> _ = 42; + //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions [E0121] +} + +fn main() {} diff --git a/tests/ui/typeck/type-placeholder-fn-in-const.stderr b/tests/ui/typeck/type-placeholder-fn-in-const.stderr new file mode 100644 index 000000000..e7b2e554a --- /dev/null +++ b/tests/ui/typeck/type-placeholder-fn-in-const.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/type-placeholder-fn-in-const.rs:4:25 + | +LL | const TEST: fn() -> _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/type-placeholder-fn-in-const.rs:4:25 + | +LL | const TEST: fn() -> _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/type-placeholder-fn-in-const.rs:10:25 + | +LL | const TEST: fn() -> _ = 42; + | ^ not allowed in type signatures + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs b/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs new file mode 100644 index 000000000..c463a8ad0 --- /dev/null +++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs @@ -0,0 +1,17 @@ +fn foo1, U>(x: T) {} +//~^ ERROR this trait takes 0 generic arguments but 1 generic argument was supplied + +trait Trait: Copy {} +//~^ ERROR this trait takes 0 generic arguments but 1 generic argument was supplied + +struct MyStruct1>; +//~^ ERROR this trait takes 0 generic arguments but 1 generic argument was supplied + +struct MyStruct2<'a, T: Copy<'a>>; +//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + +fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} +//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR this trait takes 0 generic arguments but 1 generic argument was supplied + +fn main() { } diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr new file mode 100644 index 000000000..331540d1e --- /dev/null +++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr @@ -0,0 +1,51 @@ +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:1:11 + | +LL | fn foo1, U>(x: T) {} + | ^^^^--- help: remove these generics + | | + | expected 0 generic arguments + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14 + | +LL | trait Trait: Copy {} + | ^^^^---------- help: remove these generics + | | + | expected 0 generic arguments + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21 + | +LL | struct MyStruct1>; + | ^^^^--- help: remove these generics + | | + | expected 0 generic arguments + +error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25 + | +LL | struct MyStruct2<'a, T: Copy<'a>>; + | ^^^^---- help: remove these generics + | | + | expected 0 lifetime arguments + +error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15 + | +LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} + | ^^^^ -- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15 + | +LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} + | ^^^^ - help: remove this generic argument + | | + | expected 0 generic arguments + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/typeck-cast-pointer-to-float.rs b/tests/ui/typeck/typeck-cast-pointer-to-float.rs new file mode 100644 index 000000000..2af7a3cf2 --- /dev/null +++ b/tests/ui/typeck/typeck-cast-pointer-to-float.rs @@ -0,0 +1,5 @@ +fn main() { + let x : i16 = 22; + ((&x) as *const i16) as f32; + //~^ ERROR casting `*const i16` as `f32` is invalid +} diff --git a/tests/ui/typeck/typeck-cast-pointer-to-float.stderr b/tests/ui/typeck/typeck-cast-pointer-to-float.stderr new file mode 100644 index 000000000..81d968454 --- /dev/null +++ b/tests/ui/typeck/typeck-cast-pointer-to-float.stderr @@ -0,0 +1,9 @@ +error[E0606]: casting `*const i16` as `f32` is invalid + --> $DIR/typeck-cast-pointer-to-float.rs:3:5 + | +LL | ((&x) as *const i16) as f32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs b/tests/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs new file mode 100644 index 000000000..2530a1e96 --- /dev/null +++ b/tests/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs @@ -0,0 +1,9 @@ +// run-pass + +unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () { + func() +} + +pub fn main() { + unsafe { call_unsafe(|| {}); } +} diff --git a/tests/ui/typeck/typeck-default-trait-impl-assoc-type.fixed b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.fixed new file mode 100644 index 000000000..a9107f998 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.fixed @@ -0,0 +1,17 @@ +// run-rustfix +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). +#![allow(dead_code)] + +trait Trait { + type AssocType; + fn dummy(&self) { } +} +fn bar() where ::AssocType: Send { + is_send::(); //~ ERROR E0277 +} + +fn is_send() { +} + +fn main() { } diff --git a/tests/ui/typeck/typeck-default-trait-impl-assoc-type.rs b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.rs new file mode 100644 index 000000000..bafc16577 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.rs @@ -0,0 +1,17 @@ +// run-rustfix +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). +#![allow(dead_code)] + +trait Trait { + type AssocType; + fn dummy(&self) { } +} +fn bar() { + is_send::(); //~ ERROR E0277 +} + +fn is_send() { +} + +fn main() { } diff --git a/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr new file mode 100644 index 000000000..468a14762 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -0,0 +1,20 @@ +error[E0277]: `::AssocType` cannot be sent between threads safely + --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:15 + | +LL | is_send::(); + | ^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `::AssocType` +note: required by a bound in `is_send` + --> $DIR/typeck-default-trait-impl-assoc-type.rs:14:14 + | +LL | fn is_send() { + | ^^^^ required by this bound in `is_send` +help: consider further restricting the associated type + | +LL | fn bar() where ::AssocType: Send { + | +++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs new file mode 100644 index 000000000..cc75cd490 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs @@ -0,0 +1,25 @@ +// aux-build:tdticc_coherence_lib.rs +#![allow(suspicious_auto_trait_impls)] + +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). + +#![feature(negative_impls)] + +extern crate tdticc_coherence_lib as lib; + +use lib::DefaultedTrait; + +struct A; +impl DefaultedTrait for (A,) { } //~ ERROR E0117 + +struct B; +impl !DefaultedTrait for (B,) { } //~ ERROR E0117 + +struct C; +struct D(T); +impl DefaultedTrait for Box { } //~ ERROR E0321 +impl DefaultedTrait for lib::Something { } //~ ERROR E0117 +impl DefaultedTrait for D { } // OK + +fn main() { } diff --git a/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr new file mode 100644 index 000000000..fc3778b79 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr @@ -0,0 +1,43 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:14:1 + | +LL | impl DefaultedTrait for (A,) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^---- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:17:1 + | +LL | impl !DefaultedTrait for (B,) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^---- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0321]: cross-crate traits with a default impl, like `DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:21:1 + | +LL | impl DefaultedTrait for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate + +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:22:1 + | +LL | impl DefaultedTrait for lib::Something { } + | ^^^^^^^^^^^^^^^^^^^^^^^^----------------- + | | | + | | `Something` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0117, E0321. +For more information about an error, try `rustc --explain E0117`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-send.rs b/tests/ui/typeck/typeck-default-trait-impl-negation-send.rs new file mode 100644 index 000000000..3a2fc39d4 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-send.rs @@ -0,0 +1,21 @@ +#![feature(negative_impls)] + +struct MySendable { + t: *mut u8 +} + +unsafe impl Send for MySendable {} + +struct MyNotSendable { + t: *mut u8 +} + +impl !Send for MyNotSendable {} + +fn is_send() {} + +fn main() { + is_send::(); + is_send::(); + //~^ ERROR `MyNotSendable` cannot be sent between threads safely +} diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr new file mode 100644 index 000000000..2ce32990e --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-send.stderr @@ -0,0 +1,16 @@ +error[E0277]: `MyNotSendable` cannot be sent between threads safely + --> $DIR/typeck-default-trait-impl-negation-send.rs:19:15 + | +LL | is_send::(); + | ^^^^^^^^^^^^^ `MyNotSendable` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `MyNotSendable` +note: required by a bound in `is_send` + --> $DIR/typeck-default-trait-impl-negation-send.rs:15:15 + | +LL | fn is_send() {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.rs b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.rs new file mode 100644 index 000000000..b9042188a --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.rs @@ -0,0 +1,41 @@ +#![feature(negative_impls)] + +struct Managed; +impl !Send for Managed {} +impl !Sync for Managed {} + +use std::cell::UnsafeCell; + +struct MySync { + t: *mut u8 +} + +unsafe impl Sync for MySync {} + +struct MyNotSync { + t: *mut u8 +} + +impl !Sync for MyNotSync {} + +struct MyTypeWUnsafe { + t: UnsafeCell +} + +struct MyTypeManaged { + t: Managed +} + +fn is_sync() {} + +fn main() { + is_sync::(); + is_sync::(); + //~^ ERROR `MyNotSync` cannot be shared between threads safely [E0277] + + is_sync::(); + //~^ ERROR `UnsafeCell` cannot be shared between threads safely [E0277] + + is_sync::(); + //~^ ERROR `Managed` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr new file mode 100644 index 000000000..b9fca1a1b --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -0,0 +1,52 @@ +error[E0277]: `MyNotSync` cannot be shared between threads safely + --> $DIR/typeck-default-trait-impl-negation-sync.rs:33:15 + | +LL | is_sync::(); + | ^^^^^^^^^ `MyNotSync` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `MyNotSync` +note: required by a bound in `is_sync` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 + | +LL | fn is_sync() {} + | ^^^^ required by this bound in `is_sync` + +error[E0277]: `UnsafeCell` cannot be shared between threads safely + --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:15 + | +LL | is_sync::(); + | ^^^^^^^^^^^^^ `UnsafeCell` cannot be shared between threads safely + | + = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell` +note: required because it appears within the type `MyTypeWUnsafe` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:21:8 + | +LL | struct MyTypeWUnsafe { + | ^^^^^^^^^^^^^ +note: required by a bound in `is_sync` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 + | +LL | fn is_sync() {} + | ^^^^ required by this bound in `is_sync` + +error[E0277]: `Managed` cannot be shared between threads safely + --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:15 + | +LL | is_sync::(); + | ^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely + | + = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed` +note: required because it appears within the type `MyTypeManaged` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:25:8 + | +LL | struct MyTypeManaged { + | ^^^^^^^^^^^^^ +note: required by a bound in `is_sync` + --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 + | +LL | fn is_sync() {} + | ^^^^ required by this bound in `is_sync` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck-default-trait-impl-send-param.rs b/tests/ui/typeck/typeck-default-trait-impl-send-param.rs new file mode 100644 index 000000000..7948cd101 --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-send-param.rs @@ -0,0 +1,11 @@ +// Test that we do not consider parameter types to be sendable without +// an explicit trait bound. + +fn foo() { + is_send::() //~ ERROR E0277 +} + +fn is_send() { +} + +fn main() { } diff --git a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr new file mode 100644 index 000000000..887a1ddbb --- /dev/null +++ b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -0,0 +1,19 @@ +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/typeck-default-trait-impl-send-param.rs:5:15 + | +LL | is_send::() + | ^ `T` cannot be sent between threads safely + | +note: required by a bound in `is_send` + --> $DIR/typeck-default-trait-impl-send-param.rs:8:14 + | +LL | fn is_send() { + | ^^^^ required by this bound in `is_send` +help: consider restricting type parameter `T` + | +LL | fn foo() { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs b/tests/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs new file mode 100644 index 000000000..1e954f569 --- /dev/null +++ b/tests/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs @@ -0,0 +1,12 @@ +// run-pass +// This tests reification from safe function to `unsafe fn` pointer + +fn do_nothing() -> () {} + +unsafe fn call_unsafe(func: unsafe fn() -> ()) -> () { + func() +} + +pub fn main() { + unsafe { call_unsafe(do_nothing); } +} diff --git a/tests/ui/typeck/typeck-unsafe-always-share.rs b/tests/ui/typeck/typeck-unsafe-always-share.rs new file mode 100644 index 000000000..be87ab172 --- /dev/null +++ b/tests/ui/typeck/typeck-unsafe-always-share.rs @@ -0,0 +1,32 @@ +// Verify that UnsafeCell is *always* !Sync regardless if `T` is sync. + +#![feature(negative_impls)] + +use std::cell::UnsafeCell; +use std::marker::Sync; + +struct MySync { + u: UnsafeCell +} + +struct NoSync; +impl !Sync for NoSync {} + +fn test(s: T) {} + +fn main() { + let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0)}); + test(us); + //~^ ERROR `UnsafeCell>` cannot be shared between threads safely + + let uns = UnsafeCell::new(NoSync); + test(uns); + //~^ ERROR `UnsafeCell` cannot be shared between threads safely [E0277] + + let ms = MySync{u: uns}; + test(ms); + //~^ ERROR `UnsafeCell` cannot be shared between threads safely [E0277] + + test(NoSync); + //~^ ERROR `NoSync` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/typeck/typeck-unsafe-always-share.stderr b/tests/ui/typeck/typeck-unsafe-always-share.stderr new file mode 100644 index 000000000..154e50499 --- /dev/null +++ b/tests/ui/typeck/typeck-unsafe-always-share.stderr @@ -0,0 +1,68 @@ +error[E0277]: `UnsafeCell>` cannot be shared between threads safely + --> $DIR/typeck-unsafe-always-share.rs:19:10 + | +LL | test(us); + | ---- ^^ `UnsafeCell>` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `UnsafeCell>` +note: required by a bound in `test` + --> $DIR/typeck-unsafe-always-share.rs:15:12 + | +LL | fn test(s: T) {} + | ^^^^ required by this bound in `test` + +error[E0277]: `UnsafeCell` cannot be shared between threads safely + --> $DIR/typeck-unsafe-always-share.rs:23:10 + | +LL | test(uns); + | ---- ^^^ `UnsafeCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `UnsafeCell` +note: required by a bound in `test` + --> $DIR/typeck-unsafe-always-share.rs:15:12 + | +LL | fn test(s: T) {} + | ^^^^ required by this bound in `test` + +error[E0277]: `UnsafeCell` cannot be shared between threads safely + --> $DIR/typeck-unsafe-always-share.rs:27:10 + | +LL | test(ms); + | ---- ^^ `UnsafeCell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `MySync`, the trait `Sync` is not implemented for `UnsafeCell` +note: required because it appears within the type `MySync` + --> $DIR/typeck-unsafe-always-share.rs:8:8 + | +LL | struct MySync { + | ^^^^^^ +note: required by a bound in `test` + --> $DIR/typeck-unsafe-always-share.rs:15:12 + | +LL | fn test(s: T) {} + | ^^^^ required by this bound in `test` + +error[E0277]: `NoSync` cannot be shared between threads safely + --> $DIR/typeck-unsafe-always-share.rs:30:10 + | +LL | test(NoSync); + | ---- ^^^^^^ `NoSync` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `NoSync` +note: required by a bound in `test` + --> $DIR/typeck-unsafe-always-share.rs:15:12 + | +LL | fn test(s: T) {} + | ^^^^ required by this bound in `test` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/typeck_type_placeholder_1.rs b/tests/ui/typeck/typeck_type_placeholder_1.rs new file mode 100644 index 000000000..ea7aa5285 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_1.rs @@ -0,0 +1,32 @@ +// run-pass + +#![allow(dead_code)] +// This test checks that the `_` type placeholder works +// correctly for enabling type inference. + + +struct TestStruct { + x: *const isize +} + +unsafe impl Sync for TestStruct {} + +static CONSTEXPR: TestStruct = TestStruct{ x: &413 }; + + +pub fn main() { + let x: Vec<_> = (0..5).collect(); + let expected: &[usize] = &[0,1,2,3,4]; + assert_eq!(x, expected); + + let x = (0..5).collect::>(); + assert_eq!(x, expected); + + let y: _ = "hello"; + assert_eq!(y.len(), 5); + + let ptr: &usize = &5; + let ptr2 = ptr as *const _; + + assert_eq!(ptr as *const usize as usize, ptr2 as usize); +} diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs new file mode 100644 index 000000000..b96c52713 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -0,0 +1,230 @@ +// Needed for `type Y = impl Trait<_>` and `type B = _;` +#![feature(associated_type_defaults)] +#![feature(type_alias_impl_trait)] +// This test checks that it is not possible to enable global type +// inference by using the `_` type placeholder. + +fn test() -> _ { 5 } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + +fn test2() -> (_, _) { (5, 5) } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + +static TEST3: _ = "test"; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + +static TEST4: _ = 145; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + +static TEST5: (_, _) = (1, 2); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + +fn test6(_: _) { } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn test6_b(_: _, _: T) { } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn test6_c(_: _, _: (T, K, L, A, B)) { } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn test7(x: _) { let _x: usize = x; } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn test8(_f: fn() -> _) { } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +//~^^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +struct Test9; + +impl Test9 { + fn test9(&self) -> _ { () } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + + fn test10(&self, _x : _) { } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +fn test11(x: &usize) -> &_ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + &x +} + +unsafe fn test12(x: *const usize) -> *const *const _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + &x +} + +impl Clone for Test9 { + fn clone(&self) -> _ { Test9 } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + + fn clone_from(&mut self, other: _) { *self = Test9; } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +struct Test10 { + a: _, + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs + b: (_, _), +} + +pub fn main() { + static A = 42; + //~^ ERROR missing type for `static` item + static B: _ = 42; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + static C: Option<_> = Some(42); + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + fn fn_test() -> _ { 5 } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + + fn fn_test2() -> (_, _) { (5, 5) } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + + static FN_TEST3: _ = "test"; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + + static FN_TEST4: _ = 145; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + + static FN_TEST5: (_, _) = (1, 2); + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables + + fn fn_test6(_: _) { } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + + fn fn_test7(x: _) { let _x: usize = x; } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + + fn fn_test8(_f: fn() -> _) { } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + //~^^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + + struct FnTest9; + + impl FnTest9 { + fn fn_test9(&self) -> _ { () } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + + fn fn_test10(&self, _x : _) { } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + } + + impl Clone for FnTest9 { + fn clone(&self) -> _ { FnTest9 } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + + fn clone_from(&mut self, other: _) { *self = FnTest9; } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + } + + struct FnTest10 { + a: _, + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for structs + b: (_, _), + } + + fn fn_test11(_: _) -> (_, _) { panic!() } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + //~| ERROR type annotations needed + + fn fn_test12(x: i32) -> (_, _) { (x, x) } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + + fn fn_test13(x: _) -> (i32, _) { (x, x) } + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types +} + +trait T { + fn method_test1(&self, x: _); + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn method_test2(&self, x: _) -> _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn method_test3(&self) -> _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn assoc_fn_test1(x: _); + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn assoc_fn_test2(x: _) -> _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + fn assoc_fn_test3() -> _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +} + +struct BadStruct<_>(_); +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs +trait BadTrait<_> {} +//~^ ERROR expected identifier, found reserved identifier `_` +impl BadTrait<_> for BadStruct<_> {} +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for implementations + +fn impl_trait() -> impl BadTrait<_> { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types + unimplemented!() +} + +struct BadStruct1<_, _>(_); +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR expected identifier, found reserved identifier `_` +//~| ERROR the name `_` is already used +//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs +struct BadStruct2<_, T>(_, T); +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR the placeholder `_` is not allowed within types on item signatures for structs + +type X = Box<_>; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for type aliases + +struct Struct; +trait Trait {} +impl Trait for Struct {} +type Y = impl Trait<_>; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types +fn foo() -> Y { + Struct +} + +trait Qux { + type A; + type B = _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types + const C: _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + const D: _ = 42; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + // type E: _; // FIXME: make the parser propagate the existence of `B` + type F: std::ops::Fn(_); + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl Qux for Struct { + type A = _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types + type B = _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types + const C: _; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + //~| ERROR associated constant in `impl` without body + const D: _ = 42; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} + +fn map(_: fn() -> Option<&'static T>) -> Option { + None +} + +fn value() -> Option<&'static _> { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Option::<&'static u8>::None +} + +const _: Option<_> = map(value); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + +fn evens_squared(n: usize) -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + (1..n).filter(|x| x % 2 == 0).map(|x| x * x) +} + +const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr new file mode 100644 index 000000000..bc02547c6 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -0,0 +1,663 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/typeck_type_placeholder_item.rs:154:18 + | +LL | struct BadStruct<_>(_); + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/typeck_type_placeholder_item.rs:157:16 + | +LL | trait BadTrait<_> {} + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/typeck_type_placeholder_item.rs:167:19 + | +LL | struct BadStruct1<_, _>(_); + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/typeck_type_placeholder_item.rs:167:22 + | +LL | struct BadStruct1<_, _>(_); + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/typeck_type_placeholder_item.rs:172:19 + | +LL | struct BadStruct2<_, T>(_, T); + | ^ expected identifier, found reserved identifier + +error: associated constant in `impl` without body + --> $DIR/typeck_type_placeholder_item.rs:205:5 + | +LL | const C: _; + | ^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters + --> $DIR/typeck_type_placeholder_item.rs:167:22 + | +LL | struct BadStruct1<_, _>(_); + | - ^ already used + | | + | first use of `_` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:7:14 + | +LL | fn test() -> _ { 5 } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:10:16 + | +LL | fn test2() -> (_, _) { (5, 5) } + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures + | help: replace with the correct return type: `(i32, i32)` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:13:15 + | +LL | static TEST3: _ = "test"; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `&str` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:16:15 + | +LL | static TEST4: _ = 145; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:19:15 + | +LL | static TEST5: (_, _) = (1, 2); + | ^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:22:13 + | +LL | fn test6(_: _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test6(_: T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:25:18 + | +LL | fn test6_b(_: _, _: T) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test6_b(_: U, _: T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:28:30 + | +LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test6_c(_: U, _: (T, K, L, A, B)) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:31:13 + | +LL | fn test7(x: _) { let _x: usize = x; } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test7(x: T) { let _x: usize = x; } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:34:22 + | +LL | fn test8(_f: fn() -> _) { } + | ^ + | | + | not allowed in type signatures + | help: use type parameters instead: `T` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:34:22 + | +LL | fn test8(_f: fn() -> _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test8(_f: fn() -> T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:48:26 + | +LL | fn test11(x: &usize) -> &_ { + | -^ + | || + | |not allowed in type signatures + | help: replace with the correct return type: `&'static &'static usize` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:53:52 + | +LL | unsafe fn test12(x: *const usize) -> *const *const _ { + | --------------^ + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `*const *const usize` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:67:8 + | +LL | a: _, + | ^ not allowed in type signatures +LL | +LL | b: (_, _), + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL ~ struct Test10 { +LL ~ a: T, +LL | +LL ~ b: (T, T), + | + +error: missing type for `static` item + --> $DIR/typeck_type_placeholder_item.rs:73:13 + | +LL | static A = 42; + | ^ help: provide a type for the static variable: `: i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:75:15 + | +LL | static B: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:77:15 + | +LL | static C: Option<_> = Some(42); + | ^^^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:79:21 + | +LL | fn fn_test() -> _ { 5 } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:82:23 + | +LL | fn fn_test2() -> (_, _) { (5, 5) } + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures + | help: replace with the correct return type: `(i32, i32)` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:85:22 + | +LL | static FN_TEST3: _ = "test"; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `&str` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:88:22 + | +LL | static FN_TEST4: _ = 145; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/typeck_type_placeholder_item.rs:91:22 + | +LL | static FN_TEST5: (_, _) = (1, 2); + | ^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:94:20 + | +LL | fn fn_test6(_: _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fn_test6(_: T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:97:20 + | +LL | fn fn_test7(x: _) { let _x: usize = x; } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fn_test7(x: T) { let _x: usize = x; } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:100:29 + | +LL | fn fn_test8(_f: fn() -> _) { } + | ^ + | | + | not allowed in type signatures + | help: use type parameters instead: `T` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:100:29 + | +LL | fn fn_test8(_f: fn() -> _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fn_test8(_f: fn() -> T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:123:12 + | +LL | a: _, + | ^ not allowed in type signatures +LL | +LL | b: (_, _), + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL ~ struct FnTest10 { +LL ~ a: T, +LL | +LL ~ b: (T, T), + | + +error[E0282]: type annotations needed + --> $DIR/typeck_type_placeholder_item.rs:128:18 + | +LL | fn fn_test11(_: _) -> (_, _) { panic!() } + | ^ cannot infer type + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:128:28 + | +LL | fn fn_test11(_: _) -> (_, _) { panic!() } + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:132:30 + | +LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } + | -^--^- + | || | + | || not allowed in type signatures + | |not allowed in type signatures + | help: replace with the correct return type: `(i32, i32)` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:135:33 + | +LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } + | ------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `(i32, i32)` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:154:21 + | +LL | struct BadStruct<_>(_); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct BadStruct(T); + | ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations + --> $DIR/typeck_type_placeholder_item.rs:159:15 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | impl BadTrait for BadStruct {} + | +++ ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types + --> $DIR/typeck_type_placeholder_item.rs:162:34 + | +LL | fn impl_trait() -> impl BadTrait<_> { + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:167:25 + | +LL | struct BadStruct1<_, _>(_); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct BadStruct1(T); + | ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:172:25 + | +LL | struct BadStruct2<_, T>(_, T); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct BadStruct2(U, T); + | ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases + --> $DIR/typeck_type_placeholder_item.rs:176:14 + | +LL | type X = Box<_>; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types + --> $DIR/typeck_type_placeholder_item.rs:182:21 + | +LL | type Y = impl Trait<_>; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:216:31 + | +LL | fn value() -> Option<&'static _> { + | ----------------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Option<&'static u8>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:221:10 + | +LL | const _: Option<_> = map(value); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Option` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:224:31 + | +LL | fn evens_squared(n: usize) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Iterator` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:229:10 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^ not allowed in type signatures + | +note: however, the inferred type `Map, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:229:14 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:140:31 + | +LL | fn method_test1(&self, x: _); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn method_test1(&self, x: T); + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:142:31 + | +LL | fn method_test2(&self, x: _) -> _; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn method_test2(&self, x: T) -> T; + | +++ ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:144:31 + | +LL | fn method_test3(&self) -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn method_test3(&self) -> T; + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:146:26 + | +LL | fn assoc_fn_test1(x: _); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn assoc_fn_test1(x: T); + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:148:26 + | +LL | fn assoc_fn_test2(x: _) -> _; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn assoc_fn_test2(x: T) -> T; + | +++ ~ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:150:28 + | +LL | fn assoc_fn_test3() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn assoc_fn_test3() -> T; + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:190:14 + | +LL | type B = _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:192:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:194:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:197:26 + | +LL | type F: std::ops::Fn(_); + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:41:24 + | +LL | fn test9(&self) -> _ { () } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `()` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:44:27 + | +LL | fn test10(&self, _x : _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test10(&self, _x : T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:59:24 + | +LL | fn clone(&self) -> _ { Test9 } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone(&self) -> Test9 { Test9 } + | ~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:62:37 + | +LL | fn clone_from(&mut self, other: _) { *self = Test9; } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone_from(&mut self, other: &Test9) { *self = Test9; } + | ~~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:107:31 + | +LL | fn fn_test9(&self) -> _ { () } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `()` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:110:34 + | +LL | fn fn_test10(&self, _x : _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fn_test10(&self, _x : T) { } + | +++ ~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:115:28 + | +LL | fn clone(&self) -> _ { FnTest9 } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone(&self) -> FnTest9 { FnTest9 } + | ~~~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:118:41 + | +LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } + | ^ not allowed in type signatures + | +help: try replacing `_` with the type in the corresponding trait method signature + | +LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } + | ~~~~~~~~ + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:201:14 + | +LL | type A = _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/typeck_type_placeholder_item.rs:203:14 + | +LL | type B = _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:205:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:208:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error: aborting due to 71 previous errors + +Some errors have detailed explanations: E0121, E0282, E0403. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item_help.rs b/tests/ui/typeck/typeck_type_placeholder_item_help.rs new file mode 100644 index 000000000..c459d8c3c --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_item_help.rs @@ -0,0 +1,33 @@ +// This test checks that it proper item type will be suggested when +// using the `_` type placeholder. + +fn test1() -> _ { Some(42) } +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + +const TEST2: _ = 42u32; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + +const TEST3: _ = Some(42); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + +const TEST4: fn() -> _ = 42; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions +//~| ERROR the placeholder `_` is not allowed within types on item signatures for constant items + +trait Test5 { + const TEST5: _ = 42; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} + +struct Test6; + +impl Test6 { + const TEST6: _ = 13; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} + +pub fn main() { + let _: Option = test1(); + let _: f64 = test1(); + let _: Option = test1(); +} diff --git a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr new file mode 100644 index 000000000..07a5dbd93 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr @@ -0,0 +1,60 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item_help.rs:4:15 + | +LL | fn test1() -> _ { Some(42) } + | ^ + | | + | not allowed in type signatures + | help: replace with the correct return type: `Option` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item_help.rs:7:14 + | +LL | const TEST2: _ = 42u32; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `u32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item_help.rs:10:14 + | +LL | const TEST3: _ = Some(42); + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Option` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item_help.rs:13:22 + | +LL | const TEST4: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constant items + --> $DIR/typeck_type_placeholder_item_help.rs:13:22 + | +LL | const TEST4: fn() -> _ = 42; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item_help.rs:18:18 + | +LL | const TEST5: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item_help.rs:25:18 + | +LL | const TEST6: _ = 13; + | ^ + | | + | not allowed in type signatures + | help: replace with the correct type: `i32` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs new file mode 100644 index 000000000..43e46c5b6 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs @@ -0,0 +1,11 @@ +// This test checks that the `_` type placeholder does not react +// badly if put as a lifetime parameter. + +struct Foo<'a, T:'a> { + r: &'a T +} + +pub fn main() { + let c: Foo<_, _> = Foo { r: &5 }; + //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied +} diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr new file mode 100644 index 000000000..a89c6b85c --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr @@ -0,0 +1,17 @@ +error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/typeck_type_placeholder_lifetime_1.rs:9:12 + | +LL | let c: Foo<_, _> = Foo { r: &5 }; + | ^^^ - help: remove this generic argument + | | + | expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/typeck_type_placeholder_lifetime_1.rs:4:8 + | +LL | struct Foo<'a, T:'a> { + | ^^^ - + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs new file mode 100644 index 000000000..178b8b122 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs @@ -0,0 +1,11 @@ +// This test checks that the `_` type placeholder does not react +// badly if put as a lifetime parameter. + +struct Foo<'a, T:'a> { + r: &'a T +} + +pub fn main() { + let c: Foo<_, usize> = Foo { r: &5 }; + //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied +} diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr new file mode 100644 index 000000000..f30766bdf --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr @@ -0,0 +1,17 @@ +error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/typeck_type_placeholder_lifetime_2.rs:9:12 + | +LL | let c: Foo<_, usize> = Foo { r: &5 }; + | ^^^ ----- help: remove this generic argument + | | + | expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/typeck_type_placeholder_lifetime_2.rs:4:8 + | +LL | struct Foo<'a, T:'a> { + | ^^^ - + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/typeck_type_placeholder_mismatch.rs b/tests/ui/typeck/typeck_type_placeholder_mismatch.rs new file mode 100644 index 000000000..2f9cfcf8d --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_mismatch.rs @@ -0,0 +1,27 @@ +// This test checks that genuine type errors with partial +// type hints are understandable. + +use std::marker::PhantomData; + +struct Foo(PhantomData); +struct Bar(PhantomData); + +pub fn main() { +} + +fn test1() { + let x: Foo<_> = Bar::(PhantomData); + //~^ ERROR mismatched types + //~| expected struct `Foo<_>` + //~| found struct `Bar` + //~| expected struct `Foo`, found struct `Bar` + let y: Foo = x; +} + +fn test2() { + let x: Foo<_> = Bar::(PhantomData); + //~^ ERROR mismatched types + //~| expected struct `Foo<_>` + //~| found struct `Bar` + //~| expected struct `Foo`, found struct `Bar` +} diff --git a/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr b/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr new file mode 100644 index 000000000..867412a24 --- /dev/null +++ b/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/typeck_type_placeholder_mismatch.rs:13:21 + | +LL | let x: Foo<_> = Bar::(PhantomData); + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar` + | | + | expected due to this + | + = note: expected struct `Foo<_>` + found struct `Bar` + +error[E0308]: mismatched types + --> $DIR/typeck_type_placeholder_mismatch.rs:22:21 + | +LL | let x: Foo<_> = Bar::(PhantomData); + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar` + | | + | expected due to this + | + = note: expected struct `Foo<_>` + found struct `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/ufcs-type-params.rs b/tests/ui/typeck/ufcs-type-params.rs new file mode 100644 index 000000000..eee2b55b2 --- /dev/null +++ b/tests/ui/typeck/ufcs-type-params.rs @@ -0,0 +1,15 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Foo { + fn get(&self) -> T; +} + +impl Foo for i32 { + fn get(&self) -> i32 { *self } +} + +fn main() { + let x: i32 = 1; + Foo::::get(&x); +} diff --git a/tests/ui/typeck/unify-return-ty.rs b/tests/ui/typeck/unify-return-ty.rs new file mode 100644 index 000000000..da1d82e89 --- /dev/null +++ b/tests/ui/typeck/unify-return-ty.rs @@ -0,0 +1,16 @@ +// run-pass +// Tests that the tail expr in null() has its type +// unified with the type *T, and so the type variable +// in that type gets resolved. + +// pretty-expanded FIXME #23616 + +use std::mem; + +fn null() -> *const T { + unsafe { + mem::transmute(0_usize) + } +} + +pub fn main() { null::(); } diff --git a/tests/ui/typeck/while-loop-block-cond.rs b/tests/ui/typeck/while-loop-block-cond.rs new file mode 100644 index 000000000..929759766 --- /dev/null +++ b/tests/ui/typeck/while-loop-block-cond.rs @@ -0,0 +1,4 @@ +fn main() { + while {} {} + //~^ ERROR mismatched types [E0308] +} diff --git a/tests/ui/typeck/while-loop-block-cond.stderr b/tests/ui/typeck/while-loop-block-cond.stderr new file mode 100644 index 000000000..598273af9 --- /dev/null +++ b/tests/ui/typeck/while-loop-block-cond.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/while-loop-block-cond.rs:2:11 + | +LL | while {} {} + | ^^ expected `bool`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeid-intrinsic.rs b/tests/ui/typeid-intrinsic.rs new file mode 100644 index 000000000..5bc4e0c21 --- /dev/null +++ b/tests/ui/typeid-intrinsic.rs @@ -0,0 +1,97 @@ +// run-pass + +#![allow(deprecated)] +// aux-build:typeid-intrinsic-aux1.rs +// aux-build:typeid-intrinsic-aux2.rs + +#![feature(core_intrinsics)] + +extern crate typeid_intrinsic_aux1 as other1; +extern crate typeid_intrinsic_aux2 as other2; + +use std::hash::{SipHasher, Hasher, Hash}; +use std::any::TypeId; + +struct A; +struct Test; + +pub fn main() { + assert_eq!(TypeId::of::(), other1::id_A()); + assert_eq!(TypeId::of::(), other1::id_B()); + assert_eq!(TypeId::of::(), other1::id_C()); + assert_eq!(TypeId::of::(), other1::id_D()); + assert_eq!(TypeId::of::(), other1::id_E()); + assert_eq!(TypeId::of::(), other1::id_F()); + assert_eq!(TypeId::of::(), other1::id_G()); + assert_eq!(TypeId::of::(), other1::id_H()); + assert_eq!(TypeId::of::(), other1::id_I()); + + assert_eq!(TypeId::of::(), other2::id_A()); + assert_eq!(TypeId::of::(), other2::id_B()); + assert_eq!(TypeId::of::(), other2::id_C()); + assert_eq!(TypeId::of::(), other2::id_D()); + assert_eq!(TypeId::of::(), other2::id_E()); + assert_eq!(TypeId::of::(), other2::id_F()); + assert_eq!(TypeId::of::(), other2::id_G()); + assert_eq!(TypeId::of::(), other2::id_H()); + assert_eq!(TypeId::of::(), other2::id_I()); + + assert_eq!(other1::id_F(), other2::id_F()); + assert_eq!(other1::id_G(), other2::id_G()); + assert_eq!(other1::id_H(), other2::id_H()); + assert_eq!(other1::id_I(), other2::id_I()); + + assert_eq!(TypeId::of::(), other2::foo::()); + assert_eq!(TypeId::of::(), other1::foo::()); + assert_eq!(other2::foo::(), other1::foo::()); + assert_eq!(TypeId::of::(), other2::foo::()); + assert_eq!(TypeId::of::(), other1::foo::()); + assert_eq!(other2::foo::(), other1::foo::()); + + // sanity test of TypeId + let (a, b, c) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + let (d, e, f) = (TypeId::of::(), TypeId::of::<&'static str>(), + TypeId::of::()); + + assert!(a != b); + assert!(a != c); + assert!(b != c); + + assert_eq!(a, d); + assert_eq!(b, e); + assert_eq!(c, f); + + // check it has a hash + let (a, b) = (TypeId::of::(), TypeId::of::()); + + let mut s1 = SipHasher::new(); + a.hash(&mut s1); + let mut s2 = SipHasher::new(); + b.hash(&mut s2); + + assert_eq!(s1.finish(), s2.finish()); + + // Check projections + + assert_eq!(TypeId::of::(), other1::id_i32_iterator()); + assert_eq!(TypeId::of::(), other1::id_u32_iterator()); + assert_eq!(other1::id_i32_iterator(), other2::id_i32_iterator()); + assert_eq!(other1::id_u32_iterator(), other2::id_u32_iterator()); + assert_ne!(other1::id_i32_iterator(), other1::id_u32_iterator()); + assert_ne!(TypeId::of::(), TypeId::of::()); + + // Check fn pointer against collisions + assert_ne!( + TypeId::of:: A) -> A>(), + TypeId::of:: A, A) -> A>() + ); + assert_ne!( + TypeId::of:: fn(&'a i32) -> &'a i32>(), + TypeId::of:: fn(&'a i32) -> &'static i32>() + ); + assert_ne!( + TypeId::of:: fn(&'a i32, &'b i32) -> &'a i32>(), + TypeId::of:: fn(&'b i32, &'a i32) -> &'a i32>() + ); +} diff --git a/tests/ui/typeof/issue-100183.rs b/tests/ui/typeof/issue-100183.rs new file mode 100644 index 000000000..13e9493ea --- /dev/null +++ b/tests/ui/typeof/issue-100183.rs @@ -0,0 +1,6 @@ +struct Struct { + y: (typeof("hey"),), + //~^ ERROR `typeof` is a reserved keyword but unimplemented +} + +fn main() {} diff --git a/tests/ui/typeof/issue-100183.stderr b/tests/ui/typeof/issue-100183.stderr new file mode 100644 index 000000000..01d3079b2 --- /dev/null +++ b/tests/ui/typeof/issue-100183.stderr @@ -0,0 +1,14 @@ +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/issue-100183.rs:2:9 + | +LL | y: (typeof("hey"),), + | ^^^^^^^^^^^^^ reserved keyword + | +help: consider replacing `typeof(...)` with an actual type + | +LL | y: (&'static str,), + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0516`. diff --git a/tests/ui/typeof/issue-29184.rs b/tests/ui/typeof/issue-29184.rs new file mode 100644 index 000000000..c77e364c3 --- /dev/null +++ b/tests/ui/typeof/issue-29184.rs @@ -0,0 +1,3 @@ +fn main() { + let x: typeof(92) = 92; //~ ERROR `typeof` is a reserved keyword +} diff --git a/tests/ui/typeof/issue-29184.stderr b/tests/ui/typeof/issue-29184.stderr new file mode 100644 index 000000000..75b6c64f2 --- /dev/null +++ b/tests/ui/typeof/issue-29184.stderr @@ -0,0 +1,14 @@ +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/issue-29184.rs:2:12 + | +LL | let x: typeof(92) = 92; + | ^^^^^^^^^^ reserved keyword + | +help: consider replacing `typeof(...)` with an actual type + | +LL | let x: i32 = 92; + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0516`. diff --git a/tests/ui/typeof/issue-42060.rs b/tests/ui/typeof/issue-42060.rs new file mode 100644 index 000000000..1740b2383 --- /dev/null +++ b/tests/ui/typeof/issue-42060.rs @@ -0,0 +1,11 @@ +fn main() { + let thing = (); + let other: typeof(thing) = thing; //~ ERROR attempt to use a non-constant value in a constant + //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516] +} + +fn f(){ + let q = 1; + ::N //~ ERROR attempt to use a non-constant value in a constant + //~^ ERROR `typeof` is a reserved keyword but unimplemented [E0516] +} diff --git a/tests/ui/typeof/issue-42060.stderr b/tests/ui/typeof/issue-42060.stderr new file mode 100644 index 000000000..effcbe4d7 --- /dev/null +++ b/tests/ui/typeof/issue-42060.stderr @@ -0,0 +1,32 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-42060.rs:3:23 + | +LL | let thing = (); + | --------- help: consider using `const` instead of `let`: `const thing` +LL | let other: typeof(thing) = thing; + | ^^^^^ non-constant value + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/issue-42060.rs:9:13 + | +LL | let q = 1; + | ----- help: consider using `const` instead of `let`: `const q` +LL | ::N + | ^ non-constant value + +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/issue-42060.rs:3:16 + | +LL | let other: typeof(thing) = thing; + | ^^^^^^^^^^^^^ reserved keyword + +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/issue-42060.rs:9:6 + | +LL | ::N + | ^^^^^^^^^ reserved keyword + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0435, E0516. +For more information about an error, try `rustc --explain E0435`. diff --git a/tests/ui/typeof/type_mismatch.rs b/tests/ui/typeof/type_mismatch.rs new file mode 100644 index 000000000..3f8339fa5 --- /dev/null +++ b/tests/ui/typeof/type_mismatch.rs @@ -0,0 +1,9 @@ +// Test that using typeof results in the correct type mismatch errors instead of always assuming +// `usize`, in addition to the pre-existing "typeof is reserved and unimplemented" error +fn main() { + const a: u8 = 1; + let b: typeof(a) = 1i8; + //~^ ERROR `typeof` is a reserved keyword but unimplemented + //~| ERROR mismatched types + //~| expected `u8`, found `i8` +} diff --git a/tests/ui/typeof/type_mismatch.stderr b/tests/ui/typeof/type_mismatch.stderr new file mode 100644 index 000000000..e75214cd3 --- /dev/null +++ b/tests/ui/typeof/type_mismatch.stderr @@ -0,0 +1,28 @@ +error[E0516]: `typeof` is a reserved keyword but unimplemented + --> $DIR/type_mismatch.rs:5:12 + | +LL | let b: typeof(a) = 1i8; + | ^^^^^^^^^ reserved keyword + | +help: consider replacing `typeof(...)` with an actual type + | +LL | let b: u8 = 1i8; + | ~~ + +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:5:24 + | +LL | let b: typeof(a) = 1i8; + | --------- ^^^ expected `u8`, found `i8` + | | + | expected due to this + | +help: change the type of the numeric literal from `i8` to `u8` + | +LL | let b: typeof(a) = 1u8; + | ~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0516. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typestate-multi-decl.rs b/tests/ui/typestate-multi-decl.rs new file mode 100644 index 000000000..9f9416205 --- /dev/null +++ b/tests/ui/typestate-multi-decl.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let (x, y) = (10, 20); + let z = x + y; + assert_eq!(z, 30); +} diff --git a/tests/ui/ufcs-polymorphic-paths.rs b/tests/ui/ufcs-polymorphic-paths.rs new file mode 100644 index 000000000..a14ebd6a4 --- /dev/null +++ b/tests/ui/ufcs-polymorphic-paths.rs @@ -0,0 +1,154 @@ +// run-pass + +use std::borrow::{Cow, ToOwned}; +use std::default::Default; +use std::iter::FromIterator; +use std::ops::Add; +use std::option::IntoIter as OptionIter; + +pub struct XorShiftRng; +use XorShiftRng as DummyRng; +impl Rng for XorShiftRng {} +pub trait Rng {} +pub trait Rand: Default + Sized { + fn rand(_rng: &mut R) -> Self { Default::default() } +} +impl Rand for i32 { } + +pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + fn into_cow(self) -> Cow<'a, B>; +} + +impl<'a> IntoCow<'a, str> for String { + fn into_cow(self) -> Cow<'a, str> { + Cow::Owned(self) + } +} + +#[derive(PartialEq, Eq)] +struct Newt(T); + +fn id(x: T) -> T { x } +fn eq(a: T, b: T) -> bool { a == b } +fn u8_as_i8(x: u8) -> i8 { x as i8 } +fn odd(x: usize) -> bool { x % 2 == 1 } +fn dummy_rng() -> DummyRng { XorShiftRng } + +trait Size: Sized { + fn size() -> usize { std::mem::size_of::() } +} +impl Size for T {} + +#[derive(PartialEq, Eq)] +struct BitVec; + +impl BitVec { + fn from_fn(_: usize, _: F) -> BitVec where F: FnMut(usize) -> bool { + BitVec + } +} + +#[derive(PartialEq, Eq)] +struct Foo(T); + +impl Foo { + fn map_in_place(self, mut f: F) -> Foo where F: FnMut(T) -> U { + Foo(f(self.0)) + } + +} + +macro_rules! tests { + ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({ + const C: $ty = $expr; + static S: $ty = $expr; + assert!(eq(C($($test),*), $expr($($test),*))); + assert!(eq(S($($test),*), $expr($($test),*))); + assert!(eq(C($($test),*), S($($test),*))); + })+}) +} + +tests! { + // Free function. + id, fn(i32) -> i32, (5); + id::, fn(i32) -> i32, (5); + + // Enum variant constructor. + Some, fn(i32) -> Option, (5); + Some::, fn(i32) -> Option, (5); + + // Tuple struct constructor. + Newt, fn(i32) -> Newt, (5); + Newt::, fn(i32) -> Newt, (5); + + // Inherent static methods. + Vec::new, fn() -> Vec<()>, (); + Vec::<()>::new, fn() -> Vec<()>, (); + >::new, fn() -> Vec<()>, (); + Vec::with_capacity, fn(usize) -> Vec<()>, (5); + Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5); + >::with_capacity, fn(usize) -> Vec<()>, (5); + BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); + BitVec::from_fn:: bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd); + + // Inherent non-static method. + Foo::map_in_place, fn(Foo, fn(u8) -> i8) -> Foo, (Foo(b'f'), u8_as_i8); + Foo::map_in_place:: i8>, fn(Foo, fn(u8) -> i8) -> Foo, + (Foo(b'f'), u8_as_i8); + Foo::::map_in_place, fn(Foo, fn(u8) -> i8) -> Foo + , (Foo(b'f'), u8_as_i8); + Foo::::map_in_place:: i8>, fn(Foo, fn(u8) -> i8) -> Foo + , (Foo(b'f'), u8_as_i8); + + // Trait static methods. + bool::size, fn() -> usize, (); + ::size, fn() -> usize, (); + ::size, fn() -> usize, (); + + Default::default, fn() -> i32, (); + i32::default, fn() -> i32, (); + ::default, fn() -> i32, (); + ::default, fn() -> i32, (); + + Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + Rand::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + i32::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + ::rand::, fn(&mut DummyRng) -> i32, (&mut dummy_rng()); + + // Trait non-static methods. + Clone::clone, fn(&i32) -> i32, (&5); + i32::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); + ::clone, fn(&i32) -> i32, (&5); + + FromIterator::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + Vec::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + >::from_iter, fn(OptionIter) -> Vec, (Some(5).into_iter()); + as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, + (Some(5).into_iter()); + as FromIterator<_>>::from_iter, fn(OptionIter) -> Vec, + (Some(5).into_iter()); + FromIterator::from_iter::>, fn(OptionIter) -> Vec, + (Some(5).into_iter()); + as FromIterator<_>>::from_iter::>, fn(OptionIter) -> Vec, + (Some(5).into_iter()); + + Add::add, fn(i32, i32) -> i32, (5, 6); + i32::add, fn(i32, i32) -> i32, (5, 6); + ::add, fn(i32, i32) -> i32, (5, 6); + >::add, fn(i32, i32) -> i32, (5, 6); + >::add, fn(i32, i32) -> i32, (5, 6); + + String::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); + ::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); + >::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); + >::into_cow, fn(String) -> Cow<'static, str>, + ("foo".to_string()); +} diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.rs b/tests/ui/ufcs/ufcs-explicit-self-bad.rs new file mode 100644 index 000000000..cb1fac0ba --- /dev/null +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.rs @@ -0,0 +1,59 @@ +struct Foo { + f: isize, +} + + + +impl Foo { + fn foo(self: isize, x: isize) -> isize { + //~^ ERROR invalid `self` parameter type + self.f + x + } +} + +struct Bar { + f: T, +} + +impl Bar { + fn foo(self: Bar, x: isize) -> isize { + //~^ ERROR invalid `self` parameter type + x + } + fn bar(self: &Bar, x: isize) -> isize { + //~^ ERROR invalid `self` parameter type + x + } +} + +trait SomeTrait { + fn dummy1(&self); + fn dummy2(&self); + fn dummy3(&self); +} + +impl<'a, T> SomeTrait for &'a Bar { + fn dummy1(self: &&'a Bar) { } + fn dummy2(self: &Bar) {} //~ ERROR mismatched `self` parameter type + //~^ ERROR mismatched `self` parameter type + fn dummy3(self: &&Bar) {} + //~^ ERROR mismatched `self` parameter type + //~| expected reference `&'a Bar` + //~| found reference `&Bar` + //~| lifetime mismatch + //~| ERROR mismatched `self` parameter type + //~| expected reference `&'a Bar` + //~| found reference `&Bar` + //~| lifetime mismatch +} + +fn main() { + let foo = Box::new(Foo { + f: 1, + }); + println!("{}", foo.foo(2)); + let bar = Box::new(Bar { + f: 1, + }); + println!("{} {}", bar.foo(2), bar.bar(2)); +} diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr new file mode 100644 index 000000000..f325d1d81 --- /dev/null +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -0,0 +1,107 @@ +error[E0307]: invalid `self` parameter type: isize + --> $DIR/ufcs-explicit-self-bad.rs:8:18 + | +LL | fn foo(self: isize, x: isize) -> isize { + | ^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0307]: invalid `self` parameter type: Bar + --> $DIR/ufcs-explicit-self-bad.rs:19:18 + | +LL | fn foo(self: Bar, x: isize) -> isize { + | ^^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0307]: invalid `self` parameter type: &Bar + --> $DIR/ufcs-explicit-self-bad.rs:23:18 + | +LL | fn bar(self: &Bar, x: isize) -> isize { + | ^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0308]: mismatched `self` parameter type + --> $DIR/ufcs-explicit-self-bad.rs:37:21 + | +LL | fn dummy2(self: &Bar) {} + | ^^^^^^^ lifetime mismatch + | + = note: expected reference `&'a Bar` + found reference `&Bar` +note: the anonymous lifetime defined here... + --> $DIR/ufcs-explicit-self-bad.rs:37:21 + | +LL | fn dummy2(self: &Bar) {} + | ^^^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/ufcs-explicit-self-bad.rs:35:6 + | +LL | impl<'a, T> SomeTrait for &'a Bar { + | ^^ + +error[E0308]: mismatched `self` parameter type + --> $DIR/ufcs-explicit-self-bad.rs:37:21 + | +LL | fn dummy2(self: &Bar) {} + | ^^^^^^^ lifetime mismatch + | + = note: expected reference `&'a Bar` + found reference `&Bar` +note: the lifetime `'a` as defined here... + --> $DIR/ufcs-explicit-self-bad.rs:35:6 + | +LL | impl<'a, T> SomeTrait for &'a Bar { + | ^^ +note: ...does not necessarily outlive the anonymous lifetime defined here + --> $DIR/ufcs-explicit-self-bad.rs:37:21 + | +LL | fn dummy2(self: &Bar) {} + | ^^^^^^^ + +error[E0308]: mismatched `self` parameter type + --> $DIR/ufcs-explicit-self-bad.rs:39:21 + | +LL | fn dummy3(self: &&Bar) {} + | ^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'a Bar` + found reference `&Bar` +note: the anonymous lifetime defined here... + --> $DIR/ufcs-explicit-self-bad.rs:39:22 + | +LL | fn dummy3(self: &&Bar) {} + | ^^^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/ufcs-explicit-self-bad.rs:35:6 + | +LL | impl<'a, T> SomeTrait for &'a Bar { + | ^^ + +error[E0308]: mismatched `self` parameter type + --> $DIR/ufcs-explicit-self-bad.rs:39:21 + | +LL | fn dummy3(self: &&Bar) {} + | ^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'a Bar` + found reference `&Bar` +note: the lifetime `'a` as defined here... + --> $DIR/ufcs-explicit-self-bad.rs:35:6 + | +LL | impl<'a, T> SomeTrait for &'a Bar { + | ^^ +note: ...does not necessarily outlive the anonymous lifetime defined here + --> $DIR/ufcs-explicit-self-bad.rs:39:22 + | +LL | fn dummy3(self: &&Bar) {} + | ^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0307, E0308. +For more information about an error, try `rustc --explain E0307`. diff --git a/tests/ui/ufcs/ufcs-partially-resolved.rs b/tests/ui/ufcs/ufcs-partially-resolved.rs new file mode 100644 index 000000000..e6470aa6d --- /dev/null +++ b/tests/ui/ufcs/ufcs-partially-resolved.rs @@ -0,0 +1,56 @@ +#![feature(associated_type_defaults)] + +trait Tr { + type Y = u16; + fn Y() {} +} +impl Tr for u8 {} + +trait Dr { + type X = u16; + fn Z() {} +} +impl Dr for u8 {} + +enum E { Y } +type A = u32; + +fn main() { + let _: ::N; //~ ERROR cannot find associated type `N` in trait `Tr` + let _: ::N; //~ ERROR cannot find associated type `N` in enum `E` + let _: ::N; //~ ERROR cannot find associated type `N` in `A` + ::N; //~ ERROR cannot find method or associated constant `N` in trait `Tr` + ::N; //~ ERROR cannot find method or associated constant `N` in enum `E` + ::N; //~ ERROR cannot find method or associated constant `N` in `A` + let _: ::Y; // OK + let _: ::Y; //~ ERROR expected associated type, found variant `E::Y` + ::Y; // OK + ::Y; //~ ERROR expected method or associated constant, found unit variant `E::Y` + + let _: ::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr` + let _: ::N::NN; //~ ERROR cannot find associated type `N` in enum `E` + let _: ::N::NN; //~ ERROR cannot find associated type `N` in `A` + ::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr` + ::N::NN; //~ ERROR cannot find associated type `N` in enum `E` + ::N::NN; //~ ERROR cannot find associated type `N` in `A` + let _: ::Y::NN; //~ ERROR ambiguous associated type + let _: ::Y::NN; //~ ERROR expected associated type, found variant `E::Y` + ::Y::NN; //~ ERROR no associated item named `NN` found for type `u16` + ::Y::NN; //~ ERROR expected associated type, found variant `E::Y` + + let _: ::NN; //~ ERROR cannot find associated type `NN` in `Tr::N` + let _: ::NN; //~ ERROR cannot find associated type `NN` in `E::N` + let _: ::NN; //~ ERROR cannot find associated type `NN` in `A::N` + ::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::N` + ::NN; //~ ERROR cannot find method or associated constant `NN` in `E::N` + ::NN; //~ ERROR cannot find method or associated constant `NN` in `A::N` + let _: ::NN; //~ ERROR cannot find associated type `NN` in `Tr::Y` + let _: ::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module + ::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y` + ::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module + + let _: ::Z; //~ ERROR expected associated type, found associated function `Dr::Z` + ::X; //~ ERROR expected method or associated constant, found associated type `Dr::X` + let _: ::Z::N; //~ ERROR expected associated type, found associated function `Dr::Z` + ::X::N; //~ ERROR no associated item named `N` found for type `u16` +} diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr new file mode 100644 index 000000000..72fccea8a --- /dev/null +++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr @@ -0,0 +1,230 @@ +error[E0433]: failed to resolve: `Y` is a variant, not a module + --> $DIR/ufcs-partially-resolved.rs:48:22 + | +LL | let _: ::NN; + | ^ `Y` is a variant, not a module + +error[E0433]: failed to resolve: `Y` is a variant, not a module + --> $DIR/ufcs-partially-resolved.rs:50:15 + | +LL | ::NN; + | ^ `Y` is a variant, not a module + +error[E0576]: cannot find associated type `N` in trait `Tr` + --> $DIR/ufcs-partially-resolved.rs:19:24 + | +LL | type Y = u16; + | ------------- similarly named associated type `Y` defined here +... +LL | let _: ::N; + | ^ help: an associated type with a similar name exists: `Y` + +error[E0576]: cannot find associated type `N` in enum `E` + --> $DIR/ufcs-partially-resolved.rs:20:23 + | +LL | let _: ::N; + | ^ not found in `E` + +error[E0576]: cannot find associated type `N` in `A` + --> $DIR/ufcs-partially-resolved.rs:21:23 + | +LL | let _: ::N; + | ^ not found in `A` + +error[E0576]: cannot find method or associated constant `N` in trait `Tr` + --> $DIR/ufcs-partially-resolved.rs:22:17 + | +LL | fn Y() {} + | ------ similarly named associated function `Y` defined here +... +LL | ::N; + | ^ help: an associated function with a similar name exists: `Y` + +error[E0576]: cannot find method or associated constant `N` in enum `E` + --> $DIR/ufcs-partially-resolved.rs:23:16 + | +LL | ::N; + | ^ not found in `E` + +error[E0576]: cannot find method or associated constant `N` in `A` + --> $DIR/ufcs-partially-resolved.rs:24:16 + | +LL | ::N; + | ^ not found in `A` + +error[E0575]: expected associated type, found variant `E::Y` + --> $DIR/ufcs-partially-resolved.rs:26:12 + | +LL | let _: ::Y; + | ^^^^^^^^^^^^ not a associated type + +error[E0575]: expected method or associated constant, found unit variant `E::Y` + --> $DIR/ufcs-partially-resolved.rs:28:5 + | +LL | ::Y; + | ^^^^^^^^^^^^ not a method or associated constant + +error[E0576]: cannot find associated type `N` in trait `Tr` + --> $DIR/ufcs-partially-resolved.rs:30:24 + | +LL | type Y = u16; + | ------------- similarly named associated type `Y` defined here +... +LL | let _: ::N::NN; + | ^ help: an associated type with a similar name exists: `Y` + +error[E0576]: cannot find associated type `N` in enum `E` + --> $DIR/ufcs-partially-resolved.rs:31:23 + | +LL | let _: ::N::NN; + | ^ not found in `E` + +error[E0576]: cannot find associated type `N` in `A` + --> $DIR/ufcs-partially-resolved.rs:32:23 + | +LL | let _: ::N::NN; + | ^ not found in `A` + +error[E0576]: cannot find associated type `N` in trait `Tr` + --> $DIR/ufcs-partially-resolved.rs:33:17 + | +LL | type Y = u16; + | ------------- similarly named associated type `Y` defined here +... +LL | ::N::NN; + | ^ help: an associated type with a similar name exists: `Y` + +error[E0576]: cannot find associated type `N` in enum `E` + --> $DIR/ufcs-partially-resolved.rs:34:16 + | +LL | ::N::NN; + | ^ not found in `E` + +error[E0576]: cannot find associated type `N` in `A` + --> $DIR/ufcs-partially-resolved.rs:35:16 + | +LL | ::N::NN; + | ^ not found in `A` + +error[E0575]: expected associated type, found variant `E::Y` + --> $DIR/ufcs-partially-resolved.rs:37:12 + | +LL | let _: ::Y::NN; + | ^^^^^^^^^^^^^^^^ not a associated type + +error[E0575]: expected associated type, found variant `E::Y` + --> $DIR/ufcs-partially-resolved.rs:39:5 + | +LL | ::Y::NN; + | ^^^^^^^^^^^^^^^^ not a associated type + +error[E0576]: cannot find associated type `NN` in `Tr::N` + --> $DIR/ufcs-partially-resolved.rs:41:27 + | +LL | let _: ::NN; + | ^^ not found in `Tr::N` + +error[E0576]: cannot find associated type `NN` in `E::N` + --> $DIR/ufcs-partially-resolved.rs:42:26 + | +LL | let _: ::NN; + | ^^ not found in `E::N` + +error[E0576]: cannot find associated type `NN` in `A::N` + --> $DIR/ufcs-partially-resolved.rs:43:26 + | +LL | let _: ::NN; + | ^^ not found in `A::N` + +error[E0576]: cannot find method or associated constant `NN` in `Tr::N` + --> $DIR/ufcs-partially-resolved.rs:44:20 + | +LL | ::NN; + | ^^ not found in `Tr::N` + +error[E0576]: cannot find method or associated constant `NN` in `E::N` + --> $DIR/ufcs-partially-resolved.rs:45:19 + | +LL | ::NN; + | ^^ not found in `E::N` + +error[E0576]: cannot find method or associated constant `NN` in `A::N` + --> $DIR/ufcs-partially-resolved.rs:46:19 + | +LL | ::NN; + | ^^ not found in `A::N` + +error[E0576]: cannot find associated type `NN` in `Tr::Y` + --> $DIR/ufcs-partially-resolved.rs:47:27 + | +LL | let _: ::NN; + | ^^ not found in `Tr::Y` + +error[E0576]: cannot find method or associated constant `NN` in `Tr::Y` + --> $DIR/ufcs-partially-resolved.rs:49:20 + | +LL | ::NN; + | ^^ not found in `Tr::Y` + +error[E0575]: expected associated type, found associated function `Dr::Z` + --> $DIR/ufcs-partially-resolved.rs:52:12 + | +LL | type X = u16; + | ------------- similarly named associated type `X` defined here +... +LL | let _: ::Z; + | ^^^^^^^^^^^^- + | | + | help: an associated type with a similar name exists: `X` + +error[E0575]: expected method or associated constant, found associated type `Dr::X` + --> $DIR/ufcs-partially-resolved.rs:53:5 + | +LL | fn Z() {} + | ------ similarly named associated function `Z` defined here +... +LL | ::X; + | ^^^^^^^^^^^^- + | | + | help: an associated function with a similar name exists: `Z` + | + = note: can't use a type alias as a constructor + +error[E0575]: expected associated type, found associated function `Dr::Z` + --> $DIR/ufcs-partially-resolved.rs:54:12 + | +LL | type X = u16; + | ------------- similarly named associated type `X` defined here +... +LL | let _: ::Z::N; + | ^^^^^^^^^^^^-^^^ + | | + | help: an associated type with a similar name exists: `X` + +error[E0223]: ambiguous associated type + --> $DIR/ufcs-partially-resolved.rs:36:12 + | +LL | let _: ::Y::NN; + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `NN` implemented for `::Y`, you could use the fully-qualified path + | +LL | let _: <::Y as Example>::NN; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0599]: no associated item named `NN` found for type `u16` in the current scope + --> $DIR/ufcs-partially-resolved.rs:38:20 + | +LL | ::Y::NN; + | ^^ associated item not found in `u16` + +error[E0599]: no associated item named `N` found for type `u16` in the current scope + --> $DIR/ufcs-partially-resolved.rs:55:20 + | +LL | ::X::N; + | ^ associated item not found in `u16` + +error: aborting due to 32 previous errors + +Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599. +For more information about an error, try `rustc --explain E0223`. diff --git a/tests/ui/ufcs/ufcs-qpath-missing-params.rs b/tests/ui/ufcs/ufcs-qpath-missing-params.rs new file mode 100644 index 000000000..766351634 --- /dev/null +++ b/tests/ui/ufcs/ufcs-qpath-missing-params.rs @@ -0,0 +1,20 @@ +use std::borrow::Cow; + +pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + fn into_cow(self) -> Cow<'a, B>; +} + +impl<'a> IntoCow<'a, str> for String { + fn into_cow(self) -> Cow<'a, str> { + Cow::Owned(self) + } +} + +fn main() { + ::into_cow("foo".to_string()); + //~^ ERROR missing generics for + + ::into_cow::("foo".to_string()); + //~^ ERROR this associated function takes 0 generic arguments but 1 + //~| ERROR missing generics for +} diff --git a/tests/ui/ufcs/ufcs-qpath-missing-params.stderr b/tests/ui/ufcs/ufcs-qpath-missing-params.stderr new file mode 100644 index 000000000..d0ec47d61 --- /dev/null +++ b/tests/ui/ufcs/ufcs-qpath-missing-params.stderr @@ -0,0 +1,49 @@ +error[E0107]: missing generics for trait `IntoCow` + --> $DIR/ufcs-qpath-missing-params.rs:14:16 + | +LL | ::into_cow("foo".to_string()); + | ^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `B` + --> $DIR/ufcs-qpath-missing-params.rs:3:11 + | +LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + | ^^^^^^^ - +help: add missing generic argument + | +LL | >::into_cow("foo".to_string()); + | +++ + +error[E0107]: missing generics for trait `IntoCow` + --> $DIR/ufcs-qpath-missing-params.rs:17:16 + | +LL | ::into_cow::("foo".to_string()); + | ^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `B` + --> $DIR/ufcs-qpath-missing-params.rs:3:11 + | +LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + | ^^^^^^^ - +help: add missing generic argument + | +LL | >::into_cow::("foo".to_string()); + | +++ + +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/ufcs-qpath-missing-params.rs:17:26 + | +LL | ::into_cow::("foo".to_string()); + | ^^^^^^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/ufcs-qpath-missing-params.rs:4:8 + | +LL | fn into_cow(self) -> Cow<'a, B>; + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.rs b/tests/ui/ufcs/ufcs-qpath-self-mismatch.rs new file mode 100644 index 000000000..ec86213f8 --- /dev/null +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.rs @@ -0,0 +1,11 @@ +use std::ops::Add; + +fn main() { + >::add(1, 2); + //~^ ERROR cannot add `u32` to `i32` + //~| ERROR cannot add `u32` to `i32` + >::add(1u32, 2); + //~^ ERROR mismatched types + >::add(1, 2u32); + //~^ ERROR mismatched types +} diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr new file mode 100644 index 000000000..e85144a31 --- /dev/null +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -0,0 +1,76 @@ +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:31 + | +LL | >::add(1, 2); + | ---------------------- ^ no implementation for `i32 + u32` + | | + | required by a bound introduced by this call + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + <&'a i32 as Add> + <&i32 as Add<&i32>> + > + + +error[E0308]: mismatched types + --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 + | +LL | >::add(1u32, 2); + | ---------------------- ^^^^ expected `i32`, found `u32` + | | + | arguments to this function are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/ufcs-qpath-self-mismatch.rs:7:5 + | +LL | >::add(1u32, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^----^^^^ + | | + | this argument influences the return type of `Add` +note: associated function defined here + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: change the type of the numeric literal from `u32` to `i32` + | +LL | >::add(1i32, 2); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/ufcs-qpath-self-mismatch.rs:9:31 + | +LL | >::add(1, 2u32); + | ---------------------- ^^^^ expected `i32`, found `u32` + | | + | arguments to this function are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/ufcs-qpath-self-mismatch.rs:9:5 + | +LL | >::add(1, 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^----^ + | | + | this argument influences the return type of `Add` +note: associated function defined here + --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: change the type of the numeric literal from `u32` to `i32` + | +LL | >::add(1, 2i32); + | ~~~ + +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | >::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + <&'a i32 as Add> + <&i32 as Add<&i32>> + > + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/auxiliary/unboxed-closures-cross-crate.rs b/tests/ui/unboxed-closures/auxiliary/unboxed-closures-cross-crate.rs new file mode 100644 index 000000000..ac0a74eeb --- /dev/null +++ b/tests/ui/unboxed-closures/auxiliary/unboxed-closures-cross-crate.rs @@ -0,0 +1,16 @@ +use std::ops::Add; + +#[inline] +pub fn has_closures() -> usize { + let x = 1; + let mut f = move || x; + let y = 1; + let g = || y; + f() + g() +} + +pub fn has_generic_closures + Copy>(x: T, y: T) -> T { + let mut f = move || x; + let g = || y; + f() + g() +} diff --git a/tests/ui/unboxed-closures/issue-18652.rs b/tests/ui/unboxed-closures/issue-18652.rs new file mode 100644 index 000000000..59aa01568 --- /dev/null +++ b/tests/ui/unboxed-closures/issue-18652.rs @@ -0,0 +1,10 @@ +// run-pass +// Tests multiple free variables being passed by value into an unboxed +// once closure as an optimization by codegen. This used to hit an +// incorrect assert. + +fn main() { + let x = 2u8; + let y = 3u8; + assert_eq!((move || x + y)(), 5); +} diff --git a/tests/ui/unboxed-closures/issue-18661.rs b/tests/ui/unboxed-closures/issue-18661.rs new file mode 100644 index 000000000..e24272432 --- /dev/null +++ b/tests/ui/unboxed-closures/issue-18661.rs @@ -0,0 +1,19 @@ +// run-pass +// Test that param substitutions from the correct environment are +// used when codegenning unboxed closure calls. + +// pretty-expanded FIXME #23616 + +pub fn inside(c: F) { + c(); +} + +// Use different number of type parameters and closure type to trigger +// an obvious ICE when param environments are mixed up +pub fn outside() { + inside(|| {}); +} + +fn main() { + outside::<(),()>(); +} diff --git a/tests/ui/unboxed-closures/issue-30906.rs b/tests/ui/unboxed-closures/issue-30906.rs new file mode 100644 index 000000000..e2d219e47 --- /dev/null +++ b/tests/ui/unboxed-closures/issue-30906.rs @@ -0,0 +1,22 @@ +#![feature(fn_traits, unboxed_closures)] + +fn test FnOnce<(&'x str,)>>(_: F) {} + +struct Compose(F, G); +impl FnOnce<(T,)> for Compose +where + F: FnOnce<(T,)>, + G: FnOnce<(F::Output,)>, +{ + type Output = G::Output; + extern "rust-call" fn call_once(self, (x,): (T,)) -> G::Output { + (self.1)((self.0)(x)) + } +} + +fn bad(f: fn(&'static str) -> T) { + test(Compose(f, |_| {})); + //~^ ERROR: implementation of `FnOnce` is not general enough +} + +fn main() {} diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr new file mode 100644 index 000000000..147a20974 --- /dev/null +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -0,0 +1,11 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-30906.rs:18:5 + | +LL | test(Compose(f, |_| {})); + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` + +error: aborting due to previous error + diff --git a/tests/ui/unboxed-closures/issue-53448.rs b/tests/ui/unboxed-closures/issue-53448.rs new file mode 100644 index 000000000..ea1edf7d4 --- /dev/null +++ b/tests/ui/unboxed-closures/issue-53448.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(unboxed_closures)] + +trait Lt<'a> { + type T; +} +impl<'a> Lt<'a> for () { + type T = (); +} + +fn main() { + let v: <() as Lt<'_>>::T = (); + let f: &mut dyn FnMut<(_,), Output = ()> = &mut |_: <() as Lt<'_>>::T| {}; + f(v); +} diff --git a/tests/ui/unboxed-closures/non-tupled-arg-mismatch.rs b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.rs new file mode 100644 index 000000000..d2e486002 --- /dev/null +++ b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.rs @@ -0,0 +1,8 @@ +#![feature(unboxed_closures)] + +fn a>(f: F) {} +//~^ ERROR type parameter to bare `Fn` trait must be a tuple + +fn main() { + a(|_: usize| {}); +} diff --git a/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr new file mode 100644 index 000000000..cfbe1c6f2 --- /dev/null +++ b/tests/ui/unboxed-closures/non-tupled-arg-mismatch.stderr @@ -0,0 +1,12 @@ +error[E0059]: type parameter to bare `Fn` trait must be a tuple + --> $DIR/non-tupled-arg-mismatch.rs:3:9 + | +LL | fn a>(f: F) {} + | ^^^^^^^^^ the trait `Tuple` is not implemented for `usize` + | +note: required by a bound in `Fn` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0059`. diff --git a/tests/ui/unboxed-closures/non-tupled-call.rs b/tests/ui/unboxed-closures/non-tupled-call.rs new file mode 100644 index 000000000..08bea4f16 --- /dev/null +++ b/tests/ui/unboxed-closures/non-tupled-call.rs @@ -0,0 +1,17 @@ +#![feature(fn_traits, unboxed_closures, tuple_trait)] + +use std::default::Default; +use std::marker::Tuple; + +fn wrap(func: impl Fn) { + let x: P = Default::default(); + // Should be: `func.call(x);` + func(x); + //~^ ERROR cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit +} + +fn foo() {} + +fn main() { + wrap(foo); +} diff --git a/tests/ui/unboxed-closures/non-tupled-call.stderr b/tests/ui/unboxed-closures/non-tupled-call.stderr new file mode 100644 index 000000000..35ac9ebe2 --- /dev/null +++ b/tests/ui/unboxed-closures/non-tupled-call.stderr @@ -0,0 +1,9 @@ +error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit + --> $DIR/non-tupled-call.rs:9:5 + | +LL | func(x); + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0059`. diff --git a/tests/ui/unboxed-closures/type-id-higher-rank.rs b/tests/ui/unboxed-closures/type-id-higher-rank.rs new file mode 100644 index 000000000..1f8aec205 --- /dev/null +++ b/tests/ui/unboxed-closures/type-id-higher-rank.rs @@ -0,0 +1,72 @@ +// run-pass +// Test that type IDs correctly account for higher-rank lifetimes +// Also acts as a regression test for an ICE (issue #19791) + +use std::any::{Any, TypeId}; + +struct Struct<'a>(#[allow(unused_tuple_struct_fields)] &'a ()); +trait Trait<'a> {} + +fn main() { + // Bare fns + { + let a = TypeId::of::(); + let b = TypeId::of:: fn(&'static isize, &'a isize)>(); + let c = TypeId::of:: fn(&'a isize, &'b isize)>(); + let d = TypeId::of:: fn(&'b isize, &'a isize)>(); + assert!(a != b); + assert!(a != c); + assert!(a != d); + assert!(b != c); + assert!(b != d); + assert_eq!(c, d); + + // Make sure De Bruijn indices are handled correctly + let e = TypeId::of:: fn(fn(&'a isize) -> &'a isize)>(); + let f = TypeId::of:: fn(&'a isize) -> &'a isize)>(); + assert!(e != f); + + // Make sure lifetime parameters of items are not ignored. + let g = TypeId::of:: fn(&'a dyn Trait<'a>) -> Struct<'a>>(); + let h = TypeId::of:: fn(&'a dyn Trait<'a>) -> Struct<'static>>(); + let i = TypeId::of:: fn(&'a dyn Trait<'b>) -> Struct<'b>>(); + assert!(g != h); + assert!(g != i); + assert!(h != i); + + // Make sure lifetime anonymization handles nesting correctly + let j = TypeId::of:: fn(&'a isize) -> &'a usize)>(); + let k = TypeId::of:: fn(&'b isize) -> &'b usize)>(); + assert_eq!(j, k); + } + // Boxed unboxed closures + { + let a = TypeId::of::>(); + let b = TypeId::of:: Fn(&'static isize, &'a isize)>>(); + let c = TypeId::of:: Fn(&'a isize, &'b isize)>>(); + let d = TypeId::of:: Fn(&'b isize, &'a isize)>>(); + assert!(a != b); + assert!(a != c); + assert!(a != d); + assert!(b != c); + assert!(b != d); + assert_eq!(c, d); + + // Make sure De Bruijn indices are handled correctly + let e = TypeId::of:: Fn(Box &'a isize>)>>(); + let f = TypeId::of:: Fn(&'a isize) -> &'a isize>)>>(); + assert!(e != f); + } + // Raw unboxed closures + // Note that every unboxed closure has its own anonymous type, + // so no two IDs should equal each other, even when compatible + { + let a = id(|_: &isize, _: &isize| {}); + let b = id(|_: &isize, _: &isize| {}); + assert!(a != b); + } + + fn id(_: T) -> TypeId { + TypeId::of::() + } +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-feature-gate.rs b/tests/ui/unboxed-closures/unboxed-closure-feature-gate.rs new file mode 100644 index 000000000..d8b201bf8 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-feature-gate.rs @@ -0,0 +1,20 @@ +// Check that parenthetical notation is feature-gated except with the +// `Fn` traits. + +use std::marker; + +trait Foo { + type Output; + + fn dummy(&self, a: A) { } +} + +fn main() { + let x: Box; + //~^ ERROR parenthetical notation is only stable when used with `Fn`-family + + // No errors with these: + let x: Box; + let x: Box; + let x: Box; +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr b/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr new file mode 100644 index 000000000..b824d160d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-feature-gate.stderr @@ -0,0 +1,12 @@ +error[E0658]: parenthetical notation is only stable when used with `Fn`-family traits + --> $DIR/unboxed-closure-feature-gate.rs:13:20 + | +LL | let x: Box; + | ^^^^^^^^^^ + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-illegal-move.rs b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.rs new file mode 100644 index 000000000..7377359b6 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.rs @@ -0,0 +1,38 @@ +#![feature(unboxed_closures, tuple_trait)] + +// Tests that we can't move out of an unboxed closure environment +// if the upvar is captured by ref or the closure takes self by +// reference. + +fn to_fn>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } +fn to_fn_once>(f: F) -> F { f } + +fn main() { + // By-ref cases + { + let x = Box::new(0); + let f = to_fn(|| drop(x)); //~ ERROR cannot move + } + { + let x = Box::new(0); + let f = to_fn_mut(|| drop(x)); //~ ERROR cannot move + } + { + let x = Box::new(0); + let f = to_fn_once(|| drop(x)); // OK -- FnOnce + } + // By-value cases + { + let x = Box::new(0); + let f = to_fn(move || drop(x)); //~ ERROR cannot move + } + { + let x = Box::new(0); + let f = to_fn_mut(move || drop(x)); //~ ERROR cannot move + } + { + let x = Box::new(0); + let f = to_fn_once(move || drop(x)); // this one is ok + } +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr new file mode 100644 index 000000000..bfa3061de --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr @@ -0,0 +1,43 @@ +error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure + --> $DIR/unboxed-closure-illegal-move.rs:15:31 + | +LL | let x = Box::new(0); + | - captured outer variable +LL | let f = to_fn(|| drop(x)); + | -- ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | | + | captured by this `Fn` closure + +error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure + --> $DIR/unboxed-closure-illegal-move.rs:19:35 + | +LL | let x = Box::new(0); + | - captured outer variable +LL | let f = to_fn_mut(|| drop(x)); + | -- ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | | + | captured by this `FnMut` closure + +error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure + --> $DIR/unboxed-closure-illegal-move.rs:28:36 + | +LL | let x = Box::new(0); + | - captured outer variable +LL | let f = to_fn(move || drop(x)); + | ------- ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | | + | captured by this `Fn` closure + +error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure + --> $DIR/unboxed-closure-illegal-move.rs:32:40 + | +LL | let x = Box::new(0); + | - captured outer variable +LL | let f = to_fn_mut(move || drop(x)); + | ------- ^ move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | | + | captured by this `FnMut` closure + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-immutable-capture.rs b/tests/ui/unboxed-closures/unboxed-closure-immutable-capture.rs new file mode 100644 index 000000000..3eba9c4d4 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-immutable-capture.rs @@ -0,0 +1,17 @@ +// Test that even unboxed closures that are capable of mutating their +// environment cannot mutate captured variables that have not been +// declared mutable (#18335) + +fn set(x: &mut usize) { *x = 0; } + +fn main() { + let x = 0; + move || x = 1; //~ ERROR cannot assign + move || set(&mut x); //~ ERROR cannot borrow + move || x = 1; //~ ERROR cannot assign + move || set(&mut x); //~ ERROR cannot borrow + || x = 1; //~ ERROR cannot assign + || set(&mut x); //~ ERROR cannot borrow + || x = 1; //~ ERROR cannot assign + || set(&mut x); //~ ERROR cannot borrow +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr b/tests/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr new file mode 100644 index 000000000..ad5451ced --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-immutable-capture.stderr @@ -0,0 +1,75 @@ +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:9:13 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | move || x = 1; + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:10:17 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | move || x = 1; +LL | move || set(&mut x); + | ^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:11:13 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | move || x = 1; + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:12:17 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | move || set(&mut x); + | ^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:13:8 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | || x = 1; + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:14:12 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | || set(&mut x); + | ^^^^^^ cannot borrow as mutable + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:15:8 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | || x = 1; + | ^^^^^ cannot assign + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closure-immutable-capture.rs:16:12 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +... +LL | || set(&mut x); + | ^^^^^^ cannot borrow as mutable + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0594, E0596. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs new file mode 100644 index 000000000..9d0aa4132 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.rs @@ -0,0 +1,9 @@ +// Test that unboxed closures cannot capture their own type. +// +// Also regression test for issue #21410. + +fn g(_: F) where F: FnOnce(Option) {} + +fn main() { + g(|_| { }); //~ ERROR closure/generator type that references itself +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr new file mode 100644 index 000000000..6d5dbca05 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr @@ -0,0 +1,19 @@ +error[E0644]: closure/generator type that references itself + --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:7 + | +LL | g(|_| { }); + | ^^^ cyclic type of infinite size + | + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see issue #46062 + for more information +note: required by a bound in `g` + --> $DIR/unboxed-closure-no-cyclic-sig.rs:5:24 + | +LL | fn g(_: F) where F: FnOnce(Option) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `g` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0644`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-region.rs b/tests/ui/unboxed-closures/unboxed-closure-region.rs new file mode 100644 index 000000000..51fe118c9 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-region.rs @@ -0,0 +1,11 @@ +// Test that an unboxed closure that captures a free variable by +// reference cannot escape the region of that variable. + + +fn main() { + let _f = { + let x = 0; + || x //~ ERROR closure may outlive the current block, but it borrows `x` + }; + _f; +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-region.stderr new file mode 100644 index 000000000..43e9af24a --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-region.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current block, but it borrows `x`, which is owned by the current block + --> $DIR/unboxed-closure-region.rs:8:9 + | +LL | || x + | ^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: block requires argument type to outlive `'1` + --> $DIR/unboxed-closure-region.rs:6:9 + | +LL | let _f = { + | ^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | move || x + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-default.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-default.rs new file mode 100644 index 000000000..f1c83f060 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-default.rs @@ -0,0 +1,28 @@ +// Test interaction between unboxed closure sugar and default type +// parameters (should be exactly as if angle brackets were used). + +#![feature(unboxed_closures)] +#![allow(dead_code)] + +trait Foo { + type Output; + fn dummy(&self, t: T, v: V); +} + +trait Eq { fn same_types(&self, x: &X) -> bool { true } } +impl Eq for X { } +fn eq() where A : Eq { } + +fn test<'a,'b>() { + // Parens are equivalent to omitting default in angle. + eq::, dyn Foo(isize)>(); + + // In angle version, we supply something other than the default + eq::, dyn Foo(isize)>(); + //~^ ERROR E0277 + + // Supply default explicitly. + eq::, dyn Foo(isize)>(); +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr new file mode 100644 index 000000000..a3b32d2c1 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-default.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq>` is not satisfied + --> $DIR/unboxed-closure-sugar-default.rs:21:10 + | +LL | eq::, dyn Foo(isize)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>` + | +note: required by a bound in `eq` + --> $DIR/unboxed-closure-sugar-default.rs:14:40 + | +LL | fn eq() where A : Eq { } + | ^^^^^ required by this bound in `eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs new file mode 100644 index 000000000..acf0227a7 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.rs @@ -0,0 +1,48 @@ +// Test that the unboxed closure sugar can be used with an arbitrary +// struct type and that it is equivalent to the same syntax using +// angle brackets. This test covers only simple types and in +// particular doesn't test bound regions. + +#![feature(unboxed_closures)] +#![allow(dead_code)] + +trait Foo { + type Output; + fn dummy(&self, t: T, u: Self::Output); +} + +trait Eq { } +impl Eq for X { } +fn eq>() { } + +fn test<'a,'b>() { + // No errors expected: + eq::< dyn Foo<(),Output=()>, dyn Foo() >(); + eq::< dyn Foo<(isize,),Output=()>, dyn Foo(isize) >(); + eq::< dyn Foo<(isize,usize),Output=()>, dyn Foo(isize,usize) >(); + eq::< dyn Foo<(isize,usize),Output=usize>, dyn Foo(isize,usize) -> usize >(); + eq::< dyn Foo<(&'a isize,&'b usize),Output=usize>, dyn Foo(&'a isize,&'b usize) -> usize >(); + + // Test that anonymous regions in `()` form are equivalent + // to fresh bound regions, and that we can intermingle + // named and anonymous as we choose: + eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, + dyn for<'x,'y> Foo(&'x isize,&'y usize) -> usize >(); + eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, + dyn for<'x> Foo(&'x isize,&usize) -> usize >(); + eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, + dyn for<'y> Foo(&isize,&'y usize) -> usize >(); + eq::< dyn for<'x,'y> Foo<(&'x isize,&'y usize),Output=usize>, + dyn Foo(&isize,&usize) -> usize >(); + + // lifetime elision + eq::< dyn for<'x> Foo<(&'x isize,), Output=&'x isize>, + dyn Foo(&isize) -> &isize >(); + + // Errors expected: + eq::< dyn Foo<(),Output=()>, + dyn Foo(char) >(); + //~^ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr new file mode 100644 index 000000000..bccbf307a --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq>` is not satisfied + --> $DIR/unboxed-closure-sugar-equiv.rs:44:11 + | +LL | dyn Foo(char) >(); + | ^^^^^^^^^^^^^ the trait `Eq>` is not implemented for `dyn Foo<(char,), Output = ()>` + | +note: required by a bound in `eq` + --> $DIR/unboxed-closure-sugar-equiv.rs:16:28 + | +LL | fn eq>() { } + | ^^^^^ required by this bound in `eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs new file mode 100644 index 000000000..d11d663f1 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.rs @@ -0,0 +1,27 @@ +// Test that the unboxed closure sugar can be used with an arbitrary +// struct type and that it is equivalent to the same syntax using +// angle brackets. This test covers only simple types and in +// particular doesn't test bound regions. + +#![feature(unboxed_closures)] +#![allow(dead_code)] + +use std::marker; + +trait Foo { + type Output; + fn dummy(&self, t: T); +} + +trait Eq { } +impl Eq for X { } +fn eq>() { } + +fn main() { + eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>, + dyn Foo(&isize) -> &isize >(); + eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>, + dyn Foo(&isize) -> (&isize, &isize) >(); + + let _: dyn Foo(&isize, &usize) -> &usize; //~ ERROR missing lifetime specifier +} diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr new file mode 100644 index 000000000..2b8fec86c --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -0,0 +1,24 @@ +error[E0106]: missing lifetime specifier + --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39 + | +LL | let _: dyn Foo(&isize, &usize) -> &usize; + | ------ ------ ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | let _: dyn for<'a> Foo(&'a isize, &'a usize) -> &'a usize; + | +++++++ ++ ++ ++ +help: consider introducing a named lifetime parameter + | +LL ~ fn main<'a>() { +LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>, + ... +LL | +LL ~ let _: dyn Foo(&'a isize, &'a usize) -> &'a usize; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs new file mode 100644 index 000000000..6d6ed4b56 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.rs @@ -0,0 +1,11 @@ +// Test that the `Fn` traits require `()` form without a feature gate. + +fn bar1(x: &dyn Fn<(), Output=()>) { + //~^ ERROR of `Fn`-family traits' type parameters is subject to change +} + +fn bar2(x: &T) where T: Fn<()> { + //~^ ERROR of `Fn`-family traits' type parameters is subject to change +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr new file mode 100644 index 000000000..9da36906d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr @@ -0,0 +1,21 @@ +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:17 + | +LL | fn bar1(x: &dyn Fn<(), Output=()>) { + | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:7:28 + | +LL | fn bar2(x: &T) where T: Fn<()> { + | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs new file mode 100644 index 000000000..65f40075b --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs @@ -0,0 +1,36 @@ +// Test interaction between unboxed closure sugar and region +// parameters (should be exactly as if angle brackets were used +// and regions omitted). + +#![feature(unboxed_closures)] +#![allow(dead_code)] + +use std::marker; + +trait Foo<'a,T> { + type Output; + fn dummy(&'a self) -> &'a (T,Self::Output); +} + +trait Eq { fn is_of_eq_type(&self, x: &X) -> bool { true } } +impl Eq for X { } +fn eq>() { } + +fn same_type>(a: A, b: B) { } + +fn test<'a,'b>() { + // Parens are equivalent to omitting default in angle. + eq::< dyn Foo<(isize,),Output=()>, dyn Foo(isize) >(); + + // Here we specify 'static explicitly in angle-bracket version. + // Parenthesized winds up getting inferred. + eq::< dyn Foo<'static, (isize,),Output=()>, dyn Foo(isize) >(); +} + +fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { + //~^ ERROR this trait takes 1 lifetime argument but 0 lifetime arguments were supplied + // Here, the omitted lifetimes are expanded to distinct things. + same_type(x, y) +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr new file mode 100644 index 000000000..016fc4dfb --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr @@ -0,0 +1,15 @@ +error[E0107]: this trait takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/unboxed-closure-sugar-region.rs:30:51 + | +LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { + | ^^^ expected 1 lifetime argument + | +note: trait defined here, with 1 lifetime parameter: `'a` + --> $DIR/unboxed-closure-sugar-region.rs:10:7 + | +LL | trait Foo<'a,T> { + | ^^^ -- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs new file mode 100644 index 000000000..462f6fb7b --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs @@ -0,0 +1,13 @@ +// Test that parentheses form doesn't work with struct types appearing in local variables. + +struct Bar { + f: A +} + +fn bar() { + let x: Box = panic!(); + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR this struct takes 1 generic argument but 0 generic arguments +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr new file mode 100644 index 000000000..29ea5735c --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr @@ -0,0 +1,26 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 + | +LL | let x: Box = panic!(); + | ^^^^^ only `Fn` traits may use parentheses + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 + | +LL | let x: Box = panic!(); + | ^^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `A` + --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:3:8 + | +LL | struct Bar { + | ^^^ - +help: add missing generic argument + | +LL | let x: Box = panic!(); + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs new file mode 100644 index 000000000..79ced1ecf --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs @@ -0,0 +1,18 @@ +// Test that parentheses form parses in expression paths. + +struct Bar { + f: A, r: R +} + +impl Bar { + fn new() -> Bar { panic!() } +} + +fn bar() { + let b = Bar::::new(); // OK + + let b = Bar::(isize, usize)::new(); // OK too (for the parser) + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait +} + +fn main() {} diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr new file mode 100644 index 000000000..4df404e81 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -0,0 +1,14 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:13 + | +LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) + | ^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses + | +help: use angle brackets instead + | +LL | let b = Bar::::new(); // OK too (for the parser) + | ~ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0214`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs new file mode 100644 index 000000000..bd61cbd80 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs @@ -0,0 +1,12 @@ +// Test that parentheses form doesn't work with struct types appearing in argument types. + +struct Bar { + f: A +} + +fn foo(b: Box) { + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR this struct takes 1 generic argument but 0 generic arguments +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr new file mode 100644 index 000000000..427ba3414 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr @@ -0,0 +1,26 @@ +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 + | +LL | fn foo(b: Box) { + | ^^^^^ only `Fn` traits may use parentheses + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 + | +LL | fn foo(b: Box) { + | ^^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `A` + --> $DIR/unboxed-closure-sugar-used-on-struct.rs:3:8 + | +LL | struct Bar { + | ^^^ - +help: add missing generic argument + | +LL | fn foo(b: Box) { + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs new file mode 100644 index 000000000..a6c86311b --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs @@ -0,0 +1,8 @@ +#![feature(unboxed_closures)] + +trait One { fn foo(&self) -> A; } + +fn foo(_: &dyn One()) //~ ERROR associated type `Output` not found for `One<()>` +{} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr new file mode 100644 index 000000000..59e7bc8c8 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-1.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Output` not found for `One<()>` + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-1.rs:5:16 + | +LL | fn foo(_: &dyn One()) + | ^^^^^ associated type `Output` not found + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs new file mode 100644 index 000000000..f26ad8e93 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs @@ -0,0 +1,10 @@ +#![feature(unboxed_closures)] + +trait Three { fn dummy(&self) -> (A,B,C); } + +fn foo(_: &dyn Three()) +//~^ ERROR this trait takes 3 generic arguments but 1 generic argument +//~| ERROR associated type `Output` not found +{} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr new file mode 100644 index 000000000..ebaacf0a6 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr @@ -0,0 +1,24 @@ +error[E0107]: this trait takes 3 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16 + | +LL | fn foo(_: &dyn Three()) + | ^^^^^-- supplied 1 generic argument + | | + | expected 3 generic arguments + | +note: trait defined here, with 3 generic parameters: `A`, `B`, `C` + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:3:7 + | +LL | trait Three { fn dummy(&self) -> (A,B,C); } + | ^^^^^ - - - + +error[E0220]: associated type `Output` not found for `Three<(), [type error], [type error]>` + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16 + | +LL | fn foo(_: &dyn Three()) + | ^^^^^^^ associated type `Output` not found + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0220. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs new file mode 100644 index 000000000..4465b43a7 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs @@ -0,0 +1,28 @@ +#![feature(unboxed_closures)] + +trait Zero { fn dummy(&self); } + +fn foo1(_: dyn Zero()) { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + //~| ERROR associated type `Output` not found for `Zero` +} + +fn foo2(_: dyn Zero) { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument +} + +fn foo3(_: dyn Zero < usize >) { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument +} + +fn foo4(_: dyn Zero(usize)) { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + //~| ERROR associated type `Output` not found for `Zero` +} + +fn foo5(_: dyn Zero ( usize )) { + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + //~| ERROR associated type `Output` not found for `Zero` +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr new file mode 100644 index 000000000..9601e64c1 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr @@ -0,0 +1,92 @@ +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16 + | +LL | fn foo1(_: dyn Zero()) { + | ^^^^-- help: remove these parenthetical generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7 + | +LL | trait Zero { fn dummy(&self); } + | ^^^^ + +error[E0220]: associated type `Output` not found for `Zero` + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16 + | +LL | fn foo1(_: dyn Zero()) { + | ^^^^^^ associated type `Output` not found + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:10:16 + | +LL | fn foo2(_: dyn Zero) { + | ^^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7 + | +LL | trait Zero { fn dummy(&self); } + | ^^^^ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:14:16 + | +LL | fn foo3(_: dyn Zero < usize >) { + | ^^^^-------------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7 + | +LL | trait Zero { fn dummy(&self); } + | ^^^^ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16 + | +LL | fn foo4(_: dyn Zero(usize)) { + | ^^^^------- help: remove these parenthetical generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7 + | +LL | trait Zero { fn dummy(&self); } + | ^^^^ + +error[E0220]: associated type `Output` not found for `Zero` + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16 + | +LL | fn foo4(_: dyn Zero(usize)) { + | ^^^^^^^^^^^ associated type `Output` not found + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16 + | +LL | fn foo5(_: dyn Zero ( usize )) { + | ^^^^-------------- help: remove these parenthetical generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:3:7 + | +LL | trait Zero { fn dummy(&self); } + | ^^^^ + +error[E0220]: associated type `Output` not found for `Zero` + --> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16 + | +LL | fn foo5(_: dyn Zero ( usize )) { + | ^^^^^^^^^^^^^^^^^^ associated type `Output` not found + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0107, E0220. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs new file mode 100644 index 000000000..4bcf90552 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs @@ -0,0 +1,9 @@ +#![feature(unboxed_closures)] + +trait Trait {} + +fn f isize>(x: F) {} +//~^ ERROR this trait takes 0 generic arguments but 1 generic argument +//~| ERROR associated type `Output` not found for `Trait` + +fn main() {} diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr new file mode 100644 index 000000000..3ff05fb23 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr @@ -0,0 +1,24 @@ +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:8 + | +LL | fn f isize>(x: F) {} + | ^^^^^------- help: remove these parenthetical generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/unboxed-closure-sugar-wrong-trait.rs:3:7 + | +LL | trait Trait {} + | ^^^^^ + +error[E0220]: associated type `Output` not found for `Trait` + --> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:24 + | +LL | fn f isize>(x: F) {} + | ^^^^^ associated type `Output` not found + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0220. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs b/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs new file mode 100644 index 000000000..dfccb0200 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(lang_items)] + +fn a isize>(f: F) -> isize { + f(1, 2) +} + +fn b isize>(mut f: F) -> isize { + f(3, 4) +} + +fn c isize>(f: F) -> isize { + f(5, 6) +} + +fn main() { + let z: isize = 7; + assert_eq!(a(move |x: isize, y| x + y + z), 10); + assert_eq!(b(move |x: isize, y| x + y + z), 14); + assert_eq!(c(move |x: isize, y| x + y + z), 18); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs new file mode 100644 index 000000000..a10016735 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(unused_variables)] +// Test that you can supply `&F` where `F: FnMut()`. + +#![feature(lang_items)] + +fn a i32>(mut f: F) -> i32 { + f() +} + +fn b(f: &mut dyn FnMut() -> i32) -> i32 { + a(f) +} + +fn c i32>(f: &mut F) -> i32 { + a(f) +} + +fn main() { + let z: isize = 7; + + let x = b(&mut || 22); + assert_eq!(x, 22); + + let x = c(&mut || 22); + assert_eq!(x, 22); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs new file mode 100644 index 000000000..ca1d31ca5 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(unused_variables)] +// Test that you can supply `&F` where `F: Fn()`. + +#![feature(lang_items)] + +fn a i32>(f: F) -> i32 { + f() +} + +fn b(f: &dyn Fn() -> i32) -> i32 { + a(f) +} + +fn c i32>(f: &F) -> i32 { + a(f) +} + +fn main() { + let z: isize = 7; + + let x = b(&|| 22); + assert_eq!(x, 22); + + let x = c(&|| 22); + assert_eq!(x, 22); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs new file mode 100644 index 000000000..835a1f598 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs @@ -0,0 +1,11 @@ +// Test that an unboxed closure that mutates a free variable will +// cause borrow conflicts. + + + +fn main() { + let mut x = 0; + let f = || x += 1; + let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed + f; +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr new file mode 100644 index 000000000..21d6b4fde --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr @@ -0,0 +1,15 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/unboxed-closures-borrow-conflict.rs:9:14 + | +LL | let f = || x += 1; + | -- - borrow occurs due to use of `x` in closure + | | + | borrow of `x` occurs here +LL | let _y = x; + | ^ use of borrowed `x` +LL | f; + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-boxed.rs b/tests/ui/unboxed-closures/unboxed-closures-boxed.rs new file mode 100644 index 000000000..3f550fd04 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-boxed.rs @@ -0,0 +1,15 @@ +// run-pass + +use std::ops::FnMut; + + fn make_adder(x: i32) -> Boxi32+'static> { + Box::new(move |y: i32| -> i32 { x + y }) as + Boxi32+'static> +} + +pub fn main() { + let mut adder = make_adder(3); + let z = adder(2); + println!("{}", z); + assert_eq!(z, 5); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-by-ref.rs b/tests/ui/unboxed-closures/unboxed-closures-by-ref.rs new file mode 100644 index 000000000..cf4d4d3e1 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-by-ref.rs @@ -0,0 +1,24 @@ +// run-pass +// Test by-ref capture of environment in unboxed closure types + +fn call_fn(f: F) { + f() +} + +fn call_fn_mut(mut f: F) { + f() +} + +fn call_fn_once(f: F) { + f() +} + +fn main() { + let mut x = 0_usize; + let y = 2_usize; + + call_fn(|| assert_eq!(x, 0)); + call_fn_mut(|| x += y); + call_fn_once(|| x += y); + assert_eq!(x, y * 2); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-fn-autoderef.rs b/tests/ui/unboxed-closures/unboxed-closures-call-fn-autoderef.rs new file mode 100644 index 000000000..e23a75ab3 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-call-fn-autoderef.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_imports)] +// Test that the call operator autoderefs when calling a bounded type parameter. + +use std::ops::FnMut; + +fn call_with_2(x: &fn(isize) -> isize) -> isize +{ + x(2) // look ma, no `*` +} + +fn subtract_22(x: isize) -> isize { x - 22 } + +pub fn main() { + let subtract_22: fn(isize) -> isize = subtract_22; + let z = call_with_2(&subtract_22); + assert_eq!(z, -20); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs new file mode 100644 index 000000000..9b8a3f409 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs @@ -0,0 +1,15 @@ +// run-pass +// Test that the call operator autoderefs when calling a bounded type parameter. + +use std::ops::FnMut; + +fn call_with_2(x: &mut F) -> isize + where F : FnMut(isize) -> isize +{ + x(2) // look ma, no `*` +} + +pub fn main() { + let z = call_with_2(&mut |x| x - 22); + assert_eq!(z, -20); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs new file mode 100644 index 000000000..d47ceea0f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs @@ -0,0 +1,15 @@ +// run-pass +// Test that the call operator autoderefs when calling to an object type. + +use std::ops::FnMut; + +fn make_adder(x: isize) -> Boxisize + 'static> { + Box::new(move |y| { x + y }) +} + +pub fn main() { + let mut adder = make_adder(3); + let z = adder(2); + println!("{}", z); + assert_eq!(z, 5); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs new file mode 100644 index 000000000..f77733d10 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs @@ -0,0 +1,13 @@ +// run-pass +use std::ops::FnMut; + +fn make_adder(x: isize) -> Boxisize + 'static> { + Box::new(move |y| { x + y }) +} + +pub fn main() { + let mut adder = make_adder(3); + let z = (*adder)(2); + println!("{}", z); + assert_eq!(z, 5); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs b/tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs new file mode 100644 index 000000000..390386e57 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs @@ -0,0 +1,28 @@ +// run-pass +// Test that we mutate a counter on the stack only when we expect to. + +fn call(f: F) where F : FnOnce() { + f(); +} + +fn main() { + let y = vec![format!("Hello"), format!("World")]; + let mut counter = 22_u32; + + call(|| { + // Move `y`, but do not move `counter`, even though it is read + // by value (note that it is also mutated). + for item in y { //~ WARN unused variable: `item` + let v = counter; + counter += v; + } + }); + assert_eq!(counter, 88); + + call(move || { + // this mutates a moved copy, and hence doesn't affect original + counter += 1; //~ WARN value assigned to `counter` is never read + //~| WARN unused variable: `counter` + }); + assert_eq!(counter, 88); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr b/tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr new file mode 100644 index 000000000..6450cc30a --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr @@ -0,0 +1,27 @@ +warning: unused variable: `item` + --> $DIR/unboxed-closures-counter-not-moved.rs:15:13 + | +LL | for item in y { + | ^^^^ help: if this is intentional, prefix it with an underscore: `_item` + | + = note: `#[warn(unused_variables)]` on by default + +warning: value assigned to `counter` is never read + --> $DIR/unboxed-closures-counter-not-moved.rs:24:9 + | +LL | counter += 1; + | ^^^^^^^ + | + = help: maybe it is overwritten before being read? + = note: `#[warn(unused_assignments)]` on by default + +warning: unused variable: `counter` + --> $DIR/unboxed-closures-counter-not-moved.rs:24:9 + | +LL | counter += 1; + | ^^^^^^^ + | + = help: did you mean to capture by reference instead? + +warning: 3 warnings emitted + diff --git a/tests/ui/unboxed-closures/unboxed-closures-cross-crate.rs b/tests/ui/unboxed-closures/unboxed-closures-cross-crate.rs new file mode 100644 index 000000000..39cc26072 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-cross-crate.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(non_camel_case_types)] + +// Test that unboxed closures work with cross-crate inlining +// Acts as a regression test for #16790, #18378 and #18543 + +// aux-build:unboxed-closures-cross-crate.rs + +extern crate unboxed_closures_cross_crate as ubcc; + +fn main() { + assert_eq!(ubcc::has_closures(), 2_usize); + assert_eq!(ubcc::has_generic_closures(2_usize, 3_usize), 5_usize); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-direct-sugary-call.rs b/tests/ui/unboxed-closures/unboxed-closures-direct-sugary-call.rs new file mode 100644 index 000000000..1c5e74e59 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-direct-sugary-call.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_mut)] +// pretty-expanded FIXME #23616 + +fn main() { + let mut unboxed = || {}; + unboxed(); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-drop.rs b/tests/ui/unboxed-closures/unboxed-closures-drop.rs new file mode 100644 index 000000000..ba3c61ca2 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-drop.rs @@ -0,0 +1,117 @@ +// run-pass +#![allow(path_statements)] +#![allow(dead_code)] +// A battery of tests to ensure destructors of unboxed closure environments +// run at the right times. + +static mut DROP_COUNT: usize = 0; + +fn drop_count() -> usize { + unsafe { + DROP_COUNT + } +} + +struct Droppable { + x: isize, +} + +impl Droppable { + fn new() -> Droppable { + Droppable { + x: 1 + } + } +} + +impl Drop for Droppable { + fn drop(&mut self) { + unsafe { + DROP_COUNT += 1 + } + } +} + +fn a isize>(f: F) -> isize { + f(1, 2) +} + +fn b isize>(mut f: F) -> isize { + f(3, 4) +} + +fn c isize>(f: F) -> isize { + f(5, 6) +} + +fn test_fn() { + { + a(move |a: isize, b| { a + b }); + } + assert_eq!(drop_count(), 0); + + { + let z = &Droppable::new(); + a(move |a: isize, b| { z; a + b }); + assert_eq!(drop_count(), 0); + } + assert_eq!(drop_count(), 1); + + { + let z = &Droppable::new(); + let zz = &Droppable::new(); + a(move |a: isize, b| { z; zz; a + b }); + assert_eq!(drop_count(), 1); + } + assert_eq!(drop_count(), 3); +} + +fn test_fn_mut() { + { + b(move |a: isize, b| { a + b }); + } + assert_eq!(drop_count(), 3); + + { + let z = &Droppable::new(); + b(move |a: isize, b| { z; a + b }); + assert_eq!(drop_count(), 3); + } + assert_eq!(drop_count(), 4); + + { + let z = &Droppable::new(); + let zz = &Droppable::new(); + b(move |a: isize, b| { z; zz; a + b }); + assert_eq!(drop_count(), 4); + } + assert_eq!(drop_count(), 6); +} + +fn test_fn_once() { + { + c(move |a: isize, b| { a + b }); + } + assert_eq!(drop_count(), 6); + + { + let z = Droppable::new(); + c(move |a: isize, b| { z; a + b }); + assert_eq!(drop_count(), 7); + } + assert_eq!(drop_count(), 7); + + { + let z = Droppable::new(); + let zz = Droppable::new(); + c(move |a: isize, b| { z; zz; a + b }); + assert_eq!(drop_count(), 9); + } + assert_eq!(drop_count(), 9); +} + +fn main() { + test_fn(); + test_fn_mut(); + test_fn_once(); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-extern-fn-hr.rs b/tests/ui/unboxed-closures/unboxed-closures-extern-fn-hr.rs new file mode 100644 index 000000000..3ee1aeb10 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-extern-fn-hr.rs @@ -0,0 +1,31 @@ +// run-pass +// Checks that higher-ranked extern fn pointers implement the full range of Fn traits. + +fn square(x: &isize) -> isize { (*x) * (*x) } + +fn call_itisize>(f: &F, x: isize) -> isize { + (*f)(&x) +} + +fn call_it_boxed(f: &dyn Fn(&isize) -> isize, x: isize) -> isize { + f(&x) +} + +fn call_it_mutisize>(f: &mut F, x: isize) -> isize { + (*f)(&x) +} + +fn call_it_onceisize>(f: F, x: isize) -> isize { + f(&x) +} + +fn main() { + let x = call_it(&square, 22); + let x1 = call_it_boxed(&square, 22); + let y = call_it_mut(&mut square, 22); + let z = call_it_once(square, 22); + assert_eq!(x, square(&22)); + assert_eq!(x1, square(&22)); + assert_eq!(y, square(&22)); + assert_eq!(z, square(&22)); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs new file mode 100644 index 000000000..677cd259a --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs @@ -0,0 +1,27 @@ +// run-pass +// Checks that extern fn pointers implement the full range of Fn traits. + +use std::ops::{Fn,FnMut,FnOnce}; + +fn square(x: isize) -> isize { x * x } + +fn call_itisize>(f: &F, x: isize) -> isize { + f(x) +} + +fn call_it_mutisize>(f: &mut F, x: isize) -> isize { + f(x) +} + +fn call_it_onceisize>(f: F, x: isize) -> isize { + f(x) +} + +fn main() { + let x = call_it(&square, 22); + let y = call_it_mut(&mut square, 22); + let z = call_it_once(square, 22); + assert_eq!(x, square(22)); + assert_eq!(y, square(22)); + assert_eq!(z, square(22)); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs new file mode 100644 index 000000000..1358ba0f9 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.rs @@ -0,0 +1,37 @@ +// Various unsuccessful attempts to put the unboxed closure kind +// inference into an awkward position that might require fixed point +// iteration (basically where inferring the kind of a closure `c` +// would require knowing the kind of `c`). I currently believe this is +// impossible. + +fn a() { + // This case of recursion wouldn't even require fixed-point + // iteration, but it still doesn't work. The weird structure with + // the `Option` is to avoid giving any useful hints about the `Fn` + // kind via the expected type. + let mut factorial: Option u32>> = None; + + let f = |x: u32| -> u32 { + let g = factorial.as_ref().unwrap(); + //~^ ERROR `factorial` does not live long enough + if x == 0 {1} else {x * g(x-1)} + }; + + factorial = Some(Box::new(f)); + //~^ ERROR cannot assign to `factorial` because it is borrowed +} + +fn b() { + let mut factorial: Option u32 + 'static>> = None; + + let f = |x: u32| -> u32 { + let g = factorial.as_ref().unwrap(); + //~^ ERROR `factorial` does not live long enough + if x == 0 {1} else {x * g(x-1)} + }; + + factorial = Some(Box::new(f)); + //~^ ERROR cannot assign to `factorial` because it is borrowed +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr new file mode 100644 index 000000000..cbdb4dd0f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr @@ -0,0 +1,60 @@ +error[E0597]: `factorial` does not live long enough + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17 + | +LL | let f = |x: u32| -> u32 { + | --------------- value captured here +LL | let g = factorial.as_ref().unwrap(); + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - + | | + | `factorial` dropped here while still borrowed + | borrow might be used here, when `factorial` is dropped and runs the destructor for type `Option u32>>` + +error[E0506]: cannot assign to `factorial` because it is borrowed + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:20:5 + | +LL | let f = |x: u32| -> u32 { + | --------------- borrow of `factorial` occurs here +LL | let g = factorial.as_ref().unwrap(); + | --------- borrow occurs due to use in closure +... +LL | factorial = Some(Box::new(f)); + | ^^^^^^^^^ + | | + | assignment to borrowed `factorial` occurs here + | borrow later used here + +error[E0597]: `factorial` does not live long enough + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17 + | +LL | let mut factorial: Option u32 + 'static>> = None; + | ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static` +LL | +LL | let f = |x: u32| -> u32 { + | --------------- value captured here +LL | let g = factorial.as_ref().unwrap(); + | ^^^^^^^^^ borrowed value does not live long enough +... +LL | } + | - `factorial` dropped here while still borrowed + +error[E0506]: cannot assign to `factorial` because it is borrowed + --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:33:5 + | +LL | let mut factorial: Option u32 + 'static>> = None; + | ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static` +LL | +LL | let f = |x: u32| -> u32 { + | --------------- borrow of `factorial` occurs here +LL | let g = factorial.as_ref().unwrap(); + | --------- borrow occurs due to use in closure +... +LL | factorial = Some(Box::new(f)); + | ^^^^^^^^^ assignment to borrowed `factorial` occurs here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0506, E0597. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs new file mode 100644 index 000000000..25c2dbe19 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs @@ -0,0 +1,29 @@ +// Various unsuccessful attempts to put the unboxed closure kind +// inference into an awkward position that might require fixed point +// iteration (basically where inferring the kind of a closure `c` +// would require knowing the kind of `c`). I currently believe this is +// impossible. + +fn a() { + let mut closure0 = None; + //~^ ERROR type annotations needed + let vec = vec![1, 2, 3]; + + loop { + { + let closure1 = || { + match closure0.take() { + Some(c) => { + return c(); + } + None => { } + } + }; + closure1(); + } + + closure0 = || vec; + } +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr new file mode 100644 index 000000000..ff2a597be --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed for `Option` + --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:8:9 + | +LL | let mut closure0 = None; + | ^^^^^^^^^^^^ +... +LL | return c(); + | --- type must be known at this point + | +help: consider giving `closure0` an explicit type, where the placeholders `_` are specified + | +LL | let mut closure0: Option = None; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs new file mode 100644 index 000000000..851f3d2fe --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs @@ -0,0 +1,44 @@ +// run-pass +// Checks that the Fn trait hierarchy rules permit +// any Fn trait to be used where Fn is implemented. + +#![feature(unboxed_closures, fn_traits)] + +use std::ops::{Fn,FnMut,FnOnce}; + +struct S; + +impl Fn<(i32,)> for S { + extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 { + x * x + } +} + +impl FnMut<(i32,)> for S { + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } +} + +impl FnOnce<(i32,)> for S { + type Output = i32; + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } +} + +fn call_iti32>(f: &F, x: i32) -> i32 { + f(x) +} + +fn call_it_muti32>(f: &mut F, x: i32) -> i32 { + f(x) +} + +fn call_it_oncei32>(f: F, x: i32) -> i32 { + f(x) +} + +fn main() { + let x = call_it(&S, 22); + let y = call_it_mut(&mut S, 22); + let z = call_it_once(S, 22); + assert_eq!(x, y); + assert_eq!(y, z); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs new file mode 100644 index 000000000..867e5fb1d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs @@ -0,0 +1,29 @@ +// Checks that the Fn trait hierarchy rules do not permit +// Fn to be used where FnMut is implemented. + +#![feature(fn_traits, unboxed_closures)] + +use std::ops::{Fn,FnMut,FnOnce}; + +struct S; + +impl FnMut<(isize,)> for S { + extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize { + x * x + } +} + +impl FnOnce<(isize,)> for S { + type Output = isize; + + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } +} + +fn call_itisize>(f: &F, x: isize) -> isize { + f.call((x,)) +} + +fn main() { + let x = call_it(&S, 22); + //~^ ERROR E0277 +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr new file mode 100644 index 000000000..0ea1c1dcd --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -0,0 +1,19 @@ +error[E0277]: expected a `Fn<(isize,)>` closure, found `S` + --> $DIR/unboxed-closures-fnmut-as-fn.rs:27:21 + | +LL | let x = call_it(&S, 22); + | ------- ^^ expected an `Fn<(isize,)>` closure, found `S` + | | + | required by a bound introduced by this call + | + = help: the trait `Fn<(isize,)>` is not implemented for `S` + = note: `S` implements `FnMut`, but it must implement `Fn`, which is more general +note: required by a bound in `call_it` + --> $DIR/unboxed-closures-fnmut-as-fn.rs:22:14 + | +LL | fn call_itisize>(f: &F, x: isize) -> isize { + | ^^^^^^^^^^^^^^^^ required by this bound in `call_it` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs new file mode 100644 index 000000000..bd577f7c4 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs @@ -0,0 +1,33 @@ +// run-pass +// Checks that the Fn trait hierarchy rules permit +// FnMut or FnOnce to be used where FnMut is implemented. + +#![feature(unboxed_closures, fn_traits)] + +struct S; + +impl FnMut<(i32,)> for S { + extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { + x * x + } +} + +impl FnOnce<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } +} + +fn call_it_muti32>(f: &mut F, x: i32) -> i32 { + f(x) +} + +fn call_it_oncei32>(f: F, x: i32) -> i32 { + f(x) +} + +fn main() { + let y = call_it_mut(&mut S, 22); + let z = call_it_once(S, 22); + assert_eq!(y, z); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-generic.rs b/tests/ui/unboxed-closures/unboxed-closures-generic.rs new file mode 100644 index 000000000..740b8b2a7 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-generic.rs @@ -0,0 +1,13 @@ +// run-pass +use std::ops::FnMut; + +fn call_iti32>(y: i32, mut f: F) -> i32 { + f(2, y) +} + +pub fn main() { + let f = |x: i32, y: i32| -> i32 { x + y }; + let z = call_it(3, f); + println!("{}", z); + assert_eq!(z, 5); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-bound.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-bound.rs new file mode 100644 index 000000000..e0c910576 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-bound.rs @@ -0,0 +1,23 @@ +// run-pass +// Test that we are able to infer that the type of `x` is `isize` based +// on the expected type from the object. + +// pretty-expanded FIXME #23616 + +pub trait ToPrimitive { + fn to_int(&self) {} +} + +impl ToPrimitive for isize {} +impl ToPrimitive for i32 {} +impl ToPrimitive for usize {} + +fn doit(val: T, f: &F) + where F : Fn(T) +{ + f(val) +} + +pub fn main() { + doit(0, &|x /*: isize*/ | { x.to_int(); }); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-object-type.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-object-type.rs new file mode 100644 index 000000000..d2eaee304 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-from-expected-object-type.rs @@ -0,0 +1,19 @@ +// run-pass +// Test that we are able to infer that the type of `x` is `isize` based +// on the expected type from the object. + +// pretty-expanded FIXME #23616 + +pub trait ToPrimitive { + fn to_int(&self) {} +} + +impl ToPrimitive for isize {} +impl ToPrimitive for i32 {} +impl ToPrimitive for usize {} + +fn doit(val: T, f: &dyn Fn(T)) { f(val) } + +pub fn main() { + doit(0, &|x /*: isize*/ | { x.to_int(); }); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-w-bound-regs-from-expected-bound.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-w-bound-regs-from-expected-bound.rs new file mode 100644 index 000000000..c3abdd8aa --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-arg-types-w-bound-regs-from-expected-bound.rs @@ -0,0 +1,23 @@ +// run-pass +// Test that we are able to infer that the type of `x` is `isize` based +// on the expected type from the object. + +// pretty-expanded FIXME #23616 + +pub trait ToPrimitive { + fn to_int(&self) {} +} + +impl ToPrimitive for isize {} +impl ToPrimitive for i32 {} +impl ToPrimitive for usize {} + +fn doit(val: T, f: &F) + where F : Fn(&T) +{ + f(&val) +} + +pub fn main() { + doit(0, &|x /*: isize*/ | { x.to_int(); }); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs new file mode 100644 index 000000000..6765da421 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs @@ -0,0 +1,20 @@ +#![feature(fn_traits)] + +// That a closure whose expected argument types include two distinct +// bound regions. + +use std::cell::Cell; + +fn doit(val: T, f: &F) + where F : Fn(&Cell<&T>, &T) +{ + let x = Cell::new(&val); + f.call((&x,&val)) +} + +pub fn main() { + doit(0, &|x, y| { + x.set(y); + //~^ lifetime may not live long enough + }); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr new file mode 100644 index 000000000..e97157b83 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr @@ -0,0 +1,12 @@ +error: lifetime may not live long enough + --> $DIR/unboxed-closures-infer-argument-types-two-region-pointers.rs:17:9 + | +LL | doit(0, &|x, y| { + | - - has type `&'1 i32` + | | + | has type `&Cell<&'2 i32>` +LL | x.set(y); + | ^^^^^^^^ argument requires that `'1` must outlive `'2` + +error: aborting due to previous error + diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-explicit-call-early.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-explicit-call-early.rs new file mode 100644 index 000000000..9135c82b4 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-explicit-call-early.rs @@ -0,0 +1,8 @@ +// run-pass +#![feature(fn_traits)] + +fn main() { + let mut zero = || 0; + let x = zero.call_mut(()); + assert_eq!(x, 0); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs new file mode 100644 index 000000000..6e404c616 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.rs @@ -0,0 +1,16 @@ +#![allow(unused)] + +fn foo(f: F) + where F: Fn() +{ +} + +fn main() { + // Test that this closure is inferred to `FnOnce` because it moves + // from `y.0`. This affects the error output (the error is that + // the closure implements `FnOnce`, not that it moves from inside + // a `Fn` closure.) + let y = (vec![1, 2, 3], 0); + let c = || drop(y.0); //~ ERROR expected a closure that implements the `Fn` trait + foo(c); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr new file mode 100644 index 000000000..635ebbb71 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -0,0 +1,23 @@ +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13 + | +LL | let c = || drop(y.0); + | ^^ --- closure is `FnOnce` because it moves the variable `y` out of its environment + | | + | this closure implements `FnOnce`, not `Fn` +LL | foo(c); + | --- - the requirement to implement `Fn` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:4:14 + | +LL | fn foo(f: F) + | --- required by a bound in this +LL | where F: Fn() + | ^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs new file mode 100644 index 000000000..6401b5e01 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs @@ -0,0 +1,20 @@ +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +fn main() { + let mut counter = 0; + + // Here this must be inferred to FnMut so that it can mutate counter, + // but we forgot the mut. + let tick1 = || { + counter += 1; + }; + + // In turn, tick2 must be inferred to FnMut so that it can call + // tick1, but we forgot the mut. + let tick2 = || { + tick1(); //~ ERROR cannot borrow `tick1` as mutable + }; + + tick2(); //~ ERROR cannot borrow +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr new file mode 100644 index 000000000..5c93ed6d7 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -0,0 +1,28 @@ +error[E0596]: cannot borrow `tick1` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:16:9 + | +LL | let tick1 = || { + | ----- help: consider changing this to be mutable: `mut tick1` +LL | counter += 1; + | ------- calling `tick1` requires mutable binding due to mutable borrow of `counter` +... +LL | tick1(); + | ^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:19:5 + | +LL | tick1(); + | ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1` +... +LL | tick2(); + | ^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick2 = || { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut.rs new file mode 100644 index 000000000..73f488a4f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut.rs @@ -0,0 +1,19 @@ +// run-pass +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +fn main() { + let mut counter = 0; + + { + // Here this must be inferred to FnMut so that it can mutate counter: + let mut tick1 = || counter += 1; + + // In turn, tick2 must be inferred to FnMut so that it can call tick1: + let mut tick2 = || { tick1(); tick1(); }; + + tick2(); + } + + assert_eq!(counter, 2); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs new file mode 100644 index 000000000..5c0ceb23d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.rs @@ -0,0 +1,8 @@ +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +fn main() { + let mut counter = 0; + let tick = || counter += 1; + tick(); //~ ERROR cannot borrow `tick` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr new file mode 100644 index 000000000..3f539c42d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -0,0 +1,16 @@ +error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5 + | +LL | let tick = || counter += 1; + | ------- calling `tick` requires mutable binding due to mutable borrow of `counter` +LL | tick(); + | ^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick = || counter += 1; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs new file mode 100644 index 000000000..144a674ac --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.rs @@ -0,0 +1,8 @@ +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +fn main() { + let mut counter = 0; + let tick = move || counter += 1; + tick(); //~ ERROR cannot borrow `tick` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr new file mode 100644 index 000000000..e3b19297b --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -0,0 +1,16 @@ +error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable + --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5 + | +LL | let tick = move || counter += 1; + | ------- calling `tick` requires mutable binding due to possible mutation of `counter` +LL | tick(); + | ^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick = move || counter += 1; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move.rs new file mode 100644 index 000000000..7ac1ae30f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut-move.rs @@ -0,0 +1,16 @@ +// run-pass +// Test that we are able to infer a suitable kind for this `move` +// closure that is just called (`FnMut`). + +fn main() { + let mut counter = 0; + + let v = { + let mut tick = move || { counter += 1; counter }; + tick(); + tick() + }; + + assert_eq!(counter, 0); + assert_eq!(v, 2); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut.rs new file mode 100644 index 000000000..0fbb504c2 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnmut.rs @@ -0,0 +1,15 @@ +// run-pass +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +fn main() { + let mut counter = 0; + + { + let mut tick = || counter += 1; + tick(); + tick(); + } + + assert_eq!(counter, 2); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs new file mode 100644 index 000000000..a98a01ca5 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.rs @@ -0,0 +1,11 @@ +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +use std::mem; + +fn main() { + let mut counter: Vec = Vec::new(); + let tick = || mem::drop(counter); + tick(); + tick(); //~ ERROR use of moved value: `tick` +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr new file mode 100644 index 000000000..ab6f06518 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `tick` + --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5 + | +LL | tick(); + | ------ `tick` moved due to this call +LL | tick(); + | ^^^^ value used here after move + | +note: closure cannot be invoked more than once because it moves the variable `counter` out of its environment + --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:8:29 + | +LL | let tick = || mem::drop(counter); + | ^^^^^^^ +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:9:5 + | +LL | tick(); + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs new file mode 100644 index 000000000..f87be4a06 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.rs @@ -0,0 +1,11 @@ +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnMut`). + +use std::mem; + +fn main() { + let mut counter: Vec = Vec::new(); + let tick = move || mem::drop(counter); + tick(); + tick(); //~ ERROR use of moved value: `tick` +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr new file mode 100644 index 000000000..8d70a2b17 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `tick` + --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5 + | +LL | tick(); + | ------ `tick` moved due to this call +LL | tick(); + | ^^^^ value used here after move + | +note: closure cannot be invoked more than once because it moves the variable `counter` out of its environment + --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:8:34 + | +LL | let tick = move || mem::drop(counter); + | ^^^^^^^ +note: this value implements `FnOnce`, which causes it to be moved when called + --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:9:5 + | +LL | tick(); + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move.rs new file mode 100644 index 000000000..6381386c4 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce-move.rs @@ -0,0 +1,25 @@ +// run-pass +// Test that we are able to infer a suitable kind for this `move` +// closure that is just called (`FnOnce`). + +use std::mem; + +struct DropMe<'a>(&'a mut i32); + +impl<'a> Drop for DropMe<'a> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +fn main() { + let mut counter = 0; + + { + let drop_me = DropMe(&mut counter); + let tick = move || mem::drop(drop_me); + tick(); + } + + assert_eq!(counter, 1); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce.rs new file mode 100644 index 000000000..3c8ea7d85 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fnonce.rs @@ -0,0 +1,25 @@ +// run-pass +// Test that we are able to infer a suitable kind for this closure +// that is just called (`FnOnce`). + +use std::mem; + +struct DropMe<'a>(&'a mut i32); + +impl<'a> Drop for DropMe<'a> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +fn main() { + let mut counter = 0; + + { + let drop_me = DropMe(&mut counter); + let tick = || mem::drop(drop_me); + tick(); + } + + assert_eq!(counter, 1); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-kind.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-kind.rs new file mode 100644 index 000000000..fc01bd9b6 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-kind.rs @@ -0,0 +1,27 @@ +// run-pass +// Test that we can infer the "kind" of an unboxed closure based on +// the expected type. + +// Test by-ref capture of environment in unboxed closure types + +fn call_fn(f: F) { + f() +} + +fn call_fn_mut(mut f: F) { + f() +} + +fn call_fn_once(f: F) { + f() +} + +fn main() { + let mut x = 0_usize; + let y = 2_usize; + + call_fn(|| assert_eq!(x, 0)); + call_fn_mut(|| x += y); + call_fn_once(|| x += y); + assert_eq!(x, y * 2); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs new file mode 100644 index 000000000..a0fbbafe2 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs @@ -0,0 +1,45 @@ +// run-pass +#![feature(fn_traits, unboxed_closures)] + +use std::marker::PhantomData; + +// Test that we are able to infer a suitable kind for a "recursive" +// closure. As far as I can tell, coding up a recursive closure +// requires the good ol' [Y Combinator]. +// +// [Y Combinator]: https://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator + +struct YCombinator { + func: F, + marker: PhantomData<(A,R)>, +} + +impl YCombinator { + fn new(f: F) -> YCombinator { + YCombinator { func: f, marker: PhantomData } + } +} + +impl R, A) -> R> Fn<(A,)> for YCombinator { + extern "rust-call" fn call(&self, (arg,): (A,)) -> R { + (self.func)(self, arg) + } +} + +impl R, A) -> R> FnMut<(A,)> for YCombinator { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) } +} + +impl R, A) -> R> FnOnce<(A,)> for YCombinator { + type Output = R; + extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) } +} + +fn main() { + let factorial = |recur: &dyn Fn(u32) -> u32, arg: u32| -> u32 { + if arg == 0 {1} else {arg * recur(arg-1)} + }; + let factorial: YCombinator<_,u32,u32> = YCombinator::new(factorial); + let r = factorial(10); + assert_eq!(3628800, r); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-upvar.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-upvar.rs new file mode 100644 index 000000000..6a5e5b9c2 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-upvar.rs @@ -0,0 +1,13 @@ +// run-pass +// Test that the type variable in the type(`Vec<_>`) of a closed over +// variable does not interfere with type inference. + +fn f(mut f: F) { + f(); +} + +fn main() { + let mut v: Vec<_> = vec![]; + f(|| v.push(0)); + assert_eq!(v, [0]); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs b/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs new file mode 100644 index 000000000..df60b42ab --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs @@ -0,0 +1,31 @@ +// run-pass +#![feature(unboxed_closures, fn_traits)] + +struct S; + +impl FnMut<(i32,)> for S { + extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 { + x * x + } +} + +impl FnOnce<(i32,)> for S { + type Output = i32; + + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } +} + +fn call_iti32>(mut f: F, x: i32) -> i32 { + f(x) + 3 +} + +fn call_box(f: &mut dyn FnMut(i32) -> i32, x: i32) -> i32 { + f(x) + 3 +} + +fn main() { + let x = call_it(S, 1); + let y = call_box(&mut S, 1); + assert_eq!(x, 4); + assert_eq!(y, 4); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-monomorphization.rs b/tests/ui/unboxed-closures/unboxed-closures-monomorphization.rs new file mode 100644 index 000000000..2df360d4a --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-monomorphization.rs @@ -0,0 +1,26 @@ +// run-pass +// Test that unboxed closures in contexts with free type parameters +// monomorphize correctly (issue #16791) + +fn main(){ + fn bar<'a, T:Clone+'a> (t: T) -> BoxT + 'a> { + Box::new(move || t.clone()) + } + + let mut f = bar(42_u32); + assert_eq!(f(), 42); + + let mut f = bar("forty-two"); + assert_eq!(f(), "forty-two"); + + let x = 42_u32; + let mut f = bar(&x); + assert_eq!(f(), &x); + + #[derive(Clone, Copy, Debug, PartialEq)] + struct Foo(usize, &'static str); + + let x = Foo(42, "forty-two"); + let mut f = bar(x); + assert_eq!(f(), x); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-move-from-projection-issue-30046.rs b/tests/ui/unboxed-closures/unboxed-closures-move-from-projection-issue-30046.rs new file mode 100644 index 000000000..4388e6bcf --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-move-from-projection-issue-30046.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused)] + +fn foo(f: F) + where F: FnOnce() +{ +} + +fn main() { + // Test that this closure is inferred to `FnOnce` + // because it moves from `y.as.0`: + let x = Some(vec![1, 2, 3]); + foo(|| { + match x { + Some(y) => { } + None => { } + } + }); + + // Test that this closure is inferred to `FnOnce` + // because it moves from `y.0`: + let y = (vec![1, 2, 3], 0); + foo(|| { + let x = y.0; + }); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-move-mutable.rs b/tests/ui/unboxed-closures/unboxed-closures-move-mutable.rs new file mode 100644 index 000000000..470904fd3 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-move-mutable.rs @@ -0,0 +1,31 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![deny(unused_mut)] +#![allow(unused_must_use)] + +// Test that mutating a mutable upvar in a capture-by-value unboxed +// closure does not ice (issue #18238) and marks the upvar as used +// mutably so we do not get a spurious warning about it not needing to +// be declared mutable (issue #18336 and #18769) + +fn set(x: &mut usize) { *x = 42; } + +fn main() { + { + let mut x = 0_usize; + move || x += 1; //~ WARN unused variable: `x` + } + { + let mut x = 0_usize; + move || x += 1; //~ WARN unused variable: `x` + } + { + let mut x = 0_usize; + move || set(&mut x); + } + { + let mut x = 0_usize; + move || set(&mut x); + } +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-move-mutable.stderr b/tests/ui/unboxed-closures/unboxed-closures-move-mutable.stderr new file mode 100644 index 000000000..5c06f4e62 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-move-mutable.stderr @@ -0,0 +1,19 @@ +warning: unused variable: `x` + --> $DIR/unboxed-closures-move-mutable.rs:17:17 + | +LL | move || x += 1; + | ^ + | + = help: did you mean to capture by reference instead? + = note: `#[warn(unused_variables)]` on by default + +warning: unused variable: `x` + --> $DIR/unboxed-closures-move-mutable.rs:21:17 + | +LL | move || x += 1; + | ^ + | + = help: did you mean to capture by reference instead? + +warning: 2 warnings emitted + diff --git a/tests/ui/unboxed-closures/unboxed-closures-move-some-upvars-in-by-ref-closure.rs b/tests/ui/unboxed-closures/unboxed-closures-move-some-upvars-in-by-ref-closure.rs new file mode 100644 index 000000000..2d219643f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-move-some-upvars-in-by-ref-closure.rs @@ -0,0 +1,23 @@ +// run-pass +// Test that in a by-ref once closure we move some variables even as +// we capture others by mutable reference. + +fn call(f: F) where F : FnOnce() { + f(); +} + +fn main() { + let mut x = vec![format!("Hello")]; + let y = vec![format!("World")]; + call(|| { + // Here: `x` must be captured with a mutable reference in + // order for us to append on it, and `y` must be captured by + // value. + for item in y { + x.push(item); + } + }); + assert_eq!(x.len(), 2); + assert_eq!(&*x[0], "Hello"); + assert_eq!(&*x[1], "World"); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs b/tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs new file mode 100644 index 000000000..c57312b43 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.rs @@ -0,0 +1,57 @@ +// Test that we cannot mutate an outer variable that is not declared +// as `mut` through a closure. Also test that we CAN mutate a moved copy, +// unless this is a `Fn` closure. Issue #16749. + +#![feature(unboxed_closures, tuple_trait)] + +use std::mem; + +fn to_fn>(f: F) -> F { f } +fn to_fn_mut>(f: F) -> F { f } + +fn a() { + let n = 0; + let mut f = to_fn_mut(|| { + n += 1; //~ ERROR cannot assign to `n`, as it is not declared as mutable + }); +} + +fn b() { + let mut n = 0; + let mut f = to_fn_mut(|| { + n += 1; // OK + }); +} + +fn c() { + let n = 0; + let mut f = to_fn_mut(move || { + // If we just did a straight-forward desugaring, this would + // compile, but we do something a bit more subtle, and hence + // we get an error. + n += 1; //~ ERROR cannot assign + }); +} + +fn d() { + let mut n = 0; + let mut f = to_fn_mut(move || { + n += 1; // OK + }); +} + +fn e() { + let n = 0; + let mut f = to_fn(move || { + n += 1; //~ ERROR cannot assign + }); +} + +fn f() { + let mut n = 0; + let mut f = to_fn(move || { + n += 1; //~ ERROR cannot assign + }); +} + +fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr new file mode 100644 index 000000000..26f97b519 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr @@ -0,0 +1,43 @@ +error[E0594]: cannot assign to `n`, as it is not declared as mutable + --> $DIR/unboxed-closures-mutate-upvar.rs:15:9 + | +LL | let n = 0; + | - help: consider changing this to be mutable: `mut n` +LL | let mut f = to_fn_mut(|| { +LL | n += 1; + | ^^^^^^ cannot assign + +error[E0594]: cannot assign to `n`, as it is not declared as mutable + --> $DIR/unboxed-closures-mutate-upvar.rs:32:9 + | +LL | let n = 0; + | - help: consider changing this to be mutable: `mut n` +... +LL | n += 1; + | ^^^^^^ cannot assign + +error[E0594]: cannot assign to `n`, as it is not declared as mutable + --> $DIR/unboxed-closures-mutate-upvar.rs:46:9 + | +LL | let n = 0; + | - help: consider changing this to be mutable: `mut n` +LL | let mut f = to_fn(move || { +LL | n += 1; + | ^^^^^^ cannot assign + +error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure + --> $DIR/unboxed-closures-mutate-upvar.rs:53:9 + | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | let mut f = to_fn(move || { + | ----- ------- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | n += 1; + | ^^^^^^ cannot assign + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs new file mode 100644 index 000000000..174ad245d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.rs @@ -0,0 +1,14 @@ +// Test that a by-ref `FnMut` closure gets an error when it tries to +// mutate a value. + +fn call(f: F) where F : Fn() { + f(); +} + +fn main() { + let mut counter = 0; + call(|| { + counter += 1; + //~^ ERROR cannot assign to `counter` + }); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr new file mode 100644 index 000000000..7d15cd0c8 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr @@ -0,0 +1,16 @@ +error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure + --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:11:9 + | +LL | fn call(f: F) where F : Fn() { + | - change this to accept `FnMut` instead of `Fn` +... +LL | call(|| { + | ---- -- in this closure + | | + | expects `Fn` instead of `FnMut` +LL | counter += 1; + | ^^^^^^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-prelude.rs b/tests/ui/unboxed-closures/unboxed-closures-prelude.rs new file mode 100644 index 000000000..89a273b7a --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-prelude.rs @@ -0,0 +1,18 @@ +// run-pass +// Tests that the re-exports of `FnOnce` et al from the prelude work. + +// pretty-expanded FIXME #23616 + +fn main() { + let task: Box isize> = Box::new(|x| x); + task(0); + + let mut task: Box isize> = Box::new(|x| x); + task(0); + + call(|x| x, 22); +} + +fn call isize>(f: F, x: isize) -> isize { + f(x) +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs new file mode 100644 index 000000000..5e354cb6f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs @@ -0,0 +1,43 @@ +#![feature(fn_traits, unboxed_closures)] + +use std::marker::PhantomData; + +// An erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs` +// where we attempt to perform mutation in the recursive function. This fails to compile +// because it winds up requiring `FnMut` which enforces linearity. + +struct YCombinator { + func: F, + marker: PhantomData<(A,R)>, +} + +impl YCombinator { + fn new(f: F) -> YCombinator { + YCombinator { func: f, marker: PhantomData } + } +} + +impl R, A) -> R> FnMut<(A,)> for YCombinator { + extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R { + (self.func)(self, arg) + //~^ ERROR cannot borrow `*self` as mutable more than once at a time + } +} + +impl R, A) -> R> FnOnce<(A,)> for YCombinator { + type Output = R; + extern "rust-call" fn call_once(mut self, args: (A,)) -> R { + self.call_mut(args) + } +} + +fn main() { + let mut counter = 0; + let factorial = |recur: &mut dyn FnMut(u32) -> u32, arg: u32| -> u32 { + counter += 1; + if arg == 0 {1} else {arg * recur(arg-1)} + }; + let mut factorial: YCombinator<_,u32,u32> = YCombinator::new(factorial); + let mut r = factorial(10); + assert_eq!(3628800, r); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr new file mode 100644 index 000000000..830f6bc99 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.stderr @@ -0,0 +1,12 @@ +error[E0499]: cannot borrow `*self` as mutable more than once at a time + --> $DIR/unboxed-closures-recursive-fn-using-fn-mut.rs:22:21 + | +LL | (self.func)(self, arg) + | ----------- ^^^^ second mutable borrow occurs here + | | + | first mutable borrow occurs here + | first borrow later used by call + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-simple.rs b/tests/ui/unboxed-closures/unboxed-closures-simple.rs new file mode 100644 index 000000000..144955402 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-simple.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_imports)] +use std::ops::FnMut; + +pub fn main() { + let mut f = |x: isize, y: isize| -> isize { x + y }; + let z = f(1, 2); + assert_eq!(z, 3); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-single-word-env.rs b/tests/ui/unboxed-closures/unboxed-closures-single-word-env.rs new file mode 100644 index 000000000..8ada7494e --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-single-word-env.rs @@ -0,0 +1,22 @@ +// run-pass +// Ensures that single-word environments work right in unboxed closures. +// These take a different path in codegen. + +fn a isize>(f: F) -> isize { + f(1, 2) +} + +fn b isize>(mut f: F) -> isize { + f(3, 4) +} + +fn c isize>(f: F) -> isize { + f(5, 6) +} + +fn main() { + let z = 10; + assert_eq!(a(move |x: isize, y| x + y + z), 13); + assert_eq!(b(move |x: isize, y| x + y + z), 17); + assert_eq!(c(move |x: isize, y| x + y + z), 21); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-static-call-fn-once.rs b/tests/ui/unboxed-closures/unboxed-closures-static-call-fn-once.rs new file mode 100644 index 000000000..054f284ea --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-static-call-fn-once.rs @@ -0,0 +1,7 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn main() { + let onetime = |x| x; + onetime(0); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs new file mode 100644 index 000000000..7289d9322 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.rs @@ -0,0 +1,8 @@ +#![feature(unboxed_closures, tuple_trait)] + +fn to_fn_mut>(f: F) -> F { f } + +fn main() { + let mut_ = to_fn_mut(|x| x); + mut_.call((0, )); //~ ERROR no method named `call` found +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr new file mode 100644 index 000000000..99ec51783 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope + --> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10 + | +LL | mut_.call((0, )); + | ^^^^ method not found in `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-sugar-object.rs b/tests/ui/unboxed-closures/unboxed-closures-sugar-object.rs new file mode 100644 index 000000000..1ca25517c --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-sugar-object.rs @@ -0,0 +1,25 @@ +// run-pass +// Test unboxed closure sugar used in object types. + +#![allow(dead_code)] + +struct Foo { + t: T, u: U +} + +trait Getter { + fn get(&self, arg: A) -> R; +} + +struct Identity; +impl Getter for Identity { + fn get(&self, arg: X) -> X { + arg + } +} + +fn main() { + let x: &dyn Getter<(i32,), (i32,)> = &Identity; + let (y,) = x.get((22,)); + assert_eq!(y, 22); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-type-mismatch.rs b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch.rs new file mode 100644 index 000000000..9f76849e5 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch.rs @@ -0,0 +1,7 @@ +use std::ops::FnMut; + +pub fn main() { + let mut f = |x: isize, y: isize| -> isize { x + y }; + let z = f(1_usize, 2); //~ ERROR mismatched types + println!("{}", z); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr new file mode 100644 index 000000000..455f83f57 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/unboxed-closures-type-mismatch.rs:5:15 + | +LL | let z = f(1_usize, 2); + | - ^^^^^^^ expected `isize`, found `usize` + | | + | arguments to this function are incorrect + | +note: closure parameter defined here + --> $DIR/unboxed-closures-type-mismatch.rs:4:18 + | +LL | let mut f = |x: isize, y: isize| -> isize { x + y }; + | ^^^^^^^^ +help: change the type of the numeric literal from `usize` to `isize` + | +LL | let z = f(1_isize, 2); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs b/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs new file mode 100644 index 000000000..4b7016def --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-unique-type-id.rs @@ -0,0 +1,26 @@ +// run-pass + +// This code used to produce the following ICE: +// +// error: internal compiler error: get_unique_type_id_of_type() - +// unexpected type: closure, +// Closure(rustc_ast::DefId{krate: 0, node: 66}, +// ReScope(63)) +// +// This is a regression test for issue #17021. +// +// compile-flags: -g +// ignore-asmjs wasm2js does not support source maps yet + +use std::ptr; + +pub fn replace_map<'a, T, F>(src: &mut T, prod: F) where F: FnOnce(T) -> T { + unsafe { *src = prod(ptr::read(src as *mut T as *const T)); } +} + +pub fn main() { + let mut a = 7; + let b = &mut a; + replace_map(b, |x: usize| x * 2); + assert_eq!(*b, 14); +} diff --git a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs new file mode 100644 index 000000000..e2082d4f7 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -0,0 +1,34 @@ +// Tests that unsafe extern fn pointers do not implement any Fn traits. + +use std::ops::{Fn, FnMut, FnOnce}; + +unsafe fn square(x: &isize) -> isize { + (*x) * (*x) +} + +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} + +fn a() { + let x = call_it(&square, 22); + //~^ ERROR E0277 +} + +fn b() { + let y = call_it_mut(&mut square, 22); + //~^ ERROR E0277 +} + +fn c() { + let z = call_it_once(square, 22); + //~^ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr new file mode 100644 index 000000000..802696e1b --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -0,0 +1,51 @@ +error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 + | +LL | let x = call_it(&square, 22); + | ------- ^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `call_it` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15 + | +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` + +error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 + | +LL | let y = call_it_mut(&mut square, 22); + | ----------- ^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `call_it_mut` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19 + | +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` + +error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 + | +LL | let z = call_it_once(square, 22); + | ------------ ^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `call_it_once` + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20 + | +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_once` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.rs new file mode 100644 index 000000000..dd76c597d --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -0,0 +1,34 @@ +// Tests that unsafe extern fn pointers do not implement any Fn traits. + +use std::ops::{Fn, FnMut, FnOnce}; + +extern "C" fn square(x: &isize) -> isize { + (*x) * (*x) +} + +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} + +fn a() { + let x = call_it(&square, 22); + //~^ ERROR E0277 +} + +fn b() { + let y = call_it_mut(&mut square, 22); + //~^ ERROR E0277 +} + +fn c() { + let z = call_it_once(square, 22); + //~^ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr new file mode 100644 index 000000000..0bbb9836c --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -0,0 +1,48 @@ +error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:20:21 + | +LL | let x = call_it(&square, 22); + | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` +note: required by a bound in `call_it` + --> $DIR/unboxed-closures-wrong-abi.rs:9:15 + | +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` + +error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:25:25 + | +LL | let y = call_it_mut(&mut square, 22); + | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` +note: required by a bound in `call_it_mut` + --> $DIR/unboxed-closures-wrong-abi.rs:12:19 + | +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` + +error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-abi.rs:30:26 + | +LL | let z = call_it_once(square, 22); + | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` +note: required by a bound in `call_it_once` + --> $DIR/unboxed-closures-wrong-abi.rs:15:20 + | +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_once` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs new file mode 100644 index 000000000..02e8b7b47 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -0,0 +1,35 @@ +// Tests that unsafe extern fn pointers do not implement any Fn traits. + +use std::ops::{Fn, FnMut, FnOnce}; + +unsafe fn square(x: isize) -> isize { + x * x +} +// note: argument type here is `isize`, not `&isize` + +fn call_it isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once isize>(_: F, _: isize) -> isize { + 0 +} + +fn a() { + let x = call_it(&square, 22); + //~^ ERROR E0277 +} + +fn b() { + let y = call_it_mut(&mut square, 22); + //~^ ERROR E0277 +} + +fn c() { + let z = call_it_once(square, 22); + //~^ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr new file mode 100644 index 000000000..31a66790c --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -0,0 +1,51 @@ +error[E0277]: expected a `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 + | +LL | let x = call_it(&square, 22); + | ------- ^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `call_it` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15 + | +LL | fn call_it isize>(_: &F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` + +error[E0277]: expected a `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 + | +LL | let y = call_it_mut(&mut square, 22); + | ----------- ^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `call_it_mut` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19 + | +LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` + +error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 + | +LL | let z = call_it_once(square, 22); + | ------------ ^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = note: unsafe function cannot be called generically without an unsafe block +note: required by a bound in `call_it_once` + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20 + | +LL | fn call_it_once isize>(_: F, _: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_once` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-zero-args.rs b/tests/ui/unboxed-closures/unboxed-closures-zero-args.rs new file mode 100644 index 000000000..6f41c3558 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-zero-args.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_mut)] +// pretty-expanded FIXME #23616 + +fn main() { + let mut zero = || {}; + let () = zero(); +} diff --git a/tests/ui/unconstrained-none.rs b/tests/ui/unconstrained-none.rs new file mode 100644 index 000000000..e180b3163 --- /dev/null +++ b/tests/ui/unconstrained-none.rs @@ -0,0 +1,5 @@ +// Issue #5062 + +fn main() { + None; //~ ERROR type annotations needed [E0282] +} diff --git a/tests/ui/unconstrained-none.stderr b/tests/ui/unconstrained-none.stderr new file mode 100644 index 000000000..19ac74fdf --- /dev/null +++ b/tests/ui/unconstrained-none.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/unconstrained-none.rs:4:5 + | +LL | None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | None::; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/unconstrained-ref.rs b/tests/ui/unconstrained-ref.rs new file mode 100644 index 000000000..473ca954b --- /dev/null +++ b/tests/ui/unconstrained-ref.rs @@ -0,0 +1,7 @@ +struct S<'a, T:'a> { + o: &'a Option +} + +fn main() { + S { o: &None }; //~ ERROR type annotations needed [E0282] +} diff --git a/tests/ui/unconstrained-ref.stderr b/tests/ui/unconstrained-ref.stderr new file mode 100644 index 000000000..1df6d8b44 --- /dev/null +++ b/tests/ui/unconstrained-ref.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/unconstrained-ref.rs:6:5 + | +LL | S { o: &None }; + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `S` + | +help: consider specifying the generic argument + | +LL | S:: { o: &None }; + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/underscore-ident-matcher.rs b/tests/ui/underscore-ident-matcher.rs new file mode 100644 index 000000000..bddc8c80a --- /dev/null +++ b/tests/ui/underscore-ident-matcher.rs @@ -0,0 +1,9 @@ +macro_rules! identity { + ($i: ident) => ( + $i + ) +} + +fn main() { + let identity!(_) = 10; //~ ERROR no rules expected the token `_` +} diff --git a/tests/ui/underscore-ident-matcher.stderr b/tests/ui/underscore-ident-matcher.stderr new file mode 100644 index 000000000..b0e4d88f6 --- /dev/null +++ b/tests/ui/underscore-ident-matcher.stderr @@ -0,0 +1,17 @@ +error: no rules expected the token `_` + --> $DIR/underscore-ident-matcher.rs:8:19 + | +LL | macro_rules! identity { + | --------------------- when calling this macro +... +LL | let identity!(_) = 10; + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$i:ident` + --> $DIR/underscore-ident-matcher.rs:2:6 + | +LL | ($i: ident) => ( + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/underscore-imports/auxiliary/duplicate.rs b/tests/ui/underscore-imports/auxiliary/duplicate.rs new file mode 100644 index 000000000..92d741b6a --- /dev/null +++ b/tests/ui/underscore-imports/auxiliary/duplicate.rs @@ -0,0 +1,14 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +#[proc_macro_attribute] +pub fn duplicate(_: TokenStream, input: TokenStream) -> TokenStream { + let clone = input.clone(); + input.into_iter().chain(clone.into_iter()).collect() +} diff --git a/tests/ui/underscore-imports/auxiliary/underscore-imports.rs b/tests/ui/underscore-imports/auxiliary/underscore-imports.rs new file mode 100644 index 000000000..c335336be --- /dev/null +++ b/tests/ui/underscore-imports/auxiliary/underscore-imports.rs @@ -0,0 +1,20 @@ +#[macro_export] +macro_rules! do_nothing { + () => () +} + +mod m1 { + pub trait InScope1 { + fn in_scope1(&self) {} + } + impl InScope1 for () {} +} +mod m2 { + pub trait InScope2 { + fn in_scope2(&self) {} + } + impl InScope2 for () {} +} + +pub use m1::InScope1 as _; +pub use m2::InScope2 as _; diff --git a/tests/ui/underscore-imports/basic.rs b/tests/ui/underscore-imports/basic.rs new file mode 100644 index 000000000..c021ad5ee --- /dev/null +++ b/tests/ui/underscore-imports/basic.rs @@ -0,0 +1,62 @@ +// check-pass +// aux-build:underscore-imports.rs + +#![warn(unused_imports, unused_extern_crates)] + +#[macro_use] +extern crate underscore_imports as _; + +do_nothing!(); // OK + +struct S; + +mod m { + pub trait Tr1 { + fn tr1_is_in_scope(&self) {} + } + pub trait Tr2 { + fn tr2_is_in_scope(&self) {} + } + + impl Tr1 for ::S {} + impl Tr2 for ::S {} +} + +mod unused { + use m::Tr1 as _; //~ WARN unused import + use S as _; //~ WARN unused import + extern crate core as _; // OK +} + +mod outer { + mod middle { + pub use m::Tr1 as _; + pub use m::Tr2 as _; // OK, no name conflict + struct Tr1; // OK, no name conflict + fn check() { + // Both traits are in scope + ::S.tr1_is_in_scope(); + ::S.tr2_is_in_scope(); + } + + mod inner { + // `_` imports are fetched by glob imports + use super::*; + fn check() { + // Both traits are in scope + ::S.tr1_is_in_scope(); + ::S.tr2_is_in_scope(); + } + } + } + + // `_` imports are fetched by glob imports + use self::middle::*; + fn check() { + // Both traits are in scope + ::S.tr1_is_in_scope(); + ::S.tr2_is_in_scope(); + } +} + +fn main() {} diff --git a/tests/ui/underscore-imports/basic.stderr b/tests/ui/underscore-imports/basic.stderr new file mode 100644 index 000000000..c51493562 --- /dev/null +++ b/tests/ui/underscore-imports/basic.stderr @@ -0,0 +1,20 @@ +warning: unused import: `m::Tr1 as _` + --> $DIR/basic.rs:26:9 + | +LL | use m::Tr1 as _; + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/basic.rs:4:9 + | +LL | #![warn(unused_imports, unused_extern_crates)] + | ^^^^^^^^^^^^^^ + +warning: unused import: `S as _` + --> $DIR/basic.rs:27:9 + | +LL | use S as _; + | ^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/underscore-imports/cycle.rs b/tests/ui/underscore-imports/cycle.rs new file mode 100644 index 000000000..bacf9b2d5 --- /dev/null +++ b/tests/ui/underscore-imports/cycle.rs @@ -0,0 +1,18 @@ +// Check that cyclic glob imports are allowed with underscore imports + +// check-pass + +mod x { + pub use crate::y::*; + pub use std::ops::Deref as _; +} + +mod y { + pub use crate::x::*; + pub use std::ops::Deref as _; +} + +pub fn main() { + use x::*; + (&0).deref(); +} diff --git a/tests/ui/underscore-imports/duplicate.rs b/tests/ui/underscore-imports/duplicate.rs new file mode 100644 index 000000000..20bc7848a --- /dev/null +++ b/tests/ui/underscore-imports/duplicate.rs @@ -0,0 +1,15 @@ +// check-pass +// aux-build:duplicate.rs + +extern crate duplicate; + +#[duplicate::duplicate] +use main as _; // OK + +macro_rules! duplicate { + ($item: item) => { $item $item } +} + +duplicate!(use std as _;); // OK + +fn main() {} diff --git a/tests/ui/underscore-imports/hygiene-2.rs b/tests/ui/underscore-imports/hygiene-2.rs new file mode 100644 index 000000000..510d91d0d --- /dev/null +++ b/tests/ui/underscore-imports/hygiene-2.rs @@ -0,0 +1,34 @@ +// Make sure that underscore imports with different contexts can exist in the +// same scope. + +// check-pass + +#![feature(decl_macro)] + +mod x { + pub use std::ops::Deref as _; +} + +macro n() { + pub use crate::x::*; +} + +#[macro_export] +macro_rules! p { + () => { pub use crate::x::*; } +} + +macro m($y:ident) { + mod $y { + crate::n!(); // Reexport of `Deref` should not be imported in `main` + crate::p!(); // Reexport of `Deref` should be imported into `main` + } +} + +m!(y); + +fn main() { + use crate::y::*; + #[allow(noop_method_call)] + (&()).deref(); +} diff --git a/tests/ui/underscore-imports/hygiene.rs b/tests/ui/underscore-imports/hygiene.rs new file mode 100644 index 000000000..c4db65245 --- /dev/null +++ b/tests/ui/underscore-imports/hygiene.rs @@ -0,0 +1,40 @@ +// Make sure that underscore imports have the same hygiene considerations as other imports. + +// check-pass + +#![feature(decl_macro)] + +mod x { + pub use std::ops::Deref as _; +} + +macro glob_import() { + pub use crate::x::*; +} + +macro underscore_import() { + use std::ops::DerefMut as _; +} + +mod y { + crate::glob_import!(); + crate::underscore_import!(); +} + +macro create_module($y:ident) { + mod $y { + crate::glob_import!(); + crate::underscore_import!(); + } +} + +create_module!(z); + +fn main() { + use crate::y::*; + use crate::z::*; + glob_import!(); + underscore_import!(); + (&()).deref(); + (&mut ()).deref_mut(); +} diff --git a/tests/ui/underscore-imports/intercrate.rs b/tests/ui/underscore-imports/intercrate.rs new file mode 100644 index 000000000..144f95bac --- /dev/null +++ b/tests/ui/underscore-imports/intercrate.rs @@ -0,0 +1,11 @@ +// check-pass +// aux-build:underscore-imports.rs + +extern crate underscore_imports; + +use underscore_imports::*; + +fn main() { + ().in_scope1(); + ().in_scope2(); +} diff --git a/tests/ui/underscore-imports/macro-expanded.rs b/tests/ui/underscore-imports/macro-expanded.rs new file mode 100644 index 000000000..43f527bc9 --- /dev/null +++ b/tests/ui/underscore-imports/macro-expanded.rs @@ -0,0 +1,45 @@ +// Check that macro expanded underscore imports behave as expected + +// check-pass + +#![feature(decl_macro, rustc_attrs)] + +mod x { + pub use std::ops::Not as _; +} + +macro m() { + mod w { + mod y { + pub use std::ops::Deref as _; + } + use crate::x::*; + use self::y::*; + use std::ops::DerefMut as _; + fn f() { + false.not(); + (&()).deref(); + (&mut ()).deref_mut(); + } + } +} + +#[rustc_macro_transparency = "transparent"] +macro n() { + mod z { + pub use std::ops::Deref as _; + } + use crate::x::*; + use crate::z::*; + use std::ops::DerefMut as _; + fn f() { + false.not(); + (&()).deref(); + (&mut ()).deref_mut(); + } +} + +m!(); +n!(); + +fn main() {} diff --git a/tests/ui/underscore-imports/shadow.rs b/tests/ui/underscore-imports/shadow.rs new file mode 100644 index 000000000..325f2001b --- /dev/null +++ b/tests/ui/underscore-imports/shadow.rs @@ -0,0 +1,23 @@ +// Check that underscore imports don't cause glob imports to be unshadowed + +mod a { + pub use std::ops::Deref as Shadow; +} + +mod b { + pub use crate::a::*; + macro_rules! m { + ($i:ident) => { pub struct $i; } + } + m!(Shadow); +} + +mod c { + use crate::b::Shadow as _; // Only imports the struct + + fn f(x: &()) { + x.deref(); //~ ERROR no method named `deref` found + } +} + +fn main() {} diff --git a/tests/ui/underscore-imports/shadow.stderr b/tests/ui/underscore-imports/shadow.stderr new file mode 100644 index 000000000..7faede4e6 --- /dev/null +++ b/tests/ui/underscore-imports/shadow.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `deref` found for reference `&()` in the current scope + --> $DIR/shadow.rs:19:11 + | +LL | x.deref(); + | ^^^^^ method not found in `&()` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::ops::Deref; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/underscore-imports/unused-2018.rs b/tests/ui/underscore-imports/unused-2018.rs new file mode 100644 index 000000000..d06a26a5f --- /dev/null +++ b/tests/ui/underscore-imports/unused-2018.rs @@ -0,0 +1,17 @@ +// edition:2018 + +#![deny(unused_imports)] + +mod multi_segment { + use core::any; //~ ERROR unused import: `core::any` +} + +mod single_segment { + use core; //~ ERROR unused import: `core` +} + +mod single_segment_underscore { + use core as _; // OK +} + +fn main() {} diff --git a/tests/ui/underscore-imports/unused-2018.stderr b/tests/ui/underscore-imports/unused-2018.stderr new file mode 100644 index 000000000..2afb9a10e --- /dev/null +++ b/tests/ui/underscore-imports/unused-2018.stderr @@ -0,0 +1,20 @@ +error: unused import: `core::any` + --> $DIR/unused-2018.rs:6:9 + | +LL | use core::any; + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-2018.rs:3:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `core` + --> $DIR/unused-2018.rs:10:9 + | +LL | use core; + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs b/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs new file mode 100644 index 000000000..e1deab736 --- /dev/null +++ b/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs @@ -0,0 +1,12 @@ +// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision, +// and not like an object lifetime default. +// +// cc #48468 + +use std::fmt::Debug; + +struct Foo { + x: Box, //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr new file mode 100644 index 000000000..fd0860028 --- /dev/null +++ b/tests/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/dyn-trait-underscore-in-struct.rs:9:24 + | +LL | x: Box, + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct Foo<'a> { +LL ~ x: Box, + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/dyn-trait-underscore.rs b/tests/ui/underscore-lifetime/dyn-trait-underscore.rs new file mode 100644 index 000000000..fa6e65c7d --- /dev/null +++ b/tests/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -0,0 +1,20 @@ +// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision, +// and not like an object lifetime default. +// +// cc #48468 + +fn a(items: &[T]) -> Box> { + // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` + Box::new(items.iter()) + //~^ ERROR lifetime may not live long enough +} + +fn b(items: &[T]) -> Box + '_> { + Box::new(items.iter()) // OK, equivalent to c +} + +fn c<'a, T>(items: &'a [T]) -> Box + 'a> { + Box::new(items.iter()) // OK, equivalent to b +} + +fn main() { } diff --git a/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr b/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr new file mode 100644 index 000000000..60b0b3ee7 --- /dev/null +++ b/tests/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/dyn-trait-underscore.rs:8:5 + | +LL | fn a(items: &[T]) -> Box> { + | - let's call the lifetime of this reference `'1` +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | Box::new(items.iter()) + | ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound + | +LL | fn a(items: &[T]) -> Box + '_> { + | ++++ + +error: aborting due to previous error + diff --git a/tests/ui/underscore-lifetime/in-binder.rs b/tests/ui/underscore-lifetime/in-binder.rs new file mode 100644 index 000000000..74dc331b0 --- /dev/null +++ b/tests/ui/underscore-lifetime/in-binder.rs @@ -0,0 +1,35 @@ +// Check that we error when `'_` appears as the name of a lifetime parameter. +// +// Regression test for #52098. + +struct IceCube<'a> { + v: Vec<&'a char> +} + +impl<'_> IceCube<'_> {} +//~^ ERROR `'_` cannot be used here + +struct Struct<'_> { + //~^ ERROR `'_` cannot be used here + v: Vec<&'static char> +} + +enum Enum<'_> { + //~^ ERROR `'_` cannot be used here + Variant +} + +union Union<'_> { + //~^ ERROR `'_` cannot be used here + a: u32 +} + +trait Trait<'_> { + //~^ ERROR `'_` cannot be used here +} + +fn foo<'_>() { + //~^ ERROR `'_` cannot be used here +} + +fn main() {} diff --git a/tests/ui/underscore-lifetime/in-binder.stderr b/tests/ui/underscore-lifetime/in-binder.stderr new file mode 100644 index 000000000..fcd7eddb5 --- /dev/null +++ b/tests/ui/underscore-lifetime/in-binder.stderr @@ -0,0 +1,39 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/in-binder.rs:9:6 + | +LL | impl<'_> IceCube<'_> {} + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/in-binder.rs:12:15 + | +LL | struct Struct<'_> { + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/in-binder.rs:17:11 + | +LL | enum Enum<'_> { + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/in-binder.rs:22:13 + | +LL | union Union<'_> { + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/in-binder.rs:27:13 + | +LL | trait Trait<'_> { + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/in-binder.rs:31:8 + | +LL | fn foo<'_>() { + | ^^ `'_` is a reserved lifetime name + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/in-fn-return-illegal.rs b/tests/ui/underscore-lifetime/in-fn-return-illegal.rs new file mode 100644 index 000000000..a46ece7d4 --- /dev/null +++ b/tests/ui/underscore-lifetime/in-fn-return-illegal.rs @@ -0,0 +1,7 @@ +// Check that the `'_` used in structs/enums gives an error. + +use std::fmt::Debug; + +fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } //~ ERROR missing lifetime specifier + +fn main() { } diff --git a/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr b/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr new file mode 100644 index 000000000..6a104e8f9 --- /dev/null +++ b/tests/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -0,0 +1,15 @@ +error[E0106]: missing lifetime specifier + --> $DIR/in-fn-return-illegal.rs:5:30 + | +LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } + | ---- ---- ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } } + | ++++ ++ ++ ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/in-struct.rs b/tests/ui/underscore-lifetime/in-struct.rs new file mode 100644 index 000000000..bed89c7dc --- /dev/null +++ b/tests/ui/underscore-lifetime/in-struct.rs @@ -0,0 +1,13 @@ +// Check that the `'_` used in structs/enums gives an error. + +use std::fmt::Debug; + +struct Foo { + x: &'_ u32, //~ ERROR missing lifetime specifier +} + +enum Bar { + Variant(&'_ u32), //~ ERROR missing lifetime specifier +} + +fn main() { } diff --git a/tests/ui/underscore-lifetime/in-struct.stderr b/tests/ui/underscore-lifetime/in-struct.stderr new file mode 100644 index 000000000..84183f61e --- /dev/null +++ b/tests/ui/underscore-lifetime/in-struct.stderr @@ -0,0 +1,27 @@ +error[E0106]: missing lifetime specifier + --> $DIR/in-struct.rs:6:9 + | +LL | x: &'_ u32, + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ struct Foo<'a> { +LL ~ x: &'a u32, + | + +error[E0106]: missing lifetime specifier + --> $DIR/in-struct.rs:10:14 + | +LL | Variant(&'_ u32), + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL ~ enum Bar<'a> { +LL ~ Variant(&'a u32), + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs new file mode 100644 index 000000000..3d049cc56 --- /dev/null +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs @@ -0,0 +1,22 @@ +struct Foo<'a>(&'a u8); +struct Baz<'a>(&'_ &'a u8); //~ ERROR missing lifetime specifier + +fn foo<'_> //~ ERROR cannot be used here +(_: Foo<'_>) {} + +trait Meh<'a> {} +impl<'a> Meh<'a> for u8 {} + +fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here +//~^ ERROR missing lifetime specifier +{ + Box::new(5u8) +} + +fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier + +fn main() { + let x = 5; + foo(Foo(&x)); + let _ = meh(); +} diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr new file mode 100644 index 000000000..50401791e --- /dev/null +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -0,0 +1,51 @@ +error[E0106]: missing lifetime specifier + --> $DIR/underscore-lifetime-binders.rs:2:17 + | +LL | struct Baz<'a>(&'_ &'a u8); + | ^^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct Baz<'a>(&'a &'a u8); + | ~~ + +error[E0637]: `'_` cannot be used here + --> $DIR/underscore-lifetime-binders.rs:4:8 + | +LL | fn foo<'_> + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/underscore-lifetime-binders.rs:10:25 + | +LL | fn meh() -> Box Meh<'_>> + | ^^ `'_` is a reserved lifetime name + +error[E0106]: missing lifetime specifier + --> $DIR/underscore-lifetime-binders.rs:10:33 + | +LL | fn meh() -> Box Meh<'_>> + | ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +LL | fn meh() -> Box Meh<'static>> + | ~~~~~~~ + +error[E0106]: missing lifetime specifier + --> $DIR/underscore-lifetime-binders.rs:16:35 + | +LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } + | ------ ------ ^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y` +help: consider introducing a named lifetime parameter + | +LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } + | ++++ ~~ ~~ ~~ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0106, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs new file mode 100644 index 000000000..c61126884 --- /dev/null +++ b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.rs @@ -0,0 +1,4 @@ +fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } +//~^ ERROR lifetime may not live long enough + +fn main() {} diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr new file mode 100644 index 000000000..2b34f0c55 --- /dev/null +++ b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -0,0 +1,16 @@ +error: lifetime may not live long enough + --> $DIR/underscore-lifetime-elison-mismatch.rs:1:42 + | +LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } + | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'1` + | let's call the lifetime of this reference `'2` + | +help: consider introducing a named lifetime parameter + | +LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } + | ++++ ~~ ~~ + +error: aborting due to previous error + diff --git a/tests/ui/underscore-lifetime/underscore-outlives-bounds.rs b/tests/ui/underscore-lifetime/underscore-outlives-bounds.rs new file mode 100644 index 000000000..567cc7a3f --- /dev/null +++ b/tests/ui/underscore-lifetime/underscore-outlives-bounds.rs @@ -0,0 +1,8 @@ +// Regression test to check that `'b: '_` gets an error, because it's +// basically useless. +// +// #54902 + +trait Foo<'a> {} +impl<'b: '_> Foo<'b> for i32 {} //~ ERROR `'_` cannot be used here +fn main() { } diff --git a/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr b/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr new file mode 100644 index 000000000..4b38a26f9 --- /dev/null +++ b/tests/ui/underscore-lifetime/underscore-outlives-bounds.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/underscore-outlives-bounds.rs:7:10 + | +LL | impl<'b: '_> Foo<'b> for i32 {} + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs new file mode 100644 index 000000000..43de30944 --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rs @@ -0,0 +1,18 @@ +// revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +trait WithType {} +trait WithRegion<'a> { } + +struct Foo { + t: T +} + +impl Foo +where + T: WithType<&u32> +//[rust2015]~^ ERROR `&` without an explicit lifetime name cannot be used here +//[rust2018]~^^ ERROR `&` without an explicit lifetime name cannot be used here +{ } + +fn main() {} diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr new file mode 100644 index 000000000..f4d14b5f8 --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr @@ -0,0 +1,15 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17 + | +LL | T: WithType<&u32> + | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8 + | +LL | T: WithType<&u32> + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr new file mode 100644 index 000000000..f4d14b5f8 --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr @@ -0,0 +1,15 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:17 + | +LL | T: WithType<&u32> + | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8 + | +LL | T: WithType<&u32> + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs new file mode 100644 index 000000000..38189816d --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rs @@ -0,0 +1,17 @@ +// revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +trait WithType {} +trait WithRegion<'a> { } + +struct Foo { + t: T +} + +impl Foo +where + T: WithRegion<'_> +//[rust2015,rust2018]~^ ERROR `'_` cannot be used here +{ } + +fn main() {} diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr new file mode 100644 index 000000000..95939fd6b --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2015.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/where-clause-inherent-impl-underscore.rs:13:19 + | +LL | T: WithRegion<'_> + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr new file mode 100644 index 000000000..95939fd6b --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-underscore.rust2018.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/where-clause-inherent-impl-underscore.rs:13:19 + | +LL | T: WithRegion<'_> + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs new file mode 100644 index 000000000..09e5bbd84 --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rs @@ -0,0 +1,15 @@ +// revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +trait WithType {} +trait WithRegion<'a> { } + +trait Foo { } + +impl Foo for Vec +where + T: WithType<&u32> +//[rust2015,rust2018]~^ ERROR `&` without an explicit lifetime name cannot be used here +{ } + +fn main() {} diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr new file mode 100644 index 000000000..63fc1a19b --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr @@ -0,0 +1,15 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/where-clause-trait-impl-region.rs:11:17 + | +LL | T: WithType<&u32> + | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-trait-impl-region.rs:11:8 + | +LL | T: WithType<&u32> + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr new file mode 100644 index 000000000..63fc1a19b --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr @@ -0,0 +1,15 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/where-clause-trait-impl-region.rs:11:17 + | +LL | T: WithType<&u32> + | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-trait-impl-region.rs:11:8 + | +LL | T: WithType<&u32> + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs new file mode 100644 index 000000000..371d2e4ba --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rs @@ -0,0 +1,15 @@ +// revisions: rust2015 rust2018 +//[rust2018] edition:2018 + +trait WithType {} +trait WithRegion<'a> { } + +trait Foo { } + +impl Foo for Vec +where + T: WithRegion<'_> +//[rust2015,rust2018]~^ ERROR `'_` cannot be used here +{ } + +fn main() {} diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr new file mode 100644 index 000000000..92caff0dc --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2015.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/where-clause-trait-impl-underscore.rs:11:19 + | +LL | T: WithRegion<'_> + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr new file mode 100644 index 000000000..92caff0dc --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-underscore.rust2018.stderr @@ -0,0 +1,9 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/where-clause-trait-impl-underscore.rs:11:19 + | +LL | T: WithRegion<'_> + | ^^ `'_` is a reserved lifetime name + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetime/where-clauses.rs b/tests/ui/underscore-lifetime/where-clauses.rs new file mode 100644 index 000000000..ee6823b80 --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clauses.rs @@ -0,0 +1,7 @@ +trait Foo<'a> {} + +impl<'b: '_> Foo<'b> for i32 {} //~ ERROR `'_` cannot be used here + +impl Foo<'static> for Vec {} //~ ERROR `'_` cannot be used here + +fn main() { } diff --git a/tests/ui/underscore-lifetime/where-clauses.stderr b/tests/ui/underscore-lifetime/where-clauses.stderr new file mode 100644 index 000000000..1a3ea4af7 --- /dev/null +++ b/tests/ui/underscore-lifetime/where-clauses.stderr @@ -0,0 +1,15 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/where-clauses.rs:3:10 + | +LL | impl<'b: '_> Foo<'b> for i32 {} + | ^^ `'_` is a reserved lifetime name + +error[E0637]: `'_` cannot be used here + --> $DIR/where-clauses.rs:5:9 + | +LL | impl Foo<'static> for Vec {} + | ^^ `'_` is a reserved lifetime name + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/underscore-lifetimes.rs b/tests/ui/underscore-lifetimes.rs new file mode 100644 index 000000000..a1593880d --- /dev/null +++ b/tests/ui/underscore-lifetimes.rs @@ -0,0 +1,38 @@ +// run-pass + +#![allow(dead_code)] +struct Foo<'a>(&'a u8); + +fn foo(x: &u8) -> Foo<'_> { + Foo(x) +} + +fn foo2(x: &'_ u8) -> Foo<'_> { + Foo(x) +} + +fn foo3(x: &'_ u8) -> Foo { + Foo(x) +} + +fn foo4(_: Foo<'_>) {} + +struct Foo2<'a, 'b> { + a: &'a u8, + b: &'b u8, +} +fn foo5<'b>(foo: Foo2<'_, 'b>) -> &'b u8 { + foo.b +} + +fn main() { + let x = &5; + let _ = foo(x); + let _ = foo2(x); + let _ = foo3(x); + foo4(Foo(x)); + let _ = foo5(Foo2 { + a: x, + b: &6, + }); +} diff --git a/tests/ui/underscore-method-after-integer.rs b/tests/ui/underscore-method-after-integer.rs new file mode 100644 index 000000000..7fb8607f9 --- /dev/null +++ b/tests/ui/underscore-method-after-integer.rs @@ -0,0 +1,11 @@ +// run-pass + +trait Tr : Sized { + fn _method_on_numbers(self) {} +} + +impl Tr for i32 {} + +fn main() { + 42._method_on_numbers(); +} diff --git a/tests/ui/unevaluated_fixed_size_array_len.rs b/tests/ui/unevaluated_fixed_size_array_len.rs new file mode 100644 index 000000000..6c545913d --- /dev/null +++ b/tests/ui/unevaluated_fixed_size_array_len.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/49208 + +trait Foo { + fn foo(); +} + +impl Foo for [(); 1] { + fn foo() {} +} + +fn main() { + <[(); 0] as Foo>::foo() //~ ERROR E0277 +} diff --git a/tests/ui/unevaluated_fixed_size_array_len.stderr b/tests/ui/unevaluated_fixed_size_array_len.stderr new file mode 100644 index 000000000..5e67b2c44 --- /dev/null +++ b/tests/ui/unevaluated_fixed_size_array_len.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied + --> $DIR/unevaluated_fixed_size_array_len.rs:12:5 + | +LL | <[(); 0] as Foo>::foo() + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` + | + = help: the trait `Foo` is implemented for `[(); 1]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/uniform-paths/auxiliary/issue-53691.rs b/tests/ui/uniform-paths/auxiliary/issue-53691.rs new file mode 100644 index 000000000..a46533178 --- /dev/null +++ b/tests/ui/uniform-paths/auxiliary/issue-53691.rs @@ -0,0 +1,7 @@ +// edition:2018 + +mod m { pub fn f() {} } +mod n { pub fn g() {} } + +pub use m::f; +pub use n::g; diff --git a/tests/ui/uniform-paths/basic-nested.rs b/tests/ui/uniform-paths/basic-nested.rs new file mode 100644 index 000000000..dcf0eb646 --- /dev/null +++ b/tests/ui/uniform-paths/basic-nested.rs @@ -0,0 +1,61 @@ +// This test is similar to `basic.rs`, but nested in modules. + +// run-pass +// edition:2018 + +#![feature(decl_macro)] + +#![allow(unused_imports)] +#![allow(non_camel_case_types)] + +mod foo { + // Test that ambiguity errors are not emitted between `self::test` and + // `::test`, assuming the latter (crate) is not in `extern_prelude`. + mod test { + pub struct Foo(pub ()); + } + pub use test::Foo; + + // Test that qualified paths can refer to both the external crate and local item. + mod std { + pub struct io(pub ()); + } + pub use ::std::io as std_io; + pub use self::std::io as local_io; +} + +// Test that we can refer to the external crate unqualified +// (when there isn't a local item with the same name). +use std::io; + +mod bar { + // Also test the unqualified external crate import in a nested module, + // to show that the above import doesn't resolve through a local `std` + // item, e.g., the automatically injected `extern crate std;`, which in + // the Rust 2018 should no longer be visible through `crate::std`. + pub use std::io; + + // Also test that items named `std` in other namespaces don't + // cause ambiguity errors for the import from `std` above. + pub fn std() {} + pub macro std() {} +} + + +fn main() { + foo::Foo(()); + let _ = foo::std_io::stdout(); + foo::local_io(()); + let _ = io::stdout(); + let _ = bar::io::stdout(); + bar::std(); + bar::std!(); + + { + // Test that having `io` in a module scope and a non-module + // scope is allowed, when both resolve to the same definition. + use std::io; + use io::stdout; + let _ = stdout(); + } +} diff --git a/tests/ui/uniform-paths/basic.rs b/tests/ui/uniform-paths/basic.rs new file mode 100644 index 000000000..ce611a7ca --- /dev/null +++ b/tests/ui/uniform-paths/basic.rs @@ -0,0 +1,33 @@ +// run-pass +// edition:2018 + +#![allow(unused_imports)] +#![allow(non_camel_case_types)] + +// Test that ambiguity errors are not emitted between `self::test` and +// `::test`, assuming the latter (crate) is not in `extern_prelude`. +mod test { + pub struct Foo(pub ()); +} +use test::Foo; + +// Test that qualified paths can refer to both the external crate and local item. +mod std { + pub struct io(pub ()); +} +use ::std::io as std_io; +use self::std::io as local_io; + +fn main() { + Foo(()); + let _ = std_io::stdout(); + local_io(()); + + { + // Test that having `std_io` in a module scope and a non-module + // scope is allowed, when both resolve to the same definition. + use ::std::io as std_io; + use std_io::stdout; + let _ = stdout(); + } +} diff --git a/tests/ui/uniform-paths/issue-53691.rs b/tests/ui/uniform-paths/issue-53691.rs new file mode 100644 index 000000000..5c5ca5b70 --- /dev/null +++ b/tests/ui/uniform-paths/issue-53691.rs @@ -0,0 +1,9 @@ +// run-pass +// aux-build:issue-53691.rs + +extern crate issue_53691; + +fn main() { + issue_53691::f(); + issue_53691::g(); +} diff --git a/tests/ui/uniform-paths/macros-nested.rs b/tests/ui/uniform-paths/macros-nested.rs new file mode 100644 index 000000000..175ccd34e --- /dev/null +++ b/tests/ui/uniform-paths/macros-nested.rs @@ -0,0 +1,53 @@ +// This test is similar to `macros.rs`, but nested in modules. + +// run-pass +// edition:2018 + +#![allow(non_camel_case_types)] + +mod foo { + // Test that ambiguity errors are not emitted between `self::test` and + // `::test`, assuming the latter (crate) is not in `extern_prelude`. + macro_rules! m1 { + () => { + mod test { + pub struct Foo(pub ()); + } + } + } + pub use test::Foo; + m1!(); + + // Test that qualified paths can refer to both the external crate and local item. + macro_rules! m2 { + () => { + mod std { + pub struct io(pub ()); + } + } + } + pub use ::std::io as std_io; + pub use self::std::io as local_io; + m2!(); +} + +// Test that we can refer to the external crate unqualified +// (when there isn't a local item with the same name). +use std::io; + +mod bar { + // Also test the unqualified external crate import in a nested module, + // to show that the above import doesn't resolve through a local `std` + // item, e.g., the automatically injected `extern crate std;`, which in + // the Rust 2018 should no longer be visible through `crate::std`. + pub use std::io; +} + + +fn main() { + foo::Foo(()); + let _ = foo::std_io::stdout(); + foo::local_io(()); + let _ = io::stdout(); + let _ = bar::io::stdout(); +} diff --git a/tests/ui/uniform-paths/macros.rs b/tests/ui/uniform-paths/macros.rs new file mode 100644 index 000000000..bf512b305 --- /dev/null +++ b/tests/ui/uniform-paths/macros.rs @@ -0,0 +1,36 @@ +// This test is similar to `basic.rs`, but with macros defining local items. + +// run-pass +// edition:2018 + +#![allow(non_camel_case_types)] + +// Test that ambiguity errors are not emitted between `self::test` and +// `::test`, assuming the latter (crate) is not in `extern_prelude`. +macro_rules! m1 { + () => { + mod test { + pub struct Foo(pub ()); + } + } +} +use test::Foo; +m1!(); + +// Test that qualified paths can refer to both the external crate and local item. +macro_rules! m2 { + () => { + mod std { + pub struct io(pub ()); + } + } +} +use ::std::io as std_io; +use self::std::io as local_io; +m2!(); + +fn main() { + Foo(()); + let _ = std_io::stdout(); + local_io(()); +} diff --git a/tests/ui/uniform-paths/same-crate.rs b/tests/ui/uniform-paths/same-crate.rs new file mode 100644 index 000000000..ce4cc13d9 --- /dev/null +++ b/tests/ui/uniform-paths/same-crate.rs @@ -0,0 +1,98 @@ +// run-pass +// edition:2018 + +pub const A: usize = 0; + +pub mod foo { + pub const B: usize = 1; + + pub mod bar { + pub const C: usize = 2; + + pub enum E { + V1(usize), + V2(String), + } + + pub fn test() -> String { + format!("{} {} {}", crate::A, crate::foo::B, C) + } + + pub fn test_use() -> String { + use crate::A; + use crate::foo::B; + + format!("{} {} {}", A, B, C) + } + + pub fn test_enum() -> String { + use E::*; + match E::V1(10) { + V1(i) => { format!("V1: {}", i) } + V2(s) => { format!("V2: {}", s) } + } + } + } + + pub fn test() -> String { + format!("{} {} {}", crate::A, B, bar::C) + } + + pub fn test_use() -> String { + use crate::A; + use bar::C; + + format!("{} {} {}", A, B, C) + } + + pub fn test_enum() -> String { + use bar::E::*; + match bar::E::V1(10) { + V1(i) => { format!("V1: {}", i) } + V2(s) => { format!("V2: {}", s) } + } + } +} + +pub fn test() -> String { + format!("{} {} {}", A, foo::B, foo::bar::C) +} + +pub fn test_use() -> String { + use foo::B; + use foo::bar::C; + + format!("{} {} {}", A, B, C) +} + +pub fn test_enum() -> String { + use foo::bar::E::*; + match foo::bar::E::V1(10) { + V1(i) => { format!("V1: {}", i) } + V2(s) => { format!("V2: {}", s) } + } +} + +fn main() { + let output = [ + test(), + foo::test(), + foo::bar::test(), + test_use(), + foo::test_use(), + foo::bar::test_use(), + test_enum(), + foo::test_enum(), + foo::bar::test_enum(), + ].join("\n"); + assert_eq!(output, "\ +0 1 2 +0 1 2 +0 1 2 +0 1 2 +0 1 2 +0 1 2 +V1: 10 +V1: 10 +V1: 10"); +} diff --git a/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs b/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs new file mode 100644 index 000000000..b59432078 --- /dev/null +++ b/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(exhaustive_patterns)] + +enum Void {} +fn main() { + let a: Option = None; + let None = a; +} diff --git a/tests/ui/uninhabited/privately-uninhabited-dead-code.rs b/tests/ui/uninhabited/privately-uninhabited-dead-code.rs new file mode 100644 index 000000000..f476704cd --- /dev/null +++ b/tests/ui/uninhabited/privately-uninhabited-dead-code.rs @@ -0,0 +1,20 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![deny(unused_variables)] + +mod foo { + enum Bar {} + + #[allow(dead_code)] + pub struct Foo { + value: Bar, // "privately" uninhabited + } + + pub fn give_foo() -> Foo { panic!() } +} + +fn main() { + let a = 42; + foo::give_foo(); + println!("Hello, {}", a); // ok: we can't tell that this code is dead +} diff --git a/tests/ui/uninhabited/privately-uninhabited-mir-call.rs b/tests/ui/uninhabited/privately-uninhabited-mir-call.rs new file mode 100644 index 000000000..2764bb563 --- /dev/null +++ b/tests/ui/uninhabited/privately-uninhabited-mir-call.rs @@ -0,0 +1,29 @@ +// Verifies that MIR building for a call expression respects +// privacy when checking if a call return type is uninhabited. + +pub mod widget { + enum Unimplemented {} + pub struct Widget(Unimplemented); + + impl Widget { + pub fn new() -> Widget { + todo!(); + } + } + + pub fn f() { + let x: &mut u32; + Widget::new(); + // Ok. Widget type returned from new is known to be uninhabited + // and the following code is considered unreachable. + *x = 1; + } +} + +fn main() { + let y: &mut u32; + widget::Widget::new(); + // Error. Widget type is not known to be uninhabited here, + // so the following code is considered reachable. + *y = 2; //~ ERROR E0381 +} diff --git a/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr b/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr new file mode 100644 index 000000000..0dfd22a30 --- /dev/null +++ b/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr @@ -0,0 +1,17 @@ +error[E0381]: used binding `y` isn't initialized + --> $DIR/privately-uninhabited-mir-call.rs:28:5 + | +LL | let y: &mut u32; + | - binding declared here but left uninitialized +... +LL | *y = 2; + | ^^^^^^ `y` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let y: &mut u32 = todo!(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/uninhabited/uninhabited-enum-cast.rs b/tests/ui/uninhabited/uninhabited-enum-cast.rs new file mode 100644 index 000000000..5a75c94c4 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-enum-cast.rs @@ -0,0 +1,9 @@ +// check-pass + +enum E {} + +fn f(e: E) { + println!("{}", (e as isize).to_string()); +} + +fn main() {} diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs new file mode 100644 index 000000000..4b001aca2 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs @@ -0,0 +1,30 @@ +#![feature(never_type)] +#![feature(exhaustive_patterns)] + +mod foo { + pub struct SecretlyEmpty { + _priv: !, + } + + pub struct NotSoSecretlyEmpty { + pub _pub: !, + } +} + +struct NotSoSecretlyEmpty { + _priv: !, +} + +enum Foo { + A(foo::SecretlyEmpty), + B(foo::NotSoSecretlyEmpty), + C(NotSoSecretlyEmpty), + D(u32, u32), +} + +fn main() { + let x: Foo = Foo::D(123, 456); + let Foo::D(_y, _z) = x; + //~^ ERROR refutable pattern in local binding + //~| `Foo::A(_)` not covered +} diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.stderr new file mode 100644 index 000000000..8cafea555 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-irrefutable.stderr @@ -0,0 +1,24 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/uninhabited-irrefutable.rs:27:9 + | +LL | let Foo::D(_y, _z) = x; + | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Foo` defined here + --> $DIR/uninhabited-irrefutable.rs:18:6 + | +LL | enum Foo { + | ^^^ +LL | A(foo::SecretlyEmpty), + | - not covered + = note: the matched value is of type `Foo` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Foo::D(_y, _z) = x else { todo!() }; + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs b/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs new file mode 100644 index 000000000..e804afcf9 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs @@ -0,0 +1,39 @@ +use std::mem::zeroed; +enum Void {} + +fn main() { + let x: Result = Ok(23); + let _ = match x { //~ ERROR non-exhaustive + Ok(n) => n, + }; + + // This is pretty much instant UB. However, we have no choice -- we need to + // test matching on a reference to `&Void`; we cannot do anything other than + // just accept the fact that this is UB if `main` did run, but it doesn't; + // this test only checks that these are feature-gated. + let x: &Void = unsafe { zeroed() }; + let _ = match x {}; //~ ERROR non-exhaustive + + let x: (Void,) = unsafe { zeroed() }; + let _ = match x {}; //~ ERROR non-exhaustive + + let x: [Void; 1] = unsafe { zeroed() }; + let _ = match x {}; //~ ERROR non-exhaustive + + let x: &[Void] = unsafe { zeroed() }; + let _ = match x { //~ ERROR non-exhaustive + &[] => (), + }; + + let x: Void = unsafe { zeroed() }; + let _ = match x {}; // okay + + let x: Result = Ok(23); + let _ = match x { //~ ERROR non-exhaustive + Ok(x) => x, + }; + + let x: Result = Ok(23); + let Ok(x) = x; + //~^ ERROR refutable +} diff --git a/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr new file mode 100644 index 000000000..466d7f2ea --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -0,0 +1,115 @@ +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/uninhabited-matches-feature-gated.rs:6:19 + | +LL | let _ = match x { + | ^ pattern `Err(_)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Ok(n) => n, +LL ~ Err(_) => todo!(), + | + +error[E0004]: non-exhaustive patterns: type `&Void` is non-empty + --> $DIR/uninhabited-matches-feature-gated.rs:15:19 + | +LL | let _ = match x {}; + | ^ + | +note: `Void` defined here + --> $DIR/uninhabited-matches-feature-gated.rs:2:6 + | +LL | enum Void {} + | ^^^^ + = note: the matched value is of type `&Void` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let _ = match x { +LL + _ => todo!(), +LL ~ }; + | + +error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty + --> $DIR/uninhabited-matches-feature-gated.rs:18:19 + | +LL | let _ = match x {}; + | ^ + | + = note: the matched value is of type `(Void,)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let _ = match x { +LL + _ => todo!(), +LL ~ }; + | + +error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty + --> $DIR/uninhabited-matches-feature-gated.rs:21:19 + | +LL | let _ = match x {}; + | ^ + | + = note: the matched value is of type `[Void; 1]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ let _ = match x { +LL + _ => todo!(), +LL ~ }; + | + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/uninhabited-matches-feature-gated.rs:24:19 + | +LL | let _ = match x { + | ^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[Void]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[] => (), +LL ~ &[_, ..] => todo!(), + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/uninhabited-matches-feature-gated.rs:32:19 + | +LL | let _ = match x { + | ^ pattern `Err(_)` not covered + | +note: `Result` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Ok(x) => x, +LL ~ Err(_) => todo!(), + | + +error[E0005]: refutable pattern in local binding + --> $DIR/uninhabited-matches-feature-gated.rs:37:9 + | +LL | let Ok(x) = x; + | ^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(x) = x else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/uninhabited/uninhabited-patterns.rs b/tests/ui/uninhabited/uninhabited-patterns.rs new file mode 100644 index 000000000..f1573b6ad --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-patterns.rs @@ -0,0 +1,47 @@ +#![feature(box_patterns)] +#![feature(never_type)] +#![feature(exhaustive_patterns)] + + +#![deny(unreachable_patterns)] + +mod foo { + pub struct SecretlyEmpty { + _priv: !, + } +} + +struct NotSoSecretlyEmpty { + _priv: !, +} + +fn foo() -> Option { + None +} + +fn main() { + let x: &[!] = &[]; + + match x { + &[] => (), + &[..] => (), //~ ERROR unreachable pattern + }; + + let x: Result, &[Result]> = Err(&[]); + match x { + Ok(box _) => (), //~ ERROR unreachable pattern + Err(&[]) => (), + Err(&[..]) => (), //~ ERROR unreachable pattern + } + + let x: Result> = Err(Err(123)); + match x { + Ok(_y) => (), + Err(Err(_y)) => (), + Err(Ok(_y)) => (), //~ ERROR unreachable pattern + } + + while let Some(_y) = foo() { + //~^ ERROR unreachable pattern + } +} diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr new file mode 100644 index 000000000..655569ad6 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -0,0 +1,38 @@ +error: unreachable pattern + --> $DIR/uninhabited-patterns.rs:27:9 + | +LL | &[..] => (), + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/uninhabited-patterns.rs:6:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited-patterns.rs:32:9 + | +LL | Ok(box _) => (), + | ^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited-patterns.rs:34:9 + | +LL | Err(&[..]) => (), + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited-patterns.rs:41:9 + | +LL | Err(Ok(_y)) => (), + | ^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited-patterns.rs:44:15 + | +LL | while let Some(_y) = foo() { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/uninit-empty-types.rs b/tests/ui/uninit-empty-types.rs new file mode 100644 index 000000000..b21de882b --- /dev/null +++ b/tests/ui/uninit-empty-types.rs @@ -0,0 +1,19 @@ +// build-pass +// Test the uninit() construct returning various empty types. + +// pretty-expanded FIXME #23616 + +use std::mem::MaybeUninit; + +struct Foo; + +#[allow(deprecated)] +pub fn main() { + unsafe { + // `Foo` and `[Foo; 2]` are both zero sized and inhabited, so this is safe. + let _x: Foo = MaybeUninit::uninit().assume_init(); + let _x: [Foo; 2] = MaybeUninit::uninit().assume_init(); + let _x: Foo = std::mem::uninitialized(); + let _x: [Foo; 2] = std::mem::uninitialized(); + } +} diff --git a/tests/ui/union/auxiliary/union.rs b/tests/ui/union/auxiliary/union.rs new file mode 100644 index 000000000..e785e35ae --- /dev/null +++ b/tests/ui/union/auxiliary/union.rs @@ -0,0 +1,4 @@ +pub union U { + pub a: u8, + pub b: u16, +} diff --git a/tests/ui/union/field_checks.rs b/tests/ui/union/field_checks.rs new file mode 100644 index 000000000..d5d1e44ac --- /dev/null +++ b/tests/ui/union/field_checks.rs @@ -0,0 +1,65 @@ +use std::mem::ManuallyDrop; + +union U1 { // OK + a: u8, +} + +union U2 { // OK + a: T, +} + +union U22 { // OK + a: ManuallyDrop, +} + +union U23 { // OK + a: (ManuallyDrop, i32), +} + +union U24 { // OK + a: [ManuallyDrop; 2], +} + +union U3 { + a: String, //~ ERROR unions cannot contain fields that may need dropping +} + +union U32 { // field that does not drop but is not `Copy`, either + a: std::cell::RefCell, //~ ERROR unions cannot contain fields that may need dropping +} + +union U4 { + a: T, //~ ERROR unions cannot contain fields that may need dropping +} + +union U5 { // Having a drop impl is OK + a: u8, +} + +impl Drop for U5 { + fn drop(&mut self) {} +} + +union U5Nested { // a nested union that drops is NOT OK + nest: U5, //~ ERROR unions cannot contain fields that may need dropping +} + +union U5Nested2 { // for now we don't special-case empty arrays + nest: [U5; 0], //~ ERROR unions cannot contain fields that may need dropping +} + +union U6 { // OK + s: &'static i32, + m: &'static mut i32, +} + +union U7 { // OK + f: (&'static mut i32, ManuallyDrop, i32), +} + +union U8 { // OK + f1: [(&'static mut i32, i32); 8], + f2: [ManuallyDrop; 2], +} + +fn main() {} diff --git a/tests/ui/union/field_checks.stderr b/tests/ui/union/field_checks.stderr new file mode 100644 index 000000000..1f97e97ac --- /dev/null +++ b/tests/ui/union/field_checks.stderr @@ -0,0 +1,63 @@ +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/field_checks.rs:24:5 + | +LL | a: String, + | ^^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/field_checks.rs:28:5 + | +LL | a: std::cell::RefCell, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop>, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/field_checks.rs:32:5 + | +LL | a: T, + | ^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/field_checks.rs:44:5 + | +LL | nest: U5, + | ^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | nest: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/field_checks.rs:48:5 + | +LL | nest: [U5; 0], + | ^^^^^^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | nest: std::mem::ManuallyDrop<[U5; 0]>, + | +++++++++++++++++++++++ + + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0740`. diff --git a/tests/ui/union/issue-41073.rs b/tests/ui/union/issue-41073.rs new file mode 100644 index 000000000..4dfdc606b --- /dev/null +++ b/tests/ui/union/issue-41073.rs @@ -0,0 +1,22 @@ +union Test { + a: A, //~ ERROR unions cannot contain fields that may need dropping + b: B +} + +#[derive(Debug)] +struct A(i32); +impl Drop for A { + fn drop(&mut self) { println!("A"); } +} + +#[derive(Debug)] +struct B(f32); +impl Drop for B { + fn drop(&mut self) { println!("B"); } +} + +fn main() { + let mut test = Test { a: A(3) }; + println!("{:?}", unsafe { test.b }); + unsafe { test.b = B(0.5); } +} diff --git a/tests/ui/union/issue-41073.stderr b/tests/ui/union/issue-41073.stderr new file mode 100644 index 000000000..b3887fa0f --- /dev/null +++ b/tests/ui/union/issue-41073.stderr @@ -0,0 +1,15 @@ +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/issue-41073.rs:2:5 + | +LL | a: A, + | ^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0740`. diff --git a/tests/ui/union/issue-81199.rs b/tests/ui/union/issue-81199.rs new file mode 100644 index 000000000..628e7c6ed --- /dev/null +++ b/tests/ui/union/issue-81199.rs @@ -0,0 +1,21 @@ +#[repr(C)] +union PtrRepr { + const_ptr: *const T, + mut_ptr: *mut T, + components: PtrComponents, + //~^ ERROR the trait bound +} + +#[repr(C)] +struct PtrComponents { + data_address: *const (), + metadata: ::Metadata, +} + + + +pub trait Pointee { + type Metadata; +} + +fn main() {} diff --git a/tests/ui/union/issue-81199.stderr b/tests/ui/union/issue-81199.stderr new file mode 100644 index 000000000..5bb986753 --- /dev/null +++ b/tests/ui/union/issue-81199.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Pointee` is not satisfied + --> $DIR/issue-81199.rs:5:17 + | +LL | components: PtrComponents, + | ^^^^^^^^^^^^^^^^ the trait `Pointee` is not implemented for `T` + | +note: required by a bound in `PtrComponents` + --> $DIR/issue-81199.rs:10:25 + | +LL | struct PtrComponents { + | ^^^^^^^ required by this bound in `PtrComponents` +help: consider further restricting this bound + | +LL | union PtrRepr { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/issue-99375.rs b/tests/ui/union/issue-99375.rs new file mode 100644 index 000000000..175018a7d --- /dev/null +++ b/tests/ui/union/issue-99375.rs @@ -0,0 +1,21 @@ +// check-pass + +union URes { + uninit: (), + init: R, +} + +struct Params { + function: F, + result: URes, +} + +unsafe extern "C" fn do_call(params: *mut Params) +where + R: Copy, + F: Fn() -> R, +{ + (*params).result.init = ((*params).function)(); +} + +fn main() {} diff --git a/tests/ui/union/union-align.rs b/tests/ui/union/union-align.rs new file mode 100644 index 000000000..6a44f27db --- /dev/null +++ b/tests/ui/union/union-align.rs @@ -0,0 +1,65 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] + +use std::mem::{size_of, size_of_val, align_of, align_of_val}; + +#[repr(align(16))] +pub union U16 { + a: u8, + b: u32 +} + +fn main() { + assert_eq!(align_of::(), 16); + assert_eq!(size_of::(), 16); + let u = U16 { a: 10 }; + unsafe { + assert_eq!(align_of_val(&u.a), 1); + assert_eq!(size_of_val(&u.a), 1); + assert_eq!(u.a, 10); + } + + let u = U16 { b: 11 }; + unsafe { + assert_eq!(align_of_val(&u.b), 4); + assert_eq!(size_of_val(&u.b), 4); + assert_eq!(u.b, 11); + } + + hybrid::check_hybrid(); +} + +mod hybrid { + use std::mem::{size_of, align_of}; + + #[repr(align(16))] + #[derive(Copy, Clone)] + struct S1 { + a: u16, + b: u8, + } + + #[repr(align(32))] + union U { + s: S1, + c: u16, + } + + #[repr(align(64))] + struct S2 { + d: u8, + u: U, + } + + pub fn check_hybrid() { + assert_eq!(align_of::(), 16); + assert_eq!(size_of::(), 16); + assert_eq!(align_of::(), 32); + assert_eq!(size_of::(), 32); + assert_eq!(align_of::(), 64); + assert_eq!(size_of::(), 64); + } +} diff --git a/tests/ui/union/union-backcomp.rs b/tests/ui/union/union-backcomp.rs new file mode 100644 index 000000000..b19eab9f5 --- /dev/null +++ b/tests/ui/union/union-backcomp.rs @@ -0,0 +1,28 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(path_statements)] +#![allow(dead_code)] + +macro_rules! union { + () => (struct S;) +} + +union!(); + +fn union() {} + +fn main() { + union(); + + let union = 10; + + union; + + union as u8; + + union U { + a: u8, + } +} diff --git a/tests/ui/union/union-basic.rs b/tests/ui/union/union-basic.rs new file mode 100644 index 000000000..dcc552ac7 --- /dev/null +++ b/tests/ui/union/union-basic.rs @@ -0,0 +1,62 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(unused_imports)] + +// aux-build:union.rs + +extern crate union; +use std::mem::{size_of, align_of, zeroed}; + +union U { + a: u8, + b: u16 +} + +fn local() { + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + + let u = U { a: 10 }; + unsafe { + assert_eq!(u.a, 10); + let U { a } = u; + assert_eq!(a, 10); + } + + let mut w = U { b: 0 }; + unsafe { + assert_eq!(w.a, 0); + assert_eq!(w.b, 0); + w.a = 1; + assert_eq!(w.a, 1); + assert_eq!(w.b.to_le(), 1); + } +} + +fn xcrate() { + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + + let u = union::U { a: 10 }; + unsafe { + assert_eq!(u.a, 10); + let union::U { a } = u; + assert_eq!(a, 10); + } + + let mut w = union::U { b: 0 }; + unsafe { + assert_eq!(w.a, 0); + assert_eq!(w.b, 0); + w.a = 1; + assert_eq!(w.a, 1); + assert_eq!(w.b.to_le(), 1); + } +} + +fn main() { + local(); + xcrate(); +} diff --git a/tests/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr b/tests/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr new file mode 100644 index 000000000..7f931b49a --- /dev/null +++ b/tests/ui/union/union-borrow-move-parent-sibling.mirunsafeck.stderr @@ -0,0 +1,84 @@ +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x`) + --> $DIR/union-borrow-move-parent-sibling.rs:56:13 + | +LL | let a = &mut (*u.x).0; + | --- mutable borrow occurs here (via `u.x`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x` + +error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, MockVec), MockVec)>` + --> $DIR/union-borrow-move-parent-sibling.rs:62:13 + | +LL | let a = u.x.0; + | ^^^^^ move occurs because value has type `(MockVec, MockVec)`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &u.x.0; + | + + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:64:13 + | +LL | let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = u.x.0; +LL | let a = u.x; + | --- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x`) + --> $DIR/union-borrow-move-parent-sibling.rs:70:13 + | +LL | let a = &mut ((*u.x).0).0; + | --- mutable borrow occurs here (via `u.x`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x` + +error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, MockVec), MockVec)>` + --> $DIR/union-borrow-move-parent-sibling.rs:76:13 + | +LL | let a = (u.x.0).0; + | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &(u.x.0).0; + | + + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:78:13 + | +LL | let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = (u.x.0).0; +LL | let a = u.x; + | --- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:84:13 + | +LL | let a = &mut *u.y; + | --- mutable borrow occurs here (via `u.y`) +LL | let b = &u.x; + | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0382, E0502, E0507. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/union/union-borrow-move-parent-sibling.rs b/tests/ui/union/union-borrow-move-parent-sibling.rs new file mode 100644 index 000000000..83781c5e5 --- /dev/null +++ b/tests/ui/union/union-borrow-move-parent-sibling.rs @@ -0,0 +1,96 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(unused)] + +use std::ops::{Deref, DerefMut}; +use std::mem::ManuallyDrop; + +#[derive(Default)] +struct MockBox { + value: [T; 1], +} + +impl MockBox { + fn new(value: T) -> Self { MockBox { value: [value] } } +} + +impl Deref for MockBox { + type Target = T; + fn deref(&self) -> &T { &self.value[0] } +} + +impl DerefMut for MockBox { + fn deref_mut(&mut self) -> &mut T { &mut self.value[0] } +} + +#[derive(Default)] +struct MockVec { + value: [T; 0], +} + +impl MockVec { + fn new() -> Self { MockVec { value: [] } } +} + +impl Deref for MockVec { + type Target = [T]; + fn deref(&self) -> &[T] { &self.value } +} + +impl DerefMut for MockVec { + fn deref_mut(&mut self) -> &mut [T] { &mut self.value } +} + + +union U { + x: ManuallyDrop<((MockVec, MockVec), MockVec)>, + y: ManuallyDrop>>, +} + +fn use_borrow(_: &T) {} + +unsafe fn parent_sibling_borrow() { + let mut u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + let a = &mut (*u.x).0; + let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`) + use_borrow(a); +} + +unsafe fn parent_sibling_move() { + let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + let a = u.x.0; //~ERROR cannot move out of dereference + let a = u.x; + let b = u.y; //~ ERROR use of moved value: `u` +} + +unsafe fn grandparent_sibling_borrow() { + let mut u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + let a = &mut ((*u.x).0).0; + let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`) + use_borrow(a); +} + +unsafe fn grandparent_sibling_move() { + let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + let a = (u.x.0).0; //~ERROR cannot move out of dereference + let a = u.x; + let b = u.y; //~ ERROR use of moved value: `u` +} + +unsafe fn deref_sibling_borrow() { + let mut u = U { y: ManuallyDrop::new(MockBox::default()) }; + let a = &mut *u.y; + let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`) + use_borrow(a); +} + +unsafe fn deref_sibling_move() { + let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + // No way to test deref-move without Box in union + // let a = *u.y; + // let b = u.x; ERROR use of moved value: `u` +} + + +fn main() {} diff --git a/tests/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr b/tests/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr new file mode 100644 index 000000000..7f931b49a --- /dev/null +++ b/tests/ui/union/union-borrow-move-parent-sibling.thirunsafeck.stderr @@ -0,0 +1,84 @@ +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x`) + --> $DIR/union-borrow-move-parent-sibling.rs:56:13 + | +LL | let a = &mut (*u.x).0; + | --- mutable borrow occurs here (via `u.x`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x` + +error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, MockVec), MockVec)>` + --> $DIR/union-borrow-move-parent-sibling.rs:62:13 + | +LL | let a = u.x.0; + | ^^^^^ move occurs because value has type `(MockVec, MockVec)`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &u.x.0; + | + + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:64:13 + | +LL | let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = u.x.0; +LL | let a = u.x; + | --- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x`) + --> $DIR/union-borrow-move-parent-sibling.rs:70:13 + | +LL | let a = &mut ((*u.x).0).0; + | --- mutable borrow occurs here (via `u.x`) +LL | let b = &u.y; + | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x` + +error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, MockVec), MockVec)>` + --> $DIR/union-borrow-move-parent-sibling.rs:76:13 + | +LL | let a = (u.x.0).0; + | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let a = &(u.x.0).0; + | + + +error[E0382]: use of moved value: `u` + --> $DIR/union-borrow-move-parent-sibling.rs:78:13 + | +LL | let u = U { x: ManuallyDrop::new(((MockVec::new(), MockVec::new()), MockVec::new())) }; + | - move occurs because `u` has type `U`, which does not implement the `Copy` trait +LL | let a = (u.x.0).0; +LL | let a = u.x; + | --- value moved here +LL | let b = u.y; + | ^^^ value used here after move + +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:84:13 + | +LL | let a = &mut *u.y; + | --- mutable borrow occurs here (via `u.y`) +LL | let b = &u.x; + | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here +LL | use_borrow(a); + | - mutable borrow later used here + | + = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0382, E0502, E0507. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/union/union-const-codegen.rs b/tests/ui/union/union-const-codegen.rs new file mode 100644 index 000000000..32a546cf3 --- /dev/null +++ b/tests/ui/union/union-const-codegen.rs @@ -0,0 +1,19 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + a: u64, + b: u64, +} + +const C: U = U { b: 10 }; + +fn main() { + unsafe { + let a = C.a; + let b = C.b; + assert_eq!(a, 10); + assert_eq!(b, 10); + } +} diff --git a/tests/ui/union/union-const-eval-field.rs b/tests/ui/union/union-const-eval-field.rs new file mode 100644 index 000000000..ca48785cd --- /dev/null +++ b/tests/ui/union/union-const-eval-field.rs @@ -0,0 +1,45 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +type Field1 = (i32, u32); +type Field2 = f32; +type Field3 = i64; + +union DummyUnion { + field1: Field1, + field2: Field2, + field3: Field3, +} + +const FLOAT1_AS_I32: i32 = 1065353216; +const UNION: DummyUnion = DummyUnion { field1: (FLOAT1_AS_I32, 0) }; + +const fn read_field1() -> Field1 { + const FIELD1: Field1 = unsafe { UNION.field1 }; + FIELD1 +} + +const fn read_field2() -> Field2 { + const FIELD2: Field2 = unsafe { UNION.field2 }; + FIELD2 +} + +const fn read_field3() -> Field3 { + const FIELD3: Field3 = unsafe { UNION.field3 }; + FIELD3 +} + +fn main() { + let foo = FLOAT1_AS_I32; + assert_eq!(read_field1().0, foo); + assert_eq!(read_field1().0, FLOAT1_AS_I32); + + let foo = 1.0; + assert_eq!(read_field2(), foo); + assert_eq!(read_field2(), 1.0); + + assert_eq!(read_field3(), unsafe { UNION.field3 }); + let foo = unsafe { UNION.field3 }; + assert_eq!(read_field3(), foo); +} diff --git a/tests/ui/union/union-const-eval.rs b/tests/ui/union/union-const-eval.rs new file mode 100644 index 000000000..32ee4a739 --- /dev/null +++ b/tests/ui/union/union-const-eval.rs @@ -0,0 +1,15 @@ +// check-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + a: usize, + b: usize, +} + +const C: U = U { a: 10 }; + +fn main() { + let a: [u8; unsafe { C.a }]; + let b: [u8; unsafe { C.b }]; +} diff --git a/tests/ui/union/union-const-pat.rs b/tests/ui/union/union-const-pat.rs new file mode 100644 index 000000000..e7cb248a2 --- /dev/null +++ b/tests/ui/union/union-const-pat.rs @@ -0,0 +1,13 @@ +union U { + a: usize, + b: usize, +} + +const C: U = U { a: 10 }; + +fn main() { + match C { + C => {} //~ ERROR cannot use unions in constant patterns + _ => {} + } +} diff --git a/tests/ui/union/union-const-pat.stderr b/tests/ui/union/union-const-pat.stderr new file mode 100644 index 000000000..dc87f4de5 --- /dev/null +++ b/tests/ui/union/union-const-pat.stderr @@ -0,0 +1,8 @@ +error: cannot use unions in constant patterns + --> $DIR/union-const-pat.rs:10:9 + | +LL | C => {} + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/union/union-copy.rs b/tests/ui/union/union-copy.rs new file mode 100644 index 000000000..5c3f8d908 --- /dev/null +++ b/tests/ui/union/union-copy.rs @@ -0,0 +1,14 @@ +#[derive(Clone)] +union U { + a: u8 +} + +#[derive(Clone)] +union W { + a: std::mem::ManuallyDrop +} + +impl Copy for U {} // OK +impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/union/union-copy.stderr b/tests/ui/union/union-copy.stderr new file mode 100644 index 000000000..53ee4dd2e --- /dev/null +++ b/tests/ui/union/union-copy.stderr @@ -0,0 +1,18 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/union-copy.rs:12:15 + | +LL | a: std::mem::ManuallyDrop + | --------------------------------- this field does not implement `Copy` +... +LL | impl Copy for W {} + | ^ + | +note: the `Copy` impl for `ManuallyDrop` requires that `String: Copy` + --> $DIR/union-copy.rs:8:8 + | +LL | a: std::mem::ManuallyDrop + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/union/union-deref.mirunsafeck.stderr b/tests/ui/union/union-deref.mirunsafeck.stderr new file mode 100644 index 000000000..be5e60ab8 --- /dev/null +++ b/tests/ui/union/union-deref.mirunsafeck.stderr @@ -0,0 +1,56 @@ +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:16:14 + | +LL | unsafe { u.f.0 = Vec::new() }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:18:19 + | +LL | unsafe { &mut u.f.0 }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:20:14 + | +LL | unsafe { u.f.0.push(0) }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:24:14 + | +LL | unsafe { u.f.0.0 = Vec::new() }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:26:19 + | +LL | unsafe { &mut u.f.0.0 }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:28:14 + | +LL | unsafe { u.f.0.0.push(0) }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: aborting due to 6 previous errors + diff --git a/tests/ui/union/union-deref.rs b/tests/ui/union/union-deref.rs new file mode 100644 index 000000000..5aa28d93f --- /dev/null +++ b/tests/ui/union/union-deref.rs @@ -0,0 +1,29 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +//! Test the part of RFC 2514 that is about not applying `DerefMut` coercions +//! of union fields. + +use std::mem::ManuallyDrop; + +union U1 { x:(), f: ManuallyDrop<(T,)> } + +union U2 { x:(), f: (ManuallyDrop<(T,)>,) } + +fn main() { + let mut u : U1> = U1 { x: () }; + unsafe { (*u.f).0 = Vec::new() }; // explicit deref, this compiles + unsafe { u.f.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { &mut (*u.f).0 }; // explicit deref, this compiles + unsafe { &mut u.f.0 }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { (*u.f).0.push(0) }; // explicit deref, this compiles + unsafe { u.f.0.push(0) }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + + let mut u : U2> = U2 { x: () }; + unsafe { (*u.f.0).0 = Vec::new() }; // explicit deref, this compiles + unsafe { u.f.0.0 = Vec::new() }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { &mut (*u.f.0).0 }; // explicit deref, this compiles + unsafe { &mut u.f.0.0 }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field + unsafe { (*u.f.0).0.push(0) }; // explicit deref, this compiles + unsafe { u.f.0.0.push(0) }; //~ERROR not automatically applying `DerefMut` on `ManuallyDrop` union field +} diff --git a/tests/ui/union/union-deref.thirunsafeck.stderr b/tests/ui/union/union-deref.thirunsafeck.stderr new file mode 100644 index 000000000..be5e60ab8 --- /dev/null +++ b/tests/ui/union/union-deref.thirunsafeck.stderr @@ -0,0 +1,56 @@ +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:16:14 + | +LL | unsafe { u.f.0 = Vec::new() }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:18:19 + | +LL | unsafe { &mut u.f.0 }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:20:14 + | +LL | unsafe { u.f.0.push(0) }; + | ^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:24:14 + | +LL | unsafe { u.f.0.0 = Vec::new() }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:26:19 + | +LL | unsafe { &mut u.f.0.0 }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: not automatically applying `DerefMut` on `ManuallyDrop` union field + --> $DIR/union-deref.rs:28:14 + | +LL | unsafe { u.f.0.0.push(0) }; + | ^^^^^ + | + = help: writing to this reference calls the destructor for the old value + = help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor + +error: aborting due to 6 previous errors + diff --git a/tests/ui/union/union-derive-clone.mirunsafeck.stderr b/tests/ui/union/union-derive-clone.mirunsafeck.stderr new file mode 100644 index 000000000..b80e8b988 --- /dev/null +++ b/tests/ui/union/union-derive-clone.mirunsafeck.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `U1: Copy` is not satisfied + --> $DIR/union-derive-clone.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ the trait `Copy` is not implemented for `U1` + | +note: required by a bound in `AssertParamIsCopy` + --> $SRC_DIR/core/src/clone.rs:LL:COL + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `U1` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied + --> $DIR/union-derive-clone.rs:38:15 + | +LL | union U5 { + | ----------- + | | + | method `clone` not found for this union + | doesn't satisfy `U5: Clone` +... +LL | struct CloneNoCopy; + | ------------------ doesn't satisfy `CloneNoCopy: Copy` +... +LL | let w = u.clone(); + | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds + | +note: trait bound `CloneNoCopy: Copy` was not satisfied + --> $DIR/union-derive-clone.rs:28:10 + | +LL | #[derive(Clone, Copy)] + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro +help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` + | +LL | #[derive(Clone, Copy)] + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-derive-clone.rs b/tests/ui/union/union-derive-clone.rs new file mode 100644 index 000000000..7aa62146e --- /dev/null +++ b/tests/ui/union/union-derive-clone.rs @@ -0,0 +1,39 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +use std::mem::ManuallyDrop; + +#[derive(Clone)] //~ ERROR the trait bound `U1: Copy` is not satisfied +union U1 { + a: u8, +} + +#[derive(Clone)] +union U2 { + a: u8, // OK +} + +impl Copy for U2 {} + +#[derive(Clone, Copy)] +union U3 { + a: u8, // OK +} + +#[derive(Clone, Copy)] +union U4 { + a: T, // OK +} + +#[derive(Clone, Copy)] +union U5 { + a: ManuallyDrop, // OK +} + +#[derive(Clone)] +struct CloneNoCopy; + +fn main() { + let u = U5 { a: ManuallyDrop::new(CloneNoCopy) }; + let w = u.clone(); //~ ERROR the method +} diff --git a/tests/ui/union/union-derive-clone.thirunsafeck.stderr b/tests/ui/union/union-derive-clone.thirunsafeck.stderr new file mode 100644 index 000000000..b80e8b988 --- /dev/null +++ b/tests/ui/union/union-derive-clone.thirunsafeck.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `U1: Copy` is not satisfied + --> $DIR/union-derive-clone.rs:6:10 + | +LL | #[derive(Clone)] + | ^^^^^ the trait `Copy` is not implemented for `U1` + | +note: required by a bound in `AssertParamIsCopy` + --> $SRC_DIR/core/src/clone.rs:LL:COL + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `U1` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error[E0599]: the method `clone` exists for union `U5`, but its trait bounds were not satisfied + --> $DIR/union-derive-clone.rs:38:15 + | +LL | union U5 { + | ----------- + | | + | method `clone` not found for this union + | doesn't satisfy `U5: Clone` +... +LL | struct CloneNoCopy; + | ------------------ doesn't satisfy `CloneNoCopy: Copy` +... +LL | let w = u.clone(); + | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds + | +note: trait bound `CloneNoCopy: Copy` was not satisfied + --> $DIR/union-derive-clone.rs:28:10 + | +LL | #[derive(Clone, Copy)] + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro +help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` + | +LL | #[derive(Clone, Copy)] + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-derive-eq.mirunsafeck.stderr b/tests/ui/union/union-derive-eq.mirunsafeck.stderr new file mode 100644 index 000000000..9e55390b5 --- /dev/null +++ b/tests/ui/union/union-derive-eq.mirunsafeck.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied + --> $DIR/union-derive-eq.rs:16:5 + | +LL | #[derive(Eq)] + | -- in this derive macro expansion +LL | union U2 { +LL | a: PartialEqNotEq, + | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-derive-eq.rs b/tests/ui/union/union-derive-eq.rs new file mode 100644 index 000000000..b7e7f343f --- /dev/null +++ b/tests/ui/union/union-derive-eq.rs @@ -0,0 +1,21 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#[derive(Eq)] // OK +union U1 { + a: u8, +} + +impl PartialEq for U1 { fn eq(&self, rhs: &Self) -> bool { true } } + +#[derive(PartialEq, Copy, Clone)] +struct PartialEqNotEq; + +#[derive(Eq)] +union U2 { + a: PartialEqNotEq, //~ ERROR the trait bound `PartialEqNotEq: Eq` is not satisfied +} + +impl PartialEq for U2 { fn eq(&self, rhs: &Self) -> bool { true } } + +fn main() {} diff --git a/tests/ui/union/union-derive-eq.thirunsafeck.stderr b/tests/ui/union/union-derive-eq.thirunsafeck.stderr new file mode 100644 index 000000000..9e55390b5 --- /dev/null +++ b/tests/ui/union/union-derive-eq.thirunsafeck.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied + --> $DIR/union-derive-eq.rs:16:5 + | +LL | #[derive(Eq)] + | -- in this derive macro expansion +LL | union U2 { +LL | a: PartialEqNotEq, + | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-derive-rpass.rs b/tests/ui/union/union-derive-rpass.rs new file mode 100644 index 000000000..8276bc635 --- /dev/null +++ b/tests/ui/union/union-derive-rpass.rs @@ -0,0 +1,42 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] +#![allow(unused_variables)] + +// Some traits can be derived for unions. + +#[derive( + Copy, + Clone, + Eq, +)] +union U { + a: u8, + b: u16, +} + +impl PartialEq for U { fn eq(&self, rhs: &Self) -> bool { true } } + +#[derive( + Clone, + Copy, + Eq +)] +union W { + a: T, +} + +impl PartialEq for W { fn eq(&self, rhs: &Self) -> bool { true } } + +fn main() { + let u = U { b: 0 }; + let u1 = u; + let u2 = u.clone(); + assert!(u1 == u2); + + let w = W { a: 0 }; + let w1 = w.clone(); + assert!(w == w1); +} diff --git a/tests/ui/union/union-derive.rs b/tests/ui/union/union-derive.rs new file mode 100644 index 000000000..652a6b24c --- /dev/null +++ b/tests/ui/union/union-derive.rs @@ -0,0 +1,16 @@ +// Most traits cannot be derived for unions. + +#[derive( + PartialEq, //~ ERROR this trait cannot be derived for unions + PartialOrd, //~ ERROR this trait cannot be derived for unions + Ord, //~ ERROR this trait cannot be derived for unions + Hash, //~ ERROR this trait cannot be derived for unions + Default, //~ ERROR this trait cannot be derived for unions + Debug, //~ ERROR this trait cannot be derived for unions +)] +union U { + a: u8, + b: u16, +} + +fn main() {} diff --git a/tests/ui/union/union-derive.stderr b/tests/ui/union/union-derive.stderr new file mode 100644 index 000000000..6ef72c901 --- /dev/null +++ b/tests/ui/union/union-derive.stderr @@ -0,0 +1,38 @@ +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:4:5 + | +LL | PartialEq, + | ^^^^^^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:5:5 + | +LL | PartialOrd, + | ^^^^^^^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:6:5 + | +LL | Ord, + | ^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:7:5 + | +LL | Hash, + | ^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:8:5 + | +LL | Default, + | ^^^^^^^ + +error: this trait cannot be derived for unions + --> $DIR/union-derive.rs:9:5 + | +LL | Debug, + | ^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/union/union-drop-assign.rs b/tests/ui/union/union-drop-assign.rs new file mode 100644 index 000000000..215666bdd --- /dev/null +++ b/tests/ui/union/union-drop-assign.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(unused_assignments)] + +// Drop works for union itself. + +use std::mem::ManuallyDrop; + +struct S; + +union U { + a: ManuallyDrop +} + +impl Drop for S { + fn drop(&mut self) { + unsafe { CHECK += 10; } + } +} + +impl Drop for U { + fn drop(&mut self) { + unsafe { CHECK += 1; } + } +} + +static mut CHECK: u8 = 0; + +fn main() { + unsafe { + let mut u = U { a: ManuallyDrop::new(S) }; + assert_eq!(CHECK, 0); + u = U { a: ManuallyDrop::new(S) }; + assert_eq!(CHECK, 1); // union itself is assigned, union is dropped, field is not dropped + *u.a = S; + assert_eq!(CHECK, 11); // union field is assigned, field is dropped + } +} diff --git a/tests/ui/union/union-drop.rs b/tests/ui/union/union-drop.rs new file mode 100644 index 000000000..c3d7d41ca --- /dev/null +++ b/tests/ui/union/union-drop.rs @@ -0,0 +1,60 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] +#![allow(unused_variables)] + +// Drop works for union itself. + +#[derive(Copy, Clone)] +struct S; + +union U { + a: u8 +} + +union W { + a: S, +} + +union Y { + a: S, +} + +impl Drop for U { + fn drop(&mut self) { + unsafe { CHECK += 1; } + } +} + +impl Drop for W { + fn drop(&mut self) { + unsafe { CHECK += 1; } + } +} + +static mut CHECK: u8 = 0; + +fn main() { + unsafe { + assert_eq!(CHECK, 0); + { + let u = U { a: 1 }; + } + assert_eq!(CHECK, 1); // 1, dtor of U is called + { + let w = W { a: S }; + } + assert_eq!(CHECK, 2); // 2, dtor of W is called + { + let y = Y { a: S }; + } + assert_eq!(CHECK, 2); // 2, Y has no dtor + { + let u2 = U { a: 1 }; + std::mem::forget(u2); + } + assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2 + } +} diff --git a/tests/ui/union/union-empty.rs b/tests/ui/union/union-empty.rs new file mode 100644 index 000000000..79b7e68ee --- /dev/null +++ b/tests/ui/union/union-empty.rs @@ -0,0 +1,3 @@ +union U {} //~ ERROR unions cannot have zero fields + +fn main() {} diff --git a/tests/ui/union/union-empty.stderr b/tests/ui/union/union-empty.stderr new file mode 100644 index 000000000..a80b27e6e --- /dev/null +++ b/tests/ui/union/union-empty.stderr @@ -0,0 +1,8 @@ +error: unions cannot have zero fields + --> $DIR/union-empty.rs:1:1 + | +LL | union U {} + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/union/union-fields-1.mirunsafeck.stderr b/tests/ui/union/union-fields-1.mirunsafeck.stderr new file mode 100644 index 000000000..0c9981c69 --- /dev/null +++ b/tests/ui/union/union-fields-1.mirunsafeck.stderr @@ -0,0 +1,42 @@ +error: field `c` is never read + --> $DIR/union-fields-1.rs:9:5 + | +LL | union U1 { + | -- field in this union +... +LL | c: u8, + | ^ + | +note: the lint level is defined here + --> $DIR/union-fields-1.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: field `a` is never read + --> $DIR/union-fields-1.rs:12:5 + | +LL | union U2 { + | -- field in this union +LL | a: u8, + | ^ + +error: field `a` is never read + --> $DIR/union-fields-1.rs:16:20 + | +LL | union NoDropLike { a: u8 } + | ---------- ^ + | | + | field in this union + +error: field `c` is never read + --> $DIR/union-fields-1.rs:21:5 + | +LL | union U { + | - field in this union +... +LL | c: u8, + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/union/union-fields-1.rs b/tests/ui/union/union-fields-1.rs new file mode 100644 index 000000000..cf2ef4c03 --- /dev/null +++ b/tests/ui/union/union-fields-1.rs @@ -0,0 +1,35 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![deny(dead_code)] + +union U1 { + a: u8, // should not be reported + b: u8, // should not be reported + c: u8, //~ ERROR field `c` is never read +} +union U2 { + a: u8, //~ ERROR field `a` is never read + b: u8, // should not be reported + c: u8, // should not be reported +} +union NoDropLike { a: u8 } //~ ERROR field `a` is never read + +union U { + a: u8, // should not be reported + b: u8, // should not be reported + c: u8, //~ ERROR field `c` is never read +} +type A = U; + +fn main() { + let u = U1 { a: 0 }; + let _a = unsafe { u.b }; + + let u = U2 { c: 0 }; + let _b = unsafe { u.b }; + + let _u = NoDropLike { a: 10 }; + let u = A { a: 0 }; + let _b = unsafe { u.b }; +} diff --git a/tests/ui/union/union-fields-1.thirunsafeck.stderr b/tests/ui/union/union-fields-1.thirunsafeck.stderr new file mode 100644 index 000000000..0c9981c69 --- /dev/null +++ b/tests/ui/union/union-fields-1.thirunsafeck.stderr @@ -0,0 +1,42 @@ +error: field `c` is never read + --> $DIR/union-fields-1.rs:9:5 + | +LL | union U1 { + | -- field in this union +... +LL | c: u8, + | ^ + | +note: the lint level is defined here + --> $DIR/union-fields-1.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: field `a` is never read + --> $DIR/union-fields-1.rs:12:5 + | +LL | union U2 { + | -- field in this union +LL | a: u8, + | ^ + +error: field `a` is never read + --> $DIR/union-fields-1.rs:16:20 + | +LL | union NoDropLike { a: u8 } + | ---------- ^ + | | + | field in this union + +error: field `c` is never read + --> $DIR/union-fields-1.rs:21:5 + | +LL | union U { + | - field in this union +... +LL | c: u8, + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/union/union-fields-2.mirunsafeck.stderr b/tests/ui/union/union-fields-2.mirunsafeck.stderr new file mode 100644 index 000000000..90ad16402 --- /dev/null +++ b/tests/ui/union/union-fields-2.mirunsafeck.stderr @@ -0,0 +1,84 @@ +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:10:13 + | +LL | let u = U {}; + | ^ + +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:12:13 + | +LL | let u = U { a: 0, b: 1 }; + | ^ + +error[E0560]: union `U` has no field named `c` + --> $DIR/union-fields-2.rs:13:29 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ `U` does not have this field + | + = note: available fields are: `a`, `b` + +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:13:13 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ + +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:15:13 + | +LL | let u = U { ..u }; + | ^ + +error[E0436]: functional record update syntax requires a struct + --> $DIR/union-fields-2.rs:15:19 + | +LL | let u = U { ..u }; + | ^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:18:9 + | +LL | let U {} = u; + | ^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:20:9 + | +LL | let U { a, b } = u; + | ^^^^^^^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:21:9 + | +LL | let U { a, b, c } = u; + | ^^^^^^^^^^^^^ + +error[E0026]: union `U` does not have a field named `c` + --> $DIR/union-fields-2.rs:21:19 + | +LL | let U { a, b, c } = u; + | ^ union `U` does not have this field + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:25:9 + | +LL | let U { a, .. } = u; + | ^^^^^^^^^^^ + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0026, E0436, E0560, E0784. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/union/union-fields-2.rs b/tests/ui/union/union-fields-2.rs new file mode 100644 index 000000000..e738b1847 --- /dev/null +++ b/tests/ui/union/union-fields-2.rs @@ -0,0 +1,26 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + a: u8, + b: u16, +} + +fn main() { + let u = U {}; //~ ERROR union expressions should have exactly one field + let u = U { a: 0 }; // OK + let u = U { a: 0, b: 1 }; //~ ERROR union expressions should have exactly one field + let u = U { a: 0, b: 1, c: 2 }; //~ ERROR union expressions should have exactly one field + //~^ ERROR union `U` has no field named `c` + let u = U { ..u }; //~ ERROR union expressions should have exactly one field + //~^ ERROR functional record update syntax requires a struct + + let U {} = u; //~ ERROR union patterns should have exactly one field + let U { a } = u; // OK + let U { a, b } = u; //~ ERROR union patterns should have exactly one field + let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field + //~^ ERROR union `U` does not have a field named `c` + let U { .. } = u; //~ ERROR union patterns should have exactly one field + //~^ ERROR `..` cannot be used in union patterns + let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns +} diff --git a/tests/ui/union/union-fields-2.thirunsafeck.stderr b/tests/ui/union/union-fields-2.thirunsafeck.stderr new file mode 100644 index 000000000..90ad16402 --- /dev/null +++ b/tests/ui/union/union-fields-2.thirunsafeck.stderr @@ -0,0 +1,84 @@ +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:10:13 + | +LL | let u = U {}; + | ^ + +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:12:13 + | +LL | let u = U { a: 0, b: 1 }; + | ^ + +error[E0560]: union `U` has no field named `c` + --> $DIR/union-fields-2.rs:13:29 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ `U` does not have this field + | + = note: available fields are: `a`, `b` + +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:13:13 + | +LL | let u = U { a: 0, b: 1, c: 2 }; + | ^ + +error[E0784]: union expressions should have exactly one field + --> $DIR/union-fields-2.rs:15:13 + | +LL | let u = U { ..u }; + | ^ + +error[E0436]: functional record update syntax requires a struct + --> $DIR/union-fields-2.rs:15:19 + | +LL | let u = U { ..u }; + | ^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:18:9 + | +LL | let U {} = u; + | ^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:20:9 + | +LL | let U { a, b } = u; + | ^^^^^^^^^^ + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:21:9 + | +LL | let U { a, b, c } = u; + | ^^^^^^^^^^^^^ + +error[E0026]: union `U` does not have a field named `c` + --> $DIR/union-fields-2.rs:21:19 + | +LL | let U { a, b, c } = u; + | ^ union `U` does not have this field + +error: union patterns should have exactly one field + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:23:9 + | +LL | let U { .. } = u; + | ^^^^^^^^ + +error: `..` cannot be used in union patterns + --> $DIR/union-fields-2.rs:25:9 + | +LL | let U { a, .. } = u; + | ^^^^^^^^^^^ + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0026, E0436, E0560, E0784. +For more information about an error, try `rustc --explain E0026`. diff --git a/tests/ui/union/union-generic-rpass.rs b/tests/ui/union/union-generic-rpass.rs new file mode 100644 index 000000000..25f1f5050 --- /dev/null +++ b/tests/ui/union/union-generic-rpass.rs @@ -0,0 +1,34 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] + +use std::mem::ManuallyDrop; + +union MaybeItem { + elem: ManuallyDrop, + none: (), +} + +union U where A: Copy, B: Copy { + a: A, + b: B, +} + +unsafe fn union_transmute(a: A) -> B where A: Copy, B: Copy { + U { a }.b +} + +fn main() { + unsafe { + let b = union_transmute::<(u8, u8), u16>((1, 1)); + assert_eq!(b, (1 << 8) + 1); + + let v: Vec = vec![1, 2, 3]; + let mut i = v.iter(); + i.next(); + let mi = MaybeItem::> { elem: ManuallyDrop::new(i.next().unwrap()) }; + assert_eq!(**mi.elem, 2); + } +} diff --git a/tests/ui/union/union-generic.mirunsafeck.stderr b/tests/ui/union/union-generic.mirunsafeck.stderr new file mode 100644 index 000000000..037022a91 --- /dev/null +++ b/tests/ui/union/union-generic.mirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:11:13 + | +LL | let u = U { a: Rc::new(0u32) }; + | ^ the trait `Copy` is not implemented for `Rc` + | +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 + | +LL | union U { + | ^^^^ required by this bound in `U` + +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:13:17 + | +LL | let u = U::> { a: Default::default() }; + | ^^^^^^^ the trait `Copy` is not implemented for `Rc` + | +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 + | +LL | union U { + | ^^^^ required by this bound in `U` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-generic.rs b/tests/ui/union/union-generic.rs new file mode 100644 index 000000000..3d68ecb87 --- /dev/null +++ b/tests/ui/union/union-generic.rs @@ -0,0 +1,15 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +use std::rc::Rc; + +union U { + a: T +} + +fn main() { + let u = U { a: Rc::new(0u32) }; + //~^ ERROR the trait bound `Rc: Copy` is not satisfied + let u = U::> { a: Default::default() }; + //~^ ERROR the trait bound `Rc: Copy` is not satisfied +} diff --git a/tests/ui/union/union-generic.thirunsafeck.stderr b/tests/ui/union/union-generic.thirunsafeck.stderr new file mode 100644 index 000000000..037022a91 --- /dev/null +++ b/tests/ui/union/union-generic.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:11:13 + | +LL | let u = U { a: Rc::new(0u32) }; + | ^ the trait `Copy` is not implemented for `Rc` + | +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 + | +LL | union U { + | ^^^^ required by this bound in `U` + +error[E0277]: the trait bound `Rc: Copy` is not satisfied + --> $DIR/union-generic.rs:13:17 + | +LL | let u = U::> { a: Default::default() }; + | ^^^^^^^ the trait `Copy` is not implemented for `Rc` + | +note: required by a bound in `U` + --> $DIR/union-generic.rs:6:12 + | +LL | union U { + | ^^^^ required by this bound in `U` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-inherent-method.rs b/tests/ui/union/union-inherent-method.rs new file mode 100644 index 000000000..b0fd22da7 --- /dev/null +++ b/tests/ui/union/union-inherent-method.rs @@ -0,0 +1,16 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + a: u8, +} + +impl U { + fn method(&self) -> u8 { unsafe { self.a } } +} + +fn main() { + let u = U { a: 10 }; + assert_eq!(u.method(), 10); +} diff --git a/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr b/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr new file mode 100644 index 000000000..6e21584c3 --- /dev/null +++ b/tests/ui/union/union-lint-dead-code.mirunsafeck.stderr @@ -0,0 +1,17 @@ +error: field `b` is never read + --> $DIR/union-lint-dead-code.rs:8:5 + | +LL | union Foo { + | --- field in this union +LL | x: usize, +LL | b: bool, + | ^ + | +note: the lint level is defined here + --> $DIR/union-lint-dead-code.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/union/union-lint-dead-code.rs b/tests/ui/union/union-lint-dead-code.rs new file mode 100644 index 000000000..65aaf0a1d --- /dev/null +++ b/tests/ui/union/union-lint-dead-code.rs @@ -0,0 +1,18 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![deny(dead_code)] + +union Foo { + x: usize, + b: bool, //~ ERROR: field `b` is never read + _unused: u16, +} + +fn field_read(f: Foo) -> usize { + unsafe { f.x } +} + +fn main() { + let _ = field_read(Foo { x: 2 }); +} diff --git a/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr b/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr new file mode 100644 index 000000000..6e21584c3 --- /dev/null +++ b/tests/ui/union/union-lint-dead-code.thirunsafeck.stderr @@ -0,0 +1,17 @@ +error: field `b` is never read + --> $DIR/union-lint-dead-code.rs:8:5 + | +LL | union Foo { + | --- field in this union +LL | x: usize, +LL | b: bool, + | ^ + | +note: the lint level is defined here + --> $DIR/union-lint-dead-code.rs:4:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/union/union-macro.rs b/tests/ui/union/union-macro.rs new file mode 100644 index 000000000..7fd9d8221 --- /dev/null +++ b/tests/ui/union/union-macro.rs @@ -0,0 +1,27 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(unused_variables)] + +macro_rules! duplicate { + ($i: item) => { + mod m1 { + $i + } + mod m2 { + $i + } + } +} + +duplicate! { + pub union U { + pub a: u8 + } +} + +fn main() { + let u1 = m1::U { a: 0 }; + let u2 = m2::U { a: 0 }; +} diff --git a/tests/ui/union/union-manuallydrop-rpass.rs b/tests/ui/union/union-manuallydrop-rpass.rs new file mode 100644 index 000000000..826bdf07c --- /dev/null +++ b/tests/ui/union/union-manuallydrop-rpass.rs @@ -0,0 +1,44 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] + +use std::mem::needs_drop; +use std::mem::ManuallyDrop; + +struct NeedDrop; + +impl Drop for NeedDrop { + fn drop(&mut self) {} +} + +union UnionOk1 { + empty: (), + value: ManuallyDrop, +} + +union UnionOk2 { + value: ManuallyDrop, +} + +#[allow(dead_code)] +union UnionOk3 { + empty: (), + value: T, +} + +trait Foo { } + +trait ImpliesCopy : Copy { } + +#[allow(dead_code)] +union UnionOk4 { + value: T, +} + +fn main() { + // NeedDrop should not make needs_drop true + assert!(!needs_drop::>()); + assert!(!needs_drop::>()); +} diff --git a/tests/ui/union/union-move.mirunsafeck.stderr b/tests/ui/union/union-move.mirunsafeck.stderr new file mode 100644 index 000000000..6381ae874 --- /dev/null +++ b/tests/ui/union/union-move.mirunsafeck.stderr @@ -0,0 +1,51 @@ +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:29:18 + | +LL | fn test1(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f1_nocopy); + | ----------- value moved here +LL | move_out(x.f2_nocopy); + | ^^^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function + +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:45:18 + | +LL | fn test3(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f2_nocopy); + | ----------- value moved here +LL | move_out(x.f3_copy); + | ^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function + +error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait + --> $DIR/union-move.rs:52:18 + | +LL | move_out(x.f1_nocopy); + | ^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `x.f1_nocopy` has type `ManuallyDrop>`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0509. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/union/union-move.rs b/tests/ui/union/union-move.rs new file mode 100644 index 000000000..b8b1ac804 --- /dev/null +++ b/tests/ui/union/union-move.rs @@ -0,0 +1,56 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +//! Test the behavior of moving out of non-`Copy` union fields. +//! Avoid types that `Drop`, we want to focus on moving. + +use std::cell::RefCell; +use std::mem::ManuallyDrop; + +fn move_out(x: T) {} + +union U1 { + f1_nocopy: ManuallyDrop>, + f2_nocopy: ManuallyDrop>, + f3_copy: i32, +} + +union U2 { + f1_nocopy: ManuallyDrop>, +} +impl Drop for U2 { + fn drop(&mut self) {} +} + +fn test1(x: U1) { + // Moving out of a nocopy field prevents accessing other nocopy field. + unsafe { + move_out(x.f1_nocopy); + move_out(x.f2_nocopy); //~ ERROR use of moved value: `x` + } +} + +fn test2(x: U1) { + // "Moving" out of copy field doesn't prevent later field accesses. + unsafe { + move_out(x.f3_copy); + move_out(x.f2_nocopy); // no error + } +} + +fn test3(x: U1) { + // Moving out of a nocopy field prevents accessing other copy field. + unsafe { + move_out(x.f2_nocopy); + move_out(x.f3_copy); //~ ERROR use of moved value: `x` + } +} + +fn test4(x: U2) { + // Cannot move out of union that implements `Drop`. + unsafe { + move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop` + } +} + +fn main() {} diff --git a/tests/ui/union/union-move.thirunsafeck.stderr b/tests/ui/union/union-move.thirunsafeck.stderr new file mode 100644 index 000000000..6381ae874 --- /dev/null +++ b/tests/ui/union/union-move.thirunsafeck.stderr @@ -0,0 +1,51 @@ +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:29:18 + | +LL | fn test1(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f1_nocopy); + | ----------- value moved here +LL | move_out(x.f2_nocopy); + | ^^^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function + +error[E0382]: use of moved value: `x` + --> $DIR/union-move.rs:45:18 + | +LL | fn test3(x: U1) { + | - move occurs because `x` has type `U1`, which does not implement the `Copy` trait +... +LL | move_out(x.f2_nocopy); + | ----------- value moved here +LL | move_out(x.f3_copy); + | ^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function + +error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait + --> $DIR/union-move.rs:52:18 + | +LL | move_out(x.f1_nocopy); + | ^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because `x.f1_nocopy` has type `ManuallyDrop>`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0382, E0509. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/union/union-nodrop.rs b/tests/ui/union/union-nodrop.rs new file mode 100644 index 000000000..6e6b105a7 --- /dev/null +++ b/tests/ui/union/union-nodrop.rs @@ -0,0 +1,62 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] + +use std::mem::needs_drop; +use std::mem::ManuallyDrop; + +struct NeedDrop; + +impl Drop for NeedDrop { + fn drop(&mut self) {} +} + +// Constant expressios allow `NoDrop` to go out of scope, +// unlike a value of the interior type implementing `Drop`. +static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; + +const Y: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; + +const fn _f() { (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1 } + +// A union that scrubs the drop glue from its inner type +union NoDrop { inner: ManuallyDrop } + +// Copy currently can't be implemented on drop-containing unions, +// this may change later +// https://github.com/rust-lang/rust/pull/38934#issuecomment-271219289 + +// // We should be able to implement Copy for NoDrop +// impl Copy for NoDrop {} +// impl Clone for NoDrop {fn clone(&self) -> Self { *self }} + +// // We should be able to implement Copy for things using NoDrop +// #[derive(Copy, Clone)] +struct Foo { + x: NoDrop> +} + +struct Baz { + x: NoDrop>, + y: Box, +} + +union ActuallyDrop { inner: ManuallyDrop } + +impl Drop for ActuallyDrop { + fn drop(&mut self) {} +} + +fn main() { + // NoDrop should not make needs_drop true + assert!(!needs_drop::()); + assert!(!needs_drop::>()); + assert!(!needs_drop::>>()); + // presence of other drop types should still work + assert!(needs_drop::()); + // drop impl on union itself should work + assert!(needs_drop::>()); + assert!(needs_drop::>>()); +} diff --git a/tests/ui/union/union-nonrepresentable.rs b/tests/ui/union/union-nonrepresentable.rs new file mode 100644 index 000000000..4bdf7c687 --- /dev/null +++ b/tests/ui/union/union-nonrepresentable.rs @@ -0,0 +1,6 @@ +union U { //~ ERROR recursive type `U` has infinite size + a: u8, + b: std::mem::ManuallyDrop, +} + +fn main() {} diff --git a/tests/ui/union/union-nonrepresentable.stderr b/tests/ui/union/union-nonrepresentable.stderr new file mode 100644 index 000000000..c266d2e9e --- /dev/null +++ b/tests/ui/union/union-nonrepresentable.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `U` has infinite size + --> $DIR/union-nonrepresentable.rs:1:1 + | +LL | union U { + | ^^^^^^^ +LL | a: u8, +LL | b: std::mem::ManuallyDrop, + | - recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | b: std::mem::ManuallyDrop>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/union/union-nonzero.rs b/tests/ui/union/union-nonzero.rs new file mode 100644 index 000000000..3f4f7ea1c --- /dev/null +++ b/tests/ui/union/union-nonzero.rs @@ -0,0 +1,54 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] + +// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations. +// +// For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no +// bit-value that an `Option` could reuse as `None`; this test makes sure that isn't done. +// +// Secondly, this tests the status quo (not a guarantee; subject to change!) to not apply such +// optimizations to types containing unions even if they're theoretically possible. (discussion: +// https://github.com/rust-lang/rust/issues/36394) +// +// Notably this nails down part of the behavior that `MaybeUninit` assumes: that an +// `Option>` does not take advantage of non-zero optimization, and thus is a safe +// construct. + +use std::mem::{size_of, transmute}; + +union U1 { + a: A, +} + +union U2 { + a: A, + b: B, +} + +// Option uses a value other than 0 and 1 as None +#[derive(Clone,Copy)] +enum E { + A = 0, + B = 1, +} + +fn main() { + // Unions do not participate in niche-filling/non-zero optimization... + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + + // ...even when theoretically possible: + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + + // The unused bits of the () variant can have any value. + let zeroed: U2<&u8, ()> = unsafe { transmute(std::ptr::null::()) }; + + if let None = Some(zeroed) { + panic!() + } +} diff --git a/tests/ui/union/union-overwrite.rs b/tests/ui/union/union-overwrite.rs new file mode 100644 index 000000000..0eea14d9d --- /dev/null +++ b/tests/ui/union/union-overwrite.rs @@ -0,0 +1,80 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#[repr(C)] +#[derive(Copy, Clone)] +struct Pair(T, U); +#[repr(C)] +#[derive(Copy, Clone)] +struct Triple(T, T, T); + +#[repr(C)] +union U +where + A: Copy, B: Copy +{ + a: Pair, + b: B, +} + +#[repr(C)] +union W +where + A: Copy, B: Copy +{ + a: A, + b: B, +} + +#[cfg(target_endian = "little")] +unsafe fn check() { + let mut u = U:: { b: 0xDE_DE }; + u.a.0 = 0xBE; + assert_eq!(u.b, 0xDE_BE); + + let mut u = U:: { b: 0xDEAD_DEAD }; + u.a.0 = 0xBEEF; + assert_eq!(u.b, 0xDEAD_BEEF); + + let mut u = U:: { b: 0xDEADBEEF_DEADBEEF }; + u.a.0 = 0xBAADF00D; + assert_eq!(u.b, 0xDEADBEEF_BAADF00D); + + let mut w = W::, u8>, u32> { b: 0xDEAD_DEAD }; + w.a.0 = Triple(0, 0, 0); + assert_eq!(w.b, 0xDE00_0000); + + let mut w = W::>, u32> { b: 0xDEAD_DEAD }; + w.a.1 = Triple(0, 0, 0); + assert_eq!(w.b, 0x0000_00AD); +} + +#[cfg(target_endian = "big")] +unsafe fn check() { + let mut u = U:: { b: 0xDE_DE }; + u.a.0 = 0xBE; + assert_eq!(u.b, 0xBE_DE); + + let mut u = U:: { b: 0xDEAD_DEAD }; + u.a.0 = 0xBEEF; + assert_eq!(u.b, 0xBEEF_DEAD); + + let mut u = U:: { b: 0xDEADBEEF_DEADBEEF }; + u.a.0 = 0xBAADF00D; + assert_eq!(u.b, 0xBAADF00D_DEADBEEF); + + let mut w = W::, u8>, u32> { b: 0xDEAD_DEAD }; + w.a.0 = Triple(0, 0, 0); + assert_eq!(w.b, 0x0000_00AD); + + let mut w = W::>, u32> { b: 0xDEAD_DEAD }; + w.a.1 = Triple(0, 0, 0); + assert_eq!(w.b, 0xDE00_0000); +} + +fn main() { + unsafe { + check(); + } +} diff --git a/tests/ui/union/union-packed.rs b/tests/ui/union/union-packed.rs new file mode 100644 index 000000000..9c6398bf5 --- /dev/null +++ b/tests/ui/union/union-packed.rs @@ -0,0 +1,173 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] +#![allow(non_snake_case)] + +use std::mem::{size_of, size_of_val, align_of, align_of_val}; + +struct S { + a: u16, + b: [u8; 3], +} + +#[repr(packed)] +struct Sp1 { + a: u16, + b: [u8; 3], +} + +#[repr(packed(2))] +struct Sp2 { + a: u16, + b: [u8; 3], +} + +union U { + a: u16, + b: [u8; 3], +} + +#[repr(packed)] +union Up1 { + a: u16, + b: [u8; 3], +} + +#[repr(packed(2))] +union Up2 { + a: u16, + b: [u8; 3], +} + +#[repr(C, packed(4))] +union Up4c { + a: u16, + b: [u8; 3], +} + +const CS: S = S { a: 0, b: [0, 0, 0] }; +const CSP1: Sp1 = Sp1 { a: 0, b: [0, 0, 0] }; +const CSP2: Sp2 = Sp2 { a: 0, b: [0, 0, 0] }; +const CU: U = U { b: [0, 0, 0] }; +const CUP1: Up1 = Up1 { b: [0, 0, 0] }; +const CUP2: Up2 = Up2 { b: [0, 0, 0] }; +const CUP4C: Up4c = Up4c { b: [0, 0, 0] }; + +fn main() { + let s = S { a: 0, b: [0, 0, 0] }; + assert_eq!(size_of::(), 6); + assert_eq!(size_of_val(&s), 6); + assert_eq!(size_of_val(&CS), 6); + assert_eq!(align_of::(), 2); + assert_eq!(align_of_val(&s), 2); + assert_eq!(align_of_val(&CS), 2); + + let sp1 = Sp1 { a: 0, b: [0, 0, 0] }; + assert_eq!(size_of::(), 5); + assert_eq!(size_of_val(&sp1), 5); + assert_eq!(size_of_val(&CSP1), 5); + assert_eq!(align_of::(), 1); + assert_eq!(align_of_val(&sp1), 1); + assert_eq!(align_of_val(&CSP1), 1); + + let sp2 = Sp2 { a: 0, b: [0, 0, 0] }; + assert_eq!(size_of::(), 6); + assert_eq!(size_of_val(&sp2), 6); + assert_eq!(size_of_val(&CSP2), 6); + assert_eq!(align_of::(), 2); + assert_eq!(align_of_val(&sp2), 2); + assert_eq!(align_of_val(&CSP2), 2); + + let u = U { b: [0, 0, 0] }; + assert_eq!(size_of::(), 4); + assert_eq!(size_of_val(&u), 4); + assert_eq!(size_of_val(&CU), 4); + assert_eq!(align_of::(), 2); + assert_eq!(align_of_val(&u), 2); + assert_eq!(align_of_val(&CU), 2); + + let Up1 = Up1 { b: [0, 0, 0] }; + assert_eq!(size_of::(), 3); + assert_eq!(size_of_val(&Up1), 3); + assert_eq!(size_of_val(&CUP1), 3); + assert_eq!(align_of::(), 1); + assert_eq!(align_of_val(&Up1), 1); + assert_eq!(align_of_val(&CUP1), 1); + + let up2 = Up2 { b: [0, 0, 0] }; + assert_eq!(size_of::(), 4); + assert_eq!(size_of_val(&up2), 4); + assert_eq!(size_of_val(&CUP2), 4); + assert_eq!(align_of::(), 2); + assert_eq!(align_of_val(&up2), 2); + assert_eq!(align_of_val(&CUP2), 2); + + let up4c = Up4c { b: [0, 0, 0] }; + assert_eq!(size_of::(), 4); + assert_eq!(size_of_val(&up4c), 4); + assert_eq!(size_of_val(&CUP4C), 4); + assert_eq!(align_of::(), 2); + assert_eq!(align_of_val(&up4c), 2); + assert_eq!(align_of_val(&CUP4C), 2); + + hybrid::check_hybrid(); +} + +mod hybrid { + use std::mem::{size_of, align_of}; + + #[repr(packed)] + #[derive(Copy, Clone)] + struct S1 { + a: u16, + b: u8, + } + + #[repr(packed)] + union U { + s: S1, + c: u16, + } + + #[repr(packed)] + struct S2 { + d: u8, + u: U, + } + + #[repr(C, packed(2))] + struct S1C { + a: u16, + b: u8, + } + + #[repr(C, packed(2))] + union UC { + s: S1, + c: u16, + } + + #[repr(C, packed(2))] + struct S2C { + d: u8, + u: UC, + } + + pub fn check_hybrid() { + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 3); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 3); + assert_eq!(align_of::(), 1); + assert_eq!(size_of::(), 4); + + assert_eq!(align_of::(), 2); + assert_eq!(size_of::(), 4); + assert_eq!(align_of::(), 2); + assert_eq!(size_of::(), 4); + assert_eq!(align_of::(), 2); + assert_eq!(size_of::(), 6); + } +} diff --git a/tests/ui/union/union-pat-refutability.rs b/tests/ui/union/union-pat-refutability.rs new file mode 100644 index 000000000..d628a200a --- /dev/null +++ b/tests/ui/union/union-pat-refutability.rs @@ -0,0 +1,57 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] +#![allow(illegal_floating_point_literal_pattern)] + +#[repr(u32)] +enum Tag { I, F } + +#[repr(C)] +union U { + i: i32, + f: f32, +} + +#[repr(C)] +struct Value { + tag: Tag, + u: U, +} + +fn is_zero(v: Value) -> bool { + unsafe { + match v { + Value { tag: Tag::I, u: U { i: 0 } } => true, + Value { tag: Tag::F, u: U { f: 0.0 } } => true, + _ => false, + } + } +} + +union W { + a: u8, + b: u8, +} + +fn refut(w: W) { + unsafe { + match w { + W { a: 10 } => { + panic!(); + } + W { b } => { + assert_eq!(b, 11); + } + } + } +} + +fn main() { + let v = Value { tag: Tag::I, u: U { i: 1 } }; + assert_eq!(is_zero(v), false); + + let w = W { a: 11 }; + refut(w); +} diff --git a/tests/ui/union/union-repr-c.rs b/tests/ui/union/union-repr-c.rs new file mode 100644 index 000000000..1367835e6 --- /dev/null +++ b/tests/ui/union/union-repr-c.rs @@ -0,0 +1,18 @@ +#![allow(unused)] +#![deny(improper_ctypes)] + +#[repr(C)] +union U { + a: u8, +} + +union W { + a: u8, +} + +extern "C" { + static FOREIGN1: U; // OK + static FOREIGN2: W; //~ ERROR `extern` block uses type `W` +} + +fn main() {} diff --git a/tests/ui/union/union-repr-c.stderr b/tests/ui/union/union-repr-c.stderr new file mode 100644 index 000000000..49124eee5 --- /dev/null +++ b/tests/ui/union/union-repr-c.stderr @@ -0,0 +1,21 @@ +error: `extern` block uses type `W`, which is not FFI-safe + --> $DIR/union-repr-c.rs:15:22 + | +LL | static FOREIGN2: W; + | ^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union + = note: this union has unspecified layout +note: the type is defined here + --> $DIR/union-repr-c.rs:9:1 + | +LL | union W { + | ^^^^^^^ +note: the lint level is defined here + --> $DIR/union-repr-c.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/union/union-sized-field.rs b/tests/ui/union/union-sized-field.rs new file mode 100644 index 000000000..cb852eff0 --- /dev/null +++ b/tests/ui/union/union-sized-field.rs @@ -0,0 +1,19 @@ +use std::mem::ManuallyDrop; + +union Foo { + value: ManuallyDrop, + //~^ ERROR the size for values of type +} + +struct Foo2 { + value: ManuallyDrop, + //~^ ERROR the size for values of type + t: u32, +} + +enum Foo3 { + Value(ManuallyDrop), + //~^ ERROR the size for values of type +} + +fn main() {} diff --git a/tests/ui/union/union-sized-field.stderr b/tests/ui/union/union-sized-field.stderr new file mode 100644 index 000000000..771e8f261 --- /dev/null +++ b/tests/ui/union/union-sized-field.stderr @@ -0,0 +1,78 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/union-sized-field.rs:4:12 + | +LL | union Foo { + | - this type parameter needs to be `std::marker::Sized` +LL | value: ManuallyDrop, + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: required because it appears within the type `ManuallyDrop` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - union Foo { +LL + union Foo { + | +help: borrowed types always have a statically known size + | +LL | value: &ManuallyDrop, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | value: Box>, + | ++++ + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/union-sized-field.rs:9:12 + | +LL | struct Foo2 { + | - this type parameter needs to be `std::marker::Sized` +LL | value: ManuallyDrop, + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: required because it appears within the type `ManuallyDrop` + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Foo2 { +LL + struct Foo2 { + | +help: borrowed types always have a statically known size + | +LL | value: &ManuallyDrop, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | value: Box>, + | ++++ + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/union-sized-field.rs:15:11 + | +LL | enum Foo3 { + | - this type parameter needs to be `std::marker::Sized` +LL | Value(ManuallyDrop), + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: required because it appears within the type `ManuallyDrop` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum Foo3 { +LL + enum Foo3 { + | +help: borrowed types always have a statically known size + | +LL | Value(&ManuallyDrop), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | Value(Box>), + | ++++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-suggest-field.mirunsafeck.stderr b/tests/ui/union/union-suggest-field.mirunsafeck.stderr new file mode 100644 index 000000000..58b1f5cb0 --- /dev/null +++ b/tests/ui/union/union-suggest-field.mirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0560]: union `U` has no field named `principle` + --> $DIR/union-suggest-field.rs:13:17 + | +LL | let u = U { principle: 0 }; + | ^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0609]: no field `principial` on type `U` + --> $DIR/union-suggest-field.rs:17:15 + | +LL | let w = u.principial; + | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0615]: attempted to take value of method `calculate` on type `U` + --> $DIR/union-suggest-field.rs:21:15 + | +LL | let y = u.calculate; + | ^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let y = u.calculate(); + | ++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0560, E0609, E0615. +For more information about an error, try `rustc --explain E0560`. diff --git a/tests/ui/union/union-suggest-field.rs b/tests/ui/union/union-suggest-field.rs new file mode 100644 index 000000000..601a22a06 --- /dev/null +++ b/tests/ui/union/union-suggest-field.rs @@ -0,0 +1,24 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + principal: u8, +} + +impl U { + fn calculate(&self) {} +} + +fn main() { + let u = U { principle: 0 }; + //~^ ERROR union `U` has no field named `principle` + //~| HELP a field with a similar name exists + //~| SUGGESTION principal + let w = u.principial; //~ ERROR no field `principial` on type `U` + //~| HELP a field with a similar name exists + //~| SUGGESTION principal + + let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` + //~| HELP use parentheses to call the method + //~| SUGGESTION () +} diff --git a/tests/ui/union/union-suggest-field.thirunsafeck.stderr b/tests/ui/union/union-suggest-field.thirunsafeck.stderr new file mode 100644 index 000000000..58b1f5cb0 --- /dev/null +++ b/tests/ui/union/union-suggest-field.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0560]: union `U` has no field named `principle` + --> $DIR/union-suggest-field.rs:13:17 + | +LL | let u = U { principle: 0 }; + | ^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0609]: no field `principial` on type `U` + --> $DIR/union-suggest-field.rs:17:15 + | +LL | let w = u.principial; + | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + +error[E0615]: attempted to take value of method `calculate` on type `U` + --> $DIR/union-suggest-field.rs:21:15 + | +LL | let y = u.calculate; + | ^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | let y = u.calculate(); + | ++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0560, E0609, E0615. +For more information about an error, try `rustc --explain E0560`. diff --git a/tests/ui/union/union-trait-impl.rs b/tests/ui/union/union-trait-impl.rs new file mode 100644 index 000000000..6134e91f3 --- /dev/null +++ b/tests/ui/union/union-trait-impl.rs @@ -0,0 +1,19 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +use std::fmt; + +union U { + a: u8 +} + +impl fmt::Display for U { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + unsafe { write!(f, "Oh hai {}", self.a) } + } +} + +fn main() { + assert_eq!(U { a: 2 }.to_string(), "Oh hai 2"); +} diff --git a/tests/ui/union/union-transmute.rs b/tests/ui/union/union-transmute.rs new file mode 100644 index 000000000..1a3b32d55 --- /dev/null +++ b/tests/ui/union/union-transmute.rs @@ -0,0 +1,27 @@ +// run-pass +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + a: (u8, u8), + b: u16, +} + +union W { + a: u32, + b: f32, +} + +fn main() { + unsafe { + let mut u = U { a: (1, 1) }; + assert_eq!(u.b, (1 << 8) + 1); + u.b = (2 << 8) + 2; + assert_eq!(u.a, (2, 2)); + + let mut w = W { a: 0b0_11111111_00000000000000000000000 }; + assert_eq!(w.b, f32::INFINITY); + w.b = f32::NEG_INFINITY; + assert_eq!(w.a, 0b1_11111111_00000000000000000000000); + } +} diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr new file mode 100644 index 000000000..544213dbc --- /dev/null +++ b/tests/ui/union/union-unsafe.mir.stderr @@ -0,0 +1,75 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:33:5 + | +LL | *(u.p) = 13; + | ^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:46:6 + | +LL | *u3.a = T::default(); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:52:6 + | +LL | *u3.a = T::default(); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:60:13 + | +LL | let a = u1.a; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:63:14 + | +LL | let U1 { a } = u1; + | ^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:64:12 + | +LL | if let U1 { a: 12 } = u1 {} + | ^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:69:6 + | +LL | *u2.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:73:6 + | +LL | *u3.a = 1; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:77:6 + | +LL | *u3.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs new file mode 100644 index 000000000..5e1837a90 --- /dev/null +++ b/tests/ui/union/union-unsafe.rs @@ -0,0 +1,78 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +use std::mem::ManuallyDrop; +use std::cell::RefCell; + +union U1 { + a: u8 +} + +union U2 { + a: ManuallyDrop +} + +union U3 { + a: ManuallyDrop +} + +union U4 { + a: T +} + +union URef { + p: &'static mut i32, +} + +union URefCell { // field that does not drop but is not `Copy`, either + a: (ManuallyDrop>, i32), +} + +fn deref_union_field(mut u: URef) { + // Not an assignment but an access to the union field! + *(u.p) = 13; //~ ERROR access to union field is unsafe +} + +fn assign_noncopy_union_field(mut u: URefCell) { + // FIXME(thir-unsafeck) + u.a = (ManuallyDrop::new(RefCell::new(0)), 1); // OK (assignment does not drop) + u.a.0 = ManuallyDrop::new(RefCell::new(0)); // OK (assignment does not drop) + u.a.1 = 1; // OK +} + +fn generic_noncopy() { + let mut u3 = U3 { a: ManuallyDrop::new(T::default()) }; + u3.a = ManuallyDrop::new(T::default()); // OK (assignment does not drop) + *u3.a = T::default(); //~ ERROR access to union field is unsafe +} + +fn generic_copy() { + let mut u3 = U3 { a: ManuallyDrop::new(T::default()) }; + u3.a = ManuallyDrop::new(T::default()); // OK + *u3.a = T::default(); //~ ERROR access to union field is unsafe + + let mut u4 = U4 { a: T::default() }; + u4.a = T::default(); // OK +} + +fn main() { + let mut u1 = U1 { a: 10 }; // OK + let a = u1.a; //~ ERROR access to union field is unsafe + u1.a = 11; // OK + + let U1 { a } = u1; //~ ERROR access to union field is unsafe + if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe + // let U1 { .. } = u1; // OK + + let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK + u2.a = ManuallyDrop::new(String::from("new")); // OK (assignment does not drop) + *u2.a = String::from("new"); //~ ERROR access to union field is unsafe + + let mut u3 = U3 { a: ManuallyDrop::new(0) }; // OK + u3.a = ManuallyDrop::new(1); // OK + *u3.a = 1; //~ ERROR access to union field is unsafe + + let mut u3 = U3 { a: ManuallyDrop::new(String::from("old")) }; // OK + u3.a = ManuallyDrop::new(String::from("new")); // OK (assignment does not drop) + *u3.a = String::from("new"); //~ ERROR access to union field is unsafe +} diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr new file mode 100644 index 000000000..f959fe5bd --- /dev/null +++ b/tests/ui/union/union-unsafe.thir.stderr @@ -0,0 +1,75 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:33:6 + | +LL | *(u.p) = 13; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:46:6 + | +LL | *u3.a = T::default(); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:52:6 + | +LL | *u3.a = T::default(); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:60:13 + | +LL | let a = u1.a; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:63:14 + | +LL | let U1 { a } = u1; + | ^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:64:8 + | +LL | if let U1 { a: 12 } = u1 {} + | ^^^^^^^^^^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:69:6 + | +LL | *u2.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:73:6 + | +LL | *u3.a = 1; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:77:6 + | +LL | *u3.a = String::from("new"); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/union/union-unsized.mirunsafeck.stderr b/tests/ui/union/union-unsized.mirunsafeck.stderr new file mode 100644 index 000000000..59ab835fb --- /dev/null +++ b/tests/ui/union/union-unsized.mirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:5:8 + | +LL | a: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | a: &str, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | a: Box, + | ++++ + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:13:8 + | +LL | b: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | b: &str, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box, + | ++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-unsized.rs b/tests/ui/union/union-unsized.rs new file mode 100644 index 000000000..8e897d7d3 --- /dev/null +++ b/tests/ui/union/union-unsized.rs @@ -0,0 +1,17 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +union U { + a: str, + //~^ ERROR the size for values of type + + b: u8, +} + +union W { + a: u8, + b: str, + //~^ ERROR the size for values of type +} + +fn main() {} diff --git a/tests/ui/union/union-unsized.thirunsafeck.stderr b/tests/ui/union/union-unsized.thirunsafeck.stderr new file mode 100644 index 000000000..59ab835fb --- /dev/null +++ b/tests/ui/union/union-unsized.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:5:8 + | +LL | a: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | a: &str, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | a: Box, + | ++++ + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/union-unsized.rs:13:8 + | +LL | b: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | b: &str, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box, + | ++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr b/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr new file mode 100644 index 000000000..93fe996d2 --- /dev/null +++ b/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/union-with-drop-fields.rs:11:5 + | +LL | a: String, + | ^^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/union-with-drop-fields.rs:19:5 + | +LL | a: S, + | ^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/union-with-drop-fields.rs:24:5 + | +LL | a: T, + | ^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0740`. diff --git a/tests/ui/union/union-with-drop-fields.rs b/tests/ui/union/union-with-drop-fields.rs new file mode 100644 index 000000000..a7a8b69e7 --- /dev/null +++ b/tests/ui/union/union-with-drop-fields.rs @@ -0,0 +1,31 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![allow(dead_code)] + +union U { + a: u8, // OK +} + +union W { + a: String, //~ ERROR unions cannot contain fields that may need dropping + b: String, // OK, only one field is reported +} + +struct S(String); + +// `S` doesn't implement `Drop` trait, but still has non-trivial destructor +union Y { + a: S, //~ ERROR unions cannot contain fields that may need dropping +} + +// We don't know if `T` is trivially-destructable or not until trans +union J { + a: T, //~ ERROR unions cannot contain fields that may need dropping +} + +union H { + a: T, // OK, `T` is `Copy`, no destructor +} + +fn main() {} diff --git a/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr b/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr new file mode 100644 index 000000000..93fe996d2 --- /dev/null +++ b/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/union-with-drop-fields.rs:11:5 + | +LL | a: String, + | ^^^^^^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/union-with-drop-fields.rs:19:5 + | +LL | a: S, + | ^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error[E0740]: unions cannot contain fields that may need dropping + --> $DIR/union-with-drop-fields.rs:24:5 + | +LL | a: T, + | ^^^^ + | + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0740`. diff --git a/tests/ui/unique-object-noncopyable.rs b/tests/ui/unique-object-noncopyable.rs new file mode 100644 index 000000000..2c40dfc7a --- /dev/null +++ b/tests/ui/unique-object-noncopyable.rs @@ -0,0 +1,25 @@ +trait Foo { + fn f(&self); +} + +struct Bar { + x: isize, +} + +impl Drop for Bar { + fn drop(&mut self) {} +} + +impl Foo for Bar { + fn f(&self) { + println!("hi"); + } +} + + + +fn main() { + let x = Box::new(Bar { x: 10 }); + let y: Box = x as Box; + let _z = y.clone(); //~ ERROR the method +} diff --git a/tests/ui/unique-object-noncopyable.stderr b/tests/ui/unique-object-noncopyable.stderr new file mode 100644 index 000000000..db42ed9ba --- /dev/null +++ b/tests/ui/unique-object-noncopyable.stderr @@ -0,0 +1,25 @@ +error[E0599]: the method `clone` exists for struct `Box`, but its trait bounds were not satisfied + --> $DIR/unique-object-noncopyable.rs:24:16 + | +LL | trait Foo { + | --------- + | | + | doesn't satisfy `dyn Foo: Clone` + | doesn't satisfy `dyn Foo: Sized` +... +LL | let _z = y.clone(); + | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + | + = note: doesn't satisfy `Box: Clone` + | + = note: the following trait bounds were not satisfied: + `dyn Foo: Sized` + which is required by `Box: Clone` + `dyn Foo: Clone` + which is required by `Box: Clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/unique-pinned-nocopy.rs b/tests/ui/unique-pinned-nocopy.rs new file mode 100644 index 000000000..8edaeef51 --- /dev/null +++ b/tests/ui/unique-pinned-nocopy.rs @@ -0,0 +1,14 @@ +#[derive(Debug)] +struct R { + b: bool, +} + +impl Drop for R { + fn drop(&mut self) {} +} + +fn main() { + let i = Box::new(R { b: true }); + let _j = i.clone(); //~ ERROR the method + println!("{:?}", i); +} diff --git a/tests/ui/unique-pinned-nocopy.stderr b/tests/ui/unique-pinned-nocopy.stderr new file mode 100644 index 000000000..de6611324 --- /dev/null +++ b/tests/ui/unique-pinned-nocopy.stderr @@ -0,0 +1,27 @@ +error[E0599]: the method `clone` exists for struct `Box`, but its trait bounds were not satisfied + --> $DIR/unique-pinned-nocopy.rs:12:16 + | +LL | struct R { + | -------- doesn't satisfy `R: Clone` +... +LL | let _j = i.clone(); + | ^^^^^ method cannot be called on `Box` due to unsatisfied trait bounds + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL + | + = note: doesn't satisfy `Box: Clone` + | + = note: the following trait bounds were not satisfied: + `R: Clone` + which is required by `Box: Clone` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` +help: consider annotating `R` with `#[derive(Clone)]` + | +LL | #[derive(Clone)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/unique/unique-assign-copy.rs b/tests/ui/unique/unique-assign-copy.rs new file mode 100644 index 000000000..b742973ce --- /dev/null +++ b/tests/ui/unique/unique-assign-copy.rs @@ -0,0 +1,12 @@ +// run-pass + +pub fn main() { + let mut i: Box<_> = Box::new(1); + // Should be a copy + let mut j; + j = i.clone(); + *i = 2; + *j = 3; + assert_eq!(*i, 2); + assert_eq!(*j, 3); +} diff --git a/tests/ui/unique/unique-assign-drop.rs b/tests/ui/unique/unique-assign-drop.rs new file mode 100644 index 000000000..e7685b589 --- /dev/null +++ b/tests/ui/unique/unique-assign-drop.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_assignments)] + +pub fn main() { + let i: Box<_> = Box::new(1); + let mut j: Box<_> = Box::new(2); + // Should drop the previous value of j + j = i; + assert_eq!(*j, 1); +} diff --git a/tests/ui/unique/unique-assign-generic.rs b/tests/ui/unique/unique-assign-generic.rs new file mode 100644 index 000000000..d4932d833 --- /dev/null +++ b/tests/ui/unique/unique-assign-generic.rs @@ -0,0 +1,11 @@ +// run-pass + +fn f(t: T) -> T { + let t1 = t; + t1 +} + +pub fn main() { + let t = f::>(Box::new(100)); + assert_eq!(t, Box::new(100)); +} diff --git a/tests/ui/unique/unique-assign.rs b/tests/ui/unique/unique-assign.rs new file mode 100644 index 000000000..d598744f1 --- /dev/null +++ b/tests/ui/unique/unique-assign.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_mut)] + +pub fn main() { + let mut i: Box<_>; + i = Box::new(1); + assert_eq!(*i, 1); +} diff --git a/tests/ui/unique/unique-autoderef-field.rs b/tests/ui/unique/unique-autoderef-field.rs new file mode 100644 index 000000000..64147e11f --- /dev/null +++ b/tests/ui/unique/unique-autoderef-field.rs @@ -0,0 +1,10 @@ +// run-pass + +struct J { j: isize } + +pub fn main() { + let i: Box<_> = Box::new(J { + j: 100 + }); + assert_eq!(i.j, 100); +} diff --git a/tests/ui/unique/unique-autoderef-index.rs b/tests/ui/unique/unique-autoderef-index.rs new file mode 100644 index 000000000..ea6598a7f --- /dev/null +++ b/tests/ui/unique/unique-autoderef-index.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let i: Box<_> = Box::new(vec![100]); + assert_eq!((*i)[0], 100); +} diff --git a/tests/ui/unique/unique-cmp.rs b/tests/ui/unique/unique-cmp.rs new file mode 100644 index 000000000..ee05dd5a3 --- /dev/null +++ b/tests/ui/unique/unique-cmp.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(unused_allocation)] + +pub fn main() { + let i: Box<_> = Box::new(100); + assert_eq!(i, Box::new(100)); + assert!(i < Box::new(101)); + assert!(i <= Box::new(100)); + assert!(i > Box::new(99)); + assert!(i >= Box::new(99)); +} diff --git a/tests/ui/unique/unique-containing-tag.rs b/tests/ui/unique/unique-containing-tag.rs new file mode 100644 index 000000000..6c31ae99b --- /dev/null +++ b/tests/ui/unique/unique-containing-tag.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +pub fn main() { + enum t { t1(isize), t2(isize), } + + let _x: Box<_> = Box::new(t::t1(10)); + + /*alt *x { + t1(a) { + assert_eq!(a, 10); + } + _ { panic!(); } + }*/ + + /*alt x { + Box::new(t1(a) { + assert_eq!(a, 10); + }) + _ { panic!(); } + }*/ +} diff --git a/tests/ui/unique/unique-create.rs b/tests/ui/unique/unique-create.rs new file mode 100644 index 000000000..c566e7962 --- /dev/null +++ b/tests/ui/unique/unique-create.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub fn main() { + let _: Box<_> = Box::new(100); +} + +fn vec() { + vec![0]; +} diff --git a/tests/ui/unique/unique-decl-init-copy.rs b/tests/ui/unique/unique-decl-init-copy.rs new file mode 100644 index 000000000..5b9576fcc --- /dev/null +++ b/tests/ui/unique/unique-decl-init-copy.rs @@ -0,0 +1,11 @@ +// run-pass + +pub fn main() { + let mut i: Box<_> = Box::new(1); + // Should be a copy + let mut j = i.clone(); + *i = 2; + *j = 3; + assert_eq!(*i, 2); + assert_eq!(*j, 3); +} diff --git a/tests/ui/unique/unique-decl-init.rs b/tests/ui/unique/unique-decl-init.rs new file mode 100644 index 000000000..1d70860c7 --- /dev/null +++ b/tests/ui/unique/unique-decl-init.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let i: Box<_> = Box::new(1); + let j = i; + assert_eq!(*j, 1); +} diff --git a/tests/ui/unique/unique-decl-move.rs b/tests/ui/unique/unique-decl-move.rs new file mode 100644 index 000000000..21187510f --- /dev/null +++ b/tests/ui/unique/unique-decl-move.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let i: Box<_> = Box::new(100); + let j = i; + assert_eq!(*j, 100); +} diff --git a/tests/ui/unique/unique-decl.rs b/tests/ui/unique/unique-decl.rs new file mode 100644 index 000000000..84a1b2a5b --- /dev/null +++ b/tests/ui/unique/unique-decl.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] + + +pub fn main() { + let _: Box; +} + +fn f(_i: Box) -> Box { + panic!(); +} diff --git a/tests/ui/unique/unique-deref.rs b/tests/ui/unique/unique-deref.rs new file mode 100644 index 000000000..33a1e9932 --- /dev/null +++ b/tests/ui/unique/unique-deref.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let i: Box<_> = Box::new(100); + assert_eq!(*i, 100); +} diff --git a/tests/ui/unique/unique-destructure.rs b/tests/ui/unique/unique-destructure.rs new file mode 100644 index 000000000..7207ac962 --- /dev/null +++ b/tests/ui/unique/unique-destructure.rs @@ -0,0 +1,9 @@ +// run-pass +#![feature(box_patterns)] + +struct Foo { a: isize, b: isize } + +pub fn main() { + let box Foo{ a, b } = Box::new(Foo { a: 100, b: 200 }); + assert_eq!(a + b, 300); +} diff --git a/tests/ui/unique/unique-drop-complex.rs b/tests/ui/unique/unique-drop-complex.rs new file mode 100644 index 000000000..2324f1e1a --- /dev/null +++ b/tests/ui/unique/unique-drop-complex.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let _x: Box<_> = Box::new(vec![0,0,0,0,0]); +} diff --git a/tests/ui/unique/unique-ffi-symbols.rs b/tests/ui/unique/unique-ffi-symbols.rs new file mode 100644 index 000000000..77b5ead26 --- /dev/null +++ b/tests/ui/unique/unique-ffi-symbols.rs @@ -0,0 +1,16 @@ +// run-pass +// We used to have a __rust_abi shim that resulted in duplicated symbols +// whenever the item path wasn't enough to disambiguate between them. +fn main() { + let a = { + extern "C" fn good() -> i32 { return 0; } + good as extern "C" fn() -> i32 + }; + let b = { + extern "C" fn good() -> i32 { return 5; } + good as extern "C" fn() -> i32 + }; + + assert!(a != b); + assert_eq!((a(), b()), (0, 5)); +} diff --git a/tests/ui/unique/unique-fn-arg-move.rs b/tests/ui/unique/unique-fn-arg-move.rs new file mode 100644 index 000000000..6d42df218 --- /dev/null +++ b/tests/ui/unique/unique-fn-arg-move.rs @@ -0,0 +1,10 @@ +// run-pass + +fn f(i: Box) { + assert_eq!(*i, 100); +} + +pub fn main() { + let i = Box::new(100); + f(i); +} diff --git a/tests/ui/unique/unique-fn-arg-mut.rs b/tests/ui/unique/unique-fn-arg-mut.rs new file mode 100644 index 000000000..01510200b --- /dev/null +++ b/tests/ui/unique/unique-fn-arg-mut.rs @@ -0,0 +1,11 @@ +// run-pass + +fn f(i: &mut Box) { + *i = Box::new(200); +} + +pub fn main() { + let mut i = Box::new(100); + f(&mut i); + assert_eq!(*i, 200); +} diff --git a/tests/ui/unique/unique-fn-arg.rs b/tests/ui/unique/unique-fn-arg.rs new file mode 100644 index 000000000..b4f3bc4b2 --- /dev/null +++ b/tests/ui/unique/unique-fn-arg.rs @@ -0,0 +1,11 @@ +// run-pass + +fn f(i: Box) { + assert_eq!(*i, 100); +} + +pub fn main() { + f(Box::new(100)); + let i = Box::new(100); + f(i); +} diff --git a/tests/ui/unique/unique-fn-ret.rs b/tests/ui/unique/unique-fn-ret.rs new file mode 100644 index 000000000..773a9bce1 --- /dev/null +++ b/tests/ui/unique/unique-fn-ret.rs @@ -0,0 +1,9 @@ +// run-pass + +fn f() -> Box { + Box::new(100) +} + +pub fn main() { + assert_eq!(f(), Box::new(100)); +} diff --git a/tests/ui/unique/unique-generic-assign.rs b/tests/ui/unique/unique-generic-assign.rs new file mode 100644 index 000000000..9c4405aa8 --- /dev/null +++ b/tests/ui/unique/unique-generic-assign.rs @@ -0,0 +1,11 @@ +// run-pass +#![allow(dead_code)] +// Issue #976 + + +// pretty-expanded FIXME #23616 + +fn f(x: Box) { + let _x2 = x; +} +pub fn main() { } diff --git a/tests/ui/unique/unique-in-tag.rs b/tests/ui/unique/unique-in-tag.rs new file mode 100644 index 000000000..6daa06fb1 --- /dev/null +++ b/tests/ui/unique/unique-in-tag.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +fn test1() { + enum bar { u(Box), w(isize), } + + let x = bar::u(Box::new(10)); + assert!(match x { + bar::u(a) => { + println!("{}", a); + *a + } + _ => { 66 } + } == 10); +} + +pub fn main() { + test1(); +} diff --git a/tests/ui/unique/unique-in-vec-copy.rs b/tests/ui/unique/unique-in-vec-copy.rs new file mode 100644 index 000000000..ce52d15ef --- /dev/null +++ b/tests/ui/unique/unique-in-vec-copy.rs @@ -0,0 +1,15 @@ +// run-pass + +pub fn main() { + let mut a: Vec> = vec![Box::new(10)]; + let b = a.clone(); + + assert_eq!(*a[0], 10); + assert_eq!(*b[0], 10); + + // This should only modify the value in a, not b + *a[0] = 20; + + assert_eq!(*a[0], 20); + assert_eq!(*b[0], 10); +} diff --git a/tests/ui/unique/unique-in-vec.rs b/tests/ui/unique/unique-in-vec.rs new file mode 100644 index 000000000..1e8d05e3d --- /dev/null +++ b/tests/ui/unique/unique-in-vec.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let vect : Vec> = vec![Box::new(100)]; + assert_eq!(vect[0], Box::new(100)); +} diff --git a/tests/ui/unique/unique-init.rs b/tests/ui/unique/unique-init.rs new file mode 100644 index 000000000..d19605046 --- /dev/null +++ b/tests/ui/unique/unique-init.rs @@ -0,0 +1,6 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let _i: Box<_> = Box::new(100); +} diff --git a/tests/ui/unique/unique-kinds.rs b/tests/ui/unique/unique-kinds.rs new file mode 100644 index 000000000..f02d0b507 --- /dev/null +++ b/tests/ui/unique/unique-kinds.rs @@ -0,0 +1,64 @@ +// run-pass + +use std::cmp::PartialEq; +use std::fmt::Debug; + +fn sendable() { + + fn f(i: T, j: T) { + assert_eq!(i, j); + } + + fn g(i: T, j: T) { + assert!(i != j); + } + + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(100); + f(i, j); + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(101); + g(i, j); +} + +fn copyable() { + + fn f(i: T, j: T) { + assert_eq!(i, j); + } + + fn g(i: T, j: T) { + assert!(i != j); + } + + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(100); + f(i, j); + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(101); + g(i, j); +} + +fn noncopyable() { + + fn f(i: T, j: T) { + assert_eq!(i, j); + } + + fn g(i: T, j: T) { + assert!(i != j); + } + + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(100); + f(i, j); + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(101); + g(i, j); +} + +pub fn main() { + sendable(); + copyable(); + noncopyable(); +} diff --git a/tests/ui/unique/unique-log.rs b/tests/ui/unique/unique-log.rs new file mode 100644 index 000000000..0715d1662 --- /dev/null +++ b/tests/ui/unique/unique-log.rs @@ -0,0 +1,6 @@ +// run-pass + +pub fn main() { + let i: Box<_> = Box::new(100); + println!("{}", i); +} diff --git a/tests/ui/unique/unique-match-discrim.rs b/tests/ui/unique/unique-match-discrim.rs new file mode 100644 index 000000000..6e6d74322 --- /dev/null +++ b/tests/ui/unique/unique-match-discrim.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +// Issue #961 + +// pretty-expanded FIXME #23616 + +fn altsimple() { + match Box::new(true) { + _ => { } + } +} +pub fn main() { } diff --git a/tests/ui/unique/unique-move-drop.rs b/tests/ui/unique/unique-move-drop.rs new file mode 100644 index 000000000..c0f5d8f90 --- /dev/null +++ b/tests/ui/unique/unique-move-drop.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(unused_variables)] + +pub fn main() { + let i: Box<_> = Box::new(100); + let j: Box<_> = Box::new(200); + let j = i; + assert_eq!(*j, 100); +} diff --git a/tests/ui/unique/unique-move-temp.rs b/tests/ui/unique/unique-move-temp.rs new file mode 100644 index 000000000..103af8e1f --- /dev/null +++ b/tests/ui/unique/unique-move-temp.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(unused_mut)] + +pub fn main() { + let mut i: Box<_>; + i = Box::new(100); + assert_eq!(*i, 100); +} diff --git a/tests/ui/unique/unique-move.rs b/tests/ui/unique/unique-move.rs new file mode 100644 index 000000000..40a2718e4 --- /dev/null +++ b/tests/ui/unique/unique-move.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(unused_mut)] + +pub fn main() { + let i: Box<_> = Box::new(100); + let mut j; + j = i; + assert_eq!(*j, 100); +} diff --git a/tests/ui/unique/unique-mutable.rs b/tests/ui/unique/unique-mutable.rs new file mode 100644 index 000000000..0367c0809 --- /dev/null +++ b/tests/ui/unique/unique-mutable.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let mut i: Box<_> = Box::new(0); + *i = 1; + assert_eq!(*i, 1); +} diff --git a/tests/ui/unique/unique-object-move.rs b/tests/ui/unique/unique-object-move.rs new file mode 100644 index 000000000..bb35a9b2d --- /dev/null +++ b/tests/ui/unique/unique-object-move.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +// Issue #5192 + +// pretty-expanded FIXME #23616 + +pub trait EventLoop { fn foo(&self) {} } + +pub struct UvEventLoop { + uvio: isize +} + +impl EventLoop for UvEventLoop { } + +pub fn main() { + let loop_: Box = Box::new(UvEventLoop { uvio: 0 }) as Box; + let _loop2_ = loop_; +} diff --git a/tests/ui/unique/unique-pat-2.rs b/tests/ui/unique/unique-pat-2.rs new file mode 100644 index 000000000..9c73fd220 --- /dev/null +++ b/tests/ui/unique/unique-pat-2.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] +#![allow(non_shorthand_field_patterns)] + +#![feature(box_patterns)] + +struct Foo {a: isize, b: usize} + +enum bar { u(Box), w(isize), } + +pub fn main() { + let v = match bar::u(Box::new(Foo{ a: 10, b: 40 })) { + bar::u(box Foo{ a: a, b: b }) => { a + (b as isize) } + _ => { 66 } + }; + assert_eq!(v, 50); +} diff --git a/tests/ui/unique/unique-pat-3.rs b/tests/ui/unique/unique-pat-3.rs new file mode 100644 index 000000000..2e81f898d --- /dev/null +++ b/tests/ui/unique/unique-pat-3.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +enum bar { u(Box), w(isize), } + +pub fn main() { + let v = match bar::u(10.into()) { + bar::u(a) => { + println!("{}", a); + *a + } + _ => { 66 } + }; + assert_eq!(v, 10); +} diff --git a/tests/ui/unique/unique-pat.rs b/tests/ui/unique/unique-pat.rs new file mode 100644 index 000000000..c2474d0e7 --- /dev/null +++ b/tests/ui/unique/unique-pat.rs @@ -0,0 +1,14 @@ +// run-pass + +#![feature(box_patterns)] + +fn simple() { + match Box::new(true) { + box true => { } + _ => { panic!(); } + } +} + +pub fn main() { + simple(); +} diff --git a/tests/ui/unique/unique-rec.rs b/tests/ui/unique/unique-rec.rs new file mode 100644 index 000000000..9f8ad9bb0 --- /dev/null +++ b/tests/ui/unique/unique-rec.rs @@ -0,0 +1,9 @@ +// run-pass + +struct X { x: isize } + +pub fn main() { + let x: Box<_> = Box::new(X {x: 1}); + let bar = x; + assert_eq!(bar.x, 1); +} diff --git a/tests/ui/unique/unique-send-2.rs b/tests/ui/unique/unique-send-2.rs new file mode 100644 index 000000000..23ddd2cdc --- /dev/null +++ b/tests/ui/unique/unique-send-2.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn child(tx: &Sender>, i: usize) { + tx.send(Box::new(i)).unwrap(); +} + +pub fn main() { + let (tx, rx) = channel(); + let n = 100; + let mut expected = 0; + let ts = (0..n).map(|i| { + expected += i; + let tx = tx.clone(); + thread::spawn(move|| { + child(&tx, i) + }) + }).collect::>(); + + let mut actual = 0; + for _ in 0..n { + let j = rx.recv().unwrap(); + actual += *j; + } + + assert_eq!(expected, actual); + + for t in ts { t.join(); } +} diff --git a/tests/ui/unique/unique-send.rs b/tests/ui/unique/unique-send.rs new file mode 100644 index 000000000..431cc2be5 --- /dev/null +++ b/tests/ui/unique/unique-send.rs @@ -0,0 +1,10 @@ +// run-pass + +use std::sync::mpsc::channel; + +pub fn main() { + let (tx, rx) = channel::>(); + tx.send(Box::new(100)).unwrap(); + let v = rx.recv().unwrap(); + assert_eq!(v, Box::new(100)); +} diff --git a/tests/ui/unique/unique-swap.rs b/tests/ui/unique/unique-swap.rs new file mode 100644 index 000000000..4f33ff9a8 --- /dev/null +++ b/tests/ui/unique/unique-swap.rs @@ -0,0 +1,11 @@ +// run-pass + +use std::mem::swap; + +pub fn main() { + let mut i: Box<_> = Box::new(100); + let mut j: Box<_> = Box::new(200); + swap(&mut i, &mut j); + assert_eq!(i, Box::new(200)); + assert_eq!(j, Box::new(100)); +} diff --git a/tests/ui/unit.rs b/tests/ui/unit.rs new file mode 100644 index 000000000..4f2dd4194 --- /dev/null +++ b/tests/ui/unit.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(unused_assignments)] +#![allow(unknown_lints)] +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] +#![allow(dead_assignment)] + +fn f(u: ()) { return u; } + +pub fn main() { + let u1: () = (); + let mut u2: () = f(u1); + u2 = (); + return (); +} diff --git a/tests/ui/unknown-language-item.rs b/tests/ui/unknown-language-item.rs new file mode 100644 index 000000000..20ffef714 --- /dev/null +++ b/tests/ui/unknown-language-item.rs @@ -0,0 +1,10 @@ +#![allow(unused)] +#![feature(lang_items)] + +#[lang = "foo"] +fn bar() -> ! { +//~^^ ERROR definition of an unknown language item: `foo` + loop {} +} + +fn main() {} diff --git a/tests/ui/unknown-language-item.stderr b/tests/ui/unknown-language-item.stderr new file mode 100644 index 000000000..c5fe9b8ad --- /dev/null +++ b/tests/ui/unknown-language-item.stderr @@ -0,0 +1,9 @@ +error[E0522]: definition of an unknown language item: `foo` + --> $DIR/unknown-language-item.rs:4:1 + | +LL | #[lang = "foo"] + | ^^^^^^^^^^^^^^^ definition of unknown language item `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0522`. diff --git a/tests/ui/unknown-lint-tool-name.rs b/tests/ui/unknown-lint-tool-name.rs new file mode 100644 index 000000000..cd5d2f028 --- /dev/null +++ b/tests/ui/unknown-lint-tool-name.rs @@ -0,0 +1,6 @@ +#![deny(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + +#[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` +fn main() {} diff --git a/tests/ui/unknown-lint-tool-name.stderr b/tests/ui/unknown-lint-tool-name.stderr new file mode 100644 index 000000000..5f8349ce6 --- /dev/null +++ b/tests/ui/unknown-lint-tool-name.stderr @@ -0,0 +1,35 @@ +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:1:9 + | +LL | #![deny(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:4:9 + | +LL | #[allow(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:1:9 + | +LL | #![deny(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:4:9 + | +LL | #[allow(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/unknown-llvm-arg.rs b/tests/ui/unknown-llvm-arg.rs new file mode 100644 index 000000000..289bae24f --- /dev/null +++ b/tests/ui/unknown-llvm-arg.rs @@ -0,0 +1,22 @@ +// compile-flags: -Cllvm-args=-not-a-real-llvm-arg +// normalize-stderr-test "--help" -> "-help" +// normalize-stderr-test "\n(\n|.)*" -> "" + +// I'm seeing "--help" locally, but "-help" in CI, so I'm normalizing it to just "-help". + +// Note that the rustc-supplied "program name", given when invoking LLVM, is used by LLVM to +// generate user-facing error messages and a usage (--help) messages. If the program name is +// `rustc`, the usage message in response to `--llvm-args="--help"` starts with: +// ``` +// USAGE: rustc [options] +// ``` +// followed by the list of options not to `rustc` but to `llvm`. +// +// On the other hand, if the program name is set to `rustc -Cllvm-args="..." with`, the usage +// message is more clear: +// ``` +// USAGE: rustc -Cllvm-args="..." with [options] +// ``` +// This test captures the effect of the current program name setting on LLVM command line +// error messages. +fn main() {} diff --git a/tests/ui/unknown-llvm-arg.stderr b/tests/ui/unknown-llvm-arg.stderr new file mode 100644 index 000000000..e1d3cfea2 --- /dev/null +++ b/tests/ui/unknown-llvm-arg.stderr @@ -0,0 +1 @@ +rustc -Cllvm-args="..." with: Unknown command line argument '-not-a-real-llvm-arg'. Try: 'rustc -Cllvm-args="..." with -help' \ No newline at end of file diff --git a/tests/ui/unknown-tool-name.rs b/tests/ui/unknown-tool-name.rs new file mode 100644 index 000000000..73fca61c6 --- /dev/null +++ b/tests/ui/unknown-tool-name.rs @@ -0,0 +1,2 @@ +#[foo::bar] //~ ERROR failed to resolve: use of undeclared crate or module `foo` +fn main() {} diff --git a/tests/ui/unknown-tool-name.stderr b/tests/ui/unknown-tool-name.stderr new file mode 100644 index 000000000..4a1370ba8 --- /dev/null +++ b/tests/ui/unknown-tool-name.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `foo` + --> $DIR/unknown-tool-name.rs:1:3 + | +LL | #[foo::bar] + | ^^^ use of undeclared crate or module `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-command-line.rs new file mode 100644 index 000000000..80e30f239 --- /dev/null +++ b/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-command-line.rs @@ -0,0 +1,4 @@ +// check-pass +// compile-flags: -Aunknown_lints -Atest_unstable_lint + +fn main() {} diff --git a/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-inline.rs b/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-inline.rs new file mode 100644 index 000000000..992472c89 --- /dev/null +++ b/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-inline.rs @@ -0,0 +1,5 @@ +// check-pass + +#![allow(unknown_lints, test_unstable_lint)] + +fn main() {} diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs new file mode 100644 index 000000000..dcc06850d --- /dev/null +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs @@ -0,0 +1,6 @@ +// check-fail +// compile-flags: -Dunknown_lints -Atest_unstable_lint +// error-pattern: unknown lint: `test_unstable_lint` +// error-pattern: the `test_unstable_lint` lint is unstable + +fn main() {} diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr new file mode 100644 index 000000000..aa73b824a --- /dev/null +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr @@ -0,0 +1,18 @@ +error: unknown lint: `test_unstable_lint` + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: requested on the command line with `-D unknown-lints` + +error: unknown lint: `test_unstable_lint` + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +error: unknown lint: `test_unstable_lint` + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs new file mode 100644 index 000000000..c6c60b12d --- /dev/null +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs @@ -0,0 +1,9 @@ +// check-fail + +#![deny(unknown_lints)] +#![allow(test_unstable_lint)] +//~^ ERROR unknown lint: `test_unstable_lint` +//~| ERROR unknown lint: `test_unstable_lint` +//~| ERROR unknown lint: `test_unstable_lint` + +fn main() {} diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr new file mode 100644 index 000000000..2a2a9811b --- /dev/null +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr @@ -0,0 +1,34 @@ +error: unknown lint: `test_unstable_lint` + --> $DIR/deny-unstable-lint-inline.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable +note: the lint level is defined here + --> $DIR/deny-unstable-lint-inline.rs:3:9 + | +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ + +error: unknown lint: `test_unstable_lint` + --> $DIR/deny-unstable-lint-inline.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +error: unknown lint: `test_unstable_lint` + --> $DIR/deny-unstable-lint-inline.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs new file mode 100644 index 000000000..3778291eb --- /dev/null +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs @@ -0,0 +1,6 @@ +// check-pass +// compile-flags: -Wunknown_lints -Atest_unstable_lint +// error-pattern: unknown lint: `test_unstable_lint` +// error-pattern: the `test_unstable_lint` lint is unstable + +fn main() {} diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr new file mode 100644 index 000000000..82851c800 --- /dev/null +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr @@ -0,0 +1,18 @@ +warning: unknown lint: `test_unstable_lint` + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + = note: requested on the command line with `-W unknown-lints` + +warning: unknown lint: `test_unstable_lint` + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +warning: unknown lint: `test_unstable_lint` + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +warning: 3 warnings emitted + diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs new file mode 100644 index 000000000..f4247e456 --- /dev/null +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs @@ -0,0 +1,9 @@ +// check-pass + +#![warn(unknown_lints)] +#![allow(test_unstable_lint)] +//~^ WARNING unknown lint: `test_unstable_lint` +//~| WARNING unknown lint: `test_unstable_lint` +//~| WARNING unknown lint: `test_unstable_lint` + +fn main() {} diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr new file mode 100644 index 000000000..0548cd226 --- /dev/null +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr @@ -0,0 +1,34 @@ +warning: unknown lint: `test_unstable_lint` + --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable +note: the lint level is defined here + --> $DIR/warn-unknown-unstable-lint-inline.rs:3:9 + | +LL | #![warn(unknown_lints)] + | ^^^^^^^^^^^^^ + +warning: unknown lint: `test_unstable_lint` + --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +warning: unknown lint: `test_unstable_lint` + --> $DIR/warn-unknown-unstable-lint-inline.rs:4:1 + | +LL | #![allow(test_unstable_lint)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `test_unstable_lint` lint is unstable + = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable + +warning: 3 warnings emitted + diff --git a/tests/ui/unnamed_argument_mode.rs b/tests/ui/unnamed_argument_mode.rs new file mode 100644 index 000000000..5b7b4002f --- /dev/null +++ b/tests/ui/unnamed_argument_mode.rs @@ -0,0 +1,14 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn good(_a: &isize) { +} + +// unnamed argument &isize is now parse x: &isize + +fn called(_f: F) where F: FnOnce(&isize) { +} + +pub fn main() { + called(good); +} diff --git a/tests/ui/unop-move-semantics.rs b/tests/ui/unop-move-semantics.rs new file mode 100644 index 000000000..8168da824 --- /dev/null +++ b/tests/ui/unop-move-semantics.rs @@ -0,0 +1,32 @@ +// Test that move restrictions are enforced on overloaded unary operations + +use std::ops::Not; + +fn move_then_borrow + Clone>(x: T) { + !x; + + x.clone(); //~ ERROR: borrow of moved value +} + +fn move_borrowed>(x: T, mut y: T) { + let m = &x; + let n = &mut y; + + !x; //~ ERROR: cannot move out of `x` because it is borrowed + + !y; //~ ERROR: cannot move out of `y` because it is borrowed + use_mut(n); use_imm(m); +} +fn illegal_dereference>(mut x: T, y: T) { + let m = &mut x; + let n = &y; + + !*m; //~ ERROR: cannot move out of `*m` + + !*n; //~ ERROR: cannot move out of `*n` + use_imm(n); use_mut(m); +} +fn main() {} + +fn use_mut(_: &mut T) { } +fn use_imm(_: &T) { } diff --git a/tests/ui/unop-move-semantics.stderr b/tests/ui/unop-move-semantics.stderr new file mode 100644 index 000000000..2a3ca1443 --- /dev/null +++ b/tests/ui/unop-move-semantics.stderr @@ -0,0 +1,70 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/unop-move-semantics.rs:8:5 + | +LL | fn move_then_borrow + Clone>(x: T) { + | - move occurs because `x` has type `T`, which does not implement the `Copy` trait +LL | !x; + | -- `x` moved due to usage in operator +LL | +LL | x.clone(); + | ^^^^^^^^^ value borrowed here after move + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: consider cloning the value if the performance cost is acceptable + | +LL | !x.clone(); + | ++++++++ +help: consider further restricting this bound + | +LL | fn move_then_borrow + Clone + Copy>(x: T) { + | ++++++ + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/unop-move-semantics.rs:15:6 + | +LL | let m = &x; + | -- borrow of `x` occurs here +... +LL | !x; + | ^ move out of `x` occurs here +... +LL | use_mut(n); use_imm(m); + | - borrow later used here + +error[E0505]: cannot move out of `y` because it is borrowed + --> $DIR/unop-move-semantics.rs:17:6 + | +LL | let n = &mut y; + | ------ borrow of `y` occurs here +... +LL | !y; + | ^ move out of `y` occurs here +LL | use_mut(n); use_imm(m); + | - borrow later used here + +error[E0507]: cannot move out of `*m` which is behind a mutable reference + --> $DIR/unop-move-semantics.rs:24:6 + | +LL | !*m; + | -^^ + | || + | |move occurs because `*m` has type `T`, which does not implement the `Copy` trait + | `*m` moved due to usage in operator + | +note: calling this operator moves the left-hand side + --> $SRC_DIR/core/src/ops/bit.rs:LL:COL + +error[E0507]: cannot move out of `*n` which is behind a shared reference + --> $DIR/unop-move-semantics.rs:26:6 + | +LL | !*n; + | -^^ + | || + | |move occurs because `*n` has type `T`, which does not implement the `Copy` trait + | `*n` moved due to usage in operator + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0382, E0505, E0507. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/unop-neg-bool.rs b/tests/ui/unop-neg-bool.rs new file mode 100644 index 000000000..6f1f1aba4 --- /dev/null +++ b/tests/ui/unop-neg-bool.rs @@ -0,0 +1,3 @@ +fn main() { + -true; //~ ERROR cannot apply unary operator `-` to type `bool` +} diff --git a/tests/ui/unop-neg-bool.stderr b/tests/ui/unop-neg-bool.stderr new file mode 100644 index 000000000..9913747b8 --- /dev/null +++ b/tests/ui/unop-neg-bool.stderr @@ -0,0 +1,9 @@ +error[E0600]: cannot apply unary operator `-` to type `bool` + --> $DIR/unop-neg-bool.rs:2:5 + | +LL | -true; + | ^^^^^ cannot apply unary operator `-` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/unpretty-expr-fn-arg.rs b/tests/ui/unpretty-expr-fn-arg.rs new file mode 100644 index 000000000..6e1132a33 --- /dev/null +++ b/tests/ui/unpretty-expr-fn-arg.rs @@ -0,0 +1,13 @@ +// Regression test for the ICE described in #82328. The pretty-printer for +// `-Zunpretty=hir,typed` would previously retrieve type-checking results +// when entering a body, which means that type information was not available +// for expressions occurring in function signatures, as in the `foo` example +// below, leading to an ICE. + +// check-pass +// compile-flags: -Zunpretty=hir,typed +#![allow(dead_code)] + +fn main() {} + +fn foo(-128..=127: i8) {} diff --git a/tests/ui/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty-expr-fn-arg.stdout new file mode 100644 index 000000000..b745b9886 --- /dev/null +++ b/tests/ui/unpretty-expr-fn-arg.stdout @@ -0,0 +1,17 @@ +// Regression test for the ICE described in #82328. The pretty-printer for +// `-Zunpretty=hir,typed` would previously retrieve type-checking results +// when entering a body, which means that type information was not available +// for expressions occurring in function signatures, as in the `foo` example +// below, leading to an ICE. + +// check-pass +// compile-flags: -Zunpretty=hir,typed +#![allow(dead_code)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn main() ({ } as ()) + +fn foo((-(128 as i8) as i8)...(127 as i8): i8) ({ } as ()) diff --git a/tests/ui/unpretty/avoid-crash.rs b/tests/ui/unpretty/avoid-crash.rs new file mode 100644 index 000000000..fd84b70d9 --- /dev/null +++ b/tests/ui/unpretty/avoid-crash.rs @@ -0,0 +1,4 @@ +// normalize-stderr-test "error `.*`" -> "$$ERROR_MESSAGE" +// compile-flags: -o/tmp/ -Zunpretty=ast-tree + +fn main() {} diff --git a/tests/ui/unpretty/avoid-crash.stderr b/tests/ui/unpretty/avoid-crash.stderr new file mode 100644 index 000000000..11cd3866f --- /dev/null +++ b/tests/ui/unpretty/avoid-crash.stderr @@ -0,0 +1,4 @@ +error: pretty-print failed to write `/tmp/` due to $ERROR_MESSAGE + +error: aborting due to previous error + diff --git a/tests/ui/unpretty/bad-literal.rs b/tests/ui/unpretty/bad-literal.rs new file mode 100644 index 000000000..6dcc0da30 --- /dev/null +++ b/tests/ui/unpretty/bad-literal.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zunpretty=hir +// check-fail + +// In #100948 this caused an ICE with -Zunpretty=hir. +fn main() { + 1u; + //~^ ERROR invalid suffix `u` for number literal +} diff --git a/tests/ui/unpretty/bad-literal.stderr b/tests/ui/unpretty/bad-literal.stderr new file mode 100644 index 000000000..f3fcb4a4e --- /dev/null +++ b/tests/ui/unpretty/bad-literal.stderr @@ -0,0 +1,10 @@ +error: invalid suffix `u` for number literal + --> $DIR/bad-literal.rs:6:5 + | +LL | 1u; + | ^^ invalid suffix `u` + | + = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) + +error: aborting due to previous error + diff --git a/tests/ui/unpretty/bad-literal.stdout b/tests/ui/unpretty/bad-literal.stdout new file mode 100644 index 000000000..8df933270 --- /dev/null +++ b/tests/ui/unpretty/bad-literal.stdout @@ -0,0 +1,11 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// compile-flags: -Zunpretty=hir +// check-fail + +// In #100948 this caused an ICE with -Zunpretty=hir. +fn main() { + ; + } diff --git a/tests/ui/unpretty/pretty-let-else.rs b/tests/ui/unpretty/pretty-let-else.rs new file mode 100644 index 000000000..b5ae52969 --- /dev/null +++ b/tests/ui/unpretty/pretty-let-else.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zunpretty=hir +// check-pass + + + +fn foo(x: Option) { + let Some(_) = x else { panic!() }; +} + +fn main() {} diff --git a/tests/ui/unpretty/pretty-let-else.stdout b/tests/ui/unpretty/pretty-let-else.stdout new file mode 100644 index 000000000..35ad1cd1b --- /dev/null +++ b/tests/ui/unpretty/pretty-let-else.stdout @@ -0,0 +1,18 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// compile-flags: -Zunpretty=hir +// check-pass + + + +fn foo(x: + Option) { + let Some(_) = x else + { + + { ::std::rt::begin_panic("explicit panic") } + }; + } +fn main() { } diff --git a/tests/ui/unreachable-code-1.rs b/tests/ui/unreachable-code-1.rs new file mode 100644 index 000000000..ee44f3999 --- /dev/null +++ b/tests/ui/unreachable-code-1.rs @@ -0,0 +1,19 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(unreachable_code)] + +#![allow(unused_variables)] +#![allow(dead_code)] + +fn id(x: bool) -> bool { x } + +fn call_id() { + let c = panic!(); + id(c); +} + +fn call_id_3() { id(return) && id(return); } + +pub fn main() { +} diff --git a/tests/ui/unreachable-code.rs b/tests/ui/unreachable-code.rs new file mode 100644 index 000000000..28b938edc --- /dev/null +++ b/tests/ui/unreachable-code.rs @@ -0,0 +1,28 @@ +// run-pass + +#![allow(unused_must_use)] +#![allow(dead_code)] + +#![allow(path_statements)] +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn id(x: bool) -> bool { x } + +fn call_id() { + let c = panic!(); + id(c); +} + +fn call_id_2() { id(true) && id(return); } + +fn call_id_3() { id(return) && id(return); } + +fn ret_guard() { + match 2 { + x if (return) => { x; } + _ => {} + } +} + +pub fn main() {} diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.rs b/tests/ui/unresolved/unresolved-asterisk-imports.rs new file mode 100644 index 000000000..2d853a66c --- /dev/null +++ b/tests/ui/unresolved/unresolved-asterisk-imports.rs @@ -0,0 +1,4 @@ +use not_existing_crate::*; //~ ERROR unresolved import `not_existing_crate +use std as foo; + +fn main() {} diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.stderr b/tests/ui/unresolved/unresolved-asterisk-imports.stderr new file mode 100644 index 000000000..8df8eab34 --- /dev/null +++ b/tests/ui/unresolved/unresolved-asterisk-imports.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `not_existing_crate` + --> $DIR/unresolved-asterisk-imports.rs:1:5 + | +LL | use not_existing_crate::*; + | ^^^^^^^^^^^^^^^^^^ maybe a missing crate `not_existing_crate`? + | + = help: consider adding `extern crate not_existing_crate` to use the `not_existing_crate` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/unresolved/unresolved-candidates.rs b/tests/ui/unresolved/unresolved-candidates.rs new file mode 100644 index 000000000..38b227f60 --- /dev/null +++ b/tests/ui/unresolved/unresolved-candidates.rs @@ -0,0 +1,13 @@ +mod a { + pub trait Trait {} +} + +mod b { + use Trait; //~ ERROR unresolved import `Trait` +} + +mod c { + impl Trait for () {} //~ ERROR cannot find trait `Trait` in this scope +} + +fn main() {} diff --git a/tests/ui/unresolved/unresolved-candidates.stderr b/tests/ui/unresolved/unresolved-candidates.stderr new file mode 100644 index 000000000..ea737c567 --- /dev/null +++ b/tests/ui/unresolved/unresolved-candidates.stderr @@ -0,0 +1,26 @@ +error[E0432]: unresolved import `Trait` + --> $DIR/unresolved-candidates.rs:6:9 + | +LL | use Trait; + | ^^^^^ no `Trait` in the root + | +help: consider importing this trait instead + | +LL | use a::Trait; + | ~~~~~~~~ + +error[E0405]: cannot find trait `Trait` in this scope + --> $DIR/unresolved-candidates.rs:10:10 + | +LL | impl Trait for () {} + | ^^^^^ not found in this scope + | +help: consider importing this trait + | +LL | use a::Trait; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0405, E0432. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/unresolved/unresolved-extern-mod-suggestion.rs b/tests/ui/unresolved/unresolved-extern-mod-suggestion.rs new file mode 100644 index 000000000..a1bf0f210 --- /dev/null +++ b/tests/ui/unresolved/unresolved-extern-mod-suggestion.rs @@ -0,0 +1,5 @@ +extern crate core; +use core; +//~^ ERROR the name `core` is defined multiple times + +fn main() {} diff --git a/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr b/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr new file mode 100644 index 000000000..28333228a --- /dev/null +++ b/tests/ui/unresolved/unresolved-extern-mod-suggestion.stderr @@ -0,0 +1,13 @@ +error[E0254]: the name `core` is defined multiple times + --> $DIR/unresolved-extern-mod-suggestion.rs:2:5 + | +LL | extern crate core; + | ------------------ previous import of the extern crate `core` here +LL | use core; + | ^^^^ `core` reimported here + | + = note: `core` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0254`. diff --git a/tests/ui/unresolved/unresolved-import-recovery.rs b/tests/ui/unresolved/unresolved-import-recovery.rs new file mode 100644 index 000000000..0b0653378 --- /dev/null +++ b/tests/ui/unresolved/unresolved-import-recovery.rs @@ -0,0 +1,17 @@ +// Check that unresolved imports do not create additional errors and ICEs + +mod m { + pub use unresolved; //~ ERROR unresolved import `unresolved` + + fn f() { + let unresolved = 0; // OK + } +} + +fn main() { + match 0u8 { + m::unresolved => {} // OK + m::unresolved(..) => {} // OK + m::unresolved{..} => {} // OK + } +} diff --git a/tests/ui/unresolved/unresolved-import-recovery.stderr b/tests/ui/unresolved/unresolved-import-recovery.stderr new file mode 100644 index 000000000..5e371b70b --- /dev/null +++ b/tests/ui/unresolved/unresolved-import-recovery.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `unresolved` + --> $DIR/unresolved-import-recovery.rs:4:13 + | +LL | pub use unresolved; + | ^^^^^^^^^^ no `unresolved` in the root + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs new file mode 100644 index 000000000..4125c593c --- /dev/null +++ b/tests/ui/unresolved/unresolved-import.rs @@ -0,0 +1,56 @@ +use foo::bar; //~ ERROR unresolved import `foo` [E0432] + //~^ maybe a missing crate `foo`? + //~| HELP consider adding `extern crate foo` to use the `foo` crate + +use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432] + //~| no `Baz` in `bar` + //~| HELP a similar name exists in the module + //~| SUGGESTION Bar + +use food::baz; //~ ERROR unresolved import `food::baz` + //~| no `baz` in `food` + //~| HELP a similar name exists in the module + //~| SUGGESTION bag + +use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432] + //~| no `beens` in `food` + //~| HELP a similar name exists in the module + //~| SUGGESTION beans + +mod bar { + pub struct Bar; +} + +mod food { + pub use self::zug::baz::{self as bag, Foobar as beans}; + + mod zug { + pub mod baz { + pub struct Foobar; + } + } +} + +mod m { + enum MyEnum { + MyVariant + } + + use MyEnum::*; //~ ERROR unresolved import `MyEnum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::MyEnum +} + +mod items { + enum Enum { + Variant + } + + use Enum::*; //~ ERROR unresolved import `Enum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::Enum + + fn item() {} +} + +fn main() {} diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr new file mode 100644 index 000000000..0dd928c8b --- /dev/null +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -0,0 +1,50 @@ +error[E0432]: unresolved import `foo` + --> $DIR/unresolved-import.rs:1:5 + | +LL | use foo::bar; + | ^^^ maybe a missing crate `foo`? + | + = help: consider adding `extern crate foo` to use the `foo` crate + +error[E0432]: unresolved import `bar::Baz` + --> $DIR/unresolved-import.rs:5:5 + | +LL | use bar::Baz as x; + | ^^^^^---^^^^^ + | | | + | | help: a similar name exists in the module: `Bar` + | no `Baz` in `bar` + +error[E0432]: unresolved import `food::baz` + --> $DIR/unresolved-import.rs:10:5 + | +LL | use food::baz; + | ^^^^^^--- + | | | + | | help: a similar name exists in the module: `bag` + | no `baz` in `food` + +error[E0432]: unresolved import `food::beens` + --> $DIR/unresolved-import.rs:15:12 + | +LL | use food::{beens as Foo}; + | -----^^^^^^^ + | | + | no `beens` in `food` + | help: a similar name exists in the module: `beans` + +error[E0432]: unresolved import `MyEnum` + --> $DIR/unresolved-import.rs:39:9 + | +LL | use MyEnum::*; + | ^^^^^^ help: a similar path exists: `self::MyEnum` + +error[E0432]: unresolved import `Enum` + --> $DIR/unresolved-import.rs:49:9 + | +LL | use Enum::*; + | ^^^^ help: a similar path exists: `self::Enum` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/unsafe-fn-called-from-unsafe-blk.rs b/tests/ui/unsafe-fn-called-from-unsafe-blk.rs new file mode 100644 index 000000000..3713a7065 --- /dev/null +++ b/tests/ui/unsafe-fn-called-from-unsafe-blk.rs @@ -0,0 +1,18 @@ +// run-pass + +#![allow(dead_code)] +// +// See also: ui/unsafe/unsafe-fn-called-from-safe.rs + +// pretty-expanded FIXME #23616 + +unsafe fn f() { return; } + +fn g() { + unsafe { + f(); + } +} + +pub fn main() { +} diff --git a/tests/ui/unsafe-fn-called-from-unsafe-fn.rs b/tests/ui/unsafe-fn-called-from-unsafe-fn.rs new file mode 100644 index 000000000..5e9531076 --- /dev/null +++ b/tests/ui/unsafe-fn-called-from-unsafe-fn.rs @@ -0,0 +1,17 @@ +// run-pass + +#![allow(dead_code)] +// +// See also: ui/unsafe/unsafe-fn-called-from-safe.rs + +// pretty-expanded FIXME #23616 + +unsafe fn f() { return; } + +unsafe fn g() { + f(); +} + +pub fn main() { + return; +} diff --git a/tests/ui/unsafe-pointer-assignability.rs b/tests/ui/unsafe-pointer-assignability.rs new file mode 100644 index 000000000..db822bb6a --- /dev/null +++ b/tests/ui/unsafe-pointer-assignability.rs @@ -0,0 +1,11 @@ +// run-pass + +fn f(x: *const isize) { + unsafe { + assert_eq!(*x, 3); + } +} + +pub fn main() { + f(&3); +} diff --git a/tests/ui/unsafe/access_union_field.mir.stderr b/tests/ui/unsafe/access_union_field.mir.stderr new file mode 100644 index 000000000..98bc40777 --- /dev/null +++ b/tests/ui/unsafe/access_union_field.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:13:13 + | +LL | let a = foo.bar; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:14:13 + | +LL | let b = foo.baz; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/access_union_field.rs b/tests/ui/unsafe/access_union_field.rs new file mode 100644 index 000000000..5c4e695df --- /dev/null +++ b/tests/ui/unsafe/access_union_field.rs @@ -0,0 +1,15 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![allow(unused_variables)] + +union Foo { + bar: i8, + baz: u8, +} + +fn main() { + let foo = Foo { bar: 5 }; + let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block + let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block +} diff --git a/tests/ui/unsafe/access_union_field.thir.stderr b/tests/ui/unsafe/access_union_field.thir.stderr new file mode 100644 index 000000000..98bc40777 --- /dev/null +++ b/tests/ui/unsafe/access_union_field.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:13:13 + | +LL | let a = foo.bar; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/access_union_field.rs:14:13 + | +LL | let b = foo.baz; + | ^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/auxiliary/issue-106126.rs b/tests/ui/unsafe/auxiliary/issue-106126.rs new file mode 100644 index 000000000..091a3edb7 --- /dev/null +++ b/tests/ui/unsafe/auxiliary/issue-106126.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! foo { + () => { + unsafe fn __unsf() {} + unsafe fn __foo() { + __unsf(); + } + }; +} diff --git a/tests/ui/unsafe/inline_asm.mir.stderr b/tests/ui/unsafe/inline_asm.mir.stderr new file mode 100644 index 000000000..633f1edb2 --- /dev/null +++ b/tests/ui/unsafe/inline_asm.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/inline_asm.rs:8:5 + | +LL | asm!("nop"); + | ^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/inline_asm.rs b/tests/ui/unsafe/inline_asm.rs new file mode 100644 index 000000000..12c7efe4f --- /dev/null +++ b/tests/ui/unsafe/inline_asm.rs @@ -0,0 +1,9 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck +// needs-asm-support + +use std::arch::asm; + +fn main() { + asm!("nop"); //~ ERROR use of inline assembly is unsafe and requires unsafe function or block +} diff --git a/tests/ui/unsafe/inline_asm.thir.stderr b/tests/ui/unsafe/inline_asm.thir.stderr new file mode 100644 index 000000000..633f1edb2 --- /dev/null +++ b/tests/ui/unsafe/inline_asm.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/inline_asm.rs:8:5 + | +LL | asm!("nop"); + | ^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-106126-good-path-bug.rs b/tests/ui/unsafe/issue-106126-good-path-bug.rs new file mode 100644 index 000000000..93f478ee3 --- /dev/null +++ b/tests/ui/unsafe/issue-106126-good-path-bug.rs @@ -0,0 +1,12 @@ +// Regression test for #106126. +// check-pass +// aux-build:issue-106126.rs + +#![deny(unsafe_op_in_unsafe_fn)] + +#[macro_use] +extern crate issue_106126; + +foo!(); + +fn main() {} diff --git a/tests/ui/unsafe/issue-3080.mir.stderr b/tests/ui/unsafe/issue-3080.mir.stderr new file mode 100644 index 000000000..f395c30b8 --- /dev/null +++ b/tests/ui/unsafe/issue-3080.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/issue-3080.rs:10:5 + | +LL | X(()).with(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-3080.rs b/tests/ui/unsafe/issue-3080.rs new file mode 100644 index 000000000..2b5269dda --- /dev/null +++ b/tests/ui/unsafe/issue-3080.rs @@ -0,0 +1,11 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +struct X(()); +impl X { + pub unsafe fn with(&self) { } +} + +fn main() { + X(()).with(); //~ ERROR requires unsafe function or block +} diff --git a/tests/ui/unsafe/issue-3080.thir.stderr b/tests/ui/unsafe/issue-3080.thir.stderr new file mode 100644 index 000000000..4d8acac61 --- /dev/null +++ b/tests/ui/unsafe/issue-3080.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `X::with` is unsafe and requires unsafe function or block + --> $DIR/issue-3080.rs:10:5 + | +LL | X(()).with(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr b/tests/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr new file mode 100644 index 000000000..e79609607 --- /dev/null +++ b/tests/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr @@ -0,0 +1,27 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45087-unreachable-unsafe.rs:7:5 + | +LL | *(1 as *mut u32) = 42; + | ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45087-unreachable-unsafe.rs:17:5 + | +LL | *a = 1; + | ^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45087-unreachable-unsafe.rs:29:5 + | +LL | *b = 1; + | ^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-45087-unreachable-unsafe.rs b/tests/ui/unsafe/issue-45087-unreachable-unsafe.rs new file mode 100644 index 000000000..3e3da667c --- /dev/null +++ b/tests/ui/unsafe/issue-45087-unreachable-unsafe.rs @@ -0,0 +1,31 @@ +// Verify that unreachable code undergoes unsafety checks. +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +fn main() { + return; + *(1 as *mut u32) = 42; + //~^ ERROR dereference of raw pointer is unsafe +} + +fn panic() -> ! { + panic!(); +} + +fn f(a: *mut u32) { + panic(); + *a = 1; + //~^ ERROR dereference of raw pointer is unsafe +} + +enum Void {} + +fn uninhabited() -> Void { + panic!(); +} + +fn g(b: *mut u32) { + uninhabited(); + *b = 1; + //~^ ERROR dereference of raw pointer is unsafe +} diff --git a/tests/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr b/tests/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr new file mode 100644 index 000000000..e81adad45 --- /dev/null +++ b/tests/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr @@ -0,0 +1,27 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45087-unreachable-unsafe.rs:7:5 + | +LL | *(1 as *mut u32) = 42; + | ^^^^^^^^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45087-unreachable-unsafe.rs:17:5 + | +LL | *a = 1; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-45087-unreachable-unsafe.rs:29:5 + | +LL | *b = 1; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr b/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr new file mode 100644 index 000000000..9e9cbcf33 --- /dev/null +++ b/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr @@ -0,0 +1,35 @@ +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | let f = |v: &mut Vec<_>| { +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | |w: &mut Vec| { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | |x: &mut Vec| { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs b/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs new file mode 100644 index 000000000..ac1cfd62a --- /dev/null +++ b/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs @@ -0,0 +1,28 @@ +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#[deny(unused_unsafe)] +fn main() { + let mut v = Vec::::with_capacity(24); + + unsafe { + let f = |v: &mut Vec<_>| { + unsafe { //~ ERROR unnecessary `unsafe` + v.set_len(24); + |w: &mut Vec| { unsafe { //~ ERROR unnecessary `unsafe` + w.set_len(32); + } }; + } + |x: &mut Vec| { unsafe { //~ ERROR unnecessary `unsafe` + x.set_len(40); + } }; + }; + + v.set_len(0); + f(&mut v); + } + + |y: &mut Vec| { unsafe { + y.set_len(48); + } }; +} diff --git a/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr b/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr new file mode 100644 index 000000000..9e9cbcf33 --- /dev/null +++ b/tests/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr @@ -0,0 +1,35 @@ +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | let f = |v: &mut Vec<_>| { +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | |w: &mut Vec| { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | |x: &mut Vec| { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unsafe/issue-47412.mir.stderr b/tests/ui/unsafe/issue-47412.mir.stderr new file mode 100644 index 000000000..305f482e8 --- /dev/null +++ b/tests/ui/unsafe/issue-47412.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-47412.rs:14:11 + | +LL | match u.void {} + | ^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-47412.rs:20:11 + | +LL | match *ptr {} + | ^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-47412.rs b/tests/ui/unsafe/issue-47412.rs new file mode 100644 index 000000000..df6d6e422 --- /dev/null +++ b/tests/ui/unsafe/issue-47412.rs @@ -0,0 +1,24 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +enum Void {} + +// Tests that we detect unsafe places (specifically, union fields and +// raw pointer dereferences), even when they're matched on while having +// an uninhabited type (equivalent to `std::intrinsics::unreachable()`). + +fn union_field() { + union Union { unit: (), void: Void } + let u = Union { unit: () }; + match u.void {} + //~^ ERROR access to union field is unsafe +} + +fn raw_ptr_deref() { + let ptr = std::ptr::null::(); + match *ptr {} + //~^ ERROR dereference of raw pointer is unsafe +} + +fn main() {} diff --git a/tests/ui/unsafe/issue-47412.thir.stderr b/tests/ui/unsafe/issue-47412.thir.stderr new file mode 100644 index 000000000..305f482e8 --- /dev/null +++ b/tests/ui/unsafe/issue-47412.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-47412.rs:14:11 + | +LL | match u.void {} + | ^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/issue-47412.rs:20:11 + | +LL | match *ptr {} + | ^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs b/tests/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs new file mode 100644 index 000000000..72f7b6747 --- /dev/null +++ b/tests/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs @@ -0,0 +1,27 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +// This is issue #85435. But the real story is reflected in issue #85561, where +// a bug in the implementation of feature(capture_disjoint_fields) () was +// exposed to non-feature-gated code by a diagnostic changing PR that removed +// the gating in one case. + +// This test is double-checking that the case of interest continues to work as +// expected in the *absence* of that feature gate. At the time of this writing, +// enabling the feature gate will cause this test to fail. We obviously cannot +// stabilize that feature until it can correctly handle this test. + +fn main() { + let val: u8 = 5; + let u8_ptr: *const u8 = &val; + let _closure = || { + unsafe { + let tmp = *u8_ptr; + tmp + + // Just dereferencing and returning directly compiles fine: + // *u8_ptr + } + }; +} diff --git a/tests/ui/unsafe/issue-87414-query-cycle.rs b/tests/ui/unsafe/issue-87414-query-cycle.rs new file mode 100644 index 000000000..99e40ba4b --- /dev/null +++ b/tests/ui/unsafe/issue-87414-query-cycle.rs @@ -0,0 +1,15 @@ +// Regression test for #87414. + +// check-pass +// compile-flags: -Zthir-unsafeck + +fn bad() -> Box> { todo!() } + +fn foo() -> [(); { |x: u32| { x }; 4 }] { todo!() } +fn bar() { let _: [(); { |x: u32| { x }; 4 }]; } + +// This one should not cause any errors either: +unsafe fn unsf() {} +fn bad2() -> Box> { todo!() } + +fn main() {} diff --git a/tests/ui/unsafe/ranged_ints.mir.stderr b/tests/ui/unsafe/ranged_ints.mir.stderr new file mode 100644 index 000000000..f9ef7834e --- /dev/null +++ b/tests/ui/unsafe/ranged_ints.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + --> $DIR/ranged_ints.rs:10:14 + | +LL | let _x = NonZero(0); + | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr + | + = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints.rs b/tests/ui/unsafe/ranged_ints.rs new file mode 100644 index 000000000..05efe87ba --- /dev/null +++ b/tests/ui/unsafe/ranged_ints.rs @@ -0,0 +1,11 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr +} diff --git a/tests/ui/unsafe/ranged_ints.thir.stderr b/tests/ui/unsafe/ranged_ints.thir.stderr new file mode 100644 index 000000000..f9ef7834e --- /dev/null +++ b/tests/ui/unsafe/ranged_ints.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + --> $DIR/ranged_ints.rs:10:14 + | +LL | let _x = NonZero(0); + | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr + | + = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr new file mode 100644 index 000000000..427843f8d --- /dev/null +++ b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:11:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs new file mode 100644 index 000000000..9a6bb18f9 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -0,0 +1,12 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(1) }; + let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe +} diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr new file mode 100644 index 000000000..427843f8d --- /dev/null +++ b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:11:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr new file mode 100644 index 000000000..c16550a58 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:21:22 + | +LL | let y = unsafe { &mut x.0 }; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:27:22 + | +LL | unsafe { let y = &mut x.0; } + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2_const.rs b/tests/ui/unsafe/ranged_ints2_const.rs new file mode 100644 index 000000000..56f5407bb --- /dev/null +++ b/tests/ui/unsafe/ranged_ints2_const.rs @@ -0,0 +1,29 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { +} + +const fn foo() -> NonZero { + let mut x = unsafe { NonZero(1) }; + let y = &mut x.0; //~ ERROR mutable references + //~^ ERROR mutation of layout constrained field is unsafe + unsafe { NonZero(1) } +} + +const fn bar() -> NonZero { + let mut x = unsafe { NonZero(1) }; + let y = unsafe { &mut x.0 }; //~ ERROR mutable references + unsafe { NonZero(1) } +} + +const fn boo() -> NonZero { + let mut x = unsafe { NonZero(1) }; + unsafe { let y = &mut x.0; } //~ ERROR mutable references + unsafe { NonZero(1) } +} diff --git a/tests/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr new file mode 100644 index 000000000..b3f139f72 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:21:22 + | +LL | let y = unsafe { &mut x.0 }; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:27:22 + | +LL | unsafe { let y = &mut x.0; } + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr new file mode 100644 index 000000000..9eec0b09e --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3.rs:13:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3.rs b/tests/ui/unsafe/ranged_ints3.rs new file mode 100644 index 000000000..76d4bfe95 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3.rs @@ -0,0 +1,14 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(Cell::new(1)) }; + let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability +} diff --git a/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr new file mode 100644 index 000000000..9eec0b09e --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3.rs:13:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr new file mode 100644 index 000000000..62df93330 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr @@ -0,0 +1,30 @@ +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:22:22 + | +LL | let y = unsafe { &x.0 }; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3_const.rs b/tests/ui/unsafe/ranged_ints3_const.rs new file mode 100644 index 000000000..637198d36 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3_const.rs @@ -0,0 +1,24 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() {} + +const fn foo() -> NonZero> { + let mut x = unsafe { NonZero(Cell::new(1)) }; + let y = &x.0; //~ ERROR the borrowed element may contain interior mutability + //~^ ERROR borrow of layout constrained field with interior mutability + unsafe { NonZero(Cell::new(1)) } +} + +const fn bar() -> NonZero> { + let mut x = unsafe { NonZero(Cell::new(1)) }; + let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability + unsafe { NonZero(Cell::new(1)) } +} diff --git a/tests/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr new file mode 100644 index 000000000..5dbc563aa --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr @@ -0,0 +1,30 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:22:22 + | +LL | let y = unsafe { &x.0 }; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr new file mode 100644 index 000000000..27c066409 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:14:17 + | +LL | NonZero(ref x) => { x } + | ^^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:20:23 + | +LL | match y { NonZero(ref mut y) => { y } }; + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints3_match.rs b/tests/ui/unsafe/ranged_ints3_match.rs new file mode 100644 index 000000000..d9fcf0bd6 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3_match.rs @@ -0,0 +1,22 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(Cell::new(1)) }; + match x { + NonZero(ref x) => { x } + //~^ ERROR borrow of layout constrained field with interior mutability + }; + + let mut y = unsafe { NonZero(42) }; + match y { NonZero(ref y) => { y } }; // OK, type of `y` is freeze + match y { NonZero(ref mut y) => { y } }; + //~^ ERROR mutation of layout constrained field +} diff --git a/tests/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr new file mode 100644 index 000000000..27c066409 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:14:17 + | +LL | NonZero(ref x) => { x } + | ^^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:20:23 + | +LL | match y { NonZero(ref mut y) => { y } }; + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr new file mode 100644 index 000000000..493483d2c --- /dev/null +++ b/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4.rs:11:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4.rs b/tests/ui/unsafe/ranged_ints4.rs new file mode 100644 index 000000000..fe80af454 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints4.rs @@ -0,0 +1,12 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(1) }; + x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe +} diff --git a/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr new file mode 100644 index 000000000..493483d2c --- /dev/null +++ b/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4.rs:11:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr new file mode 100644 index 000000000..a06c6f479 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:13:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints4_const.rs b/tests/ui/unsafe/ranged_ints4_const.rs new file mode 100644 index 000000000..a43c8be71 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints4_const.rs @@ -0,0 +1,22 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() {} + +const fn foo() -> NonZero { + let mut x = unsafe { NonZero(1) }; + x.0 = 0; + //~^ ERROR mutation of layout constrained field is unsafe + x +} + +const fn bar() -> NonZero { + let mut x = unsafe { NonZero(1) }; + unsafe { x.0 = 0 }; // this is UB + x +} diff --git a/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr new file mode 100644 index 000000000..a06c6f479 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:13:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints_const.mir.stderr b/tests/ui/unsafe/ranged_ints_const.mir.stderr new file mode 100644 index 000000000..33d134c7c --- /dev/null +++ b/tests/ui/unsafe/ranged_ints_const.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + --> $DIR/ranged_ints_const.rs:11:34 + | +LL | const fn foo() -> NonZero { NonZero(0) } + | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr + | + = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints_const.rs b/tests/ui/unsafe/ranged_ints_const.rs new file mode 100644 index 000000000..472b09681 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints_const.rs @@ -0,0 +1,14 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() {} + +const fn foo() -> NonZero { NonZero(0) } +//~^ ERROR initializing type with `rustc_layout_scalar_valid_range` attr is unsafe + +const fn bar() -> NonZero { unsafe { NonZero(0) } } diff --git a/tests/ui/unsafe/ranged_ints_const.thir.stderr b/tests/ui/unsafe/ranged_ints_const.thir.stderr new file mode 100644 index 000000000..33d134c7c --- /dev/null +++ b/tests/ui/unsafe/ranged_ints_const.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + --> $DIR/ranged_ints_const.rs:11:34 + | +LL | const fn foo() -> NonZero { NonZero(0) } + | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr + | + = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints_macro.rs b/tests/ui/unsafe/ranged_ints_macro.rs new file mode 100644 index 000000000..8293d0299 --- /dev/null +++ b/tests/ui/unsafe/ranged_ints_macro.rs @@ -0,0 +1,19 @@ +// build-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +macro_rules! apply { + ($val:expr) => { + #[rustc_layout_scalar_valid_range_start($val)] + #[repr(transparent)] + pub(crate) struct NonZero(pub(crate) T); + } +} + +apply!(1); + +fn main() { + let _x = unsafe { NonZero(1) }; +} diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr new file mode 100644 index 000000000..6f005fe89 --- /dev/null +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr @@ -0,0 +1,102 @@ +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:12:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5 + | +LL | *PTR; + | ^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:17:5 + | +LL | VOID = (); + | ^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: unnecessary `unsafe` block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:20:5 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:5:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8 + | +LL | #[deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]` + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5 + | +LL | *PTR; + | ^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:33:5 + | +LL | VOID = (); + | ^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: unnecessary `unsafe` block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:35:5 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:49:5 + | +LL | unsafe { unsafe { unsf() } } + | ^^^^^^ unnecessary `unsafe` block + +error[E0133]: call to unsafe function is unsafe and requires unsafe block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:81:9 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs new file mode 100644 index 000000000..db1e916a3 --- /dev/null +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs @@ -0,0 +1,85 @@ +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![deny(unsafe_op_in_unsafe_fn)] +#![deny(unused_unsafe)] + +unsafe fn unsf() {} +const PTR: *const () = std::ptr::null(); +static mut VOID: () = (); + +unsafe fn deny_level() { + unsf(); + //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe block + //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block + *PTR; + //~^ ERROR dereference of raw pointer is unsafe and requires unsafe block + VOID = (); + //~^ ERROR use of mutable static is unsafe and requires unsafe block + + unsafe {} + //~^ ERROR unnecessary `unsafe` block +} + +// Check that `unsafe_op_in_unsafe_fn` works starting from the `warn` level. +#[warn(unsafe_op_in_unsafe_fn)] +#[deny(warnings)] +unsafe fn warning_level() { + unsf(); + //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe block + //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block + *PTR; + //~^ ERROR dereference of raw pointer is unsafe and requires unsafe block + VOID = (); + //~^ ERROR use of mutable static is unsafe and requires unsafe block + unsafe {} + //~^ ERROR unnecessary `unsafe` block +} + +unsafe fn explicit_block() { + // no error + unsafe { + unsf(); + *PTR; + VOID = (); + } +} + +unsafe fn two_explicit_blocks() { + unsafe { unsafe { unsf() } } + //~^ ERROR unnecessary `unsafe` block +} + +#[allow(unsafe_op_in_unsafe_fn)] +unsafe fn allow_level() { + // lint allowed -> no error + unsf(); + *PTR; + VOID = (); + + unsafe { unsf() } +} + +unsafe fn nested_allow_level() { + #[allow(unsafe_op_in_unsafe_fn)] + { + // lint allowed -> no error + unsf(); + *PTR; + VOID = (); + + unsafe { unsf() } + } +} + +fn main() { + unsf(); + //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe block + //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe function or block + //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe function or block + } +} diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr new file mode 100644 index 000000000..13c080e5b --- /dev/null +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr @@ -0,0 +1,104 @@ +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:12:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5 + | +LL | *PTR; + | ^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:17:5 + | +LL | VOID = (); + | ^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: unnecessary `unsafe` block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:20:5 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:5:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8 + | +LL | #[deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]` + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5 + | +LL | *PTR; + | ^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:33:5 + | +LL | VOID = (); + | ^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: unnecessary `unsafe` block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:35:5 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:49:14 + | +LL | unsafe { unsafe { unsf() } } + | ------ ^^^^^^ unnecessary `unsafe` block + | | + | because it's nested under this `unsafe` block + +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe function or block + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:81:9 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/union-assignop.mirunsafeck.stderr b/tests/ui/unsafe/union-assignop.mirunsafeck.stderr new file mode 100644 index 000000000..0ecd5203d --- /dev/null +++ b/tests/ui/unsafe/union-assignop.mirunsafeck.stderr @@ -0,0 +1,51 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:19:5 + | +LL | foo.a += 5; + | ^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:20:6 + | +LL | *foo.b += NonCopy; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:21:6 + | +LL | *foo.b = NonCopy; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:23:5 + | +LL | foo.a; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:25:5 + | +LL | foo.b; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:27:13 + | +LL | foo.b = foo.b; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/union-assignop.rs b/tests/ui/unsafe/union-assignop.rs new file mode 100644 index 000000000..5e667cd10 --- /dev/null +++ b/tests/ui/unsafe/union-assignop.rs @@ -0,0 +1,29 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +use std::ops::AddAssign; +use std::mem::ManuallyDrop; + +struct NonCopy; +impl AddAssign for NonCopy { + fn add_assign(&mut self, _: Self) {} +} + +union Foo { + a: u8, // non-dropping + b: ManuallyDrop, +} + +fn main() { + let mut foo = Foo { a: 42 }; + foo.a += 5; //~ ERROR access to union field is unsafe + *foo.b += NonCopy; //~ ERROR access to union field is unsafe + *foo.b = NonCopy; //~ ERROR access to union field is unsafe + foo.b = ManuallyDrop::new(NonCopy); + foo.a; //~ ERROR access to union field is unsafe + let foo = Foo { a: 42 }; + foo.b; //~ ERROR access to union field is unsafe + let mut foo = Foo { a: 42 }; + foo.b = foo.b; + //~^ ERROR access to union field is unsafe +} diff --git a/tests/ui/unsafe/union-assignop.thirunsafeck.stderr b/tests/ui/unsafe/union-assignop.thirunsafeck.stderr new file mode 100644 index 000000000..24b357e76 --- /dev/null +++ b/tests/ui/unsafe/union-assignop.thirunsafeck.stderr @@ -0,0 +1,51 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:19:5 + | +LL | foo.a += 5; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:20:6 + | +LL | *foo.b += NonCopy; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:21:6 + | +LL | *foo.b = NonCopy; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:23:5 + | +LL | foo.a; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:25:5 + | +LL | foo.b; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-assignop.rs:27:13 + | +LL | foo.b = foo.b; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/union-modification.rs b/tests/ui/unsafe/union-modification.rs new file mode 100644 index 000000000..9a53ef908 --- /dev/null +++ b/tests/ui/unsafe/union-modification.rs @@ -0,0 +1,37 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +union Foo { + bar: i8, + _blah: isize, + _zst: (), +} + +struct FooHolder { + inner_foo: Foo +} + +fn do_nothing(_x: &mut Foo) {} + +pub fn main() { + let mut foo = Foo { bar: 5 }; + do_nothing(&mut foo); + foo.bar = 6; + unsafe { foo.bar += 1; } + assert_eq!(unsafe { foo.bar }, 7); + unsafe { + let Foo { bar: inner } = foo; + assert_eq!(inner, 7); + } + + let foo = Foo { bar: 5 }; + let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo }; + + let (_foo2, _random) = (foo, 42); + + let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } }; + foo_holder.inner_foo.bar = 4; + assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4); + drop(foo_holder); +} diff --git a/tests/ui/unsafe/union.mir.stderr b/tests/ui/unsafe/union.mir.stderr new file mode 100644 index 000000000..787714cdd --- /dev/null +++ b/tests/ui/unsafe/union.mir.stderr @@ -0,0 +1,19 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:30:20 + | +LL | Foo { bar: _a } => {}, + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:32:11 + | +LL | match foo { + | ^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/union.rs b/tests/ui/unsafe/union.rs new file mode 100644 index 000000000..4338d78ea --- /dev/null +++ b/tests/ui/unsafe/union.rs @@ -0,0 +1,53 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +union Foo { + bar: i8, + zst: (), + pizza: Pizza, +} + +#[derive(Clone, Copy)] +struct Pizza { + topping: Option +} + +#[allow(dead_code)] +#[derive(Clone, Copy)] +enum PizzaTopping { + Cheese, + Pineapple, +} + +fn do_nothing(_x: &mut Foo) {} + +pub fn main() { + let mut foo = Foo { bar: 5 }; + do_nothing(&mut foo); + + // This is UB, so this test isn't run + match foo { + Foo { bar: _a } => {}, //~ ERROR access to union field is unsafe + } + match foo { //[mir]~ ERROR access to union field is unsafe + Foo { + pizza: Pizza { //[thir]~ ERROR access to union field is unsafe + topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None + } + } => {}, + } + + // MIR unsafeck incorrectly thinks that no unsafe block is needed to do these + match foo { + Foo { zst: () } => {}, //[thir]~ ERROR access to union field is unsafe + } + match foo { + Foo { pizza: Pizza { .. } } => {}, //[thir]~ ERROR access to union field is unsafe + } + + // binding to wildcard is okay + match foo { + Foo { bar: _ } => {}, + } + let Foo { bar: _ } = foo; +} diff --git a/tests/ui/unsafe/union.thir.stderr b/tests/ui/unsafe/union.thir.stderr new file mode 100644 index 000000000..e1a1bd634 --- /dev/null +++ b/tests/ui/unsafe/union.thir.stderr @@ -0,0 +1,38 @@ +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:30:20 + | +LL | Foo { bar: _a } => {}, + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:34:20 + | +LL | pizza: Pizza { + | ____________________^ +LL | | topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None +LL | | } + | |_____________^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:42:20 + | +LL | Foo { zst: () } => {}, + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union.rs:45:22 + | +LL | Foo { pizza: Pizza { .. } } => {}, + | ^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/union_access_through_block.rs b/tests/ui/unsafe/union_access_through_block.rs new file mode 100644 index 000000000..e4c0976b8 --- /dev/null +++ b/tests/ui/unsafe/union_access_through_block.rs @@ -0,0 +1,18 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +pub struct Foo { a: bool } + +pub union Bar { + a: Foo, + b: u32, +} +pub fn baz(mut bar: Bar) { + unsafe { + { bar.a }.a = true; + } +} + +fn main() {} diff --git a/tests/ui/unsafe/union_destructure.mir.stderr b/tests/ui/unsafe/union_destructure.mir.stderr new file mode 100644 index 000000000..818f5ce03 --- /dev/null +++ b/tests/ui/unsafe/union_destructure.mir.stderr @@ -0,0 +1,16 @@ +warning: unnecessary `unsafe` block + --> $DIR/union_destructure.rs:35:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: `#[warn(unused_unsafe)]` on by default + +warning: unnecessary `unsafe` block + --> $DIR/union_destructure.rs:41:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + diff --git a/tests/ui/unsafe/union_destructure.rs b/tests/ui/unsafe/union_destructure.rs new file mode 100644 index 000000000..6c88344b5 --- /dev/null +++ b/tests/ui/unsafe/union_destructure.rs @@ -0,0 +1,51 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#[derive(Copy, Clone)] +#[allow(dead_code)] +struct Pie { + slices: u8, + size: u8, +} + +union Foo { + #[allow(dead_code)] + bar: i8, + baz: Pie +} + +fn main() { + let u = Foo { bar: 5 }; + let (Some(Foo { bar: _ }) | None) = Some(u); + let u = Foo { bar: 6 }; + let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u); + unsafe { + let u = Foo { bar: 7 }; + let (Foo { bar } | Foo { bar }) = u; + assert_eq!(bar, 7) + } + let u = Foo { bar: 8 }; + match Some(u) { + Some(Foo { bar: _ }) => 3, + None => 4, + }; + + let u = Foo { bar: 9 }; + unsafe { //[mir]~ WARNING unnecessary `unsafe` block + match u { + Foo { baz: Pie { .. } } => {}, + }; + } + let u = Foo { bar: 10 }; + unsafe { //[mir]~ WARNING unnecessary `unsafe` block + match u { + Foo { baz: Pie { slices: _, size: _ } } => {}, + }; + } + + let u = Foo { bar: 11 }; + match u { + Foo { baz: _ } => {}, + }; +} diff --git a/tests/ui/unsafe/union_wild_or_wild.rs b/tests/ui/unsafe/union_wild_or_wild.rs new file mode 100644 index 000000000..52a0a7abf --- /dev/null +++ b/tests/ui/unsafe/union_wild_or_wild.rs @@ -0,0 +1,12 @@ +// check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +union X { a: i8 } + +fn main() { + let x = X { a: 5 }; + match x { + X { a: _ | _ } => {}, + } +} diff --git a/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr b/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr new file mode 100644 index 000000000..62199e5a2 --- /dev/null +++ b/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr @@ -0,0 +1,20 @@ +error: unnecessary `unsafe` block + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9 + | +LL | unsafe { async {}.await; } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:13:5 + | +LL | unsafe { println!("foo"); } + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 2 previous errors + diff --git a/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs b/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs new file mode 100644 index 000000000..c1a327640 --- /dev/null +++ b/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs @@ -0,0 +1,14 @@ +// edition:2018 +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![deny(unused_unsafe)] + +fn main() { + let _ = async { + unsafe { async {}.await; } //~ ERROR unnecessary `unsafe` + }; + + // `format_args!` expands with a compiler-generated unsafe block + unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe` +} diff --git a/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr b/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr new file mode 100644 index 000000000..62199e5a2 --- /dev/null +++ b/tests/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr @@ -0,0 +1,20 @@ +error: unnecessary `unsafe` block + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9 + | +LL | unsafe { async {}.await; } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/unsafe-around-compiler-generated-unsafe.rs:13:5 + | +LL | unsafe { println!("foo"); } + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 2 previous errors + diff --git a/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr new file mode 100644 index 000000000..9abc51424 --- /dev/null +++ b/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-assign.rs:12:5 + | +LL | foo.0.0 = 0; + | ^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-assign.rs b/tests/ui/unsafe/unsafe-assign.rs new file mode 100644 index 000000000..15273165b --- /dev/null +++ b/tests/ui/unsafe/unsafe-assign.rs @@ -0,0 +1,25 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn nested_field() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + foo.0.0 = 0; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn block() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + { foo.0 }.0 = 0; + // ^ not unsafe because the result of the block expression is a new place +} + +fn main() {} diff --git a/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr new file mode 100644 index 000000000..9abc51424 --- /dev/null +++ b/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-assign.rs:12:5 + | +LL | foo.0.0 = 0; + | ^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-block-without-braces.rs b/tests/ui/unsafe/unsafe-block-without-braces.rs new file mode 100644 index 000000000..4e4611618 --- /dev/null +++ b/tests/ui/unsafe/unsafe-block-without-braces.rs @@ -0,0 +1,6 @@ +fn main() { + unsafe //{ + std::mem::transmute::(1.0); + //} +} +//~^^^ ERROR expected `{`, found `std` diff --git a/tests/ui/unsafe/unsafe-block-without-braces.stderr b/tests/ui/unsafe/unsafe-block-without-braces.stderr new file mode 100644 index 000000000..44f77b99c --- /dev/null +++ b/tests/ui/unsafe/unsafe-block-without-braces.stderr @@ -0,0 +1,15 @@ +error: expected `{`, found `std` + --> $DIR/unsafe-block-without-braces.rs:3:9 + | +LL | unsafe //{ + | ------ while parsing this `unsafe` expression +LL | std::mem::transmute::(1.0); + | ^^^ expected `{` + | +help: try placing this code inside a block + | +LL | { std::mem::transmute::(1.0); } + | + + + +error: aborting due to previous error + diff --git a/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr b/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr new file mode 100644 index 000000000..a20672249 --- /dev/null +++ b/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:12:13 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:32:13 + | +LL | let a = &mut foo.0[2]; + | ^^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:51:18 + | +LL | NonZero((a,)) => *a = 0, + | ^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-borrow.rs b/tests/ui/unsafe/unsafe-borrow.rs new file mode 100644 index 000000000..8dddc70be --- /dev/null +++ b/tests/ui/unsafe/unsafe-borrow.rs @@ -0,0 +1,56 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn tuple_struct() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + let a = &mut foo.0.0; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn slice() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero<'a, T>(&'a mut [T]); + + let mut nums = [1, 2, 3, 4]; + let mut foo = unsafe { NonZero(&mut nums[..]) }; + let a = &mut foo.0[2]; + // ^ not unsafe because there is an implicit dereference here +} + +fn array() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero([T; 4]); + + let nums = [1, 2, 3, 4]; + let mut foo = unsafe { NonZero(nums) }; + let a = &mut foo.0[2]; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn block() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let foo = unsafe { NonZero((1,)) }; + &mut { foo.0 }.0; + // ^ not unsafe because the result of the block expression is a new place +} + +fn mtch() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + match &mut foo { + NonZero((a,)) => *a = 0, + //~^ ERROR: mutation of layout constrained field is unsafe + } +} + +fn main() {} diff --git a/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr b/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr new file mode 100644 index 000000000..a20672249 --- /dev/null +++ b/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:12:13 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:32:13 + | +LL | let a = &mut foo.0[2]; + | ^^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:51:18 + | +LL | NonZero((a,)) => *a = 0, + | ^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-const-fn.mir.stderr b/tests/ui/unsafe/unsafe-const-fn.mir.stderr new file mode 100644 index 000000000..3031be720 --- /dev/null +++ b/tests/ui/unsafe/unsafe-const-fn.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unsafe-const-fn.rs:10:18 + | +LL | const VAL: u32 = dummy(0xFFFF); + | ^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-const-fn.rs b/tests/ui/unsafe/unsafe-const-fn.rs new file mode 100644 index 000000000..65e3acf30 --- /dev/null +++ b/tests/ui/unsafe/unsafe-const-fn.rs @@ -0,0 +1,15 @@ +// A quick test of 'unsafe const fn' functionality + +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +const unsafe fn dummy(v: u32) -> u32 { + !v +} + +const VAL: u32 = dummy(0xFFFF); +//~^ ERROR E0133 + +fn main() { + assert_eq!(VAL, 0xFFFF0000); +} diff --git a/tests/ui/unsafe/unsafe-const-fn.thir.stderr b/tests/ui/unsafe/unsafe-const-fn.thir.stderr new file mode 100644 index 000000000..1a77adf44 --- /dev/null +++ b/tests/ui/unsafe/unsafe-const-fn.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `dummy` is unsafe and requires unsafe function or block + --> $DIR/unsafe-const-fn.rs:10:18 + | +LL | const VAL: u32 = dummy(0xFFFF); + | ^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr new file mode 100644 index 000000000..fee645e41 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-assign-deref-ptr.rs:5:5 + | +LL | *p = 0; + | ^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.rs b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.rs new file mode 100644 index 000000000..a94e94375 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.rs @@ -0,0 +1,10 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +fn f(p: *mut u8) { + *p = 0; //~ ERROR dereference of raw pointer is unsafe + return; +} + +fn main() { +} diff --git a/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr new file mode 100644 index 000000000..bbe4a415b --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-assign-deref-ptr.rs:5:5 + | +LL | *p = 0; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-autoderef.rs b/tests/ui/unsafe/unsafe-fn-autoderef.rs new file mode 100644 index 000000000..60460fc6e --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-autoderef.rs @@ -0,0 +1,23 @@ +struct Rec { + f: isize +} + +fn f(p: *const Rec) -> isize { + + // Test that * ptrs do not autoderef. There is a deeper reason for + // prohibiting this, beyond making unsafe things annoying (which doesn't + // actually seem desirable to me). The deeper reason is that if you + // have a type like: + // + // enum foo = *foo; + // + // you end up with an infinite auto-deref chain, which is + // currently impossible (in all other cases, infinite auto-derefs + // are prohibited by various checks, such as that the enum is + // instantiable and so forth). + + return p.f; //~ ERROR no field `f` on type `*const Rec` +} + +fn main() { +} diff --git a/tests/ui/unsafe/unsafe-fn-autoderef.stderr b/tests/ui/unsafe/unsafe-fn-autoderef.stderr new file mode 100644 index 000000000..20a88c356 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-autoderef.stderr @@ -0,0 +1,11 @@ +error[E0609]: no field `f` on type `*const Rec` + --> $DIR/unsafe-fn-autoderef.rs:19:14 + | +LL | return p.f; + | --^ + | | + | help: `p` is a raw pointer; try dereferencing it: `(*p).f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr b/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr new file mode 100644 index 000000000..1d6fa4cbf --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-called-from-safe.rs:7:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-called-from-safe.rs b/tests/ui/unsafe/unsafe-fn-called-from-safe.rs new file mode 100644 index 000000000..55072dcc6 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-called-from-safe.rs @@ -0,0 +1,10 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +unsafe fn f() { return; } + +fn main() { + f(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `f` is unsafe +} diff --git a/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr b/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr new file mode 100644 index 000000000..206dbd90a --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-called-from-safe.rs:7:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr b/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr new file mode 100644 index 000000000..a26149924 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-deref-ptr.rs:5:12 + | +LL | return *p; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-deref-ptr.rs b/tests/ui/unsafe/unsafe-fn-deref-ptr.rs new file mode 100644 index 000000000..dc989535b --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-deref-ptr.rs @@ -0,0 +1,9 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +fn f(p: *const u8) -> u8 { + return *p; //~ ERROR dereference of raw pointer is unsafe +} + +fn main() { +} diff --git a/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr b/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr new file mode 100644 index 000000000..a26149924 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-deref-ptr.rs:5:12 + | +LL | return *p; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr b/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr new file mode 100644 index 000000000..b08a7109d --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-used-as-value.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-used-as-value.rs:8:5 + | +LL | x(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-fn-used-as-value.rs b/tests/ui/unsafe/unsafe-fn-used-as-value.rs new file mode 100644 index 000000000..9517598c7 --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-used-as-value.rs @@ -0,0 +1,11 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +unsafe fn f() { return; } + +fn main() { + let x = f; + x(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `f` is unsafe +} diff --git a/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr b/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr new file mode 100644 index 000000000..e81dd3b2b --- /dev/null +++ b/tests/ui/unsafe/unsafe-fn-used-as-value.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block + --> $DIR/unsafe-fn-used-as-value.rs:8:5 + | +LL | x(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-not-inherited.rs b/tests/ui/unsafe/unsafe-not-inherited.rs new file mode 100644 index 000000000..6d797caa0 --- /dev/null +++ b/tests/ui/unsafe/unsafe-not-inherited.rs @@ -0,0 +1,26 @@ +#![allow(unused, dead_code)] + +static mut FOO: u64 = 0; + +fn static_mod() { + unsafe {static BAR: u64 = FOO;} + //~^ ERROR: use of mutable static is unsafe + //~| NOTE: use of mutable static + //~| NOTE: mutable statics can be mutated by multiple threads + //~| NOTE: items do not inherit unsafety +} + +unsafe fn unsafe_call() {} +fn foo() { + unsafe { + //~^ NOTE: items do not inherit unsafety + fn bar() { + unsafe_call(); + //~^ ERROR: call to unsafe function + //~| NOTE: call to unsafe function + //~| NOTE: consult the function's documentation + } + } +} + +fn main() {} diff --git a/tests/ui/unsafe/unsafe-not-inherited.stderr b/tests/ui/unsafe/unsafe-not-inherited.stderr new file mode 100644 index 000000000..3bc5ca5c9 --- /dev/null +++ b/tests/ui/unsafe/unsafe-not-inherited.stderr @@ -0,0 +1,24 @@ +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/unsafe-not-inherited.rs:6:31 + | +LL | unsafe {static BAR: u64 = FOO;} + | ------ ^^^ use of mutable static + | | + | items do not inherit unsafety from separate enclosing items + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/unsafe-not-inherited.rs:18:13 + | +LL | unsafe { + | ------ items do not inherit unsafety from separate enclosing items +... +LL | unsafe_call(); + | ^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-subtyping.rs b/tests/ui/unsafe/unsafe-subtyping.rs new file mode 100644 index 000000000..a4b748a50 --- /dev/null +++ b/tests/ui/unsafe/unsafe-subtyping.rs @@ -0,0 +1,11 @@ +// Check that safe fns are not a subtype of unsafe fns. + +fn foo(x: Option) -> Option { + x //~ ERROR mismatched types +} + +fn bar(x: fn(i32)) -> unsafe fn(i32) { + x // OK, coercion! +} + +fn main() { } diff --git a/tests/ui/unsafe/unsafe-subtyping.stderr b/tests/ui/unsafe/unsafe-subtyping.stderr new file mode 100644 index 000000000..2db7cc312 --- /dev/null +++ b/tests/ui/unsafe/unsafe-subtyping.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/unsafe-subtyping.rs:4:5 + | +LL | fn foo(x: Option) -> Option { + | ---------------------- expected `Option` because of return type +LL | x + | ^ expected unsafe fn, found normal fn + | + = note: expected enum `Option` + found enum `Option` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsafe/unsafe-trait-impl.rs b/tests/ui/unsafe/unsafe-trait-impl.rs new file mode 100644 index 000000000..1fc84ca02 --- /dev/null +++ b/tests/ui/unsafe/unsafe-trait-impl.rs @@ -0,0 +1,14 @@ +// Check that safe fns are not a subtype of unsafe fns. + +trait Foo { + unsafe fn len(&self) -> u32; +} + +impl Foo for u32 { + fn len(&self) -> u32 { *self } + //~^ ERROR method `len` has an incompatible type for trait + //~| expected signature `unsafe fn(&u32) -> _` + //~| found signature `fn(&u32) -> _` +} + +fn main() { } diff --git a/tests/ui/unsafe/unsafe-trait-impl.stderr b/tests/ui/unsafe/unsafe-trait-impl.stderr new file mode 100644 index 000000000..18ba79404 --- /dev/null +++ b/tests/ui/unsafe/unsafe-trait-impl.stderr @@ -0,0 +1,17 @@ +error[E0053]: method `len` has an incompatible type for trait + --> $DIR/unsafe-trait-impl.rs:8:5 + | +LL | fn len(&self) -> u32 { *self } + | ^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn + | +note: type in trait + --> $DIR/unsafe-trait-impl.rs:4:5 + | +LL | unsafe fn len(&self) -> u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `unsafe fn(&u32) -> _` + found signature `fn(&u32) -> _` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr b/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr new file mode 100644 index 000000000..dcb84a80c --- /dev/null +++ b/tests/ui/unsafe/unsafe-unstable-const-fn.mir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/unsafe-unstable-const-fn.rs:10:5 + | +LL | *a == b + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-unstable-const-fn.rs b/tests/ui/unsafe/unsafe-unstable-const-fn.rs new file mode 100644 index 000000000..581b15cdf --- /dev/null +++ b/tests/ui/unsafe/unsafe-unstable-const-fn.rs @@ -0,0 +1,14 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + +#![stable(feature = "foo", since = "1.33.0")] +#![feature(staged_api)] + +#[stable(feature = "foo", since = "1.33.0")] +#[rustc_const_unstable(feature = "const_foo", issue = "none")] +const fn unstable(a: *const i32, b: i32) -> bool { + *a == b + //~^ dereference of raw pointer is unsafe +} + +fn main() {} diff --git a/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr b/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr new file mode 100644 index 000000000..dcb84a80c --- /dev/null +++ b/tests/ui/unsafe/unsafe-unstable-const-fn.thir.stderr @@ -0,0 +1,11 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/unsafe-unstable-const-fn.rs:10:5 + | +LL | *a == b + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsigned-literal-negation.rs b/tests/ui/unsigned-literal-negation.rs new file mode 100644 index 000000000..943c7f797 --- /dev/null +++ b/tests/ui/unsigned-literal-negation.rs @@ -0,0 +1,5 @@ +fn main() { + let x = -1 as usize; //~ ERROR: cannot apply unary operator `-` + let x = (-1) as usize; //~ ERROR: cannot apply unary operator `-` + let x: u32 = -1; //~ ERROR: cannot apply unary operator `-` +} diff --git a/tests/ui/unsigned-literal-negation.stderr b/tests/ui/unsigned-literal-negation.stderr new file mode 100644 index 000000000..0aaa8c3b7 --- /dev/null +++ b/tests/ui/unsigned-literal-negation.stderr @@ -0,0 +1,36 @@ +error[E0600]: cannot apply unary operator `-` to type `usize` + --> $DIR/unsigned-literal-negation.rs:2:13 + | +LL | let x = -1 as usize; + | ^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `usize`: `usize::MAX` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `usize` + --> $DIR/unsigned-literal-negation.rs:3:13 + | +LL | let x = (-1) as usize; + | ^^^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `usize`: `usize::MAX` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/unsigned-literal-negation.rs:4:18 + | +LL | let x: u32 = -1; + | ^^ + | | + | cannot apply unary operator `-` + | help: you may have meant the maximum value of `u32`: `u32::MAX` + | + = note: unsigned values cannot be negated + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/unsized-locals/autoderef.rs b/tests/ui/unsized-locals/autoderef.rs new file mode 100644 index 000000000..5dd5898c1 --- /dev/null +++ b/tests/ui/unsized-locals/autoderef.rs @@ -0,0 +1,49 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(unsized_locals, unsized_fn_params)] + +pub trait Foo { + fn foo(self) -> String; +} + +impl Foo for [char] { + fn foo(self) -> String { + self.iter().collect() + } +} + +impl Foo for str { + fn foo(self) -> String { + self.to_owned() + } +} + +impl Foo for dyn FnMut() -> String { + fn foo(mut self) -> String { + self() + } +} + +fn main() { + let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); + assert_eq!(&x.foo() as &str, "hello"); + + let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>; + assert_eq!(&x.foo() as &str, "hello"); + + let x = "hello".to_owned().into_boxed_str(); + assert_eq!(&x.foo() as &str, "hello"); + + let x = *("hello".to_owned().into_boxed_str()); + assert_eq!(&x.foo() as &str, "hello"); + + let x = "hello".to_owned().into_boxed_str(); + assert_eq!(&x.foo() as &str, "hello"); + + let x = *(Box::new(|| "hello".to_owned()) as Box String>); + assert_eq!(&x.foo() as &str, "hello"); + + let x = Box::new(|| "hello".to_owned()) as Box String>; + assert_eq!(&x.foo() as &str, "hello"); +} diff --git a/tests/ui/unsized-locals/auxiliary/ufuncs.rs b/tests/ui/unsized-locals/auxiliary/ufuncs.rs new file mode 100644 index 000000000..5954abf3a --- /dev/null +++ b/tests/ui/unsized-locals/auxiliary/ufuncs.rs @@ -0,0 +1,3 @@ +#![feature(unsized_locals, unsized_fn_params)] + +pub fn udrop(_x: T) {} diff --git a/tests/ui/unsized-locals/borrow-after-move.rs b/tests/ui/unsized-locals/borrow-after-move.rs new file mode 100644 index 000000000..ad73b720f --- /dev/null +++ b/tests/ui/unsized-locals/borrow-after-move.rs @@ -0,0 +1,43 @@ +#![feature(unsized_locals, unsized_fn_params)] +//~^ WARN the feature `unsized_locals` is incomplete + +pub trait Foo { + fn foo(self) -> String; +} + +impl Foo for str { + fn foo(self) -> String { + self.to_owned() + } +} + +fn drop_unsized(_: T) {} + +fn main() { + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + drop_unsized(y); + println!("{}", &x); + //~^ERROR borrow of moved value + println!("{}", &y); + //~^ERROR borrow of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + y.foo(); + println!("{}", &x); + //~^ERROR borrow of moved value + println!("{}", &y); + //~^ERROR borrow of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + x.foo(); + println!("{}", &x); + //~^ERROR borrow of moved value + } +} diff --git a/tests/ui/unsized-locals/borrow-after-move.stderr b/tests/ui/unsized-locals/borrow-after-move.stderr new file mode 100644 index 000000000..9e3c345dd --- /dev/null +++ b/tests/ui/unsized-locals/borrow-after-move.stderr @@ -0,0 +1,85 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/borrow-after-move.rs:1:12 + | +LL | #![feature(unsized_locals, unsized_fn_params)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrow-after-move.rs:21:24 + | +LL | let y = *x; + | -- value moved here +LL | drop_unsized(y); +LL | println!("{}", &x); + | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `y` + --> $DIR/borrow-after-move.rs:23:24 + | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait +LL | drop_unsized(y); + | - value moved here +... +LL | println!("{}", &y); + | ^^ value borrowed here after move + | +note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary + --> $DIR/borrow-after-move.rs:14:31 + | +LL | fn drop_unsized(_: T) {} + | ------------ ^ this parameter takes ownership of the value + | | + | in this function + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrow-after-move.rs:31:24 + | +LL | let y = *x; + | -- value moved here +LL | y.foo(); +LL | println!("{}", &x); + | ^^ value borrowed here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `y` + --> $DIR/borrow-after-move.rs:33:24 + | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait +LL | y.foo(); + | ----- `y` moved due to this method call +... +LL | println!("{}", &y); + | ^^ value borrowed here after move + | +note: `Foo::foo` takes ownership of the receiver `self`, which moves `y` + --> $DIR/borrow-after-move.rs:5:12 + | +LL | fn foo(self) -> String; + | ^^^^ + +error[E0382]: borrow of moved value: `x` + --> $DIR/borrow-after-move.rs:40:24 + | +LL | let x = "hello".to_owned().into_boxed_str(); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | x.foo(); + | - value moved here +LL | println!("{}", &x); + | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x.clone().foo(); + | ++++++++ + +error: aborting due to 5 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/unsized-locals/box-fnonce.rs b/tests/ui/unsized-locals/box-fnonce.rs new file mode 100644 index 000000000..8b2f9b4c9 --- /dev/null +++ b/tests/ui/unsized-locals/box-fnonce.rs @@ -0,0 +1,10 @@ +// run-pass + +fn call_it(f: Box T>) -> T { + f() +} + +fn main() { + let s = "hello".to_owned(); + assert_eq!(&call_it(Box::new(|| s)) as &str, "hello"); +} diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs b/tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs new file mode 100644 index 000000000..b9881defa --- /dev/null +++ b/tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs @@ -0,0 +1,25 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +struct A; + +impl Foo for A { + fn foo(self) -> String { + format!("hello") + } +} + +fn main() { + let x = *(Box::new(A) as Box); + assert_eq!(x.foo(), format!("hello")); + + // I'm not sure whether we want this to work + let x = Box::new(A) as Box; + assert_eq!(x.foo(), format!("hello")); +} diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs b/tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs new file mode 100644 index 000000000..957991f85 --- /dev/null +++ b/tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(unsized_locals, unsized_fn_params)] + +pub trait Foo { + fn foo(self) -> String { + format!("hello") + } +} + +struct A; + +impl Foo for A {} + +fn main() { + let x = *(Box::new(A) as Box); + assert_eq!(x.foo(), format!("hello")); + + // I'm not sure whether we want this to work + let x = Box::new(A) as Box; + assert_eq!(x.foo(), format!("hello")); +} diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.rs b/tests/ui/unsized-locals/by-value-trait-object-safety.rs new file mode 100644 index 000000000..d0ba6944a --- /dev/null +++ b/tests/ui/unsized-locals/by-value-trait-object-safety.rs @@ -0,0 +1,22 @@ +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete + +pub trait Foo { + fn foo(self) -> String + where + Self: Sized; +} + +struct A; + +impl Foo for A { + fn foo(self) -> String { + format!("hello") + } +} + +fn main() { + let x = *(Box::new(A) as Box); + x.foo(); + //~^ERROR the `foo` method cannot be invoked on a trait object +} diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr b/tests/ui/unsized-locals/by-value-trait-object-safety.stderr new file mode 100644 index 000000000..4f13ec7ac --- /dev/null +++ b/tests/ui/unsized-locals/by-value-trait-object-safety.stderr @@ -0,0 +1,20 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/by-value-trait-object-safety.rs:1:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: the `foo` method cannot be invoked on a trait object + --> $DIR/by-value-trait-object-safety.rs:20:7 + | +LL | Self: Sized; + | ----- this has a `Sized` requirement +... +LL | x.foo(); + | ^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/unsized-locals/double-move.rs b/tests/ui/unsized-locals/double-move.rs new file mode 100644 index 000000000..9e46ef9be --- /dev/null +++ b/tests/ui/unsized-locals/double-move.rs @@ -0,0 +1,54 @@ +#![feature(unsized_locals, unsized_fn_params)] +//~^ WARN the feature `unsized_locals` is incomplete + +pub trait Foo { + fn foo(self) -> String; +} + +impl Foo for str { + fn foo(self) -> String { + self.to_owned() + } +} + +fn drop_unsized(_: T) {} + +fn main() { + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + drop_unsized(y); + drop_unsized(y); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let _y = *x; + drop_unsized(x); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + drop_unsized(x); + let _y = *x; //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let y = *x; + y.foo(); + y.foo(); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + let _y = *x; + x.foo(); //~ERROR use of moved value + } + + { + let x = "hello".to_owned().into_boxed_str(); + x.foo(); + let _y = *x; //~ERROR use of moved value + } +} diff --git a/tests/ui/unsized-locals/double-move.stderr b/tests/ui/unsized-locals/double-move.stderr new file mode 100644 index 000000000..49b906bbe --- /dev/null +++ b/tests/ui/unsized-locals/double-move.stderr @@ -0,0 +1,86 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/double-move.rs:1:12 + | +LL | #![feature(unsized_locals, unsized_fn_params)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0382]: use of moved value: `y` + --> $DIR/double-move.rs:21:22 + | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait +LL | drop_unsized(y); + | - value moved here +LL | drop_unsized(y); + | ^ value used here after move + | +note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary + --> $DIR/double-move.rs:14:31 + | +LL | fn drop_unsized(_: T) {} + | ------------ ^ this parameter takes ownership of the value + | | + | in this function + +error[E0382]: use of moved value: `x` + --> $DIR/double-move.rs:27:22 + | +LL | let _y = *x; + | -- value moved here +LL | drop_unsized(x); + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:33:18 + | +LL | let x = "hello".to_owned().into_boxed_str(); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | drop_unsized(x); + | - value moved here +LL | let _y = *x; + | ^^ value used here after move + +error[E0382]: use of moved value: `y` + --> $DIR/double-move.rs:40:9 + | +LL | let y = *x; + | - move occurs because `y` has type `str`, which does not implement the `Copy` trait +LL | y.foo(); + | ----- `y` moved due to this method call +LL | y.foo(); + | ^ value used here after move + | +note: `Foo::foo` takes ownership of the receiver `self`, which moves `y` + --> $DIR/double-move.rs:5:12 + | +LL | fn foo(self) -> String; + | ^^^^ + +error[E0382]: use of moved value: `x` + --> $DIR/double-move.rs:46:9 + | +LL | let _y = *x; + | -- value moved here +LL | x.foo(); + | ^ value used here after move + | + = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `*x` + --> $DIR/double-move.rs:52:18 + | +LL | let x = "hello".to_owned().into_boxed_str(); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | x.foo(); + | - value moved here +LL | let _y = *x; + | ^^ value used here after move + +error: aborting due to 6 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs new file mode 100644 index 000000000..635d34f82 --- /dev/null +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs @@ -0,0 +1,8 @@ +#![feature(unsized_locals)] +//~^ WARN the feature `unsized_locals` is incomplete + +struct Test([i32]); + +fn main() { + let _x: fn(_) -> Test = Test; +} //~^the size for values of type `[i32]` cannot be known at compilation time diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr new file mode 100644 index 000000000..b6002cf89 --- /dev/null +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr @@ -0,0 +1,22 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-30276-feature-flagged.rs:1:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-30276-feature-flagged.rs:7:29 + | +LL | let _x: fn(_) -> Test = Test; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-30276.rs b/tests/ui/unsized-locals/issue-30276.rs new file mode 100644 index 000000000..9c4bf062a --- /dev/null +++ b/tests/ui/unsized-locals/issue-30276.rs @@ -0,0 +1,5 @@ +struct Test([i32]); + +fn main() { + let _x: fn(_) -> Test = Test; +} //~^the size for values of type `[i32]` cannot be known at compilation time diff --git a/tests/ui/unsized-locals/issue-30276.stderr b/tests/ui/unsized-locals/issue-30276.stderr new file mode 100644 index 000000000..8cccbd792 --- /dev/null +++ b/tests/ui/unsized-locals/issue-30276.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/issue-30276.rs:4:29 + | +LL | let _x: fn(_) -> Test = Test; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.rs b/tests/ui/unsized-locals/issue-50940-with-feature.rs new file mode 100644 index 000000000..63b0e830b --- /dev/null +++ b/tests/ui/unsized-locals/issue-50940-with-feature.rs @@ -0,0 +1,8 @@ +#![feature(unsized_locals, unsized_fn_params)] +//~^ WARN the feature `unsized_locals` is incomplete + +fn main() { + struct A(X); + A as fn(str) -> A; + //~^ERROR the size for values of type `str` cannot be known at compilation time +} diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr new file mode 100644 index 000000000..8bbe317ec --- /dev/null +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -0,0 +1,26 @@ +warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-50940-with-feature.rs:1:12 + | +LL | #![feature(unsized_locals, unsized_fn_params)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #48055 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-50940-with-feature.rs:6:5 + | +LL | A as fn(str) -> A; + | ^ doesn't have a size known at compile-time + | + = help: within `A`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `A` + --> $DIR/issue-50940-with-feature.rs:5:12 + | +LL | struct A(X); + | ^ + = note: the return type of a function must have a statically known size + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-50940.rs b/tests/ui/unsized-locals/issue-50940.rs new file mode 100644 index 000000000..7ba809b7e --- /dev/null +++ b/tests/ui/unsized-locals/issue-50940.rs @@ -0,0 +1,5 @@ +fn main() { + struct A(X); + A as fn(str) -> A; + //~^ERROR the size for values of type `str` cannot be known at compilation time +} diff --git a/tests/ui/unsized-locals/issue-50940.stderr b/tests/ui/unsized-locals/issue-50940.stderr new file mode 100644 index 000000000..8f09b460e --- /dev/null +++ b/tests/ui/unsized-locals/issue-50940.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-50940.rs:3:5 + | +LL | A as fn(str) -> A; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/reference-unsized-locals.rs b/tests/ui/unsized-locals/reference-unsized-locals.rs new file mode 100644 index 000000000..4e887f327 --- /dev/null +++ b/tests/ui/unsized-locals/reference-unsized-locals.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(unsized_locals)] + +fn main() { + let foo: Box<[u8]> = Box::new(*b"foo"); + let foo: [u8] = *foo; + assert_eq!(&foo, b"foo" as &[u8]); +} diff --git a/tests/ui/unsized-locals/simple-unsized-locals.rs b/tests/ui/unsized-locals/simple-unsized-locals.rs new file mode 100644 index 000000000..02b7c299a --- /dev/null +++ b/tests/ui/unsized-locals/simple-unsized-locals.rs @@ -0,0 +1,9 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(unsized_locals)] + +fn main() { + let foo: Box<[u8]> = Box::new(*b"foo"); + let _foo: [u8] = *foo; +} diff --git a/tests/ui/unsized-locals/suggest-borrow.rs b/tests/ui/unsized-locals/suggest-borrow.rs new file mode 100644 index 000000000..086948579 --- /dev/null +++ b/tests/ui/unsized-locals/suggest-borrow.rs @@ -0,0 +1,7 @@ +fn main() { + let x: [u8] = vec!(1, 2, 3)[..]; //~ ERROR E0277 + let x: &[u8] = vec!(1, 2, 3)[..]; //~ ERROR E0308 + let x: [u8] = &vec!(1, 2, 3)[..]; //~ ERROR E0308 + //~^ ERROR E0277 + let x: &[u8] = &vec!(1, 2, 3)[..]; +} diff --git a/tests/ui/unsized-locals/suggest-borrow.stderr b/tests/ui/unsized-locals/suggest-borrow.stderr new file mode 100644 index 000000000..08745eab2 --- /dev/null +++ b/tests/ui/unsized-locals/suggest-borrow.stderr @@ -0,0 +1,60 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:2:9 + | +LL | let x: [u8] = vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | + + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:3:20 + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | expected `&[u8]`, found slice `[{integer}]` + | | help: consider borrowing here: `&vec!(1, 2, 3)[..]` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:4:19 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ---- ^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `&[{integer}]` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let x: [u8] = &vec!(1, 2, 3)[..]; +LL + let x: [u8] = vec!(1, 2, 3)[..]; + | +help: alternatively, consider changing the type annotation + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:4:9 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/unsized-exprs-rpass.rs b/tests/ui/unsized-locals/unsized-exprs-rpass.rs new file mode 100644 index 000000000..175b02fcb --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs-rpass.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(incomplete_features, unused_braces, unused_parens)] +#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)] + +struct A(#[allow(unused_tuple_struct_fields)] X); + +fn udrop(_x: T) {} +fn foo() -> Box<[u8]> { + Box::new(*b"foo") +} +fn tfoo() -> Box<(i32, [u8])> { + Box::new((42, *b"foo")) +} +fn afoo() -> Box> { + Box::new(A(*b"foo")) +} + +impl std::ops::Add for A<[u8]> { + type Output = (); + fn add(self, _rhs: i32) -> Self::Output {} +} + +fn main() { + udrop::<[u8]>(loop { + break *foo(); + }); + udrop::<[u8]>(if true { *foo() } else { *foo() }); + udrop::<[u8]>({ *foo() }); + udrop::<[u8]>((*foo())); + udrop::<[u8]>((*tfoo()).1); + *afoo() + 42; + udrop as fn([u8]); +} diff --git a/tests/ui/unsized-locals/unsized-exprs.rs b/tests/ui/unsized-locals/unsized-exprs.rs new file mode 100644 index 000000000..1729b9ffa --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs.rs @@ -0,0 +1,28 @@ +#![feature(unsized_tuple_coercion, unsized_fn_params)] + +struct A(X); + +fn udrop(_x: T) {} +fn foo() -> Box<[u8]> { + Box::new(*b"foo") +} +fn tfoo() -> Box<(i32, [u8])> { + Box::new((42, *b"foo")) +} +fn afoo() -> Box> { + Box::new(A(*b"foo")) +} + +impl std::ops::Add for A<[u8]> { + type Output = (); + fn add(self, _rhs: i32) -> Self::Output {} +} + +fn main() { + udrop::<(i32, [u8])>((42, *foo())); + //~^ERROR E0277 + udrop::>(A { 0: *foo() }); + //~^ERROR E0277 + udrop::>(A(*foo())); + //~^ERROR E0277 +} diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr new file mode 100644 index 000000000..a7f57e3fd --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs.stderr @@ -0,0 +1,41 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:22:26 + | +LL | udrop::<(i32, [u8])>((42, *foo())); + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `({integer}, [u8])` + = note: tuples must have a statically known size to be initialized + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:24:22 + | +LL | udrop::>(A { 0: *foo() }); + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `A<[u8]>` + --> $DIR/unsized-exprs.rs:3:8 + | +LL | struct A(X); + | ^ + = note: structs must have a statically known size to be initialized + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs.rs:26:22 + | +LL | udrop::>(A(*foo())); + | ^ doesn't have a size known at compile-time + | + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `A<[u8]>` + --> $DIR/unsized-exprs.rs:3:8 + | +LL | struct A(X); + | ^ + = note: the return type of a function must have a statically known size + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/unsized-exprs2.rs b/tests/ui/unsized-locals/unsized-exprs2.rs new file mode 100644 index 000000000..127d8717e --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs2.rs @@ -0,0 +1,24 @@ +#![feature(unsized_tuple_coercion, unsized_fn_params)] + +struct A(X); + +fn udrop(_x: T) {} +fn foo() -> Box<[u8]> { + Box::new(*b"foo") +} +fn tfoo() -> Box<(i32, [u8])> { + Box::new((42, *b"foo")) +} +fn afoo() -> Box> { + Box::new(A(*b"foo")) +} + +impl std::ops::Add for A<[u8]> { + type Output = (); + fn add(self, _rhs: i32) -> Self::Output {} +} + +fn main() { + udrop::<[u8]>(foo()[..]); + //~^ERROR cannot move out of type `[u8]`, a non-copy slice +} diff --git a/tests/ui/unsized-locals/unsized-exprs2.stderr b/tests/ui/unsized-locals/unsized-exprs2.stderr new file mode 100644 index 000000000..88269f237 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs2.stderr @@ -0,0 +1,12 @@ +error[E0508]: cannot move out of type `[u8]`, a non-copy slice + --> $DIR/unsized-exprs2.rs:22:5 + | +LL | udrop::<[u8]>(foo()[..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot move out of here + | move occurs because value has type `[u8]`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/unsized-locals/unsized-exprs3.rs b/tests/ui/unsized-locals/unsized-exprs3.rs new file mode 100644 index 000000000..2133b01e0 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs3.rs @@ -0,0 +1,10 @@ +// aux-build:ufuncs.rs + +extern crate ufuncs; + +use ufuncs::udrop; + +fn main() { + udrop as fn([u8]); + //~^ERROR E0277 +} diff --git a/tests/ui/unsized-locals/unsized-exprs3.stderr b/tests/ui/unsized-locals/unsized-exprs3.stderr new file mode 100644 index 000000000..57d997822 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-exprs3.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-exprs3.rs:8:5 + | +LL | udrop as fn([u8]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/unsized-index.rs b/tests/ui/unsized-locals/unsized-index.rs new file mode 100644 index 000000000..e8782e894 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-index.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(unsized_fn_params)] + +use std::ops; +use std::ops::Index; + +pub struct A; + +impl ops::Index for A { + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + +impl ops::IndexMut for A { + fn index_mut(&mut self, _: str) -> &mut Self::Output { + panic!() + } +} + +fn main() { + let a = A {}; + let s = String::new().into_boxed_str(); + assert_eq!(&(), a.index(*s)); +} diff --git a/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs b/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs new file mode 100644 index 000000000..15263954c --- /dev/null +++ b/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.rs @@ -0,0 +1,15 @@ +#![feature(box_patterns)] +#![feature(unsized_fn_params)] + +#[allow(dead_code)] +fn f1(box box _b: Box>) {} +//~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277] + +fn f2((_x, _y): (i32, [i32])) {} +//~^ ERROR: the size for values of type `[i32]` cannot be known at compilation time [E0277] + +fn main() { + let foo: Box<[u8]> = Box::new(*b"foo"); + let _foo: [u8] = *foo; + //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time [E0277] +} diff --git a/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr new file mode 100644 index 000000000..ace5a8718 --- /dev/null +++ b/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr @@ -0,0 +1,37 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-locals-using-unsized-fn-params.rs:5:15 + | +LL | fn f1(box box _b: Box>) {} + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/unsized-locals-using-unsized-fn-params.rs:8:12 + | +LL | fn f2((_x, _y): (i32, [i32])) {} + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-locals-using-unsized-fn-params.rs:13:9 + | +LL | let _foo: [u8] = *foo; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let _foo: &[u8] = *foo; + | + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/unsized-parameters.rs b/tests/ui/unsized-locals/unsized-parameters.rs new file mode 100644 index 000000000..a1b772a7e --- /dev/null +++ b/tests/ui/unsized-locals/unsized-parameters.rs @@ -0,0 +1,13 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(unsized_fn_params)] + +pub fn f0(_f: dyn FnOnce()) {} +pub fn f1(_s: str) {} +pub fn f2(_x: i32, _y: [i32]) {} + +fn main() { + let foo = "foo".to_string().into_boxed_str(); + f1(*foo); +} diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.rs b/tests/ui/unsized/box-instead-of-dyn-fn.rs new file mode 100644 index 000000000..2fa741bc1 --- /dev/null +++ b/tests/ui/unsized/box-instead-of-dyn-fn.rs @@ -0,0 +1,15 @@ +use std::fmt::Debug; + +// Test to suggest boxing the return type, and the closure branch of the `if` + +fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { + //~^ ERROR return type cannot have an unboxed trait object + if a % 2 == 0 { + move || println!("{a}") + } else { + Box::new(move || println!("{}", b)) + //~^ ERROR `if` and `else` have incompatible types + } +} + +fn main() {} diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr new file mode 100644 index 000000000..c96c59afc --- /dev/null +++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr @@ -0,0 +1,42 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/box-instead-of-dyn-fn.rs:10:9 + | +LL | / if a % 2 == 0 { +LL | | move || println!("{a}") + | | ----------------------- + | | | + | | the expected closure + | | expected because of this +LL | | } else { +LL | | Box::new(move || println!("{}", b)) + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found struct `Box` +LL | | +LL | | } + | |_____- `if` and `else` have incompatible types + | + = note: expected closure `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:16]` + found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:25]>` + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/box-instead-of-dyn-fn.rs:5:56 + | +LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on trait objects, see + = note: if all the returned values were of the same type you could use `impl Fn() + 'a` as the return type + = note: for information on `impl Trait`, see + = note: you can create a new `enum` with a variant for each returned type +help: return a boxed trait object instead + | +LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box { + | ++++ + +help: ... and box this value + | +LL | Box::new(move || println!("{a}")) + | +++++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0746. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/unsized/issue-30355.rs b/tests/ui/unsized/issue-30355.rs new file mode 100644 index 000000000..6ff5b37f6 --- /dev/null +++ b/tests/ui/unsized/issue-30355.rs @@ -0,0 +1,9 @@ +pub struct X([u8]); + +pub static Y: &'static X = { + const Y: &'static [u8] = b""; + &X(*Y) + //~^ ERROR E0277 +}; + +fn main() {} diff --git a/tests/ui/unsized/issue-30355.stderr b/tests/ui/unsized/issue-30355.stderr new file mode 100644 index 000000000..71bbdf5de --- /dev/null +++ b/tests/ui/unsized/issue-30355.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-30355.rs:5:8 + | +LL | &X(*Y) + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-40231-1.rs b/tests/ui/unsized/issue-40231-1.rs new file mode 100644 index 000000000..999399ec8 --- /dev/null +++ b/tests/ui/unsized/issue-40231-1.rs @@ -0,0 +1,54 @@ +// check-pass + +#![allow(dead_code)] + +trait Structure: Sized where E: Encoding { + type RefTarget: ?Sized; + type FfiPtr; + unsafe fn borrow_from_ffi_ptr<'a>(ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget>; +} + +enum Slice {} + +impl Structure for Slice where E: Encoding { + type RefTarget = [E::Unit]; + type FfiPtr = (*const E::FfiUnit, usize); + unsafe fn borrow_from_ffi_ptr<'a>(_ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget> { + panic!() + } +} + +trait Encoding { + type Unit: Unit; + type FfiUnit; +} + +trait Unit {} + +enum Utf16 {} + +impl Encoding for Utf16 { + type Unit = Utf16Unit; + type FfiUnit = u16; +} + +struct Utf16Unit(pub u16); + +impl Unit for Utf16Unit {} + +type SUtf16Str = SeStr; + +struct SeStr where S: Structure, E: Encoding { + _data: S::RefTarget, +} + +impl SeStr where S: Structure, E: Encoding { + pub unsafe fn from_ptr<'a>(_ptr: S::FfiPtr) -> Option<&'a Self> { + panic!() + } +} + +fn main() { + const TEXT_U16: &'static [u16] = &[]; + let _ = unsafe { SUtf16Str::from_ptr((TEXT_U16.as_ptr(), TEXT_U16.len())).unwrap() }; +} diff --git a/tests/ui/unsized/issue-40231-2.rs b/tests/ui/unsized/issue-40231-2.rs new file mode 100644 index 000000000..780433b28 --- /dev/null +++ b/tests/ui/unsized/issue-40231-2.rs @@ -0,0 +1,54 @@ +// check-pass + +#![allow(dead_code)] + +trait Structure: Sized where E: Encoding { + type RefTarget: ?Sized; + type FfiPtr; + unsafe fn borrow_from_ffi_ptr<'a>(ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget>; +} + +enum Slice {} + +impl Structure for Slice where E: Encoding { + type RefTarget = [E::Unit]; + type FfiPtr = (*const E::FfiUnit, usize); + unsafe fn borrow_from_ffi_ptr<'a>(_ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget> { + panic!() + } +} + +trait Encoding { + type Unit: Unit; + type FfiUnit; +} + +trait Unit {} + +enum Utf16 {} + +impl Encoding for Utf16 { + type Unit = Utf16Unit; + type FfiUnit = u16; +} + +struct Utf16Unit(pub u16); + +impl Unit for Utf16Unit {} + +struct SUtf16Str { + _data: >::RefTarget, +} + +impl SUtf16Str { + pub unsafe fn from_ptr<'a>(ptr: >::FfiPtr) + -> Option<&'a Self> { + std::mem::transmute::::Unit]>, _>( + >::borrow_from_ffi_ptr(ptr)) + } +} + +fn main() { + const TEXT_U16: &'static [u16] = &[]; + let _ = unsafe { SUtf16Str::from_ptr((TEXT_U16.as_ptr(), TEXT_U16.len())).unwrap() }; +} diff --git a/tests/ui/unsized/issue-71659.rs b/tests/ui/unsized/issue-71659.rs new file mode 100644 index 000000000..3524ca02b --- /dev/null +++ b/tests/ui/unsized/issue-71659.rs @@ -0,0 +1,32 @@ +#![feature(unsize)] + +use std::marker::Unsize; + +pub trait CastTo: Unsize { + fn cast_to(&self) -> &T; +} + +impl> CastTo for U { + fn cast_to(&self) -> &T { + self + } +} + +impl Cast for T {} +pub trait Cast { + fn cast(&self) -> &T + where + Self: CastTo, + { + self + } +} + +pub trait Foo: CastTo<[i32]> {} +impl Foo for [i32; 0] {} + +fn main() { + let x: &dyn Foo = &[]; + let x = x.cast::<[i32]>(); + //~^ ERROR: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied +} diff --git a/tests/ui/unsized/issue-71659.stderr b/tests/ui/unsized/issue-71659.stderr new file mode 100644 index 000000000..d7b95f557 --- /dev/null +++ b/tests/ui/unsized/issue-71659.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied + --> $DIR/issue-71659.rs:30:15 + | +LL | let x = x.cast::<[i32]>(); + | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` + | +note: required by a bound in `Cast::cast` + --> $DIR/issue-71659.rs:19:15 + | +LL | fn cast(&self) -> &T + | ---- required by a bound in this +LL | where +LL | Self: CastTo, + | ^^^^^^^^^ required by this bound in `Cast::cast` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-75707.rs b/tests/ui/unsized/issue-75707.rs new file mode 100644 index 000000000..9f04cdbb9 --- /dev/null +++ b/tests/ui/unsized/issue-75707.rs @@ -0,0 +1,17 @@ +pub trait Callback { + fn cb(); +} + +pub trait Processing { + type Call: Callback; +} + +fn f() { + P::Call::cb(); +} + +fn main() { + struct MyCall; + f::>(); + //~^ ERROR: the trait bound `MyCall: Callback` is not satisfied +} diff --git a/tests/ui/unsized/issue-75707.stderr b/tests/ui/unsized/issue-75707.stderr new file mode 100644 index 000000000..97618ed05 --- /dev/null +++ b/tests/ui/unsized/issue-75707.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `MyCall: Callback` is not satisfied + --> $DIR/issue-75707.rs:15:9 + | +LL | f::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall` + | +note: required by a bound in `f` + --> $DIR/issue-75707.rs:9:9 + | +LL | fn f() { + | ^^^^^^^^^^ required by this bound in `f` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-75899-but-gats.rs b/tests/ui/unsized/issue-75899-but-gats.rs new file mode 100644 index 000000000..5716817f4 --- /dev/null +++ b/tests/ui/unsized/issue-75899-but-gats.rs @@ -0,0 +1,21 @@ +// check-pass + +use std::fmt::Debug; +use std::marker::PhantomData; + +trait Foo { + type Gat<'a>: ?Sized where Self: 'a; +} + +struct Bar<'a, T: Foo + 'a>(T::Gat<'a>); + +struct Baz(PhantomData); + +impl Foo for Baz { + type Gat<'a> = T where Self: 'a; +} + +fn main() { + let x = Bar::<'_, Baz<()>>(()); + let y: &Bar<'_, Baz> = &x; +} diff --git a/tests/ui/unsized/issue-75899.rs b/tests/ui/unsized/issue-75899.rs new file mode 100644 index 000000000..abff17e11 --- /dev/null +++ b/tests/ui/unsized/issue-75899.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Trait {} +impl Trait for T {} + +trait Noop { + type Assoc: ?Sized; +} +impl Noop for T { + type Assoc = T; +} + +struct NoopNewtype(T::Assoc); +fn coerce_newtype(x: &NoopNewtype) -> &NoopNewtype { + x +} + +fn main() {} diff --git a/tests/ui/unsized/issue-91801.rs b/tests/ui/unsized/issue-91801.rs new file mode 100644 index 000000000..096b1a935 --- /dev/null +++ b/tests/ui/unsized/issue-91801.rs @@ -0,0 +1,19 @@ +pub struct Something; + +type Validator<'a> = dyn 'a + Send + Sync + Fn(&'a Something) -> Result<(), ()>; + +pub static ALL_VALIDATORS: &[(&'static str, &'static Validator)] = + &[("validate that credits and debits balance", &validate_something)]; + +fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { + //~^ ERROR return type cannot have an unboxed trait object + return Box::new(move |something: &'_ Something| -> Result<(), ()> { + first(something).or_else(|_| second(something)) + }); +} + +fn validate_something(_: &Something) -> Result<(), ()> { + Ok(()) +} + +fn main() {} diff --git a/tests/ui/unsized/issue-91801.stderr b/tests/ui/unsized/issue-91801.stderr new file mode 100644 index 000000000..8795aa168 --- /dev/null +++ b/tests/ui/unsized/issue-91801.stderr @@ -0,0 +1,15 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-91801.rs:8:77 + | +LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 10:70]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` + | +LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/unsized/issue-91803.rs b/tests/ui/unsized/issue-91803.rs new file mode 100644 index 000000000..c74897cc4 --- /dev/null +++ b/tests/ui/unsized/issue-91803.rs @@ -0,0 +1,8 @@ +trait Foo<'a> {} + +fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { + //~^ ERROR return type cannot have an unboxed trait object + return Box::new(panic!()); +} + +fn main() {} diff --git a/tests/ui/unsized/issue-91803.stderr b/tests/ui/unsized/issue-91803.stderr new file mode 100644 index 000000000..2dad9e892 --- /dev/null +++ b/tests/ui/unsized/issue-91803.stderr @@ -0,0 +1,15 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/issue-91803.rs:3:43 + | +LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: for information on `impl Trait`, see +help: use `impl Foo<'a>` as the return type, as all return paths are of type `Box<_>`, which implements `Foo<'a>` + | +LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> { + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0746`. diff --git a/tests/ui/unsized/issue-97732.rs b/tests/ui/unsized/issue-97732.rs new file mode 100644 index 000000000..72f765033 --- /dev/null +++ b/tests/ui/unsized/issue-97732.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(coerce_unsized)] + +// Ensure that unsizing structs that contain ZSTs at non-zero offsets don't ICE + +use std::ops::CoerceUnsized; + +#[repr(C)] +pub struct BoxWithZstTail(Box, ()); + +impl CoerceUnsized> for BoxWithZstTail where + Box: CoerceUnsized> +{ +} + +pub fn noop_dyn_upcast_with_zst_tail( + b: BoxWithZstTail, +) -> BoxWithZstTail { + b +} + +fn main() { + let original = "foo"; + let boxed = BoxWithZstTail(Box::new(original) as Box, ()); + let noop_upcasted = noop_dyn_upcast_with_zst_tail(boxed); + assert_eq!(original, noop_upcasted.0.to_string()); +} diff --git a/tests/ui/unsized/maybe-bounds-where-cpass.rs b/tests/ui/unsized/maybe-bounds-where-cpass.rs new file mode 100644 index 000000000..0e018cdab --- /dev/null +++ b/tests/ui/unsized/maybe-bounds-where-cpass.rs @@ -0,0 +1,9 @@ +// check-pass + +struct S(*const T) where T: ?Sized; + + +fn main() { + let u = vec![1, 2, 3]; + let _s: S<[u8]> = S(&u[..]); +} diff --git a/tests/ui/unsized/maybe-bounds-where.rs b/tests/ui/unsized/maybe-bounds-where.rs new file mode 100644 index 000000000..d7af0c424 --- /dev/null +++ b/tests/ui/unsized/maybe-bounds-where.rs @@ -0,0 +1,28 @@ +struct S1(T) where (T): ?Sized; +//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared + +struct S2(T) where u8: ?Sized; +//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared + +struct S3(T) where &'static T: ?Sized; +//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared + +trait Trait<'a> {} + +struct S4(T) where for<'a> T: ?Trait<'a>; +//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +//~| WARN default bound relaxed for a type parameter + +struct S5(*const T) where T: ?Trait<'static> + ?Sized; +//~^ ERROR type parameter has more than one relaxed default bound +//~| WARN default bound relaxed for a type parameter + +impl S1 { + fn f() where T: ?Sized {} + //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +} + +fn main() { + let u = vec![1, 2, 3]; + let _s: S5<[u8]> = S5(&u[..]); // OK +} diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/maybe-bounds-where.stderr new file mode 100644 index 000000000..39bc1b88e --- /dev/null +++ b/tests/ui/unsized/maybe-bounds-where.stderr @@ -0,0 +1,51 @@ +error: `?Trait` bounds are only permitted at the point where a type parameter is declared + --> $DIR/maybe-bounds-where.rs:1:28 + | +LL | struct S1(T) where (T): ?Sized; + | ^^^^^^ + +error: `?Trait` bounds are only permitted at the point where a type parameter is declared + --> $DIR/maybe-bounds-where.rs:4:27 + | +LL | struct S2(T) where u8: ?Sized; + | ^^^^^^ + +error: `?Trait` bounds are only permitted at the point where a type parameter is declared + --> $DIR/maybe-bounds-where.rs:7:35 + | +LL | struct S3(T) where &'static T: ?Sized; + | ^^^^^^ + +error: `?Trait` bounds are only permitted at the point where a type parameter is declared + --> $DIR/maybe-bounds-where.rs:12:34 + | +LL | struct S4(T) where for<'a> T: ?Trait<'a>; + | ^^^^^^^^^^ + +error: `?Trait` bounds are only permitted at the point where a type parameter is declared + --> $DIR/maybe-bounds-where.rs:21:21 + | +LL | fn f() where T: ?Sized {} + | ^^^^^^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/maybe-bounds-where.rs:12:11 + | +LL | struct S4(T) where for<'a> T: ?Trait<'a>; + | ^ + +error[E0203]: type parameter has more than one relaxed default bound, only one is supported + --> $DIR/maybe-bounds-where.rs:16:11 + | +LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; + | ^ + +warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported + --> $DIR/maybe-bounds-where.rs:16:11 + | +LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; + | ^ + +error: aborting due to 6 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/unsized/param-mentioned-by-different-field.rs b/tests/ui/unsized/param-mentioned-by-different-field.rs new file mode 100644 index 000000000..cda94b306 --- /dev/null +++ b/tests/ui/unsized/param-mentioned-by-different-field.rs @@ -0,0 +1,10 @@ +// We must not allow this with our current setup as `T` +// is mentioned both in the tail of `Foo` and by another +// field. +struct Foo(Box, T); + +fn main() { + let x: Foo<[u8; 1]> = Foo(Box::new([2]), [3]); + let y: &Foo<[u8]> = &x; //~ ERROR mismatched types + assert_eq!(y.0.len(), 1); +} diff --git a/tests/ui/unsized/param-mentioned-by-different-field.stderr b/tests/ui/unsized/param-mentioned-by-different-field.stderr new file mode 100644 index 000000000..d18fa6456 --- /dev/null +++ b/tests/ui/unsized/param-mentioned-by-different-field.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/param-mentioned-by-different-field.rs:8:25 + | +LL | let y: &Foo<[u8]> = &x; + | ---------- ^^ expected slice `[u8]`, found array `[u8; 1]` + | | + | expected due to this + | + = note: expected reference `&Foo<[u8]>` + found reference `&Foo<[u8; 1]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsized/return-unsized-from-trait-method.rs b/tests/ui/unsized/return-unsized-from-trait-method.rs new file mode 100644 index 000000000..f053f4b0a --- /dev/null +++ b/tests/ui/unsized/return-unsized-from-trait-method.rs @@ -0,0 +1,14 @@ +// regression test for #26376 + +trait Foo { + fn foo(&self) -> [u8]; +} + +fn foo(f: Option<&dyn Foo>) { + if let Some(f) = f { + let _ = f.foo(); + //~^ ERROR cannot move a value of type `[u8]` + } +} + +fn main() { foo(None) } diff --git a/tests/ui/unsized/return-unsized-from-trait-method.stderr b/tests/ui/unsized/return-unsized-from-trait-method.stderr new file mode 100644 index 000000000..671d40993 --- /dev/null +++ b/tests/ui/unsized/return-unsized-from-trait-method.stderr @@ -0,0 +1,9 @@ +error[E0161]: cannot move a value of type `[u8]` + --> $DIR/return-unsized-from-trait-method.rs:9:17 + | +LL | let _ = f.foo(); + | ^^^^^^^ the size of `[u8]` cannot be statically determined + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0161`. diff --git a/tests/ui/unsized/unchanged-param.rs b/tests/ui/unsized/unchanged-param.rs new file mode 100644 index 000000000..6bdc89310 --- /dev/null +++ b/tests/ui/unsized/unchanged-param.rs @@ -0,0 +1,11 @@ +// run-pass +// Test that we allow unsizing even if there is an unchanged param in the +// field getting unsized. +struct A(#[allow(unused_tuple_struct_fields)] T, B); +struct B(#[allow(unused_tuple_struct_fields)] T, U); + +fn main() { + let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1])); + let y: &A<[u32; 1], [u32]> = &x; + assert_eq!(y.1.1.len(), 1); +} diff --git a/tests/ui/unsized/unsized-bare-typaram.rs b/tests/ui/unsized/unsized-bare-typaram.rs new file mode 100644 index 000000000..e611da915 --- /dev/null +++ b/tests/ui/unsized/unsized-bare-typaram.rs @@ -0,0 +1,4 @@ +fn bar() { } +fn foo() { bar::() } +//~^ ERROR the size for values of type +fn main() { } diff --git a/tests/ui/unsized/unsized-bare-typaram.stderr b/tests/ui/unsized/unsized-bare-typaram.stderr new file mode 100644 index 000000000..1eff14be8 --- /dev/null +++ b/tests/ui/unsized/unsized-bare-typaram.stderr @@ -0,0 +1,22 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/unsized-bare-typaram.rs:2:29 + | +LL | fn foo() { bar::() } + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `bar` + --> $DIR/unsized-bare-typaram.rs:1:8 + | +LL | fn bar() { } + | ^ required by this bound in `bar` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn foo() { bar::() } +LL + fn foo() { bar::() } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-enum.rs b/tests/ui/unsized/unsized-enum.rs new file mode 100644 index 000000000..02ad1c878 --- /dev/null +++ b/tests/ui/unsized/unsized-enum.rs @@ -0,0 +1,11 @@ +fn is_sized() { } +fn not_sized() { } + +enum Foo { FooSome(U), FooNone } +fn foo1() { not_sized::>() } // Hunky dory. +fn foo2() { not_sized::>() } +//~^ ERROR the size for values of type +// +// Not OK: `T` is not sized. + +fn main() { } diff --git a/tests/ui/unsized/unsized-enum.stderr b/tests/ui/unsized/unsized-enum.stderr new file mode 100644 index 000000000..5f2e22430 --- /dev/null +++ b/tests/ui/unsized/unsized-enum.stderr @@ -0,0 +1,29 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/unsized-enum.rs:6:36 + | +LL | fn foo2() { not_sized::>() } + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Foo` + --> $DIR/unsized-enum.rs:4:10 + | +LL | enum Foo { FooSome(U), FooNone } + | ^ required by this bound in `Foo` +help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box` + --> $DIR/unsized-enum.rs:4:10 + | +LL | enum Foo { FooSome(U), FooNone } + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `U: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn foo2() { not_sized::>() } +LL + fn foo2() { not_sized::>() } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-enum2.rs b/tests/ui/unsized/unsized-enum2.rs new file mode 100644 index 000000000..d589f5ae5 --- /dev/null +++ b/tests/ui/unsized/unsized-enum2.rs @@ -0,0 +1,74 @@ +use std::ops::Deref; + +// Due to aggressive error message deduplication, we require 20 *different* +// unsized types (even Path and [u8] are considered the "same"). + +trait Foo {} +trait Bar {} +trait FooBar {} +trait BarFoo {} + +trait PathHelper1 {} +trait PathHelper2 {} +trait PathHelper3 {} +trait PathHelper4 {} + +struct Path1(dyn PathHelper1); +struct Path2(dyn PathHelper2); +struct Path3(dyn PathHelper3); +struct Path4(dyn PathHelper4); + +enum E { + // parameter + VA(W), + //~^ ERROR the size for values of type + VB{x: X}, + //~^ ERROR the size for values of type + VC(isize, Y), + //~^ ERROR the size for values of type + VD{u: isize, x: Z}, + //~^ ERROR the size for values of type + + // slice / str + VE([u8]), + //~^ ERROR the size for values of type + VF{x: str}, + //~^ ERROR the size for values of type + VG(isize, [f32]), + //~^ ERROR the size for values of type + VH{u: isize, x: [u32]}, + //~^ ERROR the size for values of type + + // unsized struct + VI(Path1), + //~^ ERROR the size for values of type + VJ{x: Path2}, + //~^ ERROR the size for values of type + VK(isize, Path3), + //~^ ERROR the size for values of type + VL{u: isize, x: Path4}, + //~^ ERROR the size for values of type + + // plain trait + VM(dyn Foo), + //~^ ERROR the size for values of type + VN{x: dyn Bar}, + //~^ ERROR the size for values of type + VO(isize, dyn FooBar), + //~^ ERROR the size for values of type + VP{u: isize, x: dyn BarFoo}, + //~^ ERROR the size for values of type + + // projected + VQ(<&'static [i8] as Deref>::Target), + //~^ ERROR the size for values of type + VR{x: <&'static [char] as Deref>::Target}, + //~^ ERROR the size for values of type + VS(isize, <&'static [f64] as Deref>::Target), + //~^ ERROR the size for values of type + VT{u: isize, x: <&'static [i32] as Deref>::Target}, + //~^ ERROR the size for values of type +} + + +fn main() { } diff --git a/tests/ui/unsized/unsized-enum2.stderr b/tests/ui/unsized/unsized-enum2.stderr new file mode 100644 index 000000000..00b80327c --- /dev/null +++ b/tests/ui/unsized/unsized-enum2.stderr @@ -0,0 +1,411 @@ +error[E0277]: the size for values of type `W` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:23:8 + | +LL | enum E { + | - this type parameter needs to be `std::marker::Sized` +LL | // parameter +LL | VA(W), + | ^ doesn't have a size known at compile-time + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum E { +LL + enum E { + | +help: borrowed types always have a statically known size + | +LL | VA(&W), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VA(Box), + | ++++ + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:25:11 + | +LL | enum E { + | - this type parameter needs to be `std::marker::Sized` +... +LL | VB{x: X}, + | ^ doesn't have a size known at compile-time + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum E { +LL + enum E { + | +help: borrowed types always have a statically known size + | +LL | VB{x: &X}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VB{x: Box}, + | ++++ + + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:27:15 + | +LL | enum E { + | - this type parameter needs to be `std::marker::Sized` +... +LL | VC(isize, Y), + | ^ doesn't have a size known at compile-time + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum E { +LL + enum E { + | +help: borrowed types always have a statically known size + | +LL | VC(isize, &Y), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VC(isize, Box), + | ++++ + + +error[E0277]: the size for values of type `Z` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:29:21 + | +LL | enum E { + | - this type parameter needs to be `std::marker::Sized` +... +LL | VD{u: isize, x: Z}, + | ^ doesn't have a size known at compile-time + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum E { +LL + enum E { + | +help: borrowed types always have a statically known size + | +LL | VD{u: isize, x: &Z}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VD{u: isize, x: Box}, + | ++++ + + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:33:8 + | +LL | VE([u8]), + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VE(&[u8]), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VE(Box<[u8]>), + | ++++ + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:35:11 + | +LL | VF{x: str}, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VF{x: &str}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VF{x: Box}, + | ++++ + + +error[E0277]: the size for values of type `[f32]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:37:15 + | +LL | VG(isize, [f32]), + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[f32]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VG(isize, &[f32]), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VG(isize, Box<[f32]>), + | ++++ + + +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:39:21 + | +LL | VH{u: isize, x: [u32]}, + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VH{u: isize, x: &[u32]}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VH{u: isize, x: Box<[u32]>}, + | ++++ + + +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:53:8 + | +LL | VM(dyn Foo), + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VM(&dyn Foo), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VM(Box), + | ++++ + + +error[E0277]: the size for values of type `(dyn Bar + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:55:11 + | +LL | VN{x: dyn Bar}, + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Bar + 'static)` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VN{x: &dyn Bar}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VN{x: Box}, + | ++++ + + +error[E0277]: the size for values of type `(dyn FooBar + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:57:15 + | +LL | VO(isize, dyn FooBar), + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn FooBar + 'static)` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VO(isize, &dyn FooBar), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VO(isize, Box), + | ++++ + + +error[E0277]: the size for values of type `(dyn BarFoo + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:59:21 + | +LL | VP{u: isize, x: dyn BarFoo}, + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn BarFoo + 'static)` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VP{u: isize, x: &dyn BarFoo}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VP{u: isize, x: Box}, + | ++++ + + +error[E0277]: the size for values of type `[i8]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:63:8 + | +LL | VQ(<&'static [i8] as Deref>::Target), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i8]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VQ(&<&'static [i8] as Deref>::Target), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VQ(Box<<&'static [i8] as Deref>::Target>), + | ++++ + + +error[E0277]: the size for values of type `[char]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:65:11 + | +LL | VR{x: <&'static [char] as Deref>::Target}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[char]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VR{x: &<&'static [char] as Deref>::Target}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VR{x: Box<<&'static [char] as Deref>::Target>}, + | ++++ + + +error[E0277]: the size for values of type `[f64]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:67:15 + | +LL | VS(isize, <&'static [f64] as Deref>::Target), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[f64]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VS(isize, &<&'static [f64] as Deref>::Target), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VS(isize, Box<<&'static [f64] as Deref>::Target>), + | ++++ + + +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:69:21 + | +LL | VT{u: isize, x: <&'static [i32] as Deref>::Target}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VT{u: isize, x: &<&'static [i32] as Deref>::Target}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VT{u: isize, x: Box<<&'static [i32] as Deref>::Target>}, + | ++++ + + +error[E0277]: the size for values of type `(dyn PathHelper1 + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:43:8 + | +LL | VI(Path1), + | ^^^^^ doesn't have a size known at compile-time + | + = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)` +note: required because it appears within the type `Path1` + --> $DIR/unsized-enum2.rs:16:8 + | +LL | struct Path1(dyn PathHelper1); + | ^^^^^ + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VI(&Path1), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VI(Box), + | ++++ + + +error[E0277]: the size for values of type `(dyn PathHelper2 + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:45:11 + | +LL | VJ{x: Path2}, + | ^^^^^ doesn't have a size known at compile-time + | + = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)` +note: required because it appears within the type `Path2` + --> $DIR/unsized-enum2.rs:17:8 + | +LL | struct Path2(dyn PathHelper2); + | ^^^^^ + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VJ{x: &Path2}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VJ{x: Box}, + | ++++ + + +error[E0277]: the size for values of type `(dyn PathHelper3 + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:47:15 + | +LL | VK(isize, Path3), + | ^^^^^ doesn't have a size known at compile-time + | + = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)` +note: required because it appears within the type `Path3` + --> $DIR/unsized-enum2.rs:18:8 + | +LL | struct Path3(dyn PathHelper3); + | ^^^^^ + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VK(isize, &Path3), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VK(isize, Box), + | ++++ + + +error[E0277]: the size for values of type `(dyn PathHelper4 + 'static)` cannot be known at compilation time + --> $DIR/unsized-enum2.rs:49:21 + | +LL | VL{u: isize, x: Path4}, + | ^^^^^ doesn't have a size known at compile-time + | + = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)` +note: required because it appears within the type `Path4` + --> $DIR/unsized-enum2.rs:19:8 + | +LL | struct Path4(dyn PathHelper4); + | ^^^^^ + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | VL{u: isize, x: &Path4}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | VL{u: isize, x: Box}, + | ++++ + + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-fn-arg.fixed b/tests/ui/unsized/unsized-fn-arg.fixed new file mode 100644 index 000000000..fd9b159a4 --- /dev/null +++ b/tests/ui/unsized/unsized-fn-arg.fixed @@ -0,0 +1,6 @@ +// run-rustfix +#![crate_type="lib"] +#![allow(unused)] + +fn f(t: &T) {} +//~^ ERROR the size for values of type `T` cannot be known at compilation time diff --git a/tests/ui/unsized/unsized-fn-arg.rs b/tests/ui/unsized/unsized-fn-arg.rs new file mode 100644 index 000000000..9fc08bd6d --- /dev/null +++ b/tests/ui/unsized/unsized-fn-arg.rs @@ -0,0 +1,6 @@ +// run-rustfix +#![crate_type="lib"] +#![allow(unused)] + +fn f(t: T) {} +//~^ ERROR the size for values of type `T` cannot be known at compilation time diff --git a/tests/ui/unsized/unsized-fn-arg.stderr b/tests/ui/unsized/unsized-fn-arg.stderr new file mode 100644 index 000000000..404fa5291 --- /dev/null +++ b/tests/ui/unsized/unsized-fn-arg.stderr @@ -0,0 +1,22 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/unsized-fn-arg.rs:5:17 + | +LL | fn f(t: T) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f(t: T) {} +LL + fn f(t: T) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn f(t: &T) {} + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-fn-param.rs b/tests/ui/unsized/unsized-fn-param.rs new file mode 100644 index 000000000..32efc7e17 --- /dev/null +++ b/tests/ui/unsized/unsized-fn-param.rs @@ -0,0 +1,20 @@ +use std::convert::AsRef; +use std::path::Path; + +fn foo11(_bar: &dyn AsRef, _baz: &str) {} +fn foo12(_bar: &str, _baz: &dyn AsRef) {} + +fn foo21(_bar: &dyn AsRef, _baz: &str) {} +fn foo22(_bar: &str, _baz: &dyn AsRef) {} + +fn main() { + foo11("bar", &"baz"); //~ ERROR the size for values of type + foo11(&"bar", &"baz"); + foo12(&"bar", "baz"); //~ ERROR the size for values of type + foo12(&"bar", &"baz"); + + foo21("bar", &"baz"); //~ ERROR the size for values of type + foo21(&"bar", &"baz"); + foo22(&"bar", "baz"); //~ ERROR the size for values of type + foo22(&"bar", &"baz"); +} diff --git a/tests/ui/unsized/unsized-fn-param.stderr b/tests/ui/unsized/unsized-fn-param.stderr new file mode 100644 index 000000000..b47726054 --- /dev/null +++ b/tests/ui/unsized/unsized-fn-param.stderr @@ -0,0 +1,55 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-fn-param.rs:11:11 + | +LL | foo11("bar", &"baz"); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn AsRef` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` + | +LL | foo11(&"bar", &"baz"); + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-fn-param.rs:13:19 + | +LL | foo12(&"bar", "baz"); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn AsRef` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` + | +LL | foo12(&"bar", &"baz"); + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-fn-param.rs:16:11 + | +LL | foo21("bar", &"baz"); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn AsRef` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` + | +LL | foo21(&"bar", &"baz"); + | + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized-fn-param.rs:18:19 + | +LL | foo22(&"bar", "baz"); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: required for the cast from `str` to the object type `dyn AsRef` +help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` + | +LL | foo22(&"bar", &"baz"); + | + + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-inherent-impl-self-type.rs b/tests/ui/unsized/unsized-inherent-impl-self-type.rs new file mode 100644 index 000000000..8bdf80c94 --- /dev/null +++ b/tests/ui/unsized/unsized-inherent-impl-self-type.rs @@ -0,0 +1,11 @@ +// Test sized-ness checking in substitution in impls. + +// impl - struct + +struct S5(Y); + +impl S5 { + //~^ ERROR the size for values of type +} + +fn main() { } diff --git a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr new file mode 100644 index 000000000..a952aa063 --- /dev/null +++ b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -0,0 +1,29 @@ +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-inherent-impl-self-type.rs:7:17 + | +LL | impl S5 { + | - ^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `S5` + --> $DIR/unsized-inherent-impl-self-type.rs:5:11 + | +LL | struct S5(Y); + | ^ required by this bound in `S5` +help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` + --> $DIR/unsized-inherent-impl-self-type.rs:5:11 + | +LL | struct S5(Y); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `Y: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl S5 { +LL + impl S5 { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-struct.rs b/tests/ui/unsized/unsized-struct.rs new file mode 100644 index 000000000..bfa5aa0a5 --- /dev/null +++ b/tests/ui/unsized/unsized-struct.rs @@ -0,0 +1,18 @@ +fn is_sized() { } +fn not_sized() { } + +struct Foo { data: T } +fn foo1() { not_sized::>() } // Hunky dory. +fn foo2() { not_sized::>() } +//~^ ERROR the size for values of type +// +// Not OK: `T` is not sized. + +struct Bar { data: T } +fn bar1() { not_sized::>() } +fn bar2() { is_sized::>() } +//~^ ERROR the size for values of type +// +// Not OK: `Bar` is not sized, but it should be. + +fn main() { } diff --git a/tests/ui/unsized/unsized-struct.stderr b/tests/ui/unsized/unsized-struct.stderr new file mode 100644 index 000000000..dff1b0a51 --- /dev/null +++ b/tests/ui/unsized/unsized-struct.stderr @@ -0,0 +1,53 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/unsized-struct.rs:6:36 + | +LL | fn foo2() { not_sized::>() } + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `Foo` + --> $DIR/unsized-struct.rs:4:12 + | +LL | struct Foo { data: T } + | ^ required by this bound in `Foo` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/unsized-struct.rs:4:12 + | +LL | struct Foo { data: T } + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `T: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn foo2() { not_sized::>() } +LL + fn foo2() { not_sized::>() } + | + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/unsized-struct.rs:13:35 + | +LL | fn bar2() { is_sized::>() } + | - ^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required because it appears within the type `Bar` + --> $DIR/unsized-struct.rs:11:8 + | +LL | struct Bar { data: T } + | ^^^ +note: required by a bound in `is_sized` + --> $DIR/unsized-struct.rs:1:13 + | +LL | fn is_sized() { } + | ^ required by this bound in `is_sized` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn bar2() { is_sized::>() } +LL + fn bar2() { is_sized::>() } + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-trait-impl-self-type.rs b/tests/ui/unsized/unsized-trait-impl-self-type.rs new file mode 100644 index 000000000..df571a833 --- /dev/null +++ b/tests/ui/unsized/unsized-trait-impl-self-type.rs @@ -0,0 +1,14 @@ +// Test sized-ness checking in substitution in impls. + +// impl - struct +trait T3 { + fn foo(&self, z: &Z); +} + +struct S5(Y); + +impl T3 for S5 { + //~^ ERROR the size for values of type +} + +fn main() { } diff --git a/tests/ui/unsized/unsized-trait-impl-self-type.stderr b/tests/ui/unsized/unsized-trait-impl-self-type.stderr new file mode 100644 index 000000000..f6ba9a80c --- /dev/null +++ b/tests/ui/unsized/unsized-trait-impl-self-type.stderr @@ -0,0 +1,29 @@ +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-trait-impl-self-type.rs:10:27 + | +LL | impl T3 for S5 { + | - ^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `S5` + --> $DIR/unsized-trait-impl-self-type.rs:8:11 + | +LL | struct S5(Y); + | ^ required by this bound in `S5` +help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` + --> $DIR/unsized-trait-impl-self-type.rs:8:11 + | +LL | struct S5(Y); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `Y: ?Sized`... +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl T3 for S5 { +LL + impl T3 for S5 { + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.rs b/tests/ui/unsized/unsized-trait-impl-trait-arg.rs new file mode 100644 index 000000000..96e7e371f --- /dev/null +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.rs @@ -0,0 +1,12 @@ +// Test sized-ness checking in substitution in impls. + +// impl - unbounded +trait T2 { + fn foo(&self, z: Z); +} +struct S4(Box); +impl T2 for S4 { + //~^ ERROR the size for values of type +} + +fn main() { } diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr new file mode 100644 index 000000000..f81487d52 --- /dev/null +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -0,0 +1,26 @@ +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized-trait-impl-trait-arg.rs:8:17 + | +LL | impl T2 for S4 { + | - ^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `T2` + --> $DIR/unsized-trait-impl-trait-arg.rs:4:10 + | +LL | trait T2 { + | ^ required by this bound in `T2` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl T2 for S4 { +LL + impl T2 for S4 { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait T2 { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized-tuple-impls.rs b/tests/ui/unsized/unsized-tuple-impls.rs new file mode 100644 index 000000000..5e385f33b --- /dev/null +++ b/tests/ui/unsized/unsized-tuple-impls.rs @@ -0,0 +1,21 @@ +// run-pass + +#![feature(unsized_tuple_coercion)] + +use std::collections::HashSet; + +fn main() { + let x : &(i32, i32, [i32]) = &(0, 1, [2, 3]); + let y : &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]); + let mut a = [y, x]; + a.sort(); + assert_eq!(a, [x, y]); + + assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]"); + + let mut h = HashSet::new(); + h.insert(x); + h.insert(y); + assert!(h.contains(x)); + assert!(h.contains(y)); +} diff --git a/tests/ui/unsized/unsized.rs b/tests/ui/unsized/unsized.rs new file mode 100644 index 000000000..54304834d --- /dev/null +++ b/tests/ui/unsized/unsized.rs @@ -0,0 +1,25 @@ +// run-pass + +#![allow(type_alias_bounds)] +#![allow(dead_code)] +// Test syntax checks for `?Sized` syntax. + +use std::marker::PhantomData; + +trait T1 { } +pub trait T2 { } +trait T3 : T2 { } +trait T4 { } +trait T5 { } +trait T6 { } +trait T7 { } +trait T8 { } +trait T9 { } +struct S1(PhantomData); +enum E { E1(PhantomData) } +impl T1 for S1 {} +fn f() {} +type TT = T; + +pub fn main() { +} diff --git a/tests/ui/unsized/unsized2.rs b/tests/ui/unsized/unsized2.rs new file mode 100644 index 000000000..bbeb00d5f --- /dev/null +++ b/tests/ui/unsized/unsized2.rs @@ -0,0 +1,96 @@ +// run-pass + +#![allow(unconditional_recursion)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// Test sized-ness checking in substitution. + +use std::marker; + +// Unbounded. +fn f1(x: &X) { + f1::(x); +} +fn f2(x: &X) { + f1::(x); + f2::(x); +} + +// Bounded. +trait T { fn dummy(&self) { } } +fn f3(x: &X) { + f3::(x); +} +fn f4(x: &X) { + f3::(x); + f4::(x); +} + +// Self type. +trait T2 { + fn f() -> Box; +} +struct S; +impl T2 for S { + fn f() -> Box { + Box::new(S) + } +} +fn f5(x: &X) { + let _: Box = T2::f(); +} +fn f6(x: &X) { + let _: Box = T2::f(); +} + +trait T3 { + fn f() -> Box; +} +impl T3 for S { + fn f() -> Box { + Box::new(S) + } +} +fn f7(x: &X) { + // This is valid, but the unsized bound on X is irrelevant because any type + // which implements T3 must have statically known size. + let _: Box = T3::f(); +} + +trait T4 { + fn dummy(&self) { } + fn m1(&self, x: &dyn T4, y: X); + fn m2(&self, x: &dyn T5, y: X); +} +trait T5 { + fn dummy(&self) { } + // not an error (for now) + fn m1(&self, x: &dyn T4); + fn m2(&self, x: &dyn T5); +} + +trait T6 { + fn dummy(&self) { } + fn m1(&self, x: &dyn T4); + fn m2(&self, x: &dyn T5); +} +trait T7 { + fn dummy(&self) { } + // not an error (for now) + fn m1(&self, x: &dyn T4); + fn m2(&self, x: &dyn T5); +} + +// The last field in a struct may be unsized +struct S2 { + f: X, +} +struct S3 { + f1: isize, + f2: X, +} + +pub fn main() { +} diff --git a/tests/ui/unsized/unsized3-rpass.rs b/tests/ui/unsized/unsized3-rpass.rs new file mode 100644 index 000000000..4d5e89575 --- /dev/null +++ b/tests/ui/unsized/unsized3-rpass.rs @@ -0,0 +1,93 @@ +// run-pass +// Test structs with always-unsized fields. + +#![allow(warnings)] +#![feature(unsize, ptr_metadata)] + +use std::mem; +use std::ptr; +use std::slice; + +struct Foo { + f: [T], +} + +struct Bar { + f1: usize, + f2: [usize], +} + +struct Baz { + f1: usize, + f2: str, +} + +trait Tr { + fn foo(&self) -> usize; +} + +struct St { + f: usize, +} + +impl Tr for St { + fn foo(&self) -> usize { + self.f + } +} + +struct Qux<'a> { + f: Tr + 'a, +} + +pub fn main() { + let _: &Foo; + let _: &Bar; + let _: &Baz; + + let _: Box>; + let _: Box; + let _: Box; + + let _ = mem::size_of::>>(); + let _ = mem::size_of::>(); + let _ = mem::size_of::>(); + + unsafe { + struct Foo_ { + f: [T; 3], + } + + let data: Box> = Box::new(Foo_ { f: [1, 2, 3] }); + let x: &Foo = mem::transmute(slice::from_raw_parts(&*data, 3)); + assert_eq!(x.f.len(), 3); + assert_eq!(x.f[0], 1); + + struct Baz_ { + f1: usize, + f2: [u8; 5], + } + + let data: Box<_> = + Box::new(Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] }); + let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5)); + assert_eq!(x.f1, 42); + let chs: Vec = x.f2.chars().collect(); + assert_eq!(chs.len(), 5); + assert_eq!(chs[0], 'a'); + assert_eq!(chs[1], 'b'); + assert_eq!(chs[2], 'c'); + assert_eq!(chs[3], 'd'); + assert_eq!(chs[4], 'e'); + + struct Qux_ { + f: St, + } + + let obj: Box = Box::new(St { f: 42 }); + let obj: &Tr = &*obj; + let data: Box<_> = Box::new(Qux_ { f: St { f: 234 } }); + let x: &Qux = &*ptr::from_raw_parts::((&*data as *const _).cast(), ptr::metadata(obj)); + assert_eq!(x.f.foo(), 234); + } +} diff --git a/tests/ui/unsized/unsized3.rs b/tests/ui/unsized/unsized3.rs new file mode 100644 index 000000000..af76aca2c --- /dev/null +++ b/tests/ui/unsized/unsized3.rs @@ -0,0 +1,50 @@ +// Test sized-ness checking in substitution within fn bodies.. + +use std::marker; + +// Unbounded. +fn f1(x: &X) { + f2::(x); + //~^ ERROR the size for values of type +} +fn f2(x: &X) { +} + +// Bounded. +trait T { + fn foo(&self) { } +} +fn f3(x: &X) { + f4::(x); + //~^ ERROR the size for values of type +} +fn f4(x: &X) { +} + +fn f5(x: &Y) {} +fn f6(x: &X) {} + +// Test with unsized struct. +struct S { + x: X, +} + +fn f8(x1: &S, x2: &S) { + f5(x1); + //~^ ERROR the size for values of type + f6(x2); // ok +} + +// Test some tuples. +fn f9(x1: Box>) { + f5(&(*x1, 34)); + //~^ ERROR the size for values of type +} + +fn f10(x1: Box>) { + f5(&(32, *x1)); + //~^ ERROR the size for values of type + //~| ERROR the size for values of type +} + +pub fn main() {} diff --git a/tests/ui/unsized/unsized3.stderr b/tests/ui/unsized/unsized3.stderr new file mode 100644 index 000000000..9ad1ac6b4 --- /dev/null +++ b/tests/ui/unsized/unsized3.stderr @@ -0,0 +1,155 @@ +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:7:13 + | +LL | fn f1(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +LL | f2::(x); + | ------- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required by a bound in `f2` + --> $DIR/unsized3.rs:10:7 + | +LL | fn f2(x: &X) { + | ^ required by this bound in `f2` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f1(x: &X) { +LL + fn f1(x: &X) { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f2(x: &X) { + | ++++++++ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:18:13 + | +LL | fn f3(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +LL | f4::(x); + | ------- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required by a bound in `f4` + --> $DIR/unsized3.rs:21:7 + | +LL | fn f4(x: &X) { + | ^ required by this bound in `f4` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f3(x: &X) { +LL + fn f3(x: &X) { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f4(x: &X) { + | ++++++++ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:33:8 + | +LL | fn f8(x1: &S, x2: &S) { + | - this type parameter needs to be `std::marker::Sized` +LL | f5(x1); + | -- ^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `S` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S { + | ^ +note: required by a bound in `f5` + --> $DIR/unsized3.rs:24:7 + | +LL | fn f5(x: &Y) {} + | ^ required by this bound in `f5` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f8(x1: &S, x2: &S) { +LL + fn f8(x1: &S, x2: &S) { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f5(x: &Y) {} + | ++++++++ + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:40:5 + | +LL | fn f9(x1: Box>) { + | - this type parameter needs to be `std::marker::Sized` +LL | f5(&(*x1, 34)); + | ^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `S` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S { + | ^ + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f9(x1: Box>) { +LL + fn f9(x1: Box>) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:45:9 + | +LL | fn f10(x1: Box>) { + | - this type parameter needs to be `std::marker::Sized` +LL | f5(&(32, *x1)); + | ^^^^^^^^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `S` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S { + | ^ + = note: required because it appears within the type `({integer}, S)` + = note: tuples must have a statically known size to be initialized +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f10(x1: Box>) { +LL + fn f10(x1: Box>) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized3.rs:45:8 + | +LL | fn f10(x1: Box>) { + | - this type parameter needs to be `std::marker::Sized` +LL | f5(&(32, *x1)); + | -- ^^^^^^^^^^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | +note: required because it appears within the type `S` + --> $DIR/unsized3.rs:28:8 + | +LL | struct S { + | ^ + = note: required because it appears within the type `({integer}, S)` +note: required by a bound in `f5` + --> $DIR/unsized3.rs:24:7 + | +LL | fn f5(x: &Y) {} + | ^ required by this bound in `f5` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f10(x1: Box>) { +LL + fn f10(x1: Box>) { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | fn f5(x: &Y) {} + | ++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized5.rs b/tests/ui/unsized/unsized5.rs new file mode 100644 index 000000000..befd2244d --- /dev/null +++ b/tests/ui/unsized/unsized5.rs @@ -0,0 +1,34 @@ +// Test `?Sized` types not allowed in fields (except the last one). + +struct S1 { + f1: X, + //~^ ERROR the size for values of type + f2: isize, +} +struct S2 { + f: isize, + g: X, + //~^ ERROR the size for values of type + h: isize, +} +struct S3 { + f: str, + //~^ ERROR the size for values of type + g: [usize] +} +struct S4 { + f: [u8], + //~^ ERROR the size for values of type + g: usize +} +enum E { + V1(X, isize), + //~^ ERROR the size for values of type +} +enum F { + V2{f1: X, f: isize}, + //~^ ERROR the size for values of type +} + +pub fn main() { +} diff --git a/tests/ui/unsized/unsized5.stderr b/tests/ui/unsized/unsized5.stderr new file mode 100644 index 000000000..03ed0c457 --- /dev/null +++ b/tests/ui/unsized/unsized5.stderr @@ -0,0 +1,136 @@ +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized5.rs:4:9 + | +LL | struct S1 { + | - this type parameter needs to be `std::marker::Sized` +LL | f1: X, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct S1 { +LL + struct S1 { + | +help: borrowed types always have a statically known size + | +LL | f1: &X, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | f1: Box, + | ++++ + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized5.rs:10:8 + | +LL | struct S2 { + | - this type parameter needs to be `std::marker::Sized` +LL | f: isize, +LL | g: X, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct S2 { +LL + struct S2 { + | +help: borrowed types always have a statically known size + | +LL | g: &X, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | g: Box, + | ++++ + + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unsized5.rs:15:8 + | +LL | f: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | f: &str, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | f: Box, + | ++++ + + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized5.rs:20:8 + | +LL | f: [u8], + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | f: &[u8], + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | f: Box<[u8]>, + | ++++ + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized5.rs:25:8 + | +LL | enum E { + | - this type parameter needs to be `std::marker::Sized` +LL | V1(X, isize), + | ^ doesn't have a size known at compile-time + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum E { +LL + enum E { + | +help: borrowed types always have a statically known size + | +LL | V1(&X, isize), + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | V1(Box, isize), + | ++++ + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized5.rs:29:12 + | +LL | enum F { + | - this type parameter needs to be `std::marker::Sized` +LL | V2{f1: X, f: isize}, + | ^ doesn't have a size known at compile-time + | + = note: no field of an enum variant may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - enum F { +LL + enum F { + | +help: borrowed types always have a statically known size + | +LL | V2{f1: &X, f: isize}, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | V2{f1: Box, f: isize}, + | ++++ + + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized6.rs b/tests/ui/unsized/unsized6.rs new file mode 100644 index 000000000..79133554d --- /dev/null +++ b/tests/ui/unsized/unsized6.rs @@ -0,0 +1,44 @@ +// Test `?Sized` local variables. + +trait T {} + +fn f1(x: &X) { + let _: W; // <-- this is OK, no bindings created, no initializer. + let _: (isize, (X, isize)); + //~^ ERROR the size for values of type + let y: Y; + //~^ ERROR the size for values of type + let y: (isize, (Z, usize)); + //~^ ERROR the size for values of type +} +fn f2(x: &X) { + let y: X; + //~^ ERROR the size for values of type + let y: (isize, (Y, isize)); + //~^ ERROR the size for values of type +} + +fn f3(x1: Box, x2: Box, x3: Box) { + let y: X = *x1; + //~^ ERROR the size for values of type + let y = *x2; + //~^ ERROR the size for values of type + let (y, z) = (*x3, 4); + //~^ ERROR the size for values of type +} +fn f4(x1: Box, x2: Box, x3: Box) { + let y: X = *x1; + //~^ ERROR the size for values of type + let y = *x2; + //~^ ERROR the size for values of type + let (y, z) = (*x3, 4); + //~^ ERROR the size for values of type +} + +fn g1(x: X) {} +//~^ ERROR the size for values of type +fn g2(x: X) {} +//~^ ERROR the size for values of type + +pub fn main() { +} diff --git a/tests/ui/unsized/unsized6.stderr b/tests/ui/unsized/unsized6.stderr new file mode 100644 index 000000000..18ac1ea18 --- /dev/null +++ b/tests/ui/unsized/unsized6.stderr @@ -0,0 +1,238 @@ +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized6.rs:9:9 + | +LL | fn f1(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let y: Y; + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f1(x: &X) { +LL + fn f1(x: &X) { + | +help: consider borrowing here + | +LL | let y: &Y; + | + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:7:12 + | +LL | fn f1(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +LL | let _: W; // <-- this is OK, no bindings created, no initializer. +LL | let _: (isize, (X, isize)); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f1(x: &X) { +LL + fn f1(x: &X) { + | + +error[E0277]: the size for values of type `Z` cannot be known at compilation time + --> $DIR/unsized6.rs:11:12 + | +LL | fn f1(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let y: (isize, (Z, usize)); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f1(x: &X) { +LL + fn f1(x: &X) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:15:9 + | +LL | fn f2(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +LL | let y: X; + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f2(x: &X) { +LL + fn f2(x: &X) { + | +help: consider borrowing here + | +LL | let y: &X; + | + + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized6.rs:17:12 + | +LL | fn f2(x: &X) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let y: (isize, (Y, isize)); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: only the last element of a tuple may have a dynamically sized type +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f2(x: &X) { +LL + fn f2(x: &X) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:22:9 + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `std::marker::Sized` +LL | let y: X = *x1; + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f3(x1: Box, x2: Box, x3: Box) { +LL + fn f3(x1: Box, x2: Box, x3: Box) { + | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:24:9 + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let y = *x2; + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f3(x1: Box, x2: Box, x3: Box) { +LL + fn f3(x1: Box, x2: Box, x3: Box) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:26:10 + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let (y, z) = (*x3, 4); + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f3(x1: Box, x2: Box, x3: Box) { +LL + fn f3(x1: Box, x2: Box, x3: Box) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:30:9 + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `std::marker::Sized` +LL | let y: X = *x1; + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f4(x1: Box, x2: Box, x3: Box) { +LL + fn f4(x1: Box, x2: Box, x3: Box) { + | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:32:9 + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let y = *x2; + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f4(x1: Box, x2: Box, x3: Box) { +LL + fn f4(x1: Box, x2: Box, x3: Box) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:34:10 + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `std::marker::Sized` +... +LL | let (y, z) = (*x3, 4); + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn f4(x1: Box, x2: Box, x3: Box) { +LL + fn f4(x1: Box, x2: Box, x3: Box) { + | + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:38:18 + | +LL | fn g1(x: X) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn g1(x: X) {} +LL + fn g1(x: X) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn g1(x: &X) {} + | + + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized6.rs:40:22 + | +LL | fn g2(x: X) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn g2(x: X) {} +LL + fn g2(x: X) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn g2(x: &X) {} + | + + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/unsized7.rs b/tests/ui/unsized/unsized7.rs new file mode 100644 index 000000000..422a78481 --- /dev/null +++ b/tests/ui/unsized/unsized7.rs @@ -0,0 +1,16 @@ +// Test sized-ness checking in substitution in impls. + +trait T {} + +// I would like these to fail eventually. +// impl - bounded +trait T1 { + fn dummy(&self) -> Z; +} + +struct S3(Box); +impl T1 for S3 { + //~^ ERROR the size for values of type +} + +fn main() { } diff --git a/tests/ui/unsized/unsized7.stderr b/tests/ui/unsized/unsized7.stderr new file mode 100644 index 000000000..1555b9df4 --- /dev/null +++ b/tests/ui/unsized/unsized7.stderr @@ -0,0 +1,26 @@ +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized7.rs:12:21 + | +LL | impl T1 for S3 { + | - ^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `std::marker::Sized` + | +note: required by a bound in `T1` + --> $DIR/unsized7.rs:7:10 + | +LL | trait T1 { + | ^ required by this bound in `T1` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - impl T1 for S3 { +LL + impl T1 for S3 { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | trait T1 { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unterminated-comment.rs b/tests/ui/unterminated-comment.rs new file mode 100644 index 000000000..1cfdfb1fb --- /dev/null +++ b/tests/ui/unterminated-comment.rs @@ -0,0 +1 @@ +/* //~ ERROR E0758 diff --git a/tests/ui/unterminated-comment.stderr b/tests/ui/unterminated-comment.stderr new file mode 100644 index 000000000..c513fafee --- /dev/null +++ b/tests/ui/unterminated-comment.stderr @@ -0,0 +1,9 @@ +error[E0758]: unterminated block comment + --> $DIR/unterminated-comment.rs:1:1 + | +LL | /* + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0758`. diff --git a/tests/ui/unterminated-nested-comment.rs b/tests/ui/unterminated-nested-comment.rs new file mode 100644 index 000000000..db5f2f3ba --- /dev/null +++ b/tests/ui/unterminated-nested-comment.rs @@ -0,0 +1,4 @@ +/* //~ ERROR E0758 +/* */ +/* +*/ diff --git a/tests/ui/unterminated-nested-comment.stderr b/tests/ui/unterminated-nested-comment.stderr new file mode 100644 index 000000000..3653e76c9 --- /dev/null +++ b/tests/ui/unterminated-nested-comment.stderr @@ -0,0 +1,21 @@ +error[E0758]: unterminated block comment + --> $DIR/unterminated-nested-comment.rs:1:1 + | +LL | /* + | ^- + | | + | _unterminated block comment + | | +LL | | /* */ +LL | | /* + | | -- + | | | + | | ...as last nested comment starts here, maybe you want to close this instead? +LL | | */ + | |_--^ + | | + | ...and last nested comment terminates here. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0758`. diff --git a/tests/ui/unused-crate-deps/auxiliary/bar.rs b/tests/ui/unused-crate-deps/auxiliary/bar.rs new file mode 100644 index 000000000..1d3824e7a --- /dev/null +++ b/tests/ui/unused-crate-deps/auxiliary/bar.rs @@ -0,0 +1 @@ +pub const BAR: &str = "bar"; diff --git a/tests/ui/unused-crate-deps/auxiliary/foo.rs b/tests/ui/unused-crate-deps/auxiliary/foo.rs new file mode 100644 index 000000000..0ef03eb9e --- /dev/null +++ b/tests/ui/unused-crate-deps/auxiliary/foo.rs @@ -0,0 +1,5 @@ +// edition:2018 +// aux-crate:bar=bar.rs + +pub const FOO: &str = "foo"; +pub use bar::BAR; diff --git a/tests/ui/unused-crate-deps/deny-attr.rs b/tests/ui/unused-crate-deps/deny-attr.rs new file mode 100644 index 000000000..e9ab18ff6 --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-attr.rs @@ -0,0 +1,9 @@ +// Check for unused crate dep, no path + +// edition:2018 +// aux-crate:bar=bar.rs + +#![deny(unused_crate_dependencies)] +//~^ ERROR external crate `bar` unused in + +fn main() {} diff --git a/tests/ui/unused-crate-deps/deny-attr.stderr b/tests/ui/unused-crate-deps/deny-attr.stderr new file mode 100644 index 000000000..93694f682 --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-attr.stderr @@ -0,0 +1,14 @@ +error: external crate `bar` unused in `deny_attr`: remove the dependency or add `use bar as _;` + --> $DIR/deny-attr.rs:6:1 + | +LL | #![deny(unused_crate_dependencies)] + | ^ + | +note: the lint level is defined here + --> $DIR/deny-attr.rs:6:9 + | +LL | #![deny(unused_crate_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/unused-crate-deps/deny-cmdline-json-silent.rs b/tests/ui/unused-crate-deps/deny-cmdline-json-silent.rs new file mode 100644 index 000000000..fd9a61d6c --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-cmdline-json-silent.rs @@ -0,0 +1,8 @@ +// Check for unused crate dep, json event, deny but we're not reporting that in exit status + +// edition:2018 +// check-pass +// compile-flags: -Dunused-crate-dependencies -Zunstable-options --json unused-externs-silent --error-format=json +// aux-crate:bar=bar.rs + +fn main() {} diff --git a/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr b/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr new file mode 100644 index 000000000..595619f3a --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-cmdline-json-silent.stderr @@ -0,0 +1 @@ +{"lint_level":"deny","unused_extern_names":["bar"]} diff --git a/tests/ui/unused-crate-deps/deny-cmdline-json.rs b/tests/ui/unused-crate-deps/deny-cmdline-json.rs new file mode 100644 index 000000000..2b369dee5 --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-cmdline-json.rs @@ -0,0 +1,7 @@ +// Check for unused crate dep, json event, deny, expect compile failure + +// edition:2018 +// compile-flags: -Dunused-crate-dependencies -Zunstable-options --json unused-externs --error-format=json +// aux-crate:bar=bar.rs + +fn main() {} diff --git a/tests/ui/unused-crate-deps/deny-cmdline-json.stderr b/tests/ui/unused-crate-deps/deny-cmdline-json.stderr new file mode 100644 index 000000000..595619f3a --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-cmdline-json.stderr @@ -0,0 +1 @@ +{"lint_level":"deny","unused_extern_names":["bar"]} diff --git a/tests/ui/unused-crate-deps/deny-cmdline.rs b/tests/ui/unused-crate-deps/deny-cmdline.rs new file mode 100644 index 000000000..69e28b331 --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-cmdline.rs @@ -0,0 +1,8 @@ +// Check for unused crate dep, deny, expect failure + +// edition:2018 +// compile-flags: -Dunused-crate-dependencies +// aux-crate:bar=bar.rs + +fn main() {} +//~^ ERROR external crate `bar` unused in diff --git a/tests/ui/unused-crate-deps/deny-cmdline.stderr b/tests/ui/unused-crate-deps/deny-cmdline.stderr new file mode 100644 index 000000000..0951dc670 --- /dev/null +++ b/tests/ui/unused-crate-deps/deny-cmdline.stderr @@ -0,0 +1,10 @@ +error: external crate `bar` unused in `deny_cmdline`: remove the dependency or add `use bar as _;` + --> $DIR/deny-cmdline.rs:7:1 + | +LL | fn main() {} + | ^ + | + = note: requested on the command line with `-D unused-crate-dependencies` + +error: aborting due to previous error + diff --git a/tests/ui/unused-crate-deps/ignore-pathless-extern.rs b/tests/ui/unused-crate-deps/ignore-pathless-extern.rs new file mode 100644 index 000000000..8c273cb53 --- /dev/null +++ b/tests/ui/unused-crate-deps/ignore-pathless-extern.rs @@ -0,0 +1,12 @@ +// Pathless --extern references don't count + +// edition:2018 +// check-pass +// aux-crate:bar=bar.rs +// compile-flags:--extern proc_macro + +#![warn(unused_crate_dependencies)] + +use bar as _; + +fn main() {} diff --git a/tests/ui/unused-crate-deps/libfib.rs b/tests/ui/unused-crate-deps/libfib.rs new file mode 100644 index 000000000..c1545dca9 --- /dev/null +++ b/tests/ui/unused-crate-deps/libfib.rs @@ -0,0 +1,21 @@ +// Test warnings for a library crate + +// check-pass +// aux-crate:bar=bar.rs +// compile-flags:--crate-type lib -Wunused-crate-dependencies + +pub fn fib(n: u32) -> Vec { +//~^ WARNING external crate `bar` unused in +let mut prev = 0; + let mut cur = 1; + let mut v = vec![]; + + for _ in 0..n { + v.push(prev); + let n = prev + cur; + prev = cur; + cur = n; + } + + v +} diff --git a/tests/ui/unused-crate-deps/libfib.stderr b/tests/ui/unused-crate-deps/libfib.stderr new file mode 100644 index 000000000..15833126b --- /dev/null +++ b/tests/ui/unused-crate-deps/libfib.stderr @@ -0,0 +1,10 @@ +warning: external crate `bar` unused in `libfib`: remove the dependency or add `use bar as _;` + --> $DIR/libfib.rs:7:1 + | +LL | pub fn fib(n: u32) -> Vec { + | ^ + | + = note: requested on the command line with `-W unused-crate-dependencies` + +warning: 1 warning emitted + diff --git a/tests/ui/unused-crate-deps/lint-group.rs b/tests/ui/unused-crate-deps/lint-group.rs new file mode 100644 index 000000000..e21ffb5de --- /dev/null +++ b/tests/ui/unused-crate-deps/lint-group.rs @@ -0,0 +1,9 @@ +// `unused_crate_dependencies` is not currently in the `unused` group +// due to false positives from Cargo. + +// check-pass +// aux-crate:bar=bar.rs + +#![deny(unused)] + +fn main() {} diff --git a/tests/ui/unused-crate-deps/suppress.rs b/tests/ui/unused-crate-deps/suppress.rs new file mode 100644 index 000000000..8904d04bc --- /dev/null +++ b/tests/ui/unused-crate-deps/suppress.rs @@ -0,0 +1,11 @@ +// Suppress by using crate + +// edition:2018 +// check-pass +// aux-crate:bar=bar.rs + +#![warn(unused_crate_dependencies)] + +use bar as _; + +fn main() {} diff --git a/tests/ui/unused-crate-deps/test-use-ok.rs b/tests/ui/unused-crate-deps/test-use-ok.rs new file mode 100644 index 000000000..66d6440c9 --- /dev/null +++ b/tests/ui/unused-crate-deps/test-use-ok.rs @@ -0,0 +1,15 @@ +// Test-only use OK + +// edition:2018 +// check-pass +// aux-crate:bar=bar.rs +// compile-flags:--test + +#![deny(unused_crate_dependencies)] + +fn main() {} + +#[test] +fn test_bar() { + assert_eq!(bar::BAR, "bar"); +} diff --git a/tests/ui/unused-crate-deps/test.mk b/tests/ui/unused-crate-deps/test.mk new file mode 100644 index 000000000..0b98b4e44 --- /dev/null +++ b/tests/ui/unused-crate-deps/test.mk @@ -0,0 +1,7 @@ +# Everyone uses make for building Rust + +foo: bar.rlib + $(RUSTC) --crate-type bin --extern bar=bar.rlib + +%.rlib: %.rs + $(RUSTC) --crate-type lib $< diff --git a/tests/ui/unused-crate-deps/unused-aliases.rs b/tests/ui/unused-crate-deps/unused-aliases.rs new file mode 100644 index 000000000..1b7cb9b97 --- /dev/null +++ b/tests/ui/unused-crate-deps/unused-aliases.rs @@ -0,0 +1,13 @@ +// Warn about unused aliased for the crate + +// edition:2018 +// check-pass +// aux-crate:bar=bar.rs +// aux-crate:barbar=bar.rs + +#![warn(unused_crate_dependencies)] +//~^ WARNING external crate `barbar` unused in + +use bar as _; + +fn main() {} diff --git a/tests/ui/unused-crate-deps/unused-aliases.stderr b/tests/ui/unused-crate-deps/unused-aliases.stderr new file mode 100644 index 000000000..c8c6c4507 --- /dev/null +++ b/tests/ui/unused-crate-deps/unused-aliases.stderr @@ -0,0 +1,14 @@ +warning: external crate `barbar` unused in `unused_aliases`: remove the dependency or add `use barbar as _;` + --> $DIR/unused-aliases.rs:8:1 + | +LL | #![warn(unused_crate_dependencies)] + | ^ + | +note: the lint level is defined here + --> $DIR/unused-aliases.rs:8:9 + | +LL | #![warn(unused_crate_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/unused-crate-deps/use_extern_crate_2015.rs b/tests/ui/unused-crate-deps/use_extern_crate_2015.rs new file mode 100644 index 000000000..f15c87fa0 --- /dev/null +++ b/tests/ui/unused-crate-deps/use_extern_crate_2015.rs @@ -0,0 +1,13 @@ +// Suppress by using crate + +// edition:2015 +// check-pass +// aux-crate:bar=bar.rs + +#![warn(unused_crate_dependencies)] + +extern crate bar; + +fn main() { + println!("bar {}", bar::BAR); +} diff --git a/tests/ui/unused-crate-deps/warn-attr.rs b/tests/ui/unused-crate-deps/warn-attr.rs new file mode 100644 index 000000000..1acb307ab --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-attr.rs @@ -0,0 +1,10 @@ +// Check for unused crate dep, no path + +// edition:2018 +// check-pass +// aux-crate:bar=bar.rs + +#![warn(unused_crate_dependencies)] +//~^ WARNING external crate `bar` unused in + +fn main() {} diff --git a/tests/ui/unused-crate-deps/warn-attr.stderr b/tests/ui/unused-crate-deps/warn-attr.stderr new file mode 100644 index 000000000..0d3831570 --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-attr.stderr @@ -0,0 +1,14 @@ +warning: external crate `bar` unused in `warn_attr`: remove the dependency or add `use bar as _;` + --> $DIR/warn-attr.rs:7:1 + | +LL | #![warn(unused_crate_dependencies)] + | ^ + | +note: the lint level is defined here + --> $DIR/warn-attr.rs:7:9 + | +LL | #![warn(unused_crate_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/unused-crate-deps/warn-cmdline-json.rs b/tests/ui/unused-crate-deps/warn-cmdline-json.rs new file mode 100644 index 000000000..4826c0062 --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-cmdline-json.rs @@ -0,0 +1,8 @@ +// Check for unused crate dep, warn, json event, expect pass + +// edition:2018 +// check-pass +// compile-flags: -Wunused-crate-dependencies -Zunstable-options --json unused-externs --error-format=json +// aux-crate:bar=bar.rs + +fn main() {} diff --git a/tests/ui/unused-crate-deps/warn-cmdline-json.stderr b/tests/ui/unused-crate-deps/warn-cmdline-json.stderr new file mode 100644 index 000000000..98dbd7639 --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-cmdline-json.stderr @@ -0,0 +1 @@ +{"lint_level":"warn","unused_extern_names":["bar"]} diff --git a/tests/ui/unused-crate-deps/warn-cmdline-static.rs b/tests/ui/unused-crate-deps/warn-cmdline-static.rs new file mode 100644 index 000000000..c609529a6 --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-cmdline-static.rs @@ -0,0 +1,10 @@ +// Check for unused crate dep, no path + +// edition:2018 +// check-pass +// compile-flags: -Wunused-crate-dependencies +// aux-crate:bar=bar.rs +// no-prefer-dynamic + +fn main() {} +//~^ WARNING external crate `bar` unused in diff --git a/tests/ui/unused-crate-deps/warn-cmdline-static.stderr b/tests/ui/unused-crate-deps/warn-cmdline-static.stderr new file mode 100644 index 000000000..65956461d --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-cmdline-static.stderr @@ -0,0 +1,10 @@ +warning: external crate `bar` unused in `warn_cmdline_static`: remove the dependency or add `use bar as _;` + --> $DIR/warn-cmdline-static.rs:9:1 + | +LL | fn main() {} + | ^ + | + = note: requested on the command line with `-W unused-crate-dependencies` + +warning: 1 warning emitted + diff --git a/tests/ui/unused-crate-deps/warn-cmdline.rs b/tests/ui/unused-crate-deps/warn-cmdline.rs new file mode 100644 index 000000000..3bae61c3e --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-cmdline.rs @@ -0,0 +1,9 @@ +// Check for unused crate dep, no path + +// edition:2018 +// check-pass +// compile-flags: -Wunused-crate-dependencies +// aux-crate:bar=bar.rs + +fn main() {} +//~^ WARNING external crate `bar` unused in diff --git a/tests/ui/unused-crate-deps/warn-cmdline.stderr b/tests/ui/unused-crate-deps/warn-cmdline.stderr new file mode 100644 index 000000000..ea675ba9a --- /dev/null +++ b/tests/ui/unused-crate-deps/warn-cmdline.stderr @@ -0,0 +1,10 @@ +warning: external crate `bar` unused in `warn_cmdline`: remove the dependency or add `use bar as _;` + --> $DIR/warn-cmdline.rs:8:1 + | +LL | fn main() {} + | ^ + | + = note: requested on the command line with `-W unused-crate-dependencies` + +warning: 1 warning emitted + diff --git a/tests/ui/unused-move-capture.rs b/tests/ui/unused-move-capture.rs new file mode 100644 index 000000000..efaf10da4 --- /dev/null +++ b/tests/ui/unused-move-capture.rs @@ -0,0 +1,8 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { + let _x: Box<_> = Box::new(1); + let lam_move = || {}; + lam_move(); +} diff --git a/tests/ui/unused-move.rs b/tests/ui/unused-move.rs new file mode 100644 index 000000000..697434d47 --- /dev/null +++ b/tests/ui/unused-move.rs @@ -0,0 +1,13 @@ +// run-pass +// Issue #3878 +// Issue Name: Unused move causes a crash +// Abstract: zero-fill to block after drop + +// pretty-expanded FIXME #23616 + +#![allow(path_statements)] + +pub fn main() { + let y: Box<_> = Box::new(1); + y; +} diff --git a/tests/ui/unwind-abis/feature-gate-c-unwind-enabled.rs b/tests/ui/unwind-abis/feature-gate-c-unwind-enabled.rs new file mode 100644 index 000000000..6ff5dbda2 --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-c-unwind-enabled.rs @@ -0,0 +1,12 @@ +// Test that the "C-unwind" ABI is feature-gated, and *can* be used when the +// `c_unwind` feature gate is enabled. + +// check-pass + +#![feature(c_unwind)] + +extern "C-unwind" fn f() {} + +fn main() { + f(); +} diff --git a/tests/ui/unwind-abis/feature-gate-c-unwind.rs b/tests/ui/unwind-abis/feature-gate-c-unwind.rs new file mode 100644 index 000000000..ba72f74f2 --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-c-unwind.rs @@ -0,0 +1,13 @@ +// Test that the "C-unwind" ABI is feature-gated, and cannot be used when the +// `c_unwind` feature gate is not used. + +#![allow(ffi_unwind_calls)] +//~^ WARNING unknown lint: `ffi_unwind_calls` +//~| WARNING unknown lint: `ffi_unwind_calls` + +extern "C-unwind" fn f() {} +//~^ ERROR C-unwind ABI is experimental and subject to change [E0658] + +fn main() { + f(); +} diff --git a/tests/ui/unwind-abis/feature-gate-c-unwind.stderr b/tests/ui/unwind-abis/feature-gate-c-unwind.stderr new file mode 100644 index 000000000..214ddc45c --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-c-unwind.stderr @@ -0,0 +1,33 @@ +warning: unknown lint: `ffi_unwind_calls` + --> $DIR/feature-gate-c-unwind.rs:4:1 + | +LL | #![allow(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `ffi_unwind_calls` lint is unstable + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + = note: `#[warn(unknown_lints)]` on by default + +error[E0658]: C-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-c-unwind.rs:8:8 + | +LL | extern "C-unwind" fn f() {} + | ^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +warning: unknown lint: `ffi_unwind_calls` + --> $DIR/feature-gate-c-unwind.rs:4:1 + | +LL | #![allow(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `ffi_unwind_calls` lint is unstable + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unwind-abis/feature-gate-stdcall-unwind.rs b/tests/ui/unwind-abis/feature-gate-stdcall-unwind.rs new file mode 100644 index 000000000..cfa8eb3ca --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-stdcall-unwind.rs @@ -0,0 +1,30 @@ +// gate-test-c_unwind +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Test that the "stdcall-unwind" ABI is feature-gated, and cannot be used when +// the `c_unwind` feature gate is not used. + +extern "stdcall-unwind" fn fu() {} //~ ERROR stdcall-unwind ABI is experimental + +trait T { + extern "stdcall-unwind" fn mu(); //~ ERROR stdcall-unwind ABI is experimental + extern "stdcall-unwind" fn dmu() {} //~ ERROR stdcall-unwind ABI is experimental +} + +struct S; +impl T for S { + extern "stdcall-unwind" fn mu() {} //~ ERROR stdcall-unwind ABI is experimental +} + +impl S { + extern "stdcall-unwind" fn imu() {} //~ ERROR stdcall-unwind ABI is experimental +} + +type TAU = extern "stdcall-unwind" fn(); //~ ERROR stdcall-unwind ABI is experimental + +extern "stdcall-unwind" {} //~ ERROR stdcall-unwind ABI is experimental diff --git a/tests/ui/unwind-abis/feature-gate-stdcall-unwind.stderr b/tests/ui/unwind-abis/feature-gate-stdcall-unwind.stderr new file mode 100644 index 000000000..c2cce0e11 --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-stdcall-unwind.stderr @@ -0,0 +1,66 @@ +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:12:8 + | +LL | extern "stdcall-unwind" fn fu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:15:12 + | +LL | extern "stdcall-unwind" fn mu(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:16:12 + | +LL | extern "stdcall-unwind" fn dmu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:21:12 + | +LL | extern "stdcall-unwind" fn mu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:25:12 + | +LL | extern "stdcall-unwind" fn imu() {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:28:19 + | +LL | type TAU = extern "stdcall-unwind" fn(); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: stdcall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-stdcall-unwind.rs:30:8 + | +LL | extern "stdcall-unwind" {} + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unwind-abis/feature-gate-system-unwind.rs b/tests/ui/unwind-abis/feature-gate-system-unwind.rs new file mode 100644 index 000000000..26c2de4e8 --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-system-unwind.rs @@ -0,0 +1,9 @@ +// Test that the "system-unwind" ABI is feature-gated, and cannot be used when +// the `c_unwind` feature gate is not used. + +extern "system-unwind" fn f() {} +//~^ ERROR system-unwind ABI is experimental and subject to change [E0658] + +fn main() { + f(); +} diff --git a/tests/ui/unwind-abis/feature-gate-system-unwind.stderr b/tests/ui/unwind-abis/feature-gate-system-unwind.stderr new file mode 100644 index 000000000..878773364 --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-system-unwind.stderr @@ -0,0 +1,12 @@ +error[E0658]: system-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-system-unwind.rs:4:8 + | +LL | extern "system-unwind" fn f() {} + | ^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unwind-abis/feature-gate-thiscall-unwind.rs b/tests/ui/unwind-abis/feature-gate-thiscall-unwind.rs new file mode 100644 index 000000000..0a323e50f --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-thiscall-unwind.rs @@ -0,0 +1,39 @@ +// gate-test-abi_thiscall +// gate-test-c_unwind +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } + +// Test that the "thiscall-unwind" ABI is feature-gated, and cannot be used when +// the `c_unwind` feature gate is not used. + +extern "thiscall-unwind" fn fu() {} //~ ERROR thiscall-unwind ABI is experimental +extern "thiscall" fn f() {} //~ ERROR thiscall is experimental + +trait T { + extern "thiscall" fn m(); //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn mu(); //~ ERROR thiscall-unwind ABI is experimental + + extern "thiscall" fn dm() {} //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn dmu() {} //~ ERROR thiscall-unwind ABI is experimental +} + +struct S; +impl T for S { + extern "thiscall" fn m() {} //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn mu() {} //~ ERROR thiscall-unwind ABI is experimental +} + +impl S { + extern "thiscall" fn im() {} //~ ERROR thiscall is experimental + extern "thiscall-unwind" fn imu() {} //~ ERROR thiscall-unwind ABI is experimental +} + +type TA = extern "thiscall" fn(); //~ ERROR thiscall is experimental +type TAU = extern "thiscall-unwind" fn(); //~ ERROR thiscall-unwind ABI is experimental + +extern "thiscall" {} //~ ERROR thiscall is experimental +extern "thiscall-unwind" {} //~ ERROR thiscall-unwind ABI is experimental diff --git a/tests/ui/unwind-abis/feature-gate-thiscall-unwind.stderr b/tests/ui/unwind-abis/feature-gate-thiscall-unwind.stderr new file mode 100644 index 000000000..9ca00a55c --- /dev/null +++ b/tests/ui/unwind-abis/feature-gate-thiscall-unwind.stderr @@ -0,0 +1,122 @@ +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:13:8 + | +LL | extern "thiscall-unwind" fn fu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:14:8 + | +LL | extern "thiscall" fn f() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:17:12 + | +LL | extern "thiscall" fn m(); + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:18:12 + | +LL | extern "thiscall-unwind" fn mu(); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:20:12 + | +LL | extern "thiscall" fn dm() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:21:12 + | +LL | extern "thiscall-unwind" fn dmu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:26:12 + | +LL | extern "thiscall" fn m() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:27:12 + | +LL | extern "thiscall-unwind" fn mu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:31:12 + | +LL | extern "thiscall" fn im() {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:32:12 + | +LL | extern "thiscall-unwind" fn imu() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:35:18 + | +LL | type TA = extern "thiscall" fn(); + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:36:19 + | +LL | type TAU = extern "thiscall-unwind" fn(); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error[E0658]: thiscall is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:38:8 + | +LL | extern "thiscall" {} + | ^^^^^^^^^^ + | + = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable + +error[E0658]: thiscall-unwind ABI is experimental and subject to change + --> $DIR/feature-gate-thiscall-unwind.rs:39:8 + | +LL | extern "thiscall-unwind" {} + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #74990 for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/unwind-abis/ffi-unwind-calls-lint.rs b/tests/ui/unwind-abis/ffi-unwind-calls-lint.rs new file mode 100644 index 000000000..9a324f004 --- /dev/null +++ b/tests/ui/unwind-abis/ffi-unwind-calls-lint.rs @@ -0,0 +1,26 @@ +// build-pass +// needs-unwind + +#![feature(c_unwind)] +#![warn(ffi_unwind_calls)] + +mod foo { + #[no_mangle] + pub extern "C-unwind" fn foo() {} +} + +extern "C-unwind" { + fn foo(); +} + +fn main() { + // Call to Rust function is fine. + foo::foo(); + // Call to foreign function should warn. + unsafe { foo(); } + //~^ WARNING call to foreign function with FFI-unwind ABI + let ptr: extern "C-unwind" fn() = foo::foo; + // Call to function pointer should also warn. + ptr(); + //~^ WARNING call to function pointer with FFI-unwind ABI +} diff --git a/tests/ui/unwind-abis/ffi-unwind-calls-lint.stderr b/tests/ui/unwind-abis/ffi-unwind-calls-lint.stderr new file mode 100644 index 000000000..937a2b3df --- /dev/null +++ b/tests/ui/unwind-abis/ffi-unwind-calls-lint.stderr @@ -0,0 +1,20 @@ +warning: call to foreign function with FFI-unwind ABI + --> $DIR/ffi-unwind-calls-lint.rs:20:14 + | +LL | unsafe { foo(); } + | ^^^^^ call to foreign function with FFI-unwind ABI + | +note: the lint level is defined here + --> $DIR/ffi-unwind-calls-lint.rs:5:9 + | +LL | #![warn(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^ + +warning: call to function pointer with FFI-unwind ABI + --> $DIR/ffi-unwind-calls-lint.rs:24:5 + | +LL | ptr(); + | ^^^^^ call to function pointer with FFI-unwind ABI + +warning: 2 warnings emitted + diff --git a/tests/ui/unwind-no-uwtable.rs b/tests/ui/unwind-no-uwtable.rs new file mode 100644 index 000000000..3bc309233 --- /dev/null +++ b/tests/ui/unwind-no-uwtable.rs @@ -0,0 +1,34 @@ +// run-pass +// needs-unwind +// ignore-windows target requires uwtable +// compile-flags: -C panic=unwind -C force-unwind-tables=n + +use std::panic::{self, AssertUnwindSafe}; + +struct Increase<'a>(&'a mut u8); + +impl Drop for Increase<'_> { + fn drop(&mut self) { + *self.0 += 1; + } +} + +#[inline(never)] +fn unwind() { + panic!(); +} + +#[inline(never)] +fn increase(count: &mut u8) { + let _increase = Increase(count); + unwind(); +} + +fn main() { + let mut count = 0; + assert!(panic::catch_unwind(AssertUnwindSafe( + #[inline(never)] + || increase(&mut count) + )).is_err()); + assert_eq!(count, 1); +} diff --git a/tests/ui/unwind-unique.rs b/tests/ui/unwind-unique.rs new file mode 100644 index 000000000..50ecf751a --- /dev/null +++ b/tests/ui/unwind-unique.rs @@ -0,0 +1,15 @@ +// run-pass +// needs-unwind +// ignore-emscripten no threads support + +use std::thread; + +fn f() { + let _a: Box<_> = Box::new(0); + panic!(); +} + +pub fn main() { + let t = thread::spawn(f); + drop(t.join()); +} diff --git a/tests/ui/use-import-export.rs b/tests/ui/use-import-export.rs new file mode 100644 index 000000000..07a6866ba --- /dev/null +++ b/tests/ui/use-import-export.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +mod foo { + pub fn x() -> isize { return 1; } +} + +mod bar { + pub fn y() -> isize { return 1; } +} + +pub fn main() { foo::x(); bar::y(); } diff --git a/tests/ui/use-keyword-2.rs b/tests/ui/use-keyword-2.rs new file mode 100644 index 000000000..ebddb5d1a --- /dev/null +++ b/tests/ui/use-keyword-2.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(unused_variables)] +pub struct A; + +mod test { + pub use super :: A; + + pub use self :: A as B; +} + +impl A { + fn f() {} + fn g() { + Self :: f() + } +} + +fn main() { + let a: A = test::A; + let b: A = test::B; + let c: () = A::g(); +} diff --git a/tests/ui/use-module-level-int-consts.rs b/tests/ui/use-module-level-int-consts.rs new file mode 100644 index 000000000..200f742d7 --- /dev/null +++ b/tests/ui/use-module-level-int-consts.rs @@ -0,0 +1,12 @@ +// run-pass + +// Make sure the module level constants are still there and accessible even after +// the corresponding associated constants have been added, and later stabilized. +#![allow(deprecated, deprecated_in_future)] +use std::{u16, f32}; + +fn main() { + let _ = u16::MAX; + let _ = f32::EPSILON; + let _ = std::f64::MANTISSA_DIGITS; +} diff --git a/tests/ui/use-nested-groups.rs b/tests/ui/use-nested-groups.rs new file mode 100644 index 000000000..5c739709e --- /dev/null +++ b/tests/ui/use-nested-groups.rs @@ -0,0 +1,32 @@ +// run-pass + +mod a { + pub enum B {} + + pub mod d { + pub enum E {} + pub enum F {} + + pub mod g { + pub enum H {} + pub enum I {} + } + } +} + +// Test every possible part of the syntax +use a::{B, d::{self, *, g::H}}; + +// Test a more common use case +use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; + +fn main() { + let _: B; + let _: E; + let _: F; + let _: H; + let _: d::g::I; + + let _: Arc; + let _: Ordering; +} diff --git a/tests/ui/use.rs b/tests/ui/use.rs new file mode 100644 index 000000000..1beee4a51 --- /dev/null +++ b/tests/ui/use.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(stable_features)] +// pretty-expanded FIXME #23616 + +#![allow(unused_imports)] +#![feature(start, no_core, core)] +#![no_core] + +extern crate std; +extern crate std as zed; + +use std::str; +use zed::str as x; + +use std::io::{self, Error as IoError, Result as IoResult}; +use std::error::{self as foo}; +mod baz { + pub use std::str as x; +} + +#[start] +pub fn start(_: isize, _: *const *const u8) -> isize { 0 } diff --git a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs new file mode 100644 index 000000000..3c7756ef7 --- /dev/null +++ b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs @@ -0,0 +1,3 @@ +// compile-flags: --edition=2018 + +pub use u32; diff --git a/tests/ui/use/auxiliary/use-from-trait-xc.rs b/tests/ui/use/auxiliary/use-from-trait-xc.rs new file mode 100644 index 000000000..4abe11941 --- /dev/null +++ b/tests/ui/use/auxiliary/use-from-trait-xc.rs @@ -0,0 +1,29 @@ +pub use self::sub::{Bar, Baz}; + +pub trait Trait { + fn foo(&self); + type Assoc; + const CONST: u32; +} + +struct Foo; + +impl Foo { + pub fn new() {} + + pub const C: u32 = 0; +} + +mod sub { + pub struct Bar; + + impl Bar { + pub fn new() {} + } + + pub enum Baz {} + + impl Baz { + pub fn new() {} + } +} diff --git a/tests/ui/use/issue-18986.rs b/tests/ui/use/issue-18986.rs new file mode 100644 index 000000000..f0b292f29 --- /dev/null +++ b/tests/ui/use/issue-18986.rs @@ -0,0 +1,10 @@ +// aux-build:use-from-trait-xc.rs + +extern crate use_from_trait_xc; +pub use use_from_trait_xc::Trait; + +fn main() { + match () { + Trait { x: 42 } => () //~ ERROR expected struct, variant or union type, found trait `Trait` + } +} diff --git a/tests/ui/use/issue-18986.stderr b/tests/ui/use/issue-18986.stderr new file mode 100644 index 000000000..6c23178c7 --- /dev/null +++ b/tests/ui/use/issue-18986.stderr @@ -0,0 +1,9 @@ +error[E0574]: expected struct, variant or union type, found trait `Trait` + --> $DIR/issue-18986.rs:8:9 + | +LL | Trait { x: 42 } => () + | ^^^^^ not a struct, variant or union type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/use/issue-60976-extern-use-primitive-type.rs b/tests/ui/use/issue-60976-extern-use-primitive-type.rs new file mode 100644 index 000000000..4cd458302 --- /dev/null +++ b/tests/ui/use/issue-60976-extern-use-primitive-type.rs @@ -0,0 +1,7 @@ +// Regression test for #60976: ICE (with <=1.36.0) when another file had `use ;`. +// check-pass +// aux-build:extern-use-primitive-type-lib.rs + +extern crate extern_use_primitive_type_lib; + +fn main() {} diff --git a/tests/ui/use/use-after-move-based-on-type.rs b/tests/ui/use/use-after-move-based-on-type.rs new file mode 100644 index 000000000..ba7aa0345 --- /dev/null +++ b/tests/ui/use/use-after-move-based-on-type.rs @@ -0,0 +1,5 @@ +fn main() { + let x = "Hello!".to_string(); + let _y = x; + println!("{}", x); //~ ERROR borrow of moved value +} diff --git a/tests/ui/use/use-after-move-based-on-type.stderr b/tests/ui/use/use-after-move-based-on-type.stderr new file mode 100644 index 000000000..7b4d24549 --- /dev/null +++ b/tests/ui/use/use-after-move-based-on-type.stderr @@ -0,0 +1,19 @@ +error[E0382]: borrow of moved value: `x` + --> $DIR/use-after-move-based-on-type.rs:4:20 + | +LL | let x = "Hello!".to_string(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | let _y = x; + | - value moved here +LL | println!("{}", x); + | ^ value borrowed here after move + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = x.clone(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-after-move-implicity-coerced-object.rs b/tests/ui/use/use-after-move-implicity-coerced-object.rs new file mode 100644 index 000000000..47fbb5bf1 --- /dev/null +++ b/tests/ui/use/use-after-move-implicity-coerced-object.rs @@ -0,0 +1,30 @@ +use std::fmt; + +struct Number { + n: i64 +} + +impl fmt::Display for Number { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.n) + } +} + +struct List { + list: Vec> } + +impl List { + fn push(&mut self, n: Box) { + self.list.push(n); + } +} + +fn main() { + + let n: Box<_> = Number { n: 42 }.into(); + let mut l: Box<_> = List { list: Vec::new() }.into(); + l.push(n); + + let x = n.to_string(); + //~^ ERROR: borrow of moved value: `n` +} diff --git a/tests/ui/use/use-after-move-implicity-coerced-object.stderr b/tests/ui/use/use-after-move-implicity-coerced-object.stderr new file mode 100644 index 000000000..dfa0c0483 --- /dev/null +++ b/tests/ui/use/use-after-move-implicity-coerced-object.stderr @@ -0,0 +1,23 @@ +error[E0382]: borrow of moved value: `n` + --> $DIR/use-after-move-implicity-coerced-object.rs:28:13 + | +LL | let n: Box<_> = Number { n: 42 }.into(); + | - move occurs because `n` has type `Box`, which does not implement the `Copy` trait +LL | let mut l: Box<_> = List { list: Vec::new() }.into(); +LL | l.push(n); + | - value moved here +LL | +LL | let x = n.to_string(); + | ^^^^^^^^^^^^^ value borrowed here after move + | +note: consider changing this parameter type in method `push` to borrow instead if owning the value isn't necessary + --> $DIR/use-after-move-implicity-coerced-object.rs:17:27 + | +LL | fn push(&mut self, n: Box) { + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this method + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-after-move-self-based-on-type.rs b/tests/ui/use/use-after-move-self-based-on-type.rs new file mode 100644 index 000000000..932583495 --- /dev/null +++ b/tests/ui/use/use-after-move-self-based-on-type.rs @@ -0,0 +1,21 @@ +struct S { + x: isize, +} + +impl Drop for S { + fn drop(&mut self) {} +} + +impl S { + pub fn foo(self) -> isize { + self.bar(); + return self.x; //~ ERROR use of moved value: `self` + } + + pub fn bar(self) {} +} + +fn main() { + let x = S { x: 1 }; + println!("{}", x.foo()); +} diff --git a/tests/ui/use/use-after-move-self-based-on-type.stderr b/tests/ui/use/use-after-move-self-based-on-type.stderr new file mode 100644 index 000000000..1bdf49801 --- /dev/null +++ b/tests/ui/use/use-after-move-self-based-on-type.stderr @@ -0,0 +1,19 @@ +error[E0382]: use of moved value: `self` + --> $DIR/use-after-move-self-based-on-type.rs:12:16 + | +LL | pub fn foo(self) -> isize { + | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait +LL | self.bar(); + | ----- `self` moved due to this method call +LL | return self.x; + | ^^^^^^ value used here after move + | +note: `S::bar` takes ownership of the receiver `self`, which moves `self` + --> $DIR/use-after-move-self-based-on-type.rs:15:16 + | +LL | pub fn bar(self) {} + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-after-move-self.rs b/tests/ui/use/use-after-move-self.rs new file mode 100644 index 000000000..f7a3c0ecc --- /dev/null +++ b/tests/ui/use/use-after-move-self.rs @@ -0,0 +1,19 @@ +struct S { + x: Box, +} + + + +impl S { + pub fn foo(self) -> isize { + self.bar(); + return *self.x; //~ ERROR use of moved value: `self` + } + + pub fn bar(self) {} +} + +fn main() { + let x = S { x: 1.into() }; + println!("{}", x.foo()); +} diff --git a/tests/ui/use/use-after-move-self.stderr b/tests/ui/use/use-after-move-self.stderr new file mode 100644 index 000000000..59cc22ead --- /dev/null +++ b/tests/ui/use/use-after-move-self.stderr @@ -0,0 +1,19 @@ +error[E0382]: use of moved value: `self` + --> $DIR/use-after-move-self.rs:10:16 + | +LL | pub fn foo(self) -> isize { + | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait +LL | self.bar(); + | ----- `self` moved due to this method call +LL | return *self.x; + | ^^^^^^^ value used here after move + | +note: `S::bar` takes ownership of the receiver `self`, which moves `self` + --> $DIR/use-after-move-self.rs:13:16 + | +LL | pub fn bar(self) {} + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/use/use-associated-const.rs b/tests/ui/use/use-associated-const.rs new file mode 100644 index 000000000..714fbdabb --- /dev/null +++ b/tests/ui/use/use-associated-const.rs @@ -0,0 +1,13 @@ +#![allow(unused_imports)] + +pub mod foo { + pub struct Foo; + + impl Foo { + pub const BAR: i32 = 0; + } +} + +use foo::Foo::BAR; //~ ERROR unresolved import `foo::Foo` + +fn main() {} diff --git a/tests/ui/use/use-associated-const.stderr b/tests/ui/use/use-associated-const.stderr new file mode 100644 index 000000000..4bc0d7e61 --- /dev/null +++ b/tests/ui/use/use-associated-const.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `foo::Foo` + --> $DIR/use-associated-const.rs:11:10 + | +LL | use foo::Foo::BAR; + | ^^^ `Foo` is a struct, not a module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-crate-self.rs b/tests/ui/use/use-crate-self.rs new file mode 100644 index 000000000..65ab94814 --- /dev/null +++ b/tests/ui/use/use-crate-self.rs @@ -0,0 +1,4 @@ +use crate::{self}; + //~^ ERROR crate root imports need to be explicitly named: `use crate as name;` + +fn main() {} diff --git a/tests/ui/use/use-crate-self.stderr b/tests/ui/use/use-crate-self.stderr new file mode 100644 index 000000000..dd4036bff --- /dev/null +++ b/tests/ui/use/use-crate-self.stderr @@ -0,0 +1,8 @@ +error: crate root imports need to be explicitly named: `use crate as name;` + --> $DIR/use-crate-self.rs:1:13 + | +LL | use crate::{self}; + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/use/use-from-trait-xc.rs b/tests/ui/use/use-from-trait-xc.rs new file mode 100644 index 000000000..695ed66a1 --- /dev/null +++ b/tests/ui/use/use-from-trait-xc.rs @@ -0,0 +1,26 @@ +// aux-build:use-from-trait-xc.rs + +extern crate use_from_trait_xc; + +use use_from_trait_xc::Trait::foo; +//~^ ERROR `foo` is not directly importable + +use use_from_trait_xc::Trait::Assoc; +//~^ ERROR `Assoc` is not directly importable + +use use_from_trait_xc::Trait::CONST; +//~^ ERROR `CONST` is not directly importable + +use use_from_trait_xc::Foo::new; //~ ERROR struct `Foo` is private +//~^ ERROR unresolved import `use_from_trait_xc::Foo` + +use use_from_trait_xc::Foo::C; //~ ERROR struct `Foo` is private +//~^ ERROR unresolved import `use_from_trait_xc::Foo` + +use use_from_trait_xc::Bar::new as bnew; +//~^ ERROR unresolved import `use_from_trait_xc::Bar` + +use use_from_trait_xc::Baz::new as baznew; +//~^ ERROR unresolved import `use_from_trait_xc::Baz::new` + +fn main() {} diff --git a/tests/ui/use/use-from-trait-xc.stderr b/tests/ui/use/use-from-trait-xc.stderr new file mode 100644 index 000000000..4c4c2f622 --- /dev/null +++ b/tests/ui/use/use-from-trait-xc.stderr @@ -0,0 +1,70 @@ +error[E0253]: `foo` is not directly importable + --> $DIR/use-from-trait-xc.rs:5:5 + | +LL | use use_from_trait_xc::Trait::foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly + +error[E0253]: `Assoc` is not directly importable + --> $DIR/use-from-trait-xc.rs:8:5 + | +LL | use use_from_trait_xc::Trait::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly + +error[E0253]: `CONST` is not directly importable + --> $DIR/use-from-trait-xc.rs:11:5 + | +LL | use use_from_trait_xc::Trait::CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly + +error[E0432]: unresolved import `use_from_trait_xc::Foo` + --> $DIR/use-from-trait-xc.rs:14:24 + | +LL | use use_from_trait_xc::Foo::new; + | ^^^ `Foo` is a struct, not a module + +error[E0432]: unresolved import `use_from_trait_xc::Foo` + --> $DIR/use-from-trait-xc.rs:17:24 + | +LL | use use_from_trait_xc::Foo::C; + | ^^^ `Foo` is a struct, not a module + +error[E0432]: unresolved import `use_from_trait_xc::Bar` + --> $DIR/use-from-trait-xc.rs:20:24 + | +LL | use use_from_trait_xc::Bar::new as bnew; + | ^^^ `Bar` is a struct, not a module + +error[E0432]: unresolved import `use_from_trait_xc::Baz::new` + --> $DIR/use-from-trait-xc.rs:23:5 + | +LL | use use_from_trait_xc::Baz::new as baznew; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `new` in `sub::Baz` + +error[E0603]: struct `Foo` is private + --> $DIR/use-from-trait-xc.rs:14:24 + | +LL | use use_from_trait_xc::Foo::new; + | ^^^ private struct + | +note: the struct `Foo` is defined here + --> $DIR/auxiliary/use-from-trait-xc.rs:9:1 + | +LL | struct Foo; + | ^^^^^^^^^^ + +error[E0603]: struct `Foo` is private + --> $DIR/use-from-trait-xc.rs:17:24 + | +LL | use use_from_trait_xc::Foo::C; + | ^^^ private struct + | +note: the struct `Foo` is defined here + --> $DIR/auxiliary/use-from-trait-xc.rs:9:1 + | +LL | struct Foo; + | ^^^^^^^^^^ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0253, E0432, E0603. +For more information about an error, try `rustc --explain E0253`. diff --git a/tests/ui/use/use-from-trait.rs b/tests/ui/use/use-from-trait.rs new file mode 100644 index 000000000..eab4bb6e3 --- /dev/null +++ b/tests/ui/use/use-from-trait.rs @@ -0,0 +1,22 @@ +use Trait::foo; //~ ERROR `foo` is not directly importable +use Trait::Assoc; //~ ERROR `Assoc` is not directly importable +use Trait::C; //~ ERROR `C` is not directly importable + +use Foo::new; //~ ERROR unresolved import `Foo` [E0432] + +use Foo::C2; //~ ERROR unresolved import `Foo` [E0432] + +pub trait Trait { + fn foo(); + type Assoc; + const C: u32; +} + +struct Foo; + +impl Foo { + fn new() {} + const C2: u32 = 0; +} + +fn main() {} diff --git a/tests/ui/use/use-from-trait.stderr b/tests/ui/use/use-from-trait.stderr new file mode 100644 index 000000000..a5b0e356b --- /dev/null +++ b/tests/ui/use/use-from-trait.stderr @@ -0,0 +1,34 @@ +error[E0253]: `foo` is not directly importable + --> $DIR/use-from-trait.rs:1:5 + | +LL | use Trait::foo; + | ^^^^^^^^^^ cannot be imported directly + +error[E0253]: `Assoc` is not directly importable + --> $DIR/use-from-trait.rs:2:5 + | +LL | use Trait::Assoc; + | ^^^^^^^^^^^^ cannot be imported directly + +error[E0253]: `C` is not directly importable + --> $DIR/use-from-trait.rs:3:5 + | +LL | use Trait::C; + | ^^^^^^^^ cannot be imported directly + +error[E0432]: unresolved import `Foo` + --> $DIR/use-from-trait.rs:5:5 + | +LL | use Foo::new; + | ^^^ `Foo` is a struct, not a module + +error[E0432]: unresolved import `Foo` + --> $DIR/use-from-trait.rs:7:5 + | +LL | use Foo::C2; + | ^^^ `Foo` is a struct, not a module + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0253, E0432. +For more information about an error, try `rustc --explain E0253`. diff --git a/tests/ui/use/use-keyword.rs b/tests/ui/use/use-keyword.rs new file mode 100644 index 000000000..c30c2e06c --- /dev/null +++ b/tests/ui/use/use-keyword.rs @@ -0,0 +1,17 @@ +// Check that imports with nakes super and self don't fail during parsing +// FIXME: this shouldn't fail during name resolution either + +mod a { + mod b { + use self as A; + //~^ ERROR `self` imports are only allowed within a { } list + use super as B; + //~^ ERROR unresolved import `super` [E0432] + //~| no `super` in the root + use super::{self as C}; + //~^ ERROR unresolved import `super` [E0432] + //~| no `super` in the root + } +} + +fn main() {} diff --git a/tests/ui/use/use-keyword.stderr b/tests/ui/use/use-keyword.stderr new file mode 100644 index 000000000..501d14be5 --- /dev/null +++ b/tests/ui/use/use-keyword.stderr @@ -0,0 +1,22 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/use-keyword.rs:6:13 + | +LL | use self as A; + | ^^^^ + +error[E0432]: unresolved import `super` + --> $DIR/use-keyword.rs:8:13 + | +LL | use super as B; + | ^^^^^^^^^^ no `super` in the root + +error[E0432]: unresolved import `super` + --> $DIR/use-keyword.rs:11:21 + | +LL | use super::{self as C}; + | ^^^^^^^^^ no `super` in the root + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0429, E0432. +For more information about an error, try `rustc --explain E0429`. diff --git a/tests/ui/use/use-meta-mismatch.rs b/tests/ui/use/use-meta-mismatch.rs new file mode 100644 index 000000000..975209efb --- /dev/null +++ b/tests/ui/use/use-meta-mismatch.rs @@ -0,0 +1,5 @@ +// error-pattern:can't find crate for `fake_crate` + +extern crate fake_crate as extra; + +fn main() { } diff --git a/tests/ui/use/use-meta-mismatch.stderr b/tests/ui/use/use-meta-mismatch.stderr new file mode 100644 index 000000000..62b71fe8e --- /dev/null +++ b/tests/ui/use/use-meta-mismatch.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `fake_crate` + --> $DIR/use-meta-mismatch.rs:3:1 + | +LL | extern crate fake_crate as extra; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/use/use-mod.rs b/tests/ui/use/use-mod.rs new file mode 100644 index 000000000..87064c6a4 --- /dev/null +++ b/tests/ui/use/use-mod.rs @@ -0,0 +1,19 @@ +use foo::bar::{ + self, +//~^ ERROR `self` import can only appear once in an import list + Bar, + self +//~^ ERROR the name `bar` is defined multiple times +}; + +use {self}; +//~^ ERROR `self` import can only appear in an import list with a non-empty prefix + +mod foo { + pub mod bar { + pub struct Bar; + pub struct Baz; + } +} + +fn main() {} diff --git a/tests/ui/use/use-mod.stderr b/tests/ui/use/use-mod.stderr new file mode 100644 index 000000000..0cae5eb14 --- /dev/null +++ b/tests/ui/use/use-mod.stderr @@ -0,0 +1,33 @@ +error[E0430]: `self` import can only appear once in an import list + --> $DIR/use-mod.rs:2:5 + | +LL | self, + | ^^^^ can only appear once in an import list +... +LL | self + | ---- another `self` import appears here + +error[E0431]: `self` import can only appear in an import list with a non-empty prefix + --> $DIR/use-mod.rs:9:6 + | +LL | use {self}; + | ^^^^ can only appear in an import list with a non-empty prefix + +error[E0252]: the name `bar` is defined multiple times + --> $DIR/use-mod.rs:5:5 + | +LL | self, + | ---- previous import of the module `bar` here +... +LL | self + | ^^^^ + | | + | `bar` reimported here + | help: remove unnecessary import + | + = note: `bar` must be defined only once in the type namespace of this module + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0252, E0430, E0431. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/use/use-mod/use-mod-2.rs b/tests/ui/use/use-mod/use-mod-2.rs new file mode 100644 index 000000000..9373a62ba --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-2.rs @@ -0,0 +1,11 @@ +mod foo { + use self::{self}; + //~^ ERROR unresolved import `self` [E0432] + //~| no `self` in the root + + use super::{self}; + //~^ ERROR unresolved import `super` [E0432] + //~| no `super` in the root +} + +fn main() {} diff --git a/tests/ui/use/use-mod/use-mod-2.stderr b/tests/ui/use/use-mod/use-mod-2.stderr new file mode 100644 index 000000000..843767849 --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-2.stderr @@ -0,0 +1,15 @@ +error[E0432]: unresolved import `self` + --> $DIR/use-mod-2.rs:2:16 + | +LL | use self::{self}; + | ^^^^ no `self` in the root + +error[E0432]: unresolved import `super` + --> $DIR/use-mod-2.rs:6:17 + | +LL | use super::{self}; + | ^^^^ no `super` in the root + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-mod/use-mod-3.rs b/tests/ui/use/use-mod/use-mod-3.rs new file mode 100644 index 000000000..0afa486b9 --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-3.rs @@ -0,0 +1,12 @@ +use foo::bar::{ //~ ERROR module `bar` is private + self +}; +use foo::bar::{ //~ ERROR module `bar` is private + Bar +}; + +mod foo { + mod bar { pub type Bar = isize; } +} + +fn main() {} diff --git a/tests/ui/use/use-mod/use-mod-3.stderr b/tests/ui/use/use-mod/use-mod-3.stderr new file mode 100644 index 000000000..1b12b3c6f --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-3.stderr @@ -0,0 +1,27 @@ +error[E0603]: module `bar` is private + --> $DIR/use-mod-3.rs:1:10 + | +LL | use foo::bar::{ + | ^^^ private module + | +note: the module `bar` is defined here + --> $DIR/use-mod-3.rs:9:5 + | +LL | mod bar { pub type Bar = isize; } + | ^^^^^^^ + +error[E0603]: module `bar` is private + --> $DIR/use-mod-3.rs:4:10 + | +LL | use foo::bar::{ + | ^^^ private module + | +note: the module `bar` is defined here + --> $DIR/use-mod-3.rs:9:5 + | +LL | mod bar { pub type Bar = isize; } + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/use/use-mod/use-mod-4.rs b/tests/ui/use/use-mod/use-mod-4.rs new file mode 100644 index 000000000..46ae8ddad --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-4.rs @@ -0,0 +1,7 @@ +use foo::self; //~ ERROR unresolved import `foo` +//~^ ERROR `self` imports are only allowed within a { } list + +use std::mem::self; +//~^ ERROR `self` imports are only allowed within a { } list + +fn main() {} diff --git a/tests/ui/use/use-mod/use-mod-4.stderr b/tests/ui/use/use-mod/use-mod-4.stderr new file mode 100644 index 000000000..0b4fbadb4 --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-4.stderr @@ -0,0 +1,42 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/use-mod-4.rs:1:8 + | +LL | use foo::self; + | ^^^^^^ + | +help: consider importing the module directly + | +LL - use foo::self; +LL + use foo; + | +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use foo::{self}; + | + + + +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/use-mod-4.rs:4:13 + | +LL | use std::mem::self; + | ^^^^^^ + | +help: consider importing the module directly + | +LL - use std::mem::self; +LL + use std::mem; + | +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use std::mem::{self}; + | + + + +error[E0432]: unresolved import `foo` + --> $DIR/use-mod-4.rs:1:5 + | +LL | use foo::self; + | ^^^^^^^^^ no `foo` in the root + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0429, E0432. +For more information about an error, try `rustc --explain E0429`. diff --git a/tests/ui/use/use-mod/use-mod-5.rs b/tests/ui/use/use-mod/use-mod-5.rs new file mode 100644 index 000000000..df5b423ec --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-5.rs @@ -0,0 +1,13 @@ +mod foo { + pub mod bar { + pub fn drop() {} + } +} + +use foo::bar::self; +//~^ ERROR `self` imports are only allowed within a { } list + +fn main() { + // Because of error recovery this shouldn't error + bar::drop(); +} diff --git a/tests/ui/use/use-mod/use-mod-5.stderr b/tests/ui/use/use-mod/use-mod-5.stderr new file mode 100644 index 000000000..62859e261 --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-5.stderr @@ -0,0 +1,19 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/use-mod-5.rs:7:13 + | +LL | use foo::bar::self; + | ^^^^^^ + | +help: consider importing the module directly + | +LL - use foo::bar::self; +LL + use foo::bar; + | +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use foo::bar::{self}; + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/use/use-mod/use-mod-6.rs b/tests/ui/use/use-mod/use-mod-6.rs new file mode 100644 index 000000000..1f8777dac --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-6.rs @@ -0,0 +1,13 @@ +mod foo { + pub mod bar { + pub fn drop() {} + } +} + +use foo::bar::self as abc; +//~^ ERROR `self` imports are only allowed within a { } list + +fn main() { + // Because of error recovery this shouldn't error + abc::drop(); +} diff --git a/tests/ui/use/use-mod/use-mod-6.stderr b/tests/ui/use/use-mod/use-mod-6.stderr new file mode 100644 index 000000000..2d2c90067 --- /dev/null +++ b/tests/ui/use/use-mod/use-mod-6.stderr @@ -0,0 +1,19 @@ +error[E0429]: `self` imports are only allowed within a { } list + --> $DIR/use-mod-6.rs:7:13 + | +LL | use foo::bar::self as abc; + | ^^^^^^ + | +help: consider importing the module directly + | +LL - use foo::bar::self as abc; +LL + use foo::bar as abc; + | +help: alternatively, use the multi-path `use` syntax to import `self` + | +LL | use foo::bar::{self as abc}; + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0429`. diff --git a/tests/ui/use/use-nested-groups-error.rs b/tests/ui/use/use-nested-groups-error.rs new file mode 100644 index 000000000..d8b189d19 --- /dev/null +++ b/tests/ui/use/use-nested-groups-error.rs @@ -0,0 +1,15 @@ +mod a { + pub mod b1 { + pub enum C2 {} + } + + pub enum B2 {} +} + +use a::{b1::{C1, C2}, B2}; +//~^ ERROR unresolved import `a::b1::C1` + +fn main() { + let _: C2; + let _: B2; +} diff --git a/tests/ui/use/use-nested-groups-error.stderr b/tests/ui/use/use-nested-groups-error.stderr new file mode 100644 index 000000000..7234c8ec6 --- /dev/null +++ b/tests/ui/use/use-nested-groups-error.stderr @@ -0,0 +1,12 @@ +error[E0432]: unresolved import `a::b1::C1` + --> $DIR/use-nested-groups-error.rs:9:14 + | +LL | use a::{b1::{C1, C2}, B2}; + | ^^ + | | + | no `C1` in `a::b1` + | help: a similar name exists in the module: `C2` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-nested-groups-unused-imports.rs b/tests/ui/use/use-nested-groups-unused-imports.rs new file mode 100644 index 000000000..ca6b8ba94 --- /dev/null +++ b/tests/ui/use/use-nested-groups-unused-imports.rs @@ -0,0 +1,24 @@ +#![allow(dead_code)] +#![deny(unused_imports)] + +mod foo { + pub mod bar { + pub mod baz { + pub struct Bar(); + } + pub mod foobar {} + } + + pub struct Foo(); +} + +use foo::{Foo, bar::{baz::{}, foobar::*}, *}; + //~^ ERROR unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` +use foo::bar::baz::{*, *}; + //~^ ERROR unused import: `*` +use foo::{}; + //~^ ERROR unused import: `foo::{}` + +fn main() { + let _: Bar; +} diff --git a/tests/ui/use/use-nested-groups-unused-imports.stderr b/tests/ui/use/use-nested-groups-unused-imports.stderr new file mode 100644 index 000000000..6610f8ecd --- /dev/null +++ b/tests/ui/use/use-nested-groups-unused-imports.stderr @@ -0,0 +1,26 @@ +error: unused imports: `*`, `Foo`, `baz::{}`, `foobar::*` + --> $DIR/use-nested-groups-unused-imports.rs:15:11 + | +LL | use foo::{Foo, bar::{baz::{}, foobar::*}, *}; + | ^^^ ^^^^^^^ ^^^^^^^^^ ^ + | +note: the lint level is defined here + --> $DIR/use-nested-groups-unused-imports.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unused import: `*` + --> $DIR/use-nested-groups-unused-imports.rs:17:24 + | +LL | use foo::bar::baz::{*, *}; + | ^ + +error: unused import: `foo::{}` + --> $DIR/use-nested-groups-unused-imports.rs:19:5 + | +LL | use foo::{}; + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/use/use-paths-as-items.rs b/tests/ui/use/use-paths-as-items.rs new file mode 100644 index 000000000..7b5eb56b1 --- /dev/null +++ b/tests/ui/use/use-paths-as-items.rs @@ -0,0 +1,9 @@ +// Each path node in a `use` declaration must be treated as an item. If not, the following code +// will trigger an ICE. +// +// Related issue: #25763 + +use std::{mem, ptr}; +use std::mem; //~ ERROR the name `mem` is defined multiple times + +fn main() {} diff --git a/tests/ui/use/use-paths-as-items.stderr b/tests/ui/use/use-paths-as-items.stderr new file mode 100644 index 000000000..b09001a9b --- /dev/null +++ b/tests/ui/use/use-paths-as-items.stderr @@ -0,0 +1,13 @@ +error[E0252]: the name `mem` is defined multiple times + --> $DIR/use-paths-as-items.rs:7:5 + | +LL | use std::{mem, ptr}; + | --- previous import of the module `mem` here +LL | use std::mem; + | ^^^^^^^^ `mem` reimported here + | + = note: `mem` must be defined only once in the type namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0252`. diff --git a/tests/ui/use/use-self-type.rs b/tests/ui/use/use-self-type.rs new file mode 100644 index 000000000..3b4ce4297 --- /dev/null +++ b/tests/ui/use/use-self-type.rs @@ -0,0 +1,11 @@ +struct S; + +impl S { + fn f() {} + fn g() { + use Self::f; //~ ERROR unresolved import + pub(in Self::f) struct Z; //~ ERROR failed to resolve: `Self` + } +} + +fn main() {} diff --git a/tests/ui/use/use-self-type.stderr b/tests/ui/use/use-self-type.stderr new file mode 100644 index 000000000..e61539411 --- /dev/null +++ b/tests/ui/use/use-self-type.stderr @@ -0,0 +1,16 @@ +error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions + --> $DIR/use-self-type.rs:7:16 + | +LL | pub(in Self::f) struct Z; + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0432]: unresolved import `Self` + --> $DIR/use-self-type.rs:6:13 + | +LL | use Self::f; + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/use/use-super-global-path.rs b/tests/ui/use/use-super-global-path.rs new file mode 100644 index 000000000..64bfd14b7 --- /dev/null +++ b/tests/ui/use/use-super-global-path.rs @@ -0,0 +1,16 @@ +#![allow(unused)] + +struct S; +struct Z; + +mod foo { + use ::super::{S, Z}; //~ ERROR global paths cannot start with `super` + //~| ERROR global paths cannot start with `super` + + pub fn g() { + use ::super::main; //~ ERROR global paths cannot start with `super` + main(); + } +} + +fn main() { foo::g(); } diff --git a/tests/ui/use/use-super-global-path.stderr b/tests/ui/use/use-super-global-path.stderr new file mode 100644 index 000000000..7014a12e9 --- /dev/null +++ b/tests/ui/use/use-super-global-path.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: global paths cannot start with `super` + --> $DIR/use-super-global-path.rs:7:11 + | +LL | use ::super::{S, Z}; + | ^^^^^ global paths cannot start with `super` + +error[E0433]: failed to resolve: global paths cannot start with `super` + --> $DIR/use-super-global-path.rs:7:11 + | +LL | use ::super::{S, Z}; + | ^^^^^ global paths cannot start with `super` + +error[E0433]: failed to resolve: global paths cannot start with `super` + --> $DIR/use-super-global-path.rs:11:15 + | +LL | use ::super::main; + | ^^^^^ global paths cannot start with `super` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/used.rs b/tests/ui/used.rs new file mode 100644 index 000000000..f008724f4 --- /dev/null +++ b/tests/ui/used.rs @@ -0,0 +1,16 @@ +#[used] +static FOO: u32 = 0; // OK + +#[used] //~ ERROR attribute must be applied to a `static` variable +fn foo() {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +struct Foo {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +trait Bar {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +impl Bar for Foo {} + +fn main() {} diff --git a/tests/ui/used.stderr b/tests/ui/used.stderr new file mode 100644 index 000000000..ea77f129d --- /dev/null +++ b/tests/ui/used.stderr @@ -0,0 +1,26 @@ +error: attribute must be applied to a `static` variable + --> $DIR/used.rs:4:1 + | +LL | #[used] + | ^^^^^^^ + +error: attribute must be applied to a `static` variable + --> $DIR/used.rs:7:1 + | +LL | #[used] + | ^^^^^^^ + +error: attribute must be applied to a `static` variable + --> $DIR/used.rs:10:1 + | +LL | #[used] + | ^^^^^^^ + +error: attribute must be applied to a `static` variable + --> $DIR/used.rs:13:1 + | +LL | #[used] + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/user-defined-macro-rules.rs b/tests/ui/user-defined-macro-rules.rs new file mode 100644 index 000000000..09e071ec4 --- /dev/null +++ b/tests/ui/user-defined-macro-rules.rs @@ -0,0 +1,9 @@ +// check-pass + +macro_rules! macro_rules { () => { struct S; } } // OK + +macro_rules! {} // OK, calls the macro defined above + +fn main() { + let s = S; +} diff --git a/tests/ui/using-target-feature-unstable.rs b/tests/ui/using-target-feature-unstable.rs new file mode 100644 index 000000000..c5da45c08 --- /dev/null +++ b/tests/ui/using-target-feature-unstable.rs @@ -0,0 +1,11 @@ +// run-pass +// only-x86_64 +// aux-build:using-target-feature-unstable.rs + +extern crate using_target_feature_unstable; + +fn main() { + unsafe { + using_target_feature_unstable::foo(); + } +} diff --git a/tests/ui/usize-generic-argument-parent.rs b/tests/ui/usize-generic-argument-parent.rs new file mode 100644 index 000000000..4ab80d944 --- /dev/null +++ b/tests/ui/usize-generic-argument-parent.rs @@ -0,0 +1,5 @@ +fn foo() { + let x: usize; //~ ERROR const arguments are not allowed on builtin type `usize` +} + +fn main() {} diff --git a/tests/ui/usize-generic-argument-parent.stderr b/tests/ui/usize-generic-argument-parent.stderr new file mode 100644 index 000000000..131c476aa --- /dev/null +++ b/tests/ui/usize-generic-argument-parent.stderr @@ -0,0 +1,17 @@ +error[E0109]: const arguments are not allowed on builtin type `usize` + --> $DIR/usize-generic-argument-parent.rs:2:18 + | +LL | let x: usize; + | ----- ^^^ const argument not allowed + | | + | not allowed on builtin type `usize` + | +help: primitive type `usize` doesn't have generic parameters + | +LL - let x: usize; +LL + let x: usize; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/utf8-bom.rs b/tests/ui/utf8-bom.rs new file mode 100644 index 000000000..a3cb0e9a5 --- /dev/null +++ b/tests/ui/utf8-bom.rs @@ -0,0 +1,6 @@ +// run-pass +// + +// This file has utf-8 BOM, it should be compiled normally without error. + +pub fn main() {} diff --git a/tests/ui/utf8_idents.rs b/tests/ui/utf8_idents.rs new file mode 100644 index 000000000..1f6326dd9 --- /dev/null +++ b/tests/ui/utf8_idents.rs @@ -0,0 +1,16 @@ +// check-pass +// +#![allow(mixed_script_confusables, non_camel_case_types)] + +fn foo< + 'β, + γ +>() {} + +struct X { + δ: usize +} + +pub fn main() { + let α = 0.00001f64; +} diff --git a/tests/ui/variance-intersection-of-ref-and-opt-ref.rs b/tests/ui/variance-intersection-of-ref-and-opt-ref.rs new file mode 100644 index 000000000..74707a98d --- /dev/null +++ b/tests/ui/variance-intersection-of-ref-and-opt-ref.rs @@ -0,0 +1,25 @@ +// run-pass +// Elaborated version of the opening example from RFC 738. This failed +// to compile before variance because invariance of `Option` prevented +// us from approximating the lifetimes of `field1` and `field2` to a +// common intersection. + +#![allow(dead_code)] + +struct List<'l> { + field1: &'l i32, + field2: Option<&'l i32>, +} + +fn foo(field1: &i32, field2: Option<&i32>) -> i32 { + let list = List { field1: field1, field2: field2 }; + *list.field1 + list.field2.cloned().unwrap_or(0) +} + +fn main() { + let x = 22; + let y = Some(3); + let z = None; + assert_eq!(foo(&x, y.as_ref()), 25); + assert_eq!(foo(&x, z.as_ref()), 22); +} diff --git a/tests/ui/variance-iterators-in-libcore.rs b/tests/ui/variance-iterators-in-libcore.rs new file mode 100644 index 000000000..a542e44d5 --- /dev/null +++ b/tests/ui/variance-iterators-in-libcore.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(dead_code)] + +use std::iter::{Fuse, Zip}; + +fn fuse_covariant<'a, I>(iter: Fuse<&'static I>) -> Fuse<&'a I> { iter } +fn zip_covariant<'a, A, B>(iter: Zip<&'static A, &'static B>) -> Zip<&'a A, &'a B> { iter } + +fn main() { } diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs new file mode 100644 index 000000000..da55bc962 --- /dev/null +++ b/tests/ui/variance/variance-associated-consts.rs @@ -0,0 +1,17 @@ +// Test that the variance computation considers types that +// appear in const expressions to be invariant. + +#![feature(rustc_attrs)] +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Trait { + const Const: usize; +} + +#[rustc_variance] +struct Foo { //~ ERROR [o] + field: [u8; ::Const] +} + +fn main() { } diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr new file mode 100644 index 000000000..4df2d8da3 --- /dev/null +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -0,0 +1,8 @@ +error: [o] + --> $DIR/variance-associated-consts.rs:13:1 + | +LL | struct Foo { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-associated-types.rs b/tests/ui/variance/variance-associated-types.rs new file mode 100644 index 000000000..1165fb53c --- /dev/null +++ b/tests/ui/variance/variance-associated-types.rs @@ -0,0 +1,22 @@ +// Test that the variance computation considers types/regions that +// appear in projections to be invariant. + +#![feature(rustc_attrs)] + +trait Trait<'a> { + type Type; + + fn method(&'a self) { } +} + +#[rustc_variance] +struct Foo<'a, T : Trait<'a>> { //~ ERROR [-, +] + field: (T, &'a ()) +} + +#[rustc_variance] +struct Bar<'a, T : Trait<'a>> { //~ ERROR [o, o] + field: >::Type +} + +fn main() { } diff --git a/tests/ui/variance/variance-associated-types.stderr b/tests/ui/variance/variance-associated-types.stderr new file mode 100644 index 000000000..51f17c7c2 --- /dev/null +++ b/tests/ui/variance/variance-associated-types.stderr @@ -0,0 +1,14 @@ +error: [-, +] + --> $DIR/variance-associated-types.rs:13:1 + | +LL | struct Foo<'a, T : Trait<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, o] + --> $DIR/variance-associated-types.rs:18:1 + | +LL | struct Bar<'a, T : Trait<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-associated-types2.rs b/tests/ui/variance/variance-associated-types2.rs new file mode 100644 index 000000000..e487eefea --- /dev/null +++ b/tests/ui/variance/variance-associated-types2.rs @@ -0,0 +1,17 @@ +// Test that dyn Foo is invariant with respect to T. +// Failure to enforce invariance here can be weaponized, see #71550 for details. + +trait Foo { + type Bar; +} + +fn make() -> Box> { + panic!() +} + +fn take<'a>(_: &'a u32) { + let _: Box> = make(); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/variance/variance-associated-types2.stderr b/tests/ui/variance/variance-associated-types2.stderr new file mode 100644 index 000000000..35871c123 --- /dev/null +++ b/tests/ui/variance/variance-associated-types2.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/variance-associated-types2.rs:13:12 + | +LL | fn take<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +LL | let _: Box> = make(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-btree-invariant-types.rs b/tests/ui/variance/variance-btree-invariant-types.rs new file mode 100644 index 000000000..09c93d001 --- /dev/null +++ b/tests/ui/variance/variance-btree-invariant-types.rs @@ -0,0 +1,80 @@ +use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry}; + +fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { + v + //~^ lifetime may not live long enough +} +fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { + v + //~^ lifetime may not live long enough +} +fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { + v + //~^ lifetime may not live long enough +} +fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { + v + //~^ lifetime may not live long enough +} + +fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { + v + //~^ lifetime may not live long enough +} +fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { + v + //~^ lifetime may not live long enough +} +fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { + v + //~^ lifetime may not live long enough +} +fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { + v + //~^ lifetime may not live long enough +} + +fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) + -> OccupiedEntry<'a, &'new (), ()> { + v + //~^ lifetime may not live long enough +} +fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) + -> OccupiedEntry<'a, (), &'new ()> { + v + //~^ lifetime may not live long enough +} +fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) + -> OccupiedEntry<'a, &'static (), ()> { + v + //~^ lifetime may not live long enough +} +fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) + -> OccupiedEntry<'a, (), &'static ()> { + v + //~^ lifetime may not live long enough +} + +fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) + -> VacantEntry<'a, &'new (), ()> { + v + //~^ lifetime may not live long enough +} +fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) + -> VacantEntry<'a, (), &'new ()> { + v + //~^ lifetime may not live long enough +} +fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) + -> VacantEntry<'a, &'static (), ()> { + v + //~^ lifetime may not live long enough +} +fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) + -> VacantEntry<'a, (), &'static ()> { + v + //~^ lifetime may not live long enough +} + + +fn main() { } diff --git a/tests/ui/variance/variance-btree-invariant-types.stderr b/tests/ui/variance/variance-btree-invariant-types.stderr new file mode 100644 index 000000000..6f7910021 --- /dev/null +++ b/tests/ui/variance/variance-btree-invariant-types.stderr @@ -0,0 +1,202 @@ +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:4:5 + | +LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:8:5 + | +LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:12:5 + | +LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:16:5 + | +LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::IterMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::IterMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:21:5 + | +LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `RangeMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:25:5 + | +LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `RangeMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:29:5 + | +LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `RangeMut<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:33:5 + | +LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { + | ---- lifetime `'new` defined here +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `RangeMut<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `RangeMut<'a, K, V>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:39:5 + | +LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) + | ---- lifetime `'new` defined here +LL | -> OccupiedEntry<'a, &'new (), ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:44:5 + | +LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) + | ---- lifetime `'new` defined here +LL | -> OccupiedEntry<'a, (), &'new ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:49:5 + | +LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) + | ---- lifetime `'new` defined here +LL | -> OccupiedEntry<'a, &'static (), ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:54:5 + | +LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) + | ---- lifetime `'new` defined here +LL | -> OccupiedEntry<'a, (), &'static ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::OccupiedEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::OccupiedEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:60:5 + | +LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) + | ---- lifetime `'new` defined here +LL | -> VacantEntry<'a, &'new (), ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:65:5 + | +LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) + | ---- lifetime `'new` defined here +LL | -> VacantEntry<'a, (), &'new ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:70:5 + | +LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) + | ---- lifetime `'new` defined here +LL | -> VacantEntry<'a, &'static (), ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, &(), ()>`, which makes the generic argument `&()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-btree-invariant-types.rs:75:5 + | +LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) + | ---- lifetime `'new` defined here +LL | -> VacantEntry<'a, (), &'static ()> { +LL | v + | ^ returning this value requires that `'new` must outlive `'static` + | + = note: requirement occurs because of the type `std::collections::btree_map::VacantEntry<'_, (), &()>`, which makes the generic argument `()` invariant + = note: the struct `std::collections::btree_map::VacantEntry<'a, K, V, A>` is invariant over the parameter `K` + = help: see for more information about variance + +error: aborting due to 16 previous errors + diff --git a/tests/ui/variance/variance-cell-is-invariant.rs b/tests/ui/variance/variance-cell-is-invariant.rs new file mode 100644 index 000000000..62ce4f91f --- /dev/null +++ b/tests/ui/variance/variance-cell-is-invariant.rs @@ -0,0 +1,19 @@ +// Test that Cell is considered invariant with respect to its +// type. + +use std::cell::Cell; + +struct Foo<'a> { + x: Cell>, +} + +fn use_<'short,'long>(c: Foo<'short>, + s: &'short isize, + l: &'long isize, + _where:Option<&'short &'long ()>) { + let _: Foo<'long> = c; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/variance/variance-cell-is-invariant.stderr b/tests/ui/variance/variance-cell-is-invariant.stderr new file mode 100644 index 000000000..ab5435d16 --- /dev/null +++ b/tests/ui/variance/variance-cell-is-invariant.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/variance-cell-is-invariant.rs:14:12 + | +LL | fn use_<'short,'long>(c: Foo<'short>, + | ------ ----- lifetime `'long` defined here + | | + | lifetime `'short` defined here +... +LL | let _: Foo<'long> = c; + | ^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` + | + = help: consider adding the following bound: `'short: 'long` + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-contravariant-arg-object.rs b/tests/ui/variance/variance-contravariant-arg-object.rs new file mode 100644 index 000000000..701fcaf69 --- /dev/null +++ b/tests/ui/variance/variance-contravariant-arg-object.rs @@ -0,0 +1,27 @@ +#![allow(dead_code)] + +// Test that even when `T` is only used in contravariant position, it +// is treated as invariant. + +trait Get : 'static { + fn get(&self, t: T); +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + // Previously OK: + v + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/variance/variance-contravariant-arg-object.stderr b/tests/ui/variance/variance-contravariant-arg-object.stderr new file mode 100644 index 000000000..ab28315e1 --- /dev/null +++ b/tests/ui/variance/variance-contravariant-arg-object.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-contravariant-arg-object.rs:14:5 + | +LL | fn get_min_from_max<'min, 'max>(v: Box>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-contravariant-arg-object.rs:23:5 + | +LL | fn get_max_from_min<'min, 'max>(v: Box>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-contravariant-arg-trait-match.rs b/tests/ui/variance/variance-contravariant-arg-trait-match.rs new file mode 100644 index 000000000..e0b280105 --- /dev/null +++ b/tests/ui/variance/variance-contravariant-arg-trait-match.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] + +// Test that even when `T` is only used in contravariant position, it +// is treated as invariant. + +trait Get { + fn get(&self, t: T); +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + // Previously OK, but now an error because traits are invariant: + + impls_get::() + //~^ ERROR lifetime may not live long enough +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/tests/ui/variance/variance-contravariant-arg-trait-match.stderr b/tests/ui/variance/variance-contravariant-arg-trait-match.stderr new file mode 100644 index 000000000..df9d93907 --- /dev/null +++ b/tests/ui/variance/variance-contravariant-arg-trait-match.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-contravariant-arg-trait-match.rs:13:5 + | +LL | fn get_min_from_max<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-contravariant-arg-trait-match.rs:22:5 + | +LL | fn get_max_from_min<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-contravariant-self-trait-match.rs b/tests/ui/variance/variance-contravariant-self-trait-match.rs new file mode 100644 index 000000000..8a10554f3 --- /dev/null +++ b/tests/ui/variance/variance-contravariant-self-trait-match.rs @@ -0,0 +1,29 @@ +#![allow(dead_code)] + +// Test that even when `Self` is only used in contravariant position, it +// is treated as invariant. + +trait Get { + fn get(&self); +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : 'max, &'max G : Get +{ + impls_get::<&'min G>(); + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : 'max, &'min G : Get +{ + // Previously OK, but now error because traits are invariant with + // respect to all inputs. + + impls_get::<&'max G>(); + //~^ ERROR lifetime may not live long enough +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/tests/ui/variance/variance-contravariant-self-trait-match.stderr b/tests/ui/variance/variance-contravariant-self-trait-match.stderr new file mode 100644 index 000000000..bfea1b1b3 --- /dev/null +++ b/tests/ui/variance/variance-contravariant-self-trait-match.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-contravariant-self-trait-match.rs:13:5 + | +LL | fn get_min_from_max<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::<&'min G>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-contravariant-self-trait-match.rs:23:5 + | +LL | fn get_max_from_min<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::<&'max G>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-covariant-arg-object.rs b/tests/ui/variance/variance-covariant-arg-object.rs new file mode 100644 index 000000000..89cf3117a --- /dev/null +++ b/tests/ui/variance/variance-covariant-arg-object.rs @@ -0,0 +1,27 @@ +#![allow(dead_code)] + +// Test that even when `T` is only used in covariant position, it +// is treated as invariant. + +trait Get : 'static { + fn get(&self) -> T; +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + // Previously OK, now an error as traits are invariant. + v + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/variance/variance-covariant-arg-object.stderr b/tests/ui/variance/variance-covariant-arg-object.stderr new file mode 100644 index 000000000..51f8cb3ec --- /dev/null +++ b/tests/ui/variance/variance-covariant-arg-object.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-covariant-arg-object.rs:15:5 + | +LL | fn get_min_from_max<'min, 'max>(v: Box>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-covariant-arg-object.rs:23:5 + | +LL | fn get_max_from_min<'min, 'max>(v: Box>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-covariant-arg-trait-match.rs b/tests/ui/variance/variance-covariant-arg-trait-match.rs new file mode 100644 index 000000000..68dd449d5 --- /dev/null +++ b/tests/ui/variance/variance-covariant-arg-trait-match.rs @@ -0,0 +1,27 @@ +#![allow(dead_code)] + +// Test that even when `T` is only used in covariant position, it +// is treated as invariant. + +trait Get { + fn get(&self) -> T; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + // Previously OK, now an error as traits are invariant. + impls_get::() + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() + //~^ ERROR lifetime may not live long enough +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/tests/ui/variance/variance-covariant-arg-trait-match.stderr b/tests/ui/variance/variance-covariant-arg-trait-match.stderr new file mode 100644 index 000000000..4c7b6cf7c --- /dev/null +++ b/tests/ui/variance/variance-covariant-arg-trait-match.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-covariant-arg-trait-match.rs:14:5 + | +LL | fn get_min_from_max<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-covariant-arg-trait-match.rs:21:5 + | +LL | fn get_max_from_min<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-covariant-self-trait-match.rs b/tests/ui/variance/variance-covariant-self-trait-match.rs new file mode 100644 index 000000000..93c25e980 --- /dev/null +++ b/tests/ui/variance/variance-covariant-self-trait-match.rs @@ -0,0 +1,27 @@ +#![allow(dead_code)] + +// Test that even when `Self` is only used in covariant position, it +// is treated as invariant. + +trait Get { + fn get() -> Self; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : 'max, &'max G : Get +{ + // Previously OK, now an error as traits are invariant. + impls_get::<&'min G>(); + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : 'max, &'min G : Get +{ + impls_get::<&'max G>(); + //~^ ERROR lifetime may not live long enough +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/tests/ui/variance/variance-covariant-self-trait-match.stderr b/tests/ui/variance/variance-covariant-self-trait-match.stderr new file mode 100644 index 000000000..9b7ba3b66 --- /dev/null +++ b/tests/ui/variance/variance-covariant-self-trait-match.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-covariant-self-trait-match.rs:14:5 + | +LL | fn get_min_from_max<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::<&'min G>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-covariant-self-trait-match.rs:21:5 + | +LL | fn get_max_from_min<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::<&'max G>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-invariant-arg-object.rs b/tests/ui/variance/variance-invariant-arg-object.rs new file mode 100644 index 000000000..7381b4130 --- /dev/null +++ b/tests/ui/variance/variance-invariant-arg-object.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self, t: T) -> T; +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/variance/variance-invariant-arg-object.stderr b/tests/ui/variance/variance-invariant-arg-object.stderr new file mode 100644 index 000000000..9793a36be --- /dev/null +++ b/tests/ui/variance/variance-invariant-arg-object.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-invariant-arg-object.rs:11:5 + | +LL | fn get_min_from_max<'min, 'max>(v: Box>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-invariant-arg-object.rs:19:5 + | +LL | fn get_max_from_min<'min, 'max>(v: Box>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-invariant-arg-trait-match.rs b/tests/ui/variance/variance-invariant-arg-trait-match.rs new file mode 100644 index 000000000..fbcc24387 --- /dev/null +++ b/tests/ui/variance/variance-invariant-arg-trait-match.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] + +trait Get { + fn get(&self, t: T) -> T; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() + //~^ ERROR lifetime may not live long enough +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/tests/ui/variance/variance-invariant-arg-trait-match.stderr b/tests/ui/variance/variance-invariant-arg-trait-match.stderr new file mode 100644 index 000000000..60ffdd029 --- /dev/null +++ b/tests/ui/variance/variance-invariant-arg-trait-match.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-invariant-arg-trait-match.rs:10:5 + | +LL | fn get_min_from_max<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-invariant-arg-trait-match.rs:17:5 + | +LL | fn get_max_from_min<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::() + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-invariant-self-trait-match.rs b/tests/ui/variance/variance-invariant-self-trait-match.rs new file mode 100644 index 000000000..95c4c2403 --- /dev/null +++ b/tests/ui/variance/variance-invariant-self-trait-match.rs @@ -0,0 +1,23 @@ +#![allow(dead_code)] + +trait Get { + fn get(&self) -> Self; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, &'max G : Get, G : 'max +{ + impls_get::<&'min G>(); + //~^ ERROR lifetime may not live long enough +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, &'min G : Get, G : 'min +{ + impls_get::<&'max G>(); + //~^ ERROR lifetime may not live long enough +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/tests/ui/variance/variance-invariant-self-trait-match.stderr b/tests/ui/variance/variance-invariant-self-trait-match.stderr new file mode 100644 index 000000000..5b64bd091 --- /dev/null +++ b/tests/ui/variance/variance-invariant-self-trait-match.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/variance-invariant-self-trait-match.rs:10:5 + | +LL | fn get_min_from_max<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::<&'min G>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: lifetime may not live long enough + --> $DIR/variance-invariant-self-trait-match.rs:17:5 + | +LL | fn get_max_from_min<'min, 'max, G>() + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | impls_get::<&'max G>(); + | ^^^^^^^^^^^^^^^^^^^^ requires that `'min` must outlive `'max` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variance/variance-issue-20533.rs b/tests/ui/variance/variance-issue-20533.rs new file mode 100644 index 000000000..a2459f873 --- /dev/null +++ b/tests/ui/variance/variance-issue-20533.rs @@ -0,0 +1,43 @@ +// Regression test for issue #20533. At some point, only 1 out of the +// 3 errors below were being reported. + +use std::marker::PhantomData; + +fn foo<'a, T>(_x: &'a T) -> PhantomData<&'a ()> { + PhantomData +} + +struct Wrap(T); + +fn bar<'a, T>(_x: &'a T) -> Wrap> { + Wrap(PhantomData) +} + +struct Baked<'a>(PhantomData<&'a ()>); + +fn baz<'a, T>(_x: &'a T) -> Baked<'a> { + Baked(PhantomData) +} + +struct AffineU32(u32); + +fn main() { + { + let a = AffineU32(1); + let x = foo(&a); + drop(a); //~ ERROR cannot move out of `a` + drop(x); + } + { + let a = AffineU32(1); + let x = bar(&a); + drop(a); //~ ERROR cannot move out of `a` + drop(x); + } + { + let a = AffineU32(1); + let x = baz(&a); + drop(a); //~ ERROR cannot move out of `a` + drop(x); + } +} diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr new file mode 100644 index 000000000..008e2a002 --- /dev/null +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -0,0 +1,33 @@ +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/variance-issue-20533.rs:28:14 + | +LL | let x = foo(&a); + | -- borrow of `a` occurs here +LL | drop(a); + | ^ move out of `a` occurs here +LL | drop(x); + | - borrow later used here + +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/variance-issue-20533.rs:34:14 + | +LL | let x = bar(&a); + | -- borrow of `a` occurs here +LL | drop(a); + | ^ move out of `a` occurs here +LL | drop(x); + | - borrow later used here + +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/variance-issue-20533.rs:40:14 + | +LL | let x = baz(&a); + | -- borrow of `a` occurs here +LL | drop(a); + | ^ move out of `a` occurs here +LL | drop(x); + | - borrow later used here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/variance/variance-object-types.rs b/tests/ui/variance/variance-object-types.rs new file mode 100644 index 000000000..6ded24cd1 --- /dev/null +++ b/tests/ui/variance/variance-object-types.rs @@ -0,0 +1,12 @@ +#![feature(rustc_attrs)] + + +// For better or worse, associated types are invariant, and hence we +// get an invariant result for `'a`. +#[rustc_variance] +struct Foo<'a> { //~ ERROR [o] + x: Box &'a i32 + 'static> +} + +fn main() { +} diff --git a/tests/ui/variance/variance-object-types.stderr b/tests/ui/variance/variance-object-types.stderr new file mode 100644 index 000000000..55a760425 --- /dev/null +++ b/tests/ui/variance/variance-object-types.stderr @@ -0,0 +1,8 @@ +error: [o] + --> $DIR/variance-object-types.rs:7:1 + | +LL | struct Foo<'a> { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs new file mode 100644 index 000000000..3f34e7655 --- /dev/null +++ b/tests/ui/variance/variance-regions-direct.rs @@ -0,0 +1,65 @@ +// Test that we correctly infer variance for region parameters in +// various self-contained types. + +#![feature(rustc_attrs)] + +// Regions that just appear in normal spots are contravariant: + +#[rustc_variance] +struct Test2<'a, 'b, 'c> { //~ ERROR [-, -, -] + x: &'a isize, + y: &'b [isize], + c: &'c str +} + +// Those same annotations in function arguments become covariant: + +#[rustc_variance] +struct Test3<'a, 'b, 'c> { //~ ERROR [+, +, +] + x: extern "Rust" fn(&'a isize), + y: extern "Rust" fn(&'b [isize]), + c: extern "Rust" fn(&'c str), +} + +// Mutability induces invariance: + +#[rustc_variance] +struct Test4<'a, 'b:'a> { //~ ERROR [-, o] + x: &'a mut &'b isize, +} + +// Mutability induces invariance, even when in a +// contravariant context: + +#[rustc_variance] +struct Test5<'a, 'b:'a> { //~ ERROR [+, o] + x: extern "Rust" fn(&'a mut &'b isize), +} + +// Invariance is a trap from which NO ONE CAN ESCAPE. +// In other words, even though the `&'b isize` occurs in +// an argument list (which is contravariant), that +// argument list occurs in an invariant context. + +#[rustc_variance] +struct Test6<'a, 'b:'a> { //~ ERROR [-, o] + x: &'a mut extern "Rust" fn(&'b isize), +} + +// No uses at all is bivariant: + +#[rustc_variance] +struct Test7<'a> { //~ ERROR [*] + x: isize +} + +// Try enums too. + +#[rustc_variance] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR [+, -, o] + Test8A(extern "Rust" fn(&'a isize)), + Test8B(&'b [isize]), + Test8C(&'b mut &'c str), +} + +fn main() {} diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr new file mode 100644 index 000000000..eda02e9b0 --- /dev/null +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -0,0 +1,44 @@ +error: [-, -, -] + --> $DIR/variance-regions-direct.rs:9:1 + | +LL | struct Test2<'a, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [+, +, +] + --> $DIR/variance-regions-direct.rs:18:1 + | +LL | struct Test3<'a, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [-, o] + --> $DIR/variance-regions-direct.rs:27:1 + | +LL | struct Test4<'a, 'b:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: [+, o] + --> $DIR/variance-regions-direct.rs:35:1 + | +LL | struct Test5<'a, 'b:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: [-, o] + --> $DIR/variance-regions-direct.rs:45:1 + | +LL | struct Test6<'a, 'b:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*] + --> $DIR/variance-regions-direct.rs:52:1 + | +LL | struct Test7<'a> { + | ^^^^^^^^^^^^^^^^ + +error: [+, -, o] + --> $DIR/variance-regions-direct.rs:59:1 + | +LL | enum Test8<'a, 'b, 'c:'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs new file mode 100644 index 000000000..f84f25ada --- /dev/null +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -0,0 +1,34 @@ +// Test that we correctly infer variance for region parameters in +// case that involve multiple intricate types. +// Try enums too. + +#![feature(rustc_attrs)] + +#[rustc_variance] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [+, -, o, *] + Test8A(extern "Rust" fn(&'a isize)), + Test8B(&'b [isize]), + Test8C(&'b mut &'c str), +} + +#[rustc_variance] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, -, +] + f: Base<'z, 'y, 'x, 'w> +} + +#[rustc_variance] // Combine - and + to yield o +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] + f: Base<'a, 'a, 'b, 'c> +} + +#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, -, *] + f: Base<'a, 'b, 'a, 'c> +} + +#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR [+, -, o] + f: Base<'a, 'b, 'c, 'a> +} + +fn main() {} diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr new file mode 100644 index 000000000..fa2f4d507 --- /dev/null +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -0,0 +1,32 @@ +error: [+, -, o, *] + --> $DIR/variance-regions-indirect.rs:8:1 + | +LL | enum Base<'a, 'b, 'c:'b, 'd> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, o, -, +] + --> $DIR/variance-regions-indirect.rs:15:1 + | +LL | struct Derived1<'w, 'x:'y, 'y, 'z> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, o, *] + --> $DIR/variance-regions-indirect.rs:20:1 + | +LL | struct Derived2<'a, 'b:'a, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, -, *] + --> $DIR/variance-regions-indirect.rs:25:1 + | +LL | struct Derived3<'a:'b, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [+, -, o] + --> $DIR/variance-regions-indirect.rs:30:1 + | +LL | struct Derived4<'a, 'b, 'c:'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/variance/variance-regions-unused-direct.rs b/tests/ui/variance/variance-regions-unused-direct.rs new file mode 100644 index 000000000..2afe012bd --- /dev/null +++ b/tests/ui/variance/variance-regions-unused-direct.rs @@ -0,0 +1,15 @@ +// Test that disallow lifetime parameters that are unused. + +use std::marker; + +struct Bivariant<'a>; //~ ERROR parameter `'a` is never used + +struct Struct<'a, 'd> { //~ ERROR parameter `'d` is never used + field: &'a [i32] +} + +trait Trait<'a, 'd> { // OK on traits + fn method(&'a self); +} + +fn main() {} diff --git a/tests/ui/variance/variance-regions-unused-direct.stderr b/tests/ui/variance/variance-regions-unused-direct.stderr new file mode 100644 index 000000000..1a600f5b0 --- /dev/null +++ b/tests/ui/variance/variance-regions-unused-direct.stderr @@ -0,0 +1,19 @@ +error[E0392]: parameter `'a` is never used + --> $DIR/variance-regions-unused-direct.rs:5:18 + | +LL | struct Bivariant<'a>; + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `'d` is never used + --> $DIR/variance-regions-unused-direct.rs:7:19 + | +LL | struct Struct<'a, 'd> { + | ^^ unused parameter + | + = help: consider removing `'d`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-regions-unused-indirect.rs b/tests/ui/variance/variance-regions-unused-indirect.rs new file mode 100644 index 000000000..6c2c24ddb --- /dev/null +++ b/tests/ui/variance/variance-regions-unused-indirect.rs @@ -0,0 +1,12 @@ +// Test that disallow lifetime parameters that are unused. + +enum Foo<'a> { //~ ERROR parameter `'a` is never used + //~^ ERROR recursive types `Foo` and `Bar` have infinite size + Foo1(Bar<'a>) +} + +enum Bar<'a> { //~ ERROR parameter `'a` is never used + Bar1(Foo<'a>) +} + +fn main() {} diff --git a/tests/ui/variance/variance-regions-unused-indirect.stderr b/tests/ui/variance/variance-regions-unused-indirect.stderr new file mode 100644 index 000000000..14fdd8492 --- /dev/null +++ b/tests/ui/variance/variance-regions-unused-indirect.stderr @@ -0,0 +1,43 @@ +error[E0072]: recursive types `Foo` and `Bar` have infinite size + --> $DIR/variance-regions-unused-indirect.rs:3:1 + | +LL | enum Foo<'a> { + | ^^^^^^^^^^^^ +LL | +LL | Foo1(Bar<'a>) + | ------- recursive without indirection +... +LL | enum Bar<'a> { + | ^^^^^^^^^^^^ +LL | Bar1(Foo<'a>) + | ------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ Foo1(Box>) +LL | } +LL | +LL | enum Bar<'a> { +LL ~ Bar1(Box>) + | + +error[E0392]: parameter `'a` is never used + --> $DIR/variance-regions-unused-indirect.rs:3:10 + | +LL | enum Foo<'a> { + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `'a` is never used + --> $DIR/variance-regions-unused-indirect.rs:8:10 + | +LL | enum Bar<'a> { + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0072, E0392. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs new file mode 100644 index 000000000..ad5334602 --- /dev/null +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -0,0 +1,35 @@ +#![allow(dead_code)] +#![feature(rustc_attrs)] + +// Check that bounds on type parameters (other than `Self`) do not +// influence variance. + +trait Getter { + fn get(&self) -> T; +} + +trait Setter { + fn get(&self, _: T); +} + +#[rustc_variance] +struct TestStruct> { //~ ERROR [+, +] + t: T, u: U +} + +#[rustc_variance] +enum TestEnum> { //~ ERROR [*, +] + Foo(T) +} + +#[rustc_variance] +struct TestContraStruct> { //~ ERROR [*, +] + t: T +} + +#[rustc_variance] +struct TestBox+Setter> { //~ ERROR [*, +] + t: T +} + +pub fn main() { } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr new file mode 100644 index 000000000..5a73e541c --- /dev/null +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -0,0 +1,26 @@ +error: [+, +] + --> $DIR/variance-trait-bounds.rs:16:1 + | +LL | struct TestStruct> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:21:1 + | +LL | enum TestEnum> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:26:1 + | +LL | struct TestContraStruct> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:31:1 + | +LL | struct TestBox+Setter> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/variance/variance-trait-matching.rs b/tests/ui/variance/variance-trait-matching.rs new file mode 100644 index 000000000..b4efee7d6 --- /dev/null +++ b/tests/ui/variance/variance-trait-matching.rs @@ -0,0 +1,38 @@ +#![allow(dead_code)] + +// Get is covariant in T +trait Get { + fn get(&self) -> T; +} + +struct Cloner { + t: T +} + +impl Get for Cloner { + fn get(&self) -> T { + self.t.clone() + } +} + +fn get<'a, G>(get: &G) -> i32 + where G : Get<&'a i32> +{ + // This fails to type-check because, without variance, we can't + // use `G : Get<&'a i32>` as evidence that `G : Get<&'b i32>`, + // even if `'a : 'b`. + pick(get, &22) //~ ERROR explicit lifetime required in the type of `get` [E0621] +} + +fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32 + where G : Get<&'b i32> +{ + let v = *get.get(); + if v % 2 != 0 { v } else { *if_odd } +} + +fn main() { + let x = Cloner { t: &23 }; + let y = get(&x); + assert_eq!(y, 23); +} diff --git a/tests/ui/variance/variance-trait-matching.stderr b/tests/ui/variance/variance-trait-matching.stderr new file mode 100644 index 000000000..3308cc6d2 --- /dev/null +++ b/tests/ui/variance/variance-trait-matching.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `get` + --> $DIR/variance-trait-matching.rs:24:5 + | +LL | fn get<'a, G>(get: &G) -> i32 + | -- help: add explicit lifetime `'a` to the type of `get`: `&'a G` +... +LL | pick(get, &22) + | ^^^^^^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/variance/variance-trait-object-bound.rs b/tests/ui/variance/variance-trait-object-bound.rs new file mode 100644 index 000000000..ec3c973bc --- /dev/null +++ b/tests/ui/variance/variance-trait-object-bound.rs @@ -0,0 +1,18 @@ +// Checks that regions which appear in a trait object type are +// observed by the variance inference algorithm (and hence +// `TOption` is contavariant w/r/t `'a` and not bivariant). +// +// Issue #18262. + +#![feature(rustc_attrs)] + +use std::mem; + +trait T { fn foo(&self); } + +#[rustc_variance] +struct TOption<'a> { //~ ERROR [-] + v: Option>, +} + +fn main() { } diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr new file mode 100644 index 000000000..7c46b553f --- /dev/null +++ b/tests/ui/variance/variance-trait-object-bound.stderr @@ -0,0 +1,8 @@ +error: [-] + --> $DIR/variance-trait-object-bound.rs:14:1 + | +LL | struct TOption<'a> { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-types-bounds.rs b/tests/ui/variance/variance-types-bounds.rs new file mode 100644 index 000000000..d1814dd97 --- /dev/null +++ b/tests/ui/variance/variance-types-bounds.rs @@ -0,0 +1,43 @@ +// Test that we correctly infer variance for type parameters in +// various types and traits. + +#![feature(rustc_attrs)] + +#[rustc_variance] +struct TestImm { //~ ERROR [+, +] + x: A, + y: B, +} + +#[rustc_variance] +struct TestMut { //~ ERROR [+, o] + x: A, + y: &'static mut B, +} + +#[rustc_variance] +struct TestIndirect { //~ ERROR [+, o] + m: TestMut +} + +#[rustc_variance] +struct TestIndirect2 { //~ ERROR [o, o] + n: TestMut, + m: TestMut +} + +trait Getter { + fn get(&self) -> A; +} + +trait Setter { + fn set(&mut self, a: A); +} + +#[rustc_variance] +struct TestObject { //~ ERROR [o, o] + n: Box+Send>, + m: Box+Send>, +} + +fn main() {} diff --git a/tests/ui/variance/variance-types-bounds.stderr b/tests/ui/variance/variance-types-bounds.stderr new file mode 100644 index 000000000..bb8164434 --- /dev/null +++ b/tests/ui/variance/variance-types-bounds.stderr @@ -0,0 +1,32 @@ +error: [+, +] + --> $DIR/variance-types-bounds.rs:7:1 + | +LL | struct TestImm { + | ^^^^^^^^^^^^^^^^^^^^ + +error: [+, o] + --> $DIR/variance-types-bounds.rs:13:1 + | +LL | struct TestMut { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [+, o] + --> $DIR/variance-types-bounds.rs:19:1 + | +LL | struct TestIndirect { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, o] + --> $DIR/variance-types-bounds.rs:24:1 + | +LL | struct TestIndirect2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, o] + --> $DIR/variance-types-bounds.rs:38:1 + | +LL | struct TestObject { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/variance/variance-types.rs b/tests/ui/variance/variance-types.rs new file mode 100644 index 000000000..b9b6d9c9b --- /dev/null +++ b/tests/ui/variance/variance-types.rs @@ -0,0 +1,41 @@ +#![allow(dead_code)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Check that a type parameter which is only used in a trait bound is +// not considered bivariant. + +#[rustc_variance] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [-, o, o] + t: &'a mut (A,B) +} + +#[rustc_variance] +struct InvariantCell { //~ ERROR [o] + t: Cell +} + +#[rustc_variance] +struct InvariantIndirect { //~ ERROR [o] + t: InvariantCell +} + +#[rustc_variance] +struct Covariant { //~ ERROR [+] + t: A, u: fn() -> A +} + +#[rustc_variance] +struct Contravariant { //~ ERROR [-] + t: fn(A) +} + +#[rustc_variance] +enum Enum { //~ ERROR [+, -, o] + Foo(Covariant), + Bar(Contravariant), + Zed(Covariant,Contravariant) +} + +pub fn main() { } diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr new file mode 100644 index 000000000..9f7f1d9b0 --- /dev/null +++ b/tests/ui/variance/variance-types.stderr @@ -0,0 +1,38 @@ +error: [-, o, o] + --> $DIR/variance-types.rs:10:1 + | +LL | struct InvariantMut<'a,A:'a,B:'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o] + --> $DIR/variance-types.rs:15:1 + | +LL | struct InvariantCell { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o] + --> $DIR/variance-types.rs:20:1 + | +LL | struct InvariantIndirect { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [+] + --> $DIR/variance-types.rs:25:1 + | +LL | struct Covariant { + | ^^^^^^^^^^^^^^^^^^^ + +error: [-] + --> $DIR/variance-types.rs:30:1 + | +LL | struct Contravariant { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: [+, -, o] + --> $DIR/variance-types.rs:35:1 + | +LL | enum Enum { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/variance/variance-unused-region-param.rs b/tests/ui/variance/variance-unused-region-param.rs new file mode 100644 index 000000000..f0e4e03c9 --- /dev/null +++ b/tests/ui/variance/variance-unused-region-param.rs @@ -0,0 +1,7 @@ +// Test that we report an error for unused type parameters in types. + +struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used +enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used +trait SomeTrait<'a> { fn foo(&self); } // OK on traits. + +fn main() {} diff --git a/tests/ui/variance/variance-unused-region-param.stderr b/tests/ui/variance/variance-unused-region-param.stderr new file mode 100644 index 000000000..7c7ec40ba --- /dev/null +++ b/tests/ui/variance/variance-unused-region-param.stderr @@ -0,0 +1,19 @@ +error[E0392]: parameter `'a` is never used + --> $DIR/variance-unused-region-param.rs:3:19 + | +LL | struct SomeStruct<'a> { x: u32 } + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `'a` is never used + --> $DIR/variance-unused-region-param.rs:4:15 + | +LL | enum SomeEnum<'a> { Nothing } + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs new file mode 100644 index 000000000..d11140643 --- /dev/null +++ b/tests/ui/variance/variance-unused-type-param.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] + +// Test that we report an error for unused type parameters in types and traits, +// and that we offer a helpful suggestion. + +struct SomeStruct { x: u32 } +//~^ ERROR parameter `A` is never used + +enum SomeEnum { Nothing } +//~^ ERROR parameter `A` is never used + +// Here T might *appear* used, but in fact it isn't. +enum ListCell { +//~^ ERROR parameter `T` is never used + Cons(Box>), + Nil +} + +struct WithBounds {} +//~^ ERROR parameter `T` is never used + +struct WithWhereBounds where T: Sized {} +//~^ ERROR parameter `T` is never used + +struct WithOutlivesBounds {} +//~^ ERROR parameter `T` is never used + +fn main() {} diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr new file mode 100644 index 000000000..e612da118 --- /dev/null +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -0,0 +1,54 @@ +error[E0392]: parameter `A` is never used + --> $DIR/variance-unused-type-param.rs:6:19 + | +LL | struct SomeStruct { x: u32 } + | ^ unused parameter + | + = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `A` to be a const parameter, use `const A: usize` instead + +error[E0392]: parameter `A` is never used + --> $DIR/variance-unused-type-param.rs:9:15 + | +LL | enum SomeEnum { Nothing } + | ^ unused parameter + | + = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `A` to be a const parameter, use `const A: usize` instead + +error[E0392]: parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:13:15 + | +LL | enum ListCell { + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error[E0392]: parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:19:19 + | +LL | struct WithBounds {} + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:22:24 + | +LL | struct WithWhereBounds where T: Sized {} + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:25:27 + | +LL | struct WithOutlivesBounds {} + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-use-contravariant-struct-1.rs b/tests/ui/variance/variance-use-contravariant-struct-1.rs new file mode 100644 index 000000000..40781fbf0 --- /dev/null +++ b/tests/ui/variance/variance-use-contravariant-struct-1.rs @@ -0,0 +1,15 @@ +// Test various uses of structs with distinct variances to make sure +// they permit lifetimes to be approximated as expected. + +struct SomeStruct(fn(T)); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + + +fn main() { } diff --git a/tests/ui/variance/variance-use-contravariant-struct-1.stderr b/tests/ui/variance/variance-use-contravariant-struct-1.stderr new file mode 100644 index 000000000..50de7c90f --- /dev/null +++ b/tests/ui/variance/variance-use-contravariant-struct-1.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/variance-use-contravariant-struct-1.rs:10:5 + | +LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-use-contravariant-struct-2.rs b/tests/ui/variance/variance-use-contravariant-struct-2.rs new file mode 100644 index 000000000..d4b2d0834 --- /dev/null +++ b/tests/ui/variance/variance-use-contravariant-struct-2.rs @@ -0,0 +1,17 @@ +// Test various uses of structs with distinct variances to make sure +// they permit lifetimes to be approximated as expected. + +#![allow(dead_code)] +// build-pass (FIXME(62277): could be check-pass?) + +struct SomeStruct(fn(T)); + +fn bar<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v +} + + +fn main() { } diff --git a/tests/ui/variance/variance-use-covariant-struct-1.rs b/tests/ui/variance/variance-use-covariant-struct-1.rs new file mode 100644 index 000000000..f0fd7b26e --- /dev/null +++ b/tests/ui/variance/variance-use-covariant-struct-1.rs @@ -0,0 +1,14 @@ +// Test that a covariant struct does not permit the lifetime of a +// reference to be enlarged. + +struct SomeStruct(T); + +fn foo<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + +fn main() { } diff --git a/tests/ui/variance/variance-use-covariant-struct-1.stderr b/tests/ui/variance/variance-use-covariant-struct-1.stderr new file mode 100644 index 000000000..bab858c5a --- /dev/null +++ b/tests/ui/variance/variance-use-covariant-struct-1.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/variance-use-covariant-struct-1.rs:10:5 + | +LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + +error: aborting due to previous error + diff --git a/tests/ui/variance/variance-use-covariant-struct-2.rs b/tests/ui/variance/variance-use-covariant-struct-2.rs new file mode 100644 index 000000000..ecd2204c9 --- /dev/null +++ b/tests/ui/variance/variance-use-covariant-struct-2.rs @@ -0,0 +1,16 @@ +// Test that a covariant struct permits the lifetime of a reference to +// be shortened. + +#![allow(dead_code)] +// build-pass (FIXME(62277): could be check-pass?) + +struct SomeStruct(T); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v +} + +fn main() { } diff --git a/tests/ui/variance/variance-use-invariant-struct-1.rs b/tests/ui/variance/variance-use-invariant-struct-1.rs new file mode 100644 index 000000000..72f50f345 --- /dev/null +++ b/tests/ui/variance/variance-use-invariant-struct-1.rs @@ -0,0 +1,23 @@ +// Test various uses of structs with distinct variances to make sure +// they permit lifetimes to be approximated as expected. + +struct SomeStruct(*mut T); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + +fn bar<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v + //~^ ERROR lifetime may not live long enough +} + + +fn main() { } diff --git a/tests/ui/variance/variance-use-invariant-struct-1.stderr b/tests/ui/variance/variance-use-invariant-struct-1.stderr new file mode 100644 index 000000000..b9ca6e7d5 --- /dev/null +++ b/tests/ui/variance/variance-use-invariant-struct-1.stderr @@ -0,0 +1,34 @@ +error: lifetime may not live long enough + --> $DIR/variance-use-invariant-struct-1.rs:10:5 + | +LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + = note: requirement occurs because of the type `SomeStruct<&()>`, which makes the generic argument `&()` invariant + = note: the struct `SomeStruct` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/variance-use-invariant-struct-1.rs:18:5 + | +LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) + | ---- ---- lifetime `'max` defined here + | | + | lifetime `'min` defined here +... +LL | v + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | + = help: consider adding the following bound: `'min: 'max` + = note: requirement occurs because of the type `SomeStruct<&()>`, which makes the generic argument `&()` invariant + = note: the struct `SomeStruct` is invariant over the parameter `T` + = help: see for more information about variance + +error: aborting due to 2 previous errors + diff --git a/tests/ui/variants/auxiliary/variant-namespacing.rs b/tests/ui/variants/auxiliary/variant-namespacing.rs new file mode 100644 index 000000000..7ba601a88 --- /dev/null +++ b/tests/ui/variants/auxiliary/variant-namespacing.rs @@ -0,0 +1,5 @@ +pub enum XE { + XStruct { a: u8 }, + XTuple(u8), + XUnit, +} diff --git a/tests/ui/variants/variant-namespacing.rs b/tests/ui/variants/variant-namespacing.rs new file mode 100644 index 000000000..975e471fe --- /dev/null +++ b/tests/ui/variants/variant-namespacing.rs @@ -0,0 +1,33 @@ +// aux-build:variant-namespacing.rs + +pub enum E { + Struct { a: u8 }, + Tuple(u8), + Unit, +} + +type Struct = u8; +type Tuple = u8; +type Unit = u8; +type XStruct = u8; +type XTuple = u8; +type XUnit = u8; + +const Struct: u8 = 0; +const Tuple: u8 = 0; +const Unit: u8 = 0; +const XStruct: u8 = 0; +const XTuple: u8 = 0; +const XUnit: u8 = 0; + +extern crate variant_namespacing; +pub use variant_namespacing::XE::{XStruct, XTuple, XUnit}; +//~^ ERROR the name `XStruct` is defined multiple times +//~| ERROR the name `XTuple` is defined multiple times +//~| ERROR the name `XUnit` is defined multiple times +pub use E::{Struct, Tuple, Unit}; +//~^ ERROR the name `Struct` is defined multiple times +//~| ERROR the name `Tuple` is defined multiple times +//~| ERROR the name `Unit` is defined multiple times + +fn main() {} diff --git a/tests/ui/variants/variant-namespacing.stderr b/tests/ui/variants/variant-namespacing.stderr new file mode 100644 index 000000000..9e91ff717 --- /dev/null +++ b/tests/ui/variants/variant-namespacing.stderr @@ -0,0 +1,93 @@ +error[E0255]: the name `XStruct` is defined multiple times + --> $DIR/variant-namespacing.rs:24:35 + | +LL | type XStruct = u8; + | ------------------ previous definition of the type `XStruct` here +... +LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit}; + | ^^^^^^^ `XStruct` reimported here + | + = note: `XStruct` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use variant_namespacing::XE::{XStruct as OtherXStruct, XTuple, XUnit}; + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `XTuple` is defined multiple times + --> $DIR/variant-namespacing.rs:24:44 + | +LL | type XTuple = u8; + | ----------------- previous definition of the type `XTuple` here +... +LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit}; + | ^^^^^^ `XTuple` reimported here + | + = note: `XTuple` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use variant_namespacing::XE::{XStruct, XTuple as OtherXTuple, XUnit}; + | ~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `XUnit` is defined multiple times + --> $DIR/variant-namespacing.rs:24:52 + | +LL | type XUnit = u8; + | ---------------- previous definition of the type `XUnit` here +... +LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit}; + | ^^^^^ `XUnit` reimported here + | + = note: `XUnit` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use variant_namespacing::XE::{XStruct, XTuple, XUnit as OtherXUnit}; + | ~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Struct` is defined multiple times + --> $DIR/variant-namespacing.rs:28:13 + | +LL | type Struct = u8; + | ----------------- previous definition of the type `Struct` here +... +LL | pub use E::{Struct, Tuple, Unit}; + | ^^^^^^ `Struct` reimported here + | + = note: `Struct` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use E::{Struct as OtherStruct, Tuple, Unit}; + | ~~~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Tuple` is defined multiple times + --> $DIR/variant-namespacing.rs:28:21 + | +LL | type Tuple = u8; + | ---------------- previous definition of the type `Tuple` here +... +LL | pub use E::{Struct, Tuple, Unit}; + | ^^^^^ `Tuple` reimported here + | + = note: `Tuple` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use E::{Struct, Tuple as OtherTuple, Unit}; + | ~~~~~~~~~~~~~~~~~~~ + +error[E0255]: the name `Unit` is defined multiple times + --> $DIR/variant-namespacing.rs:28:28 + | +LL | type Unit = u8; + | --------------- previous definition of the type `Unit` here +... +LL | pub use E::{Struct, Tuple, Unit}; + | ^^^^ `Unit` reimported here + | + = note: `Unit` must be defined only once in the type namespace of this module +help: you can use `as` to change the binding name of the import + | +LL | pub use E::{Struct, Tuple, Unit as OtherUnit}; + | ~~~~~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0255`. diff --git a/tests/ui/variants/variant-size-differences.rs b/tests/ui/variants/variant-size-differences.rs new file mode 100644 index 000000000..219819951 --- /dev/null +++ b/tests/ui/variants/variant-size-differences.rs @@ -0,0 +1,8 @@ +#![deny(variant_size_differences)] + +enum _En { + V0(u8), + VBig([u8; 1024]), //~ ERROR variant is more than three times larger +} + +fn main() {} diff --git a/tests/ui/variants/variant-size-differences.stderr b/tests/ui/variants/variant-size-differences.stderr new file mode 100644 index 000000000..241a757d4 --- /dev/null +++ b/tests/ui/variants/variant-size-differences.stderr @@ -0,0 +1,14 @@ +error: enum variant is more than three times larger (1024 bytes) than the next largest + --> $DIR/variant-size-differences.rs:5:5 + | +LL | VBig([u8; 1024]), + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/variant-size-differences.rs:1:9 + | +LL | #![deny(variant_size_differences)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/variants/variant-used-as-type.rs b/tests/ui/variants/variant-used-as-type.rs new file mode 100644 index 000000000..f27db1024 --- /dev/null +++ b/tests/ui/variants/variant-used-as-type.rs @@ -0,0 +1,20 @@ +// Test error message when enum variants are used as types + + +// issue 21225 +enum Ty { + A, + B(Ty::A), + //~^ ERROR expected type, found variant `Ty::A` +} + + +// issue 19197 +enum E { + A +} + +impl E::A {} +//~^ ERROR expected type, found variant `E::A` + +fn main() {} diff --git a/tests/ui/variants/variant-used-as-type.stderr b/tests/ui/variants/variant-used-as-type.stderr new file mode 100644 index 000000000..64424abbc --- /dev/null +++ b/tests/ui/variants/variant-used-as-type.stderr @@ -0,0 +1,29 @@ +error[E0573]: expected type, found variant `Ty::A` + --> $DIR/variant-used-as-type.rs:7:7 + | +LL | B(Ty::A), + | ^^^^^ not a type + | +help: try using the variant's enum + | +LL | B(E), + | ~ +LL | B(Ty), + | ~~ + +error[E0573]: expected type, found variant `E::A` + --> $DIR/variant-used-as-type.rs:17:6 + | +LL | impl E::A {} + | ^^^^ not a type + | +help: try using the variant's enum + | +LL | impl E {} + | ~ +LL | impl Ty {} + | ~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs new file mode 100644 index 000000000..674c26a43 --- /dev/null +++ b/tests/ui/wait-forked-but-failed-child.rs @@ -0,0 +1,63 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-vxworks no 'ps' +// ignore-fuchsia no 'ps' + +#![feature(rustc_private)] + +extern crate libc; + +use std::process::Command; + +// The output from "ps -A -o pid,ppid,args" should look like this: +// PID PPID COMMAND +// 1 0 /sbin/init +// 2 0 [kthreadd] +// ... +// 6076 9064 /bin/zsh +// ... +// 7164 6076 ./spawn-failure +// 7165 7164 [spawn-failure] +// 7166 7164 [spawn-failure] +// ... +// 7197 7164 [spawn-failure] +// 7198 7164 ps -A -o pid,ppid,command +// ... + +#[cfg(unix)] +fn find_zombies() { + let my_pid = unsafe { libc::getpid() }; + + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html + let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap(); + let ps_output = String::from_utf8_lossy(&ps_cmd_output.stdout); + + for (line_no, line) in ps_output.split('\n').enumerate() { + if 0 < line_no && 0 < line.len() && + my_pid == line.split(' ').filter(|w| 0 < w.len()).nth(1) + .expect("1st column should be PPID") + .parse().ok() + .expect("PPID string into integer") && + line.contains("defunct") { + panic!("Zombie child {}", line); + } + } +} + +#[cfg(windows)] +fn find_zombies() { } + +fn main() { + let too_long = format!("/NoSuchCommand{:0300}", 0u8); + + let _failures = (0..100).map(|_| { + let mut cmd = Command::new(&too_long); + let failed = cmd.spawn(); + assert!(failed.is_err(), "Make sure the command fails to spawn(): {:?}", cmd); + failed + }).collect::>(); + + find_zombies(); + // then _failures goes out of scope +} diff --git a/tests/ui/walk-struct-literal-with.rs b/tests/ui/walk-struct-literal-with.rs new file mode 100644 index 000000000..ee1a77eb9 --- /dev/null +++ b/tests/ui/walk-struct-literal-with.rs @@ -0,0 +1,17 @@ +struct Mine{ + test: String, + other_val: isize +} + +impl Mine{ + fn make_string_bar(mut self) -> Mine{ + self.test = "Bar".to_string(); + self + } +} + +fn main(){ + let start = Mine{test:"Foo".to_string(), other_val:0}; + let end = Mine{other_val:1, ..start.make_string_bar()}; + println!("{}", start.test); //~ ERROR borrow of moved value: `start` +} diff --git a/tests/ui/walk-struct-literal-with.stderr b/tests/ui/walk-struct-literal-with.stderr new file mode 100644 index 000000000..2b85fa9be --- /dev/null +++ b/tests/ui/walk-struct-literal-with.stderr @@ -0,0 +1,20 @@ +error[E0382]: borrow of moved value: `start` + --> $DIR/walk-struct-literal-with.rs:16:20 + | +LL | let start = Mine{test:"Foo".to_string(), other_val:0}; + | ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait +LL | let end = Mine{other_val:1, ..start.make_string_bar()}; + | ----------------- `start` moved due to this method call +LL | println!("{}", start.test); + | ^^^^^^^^^^ value borrowed here after move + | +note: `Mine::make_string_bar` takes ownership of the receiver `self`, which moves `start` + --> $DIR/walk-struct-literal-with.rs:7:28 + | +LL | fn make_string_bar(mut self) -> Mine{ + | ^^^^ + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/wasm-custom-section-relocations.rs b/tests/ui/wasm-custom-section-relocations.rs new file mode 100644 index 000000000..c3cca3a35 --- /dev/null +++ b/tests/ui/wasm-custom-section-relocations.rs @@ -0,0 +1,15 @@ +// only-wasm32 + +#[link_section = "test"] +pub static A: &[u8] = &[1]; //~ ERROR: no extra levels of indirection + +#[link_section = "test"] +pub static B: [u8; 3] = [1, 2, 3]; + +#[link_section = "test"] +pub static C: usize = 3; + +#[link_section = "test"] +pub static D: &usize = &C; //~ ERROR: no extra levels of indirection + +fn main() {} diff --git a/tests/ui/wasm-custom-section-relocations.stderr b/tests/ui/wasm-custom-section-relocations.stderr new file mode 100644 index 000000000..a37edc51d --- /dev/null +++ b/tests/ui/wasm-custom-section-relocations.stderr @@ -0,0 +1,14 @@ +error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references + --> $DIR/wasm-custom-section-relocations.rs:4:1 + | +LL | pub static A: &[u8] = &[1]; + | ^^^^^^^^^^^^^^^^^^^ + +error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references + --> $DIR/wasm-custom-section-relocations.rs:13:1 + | +LL | pub static D: &usize = &C; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/wasm/simd-to-array-80108.rs b/tests/ui/wasm/simd-to-array-80108.rs new file mode 100644 index 000000000..0576c2e6b --- /dev/null +++ b/tests/ui/wasm/simd-to-array-80108.rs @@ -0,0 +1,15 @@ +// only-wasm32 +// compile-flags: --crate-type=lib -Copt-level=2 +// build-pass +#![feature(repr_simd)] + +// Regression test for #80108 + +#[repr(simd)] +pub struct Vector([i32; 4]); + +impl Vector { + pub const fn to_array(self) -> [i32; 4] { + self.0 + } +} diff --git a/tests/ui/wasm/wasm-hang-issue-76281.rs b/tests/ui/wasm/wasm-hang-issue-76281.rs new file mode 100644 index 000000000..a4adfa6d0 --- /dev/null +++ b/tests/ui/wasm/wasm-hang-issue-76281.rs @@ -0,0 +1,12 @@ +// only-wasm32 +// compile-flags: -C opt-level=2 +// build-pass + +// Regression test for #76281. +// This seems like an issue related to LLVM rather than +// libs-impl so place here. + +fn main() { + let mut v: Vec<&()> = Vec::new(); + v.sort_by_key(|&r| r as *const ()); +} diff --git a/tests/ui/wasm/wasm-import-module.rs b/tests/ui/wasm/wasm-import-module.rs new file mode 100644 index 000000000..bff08847d --- /dev/null +++ b/tests/ui/wasm/wasm-import-module.rs @@ -0,0 +1,21 @@ +#![feature(link_cfg)] + +#[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form +extern "C" {} + +#[link(name = "...", wasm_import_module(x))] //~ ERROR: must be of the form +extern "C" {} + +#[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form +extern "C" {} + +#[link(wasm_import_module = "foo", name = "bar")] //~ ERROR: `wasm_import_module` is incompatible with other arguments +extern "C" {} + +#[link(wasm_import_module = "foo", kind = "dylib")] //~ ERROR: `wasm_import_module` is incompatible with other arguments +extern "C" {} + +#[link(wasm_import_module = "foo", cfg(FALSE))] //~ ERROR: `wasm_import_module` is incompatible with other arguments +extern "C" {} + +fn main() {} diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr new file mode 100644 index 000000000..e792c33e9 --- /dev/null +++ b/tests/ui/wasm/wasm-import-module.stderr @@ -0,0 +1,38 @@ +error: wasm import module must be of the form `wasm_import_module = "string"` + --> $DIR/wasm-import-module.rs:3:22 + | +LL | #[link(name = "...", wasm_import_module)] + | ^^^^^^^^^^^^^^^^^^ + +error: wasm import module must be of the form `wasm_import_module = "string"` + --> $DIR/wasm-import-module.rs:6:22 + | +LL | #[link(name = "...", wasm_import_module(x))] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: wasm import module must be of the form `wasm_import_module = "string"` + --> $DIR/wasm-import-module.rs:9:22 + | +LL | #[link(name = "...", wasm_import_module())] + | ^^^^^^^^^^^^^^^^^^^^ + +error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes + --> $DIR/wasm-import-module.rs:12:8 + | +LL | #[link(wasm_import_module = "foo", name = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes + --> $DIR/wasm-import-module.rs:15:8 + | +LL | #[link(wasm_import_module = "foo", kind = "dylib")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes + --> $DIR/wasm-import-module.rs:18:8 + | +LL | #[link(wasm_import_module = "foo", cfg(FALSE))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/weak-new-uninhabited-issue-48493.rs b/tests/ui/weak-new-uninhabited-issue-48493.rs new file mode 100644 index 000000000..39fbf3c9e --- /dev/null +++ b/tests/ui/weak-new-uninhabited-issue-48493.rs @@ -0,0 +1,7 @@ +// run-pass + +fn main() { + enum Void {} + let _ = std::rc::Weak::::new(); + let _ = std::sync::Weak::::new(); +} diff --git a/tests/ui/weird-exit-code.rs b/tests/ui/weird-exit-code.rs new file mode 100644 index 000000000..a067b7b5b --- /dev/null +++ b/tests/ui/weird-exit-code.rs @@ -0,0 +1,28 @@ +// run-pass +// On Windows the GetExitCodeProcess API is used to get the exit code of a +// process, but it's easy to mistake a process exiting with the code 259 as +// "still running" because this is the value of the STILL_ACTIVE constant. Make +// sure we handle this case in the standard library and correctly report the +// status. +// +// Note that this is disabled on unix as processes exiting with 259 will have +// their exit status truncated to 3 (only the lower 8 bits are used). + +#[cfg(windows)] +fn main() { + use std::process::{self, Command}; + use std::env; + + if env::args().len() == 1 { + let status = Command::new(env::current_exe().unwrap()) + .arg("foo") + .status() + .unwrap(); + assert_eq!(status.code(), Some(259)); + } else { + process::exit(259); + } +} + +#[cfg(not(windows))] +fn main() {} diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs new file mode 100644 index 000000000..d65703ef5 --- /dev/null +++ b/tests/ui/weird-exprs.rs @@ -0,0 +1,230 @@ +// run-pass + +#![feature(generators)] +#![feature(unboxed_closures, fn_traits)] + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unreachable_code)] +#![allow(unused_braces, unused_must_use, unused_parens)] +#![allow(uncommon_codepoints, confusable_idents)] +#![allow(unreachable_patterns)] + +#![recursion_limit = "256"] + +use std::cell::Cell; +use std::mem::swap; + +// Just a grab bag of stuff that you wouldn't want to actually write. + +fn strange() -> bool { let _x: bool = return true; } + +fn funny() { + fn f(_x: ()) { } + f(return); +} + +fn what() { + fn the(x: &Cell) { + return while !x.get() { x.set(true); }; + } + let i = &Cell::new(false); + let dont = {||the(i)}; + dont(); + assert!((i.get())); +} + +fn zombiejesus() { + loop { + while (return) { + if (return) { + match (return) { + 1 => { + if (return) { + return + } else { + return + } + } + _ => { return } + }; + } else if (return) { + return; + } + } + if (return) { break; } + } +} + +fn notsure() { + let mut _x: isize; + let mut _y = (_x = 0) == (_x = 0); + let mut _z = (_x = 0) < (_x = 0); + let _a = (_x += 0) == (_x = 0); + let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z); +} + +fn canttouchthis() -> usize { + fn p() -> bool { true } + let _a = (assert!((true)) == (assert!(p()))); + let _c = (assert!((p())) == ()); + let _b: bool = (println!("{}", 0) == (return 0)); +} + +fn angrydome() { + loop { if break { } } + let mut i = 0; + loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } } + break; } +} + +fn evil_lincoln() { let _evil = println!("lincoln"); } + +fn dots() { + assert_eq!(String::from(".................................................."), + format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. .. + .. .. .. .. .. .. .. .. .. .. .. ..)); +} + +fn u8(u8: u8) { + if u8 != 0u8 { + assert_eq!(8u8, { + macro_rules! u8 { + (u8) => { + mod u8 { + pub fn u8<'u8: 'u8 + 'u8>(u8: &'u8 u8) -> &'u8 u8 { + "u8"; + u8 + } + } + }; + } + + u8!(u8); + let &u8: &u8 = u8::u8(&8u8); + ::u8(0u8); + u8 + }); + } +} + +fn fishy() { + assert_eq!(String::from("><>"), + String::<>::from::<>("><>").chars::<>().rev::<>().collect::()); +} + +fn union() { + union union<'union> { union: &'union union<'union>, } +} + +fn special_characters() { + let val = !((|(..):(_,_),(|__@_|__)|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})// + ; + assert!(!val); +} + +fn punch_card() -> impl std::fmt::Debug { + ..=..=.. .. .. .. .. .. .. .. .. .. .. ..=.. .. + ..=.. ..=.. .. .. .. .. .. .. .. .. ..=..=..=.. + ..=.. ..=.. ..=.. ..=.. .. ..=..=.. .. ..=.. .. + ..=..=.. .. ..=.. ..=.. ..=.. .. .. .. ..=.. .. + ..=.. ..=.. ..=.. ..=.. .. ..=.. .. .. ..=.. .. + ..=.. ..=.. ..=.. ..=.. .. .. ..=.. .. ..=.. .. + ..=.. ..=.. .. ..=..=.. ..=..=.. .. .. ..=.. .. +} + +fn r#match() { + let val = match match match match match () { + () => () + } { + () => () + } { + () => () + } { + () => () + } { + () => () + }; + assert_eq!(val, ()); +} + +fn i_yield() { + static || { + yield yield yield yield yield yield yield yield yield; + }; +} + +fn match_nested_if() { + let val = match () { + () if if if if true {true} else {false} {true} else {false} {true} else {false} => true, + _ => false, + }; + assert!(val); +} + +fn monkey_barrel() { + let val = ()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=()=(); + assert_eq!(val, ()); +} + +fn ðšŒðš˜ðš—ðšðš’ðš—ðšžðšŽ() { + type ðš•ðš˜ðš˜ðš™ = i32; + fn ðš‹ðš›ðšŽðšŠðš”() -> ðš•ðš˜ðš˜ðš™ { + let ðš›ðšŽðšðšžðš›ðš— = 42; + return ðš›ðšŽðšðšžðš›ðš—; + } + assert_eq!(loop { + break ðš‹ðš›ðšŽðšŠðš” (); + }, 42); +} + +fn function() { + struct foo; + impl FnOnce<()> for foo { + type Output = foo; + extern "rust-call" fn call_once(self, _args: ()) -> Self::Output { + foo + } + } + let foo = foo () ()() ()()() ()()()() ()()()()(); +} + +fn bathroom_stall() { + let mut i = 1; + matches!(2, _|_|_|_|_|_ if (i+=1) != (i+=1)); + assert_eq!(i, 13); +} + +fn closure_matching() { + let x = |_| Some(1); + let (|x| x) = match x(..) { + |_| Some(2) => |_| Some(3), + |_| _ => unreachable!(), + }; + assert!(matches!(x(..), |_| Some(4))); +} + +pub fn main() { + strange(); + funny(); + what(); + zombiejesus(); + notsure(); + canttouchthis(); + angrydome(); + evil_lincoln(); + dots(); + u8(8u8); + fishy(); + union(); + special_characters(); + punch_card(); + r#match(); + i_yield(); + match_nested_if(); + monkey_barrel(); + ðšŒðš˜ðš—ðšðš’ðš—ðšžðšŽ(); + function(); + bathroom_stall(); + closure_matching(); +} diff --git a/tests/ui/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs new file mode 100644 index 000000000..bdb84409d --- /dev/null +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -0,0 +1,18 @@ +// incremental + +trait Foo { + type V; +} + +trait Callback: Fn(&Bar<'_, T>, &T::V) {} + +struct Bar<'a, T> { + callback: Box>>>, + //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied + //~| ERROR the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time +} + +impl Bar<'_, Bar<'_, T>> {} + +fn main() {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr new file mode 100644 index 000000000..9fd0f9c81 --- /dev/null +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `Bar<'a, T>: Foo` is not satisfied + --> $DIR/hir-wf-canonicalized.rs:10:15 + | +LL | callback: Box>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bar<'a, T>` + +error[E0277]: the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied + --> $DIR/hir-wf-canonicalized.rs:10:15 + | +LL | callback: Box>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` + +error[E0277]: the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time + --> $DIR/hir-wf-canonicalized.rs:10:15 + | +LL | callback: Box>>>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` +note: required by a bound in `Bar` + --> $DIR/hir-wf-canonicalized.rs:9:16 + | +LL | struct Bar<'a, T> { + | ^ required by this bound in `Bar` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Bar<'a, T: ?Sized> { + | ++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs new file mode 100644 index 000000000..2b4b480df --- /dev/null +++ b/tests/ui/wf/hir-wf-check-erase-regions.rs @@ -0,0 +1,14 @@ +// Regression test for #87549. +// incremental + +pub struct Table([Option; N]); + +impl<'a, T, const N: usize> IntoIterator for &'a Table { + type IntoIter = std::iter::Flatten>; //~ ERROR `&T` is not an iterator + type Item = &'a T; + + fn into_iter(self) -> Self::IntoIter { //~ ERROR `&T` is not an iterator + unimplemented!() + } +} +fn main() {} diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr new file mode 100644 index 000000000..7bc19dd2e --- /dev/null +++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr @@ -0,0 +1,27 @@ +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:7:21 + | +LL | type IntoIter = std::iter::Flatten>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` + = note: required for `&T` to implement `IntoIterator` +note: required by a bound in `Flatten` + --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL + +error[E0277]: `&T` is not an iterator + --> $DIR/hir-wf-check-erase-regions.rs:10:27 + | +LL | fn into_iter(self) -> Self::IntoIter { + | ^^^^^^^^^^^^^^ `&T` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&T` + = help: the trait `Iterator` is implemented for `&mut I` + = note: required for `&T` to implement `IntoIterator` +note: required by a bound in `Flatten` + --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-103573.rs b/tests/ui/wf/issue-103573.rs new file mode 100644 index 000000000..bcbf4f941 --- /dev/null +++ b/tests/ui/wf/issue-103573.rs @@ -0,0 +1,22 @@ +trait TraitA { + type TypeA; +} + +trait TraitD { + type TypeD; +} + +pub trait TraitB { + type TypeB: TraitD; + + fn f(_: &::TypeD); +} + +pub trait TraitC { + type TypeC<'a>: TraitB; + + fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA); + //~^ ERROR the trait bound `<>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied +} + +fn main() {} diff --git a/tests/ui/wf/issue-103573.stderr b/tests/ui/wf/issue-103573.stderr new file mode 100644 index 000000000..5227badb7 --- /dev/null +++ b/tests/ui/wf/issue-103573.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `<>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied + --> $DIR/issue-103573.rs:18:18 + | +LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<>::TypeC<'a> as TraitB>::TypeB` + | +help: consider further restricting the associated type + | +LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA) where <>::TypeC<'a> as TraitB>::TypeB: TraitA; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-48638.rs b/tests/ui/wf/issue-48638.rs new file mode 100644 index 000000000..f07843103 --- /dev/null +++ b/tests/ui/wf/issue-48638.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait D {} +pub struct DT; +impl D for DT {} + +pub trait A: Sized { + type AS; +} + +pub struct As(R); + +pub struct AT; +impl A for AT { + type AS = As; +} + +#[repr(packed)] +struct S(>::AS); + +fn main() {} diff --git a/tests/ui/wf/issue-87495.rs b/tests/ui/wf/issue-87495.rs new file mode 100644 index 000000000..5aab74311 --- /dev/null +++ b/tests/ui/wf/issue-87495.rs @@ -0,0 +1,8 @@ +// Regression test for the ICE described in #87495. + +trait T { + const CONST: (bool, dyn T); + //~^ ERROR: the trait `T` cannot be made into an object [E0038] +} + +fn main() {} diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr new file mode 100644 index 000000000..c924cd879 --- /dev/null +++ b/tests/ui/wf/issue-87495.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `T` cannot be made into an object + --> $DIR/issue-87495.rs:4:25 + | +LL | const CONST: (bool, dyn T); + | ^^^^^ `T` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-87495.rs:4:11 + | +LL | trait T { + | - this trait cannot be made into an object... +LL | const CONST: (bool, dyn T); + | ^^^^^ ...because it contains this associated `const` + = help: consider moving `CONST` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/issue-95665.rs b/tests/ui/wf/issue-95665.rs new file mode 100644 index 000000000..67923cbb2 --- /dev/null +++ b/tests/ui/wf/issue-95665.rs @@ -0,0 +1,18 @@ +// Regression test for the ICE described in #95665. +// Ensure that the expected error is output (and thus that there is no ICE) + +pub trait Trait: {} + +pub struct Struct { + member: T, +} + +// uncomment and bug goes away +// impl Trait for u8 {} + +extern "C" { + static VAR: Struct; + //~^ 14:17: 14:27: the trait bound `u8: Trait` is not satisfied [E0277] +} + +fn main() {} diff --git a/tests/ui/wf/issue-95665.stderr b/tests/ui/wf/issue-95665.stderr new file mode 100644 index 000000000..b1cda59a9 --- /dev/null +++ b/tests/ui/wf/issue-95665.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u8: Trait` is not satisfied + --> $DIR/issue-95665.rs:14:17 + | +LL | static VAR: Struct; + | ^^^^^^^^^^ the trait `Trait` is not implemented for `u8` + | +note: required by a bound in `Struct` + --> $DIR/issue-95665.rs:6:22 + | +LL | pub struct Struct { + | ^^^^^ required by this bound in `Struct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/issue-96810.rs b/tests/ui/wf/issue-96810.rs new file mode 100644 index 000000000..c2948086b --- /dev/null +++ b/tests/ui/wf/issue-96810.rs @@ -0,0 +1,12 @@ +struct S(T::Assoc); + +trait Tr { + type Assoc; +} + +struct Hoge { + s: S, //~ ERROR the trait bound `K: Tr` is not satisfied + a: u32, +} + +fn main() {} diff --git a/tests/ui/wf/issue-96810.stderr b/tests/ui/wf/issue-96810.stderr new file mode 100644 index 000000000..1407e62b1 --- /dev/null +++ b/tests/ui/wf/issue-96810.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `K: Tr` is not satisfied + --> $DIR/issue-96810.rs:8:8 + | +LL | s: S, + | ^^^^ the trait `Tr` is not implemented for `K` + | +note: required by a bound in `S` + --> $DIR/issue-96810.rs:1:13 + | +LL | struct S(T::Assoc); + | ^^ required by this bound in `S` +help: consider restricting type parameter `K` + | +LL | struct Hoge { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-array-elem-sized.rs b/tests/ui/wf/wf-array-elem-sized.rs new file mode 100644 index 000000000..34bf22034 --- /dev/null +++ b/tests/ui/wf/wf-array-elem-sized.rs @@ -0,0 +1,11 @@ +// Check that array element types must be Sized. Issue #25692. + + +#![allow(dead_code)] + +struct Foo { + foo: [[u8]], //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-array-elem-sized.stderr b/tests/ui/wf/wf-array-elem-sized.stderr new file mode 100644 index 000000000..7f3c58d6b --- /dev/null +++ b/tests/ui/wf/wf-array-elem-sized.stderr @@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-array-elem-sized.rs:7:10 + | +LL | foo: [[u8]], + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: slice and array elements must have `Sized` type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-complex-assoc-type.rs b/tests/ui/wf/wf-complex-assoc-type.rs new file mode 100644 index 000000000..c3811e823 --- /dev/null +++ b/tests/ui/wf/wf-complex-assoc-type.rs @@ -0,0 +1,12 @@ +trait MyTrait {} +struct AssertMyTrait(T); + +trait HelperTrait { + type MyItem; +} + +impl HelperTrait for () { + type MyItem = Option<((AssertMyTrait, u8))>; //~ ERROR the trait bound +} + +fn main() {} diff --git a/tests/ui/wf/wf-complex-assoc-type.stderr b/tests/ui/wf/wf-complex-assoc-type.stderr new file mode 100644 index 000000000..ef613e313 --- /dev/null +++ b/tests/ui/wf/wf-complex-assoc-type.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `bool: MyTrait` is not satisfied + --> $DIR/wf-complex-assoc-type.rs:9:28 + | +LL | type MyItem = Option<((AssertMyTrait, u8))>; + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `bool` + | +note: required by a bound in `AssertMyTrait` + --> $DIR/wf-complex-assoc-type.rs:2:25 + | +LL | struct AssertMyTrait(T); + | ^^^^^^^ required by this bound in `AssertMyTrait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-const-type.rs b/tests/ui/wf/wf-const-type.rs new file mode 100644 index 000000000..df79aa267 --- /dev/null +++ b/tests/ui/wf/wf-const-type.rs @@ -0,0 +1,14 @@ +// Test that we check the types of constants are well-formed. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy { t: T } +struct NotCopy; + +const FOO: IsCopy> = IsCopy { t: None }; +//~^ ERROR E0277 + + +fn main() { } diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr new file mode 100644 index 000000000..85938364e --- /dev/null +++ b/tests/ui/wf/wf-const-type.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `NotCopy: Copy` is not satisfied + --> $DIR/wf-const-type.rs:10:12 + | +LL | const FOO: IsCopy> = IsCopy { t: None }; + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | + = note: required for `Option` to implement `Copy` +note: required by a bound in `IsCopy` + --> $DIR/wf-const-type.rs:7:17 + | +LL | struct IsCopy { t: T } + | ^^^^ required by this bound in `IsCopy` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs new file mode 100644 index 000000000..ffdb49a3b --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -0,0 +1,18 @@ +// Check that we do not allow casts or coercions +// to object unsafe trait objects inside a Box + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +fn takes_box(t: Box) {} + +fn main() { + Box::new(S) as Box; //~ ERROR E0038 + let t_box: Box = Box::new(S); //~ ERROR E0038 + takes_box(Box::new(S)); //~ ERROR E0038 +} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr new file mode 100644 index 000000000..6cf4f33f9 --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr @@ -0,0 +1,51 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 + | +LL | let t_box: Box = Box::new(S); + | ^^^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `Box` to implement `CoerceUnsized>` + = note: required by cast to type `Box` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 + | +LL | takes_box(Box::new(S)); + | ^^^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `Box` to implement `CoerceUnsized>` + = note: required by cast to type `Box<(dyn Trait + 'static)>` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 + | +LL | Box::new(S) as Box; + | ^^^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `Box` to implement `CoerceUnsized>` + = note: required by cast to type `Box` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs new file mode 100644 index 000000000..143b854ed --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -0,0 +1,18 @@ +// Check that we do not allow casts or coercions +// to object unsafe trait objects by ref + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +fn takes_trait(t: &dyn Trait) {} + +fn main() { + &S as &dyn Trait; //~ ERROR E0038 + let t: &dyn Trait = &S; //~ ERROR E0038 + takes_trait(&S); //~ ERROR E0038 +} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr new file mode 100644 index 000000000..c9bd4549a --- /dev/null +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr @@ -0,0 +1,51 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 + | +LL | let t: &dyn Trait = &S; + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 + | +LL | takes_trait(&S); + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 + | +LL | &S as &dyn Trait; + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-enum-bound.rs b/tests/ui/wf/wf-enum-bound.rs new file mode 100644 index 000000000..042a2cb09 --- /dev/null +++ b/tests/ui/wf/wf-enum-bound.rs @@ -0,0 +1,16 @@ +// Test that we check enum bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy { } + +enum SomeEnum + where T: ExtraCopy //~ ERROR E0277 +{ + SomeVariant(T,U) +} + + +fn main() { } diff --git a/tests/ui/wf/wf-enum-bound.stderr b/tests/ui/wf/wf-enum-bound.stderr new file mode 100644 index 000000000..d39fc0c6a --- /dev/null +++ b/tests/ui/wf/wf-enum-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-enum-bound.rs:10:14 + | +LL | where T: ExtraCopy + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-enum-bound.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | where T: ExtraCopy, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.rs b/tests/ui/wf/wf-enum-fields-struct-variant.rs new file mode 100644 index 000000000..c25622fa7 --- /dev/null +++ b/tests/ui/wf/wf-enum-fields-struct-variant.rs @@ -0,0 +1,18 @@ +// Test that we check struct fields for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy { + value: T +} + +enum AnotherEnum { + AnotherVariant { + f: IsCopy //~ ERROR E0277 + } +} + + +fn main() { } diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.stderr b/tests/ui/wf/wf-enum-fields-struct-variant.stderr new file mode 100644 index 000000000..c12d62521 --- /dev/null +++ b/tests/ui/wf/wf-enum-fields-struct-variant.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A: Copy` is not satisfied + --> $DIR/wf-enum-fields-struct-variant.rs:13:12 + | +LL | f: IsCopy + | ^^^^^^^^^ the trait `Copy` is not implemented for `A` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-enum-fields-struct-variant.rs:7:17 + | +LL | struct IsCopy { + | ^^^^ required by this bound in `IsCopy` +help: consider restricting type parameter `A` + | +LL | enum AnotherEnum { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-enum-fields.rs b/tests/ui/wf/wf-enum-fields.rs new file mode 100644 index 000000000..a465ffe5e --- /dev/null +++ b/tests/ui/wf/wf-enum-fields.rs @@ -0,0 +1,16 @@ +// Test that we check struct fields for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy { + value: T +} + +enum SomeEnum { + SomeVariant(IsCopy) //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-enum-fields.stderr b/tests/ui/wf/wf-enum-fields.stderr new file mode 100644 index 000000000..ac3301a96 --- /dev/null +++ b/tests/ui/wf/wf-enum-fields.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A: Copy` is not satisfied + --> $DIR/wf-enum-fields.rs:12:17 + | +LL | SomeVariant(IsCopy) + | ^^^^^^^^^ the trait `Copy` is not implemented for `A` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-enum-fields.rs:7:17 + | +LL | struct IsCopy { + | ^^^^ required by this bound in `IsCopy` +help: consider restricting type parameter `A` + | +LL | enum SomeEnum { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-fn-where-clause.rs b/tests/ui/wf/wf-fn-where-clause.rs new file mode 100644 index 000000000..adae53613 --- /dev/null +++ b/tests/ui/wf/wf-fn-where-clause.rs @@ -0,0 +1,20 @@ +// Test that we check where-clauses on fn items. + + +#![allow(dead_code)] + +trait ExtraCopy { } + +fn foo() where T: ExtraCopy //~ ERROR E0277 +{ +} + +fn bar() where Vec:, {} +//~^ ERROR E0277 +//~| ERROR E0038 + +struct Vec { + t: T, +} + +fn main() { } diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr new file mode 100644 index 000000000..2aec641e7 --- /dev/null +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -0,0 +1,49 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-fn-where-clause.rs:8:24 + | +LL | fn foo() where T: ExtraCopy + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-fn-where-clause.rs:6:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | fn foo() where T: ExtraCopy, U: std::marker::Copy + | ++++++++++++++++++++++ + +error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time + --> $DIR/wf-fn-where-clause.rs:12:16 + | +LL | fn bar() where Vec:, {} + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` +note: required by a bound in `Vec` + --> $DIR/wf-fn-where-clause.rs:16:12 + | +LL | struct Vec { + | ^ required by this bound in `Vec` +help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` + --> $DIR/wf-fn-where-clause.rs:16:12 + | +LL | struct Vec { + | ^ this could be changed to `T: ?Sized`... +LL | t: T, + | - ...if indirection were used here: `Box` + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/wf-fn-where-clause.rs:12:16 + | +LL | fn bar() where Vec:, {} + | ^^^^^^^^^^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-foreign-fn-decl-ret.rs b/tests/ui/wf/wf-foreign-fn-decl-ret.rs new file mode 100644 index 000000000..b9d956c05 --- /dev/null +++ b/tests/ui/wf/wf-foreign-fn-decl-ret.rs @@ -0,0 +1,18 @@ +pub trait Unsatisfied {} + +#[repr(transparent)] +pub struct Bar(T); + +pub trait Foo { + type Assoc; +} + +extern "C" { + pub fn lint_me() -> <() as Foo>::Assoc; + //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] + + pub fn lint_me_aswell() -> Bar; + //~^ ERROR: the trait bound `u32: Unsatisfied` is not satisfied [E0277] +} + +fn main() {} diff --git a/tests/ui/wf/wf-foreign-fn-decl-ret.stderr b/tests/ui/wf/wf-foreign-fn-decl-ret.stderr new file mode 100644 index 000000000..b03023b5f --- /dev/null +++ b/tests/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/wf-foreign-fn-decl-ret.rs:11:25 + | +LL | pub fn lint_me() -> <() as Foo>::Assoc; + | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + +error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied + --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 + | +LL | pub fn lint_me_aswell() -> Bar; + | ^^^^^^^^ the trait `Unsatisfied` is not implemented for `u32` + | +note: required by a bound in `Bar` + --> $DIR/wf-foreign-fn-decl-ret.rs:4:19 + | +LL | pub struct Bar(T); + | ^^^^^^^^^^^ required by this bound in `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-impl-associated-type-region.rs b/tests/ui/wf/wf-impl-associated-type-region.rs new file mode 100644 index 000000000..1bf8d3663 --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-region.rs @@ -0,0 +1,14 @@ +// Check that we require that associated types in an impl are well-formed. + + + +pub trait Foo<'a> { + type Bar; +} + +impl<'a, T> Foo<'a> for T { + type Bar = &'a T; //~ ERROR E0309 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-impl-associated-type-region.stderr b/tests/ui/wf/wf-impl-associated-type-region.stderr new file mode 100644 index 000000000..b9d4857a3 --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-region.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/wf-impl-associated-type-region.rs:10:16 + | +LL | type Bar = &'a T; + | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Foo<'a> for T { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-impl-associated-type-trait.rs b/tests/ui/wf/wf-impl-associated-type-trait.rs new file mode 100644 index 000000000..84e628e21 --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-trait.rs @@ -0,0 +1,22 @@ +// Check that we require that associated types in an impl are well-formed. + + +#![allow(dead_code)] + +pub trait MyHash { } + +pub struct MySet { + data: Vec +} + +pub trait Foo { + type Bar; +} + +impl Foo for T { + type Bar = MySet; + //~^ ERROR the trait bound `T: MyHash` is not satisfied +} + + +fn main() { } diff --git a/tests/ui/wf/wf-impl-associated-type-trait.stderr b/tests/ui/wf/wf-impl-associated-type-trait.stderr new file mode 100644 index 000000000..bdf8bba5e --- /dev/null +++ b/tests/ui/wf/wf-impl-associated-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: MyHash` is not satisfied + --> $DIR/wf-impl-associated-type-trait.rs:17:16 + | +LL | type Bar = MySet; + | ^^^^^^^^ the trait `MyHash` is not implemented for `T` + | +note: required by a bound in `MySet` + --> $DIR/wf-impl-associated-type-trait.rs:8:20 + | +LL | pub struct MySet { + | ^^^^^^ required by this bound in `MySet` +help: consider restricting type parameter `T` + | +LL | impl Foo for T { + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-impl-self-type.rs b/tests/ui/wf/wf-impl-self-type.rs new file mode 100644 index 000000000..2dd9b4ef0 --- /dev/null +++ b/tests/ui/wf/wf-impl-self-type.rs @@ -0,0 +1,7 @@ +// Tests that we point at the proper location for an error +// involving the self-type of an impl + +trait Foo {} +impl Foo for Option<[u8]> {} //~ ERROR the size for + +fn main() {} diff --git a/tests/ui/wf/wf-impl-self-type.stderr b/tests/ui/wf/wf-impl-self-type.stderr new file mode 100644 index 000000000..1ca368729 --- /dev/null +++ b/tests/ui/wf/wf-impl-self-type.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/wf-impl-self-type.rs:5:14 + | +LL | impl Foo for Option<[u8]> {} + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `Option` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-arg.rs b/tests/ui/wf/wf-in-fn-arg.rs new file mode 100644 index 000000000..18df72336 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-arg.rs @@ -0,0 +1,14 @@ +// Check that we enforce WF conditions also for argument types in fn items. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +struct MustBeCopy { + t: T +} + +fn bar(_: &MustBeCopy) //~ ERROR E0277 +{ +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-arg.stderr b/tests/ui/wf/wf-in-fn-arg.stderr new file mode 100644 index 000000000..83a4a592a --- /dev/null +++ b/tests/ui/wf/wf-in-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-arg.rs:10:15 + | +LL | fn bar(_: &MustBeCopy) + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-arg.rs:6:21 + | +LL | struct MustBeCopy { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | fn bar(_: &MustBeCopy) + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-ret.rs b/tests/ui/wf/wf-in-fn-ret.rs new file mode 100644 index 000000000..4c9535184 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-ret.rs @@ -0,0 +1,14 @@ +// Check that we enforce WF conditions also for return types in fn items. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +struct MustBeCopy { + t: T +} + +fn bar() -> MustBeCopy //~ ERROR E0277 +{ +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-ret.stderr b/tests/ui/wf/wf-in-fn-ret.stderr new file mode 100644 index 000000000..7eeb97472 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-ret.rs:10:16 + | +LL | fn bar() -> MustBeCopy + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-ret.rs:6:21 + | +LL | struct MustBeCopy { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | fn bar() -> MustBeCopy + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-arg.rs b/tests/ui/wf/wf-in-fn-type-arg.rs new file mode 100644 index 000000000..2917a8aa9 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-arg.rs @@ -0,0 +1,12 @@ +// Check that we enforce WF conditions also for types in fns. + +struct MustBeCopy { + t: T +} + +struct Bar { + // needs T: Copy + x: fn(MustBeCopy) //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-type-arg.stderr b/tests/ui/wf/wf-in-fn-type-arg.stderr new file mode 100644 index 000000000..be5e9d418 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-type-arg.rs:9:11 + | +LL | x: fn(MustBeCopy) + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-type-arg.rs:3:21 + | +LL | struct MustBeCopy { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | struct Bar { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-ret.rs b/tests/ui/wf/wf-in-fn-type-ret.rs new file mode 100644 index 000000000..ab8e697e3 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-ret.rs @@ -0,0 +1,12 @@ +// Check that we enforce WF conditions also for types in fns. + +struct MustBeCopy { + t: T +} + +struct Foo { + // needs T: 'static + x: fn() -> MustBeCopy //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-type-ret.stderr b/tests/ui/wf/wf-in-fn-type-ret.stderr new file mode 100644 index 000000000..8fcfcb0b2 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-fn-type-ret.rs:9:16 + | +LL | x: fn() -> MustBeCopy + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-type-ret.rs:3:21 + | +LL | struct MustBeCopy { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | struct Foo { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-fn-type-static.rs b/tests/ui/wf/wf-in-fn-type-static.rs new file mode 100644 index 000000000..73071dd23 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-static.rs @@ -0,0 +1,22 @@ +// Check that we enforce WF conditions related to regions also for +// types in fns. + +#![allow(dead_code)] + + +struct MustBeCopy { + t: T +} + +struct Foo { + // needs T: 'static + x: fn() -> &'static T //~ ERROR E0310 +} + +struct Bar { + // needs T: Copy + x: fn(&'static T) //~ ERROR E0310 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-type-static.stderr b/tests/ui/wf/wf-in-fn-type-static.stderr new file mode 100644 index 000000000..73fbb9ca6 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-type-static.stderr @@ -0,0 +1,25 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-in-fn-type-static.rs:13:8 + | +LL | x: fn() -> &'static T + | ^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Foo { + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-in-fn-type-static.rs:18:8 + | +LL | x: fn(&'static T) + | ^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Bar { + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/wf/wf-in-fn-where-clause.rs b/tests/ui/wf/wf-in-fn-where-clause.rs new file mode 100644 index 000000000..e55295a3b --- /dev/null +++ b/tests/ui/wf/wf-in-fn-where-clause.rs @@ -0,0 +1,15 @@ +// Check that we enforce WF conditions also for where clauses in fn items. + + +#![allow(dead_code)] + +trait MustBeCopy { +} + +fn bar() + where T: MustBeCopy //~ ERROR E0277 +{ +} + + +fn main() { } diff --git a/tests/ui/wf/wf-in-fn-where-clause.stderr b/tests/ui/wf/wf-in-fn-where-clause.stderr new file mode 100644 index 000000000..160a73840 --- /dev/null +++ b/tests/ui/wf/wf-in-fn-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-in-fn-where-clause.rs:10:14 + | +LL | where T: MustBeCopy + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-fn-where-clause.rs:6:20 + | +LL | trait MustBeCopy { + | ^^^^ required by this bound in `MustBeCopy` +help: consider further restricting type parameter `U` + | +LL | where T: MustBeCopy, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs new file mode 100644 index 000000000..4fcf8f403 --- /dev/null +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs @@ -0,0 +1,17 @@ +// Regression test for #80468. + +#![crate_type = "lib"] + +pub trait Trait {} + +#[repr(transparent)] +pub struct Wrapper(T); + +#[repr(transparent)] +pub struct Ref<'a>(&'a u8); + +impl Trait for Ref {} //~ ERROR: implicit elided lifetime not allowed here + +extern "C" { + pub fn repro(_: Wrapper); //~ ERROR: incompatible lifetime on type +} diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr new file mode 100644 index 000000000..94f6dc266 --- /dev/null +++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr @@ -0,0 +1,37 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:16 + | +LL | impl Trait for Ref {} + | ^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +LL | impl Trait for Ref<'_> {} + | ++++ + +error: incompatible lifetime on type + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21 + | +LL | pub fn repro(_: Wrapper); + | ^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23 + | +LL | pub struct Wrapper(T); + | ^^^^^ introduces a `'static` lifetime requirement +note: the anonymous lifetime as defined here... + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:29 + | +LL | pub fn repro(_: Wrapper); + | ^^^ +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1 + | +LL | impl Trait for Ref {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/wf/wf-in-obj-type-static.rs b/tests/ui/wf/wf-in-obj-type-static.rs new file mode 100644 index 000000000..1ad2fd1ed --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-static.rs @@ -0,0 +1,18 @@ +// Check that we enforce WF conditions also for types in fns. + + +#![allow(dead_code)] + +trait Object { } + +struct MustBeCopy { + t: T +} + +struct Foo { + // needs T: 'static + x: dyn Object<&'static T> //~ ERROR E0310 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-in-obj-type-static.stderr b/tests/ui/wf/wf-in-obj-type-static.stderr new file mode 100644 index 000000000..c3ad42dd5 --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-static.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-in-obj-type-static.rs:14:8 + | +LL | x: dyn Object<&'static T> + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | struct Foo { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/wf/wf-in-obj-type-trait.rs b/tests/ui/wf/wf-in-obj-type-trait.rs new file mode 100644 index 000000000..170fad55f --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-trait.rs @@ -0,0 +1,14 @@ +// Check that we enforce WF conditions also for types in fns. + +trait Object { } + +struct MustBeCopy { + t: T +} + +struct Bar { + // needs T: Copy + x: dyn Object> //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-in-obj-type-trait.stderr b/tests/ui/wf/wf-in-obj-type-trait.stderr new file mode 100644 index 000000000..f556b678e --- /dev/null +++ b/tests/ui/wf/wf-in-obj-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-in-obj-type-trait.rs:11:19 + | +LL | x: dyn Object> + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `MustBeCopy` + --> $DIR/wf-in-obj-type-trait.rs:5:21 + | +LL | struct MustBeCopy { + | ^^^^ required by this bound in `MustBeCopy` +help: consider restricting type parameter `T` + | +LL | struct Bar { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.rs b/tests/ui/wf/wf-inherent-impl-method-where-clause.rs new file mode 100644 index 000000000..eb50fc010 --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.rs @@ -0,0 +1,17 @@ +// Test that we check where-clauses on inherent impl methods. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy { } + +struct Foo(T,U); + +impl Foo { + fn foo(self) where T: ExtraCopy //~ ERROR E0277 + {} +} + + +fn main() { } diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr new file mode 100644 index 000000000..e723d1ba7 --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-inherent-impl-method-where-clause.rs:12:27 + | +LL | fn foo(self) where T: ExtraCopy + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-inherent-impl-method-where-clause.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider restricting type parameter `U` + | +LL | impl Foo { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.rs b/tests/ui/wf/wf-inherent-impl-where-clause.rs new file mode 100644 index 000000000..ac194fb13 --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-where-clause.rs @@ -0,0 +1,16 @@ +// Test that we check where-clauses on inherent impls. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy { } + +struct Foo(T,U); + +impl Foo where T: ExtraCopy //~ ERROR E0277 +{ +} + + +fn main() { } diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-where-clause.stderr new file mode 100644 index 000000000..39e0d348e --- /dev/null +++ b/tests/ui/wf/wf-inherent-impl-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-inherent-impl-where-clause.rs:11:29 + | +LL | impl Foo where T: ExtraCopy + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-inherent-impl-where-clause.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | impl Foo where T: ExtraCopy, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-misc-methods-issue-28609.rs b/tests/ui/wf/wf-misc-methods-issue-28609.rs new file mode 100644 index 000000000..050f866e1 --- /dev/null +++ b/tests/ui/wf/wf-misc-methods-issue-28609.rs @@ -0,0 +1,74 @@ +// check that misc. method calls are well-formed + +use std::marker::PhantomData; +use std::ops::{Deref, Shl}; + +#[derive(Copy, Clone)] +struct S<'a, 'b: 'a> { + marker: PhantomData<&'a &'b ()>, + bomb: Option<&'b u32> +} + +type S2<'a> = S<'a, 'a>; + +impl<'a, 'b> S<'a, 'b> { + fn transmute_inherent(&self, a: &'b u32) -> &'a u32 { + a + } +} + +fn return_dangling_pointer_inherent(s: S2) -> &u32 { + let s = s; + s.transmute_inherent(&mut 42) //~ ERROR cannot return value referencing temporary value +} + +impl<'a, 'b> Deref for S<'a, 'b> { + type Target = &'a u32; + fn deref(&self) -> &&'a u32 { + self.bomb.as_ref().unwrap() + } +} + +fn return_dangling_pointer_coerce(s: S2) -> &u32 { + let four = 4; + let mut s = s; + s.bomb = Some(&four); + &s //~ ERROR cannot return value referencing local variable `four` +} + +fn return_dangling_pointer_unary_op(s: S2) -> &u32 { + let four = 4; + let mut s = s; + s.bomb = Some(&four); + &*s //~ ERROR cannot return value referencing local variable `four` +} + +impl<'a, 'b> Shl<&'b u32> for S<'a, 'b> { + type Output = &'a u32; + fn shl(self, t: &'b u32) -> &'a u32 { t } +} + +fn return_dangling_pointer_binary_op(s: S2) -> &u32 { + let s = s; + s << &mut 3 //~ ERROR cannot return value referencing temporary value +} + +fn return_dangling_pointer_method(s: S2) -> &u32 { + let s = s; + s.shl(&mut 3) //~ ERROR cannot return value referencing temporary value +} + +fn return_dangling_pointer_ufcs(s: S2) -> &u32 { + let s = s; + S2::shl(s, &mut 3) //~ ERROR cannot return value referencing temporary value +} + +fn main() { + let s = S { marker: PhantomData, bomb: None }; + let _inherent_dp = return_dangling_pointer_inherent(s); + let _coerce_dp = return_dangling_pointer_coerce(s); + let _unary_dp = return_dangling_pointer_unary_op(s); + let _binary_dp = return_dangling_pointer_binary_op(s); + let _method_dp = return_dangling_pointer_method(s); + let _ufcs_dp = return_dangling_pointer_ufcs(s); +} diff --git a/tests/ui/wf/wf-misc-methods-issue-28609.stderr b/tests/ui/wf/wf-misc-methods-issue-28609.stderr new file mode 100644 index 000000000..fc5898434 --- /dev/null +++ b/tests/ui/wf/wf-misc-methods-issue-28609.stderr @@ -0,0 +1,55 @@ +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:22:5 + | +LL | s.transmute_inherent(&mut 42) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^--^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing local variable `four` + --> $DIR/wf-misc-methods-issue-28609.rs:36:5 + | +LL | s.bomb = Some(&four); + | ----- `four` is borrowed here +LL | &s + | ^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing local variable `four` + --> $DIR/wf-misc-methods-issue-28609.rs:43:5 + | +LL | s.bomb = Some(&four); + | ----- `four` is borrowed here +LL | &*s + | ^^^ returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:53:5 + | +LL | s << &mut 3 + | ^^^^^^^^^^- + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:58:5 + | +LL | s.shl(&mut 3) + | ^^^^^^^^^^^-^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/wf-misc-methods-issue-28609.rs:63:5 + | +LL | S2::shl(s, &mut 3) + | ^^^^^^^^^^^^^^^^-^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/wf/wf-object-safe.rs b/tests/ui/wf/wf-object-safe.rs new file mode 100644 index 000000000..42e691755 --- /dev/null +++ b/tests/ui/wf/wf-object-safe.rs @@ -0,0 +1,10 @@ +// Check that object-safe traits are not WF when used as object types. +// Issue #21953. + +trait A { + fn foo(&self, _x: &Self); +} + +fn main() { + let _x: &dyn A; //~ ERROR E0038 +} diff --git a/tests/ui/wf/wf-object-safe.stderr b/tests/ui/wf/wf-object-safe.stderr new file mode 100644 index 000000000..64969fbe3 --- /dev/null +++ b/tests/ui/wf/wf-object-safe.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/wf-object-safe.rs:9:13 + | +LL | let _x: &dyn A; + | ^^^^^^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-object-safe.rs:5:23 + | +LL | trait A { + | - this trait cannot be made into an object... +LL | fn foo(&self, _x: &Self); + | ^^^^^ ...because method `foo` references the `Self` type in this parameter + = help: consider moving `foo` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs new file mode 100644 index 000000000..85a332e24 --- /dev/null +++ b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.rs @@ -0,0 +1,22 @@ +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait Trait<'a, T> { + type Out; +} + +impl<'a, T> Trait<'a, T> for usize { + type Out = &'a fn(T); //~ ERROR `T` may not live long enough +} + +struct Foo<'a,T> { + f: &'a fn(T), +} + +trait Baz { } + +impl<'a, T> Trait<'a, T> for u32 { + type Out = &'a dyn Baz; //~ ERROR `T` may not live long enough +} + +fn main() { } diff --git a/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr new file mode 100644 index 000000000..4d4d8b2ab --- /dev/null +++ b/tests/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:16 + | +LL | type Out = &'a fn(T); + | ^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a, T> for usize { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:16 + | +LL | type Out = &'a dyn Baz; + | ^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz + 'a)` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a, T> for u32 { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs new file mode 100644 index 000000000..d0167c8c2 --- /dev/null +++ b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.rs @@ -0,0 +1,31 @@ +// rust-lang/rust#58158: We have special-case code to deal with case +// when a type is both packed and needs drop glue, (we move the fields +// out of their potentially unaligned locations before dropping them, +// which requires they be Sized; see PR #44884). +// +// So, we need to check if a given type needs drop-glue. That requires +// that we actually know that the concrete type, and we guard against +// the type having unknown parts (i.e. type variables) by ICE'ing in +// that scenario. +// +// But in a case where we have a projection (`Type as Trait::Assoc`) +// where `Type` does not actually implement `Trait`, we of course +// cannot have a concrete type, because there is no impl to look up +// the concrete type for the associated type `Assoc`. +// +// So, this test is just making sure that in such a case that we do +// not immediately ICE, and instead allow the underlying type error to +// surface. + +pub struct Matrix(S); +pub struct DefaultAllocator; + +pub trait Allocator { type Buffer; } + +// impl Allocator for DefaultAllocator { type Buffer = (); } + +#[repr(packed)] +struct Foo(Matrix<::Buffer>); +//~^ ERROR the trait bound `DefaultAllocator: Allocator` is not satisfied + +fn main() { } diff --git a/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr new file mode 100644 index 000000000..e460cdcd3 --- /dev/null +++ b/tests/ui/wf/wf-packed-on-proj-of-type-as-unimpl-trait.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `DefaultAllocator: Allocator` is not satisfied + --> $DIR/wf-packed-on-proj-of-type-as-unimpl-trait.rs:28:12 + | +LL | struct Foo(Matrix<::Buffer>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Allocator` is not implemented for `DefaultAllocator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-static-method.rs b/tests/ui/wf/wf-static-method.rs new file mode 100644 index 000000000..7ff195230 --- /dev/null +++ b/tests/ui/wf/wf-static-method.rs @@ -0,0 +1,59 @@ +// check that static methods don't get to assume their trait-ref +// is well-formed. +// FIXME(#27579): this is just a bug. However, our checking with +// static inherent methods isn't quite working - need to +// fix that before removing the check. + +trait Foo<'a, 'b, T>: Sized { + fn make_me() -> Self { loop {} } + fn static_evil(u: &'b u32) -> &'a u32; +} + +struct Evil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { + fn make_me() -> Self { } + fn static_evil(u: &'b u32) -> &'a u32 { + u + //~^ ERROR lifetime may not live long enough + } +} + +struct IndirectEvil<'a, 'b: 'a>(Option<&'a &'b ()>); + +impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { + fn make_me() -> Self { IndirectEvil(None) } + fn static_evil(u: &'b u32) -> &'a u32 { + let me = Self::make_me(); + //~^ ERROR lifetime may not live long enough + loop {} // (`me` could be used for the lifetime transmute). + } +} + +impl<'a, 'b> Evil<'a, 'b> { + fn inherent_evil(u: &'b u32) -> &'a u32 { + u + //~^ ERROR lifetime may not live long enough + } +} + +// while static methods don't get to *assume* this, we still +// *check* that they hold. + +fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + <()>::static_evil(b) + //~^ ERROR lifetime may not live long enough +} + +fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + ::static_evil(b) + //~^ ERROR lifetime may not live long enough +} + +fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + ::inherent_evil(b) + //~^ ERROR lifetime may not live long enough +} + + +fn main() {} diff --git a/tests/ui/wf/wf-static-method.stderr b/tests/ui/wf/wf-static-method.stderr new file mode 100644 index 000000000..161609a5f --- /dev/null +++ b/tests/ui/wf/wf-static-method.stderr @@ -0,0 +1,77 @@ +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:17:9 + | +LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | u + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:27:18 + | +LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let me = Self::make_me(); + | ^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:35:9 + | +LL | impl<'a, 'b> Evil<'a, 'b> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | fn inherent_evil(u: &'b u32) -> &'a u32 { +LL | u + | ^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:44:5 + | +LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | <()>::static_evil(b) + | ^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:49:5 + | +LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ::static_evil(b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/wf-static-method.rs:54:5 + | +LL | fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | ::inherent_evil(b) + | ^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/wf/wf-static-type.rs b/tests/ui/wf/wf-static-type.rs new file mode 100644 index 000000000..1c35e1daf --- /dev/null +++ b/tests/ui/wf/wf-static-type.rs @@ -0,0 +1,14 @@ +// Test that we check the types of statics are well-formed. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy { t: T } +struct NotCopy; + +static FOO: IsCopy> = IsCopy { t: None }; +//~^ ERROR E0277 + + +fn main() { } diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr new file mode 100644 index 000000000..16c6124b6 --- /dev/null +++ b/tests/ui/wf/wf-static-type.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `NotCopy: Copy` is not satisfied + --> $DIR/wf-static-type.rs:10:13 + | +LL | static FOO: IsCopy> = IsCopy { t: None }; + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | + = note: required for `Option` to implement `Copy` +note: required by a bound in `IsCopy` + --> $DIR/wf-static-type.rs:7:17 + | +LL | struct IsCopy { t: T } + | ^^^^ required by this bound in `IsCopy` +help: consider annotating `NotCopy` with `#[derive(Copy)]` + | +LL | #[derive(Copy)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-struct-bound.rs b/tests/ui/wf/wf-struct-bound.rs new file mode 100644 index 000000000..6e558ca8f --- /dev/null +++ b/tests/ui/wf/wf-struct-bound.rs @@ -0,0 +1,16 @@ +// Test that we check struct bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy { } + +struct SomeStruct + where T: ExtraCopy //~ ERROR E0277 +{ + data: (T,U) +} + + +fn main() { } diff --git a/tests/ui/wf/wf-struct-bound.stderr b/tests/ui/wf/wf-struct-bound.stderr new file mode 100644 index 000000000..6248e3e4e --- /dev/null +++ b/tests/ui/wf/wf-struct-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-struct-bound.rs:10:14 + | +LL | where T: ExtraCopy + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-struct-bound.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | where T: ExtraCopy, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-struct-field.rs b/tests/ui/wf/wf-struct-field.rs new file mode 100644 index 000000000..63f8b4382 --- /dev/null +++ b/tests/ui/wf/wf-struct-field.rs @@ -0,0 +1,16 @@ +// Test that we check struct fields for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy { + value: T +} + +struct SomeStruct { + data: IsCopy //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-struct-field.stderr b/tests/ui/wf/wf-struct-field.stderr new file mode 100644 index 000000000..78a8da860 --- /dev/null +++ b/tests/ui/wf/wf-struct-field.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A: Copy` is not satisfied + --> $DIR/wf-struct-field.rs:12:11 + | +LL | data: IsCopy + | ^^^^^^^^^ the trait `Copy` is not implemented for `A` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-struct-field.rs:7:17 + | +LL | struct IsCopy { + | ^^^^ required by this bound in `IsCopy` +help: consider restricting type parameter `A` + | +LL | struct SomeStruct { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-associated-type-bound.rs b/tests/ui/wf/wf-trait-associated-type-bound.rs new file mode 100644 index 000000000..2f20e65e5 --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-bound.rs @@ -0,0 +1,14 @@ +// Test that we check associated type bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy { } + +trait SomeTrait { + type Type1: ExtraCopy; //~ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-associated-type-bound.stderr b/tests/ui/wf/wf-trait-associated-type-bound.stderr new file mode 100644 index 000000000..829770017 --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-trait-associated-type-bound.rs:10:17 + | +LL | type Type1: ExtraCopy; + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-trait-associated-type-bound.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider restricting type parameter `T` + | +LL | trait SomeTrait { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-associated-type-region.rs b/tests/ui/wf/wf-trait-associated-type-region.rs new file mode 100644 index 000000000..0dfc9f098 --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-region.rs @@ -0,0 +1,14 @@ +// Test that we check associated type default values for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait SomeTrait<'a> { + type Type1; + type Type2 = &'a Self::Type1; + //~^ ERROR E0309 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-associated-type-region.stderr b/tests/ui/wf/wf-trait-associated-type-region.stderr new file mode 100644 index 000000000..6e2cc8aba --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-region.stderr @@ -0,0 +1,12 @@ +error[E0309]: the associated type `>::Type1` may not live long enough + --> $DIR/wf-trait-associated-type-region.rs:9:18 + | +LL | type Type2 = &'a Self::Type1; + | ^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `>::Type1: 'a`... + = note: ...so that the reference type `&'a >::Type1` does not outlive the data it points at + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/wf/wf-trait-associated-type-trait.rs b/tests/ui/wf/wf-trait-associated-type-trait.rs new file mode 100644 index 000000000..d67e110ed --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-trait.rs @@ -0,0 +1,16 @@ +// Test that we check associated type default values for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +struct IsCopy { x: T } + +trait SomeTrait { + type Type1; + type Type2 = (IsCopy, bool); + //~^ ERROR E0277 +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-associated-type-trait.stderr b/tests/ui/wf/wf-trait-associated-type-trait.stderr new file mode 100644 index 000000000..a73c3a2ae --- /dev/null +++ b/tests/ui/wf/wf-trait-associated-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `::Type1: Copy` is not satisfied + --> $DIR/wf-trait-associated-type-trait.rs:11:19 + | +LL | type Type2 = (IsCopy, bool); + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `::Type1` + | +note: required by a bound in `IsCopy` + --> $DIR/wf-trait-associated-type-trait.rs:7:17 + | +LL | struct IsCopy { x: T } + | ^^^^ required by this bound in `IsCopy` +help: consider further restricting the associated type + | +LL | trait SomeTrait where ::Type1: Copy { + | ++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-bound.rs b/tests/ui/wf/wf-trait-bound.rs new file mode 100644 index 000000000..62a1eb5b0 --- /dev/null +++ b/tests/ui/wf/wf-trait-bound.rs @@ -0,0 +1,15 @@ +// Test that we check supertrait bounds for WFedness. + +#![feature(associated_type_defaults)] + +#![allow(dead_code)] + +trait ExtraCopy { } + +trait SomeTrait + where T: ExtraCopy //~ ERROR E0277 +{ +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-bound.stderr b/tests/ui/wf/wf-trait-bound.stderr new file mode 100644 index 000000000..bace3e3ef --- /dev/null +++ b/tests/ui/wf/wf-trait-bound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `U: Copy` is not satisfied + --> $DIR/wf-trait-bound.rs:10:14 + | +LL | where T: ExtraCopy + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `U` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-trait-bound.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider further restricting type parameter `U` + | +LL | where T: ExtraCopy, U: std::marker::Copy + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-arg.rs b/tests/ui/wf/wf-trait-default-fn-arg.rs new file mode 100644 index 000000000..64fc35aeb --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-arg.rs @@ -0,0 +1,19 @@ +// Check that we test WF conditions for fn arguments. Because the +// current code is so goofy, this is only a warning for now. + + +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar { value: Box } + +trait Foo { + fn bar(&self, x: &Bar) { + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. + } +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-default-fn-arg.stderr b/tests/ui/wf/wf-trait-default-fn-arg.stderr new file mode 100644 index 000000000..8c3d0568f --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-default-fn-arg.rs:11:23 + | +LL | fn bar(&self, x: &Bar) { + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-default-fn-arg.rs:8:14 + | +LL | struct Bar { value: Box } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar) where Self: Eq { + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-ret.rs b/tests/ui/wf/wf-trait-default-fn-ret.rs new file mode 100644 index 000000000..2103dae8d --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-ret.rs @@ -0,0 +1,19 @@ +// Check that we test WF conditions for fn arguments. Because the +// current code is so goofy, this is only a warning for now. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar { value: Box } + +trait Foo { + fn bar(&self) -> Bar { + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. + loop { } + } +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-default-fn-ret.stderr b/tests/ui/wf/wf-trait-default-fn-ret.stderr new file mode 100644 index 000000000..6422e862d --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-default-fn-ret.rs:11:22 + | +LL | fn bar(&self) -> Bar { + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-default-fn-ret.rs:8:14 + | +LL | struct Bar { value: Box } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) -> Bar where Self: Eq { + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-default-fn-where-clause.rs b/tests/ui/wf/wf-trait-default-fn-where-clause.rs new file mode 100644 index 000000000..ded97214f --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-where-clause.rs @@ -0,0 +1,19 @@ +// Check that we test WF conditions for fn arguments. Because the +// current code is so goofy, this is only a warning for now. + + +#![allow(dead_code)] +#![allow(unused_variables)] + +trait Bar { } + +trait Foo { + fn bar(&self) where A: Bar { + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. + } +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-default-fn-where-clause.stderr b/tests/ui/wf/wf-trait-default-fn-where-clause.stderr new file mode 100644 index 000000000..f260d5750 --- /dev/null +++ b/tests/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-default-fn-where-clause.rs:11:31 + | +LL | fn bar(&self) where A: Bar { + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-default-fn-where-clause.rs:8:13 + | +LL | trait Bar { } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) where A: Bar, Self: Eq { + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-arg.rs b/tests/ui/wf/wf-trait-fn-arg.rs new file mode 100644 index 000000000..044569942 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-arg.rs @@ -0,0 +1,16 @@ +// Check that we test WF conditions for fn arguments in a trait definition. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar { value: Box } + +trait Foo { + fn bar(&self, x: &Bar); + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-fn-arg.stderr b/tests/ui/wf/wf-trait-fn-arg.stderr new file mode 100644 index 000000000..3bd1f4892 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-arg.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-arg.rs:10:23 + | +LL | fn bar(&self, x: &Bar); + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-arg.rs:7:14 + | +LL | struct Bar { value: Box } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar) where Self: Eq; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-ret.rs b/tests/ui/wf/wf-trait-fn-ret.rs new file mode 100644 index 000000000..f49e43087 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-ret.rs @@ -0,0 +1,16 @@ +// Check that we test WF conditions for fn return types in a trait definition. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar { value: Box } + +trait Foo { + fn bar(&self) -> &Bar; + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-fn-ret.stderr b/tests/ui/wf/wf-trait-fn-ret.stderr new file mode 100644 index 000000000..9bd3cc771 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-ret.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-ret.rs:10:23 + | +LL | fn bar(&self) -> &Bar; + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-ret.rs:7:14 + | +LL | struct Bar { value: Box } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) -> &Bar where Self: Eq; + | ++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-where-clause.rs b/tests/ui/wf/wf-trait-fn-where-clause.rs new file mode 100644 index 000000000..1d2427ff9 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-where-clause.rs @@ -0,0 +1,17 @@ +// Check that we test WF conditions for fn where clauses in a trait definition. + + +#![allow(dead_code)] +#![allow(unused_variables)] + +struct Bar { value: Box } + +trait Foo { + fn bar(&self) where Self: Sized, Bar: Copy; + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. +} + + +fn main() { } diff --git a/tests/ui/wf/wf-trait-fn-where-clause.stderr b/tests/ui/wf/wf-trait-fn-where-clause.stderr new file mode 100644 index 000000000..d064f7fc5 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-where-clause.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-where-clause.rs:10:49 + | +LL | fn bar(&self) where Self: Sized, Bar: Copy; + | ^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-where-clause.rs:7:14 + | +LL | struct Bar { value: Box } + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | fn bar(&self) where Self: Sized, Bar: Copy, Self: Eq; + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-superbound.rs b/tests/ui/wf/wf-trait-superbound.rs new file mode 100644 index 000000000..8905a8820 --- /dev/null +++ b/tests/ui/wf/wf-trait-superbound.rs @@ -0,0 +1,12 @@ +// Test that we check supertrait bounds for WFedness. + +#![feature(associated_type_defaults)] +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait ExtraCopy { } + +trait SomeTrait: ExtraCopy { //~ ERROR E0277 +} + +fn main() { } diff --git a/tests/ui/wf/wf-trait-superbound.stderr b/tests/ui/wf/wf-trait-superbound.stderr new file mode 100644 index 000000000..cd49243a4 --- /dev/null +++ b/tests/ui/wf/wf-trait-superbound.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/wf-trait-superbound.rs:9:21 + | +LL | trait SomeTrait: ExtraCopy { + | ^^^^^^^^^^^^ the trait `Copy` is not implemented for `T` + | +note: required by a bound in `ExtraCopy` + --> $DIR/wf-trait-superbound.rs:7:19 + | +LL | trait ExtraCopy { } + | ^^^^ required by this bound in `ExtraCopy` +help: consider restricting type parameter `T` + | +LL | trait SomeTrait: ExtraCopy { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-unsafe-trait-obj-match.rs new file mode 100644 index 000000000..c8731a8ec --- /dev/null +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.rs @@ -0,0 +1,29 @@ +// Check that we do not allow coercions to object +// unsafe trait objects in match arms + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +struct R; + +impl Trait for R {} + +fn opt() -> Option<()> { + Some(()) +} + +fn main() { + match opt() { + Some(()) => &S, + None => &R, //~ ERROR E0308 + } + let t: &dyn Trait = match opt() { //~ ERROR E0038 + Some(()) => &S, //~ ERROR E0038 + None => &R, + }; +} diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr new file mode 100644 index 000000000..96fc1d36b --- /dev/null +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr @@ -0,0 +1,54 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/wf-unsafe-trait-obj-match.rs:23:17 + | +LL | / match opt() { +LL | | Some(()) => &S, + | | -- this is found to be of type `&S` +LL | | None => &R, + | | ^^ expected struct `S`, found struct `R` +LL | | } + | |_____- `match` arms have incompatible types + | + = note: expected reference `&S` + found reference `&R` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 + | +LL | Some(()) => &S, + | ^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 + | +LL | let t: &dyn Trait = match opt() { + | _________________________^ +LL | | Some(()) => &S, +LL | | None => &R, +LL | | }; + | |_____^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + | +LL | trait Trait: Sized {} + | ----- ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + = note: required for `&R` to implement `CoerceUnsized<&dyn Trait>` + = note: required by cast to type `&dyn Trait` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0308. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/where-clauses/auxiliary/where_clauses_xc.rs b/tests/ui/where-clauses/auxiliary/where_clauses_xc.rs new file mode 100644 index 000000000..7c8043b20 --- /dev/null +++ b/tests/ui/where-clauses/auxiliary/where_clauses_xc.rs @@ -0,0 +1,19 @@ +pub trait Equal { + fn equal(&self, other: &Self) -> bool; + fn equals(&self, this: &T, that: &T, x: &U, y: &U) -> bool + where T: Eq, U: Eq; +} + +impl Equal for T where T: Eq { + fn equal(&self, other: &T) -> bool { + self == other + } + fn equals(&self, this: &U, other: &U, x: &X, y: &X) -> bool + where U: Eq, X: Eq { + this == other && x == y + } +} + +pub fn equal(x: &T, y: &T) -> bool where T: Eq { + x == y +} diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr new file mode 100644 index 000000000..30248a7a3 --- /dev/null +++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied + --> $DIR/higher-ranked-fn-type.rs:20:5 + | +LL | called() + | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())` + | +note: required by a bound in `called` + --> $DIR/higher-ranked-fn-type.rs:12:25 + | +LL | fn called() + | ------ required by a bound in this +LL | where +LL | for<'b> fn(&'b ()): Foo, + | ^^^ required by this bound in `called` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.rs b/tests/ui/where-clauses/higher-ranked-fn-type.rs new file mode 100644 index 000000000..c19e75eb7 --- /dev/null +++ b/tests/ui/where-clauses/higher-ranked-fn-type.rs @@ -0,0 +1,25 @@ +// revisions: quiet verbose +// [verbose]compile-flags: -Zverbose + +#![allow(unused_parens)] + +trait Foo { + type Assoc; +} + +fn called() +where + for<'b> fn(&'b ()): Foo, +{ +} + +fn caller() +where + (for<'a> fn(&'a ())): Foo, +{ + called() + //[quiet]~^ ERROR the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied + //[verbose]~^^ ERROR the trait bound `for fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ()): Foo` is not satisfied + --> $DIR/higher-ranked-fn-type.rs:20:5 + | +LL | called() + | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ())` + | +note: required by a bound in `called` + --> $DIR/higher-ranked-fn-type.rs:12:25 + | +LL | fn called() + | ------ required by a bound in this +LL | where +LL | for<'b> fn(&'b ()): Foo, + | ^^^ required by this bound in `called` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/ignore-err-clauses.rs b/tests/ui/where-clauses/ignore-err-clauses.rs new file mode 100644 index 000000000..c76f0e1a8 --- /dev/null +++ b/tests/ui/where-clauses/ignore-err-clauses.rs @@ -0,0 +1,14 @@ +use std::ops::Add; + +fn dbl(x: T) -> ::Output +where + T: Copy + Add, + UUU: Copy, + //~^ ERROR cannot find type `UUU` in this scope +{ + x + x +} + +fn main() { + println!("{}", dbl(3)); +} diff --git a/tests/ui/where-clauses/ignore-err-clauses.stderr b/tests/ui/where-clauses/ignore-err-clauses.stderr new file mode 100644 index 000000000..cfddc3e10 --- /dev/null +++ b/tests/ui/where-clauses/ignore-err-clauses.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `UUU` in this scope + --> $DIR/ignore-err-clauses.rs:6:5 + | +LL | UUU: Copy, + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs new file mode 100644 index 000000000..cf7d06b61 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs @@ -0,0 +1,23 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Bound { + fn dummy(&self) { } +} + +trait Trait { + fn a(&self, _: T) where T: Bound; + fn b(&self, _: T) where T: Bound; + fn c(&self, _: T); + fn d(&self, _: T); +} + +impl Trait for bool { + fn a(&self, _: T) {} + //^~ This gets rejected but should be accepted + fn b(&self, _: T) where T: Bound {} + fn c(&self, _: T) {} + fn d(&self, _: T) where T: Bound {} +} + +fn main() {} diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs new file mode 100644 index 000000000..0e8bb61a7 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.rs @@ -0,0 +1,18 @@ +fn require_copy(x: T) {} + +struct Foo { x: T } + +// Ensure constraints are only attached to methods locally +impl Foo { + fn needs_copy(self) where T: Copy { + require_copy(self.x); + + } + + fn fails_copy(self) { + require_copy(self.x); + //~^ ERROR the trait bound `T: Copy` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr new file mode 100644 index 000000000..43fbc0a90 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22 + | +LL | require_copy(self.x); + | ------------ ^^^^^^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_copy` + --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:20 + | +LL | fn require_copy(x: T) {} + | ^^^^ required by this bound in `require_copy` +help: consider restricting type parameter `T` + | +LL | impl Foo { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs new file mode 100644 index 000000000..25c46330e --- /dev/null +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.rs @@ -0,0 +1,23 @@ +fn require_copy(x: T) {} + +struct Bar { x: T } + +trait Foo { + fn needs_copy(self) where T: Copy; + fn fails_copy(self); +} + +// Ensure constraints are only attached to methods locally +impl Foo for Bar { + fn needs_copy(self) where T: Copy { + require_copy(self.x); + + } + + fn fails_copy(self) { + require_copy(self.x); + //~^ ERROR the trait bound `T: Copy` is not satisfied + } +} + +fn main() {} diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr new file mode 100644 index 000000000..f2db8fcc4 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22 + | +LL | require_copy(self.x); + | ------------ ^^^^^^ the trait `Copy` is not implemented for `T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `require_copy` + --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:20 + | +LL | fn require_copy(x: T) {} + | ^^^^ required by this bound in `require_copy` +help: consider restricting type parameter `T` + | +LL | impl Foo for Bar { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs new file mode 100644 index 000000000..6fc570b9b --- /dev/null +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_upper_case_globals)] + +// pretty-expanded FIXME #23616 + +trait TheTrait { fn dummy(&self) { } } + +impl TheTrait for &'static isize { } + +fn foo<'a,T>(_: &'a T) where &'a T : TheTrait { } + +fn bar(_: &'static T) where &'static T : TheTrait { } + +fn main() { + static x: isize = 1; + foo(&x); + bar(&x); +} diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs new file mode 100644 index 000000000..daa3c8dd8 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +trait Foo { fn dummy(&self, arg: T) { } } + +trait Bar { + fn method(&self) where A: Foo; +} + +struct S; +struct X; + +impl Foo for X {} + +impl Bar for i32 { + fn method(&self) where X: Foo { + } +} + +fn main() { + 1.method::(); +} diff --git a/tests/ui/where-clauses/where-clause-method-substituion.rs b/tests/ui/where-clauses/where-clause-method-substituion.rs new file mode 100644 index 000000000..4607783c0 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-method-substituion.rs @@ -0,0 +1,22 @@ +trait Foo { + fn dummy(&self, t: T) { } +} + +trait Bar { + fn method(&self) where A: Foo; +} + +struct S; +struct X; + +// Remove this impl causing the below resolution to fail // impl Foo for X {} + +impl Bar for isize { + fn method(&self) where X: Foo { + } +} + +fn main() { + 1.method::(); + //~^ ERROR the trait bound `X: Foo` is not satisfied +} diff --git a/tests/ui/where-clauses/where-clause-method-substituion.stderr b/tests/ui/where-clauses/where-clause-method-substituion.stderr new file mode 100644 index 000000000..8c47ed6d4 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-method-substituion.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `X: Foo` is not satisfied + --> $DIR/where-clause-method-substituion.rs:20:16 + | +LL | 1.method::(); + | ^ the trait `Foo` is not implemented for `X` + | +note: required by a bound in `Bar::method` + --> $DIR/where-clause-method-substituion.rs:6:34 + | +LL | fn method(&self) where A: Foo; + | ^^^^^^ required by this bound in `Bar::method` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-region-outlives.rs b/tests/ui/where-clauses/where-clause-region-outlives.rs new file mode 100644 index 000000000..84925345d --- /dev/null +++ b/tests/ui/where-clauses/where-clause-region-outlives.rs @@ -0,0 +1,12 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct A<'a, 'b> where 'a : 'b { x: &'a isize, y: &'b isize } + +fn main() { + let x = 1; + let y = 1; + let a = A { x: &x, y: &y }; +} diff --git a/tests/ui/where-clauses/where-clauses-cross-crate.rs b/tests/ui/where-clauses/where-clauses-cross-crate.rs new file mode 100644 index 000000000..9edf0bd5b --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-cross-crate.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:where_clauses_xc.rs + +extern crate where_clauses_xc; + +use where_clauses_xc::{Equal, equal}; + +fn main() { + println!("{}", equal(&1, &2)); + println!("{}", equal(&1, &1)); + println!("{}", "hello".equal(&"hello")); + println!("{}", "hello".equals::(&1, &1, &"foo", &"bar")); +} diff --git a/tests/ui/where-clauses/where-clauses-lifetimes.rs b/tests/ui/where-clauses/where-clauses-lifetimes.rs new file mode 100644 index 000000000..4bfd9e659 --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-lifetimes.rs @@ -0,0 +1,10 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +fn foo<'a, I>(mut it: I) where I: Iterator {} + +fn main() { + foo([1, 2].iter()); +} diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs b/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs new file mode 100644 index 000000000..a8ae02964 --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs @@ -0,0 +1,20 @@ +// Test that a where clause attached to a method allows us to add +// additional constraints to a parameter out of scope. + +struct Foo { + value: T +} + +struct Bar; // does not implement Eq + +impl Foo { + fn equals(&self, u: &Foo) -> bool where T : Eq { + self.value == u.value + } +} + +fn main() { + let x = Foo { value: Bar }; + x.equals(&x); + //~^ ERROR `Bar: Eq` is not satisfied +} diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr new file mode 100644 index 000000000..e90502977 --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Bar: Eq` is not satisfied + --> $DIR/where-clauses-method-unsatisfied.rs:18:7 + | +LL | x.equals(&x); + | ^^^^^^ the trait `Eq` is not implemented for `Bar` + | +note: required by a bound in `Foo::::equals` + --> $DIR/where-clauses-method-unsatisfied.rs:11:52 + | +LL | fn equals(&self, u: &Foo) -> bool where T : Eq { + | ^^ required by this bound in `Foo::::equals` +help: consider annotating `Bar` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses-method.rs b/tests/ui/where-clauses/where-clauses-method.rs new file mode 100644 index 000000000..feecff435 --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-method.rs @@ -0,0 +1,20 @@ +// run-pass +// Test that a where clause attached to a method allows us to add +// additional constraints to a parameter out of scope. + +struct Foo { + value: T +} + +impl Foo { + fn equals(&self, u: &Foo) -> bool where T : Eq { + self.value == u.value + } +} + +fn main() { + let x = Foo { value: 1 }; + let y = Foo { value: 2 }; + println!("{}", x.equals(&x)); + println!("{}", x.equals(&y)); +} diff --git a/tests/ui/where-clauses/where-clauses-unboxed-closures.rs b/tests/ui/where-clauses/where-clauses-unboxed-closures.rs new file mode 100644 index 000000000..6964cfa2e --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-unboxed-closures.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +struct Bencher; + +// ICE +fn warm_up<'a, F>(f: F) where F: Fn(&'a mut Bencher) { +} + +fn main() { + // ICE trigger + warm_up(|b: &mut Bencher| () ); + + // OK + warm_up(|b| () ); +} diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.rs b/tests/ui/where-clauses/where-clauses-unsatisfied.rs new file mode 100644 index 000000000..8b067d30a --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.rs @@ -0,0 +1,8 @@ +fn equal(a: &T, b: &T) -> bool where T : Eq { a == b } + +struct Struct; + +fn main() { + drop(equal(&Struct, &Struct)) + //~^ ERROR the trait bound `Struct: Eq` is not satisfied +} diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.stderr new file mode 100644 index 000000000..b1805a452 --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Struct: Eq` is not satisfied + --> $DIR/where-clauses-unsatisfied.rs:6:10 + | +LL | drop(equal(&Struct, &Struct)) + | ^^^^^ the trait `Eq` is not implemented for `Struct` + | +note: required by a bound in `equal` + --> $DIR/where-clauses-unsatisfied.rs:1:45 + | +LL | fn equal(a: &T, b: &T) -> bool where T : Eq { a == b } + | ^^ required by this bound in `equal` +help: consider annotating `Struct` with `#[derive(Eq)]` + | +LL | #[derive(Eq)] + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses.rs b/tests/ui/where-clauses/where-clauses.rs new file mode 100644 index 000000000..905ef7c5e --- /dev/null +++ b/tests/ui/where-clauses/where-clauses.rs @@ -0,0 +1,27 @@ +// run-pass +trait Equal { + fn equal(&self, other: &Self) -> bool; + fn equals(&self, this: &T, that: &T, x: &U, y: &U) -> bool + where T: Eq, U: Eq; +} + +impl Equal for T where T: Eq { + fn equal(&self, other: &T) -> bool { + self == other + } + fn equals(&self, this: &U, other: &U, x: &X, y: &X) -> bool + where U: Eq, X: Eq { + this == other && x == y + } +} + +fn equal(x: &T, y: &T) -> bool where T: Eq { + x == y +} + +fn main() { + println!("{}", equal(&1, &2)); + println!("{}", equal(&1, &1)); + println!("{}", "hello".equal(&"hello")); + println!("{}", "hello".equals::(&1, &1, &"foo", &"bar")); +} diff --git a/tests/ui/where-clauses/where-equality-constraints.rs b/tests/ui/where-clauses/where-equality-constraints.rs new file mode 100644 index 000000000..8828f09d9 --- /dev/null +++ b/tests/ui/where-clauses/where-equality-constraints.rs @@ -0,0 +1,6 @@ +fn f() where u8 = u16 {} +//~^ ERROR equality constraints are not yet supported in `where` clauses +fn g() where for<'a> &'static (u8,) == u16, {} +//~^ ERROR equality constraints are not yet supported in `where` clauses + +fn main() {} diff --git a/tests/ui/where-clauses/where-equality-constraints.stderr b/tests/ui/where-clauses/where-equality-constraints.stderr new file mode 100644 index 000000000..9d8fac02e --- /dev/null +++ b/tests/ui/where-clauses/where-equality-constraints.stderr @@ -0,0 +1,18 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/where-equality-constraints.rs:1:14 + | +LL | fn f() where u8 = u16 {} + | ^^^^^^^^ not supported + | + = note: see issue #20041 for more information + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/where-equality-constraints.rs:3:14 + | +LL | fn g() where for<'a> &'static (u8,) == u16, {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information + +error: aborting due to 2 previous errors + diff --git a/tests/ui/where-clauses/where-for-self-2.rs b/tests/ui/where-clauses/where-for-self-2.rs new file mode 100644 index 000000000..37c6954fd --- /dev/null +++ b/tests/ui/where-clauses/where-for-self-2.rs @@ -0,0 +1,24 @@ +// Test that we can quantify lifetimes outside a constraint (i.e., including +// the self type) in a where clause. Specifically, test that implementing for a +// specific lifetime is not enough to satisfy the `for<'a> ...` constraint, which +// should require *all* lifetimes. + +static X: &'static u32 = &42; + +trait Bar { + fn bar(&self); +} + +impl Bar for &'static u32 { + fn bar(&self) {} +} + +fn foo(x: &T) +where + for<'a> &'a T: Bar, +{ +} + +fn main() { + foo(&X); //~ ERROR implementation of `Bar` is not general enough +} diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr new file mode 100644 index 000000000..f65db78fc --- /dev/null +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -0,0 +1,11 @@ +error: implementation of `Bar` is not general enough + --> $DIR/where-for-self-2.rs:23:5 + | +LL | foo(&X); + | ^^^^^^^ implementation of `Bar` is not general enough + | + = note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'static u32` + +error: aborting due to previous error + diff --git a/tests/ui/where-clauses/where-for-self.rs b/tests/ui/where-clauses/where-for-self.rs new file mode 100644 index 000000000..9380e72cd --- /dev/null +++ b/tests/ui/where-clauses/where-for-self.rs @@ -0,0 +1,19 @@ +// Test that we can quantify lifetimes outside a constraint (i.e., including +// the self type) in a where clause. Specifically, test that we cannot nest +// quantification in constraints (to be clear, there is no reason this should not +// we're testing we don't crash or do something stupid). + +trait Bar<'a> { + fn bar(&self); +} + +impl<'a, 'b> Bar<'b> for &'a u32 { + fn bar(&self) {} +} + +fn foo(x: &T) + where for<'a> &'a T: for<'b> Bar<'b> + //~^ error: nested quantification of lifetimes +{} + +fn main() {} diff --git a/tests/ui/where-clauses/where-for-self.stderr b/tests/ui/where-clauses/where-for-self.stderr new file mode 100644 index 000000000..d06afc1e4 --- /dev/null +++ b/tests/ui/where-clauses/where-for-self.stderr @@ -0,0 +1,9 @@ +error[E0316]: nested quantification of lifetimes + --> $DIR/where-for-self.rs:15:26 + | +LL | where for<'a> &'a T: for<'b> Bar<'b> + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0316`. diff --git a/tests/ui/where-clauses/where-lifetime-resolution.rs b/tests/ui/where-clauses/where-lifetime-resolution.rs new file mode 100644 index 000000000..d8677ee95 --- /dev/null +++ b/tests/ui/where-clauses/where-lifetime-resolution.rs @@ -0,0 +1,12 @@ +trait Trait1<'a> {} +trait Trait2<'a, 'b> {} + +fn f() where + for<'a> dyn Trait1<'a>: Trait1<'a>, // OK + (dyn for<'a> Trait1<'a>): Trait1<'a>, + //~^ ERROR use of undeclared lifetime name `'a` + for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + //~^ ERROR use of undeclared lifetime name `'b` +{} + +fn main() {} diff --git a/tests/ui/where-clauses/where-lifetime-resolution.stderr b/tests/ui/where-clauses/where-lifetime-resolution.stderr new file mode 100644 index 000000000..e8df02fba --- /dev/null +++ b/tests/ui/where-clauses/where-lifetime-resolution.stderr @@ -0,0 +1,42 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/where-lifetime-resolution.rs:6:38 + | +LL | (dyn for<'a> Trait1<'a>): Trait1<'a>, + | ^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | (dyn for<'a> Trait1<'a>): for<'a> Trait1<'a>, + | +++++++ +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | for<'a> (dyn for<'a> Trait1<'a>): Trait1<'a>, + | +++++++ +help: consider introducing lifetime `'a` here + | +LL | fn f<'a>() where + | ++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/where-lifetime-resolution.rs:8:52 + | +LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + | ^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | for<'a> dyn for<'b> Trait2<'a, 'b>: for<'b> Trait2<'a, 'b>, + | +++++++ +help: consider making the bound lifetime-generic with a new `'b` lifetime + | +LL | for<'b, 'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, + | +++ +help: consider introducing lifetime `'b` here + | +LL | fn f<'b>() where + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/while-type-error.rs b/tests/ui/while-type-error.rs new file mode 100644 index 000000000..8098bfcd8 --- /dev/null +++ b/tests/ui/while-type-error.rs @@ -0,0 +1,3 @@ +// error-pattern: mismatched types + +fn main() { while main { } } diff --git a/tests/ui/while-type-error.stderr b/tests/ui/while-type-error.stderr new file mode 100644 index 000000000..529cbff05 --- /dev/null +++ b/tests/ui/while-type-error.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/while-type-error.rs:3:19 + | +LL | fn main() { while main { } } + | ^^^^ expected `bool`, found fn item + | + = note: expected type `bool` + found fn item `fn() {main}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/windows-subsystem-invalid.rs b/tests/ui/windows-subsystem-invalid.rs new file mode 100644 index 000000000..0336678b7 --- /dev/null +++ b/tests/ui/windows-subsystem-invalid.rs @@ -0,0 +1,5 @@ +// error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed + +#![windows_subsystem = "wrong"] + +fn main() {} diff --git a/tests/ui/windows-subsystem-invalid.stderr b/tests/ui/windows-subsystem-invalid.stderr new file mode 100644 index 000000000..0cb843cf0 --- /dev/null +++ b/tests/ui/windows-subsystem-invalid.stderr @@ -0,0 +1,4 @@ +error: invalid windows subsystem `wrong`, only `windows` and `console` are allowed + +error: aborting due to previous error + diff --git a/tests/ui/write-fmt-errors.rs b/tests/ui/write-fmt-errors.rs new file mode 100644 index 000000000..3fcaefaa6 --- /dev/null +++ b/tests/ui/write-fmt-errors.rs @@ -0,0 +1,48 @@ +// run-pass + +#![feature(io_error_uncategorized)] + +use std::fmt; +use std::io::{self, Error, Write, sink}; + +struct ErrorDisplay; + +impl fmt::Display for ErrorDisplay { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + Err(fmt::Error) + } +} + +struct ErrorWriter; + +const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Uncategorized; +const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected; + +impl Write for ErrorWriter { + fn write(&mut self, _buf: &[u8]) -> io::Result { + Err(Error::new(WRITER_ERROR, "not connected")) + } + + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +fn main() { + // Test that the error from the formatter is propagated. + let res = write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar"); + assert!(res.is_err(), "formatter error did not propagate"); + assert_eq!(res.unwrap_err().kind(), FORMAT_ERROR); + + // Test that an underlying error is propagated + let res = write!(ErrorWriter, "abc"); + assert!(res.is_err(), "writer error did not propagate"); + + // Writer error + let res = write!(ErrorWriter, "abc {}", ErrorDisplay); + assert!(res.is_err(), "writer error did not propagate"); + assert_eq!(res.unwrap_err().kind(), WRITER_ERROR); + + // Formatter error + let res = write!(ErrorWriter, "{} abc", ErrorDisplay); + assert!(res.is_err(), "formatter error did not propagate"); + assert_eq!(res.unwrap_err().kind(), FORMAT_ERROR); +} diff --git a/tests/ui/writing-to-immutable-vec.rs b/tests/ui/writing-to-immutable-vec.rs new file mode 100644 index 000000000..dbcc3f0bb --- /dev/null +++ b/tests/ui/writing-to-immutable-vec.rs @@ -0,0 +1,4 @@ +fn main() { + let v: Vec = vec![1, 2, 3]; + v[1] = 4; //~ ERROR cannot borrow `v` as mutable, as it is not declared as mutable +} diff --git a/tests/ui/writing-to-immutable-vec.stderr b/tests/ui/writing-to-immutable-vec.stderr new file mode 100644 index 000000000..286267c38 --- /dev/null +++ b/tests/ui/writing-to-immutable-vec.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/writing-to-immutable-vec.rs:3:5 + | +LL | v[1] = 4; + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec = vec![1, 2, 3]; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/wrong-hashset-issue-42918.rs b/tests/ui/wrong-hashset-issue-42918.rs new file mode 100644 index 000000000..ef834d915 --- /dev/null +++ b/tests/ui/wrong-hashset-issue-42918.rs @@ -0,0 +1,31 @@ +// run-pass +// +#![allow(dead_code)] +// compile-flags: -O + +use std::collections::HashSet; + +#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)] +enum MyEnum { + E0, + + E1, + + E2, + E3, + E4, + + E5, + E6, + E7, +} + + +fn main() { + use MyEnum::*; + let s: HashSet<_> = [E4, E1].iter().cloned().collect(); + let mut v: Vec<_> = s.into_iter().collect(); + v.sort(); + + assert_eq!([E1, E4], &v[..]); +} diff --git a/tests/ui/wrong-mul-method-signature.rs b/tests/ui/wrong-mul-method-signature.rs new file mode 100644 index 000000000..1c2f86559 --- /dev/null +++ b/tests/ui/wrong-mul-method-signature.rs @@ -0,0 +1,68 @@ +// This test is to make sure we don't just ICE if the trait +// method for an operator is not implemented properly. +// (In this case the mul method should take &f64 and not f64) +// See: #11450 + +use std::ops::Mul; + +struct Vec1 { + x: f64 +} + +// Expecting value in input signature +impl Mul for Vec1 { + type Output = Vec1; + + fn mul(self, s: &f64) -> Vec1 { + //~^ ERROR method `mul` has an incompatible type for trait + Vec1 { + x: self.x * *s + } + } +} + +struct Vec2 { + x: f64, + y: f64 +} + +// Wrong type parameter ordering +impl Mul for Vec2 { + type Output = f64; + + fn mul(self, s: f64) -> Vec2 { + //~^ ERROR method `mul` has an incompatible type for trait + Vec2 { + x: self.x * s, + y: self.y * s + } + } +} + +struct Vec3 { + x: f64, + y: f64, + z: f64 +} + +// Unexpected return type +impl Mul for Vec3 { + type Output = i32; + + fn mul(self, s: f64) -> f64 { + //~^ ERROR method `mul` has an incompatible type for trait + s + } +} + +pub fn main() { + // Check that the usage goes from the trait declaration: + + let x: Vec1 = Vec1 { x: 1.0 } * 2.0; // this is OK + + let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order + //~^ ERROR mismatched types + //~| ERROR mismatched types + + let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0; +} diff --git a/tests/ui/wrong-mul-method-signature.stderr b/tests/ui/wrong-mul-method-signature.stderr new file mode 100644 index 000000000..504a6032b --- /dev/null +++ b/tests/ui/wrong-mul-method-signature.stderr @@ -0,0 +1,56 @@ +error[E0053]: method `mul` has an incompatible type for trait + --> $DIR/wrong-mul-method-signature.rs:16:21 + | +LL | fn mul(self, s: &f64) -> Vec1 { + | ^^^^ + | | + | expected `f64`, found `&f64` + | help: change the parameter type to match the trait: `f64` + | + = note: expected signature `fn(Vec1, f64) -> Vec1` + found signature `fn(Vec1, &f64) -> Vec1` + +error[E0053]: method `mul` has an incompatible type for trait + --> $DIR/wrong-mul-method-signature.rs:33:21 + | +LL | fn mul(self, s: f64) -> Vec2 { + | ^^^ + | | + | expected struct `Vec2`, found `f64` + | help: change the parameter type to match the trait: `Vec2` + | + = note: expected signature `fn(Vec2, Vec2) -> f64` + found signature `fn(Vec2, f64) -> Vec2` + +error[E0053]: method `mul` has an incompatible type for trait + --> $DIR/wrong-mul-method-signature.rs:52:29 + | +LL | fn mul(self, s: f64) -> f64 { + | ^^^ + | | + | expected `i32`, found `f64` + | help: change the output type to match the trait: `i32` + | + = note: expected signature `fn(Vec3, _) -> i32` + found signature `fn(Vec3, _) -> f64` + +error[E0308]: mismatched types + --> $DIR/wrong-mul-method-signature.rs:63:45 + | +LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order + | ----------------------- ^^^ expected struct `Vec2`, found floating-point number + | | + | expected because this is `Vec2` + +error[E0308]: mismatched types + --> $DIR/wrong-mul-method-signature.rs:63:19 + | +LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found `f64` + | | + | expected due to this + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/wrong-ret-type.rs b/tests/ui/wrong-ret-type.rs new file mode 100644 index 000000000..cbff8dbae --- /dev/null +++ b/tests/ui/wrong-ret-type.rs @@ -0,0 +1,3 @@ +// error-pattern: mismatched types +fn mk_int() -> usize { let i: isize = 3; return i; } +fn main() { } diff --git a/tests/ui/wrong-ret-type.stderr b/tests/ui/wrong-ret-type.stderr new file mode 100644 index 000000000..c686a0b2f --- /dev/null +++ b/tests/ui/wrong-ret-type.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/wrong-ret-type.rs:2:49 + | +LL | fn mk_int() -> usize { let i: isize = 3; return i; } + | ----- ^ expected `usize`, found `isize` + | | + | expected `usize` because of return type + | +help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit + | +LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); } + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/xc-private-method.rs b/tests/ui/xc-private-method.rs new file mode 100644 index 000000000..f05994646 --- /dev/null +++ b/tests/ui/xc-private-method.rs @@ -0,0 +1,11 @@ +// aux-build:xc-private-method-lib.rs + +extern crate xc_private_method_lib; + +fn main() { + let _ = xc_private_method_lib::Struct::static_meth_struct(); + //~^ ERROR: associated function `static_meth_struct` is private + + let _ = xc_private_method_lib::Enum::static_meth_enum(); + //~^ ERROR: associated function `static_meth_enum` is private +} diff --git a/tests/ui/xc-private-method.stderr b/tests/ui/xc-private-method.stderr new file mode 100644 index 000000000..0eabc592a --- /dev/null +++ b/tests/ui/xc-private-method.stderr @@ -0,0 +1,25 @@ +error[E0624]: associated function `static_meth_struct` is private + --> $DIR/xc-private-method.rs:6:44 + | +LL | let _ = xc_private_method_lib::Struct::static_meth_struct(); + | ^^^^^^^^^^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:8:5 + | +LL | fn static_meth_struct() -> Struct { + | --------------------------------- private associated function defined here + +error[E0624]: associated function `static_meth_enum` is private + --> $DIR/xc-private-method.rs:9:42 + | +LL | let _ = xc_private_method_lib::Enum::static_meth_enum(); + | ^^^^^^^^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:23:5 + | +LL | fn static_meth_enum() -> Enum { + | ----------------------------- private associated function defined here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/xc-private-method2.rs b/tests/ui/xc-private-method2.rs new file mode 100644 index 000000000..92946923f --- /dev/null +++ b/tests/ui/xc-private-method2.rs @@ -0,0 +1,11 @@ +// aux-build:xc-private-method-lib.rs + +extern crate xc_private_method_lib; + +fn main() { + let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct(); + //~^ ERROR associated function `meth_struct` is private + + let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum(); + //~^ ERROR associated function `meth_enum` is private +} diff --git a/tests/ui/xc-private-method2.stderr b/tests/ui/xc-private-method2.stderr new file mode 100644 index 000000000..b569882f8 --- /dev/null +++ b/tests/ui/xc-private-method2.stderr @@ -0,0 +1,25 @@ +error[E0624]: associated function `meth_struct` is private + --> $DIR/xc-private-method2.rs:6:52 + | +LL | let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct(); + | ^^^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:12:5 + | +LL | fn meth_struct(&self) -> isize { + | ------------------------------ private associated function defined here + +error[E0624]: associated function `meth_enum` is private + --> $DIR/xc-private-method2.rs:9:55 + | +LL | let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum(); + | ^^^^^^^^^ private associated function + | + ::: $DIR/auxiliary/xc-private-method-lib.rs:27:5 + | +LL | fn meth_enum(&self) -> isize { + | ---------------------------- private associated function defined here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/xcrate/auxiliary/static_priv_by_default.rs b/tests/ui/xcrate/auxiliary/static_priv_by_default.rs new file mode 100644 index 000000000..39f912066 --- /dev/null +++ b/tests/ui/xcrate/auxiliary/static_priv_by_default.rs @@ -0,0 +1,51 @@ +#![crate_type = "lib"] + +static private: isize = 0; +pub static public: isize = 0; + +pub struct A(()); + +impl A { + fn foo() {} +} + +mod foo { + pub static a: isize = 0; + pub fn b() {} + pub struct c; + pub enum d {} + pub type e = isize; + + pub struct A(()); + + impl A { + fn foo() {} + } + + // these are public so the parent can re-export them. + pub static reexported_a: isize = 0; + pub fn reexported_b() {} + pub struct reexported_c; + pub enum reexported_d {} + pub type reexported_e = isize; +} + +pub mod bar { + pub use foo::reexported_a as e; + pub use foo::reexported_b as f; + pub use foo::reexported_c as g; + pub use foo::reexported_d as h; + pub use foo::reexported_e as i; +} + +pub static a: isize = 0; +pub fn b() {} +pub struct c; +pub enum d {} +pub type e = isize; + +static j: isize = 0; +fn k() {} +struct l; +enum m {} +type n = isize; diff --git a/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs b/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs new file mode 100644 index 000000000..69ed498e7 --- /dev/null +++ b/tests/ui/xcrate/auxiliary/xcrate_unit_struct.rs @@ -0,0 +1,28 @@ +#![crate_type = "lib"] + +// used by the rpass test + +#[derive(Copy, Clone)] +pub struct Struct; + +#[derive(Copy, Clone)] +pub enum Unit { + UnitVariant, + Argument(Struct) +} + +#[derive(Copy, Clone)] +pub struct TupleStruct(pub usize, pub &'static str); + +// used by the cfail test + +#[derive(Copy, Clone)] +pub struct StructWithFields { + foo: isize, +} + +#[derive(Copy, Clone)] +pub enum EnumWithVariants { + EnumVariant, + EnumVariantArg(isize) +} diff --git a/tests/ui/xcrate/xcrate-private-by-default.rs b/tests/ui/xcrate/xcrate-private-by-default.rs new file mode 100644 index 000000000..299cff54f --- /dev/null +++ b/tests/ui/xcrate/xcrate-private-by-default.rs @@ -0,0 +1,45 @@ +// aux-build:static_priv_by_default.rs + +extern crate static_priv_by_default; + +fn foo() {} + +fn main() { + // Actual public items should be public + static_priv_by_default::a; + static_priv_by_default::b; + static_priv_by_default::c; + foo::(); + foo::(); + + // publicly re-exported items should be available + static_priv_by_default::bar::e; + static_priv_by_default::bar::f; + static_priv_by_default::bar::g; + foo::(); + foo::(); + + // private items at the top should be inaccessible + static_priv_by_default::j; + //~^ ERROR: static `j` is private + static_priv_by_default::k; + //~^ ERROR: function `k` is private + static_priv_by_default::l; + //~^ ERROR: struct `l` is private + foo::(); + //~^ ERROR: enum `m` is private + foo::(); + //~^ ERROR: type alias `n` is private + + // public items in a private mod should be inaccessible + static_priv_by_default::foo::a; + //~^ ERROR: module `foo` is private + static_priv_by_default::foo::b; + //~^ ERROR: module `foo` is private + static_priv_by_default::foo::c; + //~^ ERROR: module `foo` is private + foo::(); + //~^ ERROR: module `foo` is private + foo::(); + //~^ ERROR: module `foo` is private +} diff --git a/tests/ui/xcrate/xcrate-private-by-default.stderr b/tests/ui/xcrate/xcrate-private-by-default.stderr new file mode 100644 index 000000000..0bdd4002f --- /dev/null +++ b/tests/ui/xcrate/xcrate-private-by-default.stderr @@ -0,0 +1,123 @@ +error[E0603]: static `j` is private + --> $DIR/xcrate-private-by-default.rs:23:29 + | +LL | static_priv_by_default::j; + | ^ private static + | +note: the static `j` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:47:1 + | +LL | static j: isize = 0; + | ^^^^^^^^^^^^^^^ + +error[E0603]: function `k` is private + --> $DIR/xcrate-private-by-default.rs:25:29 + | +LL | static_priv_by_default::k; + | ^ private function + | +note: the function `k` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:48:1 + | +LL | fn k() {} + | ^^^^^^ + +error[E0603]: unit struct `l` is private + --> $DIR/xcrate-private-by-default.rs:27:29 + | +LL | static_priv_by_default::l; + | ^ private unit struct + | +note: the unit struct `l` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:49:1 + | +LL | struct l; + | ^^^^^^^^ + +error[E0603]: enum `m` is private + --> $DIR/xcrate-private-by-default.rs:29:35 + | +LL | foo::(); + | ^ private enum + | +note: the enum `m` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:50:1 + | +LL | enum m {} + | ^^^^^^ + +error[E0603]: type alias `n` is private + --> $DIR/xcrate-private-by-default.rs:31:35 + | +LL | foo::(); + | ^ private type alias + | +note: the type alias `n` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:51:1 + | +LL | type n = isize; + | ^^^^^^ + +error[E0603]: module `foo` is private + --> $DIR/xcrate-private-by-default.rs:35:29 + | +LL | static_priv_by_default::foo::a; + | ^^^ private module + | +note: the module `foo` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:12:1 + | +LL | mod foo { + | ^^^^^^^ + +error[E0603]: module `foo` is private + --> $DIR/xcrate-private-by-default.rs:37:29 + | +LL | static_priv_by_default::foo::b; + | ^^^ private module + | +note: the module `foo` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:12:1 + | +LL | mod foo { + | ^^^^^^^ + +error[E0603]: module `foo` is private + --> $DIR/xcrate-private-by-default.rs:39:29 + | +LL | static_priv_by_default::foo::c; + | ^^^ private module + | +note: the module `foo` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:12:1 + | +LL | mod foo { + | ^^^^^^^ + +error[E0603]: module `foo` is private + --> $DIR/xcrate-private-by-default.rs:41:35 + | +LL | foo::(); + | ^^^ private module + | +note: the module `foo` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:12:1 + | +LL | mod foo { + | ^^^^^^^ + +error[E0603]: module `foo` is private + --> $DIR/xcrate-private-by-default.rs:43:35 + | +LL | foo::(); + | ^^^ private module + | +note: the module `foo` is defined here + --> $DIR/auxiliary/static_priv_by_default.rs:12:1 + | +LL | mod foo { + | ^^^^^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/xcrate/xcrate-unit-struct-2.rs b/tests/ui/xcrate/xcrate-unit-struct-2.rs new file mode 100644 index 000000000..7aa3eb0d6 --- /dev/null +++ b/tests/ui/xcrate/xcrate-unit-struct-2.rs @@ -0,0 +1,30 @@ +// run-pass +// aux-build:xcrate_unit_struct.rs +// pretty-expanded FIXME #23616 +#![allow(non_upper_case_globals)] + +extern crate xcrate_unit_struct; + +const s1: xcrate_unit_struct::Struct = xcrate_unit_struct::Struct; +static s2: xcrate_unit_struct::Unit = xcrate_unit_struct::Unit::UnitVariant; +static s3: xcrate_unit_struct::Unit = + xcrate_unit_struct::Unit::Argument(xcrate_unit_struct::Struct); +static s4: xcrate_unit_struct::Unit = xcrate_unit_struct::Unit::Argument(s1); +static s5: xcrate_unit_struct::TupleStruct = xcrate_unit_struct::TupleStruct(20, "foo"); + +fn f1(_: xcrate_unit_struct::Struct) {} +fn f2(_: xcrate_unit_struct::Unit) {} +fn f3(_: xcrate_unit_struct::TupleStruct) {} + +pub fn main() { + f1(xcrate_unit_struct::Struct); + f2(xcrate_unit_struct::Unit::UnitVariant); + f2(xcrate_unit_struct::Unit::Argument(xcrate_unit_struct::Struct)); + f3(xcrate_unit_struct::TupleStruct(10, "bar")); + + f1(s1); + f2(s2); + f2(s3); + f2(s4); + f3(s5); +} diff --git a/tests/ui/xcrate/xcrate-unit-struct.rs b/tests/ui/xcrate/xcrate-unit-struct.rs new file mode 100644 index 000000000..c99cf77ce --- /dev/null +++ b/tests/ui/xcrate/xcrate-unit-struct.rs @@ -0,0 +1,12 @@ +// aux-build:xcrate_unit_struct.rs + +// Make sure that when we have cross-crate unit structs we don't accidentally +// make values out of cross-crate structs that aren't unit. + +extern crate xcrate_unit_struct; + +fn main() { + let _ = xcrate_unit_struct::StructWithFields; + //~^ ERROR expected value, found struct `xcrate_unit_struct::StructWithFields` + let _ = xcrate_unit_struct::Struct; +} diff --git a/tests/ui/xcrate/xcrate-unit-struct.stderr b/tests/ui/xcrate/xcrate-unit-struct.stderr new file mode 100644 index 000000000..cee314568 --- /dev/null +++ b/tests/ui/xcrate/xcrate-unit-struct.stderr @@ -0,0 +1,14 @@ +error[E0423]: expected value, found struct `xcrate_unit_struct::StructWithFields` + --> $DIR/xcrate-unit-struct.rs:9:13 + | +LL | let _ = xcrate_unit_struct::StructWithFields; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `xcrate_unit_struct::StructWithFields { foo: val }` + | + ::: $DIR/auxiliary/xcrate_unit_struct.rs:20:1 + | +LL | pub struct StructWithFields { + | --------------------------- `xcrate_unit_struct::StructWithFields` defined here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/zero-sized/zero-size-type-destructors.rs b/tests/ui/zero-sized/zero-size-type-destructors.rs new file mode 100644 index 000000000..fb87d8ea0 --- /dev/null +++ b/tests/ui/zero-sized/zero-size-type-destructors.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(non_upper_case_globals)] + +static mut destructions : isize = 3; + +pub fn foo() { + struct Foo; + + impl Drop for Foo { + fn drop(&mut self) { + unsafe { destructions -= 1 }; + } + } + + let _x = [Foo, Foo, Foo]; +} + +pub fn main() { + foo(); + assert_eq!(unsafe { destructions }, 0); +} diff --git a/tests/ui/zero-sized/zero-sized-binary-heap-push.rs b/tests/ui/zero-sized/zero-sized-binary-heap-push.rs new file mode 100644 index 000000000..6553c5adb --- /dev/null +++ b/tests/ui/zero-sized/zero-sized-binary-heap-push.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_variables)] +use std::collections::BinaryHeap; +use std::iter::Iterator; + +fn main() { + const N: usize = 8; + + for len in 0..N { + let mut tester = BinaryHeap::with_capacity(len); + assert_eq!(tester.len(), 0); + assert!(tester.capacity() >= len); + for bit in 0..len { + tester.push(()); + } + assert_eq!(tester.len(), len); + assert_eq!(tester.iter().count(), len); + tester.clear(); + } +} diff --git a/tests/ui/zero-sized/zero-sized-btreemap-insert.rs b/tests/ui/zero-sized/zero-sized-btreemap-insert.rs new file mode 100644 index 000000000..52edb33d6 --- /dev/null +++ b/tests/ui/zero-sized/zero-sized-btreemap-insert.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_variables)] +#![allow(unused_imports)] +use std::cmp::{Ord, Ordering, PartialOrd}; +use std::collections::BTreeMap; +use std::iter::Iterator; + +#[derive(Eq, Hash, Debug, Ord, PartialEq, PartialOrd)] +struct Zst; + +fn main() { + const N: usize = 8; + + for len in 0..N { + let mut tester = BTreeMap::new(); + assert_eq!(tester.len(), 0); + for bit in 0..len { + tester.insert(Zst, ()); + } + assert_eq!(tester.len(), if len == 0 { 0 } else { 1 }); + assert_eq!(tester.iter().count(), if len == 0 { 0 } else { 1 }); + assert_eq!(tester.get(&Zst).is_some(), len > 0); + tester.clear(); + } +} diff --git a/tests/ui/zero-sized/zero-sized-linkedlist-push.rs b/tests/ui/zero-sized/zero-sized-linkedlist-push.rs new file mode 100644 index 000000000..03724085f --- /dev/null +++ b/tests/ui/zero-sized/zero-sized-linkedlist-push.rs @@ -0,0 +1,29 @@ +// run-pass +use std::collections::LinkedList; +use std::iter::Iterator; + +fn main() { + const N: usize = 8; + + // Test that for all possible sequences of push_front / push_back, + // we end up with a LinkedList of the correct size + + for len in 0..N { + let mut tester = LinkedList::new(); + assert_eq!(tester.len(), 0); + assert_eq!(tester.front(), None); + for case in 0..(1 << len) { + assert_eq!(tester.len(), 0); + for bit in 0..len { + if case & (1 << bit) != 0 { + tester.push_front(()); + } else { + tester.push_back(()); + } + } + assert_eq!(tester.len(), len); + assert_eq!(tester.iter().count(), len); + tester.clear(); + } + } +} diff --git a/tests/ui/zero-sized/zero-sized-tuple-struct.rs b/tests/ui/zero-sized/zero-sized-tuple-struct.rs new file mode 100644 index 000000000..2208590f7 --- /dev/null +++ b/tests/ui/zero-sized/zero-sized-tuple-struct.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(unused_braces)] +#![allow(unused_assignments)] + +// Make sure that the constructor args are codegened for zero-sized tuple structs + +struct Foo(()); + +fn main() { + let mut a = 1; + Foo({ a = 2 }); + assert_eq!(a, 2); +} -- cgit v1.2.3

; +} diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs new file mode 100644 index 000000000..3cd68ff6f --- /dev/null +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -0,0 +1,66 @@ +// Regression test for issue #83538. The problem here is that we have +// two cycles: +// +// * `Ty` embeds `Box` indirectly, which depends on `Global: 'static`, which is OkModuloRegions. +// * But `Ty` also references `First`, which has a cycle on itself. That should just be `Ok`. +// +// But our caching mechanism was blending both cycles and giving the incorrect result. + +#![feature(rustc_attrs)] +#![allow(bad_style)] + +struct First { + b: Vec, +} + +pub struct Second { + d: Vec, +} + +struct Third<'a, f> { + g: Vec<(f, &'a f)>, +} + +enum Ty { + j(Fourth, Fifth, Sixth), +} + +struct Fourth { + o: Vec, +} + +struct Fifth { + bounds: First, +} + +struct Sixth { + p: Box, +} + +#[rustc_evaluate_where_clauses] +fn forward<'a>() +where + Vec: Unpin, + Third<'a, Ty>: Unpin, +{ +} + +#[rustc_evaluate_where_clauses] +fn reverse<'a>() +where + Third<'a, Ty>: Unpin, + Vec: Unpin, +{ +} + +fn main() { + // Key is that Vec is "ok" and Third<'_, Ty> is "ok modulo regions": + + forward(); + //~^ ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + + reverse(); + //~^ ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) +} diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr new file mode 100644 index 000000000..7c4041144 --- /dev/null +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -0,0 +1,38 @@ +error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 + | +LL | Vec: Unpin, + | ----- predicate +... +LL | forward(); + | ^^^^^^^ + +error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 + | +LL | Third<'a, Ty>: Unpin, + | ----- predicate +... +LL | forward(); + | ^^^^^^^ + +error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 + | +LL | Third<'a, Ty>: Unpin, + | ----- predicate +... +LL | reverse(); + | ^^^^^^^ + +error: evaluate(Binder(TraitPredicate( as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 + | +LL | Vec: Unpin, + | ----- predicate +... +LL | reverse(); + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/issue-84399-bad-fresh-caching.rs b/tests/ui/traits/issue-84399-bad-fresh-caching.rs new file mode 100644 index 000000000..149400156 --- /dev/null +++ b/tests/ui/traits/issue-84399-bad-fresh-caching.rs @@ -0,0 +1,55 @@ +// compile-flags: --crate-type lib +// check-pass +// +// Regression test for issue #84399 +// Tests that we keep the full `ParamEnv` when +// caching predicates with freshened types in the global cache + +use std::marker::PhantomData; +pub trait Allocator { + type Buffer; +} +pub struct DefaultAllocator; +impl Allocator for DefaultAllocator { + type Buffer = (); +} +pub type Owned = >::Buffer; +pub type MatrixMN = Matrix>; +pub type Matrix4 = Matrix; +pub struct Matrix { + pub data: S, + _phantoms: PhantomData, +} +pub fn set_object_transform(matrix: &Matrix4<()>) { + matrix.js_buffer_view(); +} +pub trait Storable { + type Cell; + fn slice_to_items(_buffer: &()) -> &[Self::Cell] { + unimplemented!() + } +} +pub type Cell = ::Cell; +impl Storable for MatrixMN +where + DefaultAllocator: Allocator, +{ + type Cell = (); +} +pub trait JsBufferView { + fn js_buffer_view(&self) -> usize { + unimplemented!() + } +} +impl JsBufferView for [MatrixMN] +where + DefaultAllocator: Allocator, + MatrixMN: Storable, + [Cell>]: JsBufferView, +{ + fn js_buffer_view(&self) -> usize { + as Storable>::slice_to_items(&()).js_buffer_view() + } +} +impl JsBufferView for [()] {} +impl JsBufferView for MatrixMN where DefaultAllocator: Allocator {} diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs new file mode 100644 index 000000000..19131684a --- /dev/null +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -0,0 +1,143 @@ +// compile-flags: --edition=2021 + +#![feature(rustc_attrs)] + +use core::any::Any; +use core::marker::PhantomData; + +fn main() { + test::>>(make()); + //~^ ERROR evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + + test::>>(make()); + //~^ ERROR evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + //~| ERROR evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) +} + +#[rustc_evaluate_where_clauses] +fn test(_: T) {} + +fn make() -> T { + todo!() +} + +struct DerefWrap(T); + +impl core::ops::Deref for DerefWrap { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +struct Storage { + phantom: PhantomData<(T, D)>, +} + +type ReadStorage = Storage>>; + +pub trait Component { + type Storage; +} + +struct VecStorage; + +struct Pos; + +impl Component for Pos { + type Storage = VecStorage; +} + +struct GenericComp { + _t: T, +} + +impl Component for GenericComp { + type Storage = VecStorage; +} + +struct GenericComp2 { + _t: T, +} + +impl Component for GenericComp2 where for<'a> &'a bool: 'a { + type Storage = VecStorage; +} + +struct ReadData { + pos_interpdata: ReadStorage>, +} + +trait System { + type SystemData; + + fn run(data: Self::SystemData, any: Box); +} + +struct Sys; + +impl System for Sys { + type SystemData = (ReadData, ReadStorage); + + fn run((data, pos): Self::SystemData, any: Box) { + > as SystemData>::setup(any); + + ParJoin::par_join((&pos, &data.pos_interpdata)); + } +} + +trait ParJoin { + fn par_join(self) + where + Self: Sized, + { + } +} + +impl<'a, T, D> ParJoin for &'a Storage +where + T: Component, + D: core::ops::Deref>, + T::Storage: Sync, +{ +} + +impl ParJoin for (A, B) +where + A: ParJoin, + B: ParJoin, +{ +} + +pub trait SystemData { + fn setup(any: Box); +} + +impl SystemData for ReadStorage +where + T: Component, +{ + fn setup(any: Box) { + let storage: &MaskedStorage = any.downcast_ref().unwrap(); + + >>::cast(&storage); + } +} + +pub struct MaskedStorage { + _inner: T::Storage, +} + +pub unsafe trait CastFrom { + fn cast(t: &T) -> &Self; +} + +unsafe impl CastFrom for dyn Any +where + T: Any + 'static, +{ + fn cast(t: &T) -> &Self { + t + } +} diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr new file mode 100644 index 000000000..ebf977dd6 --- /dev/null +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -0,0 +1,38 @@ +error: evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 + | +LL | test::>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test(_: T) {} + | - predicate + +error: evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOk) + --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 + | +LL | test::>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test(_: T) {} + | ----- predicate + +error: evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 + | +LL | test::>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test(_: T) {} + | - predicate + +error: evaluate(Binder(TraitPredicate(> as std::marker::Sized>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions) + --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 + | +LL | test::>>(make()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn test(_: T) {} + | ----- predicate + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/issue-85735.rs b/tests/ui/traits/issue-85735.rs new file mode 100644 index 000000000..fb387a9c9 --- /dev/null +++ b/tests/ui/traits/issue-85735.rs @@ -0,0 +1,13 @@ +// Regression test for the invalid suggestion in #85735 (the +// underlying issue #21974 still exists here). + +trait Foo {} +impl<'a, 'b, T> Foo for T +where + T: FnMut(&'a ()), + //~^ ERROR: type annotations needed + T: FnMut(&'b ()), +{ +} + +fn main() {} diff --git a/tests/ui/traits/issue-85735.stderr b/tests/ui/traits/issue-85735.stderr new file mode 100644 index 000000000..9e80497ca --- /dev/null +++ b/tests/ui/traits/issue-85735.stderr @@ -0,0 +1,18 @@ +error[E0283]: type annotations needed: cannot satisfy `T: FnMut<(&'a (),)>` + --> $DIR/issue-85735.rs:7:8 + | +LL | T: FnMut(&'a ()), + | ^^^^^^^^^^^^^ + | +note: multiple `impl`s or `where` clauses satisfying `T: FnMut<(&'a (),)>` found + --> $DIR/issue-85735.rs:7:8 + | +LL | T: FnMut(&'a ()), + | ^^^^^^^^^^^^^ +LL | +LL | T: FnMut(&'b ()), + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/issue-87558.rs b/tests/ui/traits/issue-87558.rs new file mode 100644 index 000000000..c5d86bd63 --- /dev/null +++ b/tests/ui/traits/issue-87558.rs @@ -0,0 +1,9 @@ +struct ErrorKind; +struct Error(ErrorKind); +impl Fn(&isize) for Error { + //~^ ERROR manual implementations of `Fn` are experimental + //~| ERROR associated type bindings are not allowed here + fn from() {} //~ ERROR method `from` is not a member of trait `Fn` +} + +fn main() {} diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr new file mode 100644 index 000000000..494274d8c --- /dev/null +++ b/tests/ui/traits/issue-87558.stderr @@ -0,0 +1,24 @@ +error[E0407]: method `from` is not a member of trait `Fn` + --> $DIR/issue-87558.rs:6:5 + | +LL | fn from() {} + | ^^^^^^^^^^^^ not a member of trait `Fn` + +error[E0183]: manual implementations of `Fn` are experimental + --> $DIR/issue-87558.rs:3:6 + | +LL | impl Fn(&isize) for Error { + | ^^^^^^^^^^ manual implementations of `Fn` are experimental + | + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-87558.rs:3:6 + | +LL | impl Fn(&isize) for Error { + | ^^^^^^^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0183, E0229, E0407. +For more information about an error, try `rustc --explain E0183`. diff --git a/tests/ui/traits/issue-89119.rs b/tests/ui/traits/issue-89119.rs new file mode 100644 index 000000000..170f69915 --- /dev/null +++ b/tests/ui/traits/issue-89119.rs @@ -0,0 +1,11 @@ +// This is a regression test for issue #89119: an issue in intercrate mode caching. +// +// It requires multiple crates, of course, but the bug is triggered by the code in the dependency, +// not the main crate. This is why this file is empty. +// +// The auxiliary crate used in the test contains the code minimized from `zvariant-2.8.0`. + +// check-pass +// aux-build: issue_89119_intercrate_caching.rs + +fn main() {} diff --git a/tests/ui/traits/issue-90195-2.rs b/tests/ui/traits/issue-90195-2.rs new file mode 100644 index 000000000..b739dc46e --- /dev/null +++ b/tests/ui/traits/issue-90195-2.rs @@ -0,0 +1,20 @@ +// check-pass +pub trait Archive { + type Archived; +} + +impl Archive for Option { + type Archived = (); +} +pub type Archived = ::Archived; + +pub trait Deserialize {} + +const ARRAY_SIZE: usize = 32; +impl<__D> Deserialize<__D> for () +where + Option<[u8; ARRAY_SIZE]>: Archive, + Archived>: Deserialize<__D>, +{ +} +fn main() {} diff --git a/tests/ui/traits/issue-90195.rs b/tests/ui/traits/issue-90195.rs new file mode 100644 index 000000000..543c9f197 --- /dev/null +++ b/tests/ui/traits/issue-90195.rs @@ -0,0 +1,21 @@ +// check-pass +pub trait Archive { + type Archived; +} + +impl Archive for Option { + type Archived = (); +} +pub type Archived = ::Archived; + +pub trait Deserialize {} + +const ARRAY_SIZE: usize = 32; +impl<__D> Deserialize<__D> for () +where + Option<[u8; ARRAY_SIZE]>: Archive, + Option<[u8; ARRAY_SIZE]>: Archive, + Archived>: Deserialize<__D>, +{ +} +fn main() {} diff --git a/tests/ui/traits/issue-90662-projection-caching.rs b/tests/ui/traits/issue-90662-projection-caching.rs new file mode 100644 index 000000000..879f30071 --- /dev/null +++ b/tests/ui/traits/issue-90662-projection-caching.rs @@ -0,0 +1,34 @@ +// check-pass + +// Regression test for issue #90662 +// Tests that projection caching does not cause a spurious error + +trait HasProvider {} +trait Provider { + type Interface: ?Sized; +} + +trait Repository {} +trait Service {} + +struct DbConnection; +impl Provider for DbConnection { + type Interface = DbConnection; +} + +struct RepositoryImpl; +impl> Provider for RepositoryImpl { + type Interface = dyn Repository; +} + +struct ServiceImpl; +impl> Provider for ServiceImpl { + type Interface = dyn Service; +} + +struct TestModule; +impl HasProvider<>::Interface> for TestModule {} +impl HasProvider<>::Interface> for TestModule {} +impl HasProvider<>::Interface> for TestModule {} + +fn main() {} diff --git a/tests/ui/traits/issue-91594.rs b/tests/ui/traits/issue-91594.rs new file mode 100644 index 000000000..930f7f0c6 --- /dev/null +++ b/tests/ui/traits/issue-91594.rs @@ -0,0 +1,17 @@ +// #91594: This used to ICE. + +trait Component { + type Interface; +} +trait HasComponent {} + +struct Foo; + +impl HasComponent<>::Interface> for Foo {} +//~^ ERROR the trait bound `Foo: HasComponent<()>` is not satisfied + +impl> Component for Foo { + type Interface = u8; +} + +fn main() {} diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr new file mode 100644 index 000000000..85d903fad --- /dev/null +++ b/tests/ui/traits/issue-91594.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied + --> $DIR/issue-91594.rs:10:19 + | +LL | impl HasComponent<>::Interface> for Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | + = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` +note: required for `Foo` to implement `Component` + --> $DIR/issue-91594.rs:13:27 + | +LL | impl> Component for Foo { + | ---------------- ^^^^^^^^^^^^ ^^^ + | | + | unsatisfied trait bound introduced here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.rs b/tests/ui/traits/issue-91949-hangs-on-recursion.rs new file mode 100644 index 000000000..6474b2b38 --- /dev/null +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.rs @@ -0,0 +1,32 @@ +// build-fail +// compile-flags: -Zinline-mir=no +// error-pattern: overflow evaluating the requirement `(): Sized` +// error-pattern: function cannot return without recursing +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +// Regression test for #91949. +// This hanged *forever* on 1.56, fixed by #90423. + +#![recursion_limit = "256"] + +struct Wrapped(T); + +struct IteratorOfWrapped>(I); + +impl> Iterator for IteratorOfWrapped { + type Item = Wrapped; + fn next(&mut self) -> Option> { + self.0.next().map(Wrapped) + } +} + +fn recurse(elements: T) -> Vec +where + T: Iterator, +{ + recurse(IteratorOfWrapped(elements).map(|t| t.0)) +} + +fn main() { + recurse(std::iter::empty()); +} diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr new file mode 100644 index 000000000..1f18c5daf --- /dev/null +++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -0,0 +1,25 @@ +warning: function cannot return without recursing + --> $DIR/issue-91949-hangs-on-recursion.rs:23:1 + | +LL | / fn recurse(elements: T) -> Vec +LL | | where +LL | | T: Iterator, + | |___________________________^ cannot return without recursing +LL | { +LL | recurse(IteratorOfWrapped(elements).map(|t| t.0)) + | ------------------------------------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0275]: overflow evaluating the requirement `(): Sized` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) + = note: required for `std::iter::Empty<()>` to implement `Iterator` + = note: 171 redundant requirements hidden + = note: required for `IteratorOfWrapped<(), Map>, ...>>, ...>>` to implement `Iterator` + = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt' + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/issue-92292.rs b/tests/ui/traits/issue-92292.rs new file mode 100644 index 000000000..bb3700a2b --- /dev/null +++ b/tests/ui/traits/issue-92292.rs @@ -0,0 +1,32 @@ +// check-pass + +use std::marker::PhantomData; + +pub struct MyGenericType { + _marker: PhantomData<*const T>, +} + +pub struct MyNonGenericType; + +impl From> for MyNonGenericType { + fn from(_: MyGenericType) -> Self { + todo!() + } +} + +pub trait MyTrait { + const MY_CONSTANT: i32; +} + +impl MyTrait for MyGenericType +where + Self: Into, +{ + const MY_CONSTANT: i32 = 1; +} + +impl MyGenericType { + const MY_OTHER_CONSTANT: i32 = as MyTrait>::MY_CONSTANT; +} + +fn main() {} diff --git a/tests/ui/traits/issue-9394-inherited-calls.rs b/tests/ui/traits/issue-9394-inherited-calls.rs new file mode 100644 index 000000000..cc0dd4fc1 --- /dev/null +++ b/tests/ui/traits/issue-9394-inherited-calls.rs @@ -0,0 +1,62 @@ +// run-pass + +trait Base: Base2 + Base3{ + fn foo(&self) -> String; + fn foo1(&self) -> String; + fn foo2(&self) -> String{ + "base foo2".to_string() + } +} + +trait Base2: Base3{ + fn baz(&self) -> String; +} + +trait Base3{ + fn root(&self) -> String; +} + +trait Super: Base{ + fn bar(&self) -> String; +} + +struct X; + +impl Base for X { + fn foo(&self) -> String{ + "base foo".to_string() + } + fn foo1(&self) -> String{ + "base foo1".to_string() + } + +} + +impl Base2 for X { + fn baz(&self) -> String{ + "base2 baz".to_string() + } +} + +impl Base3 for X { + fn root(&self) -> String{ + "base3 root".to_string() + } +} + +impl Super for X { + fn bar(&self) -> String{ + "super bar".to_string() + } +} + +pub fn main() { + let n = X; + let s = &n as &dyn Super; + assert_eq!(s.bar(),"super bar".to_string()); + assert_eq!(s.foo(),"base foo".to_string()); + assert_eq!(s.foo1(),"base foo1".to_string()); + assert_eq!(s.foo2(),"base foo2".to_string()); + assert_eq!(s.baz(),"base2 baz".to_string()); + assert_eq!(s.root(),"base3 root".to_string()); +} diff --git a/tests/ui/traits/issue-95311.rs b/tests/ui/traits/issue-95311.rs new file mode 100644 index 000000000..9d40d254a --- /dev/null +++ b/tests/ui/traits/issue-95311.rs @@ -0,0 +1,19 @@ +// check-pass + +// Test to check that pointee trait doesn't let region variables escape into the cache + +#![feature(ptr_metadata)] + +trait Bar: Sized + 'static {} + +struct Foo { + marker: std::marker::PhantomData, +} + +impl Foo { + fn foo(value: &T) { + std::ptr::metadata(value); + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-95898.rs b/tests/ui/traits/issue-95898.rs new file mode 100644 index 000000000..41a20b899 --- /dev/null +++ b/tests/ui/traits/issue-95898.rs @@ -0,0 +1,9 @@ +// Test for #95898: The trait suggestion had an extra `:` after the trait. +// edition:2021 + +fn foo(t: T) { + t.clone(); + //~^ ERROR no method named `clone` found for type parameter `T` in the current scope +} + +fn main() {} diff --git a/tests/ui/traits/issue-95898.stderr b/tests/ui/traits/issue-95898.stderr new file mode 100644 index 000000000..ca7bacdbf --- /dev/null +++ b/tests/ui/traits/issue-95898.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `clone` found for type parameter `T` in the current scope + --> $DIR/issue-95898.rs:5:7 + | +LL | fn foo(t: T) { + | - method `clone` not found for this type parameter +LL | t.clone(); + | ^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `clone`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn foo(t: T) { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/issue-96664.rs b/tests/ui/traits/issue-96664.rs new file mode 100644 index 000000000..3c5314af7 --- /dev/null +++ b/tests/ui/traits/issue-96664.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(trait_alias)] + +pub trait State = Clone + Send + Sync + PartialOrd + PartialEq + std::fmt::Display; +pub trait RandState = FnMut() -> S + Send; + +pub trait Evaluator { + type State; +} + +pub struct Evolver { + rand_state: Box>, +} + +fn main() {} diff --git a/tests/ui/traits/issue-96665.rs b/tests/ui/traits/issue-96665.rs new file mode 100644 index 000000000..a571d48d9 --- /dev/null +++ b/tests/ui/traits/issue-96665.rs @@ -0,0 +1,16 @@ +// check-pass + +pub trait Sequence> {} + +pub trait NodeWalk>: + Sequence +{ +} + +pub trait GraphBase { + type NodeIndex; +} + +pub trait WalkableGraph: GraphBase {} + +fn main() {} diff --git a/tests/ui/traits/issue-97576.rs b/tests/ui/traits/issue-97576.rs new file mode 100644 index 000000000..fdc85e9fa --- /dev/null +++ b/tests/ui/traits/issue-97576.rs @@ -0,0 +1,13 @@ +struct Foo { + bar: String, +} + +impl Foo { + pub fn new(bar: impl ToString) -> Self { + Self { + bar: bar.into(), //~ ERROR the trait bound `String: From` is not satisfied + } + } +} + +fn main() {} diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr new file mode 100644 index 000000000..9062a0fab --- /dev/null +++ b/tests/ui/traits/issue-97576.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `String: From` is not satisfied + --> $DIR/issue-97576.rs:8:22 + | +LL | bar: bar.into(), + | ^^^^ the trait `From` is not implemented for `String` + | + = note: required for `impl ToString` to implement `Into` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-97695-double-trivial-bound.rs b/tests/ui/traits/issue-97695-double-trivial-bound.rs new file mode 100644 index 000000000..213605b51 --- /dev/null +++ b/tests/ui/traits/issue-97695-double-trivial-bound.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zinline-mir --emit=mir +// build-pass + +pub trait Associate { + type Associated; +} + +pub struct Wrap<'a> { + pub field: &'a i32, +} + +pub trait Create { + fn create() -> Self; +} + +pub fn oh_no<'a, T>() +where + Wrap<'a>: Associate, + as Associate>::Associated: Create, +{ + as Associate>::Associated::create(); +} + +pub fn main() {} diff --git a/tests/ui/traits/issue-99875.rs b/tests/ui/traits/issue-99875.rs new file mode 100644 index 000000000..cf73fd8d3 --- /dev/null +++ b/tests/ui/traits/issue-99875.rs @@ -0,0 +1,16 @@ +struct Argument; +struct Return; + +fn function(_: Argument) -> Return { todo!() } + +trait Trait {} +impl Trait for fn(Argument) -> Return {} + +fn takes(_: impl Trait) {} + +fn main() { + takes(function); + //~^ ERROR the trait bound + takes(|_: Argument| -> Return { todo!() }); + //~^ ERROR the trait bound +} diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr new file mode 100644 index 000000000..fb6eebbd2 --- /dev/null +++ b/tests/ui/traits/issue-99875.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied + --> $DIR/issue-99875.rs:12:11 + | +LL | takes(function); + | ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes` + --> $DIR/issue-99875.rs:9:18 + | +LL | fn takes(_: impl Trait) {} + | ^^^^^ required by this bound in `takes` +help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as` + | +LL | takes(function as fn(Argument) -> Return); + | +++++++++++++++++++++++++ + +error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied + --> $DIR/issue-99875.rs:14:11 + | +LL | takes(|_: Argument| -> Return { todo!() }); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` +note: required by a bound in `takes` + --> $DIR/issue-99875.rs:9:18 + | +LL | fn takes(_: impl Trait) {} + | ^^^^^ required by this bound in `takes` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/item-inside-macro.rs b/tests/ui/traits/item-inside-macro.rs new file mode 100644 index 000000000..54bf872d0 --- /dev/null +++ b/tests/ui/traits/item-inside-macro.rs @@ -0,0 +1,30 @@ +// run-pass +// Issue #34183 + +macro_rules! foo { + () => { + fn foo() { } + } +} + +macro_rules! bar { + () => { + fn bar(); + } +} + +trait Bleh { + foo!(); + bar!(); +} + +struct Test; + +impl Bleh for Test { + fn bar() {} +} + +fn main() { + Test::bar(); + Test::foo(); +} diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs new file mode 100644 index 000000000..38d06b967 --- /dev/null +++ b/tests/ui/traits/item-privacy.rs @@ -0,0 +1,134 @@ +#![feature(associated_type_defaults)] + +struct S; + +mod method { + trait A { + fn a(&self) { } + } + + pub trait B { + fn b(&self) { } + } + + pub trait C: A + B { + fn c(&self) { } + } + + impl A for ::S {} + impl B for ::S {} + impl C for ::S {} +} + +mod assoc_const { + trait A { + const A: u8 = 0; + } + + pub trait B { + const B: u8 = 0; + } + + pub trait C: A + B { + const C: u8 = 0; + } + + impl A for ::S {} + impl B for ::S {} + impl C for ::S {} +} + +mod assoc_ty { + trait A { + type A = u8; + } + + pub trait B { + type B = u8; + } + + pub trait C: A + B { + type C = u8; + } + + impl A for ::S {} + impl B for ::S {} + impl C for ::S {} +} + +fn check_method() { + // A is private + // B is pub, not in scope + // C : A + B is pub, in scope + use method::C; + + // Methods, method call + // a, b, c are resolved as trait items, their traits need to be in scope + S.a(); //~ ERROR no method named `a` found + S.b(); //~ ERROR no method named `b` found + S.c(); // OK + // a, b, c are resolved as inherent items, their traits don't need to be in scope + let c = &S as &dyn C; + c.a(); //~ ERROR associated function `a` is private + c.b(); // OK + c.c(); // OK + + // Methods, UFCS + // a, b, c are resolved as trait items, their traits need to be in scope + S::a(&S); + //~^ ERROR no function or associated item named `a` found + S::b(&S); + //~^ ERROR no function or associated item named `b` found + S::c(&S); // OK + // a, b, c are resolved as inherent items, their traits don't need to be in scope + ::a(&S); //~ ERROR associated function `a` is private + ::b(&S); // OK + C::c(&S); // OK +} + +fn check_assoc_const() { + // A is private + // B is pub, not in scope + // C : A + B is pub, in scope + use assoc_const::C; + + // Associated constants + // A, B, C are resolved as trait items, their traits need to be in scope + S::A; //~ ERROR no associated item named `A` found + S::B; //~ ERROR no associated item named `B` found + S::C; // OK + // A, B, C are resolved as inherent items, their traits don't need to be in scope + ::A; //~ ERROR associated constant `A` is private + //~^ ERROR the trait `assoc_const::C` cannot be made into an object + ::B; // ERROR the trait `assoc_const::C` cannot be made into an object + C::C; // OK +} + +fn check_assoc_ty() { + // A is private + // B is pub, not in scope + // C : A + B is pub, in scope + use assoc_ty::C; + + // Associated types + // A, B, C are resolved as trait items, their traits need to be in scope, not implemented yet + let _: S::A; //~ ERROR ambiguous associated type + let _: S::B; //~ ERROR ambiguous associated type + let _: S::C; //~ ERROR ambiguous associated type + // A, B, C are resolved as inherent items, their traits don't need to be in scope + let _: T::A; //~ ERROR associated type `A` is private + let _: T::B; // OK + let _: T::C; // OK + + // Associated types, bindings + let _: dyn assoc_ty::B< + B = u8, // OK + >; + let _: dyn C< + A = u8, //~ ERROR associated type `A` is private + B = u8, // OK + C = u8, // OK + >; +} + +fn main() {} diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr new file mode 100644 index 000000000..293cfbda8 --- /dev/null +++ b/tests/ui/traits/item-privacy.stderr @@ -0,0 +1,188 @@ +error[E0599]: no method named `a` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:67:7 + | +LL | struct S; + | -------- method `a` not found for this struct +... +LL | S.a(); + | ^ method not found in `S` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ + +error[E0599]: no method named `b` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:68:7 + | +LL | struct S; + | -------- method `b` not found for this struct +... +LL | fn b(&self) { } + | - the method is available for `S` here +... +LL | S.b(); + | ^ method not found in `S` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use method::B; + | + +error[E0624]: associated function `a` is private + --> $DIR/item-privacy.rs:72:7 + | +LL | fn a(&self) { } + | ----------- private associated function defined here +... +LL | c.a(); + | ^ private associated function + +error[E0599]: no function or associated item named `a` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:78:8 + | +LL | struct S; + | -------- function or associated item `a` not found for this struct +... +LL | S::a(&S); + | ^ function or associated item not found in `S` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ + +error[E0599]: no function or associated item named `b` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:80:8 + | +LL | struct S; + | -------- function or associated item `b` not found for this struct +... +LL | S::b(&S); + | ^ function or associated item not found in `S` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use method::B; + | + +error[E0624]: associated function `a` is private + --> $DIR/item-privacy.rs:84:14 + | +LL | fn a(&self) { } + | ----------- private associated function defined here +... +LL | ::a(&S); + | ^ private associated function + +error[E0599]: no associated item named `A` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:97:8 + | +LL | struct S; + | -------- associated item `A` not found for this struct +... +LL | S::A; + | ^ associated item not found in `S` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `assoc_const::A` defines an item `A`, perhaps you need to implement it + --> $DIR/item-privacy.rs:24:5 + | +LL | trait A { + | ^^^^^^^ + +error[E0599]: no associated item named `B` found for struct `S` in the current scope + --> $DIR/item-privacy.rs:98:8 + | +LL | struct S; + | -------- associated item `B` not found for this struct +... +LL | S::B; + | ^ associated item not found in `S` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use assoc_const::B; + | + +error[E0624]: associated constant `A` is private + --> $DIR/item-privacy.rs:101:14 + | +LL | const A: u8 = 0; + | ----------- private associated constant defined here +... +LL | ::A; + | ^ private associated constant + +error[E0038]: the trait `assoc_const::C` cannot be made into an object + --> $DIR/item-privacy.rs:101:6 + | +LL | ::A; + | ^^^^^ `assoc_const::C` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/item-privacy.rs:25:15 + | +LL | const A: u8 = 0; + | ^ ...because it contains this associated `const` +... +LL | const B: u8 = 0; + | ^ ...because it contains this associated `const` +... +LL | pub trait C: A + B { + | - this trait cannot be made into an object... +LL | const C: u8 = 0; + | ^ ...because it contains this associated `const` + = help: consider moving `C` to another trait + = help: consider moving `A` to another trait + = help: consider moving `B` to another trait + +error[E0223]: ambiguous associated type + --> $DIR/item-privacy.rs:115:12 + | +LL | let _: S::A; + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | let _: ::A; + | ~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/item-privacy.rs:116:12 + | +LL | let _: S::B; + | ^^^^ help: use the fully-qualified path: `::B` + +error[E0223]: ambiguous associated type + --> $DIR/item-privacy.rs:117:12 + | +LL | let _: S::C; + | ^^^^ help: use the fully-qualified path: `::C` + +error[E0624]: associated type `A` is private + --> $DIR/item-privacy.rs:119:12 + | +LL | type A = u8; + | ------ associated type defined here +... +LL | let _: T::A; + | ^^^^ private associated type + +error: associated type `A` is private + --> $DIR/item-privacy.rs:128:9 + | +LL | A = u8, + | ^^^^^^ private associated type + +error: aborting due to 15 previous errors + +Some errors have detailed explanations: E0038, E0223, E0599, E0624. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/kindck-owned-contains-1.rs b/tests/ui/traits/kindck-owned-contains-1.rs new file mode 100644 index 000000000..8adb06ba3 --- /dev/null +++ b/tests/ui/traits/kindck-owned-contains-1.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(non_snake_case)] +#![allow(non_camel_case_types)] + +trait repeat { fn get(&self) -> A; } + +impl repeat for Box { + fn get(&self) -> A { + (**self).clone() + } +} + +fn repeater(v: Box) -> Box+'static> { + Box::new(v) as Box+'static> // No +} + +pub fn main() { + let x = 3; + let y = repeater(Box::new(x)); + assert_eq!(x, y.get()); +} diff --git a/tests/ui/traits/map-types.rs b/tests/ui/traits/map-types.rs new file mode 100644 index 000000000..dc33b9618 --- /dev/null +++ b/tests/ui/traits/map-types.rs @@ -0,0 +1,19 @@ +use std::collections::HashMap; + + + +trait Map +{ + fn get(&self, k: K) -> V { panic!() } +} + +impl Map for HashMap {} + +// Test that trait types printed in error msgs include the type arguments. + +fn main() { + let x: Box> = HashMap::new().into(); + let x: Box> = x; + let y: Box> = Box::new(x); + //~^ ERROR `Box>: Map` is not satisfied +} diff --git a/tests/ui/traits/map-types.stderr b/tests/ui/traits/map-types.stderr new file mode 100644 index 000000000..f685c50b0 --- /dev/null +++ b/tests/ui/traits/map-types.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Box>: Map` is not satisfied + --> $DIR/map-types.rs:17:41 + | +LL | let y: Box> = Box::new(x); + | ^^^^^^^^^^^ the trait `Map` is not implemented for `Box>` + | + = help: the trait `Map` is implemented for `HashMap` + = note: required for the cast from `Box>` to the object type `dyn Map` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/matching-lifetimes.rs b/tests/ui/traits/matching-lifetimes.rs new file mode 100644 index 000000000..1430dc655 --- /dev/null +++ b/tests/ui/traits/matching-lifetimes.rs @@ -0,0 +1,20 @@ +// Tests that the trait matching code takes lifetime parameters into account. +// (Issue #15517.) + +struct Foo<'a,'b> { + x: &'a isize, + y: &'b isize, +} + +trait Tr : Sized { + fn foo(x: Self) {} +} + +impl<'a,'b> Tr for Foo<'a,'b> { + fn foo(x: Foo<'b,'a>) { + //~^ ERROR method not compatible with trait + //~^^ ERROR method not compatible with trait + } +} + +fn main(){} diff --git a/tests/ui/traits/matching-lifetimes.stderr b/tests/ui/traits/matching-lifetimes.stderr new file mode 100644 index 000000000..f8119ed41 --- /dev/null +++ b/tests/ui/traits/matching-lifetimes.stderr @@ -0,0 +1,41 @@ +error[E0308]: method not compatible with trait + --> $DIR/matching-lifetimes.rs:14:5 + | +LL | fn foo(x: Foo<'b,'a>) { + | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(Foo<'a, 'b>)` + found signature `fn(Foo<'b, 'a>)` +note: the lifetime `'b` as defined here... + --> $DIR/matching-lifetimes.rs:13:9 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/matching-lifetimes.rs:13:6 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ + +error[E0308]: method not compatible with trait + --> $DIR/matching-lifetimes.rs:14:5 + | +LL | fn foo(x: Foo<'b,'a>) { + | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(Foo<'a, 'b>)` + found signature `fn(Foo<'b, 'a>)` +note: the lifetime `'a` as defined here... + --> $DIR/matching-lifetimes.rs:13:6 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ +note: ...does not necessarily outlive the lifetime `'b` as defined here + --> $DIR/matching-lifetimes.rs:13:9 + | +LL | impl<'a,'b> Tr for Foo<'a,'b> { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/method-private.rs b/tests/ui/traits/method-private.rs new file mode 100644 index 000000000..4cd184854 --- /dev/null +++ b/tests/ui/traits/method-private.rs @@ -0,0 +1,20 @@ +mod inner { + pub trait Bar { + fn method(&self); + } + + pub struct Foo; + + impl Foo { + fn method(&self) {} + } + + impl Bar for Foo { + fn method(&self) {} + } +} + +fn main() { + let foo = inner::Foo; + foo.method(); //~ ERROR is private +} diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr new file mode 100644 index 000000000..8e991ec01 --- /dev/null +++ b/tests/ui/traits/method-private.stderr @@ -0,0 +1,18 @@ +error[E0624]: associated function `method` is private + --> $DIR/method-private.rs:19:9 + | +LL | fn method(&self) {} + | ---------------- private associated function defined here +... +LL | foo.method(); + | ^^^^^^ private associated function + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use inner::Bar; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/traits/monad.rs b/tests/ui/traits/monad.rs new file mode 100644 index 000000000..5d0612cf8 --- /dev/null +++ b/tests/ui/traits/monad.rs @@ -0,0 +1,48 @@ +// run-pass + +#![allow(non_camel_case_types)] + + + +trait vec_monad { + fn bind(&self, f: F ) -> Vec where F: FnMut(&A) -> Vec ; +} + +impl vec_monad for Vec { + fn bind(&self, mut f: F) -> Vec where F: FnMut(&A) -> Vec { + let mut r = Vec::new(); + for elt in self { + r.extend(f(elt)); + } + r + } +} + +trait option_monad { + fn bind(&self, f: F) -> Option where F: FnOnce(&A) -> Option; +} + +impl option_monad for Option { + fn bind(&self, f: F) -> Option where F: FnOnce(&A) -> Option { + match *self { + Some(ref a) => { f(a) } + None => { None } + } + } +} + +fn transform(x: Option) -> Option { + x.bind(|n| Some(*n + 1) ).bind(|n| Some(n.to_string()) ) +} + +pub fn main() { + assert_eq!(transform(Some(10)), Some("11".to_string())); + assert_eq!(transform(None), None); + assert_eq!((vec!["hi".to_string()]) + .bind(|x| vec![x.clone(), format!("{}!", x)] ) + .bind(|x| vec![x.clone(), format!("{}?", x)] ), + ["hi".to_string(), + "hi?".to_string(), + "hi!".to_string(), + "hi!?".to_string()]); +} diff --git a/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs b/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs new file mode 100644 index 000000000..bc314a39d --- /dev/null +++ b/tests/ui/traits/monomorphized-callees-with-ty-params-3314.rs @@ -0,0 +1,32 @@ +// run-pass +// pretty-expanded FIXME #23616 + +trait Serializer { +} + +trait Serializable { + fn serialize(&self, s: S); +} + +impl Serializable for isize { + fn serialize(&self, _s: S) { } +} + +struct F { a: A } + +impl Serializable for F { + fn serialize(&self, s: S) { + self.a.serialize(s); + } +} + +impl Serializer for isize { +} + +pub fn main() { + let foo = F { a: 1 }; + foo.serialize(1); + + let bar = F { a: F {a: 1 } }; + bar.serialize(2); +} diff --git a/tests/ui/traits/multidispatch-bad.rs b/tests/ui/traits/multidispatch-bad.rs new file mode 100644 index 000000000..b625b9615 --- /dev/null +++ b/tests/ui/traits/multidispatch-bad.rs @@ -0,0 +1,22 @@ +// Test that we detect an illegal combination of types. + +trait Convert { + fn convert(&self) -> Target; +} + +impl Convert for i32 { + fn convert(&self) -> u32 { + *self as u32 + } +} + +fn test(_: T, _: U) +where T : Convert +{ +} + +fn a() { + test(22i32, 44i32); //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/traits/multidispatch-bad.stderr b/tests/ui/traits/multidispatch-bad.stderr new file mode 100644 index 000000000..d58f1e2d9 --- /dev/null +++ b/tests/ui/traits/multidispatch-bad.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/multidispatch-bad.rs:19:17 + | +LL | test(22i32, 44i32); + | ---- ^^^^^ expected `u32`, found `i32` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/multidispatch-bad.rs:13:4 + | +LL | fn test(_: T, _: U) + | ^^^^ ---- +help: change the type of the numeric literal from `i32` to `u32` + | +LL | test(22i32, 44u32); + | ~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs new file mode 100644 index 000000000..f845e198a --- /dev/null +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that we correctly ignore the blanket impl +// because (in this case) `T` does not impl `Clone`. +// +// Issue #17594. + +use std::cell::RefCell; + +trait Foo { + fn foo(&self) {} +} + +impl Foo for T where T: Clone {} + +struct Bar; + +impl Bar { + fn foo(&self) {} +} + +fn main() { + let b = RefCell::new(Bar); + b.borrow().foo(); +} diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.rs b/tests/ui/traits/multidispatch-convert-ambig-dest.rs new file mode 100644 index 000000000..aa74e11c3 --- /dev/null +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.rs @@ -0,0 +1,31 @@ +// Check that we get an error in a multidisptach scenario where the +// set of impls is ambiguous. + +trait Convert { + fn convert(&self) -> Target; +} + +impl Convert for i32 { + fn convert(&self) -> i8 { + *self as i8 + } +} + +impl Convert for i32 { + fn convert(&self) -> i16 { + *self as i16 + } +} + +fn test(_: T, _: U) +where T : Convert +{ +} + +fn a() { + test(22, std::default::Default::default()); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr new file mode 100644 index 000000000..6e6172eea --- /dev/null +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -0,0 +1,43 @@ +error[E0282]: type annotations needed + --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 + | +LL | test(22, std::default::Default::default()); + | ^^^^ cannot infer type of the type parameter `U` declared on the function `test` + | +help: consider specifying the generic arguments + | +LL | test::(22, std::default::Default::default()); + | ++++++++++ + +error[E0283]: type annotations needed + --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 + | +LL | test(22, std::default::Default::default()); + | ^^^^ -------------------------------- type must be known at this point + | | + | cannot infer type of the type parameter `U` declared on the function `test` + | +note: multiple `impl`s satisfying `i32: Convert<_>` found + --> $DIR/multidispatch-convert-ambig-dest.rs:8:1 + | +LL | impl Convert for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Convert for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `test` + --> $DIR/multidispatch-convert-ambig-dest.rs:21:11 + | +LL | fn test(_: T, _: U) + | ---- required by a bound in this +LL | where T : Convert + | ^^^^^^^^^^ required by this bound in `test` +help: consider specifying the generic arguments + | +LL | test::(22, std::default::Default::default()); + | ++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/multidispatch-infer-convert-target.rs b/tests/ui/traits/multidispatch-infer-convert-target.rs new file mode 100644 index 000000000..626e1ae71 --- /dev/null +++ b/tests/ui/traits/multidispatch-infer-convert-target.rs @@ -0,0 +1,36 @@ +// run-pass +// Test that we can infer the Target based on the Self or vice versa. + + +use std::mem; + +trait Convert { + fn convert(&self) -> Target; +} + +impl Convert for i16 { + fn convert(&self) -> u32 { + *self as u32 + } +} + +impl Convert for u32 { + fn convert(&self) -> i16 { + *self as i16 + } +} + +fn test(_: T, _: U, t_size: usize, u_size: usize) +where T : Convert +{ + assert_eq!(mem::size_of::(), t_size); + assert_eq!(mem::size_of::(), u_size); +} + +fn main() { + // T = i16, U = u32 + test(22_i16, Default::default(), 2, 4); + + // T = u32, U = i16 + test(22_u32, Default::default(), 4, 2); +} diff --git a/tests/ui/traits/multidispatch1.rs b/tests/ui/traits/multidispatch1.rs new file mode 100644 index 000000000..f2469e149 --- /dev/null +++ b/tests/ui/traits/multidispatch1.rs @@ -0,0 +1,33 @@ +// run-pass + +use std::fmt::Debug; + +trait MyTrait { + fn get(&self) -> T; +} + +#[derive(Copy, Clone)] +struct MyType { + dummy: usize +} + +impl MyTrait for MyType { + fn get(&self) -> usize { self.dummy } +} + +impl MyTrait for MyType { + fn get(&self) -> u8 { self.dummy as u8 } +} + +fn test_eq(m: M, v: T) +where T : Eq + Debug, + M : MyTrait +{ + assert_eq!(m.get(), v); +} + +pub fn main() { + let value = MyType { dummy: 256 + 22 }; + test_eq::(value, value.dummy); + test_eq::(value, value.dummy as u8); +} diff --git a/tests/ui/traits/multidispatch2.rs b/tests/ui/traits/multidispatch2.rs new file mode 100644 index 000000000..20608aabb --- /dev/null +++ b/tests/ui/traits/multidispatch2.rs @@ -0,0 +1,39 @@ +// run-pass + +use std::fmt::Debug; +use std::default::Default; + +trait MyTrait { + fn get(&self) -> T; +} + +impl MyTrait for T + where T : Default +{ + fn get(&self) -> T { + Default::default() + } +} + +#[derive(Copy, Clone)] +struct MyType { + dummy: usize +} + +impl MyTrait for MyType { + fn get(&self) -> usize { self.dummy } +} + +fn test_eq(m: M, v: T) +where T : Eq + Debug, + M : MyTrait +{ + assert_eq!(m.get(), v); +} + +pub fn main() { + test_eq(22_usize, 0_usize); + + let value = MyType { dummy: 256 + 22 }; + test_eq(value, value.dummy); +} diff --git a/tests/ui/traits/mutual-recursion-issue-75860.rs b/tests/ui/traits/mutual-recursion-issue-75860.rs new file mode 100644 index 000000000..d7d7307b4 --- /dev/null +++ b/tests/ui/traits/mutual-recursion-issue-75860.rs @@ -0,0 +1,15 @@ +pub fn iso(a: F1, b: F2) -> (Box B>, Box A>) + where + F1: (Fn(A) -> B) + 'static, + F2: (Fn(B) -> A) + 'static, +{ + (Box::new(a), Box::new(b)) +} +pub fn iso_un_option() -> (Box B>, Box A>) { + let left = |o_a: Option<_>| o_a.unwrap(); + let right = |o_b: Option<_>| o_b.unwrap(); + iso(left, right) + //~^ ERROR overflow +} + +fn main() {} diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr new file mode 100644 index 000000000..23e182738 --- /dev/null +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -0,0 +1,13 @@ +error[E0275]: overflow evaluating the requirement `Option<_>: Sized` + --> $DIR/mutual-recursion-issue-75860.rs:11:5 + | +LL | iso(left, right) + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`) +note: required by a bound in `Option` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs new file mode 100644 index 000000000..0e17f0890 --- /dev/null +++ b/tests/ui/traits/negative-impls/auxiliary/foreign_trait.rs @@ -0,0 +1,7 @@ +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +pub trait ForeignTrait {} + +impl ForeignTrait for u32 {} +impl !ForeignTrait for String {} diff --git a/tests/ui/traits/negative-impls/eager-mono.rs b/tests/ui/traits/negative-impls/eager-mono.rs new file mode 100644 index 000000000..ce770376c --- /dev/null +++ b/tests/ui/traits/negative-impls/eager-mono.rs @@ -0,0 +1,12 @@ +// build-pass +// compile-flags:-C link-dead-code=y + +#![feature(negative_impls)] + +trait Foo { + fn foo() {} +} + +impl !Foo for () {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs new file mode 100644 index 000000000..17ddaa312 --- /dev/null +++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.rs @@ -0,0 +1,53 @@ +// This tests issue #79683: note in the error message that the trait is +// explicitly unimplemented instead of suggesting to implement it. + +#![feature(negative_impls)] + +struct Qux; +//~^ NOTE method `clone` not found for this +//~^^ NOTE method `foo` not found for this + +impl !Clone for Qux {} + +trait Bar { + fn bar(&self); +} + +impl !Bar for u32 {} + +trait Foo { + fn foo(&self); +} +//~^^^ NOTE `Foo` defines an item `foo`, perhaps you need to implement it + +trait FooBar { + fn foo(&self); +} + +impl !Foo for Qux {} + +impl !FooBar for Qux {} + +impl !FooBar for u32 {} + +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 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 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 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 explicitly unimplemented +} diff --git a/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr new file mode 100644 index 000000000..b29442d7b --- /dev/null +++ b/tests/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -0,0 +1,52 @@ +error[E0599]: no method named `clone` found for struct `Qux` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:34:9 + | +LL | struct Qux; + | ---------- method `clone` not found for this struct +... +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 explicitly unimplemented + +error[E0599]: no method named `bar` found for type `u32` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:39:11 + | +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 explicitly unimplemented + +error[E0599]: no method named `foo` found for struct `Qux` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:44:9 + | +LL | struct Qux; + | ---------- method `foo` not found for this struct +... +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 explicitly unimplemented: + Foo + FooBar + +error[E0599]: no method named `foo` found for type `u32` in the current scope + --> $DIR/explicitly-unimplemented-error-message.rs:49:11 + | +LL | 0_u32.foo(); + | ^^^ method not found in `u32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo`, perhaps you need to implement it + --> $DIR/explicitly-unimplemented-error-message.rs:18:1 + | +LL | trait Foo { + | ^^^^^^^^^ + = note: the trait `FooBar` defines an item `foo`, but is explicitly unimplemented + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs new file mode 100644 index 000000000..683fd6db6 --- /dev/null +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs @@ -0,0 +1,3 @@ +trait MyTrait {} +impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not yet fully implemented +fn main() {} diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr new file mode 100644 index 000000000..b253fbd0d --- /dev/null +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr @@ -0,0 +1,12 @@ +error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now + --> $DIR/feature-gate-negative_impls.rs:2:6 + | +LL | impl !MyTrait for u32 {} + | ^^^^^^^^ + | + = note: see issue #68318 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.rs b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs new file mode 100644 index 000000000..4bdad5dc5 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.rs @@ -0,0 +1,68 @@ +// The dummy functions are used to avoid adding new cfail files. +// What happens is that the compiler attempts to squash duplicates and some +// errors are not reported. This way, we make sure that, for each function, different +// typeck phases are involved and all errors are reported. + +#![feature(negative_impls)] + +use std::marker::Send; + +struct Outer(T); + +struct Outer2(T); + +unsafe impl Sync for Outer2 {} + +fn is_send(_: T) {} +fn is_sync(_: T) {} + +fn dummy() { + struct TestType; + impl !Send for TestType {} + + Outer(TestType); + //~^ ERROR `dummy::TestType` cannot be sent between threads safely + //~| ERROR `dummy::TestType` cannot be sent between threads safely +} + +fn dummy1b() { + struct TestType; + impl !Send for TestType {} + + is_send(TestType); + //~^ ERROR `dummy1b::TestType` cannot be sent between threads safely +} + +fn dummy1c() { + struct TestType; + impl !Send for TestType {} + + is_send((8, TestType)); + //~^ ERROR `dummy1c::TestType` cannot be sent between threads safely +} + +fn dummy2() { + struct TestType; + impl !Send for TestType {} + + is_send(Box::new(TestType)); + //~^ ERROR `dummy2::TestType` cannot be sent between threads safely +} + +fn dummy3() { + struct TestType; + impl !Send for TestType {} + + is_send(Box::new(Outer2(TestType))); + //~^ ERROR `dummy3::TestType` cannot be sent between threads safely +} + +fn main() { + struct TestType; + impl !Send for TestType {} + + // This will complain about a missing Send impl because `Sync` is implement *just* + // for T that are `Send`. Look at #20366 and #19950 + is_sync(Outer2(TestType)); + //~^ ERROR `main::TestType` cannot be sent between threads safely +} diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr new file mode 100644 index 000000000..ce690b749 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -0,0 +1,127 @@ +error[E0277]: `dummy::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:23:11 + | +LL | Outer(TestType); + | ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `dummy::TestType` +note: required by a bound in `Outer` + --> $DIR/negated-auto-traits-error.rs:10:17 + | +LL | struct Outer(T); + | ^^^^ required by this bound in `Outer` + +error[E0277]: `dummy::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:23:5 + | +LL | Outer(TestType); + | ^^^^^^^^^^^^^^^ `dummy::TestType` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `dummy::TestType` +note: required by a bound in `Outer` + --> $DIR/negated-auto-traits-error.rs:10:17 + | +LL | struct Outer(T); + | ^^^^ required by this bound in `Outer` + +error[E0277]: `dummy1b::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:32:13 + | +LL | is_send(TestType); + | ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `dummy1b::TestType` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `dummy1c::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:40:13 + | +LL | is_send((8, TestType)); + | ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` + = note: required because it appears within the type `({integer}, TestType)` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `dummy2::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:48:13 + | +LL | is_send(Box::new(TestType)); + | ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Unique: Send` is not satisfied + = note: required for `Unique` to implement `Send` + = note: required because it appears within the type `Box` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` +help: consider borrowing here + | +LL | is_send(&Box::new(TestType)); + | + + +error[E0277]: `dummy3::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:56:13 + | +LL | is_send(Box::new(Outer2(TestType))); + | ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `Outer2`, the trait `Send` is not implemented for `dummy3::TestType` +note: required because it appears within the type `Outer2` + --> $DIR/negated-auto-traits-error.rs:12:8 + | +LL | struct Outer2(T); + | ^^^^^^ + = note: required for `Unique>` to implement `Send` + = note: required because it appears within the type `Box>` +note: required by a bound in `is_send` + --> $DIR/negated-auto-traits-error.rs:16:15 + | +LL | fn is_send(_: T) {} + | ^^^^ required by this bound in `is_send` + +error[E0277]: `main::TestType` cannot be sent between threads safely + --> $DIR/negated-auto-traits-error.rs:66:13 + | +LL | is_sync(Outer2(TestType)); + | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `main::TestType` +note: required for `Outer2` to implement `Sync` + --> $DIR/negated-auto-traits-error.rs:14:22 + | +LL | unsafe impl Sync for Outer2 {} + | ---- ^^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `is_sync` + --> $DIR/negated-auto-traits-error.rs:17:15 + | +LL | fn is_sync(_: T) {} + | ^^^^ required by this bound in `is_sync` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs new file mode 100644 index 000000000..a1042f831 --- /dev/null +++ b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_variables)] +#![feature(negative_impls)] + +use std::marker::Send; + +pub struct WaitToken; +impl !Send for WaitToken {} + +pub struct Test(#[allow(unused_tuple_struct_fields)] T); +unsafe impl Send for Test {} + +pub fn spawn(_: F) -> () where F: FnOnce(), F: Send + 'static {} + +fn main() { + let wt = Test(WaitToken); + spawn(move || { + let x = wt; + println!("Hello, World!"); + }); +} diff --git a/tests/ui/traits/negative-impls/negative-default-impls.rs b/tests/ui/traits/negative-impls/negative-default-impls.rs new file mode 100644 index 000000000..c68bca432 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-default-impls.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait MyTrait { + type Foo; +} + +default impl !MyTrait for u32 {} //~ ERROR negative impls cannot be default impls + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-default-impls.stderr b/tests/ui/traits/negative-impls/negative-default-impls.stderr new file mode 100644 index 000000000..7b54cf542 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-default-impls.stderr @@ -0,0 +1,19 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-default-impls.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0750]: negative impls cannot be default impls + --> $DIR/negative-default-impls.rs:9:1 + | +LL | default impl !MyTrait for u32 {} + | ^^^^^^^ ^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0750`. diff --git a/tests/ui/traits/negative-impls/negative-impls-basic.rs b/tests/ui/traits/negative-impls/negative-impls-basic.rs new file mode 100644 index 000000000..474e03817 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-impls-basic.rs @@ -0,0 +1,17 @@ +// A simple test that we are able to create negative impls, when the +// feature gate is given. +// +// run-pass + +#![feature(negative_impls)] +#![allow(dead_code)] + +struct TestType; + +trait TestTrait { + fn dummy(&self) {} +} + +impl !TestTrait for TestType {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs new file mode 100644 index 000000000..35297ab12 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +// Test a negative impl that "specializes" another negative impl. +// +// run-pass + +trait MyTrait {} + +impl !MyTrait for T {} +impl !MyTrait for u32 {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.stderr b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr new file mode 100644 index 000000000..751e29c3b --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-negative.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs new file mode 100644 index 000000000..4281eedaf --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -0,0 +1,13 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait { + fn foo(); +} +impl MyTrait for T { + default fn foo() {} +} +impl !MyTrait for u32 {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr new file mode 100644 index 000000000..1cfa49b20 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -0,0 +1,22 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-positive-item.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive-item.rs:11:1 + | +LL | impl MyTrait for T { + | --------------------- positive implementation here +... +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.rs b/tests/ui/traits/negative-impls/negative-specializes-positive.rs new file mode 100644 index 000000000..0e227691e --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive.rs @@ -0,0 +1,14 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +// Negative impl for u32 cannot "specialize" the base impl. +trait MyTrait {} +impl MyTrait for T {} +impl !MyTrait for u32 {} //~ ERROR E0751 + +// The second impl specializes the first, no error. +trait MyTrait2 {} +impl MyTrait2 for T {} +impl MyTrait2 for u32 {} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr new file mode 100644 index 000000000..9f9e28678 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-specializes-positive.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/negative-specializes-positive.rs:7:1 + | +LL | impl MyTrait for T {} + | --------------------- positive implementation here +LL | impl !MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/no-items.rs b/tests/ui/traits/negative-impls/no-items.rs new file mode 100644 index 000000000..5fc6be9b3 --- /dev/null +++ b/tests/ui/traits/negative-impls/no-items.rs @@ -0,0 +1,11 @@ +#![feature(negative_impls)] + +trait MyTrait { + type Foo; +} + +impl !MyTrait for u32 { + type Foo = i32; //~ ERROR negative impls cannot have any items +} + +fn main() {} diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr new file mode 100644 index 000000000..67b94bba1 --- /dev/null +++ b/tests/ui/traits/negative-impls/no-items.stderr @@ -0,0 +1,9 @@ +error[E0749]: negative impls cannot have any items + --> $DIR/no-items.rs:8:5 + | +LL | type Foo = i32; + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0749`. diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs new file mode 100644 index 000000000..a5b856465 --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs @@ -0,0 +1,26 @@ +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::pin::Pin; + +struct MyType<'a>(Cell>>, PhantomPinned); + +impl<'a> Clone for &'a mut MyType<'a> { + //~^ ERROR E0751 + fn clone(&self) -> &'a mut MyType<'a> { + self.0.take().unwrap() + } +} + +fn main() { + let mut unpinned = MyType(Cell::new(None), PhantomPinned); + let bad_addr = &unpinned as *const MyType<'_> as usize; + let mut p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned)); + + // p_mut1 is okay: it does not point to the bad_addr + let p_mut1: Pin<&mut MyType<'_>> = p.as_mut(); + assert_ne!(bad_addr, &*p_mut1 as *const _ as usize); + + // but p_mut2 does point to bad_addr! this is unsound + let p_mut2: Pin<&mut MyType<'_>> = p_mut1.clone(); + assert_eq!(bad_addr, &*p_mut2 as *const _ as usize); +} diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr new file mode 100644 index 000000000..a87acb1fb --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr @@ -0,0 +1,11 @@ +error[E0751]: found both positive and negative implementation of trait `Clone` for type `&mut MyType<'_>`: + --> $DIR/pin-unsound-issue-66544-clone.rs:7:1 + | +LL | impl<'a> Clone for &'a mut MyType<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here + | + = note: negative implementation in crate `core` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs new file mode 100644 index 000000000..606cc65a8 --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs @@ -0,0 +1,33 @@ +// Demonstrate that "rogue" `DerefMut` impls for `&T` are not allowed. +// +// https://github.com/rust-lang/rust/issues/66544 + +use std::cell::Cell; +use std::marker::PhantomPinned; +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyType<'a>(Cell>>, PhantomPinned); + +impl<'a> DerefMut for &'a MyType<'a> { + //~^ ERROR E0751 + fn deref_mut(&mut self) -> &mut MyType<'a> { + self.0.take().unwrap() + } +} + +fn main() { + let mut unpinned = MyType(Cell::new(None), PhantomPinned); + let bad_addr = &unpinned as *const MyType<'_> as usize; + let p = Box::pin(MyType(Cell::new(Some(&mut unpinned)), PhantomPinned)); + + // p_ref is okay: it does not point to the bad_addr + let mut p_ref: Pin<&MyType<'_>> = p.as_ref(); + assert_ne!(bad_addr, &*p_ref as *const _ as usize); + + // but p_mut does point to bad_addr! this is unsound + let p_mut: Pin<&mut MyType<'_>> = p_ref.as_mut(); + assert_eq!(bad_addr, &*p_mut as *const _ as usize); + + println!("oh no!"); +} diff --git a/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr new file mode 100644 index 000000000..9185e8f84 --- /dev/null +++ b/tests/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr @@ -0,0 +1,11 @@ +error[E0751]: found both positive and negative implementation of trait `DerefMut` for type `&MyType<'_>`: + --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1 + | +LL | impl<'a> DerefMut for &'a MyType<'a> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ positive implementation here + | + = note: negative implementation in crate `core` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.rs b/tests/ui/traits/negative-impls/positive-specializes-negative.rs new file mode 100644 index 000000000..a06b35765 --- /dev/null +++ b/tests/ui/traits/negative-impls/positive-specializes-negative.rs @@ -0,0 +1,9 @@ +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(negative_impls)] + +trait MyTrait {} + +impl !MyTrait for T {} +impl MyTrait for u32 {} //~ ERROR E0751 + +fn main() {} diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr new file mode 100644 index 000000000..545f94143 --- /dev/null +++ b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/positive-specializes-negative.rs:1:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: + --> $DIR/positive-specializes-negative.rs:7:1 + | +LL | impl !MyTrait for T {} + | ---------------------- negative implementation here +LL | impl MyTrait for u32 {} + | ^^^^^^^^^^^^^^^^^^^^ positive implementation here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0751`. diff --git a/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs new file mode 100644 index 000000000..c1f96ab8c --- /dev/null +++ b/tests/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs @@ -0,0 +1,24 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(with_negative_coherence)] + +// aux-build: foreign_trait.rs + +// Test that we cannot implement `LocalTrait` for `String`, +// even though there is a `String: !ForeignTrait` impl. +// +// This may not be the behavior we want long term, but it's the +// current semantics that we implemented so as to land `!Foo` impls +// quickly. See internals thread: +// +// https://internals.rust-lang.org/t/foo/11587/ + +extern crate foreign_trait; +use foreign_trait::ForeignTrait; + +trait LocalTrait {} +impl LocalTrait for T {} +impl LocalTrait for String {} + +fn main() {} diff --git a/tests/ui/traits/new-solver/fn-trait-closure.rs b/tests/ui/traits/new-solver/fn-trait-closure.rs new file mode 100644 index 000000000..c0ecf1c91 --- /dev/null +++ b/tests/ui/traits/new-solver/fn-trait-closure.rs @@ -0,0 +1,15 @@ +// compile-flags: -Ztrait-solver=next +// known-bug: unknown +// failure-status: 101 +// dont-check-compiler-stderr + +// This test will fail until we fix `FulfillmentCtxt::relationships`. That's +// because we create a type variable for closure upvar types, which is not +// constrained until after we try to do fallback on diverging type variables. +// Thus, we will call that function, which is unimplemented. + +fn require_fn(_: impl Fn() -> i32) {} + +fn main() { + require_fn(|| -> i32 { 1i32 }); +} diff --git a/tests/ui/traits/new-solver/fn-trait.rs b/tests/ui/traits/new-solver/fn-trait.rs new file mode 100644 index 000000000..d566ead10 --- /dev/null +++ b/tests/ui/traits/new-solver/fn-trait.rs @@ -0,0 +1,13 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +fn require_fn(_: impl Fn() -> i32) {} + +fn f() -> i32 { + 1i32 +} + +fn main() { + require_fn(f); + require_fn(f as fn() -> i32); +} diff --git a/tests/ui/traits/new-solver/pointer-sized.rs b/tests/ui/traits/new-solver/pointer-sized.rs new file mode 100644 index 000000000..15681cd13 --- /dev/null +++ b/tests/ui/traits/new-solver/pointer-sized.rs @@ -0,0 +1,12 @@ +#![feature(pointer_sized_trait)] + +use std::marker::PointerSized; + +fn require_pointer_sized(_: impl PointerSized) {} + +fn main() { + require_pointer_sized(1usize); + require_pointer_sized(1u16); + //~^ ERROR `u16` needs to be a pointer-sized type + require_pointer_sized(&1i16); +} diff --git a/tests/ui/traits/new-solver/pointer-sized.stderr b/tests/ui/traits/new-solver/pointer-sized.stderr new file mode 100644 index 000000000..b250b1331 --- /dev/null +++ b/tests/ui/traits/new-solver/pointer-sized.stderr @@ -0,0 +1,24 @@ +error[E0277]: `u16` needs to be a pointer-sized type + --> $DIR/pointer-sized.rs:9:27 + | +LL | require_pointer_sized(1u16); + | --------------------- ^^^^ the trait `PointerSized` is not implemented for `u16` + | | + | required by a bound introduced by this call + | + = note: the trait bound `u16: PointerSized` is not satisfied +note: required by a bound in `require_pointer_sized` + --> $DIR/pointer-sized.rs:5:34 + | +LL | fn require_pointer_sized(_: impl PointerSized) {} + | ^^^^^^^^^^^^ required by this bound in `require_pointer_sized` +help: consider borrowing here + | +LL | require_pointer_sized(&1u16); + | + +LL | require_pointer_sized(&mut 1u16); + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/no-fallback-multiple-impls.rs b/tests/ui/traits/no-fallback-multiple-impls.rs new file mode 100644 index 000000000..7ed3796f0 --- /dev/null +++ b/tests/ui/traits/no-fallback-multiple-impls.rs @@ -0,0 +1,16 @@ +trait Fallback { + fn foo(&self) {} +} + +impl Fallback for i32 {} + +impl Fallback for u64 {} + +impl Fallback for usize {} + +fn main() { + missing(); + //~^ ERROR cannot find function `missing` in this scope + 0.foo(); + // But then we shouldn't report an inference ambiguity here... +} diff --git a/tests/ui/traits/no-fallback-multiple-impls.stderr b/tests/ui/traits/no-fallback-multiple-impls.stderr new file mode 100644 index 000000000..61c9e5aaa --- /dev/null +++ b/tests/ui/traits/no-fallback-multiple-impls.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/no-fallback-multiple-impls.rs:12:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/traits/no_send-struct.rs b/tests/ui/traits/no_send-struct.rs new file mode 100644 index 000000000..75a363f9f --- /dev/null +++ b/tests/ui/traits/no_send-struct.rs @@ -0,0 +1,17 @@ +#![feature(negative_impls)] + +use std::marker::Send; + +struct Foo { + a: isize, +} + +impl !Send for Foo {} + +fn bar(_: T) {} + +fn main() { + let x = Foo { a: 5 }; + bar(x); + //~^ ERROR `Foo` cannot be sent between threads safely +} diff --git a/tests/ui/traits/no_send-struct.stderr b/tests/ui/traits/no_send-struct.stderr new file mode 100644 index 000000000..ee7bdf282 --- /dev/null +++ b/tests/ui/traits/no_send-struct.stderr @@ -0,0 +1,18 @@ +error[E0277]: `Foo` cannot be sent between threads safely + --> $DIR/no_send-struct.rs:15:9 + | +LL | bar(x); + | --- ^ `Foo` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Send` is not implemented for `Foo` +note: required by a bound in `bar` + --> $DIR/no_send-struct.rs:11:11 + | +LL | fn bar(_: T) {} + | ^^^^ required by this bound in `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/normalize-supertrait.rs b/tests/ui/traits/normalize-supertrait.rs new file mode 100644 index 000000000..021a93eac --- /dev/null +++ b/tests/ui/traits/normalize-supertrait.rs @@ -0,0 +1,37 @@ +// Regression test for #77653 +// When monomorphizing `f` we need to prove `dyn Derived<()>: Base<()>`. This +// requires us to normalize the `Base<<() as Proj>::S>` to `Base<()>` when +// comparing the supertrait `Derived<()>` to the expected trait. + +// build-pass + +trait Proj { + type S; +} + +impl Proj for () { + type S = (); +} + +impl Proj for i32 { + type S = i32; +} + +trait Base { + fn is_base(&self); +} + +trait Derived: Base + Base<()> { + fn is_derived(&self); +} + +fn f(obj: &dyn Derived

{} + +impl Tnobound for () { } + +// This variant is accepted at the definition site; but it will be +// rejected at every possible usage site (such as the one immediately +// below). Maybe one day we will attempt to catch it at the definition +// site, but today this is accepted due to compiler implementation +// limitations. +trait Tsized {} + +impl Tsized for () {} +//~^ ERROR the size for values of type `[()]` cannot be known at compilation time [E0277] diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr new file mode 100644 index 000000000..679118223 --- /dev/null +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6 + | +LL | impl Tsized for () {} + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` +note: required by a bound in `Tsized` + --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14 + | +LL | trait Tsized {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs new file mode 100644 index 000000000..12db143e4 --- /dev/null +++ b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.rs @@ -0,0 +1,45 @@ +#![crate_type="lib"] + +// rust-lang/rust#61631: Uses of `Self` in the defaults of generic +// types for ADT's are not allowed. We justify this because the `Self` +// type could be considered the "final" type parameter, that is only +// well-defined after all of the other type parameters on the ADT have +// been instantiated. +// +// These were previously were ICE'ing at the usage point anyway (see +// `demo_usages` below), so there should not be any backwards +// compatibility concern. + +struct Snobound<'a, P = Self> { x: Option<&'a P> } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +enum Enobound<'a, P = Self> { A, B(Option<&'a P>) } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +// Disallowing `Self` in defaults sidesteps need to check the bounds +// on the defaults in cases like these. + +struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +fn demo_usages() { + // An ICE means you only get the error from the first line of the + // demo; comment each out to observe the other ICEs when trying + // this out on older versions of Rust. + + let _ice: Snobound; + let _ice: Enobound; + let _ice: Unobound; + let _ice: Ssized; + let _ice: Esized; + let _ice: Usized; +} diff --git a/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr new file mode 100644 index 000000000..f3a550801 --- /dev/null +++ b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr @@ -0,0 +1,39 @@ +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25 + | +LL | struct Snobound<'a, P = Self> { x: Option<&'a P> } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23 + | +LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24 + | +LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31 + | +LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29 + | +LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30 + | +LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> } + | ^^^^ `Self` in generic parameter default + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0735`. diff --git a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs new file mode 100644 index 000000000..9ea9fc71b --- /dev/null +++ b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs @@ -0,0 +1,15 @@ +#![crate_type="lib"] + +struct Nested(K); + +fn should_error() where T : Into<&u32> {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here [E0637] + +trait X<'a, K: 'a> { + fn foo<'b, L: X<&'b Nested>>(); + //~^ ERROR missing lifetime specifier [E0106] + //~| ERROR the type `&'b Nested` does not fulfill the required lifetime +} + +fn bar<'b, L: X<&'b Nested>>(){} +//~^ ERROR missing lifetime specifier [E0106] diff --git a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr new file mode 100644 index 000000000..9d859fddf --- /dev/null +++ b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -0,0 +1,57 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:37 + | +LL | fn should_error() where T : Into<&u32> {} + | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32 + | +LL | fn should_error() where T : Into<&u32> {} + | ^ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20 + | +LL | fn foo<'b, L: X<&'b Nested>>(); + | ^ expected named lifetime parameter + | +note: these named lifetimes are available to use + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:9 + | +LL | trait X<'a, K: 'a> { + | ^^ +LL | fn foo<'b, L: X<&'b Nested>>(); + | ^^ +help: consider using one of the available lifetimes here + | +LL | fn foo<'b, L: X<'lifetime, &'b Nested>>(); + | ++++++++++ + +error[E0106]: missing lifetime specifier + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:14:16 + | +LL | fn bar<'b, L: X<&'b Nested>>(){} + | ^ expected named lifetime parameter + | +help: consider using the `'b` lifetime + | +LL | fn bar<'b, L: X<'b, &'b Nested>>(){} + | +++ + +error[E0477]: the type `&'b Nested` does not fulfill the required lifetime + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19 + | +LL | fn foo<'b, L: X<&'b Nested>>(); + | ^^^^^^^^^^^^^^^^ + | +note: type must satisfy the static lifetime as required by this binding + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:16 + | +LL | trait X<'a, K: 'a> { + | ^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0106, E0477, E0637. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generics/issue-80512-param-reordering-with-defaults.rs b/tests/ui/generics/issue-80512-param-reordering-with-defaults.rs new file mode 100644 index 000000000..0e208818e --- /dev/null +++ b/tests/ui/generics/issue-80512-param-reordering-with-defaults.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +struct S(&'a T); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters diff --git a/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr b/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr new file mode 100644 index 000000000..70793a9c9 --- /dev/null +++ b/tests/ui/generics/issue-80512-param-reordering-with-defaults.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/issue-80512-param-reordering-with-defaults.rs:3:18 + | +LL | struct S(&'a T); + | ---------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T = ()>` + +error: aborting due to previous error + diff --git a/tests/ui/generics/issue-94432-garbage-ice.rs b/tests/ui/generics/issue-94432-garbage-ice.rs new file mode 100644 index 000000000..d0709e2d2 --- /dev/null +++ b/tests/ui/generics/issue-94432-garbage-ice.rs @@ -0,0 +1,10 @@ +// check-fail +// dont-check-compiler-stdout +// dont-check-compiler-stderr + +fn�a(){fn�p(){e}} //~ ERROR unknown start of token: \u{fffd} +//~^ ERROR unknown start of token: \u{fffd} +//~^^ ERROR can't use generic parameters from outer function [E0401] +//~^^^ WARN type parameter `e` should have an upper camel case name + +fn main(){} diff --git a/tests/ui/generics/issue-94923.rs b/tests/ui/generics/issue-94923.rs new file mode 100644 index 000000000..d337a5dff --- /dev/null +++ b/tests/ui/generics/issue-94923.rs @@ -0,0 +1,49 @@ +// run-pass +// regression test for issue #94923 +// min-llvm-version: 15.0.0 +// compile-flags: -C opt-level=3 + +fn f0(mut x: usize) -> usize { + for _ in 0..1000 { + x *= 123; + x %= 99 + } + x + 321 // function composition is not just longer iteration +} + +fn f1(x: usize) -> usize { + f0::<(i8, T)>(f0::<(u8, T)>(x)) +} + +fn f2(x: usize) -> usize { + f1::<(i8, T)>(f1::<(u8, T)>(x)) +} + +fn f3(x: usize) -> usize { + f2::<(i8, T)>(f2::<(u8, T)>(x)) +} + +fn f4(x: usize) -> usize { + f3::<(i8, T)>(f3::<(u8, T)>(x)) +} + +fn f5(x: usize) -> usize { + f4::<(i8, T)>(f4::<(u8, T)>(x)) +} + +fn f6(x: usize) -> usize { + f5::<(i8, T)>(f5::<(u8, T)>(x)) +} + +fn f7(x: usize) -> usize { + f6::<(i8, T)>(f6::<(u8, T)>(x)) +} + +fn f8(x: usize) -> usize { + f7::<(i8, T)>(f7::<(u8, T)>(x)) +} + +fn main() { + let y = f8::<()>(1); + assert_eq!(y, 348); +} diff --git a/tests/ui/generics/issue-95208-ignore-qself.fixed b/tests/ui/generics/issue-95208-ignore-qself.fixed new file mode 100644 index 000000000..608b4a20f --- /dev/null +++ b/tests/ui/generics/issue-95208-ignore-qself.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +#[allow(unused)] +struct Struct(T); + +impl Struct where ::Item: std::fmt::Display { +//~^ ERROR expected `:` followed by trait or lifetime +//~| HELP use single colon +} + +fn main() {} diff --git a/tests/ui/generics/issue-95208-ignore-qself.rs b/tests/ui/generics/issue-95208-ignore-qself.rs new file mode 100644 index 000000000..da7efd576 --- /dev/null +++ b/tests/ui/generics/issue-95208-ignore-qself.rs @@ -0,0 +1,11 @@ +// run-rustfix + +#[allow(unused)] +struct Struct(T); + +impl Struct where ::Item:: std::fmt::Display { +//~^ ERROR expected `:` followed by trait or lifetime +//~| HELP use single colon +} + +fn main() {} diff --git a/tests/ui/generics/issue-95208-ignore-qself.stderr b/tests/ui/generics/issue-95208-ignore-qself.stderr new file mode 100644 index 000000000..acbc1300d --- /dev/null +++ b/tests/ui/generics/issue-95208-ignore-qself.stderr @@ -0,0 +1,10 @@ +error: expected `:` followed by trait or lifetime + --> $DIR/issue-95208-ignore-qself.rs:6:88 + | +LL | impl Struct where ::Item:: std::fmt::Display { + | --- ^ + | | + | help: use single colon: `:` + +error: aborting due to previous error + diff --git a/tests/ui/generics/issue-95208.fixed b/tests/ui/generics/issue-95208.fixed new file mode 100644 index 000000000..a0b1e886c --- /dev/null +++ b/tests/ui/generics/issue-95208.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +#[allow(unused)] +struct Struct(T); + +impl Struct where T: std::fmt::Display { +//~^ ERROR expected `:` followed by trait or lifetime +//~| HELP use single colon +} + +fn main() {} diff --git a/tests/ui/generics/issue-95208.rs b/tests/ui/generics/issue-95208.rs new file mode 100644 index 000000000..0e3083484 --- /dev/null +++ b/tests/ui/generics/issue-95208.rs @@ -0,0 +1,11 @@ +// run-rustfix + +#[allow(unused)] +struct Struct(T); + +impl Struct where T:: std::fmt::Display { +//~^ ERROR expected `:` followed by trait or lifetime +//~| HELP use single colon +} + +fn main() {} diff --git a/tests/ui/generics/issue-95208.stderr b/tests/ui/generics/issue-95208.stderr new file mode 100644 index 000000000..559527663 --- /dev/null +++ b/tests/ui/generics/issue-95208.stderr @@ -0,0 +1,10 @@ +error: expected `:` followed by trait or lifetime + --> $DIR/issue-95208.rs:6:46 + | +LL | impl Struct where T:: std::fmt::Display { + | --- ^ + | | + | help: use single colon: `:` + +error: aborting due to previous error + diff --git a/tests/ui/generics/issue-98432.rs b/tests/ui/generics/issue-98432.rs new file mode 100644 index 000000000..780c50d6f --- /dev/null +++ b/tests/ui/generics/issue-98432.rs @@ -0,0 +1,9 @@ +struct Struct(T); + +impl Struct { + const CONST: fn() = || { + struct _Obligation where T:; //~ ERROR can't use generic parameters from outer function + }; +} + +fn main() {} diff --git a/tests/ui/generics/issue-98432.stderr b/tests/ui/generics/issue-98432.stderr new file mode 100644 index 000000000..c7b5c3361 --- /dev/null +++ b/tests/ui/generics/issue-98432.stderr @@ -0,0 +1,14 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-98432.rs:5:34 + | +LL | impl Struct { + | - type parameter from outer function +LL | const CONST: fn() = || { +LL | struct _Obligation where T:; + | - ^ use of generic parameter from outer function + | | + | help: try using a local generic parameter instead: `` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/generics/lifetime-before-type-params.rs b/tests/ui/generics/lifetime-before-type-params.rs new file mode 100644 index 000000000..d64b1b0b4 --- /dev/null +++ b/tests/ui/generics/lifetime-before-type-params.rs @@ -0,0 +1,11 @@ +#![allow(unused)] +fn first() {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters +fn second<'a, T, 'b>() {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters +fn third() {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters +fn fourth<'a, T, 'b, U, 'c, V>() {} +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +fn main() {} diff --git a/tests/ui/generics/lifetime-before-type-params.stderr b/tests/ui/generics/lifetime-before-type-params.stderr new file mode 100644 index 000000000..84825eb4c --- /dev/null +++ b/tests/ui/generics/lifetime-before-type-params.stderr @@ -0,0 +1,26 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/lifetime-before-type-params.rs:2:13 + | +LL | fn first() {} + | ----^^--^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/lifetime-before-type-params.rs:4:18 + | +LL | fn second<'a, T, 'b>() {} + | --------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, T>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/lifetime-before-type-params.rs:6:16 + | +LL | fn third() {} + | -------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T, U>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/lifetime-before-type-params.rs:8:18 + | +LL | fn fourth<'a, T, 'b, U, 'c, V>() {} + | --------^^-----^^---- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, 'c, T, U, V>` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/generics/mid-path-type-params.rs b/tests/ui/generics/mid-path-type-params.rs new file mode 100644 index 000000000..a8128207c --- /dev/null +++ b/tests/ui/generics/mid-path-type-params.rs @@ -0,0 +1,37 @@ +// run-pass + +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct S { + contents: T, +} + +impl S { + fn new(x: T, _: U) -> S { + S { + contents: x, + } + } +} + +trait Trait { + fn new(x: T, y: U) -> Self; +} + +struct S2 { + contents: isize, +} + +impl Trait for S2 { + fn new(x: isize, _: U) -> S2 { + S2 { + contents: x, + } + } +} + +pub fn main() { + let _ = S::::new::(1, 1.0); + let _: S2 = Trait::::new::(1, 1.0); +} diff --git a/tests/ui/generics/param-in-ct-in-ty-param-default.rs b/tests/ui/generics/param-in-ct-in-ty-param-default.rs new file mode 100644 index 000000000..3c62e4738 --- /dev/null +++ b/tests/ui/generics/param-in-ct-in-ty-param-default.rs @@ -0,0 +1,4 @@ +struct Foo()]>(T, U); +//~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/generics/param-in-ct-in-ty-param-default.stderr b/tests/ui/generics/param-in-ct-in-ty-param-default.stderr new file mode 100644 index 000000000..ab09ebcae --- /dev/null +++ b/tests/ui/generics/param-in-ct-in-ty-param-default.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/param-in-ct-in-ty-param-default.rs:1:44 + | +LL | struct Foo()]>(T, U); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.rs b/tests/ui/generics/post_monomorphization_error_backtrace.rs new file mode 100644 index 000000000..1fd9b6b3b --- /dev/null +++ b/tests/ui/generics/post_monomorphization_error_backtrace.rs @@ -0,0 +1,33 @@ +// build-fail + +fn assert_zst() { + struct F(T); + impl F { + const V: () = assert!(std::mem::size_of::() == 0); + //~^ ERROR: evaluation of `assert_zst::F::::V` failed [E0080] + //~| NOTE: in this expansion of assert! + //~| NOTE: the evaluated program panicked + //~| ERROR: evaluation of `assert_zst::F::::V` failed [E0080] + //~| NOTE: in this expansion of assert! + //~| NOTE: the evaluated program panicked + } + let _ = F::::V; +} + +fn foo() { + assert_zst::() + //~^ NOTE: the above error was encountered while instantiating `fn assert_zst::` + //~| NOTE: the above error was encountered while instantiating `fn assert_zst::` +} + + +fn bar() { + foo::() +} + +fn main() { + bar::<()>(); + bar::(); + bar::(); + bar::(); +} diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.stderr b/tests/ui/generics/post_monomorphization_error_backtrace.stderr new file mode 100644 index 000000000..0d707d83d --- /dev/null +++ b/tests/ui/generics/post_monomorphization_error_backtrace.stderr @@ -0,0 +1,31 @@ +error[E0080]: evaluation of `assert_zst::F::::V` failed + --> $DIR/post_monomorphization_error_backtrace.rs:6:23 + | +LL | const V: () = assert!(std::mem::size_of::() == 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/post_monomorphization_error_backtrace.rs:6:23 + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: the above error was encountered while instantiating `fn assert_zst::` + --> $DIR/post_monomorphization_error_backtrace.rs:18:5 + | +LL | assert_zst::() + | ^^^^^^^^^^^^^^^^^ + +error[E0080]: evaluation of `assert_zst::F::::V` failed + --> $DIR/post_monomorphization_error_backtrace.rs:6:23 + | +LL | const V: () = assert!(std::mem::size_of::() == 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/post_monomorphization_error_backtrace.rs:6:23 + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: the above error was encountered while instantiating `fn assert_zst::` + --> $DIR/post_monomorphization_error_backtrace.rs:18:5 + | +LL | assert_zst::() + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/generics/single-colon-path-not-const-generics.rs b/tests/ui/generics/single-colon-path-not-const-generics.rs new file mode 100644 index 000000000..55a7ae0bb --- /dev/null +++ b/tests/ui/generics/single-colon-path-not-const-generics.rs @@ -0,0 +1,13 @@ +pub mod foo { + pub mod bar { + pub struct A; + } +} + +pub struct Foo { + a: Vec, + //~^ ERROR expected + //~| HELP path separator +} + +fn main() {} diff --git a/tests/ui/generics/single-colon-path-not-const-generics.stderr b/tests/ui/generics/single-colon-path-not-const-generics.stderr new file mode 100644 index 000000000..3eafa9fa5 --- /dev/null +++ b/tests/ui/generics/single-colon-path-not-const-generics.stderr @@ -0,0 +1,11 @@ +error: expected one of `,` or `>`, found `:` + --> $DIR/single-colon-path-not-const-generics.rs:8:18 + | +LL | a: Vec, + | ^ + | | + | expected one of `,` or `>` + | help: write a path separator here: `::` + +error: aborting due to previous error + diff --git a/tests/ui/generics/type-params-in-for-each.rs b/tests/ui/generics/type-params-in-for-each.rs new file mode 100644 index 000000000..53475d280 --- /dev/null +++ b/tests/ui/generics/type-params-in-for-each.rs @@ -0,0 +1,23 @@ +// run-pass + +#![allow(dead_code)] + +// pretty-expanded FIXME #23616 + +struct S { + a: T, + b: usize, +} + +fn range_(lo: usize, hi: usize, mut it: F) where F: FnMut(usize) { + let mut lo_ = lo; + while lo_ < hi { it(lo_); lo_ += 1; } +} + +fn create_index(_index: Vec> , _hash_fn: extern "C" fn(T) -> usize) { + range_(0, 256, |_i| { + let _bucket: Vec = Vec::new(); + }) +} + +pub fn main() { } diff --git a/tests/ui/generics/wrong-number-of-args.rs b/tests/ui/generics/wrong-number-of-args.rs new file mode 100644 index 000000000..cd2f96a18 --- /dev/null +++ b/tests/ui/generics/wrong-number-of-args.rs @@ -0,0 +1,358 @@ +mod no_generics { + struct Ty; + + type A = Ty; + + type B = Ty<'static>; + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument + //~| HELP remove these generics + + type C = Ty<'static, usize>; + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument + //~| ERROR this struct takes 0 generic arguments but 1 generic argument + //~| HELP remove this lifetime argument + //~| HELP remove this generic argument + + type D = Ty<'static, usize, { 0 }>; + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument + //~| ERROR this struct takes 0 generic arguments but 2 generic arguments + //~| HELP remove this lifetime argument + //~| HELP remove these generic arguments +} + +mod type_and_type { + struct Ty; + + type A = Ty; + //~^ ERROR missing generics for struct `type_and_type::Ty` + //~| HELP add missing + + type B = Ty; + //~^ ERROR this struct takes 2 generic arguments but 1 generic argument + //~| HELP add missing + + type C = Ty; + + type D = Ty; + //~^ ERROR this struct takes 2 generic arguments but 3 generic arguments + //~| HELP remove this + + type E = Ty<>; + //~^ ERROR this struct takes 2 generic arguments but 0 generic arguments were supplied + //~| HELP add missing +} + +mod lifetime_and_type { + struct Ty<'a, T>; + + type A = Ty; + //~^ ERROR missing generics for struct + //~| ERROR missing lifetime specifier + //~| HELP add missing + //~| HELP consider introducing + + type B = Ty<'static>; + //~^ ERROR this struct takes 1 generic argument but 0 generic arguments + //~| HELP add missing + + type C = Ty; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + + type D = Ty<'static, usize>; + + type E = Ty<>; + //~^ ERROR this struct takes 1 generic argument but 0 generic arguments + //~| ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP add missing + + type F = Ty<'static, usize, 'static, usize>; + //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments + //~| ERROR this struct takes 1 generic argument but 2 generic arguments + //~| HELP remove this lifetime argument + //~| HELP remove this generic argument +} + +mod type_and_type_and_type { + struct Ty; + + type A = Ty; + //~^ ERROR missing generics for struct `type_and_type_and_type::Ty` + //~| HELP add missing + + type B = Ty; + //~^ ERROR this struct takes at least 2 + //~| HELP add missing + + type C = Ty; + + type D = Ty; + + type E = Ty; + //~^ ERROR this struct takes at most 3 + //~| HELP remove + + type F = Ty<>; + //~^ ERROR this struct takes at least 2 generic arguments but 0 generic arguments + //~| HELP add missing +} + +// Traits have an implicit `Self` type - these tests ensure we don't accidentally return it +// somewhere in the message +mod r#trait { + trait NonGeneric { + // + } + + trait GenericLifetime<'a> { + // + } + + trait GenericType { + // + } + + type A = Box>; + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + //~| HELP remove + + type B = Box; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + + type C = Box>; + //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| HELP remove + + type D = Box; + //~^ ERROR missing generics for trait `GenericType` + //~| HELP add missing + + type E = Box>; + //~^ ERROR this trait takes 1 generic argument but 2 generic arguments + //~| HELP remove + + type F = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + + type G = Box>; + //~^ ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing +} + +mod associated_item { + mod non_generic { + trait NonGenericAT { + type AssocTy; + } + + type A = Box>; + //~^ ERROR this trait takes 0 generic arguments but 1 generic argument + //~| HELP remove + } + + mod lifetime { + trait GenericLifetimeAT<'a> { + type AssocTy; + } + + type A = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + + type B = Box>; + //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| HELP remove + + type C = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + //~| ERROR this trait takes 0 generic arguments but 1 generic argument + //~| HELP remove + } + + mod r#type { + trait GenericTypeAT { + type AssocTy; + } + + type A = Box>; + //~^ ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing + + type B = Box>; + //~^ ERROR this trait takes 1 generic argument but 2 generic arguments + //~| HELP remove + + type C = Box>; + //~^ ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing + //~| ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + //~| HELP remove + } + + mod lifetime_and_type { + trait GenericLifetimeTypeAT<'a, A> { + type AssocTy; + } + + type A = Box>; + //~^ ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing + //~| ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + + type B = Box>; + //~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied + //~| HELP add missing + + type C = Box>; + //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| HELP remove + //~| ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing + + type D = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + + type E = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + //~| ERROR this trait takes 1 generic argument but 2 generic arguments + //~| HELP remove + + type F = Box>; + //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| HELP remove + + type G = Box>; + //~^ ERROR this trait takes 1 generic argument but 2 generic arguments + //~| HELP remove + + type H = Box>; + //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + //~| HELP remove + //~| ERROR this trait takes 1 generic argument but 2 generic arguments + //~| HELP remove + } + + mod type_and_type { + trait GenericTypeTypeAT { + type AssocTy; + } + + type A = Box>; + //~^ ERROR this trait takes 2 generic arguments but 0 generic arguments + //~| HELP add missing + + type B = Box>; + //~^ ERROR this trait takes 2 generic arguments but 1 generic argument + //~| HELP add missing + + type C = Box>; + //~^ ERROR this trait takes 2 generic arguments but 3 generic arguments + //~| HELP remove + } + + mod lifetime_and_lifetime { + trait GenericLifetimeLifetimeAT<'a, 'b> { + type AssocTy; + } + + type A = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + + type B = Box>; + //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| HELP add missing lifetime argument + } + + mod lifetime_and_lifetime_and_type { + trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { + type AssocTy; + } + + type A = Box>; + //~^ ERROR missing lifetime specifier + //~| HELP consider introducing + //~| HELP consider making the bound lifetime-generic + //~| ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing + + type B = Box>; + //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| HELP add missing lifetime argument + //~| ERROR this trait takes 1 generic argument but 0 generic arguments + //~| HELP add missing + + type C = Box>; + //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| HELP add missing lifetime argument + } +} + +mod stdlib { + mod hash_map { + use std::collections::HashMap; + + type A = HashMap; + //~^ ERROR missing generics for struct `HashMap` + //~| HELP add missing + + type B = HashMap; + //~^ ERROR this struct takes at least + //~| HELP add missing + + type C = HashMap<'static>; + //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument + //~| HELP remove these generics + //~| ERROR this struct takes at least 2 + //~| HELP add missing + + type D = HashMap; + //~^ ERROR this struct takes at most 3 + //~| HELP remove this + + type E = HashMap<>; + //~^ ERROR this struct takes at least 2 generic arguments but 0 generic arguments + //~| HELP add missing + } + + mod result { + type A = Result; + //~^ ERROR missing generics for enum `Result` + //~| HELP add missing + + type B = Result; + //~^ ERROR this enum takes 2 generic arguments but 1 generic argument + //~| HELP add missing + + type C = Result<'static>; + //~^ ERROR this enum takes 0 lifetime arguments but 1 lifetime argument + //~| HELP remove these generics + //~| ERROR this enum takes 2 generic arguments but 0 generic arguments + //~| HELP add missing + + type D = Result; + //~^ ERROR this enum takes 2 generic arguments but 3 generic arguments + //~| HELP remove + + type E = Result<>; + //~^ ERROR this enum takes 2 generic arguments but 0 generic arguments + //~| HELP add missing + } +} + +fn main() { } diff --git a/tests/ui/generics/wrong-number-of-args.stderr b/tests/ui/generics/wrong-number-of-args.stderr new file mode 100644 index 000000000..75e33f680 --- /dev/null +++ b/tests/ui/generics/wrong-number-of-args.stderr @@ -0,0 +1,1013 @@ +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:48:14 + | +LL | type A = Ty; + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Ty<'a>; + | ++++ ++++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:58:16 + | +LL | type C = Ty; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Ty<'a, usize>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:64:16 + | +LL | type E = Ty<>; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type E<'a> = Ty<'a, >; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:120:22 + | +LL | type B = Box; + | ^^^^^^^^^^^^^^^ expected named lifetime parameter + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type B = Box GenericLifetime<'a>>; + | +++++++ ++++ +help: consider introducing a named lifetime parameter + | +LL | type B<'a> = Box>; + | ++++ ++++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:137:37 + | +LL | type F = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type F = Box GenericLifetime<'a, >>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type F<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:163:43 + | +LL | type A = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeAT<'a, AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:172:43 + | +LL | type C = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type C = Box GenericLifetimeAT<'a, (), AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type C<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:205:47 + | +LL | type A = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeTypeAT<'a, AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:222:47 + | +LL | type D = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type D = Box GenericLifetimeTypeAT<'a, (), AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type D<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifier + --> $DIR/wrong-number-of-args.rs:227:47 + | +LL | type E = Box>; + | ^ expected named lifetime parameter + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type E = Box GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>; + | +++++++ +++ +help: consider introducing a named lifetime parameter + | +LL | type E<'a> = Box>; + | ++++ +++ + +error[E0106]: missing lifetime specifiers + --> $DIR/wrong-number-of-args.rs:272:51 + | +LL | type A = Box>; + | ^ expected 2 lifetime parameters + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeLifetimeAT<'a, 'a, AssocTy=()>>; + | +++++++ +++++++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++++++ + +error[E0106]: missing lifetime specifiers + --> $DIR/wrong-number-of-args.rs:287:55 + | +LL | type A = Box>; + | ^ expected 2 lifetime parameters + | +help: consider making the bound lifetime-generic with a new `'a` lifetime + | +LL | type A = Box GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>; + | +++++++ +++++++ +help: consider introducing a named lifetime parameter + | +LL | type A<'a> = Box>; + | ++++ +++++++ + +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:6:14 + | +LL | type B = Ty<'static>; + | ^^--------- help: remove these generics + | | + | expected 0 lifetime arguments + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/wrong-number-of-args.rs:2:12 + | +LL | struct Ty; + | ^^ + +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:10:14 + | +LL | type C = Ty<'static, usize>; + | ^^ ------- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/wrong-number-of-args.rs:2:12 + | +LL | struct Ty; + | ^^ + +error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:10:14 + | +LL | type C = Ty<'static, usize>; + | ^^ ----- help: remove this generic argument + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/wrong-number-of-args.rs:2:12 + | +LL | struct Ty; + | ^^ + +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:16:14 + | +LL | type D = Ty<'static, usize, { 0 }>; + | ^^ ------- help: remove this lifetime argument + | | + | expected 0 lifetime arguments + | +note: struct defined here, with 0 lifetime parameters + --> $DIR/wrong-number-of-args.rs:2:12 + | +LL | struct Ty; + | ^^ + +error[E0107]: this struct takes 0 generic arguments but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:16:14 + | +LL | type D = Ty<'static, usize, { 0 }>; + | ^^ ------------ help: remove these generic arguments + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/wrong-number-of-args.rs:2:12 + | +LL | struct Ty; + | ^^ + +error[E0107]: missing generics for struct `type_and_type::Ty` + --> $DIR/wrong-number-of-args.rs:26:14 + | +LL | type A = Ty; + | ^^ expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:24:12 + | +LL | struct Ty; + | ^^ - - +help: add missing generic arguments + | +LL | type A = Ty; + | ++++++ + +error[E0107]: this struct takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:30:14 + | +LL | type B = Ty; + | ^^ ----- supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:24:12 + | +LL | struct Ty; + | ^^ - - +help: add missing generic argument + | +LL | type B = Ty; + | +++ + +error[E0107]: this struct takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:36:14 + | +LL | type D = Ty; + | ^^ ---- help: remove this generic argument + | | + | expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:24:12 + | +LL | struct Ty; + | ^^ - - + +error[E0107]: this struct takes 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:40:14 + | +LL | type E = Ty<>; + | ^^ expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:24:12 + | +LL | struct Ty; + | ^^ - - +help: add missing generic arguments + | +LL | type E = Ty; + | ++++ + +error[E0107]: missing generics for struct `lifetime_and_type::Ty` + --> $DIR/wrong-number-of-args.rs:48:14 + | +LL | type A = Ty; + | ^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/wrong-number-of-args.rs:46:12 + | +LL | struct Ty<'a, T>; + | ^^ - +help: add missing generic argument + | +LL | type A = Ty; + | +++ + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:54:14 + | +LL | type B = Ty<'static>; + | ^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/wrong-number-of-args.rs:46:12 + | +LL | struct Ty<'a, T>; + | ^^ - +help: add missing generic argument + | +LL | type B = Ty<'static, T>; + | +++ + +error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:64:14 + | +LL | type E = Ty<>; + | ^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/wrong-number-of-args.rs:46:12 + | +LL | struct Ty<'a, T>; + | ^^ - +help: add missing generic argument + | +LL | type E = Ty; + | + + +error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/wrong-number-of-args.rs:70:14 + | +LL | type F = Ty<'static, usize, 'static, usize>; + | ^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: struct defined here, with 1 lifetime parameter: `'a` + --> $DIR/wrong-number-of-args.rs:46:12 + | +LL | struct Ty<'a, T>; + | ^^ -- + +error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:70:14 + | +LL | type F = Ty<'static, usize, 'static, usize>; + | ^^ ----- help: remove this generic argument + | | + | expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/wrong-number-of-args.rs:46:12 + | +LL | struct Ty<'a, T>; + | ^^ - + +error[E0107]: missing generics for struct `type_and_type_and_type::Ty` + --> $DIR/wrong-number-of-args.rs:80:14 + | +LL | type A = Ty; + | ^^ expected at least 2 generic arguments + | +note: struct defined here, with at least 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:78:12 + | +LL | struct Ty; + | ^^ - - +help: add missing generic arguments + | +LL | type A = Ty; + | ++++++ + +error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:84:14 + | +LL | type B = Ty; + | ^^ ----- supplied 1 generic argument + | | + | expected at least 2 generic arguments + | +note: struct defined here, with at least 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:78:12 + | +LL | struct Ty; + | ^^ - - +help: add missing generic argument + | +LL | type B = Ty; + | +++ + +error[E0107]: this struct takes at most 3 generic arguments but 4 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:92:14 + | +LL | type E = Ty; + | ^^ --- help: remove this generic argument + | | + | expected at most 3 generic arguments + | +note: struct defined here, with at most 3 generic parameters: `A`, `B`, `C` + --> $DIR/wrong-number-of-args.rs:78:12 + | +LL | struct Ty; + | ^^ - - ---------------- + +error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:96:14 + | +LL | type F = Ty<>; + | ^^ expected at least 2 generic arguments + | +note: struct defined here, with at least 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:78:12 + | +LL | struct Ty; + | ^^ - - +help: add missing generic arguments + | +LL | type F = Ty; + | ++++ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:116:22 + | +LL | type A = Box>; + | ^^^^^^^^^^------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/wrong-number-of-args.rs:104:11 + | +LL | trait NonGeneric { + | ^^^^^^^^^^ + +error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/wrong-number-of-args.rs:125:22 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: trait defined here, with 1 lifetime parameter: `'a` + --> $DIR/wrong-number-of-args.rs:108:11 + | +LL | trait GenericLifetime<'a> { + | ^^^^^^^^^^^^^^^ -- + +error[E0107]: missing generics for trait `GenericType` + --> $DIR/wrong-number-of-args.rs:129:22 + | +LL | type D = Box; + | ^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:112:11 + | +LL | trait GenericType { + | ^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type D = Box>; + | +++ + +error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:133:22 + | +LL | type E = Box>; + | ^^^^^^^^^^^ ----- help: remove this generic argument + | | + | expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:112:11 + | +LL | trait GenericType { + | ^^^^^^^^^^^ - + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:142:22 + | +LL | type G = Box>; + | ^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:112:11 + | +LL | trait GenericType { + | ^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type G = Box>; + | + + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:153:26 + | +LL | type A = Box>; + | ^^^^^^^^^^^^------------------- help: remove these generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/wrong-number-of-args.rs:149:15 + | +LL | trait NonGenericAT { + | ^^^^^^^^^^^^ + +error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/wrong-number-of-args.rs:168:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: trait defined here, with 1 lifetime parameter: `'a` + --> $DIR/wrong-number-of-args.rs:159:15 + | +LL | trait GenericLifetimeAT<'a> { + | ^^^^^^^^^^^^^^^^^ -- + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:172:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^^^^^ -- help: remove this generic argument + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/wrong-number-of-args.rs:159:15 + | +LL | trait GenericLifetimeAT<'a> { + | ^^^^^^^^^^^^^^^^^ + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:185:26 + | +LL | type A = Box>; + | ^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:181:15 + | +LL | trait GenericTypeAT { + | ^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type A = Box>; + | ++ + +error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:189:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^ -- help: remove this generic argument + | | + | expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:181:15 + | +LL | trait GenericTypeAT { + | ^^^^^^^^^^^^^ - + +error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:193:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^--------------------- help: remove these generics + | | + | expected 0 lifetime arguments + | +note: trait defined here, with 0 lifetime parameters + --> $DIR/wrong-number-of-args.rs:181:15 + | +LL | trait GenericTypeAT { + | ^^^^^^^^^^^^^ + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:193:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:181:15 + | +LL | trait GenericTypeAT { + | ^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type C = Box>; + | +++ + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:205:26 + | +LL | type A = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type A = Box>; + | ++ + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:212:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type B = Box>; + | +++ + +error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/wrong-number-of-args.rs:216:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: trait defined here, with 1 lifetime parameter: `'a` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ -- + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:216:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type C = Box>; + | +++ + +error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:227:26 + | +LL | type E = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ -- help: remove this generic argument + | | + | expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ - + +error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/wrong-number-of-args.rs:234:26 + | +LL | type F = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: trait defined here, with 1 lifetime parameter: `'a` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ -- + +error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:238:26 + | +LL | type G = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ -- help: remove this generic argument + | | + | expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ - + +error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied + --> $DIR/wrong-number-of-args.rs:242:26 + | +LL | type H = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ ------- help: remove this lifetime argument + | | + | expected 1 lifetime argument + | +note: trait defined here, with 1 lifetime parameter: `'a` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ -- + +error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:242:26 + | +LL | type H = Box>; + | ^^^^^^^^^^^^^^^^^^^^^ -- help: remove this generic argument + | | + | expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:201:15 + | +LL | trait GenericLifetimeTypeAT<'a, A> { + | ^^^^^^^^^^^^^^^^^^^^^ - + +error[E0107]: this trait takes 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:254:26 + | +LL | type A = Box>; + | ^^^^^^^^^^^^^^^^^ expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:250:15 + | +LL | trait GenericTypeTypeAT { + | ^^^^^^^^^^^^^^^^^ - - +help: add missing generic arguments + | +LL | type A = Box>; + | +++++ + +error[E0107]: this trait takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:258:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^^^^^ -- supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:250:15 + | +LL | trait GenericTypeTypeAT { + | ^^^^^^^^^^^^^^^^^ - - +help: add missing generic argument + | +LL | type B = Box>; + | +++ + +error[E0107]: this trait takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:262:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^^^^^ -- help: remove this generic argument + | | + | expected 2 generic arguments + | +note: trait defined here, with 2 generic parameters: `A`, `B` + --> $DIR/wrong-number-of-args.rs:250:15 + | +LL | trait GenericTypeTypeAT { + | ^^^^^^^^^^^^^^^^^ - - + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:277:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/wrong-number-of-args.rs:268:15 + | +LL | trait GenericLifetimeLifetimeAT<'a, 'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- +help: add missing lifetime argument + | +LL | type B = Box>; + | +++++++++ + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:287:26 + | +LL | type A = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:283:15 + | +LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type A = Box>; + | ++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:294:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/wrong-number-of-args.rs:283:15 + | +LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- +help: add missing lifetime argument + | +LL | type B = Box>; + | +++++++++ + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:294:26 + | +LL | type B = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `A` + --> $DIR/wrong-number-of-args.rs:283:15 + | +LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - +help: add missing generic argument + | +LL | type B = Box>; + | +++ + +error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:300:26 + | +LL | type C = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- supplied 1 lifetime argument + | | + | expected 2 lifetime arguments + | +note: trait defined here, with 2 lifetime parameters: `'a`, `'b` + --> $DIR/wrong-number-of-args.rs:283:15 + | +LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- +help: add missing lifetime argument + | +LL | type C = Box>; + | +++++++++ + +error[E0107]: missing generics for struct `HashMap` + --> $DIR/wrong-number-of-args.rs:310:18 + | +LL | type A = HashMap; + | ^^^^^^^ expected at least 2 generic arguments + | +help: add missing generic arguments + | +LL | type A = HashMap; + | ++++++ + +error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:314:18 + | +LL | type B = HashMap; + | ^^^^^^^ ------ supplied 1 generic argument + | | + | expected at least 2 generic arguments + | +help: add missing generic argument + | +LL | type B = HashMap; + | +++ + +error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:318:18 + | +LL | type C = HashMap<'static>; + | ^^^^^^^--------- help: remove these generics + | | + | expected 0 lifetime arguments + +error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:318:18 + | +LL | type C = HashMap<'static>; + | ^^^^^^^ expected at least 2 generic arguments + | +help: add missing generic arguments + | +LL | type C = HashMap<'static, K, V>; + | ++++++ + +error[E0107]: this struct takes at most 3 generic arguments but 4 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:324:18 + | +LL | type D = HashMap; + | ^^^^^^^ --- help: remove this generic argument + | | + | expected at most 3 generic arguments + +error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:328:18 + | +LL | type E = HashMap<>; + | ^^^^^^^ expected at least 2 generic arguments + | +help: add missing generic arguments + | +LL | type E = HashMap; + | ++++ + +error[E0107]: missing generics for enum `Result` + --> $DIR/wrong-number-of-args.rs:334:18 + | +LL | type A = Result; + | ^^^^^^ expected 2 generic arguments + | +help: add missing generic arguments + | +LL | type A = Result; + | ++++++ + +error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/wrong-number-of-args.rs:338:18 + | +LL | type B = Result; + | ^^^^^^ ------ supplied 1 generic argument + | | + | expected 2 generic arguments + | +help: add missing generic argument + | +LL | type B = Result; + | +++ + +error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied + --> $DIR/wrong-number-of-args.rs:342:18 + | +LL | type C = Result<'static>; + | ^^^^^^--------- help: remove these generics + | | + | expected 0 lifetime arguments + +error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:342:18 + | +LL | type C = Result<'static>; + | ^^^^^^ expected 2 generic arguments + | +help: add missing generic arguments + | +LL | type C = Result<'static, T, E>; + | ++++++ + +error[E0107]: this enum takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:348:18 + | +LL | type D = Result; + | ^^^^^^ ---- help: remove this generic argument + | | + | expected 2 generic arguments + +error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied + --> $DIR/wrong-number-of-args.rs:352:18 + | +LL | type E = Result<>; + | ^^^^^^ expected 2 generic arguments + | +help: add missing generic arguments + | +LL | type E = Result; + | ++++ + +error: aborting due to 71 previous errors + +Some errors have detailed explanations: E0106, E0107. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/global-scope.rs b/tests/ui/global-scope.rs new file mode 100644 index 000000000..944eee5af --- /dev/null +++ b/tests/ui/global-scope.rs @@ -0,0 +1,13 @@ +// run-pass + +pub fn f() -> isize { return 1; } + +pub mod foo { + pub fn f() -> isize { return 2; } + pub fn g() { + assert_eq!(f(), 2); + assert_eq!(::f(), 1); + } +} + +pub fn main() { return foo::g(); } diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs new file mode 100644 index 000000000..b2e9ffb57 --- /dev/null +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs @@ -0,0 +1,10 @@ +#![feature(half_open_range_patterns_in_slices)] +#![feature(exclusive_range_pattern)] + +fn main() { + match [5..4, 99..105, 43..44] { + [_, 99.., _] => {}, + //~^ ERROR mismatched types + _ => {}, + } +} diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr new file mode 100644 index 000000000..095a1c6af --- /dev/null +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` +LL | [_, 99.., _] => {}, + | ^^ expected struct `Range`, found integer + | + = note: expected struct `std::ops::Range<{integer}>` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs new file mode 100644 index 000000000..20f4d8f88 --- /dev/null +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs @@ -0,0 +1,11 @@ +#![feature(half_open_range_patterns_in_slices)] +#![feature(exclusive_range_pattern)] + +fn main() { + match [5..4, 99..105, 43..44] { + [_, 99..] => {}, + //~^ ERROR pattern requires 2 elements but array has 3 + //~| ERROR mismatched types + _ => {}, + } +} diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr new file mode 100644 index 000000000..2ea3205dc --- /dev/null +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr @@ -0,0 +1,21 @@ +error[E0527]: pattern requires 2 elements but array has 3 + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:9 + | +LL | [_, 99..] => {}, + | ^^^^^^^^^ expected 3 elements + +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` +LL | [_, 99..] => {}, + | ^^ expected struct `Range`, found integer + | + = note: expected struct `std::ops::Range<{integer}>` + found type `{integer}` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0527. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs new file mode 100644 index 000000000..14ca07d0a --- /dev/null +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs @@ -0,0 +1,11 @@ +#![feature(exclusive_range_pattern)] + +fn main() { + match [5..4, 99..105, 43..44] { + [..9, 99..100, _] => {}, + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + _ => {}, + } +} diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr new file mode 100644 index 000000000..bbdf0c83f --- /dev/null +++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr @@ -0,0 +1,40 @@ +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` +LL | [..9, 99..100, _] => {}, + | ^ expected struct `Range`, found integer + | + = note: expected struct `std::ops::Range<{integer}>` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` +LL | [..9, 99..100, _] => {}, + | ^^ --- this is of type `{integer}` + | | + | expected struct `Range`, found integer + | + = note: expected struct `std::ops::Range<{integer}>` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19 + | +LL | match [5..4, 99..105, 43..44] { + | ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]` +LL | [..9, 99..100, _] => {}, + | -- ^^^ expected struct `Range`, found integer + | | + | this is of type `{integer}` + | + = note: expected struct `std::ops::Range<{integer}>` + found type `{integer}` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs new file mode 100644 index 000000000..dac973473 --- /dev/null +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs @@ -0,0 +1,7 @@ +#![feature(exclusive_range_pattern)] + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + //~^ `X..` patterns in slices are experimental +} diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr new file mode 100644 index 000000000..ee5b0e11c --- /dev/null +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr @@ -0,0 +1,12 @@ +error[E0658]: `X..` patterns in slices are experimental + --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:10 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs new file mode 100644 index 000000000..17ea2b13f --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs @@ -0,0 +1,7 @@ +#![feature(exclusive_range_pattern)] + +fn main() { + let "a".. = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns + let .."a" = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns + let ..="a" = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr new file mode 100644 index 000000000..f7c59a196 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr @@ -0,0 +1,21 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/half-open-range-pats-bad-types.rs:4:9 + | +LL | let "a".. = "a"; + | ^^^ this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/half-open-range-pats-bad-types.rs:5:11 + | +LL | let .."a" = "a"; + | ^^^ this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/half-open-range-pats-bad-types.rs:6:12 + | +LL | let ..="a" = "a"; + | ^^^ this is of type `&'static str` but it should be `char` or numeric + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs new file mode 100644 index 000000000..a2a4c62fa --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs @@ -0,0 +1,167 @@ +// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges. + +#![feature(exclusive_range_pattern)] +#![allow(illegal_floating_point_literal_pattern)] + +fn main() {} + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +fn floats() { + m!(0f32, f32::NEG_INFINITY..); //~ ERROR non-exhaustive patterns: `_` not covered + m!(0f32, ..f32::INFINITY); //~ ERROR non-exhaustive patterns: `_` not covered +} + +fn khar() { + const ALMOST_MAX: char = '\u{10fffe}'; + const ALMOST_MIN: char = '\u{1}'; + const VAL: char = 'a'; + const VAL_1: char = 'b'; + const VAL_2: char = 'c'; + m!('a', ..core::char::MAX); //~ ERROR non-exhaustive patterns + m!('a', ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!('a', ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!('a', ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!('a', ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!('a', ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns +} + +mod unsigned { + fn u8() { + const ALMOST_MAX: u8 = u8::MAX - 1; + const ALMOST_MIN: u8 = u8::MIN + 1; + const VAL: u8 = 42; + const VAL_1: u8 = VAL + 1; + const VAL_2: u8 = VAL + 2; + m!(0, ..u8::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u16() { + const ALMOST_MAX: u16 = u16::MAX - 1; + const ALMOST_MIN: u16 = u16::MIN + 1; + const VAL: u16 = 42; + const VAL_1: u16 = VAL + 1; + const VAL_2: u16 = VAL + 2; + m!(0, ..u16::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u32() { + const ALMOST_MAX: u32 = u32::MAX - 1; + const ALMOST_MIN: u32 = u32::MIN + 1; + const VAL: u32 = 42; + const VAL_1: u32 = VAL + 1; + const VAL_2: u32 = VAL + 2; + m!(0, ..u32::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u64() { + const ALMOST_MAX: u64 = u64::MAX - 1; + const ALMOST_MIN: u64 = u64::MIN + 1; + const VAL: u64 = 42; + const VAL_1: u64 = VAL + 1; + const VAL_2: u64 = VAL + 2; + m!(0, ..u64::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn u128() { + const ALMOST_MAX: u128 = u128::MAX - 1; + const ALMOST_MIN: u128 = u128::MIN + 1; + const VAL: u128 = 42; + const VAL_1: u128 = VAL + 1; + const VAL_2: u128 = VAL + 2; + m!(0, ..u128::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } +} + +mod signed { + fn i8() { + const ALMOST_MAX: i8 = i8::MAX - 1; + const ALMOST_MIN: i8 = i8::MIN + 1; + const VAL: i8 = 42; + const VAL_1: i8 = VAL + 1; + const VAL_2: i8 = VAL + 2; + m!(0, ..i8::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i16() { + const ALMOST_MAX: i16 = i16::MAX - 1; + const ALMOST_MIN: i16 = i16::MIN + 1; + const VAL: i16 = 42; + const VAL_1: i16 = VAL + 1; + const VAL_2: i16 = VAL + 2; + m!(0, ..i16::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i32() { + const ALMOST_MAX: i32 = i32::MAX - 1; + const ALMOST_MIN: i32 = i32::MIN + 1; + const VAL: i32 = 42; + const VAL_1: i32 = VAL + 1; + const VAL_2: i32 = VAL + 2; + m!(0, ..i32::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i64() { + const ALMOST_MAX: i64 = i64::MAX - 1; + const ALMOST_MIN: i64 = i64::MIN + 1; + const VAL: i64 = 42; + const VAL_1: i64 = VAL + 1; + const VAL_2: i64 = VAL + 2; + m!(0, ..i64::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } + fn i128() { + const ALMOST_MAX: i128 = i128::MAX - 1; + const ALMOST_MIN: i128 = i128::MIN + 1; + const VAL: i128 = 42; + const VAL_1: i128 = VAL + 1; + const VAL_2: i128 = VAL + 2; + m!(0, ..i128::MAX); //~ ERROR non-exhaustive patterns + m!(0, ..ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ALMOST_MIN..); //~ ERROR non-exhaustive patterns + m!(0, ..=ALMOST_MAX); //~ ERROR non-exhaustive patterns + m!(0, ..=VAL | VAL_2..); //~ ERROR non-exhaustive patterns + m!(0, ..VAL_1 | VAL_2..); //~ ERROR non-exhaustive patterns + } +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr new file mode 100644 index 000000000..6b20a820b --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -0,0 +1,819 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 + | +LL | m!(0f32, f32::NEG_INFINITY..); + | ^^^^ pattern `_` not covered + | + = note: the matched value is of type `f32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8 + | +LL | m!(0f32, ..f32::INFINITY); + | ^^^^ pattern `_` not covered + | + = note: the matched value is of type `f32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, _ => todo!() } + | ++++++++++++++ + +error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 + | +LL | m!('a', ..core::char::MAX); + | ^^^ pattern `'\u{10ffff}'` not covered + | + = note: the matched value is of type `char` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } + | +++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 + | +LL | m!('a', ..ALMOST_MAX); + | ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered + | + = note: the matched value is of type `char` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() } + | ++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `'\0'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 + | +LL | m!('a', ALMOST_MIN..); + | ^^^ pattern `'\0'` not covered + | + = note: the matched value is of type `char` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, '\0' => todo!() } + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 + | +LL | m!('a', ..=ALMOST_MAX); + | ^^^ pattern `'\u{10ffff}'` not covered + | + = note: the matched value is of type `char` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } + | +++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `'b'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 + | +LL | m!('a', ..=VAL | VAL_2..); + | ^^^ pattern `'b'` not covered + | + = note: the matched value is of type `char` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 'b' => todo!() } + | ++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `'b'` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8 + | +LL | m!('a', ..VAL_1 | VAL_2..); + | ^^^ pattern `'b'` not covered + | + = note: the matched value is of type `char` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 'b' => todo!() } + | ++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 + | +LL | m!(0, ..u8::MAX); + | ^ pattern `u8::MAX` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `254_u8..=u8::MAX` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() } + | +++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0_u8` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u8 => todo!() } + | +++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `u8::MAX` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_u8` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u8 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_u8` not covered + | + = note: the matched value is of type `u8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u8 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 + | +LL | m!(0, ..u16::MAX); + | ^ pattern `u16::MAX` not covered + | + = note: the matched value is of type `u16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u16::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `65534_u16..=u16::MAX` not covered + | + = note: the matched value is of type `u16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() } + | +++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0_u16` not covered + | + = note: the matched value is of type `u16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u16 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `u16::MAX` not covered + | + = note: the matched value is of type `u16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u16::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_u16` not covered + | + = note: the matched value is of type `u16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u16 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_u16` not covered + | + = note: the matched value is of type `u16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u16 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 + | +LL | m!(0, ..u32::MAX); + | ^ pattern `u32::MAX` not covered + | + = note: the matched value is of type `u32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u32::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `4294967294_u32..=u32::MAX` not covered + | + = note: the matched value is of type `u32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() } + | ++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0_u32` not covered + | + = note: the matched value is of type `u32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u32 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `u32::MAX` not covered + | + = note: the matched value is of type `u32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u32::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_u32` not covered + | + = note: the matched value is of type `u32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u32 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_u32` not covered + | + = note: the matched value is of type `u32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u32 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 + | +LL | m!(0, ..u64::MAX); + | ^ pattern `u64::MAX` not covered + | + = note: the matched value is of type `u64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u64::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `18446744073709551614_u64..=u64::MAX` not covered + | + = note: the matched value is of type `u64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => todo!() } + | ++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0_u64` not covered + | + = note: the matched value is of type `u64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u64 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `u64::MAX` not covered + | + = note: the matched value is of type `u64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u64::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_u64` not covered + | + = note: the matched value is of type `u64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u64 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_u64` not covered + | + = note: the matched value is of type `u64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u64 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 + | +LL | m!(0, ..u128::MAX); + | ^ pattern `u128::MAX` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u128::MAX => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u128..=u128::MAX => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `0_u128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `0_u128` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 0_u128 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `u128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `u128::MAX` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, u128::MAX => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_u128` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u128 => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_u128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_u128` not covered + | + = note: the matched value is of type `u128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_u128 => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 + | +LL | m!(0, ..i8::MAX); + | ^ pattern `i8::MAX` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `126_i8..=i8::MAX` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() } + | +++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `i8::MIN` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i8::MIN => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i8::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `i8::MAX` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i8::MAX => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_i8` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i8 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i8` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_i8` not covered + | + = note: the matched value is of type `i8` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i8 => todo!() } + | ++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 + | +LL | m!(0, ..i16::MAX); + | ^ pattern `i16::MAX` not covered + | + = note: the matched value is of type `i16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i16::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `32766_i16..=i16::MAX` not covered + | + = note: the matched value is of type `i16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() } + | +++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i16::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `i16::MIN` not covered + | + = note: the matched value is of type `i16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i16::MIN => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i16::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `i16::MAX` not covered + | + = note: the matched value is of type `i16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i16::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_i16` not covered + | + = note: the matched value is of type `i16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i16 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i16` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_i16` not covered + | + = note: the matched value is of type `i16` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i16 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 + | +LL | m!(0, ..i32::MAX); + | ^ pattern `i32::MAX` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i32::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `2147483646_i32..=i32::MAX` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() } + | ++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i32::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `i32::MIN` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i32::MIN => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i32::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `i32::MAX` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i32::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_i32` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i32 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i32` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_i32` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i32 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 + | +LL | m!(0, ..i64::MAX); + | ^ pattern `i64::MAX` not covered + | + = note: the matched value is of type `i64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i64::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `9223372036854775806_i64..=i64::MAX` not covered + | + = note: the matched value is of type `i64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i64::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `i64::MIN` not covered + | + = note: the matched value is of type `i64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i64::MIN => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i64::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `i64::MAX` not covered + | + = note: the matched value is of type `i64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i64::MAX => todo!() } + | +++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_i64` not covered + | + = note: the matched value is of type `i64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i64 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i64` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_i64` not covered + | + = note: the matched value is of type `i64` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i64 => todo!() } + | +++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 + | +LL | m!(0, ..i128::MAX); + | ^ pattern `i128::MAX` not covered + | + = note: the matched value is of type `i128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i128::MAX => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 + | +LL | m!(0, ..ALMOST_MAX); + | ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered + | + = note: the matched value is of type `i128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i128..=i128::MAX => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i128::MIN` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 + | +LL | m!(0, ALMOST_MIN..); + | ^ pattern `i128::MIN` not covered + | + = note: the matched value is of type `i128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i128::MIN => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `i128::MAX` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 + | +LL | m!(0, ..=ALMOST_MAX); + | ^ pattern `i128::MAX` not covered + | + = note: the matched value is of type `i128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, i128::MAX => todo!() } + | ++++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 + | +LL | m!(0, ..=VAL | VAL_2..); + | ^ pattern `43_i128` not covered + | + = note: the matched value is of type `i128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i128 => todo!() } + | ++++++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `43_i128` not covered + --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12 + | +LL | m!(0, ..VAL_1 | VAL_2..); + | ^ pattern `43_i128` not covered + | + = note: the matched value is of type `i128` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | match $s { $($t)+ => {}, 43_i128 => todo!() } + | ++++++++++++++++++++ + +error: aborting due to 68 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs new file mode 100644 index 000000000..4b7eee134 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs @@ -0,0 +1,48 @@ +// check-pass + +// Test various exhaustive matches for `X..`, `..=X` and `..X` ranges. + +#![feature(exclusive_range_pattern)] + +fn main() {} + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +macro_rules! test_int { + ($s:expr, $min:path, $max:path) => { + m!($s, $min..); + m!($s, $min..5 | 5..); + m!($s, ..5 | 5..); + m!($s, ..=4 | 5..); + m!($s, ..=$max); + m!($s, ..$max | $max); + m!(($s, true), (..5, true) | (5.., true) | ($min.., false)); + } +} + +fn unsigned_int() { + test_int!(0u8, u8::MIN, u8::MAX); + test_int!(0u16, u16::MIN, u16::MAX); + test_int!(0u32, u32::MIN, u32::MAX); + test_int!(0u64, u64::MIN, u64::MAX); + test_int!(0u128, u128::MIN, u128::MAX); +} + +fn signed_int() { + test_int!(0i8, i8::MIN, i8::MAX); + test_int!(0i16, i16::MIN, i16::MAX); + test_int!(0i32, i32::MIN, i32::MAX); + test_int!(0i64, i64::MIN, i64::MAX); + test_int!(0i128, i128::MIN, i128::MAX); +} + +fn khar() { + m!('a', ..=core::char::MAX); + m!('a', '\u{0}'..); + m!('a', ..='\u{D7FF}' | '\u{E000}'..); + m!('a', ..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..); +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs new file mode 100644 index 000000000..526a797e9 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs @@ -0,0 +1,30 @@ +// Test that `...X` range-to patterns are syntactically invalid. +// +// See https://github.com/rust-lang/rust/pull/67258#issuecomment-565656155 +// for the reason why. To summarize, we might want to introduce `...expr` as +// an expression form for splatting (or "untupling") in an expression context. +// While there is no syntactic ambiguity with `...X` in a pattern context, +// there's a potential confusion factor here, and we would prefer to keep patterns +// and expressions in-sync. As such, we do not allow `...X` in patterns either. + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + match scrutinee { + ...X => {} //~ ERROR range-to patterns with `...` are not allowed + ...0 => {} //~ ERROR range-to patterns with `...` are not allowed + ...'a' => {} //~ ERROR range-to patterns with `...` are not allowed + ...0.0f32 => {} //~ ERROR range-to patterns with `...` are not allowed + } +} + +fn syntax2() { + macro_rules! mac { + ($e:expr) => { + let ...$e; //~ ERROR range-to patterns with `...` are not allowed + } + } + + mac!(0); +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr new file mode 100644 index 000000000..ddffeaf97 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -0,0 +1,37 @@ +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:15:9 + | +LL | ...X => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:16:9 + | +LL | ...0 => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9 + | +LL | ...'a' => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9 + | +LL | ...0.0f32 => {} + | ^^^ help: use `..=` instead + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17 + | +LL | let ...$e; + | ^^^ help: use `..=` instead +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors + diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs new file mode 100644 index 000000000..6567c8cc6 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs @@ -0,0 +1,24 @@ +// Test `X...` and `X..=` range patterns not being allowed syntactically. +// FIXME(Centril): perhaps these should be semantic restrictions. + +fn main() {} + +#[cfg(FALSE)] +fn foo() { + if let 0... = 1 {} //~ ERROR inclusive range with no end + if let 0..= = 1 {} //~ ERROR inclusive range with no end + const X: u8 = 0; + if let X... = 1 {} //~ ERROR inclusive range with no end + if let X..= = 1 {} //~ ERROR inclusive range with no end +} + +fn bar() { + macro_rules! mac { + ($e:expr) => { + let $e...; //~ ERROR inclusive range with no end + let $e..=; //~ ERROR inclusive range with no end + } + } + + mac!(0); +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr new file mode 100644 index 000000000..3ad84b0ef --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -0,0 +1,59 @@ +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:8:13 + | +LL | if let 0... = 1 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:9:13 + | +LL | if let 0..= = 1 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13 + | +LL | if let X... = 1 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:12:13 + | +LL | if let X..= = 1 {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:19 + | +LL | let $e...; + | ^^^ help: use `..` instead +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-inclusive-no-end.rs:19:19 + | +LL | let $e..=; + | ^^^ help: use `..` instead +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs new file mode 100644 index 000000000..2d63fe078 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs @@ -0,0 +1,24 @@ +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + match &0 { + &0.. | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + &0..= | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~| ERROR inclusive range with no end + &0... | _ => {} + //~^ ERROR inclusive range with no end + } + + match &0 { + &..0 | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + &..=0 | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + &...0 | _ => {} + //~^ ERROR the range pattern here has ambiguous interpretation + //~| ERROR range-to patterns with `...` are not allowed + } +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr new file mode 100644 index 000000000..111e81799 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr @@ -0,0 +1,55 @@ +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:6:10 + | +LL | &0.. | _ => {} + | ^^^ help: add parentheses to clarify the precedence: `(0..)` + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:11 + | +LL | &0..= | _ => {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10 + | +LL | &0..= | _ => {} + | ^^^^ help: add parentheses to clarify the precedence: `(0..=)` + +error[E0586]: inclusive range with no end + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:11:11 + | +LL | &0... | _ => {} + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:16:10 + | +LL | &..0 | _ => {} + | ^^^ help: add parentheses to clarify the precedence: `(..0)` + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10 + | +LL | &..=0 | _ => {} + | ^^^^ help: add parentheses to clarify the precedence: `(..=0)` + +error: range-to patterns with `...` are not allowed + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10 + | +LL | &...0 | _ => {} + | ^^^ help: use `..=` instead + +error: the range pattern here has ambiguous interpretation + --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10 + | +LL | &...0 | _ => {} + | ^^^^ help: add parentheses to clarify the precedence: `(..=0)` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs new file mode 100644 index 000000000..6c6ba9319 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs @@ -0,0 +1,159 @@ +// run-pass + +// Test half-open range patterns against their expression equivalents +// via `.contains(...)` and make sure the dynamic semantics match. + +#![feature(exclusive_range_pattern)] +#![allow(illegal_floating_point_literal_pattern)] +#![allow(unreachable_patterns)] + +macro_rules! yes { + ($scrutinee:expr, $($t:tt)+) => { + { + let m = match $scrutinee { $($t)+ => true, _ => false, }; + let c = ($($t)+).contains(&$scrutinee); + assert_eq!(m, c); + m + } + } +} + +fn range_to_inclusive() { + // `..=X` (`RangeToInclusive`-equivalent): + //--------------------------------------- + + // u8; `..=X` + assert!(yes!(u8::MIN, ..=u8::MIN)); + assert!(yes!(u8::MIN, ..=5)); + assert!(yes!(5u8, ..=5)); + assert!(!yes!(6u8, ..=5)); + + // i16; `..=X` + assert!(yes!(i16::MIN, ..=i16::MIN)); + assert!(yes!(i16::MIN, ..=0)); + assert!(yes!(i16::MIN, ..=-5)); + assert!(yes!(-5, ..=-5)); + assert!(!yes!(-4, ..=-5)); + + // char; `..=X` + assert!(yes!('\u{0}', ..='\u{0}')); + assert!(yes!('\u{0}', ..='a')); + assert!(yes!('a', ..='a')); + assert!(!yes!('b', ..='a')); + + // f32; `..=X` + assert!(yes!(f32::NEG_INFINITY, ..=f32::NEG_INFINITY)); + assert!(yes!(f32::NEG_INFINITY, ..=1.0f32)); + assert!(yes!(1.5f32, ..=1.5f32)); + assert!(!yes!(1.6f32, ..=-1.5f32)); + + // f64; `..=X` + assert!(yes!(f64::NEG_INFINITY, ..=f64::NEG_INFINITY)); + assert!(yes!(f64::NEG_INFINITY, ..=1.0f64)); + assert!(yes!(1.5f64, ..=1.5f64)); + assert!(!yes!(1.6f64, ..=-1.5f64)); +} + +fn range_to() { + // `..X` (`RangeTo`-equivalent): + //----------------------------- + + // u8; `..X` + assert!(yes!(0u8, ..1)); + assert!(yes!(0u8, ..5)); + assert!(!yes!(5u8, ..5)); + assert!(!yes!(6u8, ..5)); + + // u8; `..X` + const NU8: u8 = u8::MIN + 1; + assert!(yes!(u8::MIN, ..NU8)); + assert!(yes!(0u8, ..5)); + assert!(!yes!(5u8, ..5)); + assert!(!yes!(6u8, ..5)); + + // i16; `..X` + const NI16: i16 = i16::MIN + 1; + assert!(yes!(i16::MIN, ..NI16)); + assert!(yes!(i16::MIN, ..5)); + assert!(yes!(-6, ..-5)); + assert!(!yes!(-5, ..-5)); + + // char; `..X` + assert!(yes!('\u{0}', ..'\u{1}')); + assert!(yes!('\u{0}', ..'a')); + assert!(yes!('a', ..'b')); + assert!(!yes!('a', ..'a')); + assert!(!yes!('b', ..'a')); + + // f32; `..X` + assert!(yes!(f32::NEG_INFINITY, ..1.0f32)); + assert!(!yes!(1.5f32, ..1.5f32)); + const E32: f32 = 1.5f32 + f32::EPSILON; + assert!(yes!(1.5f32, ..E32)); + assert!(!yes!(1.6f32, ..1.5f32)); + + // f64; `..X` + assert!(yes!(f64::NEG_INFINITY, ..1.0f64)); + assert!(!yes!(1.5f64, ..1.5f64)); + const E64: f64 = 1.5f64 + f64::EPSILON; + assert!(yes!(1.5f64, ..E64)); + assert!(!yes!(1.6f64, ..1.5f64)); +} + +fn range_from() { + // `X..` (`RangeFrom`-equivalent): + //-------------------------------- + + // u8; `X..` + assert!(yes!(u8::MIN, u8::MIN..)); + assert!(yes!(u8::MAX, u8::MIN..)); + assert!(!yes!(u8::MIN, 1..)); + assert!(!yes!(4, 5..)); + assert!(yes!(5, 5..)); + assert!(yes!(6, 5..)); + assert!(yes!(u8::MAX, u8::MAX..)); + + // i16; `X..` + assert!(yes!(i16::MIN, i16::MIN..)); + assert!(yes!(i16::MAX, i16::MIN..)); + const NI16: i16 = i16::MIN + 1; + assert!(!yes!(i16::MIN, NI16..)); + assert!(!yes!(-4, 5..)); + assert!(yes!(-4, -4..)); + assert!(yes!(-3, -4..)); + assert!(yes!(i16::MAX, i16::MAX..)); + + // char; `X..` + assert!(yes!('\u{0}', '\u{0}'..)); + assert!(yes!(core::char::MAX, '\u{0}'..)); + assert!(yes!('a', 'a'..)); + assert!(yes!('b', 'a'..)); + assert!(!yes!('a', 'b'..)); + assert!(yes!(core::char::MAX, core::char::MAX..)); + + // f32; `X..` + assert!(yes!(f32::NEG_INFINITY, f32::NEG_INFINITY..)); + assert!(yes!(f32::INFINITY, f32::NEG_INFINITY..)); + assert!(!yes!(f32::NEG_INFINITY, 1.0f32..)); + assert!(yes!(f32::INFINITY, 1.0f32..)); + assert!(!yes!(1.0f32 - f32::EPSILON, 1.0f32..)); + assert!(yes!(1.0f32, 1.0f32..)); + assert!(yes!(f32::INFINITY, 1.0f32..)); + assert!(yes!(f32::INFINITY, f32::INFINITY..)); + + // f64; `X..` + assert!(yes!(f64::NEG_INFINITY, f64::NEG_INFINITY..)); + assert!(yes!(f64::INFINITY, f64::NEG_INFINITY..)); + assert!(!yes!(f64::NEG_INFINITY, 1.0f64..)); + assert!(yes!(f64::INFINITY, 1.0f64..)); + assert!(!yes!(1.0f64 - f64::EPSILON, 1.0f64..)); + assert!(yes!(1.0f64, 1.0f64..)); + assert!(yes!(f64::INFINITY, 1.0f64..)); + assert!(yes!(f64::INFINITY, f64::INFINITY..)); +} + +fn main() { + range_to_inclusive(); + range_to(); + range_from(); +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs new file mode 100644 index 000000000..9a73e8906 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs @@ -0,0 +1,29 @@ +// check-pass + +// Test the parsing of half-open ranges. + +#![feature(exclusive_range_pattern)] + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + match scrutinee { + X.. | 0.. | 'a'.. | 0.0f32.. => {} + ..=X | ..X => {} + ..=0 | ..0 => {} + ..='a' | ..'a' => {} + ..=0.0f32 | ..0.0f32 => {} + } +} + +fn syntax2() { + macro_rules! mac { + ($e:expr) => { + match 0u8 { ..$e => {}, _ => {} } + match 0u8 { ..=$e => {}, _ => {} } + match 0u8 { $e.. => {}, _ => {} } + } + } + mac!(42u8); +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs new file mode 100644 index 000000000..f55566602 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs @@ -0,0 +1,53 @@ +#![feature(exclusive_range_pattern)] +#![allow(illegal_floating_point_literal_pattern)] + +macro_rules! m { + ($s:expr, $($t:tt)+) => { + match $s { $($t)+ => {} } + } +} + +fn main() { + m!(0, ..u8::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..u16::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..u32::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..u64::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..u128::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + + m!(0, ..i8::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..i16::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..i32::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..i64::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0, ..i128::MIN); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + + m!(0f32, ..f32::NEG_INFINITY); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + m!(0f64, ..f64::NEG_INFINITY); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + + m!('a', ..'\u{0}'); + //~^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper +} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr new file mode 100644 index 000000000..56b224a85 --- /dev/null +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr @@ -0,0 +1,159 @@ +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11 + | +LL | m!(0, ..u8::MIN); + | ^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11 + | +LL | m!(0, ..u16::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11 + | +LL | m!(0, ..u32::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11 + | +LL | m!(0, ..u64::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11 + | +LL | m!(0, ..u128::MIN); + | ^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11 + | +LL | m!(0, ..i8::MIN); + | ^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 + | +LL | m!(0, ..i16::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11 + | +LL | m!(0, ..i32::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11 + | +LL | m!(0, ..i64::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11 + | +LL | m!(0, ..i128::MIN); + | ^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14 + | +LL | m!(0f32, ..f32::NEG_INFINITY); + | ^^^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14 + | +LL | m!(0f64, ..f64::NEG_INFINITY); + | ^^^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13 + | +LL | m!('a', ..'\u{0}'); + | ^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11 + | +LL | m!(0, ..u8::MIN); + | ^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11 + | +LL | m!(0, ..u16::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11 + | +LL | m!(0, ..u32::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11 + | +LL | m!(0, ..u64::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11 + | +LL | m!(0, ..u128::MIN); + | ^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11 + | +LL | m!(0, ..i8::MIN); + | ^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 + | +LL | m!(0, ..i16::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11 + | +LL | m!(0, ..i32::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11 + | +LL | m!(0, ..i64::MIN); + | ^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11 + | +LL | m!(0, ..i128::MIN); + | ^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14 + | +LL | m!(0f32, ..f32::NEG_INFINITY); + | ^^^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14 + | +LL | m!(0f64, ..f64::NEG_INFINITY); + | ^^^^^^^^^^^^^^^^^^^ + +error[E0579]: lower range bound must be less than upper + --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13 + | +LL | m!('a', ..'\u{0}'); + | ^^^^^^^^^ + +error: aborting due to 26 previous errors + +For more information about this error, try `rustc --explain E0579`. diff --git a/tests/ui/half-open-range-patterns/pat-tuple-4.rs b/tests/ui/half-open-range-patterns/pat-tuple-4.rs new file mode 100644 index 000000000..11c4ab9c5 --- /dev/null +++ b/tests/ui/half-open-range-patterns/pat-tuple-4.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(exclusive_range_pattern)] + +fn main() { + const PAT: u8 = 1; + + match 0 { + (.. PAT) => {} + _ => {} + } +} diff --git a/tests/ui/half-open-range-patterns/pat-tuple-5.rs b/tests/ui/half-open-range-patterns/pat-tuple-5.rs new file mode 100644 index 000000000..995ef03c8 --- /dev/null +++ b/tests/ui/half-open-range-patterns/pat-tuple-5.rs @@ -0,0 +1,9 @@ +#![feature(exclusive_range_pattern)] + +fn main() { + const PAT: u8 = 1; + + match (0, 1) { + (PAT ..) => {} //~ ERROR mismatched types + } +} diff --git a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr new file mode 100644 index 000000000..c60842638 --- /dev/null +++ b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/pat-tuple-5.rs:7:10 + | +LL | match (0, 1) { + | ------ this expression has type `({integer}, {integer})` +LL | (PAT ..) => {} + | ^^^ expected tuple, found `u8` + | + = note: expected tuple `({integer}, {integer})` + found type `u8` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs new file mode 100644 index 000000000..acb7feac1 --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -0,0 +1,31 @@ +// run-pass +#![allow(incomplete_features)] +#![feature(exclusive_range_pattern)] +#![feature(inline_const_pat)] + +fn main() { + let mut if_lettable = vec![]; + let mut first_or = vec![]; + let mut or_two = vec![]; + let mut range_from = vec![]; + let mut bottom = vec![]; + + for x in -9 + 1..=(9 - 2) { + if let -1..=0 | 2..3 | 4 = x { + if_lettable.push(x) + } + match x { + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } + assert_eq!(if_lettable, [-1, 0, 2, 4]); + assert_eq!(first_or, [-3, -2, -1, 1]); + assert_eq!(or_two, [0, 2, 3, 4, 6]); + assert_eq!(range_from, [-5, -4, 7]); + assert_eq!(bottom, [-7, -6]); +} diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs new file mode 100644 index 000000000..55353999b --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -0,0 +1,29 @@ +fn main() { + let mut if_lettable = Vec::::new(); + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + let mut errors_only = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + if let n @ 2..3|4 = x { + //~^ error: variable `n` is not bound in all patterns + //~| exclusive range pattern syntax is experimental + errors_only.push(x); + } else if let 2..3 | 4 = x { + //~^ exclusive range pattern syntax is experimental + if_lettable.push(x); + } + match x as i32 { + 0..5+1 => errors_only.push(x), + //~^ error: expected one of `=>`, `if`, or `|`, found `+` + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } +} diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr new file mode 100644 index 000000000..19ebcaf0f --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -0,0 +1,36 @@ +error: expected one of `=>`, `if`, or `|`, found `+` + --> $DIR/range_pat_interactions1.rs:19:17 + | +LL | 0..5+1 => errors_only.push(x), + | ^ expected one of `=>`, `if`, or `|` + +error[E0408]: variable `n` is not bound in all patterns + --> $DIR/range_pat_interactions1.rs:10:25 + | +LL | if let n @ 2..3|4 = x { + | - ^ pattern doesn't bind `n` + | | + | variable not in all patterns + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:10:20 + | +LL | if let n @ 2..3|4 = x { + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions1.rs:14:23 + | +LL | } else if let 2..3 | 4 = x { + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0408, E0658. +For more information about an error, try `rustc --explain E0408`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs new file mode 100644 index 000000000..4615ebd68 --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -0,0 +1,21 @@ +fn main() { + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + let mut errors_only = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + match x as i32 { + 0..=(5+1) => errors_only.push(x), + //~^ error: inclusive range with no end + //~| error: expected one of `=>`, `if`, or `|`, found `(` + 1 | -3..0 => first_or.push(x), + y @ (0..5 | 6) => or_two.push(y), + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + y => bottom.push(y), + } + } +} diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr new file mode 100644 index 000000000..13a5542a4 --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -0,0 +1,17 @@ +error[E0586]: inclusive range with no end + --> $DIR/range_pat_interactions2.rs:10:14 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^^^ help: use `..` instead + | + = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) + +error: expected one of `=>`, `if`, or `|`, found `(` + --> $DIR/range_pat_interactions2.rs:10:17 + | +LL | 0..=(5+1) => errors_only.push(x), + | ^ expected one of `=>`, `if`, or `|` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.rs b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs new file mode 100644 index 000000000..446ed45f9 --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions3.rs @@ -0,0 +1,23 @@ +fn main() { + let mut first_or = Vec::::new(); + let mut or_two = Vec::::new(); + let mut range_from = Vec::::new(); + let mut bottom = Vec::::new(); + + for x in -9 + 1..=(9 - 2) { + match x as i32 { + 8.. => bottom.push(x), + 1 | -3..0 => first_or.push(x), + //~^ exclusive range pattern syntax is experimental + y @ (0..5 | 6) => or_two.push(y), + //~^ exclusive range pattern syntax is experimental + y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + //~^ inline-const in pattern position is experimental + //~| exclusive range pattern syntax is experimental + y @ -5.. => range_from.push(y), + y @ ..-7 => assert_eq!(y, -8), + //~^ exclusive range pattern syntax is experimental + y => bottom.push(y), + } + } +} diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr new file mode 100644 index 000000000..f7fda6775 --- /dev/null +++ b/tests/ui/half-open-range-patterns/range_pat_interactions3.stderr @@ -0,0 +1,48 @@ +error[E0658]: inline-const in pattern position is experimental + --> $DIR/range_pat_interactions3.rs:14:20 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^ + | + = note: see issue #76001 for more information + = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:10:17 + | +LL | 1 | -3..0 => first_or.push(x), + | ^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:12:18 + | +LL | y @ (0..5 | 6) => or_two.push(y), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:14:17 + | +LL | y @ 0..const { 5 + 1 } => assert_eq!(y, 5), + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range_pat_interactions3.rs:18:17 + | +LL | y @ ..-7 => assert_eq!(y, -8), + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs new file mode 100644 index 000000000..d54cbfbf4 --- /dev/null +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs @@ -0,0 +1,16 @@ +#![feature(half_open_range_patterns_in_slices)] +#![feature(exclusive_range_pattern)] + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a, b, c, rest @ ..] = xs; + // Consider the following example: + assert!(a == 13 && b == 1 && c == 5 && rest.len() == 5); + + // What if we wanted to pull this apart without individually binding a, b, and c? + let [first_three @ ..3, rest @ 2..] = xs; + //~^ pattern requires 2 elements but array has 8 + // This is somewhat unintuitive and makes slice patterns exceedingly verbose. + // We want to stabilize half-open RangeFrom (`X..`) patterns + // but without banning us from using them for a more efficient slice pattern syntax. +} diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr new file mode 100644 index 000000000..ec3472a50 --- /dev/null +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.stderr @@ -0,0 +1,9 @@ +error[E0527]: pattern requires 2 elements but array has 8 + --> $DIR/slice_pattern_syntax_problem0.rs:11:9 + | +LL | let [first_three @ ..3, rest @ 2..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 8 elements + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0527`. diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs new file mode 100644 index 000000000..c37af75b8 --- /dev/null +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -0,0 +1,8 @@ +// Instead of allowing the previous case, maintain the feature gate for slice patterns for now. +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + //~^ `X..` patterns in slices are experimental + //~| exclusive range pattern syntax is experimental + //~| exclusive range pattern syntax is experimental +} diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr new file mode 100644 index 000000000..3bca554b1 --- /dev/null +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -0,0 +1,30 @@ +error[E0658]: `X..` patterns in slices are experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:10 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:23 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/slice_pattern_syntax_problem1.rs:4:32 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs new file mode 100644 index 000000000..6e7df3094 --- /dev/null +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem2.rs @@ -0,0 +1,10 @@ +// run-pass + +fn main() { + let xs = [13, 1, 5, 2, 3, 1, 21, 8]; + if let [3..=14, ..] = xs { + /* this variant must pass for now, unfortunately. + * This test is included here to help inform a future plan for these. + */ + }; +} diff --git a/tests/ui/hashmap/hashmap-capacity-overflow.rs b/tests/ui/hashmap/hashmap-capacity-overflow.rs new file mode 100644 index 000000000..2988af065 --- /dev/null +++ b/tests/ui/hashmap/hashmap-capacity-overflow.rs @@ -0,0 +1,12 @@ +// run-fail +// error-pattern:capacity overflow +// ignore-emscripten no processes + +use std::collections::hash_map::HashMap; +use std::mem::size_of; + +fn main() { + let threshold = usize::MAX / size_of::<(u64, u64, u64)>(); + let mut h = HashMap::::with_capacity(threshold + 100); + h.insert(0, 0); +} diff --git a/tests/ui/hashmap/hashmap-index-mut.rs b/tests/ui/hashmap/hashmap-index-mut.rs new file mode 100644 index 000000000..98448e9d5 --- /dev/null +++ b/tests/ui/hashmap/hashmap-index-mut.rs @@ -0,0 +1,6 @@ +use std::collections::HashMap; + +fn main() { + let mut map = HashMap::::new(); + map[&0] = 1; //~ ERROR cannot assign +} diff --git a/tests/ui/hashmap/hashmap-index-mut.stderr b/tests/ui/hashmap/hashmap-index-mut.stderr new file mode 100644 index 000000000..c1948ab62 --- /dev/null +++ b/tests/ui/hashmap/hashmap-index-mut.stderr @@ -0,0 +1,19 @@ +error[E0594]: cannot assign to data in an index of `HashMap` + --> $DIR/hashmap-index-mut.rs:5:5 + | +LL | map[&0] = 1; + | ^^^^^^^^^^^ cannot assign + | + = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap` +help: to modify a `HashMap`, use `.get_mut()`, `.insert()` or the entry API + | +LL | map.insert(&0, 1); + | ~~~~~~~~ ~ + +LL | map.get_mut(&0).map(|val| { *val = 1; }); + | ~~~~~~~~~ ~~~~~~~~~~~~~~~~~~ ++++ +LL | let val = map.entry(&0).or_insert(1); + | +++++++++ ~~~~~~~ ~~~~~~~~~~~~ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/hashmap/hashmap-iter-value-lifetime.rs b/tests/ui/hashmap/hashmap-iter-value-lifetime.rs new file mode 100644 index 000000000..260ea8c7a --- /dev/null +++ b/tests/ui/hashmap/hashmap-iter-value-lifetime.rs @@ -0,0 +1,10 @@ +fn main() { + let mut my_stuff = std::collections::HashMap::new(); + my_stuff.insert(0, 42); + + let (_, thing) = my_stuff.iter().next().unwrap(); + + my_stuff.clear(); //~ ERROR cannot borrow + + println!("{}", *thing); +} diff --git a/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr b/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr new file mode 100644 index 000000000..d6e7a1d45 --- /dev/null +++ b/tests/ui/hashmap/hashmap-iter-value-lifetime.stderr @@ -0,0 +1,15 @@ +error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable + --> $DIR/hashmap-iter-value-lifetime.rs:7:5 + | +LL | let (_, thing) = my_stuff.iter().next().unwrap(); + | --------------- immutable borrow occurs here +LL | +LL | my_stuff.clear(); + | ^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | +LL | println!("{}", *thing); + | ------ immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/hashmap/hashmap-lifetimes.rs b/tests/ui/hashmap/hashmap-lifetimes.rs new file mode 100644 index 000000000..295bf3b0e --- /dev/null +++ b/tests/ui/hashmap/hashmap-lifetimes.rs @@ -0,0 +1,8 @@ +fn main() { + let mut my_stuff = std::collections::HashMap::new(); + my_stuff.insert(0, 42); + + let mut it = my_stuff.iter(); + my_stuff.insert(1, 43); //~ ERROR cannot borrow + it; +} diff --git a/tests/ui/hashmap/hashmap-lifetimes.stderr b/tests/ui/hashmap/hashmap-lifetimes.stderr new file mode 100644 index 000000000..d1bcd53ae --- /dev/null +++ b/tests/ui/hashmap/hashmap-lifetimes.stderr @@ -0,0 +1,13 @@ +error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable + --> $DIR/hashmap-lifetimes.rs:6:5 + | +LL | let mut it = my_stuff.iter(); + | --------------- immutable borrow occurs here +LL | my_stuff.insert(1, 43); + | ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | it; + | -- immutable borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/hashmap/hashmap-memory.rs b/tests/ui/hashmap/hashmap-memory.rs new file mode 100644 index 000000000..87f8b6ad5 --- /dev/null +++ b/tests/ui/hashmap/hashmap-memory.rs @@ -0,0 +1,94 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unused_mut)] +// ignore-emscripten No support for threads + +/** + A somewhat reduced test case to expose some Valgrind issues. + + This originally came from the word-count benchmark. +*/ + +pub fn map(filename: String, mut emit: map_reduce::putter) { + emit(filename, "1".to_string()); +} + +mod map_reduce { + use std::collections::HashMap; + use std::sync::mpsc::{channel, Sender}; + use std::str; + use std::thread; + + pub type putter<'a> = Box; + + pub type mapper = extern "C" fn(String, putter); + + enum ctrl_proto { find_reducer(Vec, Sender), mapper_done, } + + fn start_mappers(ctrl: Sender, inputs: Vec) { + for i in &inputs { + let ctrl = ctrl.clone(); + let i = i.clone(); + thread::spawn(move|| map_task(ctrl.clone(), i.clone()) ); + } + } + + fn map_task(ctrl: Sender, input: String) { + let mut intermediates = HashMap::new(); + + fn emit(im: &mut HashMap, + ctrl: Sender, key: String, + _val: String) { + if im.contains_key(&key) { + return; + } + let (tx, rx) = channel(); + println!("sending find_reducer"); + ctrl.send(ctrl_proto::find_reducer(key.as_bytes().to_vec(), tx)).unwrap(); + println!("receiving"); + let c = rx.recv().unwrap(); + println!("{}", c); + im.insert(key, c); + } + + let ctrl_clone = ctrl.clone(); + ::map(input, Box::new(|a,b| emit(&mut intermediates, ctrl.clone(), a, b))); + ctrl_clone.send(ctrl_proto::mapper_done).unwrap(); + } + + pub fn map_reduce(inputs: Vec) { + let (tx, rx) = channel(); + + // This thread becomes the master control thread. It spawns others + // to do the rest. + + let mut reducers: HashMap; + + reducers = HashMap::new(); + + start_mappers(tx, inputs.clone()); + + let mut num_mappers = inputs.len() as isize; + + while num_mappers > 0 { + match rx.recv().unwrap() { + ctrl_proto::mapper_done => { num_mappers -= 1; } + ctrl_proto::find_reducer(k, cc) => { + let mut c; + match reducers.get(&str::from_utf8(&k).unwrap().to_string()) { + Some(&_c) => { c = _c; } + None => { c = 0; } + } + cc.send(c).unwrap(); + } + } + } + } +} + +pub fn main() { + map_reduce::map_reduce( + vec!["../tests/run-pass/hashmap-memory.rs".to_string()]); +} diff --git a/tests/ui/hello.rs b/tests/ui/hello.rs new file mode 100644 index 000000000..c66b7c60f --- /dev/null +++ b/tests/ui/hello.rs @@ -0,0 +1,12 @@ +// run-pass +// revisions: e2015 e2018 e2021 e2024 + +//[e2018] edition:2018 +//[e2021] edition:2021 +//[e2024] edition:2024 + +//[e2024] compile-flags: -Zunstable-options + +fn main() { + println!("hello"); +} diff --git a/tests/ui/hello_world/main.rs b/tests/ui/hello_world/main.rs new file mode 100644 index 000000000..22ce47414 --- /dev/null +++ b/tests/ui/hello_world/main.rs @@ -0,0 +1,7 @@ +// build-pass (FIXME(62277): could be check-pass?) + +// Test that compiling hello world succeeds with no output of any kind. + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/higher-lifetime-bounds.rs b/tests/ui/higher-lifetime-bounds.rs new file mode 100644 index 000000000..f3393347d --- /dev/null +++ b/tests/ui/higher-lifetime-bounds.rs @@ -0,0 +1,69 @@ +#![allow(dead_code, non_camel_case_types)] + +// Test that bounds on higher-kinded lifetime binders are rejected. + +fn bar1<'a, 'b>( + x: &'a i32, + y: &'b i32, + f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32) + //~^ ERROR lifetime bounds cannot be used in this context +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>( + //~^ ERROR lifetime bounds cannot be used in this context + x: &'a i32, + y: &'b i32, + f: F) +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +fn bar3<'a, 'b, F>( + x: &'a i32, + y: &'b i32, + f: F) + where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32 + //~^ ERROR lifetime bounds cannot be used in this context +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +fn bar4<'a, 'b, F>( + x: &'a i32, + y: &'b i32, + f: F) + where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32 + //~^ ERROR lifetime bounds cannot be used in this context +{ + // If the bound in f's type would matter, the call below would (have to) + // be rejected. + f(x, y); +} + +struct S1 Fn(&'xa i32, &'xb i32) -> &'xa i32>(F); +//~^ ERROR lifetime bounds cannot be used in this context +struct S2(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32; +//~^ ERROR lifetime bounds cannot be used in this context +struct S3(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32; +//~^ ERROR lifetime bounds cannot be used in this context + +struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32); +//~^ ERROR lifetime bounds cannot be used in this context + +type T1 = Box Fn(&'xa i32, &'xb i32) -> &'xa i32>; +//~^ ERROR lifetime bounds cannot be used in this context + +fn main() { + let _ : Option fn(&'xa i32, &'xb i32) -> &'xa i32> = None; + //~^ ERROR lifetime bounds cannot be used in this context + let _ : Option Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None; + //~^ ERROR lifetime bounds cannot be used in this context +} diff --git a/tests/ui/higher-lifetime-bounds.stderr b/tests/ui/higher-lifetime-bounds.stderr new file mode 100644 index 000000000..bc6d2288c --- /dev/null +++ b/tests/ui/higher-lifetime-bounds.stderr @@ -0,0 +1,68 @@ +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:8:22 + | +LL | f: for<'xa, 'xb: 'xa+'xa> fn(&'xa i32, &'xb i32) -> &'xa i32) + | ^^^ ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:16:34 + | +LL | fn bar2<'a, 'b, F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32>( + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:31:28 + | +LL | where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32 + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:43:25 + | +LL | where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32 + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:51:28 + | +LL | struct S1 Fn(&'xa i32, &'xb i32) -> &'xa i32>(F); + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:53:40 + | +LL | struct S2(F) where F: for<'xa, 'xb: 'xa> Fn(&'xa i32, &'xb i32) -> &'xa i32; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:55:37 + | +LL | struct S3(F) where for<'xa, 'xb: 'xa> F: Fn(&'xa i32, &'xb i32) -> &'xa i32; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:58:29 + | +LL | struct S_fnty(for<'xa, 'xb: 'xa> fn(&'xa i32, &'xb i32) -> &'xa i32); + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:61:33 + | +LL | type T1 = Box Fn(&'xa i32, &'xb i32) -> &'xa i32>; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:65:34 + | +LL | let _ : Option fn(&'xa i32, &'xb i32) -> &'xa i32> = None; + | ^^^ + +error: lifetime bounds cannot be used in this context + --> $DIR/higher-lifetime-bounds.rs:67:42 + | +LL | let _ : Option Fn(&'xa i32, &'xb i32) -> &'xa i32>> = None; + | ^^^ + +error: aborting due to 11 previous errors + diff --git a/tests/ui/higher-rank-trait-bounds/complex.rs b/tests/ui/higher-rank-trait-bounds/complex.rs new file mode 100644 index 000000000..8cdfe247e --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/complex.rs @@ -0,0 +1,28 @@ +// check-pass + +trait A<'a> {} +trait B<'b> {} +fn foo() where for<'a> T: A<'a> + 'a {} +trait C<'c>: for<'a> A<'a> + for<'b> B<'b> { + type As; +} +struct D where T: for<'c> C<'c, As=&'c ()> { + t: std::marker::PhantomData, +} +trait E<'e, 'g> { + type As; +} +trait F<'f>: for<'a> A<'a> + for<'e> E<'e, 'f> {} +struct G where T: for<'f> F<'f, As=&'f ()> { + t: std::marker::PhantomData, +} +trait H<'a, 'b> { + type As; +} +trait I<'a>: for<'b> H<'a, 'b> {} + +struct J where T: for<'i> I<'i, As=&'i ()> { + t: std::marker::PhantomData, +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs b/tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs new file mode 100644 index 000000000..1afd15613 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/due-to-where-clause.rs @@ -0,0 +1,13 @@ +fn main() { + test::(&mut 42); //~ ERROR implementation of `Foo` is not general enough +} + +trait Foo<'a> {} + +struct FooS<'a> { + data: &'a mut u32, +} + +impl<'a, 'b: 'a> Foo<'b> for FooS<'a> {} + +fn test<'a, F>(data: &'a mut u32) where F: for<'b> Foo<'b> {} diff --git a/tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr b/tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr new file mode 100644 index 000000000..520938a63 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/due-to-where-clause.stderr @@ -0,0 +1,11 @@ +error: implementation of `Foo` is not general enough + --> $DIR/due-to-where-clause.rs:2:5 + | +LL | test::(&mut 42); + | ^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs b/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs new file mode 100644 index 000000000..d34b7a296 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.rs @@ -0,0 +1,16 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +fn id( + f: &dyn Fn(u32), +) -> &dyn Fn( + &dyn Fn( + &dyn Fn( + &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))), + ), + ), +) { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr new file mode 100644 index 000000000..71e196c32 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/hang-on-deeply-nested-dyn.rs:12:5 + | +LL | ) -> &dyn Fn( + | ______- +LL | | &dyn Fn( +LL | | &dyn Fn( +LL | | &dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(u32))))))))), +LL | | ), +LL | | ), +LL | | ) { + | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type +LL | f + | ^ expected reference, found `u32` + | + = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))` + the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt' + found reference `&dyn Fn(u32)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs b/tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs new file mode 100644 index 000000000..cc766c060 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-binder-levels-in-object-types.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test that we handle binder levels in object types correctly. +// Initially, the reference to `'tcx` in the object type +// `&Typer<'tcx>` was getting an incorrect binder level, yielding +// weird compilation ICEs and so forth. + +// pretty-expanded FIXME #23616 + +trait Typer<'tcx> { + fn method(&self, data: &'tcx isize) -> &'tcx isize { data } +} + +struct Tcx<'tcx> { + fields: &'tcx isize +} + +impl<'tcx> Typer<'tcx> for Tcx<'tcx> { +} + +fn g<'tcx>(typer: &dyn Typer<'tcx>) { +} + +fn check_static_type<'x>(tcx: &Tcx<'x>) { + g(tcx) +} + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs b/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs new file mode 100644 index 000000000..a20d03c77 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.rs @@ -0,0 +1,24 @@ +// Regression test for #54302. +// +// We were incorrectly using the "evaluation cache" (which ignored +// region results) to conclude that `&'static str: Deserialize`, even +// though it would require that `for<'de> 'de: 'static`, which is +// clearly false. + +trait Deserialize<'de> {} + +trait DeserializeOwned: for<'de> Deserialize<'de> {} +impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} + +// Based on this impl, `&'static str` only implements Deserialize<'static>. +// It does not implement for<'de> Deserialize<'de>. +impl<'de: 'a, 'a> Deserialize<'de> for &'a str {} + +fn main() { + fn assert_deserialize_owned() {} + assert_deserialize_owned::<&'static str>(); //~ ERROR + + // It correctly does not implement for<'de> Deserialize<'de>. + // fn assert_hrtb Deserialize<'de>>() {} + // assert_hrtb::<&'static str>(); +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr new file mode 100644 index 000000000..f014eab86 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-cache-issue-54302.stderr @@ -0,0 +1,11 @@ +error: implementation of `Deserialize` is not general enough + --> $DIR/hrtb-cache-issue-54302.rs:19:5 + | +LL | assert_deserialize_owned::<&'static str>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough + | + = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0`... + = note: ...but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` + +error: aborting due to previous error + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs b/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs new file mode 100644 index 000000000..e83686404 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.rs @@ -0,0 +1,31 @@ +// Test that an impl with only one bound region `'a` cannot be used to +// satisfy a constraint where there are two bound regions. + +trait Foo { + fn foo(&self, x: X) { } +} + +fn want_foo2() + where T : for<'a,'b> Foo<(&'a isize, &'b isize)> +{ +} + +fn want_foo1() + where T : for<'z> Foo<(&'z isize, &'z isize)> +{ +} + +// Expressed as a where clause + +struct SomeStruct; + +impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct +{ +} + +fn a() { want_foo1::(); } // OK -- foo wants just one region +fn b() { want_foo2::(); } +//~^ ERROR implementation of +//~| ERROR implementation of + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr new file mode 100644 index 000000000..46f5308dd --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-conflate-regions.stderr @@ -0,0 +1,20 @@ +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-conflate-regions.rs:27:10 + | +LL | fn b() { want_foo2::(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs b/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs new file mode 100644 index 000000000..05d3e1a43 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.rs @@ -0,0 +1,18 @@ +// Test the case where the `Self` type has a bound lifetime that must +// be adjusted in the fn signature. Issue #19537. + +use std::collections::HashMap; + +struct Foo<'a> { + map: HashMap +} + +impl<'a> Foo<'a> { + fn new() -> Foo<'a> { panic!() } + fn insert(&'a mut self) { } +} +fn main() { + let mut foo = Foo::new(); + foo.insert(); + foo.insert(); //~ ERROR cannot borrow +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr new file mode 100644 index 000000000..fa391ecba --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-in-receiver.stderr @@ -0,0 +1,14 @@ +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/hrtb-debruijn-in-receiver.rs:17:5 + | +LL | foo.insert(); + | ------------ first mutable borrow occurs here +LL | foo.insert(); + | ^^^^^^^^^^^^ + | | + | second mutable borrow occurs here + | first borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs b/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs new file mode 100644 index 000000000..8431226a3 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-debruijn-object-types-in-closures.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +trait Typer<'tcx> { + fn method(&self, data: &'tcx isize) -> &'tcx isize { data } + fn dummy(&self) { } +} + +fn g(_: F) where F: FnOnce(&dyn Typer) {} + +fn h() { + g(|typer| typer.dummy()) +} + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs new file mode 100644 index 000000000..567802376 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.rs @@ -0,0 +1,18 @@ +// Test an `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +fn foo<'a>() -> fn(&'a u32) { + panic!() +} + +fn main() { + // Here, proving that `fn(&'a u32) <: for<'b> fn(&'b u32)`: + // + // - instantiates `'b` with a placeholder `!b`, + // - requires that `&!b u32 <: &'a u32` and hence that `!b: 'a`, + // - but we can never know this. + + let _: for<'b> fn(&'b u32) = foo(); //~ ERROR mismatched types +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr new file mode 100644 index 000000000..9914783d9 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-fn.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/hrtb-exists-forall-fn.rs:17:34 + | +LL | let _: for<'b> fn(&'b u32) = foo(); + | ^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'b> fn(&'b u32)` + found fn pointer `fn(&u32)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs new file mode 100644 index 000000000..921061916 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.rs @@ -0,0 +1,36 @@ +// Test a case where variance and higher-ranked types interact in surprising ways. +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +trait Trait {} + +fn foo() +where + T: Trait fn(&'b u32)>, +{ +} + +impl<'a> Trait for () {} + +fn main() { + // Here, proving that `(): Trait fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait }` + // - We instantiate `'a` existentially to get `(): Trait` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` -- this does a + // "bidirectional" subtyping check, so we wind up with: + // - `fn(&?a u32) <: for<'b> fn(&'b u32)` :- + // - `&'!b u32 <: &?a u32` + // - `!'b: ?a` -- solveable if `?a` is inferred to `'empty` + // - `for<'b> fn(&'b u32) <: fn(&?a u32)` :- + // - `&?a u32 u32 <: &?b u32` + // - `?a: ?b` -- solveable if `?b` is also inferred to `'empty` + // - So the subtyping check succeeds, somewhat surprisingly. + // This is because we can use `'empty`. + // + // NB. *However*, the reinstated leak-check gives an error here. + + foo::<()>(); + //~^ ERROR implementation of `Trait` is not general enough +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr new file mode 100644 index 000000000..364b613fc --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -0,0 +1,11 @@ +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `()` must implement `Trait fn(&'b u32)>` + = note: ...but it actually implements `Trait`, for some specific lifetime `'0` + +error: aborting due to previous error + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs new file mode 100644 index 000000000..f95496a6c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-covariant.rs @@ -0,0 +1,37 @@ +// Test a case where variance and higher-ranked types interact in surprising ways. +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. +// +// check-pass + +trait Trait {} + +fn foo() +where + T: Trait fn(fn(&'b u32))>, +{ +} + +impl<'a> Trait for () {} + +fn main() { + // Here, proving that `(): Trait fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait }` + // - We instantiate `'a` existentially to get `(): Trait` + // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a + // "bidirectional" subtyping check, so we wind up with: + // - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :- + // - `fn(&!b u32) <: fn(&?a u32)` + // - `&?a u32 <: &!b u32` + // - `?a: !'b` -- solveable if `?a` is inferred to `'static` + // - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :- + // - `fn(&?a u32) <: fn(&?b u32)` + // - `&?b u32 <: &?a u32` + // - `?b: ?a` -- solveable if `?b` is inferred to `'static` + // - So the subtyping check succeeds, somewhat surprisingly. + // This is because we can use `'static`. + + foo::<()>(); +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs new file mode 100644 index 000000000..9b9e4496a --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.rs @@ -0,0 +1,29 @@ +// Test an `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile! +// +// In particular, we test this pattern in trait solving, where it is not connected +// to any part of the source code. + +use std::cell::Cell; + +trait Trait {} + +fn foo() +where + T: Trait fn(Cell<&'b u32>)>, +{ +} + +impl<'a> Trait)> for () {} + +fn main() { + // Here, proving that `(): Trait fn(&'b u32)>` uses the impl: + // + // - The impl provides the clause `forall<'a> { (): Trait }` + // - We instantiate `'a` existentially to get `(): Trait` + // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` + // - This requires (among other things) instantiating `'b` universally, + // yielding `fn(&!b u32)`, in a fresh universe U1 + // - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`. + + foo::<()>(); //~ ERROR implementation of `Trait` is not general enough +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr new file mode 100644 index 000000000..cb2ce8a41 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -0,0 +1,11 @@ +error: implementation of `Trait` is not general enough + --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 + | +LL | foo::<()>(); + | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `()` must implement `Trait fn(Cell<&'b u32>)>` + = note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` + +error: aborting due to previous error + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs b/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs new file mode 100644 index 000000000..ff84ad9d2 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait-object.rs @@ -0,0 +1,27 @@ +// run-pass +// A basic test of using a higher-ranked trait bound. + + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b; + +struct Identity; + +impl<'a, T> FnLike<&'a T, &'a T> for Identity { + fn call(&self, arg: &'a T) -> &'a T { + arg + } +} + +fn call_repeatedly(f: &FnObject) { + let x = 3; + let y = f.call(&x); + assert_eq!(3, *y); +} + +fn main() { + call_repeatedly(&Identity); +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs b/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs new file mode 100644 index 000000000..afab9986c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-fn-like-trait.rs @@ -0,0 +1,27 @@ +// run-pass +// A basic test of using a higher-ranked trait bound. + + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +struct Identity; + +impl<'a, T> FnLike<&'a T, &'a T> for Identity { + fn call(&self, arg: &'a T) -> &'a T { + arg + } +} + +fn call_repeatedly(f: F) + where F : for<'a> FnLike<&'a isize, &'a isize> +{ + let x = 3; + let y = f.call(&x); + assert_eq!(3, *y); +} + +fn main() { + call_repeatedly(Identity); +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs new file mode 100644 index 000000000..f9ae1429e --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.rs @@ -0,0 +1,50 @@ +// Test HRTB supertraits with several levels of expansion required. + +trait Foo<'tcx> +{ + fn foo(&'tcx self) -> &'tcx isize; +} + +trait Bar<'ccx> + : for<'tcx> Foo<'tcx> +{ + fn bar(&'ccx self) -> &'ccx isize; +} + +trait Baz + : for<'ccx> Bar<'ccx> +{ + fn dummy(&self); +} + +trait Qux + : Bar<'static> +{ + fn dummy(&self); +} + +fn want_foo_for_any_tcx(f: &F) + where F : for<'tcx> Foo<'tcx> +{ +} + +fn want_bar_for_any_ccx(b: &B) + where B : for<'ccx> Bar<'ccx> +{ +} + +fn want_baz(b: &B) + where B : Baz +{ + want_foo_for_any_tcx(b); + want_bar_for_any_ccx(b); +} + +fn want_qux(b: &B) + where B : Qux +{ + want_foo_for_any_tcx(b); + want_bar_for_any_ccx(b); //~ ERROR +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr new file mode 100644 index 000000000..8cda76b94 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26 + | +LL | want_bar_for_any_ccx(b); + | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | | + | required by a bound introduced by this call + | +note: required by a bound in `want_bar_for_any_ccx` + --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15 + | +LL | fn want_bar_for_any_ccx(b: &B) + | -------------------- required by a bound in this +LL | where B : for<'ccx> Bar<'ccx> + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` +help: consider further restricting this bound + | +LL | where B : Qux + for<'ccx> Bar<'ccx> + | +++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs new file mode 100644 index 000000000..48ebe5017 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.rs @@ -0,0 +1,48 @@ +// Test a trait (`Bar`) with a higher-ranked supertrait. + +trait Foo<'tcx> +{ + fn foo(&'tcx self) -> &'tcx isize; +} + +trait Bar<'ccx> + : for<'tcx> Foo<'tcx> +{ + fn bar(&'ccx self) -> &'ccx isize; +} + +fn want_foo_for_some_tcx<'x,F>(f: &'x F) + where F : Foo<'x> +{ + want_foo_for_some_tcx(f); + want_foo_for_any_tcx(f); //~ ERROR not satisfied +} + +fn want_foo_for_any_tcx(f: &F) + where F : for<'tcx> Foo<'tcx> +{ + want_foo_for_some_tcx(f); + want_foo_for_any_tcx(f); +} + +fn want_bar_for_some_ccx<'x,B>(b: &B) + where B : Bar<'x> +{ + want_foo_for_some_tcx(b); + want_foo_for_any_tcx(b); + + want_bar_for_some_ccx(b); + want_bar_for_any_ccx(b); //~ ERROR not satisfied +} + +fn want_bar_for_any_ccx(b: &B) + where B : for<'ccx> Bar<'ccx> +{ + want_foo_for_some_tcx(b); + want_foo_for_any_tcx(b); + + want_bar_for_some_ccx(b); + want_bar_for_any_ccx(b); +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr new file mode 100644 index 000000000..88793a152 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied + --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26 + | +LL | want_foo_for_any_tcx(f); + | -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` + | | + | required by a bound introduced by this call + | +note: required by a bound in `want_foo_for_any_tcx` + --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15 + | +LL | fn want_foo_for_any_tcx(f: &F) + | -------------------- required by a bound in this +LL | where F : for<'tcx> Foo<'tcx> + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo_for_any_tcx` +help: consider further restricting this bound + | +LL | where F : Foo<'x> + for<'tcx> Foo<'tcx> + | +++++++++++++++++++++ + +error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied + --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 + | +LL | want_bar_for_any_ccx(b); + | -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` + | | + | required by a bound introduced by this call + | +note: required by a bound in `want_bar_for_any_ccx` + --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15 + | +LL | fn want_bar_for_any_ccx(b: &B) + | -------------------- required by a bound in this +LL | where B : for<'ccx> Bar<'ccx> + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` +help: consider further restricting this bound + | +LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> + | +++++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs b/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs new file mode 100644 index 000000000..89fc4705a --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.rs @@ -0,0 +1,26 @@ +// Test that the `'a` in the where clause correctly links the region +// of the output to the region of the input. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +fn call_repeatedly(f: F) + where F : for<'a> FnLike<&'a isize, &'a isize> +{ + // Result is stored: cannot re-assign `x` + let mut x = 3; + let y = f.call(&x); + x = 5; //~ ERROR cannot assign to `x` because it is borrowed + + // Result is not stored: can re-assign `x` + let mut x = 3; + f.call(&x); + f.call(&x); + f.call(&x); + x = 5; + drop(y); +} + +fn main() { +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr new file mode 100644 index 000000000..4886a3c8b --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr @@ -0,0 +1,14 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/hrtb-identity-fn-borrows.rs:14:5 + | +LL | let y = f.call(&x); + | -- borrow of `x` occurs here +LL | x = 5; + | ^^^^^ assignment to borrowed `x` occurs here +... +LL | drop(y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0506`. diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs b/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs new file mode 100644 index 000000000..8fb4218f8 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.rs @@ -0,0 +1,35 @@ +// Test a case where you have an impl of `Foo` for all `X` that +// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730. + +trait Foo { + fn foo(&self, x: X) { } +} + +fn want_hrtb() + where T : for<'a> Foo<&'a isize> +{ +} + +// AnyInt implements Foo<&'a isize> for any 'a, so it is a match. +struct AnyInt; +impl<'a> Foo<&'a isize> for AnyInt { } +fn give_any() { + want_hrtb::() +} + +// StaticInt only implements Foo<&'static isize>, so it is an error. +struct StaticInt; +impl Foo<&'static isize> for StaticInt { } +fn give_static() { + want_hrtb::() //~ ERROR +} + +// &'a u32 only implements Foo<&'a isize> for specific 'a, so it is an error. +impl<'a> Foo<&'a isize> for &'a u32 { } +fn give_some<'a>() { + want_hrtb::<&'a u32>() + //~^ ERROR lifetime may not live long enough + //~| ERROR implementation of `Foo` is not general enough +} + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr new file mode 100644 index 000000000..31e11e128 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr @@ -0,0 +1,34 @@ +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:24:5 + | +LL | want_hrtb::() + | ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...but it actually implements `Foo<&'static isize>` + +error: lifetime may not live long enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | fn give_some<'a>() { + | -- lifetime `'a` defined here +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-just-for-static.rs:9:15 + | +LL | where T : for<'a> Foo<&'a isize> + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of `Foo` is not general enough + --> $DIR/hrtb-just-for-static.rs:30:5 + | +LL | want_hrtb::<&'a u32>() + | ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<&'0 isize>` would have to be implemented for the type `&u32`, for any lifetime `'0`... + = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs b/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs new file mode 100644 index 000000000..4b096be59 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs @@ -0,0 +1,20 @@ +// Test that Fn-family traits with lifetime parameters shouldn't compile and +// we suggest the usage of higher-rank trait bounds instead. + +fn fa(_: impl Fn<'a>(&'a str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +use std::ops::Fn as AliasedFn; +fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fe(_: F) where F: Fn<'a>(&'a str) -> bool {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr new file mode 100644 index 000000000..e8f6d63b5 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr @@ -0,0 +1,62 @@ +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:4:17 + | +LL | fn fa(_: impl Fn<'a>(&'a str) -> bool) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fa(_: impl Fn<'a>(&'a str) -> bool) {} +LL + fn fa(_: impl for<'a> Fn(&'a str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:7:20 + | +LL | fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} + | ^^^^^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} +LL + fn fb(_: impl for<'a, 'b> FnMut(&'a str, &'b str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:10:41 + | +LL | fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} +LL + fn fc(_: impl std::fmt::Display + for<'a> FnOnce(&'a str) -> bool + std::fmt::Debug) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:14:24 + | +LL | fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} +LL + fn fd(_: impl for<'a> AliasedFn(&'a str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:17:27 + | +LL | fn fe(_: F) where F: Fn<'a>(&'a str) -> bool {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fe(_: F) where F: Fn<'a>(&'a str) -> bool {} +LL + fn fe(_: F) where F: for<'a> Fn(&'a str) -> bool {} + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs b/tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs new file mode 100644 index 000000000..04519f116 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-opt-in-copy.rs @@ -0,0 +1,28 @@ +// run-pass +// Test that we handle binder levels correctly when checking whether a +// type can implement `Copy`. In particular, we had a bug where we failed to +// liberate the late-bound regions from the impl, and thus wound up +// searching for an impl of `for<'tcx> Foo<&'tcx T>`. The impl that +// exists however is `impl Copy for Foo` and the current rules +// did not consider that a match (something I would like to revise in +// a later PR). + +#![allow(dead_code)] + +use std::marker::PhantomData; + +#[derive(Copy, Clone)] +struct Foo { x: T } + +type Ty<'tcx> = &'tcx TyS<'tcx>; + +enum TyS<'tcx> { + Boop(PhantomData<*mut &'tcx ()>) +} + +#[derive(Copy, Clone)] +enum Bar<'tcx> { + Baz(Foo>) +} + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-parse.rs b/tests/ui/higher-rank-trait-bounds/hrtb-parse.rs new file mode 100644 index 000000000..1fab9758c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-parse.rs @@ -0,0 +1,36 @@ +// run-pass +// Test that we can parse all the various places that a `for` keyword +// can appear representing universal quantification. + +// pretty-expanded FIXME #23616 + +#![allow(unused_variables)] +#![allow(dead_code)] + +trait Get { + fn get(&self, arg: A) -> R; +} + +// Parse HRTB with explicit `for` in a where-clause: + +fn foo00(t: T) + where T : for<'a> Get<&'a i32, &'a i32> +{ +} + +fn foo01 Get<&'a i32, &'a i32>>(t: T) +{ +} + +// Parse HRTB with explicit `for` in various sorts of types: + +fn foo10(t: Box Get>) { } +fn foo11(t: Box Fn(i32) -> i32>) { } + +fn foo20(t: for<'a> fn(i32) -> i32) { } +fn foo21(t: for<'a> unsafe fn(i32) -> i32) { } +fn foo22(t: for<'a> extern "C" fn(i32) -> i32) { } +fn foo23(t: for<'a> unsafe extern "C" fn(i32) -> i32) { } + +fn main() { +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr new file mode 100644 index 000000000..a94c80eb3 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.polonius.stderr @@ -0,0 +1,71 @@ +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:16:1 + | +LL | / fn no_hrtb<'b, T>(mut t: T) +LL | | where +LL | | T: Bar<&'b isize>, +LL | | { +... | +LL | | no_hrtb(&mut t); + | | --------------- recursive call site +LL | | } + | |_^ cannot return without recursing + | + = note: `#[warn(unconditional_recursion)]` on by default + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:25:1 + | +LL | / fn bar_hrtb(mut t: T) +LL | | where +LL | | T: for<'b> Bar<&'b isize>, +LL | | { +... | +LL | | bar_hrtb(&mut t); + | | ---------------- recursive call site +LL | | } + | |_^ cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:35:1 + | +LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T) +LL | | where +LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, +LL | | { +... | +LL | | foo_hrtb_bar_not(&mut t); + | | ------------------------ recursive call site +LL | | +LL | | +LL | | } + | |_^ cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + +error: higher-ranked subtype error + --> $DIR/hrtb-perfect-forwarding.rs:43:5 + | +LL | foo_hrtb_bar_not(&mut t); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:48:1 + | +LL | / fn foo_hrtb_bar_hrtb(mut t: T) +LL | | where +LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, +LL | | { +LL | | // OK -- now we have `T : for<'b> Bar<&'b isize>`. +LL | | foo_hrtb_bar_hrtb(&mut t); + | | ------------------------- recursive call site +LL | | } + | |_^ cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to previous error; 4 warnings emitted + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs b/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs new file mode 100644 index 000000000..d45fa183c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.rs @@ -0,0 +1,56 @@ +// Test a case where you have an impl of `Foo` for all `X` that +// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730. + +trait Foo { + fn foo(&mut self, x: X) {} +} + +trait Bar { + fn bar(&mut self, x: X) {} +} + +impl<'a, X, F> Foo for &'a mut F where F: Foo + Bar {} + +impl<'a, X, F> Bar for &'a mut F where F: Bar {} + +fn no_hrtb<'b, T>(mut t: T) //~ WARN function cannot return +where + T: Bar<&'b isize>, +{ + // OK -- `T : Bar<&'b isize>`, and thus the impl above ensures that + // `&mut T : Bar<&'b isize>`. + no_hrtb(&mut t); +} + +fn bar_hrtb(mut t: T) //~ WARN function cannot return +where + T: for<'b> Bar<&'b isize>, +{ + // OK -- `T : for<'b> Bar<&'b isize>`, and thus the impl above + // ensures that `&mut T : for<'b> Bar<&'b isize>`. This is an + // example of a "perfect forwarding" impl. + bar_hrtb(&mut t); +} + +fn foo_hrtb_bar_not<'b, T>(mut t: T) //~ WARN function cannot return +where + T: for<'a> Foo<&'a isize> + Bar<&'b isize>, +{ + // Not OK -- The forwarding impl for `Foo` requires that `Bar` also + // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a + // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where + // clause only specifies `T : Bar<&'b isize>`. + foo_hrtb_bar_not(&mut t); + //~^ ERROR implementation of `Bar` is not general enough + //~^^ ERROR lifetime may not live long enough +} + +fn foo_hrtb_bar_hrtb(mut t: T) //~ WARN function cannot return +where + T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, +{ + // OK -- now we have `T : for<'b> Bar<&'b isize>`. + foo_hrtb_bar_hrtb(&mut t); +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr new file mode 100644 index 000000000..727b9e6be --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr @@ -0,0 +1,79 @@ +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:16:1 + | +LL | / fn no_hrtb<'b, T>(mut t: T) +LL | | where +LL | | T: Bar<&'b isize>, + | |______________________^ cannot return without recursing +... +LL | no_hrtb(&mut t); + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:25:1 + | +LL | / fn bar_hrtb(mut t: T) +LL | | where +LL | | T: for<'b> Bar<&'b isize>, + | |______________________________^ cannot return without recursing +... +LL | bar_hrtb(&mut t); + | ---------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:35:1 + | +LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T) +LL | | where +LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, + | |_______________________________________________^ cannot return without recursing +... +LL | foo_hrtb_bar_not(&mut t); + | ------------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: lifetime may not live long enough + --> $DIR/hrtb-perfect-forwarding.rs:43:5 + | +LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) + | -- lifetime `'b` defined here +... +LL | foo_hrtb_bar_not(&mut t); + | ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static` + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/hrtb-perfect-forwarding.rs:37:8 + | +LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: implementation of `Bar` is not general enough + --> $DIR/hrtb-perfect-forwarding.rs:43:5 + | +LL | foo_hrtb_bar_not(&mut t); + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough + | + = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` + +warning: function cannot return without recursing + --> $DIR/hrtb-perfect-forwarding.rs:48:1 + | +LL | / fn foo_hrtb_bar_hrtb(mut t: T) +LL | | where +LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, + | |_______________________________________________________^ cannot return without recursing +... +LL | foo_hrtb_bar_hrtb(&mut t); + | ------------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 2 previous errors; 4 warnings emitted + diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs b/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs new file mode 100644 index 000000000..42247798f --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus-where-clause.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +// Test that `F : Fn(isize) -> isize + Send` is interpreted as two +// distinct bounds on `F`. + +fn foo1(f: F) + where F : FnOnce(isize) -> isize + Send +{ + bar(f); +} + +fn foo2(f: F) + where F : FnOnce(isize) -> isize + Send +{ + baz(f); +} + +fn bar(f: F) { } + +fn baz isize>(f: F) { } + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs b/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs new file mode 100644 index 000000000..6834c392d --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-precedence-of-plus.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +// Test that `Fn(isize) -> isize + 'static` parses as `(Fn(isize) -> isize) + +// 'static` and not `Fn(isize) -> (isize + 'static)`. The latter would +// cause a compilation error. Issue #18772. + +fn adder(y: isize) -> Box isize + 'static> { + Box::new(move |x| y + x) +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs b/tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs new file mode 100644 index 000000000..b97fdf4df --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-resolve-lifetime.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +// A basic test of using a higher-ranked trait bound. + +// pretty-expanded FIXME #23616 + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b; + +fn main() { +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs b/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs new file mode 100644 index 000000000..d8c726cdd --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-paren-notation.rs @@ -0,0 +1,26 @@ +// run-pass +// A basic test of using a higher-ranked trait bound. + +trait FnLike { + fn call(&self, arg: A) -> R; +} + +type FnObject<'b> = dyn for<'a> FnLike<(&'a i32,), &'a i32> + 'b; + +struct Identity; + +impl<'a, T> FnLike<(&'a T,), &'a T> for Identity { + fn call(&self, (arg,): (&'a T,)) -> &'a T { + arg + } +} + +fn call_repeatedly(f: &FnObject) { + let x = 3; + let y = f.call((&x,)); + assert_eq!(3, *y); +} + +fn main() { + call_repeatedly(&Identity); +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs b/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs new file mode 100644 index 000000000..41ebb3f5a --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-trait-object-passed-to-closure.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// Test that `&PrinterSupport`, which is really short for `&'a +// PrinterSupport<'b>`, gets properly expanded when it appears in a +// closure type. This used to result in messed up De Bruijn indices. + +// pretty-expanded FIXME #23616 + +trait PrinterSupport<'ast> { + fn ast_map(&self) -> Option<&'ast usize> { None } +} + +struct NoAnn<'ast> { + f: Option<&'ast usize> +} + +impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> { +} + +fn foo<'ast, G>(f: Option<&'ast usize>, g: G) where G: FnOnce(&dyn PrinterSupport) { + let annotation = NoAnn { f: f }; + g(&annotation) +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs b/tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs new file mode 100644 index 000000000..88d396101 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs @@ -0,0 +1,46 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// Test what happens when a HR obligation is applied to an impl with +// "outlives" bounds. Currently we're pretty conservative here; this +// will probably improve in time. + +trait Foo { + fn foo(&self, x: X) { } +} + +fn want_foo() + where T : for<'a> Foo<&'a isize> +{ +} + +// Expressed as a where clause + +struct SomeStruct { + x: X +} + +impl<'a,X> Foo<&'a isize> for SomeStruct + where X : 'a +{ +} + +fn one() { + want_foo::>(); +} + +// Expressed as shorthand + +struct AnotherStruct { + x: X +} + +impl<'a,X:'a> Foo<&'a isize> for AnotherStruct +{ +} + +fn two() { + want_foo::>(); +} + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs b/tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs new file mode 100644 index 000000000..a4a8a5ac6 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-unboxed-closure-trait.rs @@ -0,0 +1,11 @@ +// run-pass +// Test HRTB used with the `Fn` trait. + +fn foo(f: F) { + let x = 22; + f(&x); +} + +fn main() { + foo(|x: &isize| println!("{}", *x)); +} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs new file mode 100644 index 000000000..1a9bb2523 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.rs @@ -0,0 +1,7 @@ +fn a() where for T: Copy {} +//~^ ERROR only lifetime parameters can be used in this context + +fn b() where for [(); C]: Copy {} +//~^ ERROR only lifetime parameters can be used in this context + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr new file mode 100644 index 000000000..f31aa5546 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr @@ -0,0 +1,14 @@ +error: only lifetime parameters can be used in this context + --> $DIR/hrtb-wrong-kind.rs:1:18 + | +LL | fn a() where for T: Copy {} + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/hrtb-wrong-kind.rs:4:24 + | +LL | fn b() where for [(); C]: Copy {} + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-rank-trait-bounds/issue-100689.rs b/tests/ui/higher-rank-trait-bounds/issue-100689.rs new file mode 100644 index 000000000..2db7f8a35 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-100689.rs @@ -0,0 +1,29 @@ +// check-pass + +struct Foo<'a> { + foo: &'a mut usize, +} + +trait Bar<'a> { + type FooRef<'b> + where + 'a: 'b; + fn uwu(foo: Foo<'a>, f: impl for<'b> FnMut(Self::FooRef<'b>)); +} +impl<'a> Bar<'a> for () { + type FooRef<'b> + = + &'b Foo<'a> + where + 'a : 'b, + ; + + fn uwu( + foo: Foo<'a>, + mut f: impl for<'b> FnMut(&'b Foo<'a>), //relevant part + ) { + f(&foo); + } +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-102899.rs b/tests/ui/higher-rank-trait-bounds/issue-102899.rs new file mode 100644 index 000000000..952b81584 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-102899.rs @@ -0,0 +1,32 @@ +// check-pass + +pub trait BufferTrait<'buffer> { + type Subset<'channel> + where + 'buffer: 'channel; + + fn for_each_subset(&self, f: F) + where + F: for<'channel> Fn(Self::Subset<'channel>); +} + +pub struct SomeBuffer<'buffer> { + samples: &'buffer [()], +} + +impl<'buffer> BufferTrait<'buffer> for SomeBuffer<'buffer> { + type Subset<'subset> = Subset<'subset> where 'buffer: 'subset; + + fn for_each_subset(&self, _f: F) + where + F: for<'subset> Fn(Subset<'subset>), + { + todo!() + } +} + +pub struct Subset<'subset> { + buffer: &'subset [()], +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-30786.rs b/tests/ui/higher-rank-trait-bounds/issue-30786.rs new file mode 100644 index 000000000..e5f46f711 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-30786.rs @@ -0,0 +1,134 @@ +// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream Option; +} + +// Example stream +pub struct Repeat(u64); + +impl<'a> Stream for &'a mut Repeat { + type Item = &'a u64; + fn next(self) -> Option { + Some(&self.0) + } +} + +pub struct Map { + stream: S, + func: F, +} + +impl<'a, A, F, T> Stream for &'a mut Map +where + &'a mut A: Stream, + F: FnMut(<&'a mut A as Stream>::Item) -> T, +{ + type Item = T; + fn next(self) -> Option { + match self.stream.next() { + Some(item) => Some((self.func)(item)), + None => None, + } + } +} + +pub struct Filter { + stream: S, + func: F, +} + +impl<'a, A, F, T> Stream for &'a mut Filter +where + for<'b> &'b mut A: Stream, // <---- BAD + F: FnMut(&T) -> bool, +{ + type Item = <&'a mut A as Stream>::Item; + fn next(self) -> Option { + while let Some(item) = self.stream.next() { + if (self.func)(&item) { + return Some(item); + } + } + None + } +} + +pub trait StreamExt +where + for<'b> &'b mut Self: Stream, +{ + fn mapx(self, func: F) -> Map + where + Self: Sized, + for<'a> &'a mut Map: Stream, + { + Map { func: func, stream: self } + } + + fn filterx(self, func: F) -> Filter + where + Self: Sized, + for<'a> &'a mut Filter: Stream, + { + Filter { func: func, stream: self } + } + + fn countx(mut self) -> usize + where + Self: Sized, + { + let mut count = 0; + while let Some(_) = self.next() { + count += 1; + } + count + } +} + +impl StreamExt for T where for<'a> &'a mut T: Stream {} + +fn identity(x: &T) -> &T { + x +} + +fn variant1() { + let source = Repeat(10); + + // Here, the call to `mapx` returns a type `T` to which `StreamExt` + // is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold. + // + // More concretely, the type `T` is `Map`, and + // the where clause doesn't hold because the signature of the + // closure gets inferred to a signature like `|&'_ Stream| -> &'_` + // for some specific `'_`, rather than a more generic + // signature. + // + // Why *exactly* we opt for this signature is a bit unclear to me, + // we deduce it somehow from a reuqirement that `Map: Stream` I + // guess. + let map = source.mapx(|x: &_| x); + let filter = map.filterx(|x: &_| true); + //~^ ERROR the method +} + +fn variant2() { + let source = Repeat(10); + + // Here, we use a function, which is not subject to the vagaries + // of closure signature inference. In this case, we get the error + // on `countx` as, I think, the test originally expected. + let map = source.mapx(identity); + let filter = map.filterx(|x: &_| true); + let count = filter.countx(); + //~^ ERROR the method +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-30786.stderr b/tests/ui/higher-rank-trait-bounds/issue-30786.stderr new file mode 100644 index 000000000..0458d2535 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-30786.stderr @@ -0,0 +1,45 @@ +error[E0599]: the method `filterx` exists for struct `Map`, but its trait bounds were not satisfied + --> $DIR/issue-30786.rs:118:22 + | +LL | pub struct Map { + | -------------------- + | | + | method `filterx` not found for this struct + | doesn't satisfy `_: StreamExt` +... +LL | let filter = map.filterx(|x: &_| true); + | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&'a mut &Map: Stream` + `&'a mut &mut Map: Stream` + `&'a mut Map: Stream` + --> $DIR/issue-30786.rs:96:50 + | +LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} + | --------- - ^^^^^^ unsatisfied trait bound introduced here + +error[E0599]: the method `countx` exists for struct `Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied + --> $DIR/issue-30786.rs:130:24 + | +LL | pub struct Filter { + | ----------------------- + | | + | method `countx` not found for this struct + | doesn't satisfy `_: StreamExt` +... +LL | let count = filter.countx(); + | ^^^^^^ method cannot be called due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + `&'a mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream` + --> $DIR/issue-30786.rs:96:50 + | +LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} + | --------- - ^^^^^^ unsatisfied trait bound introduced here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs b/tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs new file mode 100644 index 000000000..2d49151ff --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-36139-normalize-closure-sig.rs @@ -0,0 +1,19 @@ +// run-pass +// Previously the closure's argument would be inferred to +// >::Item, causing an error in MIR type +// checking + +trait ITrait<'a> {type Item;} + +struct S {} + +impl<'a> ITrait<'a> for S { type Item = &'a mut usize; } + +fn m(_: F) + where I: for<'a> ITrait<'a>, + F: for<'a> FnMut(>::Item) { } + + +fn main() { + m::(|x| { *x += 1; }); +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-42114.rs b/tests/ui/higher-rank-trait-bounds/issue-42114.rs new file mode 100644 index 000000000..01515fdc9 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-42114.rs @@ -0,0 +1,20 @@ +// check-pass + +fn lifetime<'a>() +where + &'a (): 'a, +{ + /* do nothing */ +} + +fn doesnt_work() +where + for<'a> &'a (): 'a, +{ + /* do nothing */ +} + +fn main() { + lifetime(); + doesnt_work(); +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-43623.rs b/tests/ui/higher-rank-trait-bounds/issue-43623.rs new file mode 100644 index 000000000..cedcf7c36 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-43623.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait Trait<'a> { + type Assoc; +} + +pub struct Type; + +impl<'a> Trait<'a> for Type { + type Assoc = (); +} + +pub fn break_me(f: F) +where + T: for<'b> Trait<'b>, + F: for<'b> FnMut(>::Assoc), +{ + break_me::; +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-46989.rs b/tests/ui/higher-rank-trait-bounds/issue-46989.rs new file mode 100644 index 000000000..4a09f4be1 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-46989.rs @@ -0,0 +1,40 @@ +// Regression test for #46989: +// +// In the move to universes, this test started passing. +// It is not necessarily WRONG to do so, but it was a bit +// surprising. The reason that it passed is that when we were +// asked to prove that +// +// for<'a> fn(&'a i32): Foo +// +// we were able to use the impl below to prove +// +// fn(&'empty i32): Foo +// +// and then we were able to prove that +// +// fn(&'empty i32) = for<'a> fn(&'a i32) +// +// This last fact is somewhat surprising, but essentially "falls out" +// from handling variance correctly. In particular, consider the subtyping +// relations. First: +// +// fn(&'empty i32) <: for<'a> fn(&'a i32) +// +// This holds because -- intuitively -- a fn that takes a reference but doesn't use +// it can be given a reference with any lifetime. Similarly, the opposite direction: +// +// for<'a> fn(&'a i32) <: fn(&'empty i32) +// +// holds because 'a can be instantiated to 'empty. + +trait Foo {} + +impl Foo for fn(A) {} + +fn assert_foo() {} + +fn main() { + assert_foo::(); + //~^ ERROR implementation of `Foo` is not general enough +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-46989.stderr b/tests/ui/higher-rank-trait-bounds/issue-46989.stderr new file mode 100644 index 000000000..3f874220a --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-46989.stderr @@ -0,0 +1,11 @@ +error: implementation of `Foo` is not general enough + --> $DIR/issue-46989.rs:38:5 + | +LL | assert_foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` + = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` + +error: aborting due to previous error + diff --git a/tests/ui/higher-rank-trait-bounds/issue-57639.rs b/tests/ui/higher-rank-trait-bounds/issue-57639.rs new file mode 100644 index 000000000..392e7233b --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-57639.rs @@ -0,0 +1,29 @@ +// Regression test for #57639: +// +// In the move to universes, this test stopped working. The problem +// was that when the trait solver was asked to prove `for<'a> T::Item: +// Foo<'a>` as part of WF checking, it wound up "eagerly committing" +// to the where clause, which says that `T::Item: Foo<'a>`, but it +// should instead have been using the bound found in the trait +// declaration. Pre-universe, this used to work out ok because we got +// "eager errors" due to the leak check. +// +// See [this comment on GitHub][c] for more details. +// +// check-pass +// +// [c]: https://github.com/rust-lang/rust/issues/57639#issuecomment-455685861 + +trait Foo<'a> {} + +trait Bar { + type Item: for<'a> Foo<'a>; +} + +fn foo<'a, T>(_: T) +where + T: Bar, + T::Item: Foo<'a>, +{} + +fn main() { } diff --git a/tests/ui/higher-rank-trait-bounds/issue-58451.rs b/tests/ui/higher-rank-trait-bounds/issue-58451.rs new file mode 100644 index 000000000..6006a108c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-58451.rs @@ -0,0 +1,13 @@ +// Regression test for #58451: +// +// Error reporting here encountered an ICE in the shift to universes. + +fn f(i: I) +where + I: IntoIterator, + I::Item: for<'a> Into<&'a ()>, +{} + +fn main() { + f(&[f()]); //~ ERROR function takes 1 argument +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-58451.stderr b/tests/ui/higher-rank-trait-bounds/issue-58451.stderr new file mode 100644 index 000000000..0f051be21 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-58451.stderr @@ -0,0 +1,19 @@ +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/issue-58451.rs:12:9 + | +LL | f(&[f()]); + | ^-- an argument is missing + | +note: function defined here + --> $DIR/issue-58451.rs:5:4 + | +LL | fn f(i: I) + | ^ ---- +help: provide the argument + | +LL | f(&[f(/* i */)]); + | ~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/higher-rank-trait-bounds/issue-59311.rs b/tests/ui/higher-rank-trait-bounds/issue-59311.rs new file mode 100644 index 000000000..3ad548450 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-59311.rs @@ -0,0 +1,22 @@ +// Regression test for #59311. The test is taken from +// rust-lang/rust/issues/71546#issuecomment-620638437 +// as they seem to have the same cause. + +// FIXME: It's not clear that this code ought to report +// an error, but the regression test is here to ensure +// that it does not ICE. See discussion on #74889 for details. + +pub trait T { + fn t(&self, _: F) {} +} + +pub fn crash(v: &V) +where + for<'a> &'a V: T + 'static, +{ + v.t(|| {}); + //~^ ERROR: higher-ranked lifetime error + //~| ERROR: higher-ranked lifetime error +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-59311.stderr b/tests/ui/higher-rank-trait-bounds/issue-59311.stderr new file mode 100644 index 000000000..c01ab8e34 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-59311.stderr @@ -0,0 +1,18 @@ +error: higher-ranked lifetime error + --> $DIR/issue-59311.rs:17:5 + | +LL | v.t(|| {}); + | ^^^^^^^^^^ + | + = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:11] well-formed` + +error: higher-ranked lifetime error + --> $DIR/issue-59311.rs:17:9 + | +LL | v.t(|| {}); + | ^^^^^ + | + = note: could not prove `for<'a> &'a V: 'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/higher-rank-trait-bounds/issue-60283.rs b/tests/ui/higher-rank-trait-bounds/issue-60283.rs new file mode 100644 index 000000000..05315b3f9 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-60283.rs @@ -0,0 +1,20 @@ +// check-pass + +pub trait Trait<'a> { + type Item; +} + +impl<'a> Trait<'a> for () { + type Item = (); +} + +pub fn foo(_: T, _: F) +where + T: for<'a> Trait<'a>, + F: for<'a> FnMut(>::Item), +{ +} + +fn main() { + foo((), drop) +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs new file mode 100644 index 000000000..e70f6fc34 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.rs @@ -0,0 +1,54 @@ +trait T0<'a, A> { + type O; +} + +struct L { + f: T, +} + +// explicitly named variants of what one would normally denote by the +// unit type `()`. Why do this? So that we can differentiate them in +// the diagnostic output. +struct Unit1; +struct Unit2; +struct Unit3; +struct Unit4; + +impl<'a, A, T> T0<'a, A> for L +where + T: FnMut(A) -> Unit3, +{ + type O = T::Output; +} + +trait T1: for<'r> Ty<'r> { + fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + where + F: for<'r> T0<'r, (>::V,), O = >::V>, + { + unimplemented!(); + } +} + +trait Ty<'a> { + type V; +} + +fn main() { + let v = Unit2.m( + L { + //~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4` + //~| ERROR type mismatch + f: |x| { + drop(x); + Unit4 + }, + }, + ); +} + +impl<'a> Ty<'a> for Unit2 { + type V = &'a u8; +} + +impl T1 for Unit2 {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr new file mode 100644 index 000000000..810f7c28c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr @@ -0,0 +1,66 @@ +error[E0271]: type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 + | +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | / L { +LL | | +LL | | +LL | | f: |x| { +... | +LL | | }, +LL | | }, + | |_________^ type mismatch resolving `for<'r> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V` + | +note: expected this to be `<_ as Ty<'_>>::V` + --> $DIR/issue-62203-hrtb-ice.rs:21:14 + | +LL | type O = T::Output; + | ^^^^^^^^^ + = note: expected associated type `<_ as Ty<'_>>::V` + found struct `Unit4` + = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4` or calling a method that returns `<_ as Ty<'_>>::V` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:51 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (>::V,), O = >::V>, + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + +error[E0271]: expected `[closure@issue-62203-hrtb-ice.rs:42:16]` to be a closure that returns `Unit3`, but it returns `Unit4` + --> $DIR/issue-62203-hrtb-ice.rs:39:9 + | +LL | let v = Unit2.m( + | - required by a bound introduced by this call +LL | / L { +LL | | +LL | | +LL | | f: |x| { +... | +LL | | }, +LL | | }, + | |_________^ expected struct `Unit3`, found struct `Unit4` + | +note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>` + --> $DIR/issue-62203-hrtb-ice.rs:17:16 + | +LL | impl<'a, A, T> T0<'a, A> for L + | ^^^^^^^^^ ^^^^ +LL | where +LL | T: FnMut(A) -> Unit3, + | ----- unsatisfied trait bound introduced here +note: required by a bound in `T1::m` + --> $DIR/issue-62203-hrtb-ice.rs:27:12 + | +LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 + | - required by a bound in this +LL | where +LL | F: for<'r> T0<'r, (>::V,), O = >::V>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/higher-rank-trait-bounds/issue-88446.rs b/tests/ui/higher-rank-trait-bounds/issue-88446.rs new file mode 100644 index 000000000..571b85317 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-88446.rs @@ -0,0 +1,35 @@ +// check-pass + +trait Yokeable<'a> { + type Output: 'a; +} +impl<'a> Yokeable<'a> for () { + type Output = (); +} + +trait DataMarker<'data> { + type Yokeable: for<'a> Yokeable<'a>; +} +impl<'data> DataMarker<'data> for () { + type Yokeable = (); +} + +struct DataPayload<'data, M>(&'data M); + +impl DataPayload<'static, ()> { + pub fn map_project_with_capture( + _: for<'a> fn( + capture: T, + std::marker::PhantomData<&'a ()>, + ) -> >::Output, + ) -> DataPayload<'static, M2> + where + M2: DataMarker<'static>, + { + todo!() + } +} + +fn main() { + let _: DataPayload<()> = DataPayload::<()>::map_project_with_capture::<_, &()>(|_, _| todo!()); +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs b/tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs new file mode 100644 index 000000000..92b7c5deb --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs @@ -0,0 +1,13 @@ +// Regression test for #88586: a higher-ranked outlives bound on Self in a trait +// definition caused an ICE when debug_assertions were enabled. +// +// Made to pass as part of fixing #98095. +// +// check-pass + +trait A where + for<'a> Self: 'a, +{ +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/issue-90177.rs b/tests/ui/higher-rank-trait-bounds/issue-90177.rs new file mode 100644 index 000000000..b151a9d3a --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-90177.rs @@ -0,0 +1,32 @@ +// check-pass + +trait Base<'f> { + type Assoc; + + fn do_something(&self); +} + +trait ForAnyLifetime: for<'f> Base<'f> {} + +impl ForAnyLifetime for T where T: for<'f> Base<'f> {} + +trait CanBeDynamic: ForAnyLifetime + for<'f> Base<'f, Assoc = ()> {} + +fn foo(a: &dyn CanBeDynamic) { + a.do_something(); +} + +struct S; + +impl<'a> Base<'a> for S { + type Assoc = (); + + fn do_something(&self) {} +} + +impl CanBeDynamic for S {} + +fn main() { + let s = S; + foo(&s); +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-95034.rs b/tests/ui/higher-rank-trait-bounds/issue-95034.rs new file mode 100644 index 000000000..af4946a18 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-95034.rs @@ -0,0 +1,80 @@ +// check-pass +// compile-flags: --edition=2021 --crate-type=lib + +use std::{ + future::Future, + marker::PhantomData, + pin::Pin, + task::{Context, Poll}, +}; + +mod object { + use super::*; + + pub trait Object<'a> { + type Error; + type Future: Future; + fn create() -> Self::Future; + } + + impl<'a> Object<'a> for u8 { + type Error = (); + type Future = Pin>>; + fn create() -> Self::Future { + unimplemented!() + } + } + + impl<'a, E, A: Object<'a, Error = E>> Object<'a> for (A,) { + type Error = (); + type Future = CustomFut<'a, E, A>; + fn create() -> Self::Future { + unimplemented!() + } + } + + pub struct CustomFut<'f, E, A: Object<'f, Error = E>> { + ph: PhantomData<(A::Future,)>, + } + + impl<'f, E, A: Object<'f, Error = E>> Future for CustomFut<'f, E, A> { + type Output = (A,); + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + unimplemented!() + } + } +} + +mod async_fn { + use super::*; + + pub trait AsyncFn { + type Future: Future; + fn call(&self) -> Self::Future; + } + + impl AsyncFn for F + where + F: Fn() -> Fut, + Fut: Future, + { + type Future = Fut; + fn call(&self) -> Self::Future { + (self)() + } + } +} + +pub async fn test() { + use self::{async_fn::AsyncFn, object::Object}; + + async fn create>() { + T::create().await; + } + + async fn call_async_fn(inner: impl AsyncFn) { + inner.call().await; + } + + call_async_fn(create::<(u8,)>).await; +} diff --git a/tests/ui/higher-rank-trait-bounds/issue-95230.rs b/tests/ui/higher-rank-trait-bounds/issue-95230.rs new file mode 100644 index 000000000..92c506eab --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-95230.rs @@ -0,0 +1,7 @@ +// check-pass + +pub struct Bar +where + for<'a> &'a mut Self:; + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs new file mode 100644 index 000000000..f255eac0c --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-44005.rs @@ -0,0 +1,31 @@ +// check-pass + +pub trait Foo<'a> { + type Bar; + fn foo(&'a self) -> Self::Bar; +} + +impl<'a, 'b, T: 'a> Foo<'a> for &'b T { + type Bar = &'a T; + fn foo(&'a self) -> &'a T { + self + } +} + +pub fn uncallable(x: T, f: F) +where + T: for<'a> Foo<'a>, + F: for<'a> Fn(>::Bar), +{ + f(x.foo()); +} + +pub fn catalyst(x: &i32) { + broken(x, |_| {}) +} + +pub fn broken(x: &i32, f: F) { + uncallable(x, |y| f(y)); +} + +fn main() {} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs new file mode 100644 index 000000000..4d38cb19e --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs @@ -0,0 +1,30 @@ +// check-pass + +fn foo(t: T) -> usize +where + for<'a> &'a T: IntoIterator, + for<'a> <&'a T as IntoIterator>::IntoIter: ExactSizeIterator, +{ + t.into_iter().len() +} + +fn main() { + foo::>(vec![]); +} + +mod another { + use std::ops::Deref; + + fn test() + where + T: Deref, + TDeref: ?Sized, + for<'a> &'a TDeref: IntoIterator, + for<'a> <&'a TDeref as IntoIterator>::IntoIter: Clone, + { + } + + fn main() { + test::, _>(); + } +} diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs new file mode 100644 index 000000000..c6f29fa59 --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs @@ -0,0 +1,88 @@ +// check-pass + +// FamilyType (GAT workaround) +pub trait FamilyLt<'a> { + type Out; +} + +struct RefMutFamily(std::marker::PhantomData, ()); +impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily { + type Out = &'a mut T; +} + +pub trait Execute { + type E: Inject; + fn execute(self, value: <::I as FamilyLt>::Out); +} + +pub trait Inject +where + Self: Sized, +{ + type I: for<'a> FamilyLt<'a>; + fn inject(_: &()) -> ::Out; +} + +impl Inject for RefMutFamily { + type I = Self; + fn inject(_: &()) -> ::Out { + unimplemented!() + } +} + +// This struct is only used to give a hint to the compiler about the type `Q` +struct Annotate(std::marker::PhantomData); +impl Annotate { + fn new() -> Self { + Self(std::marker::PhantomData) + } +} + +// This function annotate a closure so it can have Higher-Rank Lifetime Bounds +// +// See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052 +fn annotate(_q: Annotate, func: F) -> impl Execute + 'static +where + F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out) + 'static, + Q: Inject + 'static, +{ + let wrapper: Wrapper = Wrapper(std::marker::PhantomData, func); + wrapper +} + +struct Wrapper(std::marker::PhantomData, F); +impl Execute for Wrapper + where + Q: Inject, + F: for<'r> FnOnce(<::I as FamilyLt<'r>>::Out), +{ + type E = Q; + + fn execute(self, value: <::I as FamilyLt>::Out) { + (self.1)(value) + } +} + +struct Task { + _processor: Box, +} + +// This function consume the closure +fn task

{} + +pub trait Bar { + type Output: 'static; +} + +impl Foo for i32 { } + +impl Foo for A { } + +impl Bar for i32 { + type Output = u32; +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-rfc447-constrained.rs b/tests/ui/coherence/coherence-rfc447-constrained.rs new file mode 100644 index 000000000..9d1d86883 --- /dev/null +++ b/tests/ui/coherence/coherence-rfc447-constrained.rs @@ -0,0 +1,22 @@ +// run-pass +// check that trait matching can handle impls whose types are only +// constrained by a projection. + +trait IsU32 {} +impl IsU32 for u32 {} + +trait Mirror { type Image: ?Sized; } +impl Mirror for T { type Image = T; } + +trait Bar {} +impl, L: Mirror> Bar for V + where U::Image: IsU32 {} + +trait Foo { fn name() -> &'static str; } +impl Foo for u64 { fn name() -> &'static str { "u64" } } +impl Foo for T { fn name() -> &'static str { "Bar" }} + +fn main() { + assert_eq!(::name(), "u64"); + assert_eq!(::name(), "Bar"); +} diff --git a/tests/ui/coherence/coherence-subtyping.rs b/tests/ui/coherence/coherence-subtyping.rs new file mode 100644 index 000000000..b3ed728a8 --- /dev/null +++ b/tests/ui/coherence/coherence-subtyping.rs @@ -0,0 +1,20 @@ +// Test that two distinct impls which match subtypes of one another +// yield coherence errors (or not) depending on the variance. +// +// Note: This scenario is currently accepted, but as part of the +// universe transition (#56105) may eventually become an error. + +// check-pass + +trait TheTrait { + fn foo(&self) {} +} + +impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} + +impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + //~^ WARNING conflicting implementation + //~^^ WARNING this was previously accepted by the compiler but is being phased out +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-subtyping.stderr b/tests/ui/coherence/coherence-subtyping.stderr new file mode 100644 index 000000000..9d90019a5 --- /dev/null +++ b/tests/ui/coherence/coherence-subtyping.stderr @@ -0,0 +1,16 @@ +warning: conflicting implementations of trait `TheTrait` for type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + --> $DIR/coherence-subtyping.rs:15:1 + | +LL | impl TheTrait for for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {} + | ---------------------------------------------------------- first implementation here +LL | +LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + = note: `#[warn(coherence_leak_check)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/coherence/coherence-tuple-conflict.rs b/tests/ui/coherence/coherence-tuple-conflict.rs new file mode 100644 index 000000000..8cc829726 --- /dev/null +++ b/tests/ui/coherence/coherence-tuple-conflict.rs @@ -0,0 +1,20 @@ +use std::fmt::Debug; +use std::default::Default; + +// Test that a blank impl for all T conflicts with an impl for some +// specific T. + +trait MyTrait { + fn get(&self) -> usize; +} + +impl MyTrait for (T,T) { + fn get(&self) -> usize { 0 } +} + +impl MyTrait for (A,B) { +//~^ ERROR E0119 + fn get(&self) -> usize { self.dummy } +} + +fn main() { } diff --git a/tests/ui/coherence/coherence-tuple-conflict.stderr b/tests/ui/coherence/coherence-tuple-conflict.stderr new file mode 100644 index 000000000..09ad5e5b2 --- /dev/null +++ b/tests/ui/coherence/coherence-tuple-conflict.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `(_, _)` + --> $DIR/coherence-tuple-conflict.rs:15:1 + | +LL | impl MyTrait for (T,T) { + | ------------------------- first implementation here +... +LL | impl MyTrait for (A,B) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs new file mode 100644 index 000000000..9859a226e --- /dev/null +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -0,0 +1,18 @@ +// Check that unsafe trait object do not implement themselves +// automatically + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized { + fn call(&self); +} + +fn takes_t(s: S) { + s.call(); +} + +fn takes_t_obj(t: &dyn Trait) { + takes_t(t); //~ ERROR E0277 +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr new file mode 100644 index 000000000..2e2dac288 --- /dev/null +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied + --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13 + | +LL | takes_t(t); + | ------- ^ the trait `Trait` is not implemented for `&dyn Trait` + | | + | required by a bound introduced by this call + | +note: required by a bound in `takes_t` + --> $DIR/coherence-unsafe-trait-object-impl.rs:10:15 + | +LL | fn takes_t(s: S) { + | ^^^^^ required by this bound in `takes_t` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coherence/coherence-vec-local-2.rs b/tests/ui/coherence/coherence-vec-local-2.rs new file mode 100644 index 000000000..47df06bac --- /dev/null +++ b/tests/ui/coherence/coherence-vec-local-2.rs @@ -0,0 +1,14 @@ +// Test that a local, generic type appearing within a +// *non-fundamental* remote type like `Vec` is not considered local. + +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::Remote; + +struct Local(T); + +impl Remote for Vec> { } +//~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-vec-local-2.stderr b/tests/ui/coherence/coherence-vec-local-2.stderr new file mode 100644 index 000000000..95fdf172e --- /dev/null +++ b/tests/ui/coherence/coherence-vec-local-2.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-vec-local-2.rs:11:1 + | +LL | impl Remote for Vec> { } + | ^^^^^^^^^^^^^^^^^^^------------- + | | | + | | `Vec` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-vec-local.rs b/tests/ui/coherence/coherence-vec-local.rs new file mode 100644 index 000000000..130cc39d0 --- /dev/null +++ b/tests/ui/coherence/coherence-vec-local.rs @@ -0,0 +1,14 @@ +// Test that a local type (with no type parameters) appearing within a +// *non-fundamental* remote type like `Vec` is not considered local. + +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::Remote; + +struct Local; + +impl Remote for Vec { } +//~^ ERROR E0117 + +fn main() { } diff --git a/tests/ui/coherence/coherence-vec-local.stderr b/tests/ui/coherence/coherence-vec-local.stderr new file mode 100644 index 000000000..4835e771a --- /dev/null +++ b/tests/ui/coherence/coherence-vec-local.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence-vec-local.rs:11:1 + | +LL | impl Remote for Vec { } + | ^^^^^^^^^^^^^^^^---------- + | | | + | | `Vec` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence-wasm-bindgen.rs b/tests/ui/coherence/coherence-wasm-bindgen.rs new file mode 100644 index 000000000..ee09a7244 --- /dev/null +++ b/tests/ui/coherence/coherence-wasm-bindgen.rs @@ -0,0 +1,37 @@ +// Capture a coherence pattern from wasm-bindgen that we discovered as part of +// future-compatibility warning #56105. This pattern currently receives a lint +// warning but we probably want to support it long term. +// +// Key distinction: we are implementing once for `A` (take ownership) and one +// for `&A` (borrow). +// +// c.f. #56105 + +#![deny(coherence_leak_check)] + +trait IntoWasmAbi { + fn some_method(&self) {} +} + +trait FromWasmAbi {} +trait RefFromWasmAbi {} +trait ReturnWasmAbi {} + +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) +where + A: FromWasmAbi, + R: ReturnWasmAbi, +{ +} + +// Explicitly writing the bound lifetime. +impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) +where + A: RefFromWasmAbi, + R: ReturnWasmAbi, +{ + //~^^^^^ ERROR conflicting implementation + //~| WARNING this was previously accepted +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-wasm-bindgen.stderr b/tests/ui/coherence/coherence-wasm-bindgen.stderr new file mode 100644 index 000000000..89615f0fb --- /dev/null +++ b/tests/ui/coherence/coherence-wasm-bindgen.stderr @@ -0,0 +1,21 @@ +error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn Fn(&_) -> _` + --> $DIR/coherence-wasm-bindgen.rs:28:1 + | +LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b) + | ------------------------------------------------------------ first implementation here +... +LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&dyn Fn(&_) -> _` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: downstream crates may implement trait `FromWasmAbi` for type `&_` + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +note: the lint level is defined here + --> $DIR/coherence-wasm-bindgen.rs:10:9 + | +LL | #![deny(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/coherence/coherence-where-clause.rs b/tests/ui/coherence/coherence-where-clause.rs new file mode 100644 index 000000000..5c40def86 --- /dev/null +++ b/tests/ui/coherence/coherence-where-clause.rs @@ -0,0 +1,38 @@ +// run-pass + +use std::fmt::Debug; +use std::default::Default; + +trait MyTrait { + fn get(&self) -> Self; +} + +impl MyTrait for T + where T : Default +{ + fn get(&self) -> T { + Default::default() + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +struct MyType { + dummy: usize +} + +impl MyTrait for MyType { + fn get(&self) -> MyType { (*self).clone() } +} + +fn test_eq(m: M, n: M) +where M : MyTrait + Debug + PartialEq +{ + assert_eq!(m.get(), n); +} + +pub fn main() { + test_eq(0_usize, 0_usize); + + let value = MyType { dummy: 256 + 22 }; + test_eq(value, value); +} diff --git a/tests/ui/coherence/coherence-with-closure.rs b/tests/ui/coherence/coherence-with-closure.rs new file mode 100644 index 000000000..5b6a62b24 --- /dev/null +++ b/tests/ui/coherence/coherence-with-closure.rs @@ -0,0 +1,14 @@ +// Test that encountering closures during coherence does not cause issues. +#![feature(type_alias_impl_trait)] +type OpaqueClosure = impl Sized; +fn defining_use() -> OpaqueClosure { + || () +} + +struct Wrapper(T); +trait Trait {} +impl Trait for Wrapper {} +impl Trait for Wrapper {} +//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper` + +fn main() {} diff --git a/tests/ui/coherence/coherence-with-closure.stderr b/tests/ui/coherence/coherence-with-closure.stderr new file mode 100644 index 000000000..431108e14 --- /dev/null +++ b/tests/ui/coherence/coherence-with-closure.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` + --> $DIR/coherence-with-closure.rs:11:1 + | +LL | impl Trait for Wrapper {} + | ------------------------------------- first implementation here +LL | impl Trait for Wrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-with-generator.rs b/tests/ui/coherence/coherence-with-generator.rs new file mode 100644 index 000000000..5eb8dc2a4 --- /dev/null +++ b/tests/ui/coherence/coherence-with-generator.rs @@ -0,0 +1,24 @@ +// Test that encountering closures during coherence does not cause issues. +#![feature(type_alias_impl_trait, generators)] +#![cfg_attr(specialized, feature(specialization))] +#![allow(incomplete_features)] + +// revisions: stock specialized +// [specialized]check-pass + +type OpaqueGenerator = impl Sized; +fn defining_use() -> OpaqueGenerator { + || { + for i in 0..10 { + yield i; + } + } +} + +struct Wrapper(T); +trait Trait {} +impl Trait for Wrapper {} +impl Trait for Wrapper {} +//[stock]~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper` + +fn main() {} diff --git a/tests/ui/coherence/coherence-with-generator.stock.stderr b/tests/ui/coherence/coherence-with-generator.stock.stderr new file mode 100644 index 000000000..478ac4912 --- /dev/null +++ b/tests/ui/coherence/coherence-with-generator.stock.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` + --> $DIR/coherence-with-generator.rs:21:1 + | +LL | impl Trait for Wrapper {} + | --------------------------------------- first implementation here +LL | impl Trait for Wrapper {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_copy_like.rs b/tests/ui/coherence/coherence_copy_like.rs new file mode 100644 index 000000000..92af341cc --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +trait MyTrait { } +impl MyTrait for T { } +impl MyTrait for MyType { } +impl<'a> MyTrait for &'a MyType { } +impl MyTrait for Box { } +impl<'a> MyTrait for &'a Box { } + +fn main() { } diff --git a/tests/ui/coherence/coherence_copy_like_err_fundamental_struct.rs b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct.rs new file mode 100644 index 000000000..edee6cd7b --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct.rs @@ -0,0 +1,24 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs +// build-pass (FIXME(62277): could be check-pass?) +// skip-codgen +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +trait MyTrait { fn foo() {} } +impl MyTrait for T { } + +// `MyFundamentalStruct` is declared fundamental, so we can test that +// +// MyFundamentalStruct: !MyTrait +// +// Huzzah. +impl MyTrait for lib::MyFundamentalStruct { } + + +fn main() { } diff --git a/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs new file mode 100644 index 000000000..599c804d2 --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_ref.rs @@ -0,0 +1,21 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// check-pass +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +trait MyTrait { fn foo() {} } +impl MyTrait for T { } + +// `MyFundamentalStruct` is declared fundamental, so we can test that +// +// MyFundamentalStruct<&MyTrait>: !MyTrait +// +// Huzzah. +impl<'a> MyTrait for lib::MyFundamentalStruct<&'a MyType> { } + +fn main() { } diff --git a/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs new file mode 100644 index 000000000..7d851b528 --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.rs @@ -0,0 +1,20 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +trait MyTrait { fn foo() {} } + +impl MyTrait for T { } + +// Tuples are not fundamental. +impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } +//~^ ERROR E0119 + + +fn main() { } diff --git a/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr new file mode 100644 index 000000000..93486fa5f --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFundamentalStruct<(MyType,)>` + --> $DIR/coherence_copy_like_err_fundamental_struct_tuple.rs:16:1 + | +LL | impl MyTrait for T { } + | ---------------------------------- first implementation here +... +LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFundamentalStruct<(MyType,)>` + | + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_copy_like_err_struct.rs b/tests/ui/coherence/coherence_copy_like_err_struct.rs new file mode 100644 index 000000000..fe39370c9 --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_struct.rs @@ -0,0 +1,22 @@ +// aux-build:coherence_copy_like_lib.rs + +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +trait MyTrait { fn foo() {} } +impl MyTrait for T { } + +// `MyStruct` is not declared fundamental, therefore this would +// require that +// +// MyStruct: !MyTrait +// +// which we cannot approve. +impl MyTrait for lib::MyStruct { } +//~^ ERROR E0119 + +fn main() { } diff --git a/tests/ui/coherence/coherence_copy_like_err_struct.stderr b/tests/ui/coherence/coherence_copy_like_err_struct.stderr new file mode 100644 index 000000000..7432733b9 --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_struct.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyStruct` + --> $DIR/coherence_copy_like_err_struct.rs:19:1 + | +LL | impl MyTrait for T { } + | ---------------------------------- first implementation here +... +LL | impl MyTrait for lib::MyStruct { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyStruct` + | + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_copy_like_err_tuple.rs b/tests/ui/coherence/coherence_copy_like_err_tuple.rs new file mode 100644 index 000000000..f63e205c9 --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_tuple.rs @@ -0,0 +1,21 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +trait MyTrait { fn foo() {} } +impl MyTrait for T { } + +// Tuples are not fundamental, therefore this would require that +// +// (MyType,): !MyTrait +// +// which we cannot approve. +impl MyTrait for (MyType,) { } +//~^ ERROR E0119 + +fn main() { } diff --git a/tests/ui/coherence/coherence_copy_like_err_tuple.stderr b/tests/ui/coherence/coherence_copy_like_err_tuple.stderr new file mode 100644 index 000000000..090497ec1 --- /dev/null +++ b/tests/ui/coherence/coherence_copy_like_err_tuple.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `(MyType,)` + --> $DIR/coherence_copy_like_err_tuple.rs:18:1 + | +LL | impl MyTrait for T { } + | ---------------------------------- first implementation here +... +LL | impl MyTrait for (MyType,) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)` + | + = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence_inherent.rs b/tests/ui/coherence/coherence_inherent.rs new file mode 100644 index 000000000..f3ebf0003 --- /dev/null +++ b/tests/ui/coherence/coherence_inherent.rs @@ -0,0 +1,36 @@ +// Tests that methods that implement a trait cannot be invoked +// unless the trait is imported. + +mod Lib { + pub trait TheTrait { + fn the_fn(&self); + } + + pub struct TheStruct; + + impl TheTrait for TheStruct { + fn the_fn(&self) {} + } +} + +mod Import { + // Trait is in scope here: + use Lib::TheStruct; + use Lib::TheTrait; + + fn call_the_fn(s: &TheStruct) { + s.the_fn(); + } +} + +mod NoImport { + // Trait is not in scope here: + use Lib::TheStruct; + + fn call_the_fn(s: &TheStruct) { + s.the_fn(); + //~^ ERROR E0599 + } +} + +fn main() {} diff --git a/tests/ui/coherence/coherence_inherent.stderr b/tests/ui/coherence/coherence_inherent.stderr new file mode 100644 index 000000000..46b128c08 --- /dev/null +++ b/tests/ui/coherence/coherence_inherent.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `the_fn` found for reference `&TheStruct` in the current scope + --> $DIR/coherence_inherent.rs:31:11 + | +LL | s.the_fn(); + | ^^^^^^ method not found in `&TheStruct` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use Lib::TheTrait; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/coherence/coherence_inherent_cc.rs b/tests/ui/coherence/coherence_inherent_cc.rs new file mode 100644 index 000000000..759ada248 --- /dev/null +++ b/tests/ui/coherence/coherence_inherent_cc.rs @@ -0,0 +1,28 @@ +// aux-build:coherence_inherent_cc_lib.rs + +// Tests that methods that implement a trait cannot be invoked +// unless the trait is imported. + +extern crate coherence_inherent_cc_lib; + +mod Import { + // Trait is in scope here: + use coherence_inherent_cc_lib::TheStruct; + use coherence_inherent_cc_lib::TheTrait; + + fn call_the_fn(s: &TheStruct) { + s.the_fn(); + } +} + +mod NoImport { + // Trait is not in scope here: + use coherence_inherent_cc_lib::TheStruct; + + fn call_the_fn(s: &TheStruct) { + s.the_fn(); + //~^ ERROR E0599 + } +} + +fn main() {} diff --git a/tests/ui/coherence/coherence_inherent_cc.stderr b/tests/ui/coherence/coherence_inherent_cc.stderr new file mode 100644 index 000000000..af0ef3b69 --- /dev/null +++ b/tests/ui/coherence/coherence_inherent_cc.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `the_fn` found for reference `&TheStruct` in the current scope + --> $DIR/coherence_inherent_cc.rs:23:11 + | +LL | s.the_fn(); + | ^^^^^^ method not found in `&TheStruct` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use coherence_inherent_cc_lib::TheTrait; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/coherence/coherence_local.rs b/tests/ui/coherence/coherence_local.rs new file mode 100644 index 000000000..ea724ada7 --- /dev/null +++ b/tests/ui/coherence/coherence_local.rs @@ -0,0 +1,20 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// check-pass +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// These are all legal because they are all fundamental types: + +impl lib::MyCopy for MyType { } +impl<'a> lib::MyCopy for &'a MyType { } +impl<'a> lib::MyCopy for &'a Box { } +impl lib::MyCopy for Box { } +impl lib::MyCopy for lib::MyFundamentalStruct { } +impl lib::MyCopy for lib::MyFundamentalStruct> { } + +fn main() {} diff --git a/tests/ui/coherence/coherence_local_err_struct.rs b/tests/ui/coherence/coherence_local_err_struct.rs new file mode 100644 index 000000000..a24038eb2 --- /dev/null +++ b/tests/ui/coherence/coherence_local_err_struct.rs @@ -0,0 +1,18 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// These are all legal because they are all fundamental types: + +// MyStruct is not fundamental. +impl lib::MyCopy for lib::MyStruct { } +//~^ ERROR E0117 + + +fn main() { } diff --git a/tests/ui/coherence/coherence_local_err_struct.stderr b/tests/ui/coherence/coherence_local_err_struct.stderr new file mode 100644 index 000000000..afc6fc45d --- /dev/null +++ b/tests/ui/coherence/coherence_local_err_struct.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/coherence_local_err_struct.rs:14:1 + | +LL | impl lib::MyCopy for lib::MyStruct { } + | ^^^^^^^^^^^^^^^^^^^^^--------------------- + | | | + | | `MyStruct` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence_local_err_tuple.rs b/tests/ui/coherence/coherence_local_err_tuple.rs new file mode 100644 index 000000000..f4033862a --- /dev/null +++ b/tests/ui/coherence/coherence_local_err_tuple.rs @@ -0,0 +1,18 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// aux-build:coherence_copy_like_lib.rs +#![allow(dead_code)] + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// These are all legal because they are all fundamental types: + +// Tuples are not fundamental, so this is not a local impl. +impl lib::MyCopy for (MyType,) { } +//~^ ERROR E0117 + + +fn main() { } diff --git a/tests/ui/coherence/coherence_local_err_tuple.stderr b/tests/ui/coherence/coherence_local_err_tuple.stderr new file mode 100644 index 000000000..a4953859f --- /dev/null +++ b/tests/ui/coherence/coherence_local_err_tuple.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence_local_err_tuple.rs:14:1 + | +LL | impl lib::MyCopy for (MyType,) { } + | ^^^^^^^^^^^^^^^^^^^^^--------- + | | | + | | this is not defined in the current crate because tuples are always foreign + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/coherence_local_ref.rs b/tests/ui/coherence/coherence_local_ref.rs new file mode 100644 index 000000000..2e28839c8 --- /dev/null +++ b/tests/ui/coherence/coherence_local_ref.rs @@ -0,0 +1,14 @@ +// Test that we are able to introduce a negative constraint that +// `MyType: !MyTrait` along with other "fundamental" wrappers. + +// check-pass +// aux-build:coherence_copy_like_lib.rs + +extern crate coherence_copy_like_lib as lib; + +struct MyType { x: i32 } + +// naturally, legal +impl lib::MyCopy for MyType { } + +fn main() { } diff --git a/tests/ui/coherence/conflicting-impl-with-err.rs b/tests/ui/coherence/conflicting-impl-with-err.rs new file mode 100644 index 000000000..3e0234b87 --- /dev/null +++ b/tests/ui/coherence/conflicting-impl-with-err.rs @@ -0,0 +1,16 @@ +struct ErrorKind; +struct Error(ErrorKind); + +impl From for Error { //~ ERROR failed to resolve + fn from(_: nope::Thing) -> Self { //~ ERROR failed to resolve + unimplemented!() + } +} + +impl From for Error { + fn from(_: ErrorKind) -> Self { + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/coherence/conflicting-impl-with-err.stderr b/tests/ui/coherence/conflicting-impl-with-err.stderr new file mode 100644 index 000000000..3009b452d --- /dev/null +++ b/tests/ui/coherence/conflicting-impl-with-err.stderr @@ -0,0 +1,15 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `nope` + --> $DIR/conflicting-impl-with-err.rs:4:11 + | +LL | impl From for Error { + | ^^^^ use of undeclared crate or module `nope` + +error[E0433]: failed to resolve: use of undeclared crate or module `nope` + --> $DIR/conflicting-impl-with-err.rs:5:16 + | +LL | fn from(_: nope::Thing) -> Self { + | ^^^^ use of undeclared crate or module `nope` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/coherence/const-generics-orphan-check-ok.rs b/tests/ui/coherence/const-generics-orphan-check-ok.rs new file mode 100644 index 000000000..217e8aed2 --- /dev/null +++ b/tests/ui/coherence/const-generics-orphan-check-ok.rs @@ -0,0 +1,28 @@ +// check-pass +// aux-build:trait-with-const-param.rs +extern crate trait_with_const_param; +use trait_with_const_param::*; + +// Trivial case, const param after local type. +struct Local1; +impl Trait for Local1 {} + +// Concrete consts behave the same as foreign types, +// so this also trivially works. +impl Trait<3, Local1> for i32 {} + +// This case isn't as trivial as we would forbid type +// parameters here, we do allow const parameters though. +// +// The reason that type parameters are forbidden for +// `impl Trait for i32 {}` is that another +// downstream crate can add `impl Trait for i32`. +// As these two impls would overlap we forbid any impls which +// have a type parameter in front of a local type. +// +// With const parameters this issue does not exist as there are no +// constants local to another downstream crate. +struct Local2; +impl Trait for i32 {} + +fn main() {} diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs new file mode 100644 index 000000000..80bbe387a --- /dev/null +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -0,0 +1,40 @@ +#![feature(extern_types)] + +extern "Rust" { + type OpaqueListContents; +} + +pub struct ListS { + len: usize, + data: [T; 0], + opaque: OpaqueListContents, +} + +pub struct Interned<'a, T>(&'a T); + +impl<'a, T> Clone for Interned<'a, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Copy for Interned<'a, T> {} + +pub struct List<'tcx, T>(Interned<'tcx, ListS>); +//~^ NOTE this field does not implement `Copy` +//~| NOTE the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` + +impl<'tcx, T> Clone for List<'tcx, T> { + fn clone(&self) -> Self { + *self + } +} + +impl<'tcx, T> Copy for List<'tcx, T> {} +//~^ ERROR the trait `Copy` may not be implemented for this type + +fn assert_is_copy() {} + +fn main() { + assert_is_copy::>(); +} diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr new file mode 100644 index 000000000..168ee5726 --- /dev/null +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -0,0 +1,18 @@ +error[E0204]: the trait `Copy` may not be implemented for this type + --> $DIR/deep-bad-copy-reason.rs:33:24 + | +LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); + | ------------------------ this field does not implement `Copy` +... +LL | impl<'tcx, T> Copy for List<'tcx, T> {} + | ^^^^^^^^^^^^^ + | +note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` + --> $DIR/deep-bad-copy-reason.rs:23:26 + | +LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. diff --git a/tests/ui/coherence/impl-foreign-for-foreign.rs b/tests/ui/coherence/impl-foreign-for-foreign.rs new file mode 100644 index 000000000..4c0d46045 --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-foreign.rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for i32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-foreign.stderr b/tests/ui/coherence/impl-foreign-for-foreign.stderr new file mode 100644 index 000000000..93f7a6fdc --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-foreign.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign-for-foreign.rs:10:1 + | +LL | impl Remote for i32 { + | ^^^^^^^^^^^^^^^^--- + | | | + | | `i32` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign-for-foreign[foreign].rs b/tests/ui/coherence/impl-foreign-for-foreign[foreign].rs new file mode 100644 index 000000000..e79f66c0e --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-foreign[foreign].rs @@ -0,0 +1,23 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for i32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1> for f64 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1> for f32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr new file mode 100644 index 000000000..e24537bce --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-foreign[foreign].stderr @@ -0,0 +1,39 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign-for-foreign[foreign].rs:10:1 + | +LL | impl Remote1> for i32 { + | ^^^^^----------------^^^^^--- + | | | | + | | | `i32` is not defined in the current crate + | | `Rc` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign-for-foreign[foreign].rs:14:1 + | +LL | impl Remote1> for f64 { + | ^^^^^------------------^^^^^--- + | | | | + | | | `f64` is not defined in the current crate + | | `Rc` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign-for-foreign[foreign].rs:18:1 + | +LL | impl Remote1> for f32 { + | ^^^^^^^^--------------^^^^^--- + | | | | + | | | `f32` is not defined in the current crate + | | `Rc` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign-for-foreign[local].rs b/tests/ui/coherence/impl-foreign-for-foreign[local].rs new file mode 100644 index 000000000..0b1413edf --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-foreign[local].rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local(Rc); + +impl Remote1> for i32 {} +impl Remote1> for f32 {} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].rs b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].rs new file mode 100644 index 000000000..10bdf2db8 --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].rs @@ -0,0 +1,19 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for Box { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote for Box> { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr new file mode 100644 index 000000000..55ea4409e --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -0,0 +1,27 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/impl-foreign-for-fundamental[foreign].rs:10:1 + | +LL | impl Remote for Box { + | ^^^^^------^^^^^-------- + | | | | + | | | `i32` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/impl-foreign-for-fundamental[foreign].rs:14:1 + | +LL | impl Remote for Box> { + | ^^^^^^^^------^^^^^---------- + | | | | + | | | `Rc` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign-for-fundamental[local].rs b/tests/ui/coherence/impl-foreign-for-fundamental[local].rs new file mode 100644 index 000000000..c3fc0e6b8 --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-fundamental[local].rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote for Box {} +impl Remote for Box> {} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-local.rs b/tests/ui/coherence/impl-foreign-for-local.rs new file mode 100644 index 000000000..04405bc46 --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-local.rs @@ -0,0 +1,13 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for Local {} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs b/tests/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs new file mode 100644 index 000000000..bc1e18b65 --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-locally-defined-fundamental.rs @@ -0,0 +1,15 @@ +#![feature(fundamental)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct Local(T); + +impl Remote for Local<()> {} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs b/tests/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs new file mode 100644 index 000000000..1e11789ef --- /dev/null +++ b/tests/ui/coherence/impl-foreign-for-locally-defined-fundamental[foreign].rs @@ -0,0 +1,15 @@ +#![feature(fundamental)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; + +#[fundamental] +struct MyBox(T); + +impl Remote for MyBox {} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.rs new file mode 100644 index 000000000..99a399ddc --- /dev/null +++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for f64 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr new file mode 100644 index 000000000..65b3aa394 --- /dev/null +++ b/tests/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -0,0 +1,15 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign[foreign]-for-foreign.rs:10:1 + | +LL | impl Remote1 for f64 { + | ^^^^^------------^^^^^--- + | | | | + | | | `f64` is not defined in the current crate + | | `u32` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign[foreign]-for-local.rs b/tests/ui/coherence/impl-foreign[foreign]-for-local.rs new file mode 100644 index 000000000..bc6595bb3 --- /dev/null +++ b/tests/ui/coherence/impl-foreign[foreign]-for-local.rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local { +} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs new file mode 100644 index 000000000..0476cdaff --- /dev/null +++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs @@ -0,0 +1,24 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1> for i32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1>> for f64 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1>> for f32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr new file mode 100644 index 000000000..8e77c13e1 --- /dev/null +++ b/tests/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -0,0 +1,42 @@ +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:11:1 + | +LL | impl Remote1> for i32 { + | ^^^^^--------------------^^^^^--- + | | | | + | | | `i32` is not defined in the current crate + | | `String` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:15:1 + | +LL | impl Remote1>> for f64 { + | ^^^^^---------------------^^^^^--- + | | | | + | | | `f64` is not defined in the current crate + | | `Rc` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for primitive types + --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:19:1 + | +LL | impl Remote1>> for f32 { + | ^^^^^^^^-------------------^^^^^--- + | | | | + | | | `f32` is not defined in the current crate + | | `Rc` is not defined in the current crate + | | `std::alloc::Global` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs b/tests/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs new file mode 100644 index 000000000..7b83b0485 --- /dev/null +++ b/tests/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs @@ -0,0 +1,16 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1> for i32 {} +impl Remote1>> for f64 {} +impl Remote1>> for f32 {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].rs b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].rs new file mode 100644 index 000000000..5282de4b2 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].rs @@ -0,0 +1,21 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; +use std::sync::Arc; + +struct Local; + +impl Remote for Rc { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +impl Remote for Arc { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr new file mode 100644 index 000000000..92346c291 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign-for-foreign[t].stderr @@ -0,0 +1,25 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/impl[t]-foreign-for-foreign[t].rs:11:1 + | +LL | impl Remote for Rc { + | ^^^^^^^^^^^^^^^^--------- + | | | + | | `Rc` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> $DIR/impl[t]-foreign-for-foreign[t].rs:16:1 + | +LL | impl Remote for Arc { + | ^^^^^^^^^^^^^^^^^^^------ + | | | + | | `Arc` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].rs b/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].rs new file mode 100644 index 000000000..6f5605a21 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for + // | some local type (e.g., `MyStruct`) +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr new file mode 100644 index 000000000..249a5c44c --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign-for-fundamental[t].rs:10:6 + | +LL | impl Remote for Box { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs b/tests/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs new file mode 100644 index 000000000..99f3ce447 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs @@ -0,0 +1,12 @@ +// check-pass +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +impl Remote2, Local> for usize { } + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs b/tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs new file mode 100644 index 000000000..81044cd05 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs @@ -0,0 +1,18 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote1 for &'a T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr new file mode 100644 index 000000000..95a20cc5b --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:10:6 + | +LL | impl Remote1 for Box { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:14:10 + | +LL | impl<'a, T> Remote1 for &'a T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.rs b/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.rs new file mode 100644 index 000000000..680ba9f22 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr new file mode 100644 index 000000000..aed184767 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-t.rs:10:6 + | +LL | impl Remote1 for T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs new file mode 100644 index 000000000..fc7649085 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs @@ -0,0 +1,18 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote1<&'a T> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr new file mode 100644 index 000000000..73b1e2c6e --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:10:6 + | +LL | impl Remote1> for u32 { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:14:10 + | +LL | impl<'a, T> Remote1<&'a T> for u32 { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs new file mode 100644 index 000000000..703f25dd6 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs @@ -0,0 +1,17 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl<'a, T> Remote1> for &'a T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} +impl<'a, T> Remote1<&'a T> for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr new file mode 100644 index 000000000..5f89a7aa4 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:10:10 + | +LL | impl<'a, T> Remote1> for &'a T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:13:10 + | +LL | impl<'a, T> Remote1<&'a T> for Box { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs new file mode 100644 index 000000000..ec21fdd4e --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for Local {} + +impl<'a, T> Remote1<&'a T> for Local {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs new file mode 100644 index 000000000..5bdab87bf --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs @@ -0,0 +1,17 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} +impl<'a, T> Remote1<&'a T> for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr new file mode 100644 index 000000000..45559d8b6 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:10:6 + | +LL | impl Remote1> for T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:13:10 + | +LL | impl<'a, T> Remote1<&'a T> for T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs b/tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs new file mode 100644 index 000000000..c9e3594cd --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs @@ -0,0 +1,18 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote2, Local> for u32 { + //~^ ERROR type parameter `T` must be covered by another type +} + +impl<'a, T> Remote2<&'a T, Local> for u32 { + //~^ ERROR type parameter `T` must be covered by another type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr b/tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr new file mode 100644 index 000000000..f94f04c8d --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:10:6 + | +LL | impl Remote2, Local> for u32 { + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:14:10 + | +LL | impl<'a, T> Remote2<&'a T, Local> for u32 { + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs b/tests/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs new file mode 100644 index 000000000..62e69357e --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1> for Rc {} +impl Remote1>> for Rc {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-foreign.rs b/tests/ui/coherence/impl[t]-foreign[local]-for-foreign.rs new file mode 100644 index 000000000..1fec19bba --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-foreign.rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Rc {} +impl Remote1 for Vec> {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs b/tests/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs new file mode 100644 index 000000000..c8ed28be6 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs @@ -0,0 +1,15 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1 for Rc {} +impl Remote1> for Rc {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs b/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs new file mode 100644 index 000000000..f9b88c645 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs @@ -0,0 +1,17 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1 for Box> {} +impl Remote1> for Box> {} +impl Remote1> for Box> {} +impl Remote1>> for Box> {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs new file mode 100644 index 000000000..7709bd9c8 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -0,0 +1,18 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be covered by another type +} + +impl Remote1 for &T { + //~^ ERROR type parameter `T` must be covered by another type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr new file mode 100644 index 000000000..e68f2fe58 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:10:6 + | +LL | impl Remote1 for Box { + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:14:6 + | +LL | impl Remote1 for &T { + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-local.rs b/tests/ui/coherence/impl[t]-foreign[local]-for-local.rs new file mode 100644 index 000000000..9c14eea1b --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-local.rs @@ -0,0 +1,13 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-t.rs b/tests/ui/coherence/impl[t]-foreign[local]-for-t.rs new file mode 100644 index 000000000..eed3a4b5c --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-t.rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be covered by another type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr new file mode 100644 index 000000000..d97e85dcb --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local]-for-t.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/impl[t]-foreign[local]-for-t.rs:10:6 + | +LL | impl Remote1 for T { + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs b/tests/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs new file mode 100644 index 000000000..63c342b76 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs @@ -0,0 +1,17 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local2(Rc); + +impl Remote2> for u32 {} +impl<'a, T> Remote2 for u32 {} +impl Remote2, Box> for u32 {} +impl<'a, T> Remote2, &'a T> for u32 {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.rs b/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.rs new file mode 100644 index 000000000..9bb37c2ba --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr new file mode 100644 index 000000000..44e3b7eed --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-foreign.rs:10:6 + | +LL | impl Remote1 for u32 { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs b/tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs new file mode 100644 index 000000000..79b5aa3fc --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs @@ -0,0 +1,18 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, A, B> Remote1 for &'a B { + //~^ ERROR type parameter `B` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr new file mode 100644 index 000000000..80fb5dbec --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:10:6 + | +LL | impl Remote1 for Box { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:14:13 + | +LL | impl<'a, A, B> Remote1 for &'a B { + | ^ type parameter `B` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-local.rs b/tests/ui/coherence/impl[t]-foreign[t]-for-local.rs new file mode 100644 index 000000000..bc59721c0 --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-local.rs @@ -0,0 +1,13 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local {} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-t.rs b/tests/ui/coherence/impl[t]-foreign[t]-for-t.rs new file mode 100644 index 000000000..bcd6b269a --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-t.rs @@ -0,0 +1,14 @@ +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr new file mode 100644 index 000000000..ff72969dc --- /dev/null +++ b/tests/ui/coherence/impl[t]-foreign[t]-for-t.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-t.rs:10:6 + | +LL | impl Remote1 for T { + | ^ type parameter `T` must be used as the type parameter for some local type + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs new file mode 100644 index 000000000..5b11c78ab --- /dev/null +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -0,0 +1,19 @@ +struct S; + +impl From<()> for S { + fn from(x: ()) -> Self { + S + } +} + +impl From for S +//~^ ERROR conflicting implementations of trait +where + I: Iterator, +{ + fn from(x: I) -> Self { + S + } +} + +fn main() {} diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr new file mode 100644 index 000000000..4ddd712b2 --- /dev/null +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `From<()>` for type `S` + --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 + | +LL | impl From<()> for S { + | ------------------- first implementation here +... +LL | impl From for S + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/issue-85026.rs b/tests/ui/coherence/issue-85026.rs new file mode 100644 index 000000000..8b116545a --- /dev/null +++ b/tests/ui/coherence/issue-85026.rs @@ -0,0 +1,10 @@ +#![feature(auto_traits)] +auto trait AutoTrait {} + +// You cannot impl your own `dyn AutoTrait`. +impl dyn AutoTrait {} //~ERROR E0785 + +// You cannot impl someone else's `dyn AutoTrait` +impl dyn Unpin {} //~ERROR E0785 + +fn main() {} diff --git a/tests/ui/coherence/issue-85026.stderr b/tests/ui/coherence/issue-85026.stderr new file mode 100644 index 000000000..a5da19bbf --- /dev/null +++ b/tests/ui/coherence/issue-85026.stderr @@ -0,0 +1,19 @@ +error[E0785]: cannot define inherent `impl` for a dyn auto trait + --> $DIR/issue-85026.rs:5:6 + | +LL | impl dyn AutoTrait {} + | ^^^^^^^^^^^^^ impl requires at least one non-auto trait + | + = note: define and implement a new trait or type instead + +error[E0785]: cannot define inherent `impl` for a dyn auto trait + --> $DIR/issue-85026.rs:8:6 + | +LL | impl dyn Unpin {} + | ^^^^^^^^^ impl requires at least one non-auto trait + | + = note: define and implement a new trait or type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0785`. diff --git a/tests/ui/coherence/issue-99663-2.rs b/tests/ui/coherence/issue-99663-2.rs new file mode 100644 index 000000000..10a0a5688 --- /dev/null +++ b/tests/ui/coherence/issue-99663-2.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Outer { + i: InnerSend, +} + +type InnerSend = impl Send; + +fn constrain() -> InnerSend { + () +} + +trait SendMustNotImplDrop {} + +#[allow(drop_bounds)] +impl SendMustNotImplDrop for T {} + +impl SendMustNotImplDrop for Outer {} + +fn main() {} diff --git a/tests/ui/coherence/issue-99663.rs b/tests/ui/coherence/issue-99663.rs new file mode 100644 index 000000000..a2d4d398c --- /dev/null +++ b/tests/ui/coherence/issue-99663.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Send { + i: InnerSend, +} + +type InnerSend = impl Sized; + +fn constrain() -> InnerSend { + () +} + +trait SendMustNotImplDrop {} + +#[allow(drop_bounds)] +impl SendMustNotImplDrop for T {} + +impl SendMustNotImplDrop for Send {} + +fn main() {} diff --git a/tests/ui/coherence/re-rebalance-coherence-default-generic-associated-type.rs b/tests/ui/coherence/re-rebalance-coherence-default-generic-associated-type.rs new file mode 100644 index 000000000..d18e3f453 --- /dev/null +++ b/tests/ui/coherence/re-rebalance-coherence-default-generic-associated-type.rs @@ -0,0 +1,26 @@ +// run-pass +// aux-build:re_rebalance_coherence_lib-rpass.rs + +#![allow(dead_code)] +// check that a generic type with a default value from an associated type can be used without +// specifying the value, and without invoking coherence errors. + +extern crate re_rebalance_coherence_lib_rpass as lib; +use lib::*; + +struct MyString {} + +impl LibToOwned for MyString { + type Owned = String; +} + +impl PartialEq for LibCow { + fn eq(&self, _other: &MyString) -> bool { + // Test that the default type is used. + let _s: &String = &self.o; + + false + } +} + +fn main() {} diff --git a/tests/ui/coherence/re-rebalance-coherence.rs b/tests/ui/coherence/re-rebalance-coherence.rs new file mode 100644 index 000000000..38d096b08 --- /dev/null +++ b/tests/ui/coherence/re-rebalance-coherence.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:re_rebalance_coherence_lib.rs + +extern crate re_rebalance_coherence_lib as lib; +use lib::*; + +struct Oracle; +impl Backend for Oracle {} +impl<'a, T:'a, Tab> QueryFragment for BatchInsert<'a, T, Tab> {} + +fn main() {} diff --git a/tests/ui/coherence/strict-coherence-needs-negative-coherence.rs b/tests/ui/coherence/strict-coherence-needs-negative-coherence.rs new file mode 100644 index 000000000..221683dd5 --- /dev/null +++ b/tests/ui/coherence/strict-coherence-needs-negative-coherence.rs @@ -0,0 +1,7 @@ +#![feature(rustc_attrs)] + +#[rustc_strict_coherence] +trait Foo {} +//~^ ERROR to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled + +fn main() {} diff --git a/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr b/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr new file mode 100644 index 000000000..b54729287 --- /dev/null +++ b/tests/ui/coherence/strict-coherence-needs-negative-coherence.stderr @@ -0,0 +1,10 @@ +error: to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled + --> $DIR/strict-coherence-needs-negative-coherence.rs:4:1 + | +LL | #[rustc_strict_coherence] + | ------------------------- due to this attribute +LL | trait Foo {} + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/command-line-diagnostics.rs b/tests/ui/command-line-diagnostics.rs new file mode 100644 index 000000000..248fb83a3 --- /dev/null +++ b/tests/ui/command-line-diagnostics.rs @@ -0,0 +1,7 @@ +// This test checks the output format without the intermediate json representation +// compile-flags: --error-format=human + +pub fn main() { + let x = 42; + x = 43; +} diff --git a/tests/ui/command-line-diagnostics.stderr b/tests/ui/command-line-diagnostics.stderr new file mode 100644 index 000000000..6223ad880 --- /dev/null +++ b/tests/ui/command-line-diagnostics.stderr @@ -0,0 +1,14 @@ +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/command-line-diagnostics.rs:6:5 + | +LL | let x = 42; + | - + | | + | first assignment to `x` + | help: consider making this binding mutable: `mut x` +LL | x = 43; + | ^^^^^^ cannot assign twice to immutable variable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/command/command-argv0.rs b/tests/ui/command/command-argv0.rs new file mode 100644 index 000000000..b782a4fd3 --- /dev/null +++ b/tests/ui/command/command-argv0.rs @@ -0,0 +1,30 @@ +// run-pass + +// ignore-windows - this is a unix-specific test +// ignore-emscripten no processes +// ignore-sgx no processes +use std::env; +use std::os::unix::process::CommandExt; +use std::process::Command; + +fn main() { + let args: Vec<_> = env::args().collect(); + + if args.len() > 1 { + assert_eq!(args[1], "doing-test"); + assert_eq!(args[0], "i have a silly name"); + + println!("passed"); + return; + } + + let output = + Command::new(&args[0]).arg("doing-test").arg0("i have a silly name").output().unwrap(); + assert!( + output.stderr.is_empty(), + "Non-empty stderr: {}", + String::from_utf8_lossy(&output.stderr) + ); + assert!(output.status.success()); + assert_eq!(output.stdout, b"passed\n"); +} diff --git a/tests/ui/command/command-create-pidfd.rs b/tests/ui/command/command-create-pidfd.rs new file mode 100644 index 000000000..4df443c66 --- /dev/null +++ b/tests/ui/command/command-create-pidfd.rs @@ -0,0 +1,56 @@ +// run-pass +// only-linux - pidfds are a linux-specific concept + +#![feature(linux_pidfd)] +#![feature(rustc_private)] + +extern crate libc; + +use std::io::Error; +use std::os::linux::process::{ChildExt, CommandExt}; +use std::process::Command; + +fn has_clone3() -> bool { + let res = unsafe { libc::syscall(libc::SYS_clone3, 0, 0) }; + let err = (res == -1) + .then(|| Error::last_os_error()) + .expect("probe syscall should not succeed"); + + // If the `clone3` syscall is not implemented in the current kernel version it should return an + // `ENOSYS` error. Docker also blocks the whole syscall inside unprivileged containers, and + // returns `EPERM` (instead of `ENOSYS`) when a program tries to invoke the syscall. Because of + // that we need to check for *both* `ENOSYS` and `EPERM`. + // + // Note that Docker's behavior is breaking other projects (notably glibc), so they're planning + // to update their filtering to return `ENOSYS` in a future release: + // + // https://github.com/moby/moby/issues/42680 + // + err.raw_os_error() != Some(libc::ENOSYS) && err.raw_os_error() != Some(libc::EPERM) +} + +fn main() { + // pidfds require the clone3 syscall + if !has_clone3() { + return; + } + + // We don't assert the precise value, since the standard library + // might have opened other file descriptors before our code runs. + let _ = Command::new("echo") + .create_pidfd(true) + .spawn() + .unwrap() + .pidfd().expect("failed to obtain pidfd"); + + let _ = Command::new("echo") + .create_pidfd(false) + .spawn() + .unwrap() + .pidfd().expect_err("pidfd should not have been created when create_pid(false) is set"); + + let _ = Command::new("echo") + .spawn() + .unwrap() + .pidfd().expect_err("pidfd should not have been created"); +} diff --git a/tests/ui/command/command-current-dir.rs b/tests/ui/command/command-current-dir.rs new file mode 100644 index 000000000..5d06fcdeb --- /dev/null +++ b/tests/ui/command/command-current-dir.rs @@ -0,0 +1,50 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia Needs directory creation privilege + +use std::env; +use std::fs; +use std::path::Path; +use std::process::Command; + +fn main() { + // Checks the behavior of current_dir when used with a relative exe path. + let me = env::current_exe().unwrap(); + if matches!(env::args().skip(1).next().as_deref(), Some("current-dir")) { + let cwd = env::current_dir().unwrap(); + assert_eq!(cwd.file_name().unwrap(), "bar"); + std::process::exit(0); + } + let exe = me.file_name().unwrap(); + let cwd = me.parent().unwrap(); + eprintln!("cwd={:?}", cwd); + // Change directory to where the executable is located, since this test + // fundamentally needs to use relative paths. In some cases (like + // remote-test-server), the current_dir can be somewhere else, so make + // sure it is something we can use. We assume we can write to this + // directory. + env::set_current_dir(&cwd).unwrap(); + let foo = cwd.join("foo"); + let bar = cwd.join("bar"); + fs::create_dir_all(&foo).unwrap(); + fs::create_dir_all(&bar).unwrap(); + fs::copy(&me, foo.join(exe)).unwrap(); + + // Unfortunately this is inconsistent based on the platform, see + // https://github.com/rust-lang/rust/issues/37868. On Windows, + // it is relative *before* changing the directory, and on Unix + // it is *after* changing the directory. + let relative_exe = if cfg!(windows) { + Path::new("foo").join(exe) + } else { + Path::new("../foo").join(exe) + }; + + let status = Command::new(relative_exe) + .arg("current-dir") + .current_dir("bar") + .status() + .unwrap(); + assert!(status.success()); +} diff --git a/tests/ui/command/command-exec.rs b/tests/ui/command/command-exec.rs new file mode 100644 index 000000000..032dad184 --- /dev/null +++ b/tests/ui/command/command-exec.rs @@ -0,0 +1,104 @@ +// run-pass + +#![allow(stable_features)] +// ignore-windows - this is a unix-specific test +// ignore-pretty issue #37199 +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia no execvp syscall provided + +#![feature(process_exec)] + +use std::env; +use std::os::unix::process::CommandExt; +use std::process::Command; + +fn main() { + let mut args = env::args(); + let me = args.next().unwrap(); + + if let Some(arg) = args.next() { + match &arg[..] { + "test1" => println!("passed"), + + "exec-test1" => { + let err = Command::new(&me).arg("test1").exec(); + panic!("failed to spawn: {}", err); + } + + "exec-test2" => { + Command::new("/path/to/nowhere").exec(); + println!("passed"); + } + + "exec-test3" => { + Command::new(&me).arg("bad\0").exec(); + println!("passed"); + } + + "exec-test4" => { + Command::new(&me).current_dir("/path/to/nowhere").exec(); + println!("passed"); + } + + "exec-test5" => { + env::set_var("VARIABLE", "ABC"); + Command::new("definitely-not-a-real-binary").env("VARIABLE", "XYZ").exec(); + assert_eq!(env::var("VARIABLE").unwrap(), "ABC"); + println!("passed"); + } + + "exec-test6" => { + let err = Command::new("echo").arg("passed").env_clear().exec(); + panic!("failed to spawn: {}", err); + } + + "exec-test7" => { + let err = Command::new("echo").arg("passed").env_remove("PATH").exec(); + panic!("failed to spawn: {}", err); + } + + _ => panic!("unknown argument: {}", arg), + } + return + } + + let output = Command::new(&me).arg("exec-test1").output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + + let output = Command::new(&me).arg("exec-test2").output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + + let output = Command::new(&me).arg("exec-test3").output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + + let output = Command::new(&me).arg("exec-test4").output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + + let output = Command::new(&me).arg("exec-test5").output().unwrap(); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + + if cfg!(target_os = "linux") { + let output = Command::new(&me).arg("exec-test6").output().unwrap(); + println!("{:?}", output); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + + let output = Command::new(&me).arg("exec-test7").output().unwrap(); + println!("{:?}", output); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"passed\n"); + } +} diff --git a/tests/ui/command/command-pre-exec.rs b/tests/ui/command/command-pre-exec.rs new file mode 100644 index 000000000..d366c5ffb --- /dev/null +++ b/tests/ui/command/command-pre-exec.rs @@ -0,0 +1,106 @@ +// run-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![allow(stable_features)] +// ignore-windows - this is a unix-specific test +// ignore-emscripten no processes +// ignore-sgx no processes +// ignore-fuchsia no execvp syscall +#![feature(process_exec, rustc_private)] + +extern crate libc; + +use std::env; +use std::io::Error; +use std::os::unix::process::CommandExt; +use std::process::Command; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; + +fn main() { + if let Some(arg) = env::args().nth(1) { + match &arg[..] { + "test1" => println!("hello2"), + "test2" => assert_eq!(env::var("FOO").unwrap(), "BAR"), + "test3" => assert_eq!(env::current_dir().unwrap().to_str().unwrap(), "/"), + "empty" => {} + _ => panic!("unknown argument: {}", arg), + } + return; + } + + let me = env::current_exe().unwrap(); + + let output = unsafe { + Command::new(&me) + .arg("test1") + .pre_exec(|| { + println!("hello"); + Ok(()) + }) + .output() + .unwrap() + }; + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(output.stdout, b"hello\nhello2\n"); + + let output = unsafe { + Command::new(&me) + .arg("test3") + .pre_exec(|| { + env::set_current_dir("/").unwrap(); + Ok(()) + }) + .output() + .unwrap() + }; + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert!(output.stdout.is_empty()); + + let output = unsafe { + Command::new(&me) + .arg("bad") + .pre_exec(|| Err(Error::from_raw_os_error(102))) + .output() + .unwrap_err() + }; + assert_eq!(output.raw_os_error(), Some(102)); + + let pid = unsafe { libc::getpid() }; + assert!(pid >= 0); + let output = unsafe { + Command::new(&me) + .arg("empty") + .pre_exec(move || { + let child = libc::getpid(); + assert!(child >= 0); + assert!(pid != child); + Ok(()) + }) + .output() + .unwrap() + }; + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert!(output.stdout.is_empty()); + + let mem = Arc::new(AtomicUsize::new(0)); + let mem2 = mem.clone(); + let output = unsafe { + Command::new(&me) + .arg("empty") + .pre_exec(move || { + assert_eq!(mem2.fetch_add(1, Ordering::SeqCst), 0); + Ok(()) + }) + .output() + .unwrap() + }; + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert!(output.stdout.is_empty()); + assert_eq!(mem.load(Ordering::SeqCst), 0); +} diff --git a/tests/ui/command/command-setgroups.rs b/tests/ui/command/command-setgroups.rs new file mode 100644 index 000000000..aff67f91b --- /dev/null +++ b/tests/ui/command/command-setgroups.rs @@ -0,0 +1,26 @@ +// run-pass +// ignore-windows - this is a unix-specific test +// ignore-emscripten +// ignore-sgx +// ignore-musl - returns dummy result for _SC_NGROUPS_MAX + +#![feature(rustc_private)] +#![feature(setgroups)] + +extern crate libc; +use std::process::Command; +use std::os::unix::process::CommandExt; + +fn main() { + #[cfg(unix)] + run() +} + +#[cfg(unix)] +fn run() { + let max_ngroups = unsafe { libc::sysconf(libc::_SC_NGROUPS_MAX) }; + let max_ngroups = max_ngroups as u32 + 1; + let vec: Vec = (0..max_ngroups).collect(); + let p = Command::new("/bin/id").groups(&vec[..]).spawn(); + assert!(p.is_err()); +} diff --git a/tests/ui/command/command-uid-gid.rs b/tests/ui/command/command-uid-gid.rs new file mode 100644 index 000000000..aa4e2f5b8 --- /dev/null +++ b/tests/ui/command/command-uid-gid.rs @@ -0,0 +1,32 @@ +// run-pass +// ignore-android +// ignore-emscripten +// ignore-sgx +// ignore-fuchsia no '/bin/sh', '/bin/ls' + +#![feature(rustc_private)] + +fn main() { + #[cfg(unix)] + run() +} + +#[cfg(unix)] +fn run() { + extern crate libc; + use std::process::Command; + use std::os::unix::prelude::*; + + let mut p = Command::new("/bin/sh") + .arg("-c").arg("true") + .uid(unsafe { libc::getuid() }) + .gid(unsafe { libc::getgid() }) + .spawn().unwrap(); + assert!(p.wait().unwrap().success()); + + // if we're already root, this isn't a valid test. Most of the bots run + // as non-root though (android is an exception). + if unsafe { libc::getuid() != 0 } { + assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err()); + } +} diff --git a/tests/ui/command/issue-10626.rs b/tests/ui/command/issue-10626.rs new file mode 100644 index 000000000..696a2dd16 --- /dev/null +++ b/tests/ui/command/issue-10626.rs @@ -0,0 +1,26 @@ +// run-pass +// ignore-emscripten no processes +// ignore-sgx no processes + +// Make sure that if a process doesn't have its stdio/stderr descriptors set up +// that we don't die in a large ball of fire + +use std::env; +use std::process::{Command, Stdio}; + +pub fn main () { + let args: Vec = env::args().collect(); + if args.len() > 1 && args[1] == "child" { + for _ in 0..1000 { + println!("hello?"); + } + for _ in 0..1000 { + println!("hello?"); + } + return; + } + + let mut p = Command::new(&args[0]); + p.arg("child").stdout(Stdio::null()).stderr(Stdio::null()); + println!("{:?}", p.spawn().unwrap().wait()); +} diff --git a/tests/ui/commandline-argfile-badutf8.args b/tests/ui/commandline-argfile-badutf8.args new file mode 100644 index 000000000..c070b0c24 --- /dev/null +++ b/tests/ui/commandline-argfile-badutf8.args @@ -0,0 +1,2 @@ +--cfg +unbroken€ \ No newline at end of file diff --git a/tests/ui/commandline-argfile-badutf8.rs b/tests/ui/commandline-argfile-badutf8.rs new file mode 100644 index 000000000..e2984e3ca --- /dev/null +++ b/tests/ui/commandline-argfile-badutf8.rs @@ -0,0 +1,12 @@ +// Check to see if we can get parameters from an @argsfile file +// +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/commandline-argfile-badutf8.stderr b/tests/ui/commandline-argfile-badutf8.stderr new file mode 100644 index 000000000..9af6fc0a5 --- /dev/null +++ b/tests/ui/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/tests/ui/commandline-argfile-missing.rs b/tests/ui/commandline-argfile-missing.rs new file mode 100644 index 000000000..5a6465bd0 --- /dev/null +++ b/tests/ui/commandline-argfile-missing.rs @@ -0,0 +1,14 @@ +// Check to see if we can get parameters from an @argsfile file +// +// normalize-stderr-test: "os error \d+" -> "os error $$ERR" +// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/commandline-argfile-missing.stderr b/tests/ui/commandline-argfile-missing.stderr new file mode 100644 index 000000000..179ad8310 --- /dev/null +++ b/tests/ui/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) + diff --git a/tests/ui/commandline-argfile.args b/tests/ui/commandline-argfile.args new file mode 100644 index 000000000..972938bf6 --- /dev/null +++ b/tests/ui/commandline-argfile.args @@ -0,0 +1,2 @@ +--cfg +unbroken \ No newline at end of file diff --git a/tests/ui/commandline-argfile.rs b/tests/ui/commandline-argfile.rs new file mode 100644 index 000000000..fc1ba0c8d --- /dev/null +++ b/tests/ui/commandline-argfile.rs @@ -0,0 +1,13 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/tests/ui/compare-method/bad-self-type.rs b/tests/ui/compare-method/bad-self-type.rs new file mode 100644 index 000000000..f42a9e49a --- /dev/null +++ b/tests/ui/compare-method/bad-self-type.rs @@ -0,0 +1,26 @@ +use std::future::Future; +use std::task::{Context, Poll}; + +fn main() {} + +struct MyFuture {} + +impl Future for MyFuture { + type Output = (); + fn poll(self, _: &mut Context<'_>) -> Poll<()> { + //~^ ERROR method `poll` has an incompatible type for trait + todo!() + } +} + +trait T { + fn foo(self); + fn bar(self) -> Option<()>; +} + +impl T for MyFuture { + fn foo(self: Box) {} + //~^ ERROR method `foo` has an incompatible type for trait + fn bar(self) {} + //~^ ERROR method `bar` has an incompatible type for trait +} diff --git a/tests/ui/compare-method/bad-self-type.stderr b/tests/ui/compare-method/bad-self-type.stderr new file mode 100644 index 000000000..cad942e64 --- /dev/null +++ b/tests/ui/compare-method/bad-self-type.stderr @@ -0,0 +1,50 @@ +error[E0053]: method `poll` has an incompatible type for trait + --> $DIR/bad-self-type.rs:10:13 + | +LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> { + | ^^^^ + | | + | expected struct `Pin`, found struct `MyFuture` + | help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>` + | + = note: expected signature `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>` + found signature `fn(MyFuture, &mut Context<'_>) -> Poll<_>` + +error[E0053]: method `foo` has an incompatible type for trait + --> $DIR/bad-self-type.rs:22:18 + | +LL | fn foo(self: Box) {} + | ------^^^^^^^^^ + | | | + | | expected struct `MyFuture`, found struct `Box` + | help: change the self-receiver type to match the trait: `self` + | +note: type in trait + --> $DIR/bad-self-type.rs:17:12 + | +LL | fn foo(self); + | ^^^^ + = note: expected signature `fn(MyFuture)` + found signature `fn(Box)` + +error[E0053]: method `bar` has an incompatible type for trait + --> $DIR/bad-self-type.rs:24:18 + | +LL | fn bar(self) {} + | ^ expected enum `Option`, found `()` + | +note: type in trait + --> $DIR/bad-self-type.rs:18:21 + | +LL | fn bar(self) -> Option<()>; + | ^^^^^^^^^^ + = note: expected signature `fn(MyFuture) -> Option<()>` + found signature `fn(MyFuture)` +help: change the output type to match the trait + | +LL | fn bar(self) -> Option<()> {} + | +++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/compare-method/issue-90444.rs b/tests/ui/compare-method/issue-90444.rs new file mode 100644 index 000000000..6c287d9a7 --- /dev/null +++ b/tests/ui/compare-method/issue-90444.rs @@ -0,0 +1,17 @@ +pub struct A; +impl From for A { + fn from(_: fn((), (), &mut ())) -> Self { + //~^ error: method `from` has an incompatible type for trait + loop {} + } +} + +pub struct B; +impl From for B { + fn from(_: fn((), (), u64)) -> Self { + //~^ error: method `from` has an incompatible type for trait + loop {} + } +} + +fn main() {} diff --git a/tests/ui/compare-method/issue-90444.stderr b/tests/ui/compare-method/issue-90444.stderr new file mode 100644 index 000000000..52e23d03b --- /dev/null +++ b/tests/ui/compare-method/issue-90444.stderr @@ -0,0 +1,27 @@ +error[E0053]: method `from` has an incompatible type for trait + --> $DIR/issue-90444.rs:3:16 + | +LL | fn from(_: fn((), (), &mut ())) -> Self { + | ^^^^^^^^^^^^^^^^^^^ + | | + | types differ in mutability + | help: change the parameter type to match the trait: `for<'a> fn((), (), &'a ())` + | + = note: expected signature `fn(for<'a> fn((), (), &'a ())) -> A` + found signature `fn(for<'a> fn((), (), &'a mut ())) -> A` + +error[E0053]: method `from` has an incompatible type for trait + --> $DIR/issue-90444.rs:11:16 + | +LL | fn from(_: fn((), (), u64)) -> Self { + | ^^^^^^^^^^^^^^^ + | | + | expected `u32`, found `u64` + | help: change the parameter type to match the trait: `fn((), (), u32)` + | + = note: expected signature `fn(fn((), (), u32)) -> B` + found signature `fn(fn((), (), u64)) -> B` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/compare-method/proj-outlives-region.rs b/tests/ui/compare-method/proj-outlives-region.rs new file mode 100644 index 000000000..969bc566d --- /dev/null +++ b/tests/ui/compare-method/proj-outlives-region.rs @@ -0,0 +1,14 @@ +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized, U> { + fn foo() where T: 'a; +} + +// `U::Item: 'a` does not imply that `U: 'a` +impl<'a, U: Iterator> Master<'a, U::Item, U> for () { + fn foo() where U: 'a { } //~ ERROR E0276 +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/compare-method/proj-outlives-region.stderr b/tests/ui/compare-method/proj-outlives-region.stderr new file mode 100644 index 000000000..797a81679 --- /dev/null +++ b/tests/ui/compare-method/proj-outlives-region.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/proj-outlives-region.rs:9:23 + | +LL | fn foo() where T: 'a; + | --------------------- definition of `foo` from trait +... +LL | fn foo() where U: 'a { } + | ^^ impl has extra requirement `U: 'a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/region-extra-2.rs b/tests/ui/compare-method/region-extra-2.rs new file mode 100644 index 000000000..3d57b544e --- /dev/null +++ b/tests/ui/compare-method/region-extra-2.rs @@ -0,0 +1,15 @@ +// Regression test for issue #22779. An extra where clause was +// permitted on the impl that is not present on the trait. + +trait Tr<'a, T> { + fn renew<'b: 'a>(self) -> &'b mut [T]; +} + +impl<'a, T> Tr<'a, T> for &'a mut [T] { + fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { + //~^ ERROR E0276 + &mut self[..] + } +} + +fn main() { } diff --git a/tests/ui/compare-method/region-extra-2.stderr b/tests/ui/compare-method/region-extra-2.stderr new file mode 100644 index 000000000..eb19d57ab --- /dev/null +++ b/tests/ui/compare-method/region-extra-2.stderr @@ -0,0 +1,17 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/region-extra-2.rs:9:53 + | +LL | fn renew<'b: 'a>(self) -> &'b mut [T]; + | -------------------------------------- definition of `renew` from trait +... +LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { + | ^^ impl has extra requirement `'a: 'b` + | +help: copy the `where` clause predicates from the trait + | +LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'b: 'a { + | ~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/region-extra.rs b/tests/ui/compare-method/region-extra.rs new file mode 100644 index 000000000..1070cb845 --- /dev/null +++ b/tests/ui/compare-method/region-extra.rs @@ -0,0 +1,14 @@ +// Test that you cannot add an extra where clause in the impl relating +// two regions. + +trait Master<'a, 'b> { + fn foo(); +} + +impl<'a, 'b> Master<'a, 'b> for () { + fn foo() where 'a: 'b { } //~ ERROR impl has stricter +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/compare-method/region-extra.stderr b/tests/ui/compare-method/region-extra.stderr new file mode 100644 index 000000000..1a471e18d --- /dev/null +++ b/tests/ui/compare-method/region-extra.stderr @@ -0,0 +1,18 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/region-extra.rs:9:24 + | +LL | fn foo(); + | --------- definition of `foo` from trait +... +LL | fn foo() where 'a: 'b { } + | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - fn foo() where 'a: 'b { } +LL + fn foo() { } + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/region-unrelated.rs b/tests/ui/compare-method/region-unrelated.rs new file mode 100644 index 000000000..9730c9dfe --- /dev/null +++ b/tests/ui/compare-method/region-unrelated.rs @@ -0,0 +1,15 @@ +// Test that we elaborate `Type: 'region` constraints and infer various important things. + +trait Master<'a, T: ?Sized, U> { + fn foo() where T: 'a; +} + +// `U: 'a` does not imply `V: 'a` +impl<'a, U, V> Master<'a, U, V> for () { + fn foo() where V: 'a { } + //~^ ERROR impl has stricter requirements than trait +} + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/ui/compare-method/region-unrelated.stderr b/tests/ui/compare-method/region-unrelated.stderr new file mode 100644 index 000000000..f7ae6f944 --- /dev/null +++ b/tests/ui/compare-method/region-unrelated.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/region-unrelated.rs:9:23 + | +LL | fn foo() where T: 'a; + | --------------------- definition of `foo` from trait +... +LL | fn foo() where V: 'a { } + | ^^ impl has extra requirement `V: 'a` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/reordered-type-param.rs b/tests/ui/compare-method/reordered-type-param.rs new file mode 100644 index 000000000..a858b66d7 --- /dev/null +++ b/tests/ui/compare-method/reordered-type-param.rs @@ -0,0 +1,19 @@ +// Tests that ty params get matched correctly when comparing +// an impl against a trait +// +// cc #26111 + +trait A { + fn b(&self, x: C) -> C; +} + +struct E { + f: isize +} + +impl A for E { + // n.b. The error message is awful -- see #3404 + fn b(&self, _x: G) -> G { panic!() } //~ ERROR method `b` has an incompatible type +} + +fn main() {} diff --git a/tests/ui/compare-method/reordered-type-param.stderr b/tests/ui/compare-method/reordered-type-param.stderr new file mode 100644 index 000000000..1552d542d --- /dev/null +++ b/tests/ui/compare-method/reordered-type-param.stderr @@ -0,0 +1,24 @@ +error[E0053]: method `b` has an incompatible type for trait + --> $DIR/reordered-type-param.rs:16:30 + | +LL | fn b(&self, _x: G) -> G { panic!() } + | - - ^ + | | | | + | | | expected type parameter `F`, found type parameter `G` + | | | help: change the parameter type to match the trait: `F` + | | found type parameter + | expected type parameter + | +note: type in trait + --> $DIR/reordered-type-param.rs:7:29 + | +LL | fn b(&self, x: C) -> C; + | ^ + = note: expected signature `fn(&E, F) -> F` + found signature `fn(&E, G) -> G` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/compare-method/trait-bound-on-type-parameter.rs b/tests/ui/compare-method/trait-bound-on-type-parameter.rs new file mode 100644 index 000000000..5359001ea --- /dev/null +++ b/tests/ui/compare-method/trait-bound-on-type-parameter.rs @@ -0,0 +1,18 @@ +// Tests that impl can't add extra `F: Sync` bound aren't *more* restrictive +// than the trait method it's implementing. +// +// Regr test for #26111. + +trait A { + fn b(&self, x: C) -> C; +} + +struct E { + f: isize +} + +impl A for E { + fn b(&self, _x: F) -> F { panic!() } //~ ERROR E0276 +} + +fn main() {} diff --git a/tests/ui/compare-method/trait-bound-on-type-parameter.stderr b/tests/ui/compare-method/trait-bound-on-type-parameter.stderr new file mode 100644 index 000000000..ce6885c15 --- /dev/null +++ b/tests/ui/compare-method/trait-bound-on-type-parameter.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/trait-bound-on-type-parameter.rs:15:13 + | +LL | fn b(&self, x: C) -> C; + | ---------------------------- definition of `b` from trait +... +LL | fn b(&self, _x: F) -> F { panic!() } + | ^^^^ impl has extra requirement `F: Sync` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/traits-misc-mismatch-1.rs b/tests/ui/compare-method/traits-misc-mismatch-1.rs new file mode 100644 index 000000000..0da4aba30 --- /dev/null +++ b/tests/ui/compare-method/traits-misc-mismatch-1.rs @@ -0,0 +1,71 @@ +// +// Make sure rustc checks the type parameter bounds in implementations of traits, +// see #2687 + +use std::marker; + +trait A { } + +trait B: A {} + +trait C: A {} + +trait Foo { + fn test_error1_fn(&self); + fn test_error2_fn(&self); + fn test_error3_fn(&self); + fn test3_fn(&self); + fn test4_fn(&self); + fn test_error5_fn(&self); + fn test6_fn(&self); + fn test_error7_fn(&self); + fn test_error8_fn(&self); +} + +impl Foo for isize { + // invalid bound for T, was defined as Eq in trait + fn test_error1_fn(&self) {} + //~^ ERROR E0276 + + // invalid bound for T, was defined as Eq + Ord in trait + fn test_error2_fn(&self) {} + //~^ ERROR E0276 + + // invalid bound for T, was defined as Eq + Ord in trait + fn test_error3_fn(&self) {} + //~^ ERROR E0276 + + // multiple bounds, same order as in trait + fn test3_fn(&self) {} + + // multiple bounds, different order as in trait + fn test4_fn(&self) {} + + // parameters in impls must be equal or more general than in the defining trait + fn test_error5_fn(&self) {} + //~^ ERROR E0276 + + // bound `std::cmp::Eq` not enforced by this implementation, but this is OK + fn test6_fn(&self) {} + + fn test_error7_fn(&self) {} + //~^ ERROR E0276 + + fn test_error8_fn(&self) {} + //~^ ERROR E0276 +} + +trait Getter { + fn get(&self) -> T { loop { } } +} + +trait Trait { + fn method>(&self); +} + +impl Trait for usize { + fn method>(&self) {} + //~^ ERROR E0276 +} + +fn main() {} diff --git a/tests/ui/compare-method/traits-misc-mismatch-1.stderr b/tests/ui/compare-method/traits-misc-mismatch-1.stderr new file mode 100644 index 000000000..805c04536 --- /dev/null +++ b/tests/ui/compare-method/traits-misc-mismatch-1.stderr @@ -0,0 +1,66 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:27:26 + | +LL | fn test_error1_fn(&self); + | -------------------------------- definition of `test_error1_fn` from trait +... +LL | fn test_error1_fn(&self) {} + | ^^^ impl has extra requirement `T: Ord` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:31:31 + | +LL | fn test_error2_fn(&self); + | -------------------------------------- definition of `test_error2_fn` from trait +... +LL | fn test_error2_fn(&self) {} + | ^ impl has extra requirement `T: B` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:35:26 + | +LL | fn test_error3_fn(&self); + | -------------------------------------- definition of `test_error3_fn` from trait +... +LL | fn test_error3_fn(&self) {} + | ^ impl has extra requirement `T: B` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:45:26 + | +LL | fn test_error5_fn(&self); + | ------------------------------- definition of `test_error5_fn` from trait +... +LL | fn test_error5_fn(&self) {} + | ^ impl has extra requirement `T: B` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:51:30 + | +LL | fn test_error7_fn(&self); + | ------------------------------- definition of `test_error7_fn` from trait +... +LL | fn test_error7_fn(&self) {} + | ^^ impl has extra requirement `T: Eq` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:54:26 + | +LL | fn test_error8_fn(&self); + | ------------------------------- definition of `test_error8_fn` from trait +... +LL | fn test_error8_fn(&self) {} + | ^ impl has extra requirement `T: C` + +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-1.rs:67:18 + | +LL | fn method>(&self); + | ---------------------------------- definition of `method` from trait +... +LL | fn method>(&self) {} + | ^^^^^^^^^^^^^ impl has extra requirement `G: Getter` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compare-method/traits-misc-mismatch-2.rs b/tests/ui/compare-method/traits-misc-mismatch-2.rs new file mode 100644 index 000000000..d7f31c1d9 --- /dev/null +++ b/tests/ui/compare-method/traits-misc-mismatch-2.rs @@ -0,0 +1,23 @@ +// Issue #5886: a complex instance of issue #2687. + +trait Iterator { + fn next(&mut self) -> Option; +} + +trait IteratorUtil: Sized +{ + fn zip>(self, other: U) -> ZipIterator; +} + +impl> IteratorUtil for T { + fn zip>(self, other: U) -> ZipIterator { + //~^ ERROR E0276 + ZipIterator{a: self, b: other} + } +} + +struct ZipIterator { + a: T, b: U +} + +fn main() {} diff --git a/tests/ui/compare-method/traits-misc-mismatch-2.stderr b/tests/ui/compare-method/traits-misc-mismatch-2.stderr new file mode 100644 index 000000000..36bb764d4 --- /dev/null +++ b/tests/ui/compare-method/traits-misc-mismatch-2.stderr @@ -0,0 +1,12 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/traits-misc-mismatch-2.rs:13:18 + | +LL | fn zip>(self, other: U) -> ZipIterator; + | ------------------------------------------------------------------ definition of `zip` from trait +... +LL | fn zip>(self, other: U) -> ZipIterator { + | ^^^^^^^^^^^ impl has extra requirement `U: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/compile_error_macro.rs b/tests/ui/compile_error_macro.rs new file mode 100644 index 000000000..3f7b57cd0 --- /dev/null +++ b/tests/ui/compile_error_macro.rs @@ -0,0 +1,3 @@ +fn main() { + compile_error!("a very descriptive error message"); //~ ERROR: a very descriptive error message +} diff --git a/tests/ui/compile_error_macro.stderr b/tests/ui/compile_error_macro.stderr new file mode 100644 index 000000000..91ebcaa6e --- /dev/null +++ b/tests/ui/compile_error_macro.stderr @@ -0,0 +1,8 @@ +error: a very descriptive error message + --> $DIR/compile_error_macro.rs:2:5 + | +LL | compile_error!("a very descriptive error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/compiletest-self-test/compile-flags-last.rs b/tests/ui/compiletest-self-test/compile-flags-last.rs new file mode 100644 index 000000000..232df10f1 --- /dev/null +++ b/tests/ui/compiletest-self-test/compile-flags-last.rs @@ -0,0 +1,7 @@ +// Check that the arguments provided through `// compile-flags` are added last to the command line +// in UI tests. To ensure that we invoke rustc with a flag that expects an argument withut actually +// providing it. If the compile-flags are not last, the test will fail as rustc will interpret the +// next flag as the argument of this flag. +// +// compile-flags: --cap-lints +// error-pattern: Argument to option 'cap-lints' missing diff --git a/tests/ui/compiletest-self-test/compile-flags-last.stderr b/tests/ui/compiletest-self-test/compile-flags-last.stderr new file mode 100644 index 000000000..d8d40a7d9 --- /dev/null +++ b/tests/ui/compiletest-self-test/compile-flags-last.stderr @@ -0,0 +1,2 @@ +error: Argument to option 'cap-lints' missing + diff --git a/tests/ui/compiletest-self-test/ui-testing-optout.rs b/tests/ui/compiletest-self-test/ui-testing-optout.rs new file mode 100644 index 000000000..88e811583 --- /dev/null +++ b/tests/ui/compiletest-self-test/ui-testing-optout.rs @@ -0,0 +1,94 @@ +// compile-flags: -Z ui-testing=no + +// Line number < 10 +type A = B; //~ ERROR + +// Line number >=10, <100 +type C = D; //~ ERROR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Line num >=100 +type E = F; //~ ERROR + +fn main() {} diff --git a/tests/ui/compiletest-self-test/ui-testing-optout.stderr b/tests/ui/compiletest-self-test/ui-testing-optout.stderr new file mode 100644 index 000000000..652c472c0 --- /dev/null +++ b/tests/ui/compiletest-self-test/ui-testing-optout.stderr @@ -0,0 +1,27 @@ +error[E0412]: cannot find type `B` in this scope + --> $DIR/ui-testing-optout.rs:4:10 + | +4 | type A = B; + | ^ not found in this scope + +error[E0412]: cannot find type `D` in this scope + --> $DIR/ui-testing-optout.rs:7:10 + | +4 | type A = B; + | ----------- similarly named type alias `A` defined here +... +7 | type C = D; + | ^ help: a type alias with a similar name exists: `A` + +error[E0412]: cannot find type `F` in this scope + --> $DIR/ui-testing-optout.rs:92:10 + | +4 | type A = B; + | ----------- similarly named type alias `A` defined here +... +92 | type E = F; + | ^ help: a type alias with a similar name exists: `A` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/complex.rs b/tests/ui/complex.rs new file mode 100644 index 000000000..9b11ca67e --- /dev/null +++ b/tests/ui/complex.rs @@ -0,0 +1,38 @@ +// run-pass + +#![allow(unconditional_recursion)] +#![allow(non_camel_case_types)] +#![allow(dead_code)] +#![allow(unused_mut)] + + + +type t = isize; + +fn nothing() { } + +fn putstr(_s: String) { } + +fn putint(_i: isize) { + let mut i: isize = 33; + while i < 36 { putstr("hi".to_string()); i = i + 1; } +} + +fn zerg(i: isize) -> isize { return i; } + +fn foo(x: isize) -> isize { + let mut y: t = x + 2; + putstr("hello".to_string()); + while y < 10 { putint(y); if y * 3 == 4 { y = y + 2; nothing(); } } + let mut z: t; + z = 0x55; + foo(z); + return 0; +} + +pub fn main() { + let x: isize = 2 + 2; + println!("{}", x); + println!("hello, world"); + println!("{}", 10); +} diff --git a/tests/ui/conditional-compilation/auxiliary/namespaced_enums.rs b/tests/ui/conditional-compilation/auxiliary/namespaced_enums.rs new file mode 100644 index 000000000..d3548c76c --- /dev/null +++ b/tests/ui/conditional-compilation/auxiliary/namespaced_enums.rs @@ -0,0 +1,10 @@ +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} + pub fn bar(&self) {} +} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs new file mode 100644 index 000000000..d20e79b9d --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a(b=c) +// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-1.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-1.stderr new file mode 100644 index 000000000..3a12e9786 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-1.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs new file mode 100644 index 000000000..48d656a4a --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a{b} +// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-2.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-2.stderr new file mode 100644 index 000000000..b92e1fd3d --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-2.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs new file mode 100644 index 000000000..96ac7828c --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-3.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a::b +// error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier) +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-3.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-3.stderr new file mode 100644 index 000000000..5412f7ffd --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-3.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a::b` (argument key must be an identifier) + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs new file mode 100644 index 000000000..e7dfa17b4 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a(b) +// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-4.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-4.stderr new file mode 100644 index 000000000..6853a69b9 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-4.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs new file mode 100644 index 000000000..a939f4510 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-5.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a=10 +// error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string) +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-5.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-5.stderr new file mode 100644 index 000000000..aafc4e898 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-5.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a=10` (argument value must be a string) + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs new file mode 100644 index 000000000..9fa726f93 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a{ +// error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-6.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-6.stderr new file mode 100644 index 000000000..7d2087b4b --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-6.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs new file mode 100644 index 000000000..149142f63 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-7.rs @@ -0,0 +1,5 @@ +// Regression test for issue #89358. + +// compile-flags: --cfg a" +// error-pattern: unterminated double quote string +// error-pattern: this error occurred on the command line diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-7.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-7.stderr new file mode 100644 index 000000000..919709c84 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-7.stderr @@ -0,0 +1,4 @@ +error[E0765]: unterminated double quote string + | + = note: this error occurred on the command line: `--cfg=a"` + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs new file mode 100644 index 000000000..1d7fa7885 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg ) +// error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-8.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-8.stderr new file mode 100644 index 000000000..7bb181412 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-8.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) + diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs new file mode 100644 index 000000000..628b335c8 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs @@ -0,0 +1,4 @@ +// Test for missing quotes around value, issue #66450. +// compile-flags: --cfg key=value +// error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-9.stderr b/tests/ui/conditional-compilation/cfg-arg-invalid-9.stderr new file mode 100644 index 000000000..985b52522 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-9.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") + diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs new file mode 100644 index 000000000..898c5bac8 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.rs @@ -0,0 +1,9 @@ +// +// error-pattern: `main` function not found +// compile-flags: --cfg foo + +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr new file mode 100644 index 000000000..d61872c48 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -0,0 +1,9 @@ +error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` + --> $DIR/cfg-attr-cfg-2.rs:9:14 + | +LL | fn main() { } + | ^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/conditional-compilation/cfg-attr-crate-2.rs b/tests/ui/conditional-compilation/cfg-attr-crate-2.rs new file mode 100644 index 000000000..7dbeba53a --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-crate-2.rs @@ -0,0 +1,8 @@ +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +// compile-flags: --cfg broken + +#![crate_type = "lib"] +#![cfg_attr(broken, no_core)] //~ ERROR the `#[no_core]` attribute is an experimental feature + +pub struct S {} diff --git a/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr b/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr new file mode 100644 index 000000000..4997ca4db --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-crate-2.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_core]` attribute is an experimental feature + --> $DIR/cfg-attr-crate-2.rs:6:21 + | +LL | #![cfg_attr(broken, no_core)] + | ^^^^^^^ + | + = note: see issue #29639 for more information + = help: add `#![feature(no_core)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-attr-empty-is-unused.rs b/tests/ui/conditional-compilation/cfg-attr-empty-is-unused.rs new file mode 100644 index 000000000..2600ec7c4 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-empty-is-unused.rs @@ -0,0 +1,13 @@ +// Check that `#[cfg_attr($PREDICATE,)]` triggers the `unused_attribute` lint. + +// compile-flags: --cfg TRUE + +#![deny(unused)] + +#[cfg_attr(FALSE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes +fn _f() {} + +#[cfg_attr(TRUE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes +fn _g() {} + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr b/tests/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr new file mode 100644 index 000000000..87b698813 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr @@ -0,0 +1,21 @@ +error: `#[cfg_attr]` does not expand to any attributes + --> $DIR/cfg-attr-empty-is-unused.rs:7:1 + | +LL | #[cfg_attr(FALSE,)] + | ^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/cfg-attr-empty-is-unused.rs:5:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` + +error: `#[cfg_attr]` does not expand to any attributes + --> $DIR/cfg-attr-empty-is-unused.rs:10:1 + | +LL | #[cfg_attr(TRUE,)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs new file mode 100644 index 000000000..496d196c9 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.rs @@ -0,0 +1,4 @@ +#[cfg(foo(bar))] //~ ERROR invalid predicate `foo` +fn check() {} + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr new file mode 100644 index 000000000..96c571ebe --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr @@ -0,0 +1,9 @@ +error[E0537]: invalid predicate `foo` + --> $DIR/cfg-attr-invalid-predicate.rs:1:7 + | +LL | #[cfg(foo(bar))] + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0537`. diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-false.rs b/tests/ui/conditional-compilation/cfg-attr-multi-false.rs new file mode 100644 index 000000000..0c7e7cad0 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-false.rs @@ -0,0 +1,19 @@ +// Test that cfg_attr doesn't emit any attributes when the +// configuration variable is false. This mirrors `cfg-attr-multi-true.rs` + +// build-pass (FIXME(62277): could be check-pass?) + +#![warn(unused_must_use)] + +#[cfg_attr(any(), deprecated, must_use)] +struct Struct {} + +impl Struct { + fn new() -> Struct { + Struct {} + } +} + +fn main() { + Struct::new(); +} diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs new file mode 100644 index 000000000..42ffb71e3 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs @@ -0,0 +1,7 @@ +// compile-flags: --cfg broken + +#![crate_type = "lib"] +#![cfg_attr(broken, no_core, no_std)] +//~^ ERROR the `#[no_core]` attribute is an experimental feature + +pub struct S {} diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr new file mode 100644 index 000000000..c8762d15d --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_core]` attribute is an experimental feature + --> $DIR/cfg-attr-multi-invalid-1.rs:4:21 + | +LL | #![cfg_attr(broken, no_core, no_std)] + | ^^^^^^^ + | + = note: see issue #29639 for more information + = help: add `#![feature(no_core)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs new file mode 100644 index 000000000..29690e284 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs @@ -0,0 +1,7 @@ +// compile-flags: --cfg broken + +#![crate_type = "lib"] +#![cfg_attr(broken, no_std, no_core)] +//~^ ERROR the `#[no_core]` attribute is an experimental feature + +pub struct S {} diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr new file mode 100644 index 000000000..e75b1c5b4 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[no_core]` attribute is an experimental feature + --> $DIR/cfg-attr-multi-invalid-2.rs:4:29 + | +LL | #![cfg_attr(broken, no_std, no_core)] + | ^^^^^^^ + | + = note: see issue #29639 for more information + = help: add `#![feature(no_core)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-true.rs b/tests/ui/conditional-compilation/cfg-attr-multi-true.rs new file mode 100644 index 000000000..876d8b079 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-true.rs @@ -0,0 +1,21 @@ +// Test that cfg_attr with multiple attributes actually emits both attributes. +// This is done by emitting two attributes that cause new warnings, and then +// triggering those warnings. + +// build-pass (FIXME(62277): could be check-pass?) + +#![warn(unused_must_use)] + +#[cfg_attr(all(), deprecated, must_use)] +struct MustUseDeprecated {} + +impl MustUseDeprecated { //~ warning: use of deprecated + fn new() -> MustUseDeprecated { //~ warning: use of deprecated + MustUseDeprecated {} //~ warning: use of deprecated + } +} + +fn main() { + MustUseDeprecated::new(); //~ warning: use of deprecated + //~| warning: unused `MustUseDeprecated` that must be used +} diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr b/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr new file mode 100644 index 000000000..fbfcd4565 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-multi-true.stderr @@ -0,0 +1,40 @@ +warning: use of deprecated struct `MustUseDeprecated` + --> $DIR/cfg-attr-multi-true.rs:12:6 + | +LL | impl MustUseDeprecated { + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: use of deprecated struct `MustUseDeprecated` + --> $DIR/cfg-attr-multi-true.rs:19:5 + | +LL | MustUseDeprecated::new(); + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `MustUseDeprecated` + --> $DIR/cfg-attr-multi-true.rs:13:17 + | +LL | fn new() -> MustUseDeprecated { + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated struct `MustUseDeprecated` + --> $DIR/cfg-attr-multi-true.rs:14:9 + | +LL | MustUseDeprecated {} + | ^^^^^^^^^^^^^^^^^ + +warning: unused `MustUseDeprecated` that must be used + --> $DIR/cfg-attr-multi-true.rs:19:5 + | +LL | MustUseDeprecated::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/cfg-attr-multi-true.rs:7:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: 5 warnings emitted + diff --git a/tests/ui/conditional-compilation/cfg-attr-parse.rs b/tests/ui/conditional-compilation/cfg-attr-parse.rs new file mode 100644 index 000000000..8ca31c118 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-parse.rs @@ -0,0 +1,55 @@ +// Parse `cfg_attr` with varying numbers of attributes and trailing commas + +// Completely empty `cfg_attr` input +#[cfg_attr()] //~ error: malformed `cfg_attr` attribute input +struct NoConfigurationPredicate; + +// Zero attributes, zero trailing comma (comma manatory here) +#[cfg_attr(all())] //~ error: expected `,`, found end of `cfg_attr` +struct A0C0; + +// Zero attributes, one trailing comma +#[cfg_attr(all(),)] // Ok +struct A0C1; + +// Zero attributes, two trailing commas +#[cfg_attr(all(),,)] //~ ERROR expected identifier +struct A0C2; + +// One attribute, no trailing comma +#[cfg_attr(all(), must_use)] // Ok +struct A1C0; + +// One attribute, one trailing comma +#[cfg_attr(all(), must_use,)] // Ok +struct A1C1; + +// One attribute, two trailing commas +#[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier +struct A1C2; + +// Two attributes, no trailing comma +#[cfg_attr(all(), must_use, deprecated)] // Ok +struct A2C0; + +// Two attributes, one trailing comma +#[cfg_attr(all(), must_use, deprecated,)] // Ok +struct A2C1; + +// Two attributes, two trailing commas +#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier +struct A2C2; + +// Wrong delimiter `[` +#[cfg_attr[all(),,]] +//~^ ERROR wrong `cfg_attr` delimiters +//~| ERROR expected identifier, found `,` +struct BracketZero; + +// Wrong delimiter `{` +#[cfg_attr{all(),,}] +//~^ ERROR wrong `cfg_attr` delimiters +//~| ERROR expected identifier, found `,` +struct BraceZero; + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-parse.stderr b/tests/ui/conditional-compilation/cfg-attr-parse.stderr new file mode 100644 index 000000000..8084a6220 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-parse.stderr @@ -0,0 +1,86 @@ +error: malformed `cfg_attr` attribute input + --> $DIR/cfg-attr-parse.rs:4:1 + | +LL | #[cfg_attr()] + | ^^^^^^^^^^^^^ help: missing condition and attribute: `#[cfg_attr(condition, attribute, other_attribute, ...)]` + | + = note: for more information, visit + +error: expected `,`, found end of `cfg_attr` input + --> $DIR/cfg-attr-parse.rs:8:17 + | +LL | #[cfg_attr(all())] + | ^ expected `,` + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:16:18 + | +LL | #[cfg_attr(all(),,)] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:28:28 + | +LL | #[cfg_attr(all(), must_use,,)] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:40:40 + | +LL | #[cfg_attr(all(), must_use, deprecated,,)] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: wrong `cfg_attr` delimiters + --> $DIR/cfg-attr-parse.rs:44:11 + | +LL | #[cfg_attr[all(),,]] + | ^^^^^^^^^ + | +help: the delimiters should be `(` and `)` + | +LL | #[cfg_attr(all(),,)] + | ~ ~ + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:44:18 + | +LL | #[cfg_attr[all(),,]] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: wrong `cfg_attr` delimiters + --> $DIR/cfg-attr-parse.rs:50:11 + | +LL | #[cfg_attr{all(),,}] + | ^^^^^^^^^ + | +help: the delimiters should be `(` and `)` + | +LL | #[cfg_attr(all(),,)] + | ~ ~ + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:50:18 + | +LL | #[cfg_attr{all(),,}] + | ^ expected identifier + | + = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` + = note: for more information, visit + +error: aborting due to 9 previous errors + diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs new file mode 100644 index 000000000..408eaffcc --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -0,0 +1,39 @@ +#[cfg] //~ ERROR `cfg` is not followed by parentheses +struct S1; + +#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses +struct S2; + +#[cfg()] //~ ERROR `cfg` predicate is not specified +struct S3; + +#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified +struct S4; + +#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal +struct S5; + +#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier +struct S6; + +#[cfg(a())] //~ ERROR invalid predicate `a` +struct S7; + +#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string +struct S8; + +#[cfg(a = b"hi")] //~ ERROR literal in `cfg` predicate value must be a string +struct S9; + +macro_rules! generate_s10 { + ($expr: expr) => { + #[cfg(feature = $expr)] + //~^ ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")` + //~| ERROR expected unsuffixed literal or identifier, found `concat!("nonexistent")` + struct S10; + } +} + +generate_s10!(concat!("nonexistent")); + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr new file mode 100644 index 000000000..d5b4349c0 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -0,0 +1,82 @@ +error: `cfg` is not followed by parentheses + --> $DIR/cfg-attr-syntax-validation.rs:1:1 + | +LL | #[cfg] + | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + +error: `cfg` is not followed by parentheses + --> $DIR/cfg-attr-syntax-validation.rs:4:1 + | +LL | #[cfg = 10] + | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + +error: `cfg` predicate is not specified + --> $DIR/cfg-attr-syntax-validation.rs:7:1 + | +LL | #[cfg()] + | ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + +error: multiple `cfg` predicates are specified + --> $DIR/cfg-attr-syntax-validation.rs:10:10 + | +LL | #[cfg(a, b)] + | ^ + +error: `cfg` predicate key cannot be a literal + --> $DIR/cfg-attr-syntax-validation.rs:13:7 + | +LL | #[cfg("str")] + | ^^^^^ + +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-attr-syntax-validation.rs:16:7 + | +LL | #[cfg(a::b)] + | ^^^^ + +error[E0537]: invalid predicate `a` + --> $DIR/cfg-attr-syntax-validation.rs:19:7 + | +LL | #[cfg(a())] + | ^^^ + +error[E0565]: literal in `cfg` predicate value must be a string + --> $DIR/cfg-attr-syntax-validation.rs:22:11 + | +LL | #[cfg(a = 10)] + | ^^ + +error[E0565]: literal in `cfg` predicate value must be a string + --> $DIR/cfg-attr-syntax-validation.rs:25:11 + | +LL | #[cfg(a = b"hi")] + | -^^^^ + | | + | help: consider removing the prefix + +error: expected unsuffixed literal or identifier, found `concat!("nonexistent")` + --> $DIR/cfg-attr-syntax-validation.rs:30:25 + | +LL | #[cfg(feature = $expr)] + | ^^^^^ +... +LL | generate_s10!(concat!("nonexistent")); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected unsuffixed literal or identifier, found `concat!("nonexistent")` + --> $DIR/cfg-attr-syntax-validation.rs:30:25 + | +LL | #[cfg(feature = $expr)] + | ^^^^^ +... +LL | generate_s10!(concat!("nonexistent")); + | ------------------------------------- in this macro invocation + | + = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0537, E0565. +For more information about an error, try `rustc --explain E0537`. diff --git a/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs new file mode 100644 index 000000000..45b757e92 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs @@ -0,0 +1,11 @@ +macro_rules! foo { + () => { + #[cfg_attr(all(), unknown)] + //~^ ERROR cannot find attribute `unknown` in this scope + fn foo() {} + } +} + +foo!(); + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr new file mode 100644 index 000000000..fc8df6552 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -0,0 +1,13 @@ +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:27 + | +LL | #[cfg_attr(all(), unknown)] + | ^^^^^^^ +... +LL | foo!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/conditional-compilation/cfg-empty-codemap.rs b/tests/ui/conditional-compilation/cfg-empty-codemap.rs new file mode 100644 index 000000000..9e34cacf7 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-empty-codemap.rs @@ -0,0 +1,8 @@ +// Tests that empty source_maps don't ICE (#23301) + +// compile-flags: --cfg "" + +// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) + +pub fn main() { +} diff --git a/tests/ui/conditional-compilation/cfg-empty-codemap.stderr b/tests/ui/conditional-compilation/cfg-empty-codemap.stderr new file mode 100644 index 000000000..128e3cd73 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-empty-codemap.stderr @@ -0,0 +1,2 @@ +error: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) + diff --git a/tests/ui/conditional-compilation/cfg-generic-params.rs b/tests/ui/conditional-compilation/cfg-generic-params.rs new file mode 100644 index 000000000..53aa35563 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-generic-params.rs @@ -0,0 +1,40 @@ +// compile-flags:--cfg yes + +fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(no)] T>() {} +fn f_ty<#[cfg(no)] 'a: 'a, #[cfg(yes)] T>() {} + +type FnGood = for<#[cfg(yes)] 'a, #[cfg(no)] T> fn(); // OK +type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); +//~^ ERROR only lifetime parameters can be used in this context + +type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy; // OK +type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; +//~^ ERROR only lifetime parameters can be used in this context + +struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(no)] T> u8: Copy; // OK +struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; +//~^ ERROR only lifetime parameters can be used in this context + +fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK +fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} +//~^ ERROR cannot find attribute `unknown` in this scope +fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK +fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} +//~^ ERROR cannot find attribute `unknown` in this scope + +type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK +type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); +//~^ ERROR cannot find attribute `unknown` in this scope + +type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK +type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; +//~^ ERROR cannot find attribute `unknown` in this scope + +struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK +struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; +//~^ ERROR cannot find attribute `unknown` in this scope + +fn main() { + f_lt::<'static>(); + f_ty::(); +} diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr new file mode 100644 index 000000000..4d6560e96 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr @@ -0,0 +1,50 @@ +error: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:7:45 + | +LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:11:51 + | +LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:15:54 + | +LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; + | ^ + +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:19:29 + | +LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} + | ^^^^^^^ + +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:22:29 + | +LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} + | ^^^^^^^ + +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:26:34 + | +LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); + | ^^^^^^^ + +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:30:40 + | +LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; + | ^^^^^^^ + +error: cannot find attribute `unknown` in this scope + --> $DIR/cfg-generic-params.rs:34:43 + | +LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; + | ^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.rs b/tests/ui/conditional-compilation/cfg-in-crate-1.rs new file mode 100644 index 000000000..8561cd830 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.rs @@ -0,0 +1,3 @@ +// error-pattern: `main` function not found + +#![cfg(bar)] diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr new file mode 100644 index 000000000..ff72c43ef --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -0,0 +1,9 @@ +error[E0601]: `main` function not found in crate `cfg_in_crate_1` + --> $DIR/cfg-in-crate-1.rs:3:13 + | +LL | #![cfg(bar)] + | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs new file mode 100644 index 000000000..0ddbd8a15 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs @@ -0,0 +1,11 @@ +#![feature(stmt_expr_attributes)] +#![feature(custom_test_frameworks)] + +fn main() { + let _ = #[cfg(unset)] (); + //~^ ERROR removing an expression is not supported in this position + let _ = 1 + 2 + #[cfg(unset)] 3; + //~^ ERROR removing an expression is not supported in this position + let _ = [1, 2, 3][#[cfg(unset)] 1]; + //~^ ERROR removing an expression is not supported in this position +} diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr new file mode 100644 index 000000000..933b7dc18 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr @@ -0,0 +1,20 @@ +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:5:13 + | +LL | let _ = #[cfg(unset)] (); + | ^^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:7:21 + | +LL | let _ = 1 + 2 + #[cfg(unset)] 3; + | ^^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:9:23 + | +LL | let _ = [1, 2, 3][#[cfg(unset)] 1]; + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/conditional-compilation/cfg_accessible-bugs.rs b/tests/ui/conditional-compilation/cfg_accessible-bugs.rs new file mode 100644 index 000000000..ae18bc55c --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-bugs.rs @@ -0,0 +1,18 @@ +// This test is a collection of test that should pass. +// +// check-fail + +#![feature(cfg_accessible)] +#![feature(trait_alias)] + +trait TraitAlias = std::fmt::Debug + Send; + +// FIXME: Currently shows "cannot determine" but should be `false` +#[cfg_accessible(unresolved)] //~ ERROR cannot determine +const C: bool = true; + +// FIXME: Currently shows "not sure" but should be `false` +#[cfg_accessible(TraitAlias::unresolved)] //~ ERROR not sure whether the path is accessible or not +const D: bool = true; + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-bugs.stderr b/tests/ui/conditional-compilation/cfg_accessible-bugs.stderr new file mode 100644 index 000000000..81f023878 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-bugs.stderr @@ -0,0 +1,16 @@ +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-bugs.rs:15:18 + | +LL | #[cfg_accessible(TraitAlias::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: cannot determine whether the path is accessible or not + --> $DIR/cfg_accessible-bugs.rs:11:1 + | +LL | #[cfg_accessible(unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/conditional-compilation/cfg_accessible-input-validation.rs b/tests/ui/conditional-compilation/cfg_accessible-input-validation.rs new file mode 100644 index 000000000..c51c908a4 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-input-validation.rs @@ -0,0 +1,24 @@ +#![feature(cfg_accessible)] + +#[cfg_accessible] //~ ERROR malformed `cfg_accessible` attribute input +struct S1; + +#[cfg_accessible = "value"] //~ ERROR malformed `cfg_accessible` attribute input +struct S2; + +#[cfg_accessible()] //~ ERROR `cfg_accessible` path is not specified +struct S3; + +#[cfg_accessible(std, core)] //~ ERROR multiple `cfg_accessible` paths are specified +struct S4; + +#[cfg_accessible("std")] //~ ERROR `cfg_accessible` path cannot be a literal +struct S5; + +#[cfg_accessible(std = "value")] //~ ERROR `cfg_accessible` path cannot accept arguments +struct S6; + +#[cfg_accessible(std(value))] //~ ERROR `cfg_accessible` path cannot accept arguments +struct S7; + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-input-validation.stderr b/tests/ui/conditional-compilation/cfg_accessible-input-validation.stderr new file mode 100644 index 000000000..86706c766 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-input-validation.stderr @@ -0,0 +1,44 @@ +error: malformed `cfg_accessible` attribute input + --> $DIR/cfg_accessible-input-validation.rs:3:1 + | +LL | #[cfg_accessible] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]` + +error: malformed `cfg_accessible` attribute input + --> $DIR/cfg_accessible-input-validation.rs:6:1 + | +LL | #[cfg_accessible = "value"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]` + +error: `cfg_accessible` path is not specified + --> $DIR/cfg_accessible-input-validation.rs:9:1 + | +LL | #[cfg_accessible()] + | ^^^^^^^^^^^^^^^^^^^ + +error: multiple `cfg_accessible` paths are specified + --> $DIR/cfg_accessible-input-validation.rs:12:23 + | +LL | #[cfg_accessible(std, core)] + | ^^^^ + +error: `cfg_accessible` path cannot be a literal + --> $DIR/cfg_accessible-input-validation.rs:15:18 + | +LL | #[cfg_accessible("std")] + | ^^^^^ + +error: `cfg_accessible` path cannot accept arguments + --> $DIR/cfg_accessible-input-validation.rs:18:18 + | +LL | #[cfg_accessible(std = "value")] + | ^^^^^^^^^^^^^ + +error: `cfg_accessible` path cannot accept arguments + --> $DIR/cfg_accessible-input-validation.rs:21:18 + | +LL | #[cfg_accessible(std(value))] + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2015.stderr b/tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2015.stderr new file mode 100644 index 000000000..7d5dd5890 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2015.stderr @@ -0,0 +1,122 @@ +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:14:18 + | +LL | #[cfg_accessible(Struct::existing)] + | ^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:16:18 + | +LL | #[cfg_accessible(Struct::unresolved)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:25:18 + | +LL | #[cfg_accessible(Union::existing)] + | ^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:27:18 + | +LL | #[cfg_accessible(Union::unresolved)] + | ^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:36:18 + | +LL | #[cfg_accessible(Enum::Existing::existing)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:38:18 + | +LL | #[cfg_accessible(Enum::Existing::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:40:18 + | +LL | #[cfg_accessible(Enum::unresolved)] + | ^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:50:18 + | +LL | #[cfg_accessible(Trait::existing)] + | ^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:52:18 + | +LL | #[cfg_accessible(Trait::unresolved)] + | ^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:59:18 + | +LL | #[cfg_accessible(TypeAlias::existing)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:61:18 + | +LL | #[cfg_accessible(TypeAlias::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:70:18 + | +LL | #[cfg_accessible(ForeignType::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:79:18 + | +LL | #[cfg_accessible(AssocType::AssocType::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:84:18 + | +LL | #[cfg_accessible(u8::unresolved)] + | ^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:86:18 + | +LL | #[cfg_accessible(u8::is_ascii)] + | ^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: aborting due to 15 previous errors + diff --git a/tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2021.stderr b/tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2021.stderr new file mode 100644 index 000000000..7d5dd5890 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-not_sure.edition2021.stderr @@ -0,0 +1,122 @@ +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:14:18 + | +LL | #[cfg_accessible(Struct::existing)] + | ^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:16:18 + | +LL | #[cfg_accessible(Struct::unresolved)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:25:18 + | +LL | #[cfg_accessible(Union::existing)] + | ^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:27:18 + | +LL | #[cfg_accessible(Union::unresolved)] + | ^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:36:18 + | +LL | #[cfg_accessible(Enum::Existing::existing)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:38:18 + | +LL | #[cfg_accessible(Enum::Existing::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:40:18 + | +LL | #[cfg_accessible(Enum::unresolved)] + | ^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:50:18 + | +LL | #[cfg_accessible(Trait::existing)] + | ^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:52:18 + | +LL | #[cfg_accessible(Trait::unresolved)] + | ^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:59:18 + | +LL | #[cfg_accessible(TypeAlias::existing)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:61:18 + | +LL | #[cfg_accessible(TypeAlias::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:70:18 + | +LL | #[cfg_accessible(ForeignType::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:79:18 + | +LL | #[cfg_accessible(AssocType::AssocType::unresolved)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:84:18 + | +LL | #[cfg_accessible(u8::unresolved)] + | ^^^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible-not_sure.rs:86:18 + | +LL | #[cfg_accessible(u8::is_ascii)] + | ^^^^^^^^^^^^ + | + = note: the type may have associated items, but we are currently not checking them + +error: aborting due to 15 previous errors + diff --git a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs new file mode 100644 index 000000000..99a7949db --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs @@ -0,0 +1,89 @@ +// revisions: edition2015 edition2021 +// [edition2015]compile-flags: --edition=2015 +// [edition2021]compile-flags: --edition=2021 + +#![feature(extern_types)] +#![feature(cfg_accessible)] + +// Struct::unresolved - error + +struct Struct { + existing: u8, +} + +#[cfg_accessible(Struct::existing)] //~ ERROR not sure +const A: bool = true; +#[cfg_accessible(Struct::unresolved)] //~ ERROR not sure +const B: bool = true; + +// Union::unresolved - error + +struct Union { + existing: u8, +} + +#[cfg_accessible(Union::existing)] //~ ERROR not sure +const A: bool = true; +#[cfg_accessible(Union::unresolved)] //~ ERROR not sure +const B: bool = true; + +// Enum::unresolved - error + +enum Enum { + Existing { existing: u8 }, +} + +#[cfg_accessible(Enum::Existing::existing)] //~ ERROR not sure +const A: bool = true; +#[cfg_accessible(Enum::Existing::unresolved)] //~ ERROR not sure +const B: bool = true; +#[cfg_accessible(Enum::unresolved)] //~ ERROR not sure +const C: bool = true; + +// Trait::unresolved - false or error, depending on edition (error if you can write Trait::foo +// instead of ::foo for methods like impl dyn Trait { fn foo() {} }) + +trait Trait {} +impl dyn Trait { fn existing() {} } + +// FIXME: Should be an error for edition > 2015 +#[cfg_accessible(Trait::existing)] //~ ERROR not sure +const A: bool = true; +#[cfg_accessible(Trait::unresolved)] //~ ERROR not sure +const B: bool = true; + +// TypeAlias::unresolved - error + +type TypeAlias = Struct; + +#[cfg_accessible(TypeAlias::existing)] //~ ERROR not sure +const A: bool = true; +#[cfg_accessible(TypeAlias::unresolved)] //~ ERROR not sure +const B: bool = true; + +// ForeignType::unresolved - error + +extern { + type ForeignType; +} + +#[cfg_accessible(ForeignType::unresolved)] //~ ERROR not sure +const A: bool = true; + +// AssocType::unresolved - error + +trait AssocType { + type AssocType; +} + +#[cfg_accessible(AssocType::AssocType::unresolved)] //~ ERROR not sure +const A: bool = true; + +// PrimitiveType::unresolved - error + +#[cfg_accessible(u8::unresolved)] //~ ERROR not sure +const A: bool = true; +#[cfg_accessible(u8::is_ascii)] //~ ERROR not sure +const B: bool = true; + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-private.rs b/tests/ui/conditional-compilation/cfg_accessible-private.rs new file mode 100644 index 000000000..5b095675c --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-private.rs @@ -0,0 +1,21 @@ +// check-pass + +#![feature(cfg_accessible)] + +mod private { + struct Struct; + enum Enum{} + union Union{_a:u8} +} + +#[cfg_accessible(private::Struct)] +const A: bool = true; + +#[cfg_accessible(private::Enum)] +const A: bool = true; + +#[cfg_accessible(private::Union)] +const A: bool = true; + +const A: bool = false; // Will conflict if any of those is accessible +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-stuck.rs b/tests/ui/conditional-compilation/cfg_accessible-stuck.rs new file mode 100644 index 000000000..50504a44c --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-stuck.rs @@ -0,0 +1,9 @@ +#![feature(cfg_accessible)] + +#[cfg_accessible(Z)] // OK, recovered after the other `cfg_accessible` produces an error. +struct S; + +#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not +struct Z; + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr b/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr new file mode 100644 index 000000000..33af7d625 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-stuck.stderr @@ -0,0 +1,8 @@ +error: cannot determine whether the path is accessible or not + --> $DIR/cfg_accessible-stuck.rs:6:1 + | +LL | #[cfg_accessible(S)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.rs b/tests/ui/conditional-compilation/cfg_accessible-unstable.rs new file mode 100644 index 000000000..e9247e67a --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.rs @@ -0,0 +1,2 @@ +#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible' +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr new file mode 100644 index 000000000..2f55b9559 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible-unstable.rs:1:3 + | +LL | #[cfg_accessible(std)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64797 for more information + = help: add `#![feature(cfg_accessible)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/conditional-compilation/cfg_accessible.rs b/tests/ui/conditional-compilation/cfg_accessible.rs new file mode 100644 index 000000000..df380d0d1 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible.rs @@ -0,0 +1,55 @@ +#![feature(cfg_accessible)] + +mod m { + pub struct ExistingPublic; + struct ExistingPrivate; +} + +trait Trait { + type Assoc; +} + +enum Enum { + Existing, +} + +#[cfg_accessible(Enum)] +struct ExistingResolved; + +#[cfg_accessible(Enum::Existing)] +struct ExistingResolvedVariant; + +#[cfg_accessible(m::ExistingPublic)] +struct ExistingPublic; + +#[cfg_accessible(m::ExistingPrivate)] +struct ExistingPrivate; + +#[cfg_accessible(m::NonExistent)] +struct NonExistingPrivate; + +#[cfg_accessible(n::AccessibleExpanded)] // OK, `cfg_accessible` can wait and retry. +struct AccessibleExpanded; + +#[cfg_accessible(Trait::Assoc)] +struct AccessibleTraitAssoc; + +macro_rules! generate_accessible_expanded { + () => { + mod n { + pub struct AccessibleExpanded; + } + }; +} + +generate_accessible_expanded!(); + +fn main() { + ExistingPublic; + AccessibleExpanded; + AccessibleTraitAssoc; + + ExistingPrivate; //~ ERROR cannot find + NonExistingPrivate; //~ ERROR cannot find + NonExistingTraitAlias; //~ ERROR cannot find +} diff --git a/tests/ui/conditional-compilation/cfg_accessible.stderr b/tests/ui/conditional-compilation/cfg_accessible.stderr new file mode 100644 index 000000000..e3731a1ad --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_accessible.stderr @@ -0,0 +1,27 @@ +error[E0425]: cannot find value `ExistingPrivate` in this scope + --> $DIR/cfg_accessible.rs:52:5 + | +LL | ExistingPrivate; + | ^^^^^^^^^^^^^^^ not found in this scope + | +note: unit struct `m::ExistingPrivate` exists but is inaccessible + --> $DIR/cfg_accessible.rs:5:5 + | +LL | struct ExistingPrivate; + | ^^^^^^^^^^^^^^^^^^^^^^^ not accessible + +error[E0425]: cannot find value `NonExistingPrivate` in this scope + --> $DIR/cfg_accessible.rs:53:5 + | +LL | NonExistingPrivate; + | ^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find value `NonExistingTraitAlias` in this scope + --> $DIR/cfg_accessible.rs:54:5 + | +LL | NonExistingTraitAlias; + | ^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/conditional-compilation/cfg_attr_path.rs b/tests/ui/conditional-compilation/cfg_attr_path.rs new file mode 100644 index 000000000..efb718b78 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_attr_path.rs @@ -0,0 +1,13 @@ +// check-pass + +#![deny(unused_attributes)] // c.f #35584 + +mod auxiliary { + #[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums; + #[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file; +} + +fn main() { + let _ = auxiliary::namespaced_enums::Foo::A; + let _ = auxiliary::nonexistent_file::Foo::A; +} diff --git a/tests/ui/conditional-compilation/inner-cfg-non-inline-mod.rs b/tests/ui/conditional-compilation/inner-cfg-non-inline-mod.rs new file mode 100644 index 000000000..af5a6462e --- /dev/null +++ b/tests/ui/conditional-compilation/inner-cfg-non-inline-mod.rs @@ -0,0 +1,7 @@ +// check-pass + +mod module_with_cfg; + +mod module_with_cfg {} // Ok, the module above is configured away by an inner attribute. + +fn main() {} diff --git a/tests/ui/conditional-compilation/issue-34028.rs b/tests/ui/conditional-compilation/issue-34028.rs new file mode 100644 index 000000000..d761c0c82 --- /dev/null +++ b/tests/ui/conditional-compilation/issue-34028.rs @@ -0,0 +1,10 @@ +// check-pass + +macro_rules! m { + () => { #[cfg(any())] fn f() {} } +} + +trait T {} +impl T for () { m!(); } + +fn main() {} diff --git a/tests/ui/conditional-compilation/module_with_cfg.rs b/tests/ui/conditional-compilation/module_with_cfg.rs new file mode 100644 index 000000000..56c4baadf --- /dev/null +++ b/tests/ui/conditional-compilation/module_with_cfg.rs @@ -0,0 +1,3 @@ +// ignore-test + +#![cfg_attr(all(), cfg(FALSE))] diff --git a/tests/ui/conditional-compilation/test-cfg.rs b/tests/ui/conditional-compilation/test-cfg.rs new file mode 100644 index 000000000..8750bae00 --- /dev/null +++ b/tests/ui/conditional-compilation/test-cfg.rs @@ -0,0 +1,8 @@ +// compile-flags: --cfg foo + +#[cfg(all(foo, bar))] // foo AND bar +fn foo() {} + +fn main() { + foo(); //~ ERROR cannot find function `foo` in this scope +} diff --git a/tests/ui/conditional-compilation/test-cfg.stderr b/tests/ui/conditional-compilation/test-cfg.stderr new file mode 100644 index 000000000..c35fe2f94 --- /dev/null +++ b/tests/ui/conditional-compilation/test-cfg.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/test-cfg.rs:7:5 + | +LL | foo(); + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/conflicting-repr-hints.rs b/tests/ui/conflicting-repr-hints.rs new file mode 100644 index 000000000..ed82b6a74 --- /dev/null +++ b/tests/ui/conflicting-repr-hints.rs @@ -0,0 +1,80 @@ +#![allow(dead_code)] + +#[repr(C)] +enum A { + A, +} + +#[repr(u64)] +enum B { + B, +} + +#[repr(C, u64)] //~ ERROR conflicting representation hints +//~^ WARN this was previously accepted +enum C { + C, +} + +#[repr(u32, u64)] //~ ERROR conflicting representation hints +//~^ WARN this was previously accepted +enum D { + D, +} + +#[repr(C, packed)] +struct E(i32); + +#[repr(packed, align(8))] +struct F(i32); //~ ERROR type has conflicting packed and align representation hints + +#[repr(packed)] +#[repr(align(8))] +struct G(i32); //~ ERROR type has conflicting packed and align representation hints + +#[repr(align(8))] +#[repr(packed)] +struct H(i32); //~ ERROR type has conflicting packed and align representation hints + +#[repr(packed, packed(2))] +struct I(i32); //~ ERROR type has conflicting packed representation hints + +#[repr(packed(2))] +#[repr(packed)] +struct J(i32); //~ ERROR type has conflicting packed representation hints + +#[repr(packed, packed(1))] +struct K(i32); + +#[repr(packed, align(8))] +union X { + //~^ ERROR type has conflicting packed and align representation hints + i: i32, +} + +#[repr(packed)] +#[repr(align(8))] +union Y { + //~^ ERROR type has conflicting packed and align representation hints + i: i32, +} + +#[repr(align(8))] +#[repr(packed)] +union Z { + //~^ ERROR type has conflicting packed and align representation hints + i: i32, +} + +#[repr(packed, align(0x100))] +pub struct S(u16); //~ ERROR type has conflicting packed and align representation hints + +#[repr(packed, align(0x100))] +pub union U { //~ ERROR type has conflicting packed and align representation hints + u: u16 +} + +static B: U = U { u: 0 }; +static A: S = S(0); + +fn main() {} diff --git a/tests/ui/conflicting-repr-hints.stderr b/tests/ui/conflicting-repr-hints.stderr new file mode 100644 index 000000000..4dcd8f4fc --- /dev/null +++ b/tests/ui/conflicting-repr-hints.stderr @@ -0,0 +1,83 @@ +error[E0566]: conflicting representation hints + --> $DIR/conflicting-repr-hints.rs:13:8 + | +LL | #[repr(C, u64)] + | ^ ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + = note: `#[deny(conflicting_repr_hints)]` on by default + +error[E0566]: conflicting representation hints + --> $DIR/conflicting-repr-hints.rs:19:8 + | +LL | #[repr(u32, u64)] + | ^^^ ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #68585 + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:29:1 + | +LL | struct F(i32); + | ^^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:33:1 + | +LL | struct G(i32); + | ^^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:37:1 + | +LL | struct H(i32); + | ^^^^^^^^ + +error[E0634]: type has conflicting packed representation hints + --> $DIR/conflicting-repr-hints.rs:40:1 + | +LL | struct I(i32); + | ^^^^^^^^ + +error[E0634]: type has conflicting packed representation hints + --> $DIR/conflicting-repr-hints.rs:44:1 + | +LL | struct J(i32); + | ^^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:50:1 + | +LL | union X { + | ^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:57:1 + | +LL | union Y { + | ^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:64:1 + | +LL | union Z { + | ^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:70:1 + | +LL | pub struct S(u16); + | ^^^^^^^^^^^^ + +error[E0587]: type has conflicting packed and align representation hints + --> $DIR/conflicting-repr-hints.rs:73:1 + | +LL | pub union U { + | ^^^^^^^^^^^ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0566, E0587, E0634. +For more information about an error, try `rustc --explain E0566`. diff --git a/tests/ui/confuse-field-and-method/issue-18343.rs b/tests/ui/confuse-field-and-method/issue-18343.rs new file mode 100644 index 000000000..bc2d73fae --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-18343.rs @@ -0,0 +1,9 @@ +struct Obj where F: FnMut() -> u32 { + closure: F, +} + +fn main() { + let o = Obj { closure: || 42 }; + o.closure(); + //~^ ERROR no method named `closure` found +} diff --git a/tests/ui/confuse-field-and-method/issue-18343.stderr b/tests/ui/confuse-field-and-method/issue-18343.stderr new file mode 100644 index 000000000..1c9a6847c --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-18343.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `closure` found for struct `Obj` in the current scope + --> $DIR/issue-18343.rs:7:7 + | +LL | struct Obj where F: FnMut() -> u32 { + | ------------- method `closure` not found for this struct +... +LL | o.closure(); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `closure`, surround the field access with parentheses + | +LL | (o.closure)(); + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/confuse-field-and-method/issue-2392.rs b/tests/ui/confuse-field-and-method/issue-2392.rs new file mode 100644 index 000000000..8aef091fe --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-2392.rs @@ -0,0 +1,69 @@ +struct FuncContainer { + f1: fn(data: u8), + f2: extern "C" fn(data: u8), + f3: unsafe fn(data: u8), +} + +struct FuncContainerOuter { + container: Box +} + +struct Obj where F: FnOnce() -> u32 { + closure: F, + not_closure: usize, +} + +struct BoxedObj { + boxed_closure: Box u32>, +} + +struct Wrapper where F: FnMut() -> u32 { + wrap: Obj, +} + +fn func() -> u32 { + 0 +} + +fn check_expression() -> Obj u32>> { + Obj { closure: Box::new(|| 42_u32) as Box u32>, not_closure: 42 } +} + +fn main() { + // test variations of function + + let o_closure = Obj { closure: || 42, not_closure: 42 }; + o_closure.closure(); //~ ERROR no method named `closure` found + + o_closure.not_closure(); + //~^ ERROR no method named `not_closure` found + + let o_func = Obj { closure: func, not_closure: 5 }; + o_func.closure(); //~ ERROR no method named `closure` found + + let boxed_fn = BoxedObj { boxed_closure: Box::new(func) }; + boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found + + let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box u32> }; + boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found + + // test expression writing in the notes + + let w = Wrapper { wrap: o_func }; + w.wrap.closure();//~ ERROR no method named `closure` found + + w.wrap.not_closure(); + //~^ ERROR no method named `not_closure` found + + check_expression().closure();//~ ERROR no method named `closure` found +} + +impl FuncContainerOuter { + fn run(&self) { + unsafe { + (*self.container).f1(1); //~ ERROR no method named `f1` found + (*self.container).f2(1); //~ ERROR no method named `f2` found + (*self.container).f3(1); //~ ERROR no method named `f3` found + } + } +} diff --git a/tests/ui/confuse-field-and-method/issue-2392.stderr b/tests/ui/confuse-field-and-method/issue-2392.stderr new file mode 100644 index 000000000..440fbb27c --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-2392.stderr @@ -0,0 +1,151 @@ +error[E0599]: no method named `closure` found for struct `Obj` in the current scope + --> $DIR/issue-2392.rs:36:15 + | +LL | struct Obj where F: FnOnce() -> u32 { + | ------------- method `closure` not found for this struct +... +LL | o_closure.closure(); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `closure`, surround the field access with parentheses + | +LL | (o_closure.closure)(); + | + + + +error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope + --> $DIR/issue-2392.rs:38:15 + | +LL | struct Obj where F: FnOnce() -> u32 { + | ------------- method `not_closure` not found for this struct +... +LL | o_closure.not_closure(); + | ^^^^^^^^^^^-- help: remove the arguments + | | + | field, not a method + +error[E0599]: no method named `closure` found for struct `Obj` in the current scope + --> $DIR/issue-2392.rs:42:12 + | +LL | struct Obj where F: FnOnce() -> u32 { + | ------------- method `closure` not found for this struct +... +LL | o_func.closure(); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `closure`, surround the field access with parentheses + | +LL | (o_func.closure)(); + | + + + +error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope + --> $DIR/issue-2392.rs:45:14 + | +LL | struct BoxedObj { + | --------------- method `boxed_closure` not found for this struct +... +LL | boxed_fn.boxed_closure(); + | ^^^^^^^^^^^^^ field, not a method + | +help: to call the function stored in `boxed_closure`, surround the field access with parentheses + | +LL | (boxed_fn.boxed_closure)(); + | + + + +error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the current scope + --> $DIR/issue-2392.rs:48:19 + | +LL | struct BoxedObj { + | --------------- method `boxed_closure` not found for this struct +... +LL | boxed_closure.boxed_closure(); + | ^^^^^^^^^^^^^ field, not a method + | +help: to call the function stored in `boxed_closure`, surround the field access with parentheses + | +LL | (boxed_closure.boxed_closure)(); + | + + + +error[E0599]: no method named `closure` found for struct `Obj` in the current scope + --> $DIR/issue-2392.rs:53:12 + | +LL | struct Obj where F: FnOnce() -> u32 { + | ------------- method `closure` not found for this struct +... +LL | w.wrap.closure(); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `closure`, surround the field access with parentheses + | +LL | (w.wrap.closure)(); + | + + + +error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope + --> $DIR/issue-2392.rs:55:12 + | +LL | struct Obj where F: FnOnce() -> u32 { + | ------------- method `not_closure` not found for this struct +... +LL | w.wrap.not_closure(); + | ^^^^^^^^^^^-- help: remove the arguments + | | + | field, not a method + +error[E0599]: no method named `closure` found for struct `Obj` in the current scope + --> $DIR/issue-2392.rs:58:24 + | +LL | struct Obj where F: FnOnce() -> u32 { + | ------------- method `closure` not found for this struct +... +LL | check_expression().closure(); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `closure`, surround the field access with parentheses + | +LL | (check_expression().closure)(); + | + + + +error[E0599]: no method named `f1` found for struct `FuncContainer` in the current scope + --> $DIR/issue-2392.rs:64:31 + | +LL | struct FuncContainer { + | -------------------- method `f1` not found for this struct +... +LL | (*self.container).f1(1); + | ^^ field, not a method + | +help: to call the function stored in `f1`, surround the field access with parentheses + | +LL | ((*self.container).f1)(1); + | + + + +error[E0599]: no method named `f2` found for struct `FuncContainer` in the current scope + --> $DIR/issue-2392.rs:65:31 + | +LL | struct FuncContainer { + | -------------------- method `f2` not found for this struct +... +LL | (*self.container).f2(1); + | ^^ field, not a method + | +help: to call the function stored in `f2`, surround the field access with parentheses + | +LL | ((*self.container).f2)(1); + | + + + +error[E0599]: no method named `f3` found for struct `FuncContainer` in the current scope + --> $DIR/issue-2392.rs:66:31 + | +LL | struct FuncContainer { + | -------------------- method `f3` not found for this struct +... +LL | (*self.container).f3(1); + | ^^ field, not a method + | +help: to call the function stored in `f3`, surround the field access with parentheses + | +LL | ((*self.container).f3)(1); + | + + + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/confuse-field-and-method/issue-32128.rs b/tests/ui/confuse-field-and-method/issue-32128.rs new file mode 100644 index 000000000..5a024aa4b --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-32128.rs @@ -0,0 +1,15 @@ +struct Example { + example: Box i32> +} + +fn main() { + let demo = Example { + example: Box::new(|x| { + x + 1 + }) + }; + + demo.example(1); + //~^ ERROR no method named `example` + // (demo.example)(1); +} diff --git a/tests/ui/confuse-field-and-method/issue-32128.stderr b/tests/ui/confuse-field-and-method/issue-32128.stderr new file mode 100644 index 000000000..4b96bce8d --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-32128.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `example` found for struct `Example` in the current scope + --> $DIR/issue-32128.rs:12:10 + | +LL | struct Example { + | -------------- method `example` not found for this struct +... +LL | demo.example(1); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `example`, surround the field access with parentheses + | +LL | (demo.example)(1); + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/confuse-field-and-method/issue-33784.rs b/tests/ui/confuse-field-and-method/issue-33784.rs new file mode 100644 index 000000000..e9bb1f9fb --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-33784.rs @@ -0,0 +1,33 @@ +use std::ops::Deref; + +struct Obj where F: FnMut() -> u32 { + fn_ptr: fn() -> (), + closure: F, +} + +struct C { + c_fn_ptr: fn() -> (), +} + +struct D(C); + +impl Deref for D { + type Target = C; + fn deref(&self) -> &C { + &self.0 + } +} + + +fn empty() {} + +fn main() { + let o = Obj { fn_ptr: empty, closure: || 42 }; + let p = &o; + p.closure(); //~ ERROR no method named `closure` found + let q = &p; + q.fn_ptr(); //~ ERROR no method named `fn_ptr` found + let r = D(C { c_fn_ptr: empty }); + let s = &r; + s.c_fn_ptr(); //~ ERROR no method named `c_fn_ptr` found +} diff --git a/tests/ui/confuse-field-and-method/issue-33784.stderr b/tests/ui/confuse-field-and-method/issue-33784.stderr new file mode 100644 index 000000000..3906d64c9 --- /dev/null +++ b/tests/ui/confuse-field-and-method/issue-33784.stderr @@ -0,0 +1,36 @@ +error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope + --> $DIR/issue-33784.rs:27:7 + | +LL | p.closure(); + | ^^^^^^^ field, not a method + | +help: to call the function stored in `closure`, surround the field access with parentheses + | +LL | (p.closure)(); + | + + + +error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope + --> $DIR/issue-33784.rs:29:7 + | +LL | q.fn_ptr(); + | ^^^^^^ field, not a method + | +help: to call the function stored in `fn_ptr`, surround the field access with parentheses + | +LL | (q.fn_ptr)(); + | + + + +error[E0599]: no method named `c_fn_ptr` found for reference `&D` in the current scope + --> $DIR/issue-33784.rs:32:7 + | +LL | s.c_fn_ptr(); + | ^^^^^^^^ field, not a method + | +help: to call the function stored in `c_fn_ptr`, surround the field access with parentheses + | +LL | (s.c_fn_ptr)(); + | + + + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/confuse-field-and-method/private-field.rs b/tests/ui/confuse-field-and-method/private-field.rs new file mode 100644 index 000000000..28b8935ac --- /dev/null +++ b/tests/ui/confuse-field-and-method/private-field.rs @@ -0,0 +1,19 @@ +pub mod animal { + pub struct Dog { + pub age: usize, + dog_age: usize, + } + + impl Dog { + pub fn new(age: usize) -> Dog { + Dog { age: age, dog_age: age * 7 } + } + } +} + +fn main() { + let dog = animal::Dog::new(3); + let dog_age = dog.dog_age(); //~ ERROR no method + //let dog_age = dog.dog_age; + println!("{}", dog_age); +} diff --git a/tests/ui/confuse-field-and-method/private-field.stderr b/tests/ui/confuse-field-and-method/private-field.stderr new file mode 100644 index 000000000..783378f8d --- /dev/null +++ b/tests/ui/confuse-field-and-method/private-field.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `dog_age` found for struct `Dog` in the current scope + --> $DIR/private-field.rs:16:23 + | +LL | pub struct Dog { + | -------------- method `dog_age` not found for this struct +... +LL | let dog_age = dog.dog_age(); + | ^^^^^^^ private field, not a method + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/conservative_impl_trait.rs b/tests/ui/conservative_impl_trait.rs new file mode 100644 index 000000000..b7f795ead --- /dev/null +++ b/tests/ui/conservative_impl_trait.rs @@ -0,0 +1,7 @@ +// #39872, #39553 + +fn will_ice(something: &u32) -> impl Iterator { + //~^ ERROR `()` is not an iterator +} + +fn main() {} diff --git a/tests/ui/conservative_impl_trait.stderr b/tests/ui/conservative_impl_trait.stderr new file mode 100644 index 000000000..63a4df242 --- /dev/null +++ b/tests/ui/conservative_impl_trait.stderr @@ -0,0 +1,11 @@ +error[E0277]: `()` is not an iterator + --> $DIR/conservative_impl_trait.rs:3:33 + | +LL | fn will_ice(something: &u32) -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator + | + = help: the trait `Iterator` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/apit-with-const-param.rs b/tests/ui/const-generics/apit-with-const-param.rs new file mode 100644 index 000000000..2a04dc313 --- /dev/null +++ b/tests/ui/const-generics/apit-with-const-param.rs @@ -0,0 +1,7 @@ +// check-pass + +trait Trait {} + +fn f(_: impl Trait) {} + +fn main() {} diff --git a/tests/ui/const-generics/arg-in-pat-1.rs b/tests/ui/const-generics/arg-in-pat-1.rs new file mode 100644 index 000000000..82555084e --- /dev/null +++ b/tests/ui/const-generics/arg-in-pat-1.rs @@ -0,0 +1,23 @@ +// check-pass +enum ConstGenericEnum { + Foo([i32; N]), + Bar, +} + +fn foo(val: &ConstGenericEnum) { + if let ConstGenericEnum::::Foo(field, ..) = val {} +} + +fn bar(val: &ConstGenericEnum) { + match val { + ConstGenericEnum::::Foo(field, ..) => (), + ConstGenericEnum::::Bar => (), + } +} + +fn main() { + match ConstGenericEnum::Bar { + ConstGenericEnum::<3>::Foo(field, ..) => (), + ConstGenericEnum::<3>::Bar => (), + } +} diff --git a/tests/ui/const-generics/arg-in-pat-2.rs b/tests/ui/const-generics/arg-in-pat-2.rs new file mode 100644 index 000000000..dc9e722ed --- /dev/null +++ b/tests/ui/const-generics/arg-in-pat-2.rs @@ -0,0 +1,10 @@ +// check-pass +enum Generic { + Variant, +} + +fn main() { + match todo!() { + Generic::<0usize>::Variant => todo!() + } +} diff --git a/tests/ui/const-generics/arg-in-pat-3.rs b/tests/ui/const-generics/arg-in-pat-3.rs new file mode 100644 index 000000000..24626a3b6 --- /dev/null +++ b/tests/ui/const-generics/arg-in-pat-3.rs @@ -0,0 +1,43 @@ +// check-pass +struct Foo; + +fn bindingp() { + match Foo { + mut x @ Foo::<3> => { + let ref mut _x @ Foo::<3> = x; + } + } +} + +struct Bar { + field: Foo, +} + +fn structp() { + match todo!() { + Bar::<3> { + field: Foo::<3>, + } => (), + } +} + +struct Baz(Foo); + +fn tuplestructp() { + match Baz(Foo) { + Baz::<3>(Foo::<3>) => (), + } +} + +impl Baz { + const ASSOC: usize = 3; +} + +fn pathp() { + match 3 { + Baz::<3>::ASSOC => (), + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/const-generics/argument_order.rs b/tests/ui/const-generics/argument_order.rs new file mode 100644 index 000000000..196d9b8a1 --- /dev/null +++ b/tests/ui/const-generics/argument_order.rs @@ -0,0 +1,15 @@ +struct Bad { + arr: [u8; { N }], + another: T, +} + +struct AlsoBad { + //~^ ERROR lifetime parameters must be declared prior + a: &'a T, + b: &'b U, +} + +fn main() { + let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + //~^ ERROR lifetime provided when a type was expected + } diff --git a/tests/ui/const-generics/argument_order.stderr b/tests/ui/const-generics/argument_order.stderr new file mode 100644 index 000000000..99122c6f5 --- /dev/null +++ b/tests/ui/const-generics/argument_order.stderr @@ -0,0 +1,18 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/argument_order.rs:6:32 + | +LL | struct AlsoBad { + | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>` + +error[E0747]: lifetime provided when a type was expected + --> $DIR/argument_order.rs:13:23 + | +LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + | ^^^^^^^ + | + = note: lifetime arguments must be provided before type arguments + = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, N, T, M, U>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs new file mode 100644 index 000000000..b4a083636 --- /dev/null +++ b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs @@ -0,0 +1,48 @@ +// check-pass + +pub fn yes_vec_partial_eq_array() -> impl PartialEq<[B; 32]> +where + A: PartialEq, +{ + Vec::::new() +} + +pub fn yes_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 32]> +where + A: PartialEq, +{ + Vec::::new() +} + +pub fn yes_array_into_vec() -> Vec { + [].into() +} + +pub fn yes_array_into_box() -> Box<[T]> { + [].into() +} + +use std::collections::VecDeque; + +pub fn yes_vecdeque_partial_eq_array() -> impl PartialEq<[B; 32]> +where + A: PartialEq, +{ + VecDeque::::new() +} + +pub fn yes_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 32]> +where + A: PartialEq, +{ + VecDeque::::new() +} + +pub fn yes_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 32]> +where + A: PartialEq, +{ + VecDeque::::new() +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs new file mode 100644 index 000000000..35df3278a --- /dev/null +++ b/tests/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs @@ -0,0 +1,40 @@ +// check-pass + +pub fn yes_vec_partial_eq_array() -> impl PartialEq<[B; 33]> +where + A: PartialEq, +{ + Vec::::new() +} + +pub fn yes_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]> +where + A: PartialEq, +{ + Vec::::new() +} + +use std::collections::VecDeque; + +pub fn yes_vecdeque_partial_eq_array() -> impl PartialEq<[B; 33]> +where + A: PartialEq, +{ + VecDeque::::new() +} + +pub fn yes_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]> +where + A: PartialEq, +{ + VecDeque::::new() +} + +pub fn yes_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]> +where + A: PartialEq, +{ + VecDeque::::new() +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs b/tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs new file mode 100644 index 000000000..294b405e0 --- /dev/null +++ b/tests/ui/const-generics/array-impls/alloc-types-impls-length-33.rs @@ -0,0 +1,25 @@ +// check-pass + +use std::{convert::TryFrom, rc::Rc, sync::Arc}; + +pub fn yes_vec() { + let v: Vec<_> = [0; 33].into(); +} + +pub fn yes_box() { + let boxed_slice = Box::new([0; 33]) as Box<[i32]>; + let boxed_array = >::try_from(boxed_slice); + let boxed_slice = >::from([0; 33]); +} + +pub fn yes_rc() { + let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>; + let boxed_array = >::try_from(boxed_slice); +} + +pub fn yes_arc() { + let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>; + let boxed_array = >::try_from(boxed_slice); +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs b/tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs new file mode 100644 index 000000000..9998bb84c --- /dev/null +++ b/tests/ui/const-generics/array-impls/core-traits-impls-length-32.rs @@ -0,0 +1,66 @@ +// check-pass + +pub fn yes_as_ref() -> impl AsRef<[u8]> { + [0; 32] +} + +pub fn yes_as_mut() -> impl AsMut<[u8]> { + [0; 32] +} + +pub fn yes_borrow() -> impl std::borrow::Borrow<[u8]> { + [0; 32] +} + +pub fn yes_borrow_mut() -> impl std::borrow::BorrowMut<[u8]> { + [0; 32] +} + +pub fn yes_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + [0; 32] +} + +pub fn yes_ref_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + let a: &'static _ = &[0; 32]; + a +} + +pub fn yes_hash() -> impl std::hash::Hash { + [0; 32] +} + +pub fn yes_debug() -> impl std::fmt::Debug { + [0; 32] +} + +pub fn yes_ref_into_iterator() -> impl IntoIterator { + let a: &'static _ = &[0; 32]; + a +} + +pub fn yes_partial_eq() -> impl PartialEq<[u8; 32]> { + [0; 32] +} + +pub fn yes_partial_eq_slice() -> impl PartialEq<[u8]> { + [0; 32] +} + +pub fn yes_slice_partial_eq() -> impl PartialEq<[u8; 32]> { + let a: &'static _ = &[0; 32]; + &a[..] +} + +pub fn yes_eq() -> impl Eq { + [0; 32] +} + +pub fn yes_partial_ord() -> impl PartialOrd<[u8; 32]> { + [0; 32] +} + +pub fn yes_ord() -> impl Ord { + [0; 32] +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs b/tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs new file mode 100644 index 000000000..c609a7c6f --- /dev/null +++ b/tests/ui/const-generics/array-impls/core-traits-impls-length-33.rs @@ -0,0 +1,66 @@ +// check-pass + +pub fn yes_as_ref() -> impl AsRef<[u8]> { + [0; 33] +} + +pub fn yes_as_mut() -> impl AsMut<[u8]> { + [0; 33] +} + +pub fn yes_borrow() -> impl std::borrow::Borrow<[u8]> { + [0; 33] +} + +pub fn yes_borrow_mut() -> impl std::borrow::BorrowMut<[u8]> { + [0; 33] +} + +pub fn yes_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + [0; 33] +} + +pub fn yes_ref_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> { + let a: &'static _ = &[0; 33]; + a +} + +pub fn yes_hash() -> impl std::hash::Hash { + [0; 33] +} + +pub fn yes_debug() -> impl std::fmt::Debug { + [0; 33] +} + +pub fn yes_ref_into_iterator() -> impl IntoIterator { + let a: &'static _ = &[0; 33]; + a +} + +pub fn yes_partial_eq() -> impl PartialEq<[u8; 33]> { + [0; 33] +} + +pub fn yes_partial_eq_slice() -> impl PartialEq<[u8]> { + [0; 33] +} + +pub fn yes_slice_partial_eq() -> impl PartialEq<[u8; 33]> { + let a: &'static _ = &[0; 33]; + &a[..] +} + +pub fn yes_eq() -> impl Eq { + [0; 33] +} + +pub fn yes_partial_ord() -> impl PartialOrd<[u8; 33]> { + [0; 33] +} + +pub fn yes_ord() -> impl Ord { + [0; 33] +} + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs b/tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs new file mode 100644 index 000000000..457e5ae60 --- /dev/null +++ b/tests/ui/const-generics/array-impls/into-iter-impls-length-32.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(trusted_len)] + +use std::{ + array::IntoIter, + fmt::Debug, + iter::{ExactSizeIterator, FusedIterator, TrustedLen}, +}; + +pub fn yes_iterator() -> impl Iterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_exact_size_iterator() -> impl ExactSizeIterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_fused_iterator() -> impl FusedIterator { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_trusted_len() -> impl TrustedLen { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_clone() -> impl Clone { + IntoIterator::into_iter([0i32; 32]) +} + +pub fn yes_debug() -> impl Debug { + IntoIterator::into_iter([0i32; 32]) +} + + +fn main() {} diff --git a/tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs b/tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs new file mode 100644 index 000000000..4f343f3f9 --- /dev/null +++ b/tests/ui/const-generics/array-impls/into-iter-impls-length-33.rs @@ -0,0 +1,40 @@ +// check-pass + +#![feature(trusted_len)] + +use std::{ + array::IntoIter, + fmt::Debug, + iter::{ExactSizeIterator, FusedIterator, TrustedLen}, +}; + +pub fn yes_iterator() -> impl Iterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_exact_size_iterator() -> impl ExactSizeIterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_fused_iterator() -> impl FusedIterator { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_trusted_len() -> impl TrustedLen { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_clone() -> impl Clone { + IntoIterator::into_iter([0i32; 33]) +} + +pub fn yes_debug() -> impl Debug { + IntoIterator::into_iter([0i32; 33]) +} + + +fn main() {} diff --git a/tests/ui/const-generics/array-wrapper-struct-ctor.rs b/tests/ui/const-generics/array-wrapper-struct-ctor.rs new file mode 100644 index 000000000..a712f691d --- /dev/null +++ b/tests/ui/const-generics/array-wrapper-struct-ctor.rs @@ -0,0 +1,14 @@ +// run-pass + +#![allow(dead_code)] + +struct ArrayStruct { + data: [T; N], +} + +struct ArrayTuple([T; N]); + +fn main() { + let _ = ArrayStruct { data: [0u32; 8] }; + let _ = ArrayTuple([0u32; 8]); +} diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs new file mode 100644 index 000000000..4d0aaf88e --- /dev/null +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs @@ -0,0 +1,18 @@ +#![feature(associated_const_equality)] + +pub enum Mode { + Cool, +} + +pub trait Parse { + const MODE: Mode; +} + +pub trait CoolStuff: Parse {} +//~^ ERROR expected associated constant bound +//~| ERROR expected type + +fn no_help() -> Mode::Cool {} +//~^ ERROR expected type, found variant + +fn main() {} diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr new file mode 100644 index 000000000..ba727ee0e --- /dev/null +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -0,0 +1,33 @@ +error[E0573]: expected type, found variant `Mode::Cool` + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 + | +LL | pub trait CoolStuff: Parse {} + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Mode` + +error[E0573]: expected type, found variant `Mode::Cool` + --> $DIR/assoc_const_eq_diagnostic.rs:15:17 + | +LL | fn no_help() -> Mode::Cool {} + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Mode` + +error: expected associated constant bound, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:28 + | +LL | pub trait CoolStuff: Parse {} + | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | +note: associated constant defined here + --> $DIR/assoc_const_eq_diagnostic.rs:8:5 + | +LL | const MODE: Mode; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/associated-type-bound-fail.rs b/tests/ui/const-generics/associated-type-bound-fail.rs new file mode 100644 index 000000000..937b8bcb6 --- /dev/null +++ b/tests/ui/const-generics/associated-type-bound-fail.rs @@ -0,0 +1,12 @@ +trait Bar {} + +trait Foo { + type Assoc: Bar; +} + +impl Bar<3> for u16 {} +impl Foo for i16 { + type Assoc = u16; //~ ERROR the trait bound `u16: Bar` +} + +fn main() {} diff --git a/tests/ui/const-generics/associated-type-bound-fail.stderr b/tests/ui/const-generics/associated-type-bound-fail.stderr new file mode 100644 index 000000000..e5e7ee26e --- /dev/null +++ b/tests/ui/const-generics/associated-type-bound-fail.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `u16: Bar` is not satisfied + --> $DIR/associated-type-bound-fail.rs:9:18 + | +LL | type Assoc = u16; + | ^^^ the trait `Bar` is not implemented for `u16` + | + = help: the trait `Bar<3>` is implemented for `u16` +note: required by a bound in `Foo::Assoc` + --> $DIR/associated-type-bound-fail.rs:4:17 + | +LL | type Assoc: Bar; + | ^^^^^^ required by this bound in `Foo::Assoc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/associated-type-bound.rs b/tests/ui/const-generics/associated-type-bound.rs new file mode 100644 index 000000000..3044736b4 --- /dev/null +++ b/tests/ui/const-generics/associated-type-bound.rs @@ -0,0 +1,19 @@ +// run-pass +trait Bar {} + +trait Foo { + type Assoc: Bar; +} + +impl Bar for u8 {} +impl Bar<3> for u16 {} + +impl Foo for i8 { + type Assoc = u8; +} + +impl Foo<3> for i16 { + type Assoc = u16; +} + +fn main() {} diff --git a/tests/ui/const-generics/auxiliary/const_generic_lib.rs b/tests/ui/const-generics/auxiliary/const_generic_lib.rs new file mode 100644 index 000000000..922f92d9f --- /dev/null +++ b/tests/ui/const-generics/auxiliary/const_generic_lib.rs @@ -0,0 +1,7 @@ +pub struct Struct(pub [u8; N]); + +pub type Alias = Struct<2>; + +pub fn function(value: Struct<3>) -> u8 { + value.0[0] +} diff --git a/tests/ui/const-generics/auxiliary/crayte.rs b/tests/ui/const-generics/auxiliary/crayte.rs new file mode 100644 index 000000000..19a8bb0f4 --- /dev/null +++ b/tests/ui/const-generics/auxiliary/crayte.rs @@ -0,0 +1,16 @@ +// edition:2018 + +pub trait Foo {} +struct Local; +impl Foo for Local {} + +pub fn out_foo() -> impl Foo { Local } +pub fn in_foo(_: impl Foo) {} + +pub async fn async_simple(_: [u8; N]) {} +pub async fn async_out_foo() -> impl Foo { Local } +pub async fn async_in_foo(_: impl Foo) {} + +pub trait Bar { + type Assoc: Foo; +} diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent.rs b/tests/ui/const-generics/auxiliary/generics_of_parent.rs new file mode 100644 index 000000000..5c2b1f4bd --- /dev/null +++ b/tests/ui/const-generics/auxiliary/generics_of_parent.rs @@ -0,0 +1,23 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// library portion of regression test for #87674 +pub struct Foo([(); N + 1]) +where + [(); N + 1]: ; + +// library portion of regression test for #87603 +pub struct S +where + [T; N * 2]: Sized, +{ + pub s: [T; N * 2], +} +impl S +where + [T; N * 2]: Sized, +{ + pub fn test() -> Self { + S { s: [T::default(); N * 2] } + } +} diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs new file mode 100644 index 000000000..cd5b8161d --- /dev/null +++ b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs @@ -0,0 +1,8 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// library portion of testing that `impl Trait<{ expr }>` doesnt +// ice because of a `DefKind::TyParam` parent +pub fn foo(foo: impl Into<[(); N + 1]>) { + foo.into(); +} diff --git a/tests/ui/const-generics/auxiliary/legacy-const-generics.rs b/tests/ui/const-generics/auxiliary/legacy-const-generics.rs new file mode 100644 index 000000000..67352a2fb --- /dev/null +++ b/tests/ui/const-generics/auxiliary/legacy-const-generics.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_legacy_const_generics(1)] +pub fn foo(x: usize, z: usize) -> [usize; 3] { + [x, Y, z] +} diff --git a/tests/ui/const-generics/backcompat/trait-resolution-breakage.rs b/tests/ui/const-generics/backcompat/trait-resolution-breakage.rs new file mode 100644 index 000000000..df1c99e86 --- /dev/null +++ b/tests/ui/const-generics/backcompat/trait-resolution-breakage.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Trait { + const ASSOC_CONST: usize = 0; +} + +impl Trait<()> for u8 {} + +// `u8::ASSOC_CONST` is resolved today, but will be ambiguous +// under lazy normalization. +fn foo() -> [(T, U); u8::ASSOC_CONST] +where + u8: Trait + Trait, +{ + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/backcompat/unevaluated-consts.rs b/tests/ui/const-generics/backcompat/unevaluated-consts.rs new file mode 100644 index 000000000..3f90d22ae --- /dev/null +++ b/tests/ui/const-generics/backcompat/unevaluated-consts.rs @@ -0,0 +1,18 @@ +// check-pass + +// If we allow the parent generics here without using lazy normalization +// this results in a cycle error. +struct Foo(T, U); + +impl From<[u8; 1 + 1]> for Foo { + fn from(value: [u8; 1 + 1]) -> Foo { + todo!(); + } +} + +fn break_me() +where + [u8; 1 + 1]: From<[u8; 1 + 1]> +{} + +fn main() {} diff --git a/tests/ui/const-generics/bad-const-generic-exprs.rs b/tests/ui/const-generics/bad-const-generic-exprs.rs new file mode 100644 index 000000000..ca91643ed --- /dev/null +++ b/tests/ui/const-generics/bad-const-generic-exprs.rs @@ -0,0 +1,22 @@ +struct Wow; + +fn main() { + let _: Wow; + //~^ ERROR invalid const generic expression + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + let _: Wow<|| ()>; + //~^ ERROR invalid const generic expression + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + let _: Wow; + //~^ ERROR expected one of + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + let _: Wow; + //~^ ERROR expected one of + //~| HELP expressions must be enclosed in braces to be used as const generic arguments + + // FIXME(compiler-errors): This one is still unsatisfying, + // and probably a case I could see someone typing by accident.. + let _: Wow<[12]>; + //~^ ERROR expected type, found + //~| ERROR type provided when a constant was expected +} diff --git a/tests/ui/const-generics/bad-const-generic-exprs.stderr b/tests/ui/const-generics/bad-const-generic-exprs.stderr new file mode 100644 index 000000000..24668b08b --- /dev/null +++ b/tests/ui/const-generics/bad-const-generic-exprs.stderr @@ -0,0 +1,59 @@ +error: invalid const generic expression + --> $DIR/bad-const-generic-exprs.rs:4:16 + | +LL | let _: Wow; + | ^^^^^^^^^^ + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ if true {} }>; + | + + + +error: invalid const generic expression + --> $DIR/bad-const-generic-exprs.rs:7:16 + | +LL | let _: Wow<|| ()>; + | ^^^^^ + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ || () }>; + | + + + +error: expected one of `,` or `>`, found `.` + --> $DIR/bad-const-generic-exprs.rs:10:17 + | +LL | let _: Wow; + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ A.b }>; + | + + + +error: expected one of `,` or `>`, found `.` + --> $DIR/bad-const-generic-exprs.rs:13:17 + | +LL | let _: Wow; + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | let _: Wow<{ A.0 }>; + | + + + +error: expected type, found `12` + --> $DIR/bad-const-generic-exprs.rs:19:17 + | +LL | let _: Wow<[12]>; + | ^^ expected type + +error[E0747]: type provided when a constant was expected + --> $DIR/bad-const-generic-exprs.rs:19:16 + | +LL | let _: Wow<[12]>; + | ^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/broken-mir-1.rs b/tests/ui/const-generics/broken-mir-1.rs new file mode 100644 index 000000000..6b6140e3a --- /dev/null +++ b/tests/ui/const-generics/broken-mir-1.rs @@ -0,0 +1,13 @@ +// run-pass +pub trait Foo { + fn foo(&self); +} + + +impl Foo for [T; N] { + fn foo(&self) { + let _ = &self; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/broken-mir-2.rs b/tests/ui/const-generics/broken-mir-2.rs new file mode 100644 index 000000000..9d6228117 --- /dev/null +++ b/tests/ui/const-generics/broken-mir-2.rs @@ -0,0 +1,10 @@ +// run-pass + +#![allow(dead_code)] + +use std::fmt::Debug; + +#[derive(Debug)] +struct S([T; N]); + +fn main() {} diff --git a/tests/ui/const-generics/cannot-infer-type-for-const-param.rs b/tests/ui/const-generics/cannot-infer-type-for-const-param.rs new file mode 100644 index 000000000..a6e767489 --- /dev/null +++ b/tests/ui/const-generics/cannot-infer-type-for-const-param.rs @@ -0,0 +1,10 @@ +// check-pass + +// This test confirms that the types can be inferred correctly for this example with const +// generics. Previously this would ICE, and more recently error. + +struct Foo(pub [u8; NUM_BYTES]); + +fn main() { + let _ = Foo::<3>([1, 2, 3]); +} diff --git a/tests/ui/const-generics/coerce_unsized_array.rs b/tests/ui/const-generics/coerce_unsized_array.rs new file mode 100644 index 000000000..ffd5eb9d4 --- /dev/null +++ b/tests/ui/const-generics/coerce_unsized_array.rs @@ -0,0 +1,8 @@ +// run-pass +fn foo(v: &[u8; N]) -> &[u8] { + v +} + +fn main() { + assert_eq!(foo(&[1, 2]), &[1, 2]); +} diff --git a/tests/ui/const-generics/concrete-const-as-fn-arg.rs b/tests/ui/const-generics/concrete-const-as-fn-arg.rs new file mode 100644 index 000000000..372f0433e --- /dev/null +++ b/tests/ui/const-generics/concrete-const-as-fn-arg.rs @@ -0,0 +1,11 @@ +// Test that a concrete const type i.e. A<2>, can be used as an argument type in a function +// run-pass + +struct A; // ok + +fn with_concrete_const_arg(_: A<2>) -> u32 { 17 } + +fn main() { + let val: A<2> = A; + assert_eq!(with_concrete_const_arg(val), 17); +} diff --git a/tests/ui/const-generics/concrete-const-impl-method.rs b/tests/ui/const-generics/concrete-const-impl-method.rs new file mode 100644 index 000000000..53c9c0ead --- /dev/null +++ b/tests/ui/const-generics/concrete-const-impl-method.rs @@ -0,0 +1,21 @@ +// Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>, +// is callable. +// run-pass + +pub struct A; + +impl A<2> { + fn impl_method(&self) -> u32 { + 17 + } + + fn associated_non_method() -> u32 { + 17 + } +} + +fn main() { + let val: A<2> = A; + assert_eq!(val.impl_method(), 17); + assert_eq!(A::<2>::associated_non_method(), 17); +} diff --git a/tests/ui/const-generics/condition-in-trait-const-arg.rs b/tests/ui/const-generics/condition-in-trait-const-arg.rs new file mode 100644 index 000000000..6f85237cf --- /dev/null +++ b/tests/ui/const-generics/condition-in-trait-const-arg.rs @@ -0,0 +1,14 @@ +// Checks that `impl Trait<{anon_const}> for Type` evaluates successfully. +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +trait IsZeroTrait{} + +impl IsZeroTrait<{0u8 == 0u8}> for () {} + +impl IsZeroTrait for ((),) {} + +fn main() {} diff --git a/tests/ui/const-generics/const-arg-in-const-arg.full.stderr b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr new file mode 100644 index 000000000..8672e79b3 --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-const-arg.full.stderr @@ -0,0 +1,162 @@ +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:18:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:21:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:44:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:13:12 + | +LL | let _: [u8; foo::()]; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); foo::()]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:15:12 + | +LL | let _: [u8; bar::()]; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); bar::()]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:36:12 + | +LL | let _: Foo<{ foo::() }>; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { foo::() }]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:38:12 + | +LL | let _: Foo<{ bar::() }>; + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { bar::() }]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:25:17 + | +LL | let _ = [0; foo::()]; + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); foo::()]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:27:17 + | +LL | let _ = [0; bar::()]; + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); bar::()]:` + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:30:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:33:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:47:19 + | +LL | let _ = Foo::<{ foo::() }>; + | ^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { foo::() }]:` + +error: unconstrained generic constant + --> $DIR/const-arg-in-const-arg.rs:49:19 + | +LL | let _ = Foo::<{ bar::() }>; + | ^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { bar::() }]:` + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:52:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:55:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr new file mode 100644 index 000000000..f1353aa99 --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -0,0 +1,359 @@ +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:13:23 + | +LL | let _: [u8; foo::()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:15:23 + | +LL | let _: [u8; bar::()]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:18:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:20:23 + | +LL | let _: [u8; baz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:21:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:23:23 + | +LL | let _: [u8; baz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:27:23 + | +LL | let _ = [0; bar::()]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:30:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:32:23 + | +LL | let _ = [0; baz::<'a>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:33:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:35:23 + | +LL | let _ = [0; baz::<'b>(&())]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:36:24 + | +LL | let _: Foo<{ foo::() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:38:24 + | +LL | let _: Foo<{ bar::() }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:43:24 + | +LL | let _: Foo<{ baz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:44:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:46:24 + | +LL | let _: Foo<{ baz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:47:27 + | +LL | let _ = Foo::<{ foo::() }>; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/const-arg-in-const-arg.rs:49:27 + | +LL | let _ = Foo::<{ bar::() }>; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:52:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:54:27 + | +LL | let _ = Foo::<{ baz::<'a>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:55:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-arg-in-const-arg.rs:57:27 + | +LL | let _ = Foo::<{ baz::<'b>(&()) }>; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:15:23 + | +LL | let _: [u8; bar::()]; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: [u8; bar::<{ N }>()]; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:18:23 + | +LL | let _: [u8; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:21:23 + | +LL | let _: [u8; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:38:24 + | +LL | let _: Foo<{ bar::() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Foo<{ bar::<{ N }>() }>; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:41:24 + | +LL | let _: Foo<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:44:24 + | +LL | let _: Foo<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: constant expression depends on a generic parameter + --> $DIR/const-arg-in-const-arg.rs:25:17 + | +LL | let _ = [0; foo::()]; + | ^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:27:23 + | +LL | let _ = [0; bar::()]; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _ = [0; bar::<{ N }>()]; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:30:23 + | +LL | let _ = [0; faz::<'a>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:33:23 + | +LL | let _ = [0; faz::<'b>(&())]; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-arg-in-const-arg.rs:49:27 + | +LL | let _ = Foo::<{ bar::() }>; + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _ = Foo::<{ bar::<{ N }>() }>; + | + + + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:52:27 + | +LL | let _ = Foo::<{ faz::<'a>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/const-arg-in-const-arg.rs:55:27 + | +LL | let _ = Foo::<{ faz::<'b>(&()) }>; + | ^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/const-arg-in-const-arg.rs:8:14 + | +LL | const fn faz<'a>(_: &'a ()) -> usize { 13 } + | ^^ + +error: aborting due to 36 previous errors + +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/const-arg-in-const-arg.rs b/tests/ui/const-generics/const-arg-in-const-arg.rs new file mode 100644 index 000000000..44a4f560a --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-const-arg.rs @@ -0,0 +1,60 @@ +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +const fn foo() -> usize { std::mem::size_of::() } +const fn bar() -> usize { N } +const fn faz<'a>(_: &'a ()) -> usize { 13 } +const fn baz<'a>(_: &'a ()) -> usize where &'a (): Sized { 13 } + +struct Foo; +fn test<'a, 'b, T, const N: usize>() where &'b (): Sized { + let _: [u8; foo::()]; //[min]~ ERROR generic parameters may not + //[full]~^ ERROR unconstrained generic constant + let _: [u8; bar::()]; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _: [u8; faz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: [u8; baz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + let _: [u8; faz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: [u8; baz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + + let _ = [0; foo::()]; //[min]~ ERROR constant expression depends on a generic parameter + //[full]~^ ERROR unconstrained generic constant + let _ = [0; bar::()]; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _ = [0; faz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = [0; baz::<'a>(&())]; //[min]~ ERROR a non-static lifetime + let _ = [0; faz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = [0; baz::<'b>(&())]; //[min]~ ERROR a non-static lifetime + let _: Foo<{ foo::() }>; //[min]~ ERROR generic parameters may not + //[full]~^ ERROR unconstrained generic constant + let _: Foo<{ bar::() }>; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _: Foo<{ faz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: Foo<{ baz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + let _: Foo<{ faz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _: Foo<{ baz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime + let _ = Foo::<{ foo::() }>; //[min]~ ERROR generic parameters may not + //[full]~^ ERROR unconstrained generic constant + let _ = Foo::<{ bar::() }>; //[min]~ ERROR generic parameters may not + //[min]~^ ERROR unresolved item provided when a constant was expected + //[full]~^^ ERROR unconstrained generic constant + let _ = Foo::<{ faz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = Foo::<{ baz::<'a>(&()) }>; //[min]~ ERROR a non-static lifetime + let _ = Foo::<{ faz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime + //~^ ERROR cannot specify lifetime arguments + let _ = Foo::<{ baz::<'b>(&()) }>; //[min]~ ERROR a non-static lifetime +} + +fn main() {} diff --git a/tests/ui/const-generics/const-arg-in-fn.rs b/tests/ui/const-generics/const-arg-in-fn.rs new file mode 100644 index 000000000..9b225b18d --- /dev/null +++ b/tests/ui/const-generics/const-arg-in-fn.rs @@ -0,0 +1,9 @@ +// run-pass +fn const_u32_identity() -> u32 { + X +} + + fn main() { + let val = const_u32_identity::<18>(); + assert_eq!(val, 18); +} diff --git a/tests/ui/const-generics/const-arg-type-arg-misordered.rs b/tests/ui/const-generics/const-arg-type-arg-misordered.rs new file mode 100644 index 000000000..8ee17e637 --- /dev/null +++ b/tests/ui/const-generics/const-arg-type-arg-misordered.rs @@ -0,0 +1,8 @@ +type Array = [T; N]; + +fn foo() -> Array { + //~^ ERROR constant provided when a type was expected + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/const-generics/const-arg-type-arg-misordered.stderr b/tests/ui/const-generics/const-arg-type-arg-misordered.stderr new file mode 100644 index 000000000..4e12f7a8c --- /dev/null +++ b/tests/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -0,0 +1,9 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/const-arg-type-arg-misordered.rs:3:35 + | +LL | fn foo() -> Array { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/const-argument-cross-crate-mismatch.rs b/tests/ui/const-generics/const-argument-cross-crate-mismatch.rs new file mode 100644 index 000000000..d863d097d --- /dev/null +++ b/tests/ui/const-generics/const-argument-cross-crate-mismatch.rs @@ -0,0 +1,10 @@ +// aux-build:const_generic_lib.rs + +extern crate const_generic_lib; + +fn main() { + let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + //~^ ERROR mismatched types + let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr new file mode 100644 index 000000000..d5eefd357 --- /dev/null +++ b/tests/ui/const-generics/const-argument-cross-crate-mismatch.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:6:67 + | +LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + | ------------------------- ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/auxiliary/const_generic_lib.rs:1:12 + | +LL | pub struct Struct(pub [u8; N]); + | ^^^^^^ + +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:8:65 + | +LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + | ------------------------- ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements + | | + | arguments to this struct are incorrect + | +note: tuple struct defined here + --> $DIR/auxiliary/const_generic_lib.rs:1:12 + | +LL | pub struct Struct(pub [u8; N]); + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/const-argument-cross-crate.rs b/tests/ui/const-generics/const-argument-cross-crate.rs new file mode 100644 index 000000000..5693409e9 --- /dev/null +++ b/tests/ui/const-generics/const-argument-cross-crate.rs @@ -0,0 +1,13 @@ +// run-pass +// revisions: full min +// aux-build:const_generic_lib.rs + +extern crate const_generic_lib; + +struct Container(#[allow(unused_tuple_struct_fields)] const_generic_lib::Alias); + +fn main() { + let res = const_generic_lib::function(const_generic_lib::Struct([14u8, 1u8, 2u8])); + assert_eq!(res, 14u8); + let _ = Container(const_generic_lib::Struct([0u8, 1u8])); +} diff --git a/tests/ui/const-generics/const-argument-if-length.full.stderr b/tests/ui/const-generics/const-argument-if-length.full.stderr new file mode 100644 index 000000000..2ceba59cf --- /dev/null +++ b/tests/ui/const-generics/const-argument-if-length.full.stderr @@ -0,0 +1,35 @@ +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/const-argument-if-length.rs:15:12 + | +LL | pub struct AtLeastByte { + | - this type parameter needs to be `std::marker::Sized` +LL | value: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - pub struct AtLeastByte { +LL + pub struct AtLeastByte { + | +help: borrowed types always have a statically known size + | +LL | value: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | value: Box, + | ++++ + + +error: unconstrained generic constant + --> $DIR/const-argument-if-length.rs:17:10 + | +LL | pad: [u8; is_zst::()], + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); is_zst::()]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/const-argument-if-length.min.stderr b/tests/ui/const-generics/const-argument-if-length.min.stderr new file mode 100644 index 000000000..f85e60f63 --- /dev/null +++ b/tests/ui/const-generics/const-argument-if-length.min.stderr @@ -0,0 +1,36 @@ +error: generic parameters may not be used in const operations + --> $DIR/const-argument-if-length.rs:17:24 + | +LL | pad: [u8; is_zst::()], + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/const-argument-if-length.rs:15:12 + | +LL | pub struct AtLeastByte { + | - this type parameter needs to be `std::marker::Sized` +LL | value: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - pub struct AtLeastByte { +LL + pub struct AtLeastByte { + | +help: borrowed types always have a statically known size + | +LL | value: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | value: Box, + | ++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/const-argument-if-length.rs b/tests/ui/const-generics/const-argument-if-length.rs new file mode 100644 index 000000000..db1eafca2 --- /dev/null +++ b/tests/ui/const-generics/const-argument-if-length.rs @@ -0,0 +1,22 @@ +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +pub const fn is_zst() -> usize { + if std::mem::size_of::() == 0 { + 1 + } else { + 0 + } +} + +pub struct AtLeastByte { + value: T, + //~^ ERROR the size for values of type `T` cannot be known at compilation time + pad: [u8; is_zst::()], + //[min]~^ ERROR generic parameters may not be used in const operations + //[full]~^^ ERROR unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr new file mode 100644 index 000000000..f1f3a9c3d --- /dev/null +++ b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr @@ -0,0 +1,12 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/const-argument-non-static-lifetime.rs:15:17 + | +LL | let _: &'a (); + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.rs b/tests/ui/const-generics/const-argument-non-static-lifetime.rs new file mode 100644 index 000000000..36a569784 --- /dev/null +++ b/tests/ui/const-generics/const-argument-non-static-lifetime.rs @@ -0,0 +1,21 @@ +// [full] check-pass +// revisions: full min + +// regression test for #78180 +// compile-flags: -Zsave-analysis + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] +#![allow(dead_code)] + +fn test() {} + +fn wow<'a>() -> &'a () { + test::<{ + let _: &'a (); //[min]~ ERROR a non-static lifetime + 3 + }>(); + &() +} + +fn main() {} diff --git a/tests/ui/const-generics/const-fn-with-const-param.rs b/tests/ui/const-generics/const-fn-with-const-param.rs new file mode 100644 index 000000000..161bfaab4 --- /dev/null +++ b/tests/ui/const-generics/const-fn-with-const-param.rs @@ -0,0 +1,10 @@ +// Checks that `const fn` with const params can be used. +// run-pass + +const fn const_u32_identity() -> u32 { + X +} + +fn main() { + assert_eq!(const_u32_identity::<18>(), 18); +} diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.rs b/tests/ui/const-generics/const-generic-default-wont-borrowck.rs new file mode 100644 index 000000000..e64adacac --- /dev/null +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.rs @@ -0,0 +1,5 @@ +struct X; + +fn main() {} diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr new file mode 100644 index 000000000..0ed370b83 --- /dev/null +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `s` isn't initialized + --> $DIR/const-generic-default-wont-borrowck.rs:2:26 + | +LL | let s: &'static str; s.len() + | - ^^^^^^^ `*s` used here but it isn't initialized + | | + | binding declared here but left uninitialized + | +help: consider assigning a value + | +LL | let s: &'static str = todo!(); s.len() + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0381`. diff --git a/tests/ui/const-generics/const-generic-function.rs b/tests/ui/const-generics/const-generic-function.rs new file mode 100644 index 000000000..c8d2683e5 --- /dev/null +++ b/tests/ui/const-generics/const-generic-function.rs @@ -0,0 +1,21 @@ +fn foo() -> i32 { + N +} + +const fn bar(n: i32, m: i32) -> i32 { + n +} + +const fn baz() -> i32 { + 1 +} + +const FOO: i32 = 3; + +fn main() { + foo::(); //~ ERROR expected type, found function `baz` + //~| ERROR unresolved item provided when a constant was expected + foo::(); //~ ERROR expected type, found `1` + foo::(); //~ ERROR expected type, found `1` + foo::(); //~ ERROR expected type, found `2` +} diff --git a/tests/ui/const-generics/const-generic-function.stderr b/tests/ui/const-generics/const-generic-function.stderr new file mode 100644 index 000000000..5ad3f1006 --- /dev/null +++ b/tests/ui/const-generics/const-generic-function.stderr @@ -0,0 +1,54 @@ +error: expected type, found `1` + --> $DIR/const-generic-function.rs:18:19 + | +LL | foo::(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(bar(1, 1), bar(1, 1)) }>(); + | + + + +error: expected type, found `1` + --> $DIR/const-generic-function.rs:19:15 + | +LL | foo::(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(1, 1) }>(); + | + + + +error: expected type, found `2` + --> $DIR/const-generic-function.rs:20:20 + | +LL | foo::(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(FOO, 2) }>(); + | + + + +error[E0573]: expected type, found function `baz` + --> $DIR/const-generic-function.rs:16:11 + | +LL | foo::(); + | ^^^^^ not a type + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-generic-function.rs:16:11 + | +LL | foo::(); + | ^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | foo::<{ baz() }>(); + | + + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0573, E0747. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/const-generic-type_name.rs b/tests/ui/const-generics/const-generic-type_name.rs new file mode 100644 index 000000000..bb16be9c5 --- /dev/null +++ b/tests/ui/const-generics/const-generic-type_name.rs @@ -0,0 +1,8 @@ +// run-pass + +#[derive(Debug)] +struct S; + +fn main() { + assert_eq!(std::any::type_name::>(), "const_generic_type_name::S<3>"); +} diff --git a/tests/ui/const-generics/const-param-after-const-literal-arg.rs b/tests/ui/const-generics/const-param-after-const-literal-arg.rs new file mode 100644 index 000000000..d8a0e076e --- /dev/null +++ b/tests/ui/const-generics/const-param-after-const-literal-arg.rs @@ -0,0 +1,7 @@ +// check-pass + +struct Foo; + +impl Foo<1, A> {} // ok + +fn main() {} diff --git a/tests/ui/const-generics/const-param-before-other-params.rs b/tests/ui/const-generics/const-param-before-other-params.rs new file mode 100644 index 000000000..cb1cebe1f --- /dev/null +++ b/tests/ui/const-generics/const-param-before-other-params.rs @@ -0,0 +1,7 @@ +fn bar(_: &'a ()) { + //~^ ERROR lifetime parameters must be declared prior to type and const parameters +} + +fn foo(_: &T) {} + +fn main() {} diff --git a/tests/ui/const-generics/const-param-before-other-params.stderr b/tests/ui/const-generics/const-param-before-other-params.stderr new file mode 100644 index 000000000..2c7a47bbc --- /dev/null +++ b/tests/ui/const-generics/const-param-before-other-params.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/const-param-before-other-params.rs:1:21 + | +LL | fn bar(_: &'a ()) { + | --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: u8>` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/const-param-elided-lifetime.full.stderr b/tests/ui/const-generics/const-param-elided-lifetime.full.stderr new file mode 100644 index 000000000..d6753a74f --- /dev/null +++ b/tests/ui/const-generics/const-param-elided-lifetime.full.stderr @@ -0,0 +1,33 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:9:19 + | +LL | struct A; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:14:15 + | +LL | impl A { + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo(&self) {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:22:15 + | +LL | impl B for A {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:26:17 + | +LL | fn bar() {} + | ^ explicit lifetime name needed here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr new file mode 100644 index 000000000..4bba42c77 --- /dev/null +++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -0,0 +1,78 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:9:19 + | +LL | struct A; + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:14:15 + | +LL | impl A { + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo(&self) {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:22:15 + | +LL | impl B for A {} + | ^ explicit lifetime name needed here + +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/const-param-elided-lifetime.rs:26:17 + | +LL | fn bar() {} + | ^ explicit lifetime name needed here + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:9:19 + | +LL | struct A; + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:14:15 + | +LL | impl A { + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:22:15 + | +LL | impl B for A {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:26:17 + | +LL | fn bar() {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/const-param-elided-lifetime.rs:17:21 + | +LL | fn foo(&self) {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/const-generics/const-param-elided-lifetime.rs b/tests/ui/const-generics/const-param-elided-lifetime.rs new file mode 100644 index 000000000..487b82dbf --- /dev/null +++ b/tests/ui/const-generics/const-param-elided-lifetime.rs @@ -0,0 +1,30 @@ +// Elided lifetimes within the type of a const generic parameters is disallowed. This matches the +// behaviour of trait bounds where `fn foo>() {}` is illegal. Though we could change +// elided lifetimes within the type of a const generic parameters to be 'static, like elided +// lifetimes within const/static items. +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct A; +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden +trait B {} + +impl A { +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden + fn foo(&self) {} + //~^ ERROR `&` without an explicit lifetime name cannot be used here + //[min]~^^ ERROR `&'static u8` is forbidden +} + +impl B for A {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden + +fn bar() {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here +//[min]~^^ ERROR `&'static u8` is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/const-param-in-async.rs b/tests/ui/const-generics/const-param-in-async.rs new file mode 100644 index 000000000..f823431e6 --- /dev/null +++ b/tests/ui/const-generics/const-param-in-async.rs @@ -0,0 +1,31 @@ +// edition:2018 +// check-pass + +async fn foo(arg: [u8; N]) -> usize { arg.len() } + +async fn bar() -> [u8; N] { + [0; N] +} + +trait Trait { + fn fynn(&self) -> usize; +} +impl Trait for [u8; N] { + fn fynn(&self) -> usize { + N + } +} +async fn baz() -> impl Trait { + [0; N] +} + +async fn biz(v: impl Trait) -> usize { + v.fynn() +} + +async fn user() { + let _ = foo::(bar().await).await; + let _ = biz(baz::().await).await; +} + +fn main() { } diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr new file mode 100644 index 000000000..f639e276f --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.full.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:11:52 + | +LL | pub struct Dependent([(); N]); + | ^ the type must not depend on the parameter `N` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:15:40 + | +LL | pub struct SelfDependent; + | ^ the type must not depend on the parameter `N` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr new file mode 100644 index 000000000..24aa40521 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -0,0 +1,33 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:11:52 + | +LL | pub struct Dependent([(); N]); + | ^ the type must not depend on the parameter `N` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-const-param.rs:15:40 + | +LL | pub struct SelfDependent; + | ^ the type must not depend on the parameter `N` + +error: `[u8; N]` is forbidden as the type of a const generic parameter + --> $DIR/const-param-type-depends-on-const-param.rs:11:47 + | +LL | pub struct Dependent([(); N]); + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `[u8; N]` is forbidden as the type of a const generic parameter + --> $DIR/const-param-type-depends-on-const-param.rs:15:35 + | +LL | pub struct SelfDependent; + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.rs b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs new file mode 100644 index 000000000..64b2acb03 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs @@ -0,0 +1,19 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +// Currently, const parameters cannot depend on other generic parameters, +// as our current implementation can't really support this. +// +// We may want to lift this restriction in the future. + +pub struct Dependent([(); N]); +//~^ ERROR: the type of const parameters must not depend on other generic parameters +//[min]~^^ ERROR `[u8; N]` is forbidden + +pub struct SelfDependent; +//~^ ERROR: the type of const parameters must not depend on other generic parameters +//[min]~^^ ERROR `[u8; N]` is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs new file mode 100644 index 000000000..781f50e61 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -0,0 +1,9 @@ +// compile-flags: -Zsave-analysis +// Regression test for #69414 ^ + +use std::marker::PhantomData; + +struct B(PhantomData<[T; N]>); +//~^ ERROR the type of const parameters must not depend on other generic parameters + +fn main() {} diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr new file mode 100644 index 000000000..8e14defd6 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:22 + | +LL | struct B(PhantomData<[T; N]>); + | ^ the type must not depend on the parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr new file mode 100644 index 000000000..32f7dea82 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr @@ -0,0 +1,19 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-type-param.rs:11:34 + | +LL | pub struct Dependent([(); X]); + | ^ the type must not depend on the parameter `T` + +error[E0392]: parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 + | +LL | pub struct Dependent([(); X]); + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0770. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr new file mode 100644 index 000000000..32f7dea82 --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr @@ -0,0 +1,19 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/const-param-type-depends-on-type-param.rs:11:34 + | +LL | pub struct Dependent([(); X]); + | ^ the type must not depend on the parameter `T` + +error[E0392]: parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 + | +LL | pub struct Dependent([(); X]); + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0770. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs new file mode 100644 index 000000000..71d91fd7e --- /dev/null +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -0,0 +1,15 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +// Currently, const parameters cannot depend on other generic parameters, +// as our current implementation can't really support this. +// +// We may want to lift this restriction in the future. + +pub struct Dependent([(); X]); +//~^ ERROR: the type of const parameters must not depend on other generic parameters +//~| ERROR: parameter `T` is never used + +fn main() {} diff --git a/tests/ui/const-generics/const-parameter-uppercase-lint.rs b/tests/ui/const-generics/const-parameter-uppercase-lint.rs new file mode 100644 index 000000000..b08d62ccc --- /dev/null +++ b/tests/ui/const-generics/const-parameter-uppercase-lint.rs @@ -0,0 +1,7 @@ +#![deny(non_upper_case_globals)] + +fn noop() { + //~^ ERROR const parameter `x` should have an upper case name +} + +fn main() {} diff --git a/tests/ui/const-generics/const-parameter-uppercase-lint.stderr b/tests/ui/const-generics/const-parameter-uppercase-lint.stderr new file mode 100644 index 000000000..efaa18285 --- /dev/null +++ b/tests/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -0,0 +1,14 @@ +error: const parameter `x` should have an upper case name + --> $DIR/const-parameter-uppercase-lint.rs:3:15 + | +LL | fn noop() { + | ^ help: convert the identifier to upper case (notice the capitalization): `X` + | +note: the lint level is defined here + --> $DIR/const-parameter-uppercase-lint.rs:1:9 + | +LL | #![deny(non_upper_case_globals)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.rs b/tests/ui/const-generics/const_trait_fn-issue-88433.rs new file mode 100644 index 000000000..6e04cfaec --- /dev/null +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.rs @@ -0,0 +1,27 @@ +// build-pass + +#![feature(const_trait_impl)] + +#[const_trait] +trait Func { + type Output; + + fn call_once(self, arg: T) -> Self::Output; +} + + +struct Closure; + +impl const Func<&usize> for Closure { + type Output = usize; + + fn call_once(self, arg: &usize) -> Self::Output { + *arg + } +} + +enum Bug { + V(T), +} + +fn main() {} diff --git a/tests/ui/const-generics/core-types.rs b/tests/ui/const-generics/core-types.rs new file mode 100644 index 000000000..91410c4af --- /dev/null +++ b/tests/ui/const-generics/core-types.rs @@ -0,0 +1,50 @@ +// Check that all types allowed with `min_const_generics` work. +// run-pass +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct A; +struct B; +struct C; +struct D; +struct E; +struct F; +struct G; +struct H; +struct I; +struct J; +struct K; +struct L; +struct M; +struct N; + +fn main() { + let _ = A::<{u8::MIN}>; + let _ = A::<{u8::MAX}>; + let _ = B::<{u16::MIN}>; + let _ = B::<{u16::MAX}>; + let _ = C::<{u32::MIN}>; + let _ = C::<{u32::MAX}>; + let _ = D::<{u64::MIN}>; + let _ = D::<{u64::MAX}>; + let _ = E::<{u128::MIN}>; + let _ = E::<{u128::MAX}>; + let _ = F::<{usize::MIN}>; + let _ = F::<{usize::MAX}>; + let _ = G::<{i8::MIN}>; + let _ = G::<{i8::MAX}>; + let _ = H::<{i16::MIN}>; + let _ = H::<{i16::MAX}>; + let _ = I::<{i32::MIN}>; + let _ = I::<{i32::MAX}>; + let _ = J::<{i64::MIN}>; + let _ = J::<{i64::MAX}>; + let _ = K::<{i128::MIN}>; + let _ = K::<{i128::MAX}>; + let _ = L::<{isize::MIN}>; + let _ = L::<{isize::MAX}>; + let _ = M::<'A'>; + let _ = N::; +} diff --git a/tests/ui/const-generics/cross_crate_complex.rs b/tests/ui/const-generics/cross_crate_complex.rs new file mode 100644 index 000000000..ebde155f7 --- /dev/null +++ b/tests/ui/const-generics/cross_crate_complex.rs @@ -0,0 +1,23 @@ +// aux-build:crayte.rs +// edition:2018 +// run-pass +extern crate crayte; + +use crayte::*; + +async fn foo() { + in_foo(out_foo::<3>()); + async_simple([0; 17]).await; + async_in_foo(async_out_foo::<4>().await).await; +} + +struct Faz; + +impl Foo for Faz {} +impl Bar for Faz { + type Assoc = Faz; +} + +fn main() { + let _ = foo; +} diff --git a/tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs new file mode 100644 index 000000000..eed982534 --- /dev/null +++ b/tests/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -0,0 +1,11 @@ +pub struct Defaulted; +impl Defaulted { + pub fn new() -> Self { + Defaulted + } +} +impl Defaulted { + pub fn value(&self) -> usize { + N + } +} diff --git a/tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs b/tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs new file mode 100644 index 000000000..26a2c47ff --- /dev/null +++ b/tests/ui/const-generics/defaults/auxiliary/trait_object_lt_defaults_lib.rs @@ -0,0 +1 @@ +pub struct Foo<'a, const N: usize, T: 'a + ?Sized>(pub &'a T, [(); N]); diff --git a/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr new file mode 100644 index 000000000..b836cfeae --- /dev/null +++ b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:6:47 + | +LL | struct Foo; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-generic-default-expr.rs:9:62 + | +LL | struct Bar() }>(T); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/defaults/complex-generic-default-expr.rs b/tests/ui/const-generics/defaults/complex-generic-default-expr.rs new file mode 100644 index 000000000..7f50d4c9f --- /dev/null +++ b/tests/ui/const-generics/defaults/complex-generic-default-expr.rs @@ -0,0 +1,12 @@ +// revisions: full min +//[full] check-pass +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo; +//[min]~^ ERROR generic parameters may not be used in const operations + +struct Bar() }>(T); +//[min]~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/const-generics/defaults/complex-unord-param.rs b/tests/ui/const-generics/defaults/complex-unord-param.rs new file mode 100644 index 000000000..aebc5975a --- /dev/null +++ b/tests/ui/const-generics/defaults/complex-unord-param.rs @@ -0,0 +1,17 @@ +// run-pass +// Checks a complicated usage of unordered params +#![allow(dead_code)] + +struct NestedArrays<'a, const N: usize, A: 'a, const M: usize, T:'a =u32> { + args: &'a [&'a [T; M]; N], + specifier: A, +} + +fn main() { + let array = [1, 2, 3]; + let nest = [&array]; + let _ = NestedArrays { + args: &nest, + specifier: true, + }; +} diff --git a/tests/ui/const-generics/defaults/const-default.rs b/tests/ui/const-generics/defaults/const-default.rs new file mode 100644 index 000000000..65cb0eb14 --- /dev/null +++ b/tests/ui/const-generics/defaults/const-default.rs @@ -0,0 +1,24 @@ +// run-pass +pub struct ConstDefault; + +impl ConstDefault { + fn foo(self) -> usize { + N + } +} + +impl ConstDefault { + fn new() -> Self { + ConstDefault + } + + fn bar(self) {} +} + +pub fn main() { + let s = ConstDefault::new(); + assert_eq!(s.foo(), 3); + + let w = ConstDefault::<3>; + w.bar(); +} diff --git a/tests/ui/const-generics/defaults/const-param-as-default-value.rs b/tests/ui/const-generics/defaults/const-param-as-default-value.rs new file mode 100644 index 000000000..c1c955d87 --- /dev/null +++ b/tests/ui/const-generics/defaults/const-param-as-default-value.rs @@ -0,0 +1,21 @@ +// run-pass +struct Foo([u8; N], [u8; M]); + +fn foo() -> Foo { + let x = [0; N]; + Foo(x, x) +} + +// To check that we actually apply the correct substs for const param defaults. +fn concrete_foo() -> Foo<13> { + Foo(Default::default(), Default::default()) +} + + +fn main() { + let val = foo::<13>(); + assert_eq!(val.0, val.1); + + let val = concrete_foo(); + assert_eq!(val.0, val.1); +} diff --git a/tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs new file mode 100644 index 000000000..5f0cafe2e --- /dev/null +++ b/tests/ui/const-generics/defaults/const-param-in-ty-defaults.rs @@ -0,0 +1,12 @@ +// run-pass +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo([0; N]) + } +} + +fn main() { + assert_eq!(Foo::new().0, [0; 10]); +} diff --git a/tests/ui/const-generics/defaults/default-annotation.rs b/tests/ui/const-generics/defaults/default-annotation.rs new file mode 100644 index 000000000..7a9f5732f --- /dev/null +++ b/tests/ui/const-generics/defaults/default-annotation.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(staged_api)] +#![allow(incomplete_features)] +// FIXME(const_generics_defaults): It seems like we aren't testing the right thing here, +// I would assume that we want the attributes to apply to the const parameter defaults +// themselves. +#![stable(feature = "const_default_test", since="none")] + +#[unstable(feature = "const_default_stable", issue="none")] +pub struct ConstDefaultUnstable; + +#[stable(feature = "const_default_unstable", since="none")] +pub struct ConstDefaultStable; + +fn main() {} diff --git a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs new file mode 100644 index 000000000..45275e609 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.rs @@ -0,0 +1,14 @@ +struct Struct; +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +enum Enum { } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +union Union { not_empty: () } +//~^ ERROR generic parameters cannot use `Self` in their defaults [E0735] + +fn main() { + let _: Struct; + let _: Enum; + let _: Union; +} diff --git a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr new file mode 100644 index 000000000..72d7001fd --- /dev/null +++ b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr @@ -0,0 +1,21 @@ +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:1:34 + | +LL | struct Struct; + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:4:30 + | +LL | enum Enum { } + | ^^^^ `Self` in generic parameter default + +error[E0735]: generic parameters cannot use `Self` in their defaults + --> $DIR/default-const-param-cannot-reference-self.rs:7:32 + | +LL | union Union { not_empty: () } + | ^^^^ `Self` in generic parameter default + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0735`. diff --git a/tests/ui/const-generics/defaults/default-on-impl.rs b/tests/ui/const-generics/defaults/default-on-impl.rs new file mode 100644 index 000000000..9ce46aa09 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-on-impl.rs @@ -0,0 +1,6 @@ +struct Foo; + +impl Foo {} +//~^ ERROR defaults for const parameters are only allowed + +fn main() {} diff --git a/tests/ui/const-generics/defaults/default-on-impl.stderr b/tests/ui/const-generics/defaults/default-on-impl.stderr new file mode 100644 index 000000000..4b2b05742 --- /dev/null +++ b/tests/ui/const-generics/defaults/default-on-impl.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default-on-impl.rs:3:6 + | +LL | impl Foo {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs new file mode 100644 index 000000000..41a52c7eb --- /dev/null +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -0,0 +1,3 @@ +struct Foo; +//~^ ERROR evaluation of constant value failed +fn main() {} diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr new file mode 100644 index 000000000..e8ebddade --- /dev/null +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/default-param-wf-concrete.rs:1:28 + | +LL | struct Foo; + | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/doesnt_infer.rs b/tests/ui/const-generics/defaults/doesnt_infer.rs new file mode 100644 index 000000000..9c59e672d --- /dev/null +++ b/tests/ui/const-generics/defaults/doesnt_infer.rs @@ -0,0 +1,13 @@ +// test that defaulted const params are not used to help type inference + +struct Foo; + +impl Foo { + fn foo() -> Self { loop {} } +} + +fn main() { + let foo = Foo::<1>::foo(); + let foo = Foo::foo(); + //~^ error: type annotations needed for `Foo` +} diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr new file mode 100644 index 000000000..227b2f402 --- /dev/null +++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Foo` + --> $DIR/doesnt_infer.rs:11:9 + | +LL | let foo = Foo::foo(); + | ^^^ + | +help: consider giving `foo` an explicit type, where the the value of const parameter `N` is specified + | +LL | let foo: Foo = Foo::foo(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/defaults/external.rs b/tests/ui/const-generics/defaults/external.rs new file mode 100644 index 000000000..25ec523cb --- /dev/null +++ b/tests/ui/const-generics/defaults/external.rs @@ -0,0 +1,24 @@ +// aux-build:const_defaulty.rs +// check-pass +extern crate const_defaulty; +use const_defaulty::Defaulted; + +struct Local; +impl Local { + fn new() -> Self { + Local + } +} +implLocal { + fn value(&self) -> usize { + N + } +} + +fn main() { + let v = Defaulted::new(); + assert_eq!(v.value(), 3); + + let l = Local::new(); + assert_eq!(l.value(), 4); +} diff --git a/tests/ui/const-generics/defaults/forward-declared.rs b/tests/ui/const-generics/defaults/forward-declared.rs new file mode 100644 index 000000000..ede3d873b --- /dev/null +++ b/tests/ui/const-generics/defaults/forward-declared.rs @@ -0,0 +1,13 @@ +struct Foo; +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +enum Bar {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +struct Foo2; +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +enum Bar2 {} +//~^ ERROR generic parameters with a default cannot use forward declared identifiers + +fn main() {} diff --git a/tests/ui/const-generics/defaults/forward-declared.stderr b/tests/ui/const-generics/defaults/forward-declared.stderr new file mode 100644 index 000000000..4856c7a1f --- /dev/null +++ b/tests/ui/const-generics/defaults/forward-declared.stderr @@ -0,0 +1,27 @@ +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:1:29 + | +LL | struct Foo; + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:4:27 + | +LL | enum Bar {} + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:7:30 + | +LL | struct Foo2; + | ^ defaulted generic parameters cannot be forward declared + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/forward-declared.rs:10:28 + | +LL | enum Bar2 {} + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default-concrete.rs b/tests/ui/const-generics/defaults/generic-expr-default-concrete.rs new file mode 100644 index 000000000..f082bd8d2 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-concrete.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; +fn no_constraining() -> Foo<10> { + Foo::<10, 11> +} + +pub fn different_than_default() -> Foo<10> { + Foo::<10, 12> + //~^ error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr b/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr new file mode 100644 index 000000000..61b355118 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-concrete.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/generic-expr-default-concrete.rs:10:5 + | +LL | Foo::<10, 12> + | ^^^^^^^^^^^^^ expected `11`, found `12` + | + = note: expected constant `11` + found constant `12` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs new file mode 100644 index 000000000..777865d1c --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs @@ -0,0 +1,16 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; +fn should_unify() -> Foo where [(); { N + 1 }]: { + Foo:: +} +pub fn shouldnt_unify() -> Foo +where + [(); { N + 1 }]:, + [(); { N + 2 }]:, { + Foo:: + //~^ error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr new file mode 100644 index 000000000..e83f89a60 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/generic-expr-default-mismatched-types.rs:12:5 + | +LL | Foo:: + | ^^^^^^^^^^^^^^^^^^^ expected `{ N + 1 }`, found `{ N + 2 }` + | + = note: expected constant `{ N + 1 }` + found constant `{ N + 2 }` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/generic-expr-default.rs b/tests/ui/const-generics/defaults/generic-expr-default.rs new file mode 100644 index 000000000..8fe43feb7 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default.rs @@ -0,0 +1,24 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo; +pub fn needs_evaluatable_bound() -> Foo { + //~^ error: unconstrained generic constant + loop {} +} +pub fn has_evaluatable_bound() -> Foo where [(); N1 + 1]: { + loop {} +} + +type FooAlias = [(); NP]; +fn needs_evaluatable_bound_alias() -> FooAlias +{ + //~^^ error: unconstrained generic constant + todo!() +} +fn has_evaluatable_bound_alias() -> FooAlias +where [(); N + 1]: { + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/generic-expr-default.stderr b/tests/ui/const-generics/defaults/generic-expr-default.stderr new file mode 100644 index 000000000..ada1498d1 --- /dev/null +++ b/tests/ui/const-generics/defaults/generic-expr-default.stderr @@ -0,0 +1,18 @@ +error: unconstrained generic constant + --> $DIR/generic-expr-default.rs:5:54 + | +LL | pub fn needs_evaluatable_bound() -> Foo { + | ^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:` + +error: unconstrained generic constant + --> $DIR/generic-expr-default.rs:14:58 + | +LL | fn needs_evaluatable_bound_alias() -> FooAlias + | ^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/defaults/intermixed-lifetime.rs b/tests/ui/const-generics/defaults/intermixed-lifetime.rs new file mode 100644 index 000000000..beaf7fc60 --- /dev/null +++ b/tests/ui/const-generics/defaults/intermixed-lifetime.rs @@ -0,0 +1,9 @@ +// Checks that lifetimes cannot be interspersed between consts and types. + +struct Foo(&'a (), T); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +struct Bar(&'a (), T); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +fn main() {} diff --git a/tests/ui/const-generics/defaults/intermixed-lifetime.stderr b/tests/ui/const-generics/defaults/intermixed-lifetime.stderr new file mode 100644 index 000000000..5cff61dd9 --- /dev/null +++ b/tests/ui/const-generics/defaults/intermixed-lifetime.stderr @@ -0,0 +1,14 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/intermixed-lifetime.rs:3:28 + | +LL | struct Foo(&'a (), T); + | -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` + +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/intermixed-lifetime.rs:6:37 + | +LL | struct Bar(&'a (), T); + | --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/defaults/mismatch.rs b/tests/ui/const-generics/defaults/mismatch.rs new file mode 100644 index 000000000..ec131505e --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatch.rs @@ -0,0 +1,22 @@ +pub struct Example; +pub struct Example2(T); +pub struct Example3(T); +pub struct Example4; + +fn main() { + let e: Example<13> = (); + //~^ Error: mismatched types + //~| expected struct `Example` + let e: Example2 = (); + //~^ Error: mismatched types + //~| expected struct `Example2` + let e: Example3<13, u32> = (); + //~^ Error: mismatched types + //~| expected struct `Example3` + let e: Example3<7> = (); + //~^ Error: mismatched types + //~| expected struct `Example3<7>` + let e: Example4<7> = (); + //~^ Error: mismatched types + //~| expected struct `Example4<7>` +} diff --git a/tests/ui/const-generics/defaults/mismatch.stderr b/tests/ui/const-generics/defaults/mismatch.stderr new file mode 100644 index 000000000..52c54aace --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatch.stderr @@ -0,0 +1,58 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:7:26 + | +LL | let e: Example<13> = (); + | ----------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + | + = note: expected struct `Example` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:10:32 + | +LL | let e: Example2 = (); + | ----------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:13:32 + | +LL | let e: Example3<13, u32> = (); + | ----------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:16:26 + | +LL | let e: Example3<7> = (); + | ----------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:19:26 + | +LL | let e: Example4<7> = (); + | ----------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + | + = note: expected struct `Example4<7>` + found unit type `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs new file mode 100644 index 000000000..5c9323261 --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs @@ -0,0 +1,41 @@ +trait Trait { + fn foo() {} +} +impl Trait for () { + fn foo() {} + //~^ error: method `foo` has an incompatible generic parameter for trait +} + +trait Other { + fn bar() {} +} +impl Other for () { + fn bar() {} + //~^ error: method `bar` has an incompatible generic parameter for trait +} + +trait Uwu { + fn baz() {} +} +impl Uwu for () { + fn baz() {} + //~^ error: method `baz` has an incompatible generic parameter for trait +} + +trait Aaaaaa { + fn bbbb() {} +} +impl Aaaaaa for () { + fn bbbb() {} + //~^ error: method `bbbb` has an incompatible generic parameter for trait +} + +trait Names { + fn abcd() {} +} +impl Names for () { + fn abcd() {} + //~^ error: method `abcd` has an incompatible generic parameter for trait +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr new file mode 100644 index 000000000..3455f2c8e --- /dev/null +++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr @@ -0,0 +1,68 @@ +error[E0053]: method `foo` has an incompatible generic parameter for trait `Trait` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:5:12 + | +LL | trait Trait { + | ----- +LL | fn foo() {} + | - expected type parameter +LL | } +LL | impl Trait for () { + | ----------------- +LL | fn foo() {} + | ^^^^^^^^^^^^ found const parameter of type `u64` + +error[E0053]: method `bar` has an incompatible generic parameter for trait `Other` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:13:12 + | +LL | trait Other { + | ----- +LL | fn bar() {} + | ----------- expected const parameter of type `u8` +LL | } +LL | impl Other for () { + | ----------------- +LL | fn bar() {} + | ^ found type parameter + +error[E0053]: method `baz` has an incompatible generic parameter for trait `Uwu` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:21:12 + | +LL | trait Uwu { + | --- +LL | fn baz() {} + | ------------ expected const parameter of type `u32` +LL | } +LL | impl Uwu for () { + | --------------- +LL | fn baz() {} + | ^^^^^^^^^^^^ found const parameter of type `i32` + +error[E0053]: method `bbbb` has an incompatible generic parameter for trait `Aaaaaa` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:29:13 + | +LL | trait Aaaaaa { + | ------ +LL | fn bbbb() {} + | ------------ expected const parameter of type `u32` +LL | } +LL | impl Aaaaaa for () { + | ------------------ +LL | fn bbbb() {} + | ^ found type parameter + +error[E0053]: method `abcd` has an incompatible generic parameter for trait `Names` + --> $DIR/mismatched_ty_const_in_trait_impl.rs:37:13 + | +LL | trait Names { + | ----- +LL | fn abcd() {} + | - expected type parameter +LL | } +LL | impl Names for () { + | ----------------- +LL | fn abcd() {} + | ^^^^^^^^^^^^ found const parameter of type `u32` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs new file mode 100644 index 000000000..f928fc9e7 --- /dev/null +++ b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.rs @@ -0,0 +1,4 @@ +struct Foo(&'a u32); +//~^ ERROR lifetime parameters must be declared prior to type and const parameters + +fn main() {} diff --git a/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr new file mode 100644 index 000000000..ba08b4646 --- /dev/null +++ b/tests/ui/const-generics/defaults/param-order-err-pretty-prints-default.stderr @@ -0,0 +1,8 @@ +error: lifetime parameters must be declared prior to type and const parameters + --> $DIR/param-order-err-pretty-prints-default.rs:1:33 + | +LL | struct Foo(&'a u32); + | ----------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const M: usize = 10>` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.rs b/tests/ui/const-generics/defaults/pretty-printing-ast.rs new file mode 100644 index 000000000..e202d4e86 --- /dev/null +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.rs @@ -0,0 +1,11 @@ +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] + +trait Foo {} + +fn foo() {} + +struct Range; diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout new file mode 100644 index 000000000..121138605 --- /dev/null +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -0,0 +1,18 @@ +#![feature(prelude_import)] +#![no_std] +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +trait Foo {} + +fn foo() {} + +struct Range; diff --git a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs new file mode 100644 index 000000000..118da2723 --- /dev/null +++ b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -0,0 +1,11 @@ +// Regression test for #82792. + +// run-pass + +#[repr(C)] +pub struct Loaf { + head: [T; N], + slice: [T], +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/rp_impl_trait.rs b/tests/ui/const-generics/defaults/rp_impl_trait.rs new file mode 100644 index 000000000..dde8eea45 --- /dev/null +++ b/tests/ui/const-generics/defaults/rp_impl_trait.rs @@ -0,0 +1,29 @@ +// run-pass +struct Uwu; + +trait Trait {} +impl Trait for Uwu {} + +fn rawr() -> impl Trait { + Uwu:: +} + +trait Traitor { } + +impl Traitor for u32 {} +impl Traitor<1, 1> for u64 {} + +fn uwu() -> impl Traitor { + 1_u32 +} + +fn owo() -> impl Traitor { + 1_u64 +} + +fn main() { + rawr::<3>(); + rawr::<7>(); + uwu::<{ u8::MAX }>(); + owo(); +} diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs new file mode 100644 index 000000000..80013e7b4 --- /dev/null +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -0,0 +1,30 @@ +struct Uwu; + +trait Trait {} +impl Trait for Uwu {} + +fn rawr() -> impl Trait { + //~^ error: the trait bound `Uwu<10, 12>: Trait` is not satisfied + Uwu::<10, 12> +} + +trait Traitor {} + +impl Traitor for u32 {} +impl Traitor<1, 2> for u64 {} + +fn uwu() -> impl Traitor { + //~^ error: the trait bound `u32: Traitor` is not satisfied + 1_u32 +} + +fn owo() -> impl Traitor { + //~^ error: the trait bound `u64: Traitor` is not satisfied + 1_u64 +} + +fn main() { + rawr(); + uwu(); + owo(); +} diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr new file mode 100644 index 000000000..a46bd5352 --- /dev/null +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -0,0 +1,36 @@ +error[E0277]: the trait bound `Uwu<10, 12>: Trait` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:6:14 + | +LL | fn rawr() -> impl Trait { + | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10, 12>` +LL | +LL | Uwu::<10, 12> + | ------------- return type was inferred to be `Uwu<10, 12>` here + | + = help: the trait `Trait` is implemented for `Uwu` + +error[E0277]: the trait bound `u32: Traitor` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:16:26 + | +LL | fn uwu() -> impl Traitor { + | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` +LL | +LL | 1_u32 + | ----- return type was inferred to be `u32` here + | + = help: the trait `Traitor` is implemented for `u32` + +error[E0277]: the trait bound `u64: Traitor` is not satisfied + --> $DIR/rp_impl_trait_fail.rs:21:13 + | +LL | fn owo() -> impl Traitor { + | ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64` +LL | +LL | 1_u64 + | ----- return type was inferred to be `u64` here + | + = help: the trait `Traitor<1, 2>` is implemented for `u64` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/defaults/self-referential.rs b/tests/ui/const-generics/defaults/self-referential.rs new file mode 100644 index 000000000..14a870dc3 --- /dev/null +++ b/tests/ui/const-generics/defaults/self-referential.rs @@ -0,0 +1,4 @@ +trait Foo {} +//~^ ERROR the name `M` is already used for a generic parameter in this item's generic parameters +impl Foo<2> for () {} +fn main() {} diff --git a/tests/ui/const-generics/defaults/self-referential.stderr b/tests/ui/const-generics/defaults/self-referential.stderr new file mode 100644 index 000000000..170c1f7f7 --- /dev/null +++ b/tests/ui/const-generics/defaults/self-referential.stderr @@ -0,0 +1,11 @@ +error[E0403]: the name `M` is already used for a generic parameter in this item's generic parameters + --> $DIR/self-referential.rs:1:30 + | +LL | trait Foo {} + | - ^ already used + | | + | first use of `M` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/tests/ui/const-generics/defaults/simple-defaults.rs b/tests/ui/const-generics/defaults/simple-defaults.rs new file mode 100644 index 000000000..6a782d223 --- /dev/null +++ b/tests/ui/const-generics/defaults/simple-defaults.rs @@ -0,0 +1,13 @@ +// run-pass +// Checks that type param defaults are allowed after const params. +#![allow(dead_code)] + +struct FixedOutput<'a, const N: usize, T=u32> { + out: &'a [T; N], +} + +trait FixedOutputter { + fn out(&self) -> FixedOutput<'_, 10>; +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/trait_object_lt_defaults.rs b/tests/ui/const-generics/defaults/trait_object_lt_defaults.rs new file mode 100644 index 000000000..a1828727e --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_object_lt_defaults.rs @@ -0,0 +1,24 @@ +// aux-build:trait_object_lt_defaults_lib.rs +// run-pass +#![allow(dead_code)] +extern crate trait_object_lt_defaults_lib; + +// Tests that `A<'a, 3, dyn Test>` is short for `A<'a, 3, dyn Test + 'a>` +// and `Foo<'a, 3, dyn Test>` is short for `Foo<'a, 3, dyn Test + 'a>` +// Test is in `const-generics/defaults` because it relies on param ordering + +trait Test {} + +struct A<'a, const N: usize, T: ?Sized + 'a>(&'a T, [(); N]); +fn blah<'a>(mut a: A<'a, 3, dyn Test>, arg: &'a (dyn Test + 'a)) { + a.0 = arg; +} + +fn other_blah<'a>( + mut a: trait_object_lt_defaults_lib::Foo<'a, 3, dyn Test>, + arg: &'a (dyn Test + 'a), +) { + a.0 = arg; +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/trait_objects.rs b/tests/ui/const-generics/defaults/trait_objects.rs new file mode 100644 index 000000000..750e40313 --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_objects.rs @@ -0,0 +1,43 @@ +// run-pass +trait Trait { + fn uwu(&self) -> u8 { + N + } +} + +impl Trait for u32 {} + +impl Trait<12> for u64 { + fn uwu(&self) -> u8 { + *self as u8 + } +} + +fn foo(arg: &dyn Trait) -> u8 { + arg.uwu() +} + +trait Traitor { + fn owo(&self) -> u8 { + M + } +} + +impl Traitor<2> for bool { } +impl Traitor for u8 { + fn owo(&self) -> u8 { + *self + } +} + +fn bar(arg: &dyn Traitor) -> u8 { + arg.owo() +} + +fn main() { + assert_eq!(foo(&10_u32), 12); + assert_eq!(foo(&3_u64), 3); + + assert_eq!(bar(&true), 2); + assert_eq!(bar(&1_u8), 1); +} diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.rs b/tests/ui/const-generics/defaults/trait_objects_fail.rs new file mode 100644 index 000000000..6ab803f99 --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_objects_fail.rs @@ -0,0 +1,30 @@ +trait Trait { + fn uwu(&self) -> u8 { + N + } +} + +impl Trait<2> for u32 {} + +fn foo(arg: &dyn Trait) -> u8 { + arg.uwu() +} + +trait Traitor { + fn owo(&self) -> u8 { + M + } +} + +impl Traitor<2, 3> for bool {} + +fn bar(arg: &dyn Traitor) -> u8 { + arg.owo() +} + +fn main() { + foo(&10_u32); + //~^ error: the trait bound `u32: Trait` is not satisfied + bar(&true); + //~^ error: the trait bound `bool: Traitor<_>` is not satisfied +} diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.stderr b/tests/ui/const-generics/defaults/trait_objects_fail.stderr new file mode 100644 index 000000000..0e8334d03 --- /dev/null +++ b/tests/ui/const-generics/defaults/trait_objects_fail.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `u32: Trait` is not satisfied + --> $DIR/trait_objects_fail.rs:26:9 + | +LL | foo(&10_u32); + | ^^^^^^^ the trait `Trait` is not implemented for `u32` + | + = help: the trait `Trait<2>` is implemented for `u32` + = note: required for the cast from `u32` to the object type `dyn Trait` + +error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied + --> $DIR/trait_objects_fail.rs:28:9 + | +LL | bar(&true); + | ^^^^^ the trait `Traitor<_>` is not implemented for `bool` + | + = help: the trait `Traitor<2, 3>` is implemented for `bool` + = note: required for the cast from `bool` to the object type `dyn Traitor<_>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/defaults/type-default-const-param-name.rs b/tests/ui/const-generics/defaults/type-default-const-param-name.rs new file mode 100644 index 000000000..405664ded --- /dev/null +++ b/tests/ui/const-generics/defaults/type-default-const-param-name.rs @@ -0,0 +1,14 @@ +// check-pass +struct N; + +struct Foo(T); + +impl Foo { + fn new() -> Self { + Foo(N) + } +} + +fn main() { + let Foo::<1, N>(N) = Foo::new(); +} diff --git a/tests/ui/const-generics/defaults/wfness.rs b/tests/ui/const-generics/defaults/wfness.rs new file mode 100644 index 000000000..a93f67081 --- /dev/null +++ b/tests/ui/const-generics/defaults/wfness.rs @@ -0,0 +1,23 @@ +struct Ooopsies; +//~^ error: evaluation of constant value failed + +trait Trait {} +impl Trait<3> for () {} +struct WhereClause +where + (): Trait; +//~^ error: the trait bound `(): Trait<2>` is not satisfied + +trait Traitor {} +struct WhereClauseTooGeneric(T) +where + (): Traitor; + +// no error on struct def +struct DependentDefaultWfness>(T); +fn foo() -> DependentDefaultWfness { + //~^ error: the trait bound `(): Trait<1>` is not satisfied + loop {} +} + +fn main() {} diff --git a/tests/ui/const-generics/defaults/wfness.stderr b/tests/ui/const-generics/defaults/wfness.stderr new file mode 100644 index 000000000..25038f830 --- /dev/null +++ b/tests/ui/const-generics/defaults/wfness.stderr @@ -0,0 +1,34 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/wfness.rs:1:33 + | +LL | struct Ooopsies; + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +error[E0277]: the trait bound `(): Trait<2>` is not satisfied + --> $DIR/wfness.rs:8:9 + | +LL | (): Trait; + | ^^^^^^^^ the trait `Trait<2>` is not implemented for `()` + | + = help: the trait `Trait<3>` is implemented for `()` + +error[E0277]: the trait bound `(): Trait<1>` is not satisfied + --> $DIR/wfness.rs:18:13 + | +LL | fn foo() -> DependentDefaultWfness { + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()` + | + = help: the trait `Trait<3>` is implemented for `()` +note: required by a bound in `WhereClause` + --> $DIR/wfness.rs:8:9 + | +LL | struct WhereClause + | ----------- required by a bound in this +LL | where +LL | (): Trait; + | ^^^^^^^^ required by this bound in `WhereClause` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/defaults/wrong-order.rs b/tests/ui/const-generics/defaults/wrong-order.rs new file mode 100644 index 000000000..d53d56f41 --- /dev/null +++ b/tests/ui/const-generics/defaults/wrong-order.rs @@ -0,0 +1,9 @@ +struct A { + //~^ ERROR generic parameters with a default must be trailing + arg: T, +} + +struct Foo(T); +//~^ error: generic parameters with a default must be trailing + +fn main() {} diff --git a/tests/ui/const-generics/defaults/wrong-order.stderr b/tests/ui/const-generics/defaults/wrong-order.stderr new file mode 100644 index 000000000..4d2628d03 --- /dev/null +++ b/tests/ui/const-generics/defaults/wrong-order.stderr @@ -0,0 +1,14 @@ +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:1:10 + | +LL | struct A { + | ^ + +error: generic parameters with a default must be trailing + --> $DIR/wrong-order.rs:6:18 + | +LL | struct Foo(T); + | ^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/deref-into-array-generic.rs b/tests/ui/const-generics/deref-into-array-generic.rs new file mode 100644 index 000000000..7d75af12b --- /dev/null +++ b/tests/ui/const-generics/deref-into-array-generic.rs @@ -0,0 +1,27 @@ +// check-pass + +struct Test([T; N]); + +impl Default for Test { + fn default() -> Self { + Self([T::default(); N]) + } +} + +impl std::ops::Deref for Test { + type Target = [T; N]; + + fn deref(&self) -> &[T; N] { + &self.0 + } +} + +fn test() -> Test { + let test = Test::default(); + println!("{}", test.len()); + test +} + +fn main() { + test(); +} diff --git a/tests/ui/const-generics/different_generic_args.full.stderr b/tests/ui/const-generics/different_generic_args.full.stderr new file mode 100644 index 000000000..eba1768f7 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args.full.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/different_generic_args.rs:11:9 + | +LL | u = ConstUsize::<4> {}; + | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4` + | + = note: expected struct `ConstUsize<3>` + found struct `ConstUsize<4>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/different_generic_args.min.stderr b/tests/ui/const-generics/different_generic_args.min.stderr new file mode 100644 index 000000000..eba1768f7 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args.min.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/different_generic_args.rs:11:9 + | +LL | u = ConstUsize::<4> {}; + | ^^^^^^^^^^^^^^^^^^ expected `3`, found `4` + | + = note: expected struct `ConstUsize<3>` + found struct `ConstUsize<4>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/different_generic_args.rs b/tests/ui/const-generics/different_generic_args.rs new file mode 100644 index 000000000..9ee0e0747 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args.rs @@ -0,0 +1,13 @@ +// Check that types with different const arguments are different. +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct ConstUsize {} + +fn main() { + let mut u = ConstUsize::<3> {}; + u = ConstUsize::<4> {}; + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/different_generic_args_array.rs b/tests/ui/const-generics/different_generic_args_array.rs new file mode 100644 index 000000000..4d225dfdd --- /dev/null +++ b/tests/ui/const-generics/different_generic_args_array.rs @@ -0,0 +1,11 @@ +// Check that different const types are different. +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +struct Const {} + +fn main() { + let mut x = Const::<{ [3] }> {}; + x = Const::<{ [4] }> {}; + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/different_generic_args_array.stderr b/tests/ui/const-generics/different_generic_args_array.stderr new file mode 100644 index 000000000..4c5b5ada4 --- /dev/null +++ b/tests/ui/const-generics/different_generic_args_array.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/different_generic_args_array.rs:9:9 + | +LL | x = Const::<{ [4] }> {}; + | ^^^^^^^^^^^^^^^^^^^ expected `[3]`, found `[4]` + | + = note: expected struct `Const<[3]>` + found struct `Const<[4]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs new file mode 100644 index 000000000..6c4ee1af2 --- /dev/null +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that during error handling for the "trait not implemented" error +// we dont try to evaluate std::mem::size_of:: causing an ICE + +struct Adt; + +trait Foo { + type Assoc; + fn foo() + where + [Adt; std::mem::size_of::()]: , + { + <[Adt; std::mem::size_of::()] as Foo>::bar() + //~^ Error: the trait bound + } + + fn bar() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr new file mode 100644 index 000000000..d8eebeb0d --- /dev/null +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `[Adt; std::mem::size_of::()]: Foo` is not satisfied + --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:9 + | +LL | <[Adt; std::mem::size_of::()] as Foo>::bar() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::()]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/dyn-supertraits.rs b/tests/ui/const-generics/dyn-supertraits.rs new file mode 100644 index 000000000..3dee326a1 --- /dev/null +++ b/tests/ui/const-generics/dyn-supertraits.rs @@ -0,0 +1,80 @@ +// run-pass + +trait Foo { + fn myfun(&self) -> usize; +} +trait Bar : Foo {} +trait Baz: Foo<3> {} + +struct FooType; +struct BarType; +struct BazType; + +impl Foo for FooType { + fn myfun(&self) -> usize { N } +} +impl Foo for BarType { + fn myfun(&self) -> usize { N + 1 } +} +impl Bar for BarType {} +impl Foo<3> for BazType { + fn myfun(&self) -> usize { 999 } +} +impl Baz for BazType {} + +trait Foz {} +trait Boz: Foo<3> + Foz {} +trait Bok: Foo + Foz {} + +struct FozType; +struct BozType; +struct BokType; + +impl Foz for FozType {} + +impl Foz for BozType {} +impl Foo<3> for BozType { + fn myfun(&self) -> usize { 9999 } +} +impl Boz for BozType {} + +impl Foz for BokType {} +impl Foo for BokType { + fn myfun(&self) -> usize { N + 2 } +} +impl Bok for BokType {} + +fn a(x: &dyn Foo) -> usize { x.myfun() } +fn b(x: &dyn Foo<3>) -> usize { x.myfun() } +fn c, const N: usize>(x: T) -> usize { a::(&x) } +fn d>(x: &T) -> usize { x.myfun() } +fn e(x: &dyn Bar<3>) -> usize { d(x) } + +fn main() { + let foo = FooType::<3> {}; + assert!(a(&foo) == 3); + assert!(b(&foo) == 3); + assert!(d(&foo) == 3); + + let bar = BarType::<3> {}; + assert!(a(&bar) == 4); + assert!(b(&bar) == 4); + assert!(d(&bar) == 4); + assert!(e(&bar) == 4); + + let baz = BazType {}; + assert!(a(&baz) == 999); + assert!(b(&baz) == 999); + assert!(d(&baz) == 999); + + let boz = BozType {}; + assert!(a(&boz) == 9999); + assert!(b(&boz) == 9999); + assert!(d(&boz) == 9999); + + let bok = BokType::<3> {}; + assert!(a(&bok) == 5); + assert!(b(&bok) == 5); + assert!(d(&bok) == 5); + assert!(c(BokType::<3> {}) == 5); +} diff --git a/tests/ui/const-generics/early/closing-args-token.rs b/tests/ui/const-generics/early/closing-args-token.rs new file mode 100644 index 000000000..cb4d6299e --- /dev/null +++ b/tests/ui/const-generics/early/closing-args-token.rs @@ -0,0 +1,26 @@ +struct S; +struct T; + +fn bad_args_1() { + S::<5 + 2 >> 7>; + //~^ ERROR expressions must be enclosed in braces to be used as const generic arguments + //~| ERROR comparison operators cannot be chained +} + +fn bad_args_2() { + S::<{ 5 + 2 } >> 7>; + //~^ ERROR comparison operators cannot be chained +} + +fn bad_args_3() { + T::<0 >= 3>; + //~^ ERROR expected expression, found `;` +} + +fn bad_args_4() { + let mut x = 0; + T::>= 2 > 0>; + //~^ ERROR comparison operators cannot be chained +} + +fn main() {} diff --git a/tests/ui/const-generics/early/closing-args-token.stderr b/tests/ui/const-generics/early/closing-args-token.stderr new file mode 100644 index 000000000..58fff3a85 --- /dev/null +++ b/tests/ui/const-generics/early/closing-args-token.stderr @@ -0,0 +1,52 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/closing-args-token.rs:5:9 + | +LL | S::<5 + 2 >> 7>; + | ^^^^^ + | +help: enclose the `const` expression in braces + | +LL | S::<{ 5 + 2 } >> 7>; + | + + + +error: comparison operators cannot be chained + --> $DIR/closing-args-token.rs:5:16 + | +LL | S::<5 + 2 >> 7>; + | ^ ^ + | +help: split the comparison into two + | +LL | S::<5 + 2 >> 7 && 7>; + | ++++ + +error: comparison operators cannot be chained + --> $DIR/closing-args-token.rs:11:20 + | +LL | S::<{ 5 + 2 } >> 7>; + | ^ ^ + | +help: split the comparison into two + | +LL | S::<{ 5 + 2 } >> 7 && 7>; + | ++++ + +error: expected expression, found `;` + --> $DIR/closing-args-token.rs:16:16 + | +LL | T::<0 >= 3>; + | ^ expected expression + +error: comparison operators cannot be chained + --> $DIR/closing-args-token.rs:22:12 + | +LL | T::>= 2 > 0>; + | ^^ ^ + | +help: split the comparison into two + | +LL | T::>= 2 && 2 > 0>; + | ++++ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/const-generics/early/const-expression-parameter.rs b/tests/ui/const-generics/early/const-expression-parameter.rs new file mode 100644 index 000000000..4cf7ba869 --- /dev/null +++ b/tests/ui/const-generics/early/const-expression-parameter.rs @@ -0,0 +1,19 @@ +fn i32_identity() -> i32 { + 5 +} + +fn foo_a() { + i32_identity::<-1>(); // ok +} + +fn foo_b() { + i32_identity::<1 + 2>(); //~ ERROR expressions must be enclosed in braces +} + +fn foo_c() { + i32_identity::< -1 >(); // ok +} + +fn main() { + i32_identity::<5>(); // ok +} diff --git a/tests/ui/const-generics/early/const-expression-parameter.stderr b/tests/ui/const-generics/early/const-expression-parameter.stderr new file mode 100644 index 000000000..4ce1be25e --- /dev/null +++ b/tests/ui/const-generics/early/const-expression-parameter.stderr @@ -0,0 +1,13 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/const-expression-parameter.rs:10:20 + | +LL | i32_identity::<1 + 2>(); + | ^^^^^ + | +help: enclose the `const` expression in braces + | +LL | i32_identity::<{ 1 + 2 }>(); + | + + + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.rs b/tests/ui/const-generics/early/const-param-from-outer-fn.rs new file mode 100644 index 000000000..c3b418ee3 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.rs @@ -0,0 +1,7 @@ +fn foo() { + fn bar() -> u32 { + X //~ ERROR can't use generic parameters from outer function + } +} + +fn main() {} diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr new file mode 100644 index 000000000..e3bf38b70 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr @@ -0,0 +1,13 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/const-param-from-outer-fn.rs:3:9 + | +LL | fn foo() { + | - const parameter from outer function +LL | fn bar() -> u32 { + | - help: try using a local generic parameter instead: `` +LL | X + | ^ use of generic parameter from outer function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/const-generics/early/const-param-hygiene.rs b/tests/ui/const-generics/early/const-param-hygiene.rs new file mode 100644 index 000000000..fd4e5b409 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-hygiene.rs @@ -0,0 +1,17 @@ +// run-pass + +macro_rules! bar { + ($($t:tt)*) => { impl $($t)* }; +} + +macro_rules! baz { + ($t:tt) => { fn test(&self) -> usize { $t } }; +} + +struct Foo; + +bar!(Foo { baz!{ M } }); + +fn main() { + assert_eq!(Foo::<7>.test::<3>(), 3); +} diff --git a/tests/ui/const-generics/early/const-param-shadowing.rs b/tests/ui/const-generics/early/const-param-shadowing.rs new file mode 100644 index 000000000..ddd15dbc4 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-shadowing.rs @@ -0,0 +1,7 @@ +type N = u32; +struct Foo; +fn test() -> Foo { //~ ERROR type provided when + Foo +} + +fn main() {} diff --git a/tests/ui/const-generics/early/const-param-shadowing.stderr b/tests/ui/const-generics/early/const-param-shadowing.stderr new file mode 100644 index 000000000..625338bd9 --- /dev/null +++ b/tests/ui/const-generics/early/const-param-shadowing.stderr @@ -0,0 +1,14 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/const-param-shadowing.rs:3:34 + | +LL | fn test() -> Foo { + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | fn test() -> Foo<{ N }> { + | + + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/early/invalid-const-arguments.rs b/tests/ui/const-generics/early/invalid-const-arguments.rs new file mode 100644 index 000000000..6619c9758 --- /dev/null +++ b/tests/ui/const-generics/early/invalid-const-arguments.rs @@ -0,0 +1,16 @@ +#![crate_type="lib"] + +struct A; +trait Foo {} +impl Foo for A {} +//~^ ERROR cannot find type +//~| unresolved item provided when a constant + +struct B; +impl Foo for B {} +//~^ ERROR type provided when a constant + +struct C; +impl Foo for C {} +//~^ ERROR cannot find type +//~| unresolved item provided when a constant diff --git a/tests/ui/const-generics/early/invalid-const-arguments.stderr b/tests/ui/const-generics/early/invalid-const-arguments.stderr new file mode 100644 index 000000000..b46e7e24f --- /dev/null +++ b/tests/ui/const-generics/early/invalid-const-arguments.stderr @@ -0,0 +1,73 @@ +error[E0412]: cannot find type `N` in this scope + --> $DIR/invalid-const-arguments.rs:5:16 + | +LL | struct A; + | ---------------------- similarly named struct `A` defined here +LL | trait Foo {} +LL | impl Foo for A {} + | ^ + | +help: a struct with a similar name exists + | +LL | impl Foo for A {} + | ~ +help: you might be missing a type parameter + | +LL | impl Foo for A {} + | +++ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/invalid-const-arguments.rs:14:32 + | +LL | struct A; + | ---------------------- similarly named struct `A` defined here +... +LL | impl Foo for C {} + | ^ + | +help: a struct with a similar name exists + | +LL | impl Foo for C {} + | ~ +help: you might be missing a type parameter + | +LL | impl Foo for C {} + | +++ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-const-arguments.rs:5:16 + | +LL | impl Foo for A {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl Foo for A<{ N }> {} + | + + + +error[E0747]: type provided when a constant was expected + --> $DIR/invalid-const-arguments.rs:10:19 + | +LL | impl Foo for B {} + | ^ + | +help: consider changing this type parameter to be a `const` generic + | +LL | impl Foo for B {} + | ~~~~~~~~~~~ + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-const-arguments.rs:14:32 + | +LL | impl Foo for C {} + | ^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | impl Foo for C {} + | + + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0412, E0747. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/early/macro_rules-braces.rs b/tests/ui/const-generics/early/macro_rules-braces.rs new file mode 100644 index 000000000..0ae914635 --- /dev/null +++ b/tests/ui/const-generics/early/macro_rules-braces.rs @@ -0,0 +1,73 @@ +mod m { + pub const P: usize = 0; +} + +const Q: usize = 0; + +fn test() { + struct Foo; + macro_rules! foo { + ($x:expr) => { + [u8; $x] + } + } + macro_rules! bar { + ($x:expr) => { + [u8; { $x }] + } + } + macro_rules! baz { + ( $x:expr) => { + Foo<$x> + } + } + macro_rules! biz { + ($x:expr) => { + Foo<{ $x }> + }; + } + + let _: foo!(N); + let _: foo!({ N }); + let _: foo!({{ N }}); //~ ERROR generic parameters may not + let _: foo!(Q); + let _: foo!(m::P); + let _: bar!(N); + let _: bar!({ N }); //~ ERROR generic parameters may not + let _: bar!(Q); + let _: bar!(m::P); + let _: baz!(N); + let _: baz!({ N }); + let _: baz!({{ N }}); //~ ERROR generic parameters may not + let _: baz!(Q); + let _: baz!({ m::P }); + let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces + let _: biz!(N); + let _: biz!({ N }); //~ ERROR generic parameters may not + let _: biz!(Q); + let _: biz!(m::P); + let _: foo!(3); + let _: foo!({ 3 }); + let _: foo!({{ 3 }}); + let _: bar!(3); + let _: bar!({ 3 }); + let _: baz!(3); + let _: baz!({ 3 }); + let _: baz!({{ 3 }}); + let _: biz!(3); + let _: biz!({ 3 }); + let _: foo!(10 + 7); + let _: foo!({ 10 + 7 }); + let _: foo!({{ 10 + 7 }}); + let _: bar!(10 + 7); + let _: bar!({ 10 + 7 }); + let _: baz!(10 + 7); //~ ERROR expressions must be enclosed in braces + let _: baz!({ 10 + 7 }); + let _: baz!({{ 10 + 7 }}); + let _: biz!(10 + 7); + let _: biz!({ 10 + 7 }); +} + +fn main() { + test::<3>(); +} diff --git a/tests/ui/const-generics/early/macro_rules-braces.stderr b/tests/ui/const-generics/early/macro_rules-braces.stderr new file mode 100644 index 000000000..49382dbf0 --- /dev/null +++ b/tests/ui/const-generics/early/macro_rules-braces.stderr @@ -0,0 +1,60 @@ +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/macro_rules-braces.rs:44:17 + | +LL | let _: baz!(m::P); + | ^^^^ + | +help: enclose the `const` expression in braces + | +LL | let _: baz!({ m::P }); + | + + + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/macro_rules-braces.rs:64:17 + | +LL | let _: baz!(10 + 7); + | ^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | let _: baz!({ 10 + 7 }); + | + + + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:32:20 + | +LL | let _: foo!({{ N }}); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:36:19 + | +LL | let _: bar!({ N }); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:41:20 + | +LL | let _: baz!({{ N }}); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/macro_rules-braces.rs:46:19 + | +LL | let _: biz!({ N }); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 6 previous errors + diff --git a/tests/ui/const-generics/ensure_is_evaluatable.rs b/tests/ui/const-generics/ensure_is_evaluatable.rs new file mode 100644 index 000000000..1e8d8c3d3 --- /dev/null +++ b/tests/ui/const-generics/ensure_is_evaluatable.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo() -> [(); N+2] +where + [(); N + 1]:, + [(); M + 1]:, +{ + bar() + //~^ ERROR: unconstrained +} + +fn bar() -> [(); N] +where + [(); N + 1]:, +{ + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/ensure_is_evaluatable.stderr b/tests/ui/const-generics/ensure_is_evaluatable.stderr new file mode 100644 index 000000000..bf6c35ad8 --- /dev/null +++ b/tests/ui/const-generics/ensure_is_evaluatable.stderr @@ -0,0 +1,18 @@ +error: unconstrained generic constant + --> $DIR/ensure_is_evaluatable.rs:9:5 + | +LL | bar() + | ^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N + 1]:` +note: required by a bound in `bar` + --> $DIR/ensure_is_evaluatable.rs:15:10 + | +LL | fn bar() -> [(); N] + | --- required by a bound in this +LL | where +LL | [(); N + 1]:, + | ^^^^^ required by this bound in `bar` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/enum-variants.rs b/tests/ui/const-generics/enum-variants.rs new file mode 100644 index 000000000..5c6c4a8ef --- /dev/null +++ b/tests/ui/const-generics/enum-variants.rs @@ -0,0 +1,24 @@ +// check-pass +enum Foo { + Variant, + Variant2(), + Variant3{}, +} + +struct Bar; +struct Bar2(); +struct Bar3 {} + +fn main() { + let _ = Foo::Variant::<1>; + let _ = Foo::Variant2::<1>(); + let _ = Foo::Variant3::<1>{}; + + let _ = Foo::<1>::Variant; + let _ = Foo::<1>::Variant2(); + let _ = Foo::<1>::Variant3{}; + + let _ = Bar::<1>; + let _ = Bar2::<1>(); + let _ = Bar3::<1>{}; +} diff --git a/tests/ui/const-generics/exhaustive-value.rs b/tests/ui/const-generics/exhaustive-value.rs new file mode 100644 index 000000000..778d49834 --- /dev/null +++ b/tests/ui/const-generics/exhaustive-value.rs @@ -0,0 +1,267 @@ +trait Foo { + fn test() {} +} +impl Foo<0> for () {} +impl Foo<1> for () {} +impl Foo<2> for () {} +impl Foo<3> for () {} +impl Foo<4> for () {} +impl Foo<5> for () {} +impl Foo<6> for () {} +impl Foo<7> for () {} +impl Foo<8> for () {} +impl Foo<9> for () {} +impl Foo<10> for () {} +impl Foo<11> for () {} +impl Foo<12> for () {} +impl Foo<13> for () {} +impl Foo<14> for () {} +impl Foo<15> for () {} +impl Foo<16> for () {} +impl Foo<17> for () {} +impl Foo<18> for () {} +impl Foo<19> for () {} +impl Foo<20> for () {} +impl Foo<21> for () {} +impl Foo<22> for () {} +impl Foo<23> for () {} +impl Foo<24> for () {} +impl Foo<25> for () {} +impl Foo<26> for () {} +impl Foo<27> for () {} +impl Foo<28> for () {} +impl Foo<29> for () {} +impl Foo<30> for () {} +impl Foo<31> for () {} +impl Foo<32> for () {} +impl Foo<33> for () {} +impl Foo<34> for () {} +impl Foo<35> for () {} +impl Foo<36> for () {} +impl Foo<37> for () {} +impl Foo<38> for () {} +impl Foo<39> for () {} +impl Foo<40> for () {} +impl Foo<41> for () {} +impl Foo<42> for () {} +impl Foo<43> for () {} +impl Foo<44> for () {} +impl Foo<45> for () {} +impl Foo<46> for () {} +impl Foo<47> for () {} +impl Foo<48> for () {} +impl Foo<49> for () {} +impl Foo<50> for () {} +impl Foo<51> for () {} +impl Foo<52> for () {} +impl Foo<53> for () {} +impl Foo<54> for () {} +impl Foo<55> for () {} +impl Foo<56> for () {} +impl Foo<57> for () {} +impl Foo<58> for () {} +impl Foo<59> for () {} +impl Foo<60> for () {} +impl Foo<61> for () {} +impl Foo<62> for () {} +impl Foo<63> for () {} +impl Foo<64> for () {} +impl Foo<65> for () {} +impl Foo<66> for () {} +impl Foo<67> for () {} +impl Foo<68> for () {} +impl Foo<69> for () {} +impl Foo<70> for () {} +impl Foo<71> for () {} +impl Foo<72> for () {} +impl Foo<73> for () {} +impl Foo<74> for () {} +impl Foo<75> for () {} +impl Foo<76> for () {} +impl Foo<77> for () {} +impl Foo<78> for () {} +impl Foo<79> for () {} +impl Foo<80> for () {} +impl Foo<81> for () {} +impl Foo<82> for () {} +impl Foo<83> for () {} +impl Foo<84> for () {} +impl Foo<85> for () {} +impl Foo<86> for () {} +impl Foo<87> for () {} +impl Foo<88> for () {} +impl Foo<89> for () {} +impl Foo<90> for () {} +impl Foo<91> for () {} +impl Foo<92> for () {} +impl Foo<93> for () {} +impl Foo<94> for () {} +impl Foo<95> for () {} +impl Foo<96> for () {} +impl Foo<97> for () {} +impl Foo<98> for () {} +impl Foo<99> for () {} +impl Foo<100> for () {} +impl Foo<101> for () {} +impl Foo<102> for () {} +impl Foo<103> for () {} +impl Foo<104> for () {} +impl Foo<105> for () {} +impl Foo<106> for () {} +impl Foo<107> for () {} +impl Foo<108> for () {} +impl Foo<109> for () {} +impl Foo<110> for () {} +impl Foo<111> for () {} +impl Foo<112> for () {} +impl Foo<113> for () {} +impl Foo<114> for () {} +impl Foo<115> for () {} +impl Foo<116> for () {} +impl Foo<117> for () {} +impl Foo<118> for () {} +impl Foo<119> for () {} +impl Foo<120> for () {} +impl Foo<121> for () {} +impl Foo<122> for () {} +impl Foo<123> for () {} +impl Foo<124> for () {} +impl Foo<125> for () {} +impl Foo<126> for () {} +impl Foo<127> for () {} +impl Foo<128> for () {} +impl Foo<129> for () {} +impl Foo<130> for () {} +impl Foo<131> for () {} +impl Foo<132> for () {} +impl Foo<133> for () {} +impl Foo<134> for () {} +impl Foo<135> for () {} +impl Foo<136> for () {} +impl Foo<137> for () {} +impl Foo<138> for () {} +impl Foo<139> for () {} +impl Foo<140> for () {} +impl Foo<141> for () {} +impl Foo<142> for () {} +impl Foo<143> for () {} +impl Foo<144> for () {} +impl Foo<145> for () {} +impl Foo<146> for () {} +impl Foo<147> for () {} +impl Foo<148> for () {} +impl Foo<149> for () {} +impl Foo<150> for () {} +impl Foo<151> for () {} +impl Foo<152> for () {} +impl Foo<153> for () {} +impl Foo<154> for () {} +impl Foo<155> for () {} +impl Foo<156> for () {} +impl Foo<157> for () {} +impl Foo<158> for () {} +impl Foo<159> for () {} +impl Foo<160> for () {} +impl Foo<161> for () {} +impl Foo<162> for () {} +impl Foo<163> for () {} +impl Foo<164> for () {} +impl Foo<165> for () {} +impl Foo<166> for () {} +impl Foo<167> for () {} +impl Foo<168> for () {} +impl Foo<169> for () {} +impl Foo<170> for () {} +impl Foo<171> for () {} +impl Foo<172> for () {} +impl Foo<173> for () {} +impl Foo<174> for () {} +impl Foo<175> for () {} +impl Foo<176> for () {} +impl Foo<177> for () {} +impl Foo<178> for () {} +impl Foo<179> for () {} +impl Foo<180> for () {} +impl Foo<181> for () {} +impl Foo<182> for () {} +impl Foo<183> for () {} +impl Foo<184> for () {} +impl Foo<185> for () {} +impl Foo<186> for () {} +impl Foo<187> for () {} +impl Foo<188> for () {} +impl Foo<189> for () {} +impl Foo<190> for () {} +impl Foo<191> for () {} +impl Foo<192> for () {} +impl Foo<193> for () {} +impl Foo<194> for () {} +impl Foo<195> for () {} +impl Foo<196> for () {} +impl Foo<197> for () {} +impl Foo<198> for () {} +impl Foo<199> for () {} +impl Foo<200> for () {} +impl Foo<201> for () {} +impl Foo<202> for () {} +impl Foo<203> for () {} +impl Foo<204> for () {} +impl Foo<205> for () {} +impl Foo<206> for () {} +impl Foo<207> for () {} +impl Foo<208> for () {} +impl Foo<209> for () {} +impl Foo<210> for () {} +impl Foo<211> for () {} +impl Foo<212> for () {} +impl Foo<213> for () {} +impl Foo<214> for () {} +impl Foo<215> for () {} +impl Foo<216> for () {} +impl Foo<217> for () {} +impl Foo<218> for () {} +impl Foo<219> for () {} +impl Foo<220> for () {} +impl Foo<221> for () {} +impl Foo<222> for () {} +impl Foo<223> for () {} +impl Foo<224> for () {} +impl Foo<225> for () {} +impl Foo<226> for () {} +impl Foo<227> for () {} +impl Foo<228> for () {} +impl Foo<229> for () {} +impl Foo<230> for () {} +impl Foo<231> for () {} +impl Foo<232> for () {} +impl Foo<233> for () {} +impl Foo<234> for () {} +impl Foo<235> for () {} +impl Foo<236> for () {} +impl Foo<237> for () {} +impl Foo<238> for () {} +impl Foo<239> for () {} +impl Foo<240> for () {} +impl Foo<241> for () {} +impl Foo<242> for () {} +impl Foo<243> for () {} +impl Foo<244> for () {} +impl Foo<245> for () {} +impl Foo<246> for () {} +impl Foo<247> for () {} +impl Foo<248> for () {} +impl Foo<249> for () {} +impl Foo<250> for () {} +impl Foo<251> for () {} +impl Foo<252> for () {} +impl Foo<253> for () {} +impl Foo<254> for () {} +impl Foo<255> for () {} + +fn foo() { + <() as Foo>::test() //~ ERROR the trait bound `(): Foo` +} + +fn main() { + foo::<7>(); +} diff --git a/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr new file mode 100644 index 000000000..76a83ba67 --- /dev/null +++ b/tests/ui/const-generics/exhaustive-value.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/exhaustive-value.rs:262:5 + | +LL | <() as Foo>::test() + | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | + = help: the following other types implement trait `Foo`: + <() as Foo<0>> + <() as Foo<100>> + <() as Foo<101>> + <() as Foo<102>> + <() as Foo<103>> + <() as Foo<104>> + <() as Foo<105>> + <() as Foo<106>> + and 248 others + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/expose-default-substs-param-env.rs b/tests/ui/const-generics/expose-default-substs-param-env.rs new file mode 100644 index 000000000..e40c93116 --- /dev/null +++ b/tests/ui/const-generics/expose-default-substs-param-env.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait Foo {} +pub trait Bar: Foo<{ 1 }> { } + +fn main() {} diff --git a/tests/ui/const-generics/float-generic.adt_const_params.stderr b/tests/ui/const-generics/float-generic.adt_const_params.stderr new file mode 100644 index 000000000..fef5ef0d1 --- /dev/null +++ b/tests/ui/const-generics/float-generic.adt_const_params.stderr @@ -0,0 +1,11 @@ +error[E0741]: `f32` is forbidden as the type of a const generic parameter + --> $DIR/float-generic.rs:5:17 + | +LL | fn foo() {} + | ^^^ + | + = note: floats do not derive `Eq` or `Ord`, which are required for const parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/float-generic.rs b/tests/ui/const-generics/float-generic.rs new file mode 100644 index 000000000..b72059b5b --- /dev/null +++ b/tests/ui/const-generics/float-generic.rs @@ -0,0 +1,12 @@ +// revisions: simple adt_const_params +#![cfg_attr(adt_const_params, feature(adt_const_params))] +#![cfg_attr(adt_const_params, allow(incomplete_features))] + +fn foo() {} +//~^ ERROR `f32` is forbidden as the type of a const generic parameter + +const C: f32 = 1.0; + +fn main() { + foo::(); +} diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr new file mode 100644 index 000000000..89ca36b0f --- /dev/null +++ b/tests/ui/const-generics/float-generic.simple.stderr @@ -0,0 +1,11 @@ +error: `f32` is forbidden as the type of a const generic parameter + --> $DIR/float-generic.rs:5:17 + | +LL | fn foo() {} + | ^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/fn-const-param-call.full.stderr b/tests/ui/const-generics/fn-const-param-call.full.stderr new file mode 100644 index 000000000..b55c24498 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-call.full.stderr @@ -0,0 +1,15 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:11:25 + | +LL | struct Wrapper u32>; + | ^^^^^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:13:15 + | +LL | impl u32> Wrapper { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/fn-const-param-call.min.stderr b/tests/ui/const-generics/fn-const-param-call.min.stderr new file mode 100644 index 000000000..d984449e6 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-call.min.stderr @@ -0,0 +1,14 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:11:25 + | +LL | struct Wrapper u32>; + | ^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-call.rs:13:15 + | +LL | impl u32> Wrapper { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/fn-const-param-call.rs b/tests/ui/const-generics/fn-const-param-call.rs new file mode 100644 index 000000000..dc516fb71 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-call.rs @@ -0,0 +1,22 @@ +// Check that functions cannot be used as const parameters. +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn function() -> u32 { + 17 +} + +struct Wrapper u32>; //~ ERROR: using function pointers as const generic parameters + +impl u32> Wrapper { +//~^ ERROR: using function pointers as const generic parameters + fn call() -> u32 { + F() + } +} + +fn main() { + assert_eq!(Wrapper::::call(), 17); +} diff --git a/tests/ui/const-generics/fn-const-param-infer.full.stderr b/tests/ui/const-generics/fn-const-param-infer.full.stderr new file mode 100644 index 000000000..2d66a1923 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-infer.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:6:25 + | +LL | struct Checked bool>; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr new file mode 100644 index 000000000..f0767a109 --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/fn-const-param-infer.rs:6:25 + | +LL | struct Checked bool>; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/fn-const-param-infer.rs b/tests/ui/const-generics/fn-const-param-infer.rs new file mode 100644 index 000000000..22f5f529c --- /dev/null +++ b/tests/ui/const-generics/fn-const-param-infer.rs @@ -0,0 +1,29 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Checked bool>; +//~^ ERROR: using function pointers as const generic parameters + +fn not_one(val: usize) -> bool { val != 1 } +fn not_two(val: usize) -> bool { val != 2 } + +fn generic_arg(val: T) -> bool { true } + +fn generic(val: usize) -> bool { val != 1 } + +fn main() { + let _: Option> = None; + let _: Checked = Checked::; + let _: Checked = Checked::; + + let _ = Checked::; + let _ = Checked::<{generic_arg::}>; + let _ = Checked::<{generic_arg::}>; + + let _ = Checked::; + let _ = Checked::<{generic::}>; + let _: Checked<{generic::}> = Checked::<{generic::}>; + let _: Checked<{generic::}> = Checked::<{generic::}>; +} diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.rs b/tests/ui/const-generics/fn_with_two_const_inputs.rs new file mode 100644 index 000000000..0d6246a9f --- /dev/null +++ b/tests/ui/const-generics/fn_with_two_const_inputs.rs @@ -0,0 +1,23 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn both(_: usize, b: usize) -> usize { + b +} + +fn foo() -> [(); N + 2] +where + [(); both(N + 1, M + 1)]:, +{ + bar() + //~^ ERROR: unconstrained generic constant +} + +fn bar() -> [(); N] +where + [(); N + 1]:, +{ + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.stderr b/tests/ui/const-generics/fn_with_two_const_inputs.stderr new file mode 100644 index 000000000..614e7e0d2 --- /dev/null +++ b/tests/ui/const-generics/fn_with_two_const_inputs.stderr @@ -0,0 +1,18 @@ +error: unconstrained generic constant + --> $DIR/fn_with_two_const_inputs.rs:12:5 + | +LL | bar() + | ^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N + 1]:` +note: required by a bound in `bar` + --> $DIR/fn_with_two_const_inputs.rs:18:10 + | +LL | fn bar() -> [(); N] + | --- required by a bound in this +LL | where +LL | [(); N + 1]:, + | ^^^^^ required by this bound in `bar` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/fn_with_two_same_const_inputs.rs b/tests/ui/const-generics/fn_with_two_same_const_inputs.rs new file mode 100644 index 000000000..f0ce093e0 --- /dev/null +++ b/tests/ui/const-generics/fn_with_two_same_const_inputs.rs @@ -0,0 +1,22 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn both(_: usize, b: usize) -> usize { + b +} + +fn foo() +where + [(); both(N + 1, N + 1)]:, +{ + bar::(); +} + +fn bar() +where + [(); N + 1]:, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/forbid-non-structural_match-types.rs b/tests/ui/const-generics/forbid-non-structural_match-types.rs new file mode 100644 index 000000000..6ae9d5cfb --- /dev/null +++ b/tests/ui/const-generics/forbid-non-structural_match-types.rs @@ -0,0 +1,13 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok + +struct C; + +struct D; //~ ERROR `C` must be annotated with `#[derive(PartialEq, Eq)]` + +fn main() {} diff --git a/tests/ui/const-generics/forbid-non-structural_match-types.stderr b/tests/ui/const-generics/forbid-non-structural_match-types.stderr new file mode 100644 index 000000000..81b9bdfbd --- /dev/null +++ b/tests/ui/const-generics/forbid-non-structural_match-types.stderr @@ -0,0 +1,9 @@ +error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/forbid-non-structural_match-types.rs:11:19 + | +LL | struct D; + | ^ `C` doesn't derive both `PartialEq` and `Eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/foreign-item-const-parameter.rs b/tests/ui/const-generics/foreign-item-const-parameter.rs new file mode 100644 index 000000000..4fe377b59 --- /dev/null +++ b/tests/ui/const-generics/foreign-item-const-parameter.rs @@ -0,0 +1,7 @@ +extern "C" { + fn foo(); //~ ERROR foreign items may not have const parameters + + fn bar(_: T); //~ ERROR foreign items may not have type or const parameters +} + +fn main() {} diff --git a/tests/ui/const-generics/foreign-item-const-parameter.stderr b/tests/ui/const-generics/foreign-item-const-parameter.stderr new file mode 100644 index 000000000..b02db8700 --- /dev/null +++ b/tests/ui/const-generics/foreign-item-const-parameter.stderr @@ -0,0 +1,19 @@ +error[E0044]: foreign items may not have const parameters + --> $DIR/foreign-item-const-parameter.rs:2:5 + | +LL | fn foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters + | + = help: replace the const parameters with concrete consts + +error[E0044]: foreign items may not have type or const parameters + --> $DIR/foreign-item-const-parameter.rs:4:5 + | +LL | fn bar(_: T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters + | + = help: replace the type or const parameters with concrete types or consts + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0044`. diff --git a/tests/ui/const-generics/generic-param-mismatch.rs b/tests/ui/const-generics/generic-param-mismatch.rs new file mode 100644 index 000000000..2e201e50a --- /dev/null +++ b/tests/ui/const-generics/generic-param-mismatch.rs @@ -0,0 +1,5 @@ +fn test() -> [u8; M] { + [0; N] //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic-param-mismatch.stderr b/tests/ui/const-generics/generic-param-mismatch.stderr new file mode 100644 index 000000000..d0776d49d --- /dev/null +++ b/tests/ui/const-generics/generic-param-mismatch.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/generic-param-mismatch.rs:2:5 + | +LL | fn test() -> [u8; M] { + | ------- expected `[u8; M]` because of return type +LL | [0; N] + | ^^^^^^ expected `M`, found `N` + | + = note: expected array `[u8; M]` + found array `[u8; N]` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs new file mode 100644 index 000000000..d3e53d7a8 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr.rs @@ -0,0 +1,13 @@ +// run-pass + +// To avoid having to `or` gate `_` as an expr. +#![feature(generic_arg_infer)] + +fn foo() -> [u8; 3] { + let x: [u8; _] = [0; _]; + x +} + +fn main() { + assert_eq!([0; _], foo()); +} diff --git a/tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs b/tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs new file mode 100644 index 000000000..251160a0f --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/dont-use-defaults.rs @@ -0,0 +1,15 @@ +// run-pass +#![feature(generic_arg_infer)] + +// test that we dont use defaults to aide in type inference + +struct Foo; +impl Foo { + fn make_arr() -> [(); N] { + [(); N] + } +} + +fn main() { + let [(), (), ()] = Foo::<_>::make_arr(); +} diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.rs b/tests/ui/const-generics/generic_arg_infer/in-signature.rs new file mode 100644 index 000000000..1f60b2242 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.rs @@ -0,0 +1,61 @@ +#![crate_type = "rlib"] +#![feature(generic_arg_infer)] + +struct Foo; +struct Bar(T); + +fn arr_fn() -> [u8; _] { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + [0; 3] +} + +fn ty_fn() -> Bar { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Bar::(0) +} + +fn ty_fn_mixed() -> Bar<_, _> { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + Bar::(0) +} + +const ARR_CT: [u8; _] = [0; 3]; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static ARR_STATIC: [u8; _] = [0; 3]; +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +const TY_CT: Bar = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static TY_STATIC: Bar = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +const TY_CT_MIXED: Bar<_, _> = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables +trait ArrAssocConst { + const ARR: [u8; _]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} +trait TyAssocConst { + const ARR: Bar; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} +trait TyAssocConstMixed { + const ARR: Bar<_, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants +} + +trait AssocTy { + type Assoc; +} +impl AssocTy for i8 { + type Assoc = [u8; _]; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl AssocTy for i16 { + type Assoc = Bar; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} +impl AssocTy for i32 { + type Assoc = Bar<_, _>; + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types +} diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr new file mode 100644 index 000000000..52d1b29f9 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr @@ -0,0 +1,119 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:7:21 + | +LL | fn arr_fn() -> [u8; _] { + | -----^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `[u8; 3]` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:12:24 + | +LL | fn ty_fn() -> Bar { + | ---------^- + | | | + | | not allowed in type signatures + | help: replace with the correct return type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/in-signature.rs:17:25 + | +LL | fn ty_fn_mixed() -> Bar<_, _> { + | ----^--^- + | | | | + | | | not allowed in type signatures + | | not allowed in type signatures + | help: replace with the correct return type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:22:15 + | +LL | const ARR_CT: [u8; _] = [0; 3]; + | ^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:24:20 + | +LL | static ARR_STATIC: [u8; _] = [0; 3]; + | ^^^^^^^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:26:14 + | +LL | const TY_CT: Bar = Bar::(0); + | ^^^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:28:19 + | +LL | static TY_STATIC: Bar = Bar::(0); + | ^^^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:30:20 + | +LL | const TY_CT_MIXED: Bar<_, _> = Bar::(0); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for static variables + --> $DIR/in-signature.rs:32:25 + | +LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::(0); + | ^^^^^^^^^ + | | + | not allowed in type signatures + | help: replace with the correct type: `Bar` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:35:21 + | +LL | const ARR: [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:39:25 + | +LL | const ARR: Bar; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/in-signature.rs:43:20 + | +LL | const ARR: Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:51:23 + | +LL | type Assoc = [u8; _]; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:55:27 + | +LL | type Assoc = Bar; + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types + --> $DIR/in-signature.rs:59:22 + | +LL | type Assoc = Bar<_, _>; + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs new file mode 100644 index 000000000..29aa0f59d --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs @@ -0,0 +1,22 @@ +#![feature(generic_arg_infer)] + +struct All<'a, T, const N: usize> { + v: &'a T, +} + +struct BadInfer<_>; +//~^ ERROR expected identifier +//~| ERROR parameter `_` is never used + +fn all_fn<'a, T, const N: usize>() {} + +fn bad_infer_fn<_>() {} +//~^ ERROR expected identifier + + +fn main() { + let a: All<_, _, _>; + all_fn(); + let v: [u8; _]; + let v: [u8; 10] = [0; _]; +} diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr new file mode 100644 index 000000000..e6d0c743d --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr @@ -0,0 +1,24 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/infer-arg-test.rs:7:17 + | +LL | struct BadInfer<_>; + | ^ expected identifier, found reserved identifier + +error: expected identifier, found reserved identifier `_` + --> $DIR/infer-arg-test.rs:13:17 + | +LL | fn bad_infer_fn<_>() {} + | ^ expected identifier, found reserved identifier + +error[E0392]: parameter `_` is never used + --> $DIR/infer-arg-test.rs:7:17 + | +LL | struct BadInfer<_>; + | ^ unused parameter + | + = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `_` to be a const parameter, use `const _: usize` instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs b/tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs new file mode 100644 index 000000000..23c8d7537 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/infer_arg_and_const_arg.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_arg_infer)] + +struct Foo; +struct Bar; + +fn main() { + let _: Foo = Foo::<_, 1>; + let _: Foo<_, 1> = Foo::; + let _: Bar<1, _> = Bar::<_, 300>; + let _: Bar<_, 300> = Bar::<1, _>; +} diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.rs b/tests/ui/const-generics/generic_arg_infer/issue-91614.rs new file mode 100644 index 000000000..b45e2cbc7 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.rs @@ -0,0 +1,8 @@ +#![feature(portable_simd)] +#![feature(generic_arg_infer)] +use std::simd::Mask; + +fn main() { + let y = Mask::<_, _>::splat(false); + //~^ ERROR: type annotations needed for +} diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr new file mode 100644 index 000000000..13ea4a295 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed for `Mask<_, LANES>` + --> $DIR/issue-91614.rs:6:9 + | +LL | let y = Mask::<_, _>::splat(false); + | ^ ------------------- type must be known at this point + | + = note: cannot satisfy `_: MaskElement` + = help: the following types implement trait `MaskElement`: + i16 + i32 + i64 + i8 + isize +note: required by a bound in `Mask::::splat` + --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL +help: consider giving `y` an explicit type, where the type for type parameter `T` is specified + | +LL | let y: Mask<_, LANES> = Mask::<_, _>::splat(false); + | ++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs new file mode 100644 index 000000000..06f00de13 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs @@ -0,0 +1,18 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo([u8; N as usize]) +where + [(); N as usize]:; + +struct Bar([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:; + +// unifying with subtrees +struct Evaluatable; +fn foo() where Evaluatable<{N as usize as u16 }>: { + let _ = Foo::([1; N as usize]); +} + + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs new file mode 100644 index 000000000..3b5b87b2b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Evaluatable {} + +struct Foo([u8; N as usize]) +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:` +where + Evaluatable<{N as u128}>:; + +struct Foo2(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +struct Bar([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; +//~^ Error: unconstrained generic constant +//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr new file mode 100644 index 000000000..5ca04d25e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr @@ -0,0 +1,26 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:6:25 + | +LL | struct Foo([u8; N as usize]) + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); N as usize]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:12:26 + | +LL | struct Foo2(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-2.rs:16:25 + | +LL | struct Bar([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs new file mode 100644 index 000000000..7561ae2fe --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs @@ -0,0 +1,47 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128; + +struct HasCastInTraitImpl; +impl Trait for HasCastInTraitImpl {} + +pub fn use_trait_impl() +where + [(); { N + 1}]:, + EvaluatableU128<{N as u128}>:, { + fn assert_impl() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + assert_impl::>(); + //~^ Error: mismatched types +} +pub fn use_trait_impl_2() +where + [(); { N + 1}]:, + EvaluatableU128<{N as _}>:, { + fn assert_impl() {} + + // errors are bad but seems to be pre-existing issue #86198 + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + //~^^ Error: unconstrained generic constant + assert_impl::>(); + //~^ Error: mismatched types + assert_impl::>(); + //~^ Error: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr new file mode 100644 index 000000000..cdf97bd88 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -0,0 +1,187 @@ +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:17:19 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:17:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:20:19 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:20:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:23:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | + = note: expected constant `12` + found constant `13` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:25:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | + = note: expected constant `13` + found constant `14` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:35:19 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:35:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error: unconstrained generic constant + --> $DIR/abstract-const-as-cast-3.rs:38:19 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:` +note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait` + --> $DIR/abstract-const-as-cast-3.rs:8:22 + | +LL | impl Trait for HasCastInTraitImpl {} + | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:38:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:41:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | + = note: expected constant `12` + found constant `13` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error[E0308]: mismatched types + --> $DIR/abstract-const-as-cast-3.rs:43:5 + | +LL | assert_impl::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | + = note: expected constant `13` + found constant `14` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `assert_impl` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs new file mode 100644 index 000000000..184263f89 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs @@ -0,0 +1,29 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait {} +pub struct EvaluatableU128; + +struct HasCastInTraitImpl; +impl Trait for HasCastInTraitImpl {} + +pub fn use_trait_impl() where EvaluatableU128<{N as u128}>:, { + fn assert_impl() {} + + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); +} +pub fn use_trait_impl_2() where EvaluatableU128<{N as _}>:, { + fn assert_impl() {} + + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); + assert_impl::>(); +} + + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs new file mode 100644 index 000000000..916d60c0e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo(a: [(); N as usize]) { + bar::<{ N as usize as usize }>(); + //~^ error: unconstrained generic constant +} + +fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr new file mode 100644 index 000000000..d48b639db --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/abstract-consts-as-cast-5.rs:5:11 + | +LL | bar::<{ N as usize as usize }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr new file mode 100644 index 000000000..1d10dfdf1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -0,0 +1,19 @@ +error: unconstrained generic constant + --> $DIR/array-size-in-generic-struct-param.rs:8:38 + | +LL | struct ArithArrayLen([u32; 0 + N]); + | ^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); 0 + N]:` + +error: overly complex generic constant + --> $DIR/array-size-in-generic-struct-param.rs:19:15 + | +LL | arr: [u8; CFG.arr_size], + | ^^^^^^^^^^^^ field access is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr new file mode 100644 index 000000000..18e9135d0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -0,0 +1,29 @@ +error: generic parameters may not be used in const operations + --> $DIR/array-size-in-generic-struct-param.rs:8:48 + | +LL | struct ArithArrayLen([u32; 0 + N]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/array-size-in-generic-struct-param.rs:19:15 + | +LL | arr: [u8; CFG.arr_size], + | ^^^ cannot perform const operation using `CFG` + | + = help: const parameters may only be used as standalone arguments, i.e. `CFG` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: `Config` is forbidden as the type of a const generic parameter + --> $DIR/array-size-in-generic-struct-param.rs:17:21 + | +LL | struct B { + | ^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs new file mode 100644 index 000000000..7d3fe413c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs @@ -0,0 +1,29 @@ +// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`. +// revisions: full min + +#![cfg_attr(full, feature(generic_const_exprs, adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +#[allow(dead_code)] +struct ArithArrayLen([u32; 0 + N]); +//[full]~^ ERROR unconstrained generic constant +//[min]~^^ ERROR generic parameters may not be used in const operations + +#[derive(PartialEq, Eq)] +struct Config { + arr_size: usize, +} + +struct B { + //[min]~^ ERROR `Config` is forbidden + arr: [u8; CFG.arr_size], + //[full]~^ ERROR overly complex generic constant + //[min]~^^ ERROR generic parameters may not be used in const operations +} + +const C: Config = Config { arr_size: 5 }; + +fn main() { + let b = B:: { arr: [1, 2, 3, 4, 5] }; + assert_eq!(b.arr.len(), 5); +} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs new file mode 100644 index 000000000..e8f89cb1a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/const_equate_assoc_consts.rs @@ -0,0 +1,27 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} +impl Trait for T { + const ASSOC: usize = std::mem::size_of::(); +} + +struct Foo([u8; T::ASSOC]) +where + [(); T::ASSOC]:; + +fn bar() +where + [(); T::ASSOC]:, +{ + let _: Foo = Foo::<_>(make()); +} + +fn make() -> ! { + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs new file mode 100644 index 000000000..c8f7553da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +fn foo() where [(); U::ASSOC]:, { + bar::<{ T::ASSOC }>(); + //~^ ERROR: unconstrained generic constant +} + +fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr new file mode 100644 index 000000000..e4a0cabe5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/doesnt_unify_evaluatable.rs:9:11 + | +LL | bar::<{ T::ASSOC }>(); + | ^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs new file mode 100644 index 000000000..274caa1e9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/dropck_unifies_assoc_consts.rs @@ -0,0 +1,20 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +struct Foo(T) +where + [(); T::ASSOC]:; + +impl Drop for Foo +where + [(); T::ASSOC]:, +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs new file mode 100644 index 000000000..6597b9f2b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/assoc_const_unification/unifies_evaluatable.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + const ASSOC: usize; +} + +fn foo() where [(); T::ASSOC]:, { + bar::<{ T::ASSOC }>(); +} + +fn bar() -> [(); N] { + [(); N] +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/associated-const.rs b/tests/ui/const-generics/generic_const_exprs/associated-const.rs new file mode 100644 index 000000000..a67776322 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/associated-const.rs @@ -0,0 +1,11 @@ +// check-pass +struct Foo(T); +impl Foo { + const VALUE: usize = std::mem::size_of::(); +} + +fn test() { + let _ = [0; Foo::::VALUE]; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs new file mode 100644 index 000000000..b839008d4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs @@ -0,0 +1,31 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait BlockCipher { + const BLOCK_SIZE: usize; +} + +struct FooCipher; +impl BlockCipher for FooCipher { + const BLOCK_SIZE: usize = 64; +} + +struct BarCipher; +impl BlockCipher for BarCipher { + const BLOCK_SIZE: usize = 32; +} + +pub struct Block(#[allow(unused_tuple_struct_fields)] C); + +pub fn test() +where + [u8; M - C::BLOCK_SIZE]: Sized, +{ + let _ = [0; M - C::BLOCK_SIZE]; +} + +fn main() { + test::(); + test::(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs new file mode 100644 index 000000000..97be07493 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs @@ -0,0 +1,8 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo; + +pub fn foo() -> Foo<{ N + 1 }> { + Foo +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs new file mode 100644 index 000000000..15d618cae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub fn test1() -> [u8; std::mem::size_of::() - 1] +where + [u8; std::mem::size_of::() - 1]: Sized, +{ + [0; std::mem::size_of::() - 1] +} diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs new file mode 100644 index 000000000..df454dae7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] + +use std::str::FromStr; + +pub struct If; + +pub trait True {} + +impl True for If {} + +pub struct FixedI32; + +impl FromStr for FixedI32 +where + If<{ FRAC <= 32 }>: True, +{ + type Err = (); + fn from_str(_s: &str) -> Result { + unimplemented!() + } +} diff --git a/tests/ui/const-generics/generic_const_exprs/closures.rs b/tests/ui/const-generics/generic_const_exprs/closures.rs new file mode 100644 index 000000000..1ea310d06 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/closures.rs @@ -0,0 +1,6 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +fn test() -> [u8; N + (|| 42)()] {} +//~^ ERROR cycle detected when building an abstract representation + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/closures.stderr b/tests/ui/const-generics/generic_const_exprs/closures.stderr new file mode 100644 index 000000000..a7d891d77 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/closures.stderr @@ -0,0 +1,26 @@ +error[E0391]: cycle detected when building an abstract representation for `test::{constant#0}` + --> $DIR/closures.rs:3:35 + | +LL | fn test() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + | +note: ...which requires building THIR for `test::{constant#0}`... + --> $DIR/closures.rs:3:35 + | +LL | fn test() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `test::{constant#0}`... + --> $DIR/closures.rs:3:35 + | +LL | fn test() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^ + = note: ...which again requires building an abstract representation for `test::{constant#0}`, completing the cycle +note: cycle used when checking that `test` is well-formed + --> $DIR/closures.rs:3:1 + | +LL | fn test() -> [u8; N + (|| 42)()] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs new file mode 100644 index 000000000..7332a8f03 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs @@ -0,0 +1,11 @@ +#![feature(inline_const, generic_const_exprs)] +//~^ WARN the feature `generic_const_exprs` is incomplete + +fn foo() { + let _ = [0u8; const { std::mem::size_of::() }]; + //~^ ERROR: overly complex generic constant +} + +fn main() { + foo::(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr new file mode 100644 index 000000000..f26259908 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -0,0 +1,20 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-block-is-poly.rs:1:26 + | +LL | #![feature(inline_const, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: overly complex generic constant + --> $DIR/const-block-is-poly.rs:5:19 + | +LL | let _ = [0u8; const { std::mem::size_of::() }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ const blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs new file mode 100644 index 000000000..5874625ad --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + type Assoc: Default; +} + +impl Foo<0> for () { + type Assoc = u32; +} + +impl Foo<3> for () { + type Assoc = i64; +} + +fn foo(_: T) -> <() as Foo<{ N + 1 }>>::Assoc +where + (): Foo<{ N + 1 }>, +{ + Default::default() +} + +fn main() { + let mut _q = Default::default(); + _q = foo::<_, 2>(_q); +} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs new file mode 100644 index 000000000..6093fc70b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs, generic_arg_infer)] +#![allow(incomplete_features)] + +// minimized repro for #105205 +// +// the `foo::<_, L>` call results in a `WellFormed(_)` obligation and a +// `ConstEvaluatable(Unevaluated(_ + 1 + L))` obligation. Attempting to fulfill the latter +// unifies the `_` with `Expr(L - 1)` from the paramenv which turns the `WellFormed` +// obligation into `WellFormed(Expr(L - 1))` + +fn foo(_: [(); N + 1 + M]) {} + +fn ice() +where + [(); (L - 1) + 1 + L]:, +{ + foo::<_, L>([(); L + 1 + L]); + //~^ ERROR: mismatched types + //~^^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr new file mode 100644 index 000000000..da5194696 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/wf_obligation.rs:17:17 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L` + | + = note: expected constant `N + 1 + M` + found constant `L + 1 + L` + +error: unconstrained generic constant + --> $DIR/wf_obligation.rs:17:22 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate.rs b/tests/ui/const-generics/generic_const_exprs/cross_crate.rs new file mode 100644 index 000000000..dfc69e0b0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate.rs @@ -0,0 +1,15 @@ +// aux-build:const_evaluatable_lib.rs +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_evaluatable_lib; + +fn user() where [u8; std::mem::size_of::() - 1]: Sized { + assert_eq!(const_evaluatable_lib::test1::(), [0; std::mem::size_of::() - 1]); +} + +fn main() { + assert_eq!(const_evaluatable_lib::test1::(), [0; 3]); + user::(); + user::(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs new file mode 100644 index 000000000..b08fffd69 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs @@ -0,0 +1,14 @@ +// aux-build:const_evaluatable_lib.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_evaluatable_lib; + +fn user() { + let _ = const_evaluatable_lib::test1::(); + //~^ ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant + //~| ERROR unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr new file mode 100644 index 000000000..7b4d46b82 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -0,0 +1,54 @@ +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | +LL | [u8; std::mem::size_of::() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | +LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + | +LL | [u8; std::mem::size_of::() - 1]: Sized, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: unconstrained generic constant + --> $DIR/cross_crate_predicate.rs:7:13 + | +LL | let _ = const_evaluatable_lib::test1::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` +note: required by a bound in `test1` + --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + | +LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr new file mode 100644 index 000000000..d674e3acd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr @@ -0,0 +1,39 @@ +error: generic parameters may not be used in const operations + --> $DIR/dependence_lint.rs:14:32 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/dependence_lint.rs:21:37 + | +LL | let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, error with gce + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/dependence_lint.rs:10:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/dependence_lint.rs:17:9 + | +LL | [0; if false { size_of::() } else { 3 }]; // lint on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + +error: aborting due to 2 previous errors; 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr new file mode 100644 index 000000000..74111ef1d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr @@ -0,0 +1,34 @@ +error: overly complex generic constant + --> $DIR/dependence_lint.rs:17:9 + | +LL | [0; if false { size_of::() } else { 3 }]; // lint on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: overly complex generic constant + --> $DIR/dependence_lint.rs:21:17 + | +LL | let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:14:12 + | +LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:` + +error: unconstrained generic constant + --> $DIR/dependence_lint.rs:10:9 + | +LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs new file mode 100644 index 000000000..b715e07f8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.rs @@ -0,0 +1,26 @@ +// revisions: full gce +// compile-flags: -Zdeduplicate-diagnostics=yes + +#![cfg_attr(gce, feature(generic_const_exprs))] +#![allow(incomplete_features)] + +use std::mem::size_of; + +fn foo() { + [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs` + //[gce]~^ ERROR unconstrained + //[full]~^^ WARNING cannot use constants + //[full]~| WARNING this was previously accepted + let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce + //[full]~^ ERROR generic parameters may not be used + //[gce]~^^ ERROR unconstrained generic + [0; if false { size_of::() } else { 3 }]; // lint on stable, error with gce + //[gce]~^ ERROR overly complex + //[full]~^^ WARNING cannot use constants + //[full]~| WARNING this was previously accepted + let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, error with gce + //[full]~^ ERROR generic parameters may not be used + //[gce]~^^ ERROR overly complex +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.rs b/tests/ui/const-generics/generic_const_exprs/different-fn.rs new file mode 100644 index 000000000..e8bc703bd --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::mem::size_of; +use std::marker::PhantomData; + +struct Foo(PhantomData); + +fn test() -> [u8; size_of::()] { + [0; size_of::>()] + //~^ ERROR unconstrained generic constant + //~| ERROR mismatched types +} + +fn main() { + test::(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/different-fn.stderr b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr new file mode 100644 index 000000000..83a2f3740 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/different-fn.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/different-fn.rs:10:5 + | +LL | [0; size_of::>()] + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::()`, found `size_of::>()` + | + = note: expected constant `size_of::()` + found constant `size_of::>()` + +error: unconstrained generic constant + --> $DIR/different-fn.rs:10:9 + | +LL | [0; size_of::>()] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); size_of::>()]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/division.rs b/tests/ui/const-generics/generic_const_exprs/division.rs new file mode 100644 index 000000000..098fa9e04 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/division.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn with_bound() where [u8; N / 2]: Sized { + let _: [u8; N / 2] = [0; N / 2]; +} + +fn main() { + with_bound::<4>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs new file mode 100644 index 000000000..3543960c3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test is a repro for #82279. It checks that we don't error +// when calling is_const_evaluatable on `std::mem::size_of::()` +// when looking for candidates that may prove `T: Foo` in `foo` + +trait Foo {} + +#[allow(dead_code)] +fn foo() {} + +impl Foo for T where [(); std::mem::size_of::()]: {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/drop_impl.rs b/tests/ui/const-generics/generic_const_exprs/drop_impl.rs new file mode 100644 index 000000000..077f77aa0 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/drop_impl.rs @@ -0,0 +1,16 @@ +//check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo +where + [(); N + 1]: ; + +impl Drop for Foo +where + [(); N + 1]: , +{ + fn drop(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs b/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs new file mode 100644 index 000000000..e4111157e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs @@ -0,0 +1,24 @@ +// run-pass +// Test that we use the elaborated predicates from traits +// to satisfy const evaluatable predicates. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +use std::mem::size_of; + +trait Foo: Sized +where + [(); size_of::()]: Sized, +{ +} + +impl Foo for u64 {} +impl Foo for u32 {} + +fn foo() -> [u8; size_of::()] { + [0; size_of::()] +} + +fn main() { + assert_eq!(foo::(), [0; 4]); + assert_eq!(foo::(), [0; 8]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs new file mode 100644 index 000000000..8023b998a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -0,0 +1,26 @@ +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Const; + +pub trait Trait { + type AssocTy; + fn assoc_fn() -> Self::AssocTy; +} + +impl Trait for Const // OK, trait impl predicates +where + Const<{ my_const_fn(U) }>: , +{ + type AssocTy = Const<{ my_const_fn(U) }>; + //~^ ERROR private type + fn assoc_fn() -> Self::AssocTy { + Const + } +} + +const fn my_const_fn(val: u8) -> u8 { + // body of this function doesn't matter + val +} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr new file mode 100644 index 000000000..2d9de8805 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/eval-privacy.rs:16:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs new file mode 100644 index 000000000..c59d62e57 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs @@ -0,0 +1,26 @@ +// build-pass + +#![feature(generic_const_exprs)] +//~^ WARNING the feature `generic_const_exprs` is incomplete + +trait Generic { + const ASSOC: usize; +} + +impl Generic for u8 { + const ASSOC: usize = 17; +} +impl Generic for u16 { + const ASSOC: usize = 13; +} + + +fn uses_assoc_type() -> [u8; N + T::ASSOC] { + [0; N + T::ASSOC] +} + +fn only_generic_n() -> [u8; N + 13] { + uses_assoc_type::() +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr new file mode 100644 index 000000000..8eb1fccc5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/eval-try-unify.rs:3:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs b/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs new file mode 100644 index 000000000..340e35e1c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs @@ -0,0 +1,22 @@ +// check-pass + +// We previously always returned ambiguity when equating generic consts, even if they +// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1` +// should fail. +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +enum Assert {} +trait IsTrue {} +impl IsTrue for Assert {} + +struct Foo; +trait Bar {} +impl Bar for Foo +where + Assert<{ N > 1 }>: IsTrue, + Assert<{ M > 1 }>: IsTrue, +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs new file mode 100644 index 000000000..10ab2fd86 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs @@ -0,0 +1,11 @@ +type Arr = [u8; N - 1]; +//~^ ERROR generic parameters may not be used in const operations + +fn test() -> Arr where Arr: Default { + Default::default() +} + +fn main() { + let x = test::<33>(); + assert_eq!(x, [0; 32]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr new file mode 100644 index 000000000..2d60ebaa8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/feature-gate-generic_const_exprs.rs:1:33 + | +LL | type Arr = [u8; N - 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/fn_call.rs b/tests/ui/const-generics/generic_const_exprs/fn_call.rs new file mode 100644 index 000000000..cbe4277df --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/fn_call.rs @@ -0,0 +1,30 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn test_me(a: usize, b: usize) -> usize { + if a < b { + std::mem::size_of::() + } else { + usize::MAX + } +} + +fn test_simple() -> [u8; std::mem::size_of::()] +where + [u8; std::mem::size_of::()]: Sized, +{ + [0; std::mem::size_of::()] +} + +fn test_with_args() -> [u8; test_me::(N, N + 1) + N] +where + [u8; test_me::(N, N + 1) + N]: Sized, +{ + [0; test_me::(N, N + 1) + N] +} + +fn main() { + assert_eq!([0; 8], test_simple::()); + assert_eq!([0; 12], test_with_args::()); +} diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs new file mode 100644 index 000000000..b8f9827ec --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn test() -> [u8; N - 1] { + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr new file mode 100644 index 000000000..bd71b49ee --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig-fail.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/from-sig-fail.rs:4:35 + | +LL | fn test() -> [u8; N - 1] { + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/from-sig.rs b/tests/ui/const-generics/generic_const_exprs/from-sig.rs new file mode 100644 index 000000000..28de4f864 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/from-sig.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; + +fn test() -> Foo<{ N > 10 }> { + Foo +} + +fn main() { + let _: Foo = test::<12>(); + let _: Foo = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/function-call.rs b/tests/ui/const-generics/generic_const_exprs/function-call.rs new file mode 100644 index 000000000..3c866333d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/function-call.rs @@ -0,0 +1,20 @@ +// check-pass +// compile-flags: -Zdeduplicate-diagnostics=yes + +const fn foo() -> usize { + // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here, + // which would cause this function to fail on 32 bit systems. + if false { + std::mem::size_of::() + } else { + 8 + } +} + +fn test() { + let _ = [0; foo::()]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/function-call.stderr b/tests/ui/const-generics/generic_const_exprs/function-call.stderr new file mode 100644 index 000000000..84abfe578 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/function-call.stderr @@ -0,0 +1,12 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/function-call.rs:15:17 + | +LL | let _ = [0; foo::()]; + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs b/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs new file mode 100644 index 000000000..7120d6ee2 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/impl-bounds.rs @@ -0,0 +1,25 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::mem::size_of; + +struct Foo(T); + +impl Foo() }> { + fn test() { + let _: [u8; std::mem::size_of::()]; + } +} + +trait Bar { + fn test_me(); +} + +impl Bar<{ size_of::() }> for Foo { + fn test_me() { + let _: [u8; std::mem::size_of::()]; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs b/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs new file mode 100644 index 000000000..b8058c252 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/infer-too-generic.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +use std::{mem, ptr}; + +fn split_first(arr: [T; N]) -> (T, [T; N - 1]) +where + [T; N - 1]: Sized, +{ + let arr = mem::ManuallyDrop::new(arr); + unsafe { + let head = ptr::read(&arr[0]); + let tail = ptr::read(&arr[1..] as *const [T] as *const [T; N - 1]); + (head, tail) + } +} + +fn main() { + let arr = [0, 1, 2, 3, 4]; + let (head, tail) = split_first(arr); + assert_eq!(head, 0); + assert_eq!(tail, [1, 2, 3, 4]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100217.rs b/tests/ui/const-generics/generic_const_exprs/issue-100217.rs new file mode 100644 index 000000000..acdc348a3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-100217.rs @@ -0,0 +1,42 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait TraitOne { + const MY_NUM: usize; + type MyErr: std::fmt::Debug; + + fn do_one_stuff(arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr>; +} + +trait TraitTwo { + fn do_two_stuff(); +} + +impl TraitTwo for O +where + [(); Self::MY_NUM]:, +{ + fn do_two_stuff() { + O::do_one_stuff([5; Self::MY_NUM]).unwrap() + } +} + +struct Blargotron; + +#[derive(Debug)] +struct ErrTy([(); N]); + +impl TraitOne for Blargotron { + const MY_NUM: usize = 3; + type MyErr = ErrTy<{ Self::MY_NUM }>; + + fn do_one_stuff(_arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr> { + Ok(()) + } +} + +fn main() { + Blargotron::do_two_stuff(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-100360.rs b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs new file mode 100644 index 000000000..5572f1f88 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-100360.rs @@ -0,0 +1,13 @@ +// check-pass +// (this requires debug assertions) + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +fn foo(arg: &'static bool) -> bool { + B == arg +} + +fn main() { + foo::<{ &true }>(&false); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102074.rs b/tests/ui/const-generics/generic_const_exprs/issue-102074.rs new file mode 100644 index 000000000..66d15cf12 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102074.rs @@ -0,0 +1,23 @@ +// check-pass +// Checks that the NoopMethodCall lint doesn't call Instance::resolve on unresolved consts + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[derive(Debug, Clone)] +pub struct Aes128CipherKey([u8; Aes128Cipher::KEY_LEN]); + +impl Aes128CipherKey { + pub fn new(key: &[u8; Aes128Cipher::KEY_LEN]) -> Self { + Self(key.clone()) + } +} + +#[derive(Debug, Clone)] +pub struct Aes128Cipher; + +impl Aes128Cipher { + const KEY_LEN: usize = 16; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs new file mode 100644 index 000000000..7aea0d30d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait X { + type Y<'a>; +} + +const _: () = { + fn f2<'a>(arg: Box = &'a ()>>) {} + //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments + //~| ERROR this associated type takes 0 generic arguments but 1 generic argument +}; + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr new file mode 100644 index 000000000..8278edabe --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr @@ -0,0 +1,33 @@ +error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied + --> $DIR/issue-102768.rs:9:30 + | +LL | fn f2<'a>(arg: Box = &'a ()>>) {} + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-102768.rs:5:10 + | +LL | type Y<'a>; + | ^ -- +help: add missing lifetime argument + | +LL | fn f2<'a>(arg: Box = &'a ()>>) {} + | +++ + +error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-102768.rs:9:30 + | +LL | fn f2<'a>(arg: Box = &'a ()>>) {} + | ^--- help: remove these generics + | | + | expected 0 generic arguments + | +note: associated type defined here, with 0 generic parameters + --> $DIR/issue-102768.rs:5:10 + | +LL | type Y<'a>; + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.rs b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs new file mode 100644 index 000000000..d8b23bc01 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Trait { + fn fnc(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + fn foo() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr new file mode 100644 index 000000000..ed7a8cb19 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105257.stderr @@ -0,0 +1,14 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-105257.rs:5:12 + | +LL | fn fnc(&self) {} + | ^^^^^^^^^^^^^^^^^^^ + +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-105257.rs:6:12 + | +LL | fn foo() }>(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.rs b/tests/ui/const-generics/generic_const_exprs/issue-105608.rs new file mode 100644 index 000000000..e28ba3b1a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Combination; + +impl Combination { + fn and(self) -> Combination<{ STRATEGIES + 1 }> { + Combination + } +} + +pub fn main() { + Combination::<0>.and::<_>().and::<_>(); + //~^ ERROR: type annotations needed +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr new file mode 100644 index 000000000..0be4c43da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-105608.rs:13:22 + | +LL | Combination::<0>.and::<_>().and::<_>(); + | ^^^ cannot infer type of the type parameter `M` declared on the associated function `and` + | +help: consider specifying the generic argument + | +LL | Combination::<0>.and::<_>().and::<_>(); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr new file mode 100644 index 000000000..0742db398 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | + = note: expected constant `X` + found constant `Self::SIZE` + +error: unconstrained generic constant + --> $DIR/issue-62504.rs:18:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr new file mode 100644 index 000000000..65822856e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr @@ -0,0 +1,27 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-62504.rs:18:25 + | +LL | ArrayHolder([0; Self::SIZE]) + | ^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0308]: mismatched types + --> $DIR/issue-62504.rs:18:21 + | +LL | ArrayHolder([0; Self::SIZE]) + | ----------- ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` + | | + | arguments to this struct are incorrect + | + = note: expected array `[u32; X]` + found array `[u32; Self::SIZE]` +note: tuple struct defined here + --> $DIR/issue-62504.rs:14:8 + | +LL | struct ArrayHolder([u32; X]); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs new file mode 100644 index 000000000..a97f4b8ff --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs @@ -0,0 +1,27 @@ +// revisions: full min +#![allow(incomplete_features)] +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +trait HasSize { + const SIZE: usize; +} + +impl HasSize for ArrayHolder { + const SIZE: usize = X; +} + +struct ArrayHolder([u32; X]); + +impl ArrayHolder { + pub const fn new() -> Self { + ArrayHolder([0; Self::SIZE]) + //~^ ERROR mismatched types + //[full]~^^ ERROR unconstrained generic constant + //[min]~^^^ ERROR constant expression depends on a generic parameter + } +} + +fn main() { + let mut array = ArrayHolder::new(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.rs b/tests/ui/const-generics/generic_const_exprs/issue-69654.rs new file mode 100644 index 000000000..9b36699bb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.rs @@ -0,0 +1,19 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Bar {} +impl Bar for [u8; T] {} +//~^ ERROR expected value, found type parameter `T` + +struct Foo {} +impl Foo +where + [u8; N]: Bar<[(); N]>, +{ + fn foo() {} +} + +fn main() { + Foo::foo(); + //~^ ERROR the function or associated item +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr new file mode 100644 index 000000000..eb4ff8305 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -0,0 +1,30 @@ +error[E0423]: expected value, found type parameter `T` + --> $DIR/issue-69654.rs:5:25 + | +LL | impl Bar for [u8; T] {} + | - ^ not a value + | | + | found this type parameter + +error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied + --> $DIR/issue-69654.rs:17:10 + | +LL | struct Foo {} + | -------------------------- function or associated item `foo` not found for this struct +... +LL | Foo::foo(); + | ^^^ function or associated item cannot be called on `Foo<_>` due to unsatisfied trait bounds + | +note: trait bound `[u8; _]: Bar<[(); _]>` was not satisfied + --> $DIR/issue-69654.rs:11:14 + | +LL | impl Foo + | ------ +LL | where +LL | [u8; N]: Bar<[(); N]>, + | ^^^^^^^^^^^^ unsatisfied trait bound introduced here + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0599. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr new file mode 100644 index 000000000..ea6f5f692 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -0,0 +1,38 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:11:17 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ cannot perform const operation using `LHS` + | + = help: const parameters may only be used as standalone arguments, i.e. `LHS` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:11:24 + | +LL | Condition<{ LHS <= RHS }>: True + | ^^^ cannot perform const operation using `RHS` + | + = help: const parameters may only be used as standalone arguments, i.e. `RHS` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:23:25 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ cannot perform const operation using `I` + | + = help: const parameters may only be used as standalone arguments, i.e. `I` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-72787.rs:23:36 + | +LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, + | ^ cannot perform const operation using `J` + | + = help: const parameters may only be used as standalone arguments, i.e. `J` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 4 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs new file mode 100644 index 000000000..657fec2e9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -0,0 +1,33 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +pub struct IsLessOrEqual; +pub struct Condition; +pub trait True {} + +impl True for IsLessOrEqual where + Condition<{ LHS <= RHS }>: True +//[min]~^ Error generic parameters may not be used in const operations +//[min]~| Error generic parameters may not be used in const operations +{ +} +impl True for Condition {} + +struct S; +impl S +where + IsLessOrEqual: True, + IsLessOrEqual: True, + IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, +//[min]~^ Error generic parameters may not be used in const operations +//[min]~| Error generic parameters may not be used in const operations + // Condition<{ 8 - I <= 8 - J }>: True, +{ + fn print() { + println!("I {} J {}", I, J); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr new file mode 100644 index 000000000..f2fddfbfb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-72819-generic-in-const-eval.rs:20:12 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error[E0308]: mismatched types + --> $DIR/issue-72819-generic-in-const-eval.rs:20:32 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr new file mode 100644 index 000000000..42671412f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-72819-generic-in-const-eval.rs:8:17 + | +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs new file mode 100644 index 000000000..7a5aa9e47 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs @@ -0,0 +1,23 @@ +// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type +// bounds. +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Arr +where Assert::<{N < usize::MAX / 2}>: IsTrue, +//[min]~^ ERROR generic parameters may not be used in const operations +{ +} + +enum Assert {} + +trait IsTrue {} + +impl IsTrue for Assert {} + +fn main() { + let x: Arr<{usize::MAX}> = Arr {}; + //[full]~^ ERROR mismatched types + //[full]~| ERROR mismatched types +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-73298.rs b/tests/ui/const-generics/generic_const_exprs/issue-73298.rs new file mode 100644 index 000000000..3c59e1b79 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-73298.rs @@ -0,0 +1,23 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::convert::AsMut; +use std::default::Default; + +trait Foo: Sized { + type Baz: Default + AsMut<[u8]>; + fn bar() { + Self::Baz::default().as_mut(); + } +} + +impl Foo for () { + type Baz = [u8; 1 * 1]; + //type Baz = [u8; 1]; +} + +fn main() { + <() as Foo>::bar(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-73899.rs b/tests/ui/const-generics/generic_const_exprs/issue-73899.rs new file mode 100644 index 000000000..d1ab1be04 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-73899.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo {} + +impl Foo for [(); N] where Self: FooImpl<{ N == 0 }> {} + +trait FooImpl {} + +impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {} + +impl FooImpl<{ 0u8 != 0u8 }> for [(); N] {} + +fn foo(_v: T) {} + +fn main() { + foo([]); + foo([()]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74634.rs b/tests/ui/const-generics/generic_const_exprs/issue-74634.rs new file mode 100644 index 000000000..cd1f7a9da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74634.rs @@ -0,0 +1,28 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait If {} +impl If for () {} + +trait IsZero { + type Answer; +} + +struct True; +struct False; + +impl IsZero for () +where (): If<{N == 0}> { + type Answer = True; +} + +trait Foobar {} + +impl Foobar for () +where (): IsZero {} + +impl Foobar for () +where (): IsZero {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.rs b/tests/ui/const-generics/generic_const_exprs/issue-74713.rs new file mode 100644 index 000000000..0bcb997d9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.rs @@ -0,0 +1,8 @@ +fn bug<'a>() +where + [(); { //~ ERROR mismatched types + let _: &'a (); //~ ERROR a non-static lifetime is not allowed in a `const` + }]: +{} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr new file mode 100644 index 000000000..e7673df0a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr @@ -0,0 +1,22 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-74713.rs:4:17 + | +LL | let _: &'a (); + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-74713.rs:3:10 + | +LL | [(); { + | __________^ +LL | | let _: &'a (); +LL | | }]: + | |_____^ expected `usize`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.rs b/tests/ui/const-generics/generic_const_exprs/issue-76595.rs new file mode 100644 index 000000000..10247ce6b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Bool; + +trait True {} + +impl True for Bool {} + +fn test() where Bool<{core::mem::size_of::() > 4}>: True { + todo!() +} + +fn main() { + test::<2>(); + //~^ ERROR function takes 2 generic arguments +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr new file mode 100644 index 000000000..c587a7e15 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr @@ -0,0 +1,21 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/issue-76595.rs:15:5 + | +LL | test::<2>(); + | ^^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `T`, `P` + --> $DIR/issue-76595.rs:10:4 + | +LL | fn test() where Bool<{core::mem::size_of::() > 4}>: True { + | ^^^^ - -------------- +help: add missing generic argument + | +LL | test::<2, P>(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs new file mode 100644 index 000000000..2fa9a71fb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test is a minimized reproduction for #79518 where +// during error handling for the type mismatch we would try +// to evaluate std::mem::size_of:: causing an ICE + +trait Foo { + type Assoc: PartialEq; + const AssocInstance: Self::Assoc; + + fn foo() + where + [(); std::mem::size_of::()]: , + { + Self::AssocInstance == [(); std::mem::size_of::()]; + //~^ Error: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr new file mode 100644 index 000000000..9baf9790e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32 + | +LL | Self::AssocInstance == [(); std::mem::size_of::()]; + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); std::mem::size_of::()]` + | | + | expected because this is `::Assoc` + | + = note: expected associated type `::Assoc` + found array `[(); std::mem::size_of::()]` + = help: consider constraining the associated type `::Assoc` to `[(); std::mem::size_of::()]` or calling a method that returns `::Assoc` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs b/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs new file mode 100644 index 000000000..77d3c98da --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the correct `param_env` is used so that +// attempting to normalize `Self::N` does not cause an ICE. + +pub struct Foo; + +impl Foo { + pub fn foo() {} +} + +pub trait Bar { + const N: usize; + fn bar() + where + [(); Self::N]: , + { + Foo::<{ Self::N }>::foo(); + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.rs b/tests/ui/const-generics/generic_const_exprs/issue-80742.rs new file mode 100644 index 000000000..275f69953 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.rs @@ -0,0 +1,32 @@ +// check-fail + +// This test used to cause an ICE in rustc_mir::interpret::step::eval_rvalue_into_place + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::fmt::Debug; +use std::marker::PhantomData; +use std::mem::size_of; + +struct Inline +where + [u8; size_of::() + 1]: , +{ + _phantom: PhantomData, + buf: [u8; size_of::() + 1], +} + +impl Inline +where + [u8; size_of::() + 1]: , +{ + pub fn new(val: T) -> Inline { + todo!() + } +} + +fn main() { + let dst = Inline::::new(0); //~ ERROR + //~^ ERROR +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr new file mode 100644 index 000000000..6aa8ee13b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -0,0 +1,71 @@ +error[E0080]: evaluation of `Inline::::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: size_of called on unsized type `dyn Debug` + | +note: inside `std::mem::size_of::` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `Inline::::{constant#0}` + --> $DIR/issue-80742.rs:22:10 + | +LL | [u8; size_of::() + 1]: , + | ^^^^^^^^^^^^^^ + +error[E0599]: the function or associated item `new` exists for struct `Inline`, but its trait bounds were not satisfied + --> $DIR/issue-80742.rs:30:36 + | +LL | struct Inline + | ---------------- function or associated item `new` not found for this struct +... +LL | let dst = Inline::::new(0); + | ^^^ function or associated item cannot be called on `Inline` due to unsatisfied trait bounds + --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | + = note: doesn't satisfy `dyn Debug: Sized` + | +note: trait bound `dyn Debug: Sized` was not satisfied + --> $DIR/issue-80742.rs:20:6 + | +LL | impl Inline + | ^ --------- + | | + | unsatisfied trait bound introduced here +help: consider relaxing the type parameter's implicit `Sized` bound + | +LL | impl Inline + | ++++++++ + +error[E0080]: evaluation of `Inline::::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: size_of called on unsized type `dyn Debug` + | +note: inside `std::mem::size_of::` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `Inline::::{constant#0}` + --> $DIR/issue-80742.rs:14:10 + | +LL | [u8; size_of::() + 1]: , + | ^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/issue-80742.rs:30:15 + | +LL | let dst = Inline::::new(0); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Debug` +note: required by a bound in `Inline` + --> $DIR/issue-80742.rs:12:15 + | +LL | struct Inline + | ^ required by this bound in `Inline` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Inline + | ++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0599. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-82268.rs b/tests/ui/const-generics/generic_const_exprs/issue-82268.rs new file mode 100644 index 000000000..d08fc5beb --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-82268.rs @@ -0,0 +1,73 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Collate { + type Pass; + type Fail; + + fn collate(self) -> (Self::Pass, Self::Fail); +} + +impl Collate for () { + type Pass = (); + type Fail = (); + + fn collate(self) -> ((), ()) { + ((), ()) + } +} + +trait CollateStep { + type Pass; + type Fail; + fn collate_step(x: X, prev: Prev) -> (Self::Pass, Self::Fail); +} + +impl CollateStep for () { + type Pass = (X, P); + type Fail = F; + + fn collate_step(x: X, (p, f): (P, F)) -> ((X, P), F) { + ((x, p), f) + } +} + +struct CollateOpImpl; +trait CollateOpStep { + type NextOp; + type Apply; +} + +impl CollateOpStep for CollateOpImpl +where + CollateOpImpl<{ MASK >> 1 }>: Sized, +{ + type NextOp = CollateOpImpl<{ MASK >> 1 }>; + type Apply = (); +} + +impl Collate for (H, T) +where + T: Collate, + Op::Apply: CollateStep, +{ + type Pass = >::Pass; + type Fail = >::Fail; + + fn collate(self) -> (Self::Pass, Self::Fail) { + >::collate_step(self.0, self.1.collate()) + } +} + +fn collate(x: X) -> (X::Pass, X::Fail) +where + X: Collate>, +{ + x.collate() +} + +fn main() { + dbg!(collate::<_, 5>(("Hello", (42, ('!', ()))))); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83765.rs b/tests/ui/const-generics/generic_const_exprs/issue-83765.rs new file mode 100644 index 000000000..fac811d13 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83765.rs @@ -0,0 +1,38 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn lazy_updim(&self, size: [usize; NEWDIM]) {} +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + //~^ ERROR: method not compatible with trait [E0308] + self.reference.size() + //~^ ERROR: unconstrained generic constant + //~| ERROR: mismatched types + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr b/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr new file mode 100644 index 000000000..b693023f1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83765.stderr @@ -0,0 +1,34 @@ +error[E0308]: method not compatible with trait + --> $DIR/issue-83765.rs:30:5 + | +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` + | + = note: expected constant `Self::DIM` + found constant `DIM` + +error: unconstrained generic constant + --> $DIR/issue-83765.rs:32:24 + | +LL | self.reference.size() + | ^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:` +note: required by a bound in `TensorSize::size` + --> $DIR/issue-83765.rs:9:31 + | +LL | fn size(&self) -> [usize; Self::DIM]; + | ^^^^^^^^^ required by this bound in `TensorSize::size` + +error[E0308]: mismatched types + --> $DIR/issue-83765.rs:32:9 + | +LL | self.reference.size() + | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` + | + = note: expected constant `DIM` + found constant `Self::DIM` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-83972.rs b/tests/ui/const-generics/generic_const_exprs/issue-83972.rs new file mode 100644 index 000000000..0063719b8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-83972.rs @@ -0,0 +1,38 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub trait Foo { + fn foo(&self); +} + +pub struct FooImpl; +impl Foo for FooImpl { + fn foo(&self) {} +} + +pub trait Bar: 'static { + type Foo: Foo; + fn get() -> &'static Self::Foo; +} + +struct BarImpl; +impl Bar for BarImpl { + type Foo = FooImpl< + { + { 4 } + }, + >; + fn get() -> &'static Self::Foo { + &FooImpl + } +} + +pub fn boom() { + B::get().foo(); +} + +fn main() { + boom::(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-84408.rs b/tests/ui/const-generics/generic_const_exprs/issue-84408.rs new file mode 100644 index 000000000..fb2e5590d --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-84408.rs @@ -0,0 +1,38 @@ +// Regression test for #84408. +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Melon { + fn new(arr: [i32; X]) -> Self; + fn change>(self) -> T; +} + +struct Foo([i32; 5]); +struct Bar([i32; A + B]) +where + [(); A + B]: ; + +impl Melon<5> for Foo { + fn new(arr: [i32; 5]) -> Self { + Foo(arr) + } + fn change>(self) -> T { + T::new(self.0) + } +} + +impl Melon<{ A + B }> for Bar +where + [(); A + B]: , +{ + fn new(arr: [i32; A + B]) -> Self { + Bar(arr) + } + fn change>(self) -> T { + T::new(self.0) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-84669.rs b/tests/ui/const-generics/generic_const_exprs/issue-84669.rs new file mode 100644 index 000000000..3933ff20a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-84669.rs @@ -0,0 +1,30 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + type Output; + + fn foo() -> Self::Output; +} + +impl Foo for [u8; 3] { + type Output = [u8; 1 + 2]; + + fn foo() -> [u8; 3] { + [1u8; 3] + } +} + +fn bug() +where + [u8; N]: Foo, + <[u8; N] as Foo>::Output: AsRef<[u8]>, +{ + <[u8; N]>::foo().as_ref(); +} + +fn main() { + bug::<3>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.rs b/tests/ui/const-generics/generic_const_exprs/issue-85848.rs new file mode 100644 index 000000000..3a7f4c618 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.rs @@ -0,0 +1,32 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait _Contains { + const does_contain: bool; +} + +trait Contains {} + +trait Delegates {} + +impl Delegates for T where T: Contains {} + +const fn contains() -> bool +where + A: _Contains, +{ + A::does_contain +} + +impl Contains() }> for U where T: _Contains {} + +fn writes_to_path(cap: &C) { + writes_to_specific_path(&cap); + //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277] + //~| ERROR: unconstrained generic constant + //~| ERROR: mismatched types [E0308] +} + +fn writes_to_specific_path>(cap: &C) {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr new file mode 100644 index 000000000..e50ac671e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied + --> $DIR/issue-85848.rs:24:29 + | +LL | writes_to_specific_path(&cap); + | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the trait `Delegates` is implemented for `T` +note: required for `&C` to implement `Contains<(), true>` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl Contains() }> for U where T: _Contains {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ------------ unsatisfied trait bound introduced here +note: required for `&C` to implement `Delegates<()>` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl Delegates for T where T: Contains {} + | ^^^^^^^^^^^^ ^ ----------------- unsatisfied trait bound introduced here +note: required by a bound in `writes_to_specific_path` + --> $DIR/issue-85848.rs:30:31 + | +LL | fn writes_to_specific_path>(cap: &C) {} + | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` + +error: unconstrained generic constant + --> $DIR/issue-85848.rs:24:29 + | +LL | writes_to_specific_path(&cap); + | ----------------------- ^^^^ + | | + | required by a bound introduced by this call + | + = help: try adding a `where` bound using this expression: `where [(); { contains::() }]:` +note: required for `&C` to implement `Contains<(), true>` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl Contains() }> for U where T: _Contains {} + | ^^^^^^^^^^^^----------------------^ ^ + | | + | unsatisfied trait bound introduced here +note: required for `&C` to implement `Delegates<()>` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl Delegates for T where T: Contains {} + | ^^^^^^^^^^^^ ^ ----------------- unsatisfied trait bound introduced here +note: required by a bound in `writes_to_specific_path` + --> $DIR/issue-85848.rs:30:31 + | +LL | fn writes_to_specific_path>(cap: &C) {} + | ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` + +error[E0308]: mismatched types + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::() }` + | + = note: expected constant `true` + found constant `{ contains::() }` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-86710.rs b/tests/ui/const-generics/generic_const_exprs/issue-86710.rs new file mode 100644 index 000000000..bdd8a21b3 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-86710.rs @@ -0,0 +1,73 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::marker::PhantomData; + +fn main() { + let x = FooImpl::> { phantom: PhantomData }; + let _ = x.foo::>(); +} + +trait Foo +where + T: Bar, +{ + fn foo(&self) + where + T: Operation, + >::Output: Bar; +} + +struct FooImpl +where + T: Bar, +{ + phantom: PhantomData, +} + +impl Foo for FooImpl +where + T: Bar, +{ + fn foo(&self) + where + T: Operation, + >::Output: Bar, + { + <>::Output as Bar>::error_occurs_here(); + } +} + +trait Bar { + fn error_occurs_here(); +} + +struct BarImpl; + +impl Bar for BarImpl { + fn error_occurs_here() {} +} + +trait Operation { + type Output; +} + +//// Part-A: This causes error. +impl Operation> for BarImpl +where + BarImpl<{ N + M }>: Sized, +{ + type Output = BarImpl<{ N + M }>; +} + +//// Part-B: This doesn't cause error. +// impl Operation> for BarImpl { +// type Output = BarImpl; +// } + +//// Part-C: This also doesn't cause error. +// impl Operation> for BarImpl { +// type Output = BarImpl<{ M }>; +// } diff --git a/tests/ui/const-generics/generic_const_exprs/issue-89851.rs b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs new file mode 100644 index 000000000..cde849d90 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-89851.rs @@ -0,0 +1,12 @@ +// check-pass +// (this requires debug assertions) + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub const BAR: () = ice::<"">(); +pub const fn ice() { + &10; +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-90847.rs b/tests/ui/const-generics/generic_const_exprs/issue-90847.rs new file mode 100644 index 000000000..ebc6fe141 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-90847.rs @@ -0,0 +1,9 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(adt_const_params)] + +struct Foo where [(); 0 + 0]: Sized; + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs new file mode 100644 index 000000000..643126a46 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs @@ -0,0 +1,10 @@ +// aux-build:issue-94287-aux.rs +// build-fail + +extern crate issue_94287_aux; + +use std::str::FromStr; + +fn main() { + let _ = >::from_str(""); +} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr new file mode 100644 index 000000000..7390a0077 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr @@ -0,0 +1,15 @@ +error: failed to evaluate generic const expression + --> $DIR/auxiliary/issue-94287-aux.rs:15:8 + | +LL | If<{ FRAC <= 32 }>: True, + | ^^^^^^^^^^^^^^ + | + = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]` +help: consider enabling this feature + --> $DIR/issue-94287.rs:1:1 + | +LL | #![feature(generic_const_exprs)] + | + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94293.rs b/tests/ui/const-generics/generic_const_exprs/issue-94293.rs new file mode 100644 index 000000000..713c5d89a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-94293.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![deny(const_evaluatable_unchecked)] + +pub struct If; +pub trait True {} +impl True for If {} + +pub struct FixedI8 { + pub bits: i8, +} + +impl PartialEq> for FixedI8 +where + If<{ FRAC_RHS <= 8 }>: True, +{ + fn eq(&self, _rhs: &FixedI8) -> bool { + unimplemented!() + } +} + +impl PartialEq for FixedI8 { + fn eq(&self, rhs: &i8) -> bool { + let rhs_as_fixed = FixedI8::<0> { bits: *rhs }; + PartialEq::eq(self, &rhs_as_fixed) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs new file mode 100644 index 000000000..67e30232e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs @@ -0,0 +1,25 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl Changes +where + [(); CHANGES.len()]:, +{ + pub const fn new() -> Self { + Self { + changes: [0; CHANGES.len()], + } + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr new file mode 100644 index 000000000..1cceaece7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-1.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs new file mode 100644 index 000000000..00568a089 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] +//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +pub struct Changes +where + [(); CHANGES.len()]:, +{ + changes: [usize; CHANGES.len()], +} + +impl Changes +where + [(); CHANGES.len()]:, +{ + pub fn combine(&mut self, other: &Self) { + for _change in &self.changes {} + } +} + +pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr new file mode 100644 index 000000000..774e842bc --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:12 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-97047-ice-2.rs:3:30 + | +LL | #![feature(adt_const_params, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + +warning: 2 warnings emitted + diff --git a/tests/ui/const-generics/generic_const_exprs/issue-99647.rs b/tests/ui/const-generics/generic_const_exprs/issue-99647.rs new file mode 100644 index 000000000..f797beda8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-99647.rs @@ -0,0 +1,15 @@ +// edition:2018 +// run-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-99705.rs b/tests/ui/const-generics/generic_const_exprs/issue-99705.rs new file mode 100644 index 000000000..75b57b621 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/issue-99705.rs @@ -0,0 +1,33 @@ +// check-pass +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +pub trait MyIterator { + type Output; +} + +pub trait Foo { + const ABC: usize; +} + +pub struct IteratorStruct{ + +} + +pub struct Bar { + pub data: [usize; N] +} + +impl MyIterator for IteratorStruct { + type Output = Bar; +} + +pub fn test1() -> impl MyIterator> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} + +pub trait Baz{} +impl Baz for Bar {} +pub fn test2() -> impl MyIterator> where [(); T::ABC]: Sized { + IteratorStruct::<{T::ABC}>{} +} diff --git a/tests/ui/const-generics/generic_const_exprs/less_than.rs b/tests/ui/const-generics/generic_const_exprs/less_than.rs new file mode 100644 index 000000000..2e9af1bf4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/less_than.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; + +fn test() -> Foo<{ N > 10 }> where Foo<{ N > 10 }>: Sized { + Foo +} + +fn main() { + let _: Foo = test::<12>(); + let _: Foo = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.rs b/tests/ui/const-generics/generic_const_exprs/let-bindings.rs new file mode 100644 index 000000000..cd5d76dd9 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// We do not yet want to support let-bindings in abstract consts, +// so this test should keep failing for now. +fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + //~^ ERROR overly complex generic constant + //~| ERROR overly complex generic constant + Default::default() +} + +fn main() { + let x = test::<31>(); + assert_eq!(x, [0; 32]); +} diff --git a/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr new file mode 100644 index 000000000..823a4f8a1 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -0,0 +1,20 @@ +error: overly complex generic constant + --> $DIR/let-bindings.rs:6:68 + | +LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/let-bindings.rs:6:35 + | +LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs new file mode 100644 index 000000000..2bd3c801f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn complex_maths(n : usize) -> usize { + 2 * n + 1 +} + +struct Example { + a: [f32; N], + b: [f32; complex_maths::(N)], + //~^ ERROR unconstrained + c: T, +} diff --git a/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr new file mode 100644 index 000000000..7b41e39b7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/needs_where_clause.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/needs_where_clause.rs:11:6 + | +LL | b: [f32; complex_maths::(N)], + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); complex_maths::(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs new file mode 100644 index 000000000..7e5022817 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs @@ -0,0 +1,24 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn callee() -> usize +where + [u8; M2 + 1]: Sized, +{ + M2 +} + +fn caller() -> usize +where + [u8; N1 + 1]: Sized, + [u8; (N1 + 1) + 1]: Sized, +{ + callee::<{ N1 + 1 }>() +} + +fn main() { + assert_eq!(caller::<4>(), 5); +} + +// Test that the ``(N1 + 1) + 1`` bound on ``caller`` satisfies the ``M2 + 1`` bound on ``callee`` diff --git a/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs new file mode 100644 index 000000000..769e3ae68 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Generic; + +struct ConstU64; + +impl Generic +where + ConstU64<{ K - 1 }>: , +{ + fn foo(self) -> u64 { + K + } +} + +impl Generic +where + ConstU64<{ K - 1 }>: , + ConstU64<{ K + 1 }>: , + ConstU64<{ K + 1 - 1 }>: , +{ + fn bar(self) -> u64 { + let x: Generic<{ K + 1 }> = Generic; + x.foo() + } +} + +fn main() { + assert_eq!((Generic::<10>).bar(), 11); +} + +// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the +// ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs new file mode 100644 index 000000000..316887e5e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs @@ -0,0 +1,34 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn zero_init() -> Substs1 +where + [u8; N + 1]: , +{ + Substs1([0; N + 1]) +} +struct Substs1([u8; N + 1]) +where + [(); N + 1]: ; + +fn substs2() -> Substs1<{ M * 2 }> +where + [(); { M * 2 } + 1]: , +{ + zero_init::<{ M * 2 }>() +} + +fn substs3() -> Substs1<{ (L - 1) * 2 }> +where + [(); (L - 1) * 2 + 1]: , +{ + substs2::<{ L - 1 }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 3]); +} + +// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the +// ``{ N + 1 }`` bound on ``Substs1`` diff --git a/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs new file mode 100644 index 000000000..d45a6465b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs @@ -0,0 +1,29 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_parens, unused_braces)] + +fn zero_init() -> Substs1<{ (N) }> +where + [u8; { (N) }]: , +{ + Substs1([0; { (N) }]) +} + +struct Substs1([u8; { (N) }]) +where + [(); { (N) }]: ; + +fn substs2() -> Substs1<{ (M) }> { + zero_init::<{ (M) }>() +} + +fn substs3() -> Substs1<{ (L) }> { + substs2::<{ (L) }>() +} + +fn main() { + assert_eq!(substs3::<2>().0, [0; 2]); +} + +// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the +// ``{ (N) }`` bound on ``Substs1`` diff --git a/tests/ui/const-generics/generic_const_exprs/no_dependence.rs b/tests/ui/const-generics/generic_const_exprs/no_dependence.rs new file mode 100644 index 000000000..db8dc6ed4 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_dependence.rs @@ -0,0 +1,13 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn two_args() -> [u8; M + 2] { + [0; M + 2] +} + +fn yay() -> [u8; 4] { + two_args::() // no lint +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs new file mode 100644 index 000000000..9c5de0317 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs @@ -0,0 +1,29 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused)] + +const fn complex_maths(n : usize) -> usize { + 2 * n + 1 +} + +pub struct Example { + a: [f32; N], + b: [f32; complex_maths(N)], + //~^ ERROR unconstrained generic +} + +impl Example { + pub fn new() -> Self { + Self { + a: [0.; N], + b: [0.; complex_maths(N)], + } + } +} + +impl Example<2> { + pub fn sum(&self) -> f32 { + self.a.iter().sum::() + self.b.iter().sum::() + } +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr new file mode 100644 index 000000000..3e5c2f5ca --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/no_where_clause.rs:10:6 + | +LL | b: [f32; complex_maths(N)], + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs new file mode 100644 index 000000000..1254b4435 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.rs @@ -0,0 +1,16 @@ +// aux-build:anon_const_non_local.rs + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate anon_const_non_local; + +fn bar() +where + [(); M + 1]:, +{ + let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::(); + //~^ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr new file mode 100644 index 000000000..3926c830a --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/non_local_anon_const_diagnostics.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/non_local_anon_const_diagnostics.rs:12:43 + | +LL | let _: anon_const_non_local::Foo<2> = anon_const_non_local::foo::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `anon_const_non_local::::foo::{constant#0}` + | + = note: expected constant `2` + found constant `anon_const_non_local::::foo::{constant#0}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs b/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs new file mode 100644 index 000000000..b37b354ae --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_braces)] + +#[rustfmt::skip] +fn foo() { + bar::<{{{{{{ N }}}}}}>(); +} + +fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs new file mode 100644 index 000000000..24d333aba --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + + +const fn bar() -> usize { 7 } + +trait Foo { + fn test(&self) -> [u8; bar::()]; +} + +impl Foo for () { + fn test(&self) -> [u8; bar::()] { + [0; bar::()] + } +} + +fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` cannot be made into an object + v.test(); +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr new file mode 100644 index 000000000..4e1d71f15 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-ret.rs:17:16 + | +LL | fn use_dyn(v: &dyn Foo) { + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-err-ret.rs:8:23 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) -> [u8; bar::()]; + | ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type + = help: consider moving `test` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs new file mode 100644 index 000000000..42c1cc507 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![deny(where_clauses_object_safety)] + + +const fn bar() -> usize { 7 } + +trait Foo { + fn test(&self) where [u8; bar::()]: Sized; + //~^ ERROR the trait `Foo` cannot be made into an object + //~| WARN this was previously accepted by the compiler but is being phased out +} + +impl Foo for () { + fn test(&self) where [u8; bar::()]: Sized {} +} + +fn use_dyn(v: &dyn Foo) { + v.test(); +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr new file mode 100644 index 000000000..440cf457e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr @@ -0,0 +1,24 @@ +error: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-where-bounds.rs:9:8 + | +LL | fn test(&self) where [u8; bar::()]: Sized; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #51443 +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-err-where-bounds.rs:9:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) where [u8; bar::()]: Sized; + | ^^^^ ...because method `test` references the `Self` type in its `where` clause + = help: consider moving `test` to another trait +note: the lint level is defined here + --> $DIR/object-safety-err-where-bounds.rs:3:9 + | +LL | #![deny(where_clauses_object_safety)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs new file mode 100644 index 000000000..79e9834b5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs @@ -0,0 +1,21 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + fn test(&self) -> [u8; N + 1]; +} + +impl Foo for () { + fn test(&self) -> [u8; N + 1] { + [0; N + 1] + } +} + +fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { + assert_eq!(v.test(), [0; N + 1]); +} + +fn main() { + use_dyn(&()); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr new file mode 100644 index 000000000..59e9fee1e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr @@ -0,0 +1,19 @@ +error[E0284]: type annotations needed + --> $DIR/object-safety-ok-infer-err.rs:19:5 + | +LL | use_dyn(&()); + | ^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `use_dyn` + | +note: required by a bound in `use_dyn` + --> $DIR/object-safety-ok-infer-err.rs:14:55 + | +LL | fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { + | ^^^^^ required by this bound in `use_dyn` +help: consider specifying the generic argument + | +LL | use_dyn::(&()); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs new file mode 100644 index 000000000..f4c89f623 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + fn test(&self) -> [u8; N + 1]; +} + +impl Foo for () { + fn test(&self) -> [u8; N + 1] { + [0; N + 1] + } +} + +fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { + assert_eq!(v.test(), [0; N + 1]); +} + +fn main() { + use_dyn::<3>(&()); +} diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs b/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs new file mode 100644 index 000000000..e7c8e4f66 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.rs @@ -0,0 +1,24 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait True {} + +struct Is; + +impl True for Is {} + +fn g() +//~^ NOTE required by a bound in this +where + Is<{ std::mem::size_of::() == 0 }>: True, + //~^ NOTE required by a bound in `g` + //~| NOTE required by this bound in `g` +{ +} + +fn main() { + g::(); + //~^ ERROR mismatched types + //~| NOTE expected `false`, found `true` + //~| NOTE expected constant `false` +} diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr new file mode 100644 index 000000000..a253ec676 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/obligation-cause.rs:20:5 + | +LL | g::(); + | ^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `g` + --> $DIR/obligation-cause.rs:13:44 + | +LL | fn g() + | - required by a bound in this +... +LL | Is<{ std::mem::size_of::() == 0 }>: True, + | ^^^^ required by this bound in `g` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/simple_fail.rs b/tests/ui/const-generics/generic_const_exprs/simple_fail.rs new file mode 100644 index 000000000..cae54df4c --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/simple_fail.rs @@ -0,0 +1,17 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +type Arr = [u8; N - 1]; +//~^ ERROR evaluation of `Arr::<0>::{constant#0}` failed + +fn test() -> Arr +where + [u8; N - 1]: Sized, + //~^ ERROR evaluation of `test::<0>::{constant#0}` failed +{ + todo!() +} + +fn main() { + test::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr b/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr new file mode 100644 index 000000000..a25fa56b7 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/simple_fail.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of `test::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:9:10 + | +LL | [u8; N - 1]: Sized, + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error[E0080]: evaluation of `Arr::<0>::{constant#0}` failed + --> $DIR/simple_fail.rs:4:33 + | +LL | type Arr = [u8; N - 1]; + | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs b/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs new file mode 100644 index 000000000..d6574a3aa --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs @@ -0,0 +1,17 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn make_array() -> [(); M + 1] { + [(); M + 1] +} + +fn foo() -> [(); (N * 2) + 1] { + make_array::<{ N * 2 }>() +} + +fn main() { + assert_eq!(foo::<10>(), [(); 10 * 2 + 1]) +} + +// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const diff --git a/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs b/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs new file mode 100644 index 000000000..d058b3638 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs @@ -0,0 +1,14 @@ +// check-pass +// Test that we correctly substitute generic arguments for type aliases. +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +type Alias = [T; N + 1]; + +fn foo() -> Alias where [u8; M + 1]: Sized { + [0; M + 1] +} + +fn main() { + foo::<0>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs new file mode 100644 index 000000000..c0404d35b --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs @@ -0,0 +1,35 @@ +#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] +#![allow(incomplete_features)] + +// test `N + N` unifies with explicit function calls for non-builtin-types +#[derive(PartialEq, Eq)] +struct Foo(u8); + +impl const std::ops::Add for Foo { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + self + } +} + +struct Evaluatable; + +fn foo(a: Evaluatable<{ N + N }>) { + bar::<{ std::ops::Add::add(N, N) }>(); +} + +fn bar() {} + +// test that `N + N` unifies with explicit function calls for builin-types +struct Evaluatable2; + +fn foo2(a: Evaluatable2<{ N + N }>) { + bar2::<{ std::ops::Add::add(N, N) }>(); + //~^ error: unconstrained generic constant + // FIXME(generic_const_exprs) make this not an error +} + +fn bar2() {} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr new file mode 100644 index 000000000..d18c7916f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:28:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/generic_const_exprs/unop.rs b/tests/ui/const-generics/generic_const_exprs/unop.rs new file mode 100644 index 000000000..c12fef083 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unop.rs @@ -0,0 +1,14 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Foo; + +fn test() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized { + Foo +} + +fn main() { + let _: Foo = test::<12>(); + let _: Foo = test::<9>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs b/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs new file mode 100644 index 000000000..9580f8a7f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs @@ -0,0 +1,6 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +struct Foo; +struct Bar(Foo); +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.rs b/tests/ui/const-generics/generic_const_exprs/unused_expr.rs new file mode 100644 index 000000000..c1bf19e0f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.rs @@ -0,0 +1,25 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn add() -> [u8; { N + 1; 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +fn div() -> [u8; { N / 1; 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +const fn foo(n: usize) {} + +fn fn_call() -> [u8; { foo(N); 5 }] { + //~^ ERROR overly complex generic constant + todo!() +} + +fn main() { + add::<12>(); + div::<9>(); + fn_call::<14>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr new file mode 100644 index 000000000..265a3b9d2 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -0,0 +1,29 @@ +error: overly complex generic constant + --> $DIR/unused_expr.rs:4:34 + | +LL | fn add() -> [u8; { N + 1; 5 }] { + | ^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/unused_expr.rs:9:34 + | +LL | fn div() -> [u8; { N / 1; 5 }] { + | ^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/unused_expr.rs:16:38 + | +LL | fn fn_call() -> [u8; { foo(N); 5 }] { + | ^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/ice-68875.rs b/tests/ui/const-generics/ice-68875.rs new file mode 100644 index 000000000..2ef7cfdbe --- /dev/null +++ b/tests/ui/const-generics/ice-68875.rs @@ -0,0 +1,11 @@ +// check-fail + +struct DataWrapper<'a> { + data: &'a [u8; Self::SIZE], //~ ERROR generic `Self` types are currently not permitted in anonymous constants +} + +impl DataWrapper<'_> { + const SIZE: usize = 14; +} + +pub fn main() {} diff --git a/tests/ui/const-generics/ice-68875.stderr b/tests/ui/const-generics/ice-68875.stderr new file mode 100644 index 000000000..1db62c57f --- /dev/null +++ b/tests/ui/const-generics/ice-68875.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/ice-68875.rs:4:20 + | +LL | data: &'a [u8; Self::SIZE], + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/ice-const-generic-function-return-ty.rs b/tests/ui/const-generics/ice-const-generic-function-return-ty.rs new file mode 100644 index 000000000..2bf628af8 --- /dev/null +++ b/tests/ui/const-generics/ice-const-generic-function-return-ty.rs @@ -0,0 +1,5 @@ +// #95163 +fn return_ty() -> impl Into<<() as Reexported; +//~^ ERROR expected one of `(`, `::`, `<`, or `>`, found `;` + +fn main() {} diff --git a/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr b/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr new file mode 100644 index 000000000..a72f5800a --- /dev/null +++ b/tests/ui/const-generics/ice-const-generic-function-return-ty.stderr @@ -0,0 +1,8 @@ +error: expected one of `(`, `::`, `<`, or `>`, found `;` + --> $DIR/ice-const-generic-function-return-ty.rs:2:46 + | +LL | fn return_ty() -> impl Into<<() as Reexported; + | ^ expected one of `(`, `::`, `<`, or `>` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/impl-const-generic-struct.rs b/tests/ui/const-generics/impl-const-generic-struct.rs new file mode 100644 index 000000000..7eb2c6a51 --- /dev/null +++ b/tests/ui/const-generics/impl-const-generic-struct.rs @@ -0,0 +1,12 @@ +// run-pass +struct S; + +impl S { + fn x() -> u32 { + X + } +} + +fn main() { + assert_eq!(S::<19>::x(), 19); +} diff --git a/tests/ui/const-generics/incorrect-number-of-const-args.rs b/tests/ui/const-generics/incorrect-number-of-const-args.rs new file mode 100644 index 000000000..8660cb2fb --- /dev/null +++ b/tests/ui/const-generics/incorrect-number-of-const-args.rs @@ -0,0 +1,11 @@ +fn foo() -> usize { + 0 +} + +fn main() { + foo::<0>(); + //~^ ERROR function takes 2 + + foo::<0, 0, 0>(); + //~^ ERROR function takes 2 +} diff --git a/tests/ui/const-generics/incorrect-number-of-const-args.stderr b/tests/ui/const-generics/incorrect-number-of-const-args.stderr new file mode 100644 index 000000000..a845454f7 --- /dev/null +++ b/tests/ui/const-generics/incorrect-number-of-const-args.stderr @@ -0,0 +1,35 @@ +error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/incorrect-number-of-const-args.rs:6:5 + | +LL | foo::<0>(); + | ^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `X`, `Y` + --> $DIR/incorrect-number-of-const-args.rs:1:4 + | +LL | fn foo() -> usize { + | ^^^ -------------- -------------- +help: add missing generic argument + | +LL | foo::<0, Y>(); + | +++ + +error[E0107]: this function takes 2 generic arguments but 3 generic arguments were supplied + --> $DIR/incorrect-number-of-const-args.rs:9:5 + | +LL | foo::<0, 0, 0>(); + | ^^^ - help: remove this generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `X`, `Y` + --> $DIR/incorrect-number-of-const-args.rs:1:4 + | +LL | fn foo() -> usize { + | ^^^ -------------- -------------- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/infer/cannot-infer-const-args.rs b/tests/ui/const-generics/infer/cannot-infer-const-args.rs new file mode 100644 index 000000000..f85a72910 --- /dev/null +++ b/tests/ui/const-generics/infer/cannot-infer-const-args.rs @@ -0,0 +1,7 @@ +fn foo() -> usize { + 0 +} + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/cannot-infer-const-args.stderr b/tests/ui/const-generics/infer/cannot-infer-const-args.stderr new file mode 100644 index 000000000..93e45a88a --- /dev/null +++ b/tests/ui/const-generics/infer/cannot-infer-const-args.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-const-args.rs:6:5 + | +LL | foo(); + | ^^^ cannot infer the value of the const parameter `X` declared on the function `foo` + | +help: consider specifying the generic argument + | +LL | foo::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/issue-77092.rs b/tests/ui/const-generics/infer/issue-77092.rs new file mode 100644 index 000000000..fcf7d3282 --- /dev/null +++ b/tests/ui/const-generics/infer/issue-77092.rs @@ -0,0 +1,14 @@ +use std::convert::TryInto; + +fn take_array_from_mut(data: &mut [T], start: usize) -> &mut [T; N] { + (&mut data[start .. start + N]).try_into().unwrap() +} + +fn main() { + let mut arr = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + + for i in 1 .. 4 { + println!("{:?}", take_array_from_mut(&mut arr, i)); + //~^ ERROR type annotations needed + } +} diff --git a/tests/ui/const-generics/infer/issue-77092.stderr b/tests/ui/const-generics/infer/issue-77092.stderr new file mode 100644 index 000000000..1682b26ac --- /dev/null +++ b/tests/ui/const-generics/infer/issue-77092.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-77092.rs:11:26 + | +LL | println!("{:?}", take_array_from_mut(&mut arr, i)); + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut` + | +help: consider specifying the generic arguments + | +LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); + | ++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/method-chain.rs b/tests/ui/const-generics/infer/method-chain.rs new file mode 100644 index 000000000..0c5eed489 --- /dev/null +++ b/tests/ui/const-generics/infer/method-chain.rs @@ -0,0 +1,16 @@ +struct Foo; + +impl Foo { + fn bar(self) -> Foo { + Foo + } + + fn baz(self) -> Foo { + println!("baz: {}", N); + Foo + } +} + +fn main() { + Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/method-chain.stderr b/tests/ui/const-generics/infer/method-chain.stderr new file mode 100644 index 000000000..ff6da535b --- /dev/null +++ b/tests/ui/const-generics/infer/method-chain.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/method-chain.rs:15:33 + | +LL | Foo.bar().bar().bar().bar().baz(); + | ^^^ cannot infer the value of the const parameter `N` declared on the associated function `baz` + | +help: consider specifying the generic argument + | +LL | Foo.bar().bar().bar().bar().baz::(); + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/one-param-uninferred.rs b/tests/ui/const-generics/infer/one-param-uninferred.rs new file mode 100644 index 000000000..d6018650f --- /dev/null +++ b/tests/ui/const-generics/infer/one-param-uninferred.rs @@ -0,0 +1,11 @@ +// Test that we emit an error if we cannot properly infer a constant. +fn foo() -> [u8; N] { + todo!() +} + +fn main() { + // FIXME(const_generics): Currently this only suggests one const parameter, + // but instead it should suggest to provide all parameters. + let _: [u8; 17] = foo(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/one-param-uninferred.stderr b/tests/ui/const-generics/infer/one-param-uninferred.stderr new file mode 100644 index 000000000..cf70c2181 --- /dev/null +++ b/tests/ui/const-generics/infer/one-param-uninferred.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/one-param-uninferred.rs:9:23 + | +LL | let _: [u8; 17] = foo(); + | ^^^ cannot infer the value of the const parameter `M` declared on the function `foo` + | +help: consider specifying the generic arguments + | +LL | let _: [u8; 17] = foo::<17, M>(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer/uninferred-consts.rs b/tests/ui/const-generics/infer/uninferred-consts.rs new file mode 100644 index 000000000..657f4b513 --- /dev/null +++ b/tests/ui/const-generics/infer/uninferred-consts.rs @@ -0,0 +1,11 @@ +// Test that we emit an error if we cannot properly infer a constant. + +// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893 +struct Foo; +impl Foo { + fn foo(self) {} +} +fn main() { + Foo.foo(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/const-generics/infer/uninferred-consts.stderr b/tests/ui/const-generics/infer/uninferred-consts.stderr new file mode 100644 index 000000000..3980ecea8 --- /dev/null +++ b/tests/ui/const-generics/infer/uninferred-consts.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/uninferred-consts.rs:9:9 + | +LL | Foo.foo(); + | ^^^ cannot infer the value of the const parameter `A` declared on the associated function `foo` + | +help: consider specifying the generic arguments + | +LL | Foo.foo::(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/infer_arg_from_pat.rs b/tests/ui/const-generics/infer_arg_from_pat.rs new file mode 100644 index 000000000..10317a1b9 --- /dev/null +++ b/tests/ui/const-generics/infer_arg_from_pat.rs @@ -0,0 +1,25 @@ +// run-pass +// +// see issue #70529 + +struct A { + arr: [u8; N], +} + +impl A { + fn new() -> Self { + A { + arr: [0; N], + } + } + + fn value(&self) -> usize { + N + } +} + +fn main() { + let a = A::new(); + let [_, _] = a.arr; + assert_eq!(a.value(), 2); +} diff --git a/tests/ui/const-generics/infer_arr_len_from_pat.rs b/tests/ui/const-generics/infer_arr_len_from_pat.rs new file mode 100644 index 000000000..40f6f5b8d --- /dev/null +++ b/tests/ui/const-generics/infer_arr_len_from_pat.rs @@ -0,0 +1,11 @@ +// check-pass +// +// see issue #70529 + +fn as_chunks() -> [u8; N] { + loop {} +} + +fn main() { + let [_, _] = as_chunks(); +} diff --git a/tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs b/tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs new file mode 100644 index 000000000..b385406b0 --- /dev/null +++ b/tests/ui/const-generics/inhabited-assoc-ty-ice-1.rs @@ -0,0 +1,28 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the inhabited check doesn't cause +// ICEs by trying to evaluate `T::ASSOC` with an incorrect `ParamEnv`. + +trait Foo { + const ASSOC: usize = 1; +} + +#[allow(unused_tuple_struct_fields)] +struct Iced(T, [(); T::ASSOC]) +where + [(); T::ASSOC]: ; + +impl Foo for u32 {} + +fn foo() +where + [(); T::ASSOC]: , +{ + let _iced: Iced = return; +} + +fn main() { + foo::(); +} diff --git a/tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs b/tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs new file mode 100644 index 000000000..216d29c7c --- /dev/null +++ b/tests/ui/const-generics/inhabited-assoc-ty-ice-2.rs @@ -0,0 +1,21 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This tests that the inhabited check doesn't cause +// ICEs by trying to evaluate `T::ASSOC` with an incorrect `ParamEnv`. + +trait Foo { + const ASSOC: usize = 1; +} + +#[allow(unused_tuple_struct_fields)] +struct Iced(T, [(); T::ASSOC]) +where + [(); T::ASSOC]: ; + +impl Foo for u32 {} + +fn main() { + let _iced: Iced = return; +} diff --git a/tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs new file mode 100644 index 000000000..2b8731ba7 --- /dev/null +++ b/tests/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs @@ -0,0 +1,18 @@ +// check-pass + +fn takes_closure_of_array_3(f: F) where F: Fn([i32; 3]) { + f([1, 2, 3]); +} + +fn takes_closure_of_array_3_apit(f: impl Fn([i32; 3])) { + f([1, 2, 3]); +} + +fn returns_closure_of_array_3() -> impl Fn([i32; 3]) { + |_| {} +} + +fn main() { + takes_closure_of_array_3(returns_closure_of_array_3()); + takes_closure_of_array_3_apit(returns_closure_of_array_3()); +} diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr new file mode 100644 index 000000000..b8a1027c9 --- /dev/null +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/intrinsics-type_name-as-const-argument.rs:15:44 + | +LL | T: Trait<{std::intrinsics::type_name::()}> + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22 + | +LL | trait Trait {} + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs new file mode 100644 index 000000000..147a00cb2 --- /dev/null +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.rs @@ -0,0 +1,21 @@ +// [full] check-pass +// revisions: full min + +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(adt_const_params, generic_const_exprs))] + +#![feature(core_intrinsics)] +#![feature(const_type_name)] + +trait Trait {} +//[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + +struct Bug +where + T: Trait<{std::intrinsics::type_name::()}> + //[min]~^ ERROR generic parameters may not be used in const operations +{ + t: T +} + +fn main() {} diff --git a/tests/ui/const-generics/invalid-const-arg-for-type-param.rs b/tests/ui/const-generics/invalid-const-arg-for-type-param.rs new file mode 100644 index 000000000..7d4dc98f3 --- /dev/null +++ b/tests/ui/const-generics/invalid-const-arg-for-type-param.rs @@ -0,0 +1,14 @@ +use std::convert::TryInto; + +struct S; + +fn main() { + let _: u32 = 5i32.try_into::<32>().unwrap(); + //~^ ERROR this associated function takes + + S.f::<0>(); + //~^ ERROR no method named `f` + + S::<0>; + //~^ ERROR this struct takes 0 +} diff --git a/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr b/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr new file mode 100644 index 000000000..8c76ca690 --- /dev/null +++ b/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr @@ -0,0 +1,43 @@ +error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/invalid-const-arg-for-type-param.rs:6:23 + | +LL | let _: u32 = 5i32.try_into::<32>().unwrap(); + | ^^^^^^^^ expected 0 generic arguments + | +help: consider moving this generic argument to the `TryInto` trait, which takes up to 1 argument + | +LL | let _: u32 = TryInto::<32>::try_into(5i32).unwrap(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: remove these generics + | +LL - let _: u32 = 5i32.try_into::<32>().unwrap(); +LL + let _: u32 = 5i32.try_into().unwrap(); + | + +error[E0599]: no method named `f` found for struct `S` in the current scope + --> $DIR/invalid-const-arg-for-type-param.rs:9:7 + | +LL | struct S; + | -------- method `f` not found for this struct +... +LL | S.f::<0>(); + | ^ method not found in `S` + +error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/invalid-const-arg-for-type-param.rs:12:5 + | +LL | S::<0>; + | ^----- help: remove these generics + | | + | expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/invalid-const-arg-for-type-param.rs:3:8 + | +LL | struct S; + | ^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0599. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/invalid-constant-in-args.rs b/tests/ui/const-generics/invalid-constant-in-args.rs new file mode 100644 index 000000000..7419d4a25 --- /dev/null +++ b/tests/ui/const-generics/invalid-constant-in-args.rs @@ -0,0 +1,6 @@ +use std::cell::Cell; + +fn main() { + let _: Cell<&str, "a"> = Cell::new(""); + //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied +} diff --git a/tests/ui/const-generics/invalid-constant-in-args.stderr b/tests/ui/const-generics/invalid-constant-in-args.stderr new file mode 100644 index 000000000..993b63518 --- /dev/null +++ b/tests/ui/const-generics/invalid-constant-in-args.stderr @@ -0,0 +1,11 @@ +error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied + --> $DIR/invalid-constant-in-args.rs:4:12 + | +LL | let _: Cell<&str, "a"> = Cell::new(""); + | ^^^^ --- help: remove this generic argument + | | + | expected 1 generic argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/invalid-enum.rs b/tests/ui/const-generics/invalid-enum.rs new file mode 100644 index 000000000..cb6d05349 --- /dev/null +++ b/tests/ui/const-generics/invalid-enum.rs @@ -0,0 +1,35 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +enum CompileFlag { + A, + B, +} + +pub fn test_1() {} +pub fn test_2(x: T) {} +pub struct Example{ + x: T, +} + +impl Example { + const ASSOC_FLAG: CompileFlag = CompileFlag::A; +} + +pub fn main() { + test_1::(); + //~^ ERROR: expected type, found variant + //~| ERROR: unresolved item provided when a constant was expected + + test_2::<_, CompileFlag::A>(0); + //~^ ERROR: expected type, found variant + //~| ERROR: unresolved item provided when a constant was expected + + let _: Example = Example { x: 0 }; + //~^ ERROR: expected type, found variant + //~| ERROR: unresolved item provided when a constant was expected + + let _: Example = Example { x: 0 }; + //~^ ERROR: type provided when a constant was expected +} diff --git a/tests/ui/const-generics/invalid-enum.stderr b/tests/ui/const-generics/invalid-enum.stderr new file mode 100644 index 000000000..0d3643f6f --- /dev/null +++ b/tests/ui/const-generics/invalid-enum.stderr @@ -0,0 +1,75 @@ +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:21:12 + | +LL | test_1::(); + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:25:15 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:29:18 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:29:18 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 }; + | + + + +error[E0747]: type provided when a constant was expected + --> $DIR/invalid-enum.rs:33:18 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 }; + | + + + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:21:12 + | +LL | test_1::(); + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | test_1::<{ CompileFlag::A }>(); + | + + + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/invalid-enum.rs:25:15 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | test_2::<_, { CompileFlag::A }>(0); + | + + + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0573, E0747. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/const-generics/invariant.rs b/tests/ui/const-generics/invariant.rs new file mode 100644 index 000000000..39d658be6 --- /dev/null +++ b/tests/ui/const-generics/invariant.rs @@ -0,0 +1,34 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +use std::marker::PhantomData; + +trait SadBee { + const ASSOC: usize; +} +// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while +// we allow two different impls for these types, leading +// to different const eval results. +impl SadBee for for<'a> fn(&'a ()) { + const ASSOC: usize = 0; +} +impl SadBee for fn(&'static ()) { + //~^ WARNING conflicting implementations of trait + //~| WARNING this was previously accepted + const ASSOC: usize = 100; +} + +struct Foo([u8; ::ASSOC], PhantomData) +where + [(); ::ASSOC]: ; + +fn covariant( + v: &'static Foo fn(&'a ())> +) -> &'static Foo { + v + //~^ ERROR mismatched types +} + +fn main() { + let y = covariant(&Foo([], PhantomData)); + println!("{:?}", y.0); +} diff --git a/tests/ui/const-generics/invariant.stderr b/tests/ui/const-generics/invariant.stderr new file mode 100644 index 000000000..aabe4c93b --- /dev/null +++ b/tests/ui/const-generics/invariant.stderr @@ -0,0 +1,26 @@ +warning: conflicting implementations of trait `SadBee` for type `for<'a> fn(&'a ())` + --> $DIR/invariant.rs:14:1 + | +LL | impl SadBee for for<'a> fn(&'a ()) { + | ---------------------------------- first implementation here +... +LL | impl SadBee for fn(&'static ()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + = note: `#[warn(coherence_leak_check)]` on by default + +error[E0308]: mismatched types + --> $DIR/invariant.rs:27:5 + | +LL | v + | ^ one type is more general than the other + | + = note: expected reference `&Foo` + found reference `&Foo fn(&'a ())>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issue-102124.rs b/tests/ui/const-generics/issue-102124.rs new file mode 100644 index 000000000..a28f198e9 --- /dev/null +++ b/tests/ui/const-generics/issue-102124.rs @@ -0,0 +1,20 @@ +// run-pass +// compile-flags: -Zmir-opt-level=3 + +// regression test for #102124 + +const L: usize = 4; + +pub trait Print { + fn print(&self) -> usize { + N + } +} + +pub struct Printer; +impl Print for Printer {} + +fn main() { + let p = Printer; + assert_eq!(p.print(), 4); +} diff --git a/tests/ui/const-generics/issue-105689.rs b/tests/ui/const-generics/issue-105689.rs new file mode 100644 index 000000000..4237b3cad --- /dev/null +++ b/tests/ui/const-generics/issue-105689.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2021 +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs b/tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs new file mode 100644 index 000000000..8363e5af4 --- /dev/null +++ b/tests/ui/const-generics/issue-106419-struct-with-multiple-const-params.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +#[derive(Clone)] +struct Bar +where + [(); A as usize]:, + [(); B as usize]:, +{} + +fn main() {} diff --git a/tests/ui/const-generics/issue-46511.rs b/tests/ui/const-generics/issue-46511.rs new file mode 100644 index 000000000..71c50e2f3 --- /dev/null +++ b/tests/ui/const-generics/issue-46511.rs @@ -0,0 +1,8 @@ +// check-fail + +struct Foo<'a> //~ ERROR parameter `'a` is never used [E0392] +{ + _a: [u8; std::mem::size_of::<&'a mut u8>()] //~ ERROR a non-static lifetime is not allowed in a `const` +} + +pub fn main() {} diff --git a/tests/ui/const-generics/issue-46511.stderr b/tests/ui/const-generics/issue-46511.stderr new file mode 100644 index 000000000..b21afa56d --- /dev/null +++ b/tests/ui/const-generics/issue-46511.stderr @@ -0,0 +1,21 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/issue-46511.rs:5:35 + | +LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0392]: parameter `'a` is never used + --> $DIR/issue-46511.rs:3:12 + | +LL | struct Foo<'a> + | ^^ unused parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0658. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issue-66451.rs b/tests/ui/const-generics/issue-66451.rs new file mode 100644 index 000000000..3335f7d59 --- /dev/null +++ b/tests/ui/const-generics/issue-66451.rs @@ -0,0 +1,28 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(Debug, PartialEq, Eq)] +struct Foo { + value: i32, + nested: &'static Bar, +} + +#[derive(Debug, PartialEq, Eq)] +struct Bar(T); + +struct Test; + +fn main() { + let x: Test<{ + Foo { + value: 3, + nested: &Bar(4), + } + }> = Test; + let y: Test<{ + Foo { + value: 3, + nested: &Bar(5), + } + }> = x; //~ ERROR mismatched types +} diff --git a/tests/ui/const-generics/issue-66451.stderr b/tests/ui/const-generics/issue-66451.stderr new file mode 100644 index 000000000..e0cb0b661 --- /dev/null +++ b/tests/ui/const-generics/issue-66451.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-66451.rs:27:10 + | +LL | let y: Test<{ + | ____________- +LL | | Foo { +LL | | value: 3, +LL | | nested: &Bar(5), +LL | | } +LL | | }> = x; + | | - ^ expected `Foo { value: 3, nested: &Bar::(5) }`, found `Foo { value: 3, nested: &Bar::(4) }` + | |______| + | expected due to this + | + = note: expected struct `Test(5) }>` + found struct `Test(4) }>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issue-70408.rs b/tests/ui/const-generics/issue-70408.rs new file mode 100644 index 000000000..f7557cb49 --- /dev/null +++ b/tests/ui/const-generics/issue-70408.rs @@ -0,0 +1,13 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub fn function_with_bytes() -> &'static [u8] { + BYTES +} + +pub fn main() { + assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::<{ &[0x41, 0x41, 0x41, 0x41] }>(), b"AAAA"); +} diff --git a/tests/ui/const-generics/issue-80471.rs b/tests/ui/const-generics/issue-80471.rs new file mode 100644 index 000000000..d0af8a5ea --- /dev/null +++ b/tests/ui/const-generics/issue-80471.rs @@ -0,0 +1,13 @@ +#![feature(adt_const_params)] +//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +#[derive(PartialEq, Eq)] +enum Nat { + Z, + S(Box), +} + +fn foo() {} +//~^ ERROR `Box` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + +fn main() {} diff --git a/tests/ui/const-generics/issue-80471.stderr b/tests/ui/const-generics/issue-80471.stderr new file mode 100644 index 000000000..b89706710 --- /dev/null +++ b/tests/ui/const-generics/issue-80471.stderr @@ -0,0 +1,18 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/issue-80471.rs:1:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0741]: `Box` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-80471.rs:10:17 + | +LL | fn foo() {} + | ^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issue-93647.rs b/tests/ui/const-generics/issue-93647.rs new file mode 100644 index 000000000..806540e17 --- /dev/null +++ b/tests/ui/const-generics/issue-93647.rs @@ -0,0 +1,6 @@ +struct X; + +fn main() {} diff --git a/tests/ui/const-generics/issue-93647.stderr b/tests/ui/const-generics/issue-93647.stderr new file mode 100644 index 000000000..18370eea5 --- /dev/null +++ b/tests/ui/const-generics/issue-93647.stderr @@ -0,0 +1,13 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/issue-93647.rs:2:5 + | +LL | (||1usize)() + | ^^^^^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/issue-97007.rs b/tests/ui/const-generics/issue-97007.rs new file mode 100644 index 000000000..7036834c4 --- /dev/null +++ b/tests/ui/const-generics/issue-97007.rs @@ -0,0 +1,88 @@ +// check-pass + +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] + +mod lib { + const N_ISLANDS: usize = 4; + const N_BRIDGES: usize = 7; + const BRIDGES: [(usize, usize); 7] = [(0, 1), (0, 1), (0, 2), (0, 3), (0, 3), (1, 2), (2, 3)]; + + pub type Matrix = [[usize; N_ISLANDS]; N_ISLANDS]; + + const EMPTY_MATRIX: Matrix = [[0; N_ISLANDS]; N_ISLANDS]; + + const fn build(mut matrix: Matrix, (to, from): (usize, usize)) -> Matrix { + matrix[to][from] += 1; + matrix[from][to] += 1; + matrix + } + + pub const fn walk(mut matrix: Matrix, from: usize, to: usize) -> Matrix { + matrix[from][to] -= 1; + matrix[to][from] -= 1; + matrix + } + + const fn to_matrix(bridges: [(usize, usize); N_BRIDGES]) -> Matrix { + let matrix = EMPTY_MATRIX; + + let matrix = build(matrix, bridges[0]); + let matrix = build(matrix, bridges[1]); + let matrix = build(matrix, bridges[2]); + let matrix = build(matrix, bridges[3]); + let matrix = build(matrix, bridges[4]); + let matrix = build(matrix, bridges[5]); + let matrix = build(matrix, bridges[6]); + + matrix + } + + const BRIDGE_MATRIX: [[usize; N_ISLANDS]; N_ISLANDS] = to_matrix(BRIDGES); + + pub struct Walk { + _p: (), + } + + impl Walk<0, BRIDGE_MATRIX> { + pub const fn new() -> Self { + Self { _p: () } + } + } + + impl Walk { + pub fn proceed_to( + self, + ) -> Walk { + Walk { _p: () } + } + } + + pub struct Trophy { + _p: (), + } + + impl Walk { + pub fn collect_prize(self) -> Trophy { + Trophy { _p: () } + } + } +} + +pub use lib::{Trophy, Walk}; + +fn main() { + // Example, taking the first step + let _ = Walk::new().proceed_to::<1>(); + + // Don't be so eager to collect the trophy + // let trophy = Walk::new() + // .proceed_to::<1>() + // .proceed_to::<0>() + // .collect_prize(); + + // Can't just make a Trophy out of thin air, you must earn it + // let trophy: Trophy = Trophy { _p: () }; + + // Can you collect the Trophy? +} diff --git a/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs new file mode 100644 index 000000000..6a10ee267 --- /dev/null +++ b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs @@ -0,0 +1,15 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// All of these three items must be in `lib2` to reproduce the error + +pub trait TypeFn { + type Output; +} + +pub struct GenericType; + +// Removing the braces around `42` resolves the crash +impl TypeFn for GenericType<{ 40 + 2 }> { + type Output = (); +} diff --git a/tests/ui/const-generics/issues/auxiliary/impl-const.rs b/tests/ui/const-generics/issues/auxiliary/impl-const.rs new file mode 100644 index 000000000..de3a40860 --- /dev/null +++ b/tests/ui/const-generics/issues/auxiliary/impl-const.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] + +pub struct Num; + +// Braces around const expression causes crash +impl Num<{5}> { + pub fn five(&self) { + } +} diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs new file mode 100644 index 000000000..4e9d3626a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-100313.rs @@ -0,0 +1,21 @@ +#![allow(incomplete_features)] +#![feature(const_mut_refs)] +#![feature(adt_const_params)] + +struct T; + +impl T { + const fn set_false(&self) { + unsafe { + *(B as *const bool as *mut bool) = false; + //~^ ERROR evaluation of constant value failed [E0080] + } + } +} + +const _: () = { + let x = T::<{&true}>; + x.set_false(); +}; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr new file mode 100644 index 000000000..d4b486376 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-100313.stderr @@ -0,0 +1,20 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-100313.rs:10:13 + | +LL | *(B as *const bool as *mut bool) = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only + | +note: inside `T::<&true>::set_false` + --> $DIR/issue-100313.rs:10:13 + | +LL | *(B as *const bool as *mut bool) = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: inside `_` + --> $DIR/issue-100313.rs:18:5 + | +LL | x.set_false(); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/issues/issue-105037.rs b/tests/ui/const-generics/issues/issue-105037.rs new file mode 100644 index 000000000..f7d239499 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-105037.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +#![allow(dead_code)] + +trait Table: Sync { + const COLUMNS: usize; +} + +struct Table1; +impl Table for Table1 { + const COLUMNS: usize = 123; +} + +struct Table2; +impl Table for Table2 { + const COLUMNS: usize = 456; +} + +fn process_table, const D: usize>(_table: T) +where + [(); T::COLUMNS]:, +{ +} + +fn process_all_tables() +where + [(); Table2::::COLUMNS]:, + [(); Table1::::COLUMNS]:, +{ + process_table(Table1::); + process_table(Table2::); +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-56445-1.full.stderr b/tests/ui/const-generics/issues/issue-56445-1.full.stderr new file mode 100644 index 000000000..179643a75 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-1.full.stderr @@ -0,0 +1,11 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/issue-56445-1.rs:9:26 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^ + | + = note: for more information, see issue #74052 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr new file mode 100644 index 000000000..43a5df117 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr @@ -0,0 +1,20 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/issue-56445-1.rs:9:26 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^ + | + = note: for more information, see issue #74052 + +error: `&'static str` is forbidden as the type of a const generic parameter + --> $DIR/issue-56445-1.rs:9:25 + | +LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/const-generics/issues/issue-56445-1.rs b/tests/ui/const-generics/issues/issue-56445-1.rs new file mode 100644 index 000000000..13eb2ea9f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-1.rs @@ -0,0 +1,13 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995. +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] +#![crate_type = "lib"] + +use std::marker::PhantomData; + +struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); +//~^ ERROR: use of non-static lifetime `'a` in const generic +//[min]~| ERROR: `&'static str` is forbidden as the type of a const generic parameter + +impl Bug<'_, ""> {} diff --git a/tests/ui/const-generics/issues/issue-56445-2.rs b/tests/ui/const-generics/issues/issue-56445-2.rs new file mode 100644 index 000000000..e078c8487 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-2.rs @@ -0,0 +1,11 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-502095133 +struct OnDiskDirEntry<'a> { _s: &'a usize } + +impl<'a> OnDiskDirEntry<'a> { + const LFN_FRAGMENT_LEN: usize = 2; + + fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } } + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-56445-2.stderr b/tests/ui/const-generics/issues/issue-56445-2.stderr new file mode 100644 index 000000000..770c80cbb --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-2.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-56445-2.rs:7:38 + | +LL | fn lfn_contents(&self) -> [char; Self::LFN_FRAGMENT_LEN] { loop { } } + | ^^^^ + | +note: not a concrete type + --> $DIR/issue-56445-2.rs:4:10 + | +LL | impl<'a> OnDiskDirEntry<'a> { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-56445-3.rs b/tests/ui/const-generics/issues/issue-56445-3.rs new file mode 100644 index 000000000..c29df1458 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-3.rs @@ -0,0 +1,12 @@ +// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-524494170 +pub struct Memory<'rom> { + rom: &'rom [u8], + ram: [u8; Self::SIZE], + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants +} + +impl<'rom> Memory<'rom> { + pub const SIZE: usize = 0x8000; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-56445-3.stderr b/tests/ui/const-generics/issues/issue-56445-3.stderr new file mode 100644 index 000000000..f1c49eecf --- /dev/null +++ b/tests/ui/const-generics/issues/issue-56445-3.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-56445-3.rs:4:15 + | +LL | ram: [u8; Self::SIZE], + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-60818-struct-constructors.rs b/tests/ui/const-generics/issues/issue-60818-struct-constructors.rs new file mode 100644 index 000000000..0066490df --- /dev/null +++ b/tests/ui/const-generics/issues/issue-60818-struct-constructors.rs @@ -0,0 +1,7 @@ +// check-pass + +struct Generic; + +fn main() { + let _ = Generic::<0>; +} diff --git a/tests/ui/const-generics/issues/issue-61336-1.rs b/tests/ui/const-generics/issues/issue-61336-1.rs new file mode 100644 index 000000000..beb37e63b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336-1.rs @@ -0,0 +1,9 @@ +// build-pass +fn f(x: T) -> [T; N] { + [x; N] +} + +fn main() { + let x: [u32; 5] = f::(3); + assert_eq!(x, [3u32; 5]); +} diff --git a/tests/ui/const-generics/issues/issue-61336-2.rs b/tests/ui/const-generics/issues/issue-61336-2.rs new file mode 100644 index 000000000..b7cd29f89 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336-2.rs @@ -0,0 +1,13 @@ +fn f(x: T) -> [T; N] { + [x; { N }] +} + +fn g(x: T) -> [T; N] { + [x; { N }] + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() { + let x: [u32; 5] = f::(3); + assert_eq!(x, [3u32; 5]); +} diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr new file mode 100644 index 000000000..5bb356696 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-61336-2.rs:6:6 + | +LL | [x; { N }] + | ^ the trait `Copy` is not implemented for `T` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider restricting type parameter `T` + | +LL | fn g(x: T) -> [T; N] { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-61336.rs b/tests/ui/const-generics/issues/issue-61336.rs new file mode 100644 index 000000000..80be1d8e5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336.rs @@ -0,0 +1,13 @@ +fn f(x: T) -> [T; N] { + [x; N] +} + +fn g(x: T) -> [T; N] { + [x; N] + //~^ ERROR the trait bound `T: Copy` is not satisfied +} + +fn main() { + let x: [u32; 5] = f::(3); + assert_eq!(x, [3u32; 5]); +} diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr new file mode 100644 index 000000000..8d9e545b4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61336.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `T: Copy` is not satisfied + --> $DIR/issue-61336.rs:6:6 + | +LL | [x; N] + | ^ the trait `Copy` is not implemented for `T` + | + = note: the `Copy` trait is required because this value will be copied for each element of the array +help: consider restricting type parameter `T` + | +LL | fn g(x: T) -> [T; N] { + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-61422.rs b/tests/ui/const-generics/issues/issue-61422.rs new file mode 100644 index 000000000..0b9cf40d8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61422.rs @@ -0,0 +1,24 @@ +// check-pass +use std::mem; + +// Neither of the uninits below are currently accepted as not UB, however, +// this code does not run and is merely checking that we do not ICE on this pattern, +// so this is fine. + +fn foo() { + let arr: [u8; SIZE] = unsafe { + #[allow(deprecated)] + let array: [u8; SIZE] = mem::uninitialized(); + array + }; +} + +fn bar() { + let arr: [u8; SIZE] = unsafe { + let array: [u8; SIZE] = mem::MaybeUninit::uninit().assume_init(); + array + }; +} + + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-61432.rs b/tests/ui/const-generics/issues/issue-61432.rs new file mode 100644 index 000000000..6192af82a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-61432.rs @@ -0,0 +1,9 @@ +// run-pass + +fn promote() { + let _ = &N; +} + +fn main() { + promote::<0>(); +} diff --git a/tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs new file mode 100644 index 000000000..fa76aeae9 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -0,0 +1,12 @@ +// run-pass +pub trait BitLen: Sized { + const BIT_LEN: usize; +} + +impl BitLen for [u8; L] { + const BIT_LEN: usize = 8 * L; +} + +fn main() { + let _foo = <[u8; 2]>::BIT_LEN; +} diff --git a/tests/ui/const-generics/issues/issue-62878.full.stderr b/tests/ui/const-generics/issues/issue-62878.full.stderr new file mode 100644 index 000000000..3a2b291d7 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62878.full.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-62878.rs:5:38 + | +LL | fn foo() {} + | ^ the type must not depend on the parameter `N` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr new file mode 100644 index 000000000..5a721720d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -0,0 +1,18 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-62878.rs:5:38 + | +LL | fn foo() {} + | ^ the type must not depend on the parameter `N` + +error: `[u8; N]` is forbidden as the type of a const generic parameter + --> $DIR/issue-62878.rs:5:33 + | +LL | fn foo() {} + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-62878.rs b/tests/ui/const-generics/issues/issue-62878.rs new file mode 100644 index 000000000..4c08a484e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-62878.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params, generic_arg_infer))] +#![cfg_attr(full, allow(incomplete_features))] + +fn foo() {} +//~^ ERROR the type of const parameters must not +//[min]~| ERROR `[u8; N]` is forbidden as the type of a const generic parameter + +fn main() { + foo::<_, { [1] }>(); +} diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr new file mode 100644 index 000000000..16fabd1e8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: `(dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-63322-forbid-dyn.rs:9:18 + | +LL | fn test() { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr new file mode 100644 index 000000000..9f6c7ccf3 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -0,0 +1,11 @@ +error: `&'static (dyn A + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/issue-63322-forbid-dyn.rs:9:18 + | +LL | fn test() { + | ^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs new file mode 100644 index 000000000..116c3fcfb --- /dev/null +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.rs @@ -0,0 +1,17 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +trait A {} +struct B; +impl A for B {} + +fn test() { + //[full]~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` to be used + //[min]~^^ ERROR `&'static (dyn A + 'static)` is forbidden + unimplemented!() +} + +fn main() { + test::<{ &B }>(); +} diff --git a/tests/ui/const-generics/issues/issue-64519.rs b/tests/ui/const-generics/issues/issue-64519.rs new file mode 100644 index 000000000..969289b26 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-64519.rs @@ -0,0 +1,17 @@ +// check-pass +struct Foo { + state: Option<[u8; D]>, +} + +impl Iterator for Foo<{D}> { + type Item = [u8; D]; + fn next(&mut self) -> Option { + if true { + return Some(self.state.unwrap().clone()); + } else { + return Some(self.state.unwrap().clone()); + } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs b/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs new file mode 100644 index 000000000..091419f0c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs @@ -0,0 +1,16 @@ +// check-pass +#![feature(adt_const_params)] +#![allow(incomplete_features)] + + +trait Trait { + type Assoc; +} + +impl Trait<"0"> for () { + type Assoc = (); +} + +fn main() { + let _: <() as Trait<"0">>::Assoc = (); +} diff --git a/tests/ui/const-generics/issues/issue-66906.rs b/tests/ui/const-generics/issues/issue-66906.rs new file mode 100644 index 000000000..a0b3f9122 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-66906.rs @@ -0,0 +1,9 @@ +// check-pass + +pub struct Tuple; + +pub trait Trait { + type Input: From<>::Input>; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67185-1.rs b/tests/ui/const-generics/issues/issue-67185-1.rs new file mode 100644 index 000000000..69425b25e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67185-1.rs @@ -0,0 +1,29 @@ +// check-pass + +trait Baz { + type Quaks; +} +impl Baz for u8 { + type Quaks = [u16; 3]; +} + +trait Bar {} +impl Bar for [u16; 3] {} +impl Bar for [[u16; 3]; 2] {} + +trait Foo + where + [::Quaks; 2]: Bar, + ::Quaks: Bar, +{ +} + +struct FooImpl; + +impl Foo for FooImpl {} + +fn f(_: impl Foo) {} + +fn main() { + f(FooImpl) +} diff --git a/tests/ui/const-generics/issues/issue-67185-2.rs b/tests/ui/const-generics/issues/issue-67185-2.rs new file mode 100644 index 000000000..18bb6f6bc --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67185-2.rs @@ -0,0 +1,31 @@ +trait Baz { + type Quaks; +} +impl Baz for u8 { + type Quaks = [u16; 3]; +} + +trait Bar {} +impl Bar for [u16; 4] {} +impl Bar for [[u16; 3]; 3] {} + +trait Foo +where + [::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + ::Quaks: Bar, //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +{ +} + +struct FooImpl; + +impl Foo for FooImpl {} +//~^ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +//~^^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + +fn f(_: impl Foo) {} +//~^ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] +//~^^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + +fn main() { + f(FooImpl) +} diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr new file mode 100644 index 000000000..c7be8e14a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -0,0 +1,99 @@ +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:15:5 + | +LL | ::Quaks: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:14:5 + | +LL | [::Quaks; 2]: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:21:6 + | +LL | impl Foo for FooImpl {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:15:25 + | +LL | trait Foo + | --- required by a bound in this +... +LL | ::Quaks: Bar, + | ^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:21:6 + | +LL | impl Foo for FooImpl {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:14:30 + | +LL | trait Foo + | --- required by a bound in this +LL | where +LL | [::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:25:14 + | +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:14:30 + | +LL | trait Foo + | --- required by a bound in this +LL | where +LL | [::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` + +error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied + --> $DIR/issue-67185-2.rs:25:14 + | +LL | fn f(_: impl Foo) {} + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | + = help: the following other types implement trait `Bar`: + [[u16; 3]; 3] + [u16; 4] +note: required by a bound in `Foo` + --> $DIR/issue-67185-2.rs:15:25 + | +LL | trait Foo + | --- required by a bound in this +... +LL | ::Quaks: Bar, + | ^^^ required by this bound in `Foo` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-67375.full.stderr b/tests/ui/const-generics/issues/issue-67375.full.stderr new file mode 100644 index 000000000..0cf69879a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67375.full.stderr @@ -0,0 +1,12 @@ +error: overly complex generic constant + --> $DIR/issue-67375.rs:7:17 + | +LL | inner: [(); { [|_: &T| {}; 0].len() }], + | ^^---------------------^^ + | | + | pointer casts are not allowed in generic constants + | + = help: consider moving this anonymous constant into a `const` function + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67375.min.stderr b/tests/ui/const-generics/issues/issue-67375.min.stderr new file mode 100644 index 000000000..5256d96c8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67375.min.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67375.rs:7:25 + | +LL | inner: [(); { [|_: &T| {}; 0].len() }], + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `T` is never used + --> $DIR/issue-67375.rs:5:12 + | +LL | struct Bug { + | ^ unused parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67375.rs b/tests/ui/const-generics/issues/issue-67375.rs new file mode 100644 index 000000000..8b4b276ba --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67375.rs @@ -0,0 +1,12 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(generic_const_exprs))] + +struct Bug { + //[min]~^ ERROR parameter `T` is never used + inner: [(); { [|_: &T| {}; 0].len() }], + //[min]~^ ERROR generic parameters may not be used in const operations + //[full]~^^ ERROR overly complex generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67739.full.stderr b/tests/ui/const-generics/issues/issue-67739.full.stderr new file mode 100644 index 000000000..f1a426c3c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67739.full.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-67739.rs:11:15 + | +LL | [0u8; mem::size_of::()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); mem::size_of::()]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67739.min.stderr b/tests/ui/const-generics/issues/issue-67739.min.stderr new file mode 100644 index 000000000..dcbe5b94a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67739.min.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/issue-67739.rs:11:15 + | +LL | [0u8; mem::size_of::()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67739.rs b/tests/ui/const-generics/issues/issue-67739.rs new file mode 100644 index 000000000..de0eb7f50 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67739.rs @@ -0,0 +1,18 @@ +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +use std::mem; + +pub trait Trait { + type Associated: Sized; + + fn associated_size(&self) -> usize { + [0u8; mem::size_of::()]; + //[min]~^ ERROR constant expression depends on a generic parameter + //[full]~^^ ERROR unconstrained generic constant + 0 + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr new file mode 100644 index 000000000..8e18fcdff --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-67945-1.rs:10:20 + | +LL | struct Bug { + | - this type parameter +... +LL | let x: S = MaybeUninit::uninit(); + | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit` + | | + | expected due to this + | + = note: expected type parameter `S` + found union `MaybeUninit<_>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-67945-1.min.stderr b/tests/ui/const-generics/issues/issue-67945-1.min.stderr new file mode 100644 index 000000000..eee04eb75 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-1.min.stderr @@ -0,0 +1,30 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-1.rs:10:16 + | +LL | let x: S = MaybeUninit::uninit(); + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-1.rs:13:45 + | +LL | let b = &*(&x as *const _ as *const S); + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-1.rs:7:12 + | +LL | struct Bug { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67945-1.rs b/tests/ui/const-generics/issues/issue-67945-1.rs new file mode 100644 index 000000000..99f88bc8e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-1.rs @@ -0,0 +1,19 @@ +// revisions: full min +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(generic_const_exprs))] + +use std::mem::MaybeUninit; + +struct Bug { + //[min]~^ ERROR parameter `S` is never used + A: [(); { + let x: S = MaybeUninit::uninit(); + //[min]~^ ERROR generic parameters may not be used in const operations + //[full]~^^ ERROR mismatched types + let b = &*(&x as *const _ as *const S); + //[min]~^ ERROR generic parameters may not be used in const operations + 0 + }], +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-2.full.stderr b/tests/ui/const-generics/issues/issue-67945-2.full.stderr new file mode 100644 index 000000000..47429b761 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-2.full.stderr @@ -0,0 +1,17 @@ +error: overly complex generic constant + --> $DIR/issue-67945-2.rs:7:13 + | +LL | A: [(); { + | _____________^ +LL | | +LL | | let x: Option> = None; +LL | | +LL | | 0 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-2.min.stderr b/tests/ui/const-generics/issues/issue-67945-2.min.stderr new file mode 100644 index 000000000..6e07af1e6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-2.min.stderr @@ -0,0 +1,8 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-67945-2.rs:9:27 + | +LL | let x: Option> = None; + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-2.rs b/tests/ui/const-generics/issues/issue-67945-2.rs new file mode 100644 index 000000000..cbb4e14ec --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-2.rs @@ -0,0 +1,16 @@ +// revisions: full min + +#![cfg_attr(full, allow(incomplete_features))] +#![cfg_attr(full, feature(generic_const_exprs))] + +struct Bug { + A: [(); { + //[full]~^ ERROR overly complex generic constant + let x: Option> = None; + //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants + 0 + }], + B: S +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-3.full.stderr b/tests/ui/const-generics/issues/issue-67945-3.full.stderr new file mode 100644 index 000000000..98f9f8397 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-3.full.stderr @@ -0,0 +1,16 @@ +error: overly complex generic constant + --> $DIR/issue-67945-3.rs:10:13 + | +LL | A: [(); { + | _____________^ +LL | | let x: Option = None; +LL | | +LL | | 0 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-3.min.stderr b/tests/ui/const-generics/issues/issue-67945-3.min.stderr new file mode 100644 index 000000000..8e6b4b204 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-3.min.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-3.rs:11:23 + | +LL | let x: Option = None; + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-3.rs:9:12 + | +LL | struct Bug { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67945-3.rs b/tests/ui/const-generics/issues/issue-67945-3.rs new file mode 100644 index 000000000..fd8a393ef --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-3.rs @@ -0,0 +1,17 @@ +// Regression test for +// https://github.com/rust-lang/rust/issues/67945#issuecomment-572617285 +// Make sure we don't emit an E0277 error. + +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Bug { //[min]~ ERROR: parameter `S` is never used + A: [(); { //[full]~ ERROR: overly complex generic constant + let x: Option = None; + //[min]~^ ERROR: generic parameters may not be used in const operations + 0 + }], +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-67945-4.full.stderr b/tests/ui/const-generics/issues/issue-67945-4.full.stderr new file mode 100644 index 000000000..c03d40a7b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-4.full.stderr @@ -0,0 +1,16 @@ +error: overly complex generic constant + --> $DIR/issue-67945-4.rs:9:13 + | +LL | A: [(); { + | _____________^ +LL | | let x: Option> = None; +LL | | +LL | | 0 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-67945-4.min.stderr b/tests/ui/const-generics/issues/issue-67945-4.min.stderr new file mode 100644 index 000000000..f9520872d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-4.min.stderr @@ -0,0 +1,21 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-67945-4.rs:10:27 + | +LL | let x: Option> = None; + | ^ cannot perform const operation using `S` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0392]: parameter `S` is never used + --> $DIR/issue-67945-4.rs:8:12 + | +LL | struct Bug { + | ^ unused parameter + | + = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `S` to be a const parameter, use `const S: usize` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/issues/issue-67945-4.rs b/tests/ui/const-generics/issues/issue-67945-4.rs new file mode 100644 index 000000000..9a27bf09f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-67945-4.rs @@ -0,0 +1,16 @@ +// Regression test for +// https://github.com/rust-lang/rust/issues/67945#issuecomment-572617285 + +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Bug { //[min]~ ERROR: parameter `S` is never used + A: [(); { //[full]~ ERROR: overly complex generic constant + let x: Option> = None; + //[min]~^ ERROR: generic parameters may not be used in const operations + 0 + }], +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs b/tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs new file mode 100644 index 000000000..ad5710baa --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68104-print-stack-overflow.rs @@ -0,0 +1,13 @@ +// aux-build:impl-const.rs +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate impl_const; + +use impl_const::*; + +pub fn main() { + let n = Num::<5>; + n.five(); +} diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr new file mode 100644 index 000000000..ca9eb801d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68366.full.stderr @@ -0,0 +1,21 @@ +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:11:7 + | +LL | impl Collatz<{Some(N)}> {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:17:6 + | +LL | impl Foo {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr new file mode 100644 index 000000000..3740ced90 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -0,0 +1,30 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-68366.rs:11:37 + | +LL | impl Collatz<{Some(N)}> {} + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:11:7 + | +LL | impl Collatz<{Some(N)}> {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/issue-68366.rs:17:6 + | +LL | impl Foo {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/issues/issue-68366.rs b/tests/ui/const-generics/issues/issue-68366.rs new file mode 100644 index 000000000..4c2741ab4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68366.rs @@ -0,0 +1,20 @@ +// Checks that const expressions have a useful note explaining why they can't be evaluated. +// The note should relate to the fact that it cannot be shown forall N that it maps 1-1 to a new +// type. + +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Collatz>; + +impl Collatz<{Some(N)}> {} +//~^ ERROR the const parameter +//[min]~^^ generic parameters may not be used in const operations + +struct Foo; + +impl Foo {} +//~^ ERROR the const parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-68596.rs b/tests/ui/const-generics/issues/issue-68596.rs new file mode 100644 index 000000000..c3c9141e4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68596.rs @@ -0,0 +1,15 @@ +// check-pass +pub struct S(u8); + +impl S { + pub fn get(&self) -> &u8 { + &self.0 + } +} + +fn main() { + const A: u8 = 5; + let s = S(0); + + s.get::(); +} diff --git a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr new file mode 100644 index 000000000..df04c4896 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -0,0 +1,11 @@ +error: `[usize; 0]` is forbidden as the type of a const generic parameter + --> $DIR/issue-68615-adt.rs:6:23 + | +LL | struct Const {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-68615-adt.rs b/tests/ui/const-generics/issues/issue-68615-adt.rs new file mode 100644 index 000000000..3ef1ad45e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-adt.rs @@ -0,0 +1,13 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Const {} +//[min]~^ ERROR `[usize; 0]` is forbidden as the type of a const generic parameter +type MyConst = Const<{ [] }>; + +fn main() { + let _x = Const::<{ [] }> {}; + let _y = MyConst {}; +} diff --git a/tests/ui/const-generics/issues/issue-68615-array.min.stderr b/tests/ui/const-generics/issues/issue-68615-array.min.stderr new file mode 100644 index 000000000..1b4517087 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-array.min.stderr @@ -0,0 +1,11 @@ +error: `[usize; 0]` is forbidden as the type of a const generic parameter + --> $DIR/issue-68615-array.rs:6:21 + | +LL | struct Foo {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-68615-array.rs b/tests/ui/const-generics/issues/issue-68615-array.rs new file mode 100644 index 000000000..93477be41 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-68615-array.rs @@ -0,0 +1,13 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo {} +//[min]~^ ERROR `[usize; 0]` is forbidden as the type of a const generic parameter + +type MyFoo = Foo<{ [] }>; + +fn main() { + let _ = Foo::<{ [] }> {}; +} diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.rs b/tests/ui/const-generics/issues/issue-69654-run-pass.rs new file mode 100644 index 000000000..63d7fde78 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.rs @@ -0,0 +1,15 @@ +// run-pass +trait Bar {} +impl Bar for [u8; 7] {} + +struct Foo {} +impl Foo +where + [u8; N]: Bar<[(); N]>, +{ + fn foo() {} +} + +fn main() { + Foo::foo(); +} diff --git a/tests/ui/const-generics/issues/issue-70125-1.rs b/tests/ui/const-generics/issues/issue-70125-1.rs new file mode 100644 index 000000000..0027cd46a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70125-1.rs @@ -0,0 +1,17 @@ +// run-pass + +const L: usize = 4; + +pub trait Print { + fn print(&self) -> usize { + N + } +} + +pub struct Printer; +impl Print for Printer {} + +fn main() { + let p = Printer; + assert_eq!(p.print(), 4); +} diff --git a/tests/ui/const-generics/issues/issue-70125-2.rs b/tests/ui/const-generics/issues/issue-70125-2.rs new file mode 100644 index 000000000..cfd5e784e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70125-2.rs @@ -0,0 +1,12 @@ +// run-pass +fn main() { + <()>::foo(); +} + +trait Foo { + fn foo() -> usize { + X + } +} + +impl Foo<3> for () {} diff --git a/tests/ui/const-generics/issues/issue-70167.rs b/tests/ui/const-generics/issues/issue-70167.rs new file mode 100644 index 000000000..3961941f8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70167.rs @@ -0,0 +1,6 @@ +// check-pass +pub trait Trait: From<>::Item> { + type Item; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs b/tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs new file mode 100644 index 000000000..2ec37cc3a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70180-1-stalled_on.rs @@ -0,0 +1,33 @@ +// build-pass + +pub fn works() { + let array/*: [_; _]*/ = default_array(); + let _: [_; 4] = array; + Foo::foo(&array); +} + +pub fn didnt_work() { + let array/*: [_; _]*/ = default_array(); + Foo::foo(&array); + let _: [_; 4] = array; +} + +trait Foo { + fn foo(&self) {} +} + +impl Foo for [i32; 4] {} +impl Foo for [i64; 8] {} + +// Only needed because `[_; _]` is not valid type syntax. +fn default_array() -> [T; N] +where + [T; N]: Default, +{ + Default::default() +} + +fn main() { + works(); + didnt_work(); +} diff --git a/tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs b/tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs new file mode 100644 index 000000000..95e548428 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70180-2-stalled_on.rs @@ -0,0 +1,33 @@ +// build-pass + +fn works() { + let array/*: [u8; _]*/ = default_byte_array(); + let _: [_; 4] = array; + Foo::foo(&array); +} + +fn didnt_work() { + let array/*: [u8; _]*/ = default_byte_array(); + Foo::foo(&array); + let _: [_; 4] = array; +} + +trait Foo { + fn foo(&self) {} +} + +impl Foo for [u8; 4] {} +impl Foo for [u8; 8] {} + +// Only needed because `[u8; _]` is not valid type syntax. +fn default_byte_array() -> [u8; N] +where + [u8; N]: Default, +{ + Default::default() +} + +fn main() { + works(); + didnt_work(); +} diff --git a/tests/ui/const-generics/issues/issue-70225.rs b/tests/ui/const-generics/issues/issue-70225.rs new file mode 100644 index 000000000..d458d7b2e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70225.rs @@ -0,0 +1,19 @@ +// check-pass +#![deny(dead_code)] + +// We previously incorrectly linted `L` as unused here. +const L: usize = 3; + +fn main() { + let p = Printer {}; + p.print(); +} + +trait Print { + fn print(&self) -> usize { + 3 + } +} + +struct Printer {} +impl Print for Printer {} diff --git a/tests/ui/const-generics/issues/issue-70273-assoc-fn.rs b/tests/ui/const-generics/issues/issue-70273-assoc-fn.rs new file mode 100644 index 000000000..a76488249 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-70273-assoc-fn.rs @@ -0,0 +1,14 @@ +// check-pass + +trait T { + fn f(); +} +struct S; + +impl T<0usize> for S { + fn f() {} +} + +fn main() { + let _err = >::f(); +} diff --git a/tests/ui/const-generics/issues/issue-71169.full.stderr b/tests/ui/const-generics/issues/issue-71169.full.stderr new file mode 100644 index 000000000..1f5880f36 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71169.full.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71169.rs:5:43 + | +LL | fn foo() {} + | ^^^ the type must not depend on the parameter `LEN` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71169.min.stderr b/tests/ui/const-generics/issues/issue-71169.min.stderr new file mode 100644 index 000000000..998b16a79 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71169.min.stderr @@ -0,0 +1,18 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71169.rs:5:43 + | +LL | fn foo() {} + | ^^^ the type must not depend on the parameter `LEN` + +error: `[u8; LEN]` is forbidden as the type of a const generic parameter + --> $DIR/issue-71169.rs:5:38 + | +LL | fn foo() {} + | ^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71169.rs b/tests/ui/const-generics/issues/issue-71169.rs new file mode 100644 index 000000000..e4ec6b073 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71169.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn foo() {} +//~^ ERROR the type of const parameters must not +//[min]~^^ ERROR `[u8; LEN]` is forbidden as the type of a const generic parameter +fn main() { + const DATA: [u8; 4] = *b"ABCD"; + foo::<4, DATA>(); +} diff --git a/tests/ui/const-generics/issues/issue-71202.rs b/tests/ui/const-generics/issues/issue-71202.rs new file mode 100644 index 000000000..57fd72b12 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71202.rs @@ -0,0 +1,31 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features, const_evaluatable_unchecked)] + +use std::marker::PhantomData; + +struct DataHolder { + item: T, +} + +impl DataHolder { + const ITEM_IS_COPY: [(); 1 - { //~ ERROR unconstrained generic constant + trait NotCopy { + const VALUE: bool = false; + } + + impl<__Type: ?Sized> NotCopy for __Type {} + + struct IsCopy<__Type: ?Sized>(PhantomData<__Type>); + + impl<__Type> IsCopy<__Type> + where + __Type: Sized + Copy, + { + const VALUE: bool = true; + } + + >::VALUE + } as usize] = []; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr new file mode 100644 index 000000000..277540610 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71202.stderr @@ -0,0 +1,33 @@ +error: unconstrained generic constant + --> $DIR/issue-71202.rs:11:5 + | +LL | / const ITEM_IS_COPY: [(); 1 - { +LL | | trait NotCopy { +LL | | const VALUE: bool = false; +LL | | } +... | +LL | | >::VALUE +LL | | } as usize] = []; + | |_____________________^ + | + = help: try adding a `where` bound using this expression: `where [(); 1 - { + trait NotCopy { + const VALUE: bool = false; + } + + impl<__Type: ?Sized> NotCopy for __Type {} + + struct IsCopy<__Type: ?Sized>(PhantomData<__Type>); + + impl<__Type> IsCopy<__Type> + where + __Type: Sized + Copy, + { + const VALUE: bool = true; + } + + >::VALUE + } as usize]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr new file mode 100644 index 000000000..e17cf96aa --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71381.full.stderr @@ -0,0 +1,28 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:14:82 + | +LL | pub fn call_me(&self) { + | ^^^^ the type must not depend on the parameter `Args` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:23:40 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^ the type must not depend on the parameter `Args` + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:14:61 + | +LL | pub fn call_me(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:23:19 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0741, E0770. +For more information about an error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr new file mode 100644 index 000000000..3950317b3 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -0,0 +1,27 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:14:82 + | +LL | pub fn call_me(&self) { + | ^^^^ the type must not depend on the parameter `Args` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71381.rs:23:40 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^ the type must not depend on the parameter `Args` + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:14:61 + | +LL | pub fn call_me(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:23:19 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs new file mode 100644 index 000000000..66f819dbe --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71381.rs @@ -0,0 +1,36 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Test(*const usize); + +type PassArg = (); + +unsafe extern "C" fn pass(args: PassArg) { + println!("Hello, world!"); +} + +impl Test { + pub fn call_me(&self) { + //~^ ERROR: using function pointers as const generic parameters is forbidden + //~| ERROR: the type of const parameters must not depend on other generic parameters + self.0 = Self::trampiline:: as _ + } + + unsafe extern "C" fn trampiline< + Args: Sized, + const IDX: usize, + const FN: unsafe extern "C" fn(Args), + //~^ ERROR: using function pointers as const generic parameters is forbidden + //~| ERROR: the type of const parameters must not depend on other generic parameters + >( + args: Args, + ) { + FN(args) + } +} + +fn main() { + let x = Test(); + x.call_me::() +} diff --git a/tests/ui/const-generics/issues/issue-71382.full.stderr b/tests/ui/const-generics/issues/issue-71382.full.stderr new file mode 100644 index 000000000..ab2a4e64a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71382.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71382.rs:16:23 + | +LL | fn test(&self) { + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71382.min.stderr b/tests/ui/const-generics/issues/issue-71382.min.stderr new file mode 100644 index 000000000..715037bd5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71382.min.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71382.rs:16:23 + | +LL | fn test(&self) { + | ^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-71382.rs b/tests/ui/const-generics/issues/issue-71382.rs new file mode 100644 index 000000000..4392d72e5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71382.rs @@ -0,0 +1,25 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Test(); + +fn pass() { + println!("Hello, world!"); +} + +impl Test { + pub fn call_me(&self) { + self.test::(); + } + + fn test(&self) { + //~^ ERROR: using function pointers as const generic parameters is forbidden + FN(); + } +} + +fn main() { + let x = Test(); + x.call_me() +} diff --git a/tests/ui/const-generics/issues/issue-71547.rs b/tests/ui/const-generics/issues/issue-71547.rs new file mode 100644 index 000000000..60776a1a9 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71547.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +pub trait GetType { + type Ty; + fn get(&self) -> &Self::Ty; +} + +pub fn get_val(value: &T) -> &T::Ty +where + T: GetType<"hello">, +{ + value.get() +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71611.full.stderr b/tests/ui/const-generics/issues/issue-71611.full.stderr new file mode 100644 index 000000000..656aa29e1 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71611.full.stderr @@ -0,0 +1,16 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71611.rs:5:31 + | +LL | fn func(outer: A) { + | ^ the type must not depend on the parameter `A` + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71611.rs:5:21 + | +LL | fn func(outer: A) { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0741, E0770. +For more information about an error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr new file mode 100644 index 000000000..01a85b745 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-71611.rs:5:31 + | +LL | fn func(outer: A) { + | ^ the type must not depend on the parameter `A` + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71611.rs:5:21 + | +LL | fn func(outer: A) { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71611.rs b/tests/ui/const-generics/issues/issue-71611.rs new file mode 100644 index 000000000..fbb91ca18 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71611.rs @@ -0,0 +1,11 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn func(outer: A) { + //~^ ERROR: using function pointers as const generic parameters is forbidden + //~| ERROR: the type of const parameters must not depend on other generic parameters + F(outer); +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-71986.rs b/tests/ui/const-generics/issues/issue-71986.rs new file mode 100644 index 000000000..6f0a98ead --- /dev/null +++ b/tests/ui/const-generics/issues/issue-71986.rs @@ -0,0 +1,6 @@ +// check-pass + +pub trait Foo {} +pub fn bar>() {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-72352.full.stderr b/tests/ui/const-generics/issues/issue-72352.full.stderr new file mode 100644 index 000000000..92580b336 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72352.full.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-72352.rs:7:42 + | +LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-72352.min.stderr b/tests/ui/const-generics/issues/issue-72352.min.stderr new file mode 100644 index 000000000..eedd73c4d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72352.min.stderr @@ -0,0 +1,8 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-72352.rs:7:42 + | +LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-72352.rs b/tests/ui/const-generics/issues/issue-72352.rs new file mode 100644 index 000000000..2fa1d7a53 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72352.rs @@ -0,0 +1,22 @@ +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +use std::ffi::{CStr, CString}; + +unsafe fn unsafely_do_the_thing usize>(ptr: *const i8) -> usize { + //~^ ERROR: using function pointers as const generic parameters is forbidden + F(CStr::from_ptr(ptr)) +} + +fn safely_do_the_thing(s: &CStr) -> usize { + s.to_bytes().len() +} + +fn main() { + let baguette = CString::new("baguette").unwrap(); + let ptr = baguette.as_ptr(); + println!("{}", unsafe { + unsafely_do_the_thing::(ptr) + }); +} diff --git a/tests/ui/const-generics/issues/issue-72845.rs b/tests/ui/const-generics/issues/issue-72845.rs new file mode 100644 index 000000000..bea5dc8ba --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72845.rs @@ -0,0 +1,49 @@ +#![feature(generic_const_exprs)] +#![feature(specialization)] +#![allow(incomplete_features)] + +//-------------------------------------------------- + +trait Depth { + const C: usize; +} + +trait Type { + type AT: Depth; +} + +//-------------------------------------------------- + +enum Predicate {} + +trait Satisfied {} + +impl Satisfied for Predicate {} + +//-------------------------------------------------- + +trait Spec1 {} + +impl Spec1 for T where Predicate<{T::AT::C > 0}>: Satisfied {} + +trait Spec2 {} + +//impl Spec2 for T where Predicate<{T::AT::C > 1}>: Satisfied {} +impl Spec2 for T where Predicate: Satisfied {} + +//-------------------------------------------------- + +trait Foo { + fn Bar(); +} + +impl Foo for T { + default fn Bar() {} +} + +impl Foo for T { +//~^ ERROR conflicting implementations of trait + fn Bar() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-72845.stderr b/tests/ui/const-generics/issues/issue-72845.stderr new file mode 100644 index 000000000..631c8605f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-72845.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Foo` + --> $DIR/issue-72845.rs:44:1 + | +LL | impl Foo for T { + | ------------------------ first implementation here +... +LL | impl Foo for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/issues/issue-73120.rs b/tests/ui/const-generics/issues/issue-73120.rs new file mode 100644 index 000000000..050dc9bde --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73120.rs @@ -0,0 +1,10 @@ +// check-pass +// aux-build:const_generic_issues_lib.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +extern crate const_generic_issues_lib as lib2; +fn unused_function( + _: as lib2::TypeFn>::Output +) {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-73260.rs b/tests/ui/const-generics/issues/issue-73260.rs new file mode 100644 index 000000000..d762f9c8b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73260.rs @@ -0,0 +1,19 @@ +// compile-flags: -Zsave-analysis +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] +struct Arr +where + Assert::<{N < usize::MAX / 2}>: IsTrue, +{} + +enum Assert {} + +trait IsTrue {} + +impl IsTrue for Assert {} + +fn main() { + let x: Arr<{usize::MAX}> = Arr {}; + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/tests/ui/const-generics/issues/issue-73260.stderr b/tests/ui/const-generics/issues/issue-73260.stderr new file mode 100644 index 000000000..7670032e5 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73260.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> $DIR/issue-73260.rs:16:12 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-73260.rs:6:37 + | +LL | struct Arr + | --- required by a bound in this +LL | where +LL | Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error[E0308]: mismatched types + --> $DIR/issue-73260.rs:16:32 + | +LL | let x: Arr<{usize::MAX}> = Arr {}; + | ^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-73260.rs:6:37 + | +LL | struct Arr + | --- required by a bound in this +LL | where +LL | Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-73491.min.stderr b/tests/ui/const-generics/issues/issue-73491.min.stderr new file mode 100644 index 000000000..f03354fc4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73491.min.stderr @@ -0,0 +1,11 @@ +error: `[u32; LEN]` is forbidden as the type of a const generic parameter + --> $DIR/issue-73491.rs:8:19 + | +LL | fn hoge() {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-73491.rs b/tests/ui/const-generics/issues/issue-73491.rs new file mode 100644 index 000000000..482dbb04d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73491.rs @@ -0,0 +1,11 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +const LEN: usize = 1024; + +fn hoge() {} +//[min]~^ ERROR `[u32; LEN]` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr new file mode 100644 index 000000000..0a7db6247 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr @@ -0,0 +1,11 @@ +error: `&'static [u32]` is forbidden as the type of a const generic parameter + --> $DIR/issue-73727-static-reference-array-const-param.rs:9:15 + | +LL | fn a() {} + | ^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs new file mode 100644 index 000000000..f0d604835 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs @@ -0,0 +1,14 @@ +// Regression test for #73727 + +// revisions: full min +//[full]check-pass + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn a() {} +//[min]~^ ERROR `&'static [u32]` is forbidden as the type of a const generic parameter + +fn main() { + a::<{&[]}>(); +} diff --git a/tests/ui/const-generics/issues/issue-74101.min.stderr b/tests/ui/const-generics/issues/issue-74101.min.stderr new file mode 100644 index 000000000..134c24834 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74101.min.stderr @@ -0,0 +1,20 @@ +error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + --> $DIR/issue-74101.rs:6:18 + | +LL | fn test() {} + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + --> $DIR/issue-74101.rs:9:21 + | +LL | struct Foo; + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/issues/issue-74101.rs b/tests/ui/const-generics/issues/issue-74101.rs new file mode 100644 index 000000000..4c9b2d3c6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74101.rs @@ -0,0 +1,12 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +fn test() {} +//[min]~^ ERROR `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + +struct Foo; +//[min]~^ ERROR `[u8; 1 + 2]` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-74255.min.stderr b/tests/ui/const-generics/issues/issue-74255.min.stderr new file mode 100644 index 000000000..b462d8448 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74255.min.stderr @@ -0,0 +1,11 @@ +error: `IceEnum` is forbidden as the type of a const generic parameter + --> $DIR/issue-74255.rs:14:31 + | +LL | fn ice_struct_fn() {} + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-74255.rs b/tests/ui/const-generics/issues/issue-74255.rs new file mode 100644 index 000000000..0e523926f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74255.rs @@ -0,0 +1,20 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +#[derive(PartialEq, Eq)] +enum IceEnum { + Variant +} + +struct IceStruct; + +impl IceStruct { + fn ice_struct_fn() {} + //[min]~^ ERROR `IceEnum` is forbidden as the type of a const generic parameter +} + +fn main() { + IceStruct::ice_struct_fn::<{IceEnum::Variant}>(); +} diff --git a/tests/ui/const-generics/issues/issue-74906.rs b/tests/ui/const-generics/issues/issue-74906.rs new file mode 100644 index 000000000..cc1f2853f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74906.rs @@ -0,0 +1,22 @@ +// edition:2018 +// check-pass + + +const SIZE: usize = 16; + +struct Bar {} + +struct Foo {} + +impl Foo { + async fn biz(_: &[[u8; SIZE]]) -> Vec<()> { + vec![] + } + + pub async fn baz(&self) -> Bar { + Self::biz(&vec![]).await; + Bar {} + } +} + +fn main() { } diff --git a/tests/ui/const-generics/issues/issue-74950.min.stderr b/tests/ui/const-generics/issues/issue-74950.min.stderr new file mode 100644 index 000000000..729ecc202 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74950.min.stderr @@ -0,0 +1,47 @@ +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `Inner` is forbidden as the type of a const generic parameter + --> $DIR/issue-74950.rs:17:23 + | +LL | struct Outer; + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/const-generics/issues/issue-74950.rs b/tests/ui/const-generics/issues/issue-74950.rs new file mode 100644 index 000000000..3e1ca4735 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-74950.rs @@ -0,0 +1,24 @@ +// [full] build-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + + +#[derive(PartialEq, Eq)] +struct Inner; + +// Note: We emit the error 5 times if we don't deduplicate: +// - struct definition +// - impl PartialEq +// - impl Eq +// - impl StructuralPartialEq +// - impl StructuralEq +#[derive(PartialEq, Eq)] +struct Outer; +//[min]~^ `Inner` is forbidden +//[min]~| `Inner` is forbidden +//[min]~| `Inner` is forbidden +//[min]~| `Inner` is forbidden +//[min]~| `Inner` is forbidden + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-75047.min.stderr b/tests/ui/const-generics/issues/issue-75047.min.stderr new file mode 100644 index 000000000..46af19ef3 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-75047.min.stderr @@ -0,0 +1,11 @@ +error: `[u8; Bar::::value()]` is forbidden as the type of a const generic parameter + --> $DIR/issue-75047.rs:14:21 + | +LL | struct Foo::value()]>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-75047.rs b/tests/ui/const-generics/issues/issue-75047.rs new file mode 100644 index 000000000..7b6fb92bc --- /dev/null +++ b/tests/ui/const-generics/issues/issue-75047.rs @@ -0,0 +1,17 @@ +// [full] check-pass +// revisions: full min +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Bar(T); + +impl Bar { + const fn value() -> usize { + 42 + } +} + +struct Foo::value()]>; +//[min]~^ ERROR `[u8; Bar::::value()]` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-75299.rs b/tests/ui/const-generics/issues/issue-75299.rs new file mode 100644 index 000000000..83ef09af8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-75299.rs @@ -0,0 +1,8 @@ +// compile-flags: -Zmir-opt-level=4 +// run-pass +fn main() { + fn foo() -> [u8; N] { + [0; N] + } + let _x = foo::<1>(); +} diff --git a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs new file mode 100644 index 000000000..2e6b02236 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.rs @@ -0,0 +1,11 @@ +fn ty_param() -> [u8; std::mem::size_of::()] { + //~^ ERROR generic parameters may not be used in const operations + todo!() +} + +fn const_param() -> [u8; N + 1] { + //~^ ERROR generic parameters may not be used in const operations + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr new file mode 100644 index 000000000..3b53e18e6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr @@ -0,0 +1,20 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-76701-ty-param-in-const.rs:1:46 + | +LL | fn ty_param() -> [u8; std::mem::size_of::()] { + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/issue-76701-ty-param-in-const.rs:6:42 + | +LL | fn const_param() -> [u8; N + 1] { + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/issues/issue-77357.rs b/tests/ui/const-generics/issues/issue-77357.rs new file mode 100644 index 000000000..3cb8d3846 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-77357.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MyTrait {} + +fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + //~^ ERROR overly complex generic constant + todo!() +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-77357.stderr b/tests/ui/const-generics/issues/issue-77357.stderr new file mode 100644 index 000000000..68b35a38b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-77357.stderr @@ -0,0 +1,11 @@ +error: overly complex generic constant + --> $DIR/issue-77357.rs:6:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-79674.rs b/tests/ui/const-generics/issues/issue-79674.rs new file mode 100644 index 000000000..ff141d328 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-79674.rs @@ -0,0 +1,28 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MiniTypeId { + const TYPE_ID: u64; +} + +impl MiniTypeId for T { + const TYPE_ID: u64 = 0; +} + +enum Lift {} + +trait IsFalse {} +impl IsFalse for Lift {} + +const fn is_same_type() -> bool { + T::TYPE_ID == U::TYPE_ID +} + +fn requires_distinct(_a: A, _b: B) where + A: MiniTypeId, B: MiniTypeId, + Lift<{is_same_type::()}>: IsFalse {} + +fn main() { + requires_distinct("str", 12); + //~^ ERROR mismatched types +} diff --git a/tests/ui/const-generics/issues/issue-79674.stderr b/tests/ui/const-generics/issues/issue-79674.stderr new file mode 100644 index 000000000..02b48b55f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-79674.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-79674.rs:26:5 + | +LL | requires_distinct("str", 12); + | ^^^^^^^^^^^^^^^^^ expected `true`, found `false` + | + = note: expected constant `true` + found constant `false` +note: required by a bound in `requires_distinct` + --> $DIR/issue-79674.rs:23:37 + | +LL | fn requires_distinct(_a: A, _b: B) where + | ----------------- required by a bound in this +LL | A: MiniTypeId, B: MiniTypeId, +LL | Lift<{is_same_type::()}>: IsFalse {} + | ^^^^^^^ required by this bound in `requires_distinct` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/issues/issue-80062.rs b/tests/ui/const-generics/issues/issue-80062.rs new file mode 100644 index 000000000..56dc53298 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80062.rs @@ -0,0 +1,10 @@ +// Regression test for issue #80062 (fixed by `min_const_generics`) + +fn sof() -> T { unimplemented!() } + +fn test() { + let _: [u8; sof::()]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-80062.stderr b/tests/ui/const-generics/issues/issue-80062.stderr new file mode 100644 index 000000000..754f18d5c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80062.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-80062.rs:6:23 + | +LL | let _: [u8; sof::()]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-80375.rs b/tests/ui/const-generics/issues/issue-80375.rs new file mode 100644 index 000000000..c906bb2c4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80375.rs @@ -0,0 +1,4 @@ +struct MyArray([u8; COUNT + 1]); +//~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-80375.stderr b/tests/ui/const-generics/issues/issue-80375.stderr new file mode 100644 index 000000000..5409002a9 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-80375.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/issue-80375.rs:1:41 + | +LL | struct MyArray([u8; COUNT + 1]); + | ^^^^^ cannot perform const operation using `COUNT` + | + = help: const parameters may only be used as standalone arguments, i.e. `COUNT` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-82956.rs b/tests/ui/const-generics/issues/issue-82956.rs new file mode 100644 index 000000000..3539e9b96 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-82956.rs @@ -0,0 +1,33 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct ConstCheck; + +pub trait True {} +impl True for ConstCheck {} + +pub trait OrdesDec { + type Newlen; + type Output; + + fn pop(self) -> (Self::Newlen, Self::Output); +} + +impl OrdesDec for [T; N] +where + ConstCheck<{N > 1}>: True, + [T; N - 1]: Sized, +{ + type Newlen = [T; N - 1]; + type Output = T; + + fn pop(self) -> (Self::Newlen, Self::Output) { + let mut iter = IntoIter::new(self); + //~^ ERROR: failed to resolve: use of undeclared type `IntoIter` + let end = iter.next_back().unwrap(); + let new = [(); N - 1].map(move |()| iter.next().unwrap()); + (new, end) + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-82956.stderr b/tests/ui/const-generics/issues/issue-82956.stderr new file mode 100644 index 000000000..d2320293e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-82956.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared type `IntoIter` + --> $DIR/issue-82956.rs:25:24 + | +LL | let mut iter = IntoIter::new(self); + | ^^^^^^^^ use of undeclared type `IntoIter` + | +help: consider importing one of these items + | +LL | use std::array::IntoIter; + | +LL | use std::collections::binary_heap::IntoIter; + | +LL | use std::collections::btree_map::IntoIter; + | +LL | use std::collections::btree_set::IntoIter; + | + and 8 other candidates + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/const-generics/issues/issue-83249.rs b/tests/ui/const-generics/issues/issue-83249.rs new file mode 100644 index 000000000..65148c55e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83249.rs @@ -0,0 +1,23 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Foo { + const N: usize; +} + +impl Foo for u8 { + const N: usize = 1; +} + +fn foo(_: [u8; T::N]) -> T { + todo!() +} + +pub fn bar() { + let _: u8 = foo([0; 1]); + + let _ = foo([0; 1]); + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-83249.stderr b/tests/ui/const-generics/issues/issue-83249.stderr new file mode 100644 index 000000000..7491fdc8a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83249.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/issue-83249.rs:19:9 + | +LL | let _ = foo([0; 1]); + | ^ + | +help: consider giving this pattern a type + | +LL | let _: /* Type */ = foo([0; 1]); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/issues/issue-83288.rs b/tests/ui/const-generics/issues/issue-83288.rs new file mode 100644 index 000000000..a24596d24 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83288.rs @@ -0,0 +1,69 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::{marker::PhantomData, ops::Mul}; + +pub enum Nil {} +pub struct Cons { + _phantom: PhantomData<(T, L)>, +} + +pub trait Indices { + const RANK: usize; + const NUM_ELEMS: usize; +} + +impl Indices for Nil { + const RANK: usize = 0; + const NUM_ELEMS: usize = 1; +} + +impl, const N: usize> Indices for Cons { + const RANK: usize = I::RANK + 1; + const NUM_ELEMS: usize = I::NUM_ELEMS * N; +} + +pub trait Concat { + type Output; +} + +impl Concat for Nil { + type Output = J; +} + +impl Concat for Cons +where + I: Concat, +{ + type Output = Cons>::Output>; +} + +pub struct Tensor, const N: usize> +where + [u8; I::NUM_ELEMS]: Sized, +{ + pub data: [u8; I::NUM_ELEMS], + _phantom: PhantomData, +} + +impl, J: Indices, const N: usize> Mul> for Tensor +where + I: Concat, + >::Output: Indices, + [u8; I::NUM_ELEMS]: Sized, + [u8; J::NUM_ELEMS]: Sized, + [u8; >::Output::NUM_ELEMS]: Sized, +{ + type Output = Tensor<>::Output, N>; + + fn mul(self, _rhs: Tensor) -> Self::Output { + Tensor { + data: [0u8; >::Output::NUM_ELEMS], + _phantom: PhantomData, + } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-83466.rs b/tests/ui/const-generics/issues/issue-83466.rs new file mode 100644 index 000000000..73c930101 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83466.rs @@ -0,0 +1,17 @@ +// regression test for #83466- tests that generic arg mismatch errors between +// consts and types are not suppressed when there are explicit late bound lifetimes + +struct S; +impl S { + fn func<'a, U>(self) -> U { + todo!() + } +} +fn dont_crash<'a, U>() { + S.func::<'a, 10_u32>() + //~^ WARNING cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + //~^^ WARNING this was previously accepted by + //~^^^ ERROR constant provided when a type was expected [E0747] +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-83466.stderr b/tests/ui/const-generics/issues/issue-83466.stderr new file mode 100644 index 000000000..bcfd70639 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83466.stderr @@ -0,0 +1,22 @@ +warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/issue-83466.rs:11:14 + | +LL | fn func<'a, U>(self) -> U { + | -- the late bound lifetime parameter is introduced here +... +LL | S.func::<'a, 10_u32>() + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + = note: `#[warn(late_bound_lifetime_arguments)]` on by default + +error[E0747]: constant provided when a type was expected + --> $DIR/issue-83466.rs:11:18 + | +LL | S.func::<'a, 10_u32>() + | ^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/issues/issue-83765.rs b/tests/ui/const-generics/issues/issue-83765.rs new file mode 100644 index 000000000..71c164ab0 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83765.rs @@ -0,0 +1,116 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait TensorDimension { + const DIM: usize; + //~^ ERROR cycle detected when resolving instance + // FIXME Given the current state of the compiler its expected that we cycle here, + // but the cycle is still wrong. + const ISSCALAR: bool = Self::DIM == 0; + fn is_scalar(&self) -> bool { + Self::ISSCALAR + } +} + +trait TensorSize: TensorDimension { + fn size(&self) -> [usize; Self::DIM]; + fn inbounds(&self, index: [usize; Self::DIM]) -> bool { + index.iter().zip(self.size().iter()).all(|(i, s)| i < s) + } +} + +trait Broadcastable: TensorSize + Sized { + type Element; + fn bget(&self, index: [usize; Self::DIM]) -> Option; + fn lazy_updim( + &self, + size: [usize; NEWDIM], + ) -> LazyUpdim { + assert!( + NEWDIM >= Self::DIM, + "Updimmed tensor cannot have fewer indices than the initial one." + ); + LazyUpdim { size, reference: &self } + } + fn bmap T>(&self, foo: F) -> BMap { + BMap { reference: self, closure: foo } + } +} + +struct LazyUpdim<'a, T: Broadcastable, const OLDDIM: usize, const DIM: usize> { + size: [usize; DIM], + reference: &'a T, +} + +impl<'a, T: Broadcastable, const DIM: usize> TensorDimension for LazyUpdim<'a, T, { T::DIM }, DIM> { + const DIM: usize = DIM; +} + +impl<'a, T: Broadcastable, const DIM: usize> TensorSize for LazyUpdim<'a, T, { T::DIM }, DIM> { + fn size(&self) -> [usize; DIM] { + self.size + } +} + +impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> { + type Element = T::Element; + fn bget(&self, index: [usize; DIM]) -> Option { + assert!(DIM >= T::DIM); + if !self.inbounds(index) { + return None; + } + let size = self.size(); + let newindex: [usize; T::DIM] = Default::default(); + self.reference.bget(newindex) + } +} + +struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> { + reference: &'a T, + closure: F, +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension + for BMap<'a, R, T, F, DIM> +{ + const DIM: usize = DIM; +} +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize + for BMap<'a, R, T, F, DIM> +{ + fn size(&self) -> [usize; DIM] { + self.reference.size() + } +} + +impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcastable + for BMap<'a, R, T, F, DIM> +{ + type Element = R; + fn bget(&self, index: [usize; DIM]) -> Option { + self.reference.bget(index).map(&self.closure) + } +} + +impl TensorDimension for Vec { + const DIM: usize = 1; +} +impl TensorSize for Vec { + fn size(&self) -> [usize; 1] { + [self.len()] + } +} +impl Broadcastable for Vec { + type Element = T; + fn bget(&self, index: [usize; 1]) -> Option { + self.get(index[0]).cloned() + } +} + +fn main() { + let v = vec![1, 2, 3]; + let bv = v.lazy_updim([3, 4]); + let bbv = bv.bmap(|x| x * x); + + println!("The size of v is {:?}", bbv.bget([0, 2]).expect("Out of bounds.")); +} diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr new file mode 100644 index 000000000..d7b2b006c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when resolving instance `::DIM, DIM> as TensorDimension>::DIM` + --> $DIR/issue-83765.rs:5:5 + | +LL | const DIM: usize; + | ^^^^^^^^^^^^^^^^ + | +note: ...which requires computing candidate for `::DIM, DIM> as TensorDimension>`... + --> $DIR/issue-83765.rs:4:1 + | +LL | trait TensorDimension { + | ^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires resolving instance `::DIM, DIM> as TensorDimension>::DIM`, completing the cycle +note: cycle used when computing candidate for ` as TensorDimension>` + --> $DIR/issue-83765.rs:4:1 + | +LL | trait TensorDimension { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/issues/issue-83993.rs b/tests/ui/const-generics/issues/issue-83993.rs new file mode 100644 index 000000000..f2f05d952 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-83993.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn bug<'a>() +where + for<'b> [(); { + let x: &'b (); + 0 + }]: +{} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-84659.rs b/tests/ui/const-generics/issues/issue-84659.rs new file mode 100644 index 000000000..440ca740a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-84659.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Bar {} + +trait Foo<'a> { + const N: usize; + type Baz: Bar<{ Self::N }>; + //~^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-84659.stderr b/tests/ui/const-generics/issues/issue-84659.stderr new file mode 100644 index 000000000..2dfc48a34 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-84659.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-84659.rs:8:15 + | +LL | type Baz: Bar<{ Self::N }>; + | ^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-85031-2.rs b/tests/ui/const-generics/issues/issue-85031-2.rs new file mode 100644 index 000000000..50dd66da6 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-85031-2.rs @@ -0,0 +1,17 @@ +// check-pass +// known-bug: unknown + +// This should not compile, as the compiler should not know +// `A - 0` is satisfied `?x - 0` if `?x` is inferred to `A`. +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub struct Ref<'a>(&'a i32); + +impl<'a> Ref<'a> { + pub fn foo() -> [(); A - 0] { + Self::foo() + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-85031-2.stderr b/tests/ui/const-generics/issues/issue-85031-2.stderr new file mode 100644 index 000000000..896e1c7ea --- /dev/null +++ b/tests/ui/const-generics/issues/issue-85031-2.stderr @@ -0,0 +1,13 @@ +warning: function cannot return without recursing + --> $DIR/issue-85031-2.rs:12:5 + | +LL | pub fn foo() -> [(); A - 0] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | Self::foo() + | ----------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/issues/issue-86033.rs b/tests/ui/const-generics/issues/issue-86033.rs new file mode 100644 index 000000000..cf08f722f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86033.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait IsTrue {} +impl IsTrue for () {} + +pub trait IsZST {} + +impl IsZST for T +where + (): IsTrue<{ std::mem::size_of::() == 0 }> +{} + +fn _func() -> impl IsZST { + || {} +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86530.rs b/tests/ui/const-generics/issues/issue-86530.rs new file mode 100644 index 000000000..b024decd4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86530.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait X { + const Y: usize; +} + +fn z(t: T) +where + T: X, + [(); T::Y]: , +{ +} + +fn unit_literals() { + z(" "); + //~^ ERROR: the trait bound `&str: X` is not satisfied +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86530.stderr b/tests/ui/const-generics/issues/issue-86530.stderr new file mode 100644 index 000000000..c63857b23 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86530.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `&str: X` is not satisfied + --> $DIR/issue-86530.rs:16:7 + | +LL | z(" "); + | - ^^^ the trait `X` is not implemented for `&str` + | | + | required by a bound introduced by this call + | +note: required by a bound in `z` + --> $DIR/issue-86530.rs:10:8 + | +LL | fn z(t: T) + | - required by a bound in this +LL | where +LL | T: X, + | ^ required by this bound in `z` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs new file mode 100644 index 000000000..0b535fd66 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86535-2.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Foo { + const ASSOC_C: usize; + fn foo() where [(); Self::ASSOC_C]:; +} + +struct Bar; +impl Foo for Bar { + const ASSOC_C: usize = 3; + + fn foo() where [u8; Self::ASSOC_C]: { + let _: [u8; Self::ASSOC_C] = loop {}; + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs new file mode 100644 index 000000000..5289c4e99 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86535.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(adt_const_params, generic_const_exprs)] +#![allow(incomplete_features, unused_variables)] + +struct F; +impl X for F<{ S }> { + const W: usize = 3; + + fn d(r: &[u8; Self::W]) -> F<{ S }> { + let x: [u8; Self::W] = [0; Self::W]; + F + } +} + +pub trait X { + const W: usize; + fn d(r: &[u8; Self::W]) -> Self; +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86820.rs b/tests/ui/const-generics/issues/issue-86820.rs new file mode 100644 index 000000000..ae4bd943f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86820.rs @@ -0,0 +1,24 @@ +// Regression test for the ICE described in #86820. + +#![allow(unused, dead_code)] +use std::ops::BitAnd; + +const C: fn() = || is_set(); +fn is_set() { + 0xffu8.bit::<0>(); +} + +trait Bits { + fn bit(self) -> bool; +} + +impl Bits for u8 { + fn bit(self) -> bool { + //~^ ERROR: method `bit` has an incompatible generic parameter for trait `Bits` [E0053] + let i = 1 << I; + let mask = u8::from(i); + mask & self == mask + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-86820.stderr b/tests/ui/const-generics/issues/issue-86820.stderr new file mode 100644 index 000000000..3a9cd957f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-86820.stderr @@ -0,0 +1,16 @@ +error[E0053]: method `bit` has an incompatible generic parameter for trait `Bits` + --> $DIR/issue-86820.rs:16:12 + | +LL | trait Bits { + | ---- +LL | fn bit(self) -> bool; + | ----------- expected const parameter of type `u8` +... +LL | impl Bits for u8 { + | ---------------- +LL | fn bit(self) -> bool { + | ^^^^^^^^^^^^^^ found const parameter of type `usize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/issues/issue-87076.rs b/tests/ui/const-generics/issues/issue-87076.rs new file mode 100644 index 000000000..8a567678b --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87076.rs @@ -0,0 +1,20 @@ +// build-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +pub struct UnitDims { + pub time: u8, + pub length: u8, +} + +pub struct UnitValue; + +impl UnitValue { + fn crash() {} +} + +fn main() { + UnitValue::<{ UnitDims { time: 1, length: 2 } }>::crash(); +} diff --git a/tests/ui/const-generics/issues/issue-87470.rs b/tests/ui/const-generics/issues/issue-87470.rs new file mode 100644 index 000000000..d60181a41 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87470.rs @@ -0,0 +1,24 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait TraitWithConst { + const SOME_CONST: usize; +} + +pub trait OtherTrait: TraitWithConst { + fn some_fn(self) -> [u8 ; ::SOME_CONST]; +} + +impl TraitWithConst for f32 { + const SOME_CONST: usize = 32; +} + +impl OtherTrait for f32 { + fn some_fn(self) -> [u8 ; ::SOME_CONST] { + [0; 32] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-87493.rs b/tests/ui/const-generics/issues/issue-87493.rs new file mode 100644 index 000000000..d8599ab22 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87493.rs @@ -0,0 +1,14 @@ +pub trait MyTrait { + type Assoc; +} + +pub fn foo(_s: S, _t: T) +where + S: MyTrait, + T: MyTrait, + //~^ ERROR: expected one of `,` or `>`, found `==` + //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-87493.stderr b/tests/ui/const-generics/issues/issue-87493.stderr new file mode 100644 index 000000000..653afae21 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87493.stderr @@ -0,0 +1,30 @@ +error: expected one of `,` or `>`, found `==` + --> $DIR/issue-87493.rs:8:22 + | +LL | T: MyTrait, + | ^^ expected one of `,` or `>` + | +help: if you meant to use an associated type binding, replace `==` with `=` + | +LL | T: MyTrait, + | ~ + +error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/issue-87493.rs:8:8 + | +LL | T: MyTrait, + | ^^^^^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/issue-87493.rs:1:11 + | +LL | pub trait MyTrait { + | ^^^^^^^ +help: replace the generic bound with the associated type + | +LL | T: MyTrait, + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/issues/issue-87964.rs b/tests/ui/const-generics/issues/issue-87964.rs new file mode 100644 index 000000000..116686abb --- /dev/null +++ b/tests/ui/const-generics/issues/issue-87964.rs @@ -0,0 +1,29 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Target { + const LENGTH: usize; +} + + +pub struct Container +where + [(); T::LENGTH]: Sized, +{ + _target: T, +} + +impl Container +where + [(); T::LENGTH]: Sized, +{ + pub fn start( + _target: T, + ) -> Container { + Container { _target } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88119.rs b/tests/ui/const-generics/issues/issue-88119.rs new file mode 100644 index 000000000..647b0eea8 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88119.rs @@ -0,0 +1,36 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(const_trait_impl, generic_const_exprs)] + +#[const_trait] +trait ConstName { + const NAME_BYTES: &'static [u8]; +} + +impl const ConstName for u8 { + const NAME_BYTES: &'static [u8] = b"u8"; +} + +const fn name_len() -> usize { + T::NAME_BYTES.len() +} + +impl const ConstName for &T +where + [(); name_len::()]:, +{ + const NAME_BYTES: &'static [u8] = b"&T"; +} + +impl const ConstName for &mut T +where + [(); name_len::()]:, +{ + const NAME_BYTES: &'static [u8] = b"&mut T"; +} + +pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES; +pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88468.rs b/tests/ui/const-generics/issues/issue-88468.rs new file mode 100644 index 000000000..914047236 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88468.rs @@ -0,0 +1,13 @@ +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub struct Assert(); +pub trait IsTrue {} +impl IsTrue for Assert {} + +pub trait IsNotZST {} +impl IsNotZST for T where Assert<{ std::mem::size_of::() > 0 }>: IsTrue {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88997.rs b/tests/ui/const-generics/issues/issue-88997.rs new file mode 100644 index 000000000..7666a5141 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88997.rs @@ -0,0 +1,14 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +struct ConstAssert; +trait True {} +impl True for ConstAssert {} + +struct Range(T) +//~^ ERROR the type of const parameters must not depend on other generic parameters +//~| ERROR the type of const parameters must not depend on other generic parameters +where + ConstAssert<{ MIN <= MAX }>: True; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-88997.stderr b/tests/ui/const-generics/issues/issue-88997.stderr new file mode 100644 index 000000000..505ba0da2 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-88997.stderr @@ -0,0 +1,15 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-88997.rs:8:40 + | +LL | struct Range(T) + | ^ the type must not depend on the parameter `T` + +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-88997.rs:8:54 + | +LL | struct Range(T) + | ^ the type must not depend on the parameter `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-89146.rs b/tests/ui/const-generics/issues/issue-89146.rs new file mode 100644 index 000000000..e3540f46f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89146.rs @@ -0,0 +1,26 @@ +// build-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +pub trait Foo { + const SIZE: usize; + + fn to_bytes(&self) -> [u8; Self::SIZE]; +} + +pub fn bar(a: &G) -> u8 +where + [(); G::SIZE]: Sized, +{ + deeper_bar(a) +} + +fn deeper_bar(a: &G) -> u8 +where + [(); G::SIZE]: Sized, +{ + a.to_bytes()[0] +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-89304.rs b/tests/ui/const-generics/issues/issue-89304.rs new file mode 100644 index 000000000..d544d637c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89304.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct GenericStruct { val: i64 } + +impl From> for GenericStruct<{T + 1}> { + fn from(other: GenericStruct) -> Self { + Self { val: other.val } + } +} + +impl From> for GenericStruct { + fn from(other: GenericStruct<{T + 1}>) -> Self { + Self { val: other.val } + } +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-89320.rs b/tests/ui/const-generics/issues/issue-89320.rs new file mode 100644 index 000000000..afa5c8fab --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89320.rs @@ -0,0 +1,19 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait Enumerable { + const N: usize; +} + +#[derive(Clone)] +pub struct SymmetricGroup +where + S: Enumerable, + [(); S::N]: Sized, +{ + _phantom: std::marker::PhantomData, +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-89334.rs b/tests/ui/const-generics/issues/issue-89334.rs new file mode 100644 index 000000000..b15b7428c --- /dev/null +++ b/tests/ui/const-generics/issues/issue-89334.rs @@ -0,0 +1,16 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait AnotherTrait{ + const ARRAY_SIZE: usize; +} +pub trait Shard: + AsMut<[[u8; T::ARRAY_SIZE]]> +where + [(); T::ARRAY_SIZE]: Sized +{ +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90318.rs b/tests/ui/const-generics/issues/issue-90318.rs new file mode 100644 index 000000000..909997340 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90318.rs @@ -0,0 +1,30 @@ +#![feature(const_type_id)] +#![feature(generic_const_exprs)] +#![feature(core_intrinsics)] +#![allow(incomplete_features)] + +use std::any::TypeId; + +struct If; +pub trait True {} +impl True for If {} + +fn consume(_val: T) +where + If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + //~^ overly complex generic constant +{ +} + +fn test() +where + If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + //~^ overly complex generic constant +{ +} + +fn main() { + let a = (); + consume(0i32); + consume(a); +} diff --git a/tests/ui/const-generics/issues/issue-90318.stderr b/tests/ui/const-generics/issues/issue-90318.stderr new file mode 100644 index 000000000..f13fd795d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90318.stderr @@ -0,0 +1,24 @@ +error: overly complex generic constant + --> $DIR/issue-90318.rs:14:8 + | +LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | borrowing is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: overly complex generic constant + --> $DIR/issue-90318.rs:21:8 + | +LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | borrowing is not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/issues/issue-90364.rs b/tests/ui/const-generics/issues/issue-90364.rs new file mode 100644 index 000000000..b11b07b50 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90364.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo(T) +//~^ ERROR the type of const parameters must not depend on other generic parameters +where + [(); 1]:; + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90364.stderr b/tests/ui/const-generics/issues/issue-90364.stderr new file mode 100644 index 000000000..e85bd136e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90364.stderr @@ -0,0 +1,9 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/issue-90364.rs:4:28 + | +LL | pub struct Foo(T) + | ^ the type must not depend on the parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-90455.rs b/tests/ui/const-generics/issues/issue-90455.rs new file mode 100644 index 000000000..a580410cf --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90455.rs @@ -0,0 +1,12 @@ +#![feature(generic_const_exprs, adt_const_params)] +#![allow(incomplete_features)] + +struct FieldElement { + n: [u64; num_limbs(N)], + //~^ ERROR unconstrained generic constant +} +const fn num_limbs(_: &str) -> usize { + 0 +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90455.stderr b/tests/ui/const-generics/issues/issue-90455.stderr new file mode 100644 index 000000000..724d7f42e --- /dev/null +++ b/tests/ui/const-generics/issues/issue-90455.stderr @@ -0,0 +1,10 @@ +error: unconstrained generic constant + --> $DIR/issue-90455.rs:5:8 + | +LL | n: [u64; num_limbs(N)], + | ^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); num_limbs(N)]:` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/issues/issue-92186.rs b/tests/ui/const-generics/issues/issue-92186.rs new file mode 100644 index 000000000..9ced4667d --- /dev/null +++ b/tests/ui/const-generics/issues/issue-92186.rs @@ -0,0 +1,12 @@ +// check-pass + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct Foo; +pub trait Bar {} + +impl Bar for Foo<{ 1 }> {} +impl Bar for Foo<{ 2 }> {} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-96654.rs b/tests/ui/const-generics/issues/issue-96654.rs new file mode 100644 index 000000000..8cf786dbe --- /dev/null +++ b/tests/ui/const-generics/issues/issue-96654.rs @@ -0,0 +1,15 @@ +// check-pass + +struct A {} + +struct B {} + +impl B { + const M: u32 = M; +} + +struct C { + a: A<{ B::<1>::M }>, +} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-97278.rs b/tests/ui/const-generics/issues/issue-97278.rs new file mode 100644 index 000000000..da0a9776f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-97278.rs @@ -0,0 +1,14 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +use std::sync::Arc; + +#[derive(PartialEq, Eq)] +enum Bar { + Bar(Arc) +} + +fn test() {} +//~^ ERROR `Arc` must be annotated with `#[derive(PartialEq, Eq)]` + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-97278.stderr b/tests/ui/const-generics/issues/issue-97278.stderr new file mode 100644 index 000000000..ff13cb505 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-97278.stderr @@ -0,0 +1,9 @@ +error[E0741]: `Arc` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter + --> $DIR/issue-97278.rs:11:20 + | +LL | fn test() {} + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/issues/issue-97634.rs b/tests/ui/const-generics/issues/issue-97634.rs new file mode 100644 index 000000000..422e8de68 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-97634.rs @@ -0,0 +1,10 @@ +// build-pass + +pub enum Register { + Field0 = 40, + Field1, +} + +fn main() { + let _b = Register::<0>::Field1 as u16; +} diff --git a/tests/ui/const-generics/issues/issue-98629.rs b/tests/ui/const-generics/issues/issue-98629.rs new file mode 100644 index 000000000..1d2d3012a --- /dev/null +++ b/tests/ui/const-generics/issues/issue-98629.rs @@ -0,0 +1,16 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Trait { + const N: usize; +} + +impl const Trait for i32 {} +//~^ ERROR not all trait items implemented, missing: `N` + +fn f() +where + [(); ::N]:, +{} + +fn main() {} diff --git a/tests/ui/const-generics/issues/issue-98629.stderr b/tests/ui/const-generics/issues/issue-98629.stderr new file mode 100644 index 000000000..4a248be76 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-98629.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `N` + --> $DIR/issue-98629.rs:8:1 + | +LL | const N: usize; + | -------------- `N` from trait +... +LL | impl const Trait for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing `N` in implementation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/issues/issue-99641.rs b/tests/ui/const-generics/issues/issue-99641.rs new file mode 100644 index 000000000..fae6d3fc4 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-99641.rs @@ -0,0 +1,18 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +fn main() { + pub struct Color; + //~^ ERROR using function pointers + + impl Color { + //~^ ERROR using function pointers + pub fn new() -> Self { + Color:: + } + } + + pub const D65: (fn(),) = (|| {},); + + Color::::new(); +} diff --git a/tests/ui/const-generics/issues/issue-99641.stderr b/tests/ui/const-generics/issues/issue-99641.stderr new file mode 100644 index 000000000..349ebba08 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-99641.stderr @@ -0,0 +1,15 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-99641.rs:5:35 + | +LL | pub struct Color; + | ^^^^^^^ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/issue-99641.rs:8:23 + | +LL | impl Color { + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/late-bound-vars/in_closure.rs b/tests/ui/const-generics/late-bound-vars/in_closure.rs new file mode 100644 index 000000000..5294cc3b5 --- /dev/null +++ b/tests/ui/const-generics/late-bound-vars/in_closure.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _ = || { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; + }; +} + +fn main() { + test(); +} diff --git a/tests/ui/const-generics/late-bound-vars/simple.rs b/tests/ui/const-generics/late-bound-vars/simple.rs new file mode 100644 index 000000000..6da5395ef --- /dev/null +++ b/tests/ui/const-generics/late-bound-vars/simple.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; +} + +fn main() { + test(); +} diff --git a/tests/ui/const-generics/legacy-const-generics-bad.rs b/tests/ui/const-generics/legacy-const-generics-bad.rs new file mode 100644 index 000000000..538eee337 --- /dev/null +++ b/tests/ui/const-generics/legacy-const-generics-bad.rs @@ -0,0 +1,16 @@ +// aux-build:legacy-const-generics.rs + +extern crate legacy_const_generics; + +fn foo() { + let a = 1; + legacy_const_generics::foo(0, a, 2); + //~^ ERROR attempt to use a non-constant value in a constant + + legacy_const_generics::foo(0, N, 2); + + legacy_const_generics::foo(0, N + 1, 2); + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/const-generics/legacy-const-generics-bad.stderr b/tests/ui/const-generics/legacy-const-generics-bad.stderr new file mode 100644 index 000000000..3c78dd6c7 --- /dev/null +++ b/tests/ui/const-generics/legacy-const-generics-bad.stderr @@ -0,0 +1,20 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/legacy-const-generics-bad.rs:7:35 + | +LL | let a = 1; + | ----- help: consider using `const` instead of `let`: `const a` +LL | legacy_const_generics::foo(0, a, 2); + | ^ non-constant value + +error: generic parameters may not be used in const operations + --> $DIR/legacy-const-generics-bad.rs:12:35 + | +LL | legacy_const_generics::foo(0, N + 1, 2); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/const-generics/legacy-const-generics.rs b/tests/ui/const-generics/legacy-const-generics.rs new file mode 100644 index 000000000..9abc72d98 --- /dev/null +++ b/tests/ui/const-generics/legacy-const-generics.rs @@ -0,0 +1,18 @@ +// aux-build:legacy-const-generics.rs +// run-pass + +#![feature(rustc_attrs)] + +extern crate legacy_const_generics; + +#[rustc_legacy_const_generics(1)] +pub fn bar(x: usize, z: usize) -> [usize; 3] { + [x, Y, z] +} + +fn main() { + assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]); + assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]); + // FIXME: Only works cross-crate + //assert_eq!(bar(0, 1, 2), [0, 1, 2]); +} diff --git a/tests/ui/const-generics/min_const_generics/assoc_const.rs b/tests/ui/const-generics/min_const_generics/assoc_const.rs new file mode 100644 index 000000000..27e971b5b --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/assoc_const.rs @@ -0,0 +1,16 @@ +// check-pass +struct Foo; + +impl Foo { + const VALUE: usize = N * 2; +} + +trait Bar { + const ASSOC: usize; +} + +impl Bar for Foo { + const ASSOC: usize = N * 3; +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/complex-expression.rs b/tests/ui/const-generics/min_const_generics/complex-expression.rs new file mode 100644 index 000000000..8e667aeba --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-expression.rs @@ -0,0 +1,48 @@ +// compile-flags: -Zdeduplicate-diagnostics=yes +use std::mem::size_of; + +fn test() {} + +fn ok() -> [u8; M] { + [0; { M }] +} + +struct Break0([u8; { N + 1 }]); +//~^ ERROR generic parameters may not be used in const operations + +struct Break1([u8; { { N } }]); +//~^ ERROR generic parameters may not be used in const operations + +fn break2() { + let _: [u8; N + 1]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn break3() { + let _ = [0; N + 1]; + //~^ ERROR generic parameters may not be used in const operations +} + +struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); +//~^ ERROR generic parameters may not be used in const operations + +struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); +//~^ ERROR generic parameters may not be used in const operations + +fn break_ty2() { + let _: [u8; size_of::<*mut T>() + 1]; + //~^ ERROR generic parameters may not be used in const operations +} + +fn break_ty3() { + let _ = [0; size_of::<*mut T>() + 1]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + + +trait Foo { + const ASSOC: usize; +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/complex-expression.stderr b/tests/ui/const-generics/min_const_generics/complex-expression.stderr new file mode 100644 index 000000000..deabd05a6 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-expression.stderr @@ -0,0 +1,75 @@ +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:10:38 + | +LL | struct Break0([u8; { N + 1 }]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:13:40 + | +LL | struct Break1([u8; { { N } }]); + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:17:17 + | +LL | let _: [u8; N + 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:22:17 + | +LL | let _ = [0; N + 1]; + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:26:45 + | +LL | struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:29:47 + | +LL | struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/complex-expression.rs:33:32 + | +LL | let _: [u8; size_of::<*mut T>() + 1]; + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/complex-expression.rs:38:17 + | +LL | let _ = [0; size_of::<*mut T>() + 1]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted + diff --git a/tests/ui/const-generics/min_const_generics/complex-types.rs b/tests/ui/const-generics/min_const_generics/complex-types.rs new file mode 100644 index 000000000..057bd5af8 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-types.rs @@ -0,0 +1,27 @@ +#![feature(never_type)] + +struct Foo; +//~^ ERROR `[u8; 0]` is forbidden + +struct Bar; +//~^ ERROR `()` is forbidden +#[derive(PartialEq, Eq)] +struct No; + +struct Fez; +//~^ ERROR `No` is forbidden + +struct Faz; +//~^ ERROR `&'static u8` is forbidden + +struct Fiz; +//~^ ERROR `!` is forbidden + +enum Goo { A, B } +//~^ ERROR `()` is forbidden + +union Boo { a: () } +//~^ ERROR `()` is forbidden + + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/complex-types.stderr b/tests/ui/const-generics/min_const_generics/complex-types.stderr new file mode 100644 index 000000000..4ddbadb54 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/complex-types.stderr @@ -0,0 +1,65 @@ +error: `[u8; 0]` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:3:21 + | +LL | struct Foo; + | ^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:6:21 + | +LL | struct Bar; + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `No` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:11:21 + | +LL | struct Fez; + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `&'static u8` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:14:21 + | +LL | struct Faz; + | ^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `!` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:17:21 + | +LL | struct Fiz; + | ^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:20:19 + | +LL | enum Goo { A, B } + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: `()` is forbidden as the type of a const generic parameter + --> $DIR/complex-types.rs:23:20 + | +LL | union Boo { a: () } + | ^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to 7 previous errors + diff --git a/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs new file mode 100644 index 000000000..e9d868093 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs @@ -0,0 +1,35 @@ +// check-pass +// compile-flags: -Zdeduplicate-diagnostics=yes +#![allow(dead_code)] + +fn foo() { + [0; std::mem::size_of::<*mut T>()]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out +} + +struct Foo(T); + +impl Foo { + const ASSOC: usize = 4; + + fn test() { + let _ = [0; Self::ASSOC]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out + } +} + +struct Bar; + +impl Bar { + const ASSOC: usize = 4; + + fn test() { + let _ = [0; Self::ASSOC]; + //~^ WARN cannot use constants which depend on generic parameters in types + //~| WARN this was previously accepted by the compiler but is being phased out + } +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr new file mode 100644 index 000000000..8003dfa40 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr @@ -0,0 +1,30 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const-evaluatable-unchecked.rs:6:9 + | +LL | [0; std::mem::size_of::<*mut T>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + = note: `#[warn(const_evaluatable_unchecked)]` on by default + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const-evaluatable-unchecked.rs:17:21 + | +LL | let _ = [0; Self::ASSOC]; + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const-evaluatable-unchecked.rs:29:21 + | +LL | let _ = [0; Self::ASSOC]; + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + +warning: 3 warnings emitted + diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs new file mode 100644 index 000000000..fac3777cf --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.rs @@ -0,0 +1,47 @@ +fn foo() {} + +const BAR: usize = 42; + +fn a() { + foo(); //~ ERROR comparison operators cannot be chained +} +fn b() { + foo(); //~ ERROR comparison operators cannot be chained +} +fn c() { + foo<3 + 3>(); //~ ERROR comparison operators cannot be chained +} +fn d() { + foo(); //~ ERROR comparison operators cannot be chained +} +fn e() { + foo(); //~ ERROR comparison operators cannot be chained +} +fn f() { + foo<100 - BAR>(); //~ ERROR comparison operators cannot be chained +} +fn g() { + foo()>(); //~ ERROR comparison operators cannot be chained + //~^ ERROR expected one of `;` or `}`, found `>` +} +fn h() { + foo()>(); //~ ERROR comparison operators cannot be chained +} +fn i() { + foo() + BAR>(); //~ ERROR comparison operators cannot be chained +} +fn j() { + foo() - BAR>(); //~ ERROR comparison operators cannot be chained +} +fn k() { + foo()>(); //~ ERROR comparison operators cannot be chained +} +fn l() { + foo()>(); //~ ERROR comparison operators cannot be chained +} + +const fn bar() -> usize { + C +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr new file mode 100644 index 000000000..a6825b845 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces-without-turbofish.stderr @@ -0,0 +1,140 @@ +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:6:8 + | +LL | foo(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:9:8 + | +LL | foo(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:12:8 + | +LL | foo<3 + 3>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<3 + 3>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:15:8 + | +LL | foo(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:18:8 + | +LL | foo(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:21:8 + | +LL | foo<100 - BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::<100 - BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:24:8 + | +LL | foo()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::()>(); + | ++ + +error: expected one of `;` or `}`, found `>` + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:24:19 + | +LL | foo()>(); + | ^ expected one of `;` or `}` + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:28:8 + | +LL | foo()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::()>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:31:8 + | +LL | foo() + BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::() + BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:34:8 + | +LL | foo() - BAR>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::() - BAR>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:37:8 + | +LL | foo()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::()>(); + | ++ + +error: comparison operators cannot be chained + --> $DIR/const-expression-suggest-missing-braces-without-turbofish.rs:40:8 + | +LL | foo()>(); + | ^ ^ + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | foo::()>(); + | ++ + +error: aborting due to 13 previous errors + diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs new file mode 100644 index 000000000..e12e07a28 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.rs @@ -0,0 +1,51 @@ +fn foo() {} + +const BAR: usize = 42; + +fn a() { + foo::(); //~ ERROR expected one of +} +fn b() { + // FIXME(const_generics): these diagnostics are awful, because trait objects without `dyn` were + // a terrible mistake. + foo::(); + //~^ ERROR expected trait, found constant `BAR` + //~| ERROR expected trait, found constant `BAR` + //~| ERROR type provided when a constant was expected +} +fn c() { + foo::<3 + 3>(); //~ ERROR expressions must be enclosed in braces +} +fn d() { + foo::(); //~ ERROR expected one of +} +fn e() { + foo::(); //~ ERROR expected one of +} +fn f() { + foo::<100 - BAR>(); //~ ERROR expressions must be enclosed in braces +} +fn g() { + foo::()>(); //~ ERROR expected one of +} +fn h() { + foo::()>(); //~ ERROR expected one of +} +fn i() { + foo::() + BAR>(); //~ ERROR expected one of +} +fn j() { + foo::() - BAR>(); //~ ERROR expected one of +} +fn k() { + foo::()>(); //~ ERROR expected one of +} +fn l() { + foo::()>(); //~ ERROR expected one of +} + +const fn bar() -> usize { + C +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr new file mode 100644 index 000000000..d9bcc523b --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr @@ -0,0 +1,143 @@ +error: expected one of `,` or `>`, found `3` + --> $DIR/const-expression-suggest-missing-braces.rs:6:17 + | +LL | foo::(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR + 3 }>(); + | + + + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/const-expression-suggest-missing-braces.rs:17:11 + | +LL | foo::<3 + 3>(); + | ^^^^^ + | +help: enclose the `const` expression in braces + | +LL | foo::<{ 3 + 3 }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:20:15 + | +LL | foo::(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - 3 }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:23:15 + | +LL | foo::(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - BAR }>(); + | + + + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/const-expression-suggest-missing-braces.rs:26:11 + | +LL | foo::<100 - BAR>(); + | ^^^^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | foo::<{ 100 - BAR }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:29:19 + | +LL | foo::()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar() }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:32:21 + | +LL | foo::()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar::() }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:35:21 + | +LL | foo::() + BAR>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar::() + BAR }>(); + | + + + +error: expected one of `,` or `>`, found `(` + --> $DIR/const-expression-suggest-missing-braces.rs:38:21 + | +LL | foo::() - BAR>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar::() - BAR }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:41:15 + | +LL | foo::()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - bar::() }>(); + | + + + +error: expected one of `,` or `>`, found `-` + --> $DIR/const-expression-suggest-missing-braces.rs:44:15 + | +LL | foo::()>(); + | ^ expected one of `,` or `>` + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ BAR - bar::() }>(); + | + + + +error[E0404]: expected trait, found constant `BAR` + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 + | +LL | foo::(); + | ^^^ not a trait + +error[E0404]: expected trait, found constant `BAR` + --> $DIR/const-expression-suggest-missing-braces.rs:11:17 + | +LL | foo::(); + | ^^^ not a trait + +error[E0747]: type provided when a constant was expected + --> $DIR/const-expression-suggest-missing-braces.rs:11:11 + | +LL | foo::(); + | ^^^^^^^^^ + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0404, E0747. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/const-generics/min_const_generics/const_default_first.rs b/tests/ui/const-generics/min_const_generics/const_default_first.rs new file mode 100644 index 000000000..eafafb8a2 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const_default_first.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] +#![allow(dead_code)] + +struct Both { +//~^ ERROR: generic parameters with a default must be + v: T +} diff --git a/tests/ui/const-generics/min_const_generics/const_default_first.stderr b/tests/ui/const-generics/min_const_generics/const_default_first.stderr new file mode 100644 index 000000000..0d5a393cb --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const_default_first.stderr @@ -0,0 +1,8 @@ +error: generic parameters with a default must be trailing + --> $DIR/const_default_first.rs:4:19 + | +LL | struct Both { + | ^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs b/tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs new file mode 100644 index 000000000..0c10af6c4 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/const_fn_in_generics.rs @@ -0,0 +1,15 @@ +// run-pass + +const fn identity() -> u32 { T } + +#[derive(Eq, PartialEq, Debug)] +pub struct ConstU32; + +pub fn new() -> ConstU32<{ identity::<3>() }> { + ConstU32::<{ identity::<3>() }> +} + +fn main() { + let v = new(); + assert_eq!(v, ConstU32::<3>); +} diff --git a/tests/ui/const-generics/min_const_generics/default_function_param.rs b/tests/ui/const-generics/min_const_generics/default_function_param.rs new file mode 100644 index 000000000..92d495ef6 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/default_function_param.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] + +fn foo() {} +//~^ ERROR defaults for const parameters are diff --git a/tests/ui/const-generics/min_const_generics/default_function_param.stderr b/tests/ui/const-generics/min_const_generics/default_function_param.stderr new file mode 100644 index 000000000..dedad2880 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/default_function_param.stderr @@ -0,0 +1,8 @@ +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_function_param.rs:3:8 + | +LL | fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/default_trait_param.rs b/tests/ui/const-generics/min_const_generics/default_trait_param.rs new file mode 100644 index 000000000..9cd5e3279 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/default_trait_param.rs @@ -0,0 +1,4 @@ +// check-pass +trait Foo {} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs new file mode 100644 index 000000000..6215b7d93 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs @@ -0,0 +1,25 @@ +// This test checks that non-static lifetimes are prohibited under `min_const_generics`. It +// currently emits an error with `min_const_generics`. + +fn test() {} + +fn issue_75323_and_74447_1<'a>() -> &'a () { + test::<{ let _: &'a (); 3 },>(); + //~^ ERROR a non-static lifetime is not allowed in a `const` + &() +} + +fn issue_75323_and_74447_2() { + test::<{ let _: &(); 3 },>(); +} + +fn issue_75323_and_74447_3() { + test::<{ let _: &'static (); 3 },>(); +} + +fn issue_73375<'a>() { + [(); (|_: &'a u8| (), 0).1]; + //~^ ERROR a non-static lifetime is not allowed in a `const` +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr new file mode 100644 index 000000000..5f641b070 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr @@ -0,0 +1,21 @@ +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/forbid-non-static-lifetimes.rs:7:22 + | +LL | test::<{ let _: &'a (); 3 },>(); + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error[E0658]: a non-static lifetime is not allowed in a `const` + --> $DIR/forbid-non-static-lifetimes.rs:21:16 + | +LL | [(); (|_: &'a u8| (), 0).1]; + | ^^ + | + = note: see issue #76560 for more information + = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs new file mode 100644 index 000000000..e1cf7b579 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.rs @@ -0,0 +1,15 @@ +trait AlwaysApplicable { + type Assoc; +} +impl AlwaysApplicable for T { + type Assoc = usize; +} + +trait BindsParam { + type ArrayTy; +} +impl BindsParam for ::Assoc { + type ArrayTy = [u8; Self::MAX]; //~ ERROR generic `Self` types +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr new file mode 100644 index 000000000..bda885970 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/forbid-self-no-normalize.rs:12:25 + | +LL | type ArrayTy = [u8; Self::MAX]; + | ^^^^ + | +note: not a concrete type + --> $DIR/forbid-self-no-normalize.rs:11:27 + | +LL | impl BindsParam for ::Assoc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/inferred_const.rs b/tests/ui/const-generics/min_const_generics/inferred_const.rs new file mode 100644 index 000000000..57d694158 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/inferred_const.rs @@ -0,0 +1,9 @@ +#![feature(generic_arg_infer)] +// run-pass + +fn foo(_data: [u32; N]) -> [u32; K] { + [0; K] +} +fn main() { + let _a = foo::<_, 2>([0, 1, 2]); +} diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr new file mode 100644 index 000000000..be92429e3 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -0,0 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:29:21 + | +LL | get_flag::(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:38:32 + | +LL | get_flag::(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:41:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:43:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:43:58 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr new file mode 100644 index 000000000..be92429e3 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -0,0 +1,62 @@ +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:29:21 + | +LL | get_flag::(); + | ^^^^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:31:14 + | +LL | get_flag::<7, 'c'>(); + | ^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:14 + | +LL | get_flag::<42, 0x5ad>(); + | ^^ expected `bool`, found integer + +error[E0308]: mismatched types + --> $DIR/invalid-patterns.rs:33:18 + | +LL | get_flag::<42, 0x5ad>(); + | ^^^^^ expected `char`, found `u8` + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:38:32 + | +LL | get_flag::(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:41:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:43:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x42, but expected a boolean + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 1, align: 1) { + 42 │ B + } + +error[E0080]: evaluation of constant value failed + --> $DIR/invalid-patterns.rs:43:58 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0080, E0308. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.rs b/tests/ui/const-generics/min_const_generics/invalid-patterns.rs new file mode 100644 index 000000000..13b2cca2f --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.rs @@ -0,0 +1,47 @@ +// stderr-per-bitwidth +use std::mem::transmute; + +fn get_flag() -> Option { + if FlagSet { + Some(ShortName) + } else { + None + } +} + +union CharRaw { + byte: u8, + character: char, +} + +union BoolRaw { + byte: u8, + boolean: bool, +} + +const char_raw: CharRaw = CharRaw { byte: 0xFF }; +const bool_raw: BoolRaw = BoolRaw { byte: 0x42 }; + +fn main() { + // Test that basic cases don't work + assert!(get_flag::().is_some()); + assert!(get_flag::().is_none()); + get_flag::(); + //~^ ERROR mismatched types + get_flag::<7, 'c'>(); + //~^ ERROR mismatched types + get_flag::<42, 0x5ad>(); + //~^ ERROR mismatched types + //~| ERROR mismatched types + + + get_flag::(); + //~^ ERROR evaluation of constant value failed + //~| uninitialized + get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + //~^ ERROR it is undefined behavior + get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + //~^ ERROR evaluation of constant value failed + //~| uninitialized + //~| ERROR it is undefined behavior +} diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.rs b/tests/ui/const-generics/min_const_generics/macro-fail.rs new file mode 100644 index 000000000..7fb69032e --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/macro-fail.rs @@ -0,0 +1,39 @@ +struct Example; + +macro_rules! external_macro { + () => {{ + //~^ ERROR expected type + const X: usize = 1337; + X + }} +} + +trait Marker {} +impl Marker for Example {} + +fn make_marker() -> impl Marker { + //~^ ERROR: type provided when a constant was expected + Example:: +} + +fn from_marker(_: impl Marker<{ + #[macro_export] + macro_rules! inline { () => {{ 3 }} }; inline!() +}>) {} + +fn main() { + let _ok = Example::<{ + #[macro_export] + macro_rules! gimme_a_const { + ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + //~^ ERROR expected type + //~| ERROR expected type + }; + gimme_a_const!(run) + }>; + + let _fail = Example::; + + let _fail = Example::; + //~^ ERROR unexpected end of macro invocation +} diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.stderr b/tests/ui/const-generics/min_const_generics/macro-fail.stderr new file mode 100644 index 000000000..9f73b91aa --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/macro-fail.stderr @@ -0,0 +1,71 @@ +error: expected type, found `{` + --> $DIR/macro-fail.rs:28:27 + | +LL | fn make_marker() -> impl Marker { + | ---------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation +... +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type + | + = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected type, found `{` + --> $DIR/macro-fail.rs:28:27 + | +LL | Example:: + | ---------------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation +... +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type + | + = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected type, found `{` + --> $DIR/macro-fail.rs:4:10 + | +LL | () => {{ + | __________^ +LL | | +LL | | const X: usize = 1337; +LL | | X +LL | | }} + | |___^ expected type +... +LL | let _fail = Example::; + | ----------------- + | | + | this macro call doesn't expand to a type + | in this macro invocation + | + = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected end of macro invocation + --> $DIR/macro-fail.rs:37:25 + | +LL | macro_rules! gimme_a_const { + | -------------------------- when calling this macro +... +LL | let _fail = Example::; + | ^^^^^^^^^^^^^^^^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$rusty:ident` + --> $DIR/macro-fail.rs:28:8 + | +LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + | ^^^^^^^^^^^^^ + +error[E0747]: type provided when a constant was expected + --> $DIR/macro-fail.rs:14:33 + | +LL | fn make_marker() -> impl Marker { + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/min_const_generics/macro.rs b/tests/ui/const-generics/min_const_generics/macro.rs new file mode 100644 index 000000000..9b63f7698 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/macro.rs @@ -0,0 +1,55 @@ +// run-pass +struct Example; + +macro_rules! external_macro { + () => {{ + const X: usize = 1337; + X + }} +} + +trait Marker {} +impl Marker for Example {} + +fn make_marker() -> impl Marker<{ + #[macro_export] + macro_rules! const_macro { () => {{ 3 }} } inline!() +}> { + Example::<{ const_macro!() }> +} + +fn from_marker(_: impl Marker<{ + #[macro_export] + macro_rules! inline { () => {{ 3 }} } inline!() +}>) {} + +fn main() { + let _ok = Example::<{ + #[macro_export] + macro_rules! gimme_a_const { + ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} + } + gimme_a_const!(run) + }>; + + let _ok = Example::<{ external_macro!() }>; + + let _ok: [_; gimme_a_const!(blah)] = [0,0,0]; + let _ok: [[u8; gimme_a_const!(blah)]; gimme_a_const!(blah)]; + let _ok: [u8; gimme_a_const!(blah)]; + + let _ok: [u8; { + #[macro_export] + macro_rules! const_two { () => {{ 2 }} } + const_two!() + }]; + + let _ok = [0; { + #[macro_export] + macro_rules! const_three { () => {{ 3 }} } + const_three!() + }]; + let _ok = [0; const_three!()]; + + from_marker(make_marker()); +} diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs new file mode 100644 index 000000000..9ef619365 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.rs @@ -0,0 +1,25 @@ +trait Foo { + fn t1() -> [u8; std::mem::size_of::()]; //~ERROR generic parameters +} + +struct Bar(T); + +impl Bar { + fn t2() -> [u8; std::mem::size_of::()] { todo!() } // ok +} + +impl Bar { + fn t3() -> [u8; std::mem::size_of::()] {} //~ERROR generic `Self` +} + +trait Baz { + fn hey(); +} + +impl Baz for u16 { + fn hey() { + let _: [u8; std::mem::size_of::()]; // ok + } +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr new file mode 100644 index 000000000..16a7687c0 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -0,0 +1,23 @@ +error: generic parameters may not be used in const operations + --> $DIR/self-ty-in-const-1.rs:2:41 + | +LL | fn t1() -> [u8; std::mem::size_of::()]; + | ^^^^ cannot perform const operation using `Self` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/self-ty-in-const-1.rs:12:41 + | +LL | fn t3() -> [u8; std::mem::size_of::()] {} + | ^^^^ + | +note: not a concrete type + --> $DIR/self-ty-in-const-1.rs:11:9 + | +LL | impl Bar { + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs new file mode 100644 index 000000000..286ec2d24 --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.rs @@ -0,0 +1,19 @@ +struct Bar(T); + +trait Baz { + fn hey(); +} + +impl Baz for u16 { + fn hey() { + let _: [u8; std::mem::size_of::()]; // ok + } +} + +impl Baz for Bar { + fn hey() { + let _: [u8; std::mem::size_of::()]; //~ERROR generic `Self` + } +} + +fn main() {} diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr new file mode 100644 index 000000000..41546292c --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/self-ty-in-const-2.rs:15:41 + | +LL | let _: [u8; std::mem::size_of::()]; + | ^^^^ + | +note: not a concrete type + --> $DIR/self-ty-in-const-2.rs:13:17 + | +LL | impl Baz for Bar { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs b/tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs new file mode 100644 index 000000000..fa119c59f --- /dev/null +++ b/tests/ui/const-generics/min_const_generics/type_and_const_defaults.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] + +struct Both { + arr: [T; N] +} + +trait BothTrait {} + +enum BothEnum { + Dummy([T; N]) +} + +struct OppOrder { + arr: [T; N] +} + +fn main() { + let _ = OppOrder::<3, u32> { + arr: [0,0,0], + }; + let _ = Both:: { + arr: [0], + }; +} diff --git a/tests/ui/const-generics/nested-type.full.stderr b/tests/ui/const-generics/nested-type.full.stderr new file mode 100644 index 000000000..6d9f44065 --- /dev/null +++ b/tests/ui/const-generics/nested-type.full.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants + --> $DIR/nested-type.rs:15:5 + | +LL | Foo::<17>::value() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr new file mode 100644 index 000000000..cff02b0d4 --- /dev/null +++ b/tests/ui/const-generics/nested-type.min.stderr @@ -0,0 +1,28 @@ +error: `[u8; { + struct Foo; + + impl Foo { + fn value() -> usize { + N + } + } + + Foo::<17>::value() + }]` is forbidden as the type of a const generic parameter + --> $DIR/nested-type.rs:6:21 + | +LL | struct Foo; +LL | | +LL | | impl Foo { +... | +LL | | +LL | | }]>; + | |__^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/nested-type.rs b/tests/ui/const-generics/nested-type.rs new file mode 100644 index 000000000..742340f43 --- /dev/null +++ b/tests/ui/const-generics/nested-type.rs @@ -0,0 +1,19 @@ +// revisions: full min + +#![cfg_attr(full, feature(adt_const_params))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo; + + impl Foo { + fn value() -> usize { + N + } + } + + Foo::<17>::value() + //[full]~^ ERROR cannot call non-const fn +}]>; + +fn main() {} diff --git a/tests/ui/const-generics/occurs-check/bind-param.rs b/tests/ui/const-generics/occurs-check/bind-param.rs new file mode 100644 index 000000000..ee4244051 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/bind-param.rs @@ -0,0 +1,17 @@ +// build-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test does not use any "unevaluated" consts, so it should compile just fine. + +fn bind(value: [u8; N]) -> [u8; N] { + todo!() +} + +fn sink(_: [u8; 5]) {} + +fn main() { + let mut arr = Default::default(); + arr = bind(arr); + sink(arr); +} diff --git a/tests/ui/const-generics/occurs-check/unify-fixpoint.rs b/tests/ui/const-generics/occurs-check/unify-fixpoint.rs new file mode 100644 index 000000000..e6f8e4ad3 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-fixpoint.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] //~ WARN the feature `generic_const_exprs` is incomplete + + +fn bind(value: [u8; N + 2]) -> [u8; N * 2] { + todo!() +} + +fn main() { + let mut arr = Default::default(); + arr = bind::<2>(arr); +} diff --git a/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr b/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr new file mode 100644 index 000000000..fe3f24a67 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr @@ -0,0 +1,11 @@ +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unify-fixpoint.rs:2:12 + | +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/occurs-check/unify-n-nplusone.rs b/tests/ui/const-generics/occurs-check/unify-n-nplusone.rs new file mode 100644 index 000000000..c6324bca1 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-n-nplusone.rs @@ -0,0 +1,16 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// This test would tries to unify `N` with `N + 1` which must fail the occurs check. + +fn bind(value: [u8; N]) -> [u8; N + 1] { + todo!() +} + +fn sink(_: [u8; 5]) {} + +fn main() { + let mut arr = Default::default(); + arr = bind(arr); //~ ERROR mismatched types + sink(arr); +} diff --git a/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr b/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr new file mode 100644 index 000000000..6b8e688fb --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unify-n-nplusone.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unify-n-nplusone.rs:14:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.rs b/tests/ui/const-generics/occurs-check/unused-substs-1.rs new file mode 100644 index 000000000..9d12250c9 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.rs @@ -0,0 +1,13 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Bar {} +impl Bar for A<{ 6 + 1 }> {} + +struct A +where + A: Bar; + +fn main() { + let _ = A; //~ERROR the trait bound +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr new file mode 100644 index 000000000..a3c011d92 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied + --> $DIR/unused-substs-1.rs:12:13 + | +LL | let _ = A; + | ^ the trait `Bar<_>` is not implemented for `A<_>` + | + = help: the trait `Bar` is implemented for `A<7>` +note: required by a bound in `A` + --> $DIR/unused-substs-1.rs:9:11 + | +LL | struct A + | - required by a bound in this +LL | where +LL | A: Bar; + | ^^^^^^ required by this bound in `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.rs b/tests/ui/const-generics/occurs-check/unused-substs-2.rs new file mode 100644 index 000000000..9b1212694 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.rs @@ -0,0 +1,28 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst. +// +// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty` we introduced an +// artificial inference cycle. +struct Foo; + +trait Bind { + fn bind() -> (T, Self); +} + +// `N` has to be `ConstKind::Unevaluated`. +impl Bind for Foo<{ 6 + 1 }> { + fn bind() -> (T, Self) { + (panic!(), Foo) + } +} + +fn main() { + let (mut t, foo) = Foo::bind(); + // `t` is `ty::Infer(TyVar(_#1t))` + // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs + t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.stderr b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr new file mode 100644 index 000000000..9532fc21a --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-2.rs:25:9 + | +LL | t = foo; + | ^^^ cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.rs b/tests/ui/const-generics/occurs-check/unused-substs-3.rs new file mode 100644 index 000000000..d5aeab47e --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.rs @@ -0,0 +1,19 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst. +// +// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty` we introduced an +// artificial inference cycle. +fn bind() -> (T, [u8; 6 + 1]) { + todo!() +} + +fn main() { + let (mut t, foo) = bind(); + // `t` is `ty::Infer(TyVar(_#1t))` + // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs + t = foo; + //~^ ERROR mismatched types + //~| NOTE cyclic type +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr new file mode 100644 index 000000000..fd8f8b269 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-3.rs:16:9 + | +LL | t = foo; + | ^^^- help: try using a conversion method: `.to_vec()` + | | + | cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-4.rs b/tests/ui/const-generics/occurs-check/unused-substs-4.rs new file mode 100644 index 000000000..03c2f5486 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-4.rs @@ -0,0 +1,11 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn bind(value: [u8; N]) -> [u8; 3 + 4] { + todo!() +} + +fn main() { + let mut arr = Default::default(); + arr = bind(arr); //~ ERROR mismatched type +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-4.stderr b/tests/ui/const-generics/occurs-check/unused-substs-4.stderr new file mode 100644 index 000000000..5685eedbd --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-4.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-4.rs:10:11 + | +LL | arr = bind(arr); + | ^^^^^^^^^ encountered a self-referencing constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/occurs-check/unused-substs-5.rs b/tests/ui/const-generics/occurs-check/unused-substs-5.rs new file mode 100644 index 000000000..383ab4cd8 --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-5.rs @@ -0,0 +1,20 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// `N + 1` also depends on `T` here even if it doesn't use it. +fn q(_: T) -> [u8; N + 1] { + todo!() +} + +fn supplier() -> T { + todo!() +} + +fn catch_me() where [u8; N + 1]: Default { + let mut x = supplier(); + x = q::<_, N>(x); //~ ERROR mismatched types +} + +fn main() { + catch_me::<3>(); +} diff --git a/tests/ui/const-generics/occurs-check/unused-substs-5.stderr b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr new file mode 100644 index 000000000..be289f44f --- /dev/null +++ b/tests/ui/const-generics/occurs-check/unused-substs-5.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/unused-substs-5.rs:15:9 + | +LL | x = q::<_, N>(x); + | ^^^^^^^^^^^^- help: try using a conversion method: `.to_vec()` + | | + | cyclic type of infinite size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs new file mode 100644 index 000000000..3018439af --- /dev/null +++ b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.rs @@ -0,0 +1,10 @@ +struct Foo< + 'a, + const N: usize = { + let x: &'a (); + //~^ ERROR use of non-static lifetime `'a` in const generic + 3 + }, +>(&'a ()); + +fn main() {} diff --git a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr new file mode 100644 index 000000000..9d9555d3f --- /dev/null +++ b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr @@ -0,0 +1,11 @@ +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/outer-lifetime-in-const-generic-default.rs:4:17 + | +LL | let x: &'a (); + | ^^ + | + = note: for more information, see issue #74052 + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0771`. diff --git a/tests/ui/const-generics/overlapping_impls.rs b/tests/ui/const-generics/overlapping_impls.rs new file mode 100644 index 000000000..e599eadd8 --- /dev/null +++ b/tests/ui/const-generics/overlapping_impls.rs @@ -0,0 +1,36 @@ +// check-pass +#![allow(incomplete_features)] +#![feature(adt_const_params)] +#![feature(generic_const_exprs)] +use std::marker::PhantomData; + +struct Foo {} + +const ONE: i32 = 1; +const TWO: i32 = 2; + +impl Foo { + pub fn foo() {} +} + +impl Foo { + pub fn foo() {} +} + + +pub struct Foo2 { + _marker: PhantomData, +} + +#[derive(PartialEq, Eq)] +pub enum Protocol { + Variant1, + Variant2, +} + +pub trait Bar {} + +impl Bar for Foo2<{ Protocol::Variant1 }, T> {} +impl Bar for Foo2<{ Protocol::Variant2 }, T> {} + +fn main() {} diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr new file mode 100644 index 000000000..9f0b2efae --- /dev/null +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -0,0 +1,15 @@ +error: generic parameters with a default must be trailing + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 + | +LL | struct Bar(T); + | ^ + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 + | +LL | struct Bar(T); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr new file mode 100644 index 000000000..a5e70f6b9 --- /dev/null +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -0,0 +1,24 @@ +error: generic parameters with a default must be trailing + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12 + | +LL | struct Bar(T); + | ^ + +error: generic parameters may not be used in const operations + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44 + | +LL | struct Foo()]>(T, U); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error[E0128]: generic parameters with a default cannot use forward declared identifiers + --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 + | +LL | struct Bar(T); + | ^ defaulted generic parameters cannot be forward declared + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0128`. diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs new file mode 100644 index 000000000..b24a7afab --- /dev/null +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -0,0 +1,12 @@ +// revisions: full min +#![cfg_attr(full, feature(generic_const_exprs))] +#![cfg_attr(full, allow(incomplete_features))] + +struct Foo()]>(T, U); +//[min]~^ ERROR generic parameters may not be used in const operations + +struct Bar(T); +//~^ ERROR generic parameters with a default cannot use forward declared identifiers +//~| ERROR generic parameters with a default + +fn main() {} diff --git a/tests/ui/const-generics/parent_generics_of_encoding.rs b/tests/ui/const-generics/parent_generics_of_encoding.rs new file mode 100644 index 000000000..b87e3960f --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_encoding.rs @@ -0,0 +1,25 @@ +// aux-build:generics_of_parent.rs +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate generics_of_parent; + +use generics_of_parent::{Foo, S}; + +fn main() { + // regression test for #87603 + const N: usize = 2; + let x: S = S::test(); +} + +// regression test for #87674 +fn new(a: U) -> U { + a +} +fn foo(bar: &mut Foo) +where + [(); N + 1]: , +{ + *bar = new(loop {}); +} diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs new file mode 100644 index 000000000..7a78e0f10 --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.rs @@ -0,0 +1,11 @@ +// aux-build:generics_of_parent_impl_trait.rs +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +extern crate generics_of_parent_impl_trait; + +fn main() { + // check for `impl Trait<{ const }>` which has a parent of a `DefKind::TyParam` + generics_of_parent_impl_trait::foo([()]); + //~^ error: type annotations needed +} diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr new file mode 100644 index 000000000..87ff7babe --- /dev/null +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr @@ -0,0 +1,15 @@ +error[E0284]: type annotations needed + --> $DIR/parent_generics_of_encoding_impl_trait.rs:9:5 + | +LL | generics_of_parent_impl_trait::foo([()]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `foo` + | +note: required by a bound in `foo` + --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:6:48 + | +LL | pub fn foo(foo: impl Into<[(); N + 1]>) { + | ^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs new file mode 100644 index 000000000..99d8e9dea --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs @@ -0,0 +1,16 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ERROR expected lifetime, type, or constant, found keyword `const` + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr new file mode 100644 index 000000000..1de24bff4 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr @@ -0,0 +1,14 @@ +error: expected lifetime, type, or constant, found keyword `const` + --> $DIR/issue-89013-no-assoc.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ + | +help: the `const` keyword is only needed in the definition of the type + | +LL - impl Foo for Bar { +LL + impl Foo<3> for Bar { + | + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs new file mode 100644 index 000000000..b126b2485 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -0,0 +1,18 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied +//~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr new file mode 100644 index 000000000..acfdde8e1 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -0,0 +1,35 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-89013-no-kw.rs:9:6 + | +LL | impl Foo for Bar { + | ^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `N` + --> $DIR/issue-89013-no-kw.rs:1:7 + | +LL | trait Foo { + | ^^^ -------------- +help: add missing generic argument + | +LL | impl Foo for Bar { + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ associated type not allowed here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0229, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs new file mode 100644 index 000000000..0ec6762b6 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.rs @@ -0,0 +1,16 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ERROR missing type to the right of `=` + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr new file mode 100644 index 000000000..f0d0d90c7 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-type.stderr @@ -0,0 +1,8 @@ +error: missing type to the right of `=` + --> $DIR/issue-89013-type.rs:9:13 + | +LL | impl Foo for Bar { + | ^---- expected type, found keyword `type` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs new file mode 100644 index 000000000..9431779fa --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -0,0 +1,19 @@ +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +const T: usize = 42; + +impl Foo for Bar { +//~^ ERROR expected lifetime, type, or constant, found keyword `const` +//~| ERROR this trait takes 1 generic +//~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} + +fn main() {} diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr new file mode 100644 index 000000000..583749a85 --- /dev/null +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -0,0 +1,47 @@ +error: expected lifetime, type, or constant, found keyword `const` + --> $DIR/issue-89013.rs:9:14 + | +LL | impl Foo for Bar { + | ^^^^^ + | +help: the `const` keyword is only needed in the definition of the type + | +LL - impl Foo for Bar { +LL + impl Foo for Bar { + | + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-89013.rs:9:6 + | +LL | impl Foo for Bar { + | ^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `N` + --> $DIR/issue-89013.rs:1:7 + | +LL | trait Foo { + | ^^^ -------------- +help: add missing generic argument + | +LL | impl Foo for Bar { + | ++ + +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^^^^^^^ associated type not allowed here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0229, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/projection-as-arg-const.rs b/tests/ui/const-generics/projection-as-arg-const.rs new file mode 100644 index 000000000..903548c75 --- /dev/null +++ b/tests/ui/const-generics/projection-as-arg-const.rs @@ -0,0 +1,20 @@ +// This is currently not possible to use projections as const generics. +// More information about this available here: +// https://github.com/rust-lang/rust/pull/104443#discussion_r1029375633 + +pub trait Identity { + type Identity; +} + +impl Identity for T { + type Identity = Self; +} + +pub fn foo::Identity>() { +//~^ ERROR + assert!(X == 12); +} + +fn main() { + foo::<12>(); +} diff --git a/tests/ui/const-generics/projection-as-arg-const.stderr b/tests/ui/const-generics/projection-as-arg-const.stderr new file mode 100644 index 000000000..803ed9c95 --- /dev/null +++ b/tests/ui/const-generics/projection-as-arg-const.stderr @@ -0,0 +1,11 @@ +error: `::Identity` is forbidden as the type of a const generic parameter + --> $DIR/projection-as-arg-const.rs:13:21 + | +LL | pub fn foo::Identity>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + = help: more complex types are supported with `#![feature(adt_const_params)]` + +error: aborting due to previous error + diff --git a/tests/ui/const-generics/promotion.rs b/tests/ui/const-generics/promotion.rs new file mode 100644 index 000000000..ce9a1a0fe --- /dev/null +++ b/tests/ui/const-generics/promotion.rs @@ -0,0 +1,9 @@ +// run-pass +// tests that promoting expressions containing const parameters is allowed. +fn promotion_test() -> &'static usize { + &(3 + N) +} + +fn main() { + assert_eq!(promotion_test::<13>(), &16); +} diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr new file mode 100644 index 000000000..657eee2be --- /dev/null +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.full.stderr @@ -0,0 +1,15 @@ +error[E0741]: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:9:23 + | +LL | struct Const; + | ^^^^^^^^^^ + +error[E0741]: using raw pointers as const generic parameters is forbidden + --> $DIR/raw-ptr-const-param-deref.rs:11:15 + | +LL | impl Const

Parser for P { + type Input = (); +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-iterator-binding.rs b/tests/ui/associated-types/associated-types-iterator-binding.rs new file mode 100644 index 000000000..7c5528c98 --- /dev/null +++ b/tests/ui/associated-types/associated-types-iterator-binding.rs @@ -0,0 +1,19 @@ +// run-pass + +fn pairwise_sub>(mut t: T) -> isize { + let mut result = 0; + loop { + let front = t.next(); + let back = t.next_back(); + match (front, back) { + (Some(f), Some(b)) => { result += b - f; } + _ => { return result; } + } + } +} + +fn main() { + let v = vec![1, 2, 3, 4, 5, 6]; + let r = pairwise_sub(v.into_iter()); + assert_eq!(r, 9); +} diff --git a/tests/ui/associated-types/associated-types-method.rs b/tests/ui/associated-types/associated-types-method.rs new file mode 100644 index 000000000..45df3ac20 --- /dev/null +++ b/tests/ui/associated-types/associated-types-method.rs @@ -0,0 +1,28 @@ +// run-pass +// Test that methods whose impl-trait-ref contains associated types +// are supported. + +trait Device { + type Resources; +} +#[allow(unused_tuple_struct_fields)] +struct Foo(D, R); + +trait Tr { + fn present(&self) {} +} + +impl Tr for Foo { + fn present(&self) {} +} + +struct Res; +struct Dev; +impl Device for Dev { + type Resources = Res; +} + +fn main() { + let foo = Foo(Dev, Res); + foo.present(); +} diff --git a/tests/ui/associated-types/associated-types-multiple-types-one-trait.rs b/tests/ui/associated-types/associated-types-multiple-types-one-trait.rs new file mode 100644 index 000000000..daeaf9011 --- /dev/null +++ b/tests/ui/associated-types/associated-types-multiple-types-one-trait.rs @@ -0,0 +1,46 @@ +trait Foo { + type X; + type Y; +} + +fn have_x_want_x>(t: &T) +{ + want_x(t); +} + +fn have_x_want_y>(t: &T) +{ + want_y(t); //~ ERROR type mismatch +} + +fn have_y_want_x>(t: &T) +{ + want_x(t); //~ ERROR type mismatch +} + +fn have_y_want_y>(t: &T) +{ + want_y(t); +} + +fn have_xy_want_x>(t: &T) +{ + want_x(t); +} + +fn have_xy_want_y>(t: &T) +{ + want_y(t); +} + +fn have_xy_want_xy>(t: &T) +{ + want_x(t); + want_y(t); +} + +fn want_x>(t: &T) { } + +fn want_y>(t: &T) { } + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-multiple-types-one-trait.stderr b/tests/ui/associated-types/associated-types-multiple-types-one-trait.stderr new file mode 100644 index 000000000..89cdba524 --- /dev/null +++ b/tests/ui/associated-types/associated-types-multiple-types-one-trait.stderr @@ -0,0 +1,43 @@ +error[E0271]: type mismatch resolving `::Y == i32` + --> $DIR/associated-types-multiple-types-one-trait.rs:13:12 + | +LL | want_y(t); + | ------ ^ expected `i32`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected type `i32` + found associated type `::Y` +note: required by a bound in `want_y` + --> $DIR/associated-types-multiple-types-one-trait.rs:44:17 + | +LL | fn want_y>(t: &T) { } + | ^^^^^ required by this bound in `want_y` +help: consider constraining the associated type `::Y` to `i32` + | +LL | fn have_x_want_y>(t: &T) + | +++++++++ + +error[E0271]: type mismatch resolving `::X == u32` + --> $DIR/associated-types-multiple-types-one-trait.rs:18:12 + | +LL | want_x(t); + | ------ ^ expected `u32`, found associated type + | | + | required by a bound introduced by this call + | + = note: expected type `u32` + found associated type `::X` +note: required by a bound in `want_x` + --> $DIR/associated-types-multiple-types-one-trait.rs:42:17 + | +LL | fn want_x>(t: &T) { } + | ^^^^^ required by this bound in `want_x` +help: consider constraining the associated type `::X` to `u32` + | +LL | fn have_y_want_x>(t: &T) + | +++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-nested-projections.rs b/tests/ui/associated-types/associated-types-nested-projections.rs new file mode 100644 index 000000000..76ba74962 --- /dev/null +++ b/tests/ui/associated-types/associated-types-nested-projections.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(unused_variables)] +// Test that we can resolve nested projection types. Issue #20666. + +// pretty-expanded FIXME #23616 + +use std::slice; + +trait Bound {} + +impl<'a> Bound for &'a i32 {} + +trait IntoIterator { + type Iter: Iterator; + + fn into_iter(self) -> Self::Iter; +} + +impl<'a, T> IntoIterator for &'a [T; 3] { + type Iter = slice::Iter<'a, T>; + + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +fn foo(x: X) where + X: IntoIterator, + <::Iter as Iterator>::Item: Bound, +{ +} + +fn bar(x: X) where + T: Bound, + I: Iterator, + X: IntoIterator, +{ + +} + +fn main() { + foo(&[0, 1, 2]); + bar(&[0, 1, 2]); +} diff --git a/tests/ui/associated-types/associated-types-no-suitable-bound.rs b/tests/ui/associated-types/associated-types-no-suitable-bound.rs new file mode 100644 index 000000000..d42460a4c --- /dev/null +++ b/tests/ui/associated-types/associated-types-no-suitable-bound.rs @@ -0,0 +1,16 @@ +trait Get { + type Value; + fn get(&self) -> ::Value; +} + +struct Struct { + x: isize, +} + +impl Struct { + fn uhoh(foo: ::Value) {} + //~^ ERROR the trait bound `T: Get` is not satisfied +} + +fn main() { +} diff --git a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr new file mode 100644 index 000000000..b2ee1b5e6 --- /dev/null +++ b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `T: Get` is not satisfied + --> $DIR/associated-types-no-suitable-bound.rs:11:21 + | +LL | fn uhoh(foo: ::Value) {} + | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn uhoh(foo: ::Value) {} + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.rs b/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.rs new file mode 100644 index 000000000..17dfa1773 --- /dev/null +++ b/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.rs @@ -0,0 +1,21 @@ +// Check that we get an error when you use `::Value` in +// the trait definition but `Self` does not, in fact, implement `Get`. +// +// See also associated-types-no-suitable-supertrait.rs, which checks +// that we see the same error when making this mistake on an impl +// rather than the default method impl. +// +// See also run-pass/associated-types-projection-to-unrelated-trait.rs, +// which checks that the trait interface itself is not considered an +// error as long as all impls satisfy the constraint. + +trait Get { + type Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait bound `Self: Get` is not satisfied +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr new file mode 100644 index 000000000..2e40dbd06 --- /dev/null +++ b/tests/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: Get` is not satisfied + --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40 + | +LL | fn uhoh(&self, foo: U, bar: ::Value) {} + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-no-suitable-supertrait.rs b/tests/ui/associated-types/associated-types-no-suitable-supertrait.rs new file mode 100644 index 000000000..c373c5855 --- /dev/null +++ b/tests/ui/associated-types/associated-types-no-suitable-supertrait.rs @@ -0,0 +1,26 @@ +// Check that we get an error when you use `::Value` in +// the trait definition but `Self` does not, in fact, implement `Get`. +// +// See also associated-types-no-suitable-supertrait-2.rs, which checks +// that we see the same error if we get around to checking the default +// method body. +// +// See also run-pass/associated-types-projection-to-unrelated-trait.rs, +// which checks that the trait interface itself is not considered an +// error as long as all impls satisfy the constraint. + +trait Get { + type Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) {} + //~^ ERROR the trait bound `Self: Get` is not satisfied +} + +impl Other for T { + fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} + //~^ ERROR the trait bound `(T, U): Get` is not satisfied +} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr new file mode 100644 index 000000000..bd3ee2abd --- /dev/null +++ b/tests/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `(T, U): Get` is not satisfied + --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 + | +LL | fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` + +error[E0277]: the trait bound `Self: Get` is not satisfied + --> $DIR/associated-types-no-suitable-supertrait.rs:17:40 + | +LL | fn uhoh(&self, foo: U, bar: ::Value) {} + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds-binding.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds-binding.rs new file mode 100644 index 000000000..7c54efb83 --- /dev/null +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds-binding.rs @@ -0,0 +1,38 @@ +// run-pass +#![allow(unused_variables)] +// Test that we normalize associated types that appear in a bound that +// contains a binding. Issue #21664. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +pub trait Integral { + type Opposite; +} + +impl Integral for i32 { + type Opposite = u32; +} + +impl Integral for u32 { + type Opposite = i32; +} + +pub trait FnLike { + type R; + + fn dummy(&self, a: A) -> Self::R { loop { } } +} + +fn foo() + where T : FnLike<::Opposite, R=bool> +{ + bar::(); +} + +fn bar() + where T : FnLike +{} + +fn main() { } diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs new file mode 100644 index 000000000..e09aa3663 --- /dev/null +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(unused_variables)] +// Test that we normalize associated types that appear in bounds; if +// we didn't, the call to `self.split2()` fails to type check. + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomData; + +struct Splits<'a, T:'a, P>(PhantomData<(&'a T, P)>); +struct SplitsN(PhantomData); + +trait SliceExt2 { + type Item; + + fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P> + where P: FnMut(&Self::Item) -> bool; + fn splitn2<'a, P>(&'a self, n: u32, pred: P) -> SplitsN> + where P: FnMut(&Self::Item) -> bool; +} + +impl SliceExt2 for [T] { + type Item = T; + + fn split2